summaryrefslogtreecommitdiff
path: root/drivers/target/iscsi/cxgbit/git:/git.armlinux.org.uk
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-12-10 07:48:05 +0900
committerLinus Torvalds <torvalds@linux-foundation.org>2025-12-10 07:48:05 +0900
commitc9b47175e9131118e6f221cc8fb81397d62e7c91 (patch)
treeec9cf60ad95a2e8e13e73706287825ffe9ac20f6 /drivers/target/iscsi/cxgbit/git:/git.armlinux.org.uk
parent9d588a1140b9ae211581a7a154d0b806d8cd8238 (diff)
parentd202341d9b0c5b5965787061ba0d10daafb9d6c5 (diff)
Merge tag 'i2c-for-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linuxHEADmaster
Pull i2c updates from Wolfram Sang: - general cleanups in bcm2835, designware, pcf8584, and stm32 - amd-mp2: fix device refcount - designware: avoid interrupt storms caused by bad firmware - spacemit: fix device detection failures - new devices: Intel Diamond Rapids, Rockchip RK3506, Qualcomm Kaanapali and MSM8953 - minor fixes to i801, core documentation, elektor Kconfig dependencies - at24 updates: add new compatible for Belling BL24S64 * tag 'i2c-for-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (21 commits) i2c: qcom-cci: Add msm8953 compatible i2c: spacemit: fix detect issue i2c: amd-mp2: fix reference leak in MP2 PCI device i2c: i2c.h: fix a bad kernel-doc line i2c: i2c-elektor: Allow building on SMP kernels dt-bindings: i2c: qcom-cci: Document Kaanapali compatible dt-bindings: i2c: qcom-cci: Document msm8953 compatible dt-bindings: eeprom: at24: Add compatible for Belling BL24S64 i2c: i801: Fix the Intel Diamond Rapids features i2c: pcf8584: Change pcf_doAdress() to pcf_send_address() i2c: pcf8584: Make pcf_doAddress() function void i2c: pcf8584: Move 'ret' variable inside for loop, goto out if ret < 0. i2c: designware: Disable SMBus interrupts to prevent storms from mis-configured firmware dt-bindings: i2c: i2c-rk3x: Add compatible string for RK3506 i2c: i801: Add support for Intel Diamond Rapids i2c: stm32: Omit two variable reassignments in stm32_i2c_dma_request() i2c: designware: Omit a variable reassignment in dw_i2c_plat_probe() i2c: pcf8584: Fix do not use assignment inside if conditional i2c: pcf8584: Remove debug macros from i2c-algo-pcf.c i2c: busses: bcm2835: convert from round_rate() to determine_rate() ...
Diffstat (limited to 'drivers/target/iscsi/cxgbit/git:/git.armlinux.org.uk')
0 files changed, 0 insertions, 0 deletions
-rw-r--r--Documentation/DocBook/80211.tmpl11
-rw-r--r--Documentation/DocBook/media/dvb/dvbproperty.xml24
-rw-r--r--Documentation/DocBook/media/dvb/intro.xml2
-rw-r--r--Documentation/DocBook/media/v4l/compat.xml8
-rw-r--r--Documentation/DocBook/media/v4l/dev-subdev.xml2
-rw-r--r--Documentation/DocBook/media/v4l/v4l2.xml9
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-dqevent.xml129
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-queryctrl.xml9
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml123
-rw-r--r--Documentation/DocBook/uio-howto.tmpl2
-rw-r--r--Documentation/DocBook/writing-an-alsa-driver.tmpl36
-rw-r--r--Documentation/PCI/pci.txt2
-rw-r--r--Documentation/RCU/NMI-RCU.txt2
-rw-r--r--Documentation/RCU/lockdep-splat.txt110
-rw-r--r--Documentation/RCU/lockdep.txt34
-rw-r--r--Documentation/RCU/torture.txt137
-rw-r--r--Documentation/RCU/trace.txt38
-rw-r--r--Documentation/blackfin/bfin-gpio-notes.txt2
-rw-r--r--Documentation/block/biodoc.txt2
-rw-r--r--Documentation/bus-virt-phys-mapping.txt2
-rw-r--r--Documentation/cdrom/packet-writing.txt2
-rw-r--r--Documentation/cgroups/memory.txt1
-rw-r--r--Documentation/cpu-freq/governors.txt2
-rw-r--r--Documentation/development-process/4.Coding2
-rw-r--r--Documentation/device-mapper/dm-log.txt2
-rw-r--r--Documentation/device-mapper/persistent-data.txt84
-rw-r--r--Documentation/device-mapper/thin-provisioning.txt285
-rw-r--r--Documentation/devicetree/bindings/arm/calxeda.txt8
-rw-r--r--Documentation/devicetree/bindings/arm/fsl.txt26
-rw-r--r--Documentation/devicetree/bindings/arm/gic.txt55
-rw-r--r--Documentation/devicetree/bindings/arm/l2cc.txt44
-rw-r--r--Documentation/devicetree/bindings/arm/omap/dsp.txt14
-rw-r--r--Documentation/devicetree/bindings/arm/omap/iva.txt19
-rw-r--r--Documentation/devicetree/bindings/arm/omap/l3-noc.txt19
-rw-r--r--Documentation/devicetree/bindings/arm/omap/mpu.txt27
-rw-r--r--Documentation/devicetree/bindings/arm/omap/omap.txt43
-rw-r--r--Documentation/devicetree/bindings/arm/picoxcell.txt24
-rw-r--r--Documentation/devicetree/bindings/arm/primecell.txt4
-rw-r--r--Documentation/devicetree/bindings/crypto/picochip-spacc.txt23
-rw-r--r--Documentation/devicetree/bindings/gpio/led.txt2
-rw-r--r--Documentation/devicetree/bindings/gpio/pl061-gpio.txt10
-rw-r--r--Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt25
-rw-r--r--Documentation/devicetree/bindings/i2c/samsung-i2c.txt39
-rw-r--r--Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt27
-rw-r--r--Documentation/devicetree/bindings/net/can/fsl-flexcan.txt63
-rw-r--r--Documentation/devicetree/bindings/net/smsc911x.txt38
-rw-r--r--Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt5
-rw-r--r--Documentation/devicetree/bindings/serial/rs485.txt31
-rw-r--r--Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt11
-rw-r--r--Documentation/devicetree/bindings/sound/wm8510.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/wm8523.txt16
-rw-r--r--Documentation/devicetree/bindings/sound/wm8580.txt16
-rw-r--r--Documentation/devicetree/bindings/sound/wm8711.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/wm8728.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/wm8731.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/wm8737.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/wm8741.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/wm8750.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/wm8753.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/wm8770.txt16
-rw-r--r--Documentation/devicetree/bindings/sound/wm8776.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/wm8804.txt18
-rw-r--r--Documentation/devicetree/bindings/spi/spi_pl022.txt12
-rw-r--r--Documentation/devicetree/bindings/tty/serial/atmel-usart.txt27
-rw-r--r--Documentation/devicetree/bindings/tty/serial/msm_serial.txt27
-rw-r--r--Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt25
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt40
-rw-r--r--Documentation/devicetree/bindings/virtio/mmio.txt17
-rw-r--r--Documentation/driver-model/binding.txt4
-rw-r--r--Documentation/driver-model/device.txt65
-rwxr-xr-xDocumentation/dvb/get_dvb_firmware51
-rw-r--r--Documentation/dvb/it9137.txt9
-rw-r--r--Documentation/fault-injection/fault-injection.txt8
-rw-r--r--Documentation/fb/udlfb.txt39
-rw-r--r--Documentation/feature-removal-schedule.txt67
-rw-r--r--Documentation/filesystems/9p.txt2
-rw-r--r--Documentation/filesystems/Locking1
-rw-r--r--Documentation/filesystems/caching/object.txt6
-rw-r--r--Documentation/filesystems/ext3.txt8
-rw-r--r--Documentation/filesystems/ext4.txt41
-rw-r--r--Documentation/filesystems/locks.txt11
-rw-r--r--Documentation/filesystems/nfs/idmapper.txt2
-rw-r--r--Documentation/filesystems/pohmelfs/design_notes.txt5
-rw-r--r--Documentation/filesystems/proc.txt2
-rw-r--r--Documentation/filesystems/sysfs.txt10
-rw-r--r--Documentation/filesystems/vfs.txt3
-rw-r--r--Documentation/frv/booting.txt6
-rw-r--r--Documentation/hwmon/ad731425
-rw-r--r--Documentation/hwmon/adm127540
-rw-r--r--Documentation/hwmon/exynos4_tmu81
-rw-r--r--Documentation/hwmon/lm7561
-rw-r--r--Documentation/hwmon/ltc2978103
-rw-r--r--Documentation/hwmon/pmbus13
-rw-r--r--Documentation/hwmon/pmbus-core283
-rw-r--r--Documentation/hwmon/zl6100125
-rw-r--r--Documentation/hwspinlock.txt74
-rw-r--r--Documentation/i2c/smbus-protocol8
-rw-r--r--Documentation/input/elantech.txt295
-rw-r--r--Documentation/input/input.txt2
-rw-r--r--Documentation/input/multi-touch-protocol.txt14
-rw-r--r--Documentation/kernel-docs.txt4
-rw-r--r--Documentation/kernel-parameters.txt64
-rw-r--r--Documentation/laptops/thinkpad-acpi.txt4
-rw-r--r--Documentation/media-framework.txt4
-rw-r--r--Documentation/memory-barriers.txt2
-rw-r--r--Documentation/networking/LICENSE.qlcnic51
-rw-r--r--Documentation/networking/batman-adv.txt8
-rw-r--r--Documentation/networking/ip-sysctl.txt17
-rw-r--r--Documentation/networking/mac80211-injection.txt4
-rw-r--r--Documentation/networking/netdevices.txt4
-rw-r--r--Documentation/networking/scaling.txt2
-rw-r--r--Documentation/networking/stmmac.txt44
-rw-r--r--Documentation/pinctrl.txt950
-rw-r--r--Documentation/power/00-INDEX2
-rw-r--r--Documentation/power/basic-pm-debugging.txt26
-rw-r--r--Documentation/power/devices.txt8
-rw-r--r--Documentation/power/pm_qos_interface.txt92
-rw-r--r--Documentation/power/regulator/machine.txt19
-rw-r--r--Documentation/power/runtime_pm.txt21
-rw-r--r--Documentation/power/suspend-and-cpuhotplug.txt275
-rw-r--r--Documentation/power/userland-swsusp.txt3
-rw-r--r--Documentation/rapidio/rapidio.txt2
-rw-r--r--Documentation/rapidio/tsi721.txt49
-rw-r--r--Documentation/rfkill.txt3
-rw-r--r--Documentation/scheduler/sched-bwc.txt122
-rw-r--r--Documentation/scsi/00-INDEX2
-rw-r--r--Documentation/scsi/ChangeLog.megaraid_sas15
-rw-r--r--Documentation/scsi/LICENSE.qla4xxx310
-rw-r--r--Documentation/scsi/aic7xxx_old.txt2
-rw-r--r--Documentation/scsi/bnx2fc.txt75
-rw-r--r--Documentation/scsi/scsi_mid_low_api.txt5
-rw-r--r--Documentation/security/keys-trusted-encrypted.txt3
-rw-r--r--Documentation/serial/serial-rs485.txt8
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt6
-rw-r--r--Documentation/sound/alsa/HD-Audio-Controls.txt16
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt67
-rw-r--r--Documentation/sound/alsa/HD-Audio.txt55
-rw-r--r--Documentation/sound/oss/PAS163
-rw-r--r--Documentation/spi/pxa2xx4
-rw-r--r--Documentation/stable_kernel_rules.txt14
-rw-r--r--Documentation/sysctl/kernel.txt8
-rw-r--r--Documentation/timers/highres.txt2
-rw-r--r--Documentation/trace/postprocess/trace-vmscan-postprocess.pl8
-rw-r--r--Documentation/usb/dma.txt6
-rw-r--r--Documentation/usb/dwc3.txt45
-rw-r--r--Documentation/usb/power-management.txt34
-rw-r--r--Documentation/video4linux/CARDLIST.tm6000 (renamed from drivers/staging/tm6000/CARDLIST)0
-rw-r--r--Documentation/video4linux/gspca.txt4
-rw-r--r--Documentation/video4linux/omap3isp.txt9
-rw-r--r--Documentation/video4linux/v4l2-controls.txt43
-rw-r--r--Documentation/virtual/kvm/api.txt71
-rw-r--r--Documentation/virtual/lguest/lguest.c2
-rw-r--r--Documentation/virtual/uml/UserModeLinux-HOWTO.txt532
-rw-r--r--Documentation/vm/00-INDEX2
-rw-r--r--Documentation/vm/numa4
-rw-r--r--Documentation/vm/slub.txt2
-rw-r--r--Documentation/x86/entry_64.txt3
-rw-r--r--Documentation/zh_CN/SubmitChecklist109
-rw-r--r--MAINTAINERS372
-rw-r--r--arch/alpha/include/asm/fcntl.h2
-rw-r--r--arch/alpha/include/asm/unistd.h4
-rw-r--r--arch/alpha/kernel/srm_env.c5
-rw-r--r--arch/alpha/kernel/systbls.S2
-rw-r--r--arch/arm/Kconfig175
-rw-r--r--arch/arm/Kconfig.debug224
-rw-r--r--arch/arm/Makefile12
-rw-r--r--arch/arm/boot/Makefile9
-rw-r--r--arch/arm/boot/compressed/.gitignore9
-rw-r--r--arch/arm/boot/compressed/Makefile40
-rw-r--r--arch/arm/boot/compressed/atags_to_fdt.c97
-rw-r--r--arch/arm/boot/compressed/head.S122
-rw-r--r--arch/arm/boot/compressed/libfdt_env.h15
-rw-r--r--arch/arm/boot/compressed/misc.c42
-rw-r--r--arch/arm/boot/compressed/string.c127
-rw-r--r--arch/arm/boot/compressed/vmlinux.lds.in4
-rw-r--r--arch/arm/boot/dts/at91sam9g20.dtsi119
-rw-r--r--arch/arm/boot/dts/at91sam9g45.dtsi106
-rw-r--r--arch/arm/boot/dts/at91sam9m10g45ek.dts35
-rw-r--r--arch/arm/boot/dts/highbank.dts198
-rw-r--r--arch/arm/boot/dts/imx51-babbage.dts135
-rw-r--r--arch/arm/boot/dts/imx51.dtsi246
-rw-r--r--arch/arm/boot/dts/imx53-ard.dts113
-rw-r--r--arch/arm/boot/dts/imx53-evk.dts120
-rw-r--r--arch/arm/boot/dts/imx53-qsb.dts125
-rw-r--r--arch/arm/boot/dts/imx53-smd.dts169
-rw-r--r--arch/arm/boot/dts/imx53.dtsi301
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto.dts62
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi575
-rw-r--r--arch/arm/boot/dts/msm8660-surf.dts24
-rw-r--r--arch/arm/boot/dts/omap3-beagle.dts29
-rw-r--r--arch/arm/boot/dts/omap3.dtsi63
-rw-r--r--arch/arm/boot/dts/omap4-panda.dts29
-rw-r--r--arch/arm/boot/dts/omap4-sdp.dts29
-rw-r--r--arch/arm/boot/dts/omap4.dtsi103
-rw-r--r--arch/arm/boot/dts/picoxcell-pc3x2.dtsi249
-rw-r--r--arch/arm/boot/dts/picoxcell-pc3x3.dtsi365
-rw-r--r--arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts86
-rw-r--r--arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts92
-rw-r--r--arch/arm/boot/dts/prima2-cb.dts14
-rw-r--r--arch/arm/boot/dts/tegra-harmony.dts1
-rw-r--r--arch/arm/boot/dts/tegra-seaboard.dts4
-rw-r--r--arch/arm/boot/dts/tegra-ventana.dts32
-rw-r--r--arch/arm/boot/dts/tegra20.dtsi8
-rw-r--r--arch/arm/boot/dts/usb_a9g20.dts30
-rw-r--r--arch/arm/common/Kconfig1
-rw-r--r--arch/arm/common/gic.c400
-rw-r--r--arch/arm/common/pl330.c2
-rw-r--r--arch/arm/common/sa1111.c9
-rw-r--r--arch/arm/common/scoop.c2
-rw-r--r--arch/arm/common/timer-sp.c9
-rw-r--r--arch/arm/common/vic.c3
-rw-r--r--arch/arm/configs/at91sam9g45_defconfig214
-rw-r--r--arch/arm/configs/exynos4_defconfig1
-rw-r--r--arch/arm/configs/imx_v4_v5_defconfig (renamed from arch/arm/configs/mx27_defconfig)68
-rw-r--r--arch/arm/configs/integrator_defconfig19
-rw-r--r--arch/arm/configs/mx1_defconfig91
-rw-r--r--arch/arm/configs/mx21_defconfig97
-rw-r--r--arch/arm/configs/mx3_defconfig46
-rw-r--r--arch/arm/configs/mx5_defconfig (renamed from arch/arm/configs/mx51_defconfig)60
-rw-r--r--arch/arm/configs/mxs_defconfig1
-rw-r--r--arch/arm/configs/tegra_defconfig39
-rw-r--r--arch/arm/include/asm/Kbuild17
-rw-r--r--arch/arm/include/asm/auxvec.h4
-rw-r--r--arch/arm/include/asm/bitsperlong.h1
-rw-r--r--arch/arm/include/asm/bug.h55
-rw-r--r--arch/arm/include/asm/cachetype.h5
-rw-r--r--arch/arm/include/asm/cputime.h6
-rw-r--r--arch/arm/include/asm/cputype.h6
-rw-r--r--arch/arm/include/asm/device.h8
-rw-r--r--arch/arm/include/asm/dma-mapping.h9
-rw-r--r--arch/arm/include/asm/dma.h6
-rw-r--r--arch/arm/include/asm/ecard.h1
-rw-r--r--arch/arm/include/asm/emergency-restart.h6
-rw-r--r--arch/arm/include/asm/entry-macro-multi.S7
-rw-r--r--arch/arm/include/asm/errno.h6
-rw-r--r--arch/arm/include/asm/exception.h19
-rw-r--r--arch/arm/include/asm/gpio.h19
-rw-r--r--arch/arm/include/asm/hardirq.h3
-rw-r--r--arch/arm/include/asm/hardware/cache-l2x0.h49
-rw-r--r--arch/arm/include/asm/hardware/entry-macro-gic.S19
-rw-r--r--arch/arm/include/asm/hardware/gic.h19
-rw-r--r--arch/arm/include/asm/hardware/iop3xx-gpio.h2
-rw-r--r--arch/arm/include/asm/hardware/it8152.h2
-rw-r--r--arch/arm/include/asm/hw_breakpoint.h2
-rw-r--r--arch/arm/include/asm/io.h40
-rw-r--r--arch/arm/include/asm/ioctl.h1
-rw-r--r--arch/arm/include/asm/irq_regs.h1
-rw-r--r--arch/arm/include/asm/kdebug.h1
-rw-r--r--arch/arm/include/asm/local.h1
-rw-r--r--arch/arm/include/asm/local64.h1
-rw-r--r--arch/arm/include/asm/localtimer.h18
-rw-r--r--arch/arm/include/asm/mach/arch.h5
-rw-r--r--arch/arm/include/asm/mach/map.h1
-rw-r--r--arch/arm/include/asm/memory.h25
-rw-r--r--arch/arm/include/asm/mmu.h4
-rw-r--r--arch/arm/include/asm/module.h4
-rw-r--r--arch/arm/include/asm/outercache.h7
-rw-r--r--arch/arm/include/asm/page.h42
-rw-r--r--arch/arm/include/asm/percpu.h6
-rw-r--r--arch/arm/include/asm/pgalloc.h4
-rw-r--r--arch/arm/include/asm/pgtable-2level-hwdef.h93
-rw-r--r--arch/arm/include/asm/pgtable-2level-types.h67
-rw-r--r--arch/arm/include/asm/pgtable-2level.h143
-rw-r--r--arch/arm/include/asm/pgtable-hwdef.h77
-rw-r--r--arch/arm/include/asm/pgtable.h144
-rw-r--r--arch/arm/include/asm/pmu.h93
-rw-r--r--arch/arm/include/asm/poll.h1
-rw-r--r--arch/arm/include/asm/proc-fns.h8
-rw-r--r--arch/arm/include/asm/resource.h6
-rw-r--r--arch/arm/include/asm/sections.h1
-rw-r--r--arch/arm/include/asm/siginfo.h6
-rw-r--r--arch/arm/include/asm/smp.h16
-rw-r--r--arch/arm/include/asm/smp_twd.h2
-rw-r--r--arch/arm/include/asm/suspend.h17
-rw-r--r--arch/arm/include/asm/system.h11
-rw-r--r--arch/arm/include/asm/tlbflush.h4
-rw-r--r--arch/arm/include/asm/topology.h33
-rw-r--r--arch/arm/kernel/Makefile10
-rw-r--r--arch/arm/kernel/armksyms.c3
-rw-r--r--arch/arm/kernel/asm-offsets.c12
-rw-r--r--arch/arm/kernel/bios32.c9
-rw-r--r--arch/arm/kernel/debug.S8
-rw-r--r--arch/arm/kernel/dma.c2
-rw-r--r--arch/arm/kernel/ecard.c36
-rw-r--r--arch/arm/kernel/entry-armv.S44
-rw-r--r--arch/arm/kernel/head.S139
-rw-r--r--arch/arm/kernel/hw_breakpoint.c275
-rw-r--r--arch/arm/kernel/irq.c5
-rw-r--r--arch/arm/kernel/kprobes-arm.c4
-rw-r--r--arch/arm/kernel/kprobes-test-arm.c1323
-rw-r--r--arch/arm/kernel/kprobes-test-thumb.c1187
-rw-r--r--arch/arm/kernel/kprobes-test.c1748
-rw-r--r--arch/arm/kernel/kprobes-test.h392
-rw-r--r--arch/arm/kernel/kprobes-thumb.c7
-rw-r--r--arch/arm/kernel/kprobes.h8
-rw-r--r--arch/arm/kernel/machine_kexec.c35
-rw-r--r--arch/arm/kernel/module.c2
-rw-r--r--arch/arm/kernel/perf_event.c475
-rw-r--r--arch/arm/kernel/perf_event_v6.c87
-rw-r--r--arch/arm/kernel/perf_event_v7.c395
-rw-r--r--arch/arm/kernel/perf_event_xscale.c90
-rw-r--r--arch/arm/kernel/pmu.c182
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--arch/arm/kernel/setup.c58
-rw-r--r--arch/arm/kernel/sleep.S85
-rw-r--r--arch/arm/kernel/smp.c89
-rw-r--r--arch/arm/kernel/smp_scu.c2
-rw-r--r--arch/arm/kernel/smp_twd.c47
-rw-r--r--arch/arm/kernel/suspend.c72
-rw-r--r--arch/arm/kernel/time.c6
-rw-r--r--arch/arm/kernel/topology.c148
-rw-r--r--arch/arm/kernel/traps.c52
-rw-r--r--arch/arm/kernel/vmlinux.lds.S3
-rw-r--r--arch/arm/lib/backtrace.S6
-rw-r--r--arch/arm/lib/div64.S8
-rw-r--r--arch/arm/lib/uaccess_with_memcpy.c1
-rw-r--r--arch/arm/mach-at91/Kconfig24
-rw-r--r--arch/arm/mach-at91/Makefile9
-rw-r--r--arch/arm/mach-at91/Makefile.boot8
-rw-r--r--arch/arm/mach-at91/at91cap9.c2
-rw-r--r--arch/arm/mach-at91/at91cap9_devices.c8
-rw-r--r--arch/arm/mach-at91/at91rm9200.c2
-rw-r--r--arch/arm/mach-at91/at91rm9200_devices.c10
-rw-r--r--arch/arm/mach-at91/at91sam9260.c10
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c12
-rw-r--r--arch/arm/mach-at91/at91sam9261.c29
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c10
-rw-r--r--arch/arm/mach-at91/at91sam9263.c2
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c8
-rw-r--r--arch/arm/mach-at91/at91sam9g45.c17
-rw-r--r--arch/arm/mach-at91/at91sam9g45_devices.c37
-rw-r--r--arch/arm/mach-at91/at91sam9rl_devices.c2
-rw-r--r--arch/arm/mach-at91/board-1arm.c2
-rw-r--r--arch/arm/mach-at91/board-afeb-9260v1.c2
-rw-r--r--arch/arm/mach-at91/board-cam60.c2
-rw-r--r--arch/arm/mach-at91/board-cap9adk.c2
-rw-r--r--arch/arm/mach-at91/board-carmeva.c2
-rw-r--r--arch/arm/mach-at91/board-cpu9krea.c2
-rw-r--r--arch/arm/mach-at91/board-cpuat91.c2
-rw-r--r--arch/arm/mach-at91/board-csb337.c2
-rw-r--r--arch/arm/mach-at91/board-csb637.c2
-rw-r--r--arch/arm/mach-at91/board-dt.c123
-rw-r--r--arch/arm/mach-at91/board-eb9200.c2
-rw-r--r--arch/arm/mach-at91/board-ecbat91.c2
-rw-r--r--arch/arm/mach-at91/board-kafa.c2
-rw-r--r--arch/arm/mach-at91/board-kb9202.c2
-rw-r--r--arch/arm/mach-at91/board-neocore926.c2
-rw-r--r--arch/arm/mach-at91/board-picotux200.c2
-rw-r--r--arch/arm/mach-at91/board-qil-a9260.c2
-rw-r--r--arch/arm/mach-at91/board-rm9200dk.c2
-rw-r--r--arch/arm/mach-at91/board-rm9200ek.c2
-rw-r--r--arch/arm/mach-at91/board-rsi-ews.c233
-rw-r--r--arch/arm/mach-at91/board-sam9-l9260.c2
-rw-r--r--arch/arm/mach-at91/board-sam9260ek.c2
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c2
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c2
-rw-r--r--arch/arm/mach-at91/board-sam9g20ek.c2
-rw-r--r--arch/arm/mach-at91/board-sam9m10g45ek.c2
-rw-r--r--arch/arm/mach-at91/board-sam9rlek.c2
-rw-r--r--arch/arm/mach-at91/board-usb-a9260.c230
-rw-r--r--arch/arm/mach-at91/board-usb-a926x.c (renamed from arch/arm/mach-at91/board-usb-a9263.c)181
-rw-r--r--arch/arm/mach-at91/board-yl-9200.c2
-rw-r--r--arch/arm/mach-at91/gpio.c4
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9g45.h2
-rw-r--r--arch/arm/mach-at91/include/mach/board.h5
-rw-r--r--arch/arm/mach-at91/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-at91/include/mach/gpio.h5
-rw-r--r--arch/arm/mach-at91/include/mach/timex.h5
-rw-r--r--arch/arm/mach-at91/leds.c2
-rw-r--r--arch/arm/mach-at91/pm.c2
-rw-r--r--arch/arm/mach-bcmring/Kconfig2
-rw-r--r--arch/arm/mach-bcmring/Makefile.boot2
-rw-r--r--arch/arm/mach-bcmring/arch.c4
-rw-r--r--arch/arm/mach-bcmring/include/mach/hardware.h3
-rw-r--r--arch/arm/mach-bcmring/include/mach/memory.h33
-rw-r--r--arch/arm/mach-bcmring/irq.c1
-rw-r--r--arch/arm/mach-bcmring/mm.c3
-rw-r--r--arch/arm/mach-bcmring/timer.c1
-rw-r--r--arch/arm/mach-clps711x/Makefile.boot2
-rw-r--r--arch/arm/mach-clps711x/autcpu12.c2
-rw-r--r--arch/arm/mach-clps711x/cdb89712.c2
-rw-r--r--arch/arm/mach-clps711x/ceiva.c2
-rw-r--r--arch/arm/mach-clps711x/clep7312.c5
-rw-r--r--arch/arm/mach-clps711x/edb7211-arch.c5
-rw-r--r--arch/arm/mach-clps711x/fortunet.c4
-rw-r--r--arch/arm/mach-clps711x/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-clps711x/p720t.c5
-rw-r--r--arch/arm/mach-cns3xxx/Makefile.boot2
-rw-r--r--arch/arm/mach-cns3xxx/cns3420vb.c2
-rw-r--r--arch/arm/mach-cns3xxx/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-cns3xxx/include/mach/memory.h26
-rw-r--r--arch/arm/mach-davinci/Kconfig10
-rw-r--r--arch/arm/mach-davinci/Makefile3
-rw-r--r--arch/arm/mach-davinci/Makefile.boot4
-rw-r--r--arch/arm/mach-davinci/board-da830-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c116
-rw-r--r--arch/arm/mach-davinci/board-dm355-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-dm355-leopard.c2
-rw-r--r--arch/arm/mach-davinci/board-dm365-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-dm644x-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-dm646x-evm.c4
-rw-r--r--arch/arm/mach-davinci/board-mityomapl138.c2
-rw-r--r--arch/arm/mach-davinci/board-neuros-osd2.c2
-rw-r--r--arch/arm/mach-davinci/board-omapl138-hawk.c2
-rw-r--r--arch/arm/mach-davinci/board-sffsdr.c2
-rw-r--r--arch/arm/mach-davinci/board-tnetv107x-evm.c2
-rw-r--r--arch/arm/mach-davinci/common.c3
-rw-r--r--arch/arm/mach-davinci/cpuidle.c2
-rw-r--r--arch/arm/mach-davinci/da830.c3
-rw-r--r--arch/arm/mach-davinci/da850.c12
-rw-r--r--arch/arm/mach-davinci/devices-da8xx.c3
-rw-r--r--arch/arm/mach-davinci/devices-tnetv107x.c1
-rw-r--r--arch/arm/mach-davinci/dm355.c3
-rw-r--r--arch/arm/mach-davinci/dm365.c3
-rw-r--r--arch/arm/mach-davinci/dm644x.c3
-rw-r--r--arch/arm/mach-davinci/dm646x.c3
-rw-r--r--arch/arm/mach-davinci/dma.c5
-rw-r--r--arch/arm/mach-davinci/include/mach/ddr2.h4
-rw-r--r--arch/arm/mach-davinci/include/mach/debug-macro.S52
-rw-r--r--arch/arm/mach-davinci/include/mach/gpio-davinci.h91
-rw-r--r--arch/arm/mach-davinci/include/mach/gpio.h79
-rw-r--r--arch/arm/mach-davinci/include/mach/memory.h44
-rw-r--r--arch/arm/mach-davinci/include/mach/mmc.h3
-rw-r--r--arch/arm/mach-davinci/include/mach/mux.h10
-rw-r--r--arch/arm/mach-davinci/include/mach/serial.h3
-rw-r--r--arch/arm/mach-davinci/include/mach/uncompress.h7
-rw-r--r--arch/arm/mach-davinci/sleep.S2
-rw-r--r--arch/arm/mach-davinci/tnetv107x.c3
-rw-r--r--arch/arm/mach-dove/Makefile.boot2
-rw-r--r--arch/arm/mach-dove/cm-a510.c2
-rw-r--r--arch/arm/mach-dove/dove-db-setup.c2
-rw-r--r--arch/arm/mach-dove/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-dove/include/mach/memory.h10
-rw-r--r--arch/arm/mach-ebsa110/Makefile.boot2
-rw-r--r--arch/arm/mach-ebsa110/core.c2
-rw-r--r--arch/arm/mach-ebsa110/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-ebsa110/include/mach/io.h2
-rw-r--r--arch/arm/mach-ep93xx/Kconfig7
-rw-r--r--arch/arm/mach-ep93xx/Makefile1
-rw-r--r--arch/arm/mach-ep93xx/Makefile.boot10
-rw-r--r--arch/arm/mach-ep93xx/adssphere.c2
-rw-r--r--arch/arm/mach-ep93xx/core.c1
-rw-r--r--arch/arm/mach-ep93xx/edb93xx.c23
-rw-r--r--arch/arm/mach-ep93xx/gesbc9312.c2
-rw-r--r--arch/arm/mach-ep93xx/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h100
-rw-r--r--arch/arm/mach-ep93xx/include/mach/gpio.h121
-rw-r--r--arch/arm/mach-ep93xx/micro9.c8
-rw-r--r--arch/arm/mach-ep93xx/simone.c19
-rw-r--r--arch/arm/mach-ep93xx/snappercl15.c17
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c2
-rw-r--r--arch/arm/mach-ep93xx/vision_ep9307.c364
-rw-r--r--arch/arm/mach-exynos4/Kconfig72
-rw-r--r--arch/arm/mach-exynos4/Makefile12
-rw-r--r--arch/arm/mach-exynos4/Makefile.boot2
-rw-r--r--arch/arm/mach-exynos4/clock-exynos4210.c139
-rw-r--r--arch/arm/mach-exynos4/clock-exynos4212.c118
-rw-r--r--arch/arm/mach-exynos4/clock.c218
-rw-r--r--arch/arm/mach-exynos4/cpu.c57
-rw-r--r--arch/arm/mach-exynos4/hotplug.c2
-rw-r--r--arch/arm/mach-exynos4/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-exynos4/include/mach/entry-macro.S30
-rw-r--r--arch/arm/mach-exynos4/include/mach/exynos4-clock.h43
-rw-r--r--arch/arm/mach-exynos4/include/mach/gpio.h7
-rw-r--r--arch/arm/mach-exynos4/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-exynos4/include/mach/map.h4
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-clock.h54
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-mct.h5
-rw-r--r--arch/arm/mach-exynos4/mach-armlex4210.c2
-rw-r--r--arch/arm/mach-exynos4/mach-nuri.c2
-rw-r--r--arch/arm/mach-exynos4/mach-origen.c108
-rw-r--r--arch/arm/mach-exynos4/mach-smdk4x12.c302
-rw-r--r--arch/arm/mach-exynos4/mach-smdkc210.c309
-rw-r--r--arch/arm/mach-exynos4/mach-smdkv310.c80
-rw-r--r--arch/arm/mach-exynos4/mach-universal_c210.c2
-rw-r--r--arch/arm/mach-exynos4/mct.c168
-rw-r--r--arch/arm/mach-exynos4/platsmp.c25
-rw-r--r--arch/arm/mach-exynos4/pm.c79
-rw-r--r--arch/arm/mach-footbridge/Kconfig4
-rw-r--r--arch/arm/mach-footbridge/Makefile.boot2
-rw-r--r--arch/arm/mach-footbridge/cats-hw.c5
-rw-r--r--arch/arm/mach-footbridge/ebsa285.c2
-rw-r--r--arch/arm/mach-footbridge/include/mach/debug-macro.S4
-rw-r--r--arch/arm/mach-footbridge/include/mach/hardware.h2
-rw-r--r--arch/arm/mach-footbridge/include/mach/io.h2
-rw-r--r--arch/arm/mach-footbridge/netwinder-hw.c19
-rw-r--r--arch/arm/mach-footbridge/netwinder-leds.c10
-rw-r--r--arch/arm/mach-footbridge/personal.c2
-rw-r--r--arch/arm/mach-gemini/Makefile.boot4
-rw-r--r--arch/arm/mach-gemini/board-nas4220b.c2
-rw-r--r--arch/arm/mach-gemini/board-rut1xx.c2
-rw-r--r--arch/arm/mach-gemini/board-wbd111.c2
-rw-r--r--arch/arm/mach-gemini/board-wbd222.c2
-rw-r--r--arch/arm/mach-gemini/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-gemini/include/mach/gpio.h5
-rw-r--r--arch/arm/mach-gemini/include/mach/memory.h19
-rw-r--r--arch/arm/mach-h720x/Makefile.boot2
-rw-r--r--arch/arm/mach-h720x/h7201-eval.c2
-rw-r--r--arch/arm/mach-h720x/h7202-eval.c2
-rw-r--r--arch/arm/mach-h720x/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-h720x/include/mach/memory.h11
-rw-r--r--arch/arm/mach-highbank/Makefile6
-rw-r--r--arch/arm/mach-highbank/Makefile.boot1
-rw-r--r--arch/arm/mach-highbank/clock.c62
-rw-r--r--arch/arm/mach-highbank/core.h9
-rw-r--r--arch/arm/mach-highbank/highbank.c145
-rw-r--r--arch/arm/mach-highbank/hotplug.c56
-rw-r--r--arch/arm/mach-highbank/include/mach/debug-macro.S19
-rw-r--r--arch/arm/mach-highbank/include/mach/entry-macro.S7
-rw-r--r--arch/arm/mach-highbank/include/mach/gpio.h (renamed from arch/um/include/asm/ftrace.h)0
-rw-r--r--arch/arm/mach-highbank/include/mach/io.h7
-rw-r--r--arch/arm/mach-highbank/include/mach/irqs.h6
-rw-r--r--arch/arm/mach-highbank/include/mach/memory.h1
-rw-r--r--arch/arm/mach-highbank/include/mach/system.h26
-rw-r--r--arch/arm/mach-highbank/include/mach/timex.h6
-rw-r--r--arch/arm/mach-highbank/include/mach/uncompress.h9
-rw-r--r--arch/arm/mach-highbank/include/mach/vmalloc.h1
-rw-r--r--arch/arm/mach-highbank/lluart.c34
-rw-r--r--arch/arm/mach-highbank/localtimer.c40
-rw-r--r--arch/arm/mach-highbank/platsmp.c78
-rw-r--r--arch/arm/mach-highbank/pm.c55
-rw-r--r--arch/arm/mach-highbank/sysregs.h52
-rw-r--r--arch/arm/mach-highbank/system.c33
-rw-r--r--arch/arm/mach-imx/Kconfig83
-rw-r--r--arch/arm/mach-imx/Makefile26
-rw-r--r--arch/arm/mach-imx/Makefile.boot14
-rw-r--r--arch/arm/mach-imx/cache-l2x0.c56
-rw-r--r--arch/arm/mach-imx/clock-imx25.c6
-rw-r--r--arch/arm/mach-imx/clock-imx27.c6
-rw-r--r--arch/arm/mach-imx/clock-imx31.c8
-rw-r--r--arch/arm/mach-imx/clock-imx35.c7
-rw-r--r--arch/arm/mach-imx/clock-imx6q.c2012
-rw-r--r--arch/arm/mach-imx/cpu-imx25.c41
-rw-r--r--arch/arm/mach-imx/cpu-imx27.c28
-rw-r--r--arch/arm/mach-imx/cpu-imx31.c49
-rw-r--r--arch/arm/mach-imx/cpu-imx35.c30
-rw-r--r--arch/arm/mach-imx/devices-imx27.h4
-rw-r--r--arch/arm/mach-imx/devices-imx31.h4
-rw-r--r--arch/arm/mach-imx/devices-imx35.h4
-rw-r--r--arch/arm/mach-imx/gpc.c113
-rw-r--r--arch/arm/mach-imx/head-v7.S99
-rw-r--r--arch/arm/mach-imx/hotplug.c44
-rw-r--r--arch/arm/mach-imx/iomux-imx31.c3
-rw-r--r--arch/arm/mach-imx/lluart.c32
-rw-r--r--arch/arm/mach-imx/localtimer.c35
-rw-r--r--arch/arm/mach-imx/mach-apf9328.c1
-rw-r--r--arch/arm/mach-imx/mach-armadillo5x0.c21
-rw-r--r--arch/arm/mach-imx/mach-bug.c1
-rw-r--r--arch/arm/mach-imx/mach-cpuimx27.c3
-rw-r--r--arch/arm/mach-imx/mach-cpuimx35.c5
-rw-r--r--arch/arm/mach-imx/mach-eukrea_cpuimx25.c3
-rw-r--r--arch/arm/mach-imx/mach-imx27_visstrim_m10.c3
-rw-r--r--arch/arm/mach-imx/mach-imx27ipcam.c3
-rw-r--r--arch/arm/mach-imx/mach-imx27lite.c3
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c84
-rw-r--r--arch/arm/mach-imx/mach-kzm_arm11_01.c4
-rw-r--r--arch/arm/mach-imx/mach-mx1ads.c21
-rw-r--r--arch/arm/mach-imx/mach-mx21ads.c3
-rw-r--r--arch/arm/mach-imx/mach-mx25_3ds.c13
-rw-r--r--arch/arm/mach-imx/mach-mx27_3ds.c11
-rw-r--r--arch/arm/mach-imx/mach-mx27ads.c6
-rw-r--r--arch/arm/mach-imx/mach-mx31_3ds.c11
-rw-r--r--arch/arm/mach-imx/mach-mx31ads.c3
-rw-r--r--arch/arm/mach-imx/mach-mx31lilly.c3
-rw-r--r--arch/arm/mach-imx/mach-mx31lite.c3
-rw-r--r--arch/arm/mach-imx/mach-mx31moboard.c20
-rw-r--r--arch/arm/mach-imx/mach-mx35_3ds.c3
-rw-r--r--arch/arm/mach-imx/mach-mxt_td60.c3
-rw-r--r--arch/arm/mach-imx/mach-pca100.c3
-rw-r--r--arch/arm/mach-imx/mach-pcm037.c3
-rw-r--r--arch/arm/mach-imx/mach-pcm038.c7
-rw-r--r--arch/arm/mach-imx/mach-pcm043.c3
-rw-r--r--arch/arm/mach-imx/mach-qong.c9
-rw-r--r--arch/arm/mach-imx/mach-scb9328.c3
-rw-r--r--arch/arm/mach-imx/mach-vpr200.c3
-rw-r--r--arch/arm/mach-imx/mm-imx3.c256
-rw-r--r--arch/arm/mach-imx/mm-imx31.c91
-rw-r--r--arch/arm/mach-imx/mm-imx35.c109
-rw-r--r--arch/arm/mach-imx/mmdc.c72
-rw-r--r--arch/arm/mach-imx/platsmp.c85
-rw-r--r--arch/arm/mach-imx/pm-imx27.c2
-rw-r--r--arch/arm/mach-imx/pm-imx6q.c70
-rw-r--r--arch/arm/mach-imx/src.c49
-rw-r--r--arch/arm/mach-integrator/Makefile.boot2
-rw-r--r--arch/arm/mach-integrator/core.c10
-rw-r--r--arch/arm/mach-integrator/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-integrator/include/mach/io.h2
-rw-r--r--arch/arm/mach-integrator/include/mach/platform.h12
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c88
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c2
-rw-r--r--arch/arm/mach-integrator/pci_v3.c14
-rw-r--r--arch/arm/mach-iop13xx/Makefile.boot2
-rw-r--r--arch/arm/mach-iop13xx/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-iop13xx/iq81340mc.c2
-rw-r--r--arch/arm/mach-iop13xx/iq81340sc.c2
-rw-r--r--arch/arm/mach-iop32x/Makefile.boot2
-rw-r--r--arch/arm/mach-iop32x/em7210.c2
-rw-r--r--arch/arm/mach-iop32x/glantank.c2
-rw-r--r--arch/arm/mach-iop32x/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-iop32x/include/mach/memory.h13
-rw-r--r--arch/arm/mach-iop32x/iq31244.c4
-rw-r--r--arch/arm/mach-iop32x/iq80321.c2
-rw-r--r--arch/arm/mach-iop32x/n2100.c2
-rw-r--r--arch/arm/mach-iop33x/Makefile.boot2
-rw-r--r--arch/arm/mach-iop33x/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-iop33x/include/mach/memory.h13
-rw-r--r--arch/arm/mach-iop33x/iq80331.c2
-rw-r--r--arch/arm/mach-iop33x/iq80332.c2
-rw-r--r--arch/arm/mach-ixp2000/Makefile.boot2
-rw-r--r--arch/arm/mach-ixp2000/core.c4
-rw-r--r--arch/arm/mach-ixp2000/enp2611.c2
-rw-r--r--arch/arm/mach-ixp2000/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h (renamed from arch/arm/mach-ixp2000/include/mach/gpio.h)4
-rw-r--r--arch/arm/mach-ixp2000/ixdp2400.c2
-rw-r--r--arch/arm/mach-ixp2000/ixdp2800.c2
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x00.c4
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x01.c6
-rw-r--r--arch/arm/mach-ixp23xx/Makefile.boot2
-rw-r--r--arch/arm/mach-ixp23xx/espresso.c2
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-ixp23xx/ixdp2351.c2
-rw-r--r--arch/arm/mach-ixp23xx/roadrunner.c2
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig19
-rw-r--r--arch/arm/mach-ixp4xx/Makefile4
-rw-r--r--arch/arm/mach-ixp4xx/Makefile.boot2
-rw-r--r--arch/arm/mach-ixp4xx/avila-setup.c4
-rw-r--r--arch/arm/mach-ixp4xx/common-pci.c25
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c4
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-setup.c5
-rw-r--r--arch/arm/mach-ixp4xx/fsg-setup.c5
-rw-r--r--arch/arm/mach-ixp4xx/gateway7001-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/goramo_mlr.c2
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/gpio.h3
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/io.h2
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/memory.h17
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/uncompress.h3
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c8
-rw-r--r--arch/arm/mach-ixp4xx/miccpt-pci.c78
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c5
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c5
-rw-r--r--arch/arm/mach-ixp4xx/omixp-setup.c273
-rw-r--r--arch/arm/mach-ixp4xx/vulcan-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/wg302v2-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/Makefile.boot2
-rw-r--r--arch/arm/mach-kirkwood/d2net_v2-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/db88f6281-bp-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/dockstar-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/guruplug-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-kirkwood/include/mach/memory.h10
-rw-r--r--arch/arm/mach-kirkwood/irq.c3
-rw-r--r--arch/arm/mach-kirkwood/mpp.c3
-rw-r--r--arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/netspace_v2-setup.c6
-rw-r--r--arch/arm/mach-kirkwood/netxbig_v2-setup.c4
-rw-r--r--arch/arm/mach-kirkwood/openrd-setup.c6
-rw-r--r--arch/arm/mach-kirkwood/rd88f6192-nas-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/rd88f6281-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/sheevaplug-setup.c4
-rw-r--r--arch/arm/mach-kirkwood/t5325-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/ts219-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/ts41x-setup.c2
-rw-r--r--arch/arm/mach-ks8695/Makefile2
-rw-r--r--arch/arm/mach-ks8695/Makefile.boot2
-rw-r--r--arch/arm/mach-ks8695/board-acs5k.c6
-rw-r--r--arch/arm/mach-ks8695/board-dsm320.c6
-rw-r--r--arch/arm/mach-ks8695/board-micrel.c6
-rw-r--r--arch/arm/mach-ks8695/devices.c1
-rw-r--r--arch/arm/mach-ks8695/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-ks8695/include/mach/gpio-ks8695.h39
-rw-r--r--arch/arm/mach-ks8695/include/mach/gpio.h38
-rw-r--r--arch/arm/mach-ks8695/leds.c4
-rw-r--r--arch/arm/mach-l7200/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-lpc32xx/Makefile2
-rw-r--r--arch/arm/mach-lpc32xx/Makefile.boot2
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h50
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/gpio.h75
-rw-r--r--arch/arm/mach-lpc32xx/phy3250.c3
-rw-r--r--arch/arm/mach-mmp/Kconfig2
-rw-r--r--arch/arm/mach-mmp/Makefile2
-rw-r--r--arch/arm/mach-mmp/Makefile.boot2
-rw-r--r--arch/arm/mach-mmp/aspenite.c6
-rw-r--r--arch/arm/mach-mmp/brownstone.c1
-rw-r--r--arch/arm/mach-mmp/clock.h8
-rw-r--r--arch/arm/mach-mmp/common.c4
-rw-r--r--arch/arm/mach-mmp/gplugd.c4
-rw-r--r--arch/arm/mach-mmp/include/mach/addr-map.h10
-rw-r--r--arch/arm/mach-mmp/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-mmp/include/mach/gpio-pxa.h30
-rw-r--r--arch/arm/mach-mmp/include/mach/gpio.h23
-rw-r--r--arch/arm/mach-mmp/include/mach/memory.h14
-rw-r--r--arch/arm/mach-mmp/include/mach/pxa168.h7
-rw-r--r--arch/arm/mach-mmp/jasper.c1
-rw-r--r--arch/arm/mach-mmp/mmp2.c6
-rw-r--r--arch/arm/mach-mmp/pxa168.c49
-rw-r--r--arch/arm/mach-mmp/pxa910.c3
-rw-r--r--arch/arm/mach-mmp/tavorevb.c4
-rw-r--r--arch/arm/mach-mmp/ttc_dkb.c2
-rw-r--r--arch/arm/mach-msm/Makefile.boot2
-rw-r--r--arch/arm/mach-msm/board-halibut.c6
-rw-r--r--arch/arm/mach-msm/board-mahimahi.c6
-rw-r--r--arch/arm/mach-msm/board-msm7x27.c11
-rw-r--r--arch/arm/mach-msm/board-msm7x30.c31
-rw-r--r--arch/arm/mach-msm/board-msm8960.c22
-rw-r--r--arch/arm/mach-msm/board-msm8x60.c94
-rw-r--r--arch/arm/mach-msm/board-qsd8x50.c7
-rw-r--r--arch/arm/mach-msm/board-sapphire.c9
-rw-r--r--arch/arm/mach-msm/board-trout-mmc.c3
-rw-r--r--arch/arm/mach-msm/board-trout-panel.c3
-rw-r--r--arch/arm/mach-msm/board-trout.c6
-rw-r--r--arch/arm/mach-msm/clock.c2
-rw-r--r--arch/arm/mach-msm/devices-msm7x00.c24
-rw-r--r--arch/arm/mach-msm/devices-qsd8x50.c24
-rw-r--r--arch/arm/mach-msm/hotplug.c2
-rw-r--r--arch/arm/mach-msm/include/mach/debug-macro.S4
-rw-r--r--arch/arm/mach-msm/include/mach/entry-macro-qgic.S73
-rw-r--r--arch/arm/mach-msm/include/mach/gpio.h27
-rw-r--r--arch/arm/mach-msm/include/mach/memory.h35
-rw-r--r--arch/arm/mach-msm/include/mach/mmc.h9
-rw-r--r--arch/arm/mach-msm/platsmp.c8
-rw-r--r--arch/arm/mach-msm/timer.c69
-rw-r--r--arch/arm/mach-mv78xx0/Makefile.boot2
-rw-r--r--arch/arm/mach-mv78xx0/buffalo-wxl-setup.c2
-rw-r--r--arch/arm/mach-mv78xx0/db78x00-bp-setup.c2
-rw-r--r--arch/arm/mach-mv78xx0/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-mv78xx0/include/mach/memory.h10
-rw-r--r--arch/arm/mach-mv78xx0/irq.c3
-rw-r--r--arch/arm/mach-mv78xx0/mpp.c3
-rw-r--r--arch/arm/mach-mv78xx0/rd78x00-masa-setup.c2
-rw-r--r--arch/arm/mach-mx5/Kconfig50
-rw-r--r--arch/arm/mach-mx5/Makefile6
-rw-r--r--arch/arm/mach-mx5/Makefile.boot6
-rw-r--r--arch/arm/mach-mx5/board-cpuimx51.c30
-rw-r--r--arch/arm/mach-mx5/board-cpuimx51sd.c28
-rw-r--r--arch/arm/mach-mx5/board-mx50_rdp.c1
-rw-r--r--arch/arm/mach-mx5/board-mx51_3ds.c4
-rw-r--r--arch/arm/mach-mx5/board-mx51_babbage.c38
-rw-r--r--arch/arm/mach-mx5/board-mx51_efikamx.c16
-rw-r--r--arch/arm/mach-mx5/board-mx51_efikasb.c27
-rw-r--r--arch/arm/mach-mx5/board-mx53_ard.c18
-rw-r--r--arch/arm/mach-mx5/board-mx53_evk.c10
-rw-r--r--arch/arm/mach-mx5/board-mx53_loco.c31
-rw-r--r--arch/arm/mach-mx5/board-mx53_smd.c26
-rw-r--r--arch/arm/mach-mx5/clock-mx51-mx53.c72
-rw-r--r--arch/arm/mach-mx5/cpu.c74
-rw-r--r--arch/arm/mach-mx5/devices-imx51.h17
-rw-r--r--arch/arm/mach-mx5/devices-imx53.h6
-rw-r--r--arch/arm/mach-mx5/devices.c120
-rw-r--r--arch/arm/mach-mx5/devices.h5
-rw-r--r--arch/arm/mach-mx5/ehci.c2
-rw-r--r--arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c3
-rw-r--r--arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c6
-rw-r--r--arch/arm/mach-mx5/imx51-dt.c116
-rw-r--r--arch/arm/mach-mx5/imx53-dt.c126
-rw-r--r--arch/arm/mach-mx5/mm-mx50.c72
-rw-r--r--arch/arm/mach-mx5/mm.c90
-rw-r--r--arch/arm/mach-mx5/mx51_efika.c20
-rw-r--r--arch/arm/mach-mx5/pm-imx5.c18
-rw-r--r--arch/arm/mach-mx5/system.c1
-rw-r--r--arch/arm/mach-mxs/Kconfig23
-rw-r--r--arch/arm/mach-mxs/Makefile7
-rw-r--r--arch/arm/mach-mxs/Makefile.boot2
-rw-r--r--arch/arm/mach-mxs/clock-mx28.c26
-rw-r--r--arch/arm/mach-mxs/devices-mx23.h2
-rw-r--r--arch/arm/mach-mxs/devices-mx28.h5
-rw-r--r--arch/arm/mach-mxs/devices/Kconfig6
-rw-r--r--arch/arm/mach-mxs/devices/Makefile2
-rw-r--r--arch/arm/mach-mxs/devices/platform-mxs-saif.c60
-rw-r--r--arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c51
-rw-r--r--arch/arm/mach-mxs/include/mach/debug-macro.S14
-rw-r--r--arch/arm/mach-mxs/include/mach/devices-common.h12
-rw-r--r--arch/arm/mach-mxs/include/mach/gpio.h36
-rw-r--r--arch/arm/mach-mxs/include/mach/mxs.h3
-rw-r--r--arch/arm/mach-mxs/include/mach/uncompress.h1
-rw-r--r--arch/arm/mach-mxs/mach-m28evk.c366
-rw-r--r--arch/arm/mach-mxs/mach-mx23evk.c4
-rw-r--r--arch/arm/mach-mxs/mach-mx28evk.c100
-rw-r--r--arch/arm/mach-mxs/mach-stmp378x_devb.c2
-rw-r--r--arch/arm/mach-mxs/mach-tx28.c3
-rw-r--r--arch/arm/mach-mxs/mm-mx28.c44
-rw-r--r--arch/arm/mach-mxs/mm.c (renamed from arch/arm/mach-mxs/mm-mx23.c)19
-rw-r--r--arch/arm/mach-netx/Makefile.boot2
-rw-r--r--arch/arm/mach-netx/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-netx/nxdb500.c2
-rw-r--r--arch/arm/mach-netx/nxdkn.c2
-rw-r--r--arch/arm/mach-netx/nxeb500hmi.c2
-rw-r--r--arch/arm/mach-nomadik/Makefile.boot2
-rw-r--r--arch/arm/mach-nomadik/board-nhk8815.c3
-rw-r--r--arch/arm/mach-nomadik/cpu-8815.c2
-rw-r--r--arch/arm/mach-nomadik/i2c-8815nhk.c2
-rw-r--r--arch/arm/mach-nomadik/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-nomadik/include/mach/gpio.h2
-rw-r--r--arch/arm/mach-nuc93x/Kconfig19
-rw-r--r--arch/arm/mach-nuc93x/Makefile14
-rw-r--r--arch/arm/mach-nuc93x/Makefile.boot3
-rw-r--r--arch/arm/mach-nuc93x/clock.c83
-rw-r--r--arch/arm/mach-nuc93x/clock.h36
-rw-r--r--arch/arm/mach-nuc93x/cpu.c135
-rw-r--r--arch/arm/mach-nuc93x/cpu.h48
-rw-r--r--arch/arm/mach-nuc93x/dev.c42
-rw-r--r--arch/arm/mach-nuc93x/include/mach/entry-macro.S32
-rw-r--r--arch/arm/mach-nuc93x/include/mach/hardware.h22
-rw-r--r--arch/arm/mach-nuc93x/include/mach/io.h28
-rw-r--r--arch/arm/mach-nuc93x/include/mach/irqs.h59
-rw-r--r--arch/arm/mach-nuc93x/include/mach/map.h139
-rw-r--r--arch/arm/mach-nuc93x/include/mach/memory.h21
-rw-r--r--arch/arm/mach-nuc93x/include/mach/regs-clock.h53
-rw-r--r--arch/arm/mach-nuc93x/include/mach/regs-ebi.h33
-rw-r--r--arch/arm/mach-nuc93x/include/mach/regs-irq.h42
-rw-r--r--arch/arm/mach-nuc93x/include/mach/regs-serial.h52
-rw-r--r--arch/arm/mach-nuc93x/include/mach/regs-timer.h28
-rw-r--r--arch/arm/mach-nuc93x/include/mach/system.h28
-rw-r--r--arch/arm/mach-nuc93x/include/mach/timex.h25
-rw-r--r--arch/arm/mach-nuc93x/include/mach/uncompress.h50
-rw-r--r--arch/arm/mach-nuc93x/include/mach/vmalloc.h23
-rw-r--r--arch/arm/mach-nuc93x/irq.c66
-rw-r--r--arch/arm/mach-nuc93x/mach-nuc932evb.c43
-rw-r--r--arch/arm/mach-nuc93x/nuc932.c65
-rw-r--r--arch/arm/mach-nuc93x/nuc932.h29
-rw-r--r--arch/arm/mach-nuc93x/time.c100
-rw-r--r--arch/arm/mach-omap1/Makefile2
-rw-r--r--arch/arm/mach-omap1/Makefile.boot2
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c21
-rw-r--r--arch/arm/mach-omap1/board-fsample.c81
-rw-r--r--arch/arm/mach-omap1/board-generic.c21
-rw-r--r--arch/arm/mach-omap1/board-h2-mmc.c3
-rw-r--r--arch/arm/mach-omap1/board-h2.c21
-rw-r--r--arch/arm/mach-omap1/board-h3-mmc.c3
-rw-r--r--arch/arm/mach-omap1/board-h3.c21
-rw-r--r--arch/arm/mach-omap1/board-htcherald.c15
-rw-r--r--arch/arm/mach-omap1/board-innovator.c41
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c39
-rw-r--r--arch/arm/mach-omap1/board-osk.c21
-rw-r--r--arch/arm/mach-omap1/board-palmte.c21
-rw-r--r--arch/arm/mach-omap1/board-palmtt.c20
-rw-r--r--arch/arm/mach-omap1/board-palmz71.c22
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c80
-rw-r--r--arch/arm/mach-omap1/board-sx1-mmc.c2
-rw-r--r--arch/arm/mach-omap1/board-sx1.c22
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c20
-rw-r--r--arch/arm/mach-omap1/devices.c5
-rw-r--r--arch/arm/mach-omap1/fpga.c2
-rw-r--r--arch/arm/mach-omap1/include/mach/debug-macro.S48
-rw-r--r--arch/arm/mach-omap1/include/mach/memory.h53
-rw-r--r--arch/arm/mach-omap1/io.c58
-rw-r--r--arch/arm/mach-omap1/irq.c3
-rw-r--r--arch/arm/mach-omap1/leds-h2p2-debug.c2
-rw-r--r--arch/arm/mach-omap1/leds-osk.c3
-rw-r--r--arch/arm/mach-omap1/leds.c2
-rw-r--r--arch/arm/mach-omap1/mcbsp.c45
-rw-r--r--arch/arm/mach-omap1/pm_bus.c1
-rw-r--r--arch/arm/mach-omap1/serial.c3
-rw-r--r--arch/arm/mach-omap1/timer.c173
-rw-r--r--arch/arm/mach-omap2/Kconfig10
-rw-r--r--arch/arm/mach-omap2/Makefile98
-rw-r--r--arch/arm/mach-omap2/Makefile.boot2
-rw-r--r--arch/arm/mach-omap2/board-2430sdp.c95
-rw-r--r--arch/arm/mach-omap2/board-3430sdp.c18
-rw-r--r--arch/arm/mach-omap2/board-3630sdp.c13
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c229
-rw-r--r--arch/arm/mach-omap2/board-am3517crane.c11
-rw-r--r--arch/arm/mach-omap2/board-am3517evm.c16
-rw-r--r--arch/arm/mach-omap2/board-apollon.c51
-rw-r--r--arch/arm/mach-omap2/board-cm-t35.c23
-rw-r--r--arch/arm/mach-omap2/board-cm-t3517.c11
-rw-r--r--arch/arm/mach-omap2/board-devkit8000.c31
-rw-r--r--arch/arm/mach-omap2/board-flash.c5
-rw-r--r--arch/arm/mach-omap2/board-flash.h19
-rw-r--r--arch/arm/mach-omap2/board-generic.c163
-rw-r--r--arch/arm/mach-omap2/board-h4.c69
-rw-r--r--arch/arm/mach-omap2/board-igep0020.c25
-rw-r--r--arch/arm/mach-omap2/board-ldp.c130
-rw-r--r--arch/arm/mach-omap2/board-n8x0.c31
-rw-r--r--arch/arm/mach-omap2/board-omap3beagle.c32
-rw-r--r--arch/arm/mach-omap2/board-omap3evm.c18
-rw-r--r--arch/arm/mach-omap2/board-omap3logic.c15
-rw-r--r--arch/arm/mach-omap2/board-omap3pandora.c15
-rw-r--r--arch/arm/mach-omap2/board-omap3stalker.c58
-rw-r--r--arch/arm/mach-omap2/board-omap3touchbook.c38
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c27
-rw-r--r--arch/arm/mach-omap2/board-overo.c20
-rw-r--r--arch/arm/mach-omap2/board-rm680.c27
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c1
-rw-r--r--arch/arm/mach-omap2/board-rx51.c52
-rw-r--r--arch/arm/mach-omap2/board-ti8168evm.c12
-rw-r--r--arch/arm/mach-omap2/board-zoom.c27
-rw-r--r--arch/arm/mach-omap2/clock2420_data.c48
-rw-r--r--arch/arm/mach-omap2/clock2430_data.c48
-rw-r--r--arch/arm/mach-omap2/clock3xxx_data.c47
-rw-r--r--arch/arm/mach-omap2/clock44xx_data.c33
-rw-r--r--arch/arm/mach-omap2/clockdomain.c149
-rw-r--r--arch/arm/mach-omap2/clockdomain.h22
-rw-r--r--arch/arm/mach-omap2/clockdomain2xxx_3xxx.c4
-rw-r--r--arch/arm/mach-omap2/clockdomain44xx.c2
-rw-r--r--arch/arm/mach-omap2/clockdomains2420_data.c154
-rw-r--r--arch/arm/mach-omap2/clockdomains2430_data.c181
-rw-r--r--arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c803
-rw-r--r--arch/arm/mach-omap2/clockdomains3xxx_data.c398
-rw-r--r--arch/arm/mach-omap2/clockdomains44xx_data.c409
-rw-r--r--arch/arm/mach-omap2/common.c62
-rw-r--r--arch/arm/mach-omap2/control.c14
-rw-r--r--arch/arm/mach-omap2/devices.c125
-rw-r--r--arch/arm/mach-omap2/display.c77
-rw-r--r--arch/arm/mach-omap2/dma.c25
-rw-r--r--arch/arm/mach-omap2/gpio.c22
-rw-r--r--arch/arm/mach-omap2/hsmmc.c26
-rw-r--r--arch/arm/mach-omap2/hwspinlock.c21
-rw-r--r--arch/arm/mach-omap2/id.c191
-rw-r--r--arch/arm/mach-omap2/include/mach/debug-macro.S81
-rw-r--r--arch/arm/mach-omap2/include/mach/entry-macro.S14
-rw-r--r--arch/arm/mach-omap2/include/mach/memory.h5
-rw-r--r--arch/arm/mach-omap2/io.c152
-rw-r--r--arch/arm/mach-omap2/io.h7
-rw-r--r--arch/arm/mach-omap2/iommu2.c31
-rw-r--r--arch/arm/mach-omap2/irq.c4
-rw-r--r--arch/arm/mach-omap2/mcbsp.c120
-rw-r--r--arch/arm/mach-omap2/omap-smp.c17
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c3
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2420_data.c59
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2430_data.c67
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c200
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c106
-rw-r--r--arch/arm/mach-omap2/omap_l3_noc.c147
-rw-r--r--arch/arm/mach-omap2/omap_l3_noc.h224
-rw-r--r--arch/arm/mach-omap2/omap_l3_smx.c91
-rw-r--r--arch/arm/mach-omap2/omap_l3_smx.h164
-rw-r--r--arch/arm/mach-omap2/omap_twl.c107
-rw-r--r--arch/arm/mach-omap2/opp.c2
-rw-r--r--arch/arm/mach-omap2/pm.c104
-rw-r--r--arch/arm/mach-omap2/pm24xx.c27
-rw-r--r--arch/arm/mach-omap2/pm34xx.c2
-rw-r--r--arch/arm/mach-omap2/powerdomain-common.c7
-rw-r--r--arch/arm/mach-omap2/powerdomain.c110
-rw-r--r--arch/arm/mach-omap2/powerdomain.h19
-rw-r--r--arch/arm/mach-omap2/powerdomain2xxx_3xxx.c2
-rw-r--r--arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c21
-rw-r--r--arch/arm/mach-omap2/powerdomains2xxx_data.c48
-rw-r--r--arch/arm/mach-omap2/powerdomains3xxx_data.c97
-rw-r--r--arch/arm/mach-omap2/powerdomains44xx_data.c36
-rw-r--r--arch/arm/mach-omap2/prcm.c19
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.c56
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.h12
-rw-r--r--arch/arm/mach-omap2/prm44xx.c71
-rw-r--r--arch/arm/mach-omap2/prm44xx.h12
-rw-r--r--arch/arm/mach-omap2/sdrc.c13
-rw-r--r--arch/arm/mach-omap2/serial.c39
-rw-r--r--arch/arm/mach-omap2/smartreflex-class3.c4
-rw-r--r--arch/arm/mach-omap2/smartreflex.c31
-rw-r--r--arch/arm/mach-omap2/sr_device.c19
-rw-r--r--arch/arm/mach-omap2/timer.c194
-rw-r--r--arch/arm/mach-omap2/twl-common.c11
-rw-r--r--arch/arm/mach-omap2/usb-musb.c26
-rw-r--r--arch/arm/mach-omap2/vc.c367
-rw-r--r--arch/arm/mach-omap2/vc.h88
-rw-r--r--arch/arm/mach-omap2/vc3xxx_data.c31
-rw-r--r--arch/arm/mach-omap2/vc44xx_data.c44
-rw-r--r--arch/arm/mach-omap2/voltage.c1088
-rw-r--r--arch/arm/mach-omap2/voltage.h150
-rw-r--r--arch/arm/mach-omap2/voltagedomains2xxx_data.c32
-rw-r--r--arch/arm/mach-omap2/voltagedomains3xxx_data.c83
-rw-r--r--arch/arm/mach-omap2/voltagedomains44xx_data.c99
-rw-r--r--arch/arm/mach-omap2/vp.c278
-rw-r--r--arch/arm/mach-omap2/vp.h133
-rw-r--r--arch/arm/mach-omap2/vp3xxx_data.c35
-rw-r--r--arch/arm/mach-omap2/vp44xx_data.c47
-rw-r--r--arch/arm/mach-orion5x/Makefile.boot2
-rw-r--r--arch/arm/mach-orion5x/common.c4
-rw-r--r--arch/arm/mach-orion5x/common.h4
-rw-r--r--arch/arm/mach-orion5x/d2net-setup.c4
-rw-r--r--arch/arm/mach-orion5x/db88f5281-setup.c5
-rw-r--r--arch/arm/mach-orion5x/dns323-setup.c5
-rw-r--r--arch/arm/mach-orion5x/edmini_v2-setup.c2
-rw-r--r--arch/arm/mach-orion5x/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-orion5x/include/mach/memory.h12
-rw-r--r--arch/arm/mach-orion5x/irq.c3
-rw-r--r--arch/arm/mach-orion5x/kurobox_pro-setup.c7
-rw-r--r--arch/arm/mach-orion5x/ls-chl-setup.c2
-rw-r--r--arch/arm/mach-orion5x/ls_hgl-setup.c2
-rw-r--r--arch/arm/mach-orion5x/lsmini-setup.c2
-rw-r--r--arch/arm/mach-orion5x/mss2-setup.c2
-rw-r--r--arch/arm/mach-orion5x/mv2120-setup.c5
-rw-r--r--arch/arm/mach-orion5x/net2big-setup.c2
-rw-r--r--arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c5
-rw-r--r--arch/arm/mach-orion5x/rd88f5181l-ge-setup.c5
-rw-r--r--arch/arm/mach-orion5x/rd88f5182-setup.c5
-rw-r--r--arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c5
-rw-r--r--arch/arm/mach-orion5x/terastation_pro2-setup.c5
-rw-r--r--arch/arm/mach-orion5x/ts209-setup.c5
-rw-r--r--arch/arm/mach-orion5x/ts409-setup.c5
-rw-r--r--arch/arm/mach-orion5x/ts78xx-setup.c2
-rw-r--r--arch/arm/mach-orion5x/wnr854t-setup.c5
-rw-r--r--arch/arm/mach-orion5x/wrt350n-v2-setup.c5
-rw-r--r--arch/arm/mach-picoxcell/Makefile3
-rw-r--r--arch/arm/mach-picoxcell/Makefile.boot1
-rw-r--r--arch/arm/mach-picoxcell/common.c55
-rw-r--r--arch/arm/mach-picoxcell/common.h18
-rw-r--r--arch/arm/mach-picoxcell/include/mach/debug-macro.S35
-rw-r--r--arch/arm/mach-picoxcell/include/mach/entry-macro.S19
-rw-r--r--arch/arm/mach-picoxcell/include/mach/gpio.h1
-rw-r--r--arch/arm/mach-picoxcell/include/mach/hardware.h (renamed from arch/arm/mach-lpc32xx/include/mach/memory.h)16
-rw-r--r--arch/arm/mach-picoxcell/include/mach/io.h22
-rw-r--r--arch/arm/mach-picoxcell/include/mach/irqs.h25
-rw-r--r--arch/arm/mach-picoxcell/include/mach/map.h (renamed from arch/arm/mach-nomadik/include/mach/memory.h)23
-rw-r--r--arch/arm/mach-picoxcell/include/mach/memory.h1
-rw-r--r--arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h25
-rw-r--r--arch/arm/mach-picoxcell/include/mach/system.h31
-rw-r--r--arch/arm/mach-picoxcell/include/mach/timex.h (renamed from arch/arm/mach-vexpress/include/mach/memory.h)14
-rw-r--r--arch/arm/mach-picoxcell/include/mach/uncompress.h (renamed from arch/arm/include/asm/sizes.h)12
-rw-r--r--arch/arm/mach-picoxcell/include/mach/vmalloc.h14
-rw-r--r--arch/arm/mach-picoxcell/io.c32
-rw-r--r--arch/arm/mach-picoxcell/time.c132
-rw-r--r--arch/arm/mach-pnx4008/Makefile.boot2
-rw-r--r--arch/arm/mach-pnx4008/core.c2
-rw-r--r--arch/arm/mach-pnx4008/gpio.c3
-rw-r--r--arch/arm/mach-pnx4008/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h (renamed from arch/arm/mach-pnx4008/include/mach/gpio.h)2
-rw-r--r--arch/arm/mach-pnx4008/include/mach/memory.h21
-rw-r--r--arch/arm/mach-pnx4008/serial.c3
-rw-r--r--arch/arm/mach-prima2/Makefile2
-rw-r--r--arch/arm/mach-prima2/Makefile.boot2
-rw-r--r--arch/arm/mach-prima2/clock.c4
-rw-r--r--arch/arm/mach-prima2/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-prima2/include/mach/memory.h21
-rw-r--r--arch/arm/mach-prima2/irq.c43
-rw-r--r--arch/arm/mach-prima2/l2x0.c46
-rw-r--r--arch/arm/mach-prima2/pm.c150
-rw-r--r--arch/arm/mach-prima2/pm.h29
-rw-r--r--arch/arm/mach-prima2/prima2.c5
-rw-r--r--arch/arm/mach-prima2/rtciobrg.c139
-rw-r--r--arch/arm/mach-prima2/sleep.S64
-rw-r--r--arch/arm/mach-prima2/timer.c38
-rw-r--r--arch/arm/mach-pxa/Kconfig38
-rw-r--r--arch/arm/mach-pxa/Makefile2
-rw-r--r--arch/arm/mach-pxa/Makefile.boot2
-rw-r--r--arch/arm/mach-pxa/balloon3.c12
-rw-r--r--arch/arm/mach-pxa/capc7117.c2
-rw-r--r--arch/arm/mach-pxa/cm-x255.c1
-rw-r--r--arch/arm/mach-pxa/cm-x2xx-pci.c2
-rw-r--r--arch/arm/mach-pxa/cm-x2xx.c6
-rw-r--r--arch/arm/mach-pxa/cm-x300.c14
-rw-r--r--arch/arm/mach-pxa/colibri-pxa270.c4
-rw-r--r--arch/arm/mach-pxa/colibri-pxa300.c2
-rw-r--r--arch/arm/mach-pxa/colibri-pxa320.c2
-rw-r--r--arch/arm/mach-pxa/corgi.c4
-rw-r--r--arch/arm/mach-pxa/csb726.c2
-rw-r--r--arch/arm/mach-pxa/em-x270.c4
-rw-r--r--arch/arm/mach-pxa/eseries.c15
-rw-r--r--arch/arm/mach-pxa/eseries.h3
-rw-r--r--arch/arm/mach-pxa/ezx.c12
-rw-r--r--arch/arm/mach-pxa/generic.c2
-rw-r--r--arch/arm/mach-pxa/gumstix.c2
-rw-r--r--arch/arm/mach-pxa/h5000.c2
-rw-r--r--arch/arm/mach-pxa/himalaya.c2
-rw-r--r--arch/arm/mach-pxa/hx4700.c2
-rw-r--r--arch/arm/mach-pxa/icontrol.c2
-rw-r--r--arch/arm/mach-pxa/include/mach/addr-map.h8
-rw-r--r--arch/arm/mach-pxa/include/mach/balloon3.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-pxa/include/mach/gpio-pxa.h133
-rw-r--r--arch/arm/mach-pxa/include/mach/gpio.h110
-rw-r--r--arch/arm/mach-pxa/include/mach/hardware.h9
-rw-r--r--arch/arm/mach-pxa/include/mach/littleton.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/lpd270.h4
-rw-r--r--arch/arm/mach-pxa/include/mach/memory.h20
-rw-r--r--arch/arm/mach-pxa/include/mach/mtd-xip.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/palm27x.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/palmtx.h6
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa27x.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa95x.h7
-rw-r--r--arch/arm/mach-pxa/include/mach/pxafb.h13
-rw-r--r--arch/arm/mach-pxa/include/mach/smemc.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/zeus.h4
-rw-r--r--arch/arm/mach-pxa/include/mach/zylonite.h4
-rw-r--r--arch/arm/mach-pxa/irq.c9
-rw-r--r--arch/arm/mach-pxa/littleton.c2
-rw-r--r--arch/arm/mach-pxa/lpd270.c7
-rw-r--r--arch/arm/mach-pxa/lubbock.c2
-rw-r--r--arch/arm/mach-pxa/magician.c2
-rw-r--r--arch/arm/mach-pxa/mainstone.c5
-rw-r--r--arch/arm/mach-pxa/mfp-pxa2xx.c4
-rw-r--r--arch/arm/mach-pxa/mioa701.c2
-rw-r--r--arch/arm/mach-pxa/mp900.c2
-rw-r--r--arch/arm/mach-pxa/palmld.c2
-rw-r--r--arch/arm/mach-pxa/palmt5.c2
-rw-r--r--arch/arm/mach-pxa/palmtc.c2
-rw-r--r--arch/arm/mach-pxa/palmte2.c2
-rw-r--r--arch/arm/mach-pxa/palmtreo.c12
-rw-r--r--arch/arm/mach-pxa/palmtx.c10
-rw-r--r--arch/arm/mach-pxa/palmz72.c2
-rw-r--r--arch/arm/mach-pxa/pcm027.c2
-rw-r--r--arch/arm/mach-pxa/pcm990-baseboard.c3
-rw-r--r--arch/arm/mach-pxa/poodle.c4
-rw-r--r--arch/arm/mach-pxa/pxa25x.c5
-rw-r--r--arch/arm/mach-pxa/pxa27x.c5
-rw-r--r--arch/arm/mach-pxa/pxa3xx-ulpi.c2
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c5
-rw-r--r--arch/arm/mach-pxa/pxa95x.c3
-rw-r--r--arch/arm/mach-pxa/raumfeld.c6
-rw-r--r--arch/arm/mach-pxa/saar.c4
-rw-r--r--arch/arm/mach-pxa/saarb.c7
-rw-r--r--arch/arm/mach-pxa/spitz.c4
-rw-r--r--arch/arm/mach-pxa/stargate2.c4
-rw-r--r--arch/arm/mach-pxa/tavorevb.c2
-rw-r--r--arch/arm/mach-pxa/tavorevb3.c2
-rw-r--r--arch/arm/mach-pxa/tosa.c4
-rw-r--r--arch/arm/mach-pxa/trizeps4.c4
-rw-r--r--arch/arm/mach-pxa/viper.c2
-rw-r--r--arch/arm/mach-pxa/vpac270.c2
-rw-r--r--arch/arm/mach-pxa/xcep.c5
-rw-r--r--arch/arm/mach-pxa/z2.c5
-rw-r--r--arch/arm/mach-pxa/zeus.c10
-rw-r--r--arch/arm/mach-pxa/zylonite.c2
-rw-r--r--arch/arm/mach-realview/Makefile.boot4
-rw-r--r--arch/arm/mach-realview/core.c3
-rw-r--r--arch/arm/mach-realview/core.h4
-rw-r--r--arch/arm/mach-realview/hotplug.c2
-rw-r--r--arch/arm/mach-realview/include/mach/board-pb1176.h1
-rw-r--r--arch/arm/mach-realview/include/mach/debug-macro.S19
-rw-r--r--arch/arm/mach-realview/include/mach/gpio.h7
-rw-r--r--arch/arm/mach-realview/platsmp.c10
-rw-r--r--arch/arm/mach-realview/realview_eb.c2
-rw-r--r--arch/arm/mach-realview/realview_pb1176.c50
-rw-r--r--arch/arm/mach-realview/realview_pb11mp.c2
-rw-r--r--arch/arm/mach-realview/realview_pba8.c2
-rw-r--r--arch/arm/mach-realview/realview_pbx.c8
-rw-r--r--arch/arm/mach-rpc/Makefile.boot2
-rw-r--r--arch/arm/mach-rpc/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-rpc/include/mach/hardware.h25
-rw-r--r--arch/arm/mach-rpc/include/mach/io.h193
-rw-r--r--arch/arm/mach-rpc/riscpc.c4
-rw-r--r--arch/arm/mach-s3c2400/include/mach/memory.h20
-rw-r--r--arch/arm/mach-s3c2410/Kconfig6
-rw-r--r--arch/arm/mach-s3c2410/Makefile1
-rw-r--r--arch/arm/mach-s3c2410/Makefile.boot4
-rw-r--r--arch/arm/mach-s3c2410/dma.c14
-rw-r--r--arch/arm/mach-s3c2410/gpio.c72
-rw-r--r--arch/arm/mach-s3c2410/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-s3c2410/include/mach/gpio.h6
-rw-r--r--arch/arm/mach-s3c2410/include/mach/h1940-latch.h2
-rw-r--r--arch/arm/mach-s3c2410/include/mach/io.h2
-rw-r--r--arch/arm/mach-s3c2410/include/mach/map.h52
-rw-r--r--arch/arm/mach-s3c2410/include/mach/memory.h16
-rw-r--r--arch/arm/mach-s3c2410/mach-amlm5900.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-n30.c4
-rw-r--r--arch/arm/mach-s3c2410/mach-otom.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-qt2410.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-tct_hammer.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c2
-rw-r--r--arch/arm/mach-s3c2412/Kconfig1
-rw-r--r--arch/arm/mach-s3c2412/Makefile1
-rw-r--r--arch/arm/mach-s3c2412/dma.c18
-rw-r--r--arch/arm/mach-s3c2412/gpio.c62
-rw-r--r--arch/arm/mach-s3c2412/mach-jive.c2
-rw-r--r--arch/arm/mach-s3c2412/mach-smdk2413.c9
-rw-r--r--arch/arm/mach-s3c2412/mach-vstms.c7
-rw-r--r--arch/arm/mach-s3c2416/mach-smdk2416.c2
-rw-r--r--arch/arm/mach-s3c2440/Kconfig2
-rw-r--r--arch/arm/mach-s3c2440/dma.c17
-rw-r--r--arch/arm/mach-s3c2440/mach-anubis.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-at2440evb.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-gta02.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-mini2440.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-nexcoder.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-osiris.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-rx1950.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-rx3715.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-smdk2440.c2
-rw-r--r--arch/arm/mach-s3c2443/dma.c27
-rw-r--r--arch/arm/mach-s3c2443/mach-smdk2443.c2
-rw-r--r--arch/arm/mach-s3c64xx/Makefile.boot2
-rw-r--r--arch/arm/mach-s3c64xx/cpu.c24
-rw-r--r--arch/arm/mach-s3c64xx/dev-uart.c60
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/gpio.h7
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/irqs.h30
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/map.h9
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/memory.h20
-rw-r--r--arch/arm/mach-s3c64xx/irq.c25
-rw-r--r--arch/arm/mach-s3c64xx/mach-anw6410.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410.c5
-rw-r--r--arch/arm/mach-s3c64xx/mach-hmt.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-mini6410.c10
-rw-r--r--arch/arm/mach-s3c64xx/mach-ncp.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-real6410.c10
-rw-r--r--arch/arm/mach-s3c64xx/mach-smartq5.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-smartq7.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6400.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6410.c10
-rw-r--r--arch/arm/mach-s5p64x0/Makefile.boot2
-rw-r--r--arch/arm/mach-s5p64x0/cpu.c3
-rw-r--r--arch/arm/mach-s5p64x0/dev-spi.c8
-rw-r--r--arch/arm/mach-s5p64x0/dma.c7
-rw-r--r--arch/arm/mach-s5p64x0/gpiolib.c7
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/gpio.h7
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/memory.h19
-rw-r--r--arch/arm/mach-s5p64x0/irq-eint.c3
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6440.c10
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6450.c10
-rw-r--r--arch/arm/mach-s5pc100/Makefile.boot2
-rw-r--r--arch/arm/mach-s5pc100/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-s5pc100/include/mach/gpio.h7
-rw-r--r--arch/arm/mach-s5pc100/include/mach/memory.h18
-rw-r--r--arch/arm/mach-s5pc100/mach-smdkc100.c10
-rw-r--r--arch/arm/mach-s5pv210/Kconfig6
-rw-r--r--arch/arm/mach-s5pv210/Makefile2
-rw-r--r--arch/arm/mach-s5pv210/Makefile.boot2
-rw-r--r--arch/arm/mach-s5pv210/cpu.c2
-rw-r--r--arch/arm/mach-s5pv210/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-s5pv210/include/mach/gpio.h7
-rw-r--r--arch/arm/mach-s5pv210/include/mach/memory.h1
-rw-r--r--arch/arm/mach-s5pv210/mach-aquila.c2
-rw-r--r--arch/arm/mach-s5pv210/mach-goni.c2
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkc110.c2
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkv210.c10
-rw-r--r--arch/arm/mach-s5pv210/mach-torbreck.c2
-rw-r--r--arch/arm/mach-sa1100/Makefile3
-rw-r--r--arch/arm/mach-sa1100/Makefile.boot5
-rw-r--r--arch/arm/mach-sa1100/assabet.c5
-rw-r--r--arch/arm/mach-sa1100/badge4.c2
-rw-r--r--arch/arm/mach-sa1100/generic.c2
-rw-r--r--arch/arm/mach-sa1100/h3100.c2
-rw-r--r--arch/arm/mach-sa1100/h3600.c2
-rw-r--r--arch/arm/mach-sa1100/hackkit.c2
-rw-r--r--arch/arm/mach-sa1100/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-sa1100/include/mach/gpio.h4
-rw-r--r--arch/arm/mach-sa1100/include/mach/io.h6
-rw-r--r--arch/arm/mach-sa1100/include/mach/simpad.h94
-rw-r--r--arch/arm/mach-sa1100/jornada720.c2
-rw-r--r--arch/arm/mach-sa1100/lart.c2
-rw-r--r--arch/arm/mach-sa1100/leds-simpad.c100
-rw-r--r--arch/arm/mach-sa1100/leds.c2
-rw-r--r--arch/arm/mach-sa1100/leds.h1
-rw-r--r--arch/arm/mach-sa1100/nanoengine.c2
-rw-r--r--arch/arm/mach-sa1100/shannon.c2
-rw-r--r--arch/arm/mach-sa1100/simpad.c215
-rw-r--r--arch/arm/mach-shark/Makefile.boot2
-rw-r--r--arch/arm/mach-shark/core.c2
-rw-r--r--arch/arm/mach-shark/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-shark/leds.c6
-rw-r--r--arch/arm/mach-shmobile/Makefile.boot2
-rw-r--r--arch/arm/mach-shmobile/board-ag5evm.c9
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c9
-rw-r--r--arch/arm/mach-shmobile/board-g3evm.c3
-rw-r--r--arch/arm/mach-shmobile/board-g4evm.c3
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c22
-rw-r--r--arch/arm/mach-shmobile/entry-intc.S3
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h4
-rw-r--r--arch/arm/mach-shmobile/include/mach/entry-macro.S3
-rw-r--r--arch/arm/mach-shmobile/include/mach/gpio.h24
-rw-r--r--arch/arm/mach-shmobile/include/mach/memory.h3
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h13
-rw-r--r--arch/arm/mach-shmobile/intc-sh7372.c52
-rw-r--r--arch/arm/mach-shmobile/platsmp.c6
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c342
-rw-r--r--arch/arm/mach-shmobile/pm_runtime.c1
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c25
-rw-r--r--arch/arm/mach-shmobile/sleep-sh7372.S221
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c6
-rw-r--r--arch/arm/mach-spear3xx/Makefile.boot2
-rw-r--r--arch/arm/mach-spear3xx/include/mach/memory.h19
-rw-r--r--arch/arm/mach-spear3xx/spear300_evb.c2
-rw-r--r--arch/arm/mach-spear3xx/spear310_evb.c2
-rw-r--r--arch/arm/mach-spear3xx/spear320_evb.c2
-rw-r--r--arch/arm/mach-spear6xx/Makefile.boot2
-rw-r--r--arch/arm/mach-spear6xx/include/mach/memory.h19
-rw-r--r--arch/arm/mach-spear6xx/spear600_evb.c2
-rw-r--r--arch/arm/mach-tcc8k/Makefile.boot2
-rw-r--r--arch/arm/mach-tcc8k/board-tcc8000-sdk.c2
-rw-r--r--arch/arm/mach-tegra/Kconfig6
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/Makefile.boot3
-rw-r--r--arch/arm/mach-tegra/board-dt.c26
-rw-r--r--arch/arm/mach-tegra/board-harmony-pcie.c10
-rw-r--r--arch/arm/mach-tegra/board-harmony-pinmux.c8
-rw-r--r--arch/arm/mach-tegra/board-harmony-power.c13
-rw-r--r--arch/arm/mach-tegra/board-harmony.c11
-rw-r--r--arch/arm/mach-tegra/board-harmony.h3
-rw-r--r--arch/arm/mach-tegra/board-paz00-pinmux.c11
-rw-r--r--arch/arm/mach-tegra/board-paz00.c70
-rw-r--r--arch/arm/mach-tegra/board-paz00.h10
-rw-r--r--arch/arm/mach-tegra/board-seaboard-pinmux.c75
-rw-r--r--arch/arm/mach-tegra/board-seaboard.c87
-rw-r--r--arch/arm/mach-tegra/board-seaboard.h14
-rw-r--r--arch/arm/mach-tegra/board-trimslice-pinmux.c10
-rw-r--r--arch/arm/mach-tegra/board-trimslice.c10
-rw-r--r--arch/arm/mach-tegra/board-trimslice.h2
-rw-r--r--arch/arm/mach-tegra/common.c2
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c6
-rw-r--r--arch/arm/mach-tegra/devices.c86
-rw-r--r--arch/arm/mach-tegra/devices.h2
-rw-r--r--arch/arm/mach-tegra/dma.c14
-rw-r--r--arch/arm/mach-tegra/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-tegra/include/mach/gpio-tegra.h (renamed from arch/arm/mach-tegra/include/mach/memory.h)25
-rw-r--r--arch/arm/mach-tegra/include/mach/gpio.h61
-rw-r--r--arch/arm/mach-tegra/include/mach/io.h18
-rw-r--r--arch/arm/mach-tegra/include/mach/pinmux.h4
-rw-r--r--arch/arm/mach-tegra/include/mach/powergate.h1
-rw-r--r--arch/arm/mach-tegra/io.c8
-rw-r--r--arch/arm/mach-tegra/pcie.c8
-rw-r--r--arch/arm/mach-tegra/pinmux-t2-tables.c76
-rw-r--r--arch/arm/mach-tegra/pinmux.c163
-rw-r--r--arch/arm/mach-tegra/platsmp.c8
-rw-r--r--arch/arm/mach-tegra/powergate.c5
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c50
-rw-r--r--arch/arm/mach-tegra/timer.c6
-rw-r--r--arch/arm/mach-tegra/usb_phy.c1
-rw-r--r--arch/arm/mach-u300/Kconfig49
-rw-r--r--arch/arm/mach-u300/Makefile2
-rw-r--r--arch/arm/mach-u300/Makefile.boot17
-rw-r--r--arch/arm/mach-u300/core.c197
-rw-r--r--arch/arm/mach-u300/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-u300/include/mach/gpio-u300.h150
-rw-r--r--arch/arm/mach-u300/include/mach/gpio.h295
-rw-r--r--arch/arm/mach-u300/include/mach/irqs.h16
-rw-r--r--arch/arm/mach-u300/include/mach/memory.h27
-rw-r--r--arch/arm/mach-u300/include/mach/syscon.h136
-rw-r--r--arch/arm/mach-u300/mmc.c18
-rw-r--r--arch/arm/mach-u300/padmux.c367
-rw-r--r--arch/arm/mach-u300/padmux.h39
-rw-r--r--arch/arm/mach-u300/spi.c20
-rw-r--r--arch/arm/mach-u300/u300.c18
-rw-r--r--arch/arm/mach-ux500/Makefile3
-rw-r--r--arch/arm/mach-ux500/Makefile.boot2
-rw-r--r--arch/arm/mach-ux500/board-mop500-pins.c36
-rw-r--r--arch/arm/mach-ux500/board-mop500-sdi.c52
-rw-r--r--arch/arm/mach-ux500/board-mop500-u8500uib.c3
-rw-r--r--arch/arm/mach-ux500/board-mop500.c85
-rw-r--r--arch/arm/mach-ux500/board-mop500.h3
-rw-r--r--arch/arm/mach-ux500/board-u5500-sdi.c2
-rw-r--r--arch/arm/mach-ux500/board-u5500.c4
-rw-r--r--arch/arm/mach-ux500/cache-l2x0.c95
-rw-r--r--arch/arm/mach-ux500/cpu-db5500.c2
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c2
-rw-r--r--arch/arm/mach-ux500/cpu.c98
-rw-r--r--arch/arm/mach-ux500/devices-common.c2
-rw-r--r--arch/arm/mach-ux500/hotplug.c2
-rw-r--r--arch/arm/mach-ux500/include/mach/db5500-regs.h2
-rw-r--r--arch/arm/mach-ux500/include/mach/db8500-regs.h3
-rw-r--r--arch/arm/mach-ux500/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-ux500/include/mach/gpio.h2
-rw-r--r--arch/arm/mach-ux500/include/mach/memory.h18
-rw-r--r--arch/arm/mach-ux500/include/mach/uncompress.h10
-rw-r--r--arch/arm/mach-ux500/pins-db8500.h142
-rw-r--r--arch/arm/mach-ux500/platsmp.c12
-rw-r--r--arch/arm/mach-ux500/timer.c68
-rw-r--r--arch/arm/mach-versatile/Makefile.boot2
-rw-r--r--arch/arm/mach-versatile/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-versatile/include/mach/gpio.h7
-rw-r--r--arch/arm/mach-versatile/include/mach/memory.h28
-rw-r--r--arch/arm/mach-versatile/versatile_ab.c2
-rw-r--r--arch/arm/mach-versatile/versatile_pb.c2
-rw-r--r--arch/arm/mach-vexpress/Makefile.boot2
-rw-r--r--arch/arm/mach-vexpress/ct-ca9x4.c6
-rw-r--r--arch/arm/mach-vexpress/hotplug.c11
-rw-r--r--arch/arm/mach-vexpress/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-vexpress/include/mach/gpio.h1
-rw-r--r--arch/arm/mach-vexpress/include/mach/io.h2
-rw-r--r--arch/arm/mach-vexpress/v2m.c2
-rw-r--r--arch/arm/mach-vt8500/Makefile.boot2
-rw-r--r--arch/arm/mach-vt8500/bv07.c2
-rw-r--r--arch/arm/mach-vt8500/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-vt8500/include/mach/gpio.h7
-rw-r--r--arch/arm/mach-vt8500/include/mach/io.h2
-rw-r--r--arch/arm/mach-vt8500/wm8505_7in.c2
-rw-r--r--arch/arm/mach-w90x900/Makefile.boot2
-rw-r--r--arch/arm/mach-w90x900/cpu.c2
-rw-r--r--arch/arm/mach-w90x900/include/mach/gpio.h6
-rw-r--r--arch/arm/mach-w90x900/include/mach/memory.h23
-rw-r--r--arch/arm/mach-w90x900/mach-nuc910evb.c1
-rw-r--r--arch/arm/mach-w90x900/mach-nuc950evb.c1
-rw-r--r--arch/arm/mach-w90x900/mach-nuc960evb.c1
-rw-r--r--arch/arm/mach-zynq/Makefile.boot2
-rw-r--r--arch/arm/mach-zynq/include/mach/debug-macro.S2
-rw-r--r--arch/arm/mach-zynq/include/mach/memory.h22
-rw-r--r--arch/arm/mm/Kconfig4
-rw-r--r--arch/arm/mm/alignment.c20
-rw-r--r--arch/arm/mm/cache-l2x0.c262
-rw-r--r--arch/arm/mm/context.c14
-rw-r--r--arch/arm/mm/copypage-v4mc.c6
-rw-r--r--arch/arm/mm/copypage-v6.c10
-rw-r--r--arch/arm/mm/copypage-xscale.c6
-rw-r--r--arch/arm/mm/dma-mapping.c46
-rw-r--r--arch/arm/mm/fault.c1
-rw-r--r--arch/arm/mm/init.c9
-rw-r--r--arch/arm/mm/ioremap.c21
-rw-r--r--arch/arm/mm/mm.h4
-rw-r--r--arch/arm/mm/mmu.c26
-rw-r--r--arch/arm/mm/proc-arm920.S21
-rw-r--r--arch/arm/mm/proc-arm926.S21
-rw-r--r--arch/arm/mm/proc-sa1100.S25
-rw-r--r--arch/arm/mm/proc-v6.S44
-rw-r--r--arch/arm/mm/proc-v7.S52
-rw-r--r--arch/arm/mm/proc-xsc3.S28
-rw-r--r--arch/arm/mm/proc-xscale.S25
-rw-r--r--arch/arm/plat-mxc/Kconfig52
-rw-r--r--arch/arm/plat-mxc/Makefile2
-rw-r--r--arch/arm/plat-mxc/audmux-v2.c18
-rw-r--r--arch/arm/plat-mxc/avic.c91
-rw-r--r--arch/arm/plat-mxc/cpu.c9
-rw-r--r--arch/arm/plat-mxc/devices.c67
-rw-r--r--arch/arm/plat-mxc/devices/Kconfig9
-rw-r--r--arch/arm/plat-mxc/devices/Makefile2
-rw-r--r--arch/arm/plat-mxc/devices/platform-ahci-imx.c156
-rw-r--r--arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c5
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-i2c.c6
-rw-r--r--arch/arm/plat-mxc/devices/platform-mxc-ehci.c9
-rw-r--r--arch/arm/plat-mxc/devices/platform-pata_imx.c59
-rw-r--r--arch/arm/plat-mxc/gic.c48
-rw-r--r--arch/arm/plat-mxc/include/mach/common.h63
-rw-r--r--arch/arm/plat-mxc/include/mach/debug-macro.S42
-rw-r--r--arch/arm/plat-mxc/include/mach/devices-common.h34
-rw-r--r--arch/arm/plat-mxc/include/mach/entry-macro.S64
-rw-r--r--arch/arm/plat-mxc/include/mach/gpio.h40
-rw-r--r--arch/arm/plat-mxc/include/mach/hardware.h19
-rw-r--r--arch/arm/plat-mxc/include/mach/i2c.h4
-rw-r--r--arch/arm/plat-mxc/include/mach/io.h22
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx3.h1
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx51.h2270
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx53.h3530
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-v3.h11
-rw-r--r--arch/arm/plat-mxc/include/mach/irqs.h10
-rw-r--r--arch/arm/plat-mxc/include/mach/memory.h58
-rw-r--r--arch/arm/plat-mxc/include/mach/mx25.h5
-rw-r--r--arch/arm/plat-mxc/include/mach/mx27.h14
-rw-r--r--arch/arm/plat-mxc/include/mach/mx31.h14
-rw-r--r--arch/arm/plat-mxc/include/mach/mx35.h2
-rw-r--r--arch/arm/plat-mxc/include/mach/mx3x.h18
-rw-r--r--arch/arm/plat-mxc/include/mach/mx51.h183
-rw-r--r--arch/arm/plat-mxc/include/mach/mx53.h1
-rw-r--r--arch/arm/plat-mxc/include/mach/mx6q.h33
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc.h7
-rw-r--r--arch/arm/plat-mxc/include/mach/system.h35
-rw-r--r--arch/arm/plat-mxc/irq-common.c21
-rw-r--r--arch/arm/plat-mxc/irq-common.h3
-rw-r--r--arch/arm/plat-mxc/pwm.c2
-rw-r--r--arch/arm/plat-mxc/system.c3
-rw-r--r--arch/arm/plat-mxc/tzic.c32
-rw-r--r--arch/arm/plat-nomadik/Kconfig8
-rw-r--r--arch/arm/plat-nomadik/include/plat/gpio-nomadik.h (renamed from arch/arm/plat-nomadik/include/plat/gpio.h)20
-rw-r--r--arch/arm/plat-nomadik/include/plat/mtu.h47
-rw-r--r--arch/arm/plat-nomadik/include/plat/pincfg.h5
-rw-r--r--arch/arm/plat-nomadik/timer.c138
-rw-r--r--arch/arm/plat-omap/Kconfig14
-rw-r--r--arch/arm/plat-omap/Makefile2
-rw-r--r--arch/arm/plat-omap/debug-devices.c3
-rw-r--r--arch/arm/plat-omap/debug-leds.c3
-rw-r--r--arch/arm/plat-omap/devices.c85
-rw-r--r--arch/arm/plat-omap/dmtimer.c713
-rw-r--r--arch/arm/plat-omap/i2c.c45
-rw-r--r--arch/arm/plat-omap/include/plat/clock.h2
-rw-r--r--arch/arm/plat-omap/include/plat/common.h30
-rw-r--r--arch/arm/plat-omap/include/plat/cpu.h108
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h233
-rw-r--r--arch/arm/plat-omap/include/plat/gpio.h20
-rw-r--r--arch/arm/plat-omap/include/plat/io.h37
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h78
-rw-r--r--arch/arm/plat-omap/include/plat/iommu2.h4
-rw-r--r--arch/arm/plat-omap/include/plat/iopgtable.h (renamed from arch/arm/plat-omap/iopgtable.h)20
-rw-r--r--arch/arm/plat-omap/include/plat/iovmm.h30
-rw-r--r--arch/arm/plat-omap/include/plat/mcbsp.h208
-rw-r--r--arch/arm/plat-omap/include/plat/memory.h102
-rw-r--r--arch/arm/plat-omap/include/plat/mmc.h19
-rw-r--r--arch/arm/plat-omap/include/plat/omap_device.h31
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h3
-rw-r--r--arch/arm/plat-omap/include/plat/serial.h6
-rw-r--r--arch/arm/plat-omap/include/plat/uncompress.h8
-rw-r--r--arch/arm/plat-omap/include/plat/voltage.h20
-rw-r--r--arch/arm/plat-omap/io.c18
-rw-r--r--arch/arm/plat-omap/mcbsp.c385
-rw-r--r--arch/arm/plat-omap/omap_device.c450
-rw-r--r--arch/arm/plat-omap/sram.c85
-rw-r--r--arch/arm/plat-orion/include/plat/gpio.h10
-rw-r--r--arch/arm/plat-pxa/Makefile1
-rw-r--r--arch/arm/plat-pxa/include/plat/gpio-pxa.h44
-rw-r--r--arch/arm/plat-pxa/include/plat/gpio.h40
-rw-r--r--arch/arm/plat-pxa/include/plat/mfp.h2
-rw-r--r--arch/arm/plat-pxa/mfp.c4
-rw-r--r--arch/arm/plat-s3c24xx/cpu.c9
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/map.h100
-rw-r--r--arch/arm/plat-s5p/Kconfig1
-rw-r--r--arch/arm/plat-s5p/cpu.c46
-rw-r--r--arch/arm/plat-s5p/dev-uart.c84
-rw-r--r--arch/arm/plat-s5p/include/plat/exynos4.h5
-rw-r--r--arch/arm/plat-s5p/include/plat/irqs.h35
-rw-r--r--arch/arm/plat-s5p/include/plat/pll.h56
-rw-r--r--arch/arm/plat-s5p/irq.c34
-rw-r--r--arch/arm/plat-samsung/Kconfig12
-rw-r--r--arch/arm/plat-samsung/Makefile3
-rw-r--r--arch/arm/plat-samsung/cpu.c58
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc.c19
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc1.c19
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc2.c19
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc3.c19
-rw-r--r--arch/arm/plat-samsung/dev-ts.c9
-rw-r--r--arch/arm/plat-samsung/include/plat/cpu.h113
-rw-r--r--arch/arm/plat-samsung/include/plat/dma-s3c24xx.h6
-rw-r--r--arch/arm/plat-samsung/include/plat/map-s3c.h84
-rw-r--r--arch/arm/plat-samsung/include/plat/map-s5p.h (renamed from arch/arm/plat-s5p/include/plat/map-s5p.h)6
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-serial.h5
-rw-r--r--arch/arm/plat-samsung/include/plat/sdhci.h7
-rw-r--r--arch/arm/plat-samsung/irq-uart.c96
-rw-r--r--arch/arm/plat-samsung/platformdata.c22
-rw-r--r--arch/arm/plat-spear/include/plat/debug-macro.S2
-rw-r--r--arch/arm/plat-spear/include/plat/gpio.h25
-rw-r--r--arch/arm/plat-spear/include/plat/memory.h20
-rw-r--r--arch/arm/plat-tcc/include/mach/debug-macro.S2
-rw-r--r--arch/arm/plat-tcc/include/mach/memory.h18
-rw-r--r--arch/arm/plat-versatile/platsmp.c2
-rw-r--r--arch/arm/tools/mach-types20
-rw-r--r--arch/arm/vfp/Makefile2
-rw-r--r--arch/arm/vfp/vfpmodule.c31
-rw-r--r--arch/blackfin/Kconfig4
-rw-r--r--arch/blackfin/configs/BF548-EZKIT_defconfig13
-rw-r--r--arch/blackfin/include/asm/Kbuild1
-rw-r--r--arch/blackfin/include/asm/atomic.h104
-rw-r--r--arch/blackfin/include/asm/mutex.h1
-rw-r--r--arch/blackfin/include/asm/uaccess.h6
-rw-r--r--arch/blackfin/kernel/Makefile2
-rw-r--r--arch/blackfin/kernel/kgdb_test.c3
-rw-r--r--arch/blackfin/kernel/time-ts.c6
-rw-r--r--arch/blackfin/kernel/time.c1
-rw-r--r--arch/blackfin/mach-bf533/boards/H8606.c3
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537e.c2
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537u.c2
-rw-r--r--arch/blackfin/mach-bf537/boards/stamp.c88
-rw-r--r--arch/blackfin/mach-bf537/boards/tcm_bf537.c2
-rw-r--r--arch/blackfin/mach-bf561/boards/cm_bf561.c2
-rw-r--r--arch/blackfin/mach-bf561/smp.c2
-rw-r--r--arch/blackfin/mach-common/smp.c7
-rw-r--r--arch/cris/Kconfig4
-rw-r--r--arch/cris/arch-v10/Kconfig12
-rw-r--r--arch/cris/arch-v10/drivers/Kconfig1
-rw-r--r--arch/cris/arch-v10/kernel/kgdb.c6
-rw-r--r--arch/cris/arch-v32/drivers/Kconfig1
-rw-r--r--arch/cris/arch-v32/kernel/kgdb.c14
-rw-r--r--arch/cris/arch-v32/lib/nand_init.S178
-rw-r--r--arch/frv/kernel/gdb-stub.c44
-rw-r--r--arch/h8300/Kconfig4
-rw-r--r--arch/h8300/include/asm/gpio-internal.h (renamed from arch/h8300/include/asm/gpio.h)0
-rw-r--r--arch/h8300/platform/h8300h/irq.c2
-rw-r--r--arch/h8300/platform/h8s/irq.c2
-rw-r--r--arch/hexagon/Kconfig220
-rw-r--r--arch/hexagon/Makefile58
-rw-r--r--arch/hexagon/configs/comet_defconfig85
-rw-r--r--arch/hexagon/include/asm/Kbuild58
-rw-r--r--arch/hexagon/include/asm/asm-offsets.h1
-rw-r--r--arch/hexagon/include/asm/atomic.h164
-rw-r--r--arch/hexagon/include/asm/bitops.h301
-rw-r--r--arch/hexagon/include/asm/bitsperlong.h26
-rw-r--r--arch/hexagon/include/asm/byteorder.h28
-rw-r--r--arch/hexagon/include/asm/cache.h34
-rw-r--r--arch/hexagon/include/asm/cacheflush.h99
-rw-r--r--arch/hexagon/include/asm/checksum.h50
-rw-r--r--arch/hexagon/include/asm/delay.h28
-rw-r--r--arch/hexagon/include/asm/dma-mapping.h101
-rw-r--r--arch/hexagon/include/asm/dma.h (renamed from arch/arm/mach-vt8500/include/mach/memory.h)27
-rw-r--r--arch/hexagon/include/asm/elf.h229
-rw-r--r--arch/hexagon/include/asm/fixmap.h73
-rw-r--r--arch/hexagon/include/asm/fpu.h4
-rw-r--r--arch/hexagon/include/asm/futex.h137
-rw-r--r--arch/hexagon/include/asm/hexagon_vm.h281
-rw-r--r--arch/hexagon/include/asm/intrinsics.h26
-rw-r--r--arch/hexagon/include/asm/io.h326
-rw-r--r--arch/hexagon/include/asm/irq.h36
-rw-r--r--arch/hexagon/include/asm/irqflags.h62
-rw-r--r--arch/hexagon/include/asm/kgdb.h43
-rw-r--r--arch/hexagon/include/asm/linkage.h (renamed from arch/arm/mach-netx/include/mach/memory.h)19
-rw-r--r--arch/hexagon/include/asm/mem-layout.h112
-rw-r--r--arch/hexagon/include/asm/mmu.h37
-rw-r--r--arch/hexagon/include/asm/mmu_context.h100
-rw-r--r--arch/hexagon/include/asm/module.h26
-rw-r--r--arch/hexagon/include/asm/mutex.h8
-rw-r--r--arch/hexagon/include/asm/page.h157
-rw-r--r--arch/hexagon/include/asm/param.h26
-rw-r--r--arch/hexagon/include/asm/perf_event.h24
-rw-r--r--arch/hexagon/include/asm/pgalloc.h146
-rw-r--r--arch/hexagon/include/asm/pgtable.h518
-rw-r--r--arch/hexagon/include/asm/processor.h123
-rw-r--r--arch/hexagon/include/asm/ptrace.h35
-rw-r--r--arch/hexagon/include/asm/registers.h236
-rw-r--r--arch/hexagon/include/asm/setup.h29
-rw-r--r--arch/hexagon/include/asm/sigcontext.h33
-rw-r--r--arch/hexagon/include/asm/signal.h26
-rw-r--r--arch/hexagon/include/asm/smp.h44
-rw-r--r--arch/hexagon/include/asm/spinlock.h186
-rw-r--r--arch/hexagon/include/asm/spinlock_types.h42
-rw-r--r--arch/hexagon/include/asm/string.h32
-rw-r--r--arch/hexagon/include/asm/suspend.h27
-rw-r--r--arch/hexagon/include/asm/swab.h24
-rw-r--r--arch/hexagon/include/asm/syscall.h54
-rw-r--r--arch/hexagon/include/asm/system.h126
-rw-r--r--arch/hexagon/include/asm/thread_info.h154
-rw-r--r--arch/hexagon/include/asm/time.h29
-rw-r--r--arch/hexagon/include/asm/timer-regs.h39
-rw-r--r--arch/hexagon/include/asm/timex.h36
-rw-r--r--arch/hexagon/include/asm/tlb.h39
-rw-r--r--arch/hexagon/include/asm/tlbflush.h58
-rw-r--r--arch/hexagon/include/asm/traps.h29
-rw-r--r--arch/hexagon/include/asm/uaccess.h116
-rw-r--r--arch/hexagon/include/asm/unistd.h36
-rw-r--r--arch/hexagon/include/asm/user.h81
-rw-r--r--arch/hexagon/include/asm/vdso.h30
-rw-r--r--arch/hexagon/include/asm/vm_fault.h26
-rw-r--r--arch/hexagon/include/asm/vm_mmu.h111
-rw-r--r--arch/hexagon/kernel/Makefile18
-rw-r--r--arch/hexagon/kernel/asm-offsets.c104
-rw-r--r--arch/hexagon/kernel/dma.c220
-rw-r--r--arch/hexagon/kernel/head.S162
-rw-r--r--arch/hexagon/kernel/hexagon_ksyms.c40
-rw-r--r--arch/hexagon/kernel/init_task.c54
-rw-r--r--arch/hexagon/kernel/irq_cpu.c90
-rw-r--r--arch/hexagon/kernel/kgdb.c254
-rw-r--r--arch/hexagon/kernel/module.c162
-rw-r--r--arch/hexagon/kernel/process.c279
-rw-r--r--arch/hexagon/kernel/ptrace.c180
-rw-r--r--arch/hexagon/kernel/reset.c38
-rw-r--r--arch/hexagon/kernel/setup.c145
-rw-r--r--arch/hexagon/kernel/signal.c345
-rw-r--r--arch/hexagon/kernel/smp.c276
-rw-r--r--arch/hexagon/kernel/stacktrace.c66
-rw-r--r--arch/hexagon/kernel/syscall.c90
-rw-r--r--arch/hexagon/kernel/syscalltab.c32
-rw-r--r--arch/hexagon/kernel/time.c250
-rw-r--r--arch/hexagon/kernel/topology.c52
-rw-r--r--arch/hexagon/kernel/trampoline.S35
-rw-r--r--arch/hexagon/kernel/traps.c454
-rw-r--r--arch/hexagon/kernel/vdso.c100
-rw-r--r--arch/hexagon/kernel/vm_entry.S269
-rw-r--r--arch/hexagon/kernel/vm_events.c101
-rw-r--r--arch/hexagon/kernel/vm_init_segtable.S442
-rw-r--r--arch/hexagon/kernel/vm_ops.S102
-rw-r--r--arch/hexagon/kernel/vm_switch.S95
-rw-r--r--arch/hexagon/kernel/vm_vectors.S48
-rw-r--r--arch/hexagon/kernel/vmlinux.lds.S88
-rw-r--r--arch/hexagon/lib/Makefile4
-rw-r--r--arch/hexagon/lib/checksum.c203
-rw-r--r--arch/hexagon/lib/io.c91
-rw-r--r--arch/hexagon/lib/memcpy.S543
-rw-r--r--arch/hexagon/lib/memset.S315
-rw-r--r--arch/hexagon/mm/Makefile6
-rw-r--r--arch/hexagon/mm/cache.c128
-rw-r--r--arch/hexagon/mm/copy_from_user.S114
-rw-r--r--arch/hexagon/mm/copy_to_user.S92
-rw-r--r--arch/hexagon/mm/copy_user_template.S185
-rw-r--r--arch/hexagon/mm/init.c276
-rw-r--r--arch/hexagon/mm/ioremap.c56
-rw-r--r--arch/hexagon/mm/pgalloc.c23
-rw-r--r--arch/hexagon/mm/strnlen_user.S139
-rw-r--r--arch/hexagon/mm/uaccess.c59
-rw-r--r--arch/hexagon/mm/vm_fault.c187
-rw-r--r--arch/hexagon/mm/vm_tlb.c93
-rw-r--r--arch/ia64/Kconfig2
-rw-r--r--arch/ia64/configs/generic_defconfig3
-rw-r--r--arch/ia64/configs/gensparse_defconfig1
-rw-r--r--arch/ia64/configs/tiger_defconfig1
-rw-r--r--arch/ia64/configs/xen_domu_defconfig1
-rw-r--r--arch/ia64/configs/zx1_defconfig1
-rw-r--r--arch/ia64/dig/Makefile2
-rw-r--r--arch/ia64/hp/common/sba_iommu.c12
-rw-r--r--arch/ia64/hp/sim/simeth.c2
-rw-r--r--arch/ia64/include/asm/device.h2
-rw-r--r--arch/ia64/include/asm/iommu.h6
-rw-r--r--arch/ia64/include/asm/pci.h2
-rw-r--r--arch/ia64/kernel/Makefile2
-rw-r--r--arch/ia64/kernel/acpi.c4
-rw-r--r--arch/ia64/kernel/msi_ia64.c4
-rw-r--r--arch/ia64/kernel/pci-dma.c2
-rw-r--r--arch/ia64/kvm/kvm-ia64.c3
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c12
-rw-r--r--arch/m32r/Kconfig1
-rw-r--r--arch/m68k/Kconfig195
-rw-r--r--arch/m68k/Kconfig.bus55
-rw-r--r--arch/m68k/Kconfig.cpu429
-rw-r--r--arch/m68k/Kconfig.devices123
-rw-r--r--arch/m68k/Kconfig.machine (renamed from arch/m68k/Kconfig.nommu)562
-rw-r--r--arch/m68k/Kconfig.mmu411
-rw-r--r--arch/m68k/Makefile168
-rw-r--r--arch/m68k/Makefile_mm121
-rw-r--r--arch/m68k/Makefile_no124
-rw-r--r--arch/m68k/include/asm/entry.h255
-rw-r--r--arch/m68k/include/asm/entry_mm.h128
-rw-r--r--arch/m68k/include/asm/entry_no.h181
-rw-r--r--arch/m68k/include/asm/m520xsim.h26
-rw-r--r--arch/m68k/include/asm/mcfqspi.h8
-rw-r--r--arch/m68k/include/asm/page_no.h3
-rw-r--r--arch/m68k/include/asm/processor.h6
-rw-r--r--arch/m68k/include/asm/sections.h2
-rw-r--r--arch/m68k/kernel/Makefile24
-rw-r--r--arch/m68k/kernel/Makefile_mm17
-rw-r--r--arch/m68k/kernel/Makefile_no10
-rw-r--r--arch/m68k/kernel/entry_no.S6
-rw-r--r--arch/m68k/kernel/setup_no.c4
-rw-r--r--arch/m68k/kernel/traps.c1108
-rw-r--r--arch/m68k/kernel/traps_mm.c1207
-rw-r--r--arch/m68k/kernel/traps_no.c361
-rw-r--r--arch/m68k/kernel/vectors.c145
-rw-r--r--arch/m68k/kernel/vmlinux.lds_no.S1
-rw-r--r--arch/m68k/lib/memcpy.c9
-rw-r--r--arch/m68k/mac/macints.c2
-rw-r--r--arch/m68k/mac/misc.c40
-rw-r--r--arch/m68k/mm/init_no.c21
-rw-r--r--arch/m68k/platform/520x/config.c6
-rw-r--r--arch/m68k/platform/520x/gpio.c50
-rw-r--r--arch/m68k/platform/68328/Makefile5
-rw-r--r--arch/m68k/platform/68328/entry.S18
-rw-r--r--arch/m68k/platform/68360/Makefile6
-rw-r--r--arch/m68k/platform/68360/entry.S4
-rw-r--r--arch/m68k/platform/coldfire/entry.S6
-rw-r--r--arch/m68k/q40/README2
-rw-r--r--arch/microblaze/include/asm/dma-mapping.h22
-rw-r--r--arch/microblaze/include/asm/elf.h8
-rw-r--r--arch/microblaze/include/asm/system.h9
-rw-r--r--arch/microblaze/include/asm/uaccess.h2
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo.c1
-rw-r--r--arch/microblaze/kernel/dma.c82
-rw-r--r--arch/microblaze/kernel/exceptions.c2
-rw-r--r--arch/microblaze/kernel/process.c1
-rw-r--r--arch/microblaze/kernel/ptrace.c2
-rw-r--r--arch/microblaze/kernel/timer.c3
-rw-r--r--arch/microblaze/lib/Makefile1
-rw-r--r--arch/microblaze/lib/uaccess_old.S123
-rw-r--r--arch/microblaze/lib/ucmpdi2.c20
-rw-r--r--arch/microblaze/mm/init.c6
-rw-r--r--arch/mips/Kconfig8
-rw-r--r--arch/mips/alchemy/devboards/db1200/platform.c16
-rw-r--r--arch/mips/alchemy/devboards/db1x00/platform.c48
-rw-r--r--arch/mips/bcm47xx/Kconfig31
-rw-r--r--arch/mips/bcm47xx/Makefile3
-rw-r--r--arch/mips/bcm47xx/gpio.c82
-rw-r--r--arch/mips/bcm47xx/irq.c12
-rw-r--r--arch/mips/bcm47xx/nvram.c29
-rw-r--r--arch/mips/bcm47xx/serial.c46
-rw-r--r--arch/mips/bcm47xx/setup.c90
-rw-r--r--arch/mips/bcm47xx/time.c16
-rw-r--r--arch/mips/bcm47xx/wgt634u.c14
-rw-r--r--arch/mips/include/asm/compat.h3
-rw-r--r--arch/mips/include/asm/lasat/lasat.h6
-rw-r--r--arch/mips/include/asm/mach-au1x00/au1xxx_psc.h13
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/bcm47xx.h26
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/gpio.h108
-rw-r--r--arch/mips/pci/pci-bcm47xx.c6
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_serial.c73
-rw-r--r--arch/mips/txx9/generic/setup_tx4939.c2
-rw-r--r--arch/mn10300/Kconfig5
-rw-r--r--arch/mn10300/kernel/gdb-stub.c52
-rw-r--r--arch/mn10300/kernel/irq.c1
-rw-r--r--arch/openrisc/Kconfig2
-rw-r--r--arch/openrisc/include/asm/dma-mapping.h2
-rw-r--r--arch/parisc/Kconfig4
-rw-r--r--arch/parisc/include/asm/compat.h3
-rw-r--r--arch/parisc/include/asm/dma-mapping.h2
-rw-r--r--arch/parisc/kernel/pci-dma.c2
-rw-r--r--arch/powerpc/Kconfig2
-rw-r--r--arch/powerpc/boot/dts/p1010rdb.dts10
-rw-r--r--arch/powerpc/boot/dts/p1010si.dtsi10
-rw-r--r--arch/powerpc/configs/40x/acadia_defconfig11
-rw-r--r--arch/powerpc/configs/40x/ep405_defconfig5
-rw-r--r--arch/powerpc/configs/40x/hcu4_defconfig5
-rw-r--r--arch/powerpc/configs/40x/kilauea_defconfig9
-rw-r--r--arch/powerpc/configs/40x/makalu_defconfig9
-rw-r--r--arch/powerpc/configs/40x/walnut_defconfig5
-rw-r--r--arch/powerpc/configs/44x/arches_defconfig9
-rw-r--r--arch/powerpc/configs/44x/bamboo_defconfig5
-rw-r--r--arch/powerpc/configs/44x/bluestone_defconfig9
-rw-r--r--arch/powerpc/configs/44x/canyonlands_defconfig9
-rw-r--r--arch/powerpc/configs/44x/ebony_defconfig5
-rw-r--r--arch/powerpc/configs/44x/eiger_defconfig9
-rw-r--r--arch/powerpc/configs/44x/icon_defconfig5
-rw-r--r--arch/powerpc/configs/44x/katmai_defconfig5
-rw-r--r--arch/powerpc/configs/44x/redwood_defconfig11
-rw-r--r--arch/powerpc/configs/44x/sam440ep_defconfig5
-rw-r--r--arch/powerpc/configs/44x/sequoia_defconfig5
-rw-r--r--arch/powerpc/configs/44x/taishan_defconfig5
-rw-r--r--arch/powerpc/configs/44x/warp_defconfig5
-rw-r--r--arch/powerpc/configs/ppc40x_defconfig5
-rw-r--r--arch/powerpc/configs/ppc44x_defconfig5
-rw-r--r--arch/powerpc/include/asm/compat.h3
-rw-r--r--arch/powerpc/include/asm/kvm.h13
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h40
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_asm.h2
-rw-r--r--arch/powerpc/include/asm/kvm_host.h30
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h1
-rw-r--r--arch/powerpc/include/asm/qe.h2
-rw-r--r--arch/powerpc/include/asm/systbl.h2
-rw-r--r--arch/powerpc/include/asm/udbg.h1
-rw-r--r--arch/powerpc/include/asm/unistd.h4
-rw-r--r--arch/powerpc/kernel/asm-offsets.c13
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S10
-rw-r--r--arch/powerpc/kernel/udbg.c2
-rw-r--r--arch/powerpc/kvm/44x.c2
-rw-r--r--arch/powerpc/kvm/Makefile4
-rw-r--r--arch/powerpc/kvm/book3s_32_sr.S2
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu.c8
-rw-r--r--arch/powerpc/kvm/book3s_64_slb.S2
-rw-r--r--arch/powerpc/kvm/book3s_emulate.c29
-rw-r--r--arch/powerpc/kvm/book3s_exports.c4
-rw-r--r--arch/powerpc/kvm/book3s_hv.c343
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_mmu.c33
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S300
-rw-r--r--arch/powerpc/kvm/book3s_interrupts.S129
-rw-r--r--arch/powerpc/kvm/book3s_pr.c58
-rw-r--r--arch/powerpc/kvm/book3s_pr_papr.c158
-rw-r--r--arch/powerpc/kvm/book3s_rmhandlers.S54
-rw-r--r--arch/powerpc/kvm/book3s_segment.S117
-rw-r--r--arch/powerpc/kvm/booke.c10
-rw-r--r--arch/powerpc/kvm/e500.c2
-rw-r--r--arch/powerpc/kvm/powerpc.c55
-rw-r--r--arch/powerpc/mm/gup.c12
-rw-r--r--arch/powerpc/mm/hugetlbpage.c21
-rw-r--r--arch/powerpc/platforms/40x/Kconfig12
-rw-r--r--arch/powerpc/platforms/44x/Kconfig54
-rw-r--r--arch/powerpc/platforms/512x/mpc512x_shared.c24
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/85xx/p1022_ds.c47
-rw-r--r--arch/powerpc/platforms/86xx/mpc8610_hpcd.c55
-rw-r--r--arch/powerpc/platforms/cell/Kconfig8
-rw-r--r--arch/powerpc/platforms/embedded6xx/storcenter.c2
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c1
-rw-r--r--arch/powerpc/sysdev/fsl_soc.h25
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c2
-rw-r--r--arch/powerpc/sysdev/uic.c24
-rw-r--r--arch/s390/Kconfig11
-rw-r--r--arch/s390/boot/compressed/misc.c2
-rw-r--r--arch/s390/defconfig2
-rw-r--r--arch/s390/hypfs/hypfs_diag.c3
-rw-r--r--arch/s390/hypfs/inode.c6
-rw-r--r--arch/s390/include/asm/ccwdev.h3
-rw-r--r--arch/s390/include/asm/compat.h16
-rw-r--r--arch/s390/include/asm/ipl.h1
-rw-r--r--arch/s390/include/asm/irq.h6
-rw-r--r--arch/s390/include/asm/kexec.h6
-rw-r--r--arch/s390/include/asm/kvm_host.h8
-rw-r--r--arch/s390/include/asm/lowcore.h10
-rw-r--r--arch/s390/include/asm/page.h1
-rw-r--r--arch/s390/include/asm/pgtable.h2
-rw-r--r--arch/s390/include/asm/processor.h48
-rw-r--r--arch/s390/include/asm/ptrace.h29
-rw-r--r--arch/s390/include/asm/qdio.h83
-rw-r--r--arch/s390/include/asm/reset.h2
-rw-r--r--arch/s390/include/asm/setup.h13
-rw-r--r--arch/s390/include/asm/sfp-util.h2
-rw-r--r--arch/s390/include/asm/smp.h5
-rw-r--r--arch/s390/include/asm/spinlock.h2
-rw-r--r--arch/s390/include/asm/syscall.h6
-rw-r--r--arch/s390/include/asm/system.h10
-rw-r--r--arch/s390/include/asm/thread_info.h7
-rw-r--r--arch/s390/include/asm/timex.h11
-rw-r--r--arch/s390/include/asm/tlbflush.h1
-rw-r--r--arch/s390/kernel/Makefile1
-rw-r--r--arch/s390/kernel/asm-offsets.c4
-rw-r--r--arch/s390/kernel/base.S6
-rw-r--r--arch/s390/kernel/compat_linux.c32
-rw-r--r--arch/s390/kernel/compat_signal.c71
-rw-r--r--arch/s390/kernel/compat_wrapper.S3
-rw-r--r--arch/s390/kernel/crash_dump.c426
-rw-r--r--arch/s390/kernel/early.c2
-rw-r--r--arch/s390/kernel/entry.S84
-rw-r--r--arch/s390/kernel/entry.h13
-rw-r--r--arch/s390/kernel/entry64.S86
-rw-r--r--arch/s390/kernel/head.S22
-rw-r--r--arch/s390/kernel/head31.S2
-rw-r--r--arch/s390/kernel/head64.S2
-rw-r--r--arch/s390/kernel/head_kdump.S119
-rw-r--r--arch/s390/kernel/ipl.c26
-rw-r--r--arch/s390/kernel/irq.c6
-rw-r--r--arch/s390/kernel/kprobes.c2
-rw-r--r--arch/s390/kernel/machine_kexec.c192
-rw-r--r--arch/s390/kernel/mem_detect.c69
-rw-r--r--arch/s390/kernel/process.c4
-rw-r--r--arch/s390/kernel/processor.c2
-rw-r--r--arch/s390/kernel/ptrace.c124
-rw-r--r--arch/s390/kernel/reipl.S6
-rw-r--r--arch/s390/kernel/reipl64.S9
-rw-r--r--arch/s390/kernel/setup.c275
-rw-r--r--arch/s390/kernel/signal.c128
-rw-r--r--arch/s390/kernel/smp.c73
-rw-r--r--arch/s390/kernel/suspend.c119
-rw-r--r--arch/s390/kernel/swsusp_asm64.S3
-rw-r--r--arch/s390/kernel/sysinfo.c2
-rw-r--r--arch/s390/kernel/time.c14
-rw-r--r--arch/s390/kernel/topology.c4
-rw-r--r--arch/s390/kernel/traps.c5
-rw-r--r--arch/s390/kernel/vtime.c11
-rw-r--r--arch/s390/kvm/diag.c32
-rw-r--r--arch/s390/kvm/interrupt.c30
-rw-r--r--arch/s390/kvm/kvm-s390.c21
-rw-r--r--arch/s390/kvm/sigp.c45
-rw-r--r--arch/s390/lib/delay.c3
-rw-r--r--arch/s390/lib/uaccess_pt.c6
-rw-r--r--arch/s390/mm/fault.c6
-rw-r--r--arch/s390/mm/gup.c14
-rw-r--r--arch/s390/mm/maccess.c56
-rw-r--r--arch/s390/mm/mmap.c1
-rw-r--r--arch/s390/mm/pageattr.c1
-rw-r--r--arch/s390/mm/pgtable.c83
-rw-r--r--arch/s390/mm/vmem.c6
-rw-r--r--arch/s390/oprofile/hwsampler.c8
-rw-r--r--arch/sh/Kconfig17
-rw-r--r--arch/sh/Makefile1
-rw-r--r--arch/sh/boards/board-espt.c2
-rw-r--r--arch/sh/boards/board-secureedge5410.c3
-rw-r--r--arch/sh/boards/board-sh7757lcr.c2
-rw-r--r--arch/sh/boards/mach-cayman/irq.c2
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c6
-rw-r--r--arch/sh/boards/mach-hp6xx/hp6xx_apm.c2
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c2
-rw-r--r--arch/sh/boards/mach-sh7763rdp/setup.c2
-rw-r--r--arch/sh/boot/Makefile6
-rw-r--r--arch/sh/drivers/dma/dma-g2.c2
-rw-r--r--arch/sh/drivers/dma/dma-pvr2.c1
-rw-r--r--arch/sh/drivers/dma/dma-sh.c4
-rw-r--r--arch/sh/drivers/dma/dmabrg.c6
-rw-r--r--arch/sh/drivers/pci/pci-sh5.c4
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.c2
-rw-r--r--arch/sh/drivers/push-switch.c2
-rw-r--r--arch/sh/include/asm/page.h10
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7757.c10
-rw-r--r--arch/sh/kernel/cpu/sh4a/smp-shx3.c2
-rw-r--r--arch/sh/kernel/setup.c9
-rw-r--r--arch/sh/kernel/topology.c1
-rw-r--r--arch/sh/kernel/vmlinux.lds.S2
-rw-r--r--arch/sh/mm/init.c8
-rw-r--r--arch/sparc/include/asm/compat.h3
-rw-r--r--arch/sparc/kernel/visemul.c32
-rw-r--r--arch/sparc/lib/memcpy.S804
-rw-r--r--arch/sparc/mm/gup.c2
-rw-r--r--arch/tile/Kconfig3
-rw-r--r--arch/tile/configs/tilegx_defconfig1
-rw-r--r--arch/tile/configs/tilepro_defconfig1
-rw-r--r--arch/um/Kconfig.char114
-rw-r--r--arch/um/Kconfig.rest23
-rw-r--r--arch/um/Kconfig.um6
-rw-r--r--arch/um/Makefile49
-rw-r--r--arch/um/Makefile-x86_6426
-rw-r--r--arch/um/defconfig1
-rw-r--r--arch/um/drivers/chan.h (renamed from arch/um/include/shared/chan_kern.h)6
-rw-r--r--arch/um/drivers/chan_kern.c12
-rw-r--r--arch/um/drivers/chan_user.c9
-rw-r--r--arch/um/drivers/chan_user.h (renamed from arch/um/include/shared/chan_user.h)0
-rw-r--r--arch/um/drivers/cow_sys.h1
-rw-r--r--arch/um/drivers/daemon_user.c1
-rw-r--r--arch/um/drivers/fd.c2
-rw-r--r--arch/um/drivers/harddog_user.c1
-rw-r--r--arch/um/drivers/line.c2
-rw-r--r--arch/um/drivers/line.h (renamed from arch/um/include/shared/line.h)0
-rw-r--r--arch/um/drivers/mconsole.h (renamed from arch/um/include/shared/mconsole.h)0
-rw-r--r--arch/um/drivers/mconsole_kern.h (renamed from arch/um/include/shared/mconsole_kern.h)0
-rw-r--r--arch/um/drivers/mconsole_user.c2
-rw-r--r--arch/um/drivers/net_kern.c2
-rw-r--r--arch/um/drivers/net_user.c2
-rw-r--r--arch/um/drivers/pcap_user.c2
-rw-r--r--arch/um/drivers/port_user.c2
-rw-r--r--arch/um/drivers/pty.c2
-rw-r--r--arch/um/drivers/slip_user.c2
-rw-r--r--arch/um/drivers/slirp_user.c2
-rw-r--r--arch/um/drivers/ssl.c4
-rw-r--r--arch/um/drivers/stdio_console.c3
-rw-r--r--arch/um/drivers/tty.c2
-rw-r--r--arch/um/drivers/ubd_kern.c33
-rw-r--r--arch/um/drivers/ubd_user.c1
-rw-r--r--arch/um/drivers/ubd_user.h (renamed from arch/um/include/shared/ubd_user.h)0
-rw-r--r--arch/um/drivers/umcast_user.c2
-rw-r--r--arch/um/drivers/vde_user.c2
-rw-r--r--arch/um/drivers/xterm.c2
-rw-r--r--arch/um/include/asm/Kbuild3
-rw-r--r--arch/um/include/asm/bug.h6
-rw-r--r--arch/um/include/asm/checksum.h6
-rw-r--r--arch/um/include/asm/cputime.h6
-rw-r--r--arch/um/include/asm/device.h7
-rw-r--r--arch/um/include/asm/emergency-restart.h6
-rw-r--r--arch/um/include/asm/futex.h6
-rw-r--r--arch/um/include/asm/hardirq.h1
-rw-r--r--arch/um/include/asm/hw_irq.h7
-rw-r--r--arch/um/include/asm/irq_regs.h1
-rw-r--r--arch/um/include/asm/irqflags.h38
-rw-r--r--arch/um/include/asm/kdebug.h1
-rw-r--r--arch/um/include/asm/mmu.h22
-rw-r--r--arch/um/include/asm/mmu_context.h7
-rw-r--r--arch/um/include/asm/page.h2
-rw-r--r--arch/um/include/asm/page_offset.h1
-rw-r--r--arch/um/include/asm/pda.h21
-rw-r--r--arch/um/include/asm/percpu.h6
-rw-r--r--arch/um/include/asm/ptrace-generic.h7
-rw-r--r--arch/um/include/asm/sections.h7
-rw-r--r--arch/um/include/asm/system.h47
-rw-r--r--arch/um/include/asm/topology.h6
-rw-r--r--arch/um/include/asm/uaccess.h89
-rw-r--r--arch/um/include/asm/xor.h6
-rw-r--r--arch/um/include/shared/as-layout.h2
-rw-r--r--arch/um/include/shared/common-offsets.h1
-rw-r--r--arch/um/include/shared/initrd.h12
-rw-r--r--arch/um/include/shared/kern.h18
-rw-r--r--arch/um/include/shared/kern_util.h1
-rw-r--r--arch/um/include/shared/ldt.h37
-rw-r--r--arch/um/include/shared/mem_kern.h20
-rw-r--r--arch/um/include/shared/os.h13
-rw-r--r--arch/um/include/shared/process.h17
-rw-r--r--arch/um/include/shared/ptrace_user.h3
-rw-r--r--arch/um/include/shared/skas_ptregs.h6
-rw-r--r--arch/um/include/shared/syscall.h12
-rw-r--r--arch/um/include/shared/task.h9
-rw-r--r--arch/um/include/shared/tlb.h15
-rw-r--r--arch/um/include/shared/um_malloc.h2
-rw-r--r--arch/um/include/shared/um_mmu.h24
-rw-r--r--arch/um/include/shared/um_uaccess.h97
-rw-r--r--arch/um/include/shared/user.h7
-rw-r--r--arch/um/kernel/Makefile2
-rw-r--r--arch/um/kernel/exec.c18
-rw-r--r--arch/um/kernel/gmon_syms.c15
-rw-r--r--arch/um/kernel/initrd.c4
-rw-r--r--arch/um/kernel/irq.c1
-rw-r--r--arch/um/kernel/ksyms.c38
-rw-r--r--arch/um/kernel/mem.c2
-rw-r--r--arch/um/kernel/physmem.c21
-rw-r--r--arch/um/kernel/process.c4
-rw-r--r--arch/um/kernel/signal.c1
-rw-r--r--arch/um/kernel/skas/clone.c1
-rw-r--r--arch/um/kernel/skas/uaccess.c6
-rw-r--r--arch/um/kernel/tlb.c5
-rw-r--r--arch/um/kernel/trap.c3
-rw-r--r--arch/um/kernel/uaccess.c33
-rw-r--r--arch/um/kernel/um_arch.c2
-rw-r--r--arch/um/os-Linux/Makefile6
-rw-r--r--arch/um/os-Linux/aio.c2
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c2
-rw-r--r--arch/um/os-Linux/elf_aux.c1
-rw-r--r--arch/um/os-Linux/file.c2
-rw-r--r--arch/um/os-Linux/helper.c2
-rw-r--r--arch/um/os-Linux/internal.h1
-rw-r--r--arch/um/os-Linux/irq.c3
-rw-r--r--arch/um/os-Linux/main.c1
-rw-r--r--arch/um/os-Linux/mem.c2
-rw-r--r--arch/um/os-Linux/process.c23
-rw-r--r--arch/um/os-Linux/sigio.c3
-rw-r--r--arch/um/os-Linux/signal.c72
-rw-r--r--arch/um/os-Linux/skas/mem.c2
-rw-r--r--arch/um/os-Linux/skas/process.c21
-rw-r--r--arch/um/os-Linux/start_up.c10
-rw-r--r--arch/um/os-Linux/sys-i386/signal.c13
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile10
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c52
-rw-r--r--arch/um/os-Linux/sys-x86_64/signal.c16
-rw-r--r--arch/um/os-Linux/sys-x86_64/task_size.c5
-rw-r--r--arch/um/os-Linux/time.c4
-rw-r--r--arch/um/os-Linux/tls.c35
-rw-r--r--arch/um/os-Linux/tty.c2
-rw-r--r--arch/um/os-Linux/uaccess.c32
-rw-r--r--arch/um/os-Linux/umid.c2
-rw-r--r--arch/um/os-Linux/util.c2
-rw-r--r--arch/um/scripts/Makefile.rules7
-rw-r--r--arch/um/sys-i386/Makefile24
-rw-r--r--arch/um/sys-i386/asm/elf.h125
-rw-r--r--arch/um/sys-i386/asm/module.h13
-rw-r--r--arch/um/sys-i386/atomic64_cx8_32.S225
-rw-r--r--arch/um/sys-i386/bug.c21
-rw-r--r--arch/um/sys-i386/ksyms.c5
-rw-r--r--arch/um/sys-i386/shared/sysdep/barrier.h9
-rw-r--r--arch/um/sys-i386/shared/sysdep/host_ldt.h34
-rw-r--r--arch/um/sys-i386/shared/sysdep/ptrace_user.h50
-rw-r--r--arch/um/sys-i386/shared/sysdep/sc.h44
-rw-r--r--arch/um/sys-i386/shared/sysdep/sigcontext.h26
-rw-r--r--arch/um/sys-i386/shared/sysdep/system.h132
-rw-r--r--arch/um/sys-i386/shared/sysdep/vm-flags.h14
-rw-r--r--arch/um/sys-i386/stub_segv.c17
-rw-r--r--arch/um/sys-i386/user-offsets.c53
-rw-r--r--arch/um/sys-x86_64/Makefile27
-rw-r--r--arch/um/sys-x86_64/asm/archparam.h16
-rw-r--r--arch/um/sys-x86_64/asm/module.h20
-rw-r--r--arch/um/sys-x86_64/delay.c60
-rw-r--r--arch/um/sys-x86_64/fault.c28
-rw-r--r--arch/um/sys-x86_64/ptrace_user.c22
-rw-r--r--arch/um/sys-x86_64/shared/sysdep/barrier.h7
-rw-r--r--arch/um/sys-x86_64/shared/sysdep/host_ldt.h38
-rw-r--r--arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h23
-rw-r--r--arch/um/sys-x86_64/shared/sysdep/ptrace_user.h77
-rw-r--r--arch/um/sys-x86_64/shared/sysdep/sc.h45
-rw-r--r--arch/um/sys-x86_64/shared/sysdep/sigcontext.h27
-rw-r--r--arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h22
-rw-r--r--arch/um/sys-x86_64/shared/sysdep/tls.h29
-rw-r--r--arch/um/sys-x86_64/signal.c290
-rw-r--r--arch/unicore32/include/asm/io.h2
-rw-r--r--arch/x86/Kconfig33
-rw-r--r--arch/x86/Kconfig.debug2
-rw-r--r--arch/x86/Makefile.um (renamed from arch/um/Makefile-i386)37
-rw-r--r--arch/x86/boot/header.S2
-rw-r--r--arch/x86/configs/x86_64_defconfig4
-rw-r--r--arch/x86/crypto/Makefile12
-rw-r--r--arch/x86/crypto/aes_glue.c1
-rw-r--r--arch/x86/crypto/blowfish-x86_64-asm_64.S390
-rw-r--r--arch/x86/crypto/blowfish_glue.c492
-rw-r--r--arch/x86/crypto/sha1_ssse3_asm.S558
-rw-r--r--arch/x86/crypto/sha1_ssse3_glue.c240
-rw-r--r--arch/x86/crypto/twofish-i586-asm_32.S10
-rw-r--r--arch/x86/crypto/twofish-x86_64-asm_64-3way.S316
-rw-r--r--arch/x86/crypto/twofish-x86_64-asm_64.S6
-rw-r--r--arch/x86/crypto/twofish_glue.c12
-rw-r--r--arch/x86/crypto/twofish_glue_3way.c472
-rw-r--r--arch/x86/ia32/ia32entry.S2
-rw-r--r--arch/x86/include/asm/amd_nb.h6
-rw-r--r--arch/x86/include/asm/apic.h2
-rw-r--r--arch/x86/include/asm/apicdef.h2
-rw-r--r--arch/x86/include/asm/archrandom.h75
-rw-r--r--arch/x86/include/asm/atomic.h8
-rw-r--r--arch/x86/include/asm/atomic64_64.h6
-rw-r--r--arch/x86/include/asm/cmpxchg.h205
-rw-r--r--arch/x86/include/asm/cmpxchg_32.h114
-rw-r--r--arch/x86/include/asm/cmpxchg_64.h131
-rw-r--r--arch/x86/include/asm/compat.h3
-rw-r--r--arch/x86/include/asm/cpufeature.h5
-rw-r--r--arch/x86/include/asm/device.h2
-rw-r--r--arch/x86/include/asm/dma-mapping.h2
-rw-r--r--arch/x86/include/asm/dwarf2.h2
-rw-r--r--arch/x86/include/asm/elf.h31
-rw-r--r--arch/x86/include/asm/hw_irq.h2
-rw-r--r--arch/x86/include/asm/hyperv.h1
-rw-r--r--arch/x86/include/asm/irq_remapping.h6
-rw-r--r--arch/x86/include/asm/irq_vectors.h12
-rw-r--r--arch/x86/include/asm/kvm_emulate.h4
-rw-r--r--arch/x86/include/asm/kvm_host.h14
-rw-r--r--arch/x86/include/asm/msr-index.h2
-rw-r--r--arch/x86/include/asm/nmi.h37
-rw-r--r--arch/x86/include/asm/pci_x86.h6
-rw-r--r--arch/x86/include/asm/perf_event.h55
-rw-r--r--arch/x86/include/asm/processor.h4
-rw-r--r--arch/x86/include/asm/reboot.h2
-rw-r--r--arch/x86/include/asm/rwsem.h8
-rw-r--r--arch/x86/include/asm/spinlock.h114
-rw-r--r--arch/x86/include/asm/spinlock_types.h22
-rw-r--r--arch/x86/include/asm/unistd_32.h4
-rw-r--r--arch/x86/include/asm/unistd_64.h5
-rw-r--r--arch/x86/include/asm/uv/uv_bau.h7
-rw-r--r--arch/x86/include/asm/uv/uv_hub.h37
-rw-r--r--arch/x86/include/asm/vmx.h12
-rw-r--r--arch/x86/include/asm/xen/page.h6
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/amd_gart_64.c2
-rw-r--r--arch/x86/kernel/apic/apic.c33
-rw-r--r--arch/x86/kernel/apic/bigsmp_32.c20
-rw-r--r--arch/x86/kernel/apic/hw_nmi.c27
-rw-r--r--arch/x86/kernel/apic/io_apic.c678
-rw-r--r--arch/x86/kernel/apic/probe_32.c10
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c27
-rw-r--r--arch/x86/kernel/apm_32.c2
-rw-r--r--arch/x86/kernel/cpu/Makefile8
-rw-r--r--arch/x86/kernel/cpu/amd.c49
-rw-r--r--arch/x86/kernel/cpu/common.c5
-rw-r--r--arch/x86/kernel/cpu/cpu.h1
-rw-r--r--arch/x86/kernel/cpu/intel.c24
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c127
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-inject.c20
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c50
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel.c10
-rw-r--r--arch/x86/kernel/cpu/mshyperv.c23
-rw-r--r--arch/x86/kernel/cpu/perf_event.c442
-rw-r--r--arch/x86/kernel/cpu/perf_event.h505
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd.c38
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd_ibs.c294
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c146
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c79
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_lbr.c28
-rw-r--r--arch/x86/kernel/cpu/perf_event_p4.c10
-rw-r--r--arch/x86/kernel/cpu/perf_event_p6.c9
-rw-r--r--arch/x86/kernel/cpu/proc.c2
-rw-r--r--arch/x86/kernel/cpu/rdrand.c73
-rw-r--r--arch/x86/kernel/crash.c5
-rw-r--r--arch/x86/kernel/entry_64.S14
-rw-r--r--arch/x86/kernel/jump_label.c2
-rw-r--r--arch/x86/kernel/kgdb.c60
-rw-r--r--arch/x86/kernel/kprobes.c5
-rw-r--r--arch/x86/kernel/microcode_amd.c5
-rw-r--r--arch/x86/kernel/microcode_core.c8
-rw-r--r--arch/x86/kernel/microcode_intel.c14
-rw-r--r--arch/x86/kernel/nmi.c433
-rw-r--r--arch/x86/kernel/pci-dma.c4
-rw-r--r--arch/x86/kernel/process.c2
-rw-r--r--arch/x86/kernel/process_32.c4
-rw-r--r--arch/x86/kernel/process_64.c2
-rw-r--r--arch/x86/kernel/reboot.c23
-rw-r--r--arch/x86/kernel/sys_x86_64.c78
-rw-r--r--arch/x86/kernel/syscall_table_32.S2
-rw-r--r--arch/x86/kernel/traps.c155
-rw-r--r--arch/x86/kvm/emulate.c867
-rw-r--r--arch/x86/kvm/i8254.c6
-rw-r--r--arch/x86/kvm/i8259.c123
-rw-r--r--arch/x86/kvm/irq.h4
-rw-r--r--arch/x86/kvm/kvm_cache_regs.h7
-rw-r--r--arch/x86/kvm/kvm_timer.h2
-rw-r--r--arch/x86/kvm/lapic.c167
-rw-r--r--arch/x86/kvm/lapic.h4
-rw-r--r--arch/x86/kvm/mmu.c5
-rw-r--r--arch/x86/kvm/mmu_audit.c6
-rw-r--r--arch/x86/kvm/paging_tmpl.h24
-rw-r--r--arch/x86/kvm/svm.c93
-rw-r--r--arch/x86/kvm/trace.h118
-rw-r--r--arch/x86/kvm/vmx.c131
-rw-r--r--arch/x86/kvm/x86.c277
-rw-r--r--arch/x86/lguest/boot.c10
-rw-r--r--arch/x86/lib/insn.c48
-rw-r--r--arch/x86/mm/fault.c10
-rw-r--r--arch/x86/mm/gup.c10
-rw-r--r--arch/x86/mm/mmap.c20
-rw-r--r--arch/x86/mm/mmio-mod.c1
-rw-r--r--arch/x86/oprofile/nmi_int.c44
-rw-r--r--arch/x86/oprofile/nmi_timer_int.c28
-rw-r--r--arch/x86/oprofile/op_model_amd.c234
-rw-r--r--arch/x86/oprofile/op_model_ppro.c27
-rw-r--r--arch/x86/oprofile/op_x86_model.h1
-rw-r--r--arch/x86/pci/ce4100.c2
-rw-r--r--arch/x86/pci/common.c4
-rw-r--r--arch/x86/pci/direct.c6
-rw-r--r--arch/x86/pci/mmconfig_32.c2
-rw-r--r--arch/x86/pci/mmconfig_64.c2
-rw-r--r--arch/x86/pci/numaq_32.c2
-rw-r--r--arch/x86/pci/olpc.c2
-rw-r--r--arch/x86/pci/pcbios.c4
-rw-r--r--arch/x86/pci/xen.c32
-rw-r--r--arch/x86/platform/Makefile1
-rw-r--r--arch/x86/platform/geode/Makefile1
-rw-r--r--arch/x86/platform/geode/alix.c142
-rw-r--r--arch/x86/platform/mrst/mrst.c3
-rw-r--r--arch/x86/platform/uv/tlb_uv.c17
-rw-r--r--arch/x86/um/Kconfig (renamed from arch/um/Kconfig.x86)0
-rw-r--r--arch/x86/um/Makefile45
-rw-r--r--arch/x86/um/asm/apic.h (renamed from arch/um/include/asm/apic.h)0
-rw-r--r--arch/x86/um/asm/arch_hweight.h (renamed from arch/um/include/asm/arch_hweight.h)0
-rw-r--r--arch/x86/um/asm/archparam.h (renamed from arch/um/sys-i386/asm/archparam.h)8
-rw-r--r--arch/x86/um/asm/checksum.h10
-rw-r--r--arch/x86/um/asm/checksum_32.h (renamed from arch/um/sys-i386/shared/sysdep/checksum.h)2
-rw-r--r--arch/x86/um/asm/checksum_64.h (renamed from arch/um/sys-x86_64/shared/sysdep/checksum.h)0
-rw-r--r--arch/x86/um/asm/desc.h (renamed from arch/um/include/asm/desc.h)0
-rw-r--r--arch/x86/um/asm/elf.h (renamed from arch/um/sys-x86_64/asm/elf.h)145
-rw-r--r--arch/x86/um/asm/irq_vectors.h (renamed from arch/um/include/asm/irq_vectors.h)0
-rw-r--r--arch/x86/um/asm/mm_context.h72
-rw-r--r--arch/x86/um/asm/module.h23
-rw-r--r--arch/x86/um/asm/processor.h22
-rw-r--r--arch/x86/um/asm/processor_32.h (renamed from arch/um/sys-i386/asm/processor.h)18
-rw-r--r--arch/x86/um/asm/processor_64.h (renamed from arch/um/sys-x86_64/asm/processor.h)11
-rw-r--r--arch/x86/um/asm/ptrace.h5
-rw-r--r--arch/x86/um/asm/ptrace_32.h (renamed from arch/um/sys-i386/asm/ptrace.h)0
-rw-r--r--arch/x86/um/asm/ptrace_64.h (renamed from arch/um/sys-x86_64/asm/ptrace.h)2
-rw-r--r--arch/x86/um/asm/required-features.h (renamed from arch/um/include/asm/required-features.h)0
-rw-r--r--arch/x86/um/asm/segment.h (renamed from arch/um/include/asm/segment.h)0
-rw-r--r--arch/x86/um/asm/system.h (renamed from arch/um/sys-x86_64/shared/sysdep/system.h)3
-rw-r--r--arch/x86/um/asm/vm-flags.h (renamed from arch/um/sys-x86_64/shared/sysdep/vm-flags.h)14
-rw-r--r--arch/x86/um/bug.c (renamed from arch/um/sys-x86_64/bug.c)0
-rw-r--r--arch/x86/um/bugs_32.c (renamed from arch/um/sys-i386/bugs.c)6
-rw-r--r--arch/x86/um/bugs_64.c (renamed from arch/um/sys-x86_64/bugs.c)0
-rw-r--r--arch/x86/um/checksum_32.S (renamed from arch/um/sys-i386/checksum.S)0
-rw-r--r--arch/x86/um/delay.c (renamed from arch/um/sys-i386/delay.c)0
-rw-r--r--arch/x86/um/elfcore.c (renamed from arch/um/sys-i386/elfcore.c)0
-rw-r--r--arch/x86/um/fault.c (renamed from arch/um/sys-i386/fault.c)0
-rw-r--r--arch/x86/um/ksyms.c (renamed from arch/um/sys-x86_64/ksyms.c)2
-rw-r--r--arch/x86/um/ldt.c (renamed from arch/um/sys-i386/ldt.c)36
-rw-r--r--arch/x86/um/mem_32.c (renamed from arch/um/sys-i386/mem.c)0
-rw-r--r--arch/x86/um/mem_64.c (renamed from arch/um/sys-x86_64/mem.c)0
-rw-r--r--arch/x86/um/os-Linux/Makefile (renamed from arch/um/os-Linux/sys-i386/Makefile)5
-rw-r--r--arch/x86/um/os-Linux/mcontext.c31
-rw-r--r--arch/x86/um/os-Linux/prctl.c (renamed from arch/um/os-Linux/sys-x86_64/prctl.c)0
-rw-r--r--arch/x86/um/os-Linux/registers.c (renamed from arch/um/os-Linux/sys-i386/registers.c)62
-rw-r--r--arch/x86/um/os-Linux/task_size.c (renamed from arch/um/os-Linux/sys-i386/task_size.c)13
-rw-r--r--arch/x86/um/os-Linux/tls.c (renamed from arch/um/os-Linux/sys-i386/tls.c)35
-rw-r--r--arch/x86/um/ptrace_32.c (renamed from arch/um/sys-i386/ptrace.c)69
-rw-r--r--arch/x86/um/ptrace_64.c (renamed from arch/um/sys-x86_64/ptrace.c)103
-rw-r--r--arch/x86/um/ptrace_user.c (renamed from arch/um/sys-i386/ptrace_user.c)2
-rw-r--r--arch/x86/um/setjmp_32.S (renamed from arch/um/sys-i386/setjmp.S)0
-rw-r--r--arch/x86/um/setjmp_64.S (renamed from arch/um/sys-x86_64/setjmp.S)0
-rw-r--r--arch/x86/um/shared/sysdep/archsetjmp.h5
-rw-r--r--arch/x86/um/shared/sysdep/archsetjmp_32.h (renamed from arch/um/sys-i386/shared/sysdep/archsetjmp.h)0
-rw-r--r--arch/x86/um/shared/sysdep/archsetjmp_64.h (renamed from arch/um/sys-x86_64/shared/sysdep/archsetjmp.h)0
-rw-r--r--arch/x86/um/shared/sysdep/faultinfo.h5
-rw-r--r--arch/x86/um/shared/sysdep/faultinfo_32.h (renamed from arch/um/sys-i386/shared/sysdep/faultinfo.h)6
-rw-r--r--arch/x86/um/shared/sysdep/faultinfo_64.h (renamed from arch/um/sys-x86_64/shared/sysdep/faultinfo.h)6
-rw-r--r--arch/x86/um/shared/sysdep/kernel-offsets.h (renamed from arch/um/sys-i386/shared/sysdep/kernel-offsets.h)0
-rw-r--r--arch/x86/um/shared/sysdep/mcontext.h31
-rw-r--r--arch/x86/um/shared/sysdep/ptrace.h5
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_32.h (renamed from arch/um/sys-i386/shared/sysdep/ptrace.h)75
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_64.h (renamed from arch/um/sys-x86_64/shared/sysdep/ptrace.h)103
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_user.h27
-rw-r--r--arch/x86/um/shared/sysdep/skas_ptrace.h (renamed from arch/um/sys-i386/shared/sysdep/skas_ptrace.h)4
-rw-r--r--arch/x86/um/shared/sysdep/stub.h14
-rw-r--r--arch/x86/um/shared/sysdep/stub_32.h (renamed from arch/um/sys-i386/shared/sysdep/stub.h)8
-rw-r--r--arch/x86/um/shared/sysdep/stub_64.h (renamed from arch/um/sys-x86_64/shared/sysdep/stub.h)8
-rw-r--r--arch/x86/um/shared/sysdep/syscalls.h5
-rw-r--r--arch/x86/um/shared/sysdep/syscalls_32.h (renamed from arch/um/sys-i386/shared/sysdep/syscalls.h)0
-rw-r--r--arch/x86/um/shared/sysdep/syscalls_64.h (renamed from arch/um/sys-x86_64/shared/sysdep/syscalls.h)1
-rw-r--r--arch/x86/um/shared/sysdep/tls.h (renamed from arch/um/sys-i386/shared/sysdep/tls.h)9
-rw-r--r--arch/x86/um/signal.c (renamed from arch/um/sys-i386/signal.c)304
-rw-r--r--arch/x86/um/stub_32.S (renamed from arch/um/sys-i386/stub.S)0
-rw-r--r--arch/x86/um/stub_64.S (renamed from arch/um/sys-x86_64/stub.S)0
-rw-r--r--arch/x86/um/stub_segv.c (renamed from arch/um/sys-x86_64/stub_segv.c)11
-rw-r--r--arch/x86/um/sys_call_table_32.S (renamed from arch/um/sys-i386/sys_call_table.S)4
-rw-r--r--arch/x86/um/sys_call_table_64.c (renamed from arch/um/sys-x86_64/syscall_table.c)3
-rw-r--r--arch/x86/um/syscalls_32.c (renamed from arch/um/sys-i386/syscalls.c)0
-rw-r--r--arch/x86/um/syscalls_64.c (renamed from arch/um/sys-x86_64/syscalls.c)0
-rw-r--r--arch/x86/um/sysrq_32.c (renamed from arch/um/sys-i386/sysrq.c)0
-rw-r--r--arch/x86/um/sysrq_64.c (renamed from arch/um/sys-x86_64/sysrq.c)2
-rw-r--r--arch/x86/um/tls_32.c (renamed from arch/um/sys-i386/tls.c)0
-rw-r--r--arch/x86/um/tls_64.c (renamed from arch/um/sys-x86_64/tls.c)0
-rw-r--r--arch/x86/um/user-offsets.c (renamed from arch/um/sys-x86_64/user-offsets.c)51
-rw-r--r--arch/x86/um/vdso/Makefile (renamed from arch/um/sys-x86_64/vdso/Makefile)4
-rw-r--r--arch/x86/um/vdso/checkundef.sh (renamed from arch/um/sys-x86_64/vdso/checkundef.sh)0
-rw-r--r--arch/x86/um/vdso/um_vdso.c (renamed from arch/um/sys-x86_64/vdso/um_vdso.c)0
-rw-r--r--arch/x86/um/vdso/vdso-layout.lds.S (renamed from arch/um/sys-x86_64/vdso/vdso-layout.lds.S)0
-rw-r--r--arch/x86/um/vdso/vdso-note.S (renamed from arch/um/sys-x86_64/vdso/vdso-note.S)0
-rw-r--r--arch/x86/um/vdso/vdso.S (renamed from arch/um/sys-x86_64/vdso/vdso.S)2
-rw-r--r--arch/x86/um/vdso/vdso.lds.S (renamed from arch/um/sys-x86_64/vdso/vdso.lds.S)0
-rw-r--r--arch/x86/um/vdso/vma.c (renamed from arch/um/sys-x86_64/vdso/vma.c)2
-rw-r--r--arch/x86/vdso/vma.c9
-rw-r--r--arch/x86/xen/Kconfig11
-rw-r--r--arch/x86/xen/enlighten.c1
-rw-r--r--arch/x86/xen/mmu.c52
-rw-r--r--arch/x86/xen/p2m.c128
-rw-r--r--arch/x86/xen/setup.c284
-rw-r--r--arch/xtensa/configs/iss_defconfig1
-rw-r--r--arch/xtensa/configs/s6105_defconfig1
-rw-r--r--arch/xtensa/platforms/iss/network.c2
-rw-r--r--block/genhd.c71
-rw-r--r--crypto/Kconfig63
-rw-r--r--crypto/Makefile4
-rw-r--r--crypto/ablkcipher.c48
-rw-r--r--crypto/aead.c48
-rw-r--r--crypto/ahash.c21
-rw-r--r--crypto/algapi.c12
-rw-r--r--crypto/blkcipher.c25
-rw-r--r--crypto/blowfish_common.c (renamed from crypto/blowfish.c)98
-rw-r--r--crypto/blowfish_generic.c142
-rw-r--r--crypto/cryptd.c2
-rw-r--r--crypto/crypto_user.c438
-rw-r--r--crypto/internal.h3
-rw-r--r--crypto/pcompress.c18
-rw-r--r--crypto/rng.c20
-rw-r--r--crypto/sha1_generic.c9
-rw-r--r--crypto/shash.c21
-rw-r--r--crypto/tcrypt.c10
-rw-r--r--crypto/testmgr.c30
-rw-r--r--crypto/testmgr.h398
-rw-r--r--crypto/wp512.c18
-rw-r--r--drivers/Kconfig6
-rw-r--r--drivers/Makefile5
-rw-r--r--drivers/acpi/apei/Kconfig1
-rw-r--r--drivers/acpi/apei/erst.c12
-rw-r--r--drivers/acpi/apei/ghes.c22
-rw-r--r--drivers/acpi/osl.c3
-rw-r--r--drivers/acpi/processor_idle.c12
-rw-r--r--drivers/acpi/sleep.c24
-rw-r--r--drivers/amba/bus.c68
-rw-r--r--drivers/ata/Kconfig3
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/ahci_platform.c44
-rw-r--r--drivers/ata/ata_piix.c153
-rw-r--r--drivers/ata/libata-core.c3
-rw-r--r--drivers/ata/libata-eh.c5
-rw-r--r--drivers/ata/libata-scsi.c44
-rw-r--r--drivers/ata/libata-sff.c117
-rw-r--r--drivers/ata/pata_ali.c2
-rw-r--r--drivers/ata/pata_arasan_cf.c6
-rw-r--r--drivers/ata/pata_artop.c107
-rw-r--r--drivers/ata/pata_at91.c7
-rw-r--r--drivers/ata/pata_atiixp.c35
-rw-r--r--drivers/ata/pata_cmd64x.c44
-rw-r--r--drivers/ata/pata_cs5535.c16
-rw-r--r--drivers/ata/pata_efar.c22
-rw-r--r--drivers/ata/pata_hpt366.c35
-rw-r--r--drivers/ata/pata_it8213.c24
-rw-r--r--drivers/ata/pata_legacy.c129
-rw-r--r--drivers/ata/pata_mpc52xx.c2
-rw-r--r--drivers/ata/pata_of_platform.c6
-rw-r--r--drivers/ata/pata_pdc2027x.c30
-rw-r--r--drivers/ata/pata_qdi.c366
-rw-r--r--drivers/ata/pata_rdc.c16
-rw-r--r--drivers/ata/pata_sc1200.c14
-rw-r--r--drivers/ata/pata_scc.c14
-rw-r--r--drivers/ata/pata_serverworks.c127
-rw-r--r--drivers/ata/pata_sil680.c94
-rw-r--r--drivers/ata/pata_sis.c154
-rw-r--r--drivers/ata/pata_sl82c105.c37
-rw-r--r--drivers/ata/pata_via.c49
-rw-r--r--drivers/ata/sata_mv.c16
-rw-r--r--drivers/ata/sata_sil24.c4
-rw-r--r--drivers/atm/eni.c5
-rw-r--r--drivers/atm/idt77252.c11
-rw-r--r--drivers/atm/iphase.c265
-rw-r--r--drivers/atm/iphase.h395
-rw-r--r--drivers/atm/lanai.c3
-rw-r--r--drivers/base/class.c17
-rw-r--r--drivers/base/core.c5
-rw-r--r--drivers/base/dd.c3
-rw-r--r--drivers/base/memory.c62
-rw-r--r--drivers/base/platform.c54
-rw-r--r--drivers/base/power/Makefile4
-rw-r--r--drivers/base/power/clock_ops.c127
-rw-r--r--drivers/base/power/common.c86
-rw-r--r--drivers/base/power/domain.c352
-rw-r--r--drivers/base/power/main.c42
-rw-r--r--drivers/base/power/opp.c30
-rw-r--r--drivers/base/power/power.h10
-rw-r--r--drivers/base/power/qos.c419
-rw-r--r--drivers/base/power/runtime.c127
-rw-r--r--drivers/base/power/wakeup.c4
-rw-r--r--drivers/base/regmap/Kconfig2
-rw-r--r--drivers/base/regmap/Makefile3
-rw-r--r--drivers/base/regmap/internal.h128
-rw-r--r--drivers/base/regmap/regcache-indexed.c64
-rw-r--r--drivers/base/regmap/regcache-lzo.c361
-rw-r--r--drivers/base/regmap/regcache-rbtree.c345
-rw-r--r--drivers/base/regmap/regcache.c401
-rw-r--r--drivers/base/regmap/regmap-debugfs.c209
-rw-r--r--drivers/base/regmap/regmap-i2c.c2
-rw-r--r--drivers/base/regmap/regmap-spi.c2
-rw-r--r--drivers/base/regmap/regmap.c221
-rw-r--r--drivers/bcma/Kconfig13
-rw-r--r--drivers/bcma/Makefile2
-rw-r--r--drivers/bcma/bcma_private.h16
-rw-r--r--drivers/bcma/core.c2
-rw-r--r--drivers/bcma/driver_chipcommon.c53
-rw-r--r--drivers/bcma/driver_chipcommon_pmu.c191
-rw-r--r--drivers/bcma/driver_mips.c256
-rw-r--r--drivers/bcma/driver_pci.c16
-rw-r--r--drivers/bcma/host_soc.c183
-rw-r--r--drivers/bcma/main.c70
-rw-r--r--drivers/bcma/scan.c348
-rw-r--r--drivers/bcma/sprom.c15
-rw-r--r--drivers/block/drbd/drbd_bitmap.c5
-rw-r--r--drivers/block/drbd/drbd_int.h3
-rw-r--r--drivers/block/drbd/drbd_nl.c4
-rw-r--r--drivers/block/rbd.c4
-rw-r--r--drivers/block/virtio_blk.c30
-rw-r--r--drivers/block/xen-blkback/blkback.c2
-rw-r--r--drivers/block/xen-blkback/common.h1
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c4
-rw-r--r--drivers/bluetooth/btusb.c8
-rw-r--r--drivers/char/Kconfig6
-rw-r--r--drivers/char/agp/backend.c3
-rw-r--r--drivers/char/agp/hp-agp.c6
-rw-r--r--drivers/char/agp/intel-gtt.c32
-rw-r--r--drivers/char/apm-emulation.c21
-rw-r--r--drivers/char/hw_random/Kconfig28
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/atmel-rng.c158
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c33
-rw-r--r--drivers/char/random.c23
-rw-r--r--drivers/char/raw.c3
-rw-r--r--drivers/char/rtc.c7
-rw-r--r--drivers/char/scc.h613
-rw-r--r--drivers/char/tpm/tpm.c3
-rw-r--r--drivers/char/ttyprintk.c2
-rw-r--r--drivers/char/virtio_console.c120
-rw-r--r--drivers/clocksource/Kconfig15
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/clksrc-dbx500-prcmu.c106
-rw-r--r--drivers/clocksource/dw_apb_timer.c2
-rw-r--r--drivers/connector/cn_proc.c26
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c4
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c6
-rw-r--r--drivers/cpuidle/cpuidle.c2
-rw-r--r--drivers/cpuidle/governors/ladder.c2
-rw-r--r--drivers/cpuidle/governors/menu.c2
-rw-r--r--drivers/crypto/Kconfig3
-rw-r--r--drivers/crypto/hifn_795x.c6
-rw-r--r--drivers/crypto/n2_core.c4
-rw-r--r--drivers/crypto/padlock-aes.c4
-rw-r--r--drivers/crypto/picoxcell_crypto.c121
-rw-r--r--drivers/crypto/talitos.c18
-rw-r--r--drivers/dca/dca-core.c78
-rw-r--r--drivers/devfreq/Kconfig75
-rw-r--r--drivers/devfreq/Makefile5
-rw-r--r--drivers/devfreq/devfreq.c601
-rw-r--r--drivers/devfreq/governor.h24
-rw-r--r--drivers/devfreq/governor_performance.c29
-rw-r--r--drivers/devfreq/governor_powersave.c29
-rw-r--r--drivers/devfreq/governor_simpleondemand.c88
-rw-r--r--drivers/devfreq/governor_userspace.c116
-rw-r--r--drivers/dma/ipu/ipu_irq.c48
-rw-r--r--drivers/edac/Kconfig16
-rw-r--r--drivers/edac/Makefile2
-rw-r--r--drivers/edac/amd64_edac.c37
-rw-r--r--drivers/edac/edac_core.h350
-rw-r--r--drivers/edac/edac_mce.c61
-rw-r--r--drivers/edac/i7300_edac.c51
-rw-r--r--drivers/edac/i7core_edac.c415
-rw-r--r--drivers/edac/mce_amd.c46
-rw-r--r--drivers/edac/mce_amd.h6
-rw-r--r--drivers/edac/sb_edac.c1893
-rw-r--r--drivers/firewire/core-transaction.c4
-rw-r--r--drivers/firewire/net.c15
-rw-r--r--drivers/firewire/ohci.c255
-rw-r--r--drivers/firewire/sbp2.c260
-rw-r--r--drivers/firmware/efivars.c19
-rw-r--r--drivers/gpio/Kconfig11
-rw-r--r--drivers/gpio/Makefile7
-rw-r--r--drivers/gpio/gpio-davinci.c (renamed from arch/arm/mach-davinci/gpio.c)7
-rw-r--r--drivers/gpio/gpio-ep93xx.c22
-rw-r--r--drivers/gpio/gpio-ks8695.c (renamed from arch/arm/mach-ks8695/gpio.c)4
-rw-r--r--drivers/gpio/gpio-langwell.c27
-rw-r--r--drivers/gpio/gpio-lpc32xx.c (renamed from arch/arm/mach-lpc32xx/gpiolib.c)2
-rw-r--r--drivers/gpio/gpio-ml-ioh.c254
-rw-r--r--drivers/gpio/gpio-mxc.c18
-rw-r--r--drivers/gpio/gpio-mxs.c2
-rw-r--r--drivers/gpio/gpio-nomadik.c130
-rw-r--r--drivers/gpio/gpio-omap.c2
-rw-r--r--drivers/gpio/gpio-pch.c250
-rw-r--r--drivers/gpio/gpio-pl061.c31
-rw-r--r--drivers/gpio/gpio-pxa.c (renamed from arch/arm/plat-pxa/gpio.c)6
-rw-r--r--drivers/gpio/gpio-sa1100.c (renamed from arch/arm/mach-sa1100/gpio.c)4
-rw-r--r--drivers/gpio/gpio-tegra.c166
-rw-r--r--drivers/gpio/gpio-tnetv107x.c (renamed from arch/arm/mach-davinci/gpio-tnetv107x.c)0
-rw-r--r--drivers/gpio/gpio-u300.c1190
-rw-r--r--drivers/gpu/drm/Kconfig4
-rw-r--r--drivers/gpu/drm/Makefile1
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c2
-rw-r--r--drivers/gpu/drm/drm_debugfs.c5
-rw-r--r--drivers/gpu/drm/drm_drv.c2
-rw-r--r--drivers/gpu/drm/drm_edid.c171
-rw-r--r--drivers/gpu/drm/drm_gem.c88
-rw-r--r--drivers/gpu/drm/drm_proc.c3
-rw-r--r--drivers/gpu/drm/exynos/Kconfig20
-rw-r--r--drivers/gpu/drm/exynos/Makefile11
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_buf.c110
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_buf.h53
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_connector.c293
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_connector.h34
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_core.c272
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c381
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h38
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c244
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h254
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.c271
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.h45
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c265
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.h37
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c456
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.h37
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c811
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c415
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.h107
-rw-r--r--drivers/gpu/drm/i915/dvo_ch7017.c2
-rw-r--r--drivers/gpu/drm/i915/dvo_ch7xxx.c4
-rw-r--r--drivers/gpu/drm/i915/dvo_ivch.c6
-rw-r--r--drivers/gpu/drm/i915/dvo_sil164.c2
-rw-r--r--drivers/gpu/drm/i915/dvo_tfp410.c14
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c38
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c48
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c63
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h103
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c113
-rw-r--r--drivers/gpu/drm/i915/i915_gem_debug.c8
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c3
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c30
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c15
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c42
-rw-r--r--drivers/gpu/drm/i915/i915_mem.c14
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h111
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c8
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h46
-rw-r--r--drivers/gpu/drm/i915/intel_acpi.c2
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c23
-rw-r--r--drivers/gpu/drm/i915/intel_bios.h22
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c20
-rw-r--r--drivers/gpu/drm/i915/intel_display.c762
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c614
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h21
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c33
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c8
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c8
-rw-r--r--drivers/gpu/drm/i915/intel_modes.c2
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c90
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c146
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c27
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c369
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h16
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c249
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo_regs.h558
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c58
-rw-r--r--drivers/gpu/drm/nouveau/Makefile9
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c169
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c275
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_channel.c16
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c52
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_crtc.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c9
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c963
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h123
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h27
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_i2c.c56
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c284
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mm.c89
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mm.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_object.c18
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_perf.c118
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_pm.c100
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_pm.h15
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_reg.h11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sgdma.c66
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c210
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.c40
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_volt.c46
-rw-r--r--drivers/gpu/drm/nouveau/nv04_display.c23
-rw-r--r--drivers/gpu/drm/nouveau/nv04_pm.c4
-rw-r--r--drivers/gpu/drm/nouveau/nv04_timer.c84
-rw-r--r--drivers/gpu/drm/nouveau/nv31_mpeg.c (renamed from drivers/gpu/drm/nouveau/nv40_mpeg.c)91
-rw-r--r--drivers/gpu/drm/nouveau/nv40_pm.c338
-rw-r--r--drivers/gpu/drm/nouveau/nv50_crtc.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_cursor.c18
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c76
-rw-r--r--drivers/gpu/drm/nouveau/nv50_gpio.c31
-rw-r--r--drivers/gpu/drm/nouveau/nv50_graph.c118
-rw-r--r--drivers/gpu/drm/nouveau/nv50_grctx.c11
-rw-r--r--drivers/gpu/drm/nouveau/nv50_pm.c8
-rw-r--r--drivers/gpu/drm/nouveau/nv50_sor.c42
-rw-r--r--drivers/gpu/drm/nouveau/nv50_vram.c4
-rw-r--r--drivers/gpu/drm/nouveau/nva3_pm.c402
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fb.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fifo.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.c40
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grctx.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grgpc.fuc8
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h29
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grhub.fuc3
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h16
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_pm.c155
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_vram.c50
-rw-r--r--drivers/gpu/drm/nouveau/nvd0_display.c1473
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c51
-rw-r--r--drivers/gpu/drm/radeon/evergreen_blit_kms.c348
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c32
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h42
-rw-r--r--drivers/gpu/drm/radeon/ni.c21
-rw-r--r--drivers/gpu/drm/radeon/r100.c149
-rw-r--r--drivers/gpu/drm/radeon/r100_track.h110
-rw-r--r--drivers/gpu/drm/radeon/r300.c5
-rw-r--r--drivers/gpu/drm/radeon/r300_cmdbuf.c2
-rw-r--r--drivers/gpu/drm/radeon/r600.c37
-rw-r--r--drivers/gpu/drm/radeon/r600_blit.c24
-rw-r--r--drivers/gpu/drm/radeon/r600_blit_kms.c359
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c41
-rw-r--r--drivers/gpu/drm/radeon/r600d.h22
-rw-r--r--drivers/gpu/drm/radeon/radeon.h109
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h14
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_benchmark.c247
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c28
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c22
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_gart.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c48
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_tv.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c41
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.h42
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c38
-rw-r--r--drivers/gpu/drm/radeon/radeon_state.c16
-rw-r--r--drivers/gpu/drm/radeon/rs400.c3
-rw-r--r--drivers/gpu/drm/radeon/rs600.c3
-rw-r--r--drivers/gpu/drm/radeon/rv770.c15
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/Kconfig9
-rw-r--r--drivers/gpu/drm/vmwgfx/Makefile3
-rw-r--r--drivers/gpu/drm/vmwgfx/svga3d_reg.h259
-rw-r--r--drivers/gpu/drm/vmwgfx/svga_escape.h2
-rw-r--r--drivers/gpu/drm/vmwgfx/svga_overlay.h22
-rw-r--r--drivers/gpu/drm/vmwgfx/svga_reg.h304
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c73
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c322
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c276
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h227
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c870
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c74
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.c1135
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.h113
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c156
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c81
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c46
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c273
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_irq.c187
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c1083
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h44
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c305
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_marker.c171
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c188
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c1035
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c567
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c5
-rw-r--r--drivers/hid/Kconfig42
-rw-r--r--drivers/hid/Makefile4
-rw-r--r--drivers/hid/hid-apple.c24
-rw-r--r--drivers/hid/hid-axff.c36
-rw-r--r--drivers/hid/hid-core.c86
-rw-r--r--drivers/hid/hid-debug.c5
-rw-r--r--drivers/hid/hid-ids.h25
-rw-r--r--drivers/hid/hid-input.c11
-rw-r--r--drivers/hid/hid-lg.c29
-rw-r--r--drivers/hid/hid-lg.h4
-rw-r--r--drivers/hid/hid-lg4ff.c403
-rw-r--r--drivers/hid/hid-lgff.c13
-rw-r--r--drivers/hid/hid-logitech-dj.c922
-rw-r--r--drivers/hid/hid-logitech-dj.h123
-rw-r--r--drivers/hid/hid-magicmouse.c7
-rw-r--r--drivers/hid/hid-multitouch.c46
-rw-r--r--drivers/hid/hid-picolcd.c2
-rw-r--r--drivers/hid/hid-primax.c117
-rw-r--r--drivers/hid/hid-prodikeys.c8
-rw-r--r--drivers/hid/hid-roccat-kone.c63
-rw-r--r--drivers/hid/hid-roccat-kovaplus.c17
-rw-r--r--drivers/hid/hid-roccat-pyra.c23
-rw-r--r--drivers/hid/hid-roccat.c18
-rw-r--r--drivers/hid/hid-sjoy.c75
-rw-r--r--drivers/hid/hid-wacom.c81
-rw-r--r--drivers/hid/hid-wiimote.c800
-rw-r--r--drivers/hid/hid-zydacron.c4
-rw-r--r--drivers/hid/hidraw.c11
-rw-r--r--drivers/hid/usbhid/hid-core.c9
-rw-r--r--drivers/hid/usbhid/hid-quirks.c2
-rw-r--r--drivers/hid/usbhid/hiddev.c2
-rw-r--r--drivers/hv/Kconfig14
-rw-r--r--drivers/hv/Makefile7
-rw-r--r--drivers/hv/channel.c (renamed from drivers/staging/hv/channel.c)122
-rw-r--r--drivers/hv/channel_mgmt.c (renamed from drivers/staging/hv/channel_mgmt.c)190
-rw-r--r--drivers/hv/connection.c (renamed from drivers/staging/hv/connection.c)58
-rw-r--r--drivers/hv/hv.c (renamed from drivers/staging/hv/hv.c)25
-rw-r--r--drivers/hv/hv_kvp.c (renamed from drivers/staging/hv/hv_kvp.c)49
-rw-r--r--drivers/hv/hv_kvp.h (renamed from drivers/staging/hv/hv_kvp.h)2
-rw-r--r--drivers/hv/hv_util.c (renamed from drivers/staging/hv/hv_util.c)210
-rw-r--r--drivers/hv/hyperv_vmbus.h (renamed from drivers/staging/hv/hyperv_vmbus.h)17
-rw-r--r--drivers/hv/ring_buffer.c (renamed from drivers/staging/hv/ring_buffer.c)42
-rw-r--r--drivers/hv/vmbus_drv.c (renamed from drivers/staging/hv/vmbus_drv.c)472
-rw-r--r--drivers/hwmon/Kconfig21
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/ad7314.c186
-rw-r--r--drivers/hwmon/coretemp.c28
-rw-r--r--drivers/hwmon/exynos4_tmu.c524
-rw-r--r--drivers/hwmon/f71882fg.c231
-rw-r--r--drivers/hwmon/hwmon.c32
-rw-r--r--drivers/hwmon/ibmaem.c47
-rw-r--r--drivers/hwmon/lm75.c39
-rw-r--r--drivers/hwmon/pmbus/Kconfig28
-rw-r--r--drivers/hwmon/pmbus/Makefile2
-rw-r--r--drivers/hwmon/pmbus/adm1275.c159
-rw-r--r--drivers/hwmon/pmbus/lm25066.c17
-rw-r--r--drivers/hwmon/pmbus/ltc2978.c408
-rw-r--r--drivers/hwmon/pmbus/max16064.c3
-rw-r--r--drivers/hwmon/pmbus/max34440.c13
-rw-r--r--drivers/hwmon/pmbus/max8688.c9
-rw-r--r--drivers/hwmon/pmbus/pmbus.c10
-rw-r--r--drivers/hwmon/pmbus/pmbus.h23
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c85
-rw-r--r--drivers/hwmon/pmbus/ucd9000.c13
-rw-r--r--drivers/hwmon/pmbus/ucd9200.c5
-rw-r--r--drivers/hwmon/pmbus/zl6100.c256
-rw-r--r--drivers/hwmon/w83627ehf.c238
-rw-r--r--drivers/hwspinlock/Kconfig27
-rw-r--r--drivers/hwspinlock/Makefile1
-rw-r--r--drivers/hwspinlock/hwspinlock_core.c204
-rw-r--r--drivers/hwspinlock/hwspinlock_internal.h40
-rw-r--r--drivers/hwspinlock/omap_hwspinlock.c127
-rw-r--r--drivers/hwspinlock/u8500_hsem.c198
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c24
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c6
-rw-r--r--drivers/i2c/busses/Kconfig18
-rw-r--r--drivers/i2c/busses/Makefile5
-rw-r--r--drivers/i2c/busses/i2c-au1550.c280
-rw-r--r--drivers/i2c/busses/i2c-bfin-twi.c4
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c (renamed from drivers/i2c/busses/i2c-designware.c)384
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h105
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c392
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c215
-rw-r--r--drivers/i2c/busses/i2c-eg20t.c270
-rw-r--r--drivers/i2c/busses/i2c-highlander.c2
-rw-r--r--drivers/i2c/busses/i2c-imx.c46
-rw-r--r--drivers/i2c/busses/i2c-ixp2000.c2
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c91
-rw-r--r--drivers/i2c/busses/i2c-nuc900.c2
-rw-r--r--drivers/i2c/busses/i2c-omap.c164
-rw-r--r--drivers/i2c/busses/i2c-pmcmsp.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c130
-rw-r--r--drivers/i2c/busses/i2c-sh7760.c2
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c2
-rw-r--r--drivers/i2c/busses/i2c-stu300.c2
-rw-r--r--drivers/i2c/busses/i2c-tegra.c2
-rw-r--r--drivers/i2c/busses/scx200_acb.c6
-rw-r--r--drivers/ide/Kconfig2
-rw-r--r--drivers/ide/at91_ide.c2
-rw-r--r--drivers/infiniband/core/cm.c63
-rw-r--r--drivers/infiniband/core/cm_msgs.h32
-rw-r--r--drivers/infiniband/core/cma.c67
-rw-r--r--drivers/infiniband/core/mad.c3
-rw-r--r--drivers/infiniband/core/sysfs.c26
-rw-r--r--drivers/infiniband/core/ucm.c2
-rw-r--r--drivers/infiniband/core/ucma.c7
-rw-r--r--drivers/infiniband/core/umem.c6
-rw-r--r--drivers/infiniband/core/user_mad.c5
-rw-r--r--drivers/infiniband/core/uverbs.h18
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c703
-rw-r--r--drivers/infiniband/core/uverbs_main.c30
-rw-r--r--drivers/infiniband/core/verbs.c376
-rw-r--r--drivers/infiniband/hw/amso1100/c2.c11
-rw-r--r--drivers/infiniband/hw/amso1100/c2_ae.c5
-rw-r--r--drivers/infiniband/hw/amso1100/c2_intr.c5
-rw-r--r--drivers/infiniband/hw/amso1100/c2_provider.c5
-rw-r--r--drivers/infiniband/hw/cxgb3/Makefile2
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c10
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_ev.c6
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.h1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_qp.c14
-rw-r--r--drivers/infiniband/hw/cxgb4/Makefile2
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c469
-rw-r--r--drivers/infiniband/hw/cxgb4/cq.c3
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c41
-rw-r--r--drivers/infiniband/hw/cxgb4/ev.c10
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h23
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c39
-rw-r--r--drivers/infiniband/hw/ehca/ehca_eq.c4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_srq.c5
-rw-r--r--drivers/infiniband/hw/ipath/ipath_user_pages.c6
-rw-r--r--drivers/infiniband/hw/mlx4/Kconfig3
-rw-r--r--drivers/infiniband/hw/mlx4/main.c106
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h13
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c131
-rw-r--r--drivers/infiniband/hw/mlx4/srq.c10
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c3
-rw-r--r--drivers/infiniband/hw/nes/Makefile2
-rw-r--r--drivers/infiniband/hw/nes/nes.c8
-rw-r--r--drivers/infiniband/hw/nes/nes.h17
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c1121
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.h75
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c99
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h35
-rw-r--r--drivers/infiniband/hw/nes/nes_mgt.c1162
-rw-r--r--drivers/infiniband/hw/nes/nes_mgt.h97
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c33
-rw-r--r--drivers/infiniband/hw/nes/nes_utils.c53
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c8
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.h12
-rw-r--r--drivers/infiniband/hw/qib/qib.h15
-rw-r--r--drivers/infiniband/hw/qib/qib_driver.c20
-rw-r--r--drivers/infiniband/hw/qib/qib_file_ops.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7220.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c135
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c8
-rw-r--r--drivers/infiniband/hw/qib/qib_qp.c90
-rw-r--r--drivers/infiniband/hw/qib/qib_qsfp.c25
-rw-r--r--drivers/infiniband/hw/qib/qib_qsfp.h3
-rw-r--r--drivers/infiniband/hw/qib/qib_rc.c36
-rw-r--r--drivers/infiniband/hw/qib/qib_ruc.c7
-rw-r--r--drivers/infiniband/hw/qib/qib_srq.c5
-rw-r--r--drivers/infiniband/hw/qib/qib_sysfs.c3
-rw-r--r--drivers/infiniband/hw/qib/qib_uc.c25
-rw-r--r--drivers/infiniband/hw/qib/qib_user_pages.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.c36
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.h5
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c12
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_fs.c7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c23
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c2
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c80
-rw-r--r--drivers/input/Kconfig2
-rw-r--r--drivers/input/ff-core.c11
-rw-r--r--drivers/input/input-mt.c1
-rw-r--r--drivers/input/input-polldev.c6
-rw-r--r--drivers/input/keyboard/Kconfig4
-rw-r--r--drivers/input/keyboard/adp5588-keys.c2
-rw-r--r--drivers/input/keyboard/adp5589-keys.c609
-rw-r--r--drivers/input/keyboard/davinci_keyscan.c2
-rw-r--r--drivers/input/keyboard/ep93xx_keypad.c2
-rw-r--r--drivers/input/keyboard/gpio_keys.c24
-rw-r--r--drivers/input/keyboard/imx_keypad.c46
-rw-r--r--drivers/input/keyboard/jornada720_kbd.c2
-rw-r--r--drivers/input/keyboard/lm8323.c2
-rw-r--r--drivers/input/keyboard/matrix_keypad.c1
-rw-r--r--drivers/input/keyboard/omap-keypad.c2
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c2
-rw-r--r--drivers/input/keyboard/pxa930_rotary.c2
-rw-r--r--drivers/input/keyboard/tc3589x-keypad.c2
-rw-r--r--drivers/input/keyboard/tegra-kbc.c85
-rw-r--r--drivers/input/keyboard/w90p910_keypad.c2
-rw-r--r--drivers/input/misc/Kconfig61
-rw-r--r--drivers/input/misc/Makefile5
-rw-r--r--drivers/input/misc/ad714x-i2c.c4
-rw-r--r--drivers/input/misc/bma150.c691
-rw-r--r--drivers/input/misc/ixp4xx-beeper.c2
-rw-r--r--drivers/input/misc/mma8450.c20
-rw-r--r--drivers/input/misc/pm8xxx-vibrator.c296
-rw-r--r--drivers/input/misc/rotary_encoder.c2
-rw-r--r--drivers/input/misc/twl6040-vibra.c23
-rw-r--r--drivers/input/mouse/alps.c52
-rw-r--r--drivers/input/mouse/elantech.c734
-rw-r--r--drivers/input/mouse/elantech.h57
-rw-r--r--drivers/input/mouse/hgpk.c84
-rw-r--r--drivers/input/mouse/hgpk.h11
-rw-r--r--drivers/input/mouse/lifebook.c6
-rw-r--r--drivers/input/mouse/logips2pp.c16
-rw-r--r--drivers/input/mouse/psmouse-base.c67
-rw-r--r--drivers/input/mouse/psmouse.h25
-rw-r--r--drivers/input/mouse/pxa930_trkball.c2
-rw-r--r--drivers/input/mouse/sentelic.c13
-rw-r--r--drivers/input/mouse/synaptics.c610
-rw-r--r--drivers/input/mouse/synaptics.h27
-rw-r--r--drivers/input/mouse/synaptics_i2c.c4
-rw-r--r--drivers/input/serio/serio_raw.c215
-rw-r--r--drivers/input/tablet/wacom.h10
-rw-r--r--drivers/input/tablet/wacom_sys.c356
-rw-r--r--drivers/input/tablet/wacom_wac.c48
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ad7879-i2c.c6
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c21
-rw-r--r--drivers/input/touchscreen/atmel_tsadcc.c2
-rw-r--r--drivers/input/touchscreen/h3600_ts_input.c4
-rw-r--r--drivers/input/touchscreen/hp680_ts_input.c2
-rw-r--r--drivers/input/touchscreen/jornada720_ts.c2
-rw-r--r--drivers/input/touchscreen/lpc32xx_ts.c2
-rw-r--r--drivers/input/touchscreen/penmount.c199
-rw-r--r--drivers/input/touchscreen/s3c2410_ts.c2
-rw-r--r--drivers/input/touchscreen/tsc2007.c200
-rw-r--r--drivers/input/touchscreen/tsc40.c184
-rw-r--r--drivers/input/touchscreen/w90p910_ts.c2
-rw-r--r--drivers/input/touchscreen/wacom_w8001.c29
-rw-r--r--drivers/iommu/Kconfig44
-rw-r--r--drivers/iommu/Makefile8
-rw-r--r--drivers/iommu/amd_iommu.c4
-rw-r--r--drivers/iommu/dmar.c246
-rw-r--r--drivers/iommu/intel-iommu.c205
-rw-r--r--drivers/iommu/intr_remapping.c93
-rw-r--r--drivers/iommu/iommu.c114
-rw-r--r--drivers/iommu/msm_iommu.c9
-rw-r--r--drivers/iommu/omap-iommu-debug.c (renamed from arch/arm/plat-omap/iommu-debug.c)36
-rw-r--r--drivers/iommu/omap-iommu.c (renamed from arch/arm/plat-omap/iommu.c)529
-rw-r--r--drivers/iommu/omap-iovmm.c (renamed from arch/arm/plat-omap/iovmm.c)370
-rw-r--r--drivers/isdn/Kconfig2
-rw-r--r--drivers/isdn/hisax/callc.c4
-rw-r--r--drivers/isdn/hisax/hisax.h4
-rw-r--r--drivers/isdn/hisax/isdnl1.h2
-rw-r--r--drivers/isdn/hisax/isdnl3.c2
-rw-r--r--drivers/isdn/hisax/st5481_d.c4
-rw-r--r--drivers/isdn/i4l/isdn_common.c4
-rw-r--r--drivers/isdn/i4l/isdn_tty.c2
-rw-r--r--drivers/isdn/mISDN/dsp_core.c3
-rw-r--r--drivers/isdn/mISDN/l1oip_codec.c6
-rw-r--r--drivers/leds/Kconfig22
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/led-class.c7
-rw-r--r--drivers/leds/led-triggers.c5
-rw-r--r--drivers/leds/leds-alix2.c239
-rw-r--r--drivers/leds/leds-gpio.c2
-rw-r--r--drivers/leds/leds-lm3530.c3
-rw-r--r--drivers/leds/leds-lp5521.c24
-rw-r--r--drivers/leds/leds-renesas-tpu.c357
-rw-r--r--drivers/lguest/core.c16
-rw-r--r--drivers/md/Kconfig36
-rw-r--r--drivers/md/Makefile4
-rw-r--r--drivers/md/bitmap.c188
-rw-r--r--drivers/md/bitmap.h12
-rw-r--r--drivers/md/dm-bufio.c1699
-rw-r--r--drivers/md/dm-bufio.h112
-rw-r--r--drivers/md/dm-ioctl.c11
-rw-r--r--drivers/md/dm-kcopyd.c31
-rw-r--r--drivers/md/dm-log-userspace-base.c37
-rw-r--r--drivers/md/dm-raid.c76
-rw-r--r--drivers/md/dm-table.c73
-rw-r--r--drivers/md/dm-thin-metadata.c1391
-rw-r--r--drivers/md/dm-thin-metadata.h156
-rw-r--r--drivers/md/dm-thin.c2428
-rw-r--r--drivers/md/dm.c21
-rw-r--r--drivers/md/dm.h2
-rw-r--r--drivers/md/faulty.c38
-rw-r--r--drivers/md/linear.c46
-rw-r--r--drivers/md/linear.h12
-rw-r--r--drivers/md/md.c631
-rw-r--r--drivers/md/md.h153
-rw-r--r--drivers/md/multipath.c64
-rw-r--r--drivers/md/multipath.h10
-rw-r--r--drivers/md/persistent-data/Kconfig8
-rw-r--r--drivers/md/persistent-data/Makefile11
-rw-r--r--drivers/md/persistent-data/dm-block-manager.c620
-rw-r--r--drivers/md/persistent-data/dm-block-manager.h123
-rw-r--r--drivers/md/persistent-data/dm-btree-internal.h137
-rw-r--r--drivers/md/persistent-data/dm-btree-remove.c566
-rw-r--r--drivers/md/persistent-data/dm-btree-spine.c244
-rw-r--r--drivers/md/persistent-data/dm-btree.c805
-rw-r--r--drivers/md/persistent-data/dm-btree.h145
-rw-r--r--drivers/md/persistent-data/dm-persistent-data-internal.h19
-rw-r--r--drivers/md/persistent-data/dm-space-map-checker.c437
-rw-r--r--drivers/md/persistent-data/dm-space-map-checker.h26
-rw-r--r--drivers/md/persistent-data/dm-space-map-common.c705
-rw-r--r--drivers/md/persistent-data/dm-space-map-common.h126
-rw-r--r--drivers/md/persistent-data/dm-space-map-disk.c335
-rw-r--r--drivers/md/persistent-data/dm-space-map-disk.h25
-rw-r--r--drivers/md/persistent-data/dm-space-map-metadata.c596
-rw-r--r--drivers/md/persistent-data/dm-space-map-metadata.h33
-rw-r--r--drivers/md/persistent-data/dm-space-map.h134
-rw-r--r--drivers/md/persistent-data/dm-transaction-manager.c400
-rw-r--r--drivers/md/persistent-data/dm-transaction-manager.h130
-rw-r--r--drivers/md/raid0.c191
-rw-r--r--drivers/md/raid0.h10
-rw-r--r--drivers/md/raid1.c335
-rw-r--r--drivers/md/raid1.h85
-rw-r--r--drivers/md/raid10.c282
-rw-r--r--drivers/md/raid10.h22
-rw-r--r--drivers/md/raid5.c363
-rw-r--r--drivers/md/raid5.h20
-rw-r--r--drivers/media/common/saa7146_core.c74
-rw-r--r--drivers/media/common/saa7146_fops.c118
-rw-r--r--drivers/media/common/saa7146_hlp.c14
-rw-r--r--drivers/media/common/saa7146_i2c.c60
-rw-r--r--drivers/media/common/saa7146_vbi.c48
-rw-r--r--drivers/media/common/saa7146_video.c183
-rw-r--r--drivers/media/common/tuners/Makefile4
-rw-r--r--drivers/media/common/tuners/mt20xx.c24
-rw-r--r--drivers/media/common/tuners/mxl5005s.c22
-rw-r--r--drivers/media/common/tuners/tda18212.c31
-rw-r--r--drivers/media/common/tuners/tda18271-common.c32
-rw-r--r--drivers/media/common/tuners/tda18271-fe.c2
-rw-r--r--drivers/media/common/tuners/tda18271-priv.h39
-rw-r--r--drivers/media/common/tuners/tda827x.c8
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.c18
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.h1
-rw-r--r--drivers/media/dvb/b2c2/Makefile4
-rw-r--r--drivers/media/dvb/bt8xx/Makefile8
-rw-r--r--drivers/media/dvb/ddbridge/Makefile8
-rw-r--r--drivers/media/dvb/ddbridge/ddbridge-core.c43
-rw-r--r--drivers/media/dvb/dm1105/Makefile2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c95
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h1
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c2
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig28
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile15
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c4
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-fe.c2
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-remote.c2
-rw-r--r--drivers/media/dvb/dvb-usb/af9005.c7
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c70
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.c337
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.h1
-rw-r--r--drivers/media/dvb/dvb-usb/au6610.c9
-rw-r--r--drivers/media/dvb/dvb-usb/az6027.c26
-rw-r--r--drivers/media/dvb/dvb-usb/ce6230.c9
-rw-r--r--drivers/media/dvb/dvb-usb/cinergyT2-core.c5
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c142
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_core.c99
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c377
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-common.c27
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c31
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mc.c3
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c16
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c14
-rw-r--r--drivers/media/dvb/dvb-usb/dtv5100.c11
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-dvb.c153
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h4
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c41
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-urb.c28
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h37
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.c115
-rw-r--r--drivers/media/dvb/dvb-usb/ec168.c9
-rw-r--r--drivers/media/dvb/dvb-usb/friio.c7
-rw-r--r--drivers/media/dvb/dvb-usb/gl861.c9
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk-fe.c17
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.c5
-rw-r--r--drivers/media/dvb/dvb-usb/it913x.c651
-rw-r--r--drivers/media/dvb/dvb-usb/lmedm04.c60
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.c58
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-gpio.c763
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-gpio.h56
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-i2c.c851
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-i2c.h35
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-phy.c342
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-phy.h53
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-reg.h179
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-tuner.c476
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-tuner.h89
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf.c864
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf.h158
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c4
-rw-r--r--drivers/media/dvb/dvb-usb/opera1.c13
-rw-r--r--drivers/media/dvb/dvb-usb/pctv452e.c1079
-rw-r--r--drivers/media/dvb/dvb-usb/technisat-usb2.c28
-rw-r--r--drivers/media/dvb/dvb-usb/ttusb2.c407
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c8
-rw-r--r--drivers/media/dvb/dvb-usb/usb-urb.c4
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.c5
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c5
-rw-r--r--drivers/media/dvb/frontends/Kconfig30
-rw-r--r--drivers/media/dvb/frontends/Makefile8
-rw-r--r--drivers/media/dvb/frontends/a8293.c184
-rw-r--r--drivers/media/dvb/frontends/a8293.h (renamed from drivers/media/common/tuners/tda18212_priv.h)39
-rw-r--r--drivers/media/dvb/frontends/cxd2820r.h9
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_c.c1
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_core.c80
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_priv.h1
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_t.c1
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_t2.c1
-rw-r--r--drivers/media/dvb/frontends/dib0070.c37
-rw-r--r--drivers/media/dvb/frontends/dib0090.c70
-rw-r--r--drivers/media/dvb/frontends/dib3000.h2
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c2
-rw-r--r--drivers/media/dvb/frontends/dib7000m.c27
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c34
-rw-r--r--drivers/media/dvb/frontends/dib8000.c72
-rw-r--r--drivers/media/dvb/frontends/dib9000.c167
-rw-r--r--drivers/media/dvb/frontends/dibx000_common.c76
-rw-r--r--drivers/media/dvb/frontends/dibx000_common.h1
-rw-r--r--drivers/media/dvb/frontends/drxd_hard.c24
-rw-r--r--drivers/media/dvb/frontends/drxk_hard.c10
-rw-r--r--drivers/media/dvb/frontends/it913x-fe-priv.h336
-rw-r--r--drivers/media/dvb/frontends/it913x-fe.c839
-rw-r--r--drivers/media/dvb/frontends/it913x-fe.h196
-rw-r--r--drivers/media/dvb/frontends/lnbp22.c148
-rw-r--r--drivers/media/dvb/frontends/lnbp22.h57
-rw-r--r--drivers/media/dvb/frontends/stb0899_algo.c3
-rw-r--r--drivers/media/dvb/frontends/stb0899_drv.c6
-rw-r--r--drivers/media/dvb/frontends/stv0288.c29
-rw-r--r--drivers/media/dvb/frontends/stv090x.c35
-rw-r--r--drivers/media/dvb/frontends/tda10048.c37
-rw-r--r--drivers/media/dvb/frontends/tda10048.h8
-rw-r--r--drivers/media/dvb/frontends/tda10071.c1269
-rw-r--r--drivers/media/dvb/frontends/tda10071.h81
-rw-r--r--drivers/media/dvb/frontends/tda10071_priv.h122
-rw-r--r--drivers/media/dvb/frontends/tda18271c2dd.c4
-rw-r--r--drivers/media/dvb/mantis/Makefile2
-rw-r--r--drivers/media/dvb/mantis/hopper_cards.c6
-rw-r--r--drivers/media/dvb/mantis/mantis_cards.c6
-rw-r--r--drivers/media/dvb/mantis/mantis_common.h5
-rw-r--r--drivers/media/dvb/mantis/mantis_dma.c92
-rw-r--r--drivers/media/dvb/mantis/mantis_vp1041.c1
-rw-r--r--drivers/media/dvb/ngene/Makefile8
-rw-r--r--drivers/media/dvb/pluto2/Makefile2
-rw-r--r--drivers/media/dvb/pt1/Makefile2
-rw-r--r--drivers/media/dvb/siano/Makefile4
-rw-r--r--drivers/media/dvb/ttpci/Makefile4
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c32
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c47
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c1
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c2
-rw-r--r--drivers/media/dvb/ttpci/budget.h1
-rw-r--r--drivers/media/dvb/ttpci/ttpci-eeprom.c29
-rw-r--r--drivers/media/dvb/ttpci/ttpci-eeprom.h1
-rw-r--r--drivers/media/dvb/ttusb-budget/Makefile2
-rw-r--r--drivers/media/dvb/ttusb-dec/Makefile2
-rw-r--r--drivers/media/radio/Makefile2
-rw-r--r--drivers/media/radio/radio-si4713.c4
-rw-r--r--drivers/media/radio/radio-wl1273.c2
-rw-r--r--drivers/media/radio/si470x/radio-si470x-usb.c2
-rw-r--r--drivers/media/radio/wl128x/fmdrv_v4l2.c8
-rw-r--r--drivers/media/rc/Kconfig23
-rw-r--r--drivers/media/rc/Makefile1
-rw-r--r--drivers/media/rc/ati_remote.c (renamed from drivers/input/misc/ati_remote.c)301
-rw-r--r--drivers/media/rc/ene_ir.c73
-rw-r--r--drivers/media/rc/ene_ir.h19
-rw-r--r--drivers/media/rc/imon.c36
-rw-r--r--drivers/media/rc/ir-lirc-codec.c9
-rw-r--r--drivers/media/rc/keymaps/Makefile3
-rw-r--r--drivers/media/rc/keymaps/rc-ati-x10.c104
-rw-r--r--drivers/media/rc/keymaps/rc-medion-x10.c117
-rw-r--r--drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c1
-rw-r--r--drivers/media/rc/keymaps/rc-snapstream-firefly.c107
-rw-r--r--drivers/media/rc/mceusb.c410
-rw-r--r--drivers/media/rc/rc-core-priv.h14
-rw-r--r--drivers/media/rc/rc-main.c29
-rw-r--r--drivers/media/rc/redrat3.c7
-rw-r--r--drivers/media/rc/winbond-cir.c6
-rw-r--r--drivers/media/video/Kconfig52
-rw-r--r--drivers/media/video/Makefile9
-rw-r--r--drivers/media/video/adp1653.c20
-rw-r--r--drivers/media/video/adv7175.c62
-rw-r--r--drivers/media/video/atmel-isi.c24
-rw-r--r--drivers/media/video/au0828/Makefile8
-rw-r--r--drivers/media/video/bt819.c2
-rw-r--r--drivers/media/video/bt8xx/Makefile6
-rw-r--r--drivers/media/video/bt8xx/bttv-cards.c242
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c294
-rw-r--r--drivers/media/video/bt8xx/bttv-gpio.c4
-rw-r--r--drivers/media/video/bt8xx/bttv-i2c.c56
-rw-r--r--drivers/media/video/bt8xx/bttv-input.c37
-rw-r--r--drivers/media/video/bt8xx/bttv-risc.c25
-rw-r--r--drivers/media/video/bt8xx/bttv-vbi.c9
-rw-r--r--drivers/media/video/bt8xx/bttvp.h18
-rw-r--r--drivers/media/video/cx18/Makefile6
-rw-r--r--drivers/media/video/cx18/cx18-driver.h5
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c2
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c18
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c2
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.h2
-rw-r--r--drivers/media/video/cx18/cx18-streams.c13
-rw-r--r--drivers/media/video/cx231xx/Makefile10
-rw-r--r--drivers/media/video/cx23885/Kconfig2
-rw-r--r--drivers/media/video/cx23885/Makefile12
-rw-r--r--drivers/media/video/cx23885/cx23885-alsa.c535
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c55
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c99
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c2
-rw-r--r--drivers/media/video/cx23885/cx23885-i2c.c1
-rw-r--r--drivers/media/video/cx23885/cx23885-reg.h3
-rw-r--r--drivers/media/video/cx23885/cx23885-vbi.c72
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c358
-rw-r--r--drivers/media/video/cx23885/cx23885.h56
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.c12
-rw-r--r--drivers/media/video/cx25840/Makefile2
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c10
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c19
-rw-r--r--drivers/media/video/cx25840/cx25840-ir.c12
-rw-r--r--drivers/media/video/cx88/Makefile8
-rw-r--r--drivers/media/video/cx88/cx88-core.c3
-rw-r--r--drivers/media/video/cx88/cx88-video.c2
-rw-r--r--drivers/media/video/davinci/vpbe_display.c1
-rw-r--r--drivers/media/video/davinci/vpbe_osd.c2
-rw-r--r--drivers/media/video/em28xx/Kconfig2
-rw-r--r--drivers/media/video/em28xx/Makefile8
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c155
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c45
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c117
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c6
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c58
-rw-r--r--drivers/media/video/em28xx/em28xx.h3
-rw-r--r--drivers/media/video/et61x251/et61x251.h66
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c2
-rw-r--r--drivers/media/video/et61x251/et61x251_tas5130d1b.c2
-rw-r--r--drivers/media/video/gspca/Kconfig10
-rw-r--r--drivers/media/video/gspca/Makefile2
-rw-r--r--drivers/media/video/gspca/benq.c31
-rw-r--r--drivers/media/video/gspca/conex.c6
-rw-r--r--drivers/media/video/gspca/cpia1.c7
-rw-r--r--drivers/media/video/gspca/etoms.c6
-rw-r--r--drivers/media/video/gspca/finepix.c8
-rw-r--r--drivers/media/video/gspca/gl860/Makefile2
-rw-r--r--drivers/media/video/gspca/gl860/gl860.c8
-rw-r--r--drivers/media/video/gspca/gspca.c287
-rw-r--r--drivers/media/video/gspca/gspca.h22
-rw-r--r--drivers/media/video/gspca/jeilinj.c20
-rw-r--r--drivers/media/video/gspca/kinect.c41
-rw-r--r--drivers/media/video/gspca/konica.c16
-rw-r--r--drivers/media/video/gspca/m5602/Makefile2
-rw-r--r--drivers/media/video/gspca/m5602/m5602_core.c9
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.c28
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov7660.c21
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.c19
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.c21
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.c35
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.c30
-rw-r--r--drivers/media/video/gspca/mars.c6
-rw-r--r--drivers/media/video/gspca/mr97310a.c24
-rw-r--r--drivers/media/video/gspca/nw80x.c9
-rw-r--r--drivers/media/video/gspca/ov519.c41
-rw-r--r--drivers/media/video/gspca/ov534.c12
-rw-r--r--drivers/media/video/gspca/ov534_9.c516
-rw-r--r--drivers/media/video/gspca/pac207.c14
-rw-r--r--drivers/media/video/gspca/pac7302.c15
-rw-r--r--drivers/media/video/gspca/pac7311.c15
-rw-r--r--drivers/media/video/gspca/se401.c46
-rw-r--r--drivers/media/video/gspca/sn9c2028.c14
-rw-r--r--drivers/media/video/gspca/sn9c20x.c76
-rw-r--r--drivers/media/video/gspca/sonixj.c45
-rw-r--r--drivers/media/video/gspca/spca1528.c34
-rw-r--r--drivers/media/video/gspca/spca500.c6
-rw-r--r--drivers/media/video/gspca/spca501.c4
-rw-r--r--drivers/media/video/gspca/spca505.c8
-rw-r--r--drivers/media/video/gspca/spca508.c6
-rw-r--r--drivers/media/video/gspca/spca561.c4
-rw-r--r--drivers/media/video/gspca/sq905.c17
-rw-r--r--drivers/media/video/gspca/sq905c.c10
-rw-r--r--drivers/media/video/gspca/sq930x.c21
-rw-r--r--drivers/media/video/gspca/stk014.c16
-rw-r--r--drivers/media/video/gspca/stv0680.c6
-rw-r--r--drivers/media/video/gspca/stv06xx/Makefile2
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx.c18
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx.h6
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c10
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c4
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_st6422.c4
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c32
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h56
-rw-r--r--drivers/media/video/gspca/sunplus.c10
-rw-r--r--drivers/media/video/gspca/t613.c12
-rw-r--r--drivers/media/video/gspca/topro.c4989
-rw-r--r--drivers/media/video/gspca/vc032x.c13
-rw-r--r--drivers/media/video/gspca/vicam.c12
-rw-r--r--drivers/media/video/gspca/w996Xcf.c8
-rw-r--r--drivers/media/video/gspca/xirlink_cit.c14
-rw-r--r--drivers/media/video/gspca/zc3xx.c15
-rw-r--r--drivers/media/video/hdpvr/Makefile4
-rw-r--r--drivers/media/video/hexium_gemini.c44
-rw-r--r--drivers/media/video/hexium_orion.c38
-rw-r--r--drivers/media/video/ivtv/Makefile8
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c15
-rw-r--r--drivers/media/video/m5mols/m5mols_core.c6
-rw-r--r--drivers/media/video/marvell-ccic/mcam-core.c12
-rw-r--r--drivers/media/video/marvell-ccic/mmp-driver.c1
-rw-r--r--drivers/media/video/mem2mem_testdev.c16
-rw-r--r--drivers/media/video/msp3400-driver.c20
-rw-r--r--drivers/media/video/msp3400-driver.h2
-rw-r--r--drivers/media/video/msp3400-kthreads.c86
-rw-r--r--drivers/media/video/mt9m111.c9
-rw-r--r--drivers/media/video/mt9p031.c964
-rw-r--r--drivers/media/video/mt9t001.c836
-rw-r--r--drivers/media/video/mx3_camera.c4
-rw-r--r--drivers/media/video/mxb.c80
-rw-r--r--drivers/media/video/noon010pc30.c263
-rw-r--r--drivers/media/video/omap/omap_vout.c18
-rw-r--r--drivers/media/video/omap3isp/Makefile4
-rw-r--r--drivers/media/video/omap3isp/isp.c51
-rw-r--r--drivers/media/video/omap3isp/isp.h90
-rw-r--r--drivers/media/video/omap3isp/ispccdc.c36
-rw-r--r--drivers/media/video/omap3isp/ispccp2.c4
-rw-r--r--drivers/media/video/omap3isp/ispqueue.c4
-rw-r--r--drivers/media/video/omap3isp/ispstat.c11
-rw-r--r--drivers/media/video/omap3isp/ispvideo.c26
-rw-r--r--drivers/media/video/pvrusb2/Makefile8
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c7
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.h3
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c8
-rw-r--r--drivers/media/video/pwc/pwc-if.c4
-rw-r--r--drivers/media/video/pwc/pwc-v4l.c136
-rw-r--r--drivers/media/video/s5p-fimc/Makefile2
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c1462
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c1134
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h221
-rw-r--r--drivers/media/video/s5p-fimc/fimc-mdevice.c858
-rw-r--r--drivers/media/video/s5p-fimc/fimc-mdevice.h118
-rw-r--r--drivers/media/video/s5p-fimc/fimc-reg.c90
-rw-r--r--drivers/media/video/s5p-fimc/mipi-csis.c90
-rw-r--r--drivers/media/video/s5p-fimc/regs-fimc.h9
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc.c15
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_dec.c18
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_enc.c36
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_opr.c14
-rw-r--r--drivers/media/video/s5p-tv/Kconfig2
-rw-r--r--drivers/media/video/s5p-tv/hdmi_drv.c15
-rw-r--r--drivers/media/video/s5p-tv/mixer.h2
-rw-r--r--drivers/media/video/s5p-tv/mixer_grp_layer.c2
-rw-r--r--drivers/media/video/s5p-tv/mixer_reg.c11
-rw-r--r--drivers/media/video/s5p-tv/mixer_video.c24
-rw-r--r--drivers/media/video/s5p-tv/mixer_vp_layer.c4
-rw-r--r--drivers/media/video/s5p-tv/regs-hdmi.h4
-rw-r--r--drivers/media/video/s5p-tv/regs-mixer.h1
-rw-r--r--drivers/media/video/s5p-tv/sdo_drv.c1
-rw-r--r--drivers/media/video/saa7115.c53
-rw-r--r--drivers/media/video/saa7134/Makefile8
-rw-r--r--drivers/media/video/saa7164/Makefile10
-rw-r--r--drivers/media/video/saa7164/saa7164-cards.c128
-rw-r--r--drivers/media/video/saa7164/saa7164-dvb.c2
-rw-r--r--drivers/media/video/saa7164/saa7164.h2
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c6
-rw-r--r--drivers/media/video/sr030pc30.c6
-rw-r--r--drivers/media/video/stk-webcam.c29
-rw-r--r--drivers/media/video/tlg2300/Makefile8
-rw-r--r--drivers/media/video/tm6000/Kconfig (renamed from drivers/staging/tm6000/Kconfig)0
-rw-r--r--drivers/media/video/tm6000/Makefile (renamed from drivers/staging/tm6000/Makefile)0
-rw-r--r--drivers/media/video/tm6000/tm6000-alsa.c (renamed from drivers/staging/tm6000/tm6000-alsa.c)9
-rw-r--r--drivers/media/video/tm6000/tm6000-cards.c (renamed from drivers/staging/tm6000/tm6000-cards.c)44
-rw-r--r--drivers/media/video/tm6000/tm6000-core.c (renamed from drivers/staging/tm6000/tm6000-core.c)108
-rw-r--r--drivers/media/video/tm6000/tm6000-dvb.c (renamed from drivers/staging/tm6000/tm6000-dvb.c)18
-rw-r--r--drivers/media/video/tm6000/tm6000-i2c.c (renamed from drivers/staging/tm6000/tm6000-i2c.c)21
-rw-r--r--drivers/media/video/tm6000/tm6000-input.c (renamed from drivers/staging/tm6000/tm6000-input.c)2
-rw-r--r--drivers/media/video/tm6000/tm6000-regs.h (renamed from drivers/staging/tm6000/tm6000-regs.h)6
-rw-r--r--drivers/media/video/tm6000/tm6000-stds.c659
-rw-r--r--drivers/media/video/tm6000/tm6000-usb-isoc.h (renamed from drivers/staging/tm6000/tm6000-usb-isoc.h)2
-rw-r--r--drivers/media/video/tm6000/tm6000-video.c (renamed from drivers/staging/tm6000/tm6000-video.c)122
-rw-r--r--drivers/media/video/tm6000/tm6000.h (renamed from drivers/staging/tm6000/tm6000.h)15
-rw-r--r--drivers/media/video/tvaudio.c9
-rw-r--r--drivers/media/video/tvp5150_reg.h17
-rw-r--r--drivers/media/video/tvp7002.c14
-rw-r--r--drivers/media/video/usbvision/Makefile4
-rw-r--r--drivers/media/video/uvc/uvc_driver.c13
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c54
-rw-r--r--drivers/media/video/uvc/uvc_video.c17
-rw-r--r--drivers/media/video/uvc/uvcvideo.h104
-rw-r--r--drivers/media/video/v4l2-ctrls.c104
-rw-r--r--drivers/media/video/v4l2-ioctl.c525
-rw-r--r--drivers/media/video/v4l2-mem2mem.c18
-rw-r--r--drivers/media/video/v4l2-subdev.c19
-rw-r--r--drivers/media/video/via-camera.c4
-rw-r--r--drivers/media/video/videobuf2-core.c205
-rw-r--r--drivers/media/video/videobuf2-dma-contig.c16
-rw-r--r--drivers/media/video/videobuf2-dma-sg.c6
-rw-r--r--drivers/media/video/videobuf2-memops.c6
-rw-r--r--drivers/media/video/vivi.c23
-rw-r--r--drivers/media/video/vpx3220.c2
-rw-r--r--drivers/media/video/zr364xx.c3
-rw-r--r--drivers/message/fusion/mptbase.c92
-rw-r--r--drivers/message/fusion/mptbase.h72
-rw-r--r--drivers/message/fusion/mptsas.c47
-rw-r--r--drivers/message/fusion/mptscsih.c18
-rw-r--r--drivers/message/fusion/mptscsih.h1
-rw-r--r--drivers/mfd/Kconfig3
-rw-r--r--drivers/mfd/menelaus.c2
-rw-r--r--drivers/mfd/twl6040-core.c67
-rw-r--r--drivers/mfd/wm831x-core.c426
-rw-r--r--drivers/mfd/wm831x-i2c.c68
-rw-r--r--drivers/mfd/wm831x-spi.c196
-rw-r--r--drivers/mfd/wm8400-core.c106
-rw-r--r--drivers/mfd/wm8994-core.c205
-rw-r--r--drivers/misc/Kconfig3
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/ad525x_dpot-i2c.c1
-rw-r--r--drivers/misc/altera-stapl/Kconfig (renamed from drivers/staging/altera-stapl/Kconfig)2
-rw-r--r--drivers/misc/altera-stapl/Makefile3
-rw-r--r--drivers/misc/altera-stapl/altera-comp.c (renamed from drivers/staging/altera-stapl/altera-comp.c)0
-rw-r--r--drivers/misc/altera-stapl/altera-exprt.h (renamed from drivers/staging/altera-stapl/altera-exprt.h)0
-rw-r--r--drivers/misc/altera-stapl/altera-jtag.c (renamed from drivers/staging/altera-stapl/altera-jtag.c)2
-rw-r--r--drivers/misc/altera-stapl/altera-jtag.h (renamed from drivers/staging/altera-stapl/altera-jtag.h)0
-rw-r--r--drivers/misc/altera-stapl/altera-lpt.c (renamed from drivers/staging/altera-stapl/altera-lpt.c)0
-rw-r--r--drivers/misc/altera-stapl/altera.c (renamed from drivers/staging/altera-stapl/altera.c)5
-rw-r--r--drivers/misc/fsa9480.c3
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d.c389
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d.h9
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d_i2c.c45
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d_spi.c2
-rw-r--r--drivers/misc/pch_phub.c10
-rw-r--r--drivers/misc/vmw_balloon.c4
-rw-r--r--drivers/mmc/card/block.c310
-rw-r--r--drivers/mmc/card/mmc_test.c65
-rw-r--r--drivers/mmc/card/queue.c8
-rw-r--r--drivers/mmc/card/sdio_uart.c10
-rw-r--r--drivers/mmc/core/bus.c6
-rw-r--r--drivers/mmc/core/core.c426
-rw-r--r--drivers/mmc/core/core.h1
-rw-r--r--drivers/mmc/core/debugfs.c28
-rw-r--r--drivers/mmc/core/host.c11
-rw-r--r--drivers/mmc/core/mmc.c287
-rw-r--r--drivers/mmc/core/mmc_ops.c39
-rw-r--r--drivers/mmc/core/mmc_ops.h1
-rw-r--r--drivers/mmc/core/quirks.c11
-rw-r--r--drivers/mmc/core/sd.c49
-rw-r--r--drivers/mmc/core/sd_ops.c8
-rw-r--r--drivers/mmc/core/sdio.c11
-rw-r--r--drivers/mmc/core/sdio_bus.c2
-rw-r--r--drivers/mmc/core/sdio_cis.c4
-rw-r--r--drivers/mmc/core/sdio_irq.c6
-rw-r--r--drivers/mmc/core/sdio_ops.c9
-rw-r--r--drivers/mmc/host/Kconfig16
-rw-r--r--drivers/mmc/host/at91_mci.c6
-rw-r--r--drivers/mmc/host/atmel-mci-regs.h220
-rw-r--r--drivers/mmc/host/atmel-mci.c823
-rw-r--r--drivers/mmc/host/au1xmmc.c10
-rw-r--r--drivers/mmc/host/davinci_mmc.c13
-rw-r--r--drivers/mmc/host/dw_mmc.c104
-rw-r--r--drivers/mmc/host/dw_mmc.h15
-rw-r--r--drivers/mmc/host/imxmmc.c2
-rw-r--r--drivers/mmc/host/mmc_spi.c1
-rw-r--r--drivers/mmc/host/mmci.c25
-rw-r--r--drivers/mmc/host/msm_sdcc.c86
-rw-r--r--drivers/mmc/host/msm_sdcc.h6
-rw-r--r--drivers/mmc/host/mvsdio.c14
-rw-r--r--drivers/mmc/host/mxcmmc.c3
-rw-r--r--drivers/mmc/host/mxs-mmc.c1
-rw-r--r--drivers/mmc/host/omap.c2
-rw-r--r--drivers/mmc/host/omap_hsmmc.c32
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/s3cmci.c4
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c80
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c19
-rw-r--r--drivers/mmc/host/sdhci-of-hlwd.c1
-rw-r--r--drivers/mmc/host/sdhci-pci.c268
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c1
-rw-r--r--drivers/mmc/host/sdhci-pxav2.c5
-rw-r--r--drivers/mmc/host/sdhci-pxav3.c1
-rw-r--r--drivers/mmc/host/sdhci-s3c.c34
-rw-r--r--drivers/mmc/host/sdhci-spear.c3
-rw-r--r--drivers/mmc/host/sdhci-tegra.c59
-rw-r--r--drivers/mmc/host/sdhci.c358
-rw-r--r--drivers/mmc/host/sdhci.h7
-rw-r--r--drivers/mmc/host/sdricoh_cs.c1
-rw-r--r--drivers/mmc/host/sh_mmcif.c21
-rw-r--r--drivers/mmc/host/sh_mobile_sdhi.c99
-rw-r--r--drivers/mmc/host/tifm_sd.c19
-rw-r--r--drivers/mmc/host/tmio_mmc.c4
-rw-r--r--drivers/mmc/host/tmio_mmc.h7
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c151
-rw-r--r--drivers/mmc/host/via-sdmmc.c3
-rw-r--r--drivers/mmc/host/wbsd.c22
-rw-r--r--drivers/mtd/Kconfig2
-rw-r--r--drivers/mtd/mtdchar.c2
-rw-r--r--drivers/mtd/nand/ams-delta.c2
-rw-r--r--drivers/mtd/onenand/omap2.c2
-rw-r--r--drivers/net/Kconfig3390
-rw-r--r--drivers/net/Makefile326
-rw-r--r--drivers/net/appletalk/cops.c2
-rw-r--r--drivers/net/appletalk/ltpc.c2
-rw-r--r--drivers/net/arcnet/Kconfig14
-rw-r--r--drivers/net/arcnet/Makefile1
-rw-r--r--drivers/net/arcnet/com20020.c2
-rw-r--r--drivers/net/arcnet/com20020_cs.c (renamed from drivers/net/pcmcia/com20020_cs.c)0
-rw-r--r--drivers/net/arm/Kconfig74
-rw-r--r--drivers/net/arm/Makefile14
-rw-r--r--drivers/net/benet/Kconfig6
-rw-r--r--drivers/net/bna/bfa_ioc_ct.c516
-rw-r--r--drivers/net/bna/bfi_ctreg.h646
-rw-r--r--drivers/net/bna/bfi_ll.h438
-rw-r--r--drivers/net/bna/bna_ctrl.c3076
-rw-r--r--drivers/net/bna/bna_hw.h1490
-rw-r--r--drivers/net/bna/bna_txrx.c4185
-rw-r--r--drivers/net/bonding/bond_3ad.c15
-rw-r--r--drivers/net/bonding/bond_alb.c16
-rw-r--r--drivers/net/bonding/bond_main.c172
-rw-r--r--drivers/net/bonding/bond_sysfs.c46
-rw-r--r--drivers/net/bonding/bonding.h9
-rw-r--r--drivers/net/caif/caif_hsi.c436
-rw-r--r--drivers/net/caif/caif_spi.c4
-rw-r--r--drivers/net/can/at91_can.c2
-rw-r--r--drivers/net/can/dev.c14
-rw-r--r--drivers/net/can/flexcan.c189
-rw-r--r--drivers/net/can/mscan/mscan.c26
-rw-r--r--drivers/net/can/sja1000/Kconfig14
-rw-r--r--drivers/net/can/sja1000/Makefile2
-rw-r--r--drivers/net/can/sja1000/ems_pcmcia.c331
-rw-r--r--drivers/net/can/sja1000/peak_pci.c291
-rw-r--r--drivers/net/can/sja1000/sja1000.c2
-rw-r--r--drivers/net/can/sja1000/sja1000.h2
-rw-r--r--drivers/net/can/sja1000/sja1000_of_platform.c2
-rw-r--r--drivers/net/can/slcan.c2
-rw-r--r--drivers/net/can/vcan.c2
-rw-r--r--drivers/net/cris/eth_v10.c2
-rw-r--r--drivers/net/dummy.c2
-rw-r--r--drivers/net/ethernet/3com/3c501.c (renamed from drivers/net/3c501.c)2
-rw-r--r--drivers/net/ethernet/3com/3c501.h (renamed from drivers/net/3c501.h)0
-rw-r--r--drivers/net/ethernet/3com/3c509.c (renamed from drivers/net/3c509.c)2
-rw-r--r--drivers/net/ethernet/3com/3c515.c (renamed from drivers/net/3c515.c)2
-rw-r--r--drivers/net/ethernet/3com/3c574_cs.c (renamed from drivers/net/pcmcia/3c574_cs.c)2
-rw-r--r--drivers/net/ethernet/3com/3c589_cs.c (renamed from drivers/net/pcmcia/3c589_cs.c)2
-rw-r--r--drivers/net/ethernet/3com/3c59x.c (renamed from drivers/net/3c59x.c)15
-rw-r--r--drivers/net/ethernet/3com/Kconfig122
-rw-r--r--drivers/net/ethernet/3com/Makefile11
-rw-r--r--drivers/net/ethernet/3com/typhoon.c (renamed from drivers/net/typhoon.c)15
-rw-r--r--drivers/net/ethernet/3com/typhoon.h (renamed from drivers/net/typhoon.h)0
-rw-r--r--drivers/net/ethernet/8390/3c503.c (renamed from drivers/net/3c503.c)2
-rw-r--r--drivers/net/ethernet/8390/3c503.h (renamed from drivers/net/3c503.h)0
-rw-r--r--drivers/net/ethernet/8390/8390.c (renamed from drivers/net/8390.c)2
-rw-r--r--drivers/net/ethernet/8390/8390.h (renamed from drivers/net/8390.h)0
-rw-r--r--drivers/net/ethernet/8390/8390p.c (renamed from drivers/net/8390p.c)2
-rw-r--r--drivers/net/ethernet/8390/Kconfig337
-rw-r--r--drivers/net/ethernet/8390/Makefile29
-rw-r--r--drivers/net/ethernet/8390/ac3200.c (renamed from drivers/net/ac3200.c)2
-rw-r--r--drivers/net/ethernet/8390/apne.c (renamed from drivers/net/apne.c)0
-rw-r--r--drivers/net/ethernet/8390/ax88796.c (renamed from drivers/net/ax88796.c)2
-rw-r--r--drivers/net/ethernet/8390/axnet_cs.c (renamed from drivers/net/pcmcia/axnet_cs.c)4
-rw-r--r--drivers/net/ethernet/8390/e2100.c (renamed from drivers/net/e2100.c)2
-rw-r--r--drivers/net/ethernet/8390/es3210.c (renamed from drivers/net/es3210.c)0
-rw-r--r--drivers/net/ethernet/8390/etherh.c (renamed from drivers/net/arm/etherh.c)4
-rw-r--r--drivers/net/ethernet/8390/hp-plus.c (renamed from drivers/net/hp-plus.c)2
-rw-r--r--drivers/net/ethernet/8390/hp.c (renamed from drivers/net/hp.c)0
-rw-r--r--drivers/net/ethernet/8390/hydra.c (renamed from drivers/net/hydra.c)2
-rw-r--r--drivers/net/ethernet/8390/lib8390.c (renamed from drivers/net/lib8390.c)0
-rw-r--r--drivers/net/ethernet/8390/lne390.c (renamed from drivers/net/lne390.c)0
-rw-r--r--drivers/net/ethernet/8390/mac8390.c (renamed from drivers/net/mac8390.c)2
-rw-r--r--drivers/net/ethernet/8390/ne-h8300.c (renamed from drivers/net/ne-h8300.c)2
-rw-r--r--drivers/net/ethernet/8390/ne.c (renamed from drivers/net/ne.c)0
-rw-r--r--drivers/net/ethernet/8390/ne2.c (renamed from drivers/net/ne2.c)0
-rw-r--r--drivers/net/ethernet/8390/ne2k-pci.c (renamed from drivers/net/ne2k-pci.c)2
-rw-r--r--drivers/net/ethernet/8390/ne3210.c (renamed from drivers/net/ne3210.c)0
-rw-r--r--drivers/net/ethernet/8390/pcnet_cs.c (renamed from drivers/net/pcmcia/pcnet_cs.c)4
-rw-r--r--drivers/net/ethernet/8390/smc-mca.c (renamed from drivers/net/smc-mca.c)2
-rw-r--r--drivers/net/ethernet/8390/smc-ultra.c (renamed from drivers/net/smc-ultra.c)2
-rw-r--r--drivers/net/ethernet/8390/smc-ultra32.c (renamed from drivers/net/smc-ultra32.c)2
-rw-r--r--drivers/net/ethernet/8390/stnic.c (renamed from drivers/net/stnic.c)0
-rw-r--r--drivers/net/ethernet/8390/wd.c (renamed from drivers/net/wd.c)2
-rw-r--r--drivers/net/ethernet/8390/zorro8390.c (renamed from drivers/net/zorro8390.c)2
-rw-r--r--drivers/net/ethernet/Kconfig177
-rw-r--r--drivers/net/ethernet/Makefile74
-rw-r--r--drivers/net/ethernet/adaptec/Kconfig36
-rw-r--r--drivers/net/ethernet/adaptec/Makefile5
-rw-r--r--drivers/net/ethernet/adaptec/starfire.c (renamed from drivers/net/starfire.c)13
-rw-r--r--drivers/net/ethernet/adi/Kconfig69
-rw-r--r--drivers/net/ethernet/adi/Makefile5
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.c (renamed from drivers/net/bfin_mac.c)2
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.h (renamed from drivers/net/bfin_mac.h)0
-rw-r--r--drivers/net/ethernet/aeroflex/Kconfig11
-rw-r--r--drivers/net/ethernet/aeroflex/Makefile5
-rw-r--r--drivers/net/ethernet/aeroflex/greth.c (renamed from drivers/net/greth.c)20
-rw-r--r--drivers/net/ethernet/aeroflex/greth.h (renamed from drivers/net/greth.h)0
-rw-r--r--drivers/net/ethernet/alteon/Kconfig48
-rw-r--r--drivers/net/ethernet/alteon/Makefile5
-rw-r--r--drivers/net/ethernet/alteon/acenic.c (renamed from drivers/net/acenic.c)16
-rw-r--r--drivers/net/ethernet/alteon/acenic.h (renamed from drivers/net/acenic.h)0
-rw-r--r--drivers/net/ethernet/amd/7990.c (renamed from drivers/net/7990.c)0
-rw-r--r--drivers/net/ethernet/amd/7990.h (renamed from drivers/net/7990.h)0
-rw-r--r--drivers/net/ethernet/amd/Kconfig195
-rw-r--r--drivers/net/ethernet/amd/Makefile20
-rw-r--r--drivers/net/ethernet/amd/a2065.c (renamed from drivers/net/a2065.c)2
-rw-r--r--drivers/net/ethernet/amd/a2065.h (renamed from drivers/net/a2065.h)0
-rw-r--r--drivers/net/ethernet/amd/am79c961a.c (renamed from drivers/net/arm/am79c961a.c)2
-rw-r--r--drivers/net/ethernet/amd/am79c961a.h (renamed from drivers/net/arm/am79c961a.h)0
-rw-r--r--drivers/net/ethernet/amd/amd8111e.c (renamed from drivers/net/amd8111e.c)2
-rw-r--r--drivers/net/ethernet/amd/amd8111e.h (renamed from drivers/net/amd8111e.h)0
-rw-r--r--drivers/net/ethernet/amd/ariadne.c (renamed from drivers/net/ariadne.c)2
-rw-r--r--drivers/net/ethernet/amd/ariadne.h (renamed from drivers/net/ariadne.h)0
-rw-r--r--drivers/net/ethernet/amd/atarilance.c (renamed from drivers/net/atarilance.c)2
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c (renamed from drivers/net/au1000_eth.c)2
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.h (renamed from drivers/net/au1000_eth.h)0
-rw-r--r--drivers/net/ethernet/amd/declance.c (renamed from drivers/net/declance.c)2
-rw-r--r--drivers/net/ethernet/amd/depca.c (renamed from drivers/net/depca.c)2
-rw-r--r--drivers/net/ethernet/amd/depca.h (renamed from drivers/net/depca.h)2
-rw-r--r--drivers/net/ethernet/amd/hplance.c (renamed from drivers/net/hplance.c)2
-rw-r--r--drivers/net/ethernet/amd/hplance.h (renamed from drivers/net/hplance.h)0
-rw-r--r--drivers/net/ethernet/amd/lance.c (renamed from drivers/net/lance.c)2
-rw-r--r--drivers/net/ethernet/amd/mvme147.c (renamed from drivers/net/mvme147.c)2
-rw-r--r--drivers/net/ethernet/amd/ni65.c (renamed from drivers/net/ni65.c)2
-rw-r--r--drivers/net/ethernet/amd/ni65.h (renamed from drivers/net/ni65.h)0
-rw-r--r--drivers/net/ethernet/amd/nmclan_cs.c (renamed from drivers/net/pcmcia/nmclan_cs.c)2
-rw-r--r--drivers/net/ethernet/amd/pcnet32.c (renamed from drivers/net/pcnet32.c)204
-rw-r--r--drivers/net/ethernet/amd/sun3lance.c (renamed from drivers/net/sun3lance.c)2
-rw-r--r--drivers/net/ethernet/amd/sunlance.c (renamed from drivers/net/sunlance.c)2
-rw-r--r--drivers/net/ethernet/apple/Kconfig77
-rw-r--r--drivers/net/ethernet/apple/Makefile8
-rw-r--r--drivers/net/ethernet/apple/bmac.c (renamed from drivers/net/bmac.c)2
-rw-r--r--drivers/net/ethernet/apple/bmac.h (renamed from drivers/net/bmac.h)0
-rw-r--r--drivers/net/ethernet/apple/mac89x0.c (renamed from drivers/net/mac89x0.c)2
-rw-r--r--drivers/net/ethernet/apple/mace.c (renamed from drivers/net/mace.c)2
-rw-r--r--drivers/net/ethernet/apple/mace.h (renamed from drivers/net/mace.h)0
-rw-r--r--drivers/net/ethernet/apple/macmace.c (renamed from drivers/net/macmace.c)11
-rw-r--r--drivers/net/ethernet/atheros/Kconfig70
-rw-r--r--drivers/net/ethernet/atheros/Makefile8
-rw-r--r--drivers/net/ethernet/atheros/atl1c/Makefile (renamed from drivers/net/atl1c/Makefile)0
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c.h (renamed from drivers/net/atl1c/atl1c.h)0
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c (renamed from drivers/net/atl1c/atl1c_ethtool.c)0
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.c (renamed from drivers/net/atl1c/atl1c_hw.c)0
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.h (renamed from drivers/net/atl1c/atl1c_hw.h)0
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c (renamed from drivers/net/atl1c/atl1c_main.c)13
-rw-r--r--drivers/net/ethernet/atheros/atl1e/Makefile (renamed from drivers/net/atl1e/Makefile)0
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e.h (renamed from drivers/net/atl1e/atl1e.h)0
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c (renamed from drivers/net/atl1e/atl1e_ethtool.c)0
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_hw.c (renamed from drivers/net/atl1e/atl1e_hw.c)0
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_hw.h (renamed from drivers/net/atl1e/atl1e_hw.h)0
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_main.c (renamed from drivers/net/atl1e/atl1e_main.c)19
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_param.c (renamed from drivers/net/atl1e/atl1e_param.c)0
-rw-r--r--drivers/net/ethernet/atheros/atlx/Makefile (renamed from drivers/net/atlx/Makefile)0
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c (renamed from drivers/net/atlx/atl1.c)27
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.h (renamed from drivers/net/atlx/atl1.h)0
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.c (renamed from drivers/net/atlx/atl2.c)2
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.h (renamed from drivers/net/atlx/atl2.h)0
-rw-r--r--drivers/net/ethernet/atheros/atlx/atlx.c (renamed from drivers/net/atlx/atlx.c)0
-rw-r--r--drivers/net/ethernet/atheros/atlx/atlx.h (renamed from drivers/net/atlx/atlx.h)0
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig122
-rw-r--r--drivers/net/ethernet/broadcom/Makefile11
-rw-r--r--drivers/net/ethernet/broadcom/b44.c (renamed from drivers/net/b44.c)2
-rw-r--r--drivers/net/ethernet/broadcom/b44.h (renamed from drivers/net/b44.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.c (renamed from drivers/net/bcm63xx_enet.c)4
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.h (renamed from drivers/net/bcm63xx_enet.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c (renamed from drivers/net/bnx2.c)94
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.h (renamed from drivers/net/bnx2.h)12
-rw-r--r--drivers/net/ethernet/broadcom/bnx2_fw.h (renamed from drivers/net/bnx2_fw.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/Makefile (renamed from drivers/net/bnx2x/Makefile)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h (renamed from drivers/net/bnx2x/bnx2x.h)71
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c (renamed from drivers/net/bnx2x/bnx2x_cmn.c)65
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h (renamed from drivers/net/bnx2x/bnx2x_cmn.h)10
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c (renamed from drivers/net/bnx2x/bnx2x_dcb.c)5
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h (renamed from drivers/net/bnx2x/bnx2x_dcb.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h (renamed from drivers/net/bnx2x/bnx2x_dump.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c (renamed from drivers/net/bnx2x/bnx2x_ethtool.c)31
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h (renamed from drivers/net/bnx2x/bnx2x_fw_defs.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h (renamed from drivers/net/bnx2x/bnx2x_fw_file_hdr.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h (renamed from drivers/net/bnx2x/bnx2x_hsi.h)4
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h (renamed from drivers/net/bnx2x/bnx2x_init.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h (renamed from drivers/net/bnx2x/bnx2x_init_ops.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c (renamed from drivers/net/bnx2x/bnx2x_link.c)367
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h (renamed from drivers/net/bnx2x/bnx2x_link.h)3
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c (renamed from drivers/net/bnx2x/bnx2x_main.c)81
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h (renamed from drivers/net/bnx2x/bnx2x_reg.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c (renamed from drivers/net/bnx2x/bnx2x_sp.c)67
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h (renamed from drivers/net/bnx2x/bnx2x_sp.h)0
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c (renamed from drivers/net/bnx2x/bnx2x_stats.c)46
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h (renamed from drivers/net/bnx2x/bnx2x_stats.h)0
-rw-r--r--drivers/net/ethernet/broadcom/cnic.c (renamed from drivers/net/cnic.c)35
-rw-r--r--drivers/net/ethernet/broadcom/cnic.h (renamed from drivers/net/cnic.h)4
-rw-r--r--drivers/net/ethernet/broadcom/cnic_defs.h (renamed from drivers/net/cnic_defs.h)1
-rw-r--r--drivers/net/ethernet/broadcom/cnic_if.h (renamed from drivers/net/cnic_if.h)0
-rw-r--r--drivers/net/ethernet/broadcom/sb1250-mac.c (renamed from drivers/net/sb1250-mac.c)2
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c (renamed from drivers/net/tg3.c)1444
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h (renamed from drivers/net/tg3.h)4
-rw-r--r--drivers/net/ethernet/brocade/Kconfig23
-rw-r--r--drivers/net/ethernet/brocade/Makefile5
-rw-r--r--drivers/net/ethernet/brocade/bna/Kconfig17
-rw-r--r--drivers/net/ethernet/brocade/bna/Makefile (renamed from drivers/net/bna/Makefile)5
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_cee.c (renamed from drivers/net/bna/bfa_cee.c)5
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_cee.h (renamed from drivers/net/bna/bfa_cee.h)0
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_cs.h (renamed from drivers/net/bna/bfa_cs.h)0
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_defs.h (renamed from drivers/net/bna/bfa_defs.h)64
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_defs_cna.h (renamed from drivers/net/bna/bfa_defs_cna.h)8
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h (renamed from drivers/net/bna/bfa_defs_mfg_comm.h)69
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_defs_status.h (renamed from drivers/net/bna/bfa_defs_status.h)0
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.c (renamed from drivers/net/bna/bfa_ioc.c)459
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.h (renamed from drivers/net/bna/bfa_ioc.h)68
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c878
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_msgq.c669
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_msgq.h130
-rw-r--r--drivers/net/ethernet/brocade/bna/bfi.h (renamed from drivers/net/bna/bfi.h)257
-rw-r--r--drivers/net/ethernet/brocade/bna/bfi_cna.h (renamed from drivers/net/bna/bfi_cna.h)0
-rw-r--r--drivers/net/ethernet/brocade/bna/bfi_enet.h901
-rw-r--r--drivers/net/ethernet/brocade/bna/bfi_reg.h452
-rw-r--r--drivers/net/ethernet/brocade/bna/bna.h (renamed from drivers/net/bna/bna.h)351
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_enet.c2144
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_hw_defs.h422
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_tx_rx.c3798
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_types.h (renamed from drivers/net/bna/bna_types.h)656
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c (renamed from drivers/net/bna/bnad.c)1178
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.h (renamed from drivers/net/bna/bnad.h)101
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_ethtool.c (renamed from drivers/net/bna/bnad_ethtool.c)490
-rw-r--r--drivers/net/ethernet/brocade/bna/cna.h (renamed from drivers/net/bna/cna.h)43
-rw-r--r--drivers/net/ethernet/brocade/bna/cna_fwimg.c (renamed from drivers/net/bna/cna_fwimg.c)48
-rw-r--r--drivers/net/ethernet/cadence/Kconfig45
-rw-r--r--drivers/net/ethernet/cadence/Makefile6
-rw-r--r--drivers/net/ethernet/cadence/at91_ether.c (renamed from drivers/net/arm/at91_ether.c)4
-rw-r--r--drivers/net/ethernet/cadence/at91_ether.h (renamed from drivers/net/arm/at91_ether.h)0
-rw-r--r--drivers/net/ethernet/cadence/macb.c (renamed from drivers/net/macb.c)2
-rw-r--r--drivers/net/ethernet/cadence/macb.h (renamed from drivers/net/macb.h)0
-rw-r--r--drivers/net/ethernet/chelsio/Kconfig107
-rw-r--r--drivers/net/ethernet/chelsio/Makefile8
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/Makefile (renamed from drivers/net/chelsio/Makefile)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/common.h (renamed from drivers/net/chelsio/common.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/cphy.h (renamed from drivers/net/chelsio/cphy.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/cpl5_cmd.h (renamed from drivers/net/chelsio/cpl5_cmd.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/cxgb2.c (renamed from drivers/net/chelsio/cxgb2.c)4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/elmer0.h (renamed from drivers/net/chelsio/elmer0.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/espi.c (renamed from drivers/net/chelsio/espi.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/espi.h (renamed from drivers/net/chelsio/espi.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/fpga_defs.h (renamed from drivers/net/chelsio/fpga_defs.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/gmac.h (renamed from drivers/net/chelsio/gmac.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/mv88e1xxx.c (renamed from drivers/net/chelsio/mv88e1xxx.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/mv88e1xxx.h (renamed from drivers/net/chelsio/mv88e1xxx.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/mv88x201x.c (renamed from drivers/net/chelsio/mv88x201x.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/my3126.c (renamed from drivers/net/chelsio/my3126.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/pm3393.c (renamed from drivers/net/chelsio/pm3393.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/regs.h (renamed from drivers/net/chelsio/regs.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/sge.c (renamed from drivers/net/chelsio/sge.c)13
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/sge.h (renamed from drivers/net/chelsio/sge.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/subr.c (renamed from drivers/net/chelsio/subr.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/suni1x10gexp_regs.h (renamed from drivers/net/chelsio/suni1x10gexp_regs.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/tp.c (renamed from drivers/net/chelsio/tp.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/tp.h (renamed from drivers/net/chelsio/tp.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/vsc7326.c (renamed from drivers/net/chelsio/vsc7326.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/vsc7326_reg.h (renamed from drivers/net/chelsio/vsc7326_reg.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/Makefile (renamed from drivers/net/cxgb3/Makefile)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/adapter.h (renamed from drivers/net/cxgb3/adapter.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/ael1002.c (renamed from drivers/net/cxgb3/ael1002.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/aq100x.c (renamed from drivers/net/cxgb3/aq100x.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/common.h (renamed from drivers/net/cxgb3/common.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_ctl_defs.h (renamed from drivers/net/cxgb3/cxgb3_ctl_defs.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_defs.h (renamed from drivers/net/cxgb3/cxgb3_defs.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_ioctl.h (renamed from drivers/net/cxgb3/cxgb3_ioctl.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c (renamed from drivers/net/cxgb3/cxgb3_main.c)3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c (renamed from drivers/net/cxgb3/cxgb3_offload.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.h (renamed from drivers/net/cxgb3/cxgb3_offload.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/firmware_exports.h (renamed from drivers/net/cxgb3/firmware_exports.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/l2t.c (renamed from drivers/net/cxgb3/l2t.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/l2t.h (renamed from drivers/net/cxgb3/l2t.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/mc5.c (renamed from drivers/net/cxgb3/mc5.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/regs.h (renamed from drivers/net/cxgb3/regs.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/sge.c (renamed from drivers/net/cxgb3/sge.c)16
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/sge_defs.h (renamed from drivers/net/cxgb3/sge_defs.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/t3_cpl.h (renamed from drivers/net/cxgb3/t3_cpl.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/t3_hw.c (renamed from drivers/net/cxgb3/t3_hw.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/t3cdev.h (renamed from drivers/net/cxgb3/t3cdev.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/version.h (renamed from drivers/net/cxgb3/version.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/vsc8211.c (renamed from drivers/net/cxgb3/vsc8211.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/xgmac.c (renamed from drivers/net/cxgb3/xgmac.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/Makefile (renamed from drivers/net/cxgb4/Makefile)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h (renamed from drivers/net/cxgb4/cxgb4.h)2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c (renamed from drivers/net/cxgb4/cxgb4_main.c)5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h (renamed from drivers/net/cxgb4/cxgb4_uld.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.c (renamed from drivers/net/cxgb4/l2t.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.h (renamed from drivers/net/cxgb4/l2t.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c (renamed from drivers/net/cxgb4/sge.c)49
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c (renamed from drivers/net/cxgb4/t4_hw.c)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.h (renamed from drivers/net/cxgb4/t4_hw.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_msg.h (renamed from drivers/net/cxgb4/t4_msg.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_regs.h (renamed from drivers/net/cxgb4/t4_regs.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h (renamed from drivers/net/cxgb4/t4fw_api.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/Makefile (renamed from drivers/net/cxgb4vf/Makefile)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/adapter.h (renamed from drivers/net/cxgb4vf/adapter.h)2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c (renamed from drivers/net/cxgb4vf/cxgb4vf_main.c)2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/sge.c (renamed from drivers/net/cxgb4vf/sge.c)94
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h (renamed from drivers/net/cxgb4vf/t4vf_common.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/t4vf_defs.h (renamed from drivers/net/cxgb4vf/t4vf_defs.h)0
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c (renamed from drivers/net/cxgb4vf/t4vf_hw.c)0
-rw-r--r--drivers/net/ethernet/cirrus/Kconfig50
-rw-r--r--drivers/net/ethernet/cirrus/Makefile6
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.c (renamed from drivers/net/cs89x0.c)2
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.h (renamed from drivers/net/cs89x0.h)0
-rw-r--r--drivers/net/ethernet/cirrus/ep93xx_eth.c (renamed from drivers/net/arm/ep93xx_eth.c)0
-rw-r--r--drivers/net/ethernet/cisco/Kconfig23
-rw-r--r--drivers/net/ethernet/cisco/Makefile5
-rw-r--r--drivers/net/ethernet/cisco/enic/Kconfig9
-rw-r--r--drivers/net/ethernet/cisco/enic/Makefile (renamed from drivers/net/enic/Makefile)0
-rw-r--r--drivers/net/ethernet/cisco/enic/cq_desc.h (renamed from drivers/net/enic/cq_desc.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/cq_enet_desc.h (renamed from drivers/net/enic/cq_enet_desc.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h (renamed from drivers/net/enic/enic.h)15
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_dev.c (renamed from drivers/net/enic/enic_dev.c)0
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_dev.h (renamed from drivers/net/enic/enic_dev.h)19
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c (renamed from drivers/net/enic/enic_main.c)202
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_pp.c (renamed from drivers/net/enic/enic_pp.c)192
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_pp.h (renamed from drivers/net/enic/enic_pp.h)15
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_res.c (renamed from drivers/net/enic/enic_res.c)0
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_res.h (renamed from drivers/net/enic/enic_res.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/rq_enet_desc.h (renamed from drivers/net/enic/rq_enet_desc.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_cq.c (renamed from drivers/net/enic/vnic_cq.c)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_cq.h (renamed from drivers/net/enic/vnic_cq.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_dev.c (renamed from drivers/net/enic/vnic_dev.c)28
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_dev.h (renamed from drivers/net/enic/vnic_dev.h)2
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_devcmd.h (renamed from drivers/net/enic/vnic_devcmd.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_enet.h (renamed from drivers/net/enic/vnic_enet.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_intr.c (renamed from drivers/net/enic/vnic_intr.c)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_intr.h (renamed from drivers/net/enic/vnic_intr.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_nic.h (renamed from drivers/net/enic/vnic_nic.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_resource.h (renamed from drivers/net/enic/vnic_resource.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_rq.c (renamed from drivers/net/enic/vnic_rq.c)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_rq.h (renamed from drivers/net/enic/vnic_rq.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_rss.h (renamed from drivers/net/enic/vnic_rss.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_stats.h (renamed from drivers/net/enic/vnic_stats.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_vic.c (renamed from drivers/net/enic/vnic_vic.c)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_vic.h (renamed from drivers/net/enic/vnic_vic.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_wq.c (renamed from drivers/net/enic/vnic_wq.c)0
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_wq.h (renamed from drivers/net/enic/vnic_wq.h)0
-rw-r--r--drivers/net/ethernet/cisco/enic/wq_enet_desc.h (renamed from drivers/net/enic/wq_enet_desc.h)0
-rw-r--r--drivers/net/ethernet/davicom/Kconfig24
-rw-r--r--drivers/net/ethernet/davicom/Makefile5
-rw-r--r--drivers/net/ethernet/davicom/dm9000.c (renamed from drivers/net/dm9000.c)13
-rw-r--r--drivers/net/ethernet/davicom/dm9000.h (renamed from drivers/net/dm9000.h)0
-rw-r--r--drivers/net/ethernet/dec/Kconfig37
-rw-r--r--drivers/net/ethernet/dec/Makefile6
-rw-r--r--drivers/net/ethernet/dec/ewrk3.c (renamed from drivers/net/ewrk3.c)2
-rw-r--r--drivers/net/ethernet/dec/ewrk3.h (renamed from drivers/net/ewrk3.h)0
-rw-r--r--drivers/net/ethernet/dec/tulip/21142.c (renamed from drivers/net/tulip/21142.c)3
-rw-r--r--drivers/net/ethernet/dec/tulip/Kconfig (renamed from drivers/net/tulip/Kconfig)21
-rw-r--r--drivers/net/ethernet/dec/tulip/Makefile (renamed from drivers/net/tulip/Makefile)0
-rw-r--r--drivers/net/ethernet/dec/tulip/de2104x.c (renamed from drivers/net/tulip/de2104x.c)2
-rw-r--r--drivers/net/ethernet/dec/tulip/de4x5.c (renamed from drivers/net/tulip/de4x5.c)2
-rw-r--r--drivers/net/ethernet/dec/tulip/de4x5.h (renamed from drivers/net/tulip/de4x5.h)2
-rw-r--r--drivers/net/ethernet/dec/tulip/dmfe.c (renamed from drivers/net/tulip/dmfe.c)2
-rw-r--r--drivers/net/ethernet/dec/tulip/eeprom.c (renamed from drivers/net/tulip/eeprom.c)2
-rw-r--r--drivers/net/ethernet/dec/tulip/interrupt.c (renamed from drivers/net/tulip/interrupt.c)3
-rw-r--r--drivers/net/ethernet/dec/tulip/media.c (renamed from drivers/net/tulip/media.c)3
-rw-r--r--drivers/net/ethernet/dec/tulip/pnic.c (renamed from drivers/net/tulip/pnic.c)3
-rw-r--r--drivers/net/ethernet/dec/tulip/pnic2.c (renamed from drivers/net/tulip/pnic2.c)3
-rw-r--r--drivers/net/ethernet/dec/tulip/timer.c (renamed from drivers/net/tulip/timer.c)3
-rw-r--r--drivers/net/ethernet/dec/tulip/tulip.h (renamed from drivers/net/tulip/tulip.h)3
-rw-r--r--drivers/net/ethernet/dec/tulip/tulip_core.c (renamed from drivers/net/tulip/tulip_core.c)5
-rw-r--r--drivers/net/ethernet/dec/tulip/uli526x.c (renamed from drivers/net/tulip/uli526x.c)2
-rw-r--r--drivers/net/ethernet/dec/tulip/winbond-840.c (renamed from drivers/net/tulip/winbond-840.c)2
-rw-r--r--drivers/net/ethernet/dec/tulip/xircom_cb.c (renamed from drivers/net/tulip/xircom_cb.c)0
-rw-r--r--drivers/net/ethernet/dlink/Kconfig86
-rw-r--r--drivers/net/ethernet/dlink/Makefile8
-rw-r--r--drivers/net/ethernet/dlink/de600.c (renamed from drivers/net/de600.c)0
-rw-r--r--drivers/net/ethernet/dlink/de600.h (renamed from drivers/net/de600.h)0
-rw-r--r--drivers/net/ethernet/dlink/de620.c (renamed from drivers/net/de620.c)2
-rw-r--r--drivers/net/ethernet/dlink/de620.h (renamed from drivers/net/de620.h)0
-rw-r--r--drivers/net/ethernet/dlink/dl2k.c (renamed from drivers/net/dl2k.c)107
-rw-r--r--drivers/net/ethernet/dlink/dl2k.h (renamed from drivers/net/dl2k.h)110
-rw-r--r--drivers/net/ethernet/dlink/sundance.c (renamed from drivers/net/sundance.c)2
-rw-r--r--drivers/net/ethernet/dnet.c (renamed from drivers/net/dnet.c)0
-rw-r--r--drivers/net/ethernet/dnet.h (renamed from drivers/net/dnet.h)0
-rw-r--r--drivers/net/ethernet/emulex/Kconfig23
-rw-r--r--drivers/net/ethernet/emulex/Makefile5
-rw-r--r--drivers/net/ethernet/emulex/benet/Kconfig6
-rw-r--r--drivers/net/ethernet/emulex/benet/Makefile (renamed from drivers/net/benet/Makefile)0
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h (renamed from drivers/net/benet/be.h)132
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c (renamed from drivers/net/benet/be_cmds.c)687
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h (renamed from drivers/net/benet/be_cmds.h)104
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c (renamed from drivers/net/benet/be_ethtool.c)168
-rw-r--r--drivers/net/ethernet/emulex/benet/be_hw.h (renamed from drivers/net/benet/be_hw.h)21
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c (renamed from drivers/net/benet/be_main.c)943
-rw-r--r--drivers/net/ethernet/ethoc.c (renamed from drivers/net/ethoc.c)2
-rw-r--r--drivers/net/ethernet/faraday/Kconfig40
-rw-r--r--drivers/net/ethernet/faraday/Makefile6
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.c (renamed from drivers/net/ftgmac100.c)4
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.h (renamed from drivers/net/ftgmac100.h)0
-rw-r--r--drivers/net/ethernet/faraday/ftmac100.c (renamed from drivers/net/ftmac100.c)5
-rw-r--r--drivers/net/ethernet/faraday/ftmac100.h (renamed from drivers/net/ftmac100.h)0
-rw-r--r--drivers/net/ethernet/fealnx.c (renamed from drivers/net/fealnx.c)2
-rw-r--r--drivers/net/ethernet/freescale/Kconfig88
-rw-r--r--drivers/net/ethernet/freescale/Makefile18
-rw-r--r--drivers/net/ethernet/freescale/fec.c (renamed from drivers/net/fec.c)117
-rw-r--r--drivers/net/ethernet/freescale/fec.h (renamed from drivers/net/fec.h)0
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c (renamed from drivers/net/fec_mpc52xx.c)2
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.h (renamed from drivers/net/fec_mpc52xx.h)0
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx_phy.c (renamed from drivers/net/fec_mpc52xx_phy.c)0
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/Kconfig (renamed from drivers/net/fs_enet/Kconfig)3
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/Makefile (renamed from drivers/net/fs_enet/Makefile)0
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fec.h (renamed from drivers/net/fs_enet/fec.h)0
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c (renamed from drivers/net/fs_enet/fs_enet-main.c)2
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet.h (renamed from drivers/net/fs_enet/fs_enet.h)0
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-fcc.c (renamed from drivers/net/fs_enet/mac-fcc.c)0
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-fec.c (renamed from drivers/net/fs_enet/mac-fec.c)0
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-scc.c (renamed from drivers/net/fs_enet/mac-scc.c)0
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c (renamed from drivers/net/fs_enet/mii-bitbang.c)0
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mii-fec.c (renamed from drivers/net/fs_enet/mii-fec.c)0
-rw-r--r--drivers/net/ethernet/freescale/fsl_pq_mdio.c (renamed from drivers/net/fsl_pq_mdio.c)0
-rw-r--r--drivers/net/ethernet/freescale/fsl_pq_mdio.h (renamed from drivers/net/fsl_pq_mdio.h)0
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c (renamed from drivers/net/gianfar.c)12
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h (renamed from drivers/net/gianfar.h)0
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c (renamed from drivers/net/gianfar_ethtool.c)5
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ptp.c (renamed from drivers/net/gianfar_ptp.c)0
-rw-r--r--drivers/net/ethernet/freescale/gianfar_sysfs.c (renamed from drivers/net/gianfar_sysfs.c)0
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.c (renamed from drivers/net/ucc_geth.c)12
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.h (renamed from drivers/net/ucc_geth.h)0
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth_ethtool.c (renamed from drivers/net/ucc_geth_ethtool.c)0
-rw-r--r--drivers/net/ethernet/fujitsu/Kconfig54
-rw-r--r--drivers/net/ethernet/fujitsu/Makefile7
-rw-r--r--drivers/net/ethernet/fujitsu/at1700.c (renamed from drivers/net/at1700.c)2
-rw-r--r--drivers/net/ethernet/fujitsu/eth16i.c (renamed from drivers/net/eth16i.c)2
-rw-r--r--drivers/net/ethernet/fujitsu/fmvj18x_cs.c (renamed from drivers/net/pcmcia/fmvj18x_cs.c)2
-rw-r--r--drivers/net/ethernet/hp/Kconfig32
-rw-r--r--drivers/net/ethernet/hp/Makefile5
-rw-r--r--drivers/net/ethernet/hp/hp100.c (renamed from drivers/net/hp100.c)4
-rw-r--r--drivers/net/ethernet/hp/hp100.h (renamed from drivers/net/hp100.h)0
-rw-r--r--drivers/net/ethernet/i825xx/3c505.c (renamed from drivers/net/3c505.c)2
-rw-r--r--drivers/net/ethernet/i825xx/3c505.h (renamed from drivers/net/3c505.h)0
-rw-r--r--drivers/net/ethernet/i825xx/3c507.c (renamed from drivers/net/3c507.c)0
-rw-r--r--drivers/net/ethernet/i825xx/3c523.c (renamed from drivers/net/3c523.c)2
-rw-r--r--drivers/net/ethernet/i825xx/3c523.h (renamed from drivers/net/3c523.h)0
-rw-r--r--drivers/net/ethernet/i825xx/3c527.c (renamed from drivers/net/3c527.c)2
-rw-r--r--drivers/net/ethernet/i825xx/3c527.h (renamed from drivers/net/3c527.h)0
-rw-r--r--drivers/net/ethernet/i825xx/82596.c (renamed from drivers/net/82596.c)2
-rw-r--r--drivers/net/ethernet/i825xx/Kconfig183
-rw-r--r--drivers/net/ethernet/i825xx/Makefile20
-rw-r--r--drivers/net/ethernet/i825xx/eepro.c (renamed from drivers/net/eepro.c)2
-rw-r--r--drivers/net/ethernet/i825xx/eexpress.c (renamed from drivers/net/eexpress.c)2
-rw-r--r--drivers/net/ethernet/i825xx/eexpress.h (renamed from drivers/net/eexpress.h)0
-rw-r--r--drivers/net/ethernet/i825xx/ether1.c (renamed from drivers/net/arm/ether1.c)2
-rw-r--r--drivers/net/ethernet/i825xx/ether1.h (renamed from drivers/net/arm/ether1.h)0
-rw-r--r--drivers/net/ethernet/i825xx/lasi_82596.c (renamed from drivers/net/lasi_82596.c)0
-rw-r--r--drivers/net/ethernet/i825xx/lib82596.c (renamed from drivers/net/lib82596.c)2
-rw-r--r--drivers/net/ethernet/i825xx/lp486e.c (renamed from drivers/net/lp486e.c)2
-rw-r--r--drivers/net/ethernet/i825xx/ni52.c (renamed from drivers/net/ni52.c)2
-rw-r--r--drivers/net/ethernet/i825xx/ni52.h (renamed from drivers/net/ni52.h)0
-rw-r--r--drivers/net/ethernet/i825xx/sni_82596.c (renamed from drivers/net/sni_82596.c)0
-rw-r--r--drivers/net/ethernet/i825xx/sun3_82586.c (renamed from drivers/net/sun3_82586.c)2
-rw-r--r--drivers/net/ethernet/i825xx/sun3_82586.h (renamed from drivers/net/sun3_82586.h)0
-rw-r--r--drivers/net/ethernet/i825xx/znet.c (renamed from drivers/net/znet.c)2
-rw-r--r--drivers/net/ethernet/ibm/Kconfig48
-rw-r--r--drivers/net/ethernet/ibm/Makefile8
-rw-r--r--drivers/net/ethernet/ibm/ehea/Makefile (renamed from drivers/net/ehea/Makefile)0
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea.h (renamed from drivers/net/ehea/ehea.h)21
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_ethtool.c (renamed from drivers/net/ehea/ehea_ethtool.c)33
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_hw.h (renamed from drivers/net/ehea/ehea_hw.h)25
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_main.c (renamed from drivers/net/ehea/ehea_main.c)544
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_phyp.c (renamed from drivers/net/ehea/ehea_phyp.c)0
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_phyp.h (renamed from drivers/net/ehea/ehea_phyp.h)0
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_qmr.c (renamed from drivers/net/ehea/ehea_qmr.c)0
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_qmr.h (renamed from drivers/net/ehea/ehea_qmr.h)2
-rw-r--r--drivers/net/ethernet/ibm/emac/Kconfig (renamed from drivers/net/ibm_newemac/Kconfig)40
-rw-r--r--drivers/net/ethernet/ibm/emac/Makefile11
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c (renamed from drivers/net/ibm_newemac/core.c)22
-rw-r--r--drivers/net/ethernet/ibm/emac/core.h (renamed from drivers/net/ibm_newemac/core.h)16
-rw-r--r--drivers/net/ethernet/ibm/emac/debug.c (renamed from drivers/net/ibm_newemac/debug.c)0
-rw-r--r--drivers/net/ethernet/ibm/emac/debug.h (renamed from drivers/net/ibm_newemac/debug.h)2
-rw-r--r--drivers/net/ethernet/ibm/emac/emac.h (renamed from drivers/net/ibm_newemac/emac.h)0
-rw-r--r--drivers/net/ethernet/ibm/emac/mal.c (renamed from drivers/net/ibm_newemac/mal.c)6
-rw-r--r--drivers/net/ethernet/ibm/emac/mal.h (renamed from drivers/net/ibm_newemac/mal.h)4
-rw-r--r--drivers/net/ethernet/ibm/emac/phy.c (renamed from drivers/net/ibm_newemac/phy.c)0
-rw-r--r--drivers/net/ethernet/ibm/emac/phy.h (renamed from drivers/net/ibm_newemac/phy.h)0
-rw-r--r--drivers/net/ethernet/ibm/emac/rgmii.c (renamed from drivers/net/ibm_newemac/rgmii.c)0
-rw-r--r--drivers/net/ethernet/ibm/emac/rgmii.h (renamed from drivers/net/ibm_newemac/rgmii.h)4
-rw-r--r--drivers/net/ethernet/ibm/emac/tah.c (renamed from drivers/net/ibm_newemac/tah.c)0
-rw-r--r--drivers/net/ethernet/ibm/emac/tah.h (renamed from drivers/net/ibm_newemac/tah.h)4
-rw-r--r--drivers/net/ethernet/ibm/emac/zmii.c (renamed from drivers/net/ibm_newemac/zmii.c)0
-rw-r--r--drivers/net/ethernet/ibm/emac/zmii.h (renamed from drivers/net/ibm_newemac/zmii.h)4
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c (renamed from drivers/net/ibmveth.c)11
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.h (renamed from drivers/net/ibmveth.h)0
-rw-r--r--drivers/net/ethernet/ibm/iseries_veth.c (renamed from drivers/net/iseries_veth.c)2
-rw-r--r--drivers/net/ethernet/icplus/Kconfig14
-rw-r--r--drivers/net/ethernet/icplus/Makefile5
-rw-r--r--drivers/net/ethernet/icplus/ipg.c (renamed from drivers/net/ipg.c)199
-rw-r--r--drivers/net/ethernet/icplus/ipg.h (renamed from drivers/net/ipg.h)0
-rw-r--r--drivers/net/ethernet/intel/Kconfig222
-rw-r--r--drivers/net/ethernet/intel/Makefile12
-rw-r--r--drivers/net/ethernet/intel/e100.c (renamed from drivers/net/e100.c)6
-rw-r--r--drivers/net/ethernet/intel/e1000/Makefile (renamed from drivers/net/e1000/Makefile)0
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000.h (renamed from drivers/net/e1000/e1000.h)14
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_ethtool.c (renamed from drivers/net/e1000/e1000_ethtool.c)4
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_hw.c (renamed from drivers/net/e1000/e1000_hw.c)22
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_hw.h (renamed from drivers/net/e1000/e1000_hw.h)0
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c (renamed from drivers/net/e1000/e1000_main.c)219
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_osdep.h (renamed from drivers/net/e1000/e1000_osdep.h)0
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_param.c (renamed from drivers/net/e1000/e1000_param.c)0
-rw-r--r--drivers/net/ethernet/intel/e1000e/80003es2lan.c (renamed from drivers/net/e1000e/es2lan.c)9
-rw-r--r--drivers/net/ethernet/intel/e1000e/82571.c (renamed from drivers/net/e1000e/82571.c)25
-rw-r--r--drivers/net/ethernet/intel/e1000e/Makefile (renamed from drivers/net/e1000e/Makefile)2
-rw-r--r--drivers/net/ethernet/intel/e1000e/defines.h (renamed from drivers/net/e1000e/defines.h)0
-rw-r--r--drivers/net/ethernet/intel/e1000e/e1000.h (renamed from drivers/net/e1000e/e1000.h)35
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c (renamed from drivers/net/e1000e/ethtool.c)101
-rw-r--r--drivers/net/ethernet/intel/e1000e/hw.h (renamed from drivers/net/e1000e/hw.h)0
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c (renamed from drivers/net/e1000e/ich8lan.c)69
-rw-r--r--drivers/net/ethernet/intel/e1000e/lib.c (renamed from drivers/net/e1000e/lib.c)0
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c (renamed from drivers/net/e1000e/netdev.c)269
-rw-r--r--drivers/net/ethernet/intel/e1000e/param.c (renamed from drivers/net/e1000e/param.c)0
-rw-r--r--drivers/net/ethernet/intel/e1000e/phy.c (renamed from drivers/net/e1000e/phy.c)0
-rw-r--r--drivers/net/ethernet/intel/igb/Makefile (renamed from drivers/net/igb/Makefile)0
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.c (renamed from drivers/net/igb/e1000_82575.c)43
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.h (renamed from drivers/net/igb/e1000_82575.h)2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_defines.h (renamed from drivers/net/igb/e1000_defines.h)4
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_hw.h (renamed from drivers/net/igb/e1000_hw.h)0
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.c (renamed from drivers/net/igb/e1000_mac.c)72
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.h (renamed from drivers/net/igb/e1000_mac.h)1
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mbx.c (renamed from drivers/net/igb/e1000_mbx.c)2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mbx.h (renamed from drivers/net/igb/e1000_mbx.h)0
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_nvm.c (renamed from drivers/net/igb/e1000_nvm.c)0
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_nvm.h (renamed from drivers/net/igb/e1000_nvm.h)0
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_phy.c (renamed from drivers/net/igb/e1000_phy.c)6
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_phy.h (renamed from drivers/net/igb/e1000_phy.h)0
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_regs.h (renamed from drivers/net/igb/e1000_regs.h)1
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h (renamed from drivers/net/igb/igb.h)221
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c (renamed from drivers/net/igb/igb_ethtool.c)47
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c (renamed from drivers/net/igb/igb_main.c)2289
-rw-r--r--drivers/net/ethernet/intel/igbvf/Makefile (renamed from drivers/net/igbvf/Makefile)0
-rw-r--r--drivers/net/ethernet/intel/igbvf/defines.h (renamed from drivers/net/igbvf/defines.h)0
-rw-r--r--drivers/net/ethernet/intel/igbvf/ethtool.c (renamed from drivers/net/igbvf/ethtool.c)61
-rw-r--r--drivers/net/ethernet/intel/igbvf/igbvf.h (renamed from drivers/net/igbvf/igbvf.h)0
-rw-r--r--drivers/net/ethernet/intel/igbvf/mbx.c (renamed from drivers/net/igbvf/mbx.c)2
-rw-r--r--drivers/net/ethernet/intel/igbvf/mbx.h (renamed from drivers/net/igbvf/mbx.h)0
-rw-r--r--drivers/net/ethernet/intel/igbvf/netdev.c (renamed from drivers/net/igbvf/netdev.c)56
-rw-r--r--drivers/net/ethernet/intel/igbvf/regs.h (renamed from drivers/net/igbvf/regs.h)0
-rw-r--r--drivers/net/ethernet/intel/igbvf/vf.c (renamed from drivers/net/igbvf/vf.c)0
-rw-r--r--drivers/net/ethernet/intel/igbvf/vf.h (renamed from drivers/net/igbvf/vf.h)0
-rw-r--r--drivers/net/ethernet/intel/ixgb/Makefile (renamed from drivers/net/ixgb/Makefile)0
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb.h (renamed from drivers/net/ixgb/ixgb.h)2
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_ee.c (renamed from drivers/net/ixgb/ixgb_ee.c)2
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_ee.h (renamed from drivers/net/ixgb/ixgb_ee.h)4
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c (renamed from drivers/net/ixgb/ixgb_ethtool.c)102
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_hw.c (renamed from drivers/net/ixgb/ixgb_hw.c)2
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_hw.h (renamed from drivers/net/ixgb/ixgb_hw.h)4
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_ids.h (renamed from drivers/net/ixgb/ixgb_ids.h)0
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_main.c (renamed from drivers/net/ixgb/ixgb_main.c)78
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_osdep.h (renamed from drivers/net/ixgb/ixgb_osdep.h)1
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_param.c (renamed from drivers/net/ixgb/ixgb_param.c)18
-rw-r--r--drivers/net/ethernet/intel/ixgbe/Makefile (renamed from drivers/net/ixgbe/Makefile)0
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h (renamed from drivers/net/ixgbe/ixgbe.h)87
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c (renamed from drivers/net/ixgbe/ixgbe_82598.c)45
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c (renamed from drivers/net/ixgbe/ixgbe_82599.c)147
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.c (renamed from drivers/net/ixgbe/ixgbe_common.c)188
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.h (renamed from drivers/net/ixgbe/ixgbe_common.h)2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c (renamed from drivers/net/ixgbe/ixgbe_dcb.c)58
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h (renamed from drivers/net/ixgbe/ixgbe_dcb.h)7
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c (renamed from drivers/net/ixgbe/ixgbe_dcb_82598.c)9
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h (renamed from drivers/net/ixgbe/ixgbe_dcb_82598.h)0
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c (renamed from drivers/net/ixgbe/ixgbe_dcb_82599.c)56
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h (renamed from drivers/net/ixgbe/ixgbe_dcb_82599.h)2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c (renamed from drivers/net/ixgbe/ixgbe_dcb_nl.c)173
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c (renamed from drivers/net/ixgbe/ixgbe_ethtool.c)307
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c (renamed from drivers/net/ixgbe/ixgbe_fcoe.c)47
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h (renamed from drivers/net/ixgbe/ixgbe_fcoe.h)2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c (renamed from drivers/net/ixgbe/ixgbe_main.c)2296
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c (renamed from drivers/net/ixgbe/ixgbe_mbx.c)2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h (renamed from drivers/net/ixgbe/ixgbe_mbx.h)0
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c (renamed from drivers/net/ixgbe/ixgbe_phy.c)33
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h (renamed from drivers/net/ixgbe/ixgbe_phy.h)0
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c (renamed from drivers/net/ixgbe/ixgbe_sriov.c)255
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h (renamed from drivers/net/ixgbe/ixgbe_sriov.h)6
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h (renamed from drivers/net/ixgbe/ixgbe_type.h)80
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c (renamed from drivers/net/ixgbe/ixgbe_x540.c)92
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/Makefile (renamed from drivers/net/ixgbevf/Makefile)0
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/defines.h (renamed from drivers/net/ixgbevf/defines.h)0
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ethtool.c (renamed from drivers/net/ixgbevf/ethtool.c)50
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf.h (renamed from drivers/net/ixgbevf/ixgbevf.h)8
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c (renamed from drivers/net/ixgbevf/ixgbevf_main.c)107
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/mbx.c (renamed from drivers/net/ixgbevf/mbx.c)2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/mbx.h (renamed from drivers/net/ixgbevf/mbx.h)0
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/regs.h (renamed from drivers/net/ixgbevf/regs.h)0
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.c (renamed from drivers/net/ixgbevf/vf.c)0
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.h (renamed from drivers/net/ixgbevf/vf.h)0
-rw-r--r--drivers/net/ethernet/jme.c (renamed from drivers/net/jme.c)15
-rw-r--r--drivers/net/ethernet/jme.h (renamed from drivers/net/jme.h)1
-rw-r--r--drivers/net/ethernet/korina.c (renamed from drivers/net/korina.c)3
-rw-r--r--drivers/net/ethernet/lantiq_etop.c (renamed from drivers/net/lantiq_etop.c)2
-rw-r--r--drivers/net/ethernet/marvell/Kconfig111
-rw-r--r--drivers/net/ethernet/marvell/Makefile8
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c (renamed from drivers/net/mv643xx_eth.c)21
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c (renamed from drivers/net/pxa168_eth.c)0
-rw-r--r--drivers/net/ethernet/marvell/skge.c (renamed from drivers/net/skge.c)88
-rw-r--r--drivers/net/ethernet/marvell/skge.h (renamed from drivers/net/skge.h)0
-rw-r--r--drivers/net/ethernet/marvell/sky2.c (renamed from drivers/net/sky2.c)126
-rw-r--r--drivers/net/ethernet/marvell/sky2.h (renamed from drivers/net/sky2.h)0
-rw-r--r--drivers/net/ethernet/mellanox/Kconfig23
-rw-r--r--drivers/net/ethernet/mellanox/Makefile5
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/Kconfig27
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/Makefile (renamed from drivers/net/mlx4/Makefile)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/alloc.c (renamed from drivers/net/mlx4/alloc.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/catas.c (renamed from drivers/net/mlx4/catas.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c (renamed from drivers/net/mlx4/cmd.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cq.c (renamed from drivers/net/mlx4/cq.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_cq.c (renamed from drivers/net/mlx4/en_cq.c)31
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c (renamed from drivers/net/mlx4/en_ethtool.c)14
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_main.c (renamed from drivers/net/mlx4/en_main.c)6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c (renamed from drivers/net/mlx4/en_netdev.c)116
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_port.c (renamed from drivers/net/mlx4/en_port.c)24
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_port.h (renamed from drivers/net/mlx4/en_port.h)11
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_resources.c (renamed from drivers/net/mlx4/en_resources.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c (renamed from drivers/net/mlx4/en_rx.c)74
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_selftest.c (renamed from drivers/net/mlx4/en_selftest.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c (renamed from drivers/net/mlx4/en_tx.c)32
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c (renamed from drivers/net/mlx4/eq.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c (renamed from drivers/net/mlx4/fw.c)7
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.h (renamed from drivers/net/mlx4/fw.h)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/icm.c (renamed from drivers/net/mlx4/icm.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/icm.h (renamed from drivers/net/mlx4/icm.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/intf.c (renamed from drivers/net/mlx4/intf.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c (renamed from drivers/net/mlx4/main.c)36
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mcg.c (renamed from drivers/net/mlx4/mcg.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h (renamed from drivers/net/mlx4/mlx4.h)4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h (renamed from drivers/net/mlx4/mlx4_en.h)25
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mr.c (renamed from drivers/net/mlx4/mr.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/pd.c (renamed from drivers/net/mlx4/pd.c)30
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c (renamed from drivers/net/mlx4/port.c)87
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/profile.c (renamed from drivers/net/mlx4/profile.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/qp.c (renamed from drivers/net/mlx4/qp.c)3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/reset.c (renamed from drivers/net/mlx4/reset.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/sense.c (renamed from drivers/net/mlx4/sense.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/srq.c (renamed from drivers/net/mlx4/srq.c)20
-rw-r--r--drivers/net/ethernet/micrel/Kconfig69
-rw-r--r--drivers/net/ethernet/micrel/Makefile9
-rw-r--r--drivers/net/ethernet/micrel/ks8695net.c (renamed from drivers/net/arm/ks8695net.c)4
-rw-r--r--drivers/net/ethernet/micrel/ks8695net.h (renamed from drivers/net/arm/ks8695net.h)0
-rw-r--r--drivers/net/ethernet/micrel/ks8842.c (renamed from drivers/net/ks8842.c)0
-rw-r--r--drivers/net/ethernet/micrel/ks8851.c (renamed from drivers/net/ks8851.c)0
-rw-r--r--drivers/net/ethernet/micrel/ks8851.h (renamed from drivers/net/ks8851.h)0
-rw-r--r--drivers/net/ethernet/micrel/ks8851_mll.c (renamed from drivers/net/ks8851_mll.c)0
-rw-r--r--drivers/net/ethernet/micrel/ksz884x.c (renamed from drivers/net/ksz884x.c)5
-rw-r--r--drivers/net/ethernet/microchip/Kconfig38
-rw-r--r--drivers/net/ethernet/microchip/Makefile5
-rw-r--r--drivers/net/ethernet/microchip/enc28j60.c (renamed from drivers/net/enc28j60.c)2
-rw-r--r--drivers/net/ethernet/microchip/enc28j60_hw.h (renamed from drivers/net/enc28j60_hw.h)0
-rw-r--r--drivers/net/ethernet/mipsnet.c (renamed from drivers/net/mipsnet.c)2
-rw-r--r--drivers/net/ethernet/myricom/Kconfig47
-rw-r--r--drivers/net/ethernet/myricom/Makefile5
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/Makefile (renamed from drivers/net/myri10ge/Makefile)0
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c (renamed from drivers/net/myri10ge/myri10ge.c)31
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp.h (renamed from drivers/net/myri10ge/myri10ge_mcp.h)0
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h (renamed from drivers/net/myri10ge/myri10ge_mcp_gen_header.h)0
-rw-r--r--drivers/net/ethernet/natsemi/Kconfig83
-rw-r--r--drivers/net/ethernet/natsemi/Makefile10
-rw-r--r--drivers/net/ethernet/natsemi/ibmlana.c (renamed from drivers/net/ibmlana.c)2
-rw-r--r--drivers/net/ethernet/natsemi/ibmlana.h (renamed from drivers/net/ibmlana.h)0
-rw-r--r--drivers/net/ethernet/natsemi/jazzsonic.c (renamed from drivers/net/jazzsonic.c)2
-rw-r--r--drivers/net/ethernet/natsemi/macsonic.c (renamed from drivers/net/macsonic.c)11
-rw-r--r--drivers/net/ethernet/natsemi/natsemi.c (renamed from drivers/net/natsemi.c)2
-rw-r--r--drivers/net/ethernet/natsemi/ns83820.c (renamed from drivers/net/ns83820.c)9
-rw-r--r--drivers/net/ethernet/natsemi/sonic.c (renamed from drivers/net/sonic.c)0
-rw-r--r--drivers/net/ethernet/natsemi/sonic.h (renamed from drivers/net/sonic.h)0
-rw-r--r--drivers/net/ethernet/natsemi/xtsonic.c (renamed from drivers/net/xtsonic.c)2
-rw-r--r--drivers/net/ethernet/neterion/Kconfig55
-rw-r--r--drivers/net/ethernet/neterion/Makefile6
-rw-r--r--drivers/net/ethernet/neterion/s2io-regs.h (renamed from drivers/net/s2io-regs.h)0
-rw-r--r--drivers/net/ethernet/neterion/s2io.c (renamed from drivers/net/s2io.c)22
-rw-r--r--drivers/net/ethernet/neterion/s2io.h (renamed from drivers/net/s2io.h)0
-rw-r--r--drivers/net/ethernet/neterion/vxge/Makefile (renamed from drivers/net/vxge/Makefile)0
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-config.c (renamed from drivers/net/vxge/vxge-config.c)11
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-config.h (renamed from drivers/net/vxge/vxge-config.h)4
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-ethtool.c (renamed from drivers/net/vxge/vxge-ethtool.c)0
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-ethtool.h (renamed from drivers/net/vxge/vxge-ethtool.h)0
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.c (renamed from drivers/net/vxge/vxge-main.c)30
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.h (renamed from drivers/net/vxge/vxge-main.h)0
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-reg.h (renamed from drivers/net/vxge/vxge-reg.h)0
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-traffic.c (renamed from drivers/net/vxge/vxge-traffic.c)12
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-traffic.h (renamed from drivers/net/vxge/vxge-traffic.h)0
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-version.h (renamed from drivers/net/vxge/vxge-version.h)0
-rw-r--r--drivers/net/ethernet/netx-eth.c (renamed from drivers/net/netx-eth.c)2
-rw-r--r--drivers/net/ethernet/nuvoton/Kconfig31
-rw-r--r--drivers/net/ethernet/nuvoton/Makefile5
-rw-r--r--drivers/net/ethernet/nuvoton/w90p910_ether.c (renamed from drivers/net/arm/w90p910_ether.c)2
-rw-r--r--drivers/net/ethernet/nvidia/Kconfig32
-rw-r--r--drivers/net/ethernet/nvidia/Makefile5
-rw-r--r--drivers/net/ethernet/nvidia/forcedeth.c (renamed from drivers/net/forcedeth.c)40
-rw-r--r--drivers/net/ethernet/octeon/Kconfig (renamed from drivers/net/octeon/Kconfig)6
-rw-r--r--drivers/net/ethernet/octeon/Makefile5
-rw-r--r--drivers/net/ethernet/octeon/octeon_mgmt.c (renamed from drivers/net/octeon/octeon_mgmt.c)4
-rw-r--r--drivers/net/ethernet/oki-semi/Kconfig23
-rw-r--r--drivers/net/ethernet/oki-semi/Makefile5
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/Kconfig22
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/Makefile (renamed from drivers/net/pch_gbe/Makefile)0
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h (renamed from drivers/net/pch_gbe/pch_gbe.h)0
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c (renamed from drivers/net/pch_gbe/pch_gbe_api.c)0
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h (renamed from drivers/net/pch_gbe/pch_gbe_api.h)0
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c (renamed from drivers/net/pch_gbe/pch_gbe_ethtool.c)4
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c (renamed from drivers/net/pch_gbe/pch_gbe_main.c)3
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c (renamed from drivers/net/pch_gbe/pch_gbe_param.c)0
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c (renamed from drivers/net/pch_gbe/pch_gbe_phy.c)0
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h (renamed from drivers/net/pch_gbe/pch_gbe_phy.h)0
-rw-r--r--drivers/net/ethernet/packetengines/Kconfig47
-rw-r--r--drivers/net/ethernet/packetengines/Makefile6
-rw-r--r--drivers/net/ethernet/packetengines/hamachi.c (renamed from drivers/net/hamachi.c)2
-rw-r--r--drivers/net/ethernet/packetengines/yellowfin.c (renamed from drivers/net/yellowfin.c)2
-rw-r--r--drivers/net/ethernet/pasemi/Kconfig30
-rw-r--r--drivers/net/ethernet/pasemi/Makefile5
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.c (renamed from drivers/net/pasemi_mac.c)15
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.h (renamed from drivers/net/pasemi_mac.h)0
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac_ethtool.c (renamed from drivers/net/pasemi_mac_ethtool.c)0
-rw-r--r--drivers/net/ethernet/qlogic/Kconfig54
-rw-r--r--drivers/net/ethernet/qlogic/Makefile8
-rw-r--r--drivers/net/ethernet/qlogic/netxen/Makefile (renamed from drivers/net/netxen/Makefile)0
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic.h (renamed from drivers/net/netxen/netxen_nic.h)10
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c (renamed from drivers/net/netxen/netxen_nic_ctx.c)0
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c (renamed from drivers/net/netxen/netxen_nic_ethtool.c)3
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h (renamed from drivers/net/netxen/netxen_nic_hdr.h)0
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c (renamed from drivers/net/netxen/netxen_nic_hw.c)0
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.h (renamed from drivers/net/netxen/netxen_nic_hw.h)0
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c (renamed from drivers/net/netxen/netxen_nic_init.c)8
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c (renamed from drivers/net/netxen/netxen_nic_main.c)178
-rw-r--r--drivers/net/ethernet/qlogic/qla3xxx.c (renamed from drivers/net/qla3xxx.c)14
-rw-r--r--drivers/net/ethernet/qlogic/qla3xxx.h (renamed from drivers/net/qla3xxx.h)0
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/Makefile (renamed from drivers/net/qlcnic/Makefile)0
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h (renamed from drivers/net/qlcnic/qlcnic.h)32
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c (renamed from drivers/net/qlcnic/qlcnic_ctx.c)312
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c (renamed from drivers/net/qlcnic/qlcnic_ethtool.c)99
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h (renamed from drivers/net/qlcnic/qlcnic_hdr.h)6
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c (renamed from drivers/net/qlcnic/qlcnic_hw.c)6
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c (renamed from drivers/net/qlcnic/qlcnic_init.c)71
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c (renamed from drivers/net/qlcnic/qlcnic_main.c)203
-rw-r--r--drivers/net/ethernet/qlogic/qlge/Makefile (renamed from drivers/net/qlge/Makefile)0
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge.h (renamed from drivers/net/qlge/qlge.h)0
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_dbg.c (renamed from drivers/net/qlge/qlge_dbg.c)0
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c (renamed from drivers/net/qlge/qlge_ethtool.c)0
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_main.c (renamed from drivers/net/qlge/qlge_main.c)26
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_mpi.c (renamed from drivers/net/qlge/qlge_mpi.c)0
-rw-r--r--drivers/net/ethernet/racal/Kconfig33
-rw-r--r--drivers/net/ethernet/racal/Makefile5
-rw-r--r--drivers/net/ethernet/racal/ni5010.c (renamed from drivers/net/ni5010.c)2
-rw-r--r--drivers/net/ethernet/racal/ni5010.h (renamed from drivers/net/ni5010.h)0
-rw-r--r--drivers/net/ethernet/rdc/Kconfig35
-rw-r--r--drivers/net/ethernet/rdc/Makefile5
-rw-r--r--drivers/net/ethernet/rdc/r6040.c (renamed from drivers/net/r6040.c)10
-rw-r--r--drivers/net/ethernet/realtek/8139cp.c (renamed from drivers/net/8139cp.c)19
-rw-r--r--drivers/net/ethernet/realtek/8139too.c (renamed from drivers/net/8139too.c)2
-rw-r--r--drivers/net/ethernet/realtek/Kconfig130
-rw-r--r--drivers/net/ethernet/realtek/Makefile9
-rw-r--r--drivers/net/ethernet/realtek/atp.c (renamed from drivers/net/atp.c)2
-rw-r--r--drivers/net/ethernet/realtek/atp.h (renamed from drivers/net/atp.h)0
-rw-r--r--drivers/net/ethernet/realtek/r8169.c (renamed from drivers/net/r8169.c)495
-rw-r--r--drivers/net/ethernet/realtek/sc92031.c (renamed from drivers/net/sc92031.c)10
-rw-r--r--drivers/net/ethernet/renesas/Kconfig19
-rw-r--r--drivers/net/ethernet/renesas/Makefile5
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c (renamed from drivers/net/sh_eth.c)44
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.h (renamed from drivers/net/sh_eth.h)17
-rw-r--r--drivers/net/ethernet/s6gmac.c (renamed from drivers/net/s6gmac.c)0
-rw-r--r--drivers/net/ethernet/seeq/Kconfig47
-rw-r--r--drivers/net/ethernet/seeq/Makefile7
-rw-r--r--drivers/net/ethernet/seeq/ether3.c (renamed from drivers/net/arm/ether3.c)2
-rw-r--r--drivers/net/ethernet/seeq/ether3.h (renamed from drivers/net/arm/ether3.h)0
-rw-r--r--drivers/net/ethernet/seeq/seeq8005.c (renamed from drivers/net/seeq8005.c)2
-rw-r--r--drivers/net/ethernet/seeq/seeq8005.h (renamed from drivers/net/seeq8005.h)0
-rw-r--r--drivers/net/ethernet/seeq/sgiseeq.c (renamed from drivers/net/sgiseeq.c)2
-rw-r--r--drivers/net/ethernet/seeq/sgiseeq.h (renamed from drivers/net/sgiseeq.h)0
-rw-r--r--drivers/net/ethernet/sfc/Kconfig (renamed from drivers/net/sfc/Kconfig)4
-rw-r--r--drivers/net/ethernet/sfc/Makefile (renamed from drivers/net/sfc/Makefile)0
-rw-r--r--drivers/net/ethernet/sfc/bitfield.h (renamed from drivers/net/sfc/bitfield.h)0
-rw-r--r--drivers/net/ethernet/sfc/efx.c (renamed from drivers/net/sfc/efx.c)56
-rw-r--r--drivers/net/ethernet/sfc/efx.h (renamed from drivers/net/sfc/efx.h)11
-rw-r--r--drivers/net/ethernet/sfc/enum.h (renamed from drivers/net/sfc/enum.h)0
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c (renamed from drivers/net/sfc/ethtool.c)111
-rw-r--r--drivers/net/ethernet/sfc/falcon.c (renamed from drivers/net/sfc/falcon.c)5
-rw-r--r--drivers/net/ethernet/sfc/falcon_boards.c (renamed from drivers/net/sfc/falcon_boards.c)3
-rw-r--r--drivers/net/ethernet/sfc/falcon_xmac.c (renamed from drivers/net/sfc/falcon_xmac.c)0
-rw-r--r--drivers/net/ethernet/sfc/filter.c (renamed from drivers/net/sfc/filter.c)0
-rw-r--r--drivers/net/ethernet/sfc/filter.h (renamed from drivers/net/sfc/filter.h)0
-rw-r--r--drivers/net/ethernet/sfc/io.h (renamed from drivers/net/sfc/io.h)0
-rw-r--r--drivers/net/ethernet/sfc/mac.h (renamed from drivers/net/sfc/mac.h)0
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c (renamed from drivers/net/sfc/mcdi.c)0
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h (renamed from drivers/net/sfc/mcdi.h)0
-rw-r--r--drivers/net/ethernet/sfc/mcdi_mac.c (renamed from drivers/net/sfc/mcdi_mac.c)0
-rw-r--r--drivers/net/ethernet/sfc/mcdi_pcol.h (renamed from drivers/net/sfc/mcdi_pcol.h)0
-rw-r--r--drivers/net/ethernet/sfc/mcdi_phy.c (renamed from drivers/net/sfc/mcdi_phy.c)0
-rw-r--r--drivers/net/ethernet/sfc/mdio_10g.c (renamed from drivers/net/sfc/mdio_10g.c)0
-rw-r--r--drivers/net/ethernet/sfc/mdio_10g.h (renamed from drivers/net/sfc/mdio_10g.h)0
-rw-r--r--drivers/net/ethernet/sfc/mtd.c (renamed from drivers/net/sfc/mtd.c)0
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h (renamed from drivers/net/sfc/net_driver.h)0
-rw-r--r--drivers/net/ethernet/sfc/nic.c (renamed from drivers/net/sfc/nic.c)0
-rw-r--r--drivers/net/ethernet/sfc/nic.h (renamed from drivers/net/sfc/nic.h)3
-rw-r--r--drivers/net/ethernet/sfc/phy.h (renamed from drivers/net/sfc/phy.h)0
-rw-r--r--drivers/net/ethernet/sfc/qt202x_phy.c (renamed from drivers/net/sfc/qt202x_phy.c)0
-rw-r--r--drivers/net/ethernet/sfc/regs.h (renamed from drivers/net/sfc/regs.h)0
-rw-r--r--drivers/net/ethernet/sfc/rx.c (renamed from drivers/net/sfc/rx.c)4
-rw-r--r--drivers/net/ethernet/sfc/selftest.c (renamed from drivers/net/sfc/selftest.c)0
-rw-r--r--drivers/net/ethernet/sfc/selftest.h (renamed from drivers/net/sfc/selftest.h)0
-rw-r--r--drivers/net/ethernet/sfc/siena.c (renamed from drivers/net/sfc/siena.c)2
-rw-r--r--drivers/net/ethernet/sfc/spi.h (renamed from drivers/net/sfc/spi.h)0
-rw-r--r--drivers/net/ethernet/sfc/tenxpress.c (renamed from drivers/net/sfc/tenxpress.c)0
-rw-r--r--drivers/net/ethernet/sfc/tx.c (renamed from drivers/net/sfc/tx.c)21
-rw-r--r--drivers/net/ethernet/sfc/txc43128_phy.c (renamed from drivers/net/sfc/txc43128_phy.c)0
-rw-r--r--drivers/net/ethernet/sfc/workarounds.h (renamed from drivers/net/sfc/workarounds.h)0
-rw-r--r--drivers/net/ethernet/sgi/Kconfig36
-rw-r--r--drivers/net/ethernet/sgi/Makefile6
-rw-r--r--drivers/net/ethernet/sgi/ioc3-eth.c (renamed from drivers/net/ioc3-eth.c)2
-rw-r--r--drivers/net/ethernet/sgi/meth.c (renamed from drivers/net/meth.c)0
-rw-r--r--drivers/net/ethernet/sgi/meth.h (renamed from drivers/net/meth.h)0
-rw-r--r--drivers/net/ethernet/sis/Kconfig53
-rw-r--r--drivers/net/ethernet/sis/Makefile6
-rw-r--r--drivers/net/ethernet/sis/sis190.c (renamed from drivers/net/sis190.c)2
-rw-r--r--drivers/net/ethernet/sis/sis900.c (renamed from drivers/net/sis900.c)2
-rw-r--r--drivers/net/ethernet/sis/sis900.h (renamed from drivers/net/sis900.h)0
-rw-r--r--drivers/net/ethernet/smsc/Kconfig136
-rw-r--r--drivers/net/ethernet/smsc/Makefile11
-rw-r--r--drivers/net/ethernet/smsc/epic100.c (renamed from drivers/net/epic100.c)2
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c (renamed from drivers/net/smc911x.c)2
-rw-r--r--drivers/net/ethernet/smsc/smc911x.h (renamed from drivers/net/smc911x.h)0
-rw-r--r--drivers/net/ethernet/smsc/smc9194.c (renamed from drivers/net/smc9194.c)2
-rw-r--r--drivers/net/ethernet/smsc/smc9194.h (renamed from drivers/net/smc9194.h)0
-rw-r--r--drivers/net/ethernet/smsc/smc91c92_cs.c (renamed from drivers/net/pcmcia/smc91c92_cs.c)2
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c (renamed from drivers/net/smc91x.c)2
-rw-r--r--drivers/net/ethernet/smsc/smc91x.h (renamed from drivers/net/smc91x.h)0
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c (renamed from drivers/net/smsc911x.c)89
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.h (renamed from drivers/net/smsc911x.h)0
-rw-r--r--drivers/net/ethernet/smsc/smsc9420.c (renamed from drivers/net/smsc9420.c)2
-rw-r--r--drivers/net/ethernet/smsc/smsc9420.h (renamed from drivers/net/smsc9420.h)0
-rw-r--r--drivers/net/ethernet/stmicro/Kconfig23
-rw-r--r--drivers/net/ethernet/stmicro/Makefile5
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig (renamed from drivers/net/stmmac/Kconfig)41
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile (renamed from drivers/net/stmmac/Makefile)5
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/chain_mode.c137
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h (renamed from drivers/net/stmmac/common.h)97
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/descs.h (renamed from drivers/net/stmmac/descs.h)31
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/descs_com.h126
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac100.h (renamed from drivers/net/stmmac/dwmac100.h)0
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000.h (renamed from drivers/net/stmmac/dwmac1000.h)0
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c (renamed from drivers/net/stmmac/dwmac1000_core.c)11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c (renamed from drivers/net/stmmac/dwmac1000_dma.c)14
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c (renamed from drivers/net/stmmac/dwmac100_core.c)12
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c (renamed from drivers/net/stmmac/dwmac100_dma.c)0
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h (renamed from drivers/net/stmmac/dwmac_dma.h)1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c (renamed from drivers/net/stmmac/dwmac_lib.c)0
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/enh_desc.c (renamed from drivers/net/stmmac/enh_desc.c)22
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/mmc.h131
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/mmc_core.c265
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/norm_desc.c (renamed from drivers/net/stmmac/norm_desc.c)52
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/ring_mode.c126
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h (renamed from drivers/net/stmmac/stmmac.h)8
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c (renamed from drivers/net/stmmac/stmmac_ethtool.c)156
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c (renamed from drivers/net/stmmac/stmmac_main.c)484
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c (renamed from drivers/net/stmmac/stmmac_mdio.c)0
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c (renamed from drivers/net/stmmac/stmmac_timer.c)0
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h (renamed from drivers/net/stmmac/stmmac_timer.h)0
-rw-r--r--drivers/net/ethernet/sun/Kconfig88
-rw-r--r--drivers/net/ethernet/sun/Makefile11
-rw-r--r--drivers/net/ethernet/sun/cassini.c (renamed from drivers/net/cassini.c)25
-rw-r--r--drivers/net/ethernet/sun/cassini.h (renamed from drivers/net/cassini.h)0
-rw-r--r--drivers/net/ethernet/sun/niu.c (renamed from drivers/net/niu.c)34
-rw-r--r--drivers/net/ethernet/sun/niu.h (renamed from drivers/net/niu.h)0
-rw-r--r--drivers/net/ethernet/sun/sunbmac.c (renamed from drivers/net/sunbmac.c)33
-rw-r--r--drivers/net/ethernet/sun/sunbmac.h (renamed from drivers/net/sunbmac.h)17
-rw-r--r--drivers/net/ethernet/sun/sungem.c (renamed from drivers/net/sungem.c)16
-rw-r--r--drivers/net/ethernet/sun/sungem.h (renamed from drivers/net/sungem.h)0
-rw-r--r--drivers/net/ethernet/sun/sunhme.c (renamed from drivers/net/sunhme.c)11
-rw-r--r--drivers/net/ethernet/sun/sunhme.h (renamed from drivers/net/sunhme.h)0
-rw-r--r--drivers/net/ethernet/sun/sunqe.c (renamed from drivers/net/sunqe.c)2
-rw-r--r--drivers/net/ethernet/sun/sunqe.h (renamed from drivers/net/sunqe.h)0
-rw-r--r--drivers/net/ethernet/sun/sunvnet.c (renamed from drivers/net/sunvnet.c)2
-rw-r--r--drivers/net/ethernet/sun/sunvnet.h (renamed from drivers/net/sunvnet.h)0
-rw-r--r--drivers/net/ethernet/tehuti/Kconfig27
-rw-r--r--drivers/net/ethernet/tehuti/Makefile5
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.c (renamed from drivers/net/tehuti.c)20
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.h (renamed from drivers/net/tehuti.h)0
-rw-r--r--drivers/net/ethernet/ti/Kconfig77
-rw-r--r--drivers/net/ethernet/ti/Makefile9
-rw-r--r--drivers/net/ethernet/ti/cpmac.c (renamed from drivers/net/cpmac.c)2
-rw-r--r--drivers/net/ethernet/ti/davinci_cpdma.c (renamed from drivers/net/davinci_cpdma.c)0
-rw-r--r--drivers/net/ethernet/ti/davinci_cpdma.h (renamed from drivers/net/davinci_cpdma.h)0
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c (renamed from drivers/net/davinci_emac.c)2
-rw-r--r--drivers/net/ethernet/ti/davinci_mdio.c (renamed from drivers/net/davinci_mdio.c)0
-rw-r--r--drivers/net/ethernet/ti/tlan.c (renamed from drivers/net/tlan.c)2
-rw-r--r--drivers/net/ethernet/ti/tlan.h (renamed from drivers/net/tlan.h)0
-rw-r--r--drivers/net/ethernet/tile/Kconfig15
-rw-r--r--drivers/net/ethernet/tile/Makefile (renamed from drivers/net/tile/Makefile)0
-rw-r--r--drivers/net/ethernet/tile/tilepro.c (renamed from drivers/net/tile/tilepro.c)4
-rw-r--r--drivers/net/ethernet/toshiba/Kconfig57
-rw-r--r--drivers/net/ethernet/toshiba/Makefile10
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_net.c (renamed from drivers/net/ps3_gelic_net.c)2
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_net.h (renamed from drivers/net/ps3_gelic_net.h)0
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.c (renamed from drivers/net/ps3_gelic_wireless.c)2
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.h (renamed from drivers/net/ps3_gelic_wireless.h)0
-rw-r--r--drivers/net/ethernet/toshiba/spider_net.c (renamed from drivers/net/spider_net.c)6
-rw-r--r--drivers/net/ethernet/toshiba/spider_net.h (renamed from drivers/net/spider_net.h)2
-rw-r--r--drivers/net/ethernet/toshiba/spider_net_ethtool.c (renamed from drivers/net/spider_net_ethtool.c)0
-rw-r--r--drivers/net/ethernet/toshiba/tc35815.c (renamed from drivers/net/tc35815.c)2
-rw-r--r--drivers/net/ethernet/tundra/Kconfig29
-rw-r--r--drivers/net/ethernet/tundra/Makefile5
-rw-r--r--drivers/net/ethernet/tundra/tsi108_eth.c (renamed from drivers/net/tsi108_eth.c)13
-rw-r--r--drivers/net/ethernet/tundra/tsi108_eth.h (renamed from drivers/net/tsi108_eth.h)0
-rw-r--r--drivers/net/ethernet/via/Kconfig59
-rw-r--r--drivers/net/ethernet/via/Makefile6
-rw-r--r--drivers/net/ethernet/via/via-rhine.c (renamed from drivers/net/via-rhine.c)2
-rw-r--r--drivers/net/ethernet/via/via-velocity.c (renamed from drivers/net/via-velocity.c)159
-rw-r--r--drivers/net/ethernet/via/via-velocity.h (renamed from drivers/net/via-velocity.h)0
-rw-r--r--drivers/net/ethernet/xilinx/Kconfig36
-rw-r--r--drivers/net/ethernet/xilinx/Makefile7
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac.h (renamed from drivers/net/ll_temac.h)0
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c (renamed from drivers/net/ll_temac_main.c)35
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_mdio.c (renamed from drivers/net/ll_temac_mdio.c)0
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_emaclite.c (renamed from drivers/net/xilinx_emaclite.c)0
-rw-r--r--drivers/net/ethernet/xircom/Kconfig31
-rw-r--r--drivers/net/ethernet/xircom/Makefile5
-rw-r--r--drivers/net/ethernet/xircom/xirc2ps_cs.c (renamed from drivers/net/pcmcia/xirc2ps_cs.c)2
-rw-r--r--drivers/net/ethernet/xscale/Kconfig32
-rw-r--r--drivers/net/ethernet/xscale/Makefile6
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/Kconfig (renamed from drivers/net/ixp2000/Kconfig)2
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/Makefile (renamed from drivers/net/ixp2000/Makefile)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/caleb.c (renamed from drivers/net/ixp2000/caleb.c)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/caleb.h (renamed from drivers/net/ixp2000/caleb.h)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/enp2611.c (renamed from drivers/net/ixp2000/enp2611.c)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.c (renamed from drivers/net/ixp2000/ixp2400-msf.c)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.h (renamed from drivers/net/ixp2000/ixp2400-msf.h)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.uc (renamed from drivers/net/ixp2000/ixp2400_rx.uc)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.ucode (renamed from drivers/net/ixp2000/ixp2400_rx.ucode)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.uc (renamed from drivers/net/ixp2000/ixp2400_tx.uc)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.ucode (renamed from drivers/net/ixp2000/ixp2400_tx.ucode)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixpdev.c (renamed from drivers/net/ixp2000/ixpdev.c)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixpdev.h (renamed from drivers/net/ixp2000/ixpdev.h)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixpdev_priv.h (renamed from drivers/net/ixp2000/ixpdev_priv.h)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/pm3386.c (renamed from drivers/net/ixp2000/pm3386.c)0
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/pm3386.h (renamed from drivers/net/ixp2000/pm3386.h)0
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c (renamed from drivers/net/arm/ixp4xx_eth.c)2
-rw-r--r--drivers/net/fddi/Kconfig77
-rw-r--r--drivers/net/fddi/Makefile6
-rw-r--r--drivers/net/fddi/defxx.c (renamed from drivers/net/defxx.c)2
-rw-r--r--drivers/net/fddi/defxx.h (renamed from drivers/net/defxx.h)0
-rw-r--r--drivers/net/fddi/skfp/Makefile (renamed from drivers/net/skfp/Makefile)0
-rw-r--r--drivers/net/fddi/skfp/cfm.c (renamed from drivers/net/skfp/cfm.c)0
-rw-r--r--drivers/net/fddi/skfp/drvfbi.c (renamed from drivers/net/skfp/drvfbi.c)0
-rw-r--r--drivers/net/fddi/skfp/ecm.c (renamed from drivers/net/skfp/ecm.c)0
-rw-r--r--drivers/net/fddi/skfp/ess.c (renamed from drivers/net/skfp/ess.c)0
-rw-r--r--drivers/net/fddi/skfp/fplustm.c (renamed from drivers/net/skfp/fplustm.c)0
-rw-r--r--drivers/net/fddi/skfp/h/cmtdef.h (renamed from drivers/net/skfp/h/cmtdef.h)4
-rw-r--r--drivers/net/fddi/skfp/h/fddi.h (renamed from drivers/net/skfp/h/fddi.h)0
-rw-r--r--drivers/net/fddi/skfp/h/fddimib.h (renamed from drivers/net/skfp/h/fddimib.h)0
-rw-r--r--drivers/net/fddi/skfp/h/fplustm.h (renamed from drivers/net/skfp/h/fplustm.h)0
-rw-r--r--drivers/net/fddi/skfp/h/hwmtm.h (renamed from drivers/net/skfp/h/hwmtm.h)2
-rw-r--r--drivers/net/fddi/skfp/h/mbuf.h (renamed from drivers/net/skfp/h/mbuf.h)0
-rw-r--r--drivers/net/fddi/skfp/h/osdef1st.h (renamed from drivers/net/skfp/h/osdef1st.h)0
-rw-r--r--drivers/net/fddi/skfp/h/sba.h (renamed from drivers/net/skfp/h/sba.h)4
-rw-r--r--drivers/net/fddi/skfp/h/sba_def.h (renamed from drivers/net/skfp/h/sba_def.h)0
-rw-r--r--drivers/net/fddi/skfp/h/skfbi.h (renamed from drivers/net/skfp/h/skfbi.h)0
-rw-r--r--drivers/net/fddi/skfp/h/skfbiinc.h (renamed from drivers/net/skfp/h/skfbiinc.h)2
-rw-r--r--drivers/net/fddi/skfp/h/smc.h (renamed from drivers/net/skfp/h/smc.h)14
-rw-r--r--drivers/net/fddi/skfp/h/smt.h (renamed from drivers/net/skfp/h/smt.h)0
-rw-r--r--drivers/net/fddi/skfp/h/smt_p.h (renamed from drivers/net/skfp/h/smt_p.h)0
-rw-r--r--drivers/net/fddi/skfp/h/smtstate.h (renamed from drivers/net/skfp/h/smtstate.h)0
-rw-r--r--drivers/net/fddi/skfp/h/supern_2.h (renamed from drivers/net/skfp/h/supern_2.h)0
-rw-r--r--drivers/net/fddi/skfp/h/targethw.h (renamed from drivers/net/skfp/h/targethw.h)6
-rw-r--r--drivers/net/fddi/skfp/h/targetos.h (renamed from drivers/net/skfp/h/targetos.h)2
-rw-r--r--drivers/net/fddi/skfp/h/types.h (renamed from drivers/net/skfp/h/types.h)0
-rw-r--r--drivers/net/fddi/skfp/hwmtm.c (renamed from drivers/net/skfp/hwmtm.c)0
-rw-r--r--drivers/net/fddi/skfp/hwt.c (renamed from drivers/net/skfp/hwt.c)0
-rw-r--r--drivers/net/fddi/skfp/pcmplc.c (renamed from drivers/net/skfp/pcmplc.c)0
-rw-r--r--drivers/net/fddi/skfp/pmf.c (renamed from drivers/net/skfp/pmf.c)0
-rw-r--r--drivers/net/fddi/skfp/queue.c (renamed from drivers/net/skfp/queue.c)0
-rw-r--r--drivers/net/fddi/skfp/rmt.c (renamed from drivers/net/skfp/rmt.c)0
-rw-r--r--drivers/net/fddi/skfp/skfddi.c (renamed from drivers/net/skfp/skfddi.c)2
-rw-r--r--drivers/net/fddi/skfp/smt.c (renamed from drivers/net/skfp/smt.c)0
-rw-r--r--drivers/net/fddi/skfp/smtdef.c (renamed from drivers/net/skfp/smtdef.c)0
-rw-r--r--drivers/net/fddi/skfp/smtinit.c (renamed from drivers/net/skfp/smtinit.c)0
-rw-r--r--drivers/net/fddi/skfp/smttimer.c (renamed from drivers/net/skfp/smttimer.c)0
-rw-r--r--drivers/net/fddi/skfp/srf.c (renamed from drivers/net/skfp/srf.c)0
-rw-r--r--drivers/net/hippi/Kconfig39
-rw-r--r--drivers/net/hippi/Makefile5
-rw-r--r--drivers/net/hippi/rrunner.c (renamed from drivers/net/rrunner.c)0
-rw-r--r--drivers/net/hippi/rrunner.h (renamed from drivers/net/rrunner.h)0
-rw-r--r--drivers/net/ibm_newemac/Makefile11
-rw-r--r--drivers/net/irda/Kconfig2
-rw-r--r--drivers/net/irda/sh_irda.c124
-rw-r--r--drivers/net/macvlan.c8
-rw-r--r--drivers/net/macvtap.c183
-rw-r--r--drivers/net/octeon/Makefile2
-rw-r--r--drivers/net/pci-skeleton.c1923
-rw-r--r--drivers/net/pcmcia/Kconfig123
-rw-r--r--drivers/net/pcmcia/Makefile16
-rw-r--r--drivers/net/phy/Kconfig2
-rw-r--r--drivers/net/phy/broadcom.c2
-rw-r--r--drivers/net/phy/dp83640.c214
-rw-r--r--drivers/net/phy/icplus.c100
-rw-r--r--drivers/net/phy/mdio-gpio.c2
-rw-r--r--drivers/net/phy/phy_device.c4
-rw-r--r--drivers/net/phy/vitesse.c34
-rw-r--r--drivers/net/plip/Kconfig38
-rw-r--r--drivers/net/plip/Makefile5
-rw-r--r--drivers/net/plip/plip.c (renamed from drivers/net/plip.c)0
-rw-r--r--drivers/net/ppp/Kconfig175
-rw-r--r--drivers/net/ppp/Makefile13
-rw-r--r--drivers/net/ppp/bsd_comp.c (renamed from drivers/net/bsd_comp.c)0
-rw-r--r--drivers/net/ppp/ppp_async.c (renamed from drivers/net/ppp_async.c)0
-rw-r--r--drivers/net/ppp/ppp_deflate.c (renamed from drivers/net/ppp_deflate.c)0
-rw-r--r--drivers/net/ppp/ppp_generic.c (renamed from drivers/net/ppp_generic.c)0
-rw-r--r--drivers/net/ppp/ppp_mppe.c (renamed from drivers/net/ppp_mppe.c)0
-rw-r--r--drivers/net/ppp/ppp_mppe.h (renamed from drivers/net/ppp_mppe.h)0
-rw-r--r--drivers/net/ppp/ppp_synctty.c (renamed from drivers/net/ppp_synctty.c)0
-rw-r--r--drivers/net/ppp/pppoe.c (renamed from drivers/net/pppoe.c)0
-rw-r--r--drivers/net/ppp/pppox.c (renamed from drivers/net/pppox.c)0
-rw-r--r--drivers/net/ppp/pptp.c (renamed from drivers/net/pptp.c)0
-rw-r--r--drivers/net/rionet.c4
-rw-r--r--drivers/net/slip/Kconfig79
-rw-r--r--drivers/net/slip/Makefile6
-rw-r--r--drivers/net/slip/slhc.c (renamed from drivers/net/slhc.c)0
-rw-r--r--drivers/net/slip/slip.c (renamed from drivers/net/slip.c)29
-rw-r--r--drivers/net/slip/slip.h (renamed from drivers/net/slip.h)9
-rw-r--r--drivers/net/sungem_phy.c7
-rw-r--r--drivers/net/tokenring/3c359.c2
-rw-r--r--drivers/net/tokenring/Kconfig15
-rw-r--r--drivers/net/tokenring/Makefile21
-rw-r--r--drivers/net/tokenring/ibmtr.c2
-rw-r--r--drivers/net/tokenring/ibmtr_cs.c (renamed from drivers/net/pcmcia/ibmtr_cs.c)2
-rw-r--r--drivers/net/tokenring/lanstreamer.c2
-rw-r--r--drivers/net/tokenring/olympic.c2
-rw-r--r--drivers/net/tokenring/smctr.c2
-rw-r--r--drivers/net/tokenring/tms380tr.c2
-rw-r--r--drivers/net/tun.c2
-rw-r--r--drivers/net/usb/Kconfig3
-rw-r--r--drivers/net/usb/asix.c412
-rw-r--r--drivers/net/usb/catc.c2
-rw-r--r--drivers/net/usb/dm9601.c2
-rw-r--r--drivers/net/usb/int51x1.c2
-rw-r--r--drivers/net/usb/kaweth.c2
-rw-r--r--drivers/net/usb/lg-vl600.c19
-rw-r--r--drivers/net/usb/mcs7830.c2
-rw-r--r--drivers/net/usb/pegasus.c2
-rw-r--r--drivers/net/usb/rtl8150.c113
-rw-r--r--drivers/net/usb/smsc75xx.c2
-rw-r--r--drivers/net/usb/smsc95xx.c2
-rw-r--r--drivers/net/usb/usbnet.c8
-rw-r--r--drivers/net/virtio_net.c56
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c22
-rw-r--r--drivers/net/vmxnet3/vmxnet3_ethtool.c2
-rw-r--r--drivers/net/wan/hdlc_ppp.c14
-rw-r--r--drivers/net/wan/hdlc_x25.c16
-rw-r--r--drivers/net/wan/lapbether.c3
-rw-r--r--drivers/net/wan/sbni.c2
-rw-r--r--drivers/net/wan/x25_asy.c3
-rw-r--r--drivers/net/wimax/i2400m/usb.c4
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/Makefile5
-rw-r--r--drivers/net/wireless/adm8211.c3
-rw-r--r--drivers/net/wireless/airo.c4
-rw-r--r--drivers/net/wireless/at76c50x-usb.c18
-rw-r--r--drivers/net/wireless/ath/Kconfig3
-rw-r--r--drivers/net/wireless/ath/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath.h52
-rw-r--r--drivers/net/wireless/ath/ath5k/ahb.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/ani.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/ani.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h98
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c18
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c37
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h55
-rw-r--r--drivers/net/wireless/ath/ath5k/caps.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c15
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/desc.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/dma.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c10
-rw-r--r--drivers/net/wireless/ath/ath5k/gpio.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/initvals.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c13
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c5
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c91
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c10
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c79
-rw-r--r--drivers/net/wireless/ath/ath5k/rfkill.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/sysfs.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/trace.h3
-rw-r--r--drivers/net/wireless/ath/ath6kl/Kconfig15
-rw-r--r--drivers/net/wireless/ath/ath6kl/Makefile37
-rw-r--r--drivers/net/wireless/ath/ath6kl/bmi.c689
-rw-r--r--drivers/net/wireless/ath/ath6kl/bmi.h250
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c1914
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.h39
-rw-r--r--drivers/net/wireless/ath/ath6kl/common.h97
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h637
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.c934
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.h138
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif-ops.h77
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif.h208
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc.c2478
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc.h607
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_hif.c641
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_hif.h92
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c1727
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c1477
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c949
-rw-r--r--drivers/net/wireless/ath/ath6kl/target.h364
-rw-r--r--drivers/net/wireless/ath/ath6kl/testmode.c167
-rw-r--r--drivers/net/wireless/ath/ath6kl/testmode.h36
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c1478
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c3127
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h2282
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_initvals.h131
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c43
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9001_initvals.h266
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_calib.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c56
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_initvals.h3403
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_mac.c257
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h204
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c280
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c310
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c610
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c378
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_paprd.c24
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c123
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h130
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_rtt.c153
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_rtt.h28
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9462_1p0_initvals.h1833
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h1928
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h1673
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h34
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c80
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c32
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c493
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h68
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h17
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c272
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c169
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c241
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_gpio.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c29
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c33
-rw-r--r--drivers/net/wireless/ath/ath9k/hw-ops.h78
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c257
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h83
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c81
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c59
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h57
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c629
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c57
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c44
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c109
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h83
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c894
-rw-r--r--drivers/net/wireless/ath/carl9170/Kconfig14
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h24
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.c34
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.h1
-rw-r--r--drivers/net/wireless/ath/carl9170/fw.c3
-rw-r--r--drivers/net/wireless/ath/carl9170/fwcmd.h11
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c236
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.c16
-rw-r--r--drivers/net/wireless/ath/carl9170/version.h4
-rw-r--r--drivers/net/wireless/ath/main.c8
-rw-r--r--drivers/net/wireless/ath/regd.h2
-rw-r--r--drivers/net/wireless/ath/regd_common.h2
-rw-r--r--drivers/net/wireless/b43/Kconfig22
-rw-r--r--drivers/net/wireless/b43/b43.h77
-rw-r--r--drivers/net/wireless/b43/bus.c2
-rw-r--r--drivers/net/wireless/b43/dma.c157
-rw-r--r--drivers/net/wireless/b43/dma.h16
-rw-r--r--drivers/net/wireless/b43/main.c133
-rw-r--r--drivers/net/wireless/b43/phy_common.c32
-rw-r--r--drivers/net/wireless/b43/phy_common.h2
-rw-r--r--drivers/net/wireless/b43/phy_ht.c205
-rw-r--r--drivers/net/wireless/b43/phy_ht.h19
-rw-r--r--drivers/net/wireless/b43/phy_lcn.c853
-rw-r--r--drivers/net/wireless/b43/phy_lcn.h19
-rw-r--r--drivers/net/wireless/b43/phy_n.c575
-rw-r--r--drivers/net/wireless/b43/phy_n.h4
-rw-r--r--drivers/net/wireless/b43/pio.c12
-rw-r--r--drivers/net/wireless/b43/radio_2055.c1
-rw-r--r--drivers/net/wireless/b43/radio_2056.c2
-rw-r--r--drivers/net/wireless/b43/radio_2056.h26
-rw-r--r--drivers/net/wireless/b43/radio_2059.c2
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c1
-rw-r--r--drivers/net/wireless/b43/tables_phy_ht.c86
-rw-r--r--drivers/net/wireless/b43/tables_phy_ht.h4
-rw-r--r--drivers/net/wireless/b43/tables_phy_lcn.c690
-rw-r--r--drivers/net/wireless/b43/tables_phy_lcn.h18
-rw-r--r--drivers/net/wireless/b43/xmit.c138
-rw-r--r--drivers/net/wireless/b43/xmit.h72
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h21
-rw-r--r--drivers/net/wireless/b43legacy/dma.c374
-rw-r--r--drivers/net/wireless/b43legacy/dma.h107
-rw-r--r--drivers/net/wireless/b43legacy/main.c11
-rw-r--r--drivers/net/wireless/brcm80211/Kconfig (renamed from drivers/staging/brcm80211/Kconfig)15
-rw-r--r--drivers/net/wireless/brcm80211/Makefile (renamed from drivers/staging/brcm80211/Makefile)1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile (renamed from drivers/staging/brcm80211/brcmfmac/Makefile)12
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h (renamed from drivers/staging/brcm80211/brcmfmac/bcmchip.h)0
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c371
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c626
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h (renamed from drivers/staging/brcm80211/brcmfmac/dhd.h)526
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h (renamed from drivers/staging/brcm80211/brcmfmac/dhd_bus.h)39
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c (renamed from drivers/staging/brcm80211/brcmfmac/dhd_cdc.c)220
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c895
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h (renamed from drivers/staging/brcm80211/brcmfmac/dhd_dbg.h)46
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c1356
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h (renamed from drivers/staging/brcm80211/brcmfmac/dhd_proto.h)25
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c4591
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h252
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c (renamed from drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c)3394
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h (renamed from drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h)91
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/Makefile (renamed from drivers/staging/brcm80211/brcmsmac/Makefile)21
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/aiutils.c (renamed from drivers/staging/brcm80211/brcmsmac/aiutils.c)1248
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/aiutils.h (renamed from drivers/staging/brcm80211/brcmsmac/aiutils.h)310
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/ampdu.c (renamed from drivers/staging/brcm80211/brcmsmac/ampdu.c)594
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/ampdu.h (renamed from drivers/staging/brcm80211/brcmsmac/ampdu.h)0
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/antsel.c (renamed from drivers/staging/brcm80211/brcmsmac/antsel.c)240
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/antsel.h (renamed from drivers/staging/brcm80211/brcmsmac/antsel.h)0
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c (renamed from drivers/staging/brcm80211/brcmsmac/alloc.h)12
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h92
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.c (renamed from drivers/staging/brcm80211/brcmsmac/channel.c)1216
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.h53
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/d11.h (renamed from drivers/staging/brcm80211/brcmsmac/d11.h)705
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/dma.c1425
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/dma.h120
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c (renamed from drivers/staging/brcm80211/brcmsmac/mac80211_if.c)1552
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h (renamed from drivers/staging/brcm80211/brcmsmac/mac80211_if.h)44
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c8775
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.h735
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/nicpci.c (renamed from drivers/staging/brcm80211/brcmsmac/nicpci.c)181
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/nicpci.h (renamed from drivers/staging/brcm80211/brcmsmac/nicpci.h)41
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/otp.c (renamed from drivers/staging/brcm80211/brcmsmac/otp.c)237
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/otp.h (renamed from drivers/staging/brcm80211/brcmsmac/otp.h)15
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c)1163
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h)85
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/phy_int.h)212
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c)3478
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.h)0
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/phy_n.c)15452
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c)172
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.h)0
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/phy_radio.h)0
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/phyreg_n.h)0
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c)1236
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.h)0
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c (renamed from drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c)131
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h (renamed from drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h)24
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c (renamed from drivers/staging/brcm80211/brcmsmac/phy_shim.c)53
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h (renamed from drivers/staging/brcm80211/brcmsmac/phy_shim.h)82
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pmu.c (renamed from drivers/staging/brcm80211/brcmsmac/pmu.c)76
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pmu.h (renamed from drivers/staging/brcm80211/brcmsmac/pmu.h)14
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pub.h634
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/rate.c (renamed from drivers/staging/brcm80211/brcmsmac/rate.c)182
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/rate.h250
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/scb.h (renamed from drivers/staging/brcm80211/brcmsmac/scb.h)61
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/srom.c1298
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/srom.h (renamed from drivers/staging/brcm80211/brcmsmac/srom.h)4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/stf.c (renamed from drivers/staging/brcm80211/brcmsmac/stf.c)259
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/stf.h (renamed from drivers/staging/brcm80211/brcmsmac/stf.h)6
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/types.h352
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c109
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h (renamed from drivers/staging/brcm80211/brcmsmac/ucode_loader.h)50
-rw-r--r--drivers/net/wireless/brcm80211/brcmutil/Makefile (renamed from drivers/staging/brcm80211/brcmutil/Makefile)7
-rw-r--r--drivers/net/wireless/brcm80211/brcmutil/utils.c386
-rw-r--r--drivers/net/wireless/brcm80211/include/brcm_hw_ids.h (renamed from drivers/staging/brcm80211/include/brcm_hw_ids.h)0
-rw-r--r--drivers/net/wireless/brcm80211/include/brcmu_utils.h195
-rw-r--r--drivers/net/wireless/brcm80211/include/brcmu_wifi.h (renamed from drivers/staging/brcm80211/include/brcmu_wifi.h)190
-rw-r--r--drivers/net/wireless/brcm80211/include/chipcommon.h (renamed from drivers/staging/brcm80211/include/chipcommon.h)13
-rw-r--r--drivers/net/wireless/brcm80211/include/defs.h (renamed from drivers/staging/brcm80211/include/defs.h)32
-rw-r--r--drivers/net/wireless/brcm80211/include/soc.h (renamed from drivers/staging/brcm80211/include/soc.h)9
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c6
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c4
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c3
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_tx.c2
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945-led.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945-rs.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-led.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-rs.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-tx.c2
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-core.c6
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-core.h6
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-led.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl3945-base.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl4965-base.c1
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig43
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile38
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c58
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-2000.c90
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000-hw.h88
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c104
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c93
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c133
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c299
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hw.h32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c1120
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c117
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c (renamed from drivers/net/wireless/iwlwifi/iwl-rx.c)302
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c104
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-sta.c943
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tt.c82
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tt.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c992
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c119
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c1499
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h216
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-bus.h90
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-cfg.h (renamed from drivers/net/wireless/iwlwifi/iwl-6000-hw.h)66
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h62
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c405
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h179
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h48
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c450
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h556
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-devtrace.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c306
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fh.h20
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h184
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.c192
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h61
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-pci.c49
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c764
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-shared.h534
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c832
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h138
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sv-open.c30
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h82
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h436
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c1435
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c (renamed from drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c)699
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c1998
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c979
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c1115
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h278
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c6
-rw-r--r--drivers/net/wireless/libertas/README25
-rw-r--r--drivers/net/wireless/libertas/cfg.c120
-rw-r--r--drivers/net/wireless/libertas/cfg.h1
-rw-r--r--drivers/net/wireless/libertas/cmd.c6
-rw-r--r--drivers/net/wireless/libertas/decl.h6
-rw-r--r--drivers/net/wireless/libertas/dev.h30
-rw-r--r--drivers/net/wireless/libertas/ethtool.c1
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c277
-rw-r--r--drivers/net/wireless/libertas/if_spi.c4
-rw-r--r--drivers/net/wireless/libertas/if_usb.c34
-rw-r--r--drivers/net/wireless/libertas/main.c249
-rw-r--r--drivers/net/wireless/libertas/mesh.c79
-rw-r--r--drivers/net/wireless/libertas/mesh.h27
-rw-r--r--drivers/net/wireless/libertas/rx.c1
-rw-r--r--drivers/net/wireless/libertas/tx.c1
-rw-r--r--drivers/net/wireless/libertas_tf/deb_defs.h2
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c9
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c5
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.h1
-rw-r--r--drivers/net/wireless/mwifiex/Kconfig11
-rw-r--r--drivers/net/wireless/mwifiex/Makefile3
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c392
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.h3
-rw-r--r--drivers/net/wireless/mwifiex/cfp.c10
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c37
-rw-r--r--drivers/net/wireless/mwifiex/decl.h9
-rw-r--r--drivers/net/wireless/mwifiex/fw.h51
-rw-r--r--drivers/net/wireless/mwifiex/init.c96
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h5
-rw-r--r--drivers/net/wireless/mwifiex/join.c35
-rw-r--r--drivers/net/wireless/mwifiex/main.c282
-rw-r--r--drivers/net/wireless/mwifiex/main.h107
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c1948
-rw-r--r--drivers/net/wireless/mwifiex/pcie.h148
-rw-r--r--drivers/net/wireless/mwifiex/scan.c1647
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c19
-rw-r--r--drivers/net/wireless/mwifiex/sdio.h24
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c64
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c2
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c9
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c295
-rw-r--r--drivers/net/wireless/mwifiex/sta_tx.c2
-rw-r--r--drivers/net/wireless/mwifiex/txrx.c45
-rw-r--r--drivers/net/wireless/mwifiex/util.c5
-rw-r--r--drivers/net/wireless/mwifiex/util.h9
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c36
-rw-r--r--drivers/net/wireless/mwl8k.c16
-rw-r--r--drivers/net/wireless/orinoco/main.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c2
-rw-r--r--drivers/net/wireless/orinoco/wext.c1
-rw-r--r--drivers/net/wireless/p54/eeprom.c26
-rw-r--r--drivers/net/wireless/p54/fwio.c2
-rw-r--r--drivers/net/wireless/p54/main.c116
-rw-r--r--drivers/net/wireless/p54/p54.h18
-rw-r--r--drivers/net/wireless/p54/p54spi.c2
-rw-r--r--drivers/net/wireless/p54/txrx.c72
-rw-r--r--drivers/net/wireless/ray_cs.c2
-rw-r--r--drivers/net/wireless/rndis_wlan.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c49
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c42
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h3
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c198
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h10
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c61
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c7
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h33
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c22
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c53
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c7
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h5
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c41
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c7
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c5
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/dev.c5
-rw-r--r--drivers/net/wireless/rtlwifi/Kconfig4
-rw-r--r--drivers/net/wireless/rtlwifi/base.c167
-rw-r--r--drivers/net/wireless/rtlwifi/base.h2
-rw-r--r--drivers/net/wireless/rtlwifi/core.c11
-rw-r--r--drivers/net/wireless/rtlwifi/debug.c2
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c62
-rw-r--r--drivers/net/wireless/rtlwifi/pci.h30
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/def.h153
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/sw.c77
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/trx.c116
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/trx.h6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/def.h4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/mac.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/mac.h6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/rf.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/sw.c35
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/trx.c23
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/def.h170
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/hw.c15
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/sw.c63
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/trx.c121
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/trx.h6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/def.h41
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/hw.c22
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/reg.h1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/sw.c64
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/trx.c169
-rw-r--r--drivers/net/wireless/rtlwifi/usb.c40
-rw-r--r--drivers/net/wireless/rtlwifi/wifi.h54
-rw-r--r--drivers/net/wireless/wl1251/cmd.h2
-rw-r--r--drivers/net/wireless/wl1251/main.c3
-rw-r--r--drivers/net/wireless/wl1251/wl12xx_80211.h2
-rw-r--r--drivers/net/wireless/wl12xx/Kconfig10
-rw-r--r--drivers/net/wireless/wl12xx/Makefile6
-rw-r--r--drivers/net/wireless/wl12xx/acx.c378
-rw-r--r--drivers/net/wireless/wl12xx/acx.h413
-rw-r--r--drivers/net/wireless/wl12xx/boot.c51
-rw-r--r--drivers/net/wireless/wl12xx/boot.h3
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c866
-rw-r--r--drivers/net/wireless/wl12xx/cmd.h354
-rw-r--r--drivers/net/wireless/wl12xx/conf.h387
-rw-r--r--drivers/net/wireless/wl12xx/debugfs.c105
-rw-r--r--drivers/net/wireless/wl12xx/event.c56
-rw-r--r--drivers/net/wireless/wl12xx/event.h80
-rw-r--r--drivers/net/wireless/wl12xx/init.c113
-rw-r--r--drivers/net/wireless/wl12xx/io.h1
-rw-r--r--drivers/net/wireless/wl12xx/main.c1345
-rw-r--r--drivers/net/wireless/wl12xx/ps.c12
-rw-r--r--drivers/net/wireless/wl12xx/reg.h75
-rw-r--r--drivers/net/wireless/wl12xx/rx.c69
-rw-r--r--drivers/net/wireless/wl12xx/rx.h18
-rw-r--r--drivers/net/wireless/wl12xx/scan.c200
-rw-r--r--drivers/net/wireless/wl12xx/scan.h31
-rw-r--r--drivers/net/wireless/wl12xx/sdio.c4
-rw-r--r--drivers/net/wireless/wl12xx/sdio_test.c17
-rw-r--r--drivers/net/wireless/wl12xx/spi.c4
-rw-r--r--drivers/net/wireless/wl12xx/tx.c192
-rw-r--r--drivers/net/wireless/wl12xx/tx.h26
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h174
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx_80211.h27
-rw-r--r--drivers/net/wireless/wl3501_cs.c2
-rw-r--r--drivers/net/wireless/zd1201.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c2
-rw-r--r--drivers/net/xen-netback/netback.c58
-rw-r--r--drivers/net/xen-netfront.c38
-rw-r--r--drivers/nfc/Kconfig11
-rw-r--r--drivers/nfc/Makefile1
-rw-r--r--drivers/nfc/nfcwilink.c342
-rw-r--r--drivers/nfc/pn533.c21
-rw-r--r--drivers/of/base.c234
-rw-r--r--drivers/of/fdt.c6
-rw-r--r--drivers/of/irq.c121
-rw-r--r--drivers/of/of_mdio.c1
-rw-r--r--drivers/of/pdt.c8
-rw-r--r--drivers/oprofile/event_buffer.c4
-rw-r--r--drivers/oprofile/oprofile_perf.c4
-rw-r--r--drivers/oprofile/oprofilefs.c6
-rw-r--r--drivers/parisc/sba_iommu.c16
-rw-r--r--drivers/parport/parport_pc.c3
-rw-r--r--drivers/pci/Kconfig26
-rw-r--r--drivers/pci/Makefile1
-rw-r--r--drivers/pci/ats.c438
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c109
-rw-r--r--drivers/pci/iov.c142
-rw-r--r--drivers/pci/pci-acpi.c6
-rw-r--r--drivers/pci/pci.c59
-rw-r--r--drivers/pci/pcie/pme.c9
-rw-r--r--drivers/pci/probe.c68
-rw-r--r--drivers/pci/quirks.c113
-rw-r--r--drivers/pci/setup-bus.c2
-rw-r--r--drivers/pci/xen-pcifront.c5
-rw-r--r--drivers/pcmcia/pxa2xx_balloon3.c2
-rw-r--r--drivers/pcmcia/pxa2xx_vpac270.c2
-rw-r--r--drivers/pcmcia/sa1100_simpad.c35
-rw-r--r--drivers/pinctrl/Kconfig43
-rw-r--r--drivers/pinctrl/Makefile8
-rw-r--r--drivers/pinctrl/core.c598
-rw-r--r--drivers/pinctrl/core.h71
-rw-r--r--drivers/pinctrl/pinmux-sirf.c1215
-rw-r--r--drivers/pinctrl/pinmux-u300.c1135
-rw-r--r--drivers/pinctrl/pinmux.c1190
-rw-r--r--drivers/pinctrl/pinmux.h47
-rw-r--r--drivers/platform/x86/Kconfig22
-rw-r--r--drivers/platform/x86/acer-wmi.c488
-rw-r--r--drivers/platform/x86/asus-laptop.c378
-rw-r--r--drivers/platform/x86/asus-wmi.c4
-rw-r--r--drivers/platform/x86/dell-laptop.c84
-rw-r--r--drivers/platform/x86/eeepc-laptop.c2
-rw-r--r--drivers/platform/x86/hp_accel.c15
-rw-r--r--drivers/platform/x86/ideapad-laptop.c251
-rw-r--r--drivers/platform/x86/intel_scu_ipcutil.c8
-rw-r--r--drivers/platform/x86/samsung-laptop.c107
-rw-r--r--drivers/platform/x86/sony-laptop.c2
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c2
-rw-r--r--drivers/platform/x86/topstar-laptop.c1
-rw-r--r--drivers/platform/x86/toshiba_acpi.c641
-rw-r--r--drivers/platform/x86/wmi.c6
-rw-r--r--drivers/power/Kconfig1
-rw-r--r--drivers/power/ds2780_battery.c86
-rw-r--r--drivers/pps/clients/Kconfig9
-rw-r--r--drivers/pps/clients/Makefile1
-rw-r--r--drivers/pps/clients/pps-gpio.c227
-rw-r--r--drivers/pps/clients/pps-ktimer.c12
-rw-r--r--drivers/pps/clients/pps_parport.c9
-rw-r--r--drivers/pps/kapi.c20
-rw-r--r--drivers/rapidio/Kconfig6
-rw-r--r--drivers/rapidio/Makefile1
-rw-r--r--drivers/rapidio/devices/Kconfig10
-rw-r--r--drivers/rapidio/devices/Makefile5
-rw-r--r--drivers/rapidio/devices/tsi721.c2360
-rw-r--r--drivers/rapidio/devices/tsi721.h766
-rw-r--r--drivers/rapidio/rio-scan.c6
-rw-r--r--drivers/regulator/88pm8607.c2
-rw-r--r--drivers/regulator/Kconfig10
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/aat2870-regulator.c1
-rw-r--r--drivers/regulator/core.c107
-rw-r--r--drivers/regulator/gpio-regulator.c358
-rw-r--r--drivers/regulator/max8649.c2
-rw-r--r--drivers/regulator/max8952.c3
-rw-r--r--drivers/regulator/tps65023-regulator.c183
-rw-r--r--drivers/regulator/tps6507x-regulator.c8
-rw-r--r--drivers/regulator/tps6586x-regulator.c32
-rw-r--r--drivers/regulator/tps65912-regulator.c2
-rw-r--r--drivers/regulator/wm8994-regulator.c13
-rw-r--r--drivers/rtc/Kconfig2
-rw-r--r--drivers/rtc/class.c32
-rw-r--r--drivers/rtc/rtc-ds1307.c27
-rw-r--r--drivers/rtc/rtc-mc13xxx.c6
-rw-r--r--drivers/s390/block/dasd.c19
-rw-r--r--drivers/s390/block/dasd_eckd.c45
-rw-r--r--drivers/s390/block/dasd_fba.c1
-rw-r--r--drivers/s390/block/dasd_int.h2
-rw-r--r--drivers/s390/char/con3215.c3
-rw-r--r--drivers/s390/char/raw3270.c3
-rw-r--r--drivers/s390/char/sclp_cmd.c4
-rw-r--r--drivers/s390/char/sclp_quiesce.c3
-rw-r--r--drivers/s390/char/tape_34xx.c1
-rw-r--r--drivers/s390/char/tape_3590.c1
-rw-r--r--drivers/s390/char/tape_core.c2
-rw-r--r--drivers/s390/char/vmur.c3
-rw-r--r--drivers/s390/char/zcore.c21
-rw-r--r--drivers/s390/cio/blacklist.c3
-rw-r--r--drivers/s390/cio/ccwgroup.c333
-rw-r--r--drivers/s390/cio/ccwreq.c23
-rw-r--r--drivers/s390/cio/chsc_sch.c5
-rw-r--r--drivers/s390/cio/cio.c19
-rw-r--r--drivers/s390/cio/css.h2
-rw-r--r--drivers/s390/cio/device.c13
-rw-r--r--drivers/s390/cio/device.h13
-rw-r--r--drivers/s390/cio/io_sch.h2
-rw-r--r--drivers/s390/cio/qdio.h50
-rw-r--r--drivers/s390/cio/qdio_debug.c13
-rw-r--r--drivers/s390/cio/qdio_main.c309
-rw-r--r--drivers/s390/cio/qdio_setup.c84
-rw-r--r--drivers/s390/cio/qdio_thinint.c138
-rw-r--r--drivers/s390/kvm/kvm_virtio.c8
-rw-r--r--drivers/s390/net/claw.c3
-rw-r--r--drivers/s390/net/ctcm_main.c3
-rw-r--r--drivers/s390/net/ctcm_sysfs.c2
-rw-r--r--drivers/s390/net/lcs.c7
-rw-r--r--drivers/s390/net/qeth_core.h50
-rw-r--r--drivers/s390/net/qeth_core_main.c780
-rw-r--r--drivers/s390/net/qeth_l2_main.c4
-rw-r--r--drivers/s390/net/qeth_l3.h4
-rw-r--r--drivers/s390/net/qeth_l3_main.c94
-rw-r--r--drivers/s390/net/qeth_l3_sys.c110
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c36
-rw-r--r--drivers/s390/scsi/zfcp_def.h7
-rw-r--r--drivers/s390/scsi/zfcp_ext.h1
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c80
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c58
-rw-r--r--drivers/s390/scsi/zfcp_qdio.h66
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c15
-rw-r--r--drivers/scsi/Kconfig14
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/aacraid/linit.c7
-rw-r--r--drivers/scsi/aacraid/src.c1
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic79xx3
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx3
-rw-r--r--drivers/scsi/aic94xx/aic94xx_dump.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_scb.c1
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c20
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.h2
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c60
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.h2
-rw-r--r--drivers/scsi/be2iscsi/be_main.c112
-rw-r--r--drivers/scsi/be2iscsi/be_main.h5
-rw-r--r--drivers/scsi/bfa/bfad_drv.h1
-rw-r--r--drivers/scsi/bnx2fc/Kconfig3
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h7
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_els.c26
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c232
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c16
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c32
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c23
-rw-r--r--drivers/scsi/bnx2i/Kconfig3
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h2
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c80
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/Kbuild2
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/Kconfig3
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/cxgb3i.c21
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/Kbuild2
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/Kconfig3
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c21
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.c78
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.h3
-rw-r--r--drivers/scsi/device_handler/scsi_dh.c61
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c107
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c6
-rw-r--r--drivers/scsi/fcoe/fcoe.c110
-rw-r--r--drivers/scsi/fcoe/fcoe.h11
-rw-r--r--drivers/scsi/fcoe/fcoe_transport.c108
-rw-r--r--drivers/scsi/hpsa.c6
-rw-r--r--drivers/scsi/ipr.c31
-rw-r--r--drivers/scsi/ipr.h4
-rw-r--r--drivers/scsi/isci/host.c69
-rw-r--r--drivers/scsi/isci/host.h15
-rw-r--r--drivers/scsi/isci/init.c3
-rw-r--r--drivers/scsi/isci/isci.h2
-rw-r--r--drivers/scsi/isci/phy.c13
-rw-r--r--drivers/scsi/isci/port.c2
-rw-r--r--drivers/scsi/isci/port_config.c2
-rw-r--r--drivers/scsi/isci/registers.h122
-rw-r--r--drivers/scsi/isci/remote_device.c24
-rw-r--r--drivers/scsi/isci/remote_device.h9
-rw-r--r--drivers/scsi/isci/request.c380
-rw-r--r--drivers/scsi/isci/request.h31
-rw-r--r--drivers/scsi/isci/sas.h2
-rw-r--r--drivers/scsi/isci/task.c29
-rw-r--r--drivers/scsi/isci/task.h19
-rw-r--r--drivers/scsi/iscsi_tcp.c83
-rw-r--r--drivers/scsi/libfc/fc_exch.c11
-rw-r--r--drivers/scsi/libfc/fc_fcp.c2
-rw-r--r--drivers/scsi/libiscsi.c9
-rw-r--r--drivers/scsi/libsas/sas_discover.c13
-rw-r--r--drivers/scsi/libsas/sas_expander.c37
-rw-r--r--drivers/scsi/libsas/sas_host_smp.c103
-rw-r--r--drivers/scsi/libsas/sas_init.c43
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c145
-rw-r--r--drivers/scsi/lpfc/lpfc.h20
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c79
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c181
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c33
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h300
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c287
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c80
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c244
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c460
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h18
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h23
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c16
-rw-r--r--drivers/scsi/mac_esp.c9
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h22
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c239
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c26
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c193
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.h19
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c448
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h46
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_config.c1
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c29
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c3
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c2
-rw-r--r--drivers/scsi/mvsas/mv_94xx.c35
-rw-r--r--drivers/scsi/mvsas/mv_defs.h2
-rw-r--r--drivers/scsi/mvsas/mv_init.c13
-rw-r--r--drivers/scsi/mvsas/mv_sas.c79
-rw-r--r--drivers/scsi/mvsas/mv_sas.h5
-rw-r--r--drivers/scsi/mvumi.c2018
-rw-r--r--drivers/scsi/mvumi.h505
-rw-r--r--drivers/scsi/osd/Kconfig4
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c73
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c4
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c93
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h2
-rw-r--r--drivers/scsi/pmcraid.c1
-rw-r--r--drivers/scsi/pmcraid.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c111
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c152
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.h42
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h9
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h18
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c36
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c5
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c127
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c970
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.h255
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c46
-rw-r--r--drivers/scsi/qla4xxx/Kconfig1
-rw-r--r--drivers/scsi/qla4xxx/Makefile2
-rw-r--r--drivers/scsi/qla4xxx/ql4_attr.c76
-rw-r--r--drivers/scsi/qla4xxx/ql4_bsg.c513
-rw-r--r--drivers/scsi/qla4xxx/ql4_bsg.h19
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h214
-rw-r--r--drivers/scsi/qla4xxx/ql4_fw.h198
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h71
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c852
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c68
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c83
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c824
-rw-r--r--drivers/scsi/qla4xxx/ql4_nvram.c21
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c17
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c2321
-rw-r--r--drivers/scsi/qla4xxx/ql4_version.h2
-rw-r--r--drivers/scsi/qlogicpti.c2
-rw-r--r--drivers/scsi/scsi_error.c12
-rw-r--r--drivers/scsi/scsi_sysfs.c38
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c742
-rw-r--r--drivers/scsi/scsi_transport_sas.c10
-rw-r--r--drivers/scsi/sd.c7
-rw-r--r--drivers/scsi/sg.c18
-rw-r--r--drivers/sh/intc/chip.c9
-rw-r--r--drivers/sh/intc/userimask.c1
-rw-r--r--drivers/sh/pfc.c29
-rw-r--r--drivers/spi/spi-altera.c13
-rw-r--r--drivers/spi/spi-ath79.c13
-rw-r--r--drivers/spi/spi-atmel.c15
-rw-r--r--drivers/spi/spi-bfin-sport.c13
-rw-r--r--drivers/spi/spi-bfin5xx.c2
-rw-r--r--drivers/spi/spi-coldfire-qspi.c16
-rw-r--r--drivers/spi/spi-davinci.c20
-rw-r--r--drivers/spi/spi-dw-mid.c9
-rw-r--r--drivers/spi/spi-dw-mmio.c14
-rw-r--r--drivers/spi/spi-dw.c62
-rw-r--r--drivers/spi/spi-dw.h97
-rw-r--r--drivers/spi/spi-ep93xx.c21
-rw-r--r--drivers/spi/spi-fsl-espi.c13
-rw-r--r--drivers/spi/spi-gpio.c21
-rw-r--r--drivers/spi/spi-imx.c14
-rw-r--r--drivers/spi/spi-mpc512x-psc.c13
-rw-r--r--drivers/spi/spi-mpc52xx-psc.c13
-rw-r--r--drivers/spi/spi-mpc52xx.c14
-rw-r--r--drivers/spi/spi-nuc900.c14
-rw-r--r--drivers/spi/spi-oc-tiny.c13
-rw-r--r--drivers/spi/spi-omap2-mcspi.c7
-rw-r--r--drivers/spi/spi-pl022.c238
-rw-r--r--drivers/spi/spi-ppc4xx.c15
-rw-r--r--drivers/spi/spi-s3c24xx.c21
-rw-r--r--drivers/spi/spi-sh-msiof.c15
-rw-r--r--drivers/spi/spi-sh-sci.c13
-rw-r--r--drivers/spi/spi-sh.c15
-rw-r--r--drivers/spi/spi-stmp.c13
-rw-r--r--drivers/spi/spi-tegra.c17
-rw-r--r--drivers/spi/spi-ti-ssp.c13
-rw-r--r--drivers/spi/spi-xilinx.c13
-rw-r--r--drivers/ssb/main.c24
-rw-r--r--drivers/staging/Kconfig14
-rw-r--r--drivers/staging/Makefile7
-rw-r--r--drivers/staging/altera-stapl/Makefile3
-rw-r--r--drivers/staging/ath6kl/Kconfig158
-rw-r--r--drivers/staging/ath6kl/Makefile122
-rw-r--r--drivers/staging/ath6kl/TODO25
-rw-r--r--drivers/staging/ath6kl/bmi/include/bmi_internal.h54
-rw-r--r--drivers/staging/ath6kl/bmi/src/bmi.c1010
-rw-r--r--drivers/staging/ath6kl/hif/common/hif_sdio_common.h87
-rw-r--r--drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h131
-rw-r--r--drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c1273
-rw-r--r--drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c393
-rw-r--r--drivers/staging/ath6kl/htc2/AR6000/ar6k.c1479
-rw-r--r--drivers/staging/ath6kl/htc2/AR6000/ar6k.h401
-rw-r--r--drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c783
-rw-r--r--drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c755
-rw-r--r--drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c1284
-rw-r--r--drivers/staging/ath6kl/htc2/htc.c575
-rw-r--r--drivers/staging/ath6kl/htc2/htc_debug.h38
-rw-r--r--drivers/staging/ath6kl/htc2/htc_internal.h211
-rw-r--r--drivers/staging/ath6kl/htc2/htc_recv.c1572
-rw-r--r--drivers/staging/ath6kl/htc2/htc_send.c1018
-rw-r--r--drivers/staging/ath6kl/htc2/htc_services.c450
-rw-r--r--drivers/staging/ath6kl/include/a_config.h31
-rw-r--r--drivers/staging/ath6kl/include/a_debug.h195
-rw-r--r--drivers/staging/ath6kl/include/a_drv.h32
-rw-r--r--drivers/staging/ath6kl/include/a_drv_api.h204
-rw-r--r--drivers/staging/ath6kl/include/a_osapi.h32
-rw-r--r--drivers/staging/ath6kl/include/aggr_recv_api.h140
-rw-r--r--drivers/staging/ath6kl/include/ar3kconfig.h65
-rw-r--r--drivers/staging/ath6kl/include/ar6000_api.h32
-rw-r--r--drivers/staging/ath6kl/include/ar6000_diag.h48
-rw-r--r--drivers/staging/ath6kl/include/ar6kap_common.h44
-rw-r--r--drivers/staging/ath6kl/include/athbtfilter.h135
-rw-r--r--drivers/staging/ath6kl/include/bmi.h134
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h52
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/addrs.h90
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h40
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h40
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h24
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h552
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h471
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h589
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h187
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h162
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h40
-rw-r--r--drivers/staging/ath6kl/include/common/athdefs.h75
-rw-r--r--drivers/staging/ath6kl/include/common/bmi_msg.h233
-rw-r--r--drivers/staging/ath6kl/include/common/cnxmgmt.h36
-rw-r--r--drivers/staging/ath6kl/include/common/dbglog.h126
-rw-r--r--drivers/staging/ath6kl/include/common/dbglog_id.h558
-rw-r--r--drivers/staging/ath6kl/include/common/discovery.h75
-rw-r--r--drivers/staging/ath6kl/include/common/epping_test.h111
-rw-r--r--drivers/staging/ath6kl/include/common/gmboxif.h70
-rw-r--r--drivers/staging/ath6kl/include/common/gpio_reg.h9
-rw-r--r--drivers/staging/ath6kl/include/common/htc.h227
-rw-r--r--drivers/staging/ath6kl/include/common/htc_services.h52
-rw-r--r--drivers/staging/ath6kl/include/common/pkt_log.h45
-rw-r--r--drivers/staging/ath6kl/include/common/roaming.h41
-rw-r--r--drivers/staging/ath6kl/include/common/targaddrs.h395
-rw-r--r--drivers/staging/ath6kl/include/common/testcmd.h185
-rw-r--r--drivers/staging/ath6kl/include/common/tlpm.h38
-rw-r--r--drivers/staging/ath6kl/include/common/wlan_defs.h79
-rw-r--r--drivers/staging/ath6kl/include/common/wmi.h3220
-rw-r--r--drivers/staging/ath6kl/include/common/wmix.h271
-rw-r--r--drivers/staging/ath6kl/include/common_drv.h104
-rw-r--r--drivers/staging/ath6kl/include/dbglog_api.h52
-rw-r--r--drivers/staging/ath6kl/include/dl_list.h153
-rw-r--r--drivers/staging/ath6kl/include/dset_api.h65
-rw-r--r--drivers/staging/ath6kl/include/hci_transport_api.h259
-rw-r--r--drivers/staging/ath6kl/include/hif.h456
-rw-r--r--drivers/staging/ath6kl/include/host_version.h52
-rw-r--r--drivers/staging/ath6kl/include/htc_api.h575
-rw-r--r--drivers/staging/ath6kl/include/htc_packet.h227
-rw-r--r--drivers/staging/ath6kl/include/wlan_api.h128
-rw-r--r--drivers/staging/ath6kl/include/wmi_api.h441
-rw-r--r--drivers/staging/ath6kl/miscdrv/ar3kconfig.c565
-rw-r--r--drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c572
-rw-r--r--drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h75
-rw-r--r--drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c969
-rw-r--r--drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h113
-rw-r--r--drivers/staging/ath6kl/miscdrv/common_drv.c910
-rw-r--r--drivers/staging/ath6kl/miscdrv/credit_dist.c417
-rw-r--r--drivers/staging/ath6kl/miscdrv/miscdrv.h42
-rw-r--r--drivers/staging/ath6kl/os/linux/ar6000_drv.c6267
-rw-r--r--drivers/staging/ath6kl/os/linux/ar6000_pm.c626
-rw-r--r--drivers/staging/ath6kl/os/linux/ar6000_raw_if.c455
-rw-r--r--drivers/staging/ath6kl/os/linux/cfg80211.c1892
-rw-r--r--drivers/staging/ath6kl/os/linux/export_hci_transport.c124
-rw-r--r--drivers/staging/ath6kl/os/linux/hci_bridge.c1141
-rw-r--r--drivers/staging/ath6kl/os/linux/include/ar6000_drv.h776
-rw-r--r--drivers/staging/ath6kl/os/linux/include/ar6k_pal.h36
-rw-r--r--drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h190
-rw-r--r--drivers/staging/ath6kl/os/linux/include/athdrv_linux.h1217
-rw-r--r--drivers/staging/ath6kl/os/linux/include/cfg80211.h61
-rw-r--r--drivers/staging/ath6kl/os/linux/include/config_linux.h51
-rw-r--r--drivers/staging/ath6kl/os/linux/include/debug_linux.h50
-rw-r--r--drivers/staging/ath6kl/os/linux/include/export_hci_transport.h76
-rw-r--r--drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h177
-rw-r--r--drivers/staging/ath6kl/os/linux/include/osapi_linux.h339
-rw-r--r--drivers/staging/ath6kl/os/linux/include/wlan_config.h108
-rw-r--r--drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h300
-rw-r--r--drivers/staging/ath6kl/os/linux/netbuf.c231
-rw-r--r--drivers/staging/ath6kl/reorder/aggr_rx_internal.h117
-rw-r--r--drivers/staging/ath6kl/reorder/rcv_aggr.c661
-rw-r--r--drivers/staging/ath6kl/wlan/include/ieee80211.h397
-rw-r--r--drivers/staging/ath6kl/wlan/include/ieee80211_node.h93
-rw-r--r--drivers/staging/ath6kl/wlan/src/wlan_node.c636
-rw-r--r--drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c199
-rw-r--r--drivers/staging/ath6kl/wlan/src/wlan_utils.c58
-rw-r--r--drivers/staging/ath6kl/wmi/wmi.c6444
-rw-r--r--drivers/staging/ath6kl/wmi/wmi_host.h102
-rw-r--r--drivers/staging/bcm/Bcmchar.c3171
-rw-r--r--drivers/staging/bcm/InterfaceDld.c456
-rw-r--r--drivers/staging/bcm/InterfaceInit.c39
-rw-r--r--drivers/staging/bcm/InterfaceMisc.c304
-rw-r--r--drivers/staging/bcm/Macros.h337
-rw-r--r--drivers/staging/bcm/Misc.c1833
-rw-r--r--drivers/staging/bcm/headers.h2
-rw-r--r--drivers/staging/bcm/nvm.c13
-rw-r--r--drivers/staging/brcm80211/README1
-rw-r--r--drivers/staging/brcm80211/TODO13
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh.c642
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c1196
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_common.c1196
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_linux.c1736
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_sdio.c6772
-rw-r--r--drivers/staging/brcm80211/brcmfmac/sdio_host.h347
-rw-r--r--drivers/staging/brcm80211/brcmsmac/alloc.c275
-rw-r--r--drivers/staging/brcm80211/brcmsmac/bmac.c3593
-rw-r--r--drivers/staging/brcm80211/brcmsmac/bmac.h174
-rw-r--r--drivers/staging/brcm80211/brcmsmac/channel.h132
-rw-r--r--drivers/staging/brcm80211/brcmsmac/dma.c1917
-rw-r--r--drivers/staging/brcm80211/brcmsmac/dma.h250
-rw-r--r--drivers/staging/brcm80211/brcmsmac/main.c6102
-rw-r--r--drivers/staging/brcm80211/brcmsmac/main.h1025
-rw-r--r--drivers/staging/brcm80211/brcmsmac/pub.h665
-rw-r--r--drivers/staging/brcm80211/brcmsmac/rate.h173
-rw-r--r--drivers/staging/brcm80211/brcmsmac/srom.c1237
-rw-r--r--drivers/staging/brcm80211/brcmsmac/types.h399
-rw-r--r--drivers/staging/brcm80211/brcmsmac/ucode_loader.c115
-rw-r--r--drivers/staging/brcm80211/brcmutil/utils.c787
-rw-r--r--drivers/staging/brcm80211/brcmutil/wifi.c131
-rw-r--r--drivers/staging/brcm80211/include/brcmu_utils.h301
-rw-r--r--drivers/staging/comedi/Kconfig18
-rw-r--r--drivers/staging/comedi/comedi_fops.c2
-rw-r--r--drivers/staging/comedi/drivers/Makefile1
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c2
-rw-r--r--drivers/staging/comedi/drivers/c6xdigio.c13
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c5
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio.c10
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c18
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c2
-rw-r--r--drivers/staging/comedi/drivers/pcmmio.c34
-rw-r--r--drivers/staging/comedi/drivers/usbduxsigma.c2880
-rw-r--r--drivers/staging/crystalhd/bc_dts_defs.h4
-rw-r--r--drivers/staging/crystalhd/bc_dts_glob_lnx.h6
-rw-r--r--drivers/staging/crystalhd/bc_dts_types.h57
-rw-r--r--drivers/staging/crystalhd/crystalhd_cmds.h2
-rw-r--r--drivers/staging/crystalhd/crystalhd_fw_if.h532
-rw-r--r--drivers/staging/crystalhd/crystalhd_misc.h6
-rw-r--r--drivers/staging/cx25821/cx25821-alsa.c2
-rw-r--r--drivers/staging/cx25821/cx25821-audio-upstream.c43
-rw-r--r--drivers/staging/cx25821/cx25821-audio-upstream.h9
-rw-r--r--drivers/staging/cx25821/cx25821-audio.h6
-rw-r--r--drivers/staging/cx25821/cx25821-cards.c26
-rw-r--r--drivers/staging/cx25821/cx25821-core.c505
-rw-r--r--drivers/staging/cx25821/cx25821-gpio.c1
-rw-r--r--drivers/staging/cx25821/cx25821-gpio.h2
-rw-r--r--drivers/staging/cx25821/cx25821-i2c.c30
-rw-r--r--drivers/staging/cx25821/cx25821-video-upstream-ch2.c81
-rw-r--r--drivers/staging/cx25821/cx25821-video-upstream-ch2.h83
-rw-r--r--drivers/staging/cx25821/cx25821-video-upstream.c18
-rw-r--r--drivers/staging/cx25821/cx25821-video-upstream.h78
-rw-r--r--drivers/staging/cx25821/cx25821-video.c1244
-rw-r--r--drivers/staging/cx25821/cx25821-video.h79
-rw-r--r--drivers/staging/cx25821/cx25821.h10
-rw-r--r--drivers/staging/cxd2099/Makefile6
-rw-r--r--drivers/staging/cxt1e1/Kconfig3
-rw-r--r--drivers/staging/cxt1e1/linux.c6
-rw-r--r--drivers/staging/cxt1e1/sbecom_inline_linux.h64
-rw-r--r--drivers/staging/dt3155v4l/dt3155v4l.c126
-rw-r--r--drivers/staging/dt3155v4l/dt3155v4l.h4
-rw-r--r--drivers/staging/easycap/easycap.h11
-rw-r--r--drivers/staging/easycap/easycap_ioctl.c32
-rw-r--r--drivers/staging/easycap/easycap_main.c54
-rw-r--r--drivers/staging/easycap/easycap_sound.c3
-rw-r--r--drivers/staging/et131x/Kconfig11
-rw-r--r--drivers/staging/et131x/Makefile10
-rw-r--r--drivers/staging/et131x/README15
-rw-r--r--drivers/staging/et131x/et1310_address_map.h1434
-rw-r--r--drivers/staging/et131x/et1310_eeprom.c407
-rw-r--r--drivers/staging/et131x/et1310_mac.c654
-rw-r--r--drivers/staging/et131x/et1310_phy.c979
-rw-r--r--drivers/staging/et131x/et1310_phy.h458
-rw-r--r--drivers/staging/et131x/et1310_pm.c180
-rw-r--r--drivers/staging/et131x/et1310_rx.c1152
-rw-r--r--drivers/staging/et131x/et1310_rx.h243
-rw-r--r--drivers/staging/et131x/et1310_tx.c797
-rw-r--r--drivers/staging/et131x/et1310_tx.h150
-rw-r--r--drivers/staging/et131x/et131x.c5514
-rw-r--r--drivers/staging/et131x/et131x.h1721
-rw-r--r--drivers/staging/et131x/et131x_adapter.h243
-rw-r--r--drivers/staging/et131x/et131x_defs.h126
-rw-r--r--drivers/staging/et131x/et131x_initpci.c848
-rw-r--r--drivers/staging/et131x/et131x_isr.c480
-rw-r--r--drivers/staging/et131x/et131x_netdev.c686
-rw-r--r--drivers/staging/et131x/et131x_version.h74
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000.h10
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c8
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c3
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c24
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c4
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_hw.c2
-rw-r--r--drivers/staging/gma500/accel_2d.c24
-rw-r--r--drivers/staging/gma500/cdv_device.c1
-rw-r--r--drivers/staging/gma500/framebuffer.c92
-rw-r--r--drivers/staging/gma500/gem.c5
-rw-r--r--drivers/staging/gma500/gtt.c81
-rw-r--r--drivers/staging/gma500/gtt.h3
-rw-r--r--drivers/staging/gma500/intel_opregion.c1
-rw-r--r--drivers/staging/gma500/mdfld_intel_display.c12
-rw-r--r--drivers/staging/gma500/mrst_crtc.c16
-rw-r--r--drivers/staging/gma500/power.c8
-rw-r--r--drivers/staging/gma500/psb_device.c32
-rw-r--r--drivers/staging/gma500/psb_drv.c49
-rw-r--r--drivers/staging/gma500/psb_drv.h6
-rw-r--r--drivers/staging/gma500/psb_intel_display.c4
-rw-r--r--drivers/staging/gma500/psb_intel_lvds.c61
-rw-r--r--drivers/staging/gma500/psb_irq.c71
-rw-r--r--drivers/staging/gma500/psb_lid.c2
-rw-r--r--drivers/staging/go7007/Makefile8
-rw-r--r--drivers/staging/go7007/wis-tw2804.c6
-rw-r--r--drivers/staging/hv/Kconfig35
-rw-r--r--drivers/staging/hv/Makefile10
-rw-r--r--drivers/staging/hv/TODO11
-rw-r--r--drivers/staging/hv/blkvsc_drv.c1026
-rw-r--r--drivers/staging/hv/hv_mouse.c715
-rw-r--r--drivers/staging/hv/hv_timesource.c101
-rw-r--r--drivers/staging/hv/hyperv_net.h7
-rw-r--r--drivers/staging/hv/hyperv_storage.h334
-rw-r--r--drivers/staging/hv/netvsc.c329
-rw-r--r--drivers/staging/hv/netvsc_drv.c156
-rw-r--r--drivers/staging/hv/rndis_filter.c146
-rw-r--r--drivers/staging/hv/storvsc.c564
-rw-r--r--drivers/staging/hv/storvsc_drv.c892
-rw-r--r--drivers/staging/iio/Documentation/generic_buffer.c12
-rw-r--r--drivers/staging/iio/Documentation/iio_utils.h2
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio738
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a21
-rw-r--r--drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad593330
-rw-r--r--drivers/staging/iio/Kconfig35
-rw-r--r--drivers/staging/iio/Makefile11
-rw-r--r--drivers/staging/iio/accel/Kconfig33
-rw-r--r--drivers/staging/iio/accel/Makefile12
-rw-r--r--drivers/staging/iio/accel/accel.h87
-rw-r--r--drivers/staging/iio/accel/adis16201.h6
-rw-r--r--drivers/staging/iio/accel/adis16201_core.c42
-rw-r--r--drivers/staging/iio/accel/adis16201_ring.c48
-rw-r--r--drivers/staging/iio/accel/adis16201_trigger.c13
-rw-r--r--drivers/staging/iio/accel/adis16203.h6
-rw-r--r--drivers/staging/iio/accel/adis16203_core.c42
-rw-r--r--drivers/staging/iio/accel/adis16203_ring.c39
-rw-r--r--drivers/staging/iio/accel/adis16203_trigger.c14
-rw-r--r--drivers/staging/iio/accel/adis16204.h6
-rw-r--r--drivers/staging/iio/accel/adis16204_core.c94
-rw-r--r--drivers/staging/iio/accel/adis16204_ring.c39
-rw-r--r--drivers/staging/iio/accel/adis16204_trigger.c14
-rw-r--r--drivers/staging/iio/accel/adis16209.h6
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c45
-rw-r--r--drivers/staging/iio/accel/adis16209_ring.c42
-rw-r--r--drivers/staging/iio/accel/adis16209_trigger.c14
-rw-r--r--drivers/staging/iio/accel/adis16220_core.c356
-rw-r--r--drivers/staging/iio/accel/adis16240.h6
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c43
-rw-r--r--drivers/staging/iio/accel/adis16240_ring.c40
-rw-r--r--drivers/staging/iio/accel/adis16240_trigger.c14
-rw-r--r--drivers/staging/iio/accel/inclinometer.h25
-rw-r--r--drivers/staging/iio/accel/kxsd9.c270
-rw-r--r--drivers/staging/iio/accel/lis3l02dq.h26
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_core.c114
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c124
-rw-r--r--drivers/staging/iio/accel/sca3000.h4
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c106
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c152
-rw-r--r--drivers/staging/iio/adc/Kconfig97
-rw-r--r--drivers/staging/iio/adc/Makefile15
-rw-r--r--drivers/staging/iio/adc/ad7150.c812
-rw-r--r--drivers/staging/iio/adc/ad7152.c586
-rw-r--r--drivers/staging/iio/adc/ad7192.c1179
-rw-r--r--drivers/staging/iio/adc/ad7192.h47
-rw-r--r--drivers/staging/iio/adc/ad7280a.c997
-rw-r--r--drivers/staging/iio/adc/ad7280a.h38
-rw-r--r--drivers/staging/iio/adc/ad7291.c1094
-rw-r--r--drivers/staging/iio/adc/ad7298.h6
-rw-r--r--drivers/staging/iio/adc/ad7298_core.c62
-rw-r--r--drivers/staging/iio/adc/ad7298_ring.c50
-rw-r--r--drivers/staging/iio/adc/ad7314.c281
-rw-r--r--drivers/staging/iio/adc/ad7476.h6
-rw-r--r--drivers/staging/iio/adc/ad7476_core.c81
-rw-r--r--drivers/staging/iio/adc/ad7476_ring.c50
-rw-r--r--drivers/staging/iio/adc/ad7606.h12
-rw-r--r--drivers/staging/iio/adc/ad7606_core.c277
-rw-r--r--drivers/staging/iio/adc/ad7606_par.c2
-rw-r--r--drivers/staging/iio/adc/ad7606_ring.c86
-rw-r--r--drivers/staging/iio/adc/ad7606_spi.c2
-rw-r--r--drivers/staging/iio/adc/ad7745.c674
-rw-r--r--drivers/staging/iio/adc/ad7780.c10
-rw-r--r--drivers/staging/iio/adc/ad7793.c275
-rw-r--r--drivers/staging/iio/adc/ad7816.c60
-rw-r--r--drivers/staging/iio/adc/ad7887.h10
-rw-r--r--drivers/staging/iio/adc/ad7887_core.c70
-rw-r--r--drivers/staging/iio/adc/ad7887_ring.c59
-rw-r--r--drivers/staging/iio/adc/ad799x.h4
-rw-r--r--drivers/staging/iio/adc/ad799x_core.c744
-rw-r--r--drivers/staging/iio/adc/ad799x_ring.c69
-rw-r--r--drivers/staging/iio/adc/adc.h42
-rw-r--r--drivers/staging/iio/adc/adt7310.c24
-rw-r--r--drivers/staging/iio/adc/adt7410.c24
-rw-r--r--drivers/staging/iio/adc/adt75.c657
-rw-r--r--drivers/staging/iio/adc/max1363.h8
-rw-r--r--drivers/staging/iio/adc/max1363_core.c314
-rw-r--r--drivers/staging/iio/adc/max1363_ring.c63
-rw-r--r--drivers/staging/iio/addac/Kconfig5
-rw-r--r--drivers/staging/iio/addac/adt7316-i2c.c3
-rw-r--r--drivers/staging/iio/addac/adt7316.c46
-rw-r--r--drivers/staging/iio/buffer_generic.h228
-rw-r--r--drivers/staging/iio/cdc/Kconfig36
-rw-r--r--drivers/staging/iio/cdc/Makefile7
-rw-r--r--drivers/staging/iio/cdc/ad7150.c676
-rw-r--r--drivers/staging/iio/cdc/ad7152.c559
-rw-r--r--drivers/staging/iio/cdc/ad7746.c807
-rw-r--r--drivers/staging/iio/cdc/ad7746.h29
-rw-r--r--drivers/staging/iio/chrdev.h54
-rw-r--r--drivers/staging/iio/dac/Kconfig27
-rw-r--r--drivers/staging/iio/dac/Makefile2
-rw-r--r--drivers/staging/iio/dac/ad5064.c463
-rw-r--r--drivers/staging/iio/dac/ad5360.c581
-rw-r--r--drivers/staging/iio/dac/ad5446.c72
-rw-r--r--drivers/staging/iio/dac/ad5504.c94
-rw-r--r--drivers/staging/iio/dac/ad5624r_spi.c83
-rw-r--r--drivers/staging/iio/dac/ad5686.c133
-rw-r--r--drivers/staging/iio/dac/ad5791.c262
-rw-r--r--drivers/staging/iio/dac/ad5791.h6
-rw-r--r--drivers/staging/iio/dac/dac.h2
-rw-r--r--drivers/staging/iio/dac/max517.c34
-rw-r--r--drivers/staging/iio/dds/Kconfig4
-rw-r--r--drivers/staging/iio/dds/ad5930.c2
-rw-r--r--drivers/staging/iio/dds/ad9832.c20
-rw-r--r--drivers/staging/iio/dds/ad9834.c37
-rw-r--r--drivers/staging/iio/dds/ad9850.c2
-rw-r--r--drivers/staging/iio/dds/ad9852.c3
-rw-r--r--drivers/staging/iio/dds/ad9910.c3
-rw-r--r--drivers/staging/iio/dds/ad9951.c3
-rw-r--r--drivers/staging/iio/gyro/Kconfig8
-rw-r--r--drivers/staging/iio/gyro/Makefile2
-rw-r--r--drivers/staging/iio/gyro/adis16060_core.c125
-rw-r--r--drivers/staging/iio/gyro/adis16080_core.c104
-rw-r--r--drivers/staging/iio/gyro/adis16130_core.c146
-rw-r--r--drivers/staging/iio/gyro/adis16260.h6
-rw-r--r--drivers/staging/iio/gyro/adis16260_core.c58
-rw-r--r--drivers/staging/iio/gyro/adis16260_ring.c39
-rw-r--r--drivers/staging/iio/gyro/adis16260_trigger.c14
-rw-r--r--drivers/staging/iio/gyro/adxrs450_core.c265
-rw-r--r--drivers/staging/iio/gyro/gyro.h85
-rw-r--r--drivers/staging/iio/iio.h248
-rw-r--r--drivers/staging/iio/iio_core.h63
-rw-r--r--drivers/staging/iio/iio_core_trigger.h47
-rw-r--r--drivers/staging/iio/iio_dummy_evgen.c217
-rw-r--r--drivers/staging/iio/iio_dummy_evgen.h2
-rw-r--r--drivers/staging/iio/iio_simple_dummy.c545
-rw-r--r--drivers/staging/iio/iio_simple_dummy.h108
-rw-r--r--drivers/staging/iio/iio_simple_dummy_buffer.c206
-rw-r--r--drivers/staging/iio/iio_simple_dummy_events.c190
-rw-r--r--drivers/staging/iio/impedance-analyzer/Kconfig18
-rw-r--r--drivers/staging/iio/impedance-analyzer/Makefile5
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c814
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.h28
-rw-r--r--drivers/staging/iio/imu/Kconfig16
-rw-r--r--drivers/staging/iio/imu/Makefile2
-rw-r--r--drivers/staging/iio/imu/adis16400.h6
-rw-r--r--drivers/staging/iio/imu/adis16400_core.c653
-rw-r--r--drivers/staging/iio/imu/adis16400_ring.c49
-rw-r--r--drivers/staging/iio/imu/adis16400_trigger.c16
-rw-r--r--drivers/staging/iio/industrialio-buffer.c635
-rw-r--r--drivers/staging/iio/industrialio-core.c961
-rw-r--r--drivers/staging/iio/industrialio-ring.c596
-rw-r--r--drivers/staging/iio/industrialio-trigger.c174
-rw-r--r--drivers/staging/iio/kfifo_buf.c78
-rw-r--r--drivers/staging/iio/kfifo_buf.h16
-rw-r--r--drivers/staging/iio/light/Kconfig4
-rw-r--r--drivers/staging/iio/light/isl29018.c74
-rw-r--r--drivers/staging/iio/light/tsl2563.c69
-rw-r--r--drivers/staging/iio/light/tsl2583.c222
-rw-r--r--drivers/staging/iio/magnetometer/Kconfig4
-rw-r--r--drivers/staging/iio/magnetometer/ak8975.c240
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.c104
-rw-r--r--drivers/staging/iio/magnetometer/magnet.h31
-rw-r--r--drivers/staging/iio/meter/Kconfig8
-rw-r--r--drivers/staging/iio/meter/Makefile2
-rw-r--r--drivers/staging/iio/meter/ade7753.c32
-rw-r--r--drivers/staging/iio/meter/ade7754.c31
-rw-r--r--drivers/staging/iio/meter/ade7758.h13
-rw-r--r--drivers/staging/iio/meter/ade7758_core.c57
-rw-r--r--drivers/staging/iio/meter/ade7758_ring.c57
-rw-r--r--drivers/staging/iio/meter/ade7758_trigger.c16
-rw-r--r--drivers/staging/iio/meter/ade7759.c27
-rw-r--r--drivers/staging/iio/meter/ade7854-i2c.c1
-rw-r--r--drivers/staging/iio/meter/ade7854-spi.c1
-rw-r--r--drivers/staging/iio/meter/ade7854.c5
-rw-r--r--drivers/staging/iio/resolver/Kconfig9
-rw-r--r--drivers/staging/iio/resolver/Makefile2
-rw-r--r--drivers/staging/iio/resolver/ad2s1200.c188
-rw-r--r--drivers/staging/iio/resolver/ad2s120x.c177
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c223
-rw-r--r--drivers/staging/iio/resolver/ad2s90.c60
-rw-r--r--drivers/staging/iio/ring_generic.h288
-rw-r--r--drivers/staging/iio/ring_hw.h6
-rw-r--r--drivers/staging/iio/ring_sw.c69
-rw-r--r--drivers/staging/iio/ring_sw.h8
-rw-r--r--drivers/staging/iio/sysfs.h136
-rw-r--r--drivers/staging/iio/trigger.h119
-rw-r--r--drivers/staging/iio/trigger/iio-trig-bfin-timer.c6
-rw-r--r--drivers/staging/iio/trigger/iio-trig-gpio.c6
-rw-r--r--drivers/staging/iio/trigger/iio-trig-periodic-rtc.c7
-rw-r--r--drivers/staging/iio/trigger/iio-trig-sysfs.c13
-rw-r--r--drivers/staging/iio/trigger_consumer.h71
-rw-r--r--drivers/staging/intel_sst/intel_sst.c10
-rw-r--r--drivers/staging/intel_sst/intel_sst_dsp.c2
-rw-r--r--drivers/staging/intel_sst/intelmid.c1
-rw-r--r--drivers/staging/keucr/scsiglue.c5
-rw-r--r--drivers/staging/keucr/smil.h6
-rw-r--r--drivers/staging/keucr/smilsub.c1574
-rw-r--r--drivers/staging/keucr/smscsi.c117
-rw-r--r--drivers/staging/lirc/lirc_imon.c6
-rw-r--r--drivers/staging/lirc/lirc_sasem.c46
-rw-r--r--drivers/staging/lirc/lirc_serial.c2
-rw-r--r--drivers/staging/lirc/lirc_sir.c2
-rw-r--r--drivers/staging/mei/Kconfig2
-rw-r--r--drivers/staging/mei/TODO10
-rw-r--r--drivers/staging/mei/init.c25
-rw-r--r--drivers/staging/mei/interface.c4
-rw-r--r--drivers/staging/mei/interface.h8
-rw-r--r--drivers/staging/mei/interrupt.c85
-rw-r--r--drivers/staging/mei/main.c51
-rw-r--r--drivers/staging/mei/mei_dev.h24
-rw-r--r--drivers/staging/mei/wd.c242
-rw-r--r--drivers/staging/nvec/Kconfig12
-rw-r--r--drivers/staging/nvec/Makefile1
-rw-r--r--drivers/staging/nvec/TODO10
-rw-r--r--drivers/staging/nvec/nvec-keytable.h225
-rw-r--r--drivers/staging/nvec/nvec.c958
-rw-r--r--drivers/staging/nvec/nvec.h217
-rw-r--r--drivers/staging/nvec/nvec_kbd.c95
-rw-r--r--drivers/staging/nvec/nvec_leds.c114
-rw-r--r--drivers/staging/nvec/nvec_power.c352
-rw-r--r--drivers/staging/nvec/nvec_ps2.c114
-rw-r--r--drivers/staging/octeon/ethernet.c12
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c47
-rw-r--r--drivers/staging/panel/panel.c10
-rw-r--r--drivers/staging/pohmelfs/Kconfig8
-rw-r--r--drivers/staging/pohmelfs/inode.c2
-rw-r--r--drivers/staging/pohmelfs/trans.c6
-rw-r--r--drivers/staging/quatech_usb2/quatech_usb2.c9
-rw-r--r--drivers/staging/rtl8187se/Makefile6
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211.h4
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c14
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c2
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8225z2.c4
-rw-r--r--drivers/staging/rtl8192e/Makefile67
-rw-r--r--drivers/staging/rtl8192e/TODO2
-rw-r--r--drivers/staging/rtl8192e/dot11d.c216
-rw-r--r--drivers/staging/rtl8192e/dot11d.h113
-rw-r--r--drivers/staging/rtl8192e/ieee80211/dot11d.c218
-rw-r--r--drivers/staging/rtl8192e/ieee80211/dot11d.h102
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211.h2636
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_module.c352
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c2676
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c3278
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c955
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c872
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_BA.h69
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c676
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h483
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c1732
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_Qos.h582
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h56
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c627
-rw-r--r--drivers/staging/rtl8192e/license339
-rw-r--r--drivers/staging/rtl8192e/r8180_93cx6.c141
-rw-r--r--drivers/staging/rtl8192e/r8180_93cx6.h41
-rw-r--r--drivers/staging/rtl8192e/r8190P_def.h410
-rw-r--r--drivers/staging/rtl8192e/r8190P_rtl8256.c306
-rw-r--r--drivers/staging/rtl8192e/r8190P_rtl8256.h31
-rw-r--r--drivers/staging/rtl8192e/r8190_rtl8256.c677
-rw-r--r--drivers/staging/rtl8192e/r8190_rtl8256.h29
-rw-r--r--drivers/staging/rtl8192e/r8192E.h1148
-rw-r--r--drivers/staging/rtl8192e/r8192E_cmdpkt.c418
-rw-r--r--drivers/staging/rtl8192e/r8192E_cmdpkt.h159
-rw-r--r--drivers/staging/rtl8192e/r8192E_core.c5039
-rw-r--r--drivers/staging/rtl8192e/r8192E_dev.c2395
-rw-r--r--drivers/staging/rtl8192e/r8192E_dev.h62
-rw-r--r--drivers/staging/rtl8192e/r8192E_dm.c2554
-rw-r--r--drivers/staging/rtl8192e/r8192E_dm.h228
-rw-r--r--drivers/staging/rtl8192e/r8192E_firmware.c348
-rw-r--r--drivers/staging/rtl8192e/r8192E_firmware.h73
-rw-r--r--drivers/staging/rtl8192e/r8192E_hw.h552
-rw-r--r--drivers/staging/rtl8192e/r8192E_hwimg.c3336
-rw-r--r--drivers/staging/rtl8192e/r8192E_hwimg.h51
-rw-r--r--drivers/staging/rtl8192e/r8192E_phy.c1637
-rw-r--r--drivers/staging/rtl8192e/r8192E_phy.h120
-rw-r--r--drivers/staging/rtl8192e/r8192E_phyreg.h852
-rw-r--r--drivers/staging/rtl8192e/r8192E_wx.c1163
-rw-r--r--drivers/staging/rtl8192e/r8192E_wx.h18
-rw-r--r--drivers/staging/rtl8192e/r8192_pm.c123
-rw-r--r--drivers/staging/rtl8192e/r8192_pm.h24
-rw-r--r--drivers/staging/rtl8192e/r819xE_cmdpkt.c444
-rw-r--r--drivers/staging/rtl8192e/r819xE_cmdpkt.h207
-rw-r--r--drivers/staging/rtl8192e/r819xE_firmware.c351
-rw-r--r--drivers/staging/rtl8192e/r819xE_phy.c2225
-rw-r--r--drivers/staging/rtl8192e/r819xE_phy.h131
-rw-r--r--drivers/staging/rtl8192e/rtl819x_BA.h77
-rw-r--r--drivers/staging/rtl8192e/rtl819x_BAProc.c566
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HT.h475
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HTProc.c1075
-rw-r--r--drivers/staging/rtl8192e/rtl819x_Qos.h444
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TS.h73
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TSProc.c548
-rw-r--r--drivers/staging/rtl8192e/rtl_cam.c304
-rw-r--r--drivers/staging/rtl8192e/rtl_cam.h46
-rw-r--r--drivers/staging/rtl8192e/rtl_core.c3198
-rw-r--r--drivers/staging/rtl8192e/rtl_core.h1124
-rw-r--r--drivers/staging/rtl8192e/rtl_crypto.h (renamed from drivers/staging/rtl8192e/ieee80211/rtl_crypto.h)105
-rw-r--r--drivers/staging/rtl8192e/rtl_debug.c1108
-rw-r--r--drivers/staging/rtl8192e/rtl_debug.h299
-rw-r--r--drivers/staging/rtl8192e/rtl_dm.c2995
-rw-r--r--drivers/staging/rtl8192e/rtl_dm.h324
-rw-r--r--drivers/staging/rtl8192e/rtl_eeprom.c139
-rw-r--r--drivers/staging/rtl8192e/rtl_eeprom.h29
-rw-r--r--drivers/staging/rtl8192e/rtl_ethtool.c53
-rw-r--r--drivers/staging/rtl8192e/rtl_pci.c97
-rw-r--r--drivers/staging/rtl8192e/rtl_pci.h104
-rw-r--r--drivers/staging/rtl8192e/rtl_pm.c136
-rw-r--r--drivers/staging/rtl8192e/rtl_pm.h35
-rw-r--r--drivers/staging/rtl8192e/rtl_ps.c310
-rw-r--r--drivers/staging/rtl8192e/rtl_ps.h47
-rw-r--r--drivers/staging/rtl8192e/rtl_wx.c1333
-rw-r--r--drivers/staging/rtl8192e/rtl_wx.h31
-rw-r--r--drivers/staging/rtl8192e/rtllib.h3144
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt.c (renamed from drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c)91
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt.h (renamed from drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.h)32
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_ccmp.c (renamed from drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c)170
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_tkip.c (renamed from drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c)310
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_wep.c (renamed from drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c)116
-rw-r--r--drivers/staging/rtl8192e/rtllib_endianfree.h160
-rw-r--r--drivers/staging/rtl8192e/rtllib_module.c289
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c2720
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c3741
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac_wx.c (renamed from drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c)381
-rw-r--r--drivers/staging/rtl8192e/rtllib_tx.c967
-rw-r--r--drivers/staging/rtl8192e/rtllib_wx.c876
-rw-r--r--drivers/staging/rtl8192u/ieee80211/Makefile109
-rw-r--r--drivers/staging/rtl8192u/ieee80211/compress.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c14
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c2
-rw-r--r--drivers/staging/rtl8712/Kconfig7
-rw-r--r--drivers/staging/rtl8712/basic_types.h25
-rw-r--r--drivers/staging/rtl8712/big_endian.h25
-rw-r--r--drivers/staging/rtl8712/drv_types.h33
-rw-r--r--drivers/staging/rtl8712/ethernet.h25
-rw-r--r--drivers/staging/rtl8712/generic.h25
-rw-r--r--drivers/staging/rtl8712/hal_init.c6
-rw-r--r--drivers/staging/rtl8712/ieee80211.c35
-rw-r--r--drivers/staging/rtl8712/ieee80211.h31
-rw-r--r--drivers/staging/rtl8712/if_ether.h25
-rw-r--r--drivers/staging/rtl8712/little_endian.h25
-rw-r--r--drivers/staging/rtl8712/mlme_osdep.h25
-rw-r--r--drivers/staging/rtl8712/mp_custom_oid.h25
-rw-r--r--drivers/staging/rtl8712/os_intfs.c33
-rw-r--r--drivers/staging/rtl8712/osdep_intf.h25
-rw-r--r--drivers/staging/rtl8712/osdep_service.h69
-rw-r--r--drivers/staging/rtl8712/recv_linux.c6
-rw-r--r--drivers/staging/rtl8712/recv_osdep.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_bitdef.h21
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.c18
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.h87
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.c75
-rw-r--r--drivers/staging/rtl8712/rtl8712_event.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_bitdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_regdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_hal.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c2
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_powersave_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_powersave_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.c24
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.h31
-rw-r--r--drivers/staging/rtl8712/rtl8712_regdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_security_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_spec.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_regdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_bitdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_regdef.h25
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.c303
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.h37
-rw-r--r--drivers/staging/rtl8712/rtl871x_byteorder.h19
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c172
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.h77
-rw-r--r--drivers/staging/rtl8712/rtl871x_debug.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_eeprom.h19
-rw-r--r--drivers/staging/rtl8712/rtl871x_event.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_ht.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c306
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_rtl.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.c3
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.h27
-rw-r--r--drivers/staging/rtl8712/rtl871x_led.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c62
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.h28
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.c26
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.h26
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.h29
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c4
-rw-r--r--drivers/staging/rtl8712/rtl871x_rf.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.c15
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_wlan_sme.h25
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.c31
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.h52
-rw-r--r--drivers/staging/rtl8712/sta_info.h29
-rw-r--r--drivers/staging/rtl8712/swab.h25
-rw-r--r--drivers/staging/rtl8712/usb_intf.c19
-rw-r--r--drivers/staging/rtl8712/usb_ops.h25
-rw-r--r--drivers/staging/rtl8712/usb_ops_linux.c29
-rw-r--r--drivers/staging/rtl8712/usb_osintf.h26
-rw-r--r--drivers/staging/rtl8712/usb_vendor_req.h25
-rw-r--r--drivers/staging/rtl8712/wifi.h25
-rw-r--r--drivers/staging/rtl8712/wlan_bssdef.h25
-rw-r--r--drivers/staging/rtl8712/xmit_linux.c27
-rw-r--r--drivers/staging/rtl8712/xmit_osdep.h26
-rw-r--r--drivers/staging/rts5139/Kconfig16
-rw-r--r--drivers/staging/rts5139/Makefile37
-rw-r--r--drivers/staging/rts5139/TODO5
-rw-r--r--drivers/staging/rts5139/debug.h46
-rw-r--r--drivers/staging/rts5139/ms.c4191
-rw-r--r--drivers/staging/rts5139/ms.h263
-rw-r--r--drivers/staging/rts5139/ms_mg.c642
-rw-r--r--drivers/staging/rts5139/ms_mg.h41
-rw-r--r--drivers/staging/rts5139/rts51x.c967
-rw-r--r--drivers/staging/rts5139/rts51x.h205
-rw-r--r--drivers/staging/rts5139/rts51x_card.c986
-rw-r--r--drivers/staging/rts5139/rts51x_card.h881
-rw-r--r--drivers/staging/rts5139/rts51x_chip.c1167
-rw-r--r--drivers/staging/rts5139/rts51x_chip.h904
-rw-r--r--drivers/staging/rts5139/rts51x_fop.c298
-rw-r--r--drivers/staging/rts5139/rts51x_fop.h62
-rw-r--r--drivers/staging/rts5139/rts51x_scsi.c2234
-rw-r--r--drivers/staging/rts5139/rts51x_scsi.h162
-rw-r--r--drivers/staging/rts5139/rts51x_sys.h54
-rw-r--r--drivers/staging/rts5139/rts51x_transport.c1000
-rw-r--r--drivers/staging/rts5139/rts51x_transport.h80
-rw-r--r--drivers/staging/rts5139/sd.c3400
-rw-r--r--drivers/staging/rts5139/sd.h304
-rw-r--r--drivers/staging/rts5139/sd_cprm.c1215
-rw-r--r--drivers/staging/rts5139/sd_cprm.h54
-rw-r--r--drivers/staging/rts5139/trace.h137
-rw-r--r--drivers/staging/rts5139/xd.c2255
-rw-r--r--drivers/staging/rts5139/xd.h193
-rw-r--r--drivers/staging/rts_pstor/Makefile2
-rw-r--r--drivers/staging/rts_pstor/rtsx.c62
-rw-r--r--drivers/staging/rts_pstor/rtsx.h10
-rw-r--r--drivers/staging/rts_pstor/rtsx_scsi.c2
-rw-r--r--drivers/staging/rts_pstor/sd.c35
-rw-r--r--drivers/staging/rts_pstor/spi.c2
-rw-r--r--drivers/staging/sep/sep_driver.c6
-rw-r--r--drivers/staging/serial/68360serial.c (renamed from drivers/tty/serial/68360serial.c)0
-rw-r--r--drivers/staging/serial/Kconfig16
-rw-r--r--drivers/staging/serial/Makefile1
-rw-r--r--drivers/staging/serial/TODO6
-rw-r--r--drivers/staging/serqt_usb2/serqt_usb2.c37
-rw-r--r--drivers/staging/slicoss/Kconfig2
-rw-r--r--drivers/staging/slicoss/slicoss.c2
-rw-r--r--drivers/staging/sm7xx/smtcfb.c2
-rw-r--r--drivers/staging/spectra/ffsport.c15
-rw-r--r--drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c1
-rw-r--r--drivers/staging/tidspbridge/gen/gh.c2
-rw-r--r--drivers/staging/tidspbridge/hw/hw_mmu.c2
-rw-r--r--drivers/staging/tm6000/README22
-rw-r--r--drivers/staging/tm6000/TODO8
-rw-r--r--drivers/staging/tm6000/tm6000-stds.c679
-rw-r--r--drivers/staging/usbip/stub.h5
-rw-r--r--drivers/staging/usbip/stub_dev.c7
-rw-r--r--drivers/staging/usbip/stub_main.c1
-rw-r--r--drivers/staging/usbip/stub_rx.c5
-rw-r--r--drivers/staging/usbip/usbip_common.h8
-rw-r--r--drivers/staging/usbip/usbip_protocol.txt358
-rw-r--r--drivers/staging/usbip/userspace/libsrc/vhci_driver.c2
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_attach.c4
-rw-r--r--drivers/staging/usbip/userspace/src/utils.h1
-rw-r--r--drivers/staging/usbip/vhci.h5
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.c24
-rw-r--r--drivers/staging/vme/bridges/vme_tsi148.c24
-rw-r--r--drivers/staging/vme/devices/vme_user.c69
-rw-r--r--drivers/staging/vme/devices/vme_user.h2
-rw-r--r--drivers/staging/vme/vme.c349
-rw-r--r--drivers/staging/vme/vme.h50
-rw-r--r--drivers/staging/vme/vme_api.txt90
-rw-r--r--drivers/staging/vme/vme_bridge.h17
-rw-r--r--drivers/staging/vt6655/IEEE11h.c406
-rw-r--r--drivers/staging/vt6655/device_main.c12
-rw-r--r--drivers/staging/vt6655/dpc.c30
-rw-r--r--drivers/staging/vt6655/ioctl.c1092
-rw-r--r--drivers/staging/vt6655/wmgr.c49
-rw-r--r--drivers/staging/vt6655/wpactl.c4
-rw-r--r--drivers/staging/vt6656/dpc.c30
-rw-r--r--drivers/staging/vt6656/ioctl.c1040
-rw-r--r--drivers/staging/vt6656/main_usb.c13
-rw-r--r--drivers/staging/vt6656/wmgr.c49
-rw-r--r--drivers/staging/vt6656/wpactl.c18
-rw-r--r--drivers/staging/winbond/phy_calibration.c12
-rw-r--r--drivers/staging/winbond/wbusb.c2
-rw-r--r--drivers/staging/wlags49_h2/Makefile26
-rw-r--r--drivers/staging/wlags49_h2/debug.h61
-rw-r--r--drivers/staging/wlags49_h2/hcf.c6428
-rw-r--r--drivers/staging/wlags49_h2/hcf.h10
-rw-r--r--drivers/staging/wlags49_h2/hcfcfg.h1586
-rw-r--r--drivers/staging/wlags49_h2/hcfdef.h857
-rw-r--r--drivers/staging/wlags49_h2/mdd.h34
-rw-r--r--drivers/staging/wlags49_h2/wl_cs.c114
-rw-r--r--drivers/staging/wlags49_h2/wl_internal.h15
-rw-r--r--drivers/staging/wlags49_h2/wl_main.c6
-rw-r--r--drivers/staging/wlags49_h2/wl_netdev.c4
-rw-r--r--drivers/staging/wlags49_h2/wl_sysfs.c18
-rw-r--r--drivers/staging/wlags49_h2/wl_version.h6
-rw-r--r--drivers/staging/wlags49_h2/wl_wext.c1184
-rw-r--r--drivers/staging/wlags49_h2/wl_wext.h8
-rw-r--r--drivers/staging/wlags49_h25/Makefile26
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c2
-rw-r--r--drivers/staging/xgifb/TODO1
-rw-r--r--drivers/staging/xgifb/XGI_main.h238
-rw-r--r--drivers/staging/xgifb/XGI_main_26.c1451
-rw-r--r--drivers/staging/xgifb/XGIfb.h48
-rw-r--r--drivers/staging/xgifb/vb_def.h605
-rw-r--r--drivers/staging/xgifb/vb_ext.h20
-rw-r--r--drivers/staging/xgifb/vb_init.c257
-rw-r--r--drivers/staging/xgifb/vb_init.h2
-rw-r--r--drivers/staging/xgifb/vb_setmode.c1535
-rw-r--r--drivers/staging/xgifb/vb_struct.h97
-rw-r--r--drivers/staging/xgifb/vb_table.h1200
-rw-r--r--drivers/staging/xgifb/vb_util.c5
-rw-r--r--drivers/staging/xgifb/vgatypes.h11
-rw-r--r--drivers/staging/zcache/zcache-main.c51
-rw-r--r--drivers/staging/zram/zram_drv.c96
-rw-r--r--drivers/staging/zram/zram_drv.h12
-rw-r--r--drivers/staging/zram/zram_sysfs.c22
-rw-r--r--drivers/target/Makefile1
-rw-r--r--drivers/target/iscsi/iscsi_target.c39
-rw-r--r--drivers/target/iscsi/iscsi_target_auth.c34
-rw-r--r--drivers/target/iscsi/iscsi_target_core.h4
-rw-r--r--drivers/target/iscsi/iscsi_target_erl2.c49
-rw-r--r--drivers/target/iscsi/iscsi_target_nego.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_tmr.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c20
-rw-r--r--drivers/target/iscsi/iscsi_target_util.h1
-rw-r--r--drivers/target/loopback/tcm_loop.c18
-rw-r--r--drivers/target/target_core_alua.c21
-rw-r--r--drivers/target/target_core_cdb.c79
-rw-r--r--drivers/target/target_core_configfs.c16
-rw-r--r--drivers/target/target_core_device.c70
-rw-r--r--drivers/target/target_core_fabric_configfs.c1
-rw-r--r--drivers/target/target_core_fabric_lib.c12
-rw-r--r--drivers/target/target_core_file.c56
-rw-r--r--drivers/target/target_core_file.h4
-rw-r--r--drivers/target/target_core_iblock.c274
-rw-r--r--drivers/target/target_core_iblock.h2
-rw-r--r--drivers/target/target_core_pr.c1
-rw-r--r--drivers/target/target_core_pscsi.c261
-rw-r--r--drivers/target/target_core_pscsi.h1
-rw-r--r--drivers/target/target_core_rd.c19
-rw-r--r--drivers/target/target_core_rd.h2
-rw-r--r--drivers/target/target_core_scdb.c105
-rw-r--r--drivers/target/target_core_scdb.h10
-rw-r--r--drivers/target/target_core_stat.c1
-rw-r--r--drivers/target/target_core_tmr.c251
-rw-r--r--drivers/target/target_core_tpg.c2
-rw-r--r--drivers/target/target_core_transport.c1477
-rw-r--r--drivers/target/target_core_ua.c1
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c18
-rw-r--r--drivers/target/tcm_fc/tfc_conf.c13
-rw-r--r--drivers/target/tcm_fc/tfc_io.c1
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c1
-rw-r--r--drivers/tty/Kconfig42
-rw-r--r--drivers/tty/Makefile1
-rw-r--r--drivers/tty/amiserial.c12
-rw-r--r--drivers/tty/cyclades.c14
-rw-r--r--drivers/tty/ehv_bytechan.c881
-rw-r--r--drivers/tty/hvc/hvc_console.c9
-rw-r--r--drivers/tty/hvc/hvc_irq.c2
-rw-r--r--drivers/tty/hvc/hvcs.c4
-rw-r--r--drivers/tty/hvc/hvsi.c2
-rw-r--r--drivers/tty/isicom.c2
-rw-r--r--drivers/tty/mxser.c13
-rw-r--r--drivers/tty/n_gsm.c70
-rw-r--r--drivers/tty/pty.c26
-rw-r--r--drivers/tty/serial/68328serial.c37
-rw-r--r--drivers/tty/serial/68328serial.h1
-rw-r--r--drivers/tty/serial/8250.c132
-rw-r--r--drivers/tty/serial/8250_dw.c194
-rw-r--r--drivers/tty/serial/8250_pci.c42
-rw-r--r--drivers/tty/serial/Kconfig30
-rw-r--r--drivers/tty/serial/Makefile4
-rw-r--r--drivers/tty/serial/altera_jtaguart.c7
-rw-r--r--drivers/tty/serial/altera_uart.c6
-rw-r--r--drivers/tty/serial/amba-pl010.c14
-rw-r--r--drivers/tty/serial/amba-pl011.c14
-rw-r--r--drivers/tty/serial/apbuart.c1
-rw-r--r--drivers/tty/serial/atmel_serial.c130
-rw-r--r--drivers/tty/serial/bfin_sport_uart.c2
-rw-r--r--drivers/tty/serial/bfin_uart.c (renamed from drivers/tty/serial/bfin_5xx.c)65
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c1
-rw-r--r--drivers/tty/serial/crisv10.c30
-rw-r--r--drivers/tty/serial/dz.c1
-rw-r--r--drivers/tty/serial/icom.c2
-rw-r--r--drivers/tty/serial/imx.c21
-rw-r--r--drivers/tty/serial/ioc3_serial.c1
-rw-r--r--drivers/tty/serial/ioc4_serial.c1
-rw-r--r--drivers/tty/serial/jsm/jsm.h10
-rw-r--r--drivers/tty/serial/jsm/jsm_driver.c19
-rw-r--r--drivers/tty/serial/jsm/jsm_neo.c29
-rw-r--r--drivers/tty/serial/jsm/jsm_tty.c94
-rw-r--r--drivers/tty/serial/lantiq.c6
-rw-r--r--drivers/tty/serial/m32r_sio.c1
-rw-r--r--drivers/tty/serial/max3100.c2
-rw-r--r--drivers/tty/serial/max3107.c2
-rw-r--r--drivers/tty/serial/mcf.c2
-rw-r--r--drivers/tty/serial/mfd.c49
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c3
-rw-r--r--drivers/tty/serial/mrst_max3110.c117
-rw-r--r--drivers/tty/serial/mrst_max3110.h1
-rw-r--r--drivers/tty/serial/msm_serial.c32
-rw-r--r--drivers/tty/serial/msm_serial_hs.c2
-rw-r--r--drivers/tty/serial/mux.c2
-rw-r--r--drivers/tty/serial/nwpserial.c1
-rw-r--r--drivers/tty/serial/of_serial.c12
-rw-r--r--drivers/tty/serial/pch_uart.c2
-rw-r--r--drivers/tty/serial/pxa.c20
-rw-r--r--drivers/tty/serial/samsung.c107
-rw-r--r--drivers/tty/serial/samsung.h1
-rw-r--r--drivers/tty/serial/sb1250-duart.c1
-rw-r--r--drivers/tty/serial/serial_core.c72
-rw-r--r--drivers/tty/serial/serial_ks8695.c9
-rw-r--r--drivers/tty/serial/serial_txx9.c2
-rw-r--r--drivers/tty/serial/sh-sci.c2
-rw-r--r--drivers/tty/serial/sn_console.c3
-rw-r--r--drivers/tty/serial/timbuart.c2
-rw-r--r--drivers/tty/serial/uartlite.c5
-rw-r--r--drivers/tty/serial/ucc_uart.c4
-rw-r--r--drivers/tty/serial/xilinx_uartps.c4
-rw-r--r--drivers/tty/serial/zs.c1
-rw-r--r--drivers/tty/synclink.c1
-rw-r--r--drivers/tty/synclinkmp.c6
-rw-r--r--drivers/tty/tty_io.c50
-rw-r--r--drivers/tty/tty_ioctl.c17
-rw-r--r--drivers/tty/tty_ldisc.c1
-rw-r--r--drivers/tty/tty_mutex.c12
-rw-r--r--drivers/tty/tty_port.c2
-rw-r--r--drivers/tty/vt/keyboard.c3
-rw-r--r--drivers/tty/vt/selection.c4
-rw-r--r--drivers/tty/vt/vt.c2
-rw-r--r--drivers/uio/uio.c14
-rw-r--r--drivers/uio/uio_pci_generic.c5
-rw-r--r--drivers/uio/uio_pdrv_genirq.c2
-rw-r--r--drivers/usb/Kconfig16
-rw-r--r--drivers/usb/Makefile4
-rw-r--r--drivers/usb/class/cdc-acm.c11
-rw-r--r--drivers/usb/class/cdc-wdm.c8
-rw-r--r--drivers/usb/class/usbtmc.c5
-rw-r--r--drivers/usb/core/config.c111
-rw-r--r--drivers/usb/core/devices.c4
-rw-r--r--drivers/usb/core/devio.c57
-rw-r--r--drivers/usb/core/driver.c25
-rw-r--r--drivers/usb/core/endpoint.c2
-rw-r--r--drivers/usb/core/hcd-pci.c2
-rw-r--r--drivers/usb/core/hcd.c36
-rw-r--r--drivers/usb/core/hub.c326
-rw-r--r--drivers/usb/core/message.c2
-rw-r--r--drivers/usb/core/quirks.c24
-rw-r--r--drivers/usb/core/sysfs.c59
-rw-r--r--drivers/usb/core/urb.c2
-rw-r--r--drivers/usb/core/usb.c1
-rw-r--r--drivers/usb/core/usb.h7
-rw-r--r--drivers/usb/dwc3/Kconfig25
-rw-r--r--drivers/usb/dwc3/Makefile36
-rw-r--r--drivers/usb/dwc3/core.c484
-rw-r--r--drivers/usb/dwc3/core.h768
-rw-r--r--drivers/usb/dwc3/debug.h50
-rw-r--r--drivers/usb/dwc3/debugfs.c441
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c401
-rw-r--r--drivers/usb/dwc3/dwc3-pci.c219
-rw-r--r--drivers/usb/dwc3/ep0.c804
-rw-r--r--drivers/usb/dwc3/gadget.c2104
-rw-r--r--drivers/usb/dwc3/gadget.h211
-rw-r--r--drivers/usb/dwc3/io.h54
-rw-r--r--drivers/usb/gadget/Kconfig47
-rw-r--r--drivers/usb/gadget/Makefile4
-rw-r--r--drivers/usb/gadget/acm_ms.c256
-rw-r--r--drivers/usb/gadget/amd5536udc.c20
-rw-r--r--drivers/usb/gadget/amd5536udc.h9
-rw-r--r--drivers/usb/gadget/at91_udc.c32
-rw-r--r--drivers/usb/gadget/at91_udc.h10
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c13
-rw-r--r--drivers/usb/gadget/cdc2.c9
-rw-r--r--drivers/usb/gadget/ci13xxx_msm.c11
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.c2
-rw-r--r--drivers/usb/gadget/composite.c37
-rw-r--r--drivers/usb/gadget/config.c9
-rw-r--r--drivers/usb/gadget/dbgp.c1
-rw-r--r--drivers/usb/gadget/dummy_hcd.c13
-rw-r--r--drivers/usb/gadget/epautoconf.c12
-rw-r--r--drivers/usb/gadget/ether.c9
-rw-r--r--drivers/usb/gadget/f_audio.c15
-rw-r--r--drivers/usb/gadget/f_ecm.c9
-rw-r--r--drivers/usb/gadget/f_eem.c9
-rw-r--r--drivers/usb/gadget/f_fs.c9
-rw-r--r--drivers/usb/gadget/f_hid.c9
-rw-r--r--drivers/usb/gadget/f_loopback.c9
-rw-r--r--drivers/usb/gadget/f_mass_storage.c196
-rw-r--r--drivers/usb/gadget/f_midi.c998
-rw-r--r--drivers/usb/gadget/f_ncm.c9
-rw-r--r--drivers/usb/gadget/f_obex.c9
-rw-r--r--drivers/usb/gadget/f_phonet.c10
-rw-r--r--drivers/usb/gadget/f_rndis.c9
-rw-r--r--drivers/usb/gadget/f_sourcesink.c9
-rw-r--r--drivers/usb/gadget/f_subset.c9
-rw-r--r--drivers/usb/gadget/f_uvc.c1
-rw-r--r--drivers/usb/gadget/f_uvc.h1
-rw-r--r--drivers/usb/gadget/file_storage.c254
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c2
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c55
-rw-r--r--drivers/usb/gadget/fusb300_udc.c16
-rw-r--r--drivers/usb/gadget/fusb300_udc.h10
-rw-r--r--drivers/usb/gadget/g_ffs.c9
-rw-r--r--drivers/usb/gadget/gadget_chips.h3
-rw-r--r--drivers/usb/gadget/gmidi.c1292
-rw-r--r--drivers/usb/gadget/hid.c9
-rw-r--r--drivers/usb/gadget/imx_udc.c4
-rw-r--r--drivers/usb/gadget/imx_udc.h5
-rw-r--r--drivers/usb/gadget/inode.c9
-rw-r--r--drivers/usb/gadget/langwell_udc.c149
-rw-r--r--drivers/usb/gadget/langwell_udc.h12
-rw-r--r--drivers/usb/gadget/m66592-udc.c16
-rw-r--r--drivers/usb/gadget/m66592-udc.h10
-rw-r--r--drivers/usb/gadget/mass_storage.c11
-rw-r--r--drivers/usb/gadget/multi.c9
-rw-r--r--drivers/usb/gadget/mv_udc.h26
-rw-r--r--drivers/usb/gadget/mv_udc_core.c564
-rw-r--r--drivers/usb/gadget/mv_udc_phy.c214
-rw-r--r--drivers/usb/gadget/ncm.c9
-rw-r--r--drivers/usb/gadget/ndis.h6
-rw-r--r--drivers/usb/gadget/net2272.c78
-rw-r--r--drivers/usb/gadget/net2280.c89
-rw-r--r--drivers/usb/gadget/net2280.h9
-rw-r--r--drivers/usb/gadget/omap_udc.c18
-rw-r--r--drivers/usb/gadget/pch_udc.c15
-rw-r--r--drivers/usb/gadget/printer.c25
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c30
-rw-r--r--drivers/usb/gadget/pxa25x_udc.h17
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c12
-rw-r--r--drivers/usb/gadget/pxa27x_udc.h9
-rw-r--r--drivers/usb/gadget/r8a66597-udc.c516
-rw-r--r--drivers/usb/gadget/r8a66597-udc.h73
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c10
-rw-r--r--drivers/usb/gadget/s3c-hsudc.c69
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c16
-rw-r--r--drivers/usb/gadget/s3c2410_udc.h10
-rw-r--r--drivers/usb/gadget/storage_common.c185
-rw-r--r--drivers/usb/gadget/u_ether.c9
-rw-r--r--drivers/usb/gadget/u_ether.h9
-rw-r--r--drivers/usb/gadget/u_serial.c3
-rw-r--r--drivers/usb/gadget/udc-core.c21
-rw-r--r--drivers/usb/gadget/uvc.h2
-rw-r--r--drivers/usb/gadget/uvc_queue.c1
-rw-r--r--drivers/usb/gadget/uvc_v4l2.c2
-rw-r--r--drivers/usb/gadget/uvc_video.c1
-rw-r--r--drivers/usb/gadget/webcam.c2
-rw-r--r--drivers/usb/gadget/zero.c9
-rw-r--r--drivers/usb/host/Kconfig28
-rw-r--r--drivers/usb/host/Makefile3
-rw-r--r--drivers/usb/host/ehci-ath79.c2
-rw-r--r--drivers/usb/host/ehci-au1xxx.c4
-rw-r--r--drivers/usb/host/ehci-dbg.c19
-rw-r--r--drivers/usb/host/ehci-fsl.c6
-rw-r--r--drivers/usb/host/ehci-hcd.c64
-rw-r--r--drivers/usb/host/ehci-hub.c10
-rw-r--r--drivers/usb/host/ehci-mxc.c2
-rw-r--r--drivers/usb/host/ehci-octeon.c2
-rw-r--r--drivers/usb/host/ehci-omap.c2
-rw-r--r--drivers/usb/host/ehci-orion.c2
-rw-r--r--drivers/usb/host/ehci-pci.c7
-rw-r--r--drivers/usb/host/ehci-ps3.c2
-rw-r--r--drivers/usb/host/ehci-pxa168.c363
-rw-r--r--drivers/usb/host/ehci-q.c31
-rw-r--r--drivers/usb/host/ehci-s5p.c4
-rw-r--r--drivers/usb/host/ehci-sched.c41
-rw-r--r--drivers/usb/host/ehci-sh.c2
-rw-r--r--drivers/usb/host/ehci-spear.c2
-rw-r--r--drivers/usb/host/ehci-tegra.c2
-rw-r--r--drivers/usb/host/ehci-vt8500.c2
-rw-r--r--drivers/usb/host/ehci-xls.c161
-rw-r--r--drivers/usb/host/ehci.h24
-rw-r--r--drivers/usb/host/fhci-hcd.c9
-rw-r--r--drivers/usb/host/fhci-sched.c19
-rw-r--r--drivers/usb/host/imx21-hcd.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c2
-rw-r--r--drivers/usb/host/isp1362-hcd.c8
-rw-r--r--drivers/usb/host/isp1760-hcd.c418
-rw-r--r--drivers/usb/host/isp1760-hcd.h5
-rw-r--r--drivers/usb/host/isp1760-if.c80
-rw-r--r--drivers/usb/host/ohci-at91.c239
-rw-r--r--drivers/usb/host/ohci-ath79.c2
-rw-r--r--drivers/usb/host/ohci-au1xxx.c2
-rw-r--r--drivers/usb/host/ohci-da8xx.c2
-rw-r--r--drivers/usb/host/ohci-ep93xx.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c5
-rw-r--r--drivers/usb/host/ohci-hub.c5
-rw-r--r--drivers/usb/host/ohci-octeon.c2
-rw-r--r--drivers/usb/host/ohci-omap.c4
-rw-r--r--drivers/usb/host/ohci-omap3.c4
-rw-r--r--drivers/usb/host/ohci-pnx4008.c4
-rw-r--r--drivers/usb/host/ohci-pnx8550.c2
-rw-r--r--drivers/usb/host/ohci-ppc-of.c2
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c2
-rw-r--r--drivers/usb/host/ohci-ps3.c2
-rw-r--r--drivers/usb/host/ohci-pxa27x.c2
-rw-r--r--drivers/usb/host/ohci-q.c4
-rw-r--r--drivers/usb/host/ohci-s3c2410.c2
-rw-r--r--drivers/usb/host/ohci-sa1111.c2
-rw-r--r--drivers/usb/host/ohci-sh.c2
-rw-r--r--drivers/usb/host/ohci-sm501.c2
-rw-r--r--drivers/usb/host/ohci-spear.c2
-rw-r--r--drivers/usb/host/ohci-ssb.c2
-rw-r--r--drivers/usb/host/ohci-tmio.c2
-rw-r--r--drivers/usb/host/ohci-xls.c151
-rw-r--r--drivers/usb/host/r8a66597-hcd.c4
-rw-r--r--drivers/usb/host/sl811-hcd.c2
-rw-r--r--drivers/usb/host/uhci-hcd.c66
-rw-r--r--drivers/usb/host/uhci-q.c6
-rw-r--r--drivers/usb/host/xhci-ext-caps.h6
-rw-r--r--drivers/usb/host/xhci-hub.c139
-rw-r--r--drivers/usb/host/xhci-mem.c371
-rw-r--r--drivers/usb/host/xhci-pci.c107
-rw-r--r--drivers/usb/host/xhci-ring.c80
-rw-r--r--drivers/usb/host/xhci.c1151
-rw-r--r--drivers/usb/host/xhci.h187
-rw-r--r--drivers/usb/misc/adutux.c14
-rw-r--r--drivers/usb/misc/ftdi-elan.c2
-rw-r--r--drivers/usb/misc/idmouse.c2
-rw-r--r--drivers/usb/misc/iowarrior.c2
-rw-r--r--drivers/usb/misc/ldusb.c4
-rw-r--r--drivers/usb/misc/legousbtower.c4
-rw-r--r--drivers/usb/misc/usblcd.c129
-rw-r--r--drivers/usb/misc/usbled.c25
-rw-r--r--drivers/usb/misc/usbtest.c31
-rw-r--r--drivers/usb/mon/mon_bin.c2
-rw-r--r--drivers/usb/musb/davinci.c2
-rw-r--r--drivers/usb/musb/musb_debugfs.c6
-rw-r--r--drivers/usb/musb/musb_gadget.c73
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c8
-rw-r--r--drivers/usb/musb/musb_host.c2
-rw-r--r--drivers/usb/musb/musbhsdma.c2
-rw-r--r--drivers/usb/otg/isp1301_omap.c2
-rw-r--r--drivers/usb/otg/twl6030-usb.c16
-rw-r--r--drivers/usb/renesas_usbhs/Kconfig2
-rw-r--r--drivers/usb/renesas_usbhs/Makefile8
-rw-r--r--drivers/usb/renesas_usbhs/common.c236
-rw-r--r--drivers/usb/renesas_usbhs/common.h60
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c222
-rw-r--r--drivers/usb/renesas_usbhs/fifo.h22
-rw-r--r--drivers/usb/renesas_usbhs/mod.c81
-rw-r--r--drivers/usb/renesas_usbhs/mod.h57
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c130
-rw-r--r--drivers/usb/renesas_usbhs/mod_host.c1312
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c200
-rw-r--r--drivers/usb/renesas_usbhs/pipe.h27
-rw-r--r--drivers/usb/serial/Kconfig1
-rw-r--r--drivers/usb/serial/digi_acceleport.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c91
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h7
-rw-r--r--drivers/usb/serial/io_edgeport.c4
-rw-r--r--drivers/usb/serial/ipw.c33
-rw-r--r--drivers/usb/serial/mos7720.c1
-rw-r--r--drivers/usb/serial/mos7840.c1
-rw-r--r--drivers/usb/serial/opticon.c2
-rw-r--r--drivers/usb/serial/option.c170
-rw-r--r--drivers/usb/serial/pl2303.c4
-rw-r--r--drivers/usb/serial/pl2303.h5
-rw-r--r--drivers/usb/serial/qcserial.c2
-rw-r--r--drivers/usb/serial/sierra.c2
-rw-r--r--drivers/usb/serial/symbolserial.c2
-rw-r--r--drivers/usb/serial/usb-serial.c8
-rw-r--r--drivers/usb/serial/usb_wwan.c2
-rw-r--r--drivers/usb/storage/Kconfig2
-rw-r--r--drivers/usb/storage/realtek_cr.c117
-rw-r--r--drivers/usb/storage/transport.c34
-rw-r--r--drivers/usb/storage/usb.c16
-rw-r--r--drivers/usb/usb-common.c35
-rw-r--r--drivers/usb/usb-skeleton.c2
-rw-r--r--drivers/usb/wusbcore/wa-hc.c2
-rw-r--r--drivers/uwb/uwb-internal.h1
-rw-r--r--drivers/video/68328fb.c4
-rw-r--r--drivers/video/Kconfig34
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/acornfb.c5
-rw-r--r--drivers/video/amba-clcd.c9
-rw-r--r--drivers/video/arkfb.c9
-rw-r--r--drivers/video/atmel_lcdfb.c17
-rw-r--r--drivers/video/aty/radeon_base.c10
-rw-r--r--drivers/video/au1100fb.c181
-rw-r--r--drivers/video/au1100fb.h6
-rw-r--r--drivers/video/au1200fb.c299
-rw-r--r--drivers/video/backlight/adp8860_bl.c1
-rw-r--r--drivers/video/backlight/adp8870_bl.c3
-rw-r--r--drivers/video/backlight/generic_bl.c4
-rw-r--r--drivers/video/backlight/l4f00242t03.c70
-rw-r--r--drivers/video/bf54x-lq043fb.c2
-rw-r--r--drivers/video/bfin-lq035q1-fb.c2
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c2
-rw-r--r--drivers/video/bfin_adv7393fb.c2
-rw-r--r--drivers/video/carminefb.c6
-rw-r--r--drivers/video/console/vgacon.c42
-rw-r--r--drivers/video/controlfb.c2
-rw-r--r--drivers/video/da8xx-fb.c186
-rw-r--r--drivers/video/fb-puv3.c4
-rw-r--r--drivers/video/fb_defio.c3
-rw-r--r--drivers/video/fbmem.c3
-rw-r--r--drivers/video/fbmon.c21
-rw-r--r--drivers/video/fbsysfs.c3
-rw-r--r--drivers/video/fsl-diu-fb.c992
-rw-r--r--drivers/video/g364fb.c5
-rw-r--r--drivers/video/grvga.c579
-rw-r--r--drivers/video/gxt4500.c4
-rw-r--r--drivers/video/hgafb.c4
-rw-r--r--drivers/video/igafb.c2
-rw-r--r--drivers/video/imsttfb.c2
-rw-r--r--drivers/video/intelfb/intelfbhw.c6
-rw-r--r--drivers/video/mb862xx/mb862xx-i2c.c2
-rw-r--r--drivers/video/mb862xx/mb862xxfbdrv.c6
-rw-r--r--drivers/video/mbx/mbxfb.c6
-rw-r--r--drivers/video/modedb.c444
-rw-r--r--drivers/video/msm/mddi.c2
-rw-r--r--drivers/video/msm/mdp.c6
-rw-r--r--drivers/video/mx3fb.c19
-rw-r--r--drivers/video/mxsfb.c1
-rw-r--r--drivers/video/neofb.c4
-rw-r--r--drivers/video/nuc900fb.c3
-rw-r--r--drivers/video/omap/Kconfig29
-rw-r--r--drivers/video/omap/Makefile8
-rw-r--r--drivers/video/omap/lcd_2430sdp.c203
-rw-r--r--drivers/video/omap/lcd_apollon.c136
-rw-r--r--drivers/video/omap/lcd_h3.c2
-rw-r--r--drivers/video/omap/lcd_h4.c117
-rw-r--r--drivers/video/omap/lcd_inn1610.c2
-rw-r--r--drivers/video/omap/lcd_ldp.c201
-rw-r--r--drivers/video/omap/lcd_omap3beagle.c130
-rw-r--r--drivers/video/omap/lcd_omap3evm.c193
-rw-r--r--drivers/video/omap/lcd_osk.c2
-rw-r--r--drivers/video/omap/lcd_overo.c180
-rw-r--r--drivers/video/omap/lcd_palmtt.c2
-rw-r--r--drivers/video/omap2/displays/Kconfig28
-rw-r--r--drivers/video/omap2/displays/Makefile3
-rw-r--r--drivers/video/omap2/displays/panel-dvi.c363
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c113
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c747
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c594
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.h288
-rw-r--r--drivers/video/omap2/displays/panel-taal.c125
-rw-r--r--drivers/video/omap2/dss/Kconfig2
-rw-r--r--drivers/video/omap2/dss/Makefile2
-rw-r--r--drivers/video/omap2/dss/core.c4
-rw-r--r--drivers/video/omap2/dss/dispc.c1700
-rw-r--r--drivers/video/omap2/dss/dispc.h57
-rw-r--r--drivers/video/omap2/dss/display.c31
-rw-r--r--drivers/video/omap2/dss/dpi.c28
-rw-r--r--drivers/video/omap2/dss/dsi.c929
-rw-r--r--drivers/video/omap2/dss/dss.c18
-rw-r--r--drivers/video/omap2/dss/dss.h156
-rw-r--r--drivers/video/omap2/dss/dss_features.c130
-rw-r--r--drivers/video/omap2/dss/dss_features.h17
-rw-r--r--drivers/video/omap2/dss/hdmi.c1260
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c (renamed from drivers/video/omap2/dss/hdmi_omap4_panel.c)68
-rw-r--r--drivers/video/omap2/dss/manager.c191
-rw-r--r--drivers/video/omap2/dss/overlay.c122
-rw-r--r--drivers/video/omap2/dss/rfbi.c45
-rw-r--r--drivers/video/omap2/dss/sdi.c19
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h138
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c1239
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h (renamed from drivers/video/omap2/dss/hdmi.h)400
-rw-r--r--drivers/video/omap2/dss/venc.c27
-rw-r--r--drivers/video/omap2/omapfb/Kconfig2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c134
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c6
-rw-r--r--drivers/video/platinumfb.c4
-rw-r--r--drivers/video/pm2fb.c6
-rw-r--r--drivers/video/pm3fb.c6
-rw-r--r--drivers/video/pnx4008/sdum.c2
-rw-r--r--drivers/video/ps3fb.c2
-rw-r--r--drivers/video/pxa3xx-gcu.c4
-rw-r--r--drivers/video/pxafb.c12
-rw-r--r--drivers/video/s3c-fb.c117
-rw-r--r--drivers/video/s3c2410fb.c3
-rw-r--r--drivers/video/s3fb.c9
-rw-r--r--drivers/video/sa1100fb.c3
-rw-r--r--drivers/video/savage/savagefb_driver.c16
-rw-r--r--drivers/video/sh_mobile_hdmi.c47
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c1162
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h12
-rw-r--r--drivers/video/sh_mobile_meram.c208
-rw-r--r--drivers/video/sh_mobile_meram.h41
-rw-r--r--drivers/video/sis/sis_main.c30
-rw-r--r--drivers/video/skeletonfb.c2
-rw-r--r--drivers/video/sm501fb.c6
-rw-r--r--drivers/video/smscufx.c1994
-rw-r--r--drivers/video/tmiofb.c2
-rw-r--r--drivers/video/tridentfb.c4
-rw-r--r--drivers/video/udlfb.c187
-rw-r--r--drivers/video/valkyriefb.c2
-rw-r--r--drivers/video/vfb.c4
-rw-r--r--drivers/video/vga16fb.c2
-rw-r--r--drivers/video/via/dvi.c34
-rw-r--r--drivers/video/via/dvi.h3
-rw-r--r--drivers/video/via/global.c2
-rw-r--r--drivers/video/via/global.h2
-rw-r--r--drivers/video/via/hw.c544
-rw-r--r--drivers/video/via/hw.h285
-rw-r--r--drivers/video/via/lcd.c53
-rw-r--r--drivers/video/via/lcd.h7
-rw-r--r--drivers/video/via/share.h23
-rw-r--r--drivers/video/via/via-core.c2
-rw-r--r--drivers/video/via/via_modesetting.c104
-rw-r--r--drivers/video/via/via_modesetting.h23
-rw-r--r--drivers/video/via/viafbdev.c182
-rw-r--r--drivers/video/via/viamode.c60
-rw-r--r--drivers/video/via/viamode.h4
-rw-r--r--drivers/video/vt8500lcdfb.c6
-rw-r--r--drivers/video/vt8623fb.c9
-rw-r--r--drivers/video/xilinxfb.c1
-rw-r--r--drivers/virtio/Kconfig11
-rw-r--r--drivers/virtio/Makefile1
-rw-r--r--drivers/virtio/virtio_mmio.c479
-rw-r--r--drivers/virtio/virtio_pci.c10
-rw-r--r--drivers/virtio/virtio_ring.c10
-rw-r--r--drivers/w1/slaves/w1_ds2760.c48
-rw-r--r--drivers/w1/slaves/w1_ds2780.c96
-rw-r--r--drivers/w1/slaves/w1_ds2780.h2
-rw-r--r--drivers/w1/w1_int.c1
-rw-r--r--drivers/w1/w1_io.c5
-rw-r--r--drivers/watchdog/Kconfig6
-rw-r--r--drivers/watchdog/bcm47xx_wdt.c27
-rw-r--r--drivers/watchdog/hpwdt.c25
-rw-r--r--drivers/watchdog/smsc37b787_wdt.c2
-rw-r--r--drivers/xen/Kconfig10
-rw-r--r--drivers/xen/Makefile4
-rw-r--r--drivers/xen/balloon.c62
-rw-r--r--drivers/xen/events.c49
-rw-r--r--drivers/xen/gntdev.c39
-rw-r--r--drivers/xen/grant-table.c6
-rw-r--r--drivers/xen/pci.c105
-rw-r--r--drivers/xen/swiotlb-xen.c70
-rw-r--r--drivers/xen/xen-pciback/conf_space.c1
-rw-r--r--drivers/xen/xen-pciback/conf_space_header.c5
-rw-r--r--drivers/xen/xen-pciback/conf_space_quirks.c3
-rw-r--r--drivers/xen/xen-pciback/passthrough.c34
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c35
-rw-r--r--drivers/xen/xen-pciback/pciback.h32
-rw-r--r--drivers/xen/xen-pciback/pciback_ops.c1
-rw-r--r--drivers/xen/xen-pciback/vpci.c35
-rw-r--r--drivers/xen/xen-pciback/xenbus.c29
-rw-r--r--drivers/xen/xen-selfballoon.c67
-rw-r--r--drivers/xen/xenbus/xenbus_comms.c4
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c101
-rw-r--r--drivers/xen/xenbus/xenbus_probe_backend.c2
-rw-r--r--drivers/xen/xenbus/xenbus_probe_frontend.c121
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c17
-rw-r--r--drivers/zorro/zorro-driver.c8
-rw-r--r--fs/9p/v9fs.c33
-rw-r--r--fs/9p/vfs_dir.c14
-rw-r--r--fs/9p/vfs_inode.c6
-rw-r--r--fs/9p/vfs_inode_dotl.c4
-rw-r--r--fs/Kconfig2
-rw-r--r--fs/Makefile2
-rw-r--r--fs/adfs/inode.c2
-rw-r--r--fs/affs/amigaffs.c4
-rw-r--r--fs/affs/inode.c8
-rw-r--r--fs/affs/namei.c6
-rw-r--r--fs/afs/fsclient.c2
-rw-r--r--fs/afs/inode.c4
-rw-r--r--fs/aio.c140
-rw-r--r--fs/attr.c5
-rw-r--r--fs/autofs4/inode.c2
-rw-r--r--fs/befs/linuxvfs.c2
-rw-r--r--fs/bfs/dir.c2
-rw-r--r--fs/bfs/inode.c2
-rw-r--r--fs/binfmt_elf.c11
-rw-r--r--fs/binfmt_misc.c2
-rw-r--r--fs/btrfs/delayed-inode.c2
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/file.c2
-rw-r--r--fs/btrfs/inode.c4
-rw-r--r--fs/btrfs/tree-log.c2
-rw-r--r--fs/btrfs/xattr.c50
-rw-r--r--fs/buffer.c9
-rw-r--r--fs/ceph/addr.c193
-rw-r--r--fs/ceph/caps.c4
-rw-r--r--fs/ceph/inode.c48
-rw-r--r--fs/ceph/ioctl.c34
-rw-r--r--fs/ceph/ioctl.h55
-rw-r--r--fs/ceph/mds_client.c11
-rw-r--r--fs/ceph/super.c61
-rw-r--r--fs/ceph/super.h19
-rw-r--r--fs/cifs/README14
-rw-r--r--fs/cifs/cifs_debug.c9
-rw-r--r--fs/cifs/cifs_fs_sb.h4
-rw-r--r--fs/cifs/cifsacl.c347
-rw-r--r--fs/cifs/cifsencrypt.c105
-rw-r--r--fs/cifs/cifsfs.c26
-rw-r--r--fs/cifs/cifsfs.h4
-rw-r--r--fs/cifs/cifsglob.h55
-rw-r--r--fs/cifs/cifspdu.h48
-rw-r--r--fs/cifs/cifsproto.h48
-rw-r--r--fs/cifs/cifssmb.c454
-rw-r--r--fs/cifs/connect.c699
-rw-r--r--fs/cifs/dir.c22
-rw-r--r--fs/cifs/export.c4
-rw-r--r--fs/cifs/file.c1126
-rw-r--r--fs/cifs/inode.c60
-rw-r--r--fs/cifs/link.c19
-rw-r--r--fs/cifs/misc.c66
-rw-r--r--fs/cifs/sess.c4
-rw-r--r--fs/cifs/smbencrypt.c121
-rw-r--r--fs/cifs/transport.c19
-rw-r--r--fs/cifs/xattr.c42
-rw-r--r--fs/coda/coda_linux.c2
-rw-r--r--fs/coda/coda_linux.h5
-rw-r--r--fs/coda/dir.c2
-rw-r--r--fs/compat.c15
-rw-r--r--fs/configfs/inode.c3
-rw-r--r--fs/configfs/item.c2
-rw-r--r--fs/dcache.c40
-rw-r--r--fs/debugfs/inode.c2
-rw-r--r--fs/devpts/inode.c4
-rw-r--r--fs/direct-io.c646
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h2
-rw-r--r--fs/ecryptfs/inode.c12
-rw-r--r--fs/efs/inode.c2
-rw-r--r--fs/eventpoll.c27
-rw-r--r--fs/exec.c4
-rw-r--r--fs/exofs/Kbuild3
-rw-r--r--fs/exofs/Kconfig9
-rw-r--r--fs/exofs/exofs.h26
-rw-r--r--fs/exofs/inode.c235
-rw-r--r--fs/exofs/ore.c656
-rw-r--r--fs/exofs/ore_raid.c660
-rw-r--r--fs/exofs/ore_raid.h79
-rw-r--r--fs/exofs/super.c205
-rw-r--r--fs/ext2/balloc.c2
-rw-r--r--fs/ext2/ext2.h8
-rw-r--r--fs/ext2/ialloc.c2
-rw-r--r--fs/ext2/inode.c2
-rw-r--r--fs/ext2/super.c8
-rw-r--r--fs/ext2/xattr_security.c34
-rw-r--r--fs/ext3/balloc.c17
-rw-r--r--fs/ext3/fsync.c10
-rw-r--r--fs/ext3/ialloc.c47
-rw-r--r--fs/ext3/inode.c2
-rw-r--r--fs/ext3/ioctl.c24
-rw-r--r--fs/ext3/namei.c6
-rw-r--r--fs/ext3/super.c12
-rw-r--r--fs/ext3/xattr_security.c36
-rw-r--r--fs/ext4/balloc.c345
-rw-r--r--fs/ext4/ext4.h185
-rw-r--r--fs/ext4/ext4_extents.h2
-rw-r--r--fs/ext4/ext4_jbd2.c8
-rw-r--r--fs/ext4/extents.c1168
-rw-r--r--fs/ext4/file.c51
-rw-r--r--fs/ext4/fsync.c10
-rw-r--r--fs/ext4/ialloc.c206
-rw-r--r--fs/ext4/indirect.c20
-rw-r--r--fs/ext4/inode.c520
-rw-r--r--fs/ext4/ioctl.c65
-rw-r--r--fs/ext4/mballoc.c331
-rw-r--r--fs/ext4/mballoc.h11
-rw-r--r--fs/ext4/migrate.c111
-rw-r--r--fs/ext4/mmp.c10
-rw-r--r--fs/ext4/move_extent.c1
-rw-r--r--fs/ext4/namei.c29
-rw-r--r--fs/ext4/page-io.c66
-rw-r--r--fs/ext4/resize.c10
-rw-r--r--fs/ext4/super.c263
-rw-r--r--fs/ext4/xattr.c12
-rw-r--r--fs/ext4/xattr_security.c36
-rw-r--r--fs/fat/dir.c4
-rw-r--r--fs/fat/fat.h9
-rw-r--r--fs/fat/inode.c4
-rw-r--r--fs/fat/namei_msdos.c2
-rw-r--r--fs/fat/namei_vfat.c2
-rw-r--r--fs/freevxfs/vxfs_inode.c2
-rw-r--r--fs/fuse/control.c2
-rw-r--r--fs/fuse/inode.c2
-rw-r--r--fs/gfs2/acl.c5
-rw-r--r--fs/gfs2/aops.c8
-rw-r--r--fs/gfs2/bmap.c199
-rw-r--r--fs/gfs2/dir.c50
-rw-r--r--fs/gfs2/file.c299
-rw-r--r--fs/gfs2/glock.h2
-rw-r--r--fs/gfs2/glops.c91
-rw-r--r--fs/gfs2/glops.h2
-rw-r--r--fs/gfs2/incore.h23
-rw-r--r--fs/gfs2/inode.c150
-rw-r--r--fs/gfs2/inode.h2
-rw-r--r--fs/gfs2/lops.c66
-rw-r--r--fs/gfs2/ops_fstype.c6
-rw-r--r--fs/gfs2/quota.c28
-rw-r--r--fs/gfs2/rgrp.c573
-rw-r--r--fs/gfs2/rgrp.h31
-rw-r--r--fs/gfs2/super.c134
-rw-r--r--fs/gfs2/trans.c5
-rw-r--r--fs/gfs2/trans.h22
-rw-r--r--fs/gfs2/xattr.c28
-rw-r--r--fs/hfs/btree.c20
-rw-r--r--fs/hfs/dir.c4
-rw-r--r--fs/hfs/inode.c4
-rw-r--r--fs/hfsplus/dir.c4
-rw-r--r--fs/hfsplus/inode.c10
-rw-r--r--fs/hostfs/hostfs_kern.c2
-rw-r--r--fs/hostfs/hostfs_user.c1
-rw-r--r--fs/hpfs/dir.c2
-rw-r--r--fs/hpfs/hpfs_fn.h4
-rw-r--r--fs/hpfs/inode.c10
-rw-r--r--fs/hpfs/namei.c8
-rw-r--r--fs/hppfs/hppfs.c2
-rw-r--r--fs/hugetlbfs/inode.c2
-rw-r--r--fs/inode.c4
-rw-r--r--fs/isofs/inode.c14
-rw-r--r--fs/isofs/rock.c4
-rw-r--r--fs/jbd/journal.c8
-rw-r--r--fs/jbd2/commit.c26
-rw-r--r--fs/jbd2/journal.c44
-rw-r--r--fs/jbd2/recovery.c28
-rw-r--r--fs/jbd2/transaction.c68
-rw-r--r--fs/jffs2/dir.c6
-rw-r--r--fs/jffs2/fs.c6
-rw-r--r--fs/jffs2/security.c35
-rw-r--r--fs/jfs/jfs_imap.c6
-rw-r--r--fs/jfs/jfs_inode.c2
-rw-r--r--fs/jfs/namei.c12
-rw-r--r--fs/jfs/super.c1
-rw-r--r--fs/jfs/xattr.c57
-rw-r--r--fs/libfs.c6
-rw-r--r--fs/lockd/host.c25
-rw-r--r--fs/lockd/svc.c2
-rw-r--r--fs/locks.c225
-rw-r--r--fs/logfs/dir.c8
-rw-r--r--fs/logfs/inode.c3
-rw-r--r--fs/logfs/logfs.h1
-rw-r--r--fs/logfs/readwrite.c2
-rw-r--r--fs/logfs/super.c22
-rw-r--r--fs/minix/inode.c4
-rw-r--r--fs/namei.c35
-rw-r--r--fs/namespace.c1
-rw-r--r--fs/ncpfs/inode.c2
-rw-r--r--fs/nfs/blocklayout/blocklayout.c58
-rw-r--r--fs/nfs/blocklayout/blocklayout.h4
-rw-r--r--fs/nfs/blocklayout/blocklayoutdev.c35
-rw-r--r--fs/nfs/callback.c4
-rw-r--r--fs/nfs/client.c11
-rw-r--r--fs/nfs/delegation.c2
-rw-r--r--fs/nfs/file.c10
-rw-r--r--fs/nfs/fscache-index.c4
-rw-r--r--fs/nfs/idmap.c25
-rw-r--r--fs/nfs/inode.c22
-rw-r--r--fs/nfs/internal.h10
-rw-r--r--fs/nfs/nfs4_fs.h24
-rw-r--r--fs/nfs/nfs4filelayout.c33
-rw-r--r--fs/nfs/nfs4proc.c93
-rw-r--r--fs/nfs/pnfs.c52
-rw-r--r--fs/nfs/pnfs.h5
-rw-r--r--fs/nfs/read.c40
-rw-r--r--fs/nfs/super.c17
-rw-r--r--fs/nfs/unlink.c4
-rw-r--r--fs/nfs/write.c73
-rw-r--r--fs/nfsd/export.c16
-rw-r--r--fs/nfsd/nfs4callback.c20
-rw-r--r--fs/nfsd/nfs4proc.c374
-rw-r--r--fs/nfsd/nfs4recover.c53
-rw-r--r--fs/nfsd/nfs4state.c1794
-rw-r--r--fs/nfsd/nfs4xdr.c380
-rw-r--r--fs/nfsd/nfsctl.c1
-rw-r--r--fs/nfsd/nfsd.h33
-rw-r--r--fs/nfsd/nfsfh.c39
-rw-r--r--fs/nfsd/state.h174
-rw-r--r--fs/nfsd/vfs.c31
-rw-r--r--fs/nfsd/vfs.h29
-rw-r--r--fs/nfsd/xdr4.h28
-rw-r--r--fs/nilfs2/inode.c4
-rw-r--r--fs/nilfs2/namei.c2
-rw-r--r--fs/nilfs2/nilfs.h8
-rw-r--r--fs/ntfs/debug.h15
-rw-r--r--fs/ntfs/inode.c8
-rw-r--r--fs/ocfs2/dir.c4
-rw-r--r--fs/ocfs2/dlmglue.c2
-rw-r--r--fs/ocfs2/inode.c4
-rw-r--r--fs/ocfs2/namei.c18
-rw-r--r--fs/ocfs2/super.h14
-rw-r--r--fs/ocfs2/xattr.c38
-rw-r--r--fs/open.c4
-rw-r--r--fs/openpromfs/inode.c4
-rw-r--r--fs/partitions/ldm.c16
-rw-r--r--fs/pipe.c1
-rw-r--r--fs/posix_acl.c2
-rw-r--r--fs/proc/base.c171
-rw-r--r--fs/proc/generic.c2
-rw-r--r--fs/proc/inode.c2
-rw-r--r--fs/proc/proc_sysctl.c48
-rw-r--r--fs/proc/stat.c41
-rw-r--r--fs/proc/task_mmu.c5
-rw-r--r--fs/pstore/inode.c40
-rw-r--r--fs/pstore/internal.h2
-rw-r--r--fs/pstore/platform.c93
-rw-r--r--fs/qnx4/inode.c2
-rw-r--r--fs/quota/quota.c7
-rw-r--r--fs/ramfs/inode.c10
-rw-r--r--fs/read_write.c82
-rw-r--r--fs/reiserfs/inode.c10
-rw-r--r--fs/reiserfs/journal.c9
-rw-r--r--fs/reiserfs/namei.c16
-rw-r--r--fs/reiserfs/resize.c4
-rw-r--r--fs/reiserfs/xattr_security.c4
-rw-r--r--fs/romfs/super.c2
-rw-r--r--fs/squashfs/Kconfig6
-rw-r--r--fs/squashfs/inode.c18
-rw-r--r--fs/stack.c2
-rw-r--r--fs/stat.c5
-rw-r--r--fs/super.c11
-rw-r--r--fs/sysfs/dir.c196
-rw-r--r--fs/sysfs/file.c56
-rw-r--r--fs/sysfs/inode.c16
-rw-r--r--fs/sysfs/sysfs.h17
-rw-r--r--fs/sysv/inode.c2
-rw-r--r--fs/ubifs/super.c2
-rw-r--r--fs/ubifs/xattr.c4
-rw-r--r--fs/udf/balloc.c14
-rw-r--r--fs/udf/directory.c8
-rw-r--r--fs/udf/inode.c56
-rw-r--r--fs/udf/lowlevel.c2
-rw-r--r--fs/udf/misc.c19
-rw-r--r--fs/udf/namei.c20
-rw-r--r--fs/udf/partition.c19
-rw-r--r--fs/udf/super.c280
-rw-r--r--fs/udf/truncate.c22
-rw-r--r--fs/udf/udf_sb.h5
-rw-r--r--fs/udf/udfdecl.h35
-rw-r--r--fs/udf/udftime.c3
-rw-r--r--fs/udf/unicode.c6
-rw-r--r--fs/ufs/ialloc.c2
-rw-r--r--fs/ufs/inode.c4
-rw-r--r--fs/ufs/ufs.h9
-rw-r--r--fs/xattr.c63
-rw-r--r--fs/xfs/kmem.h7
-rw-r--r--fs/xfs/xfs_alloc.c4
-rw-r--r--fs/xfs/xfs_aops.c127
-rw-r--r--fs/xfs/xfs_aops.h4
-rw-r--r--fs/xfs/xfs_attr.c89
-rw-r--r--fs/xfs/xfs_attr_leaf.c7
-rw-r--r--fs/xfs/xfs_bmap.c2531
-rw-r--r--fs/xfs/xfs_bmap.h318
-rw-r--r--fs/xfs/xfs_btree.c11
-rw-r--r--fs/xfs/xfs_buf.c244
-rw-r--r--fs/xfs/xfs_buf.h51
-rw-r--r--fs/xfs/xfs_buf_item.c12
-rw-r--r--fs/xfs/xfs_da_btree.c54
-rw-r--r--fs/xfs/xfs_dfrag.c6
-rw-r--r--fs/xfs/xfs_dir2_leaf.c6
-rw-r--r--fs/xfs/xfs_discard.c20
-rw-r--r--fs/xfs/xfs_dquot.c32
-rw-r--r--fs/xfs/xfs_export.c12
-rw-r--r--fs/xfs/xfs_file.c168
-rw-r--r--fs/xfs/xfs_filestream.c4
-rw-r--r--fs/xfs/xfs_fsops.c60
-rw-r--r--fs/xfs/xfs_ialloc.c15
-rw-r--r--fs/xfs/xfs_iget.c2
-rw-r--r--fs/xfs/xfs_inode.c43
-rw-r--r--fs/xfs/xfs_inode.h1
-rw-r--r--fs/xfs/xfs_inode_item.c4
-rw-r--r--fs/xfs/xfs_ioctl.c2
-rw-r--r--fs/xfs/xfs_iomap.c39
-rw-r--r--fs/xfs/xfs_iops.c55
-rw-r--r--fs/xfs/xfs_log.c20
-rw-r--r--fs/xfs/xfs_log_recover.c43
-rw-r--r--fs/xfs/xfs_message.h42
-rw-r--r--fs/xfs/xfs_mount.c36
-rw-r--r--fs/xfs/xfs_qm.c12
-rw-r--r--fs/xfs/xfs_qm_syscalls.c2
-rw-r--r--fs/xfs/xfs_rename.c8
-rw-r--r--fs/xfs/xfs_rtalloc.c48
-rw-r--r--fs/xfs/xfs_rw.c23
-rw-r--r--fs/xfs/xfs_rw.h2
-rw-r--r--fs/xfs/xfs_super.c13
-rw-r--r--fs/xfs/xfs_sync.c16
-rw-r--r--fs/xfs/xfs_trace.h39
-rw-r--r--fs/xfs/xfs_trans.c13
-rw-r--r--fs/xfs/xfs_trans.h8
-rw-r--r--fs/xfs/xfs_trans_ail.c43
-rw-r--r--fs/xfs/xfs_trans_buf.c24
-rw-r--r--fs/xfs/xfs_trans_inode.c25
-rw-r--r--fs/xfs/xfs_trans_priv.h1
-rw-r--r--fs/xfs/xfs_vnodeops.c109
-rw-r--r--include/acpi/acpiosxf.h2
-rw-r--r--include/asm-generic/bug.h11
-rw-r--r--include/asm-generic/checksum.h4
-rw-r--r--include/asm-generic/cputime.h4
-rw-r--r--include/asm-generic/dma-mapping-common.h14
-rw-r--r--include/asm-generic/fcntl.h5
-rw-r--r--include/asm-generic/gpio.h17
-rw-r--r--include/asm-generic/page.h4
-rw-r--r--include/asm-generic/rwsem.h132
-rw-r--r--include/asm-generic/vmlinux.lds.h1
-rw-r--r--include/crypto/algapi.h2
-rw-r--r--include/crypto/blowfish.h23
-rw-r--r--include/crypto/sha.h5
-rw-r--r--include/drm/drmP.h13
-rw-r--r--include/drm/drm_crtc.h9
-rw-r--r--include/drm/drm_dp_helper.h61
-rw-r--r--include/drm/drm_edid.h9
-rw-r--r--include/drm/exynos_drm.h104
-rw-r--r--include/drm/intel-gtt.h2
-rw-r--r--include/drm/vmwgfx_drm.h358
-rw-r--r--include/linux/aio.h1
-rw-r--r--include/linux/alarmtimer.h51
-rw-r--r--include/linux/amba/pl061.h3
-rw-r--r--include/linux/atalk.h3
-rw-r--r--include/linux/atmel-mci.h4
-rw-r--r--include/linux/atmel_pdc.h2
-rw-r--r--include/linux/audit.h11
-rw-r--r--include/linux/ax25.h2
-rw-r--r--include/linux/bcma/bcma.h9
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h94
-rw-r--r--include/linux/bcma/bcma_driver_mips.h51
-rw-r--r--include/linux/bcma/bcma_soc.h16
-rw-r--r--include/linux/blktrace_api.h2
-rw-r--r--include/linux/bma150.h46
-rw-r--r--include/linux/caif/caif_socket.h7
-rw-r--r--include/linux/can.h4
-rw-r--r--include/linux/can/Kbuild1
-rw-r--r--include/linux/can/bcm.h3
-rw-r--r--include/linux/can/core.h2
-rw-r--r--include/linux/can/dev.h1
-rw-r--r--include/linux/can/error.h2
-rw-r--r--include/linux/can/gw.h162
-rw-r--r--include/linux/can/netlink.h2
-rw-r--r--include/linux/can/raw.h2
-rw-r--r--include/linux/capability.h3
-rw-r--r--include/linux/ceph/libceph.h4
-rw-r--r--include/linux/ceph/messenger.h4
-rw-r--r--include/linux/cgroup.h2
-rw-r--r--include/linux/clk.h43
-rw-r--r--include/linux/clkdev.h7
-rw-r--r--include/linux/clksrc-dbx500-prcmu.h20
-rw-r--r--include/linux/clockchips.h12
-rw-r--r--include/linux/cn_proc.h11
-rw-r--r--include/linux/compaction.h8
-rw-r--r--include/linux/compat.h3
-rw-r--r--include/linux/cpu_pm.h109
-rw-r--r--include/linux/crash_dump.h1
-rw-r--r--include/linux/crypto.h5
-rw-r--r--include/linux/cryptouser.h102
-rw-r--r--include/linux/dcache.h8
-rw-r--r--include/linux/devfreq.h238
-rw-r--r--include/linux/device-mapper.h45
-rw-r--r--include/linux/device.h126
-rw-r--r--include/linux/dm-ioctl.h4
-rw-r--r--include/linux/dm-kcopyd.h4
-rw-r--r--include/linux/dm-log-userspace.h18
-rw-r--r--include/linux/dma-mapping.h10
-rw-r--r--include/linux/dma_remapping.h10
-rw-r--r--include/linux/dmar.h45
-rw-r--r--include/linux/drbd_tag_magic.h2
-rw-r--r--include/linux/dvb/frontend.h1
-rw-r--r--include/linux/dvb/version.h2
-rw-r--r--include/linux/dw_apb_timer.h2
-rw-r--r--include/linux/dynamic_debug.h81
-rw-r--r--include/linux/edac.h350
-rw-r--r--include/linux/edac_mce.h31
-rw-r--r--include/linux/elf.h1
-rw-r--r--include/linux/ethtool.h180
-rw-r--r--include/linux/evm.h100
-rw-r--r--include/linux/ext2_fs.h4
-rw-r--r--include/linux/ext3_fs.h22
-rw-r--r--include/linux/ext3_fs_sb.h4
-rw-r--r--include/linux/filter.h2
-rw-r--r--include/linux/freezer.h26
-rw-r--r--include/linux/fs.h88
-rw-r--r--include/linux/fscache-cache.h8
-rw-r--r--include/linux/fsl-diu-fb.h92
-rw-r--r--include/linux/gameport.h8
-rw-r--r--include/linux/genhd.h4
-rw-r--r--include/linux/gpio.h22
-rw-r--r--include/linux/hid.h3
-rw-r--r--include/linux/huge_mm.h5
-rw-r--r--include/linux/hwspinlock.h46
-rw-r--r--include/linux/hyperv.h (renamed from drivers/staging/hv/hyperv.h)181
-rw-r--r--include/linux/i2c-omap.h5
-rw-r--r--include/linux/i2c.h17
-rw-r--r--include/linux/i2c/tsc2007.h2
-rw-r--r--include/linux/ieee80211.h156
-rw-r--r--include/linux/if.h1
-rw-r--r--include/linux/if_ether.h2
-rw-r--r--include/linux/if_link.h10
-rw-r--r--include/linux/if_macvlan.h1
-rw-r--r--include/linux/if_packet.h119
-rw-r--r--include/linux/if_pppol2tp.h2
-rw-r--r--include/linux/if_pppox.h9
-rw-r--r--include/linux/if_vlan.h6
-rw-r--r--include/linux/ima.h13
-rw-r--r--include/linux/in.h2
-rw-r--r--include/linux/inet_diag.h3
-rw-r--r--include/linux/init_task.h2
-rw-r--r--include/linux/input.h4
-rw-r--r--include/linux/input/adp5589.h157
-rw-r--r--include/linux/input/adxl34x.h21
-rw-r--r--include/linux/integrity.h39
-rw-r--r--include/linux/intel-iommu.h10
-rw-r--r--include/linux/interrupt.h41
-rw-r--r--include/linux/io-mapping.h6
-rw-r--r--include/linux/iommu.h76
-rw-r--r--include/linux/ip6_tunnel.h2
-rw-r--r--include/linux/ipx.h2
-rw-r--r--include/linux/irda.h9
-rw-r--r--include/linux/irq.h18
-rw-r--r--include/linux/irq_work.h15
-rw-r--r--include/linux/irqdesc.h1
-rw-r--r--include/linux/irqdomain.h16
-rw-r--r--include/linux/isdn.h2
-rw-r--r--include/linux/jbd.h64
-rw-r--r--include/linux/jbd2.h69
-rw-r--r--include/linux/jbd_common.h68
-rw-r--r--include/linux/jiffies.h2
-rw-r--r--include/linux/kallsyms.h5
-rw-r--r--include/linux/kdb.h9
-rw-r--r--include/linux/kernel.h57
-rw-r--r--include/linux/kexec.h14
-rw-r--r--include/linux/kmod.h4
-rw-r--r--include/linux/kobject.h26
-rw-r--r--include/linux/kprobes.h2
-rw-r--r--include/linux/kthread.h4
-rw-r--r--include/linux/kvm.h6
-rw-r--r--include/linux/kvm_host.h32
-rw-r--r--include/linux/l2tp.h7
-rw-r--r--include/linux/lapb.h3
-rw-r--r--include/linux/libata.h20
-rw-r--r--include/linux/lis3lv02d.h1
-rw-r--r--include/linux/llc.h10
-rw-r--r--include/linux/llist.h77
-rw-r--r--include/linux/lockdep.h2
-rw-r--r--include/linux/magic.h10
-rw-r--r--include/linux/memblock.h1
-rw-r--r--include/linux/memcontrol.h47
-rw-r--r--include/linux/mfd/tps6586x.h16
-rw-r--r--include/linux/mfd/twl6040.h46
-rw-r--r--include/linux/mfd/wm831x/core.h9
-rw-r--r--include/linux/mfd/wm8400-private.h7
-rw-r--r--include/linux/mfd/wm8994/core.h10
-rw-r--r--include/linux/mfd/wm8994/registers.h88
-rw-r--r--include/linux/mii.h210
-rw-r--r--include/linux/mlx4/device.h17
-rw-r--r--include/linux/mlx4/qp.h3
-rw-r--r--include/linux/mm.h70
-rw-r--r--include/linux/mm_types.h60
-rw-r--r--include/linux/mmc/card.h58
-rw-r--r--include/linux/mmc/core.h9
-rw-r--r--include/linux/mmc/dw_mmc.h4
-rw-r--r--include/linux/mmc/host.h29
-rw-r--r--include/linux/mmc/mmc.h38
-rw-r--r--include/linux/mmc/sdhci.h8
-rw-r--r--include/linux/mmc/sdio.h2
-rw-r--r--include/linux/mmc/sh_mmcif.h4
-rw-r--r--include/linux/mmc/sh_mobile_sdhi.h4
-rw-r--r--include/linux/mmiotrace.h8
-rw-r--r--include/linux/mmzone.h13
-rw-r--r--include/linux/mod_devicetable.h9
-rw-r--r--include/linux/module.h12
-rw-r--r--include/linux/moduleparam.h20
-rw-r--r--include/linux/namei.h1
-rw-r--r--include/linux/net_tstamp.h13
-rw-r--r--include/linux/netdevice.h64
-rw-r--r--include/linux/netfilter/xt_connlimit.h1
-rw-r--r--include/linux/netfilter/xt_conntrack.h1
-rw-r--r--include/linux/netfilter/xt_iprange.h1
-rw-r--r--include/linux/netfilter_arp/arp_tables.h14
-rw-r--r--include/linux/netfilter_decnet.h3
-rw-r--r--include/linux/netfilter_ipv4.h3
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h20
-rw-r--r--include/linux/netfilter_ipv6.h3
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h22
-rw-r--r--include/linux/netlink.h3
-rw-r--r--include/linux/netrom.h2
-rw-r--r--include/linux/nfc.h8
-rw-r--r--include/linux/nfs4.h21
-rw-r--r--include/linux/nfs_fs.h1
-rw-r--r--include/linux/nfs_page.h1
-rw-r--r--include/linux/nfs_xdr.h5
-rw-r--r--include/linux/nfsd/Kbuild2
-rw-r--r--include/linux/nfsd/const.h55
-rw-r--r--include/linux/nfsd/export.h2
-rw-r--r--include/linux/nfsd/nfsfh.h7
-rw-r--r--include/linux/nfsd/syscall.h116
-rw-r--r--include/linux/nl80211.h238
-rw-r--r--include/linux/of.h60
-rw-r--r--include/linux/of_irq.h3
-rw-r--r--include/linux/omap3isp.h2
-rw-r--r--include/linux/oom.h1
-rw-r--r--include/linux/opp.h12
-rw-r--r--include/linux/oprofile.h2
-rw-r--r--include/linux/pci-ats.h75
-rw-r--r--include/linux/pci.h4
-rw-r--r--include/linux/pci_ids.h5
-rw-r--r--include/linux/pci_regs.h20
-rw-r--r--include/linux/percpu_counter.h2
-rw-r--r--include/linux/perf_event.h5
-rw-r--r--include/linux/phonet.h5
-rw-r--r--include/linux/phy.h2
-rw-r--r--include/linux/pinctrl/machine.h107
-rw-r--r--include/linux/pinctrl/pinctrl.h133
-rw-r--r--include/linux/pinctrl/pinmux.h117
-rw-r--r--include/linux/platform_data/dwc3-omap.h47
-rw-r--r--include/linux/platform_data/exynos4_tmu.h83
-rw-r--r--include/linux/platform_data/leds-renesas-tpu.h14
-rw-r--r--include/linux/platform_data/mv_usb.h50
-rw-r--r--include/linux/platform_data/ntc_thermistor.h2
-rw-r--r--include/linux/platform_device.h65
-rw-r--r--include/linux/pm.h26
-rw-r--r--include/linux/pm_clock.h71
-rw-r--r--include/linux/pm_domain.h26
-rw-r--r--include/linux/pm_qos.h155
-rw-r--r--include/linux/pm_qos_params.h38
-rw-r--r--include/linux/pm_runtime.h42
-rw-r--r--include/linux/posix-timers.h5
-rw-r--r--include/linux/pps-gpio.h32
-rw-r--r--include/linux/printk.h12
-rw-r--r--include/linux/proportions.h6
-rw-r--r--include/linux/pstore.h6
-rw-r--r--include/linux/quotaops.h2
-rw-r--r--include/linux/random.h13
-rw-r--r--include/linux/ratelimit.h6
-rw-r--r--include/linux/rcupdate.h300
-rw-r--r--include/linux/rcutiny.h20
-rw-r--r--include/linux/rcutree.h2
-rw-r--r--include/linux/regmap.h79
-rw-r--r--include/linux/regulator/consumer.h7
-rw-r--r--include/linux/regulator/driver.h3
-rw-r--r--include/linux/regulator/gpio-regulator.h87
-rw-r--r--include/linux/regulator/machine.h2
-rw-r--r--include/linux/rfkill-gpio.h4
-rw-r--r--include/linux/ring_buffer.h2
-rw-r--r--include/linux/rio_ids.h1
-rw-r--r--include/linux/rose.h7
-rw-r--r--include/linux/rtc/sirfsoc_rtciobrg.h18
-rw-r--r--include/linux/rwsem-spinlock.h2
-rw-r--r--include/linux/rwsem.h10
-rw-r--r--include/linux/sched.h18
-rw-r--r--include/linux/security.h32
-rw-r--r--include/linux/sem.h49
-rw-r--r--include/linux/semaphore.h4
-rw-r--r--include/linux/seq_file.h3
-rw-r--r--include/linux/serial.h1
-rw-r--r--include/linux/serial_8250.h2
-rw-r--r--include/linux/serial_core.h10
-rw-r--r--include/linux/serial_reg.h1
-rw-r--r--include/linux/serio.h1
-rw-r--r--include/linux/sh_eth.h (renamed from arch/sh/include/asm/sh_eth.h)2
-rw-r--r--include/linux/sh_pfc.h12
-rw-r--r--include/linux/shrinker.h1
-rw-r--r--include/linux/skbuff.h262
-rw-r--r--include/linux/slub_def.h4
-rw-r--r--include/linux/spi/l4f00242t03.h2
-rw-r--r--include/linux/ssb/ssb.h2
-rw-r--r--include/linux/ssb/ssb_regs.h40
-rw-r--r--include/linux/string.h1
-rw-r--r--include/linux/sungem_phy.h (renamed from drivers/net/sungem_phy.h)2
-rw-r--r--include/linux/sunrpc/clnt.h11
-rw-r--r--include/linux/sunrpc/rpc_pipe_fs.h2
-rw-r--r--include/linux/sunrpc/svc.h32
-rw-r--r--include/linux/suspend.h95
-rw-r--r--include/linux/swap.h7
-rw-r--r--include/linux/syscalls.h13
-rw-r--r--include/linux/sysctl.h24
-rw-r--r--include/linux/sysfs.h1
-rw-r--r--include/linux/tcp.h7
-rw-r--r--include/linux/tipc_config.h4
-rw-r--r--include/linux/trace_clock.h1
-rw-r--r--include/linux/trace_seq.h8
-rw-r--r--include/linux/tracepoint.h25
-rw-r--r--include/linux/tty.h26
-rw-r--r--include/linux/types.h10
-rw-r--r--include/linux/uinput.h2
-rw-r--r--include/linux/uio_driver.h7
-rw-r--r--include/linux/un.h4
-rw-r--r--include/linux/usb.h20
-rw-r--r--include/linux/usb/Kbuild1
-rw-r--r--include/linux/usb/ch9.h46
-rw-r--r--include/linux/usb/gadget.h4
-rw-r--r--include/linux/usb/hcd.h3
-rw-r--r--include/linux/usb/r8a66597.h60
-rw-r--r--include/linux/usb/renesas_usbhs.h14
-rw-r--r--include/linux/utsname.h16
-rw-r--r--include/linux/videodev2.h92
-rw-r--r--include/linux/virtio.h9
-rw-r--r--include/linux/virtio_config.h3
-rw-r--r--include/linux/virtio_mmio.h111
-rw-r--r--include/linux/virtio_ring.h6
-rw-r--r--include/linux/vmalloc.h1
-rw-r--r--include/linux/x25.h3
-rw-r--r--include/linux/xattr.h19
-rw-r--r--include/media/m5mols.h4
-rw-r--r--include/media/mt9p031.h19
-rw-r--r--include/media/mt9t001.h8
-rw-r--r--include/media/omap3isp.h140
-rw-r--r--include/media/pwc-ioctl.h1
-rw-r--r--include/media/rc-core.h7
-rw-r--r--include/media/rc-map.h3
-rw-r--r--include/media/s5p_fimc.h18
-rw-r--r--include/media/saa7146.h36
-rw-r--r--include/media/v4l2-chip-ident.h3
-rw-r--r--include/media/v4l2-ctrls.h15
-rw-r--r--include/media/v4l2-mediabus.h12
-rw-r--r--include/media/videobuf-dma-sg.h2
-rw-r--r--include/media/videobuf2-core.h23
-rw-r--r--include/media/videobuf2-dma-contig.h6
-rw-r--r--include/misc/altera.h (renamed from drivers/staging/altera-stapl/altera.h)0
-rw-r--r--include/net/9p/9p.h14
-rw-r--r--include/net/9p/client.h8
-rw-r--r--include/net/9p/transport.h10
-rw-r--r--include/net/addrconf.h2
-rw-r--r--include/net/bluetooth/bluetooth.h2
-rw-r--r--include/net/bluetooth/hci.h10
-rw-r--r--include/net/bluetooth/hci_core.h25
-rw-r--r--include/net/bluetooth/l2cap.h11
-rw-r--r--include/net/bluetooth/mgmt.h16
-rw-r--r--include/net/bluetooth/smp.h17
-rw-r--r--include/net/caif/caif_hsi.h37
-rw-r--r--include/net/cfg80211-wext.h55
-rw-r--r--include/net/cfg80211.h385
-rw-r--r--include/net/dcbevent.h18
-rw-r--r--include/net/dcbnl.h3
-rw-r--r--include/net/dst.h9
-rw-r--r--include/net/ieee80211_radiotap.h1
-rw-r--r--include/net/if_inet6.h1
-rw-r--r--include/net/inet_ecn.h8
-rw-r--r--include/net/inet_timewait_sock.h4
-rw-r--r--include/net/ip.h12
-rw-r--r--include/net/ipv6.h3
-rw-r--r--include/net/iucv/af_iucv.h52
-rw-r--r--include/net/iucv/iucv.h36
-rw-r--r--include/net/lapb.h2
-rw-r--r--include/net/lib80211.h3
-rw-r--r--include/net/mac80211.h294
-rw-r--r--include/net/netfilter/nf_log.h3
-rw-r--r--include/net/nfc/nci.h313
-rw-r--r--include/net/nfc/nci_core.h184
-rw-r--r--include/net/nfc/nfc.h (renamed from include/net/nfc.h)11
-rw-r--r--include/net/regulatory.h16
-rw-r--r--include/net/sch_generic.h24
-rw-r--r--include/net/scm.h5
-rw-r--r--include/net/sctp/structs.h1
-rw-r--r--include/net/secure_seq.h2
-rw-r--r--include/net/sock.h19
-rw-r--r--include/net/tcp.h71
-rw-r--r--include/rdma/ib_addr.h6
-rw-r--r--include/rdma/ib_user_verbs.h48
-rw-r--r--include/rdma/ib_verbs.h106
-rw-r--r--include/rdma/iw_cm.h4
-rw-r--r--include/rdma/rdma_cm.h1
-rw-r--r--include/rdma/rdma_user_cm.h3
-rw-r--r--include/scsi/iscsi_if.h135
-rw-r--r--include/scsi/libfc.h76
-rw-r--r--include/scsi/libfcoe.h5
-rw-r--r--include/scsi/libsas.h54
-rw-r--r--include/scsi/osd_ore.h80
-rw-r--r--include/scsi/sas.h24
-rw-r--r--include/scsi/scsi_bsg_iscsi.h110
-rw-r--r--include/scsi/scsi_device.h6
-rw-r--r--include/scsi/scsi_host.h16
-rw-r--r--include/scsi/scsi_transport_iscsi.h47
-rw-r--r--include/sound/adau1373.h34
-rw-r--r--include/sound/asound.h4
-rw-r--r--include/sound/core.h4
-rw-r--r--include/sound/info.h4
-rw-r--r--include/sound/initval.h2
-rw-r--r--include/sound/jack.h1
-rw-r--r--include/sound/mpu401.h7
-rw-r--r--include/sound/pcm.h8
-rw-r--r--include/sound/saif.h16
-rw-r--r--include/sound/seq_kernel.h4
-rw-r--r--include/sound/soc-dai.h37
-rw-r--r--include/sound/soc-dapm.h16
-rw-r--r--include/sound/soc.h107
-rw-r--r--include/sound/tpa6130a2-plat.h6
-rw-r--r--include/sound/wm1250-ev1.h27
-rw-r--r--include/sound/wm5100.h59
-rw-r--r--include/target/configfs_macros.h4
-rw-r--r--include/target/target_core_base.h71
-rw-r--r--include/target/target_core_tmr.h2
-rw-r--r--include/target/target_core_transport.h75
-rw-r--r--include/trace/events/9p.h176
-rw-r--r--include/trace/events/asoc.h25
-rw-r--r--include/trace/events/ext4.h480
-rw-r--r--include/trace/events/rcu.h459
-rw-r--r--include/trace/events/regmap.h136
-rw-r--r--include/trace/events/rpm.h99
-rw-r--r--include/trace/events/sched.h9
-rw-r--r--include/trace/events/vmscan.h8
-rw-r--r--include/trace/ftrace.h3
-rw-r--r--include/video/omap-panel-dvi.h37
-rw-r--r--include/video/omap-panel-n8x0.h15
-rw-r--r--include/video/omap-panel-nokia-dsi.h8
-rw-r--r--include/video/omap-panel-picodlp.h23
-rw-r--r--include/video/omapdss.h100
-rw-r--r--include/video/sh_mobile_lcdc.h135
-rw-r--r--include/video/udlfb.h1
-rw-r--r--include/xen/balloon.h5
-rw-r--r--include/xen/grant_table.h1
-rw-r--r--include/xen/hvc-console.h4
-rw-r--r--include/xen/interface/io/xs_wire.h6
-rw-r--r--include/xen/interface/physdev.h34
-rw-r--r--include/xen/page.h12
-rw-r--r--include/xen/xenbus.h12
-rw-r--r--init/Kconfig22
-rw-r--r--init/do_mounts.c48
-rw-r--r--init/do_mounts_rd.c14
-rw-r--r--init/main.c4
-rw-r--r--ipc/mqueue.c4
-rw-r--r--ipc/sem.c56
-rw-r--r--kernel/Makefile3
-rw-r--r--kernel/async.c4
-rw-r--r--kernel/cgroup.c57
-rw-r--r--kernel/cpu_pm.c233
-rw-r--r--kernel/cpuset.c9
-rw-r--r--kernel/crash_dump.c11
-rw-r--r--kernel/cred.c18
-rw-r--r--kernel/debug/gdbstub.c12
-rw-r--r--kernel/events/core.c10
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/fork.c10
-rw-r--r--kernel/freezer.c2
-rw-r--r--kernel/futex.c10
-rw-r--r--kernel/irq/chip.c64
-rw-r--r--kernel/irq/generic-chip.c4
-rw-r--r--kernel/irq/internals.h19
-rw-r--r--kernel/irq/irqdesc.c32
-rw-r--r--kernel/irq/irqdomain.c12
-rw-r--r--kernel/irq/manage.c218
-rw-r--r--kernel/irq/pm.c48
-rw-r--r--kernel/irq/settings.h7
-rw-r--r--kernel/irq_work.c91
-rw-r--r--kernel/kexec.c41
-rw-r--r--kernel/kmod.c4
-rw-r--r--kernel/kprobes.c34
-rw-r--r--kernel/latencytop.c14
-rw-r--r--kernel/lockdep.c240
-rw-r--r--kernel/module.c47
-rw-r--r--kernel/params.c21
-rw-r--r--kernel/pid.c4
-rw-r--r--kernel/posix-cpu-timers.c14
-rw-r--r--kernel/power/Kconfig8
-rw-r--r--kernel/power/Makefile4
-rw-r--r--kernel/power/console.c4
-rw-r--r--kernel/power/hibernate.c53
-rw-r--r--kernel/power/main.c102
-rw-r--r--kernel/power/power.h4
-rw-r--r--kernel/power/process.c30
-rw-r--r--kernel/power/qos.c (renamed from kernel/pm_qos_params.c)273
-rw-r--r--kernel/power/snapshot.c18
-rw-r--r--kernel/power/suspend.c17
-rw-r--r--kernel/power/swap.c818
-rw-r--r--kernel/printk.c56
-rw-r--r--kernel/rcu.h85
-rw-r--r--kernel/rcupdate.c26
-rw-r--r--kernel/rcutiny.c117
-rw-r--r--kernel/rcutiny_plugin.h134
-rw-r--r--kernel/rcutorture.c77
-rw-r--r--kernel/rcutree.c290
-rw-r--r--kernel/rcutree.h17
-rw-r--r--kernel/rcutree_plugin.h150
-rw-r--r--kernel/rcutree_trace.c13
-rw-r--r--kernel/rtmutex-debug.c77
-rw-r--r--kernel/rtmutex.c8
-rw-r--r--kernel/sched.c681
-rw-r--r--kernel/sched_cpupri.c89
-rw-r--r--kernel/sched_cpupri.h7
-rw-r--r--kernel/sched_fair.c761
-rw-r--r--kernel/sched_features.h5
-rw-r--r--kernel/sched_rt.c99
-rw-r--r--kernel/sched_stats.h12
-rw-r--r--kernel/sched_stoptask.c2
-rw-r--r--kernel/semaphore.c28
-rw-r--r--kernel/signal.c24
-rw-r--r--kernel/stop_machine.c22
-rw-r--r--kernel/sys.c3
-rw-r--r--kernel/sys_ni.c4
-rw-r--r--kernel/sysctl.c27
-rw-r--r--kernel/sysctl_binary.c2
-rw-r--r--kernel/time.c2
-rw-r--r--kernel/time/Kconfig2
-rw-r--r--kernel/time/alarmtimer.c266
-rw-r--r--kernel/time/clockevents.c129
-rw-r--r--kernel/time/clocksource.c38
-rw-r--r--kernel/time/tick-broadcast.c4
-rw-r--r--kernel/time/tick-common.c4
-rw-r--r--kernel/time/tick-internal.h2
-rw-r--r--kernel/time/tick-oneshot.c77
-rw-r--r--kernel/time/tick-sched.c61
-rw-r--r--kernel/time/timer_stats.c6
-rw-r--r--kernel/trace/Makefile5
-rw-r--r--kernel/trace/ftrace.c8
-rw-r--r--kernel/trace/ring_buffer.c122
-rw-r--r--kernel/trace/rpm-traces.c20
-rw-r--r--kernel/trace/trace.c191
-rw-r--r--kernel/trace/trace.h16
-rw-r--r--kernel/trace/trace_clock.c12
-rw-r--r--kernel/trace/trace_events_filter.c795
-rw-r--r--kernel/trace/trace_events_filter_test.h50
-rw-r--r--kernel/trace/trace_irqsoff.c10
-rw-r--r--kernel/trace/trace_kprobe.c58
-rw-r--r--kernel/trace/trace_printk.c19
-rw-r--r--kernel/tracepoint.c169
-rw-r--r--kernel/utsname_sysctl.c23
-rw-r--r--kernel/watchdog.c11
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Kconfig.debug60
-rw-r--r--lib/Makefile4
-rw-r--r--lib/atomic64.c66
-rw-r--r--lib/bitmap.c10
-rw-r--r--lib/dma-debug.c68
-rw-r--r--lib/dynamic_debug.c174
-rw-r--r--lib/fault-inject.c5
-rw-r--r--lib/hexdump.c15
-rw-r--r--lib/idr.c17
-rw-r--r--lib/kobject_uevent.c2
-rw-r--r--lib/kstrtox.c75
-rw-r--r--lib/kstrtox.h8
-rw-r--r--lib/llist.c74
-rw-r--r--lib/percpu_counter.c20
-rw-r--r--lib/proportions.c12
-rw-r--r--lib/radix-tree.c10
-rw-r--r--lib/raid6/int.uc2
-rw-r--r--lib/ratelimit.c4
-rw-r--r--lib/rwsem-spinlock.c38
-rw-r--r--lib/rwsem.c14
-rw-r--r--lib/smp_processor_id.c2
-rw-r--r--lib/spinlock_debug.c19
-rw-r--r--lib/string.c57
-rw-r--r--lib/vsprintf.c47
-rw-r--r--mm/Kconfig3
-rw-r--r--mm/Makefile3
-rw-r--r--mm/backing-dev.c5
-rw-r--r--mm/compaction.c26
-rw-r--r--mm/debug-pagealloc.c56
-rw-r--r--mm/filemap.c3
-rw-r--r--mm/highmem.c2
-rw-r--r--mm/huge_memory.c91
-rw-r--r--mm/internal.h46
-rw-r--r--mm/ksm.c3
-rw-r--r--mm/memblock.c11
-rw-r--r--mm/memcontrol.c1009
-rw-r--r--mm/memory-failure.c12
-rw-r--r--mm/memory.c2
-rw-r--r--mm/mempolicy.c2
-rw-r--r--mm/migrate.c75
-rw-r--r--mm/mlock.c13
-rw-r--r--mm/mmap.c9
-rw-r--r--mm/mremap.c42
-rw-r--r--mm/oom_kill.c53
-rw-r--r--mm/page-writeback.c4
-rw-r--r--mm/page_alloc.c17
-rw-r--r--mm/page_cgroup.c12
-rw-r--r--mm/process_vm_access.c496
-rw-r--r--mm/rmap.c2
-rw-r--r--mm/shmem.c12
-rw-r--r--mm/slab.c19
-rw-r--r--mm/slub.c605
-rw-r--r--mm/swap.c83
-rw-r--r--mm/swapfile.c2
-rw-r--r--mm/thrash.c2
-rw-r--r--mm/vmalloc.c80
-rw-r--r--mm/vmscan.c331
-rw-r--r--mm/vmstat.c3
-rw-r--r--net/802/garp.c4
-rw-r--r--net/802/stp.c4
-rw-r--r--net/8021q/vlan.c2
-rw-r--r--net/8021q/vlan_core.c7
-rw-r--r--net/8021q/vlan_dev.c4
-rw-r--r--net/9p/client.c469
-rw-r--r--net/9p/protocol.c99
-rw-r--r--net/9p/protocol.h4
-rw-r--r--net/9p/trans_common.c53
-rw-r--r--net/9p/trans_common.h21
-rw-r--r--net/9p/trans_virtio.c319
-rw-r--r--net/appletalk/ddp.c5
-rw-r--r--net/atm/lec.c2
-rw-r--r--net/batman-adv/Makefile2
-rw-r--r--net/batman-adv/aggregation.c293
-rw-r--r--net/batman-adv/aggregation.h46
-rw-r--r--net/batman-adv/bat_iv_ogm.c1170
-rw-r--r--net/batman-adv/bat_ogm.h35
-rw-r--r--net/batman-adv/bat_sysfs.c2
-rw-r--r--net/batman-adv/bitarray.c6
-rw-r--r--net/batman-adv/gateway_client.c10
-rw-r--r--net/batman-adv/hard-interface.c88
-rw-r--r--net/batman-adv/hard-interface.h1
-rw-r--r--net/batman-adv/hash.h25
-rw-r--r--net/batman-adv/main.c4
-rw-r--r--net/batman-adv/main.h8
-rw-r--r--net/batman-adv/originator.c21
-rw-r--r--net/batman-adv/packet.h19
-rw-r--r--net/batman-adv/routing.c669
-rw-r--r--net/batman-adv/routing.h17
-rw-r--r--net/batman-adv/send.c313
-rw-r--r--net/batman-adv/send.h9
-rw-r--r--net/batman-adv/soft-interface.c36
-rw-r--r--net/batman-adv/translation-table.c223
-rw-r--r--net/batman-adv/translation-table.h21
-rw-r--r--net/batman-adv/types.h9
-rw-r--r--net/batman-adv/unicast.c6
-rw-r--r--net/batman-adv/unicast.h2
-rw-r--r--net/batman-adv/vis.c10
-rw-r--r--net/bluetooth/af_bluetooth.c30
-rw-r--r--net/bluetooth/bnep/core.c5
-rw-r--r--net/bluetooth/bnep/netdev.c2
-rw-r--r--net/bluetooth/cmtp/core.c5
-rw-r--r--net/bluetooth/hci_conn.c16
-rw-r--r--net/bluetooth/hci_core.c57
-rw-r--r--net/bluetooth/hci_event.c36
-rw-r--r--net/bluetooth/hci_sock.c18
-rw-r--r--net/bluetooth/hci_sysfs.c2
-rw-r--r--net/bluetooth/hidp/core.c13
-rw-r--r--net/bluetooth/l2cap_core.c273
-rw-r--r--net/bluetooth/mgmt.c212
-rw-r--r--net/bluetooth/rfcomm/core.c5
-rw-r--r--net/bluetooth/smp.c421
-rw-r--r--net/bridge/br_device.c4
-rw-r--r--net/bridge/br_fdb.c23
-rw-r--r--net/bridge/br_if.c41
-rw-r--r--net/bridge/br_input.c33
-rw-r--r--net/bridge/br_private.h7
-rw-r--r--net/bridge/br_sysfs_br.c34
-rw-r--r--net/bridge/netfilter/ebtable_broute.c4
-rw-r--r--net/caif/caif_dev.c5
-rw-r--r--net/caif/cfcnfg.c38
-rw-r--r--net/caif/cfctrl.c23
-rw-r--r--net/caif/cfdbgl.c7
-rw-r--r--net/caif/cfdgml.c7
-rw-r--r--net/caif/cffrml.c7
-rw-r--r--net/caif/cfmuxl.c6
-rw-r--r--net/caif/cfrfml.c7
-rw-r--r--net/caif/cfserl.c7
-rw-r--r--net/caif/cfsrvl.c8
-rw-r--r--net/caif/cfutill.c7
-rw-r--r--net/caif/cfveil.c7
-rw-r--r--net/caif/cfvidl.c7
-rw-r--r--net/can/Kconfig11
-rw-r--r--net/can/Makefile3
-rw-r--r--net/can/af_can.c6
-rw-r--r--net/can/af_can.h2
-rw-r--r--net/can/bcm.c2
-rw-r--r--net/can/gw.c957
-rw-r--r--net/can/proc.c2
-rw-r--r--net/can/raw.c2
-rw-r--r--net/ceph/Kconfig14
-rw-r--r--net/ceph/ceph_common.c47
-rw-r--r--net/ceph/messenger.c130
-rw-r--r--net/ceph/mon_client.c79
-rw-r--r--net/ceph/msgpool.c4
-rw-r--r--net/ceph/osd_client.c34
-rw-r--r--net/core/datagram.c24
-rw-r--r--net/core/dev.c339
-rw-r--r--net/core/dev_addr_lists.c4
-rw-r--r--net/core/dst.c15
-rw-r--r--net/core/ethtool.c20
-rw-r--r--net/core/fib_rules.c4
-rw-r--r--net/core/filter.c4
-rw-r--r--net/core/flow.c14
-rw-r--r--net/core/kmap_skb.h2
-rw-r--r--net/core/link_watch.c9
-rw-r--r--net/core/neighbour.c44
-rw-r--r--net/core/net-sysfs.c12
-rw-r--r--net/core/netpoll.c4
-rw-r--r--net/core/pktgen.c25
-rw-r--r--net/core/rtnetlink.c34
-rw-r--r--net/core/scm.c10
-rw-r--r--net/core/secure_seq.c2
-rw-r--r--net/core/skbuff.c174
-rw-r--r--net/core/sock.c24
-rw-r--r--net/core/timestamping.c12
-rw-r--r--net/core/user_dma.c6
-rw-r--r--net/dcb/dcbnl.c30
-rw-r--r--net/dccp/ccids/ccid2.c84
-rw-r--r--net/dccp/ccids/ccid2.h6
-rw-r--r--net/dccp/dccp.h1
-rw-r--r--net/dccp/feat.c202
-rw-r--r--net/dccp/feat.h1
-rw-r--r--net/dccp/ipv6.c4
-rw-r--r--net/dccp/proto.c1
-rw-r--r--net/decnet/dn_dev.c6
-rw-r--r--net/dsa/slave.c3
-rw-r--r--net/ieee802154/6lowpan.c891
-rw-r--r--net/ieee802154/6lowpan.h212
-rw-r--r--net/ieee802154/Kconfig6
-rw-r--r--net/ieee802154/Makefile8
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/cipso_ipv4.c2
-rw-r--r--net/ipv4/devinet.c6
-rw-r--r--net/ipv4/fib_trie.c12
-rw-r--r--net/ipv4/gre.c4
-rw-r--r--net/ipv4/icmp.c5
-rw-r--r--net/ipv4/igmp.c12
-rw-r--r--net/ipv4/inet_diag.c5
-rw-r--r--net/ipv4/inet_lro.c10
-rw-r--r--net/ipv4/inet_timewait_sock.c1
-rw-r--r--net/ipv4/ip_fragment.c40
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_output.c17
-rw-r--r--net/ipv4/ip_sockglue.c7
-rw-r--r--net/ipv4/ipip.c10
-rw-r--r--net/ipv4/ipmr.c8
-rw-r--r--net/ipv4/netfilter/nf_nat_amanda.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c24
-rw-r--r--net/ipv4/netfilter/nf_nat_ftp.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c36
-rw-r--r--net/ipv4/netfilter/nf_nat_irc.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c16
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c28
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c6
-rw-r--r--net/ipv4/netfilter/nf_nat_tftp.c4
-rw-r--r--net/ipv4/route.c53
-rw-r--r--net/ipv4/syncookies.c2
-rw-r--r--net/ipv4/tcp.c97
-rw-r--r--net/ipv4/tcp_input.c244
-rw-r--r--net/ipv4/tcp_ipv4.c57
-rw-r--r--net/ipv4/tcp_minisocks.c5
-rw-r--r--net/ipv4/tcp_output.c152
-rw-r--r--net/ipv4/tcp_timer.c2
-rw-r--r--net/ipv4/udp.c11
-rw-r--r--net/ipv4/xfrm4_policy.c14
-rw-r--r--net/ipv6/addrconf.c124
-rw-r--r--net/ipv6/datagram.c4
-rw-r--r--net/ipv6/exthdrs.c7
-rw-r--r--net/ipv6/icmp.c28
-rw-r--r--net/ipv6/inet6_connection_sock.c9
-rw-r--r--net/ipv6/ip6_fib.c4
-rw-r--r--net/ipv6/ip6_output.c37
-rw-r--r--net/ipv6/ip6_tunnel.c54
-rw-r--r--net/ipv6/ipv6_sockglue.c2
-rw-r--r--net/ipv6/ndisc.c42
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c4
-rw-r--r--net/ipv6/raw.c11
-rw-r--r--net/ipv6/reassembly.c4
-rw-r--r--net/ipv6/route.c3
-rw-r--r--net/ipv6/sit.c12
-rw-r--r--net/ipv6/syncookies.c6
-rw-r--r--net/ipv6/tcp_ipv6.c65
-rw-r--r--net/ipv6/udp.c4
-rw-r--r--net/ipv6/xfrm6_output.c56
-rw-r--r--net/irda/ircomm/ircomm_tty.c2
-rw-r--r--net/irda/irlan/irlan_eth.c2
-rw-r--r--net/iucv/Kconfig14
-rw-r--r--net/iucv/af_iucv.c870
-rw-r--r--net/iucv/iucv.c23
-rw-r--r--net/l2tp/l2tp_ppp.c9
-rw-r--r--net/lapb/lapb_iface.c29
-rw-r--r--net/mac80211/Kconfig25
-rw-r--r--net/mac80211/agg-rx.c25
-rw-r--r--net/mac80211/agg-tx.c64
-rw-r--r--net/mac80211/cfg.c497
-rw-r--r--net/mac80211/debugfs.c71
-rw-r--r--net/mac80211/debugfs_netdev.c59
-rw-r--r--net/mac80211/debugfs_sta.c37
-rw-r--r--net/mac80211/driver-ops.h91
-rw-r--r--net/mac80211/driver-trace.h117
-rw-r--r--net/mac80211/ht.c8
-rw-r--r--net/mac80211/ibss.c16
-rw-r--r--net/mac80211/ieee80211_i.h104
-rw-r--r--net/mac80211/iface.c26
-rw-r--r--net/mac80211/key.c4
-rw-r--r--net/mac80211/main.c27
-rw-r--r--net/mac80211/mesh.c213
-rw-r--r--net/mac80211/mesh.h38
-rw-r--r--net/mac80211/mesh_hwmp.c177
-rw-r--r--net/mac80211/mesh_pathtbl.c481
-rw-r--r--net/mac80211/mesh_plink.c257
-rw-r--r--net/mac80211/mlme.c140
-rw-r--r--net/mac80211/pm.c2
-rw-r--r--net/mac80211/rate.c37
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c13
-rw-r--r--net/mac80211/rx.c199
-rw-r--r--net/mac80211/scan.c6
-rw-r--r--net/mac80211/spectmgmt.c6
-rw-r--r--net/mac80211/sta_info.c977
-rw-r--r--net/mac80211/sta_info.h171
-rw-r--r--net/mac80211/status.c251
-rw-r--r--net/mac80211/tx.c557
-rw-r--r--net/mac80211/util.c280
-rw-r--r--net/mac80211/wme.c20
-rw-r--r--net/mac80211/wme.h3
-rw-r--r--net/mac80211/work.c10
-rw-r--r--net/mac80211/wpa.c3
-rw-r--r--net/netfilter/Kconfig2
-rw-r--r--net/netfilter/core.c4
-rw-r--r--net/netfilter/nf_conntrack_core.c12
-rw-r--r--net/netfilter/nf_conntrack_ecache.c8
-rw-r--r--net/netfilter/nf_conntrack_extend.c4
-rw-r--r--net/netfilter/nf_conntrack_helper.c6
-rw-r--r--net/netfilter/nf_conntrack_netlink.c6
-rw-r--r--net/netfilter/nf_log.c10
-rw-r--r--net/netfilter/nf_queue.c6
-rw-r--r--net/netfilter/nfnetlink.c6
-rw-r--r--net/netfilter/x_tables.c5
-rw-r--r--net/netlabel/netlabel_domainhash.c6
-rw-r--r--net/netlabel/netlabel_unlabeled.c6
-rw-r--r--net/netlink/af_netlink.c7
-rw-r--r--net/nfc/Kconfig2
-rw-r--r--net/nfc/Makefile1
-rw-r--r--net/nfc/core.c83
-rw-r--r--net/nfc/nci/Kconfig10
-rw-r--r--net/nfc/nci/Makefile7
-rw-r--r--net/nfc/nci/core.c797
-rw-r--r--net/nfc/nci/data.c247
-rw-r--r--net/nfc/nci/lib.c94
-rw-r--r--net/nfc/nci/ntf.c258
-rw-r--r--net/nfc/nci/rsp.c226
-rw-r--r--net/nfc/netlink.c56
-rw-r--r--net/nfc/nfc.h8
-rw-r--r--net/nfc/rawsock.c13
-rw-r--r--net/packet/af_packet.c987
-rw-r--r--net/phonet/af_phonet.c4
-rw-r--r--net/phonet/pn_dev.c6
-rw-r--r--net/phonet/socket.c6
-rw-r--r--net/rds/Kconfig1
-rw-r--r--net/rds/ib_cm.c6
-rw-r--r--net/rds/ib_rdma.c112
-rw-r--r--net/rds/rds.h8
-rw-r--r--net/rds/xlist.h80
-rw-r--r--net/rfkill/core.c2
-rw-r--r--net/rfkill/rfkill-gpio.c11
-rw-r--r--net/rfkill/rfkill-regulator.c1
-rw-r--r--net/sched/cls_flow.c188
-rw-r--r--net/sched/sch_sfb.c13
-rw-r--r--net/sctp/associola.c1
-rw-r--r--net/sctp/ipv6.c2
-rw-r--r--net/sctp/outqueue.c4
-rw-r--r--net/sctp/protocol.c2
-rw-r--r--net/sctp/sm_make_chunk.c1
-rw-r--r--net/sctp/sm_statefuns.c5
-rw-r--r--net/socket.c4
-rw-r--r--net/sunrpc/addr.c6
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c28
-rw-r--r--net/sunrpc/clnt.c4
-rw-r--r--net/sunrpc/rpc_pipe.c23
-rw-r--r--net/sunrpc/rpcb_clnt.c6
-rw-r--r--net/sunrpc/svc.c38
-rw-r--r--net/sunrpc/svc_xprt.c13
-rw-r--r--net/sunrpc/svcsock.c23
-rw-r--r--net/tipc/bcast.c111
-rw-r--r--net/tipc/bcast.h1
-rw-r--r--net/tipc/bearer.c8
-rw-r--r--net/tipc/bearer.h4
-rw-r--r--net/tipc/config.h1
-rw-r--r--net/tipc/discover.c6
-rw-r--r--net/tipc/eth_media.c32
-rw-r--r--net/tipc/link.c111
-rw-r--r--net/tipc/link.h1
-rw-r--r--net/tipc/name_distr.c35
-rw-r--r--net/tipc/net.c11
-rw-r--r--net/tipc/node.c45
-rw-r--r--net/tipc/node.h10
-rw-r--r--net/tipc/socket.c51
-rw-r--r--net/tipc/subscr.c3
-rw-r--r--net/tipc/subscr.h6
-rw-r--r--net/unix/af_unix.c24
-rw-r--r--net/wireless/core.c2
-rw-r--r--net/wireless/core.h6
-rw-r--r--net/wireless/lib80211.c15
-rw-r--r--net/wireless/lib80211_crypt_ccmp.c2
-rw-r--r--net/wireless/lib80211_crypt_tkip.c4
-rw-r--r--net/wireless/lib80211_crypt_wep.c4
-rw-r--r--net/wireless/mesh.c3
-rw-r--r--net/wireless/mlme.c16
-rw-r--r--net/wireless/nl80211.c405
-rw-r--r--net/wireless/nl80211.h4
-rw-r--r--net/wireless/reg.c47
-rw-r--r--net/wireless/reg.h2
-rw-r--r--net/wireless/scan.c28
-rw-r--r--net/wireless/sme.c19
-rw-r--r--net/wireless/util.c194
-rw-r--r--net/wireless/wext-compat.c137
-rw-r--r--net/wireless/wext-compat.h8
-rw-r--r--net/wireless/wext-sme.c3
-rw-r--r--net/xfrm/xfrm_ipcomp.c13
-rw-r--r--net/xfrm/xfrm_replay.c98
-rw-r--r--net/xfrm/xfrm_user.c4
-rwxr-xr-xscripts/checkpatch.pl40
-rw-r--r--scripts/mod/file2alias.c25
-rw-r--r--security/Kconfig6
-rw-r--r--security/Makefile4
-rw-r--r--security/apparmor/apparmorfs.c2
-rw-r--r--security/apparmor/ipc.c1
-rw-r--r--security/apparmor/lib.c1
-rw-r--r--security/apparmor/policy_unpack.c12
-rw-r--r--security/apparmor/procattr.c1
-rw-r--r--security/commoncap.c16
-rw-r--r--security/integrity/Kconfig7
-rw-r--r--security/integrity/Makefile12
-rw-r--r--security/integrity/evm/Kconfig13
-rw-r--r--security/integrity/evm/Makefile7
-rw-r--r--security/integrity/evm/evm.h38
-rw-r--r--security/integrity/evm/evm_crypto.c216
-rw-r--r--security/integrity/evm/evm_main.c384
-rw-r--r--security/integrity/evm/evm_posix_acl.c26
-rw-r--r--security/integrity/evm/evm_secfs.c108
-rw-r--r--security/integrity/iint.c172
-rw-r--r--security/integrity/ima/Kconfig3
-rw-r--r--security/integrity/ima/Makefile2
-rw-r--r--security/integrity/ima/ima.h30
-rw-r--r--security/integrity/ima/ima_api.c7
-rw-r--r--security/integrity/ima/ima_fs.c2
-rw-r--r--security/integrity/ima/ima_iint.c169
-rw-r--r--security/integrity/ima/ima_main.c13
-rw-r--r--security/integrity/integrity.h50
-rw-r--r--security/keys/Makefile2
-rw-r--r--security/keys/compat.c2
-rw-r--r--security/keys/encrypted-keys/Makefile6
-rw-r--r--security/keys/encrypted-keys/ecryptfs_format.c (renamed from security/keys/ecryptfs_format.c)0
-rw-r--r--security/keys/encrypted-keys/ecryptfs_format.h (renamed from security/keys/ecryptfs_format.h)0
-rw-r--r--security/keys/encrypted-keys/encrypted.c (renamed from security/keys/encrypted.c)51
-rw-r--r--security/keys/encrypted-keys/encrypted.h (renamed from security/keys/encrypted.h)11
-rw-r--r--security/keys/encrypted-keys/masterkey_trusted.c45
-rw-r--r--security/keys/gc.c386
-rw-r--r--security/keys/internal.h4
-rw-r--r--security/keys/key.c121
-rw-r--r--security/keys/keyctl.c2
-rw-r--r--security/keys/keyring.c3
-rw-r--r--security/keys/process_keys.c16
-rw-r--r--security/keys/trusted.c21
-rw-r--r--security/security.c76
-rw-r--r--security/selinux/exports.c1
-rw-r--r--security/selinux/hooks.c13
-rw-r--r--security/selinux/include/avc_ss.h6
-rw-r--r--security/selinux/include/security.h8
-rw-r--r--security/selinux/netlink.c2
-rw-r--r--security/selinux/nlmsgtab.c1
-rw-r--r--security/selinux/selinuxfs.c5
-rw-r--r--security/selinux/ss/conditional.c2
-rw-r--r--security/selinux/ss/conditional.h1
-rw-r--r--security/selinux/ss/policydb.c2
-rw-r--r--security/selinux/ss/services.c3
-rw-r--r--security/smack/smack.h24
-rw-r--r--security/smack/smack_access.c134
-rw-r--r--security/smack/smack_lsm.c266
-rw-r--r--security/smack/smackfs.c277
-rw-r--r--security/tomoyo/Kconfig2
-rw-r--r--security/tomoyo/Makefile4
-rw-r--r--security/tomoyo/audit.c7
-rw-r--r--security/tomoyo/common.c258
-rw-r--r--security/tomoyo/common.h189
-rw-r--r--security/tomoyo/condition.c71
-rw-r--r--security/tomoyo/domain.c209
-rw-r--r--security/tomoyo/environ.c122
-rw-r--r--security/tomoyo/file.c42
-rw-r--r--security/tomoyo/gc.c540
-rw-r--r--security/tomoyo/group.c61
-rw-r--r--security/tomoyo/memory.c39
-rw-r--r--security/tomoyo/network.c771
-rw-r--r--security/tomoyo/realpath.c32
-rw-r--r--security/tomoyo/securityfs_if.c123
-rw-r--r--security/tomoyo/tomoyo.c62
-rw-r--r--security/tomoyo/util.c80
-rw-r--r--sound/Kconfig2
-rw-r--r--sound/aoa/codecs/onyx.c4
-rw-r--r--sound/arm/aaci.c2
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c2
-rw-r--r--sound/core/control.c84
-rw-r--r--sound/core/control_compat.c4
-rw-r--r--sound/core/jack.c1
-rw-r--r--sound/core/memalloc.c4
-rw-r--r--sound/core/oss/mixer_oss.c2
-rw-r--r--sound/core/pcm_lib.c26
-rw-r--r--sound/core/pcm_native.c21
-rw-r--r--sound/drivers/aloop.c13
-rw-r--r--sound/drivers/ml403-ac97cr.c4
-rw-r--r--sound/drivers/mpu401/mpu401.c3
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c20
-rw-r--r--sound/drivers/mtpav.c2
-rw-r--r--sound/drivers/serial-u16550.c2
-rw-r--r--sound/firewire/cmp.c2
-rw-r--r--sound/firewire/isight.c1
-rw-r--r--sound/firewire/speakers.c5
-rw-r--r--sound/isa/ad1816a/ad1816a.c2
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c2
-rw-r--r--sound/isa/als100.c1
-rw-r--r--sound/isa/azt2320.c3
-rw-r--r--sound/isa/cmi8330.c2
-rw-r--r--sound/isa/cs423x/cs4231.c1
-rw-r--r--sound/isa/cs423x/cs4236.c3
-rw-r--r--sound/isa/es1688/es1688.c2
-rw-r--r--sound/isa/es1688/es1688_lib.c2
-rw-r--r--sound/isa/es18xx.c6
-rw-r--r--sound/isa/galaxy/galaxy.c3
-rw-r--r--sound/isa/gus/gus_main.c2
-rw-r--r--sound/isa/gus/gusextreme.c3
-rw-r--r--sound/isa/gus/gusmax.c2
-rw-r--r--sound/isa/gus/interwave.c2
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c2
-rw-r--r--sound/isa/opl3sa2.c7
-rw-r--r--sound/isa/opti9xx/miro.c3
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c4
-rw-r--r--sound/isa/sb/jazz16.c1
-rw-r--r--sound/isa/sb/sb16.c5
-rw-r--r--sound/isa/sb/sb_common.c2
-rw-r--r--sound/isa/sc6000.c3
-rw-r--r--sound/isa/sscape.c3
-rw-r--r--sound/isa/wavefront/wavefront.c5
-rw-r--r--sound/isa/wss/wss_lib.c2
-rw-r--r--sound/mips/Kconfig5
-rw-r--r--sound/mips/au1x00.c4
-rw-r--r--sound/oss/Kconfig4
-rw-r--r--sound/oss/sound_timer.c2
-rw-r--r--sound/pci/als4000.c5
-rw-r--r--sound/pci/au88x0/au88x0_mpu401.c6
-rw-r--r--sound/pci/azt3328.c5
-rw-r--r--sound/pci/cmipci.c5
-rw-r--r--sound/pci/ctxfi/ctpcm.c2
-rw-r--r--sound/pci/ctxfi/ctsrc.c2
-rw-r--r--sound/pci/ctxfi/ctvmem.h2
-rw-r--r--sound/pci/emu10k1/emupcm.c5
-rw-r--r--sound/pci/es1938.c5
-rw-r--r--sound/pci/es1968.c5
-rw-r--r--sound/pci/fm801.c20
-rw-r--r--sound/pci/hda/Makefile3
-rw-r--r--sound/pci/hda/alc260_quirks.c304
-rw-r--r--sound/pci/hda/alc262_quirks.c530
-rw-r--r--sound/pci/hda/alc268_quirks.c636
-rw-r--r--sound/pci/hda/alc269_quirks.c674
-rw-r--r--sound/pci/hda/alc662_quirks.c1408
-rw-r--r--sound/pci/hda/alc680_quirks.c222
-rw-r--r--sound/pci/hda/alc861_quirks.c725
-rw-r--r--sound/pci/hda/alc861vd_quirks.c605
-rw-r--r--sound/pci/hda/alc880_quirks.c17
-rw-r--r--sound/pci/hda/alc882_quirks.c85
-rw-r--r--sound/pci/hda/alc_quirks.c13
-rw-r--r--sound/pci/hda/hda_codec.c143
-rw-r--r--sound/pci/hda/hda_eld.c39
-rw-r--r--sound/pci/hda/hda_hwdep.c6
-rw-r--r--sound/pci/hda/hda_intel.c225
-rw-r--r--sound/pci/hda/hda_local.h32
-rw-r--r--sound/pci/hda/hda_proc.c12
-rw-r--r--sound/pci/hda/hda_trace.h117
-rw-r--r--sound/pci/hda/patch_analog.c176
-rw-r--r--sound/pci/hda/patch_conexant.c165
-rw-r--r--sound/pci/hda/patch_hdmi.c99
-rw-r--r--sound/pci/hda/patch_realtek.c1402
-rw-r--r--sound/pci/hda/patch_sigmatel.c50
-rw-r--r--sound/pci/hda/patch_via.c68
-rw-r--r--sound/pci/ice1712/ice1712.c10
-rw-r--r--sound/pci/maestro3.c4
-rw-r--r--sound/pci/oxygen/oxygen_lib.c6
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c1
-rw-r--r--sound/pci/riptide/riptide.c2
-rw-r--r--sound/pci/rme9652/hdspm.c153
-rw-r--r--sound/pci/sis7019.c4
-rw-r--r--sound/pci/sonicvibes.c7
-rw-r--r--sound/pci/trident/trident.c5
-rw-r--r--sound/pci/via82xx.c13
-rw-r--r--sound/pci/ymfpci/ymfpci.c5
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c32
-rw-r--r--sound/ppc/keywest.c1
-rw-r--r--sound/ppc/snd_ps3.c2
-rw-r--r--sound/soc/Kconfig3
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c6
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c2
-rw-r--r--sound/soc/atmel/snd-soc-afeb9260.c2
-rw-r--r--sound/soc/au1x/Kconfig28
-rw-r--r--sound/soc/au1x/Makefile10
-rw-r--r--sound/soc/au1x/ac97c.c366
-rw-r--r--sound/soc/au1x/db1000.c75
-rw-r--r--sound/soc/au1x/db1200.c64
-rw-r--r--sound/soc/au1x/dbdma2.c91
-rw-r--r--sound/soc/au1x/dma.c377
-rw-r--r--sound/soc/au1x/i2sc.c349
-rw-r--r--sound/soc/au1x/psc-ac97.c61
-rw-r--r--sound/soc/au1x/psc-i2s.c55
-rw-r--r--sound/soc/au1x/psc.h16
-rw-r--r--sound/soc/blackfin/Kconfig13
-rw-r--r--sound/soc/blackfin/Makefile2
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c2
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c2
-rw-r--r--sound/soc/blackfin/bfin-eval-adau1373.c202
-rw-r--r--sound/soc/codecs/88pm860x-codec.c14
-rw-r--r--sound/soc/codecs/Kconfig16
-rw-r--r--sound/soc/codecs/Makefile8
-rw-r--r--sound/soc/codecs/ad193x.c96
-rw-r--r--sound/soc/codecs/ad193x.h36
-rw-r--r--sound/soc/codecs/ad1980.c11
-rw-r--r--sound/soc/codecs/adau1373.c1414
-rw-r--r--sound/soc/codecs/adau1373.h29
-rw-r--r--sound/soc/codecs/adau1701.c3
-rw-r--r--sound/soc/codecs/adav80x.c3
-rw-r--r--sound/soc/codecs/ads117x.h13
-rw-r--r--sound/soc/codecs/ak4104.c2
-rw-r--r--sound/soc/codecs/ak4535.c110
-rw-r--r--sound/soc/codecs/ak4641.c3
-rw-r--r--sound/soc/codecs/ak4642.c104
-rw-r--r--sound/soc/codecs/ak4671.c22
-rw-r--r--sound/soc/codecs/alc5623.c8
-rw-r--r--sound/soc/codecs/cs4270.c14
-rw-r--r--sound/soc/codecs/cs4271.c5
-rw-r--r--sound/soc/codecs/cs42l51.c15
-rw-r--r--sound/soc/codecs/da7210.c649
-rw-r--r--sound/soc/codecs/lm4857.c2
-rw-r--r--sound/soc/codecs/max98088.c36
-rw-r--r--sound/soc/codecs/max98095.c47
-rw-r--r--sound/soc/codecs/rt5631.c1773
-rw-r--r--sound/soc/codecs/rt5631.h701
-rw-r--r--sound/soc/codecs/sgtl5000.c37
-rw-r--r--sound/soc/codecs/sgtl5000.h2
-rw-r--r--sound/soc/codecs/sn95031.c16
-rw-r--r--sound/soc/codecs/ssm2602.c107
-rw-r--r--sound/soc/codecs/ssm2602.h6
-rw-r--r--sound/soc/codecs/sta32x.c54
-rw-r--r--sound/soc/codecs/tlv320aic23.c181
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c65
-rw-r--r--sound/soc/codecs/tlv320aic3x.c25
-rw-r--r--sound/soc/codecs/tlv320dac33.c31
-rw-r--r--sound/soc/codecs/tpa6130a2.c13
-rw-r--r--sound/soc/codecs/twl4030.c69
-rw-r--r--sound/soc/codecs/twl6040.c805
-rw-r--r--sound/soc/codecs/twl6040.h13
-rw-r--r--sound/soc/codecs/wl1273.c1
-rw-r--r--sound/soc/codecs/wm1250-ev1.c140
-rw-r--r--sound/soc/codecs/wm5100-tables.c1531
-rw-r--r--sound/soc/codecs/wm5100.c2809
-rw-r--r--sound/soc/codecs/wm5100.h5155
-rw-r--r--sound/soc/codecs/wm8350.c43
-rw-r--r--sound/soc/codecs/wm8400.c2
-rw-r--r--sound/soc/codecs/wm8510.c21
-rw-r--r--sound/soc/codecs/wm8523.c36
-rw-r--r--sound/soc/codecs/wm8580.c69
-rw-r--r--sound/soc/codecs/wm8711.c38
-rw-r--r--sound/soc/codecs/wm8728.c13
-rw-r--r--sound/soc/codecs/wm8731.c25
-rw-r--r--sound/soc/codecs/wm8737.c10
-rw-r--r--sound/soc/codecs/wm8741.c151
-rw-r--r--sound/soc/codecs/wm8750.c56
-rw-r--r--sound/soc/codecs/wm8753.c13
-rw-r--r--sound/soc/codecs/wm8770.c8
-rw-r--r--sound/soc/codecs/wm8776.c67
-rw-r--r--sound/soc/codecs/wm8782.c2
-rw-r--r--sound/soc/codecs/wm8804.c9
-rw-r--r--sound/soc/codecs/wm8900.c115
-rw-r--r--sound/soc/codecs/wm8904.c2
-rw-r--r--sound/soc/codecs/wm8940.c51
-rw-r--r--sound/soc/codecs/wm8960.c18
-rw-r--r--sound/soc/codecs/wm8961.c4
-rw-r--r--sound/soc/codecs/wm8962.c222
-rw-r--r--sound/soc/codecs/wm8971.c42
-rw-r--r--sound/soc/codecs/wm8974.c15
-rw-r--r--sound/soc/codecs/wm8978.c3
-rw-r--r--sound/soc/codecs/wm8983.c2
-rw-r--r--sound/soc/codecs/wm8988.c33
-rw-r--r--sound/soc/codecs/wm8990.c105
-rw-r--r--sound/soc/codecs/wm8991.c24
-rw-r--r--sound/soc/codecs/wm8993.c7
-rw-r--r--sound/soc/codecs/wm8994-tables.c16
-rw-r--r--sound/soc/codecs/wm8994.c376
-rw-r--r--sound/soc/codecs/wm8994.h2
-rw-r--r--sound/soc/codecs/wm8995.c22
-rw-r--r--sound/soc/codecs/wm8996.c321
-rw-r--r--sound/soc/codecs/wm9081.c14
-rw-r--r--sound/soc/codecs/wm9090.c7
-rw-r--r--sound/soc/codecs/wm_hubs.c68
-rw-r--r--sound/soc/codecs/wm_hubs.h3
-rw-r--r--sound/soc/davinci/Kconfig1
-rw-r--r--sound/soc/davinci/davinci-evm.c2
-rw-r--r--sound/soc/davinci/davinci-i2s.c5
-rw-r--r--sound/soc/davinci/davinci-mcasp.c20
-rw-r--r--sound/soc/davinci/davinci-pcm.c123
-rw-r--r--sound/soc/ep93xx/edb93xx.c60
-rw-r--r--sound/soc/ep93xx/ep93xx-ac97.c2
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c1
-rw-r--r--sound/soc/ep93xx/simone.c64
-rw-r--r--sound/soc/ep93xx/snappercl15.c53
-rw-r--r--sound/soc/fsl/fsl_dma.c1
-rw-r--r--sound/soc/fsl/fsl_ssi.c206
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c2
-rw-r--r--sound/soc/fsl/p1022_ds.c4
-rw-r--r--sound/soc/imx/Kconfig3
-rw-r--r--sound/soc/imx/imx-pcm-fiq.c12
-rw-r--r--sound/soc/imx/imx-ssi.c9
-rw-r--r--sound/soc/imx/imx-ssi.h6
-rw-r--r--sound/soc/jz4740/jz4740-pcm.c2
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c2
-rw-r--r--sound/soc/kirkwood/kirkwood-t5325.c2
-rw-r--r--sound/soc/mid-x86/mfld_machine.c4
-rw-r--r--sound/soc/mid-x86/sst_platform.c19
-rw-r--r--sound/soc/mxs/Kconfig20
-rw-r--r--sound/soc/mxs/Makefile10
-rw-r--r--sound/soc/mxs/mxs-pcm.c359
-rw-r--r--sound/soc/mxs/mxs-pcm.h (renamed from arch/arm/mach-mxs/include/mach/memory.h)29
-rw-r--r--sound/soc/mxs/mxs-saif.c798
-rw-r--r--sound/soc/mxs/mxs-saif.h134
-rw-r--r--sound/soc/mxs/mxs-sgtl5000.c173
-rw-r--r--sound/soc/nuc900/nuc900-pcm.c5
-rw-r--r--sound/soc/omap/Makefile2
-rw-r--r--sound/soc/omap/am3517evm.c50
-rw-r--r--sound/soc/omap/ams-delta.c1
-rw-r--r--sound/soc/omap/igep0020.c23
-rw-r--r--sound/soc/omap/mcpdm.c470
-rw-r--r--sound/soc/omap/mcpdm.h153
-rw-r--r--sound/soc/omap/n810.c42
-rw-r--r--sound/soc/omap/omap-mcbsp.c27
-rw-r--r--sound/soc/omap/omap-mcpdm.c481
-rw-r--r--sound/soc/omap/omap-mcpdm.h107
-rw-r--r--sound/soc/omap/omap-pcm.c8
-rw-r--r--sound/soc/omap/omap3evm.c23
-rw-r--r--sound/soc/omap/omap3pandora.c28
-rw-r--r--sound/soc/omap/osk5912.c50
-rw-r--r--sound/soc/omap/overo.c23
-rw-r--r--sound/soc/omap/rx51.c22
-rw-r--r--sound/soc/omap/sdp3430.c88
-rw-r--r--sound/soc/omap/sdp4430.c47
-rw-r--r--sound/soc/omap/zoom2.c96
-rw-r--r--sound/soc/pxa/Kconfig2
-rw-r--r--sound/soc/pxa/corgi.c1
-rw-r--r--sound/soc/pxa/e740_wm9705.c2
-rw-r--r--sound/soc/pxa/e750_wm9705.c2
-rw-r--r--sound/soc/pxa/e800_wm9712.c1
-rw-r--r--sound/soc/pxa/magician.c4
-rw-r--r--sound/soc/pxa/mioa701_wm9713.c1
-rw-r--r--sound/soc/pxa/palm27x.c4
-rw-r--r--sound/soc/pxa/poodle.c1
-rw-r--r--sound/soc/pxa/raumfeld.c4
-rw-r--r--sound/soc/pxa/saarb.c4
-rw-r--r--sound/soc/pxa/spitz.c3
-rw-r--r--sound/soc/pxa/tavorevb3.c4
-rw-r--r--sound/soc/pxa/tosa.c1
-rw-r--r--sound/soc/pxa/z2.c6
-rw-r--r--sound/soc/pxa/zylonite.c1
-rw-r--r--sound/soc/s6000/s6000-pcm.c1
-rw-r--r--sound/soc/samsung/Kconfig12
-rw-r--r--sound/soc/samsung/ac97.c4
-rw-r--r--sound/soc/samsung/goni_wm8994.c15
-rw-r--r--sound/soc/samsung/h1940_uda1380.c19
-rw-r--r--sound/soc/samsung/i2s.c2
-rw-r--r--sound/soc/samsung/jive_wm8750.c19
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c4
-rw-r--r--sound/soc/samsung/pcm.c2
-rw-r--r--sound/soc/samsung/rx1950_uda1380.c33
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.c1
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c6
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c6
-rw-r--r--sound/soc/samsung/s3c24xx_simtec.c2
-rw-r--r--sound/soc/samsung/s3c24xx_simtec_hermes.c11
-rw-r--r--sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c11
-rw-r--r--sound/soc/samsung/s3c24xx_uda134x.c8
-rw-r--r--sound/soc/samsung/smartq_wm8987.c27
-rw-r--r--sound/soc/samsung/smdk_wm8580.c51
-rw-r--r--sound/soc/samsung/smdk_wm8580pcm.c4
-rw-r--r--sound/soc/samsung/smdk_wm8994.c2
-rw-r--r--sound/soc/samsung/spdif.c4
-rw-r--r--sound/soc/samsung/speyside.c10
-rw-r--r--sound/soc/samsung/speyside_wm8962.c41
-rw-r--r--sound/soc/sh/fsi.c12
-rw-r--r--sound/soc/sh/sh7760-ac97.c7
-rw-r--r--sound/soc/sh/ssi.c2
-rw-r--r--sound/soc/soc-cache.c7
-rw-r--r--sound/soc/soc-core.c215
-rw-r--r--sound/soc/soc-dapm.c416
-rw-r--r--sound/soc/soc-io.c357
-rw-r--r--sound/soc/soc-jack.c2
-rw-r--r--sound/soc/soc-pcm.c57
-rw-r--r--sound/soc/tegra/tegra_das.c4
-rw-r--r--sound/soc/tegra/tegra_i2s.c2
-rw-r--r--sound/soc/tegra/tegra_pcm.c2
-rw-r--r--sound/soc/tegra/tegra_spdif.c5
-rw-r--r--sound/soc/tegra/tegra_wm8903.c2
-rw-r--r--sound/soc/tegra/trimslice.c2
-rw-r--r--sound/soc/txx9/txx9aclc-ac97.c2
-rw-r--r--sound/soc/txx9/txx9aclc-generic.c2
-rw-r--r--sound/sparc/amd7930.c2
-rw-r--r--sound/usb/6fire/firmware.c25
-rw-r--r--sound/usb/Kconfig2
-rw-r--r--sound/usb/Makefile12
-rw-r--r--sound/usb/caiaq/device.c8
-rw-r--r--sound/usb/caiaq/device.h1
-rw-r--r--sound/usb/caiaq/input.c155
-rw-r--r--sound/usb/card.c6
-rw-r--r--sound/usb/card.h2
-rw-r--r--sound/usb/clock.c12
-rw-r--r--sound/usb/endpoint.c1199
-rw-r--r--sound/usb/endpoint.h20
-rw-r--r--sound/usb/format.c4
-rw-r--r--sound/usb/helper.c4
-rw-r--r--sound/usb/helper.h2
-rw-r--r--sound/usb/midi.c27
-rw-r--r--sound/usb/mixer.c21
-rw-r--r--sound/usb/mixer_quirks.c10
-rw-r--r--sound/usb/pcm.c34
-rw-r--r--sound/usb/pcm.h3
-rw-r--r--sound/usb/quirks-table.h25
-rw-r--r--sound/usb/quirks.c16
-rw-r--r--sound/usb/stream.c452
-rw-r--r--sound/usb/stream.h12
-rw-r--r--sound/usb/urb.c941
-rw-r--r--sound/usb/urb.h21
-rw-r--r--sound/usb/usbaudio.h1
-rw-r--r--tools/hv/hv_kvp_daemon.c (renamed from drivers/staging/hv/tools/hv_kvp_daemon.c)19
-rw-r--r--tools/perf/Documentation/perf-annotate.txt13
-rw-r--r--tools/perf/Documentation/perf-buildid-list.txt6
-rw-r--r--tools/perf/Documentation/perf-report.txt20
-rw-r--r--tools/perf/Documentation/perf-sched.txt6
-rw-r--r--tools/perf/Documentation/perf-script.txt7
-rw-r--r--tools/perf/Documentation/perf-stat.txt16
-rw-r--r--tools/perf/Documentation/perf-top.txt48
-rw-r--r--tools/perf/Documentation/perfconfig.example20
-rw-r--r--tools/perf/Makefile5
-rw-r--r--tools/perf/arch/powerpc/Makefile1
-rw-r--r--tools/perf/arch/powerpc/util/header.c36
-rw-r--r--tools/perf/arch/x86/Makefile1
-rw-r--r--tools/perf/arch/x86/util/header.c59
-rw-r--r--tools/perf/builtin-annotate.c25
-rw-r--r--tools/perf/builtin-buildid-list.c52
-rw-r--r--tools/perf/builtin-diff.c2
-rw-r--r--tools/perf/builtin-record.c34
-rw-r--r--tools/perf/builtin-report.c28
-rw-r--r--tools/perf/builtin-script.c6
-rw-r--r--tools/perf/builtin-stat.c190
-rw-r--r--tools/perf/builtin-top.c495
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/perf.c24
-rw-r--r--tools/perf/perf.h13
-rwxr-xr-xtools/perf/scripts/python/bin/net_dropmonitor-record2
-rwxr-xr-xtools/perf/scripts/python/bin/net_dropmonitor-report4
-rwxr-xr-xtools/perf/scripts/python/net_dropmonitor.py72
-rw-r--r--tools/perf/util/annotate.c11
-rw-r--r--tools/perf/util/annotate.h9
-rw-r--r--tools/perf/util/color.c2
-rw-r--r--tools/perf/util/config.c4
-rw-r--r--tools/perf/util/evlist.c6
-rw-r--r--tools/perf/util/evlist.h4
-rw-r--r--tools/perf/util/evsel.c1
-rw-r--r--tools/perf/util/header.c1231
-rw-r--r--tools/perf/util/header.h29
-rw-r--r--tools/perf/util/hist.c447
-rw-r--r--tools/perf/util/hist.h61
-rw-r--r--tools/perf/util/map.c102
-rw-r--r--tools/perf/util/map.h42
-rw-r--r--tools/perf/util/probe-event.c4
-rw-r--r--tools/perf/util/session.c19
-rw-r--r--tools/perf/util/session.h1
-rw-r--r--tools/perf/util/sort.c4
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/symbol.c3
-rw-r--r--tools/perf/util/symbol.h5
-rw-r--r--tools/perf/util/top.c141
-rw-r--r--tools/perf/util/top.h39
-rw-r--r--tools/perf/util/trace-event-info.c112
-rw-r--r--tools/perf/util/trace-event.h13
-rw-r--r--tools/perf/util/ui/browser.c386
-rw-r--r--tools/perf/util/ui/browser.h12
-rw-r--r--tools/perf/util/ui/browsers/annotate.c201
-rw-r--r--tools/perf/util/ui/browsers/hists.c297
-rw-r--r--tools/perf/util/ui/browsers/map.c6
-rw-r--r--tools/perf/util/ui/browsers/top.c212
-rw-r--r--tools/perf/util/ui/helpline.h3
-rw-r--r--tools/perf/util/ui/keysyms.h25
-rw-r--r--tools/perf/util/ui/libslang.h2
-rw-r--r--tools/perf/util/ui/setup.c38
-rw-r--r--tools/slub/slabinfo.c10
-rw-r--r--virt/kvm/assigned-dev.c64
-rw-r--r--virt/kvm/coalesced_mmio.c131
-rw-r--r--virt/kvm/coalesced_mmio.h7
-rw-r--r--virt/kvm/eventfd.c3
-rw-r--r--virt/kvm/ioapic.c3
-rw-r--r--virt/kvm/iommu.c8
-rw-r--r--virt/kvm/kvm_main.c112
8321 files changed, 521708 insertions, 333273 deletions
diff --git a/Documentation/ABI/removed/o2cb b/Documentation/ABI/removed/o2cb
index 7f5daa465093..20c91adca6d4 100644
--- a/Documentation/ABI/removed/o2cb
+++ b/Documentation/ABI/removed/o2cb
@@ -1,6 +1,6 @@
What: /sys/o2cb symlink
Date: May 2011
-KernelVersion: 2.6.40
+KernelVersion: 3.0
Contact: ocfs2-devel@oss.oracle.com
Description: This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink is
removed when new versions of ocfs2-tools which know to look
diff --git a/Documentation/ABI/removed/raw1394 b/Documentation/ABI/removed/raw1394
index 490aa1efc4ae..ec333e676322 100644
--- a/Documentation/ABI/removed/raw1394
+++ b/Documentation/ABI/removed/raw1394
@@ -5,7 +5,7 @@ Description:
/dev/raw1394 was a character device file that allowed low-level
access to FireWire buses. Its major drawbacks were its inability
to implement sensible device security policies, and its low level
- of abstraction that required userspace clients do duplicate much
+ of abstraction that required userspace clients to duplicate much
of the kernel's ieee1394 core functionality.
Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
firewire-core.
diff --git a/Documentation/ABI/testing/debugfs-ideapad b/Documentation/ABI/testing/debugfs-ideapad
new file mode 100644
index 000000000000..7079c0b21030
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-ideapad
@@ -0,0 +1,19 @@
+What: /sys/kernel/debug/ideapad/cfg
+Date: Sep 2011
+KernelVersion: 3.2
+Contact: Ike Panhc <ike.pan@canonical.com>
+Description:
+
+cfg shows the return value of _CFG method in VPC2004 device. It tells machine
+capability and what graphic component within the machine.
+
+
+What: /sys/kernel/debug/ideapad/status
+Date: Sep 2011
+KernelVersion: 3.2
+Contact: Ike Panhc <ike.pan@canonical.com>
+Description:
+
+status shows infos we can read and tells its meaning and value.
+
+
diff --git a/Documentation/ABI/testing/evm b/Documentation/ABI/testing/evm
new file mode 100644
index 000000000000..8374d4557e5d
--- /dev/null
+++ b/Documentation/ABI/testing/evm
@@ -0,0 +1,23 @@
+What: security/evm
+Date: March 2011
+Contact: Mimi Zohar <zohar@us.ibm.com>
+Description:
+ EVM protects a file's security extended attributes(xattrs)
+ against integrity attacks. The initial method maintains an
+ HMAC-sha1 value across the extended attributes, storing the
+ value as the extended attribute 'security.evm'.
+
+ EVM depends on the Kernel Key Retention System to provide it
+ with a trusted/encrypted key for the HMAC-sha1 operation.
+ The key is loaded onto the root's keyring using keyctl. Until
+ EVM receives notification that the key has been successfully
+ loaded onto the keyring (echo 1 > <securityfs>/evm), EVM
+ can not create or validate the 'security.evm' xattr, but
+ returns INTEGRITY_UNKNOWN. Loading the key and signaling EVM
+ should be done as early as possible. Normally this is done
+ in the initramfs, which has already been measured as part
+ of the trusted boot. For more information on creating and
+ loading existing trusted/encrypted keys, refer to:
+ Documentation/keys-trusted-encrypted.txt. (A sample dracut
+ patch, which loads the trusted/encrypted key and enables
+ EVM, is available from http://linux-ima.sourceforge.net/#EVM.)
diff --git a/Documentation/ABI/testing/sysfs-block b/Documentation/ABI/testing/sysfs-block
index c1eb41cb9876..2b5d56127fce 100644
--- a/Documentation/ABI/testing/sysfs-block
+++ b/Documentation/ABI/testing/sysfs-block
@@ -206,3 +206,16 @@ Description:
when a discarded area is read the discard_zeroes_data
parameter will be set to one. Otherwise it will be 0 and
the result of reading a discarded area is undefined.
+What: /sys/block/<disk>/alias
+Date: Aug 2011
+Contact: Nao Nishijima <nao.nishijima.xt@hitachi.com>
+Description:
+ A raw device name of a disk does not always point a same disk
+ each boot-up time. Therefore, users have to use persistent
+ device names, which udev creates when the kernel finds a disk,
+ instead of raw device name. However, kernel doesn't show those
+ persistent names on its messages (e.g. dmesg).
+ This file can store an alias of the disk and it would be
+ appeared in kernel messages if it is set. A disk can have an
+ alias which length is up to 255bytes. Users can use alphabets,
+ numbers, "-" and "_" in alias name. This file is writeonce.
diff --git a/Documentation/ABI/testing/sysfs-bus-bcma b/Documentation/ABI/testing/sysfs-bus-bcma
index 06b62badddd1..721b4aea3020 100644
--- a/Documentation/ABI/testing/sysfs-bus-bcma
+++ b/Documentation/ABI/testing/sysfs-bus-bcma
@@ -1,6 +1,6 @@
What: /sys/bus/bcma/devices/.../manuf
Date: May 2011
-KernelVersion: 2.6.40
+KernelVersion: 3.0
Contact: Rafał Miłecki <zajec5@gmail.com>
Description:
Each BCMA core has it's manufacturer id. See
@@ -8,7 +8,7 @@ Description:
What: /sys/bus/bcma/devices/.../id
Date: May 2011
-KernelVersion: 2.6.40
+KernelVersion: 3.0
Contact: Rafał Miłecki <zajec5@gmail.com>
Description:
There are a few types of BCMA cores, they can be identified by
@@ -16,7 +16,7 @@ Description:
What: /sys/bus/bcma/devices/.../rev
Date: May 2011
-KernelVersion: 2.6.40
+KernelVersion: 3.0
Contact: Rafał Miłecki <zajec5@gmail.com>
Description:
BCMA cores of the same type can still slightly differ depending
@@ -24,7 +24,7 @@ Description:
What: /sys/bus/bcma/devices/.../class
Date: May 2011
-KernelVersion: 2.6.40
+KernelVersion: 3.0
Contact: Rafał Miłecki <zajec5@gmail.com>
Description:
Each BCMA core is identified by few fields, including class it
diff --git a/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd b/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd
new file mode 100644
index 000000000000..60c60fa624b2
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd
@@ -0,0 +1,46 @@
+What: /sys/bus/pci/drivers/ehci_hcd/.../companion
+ /sys/bus/usb/devices/usbN/../companion
+Date: January 2007
+KernelVersion: 2.6.21
+Contact: Alan Stern <stern@rowland.harvard.edu>
+Description:
+ PCI-based EHCI USB controllers (i.e., high-speed USB-2.0
+ controllers) are often implemented along with a set of
+ "companion" full/low-speed USB-1.1 controllers. When a
+ high-speed device is plugged in, the connection is routed
+ to the EHCI controller; when a full- or low-speed device
+ is plugged in, the connection is routed to the companion
+ controller.
+
+ Sometimes you want to force a high-speed device to connect
+ at full speed, which can be accomplished by forcing the
+ connection to be routed to the companion controller.
+ That's what this file does. Writing a port number to the
+ file causes connections on that port to be routed to the
+ companion controller, and writing the negative of a port
+ number returns the port to normal operation.
+
+ For example: To force the high-speed device attached to
+ port 4 on bus 2 to run at full speed:
+
+ echo 4 >/sys/bus/usb/devices/usb2/../companion
+
+ To return the port to high-speed operation:
+
+ echo -4 >/sys/bus/usb/devices/usb2/../companion
+
+ Reading the file gives the list of ports currently forced
+ to the companion controller.
+
+ Note: Some EHCI controllers do not have companions; they
+ may contain an internal "transaction translator" or they
+ may be attached directly to a "rate-matching hub". This
+ mechanism will not work with such controllers. Also, it
+ cannot be used to force a port on a high-speed hub to
+ connect at full speed.
+
+ Note: When this file was first added, it appeared in a
+ different sysfs directory. The location given above is
+ correct for 2.6.35 (and probably several earlier kernel
+ versions as well).
+
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index 294aa864a60a..e647378e9e88 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -142,3 +142,18 @@ Description:
such devices.
Users:
usb_modeswitch
+
+What: /sys/bus/usb/devices/.../power/usb2_hardware_lpm
+Date: September 2011
+Contact: Andiry Xu <andiry.xu@amd.com>
+Description:
+ If CONFIG_USB_SUSPEND is set and a USB 2.0 lpm-capable device
+ is plugged in to a xHCI host which support link PM, it will
+ perform a LPM test; if the test is passed and host supports
+ USB2 hardware LPM (xHCI 1.0 feature), USB2 hardware LPM will
+ be enabled for the device and the USB device directory will
+ contain a file named power/usb2_hardware_lpm. The file holds
+ a string value (enable or disable) indicating whether or not
+ USB2 hardware LPM is enabled for the device. Developer can
+ write y/Y/1 or n/N/0 to the file to enable/disable the
+ feature.
diff --git a/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870
index aa11dbdd794b..4a9c545bda4b 100644
--- a/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870
+++ b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870
@@ -4,8 +4,8 @@ What: /sys/class/backlight/<backlight>/l2_bright_max
What: /sys/class/backlight/<backlight>/l3_office_max
What: /sys/class/backlight/<backlight>/l4_indoor_max
What: /sys/class/backlight/<backlight>/l5_dark_max
-Date: Mai 2011
-KernelVersion: 2.6.40
+Date: May 2011
+KernelVersion: 3.0
Contact: device-drivers-devel@blackfin.uclinux.org
Description:
Control the maximum brightness for <ambient light zone>
@@ -18,8 +18,8 @@ What: /sys/class/backlight/<backlight>/l2_bright_dim
What: /sys/class/backlight/<backlight>/l3_office_dim
What: /sys/class/backlight/<backlight>/l4_indoor_dim
What: /sys/class/backlight/<backlight>/l5_dark_dim
-Date: Mai 2011
-KernelVersion: 2.6.40
+Date: May 2011
+KernelVersion: 3.0
Contact: device-drivers-devel@blackfin.uclinux.org
Description:
Control the dim brightness for <ambient light zone>
@@ -29,8 +29,8 @@ Description:
this <ambient light zone>.
What: /sys/class/backlight/<backlight>/ambient_light_level
-Date: Mai 2011
-KernelVersion: 2.6.40
+Date: May 2011
+KernelVersion: 3.0
Contact: device-drivers-devel@blackfin.uclinux.org
Description:
Get conversion value of the light sensor.
@@ -39,8 +39,8 @@ Description:
8000 (max ambient brightness)
What: /sys/class/backlight/<backlight>/ambient_light_zone
-Date: Mai 2011
-KernelVersion: 2.6.40
+Date: May 2011
+KernelVersion: 3.0
Contact: device-drivers-devel@blackfin.uclinux.org
Description:
Get/Set current ambient light zone. Reading returns
diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq
new file mode 100644
index 000000000000..23d78b5aab11
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-devfreq
@@ -0,0 +1,52 @@
+What: /sys/class/devfreq/.../
+Date: September 2011
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ Provide a place in sysfs for the devfreq objects.
+ This allows accessing various devfreq specific variables.
+ The name of devfreq object denoted as ... is same as the
+ name of device using devfreq.
+
+What: /sys/class/devfreq/.../governor
+Date: September 2011
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ The /sys/class/devfreq/.../governor shows the name of the
+ governor used by the corresponding devfreq object.
+
+What: /sys/class/devfreq/.../cur_freq
+Date: September 2011
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ The /sys/class/devfreq/.../cur_freq shows the current
+ frequency of the corresponding devfreq object.
+
+What: /sys/class/devfreq/.../central_polling
+Date: September 2011
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ The /sys/class/devfreq/.../central_polling shows whether
+ the devfreq ojbect is using devfreq-provided central
+ polling mechanism or not.
+
+What: /sys/class/devfreq/.../polling_interval
+Date: September 2011
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ The /sys/class/devfreq/.../polling_interval shows and sets
+ the requested polling interval of the corresponding devfreq
+ object. The values are represented in ms. If the value is
+ less than 1 jiffy, it is considered to be 0, which means
+ no polling. This value is meaningless if the governor is
+ not polling; thus. If the governor is not using
+ devfreq-provided central polling
+ (/sys/class/devfreq/.../central_polling is 0), this value
+ may be useless.
+
+What: /sys/class/devfreq/.../userspace/set_freq
+Date: September 2011
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+ The /sys/class/devfreq/.../userspace/set_freq shows and
+ sets the requested frequency for the devfreq object if
+ userspace governor is in effect.
diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh
index 748fe1701d25..b02001488eef 100644
--- a/Documentation/ABI/testing/sysfs-class-net-mesh
+++ b/Documentation/ABI/testing/sysfs-class-net-mesh
@@ -22,6 +22,14 @@ 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>
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
new file mode 100644
index 000000000000..9aec8ef228b0
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
@@ -0,0 +1,7 @@
+What: /sys/module/hid_logitech/drivers/hid:logitech/<dev>/range.
+Date: July 2011
+KernelVersion: 3.2
+Contact: Michal Malý <madcatxster@gmail.com>
+Description: Display minimum, maximum and current range of the steering
+ wheel. Writing a value within min and max boundaries sets the
+ range of the wheel.
diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom
new file mode 100644
index 000000000000..82d4df136444
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-wacom
@@ -0,0 +1,72 @@
+What: /sys/class/hidraw/hidraw*/device/speed
+Date: April 2010
+Kernel Version: 2.6.35
+Contact: linux-bluetooth@vger.kernel.org
+Description:
+ The /sys/class/hidraw/hidraw*/device/speed file controls
+ reporting speed of Wacom bluetooth tablet. Reading from
+ this file returns 1 if tablet reports in high speed mode
+ or 0 otherwise. Writing to this file one of these values
+ switches reporting speed.
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/led
+Date: August 2011
+Contact: linux-input@vger.kernel.org
+Description:
+ Attribute group for control of the status LEDs and the OLEDs.
+ This attribute group is only available for Intuos 4 M, L,
+ and XL (with LEDs and OLEDs) and Cintiq 21UX2 (LEDs only).
+ Therefore its presence implicitly signifies the presence of
+ said LEDs and OLEDs on the tablet device.
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
+Date: August 2011
+Contact: linux-input@vger.kernel.org
+Description:
+ Writing to this file sets the status LED luminance (1..127)
+ when the stylus does not touch the tablet surface, and no
+ button is pressed on the stylus. This luminance level is
+ normally lower than the level when a button is pressed.
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status1_luminance
+Date: August 2011
+Contact: linux-input@vger.kernel.org
+Description:
+ Writing to this file sets the status LED luminance (1..127)
+ when the stylus touches the tablet surface, or any button is
+ pressed on the stylus.
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led0_select
+Date: August 2011
+Contact: linux-input@vger.kernel.org
+Description:
+ Writing to this file sets which one of the four (for Intuos 4)
+ or of the right four (for Cintiq 21UX2) status LEDs is active (0..3).
+ The other three LEDs on the same side are always inactive.
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led1_select
+Date: September 2011
+Contact: linux-input@vger.kernel.org
+Description:
+ Writing to this file sets which one of the left four (for Cintiq 21UX2)
+ status LEDs is active (0..3). The other three LEDs on the left are always
+ inactive.
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/buttons_luminance
+Date: August 2011
+Contact: linux-input@vger.kernel.org
+Description:
+ Writing to this file sets the overall luminance level (0..15)
+ of all eight button OLED displays.
+
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/button<n>_rawimg
+Date: August 2011
+Contact: linux-input@vger.kernel.org
+Description:
+ When writing a 1024 byte raw image in Wacom Intuos 4
+ interleaving format to the file, the image shows up on Button N
+ of the device. The image is a 64x32 pixel 4-bit gray image. The
+ 1024 byte binary is split up into 16x 64 byte chunks. Each 64
+ byte chunk encodes the image data for two consecutive lines on
+ the display. The low nibble of each byte contains the first
+ line, and the high nibble contains the second line.
diff --git a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
index ff53183c3848..814b01354c41 100644
--- a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
+++ b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
@@ -5,19 +5,4 @@ Contact: "Ike Panhc <ike.pan@canonical.com>"
Description:
Control the power of camera module. 1 means on, 0 means off.
-What: /sys/devices/platform/ideapad/cfg
-Date: Jun 2011
-KernelVersion: 3.1
-Contact: "Ike Panhc <ike.pan@canonical.com>"
-Description:
- Ideapad capability bits.
- Bit 8-10: 1 - Intel graphic only
- 2 - ATI graphic only
- 3 - Nvidia graphic only
- 4 - Intel and ATI graphic
- 5 - Intel and Nvidia graphic
- Bit 16: Bluetooth exist (1 for exist)
- Bit 17: 3G exist (1 for exist)
- Bit 18: Wifi exist (1 for exist)
- Bit 19: Camera exist (1 for exist)
diff --git a/Documentation/ABI/testing/sysfs-wacom b/Documentation/ABI/testing/sysfs-wacom
deleted file mode 100644
index 1517976e25c4..000000000000
--- a/Documentation/ABI/testing/sysfs-wacom
+++ /dev/null
@@ -1,10 +0,0 @@
-What: /sys/class/hidraw/hidraw*/device/speed
-Date: April 2010
-Kernel Version: 2.6.35
-Contact: linux-bluetooth@vger.kernel.org
-Description:
- The /sys/class/hidraw/hidraw*/device/speed file controls
- reporting speed of wacom bluetooth tablet. Reading from
- this file returns 1 if tablet reports in high speed mode
- or 0 otherwise. Writing to this file one of these values
- switches reporting speed.
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index fe2326906610..66bd97a95f10 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -50,6 +50,13 @@ specify the GFP_ flags (see kmalloc) for the allocation (the
implementation may choose to ignore flags that affect the location of
the returned memory, like GFP_DMA).
+void *
+dma_zalloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+
+Wraps dma_alloc_coherent() and also zeroes the returned memory if the
+allocation attempt succeeded.
+
void
dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_handle)
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
index 445289cd0e65..2014155c899d 100644
--- a/Documentation/DocBook/80211.tmpl
+++ b/Documentation/DocBook/80211.tmpl
@@ -433,8 +433,18 @@
Insert notes about VLAN interfaces with hw crypto here or
in the hw crypto chapter.
</para>
+ <section id="ps-client">
+ <title>support for powersaving clients</title>
+!Pinclude/net/mac80211.h AP support for powersaving clients
+ </section>
!Finclude/net/mac80211.h ieee80211_get_buffered_bc
!Finclude/net/mac80211.h ieee80211_beacon_get
+!Finclude/net/mac80211.h ieee80211_sta_eosp_irqsafe
+!Finclude/net/mac80211.h ieee80211_frame_release_type
+!Finclude/net/mac80211.h ieee80211_sta_ps_transition
+!Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni
+!Finclude/net/mac80211.h ieee80211_sta_set_buffered
+!Finclude/net/mac80211.h ieee80211_sta_block_awake
</chapter>
<chapter id="multi-iface">
@@ -460,7 +470,6 @@
!Finclude/net/mac80211.h sta_notify_cmd
!Finclude/net/mac80211.h ieee80211_find_sta
!Finclude/net/mac80211.h ieee80211_find_sta_by_ifaddr
-!Finclude/net/mac80211.h ieee80211_sta_block_awake
</chapter>
<chapter id="hardware-scan-offload">
diff --git a/Documentation/DocBook/media/dvb/dvbproperty.xml b/Documentation/DocBook/media/dvb/dvbproperty.xml
index 207e1a5bf8f0..3bc8a61efe30 100644
--- a/Documentation/DocBook/media/dvb/dvbproperty.xml
+++ b/Documentation/DocBook/media/dvb/dvbproperty.xml
@@ -352,6 +352,7 @@ typedef enum fe_delivery_system {
SYS_CMMB,
SYS_DAB,
SYS_DVBT2,
+ SYS_TURBO,
} fe_delivery_system_t;
</programlisting>
</section>
@@ -809,6 +810,8 @@ typedef enum fe_hierarchy {
<listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
<listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
<listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
+ <listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
+ <listitem><para><link linkend="DTV-TONE"><constant>DTV_TONE</constant></link></para></listitem>
</itemizedlist>
<para>Future implementations might add those two missing parameters:</para>
<itemizedlist mark='opencircle'>
@@ -818,25 +821,18 @@ typedef enum fe_hierarchy {
</section>
<section id="dvbs2-params">
<title>DVB-S2 delivery system</title>
- <para>The following parameters are valid for DVB-S2:</para>
+ <para>In addition to all parameters valid for DVB-S, DVB-S2 supports the following parameters:</para>
<itemizedlist mark='opencircle'>
- <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-TONE"><constant>DTV_TONE</constant></link></para></listitem>
+ <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
<listitem><para><link linkend="DTV-PILOT"><constant>DTV_PILOT</constant></link></para></listitem>
<listitem><para><link linkend="DTV-ROLLOFF"><constant>DTV_ROLLOFF</constant></link></para></listitem>
</itemizedlist>
- <para>Future implementations might add those two missing parameters:</para>
+ </section>
+ <section id="turbo-params">
+ <title>Turbo code delivery system</title>
+ <para>In addition to all parameters valid for DVB-S, turbo code supports the following parameters:</para>
<itemizedlist mark='opencircle'>
- <listitem><para><link linkend="DTV-DISEQC-MASTER"><constant>DTV_DISEQC_MASTER</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-DISEQC-SLAVE-REPLY"><constant>DTV_DISEQC_SLAVE_REPLY</constant></link></para></listitem>
+ <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
</itemizedlist>
</section>
<section id="isdbs-params">
diff --git a/Documentation/DocBook/media/dvb/intro.xml b/Documentation/DocBook/media/dvb/intro.xml
index c75dc7cc3e9b..170064a3dc8f 100644
--- a/Documentation/DocBook/media/dvb/intro.xml
+++ b/Documentation/DocBook/media/dvb/intro.xml
@@ -205,7 +205,7 @@ a partial path like:</para>
additional include file <emphasis
role="tt">linux/dvb/version.h</emphasis> exists, which defines the
constant <emphasis role="tt">DVB_API_VERSION</emphasis>. This document
-describes <emphasis role="tt">DVB_API_VERSION&#x00A0;3</emphasis>.
+describes <emphasis role="tt">DVB_API_VERSION 5.4</emphasis>.
</para>
</section>
diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
index ce1004a7da52..91410b6e7e08 100644
--- a/Documentation/DocBook/media/v4l/compat.xml
+++ b/Documentation/DocBook/media/v4l/compat.xml
@@ -2370,6 +2370,14 @@ that used it. It was originally scheduled for removal in 2.6.35.
</listitem>
</orderedlist>
</section>
+ <section>
+ <title>V4L2 in Linux 3.2</title>
+ <orderedlist>
+ <listitem>
+ <para>V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace.</para>
+ </listitem>
+ </orderedlist>
+ </section>
<section id="other">
<title>Relation of V4L2 to other Linux multimedia APIs</title>
diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml
index 05c8fefcbcbe..0916a7343a16 100644
--- a/Documentation/DocBook/media/v4l/dev-subdev.xml
+++ b/Documentation/DocBook/media/v4l/dev-subdev.xml
@@ -266,7 +266,7 @@
<para>When satisfied with the try results, applications can set the active
formats by setting the <structfield>which</structfield> argument to
- <constant>V4L2_SUBDEV_FORMAT_TRY</constant>. Active formats are changed
+ <constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. Active formats are changed
exactly as try formats by drivers. To avoid modifying the hardware state
during format negotiation, applications should negotiate try formats first
and then modify the active settings using the try formats returned during
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index 0d05e8747c12..40132c277647 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -128,6 +128,13 @@ structs, ioctls) must be noted in more detail in the history chapter
applications. -->
<revision>
+ <revnumber>3.2</revnumber>
+ <date>2011-08-26</date>
+ <authorinitials>hv</authorinitials>
+ <revremark>Added V4L2_CTRL_FLAG_VOLATILE.</revremark>
+ </revision>
+
+ <revision>
<revnumber>3.1</revnumber>
<date>2011-06-27</date>
<authorinitials>mcc, po, hv</authorinitials>
@@ -410,7 +417,7 @@ and discussions on the V4L mailing list.</revremark>
</partinfo>
<title>Video for Linux Two API Specification</title>
- <subtitle>Revision 3.1</subtitle>
+ <subtitle>Revision 3.2</subtitle>
<chapter id="common">
&sub-common;
diff --git a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
index 7769642ee431..e8714aa16433 100644
--- a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
@@ -88,6 +88,12 @@
</row>
<row>
<entry></entry>
+ <entry>&v4l2-event-frame-sync;</entry>
+ <entry><structfield>frame</structfield></entry>
+ <entry>Event data for event V4L2_EVENT_FRAME_SYNC.</entry>
+ </row>
+ <row>
+ <entry></entry>
<entry>__u8</entry>
<entry><structfield>data</structfield>[64]</entry>
<entry>Event data. Defined by the event type. The union
@@ -135,6 +141,129 @@
</tgroup>
</table>
+ <table frame="none" pgwide="1" id="v4l2-event-vsync">
+ <title>struct <structname>v4l2_event_vsync</structname></title>
+ <tgroup cols="3">
+ &cs-str;
+ <tbody valign="top">
+ <row>
+ <entry>__u8</entry>
+ <entry><structfield>field</structfield></entry>
+ <entry>The upcoming field. See &v4l2-field;.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="none" pgwide="1" id="v4l2-event-ctrl">
+ <title>struct <structname>v4l2_event_ctrl</structname></title>
+ <tgroup cols="4">
+ &cs-str;
+ <tbody valign="top">
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>changes</structfield></entry>
+ <entry></entry>
+ <entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>type</structfield></entry>
+ <entry></entry>
+ <entry>The type of the control. See &v4l2-ctrl-type;.</entry>
+ </row>
+ <row>
+ <entry>union (anonymous)</entry>
+ <entry></entry>
+ <entry></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>__s32</entry>
+ <entry><structfield>value</structfield></entry>
+ <entry>The 32-bit value of the control for 32-bit control types.
+ This is 0 for string controls since the value of a string
+ cannot be passed using &VIDIOC-DQEVENT;.</entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>__s64</entry>
+ <entry><structfield>value64</structfield></entry>
+ <entry>The 64-bit value of the control for 64-bit control types.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>flags</structfield></entry>
+ <entry></entry>
+ <entry>The control flags. See <xref linkend="control-flags" />.</entry>
+ </row>
+ <row>
+ <entry>__s32</entry>
+ <entry><structfield>minimum</structfield></entry>
+ <entry></entry>
+ <entry>The minimum value of the control. See &v4l2-queryctrl;.</entry>
+ </row>
+ <row>
+ <entry>__s32</entry>
+ <entry><structfield>maximum</structfield></entry>
+ <entry></entry>
+ <entry>The maximum value of the control. See &v4l2-queryctrl;.</entry>
+ </row>
+ <row>
+ <entry>__s32</entry>
+ <entry><structfield>step</structfield></entry>
+ <entry></entry>
+ <entry>The step value of the control. See &v4l2-queryctrl;.</entry>
+ </row>
+ <row>
+ <entry>__s32</entry>
+ <entry><structfield>default_value</structfield></entry>
+ <entry></entry>
+ <entry>The default value value of the control. See &v4l2-queryctrl;.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="none" pgwide="1" id="v4l2-event-frame-sync">
+ <title>struct <structname>v4l2_event_frame_sync</structname></title>
+ <tgroup cols="3">
+ &cs-str;
+ <tbody valign="top">
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>frame_sequence</structfield></entry>
+ <entry>
+ The sequence number of the frame being received.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table pgwide="1" frame="none" id="changes-flags">
+ <title>Changes</title>
+ <tgroup cols="3">
+ &cs-def;
+ <tbody valign="top">
+ <row>
+ <entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
+ <entry>0x0001</entry>
+ <entry>This control event was triggered because the value of the control
+ changed. Special case: if a button control is pressed, then this
+ event is sent as well, even though there is not explicit value
+ associated with a button control.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>
+ <entry>0x0002</entry>
+ <entry>This control event was triggered because the control flags
+ changed.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
</refsect1>
<refsect1>
&return-value;
diff --git a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
index 677ea646c29f..0ac0057a51c4 100644
--- a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
@@ -406,6 +406,15 @@ flag is typically present for relative controls or action controls where
writing a value will cause the device to carry out a given action
(&eg; motor control) but no meaningful value can be returned.</entry>
</row>
+ <row>
+ <entry><constant>V4L2_CTRL_FLAG_VOLATILE</constant></entry>
+ <entry>0x0080</entry>
+ <entry>This control is volatile, which means that the value of the control
+changes continuously. A typical example would be the current gain value if the device
+is in auto-gain mode. In such a case the hardware calculates the gain value based on
+the lighting conditions which can change over time. Note that setting a new value for
+a volatile control will have no effect. The new value will just be ignored.</entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml b/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
index 69c0d8a2a3d2..5c70b616d818 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
@@ -139,6 +139,22 @@
</entry>
</row>
<row>
+ <entry><constant>V4L2_EVENT_FRAME_SYNC</constant></entry>
+ <entry>4</entry>
+ <entry>
+ <para>Triggered immediately when the reception of a
+ frame has begun. This event has a
+ &v4l2-event-frame-sync; associated with it.</para>
+
+ <para>If the hardware needs to be stopped in the case of a
+ buffer underrun it might not be able to generate this event.
+ In such cases the <structfield>frame_sequence</structfield>
+ field in &v4l2-event-frame-sync; will not be incremented. This
+ causes two consecutive frame sequence numbers to have n times
+ frame interval in between them.</para>
+ </entry>
+ </row>
+ <row>
<entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
<entry>0x08000000</entry>
<entry>Base event number for driver-private events.</entry>
@@ -183,113 +199,6 @@
</tgroup>
</table>
- <table frame="none" pgwide="1" id="v4l2-event-vsync">
- <title>struct <structname>v4l2_event_vsync</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u8</entry>
- <entry><structfield>field</structfield></entry>
- <entry>The upcoming field. See &v4l2-field;.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="v4l2-event-ctrl">
- <title>struct <structname>v4l2_event_ctrl</structname></title>
- <tgroup cols="4">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>changes</structfield></entry>
- <entry></entry>
- <entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry></entry>
- <entry>The type of the control. See &v4l2-ctrl-type;.</entry>
- </row>
- <row>
- <entry>union (anonymous)</entry>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry>__s32</entry>
- <entry><structfield>value</structfield></entry>
- <entry>The 32-bit value of the control for 32-bit control types.
- This is 0 for string controls since the value of a string
- cannot be passed using &VIDIOC-DQEVENT;.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__s64</entry>
- <entry><structfield>value64</structfield></entry>
- <entry>The 64-bit value of the control for 64-bit control types.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry></entry>
- <entry>The control flags. See <xref linkend="control-flags" />.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>minimum</structfield></entry>
- <entry></entry>
- <entry>The minimum value of the control. See &v4l2-queryctrl;.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>maximum</structfield></entry>
- <entry></entry>
- <entry>The maximum value of the control. See &v4l2-queryctrl;.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>step</structfield></entry>
- <entry></entry>
- <entry>The step value of the control. See &v4l2-queryctrl;.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>default_value</structfield></entry>
- <entry></entry>
- <entry>The default value value of the control. See &v4l2-queryctrl;.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="changes-flags">
- <title>Changes</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
- <entry>0x0001</entry>
- <entry>This control event was triggered because the value of the control
- changed. Special case: if a button control is pressed, then this
- event is sent as well, even though there is not explicit value
- associated with a button control.</entry>
- </row>
- <row>
- <entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>
- <entry>0x0002</entry>
- <entry>This control event was triggered because the control flags
- changed.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
</refsect1>
<refsect1>
&return-value;
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
index 7c4b514d62b1..54883de5d5f9 100644
--- a/Documentation/DocBook/uio-howto.tmpl
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -529,7 +529,7 @@ memory (e.g. allocated with <function>kmalloc()</function>). There's also
</para></listitem>
<listitem><para>
-<varname>unsigned long addr</varname>: Required if the mapping is used.
+<varname>phys_addr_t addr</varname>: Required if the mapping is used.
Fill in the address of your memory block. This address is the one that
appears in sysfs.
</para></listitem>
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl
index 598c22f3b3ac..5de23c007078 100644
--- a/Documentation/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl
@@ -4288,7 +4288,7 @@ struct _snd_pcm_runtime {
<![CDATA[
struct snd_rawmidi *rmidi;
snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
- irq, irq_flags, &rmidi);
+ irq, &rmidi);
]]>
</programlisting>
</informalexample>
@@ -4343,6 +4343,13 @@ struct _snd_pcm_runtime {
by itself to start processing the output stream in the irq handler.
</para>
+ <para>
+ If the MPU-401 interface shares its interrupt with the other logical
+ devices on the card, set <constant>MPU401_INFO_IRQ_HOOK</constant>
+ (see <link linkend="midi-interface-interrupt-handler"><citetitle>
+ below</citetitle></link>).
+ </para>
+
<para>
Usually, the port address corresponds to the command port and
port + 1 corresponds to the data port. If not, you may change
@@ -4375,14 +4382,12 @@ struct _snd_pcm_runtime {
</para>
<para>
- The 6th argument specifies the irq number for UART. If the irq
- is already allocated, pass 0 to the 7th argument
- (<parameter>irq_flags</parameter>). Otherwise, pass the flags
- for irq allocation
- (<constant>SA_XXX</constant> bits) to it, and the irq will be
- reserved by the mpu401-uart layer. If the card doesn't generate
- UART interrupts, pass -1 as the irq number. Then a timer
- interrupt will be invoked for polling.
+ The 6th argument specifies the ISA irq number that will be
+ allocated. If no interrupt is to be allocated (because your
+ code is already allocating a shared interrupt, or because the
+ device does not use interrupts), pass -1 instead.
+ For a MPU-401 device without an interrupt, a polling timer
+ will be used instead.
</para>
</section>
@@ -4390,12 +4395,13 @@ struct _snd_pcm_runtime {
<title>Interrupt Handler</title>
<para>
When the interrupt is allocated in
- <function>snd_mpu401_uart_new()</function>, the private
- interrupt handler is used, hence you don't have anything else to do
- than creating the mpu401 stuff. Otherwise, you have to call
- <function>snd_mpu401_uart_interrupt()</function> explicitly when
- a UART interrupt is invoked and checked in your own interrupt
- handler.
+ <function>snd_mpu401_uart_new()</function>, an exclusive ISA
+ interrupt handler is automatically used, hence you don't have
+ anything else to do than creating the mpu401 stuff. Otherwise, you
+ have to set <constant>MPU401_INFO_IRQ_HOOK</constant>, and call
+ <function>snd_mpu401_uart_interrupt()</function> explicitly from your
+ own interrupt handler when it has determined that a UART interrupt
+ has occurred.
</para>
<para>
diff --git a/Documentation/PCI/pci.txt b/Documentation/PCI/pci.txt
index 6148d4080f88..aa09e5476bba 100644
--- a/Documentation/PCI/pci.txt
+++ b/Documentation/PCI/pci.txt
@@ -314,7 +314,7 @@ from the PCI device config space. Use the values in the pci_dev structure
as the PCI "bus address" might have been remapped to a "host physical"
address by the arch/chip-set specific kernel support.
-See Documentation/IO-mapping.txt for how to access device registers
+See Documentation/io-mapping.txt for how to access device registers
or device memory.
The device driver needs to call pci_request_region() to verify
diff --git a/Documentation/RCU/NMI-RCU.txt b/Documentation/RCU/NMI-RCU.txt
index bf82851a0e57..687777f83b23 100644
--- a/Documentation/RCU/NMI-RCU.txt
+++ b/Documentation/RCU/NMI-RCU.txt
@@ -95,7 +95,7 @@ not to return until all ongoing NMI handlers exit. It is therefore safe
to free up the handler's data as soon as synchronize_sched() returns.
Important note: for this to work, the architecture in question must
-invoke irq_enter() and irq_exit() on NMI entry and exit, respectively.
+invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively.
Answer to Quick Quiz
diff --git a/Documentation/RCU/lockdep-splat.txt b/Documentation/RCU/lockdep-splat.txt
new file mode 100644
index 000000000000..bf9061142827
--- /dev/null
+++ b/Documentation/RCU/lockdep-splat.txt
@@ -0,0 +1,110 @@
+Lockdep-RCU was added to the Linux kernel in early 2010
+(http://lwn.net/Articles/371986/). This facility checks for some common
+misuses of the RCU API, most notably using one of the rcu_dereference()
+family to access an RCU-protected pointer without the proper protection.
+When such misuse is detected, an lockdep-RCU splat is emitted.
+
+The usual cause of a lockdep-RCU slat is someone accessing an
+RCU-protected data structure without either (1) being in the right kind of
+RCU read-side critical section or (2) holding the right update-side lock.
+This problem can therefore be serious: it might result in random memory
+overwriting or worse. There can of course be false positives, this
+being the real world and all that.
+
+So let's look at an example RCU lockdep splat from 3.0-rc5, one that
+has long since been fixed:
+
+===============================
+[ INFO: suspicious RCU usage. ]
+-------------------------------
+block/cfq-iosched.c:2776 suspicious rcu_dereference_protected() usage!
+
+other info that might help us debug this:
+
+
+rcu_scheduler_active = 1, debug_locks = 0
+3 locks held by scsi_scan_6/1552:
+ #0: (&shost->scan_mutex){+.+.+.}, at: [<ffffffff8145efca>]
+scsi_scan_host_selected+0x5a/0x150
+ #1: (&eq->sysfs_lock){+.+...}, at: [<ffffffff812a5032>]
+elevator_exit+0x22/0x60
+ #2: (&(&q->__queue_lock)->rlock){-.-...}, at: [<ffffffff812b6233>]
+cfq_exit_queue+0x43/0x190
+
+stack backtrace:
+Pid: 1552, comm: scsi_scan_6 Not tainted 3.0.0-rc5 #17
+Call Trace:
+ [<ffffffff810abb9b>] lockdep_rcu_dereference+0xbb/0xc0
+ [<ffffffff812b6139>] __cfq_exit_single_io_context+0xe9/0x120
+ [<ffffffff812b626c>] cfq_exit_queue+0x7c/0x190
+ [<ffffffff812a5046>] elevator_exit+0x36/0x60
+ [<ffffffff812a802a>] blk_cleanup_queue+0x4a/0x60
+ [<ffffffff8145cc09>] scsi_free_queue+0x9/0x10
+ [<ffffffff81460944>] __scsi_remove_device+0x84/0xd0
+ [<ffffffff8145dca3>] scsi_probe_and_add_lun+0x353/0xb10
+ [<ffffffff817da069>] ? error_exit+0x29/0xb0
+ [<ffffffff817d98ed>] ? _raw_spin_unlock_irqrestore+0x3d/0x80
+ [<ffffffff8145e722>] __scsi_scan_target+0x112/0x680
+ [<ffffffff812c690d>] ? trace_hardirqs_off_thunk+0x3a/0x3c
+ [<ffffffff817da069>] ? error_exit+0x29/0xb0
+ [<ffffffff812bcc60>] ? kobject_del+0x40/0x40
+ [<ffffffff8145ed16>] scsi_scan_channel+0x86/0xb0
+ [<ffffffff8145f0b0>] scsi_scan_host_selected+0x140/0x150
+ [<ffffffff8145f149>] do_scsi_scan_host+0x89/0x90
+ [<ffffffff8145f170>] do_scan_async+0x20/0x160
+ [<ffffffff8145f150>] ? do_scsi_scan_host+0x90/0x90
+ [<ffffffff810975b6>] kthread+0xa6/0xb0
+ [<ffffffff817db154>] kernel_thread_helper+0x4/0x10
+ [<ffffffff81066430>] ? finish_task_switch+0x80/0x110
+ [<ffffffff817d9c04>] ? retint_restore_args+0xe/0xe
+ [<ffffffff81097510>] ? __init_kthread_worker+0x70/0x70
+ [<ffffffff817db150>] ? gs_change+0xb/0xb
+
+Line 2776 of block/cfq-iosched.c in v3.0-rc5 is as follows:
+
+ if (rcu_dereference(ioc->ioc_data) == cic) {
+
+This form says that it must be in a plain vanilla RCU read-side critical
+section, but the "other info" list above shows that this is not the
+case. Instead, we hold three locks, one of which might be RCU related.
+And maybe that lock really does protect this reference. If so, the fix
+is to inform RCU, perhaps by changing __cfq_exit_single_io_context() to
+take the struct request_queue "q" from cfq_exit_queue() as an argument,
+which would permit us to invoke rcu_dereference_protected as follows:
+
+ if (rcu_dereference_protected(ioc->ioc_data,
+ lockdep_is_held(&q->queue_lock)) == cic) {
+
+With this change, there would be no lockdep-RCU splat emitted if this
+code was invoked either from within an RCU read-side critical section
+or with the ->queue_lock held. In particular, this would have suppressed
+the above lockdep-RCU splat because ->queue_lock is held (see #2 in the
+list above).
+
+On the other hand, perhaps we really do need an RCU read-side critical
+section. In this case, the critical section must span the use of the
+return value from rcu_dereference(), or at least until there is some
+reference count incremented or some such. One way to handle this is to
+add rcu_read_lock() and rcu_read_unlock() as follows:
+
+ rcu_read_lock();
+ if (rcu_dereference(ioc->ioc_data) == cic) {
+ spin_lock(&ioc->lock);
+ rcu_assign_pointer(ioc->ioc_data, NULL);
+ spin_unlock(&ioc->lock);
+ }
+ rcu_read_unlock();
+
+With this change, the rcu_dereference() is always within an RCU
+read-side critical section, which again would have suppressed the
+above lockdep-RCU splat.
+
+But in this particular case, we don't actually deference the pointer
+returned from rcu_dereference(). Instead, that pointer is just compared
+to the cic pointer, which means that the rcu_dereference() can be replaced
+by rcu_access_pointer() as follows:
+
+ if (rcu_access_pointer(ioc->ioc_data) == cic) {
+
+Because it is legal to invoke rcu_access_pointer() without protection,
+this change would also suppress the above lockdep-RCU splat.
diff --git a/Documentation/RCU/lockdep.txt b/Documentation/RCU/lockdep.txt
index d7a49b2f6994..a102d4b3724b 100644
--- a/Documentation/RCU/lockdep.txt
+++ b/Documentation/RCU/lockdep.txt
@@ -32,9 +32,27 @@ checking of rcu_dereference() primitives:
srcu_dereference(p, sp):
Check for SRCU read-side critical section.
rcu_dereference_check(p, c):
- Use explicit check expression "c". This is useful in
- code that is invoked by both readers and updaters.
- rcu_dereference_raw(p)
+ Use explicit check expression "c" along with
+ rcu_read_lock_held(). This is useful in code that is
+ invoked by both RCU readers and updaters.
+ rcu_dereference_bh_check(p, c):
+ Use explicit check expression "c" along with
+ rcu_read_lock_bh_held(). This is useful in code that
+ is invoked by both RCU-bh readers and updaters.
+ rcu_dereference_sched_check(p, c):
+ Use explicit check expression "c" along with
+ rcu_read_lock_sched_held(). This is useful in code that
+ is invoked by both RCU-sched readers and updaters.
+ srcu_dereference_check(p, c):
+ Use explicit check expression "c" along with
+ srcu_read_lock_held()(). This is useful in code that
+ is invoked by both SRCU readers and updaters.
+ rcu_dereference_index_check(p, c):
+ Use explicit check expression "c", but the caller
+ must supply one of the rcu_read_lock_held() functions.
+ This is useful in code that uses RCU-protected arrays
+ that is invoked by both RCU readers and updaters.
+ rcu_dereference_raw(p):
Don't check. (Use sparingly, if at all.)
rcu_dereference_protected(p, c):
Use explicit check expression "c", and omit all barriers
@@ -48,13 +66,11 @@ checking of rcu_dereference() primitives:
value of the pointer itself, for example, against NULL.
The rcu_dereference_check() check expression can be any boolean
-expression, but would normally include one of the rcu_read_lock_held()
-family of functions and a lockdep expression. However, any boolean
-expression can be used. For a moderately ornate example, consider
-the following:
+expression, but would normally include a lockdep expression. However,
+any boolean expression can be used. For a moderately ornate example,
+consider the following:
file = rcu_dereference_check(fdt->fd[fd],
- rcu_read_lock_held() ||
lockdep_is_held(&files->file_lock) ||
atomic_read(&files->count) == 1);
@@ -62,7 +78,7 @@ This expression picks up the pointer "fdt->fd[fd]" in an RCU-safe manner,
and, if CONFIG_PROVE_RCU is configured, verifies that this expression
is used in:
-1. An RCU read-side critical section, or
+1. An RCU read-side critical section (implicit), or
2. with files->file_lock held, or
3. on an unshared files_struct.
diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt
index 5d9016795fd8..783d6c134d3f 100644
--- a/Documentation/RCU/torture.txt
+++ b/Documentation/RCU/torture.txt
@@ -42,7 +42,7 @@ fqs_holdoff Holdoff time (in microseconds) between consecutive calls
fqs_stutter Wait time (in seconds) between consecutive bursts
of calls to force_quiescent_state().
-irqreaders Says to invoke RCU readers from irq level. This is currently
+irqreader Says to invoke RCU readers from irq level. This is currently
done via timers. Defaults to "1" for variants of RCU that
permit this. (Or, more accurately, variants of RCU that do
-not- permit this know to ignore this variable.)
@@ -79,19 +79,68 @@ stutter The length of time to run the test before pausing for this
Specifying "stutter=0" causes the test to run continuously
without pausing, which is the old default behavior.
+test_boost Whether or not to test the ability of RCU to do priority
+ boosting. Defaults to "test_boost=1", which performs
+ RCU priority-inversion testing only if the selected
+ RCU implementation supports priority boosting. Specifying
+ "test_boost=0" never performs RCU priority-inversion
+ testing. Specifying "test_boost=2" performs RCU
+ priority-inversion testing even if the selected RCU
+ implementation does not support RCU priority boosting,
+ which can be used to test rcutorture's ability to
+ carry out RCU priority-inversion testing.
+
+test_boost_interval
+ The number of seconds in an RCU priority-inversion test
+ cycle. Defaults to "test_boost_interval=7". It is
+ usually wise for this value to be relatively prime to
+ the value selected for "stutter".
+
+test_boost_duration
+ The number of seconds to do RCU priority-inversion testing
+ within any given "test_boost_interval". Defaults to
+ "test_boost_duration=4".
+
test_no_idle_hz Whether or not to test the ability of RCU to operate in
a kernel that disables the scheduling-clock interrupt to
idle CPUs. Boolean parameter, "1" to test, "0" otherwise.
Defaults to omitting this test.
-torture_type The type of RCU to test: "rcu" for the rcu_read_lock() API,
- "rcu_sync" for rcu_read_lock() with synchronous reclamation,
- "rcu_bh" for the rcu_read_lock_bh() API, "rcu_bh_sync" for
- rcu_read_lock_bh() with synchronous reclamation, "srcu" for
- the "srcu_read_lock()" API, "sched" for the use of
- preempt_disable() together with synchronize_sched(),
- and "sched_expedited" for the use of preempt_disable()
- with synchronize_sched_expedited().
+torture_type The type of RCU to test, with string values as follows:
+
+ "rcu": rcu_read_lock(), rcu_read_unlock() and call_rcu().
+
+ "rcu_sync": rcu_read_lock(), rcu_read_unlock(), and
+ synchronize_rcu().
+
+ "rcu_expedited": rcu_read_lock(), rcu_read_unlock(), and
+ synchronize_rcu_expedited().
+
+ "rcu_bh": rcu_read_lock_bh(), rcu_read_unlock_bh(), and
+ call_rcu_bh().
+
+ "rcu_bh_sync": rcu_read_lock_bh(), rcu_read_unlock_bh(),
+ and synchronize_rcu_bh().
+
+ "rcu_bh_expedited": rcu_read_lock_bh(), rcu_read_unlock_bh(),
+ and synchronize_rcu_bh_expedited().
+
+ "srcu": srcu_read_lock(), srcu_read_unlock() and
+ synchronize_srcu().
+
+ "srcu_expedited": srcu_read_lock(), srcu_read_unlock() and
+ synchronize_srcu_expedited().
+
+ "sched": preempt_disable(), preempt_enable(), and
+ call_rcu_sched().
+
+ "sched_sync": preempt_disable(), preempt_enable(), and
+ synchronize_sched().
+
+ "sched_expedited": preempt_disable(), preempt_enable(), and
+ synchronize_sched_expedited().
+
+ Defaults to "rcu".
verbose Enable debug printk()s. Default is disabled.
@@ -100,12 +149,12 @@ OUTPUT
The statistics output is as follows:
- rcu-torture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
- rcu-torture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915
- rcu-torture: Reader Pipe: 1466408 9747 0 0 0 0 0 0 0 0 0
- rcu-torture: Reader Batch: 1464477 11678 0 0 0 0 0 0 0 0
- rcu-torture: Free-Block Circulation: 1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0
- rcu-torture: --- End of test
+ rcu-torture:--- Start of test: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4
+ rcu-torture: rtc: (null) ver: 155441 tfle: 0 rta: 155441 rtaf: 8884 rtf: 155440 rtmbe: 0 rtbke: 0 rtbre: 0 rtbf: 0 rtb: 0 nt: 3055767
+ rcu-torture: Reader Pipe: 727860534 34213 0 0 0 0 0 0 0 0 0
+ rcu-torture: Reader Batch: 727877838 17003 0 0 0 0 0 0 0 0 0
+ rcu-torture: Free-Block Circulation: 155440 155440 155440 155440 155440 155440 155440 155440 155440 155440 0
+ rcu-torture:--- End of test: SUCCESS: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4
The command "dmesg | grep torture:" will extract this information on
most systems. On more esoteric configurations, it may be necessary to
@@ -113,26 +162,55 @@ use other commands to access the output of the printk()s used by
the RCU torture test. The printk()s use KERN_ALERT, so they should
be evident. ;-)
+The first and last lines show the rcutorture module parameters, and the
+last line shows either "SUCCESS" or "FAILURE", based on rcutorture's
+automatic determination as to whether RCU operated correctly.
+
The entries are as follows:
o "rtc": The hexadecimal address of the structure currently visible
to readers.
-o "ver": The number of times since boot that the rcutw writer task
+o "ver": The number of times since boot that the RCU writer task
has changed the structure visible to readers.
o "tfle": If non-zero, indicates that the "torture freelist"
- containing structure to be placed into the "rtc" area is empty.
+ containing structures to be placed into the "rtc" area is empty.
This condition is important, since it can fool you into thinking
that RCU is working when it is not. :-/
o "rta": Number of structures allocated from the torture freelist.
o "rtaf": Number of allocations from the torture freelist that have
- failed due to the list being empty.
+ failed due to the list being empty. It is not unusual for this
+ to be non-zero, but it is bad for it to be a large fraction of
+ the value indicated by "rta".
o "rtf": Number of frees into the torture freelist.
+o "rtmbe": A non-zero value indicates that rcutorture believes that
+ rcu_assign_pointer() and rcu_dereference() are not working
+ correctly. This value should be zero.
+
+o "rtbke": rcutorture was unable to create the real-time kthreads
+ used to force RCU priority inversion. This value should be zero.
+
+o "rtbre": Although rcutorture successfully created the kthreads
+ used to force RCU priority inversion, it was unable to set them
+ to the real-time priority level of 1. This value should be zero.
+
+o "rtbf": The number of times that RCU priority boosting failed
+ to resolve RCU priority inversion.
+
+o "rtb": The number of times that rcutorture attempted to force
+ an RCU priority inversion condition. If you are testing RCU
+ priority boosting via the "test_boost" module parameter, this
+ value should be non-zero.
+
+o "nt": The number of times rcutorture ran RCU read-side code from
+ within a timer handler. This value should be non-zero only
+ if you specified the "irqreader" module parameter.
+
o "Reader Pipe": Histogram of "ages" of structures seen by readers.
If any entries past the first two are non-zero, RCU is broken.
And rcutorture prints the error flag string "!!!" to make sure
@@ -162,26 +240,15 @@ o "Free-Block Circulation": Shows the number of torture structures
somehow gets incremented farther than it should.
Different implementations of RCU can provide implementation-specific
-additional information. For example, SRCU provides the following:
+additional information. For example, SRCU provides the following
+additional line:
- srcu-torture: rtc: f8cf46a8 ver: 355 tfle: 0 rta: 356 rtaf: 0 rtf: 346 rtmbe: 0
- srcu-torture: Reader Pipe: 559738 939 0 0 0 0 0 0 0 0 0
- srcu-torture: Reader Batch: 560434 243 0 0 0 0 0 0 0 0
- srcu-torture: Free-Block Circulation: 355 354 353 352 351 350 349 348 347 346 0
srcu-torture: per-CPU(idx=1): 0(0,1) 1(0,1) 2(0,0) 3(0,1)
-The first four lines are similar to those for RCU. The last line shows
-the per-CPU counter state. The numbers in parentheses are the values
-of the "old" and "current" counters for the corresponding CPU. The
-"idx" value maps the "old" and "current" values to the underlying array,
-and is useful for debugging.
-
-Similarly, sched_expedited RCU provides the following:
-
- sched_expedited-torture: rtc: d0000000016c1880 ver: 1090796 tfle: 0 rta: 1090796 rtaf: 0 rtf: 1090787 rtmbe: 0 nt: 27713319
- sched_expedited-torture: Reader Pipe: 12660320201 95875 0 0 0 0 0 0 0 0 0
- sched_expedited-torture: Reader Batch: 12660424885 0 0 0 0 0 0 0 0 0 0
- sched_expedited-torture: Free-Block Circulation: 1090795 1090795 1090794 1090793 1090792 1090791 1090790 1090789 1090788 1090787 0
+This line shows the per-CPU counter state. The numbers in parentheses are
+the values of the "old" and "current" counters for the corresponding CPU.
+The "idx" value maps the "old" and "current" values to the underlying
+array, and is useful for debugging.
USAGE
diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt
index 8173cec473aa..aaf65f6c6cd7 100644
--- a/Documentation/RCU/trace.txt
+++ b/Documentation/RCU/trace.txt
@@ -33,23 +33,23 @@ rcu/rcuboost:
The output of "cat rcu/rcudata" looks as follows:
rcu_sched:
- 0 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=545/1/0 df=50 of=0 ri=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0
- 1 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=967/1/0 df=58 of=0 ri=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0
- 2 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1081/1/0 df=175 of=0 ri=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0
- 3 c=20942 g=20943 pq=1 pqc=20942 qp=1 dt=1846/0/0 df=404 of=0 ri=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0
- 4 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=369/1/0 df=83 of=0 ri=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0
- 5 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=381/1/0 df=64 of=0 ri=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0
- 6 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1037/1/0 df=183 of=0 ri=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0
- 7 c=20897 g=20897 pq=1 pqc=20896 qp=0 dt=1572/0/0 df=382 of=0 ri=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0
+ 0 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=545/1/0 df=50 of=0 ri=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0
+ 1 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=967/1/0 df=58 of=0 ri=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0
+ 2 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=1081/1/0 df=175 of=0 ri=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0
+ 3 c=20942 g=20943 pq=1 pgp=20942 qp=1 dt=1846/0/0 df=404 of=0 ri=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0
+ 4 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=369/1/0 df=83 of=0 ri=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0
+ 5 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=381/1/0 df=64 of=0 ri=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0
+ 6 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=1037/1/0 df=183 of=0 ri=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0
+ 7 c=20897 g=20897 pq=1 pgp=20896 qp=0 dt=1572/0/0 df=382 of=0 ri=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0
rcu_bh:
- 0 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=545/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0
- 1 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=967/1/0 df=3 of=0 ri=1 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0
- 2 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1081/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0
- 3 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1846/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0
- 4 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=369/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0
- 5 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=381/1/0 df=4 of=0 ri=1 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0
- 6 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1037/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0
- 7 c=1474 g=1474 pq=1 pqc=1473 qp=0 dt=1572/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0
+ 0 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=545/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0
+ 1 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=967/1/0 df=3 of=0 ri=1 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0
+ 2 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1081/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0
+ 3 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1846/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0
+ 4 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=369/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0
+ 5 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=381/1/0 df=4 of=0 ri=1 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0
+ 6 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1037/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0
+ 7 c=1474 g=1474 pq=1 pgp=1473 qp=0 dt=1572/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0
The first section lists the rcu_data structures for rcu_sched, the second
for rcu_bh. Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
@@ -84,7 +84,7 @@ o "pq" indicates that this CPU has passed through a quiescent state
CPU has not yet reported that fact, (2) some other CPU has not
yet reported for this grace period, or (3) both.
-o "pqc" indicates which grace period the last-observed quiescent
+o "pgp" indicates which grace period the last-observed quiescent
state for this CPU corresponds to. This is important for handling
the race between CPU 0 reporting an extended dynticks-idle
quiescent state for CPU 1 and CPU 1 suddenly waking up and
@@ -184,10 +184,14 @@ o "kt" is the per-CPU kernel-thread state. The digit preceding
The number after the final slash is the CPU that the kthread
is actually running on.
+ This field is displayed only for CONFIG_RCU_BOOST kernels.
+
o "ktl" is the low-order 16 bits (in hexadecimal) of the count of
the number of times that this CPU's per-CPU kthread has gone
through its loop servicing invoke_rcu_cpu_kthread() requests.
+ This field is displayed only for CONFIG_RCU_BOOST kernels.
+
o "b" is the batch limit for this CPU. If more than this number
of RCU callbacks is ready to invoke, then the remainder will
be deferred.
diff --git a/Documentation/blackfin/bfin-gpio-notes.txt b/Documentation/blackfin/bfin-gpio-notes.txt
index f731c1e56475..d36b01f778b9 100644
--- a/Documentation/blackfin/bfin-gpio-notes.txt
+++ b/Documentation/blackfin/bfin-gpio-notes.txt
@@ -1,5 +1,5 @@
/*
- * File: Documentation/blackfin/bfin-gpio-note.txt
+ * File: Documentation/blackfin/bfin-gpio-notes.txt
* Based on:
* Author:
*
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index c6d84cfd2f56..e418dc0a7086 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -186,7 +186,7 @@ a virtual address mapping (unlike the earlier scheme of virtual address
do not have a corresponding kernel virtual address space mapping) and
low-memory pages.
-Note: Please refer to Documentation/PCI/PCI-DMA-mapping.txt for a discussion
+Note: Please refer to Documentation/DMA-API-HOWTO.txt for a discussion
on PCI high mem DMA aspects and mapping of scatter gather lists, and support
for 64 bit PCI.
diff --git a/Documentation/bus-virt-phys-mapping.txt b/Documentation/bus-virt-phys-mapping.txt
index 1b5aa10df845..2bc55ff3b4d1 100644
--- a/Documentation/bus-virt-phys-mapping.txt
+++ b/Documentation/bus-virt-phys-mapping.txt
@@ -1,6 +1,6 @@
[ NOTE: The virt_to_bus() and bus_to_virt() functions have been
superseded by the functionality provided by the PCI DMA interface
- (see Documentation/PCI/PCI-DMA-mapping.txt). They continue
+ (see Documentation/DMA-API-HOWTO.txt). They continue
to be documented below for historical purposes, but new code
must not use them. --davidm 00/12/12 ]
diff --git a/Documentation/cdrom/packet-writing.txt b/Documentation/cdrom/packet-writing.txt
index 13c251d5add6..2834170d821e 100644
--- a/Documentation/cdrom/packet-writing.txt
+++ b/Documentation/cdrom/packet-writing.txt
@@ -109,7 +109,7 @@ this interface. (see http://tom.ist-im-web.de/download/pktcdvd )
For a description of the sysfs interface look into the file:
- Documentation/ABI/testing/sysfs-block-pktcdvd
+ Documentation/ABI/testing/sysfs-class-pktcdvd
Using the pktcdvd debugfs interface
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index 06eb6d957c83..cc0ebc5241b3 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -418,7 +418,6 @@ total_unevictable - sum of all children's "unevictable"
# The following additional stats are dependent on CONFIG_DEBUG_VM.
-inactive_ratio - VM internal parameter. (see mm/page_alloc.c)
recent_rotated_anon - VM internal parameter. (see mm/vmscan.c)
recent_rotated_file - VM internal parameter. (see mm/vmscan.c)
recent_scanned_anon - VM internal parameter. (see mm/vmscan.c)
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index e74d0a2eb1cf..d221781dabaa 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -132,7 +132,7 @@ The sampling rate is limited by the HW transition latency:
transition_latency * 100
Or by kernel restrictions:
If CONFIG_NO_HZ is set, the limit is 10ms fixed.
-If CONFIG_NO_HZ is not set or no_hz=off boot parameter is used, the
+If CONFIG_NO_HZ is not set or nohz=off boot parameter is used, the
limits depend on the CONFIG_HZ option:
HZ=1000: min=20000us (20ms)
HZ=250: min=80000us (80ms)
diff --git a/Documentation/development-process/4.Coding b/Documentation/development-process/4.Coding
index 83f5f5b365a3..e3cb6a56653a 100644
--- a/Documentation/development-process/4.Coding
+++ b/Documentation/development-process/4.Coding
@@ -278,7 +278,7 @@ enabled, a configurable percentage of memory allocations will be made to
fail; these failures can be restricted to a specific range of code.
Running with fault injection enabled allows the programmer to see how the
code responds when things go badly. See
-Documentation/fault-injection/fault-injection.text for more information on
+Documentation/fault-injection/fault-injection.txt for more information on
how to use this facility.
Other kinds of errors can be found with the "sparse" static analysis tool.
diff --git a/Documentation/device-mapper/dm-log.txt b/Documentation/device-mapper/dm-log.txt
index 994dd75475a6..c155ac569c44 100644
--- a/Documentation/device-mapper/dm-log.txt
+++ b/Documentation/device-mapper/dm-log.txt
@@ -48,7 +48,7 @@ kernel and userspace, 'connector' is used as the interface for
communication.
There are currently two userspace log implementations that leverage this
-framework - "clustered_disk" and "clustered_core". These implementations
+framework - "clustered-disk" and "clustered-core". These implementations
provide a cluster-coherent log for shared-storage. Device-mapper mirroring
can be used in a shared-storage environment when the cluster log implementations
are employed.
diff --git a/Documentation/device-mapper/persistent-data.txt b/Documentation/device-mapper/persistent-data.txt
new file mode 100644
index 000000000000..0e5df9b04ad2
--- /dev/null
+++ b/Documentation/device-mapper/persistent-data.txt
@@ -0,0 +1,84 @@
+Introduction
+============
+
+The more-sophisticated device-mapper targets require complex metadata
+that is managed in kernel. In late 2010 we were seeing that various
+different targets were rolling their own data strutures, for example:
+
+- Mikulas Patocka's multisnap implementation
+- Heinz Mauelshagen's thin provisioning target
+- Another btree-based caching target posted to dm-devel
+- Another multi-snapshot target based on a design of Daniel Phillips
+
+Maintaining these data structures takes a lot of work, so if possible
+we'd like to reduce the number.
+
+The persistent-data library is an attempt to provide a re-usable
+framework for people who want to store metadata in device-mapper
+targets. It's currently used by the thin-provisioning target and an
+upcoming hierarchical storage target.
+
+Overview
+========
+
+The main documentation is in the header files which can all be found
+under drivers/md/persistent-data.
+
+The block manager
+-----------------
+
+dm-block-manager.[hc]
+
+This provides access to the data on disk in fixed sized-blocks. There
+is a read/write locking interface to prevent concurrent accesses, and
+keep data that is being used in the cache.
+
+Clients of persistent-data are unlikely to use this directly.
+
+The transaction manager
+-----------------------
+
+dm-transaction-manager.[hc]
+
+This restricts access to blocks and enforces copy-on-write semantics.
+The only way you can get hold of a writable block through the
+transaction manager is by shadowing an existing block (ie. doing
+copy-on-write) or allocating a fresh one. Shadowing is elided within
+the same transaction so performance is reasonable. The commit method
+ensures that all data is flushed before it writes the superblock.
+On power failure your metadata will be as it was when last committed.
+
+The Space Maps
+--------------
+
+dm-space-map.h
+dm-space-map-metadata.[hc]
+dm-space-map-disk.[hc]
+
+On-disk data structures that keep track of reference counts of blocks.
+Also acts as the allocator of new blocks. Currently two
+implementations: a simpler one for managing blocks on a different
+device (eg. thinly-provisioned data blocks); and one for managing
+the metadata space. The latter is complicated by the need to store
+its own data within the space it's managing.
+
+The data structures
+-------------------
+
+dm-btree.[hc]
+dm-btree-remove.c
+dm-btree-spine.c
+dm-btree-internal.h
+
+Currently there is only one data structure, a hierarchical btree.
+There are plans to add more. For example, something with an
+array-like interface would see a lot of use.
+
+The btree is 'hierarchical' in that you can define it to be composed
+of nested btrees, and take multiple keys. For example, the
+thin-provisioning target uses a btree with two levels of nesting.
+The first maps a device id to a mapping tree, and that in turn maps a
+virtual block to a physical block.
+
+Values stored in the btrees can have arbitrary size. Keys are always
+64bits, although nesting allows you to use multiple keys.
diff --git a/Documentation/device-mapper/thin-provisioning.txt b/Documentation/device-mapper/thin-provisioning.txt
new file mode 100644
index 000000000000..801d9d1cf82b
--- /dev/null
+++ b/Documentation/device-mapper/thin-provisioning.txt
@@ -0,0 +1,285 @@
+Introduction
+============
+
+This document descibes a collection of device-mapper targets that
+between them implement thin-provisioning and snapshots.
+
+The main highlight of this implementation, compared to the previous
+implementation of snapshots, is that it allows many virtual devices to
+be stored on the same data volume. This simplifies administration and
+allows the sharing of data between volumes, thus reducing disk usage.
+
+Another significant feature is support for an arbitrary depth of
+recursive snapshots (snapshots of snapshots of snapshots ...). The
+previous implementation of snapshots did this by chaining together
+lookup tables, and so performance was O(depth). This new
+implementation uses a single data structure to avoid this degradation
+with depth. Fragmentation may still be an issue, however, in some
+scenarios.
+
+Metadata is stored on a separate device from data, giving the
+administrator some freedom, for example to:
+
+- Improve metadata resilience by storing metadata on a mirrored volume
+ but data on a non-mirrored one.
+
+- Improve performance by storing the metadata on SSD.
+
+Status
+======
+
+These targets are very much still in the EXPERIMENTAL state. Please
+do not yet rely on them in production. But do experiment and offer us
+feedback. Different use cases will have different performance
+characteristics, for example due to fragmentation of the data volume.
+
+If you find this software is not performing as expected please mail
+dm-devel@redhat.com with details and we'll try our best to improve
+things for you.
+
+Userspace tools for checking and repairing the metadata are under
+development.
+
+Cookbook
+========
+
+This section describes some quick recipes for using thin provisioning.
+They use the dmsetup program to control the device-mapper driver
+directly. End users will be advised to use a higher-level volume
+manager such as LVM2 once support has been added.
+
+Pool device
+-----------
+
+The pool device ties together the metadata volume and the data volume.
+It maps I/O linearly to the data volume and updates the metadata via
+two mechanisms:
+
+- Function calls from the thin targets
+
+- Device-mapper 'messages' from userspace which control the creation of new
+ virtual devices amongst other things.
+
+Setting up a fresh pool device
+------------------------------
+
+Setting up a pool device requires a valid metadata device, and a
+data device. If you do not have an existing metadata device you can
+make one by zeroing the first 4k to indicate empty metadata.
+
+ dd if=/dev/zero of=$metadata_dev bs=4096 count=1
+
+The amount of metadata you need will vary according to how many blocks
+are shared between thin devices (i.e. through snapshots). If you have
+less sharing than average you'll need a larger-than-average metadata device.
+
+As a guide, we suggest you calculate the number of bytes to use in the
+metadata device as 48 * $data_dev_size / $data_block_size but round it up
+to 2MB if the answer is smaller. The largest size supported is 16GB.
+
+If you're creating large numbers of snapshots which are recording large
+amounts of change, you may need find you need to increase this.
+
+Reloading a pool table
+----------------------
+
+You may reload a pool's table, indeed this is how the pool is resized
+if it runs out of space. (N.B. While specifying a different metadata
+device when reloading is not forbidden at the moment, things will go
+wrong if it does not route I/O to exactly the same on-disk location as
+previously.)
+
+Using an existing pool device
+-----------------------------
+
+ dmsetup create pool \
+ --table "0 20971520 thin-pool $metadata_dev $data_dev \
+ $data_block_size $low_water_mark"
+
+$data_block_size gives the smallest unit of disk space that can be
+allocated at a time expressed in units of 512-byte sectors. People
+primarily interested in thin provisioning may want to use a value such
+as 1024 (512KB). People doing lots of snapshotting may want a smaller value
+such as 128 (64KB). If you are not zeroing newly-allocated data,
+a larger $data_block_size in the region of 256000 (128MB) is suggested.
+$data_block_size must be the same for the lifetime of the
+metadata device.
+
+$low_water_mark is expressed in blocks of size $data_block_size. If
+free space on the data device drops below this level then a dm event
+will be triggered which a userspace daemon should catch allowing it to
+extend the pool device. Only one such event will be sent.
+Resuming a device with a new table itself triggers an event so the
+userspace daemon can use this to detect a situation where a new table
+already exceeds the threshold.
+
+Thin provisioning
+-----------------
+
+i) Creating a new thinly-provisioned volume.
+
+ To create a new thinly- provisioned volume you must send a message to an
+ active pool device, /dev/mapper/pool in this example.
+
+ dmsetup message /dev/mapper/pool 0 "create_thin 0"
+
+ Here '0' is an identifier for the volume, a 24-bit number. It's up
+ to the caller to allocate and manage these identifiers. If the
+ identifier is already in use, the message will fail with -EEXIST.
+
+ii) Using a thinly-provisioned volume.
+
+ Thinly-provisioned volumes are activated using the 'thin' target:
+
+ dmsetup create thin --table "0 2097152 thin /dev/mapper/pool 0"
+
+ The last parameter is the identifier for the thinp device.
+
+Internal snapshots
+------------------
+
+i) Creating an internal snapshot.
+
+ Snapshots are created with another message to the pool.
+
+ N.B. If the origin device that you wish to snapshot is active, you
+ must suspend it before creating the snapshot to avoid corruption.
+ This is NOT enforced at the moment, so please be careful!
+
+ dmsetup suspend /dev/mapper/thin
+ dmsetup message /dev/mapper/pool 0 "create_snap 1 0"
+ dmsetup resume /dev/mapper/thin
+
+ Here '1' is the identifier for the volume, a 24-bit number. '0' is the
+ identifier for the origin device.
+
+ii) Using an internal snapshot.
+
+ Once created, the user doesn't have to worry about any connection
+ between the origin and the snapshot. Indeed the snapshot is no
+ different from any other thinly-provisioned device and can be
+ snapshotted itself via the same method. It's perfectly legal to
+ have only one of them active, and there's no ordering requirement on
+ activating or removing them both. (This differs from conventional
+ device-mapper snapshots.)
+
+ Activate it exactly the same way as any other thinly-provisioned volume:
+
+ dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 1"
+
+Deactivation
+------------
+
+All devices using a pool must be deactivated before the pool itself
+can be.
+
+ dmsetup remove thin
+ dmsetup remove snap
+ dmsetup remove pool
+
+Reference
+=========
+
+'thin-pool' target
+------------------
+
+i) Constructor
+
+ thin-pool <metadata dev> <data dev> <data block size (sectors)> \
+ <low water mark (blocks)> [<number of feature args> [<arg>]*]
+
+ Optional feature arguments:
+ - 'skip_block_zeroing': skips the zeroing of newly-provisioned blocks.
+
+ Data block size must be between 64KB (128 sectors) and 1GB
+ (2097152 sectors) inclusive.
+
+
+ii) Status
+
+ <transaction id> <used metadata blocks>/<total metadata blocks>
+ <used data blocks>/<total data blocks> <held metadata root>
+
+
+ transaction id:
+ A 64-bit number used by userspace to help synchronise with metadata
+ from volume managers.
+
+ used data blocks / total data blocks
+ If the number of free blocks drops below the pool's low water mark a
+ dm event will be sent to userspace. This event is edge-triggered and
+ it will occur only once after each resume so volume manager writers
+ should register for the event and then check the target's status.
+
+ held metadata root:
+ The location, in sectors, of the metadata root that has been
+ 'held' for userspace read access. '-' indicates there is no
+ held root. This feature is not yet implemented so '-' is
+ always returned.
+
+iii) Messages
+
+ create_thin <dev id>
+
+ Create a new thinly-provisioned device.
+ <dev id> is an arbitrary unique 24-bit identifier chosen by
+ the caller.
+
+ create_snap <dev id> <origin id>
+
+ Create a new snapshot of another thinly-provisioned device.
+ <dev id> is an arbitrary unique 24-bit identifier chosen by
+ the caller.
+ <origin id> is the identifier of the thinly-provisioned device
+ of which the new device will be a snapshot.
+
+ delete <dev id>
+
+ Deletes a thin device. Irreversible.
+
+ trim <dev id> <new size in sectors>
+
+ Delete mappings from the end of a thin device. Irreversible.
+ You might want to use this if you're reducing the size of
+ your thinly-provisioned device. In many cases, due to the
+ sharing of blocks between devices, it is not possible to
+ determine in advance how much space 'trim' will release. (In
+ future a userspace tool might be able to perform this
+ calculation.)
+
+ set_transaction_id <current id> <new id>
+
+ Userland volume managers, such as LVM, need a way to
+ synchronise their external metadata with the internal metadata of the
+ pool target. The thin-pool target offers to store an
+ arbitrary 64-bit transaction id and return it on the target's
+ status line. To avoid races you must provide what you think
+ the current transaction id is when you change it with this
+ compare-and-swap message.
+
+'thin' target
+-------------
+
+i) Constructor
+
+ thin <pool dev> <dev id>
+
+ pool dev:
+ the thin-pool device, e.g. /dev/mapper/my_pool or 253:0
+
+ dev id:
+ the internal device identifier of the device to be
+ activated.
+
+The pool doesn't store any size against the thin devices. If you
+load a thin target that is smaller than you've been using previously,
+then you'll have no access to blocks mapped beyond the end. If you
+load a target that is bigger than before, then extra blocks will be
+provisioned as and when needed.
+
+If you wish to reduce the size of your thin device and potentially
+regain some space then send the 'trim' message to the pool.
+
+ii) Status
+
+ <nr mapped sectors> <highest mapped sector>
diff --git a/Documentation/devicetree/bindings/arm/calxeda.txt b/Documentation/devicetree/bindings/arm/calxeda.txt
new file mode 100644
index 000000000000..4755caaccba6
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/calxeda.txt
@@ -0,0 +1,8 @@
+Calxeda Highbank Platforms Device Tree Bindings
+-----------------------------------------------
+
+Boards with Calxeda Cortex-A9 based Highbank SOC shall have the following
+properties.
+
+Required root node properties:
+ - compatible = "calxeda,highbank";
diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
new file mode 100644
index 000000000000..c9848ad0e2e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -0,0 +1,26 @@
+Freescale i.MX Platforms Device Tree Bindings
+-----------------------------------------------
+
+i.MX51 Babbage Board
+Required root node properties:
+ - compatible = "fsl,imx51-babbage", "fsl,imx51";
+
+i.MX53 Automotive Reference Design Board
+Required root node properties:
+ - compatible = "fsl,imx53-ard", "fsl,imx53";
+
+i.MX53 Evaluation Kit
+Required root node properties:
+ - compatible = "fsl,imx53-evk", "fsl,imx53";
+
+i.MX53 Quick Start Board
+Required root node properties:
+ - compatible = "fsl,imx53-qsb", "fsl,imx53";
+
+i.MX53 Smart Mobile Reference Design Board
+Required root node properties:
+ - compatible = "fsl,imx53-smd", "fsl,imx53";
+
+i.MX6 Quad SABRE Automotive Board
+Required root node properties:
+ - compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
new file mode 100644
index 000000000000..52916b4aa1fe
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -0,0 +1,55 @@
+* ARM Generic Interrupt Controller
+
+ARM SMP cores are often associated with a GIC, providing per processor
+interrupts (PPI), shared processor interrupts (SPI) and software
+generated interrupts (SGI).
+
+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
+Secondary GICs are cascaded into the upward interrupt controller and do not
+have PPIs or SGIs.
+
+Main node required properties:
+
+- compatible : should be one of:
+ "arm,cortex-a9-gic"
+ "arm,arm11mp-gic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+ interrupt source. The type shall be a <u32> and the value shall be 3.
+
+ The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+ interrupts.
+
+ The 2nd cell contains the interrupt number for the interrupt type.
+ SPI interrupts are in the range [0-987]. PPI interrupts are in the
+ range [0-15].
+
+ The 3rd cell is the flags, encoded as follows:
+ bits[3:0] trigger type and level flags.
+ 1 = low-to-high edge triggered
+ 2 = high-to-low edge triggered
+ 4 = active high level-sensitive
+ 8 = active low level-sensitive
+ bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of
+ the 8 possible cpus attached to the GIC. A bit set to '1' indicated
+ the interrupt is wired to that CPU. Only valid for PPI interrupts.
+
+- reg : Specifies base physical address(s) and size of the GIC registers. The
+ first region is the GIC distributor register base and size. The 2nd region is
+ the GIC cpu interface register base and size.
+
+Optional
+- interrupts : Interrupt source of the parent interrupt controller. Only
+ present on secondary GICs.
+
+Example:
+
+ intc: interrupt-controller@fff11000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ interrupt-controller;
+ reg = <0xfff11000 0x1000>,
+ <0xfff10100 0x100>;
+ };
+
diff --git a/Documentation/devicetree/bindings/arm/l2cc.txt b/Documentation/devicetree/bindings/arm/l2cc.txt
new file mode 100644
index 000000000000..7ca52161e7ab
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/l2cc.txt
@@ -0,0 +1,44 @@
+* ARM L2 Cache Controller
+
+ARM cores often have a separate level 2 cache controller. There are various
+implementations of the L2 cache controller with compatible programming models.
+The ARM L2 cache representation in the device tree should be done as follows:
+
+Required properties:
+
+- compatible : should be one of:
+ "arm,pl310-cache"
+ "arm,l220-cache"
+ "arm,l210-cache"
+- cache-unified : Specifies the cache is a unified cache.
+- cache-level : Should be set to 2 for a level 2 cache.
+- reg : Physical base address and size of cache controller's memory mapped
+ registers.
+
+Optional properties:
+
+- arm,data-latency : Cycles of latency for Data RAM accesses. Specifies 3 cells of
+ read, write and setup latencies. Minimum valid values are 1. Controllers
+ without setup latency control should use a value of 0.
+- arm,tag-latency : Cycles of latency for Tag RAM accesses. Specifies 3 cells of
+ read, write and setup latencies. Controllers without setup latency control
+ should use 0. Controllers without separate read and write Tag RAM latency
+ values should only use the first cell.
+- arm,dirty-latency : Cycles of latency for Dirty RAMs. This is a single cell.
+- arm,filter-ranges : <start length> Starting address and length of window to
+ filter. Addresses in the filter window are directed to the M1 port. Other
+ addresses will go to the M0 port.
+- interrupts : 1 combined interrupt.
+
+Example:
+
+L2: cache-controller {
+ compatible = "arm,pl310-cache";
+ reg = <0xfff12000 0x1000>;
+ arm,data-latency = <1 1 1>;
+ arm,tag-latency = <2 2 2>;
+ arm,filter-latency = <0x80000000 0x8000000>;
+ cache-unified;
+ cache-level = <2>;
+ interrupts = <45>;
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/dsp.txt b/Documentation/devicetree/bindings/arm/omap/dsp.txt
new file mode 100644
index 000000000000..d3830a32ce08
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/dsp.txt
@@ -0,0 +1,14 @@
+* TI - DSP (Digital Signal Processor)
+
+TI DSP included in OMAP SoC
+
+Required properties:
+- compatible : Should be "ti,omap3-c64" for OMAP3 & 4
+- ti,hwmods: "dsp"
+
+Examples:
+
+dsp {
+ compatible = "ti,omap3-c64";
+ ti,hwmods = "dsp";
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/iva.txt b/Documentation/devicetree/bindings/arm/omap/iva.txt
new file mode 100644
index 000000000000..6d6295171358
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/iva.txt
@@ -0,0 +1,19 @@
+* TI - IVA (Imaging and Video Accelerator) subsystem
+
+The IVA contain various audio, video or imaging HW accelerator
+depending of the version.
+
+Required properties:
+- compatible : Should be:
+ - "ti,ivahd" for OMAP4
+ - "ti,iva2.2" for OMAP3
+ - "ti,iva2.1" for OMAP2430
+ - "ti,iva1" for OMAP2420
+- ti,hwmods: "iva"
+
+Examples:
+
+iva {
+ compatible = "ti,ivahd", "ti,iva";
+ ti,hwmods = "iva";
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
new file mode 100644
index 000000000000..6888a5efc860
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
@@ -0,0 +1,19 @@
+* TI - L3 Network On Chip (NoC)
+
+This version is an implementation of the generic NoC IP
+provided by Arteris.
+
+Required properties:
+- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
+ Should be "ti,omap4-l3-noc" for OMAP4 family
+- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.
+
+Examples:
+
+ocp {
+ compatible = "ti,omap4-l3-noc", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/mpu.txt b/Documentation/devicetree/bindings/arm/omap/mpu.txt
new file mode 100644
index 000000000000..1a5a42ce21bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/mpu.txt
@@ -0,0 +1,27 @@
+* TI - MPU (Main Processor Unit) subsystem
+
+The MPU subsystem contain one or several ARM cores
+depending of the version.
+The MPU contain CPUs, GIC, L2 cache and a local PRCM.
+
+Required properties:
+- compatible : Should be "ti,omap3-mpu" for OMAP3
+ Should be "ti,omap4-mpu" for OMAP4
+- ti,hwmods: "mpu"
+
+Examples:
+
+- For an OMAP4 SMP system:
+
+mpu {
+ compatible = "ti,omap4-mpu";
+ ti,hwmods = "mpu";
+};
+
+
+- For an OMAP3 monocore system:
+
+mpu {
+ compatible = "ti,omap3-mpu";
+ ti,hwmods = "mpu";
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
new file mode 100644
index 000000000000..dbdab40ed3a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -0,0 +1,43 @@
+* Texas Instruments OMAP
+
+OMAP is currently using a static file per SoC family to describe the
+IPs present in the SoC.
+On top of that an omap_device is created to extend the platform_device
+capabilities and to allow binding with one or several hwmods.
+The hwmods will contain all the information to build the device:
+adresse range, irq lines, dma lines, interconnect, PRCM register,
+clock domain, input clocks.
+For the moment just point to the existing hwmod, the next step will be
+to move data from hwmod to device-tree representation.
+
+
+Required properties:
+- compatible: Every devices present in OMAP SoC should be in the
+ form: "ti,XXX"
+- ti,hwmods: list of hwmod names (ascii strings), that comes from the OMAP
+ HW documentation, attached to a device. Must contain at least
+ one hwmod.
+
+Optional properties:
+- ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
+ during suspend.
+
+
+Example:
+
+spinlock@1 {
+ compatible = "ti,omap4-spinlock";
+ ti,hwmods = "spinlock";
+};
+
+
+Boards:
+
+- OMAP3 BeagleBoard : Low cost community board
+ compatible = "ti,omap3-beagle", "ti,omap3"
+
+- OMAP4 SDP : Software Developement Board
+ compatible = "ti,omap4-sdp", "ti,omap4430"
+
+- OMAP4 PandaBoard : Low cost community board
+ compatible = "ti,omap4-panda", "ti,omap4430"
diff --git a/Documentation/devicetree/bindings/arm/picoxcell.txt b/Documentation/devicetree/bindings/arm/picoxcell.txt
new file mode 100644
index 000000000000..e75c0ef51e69
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/picoxcell.txt
@@ -0,0 +1,24 @@
+Picochip picoXcell device tree bindings.
+========================================
+
+Required root node properties:
+ - compatible:
+ - "picochip,pc7302-pc3x3" : PC7302 development board with PC3X3 device.
+ - "picochip,pc7302-pc3x2" : PC7302 development board with PC3X2 device.
+ - "picochip,pc3x3" : picoXcell PC3X3 device based board.
+ - "picochip,pc3x2" : picoXcell PC3X2 device based board.
+
+Timers required properties:
+ - compatible = "picochip,pc3x2-timer"
+ - interrupts : The single IRQ line for the timer.
+ - clock-freq : The frequency in HZ of the timer.
+ - reg : The register bank for the timer.
+
+Note: two timers are required - one for the scheduler clock and one for the
+event tick/NOHZ.
+
+VIC required properties:
+ - compatible = "arm,pl192-vic".
+ - interrupt-controller.
+ - reg : The register bank for the device.
+ - #interrupt-cells : Must be 1.
diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Documentation/devicetree/bindings/arm/primecell.txt
index 1d5d7a870ec7..951ca46789d4 100644
--- a/Documentation/devicetree/bindings/arm/primecell.txt
+++ b/Documentation/devicetree/bindings/arm/primecell.txt
@@ -6,7 +6,9 @@ driver matching.
Required properties:
-- compatible : should be a specific value for peripheral and "arm,primecell"
+- compatible : should be a specific name for the peripheral and
+ "arm,primecell". The specific name will match the ARM
+ engineering name for the logic block in the form: "arm,pl???"
Optional properties:
diff --git a/Documentation/devicetree/bindings/crypto/picochip-spacc.txt b/Documentation/devicetree/bindings/crypto/picochip-spacc.txt
new file mode 100644
index 000000000000..d8609ece1f4c
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/picochip-spacc.txt
@@ -0,0 +1,23 @@
+Picochip picoXcell SPAcc (Security Protocol Accelerator) bindings
+
+Picochip picoXcell devices contain crypto offload engines that may be used for
+IPSEC and femtocell layer 2 ciphering.
+
+Required properties:
+ - compatible : "picochip,spacc-ipsec" for the IPSEC offload engine
+ "picochip,spacc-l2" for the femtocell layer 2 ciphering engine.
+ - reg : Offset and length of the register set for this device
+ - interrupt-parent : The interrupt controller that controls the SPAcc
+ interrupt.
+ - interrupts : The interrupt line from the SPAcc.
+ - ref-clock : The input clock that drives the SPAcc.
+
+Example SPAcc node:
+
+spacc@10000 {
+ compatible = "picochip,spacc-ipsec";
+ reg = <0x100000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <24>;
+ ref-clock = <&ipsec_clk>, "ref";
+};
diff --git a/Documentation/devicetree/bindings/gpio/led.txt b/Documentation/devicetree/bindings/gpio/led.txt
index 064db928c3c1..141087cf3107 100644
--- a/Documentation/devicetree/bindings/gpio/led.txt
+++ b/Documentation/devicetree/bindings/gpio/led.txt
@@ -8,7 +8,7 @@ node's name represents the name of the corresponding LED.
LED sub-node properties:
- gpios : Should specify the LED's GPIO, see "Specifying GPIO information
- for devices" in Documentation/powerpc/booting-without-of.txt. Active
+ for devices" in Documentation/devicetree/booting-without-of.txt. Active
low LEDs should be indicated using flags in the GPIO specifier.
- label : (optional) The label for this LED. If omitted, the label is
taken from the node name (excluding the unit address).
diff --git a/Documentation/devicetree/bindings/gpio/pl061-gpio.txt b/Documentation/devicetree/bindings/gpio/pl061-gpio.txt
new file mode 100644
index 000000000000..a2c416bcbccc
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/pl061-gpio.txt
@@ -0,0 +1,10 @@
+ARM PL061 GPIO controller
+
+Required properties:
+- compatible : "arm,pl061", "arm,primecell"
+- #gpio-cells : Should be two. The first cell is the pin number and the
+ second cell is used to specify optional parameters:
+ - bit 0 specifies polarity (0 for normal, 1 for inverted)
+- gpio-controller : Marks the device node as a GPIO controller.
+- interrupts : Interrupt mapping for GPIO IRQ.
+
diff --git a/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt b/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
new file mode 100644
index 000000000000..f3cf43b66f7e
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
@@ -0,0 +1,25 @@
+* Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX
+
+Required properties:
+- compatible : Should be "fsl,<chip>-i2c"
+- reg : Should contain I2C/HS-I2C registers location and length
+- interrupts : Should contain I2C/HS-I2C interrupt
+
+Optional properties:
+- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
+ The absence of the propoerty indicates the default frequency 100 kHz.
+
+Examples:
+
+i2c@83fc4000 { /* I2C2 on i.MX51 */
+ compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+ reg = <0x83fc4000 0x4000>;
+ interrupts = <63>;
+};
+
+i2c@70038000 { /* HS-I2C on i.MX51 */
+ compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+ reg = <0x70038000 0x4000>;
+ interrupts = <64>;
+ clock-frequency = <400000>;
+};
diff --git a/Documentation/devicetree/bindings/i2c/samsung-i2c.txt b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt
new file mode 100644
index 000000000000..38832c712919
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt
@@ -0,0 +1,39 @@
+* Samsung's I2C controller
+
+The Samsung's I2C controller is used to interface with I2C devices.
+
+Required properties:
+ - compatible: value should be either of the following.
+ (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c.
+ (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
+ - reg: physical base address of the controller and length of memory mapped
+ region.
+ - interrupts: interrupt number to the cpu.
+ - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges.
+ - gpios: The order of the gpios should be the following: <SDA, SCL>.
+ The gpio specifier depends on the gpio controller.
+
+Optional properties:
+ - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not
+ specified, default value is 0.
+ - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
+ specified, the default value in Hz is 100000.
+
+Example:
+
+ i2c@13870000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x13870000 0x100>;
+ interrupts = <345>;
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <100000>;
+ gpios = <&gpd1 2 0 /* SDA */
+ &gpd1 3 0 /* SCL */>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ wm8994@1a {
+ compatible = "wlf,wm8994";
+ reg = <0x1a>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt b/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt
new file mode 100644
index 000000000000..7e51154679a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt
@@ -0,0 +1,27 @@
+* NVIDIA Tegra Secure Digital Host Controller
+
+This controller on Tegra family SoCs provides an interface for MMC, SD,
+and SDIO types of memory cards.
+
+Required properties:
+- compatible : Should be "nvidia,<chip>-sdhci"
+- reg : Should contain SD/MMC registers location and length
+- interrupts : Should contain SD/MMC interrupt
+
+Optional properties:
+- cd-gpios : Specify GPIOs for card detection
+- wp-gpios : Specify GPIOs for write protection
+- power-gpios : Specify GPIOs for power control
+- support-8bit : Boolean, indicates if 8-bit mode should be used.
+
+Example:
+
+sdhci@c8000200 {
+ compatible = "nvidia,tegra20-sdhci";
+ reg = <0xc8000200 0x200>;
+ interrupts = <47>;
+ cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+ wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+ power-gpios = <&gpio 155 0>; /* gpio PT3 */
+ support-8bit;
+};
diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
index 1a729f089866..1ad80d5865a9 100644
--- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
+++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
@@ -1,61 +1,24 @@
-CAN Device Tree Bindings
-------------------------
-2011 Freescale Semiconductor, Inc.
+Flexcan CAN contoller on Freescale's ARM and PowerPC system-on-a-chip (SOC).
-fsl,flexcan-v1.0 nodes
------------------------
-In addition to the required compatible-, reg- and interrupt-properties, you can
-also specify which clock source shall be used for the controller.
+Required properties:
-CPI Clock- Can Protocol Interface Clock
- This CLK_SRC bit of CTRL(control register) selects the clock source to
- the CAN Protocol Interface(CPI) to be either the peripheral clock
- (driven by the PLL) or the crystal oscillator clock. The selected clock
- is the one fed to the prescaler to generate the Serial Clock (Sclock).
- The PRESDIV field of CTRL(control register) controls a prescaler that
- generates the Serial Clock (Sclock), whose period defines the
- time quantum used to compose the CAN waveform.
+- compatible : Should be "fsl,<processor>-flexcan"
-Can Engine Clock Source
- There are two sources for CAN clock
- - Platform Clock It represents the bus clock
- - Oscillator Clock
+ An implementation should also claim any of the following compatibles
+ that it is fully backwards compatible with:
- Peripheral Clock (PLL)
- --------------
- |
- --------- -------------
- | |CPI Clock | Prescaler | Sclock
- | |---------------->| (1.. 256) |------------>
- --------- -------------
- | |
- -------------- ---------------------CLK_SRC
- Oscillator Clock
+ - fsl,p1010-flexcan
-- fsl,flexcan-clock-source : CAN Engine Clock Source.This property selects
- the peripheral clock. PLL clock is fed to the
- prescaler to generate the Serial Clock (Sclock).
- Valid values are "oscillator" and "platform"
- "oscillator": CAN engine clock source is oscillator clock.
- "platform" The CAN engine clock source is the bus clock
- (platform clock).
+- reg : Offset and length of the register set for this device
+- interrupts : Interrupt tuple for this device
+- clock-frequency : The oscillator frequency driving the flexcan device
-- fsl,flexcan-clock-divider : for the reference and system clock, an additional
- clock divider can be specified.
-- clock-frequency: frequency required to calculate the bitrate for FlexCAN.
+Example:
-Note:
- - v1.0 of flexcan-v1.0 represent the IP block version for P1010 SOC.
- - P1010 does not have oscillator as the Clock Source.So the default
- Clock Source is platform clock.
-Examples:
-
- can0@1c000 {
- compatible = "fsl,flexcan-v1.0";
+ can@1c000 {
+ compatible = "fsl,p1010-flexcan";
reg = <0x1c000 0x1000>;
interrupts = <48 0x2>;
interrupt-parent = <&mpic>;
- fsl,flexcan-clock-source = "platform";
- fsl,flexcan-clock-divider = <2>;
- clock-frequency = <fixed by u-boot>;
+ clock-frequency = <200000000>; // filled in by bootloader
};
diff --git a/Documentation/devicetree/bindings/net/smsc911x.txt b/Documentation/devicetree/bindings/net/smsc911x.txt
new file mode 100644
index 000000000000..adb5b5744ecd
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/smsc911x.txt
@@ -0,0 +1,38 @@
+* Smart Mixed-Signal Connectivity (SMSC) LAN911x/912x Controller
+
+Required properties:
+- compatible : Should be "smsc,lan<model>", "smsc,lan9115"
+- reg : Address and length of the io space for SMSC LAN
+- interrupts : Should contain SMSC LAN interrupt line
+- interrupt-parent : Should be the phandle for the interrupt controller
+ that services interrupts for this device
+- phy-mode : String, operation mode of the PHY interface.
+ Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
+ "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
+
+Optional properties:
+- reg-shift : Specify the quantity to shift the register offsets by
+- reg-io-width : Specify the size (in bytes) of the IO accesses that
+ should be performed on the device. Valid value for SMSC LAN is
+ 2 or 4. If it's omitted or invalid, the size would be 2.
+- smsc,irq-active-high : Indicates the IRQ polarity is active-high
+- smsc,irq-push-pull : Indicates the IRQ type is push-pull
+- smsc,force-internal-phy : Forces SMSC LAN controller to use
+ internal PHY
+- smsc,force-external-phy : Forces SMSC LAN controller to use
+ external PHY
+- smsc,save-mac-address : Indicates that mac address needs to be saved
+ before resetting the controller
+- local-mac-address : 6 bytes, mac address
+
+Examples:
+
+lan9220@f4000000 {
+ compatible = "smsc,lan9220", "smsc,lan9115";
+ reg = <0xf4000000 0x2000000>;
+ phy-mode = "mii";
+ interrupt-parent = <&gpio1>;
+ interrupts = <31>;
+ reg-io-width = <4>;
+ smsc,irq-push-pull;
+};
diff --git a/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
new file mode 100644
index 000000000000..36f82dbdd14d
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
@@ -0,0 +1,5 @@
+NVIDIA Tegra 2 pinmux controller
+
+Required properties:
+- compatible : "nvidia,tegra20-pinmux"
+
diff --git a/Documentation/devicetree/bindings/serial/rs485.txt b/Documentation/devicetree/bindings/serial/rs485.txt
new file mode 100644
index 000000000000..1e753c69fc83
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/rs485.txt
@@ -0,0 +1,31 @@
+* RS485 serial communications
+
+The RTS signal is capable of automatically controlling line direction for
+the built-in half-duplex mode.
+The properties described hereafter shall be given to a half-duplex capable
+UART node.
+
+Required properties:
+- rs485-rts-delay: prop-encoded-array <a b> where:
+ * a is the delay beteween rts signal and beginning of data sent in milliseconds.
+ it corresponds to the delay before sending data.
+ * b is the delay between end of data sent and rts signal in milliseconds
+ it corresponds to the delay after sending data and actual release of the line.
+
+Optional properties:
+- linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485
+ feature at boot time. It can be disabled later with proper ioctl.
+- rs485-rx-during-tx: empty property that enables the receiving of data even
+ whilst sending data.
+
+RS485 example for Atmel USART:
+ usart0: serial@fff8c000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff8c000 0x4000>;
+ interrupts = <7>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ linux,rs485-enabled-at-boot-time;
+ rs485-rts-delay = <0 200>; // in milliseconds
+ };
+
diff --git a/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt b/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt
new file mode 100644
index 000000000000..2c3cd413f042
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt
@@ -0,0 +1,11 @@
+* Freescale SGTL5000 Stereo Codec
+
+Required properties:
+- compatible : "fsl,sgtl5000".
+
+Example:
+
+codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8510.txt b/Documentation/devicetree/bindings/sound/wm8510.txt
new file mode 100644
index 000000000000..fa1a32b85577
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8510.txt
@@ -0,0 +1,18 @@
+WM8510 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+ - compatible : "wlf,wm8510"
+
+ - reg : the I2C address of the device for I2C, the chip select
+ number for SPI.
+
+Example:
+
+codec: wm8510@1a {
+ compatible = "wlf,wm8510";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8523.txt b/Documentation/devicetree/bindings/sound/wm8523.txt
new file mode 100644
index 000000000000..04746186b283
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8523.txt
@@ -0,0 +1,16 @@
+WM8523 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+ - compatible : "wlf,wm8523"
+
+ - reg : the I2C address of the device.
+
+Example:
+
+codec: wm8523@1a {
+ compatible = "wlf,wm8523";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8580.txt b/Documentation/devicetree/bindings/sound/wm8580.txt
new file mode 100644
index 000000000000..7d9821f348da
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8580.txt
@@ -0,0 +1,16 @@
+WM8580 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+ - compatible : "wlf,wm8580"
+
+ - reg : the I2C address of the device.
+
+Example:
+
+codec: wm8580@1a {
+ compatible = "wlf,wm8580";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8711.txt b/Documentation/devicetree/bindings/sound/wm8711.txt
new file mode 100644
index 000000000000..8ed9998cd23c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8711.txt
@@ -0,0 +1,18 @@
+WM8711 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+ - compatible : "wlf,wm8711"
+
+ - reg : the I2C address of the device for I2C, the chip select
+ number for SPI.
+
+Example:
+
+codec: wm8711@1a {
+ compatible = "wlf,wm8711";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8728.txt b/Documentation/devicetree/bindings/sound/wm8728.txt
new file mode 100644
index 000000000000..a8b5c3668e60
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8728.txt
@@ -0,0 +1,18 @@
+WM8728 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+ - compatible : "wlf,wm8728"
+
+ - reg : the I2C address of the device for I2C, the chip select
+ number for SPI.
+
+Example:
+
+codec: wm8728@1a {
+ compatible = "wlf,wm8728";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8731.txt b/Documentation/devicetree/bindings/sound/wm8731.txt
new file mode 100644
index 000000000000..15f70048469b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8731.txt
@@ -0,0 +1,18 @@
+WM8731 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+ - compatible : "wlf,wm8731"
+
+ - reg : the I2C address of the device for I2C, the chip select
+ number for SPI.
+
+Example:
+
+codec: wm8731@1a {
+ compatible = "wlf,wm8731";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8737.txt b/Documentation/devicetree/bindings/sound/wm8737.txt
new file mode 100644
index 000000000000..4bc2cea3b140
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8737.txt
@@ -0,0 +1,18 @@
+WM8737 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+ - compatible : "wlf,wm8737"
+
+ - reg : the I2C address of the device for I2C, the chip select
+ number for SPI.
+
+Example:
+
+codec: wm8737@1a {
+ compatible = "wlf,wm8737";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8741.txt b/Documentation/devicetree/bindings/sound/wm8741.txt
new file mode 100644
index 000000000000..74bda58c1bcf
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8741.txt
@@ -0,0 +1,18 @@
+WM8741 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+ - compatible : "wlf,wm8741"
+
+ - reg : the I2C address of the device for I2C, the chip select
+ number for SPI.
+
+Example:
+
+codec: wm8741@1a {
+ compatible = "wlf,wm8741";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8750.txt b/Documentation/devicetree/bindings/sound/wm8750.txt
new file mode 100644
index 000000000000..8db239fd5ecd
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8750.txt
@@ -0,0 +1,18 @@
+WM8750 and WM8987 audio CODECs
+
+These devices support both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+ - compatible : "wlf,wm8750" or "wlf,wm8987"
+
+ - reg : the I2C address of the device for I2C, the chip select
+ number for SPI.
+
+Example:
+
+codec: wm8750@1a {
+ compatible = "wlf,wm8750";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8753.txt b/Documentation/devicetree/bindings/sound/wm8753.txt
new file mode 100644
index 000000000000..e65277a0fb60
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8753.txt
@@ -0,0 +1,18 @@
+WM8753 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+ - compatible : "wlf,wm8753"
+
+ - reg : the I2C address of the device for I2C, the chip select
+ number for SPI.
+
+Example:
+
+codec: wm8737@1a {
+ compatible = "wlf,wm8753";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8770.txt b/Documentation/devicetree/bindings/sound/wm8770.txt
new file mode 100644
index 000000000000..866e00ca150b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8770.txt
@@ -0,0 +1,16 @@
+WM8770 audio CODEC
+
+This device supports SPI.
+
+Required properties:
+
+ - compatible : "wlf,wm8770"
+
+ - reg : the chip select number.
+
+Example:
+
+codec: wm8770@1 {
+ compatible = "wlf,wm8770";
+ reg = <1>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8776.txt b/Documentation/devicetree/bindings/sound/wm8776.txt
new file mode 100644
index 000000000000..3b9ca49abc2b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8776.txt
@@ -0,0 +1,18 @@
+WM8776 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+ - compatible : "wlf,wm8776"
+
+ - reg : the I2C address of the device for I2C, the chip select
+ number for SPI.
+
+Example:
+
+codec: wm8776@1a {
+ compatible = "wlf,wm8776";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8804.txt b/Documentation/devicetree/bindings/sound/wm8804.txt
new file mode 100644
index 000000000000..4d3a56f38adc
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8804.txt
@@ -0,0 +1,18 @@
+WM8804 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+ - compatible : "wlf,wm8804"
+
+ - reg : the I2C address of the device for I2C, the chip select
+ number for SPI.
+
+Example:
+
+codec: wm8804@1a {
+ compatible = "wlf,wm8804";
+ reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/spi/spi_pl022.txt b/Documentation/devicetree/bindings/spi/spi_pl022.txt
new file mode 100644
index 000000000000..306ec3ff3c0e
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi_pl022.txt
@@ -0,0 +1,12 @@
+ARM PL022 SPI controller
+
+Required properties:
+- compatible : "arm,pl022", "arm,primecell"
+- reg : Offset and length of the register set for the device
+- interrupts : Should contain SPI controller interrupt
+
+Optional properties:
+- cs-gpios : should specify GPIOs used for chipselects.
+ The gpios will be referred to as reg = <index> in the SPI child nodes.
+ If unspecified, a single SPI device without a chip select can be used.
+
diff --git a/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt
new file mode 100644
index 000000000000..a49d9a1d4ccf
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt
@@ -0,0 +1,27 @@
+* Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART)
+
+Required properties:
+- compatible: Should be "atmel,<chip>-usart"
+ The compatible <chip> indicated will be the first SoC to support an
+ additional mode or an USART new feature.
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+
+Optional properties:
+- atmel,use-dma-rx: use of PDC or DMA for receiving data
+- atmel,use-dma-tx: use of PDC or DMA for transmitting data
+
+<chip> compatible description:
+- at91rm9200: legacy USART support
+- at91sam9260: generic USART implementation for SAM9 SoCs
+
+Example:
+
+ usart0: serial@fff8c000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff8c000 0x4000>;
+ interrupts = <7>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ };
+
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
new file mode 100644
index 000000000000..aef383eb8876
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
@@ -0,0 +1,27 @@
+* Qualcomm MSM UART
+
+Required properties:
+- compatible :
+ - "qcom,msm-uart", and one of "qcom,msm-hsuart" or
+ "qcom,msm-lsuart".
+- reg : offset and length of the register set for the device
+ for the hsuart operating in compatible mode, there should be a
+ second pair describing the gsbi registers.
+- interrupts : should contain the uart interrupt.
+
+There are two different UART blocks used in MSM devices,
+"qcom,msm-hsuart" and "qcom,msm-lsuart". The msm-serial driver is
+able to handle both of these, and matches against the "qcom,msm-uart"
+as the compatibility.
+
+The registers for the "qcom,msm-hsuart" device need to specify both
+register blocks, even for the common driver.
+
+Example:
+
+ uart@19c400000 {
+ compatible = "qcom,msm-hsuart", "qcom,msm-uart";
+ reg = <0x19c40000 0x1000>,
+ <0x19c00000 0x1000>;
+ interrupts = <195>;
+ };
diff --git a/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt b/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt
new file mode 100644
index 000000000000..f13f1c5be91c
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt
@@ -0,0 +1,25 @@
+* Synopsys DesignWare ABP UART
+
+Required properties:
+- compatible : "snps,dw-apb-uart"
+- reg : offset and length of the register set for the device.
+- interrupts : should contain uart interrupt.
+- clock-frequency : the input clock frequency for the UART.
+
+Optional properties:
+- reg-shift : quantity to shift the register offsets by. If this property is
+ not present then the register offsets are not shifted.
+- reg-io-width : the size (in bytes) of the IO accesses that should be
+ performed on the device. If this property is not present then single byte
+ accesses are used.
+
+Example:
+
+ uart@80230000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x80230000 0x100>;
+ clock-frequency = <3686400>;
+ interrupts = <10>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
new file mode 100644
index 000000000000..e8552782b440
--- /dev/null
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -0,0 +1,40 @@
+Device tree binding vendor prefix registry. Keep list in alphabetical order.
+
+This isn't an exhaustive list, but you should add new prefixes to it before
+using them to avoid name-space collisions.
+
+adi Analog Devices, Inc.
+amcc Applied Micro Circuits Corporation (APM, formally AMCC)
+apm Applied Micro Circuits Corporation (APM)
+arm ARM Ltd.
+atmel Atmel Corporation
+chrp Common Hardware Reference Platform
+dallas Maxim Integrated Products (formerly Dallas Semiconductor)
+denx Denx Software Engineering
+epson Seiko Epson Corp.
+est ESTeem Wireless Modems
+fsl Freescale Semiconductor
+GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+hp Hewlett Packard
+ibm International Business Machines (IBM)
+idt Integrated Device Technologies, Inc.
+intercontrol Inter Control Group
+linux Linux-specific binding
+marvell Marvell Technology Group Ltd.
+maxim Maxim Integrated Products
+mosaixtech Mosaix Technologies, Inc.
+national National Semiconductor
+nintendo Nintendo
+nvidia NVIDIA
+nxp NXP Semiconductors
+powervr Imagination Technologies
+qcom Qualcomm, Inc.
+ramtron Ramtron International
+samsung Samsung Semiconductor
+schindler Schindler
+simtek
+sirf SiRF Technology, Inc.
+stericsson ST-Ericsson
+ti Texas Instruments
+xlnx Xilinx
diff --git a/Documentation/devicetree/bindings/virtio/mmio.txt b/Documentation/devicetree/bindings/virtio/mmio.txt
new file mode 100644
index 000000000000..5069c1b8e193
--- /dev/null
+++ b/Documentation/devicetree/bindings/virtio/mmio.txt
@@ -0,0 +1,17 @@
+* virtio memory mapped device
+
+See http://ozlabs.org/~rusty/virtio-spec/ for more details.
+
+Required properties:
+
+- compatible: "virtio,mmio" compatibility string
+- reg: control registers base address and size including configuration space
+- interrupts: interrupt generated by the device
+
+Example:
+
+ virtio_block@3000 {
+ compatible = "virtio,mmio";
+ reg = <0x3000 0x100>;
+ interrupts = <41>;
+ }
diff --git a/Documentation/driver-model/binding.txt b/Documentation/driver-model/binding.txt
index f7ec9d625bfc..abfc8e290d53 100644
--- a/Documentation/driver-model/binding.txt
+++ b/Documentation/driver-model/binding.txt
@@ -48,10 +48,6 @@ devclass_add_device is called to enumerate the device within the class
and actually register it with the class, which happens with the
class's register_dev callback.
-NOTE: The device class structures and core routines to manipulate them
-are not in the mainline kernel, so the discussion is still a bit
-speculative.
-
Driver
~~~~~~
diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt
index bdefe728a737..1e70220d20f4 100644
--- a/Documentation/driver-model/device.txt
+++ b/Documentation/driver-model/device.txt
@@ -45,33 +45,52 @@ struct device_attribute {
const char *buf, size_t count);
};
-Attributes of devices can be exported via drivers using a simple
-procfs-like interface.
+Attributes of devices can be exported by a device driver through sysfs.
Please see Documentation/filesystems/sysfs.txt for more information
on how sysfs works.
+As explained in Documentation/kobject.txt, device attributes must be be
+created before the KOBJ_ADD uevent is generated. The only way to realize
+that is by defining an attribute group.
+
Attributes are declared using a macro called DEVICE_ATTR:
#define DEVICE_ATTR(name,mode,show,store)
Example:
-DEVICE_ATTR(power,0644,show_power,store_power);
+static DEVICE_ATTR(type, 0444, show_type, NULL);
+static DEVICE_ATTR(power, 0644, show_power, store_power);
-This declares a structure of type struct device_attribute named
-'dev_attr_power'. This can then be added and removed to the device's
-directory using:
+This declares two structures of type struct device_attribute with respective
+names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be
+organized as follows into a group:
-int device_create_file(struct device *device, struct device_attribute * entry);
-void device_remove_file(struct device * dev, struct device_attribute * attr);
+static struct attribute *dev_attrs[] = {
+ &dev_attr_type.attr,
+ &dev_attr_power.attr,
+ NULL,
+};
-Example:
+static struct attribute_group dev_attr_group = {
+ .attrs = dev_attrs,
+};
+
+static const struct attribute_group *dev_attr_groups[] = {
+ &dev_attr_group,
+ NULL,
+};
+
+This array of groups can then be associated with a device by setting the
+group pointer in struct device before device_register() is invoked:
-device_create_file(dev,&dev_attr_power);
-device_remove_file(dev,&dev_attr_power);
+ dev->groups = dev_attr_groups;
+ device_register(dev);
-The file name will be 'power' with a mode of 0644 (-rw-r--r--).
+The device_register() function will use the 'groups' pointer to create the
+device attributes and the device_unregister() function will use this pointer
+to remove the device attributes.
Word of warning: While the kernel allows device_create_file() and
device_remove_file() to be called on a device at any time, userspace has
@@ -84,24 +103,4 @@ not know about the new attributes.
This is important for device driver that need to publish additional
attributes for a device at driver probe time. If the device driver simply
calls device_create_file() on the device structure passed to it, then
-userspace will never be notified of the new attributes. Instead, it should
-probably use class_create() and class->dev_attrs to set up a list of
-desired attributes in the modules_init function, and then in the .probe()
-hook, and then use device_create() to create a new device as a child
-of the probed device. The new device will generate a new uevent and
-properly advertise the new attributes to userspace.
-
-For example, if a driver wanted to add the following attributes:
-struct device_attribute mydriver_attribs[] = {
- __ATTR(port_count, 0444, port_count_show),
- __ATTR(serial_number, 0444, serial_number_show),
- NULL
-};
-
-Then in the module init function is would do:
- mydriver_class = class_create(THIS_MODULE, "my_attrs");
- mydriver_class.dev_attr = mydriver_attribs;
-
-And assuming 'dev' is the struct device passed into the probe hook, the driver
-probe function would do something like:
- device_create(&mydriver_class, dev, chrdev, &private_data, "my_name");
+userspace will never be notified of the new attributes.
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
index c466f5831f15..e67be7afc78b 100755
--- a/Documentation/dvb/get_dvb_firmware
+++ b/Documentation/dvb/get_dvb_firmware
@@ -27,7 +27,8 @@ use IO::Handle;
"or51211", "or51132_qam", "or51132_vsb", "bluebird",
"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
- "lme2510c_s7395_old", "drxk", "drxk_terratec_h5");
+ "lme2510c_s7395_old", "drxk", "drxk_terratec_h5", "tda10071",
+ "it9135" );
# Check args
syntax() if (scalar(@ARGV) != 1);
@@ -575,19 +576,10 @@ sub ngene {
}
sub az6027{
- my $file = "AZ6027_Linux_Driver.tar.gz";
- my $url = "http://linux.terratec.de/files/$file";
my $firmware = "dvb-usb-az6027-03.fw";
+ my $url = "http://linux.terratec.de/files/TERRATEC_S7/$firmware";
- wgetfile($file, $url);
-
- #untar
- if( system("tar xzvf $file $firmware")){
- die "failed to untar firmware";
- }
- if( system("rm $file")){
- die ("unable to remove unnecessary files");
- }
+ wgetfile($firmware, $url);
$firmware;
}
@@ -665,6 +657,41 @@ sub drxk_terratec_h5 {
"$fwfile"
}
+sub it9135 {
+ my $url = "http://kworld.server261.com/kworld/CD/ITE_TiVme/V1.00/";
+ my $zipfile = "Driver_V10.323.1.0412.100412.zip";
+ my $hash = "79b597dc648698ed6820845c0c9d0d37";
+ my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 0);
+ my $drvfile = "Driver_V10.323.1.0412.100412/Data/x86/IT9135BDA.sys";
+ my $fwfile = "dvb-usb-it9137-01.fw";
+
+ checkstandard();
+
+ wgetfile($zipfile, $url . $zipfile);
+ verify($zipfile, $hash);
+ unzip($zipfile, $tmpdir);
+ extract("$tmpdir/$drvfile", 69632, 5731, "$fwfile");
+
+ "$fwfile"
+}
+
+sub tda10071 {
+ my $sourcefile = "PCTV_460e_reference.zip";
+ my $url = "ftp://ftp.pctvsystems.com/TV/driver/PCTV%2070e%2080e%20100e%20320e%20330e%20800e/";
+ my $hash = "4403de903bf2593464c8d74bbc200a57";
+ my $fwfile = "dvb-fe-tda10071.fw";
+ my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
+
+ checkstandard();
+
+ wgetfile($sourcefile, $url . $sourcefile);
+ verify($sourcefile, $hash);
+ unzip($sourcefile, $tmpdir);
+ extract("$tmpdir/PCTV\ 70e\ 80e\ 100e\ 320e\ 330e\ 800e/32\ bit/emOEM.sys", 0x67d38, 40504, $fwfile);
+
+ "$fwfile";
+}
+
# ---------------------------------------------------------------
# Utilities
diff --git a/Documentation/dvb/it9137.txt b/Documentation/dvb/it9137.txt
new file mode 100644
index 000000000000..9e6726eead90
--- /dev/null
+++ b/Documentation/dvb/it9137.txt
@@ -0,0 +1,9 @@
+To extract firmware for Kworld UB499-2T (id 1b80:e409) you need to copy the
+following file(s) to this directory.
+
+IT9135BDA.sys Dated Mon 22 Mar 2010 02:20:08 GMT
+
+extract using dd
+dd if=IT9135BDA.sys ibs=1 skip=69632 count=5731 of=dvb-usb-it9137-01.fw
+
+copy to default firmware location.
diff --git a/Documentation/fault-injection/fault-injection.txt b/Documentation/fault-injection/fault-injection.txt
index 82a5d250d75e..ba4be8b77093 100644
--- a/Documentation/fault-injection/fault-injection.txt
+++ b/Documentation/fault-injection/fault-injection.txt
@@ -21,6 +21,11 @@ o fail_make_request
/sys/block/<device>/make-it-fail or
/sys/block/<device>/<partition>/make-it-fail. (generic_make_request())
+o fail_mmc_request
+
+ injects MMC data errors on devices permitted by setting
+ debugfs entries under /sys/kernel/debug/mmc0/fail_mmc_request
+
Configure fault-injection capabilities behavior
-----------------------------------------------
@@ -115,7 +120,8 @@ use the boot option:
failslab=
fail_page_alloc=
- fail_make_request=<interval>,<probability>,<space>,<times>
+ fail_make_request=
+ mmc_core.fail_request=<interval>,<probability>,<space>,<times>
How to add new fault injection capability
-----------------------------------------
diff --git a/Documentation/fb/udlfb.txt b/Documentation/fb/udlfb.txt
index 7fdde2a02a27..57d2f2908b12 100644
--- a/Documentation/fb/udlfb.txt
+++ b/Documentation/fb/udlfb.txt
@@ -87,23 +87,38 @@ Special configuration for udlfb is usually unnecessary. There are a few
options, however.
From the command line, pass options to modprobe
-modprobe udlfb defio=1 console=1
+modprobe udlfb fb_defio=0 console=1 shadow=1
-Or for permanent option, create file like /etc/modprobe.d/options with text
-options udlfb defio=1 console=1
+Or modify options on the fly at /sys/module/udlfb/parameters directory via
+sudo nano fb_defio
+change the parameter in place, and save the file.
-Accepted options:
+Unplug/replug USB device to apply with new settings
+
+Or for permanent option, create file like /etc/modprobe.d/udlfb.conf with text
+options udlfb fb_defio=0 console=1 shadow=1
+
+Accepted boolean options:
fb_defio Make use of the fb_defio (CONFIG_FB_DEFERRED_IO) kernel
module to track changed areas of the framebuffer by page faults.
- Standard fbdev applications that use mmap but that do not
- report damage, may be able to work with this enabled.
- Disabled by default because of overhead and other issues.
-
-console Allow fbcon to attach to udlfb provided framebuffers. This
- is disabled by default because fbcon will aggressively consume
- the first framebuffer it finds, which isn't usually what the
- user wants in the case of USB displays.
+ Standard fbdev applications that use mmap but that do not
+ report damage, should be able to work with this enabled.
+ Disable when running with X server that supports reporting
+ changed regions via ioctl, as this method is simpler,
+ more stable, and higher performance.
+ default: fb_defio=1
+
+console Allow fbcon to attach to udlfb provided framebuffers.
+ Can be disabled if fbcon and other clients
+ (e.g. X with --shared-vt) are in conflict.
+ default: console=1
+
+shadow Allocate a 2nd framebuffer to shadow what's currently across
+ the USB bus in device memory. If any pixels are unchanged,
+ do not transmit. Spends host memory to save USB transfers.
+ Enabled by default. Only disable on very low memory systems.
+ default: shadow=1
Sysfs Attributes
================
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 4dc465477665..3d849122b5b1 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -133,41 +133,6 @@ Who: Pavel Machek <pavel@ucw.cz>
---------------------------
-What: sys_sysctl
-When: September 2010
-Option: CONFIG_SYSCTL_SYSCALL
-Why: The same information is available in a more convenient from
- /proc/sys, and none of the sysctl variables appear to be
- important performance wise.
-
- Binary sysctls are a long standing source of subtle kernel
- bugs and security issues.
-
- When I looked several months ago all I could find after
- searching several distributions were 5 user space programs and
- glibc (which falls back to /proc/sys) using this syscall.
-
- The man page for sysctl(2) documents it as unusable for user
- space programs.
-
- sysctl(2) is not generally ABI compatible to a 32bit user
- space application on a 64bit and a 32bit kernel.
-
- For the last several months the policy has been no new binary
- sysctls and no one has put forward an argument to use them.
-
- Binary sysctls issues seem to keep happening appearing so
- properly deprecating them (with a warning to user space) and a
- 2 year grace warning period will mean eventually we can kill
- them and end the pain.
-
- In the mean time individual binary sysctls can be dealt with
- in a piecewise fashion.
-
-Who: Eric Biederman <ebiederm@xmission.com>
-
----------------------------
-
What: /proc/<pid>/oom_adj
When: August 2012
Why: /proc/<pid>/oom_adj allows userspace to influence the oom killer's
@@ -495,29 +460,6 @@ Who: Jean Delvare <khali@linux-fr.org>
----------------------------
-What: Support for UVCIOC_CTRL_ADD in the uvcvideo driver
-When: 3.2
-Why: The information passed to the driver by this ioctl is now queried
- dynamically from the device.
-Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-
-----------------------------
-
-What: Support for UVCIOC_CTRL_MAP_OLD in the uvcvideo driver
-When: 3.2
-Why: Used only by applications compiled against older driver versions.
- Superseded by UVCIOC_CTRL_MAP which supports V4L2 menu controls.
-Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-
-----------------------------
-
-What: Support for UVCIOC_CTRL_GET and UVCIOC_CTRL_SET in the uvcvideo driver
-When: 3.2
-Why: Superseded by the UVCIOC_CTRL_QUERY ioctl.
-Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-
-----------------------------
-
What: Support for driver specific ioctls in the pwc driver (everything
defined in media/pwc-ioctl.h)
When: 3.3
@@ -594,9 +536,18 @@ Why: In 3.0, we can now autodetect internal 3G device and already have
Who: Lee, Chun-Yi <jlee@novell.com>
----------------------------
+
What: The XFS nodelaylog mount option
When: 3.3
Why: The delaylog mode that has been the default since 2.6.39 has proven
stable, and the old code is in the way of additional improvements in
the log code.
Who: Christoph Hellwig <hch@lst.de>
+
+----------------------------
+
+What: iwlagn alias support
+When: 3.5
+Why: The iwlagn module has been renamed iwlwifi. The alias will be around
+ for backward compatibility for several cycles and then dropped.
+Who: Don Fry <donald.h.fry@intel.com>
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt
index 13de64c7f0ab..2c0321442845 100644
--- a/Documentation/filesystems/9p.txt
+++ b/Documentation/filesystems/9p.txt
@@ -92,7 +92,7 @@ OPTIONS
wfdno=n the file descriptor for writing with trans=fd
- maxdata=n the number of bytes to use for 9p packet payload (msize)
+ msize=n the number of bytes to use for 9p packet payload
port=n port to connect to on the remote server
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 653380793a6c..d819ba16a0c7 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -29,6 +29,7 @@ d_hash no no no maybe
d_compare: yes no no maybe
d_delete: no yes no no
d_release: no no yes no
+d_prune: no yes no no
d_iput: no no yes no
d_dname: no no no no
d_automount: no no yes no
diff --git a/Documentation/filesystems/caching/object.txt b/Documentation/filesystems/caching/object.txt
index e8b0a35d8fe5..58313348da87 100644
--- a/Documentation/filesystems/caching/object.txt
+++ b/Documentation/filesystems/caching/object.txt
@@ -127,9 +127,9 @@ fscache_enqueue_object()).
PROVISION OF CPU TIME
---------------------
-The work to be done by the various states is given CPU time by the threads of
-the slow work facility (see Documentation/slow-work.txt). This is used in
-preference to the workqueue facility because:
+The work to be done by the various states was given CPU time by the threads of
+the slow work facility. This was used in preference to the workqueue facility
+because:
(1) Threads may be completely occupied for very long periods of time by a
particular work item. These state actions may be doing sequences of
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 22f3a0eda1d2..b100adc38adb 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -73,14 +73,6 @@ nobarrier (*) This also requires an IO stack which can support
also be used to enable or disable barriers, for
consistency with other ext3 mount options.
-orlov (*) This enables the new Orlov block allocator. It is
- enabled by default.
-
-oldalloc This disables the Orlov block allocator and enables
- the old block allocator. Orlov should have better
- performance - we'd like to get some feedback if it's
- the contrary for you.
-
user_xattr Enables Extended User Attributes. Additionally, you
need to have extended attribute support enabled in the
kernel configuration (CONFIG_EXT3_FS_XATTR). See the
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
index 232a575a0c48..4917cf24a5e0 100644
--- a/Documentation/filesystems/ext4.txt
+++ b/Documentation/filesystems/ext4.txt
@@ -160,7 +160,9 @@ noload if the filesystem was not unmounted cleanly,
lead to any number of problems.
data=journal All data are committed into the journal prior to being
- written into the main file system.
+ written into the main file system. Enabling
+ this mode will disable delayed allocation and
+ O_DIRECT support.
data=ordered (*) All data are forced directly out to the main file
system prior to its metadata being committed to the
@@ -201,30 +203,19 @@ inode_readahead_blks=n This tuning parameter controls the maximum
table readahead algorithm will pre-read into
the buffer cache. The default value is 32 blocks.
-orlov (*) This enables the new Orlov block allocator. It is
- enabled by default.
-
-oldalloc This disables the Orlov block allocator and enables
- the old block allocator. Orlov should have better
- performance - we'd like to get some feedback if it's
- the contrary for you.
-
-user_xattr Enables Extended User Attributes. Additionally, you
- need to have extended attribute support enabled in the
- kernel configuration (CONFIG_EXT4_FS_XATTR). See the
- attr(5) manual page and http://acl.bestbits.at/ to
- learn more about extended attributes.
-
-nouser_xattr Disables Extended User Attributes.
-
-acl Enables POSIX Access Control Lists support.
- Additionally, you need to have ACL support enabled in
- the kernel configuration (CONFIG_EXT4_FS_POSIX_ACL).
- See the acl(5) manual page and http://acl.bestbits.at/
- for more information.
+nouser_xattr Disables Extended User Attributes. If you have extended
+ attribute support enabled in the kernel configuration
+ (CONFIG_EXT4_FS_XATTR), extended attribute support
+ is enabled by default on mount. See the attr(5) manual
+ page and http://acl.bestbits.at/ for more information
+ about extended attributes.
noacl This option disables POSIX Access Control List
- support.
+ support. If ACL support is enabled in the kernel
+ configuration (CONFIG_EXT4_FS_POSIX_ACL), ACL is
+ enabled by default on mount. See the acl(5) manual
+ page and http://acl.bestbits.at/ for more information
+ about acl.
bsddf (*) Make 'df' act like BSD.
minixdf Make 'df' act like Minix.
@@ -419,8 +410,8 @@ written to the journal first, and then to its final location.
In the event of a crash, the journal can be replayed, bringing both data and
metadata into a consistent state. This mode is the slowest except when data
needs to be read from and written to disk at the same time where it
-outperforms all others modes. Currently ext4 does not have delayed
-allocation support if this data journalling mode is selected.
+outperforms all others modes. Enabling this mode will disable delayed
+allocation and O_DIRECT support.
/proc entries
=============
diff --git a/Documentation/filesystems/locks.txt b/Documentation/filesystems/locks.txt
index fab857accbd6..2cf81082581d 100644
--- a/Documentation/filesystems/locks.txt
+++ b/Documentation/filesystems/locks.txt
@@ -53,11 +53,12 @@ fcntl(), with all the problems that implies.
1.3 Mandatory Locking As A Mount Option
---------------------------------------
-Mandatory locking, as described in 'Documentation/filesystems/mandatory.txt'
-was prior to this release a general configuration option that was valid for
-all mounted filesystems. This had a number of inherent dangers, not the
-least of which was the ability to freeze an NFS server by asking it to read
-a file for which a mandatory lock existed.
+Mandatory locking, as described in
+'Documentation/filesystems/mandatory-locking.txt' was prior to this release a
+general configuration option that was valid for all mounted filesystems. This
+had a number of inherent dangers, not the least of which was the ability to
+freeze an NFS server by asking it to read a file for which a mandatory lock
+existed.
From this release of the kernel, mandatory locking can be turned on and off
on a per-filesystem basis, using the mount options 'mand' and 'nomand'.
diff --git a/Documentation/filesystems/nfs/idmapper.txt b/Documentation/filesystems/nfs/idmapper.txt
index 9c8fd6148656..120fd3cf7fd9 100644
--- a/Documentation/filesystems/nfs/idmapper.txt
+++ b/Documentation/filesystems/nfs/idmapper.txt
@@ -47,7 +47,7 @@ request-key will find the first matching line and corresponding program. In
this case, /some/other/program will handle all uid lookups and
/usr/sbin/nfs.idmap will handle gid, user, and group lookups.
-See <file:Documentation/security/keys-request-keys.txt> for more information
+See <file:Documentation/security/keys-request-key.txt> for more information
about the request-key function.
diff --git a/Documentation/filesystems/pohmelfs/design_notes.txt b/Documentation/filesystems/pohmelfs/design_notes.txt
index dcf833587162..8aef91335701 100644
--- a/Documentation/filesystems/pohmelfs/design_notes.txt
+++ b/Documentation/filesystems/pohmelfs/design_notes.txt
@@ -58,8 +58,9 @@ data transfers.
POHMELFS clients operate with a working set of servers and are capable of balancing read-only
operations (like lookups or directory listings) between them according to IO priorities.
Administrators can add or remove servers from the set at run-time via special commands (described
-in Documentation/pohmelfs/info.txt file). Writes are replicated to all servers, which are connected
-with write permission turned on. IO priority and permissions can be changed in run-time.
+in Documentation/filesystems/pohmelfs/info.txt file). Writes are replicated to all servers, which
+are connected with write permission turned on. IO priority and permissions can be changed in
+run-time.
POHMELFS is capable of full data channel encryption and/or strong crypto hashing.
One can select any kernel supported cipher, encryption mode, hash type and operation mode
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index db3b1aba32a3..0ec91f03422e 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1263,7 +1263,7 @@ review the kernel documentation in the directory /usr/src/linux/Documentation.
This chapter is heavily based on the documentation included in the pre 2.2
kernels, and became part of it in version 2.2.1 of the Linux kernel.
-Please see: Documentation/sysctls/ directory for descriptions of these
+Please see: Documentation/sysctl/ directory for descriptions of these
entries.
------------------------------------------------------------------------------
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index 597f728e7b4e..07235caec22c 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -4,7 +4,7 @@ sysfs - _The_ filesystem for exporting kernel objects.
Patrick Mochel <mochel@osdl.org>
Mike Murphy <mamurph@cs.clemson.edu>
-Revised: 15 July 2010
+Revised: 16 August 2011
Original: 10 January 2003
@@ -370,3 +370,11 @@ int driver_create_file(struct device_driver *, const struct driver_attribute *);
void driver_remove_file(struct device_driver *, const struct driver_attribute *);
+Documentation
+~~~~~~~~~~~~~
+
+The sysfs directory structure and the attributes in each directory define an
+ABI between the kernel and user space. As for any ABI, it is important that
+this ABI is stable and properly documented. All new sysfs attributes must be
+documented in Documentation/ABI. See also Documentation/ABI/README for more
+information.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 52d8fb81cfff..43cbd0821721 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -1053,9 +1053,6 @@ manipulate dentries:
and the dentry is returned. The caller must use dput()
to free the dentry when it finishes using it.
-For further information on dentry locking, please refer to the document
-Documentation/filesystems/dentry-locking.txt.
-
Mount Options
=============
diff --git a/Documentation/frv/booting.txt b/Documentation/frv/booting.txt
index 37c4d84a0e57..9bdf4b46e741 100644
--- a/Documentation/frv/booting.txt
+++ b/Documentation/frv/booting.txt
@@ -180,9 +180,3 @@ separated by spaces:
This tells the kernel what program to run initially. By default this is
/sbin/init, but /sbin/sash or /bin/sh are common alternatives.
-
- (*) vdc=...
-
- This option configures the MB93493 companion chip visual display
- driver. Please see Documentation/frv/mb93493/vdc.txt for more
- information.
diff --git a/Documentation/hwmon/ad7314 b/Documentation/hwmon/ad7314
new file mode 100644
index 000000000000..1912549c7467
--- /dev/null
+++ b/Documentation/hwmon/ad7314
@@ -0,0 +1,25 @@
+Kernel driver ad7314
+====================
+
+Supported chips:
+ * Analog Devices AD7314
+ Prefix: 'ad7314'
+ Datasheet: Publicly available at Analog Devices website.
+ * Analog Devices ADT7301
+ Prefix: 'adt7301'
+ Datasheet: Publicly available at Analog Devices website.
+ * Analog Devices ADT7302
+ Prefix: 'adt7302'
+ Datasheet: Publicly available at Analog Devices website.
+
+Description
+-----------
+
+Driver supports the above parts. The ad7314 has a 10 bit
+sensor with 1lsb = 0.25 degrees centigrade. The adt7301 and
+adt7302 have 14 bit sensors with 1lsb = 0.03125 degrees centigrade.
+
+Notes
+-----
+
+Currently power down mode is not supported.
diff --git a/Documentation/hwmon/adm1275 b/Documentation/hwmon/adm1275
index 097b3ccc4be7..ab70d96d2dfd 100644
--- a/Documentation/hwmon/adm1275
+++ b/Documentation/hwmon/adm1275
@@ -6,6 +6,10 @@ Supported chips:
Prefix: 'adm1275'
Addresses scanned: -
Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1275.pdf
+ * Analog Devices ADM1276
+ Prefix: 'adm1276'
+ Addresses scanned: -
+ Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com>
@@ -13,13 +17,13 @@ Author: Guenter Roeck <guenter.roeck@ericsson.com>
Description
-----------
-This driver supports hardware montoring for Analog Devices ADM1275 Hot-Swap
-Controller and Digital Power Monitor.
+This driver supports hardware montoring for Analog Devices ADM1275 and ADM1276
+Hot-Swap Controller and Digital Power Monitor.
-The ADM1275 is a hot-swap controller that allows a circuit board to be removed
-from or inserted into a live backplane. It also features current and voltage
-readback via an integrated 12-bit analog-to-digital converter (ADC), accessed
-using a PMBus. interface.
+ADM1275 and ADM1276 are hot-swap controllers that allow a circuit board to be
+removed from or inserted into a live backplane. They also feature current and
+voltage readback via an integrated 12-bit analog-to-digital converter (ADC),
+accessed using a PMBus interface.
The driver is a client driver to the core PMBus driver. Please see
Documentation/hwmon/pmbus for details on PMBus client drivers.
@@ -48,17 +52,25 @@ attributes are write-only, all other attributes are read-only.
in1_label "vin1" or "vout1" depending on chip variant and
configuration.
-in1_input Measured voltage. From READ_VOUT register.
-in1_min Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
-in1_max Maximum voltage. From VOUT_OV_WARN_LIMIT register.
-in1_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
-in1_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in1_input Measured voltage.
+in1_min Minumum Voltage.
+in1_max Maximum voltage.
+in1_min_alarm Voltage low alarm.
+in1_max_alarm Voltage high alarm.
in1_highest Historical maximum voltage.
in1_reset_history Write any value to reset history.
curr1_label "iout1"
-curr1_input Measured current. From READ_IOUT register.
-curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register.
-curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register.
+curr1_input Measured current.
+curr1_max Maximum current.
+curr1_max_alarm Current high alarm.
+curr1_lcrit Critical minimum current. Depending on the chip
+ configuration, either curr1_lcrit or curr1_crit is
+ supported, but not both.
+curr1_lcrit_alarm Critical current low alarm.
+curr1_crit Critical maximum current. Depending on the chip
+ configuration, either curr1_lcrit or curr1_crit is
+ supported, but not both.
+curr1_crit_alarm Critical current high alarm.
curr1_highest Historical maximum current.
curr1_reset_history Write any value to reset history.
diff --git a/Documentation/hwmon/exynos4_tmu b/Documentation/hwmon/exynos4_tmu
new file mode 100644
index 000000000000..c3c6b41db607
--- /dev/null
+++ b/Documentation/hwmon/exynos4_tmu
@@ -0,0 +1,81 @@
+Kernel driver exynos4_tmu
+=================
+
+Supported chips:
+* ARM SAMSUNG EXYNOS4 series of SoC
+ Prefix: 'exynos4-tmu'
+ Datasheet: Not publicly available
+
+Authors: Donggeun Kim <dg77.kim@samsung.com>
+
+Description
+-----------
+
+This driver allows to read temperature inside SAMSUNG EXYNOS4 series of SoC.
+
+The chip only exposes the measured 8-bit temperature code value
+through a register.
+Temperature can be taken from the temperature code.
+There are three equations converting from temperature to temperature code.
+
+The three equations are:
+ 1. Two point trimming
+ Tc = (T - 25) * (TI2 - TI1) / (85 - 25) + TI1
+
+ 2. One point trimming
+ Tc = T + TI1 - 25
+
+ 3. No trimming
+ Tc = T + 50
+
+ Tc: Temperature code, T: Temperature,
+ TI1: Trimming info for 25 degree Celsius (stored at TRIMINFO register)
+ Temperature code measured at 25 degree Celsius which is unchanged
+ TI2: Trimming info for 85 degree Celsius (stored at TRIMINFO register)
+ Temperature code measured at 85 degree Celsius which is unchanged
+
+TMU(Thermal Management Unit) in EXYNOS4 generates interrupt
+when temperature exceeds pre-defined levels.
+The maximum number of configurable threshold is four.
+The threshold levels are defined as follows:
+ Level_0: current temperature > trigger_level_0 + threshold
+ Level_1: current temperature > trigger_level_1 + threshold
+ Level_2: current temperature > trigger_level_2 + threshold
+ Level_3: current temperature > trigger_level_3 + threshold
+
+ The threshold and each trigger_level are set
+ through the corresponding registers.
+
+When an interrupt occurs, this driver notify user space of
+one of four threshold levels for the interrupt
+through kobject_uevent_env and sysfs_notify functions.
+Although an interrupt condition for level_0 can be set,
+it is not notified to user space through sysfs_notify function.
+
+Sysfs Interface
+---------------
+name name of the temperature sensor
+ RO
+
+temp1_input temperature
+ RO
+
+temp1_max temperature for level_1 interrupt
+ RO
+
+temp1_crit temperature for level_2 interrupt
+ RO
+
+temp1_emergency temperature for level_3 interrupt
+ RO
+
+temp1_max_alarm alarm for level_1 interrupt
+ RO
+
+temp1_crit_alarm
+ alarm for level_2 interrupt
+ RO
+
+temp1_emergency_alarm
+ alarm for level_3 interrupt
+ RO
diff --git a/Documentation/hwmon/lm75 b/Documentation/hwmon/lm75
index a1790401fdde..c91a1d15fa28 100644
--- a/Documentation/hwmon/lm75
+++ b/Documentation/hwmon/lm75
@@ -12,26 +12,46 @@ Supported chips:
Addresses scanned: I2C 0x48 - 0x4f
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/
- * Dallas Semiconductor DS75
- Prefix: 'lm75'
- Addresses scanned: I2C 0x48 - 0x4f
- Datasheet: Publicly available at the Dallas Semiconductor website
- http://www.maxim-ic.com/
- * Dallas Semiconductor DS1775
- Prefix: 'lm75'
- Addresses scanned: I2C 0x48 - 0x4f
+ * Dallas Semiconductor DS75, DS1775
+ Prefixes: 'ds75', 'ds1775'
+ Addresses scanned: none
Datasheet: Publicly available at the Dallas Semiconductor website
http://www.maxim-ic.com/
* Maxim MAX6625, MAX6626
- Prefix: 'lm75'
- Addresses scanned: I2C 0x48 - 0x4b
+ Prefixes: 'max6625', 'max6626'
+ Addresses scanned: none
Datasheet: Publicly available at the Maxim website
http://www.maxim-ic.com/
* Microchip (TelCom) TCN75
Prefix: 'lm75'
- Addresses scanned: I2C 0x48 - 0x4f
+ Addresses scanned: none
+ Datasheet: Publicly available at the Microchip website
+ http://www.microchip.com/
+ * Microchip MCP9800, MCP9801, MCP9802, MCP9803
+ Prefix: 'mcp980x'
+ Addresses scanned: none
Datasheet: Publicly available at the Microchip website
http://www.microchip.com/
+ * Analog Devices ADT75
+ Prefix: 'adt75'
+ Addresses scanned: none
+ Datasheet: Publicly available at the Analog Devices website
+ http://www.analog.com/adt75
+ * ST Microelectronics STDS75
+ Prefix: 'stds75'
+ Addresses scanned: none
+ Datasheet: Publicly available at the ST website
+ http://www.st.com/internet/analog/product/121769.jsp
+ * Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175, TMP275
+ Prefixes: 'tmp100', 'tmp101', 'tmp105', 'tmp175', 'tmp75', 'tmp275'
+ Addresses scanned: none
+ Datasheet: Publicly available at the Texas Instruments website
+ http://www.ti.com/product/tmp100
+ http://www.ti.com/product/tmp101
+ http://www.ti.com/product/tmp105
+ http://www.ti.com/product/tmp75
+ http://www.ti.com/product/tmp175
+ http://www.ti.com/product/tmp275
Author: Frodo Looijaard <frodol@dds.nl>
@@ -50,21 +70,16 @@ range of -55 to +125 degrees.
The LM75 only updates its values each 1.5 seconds; reading it more often
will do no harm, but will return 'old' values.
-The LM75 is usually used in combination with LM78-like chips, to measure
-the temperature of the processor(s).
-
-The DS75, DS1775, MAX6625, and MAX6626 are supported as well.
-They are not distinguished from an LM75. While most of these chips
-have three additional bits of accuracy (12 vs. 9 for the LM75),
-the additional bits are not supported. Not only that, but these chips will
-not be detected if not in 9-bit precision mode (use the force parameter if
-needed).
-
-The TCN75 is supported as well, and is not distinguished from an LM75.
+The original LM75 was typically used in combination with LM78-like chips
+on PC motherboards, to measure the temperature of the processor(s). Clones
+are now used in various embedded designs.
The LM75 is essentially an industry standard; there may be other
LM75 clones not listed here, with or without various enhancements,
-that are supported.
+that are supported. The clones are not detected by the driver, unless
+they reproduce the exact register tricks of the original LM75, and must
+therefore be instantiated explicitly. The specific enhancements (such as
+higher resolution) are not currently supported by the driver.
The LM77 is not supported, contrary to what we pretended for a long time.
Both chips are simply not compatible, value encoding differs.
diff --git a/Documentation/hwmon/ltc2978 b/Documentation/hwmon/ltc2978
new file mode 100644
index 000000000000..c365f9beb5dd
--- /dev/null
+++ b/Documentation/hwmon/ltc2978
@@ -0,0 +1,103 @@
+Kernel driver ltc2978
+=====================
+
+Supported chips:
+ * Linear Technology LTC2978
+ Prefix: 'ltc2978'
+ Addresses scanned: -
+ Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
+ * Linear Technology LTC3880
+ Prefix: 'ltc3880'
+ Addresses scanned: -
+ Datasheet: http://cds.linear.com/docs/Datasheet/3880f.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+The LTC2978 is an octal power supply monitor, supervisor, sequencer and
+margin controller. The LTC3880 is a dual, PolyPhase DC/DC synchronous
+step-down switching regulator controller.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for PMBus devices. You will have to instantiate
+devices explicitly.
+
+Example: the following commands will load the driver for an LTC2978 at address
+0x60 on I2C bus #1:
+
+# modprobe ltc2978
+# echo ltc2978 0x60 > /sys/bus/i2c/devices/i2c-1/new_device
+
+
+Sysfs attributes
+----------------
+
+in1_label "vin"
+in1_input Measured input voltage.
+in1_min Minimum input voltage.
+in1_max Maximum input voltage.
+in1_lcrit Critical minimum input voltage.
+in1_crit Critical maximum input voltage.
+in1_min_alarm Input voltage low alarm.
+in1_max_alarm Input voltage high alarm.
+in1_lcrit_alarm Input voltage critical low alarm.
+in1_crit_alarm Input voltage critical high alarm.
+in1_lowest Lowest input voltage. LTC2978 only.
+in1_highest Highest input voltage.
+in1_reset_history Reset history. Writing into this attribute will reset
+ history for all attributes.
+
+in[2-9]_label "vout[1-8]". Channels 3 to 9 on LTC2978 only.
+in[2-9]_input Measured output voltage.
+in[2-9]_min Minimum output voltage.
+in[2-9]_max Maximum output voltage.
+in[2-9]_lcrit Critical minimum output voltage.
+in[2-9]_crit Critical maximum output voltage.
+in[2-9]_min_alarm Output voltage low alarm.
+in[2-9]_max_alarm Output voltage high alarm.
+in[2-9]_lcrit_alarm Output voltage critical low alarm.
+in[2-9]_crit_alarm Output voltage critical high alarm.
+in[2-9]_lowest Lowest output voltage. LTC2978 only.
+in[2-9]_highest Lowest output voltage.
+in[2-9]_reset_history Reset history. Writing into this attribute will reset
+ history for all attributes.
+
+temp[1-3]_input Measured temperature.
+ On LTC2978, only one temperature measurement is
+ supported and reflects the internal temperature.
+ On LTC3880, temp1 and temp2 report external
+ temperatures, and temp3 reports the internal
+ temperature.
+temp[1-3]_min Mimimum temperature.
+temp[1-3]_max Maximum temperature.
+temp[1-3]_lcrit Critical low temperature.
+temp[1-3]_crit Critical high temperature.
+temp[1-3]_min_alarm Chip temperature low alarm.
+temp[1-3]_max_alarm Chip temperature high alarm.
+temp[1-3]_lcrit_alarm Chip temperature critical low alarm.
+temp[1-3]_crit_alarm Chip temperature critical high alarm.
+temp[1-3]_lowest Lowest measured temperature. LTC2978 only.
+temp[1-3]_highest Highest measured temperature.
+temp[1-3]_reset_history Reset history. Writing into this attribute will reset
+ history for all attributes.
+
+power[1-2]_label "pout[1-2]". LTC3880 only.
+power[1-2]_input Measured power.
+
+curr1_label "iin". LTC3880 only.
+curr1_input Measured input current.
+curr1_max Maximum input current.
+curr1_max_alarm Input current high alarm.
+
+curr[2-3]_label "iout[1-2]". LTC3880 only.
+curr[2-3]_input Measured input current.
+curr[2-3]_max Maximum input current.
+curr[2-3]_crit Critical input current.
+curr[2-3]_max_alarm Input current high alarm.
+curr[2-3]_crit_alarm Input current critical high alarm.
diff --git a/Documentation/hwmon/pmbus b/Documentation/hwmon/pmbus
index c36c1c1a62bb..15ac911ce51b 100644
--- a/Documentation/hwmon/pmbus
+++ b/Documentation/hwmon/pmbus
@@ -8,11 +8,6 @@ Supported chips:
Addresses scanned: -
Datasheet:
http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146395
- * Linear Technology LTC2978
- Octal PMBus Power Supply Monitor and Controller
- Prefix: 'ltc2978'
- Addresses scanned: -
- Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
* ON Semiconductor ADP4000, NCP4200, NCP4208
Prefixes: 'adp4000', 'ncp4200', 'ncp4208'
Addresses scanned: -
@@ -20,6 +15,14 @@ Supported chips:
http://www.onsemi.com/pub_link/Collateral/ADP4000-D.PDF
http://www.onsemi.com/pub_link/Collateral/NCP4200-D.PDF
http://www.onsemi.com/pub_link/Collateral/JUNE%202009-%20REV.%200.PDF
+ * Lineage Power
+ Prefixes: 'pdt003', 'pdt006', 'pdt012', 'udt020'
+ Addresses scanned: -
+ Datasheets:
+ http://www.lineagepower.com/oem/pdf/PDT003A0X.pdf
+ http://www.lineagepower.com/oem/pdf/PDT006A0X.pdf
+ http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf
+ http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf
* Generic PMBus devices
Prefix: 'pmbus'
Addresses scanned: -
diff --git a/Documentation/hwmon/pmbus-core b/Documentation/hwmon/pmbus-core
new file mode 100644
index 000000000000..31e4720fed18
--- /dev/null
+++ b/Documentation/hwmon/pmbus-core
@@ -0,0 +1,283 @@
+PMBus core driver and internal API
+==================================
+
+Introduction
+============
+
+[from pmbus.org] The Power Management Bus (PMBus) is an open standard
+power-management protocol with a fully defined command language that facilitates
+communication with power converters and other devices in a power system. The
+protocol is implemented over the industry-standard SMBus serial interface and
+enables programming, control, and real-time monitoring of compliant power
+conversion products. This flexible and highly versatile standard allows for
+communication between devices based on both analog and digital technologies, and
+provides true interoperability which will reduce design complexity and shorten
+time to market for power system designers. Pioneered by leading power supply and
+semiconductor companies, this open power system standard is maintained and
+promoted by the PMBus Implementers Forum (PMBus-IF), comprising 30+ adopters
+with the objective to provide support to, and facilitate adoption among, users.
+
+Unfortunately, while PMBus commands are standardized, there are no mandatory
+commands, and manufacturers can add as many non-standard commands as they like.
+Also, different PMBUs devices act differently if non-supported commands are
+executed. Some devices return an error, some devices return 0xff or 0xffff and
+set a status error flag, and some devices may simply hang up.
+
+Despite all those difficulties, a generic PMBus device driver is still useful
+and supported since kernel version 2.6.39. However, it was necessary to support
+device specific extensions in addition to the core PMBus driver, since it is
+simply unknown what new device specific functionality PMBus device developers
+come up with next.
+
+To make device specific extensions as scalable as possible, and to avoid having
+to modify the core PMBus driver repeatedly for new devices, the PMBus driver was
+split into core, generic, and device specific code. The core code (in
+pmbus_core.c) provides generic functionality. The generic code (in pmbus.c)
+provides support for generic PMBus devices. Device specific code is responsible
+for device specific initialization and, if needed, maps device specific
+functionality into generic functionality. This is to some degree comparable
+to PCI code, where generic code is augmented as needed with quirks for all kinds
+of devices.
+
+PMBus device capabilities auto-detection
+========================================
+
+For generic PMBus devices, code in pmbus.c attempts to auto-detect all supported
+PMBus commands. Auto-detection is somewhat limited, since there are simply too
+many variables to consider. For example, it is almost impossible to autodetect
+which PMBus commands are paged and which commands are replicated across all
+pages (see the PMBus specification for details on multi-page PMBus devices).
+
+For this reason, it often makes sense to provide a device specific driver if not
+all commands can be auto-detected. The data structures in this driver can be
+used to inform the core driver about functionality supported by individual
+chips.
+
+Some commands are always auto-detected. This applies to all limit commands
+(lcrit, min, max, and crit attributes) as well as associated alarm attributes.
+Limits and alarm attributes are auto-detected because there are simply too many
+possible combinations to provide a manual configuration interface.
+
+PMBus internal API
+==================
+
+The API between core and device specific PMBus code is defined in
+drivers/hwmon/pmbus/pmbus.h. In addition to the internal API, pmbus.h defines
+standard PMBus commands and virtual PMBus commands.
+
+Standard PMBus commands
+-----------------------
+
+Standard PMBus commands (commands values 0x00 to 0xff) are defined in the PMBUs
+specification.
+
+Virtual PMBus commands
+----------------------
+
+Virtual PMBus commands are provided to enable support for non-standard
+functionality which has been implemented by several chip vendors and is thus
+desirable to support.
+
+Virtual PMBus commands start with command value 0x100 and can thus easily be
+distinguished from standard PMBus commands (which can not have values larger
+than 0xff). Support for virtual PMBus commands is device specific and thus has
+to be implemented in device specific code.
+
+Virtual commands are named PMBUS_VIRT_xxx and start with PMBUS_VIRT_BASE. All
+virtual commands are word sized.
+
+There are currently two types of virtual commands.
+
+- READ commands are read-only; writes are either ignored or return an error.
+- RESET commands are read/write. Reading reset registers returns zero
+ (used for detection), writing any value causes the associated history to be
+ reset.
+
+Virtual commands have to be handled in device specific driver code. Chip driver
+code returns non-negative values if a virtual command is supported, or a
+negative error code if not. The chip driver may return -ENODATA or any other
+Linux error code in this case, though an error code other than -ENODATA is
+handled more efficiently and thus preferred. Either case, the calling PMBus
+core code will abort if the chip driver returns an error code when reading
+or writing virtual registers (in other words, the PMBus core code will never
+send a virtual command to a chip).
+
+PMBus driver information
+------------------------
+
+PMBus driver information, defined in struct pmbus_driver_info, is the main means
+for device specific drivers to pass information to the core PMBus driver.
+Specifically, it provides the following information.
+
+- For devices supporting its data in Direct Data Format, it provides coefficients
+ for converting register values into normalized data. This data is usually
+ provided by chip manufacturers in device datasheets.
+- Supported chip functionality can be provided to the core driver. This may be
+ necessary for chips which react badly if non-supported commands are executed,
+ and/or to speed up device detection and initialization.
+- Several function entry points are provided to support overriding and/or
+ augmenting generic command execution. This functionality can be used to map
+ non-standard PMBus commands to standard commands, or to augment standard
+ command return values with device specific information.
+
+ API functions
+ -------------
+
+ Functions provided by chip driver
+ ---------------------------------
+
+ All functions return the command return value (read) or zero (write) if
+ successful. A return value of -ENODATA indicates that there is no manufacturer
+ specific command, but that a standard PMBus command may exist. Any other
+ negative return value indicates that the commands does not exist for this
+ chip, and that no attempt should be made to read or write the standard
+ command.
+
+ As mentioned above, an exception to this rule applies to virtual commands,
+ which _must_ be handled in driver specific code. See "Virtual PMBus Commands"
+ above for more details.
+
+ Command execution in the core PMBus driver code is as follows.
+
+ if (chip_access_function) {
+ status = chip_access_function();
+ if (status != -ENODATA)
+ return status;
+ }
+ if (command >= PMBUS_VIRT_BASE) /* For word commands/registers only */
+ return -EINVAL;
+ return generic_access();
+
+ Chip drivers may provide pointers to the following functions in struct
+ pmbus_driver_info. All functions are optional.
+
+ int (*read_byte_data)(struct i2c_client *client, int page, int reg);
+
+ Read byte from page <page>, register <reg>.
+ <page> may be -1, which means "current page".
+
+ int (*read_word_data)(struct i2c_client *client, int page, int reg);
+
+ Read word from page <page>, register <reg>.
+
+ int (*write_word_data)(struct i2c_client *client, int page, int reg,
+ u16 word);
+
+ Write word to page <page>, register <reg>.
+
+ int (*write_byte)(struct i2c_client *client, int page, u8 value);
+
+ Write byte to page <page>, register <reg>.
+ <page> may be -1, which means "current page".
+
+ int (*identify)(struct i2c_client *client, struct pmbus_driver_info *info);
+
+ Determine supported PMBus functionality. This function is only necessary
+ if a chip driver supports multiple chips, and the chip functionality is not
+ pre-determined. It is currently only used by the generic pmbus driver
+ (pmbus.c).
+
+ Functions exported by core driver
+ ---------------------------------
+
+ Chip drivers are expected to use the following functions to read or write
+ PMBus registers. Chip drivers may also use direct I2C commands. If direct I2C
+ commands are used, the chip driver code must not directly modify the current
+ page, since the selected page is cached in the core driver and the core driver
+ will assume that it is selected. Using pmbus_set_page() to select a new page
+ is mandatory.
+
+ int pmbus_set_page(struct i2c_client *client, u8 page);
+
+ Set PMBus page register to <page> for subsequent commands.
+
+ int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
+
+ Read word data from <page>, <reg>. Similar to i2c_smbus_read_word_data(), but
+ selects page first.
+
+ int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg,
+ u16 word);
+
+ Write word data to <page>, <reg>. Similar to i2c_smbus_write_word_data(), but
+ selects page first.
+
+ int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
+
+ Read byte data from <page>, <reg>. Similar to i2c_smbus_read_byte_data(), but
+ selects page first. <page> may be -1, which means "current page".
+
+ int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
+
+ Write byte data to <page>, <reg>. Similar to i2c_smbus_write_byte(), but
+ selects page first. <page> may be -1, which means "current page".
+
+ void pmbus_clear_faults(struct i2c_client *client);
+
+ Execute PMBus "Clear Fault" command on all chip pages.
+ This function calls the device specific write_byte function if defined.
+ Therefore, it must _not_ be called from that function.
+
+ bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
+
+ Check if byte register exists. Return true if the register exists, false
+ otherwise.
+ This function calls the device specific write_byte function if defined to
+ obtain the chip status. Therefore, it must _not_ be called from that function.
+
+ bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
+
+ Check if word register exists. Return true if the register exists, false
+ otherwise.
+ This function calls the device specific write_byte function if defined to
+ obtain the chip status. Therefore, it must _not_ be called from that function.
+
+ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
+ struct pmbus_driver_info *info);
+
+ Execute probe function. Similar to standard probe function for other drivers,
+ with the pointer to struct pmbus_driver_info as additional argument. Calls
+ identify function if supported. Must only be called from device probe
+ function.
+
+ void pmbus_do_remove(struct i2c_client *client);
+
+ Execute driver remove function. Similar to standard driver remove function.
+
+ const struct pmbus_driver_info
+ *pmbus_get_driver_info(struct i2c_client *client);
+
+ Return pointer to struct pmbus_driver_info as passed to pmbus_do_probe().
+
+
+PMBus driver platform data
+==========================
+
+PMBus platform data is defined in include/linux/i2c/pmbus.h. Platform data
+currently only provides a flag field with a single bit used.
+
+#define PMBUS_SKIP_STATUS_CHECK (1 << 0)
+
+struct pmbus_platform_data {
+ u32 flags; /* Device specific flags */
+};
+
+
+Flags
+-----
+
+PMBUS_SKIP_STATUS_CHECK
+
+During register detection, skip checking the status register for
+communication or command errors.
+
+Some PMBus chips respond with valid data when trying to read an unsupported
+register. For such chips, checking the status register is mandatory when
+trying to determine if a chip register exists or not.
+Other PMBus chips don't support the STATUS_CML register, or report
+communication errors for no explicable reason. For such chips, checking the
+status register must be disabled.
+
+Some i2c controllers do not support single-byte commands (write commands with
+no data, i2c_smbus_write_byte()). With such controllers, clearing the status
+register is impossible, and the PMBUS_SKIP_STATUS_CHECK flag must be set.
diff --git a/Documentation/hwmon/zl6100 b/Documentation/hwmon/zl6100
new file mode 100644
index 000000000000..7617798b5c97
--- /dev/null
+++ b/Documentation/hwmon/zl6100
@@ -0,0 +1,125 @@
+Kernel driver zl6100
+====================
+
+Supported chips:
+ * Intersil / Zilker Labs ZL2004
+ Prefix: 'zl2004'
+ Addresses scanned: -
+ Datasheet: http://www.intersil.com/data/fn/fn6847.pdf
+ * Intersil / Zilker Labs ZL2006
+ Prefix: 'zl2006'
+ Addresses scanned: -
+ Datasheet: http://www.intersil.com/data/fn/fn6850.pdf
+ * Intersil / Zilker Labs ZL2008
+ Prefix: 'zl2008'
+ Addresses scanned: -
+ Datasheet: http://www.intersil.com/data/fn/fn6859.pdf
+ * Intersil / Zilker Labs ZL2105
+ Prefix: 'zl2105'
+ Addresses scanned: -
+ Datasheet: http://www.intersil.com/data/fn/fn6851.pdf
+ * Intersil / Zilker Labs ZL2106
+ Prefix: 'zl2106'
+ Addresses scanned: -
+ Datasheet: http://www.intersil.com/data/fn/fn6852.pdf
+ * Intersil / Zilker Labs ZL6100
+ Prefix: 'zl6100'
+ Addresses scanned: -
+ Datasheet: http://www.intersil.com/data/fn/fn6876.pdf
+ * Intersil / Zilker Labs ZL6105
+ Prefix: 'zl6105'
+ Addresses scanned: -
+ Datasheet: http://www.intersil.com/data/fn/fn6906.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Intersil / Zilker Labs ZL6100 and
+compatible digital DC-DC controllers.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus and Documentation.hwmon/pmbus-core for details
+on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+WARNING: Do not access chip registers using the i2cdump command, and do not use
+any of the i2ctools commands on a command register used to save and restore
+configuration data (0x11, 0x12, 0x15, 0x16, and 0xf4). The chips supported by
+this driver interpret any access to those command registers (including read
+commands) as request to execute the command in question. Unless write accesses
+to those registers are protected, this may result in power loss, board resets,
+and/or Flash corruption. Worst case, your board may turn into a brick.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Module parameters
+-----------------
+
+delay
+-----
+
+Some Intersil/Zilker Labs DC-DC controllers require a minimum interval between
+I2C bus accesses. According to Intersil, the minimum interval is 2 ms, though
+1 ms appears to be sufficient and has not caused any problems in testing.
+The problem is known to affect ZL6100, ZL2105, and ZL2008. It is known not to
+affect ZL2004 and ZL6105. The driver automatically sets the interval to 1 ms
+except for ZL2004 and ZL6105. To enable manual override, the driver provides a
+writeable module parameter, 'delay', which can be used to set the interval to
+a value between 0 and 65,535 microseconds.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in1_label "vin"
+in1_input Measured input voltage.
+in1_min Minimum input voltage.
+in1_max Maximum input voltage.
+in1_lcrit Critical minumum input voltage.
+in1_crit Critical maximum input voltage.
+in1_min_alarm Input voltage low alarm.
+in1_max_alarm Input voltage high alarm.
+in1_lcrit_alarm Input voltage critical low alarm.
+in1_crit_alarm Input voltage critical high alarm.
+
+in2_label "vout1"
+in2_input Measured output voltage.
+in2_lcrit Critical minumum output Voltage.
+in2_crit Critical maximum output voltage.
+in2_lcrit_alarm Critical output voltage critical low alarm.
+in2_crit_alarm Critical output voltage critical high alarm.
+
+curr1_label "iout1"
+curr1_input Measured output current.
+curr1_lcrit Critical minimum output current.
+curr1_crit Critical maximum output current.
+curr1_lcrit_alarm Output current critical low alarm.
+curr1_crit_alarm Output current critical high alarm.
+
+temp[12]_input Measured temperature.
+temp[12]_min Minimum temperature.
+temp[12]_max Maximum temperature.
+temp[12]_lcrit Critical low temperature.
+temp[12]_crit Critical high temperature.
+temp[12]_min_alarm Chip temperature low alarm.
+temp[12]_max_alarm Chip temperature high alarm.
+temp[12]_lcrit_alarm Chip temperature critical low alarm.
+temp[12]_crit_alarm Chip temperature critical high alarm.
diff --git a/Documentation/hwspinlock.txt b/Documentation/hwspinlock.txt
index 7dcd1a4e726c..a903ee5e9776 100644
--- a/Documentation/hwspinlock.txt
+++ b/Documentation/hwspinlock.txt
@@ -39,23 +39,20 @@ independent, drivers.
in case an unused hwspinlock isn't available. Users of this
API will usually want to communicate the lock's id to the remote core
before it can be used to achieve synchronization.
- Can be called from an atomic context (this function will not sleep) but
- not from within interrupt context.
+ Should be called from a process context (might sleep).
struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
- assign a specific hwspinlock id and return its address, or NULL
if that hwspinlock is already in use. Usually board code will
be calling this function in order to reserve specific hwspinlock
ids for predefined purposes.
- Can be called from an atomic context (this function will not sleep) but
- not from within interrupt context.
+ Should be called from a process context (might sleep).
int hwspin_lock_free(struct hwspinlock *hwlock);
- free a previously-assigned hwspinlock; returns 0 on success, or an
appropriate error code on failure (e.g. -EINVAL if the hwspinlock
is already free).
- Can be called from an atomic context (this function will not sleep) but
- not from within interrupt context.
+ Should be called from a process context (might sleep).
int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int timeout);
- lock a previously-assigned hwspinlock with a timeout limit (specified in
@@ -230,45 +227,62 @@ int hwspinlock_example2(void)
4. API for implementors
- int hwspin_lock_register(struct hwspinlock *hwlock);
+ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
+ const struct hwspinlock_ops *ops, int base_id, int num_locks);
- to be called from the underlying platform-specific implementation, in
- order to register a new hwspinlock instance. Can be called from an atomic
- context (this function will not sleep) but not from within interrupt
- context. Returns 0 on success, or appropriate error code on failure.
+ order to register a new hwspinlock device (which is usually a bank of
+ numerous locks). Should be called from a process context (this function
+ might sleep).
+ Returns 0 on success, or appropriate error code on failure.
- struct hwspinlock *hwspin_lock_unregister(unsigned int id);
+ int hwspin_lock_unregister(struct hwspinlock_device *bank);
- to be called from the underlying vendor-specific implementation, in order
- to unregister an existing (and unused) hwspinlock instance.
- Can be called from an atomic context (will not sleep) but not from
- within interrupt context.
+ to unregister an hwspinlock device (which is usually a bank of numerous
+ locks).
+ Should be called from a process context (this function might sleep).
Returns the address of hwspinlock on success, or NULL on error (e.g.
if the hwspinlock is sill in use).
-5. struct hwspinlock
+5. Important structs
-This struct represents an hwspinlock instance. It is registered by the
-underlying hwspinlock implementation using the hwspin_lock_register() API.
+struct hwspinlock_device is a device which usually contains a bank
+of hardware locks. It is registered by the underlying hwspinlock
+implementation using the hwspin_lock_register() API.
/**
- * struct hwspinlock - vendor-specific hwspinlock implementation
- *
- * @dev: underlying device, will be used with runtime PM api
- * @ops: vendor-specific hwspinlock handlers
- * @id: a global, unique, system-wide, index of the lock.
- * @lock: initialized and used by hwspinlock core
- * @owner: underlying implementation module, used to maintain module ref count
+ * struct hwspinlock_device - a device which usually spans numerous hwspinlocks
+ * @dev: underlying device, will be used to invoke runtime PM api
+ * @ops: platform-specific hwspinlock handlers
+ * @base_id: id index of the first lock in this device
+ * @num_locks: number of locks in this device
+ * @lock: dynamically allocated array of 'struct hwspinlock'
*/
-struct hwspinlock {
+struct hwspinlock_device {
struct device *dev;
const struct hwspinlock_ops *ops;
- int id;
+ int base_id;
+ int num_locks;
+ struct hwspinlock lock[0];
+};
+
+struct hwspinlock_device contains an array of hwspinlock structs, each
+of which represents a single hardware lock:
+
+/**
+ * struct hwspinlock - this struct represents a single hwspinlock instance
+ * @bank: the hwspinlock_device structure which owns this lock
+ * @lock: initialized and used by hwspinlock core
+ * @priv: private data, owned by the underlying platform-specific hwspinlock drv
+ */
+struct hwspinlock {
+ struct hwspinlock_device *bank;
spinlock_t lock;
- struct module *owner;
+ void *priv;
};
-The underlying implementation is responsible to assign the dev, ops, id and
-owner members. The lock member, OTOH, is initialized and used by the hwspinlock
-core.
+When registering a bank of locks, the hwspinlock driver only needs to
+set the priv members of the locks. The rest of the members are set and
+initialized by the hwspinlock core itself.
6. Implementation callbacks
diff --git a/Documentation/i2c/smbus-protocol b/Documentation/i2c/smbus-protocol
index 7c19d1a2bea0..49f5b680809d 100644
--- a/Documentation/i2c/smbus-protocol
+++ b/Documentation/i2c/smbus-protocol
@@ -88,6 +88,10 @@ byte. But this time, the data is a complete word (16 bits).
S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
+Note the convenience function i2c_smbus_read_word_swapped is
+available for reads where the two data bytes are the other way
+around (not SMBus compliant, but very popular.)
+
SMBus Write Byte: i2c_smbus_write_byte_data()
==============================================
@@ -108,6 +112,10 @@ specified through the Comm byte.
S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
+Note the convenience function i2c_smbus_write_word_swapped is
+available for writes where the two data bytes are the other way
+around (not SMBus compliant, but very popular.)
+
SMBus Process Call: i2c_smbus_process_call()
=============================================
diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt
index db798af5ef98..5602eb71ad5d 100644
--- a/Documentation/input/elantech.txt
+++ b/Documentation/input/elantech.txt
@@ -16,15 +16,28 @@ Contents
1. Introduction
2. Extra knobs
- 3. Hardware version 1
- 3.1 Registers
- 3.2 Native relative mode 4 byte packet format
- 3.3 Native absolute mode 4 byte packet format
- 4. Hardware version 2
+ 3. Differentiating hardware versions
+ 4. Hardware version 1
4.1 Registers
- 4.2 Native absolute mode 6 byte packet format
- 4.2.1 One finger touch
- 4.2.2 Two finger touch
+ 4.2 Native relative mode 4 byte packet format
+ 4.3 Native absolute mode 4 byte packet format
+ 5. Hardware version 2
+ 5.1 Registers
+ 5.2 Native absolute mode 6 byte packet format
+ 5.2.1 Parity checking and packet re-synchronization
+ 5.2.2 One/Three finger touch
+ 5.2.3 Two finger touch
+ 6. Hardware version 3
+ 6.1 Registers
+ 6.2 Native absolute mode 6 byte packet format
+ 6.2.1 One/Three finger touch
+ 6.2.2 Two finger touch
+ 7. Hardware version 4
+ 7.1 Registers
+ 7.2 Native absolute mode 6 byte packet format
+ 7.2.1 Status packet
+ 7.2.2 Head packet
+ 7.2.3 Motion packet
@@ -375,7 +388,7 @@ For all the other ones, there are just a few constant bits:
In case an error is detected, all the packets are shifted by one (and packet[0] is discarded).
-5.2.1 One/Three finger touch
+5.2.2 One/Three finger touch
~~~~~~~~~~~~~~~~
byte 0:
@@ -384,19 +397,19 @@ byte 0:
n1 n0 w3 w2 . . R L
L, R = 1 when Left, Right mouse button pressed
- n1..n0 = numbers of fingers on touchpad
+ n1..n0 = number of fingers on touchpad
byte 1:
bit 7 6 5 4 3 2 1 0
- p7 p6 p5 p4 . x10 x9 x8
+ p7 p6 p5 p4 x11 x10 x9 x8
byte 2:
bit 7 6 5 4 3 2 1 0
x7 x6 x5 x4 x3 x2 x1 x0
- x10..x0 = absolute x value (horizontal)
+ x11..x0 = absolute x value (horizontal)
byte 3:
@@ -420,7 +433,7 @@ byte 3:
byte 4:
bit 7 6 5 4 3 2 1 0
- p3 p1 p2 p0 . . y9 y8
+ p3 p1 p2 p0 y11 y10 y9 y8
p7..p0 = pressure (not EF113)
@@ -429,10 +442,10 @@ byte 5:
bit 7 6 5 4 3 2 1 0
y7 y6 y5 y4 y3 y2 y1 y0
- y9..y0 = absolute y value (vertical)
+ y11..y0 = absolute y value (vertical)
-4.2.2 Two finger touch
+5.2.3 Two finger touch
~~~~~~~~~~~~~~~~
Note that the two pairs of coordinates are not exactly the coordinates of the
@@ -446,7 +459,7 @@ byte 0:
n1 n0 ay8 ax8 . . R L
L, R = 1 when Left, Right mouse button pressed
- n1..n0 = numbers of fingers on touchpad
+ n1..n0 = number of fingers on touchpad
byte 1:
@@ -480,3 +493,253 @@ byte 5:
by7 by8 by5 by4 by3 by2 by1 by0
by8..by0 = upper-right finger absolute y value
+
+/////////////////////////////////////////////////////////////////////////////
+
+6. Hardware version 3
+ ==================
+
+6.1 Registers
+ ~~~~~~~~~
+* reg_10
+
+ bit 7 6 5 4 3 2 1 0
+ 0 0 0 0 0 0 0 A
+
+ A: 1 = enable absolute tracking
+
+6.2 Native absolute mode 6 byte packet format
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1 and 3 finger touch shares the same 6-byte packet format, except that
+3 finger touch only reports the position of the center of all three fingers.
+
+Firmware would send 12 bytes of data for 2 finger touch.
+
+Note on debounce:
+In case the box has unstable power supply or other electricity issues, or
+when number of finger changes, F/W would send "debounce packet" to inform
+driver that the hardware is in debounce status.
+The debouce packet has the following signature:
+ byte 0: 0xc4
+ byte 1: 0xff
+ byte 2: 0xff
+ byte 3: 0x02
+ byte 4: 0xff
+ byte 5: 0xff
+When we encounter this kind of packet, we just ignore it.
+
+6.2.1 One/Three finger touch
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+byte 0:
+
+ bit 7 6 5 4 3 2 1 0
+ n1 n0 w3 w2 0 1 R L
+
+ L, R = 1 when Left, Right mouse button pressed
+ n1..n0 = number of fingers on touchpad
+
+byte 1:
+
+ bit 7 6 5 4 3 2 1 0
+ p7 p6 p5 p4 x11 x10 x9 x8
+
+byte 2:
+
+ bit 7 6 5 4 3 2 1 0
+ x7 x6 x5 x4 x3 x2 x1 x0
+
+ x11..x0 = absolute x value (horizontal)
+
+byte 3:
+
+ bit 7 6 5 4 3 2 1 0
+ 0 0 w1 w0 0 0 1 0
+
+ w3..w0 = width of the finger touch
+
+byte 4:
+
+ bit 7 6 5 4 3 2 1 0
+ p3 p1 p2 p0 y11 y10 y9 y8
+
+ p7..p0 = pressure
+
+byte 5:
+
+ bit 7 6 5 4 3 2 1 0
+ y7 y6 y5 y4 y3 y2 y1 y0
+
+ y11..y0 = absolute y value (vertical)
+
+6.2.2 Two finger touch
+ ~~~~~~~~~~~~~~~~
+
+The packet format is exactly the same for two finger touch, except the hardware
+sends two 6 byte packets. The first packet contains data for the first finger,
+the second packet has data for the second finger. So for two finger touch a
+total of 12 bytes are sent.
+
+/////////////////////////////////////////////////////////////////////////////
+
+7. Hardware version 4
+ ==================
+
+7.1 Registers
+ ~~~~~~~~~
+* reg_07
+
+ bit 7 6 5 4 3 2 1 0
+ 0 0 0 0 0 0 0 A
+
+ A: 1 = enable absolute tracking
+
+7.2 Native absolute mode 6 byte packet format
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers.
+Unfortunately, due to PS/2's limited bandwidth, its packet format is rather
+complex.
+
+Whenever the numbers or identities of the fingers changes, the hardware sends a
+status packet to indicate how many and which fingers is on touchpad, followed by
+head packets or motion packets. A head packet contains data of finger id, finger
+position (absolute x, y values), width, and pressure. A motion packet contains
+two fingers' position delta.
+
+For example, when status packet tells there are 2 fingers on touchpad, then we
+can expect two following head packets. If the finger status doesn't change,
+the following packets would be motion packets, only sending delta of finger
+position, until we receive a status packet.
+
+One exception is one finger touch. when a status packet tells us there is only
+one finger, the hardware would just send head packets afterwards.
+
+7.2.1 Status packet
+ ~~~~~~~~~~~~~
+
+byte 0:
+
+ bit 7 6 5 4 3 2 1 0
+ . . . . 0 1 R L
+
+ L, R = 1 when Left, Right mouse button pressed
+
+byte 1:
+
+ bit 7 6 5 4 3 2 1 0
+ . . . ft4 ft3 ft2 ft1 ft0
+
+ ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad
+
+byte 2: not used
+
+byte 3:
+
+ bit 7 6 5 4 3 2 1 0
+ . . . 1 0 0 0 0
+
+ constant bits
+
+byte 4:
+
+ bit 7 6 5 4 3 2 1 0
+ p . . . . . . .
+
+ p = 1 for palm
+
+byte 5: not used
+
+7.2.2 Head packet
+ ~~~~~~~~~~~
+
+byte 0:
+
+ bit 7 6 5 4 3 2 1 0
+ w3 w2 w1 w0 0 1 R L
+
+ L, R = 1 when Left, Right mouse button pressed
+ w3..w0 = finger width (spans how many trace lines)
+
+byte 1:
+
+ bit 7 6 5 4 3 2 1 0
+ p7 p6 p5 p4 x11 x10 x9 x8
+
+byte 2:
+
+ bit 7 6 5 4 3 2 1 0
+ x7 x6 x5 x4 x3 x2 x1 x0
+
+ x11..x0 = absolute x value (horizontal)
+
+byte 3:
+
+ bit 7 6 5 4 3 2 1 0
+ id2 id1 id0 1 0 0 0 1
+
+ id2..id0 = finger id
+
+byte 4:
+
+ bit 7 6 5 4 3 2 1 0
+ p3 p1 p2 p0 y11 y10 y9 y8
+
+ p7..p0 = pressure
+
+byte 5:
+
+ bit 7 6 5 4 3 2 1 0
+ y7 y6 y5 y4 y3 y2 y1 y0
+
+ y11..y0 = absolute y value (vertical)
+
+7.2.3 Motion packet
+ ~~~~~~~~~~~~~
+
+byte 0:
+
+ bit 7 6 5 4 3 2 1 0
+ id2 id1 id0 w 0 1 R L
+
+ L, R = 1 when Left, Right mouse button pressed
+ id2..id0 = finger id
+ w = 1 when delta overflows (> 127 or < -128), in this case
+ firmware sends us (delta x / 5) and (delta y / 5)
+
+byte 1:
+
+ bit 7 6 5 4 3 2 1 0
+ x7 x6 x5 x4 x3 x2 x1 x0
+
+ x7..x0 = delta x (two's complement)
+
+byte 2:
+
+ bit 7 6 5 4 3 2 1 0
+ y7 y6 y5 y4 y3 y2 y1 y0
+
+ y7..y0 = delta y (two's complement)
+
+byte 3:
+
+ bit 7 6 5 4 3 2 1 0
+ id2 id1 id0 1 0 0 1 0
+
+ id2..id0 = finger id
+
+byte 4:
+
+ bit 7 6 5 4 3 2 1 0
+ x7 x6 x5 x4 x3 x2 x1 x0
+
+ x7..x0 = delta x (two's complement)
+
+byte 5:
+
+ bit 7 6 5 4 3 2 1 0
+ y7 y6 y5 y4 y3 y2 y1 y0
+
+ y7..y0 = delta y (two's complement)
+
+ byte 0 ~ 2 for one finger
+ byte 3 ~ 5 for another
diff --git a/Documentation/input/input.txt b/Documentation/input/input.txt
index b93c08442e3c..b3d6787b4fb1 100644
--- a/Documentation/input/input.txt
+++ b/Documentation/input/input.txt
@@ -111,7 +111,7 @@ LCDs and many other purposes.
The monitor and speaker controls should be easy to add to the hid/input
interface, but for the UPSs and LCDs it doesn't make much sense. For this,
-the hiddev interface was designed. See Documentation/usb/hiddev.txt
+the hiddev interface was designed. See Documentation/hid/hiddev.txt
for more information about it.
The usage of the usbhid module is very simple, it takes no parameters,
diff --git a/Documentation/input/multi-touch-protocol.txt b/Documentation/input/multi-touch-protocol.txt
index 71536e78406f..543101c5bf26 100644
--- a/Documentation/input/multi-touch-protocol.txt
+++ b/Documentation/input/multi-touch-protocol.txt
@@ -65,6 +65,20 @@ the full state of each initiated contact has to reside in the receiving
end. Upon receiving an MT event, one simply updates the appropriate
attribute of the current slot.
+Some devices identify and/or track more contacts than they can report to the
+driver. A driver for such a device should associate one type B slot with each
+contact that is reported by the hardware. Whenever the identity of the
+contact associated with a slot changes, the driver should invalidate that
+slot by changing its ABS_MT_TRACKING_ID. If the hardware signals that it is
+tracking more contacts than it is currently reporting, the driver should use
+a BTN_TOOL_*TAP event to inform userspace of the total number of contacts
+being tracked by the hardware at that moment. The driver should do this by
+explicitly sending the corresponding BTN_TOOL_*TAP event and setting
+use_count to false when calling input_mt_report_pointer_emulation().
+The driver should only advertise as many slots as the hardware can report.
+Userspace can detect that a driver can report more total contacts than slots
+by noting that the largest supported BTN_TOOL_*TAP event is larger than the
+total number of type B slots reported in the absinfo for the ABS_MT_SLOT axis.
Protocol Example A
------------------
diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt
index 0e0734b509d8..eda1eb1451a0 100644
--- a/Documentation/kernel-docs.txt
+++ b/Documentation/kernel-docs.txt
@@ -300,7 +300,7 @@
* Title: "The Kernel Hacking HOWTO"
Author: Various Talented People, and Rusty.
- Location: in kernel tree, Documentation/DocBook/kernel-hacking/
+ Location: in kernel tree, Documentation/DocBook/kernel-hacking.tmpl
(must be built as "make {htmldocs | psdocs | pdfdocs})
Keywords: HOWTO, kernel contexts, deadlock, locking, modules,
symbols, return conventions.
@@ -351,7 +351,7 @@
* Title: "Linux Kernel Locking HOWTO"
Author: Various Talented People, and Rusty.
- Location: in kernel tree, Documentation/DocBook/kernel-locking/
+ Location: in kernel tree, Documentation/DocBook/kernel-locking.tmpl
(must be built as "make {htmldocs | psdocs | pdfdocs})
Keywords: locks, locking, spinlock, semaphore, atomic, race
condition, bottom halves, tasklets, softirqs.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d6e6724446c8..a0c5c5f4fce6 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -49,6 +49,7 @@ parameter is applicable:
EDD BIOS Enhanced Disk Drive Services (EDD) is enabled
EFI EFI Partitioning (GPT) is enabled
EIDE EIDE/ATAPI support is enabled.
+ EVM Extended Verification Module
FB The frame buffer device is enabled.
FTRACE Function tracing enabled.
GCOV GCOV profiling is enabled.
@@ -163,7 +164,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
rsdt -- prefer RSDT over (default) XSDT
copy_dsdt -- copy DSDT to memory
- See also Documentation/power/pm.txt, pci=noacpi
+ See also Documentation/power/runtime_pm.txt, pci=noacpi
acpi_rsdp= [ACPI,EFI,KEXEC]
Pass the RSDP address to the kernel, mostly used
@@ -306,6 +307,19 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
behaviour to be specified. Bit 0 enables warnings,
bit 1 enables fixups, and bit 2 sends a segfault.
+ align_va_addr= [X86-64]
+ Align virtual addresses by clearing slice [14:12] when
+ allocating a VMA at process creation time. This option
+ gives you up to 3% performance improvement on AMD F15h
+ machines (where it is enabled by default) for a
+ CPU-intensive style benchmark, and it can vary highly in
+ a microbenchmark depending on workload and compiler.
+
+ 1: only for 32-bit processes
+ 2: only for 64-bit processes
+ on: enable for both 32- and 64-bit processes
+ off: disable for both 32- and 64-bit processes
+
amd_iommu= [HW,X86-84]
Pass parameters to the AMD IOMMU driver in the system.
Possible values are:
@@ -319,7 +333,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
amijoy.map= [HW,JOY] Amiga joystick support
Map of devices attached to JOY0DAT and JOY1DAT
Format: <a>,<b>
- See also Documentation/kernel/input/joystick.txt
+ See also Documentation/input/joystick.txt
analog.map= [HW,JOY] Analog joystick and gamepad support
Specifies type or capabilities of an analog joystick
@@ -408,7 +422,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
bttv.radio= Most important insmod options are available as
kernel args too.
bttv.pll= See Documentation/video4linux/bttv/Insmod-options
- bttv.tuner= and Documentation/video4linux/bttv/CARDLIST
+ bttv.tuner=
bulk_remove=off [PPC] This parameter disables the use of the pSeries
firmware feature for flushing multiple hpte entries
@@ -724,13 +738,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
elevator= [IOSCHED]
Format: {"cfq" | "deadline" | "noop"}
- See Documentation/block/as-iosched.txt and
+ See Documentation/block/cfq-iosched.txt and
Documentation/block/deadline-iosched.txt for details.
- elfcorehdr= [IA-64,PPC,SH,X86]
+ elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390]
Specifies physical address of start of kernel core
- image elf header. Generally kexec loader will
- pass this option to capture kernel.
+ image elf header and optionally the size. Generally
+ kexec loader will pass this option to capture kernel.
See Documentation/kdump/kdump.txt for details.
enable_mtrr_cleanup [X86]
@@ -760,12 +774,17 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
This option is obsoleted by the "netdev=" option, which
has equivalent usage. See its documentation for details.
+ evm= [EVM]
+ Format: { "fix" }
+ Permit 'security.evm' to be updated regardless of
+ current integrity status.
+
failslab=
fail_page_alloc=
fail_make_request=[KNL]
General fault injection mechanism.
Format: <interval>,<probability>,<space>,<times>
- See also /Documentation/fault-injection/.
+ See also Documentation/fault-injection/.
floppy= [HW]
See Documentation/blockdev/floppy.txt.
@@ -954,6 +973,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
ignore_loglevel [KNL]
Ignore loglevel setting - this will print /all/
kernel messages to the console. Useful for debugging.
+ We also add it as printk module parameter, so users
+ could change it dynamically, usually by
+ /sys/module/printk/parameters/ignore_loglevel.
ihash_entries= [KNL]
Set number of hash buckets for inode cache.
@@ -1014,10 +1036,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
has the capability. With this option, super page will
not be supported.
intremap= [X86-64, Intel-IOMMU]
- Format: { on (default) | off | nosid }
on enable Interrupt Remapping (default)
off disable Interrupt Remapping
nosid disable Source ID checking
+ no_x2apic_optout
+ BIOS x2APIC opt-out request will be ignored
inttest= [IA-64]
@@ -1181,6 +1204,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
[KVM,Intel] Disable FlexPriority feature (TPR shadow).
Default is 1 (enabled)
+ kvm-intel.nested=
+ [KVM,Intel] Enable VMX nesting (nVMX).
+ Default is 0 (disabled)
+
kvm-intel.unrestricted_guest=
[KVM,Intel] Disable unrestricted guest feature
(virtualized real and unpaged mode) on capable
@@ -1642,6 +1669,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
debugging driver suspend/resume hooks). This may
not work reliably with all consoles, but is known
to work with serial and VGA consoles.
+ To facilitate more flexible debugging, we also add
+ console_suspend, a printk module parameter to control
+ it. Users could use console_suspend (usually
+ /sys/module/printk/parameters/console_suspend) to
+ turn on/off it dynamically.
noaliencache [MM, NUMA, SLAB] Disables the allocation of alien
caches in the slab allocator. Saves per-node memory,
@@ -1777,6 +1809,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
noresidual [PPC] Don't use residual data on PReP machines.
+ nordrand [X86] Disable the direct use of the RDRAND
+ instruction even if it is supported by the
+ processor. RDRAND is still available to user
+ space applications.
+
noresume [SWSUSP] Disables resume and restores original swap
space.
@@ -2240,6 +2277,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
in <PAGE_SIZE> units (needed only for swap files).
See Documentation/power/swsusp-and-swap-files.txt
+ resumedelay= [HIBERNATION] Delay (in seconds) to pause before attempting to
+ read the resume files
+
+ resumewait [HIBERNATION] Wait (indefinitely) for resume device to show up.
+ Useful for devices that are detected asynchronously
+ (e.g. USB and MMC devices).
+
hibernate= [HIBERNATION]
noresume Don't check if there's a hibernation image
present during boot.
@@ -2375,7 +2419,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Format: <integer>
sonypi.*= [HW] Sony Programmable I/O Control Device driver
- See Documentation/sonypi.txt
+ See Documentation/laptops/sonypi.txt
specialix= [HW,SERIAL] Specialix multi-serial port adapter
See Documentation/serial/specialix.txt.
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index 61815483efa3..3ff0dad62d36 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -736,7 +736,7 @@ status as "unknown". The available commands are:
sysfs notes:
The ThinkLight sysfs interface is documented by the LED class
-documentation, in Documentation/leds-class.txt. The ThinkLight LED name
+documentation, in Documentation/leds/leds-class.txt. The ThinkLight LED name
is "tpacpi::thinklight".
Due to limitations in the sysfs LED class, if the status of the ThinkLight
@@ -833,7 +833,7 @@ All of the above can be turned on and off and can be made to blink.
sysfs notes:
The ThinkPad LED sysfs interface is described in detail by the LED class
-documentation, in Documentation/leds-class.txt.
+documentation, in Documentation/leds/leds-class.txt.
The LEDs are named (in LED ID order, from 0 to 12):
"tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt",
diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
index 669b5fb03a86..3a0f879533ce 100644
--- a/Documentation/media-framework.txt
+++ b/Documentation/media-framework.txt
@@ -9,8 +9,8 @@ Introduction
------------
The media controller API is documented in DocBook format in
-Documentation/DocBook/v4l/media-controller.xml. This document will focus on
-the kernel-side implementation of the media framework.
+Documentation/DocBook/media/v4l/media-controller.xml. This document will focus
+on the kernel-side implementation of the media framework.
Abstract media device model
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index f0d3a8026a56..2759f7c188f0 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -438,7 +438,7 @@ There are certain things that the Linux kernel memory barriers do not guarantee:
[*] For information on bus mastering DMA and coherency please read:
Documentation/PCI/pci.txt
- Documentation/PCI/PCI-DMA-mapping.txt
+ Documentation/DMA-API-HOWTO.txt
Documentation/DMA-API.txt
diff --git a/Documentation/networking/LICENSE.qlcnic b/Documentation/networking/LICENSE.qlcnic
index 29ad4b106420..e7fb2c6023bc 100644
--- a/Documentation/networking/LICENSE.qlcnic
+++ b/Documentation/networking/LICENSE.qlcnic
@@ -1,61 +1,22 @@
-Copyright (c) 2009-2010 QLogic Corporation
+Copyright (c) 2009-2011 QLogic Corporation
QLogic Linux qlcnic NIC Driver
-This program includes a device driver for Linux 2.6 that may be
-distributed with QLogic hardware specific firmware binary file.
You may modify and redistribute the device driver code under the
GNU General Public License (a copy of which is attached hereto as
Exhibit A) published by the Free Software Foundation (version 2).
-You may redistribute the hardware specific firmware binary file
-under the following terms:
-
- 1. Redistribution of source code (only if applicable),
- must retain the above copyright notice, this list of
- conditions and the following disclaimer.
-
- 2. Redistribution in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
-
- 3. The name of QLogic Corporation may not be used to
- endorse or promote products derived from this software
- without specific prior written permission
-
-REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
-THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "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
-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.
-
-USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
-CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
-OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
-TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
-ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
-COMBINATION WITH THIS PROGRAM.
-
EXHIBIT A
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
- Preamble
+ Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -105,7 +66,7 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
- GNU GENERAL PUBLIC LICENSE
+ GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@@ -304,7 +265,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
- NO WARRANTY
+ NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index 88d4afbdef98..c86d03f18a5b 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -1,4 +1,4 @@
-[state: 17-04-2011]
+[state: 21-08-2011]
BATMAN-ADV
----------
@@ -68,9 +68,9 @@ All mesh wide settings can be found in batman's own interface
folder:
# ls /sys/class/net/bat0/mesh/
-# aggregated_ogms gw_bandwidth hop_penalty
-# bonding gw_mode orig_interval
-# fragmentation gw_sel_class vis_mode
+# aggregated_ogms fragmentation gw_sel_class vis_mode
+# ap_isolation gw_bandwidth hop_penalty
+# bonding gw_mode orig_interval
There is a special folder for debugging information:
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index ca5cdcd0f0e3..cb7f3148035d 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1045,6 +1045,11 @@ conf/interface/*:
accept_ra - INTEGER
Accept Router Advertisements; autoconfigure using them.
+ It also determines whether or not to transmit Router
+ Solicitations. If and only if the functional setting is to
+ accept Router Advertisements, Router Solicitations will be
+ transmitted.
+
Possible values are:
0 Do not accept Router Advertisements.
1 Accept Router Advertisements if forwarding is disabled.
@@ -1115,14 +1120,14 @@ forwarding - INTEGER
Possible values are:
0 Forwarding disabled
1 Forwarding enabled
- 2 Forwarding enabled (Hybrid Mode)
FALSE (0):
By default, Host behaviour is assumed. This means:
1. IsRouter flag is not set in Neighbour Advertisements.
- 2. Router Solicitations are being sent when necessary.
+ 2. If accept_ra is TRUE (default), transmit Router
+ Solicitations.
3. If accept_ra is TRUE (default), accept Router
Advertisements (and do autoconfiguration).
4. If accept_redirects is TRUE (default), accept Redirects.
@@ -1133,16 +1138,10 @@ forwarding - INTEGER
This means exactly the reverse from the above:
1. IsRouter flag is set in Neighbour Advertisements.
- 2. Router Solicitations are not sent.
+ 2. Router Solicitations are not sent unless accept_ra is 2.
3. Router Advertisements are ignored unless accept_ra is 2.
4. Redirects are ignored.
- TRUE (2):
-
- Hybrid mode. Same behaviour as TRUE, except for:
-
- 2. Router Solicitations are being sent when necessary.
-
Default: 0 (disabled) if global forwarding is disabled (default),
otherwise 1 (enabled).
diff --git a/Documentation/networking/mac80211-injection.txt b/Documentation/networking/mac80211-injection.txt
index b30e81ad5307..3a930072b161 100644
--- a/Documentation/networking/mac80211-injection.txt
+++ b/Documentation/networking/mac80211-injection.txt
@@ -23,6 +23,10 @@ radiotap headers and used to control injection:
IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
current fragmentation threshold.
+ * IEEE80211_RADIOTAP_TX_FLAGS
+
+ IEEE80211_RADIOTAP_F_TX_NOACK: frame should be sent without waiting for
+ an ACK even if it is a unicast frame
The injection code can also skip all other currently defined radiotap fields
facilitating replay of captured radiotap headers directly.
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index 87b3d15f523a..89358341682a 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -73,7 +73,7 @@ dev->hard_start_xmit:
has to lock by itself when needed. It is recommended to use a try lock
for this and return NETDEV_TX_LOCKED when the spin lock fails.
The locking there should also properly protect against
- set_multicast_list. Note that the use of NETIF_F_LLTX is deprecated.
+ set_rx_mode. Note that the use of NETIF_F_LLTX is deprecated.
Don't use it for new drivers.
Context: Process with BHs disabled or BH (timer),
@@ -92,7 +92,7 @@ dev->tx_timeout:
Context: BHs disabled
Notes: netif_queue_stopped() is guaranteed true
-dev->set_multicast_list:
+dev->set_rx_mode:
Synchronization: netif_tx_lock spinlock.
Context: BHs disabled
diff --git a/Documentation/networking/scaling.txt b/Documentation/networking/scaling.txt
index fe67b5c79f0f..a177de21d28e 100644
--- a/Documentation/networking/scaling.txt
+++ b/Documentation/networking/scaling.txt
@@ -73,7 +73,7 @@ of queues to IRQs can be determined from /proc/interrupts. By default,
an IRQ may be handled on any CPU. Because a non-negligible part of packet
processing takes place in receive interrupt handling, it is advantageous
to spread receive interrupts between CPUs. To manually adjust the IRQ
-affinity of each interrupt see Documentation/IRQ-affinity. Some systems
+affinity of each interrupt see Documentation/IRQ-affinity.txt. Some systems
will be running irqbalance, a daemon that dynamically optimizes IRQ
assignments and as a result may override any manual settings.
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 57a24108b845..8d67980fabe8 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -76,7 +76,16 @@ core.
4.5) DMA descriptors
Driver handles both normal and enhanced descriptors. The latter has been only
-tested on DWC Ether MAC 10/100/1000 Universal version 3.41a.
+tested on DWC Ether MAC 10/100/1000 Universal version 3.41a and later.
+
+STMMAC supports DMA descriptor to operate both in dual buffer (RING)
+and linked-list(CHAINED) mode. In RING each descriptor points to two
+data buffer pointers whereas in CHAINED mode they point to only one data
+buffer pointer. RING mode is the default.
+
+In CHAINED mode each descriptor will have pointer to next descriptor in
+the list, hence creating the explicit chaining in the descriptor itself,
+whereas such explicit chaining is not possible in RING mode.
4.6) Ethtool support
Ethtool is supported. Driver statistics and internal errors can be taken using:
@@ -235,7 +244,38 @@ reset procedure etc).
o enh_desc.c: functions for handling enhanced descriptors
o norm_desc.c: functions for handling normal descriptors
-5) TODO:
+5) Debug Information
+
+The driver exports many information i.e. internal statistics,
+debug information, MAC and DMA registers etc.
+
+These can be read in several ways depending on the
+type of the information actually needed.
+
+For example a user can be use the ethtool support
+to get statistics: e.g. using: ethtool -S ethX
+(that shows the Management counters (MMC) if supported)
+or sees the MAC/DMA registers: e.g. using: ethtool -d ethX
+
+Compiling the Kernel with CONFIG_DEBUG_FS and enabling the
+STMMAC_DEBUG_FS option the driver will export the following
+debugfs entries:
+
+/sys/kernel/debug/stmmaceth/descriptors_status
+ To show the DMA TX/RX descriptor rings
+
+Developer can also use the "debug" module parameter to get
+further debug information.
+
+In the end, there are other macros (that cannot be enabled
+via menuconfig) to turn-on the RX/TX DMA debugging,
+specific MAC core debug printk etc. Others to enable the
+debug in the TX and RX processes.
+All these are only useful during the developing stage
+and should never enabled inside the code for general usage.
+In fact, these can generate an huge amount of debug messages.
+
+6) TODO:
o XGMAC is not supported.
o Review the timer optimisation code to use an embedded device that will be
available in new chip generations.
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
new file mode 100644
index 000000000000..b04cb7d45a16
--- /dev/null
+++ b/Documentation/pinctrl.txt
@@ -0,0 +1,950 @@
+PINCTRL (PIN CONTROL) subsystem
+This document outlines the pin control subsystem in Linux
+
+This subsystem deals with:
+
+- Enumerating and naming controllable pins
+
+- Multiplexing of pins, pads, fingers (etc) see below for details
+
+The intention is to also deal with:
+
+- Software-controlled biasing and driving mode specific pins, such as
+ pull-up/down, open drain etc, load capacitance configuration when controlled
+ by software, etc.
+
+
+Top-level interface
+===================
+
+Definition of PIN CONTROLLER:
+
+- A pin controller is a piece of hardware, usually a set of registers, that
+ can control PINs. It may be able to multiplex, bias, set load capacitance,
+ set drive strength etc for individual pins or groups of pins.
+
+Definition of PIN:
+
+- PINS are equal to pads, fingers, balls or whatever packaging input or
+ output line you want to control and these are denoted by unsigned integers
+ in the range 0..maxpin. This numberspace is local to each PIN CONTROLLER, so
+ there may be several such number spaces in a system. This pin space may
+ be sparse - i.e. there may be gaps in the space with numbers where no
+ pin exists.
+
+When a PIN CONTROLLER is instatiated, it will register a descriptor to the
+pin control framework, and this descriptor contains an array of pin descriptors
+describing the pins handled by this specific pin controller.
+
+Here is an example of a PGA (Pin Grid Array) chip seen from underneath:
+
+ A B C D E F G H
+
+ 8 o o o o o o o o
+
+ 7 o o o o o o o o
+
+ 6 o o o o o o o o
+
+ 5 o o o o o o o o
+
+ 4 o o o o o o o o
+
+ 3 o o o o o o o o
+
+ 2 o o o o o o o o
+
+ 1 o o o o o o o o
+
+To register a pin controller and name all the pins on this package we can do
+this in our driver:
+
+#include <linux/pinctrl/pinctrl.h>
+
+const struct pinctrl_pin_desc __refdata foo_pins[] = {
+ PINCTRL_PIN(0, "A1"),
+ PINCTRL_PIN(1, "A2"),
+ PINCTRL_PIN(2, "A3"),
+ ...
+ PINCTRL_PIN(61, "H6"),
+ PINCTRL_PIN(62, "H7"),
+ PINCTRL_PIN(63, "H8"),
+};
+
+static struct pinctrl_desc foo_desc = {
+ .name = "foo",
+ .pins = foo_pins,
+ .npins = ARRAY_SIZE(foo_pins),
+ .maxpin = 63,
+ .owner = THIS_MODULE,
+};
+
+int __init foo_probe(void)
+{
+ struct pinctrl_dev *pctl;
+
+ pctl = pinctrl_register(&foo_desc, <PARENT>, NULL);
+ if (IS_ERR(pctl))
+ pr_err("could not register foo pin driver\n");
+}
+
+Pins usually have fancier names than this. You can find these in the dataheet
+for your chip. Notice that the core pinctrl.h file provides a fancy macro
+called PINCTRL_PIN() to create the struct entries. As you can see I enumerated
+the pins from 0 in the upper left corner to 63 in the lower right corner,
+this enumeration was arbitrarily chosen, in practice you need to think
+through your numbering system so that it matches the layout of registers
+and such things in your driver, or the code may become complicated. You must
+also consider matching of offsets to the GPIO ranges that may be handled by
+the pin controller.
+
+For a padring with 467 pads, as opposed to actual pins, I used an enumeration
+like this, walking around the edge of the chip, which seems to be industry
+standard too (all these pads had names, too):
+
+
+ 0 ..... 104
+ 466 105
+ . .
+ . .
+ 358 224
+ 357 .... 225
+
+
+Pin groups
+==========
+
+Many controllers need to deal with groups of pins, so the pin controller
+subsystem has a mechanism for enumerating groups of pins and retrieving the
+actual enumerated pins that are part of a certain group.
+
+For example, say that we have a group of pins dealing with an SPI interface
+on { 0, 8, 16, 24 }, and a group of pins dealing with an I2C interface on pins
+on { 24, 25 }.
+
+These two groups are presented to the pin control subsystem by implementing
+some generic pinctrl_ops like this:
+
+#include <linux/pinctrl/pinctrl.h>
+
+struct foo_group {
+ const char *name;
+ const unsigned int *pins;
+ const unsigned num_pins;
+};
+
+static unsigned int spi0_pins[] = { 0, 8, 16, 24 };
+static unsigned int i2c0_pins[] = { 24, 25 };
+
+static const struct foo_group foo_groups[] = {
+ {
+ .name = "spi0_grp",
+ .pins = spi0_pins,
+ .num_pins = ARRAY_SIZE(spi0_pins),
+ },
+ {
+ .name = "i2c0_grp",
+ .pins = i2c0_pins,
+ .num_pins = ARRAY_SIZE(i2c0_pins),
+ },
+};
+
+
+static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(foo_groups))
+ return -EINVAL;
+ return 0;
+}
+
+static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return foo_groups[selector].name;
+}
+
+static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned ** const pins,
+ unsigned * const num_pins)
+{
+ *pins = (unsigned *) foo_groups[selector].pins;
+ *num_pins = foo_groups[selector].num_pins;
+ return 0;
+}
+
+static struct pinctrl_ops foo_pctrl_ops = {
+ .list_groups = foo_list_groups,
+ .get_group_name = foo_get_group_name,
+ .get_group_pins = foo_get_group_pins,
+};
+
+
+static struct pinctrl_desc foo_desc = {
+ ...
+ .pctlops = &foo_pctrl_ops,
+};
+
+The pin control subsystem will call the .list_groups() function repeatedly
+beginning on 0 until it returns non-zero to determine legal selectors, then
+it will call the other functions to retrieve the name and pins of the group.
+Maintaining the data structure of the groups is up to the driver, this is
+just a simple example - in practice you may need more entries in your group
+structure, for example specific register ranges associated with each group
+and so on.
+
+
+Interaction with the GPIO subsystem
+===================================
+
+The GPIO drivers may want to perform operations of various types on the same
+physical pins that are also registered as pin controller pins.
+
+Since the pin controller subsystem have its pinspace local to the pin
+controller we need a mapping so that the pin control subsystem can figure out
+which pin controller handles control of a certain GPIO pin. Since a single
+pin controller may be muxing several GPIO ranges (typically SoCs that have
+one set of pins but internally several GPIO silicon blocks, each modeled as
+a struct gpio_chip) any number of GPIO ranges can be added to a pin controller
+instance like this:
+
+struct gpio_chip chip_a;
+struct gpio_chip chip_b;
+
+static struct pinctrl_gpio_range gpio_range_a = {
+ .name = "chip a",
+ .id = 0,
+ .base = 32,
+ .npins = 16,
+ .gc = &chip_a;
+};
+
+static struct pinctrl_gpio_range gpio_range_a = {
+ .name = "chip b",
+ .id = 0,
+ .base = 48,
+ .npins = 8,
+ .gc = &chip_b;
+};
+
+
+{
+ struct pinctrl_dev *pctl;
+ ...
+ pinctrl_add_gpio_range(pctl, &gpio_range_a);
+ pinctrl_add_gpio_range(pctl, &gpio_range_b);
+}
+
+So this complex system has one pin controller handling two different
+GPIO chips. Chip a has 16 pins and chip b has 8 pins. They are mapped in
+the global GPIO pin space at:
+
+chip a: [32 .. 47]
+chip b: [48 .. 55]
+
+When GPIO-specific functions in the pin control subsystem are called, these
+ranges will be used to look up the apropriate pin controller by inspecting
+and matching the pin to the pin ranges across all controllers. When a
+pin controller handling the matching range is found, GPIO-specific functions
+will be called on that specific pin controller.
+
+For all functionalities dealing with pin biasing, pin muxing etc, the pin
+controller subsystem will subtract the range's .base offset from the passed
+in gpio pin number, and pass that on to the pin control driver, so the driver
+will get an offset into its handled number range. Further it is also passed
+the range ID value, so that the pin controller knows which range it should
+deal with.
+
+For example: if a user issues pinctrl_gpio_set_foo(50), the pin control
+subsystem will find that the second range on this pin controller matches,
+subtract the base 48 and call the
+pinctrl_driver_gpio_set_foo(pinctrl, range, 2) where the latter function has
+this signature:
+
+int pinctrl_driver_gpio_set_foo(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *rangeid,
+ unsigned offset);
+
+Now the driver knows that we want to do some GPIO-specific operation on the
+second GPIO range handled by "chip b", at offset 2 in that specific range.
+
+(If the GPIO subsystem is ever refactored to use a local per-GPIO controller
+pin space, this mapping will need to be augmented accordingly.)
+
+
+PINMUX interfaces
+=================
+
+These calls use the pinmux_* naming prefix. No other calls should use that
+prefix.
+
+
+What is pinmuxing?
+==================
+
+PINMUX, also known as padmux, ballmux, alternate functions or mission modes
+is a way for chip vendors producing some kind of electrical packages to use
+a certain physical pin (ball, pad, finger, etc) for multiple mutually exclusive
+functions, depending on the application. By "application" in this context
+we usually mean a way of soldering or wiring the package into an electronic
+system, even though the framework makes it possible to also change the function
+at runtime.
+
+Here is an example of a PGA (Pin Grid Array) chip seen from underneath:
+
+ A B C D E F G H
+ +---+
+ 8 | o | o o o o o o o
+ | |
+ 7 | o | o o o o o o o
+ | |
+ 6 | o | o o o o o o o
+ +---+---+
+ 5 | o | o | o o o o o o
+ +---+---+ +---+
+ 4 o o o o o o | o | o
+ | |
+ 3 o o o o o o | o | o
+ | |
+ 2 o o o o o o | o | o
+ +-------+-------+-------+---+---+
+ 1 | o o | o o | o o | o | o |
+ +-------+-------+-------+---+---+
+
+This is not tetris. The game to think of is chess. Not all PGA/BGA packages
+are chessboard-like, big ones have "holes" in some arrangement according to
+different design patterns, but we're using this as a simple example. Of the
+pins you see some will be taken by things like a few VCC and GND to feed power
+to the chip, and quite a few will be taken by large ports like an external
+memory interface. The remaining pins will often be subject to pin multiplexing.
+
+The example 8x8 PGA package above will have pin numbers 0 thru 63 assigned to
+its physical pins. It will name the pins { A1, A2, A3 ... H6, H7, H8 } using
+pinctrl_register_pins() and a suitable data set as shown earlier.
+
+In this 8x8 BGA package the pins { A8, A7, A6, A5 } can be used as an SPI port
+(these are four pins: CLK, RXD, TXD, FRM). In that case, pin B5 can be used as
+some general-purpose GPIO pin. However, in another setting, pins { A5, B5 } can
+be used as an I2C port (these are just two pins: SCL, SDA). Needless to say,
+we cannot use the SPI port and I2C port at the same time. However in the inside
+of the package the silicon performing the SPI logic can alternatively be routed
+out on pins { G4, G3, G2, G1 }.
+
+On the botton row at { A1, B1, C1, D1, E1, F1, G1, H1 } we have something
+special - it's an external MMC bus that can be 2, 4 or 8 bits wide, and it will
+consume 2, 4 or 8 pins respectively, so either { A1, B1 } are taken or
+{ A1, B1, C1, D1 } or all of them. If we use all 8 bits, we cannot use the SPI
+port on pins { G4, G3, G2, G1 } of course.
+
+This way the silicon blocks present inside the chip can be multiplexed "muxed"
+out on different pin ranges. Often contemporary SoC (systems on chip) will
+contain several I2C, SPI, SDIO/MMC, etc silicon blocks that can be routed to
+different pins by pinmux settings.
+
+Since general-purpose I/O pins (GPIO) are typically always in shortage, it is
+common to be able to use almost any pin as a GPIO pin if it is not currently
+in use by some other I/O port.
+
+
+Pinmux conventions
+==================
+
+The purpose of the pinmux functionality in the pin controller subsystem is to
+abstract and provide pinmux settings to the devices you choose to instantiate
+in your machine configuration. It is inspired by the clk, GPIO and regulator
+subsystems, so devices will request their mux setting, but it's also possible
+to request a single pin for e.g. GPIO.
+
+Definitions:
+
+- FUNCTIONS can be switched in and out by a driver residing with the pin
+ control subsystem in the drivers/pinctrl/* directory of the kernel. The
+ pin control driver knows the possible functions. In the example above you can
+ identify three pinmux functions, one for spi, one for i2c and one for mmc.
+
+- FUNCTIONS are assumed to be enumerable from zero in a one-dimensional array.
+ In this case the array could be something like: { spi0, i2c0, mmc0 }
+ for the three available functions.
+
+- FUNCTIONS have PIN GROUPS as defined on the generic level - so a certain
+ function is *always* associated with a certain set of pin groups, could
+ be just a single one, but could also be many. In the example above the
+ function i2c is associated with the pins { A5, B5 }, enumerated as
+ { 24, 25 } in the controller pin space.
+
+ The Function spi is associated with pin groups { A8, A7, A6, A5 }
+ and { G4, G3, G2, G1 }, which are enumerated as { 0, 8, 16, 24 } and
+ { 38, 46, 54, 62 } respectively.
+
+ Group names must be unique per pin controller, no two groups on the same
+ controller may have the same name.
+
+- The combination of a FUNCTION and a PIN GROUP determine a certain function
+ for a certain set of pins. The knowledge of the functions and pin groups
+ and their machine-specific particulars are kept inside the pinmux driver,
+ from the outside only the enumerators are known, and the driver core can:
+
+ - Request the name of a function with a certain selector (>= 0)
+ - A list of groups associated with a certain function
+ - Request that a certain group in that list to be activated for a certain
+ function
+
+ As already described above, pin groups are in turn self-descriptive, so
+ the core will retrieve the actual pin range in a certain group from the
+ driver.
+
+- FUNCTIONS and GROUPS on a certain PIN CONTROLLER are MAPPED to a certain
+ device by the board file, device tree or similar machine setup configuration
+ mechanism, similar to how regulators are connected to devices, usually by
+ name. Defining a pin controller, function and group thus uniquely identify
+ the set of pins to be used by a certain device. (If only one possible group
+ of pins is available for the function, no group name need to be supplied -
+ the core will simply select the first and only group available.)
+
+ In the example case we can define that this particular machine shall
+ use device spi0 with pinmux function fspi0 group gspi0 and i2c0 on function
+ fi2c0 group gi2c0, on the primary pin controller, we get mappings
+ like these:
+
+ {
+ {"map-spi0", spi0, pinctrl0, fspi0, gspi0},
+ {"map-i2c0", i2c0, pinctrl0, fi2c0, gi2c0}
+ }
+
+ Every map must be assigned a symbolic name, pin controller and function.
+ The group is not compulsory - if it is omitted the first group presented by
+ the driver as applicable for the function will be selected, which is
+ useful for simple cases.
+
+ The device name is present in map entries tied to specific devices. Maps
+ without device names are referred to as SYSTEM pinmuxes, such as can be taken
+ by the machine implementation on boot and not tied to any specific device.
+
+ It is possible to map several groups to the same combination of device,
+ pin controller and function. This is for cases where a certain function on
+ a certain pin controller may use different sets of pins in different
+ configurations.
+
+- PINS for a certain FUNCTION using a certain PIN GROUP on a certain
+ PIN CONTROLLER are provided on a first-come first-serve basis, so if some
+ other device mux setting or GPIO pin request has already taken your physical
+ pin, you will be denied the use of it. To get (activate) a new setting, the
+ old one has to be put (deactivated) first.
+
+Sometimes the documentation and hardware registers will be oriented around
+pads (or "fingers") rather than pins - these are the soldering surfaces on the
+silicon inside the package, and may or may not match the actual number of
+pins/balls underneath the capsule. Pick some enumeration that makes sense to
+you. Define enumerators only for the pins you can control if that makes sense.
+
+Assumptions:
+
+We assume that the number possible function maps to pin groups is limited by
+the hardware. I.e. we assume that there is no system where any function can be
+mapped to any pin, like in a phone exchange. So the available pins groups for
+a certain function will be limited to a few choices (say up to eight or so),
+not hundreds or any amount of choices. This is the characteristic we have found
+by inspecting available pinmux hardware, and a necessary assumption since we
+expect pinmux drivers to present *all* possible function vs pin group mappings
+to the subsystem.
+
+
+Pinmux drivers
+==============
+
+The pinmux core takes care of preventing conflicts on pins and calling
+the pin controller driver to execute different settings.
+
+It is the responsibility of the pinmux driver to impose further restrictions
+(say for example infer electronic limitations due to load etc) to determine
+whether or not the requested function can actually be allowed, and in case it
+is possible to perform the requested mux setting, poke the hardware so that
+this happens.
+
+Pinmux drivers are required to supply a few callback functions, some are
+optional. Usually the enable() and disable() functions are implemented,
+writing values into some certain registers to activate a certain mux setting
+for a certain pin.
+
+A simple driver for the above example will work by setting bits 0, 1, 2, 3 or 4
+into some register named MUX to select a certain function with a certain
+group of pins would work something like this:
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+struct foo_group {
+ const char *name;
+ const unsigned int *pins;
+ const unsigned num_pins;
+};
+
+static const unsigned spi0_0_pins[] = { 0, 8, 16, 24 };
+static const unsigned spi0_1_pins[] = { 38, 46, 54, 62 };
+static const unsigned i2c0_pins[] = { 24, 25 };
+static const unsigned mmc0_1_pins[] = { 56, 57 };
+static const unsigned mmc0_2_pins[] = { 58, 59 };
+static const unsigned mmc0_3_pins[] = { 60, 61, 62, 63 };
+
+static const struct foo_group foo_groups[] = {
+ {
+ .name = "spi0_0_grp",
+ .pins = spi0_0_pins,
+ .num_pins = ARRAY_SIZE(spi0_0_pins),
+ },
+ {
+ .name = "spi0_1_grp",
+ .pins = spi0_1_pins,
+ .num_pins = ARRAY_SIZE(spi0_1_pins),
+ },
+ {
+ .name = "i2c0_grp",
+ .pins = i2c0_pins,
+ .num_pins = ARRAY_SIZE(i2c0_pins),
+ },
+ {
+ .name = "mmc0_1_grp",
+ .pins = mmc0_1_pins,
+ .num_pins = ARRAY_SIZE(mmc0_1_pins),
+ },
+ {
+ .name = "mmc0_2_grp",
+ .pins = mmc0_2_pins,
+ .num_pins = ARRAY_SIZE(mmc0_2_pins),
+ },
+ {
+ .name = "mmc0_3_grp",
+ .pins = mmc0_3_pins,
+ .num_pins = ARRAY_SIZE(mmc0_3_pins),
+ },
+};
+
+
+static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(foo_groups))
+ return -EINVAL;
+ return 0;
+}
+
+static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return foo_groups[selector].name;
+}
+
+static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned ** const pins,
+ unsigned * const num_pins)
+{
+ *pins = (unsigned *) foo_groups[selector].pins;
+ *num_pins = foo_groups[selector].num_pins;
+ return 0;
+}
+
+static struct pinctrl_ops foo_pctrl_ops = {
+ .list_groups = foo_list_groups,
+ .get_group_name = foo_get_group_name,
+ .get_group_pins = foo_get_group_pins,
+};
+
+struct foo_pmx_func {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+};
+
+static const char * const spi0_groups[] = { "spi0_1_grp" };
+static const char * const i2c0_groups[] = { "i2c0_grp" };
+static const char * const mmc0_groups[] = { "mmc0_1_grp", "mmc0_2_grp",
+ "mmc0_3_grp" };
+
+static const struct foo_pmx_func foo_functions[] = {
+ {
+ .name = "spi0",
+ .groups = spi0_groups,
+ .num_groups = ARRAY_SIZE(spi0_groups),
+ },
+ {
+ .name = "i2c0",
+ .groups = i2c0_groups,
+ .num_groups = ARRAY_SIZE(i2c0_groups),
+ },
+ {
+ .name = "mmc0",
+ .groups = mmc0_groups,
+ .num_groups = ARRAY_SIZE(mmc0_groups),
+ },
+};
+
+int foo_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(foo_functions))
+ return -EINVAL;
+ return 0;
+}
+
+const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
+{
+ return myfuncs[selector].name;
+}
+
+static int foo_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = foo_functions[selector].groups;
+ *num_groups = foo_functions[selector].num_groups;
+ return 0;
+}
+
+int foo_enable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ u8 regbit = (1 << group);
+
+ writeb((readb(MUX)|regbit), MUX)
+ return 0;
+}
+
+int foo_disable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ u8 regbit = (1 << group);
+
+ writeb((readb(MUX) & ~(regbit)), MUX)
+ return 0;
+}
+
+struct pinmux_ops foo_pmxops = {
+ .list_functions = foo_list_funcs,
+ .get_function_name = foo_get_fname,
+ .get_function_groups = foo_get_groups,
+ .enable = foo_enable,
+ .disable = foo_disable,
+};
+
+/* Pinmux operations are handled by some pin controller */
+static struct pinctrl_desc foo_desc = {
+ ...
+ .pctlops = &foo_pctrl_ops,
+ .pmxops = &foo_pmxops,
+};
+
+In the example activating muxing 0 and 1 at the same time setting bits
+0 and 1, uses one pin in common so they would collide.
+
+The beauty of the pinmux subsystem is that since it keeps track of all
+pins and who is using them, it will already have denied an impossible
+request like that, so the driver does not need to worry about such
+things - when it gets a selector passed in, the pinmux subsystem makes
+sure no other device or GPIO assignment is already using the selected
+pins. Thus bits 0 and 1 in the control register will never be set at the
+same time.
+
+All the above functions are mandatory to implement for a pinmux driver.
+
+
+Pinmux interaction with the GPIO subsystem
+==========================================
+
+The function list could become long, especially if you can convert every
+individual pin into a GPIO pin independent of any other pins, and then try
+the approach to define every pin as a function.
+
+In this case, the function array would become 64 entries for each GPIO
+setting and then the device functions.
+
+For this reason there is an additional function a pinmux driver can implement
+to enable only GPIO on an individual pin: .gpio_request_enable(). The same
+.free() function as for other functions is assumed to be usable also for
+GPIO pins.
+
+This function will pass in the affected GPIO range identified by the pin
+controller core, so you know which GPIO pins are being affected by the request
+operation.
+
+Alternatively it is fully allowed to use named functions for each GPIO
+pin, the pinmux_request_gpio() will attempt to obtain the function "gpioN"
+where "N" is the global GPIO pin number if no special GPIO-handler is
+registered.
+
+
+Pinmux board/machine configuration
+==================================
+
+Boards and machines define how a certain complete running system is put
+together, including how GPIOs and devices are muxed, how regulators are
+constrained and how the clock tree looks. Of course pinmux settings are also
+part of this.
+
+A pinmux config for a machine looks pretty much like a simple regulator
+configuration, so for the example array above we want to enable i2c and
+spi on the second function mapping:
+
+#include <linux/pinctrl/machine.h>
+
+static struct pinmux_map pmx_mapping[] = {
+ {
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "spi0",
+ .dev_name = "foo-spi.0",
+ },
+ {
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "i2c0",
+ .dev_name = "foo-i2c.0",
+ },
+ {
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "mmc0",
+ .dev_name = "foo-mmc.0",
+ },
+};
+
+The dev_name here matches to the unique device name that can be used to look
+up the device struct (just like with clockdev or regulators). The function name
+must match a function provided by the pinmux driver handling this pin range.
+
+As you can see we may have several pin controllers on the system and thus
+we need to specify which one of them that contain the functions we wish
+to map. The map can also use struct device * directly, so there is no
+inherent need to use strings to specify .dev_name or .ctrl_dev_name, these
+are for the situation where you do not have a handle to the struct device *,
+for example if they are not yet instantiated or cumbersome to obtain.
+
+You register this pinmux mapping to the pinmux subsystem by simply:
+
+ ret = pinmux_register_mappings(&pmx_mapping, ARRAY_SIZE(pmx_mapping));
+
+Since the above construct is pretty common there is a helper macro to make
+it even more compact which assumes you want to use pinctrl.0 and position
+0 for mapping, for example:
+
+static struct pinmux_map pmx_mapping[] = {
+ PINMUX_MAP_PRIMARY("I2CMAP", "i2c0", "foo-i2c.0"),
+};
+
+
+Complex mappings
+================
+
+As it is possible to map a function to different groups of pins an optional
+.group can be specified like this:
+
+...
+{
+ .name = "spi0-pos-A",
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "spi0",
+ .group = "spi0_0_grp",
+ .dev_name = "foo-spi.0",
+},
+{
+ .name = "spi0-pos-B",
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "spi0",
+ .group = "spi0_1_grp",
+ .dev_name = "foo-spi.0",
+},
+...
+
+This example mapping is used to switch between two positions for spi0 at
+runtime, as described further below under the heading "Runtime pinmuxing".
+
+Further it is possible to match several groups of pins to the same function
+for a single device, say for example in the mmc0 example above, where you can
+additively expand the mmc0 bus from 2 to 4 to 8 pins. If we want to use all
+three groups for a total of 2+2+4 = 8 pins (for an 8-bit MMC bus as is the
+case), we define a mapping like this:
+
+...
+{
+ .name "2bit"
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "mmc0",
+ .group = "mmc0_0_grp",
+ .dev_name = "foo-mmc.0",
+},
+{
+ .name "4bit"
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "mmc0",
+ .group = "mmc0_0_grp",
+ .dev_name = "foo-mmc.0",
+},
+{
+ .name "4bit"
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "mmc0",
+ .group = "mmc0_1_grp",
+ .dev_name = "foo-mmc.0",
+},
+{
+ .name "8bit"
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "mmc0",
+ .group = "mmc0_0_grp",
+ .dev_name = "foo-mmc.0",
+},
+{
+ .name "8bit"
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "mmc0",
+ .group = "mmc0_1_grp",
+ .dev_name = "foo-mmc.0",
+},
+{
+ .name "8bit"
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "mmc0",
+ .group = "mmc0_2_grp",
+ .dev_name = "foo-mmc.0",
+},
+...
+
+The result of grabbing this mapping from the device with something like
+this (see next paragraph):
+
+ pmx = pinmux_get(&device, "8bit");
+
+Will be that you activate all the three bottom records in the mapping at
+once. Since they share the same name, pin controller device, funcion and
+device, and since we allow multiple groups to match to a single device, they
+all get selected, and they all get enabled and disable simultaneously by the
+pinmux core.
+
+
+Pinmux requests from drivers
+============================
+
+Generally it is discouraged to let individual drivers get and enable pinmuxes.
+So if possible, handle the pinmuxes in platform code or some other place where
+you have access to all the affected struct device * pointers. In some cases
+where a driver needs to switch between different mux mappings at runtime
+this is not possible.
+
+A driver may request a certain mux to be activated, usually just the default
+mux like this:
+
+#include <linux/pinctrl/pinmux.h>
+
+struct foo_state {
+ struct pinmux *pmx;
+ ...
+};
+
+foo_probe()
+{
+ /* Allocate a state holder named "state" etc */
+ struct pinmux pmx;
+
+ pmx = pinmux_get(&device, NULL);
+ if IS_ERR(pmx)
+ return PTR_ERR(pmx);
+ pinmux_enable(pmx);
+
+ state->pmx = pmx;
+}
+
+foo_remove()
+{
+ pinmux_disable(state->pmx);
+ pinmux_put(state->pmx);
+}
+
+If you want to grab a specific mux mapping and not just the first one found for
+this device you can specify a specific mapping name, for example in the above
+example the second i2c0 setting: pinmux_get(&device, "spi0-pos-B");
+
+This get/enable/disable/put sequence can just as well be handled by bus drivers
+if you don't want each and every driver to handle it and you know the
+arrangement on your bus.
+
+The semantics of the get/enable respective disable/put is as follows:
+
+- pinmux_get() is called in process context to reserve the pins affected with
+ a certain mapping and set up the pinmux core and the driver. It will allocate
+ a struct from the kernel memory to hold the pinmux state.
+
+- pinmux_enable()/pinmux_disable() is quick and can be called from fastpath
+ (irq context) when you quickly want to set up/tear down the hardware muxing
+ when running a device driver. Usually it will just poke some values into a
+ register.
+
+- pinmux_disable() is called in process context to tear down the pin requests
+ and release the state holder struct for the mux setting.
+
+Usually the pinmux core handled the get/put pair and call out to the device
+drivers bookkeeping operations, like checking available functions and the
+associated pins, whereas the enable/disable pass on to the pin controller
+driver which takes care of activating and/or deactivating the mux setting by
+quickly poking some registers.
+
+The pins are allocated for your device when you issue the pinmux_get() call,
+after this you should be able to see this in the debugfs listing of all pins.
+
+
+System pinmux hogging
+=====================
+
+A system pinmux map entry, i.e. a pinmux setting that does not have a device
+associated with it, can be hogged by the core when the pin controller is
+registered. This means that the core will attempt to call pinmux_get() and
+pinmux_enable() on it immediately after the pin control device has been
+registered.
+
+This is enabled by simply setting the .hog_on_boot field in the map to true,
+like this:
+
+{
+ .name "POWERMAP"
+ .ctrl_dev_name = "pinctrl.0",
+ .function = "power_func",
+ .hog_on_boot = true,
+},
+
+Since it may be common to request the core to hog a few always-applicable
+mux settings on the primary pin controller, there is a convenience macro for
+this:
+
+PINMUX_MAP_PRIMARY_SYS_HOG("POWERMAP", "power_func")
+
+This gives the exact same result as the above construction.
+
+
+Runtime pinmuxing
+=================
+
+It is possible to mux a certain function in and out at runtime, say to move
+an SPI port from one set of pins to another set of pins. Say for example for
+spi0 in the example above, we expose two different groups of pins for the same
+function, but with different named in the mapping as described under
+"Advanced mapping" above. So we have two mappings named "spi0-pos-A" and
+"spi0-pos-B".
+
+This snippet first muxes the function in the pins defined by group A, enables
+it, disables and releases it, and muxes it in on the pins defined by group B:
+
+foo_switch()
+{
+ struct pinmux pmx;
+
+ /* Enable on position A */
+ pmx = pinmux_get(&device, "spi0-pos-A");
+ if IS_ERR(pmx)
+ return PTR_ERR(pmx);
+ pinmux_enable(pmx);
+
+ /* This releases the pins again */
+ pinmux_disable(pmx);
+ pinmux_put(pmx);
+
+ /* Enable on position B */
+ pmx = pinmux_get(&device, "spi0-pos-B");
+ if IS_ERR(pmx)
+ return PTR_ERR(pmx);
+ pinmux_enable(pmx);
+ ...
+}
+
+The above has to be done from process context.
diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX
index 45e9d4a91284..a4d682f54231 100644
--- a/Documentation/power/00-INDEX
+++ b/Documentation/power/00-INDEX
@@ -26,6 +26,8 @@ s2ram.txt
- How to get suspend to ram working (and debug it when it isn't)
states.txt
- System power management states
+suspend-and-cpuhotplug.txt
+ - Explains the interaction between Suspend-to-RAM (S3) and CPU hotplug
swsusp-and-swap-files.txt
- Using swap files with software suspend (to disk)
swsusp-dmcrypt.txt
diff --git a/Documentation/power/basic-pm-debugging.txt b/Documentation/power/basic-pm-debugging.txt
index ddd78172ef73..40a4c65f380a 100644
--- a/Documentation/power/basic-pm-debugging.txt
+++ b/Documentation/power/basic-pm-debugging.txt
@@ -173,7 +173,7 @@ kernel messages using the serial console. This may provide you with some
information about the reasons of the suspend (resume) failure. Alternatively,
it may be possible to use a FireWire port for debugging with firescope
(ftp://ftp.firstfloor.org/pub/ak/firescope/). On x86 it is also possible to
-use the PM_TRACE mechanism documented in Documentation/s2ram.txt .
+use the PM_TRACE mechanism documented in Documentation/power/s2ram.txt .
2. Testing suspend to RAM (STR)
@@ -201,3 +201,27 @@ case, you may be able to search for failing drivers by following the procedure
analogous to the one described in section 1. If you find some failing drivers,
you will have to unload them every time before an STR transition (ie. before
you run s2ram), and please report the problems with them.
+
+There is a debugfs entry which shows the suspend to RAM statistics. Here is an
+example of its output.
+ # mount -t debugfs none /sys/kernel/debug
+ # cat /sys/kernel/debug/suspend_stats
+ success: 20
+ fail: 5
+ failed_freeze: 0
+ failed_prepare: 0
+ failed_suspend: 5
+ failed_suspend_noirq: 0
+ failed_resume: 0
+ failed_resume_noirq: 0
+ failures:
+ last_failed_dev: alarm
+ adc
+ last_failed_errno: -16
+ -16
+ last_failed_step: suspend
+ suspend
+Field success means the success number of suspend to RAM, and field fail means
+the failure number. Others are the failure number of different steps of suspend
+to RAM. suspend_stats just lists the last 2 failed devices, error number and
+failed step of suspend.
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 3384d5996be2..646a89e0c07d 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -152,7 +152,9 @@ try to use its wakeup mechanism. device_set_wakeup_enable() affects this flag;
for the most part drivers should not change its value. The initial value of
should_wakeup is supposed to be false for the majority of devices; the major
exceptions are power buttons, keyboards, and Ethernet adapters whose WoL
-(wake-on-LAN) feature has been set up with ethtool.
+(wake-on-LAN) feature has been set up with ethtool. It should also default
+to true for devices that don't generate wakeup requests on their own but merely
+forward wakeup requests from one bus to another (like PCI bridges).
Whether or not a device is capable of issuing wakeup events is a hardware
matter, and the kernel is responsible for keeping track of it. By contrast,
@@ -279,10 +281,6 @@ When the system goes into the standby or memory sleep state, the phases are:
time.) Unlike the other suspend-related phases, during the prepare
phase the device tree is traversed top-down.
- In addition to that, if device drivers need to allocate additional
- memory to be able to hadle device suspend correctly, that should be
- done in the prepare phase.
-
After the prepare callback method returns, no new children may be
registered below the device. The method may also prepare the device or
driver in some way for the upcoming system power transition (for
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index bfed898a03fc..17e130a80347 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -4,14 +4,19 @@ This interface provides a kernel and user mode interface for registering
performance expectations by drivers, subsystems and user space applications on
one of the parameters.
-Currently we have {cpu_dma_latency, network_latency, network_throughput} as the
-initial set of pm_qos parameters.
+Two different PM QoS frameworks are available:
+1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput.
+2. the per-device PM QoS framework provides the API to manage the per-device latency
+constraints.
Each parameters have defined units:
* latency: usec
* timeout: usec
* throughput: kbs (kilo bit / sec)
+
+1. PM QoS framework
+
The infrastructure exposes multiple misc device nodes one per implemented
parameter. The set of parameters implement is defined by pm_qos_power_init()
and pm_qos_params.h. This is done because having the available parameters
@@ -23,14 +28,18 @@ an aggregated target value. The aggregated target value is updated with
changes to the request list or elements of the list. Typically the
aggregated target value is simply the max or min of the request values held
in the parameter list elements.
+Note: the aggregated target value is implemented as an atomic variable so that
+reading the aggregated value does not require any locking mechanism.
+
From kernel mode the use of this interface is simple:
-handle = pm_qos_add_request(param_class, target_value):
-Will insert an element into the list for that identified PM_QOS class with the
+void pm_qos_add_request(handle, param_class, target_value):
+Will insert an element into the list for that identified PM QoS class with the
target value. Upon change to this list the new target is recomputed and any
registered notifiers are called only if the target value is now different.
-Clients of pm_qos need to save the returned handle.
+Clients of pm_qos need to save the returned handle for future use in other
+pm_qos API functions.
void pm_qos_update_request(handle, new_target_value):
Will update the list element pointed to by the handle with the new target value
@@ -42,6 +51,20 @@ Will remove the element. After removal it will update the aggregate target and
call the notification tree if the target was changed as a result of removing
the request.
+int pm_qos_request(param_class):
+Returns the aggregated value for a given PM QoS class.
+
+int pm_qos_request_active(handle):
+Returns if the request is still active, i.e. it has not been removed from a
+PM QoS class constraints list.
+
+int pm_qos_add_notifier(param_class, notifier):
+Adds a notification callback function to the PM QoS class. The callback is
+called when the aggregated value for the PM QoS class is changed.
+
+int pm_qos_remove_notifier(int param_class, notifier):
+Removes the notification callback function for the PM QoS class.
+
From user mode:
Only processes can register a pm_qos request. To provide for automatic
@@ -63,4 +86,63 @@ To remove the user mode request for a target value simply close the device
node.
+2. PM QoS per-device latency framework
+
+For each device a list of performance requests is maintained along with
+an aggregated target value. The aggregated target value is updated with
+changes to the request list or elements of the list. Typically the
+aggregated target value is simply the max or min of the request values held
+in the parameter list elements.
+Note: the aggregated target value is implemented as an atomic variable so that
+reading the aggregated value does not require any locking mechanism.
+
+
+From kernel mode the use of this interface is the following:
+
+int dev_pm_qos_add_request(device, handle, value):
+Will insert an element into the list for that identified device with the
+target value. Upon change to this list the new target is recomputed and any
+registered notifiers are called only if the target value is now different.
+Clients of dev_pm_qos need to save the handle for future use in other
+dev_pm_qos API functions.
+
+int dev_pm_qos_update_request(handle, new_value):
+Will update the list element pointed to by the handle with the new target value
+and recompute the new aggregated target, calling the notification trees if the
+target is changed.
+
+int dev_pm_qos_remove_request(handle):
+Will remove the element. After removal it will update the aggregate target and
+call the notification trees if the target was changed as a result of removing
+the request.
+
+s32 dev_pm_qos_read_value(device):
+Returns the aggregated value for a given device's constraints list.
+
+
+Notification mechanisms:
+The per-device PM QoS framework has 2 different and distinct notification trees:
+a per-device notification tree and a global notification tree.
+
+int dev_pm_qos_add_notifier(device, notifier):
+Adds a notification callback function for the device.
+The callback is called when the aggregated value of the device constraints list
+is changed.
+
+int dev_pm_qos_remove_notifier(device, notifier):
+Removes the notification callback function for the device.
+
+int dev_pm_qos_add_global_notifier(notifier):
+Adds a notification callback function in the global notification tree of the
+framework.
+The callback is called when the aggregated value for any device is changed.
+
+int dev_pm_qos_remove_global_notifier(notifier):
+Removes the notification callback function from the global notification tree
+of the framework.
+
+
+From user mode:
+No API for user space access to the per-device latency constraints is provided
+yet - still under discussion.
diff --git a/Documentation/power/regulator/machine.txt b/Documentation/power/regulator/machine.txt
index b42419b52e44..ce63af0a8e35 100644
--- a/Documentation/power/regulator/machine.txt
+++ b/Documentation/power/regulator/machine.txt
@@ -16,7 +16,7 @@ initialisation code by creating a struct regulator_consumer_supply for
each regulator.
struct regulator_consumer_supply {
- struct device *dev; /* consumer */
+ const char *dev_name; /* consumer dev_name() */
const char *supply; /* consumer supply - e.g. "vcc" */
};
@@ -24,13 +24,13 @@ e.g. for the machine above
static struct regulator_consumer_supply regulator1_consumers[] = {
{
- .dev = &platform_consumerB_device.dev,
- .supply = "Vcc",
+ .dev_name = "dev_name(consumer B)",
+ .supply = "Vcc",
},};
static struct regulator_consumer_supply regulator2_consumers[] = {
{
- .dev = &platform_consumerA_device.dev,
+ .dev = "dev_name(consumer A"),
.supply = "Vcc",
},};
@@ -43,6 +43,7 @@ to their supply regulator :-
static struct regulator_init_data regulator1_data = {
.constraints = {
+ .name = "Regulator-1",
.min_uV = 3300000,
.max_uV = 3300000,
.valid_modes_mask = REGULATOR_MODE_NORMAL,
@@ -51,13 +52,19 @@ static struct regulator_init_data regulator1_data = {
.consumer_supplies = regulator1_consumers,
};
+The name field should be set to something that is usefully descriptive
+for the board for configuration of supplies for other regulators and
+for use in logging and other diagnostic output. Normally the name
+used for the supply rail in the schematic is a good choice. If no
+name is provided then the subsystem will choose one.
+
Regulator-1 supplies power to Regulator-2. This relationship must be registered
with the core so that Regulator-1 is also enabled when Consumer A enables its
supply (Regulator-2). The supply regulator is set by the supply_regulator
-field below:-
+field below and co:-
static struct regulator_init_data regulator2_data = {
- .supply_regulator = "regulator_name",
+ .supply_regulator = "Regulator-1",
.constraints = {
.min_uV = 1800000,
.max_uV = 2000000,
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index 6066e3a6b9a9..0e856088db7c 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -43,13 +43,18 @@ struct dev_pm_ops {
...
};
-The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are
-executed by the PM core for either the device type, or the class (if the device
-type's struct dev_pm_ops object does not exist), or the bus type (if the
-device type's and class' struct dev_pm_ops objects do not exist) of the given
-device (this allows device types to override callbacks provided by bus types or
-classes if necessary). The bus type, device type and class callbacks are
-referred to as subsystem-level callbacks in what follows.
+The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks
+are executed by the PM core for either the power domain, or the device type
+(if the device power domain's struct dev_pm_ops does not exist), or the class
+(if the device power domain's and type's struct dev_pm_ops object does not
+exist), or the bus type (if the device power domain's, type's and class'
+struct dev_pm_ops objects do not exist) of the given device, so the priority
+order of callbacks from high to low is that power domain callbacks, device
+type callbacks, class callbacks and bus type callbacks, and the high priority
+one will take precedence over low priority one. The bus type, device type and
+class callbacks are referred to as subsystem-level callbacks in what follows,
+and generally speaking, the power domain callbacks are used for representing
+power domains within a SoC.
By default, the callbacks are always invoked in process context with interrupts
enabled. However, subsystems can use the pm_runtime_irq_safe() helper function
@@ -477,12 +482,14 @@ pm_runtime_autosuspend_expiration()
If pm_runtime_irq_safe() has been called for a device then the following helper
functions may also be used in interrupt context:
+pm_runtime_idle()
pm_runtime_suspend()
pm_runtime_autosuspend()
pm_runtime_resume()
pm_runtime_get_sync()
pm_runtime_put_sync()
pm_runtime_put_sync_suspend()
+pm_runtime_put_sync_autosuspend()
5. Runtime PM Initialization, Device Probing and Removal
diff --git a/Documentation/power/suspend-and-cpuhotplug.txt b/Documentation/power/suspend-and-cpuhotplug.txt
new file mode 100644
index 000000000000..f28f9a6f0347
--- /dev/null
+++ b/Documentation/power/suspend-and-cpuhotplug.txt
@@ -0,0 +1,275 @@
+Interaction of Suspend code (S3) with the CPU hotplug infrastructure
+
+ (C) 2011 Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
+
+
+I. How does the regular CPU hotplug code differ from how the Suspend-to-RAM
+ infrastructure uses it internally? And where do they share common code?
+
+Well, a picture is worth a thousand words... So ASCII art follows :-)
+
+[This depicts the current design in the kernel, and focusses only on the
+interactions involving the freezer and CPU hotplug and also tries to explain
+the locking involved. It outlines the notifications involved as well.
+But please note that here, only the call paths are illustrated, with the aim
+of describing where they take different paths and where they share code.
+What happens when regular CPU hotplug and Suspend-to-RAM race with each other
+is not depicted here.]
+
+On a high level, the suspend-resume cycle goes like this:
+
+|Freeze| -> |Disable nonboot| -> |Do suspend| -> |Enable nonboot| -> |Thaw |
+|tasks | | cpus | | | | cpus | |tasks|
+
+
+More details follow:
+
+ Suspend call path
+ -----------------
+
+ Write 'mem' to
+ /sys/power/state
+ syfs file
+ |
+ v
+ Acquire pm_mutex lock
+ |
+ v
+ Send PM_SUSPEND_PREPARE
+ notifications
+ |
+ v
+ Freeze tasks
+ |
+ |
+ v
+ disable_nonboot_cpus()
+ /* start */
+ |
+ v
+ Acquire cpu_add_remove_lock
+ |
+ v
+ Iterate over CURRENTLY
+ online CPUs
+ |
+ |
+ | ----------
+ v | L
+ ======> _cpu_down() |
+ | [This takes cpuhotplug.lock |
+ Common | before taking down the CPU |
+ code | and releases it when done] | O
+ | While it is at it, notifications |
+ | are sent when notable events occur, |
+ ======> by running all registered callbacks. |
+ | | O
+ | |
+ | |
+ v |
+ Note down these cpus in | P
+ frozen_cpus mask ----------
+ |
+ v
+ Disable regular cpu hotplug
+ by setting cpu_hotplug_disabled=1
+ |
+ v
+ Release cpu_add_remove_lock
+ |
+ v
+ /* disable_nonboot_cpus() complete */
+ |
+ v
+ Do suspend
+
+
+
+Resuming back is likewise, with the counterparts being (in the order of
+execution during resume):
+* enable_nonboot_cpus() which involves:
+ | Acquire cpu_add_remove_lock
+ | Reset cpu_hotplug_disabled to 0, thereby enabling regular cpu hotplug
+ | Call _cpu_up() [for all those cpus in the frozen_cpus mask, in a loop]
+ | Release cpu_add_remove_lock
+ v
+
+* thaw tasks
+* send PM_POST_SUSPEND notifications
+* Release pm_mutex lock.
+
+
+It is to be noted here that the pm_mutex lock is acquired at the very
+beginning, when we are just starting out to suspend, and then released only
+after the entire cycle is complete (i.e., suspend + resume).
+
+
+
+ Regular CPU hotplug call path
+ -----------------------------
+
+ Write 0 (or 1) to
+ /sys/devices/system/cpu/cpu*/online
+ sysfs file
+ |
+ |
+ v
+ cpu_down()
+ |
+ v
+ Acquire cpu_add_remove_lock
+ |
+ v
+ If cpu_hotplug_disabled is 1
+ return gracefully
+ |
+ |
+ v
+ ======> _cpu_down()
+ | [This takes cpuhotplug.lock
+ Common | before taking down the CPU
+ code | and releases it when done]
+ | While it is at it, notifications
+ | are sent when notable events occur,
+ ======> by running all registered callbacks.
+ |
+ |
+ v
+ Release cpu_add_remove_lock
+ [That's it!, for
+ regular CPU hotplug]
+
+
+
+So, as can be seen from the two diagrams (the parts marked as "Common code"),
+regular CPU hotplug and the suspend code path converge at the _cpu_down() and
+_cpu_up() functions. They differ in the arguments passed to these functions,
+in that during regular CPU hotplug, 0 is passed for the 'tasks_frozen'
+argument. But during suspend, since the tasks are already frozen by the time
+the non-boot CPUs are offlined or onlined, the _cpu_*() functions are called
+with the 'tasks_frozen' argument set to 1.
+[See below for some known issues regarding this.]
+
+
+Important files and functions/entry points:
+------------------------------------------
+
+kernel/power/process.c : freeze_processes(), thaw_processes()
+kernel/power/suspend.c : suspend_prepare(), suspend_enter(), suspend_finish()
+kernel/cpu.c: cpu_[up|down](), _cpu_[up|down](), [disable|enable]_nonboot_cpus()
+
+
+
+II. What are the issues involved in CPU hotplug?
+ -------------------------------------------
+
+There are some interesting situations involving CPU hotplug and microcode
+update on the CPUs, as discussed below:
+
+[Please bear in mind that the kernel requests the microcode images from
+userspace, using the request_firmware() function defined in
+drivers/base/firmware_class.c]
+
+
+a. When all the CPUs are identical:
+
+ This is the most common situation and it is quite straightforward: we want
+ to apply the same microcode revision to each of the CPUs.
+ To give an example of x86, the collect_cpu_info() function defined in
+ arch/x86/kernel/microcode_core.c helps in discovering the type of the CPU
+ and thereby in applying the correct microcode revision to it.
+ But note that the kernel does not maintain a common microcode image for the
+ all CPUs, in order to handle case 'b' described below.
+
+
+b. When some of the CPUs are different than the rest:
+
+ In this case since we probably need to apply different microcode revisions
+ to different CPUs, the kernel maintains a copy of the correct microcode
+ image for each CPU (after appropriate CPU type/model discovery using
+ functions such as collect_cpu_info()).
+
+
+c. When a CPU is physically hot-unplugged and a new (and possibly different
+ type of) CPU is hot-plugged into the system:
+
+ In the current design of the kernel, whenever a CPU is taken offline during
+ a regular CPU hotplug operation, upon receiving the CPU_DEAD notification
+ (which is sent by the CPU hotplug code), the microcode update driver's
+ callback for that event reacts by freeing the kernel's copy of the
+ microcode image for that CPU.
+
+ Hence, when a new CPU is brought online, since the kernel finds that it
+ doesn't have the microcode image, it does the CPU type/model discovery
+ afresh and then requests the userspace for the appropriate microcode image
+ for that CPU, which is subsequently applied.
+
+ For example, in x86, the mc_cpu_callback() function (which is the microcode
+ update driver's callback registered for CPU hotplug events) calls
+ microcode_update_cpu() which would call microcode_init_cpu() in this case,
+ instead of microcode_resume_cpu() when it finds that the kernel doesn't
+ have a valid microcode image. This ensures that the CPU type/model
+ discovery is performed and the right microcode is applied to the CPU after
+ getting it from userspace.
+
+
+d. Handling microcode update during suspend/hibernate:
+
+ Strictly speaking, during a CPU hotplug operation which does not involve
+ physically removing or inserting CPUs, the CPUs are not actually powered
+ off during a CPU offline. They are just put to the lowest C-states possible.
+ Hence, in such a case, it is not really necessary to re-apply microcode
+ when the CPUs are brought back online, since they wouldn't have lost the
+ image during the CPU offline operation.
+
+ This is the usual scenario encountered during a resume after a suspend.
+ However, in the case of hibernation, since all the CPUs are completely
+ powered off, during restore it becomes necessary to apply the microcode
+ images to all the CPUs.
+
+ [Note that we don't expect someone to physically pull out nodes and insert
+ nodes with a different type of CPUs in-between a suspend-resume or a
+ hibernate/restore cycle.]
+
+ In the current design of the kernel however, during a CPU offline operation
+ as part of the suspend/hibernate cycle (the CPU_DEAD_FROZEN notification),
+ the existing copy of microcode image in the kernel is not freed up.
+ And during the CPU online operations (during resume/restore), since the
+ kernel finds that it already has copies of the microcode images for all the
+ CPUs, it just applies them to the CPUs, avoiding any re-discovery of CPU
+ type/model and the need for validating whether the microcode revisions are
+ right for the CPUs or not (due to the above assumption that physical CPU
+ hotplug will not be done in-between suspend/resume or hibernate/restore
+ cycles).
+
+
+III. Are there any known problems when regular CPU hotplug and suspend race
+ with each other?
+
+Yes, they are listed below:
+
+1. When invoking regular CPU hotplug, the 'tasks_frozen' argument passed to
+ the _cpu_down() and _cpu_up() functions is *always* 0.
+ This might not reflect the true current state of the system, since the
+ tasks could have been frozen by an out-of-band event such as a suspend
+ operation in progress. Hence, it will lead to wrong notifications being
+ sent during the cpu online/offline events (eg, CPU_ONLINE notification
+ instead of CPU_ONLINE_FROZEN) which in turn will lead to execution of
+ inappropriate code by the callbacks registered for such CPU hotplug events.
+
+2. If a regular CPU hotplug stress test happens to race with the freezer due
+ to a suspend operation in progress at the same time, then we could hit the
+ situation described below:
+
+ * A regular cpu online operation continues its journey from userspace
+ into the kernel, since the freezing has not yet begun.
+ * Then freezer gets to work and freezes userspace.
+ * If cpu online has not yet completed the microcode update stuff by now,
+ it will now start waiting on the frozen userspace in the
+ TASK_UNINTERRUPTIBLE state, in order to get the microcode image.
+ * Now the freezer continues and tries to freeze the remaining tasks. But
+ due to this wait mentioned above, the freezer won't be able to freeze
+ the cpu online hotplug task and hence freezing of tasks fails.
+
+ As a result of this task freezing failure, the suspend operation gets
+ aborted.
diff --git a/Documentation/power/userland-swsusp.txt b/Documentation/power/userland-swsusp.txt
index 1101bee4e822..0e870825c1b9 100644
--- a/Documentation/power/userland-swsusp.txt
+++ b/Documentation/power/userland-swsusp.txt
@@ -77,7 +77,8 @@ SNAPSHOT_SET_SWAP_AREA - set the resume partition and the offset (in <PAGE_SIZE>
resume_swap_area, as defined in kernel/power/suspend_ioctls.h,
containing the resume device specification and the offset); for swap
partitions the offset is always 0, but it is different from zero for
- swap files (see Documentation/swsusp-and-swap-files.txt for details).
+ swap files (see Documentation/power/swsusp-and-swap-files.txt for
+ details).
SNAPSHOT_PLATFORM_SUPPORT - enable/disable the hibernation platform support,
depending on the argument value (enable, if the argument is nonzero)
diff --git a/Documentation/rapidio/rapidio.txt b/Documentation/rapidio/rapidio.txt
index be70ee15f8ca..c75694b35d08 100644
--- a/Documentation/rapidio/rapidio.txt
+++ b/Documentation/rapidio/rapidio.txt
@@ -144,7 +144,7 @@ and the default device ID in order to access the device on the active port.
After the host has completed enumeration of the entire network it releases
devices by clearing device ID locks (calls rio_clear_locks()). For each endpoint
-in the system, it sets the Master Enable bit in the Port General Control CSR
+in the system, it sets the Discovered bit in the Port General Control CSR
to indicate that enumeration is completed and agents are allowed to execute
passive discovery of the network.
diff --git a/Documentation/rapidio/tsi721.txt b/Documentation/rapidio/tsi721.txt
new file mode 100644
index 000000000000..335f3c6087dc
--- /dev/null
+++ b/Documentation/rapidio/tsi721.txt
@@ -0,0 +1,49 @@
+RapidIO subsystem mport driver for IDT Tsi721 PCI Express-to-SRIO bridge.
+=========================================================================
+
+I. Overview
+
+This driver implements all currently defined RapidIO mport callback functions.
+It supports maintenance read and write operations, inbound and outbound RapidIO
+doorbells, inbound maintenance port-writes and RapidIO messaging.
+
+To generate SRIO maintenance transactions this driver uses one of Tsi721 DMA
+channels. This mechanism provides access to larger range of hop counts and
+destination IDs without need for changes in outbound window translation.
+
+RapidIO messaging support uses dedicated messaging channels for each mailbox.
+For inbound messages this driver uses destination ID matching to forward messages
+into the corresponding message queue. Messaging callbacks are implemented to be
+fully compatible with RIONET driver (Ethernet over RapidIO messaging services).
+
+II. Known problems
+
+ None.
+
+III. To do
+
+ Add DMA data transfers (non-messaging).
+ Add inbound region (SRIO-to-PCIe) mapping.
+
+IV. Version History
+
+ 1.0.0 - Initial driver release.
+
+V. License
+-----------------------------------------------
+
+ Copyright(c) 2011 Integrated Device Technology, Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; 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.
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt
index 83668e5dd17f..03c9d9299c6b 100644
--- a/Documentation/rfkill.txt
+++ b/Documentation/rfkill.txt
@@ -117,5 +117,4 @@ The contents of these variables corresponds to the "name", "state" and
"type" sysfs files explained above.
-For further details consult Documentation/ABI/stable/dev-rfkill and
-Documentation/ABI/stable/sysfs-class-rfkill.
+For further details consult Documentation/ABI/stable/sysfs-class-rfkill.
diff --git a/Documentation/scheduler/sched-bwc.txt b/Documentation/scheduler/sched-bwc.txt
new file mode 100644
index 000000000000..f6b1873f68ab
--- /dev/null
+++ b/Documentation/scheduler/sched-bwc.txt
@@ -0,0 +1,122 @@
+CFS Bandwidth Control
+=====================
+
+[ This document only discusses CPU bandwidth control for SCHED_NORMAL.
+ The SCHED_RT case is covered in Documentation/scheduler/sched-rt-group.txt ]
+
+CFS bandwidth control is a CONFIG_FAIR_GROUP_SCHED extension which allows the
+specification of the maximum CPU bandwidth available to a group or hierarchy.
+
+The bandwidth allowed for a group is specified using a quota and period. Within
+each given "period" (microseconds), a group is allowed to consume only up to
+"quota" microseconds of CPU time. When the CPU bandwidth consumption of a
+group exceeds this limit (for that period), the tasks belonging to its
+hierarchy will be throttled and are not allowed to run again until the next
+period.
+
+A group's unused runtime is globally tracked, being refreshed with quota units
+above at each period boundary. As threads consume this bandwidth it is
+transferred to cpu-local "silos" on a demand basis. The amount transferred
+within each of these updates is tunable and described as the "slice".
+
+Management
+----------
+Quota and period are managed within the cpu subsystem via cgroupfs.
+
+cpu.cfs_quota_us: the total available run-time within a period (in microseconds)
+cpu.cfs_period_us: the length of a period (in microseconds)
+cpu.stat: exports throttling statistics [explained further below]
+
+The default values are:
+ cpu.cfs_period_us=100ms
+ cpu.cfs_quota=-1
+
+A value of -1 for cpu.cfs_quota_us indicates that the group does not have any
+bandwidth restriction in place, such a group is described as an unconstrained
+bandwidth group. This represents the traditional work-conserving behavior for
+CFS.
+
+Writing any (valid) positive value(s) will enact the specified bandwidth limit.
+The minimum quota allowed for the quota or period is 1ms. There is also an
+upper bound on the period length of 1s. Additional restrictions exist when
+bandwidth limits are used in a hierarchical fashion, these are explained in
+more detail below.
+
+Writing any negative value to cpu.cfs_quota_us will remove the bandwidth limit
+and return the group to an unconstrained state once more.
+
+Any updates to a group's bandwidth specification will result in it becoming
+unthrottled if it is in a constrained state.
+
+System wide settings
+--------------------
+For efficiency run-time is transferred between the global pool and CPU local
+"silos" in a batch fashion. This greatly reduces global accounting pressure
+on large systems. The amount transferred each time such an update is required
+is described as the "slice".
+
+This is tunable via procfs:
+ /proc/sys/kernel/sched_cfs_bandwidth_slice_us (default=5ms)
+
+Larger slice values will reduce transfer overheads, while smaller values allow
+for more fine-grained consumption.
+
+Statistics
+----------
+A group's bandwidth statistics are exported via 3 fields in cpu.stat.
+
+cpu.stat:
+- nr_periods: Number of enforcement intervals that have elapsed.
+- nr_throttled: Number of times the group has been throttled/limited.
+- throttled_time: The total time duration (in nanoseconds) for which entities
+ of the group have been throttled.
+
+This interface is read-only.
+
+Hierarchical considerations
+---------------------------
+The interface enforces that an individual entity's bandwidth is always
+attainable, that is: max(c_i) <= C. However, over-subscription in the
+aggregate case is explicitly allowed to enable work-conserving semantics
+within a hierarchy.
+ e.g. \Sum (c_i) may exceed C
+[ Where C is the parent's bandwidth, and c_i its children ]
+
+
+There are two ways in which a group may become throttled:
+ a. it fully consumes its own quota within a period
+ b. a parent's quota is fully consumed within its period
+
+In case b) above, even though the child may have runtime remaining it will not
+be allowed to until the parent's runtime is refreshed.
+
+Examples
+--------
+1. Limit a group to 1 CPU worth of runtime.
+
+ If period is 250ms and quota is also 250ms, the group will get
+ 1 CPU worth of runtime every 250ms.
+
+ # echo 250000 > cpu.cfs_quota_us /* quota = 250ms */
+ # echo 250000 > cpu.cfs_period_us /* period = 250ms */
+
+2. Limit a group to 2 CPUs worth of runtime on a multi-CPU machine.
+
+ With 500ms period and 1000ms quota, the group can get 2 CPUs worth of
+ runtime every 500ms.
+
+ # echo 1000000 > cpu.cfs_quota_us /* quota = 1000ms */
+ # echo 500000 > cpu.cfs_period_us /* period = 500ms */
+
+ The larger period here allows for increased burst capacity.
+
+3. Limit a group to 20% of 1 CPU.
+
+ With 50ms period, 10ms quota will be equivalent to 20% of 1 CPU.
+
+ # echo 10000 > cpu.cfs_quota_us /* quota = 10ms */
+ # echo 50000 > cpu.cfs_period_us /* period = 50ms */
+
+ By using a small period here we are ensuring a consistent latency
+ response at the expense of burst capacity.
+
diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX
index c2e18e109858..b48ded55b555 100644
--- a/Documentation/scsi/00-INDEX
+++ b/Documentation/scsi/00-INDEX
@@ -28,6 +28,8 @@ LICENSE.FlashPoint
- Licence of the Flashpoint driver
LICENSE.qla2xxx
- License for QLogic Linux Fibre Channel HBA Driver firmware.
+LICENSE.qla4xxx
+ - License for QLogic Linux iSCSI HBA Driver.
Mylex.txt
- info on driver for Mylex adapters
NinjaSCSI.txt
diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
index 1b6e27ddb7f3..64adb98b181c 100644
--- a/Documentation/scsi/ChangeLog.megaraid_sas
+++ b/Documentation/scsi/ChangeLog.megaraid_sas
@@ -1,3 +1,18 @@
+Release Date : Wed. Oct 5, 2011 17:00:00 PST 2010 -
+ (emaild-id:megaraidlinux@lsi.com)
+ Adam Radford
+Current Version : 00.00.06.12-rc1
+Old Version : 00.00.05.40-rc1
+ 1. Continue booting immediately if FW in FAULT at driver load time.
+ 2. Increase default cmds per lun to 256.
+ 3. Fix mismatch in megasas_reset_fusion() mutex lock-unlock.
+ 4. Remove some un-necessary code.
+ 5. Clear state change interrupts for Fusion/Invader.
+ 6. Clear FUSION_IN_RESET before enabling interrupts.
+ 7. Add support for MegaRAID 9360/9380 12GB/s controllers.
+ 8. Add multiple MSI-X vector/multiple reply queue support.
+ 9. Add driver workaround for PERC5/1068 kdump kernel panic.
+-------------------------------------------------------------------------------
Release Date : Tue. Jul 26, 2011 17:00:00 PST 2010 -
(emaild-id:megaraidlinux@lsi.com)
Adam Radford
diff --git a/Documentation/scsi/LICENSE.qla4xxx b/Documentation/scsi/LICENSE.qla4xxx
new file mode 100644
index 000000000000..494980e40491
--- /dev/null
+++ b/Documentation/scsi/LICENSE.qla4xxx
@@ -0,0 +1,310 @@
+Copyright (c) 2003-2011 QLogic Corporation
+QLogic Linux iSCSI HBA Driver
+
+This program includes a device driver for Linux 3.x.
+You may modify and redistribute the device driver code under the
+GNU General Public License (a copy of which is attached hereto as
+Exhibit A) published by the Free Software Foundation (version 2).
+
+REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
+THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "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
+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.
+
+USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
+CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
+OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
+TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
+ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
+COMBINATION WITH THIS PROGRAM.
+
+
+EXHIBIT A
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/Documentation/scsi/aic7xxx_old.txt b/Documentation/scsi/aic7xxx_old.txt
index 7bd210ab45a1..ecfc474f36a8 100644
--- a/Documentation/scsi/aic7xxx_old.txt
+++ b/Documentation/scsi/aic7xxx_old.txt
@@ -444,7 +444,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
Kernel Compile options
------------------------------
The various kernel compile time options for this driver are now fairly
- well documented in the file Documentation/Configure.help. In order to
+ well documented in the file drivers/scsi/Kconfig. In order to
see this documentation, you need to use one of the advanced configuration
programs (menuconfig and xconfig). If you are using the "make menuconfig"
method of configuring your kernel, then you would simply highlight the
diff --git a/Documentation/scsi/bnx2fc.txt b/Documentation/scsi/bnx2fc.txt
new file mode 100644
index 000000000000..80823556d62f
--- /dev/null
+++ b/Documentation/scsi/bnx2fc.txt
@@ -0,0 +1,75 @@
+Operating FCoE using bnx2fc
+===========================
+Broadcom FCoE offload through bnx2fc is full stateful hardware offload that
+cooperates with all interfaces provided by the Linux ecosystem for FC/FCoE and
+SCSI controllers. As such, FCoE functionality, once enabled is largely
+transparent. Devices discovered on the SAN will be registered and unregistered
+automatically with the upper storage layers.
+
+Despite the fact that the Broadcom's FCoE offload is fully offloaded, it does
+depend on the state of the network interfaces to operate. As such, the network
+interface (e.g. eth0) associated with the FCoE offload initiator must be 'up'.
+It is recommended that the network interfaces be configured to be brought up
+automatically at boot time.
+
+Furthermore, the Broadcom FCoE offload solution creates VLAN interfaces to
+support the VLANs that have been discovered for FCoE operation (e.g.
+eth0.1001-fcoe). Do not delete or disable these interfaces or FCoE operation
+will be disrupted.
+
+Driver Usage Model:
+===================
+
+1. Ensure that fcoe-utils package is installed.
+
+2. Configure the interfaces on which bnx2fc driver has to operate on.
+Here are the steps to configure:
+ a. cd /etc/fcoe
+ b. copy cfg-ethx to cfg-eth5 if FCoE has to be enabled on eth5.
+ c. Repeat this for all the interfaces where FCoE has to be enabled.
+ d. Edit all the cfg-eth files to set "no" for DCB_REQUIRED** field, and
+ "yes" for AUTO_VLAN.
+ e. Other configuration parameters should be left as default
+
+3. Ensure that "bnx2fc" is in SUPPORTED_DRIVERS list in /etc/fcoe/config.
+
+4. Start fcoe service. (service fcoe start). If Broadcom devices are present in
+the system, bnx2fc driver would automatically claim the interfaces, starts vlan
+discovery and log into the targets.
+
+5. "Symbolic Name" in 'fcoeadm -i' output would display if bnx2fc has claimed
+the interface.
+Eg:
+[root@bh2 ~]# fcoeadm -i
+ Description: NetXtreme II BCM57712 10 Gigabit Ethernet
+ Revision: 01
+ Manufacturer: Broadcom Corporation
+ Serial Number: 0010186FD558
+ Driver: bnx2x 1.70.00-0
+ Number of Ports: 2
+
+ Symbolic Name: bnx2fc v1.0.5 over eth5.4
+ OS Device Name: host11
+ Node Name: 0x10000010186FD559
+ Port Name: 0x20000010186FD559
+ FabricName: 0x2001000DECB3B681
+ Speed: 10 Gbit
+ Supported Speed: 10 Gbit
+ MaxFrameSize: 2048
+ FC-ID (Port ID): 0x0F0377
+ State: Online
+
+6. Verify the vlan discovery is performed by running ifconfig and notice
+<INTERFACE>.<VLAN>-fcoe interfaces are automatically created.
+
+Refer to fcoeadm manpage for more information on fcoeadm operations to
+create/destroy interfaces or to display lun/target information.
+
+NOTE:
+====
+** Broadcom FCoE capable devices implement a DCBX/LLDP client on-chip. Only one
+LLDP client is allowed per interface. For proper operation all host software
+based DCBX/LLDP clients (e.g. lldpad) must be disabled. To disable lldpad on a
+given interface, run the following command:
+
+lldptool set-lldp -i <interface_name> adminStatus=disabled
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 5f17d29c59b5..a340b18cd4eb 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -55,11 +55,6 @@ or in the same directory as the C source code. For example to find a url
about the USB mass storage driver see the
/usr/src/linux/drivers/usb/storage directory.
-The Linux kernel source Documentation/DocBook/scsidrivers.tmpl file
-refers to this file. With the appropriate DocBook tool-set, this permits
-users to generate html, ps and pdf renderings of information within this
-file (e.g. the interface functions).
-
Driver structure
================
Traditionally an LLD for the SCSI subsystem has been at least two files in
diff --git a/Documentation/security/keys-trusted-encrypted.txt b/Documentation/security/keys-trusted-encrypted.txt
index 5f50ccabfc8a..c9e4855ed3d7 100644
--- a/Documentation/security/keys-trusted-encrypted.txt
+++ b/Documentation/security/keys-trusted-encrypted.txt
@@ -156,4 +156,5 @@ Load an encrypted key "evm" from saved blob:
Other uses for trusted and encrypted keys, such as for disk and file encryption
are anticipated. In particular the new format 'ecryptfs' has been defined in
in order to use encrypted keys to mount an eCryptfs filesystem. More details
-about the usage can be found in the file 'Documentation/keys-ecryptfs.txt'.
+about the usage can be found in the file
+'Documentation/security/keys-ecryptfs.txt'.
diff --git a/Documentation/serial/serial-rs485.txt b/Documentation/serial/serial-rs485.txt
index a4932387bbfb..079cb3df62cf 100644
--- a/Documentation/serial/serial-rs485.txt
+++ b/Documentation/serial/serial-rs485.txt
@@ -28,6 +28,10 @@
RS485 communications. This data structure is used to set and configure RS485
parameters in the platform data and in ioctls.
+ The device tree can also provide RS485 boot time parameters (see [2]
+ for bindings). The driver is in charge of filling this data structure from
+ the values given by the device tree.
+
Any driver for devices capable of working both as RS232 and RS485 should
provide at least the following ioctls:
@@ -104,6 +108,9 @@
rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
rs485conf.delay_rts_after_send = ...;
+ /* Set this flag if you want to receive data even whilst sending data */
+ rs485conf.flags |= SER_RS485_RX_DURING_TX;
+
if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
/* Error handling. See errno. */
}
@@ -118,3 +125,4 @@
5. REFERENCES
[1] include/linux/serial.h
+ [2] Documentation/devicetree/bindings/serial/rs485.txt
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 89757012c7ff..936699e4f04b 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -886,6 +886,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
disable)
power_save_controller - Reset HD-audio controller in power-saving mode
(default = on)
+ align_buffer_size - Force rounding of buffer/period sizes to multiples
+ of 128 bytes. This is more efficient in terms of memory
+ access but isn't required by the HDA spec and prevents
+ users from specifying exact period/buffer sizes.
+ (default = on)
+ snoop - Enable/disable snooping (default = on)
This module supports multiple cards and autoprobe.
diff --git a/Documentation/sound/alsa/HD-Audio-Controls.txt b/Documentation/sound/alsa/HD-Audio-Controls.txt
index 1482035243e6..e9621e349e17 100644
--- a/Documentation/sound/alsa/HD-Audio-Controls.txt
+++ b/Documentation/sound/alsa/HD-Audio-Controls.txt
@@ -98,3 +98,19 @@ Conexant codecs
* Auto-Mute Mode
See Reatek codecs.
+
+
+Analog codecs
+--------------
+
+* Channel Mode
+ This is an enum control to change the surround-channel setup,
+ appears only when the surround channels are available.
+ It gives the number of channels to be used, "2ch", "4ch" and "6ch".
+ According to the configuration, this also controls the
+ jack-retasking of multi-I/O jacks.
+
+* Independent HP
+ When this enum control is enabled, the headphone output is routed
+ from an individual stream (the third PCM such as hw:0,2) instead of
+ the primary stream.
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index d70c93bdcadf..4f3443230d89 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -29,9 +29,6 @@ ALC880
ALC260
======
- hp HP machines
- hp-3013 HP machines (3013-variant)
- hp-dc7600 HP DC7600
fujitsu Fujitsu S7020
acer Acer TravelMate
will Will laptops (PB V7900)
@@ -46,15 +43,10 @@ ALC260
ALC262
======
fujitsu Fujitsu Laptop
- hp-bpc HP xw4400/6400/8400/9400 laptops
- hp-bpc-d7000 HP BPC D7000
- hp-tc-t5735 HP Thin Client T5735
- hp-rp5700 HP RP5700
benq Benq ED8
benq-t31 Benq T31
hippo Hippo (ATI) with jack detection, Sony UX-90s
hippo_1 Hippo (Benq) with jack detection
- sony-assamd Sony ASSAMD
toshiba-s06 Toshiba S06
toshiba-rx1 Toshiba RX1
tyan Tyan Thunder n6650W (S2915-E)
@@ -66,43 +58,15 @@ ALC262
ALC267/268
==========
- quanta-il1 Quanta IL1 mini-notebook
- 3stack 3-stack model
- toshiba Toshiba A205
- acer Acer laptops
- acer-dmic Acer laptops with digital-mic
- acer-aspire Acer Aspire One
- dell Dell OEM laptops (Vostro 1200)
- zepto Zepto laptops
- test for testing/debugging purpose, almost all controls can
- adjusted. Appearing only when compiled with
- $CONFIG_SND_DEBUG=y
- auto auto-config reading BIOS (default)
+ N/A
ALC269
======
- basic Basic preset
- quanta Quanta FL1
laptop-amic Laptops with analog-mic input
laptop-dmic Laptops with digital-mic input
- fujitsu FSC Amilo
- lifebook Fujitsu Lifebook S6420
- auto auto-config reading BIOS (default)
ALC662/663/272
==============
- 3stack-dig 3-stack (2-channel) with SPDIF
- 3stack-6ch 3-stack (6-channel)
- 3stack-6ch-dig 3-stack (6-channel) with SPDIF
- 5stack-dig 5-stack with SPDIF
- lenovo-101e Lenovo laptop
- eeepc-p701 ASUS Eeepc P701
- eeepc-ep20 ASUS Eeepc EP20
- ecs ECS/Foxconn mobo
- m51va ASUS M51VA
- g71v ASUS G71V
- h13 ASUS H13
- g50v ASUS G50V
asus-mode1 ASUS
asus-mode2 ASUS
asus-mode3 ASUS
@@ -111,15 +75,10 @@ ALC662/663/272
asus-mode6 ASUS
asus-mode7 ASUS
asus-mode8 ASUS
- dell Dell with ALC272
- dell-zm1 Dell ZM1 with ALC272
- samsung-nc10 Samsung NC10 mini notebook
- auto auto-config reading BIOS (default)
ALC680
======
- base Base model (ASUS NX90)
- auto auto-config reading BIOS (default)
+ N/A
ALC882/883/885/888/889
======================
@@ -175,28 +134,11 @@ ALC882/883/885/888/889
ALC861/660
==========
- 3stack 3-jack
- 3stack-dig 3-jack with SPDIF I/O
- 6stack-dig 6-jack with SPDIF I/O
- 3stack-660 3-jack (for ALC660)
- uniwill-m31 Uniwill M31 laptop
- toshiba Toshiba laptop support
- asus Asus laptop support
- asus-laptop ASUS F2/F3 laptops
- auto auto-config reading BIOS (default)
+ N/A
ALC861VD/660VD
==============
- 3stack 3-jack
- 3stack-dig 3-jack with SPDIF OUT
- 6stack-dig 6-jack with SPDIF OUT
- 3stack-660 3-jack (for ALC660VD)
- 3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD)
- lenovo Lenovo 3000 C200
- dallas Dallas laptops
- hp HP TX1000
- asus-v1s ASUS V1Sn
- auto auto-config reading BIOS (default)
+ N/A
CMI9880
=======
@@ -289,7 +231,6 @@ Conexant 5051
hp-dv6736 HP dv6736
hp-f700 HP Compaq Presario F700
ideapad Lenovo IdeaPad laptop
- lenovo-x200 Lenovo X200 laptop
toshiba Toshiba Satellite M300
Conexant 5066
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index c82beb007634..03e2771ddeef 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -447,7 +447,10 @@ The file needs to have a line `[codec]`. The next line should contain
three numbers indicating the codec vendor-id (0x12345678 in the
example), the codec subsystem-id (0xabcd1234) and the address (2) of
the codec. The rest patch entries are applied to this specified codec
-until another codec entry is given.
+until another codec entry is given. Passing 0 or a negative number to
+the first or the second value will make the check of the corresponding
+field be skipped. It'll be useful for really broken devices that don't
+initialize SSID properly.
The `[model]` line allows to change the model name of the each codec.
In the example above, it will be changed to model=auto.
@@ -491,7 +494,7 @@ Also, the codec chip name can be rewritten via `[chip_name]` line.
The hd-audio driver reads the file via request_firmware(). Thus,
a patch file has to be located on the appropriate firmware path,
typically, /lib/firmware. For example, when you pass the option
-`patch=hda-init.fw`, the file /lib/firmware/hda-init-fw must be
+`patch=hda-init.fw`, the file /lib/firmware/hda-init.fw must be
present.
The patch module option is specific to each card instance, and you
@@ -524,6 +527,54 @@ power-saving. See /sys/module/snd_hda_intel/parameters/power_save to
check the current value. If it's non-zero, the feature is turned on.
+Tracepoints
+~~~~~~~~~~~
+The hd-audio driver gives a few basic tracepoints.
+`hda:hda_send_cmd` traces each CORB write while `hda:hda_get_response`
+traces the response from RIRB (only when read from the codec driver).
+`hda:hda_bus_reset` traces the bus-reset due to fatal error, etc,
+`hda:hda_unsol_event` traces the unsolicited events, and
+`hda:hda_power_down` and `hda:hda_power_up` trace the power down/up
+via power-saving behavior.
+
+Enabling all tracepoints can be done like
+------------------------------------------------------------------------
+ # echo 1 > /sys/kernel/debug/tracing/events/hda/enable
+------------------------------------------------------------------------
+then after some commands, you can traces from
+/sys/kernel/debug/tracing/trace file. For example, when you want to
+trace what codec command is sent, enable the tracepoint like:
+------------------------------------------------------------------------
+ # cat /sys/kernel/debug/tracing/trace
+ # tracer: nop
+ #
+ # TASK-PID CPU# TIMESTAMP FUNCTION
+ # | | | | |
+ <...>-7807 [002] 105147.774889: hda_send_cmd: [0:0] val=e3a019
+ <...>-7807 [002] 105147.774893: hda_send_cmd: [0:0] val=e39019
+ <...>-7807 [002] 105147.999542: hda_send_cmd: [0:0] val=e3a01a
+ <...>-7807 [002] 105147.999543: hda_send_cmd: [0:0] val=e3901a
+ <...>-26764 [001] 349222.837143: hda_send_cmd: [0:0] val=e3a019
+ <...>-26764 [001] 349222.837148: hda_send_cmd: [0:0] val=e39019
+ <...>-26764 [001] 349223.058539: hda_send_cmd: [0:0] val=e3a01a
+ <...>-26764 [001] 349223.058541: hda_send_cmd: [0:0] val=e3901a
+------------------------------------------------------------------------
+Here `[0:0]` indicates the card number and the codec address, and
+`val` shows the value sent to the codec, respectively. The value is
+a packed value, and you can decode it via hda-decode-verb program
+included in hda-emu package below. For example, the value e3a019 is
+to set the left output-amp value to 25.
+------------------------------------------------------------------------
+ % hda-decode-verb 0xe3a019
+ raw value = 0x00e3a019
+ cid = 0, nid = 0x0e, verb = 0x3a0, parm = 0x19
+ raw value: verb = 0x3a0, parm = 0x19
+ verbname = set_amp_gain_mute
+ amp raw val = 0xa019
+ output, left, idx=0, mute=0, val=25
+------------------------------------------------------------------------
+
+
Development Tree
~~~~~~~~~~~~~~~~
The latest development codes for HD-audio are found on sound git tree:
diff --git a/Documentation/sound/oss/PAS16 b/Documentation/sound/oss/PAS16
index 951b3dce51b4..3dca4b75988e 100644
--- a/Documentation/sound/oss/PAS16
+++ b/Documentation/sound/oss/PAS16
@@ -60,8 +60,7 @@ With PAS16 you can use two audio device files at the same time. /dev/dsp (and
The new stuff for 2.3.99 and later
============================================================================
-The following configuration options from Documentation/Configure.help
-are relevant to configuring the PAS16:
+The following configuration options are relevant to configuring the PAS16:
Sound card support
CONFIG_SOUND
diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx
index 00511e08db78..3352f97430e4 100644
--- a/Documentation/spi/pxa2xx
+++ b/Documentation/spi/pxa2xx
@@ -2,7 +2,7 @@ PXA2xx SPI on SSP driver HOWTO
===================================================
This a mini howto on the pxa2xx_spi driver. The driver turns a PXA2xx
synchronous serial port into a SPI master controller
-(see Documentation/spi/spi_summary). The driver has the following features
+(see Documentation/spi/spi-summary). The driver has the following features
- Support for any PXA2xx SSP
- SSP PIO and SSP DMA data transfers.
@@ -85,7 +85,7 @@ Declaring Slave Devices
-----------------------
Typically each SPI slave (chip) is defined in the arch/.../mach-*/board-*.c
using the "spi_board_info" structure found in "linux/spi/spi.h". See
-"Documentation/spi/spi_summary" for additional information.
+"Documentation/spi/spi-summary" for additional information.
Each slave device attached to the PXA must provide slave specific configuration
information via the structure "pxa2xx_spi_chip" found in
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt
index e213f45cf9d7..21fd05c28e73 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/stable_kernel_rules.txt
@@ -24,10 +24,10 @@ Rules on what kind of patches are accepted, and which ones are not, into the
Procedure for submitting patches to the -stable tree:
- Send the patch, after verifying that it follows the above rules, to
- stable@kernel.org. You must note the upstream commit ID in the changelog
- of your submission.
+ stable@vger.kernel.org. You must note the upstream commit ID in the
+ changelog of your submission.
- To have the patch automatically included in the stable tree, add the tag
- Cc: stable@kernel.org
+ Cc: stable@vger.kernel.org
in the sign-off area. Once the patch is merged it will be applied to
the stable tree without anything else needing to be done by the author
or subsystem maintainer.
@@ -35,10 +35,10 @@ Procedure for submitting patches to the -stable tree:
cherry-picked than this can be specified in the following format in
the sign-off area:
- Cc: <stable@kernel.org> # .32.x: a1f84a3: sched: Check for idle
- Cc: <stable@kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
- Cc: <stable@kernel.org> # .32.x: fd21073: sched: Fix affinity logic
- Cc: <stable@kernel.org> # .32.x
+ Cc: <stable@vger.kernel.org> # .32.x: a1f84a3: sched: Check for idle
+ Cc: <stable@vger.kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
+ Cc: <stable@vger.kernel.org> # .32.x: fd21073: sched: Fix affinity logic
+ Cc: <stable@vger.kernel.org> # .32.x
Signed-off-by: Ingo Molnar <mingo@elte.hu>
The tag sequence has the meaning of:
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 704e474a93df..1f2463671a1a 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -24,6 +24,7 @@ show up in /proc/sys/kernel:
- bootloader_type [ X86 only ]
- bootloader_version [ X86 only ]
- callhome [ S390 only ]
+- cap_last_cap
- core_pattern
- core_pipe_limit
- core_uses_pid
@@ -155,6 +156,13 @@ on has a service contract with IBM.
==============================================================
+cap_last_cap
+
+Highest valid capability of the running kernel. Exports
+CAP_LAST_CAP from the kernel.
+
+==============================================================
+
core_pattern:
core_pattern is used to specify a core dumpfile pattern name.
diff --git a/Documentation/timers/highres.txt b/Documentation/timers/highres.txt
index 21332233cef1..e8789976e77c 100644
--- a/Documentation/timers/highres.txt
+++ b/Documentation/timers/highres.txt
@@ -30,7 +30,7 @@ hrtimer base infrastructure
---------------------------
The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
-the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See
+the base implementation are covered in Documentation/timers/hrtimers.txt. See
also figure #2 (OLS slides p. 15)
The main differences to the timer wheel, which holds the armed timer_list type
diff --git a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
index 12cecc83cd91..4a37c4759cd2 100644
--- a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
+++ b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
@@ -379,10 +379,10 @@ EVENT_PROCESS:
# To closer match vmstat scanning statistics, only count isolate_both
# and isolate_inactive as scanning. isolate_active is rotation
- # isolate_inactive == 0
- # isolate_active == 1
- # isolate_both == 2
- if ($isolate_mode != 1) {
+ # isolate_inactive == 1
+ # isolate_active == 2
+ # isolate_both == 3
+ if ($isolate_mode != 2) {
$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
}
$perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty;
diff --git a/Documentation/usb/dma.txt b/Documentation/usb/dma.txt
index 84ef865237db..444651e70d95 100644
--- a/Documentation/usb/dma.txt
+++ b/Documentation/usb/dma.txt
@@ -7,7 +7,7 @@ API OVERVIEW
The big picture is that USB drivers can continue to ignore most DMA issues,
though they still must provide DMA-ready buffers (see
-Documentation/PCI/PCI-DMA-mapping.txt). That's how they've worked through
+Documentation/DMA-API-HOWTO.txt). That's how they've worked through
the 2.4 (and earlier) kernels.
OR: they can now be DMA-aware.
@@ -57,7 +57,7 @@ and effects like cache-trashing can impose subtle penalties.
force a consistent memory access ordering by using memory barriers. It's
not using a streaming DMA mapping, so it's good for small transfers on
systems where the I/O would otherwise thrash an IOMMU mapping. (See
- Documentation/PCI/PCI-DMA-mapping.txt for definitions of "coherent" and
+ Documentation/DMA-API-HOWTO.txt for definitions of "coherent" and
"streaming" DMA mappings.)
Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
@@ -88,7 +88,7 @@ WORKING WITH EXISTING BUFFERS
Existing buffers aren't usable for DMA without first being mapped into the
DMA address space of the device. However, most buffers passed to your
driver can safely be used with such DMA mapping. (See the first section
-of Documentation/PCI/PCI-DMA-mapping.txt, titled "What memory is DMA-able?")
+of Documentation/DMA-API-HOWTO.txt, titled "What memory is DMA-able?")
- When you're using scatterlists, you can map everything at once. On some
systems, this kicks in an IOMMU and turns the scatterlists into single
diff --git a/Documentation/usb/dwc3.txt b/Documentation/usb/dwc3.txt
new file mode 100644
index 000000000000..7b590edae145
--- /dev/null
+++ b/Documentation/usb/dwc3.txt
@@ -0,0 +1,45 @@
+
+ TODO
+~~~~~~
+Please pick something while reading :)
+
+- Convert interrupt handler to per-ep-thread-irq
+
+ As it turns out some DWC3-commands ~1ms to complete. Currently we spin
+ until the command completes which is bad.
+
+ Implementation idea:
+ - dwc core implements a demultiplexing irq chip for interrupts per
+ endpoint. The interrupt numbers are allocated during probe and belong
+ to the device. If MSI provides per-endpoint interrupt this dummy
+ interrupt chip can be replaced with "real" interrupts.
+ - interrupts are requested / allocated on usb_ep_enable() and removed on
+ usb_ep_disable(). Worst case are 32 interrupts, the lower limit is two
+ for ep0/1.
+ - dwc3_send_gadget_ep_cmd() will sleep in wait_for_completion_timeout()
+ until the command completes.
+ - the interrupt handler is split into the following pieces:
+ - primary handler of the device
+ goes through every event and calls generic_handle_irq() for event
+ it. On return from generic_handle_irq() in acknowledges the event
+ counter so interrupt goes away (eventually).
+
+ - threaded handler of the device
+ none
+
+ - primary handler of the EP-interrupt
+ reads the event and tries to process it. Everything that requries
+ sleeping is handed over to the Thread. The event is saved in an
+ per-endpoint data-structure.
+ We probably have to pay attention not to process events once we
+ handed something to thread so we don't process event X prio Y
+ where X > Y.
+
+ - threaded handler of the EP-interrupt
+ handles the remaining EP work which might sleep such as waiting
+ for command completion.
+
+ Latency:
+ There should be no increase in latency since the interrupt-thread has a
+ high priority and will be run before an average task in user land
+ (except the user changed priorities).
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
index c9ffa9ced7ee..12511c98cc4f 100644
--- a/Documentation/usb/power-management.txt
+++ b/Documentation/usb/power-management.txt
@@ -439,10 +439,10 @@ cause autosuspends to fail with -EBUSY if the driver needs to use the
device.
External suspend calls should never be allowed to fail in this way,
-only autosuspend calls. The driver can tell them apart by checking
-the PM_EVENT_AUTO bit in the message.event argument to the suspend
-method; this bit will be set for internal PM events (autosuspend) and
-clear for external PM events.
+only autosuspend calls. The driver can tell them apart by applying
+the PMSG_IS_AUTO() macro to the message argument to the suspend
+method; it will return True for internal PM events (autosuspend) and
+False for external PM events.
Mutual exclusion
@@ -487,3 +487,29 @@ succeed, it may still remain active and thus cause the system to
resume as soon as the system suspend is complete. Or the remote
wakeup may fail and get lost. Which outcome occurs depends on timing
and on the hardware and firmware design.
+
+
+ xHCI hardware link PM
+ ---------------------
+
+xHCI host controller provides hardware link power management to usb2.0
+(xHCI 1.0 feature) and usb3.0 devices which support link PM. By
+enabling hardware LPM, the host can automatically put the device into
+lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
+which state device can enter and resume very quickly.
+
+The user interface for controlling USB2 hardware LPM is located in the
+power/ subdirectory of each USB device's sysfs directory, that is, in
+/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
+relevant attribute files is usb2_hardware_lpm.
+
+ power/usb2_hardware_lpm
+
+ When a USB2 device which support LPM is plugged to a
+ xHCI host root hub which support software LPM, the
+ host will run a software LPM test for it; if the device
+ enters L1 state and resume successfully and the host
+ supports USB2 hardware LPM, this file will show up and
+ driver will enable hardware LPM for the device. You
+ can write y/Y/1 or n/N/0 to the file to enable/disable
+ USB2 hardware LPM manually. This is for test purpose mainly.
diff --git a/drivers/staging/tm6000/CARDLIST b/Documentation/video4linux/CARDLIST.tm6000
index b5edce487997..b5edce487997 100644
--- a/drivers/staging/tm6000/CARDLIST
+++ b/Documentation/video4linux/CARDLIST.tm6000
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index 5bfa9a777d26..b15e29f31121 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -8,6 +8,7 @@ xxxx vend:prod
----
spca501 0000:0000 MystFromOri Unknown Camera
spca508 0130:0130 Clone Digital Webcam 11043
+zc3xx 03f0:1b07 HP Premium Starter Cam
m5602 0402:5602 ALi Video Camera Controller
spca501 040a:0002 Kodak DVC-325
spca500 040a:0300 Kodak EZ200
@@ -190,6 +191,7 @@ ov519 05a9:0519 OV519 Microphone
ov519 05a9:0530 OmniVision
ov519 05a9:2800 OmniVision SuperCAM
ov519 05a9:4519 Webcam Classic
+ov534_9 05a9:8065 OmniVision test kit ov538+ov9712
ov519 05a9:8519 OmniVision
ov519 05a9:a511 D-Link USB Digital Video Camera
ov519 05a9:a518 D-Link DSB-C310 Webcam
@@ -199,6 +201,8 @@ gl860 05e3:0503 Genesys Logic PC Camera
gl860 05e3:f191 Genesys Logic PC Camera
spca561 060b:a001 Maxell Compact Pc PM3
zc3xx 0698:2003 CTX M730V built in
+topro 06a2:0003 TP6800 PC Camera, CmoX CX0342 webcam
+topro 06a2:6810 Creative Qmax
nw80x 06a5:0000 Typhoon Webcam 100 USB
nw80x 06a5:d001 Divio based webcams
nw80x 06a5:d800 Divio Chicony TwinkleCam, Trust SpaceCam
diff --git a/Documentation/video4linux/omap3isp.txt b/Documentation/video4linux/omap3isp.txt
index 69be2c782b98..5dd1439b61fd 100644
--- a/Documentation/video4linux/omap3isp.txt
+++ b/Documentation/video4linux/omap3isp.txt
@@ -70,10 +70,11 @@ Events
The OMAP 3 ISP driver does support the V4L2 event interface on CCDC and
statistics (AEWB, AF and histogram) subdevs.
-The CCDC subdev produces V4L2_EVENT_OMAP3ISP_HS_VS type event on HS_VS
-interrupt which is used to signal frame start. The event is triggered exactly
-when the reception of the first line of the frame starts in the CCDC module.
-The event can be subscribed on the CCDC subdev.
+The CCDC subdev produces V4L2_EVENT_FRAME_SYNC type event on HS_VS
+interrupt which is used to signal frame start. Earlier version of this
+driver used V4L2_EVENT_OMAP3ISP_HS_VS for this purpose. The event is
+triggered exactly when the reception of the first line of the frame starts
+in the CCDC module. The event can be subscribed on the CCDC subdev.
(When using parallel interface one must pay account to correct configuration
of the VS signal polarity. This is automatically correct when using the serial
diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt
index 9346fc8cbf2b..26aa0573933e 100644
--- a/Documentation/video4linux/v4l2-controls.txt
+++ b/Documentation/video4linux/v4l2-controls.txt
@@ -285,11 +285,11 @@ implement g_volatile_ctrl like this:
Note that you use the 'new value' union as well in g_volatile_ctrl. In general
controls that need to implement g_volatile_ctrl are read-only controls.
-To mark a control as volatile you have to set the is_volatile flag:
+To mark a control as volatile you have to set V4L2_CTRL_FLAG_VOLATILE:
ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...);
if (ctrl)
- ctrl->is_volatile = 1;
+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
For try/s_ctrl the new values (i.e. as passed by the user) are filled in and
you can modify them in try_ctrl or set them in s_ctrl. The 'cur' union
@@ -367,8 +367,7 @@ Driver specific controls can be created using v4l2_ctrl_new_custom():
The last argument is the priv pointer which can be set to driver-specific
private data.
-The v4l2_ctrl_config struct also has fields to set the is_private and is_volatile
-flags.
+The v4l2_ctrl_config struct also has a field to set the is_private flag.
If the name field is not set, then the framework will assume this is a standard
control and will fill in the name, type and flags fields accordingly.
@@ -496,18 +495,20 @@ Handling autogain/gain-type Controls with Auto Clusters
A common type of control cluster is one that handles 'auto-foo/foo'-type
controls. Typical examples are autogain/gain, autoexposure/exposure,
-autowhitebalance/red balance/blue balance. In all cases you have one controls
+autowhitebalance/red balance/blue balance. In all cases you have one control
that determines whether another control is handled automatically by the hardware,
or whether it is under manual control from the user.
If the cluster is in automatic mode, then the manual controls should be
-marked inactive. When the volatile controls are read the g_volatile_ctrl
-operation should return the value that the hardware's automatic mode set up
-automatically.
+marked inactive and volatile. When the volatile controls are read the
+g_volatile_ctrl operation should return the value that the hardware's automatic
+mode set up automatically.
If the cluster is put in manual mode, then the manual controls should become
-active again and the is_volatile flag should be ignored (so g_volatile_ctrl is
-no longer called while in manual mode).
+active again and the volatile flag is cleared (so g_volatile_ctrl is no longer
+called while in manual mode). In addition just before switching to manual mode
+the current values as determined by the auto mode are copied as the new manual
+values.
Finally the V4L2_CTRL_FLAG_UPDATE should be set for the auto control since
changing that control affects the control flags of the manual controls.
@@ -520,7 +521,11 @@ void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
The first two arguments are identical to v4l2_ctrl_cluster. The third argument
tells the framework which value switches the cluster into manual mode. The
-last argument will optionally set the is_volatile flag for the non-auto controls.
+last argument will optionally set V4L2_CTRL_FLAG_VOLATILE for the non-auto controls.
+If it is false, then the manual controls are never volatile. You would typically
+use that if the hardware does not give you the option to read back to values as
+determined by the auto mode (e.g. if autogain is on, the hardware doesn't allow
+you to obtain the current gain value).
The first control of the cluster is assumed to be the 'auto' control.
@@ -681,16 +686,6 @@ if there are no controls at all.
count if nothing was done yet. If it is less than count then only the controls
up to error_idx-1 were successfully applied.
-3) When attempting to read a button control the framework will return -EACCES
-instead of -EINVAL as stated in the spec. It seems to make more sense since
-button controls are write-only controls.
-
-4) Attempting to write to a read-only control will return -EACCES instead of
--EINVAL as the spec says.
-
-5) The spec does not mention what should happen when you try to set/get a
-control class controls. The framework will return -EACCES.
-
Proposals for Extensions
========================
@@ -703,9 +698,3 @@ decimal. Useful for e.g. video_mute_yuv.
2) It is possible to mark in the controls array which controls have been
successfully written and which failed by for example adding a bit to the
control ID. Not sure if it is worth the effort, though.
-
-3) Trying to set volatile inactive controls should result in -EACCESS.
-
-4) Add a new flag to mark volatile controls. Any application that wants
-to store the state of the controls can then skip volatile inactive controls.
-Currently it is not possible to detect such controls.
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index b0e4b9cd6a66..7945b0bd35e2 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -175,10 +175,30 @@ Parameters: vcpu id (apic id on x86)
Returns: vcpu fd on success, -1 on error
This API adds a vcpu to a virtual machine. The vcpu id is a small integer
-in the range [0, max_vcpus). You can use KVM_CAP_NR_VCPUS of the
-KVM_CHECK_EXTENSION ioctl() to determine the value for max_vcpus at run-time.
+in the range [0, max_vcpus).
+
+The recommended max_vcpus value can be retrieved using the KVM_CAP_NR_VCPUS of
+the KVM_CHECK_EXTENSION ioctl() at run-time.
+The maximum possible value for max_vcpus can be retrieved using the
+KVM_CAP_MAX_VCPUS of the KVM_CHECK_EXTENSION ioctl() at run-time.
+
If the KVM_CAP_NR_VCPUS does not exist, you should assume that max_vcpus is 4
cpus max.
+If the KVM_CAP_MAX_VCPUS does not exist, you should assume that max_vcpus is
+same as the value returned from KVM_CAP_NR_VCPUS.
+
+On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
+threads in one or more virtual CPU cores. (This is because the
+hardware requires all the hardware threads in a CPU core to be in the
+same partition.) The KVM_CAP_PPC_SMT capability indicates the number
+of vcpus per virtual core (vcore). The vcore id is obtained by
+dividing the vcpu id by the number of vcpus per vcore. The vcpus in a
+given vcore will always be in the same physical core as each other
+(though that might be a different physical core from time to time).
+Userspace can control the threading (SMT) mode of the guest by its
+allocation of vcpu ids. For example, if userspace wants
+single-threaded guest vcpus, it should make all vcpu ids be a multiple
+of the number of vcpus per vcore.
On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
threads in one or more virtual CPU cores. (This is because the
@@ -1633,3 +1653,50 @@ developer registration required to access it).
char padding[256];
};
};
+
+6. Capabilities that can be enabled
+
+There are certain capabilities that change the behavior of the virtual CPU when
+enabled. To enable them, please see section 4.37. Below you can find a list of
+capabilities and what their effect on the vCPU is when enabling them.
+
+The following information is provided along with the description:
+
+ Architectures: which instruction set architectures provide this ioctl.
+ x86 includes both i386 and x86_64.
+
+ Parameters: what parameters are accepted by the capability.
+
+ Returns: the return value. General error numbers (EBADF, ENOMEM, EINVAL)
+ are not detailed, but errors with specific meanings are.
+
+6.1 KVM_CAP_PPC_OSI
+
+Architectures: ppc
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables interception of OSI hypercalls that otherwise would
+be treated as normal system calls to be injected into the guest. OSI hypercalls
+were invented by Mac-on-Linux to have a standardized communication mechanism
+between the guest and the host.
+
+When this capability is enabled, KVM_EXIT_OSI can occur.
+
+6.2 KVM_CAP_PPC_PAPR
+
+Architectures: ppc
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables interception of PAPR hypercalls. PAPR hypercalls are
+done using the hypercall instruction "sc 1".
+
+It also sets the guest privilege level to "supervisor" mode. Usually the guest
+runs in "hypervisor" privilege mode with a few missing features.
+
+In addition to the above, it changes the semantics of SDR1. In this mode, the
+HTAB address part of SDR1 contains an HVA instead of a GPA, as PAPR keeps the
+HTAB invisible to the guest.
+
+When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur.
diff --git a/Documentation/virtual/lguest/lguest.c b/Documentation/virtual/lguest/lguest.c
index d928c134dee6..c095d79cae73 100644
--- a/Documentation/virtual/lguest/lguest.c
+++ b/Documentation/virtual/lguest/lguest.c
@@ -436,7 +436,7 @@ static unsigned long load_bzimage(int fd)
/*
* Go back to the start of the file and read the header. It should be
- * a Linux boot header (see Documentation/x86/i386/boot.txt)
+ * a Linux boot header (see Documentation/x86/boot.txt)
*/
lseek(fd, 0, SEEK_SET);
read(fd, &boot, sizeof(boot));
diff --git a/Documentation/virtual/uml/UserModeLinux-HOWTO.txt b/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
index 5d0fc8bfcdb9..77dfecf4e2d6 100644
--- a/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
+++ b/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
@@ -134,13 +134,13 @@
______________________________________________________________________
- 11.. IInnttrroodduuccttiioonn
+ 1. Introduction
Welcome to User Mode Linux. It's going to be fun.
- 11..11.. HHooww iiss UUsseerr MMooddee LLiinnuuxx DDiiffffeerreenntt??
+ 1.1. How is User Mode Linux Different?
Normally, the Linux Kernel talks straight to your hardware (video
card, keyboard, hard drives, etc), and any programs which run ask the
@@ -181,7 +181,7 @@
- 11..22.. WWhhyy WWoouulldd II WWaanntt UUsseerr MMooddee LLiinnuuxx??
+ 1.2. Why Would I Want User Mode Linux?
1. If User Mode Linux crashes, your host kernel is still fine.
@@ -206,12 +206,12 @@
- 22.. CCoommppiilliinngg tthhee kkeerrnneell aanndd mmoodduulleess
+ 2. Compiling the kernel and modules
- 22..11.. CCoommppiilliinngg tthhee kkeerrnneell
+ 2.1. Compiling the kernel
Compiling the user mode kernel is just like compiling any other
@@ -322,7 +322,7 @@
bug fixes and enhancements that have gone into subsequent releases.
- 22..22.. CCoommppiilliinngg aanndd iinnssttaalllliinngg kkeerrnneell mmoodduulleess
+ 2.2. Compiling and installing kernel modules
UML modules are built in the same way as the native kernel (with the
exception of the 'ARCH=um' that you always need for UML):
@@ -386,19 +386,19 @@
- 22..33.. CCoommppiilliinngg aanndd iinnssttaalllliinngg uummll__uuttiilliittiieess
+ 2.3. Compiling and installing uml_utilities
Many features of the UML kernel require a user-space helper program,
so a uml_utilities package is distributed separately from the kernel
patch which provides these helpers. Included within this is:
- +o port-helper - Used by consoles which connect to xterms or ports
+ o port-helper - Used by consoles which connect to xterms or ports
- +o tunctl - Configuration tool to create and delete tap devices
+ o tunctl - Configuration tool to create and delete tap devices
- +o uml_net - Setuid binary for automatic tap device configuration
+ o uml_net - Setuid binary for automatic tap device configuration
- +o uml_switch - User-space virtual switch required for daemon
+ o uml_switch - User-space virtual switch required for daemon
transport
The uml_utilities tree is compiled with:
@@ -423,11 +423,11 @@
- 33.. RRuunnnniinngg UUMMLL aanndd llooggggiinngg iinn
+ 3. Running UML and logging in
- 33..11.. RRuunnnniinngg UUMMLL
+ 3.1. Running UML
It runs on 2.2.15 or later, and all 2.4 kernels.
@@ -454,7 +454,7 @@
- 33..22.. LLooggggiinngg iinn
+ 3.2. Logging in
@@ -468,7 +468,7 @@
There are a couple of other ways to log in:
- +o On a virtual console
+ o On a virtual console
@@ -480,7 +480,7 @@
- +o Over the serial line
+ o Over the serial line
In the boot output, find a line that looks like:
@@ -503,7 +503,7 @@
- +o Over the net
+ o Over the net
If the network is running, then you can telnet to the virtual
@@ -514,13 +514,13 @@
down and the process will exit.
- 33..33.. EExxaammpplleess
+ 3.3. Examples
Here are some examples of UML in action:
- +o A login session <http://user-mode-linux.sourceforge.net/login.html>
+ o A login session <http://user-mode-linux.sourceforge.net/login.html>
- +o A virtual network <http://user-mode-linux.sourceforge.net/net.html>
+ o A virtual network <http://user-mode-linux.sourceforge.net/net.html>
@@ -528,12 +528,12 @@
- 44.. UUMMLL oonn 22GG//22GG hhoossttss
+ 4. UML on 2G/2G hosts
- 44..11.. IInnttrroodduuccttiioonn
+ 4.1. Introduction
Most Linux machines are configured so that the kernel occupies the
@@ -546,7 +546,7 @@
- 44..22.. TThhee pprroobblleemm
+ 4.2. The problem
The prebuilt UML binaries on this site will not run on 2G/2G hosts
@@ -558,7 +558,7 @@
- 44..33.. TThhee ssoolluuttiioonn
+ 4.3. The solution
The fix for this is to rebuild UML from source after enabling
@@ -576,7 +576,7 @@
- 55.. SSeettttiinngg uupp sseerriiaall lliinneess aanndd ccoonnssoolleess
+ 5. Setting up serial lines and consoles
It is possible to attach UML serial lines and consoles to many types
@@ -586,12 +586,12 @@
You can attach them to host ptys, ttys, file descriptors, and ports.
This allows you to do things like
- +o have a UML console appear on an unused host console,
+ o have a UML console appear on an unused host console,
- +o hook two virtual machines together by having one attach to a pty
+ o hook two virtual machines together by having one attach to a pty
and having the other attach to the corresponding tty
- +o make a virtual machine accessible from the net by attaching a
+ o make a virtual machine accessible from the net by attaching a
console to a port on the host.
@@ -599,7 +599,7 @@
- 55..11.. SSppeecciiffyyiinngg tthhee ddeevviiccee
+ 5.1. Specifying the device
Devices are specified with "con" or "ssl" (console or serial line,
respectively), optionally with a device number if you are talking
@@ -626,13 +626,13 @@
- 55..22.. SSppeecciiffyyiinngg tthhee cchhaannnneell
+ 5.2. Specifying the channel
There are a number of different types of channels to attach a UML
device to, each with a different way of specifying exactly what to
attach to.
- +o pseudo-terminals - device=pty pts terminals - device=pts
+ o pseudo-terminals - device=pty pts terminals - device=pts
This will cause UML to allocate a free host pseudo-terminal for the
@@ -640,20 +640,20 @@
log. You access it by attaching a terminal program to the
corresponding tty:
- +o screen /dev/pts/n
+ o screen /dev/pts/n
- +o screen /dev/ttyxx
+ o screen /dev/ttyxx
- +o minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
+ o minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
devices
- +o kermit - start it up, 'open' the device, then 'connect'
+ o kermit - start it up, 'open' the device, then 'connect'
- +o terminals - device=tty:tty device file
+ o terminals - device=tty:tty device file
This will make UML attach the device to the specified tty (i.e
@@ -672,7 +672,7 @@
- +o xterms - device=xterm
+ o xterms - device=xterm
UML will run an xterm and the device will be attached to it.
@@ -681,7 +681,7 @@
- +o Port - device=port:port number
+ o Port - device=port:port number
This will attach the UML devices to the specified host port.
@@ -725,7 +725,7 @@
- +o already-existing file descriptors - device=file descriptor
+ o already-existing file descriptors - device=file descriptor
If you set up a file descriptor on the UML command line, you can
@@ -743,7 +743,7 @@
- +o Nothing - device=null
+ o Nothing - device=null
This allows the device to be opened, in contrast to 'none', but
@@ -754,7 +754,7 @@
- +o None - device=none
+ o None - device=none
This causes the device to disappear.
@@ -770,7 +770,7 @@
- will cause serial line 3 to accept input on the host's /dev/tty3 and
+ will cause serial line 3 to accept input on the host's /dev/tty2 and
display output on an xterm. That's a silly example - the most common
use of this syntax is to reattach the main console to stdin and stdout
as shown above.
@@ -785,7 +785,7 @@
- 55..33.. EExxaammpplleess
+ 5.3. Examples
There are a number of interesting things you can do with this
capability.
@@ -838,7 +838,7 @@
prompt of the other virtual machine.
- 66.. SSeettttiinngg uupp tthhee nneettwwoorrkk
+ 6. Setting up the network
@@ -858,19 +858,19 @@
There are currently five transport types available for a UML virtual
machine to exchange packets with other hosts:
- +o ethertap
+ o ethertap
- +o TUN/TAP
+ o TUN/TAP
- +o Multicast
+ o Multicast
- +o a switch daemon
+ o a switch daemon
- +o slip
+ o slip
- +o slirp
+ o slirp
- +o pcap
+ o pcap
The TUN/TAP, ethertap, slip, and slirp transports allow a UML
instance to exchange packets with the host. They may be directed
@@ -893,28 +893,28 @@
With so many host transports, which one should you use? Here's when
you should use each one:
- +o ethertap - if you want access to the host networking and it is
+ o ethertap - if you want access to the host networking and it is
running 2.2
- +o TUN/TAP - if you want access to the host networking and it is
+ o TUN/TAP - if you want access to the host networking and it is
running 2.4. Also, the TUN/TAP transport is able to use a
preconfigured device, allowing it to avoid using the setuid uml_net
helper, which is a security advantage.
- +o Multicast - if you want a purely virtual network and you don't want
+ o Multicast - if you want a purely virtual network and you don't want
to set up anything but the UML
- +o a switch daemon - if you want a purely virtual network and you
+ o a switch daemon - if you want a purely virtual network and you
don't mind running the daemon in order to get somewhat better
performance
- +o slip - there is no particular reason to run the slip backend unless
+ o slip - there is no particular reason to run the slip backend unless
ethertap and TUN/TAP are just not available for some reason
- +o slirp - if you don't have root access on the host to setup
+ o slirp - if you don't have root access on the host to setup
networking, or if you don't want to allocate an IP to your UML
- +o pcap - not much use for actual network connectivity, but great for
+ o pcap - not much use for actual network connectivity, but great for
monitoring traffic on the host
Ethertap is available on 2.4 and works fine. TUN/TAP is preferred
@@ -926,7 +926,7 @@
exploit the helper's root privileges.
- 66..11.. GGeenneerraall sseettuupp
+ 6.1. General setup
First, you must have the virtual network enabled in your UML. If are
running a prebuilt kernel from this site, everything is already
@@ -995,7 +995,7 @@
- 66..22.. UUsseerrssppaaccee ddaaeemmoonnss
+ 6.2. Userspace daemons
You will likely need the setuid helper, or the switch daemon, or both.
They are both installed with the RPM and deb, so if you've installed
@@ -1011,7 +1011,7 @@
- 66..33.. SSppeecciiffyyiinngg eetthheerrnneett aaddddrreesssseess
+ 6.3. Specifying ethernet addresses
Below, you will see that the TUN/TAP, ethertap, and daemon interfaces
allow you to specify hardware addresses for the virtual ethernet
@@ -1023,11 +1023,11 @@
sufficient to guarantee a unique hardware address for the device. A
couple of exceptions are:
- +o Another set of virtual ethernet devices are on the same network and
+ o Another set of virtual ethernet devices are on the same network and
they are assigned hardware addresses using a different scheme which
may conflict with the UML IP address-based scheme
- +o You aren't going to use the device for IP networking, so you don't
+ o You aren't going to use the device for IP networking, so you don't
assign the device an IP address
If you let the driver provide the hardware address, you should make
@@ -1049,7 +1049,7 @@
- 66..44.. UUMMLL iinntteerrffaaccee sseettuupp
+ 6.4. UML interface setup
Once the network devices have been described on the command line, you
should boot UML and log in.
@@ -1131,7 +1131,7 @@
- 66..55.. MMuullttiiccaasstt
+ 6.5. Multicast
The simplest way to set up a virtual network between multiple UMLs is
to use the mcast transport. This was written by Harald Welte and is
@@ -1194,7 +1194,7 @@
- 66..66.. TTUUNN//TTAAPP wwiitthh tthhee uummll__nneett hheellppeerr
+ 6.6. TUN/TAP with the uml_net helper
TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the
host. The TUN/TAP backend has been in UML since 2.4.9-3um.
@@ -1247,10 +1247,10 @@
There are a couple potential problems with running the TUN/TAP
transport on a 2.4 host kernel
- +o TUN/TAP seems not to work on 2.4.3 and earlier. Upgrade the host
+ o TUN/TAP seems not to work on 2.4.3 and earlier. Upgrade the host
kernel or use the ethertap transport.
- +o With an upgraded kernel, TUN/TAP may fail with
+ o With an upgraded kernel, TUN/TAP may fail with
File descriptor in bad state
@@ -1269,7 +1269,7 @@
- 66..77.. TTUUNN//TTAAPP wwiitthh aa pprreeccoonnffiigguurreedd ttaapp ddeevviiccee
+ 6.7. TUN/TAP with a preconfigured tap device
If you prefer not to have UML use uml_net (which is somewhat
insecure), with UML 2.4.17-11, you can set up a TUN/TAP device
@@ -1277,7 +1277,7 @@
there is no need for root assistance. Setting up the device is done
as follows:
- +o Create the device with tunctl (available from the UML utilities
+ o Create the device with tunctl (available from the UML utilities
tarball)
@@ -1291,7 +1291,7 @@
where uid is the user id or username that UML will be run as. This
will tell you what device was created.
- +o Configure the device IP (change IP addresses and device name to
+ o Configure the device IP (change IP addresses and device name to
suit)
@@ -1303,7 +1303,7 @@
- +o Set up routing and arping if desired - this is my recipe, there are
+ o Set up routing and arping if desired - this is my recipe, there are
other ways of doing the same thing
@@ -1338,7 +1338,7 @@
utility which reads the information from a config file and sets up
devices at boot time.
- +o Rather than using up two IPs and ARPing for one of them, you can
+ o Rather than using up two IPs and ARPing for one of them, you can
also provide direct access to your LAN by the UML by using a
bridge.
@@ -1417,7 +1417,7 @@
Note that 'br0' should be setup using ifconfig with the existing IP
address of eth0, as eth0 no longer has its own IP.
- +o
+ o
Also, the /dev/net/tun device must be writable by the user running
@@ -1438,11 +1438,11 @@
devices and chgrp /dev/net/tun to that group with mode 664 or 660.
- +o Once the device is set up, run UML with 'eth0=tuntap,device name'
+ o Once the device is set up, run UML with 'eth0=tuntap,device name'
(i.e. 'eth0=tuntap,tap0') on the command line (or do it with the
mconsole config command).
- +o Bring the eth device up in UML and you're in business.
+ o Bring the eth device up in UML and you're in business.
If you don't want that tap device any more, you can make it non-
persistent with
@@ -1465,7 +1465,7 @@
- 66..88.. EEtthheerrttaapp
+ 6.8. Ethertap
Ethertap is the general mechanism on 2.2 for userspace processes to
exchange packets with the kernel.
@@ -1561,9 +1561,9 @@
- 66..99.. TThhee sswwiittcchh ddaaeemmoonn
+ 6.9. The switch daemon
- NNoottee: This is the daemon formerly known as uml_router, but which was
+ Note: This is the daemon formerly known as uml_router, but which was
renamed so the network weenies of the world would stop growling at me.
@@ -1649,7 +1649,7 @@
- 66..1100.. SSlliipp
+ 6.10. Slip
Slip is another, less general, mechanism for a process to communicate
with the host networking. In contrast to the ethertap interface,
@@ -1681,7 +1681,7 @@
- 66..1111.. SSlliirrpp
+ 6.11. Slirp
slirp uses an external program, usually /usr/bin/slirp, to provide IP
only networking connectivity through the host. This is similar to IP
@@ -1737,7 +1737,7 @@
- 66..1122.. ppccaapp
+ 6.12. pcap
The pcap transport is attached to a UML ethernet device on the command
line or with uml_mconsole with the following syntax:
@@ -1777,7 +1777,7 @@
- 66..1133.. SSeettttiinngg uupp tthhee hhoosstt yyoouurrsseellff
+ 6.13. Setting up the host yourself
If you don't specify an address for the host side of the ethertap or
slip device, UML won't do any setup on the host. So this is what is
@@ -1785,7 +1785,7 @@
192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your
own network):
- +o The device needs to be configured with its IP address. Tap devices
+ o The device needs to be configured with its IP address. Tap devices
are also configured with an mtu of 1484. Slip devices are
configured with a point-to-point address pointing at the UML ip
address.
@@ -1805,7 +1805,7 @@
- +o If a tap device is being set up, a route is set to the UML IP.
+ o If a tap device is being set up, a route is set to the UML IP.
UML# route add -host 192.168.0.250 gw 192.168.0.251
@@ -1814,7 +1814,7 @@
- +o To allow other hosts on your network to see the virtual machine,
+ o To allow other hosts on your network to see the virtual machine,
proxy arp is set up for it.
@@ -1824,7 +1824,7 @@
- +o Finally, the host is set up to route packets.
+ o Finally, the host is set up to route packets.
host# echo 1 > /proc/sys/net/ipv4/ip_forward
@@ -1838,12 +1838,12 @@
- 77.. SShhaarriinngg FFiilleessyysstteemmss bbeettwweeeenn VViirrttuuaall MMaacchhiinneess
+ 7. Sharing Filesystems between Virtual Machines
- 77..11.. AA wwaarrnniinngg
+ 7.1. A warning
Don't attempt to share filesystems simply by booting two UMLs from the
same file. That's the same thing as booting two physical machines
@@ -1851,7 +1851,7 @@
- 77..22.. UUssiinngg llaayyeerreedd bblloocckk ddeevviicceess
+ 7.2. Using layered block devices
The way to share a filesystem between two virtual machines is to use
the copy-on-write (COW) layering capability of the ubd block driver.
@@ -1896,7 +1896,7 @@
- 77..33.. NNoottee!!
+ 7.3. Note!
When checking the size of the COW file in order to see the gobs of
space that you're saving, make sure you use 'ls -ls' to see the actual
@@ -1926,7 +1926,7 @@
- 77..44.. AAnnootthheerr wwaarrnniinngg
+ 7.4. Another warning
Once a filesystem is being used as a readonly backing file for a COW
file, do not boot directly from it or modify it in any way. Doing so
@@ -1952,7 +1952,7 @@
- 77..55.. uummll__mmoooo :: MMeerrggiinngg aa CCOOWW ffiillee wwiitthh iittss bbaacckkiinngg ffiillee
+ 7.5. uml_moo : Merging a COW file with its backing file
Depending on how you use UML and COW devices, it may be advisable to
merge the changes in the COW file into the backing file every once in
@@ -2001,7 +2001,7 @@
- 88.. CCrreeaattiinngg ffiilleessyysstteemmss
+ 8. Creating filesystems
You may want to create and mount new UML filesystems, either because
@@ -2015,7 +2015,7 @@
should be easy to translate to the filesystem of your choice.
- 88..11.. CCrreeaattee tthhee ffiilleessyysstteemm ffiillee
+ 8.1. Create the filesystem file
dd is your friend. All you need to do is tell dd to create an empty
file of the appropriate size. I usually make it sparse to save time
@@ -2032,7 +2032,7 @@
- 88..22.. AAssssiiggnn tthhee ffiillee ttoo aa UUMMLL ddeevviiccee
+ 8.2. Assign the file to a UML device
Add an argument like the following to the UML command line:
@@ -2045,7 +2045,7 @@
- 88..33.. CCrreeaattiinngg aanndd mmoouunnttiinngg tthhee ffiilleessyysstteemm
+ 8.3. Creating and mounting the filesystem
Make sure that the filesystem is available, either by being built into
the kernel, or available as a module, then boot up UML and log in. If
@@ -2096,7 +2096,7 @@
- 99.. HHoosstt ffiillee aacccceessss
+ 9. Host file access
If you want to access files on the host machine from inside UML, you
@@ -2112,7 +2112,7 @@
files contained in it just as you would on the host.
- 99..11.. UUssiinngg hhoossttffss
+ 9.1. Using hostfs
To begin with, make sure that hostfs is available inside the virtual
machine with
@@ -2151,7 +2151,7 @@
- 99..22.. hhoossttffss aass tthhee rroooott ffiilleessyysstteemm
+ 9.2. hostfs as the root filesystem
It's possible to boot from a directory hierarchy on the host using
hostfs rather than using the standard filesystem in a file.
@@ -2194,20 +2194,20 @@
UML should then boot as it does normally.
- 99..33.. BBuuiillddiinngg hhoossttffss
+ 9.3. Building hostfs
If you need to build hostfs because it's not in your kernel, you have
two choices:
- +o Compiling hostfs into the kernel:
+ o Compiling hostfs into the kernel:
Reconfigure the kernel and set the 'Host filesystem' option under
- +o Compiling hostfs as a module:
+ o Compiling hostfs as a module:
Reconfigure the kernel and set the 'Host filesystem' option under
@@ -2228,7 +2228,7 @@
- 1100.. TThhee MMaannaaggeemmeenntt CCoonnssoollee
+ 10. The Management Console
@@ -2240,15 +2240,15 @@
There are a number of things you can do with the mconsole interface:
- +o get the kernel version
+ o get the kernel version
- +o add and remove devices
+ o add and remove devices
- +o halt or reboot the machine
+ o halt or reboot the machine
- +o Send SysRq commands
+ o Send SysRq commands
- +o Pause and resume the UML
+ o Pause and resume the UML
You need the mconsole client (uml_mconsole) which is present in CVS
@@ -2300,28 +2300,28 @@
You'll get a prompt, at which you can run one of these commands:
- +o version
+ o version
- +o halt
+ o halt
- +o reboot
+ o reboot
- +o config
+ o config
- +o remove
+ o remove
- +o sysrq
+ o sysrq
- +o help
+ o help
- +o cad
+ o cad
- +o stop
+ o stop
- +o go
+ o go
- 1100..11.. vveerrssiioonn
+ 10.1. version
This takes no arguments. It prints the UML version.
@@ -2342,7 +2342,7 @@
- 1100..22.. hhaalltt aanndd rreebboooott
+ 10.2. halt and reboot
These take no arguments. They shut the machine down immediately, with
no syncing of disks and no clean shutdown of userspace. So, they are
@@ -2357,7 +2357,7 @@
- 1100..33.. ccoonnffiigg
+ 10.3. config
"config" adds a new device to the virtual machine. Currently the ubd
and network drivers support this. It takes one argument, which is the
@@ -2378,7 +2378,7 @@
- 1100..44.. rreemmoovvee
+ 10.4. remove
"remove" deletes a device from the system. Its argument is just the
name of the device to be removed. The device must be idle in whatever
@@ -2397,7 +2397,7 @@
- 1100..55.. ssyyssrrqq
+ 10.5. sysrq
This takes one argument, which is a single letter. It calls the
generic kernel's SysRq driver, which does whatever is called for by
@@ -2407,14 +2407,14 @@
- 1100..66.. hheellpp
+ 10.6. help
"help" returns a string listing the valid commands and what each one
does.
- 1100..77.. ccaadd
+ 10.7. cad
This invokes the Ctl-Alt-Del action on init. What exactly this ends
up doing is up to /etc/inittab. Normally, it reboots the machine.
@@ -2432,7 +2432,7 @@
- 1100..88.. ssttoopp
+ 10.8. stop
This puts the UML in a loop reading mconsole requests until a 'go'
mconsole command is received. This is very useful for making backups
@@ -2448,7 +2448,7 @@
- 1100..99.. ggoo
+ 10.9. go
This resumes a UML after being paused by a 'stop' command. Note that
when the UML has resumed, TCP connections may have timed out and if
@@ -2462,10 +2462,10 @@
- 1111.. KKeerrnneell ddeebbuuggggiinngg
+ 11. Kernel debugging
- NNoottee:: The interface that makes debugging, as described here, possible
+ Note: The interface that makes debugging, as described here, possible
is present in 2.4.0-test6 kernels and later.
@@ -2485,7 +2485,7 @@
- 1111..11.. SSttaarrttiinngg tthhee kkeerrnneell uunnddeerr ggddbb
+ 11.1. Starting the kernel under gdb
You can have the kernel running under the control of gdb from the
beginning by putting 'debug' on the command line. You will get an
@@ -2498,7 +2498,7 @@
There is a transcript of a debugging session here <debug-
session.html> , with breakpoints being set in the scheduler and in an
interrupt handler.
- 1111..22.. EExxaammiinniinngg sslleeeeppiinngg pprroocceesssseess
+ 11.2. Examining sleeping processes
Not every bug is evident in the currently running process. Sometimes,
processes hang in the kernel when they shouldn't because they've
@@ -2516,7 +2516,7 @@
Now what you do is this:
- +o detach from the current thread
+ o detach from the current thread
(UML gdb) det
@@ -2525,7 +2525,7 @@
- +o attach to the thread you are interested in
+ o attach to the thread you are interested in
(UML gdb) att <host pid>
@@ -2534,7 +2534,7 @@
- +o look at its stack and anything else of interest
+ o look at its stack and anything else of interest
(UML gdb) bt
@@ -2545,7 +2545,7 @@
Note that you can't do anything at this point that requires that a
process execute, e.g. calling a function
- +o when you're done looking at that process, reattach to the current
+ o when you're done looking at that process, reattach to the current
thread and continue it
@@ -2569,12 +2569,12 @@
- 1111..33.. RRuunnnniinngg dddddd oonn UUMMLL
+ 11.3. Running ddd on UML
ddd works on UML, but requires a special kludge. The process goes
like this:
- +o Start ddd
+ o Start ddd
host% ddd linux
@@ -2583,14 +2583,14 @@
- +o With ps, get the pid of the gdb that ddd started. You can ask the
+ o With ps, get the pid of the gdb that ddd started. You can ask the
gdb to tell you, but for some reason that confuses things and
causes a hang.
- +o run UML with 'debug=parent gdb-pid=<pid>' added to the command line
+ o run UML with 'debug=parent gdb-pid=<pid>' added to the command line
- it will just sit there after you hit return
- +o type 'att 1' to the ddd gdb and you will see something like
+ o type 'att 1' to the ddd gdb and you will see something like
0xa013dc51 in __kill ()
@@ -2602,12 +2602,12 @@
- +o At this point, type 'c', UML will boot up, and you can use ddd just
+ o At this point, type 'c', UML will boot up, and you can use ddd just
as you do on any other process.
- 1111..44.. DDeebbuuggggiinngg mmoodduulleess
+ 11.4. Debugging modules
gdb has support for debugging code which is dynamically loaded into
the process. This support is what is needed to debug kernel modules
@@ -2823,7 +2823,7 @@
- 1111..55.. AAttttaacchhiinngg ggddbb ttoo tthhee kkeerrnneell
+ 11.5. Attaching gdb to the kernel
If you don't have the kernel running under gdb, you can attach gdb to
it later by sending the tracing thread a SIGUSR1. The first line of
@@ -2857,7 +2857,7 @@
- 1111..66.. UUssiinngg aalltteerrnnaattee ddeebbuuggggeerrss
+ 11.6. Using alternate debuggers
UML has support for attaching to an already running debugger rather
than starting gdb itself. This is present in CVS as of 17 Apr 2001.
@@ -2886,7 +2886,7 @@
An example of an alternate debugger is strace. You can strace the
actual kernel as follows:
- +o Run the following in a shell
+ o Run the following in a shell
host%
@@ -2894,10 +2894,10 @@
- +o Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
+ o Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
by the previous command
- +o Hit return in the shell, and UML will start running, and strace
+ o Hit return in the shell, and UML will start running, and strace
output will start accumulating in the output file.
Note that this is different from running
@@ -2917,9 +2917,9 @@
- 1122.. KKeerrnneell ddeebbuuggggiinngg eexxaammpplleess
+ 12. Kernel debugging examples
- 1122..11.. TThhee ccaassee ooff tthhee hhuunngg ffsscckk
+ 12.1. The case of the hung fsck
When booting up the kernel, fsck failed, and dropped me into a shell
to fix things up. I ran fsck -y, which hung:
@@ -3154,9 +3154,9 @@
The interesting things here are :
- +o There are two segfaults on this stack (frames 9 and 14)
+ o There are two segfaults on this stack (frames 9 and 14)
- +o The first faulting address (frame 11) is 0x50000800
+ o The first faulting address (frame 11) is 0x50000800
(gdb) p (void *)1342179328
$16 = (void *) 0x50000800
@@ -3399,7 +3399,7 @@
on will be somewhat clearer.
- 1122..22.. EEppiissooddee 22:: TThhee ccaassee ooff tthhee hhuunngg ffsscckk
+ 12.2. Episode 2: The case of the hung fsck
After setting a trap in the SEGV handler for accesses to the signal
thread's stack, I reran the kernel.
@@ -3788,12 +3788,12 @@
- 1133.. WWhhaatt ttoo ddoo wwhheenn UUMMLL ddooeessnn''tt wwoorrkk
+ 13. What to do when UML doesn't work
- 1133..11.. SSttrraannggee ccoommppiillaattiioonn eerrrroorrss wwhheenn yyoouu bbuuiilldd ffrroomm ssoouurrccee
+ 13.1. Strange compilation errors when you build from source
As of test11, it is necessary to have "ARCH=um" in the environment or
on the make command line for all steps in building UML, including
@@ -3824,8 +3824,8 @@
- 1133..33.. AA vvaarriieettyy ooff ppaanniiccss aanndd hhaannggss wwiitthh //ttmmpp oonn aa rreeiisseerrffss ffiilleessyyss--
- tteemm
+ 13.3. A variety of panics and hangs with /tmp on a reiserfs filesys-
+ tem
I saw this on reiserfs 3.5.21 and it seems to be fixed in 3.5.27.
Panics preceded by
@@ -3842,8 +3842,8 @@
- 1133..44.. TThhee ccoommppiillee ffaaiillss wwiitthh eerrrroorrss aabboouutt ccoonnfflliiccttiinngg ttyyppeess ffoorr
- ''ooppeenn'',, ''dduupp'',, aanndd ''wwaaiittppiidd''
+ 13.4. The compile fails with errors about conflicting types for
+ 'open', 'dup', and 'waitpid'
This happens when you build in /usr/src/linux. The UML build makes
the include/asm link point to include/asm-um. /usr/include/asm points
@@ -3854,14 +3854,14 @@
- 1133..55.. UUMMLL ddooeessnn''tt wwoorrkk wwhheenn //ttmmpp iiss aann NNFFSS ffiilleessyysstteemm
+ 13.5. UML doesn't work when /tmp is an NFS filesystem
This seems to be a similar situation with the ReiserFS problem above.
Some versions of NFS seems not to handle mmap correctly, which UML
depends on. The workaround is have /tmp be a non-NFS directory.
- 1133..66.. UUMMLL hhaannggss oonn bboooott wwhheenn ccoommppiilleedd wwiitthh ggpprrooff ssuuppppoorrtt
+ 13.6. UML hangs on boot when compiled with gprof support
If you build UML with gprof support and, early in the boot, it does
this
@@ -3878,7 +3878,7 @@
- 1133..77.. ssyyssllooggdd ddiieess wwiitthh aa SSIIGGTTEERRMM oonn ssttaarrttuupp
+ 13.7. syslogd dies with a SIGTERM on startup
The exact boot error depends on the distribution that you're booting,
but Debian produces this:
@@ -3897,17 +3897,17 @@
- 1133..88.. TTUUNN//TTAAPP nneettwwoorrkkiinngg ddooeessnn''tt wwoorrkk oonn aa 22..44 hhoosstt
+ 13.8. TUN/TAP networking doesn't work on a 2.4 host
There are a couple of problems which were
<http://www.geocrawler.com/lists/3/SourceForge/597/0/> name="pointed
out"> by Tim Robinson <timro at trkr dot net>
- +o It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
+ o It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
The fix is to upgrade to something more recent and then read the
next item.
- +o If you see
+ o If you see
File descriptor in bad state
@@ -3921,8 +3921,8 @@
- 1133..99.. YYoouu ccaann nneettwwoorrkk ttoo tthhee hhoosstt bbuutt nnoott ttoo ootthheerr mmaacchhiinneess oonn tthhee
- nneett
+ 13.9. You can network to the host but not to other machines on the
+ net
If you can connect to the host, and the host can connect to UML, but
you cannot connect to any other machines, then you may need to enable
@@ -3972,7 +3972,7 @@
- 1133..1100.. II hhaavvee nnoo rroooott aanndd II wwaanntt ttoo ssccrreeaamm
+ 13.10. I have no root and I want to scream
Thanks to Birgit Wahlich for telling me about this strange one. It
turns out that there's a limit of six environment variables on the
@@ -3987,7 +3987,7 @@
- 1133..1111.. UUMMLL bbuuiilldd ccoonnfflliicctt bbeettwweeeenn ppttrraaccee..hh aanndd uuccoonntteexxtt..hh
+ 13.11. UML build conflict between ptrace.h and ucontext.h
On some older systems, /usr/include/asm/ptrace.h and
/usr/include/sys/ucontext.h define the same names. So, when they're
@@ -4007,7 +4007,7 @@
- 1133..1122.. TThhee UUMMLL BBooggooMMiippss iiss eexxaaccttllyy hhaallff tthhee hhoosstt''ss BBooggooMMiippss
+ 13.12. The UML BogoMips is exactly half the host's BogoMips
On i386 kernels, there are two ways of running the loop that is used
to calculate the BogoMips rating, using the TSC if it's there or using
@@ -4019,7 +4019,7 @@
- 1133..1133.. WWhheenn yyoouu rruunn UUMMLL,, iitt iimmmmeeddiiaatteellyy sseeggffaauullttss
+ 13.13. When you run UML, it immediately segfaults
If the host is configured with the 2G/2G address space split, that's
why. See ``UML on 2G/2G hosts'' for the details on getting UML to
@@ -4027,7 +4027,7 @@
- 1133..1144.. xxtteerrmmss aappppeeaarr,, tthheenn iimmmmeeddiiaatteellyy ddiissaappppeeaarr
+ 13.14. xterms appear, then immediately disappear
If you're running an up to date kernel with an old release of
uml_utilities, the port-helper program will not work properly, so
@@ -4039,7 +4039,7 @@
- 1133..1155.. AAnnyy ootthheerr ppaanniicc,, hhaanngg,, oorr ssttrraannggee bbeehhaavviioorr
+ 13.15. Any other panic, hang, or strange behavior
If you're seeing truly strange behavior, such as hangs or panics that
happen in random places, or you try running the debugger to see what's
@@ -4059,7 +4059,7 @@
If you want to be super-helpful, read ``Diagnosing Problems'' and
follow the instructions contained therein.
- 1144.. DDiiaaggnnoossiinngg PPrroobblleemmss
+ 14. Diagnosing Problems
If you get UML to crash, hang, or otherwise misbehave, you should
@@ -4078,7 +4078,7 @@
``Kernel debugging'' UML first.
- 1144..11.. CCaassee 11 :: NNoorrmmaall kkeerrnneell ppaanniiccss
+ 14.1. Case 1 : Normal kernel panics
The most common case is for a normal thread to panic. To debug this,
you will need to run it under the debugger (add 'debug' to the command
@@ -4128,7 +4128,7 @@
to get that information from the faulting ip.
- 1144..22.. CCaassee 22 :: TTrraacciinngg tthhrreeaadd ppaanniiccss
+ 14.2. Case 2 : Tracing thread panics
The less common and more painful case is when the tracing thread
panics. In this case, the kernel debugger will be useless because it
@@ -4161,7 +4161,7 @@
backtrace in and wait for our crack debugging team to fix the problem.
- 1144..33.. CCaassee 33 :: TTrraacciinngg tthhrreeaadd ppaanniiccss ccaauusseedd bbyy ootthheerr tthhrreeaaddss
+ 14.3. Case 3 : Tracing thread panics caused by other threads
However, there are cases where the misbehavior of another thread
caused the problem. The most common panic of this type is:
@@ -4227,7 +4227,7 @@
- 1144..44.. CCaassee 44 :: HHaannggss
+ 14.4. Case 4 : Hangs
Hangs seem to be fairly rare, but they sometimes happen. When a hang
happens, we need a backtrace from the offending process. Run the
@@ -4257,7 +4257,7 @@
- 1155.. TThhaannkkss
+ 15. Thanks
A number of people have helped this project in various ways, and this
@@ -4274,20 +4274,20 @@
bookkeeping lapses and I forget about contributions.
- 1155..11.. CCooddee aanndd DDooccuummeennttaattiioonn
+ 15.1. Code and Documentation
Rusty Russell <rusty at linuxcare.com.au> -
- +o wrote the HOWTO <http://user-mode-
+ o wrote the HOWTO <http://user-mode-
linux.sourceforge.net/UserModeLinux-HOWTO.html>
- +o prodded me into making this project official and putting it on
+ o prodded me into making this project official and putting it on
SourceForge
- +o came up with the way cool UML logo <http://user-mode-
+ o came up with the way cool UML logo <http://user-mode-
linux.sourceforge.net/uml-small.png>
- +o redid the config process
+ o redid the config process
Peter Moulder <reiter at netspace.net.au> - Fixed my config and build
@@ -4296,18 +4296,18 @@
Bill Stearns <wstearns at pobox.com> -
- +o HOWTO updates
+ o HOWTO updates
- +o lots of bug reports
+ o lots of bug reports
- +o lots of testing
+ o lots of testing
- +o dedicated a box (uml.ists.dartmouth.edu) to support UML development
+ o dedicated a box (uml.ists.dartmouth.edu) to support UML development
- +o wrote the mkrootfs script, which allows bootable filesystems of
+ o wrote the mkrootfs script, which allows bootable filesystems of
RPM-based distributions to be cranked out
- +o cranked out a large number of filesystems with said script
+ o cranked out a large number of filesystems with said script
Jim Leu <jleu at mindspring.com> - Wrote the virtual ethernet driver
@@ -4375,176 +4375,176 @@
David Coulson <http://davidcoulson.net> -
- +o Set up the usermodelinux.org <http://usermodelinux.org> site,
+ o Set up the usermodelinux.org <http://usermodelinux.org> site,
which is a great way of keeping the UML user community on top of
UML goings-on.
- +o Site documentation and updates
+ o Site documentation and updates
- +o Nifty little UML management daemon UMLd
+ o Nifty little UML management daemon UMLd
<http://uml.openconsultancy.com/umld/>
- +o Lots of testing and bug reports
+ o Lots of testing and bug reports
- 1155..22.. FFlluusshhiinngg oouutt bbuuggss
+ 15.2. Flushing out bugs
- +o Yuri Pudgorodsky
+ o Yuri Pudgorodsky
- +o Gerald Britton
+ o Gerald Britton
- +o Ian Wehrman
+ o Ian Wehrman
- +o Gord Lamb
+ o Gord Lamb
- +o Eugene Koontz
+ o Eugene Koontz
- +o John H. Hartman
+ o John H. Hartman
- +o Anders Karlsson
+ o Anders Karlsson
- +o Daniel Phillips
+ o Daniel Phillips
- +o John Fremlin
+ o John Fremlin
- +o Rainer Burgstaller
+ o Rainer Burgstaller
- +o James Stevenson
+ o James Stevenson
- +o Matt Clay
+ o Matt Clay
- +o Cliff Jefferies
+ o Cliff Jefferies
- +o Geoff Hoff
+ o Geoff Hoff
- +o Lennert Buytenhek
+ o Lennert Buytenhek
- +o Al Viro
+ o Al Viro
- +o Frank Klingenhoefer
+ o Frank Klingenhoefer
- +o Livio Baldini Soares
+ o Livio Baldini Soares
- +o Jon Burgess
+ o Jon Burgess
- +o Petru Paler
+ o Petru Paler
- +o Paul
+ o Paul
- +o Chris Reahard
+ o Chris Reahard
- +o Sverker Nilsson
+ o Sverker Nilsson
- +o Gong Su
+ o Gong Su
- +o johan verrept
+ o johan verrept
- +o Bjorn Eriksson
+ o Bjorn Eriksson
- +o Lorenzo Allegrucci
+ o Lorenzo Allegrucci
- +o Muli Ben-Yehuda
+ o Muli Ben-Yehuda
- +o David Mansfield
+ o David Mansfield
- +o Howard Goff
+ o Howard Goff
- +o Mike Anderson
+ o Mike Anderson
- +o John Byrne
+ o John Byrne
- +o Sapan J. Batia
+ o Sapan J. Batia
- +o Iris Huang
+ o Iris Huang
- +o Jan Hudec
+ o Jan Hudec
- +o Voluspa
+ o Voluspa
- 1155..33.. BBuugglleettss aanndd cclleeaann--uuppss
+ 15.3. Buglets and clean-ups
- +o Dave Zarzycki
+ o Dave Zarzycki
- +o Adam Lazur
+ o Adam Lazur
- +o Boria Feigin
+ o Boria Feigin
- +o Brian J. Murrell
+ o Brian J. Murrell
- +o JS
+ o JS
- +o Roman Zippel
+ o Roman Zippel
- +o Wil Cooley
+ o Wil Cooley
- +o Ayelet Shemesh
+ o Ayelet Shemesh
- +o Will Dyson
+ o Will Dyson
- +o Sverker Nilsson
+ o Sverker Nilsson
- +o dvorak
+ o dvorak
- +o v.naga srinivas
+ o v.naga srinivas
- +o Shlomi Fish
+ o Shlomi Fish
- +o Roger Binns
+ o Roger Binns
- +o johan verrept
+ o johan verrept
- +o MrChuoi
+ o MrChuoi
- +o Peter Cleve
+ o Peter Cleve
- +o Vincent Guffens
+ o Vincent Guffens
- +o Nathan Scott
+ o Nathan Scott
- +o Patrick Caulfield
+ o Patrick Caulfield
- +o jbearce
+ o jbearce
- +o Catalin Marinas
+ o Catalin Marinas
- +o Shane Spencer
+ o Shane Spencer
- +o Zou Min
+ o Zou Min
- +o Ryan Boder
+ o Ryan Boder
- +o Lorenzo Colitti
+ o Lorenzo Colitti
- +o Gwendal Grignou
+ o Gwendal Grignou
- +o Andre' Breiler
+ o Andre' Breiler
- +o Tsutomu Yasuda
+ o Tsutomu Yasuda
- 1155..44.. CCaassee SSttuuddiieess
+ 15.4. Case Studies
- +o Jon Wright
+ o Jon Wright
- +o William McEwan
+ o William McEwan
- +o Michael Richardson
+ o Michael Richardson
- 1155..55.. OOtthheerr ccoonnttrriibbuuttiioonnss
+ 15.5. Other contributions
Bill Carr <Bill.Carr at compaq.com> made the Red Hat mkrootfs script
diff --git a/Documentation/vm/00-INDEX b/Documentation/vm/00-INDEX
index dca82d7c83d8..5481c8ba3412 100644
--- a/Documentation/vm/00-INDEX
+++ b/Documentation/vm/00-INDEX
@@ -30,8 +30,6 @@ page_migration
- description of page migration in NUMA systems.
pagemap.txt
- pagemap, from the userspace perspective
-slabinfo.c
- - source code for a tool to get reports about slabs.
slub.txt
- a short users guide for SLUB.
unevictable-lru.txt
diff --git a/Documentation/vm/numa b/Documentation/vm/numa
index a200a386429d..ade01274212d 100644
--- a/Documentation/vm/numa
+++ b/Documentation/vm/numa
@@ -109,11 +109,11 @@ to improve NUMA locality using various CPU affinity command line interfaces,
such as taskset(1) and numactl(1), and program interfaces such as
sched_setaffinity(2). Further, one can modify the kernel's default local
allocation behavior using Linux NUMA memory policy.
-[see Documentation/vm/numa_memory_policy.]
+[see Documentation/vm/numa_memory_policy.txt.]
System administrators can restrict the CPUs and nodes' memories that a non-
privileged user can specify in the scheduling or NUMA commands and functions
-using control groups and CPUsets. [see Documentation/cgroups/CPUsets.txt]
+using control groups and CPUsets. [see Documentation/cgroups/cpusets.txt]
On architectures that do not hide memoryless nodes, Linux will include only
zones [nodes] with memory in the zonelists. This means that for a memoryless
diff --git a/Documentation/vm/slub.txt b/Documentation/vm/slub.txt
index 07375e73981a..f464f47bc60d 100644
--- a/Documentation/vm/slub.txt
+++ b/Documentation/vm/slub.txt
@@ -17,7 +17,7 @@ data and perform operation on the slabs. By default slabinfo only lists
slabs that have data in them. See "slabinfo -h" for more options when
running the command. slabinfo can be compiled with
-gcc -o slabinfo Documentation/vm/slabinfo.c
+gcc -o slabinfo tools/slub/slabinfo.c
Some of the modes of operation of slabinfo require that slub debugging
be enabled on the command line. F.e. no tracking information will be
diff --git a/Documentation/x86/entry_64.txt b/Documentation/x86/entry_64.txt
index 7869f14d055c..bc7226ef5055 100644
--- a/Documentation/x86/entry_64.txt
+++ b/Documentation/x86/entry_64.txt
@@ -27,9 +27,6 @@ Some of these entries are:
magically-generated functions that make their way to do_IRQ with
the interrupt number as a parameter.
- - emulate_vsyscall: int 0xcc, a special non-ABI entry used by
- vsyscall emulation.
-
- APIC interrupts: Various special-purpose interrupts for things
like TLB shootdown.
diff --git a/Documentation/zh_CN/SubmitChecklist b/Documentation/zh_CN/SubmitChecklist
deleted file mode 100644
index 4c741d6bc048..000000000000
--- a/Documentation/zh_CN/SubmitChecklist
+++ /dev/null
@@ -1,109 +0,0 @@
-Chinese translated version of Documentation/SubmitChecklist
-
-If you have any comment or update to the content, please contact the
-original document maintainer directly. However, if you have a problem
-communicating in English you can also ask the Chinese maintainer for
-help. Contact the Chinese maintainer if this translation is outdated
-or if there is a problem with the translation.
-
-Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
----------------------------------------------------------------------
-Documentation/SubmitChecklist µÄÖÐÎÄ·­Òë
-
-Èç¹ûÏëÆÀÂÛ»ò¸üб¾ÎĵÄÄÚÈÝ£¬ÇëÖ±½ÓÁªÏµÔ­ÎĵµµÄά»¤Õß¡£Èç¹ûÄãʹÓÃÓ¢ÎÄ
-½»Á÷ÓÐÀ§Äѵϰ£¬Ò²¿ÉÒÔÏòÖÐÎİæÎ¬»¤ÕßÇóÖú¡£Èç¹û±¾·­Òë¸üв»¼°Ê±»òÕß·­
-Òë´æÔÚÎÊÌ⣬ÇëÁªÏµÖÐÎİæÎ¬»¤Õß¡£
-
-ÖÐÎİæÎ¬»¤Õߣº ¼ÖÍþÍþ Harry Wei <harryxiyou@gmail.com>
-ÖÐÎİ淭ÒëÕߣº ¼ÖÍþÍþ Harry Wei <harryxiyou@gmail.com>
-ÖÐÎİæÐ£ÒëÕߣº ¼ÖÍþÍþ Harry Wei <harryxiyou@gmail.com>
-
-
-ÒÔÏÂΪÕýÎÄ
----------------------------------------------------------------------
-LinuxÄÚºËÌá½»Çåµ¥
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-ÕâÀïÓÐһЩÄں˿ª·¢ÕßÓ¦¸Ã×öµÄ»ù±¾ÊÂÇ飬Èç¹ûËûÃÇÏë¿´µ½×Ô¼ºµÄÄں˲¹¶¡Ìá½»
-±»½ÓÊܵĸü¿ì¡£
-
-ÕâЩ¶¼Êdz¬³öDocumentation/SubmittingPatchesÎĵµÀïËùÌṩµÄÒÔ¼°ÆäËû
-¹ØÓÚÌá½»LinuxÄں˲¹¶¡µÄ˵Ã÷¡£
-
-1£ºÈç¹ûÄãʹÓÃÁËÒ»¸ö¹¦ÄÜÄÇô¾Í#include¶¨Òå/ÉùÃ÷ÄǸö¹¦ÄܵÄÄǸöÎļþ¡£
- ²»ÒªÒÀ¿¿ÆäËû¼ä½ÓÒýÈ붨Òå/ÉùÃ÷ÄǸö¹¦ÄܵÄÍ·Îļþ¡£
-
-2£º¹¹½¨¼ò½àÊÊÓûòÕ߸ü¸ÄCONFIGÑ¡Ïî =y£¬=m£¬»òÕß=n¡£
- ²»ÒªÓбàÒ뾯¸æ/´íÎó£¬ ²»ÒªÓÐÁ´½Ó¾¯¸æ/´íÎó¡£
-
-2b£ºÍ¨¹ý allnoconfig, allmodconfig
-
-2c£ºµ±Ê¹Óà 0=builddir ³É¹¦µØ¹¹½¨
-
-3£ºÍ¨¹ýʹÓñ¾µØ½»²æ±àÒ빤¾ß»òÕ߯äËûһЩ¹¹½¨²úËù£¬ÔÚ¶àCPU¿ò¼ÜÉϹ¹½¨¡£
-
-4£ºppc64 ÊÇÒ»¸öºÜºÃµÄ¼ì²é½»²æ±àÒëµÄ¿ò¼Ü£¬ÒòΪËüÍùÍù°Ñ¡®unsigned long¡¯
- µ±64λֵÀ´Ê¹Óá£
-
-5£º°´ÕÕDocumentation/CodingStyleÎļþÀïµÄÏêϸÃèÊö£¬¼ì²éÄã²¹¶¡µÄÕûÌå·ç¸ñ¡£
- ʹÓò¹¶¡·ç¸ñ¼ì²éËöËéµÄÎ¥¹æ(scripts/checkpatch.pl)£¬ÉóºËÔ±ÓÅÏÈÌá½»¡£
- ÄãÓ¦¸Ãµ÷ÕûÒÅÁôÔÚÄã²¹¶¡ÖеÄËùÓÐÎ¥¹æ¡£
-
-6£ºÈκθüлòÕ߸͝CONFIGÑ¡Ïî¶¼²»ÄÜ´òÂÒÅäÖò˵¥¡£
-
-7£ºËùÓеÄKconfigÑ¡Ïî¸üж¼ÒªÓÐ˵Ã÷ÎÄ×Ö¡£
-
-8£ºÒѾ­ÈÏÕæµØ×ܽáÁËÏà¹ØµÄKconfig×éºÏ¡£ÕâÊǺÜÄÑͨ¹ý²âÊÔ×öºÃµÄ--ÄÔÁ¦ÔÚÕâÀïϽµ¡£
-
-9£º¼ì²é¾ßÓмò½àÐÔ¡£
-
-10£ºÊ¹ÓÃ'make checkstack'ºÍ'make namespacecheck'¼ì²é£¬È»ºóÐÞ¸ÄËùÕÒµ½µÄÎÊÌâ¡£
- ×¢Ò⣺¶ÑÕ»¼ì²é²»»áÃ÷È·µØ³öÏÖÎÊÌ⣬µ«ÊÇÈκεÄÒ»¸öº¯ÊýÔÚ¶ÑÕ»ÉÏʹÓöàÓÚ512×Ö½Ú
- ¶¼Òª×¼±¸Ð޸ġ£
-
-11£º°üº¬kernel-docµ½È«¾ÖÄÚºËAPIsÎļþ¡££¨²»ÒªÇó¾²Ì¬µÄº¯Êý£¬µ«Êǰüº¬Ò²ÎÞËùν¡££©
- ʹÓÃ'make htmldocs'»òÕß'make mandocs'À´¼ì²ékernel-doc£¬È»ºóÐÞ¸ÄÈκÎ
- ·¢ÏÖµÄÎÊÌâ¡£
-
-12£ºÒѾ­Í¨¹ýCONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
- CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
- CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP²âÊÔ£¬²¢ÇÒͬʱ¶¼
- ʹÄÜ¡£
-
-13£ºÒѾ­¶¼¹¹½¨²¢ÇÒʹÓûòÕß²»Ê¹Óà CONFIG_SMP ºÍ CONFIG_PREEMPT²âÊÔÖ´ÐÐʱ¼ä¡£
-
-14£ºÈç¹û²¹¶¡Ó°ÏìIO/Disk£¬µÈµÈ£ºÒѾ­Í¨¹ýʹÓûòÕß²»Ê¹Óà CONFIG_LBDAF ²âÊÔ¡£
-
-15£ºËùÓеÄcodepathsÒѾ­ÐÐʹËùÓÐlockdepÆôÓù¦ÄÜ¡£
-
-16£ºËùÓеÄ/proc¼Ç¼¸üж¼Òª×÷³ÉÎļþ·ÅÔÚDocumentation/Ŀ¼Ï¡£
-
-17£ºËùÓеÄÄÚºËÆô¶¯²ÎÊý¸üж¼±»¼Ç¼µ½Documentation/kernel-parameters.txtÎļþÖС£
-
-18£ºËùÓеÄÄ£¿é²ÎÊý¸üж¼ÓÃMODULE_PARM_DESC()¼Ç¼¡£
-
-19£ºËùÓеÄÓû§¿Õ¼ä½Ó¿Ú¸üж¼±»¼Ç¼µ½Documentation/ABI/¡£²é¿´Documentation/ABI/README
- ¿ÉÒÔ»ñµÃ¸ü¶àµÄÐÅÏ¢¡£¸Ä±äÓû§¿Õ¼ä½Ó¿ÚµÄ²¹¶¡Ó¦¸Ã±»Óʼþ³­Ë͸ølinux-api@vger.kernel.org¡£
-
-20£º¼ì²éËüÊDz»ÊǶ¼Í¨¹ý`make headers_check'¡£
-
-21£ºÒѾ­Í¨¹ýÖÁÉÙÒýÈëslabºÍpage-allocationʧ°Ü¼ì²é¡£²é¿´Documentation/fault-injection/¡£
-
-22£ºÐ¼ÓÈëµÄÔ´ÂëÒѾ­Í¨¹ý`gcc -W'£¨Ê¹ÓÃ"make EXTRA_CFLAGS=-W"£©±àÒë¡£ÕâÑù½«²úÉúºÜ¶à·³ÄÕ£¬
- µ«ÊǶÔÓÚѰÕÒ©¶´ºÜÓÐÒæ´¦£¬ÀýÈç:"warning: comparison between signed and unsigned"¡£
-
-23£ºµ±Ëü±»ºÏ²¢µ½-mm²¹¶¡¼¯ºóÔÙ²âÊÔ£¬ÓÃÀ´È·¶¨ËüÊÇ·ñ»¹ºÍ²¹¶¡¶ÓÁÐÖÐµÄÆäËû²¹¶¡Ò»Æð¹¤×÷ÒÔ¼°ÔÚVM£¬VFS
- ºÍÆäËû×ÓϵͳÖи÷¸ö±ä»¯¡£
-
-24£ºËùÓеÄÄÚ´æÆÁÕÏ{e.g., barrier(), rmb(), wmb()}ÐèÒªÔÚÔ´´úÂëÖеÄÒ»¸ö×¢ÊÍÀ´½âÊÍËûÃǶ¼ÊǸÉʲôµÄ
- ÒÔ¼°Ô­Òò¡£
-
-25£ºÈç¹ûÓÐÈκÎÊäÈëÊä³ö¿ØÖƵIJ¹¶¡±»Ìí¼Ó£¬Ò²Òª¸üÐÂDocumentation/ioctl/ioctl-number.txt¡£
-
-26£ºÈç¹ûÄãµÄ¸ü¸Ä´úÂëÒÀ¿¿»òÕßʹÓÃÈκεÄÄÚºËAPIs»òÕßÓëÏÂÃæµÄkconfig·ûºÅÓйØÏµµÄ¹¦ÄÜ£¬Äã¾ÍÒª
- ʹÓÃÏà¹ØµÄkconfig·ûºÅ¹Ø±Õ£¬ and/or =m£¨Èç¹ûÑ¡ÏîÌṩ£©[ÔÚͬһʱ¼ä²»ÊÇËùÓõͼÆôÓ㬽ö½ö¸÷¸ö»òÕß×ÔÓÉ
- ×éºÏËûÃÇ]£º
-
- CONFIG_SMP, CONFIG_SYSFS, CONFIG_PROC_FS, CONFIG_INPUT, CONFIG_PCI,
- CONFIG_BLOCK, CONFIG_PM, CONFIG_HOTPLUG, CONFIG_MAGIC_SYSRQ,
- CONFIG_NET, CONFIG_INET=n (ºóÒ»¸öʹÓà CONFIG_NET=y)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6185d0513584..ab7767001286 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -117,20 +117,20 @@ Maintainers List (try to look for most precise areas first)
M: Philip Blundell <philb@gnu.org>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/3c505*
+F: drivers/net/ethernet/i825xx/3c505*
3C59X NETWORK DRIVER
M: Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/networking/vortex.txt
-F: drivers/net/3c59x.c
+F: drivers/net/ethernet/3com/3c59x.c
3CR990 NETWORK DRIVER
M: David Dillow <dave@thedillows.org>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/typhoon*
+F: drivers/net/ethernet/3com/typhoon*
3WARE SAS/SATA-RAID SCSI DRIVERS (3W-XXXX, 3W-9XXX, 3W-SAS)
M: Adam Radford <linuxraid@lsi.com>
@@ -156,7 +156,7 @@ M: Realtek linux nic maintainers <nic_swsd@realtek.com>
M: Francois Romieu <romieu@fr.zoreil.com>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/r8169.c
+F: drivers/net/ethernet/realtek/r8169.c
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
M: Greg Kroah-Hartman <gregkh@suse.de>
@@ -170,8 +170,7 @@ F: include/linux/serial_8250.h
8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
L: netdev@vger.kernel.org
S: Orphan / Obsolete
-F: drivers/net/*8390*
-F: drivers/net/ax88796.c
+F: drivers/net/ethernet/8390/
9P FILE SYSTEM
M: Eric Van Hensbergen <ericvh@gmail.com>
@@ -214,7 +213,7 @@ ACENIC DRIVER
M: Jes Sorensen <jes@trained-monkey.org>
L: linux-acenic@sunsite.dk
S: Maintained
-F: drivers/net/acenic*
+F: drivers/net/ethernet/alteon/acenic*
ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER
M: Peter Feuerer <peter@piie.net>
@@ -317,6 +316,10 @@ W: http://wiki.analog.com/AD7879
S: Supported
F: drivers/input/touchscreen/ad7879.c
+ADDRESS SPACE LAYOUT RANDOMIZATION (ASLR)
+M: Jiri Kosina <jkosina@suse.cz>
+S: Maintained
+
ADM1025 HARDWARE MONITOR DRIVER
M: Jean Delvare <khali@linux-fr.org>
L: lm-sensors@lm-sensors.org
@@ -530,6 +533,7 @@ S: Maintained
F: drivers/infiniband/hw/amso1100/
ANALOG DEVICES INC ASOC CODEC DRIVERS
+M: Lars-Peter Clausen <lars@metafoo.de>
L: device-drivers-devel@blackfin.uclinux.org
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://wiki.analog.com/
@@ -688,6 +692,12 @@ F: drivers/mtd/nand/bcm_umi_nand.c
F: drivers/mtd/nand/bcm_umi_bch.c
F: drivers/mtd/nand/nand_bcm_umi.h
+ARM/CALXEDA HIGHBANK ARCHITECTURE
+M: Rob Herring <rob.herring@calxeda.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-highbank/
+
ARM/CAVIUM NETWORKS CNS3XXX MACHINE SUPPORT
M: Anton Vorontsov <avorontsov@mvista.com>
S: Maintained
@@ -746,7 +756,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.arm.linux.org.uk/
S: Maintained
F: arch/arm/mach-ebsa110/
-F: drivers/net/arm/am79c961a.*
+F: drivers/net/ethernet/amd/am79c961a.*
ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
M: Daniel Ribeiro <drwyrm@gmail.com>
@@ -787,6 +797,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-mx5/
+ARM/FREESCALE IMX6
+M: Shawn Guo <shawn.guo@linaro.org>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+T: git git://git.linaro.org/people/shawnguo/linux-2.6.git
+F: arch/arm/mach-imx/*imx6*
+
ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1015,7 +1032,8 @@ F: arch/arm/include/asm/hardware/ioc.h
F: arch/arm/include/asm/hardware/iomd.h
F: arch/arm/include/asm/hardware/memc.h
F: arch/arm/mach-rpc/
-F: drivers/net/arm/ether*
+F: drivers/net/ethernet/i825xx/ether1*
+F: drivers/net/ethernet/seeq/ether3*
F: drivers/scsi/arm/
ARM/SHARK MACHINE SUPPORT
@@ -1084,6 +1102,24 @@ F: arch/arm/plat-s5p/dev-fimc*
F: arch/arm/plat-samsung/include/plat/*fimc*
F: drivers/media/video/s5p-fimc/
+ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
+M: Kyungmin Park <kyungmin.park@samsung.com>
+M: Kamil Debski <k.debski@samsung.com>
+L: linux-arm-kernel@lists.infradead.org
+L: linux-media@vger.kernel.org
+S: Maintained
+F: arch/arm/plat-s5p/dev-mfc.c
+F: drivers/media/video/s5p-mfc/
+
+ARM/SAMSUNG S5P SERIES TV SUBSYSTEM SUPPORT
+M: Kyungmin Park <kyungmin.park@samsung.com>
+M: Tomasz Stanislawski <t.stanislaws@samsung.com>
+L: linux-arm-kernel@lists.infradead.org
+L: linux-media@vger.kernel.org
+S: Maintained
+F: arch/arm/plat-s5p/dev-tv.c
+F: drivers/media/video/s5p-tv/
+
ARM/SHMOBILE ARM ARCHITECTURE
M: Paul Mundt <lethal@linux-sh.org>
M: Magnus Damm <magnus.damm@gmail.com>
@@ -1127,7 +1163,7 @@ F: arch/arm/mach-nuc93x/
F: drivers/input/keyboard/w90p910_keypad.c
F: drivers/input/touchscreen/w90p910_ts.c
F: drivers/watchdog/nuc900_wdt.c
-F: drivers/net/arm/w90p910_ether.c
+F: drivers/net/ethernet/nuvoton/w90p910_ether.c
F: drivers/mtd/nand/nuc900_nand.c
F: drivers/rtc/rtc-nuc900.c
F: drivers/spi/spi_nuc900.c
@@ -1230,7 +1266,7 @@ F: Documentation/aoe/
F: drivers/block/aoe/
ATHEROS ATH GENERIC UTILITIES
-M: "Luis R. Rodriguez" <lrodriguez@atheros.com>
+M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
L: linux-wireless@vger.kernel.org
S: Supported
F: drivers/net/wireless/ath/*
@@ -1238,7 +1274,7 @@ F: drivers/net/wireless/ath/*
ATHEROS ATH5K WIRELESS DRIVER
M: Jiri Slaby <jirislaby@gmail.com>
M: Nick Kossifidis <mickflemm@gmail.com>
-M: "Luis R. Rodriguez" <lrodriguez@atheros.com>
+M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
M: Bob Copeland <me@bobcopeland.com>
L: linux-wireless@vger.kernel.org
L: ath5k-devel@lists.ath5k.org
@@ -1246,11 +1282,19 @@ W: http://wireless.kernel.org/en/users/Drivers/ath5k
S: Maintained
F: drivers/net/wireless/ath/ath5k/
+ATHEROS ATH6KL WIRELESS DRIVER
+M: Kalle Valo <kvalo@qca.qualcomm.com>
+L: linux-wireless@vger.kernel.org
+W: http://wireless.kernel.org/en/users/Drivers/ath6kl
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath6kl.git
+S: Supported
+F: drivers/net/wireless/ath/ath6kl/
+
ATHEROS ATH9K WIRELESS DRIVER
-M: "Luis R. Rodriguez" <lrodriguez@atheros.com>
-M: Jouni Malinen <jmalinen@atheros.com>
-M: Vasanthakumar Thiagarajan <vasanth@atheros.com>
-M: Senthil Balasubramanian <senthilkumar@atheros.com>
+M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
+M: Jouni Malinen <jouni@qca.qualcomm.com>
+M: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
+M: Senthil Balasubramanian <senthilb@qca.qualcomm.com>
L: linux-wireless@vger.kernel.org
L: ath9k-devel@lists.ath9k.org
W: http://wireless.kernel.org/en/users/Drivers/ath9k
@@ -1282,7 +1326,7 @@ L: netdev@vger.kernel.org
W: http://sourceforge.net/projects/atl1
W: http://atl1.sourceforge.net
S: Maintained
-F: drivers/net/atlx/
+F: drivers/net/ethernet/atheros/
ATM
M: Chas Williams <chas@cmf.nrl.navy.mil>
@@ -1322,7 +1366,7 @@ F: include/video/atmel_lcdc.h
ATMEL MACB ETHERNET DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported
-F: drivers/net/macb.*
+F: drivers/net/ethernet/cadence/
ATMEL SPI DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com>
@@ -1445,7 +1489,7 @@ BLACKFIN EMAC DRIVER
L: uclinux-dist-devel@blackfin.uclinux.org
W: http://blackfin.uclinux.org
S: Supported
-F: drivers/net/bfin_mac.*
+F: drivers/net/ethernet/adi/
BLACKFIN RTC DRIVER
M: Mike Frysinger <vapier.adi@gmail.com>
@@ -1526,27 +1570,27 @@ BROADCOM B44 10/100 ETHERNET DRIVER
M: Gary Zambrano <zambrano@broadcom.com>
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/b44.*
+F: drivers/net/ethernet/broadcom/b44.*
BROADCOM BNX2 GIGABIT ETHERNET DRIVER
M: Michael Chan <mchan@broadcom.com>
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/bnx2.*
-F: drivers/net/bnx2_*
+F: drivers/net/ethernet/broadcom/bnx2.*
+F: drivers/net/ethernet/broadcom/bnx2_*
BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
M: Eilon Greenstein <eilong@broadcom.com>
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/bnx2x/
+F: drivers/net/ethernet/broadcom/bnx2x/
BROADCOM TG3 GIGABIT ETHERNET DRIVER
M: Matt Carlson <mcarlson@broadcom.com>
M: Michael Chan <mchan@broadcom.com>
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/tg3.*
+F: drivers/net/ethernet/broadcom/tg3.*
BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
M: Brett Rudley <brudley@broadcom.com>
@@ -1575,7 +1619,7 @@ BROCADE BNA 10 GIGABIT ETHERNET DRIVER
M: Rasesh Mody <rmody@brocade.com>
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/bna/
+F: drivers/net/ethernet/brocade/bna/
BSG (block layer generic sg v4 driver)
M: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
@@ -1663,7 +1707,7 @@ CAN NETWORK LAYER
M: Oliver Hartkopp <socketcan@hartkopp.net>
M: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
M: Urs Thuermann <urs.thuermann@volkswagen.de>
-L: socketcan-core@lists.berlios.de (subscribers-only)
+L: linux-can@vger.kernel.org
L: netdev@vger.kernel.org
W: http://developer.berlios.de/projects/socketcan/
S: Maintained
@@ -1675,7 +1719,7 @@ F: include/linux/can/raw.h
CAN NETWORK DRIVERS
M: Wolfgang Grandegger <wg@grandegger.com>
-L: socketcan-core@lists.berlios.de (subscribers-only)
+L: linux-can@vger.kernel.org
L: netdev@vger.kernel.org
W: http://developer.berlios.de/projects/socketcan/
S: Maintained
@@ -1759,13 +1803,13 @@ M: Christian Benvenuti <benve@cisco.com>
M: Roopa Prabhu <roprabhu@cisco.com>
M: David Wang <dwang2@cisco.com>
S: Supported
-F: drivers/net/enic/
+F: drivers/net/ethernet/cisco/enic/
CIRRUS LOGIC EP93XX ETHERNET DRIVER
M: Hartley Sweeten <hsweeten@visionengravers.com>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/arm/ep93xx_eth.c
+F: drivers/net/ethernet/cirrus/ep93xx_eth.c
CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER
M: Lennert Buytenhek <kernel@wantstofly.org>
@@ -1905,7 +1949,7 @@ CPMAC ETHERNET DRIVER
M: Florian Fainelli <florian@openwrt.org>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/cpmac.c
+F: drivers/net/ethernet/ti/cpmac.c
CPU FREQUENCY DRIVERS
M: Dave Jones <davej@redhat.com>
@@ -1992,7 +2036,7 @@ M: Divy Le Ray <divy@chelsio.com>
L: netdev@vger.kernel.org
W: http://www.chelsio.com
S: Supported
-F: drivers/net/cxgb3/
+F: drivers/net/ethernet/chelsio/cxgb3/
CXGB3 IWARP RNIC DRIVER (IW_CXGB3)
M: Steve Wise <swise@chelsio.com>
@@ -2006,7 +2050,7 @@ M: Dimitris Michailidis <dm@chelsio.com>
L: netdev@vger.kernel.org
W: http://www.chelsio.com
S: Supported
-F: drivers/net/cxgb4/
+F: drivers/net/ethernet/chelsio/cxgb4/
CXGB4 IWARP RNIC DRIVER (IW_CXGB4)
M: Steve Wise <swise@chelsio.com>
@@ -2020,14 +2064,14 @@ M: Casey Leedom <leedom@chelsio.com>
L: netdev@vger.kernel.org
W: http://www.chelsio.com
S: Supported
-F: drivers/net/cxgb4vf/
+F: drivers/net/ethernet/chelsio/cxgb4vf/
STMMAC ETHERNET DRIVER
M: Giuseppe Cavallaro <peppe.cavallaro@st.com>
L: netdev@vger.kernel.org
W: http://www.stlinux.com
S: Supported
-F: drivers/net/stmmac/
+F: drivers/net/ethernet/stmicro/stmmac/
CYBERPRO FB DRIVER
M: Russell King <linux@arm.linux.org.uk>
@@ -2071,7 +2115,7 @@ DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
L: netdev@vger.kernel.org
S: Orphan
F: Documentation/networking/dmfe.txt
-F: drivers/net/tulip/dmfe.c
+F: drivers/net/ethernet/tulip/dmfe.c
DC390/AM53C974 SCSI driver
M: Kurt Garloff <garloff@suse.de>
@@ -2110,7 +2154,7 @@ F: net/decnet/
DEFXX FDDI NETWORK DRIVER
M: "Maciej W. Rozycki" <macro@linux-mips.org>
S: Maintained
-F: drivers/net/defxx.*
+F: drivers/net/fddi/defxx.*
DELL LAPTOP DRIVER
M: Matthew Garrett <mjg59@srcf.ucam.org>
@@ -2136,6 +2180,14 @@ M: Matthew Garrett <mjg59@srcf.ucam.org>
S: Maintained
F: drivers/platform/x86/dell-wmi.c
+DESIGNWARE USB3 DRD IP DRIVER
+M: Felipe Balbi <balbi@ti.com>
+L: linux-usb@vger.kernel.org
+L: linux-omap@vger.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
+S: Maintained
+F: drivers/usb/dwc3/
+
DEVICE NUMBER REGISTRY
M: Torben Mathiasen <device@lanana.org>
W: http://lanana.org/docs/device-list/index.html
@@ -2294,6 +2346,12 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/wan/dscc4.c
+DYNAMIC DEBUG
+M: Jason Baron <jbaron@redhat.com>
+S: Maintained
+F: lib/dynamic_debug.c
+F: include/linux/dynamic_debug.h
+
DZ DECSTATION DZ11 SERIAL DRIVER
M: "Maciej W. Rozycki" <macro@linux-mips.org>
S: Maintained
@@ -2409,8 +2467,6 @@ L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i7core_edac.c
-F: drivers/edac/edac_mce.c
-F: include/linux/edac_mce.h
EDAC-I82975X
M: Ranganathan Desikan <ravi@jetztechnologies.com>
@@ -2434,6 +2490,13 @@ W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/r82600_edac.c
+EDAC-SBRIDGE
+M: Mauro Carvalho Chehab <mchehab@redhat.com>
+L: linux-edac@vger.kernel.org
+W: bluesmoke.sourceforge.net
+S: Maintained
+F: drivers/edac/sb_edac.c
+
EDIROL UA-101/UA-1000 DRIVER
M: Clemens Ladisch <clemens@ladisch.de>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -2463,7 +2526,7 @@ EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
M: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/ehea/
+F: drivers/net/ethernet/ibm/ehea/
EMBEDDED LINUX
M: Paul Gortmaker <paul.gortmaker@windriver.com>
@@ -2508,7 +2571,7 @@ ETHEREXPRESS-16 NETWORK DRIVER
M: Philip Blundell <philb@gnu.org>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/eexpress.*
+F: drivers/net/ethernet/i825xx/eexpress.*
ETHERNET BRIDGE
M: Stephen Hemminger <shemminger@linux-foundation.org>
@@ -2522,7 +2585,7 @@ F: net/bridge/
ETHERTEAM 16I DRIVER
M: Mika Kuoppala <miku@iki.fi>
S: Maintained
-F: drivers/net/eth16i.c
+F: drivers/net/ethernet/fujitsu/eth16i.c
EXT2 FILE SYSTEM
M: Jan Kara <jack@suse.cz>
@@ -2552,6 +2615,11 @@ S: Maintained
F: Documentation/filesystems/ext4.txt
F: fs/ext4/
+Extended Verification Module (EVM)
+M: Mimi Zohar <zohar@us.ibm.com>
+S: Supported
+F: security/integrity/evm/
+
F71805F HARDWARE MONITORING DRIVER
M: Jean Delvare <khali@linux-fr.org>
L: lm-sensors@lm-sensors.org
@@ -2686,7 +2754,7 @@ M: Vitaly Bordug <vbordug@ru.mvista.com>
L: linuxppc-dev@lists.ozlabs.org
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/fs_enet/
+F: drivers/net/ethernet/freescale/fs_enet/
F: include/linux/fs_enet_pd.h
FREESCALE QUICC ENGINE LIBRARY
@@ -2708,7 +2776,7 @@ M: Li Yang <leoli@freescale.com>
L: netdev@vger.kernel.org
L: linuxppc-dev@lists.ozlabs.org
S: Maintained
-F: drivers/net/ucc_geth*
+F: drivers/net/ethernet/freescale/ucc_geth*
FREESCALE QUICC ENGINE UCC UART DRIVER
M: Timur Tabi <timur@freescale.com>
@@ -2733,7 +2801,7 @@ F: fs/freevxfs/
FREEZER
M: Pavel Machek <pavel@ucw.cz>
M: "Rafael J. Wysocki" <rjw@sisk.pl>
-L: linux-pm@lists.linux-foundation.org
+L: linux-pm@vger.kernel.org
S: Supported
F: Documentation/power/freezing-of-tasks.txt
F: include/linux/freezer.h
@@ -2950,6 +3018,13 @@ F: Documentation/hw_random.txt
F: drivers/char/hw_random/
F: include/linux/hw_random.h
+HARDWARE SPINLOCK CORE
+M: Ohad Ben-Cohen <ohad@wizery.com>
+S: Maintained
+F: Documentation/hwspinlock.txt
+F: drivers/hwspinlock/hwspinlock_*
+F: include/linux/hwspinlock.h
+
HARMONY SOUND DRIVER
M: Kyle McMartin <kyle@mcmartin.ca>
L: linux-parisc@vger.kernel.org
@@ -2995,7 +3070,7 @@ F: drivers/video/hgafb.c
HIBERNATION (aka Software Suspend, aka swsusp)
M: Pavel Machek <pavel@ucw.cz>
M: "Rafael J. Wysocki" <rjw@sisk.pl>
-L: linux-pm@lists.linux-foundation.org
+L: linux-pm@vger.kernel.org
S: Supported
F: arch/x86/power/
F: drivers/base/power/
@@ -3046,6 +3121,7 @@ S: Maintained
F: include/linux/hippidevice.h
F: include/linux/if_hippi.h
F: net/802/hippi.c
+F: drivers/net/hippi/
HOST AP DRIVER
M: Jouni Malinen <j@w1.fi>
@@ -3063,7 +3139,7 @@ F: drivers/platform/x86/tc1100-wmi.c
HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
M: Jaroslav Kysela <perex@perex.cz>
S: Maintained
-F: drivers/net/hp100.*
+F: drivers/net/ethernet/hp/hp100.*
HPET: High Precision Event Timers driver
M: Clemens Ladisch <clemens@ladisch.de>
@@ -3141,8 +3217,7 @@ IA64 (Itanium) PLATFORM
M: Tony Luck <tony.luck@intel.com>
M: Fenghua Yu <fenghua.yu@intel.com>
L: linux-ia64@vger.kernel.org
-W: http://www.ia64-linux.org/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git
S: Maintained
F: arch/ia64/
@@ -3161,7 +3236,7 @@ IBM Power Virtual Ethernet Device Driver
M: Santiago Leon <santil@linux.vnet.ibm.com>
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/ibmveth.*
+F: drivers/net/ethernet/ibm/ibmveth.*
IBM ServeRAID RAID DRIVER
P: Jack Hammer
@@ -3180,6 +3255,13 @@ F: Documentation/ide/
F: drivers/ide/
F: include/linux/ide.h
+IDEAPAD LAPTOP EXTRAS DRIVER
+M: Ike Panhc <ike.pan@canonical.com>
+L: platform-driver-x86@vger.kernel.org
+W: http://launchpad.net/ideapad-laptop
+S: Maintained
+F: drivers/platform/x86/ideapad-laptop.c
+
IDE/ATAPI DRIVERS
M: Borislav Petkov <petkovbb@gmail.com>
L: linux-ide@vger.kernel.org
@@ -3189,7 +3271,7 @@ F: drivers/ide/ide-cd*
IDLE-I7300
M: Andy Henroid <andrew.d.henroid@intel.com>
-L: linux-pm@lists.linux-foundation.org
+L: linux-pm@vger.kernel.org
S: Supported
F: drivers/idle/i7300_idle.c
@@ -3272,7 +3354,7 @@ F: firmware/isci/
INTEL IDLE DRIVER
M: Len Brown <lenb@kernel.org>
-L: linux-pm@lists.linux-foundation.org
+L: linux-pm@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-idle-2.6.git
S: Supported
F: drivers/idle/intel_idle.c
@@ -3328,7 +3410,7 @@ F: arch/arm/mach-ixp4xx/include/mach/qmgr.h
F: arch/arm/mach-ixp4xx/include/mach/npe.h
F: arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
F: arch/arm/mach-ixp4xx/ixp4xx_npe.c
-F: drivers/net/arm/ixp4xx_eth.c
+F: drivers/net/ethernet/xscale/ixp4xx_eth.c
F: drivers/net/wan/ixp4xx_hss.c
INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
@@ -3340,7 +3422,7 @@ INTEL IXP2000 ETHERNET DRIVER
M: Lennert Buytenhek <kernel@wantstofly.org>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/ixp2000/
+F: drivers/net/ethernet/xscale/ixp2000/
INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf)
M: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
@@ -3349,13 +3431,13 @@ M: Bruce Allan <bruce.w.allan@intel.com>
M: Carolyn Wyborny <carolyn.wyborny@intel.com>
M: Don Skidmore <donald.c.skidmore@intel.com>
M: Greg Rose <gregory.v.rose@intel.com>
-M: PJ Waskiewicz <peter.p.waskiewicz.jr@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>
L: e1000-devel@lists.sourceforge.net
W: http://e1000.sourceforge.net/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-2.6.git
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next-2.6.git
+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
S: Supported
F: Documentation/networking/e100.txt
F: Documentation/networking/e1000.txt
@@ -3365,18 +3447,11 @@ F: Documentation/networking/igbvf.txt
F: Documentation/networking/ixgb.txt
F: Documentation/networking/ixgbe.txt
F: Documentation/networking/ixgbevf.txt
-F: drivers/net/e100.c
-F: drivers/net/e1000/
-F: drivers/net/e1000e/
-F: drivers/net/igb/
-F: drivers/net/igbvf/
-F: drivers/net/ixgb/
-F: drivers/net/ixgbe/
-F: drivers/net/ixgbevf/
+F: drivers/net/ethernet/intel/
INTEL MRST PMU DRIVER
M: Len Brown <len.brown@intel.com>
-L: linux-pm@lists.linux-foundation.org
+L: linux-pm@vger.kernel.org
S: Supported
F: arch/x86/platform/mrst/pmu.*
@@ -3424,7 +3499,7 @@ M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org
W: http://intellinuxwireless.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git
S: Supported
F: drivers/net/wireless/iwlwifi/
@@ -3440,7 +3515,7 @@ IOC3 ETHERNET DRIVER
M: Ralf Baechle <ralf@linux-mips.org>
L: linux-mips@linux-mips.org
S: Maintained
-F: drivers/net/ioc3-eth.c
+F: drivers/net/ethernet/sgi/ioc3-eth.c
IOC3 SERIAL DRIVER
M: Pat Gefre <pfg@sgi.com>
@@ -3458,7 +3533,7 @@ M: Francois Romieu <romieu@fr.zoreil.com>
M: Sorbica Shieh <sorbica@icplus.com.tw>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/ipg.*
+F: drivers/net/ethernet/icplus/ipg.*
IPATH DRIVER
M: Mike Marciniszyn <infinipath@qlogic.com>
@@ -3606,7 +3681,7 @@ JME NETWORK DRIVER
M: Guo-Fu Tseng <cooldavid@cooldavid.org>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/jme.*
+F: drivers/net/ethernet/jme.*
JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
M: David Woodhouse <dwmw2@infradead.org>
@@ -3973,6 +4048,7 @@ M: Eric Piel <eric.piel@tremplin-utc.net>
S: Maintained
F: Documentation/misc-devices/lis3lv02d
F: drivers/misc/lis3lv02d/
+F: drivers/platform/x86/hp_accel.c
LLC (802.2)
M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
@@ -4067,7 +4143,7 @@ S: Maintained
M32R ARCHITECTURE
M: Hirokazu Takata <takata@linux-m32r.org>
-L: linux-m32r@ml.linux-m32r.org
+L: linux-m32r@ml.linux-m32r.org (moderated for non-subscribers)
L: linux-m32r-ja@ml.linux-m32r.org (in Japanese)
W: http://www.linux-m32r.org/
S: Maintained
@@ -4137,7 +4213,7 @@ MARVELL MV643XX ETHERNET DRIVER
M: Lennert Buytenhek <buytenh@wantstofly.org>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/mv643xx_eth.*
+F: drivers/net/ethernet/marvell/mv643xx_eth.*
F: include/linux/mv643xx.h
MARVELL MWIFIEX WIRELESS DRIVER
@@ -4236,7 +4312,7 @@ F: include/mtd/
MICROBLAZE ARCHITECTURE
M: Michal Simek <monstr@monstr.eu>
-L: microblaze-uclinux@itee.uq.edu.au
+L: microblaze-uclinux@itee.uq.edu.au (moderated for non-subscribers)
W: http://www.monstr.eu/fdt/
T: git git://git.monstr.eu/linux-2.6-microblaze.git
S: Supported
@@ -4351,12 +4427,12 @@ M: Andrew Gallatin <gallatin@myri.com>
L: netdev@vger.kernel.org
W: http://www.myri.com/scs/download-Myri10GE.html
S: Supported
-F: drivers/net/myri10ge/
+F: drivers/net/ethernet/myricom/myri10ge/
NATSEMI ETHERNET DRIVER (DP8381x)
M: Tim Hockin <thockin@hockin.org>
S: Maintained
-F: drivers/net/natsemi.c
+F: drivers/net/ethernet/natsemi/natsemi.c
NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER
M: Daniel Mack <zonque@gmail.com>
@@ -4396,9 +4472,8 @@ W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous
W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous
S: Supported
F: Documentation/networking/s2io.txt
-F: drivers/net/s2io*
F: Documentation/networking/vxge.txt
-F: drivers/net/vxge/
+F: drivers/net/ethernet/neterion/
NETFILTER/IPTABLES/IPCHAINS
P: Rusty Russell
@@ -4512,11 +4587,23 @@ F: include/linux/if_*
F: include/linux/*device.h
NETXEN (1/10) GbE SUPPORT
-M: Amit Kumar Salecha <amit.salecha@qlogic.com>
+M: Sony Chacko <sony.chacko@qlogic.com>
+M: Rajesh Borundia <rajesh.borundia@qlogic.com>
L: netdev@vger.kernel.org
W: http://www.qlogic.com
S: Supported
-F: drivers/net/netxen/
+F: drivers/net/ethernet/qlogic/netxen/
+
+NFC SUBSYSTEM
+M: Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+M: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+M: Samuel Ortiz <sameo@linux.intel.com>
+L: linux-wireless@vger.kernel.org
+S: Maintained
+F: net/nfc/
+F: include/linux/nfc.h
+F: include/net/nfc/
+F: drivers/nfc/
NFS, SUNRPC, AND LOCKD CLIENTS
M: Trond Myklebust <Trond.Myklebust@netapp.com>
@@ -4537,7 +4624,7 @@ M: Jan-Pascal van Best <janpascal@vanbest.org>
M: Andreas Mohr <andi@lisas.de>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/ni5010.*
+F: drivers/net/ethernet/racal/ni5010.*
NILFS2 FILESYSTEM
M: KONISHI Ryusuke <konishi.ryusuke@lab.ntt.co.jp>
@@ -4634,6 +4721,13 @@ S: Maintained
F: drivers/video/omap2/
F: Documentation/arm/OMAP/DSS
+OMAP HARDWARE SPINLOCK SUPPORT
+M: Ohad Ben-Cohen <ohad@wizery.com>
+L: linux-omap@vger.kernel.org
+S: Maintained
+F: drivers/hwspinlock/omap_hwspinlock.c
+F: arch/arm/mach-omap2/hwspinlock.c
+
OMAP MMC SUPPORT
M: Jarkko Lavinen <jarkko.lavinen@nokia.com>
L: linux-omap@vger.kernel.org
@@ -4728,10 +4822,12 @@ F: drivers/i2c/busses/i2c-ocores.c
OPEN FIRMWARE AND FLATTENED DEVICE TREE
M: Grant Likely <grant.likely@secretlab.ca>
+M: Rob Herring <rob.herring@calxeda.com>
L: devicetree-discuss@lists.ozlabs.org (moderated for non-subscribers)
W: http://fdt.secretlab.ca
T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
+F: Documentation/devicetree
F: drivers/of
F: include/linux/of*.h
K: of_get_property
@@ -4740,7 +4836,7 @@ K: of_match_table
OPENRISC ARCHITECTURE
M: Jonas Bonn <jonas@southpole.se>
W: http://openrisc.net
-L: linux@lists.openrisc.net
+L: linux@lists.openrisc.net (moderated for non-subscribers)
S: Maintained
T: git git://openrisc.net/~jonas/linux
F: arch/openrisc
@@ -4803,7 +4899,7 @@ PA SEMI ETHERNET DRIVER
M: Olof Johansson <olof@lixom.net>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/pasemi_mac.*
+F: drivers/net/ethernet/pasemi/*
PA SEMI SMBUS DRIVER
M: Olof Johansson <olof@lixom.net>
@@ -4914,7 +5010,7 @@ F: include/linux/i2c-algo-pca.h
F: include/linux/i2c-pca-platform.h
PCI ERROR RECOVERY
-M: Linas Vepstas <linas@austin.ibm.com>
+M: Linas Vepstas <linasvepstas@gmail.com>
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/PCI/pci-error-recovery.txt
@@ -4950,7 +5046,7 @@ PCNET32 NETWORK DRIVER
M: Don Fry <pcnet32@frontier.com>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/pcnet32.c
+F: drivers/net/ethernet/amd/pcnet32.c
PCRYPT PARALLEL CRYPTO ENGINE
M: Steffen Klassert <steffen.klassert@secunet.com>
@@ -5010,6 +5106,11 @@ L: linux-mtd@lists.infradead.org
S: Maintained
F: drivers/mtd/devices/phram.c
+PIN CONTROL SUBSYSTEM
+M: Linus Walleij <linus.walleij@linaro.org>
+S: Maintained
+F: drivers/pinmux/
+
PKTCDVD DRIVER
M: Peter Osterlund <petero2@telia.com>
S: Maintained
@@ -5082,7 +5183,7 @@ PPP PROTOCOL DRIVERS AND COMPRESSORS
M: Paul Mackerras <paulus@samba.org>
L: linux-ppp@vger.kernel.org
S: Maintained
-F: drivers/net/ppp_*
+F: drivers/net/ppp/ppp_*
PPP OVER ATM (RFC 2364)
M: Mitchell Blank Jr <mitch@sfgoth.com>
@@ -5093,8 +5194,8 @@ F: include/linux/atmppp.h
PPP OVER ETHERNET
M: Michal Ostrowski <mostrows@earthlink.net>
S: Maintained
-F: drivers/net/pppoe.c
-F: drivers/net/pppox.c
+F: drivers/net/ppp/pppoe.c
+F: drivers/net/ppp/pppox.c
PPP OVER L2TP
M: James Chapman <jchapman@katalix.com>
@@ -5115,7 +5216,7 @@ PPTP DRIVER
M: Dmitry Kozlov <xeb@mail.ru>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/pptp.c
+F: drivers/net/ppp/pptp.c
W: http://sourceforge.net/projects/accel-pptp
PREEMPTIBLE KERNEL
@@ -5144,7 +5245,7 @@ M: Geoff Levand <geoff@infradead.org>
L: netdev@vger.kernel.org
L: cbe-oss-dev@lists.ozlabs.org
S: Maintained
-F: drivers/net/ps3_gelic_net.*
+F: drivers/net/ethernet/toshiba/ps3_gelic_net.*
PS3 PLATFORM SUPPORT
M: Geoff Levand <geoff@infradead.org>
@@ -5262,23 +5363,24 @@ M: linux-driver@qlogic.com
L: netdev@vger.kernel.org
S: Supported
F: Documentation/networking/LICENSE.qla3xxx
-F: drivers/net/qla3xxx.*
+F: drivers/net/ethernet/qlogic/qla3xxx.*
QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
-M: Amit Kumar Salecha <amit.salecha@qlogic.com>
M: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
+M: Sony Chacko <sony.chacko@qlogic.com>
M: linux-driver@qlogic.com
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/qlcnic/
+F: drivers/net/ethernet/qlogic/qlcnic/
QLOGIC QLGE 10Gb ETHERNET DRIVER
+M: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
M: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
M: Ron Mercer <ron.mercer@qlogic.com>
M: linux-driver@qlogic.com
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/qlge/
+F: drivers/net/ethernet/qlogic/qlge/
QNX4 FILESYSTEM
M: Anders Larsen <al@alarsen.net>
@@ -5288,6 +5390,12 @@ F: fs/qnx4/
F: include/linux/qnx4_fs.h
F: include/linux/qnxtypes.h
+QUALCOMM HEXAGON ARCHITECTURE
+M: Richard Kuo <rkuo@codeaurora.org>
+L: linux-hexagon@vger.kernel.org
+S: Supported
+F: arch/hexagon/
+
RADOS BLOCK DEVICE (RBD)
F: include/linux/qnxtypes.h
M: Yehuda Sadeh <yehuda@hq.newdream.net>
@@ -5360,7 +5468,7 @@ RDC R6040 FAST ETHERNET DRIVER
M: Florian Fainelli <florian@openwrt.org>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/r6040.c
+F: drivers/net/ethernet/rdc/r6040.c
RDS - RELIABLE DATAGRAM SOCKETS
M: Andy Grover <andy.grover@oracle.com>
@@ -5764,7 +5872,7 @@ M: Ajit Khaparde <ajit.khaparde@emulex.com>
L: netdev@vger.kernel.org
W: http://www.emulex.com
S: Supported
-F: drivers/net/benet/
+F: drivers/net/ethernet/emulex/benet/
SFC NETWORK DRIVER
M: Solarflare linux maintainers <linux-net-drivers@solarflare.com>
@@ -5772,7 +5880,7 @@ M: Steve Hodgson <shodgson@solarflare.com>
M: Ben Hutchings <bhutchings@solarflare.com>
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/sfc/
+F: drivers/net/ethernet/sfc/
SGI GRU DRIVER
M: Jack Steiner <steiner@sgi.com>
@@ -5838,14 +5946,14 @@ SIS 190 ETHERNET DRIVER
M: Francois Romieu <romieu@fr.zoreil.com>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/sis190.c
+F: drivers/net/ethernet/sis/sis190.c
SIS 900/7016 FAST ETHERNET DRIVER
M: Daniele Venzano <venza@brownhat.org>
W: http://www.brownhat.org/sis900.html
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/sis900.*
+F: drivers/net/ethernet/sis/sis900.*
SIS 96X I2C/SMBUS DRIVER
M: "Mark M. Hoffman" <mhoffman@lightlink.com>
@@ -5872,8 +5980,7 @@ SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
M: Stephen Hemminger <shemminger@linux-foundation.org>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/skge.*
-F: drivers/net/sky2.*
+F: drivers/net/ethernet/marvell/sk*
SLAB ALLOCATOR
M: Christoph Lameter <cl@linux-foundation.org>
@@ -5887,7 +5994,7 @@ F: mm/sl?b.c
SMC91x ETHERNET DRIVER
M: Nicolas Pitre <nico@fluxnic.net>
S: Odd Fixes
-F: drivers/net/smc91x.*
+F: drivers/net/ethernet/smsc/smc91x.*
SMM665 HARDWARE MONITOR DRIVER
M: Guenter Roeck <linux@roeck-us.net>
@@ -5922,13 +6029,19 @@ M: Steve Glendinning <steve.glendinning@smsc.com>
L: netdev@vger.kernel.org
S: Supported
F: include/linux/smsc911x.h
-F: drivers/net/smsc911x.*
+F: drivers/net/ethernet/smsc/smsc911x.*
SMSC9420 PCI ETHERNET DRIVER
M: Steve Glendinning <steve.glendinning@smsc.com>
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/smsc9420.*
+F: drivers/net/ethernet/smsc/smsc9420.*
+
+SMSC UFX6000 and UFX7000 USB to VGA DRIVER
+M: Steve Glendinning <steve.glendinning@smsc.com>
+L: linux-fbdev@vger.kernel.org
+S: Supported
+F: drivers/video/smscufx.c
SN-IA64 (Itanium) SUB-PLATFORM
M: Jes Sorensen <jes@sgi.com>
@@ -5962,7 +6075,7 @@ SONIC NETWORK DRIVER
M: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/sonic.*
+F: drivers/net/ethernet/natsemi/sonic.*
SONICS SILICON BACKPLANE DRIVER (SSB)
M: Michael Buesch <m@bues.ch>
@@ -5999,7 +6112,7 @@ M: Jaroslav Kysela <perex@perex.cz>
M: Takashi Iwai <tiwai@suse.de>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://www.alsa-project.org/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
T: git git://git.alsa-project.org/alsa-kernel.git
S: Maintained
F: Documentation/sound/
@@ -6103,7 +6216,7 @@ M: Jens Osterkamp <jens@de.ibm.com>
L: netdev@vger.kernel.org
S: Supported
F: Documentation/networking/spider_net.txt
-F: drivers/net/spider_net*
+F: drivers/net/ethernet/toshiba/spider_net*
SPU FILE SYSTEM
M: Jeremy Kerr <jk@ozlabs.org>
@@ -6134,7 +6247,7 @@ S: Maintained
STAGING SUBSYSTEM
M: Greg Kroah-Hartman <gregkh@suse.de>
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
L: devel@driverdev.osuosl.org
S: Maintained
F: drivers/staging/
@@ -6150,12 +6263,6 @@ M: Jakub Schmidtke <sjakub@gmail.com>
S: Odd Fixes
F: drivers/staging/asus_oled/
-STAGING - ATHEROS ATH6KL WIRELESS DRIVER
-M: Luis R. Rodriguez <mcgrof@gmail.com>
-M: Naveen Singh <nsingh@atheros.com>
-S: Odd Fixes
-F: drivers/staging/ath6kl/
-
STAGING - COMEDI
M: Ian Abbott <abbotti@mev.co.uk>
M: Mori Hess <fmhess@users.sourceforge.net>
@@ -6181,6 +6288,11 @@ M: David Rowe <david@rowetel.com>
S: Odd Fixes
F: drivers/staging/echo/
+STAGING - ET131X NETWORK DRIVER
+M: Mark Einon <mark.einon@gmail.com>
+S: Odd Fixes
+F: drivers/staging/et131x/
+
STAGING - FLARION FT1000 DRIVERS
M: Marek Belisko <marek.belisko@gmail.com>
S: Odd Fixes
@@ -6209,6 +6321,13 @@ W: http://www.lirc.org/
S: Odd Fixes
F: drivers/staging/lirc/
+STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec)
+M: Julian Andres Klode <jak@jak-linux.org>
+M: Marc Dietrich <marvin24@gmx.de>
+L: ac100@lists.launchpad.net (moderated for non-subscribers)
+S: Maintained
+F: drivers/staging/nvec/
+
STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
M: Andres Salomon <dilinger@queued.net>
M: Chris Ball <cjb@laptop.org>
@@ -6281,7 +6400,7 @@ F: drivers/staging/xgifb/
STARFIRE/DURALAN NETWORK DRIVER
M: Ion Badulescu <ionut@badula.org>
S: Odd Fixes
-F: drivers/net/starfire*
+F: drivers/net/ethernet/adaptec/starfire*
SUN3/3X
M: Sam Creasey <sammy@sammy.net>
@@ -6290,6 +6409,7 @@ S: Maintained
F: arch/m68k/kernel/*sun3*
F: arch/m68k/sun3*/
F: arch/m68k/include/asm/sun3*
+F: drivers/net/ethernet/i825xx/sun3*
SUPERH
M: Paul Mundt <lethal@linux-sh.org>
@@ -6306,7 +6426,7 @@ SUSPEND TO RAM
M: Len Brown <len.brown@intel.com>
M: Pavel Machek <pavel@ucw.cz>
M: "Rafael J. Wysocki" <rjw@sisk.pl>
-L: linux-pm@lists.linux-foundation.org
+L: linux-pm@vger.kernel.org
S: Supported
F: Documentation/power/
F: arch/x86/kernel/acpi/
@@ -6377,7 +6497,7 @@ TEHUTI ETHERNET DRIVER
M: Andy Gospodarek <andy@greyhouse.net>
L: netdev@vger.kernel.org
S: Supported
-F: drivers/net/tehuti*
+F: drivers/net/ethernet/tehuti/*
Telecom Clock Driver for MCPL0010
M: Mark Gross <mark.gross@intel.com>
@@ -6428,7 +6548,7 @@ W: http://www.tilera.com/scm/
S: Supported
F: arch/tile/
F: drivers/tty/hvc/hvc_tile.c
-F: drivers/net/tile/
+F: drivers/net/ethernet/tile/
F: drivers/edac/tile_edac.c
TLAN NETWORK DRIVER
@@ -6437,7 +6557,7 @@ L: tlan-devel@lists.sourceforge.net (subscribers-only)
W: http://sourceforge.net/projects/tlan/
S: Maintained
F: Documentation/networking/tlan.txt
-F: drivers/net/tlan.*
+F: drivers/net/ethernet/ti/tlan.*
TOMOYO SECURITY MODULE
M: Kentaro Takeda <takedakn@nttdata.co.jp>
@@ -6447,7 +6567,7 @@ L: tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for users in English)
L: tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese)
L: tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese)
W: http://tomoyo.sourceforge.jp/
-T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.4.x/tomoyo-lsm/patches/
+T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.5.x/tomoyo-lsm/patches/
S: Maintained
F: security/tomoyo/
@@ -6531,7 +6651,7 @@ TULIP NETWORK DRIVERS
M: Grant Grundler <grundler@parisc-linux.org>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/tulip/
+F: drivers/net/ethernet/tulip/
TUN/TAP driver
M: Maxim Krasnyansky <maxk@qualcomm.com>
@@ -6577,11 +6697,10 @@ W: http://uclinux-h8.sourceforge.jp/
S: Supported
F: arch/h8300/
F: drivers/ide/ide-h8300.c
-F: drivers/net/ne-h8300.c
+F: drivers/net/ethernet/8390/ne-h8300.c
UDF FILESYSTEM
M: Jan Kara <jack@suse.cz>
-W: http://linux-udf.sourceforge.net
S: Maintained
F: Documentation/filesystems/udf.txt
F: fs/udf/
@@ -7005,7 +7124,7 @@ F: include/linux/vhost.h
VIA RHINE NETWORK DRIVER
M: Roger Luethi <rl@hellgate.ch>
S: Maintained
-F: drivers/net/via-rhine.c
+F: drivers/net/ethernet/via/via-rhine.c
VIAPRO SMBUS DRIVER
M: Jean Delvare <khali@linux-fr.org>
@@ -7033,7 +7152,7 @@ VIA VELOCITY NETWORK DRIVER
M: Francois Romieu <romieu@fr.zoreil.com>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/via-velocity.*
+F: drivers/net/ethernet/via/via-velocity.*
VLAN (802.1Q)
M: Patrick McHardy <kaber@trash.net>
@@ -7142,6 +7261,12 @@ L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/scsi/wd7000.c
+WIIMOTE HID DRIVER
+M: David Herrmann <dh.herrmann@googlemail.com>
+L: linux-input@vger.kernel.org
+S: Maintained
+F: drivers/hid/hid-wiimote*
+
WINBOND CIR DRIVER
M: David Härdeman <david@hardeman.nu>
S: Maintained
@@ -7207,6 +7332,7 @@ T: git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
W: http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
S: Supported
F: Documentation/hwmon/wm83??
+F: arch/arm/mach-s3c64xx/mach-crag6410*
F: drivers/leds/leds-wm83*.c
F: drivers/input/misc/wm831x-on.c
F: drivers/input/touchscreen/wm831x-ts.c
diff --git a/arch/alpha/include/asm/fcntl.h b/arch/alpha/include/asm/fcntl.h
index 1b71ca70c9f6..6d9e805f18a7 100644
--- a/arch/alpha/include/asm/fcntl.h
+++ b/arch/alpha/include/asm/fcntl.h
@@ -51,8 +51,6 @@
#define F_EXLCK 16 /* or 3 */
#define F_SHLCK 32 /* or 4 */
-#define F_INPROGRESS 64
-
#include <asm-generic/fcntl.h>
#endif
diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h
index 4ac48a095f3a..2207fc61665d 100644
--- a/arch/alpha/include/asm/unistd.h
+++ b/arch/alpha/include/asm/unistd.h
@@ -457,10 +457,12 @@
#define __NR_clock_adjtime 499
#define __NR_syncfs 500
#define __NR_setns 501
+#define __NR_accept4 502
+#define __NR_sendmmsg 503
#ifdef __KERNEL__
-#define NR_SYSCALLS 502
+#define NR_SYSCALLS 504
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c
index f0df3fbd8402..b9fc6c309d2e 100644
--- a/arch/alpha/kernel/srm_env.c
+++ b/arch/alpha/kernel/srm_env.c
@@ -4,9 +4,8 @@
*
* (C) 2001,2002,2006 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
*
- * This driver is at all a modified version of Erik Mouw's
- * Documentation/DocBook/procfs_example.c, so: thank
- * you, Erik! He can be reached via email at
+ * This driver is a modified version of Erik Mouw's example proc
+ * interface, so: thank you, Erik! He can be reached via email at
* <J.A.K.Mouw@its.tudelft.nl>. It is based on an idea
* provided by DEC^WCompaq^WIntel's "Jumpstart" CD. They
* included a patch like this as well. Thanks for idea!
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index 6acea1f96de3..e534e1c5bc11 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -520,6 +520,8 @@ sys_call_table:
.quad sys_clock_adjtime
.quad sys_syncfs /* 500 */
.quad sys_setns
+ .quad sys_accept4
+ .quad sys_sendmmsg
.size sys_call_table, . - sys_call_table
.type sys_call_table, @object
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3146ed3f6eca..fe6b0526b3a6 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -3,7 +3,7 @@ config ARM
default y
select HAVE_AOUT
select HAVE_DMA_API_DEBUG
- select HAVE_IDE
+ select HAVE_IDE if PCI || ISA || PCMCIA
select HAVE_MEMBLOCK
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
@@ -29,6 +29,7 @@ config ARM
select HAVE_GENERIC_HARDIRQS
select HAVE_SPARSE_IRQ
select GENERIC_IRQ_SHOW
+ select CPU_PM if (SUSPEND || CPU_IDLE)
help
The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and
@@ -195,7 +196,8 @@ config VECTORS_BASE
The base address of exception vectors.
config ARM_PATCH_PHYS_VIRT
- bool "Patch physical to virtual translations at runtime"
+ bool "Patch physical to virtual translations at runtime" if EMBEDDED
+ default y
depends on !XIP_KERNEL && MMU
depends on !ARCH_REALVIEW || !SPARSEMEM
help
@@ -204,16 +206,29 @@ config ARM_PATCH_PHYS_VIRT
kernel in system memory.
This can only be used with non-XIP MMU kernels where the base
- of physical memory is at a 16MB boundary, or theoretically 64K
- for the MSM machine class.
+ of physical memory is at a 16MB boundary.
-config ARM_PATCH_PHYS_VIRT_16BIT
- def_bool y
- depends on ARM_PATCH_PHYS_VIRT && ARCH_MSM
+ Only disable this option if you know that you do not require
+ this feature (eg, building a kernel for a single machine) and
+ you need to shrink the kernel to the minimal size.
+
+config NEED_MACH_MEMORY_H
+ bool
+ help
+ Select this when mach/memory.h is required to provide special
+ definitions for this platform. The need for mach/memory.h should
+ be avoided when possible.
+
+config PHYS_OFFSET
+ hex "Physical address of main memory"
+ depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H
help
- This option extends the physical to virtual translation patching
- to allow physical memory down to a theoretical minimum of 64K
- boundaries.
+ Please provide the physical address corresponding to the
+ location of main memory in your system.
+
+config GENERIC_BUG
+ def_bool y
+ depends on BUG
source "init/Kconfig"
@@ -246,6 +261,7 @@ config ARCH_INTEGRATOR
select GENERIC_CLOCKEVENTS
select PLAT_VERSATILE
select PLAT_VERSATILE_FPGA_IRQ
+ select NEED_MACH_MEMORY_H
help
Support for ARM's Integrator platform.
@@ -261,6 +277,7 @@ config ARCH_REALVIEW
select PLAT_VERSATILE_CLCD
select ARM_TIMER_SP804
select GPIO_PL061 if GPIOLIB
+ select NEED_MACH_MEMORY_H
help
This enables support for ARM Ltd RealView boards.
@@ -301,7 +318,6 @@ config ARCH_AT91
select ARCH_REQUIRE_GPIOLIB
select HAVE_CLK
select CLKDEV_LOOKUP
- select ARM_PATCH_PHYS_VIRT if MMU
help
This enables support for systems based on the Atmel AT91RM9200,
AT91SAM9 and AT91CAP9 processors.
@@ -318,10 +334,25 @@ config ARCH_BCMRING
help
Support for Broadcom's BCMRing platform.
+config ARCH_HIGHBANK
+ bool "Calxeda Highbank-based"
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+ select ARM_AMBA
+ select ARM_GIC
+ select ARM_TIMER_SP804
+ select CLKDEV_LOOKUP
+ select CPU_V7
+ select GENERIC_CLOCKEVENTS
+ select HAVE_ARM_SCU
+ select USE_OF
+ help
+ Support for the Calxeda Highbank SoC based boards.
+
config ARCH_CLPS711X
bool "Cirrus Logic CLPS711x/EP721x-based"
select CPU_ARM720T
select ARCH_USES_GETTIMEOFFSET
+ select NEED_MACH_MEMORY_H
help
Support for Cirrus Logic 711x/721x based boards.
@@ -346,7 +377,6 @@ config ARCH_GEMINI
config ARCH_PRIMA2
bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
select CPU_V7
- select GENERIC_TIME
select NO_IOPORT
select GENERIC_CLOCKEVENTS
select CLKDEV_LOOKUP
@@ -362,6 +392,7 @@ config ARCH_EBSA110
select ISA
select NO_IOPORT
select ARCH_USES_GETTIMEOFFSET
+ select NEED_MACH_MEMORY_H
help
This is an evaluation board for the StrongARM processor available
from Digital. It has limited hardware on-board, including an
@@ -377,6 +408,7 @@ config ARCH_EP93XX
select ARCH_REQUIRE_GPIOLIB
select ARCH_HAS_HOLES_MEMORYMODEL
select ARCH_USES_GETTIMEOFFSET
+ select NEED_MACH_MEMORY_H
help
This enables support for the Cirrus EP93xx series of CPUs.
@@ -385,6 +417,8 @@ config ARCH_FOOTBRIDGE
select CPU_SA110
select FOOTBRIDGE
select GENERIC_CLOCKEVENTS
+ select HAVE_IDE
+ select NEED_MACH_MEMORY_H
help
Support for systems based on the DC21285 companion chip
("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
@@ -397,6 +431,7 @@ config ARCH_MXC
select CLKSRC_MMIO
select GENERIC_IRQ_CHIP
select HAVE_SCHED_CLOCK
+ select MULTI_IRQ_HANDLER
help
Support for Freescale MXC/iMX-based family of processors
@@ -434,6 +469,7 @@ config ARCH_IOP13XX
select PCI
select ARCH_SUPPORTS_MSI
select VMSPLIT_1G
+ select NEED_MACH_MEMORY_H
help
Support for Intel's IOP13XX (XScale) family of processors.
@@ -464,6 +500,7 @@ config ARCH_IXP23XX
select CPU_XSC3
select PCI
select ARCH_USES_GETTIMEOFFSET
+ select NEED_MACH_MEMORY_H
help
Support for Intel's IXP23xx (XScale) family of processors.
@@ -473,6 +510,7 @@ config ARCH_IXP2000
select CPU_XSCALE
select PCI
select ARCH_USES_GETTIMEOFFSET
+ select NEED_MACH_MEMORY_H
help
Support for Intel's IXP2400/2800 (XScale) family of processors.
@@ -519,7 +557,6 @@ config ARCH_LPC32XX
select ARM_AMBA
select USB_ARCH_HAS_OHCI
select CLKDEV_LOOKUP
- select GENERIC_TIME
select GENERIC_CLOCKEVENTS
help
Support for the NXP LPC32XX family of processors
@@ -566,6 +603,7 @@ config ARCH_KS8695
select CPU_ARM922T
select ARCH_REQUIRE_GPIOLIB
select ARCH_USES_GETTIMEOFFSET
+ select NEED_MACH_MEMORY_H
help
Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
System-on-Chip devices.
@@ -586,19 +624,10 @@ config ARCH_W90X900
<http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/
ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller>
-config ARCH_NUC93X
- bool "Nuvoton NUC93X CPU"
- select CPU_ARM926T
- select CLKDEV_LOOKUP
- help
- Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
- low-power and high performance MPEG-4/JPEG multimedia controller chip.
-
config ARCH_TEGRA
bool "NVIDIA Tegra"
select CLKDEV_LOOKUP
select CLKSRC_MMIO
- select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select GENERIC_GPIO
select HAVE_CLK
@@ -608,6 +637,24 @@ config ARCH_TEGRA
This enables support for NVIDIA Tegra based systems (Tegra APX,
Tegra 6xx and Tegra 2 series).
+config ARCH_PICOXCELL
+ bool "Picochip picoXcell"
+ select ARCH_REQUIRE_GPIOLIB
+ select ARM_PATCH_PHYS_VIRT
+ select ARM_VIC
+ select CPU_V6K
+ select DW_APB_TIMER
+ select GENERIC_CLOCKEVENTS
+ select GENERIC_GPIO
+ select HAVE_SCHED_CLOCK
+ select HAVE_TCM
+ select NO_IOPORT
+ select USE_OF
+ help
+ This enables support for systems based on the Picochip picoXcell
+ family of Femtocell devices. The picoxcell support requires device tree
+ for all boards.
+
config ARCH_PNX4008
bool "Philips Nexperia PNX4008 Mobile"
select CPU_ARM926T
@@ -631,6 +678,8 @@ config ARCH_PXA
select SPARSE_IRQ
select AUTO_ZRELADDR
select MULTI_IRQ_HANDLER
+ select ARM_CPU_SUSPEND if PM
+ select HAVE_IDE
help
Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
@@ -657,6 +706,7 @@ config ARCH_SHMOBILE
select SPARSE_IRQ
select MULTI_IRQ_HANDLER
select PM_GENERIC_DOMAINS if PM
+ select NEED_MACH_MEMORY_H
help
Support for Renesas's SH-Mobile and R-Mobile ARM platforms.
@@ -671,6 +721,8 @@ config ARCH_RPC
select NO_IOPORT
select ARCH_SPARSEMEM_ENABLE
select ARCH_USES_GETTIMEOFFSET
+ select HAVE_IDE
+ select NEED_MACH_MEMORY_H
help
On the Acorn Risc-PC, Linux can support the internal IDE disk and
CD-ROM interface, serial and parallel port, and the floppy drive.
@@ -689,6 +741,8 @@ config ARCH_SA1100
select HAVE_SCHED_CLOCK
select TICK_ONESHOT
select ARCH_REQUIRE_GPIOLIB
+ select HAVE_IDE
+ select NEED_MACH_MEMORY_H
help
Support for StrongARM 11x0 based boards.
@@ -722,7 +776,6 @@ config ARCH_S3C64XX
select ARCH_REQUIRE_GPIOLIB
select SAMSUNG_CLKSRC
select SAMSUNG_IRQ_VIC_TIMER
- select SAMSUNG_IRQ_UART
select S3C_GPIO_TRACK
select S3C_GPIO_PULL_UPDOWN
select S3C_GPIO_CFG_S3C24XX
@@ -781,6 +834,7 @@ config ARCH_S5PV210
select HAVE_S3C2410_I2C if I2C
select HAVE_S3C_RTC if RTC_CLASS
select HAVE_S3C2410_WATCHDOG if WATCHDOG
+ select NEED_MACH_MEMORY_H
help
Samsung S5PV210/S5PC110 series based systems
@@ -797,6 +851,7 @@ config ARCH_EXYNOS4
select HAVE_S3C_RTC if RTC_CLASS
select HAVE_S3C2410_I2C if I2C
select HAVE_S3C2410_WATCHDOG if WATCHDOG
+ select NEED_MACH_MEMORY_H
help
Samsung EXYNOS4 series based systems
@@ -808,6 +863,7 @@ config ARCH_SHARK
select ZONE_DMA
select PCI
select ARCH_USES_GETTIMEOFFSET
+ select NEED_MACH_MEMORY_H
help
Support for the StrongARM based Digital DNARD machine, also known
as "Shark" (<http://www.shark-linux.de/shark.html>).
@@ -830,11 +886,14 @@ config ARCH_U300
select HAVE_SCHED_CLOCK
select HAVE_TCM
select ARM_AMBA
+ select ARM_PATCH_PHYS_VIRT
select ARM_VIC
select GENERIC_CLOCKEVENTS
select CLKDEV_LOOKUP
select HAVE_MACH_CLKDEV
select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ select NEED_MACH_MEMORY_H
help
Support for ST-Ericsson U300 series mobile platforms.
@@ -910,7 +969,6 @@ config ARCH_VT8500
config ARCH_ZYNQ
bool "Xilinx Zynq ARM Cortex A9 Platform"
select CPU_V7
- select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select CLKDEV_LOOKUP
select ARM_GIC
@@ -979,8 +1037,6 @@ source "arch/arm/mach-netx/Kconfig"
source "arch/arm/mach-nomadik/Kconfig"
source "arch/arm/plat-nomadik/Kconfig"
-source "arch/arm/mach-nuc93x/Kconfig"
-
source "arch/arm/plat-omap/Kconfig"
source "arch/arm/mach-omap1/Kconfig"
@@ -1374,7 +1430,8 @@ config SMP
depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
- ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE
+ ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_HIGHBANK || SOC_IMX6Q
+ depends on MMU
select USE_GENERIC_SMP_HELPERS
select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
help
@@ -1388,7 +1445,7 @@ config SMP
processor machines. On a single processor machine, the kernel will
run faster if you say N here.
- See also <file:Documentation/i386/IO-APIC.txt>,
+ See also <file:Documentation/x86/i386/IO-APIC.txt>,
<file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
<http://tldp.org/HOWTO/SMP-HOWTO.html>.
@@ -1407,6 +1464,31 @@ config SMP_ON_UP
If you don't know what to do here, say Y.
+config ARM_CPU_TOPOLOGY
+ bool "Support cpu topology definition"
+ depends on SMP && CPU_V7
+ default y
+ help
+ Support ARM cpu topology definition. The MPIDR register defines
+ affinity between processors which is then used to describe the cpu
+ topology of an ARM System.
+
+config SCHED_MC
+ bool "Multi-core scheduler support"
+ depends on ARM_CPU_TOPOLOGY
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+ making when dealing with multi-core CPU chips at a cost of slightly
+ increased overhead in some places. If unsure say N here.
+
+config SCHED_SMT
+ bool "SMT scheduler support"
+ depends on ARM_CPU_TOPOLOGY
+ help
+ Improves the CPU scheduler's decision making when dealing with
+ MultiThreading at a cost of slightly increased overhead in some
+ places. If unsure say N here.
+
config HAVE_ARM_SCU
bool
help
@@ -1482,6 +1564,7 @@ config THUMB2_KERNEL
depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
select AEABI
select ARM_ASM_UNIFIED
+ select ARM_UNWIND
help
By enabling this option, the kernel will be compiled in
Thumb-2 mode. A compiler/assembler that understand the unified
@@ -1807,6 +1890,38 @@ config ZBOOT_ROM_SH_MOBILE_SDHI
endchoice
+config ARM_APPENDED_DTB
+ bool "Use appended device tree blob to zImage (EXPERIMENTAL)"
+ depends on OF && !ZBOOT_ROM && EXPERIMENTAL
+ help
+ With this option, the boot code will look for a device tree binary
+ (DTB) appended to zImage
+ (e.g. cat zImage <filename>.dtb > zImage_w_dtb).
+
+ This is meant as a backward compatibility convenience for those
+ systems with a bootloader that can't be upgraded to accommodate
+ the documented boot protocol using a device tree.
+
+ Beware that there is very little in terms of protection against
+ this option being confused by leftover garbage in memory that might
+ look like a DTB header after a reboot if no actual DTB is appended
+ to zImage. Do not leave this option active in a production kernel
+ if you don't intend to always append a DTB. Proper passing of the
+ location into r2 of a bootloader provided DTB is always preferable
+ to this option.
+
+config ARM_ATAG_DTB_COMPAT
+ bool "Supplement the appended DTB with traditional ATAG information"
+ depends on ARM_APPENDED_DTB
+ help
+ Some old bootloaders can't be updated to a DTB capable one, yet
+ they provide ATAGs with memory configuration, the ramdisk address,
+ the kernel cmdline string, etc. Such information is dynamically
+ provided by the bootloader and can't always be stored in a static
+ DTB. To allow a device tree enabled kernel to be used with such
+ bootloaders, this option allows zImage to extract the information
+ from the ATAG list and store it at run time into the appended DTB.
+
config CMDLINE
string "Default kernel command string"
default ""
@@ -1953,6 +2068,7 @@ config CPU_FREQ_PXA
bool
depends on CPU_FREQ && ARCH_PXA && PXA25x
default y
+ select CPU_FREQ_TABLE
select CPU_FREQ_DEFAULT_GOV_USERSPACE
config CPU_FREQ_S3C
@@ -2101,6 +2217,9 @@ config ARCH_SUSPEND_POSSIBLE
CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
def_bool y
+config ARM_CPU_SUSPEND
+ def_bool PM_SLEEP
+
endmenu
source "net/Kconfig"
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 81cbe40c159c..c5213e78606b 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -65,13 +65,190 @@ config DEBUG_USER
# These options are only for real kernel hackers who want to get their hands dirty.
config DEBUG_LL
- bool "Kernel low-level debugging functions"
+ bool "Kernel low-level debugging functions (read help!)"
depends on DEBUG_KERNEL
help
Say Y here to include definitions of printascii, printch, printhex
in the kernel. This is helpful if you are debugging code that
executes before the console is initialized.
+ Note that selecting this option will limit the kernel to a single
+ UART definition, as specified below. Attempting to boot the kernel
+ image on a different platform *will not work*, so this option should
+ not be enabled for kernels that are intended to be portable.
+
+choice
+ prompt "Kernel low-level debugging port"
+ depends on DEBUG_LL
+
+ config DEBUG_LL_UART_NONE
+ bool "No low-level debugging UART"
+ help
+ Say Y here if your platform doesn't provide a UART option
+ below. This relies on your platform choosing the right UART
+ definition internally in order for low-level debugging to
+ work.
+
+ config DEBUG_ICEDCC
+ bool "Kernel low-level debugging via EmbeddedICE DCC channel"
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the EmbeddedICE macrocell's DCC channel using
+ co-processor 14. This is known to work on the ARM9 style ICE
+ channel and on the XScale with the PEEDI.
+
+ Note that the system will appear to hang during boot if there
+ is nothing connected to read from the DCC.
+
+ config DEBUG_FOOTBRIDGE_COM1
+ bool "Kernel low-level debugging messages via footbridge 8250 at PCI COM1"
+ depends on FOOTBRIDGE
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the 8250 at PCI COM1.
+
+ config DEBUG_DC21285_PORT
+ bool "Kernel low-level debugging messages via footbridge serial port"
+ depends on FOOTBRIDGE
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the serial port in the DC21285 (Footbridge).
+
+ config DEBUG_CLPS711X_UART1
+ bool "Kernel low-level debugging messages via UART1"
+ depends on ARCH_CLPS711X
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the first serial port on these devices.
+
+ config DEBUG_CLPS711X_UART2
+ bool "Kernel low-level debugging messages via UART2"
+ depends on ARCH_CLPS711X
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the second serial port on these devices.
+
+ config DEBUG_HIGHBANK_UART
+ bool "Kernel low-level debugging messages via Highbank UART"
+ depends on ARCH_HIGHBANK
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the UART on Highbank based devices.
+
+ config DEBUG_IMX1_UART
+ bool "i.MX1 Debug UART"
+ depends on SOC_IMX1
+ help
+ Say Y here if you want kernel low-level debugging support
+ on i.MX1.
+
+ config DEBUG_IMX23_UART
+ bool "i.MX23 Debug UART"
+ depends on SOC_IMX23
+ help
+ Say Y here if you want kernel low-level debugging support
+ on i.MX23.
+
+ config DEBUG_IMX25_UART
+ bool "i.MX25 Debug UART"
+ depends on SOC_IMX25
+ help
+ Say Y here if you want kernel low-level debugging support
+ on i.MX25.
+
+ config DEBUG_IMX21_IMX27_UART
+ bool "i.MX21 and i.MX27 Debug UART"
+ depends on SOC_IMX21 || SOC_IMX27
+ help
+ Say Y here if you want kernel low-level debugging support
+ on i.MX21 or i.MX27.
+
+ config DEBUG_IMX28_UART
+ bool "i.MX28 Debug UART"
+ depends on SOC_IMX28
+ help
+ Say Y here if you want kernel low-level debugging support
+ on i.MX28.
+
+ config DEBUG_IMX31_IMX35_UART
+ bool "i.MX31 and i.MX35 Debug UART"
+ depends on SOC_IMX31 || SOC_IMX35
+ help
+ Say Y here if you want kernel low-level debugging support
+ on i.MX31 or i.MX35.
+
+ config DEBUG_IMX51_UART
+ bool "i.MX51 Debug UART"
+ depends on SOC_IMX51
+ help
+ Say Y here if you want kernel low-level debugging support
+ on i.MX51.
+
+ config DEBUG_IMX50_IMX53_UART
+ bool "i.MX50 and i.MX53 Debug UART"
+ depends on SOC_IMX50 || SOC_IMX53
+ help
+ Say Y here if you want kernel low-level debugging support
+ on i.MX50 or i.MX53.
+
+ 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.
+
+ config DEBUG_S3C_UART0
+ depends on PLAT_SAMSUNG
+ bool "Use S3C UART 0 for low-level debug"
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to UART 0. The port must have been initialised
+ by the boot-loader before use.
+
+ The uncompressor code port configuration is now handled
+ by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+ config DEBUG_S3C_UART1
+ depends on PLAT_SAMSUNG
+ bool "Use S3C UART 1 for low-level debug"
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to UART 1. The port must have been initialised
+ by the boot-loader before use.
+
+ The uncompressor code port configuration is now handled
+ by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+ config DEBUG_S3C_UART2
+ depends on PLAT_SAMSUNG
+ bool "Use S3C UART 2 for low-level debug"
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to UART 2. The port must have been initialised
+ by the boot-loader before use.
+
+ The uncompressor code port configuration is now handled
+ by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+ config DEBUG_REALVIEW_STD_PORT
+ bool "RealView Default UART"
+ depends on ARCH_REALVIEW
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the serial port on RealView EB, PB11MP, PBA8
+ and PBX platforms.
+
+ config DEBUG_REALVIEW_PB1176_PORT
+ bool "RealView PB1176 UART"
+ depends on MACH_REALVIEW_PB1176
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the standard serial port on the RealView
+ PB1176 platform.
+
+endchoice
+
config EARLY_PRINTK
bool "Early printk"
depends on DEBUG_LL
@@ -80,53 +257,18 @@ config EARLY_PRINTK
kernel low-level debugging functions. Add earlyprintk to your
kernel parameters to enable this console.
-config DEBUG_ICEDCC
- bool "Kernel low-level debugging via EmbeddedICE DCC channel"
- depends on DEBUG_LL
- help
- Say Y here if you want the debug print routines to direct their
- output to the EmbeddedICE macrocell's DCC channel using
- co-processor 14. This is known to work on the ARM9 style ICE
- channel and on the XScale with the PEEDI.
-
- It does include a timeout to ensure that the system does not
- totally freeze when there is nothing connected to read.
-
config OC_ETM
bool "On-chip ETM and ETB"
- select ARM_AMBA
+ depends on ARM_AMBA
help
Enables the on-chip embedded trace macrocell and embedded trace
buffer driver that will allow you to collect traces of the
kernel code.
-config DEBUG_DC21285_PORT
- bool "Kernel low-level debugging messages via footbridge serial port"
- depends on DEBUG_LL && FOOTBRIDGE
- help
- Say Y here if you want the debug print routines to direct their
- output to the serial port in the DC21285 (Footbridge). Saying N
- will cause the debug messages to appear on the first 16550
- serial port.
-
-config DEBUG_CLPS711X_UART2
- bool "Kernel low-level debugging messages via UART2"
- depends on DEBUG_LL && ARCH_CLPS711X
+config ARM_KPROBES_TEST
+ tristate "Kprobes test module"
+ depends on KPROBES && MODULES
help
- Say Y here if you want the debug print routines to direct their
- output to the second serial port on these devices. Saying N will
- cause the debug messages to appear on the first serial port.
-
-config DEBUG_S3C_UART
- depends on PLAT_SAMSUNG
- int "S3C UART to use for low-level debug"
- default "0"
- help
- Choice for UART for kernel low-level using S3C UARTS,
- should be between zero and two. The port must have been
- initialised by the boot-loader before use.
-
- The uncompressor code port configuration is now handled
- by CONFIG_S3C_LOWLEVEL_UART_PORT.
+ Perform tests of kprobes API and instruction set simulation.
endmenu
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 70c424eaf7b0..b7c2d377a6c2 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -128,6 +128,9 @@ textofs-$(CONFIG_PM_H1940) := 0x00108000
ifeq ($(CONFIG_ARCH_SA1100),y)
textofs-$(CONFIG_SA1111) := 0x00208000
endif
+textofs-$(CONFIG_ARCH_MSM7X30) := 0x00208000
+textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000
+textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
# Machine directory name. This list is sorted alphanumerically
# by CONFIG_* macro name.
@@ -141,6 +144,7 @@ machine-$(CONFIG_ARCH_EBSA110) := ebsa110
machine-$(CONFIG_ARCH_EP93XX) := ep93xx
machine-$(CONFIG_ARCH_GEMINI) := gemini
machine-$(CONFIG_ARCH_H720X) := h720x
+machine-$(CONFIG_ARCH_HIGHBANK) := highbank
machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
machine-$(CONFIG_ARCH_IOP13XX) := iop13xx
machine-$(CONFIG_ARCH_IOP32X) := iop32x
@@ -154,10 +158,8 @@ machine-$(CONFIG_ARCH_LPC32XX) := lpc32xx
machine-$(CONFIG_ARCH_MMP) := mmp
machine-$(CONFIG_ARCH_MSM) := msm
machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0
-machine-$(CONFIG_ARCH_MX1) := imx
-machine-$(CONFIG_ARCH_MX2) := imx
-machine-$(CONFIG_ARCH_MX25) := imx
-machine-$(CONFIG_ARCH_MX3) := imx
+machine-$(CONFIG_ARCH_IMX_V4_V5) := imx
+machine-$(CONFIG_ARCH_IMX_V6_V7) := imx
machine-$(CONFIG_ARCH_MX5) := mx5
machine-$(CONFIG_ARCH_MXS) := mxs
machine-$(CONFIG_ARCH_NETX) := netx
@@ -167,6 +169,7 @@ machine-$(CONFIG_ARCH_OMAP2) := omap2
machine-$(CONFIG_ARCH_OMAP3) := omap2
machine-$(CONFIG_ARCH_OMAP4) := omap2
machine-$(CONFIG_ARCH_ORION5X) := orion5x
+machine-$(CONFIG_ARCH_PICOXCELL) := picoxcell
machine-$(CONFIG_ARCH_PNX4008) := pnx4008
machine-$(CONFIG_ARCH_PRIMA2) := prima2
machine-$(CONFIG_ARCH_PXA) := pxa
@@ -189,7 +192,6 @@ machine-$(CONFIG_ARCH_VERSATILE) := versatile
machine-$(CONFIG_ARCH_VEXPRESS) := vexpress
machine-$(CONFIG_ARCH_VT8500) := vt8500
machine-$(CONFIG_ARCH_W90X900) := w90x900
-machine-$(CONFIG_ARCH_NUC93X) := nuc93x
machine-$(CONFIG_FOOTBRIDGE) := footbridge
machine-$(CONFIG_MACH_SPEAR300) := spear3xx
machine-$(CONFIG_MACH_SPEAR310) := spear3xx
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index a1edfd5a129a..176062ac7f07 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -78,7 +78,16 @@ endif
$(obj)/uImage: STARTADDR=$(LOADADDR)
+check_for_multiple_loadaddr = \
+if [ $(words $(LOADADDR)) -gt 1 ]; then \
+ echo 'multiple load addresses: $(LOADADDR)'; \
+ echo 'This is incompatible with uImages'; \
+ echo 'Specify LOADADDR on the commandline to build an uImage'; \
+ false; \
+fi
+
$(obj)/uImage: $(obj)/zImage FORCE
+ @$(check_for_multiple_loadaddr)
$(call if_changed,uimage)
@echo ' Image $@ is ready'
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
index c6028967d336..e0936a148516 100644
--- a/arch/arm/boot/compressed/.gitignore
+++ b/arch/arm/boot/compressed/.gitignore
@@ -5,3 +5,12 @@ piggy.lzo
piggy.lzma
vmlinux
vmlinux.lds
+
+# borrowed libfdt files
+fdt.c
+fdt.h
+fdt_ro.c
+fdt_rw.c
+fdt_wip.c
+libfdt.h
+libfdt_internal.h
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 0c74a6fab952..21f56ff32797 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -26,6 +26,10 @@ HEAD = head.o
OBJS += misc.o decompress.o
FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
+# string library code (-Os is enforced to keep it much smaller)
+OBJS += string.o
+CFLAGS_string.o := -Os
+
#
# Architecture dependencies
#
@@ -89,21 +93,41 @@ suffix_$(CONFIG_KERNEL_GZIP) = gzip
suffix_$(CONFIG_KERNEL_LZO) = lzo
suffix_$(CONFIG_KERNEL_LZMA) = lzma
+# Borrowed libfdt files for the ATAG compatibility mode
+
+libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c
+libfdt_hdrs := fdt.h libfdt.h libfdt_internal.h
+
+libfdt_objs := $(addsuffix .o, $(basename $(libfdt)))
+
+$(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/%
+ $(call cmd,shipped)
+
+$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
+ $(addprefix $(obj)/,$(libfdt_hdrs))
+
+ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
+OBJS += $(libfdt_objs) atags_to_fdt.o
+endif
+
targets := vmlinux vmlinux.lds \
piggy.$(suffix_y) piggy.$(suffix_y).o \
- font.o font.c head.o misc.o $(OBJS)
+ lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS)
# Make sure files are removed during clean
-extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S
+extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
ifeq ($(CONFIG_FUNCTION_TRACER),y)
ORIG_CFLAGS := $(KBUILD_CFLAGS)
KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
endif
-ccflags-y := -fpic -fno-builtin
+ccflags-y := -fpic -fno-builtin -I$(obj)
asflags-y := -Wa,-march=all
+# Supply kernel BSS size to the decompressor via a linker symbol.
+KBSS_SZ = $(shell size $(obj)/../../../../vmlinux | awk 'END{print $$3}')
+LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
# Supply ZRELADDR to the decompressor via a linker symbol.
ifneq ($(CONFIG_AUTO_ZRELADDR),y)
LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)
@@ -123,7 +147,7 @@ LDFLAGS_vmlinux += -T
# For __aeabi_uidivmod
lib1funcs = $(obj)/lib1funcs.o
-$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
+$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
$(call cmd,shipped)
# We need to prevent any GOTOFF relocs being used with references
@@ -139,8 +163,16 @@ bad_syms=$$($(CROSS_COMPILE)nm $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \
( echo "following symbols must have non local/private scope:" >&2; \
echo "$$bad_syms" >&2; rm -f $@; false )
+check_for_multiple_zreladdr = \
+if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \
+ echo 'multiple zreladdrs: $(ZRELADDR)'; \
+ echo 'This needs CONFIG_AUTO_ZRELADDR to be set'; \
+ false; \
+fi
+
$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
+ @$(check_for_multiple_zreladdr)
$(call if_changed,ld)
@$(check_for_bad_syms)
diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c
new file mode 100644
index 000000000000..6ce11c481178
--- /dev/null
+++ b/arch/arm/boot/compressed/atags_to_fdt.c
@@ -0,0 +1,97 @@
+#include <asm/setup.h>
+#include <libfdt.h>
+
+static int node_offset(void *fdt, const char *node_path)
+{
+ int offset = fdt_path_offset(fdt, node_path);
+ if (offset == -FDT_ERR_NOTFOUND)
+ offset = fdt_add_subnode(fdt, 0, node_path);
+ return offset;
+}
+
+static int setprop(void *fdt, const char *node_path, const char *property,
+ uint32_t *val_array, int size)
+{
+ int offset = node_offset(fdt, node_path);
+ if (offset < 0)
+ return offset;
+ return fdt_setprop(fdt, offset, property, val_array, size);
+}
+
+static int setprop_string(void *fdt, const char *node_path,
+ const char *property, const char *string)
+{
+ int offset = node_offset(fdt, node_path);
+ if (offset < 0)
+ return offset;
+ return fdt_setprop_string(fdt, offset, property, string);
+}
+
+static int setprop_cell(void *fdt, const char *node_path,
+ const char *property, uint32_t val)
+{
+ int offset = node_offset(fdt, node_path);
+ if (offset < 0)
+ return offset;
+ return fdt_setprop_cell(fdt, offset, property, val);
+}
+
+/*
+ * Convert and fold provided ATAGs into the provided FDT.
+ *
+ * REturn values:
+ * = 0 -> pretend success
+ * = 1 -> bad ATAG (may retry with another possible ATAG pointer)
+ * < 0 -> error from libfdt
+ */
+int atags_to_fdt(void *atag_list, void *fdt, int total_space)
+{
+ struct tag *atag = atag_list;
+ uint32_t mem_reg_property[2 * NR_BANKS];
+ int memcount = 0;
+ int ret;
+
+ /* make sure we've got an aligned pointer */
+ if ((u32)atag_list & 0x3)
+ return 1;
+
+ /* if we get a DTB here we're done already */
+ if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
+ return 0;
+
+ /* validate the ATAG */
+ if (atag->hdr.tag != ATAG_CORE ||
+ (atag->hdr.size != tag_size(tag_core) &&
+ atag->hdr.size != 2))
+ return 1;
+
+ /* let's give it all the room it could need */
+ ret = fdt_open_into(fdt, fdt, total_space);
+ if (ret < 0)
+ return ret;
+
+ for_each_tag(atag, atag_list) {
+ if (atag->hdr.tag == ATAG_CMDLINE) {
+ setprop_string(fdt, "/chosen", "bootargs",
+ atag->u.cmdline.cmdline);
+ } else if (atag->hdr.tag == ATAG_MEM) {
+ if (memcount >= sizeof(mem_reg_property)/4)
+ continue;
+ mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
+ mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
+ } else if (atag->hdr.tag == ATAG_INITRD2) {
+ uint32_t initrd_start, initrd_size;
+ initrd_start = atag->u.initrd.start;
+ initrd_size = atag->u.initrd.size;
+ setprop_cell(fdt, "/chosen", "linux,initrd-start",
+ initrd_start);
+ setprop_cell(fdt, "/chosen", "linux,initrd-end",
+ initrd_start + initrd_size);
+ }
+ }
+
+ if (memcount)
+ setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);
+
+ return fdt_pack(fdt);
+}
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index e95a5989602a..c2effc917254 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -216,6 +216,104 @@ restart: adr r0, LC0
mov r10, r6
#endif
+ mov r5, #0 @ init dtb size to 0
+#ifdef CONFIG_ARM_APPENDED_DTB
+/*
+ * r0 = delta
+ * r2 = BSS start
+ * r3 = BSS end
+ * r4 = final kernel address
+ * r5 = appended dtb size (still unknown)
+ * r6 = _edata
+ * r7 = architecture ID
+ * r8 = atags/device tree pointer
+ * r9 = size of decompressed image
+ * r10 = end of this image, including bss/stack/malloc space if non XIP
+ * r11 = GOT start
+ * r12 = GOT end
+ * sp = stack pointer
+ *
+ * if there are device trees (dtb) appended to zImage, advance r10 so that the
+ * dtb data will get relocated along with the kernel if necessary.
+ */
+
+ ldr lr, [r6, #0]
+#ifndef __ARMEB__
+ ldr r1, =0xedfe0dd0 @ sig is 0xd00dfeed big endian
+#else
+ ldr r1, =0xd00dfeed
+#endif
+ cmp lr, r1
+ bne dtb_check_done @ not found
+
+#ifdef CONFIG_ARM_ATAG_DTB_COMPAT
+ /*
+ * OK... Let's do some funky business here.
+ * If we do have a DTB appended to zImage, and we do have
+ * an ATAG list around, we want the later to be translated
+ * and folded into the former here. To be on the safe side,
+ * let's temporarily move the stack away into the malloc
+ * area. No GOT fixup has occurred yet, but none of the
+ * code we're about to call uses any global variable.
+ */
+ add sp, sp, #0x10000
+ stmfd sp!, {r0-r3, ip, lr}
+ mov r0, r8
+ mov r1, r6
+ sub r2, sp, r6
+ bl atags_to_fdt
+
+ /*
+ * If returned value is 1, there is no ATAG at the location
+ * pointed by r8. Try the typical 0x100 offset from start
+ * of RAM and hope for the best.
+ */
+ cmp r0, #1
+ sub r0, r4, #TEXT_OFFSET
+ add r0, r0, #0x100
+ mov r1, r6
+ sub r2, sp, r6
+ blne atags_to_fdt
+
+ ldmfd sp!, {r0-r3, ip, lr}
+ sub sp, sp, #0x10000
+#endif
+
+ mov r8, r6 @ use the appended device tree
+
+ /*
+ * Make sure that the DTB doesn't end up in the final
+ * kernel's .bss area. To do so, we adjust the decompressed
+ * kernel size to compensate if that .bss size is larger
+ * than the relocated code.
+ */
+ ldr r5, =_kernel_bss_size
+ adr r1, wont_overwrite
+ sub r1, r6, r1
+ subs r1, r5, r1
+ addhi r9, r9, r1
+
+ /* Get the dtb's size */
+ ldr r5, [r6, #4]
+#ifndef __ARMEB__
+ /* convert r5 (dtb size) to little endian */
+ eor r1, r5, r5, ror #16
+ bic r1, r1, #0x00ff0000
+ mov r5, r5, ror #8
+ eor r5, r5, r1, lsr #8
+#endif
+
+ /* preserve 64-bit alignment */
+ add r5, r5, #7
+ bic r5, r5, #7
+
+ /* relocate some pointers past the appended dtb */
+ add r6, r6, r5
+ add r10, r10, r5
+ add sp, sp, r5
+dtb_check_done:
+#endif
+
/*
* Check to see if we will overwrite ourselves.
* r4 = final kernel address
@@ -223,15 +321,14 @@ restart: adr r0, LC0
* r10 = end of this image, including bss/stack/malloc space if non XIP
* We basically want:
* r4 - 16k page directory >= r10 -> OK
- * r4 + image length <= current position (pc) -> OK
+ * r4 + image length <= address of wont_overwrite -> OK
*/
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
- ARM( cmp r10, pc )
- THUMB( mov lr, pc )
- THUMB( cmp r10, lr )
+ adr r9, wont_overwrite
+ cmp r10, r9
bls wont_overwrite
/*
@@ -285,14 +382,16 @@ wont_overwrite:
* r2 = BSS start
* r3 = BSS end
* r4 = kernel execution address
+ * r5 = appended dtb size (0 if not present)
* r7 = architecture ID
* r8 = atags pointer
* r11 = GOT start
* r12 = GOT end
* sp = stack pointer
*/
- teq r0, #0
+ orrs r1, r0, r5
beq not_relocated
+
add r11, r11, r0
add r12, r12, r0
@@ -307,12 +406,21 @@ wont_overwrite:
/*
* Relocate all entries in the GOT table.
+ * Bump bss entries to _edata + dtb size
*/
1: ldr r1, [r11, #0] @ relocate entries in the GOT
- add r1, r1, r0 @ table. This fixes up the
- str r1, [r11], #4 @ C references.
+ add r1, r1, r0 @ This fixes up C references
+ cmp r1, r2 @ if entry >= bss_start &&
+ cmphs r3, r1 @ bss_end > entry
+ addhi r1, r1, r5 @ entry += dtb size
+ str r1, [r11], #4 @ next entry
cmp r11, r12
blo 1b
+
+ /* bump our bss pointers too */
+ add r2, r2, r5
+ add r3, r3, r5
+
#else
/*
diff --git a/arch/arm/boot/compressed/libfdt_env.h b/arch/arm/boot/compressed/libfdt_env.h
new file mode 100644
index 000000000000..1f4e71876b00
--- /dev/null
+++ b/arch/arm/boot/compressed/libfdt_env.h
@@ -0,0 +1,15 @@
+#ifndef _ARM_LIBFDT_ENV_H
+#define _ARM_LIBFDT_ENV_H
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/byteorder.h>
+
+#define fdt16_to_cpu(x) be16_to_cpu(x)
+#define cpu_to_fdt16(x) cpu_to_be16(x)
+#define fdt32_to_cpu(x) be32_to_cpu(x)
+#define cpu_to_fdt32(x) cpu_to_be32(x)
+#define fdt64_to_cpu(x) be64_to_cpu(x)
+#define cpu_to_fdt64(x) cpu_to_be64(x)
+
+#endif
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 832d37236c59..8e2a8fca5ed2 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -18,14 +18,9 @@
unsigned int __machine_arch_type;
-#define _LINUX_STRING_H_
-
#include <linux/compiler.h> /* for inline */
-#include <linux/types.h> /* for size_t */
-#include <linux/stddef.h> /* for NULL */
+#include <linux/types.h>
#include <linux/linkage.h>
-#include <asm/string.h>
-
static void putstr(const char *ptr);
extern void error(char *x);
@@ -101,41 +96,6 @@ static void putstr(const char *ptr)
flush();
}
-
-void *memcpy(void *__dest, __const void *__src, size_t __n)
-{
- int i = 0;
- unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
-
- for (i = __n >> 3; i > 0; i--) {
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- }
-
- if (__n & 1 << 2) {
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- *d++ = *s++;
- }
-
- if (__n & 1 << 1) {
- *d++ = *s++;
- *d++ = *s++;
- }
-
- if (__n & 1)
- *d++ = *s++;
-
- return __dest;
-}
-
/*
* gzip declarations
*/
diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c
new file mode 100644
index 000000000000..36e53ef9200f
--- /dev/null
+++ b/arch/arm/boot/compressed/string.c
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/boot/compressed/string.c
+ *
+ * Small subset of simple string routines
+ */
+
+#include <linux/string.h>
+
+void *memcpy(void *__dest, __const void *__src, size_t __n)
+{
+ int i = 0;
+ unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
+
+ for (i = __n >> 3; i > 0; i--) {
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ }
+
+ if (__n & 1 << 2) {
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ }
+
+ if (__n & 1 << 1) {
+ *d++ = *s++;
+ *d++ = *s++;
+ }
+
+ if (__n & 1)
+ *d++ = *s++;
+
+ return __dest;
+}
+
+void *memmove(void *__dest, __const void *__src, size_t count)
+{
+ unsigned char *d = __dest;
+ const unsigned char *s = __src;
+
+ if (__dest == __src)
+ return __dest;
+
+ if (__dest < __src)
+ return memcpy(__dest, __src, count);
+
+ while (count--)
+ d[count] = s[count];
+ return __dest;
+}
+
+size_t strlen(const char *s)
+{
+ const char *sc = s;
+
+ while (*sc != '\0')
+ sc++;
+ return sc - s;
+}
+
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+ const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;
+ int res = 0;
+
+ while (su1 < end) {
+ res = *su1++ - *su2++;
+ if (res)
+ break;
+ }
+ return res;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+ unsigned char c1, c2;
+ int res = 0;
+
+ do {
+ c1 = *cs++;
+ c2 = *ct++;
+ res = c1 - c2;
+ if (res)
+ break;
+ } while (c1);
+ return res;
+}
+
+void *memchr(const void *s, int c, size_t count)
+{
+ const unsigned char *p = s;
+
+ while (count--)
+ if ((unsigned char)c == *p++)
+ return (void *)(p - 1);
+ return NULL;
+}
+
+char *strchr(const char *s, int c)
+{
+ while (*s != (char)c)
+ if (*s++ == '\0')
+ return NULL;
+ return (char *)s;
+}
+
+#undef memset
+
+void *memset(void *s, int c, size_t count)
+{
+ char *xs = s;
+ while (count--)
+ *xs++ = c;
+ return s;
+}
+
+void __memzero(void *s, size_t count)
+{
+ memset(s, 0, count);
+}
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index 4e728834a1b9..4919f2ac8b89 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -51,6 +51,10 @@ SECTIONS
_got_start = .;
.got : { *(.got) }
_got_end = .;
+
+ /* ensure the zImage file size is always a multiple of 64 bits */
+ /* (without a dummy byte, ld just ignores the empty section) */
+ .pad : { BYTE(0); . = ALIGN(8); }
_edata = .;
. = BSS_START;
diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
new file mode 100644
index 000000000000..aeef04269cf8
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
@@ -0,0 +1,119 @@
+/*
+ * at91sam9g20.dtsi - Device Tree Include file for AT91SAM9G20 family SoC
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
+ * 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9G20 family SoC";
+ compatible = "atmel,at91sam9g20";
+ interrupt-parent = <&aic>;
+
+ aliases {
+ serial0 = &dbgu;
+ serial1 = &usart0;
+ serial2 = &usart1;
+ serial3 = &usart2;
+ serial4 = &usart3;
+ serial5 = &usart4;
+ serial6 = &usart5;
+ };
+ cpus {
+ cpu@0 {
+ compatible = "arm,arm926ejs";
+ };
+ };
+
+ memory@20000000 {
+ reg = <0x20000000 0x08000000>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ aic: interrupt-controller@fffff000 {
+ #interrupt-cells = <1>;
+ compatible = "atmel,at91rm9200-aic";
+ interrupt-controller;
+ interrupt-parent;
+ reg = <0xfffff000 0x200>;
+ };
+
+ dbgu: serial@fffff200 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffff200 0x200>;
+ interrupts = <1>;
+ status = "disabled";
+ };
+
+ usart0: serial@fffb0000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffb0000 0x200>;
+ interrupts = <6>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart1: serial@fffb4000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffb4000 0x200>;
+ interrupts = <7>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart2: serial@fffb8000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffb8000 0x200>;
+ interrupts = <8>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart3: serial@fffd0000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffd0000 0x200>;
+ interrupts = <23>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart4: serial@fffd4000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffd4000 0x200>;
+ interrupts = <24>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart5: serial@fffd8000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffd8000 0x200>;
+ interrupts = <25>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
new file mode 100644
index 000000000000..db6a45202f26
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -0,0 +1,106 @@
+/*
+ * at91sam9g45.dtsi - Device Tree Include file for AT91SAM9G45 family SoC
+ * applies to AT91SAM9G45, AT91SAM9M10,
+ * AT91SAM9G46, AT91SAM9M11 SoC
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9G45 family SoC";
+ compatible = "atmel,at91sam9g45";
+ interrupt-parent = <&aic>;
+
+ aliases {
+ serial0 = &dbgu;
+ serial1 = &usart0;
+ serial2 = &usart1;
+ serial3 = &usart2;
+ serial4 = &usart3;
+ };
+ cpus {
+ cpu@0 {
+ compatible = "arm,arm926ejs";
+ };
+ };
+
+ memory@70000000 {
+ reg = <0x70000000 0x10000000>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ aic: interrupt-controller@fffff000 {
+ #interrupt-cells = <1>;
+ compatible = "atmel,at91rm9200-aic";
+ interrupt-controller;
+ interrupt-parent;
+ reg = <0xfffff000 0x200>;
+ };
+
+ dma: dma-controller@ffffec00 {
+ compatible = "atmel,at91sam9g45-dma";
+ reg = <0xffffec00 0x200>;
+ interrupts = <21>;
+ };
+
+ dbgu: serial@ffffee00 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xffffee00 0x200>;
+ interrupts = <1>;
+ status = "disabled";
+ };
+
+ usart0: serial@fff8c000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff8c000 0x200>;
+ interrupts = <7>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart1: serial@fff90000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff90000 0x200>;
+ interrupts = <8>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart2: serial@fff94000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff94000 0x200>;
+ interrupts = <9>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+
+ usart3: serial@fff98000 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfff98000 0x200>;
+ interrupts = <10>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
new file mode 100644
index 000000000000..85b34f59cd82
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -0,0 +1,35 @@
+/*
+ * at91sam9m10g45ek.dts - Device Tree file for AT91SAM9M10G45-EK board
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g45.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9M10G45-EK";
+ compatible = "atmel,at91sam9m10g45ek", "atmel,at91sam9g45", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:4M(bootstrap/uboot/kernel)ro,60M(rootfs),-(data) root=/dev/mtdblock1 rw rootfstype=jffs2";
+ };
+
+ memory@70000000 {
+ reg = <0x70000000 0x4000000>;
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@ffffee00 {
+ status = "okay";
+ };
+
+ usart1: serial@fff90000 {
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts
new file mode 100644
index 000000000000..aeb1a7578fad
--- /dev/null
+++ b/arch/arm/boot/dts/highbank.dts
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2011 Calxeda, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+
+/* First 4KB has pen for secondary cores. */
+/memreserve/ 0x00000000 0x0001000;
+
+/ {
+ model = "Calxeda Highbank";
+ compatible = "calxeda,highbank";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@2 {
+ compatible = "arm,cortex-a9";
+ reg = <2>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@3 {
+ compatible = "arm,cortex-a9";
+ reg = <3>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ memory {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x00000000 0xff900000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyAMA0";
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&intc>;
+ ranges;
+
+ timer@fff10600 {
+ compatible = "arm,smp-twd";
+ reg = <0xfff10600 0x20>;
+ interrupts = <1 13 0xf04>;
+ };
+
+ watchdog@fff10620 {
+ compatible = "arm,cortex-a9-wdt";
+ reg = <0xfff10620 0x20>;
+ interrupts = <1 14 0xf04>;
+ };
+
+ intc: interrupt-controller@fff11000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #size-cells = <0>;
+ #address-cells = <1>;
+ interrupt-controller;
+ interrupt-parent;
+ reg = <0xfff11000 0x1000>,
+ <0xfff10100 0x100>;
+ };
+
+ L2: l2-cache {
+ compatible = "arm,pl310-cache";
+ reg = <0xfff12000 0x1000>;
+ interrupts = <0 70 4>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupts = <0 76 4 0 75 4 0 74 4 0 73 4>;
+ };
+
+ sata@ffe08000 {
+ compatible = "calxeda,hb-ahci";
+ reg = <0xffe08000 0x10000>;
+ interrupts = <0 83 4>;
+ };
+
+ sdhci@ffe0e000 {
+ compatible = "calxeda,hb-sdhci";
+ reg = <0xffe0e000 0x1000>;
+ interrupts = <0 90 4>;
+ };
+
+ ipc@fff20000 {
+ compatible = "arm,pl320", "arm,primecell";
+ reg = <0xfff20000 0x1000>;
+ interrupts = <0 7 4>;
+ };
+
+ gpioe: gpio@fff30000 {
+ #gpio-cells = <2>;
+ compatible = "arm,pl061", "arm,primecell";
+ gpio-controller;
+ reg = <0xfff30000 0x1000>;
+ interrupts = <0 14 4>;
+ };
+
+ gpiof: gpio@fff31000 {
+ #gpio-cells = <2>;
+ compatible = "arm,pl061", "arm,primecell";
+ gpio-controller;
+ reg = <0xfff31000 0x1000>;
+ interrupts = <0 15 4>;
+ };
+
+ gpiog: gpio@fff32000 {
+ #gpio-cells = <2>;
+ compatible = "arm,pl061", "arm,primecell";
+ gpio-controller;
+ reg = <0xfff32000 0x1000>;
+ interrupts = <0 16 4>;
+ };
+
+ gpioh: gpio@fff33000 {
+ #gpio-cells = <2>;
+ compatible = "arm,pl061", "arm,primecell";
+ gpio-controller;
+ reg = <0xfff33000 0x1000>;
+ interrupts = <0 17 4>;
+ };
+
+ timer {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0xfff34000 0x1000>;
+ interrupts = <0 18 4>;
+ };
+
+ rtc@fff35000 {
+ compatible = "arm,pl031", "arm,primecell";
+ reg = <0xfff35000 0x1000>;
+ interrupts = <0 19 4>;
+ };
+
+ serial@fff36000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xfff36000 0x1000>;
+ interrupts = <0 20 4>;
+ };
+
+ smic@fff3a000 {
+ compatible = "ipmi-smic";
+ device_type = "ipmi";
+ reg = <0xfff3a000 0x1000>;
+ interrupts = <0 24 4>;
+ reg-size = <4>;
+ reg-spacing = <4>;
+ };
+
+ sregs@fff3c000 {
+ compatible = "calxeda,hb-sregs";
+ reg = <0xfff3c000 0x1000>;
+ };
+
+ dma@fff3d000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0xfff3d000 0x1000>;
+ interrupts = <0 92 4>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
new file mode 100644
index 000000000000..f8766af11215
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx51.dtsi"
+
+/ {
+ model = "Freescale i.MX51 Babbage Board";
+ compatible = "fsl,imx51-babbage", "fsl,imx51";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+ };
+
+ memory {
+ reg = <0x90000000 0x20000000>;
+ };
+
+ soc {
+ aips@70000000 { /* aips-1 */
+ spba@70000000 {
+ esdhc@70004000 { /* ESDHC1 */
+ fsl,cd-internal;
+ fsl,wp-internal;
+ status = "okay";
+ };
+
+ esdhc@70008000 { /* ESDHC2 */
+ cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */
+ wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */
+ status = "okay";
+ };
+
+ uart2: uart@7000c000 { /* UART3 */
+ fsl,uart-has-rtscts;
+ status = "okay";
+ };
+
+ ecspi@70010000 { /* ECSPI1 */
+ fsl,spi-num-chipselects = <2>;
+ cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
+ <&gpio3 25 0>; /* GPIO4_25 */
+ status = "okay";
+
+ pmic: mc13892@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mc13892";
+ spi-max-frequency = <6000000>;
+ reg = <0>;
+ mc13xxx-irq-gpios = <&gpio0 8 0>; /* GPIO1_8 */
+ fsl,mc13xxx-uses-regulator;
+ };
+
+ flash: at45db321d@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+ spi-max-frequency = <25000000>;
+ reg = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0x0 0x40000>;
+ read-only;
+ };
+
+ partition@40000 {
+ label = "Kernel";
+ reg = <0x40000 0x3c0000>;
+ };
+ };
+ };
+ };
+
+ wdog@73f98000 { /* WDOG1 */
+ status = "okay";
+ };
+
+ iomuxc@73fa8000 {
+ compatible = "fsl,imx51-iomuxc-babbage";
+ reg = <0x73fa8000 0x4000>;
+ };
+
+ uart0: uart@73fbc000 {
+ fsl,uart-has-rtscts;
+ status = "okay";
+ };
+
+ uart1: uart@73fc0000 {
+ status = "okay";
+ };
+ };
+
+ aips@80000000 { /* aips-2 */
+ sdma@83fb0000 {
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
+ };
+
+ i2c@83fc4000 { /* I2C2 */
+ status = "okay";
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ };
+ };
+
+ fec@83fec000 {
+ phy-mode = "mii";
+ status = "okay";
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power {
+ label = "Power Button";
+ gpios = <&gpio1 21 0>;
+ linux,code = <116>; /* KEY_POWER */
+ gpio-key,wakeup;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
new file mode 100644
index 000000000000..327ab8e3a4c8
--- /dev/null
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ };
+
+ tzic: tz-interrupt-controller@e0000000 {
+ compatible = "fsl,imx51-tzic", "fsl,tzic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xe0000000 0x4000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil {
+ compatible = "fsl,imx-ckil", "fixed-clock";
+ clock-frequency = <32768>;
+ };
+
+ ckih1 {
+ compatible = "fsl,imx-ckih1", "fixed-clock";
+ clock-frequency = <22579200>;
+ };
+
+ ckih2 {
+ compatible = "fsl,imx-ckih2", "fixed-clock";
+ clock-frequency = <0>;
+ };
+
+ osc {
+ compatible = "fsl,imx-osc", "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&tzic>;
+ ranges;
+
+ aips@70000000 { /* AIPS1 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x70000000 0x10000000>;
+ ranges;
+
+ spba@70000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x70000000 0x40000>;
+ ranges;
+
+ esdhc@70004000 { /* ESDHC1 */
+ compatible = "fsl,imx51-esdhc";
+ reg = <0x70004000 0x4000>;
+ interrupts = <1>;
+ status = "disabled";
+ };
+
+ esdhc@70008000 { /* ESDHC2 */
+ compatible = "fsl,imx51-esdhc";
+ reg = <0x70008000 0x4000>;
+ interrupts = <2>;
+ status = "disabled";
+ };
+
+ uart2: uart@7000c000 { /* UART3 */
+ compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+ reg = <0x7000c000 0x4000>;
+ interrupts = <33>;
+ status = "disabled";
+ };
+
+ ecspi@70010000 { /* ECSPI1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-ecspi";
+ reg = <0x70010000 0x4000>;
+ interrupts = <36>;
+ status = "disabled";
+ };
+
+ esdhc@70020000 { /* ESDHC3 */
+ compatible = "fsl,imx51-esdhc";
+ reg = <0x70020000 0x4000>;
+ interrupts = <3>;
+ status = "disabled";
+ };
+
+ esdhc@70024000 { /* ESDHC4 */
+ compatible = "fsl,imx51-esdhc";
+ reg = <0x70024000 0x4000>;
+ interrupts = <4>;
+ status = "disabled";
+ };
+ };
+
+ gpio0: gpio@73f84000 { /* GPIO1 */
+ compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+ reg = <0x73f84000 0x4000>;
+ interrupts = <50 51>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio1: gpio@73f88000 { /* GPIO2 */
+ compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+ reg = <0x73f88000 0x4000>;
+ interrupts = <52 53>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio2: gpio@73f8c000 { /* GPIO3 */
+ compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+ reg = <0x73f8c000 0x4000>;
+ interrupts = <54 55>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio3: gpio@73f90000 { /* GPIO4 */
+ compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+ reg = <0x73f90000 0x4000>;
+ interrupts = <56 57>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ wdog@73f98000 { /* WDOG1 */
+ compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+ reg = <0x73f98000 0x4000>;
+ interrupts = <58>;
+ status = "disabled";
+ };
+
+ wdog@73f9c000 { /* WDOG2 */
+ compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+ reg = <0x73f9c000 0x4000>;
+ interrupts = <59>;
+ status = "disabled";
+ };
+
+ uart0: uart@73fbc000 {
+ compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+ reg = <0x73fbc000 0x4000>;
+ interrupts = <31>;
+ status = "disabled";
+ };
+
+ uart1: uart@73fc0000 {
+ compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+ reg = <0x73fc0000 0x4000>;
+ interrupts = <32>;
+ status = "disabled";
+ };
+ };
+
+ aips@80000000 { /* AIPS2 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x80000000 0x10000000>;
+ ranges;
+
+ ecspi@83fac000 { /* ECSPI2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-ecspi";
+ reg = <0x83fac000 0x4000>;
+ interrupts = <37>;
+ status = "disabled";
+ };
+
+ sdma@83fb0000 {
+ compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
+ reg = <0x83fb0000 0x4000>;
+ interrupts = <6>;
+ };
+
+ cspi@83fc0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
+ reg = <0x83fc0000 0x4000>;
+ interrupts = <38>;
+ status = "disabled";
+ };
+
+ i2c@83fc4000 { /* I2C2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+ reg = <0x83fc4000 0x4000>;
+ interrupts = <63>;
+ status = "disabled";
+ };
+
+ i2c@83fc8000 { /* I2C1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+ reg = <0x83fc8000 0x4000>;
+ interrupts = <62>;
+ status = "disabled";
+ };
+
+ fec@83fec000 {
+ compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+ reg = <0x83fec000 0x4000>;
+ interrupts = <87>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts
new file mode 100644
index 000000000000..2ab7f80a0a35
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-ard.dts
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+ model = "Freescale i.MX53 Automotive Reference Design Board";
+ compatible = "fsl,imx53-ard", "fsl,imx53";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+ };
+
+ memory {
+ reg = <0x70000000 0x40000000>;
+ };
+
+ soc {
+ aips@50000000 { /* AIPS1 */
+ spba@50000000 {
+ esdhc@50004000 { /* ESDHC1 */
+ cd-gpios = <&gpio0 1 0>; /* GPIO1_1 */
+ wp-gpios = <&gpio0 9 0>; /* GPIO1_9 */
+ status = "okay";
+ };
+ };
+
+ wdog@53f98000 { /* WDOG1 */
+ status = "okay";
+ };
+
+ iomuxc@53fa8000 {
+ compatible = "fsl,imx53-iomuxc-ard";
+ reg = <0x53fa8000 0x4000>;
+ };
+
+ uart0: uart@53fbc000 { /* UART1 */
+ status = "okay";
+ };
+ };
+
+ aips@60000000 { /* AIPS2 */
+ sdma@63fb0000 {
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+ };
+ };
+ };
+
+ eim-cs1@f4000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,eim-bus", "simple-bus";
+ reg = <0xf4000000 0x3ff0000>;
+ ranges;
+
+ lan9220@f4000000 {
+ compatible = "smsc,lan9220", "smsc,lan9115";
+ reg = <0xf4000000 0x2000000>;
+ phy-mode = "mii";
+ interrupt-parent = <&gpio1>;
+ interrupts = <31>;
+ reg-io-width = <4>;
+ smsc,irq-push-pull;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ home {
+ label = "Home";
+ gpios = <&gpio4 10 0>; /* GPIO5_10 */
+ linux,code = <102>; /* KEY_HOME */
+ gpio-key,wakeup;
+ };
+
+ back {
+ label = "Back";
+ gpios = <&gpio4 11 0>; /* GPIO5_11 */
+ linux,code = <158>; /* KEY_BACK */
+ gpio-key,wakeup;
+ };
+
+ program {
+ label = "Program";
+ gpios = <&gpio4 12 0>; /* GPIO5_12 */
+ linux,code = <362>; /* KEY_PROGRAM */
+ gpio-key,wakeup;
+ };
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio4 13 0>; /* GPIO5_13 */
+ linux,code = <115>; /* KEY_VOLUMEUP */
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio3 0 0>; /* GPIO4_0 */
+ linux,code = <114>; /* KEY_VOLUMEDOWN */
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx53-evk.dts b/arch/arm/boot/dts/imx53-evk.dts
new file mode 100644
index 000000000000..3f3a88185ff8
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-evk.dts
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+ model = "Freescale i.MX53 Evaluation Kit";
+ compatible = "fsl,imx53-evk", "fsl,imx53";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+ };
+
+ memory {
+ reg = <0x70000000 0x80000000>;
+ };
+
+ soc {
+ aips@50000000 { /* AIPS1 */
+ spba@50000000 {
+ esdhc@50004000 { /* ESDHC1 */
+ cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+ wp-gpios = <&gpio2 14 0>; /* GPIO3_14 */
+ status = "okay";
+ };
+
+ ecspi@50010000 { /* ECSPI1 */
+ fsl,spi-num-chipselects = <2>;
+ cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */
+ <&gpio2 19 0>; /* GPIO3_19 */
+ status = "okay";
+
+ flash: at45db321d@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+ spi-max-frequency = <25000000>;
+ reg = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0x0 0x40000>;
+ read-only;
+ };
+
+ partition@40000 {
+ label = "Kernel";
+ reg = <0x40000 0x3c0000>;
+ };
+ };
+ };
+
+ esdhc@50020000 { /* ESDHC3 */
+ cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */
+ wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */
+ status = "okay";
+ };
+ };
+
+ wdog@53f98000 { /* WDOG1 */
+ status = "okay";
+ };
+
+ iomuxc@53fa8000 {
+ compatible = "fsl,imx53-iomuxc-evk";
+ reg = <0x53fa8000 0x4000>;
+ };
+
+ uart0: uart@53fbc000 { /* UART1 */
+ status = "okay";
+ };
+ };
+
+ aips@60000000 { /* AIPS2 */
+ sdma@63fb0000 {
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+ };
+
+ i2c@63fc4000 { /* I2C2 */
+ status = "okay";
+
+ pmic: mc13892@08 {
+ compatible = "fsl,mc13892", "fsl,mc13xxx";
+ reg = <0x08>;
+ };
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ };
+ };
+
+ fec@63fec000 {
+ phy-mode = "rmii";
+ phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+ status = "okay";
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ green {
+ label = "Heartbeat";
+ gpios = <&gpio6 7 0>; /* GPIO7_7 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
new file mode 100644
index 000000000000..ae6de6d0c3f1
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+ model = "Freescale i.MX53 Quick Start Board";
+ compatible = "fsl,imx53-qsb", "fsl,imx53";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+ };
+
+ memory {
+ reg = <0x70000000 0x40000000>;
+ };
+
+ soc {
+ aips@50000000 { /* AIPS1 */
+ spba@50000000 {
+ esdhc@50004000 { /* ESDHC1 */
+ cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+ status = "okay";
+ };
+
+ esdhc@50020000 { /* ESDHC3 */
+ cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */
+ wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */
+ status = "okay";
+ };
+ };
+
+ wdog@53f98000 { /* WDOG1 */
+ status = "okay";
+ };
+
+ iomuxc@53fa8000 {
+ compatible = "fsl,imx53-iomuxc-qsb";
+ reg = <0x53fa8000 0x4000>;
+ };
+
+ uart0: uart@53fbc000 { /* UART1 */
+ status = "okay";
+ };
+ };
+
+ aips@60000000 { /* AIPS2 */
+ sdma@63fb0000 {
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+ };
+
+ i2c@63fc4000 { /* I2C2 */
+ status = "okay";
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ };
+ };
+
+ i2c@63fc8000 { /* I2C1 */
+ status = "okay";
+
+ accelerometer: mma8450@1c {
+ compatible = "fsl,mma8450";
+ reg = <0x1c>;
+ };
+
+ pmic: dialog@48 {
+ compatible = "dialog,da9053", "dialog,da9052";
+ reg = <0x48>;
+ };
+ };
+
+ fec@63fec000 {
+ phy-mode = "rmii";
+ phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+ status = "okay";
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power {
+ label = "Power Button";
+ gpios = <&gpio0 8 0>; /* GPIO1_8 */
+ linux,code = <116>; /* KEY_POWER */
+ gpio-key,wakeup;
+ };
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio1 14 0>; /* GPIO2_14 */
+ linux,code = <115>; /* KEY_VOLUMEUP */
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio1 15 0>; /* GPIO2_15 */
+ linux,code = <114>; /* KEY_VOLUMEDOWN */
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ user {
+ label = "Heartbeat";
+ gpios = <&gpio6 7 0>; /* GPIO7_7 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts
new file mode 100644
index 000000000000..b1c062eea715
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-smd.dts
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+ model = "Freescale i.MX53 Smart Mobile Reference Design Board";
+ compatible = "fsl,imx53-smd", "fsl,imx53";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+ };
+
+ memory {
+ reg = <0x70000000 0x40000000>;
+ };
+
+ soc {
+ aips@50000000 { /* AIPS1 */
+ spba@50000000 {
+ esdhc@50004000 { /* ESDHC1 */
+ cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+ wp-gpios = <&gpio3 11 0>; /* GPIO4_11 */
+ status = "okay";
+ };
+
+ esdhc@50008000 { /* ESDHC2 */
+ fsl,card-wired;
+ status = "okay";
+ };
+
+ uart2: uart@5000c000 { /* UART3 */
+ fsl,uart-has-rtscts;
+ status = "okay";
+ };
+
+ ecspi@50010000 { /* ECSPI1 */
+ fsl,spi-num-chipselects = <2>;
+ cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */
+ <&gpio2 19 0>; /* GPIO3_19 */
+ status = "okay";
+
+ zigbee: mc1323@0 {
+ compatible = "fsl,mc1323";
+ spi-max-frequency = <8000000>;
+ reg = <0>;
+ };
+
+ flash: m25p32@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,m25p32", "st,m25p";
+ spi-max-frequency = <20000000>;
+ reg = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0x0 0x40000>;
+ read-only;
+ };
+
+ partition@40000 {
+ label = "Kernel";
+ reg = <0x40000 0x3c0000>;
+ };
+ };
+ };
+
+ esdhc@50020000 { /* ESDHC3 */
+ fsl,card-wired;
+ status = "okay";
+ };
+ };
+
+ wdog@53f98000 { /* WDOG1 */
+ status = "okay";
+ };
+
+ iomuxc@53fa8000 {
+ compatible = "fsl,imx53-iomuxc-smd";
+ reg = <0x53fa8000 0x4000>;
+ };
+
+ uart0: uart@53fbc000 { /* UART1 */
+ status = "okay";
+ };
+
+ uart1: uart@53fc0000 { /* UART2 */
+ status = "okay";
+ };
+ };
+
+ aips@60000000 { /* AIPS2 */
+ sdma@63fb0000 {
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+ };
+
+ i2c@63fc4000 { /* I2C2 */
+ status = "okay";
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ };
+
+ magnetometer: mag3110@0e {
+ compatible = "fsl,mag3110";
+ reg = <0x0e>;
+ };
+
+ touchkey: mpr121@5a {
+ compatible = "fsl,mpr121";
+ reg = <0x5a>;
+ };
+ };
+
+ i2c@63fc8000 { /* I2C1 */
+ status = "okay";
+
+ accelerometer: mma8450@1c {
+ compatible = "fsl,mma8450";
+ reg = <0x1c>;
+ };
+
+ camera: ov5642@3c {
+ compatible = "ovti,ov5642";
+ reg = <0x3c>;
+ };
+
+ pmic: dialog@48 {
+ compatible = "dialog,da9053", "dialog,da9052";
+ reg = <0x48>;
+ };
+ };
+
+ fec@63fec000 {
+ phy-mode = "rmii";
+ phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+ status = "okay";
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio1 14 0>; /* GPIO2_14 */
+ linux,code = <115>; /* KEY_VOLUMEUP */
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio1 15 0>; /* GPIO2_15 */
+ linux,code = <114>; /* KEY_VOLUMEDOWN */
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
new file mode 100644
index 000000000000..099cd84ee372
--- /dev/null
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ tzic: tz-interrupt-controller@0fffc000 {
+ compatible = "fsl,imx53-tzic", "fsl,tzic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x0fffc000 0x4000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil {
+ compatible = "fsl,imx-ckil", "fixed-clock";
+ clock-frequency = <32768>;
+ };
+
+ ckih1 {
+ compatible = "fsl,imx-ckih1", "fixed-clock";
+ clock-frequency = <22579200>;
+ };
+
+ ckih2 {
+ compatible = "fsl,imx-ckih2", "fixed-clock";
+ clock-frequency = <0>;
+ };
+
+ osc {
+ compatible = "fsl,imx-osc", "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&tzic>;
+ ranges;
+
+ aips@50000000 { /* AIPS1 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x50000000 0x10000000>;
+ ranges;
+
+ spba@50000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x50000000 0x40000>;
+ ranges;
+
+ esdhc@50004000 { /* ESDHC1 */
+ compatible = "fsl,imx53-esdhc";
+ reg = <0x50004000 0x4000>;
+ interrupts = <1>;
+ status = "disabled";
+ };
+
+ esdhc@50008000 { /* ESDHC2 */
+ compatible = "fsl,imx53-esdhc";
+ reg = <0x50008000 0x4000>;
+ interrupts = <2>;
+ status = "disabled";
+ };
+
+ uart2: uart@5000c000 { /* UART3 */
+ compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+ reg = <0x5000c000 0x4000>;
+ interrupts = <33>;
+ status = "disabled";
+ };
+
+ ecspi@50010000 { /* ECSPI1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+ reg = <0x50010000 0x4000>;
+ interrupts = <36>;
+ status = "disabled";
+ };
+
+ esdhc@50020000 { /* ESDHC3 */
+ compatible = "fsl,imx53-esdhc";
+ reg = <0x50020000 0x4000>;
+ interrupts = <3>;
+ status = "disabled";
+ };
+
+ esdhc@50024000 { /* ESDHC4 */
+ compatible = "fsl,imx53-esdhc";
+ reg = <0x50024000 0x4000>;
+ interrupts = <4>;
+ status = "disabled";
+ };
+ };
+
+ gpio0: gpio@53f84000 { /* GPIO1 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53f84000 0x4000>;
+ interrupts = <50 51>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio1: gpio@53f88000 { /* GPIO2 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53f88000 0x4000>;
+ interrupts = <52 53>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio2: gpio@53f8c000 { /* GPIO3 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53f8c000 0x4000>;
+ interrupts = <54 55>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio3: gpio@53f90000 { /* GPIO4 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53f90000 0x4000>;
+ interrupts = <56 57>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ wdog@53f98000 { /* WDOG1 */
+ compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+ reg = <0x53f98000 0x4000>;
+ interrupts = <58>;
+ status = "disabled";
+ };
+
+ wdog@53f9c000 { /* WDOG2 */
+ compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+ reg = <0x53f9c000 0x4000>;
+ interrupts = <59>;
+ status = "disabled";
+ };
+
+ uart0: uart@53fbc000 { /* UART1 */
+ compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+ reg = <0x53fbc000 0x4000>;
+ interrupts = <31>;
+ status = "disabled";
+ };
+
+ uart1: uart@53fc0000 { /* UART2 */
+ compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+ reg = <0x53fc0000 0x4000>;
+ interrupts = <32>;
+ status = "disabled";
+ };
+
+ gpio4: gpio@53fdc000 { /* GPIO5 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53fdc000 0x4000>;
+ interrupts = <103 104>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio5: gpio@53fe0000 { /* GPIO6 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53fe0000 0x4000>;
+ interrupts = <105 106>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio6: gpio@53fe4000 { /* GPIO7 */
+ compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+ reg = <0x53fe4000 0x4000>;
+ interrupts = <107 108>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ i2c@53fec000 { /* I2C3 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+ reg = <0x53fec000 0x4000>;
+ interrupts = <64>;
+ status = "disabled";
+ };
+
+ uart3: uart@53ff0000 { /* UART4 */
+ compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+ reg = <0x53ff0000 0x4000>;
+ interrupts = <13>;
+ status = "disabled";
+ };
+ };
+
+ aips@60000000 { /* AIPS2 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x60000000 0x10000000>;
+ ranges;
+
+ uart4: uart@63f90000 { /* UART5 */
+ compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+ reg = <0x63f90000 0x4000>;
+ interrupts = <86>;
+ status = "disabled";
+ };
+
+ ecspi@63fac000 { /* ECSPI2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+ reg = <0x63fac000 0x4000>;
+ interrupts = <37>;
+ status = "disabled";
+ };
+
+ sdma@63fb0000 {
+ compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
+ reg = <0x63fb0000 0x4000>;
+ interrupts = <6>;
+ };
+
+ cspi@63fc0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
+ reg = <0x63fc0000 0x4000>;
+ interrupts = <38>;
+ status = "disabled";
+ };
+
+ i2c@63fc4000 { /* I2C2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+ reg = <0x63fc4000 0x4000>;
+ interrupts = <63>;
+ status = "disabled";
+ };
+
+ i2c@63fc8000 { /* I2C1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+ reg = <0x63fc8000 0x4000>;
+ interrupts = <62>;
+ status = "disabled";
+ };
+
+ fec@63fec000 {
+ compatible = "fsl,imx53-fec", "fsl,imx25-fec";
+ reg = <0x63fec000 0x4000>;
+ interrupts = <87>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts
new file mode 100644
index 000000000000..072974e443f2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto.dts
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx6q.dtsi"
+
+/ {
+ model = "Freescale i.MX6 Quad SABRE Automotive Board";
+ compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 root=/dev/mmcblk3p3 rootwait";
+ };
+
+ memory {
+ reg = <0x10000000 0x80000000>;
+ };
+
+ soc {
+ aips-bus@02100000 { /* AIPS2 */
+ enet@02188000 {
+ phy-mode = "rgmii";
+ local-mac-address = [00 04 9F 01 1B 61];
+ status = "okay";
+ };
+
+ usdhc@02198000 { /* uSDHC3 */
+ cd-gpios = <&gpio5 11 0>; /* GPIO6_11 */
+ wp-gpios = <&gpio5 14 0>; /* GPIO6_14 */
+ status = "okay";
+ };
+
+ usdhc@0219c000 { /* uSDHC4 */
+ fsl,card-wired;
+ status = "okay";
+ };
+
+ uart3: uart@021f0000 { /* UART4 */
+ status = "okay";
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ debug-led {
+ label = "Heartbeat";
+ gpios = <&gpio2 25 0>; /* GPIO3_25 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
new file mode 100644
index 000000000000..7dda599558cc
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -0,0 +1,575 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@2 {
+ compatible = "arm,cortex-a9";
+ reg = <2>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu@3 {
+ compatible = "arm,cortex-a9";
+ reg = <3>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ intc: interrupt-controller@00a01000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-controller;
+ reg = <0x00a01000 0x1000>,
+ <0x00a00100 0x100>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil {
+ compatible = "fsl,imx-ckil", "fixed-clock";
+ clock-frequency = <32768>;
+ };
+
+ ckih1 {
+ compatible = "fsl,imx-ckih1", "fixed-clock";
+ clock-frequency = <0>;
+ };
+
+ osc {
+ compatible = "fsl,imx-osc", "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&intc>;
+ ranges;
+
+ timer@00a00600 {
+ compatible = "arm,smp-twd";
+ reg = <0x00a00600 0x100>;
+ interrupts = <1 13 0xf4>;
+ };
+
+ L2: l2-cache@00a02000 {
+ compatible = "arm,pl310-cache";
+ reg = <0x00a02000 0x1000>;
+ interrupts = <0 92 0x04>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ aips-bus@02000000 { /* AIPS1 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x100000>;
+ ranges;
+
+ spba-bus@02000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x40000>;
+ ranges;
+
+ spdif@02004000 {
+ reg = <0x02004000 0x4000>;
+ interrupts = <0 52 0x04>;
+ };
+
+ ecspi@02008000 { /* eCSPI1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02008000 0x4000>;
+ interrupts = <0 31 0x04>;
+ status = "disabled";
+ };
+
+ ecspi@0200c000 { /* eCSPI2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ reg = <0x0200c000 0x4000>;
+ interrupts = <0 32 0x04>;
+ status = "disabled";
+ };
+
+ ecspi@02010000 { /* eCSPI3 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02010000 0x4000>;
+ interrupts = <0 33 0x04>;
+ status = "disabled";
+ };
+
+ ecspi@02014000 { /* eCSPI4 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02014000 0x4000>;
+ interrupts = <0 34 0x04>;
+ status = "disabled";
+ };
+
+ ecspi@02018000 { /* eCSPI5 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02018000 0x4000>;
+ interrupts = <0 35 0x04>;
+ status = "disabled";
+ };
+
+ uart0: uart@02020000 { /* UART1 */
+ compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x02020000 0x4000>;
+ interrupts = <0 26 0x04>;
+ status = "disabled";
+ };
+
+ esai@02024000 {
+ reg = <0x02024000 0x4000>;
+ interrupts = <0 51 0x04>;
+ };
+
+ ssi@02028000 { /* SSI1 */
+ reg = <0x02028000 0x4000>;
+ interrupts = <0 46 0x04>;
+ };
+
+ ssi@0202c000 { /* SSI2 */
+ reg = <0x0202c000 0x4000>;
+ interrupts = <0 47 0x04>;
+ };
+
+ ssi@02030000 { /* SSI3 */
+ reg = <0x02030000 0x4000>;
+ interrupts = <0 48 0x04>;
+ };
+
+ asrc@02034000 {
+ reg = <0x02034000 0x4000>;
+ interrupts = <0 50 0x04>;
+ };
+
+ spba@0203c000 {
+ reg = <0x0203c000 0x4000>;
+ };
+ };
+
+ vpu@02040000 {
+ reg = <0x02040000 0x3c000>;
+ interrupts = <0 3 0x04 0 12 0x04>;
+ };
+
+ aipstz@0207c000 { /* AIPSTZ1 */
+ reg = <0x0207c000 0x4000>;
+ };
+
+ pwm@02080000 { /* PWM1 */
+ reg = <0x02080000 0x4000>;
+ interrupts = <0 83 0x04>;
+ };
+
+ pwm@02084000 { /* PWM2 */
+ reg = <0x02084000 0x4000>;
+ interrupts = <0 84 0x04>;
+ };
+
+ pwm@02088000 { /* PWM3 */
+ reg = <0x02088000 0x4000>;
+ interrupts = <0 85 0x04>;
+ };
+
+ pwm@0208c000 { /* PWM4 */
+ reg = <0x0208c000 0x4000>;
+ interrupts = <0 86 0x04>;
+ };
+
+ flexcan@02090000 { /* CAN1 */
+ reg = <0x02090000 0x4000>;
+ interrupts = <0 110 0x04>;
+ };
+
+ flexcan@02094000 { /* CAN2 */
+ reg = <0x02094000 0x4000>;
+ interrupts = <0 111 0x04>;
+ };
+
+ gpt@02098000 {
+ compatible = "fsl,imx6q-gpt";
+ reg = <0x02098000 0x4000>;
+ interrupts = <0 55 0x04>;
+ };
+
+ gpio0: gpio@0209c000 { /* GPIO1 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x0209c000 0x4000>;
+ interrupts = <0 66 0x04 0 67 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio1: gpio@020a0000 { /* GPIO2 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020a0000 0x4000>;
+ interrupts = <0 68 0x04 0 69 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio2: gpio@020a4000 { /* GPIO3 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020a4000 0x4000>;
+ interrupts = <0 70 0x04 0 71 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio3: gpio@020a8000 { /* GPIO4 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020a8000 0x4000>;
+ interrupts = <0 72 0x04 0 73 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio4: gpio@020ac000 { /* GPIO5 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020ac000 0x4000>;
+ interrupts = <0 74 0x04 0 75 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio5: gpio@020b0000 { /* GPIO6 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020b0000 0x4000>;
+ interrupts = <0 76 0x04 0 77 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gpio6: gpio@020b4000 { /* GPIO7 */
+ compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+ reg = <0x020b4000 0x4000>;
+ interrupts = <0 78 0x04 0 79 0x04>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ kpp@020b8000 {
+ reg = <0x020b8000 0x4000>;
+ interrupts = <0 82 0x04>;
+ };
+
+ wdog@020bc000 { /* WDOG1 */
+ compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+ reg = <0x020bc000 0x4000>;
+ interrupts = <0 80 0x04>;
+ status = "disabled";
+ };
+
+ wdog@020c0000 { /* WDOG2 */
+ compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+ reg = <0x020c0000 0x4000>;
+ interrupts = <0 81 0x04>;
+ status = "disabled";
+ };
+
+ ccm@020c4000 {
+ compatible = "fsl,imx6q-ccm";
+ reg = <0x020c4000 0x4000>;
+ interrupts = <0 87 0x04 0 88 0x04>;
+ };
+
+ anatop@020c8000 {
+ compatible = "fsl,imx6q-anatop";
+ reg = <0x020c8000 0x1000>;
+ interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
+ };
+
+ usbphy@020c9000 { /* USBPHY1 */
+ reg = <0x020c9000 0x1000>;
+ interrupts = <0 44 0x04>;
+ };
+
+ usbphy@020ca000 { /* USBPHY2 */
+ reg = <0x020ca000 0x1000>;
+ interrupts = <0 45 0x04>;
+ };
+
+ snvs@020cc000 {
+ reg = <0x020cc000 0x4000>;
+ interrupts = <0 19 0x04 0 20 0x04>;
+ };
+
+ epit@020d0000 { /* EPIT1 */
+ reg = <0x020d0000 0x4000>;
+ interrupts = <0 56 0x04>;
+ };
+
+ epit@020d4000 { /* EPIT2 */
+ reg = <0x020d4000 0x4000>;
+ interrupts = <0 57 0x04>;
+ };
+
+ src@020d8000 {
+ compatible = "fsl,imx6q-src";
+ reg = <0x020d8000 0x4000>;
+ interrupts = <0 91 0x04 0 96 0x04>;
+ };
+
+ gpc@020dc000 {
+ compatible = "fsl,imx6q-gpc";
+ reg = <0x020dc000 0x4000>;
+ interrupts = <0 89 0x04 0 90 0x04>;
+ };
+
+ iomuxc@020e0000 {
+ reg = <0x020e0000 0x4000>;
+ };
+
+ dcic@020e4000 { /* DCIC1 */
+ reg = <0x020e4000 0x4000>;
+ interrupts = <0 124 0x04>;
+ };
+
+ dcic@020e8000 { /* DCIC2 */
+ reg = <0x020e8000 0x4000>;
+ interrupts = <0 125 0x04>;
+ };
+
+ sdma@020ec000 {
+ compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
+ reg = <0x020ec000 0x4000>;
+ interrupts = <0 2 0x04>;
+ };
+ };
+
+ aips-bus@02100000 { /* AIPS2 */
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02100000 0x100000>;
+ ranges;
+
+ caam@02100000 {
+ reg = <0x02100000 0x40000>;
+ interrupts = <0 105 0x04 0 106 0x04>;
+ };
+
+ aipstz@0217c000 { /* AIPSTZ2 */
+ reg = <0x0217c000 0x4000>;
+ };
+
+ enet@02188000 {
+ compatible = "fsl,imx6q-fec";
+ reg = <0x02188000 0x4000>;
+ interrupts = <0 118 0x04 0 119 0x04>;
+ status = "disabled";
+ };
+
+ mlb@0218c000 {
+ reg = <0x0218c000 0x4000>;
+ interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
+ };
+
+ usdhc@02190000 { /* uSDHC1 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x02190000 0x4000>;
+ interrupts = <0 22 0x04>;
+ status = "disabled";
+ };
+
+ usdhc@02194000 { /* uSDHC2 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x02194000 0x4000>;
+ interrupts = <0 23 0x04>;
+ status = "disabled";
+ };
+
+ usdhc@02198000 { /* uSDHC3 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x02198000 0x4000>;
+ interrupts = <0 24 0x04>;
+ status = "disabled";
+ };
+
+ usdhc@0219c000 { /* uSDHC4 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x0219c000 0x4000>;
+ interrupts = <0 25 0x04>;
+ status = "disabled";
+ };
+
+ i2c@021a0000 { /* I2C1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+ reg = <0x021a0000 0x4000>;
+ interrupts = <0 36 0x04>;
+ status = "disabled";
+ };
+
+ i2c@021a4000 { /* I2C2 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+ reg = <0x021a4000 0x4000>;
+ interrupts = <0 37 0x04>;
+ status = "disabled";
+ };
+
+ i2c@021a8000 { /* I2C3 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+ reg = <0x021a8000 0x4000>;
+ interrupts = <0 38 0x04>;
+ status = "disabled";
+ };
+
+ romcp@021ac000 {
+ reg = <0x021ac000 0x4000>;
+ };
+
+ mmdc@021b0000 { /* MMDC0 */
+ compatible = "fsl,imx6q-mmdc";
+ reg = <0x021b0000 0x4000>;
+ };
+
+ mmdc@021b4000 { /* MMDC1 */
+ reg = <0x021b4000 0x4000>;
+ };
+
+ weim@021b8000 {
+ reg = <0x021b8000 0x4000>;
+ interrupts = <0 14 0x04>;
+ };
+
+ ocotp@021bc000 {
+ reg = <0x021bc000 0x4000>;
+ };
+
+ ocotp@021c0000 {
+ reg = <0x021c0000 0x4000>;
+ interrupts = <0 21 0x04>;
+ };
+
+ tzasc@021d0000 { /* TZASC1 */
+ reg = <0x021d0000 0x4000>;
+ interrupts = <0 108 0x04>;
+ };
+
+ tzasc@021d4000 { /* TZASC2 */
+ reg = <0x021d4000 0x4000>;
+ interrupts = <0 109 0x04>;
+ };
+
+ audmux@021d8000 {
+ reg = <0x021d8000 0x4000>;
+ };
+
+ mipi@021dc000 { /* MIPI-CSI */
+ reg = <0x021dc000 0x4000>;
+ };
+
+ mipi@021e0000 { /* MIPI-DSI */
+ reg = <0x021e0000 0x4000>;
+ };
+
+ vdoa@021e4000 {
+ reg = <0x021e4000 0x4000>;
+ interrupts = <0 18 0x04>;
+ };
+
+ uart1: uart@021e8000 { /* UART2 */
+ compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021e8000 0x4000>;
+ interrupts = <0 27 0x04>;
+ status = "disabled";
+ };
+
+ uart2: uart@021ec000 { /* UART3 */
+ compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021ec000 0x4000>;
+ interrupts = <0 28 0x04>;
+ status = "disabled";
+ };
+
+ uart3: uart@021f0000 { /* UART4 */
+ compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021f0000 0x4000>;
+ interrupts = <0 29 0x04>;
+ status = "disabled";
+ };
+
+ uart4: uart@021f4000 { /* UART5 */
+ compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+ reg = <0x021f4000 0x4000>;
+ interrupts = <0 30 0x04>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts
new file mode 100644
index 000000000000..15ded0deaa79
--- /dev/null
+++ b/arch/arm/boot/dts/msm8660-surf.dts
@@ -0,0 +1,24 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Qualcomm MSM8660 SURF";
+ compatible = "qcom,msm8660-surf", "qcom,msm8660";
+ interrupt-parent = <&intc>;
+
+ intc: interrupt-controller@02080000 {
+ compatible = "qcom,msm-8660-qgic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = < 0x02080000 0x1000 >,
+ < 0x02081000 0x1000 >;
+ };
+
+ serial@19c400000 {
+ compatible = "qcom,msm-hsuart", "qcom,msm-uart";
+ reg = <0x19c40000 0x1000>,
+ <0x19c00000 0x1000>;
+ interrupts = <195>;
+ };
+};
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
new file mode 100644
index 000000000000..9486be62bcdd
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap3.dtsi"
+
+/ {
+ model = "TI OMAP3 BeagleBoard";
+ compatible = "ti,omap3-beagle", "ti,omap3";
+
+ /*
+ * Since the initial device tree board file does not create any
+ * devices (MMC, network...), the only way to boot is to provide a
+ * ramdisk.
+ */
+ chosen {
+ bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug earlyprintk";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x20000000>; /* 512 MB */
+ };
+};
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
new file mode 100644
index 000000000000..d202bb5ec7ef
--- /dev/null
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -0,0 +1,63 @@
+/*
+ * Device Tree Source for OMAP3 SoC
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "ti,omap3430", "ti,omap3";
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a8";
+ };
+ };
+
+ /*
+ * The soc node represents the soc top level view. It is uses for IPs
+ * that are not memory mapped in the MPU view or for the MPU itself.
+ */
+ soc {
+ compatible = "ti,omap-infra";
+ mpu {
+ compatible = "ti,omap3-mpu";
+ ti,hwmods = "mpu";
+ };
+
+ iva {
+ compatible = "ti,iva2.2";
+ ti,hwmods = "iva";
+
+ dsp {
+ compatible = "ti,omap3-c64";
+ };
+ };
+ };
+
+ /*
+ * XXX: Use a flat representation of the OMAP3 interconnect.
+ * The real OMAP interconnect network is quite complex.
+ * Since that will not bring real advantage to represent that in DT for
+ * the moment, just use a fake OCP bus entry to represent the whole bus
+ * hierarchy.
+ */
+ ocp {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ ti,hwmods = "l3_main";
+
+ intc: interrupt-controller@1 {
+ compatible = "ti,omap3-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts
new file mode 100644
index 000000000000..c7026578ce7d
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-panda.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+ model = "TI OMAP4 PandaBoard";
+ compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4";
+
+ /*
+ * Since the initial device tree board file does not create any
+ * devices (MMC, network...), the only way to boot is to provide a
+ * ramdisk.
+ */
+ chosen {
+ bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x40000000>; /* 1 GB */
+ };
+};
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
new file mode 100644
index 000000000000..066e28c90328
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+ model = "TI OMAP4 SDP board";
+ compatible = "ti,omap4-sdp", "ti,omap4430", "ti,omap4";
+
+ /*
+ * Since the initial device tree board file does not create any
+ * devices (MMC, network...), the only way to boot is to provide a
+ * ramdisk.
+ */
+ chosen {
+ bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x40000000>; /* 1 GB */
+ };
+};
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
new file mode 100644
index 000000000000..4c61c829043a
--- /dev/null
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Carveout for multimedia usecases
+ * It should be the last 48MB of the first 512MB memory part
+ * In theory, it should not even exist. That zone should be reserved
+ * dynamically during the .reserve callback.
+ */
+/memreserve/ 0x9d000000 0x03000000;
+
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "ti,omap4430", "ti,omap4";
+ interrupt-parent = <&gic>;
+
+ aliases {
+ };
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ };
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ };
+ };
+
+ /*
+ * The soc node represents the soc top level view. It is uses for IPs
+ * that are not memory mapped in the MPU view or for the MPU itself.
+ */
+ soc {
+ compatible = "ti,omap-infra";
+ mpu {
+ compatible = "ti,omap4-mpu";
+ ti,hwmods = "mpu";
+ };
+
+ dsp {
+ compatible = "ti,omap3-c64";
+ ti,hwmods = "dsp";
+ };
+
+ iva {
+ compatible = "ti,ivahd";
+ ti,hwmods = "iva";
+ };
+ };
+
+ /*
+ * XXX: Use a flat representation of the OMAP4 interconnect.
+ * The real OMAP interconnect network is quite complex.
+ *
+ * MPU -+-- MPU_PRIVATE - GIC, L2
+ * |
+ * +----------------+----------+
+ * | | |
+ * + +- EMIF - DDR |
+ * | | |
+ * | + +--------+
+ * | | |
+ * | +- L4_ABE - AESS, MCBSP, TIMERs...
+ * | |
+ * +- L3_MAIN --+- L4_CORE - IPs...
+ * |
+ * +- L4_PER - IPs...
+ * |
+ * +- L4_CFG -+- L4_WKUP - IPs...
+ * | |
+ * | +- IPs...
+ * +- IPU ----+
+ * | |
+ * +- DSP ----+
+ * | |
+ * +- DSS ----+
+ *
+ * Since that will not bring real advantage to represent that in DT for
+ * the moment, just use a fake OCP bus entry to represent the whole bus
+ * hierarchy.
+ */
+ ocp {
+ compatible = "ti,omap4-l3-noc", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+
+ gic: interrupt-controller@48241000 {
+ compatible = "arm,cortex-a9-gic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x48241000 0x1000>,
+ <0x48240100 0x0100>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc3x2.dtsi b/arch/arm/boot/dts/picoxcell-pc3x2.dtsi
new file mode 100644
index 000000000000..f0a8c2068ea7
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc3x2.dtsi
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * 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"
+/ {
+ model = "Picochip picoXcell PC3X2";
+ compatible = "picochip,pc3x2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,1176jz-s";
+ clock-frequency = <400000000>;
+ reg = <0>;
+ d-cache-line-size = <32>;
+ d-cache-size = <32768>;
+ i-cache-line-size = <32>;
+ i-cache-size = <32768>;
+ };
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pclk: clock@0 {
+ compatible = "fixed-clock";
+ clock-outputs = "bus", "pclk";
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+ };
+
+ paxi {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x80000000 0x400000>;
+
+ emac: gem@30000 {
+ compatible = "cadence,gem";
+ reg = <0x30000 0x10000>;
+ interrupts = <31>;
+ };
+
+ dmac1: dmac@40000 {
+ compatible = "snps,dw-dmac";
+ reg = <0x40000 0x10000>;
+ interrupts = <25>;
+ };
+
+ dmac2: dmac@50000 {
+ compatible = "snps,dw-dmac";
+ reg = <0x50000 0x10000>;
+ interrupts = <26>;
+ };
+
+ vic0: interrupt-controller@60000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0x60000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ vic1: interrupt-controller@64000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0x64000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ fuse: picoxcell-fuse@80000 {
+ compatible = "picoxcell,fuse-pc3x2";
+ reg = <0x80000 0x10000>;
+ };
+
+ ssi: picoxcell-spi@90000 {
+ compatible = "picoxcell,spi";
+ reg = <0x90000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <10>;
+ };
+
+ ipsec: spacc@100000 {
+ compatible = "picochip,spacc-ipsec";
+ reg = <0x100000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <24>;
+ ref-clock = <&pclk>, "ref";
+ };
+
+ srtp: spacc@140000 {
+ compatible = "picochip,spacc-srtp";
+ reg = <0x140000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <23>;
+ };
+
+ l2_engine: spacc@180000 {
+ compatible = "picochip,spacc-l2";
+ reg = <0x180000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <22>;
+ ref-clock = <&pclk>, "ref";
+ };
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x200000 0x80000>;
+
+ rtc0: rtc@00000 {
+ compatible = "picochip,pc3x2-rtc";
+ clock-freq = <200000000>;
+ reg = <0x00000 0xf>;
+ interrupt-parent = <&vic1>;
+ interrupts = <8>;
+ };
+
+ timer0: timer@10000 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <4>;
+ clock-freq = <200000000>;
+ reg = <0x10000 0x14>;
+ };
+
+ timer1: timer@10014 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <5>;
+ clock-freq = <200000000>;
+ reg = <0x10014 0x14>;
+ };
+
+ timer2: timer@10028 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <6>;
+ clock-freq = <200000000>;
+ reg = <0x10028 0x14>;
+ };
+
+ timer3: timer@1003c {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <7>;
+ clock-freq = <200000000>;
+ reg = <0x1003c 0x14>;
+ };
+
+ gpio: gpio@20000 {
+ compatible = "snps,dw-apb-gpio";
+ reg = <0x20000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-io-width = <4>;
+
+ banka: gpio-controller@0 {
+ compatible = "snps,dw-apb-gpio-bank";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-generic,nr-gpio = <8>;
+
+ regoffset-dat = <0x50>;
+ regoffset-set = <0x00>;
+ regoffset-dirout = <0x04>;
+ };
+
+ bankb: gpio-controller@1 {
+ compatible = "snps,dw-apb-gpio-bank";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-generic,nr-gpio = <8>;
+
+ regoffset-dat = <0x54>;
+ regoffset-set = <0x0c>;
+ regoffset-dirout = <0x10>;
+ };
+ };
+
+ uart0: uart@30000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x30000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <10>;
+ clock-frequency = <3686400>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+ uart1: uart@40000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x40000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <9>;
+ clock-frequency = <3686400>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+ wdog: watchdog@50000 {
+ compatible = "snps,dw-apb-wdg";
+ reg = <0x50000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <11>;
+ bus-clock = <&pclk>, "bus";
+ };
+ };
+ };
+
+ rwid-axi {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ ebi@50000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0 0x40000000 0x08000000
+ 1 0 0x48000000 0x08000000
+ 2 0 0x50000000 0x08000000
+ 3 0 0x58000000 0x08000000>;
+ };
+
+ axi2pico@c0000000 {
+ compatible = "picochip,axi2pico-pc3x2";
+ reg = <0xc0000000 0x10000>;
+ interrupts = <13 14 15 16 17 18 19 20 21>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc3x3.dtsi b/arch/arm/boot/dts/picoxcell-pc3x3.dtsi
new file mode 100644
index 000000000000..daa962d191e6
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc3x3.dtsi
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * 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"
+/ {
+ model = "Picochip picoXcell PC3X3";
+ compatible = "picochip,pc3x3";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,1176jz-s";
+ cpu-clock = <&arm_clk>, "cpu";
+ reg = <0>;
+ d-cache-line-size = <32>;
+ d-cache-size = <32768>;
+ i-cache-line-size = <32>;
+ i-cache-size = <32768>;
+ };
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ clkgate: clkgate@800a0048 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x800a0048 4>;
+ compatible = "picochip,pc3x3-clk-gate";
+
+ tzprot_clk: clock@0 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <0>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ spi_clk: clock@1 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <1>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ dmac0_clk: clock@2 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <2>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ dmac1_clk: clock@3 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <3>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ ebi_clk: clock@4 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <4>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ ipsec_clk: clock@5 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <5>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ l2_clk: clock@6 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <6>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ trng_clk: clock@7 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <7>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ fuse_clk: clock@8 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <8>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+
+ otp_clk: clock@9 {
+ compatible = "picochip,pc3x3-gated-clk";
+ clock-outputs = "bus";
+ picochip,clk-disable-bit = <9>;
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+ };
+
+ arm_clk: clock@11 {
+ compatible = "picochip,pc3x3-pll";
+ reg = <0x800a0050 0x8>;
+ picochip,min-freq = <140000000>;
+ picochip,max-freq = <700000000>;
+ ref-clock = <&ref_clk>, "ref";
+ clock-outputs = "cpu";
+ };
+
+ pclk: clock@12 {
+ compatible = "fixed-clock";
+ clock-outputs = "bus", "pclk";
+ clock-frequency = <200000000>;
+ ref-clock = <&ref_clk>, "ref";
+ };
+ };
+
+ paxi {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x80000000 0x400000>;
+
+ emac: gem@30000 {
+ compatible = "cadence,gem";
+ reg = <0x30000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <31>;
+ };
+
+ dmac1: dmac@40000 {
+ compatible = "snps,dw-dmac";
+ reg = <0x40000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <25>;
+ };
+
+ dmac2: dmac@50000 {
+ compatible = "snps,dw-dmac";
+ reg = <0x50000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <26>;
+ };
+
+ vic0: interrupt-controller@60000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0x60000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ vic1: interrupt-controller@64000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0x64000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ fuse: picoxcell-fuse@80000 {
+ compatible = "picoxcell,fuse-pc3x3";
+ reg = <0x80000 0x10000>;
+ };
+
+ ssi: picoxcell-spi@90000 {
+ compatible = "picoxcell,spi";
+ reg = <0x90000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <10>;
+ };
+
+ ipsec: spacc@100000 {
+ compatible = "picochip,spacc-ipsec";
+ reg = <0x100000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <24>;
+ ref-clock = <&ipsec_clk>, "ref";
+ };
+
+ srtp: spacc@140000 {
+ compatible = "picochip,spacc-srtp";
+ reg = <0x140000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <23>;
+ };
+
+ l2_engine: spacc@180000 {
+ compatible = "picochip,spacc-l2";
+ reg = <0x180000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <22>;
+ ref-clock = <&l2_clk>, "ref";
+ };
+
+ apb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x200000 0x80000>;
+
+ rtc0: rtc@00000 {
+ compatible = "picochip,pc3x2-rtc";
+ clock-freq = <200000000>;
+ reg = <0x00000 0xf>;
+ interrupt-parent = <&vic0>;
+ interrupts = <8>;
+ };
+
+ timer0: timer@10000 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <4>;
+ clock-freq = <200000000>;
+ reg = <0x10000 0x14>;
+ };
+
+ timer1: timer@10014 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <5>;
+ clock-freq = <200000000>;
+ reg = <0x10014 0x14>;
+ };
+
+ gpio: gpio@20000 {
+ compatible = "snps,dw-apb-gpio";
+ reg = <0x20000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-io-width = <4>;
+
+ banka: gpio-controller@0 {
+ compatible = "snps,dw-apb-gpio-bank";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-generic,nr-gpio = <8>;
+
+ regoffset-dat = <0x50>;
+ regoffset-set = <0x00>;
+ regoffset-dirout = <0x04>;
+ };
+
+ bankb: gpio-controller@1 {
+ compatible = "snps,dw-apb-gpio-bank";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-generic,nr-gpio = <16>;
+
+ regoffset-dat = <0x54>;
+ regoffset-set = <0x0c>;
+ regoffset-dirout = <0x10>;
+ };
+
+ bankd: gpio-controller@2 {
+ compatible = "snps,dw-apb-gpio-bank";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-generic,nr-gpio = <30>;
+
+ regoffset-dat = <0x5c>;
+ regoffset-set = <0x24>;
+ regoffset-dirout = <0x28>;
+ };
+ };
+
+ uart0: uart@30000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x30000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <10>;
+ clock-frequency = <3686400>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+ uart1: uart@40000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x40000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <9>;
+ clock-frequency = <3686400>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+ wdog: watchdog@50000 {
+ compatible = "snps,dw-apb-wdg";
+ reg = <0x50000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <11>;
+ bus-clock = <&pclk>, "bus";
+ };
+
+ timer2: timer@60000 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <6>;
+ clock-freq = <200000000>;
+ reg = <0x60000 0x14>;
+ };
+
+ timer3: timer@60014 {
+ compatible = "picochip,pc3x2-timer";
+ interrupt-parent = <&vic0>;
+ interrupts = <7>;
+ clock-freq = <200000000>;
+ reg = <0x60014 0x14>;
+ };
+ };
+ };
+
+ rwid-axi {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ ebi@50000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0 0x40000000 0x08000000
+ 1 0 0x48000000 0x08000000
+ 2 0 0x50000000 0x08000000
+ 3 0 0x58000000 0x08000000>;
+ };
+
+ axi2pico@c0000000 {
+ compatible = "picochip,axi2pico-pc3x3";
+ reg = <0xc0000000 0x10000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <13 14 15 16 17 18 19 20 21>;
+ };
+
+ otp@ffff8000 {
+ compatible = "picochip,otp-pc3x3";
+ reg = <0xffff8000 0x8000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts b/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts
new file mode 100644
index 000000000000..1297414dd649
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * 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/ "picoxcell-pc3x2.dtsi"
+/ {
+ model = "Picochip PC7302 (PC3X2)";
+ compatible = "picochip,pc7302-pc3x2", "picochip,pc3x2";
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x08000000>;
+ };
+
+ chosen {
+ linux,stdout-path = &uart0;
+ };
+
+ clocks {
+ ref_clk: clock@1 {
+ compatible = "fixed-clock";
+ clock-outputs = "ref";
+ clock-frequency = <20000000>;
+ };
+ };
+
+ rwid-axi {
+ ebi@50000000 {
+ nand: gpio-nand@2,0 {
+ compatible = "gpio-control-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <2 0x0000 0x1000>;
+ bus-clock = <&pclk>, "bus";
+ gpio-control-nand,io-sync-reg =
+ <0x00000000 0x80220000>;
+
+ gpios = <&banka 1 0 /* rdy */
+ &banka 2 0 /* nce */
+ &banka 3 0 /* ale */
+ &banka 4 0 /* cle */
+ 0 /* nwp */>;
+
+ boot@100000 {
+ label = "Boot";
+ reg = <0x100000 0x80000>;
+ };
+
+ redundant-boot@200000 {
+ label = "Redundant Boot";
+ reg = <0x200000 0x80000>;
+ };
+
+ boot-env@300000 {
+ label = "Boot Evironment";
+ reg = <0x300000 0x20000>;
+ };
+
+ redundant-boot-env@320000 {
+ label = "Redundant Boot Environment";
+ reg = <0x300000 0x20000>;
+ };
+
+ kernel@380000 {
+ label = "Kernel";
+ reg = <0x380000 0x800000>;
+ };
+
+ fs@b80000 {
+ label = "File System";
+ reg = <0xb80000 0xf480000>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts b/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts
new file mode 100644
index 000000000000..9e317a4f431c
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * 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/ "picoxcell-pc3x3.dtsi"
+/ {
+ model = "Picochip PC7302 (PC3X3)";
+ compatible = "picochip,pc7302-pc3x3", "picochip,pc3x3";
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x08000000>;
+ };
+
+ chosen {
+ linux,stdout-path = &uart0;
+ };
+
+ clocks {
+ ref_clk: clock@10 {
+ compatible = "fixed-clock";
+ clock-outputs = "ref";
+ clock-frequency = <20000000>;
+ };
+
+ clkgate: clkgate@800a0048 {
+ clock@4 {
+ picochip,clk-no-disable;
+ };
+ };
+ };
+
+ rwid-axi {
+ ebi@50000000 {
+ nand: gpio-nand@2,0 {
+ compatible = "gpio-control-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <2 0x0000 0x1000>;
+ bus-clock = <&ebi_clk>, "bus";
+ gpio-control-nand,io-sync-reg =
+ <0x00000000 0x80220000>;
+
+ gpios = <&banka 1 0 /* rdy */
+ &banka 2 0 /* nce */
+ &banka 3 0 /* ale */
+ &banka 4 0 /* cle */
+ 0 /* nwp */>;
+
+ boot@100000 {
+ label = "Boot";
+ reg = <0x100000 0x80000>;
+ };
+
+ redundant-boot@200000 {
+ label = "Redundant Boot";
+ reg = <0x200000 0x80000>;
+ };
+
+ boot-env@300000 {
+ label = "Boot Evironment";
+ reg = <0x300000 0x20000>;
+ };
+
+ redundant-boot-env@320000 {
+ label = "Redundant Boot Environment";
+ reg = <0x300000 0x20000>;
+ };
+
+ kernel@380000 {
+ label = "Kernel";
+ reg = <0x380000 0x800000>;
+ };
+
+ fs@b80000 {
+ label = "File System";
+ reg = <0xb80000 0xf480000>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/prima2-cb.dts b/arch/arm/boot/dts/prima2-cb.dts
index 6fecc88065b2..34ae3a64ba25 100644
--- a/arch/arm/boot/dts/prima2-cb.dts
+++ b/arch/arm/boot/dts/prima2-cb.dts
@@ -39,9 +39,12 @@
ranges = <0x40000000 0x40000000 0x80000000>;
l2-cache-controller@80040000 {
- compatible = "arm,pl310-cache";
+ compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache";
reg = <0x80040000 0x1000>;
interrupts = <59>;
+ arm,tag-latency = <1 1 1>;
+ arm,data-latency = <1 1 1>;
+ arm,filter-ranges = <0 0x40000000>;
};
intc: interrupt-controller@80020000 {
@@ -67,6 +70,11 @@
compatible = "sirf,prima2-rstc";
reg = <0x88010000 0x1000>;
};
+
+ rsc-controller@88020000 {
+ compatible = "sirf,prima2-rsc";
+ reg = <0x88020000 0x1000>;
+ };
};
mem-iobg {
@@ -274,7 +282,7 @@
gpio: gpio-controller@b0120000 {
#gpio-cells = <2>;
#interrupt-cells = <2>;
- compatible = "sirf,prima2-gpio";
+ compatible = "sirf,prima2-gpio-pinmux";
reg = <0xb0120000 0x10000>;
gpio-controller;
interrupt-controller;
@@ -358,7 +366,7 @@
};
rtc-iobg {
- compatible = "sirf,prima2-rtciobg", "simple-bus";
+ compatible = "sirf,prima2-rtciobg", "sirf-prima2-rtciobg-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x80030000 0x10000>;
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts
index e5818668d091..0e225b86b652 100644
--- a/arch/arm/boot/dts/tegra-harmony.dts
+++ b/arch/arm/boot/dts/tegra-harmony.dts
@@ -66,5 +66,6 @@
cd-gpios = <&gpio 58 0>; /* gpio PH2 */
wp-gpios = <&gpio 59 0>; /* gpio PH3 */
power-gpios = <&gpio 70 0>; /* gpio PI6 */
+ support-8bit;
};
};
diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts
index 64cedca6fc79..a72299b8e668 100644
--- a/arch/arm/boot/dts/tegra-seaboard.dts
+++ b/arch/arm/boot/dts/tegra-seaboard.dts
@@ -25,4 +25,8 @@
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
power-gpios = <&gpio 70 0>; /* gpio PI6 */
};
+
+ sdhci@c8000600 {
+ support-8bit;
+ };
};
diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts
new file mode 100644
index 000000000000..9b29a623aaf1
--- /dev/null
+++ b/arch/arm/boot/dts/tegra-ventana.dts
@@ -0,0 +1,32 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+ model = "NVIDIA Tegra2 Ventana evaluation board";
+ compatible = "nvidia,ventana", "nvidia,tegra20";
+
+ chosen {
+ bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/ram rdinit=/sbin/init";
+ };
+
+ memory {
+ reg = < 0x00000000 0x40000000 >;
+ };
+
+ serial@70006300 {
+ clock-frequency = < 216000000 >;
+ };
+
+ sdhci@c8000400 {
+ cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+ wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+ power-gpios = <&gpio 155 0>; /* gpio PT3 */
+ };
+
+ sdhci@c8000600 {
+ power-gpios = <&gpio 70 0>; /* gpio PI6 */
+ support-8bit;
+ };
+};
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 5727595cde61..65d7e6a333eb 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -77,6 +77,14 @@
gpio-controller;
};
+ pinmux: pinmux@70000000 {
+ compatible = "nvidia,tegra20-pinmux";
+ reg = < 0x70000014 0x10 /* Tri-state registers */
+ 0x70000080 0x20 /* Mux registers */
+ 0x700000a0 0x14 /* Pull-up/down registers */
+ 0x70000868 0xa8 >; /* Pad control registers */
+ };
+
serial@70006000 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006000 0x40>;
diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts
new file mode 100644
index 000000000000..d66e2c00ac35
--- /dev/null
+++ b/arch/arm/boot/dts/usb_a9g20.dts
@@ -0,0 +1,30 @@
+/*
+ * usb_a9g20.dts - Device Tree file for Caloa USB A9G20 board
+ *
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g20.dtsi"
+
+/ {
+ model = "Calao USB A9G20";
+ compatible = "calao,usb-a9g20", "atmel,at91sam9g20", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:128k(at91bootstrap),256k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),4M(kernel),120M(rootfs),-(data) root=/dev/mtdblock5 rw rootfstype=ubifs";
+ };
+
+ memory@20000000 {
+ reg = <0x20000000 0x4000000>;
+ };
+
+ ahb {
+ apb {
+ dbgu: serial@fffff200 {
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 4b71766fb21d..74df9ca2be31 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,4 +1,5 @@
config ARM_GIC
+ select IRQ_DOMAIN
bool
config ARM_VIC
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 3227ca952a12..0e6ae470c94f 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -24,16 +24,26 @@
*/
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
#include <linux/list.h>
#include <linux/smp.h>
+#include <linux/cpu_pm.h>
#include <linux/cpumask.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>
-static DEFINE_SPINLOCK(irq_controller_lock);
+static DEFINE_RAW_SPINLOCK(irq_controller_lock);
/* Address of GIC 0 CPU interface */
void __iomem *gic_cpu_base_addr __read_mostly;
@@ -71,8 +81,7 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d)
static inline unsigned int gic_irq(struct irq_data *d)
{
- struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
- return d->irq - gic_data->irq_offset;
+ return d->hwirq;
}
/*
@@ -80,32 +89,32 @@ static inline unsigned int gic_irq(struct irq_data *d)
*/
static void gic_mask_irq(struct irq_data *d)
{
- u32 mask = 1 << (d->irq % 32);
+ u32 mask = 1 << (gic_irq(d) % 32);
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
if (gic_arch_extn.irq_mask)
gic_arch_extn.irq_mask(d);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
}
static void gic_unmask_irq(struct irq_data *d)
{
- u32 mask = 1 << (d->irq % 32);
+ u32 mask = 1 << (gic_irq(d) % 32);
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
if (gic_arch_extn.irq_unmask)
gic_arch_extn.irq_unmask(d);
writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
}
static void gic_eoi_irq(struct irq_data *d)
{
if (gic_arch_extn.irq_eoi) {
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
gic_arch_extn.irq_eoi(d);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
}
writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
@@ -129,7 +138,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
return -EINVAL;
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
if (gic_arch_extn.irq_set_type)
gic_arch_extn.irq_set_type(d, type);
@@ -154,7 +163,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
if (enabled)
writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
return 0;
}
@@ -172,7 +181,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
bool force)
{
void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
- unsigned int shift = (d->irq % 4) * 8;
+ unsigned int shift = (gic_irq(d) % 4) * 8;
unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
u32 val, mask, bit;
@@ -180,12 +189,12 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
return -EINVAL;
mask = 0xff << shift;
- bit = 1 << (cpu + shift);
+ bit = 1 << (cpu_logical_map(cpu) + shift);
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
val = readl_relaxed(reg) & ~mask;
writel_relaxed(val | bit, reg);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
return IRQ_SET_MASK_OK;
}
@@ -215,15 +224,15 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
chained_irq_enter(chip, desc);
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
gic_irq = (status & 0x3ff);
if (gic_irq == 1023)
goto out;
- cascade_irq = gic_irq + chip_data->irq_offset;
+ cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
do_bad_IRQ(cascade_irq, desc);
else
@@ -255,28 +264,26 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
irq_set_chained_handler(irq, gic_handle_cascade_irq);
}
-static void __init gic_dist_init(struct gic_chip_data *gic,
- unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic)
{
- unsigned int gic_irqs, irq_limit, i;
+ unsigned int i, irq;
+ u32 cpumask;
+ unsigned int gic_irqs = gic->gic_irqs;
+ struct irq_domain *domain = &gic->domain;
void __iomem *base = gic->dist_base;
- u32 cpumask = 1 << smp_processor_id();
+ u32 cpu = 0;
+#ifdef CONFIG_SMP
+ cpu = cpu_logical_map(smp_processor_id());
+#endif
+
+ cpumask = 1 << cpu;
cpumask |= cpumask << 8;
cpumask |= cpumask << 16;
writel_relaxed(0, base + GIC_DIST_CTRL);
/*
- * Find out how many interrupts are supported.
- * The GIC only supports up to 1020 interrupt sources.
- */
- gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
- gic_irqs = (gic_irqs + 1) * 32;
- if (gic_irqs > 1020)
- gic_irqs = 1020;
-
- /*
* Set all global interrupts to be level triggered, active low.
*/
for (i = 32; i < gic_irqs; i += 16)
@@ -302,19 +309,20 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
/*
- * Limit number of interrupts registered to the platform maximum
- */
- irq_limit = gic->irq_offset + gic_irqs;
- if (WARN_ON(irq_limit > NR_IRQS))
- irq_limit = NR_IRQS;
-
- /*
* Setup the Linux IRQ subsystem.
*/
- for (i = irq_start; i < irq_limit; i++) {
- irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
- irq_set_chip_data(i, gic);
- set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+ irq_domain_for_each_irq(domain, i, irq) {
+ if (i < 32) {
+ irq_set_percpu_devid(irq);
+ irq_set_chip_and_handler(irq, &gic_chip,
+ handle_percpu_devid_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
+ } else {
+ irq_set_chip_and_handler(irq, &gic_chip,
+ handle_fasteoi_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+ irq_set_chip_data(irq, gic);
}
writel_relaxed(1, base + GIC_DIST_CTRL);
@@ -343,23 +351,270 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
writel_relaxed(1, base + GIC_CPU_CTRL);
}
-void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
+#ifdef CONFIG_CPU_PM
+/*
+ * Saves the GIC distributor registers during suspend or idle. Must be called
+ * with interrupts disabled but before powering down the GIC. After calling
+ * this function, no interrupts will be delivered by the GIC, and another
+ * platform-specific wakeup source must be enabled.
+ */
+static void gic_dist_save(unsigned int gic_nr)
+{
+ unsigned int gic_irqs;
+ void __iomem *dist_base;
+ int i;
+
+ if (gic_nr >= MAX_GIC_NR)
+ BUG();
+
+ gic_irqs = gic_data[gic_nr].gic_irqs;
+ dist_base = gic_data[gic_nr].dist_base;
+
+ if (!dist_base)
+ return;
+
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
+ gic_data[gic_nr].saved_spi_conf[i] =
+ readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
+
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+ gic_data[gic_nr].saved_spi_target[i] =
+ readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
+
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+ gic_data[gic_nr].saved_spi_enable[i] =
+ readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+}
+
+/*
+ * Restores the GIC distributor registers during resume or when coming out of
+ * idle. Must be called before enabling interrupts. If a level interrupt
+ * that occured while the GIC was suspended is still present, it will be
+ * handled normally, but any edge interrupts that occured will not be seen by
+ * the GIC and need to be handled by the platform-specific wakeup source.
+ */
+static void gic_dist_restore(unsigned int gic_nr)
+{
+ unsigned int gic_irqs;
+ unsigned int i;
+ void __iomem *dist_base;
+
+ if (gic_nr >= MAX_GIC_NR)
+ BUG();
+
+ gic_irqs = gic_data[gic_nr].gic_irqs;
+ dist_base = gic_data[gic_nr].dist_base;
+
+ if (!dist_base)
+ return;
+
+ writel_relaxed(0, dist_base + GIC_DIST_CTRL);
+
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
+ writel_relaxed(gic_data[gic_nr].saved_spi_conf[i],
+ dist_base + GIC_DIST_CONFIG + i * 4);
+
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+ writel_relaxed(0xa0a0a0a0,
+ dist_base + GIC_DIST_PRI + i * 4);
+
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+ writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
+ dist_base + GIC_DIST_TARGET + i * 4);
+
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+ writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
+ dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+ writel_relaxed(1, dist_base + GIC_DIST_CTRL);
+}
+
+static void gic_cpu_save(unsigned int gic_nr)
+{
+ int i;
+ u32 *ptr;
+ void __iomem *dist_base;
+ void __iomem *cpu_base;
+
+ if (gic_nr >= MAX_GIC_NR)
+ BUG();
+
+ dist_base = gic_data[gic_nr].dist_base;
+ cpu_base = gic_data[gic_nr].cpu_base;
+
+ if (!dist_base || !cpu_base)
+ return;
+
+ ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
+ for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+ ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+ ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
+ for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
+ ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
+
+}
+
+static void gic_cpu_restore(unsigned int gic_nr)
+{
+ int i;
+ u32 *ptr;
+ void __iomem *dist_base;
+ void __iomem *cpu_base;
+
+ if (gic_nr >= MAX_GIC_NR)
+ BUG();
+
+ dist_base = gic_data[gic_nr].dist_base;
+ cpu_base = gic_data[gic_nr].cpu_base;
+
+ if (!dist_base || !cpu_base)
+ return;
+
+ ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
+ for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+ writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+ ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
+ for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
+ writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
+
+ for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
+ writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
+
+ writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
+ writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
+}
+
+static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v)
+{
+ int i;
+
+ for (i = 0; i < MAX_GIC_NR; i++) {
+ switch (cmd) {
+ case CPU_PM_ENTER:
+ gic_cpu_save(i);
+ break;
+ case CPU_PM_ENTER_FAILED:
+ case CPU_PM_EXIT:
+ gic_cpu_restore(i);
+ break;
+ case CPU_CLUSTER_PM_ENTER:
+ gic_dist_save(i);
+ break;
+ case CPU_CLUSTER_PM_ENTER_FAILED:
+ case CPU_CLUSTER_PM_EXIT:
+ gic_dist_restore(i);
+ break;
+ }
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block gic_notifier_block = {
+ .notifier_call = gic_notifier,
+};
+
+static void __init gic_pm_init(struct gic_chip_data *gic)
+{
+ gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
+ sizeof(u32));
+ BUG_ON(!gic->saved_ppi_enable);
+
+ gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
+ sizeof(u32));
+ BUG_ON(!gic->saved_ppi_conf);
+
+ cpu_pm_register_notifier(&gic_notifier_block);
+}
+#else
+static void __init gic_pm_init(struct gic_chip_data *gic)
+{
+}
+#endif
+
+#ifdef CONFIG_OF
+static int gic_irq_domain_dt_translate(struct irq_domain *d,
+ struct device_node *controller,
+ const u32 *intspec, unsigned int intsize,
+ unsigned long *out_hwirq, unsigned int *out_type)
+{
+ if (d->of_node != controller)
+ return -EINVAL;
+ if (intsize < 3)
+ return -EINVAL;
+
+ /* Get the interrupt number and add 16 to skip over SGIs */
+ *out_hwirq = intspec[1] + 16;
+
+ /* For SPIs, we need to add 16 more to get the GIC irq ID number */
+ if (!intspec[0])
+ *out_hwirq += 16;
+
+ *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+ return 0;
+}
+#endif
+
+const struct irq_domain_ops gic_irq_domain_ops = {
+#ifdef CONFIG_OF
+ .dt_translate = gic_irq_domain_dt_translate,
+#endif
+};
+
+void __init gic_init(unsigned int gic_nr, int irq_start,
void __iomem *dist_base, void __iomem *cpu_base)
{
struct gic_chip_data *gic;
+ struct irq_domain *domain;
+ int gic_irqs;
BUG_ON(gic_nr >= MAX_GIC_NR);
gic = &gic_data[gic_nr];
+ domain = &gic->domain;
gic->dist_base = dist_base;
gic->cpu_base = cpu_base;
- gic->irq_offset = (irq_start - 1) & ~31;
- if (gic_nr == 0)
+ /*
+ * For primary GICs, skip over SGIs.
+ * For secondary GICs, skip over PPIs, too.
+ */
+ if (gic_nr == 0) {
gic_cpu_base_addr = cpu_base;
+ domain->hwirq_base = 16;
+ if (irq_start > 0)
+ irq_start = (irq_start & ~31) + 16;
+ } else
+ domain->hwirq_base = 32;
+
+ /*
+ * Find out how many interrupts are supported.
+ * The GIC only supports up to 1020 interrupt sources.
+ */
+ gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
+ gic_irqs = (gic_irqs + 1) * 32;
+ if (gic_irqs > 1020)
+ gic_irqs = 1020;
+ gic->gic_irqs = gic_irqs;
+
+ domain->nr_irq = gic_irqs - domain->hwirq_base;
+ domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq,
+ numa_node_id());
+ if (IS_ERR_VALUE(domain->irq_base)) {
+ WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
+ irq_start);
+ domain->irq_base = irq_start;
+ }
+ domain->priv = gic;
+ domain->ops = &gic_irq_domain_ops;
+ irq_domain_add(domain);
- gic_dist_init(gic, irq_start);
+ gic_chip.flags |= gic_arch_extn.flags;
+ gic_dist_init(gic);
gic_cpu_init(gic);
+ gic_pm_init(gic);
}
void __cpuinit gic_secondary_init(unsigned int gic_nr)
@@ -369,20 +624,15 @@ void __cpuinit gic_secondary_init(unsigned int gic_nr)
gic_cpu_init(&gic_data[gic_nr]);
}
-void __cpuinit gic_enable_ppi(unsigned int irq)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- irq_set_status_flags(irq, IRQ_NOPROBE);
- gic_unmask_irq(irq_get_irq_data(irq));
- local_irq_restore(flags);
-}
-
#ifdef CONFIG_SMP
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
{
- unsigned long map = *cpus_addr(*mask);
+ int cpu;
+ unsigned long map = 0;
+
+ /* Convert our logical CPU mask into a physical one. */
+ for_each_cpu(cpu, mask)
+ map |= 1 << cpu_logical_map(cpu);
/*
* Ensure that stores to Normal memory are visible to the
@@ -394,3 +644,35 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
}
#endif
+
+#ifdef CONFIG_OF
+static int gic_cnt __initdata = 0;
+
+int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+ void __iomem *cpu_base;
+ void __iomem *dist_base;
+ int irq;
+ struct irq_domain *domain = &gic_data[gic_cnt].domain;
+
+ if (WARN_ON(!node))
+ return -ENODEV;
+
+ dist_base = of_iomap(node, 0);
+ WARN(!dist_base, "unable to map gic dist registers\n");
+
+ cpu_base = of_iomap(node, 1);
+ WARN(!cpu_base, "unable to map gic cpu registers\n");
+
+ domain->of_node = of_node_get(node);
+
+ gic_init(gic_cnt, -1, dist_base, cpu_base);
+
+ if (parent) {
+ irq = irq_of_parse_and_map(node, 0);
+ gic_cascade_irq(gic_cnt, irq);
+ }
+ gic_cnt++;
+ return 0;
+}
+#endif
diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
index 97912fa48782..7129cfbdacd6 100644
--- a/arch/arm/common/pl330.c
+++ b/arch/arm/common/pl330.c
@@ -1546,7 +1546,7 @@ int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
/* Start the next */
case PL330_OP_START:
- if (!_start(thrd))
+ if (!_thrd_active(thrd) && !_start(thrd))
ret = -EIO;
break;
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 0569de6acfba..61691cdbdcf2 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -718,6 +718,10 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
goto err_free;
}
+ ret = clk_prepare(sachip->clk);
+ if (ret)
+ goto err_clkput;
+
spin_lock_init(&sachip->lock);
sachip->dev = me;
@@ -733,7 +737,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
sachip->base = ioremap(mem->start, PAGE_SIZE * 2);
if (!sachip->base) {
ret = -ENOMEM;
- goto err_clkput;
+ goto err_clk_unprep;
}
/*
@@ -809,6 +813,8 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
err_unmap:
iounmap(sachip->base);
+ err_clk_unprep:
+ clk_unprepare(sachip->clk);
err_clkput:
clk_put(sachip->clk);
err_free:
@@ -835,6 +841,7 @@ static void __sa1111_remove(struct sa1111 *sachip)
sa1111_writel(0, irqbase + SA1111_WAKEEN1);
clk_disable(sachip->clk);
+ clk_unprepare(sachip->clk);
if (sachip->irq != NO_IRQ) {
irq_set_chained_handler(sachip->irq, NULL);
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index a07b0e763a80..1cde34a080d7 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -12,11 +12,11 @@
*/
#include <linux/device.h>
+#include <linux/gpio.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <asm/gpio.h>
#include <asm/hardware/scoop.h>
/* PCMCIA to Scoop linkage
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
index 41df47875122..2393b5bc96fa 100644
--- a/arch/arm/common/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -41,9 +41,17 @@ static long __init sp804_get_clock_rate(const char *name)
return PTR_ERR(clk);
}
+ err = clk_prepare(clk);
+ if (err) {
+ pr_err("sp804: %s clock failed to prepare: %d\n", name, err);
+ clk_put(clk);
+ return err;
+ }
+
err = clk_enable(clk);
if (err) {
pr_err("sp804: %s clock failed to enable: %d\n", name, err);
+ clk_unprepare(clk);
clk_put(clk);
return err;
}
@@ -52,6 +60,7 @@ static long __init sp804_get_clock_rate(const char *name)
if (rate < 0) {
pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate);
clk_disable(clk);
+ clk_unprepare(clk);
clk_put(clk);
}
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 197f81c77351..01f18a421b17 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -346,7 +346,8 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
/* Identify which VIC cell this one is, by reading the ID */
for (i = 0; i < 4; i++) {
- u32 addr = ((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
+ void __iomem *addr;
+ addr = (void __iomem *)((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
cellid |= (readl(addr) & 0xff) << (8 * i);
}
vendor = (cellid >> 12) & 0xff;
diff --git a/arch/arm/configs/at91sam9g45_defconfig b/arch/arm/configs/at91sam9g45_defconfig
new file mode 100644
index 000000000000..c5876d244f4b
--- /dev/null
+++ b/arch/arm/configs/at91sam9g45_defconfig
@@ -0,0 +1,214 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G45=y
+CONFIG_MACH_AT91SAM9M10G45EK=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_SLOW_CLOCK=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x71100000,25165824 root=/dev/ram0 rw"
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_CFG80211=y
+CONFIG_LIB80211=y
+CONFIG_MAC80211=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_MISC_DEVICES=y
+CONFIG_ATMEL_PWM=y
+CONFIG_ATMEL_TCLIB=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MACB=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=m
+CONFIG_RTL8187=m
+CONFIG_ATH_COMMON=m
+CONFIG_ATH9K=m
+CONFIG_CARL9170=m
+CONFIG_B43=m
+CONFIG_B43_PHY_N=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RTL8192CU=m
+CONFIG_WL1251=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+CONFIG_WL12XX_SDIO=m
+CONFIG_ZD1211RW=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=272
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_QT1070=m
+CONFIG_KEYBOARD_QT2160=m
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_FB_UDL=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_ATMEL_LCDC=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_ATMEL_AC97C=y
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ATMEL_USBA=m
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_MMC=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_SDIO_UART=m
+CONFIG_MMC_ATMELMCI=y
+CONFIG_MMC_ATMELMCI_DMA=y
+CONFIG_LEDS_ATMEL_PWM=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91RM9200=y
+CONFIG_DMADEVICES=y
+CONFIG_AT_HDMAC=y
+CONFIG_DMATEST=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+# CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/configs/exynos4_defconfig b/arch/arm/configs/exynos4_defconfig
index da53ff3b4d70..cd40bb56e568 100644
--- a/arch/arm/configs/exynos4_defconfig
+++ b/arch/arm/configs/exynos4_defconfig
@@ -11,6 +11,7 @@ CONFIG_MACH_SMDKV310=y
CONFIG_MACH_ARMLEX4210=y
CONFIG_MACH_UNIVERSAL_C210=y
CONFIG_MACH_NURI=y
+CONFIG_MACH_ORIGEN=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
diff --git a/arch/arm/configs/mx27_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index 9ad4c656c9bd..11a4192197c8 100644
--- a/arch/arm/configs/mx27_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -3,9 +3,7 @@ CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
CONFIG_PROFILING=y
@@ -17,8 +15,12 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX2=y
-CONFIG_MACH_MX27=y
+CONFIG_ARCH_IMX_V4_V5=y
+CONFIG_ARCH_MX1ADS=y
+CONFIG_MACH_SCB9328=y
+CONFIG_MACH_MX21ADS=y
+CONFIG_MACH_MX25_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX25=y
CONFIG_MACH_MX27ADS=y
CONFIG_MACH_PCM038=y
CONFIG_MACH_CPUIMX27=y
@@ -29,6 +31,7 @@ CONFIG_MACH_IMX27_VISSTRIM_M10=y
CONFIG_MACH_IMX27LITE=y
CONFIG_MACH_PCA100=y
CONFIG_MACH_MXT_TD60=y
+CONFIG_MACH_IMX27IPCAM=y
CONFIG_MXC_IRQ_PRIOR=y
CONFIG_MXC_PWM=y
CONFIG_NO_HZ=y
@@ -39,7 +42,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_FPE_NWFPE=y
CONFIG_FPE_NWFPE_XP=y
-CONFIG_PM=y
CONFIG_PM_DEBUG=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -55,8 +57,9 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_DIAG is not set
# CONFIG_IPV6 is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
@@ -69,12 +72,15 @@ CONFIG_MTD_CFI_GEOMETRY=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
CONFIG_MTD_UBI=y
+CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
-CONFIG_FEC=y
+CONFIG_SMC91X=y
+CONFIG_DM9000=y
+CONFIG_SMC911X=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT_MOUSEDEV is not set
@@ -84,10 +90,10 @@ CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ADS7846=m
# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_8250=m
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
@@ -98,19 +104,56 @@ CONFIG_W1=y
CONFIG_W1_MASTER_MXC=y
CONFIG_W1_SLAVE_THERM=y
# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13783=y
+CONFIG_REGULATOR_MC13892=y
CONFIG_FB=y
CONFIG_FB_IMX=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=m
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_MX27VIS_AIC32X4=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_USB_HID=m
+CONFIG_USB=y
# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
CONFIG_USB_ULPI=y
CONFIG_MMC=y
CONFIG_MMC_MXC=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_MC13783=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_IMXDI=y
+CONFIG_RTC_MXC=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=y
+CONFIG_IMX_DMA=y
+# CONFIG_IOMMU_SUPPORT is not set
# CONFIG_DNOTIFY is not set
# CONFIG_PROC_PAGE_MONITOR is not set
CONFIG_TMPFS=y
@@ -119,12 +162,9 @@ CONFIG_UBIFS_FS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
-CONFIG_NLS=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_850=m
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_15=m
-CONFIG_DEBUG_FS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig
index 7196ade07e27..1103f62a1964 100644
--- a/arch/arm/configs/integrator_defconfig
+++ b/arch/arm/configs/integrator_defconfig
@@ -1,5 +1,6 @@
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
+CONFIG_TINY_RCU=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
@@ -8,20 +9,29 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_ARCH_INTEGRATOR=y
CONFIG_ARCH_INTEGRATOR_AP=y
+CONFIG_ARCH_INTEGRATOR_CP=y
CONFIG_CPU_ARM720T=y
CONFIG_CPU_ARM920T=y
+CONFIG_CPU_ARM922T=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_ARM1020=y
+CONFIG_CPU_ARM1022=y
+CONFIG_CPU_ARM1026=y
CONFIG_PCI=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
CONFIG_LEDS=y
CONFIG_LEDS_CPU=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp mem=32M"
+CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp"
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -32,7 +42,6 @@ CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IPV6 is not set
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_AFS_PARTS=y
CONFIG_MTD_CHAR=y
@@ -40,6 +49,7 @@ CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
@@ -56,6 +66,8 @@ CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y
CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PL030=y
CONFIG_EXT2_FS=y
CONFIG_TMPFS=y
CONFIG_JFFS2_FS=y
@@ -68,4 +80,3 @@ CONFIG_NFSD_V3=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_ERRORS=y
diff --git a/arch/arm/configs/mx1_defconfig b/arch/arm/configs/mx1_defconfig
deleted file mode 100644
index c9436d0bf593..000000000000
--- a/arch/arm/configs/mx1_defconfig
+++ /dev/null
@@ -1,91 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX1=y
-CONFIG_ARCH_MX1ADS=y
-CONFIG_MACH_SCB9328=y
-CONFIG_MACH_APF9328=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_FW_LOADER=m
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_PHYSMAP=y
-# CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_PHYLIB=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_DM9000=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_MXC=y
-CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_IMX=y
-CONFIG_USB_ETH=m
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-# CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx21_defconfig b/arch/arm/configs/mx21_defconfig
deleted file mode 100644
index 411f88dd4402..000000000000
--- a/arch/arm/configs/mx21_defconfig
+++ /dev/null
@@ -1,97 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX2=y
-CONFIG_MACH_MX21ADS=y
-CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_NET=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FW_LOADER is not set
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=3
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_SERIO is not set
-# CONFIG_CONSOLE_TRANSLATIONS is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_IMX=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_LOGO=y
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-# CONFIG_DNOTIFY is not set
-CONFIG_MSDOS_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx3_defconfig b/arch/arm/configs/mx3_defconfig
index 7c4b30b34952..cb0717fbb03d 100644
--- a/arch/arm/configs/mx3_defconfig
+++ b/arch/arm/configs/mx3_defconfig
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_EXPERT=y
CONFIG_SLAB=y
CONFIG_MODULES=y
@@ -13,20 +12,21 @@ CONFIG_MODVERSIONS=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_ARCH_MXC=y
CONFIG_MACH_MX31ADS_WM1133_EV1=y
+CONFIG_MACH_MX31LILLY=y
+CONFIG_MACH_MX31LITE=y
CONFIG_MACH_PCM037=y
CONFIG_MACH_PCM037_EET=y
-CONFIG_MACH_MX31LITE=y
CONFIG_MACH_MX31_3DS=y
CONFIG_MACH_MX31MOBOARD=y
-CONFIG_MACH_MX31LILLY=y
CONFIG_MACH_QONG=y
-CONFIG_MACH_PCM043=y
CONFIG_MACH_ARMADILLO5X0=y
-CONFIG_MACH_MX35_3DS=y
CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_PCM043=y
+CONFIG_MACH_MX35_3DS=y
CONFIG_MACH_EUKREA_CPUIMX35=y
CONFIG_MXC_IRQ_PRIOR=y
CONFIG_MXC_PWM=y
+CONFIG_ARM_ERRATA_411920=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
@@ -35,7 +35,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
CONFIG_VFP=y
-CONFIG_PM=y
CONFIG_PM_DEBUG=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -52,7 +51,6 @@ CONFIG_IP_PNP_DHCP=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_FW_LOADER=m
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
@@ -62,24 +60,27 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_MXC=y
CONFIG_MTD_UBI=y
# CONFIG_BLK_DEV is not set
+CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_AT24=y
CONFIG_NETDEVICES=y
CONFIG_SMSC_PHY=y
CONFIG_NET_ETHERNET=y
CONFIG_SMSC911X=y
CONFIG_DNET=y
-CONFIG_FEC=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_IMX=y
+# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_8250=m
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
@@ -89,12 +90,15 @@ CONFIG_W1=y
CONFIG_W1_MASTER_MXC=y
CONFIG_W1_SLAVE_THERM=y
# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
CONFIG_MFD_WM8350_I2C=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_WM8350=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
-# CONFIG_VIDEO_ALLOW_V4L1 is not set
+# CONFIG_RC_CORE is not set
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
CONFIG_SOC_CAMERA=y
CONFIG_SOC_CAMERA_MT9M001=y
CONFIG_SOC_CAMERA_MT9M111=y
@@ -105,9 +109,26 @@ CONFIG_SOC_CAMERA_OV772X=y
CONFIG_VIDEO_MX3=y
# CONFIG_RADIO_ADAPTERS is not set
CONFIG_FB=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_MXC_SOC_WM1133_EV1=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_GADGET=m
+CONFIG_USB_FSL_USB2=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_ULPI=y
CONFIG_MMC=y
CONFIG_MMC_MXC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_MXC=y
CONFIG_DMADEVICES=y
# CONFIG_DNOTIFY is not set
CONFIG_TMPFS=y
@@ -119,6 +140,5 @@ CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx5_defconfig
index 88c5802a2351..d0d8dfece37e 100644
--- a/arch/arm/configs/mx51_defconfig
+++ b/arch/arm/configs/mx5_defconfig
@@ -1,5 +1,6 @@
CONFIG_EXPERIMENTAL=y
# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
CONFIG_SYSVIPC=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_RELAY=y
@@ -13,21 +14,29 @@ CONFIG_MODULE_SRCVERSION_ALL=y
# CONFIG_LBDAF is not set
# CONFIG_BLK_DEV_BSG is not set
CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX51=y
+CONFIG_ARCH_MX5=y
CONFIG_MACH_MX51_BABBAGE=y
CONFIG_MACH_MX51_3DS=y
CONFIG_MACH_EUKREA_CPUIMX51=y
+CONFIG_MACH_EUKREA_CPUIMX51SD=y
+CONFIG_MACH_MX51_EFIKAMX=y
+CONFIG_MACH_MX51_EFIKASB=y
+CONFIG_MACH_MX53_EVK=y
+CONFIG_MACH_MX53_SMD=y
+CONFIG_MACH_MX53_LOCO=y
+CONFIG_MACH_MX53_ARD=y
+CONFIG_MXC_PWM=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_VMSPLIT_2G=y
CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_AEABI=y
# CONFIG_OABI_COMPAT is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.0.101:/shared/nfs ip=dhcp"
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
CONFIG_VFP=y
CONFIG_NEON=y
CONFIG_BINFMT_MISC=m
-CONFIG_PM=y
CONFIG_PM_DEBUG=y
CONFIG_PM_TEST_SUSPEND=y
CONFIG_NET=y
@@ -42,13 +51,13 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_LRO is not set
# CONFIG_IPV6 is not set
# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
CONFIG_CONNECTOR=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=65536
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_MULTI_LUN=y
@@ -56,8 +65,10 @@ CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_ATA=m
+CONFIG_ATA=y
+CONFIG_PATA_IMX=y
CONFIG_NETDEVICES=y
+CONFIG_MII=m
CONFIG_MARVELL_PHY=y
CONFIG_DAVICOM_PHY=y
CONFIG_QSEMI_PHY=y
@@ -71,49 +82,57 @@ CONFIG_REALTEK_PHY=y
CONFIG_NATIONAL_PHY=y
CONFIG_STE10XP=y
CONFIG_LSI_ET1011C_PHY=y
-CONFIG_MDIO_BITBANG=y
-CONFIG_MDIO_GPIO=y
+CONFIG_MICREL_PHY=y
CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
-CONFIG_FEC=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_WLAN is not set
-CONFIG_INPUT_FF_MEMLESS=m
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
CONFIG_SERIO_SERPORT=m
CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
CONFIG_HW_RANDOM=y
CONFIG_I2C=y
# CONFIG_I2C_COMPAT is not set
-CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_HELPER_AUTO is not set
CONFIG_I2C_ALGOBIT=m
CONFIG_I2C_ALGOPCF=m
CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
-# CONFIG_HID_SUPPORT is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13892=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_MXC=y
CONFIG_USB_STORAGE=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=m
-CONFIG_MMC_SDHCI=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_MXC=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
@@ -127,7 +146,6 @@ CONFIG_EXT4_FS_SECURITY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=y
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=y
CONFIG_ISO9660_FS=m
@@ -151,17 +169,13 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_FTRACE is not set
# CONFIG_ARM_UNWIND is not set
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_CCITT=m
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index db2cb7d180dc..6ee781bf6bf1 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -26,6 +26,7 @@ CONFIG_MACH_MX23EVK=y
CONFIG_MACH_MX28EVK=y
CONFIG_MACH_STMP378X_DEVB=y
CONFIG_MACH_TX28=y
+CONFIG_MACH_M28EVK=y
# CONFIG_ARM_THUMB is not set
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index 8845f1c9925d..195729760aeb 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -25,6 +25,7 @@ CONFIG_MACH_KAEN=y
CONFIG_MACH_PAZ00=y
CONFIG_MACH_TRIMSLICE=y
CONFIG_MACH_WARIO=y
+CONFIG_MACH_VENTANA=y
CONFIG_TEGRA_DEBUG_UARTD=y
CONFIG_ARM_ERRATA_742230=y
CONFIG_NO_HZ=y
@@ -38,7 +39,6 @@ CONFIG_HIGHMEM=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_VFP=y
-CONFIG_PM=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -65,6 +65,7 @@ CONFIG_IPV6_TUNNEL=y
CONFIG_IPV6_MULTIPLE_TABLES=y
# CONFIG_WIRELESS is not set
# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_MISC_DEVICES=y
CONFIG_AD525X_DPOT=y
@@ -72,34 +73,61 @@ CONFIG_AD525X_DPOT_I2C=y
CONFIG_ICS932S401=y
CONFIG_APDS9802ALS=y
CONFIG_ISL29003=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_NET_ETHERNET=y
CONFIG_R8169=y
# CONFIG_NETDEV_10000 is not set
# CONFIG_WLAN is not set
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
# CONFIG_I2C_COMPAT is not set
# CONFIG_I2C_HELPER_AUTO is not set
CONFIG_I2C_TEGRA=y
+CONFIG_SPI=y
+CONFIG_SPI_TEGRA=y
CONFIG_SENSORS_LM90=y
CONFIG_MFD_TPS6586X=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_TPS6586X=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_WM8903=y
+CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_STORAGE=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_TEGRA=y
CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
CONFIG_IIO=y
CONFIG_SENSORS_ISL29018=y
CONFIG_SENSORS_AK8975=y
@@ -123,18 +151,15 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
CONFIG_DEBUG_SLAB=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_VM=y
CONFIG_DEBUG_SG=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_DEBUG_LL=y
CONFIG_EARLY_PRINTK=y
CONFIG_CRYPTO_ECB=y
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 6550db3aa5c7..960abceb8e14 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -1,3 +1,20 @@
include include/asm-generic/Kbuild.asm
header-y += hwcap.h
+
+generic-y += auxvec.h
+generic-y += bitsperlong.h
+generic-y += cputime.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += ioctl.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += resource.h
+generic-y += sections.h
+generic-y += siginfo.h
+generic-y += sizes.h
diff --git a/arch/arm/include/asm/auxvec.h b/arch/arm/include/asm/auxvec.h
deleted file mode 100644
index c0536f6b29a7..000000000000
--- a/arch/arm/include/asm/auxvec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMARM_AUXVEC_H
-#define __ASMARM_AUXVEC_H
-
-#endif
diff --git a/arch/arm/include/asm/bitsperlong.h b/arch/arm/include/asm/bitsperlong.h
deleted file mode 100644
index 6dc0bb0c13b2..000000000000
--- a/arch/arm/include/asm/bitsperlong.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff --git a/arch/arm/include/asm/bug.h b/arch/arm/include/asm/bug.h
index 4d88425a4169..9abe7a07d5ac 100644
--- a/arch/arm/include/asm/bug.h
+++ b/arch/arm/include/asm/bug.h
@@ -3,21 +3,58 @@
#ifdef CONFIG_BUG
-#ifdef CONFIG_DEBUG_BUGVERBOSE
-extern void __bug(const char *file, int line) __attribute__((noreturn));
-
-/* give file/line information */
-#define BUG() __bug(__FILE__, __LINE__)
+/*
+ * Use a suitable undefined instruction to use for ARM/Thumb2 bug handling.
+ * We need to be careful not to conflict with those used by other modules and
+ * the register_undef_hook() system.
+ */
+#ifdef CONFIG_THUMB2_KERNEL
+#define BUG_INSTR_VALUE 0xde02
+#define BUG_INSTR_TYPE ".hword "
#else
+#define BUG_INSTR_VALUE 0xe7f001f2
+#define BUG_INSTR_TYPE ".word "
+#endif
-/* this just causes an oops */
-#define BUG() do { *(int *)0 = 0; } while (1)
-#endif
+#define BUG() _BUG(__FILE__, __LINE__, BUG_INSTR_VALUE)
+#define _BUG(file, line, value) __BUG(file, line, value)
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+
+/*
+ * The extra indirection is to ensure that the __FILE__ string comes through
+ * OK. Many version of gcc do not support the asm %c parameter which would be
+ * preferable to this unpleasantness. We use mergeable string sections to
+ * avoid multiple copies of the string appearing in the kernel image.
+ */
+
+#define __BUG(__file, __line, __value) \
+do { \
+ BUILD_BUG_ON(sizeof(struct bug_entry) != 12); \
+ asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n" \
+ ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \
+ "2:\t.asciz " #__file "\n" \
+ ".popsection\n" \
+ ".pushsection __bug_table,\"a\"\n" \
+ "3:\t.word 1b, 2b\n" \
+ "\t.hword " #__line ", 0\n" \
+ ".popsection"); \
+ unreachable(); \
+} while (0)
+
+#else /* not CONFIG_DEBUG_BUGVERBOSE */
+
+#define __BUG(__file, __line, __value) \
+do { \
+ asm volatile(BUG_INSTR_TYPE #__value); \
+ unreachable(); \
+} while (0)
+#endif /* CONFIG_DEBUG_BUGVERBOSE */
#define HAVE_ARCH_BUG
-#endif
+#endif /* CONFIG_BUG */
#include <asm-generic/bug.h>
diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h
index c023db09fcc1..7ea78144ae22 100644
--- a/arch/arm/include/asm/cachetype.h
+++ b/arch/arm/include/asm/cachetype.h
@@ -7,6 +7,7 @@
#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
#define CACHEID_ASID_TAGGED (1 << 3)
#define CACHEID_VIPT_I_ALIASING (1 << 4)
+#define CACHEID_PIPT (1 << 5)
extern unsigned int cacheid;
@@ -16,6 +17,7 @@ extern unsigned int cacheid;
#define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING)
#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED)
#define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING)
+#define icache_is_pipt() cacheid_is(CACHEID_PIPT)
/*
* __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
@@ -26,7 +28,8 @@ extern unsigned int cacheid;
#if __LINUX_ARM_ARCH__ >= 7
#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\
CACHEID_ASID_TAGGED |\
- CACHEID_VIPT_I_ALIASING)
+ CACHEID_VIPT_I_ALIASING |\
+ CACHEID_PIPT)
#elif __LINUX_ARM_ARCH__ >= 6
#define __CACHEID_ARCH_MIN (~CACHEID_VIVT)
#else
diff --git a/arch/arm/include/asm/cputime.h b/arch/arm/include/asm/cputime.h
deleted file mode 100644
index 3a8002a5fec7..000000000000
--- a/arch/arm/include/asm/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ARM_CPUTIME_H
-#define __ARM_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __ARM_CPUTIME_H */
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index cd4458f64171..cb47d28cbe1f 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -8,6 +8,7 @@
#define CPUID_CACHETYPE 1
#define CPUID_TCM 2
#define CPUID_TLBTYPE 3
+#define CPUID_MPIDR 5
#define CPUID_EXT_PFR0 "c1, 0"
#define CPUID_EXT_PFR1 "c1, 1"
@@ -70,6 +71,11 @@ static inline unsigned int __attribute_const__ read_cpuid_tcmstatus(void)
return read_cpuid(CPUID_TCM);
}
+static inline unsigned int __attribute_const__ read_cpuid_mpidr(void)
+{
+ return read_cpuid(CPUID_MPIDR);
+}
+
/*
* Intel's XScale3 core supports some v6 features (supersections, L2)
* but advertises itself as v5 as it does not support the v6 ISA. For
diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h
index 9f390ce335cb..7aa368003b05 100644
--- a/arch/arm/include/asm/device.h
+++ b/arch/arm/include/asm/device.h
@@ -10,9 +10,17 @@ struct dev_archdata {
#ifdef CONFIG_DMABOUNCE
struct dmabounce_device_info *dmabounce;
#endif
+#ifdef CONFIG_IOMMU_API
+ void *iommu; /* private IOMMU data */
+#endif
};
+struct omap_device;
+
struct pdev_archdata {
+#ifdef CONFIG_ARCH_OMAP
+ struct omap_device *od;
+#endif
};
#endif
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 7a21d0bf7134..cb3b7c981c4b 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -32,7 +32,7 @@ static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
{
- return (void *)__bus_to_virt(addr);
+ return (void *)__bus_to_virt((unsigned long)addr);
}
static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
@@ -205,6 +205,13 @@ extern void *dma_alloc_writecombine(struct device *, size_t, dma_addr_t *,
int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
void *, dma_addr_t, size_t);
+/*
+ * This can be called during boot to increase the size of the consistent
+ * DMA region above it's default value of 2MB. It must be called before the
+ * memory allocator is initialised, i.e. before any core_initcall.
+ */
+extern void __init init_consistent_dma_size(unsigned long size);
+
#ifdef CONFIG_DMABOUNCE
/*
diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h
index 628670e9d7c9..69a5b0b6455c 100644
--- a/arch/arm/include/asm/dma.h
+++ b/arch/arm/include/asm/dma.h
@@ -34,18 +34,18 @@
#define DMA_MODE_CASCADE 0xc0
#define DMA_AUTOINIT 0x10
-extern spinlock_t dma_spin_lock;
+extern raw_spinlock_t dma_spin_lock;
static inline unsigned long claim_dma_lock(void)
{
unsigned long flags;
- spin_lock_irqsave(&dma_spin_lock, flags);
+ raw_spin_lock_irqsave(&dma_spin_lock, flags);
return flags;
}
static inline void release_dma_lock(unsigned long flags)
{
- spin_unlock_irqrestore(&dma_spin_lock, flags);
+ raw_spin_unlock_irqrestore(&dma_spin_lock, flags);
}
/* Clear the 'DMA Pointer Flip Flop'.
diff --git a/arch/arm/include/asm/ecard.h b/arch/arm/include/asm/ecard.h
index 29f2610efc70..eaea14676d57 100644
--- a/arch/arm/include/asm/ecard.h
+++ b/arch/arm/include/asm/ecard.h
@@ -161,7 +161,6 @@ struct expansion_card {
/* Private internal data */
const char *card_desc; /* Card description */
- CONST unsigned int podaddr; /* Base Linux address for card */
CONST loader_t loader; /* loader program */
u64 dma_mask;
};
diff --git a/arch/arm/include/asm/emergency-restart.h b/arch/arm/include/asm/emergency-restart.h
deleted file mode 100644
index 108d8c48e42e..000000000000
--- a/arch/arm/include/asm/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
index 2f1e2098dfe7..88d61815f0c0 100644
--- a/arch/arm/include/asm/entry-macro-multi.S
+++ b/arch/arm/include/asm/entry-macro-multi.S
@@ -25,13 +25,6 @@
movne r1, sp
adrne lr, BSYM(1b)
bne do_IPI
-
-#ifdef CONFIG_LOCAL_TIMERS
- test_for_ltirq r0, r2, r6, lr
- movne r0, sp
- adrne lr, BSYM(1b)
- bne do_local_timer
-#endif
#endif
9997:
.endm
diff --git a/arch/arm/include/asm/errno.h b/arch/arm/include/asm/errno.h
deleted file mode 100644
index 6e60f0612bb6..000000000000
--- a/arch/arm/include/asm/errno.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ARM_ERRNO_H
-#define _ARM_ERRNO_H
-
-#include <asm-generic/errno.h>
-
-#endif
diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h
new file mode 100644
index 000000000000..5abaf5bbd985
--- /dev/null
+++ b/arch/arm/include/asm/exception.h
@@ -0,0 +1,19 @@
+/*
+ * Annotations for marking C functions as exception handlers.
+ *
+ * These should only be used for C functions that are called from the low
+ * level exception entry code and not any intervening C code.
+ */
+#ifndef __ASM_ARM_EXCEPTION_H
+#define __ASM_ARM_EXCEPTION_H
+
+#include <linux/ftrace.h>
+
+#define __exception __attribute__((section(".exception.text")))
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#define __exception_irq_entry __irq_entry
+#else
+#define __exception_irq_entry __exception
+#endif
+
+#endif /* __ASM_ARM_EXCEPTION_H */
diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h
index 166a7a3e2840..11ad0bfbb0ad 100644
--- a/arch/arm/include/asm/gpio.h
+++ b/arch/arm/include/asm/gpio.h
@@ -4,4 +4,23 @@
/* not all ARM platforms necessarily support this API ... */
#include <mach/gpio.h>
+#ifndef __ARM_GPIOLIB_COMPLEX
+/* Note: this may rely upon the value of ARCH_NR_GPIOS set in mach/gpio.h */
+#include <asm-generic/gpio.h>
+
+/* The trivial gpiolib dispatchers */
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep __gpio_cansleep
+#endif
+
+/*
+ * Provide a default gpio_to_irq() which should satisfy every case.
+ * However, some platforms want to do this differently, so allow them
+ * to override it.
+ */
+#ifndef gpio_to_irq
+#define gpio_to_irq __gpio_to_irq
+#endif
+
#endif /* _ARCH_ARM_GPIO_H */
diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h
index 89ad1805e579..ddf07a92a6c8 100644
--- a/arch/arm/include/asm/hardirq.h
+++ b/arch/arm/include/asm/hardirq.h
@@ -9,9 +9,6 @@
typedef struct {
unsigned int __softirq_pending;
-#ifdef CONFIG_LOCAL_TIMERS
- unsigned int local_timer_irqs;
-#endif
#ifdef CONFIG_SMP
unsigned int ipi_irqs[NR_IPI];
#endif
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index 99a6ed7e1bfd..1db1143a9483 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -52,6 +52,8 @@
#define L2X0_LOCKDOWN_WAY_D_BASE 0x900
#define L2X0_LOCKDOWN_WAY_I_BASE 0x904
#define L2X0_LOCKDOWN_STRIDE 0x08
+#define L2X0_ADDR_FILTER_START 0xC00
+#define L2X0_ADDR_FILTER_END 0xC04
#define L2X0_TEST_OPERATION 0xF00
#define L2X0_LINE_DATA 0xF10
#define L2X0_LINE_TAG 0xF30
@@ -65,8 +67,23 @@
#define L2X0_CACHE_ID_PART_MASK (0xf << 6)
#define L2X0_CACHE_ID_PART_L210 (1 << 6)
#define L2X0_CACHE_ID_PART_L310 (3 << 6)
+#define L2X0_CACHE_ID_RTL_MASK 0x3f
+#define L2X0_CACHE_ID_RTL_R0P0 0x0
+#define L2X0_CACHE_ID_RTL_R1P0 0x2
+#define L2X0_CACHE_ID_RTL_R2P0 0x4
+#define L2X0_CACHE_ID_RTL_R3P0 0x5
+#define L2X0_CACHE_ID_RTL_R3P1 0x6
+#define L2X0_CACHE_ID_RTL_R3P2 0x8
#define L2X0_AUX_CTRL_MASK 0xc0000fff
+#define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0
+#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK 0x7
+#define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT 3
+#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (0x7 << 3)
+#define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT 6
+#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (0x7 << 6)
+#define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT 9
+#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (0x7 << 9)
#define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT 16
#define L2X0_AUX_CTRL_WAY_SIZE_SHIFT 17
#define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x7 << 17)
@@ -77,8 +94,40 @@
#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29
#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30
+#define L2X0_LATENCY_CTRL_SETUP_SHIFT 0
+#define L2X0_LATENCY_CTRL_RD_SHIFT 4
+#define L2X0_LATENCY_CTRL_WR_SHIFT 8
+
+#define L2X0_ADDR_FILTER_EN 1
+
#ifndef __ASSEMBLY__
extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
+#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
+extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask);
+#else
+static inline int l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+{
+ return -ENODEV;
+}
#endif
+struct l2x0_regs {
+ unsigned long phy_base;
+ unsigned long aux_ctrl;
+ /*
+ * Whether the following registers need to be saved/restored
+ * depends on platform
+ */
+ unsigned long tag_latency;
+ unsigned long data_latency;
+ unsigned long filter_start;
+ unsigned long filter_end;
+ unsigned long prefetch_ctrl;
+ unsigned long pwr_ctrl;
+};
+
+extern struct l2x0_regs l2x0_saved_regs;
+
+#endif /* __ASSEMBLY__ */
+
#endif
diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S
index c115b82fe80a..74ebc803904d 100644
--- a/arch/arm/include/asm/hardware/entry-macro-gic.S
+++ b/arch/arm/include/asm/hardware/entry-macro-gic.S
@@ -22,15 +22,11 @@
* interrupt controller spec. To wit:
*
* Interrupts 0-15 are IPI
- * 16-28 are reserved
- * 29-31 are local. We allow 30 to be used for the watchdog.
+ * 16-31 are local. We allow 30 to be used for the watchdog.
* 32-1020 are global
* 1021-1022 are reserved
* 1023 is "spurious" (no interrupt)
*
- * For now, we ignore all local interrupts so only return an interrupt if it's
- * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
- *
* A simple read from the controller will tell us the number of the highest
* priority enabled interrupt. We then just need to check whether it is in the
* valid range for an IRQ (30-1020 inclusive).
@@ -43,7 +39,7 @@
ldr \tmp, =1021
bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #29
+ cmp \irqnr, #15
cmpcc \irqnr, \irqnr
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
@@ -62,14 +58,3 @@
strcc \irqstat, [\base, #GIC_CPU_EOI]
cmpcs \irqnr, \irqnr
.endm
-
-/* As above, this assumes that irqstat and base are preserved.. */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #29
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 435d3f86c708..3e91f22046f5 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,19 +33,32 @@
#define GIC_DIST_SOFTINT 0xf00
#ifndef __ASSEMBLY__
+#include <linux/irqdomain.h>
+struct device_node;
+
extern void __iomem *gic_cpu_base_addr;
extern struct irq_chip gic_arch_extn;
-void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+void gic_init(unsigned int, int, void __iomem *, void __iomem *);
+int gic_of_init(struct device_node *node, struct device_node *parent);
void gic_secondary_init(unsigned int);
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
-void gic_enable_ppi(unsigned int);
struct gic_chip_data {
- unsigned int irq_offset;
void __iomem *dist_base;
void __iomem *cpu_base;
+#ifdef CONFIG_CPU_PM
+ u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
+ u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
+ u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
+ u32 __percpu *saved_ppi_enable;
+ u32 __percpu *saved_ppi_conf;
+#endif
+#ifdef CONFIG_IRQ_DOMAIN
+ struct irq_domain domain;
+#endif
+ unsigned int gic_irqs;
};
#endif
diff --git a/arch/arm/include/asm/hardware/iop3xx-gpio.h b/arch/arm/include/asm/hardware/iop3xx-gpio.h
index b69d972b1f7d..9eda7dc92ad8 100644
--- a/arch/arm/include/asm/hardware/iop3xx-gpio.h
+++ b/arch/arm/include/asm/hardware/iop3xx-gpio.h
@@ -28,6 +28,8 @@
#include <mach/hardware.h>
#include <asm-generic/gpio.h>
+#define __ARM_GPIOLIB_COMPLEX
+
#define IOP3XX_N_GPIOS 8
static inline int gpio_get_value(unsigned gpio)
diff --git a/arch/arm/include/asm/hardware/it8152.h b/arch/arm/include/asm/hardware/it8152.h
index b3fea38d55c6..43cab498bc27 100644
--- a/arch/arm/include/asm/hardware/it8152.h
+++ b/arch/arm/include/asm/hardware/it8152.h
@@ -9,7 +9,7 @@
#ifndef __ASM_HARDWARE_IT8152_H
#define __ASM_HARDWARE_IT8152_H
-extern unsigned long it8152_base_address;
+extern void __iomem *it8152_base_address;
#define IT8152_IO_BASE (it8152_base_address + 0x03e00000)
#define IT8152_CFGREG_BASE (it8152_base_address + 0x03f00000)
diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h
index f389b2704d82..c190bc992f0e 100644
--- a/arch/arm/include/asm/hw_breakpoint.h
+++ b/arch/arm/include/asm/hw_breakpoint.h
@@ -50,6 +50,7 @@ static inline void decode_ctrl_reg(u32 reg,
#define ARM_DEBUG_ARCH_V6_1 2
#define ARM_DEBUG_ARCH_V7_ECP14 3
#define ARM_DEBUG_ARCH_V7_MM 4
+#define ARM_DEBUG_ARCH_V7_1 5
/* Breakpoint */
#define ARM_BREAKPOINT_EXECUTE 0
@@ -57,6 +58,7 @@ static inline void decode_ctrl_reg(u32 reg,
/* Watchpoints */
#define ARM_BREAKPOINT_LOAD 1
#define ARM_BREAKPOINT_STORE 2
+#define ARM_FSR_ACCESS_MASK (1 << 11)
/* Privilege Levels */
#define ARM_BREAKPOINT_PRIV 1
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index d66605dea55a..065d100fa63e 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -80,6 +80,7 @@ extern void __iomem *__arm_ioremap_caller(unsigned long, size_t, unsigned int,
extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int);
+extern void __iomem *__arm_ioremap_exec(unsigned long, size_t, bool cached);
extern void __iounmap(volatile void __iomem *addr);
/*
@@ -110,6 +111,27 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
#include <mach/io.h>
/*
+ * This is the limit of PC card/PCI/ISA IO space, which is by default
+ * 64K if we have PC card, PCI or ISA support. Otherwise, default to
+ * zero to prevent ISA/PCI drivers claiming IO space (and potentially
+ * oopsing.)
+ *
+ * Only set this larger if you really need inb() et.al. to operate over
+ * a larger address space. Note that SOC_COMMON ioremaps each sockets
+ * IO space area, and so inb() et.al. must be defined to operate as per
+ * readb() et.al. on such platforms.
+ */
+#ifndef IO_SPACE_LIMIT
+#if defined(CONFIG_PCMCIA_SOC_COMMON) || defined(CONFIG_PCMCIA_SOC_COMMON_MODULE)
+#define IO_SPACE_LIMIT ((resource_size_t)0xffffffff)
+#elif defined(CONFIG_PCI) || defined(CONFIG_ISA) || defined(CONFIG_PCCARD)
+#define IO_SPACE_LIMIT ((resource_size_t)0xffff)
+#else
+#define IO_SPACE_LIMIT ((resource_size_t)0)
+#endif
+#endif
+
+/*
* IO port access primitives
* -------------------------
*
@@ -189,11 +211,11 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
* IO port primitives for more information.
*/
#ifdef __mem_pci
-#define readb_relaxed(c) ({ u8 __v = __raw_readb(__mem_pci(c)); __v; })
-#define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16) \
- __raw_readw(__mem_pci(c))); __v; })
-#define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32) \
- __raw_readl(__mem_pci(c))); __v; })
+#define readb_relaxed(c) ({ u8 __r = __raw_readb(__mem_pci(c)); __r; })
+#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
+ __raw_readw(__mem_pci(c))); __r; })
+#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
+ __raw_readl(__mem_pci(c))); __r; })
#define writeb_relaxed(v,c) ((void)__raw_writeb(v,__mem_pci(c)))
#define writew_relaxed(v,c) ((void)__raw_writew((__force u16) \
@@ -238,7 +260,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
* ioremap and friends.
*
* ioremap takes a PCI memory address, as specified in
- * Documentation/IO-mapping.txt.
+ * Documentation/io-mapping.txt.
*
*/
#ifndef __arch_ioremap
@@ -260,10 +282,16 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
#define ioread16(p) ({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; })
#define ioread32(p) ({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; })
+#define ioread16be(p) ({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
+#define ioread32be(p) ({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
+
#define iowrite8(v,p) ({ __iowmb(); (void)__raw_writeb(v, p); })
#define iowrite16(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_le16(v), p); })
#define iowrite32(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_le32(v), p); })
+#define iowrite16be(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_be16(v), p); })
+#define iowrite32be(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_be32(v), p); })
+
#define ioread8_rep(p,d,c) __raw_readsb(p,d,c)
#define ioread16_rep(p,d,c) __raw_readsw(p,d,c)
#define ioread32_rep(p,d,c) __raw_readsl(p,d,c)
diff --git a/arch/arm/include/asm/ioctl.h b/arch/arm/include/asm/ioctl.h
deleted file mode 100644
index b279fe06dfe5..000000000000
--- a/arch/arm/include/asm/ioctl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/arm/include/asm/irq_regs.h b/arch/arm/include/asm/irq_regs.h
deleted file mode 100644
index 3dd9c0b70270..000000000000
--- a/arch/arm/include/asm/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/arm/include/asm/kdebug.h b/arch/arm/include/asm/kdebug.h
deleted file mode 100644
index 6ece1b037665..000000000000
--- a/arch/arm/include/asm/kdebug.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/arm/include/asm/local.h b/arch/arm/include/asm/local.h
deleted file mode 100644
index c11c530f74d0..000000000000
--- a/arch/arm/include/asm/local.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff --git a/arch/arm/include/asm/local64.h b/arch/arm/include/asm/local64.h
deleted file mode 100644
index 36c93b5cc239..000000000000
--- a/arch/arm/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
index ff66638ff54d..c6a18424888e 100644
--- a/arch/arm/include/asm/localtimer.h
+++ b/arch/arm/include/asm/localtimer.h
@@ -11,6 +11,7 @@
#define __ASM_ARM_LOCALTIMER_H
#include <linux/errno.h>
+#include <linux/interrupt.h>
struct clock_event_device;
@@ -19,27 +20,20 @@ struct clock_event_device;
*/
void percpu_timer_setup(void);
-/*
- * Called from assembly, this is the local timer IRQ handler
- */
-asmlinkage void do_local_timer(struct pt_regs *);
-
-
#ifdef CONFIG_LOCAL_TIMERS
#ifdef CONFIG_HAVE_ARM_TWD
#include "smp_twd.h"
-#define local_timer_ack() twd_timer_ack()
+#define local_timer_stop(c) twd_timer_stop((c))
#else
/*
- * Platform provides this to acknowledge a local timer IRQ.
- * Returns true if the local timer IRQ is to be processed.
+ * Stop the local timer
*/
-int local_timer_ack(void);
+void local_timer_stop(struct clock_event_device *);
#endif
@@ -54,6 +48,10 @@ static inline int local_timer_setup(struct clock_event_device *evt)
{
return -ENXIO;
}
+
+static inline void local_timer_stop(struct clock_event_device *evt)
+{
+}
#endif
#endif
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 217aa1911dd7..7d19425dd496 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -17,7 +17,7 @@ struct sys_timer;
struct machine_desc {
unsigned int nr; /* architecture number */
const char *name; /* architecture name */
- unsigned long boot_params; /* tagged list */
+ unsigned long atag_offset; /* tagged list (relative) */
const char **dt_compat; /* array of device tree
* 'compatible' strings */
@@ -34,8 +34,7 @@ struct machine_desc {
unsigned int reserve_lp1 :1; /* never has lp1 */
unsigned int reserve_lp2 :1; /* never has lp2 */
unsigned int soft_reboot :1; /* soft reboot */
- void (*fixup)(struct machine_desc *,
- struct tag *, char **,
+ void (*fixup)(struct tag *, char **,
struct meminfo *);
void (*reserve)(void);/* reserve mem blocks */
void (*map_io)(void);/* IO mapping function */
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index d2fedb5aeb1f..b36f3654bf54 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -29,6 +29,7 @@ struct map_desc {
#define MT_MEMORY_NONCACHED 11
#define MT_MEMORY_DTCM 12
#define MT_MEMORY_ITCM 13
+#define MT_MEMORY_SO 14
#ifdef CONFIG_MMU
extern void iotable_init(struct map_desc *, int);
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index b8de516e600e..a8997d71084e 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -16,9 +16,12 @@
#include <linux/compiler.h>
#include <linux/const.h>
#include <linux/types.h>
-#include <mach/memory.h>
#include <asm/sizes.h>
+#ifdef CONFIG_NEED_MACH_MEMORY_H
+#include <mach/memory.h>
+#endif
+
/*
* Allow for constants defined here to be used from assembly code
* by prepending the UL suffix only with actual C code compilation.
@@ -77,16 +80,7 @@
*/
#define IOREMAP_MAX_ORDER 24
-/*
- * Size of DMA-consistent memory region. Must be multiple of 2M,
- * between 2MB and 14MB inclusive.
- */
-#ifndef CONSISTENT_DMA_SIZE
-#define CONSISTENT_DMA_SIZE SZ_2M
-#endif
-
#define CONSISTENT_END (0xffe00000UL)
-#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE)
#else /* CONFIG_MMU */
@@ -160,7 +154,6 @@
* so that all we need to do is modify the 8-bit constant field.
*/
#define __PV_BITS_31_24 0x81000000
-#define __PV_BITS_23_16 0x00810000
extern unsigned long __pv_phys_offset;
#define PHYS_OFFSET __pv_phys_offset
@@ -178,9 +171,6 @@ static inline unsigned long __virt_to_phys(unsigned long x)
{
unsigned long t;
__pv_stub(x, t, "add", __PV_BITS_31_24);
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
- __pv_stub(t, t, "add", __PV_BITS_23_16);
-#endif
return t;
}
@@ -188,9 +178,6 @@ static inline unsigned long __phys_to_virt(unsigned long x)
{
unsigned long t;
__pv_stub(x, t, "sub", __PV_BITS_31_24);
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
- __pv_stub(t, t, "sub", __PV_BITS_23_16);
-#endif
return t;
}
#else
@@ -200,7 +187,11 @@ static inline unsigned long __phys_to_virt(unsigned long x)
#endif
#ifndef PHYS_OFFSET
+#ifdef PLAT_PHYS_OFFSET
#define PHYS_OFFSET PLAT_PHYS_OFFSET
+#else
+#define PHYS_OFFSET UL(CONFIG_PHYS_OFFSET)
+#endif
#endif
/*
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index b4ffe9d5b526..14965658a923 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -6,7 +6,7 @@
typedef struct {
#ifdef CONFIG_CPU_HAS_ASID
unsigned int id;
- spinlock_t id_lock;
+ raw_spinlock_t id_lock;
#endif
unsigned int kvm_seq;
} mm_context_t;
@@ -16,7 +16,7 @@ typedef struct {
/* init_mm.context.id_lock should be initialized. */
#define INIT_MM_CONTEXT(name) \
- .context.id_lock = __SPIN_LOCK_UNLOCKED(name.context.id_lock),
+ .context.id_lock = __RAW_SPIN_LOCK_UNLOCKED(name.context.id_lock),
#else
#define ASID(mm) (0)
#endif
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index 543b44916d2c..6c6809f982f1 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -31,11 +31,7 @@ struct mod_arch_specific {
/* Add __virt_to_phys patching state as well */
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
-#define MODULE_ARCH_VERMAGIC_P2V "p2v16 "
-#else
#define MODULE_ARCH_VERMAGIC_P2V "p2v8 "
-#endif
#else
#define MODULE_ARCH_VERMAGIC_P2V ""
#endif
diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h
index d8387437ec5a..53426c66352a 100644
--- a/arch/arm/include/asm/outercache.h
+++ b/arch/arm/include/asm/outercache.h
@@ -34,6 +34,7 @@ struct outer_cache_fns {
void (*sync)(void);
#endif
void (*set_debug)(unsigned long);
+ void (*resume)(void);
};
#ifdef CONFIG_OUTER_CACHE
@@ -74,6 +75,12 @@ static inline void outer_disable(void)
outer_cache.disable();
}
+static inline void outer_resume(void)
+{
+ if (outer_cache.resume)
+ outer_cache.resume();
+}
+
#else
static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
index ac75d0848889..ca94653f1ecb 100644
--- a/arch/arm/include/asm/page.h
+++ b/arch/arm/include/asm/page.h
@@ -151,47 +151,7 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
extern void copy_page(void *to, const void *from);
-typedef unsigned long pteval_t;
-
-#undef STRICT_MM_TYPECHECKS
-
-#ifdef STRICT_MM_TYPECHECKS
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { pteval_t pte; } pte_t;
-typedef struct { unsigned long pmd; } pmd_t;
-typedef struct { unsigned long pgd[2]; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-
-#define pte_val(x) ((x).pte)
-#define pmd_val(x) ((x).pmd)
-#define pgd_val(x) ((x).pgd[0])
-#define pgprot_val(x) ((x).pgprot)
-
-#define __pte(x) ((pte_t) { (x) } )
-#define __pmd(x) ((pmd_t) { (x) } )
-#define __pgprot(x) ((pgprot_t) { (x) } )
-
-#else
-/*
- * .. while these make it easier on the compiler
- */
-typedef pteval_t pte_t;
-typedef unsigned long pmd_t;
-typedef unsigned long pgd_t[2];
-typedef unsigned long pgprot_t;
-
-#define pte_val(x) (x)
-#define pmd_val(x) (x)
-#define pgd_val(x) ((x)[0])
-#define pgprot_val(x) (x)
-
-#define __pte(x) (x)
-#define __pmd(x) (x)
-#define __pgprot(x) (x)
-
-#endif /* STRICT_MM_TYPECHECKS */
+#include <asm/pgtable-2level-types.h>
#endif /* CONFIG_MMU */
diff --git a/arch/arm/include/asm/percpu.h b/arch/arm/include/asm/percpu.h
deleted file mode 100644
index b4e32d8ec072..000000000000
--- a/arch/arm/include/asm/percpu.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ARM_PERCPU
-#define __ARM_PERCPU
-
-#include <asm-generic/percpu.h>
-
-#endif
diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h
index 22de005f159c..3e08fd3fbb6b 100644
--- a/arch/arm/include/asm/pgalloc.h
+++ b/arch/arm/include/asm/pgalloc.h
@@ -105,9 +105,9 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
}
static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte,
- unsigned long prot)
+ pmdval_t prot)
{
- unsigned long pmdval = (pte + PTE_HWTABLE_OFF) | prot;
+ pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot;
pmdp[0] = __pmd(pmdval);
pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
flush_pmd_entry(pmdp);
diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h
new file mode 100644
index 000000000000..5cfba15cb401
--- /dev/null
+++ b/arch/arm/include/asm/pgtable-2level-hwdef.h
@@ -0,0 +1,93 @@
+/*
+ * arch/arm/include/asm/pgtable-2level-hwdef.h
+ *
+ * Copyright (C) 1995-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ASM_PGTABLE_2LEVEL_HWDEF_H
+#define _ASM_PGTABLE_2LEVEL_HWDEF_H
+
+/*
+ * Hardware page table definitions.
+ *
+ * + Level 1 descriptor (PMD)
+ * - common
+ */
+#define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0)
+#define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0)
+#define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0)
+#define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0)
+#define PMD_BIT4 (_AT(pmdval_t, 1) << 4)
+#define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5)
+#define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */
+/*
+ * - section
+ */
+#define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2)
+#define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3)
+#define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */
+#define PMD_SECT_AP_WRITE (_AT(pmdval_t, 1) << 10)
+#define PMD_SECT_AP_READ (_AT(pmdval_t, 1) << 11)
+#define PMD_SECT_TEX(x) (_AT(pmdval_t, (x)) << 12) /* v5 */
+#define PMD_SECT_APX (_AT(pmdval_t, 1) << 15) /* v6 */
+#define PMD_SECT_S (_AT(pmdval_t, 1) << 16) /* v6 */
+#define PMD_SECT_nG (_AT(pmdval_t, 1) << 17) /* v6 */
+#define PMD_SECT_SUPER (_AT(pmdval_t, 1) << 18) /* v6 */
+#define PMD_SECT_AF (_AT(pmdval_t, 0))
+
+#define PMD_SECT_UNCACHED (_AT(pmdval_t, 0))
+#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE)
+#define PMD_SECT_WT (PMD_SECT_CACHEABLE)
+#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
+#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2))
+
+/*
+ * - coarse table (not used)
+ */
+
+/*
+ * + Level 2 descriptor (PTE)
+ * - common
+ */
+#define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0)
+#define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0)
+#define PTE_TYPE_LARGE (_AT(pteval_t, 1) << 0)
+#define PTE_TYPE_SMALL (_AT(pteval_t, 2) << 0)
+#define PTE_TYPE_EXT (_AT(pteval_t, 3) << 0) /* v5 */
+#define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2)
+#define PTE_CACHEABLE (_AT(pteval_t, 1) << 3)
+
+/*
+ * - extended small page/tiny page
+ */
+#define PTE_EXT_XN (_AT(pteval_t, 1) << 0) /* v6 */
+#define PTE_EXT_AP_MASK (_AT(pteval_t, 3) << 4)
+#define PTE_EXT_AP0 (_AT(pteval_t, 1) << 4)
+#define PTE_EXT_AP1 (_AT(pteval_t, 2) << 4)
+#define PTE_EXT_AP_UNO_SRO (_AT(pteval_t, 0) << 4)
+#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0)
+#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1)
+#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0)
+#define PTE_EXT_TEX(x) (_AT(pteval_t, (x)) << 6) /* v5 */
+#define PTE_EXT_APX (_AT(pteval_t, 1) << 9) /* v6 */
+#define PTE_EXT_COHERENT (_AT(pteval_t, 1) << 9) /* XScale3 */
+#define PTE_EXT_SHARED (_AT(pteval_t, 1) << 10) /* v6 */
+#define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* v6 */
+
+/*
+ * - small page
+ */
+#define PTE_SMALL_AP_MASK (_AT(pteval_t, 0xff) << 4)
+#define PTE_SMALL_AP_UNO_SRO (_AT(pteval_t, 0x00) << 4)
+#define PTE_SMALL_AP_UNO_SRW (_AT(pteval_t, 0x55) << 4)
+#define PTE_SMALL_AP_URO_SRW (_AT(pteval_t, 0xaa) << 4)
+#define PTE_SMALL_AP_URW_SRW (_AT(pteval_t, 0xff) << 4)
+
+#define PHYS_MASK (~0UL)
+
+#endif
diff --git a/arch/arm/include/asm/pgtable-2level-types.h b/arch/arm/include/asm/pgtable-2level-types.h
new file mode 100644
index 000000000000..66cb5b0e89c5
--- /dev/null
+++ b/arch/arm/include/asm/pgtable-2level-types.h
@@ -0,0 +1,67 @@
+/*
+ * arch/arm/include/asm/pgtable-2level-types.h
+ *
+ * Copyright (C) 1995-2003 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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_PGTABLE_2LEVEL_TYPES_H
+#define _ASM_PGTABLE_2LEVEL_TYPES_H
+
+#include <asm/types.h>
+
+typedef u32 pteval_t;
+typedef u32 pmdval_t;
+
+#undef STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { pteval_t pte; } pte_t;
+typedef struct { pmdval_t pmd; } pmd_t;
+typedef struct { pmdval_t pgd[2]; } pgd_t;
+typedef struct { pteval_t pgprot; } pgprot_t;
+
+#define pte_val(x) ((x).pte)
+#define pmd_val(x) ((x).pmd)
+#define pgd_val(x) ((x).pgd[0])
+#define pgprot_val(x) ((x).pgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __pmd(x) ((pmd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef pteval_t pte_t;
+typedef pmdval_t pmd_t;
+typedef pmdval_t pgd_t[2];
+typedef pteval_t pgprot_t;
+
+#define pte_val(x) (x)
+#define pmd_val(x) (x)
+#define pgd_val(x) ((x)[0])
+#define pgprot_val(x) (x)
+
+#define __pte(x) (x)
+#define __pmd(x) (x)
+#define __pgprot(x) (x)
+
+#endif /* STRICT_MM_TYPECHECKS */
+
+#endif /* _ASM_PGTABLE_2LEVEL_TYPES_H */
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
new file mode 100644
index 000000000000..470457e1cfc5
--- /dev/null
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -0,0 +1,143 @@
+/*
+ * arch/arm/include/asm/pgtable-2level.h
+ *
+ * Copyright (C) 1995-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ASM_PGTABLE_2LEVEL_H
+#define _ASM_PGTABLE_2LEVEL_H
+
+/*
+ * Hardware-wise, we have a two level page table structure, where the first
+ * level has 4096 entries, and the second level has 256 entries. Each entry
+ * is one 32-bit word. Most of the bits in the second level entry are used
+ * by hardware, and there aren't any "accessed" and "dirty" bits.
+ *
+ * Linux on the other hand has a three level page table structure, which can
+ * be wrapped to fit a two level page table structure easily - using the PGD
+ * and PTE only. However, Linux also expects one "PTE" table per page, and
+ * at least a "dirty" bit.
+ *
+ * Therefore, we tweak the implementation slightly - we tell Linux that we
+ * have 2048 entries in the first level, each of which is 8 bytes (iow, two
+ * hardware pointers to the second level.) The second level contains two
+ * hardware PTE tables arranged contiguously, preceded by Linux versions
+ * which contain the state information Linux needs. We, therefore, end up
+ * with 512 entries in the "PTE" level.
+ *
+ * This leads to the page tables having the following layout:
+ *
+ * pgd pte
+ * | |
+ * +--------+
+ * | | +------------+ +0
+ * +- - - - + | Linux pt 0 |
+ * | | +------------+ +1024
+ * +--------+ +0 | Linux pt 1 |
+ * | |-----> +------------+ +2048
+ * +- - - - + +4 | h/w pt 0 |
+ * | |-----> +------------+ +3072
+ * +--------+ +8 | h/w pt 1 |
+ * | | +------------+ +4096
+ *
+ * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
+ * PTE_xxx for definitions of bits appearing in the "h/w pt".
+ *
+ * PMD_xxx definitions refer to bits in the first level page table.
+ *
+ * The "dirty" bit is emulated by only granting hardware write permission
+ * iff the page is marked "writable" and "dirty" in the Linux PTE. This
+ * means that a write to a clean page will cause a permission fault, and
+ * the Linux MM layer will mark the page dirty via handle_pte_fault().
+ * For the hardware to notice the permission change, the TLB entry must
+ * be flushed, and ptep_set_access_flags() does that for us.
+ *
+ * The "accessed" or "young" bit is emulated by a similar method; we only
+ * allow accesses to the page if the "young" bit is set. Accesses to the
+ * page will cause a fault, and handle_pte_fault() will set the young bit
+ * for us as long as the page is marked present in the corresponding Linux
+ * PTE entry. Again, ptep_set_access_flags() will ensure that the TLB is
+ * up to date.
+ *
+ * However, when the "young" bit is cleared, we deny access to the page
+ * by clearing the hardware PTE. Currently Linux does not flush the TLB
+ * for us in this case, which means the TLB will retain the transation
+ * until either the TLB entry is evicted under pressure, or a context
+ * switch which changes the user space mapping occurs.
+ */
+#define PTRS_PER_PTE 512
+#define PTRS_PER_PMD 1
+#define PTRS_PER_PGD 2048
+
+#define PTE_HWTABLE_PTRS (PTRS_PER_PTE)
+#define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t))
+#define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32))
+
+/*
+ * PMD_SHIFT determines the size of the area a second-level page table can map
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
+#define PMD_SHIFT 21
+#define PGDIR_SHIFT 21
+
+#define PMD_SIZE (1UL << PMD_SHIFT)
+#define PMD_MASK (~(PMD_SIZE-1))
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+/*
+ * section address mask and size definitions.
+ */
+#define SECTION_SHIFT 20
+#define SECTION_SIZE (1UL << SECTION_SHIFT)
+#define SECTION_MASK (~(SECTION_SIZE-1))
+
+/*
+ * ARMv6 supersection address mask and size definitions.
+ */
+#define SUPERSECTION_SHIFT 24
+#define SUPERSECTION_SIZE (1UL << SUPERSECTION_SHIFT)
+#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1))
+
+#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
+
+/*
+ * "Linux" PTE definitions.
+ *
+ * We keep two sets of PTEs - the hardware and the linux version.
+ * This allows greater flexibility in the way we map the Linux bits
+ * onto the hardware tables, and allows us to have YOUNG and DIRTY
+ * bits.
+ *
+ * The PTE table pointer refers to the hardware entries; the "Linux"
+ * entries are stored 1024 bytes below.
+ */
+#define L_PTE_PRESENT (_AT(pteval_t, 1) << 0)
+#define L_PTE_YOUNG (_AT(pteval_t, 1) << 1)
+#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */
+#define L_PTE_DIRTY (_AT(pteval_t, 1) << 6)
+#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7)
+#define L_PTE_USER (_AT(pteval_t, 1) << 8)
+#define L_PTE_XN (_AT(pteval_t, 1) << 9)
+#define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */
+
+/*
+ * These are the memory types, defined to be compatible with
+ * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB
+ */
+#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */
+#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */
+#define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 0x02) << 2) /* 0010 */
+#define L_PTE_MT_WRITEBACK (_AT(pteval_t, 0x03) << 2) /* 0011 */
+#define L_PTE_MT_MINICACHE (_AT(pteval_t, 0x06) << 2) /* 0110 (sa1100, xscale) */
+#define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 0x07) << 2) /* 0111 */
+#define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 0x04) << 2) /* 0100 */
+#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */
+#define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */
+#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */
+#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2)
+
+#endif /* _ASM_PGTABLE_2LEVEL_H */
diff --git a/arch/arm/include/asm/pgtable-hwdef.h b/arch/arm/include/asm/pgtable-hwdef.h
index fd1521d5cb9d..183111164ce9 100644
--- a/arch/arm/include/asm/pgtable-hwdef.h
+++ b/arch/arm/include/asm/pgtable-hwdef.h
@@ -10,81 +10,6 @@
#ifndef _ASMARM_PGTABLE_HWDEF_H
#define _ASMARM_PGTABLE_HWDEF_H
-/*
- * Hardware page table definitions.
- *
- * + Level 1 descriptor (PMD)
- * - common
- */
-#define PMD_TYPE_MASK (3 << 0)
-#define PMD_TYPE_FAULT (0 << 0)
-#define PMD_TYPE_TABLE (1 << 0)
-#define PMD_TYPE_SECT (2 << 0)
-#define PMD_BIT4 (1 << 4)
-#define PMD_DOMAIN(x) ((x) << 5)
-#define PMD_PROTECTION (1 << 9) /* v5 */
-/*
- * - section
- */
-#define PMD_SECT_BUFFERABLE (1 << 2)
-#define PMD_SECT_CACHEABLE (1 << 3)
-#define PMD_SECT_XN (1 << 4) /* v6 */
-#define PMD_SECT_AP_WRITE (1 << 10)
-#define PMD_SECT_AP_READ (1 << 11)
-#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */
-#define PMD_SECT_APX (1 << 15) /* v6 */
-#define PMD_SECT_S (1 << 16) /* v6 */
-#define PMD_SECT_nG (1 << 17) /* v6 */
-#define PMD_SECT_SUPER (1 << 18) /* v6 */
-
-#define PMD_SECT_UNCACHED (0)
-#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE)
-#define PMD_SECT_WT (PMD_SECT_CACHEABLE)
-#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
-#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
-#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
-#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2))
-
-/*
- * - coarse table (not used)
- */
-
-/*
- * + Level 2 descriptor (PTE)
- * - common
- */
-#define PTE_TYPE_MASK (3 << 0)
-#define PTE_TYPE_FAULT (0 << 0)
-#define PTE_TYPE_LARGE (1 << 0)
-#define PTE_TYPE_SMALL (2 << 0)
-#define PTE_TYPE_EXT (3 << 0) /* v5 */
-#define PTE_BUFFERABLE (1 << 2)
-#define PTE_CACHEABLE (1 << 3)
-
-/*
- * - extended small page/tiny page
- */
-#define PTE_EXT_XN (1 << 0) /* v6 */
-#define PTE_EXT_AP_MASK (3 << 4)
-#define PTE_EXT_AP0 (1 << 4)
-#define PTE_EXT_AP1 (2 << 4)
-#define PTE_EXT_AP_UNO_SRO (0 << 4)
-#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0)
-#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1)
-#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0)
-#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
-#define PTE_EXT_APX (1 << 9) /* v6 */
-#define PTE_EXT_COHERENT (1 << 9) /* XScale3 */
-#define PTE_EXT_SHARED (1 << 10) /* v6 */
-#define PTE_EXT_NG (1 << 11) /* v6 */
-
-/*
- * - small page
- */
-#define PTE_SMALL_AP_MASK (0xff << 4)
-#define PTE_SMALL_AP_UNO_SRO (0x00 << 4)
-#define PTE_SMALL_AP_UNO_SRW (0x55 << 4)
-#define PTE_SMALL_AP_URO_SRW (0xaa << 4)
-#define PTE_SMALL_AP_URW_SRW (0xff << 4)
+#include <asm/pgtable-2level-hwdef.h>
#endif
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 5750704e0271..9451dce3a553 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -24,6 +24,8 @@
#include <mach/vmalloc.h>
#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable-2level.h>
+
/*
* Just any arbitrary offset to the start of the vmalloc VM area: the
* current 8MB value just means that there will be a 8MB "hole" after the
@@ -41,79 +43,6 @@
#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#endif
-/*
- * Hardware-wise, we have a two level page table structure, where the first
- * level has 4096 entries, and the second level has 256 entries. Each entry
- * is one 32-bit word. Most of the bits in the second level entry are used
- * by hardware, and there aren't any "accessed" and "dirty" bits.
- *
- * Linux on the other hand has a three level page table structure, which can
- * be wrapped to fit a two level page table structure easily - using the PGD
- * and PTE only. However, Linux also expects one "PTE" table per page, and
- * at least a "dirty" bit.
- *
- * Therefore, we tweak the implementation slightly - we tell Linux that we
- * have 2048 entries in the first level, each of which is 8 bytes (iow, two
- * hardware pointers to the second level.) The second level contains two
- * hardware PTE tables arranged contiguously, preceded by Linux versions
- * which contain the state information Linux needs. We, therefore, end up
- * with 512 entries in the "PTE" level.
- *
- * This leads to the page tables having the following layout:
- *
- * pgd pte
- * | |
- * +--------+
- * | | +------------+ +0
- * +- - - - + | Linux pt 0 |
- * | | +------------+ +1024
- * +--------+ +0 | Linux pt 1 |
- * | |-----> +------------+ +2048
- * +- - - - + +4 | h/w pt 0 |
- * | |-----> +------------+ +3072
- * +--------+ +8 | h/w pt 1 |
- * | | +------------+ +4096
- *
- * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
- * PTE_xxx for definitions of bits appearing in the "h/w pt".
- *
- * PMD_xxx definitions refer to bits in the first level page table.
- *
- * The "dirty" bit is emulated by only granting hardware write permission
- * iff the page is marked "writable" and "dirty" in the Linux PTE. This
- * means that a write to a clean page will cause a permission fault, and
- * the Linux MM layer will mark the page dirty via handle_pte_fault().
- * For the hardware to notice the permission change, the TLB entry must
- * be flushed, and ptep_set_access_flags() does that for us.
- *
- * The "accessed" or "young" bit is emulated by a similar method; we only
- * allow accesses to the page if the "young" bit is set. Accesses to the
- * page will cause a fault, and handle_pte_fault() will set the young bit
- * for us as long as the page is marked present in the corresponding Linux
- * PTE entry. Again, ptep_set_access_flags() will ensure that the TLB is
- * up to date.
- *
- * However, when the "young" bit is cleared, we deny access to the page
- * by clearing the hardware PTE. Currently Linux does not flush the TLB
- * for us in this case, which means the TLB will retain the transation
- * until either the TLB entry is evicted under pressure, or a context
- * switch which changes the user space mapping occurs.
- */
-#define PTRS_PER_PTE 512
-#define PTRS_PER_PMD 1
-#define PTRS_PER_PGD 2048
-
-#define PTE_HWTABLE_PTRS (PTRS_PER_PTE)
-#define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t))
-#define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32))
-
-/*
- * PMD_SHIFT determines the size of the area a second-level page table can map
- * PGDIR_SHIFT determines what a third-level page table entry can map
- */
-#define PMD_SHIFT 21
-#define PGDIR_SHIFT 21
-
#define LIBRARY_TEXT_START 0x0c000000
#ifndef __ASSEMBLY__
@@ -124,12 +53,6 @@ extern void __pgd_error(const char *file, int line, pgd_t);
#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte)
#define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd)
#define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd)
-#endif /* !__ASSEMBLY__ */
-
-#define PMD_SIZE (1UL << PMD_SHIFT)
-#define PMD_MASK (~(PMD_SIZE-1))
-#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
/*
* This is the lowest virtual address we can permit any user space
@@ -138,60 +61,6 @@ extern void __pgd_error(const char *file, int line, pgd_t);
*/
#define FIRST_USER_ADDRESS PAGE_SIZE
-#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
-
-/*
- * section address mask and size definitions.
- */
-#define SECTION_SHIFT 20
-#define SECTION_SIZE (1UL << SECTION_SHIFT)
-#define SECTION_MASK (~(SECTION_SIZE-1))
-
-/*
- * ARMv6 supersection address mask and size definitions.
- */
-#define SUPERSECTION_SHIFT 24
-#define SUPERSECTION_SIZE (1UL << SUPERSECTION_SHIFT)
-#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1))
-
-/*
- * "Linux" PTE definitions.
- *
- * We keep two sets of PTEs - the hardware and the linux version.
- * This allows greater flexibility in the way we map the Linux bits
- * onto the hardware tables, and allows us to have YOUNG and DIRTY
- * bits.
- *
- * The PTE table pointer refers to the hardware entries; the "Linux"
- * entries are stored 1024 bytes below.
- */
-#define L_PTE_PRESENT (_AT(pteval_t, 1) << 0)
-#define L_PTE_YOUNG (_AT(pteval_t, 1) << 1)
-#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */
-#define L_PTE_DIRTY (_AT(pteval_t, 1) << 6)
-#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7)
-#define L_PTE_USER (_AT(pteval_t, 1) << 8)
-#define L_PTE_XN (_AT(pteval_t, 1) << 9)
-#define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */
-
-/*
- * These are the memory types, defined to be compatible with
- * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB
- */
-#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */
-#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */
-#define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 0x02) << 2) /* 0010 */
-#define L_PTE_MT_WRITEBACK (_AT(pteval_t, 0x03) << 2) /* 0011 */
-#define L_PTE_MT_MINICACHE (_AT(pteval_t, 0x06) << 2) /* 0110 (sa1100, xscale) */
-#define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 0x07) << 2) /* 0111 */
-#define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 0x04) << 2) /* 0100 */
-#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */
-#define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */
-#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */
-#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2)
-
-#ifndef __ASSEMBLY__
-
/*
* The pgprot_* and protection_map entries will be fixed up in runtime
* to include the cachable and bufferable bits based on memory policy,
@@ -232,6 +101,9 @@ extern pgprot_t pgprot_kernel;
#define pgprot_writecombine(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
+#define pgprot_stronglyordered(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
#define pgprot_dmacoherent(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
@@ -327,10 +199,10 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
static inline pte_t *pmd_page_vaddr(pmd_t pmd)
{
- return __va(pmd_val(pmd) & PAGE_MASK);
+ return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
}
-#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
+#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
/* we don't need complex calculations here as the pmd is folded into the pgd */
#define pmd_addr_end(addr,end) (end)
@@ -351,7 +223,7 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
#define pte_offset_map(pmd,addr) (__pte_map(pmd) + pte_index(addr))
#define pte_unmap(pte) __pte_unmap(pte)
-#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
+#define pte_pfn(pte) ((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT)
#define pfn_pte(pfn,prot) __pte(__pfn_to_phys(pfn) | pgprot_val(prot))
#define pte_page(pte) pfn_to_page(pte_pfn(pte))
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index b7e82c4aced6..71d99b83cdb9 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -13,7 +13,12 @@
#define __ARM_PMU_H__
#include <linux/interrupt.h>
+#include <linux/perf_event.h>
+/*
+ * Types of PMUs that can be accessed directly and require mutual
+ * exclusion between profiling tools.
+ */
enum arm_pmu_type {
ARM_PMU_DEVICE_CPU = 0,
ARM_NUM_PMU_DEVICES,
@@ -37,21 +42,17 @@ struct arm_pmu_platdata {
* reserve_pmu() - reserve the hardware performance counters
*
* Reserve the hardware performance counters in the system for exclusive use.
- * The platform_device for the system is returned on success, ERR_PTR()
- * encoded error on failure.
+ * Returns 0 on success or -EBUSY if the lock is already held.
*/
-extern struct platform_device *
+extern int
reserve_pmu(enum arm_pmu_type type);
/**
* release_pmu() - Relinquish control of the performance counters
*
* Release the performance counters and allow someone else to use them.
- * Callers must have disabled the counters and released IRQs before calling
- * this. The platform_device returned from reserve_pmu() must be passed as
- * a cookie.
*/
-extern int
+extern void
release_pmu(enum arm_pmu_type type);
/**
@@ -68,24 +69,78 @@ init_pmu(enum arm_pmu_type type);
#include <linux/err.h>
-static inline struct platform_device *
-reserve_pmu(enum arm_pmu_type type)
-{
- return ERR_PTR(-ENODEV);
-}
-
static inline int
-release_pmu(enum arm_pmu_type type)
+reserve_pmu(enum arm_pmu_type type)
{
return -ENODEV;
}
-static inline int
-init_pmu(enum arm_pmu_type type)
-{
- return -ENODEV;
-}
+static inline void
+release_pmu(enum arm_pmu_type type) { }
#endif /* CONFIG_CPU_HAS_PMU */
+#ifdef CONFIG_HW_PERF_EVENTS
+
+/* The events for a given PMU register set. */
+struct pmu_hw_events {
+ /*
+ * The events that are active on the PMU for the given index.
+ */
+ struct perf_event **events;
+
+ /*
+ * A 1 bit for an index indicates that the counter is being used for
+ * an event. A 0 means that the counter can be used.
+ */
+ unsigned long *used_mask;
+
+ /*
+ * Hardware lock to serialize accesses to PMU registers. Needed for the
+ * read/modify/write sequences.
+ */
+ raw_spinlock_t pmu_lock;
+};
+
+struct arm_pmu {
+ struct pmu pmu;
+ enum arm_perf_pmu_ids id;
+ enum arm_pmu_type type;
+ cpumask_t active_irqs;
+ const char *name;
+ irqreturn_t (*handle_irq)(int irq_num, void *dev);
+ void (*enable)(struct hw_perf_event *evt, int idx);
+ void (*disable)(struct hw_perf_event *evt, int idx);
+ int (*get_event_idx)(struct pmu_hw_events *hw_events,
+ struct hw_perf_event *hwc);
+ int (*set_event_filter)(struct hw_perf_event *evt,
+ struct perf_event_attr *attr);
+ u32 (*read_counter)(int idx);
+ void (*write_counter)(int idx, u32 val);
+ void (*start)(void);
+ void (*stop)(void);
+ void (*reset)(void *);
+ int (*map_event)(struct perf_event *event);
+ int num_events;
+ atomic_t active_events;
+ struct mutex reserve_mutex;
+ u64 max_period;
+ struct platform_device *plat_device;
+ struct pmu_hw_events *(*get_hw_events)(void);
+};
+
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
+
+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type);
+
+u64 armpmu_event_update(struct perf_event *event,
+ struct hw_perf_event *hwc,
+ int idx, int overflow);
+
+int armpmu_event_set_period(struct perf_event *event,
+ struct hw_perf_event *hwc,
+ int idx);
+
+#endif /* CONFIG_HW_PERF_EVENTS */
+
#endif /* __ARM_PMU_H__ */
diff --git a/arch/arm/include/asm/poll.h b/arch/arm/include/asm/poll.h
deleted file mode 100644
index c98509d3149e..000000000000
--- a/arch/arm/include/asm/poll.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/poll.h>
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 633d1cb84d87..9e92cb205e65 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -81,6 +81,10 @@ extern void cpu_dcache_clean_area(void *, int);
extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
+
+/* These three are private to arch/arm/kernel/suspend.c */
+extern void cpu_do_suspend(void *);
+extern void cpu_do_resume(void *);
#else
#define cpu_proc_init processor._proc_init
#define cpu_proc_fin processor._proc_fin
@@ -89,6 +93,10 @@ extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
#define cpu_dcache_clean_area processor.dcache_clean_area
#define cpu_set_pte_ext processor.set_pte_ext
#define cpu_do_switch_mm processor.switch_mm
+
+/* These three are private to arch/arm/kernel/suspend.c */
+#define cpu_do_suspend processor.do_suspend
+#define cpu_do_resume processor.do_resume
#endif
extern void cpu_resume(void);
diff --git a/arch/arm/include/asm/resource.h b/arch/arm/include/asm/resource.h
deleted file mode 100644
index 734b581b5b6a..000000000000
--- a/arch/arm/include/asm/resource.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ARM_RESOURCE_H
-#define _ARM_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif
diff --git a/arch/arm/include/asm/sections.h b/arch/arm/include/asm/sections.h
deleted file mode 100644
index 2b8c5160388f..000000000000
--- a/arch/arm/include/asm/sections.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sections.h>
diff --git a/arch/arm/include/asm/siginfo.h b/arch/arm/include/asm/siginfo.h
deleted file mode 100644
index 5e21852e6039..000000000000
--- a/arch/arm/include/asm/siginfo.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASMARM_SIGINFO_H
-#define _ASMARM_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index e42d96a45d3e..1e5717afc4ac 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -33,6 +33,11 @@ extern void show_ipi_list(struct seq_file *, int);
asmlinkage void do_IPI(int ipinr, struct pt_regs *regs);
/*
+ * Called from C code, this handles an IPI.
+ */
+void handle_IPI(int ipinr, struct pt_regs *regs);
+
+/*
* Setup the set of possible CPUs (via set_cpu_possible)
*/
extern void smp_init_cpus(void);
@@ -66,6 +71,12 @@ extern void platform_secondary_init(unsigned int cpu);
extern void platform_smp_prepare_cpus(unsigned int);
/*
+ * Logical CPU mapping.
+ */
+extern int __cpu_logical_map[NR_CPUS];
+#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
+
+/*
* Initial data for bringing up a secondary CPU.
*/
struct secondary_data {
@@ -88,9 +99,4 @@ extern void platform_cpu_enable(unsigned int cpu);
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
-/*
- * show local interrupt info
- */
-extern void show_local_irqs(struct seq_file *, int);
-
#endif /* ifndef __ASM_ARM_SMP_H */
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
index fed9981fba08..ef9ffba97ad8 100644
--- a/arch/arm/include/asm/smp_twd.h
+++ b/arch/arm/include/asm/smp_twd.h
@@ -22,7 +22,7 @@ struct clock_event_device;
extern void __iomem *twd_base;
-int twd_timer_ack(void);
void twd_timer_setup(struct clock_event_device *);
+void twd_timer_stop(struct clock_event_device *);
#endif
diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h
index b0e4e1a02318..1c0a551ae375 100644
--- a/arch/arm/include/asm/suspend.h
+++ b/arch/arm/include/asm/suspend.h
@@ -1,22 +1,7 @@
#ifndef __ASM_ARM_SUSPEND_H
#define __ASM_ARM_SUSPEND_H
-#include <asm/memory.h>
-#include <asm/tlbflush.h>
-
extern void cpu_resume(void);
-
-/*
- * Hide the first two arguments to __cpu_suspend - these are an implementation
- * detail which platform code shouldn't have to know about.
- */
-static inline int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
-{
- extern int __cpu_suspend(int, long, unsigned long,
- int (*)(unsigned long));
- int ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
- flush_tlb_all();
- return ret;
-}
+extern int cpu_suspend(unsigned long, int (*)(unsigned long));
#endif
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 832888d0c20c..984014b92647 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -57,18 +57,12 @@
#ifndef __ASSEMBLY__
+#include <linux/compiler.h>
#include <linux/linkage.h>
#include <linux/irqflags.h>
#include <asm/outercache.h>
-#define __exception __attribute__((section(".exception.text")))
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-#define __exception_irq_entry __irq_entry
-#else
-#define __exception_irq_entry __exception
-#endif
-
struct thread_info;
struct task_struct;
@@ -97,14 +91,13 @@ void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
#define xchg(ptr,x) \
((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-extern asmlinkage void __backtrace(void);
extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
struct mm_struct;
extern void show_pte(struct mm_struct *mm, unsigned long addr);
extern void __show_regs(struct pt_regs *);
-extern int cpu_architecture(void);
+extern int __pure cpu_architecture(void);
extern void cpu_init(void);
void arm_machine_restart(char mode, const char *cmd);
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index 8077145698ff..02b2f8203982 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -471,7 +471,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
* these operations. This is typically used when we are removing
* PMD entries.
*/
-static inline void flush_pmd_entry(pmd_t *pmd)
+static inline void flush_pmd_entry(void *pmd)
{
const unsigned int __tlb_flag = __cpu_tlb_flags;
@@ -487,7 +487,7 @@ static inline void flush_pmd_entry(pmd_t *pmd)
dsb();
}
-static inline void clean_pmd_entry(pmd_t *pmd)
+static inline void clean_pmd_entry(void *pmd)
{
const unsigned int __tlb_flag = __cpu_tlb_flags;
diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h
index accbd7cad9b5..a7e457ed27c3 100644
--- a/arch/arm/include/asm/topology.h
+++ b/arch/arm/include/asm/topology.h
@@ -1,6 +1,39 @@
#ifndef _ASM_ARM_TOPOLOGY_H
#define _ASM_ARM_TOPOLOGY_H
+#ifdef CONFIG_ARM_CPU_TOPOLOGY
+
+#include <linux/cpumask.h>
+
+struct cputopo_arm {
+ int thread_id;
+ int core_id;
+ int socket_id;
+ cpumask_t thread_sibling;
+ cpumask_t core_sibling;
+};
+
+extern struct cputopo_arm cpu_topology[NR_CPUS];
+
+#define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id)
+#define topology_core_id(cpu) (cpu_topology[cpu].core_id)
+#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling)
+#define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling)
+
+#define mc_capable() (cpu_topology[0].socket_id != -1)
+#define smt_capable() (cpu_topology[0].thread_id != -1)
+
+void init_cpu_topology(void);
+void store_cpu_topology(unsigned int cpuid);
+const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
+
+#else
+
+static inline void init_cpu_topology(void) { }
+static inline void store_cpu_topology(unsigned int cpuid) { }
+
+#endif
+
#include <asm-generic/topology.h>
#endif /* _ASM_ARM_TOPOLOGY_H */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index f7887dc53c1f..16eed6aebfa4 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,7 +29,7 @@ obj-$(CONFIG_MODULES) += armksyms.o module.o
obj-$(CONFIG_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o isa.o
-obj-$(CONFIG_PM_SLEEP) += sleep.o
+obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o
obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o
obj-$(CONFIG_SMP) += smp.o smp_tlb.o
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
@@ -43,6 +43,13 @@ obj-$(CONFIG_KPROBES) += kprobes-thumb.o
else
obj-$(CONFIG_KPROBES) += kprobes-arm.o
endif
+obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o
+test-kprobes-objs := kprobes-test.o
+ifdef CONFIG_THUMB2_KERNEL
+test-kprobes-objs += kprobes-test-thumb.o
+else
+test-kprobes-objs += kprobes-test-arm.o
+endif
obj-$(CONFIG_ATAGS_PROC) += atags.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
@@ -66,6 +73,7 @@ obj-$(CONFIG_IWMMXT) += iwmmxt.o
obj-$(CONFIG_CPU_HAS_PMU) += pmu.o
obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt
+obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o
ifneq ($(CONFIG_ARCH_EBSA110),y)
obj-y += io.o
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index aeef960ff795..8e3c6f11b0a1 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -49,9 +49,6 @@ extern void __aeabi_ulcmp(void);
extern void fpundefinstr(void);
-
-EXPORT_SYMBOL(__backtrace);
-
/* platform dependent support */
EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(__const_udelay);
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 16baba2e4369..1429d8989fb9 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -20,6 +20,7 @@
#include <asm/thread_info.h>
#include <asm/memory.h>
#include <asm/procinfo.h>
+#include <asm/hardware/cache-l2x0.h>
#include <linux/kbuild.h>
/*
@@ -92,6 +93,17 @@ int main(void)
DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0));
DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
BLANK();
+#ifdef CONFIG_CACHE_L2X0
+ DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base));
+ DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl));
+ DEFINE(L2X0_R_TAG_LATENCY, offsetof(struct l2x0_regs, tag_latency));
+ DEFINE(L2X0_R_DATA_LATENCY, offsetof(struct l2x0_regs, data_latency));
+ DEFINE(L2X0_R_FILTER_START, offsetof(struct l2x0_regs, filter_start));
+ DEFINE(L2X0_R_FILTER_END, offsetof(struct l2x0_regs, filter_end));
+ DEFINE(L2X0_R_PREFETCH_CTRL, offsetof(struct l2x0_regs, prefetch_ctrl));
+ DEFINE(L2X0_R_PWR_CTRL, offsetof(struct l2x0_regs, pwr_ctrl));
+ BLANK();
+#endif
#ifdef CONFIG_CPU_HAS_ASID
DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id));
BLANK();
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index d6df359408f0..c0d9203fc75e 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -412,6 +412,9 @@ void pcibios_fixup_bus(struct pci_bus *bus)
printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
}
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_fixup_bus);
+#endif
/*
* Convert from Linux-centric to bus-centric addresses for bridge devices.
@@ -431,6 +434,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
region->start = res->start - offset;
region->end = res->end - offset;
}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
void __devinit
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
@@ -447,12 +451,7 @@ pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
res->start = region->start + offset;
res->end = region->end + offset;
}
-
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pcibios_fixup_bus);
-EXPORT_SYMBOL(pcibios_resource_to_bus);
EXPORT_SYMBOL(pcibios_bus_to_resource);
-#endif
/*
* Swizzle the device pin each time we cross a bridge.
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index bcd66e00bdbe..204e2160cfcc 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -22,7 +22,7 @@
#if defined(CONFIG_DEBUG_ICEDCC)
@@ debug using ARM EmbeddedICE DCC channel
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
.endm
#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
@@ -106,7 +106,7 @@
#ifdef CONFIG_MMU
.macro addruart_current, rx, tmp1, tmp2
- addruart \tmp1, \tmp2
+ addruart \tmp1, \tmp2, \rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1
moveq \rx, \tmp1
@@ -151,6 +151,8 @@ printhex: adr r2, hexbuf
b printascii
ENDPROC(printhex2)
+hexbuf: .space 16
+
.ltorg
ENTRY(printascii)
@@ -175,5 +177,3 @@ ENTRY(printch)
mov r0, #0
b 1b
ENDPROC(printch)
-
-hexbuf: .space 16
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index 2c4a185f92cd..7b829d9663b1 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -23,7 +23,7 @@
#include <asm/mach/dma.h>
-DEFINE_SPINLOCK(dma_spin_lock);
+DEFINE_RAW_SPINLOCK(dma_spin_lock);
EXPORT_SYMBOL(dma_spin_lock);
static dma_t *dma_chan[MAX_DMA_CHANNELS];
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index d16500110ee9..4dd0edab6a65 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -237,7 +237,7 @@ static void ecard_init_pgtables(struct mm_struct *mm)
memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE));
- src_pgd = pgd_offset(mm, EASI_BASE);
+ src_pgd = pgd_offset(mm, (unsigned long)EASI_BASE);
dst_pgd = pgd_offset(mm, EASI_START);
memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE));
@@ -674,44 +674,37 @@ static int __init ecard_probeirqhw(void)
#define ecard_probeirqhw() (0)
#endif
-#ifndef IO_EC_MEMC8_BASE
-#define IO_EC_MEMC8_BASE 0
-#endif
-
-static unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
+static void __iomem *__ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
{
- unsigned long address = 0;
+ void __iomem *address = NULL;
int slot = ec->slot_no;
if (ec->slot_no == 8)
- return IO_EC_MEMC8_BASE;
+ return ECARD_MEMC8_BASE;
ectcr &= ~(1 << slot);
switch (type) {
case ECARD_MEMC:
if (slot < 4)
- address = IO_EC_MEMC_BASE + (slot << 12);
+ address = ECARD_MEMC_BASE + (slot << 14);
break;
case ECARD_IOC:
if (slot < 4)
- address = IO_EC_IOC_BASE + (slot << 12);
-#ifdef IO_EC_IOC4_BASE
+ address = ECARD_IOC_BASE + (slot << 14);
else
- address = IO_EC_IOC4_BASE + ((slot - 4) << 12);
-#endif
+ address = ECARD_IOC4_BASE + ((slot - 4) << 14);
if (address)
- address += speed << 17;
+ address += speed << 19;
break;
-#ifdef IO_EC_EASI_BASE
case ECARD_EASI:
- address = IO_EC_EASI_BASE + (slot << 22);
+ address = ECARD_EASI_BASE + (slot << 24);
if (speed == ECARD_FAST)
ectcr |= 1 << slot;
break;
-#endif
+
default:
break;
}
@@ -990,6 +983,7 @@ ecard_probe(int slot, card_type_t type)
ecard_t **ecp;
ecard_t *ec;
struct ex_ecid cid;
+ void __iomem *addr;
int i, rc;
ec = ecard_alloc_card(type, slot);
@@ -999,7 +993,7 @@ ecard_probe(int slot, card_type_t type)
}
rc = -ENODEV;
- if ((ec->podaddr = __ecard_address(ec, type, ECARD_SYNC)) == 0)
+ if ((addr = __ecard_address(ec, type, ECARD_SYNC)) == NULL)
goto nodev;
cid.r_zero = 1;
@@ -1019,7 +1013,7 @@ ecard_probe(int slot, card_type_t type)
ec->cid.fiqmask = cid.r_fiqmask;
ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff);
ec->fiqaddr =
- ec->irqaddr = (void __iomem *)ioaddr(ec->podaddr);
+ ec->irqaddr = addr;
if (ec->cid.is) {
ec->irqmask = ec->cid.irqmask;
@@ -1048,10 +1042,8 @@ ecard_probe(int slot, card_type_t type)
set_irq_flags(ec->irq, IRQF_VALID);
}
-#ifdef IO_EC_MEMC8_BASE
if (slot == 8)
ec->irq = 11;
-#endif
#ifdef CONFIG_ARCH_RPC
/* On RiscPC, only first two slots have DMA capability */
if (slot < 2)
@@ -1097,9 +1089,7 @@ static int __init ecard_init(void)
ecard_probe(slot, ECARD_IOC);
}
-#ifdef IO_EC_MEMC8_BASE
ecard_probe(8, ECARD_IOC);
-#endif
irqhw = ecard_probeirqhw();
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index a87cbf889ff4..9ad50c4208ae 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -24,6 +24,7 @@
#include <asm/unwind.h>
#include <asm/unistd.h>
#include <asm/tls.h>
+#include <asm/system.h>
#include "entry-header.S"
#include <asm/entry-macro-multi.S>
@@ -262,8 +263,7 @@ __und_svc:
ldr r0, [r4, #-4]
#else
ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2
- and r9, r0, #0xf800
- cmp r9, #0xe800 @ 32-bit instruction if xx >= 0
+ cmp r0, #0xe800 @ 32-bit instruction if xx >= 0
ldrhhs r9, [r4] @ bottom 16 bits
orrhs r0, r9, r0, lsl #16
#endif
@@ -440,18 +440,46 @@ __und_usr:
#endif
beq call_fpe
@ Thumb instruction
-#if __LINUX_ARM_ARCH__ >= 7
+#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
+/*
+ * Thumb-2 instruction handling. Note that because pre-v6 and >= v6 platforms
+ * can never be supported in a single kernel, this code is not applicable at
+ * all when __LINUX_ARM_ARCH__ < 6. This allows simplifying assumptions to be
+ * made about .arch directives.
+ */
+#if __LINUX_ARM_ARCH__ < 7
+/* If the target CPU may not be Thumb-2-capable, a run-time check is needed: */
+#define NEED_CPU_ARCHITECTURE
+ ldr r5, .LCcpu_architecture
+ ldr r5, [r5]
+ cmp r5, #CPU_ARCH_ARMv7
+ blo __und_usr_unknown
+/*
+ * The following code won't get run unless the running CPU really is v7, so
+ * coding round the lack of ldrht on older arches is pointless. Temporarily
+ * override the assembler target arch with the minimum required instead:
+ */
+ .arch armv6t2
+#endif
2:
ARM( ldrht r5, [r4], #2 )
THUMB( ldrht r5, [r4] )
THUMB( add r4, r4, #2 )
- and r0, r5, #0xf800 @ mask bits 111x x... .... ....
- cmp r0, #0xe800 @ 32bit instruction if xx != 0
+ cmp r5, #0xe800 @ 32bit instruction if xx != 0
blo __und_usr_unknown
3: ldrht r0, [r4]
add r2, r2, #2 @ r2 is PC + 2, make it PC + 4
orr r0, r0, r5, lsl #16
+
+#if __LINUX_ARM_ARCH__ < 7
+/* If the target arch was overridden, change it back: */
+#ifdef CONFIG_CPU_32v6K
+ .arch armv6k
#else
+ .arch armv6
+#endif
+#endif /* __LINUX_ARM_ARCH__ < 7 */
+#else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */
b __und_usr_unknown
#endif
UNWIND(.fnend )
@@ -578,6 +606,12 @@ call_fpe:
movw_pc lr @ CP#14 (Debug)
movw_pc lr @ CP#15 (Control)
+#ifdef NEED_CPU_ARCHITECTURE
+ .align 2
+.LCcpu_architecture:
+ .word __cpu_architecture
+#endif
+
#ifdef CONFIG_NEON
.align 6
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 742b6108a001..566c54c2a1fe 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -21,6 +21,7 @@
#include <asm/memory.h>
#include <asm/thread_info.h>
#include <asm/system.h>
+#include <asm/pgtable.h>
#ifdef CONFIG_DEBUG_LL
#include <mach/debug-macro.S>
@@ -38,11 +39,14 @@
#error KERNEL_RAM_VADDR must start at 0xXXXX8000
#endif
+#define PG_DIR_SIZE 0x4000
+#define PMD_ORDER 2
+
.globl swapper_pg_dir
- .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000
+ .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE
.macro pgtbl, rd, phys
- add \rd, \phys, #TEXT_OFFSET - 0x4000
+ add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE
.endm
#ifdef CONFIG_XIP_KERNEL
@@ -95,7 +99,7 @@ ENTRY(stext)
sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET)
add r8, r8, r4 @ PHYS_OFFSET
#else
- ldr r8, =PLAT_PHYS_OFFSET
+ ldr r8, =PHYS_OFFSET @ always constant in this case
#endif
/*
@@ -148,11 +152,11 @@ __create_page_tables:
pgtbl r4, r8 @ page table address
/*
- * Clear the 16K level 1 swapper page table
+ * Clear the swapper page table
*/
mov r0, r4
mov r3, #0
- add r6, r0, #0x4000
+ add r6, r0, #PG_DIR_SIZE
1: str r3, [r0], #4
str r3, [r0], #4
str r3, [r0], #4
@@ -171,30 +175,30 @@ __create_page_tables:
sub r0, r0, r3 @ virt->phys offset
add r5, r5, r0 @ phys __enable_mmu
add r6, r6, r0 @ phys __enable_mmu_end
- mov r5, r5, lsr #20
- mov r6, r6, lsr #20
+ mov r5, r5, lsr #SECTION_SHIFT
+ mov r6, r6, lsr #SECTION_SHIFT
-1: orr r3, r7, r5, lsl #20 @ flags + kernel base
- str r3, [r4, r5, lsl #2] @ identity mapping
- teq r5, r6
- addne r5, r5, #1 @ next section
- bne 1b
+1: orr r3, r7, r5, lsl #SECTION_SHIFT @ flags + kernel base
+ str r3, [r4, r5, lsl #PMD_ORDER] @ identity mapping
+ cmp r5, r6
+ addlo r5, r5, #1 @ next section
+ blo 1b
/*
* Now setup the pagetables for our kernel direct
* mapped region.
*/
mov r3, pc
- mov r3, r3, lsr #20
- orr r3, r7, r3, lsl #20
- add r0, r4, #(KERNEL_START & 0xff000000) >> 18
- str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
+ mov r3, r3, lsr #SECTION_SHIFT
+ orr r3, r7, r3, lsl #SECTION_SHIFT
+ add r0, r4, #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER)
+ str r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]!
ldr r6, =(KERNEL_END - 1)
- add r0, r0, #4
- add r6, r4, r6, lsr #18
+ add r0, r0, #1 << PMD_ORDER
+ add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)
1: cmp r0, r6
- add r3, r3, #1 << 20
- strls r3, [r0], #4
+ add r3, r3, #1 << SECTION_SHIFT
+ strls r3, [r0], #1 << PMD_ORDER
bls 1b
#ifdef CONFIG_XIP_KERNEL
@@ -203,11 +207,11 @@ __create_page_tables:
*/
add r3, r8, #TEXT_OFFSET
orr r3, r3, r7
- add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18
- str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
+ add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER)
+ str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]!
ldr r6, =(_end - 1)
add r0, r0, #4
- add r6, r4, r6, lsr #18
+ add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)
1: cmp r0, r6
add r3, r3, #1 << 20
strls r3, [r0], #4
@@ -218,12 +222,12 @@ __create_page_tables:
* Then map boot params address in r2 or
* the first 1MB of ram if boot params address is not specified.
*/
- mov r0, r2, lsr #20
- movs r0, r0, lsl #20
+ mov r0, r2, lsr #SECTION_SHIFT
+ movs r0, r0, lsl #SECTION_SHIFT
moveq r0, r8
sub r3, r0, r8
add r3, r3, #PAGE_OFFSET
- add r3, r4, r3, lsr #18
+ add r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
orr r6, r7, r0
str r6, [r3]
@@ -234,23 +238,23 @@ __create_page_tables:
* This allows debug messages to be output
* via a serial console before paging_init.
*/
- addruart r7, r3
+ addruart r7, r3, r0
- mov r3, r3, lsr #20
- mov r3, r3, lsl #2
+ mov r3, r3, lsr #SECTION_SHIFT
+ mov r3, r3, lsl #PMD_ORDER
add r0, r4, r3
rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long)
cmp r3, #0x0800 @ limit to 512MB
movhi r3, #0x0800
add r6, r0, r3
- mov r3, r7, lsr #20
+ mov r3, r7, lsr #SECTION_SHIFT
ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
- orr r3, r7, r3, lsl #20
+ orr r3, r7, r3, lsl #SECTION_SHIFT
1: str r3, [r0], #4
- add r3, r3, #1 << 20
- teq r0, r6
- bne 1b
+ add r3, r3, #1 << SECTION_SHIFT
+ cmp r0, r6
+ blo 1b
#else /* CONFIG_DEBUG_ICEDCC */
/* we don't need any serial debugging mappings for ICEDCC */
@@ -262,7 +266,7 @@ __create_page_tables:
* If we're using the NetWinder or CATS, we also need to map
* in the 16550-type serial port for the debug messages
*/
- add r0, r4, #0xff000000 >> 18
+ add r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER)
orr r3, r7, #0x7c000000
str r3, [r0]
#endif
@@ -272,10 +276,10 @@ __create_page_tables:
* Similar reasons here - for debug. This is
* only for Acorn RiscPC architectures.
*/
- add r0, r4, #0x02000000 >> 18
+ add r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER)
orr r3, r7, #0x02000000
str r3, [r0]
- add r0, r4, #0xd8000000 >> 18
+ add r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER)
str r3, [r0]
#endif
#endif
@@ -488,13 +492,8 @@ __fixup_pv_table:
add r5, r5, r3 @ adjust table end address
add r7, r7, r3 @ adjust __pv_phys_offset address
str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset
-#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
mov r6, r3, lsr #24 @ constant for add/sub instructions
teq r3, r6, lsl #24 @ must be 16MiB aligned
-#else
- mov r6, r3, lsr #16 @ constant for add/sub instructions
- teq r3, r6, lsl #16 @ must be 64kiB aligned
-#endif
THUMB( it ne @ cross section branch )
bne __error
str r6, [r7, #4] @ save to __pv_offset
@@ -510,20 +509,8 @@ ENDPROC(__fixup_pv_table)
.text
__fixup_a_pv_table:
#ifdef CONFIG_THUMB2_KERNEL
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
- lsls r0, r6, #24
- lsr r6, #8
- beq 1f
- clz r7, r0
- lsr r0, #24
- lsl r0, r7
- bic r0, 0x0080
- lsrs r7, #1
- orrcs r0, #0x0080
- orr r0, r0, r7, lsl #12
-#endif
-1: lsls r6, #24
- beq 4f
+ lsls r6, #24
+ beq 2f
clz r7, r6
lsr r6, #24
lsl r6, r7
@@ -532,43 +519,25 @@ __fixup_a_pv_table:
orrcs r6, #0x0080
orr r6, r6, r7, lsl #12
orr r6, #0x4000
- b 4f
-2: @ at this point the C flag is always clear
- add r7, r3
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
- ldrh ip, [r7]
- tst ip, 0x0400 @ the i bit tells us LS or MS byte
- beq 3f
- cmp r0, #0 @ set C flag, and ...
- biceq ip, 0x0400 @ immediate zero value has a special encoding
- streqh ip, [r7] @ that requires the i bit cleared
-#endif
-3: ldrh ip, [r7, #2]
+ b 2f
+1: add r7, r3
+ ldrh ip, [r7, #2]
and ip, 0x8f00
- orrcc ip, r6 @ mask in offset bits 31-24
- orrcs ip, r0 @ mask in offset bits 23-16
+ orr ip, r6 @ mask in offset bits 31-24
strh ip, [r7, #2]
-4: cmp r4, r5
+2: cmp r4, r5
ldrcc r7, [r4], #4 @ use branch for delay slot
- bcc 2b
+ bcc 1b
bx lr
#else
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
- and r0, r6, #255 @ offset bits 23-16
- mov r6, r6, lsr #8 @ offset bits 31-24
-#else
- mov r0, #0 @ just in case...
-#endif
- b 3f
-2: ldr ip, [r7, r3]
+ b 2f
+1: ldr ip, [r7, r3]
bic ip, ip, #0x000000ff
- tst ip, #0x400 @ rotate shift tells us LS or MS byte
- orrne ip, ip, r6 @ mask in offset bits 31-24
- orreq ip, ip, r0 @ mask in offset bits 23-16
+ orr ip, ip, r6 @ mask in offset bits 31-24
str ip, [r7, r3]
-3: cmp r4, r5
+2: cmp r4, r5
ldrcc r7, [r4], #4 @ use branch for delay slot
- bcc 2b
+ bcc 1b
mov pc, lr
#endif
ENDPROC(__fixup_a_pv_table)
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index a927ca1f5566..814a52a9dc39 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -45,7 +45,6 @@ static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]);
/* Number of BRP/WRP registers on this CPU. */
static int core_num_brps;
-static int core_num_reserved_brps;
static int core_num_wrps;
/* Debug architecture version. */
@@ -137,10 +136,11 @@ static u8 get_debug_arch(void)
u32 didr;
/* Do we implement the extended CPUID interface? */
- if (WARN_ONCE((((read_cpuid_id() >> 16) & 0xf) != 0xf),
- "CPUID feature registers not supported. "
- "Assuming v6 debug is present.\n"))
+ if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
+ pr_warning("CPUID feature registers not supported. "
+ "Assuming v6 debug is present.\n");
return ARM_DEBUG_ARCH_V6;
+ }
ARM_DBG_READ(c0, 0, didr);
return (didr >> 16) & 0xf;
@@ -154,10 +154,21 @@ u8 arch_get_debug_arch(void)
static int debug_arch_supported(void)
{
u8 arch = get_debug_arch();
- return arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14;
+
+ /* We don't support the memory-mapped interface. */
+ return (arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14) ||
+ arch >= ARM_DEBUG_ARCH_V7_1;
+}
+
+/* Determine number of WRP registers available. */
+static int get_num_wrp_resources(void)
+{
+ u32 didr;
+ ARM_DBG_READ(c0, 0, didr);
+ return ((didr >> 28) & 0xf) + 1;
}
-/* Determine number of BRP register available. */
+/* Determine number of BRP registers available. */
static int get_num_brp_resources(void)
{
u32 didr;
@@ -176,9 +187,10 @@ static int core_has_mismatch_brps(void)
static int get_num_wrps(void)
{
/*
- * FIXME: When a watchpoint fires, the only way to work out which
- * watchpoint it was is by disassembling the faulting instruction
- * and working out the address of the memory access.
+ * On debug architectures prior to 7.1, when a watchpoint fires, the
+ * only way to work out which watchpoint it was is by disassembling
+ * the faulting instruction and working out the address of the memory
+ * access.
*
* Furthermore, we can only do this if the watchpoint was precise
* since imprecise watchpoints prevent us from calculating register
@@ -192,36 +204,17 @@ static int get_num_wrps(void)
* [the ARM ARM states that the DFAR is UNKNOWN, but experience shows
* that it is set on some implementations].
*/
+ if (get_debug_arch() < ARM_DEBUG_ARCH_V7_1)
+ return 1;
-#if 0
- int wrps;
- u32 didr;
- ARM_DBG_READ(c0, 0, didr);
- wrps = ((didr >> 28) & 0xf) + 1;
-#endif
- int wrps = 1;
-
- if (core_has_mismatch_brps() && wrps >= get_num_brp_resources())
- wrps = get_num_brp_resources() - 1;
-
- return wrps;
-}
-
-/* We reserve one breakpoint for each watchpoint. */
-static int get_num_reserved_brps(void)
-{
- if (core_has_mismatch_brps())
- return get_num_wrps();
- return 0;
+ return get_num_wrp_resources();
}
/* Determine number of usable BRPs available. */
static int get_num_brps(void)
{
int brps = get_num_brp_resources();
- if (core_has_mismatch_brps())
- brps -= get_num_reserved_brps();
- return brps;
+ return core_has_mismatch_brps() ? brps - 1 : brps;
}
/*
@@ -239,7 +232,7 @@ static int enable_monitor_mode(void)
/* Ensure that halting mode is disabled. */
if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
- "halting debug mode enabled. Unable to access hardware resources.\n")) {
+ "halting debug mode enabled. Unable to access hardware resources.\n")) {
ret = -EPERM;
goto out;
}
@@ -255,6 +248,7 @@ static int enable_monitor_mode(void)
ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
break;
case ARM_DEBUG_ARCH_V7_ECP14:
+ case ARM_DEBUG_ARCH_V7_1:
ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));
break;
default:
@@ -346,24 +340,10 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
val_base = ARM_BASE_BVR;
slots = (struct perf_event **)__get_cpu_var(bp_on_reg);
max_slots = core_num_brps;
- if (info->step_ctrl.enabled) {
- /* Override the breakpoint data with the step data. */
- addr = info->trigger & ~0x3;
- ctrl = encode_ctrl_reg(info->step_ctrl);
- }
} else {
/* Watchpoint */
- if (info->step_ctrl.enabled) {
- /* Install into the reserved breakpoint region. */
- ctrl_base = ARM_BASE_BCR + core_num_brps;
- val_base = ARM_BASE_BVR + core_num_brps;
- /* Override the watchpoint data with the step data. */
- addr = info->trigger & ~0x3;
- ctrl = encode_ctrl_reg(info->step_ctrl);
- } else {
- ctrl_base = ARM_BASE_WCR;
- val_base = ARM_BASE_WVR;
- }
+ ctrl_base = ARM_BASE_WCR;
+ val_base = ARM_BASE_WVR;
slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
max_slots = core_num_wrps;
}
@@ -382,6 +362,17 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
goto out;
}
+ /* Override the breakpoint data with the step data. */
+ if (info->step_ctrl.enabled) {
+ addr = info->trigger & ~0x3;
+ ctrl = encode_ctrl_reg(info->step_ctrl);
+ if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE) {
+ i = 0;
+ ctrl_base = ARM_BASE_BCR + core_num_brps;
+ val_base = ARM_BASE_BVR + core_num_brps;
+ }
+ }
+
/* Setup the address register. */
write_wb_reg(val_base + i, addr);
@@ -405,10 +396,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
max_slots = core_num_brps;
} else {
/* Watchpoint */
- if (info->step_ctrl.enabled)
- base = ARM_BASE_BCR + core_num_brps;
- else
- base = ARM_BASE_WCR;
+ base = ARM_BASE_WCR;
slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
max_slots = core_num_wrps;
}
@@ -426,6 +414,13 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
return;
+ /* Ensure that we disable the mismatch breakpoint. */
+ if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE &&
+ info->step_ctrl.enabled) {
+ i = 0;
+ base = ARM_BASE_BCR + core_num_brps;
+ }
+
/* Reset the control register. */
write_wb_reg(base + i, 0);
}
@@ -632,10 +627,9 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
* we can use the mismatch feature as a poor-man's hardware
* single-step, but this only works for per-task breakpoints.
*/
- if (WARN_ONCE(!bp->overflow_handler &&
- (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()
- || !bp->hw.bp_target),
- "overflow handler required but none found\n")) {
+ if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) ||
+ !core_has_mismatch_brps() || !bp->hw.bp_target)) {
+ pr_warning("overflow handler required but none found\n");
ret = -EINVAL;
}
out:
@@ -666,34 +660,62 @@ static void disable_single_step(struct perf_event *bp)
arch_install_hw_breakpoint(bp);
}
-static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
+static void watchpoint_handler(unsigned long addr, unsigned int fsr,
+ struct pt_regs *regs)
{
- int i;
+ int i, access;
+ u32 val, ctrl_reg, alignment_mask;
struct perf_event *wp, **slots;
struct arch_hw_breakpoint *info;
+ struct arch_hw_breakpoint_ctrl ctrl;
slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
- /* Without a disassembler, we can only handle 1 watchpoint. */
- BUG_ON(core_num_wrps > 1);
-
for (i = 0; i < core_num_wrps; ++i) {
rcu_read_lock();
wp = slots[i];
- if (wp == NULL) {
- rcu_read_unlock();
- continue;
- }
+ if (wp == NULL)
+ goto unlock;
+ info = counter_arch_bp(wp);
/*
- * The DFAR is an unknown value. Since we only allow a
- * single watchpoint, we can set the trigger to the lowest
- * possible faulting address.
+ * The DFAR is an unknown value on debug architectures prior
+ * to 7.1. Since we only allow a single watchpoint on these
+ * older CPUs, we can set the trigger to the lowest possible
+ * faulting address.
*/
- info = counter_arch_bp(wp);
- info->trigger = wp->attr.bp_addr;
+ if (debug_arch < ARM_DEBUG_ARCH_V7_1) {
+ BUG_ON(i > 0);
+ info->trigger = wp->attr.bp_addr;
+ } else {
+ if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
+ alignment_mask = 0x7;
+ else
+ alignment_mask = 0x3;
+
+ /* Check if the watchpoint value matches. */
+ val = read_wb_reg(ARM_BASE_WVR + i);
+ if (val != (addr & ~alignment_mask))
+ goto unlock;
+
+ /* Possible match, check the byte address select. */
+ ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
+ decode_ctrl_reg(ctrl_reg, &ctrl);
+ if (!((1 << (addr & alignment_mask)) & ctrl.len))
+ goto unlock;
+
+ /* Check that the access type matches. */
+ access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W :
+ HW_BREAKPOINT_R;
+ if (!(access & hw_breakpoint_type(wp)))
+ goto unlock;
+
+ /* We have a winner. */
+ info->trigger = addr;
+ }
+
pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
perf_bp_event(wp, regs);
@@ -705,6 +727,7 @@ static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
if (!wp->overflow_handler)
enable_single_step(wp, instruction_pointer(regs));
+unlock:
rcu_read_unlock();
}
}
@@ -717,7 +740,7 @@ static void watchpoint_single_step_handler(unsigned long pc)
slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
- for (i = 0; i < core_num_reserved_brps; ++i) {
+ for (i = 0; i < core_num_wrps; ++i) {
rcu_read_lock();
wp = slots[i];
@@ -820,7 +843,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
case ARM_ENTRY_ASYNC_WATCHPOINT:
WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n");
case ARM_ENTRY_SYNC_WATCHPOINT:
- watchpoint_handler(addr, regs);
+ watchpoint_handler(addr, fsr, regs);
break;
default:
ret = 1; /* Unhandled fault. */
@@ -834,11 +857,31 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
/*
* One-time initialisation.
*/
-static void reset_ctrl_regs(void *info)
+static cpumask_t debug_err_mask;
+
+static int debug_reg_trap(struct pt_regs *regs, unsigned int instr)
{
- int i, cpu = smp_processor_id();
+ int cpu = smp_processor_id();
+
+ pr_warning("Debug register access (0x%x) caused undefined instruction on CPU %d\n",
+ instr, cpu);
+
+ /* Set the error flag for this CPU and skip the faulting instruction. */
+ cpumask_set_cpu(cpu, &debug_err_mask);
+ instruction_pointer(regs) += 4;
+ return 0;
+}
+
+static struct undef_hook debug_reg_hook = {
+ .instr_mask = 0x0fe80f10,
+ .instr_val = 0x0e000e10,
+ .fn = debug_reg_trap,
+};
+
+static void reset_ctrl_regs(void *unused)
+{
+ int i, raw_num_brps, err = 0, cpu = smp_processor_id();
u32 dbg_power;
- cpumask_t *cpumask = info;
/*
* v7 debug contains save and restore registers so that debug state
@@ -848,38 +891,57 @@ static void reset_ctrl_regs(void *info)
* Access Register to avoid taking undefined instruction exceptions
* later on.
*/
- if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) {
+ switch (debug_arch) {
+ case ARM_DEBUG_ARCH_V6:
+ case ARM_DEBUG_ARCH_V6_1:
+ /* ARMv6 cores just need to reset the registers. */
+ goto reset_regs;
+ case ARM_DEBUG_ARCH_V7_ECP14:
/*
* Ensure sticky power-down is clear (i.e. debug logic is
* powered up).
*/
asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power));
- if ((dbg_power & 0x1) == 0) {
- pr_warning("CPU %d debug is powered down!\n", cpu);
- cpumask_or(cpumask, cpumask, cpumask_of(cpu));
- return;
- }
-
+ if ((dbg_power & 0x1) == 0)
+ err = -EPERM;
+ break;
+ case ARM_DEBUG_ARCH_V7_1:
/*
- * Unconditionally clear the lock by writing a value
- * other than 0xC5ACCE55 to the access register.
+ * Ensure the OS double lock is clear.
*/
- asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
- isb();
+ asm volatile("mrc p14, 0, %0, c1, c3, 4" : "=r" (dbg_power));
+ if ((dbg_power & 0x1) == 1)
+ err = -EPERM;
+ break;
+ }
- /*
- * Clear any configured vector-catch events before
- * enabling monitor mode.
- */
- asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
- isb();
+ if (err) {
+ pr_warning("CPU %d debug is powered down!\n", cpu);
+ cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
+ return;
}
+ /*
+ * Unconditionally clear the lock by writing a value
+ * other than 0xC5ACCE55 to the access register.
+ */
+ asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
+ isb();
+
+ /*
+ * Clear any configured vector-catch events before
+ * enabling monitor mode.
+ */
+ asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
+ isb();
+
+reset_regs:
if (enable_monitor_mode())
return;
/* We must also reset any reserved registers. */
- for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
+ raw_num_brps = get_num_brp_resources();
+ for (i = 0; i < raw_num_brps; ++i) {
write_wb_reg(ARM_BASE_BCR + i, 0UL);
write_wb_reg(ARM_BASE_BVR + i, 0UL);
}
@@ -895,6 +957,7 @@ static int __cpuinit dbg_reset_notify(struct notifier_block *self,
{
if (action == CPU_ONLINE)
smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
+
return NOTIFY_OK;
}
@@ -905,7 +968,6 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = {
static int __init arch_hw_breakpoint_init(void)
{
u32 dscr;
- cpumask_t cpumask = { CPU_BITS_NONE };
debug_arch = get_debug_arch();
@@ -916,28 +978,31 @@ static int __init arch_hw_breakpoint_init(void)
/* Determine how many BRPs/WRPs are available. */
core_num_brps = get_num_brps();
- core_num_reserved_brps = get_num_reserved_brps();
core_num_wrps = get_num_wrps();
- pr_info("found %d breakpoint and %d watchpoint registers.\n",
- core_num_brps + core_num_reserved_brps, core_num_wrps);
-
- if (core_num_reserved_brps)
- pr_info("%d breakpoint(s) reserved for watchpoint "
- "single-step.\n", core_num_reserved_brps);
+ /*
+ * We need to tread carefully here because DBGSWENABLE may be
+ * driven low on this core and there isn't an architected way to
+ * determine that.
+ */
+ register_undef_hook(&debug_reg_hook);
/*
* Reset the breakpoint resources. We assume that a halting
* debugger will leave the world in a nice state for us.
*/
- on_each_cpu(reset_ctrl_regs, &cpumask, 1);
- if (!cpumask_empty(&cpumask)) {
+ on_each_cpu(reset_ctrl_regs, NULL, 1);
+ unregister_undef_hook(&debug_reg_hook);
+ if (!cpumask_empty(&debug_err_mask)) {
core_num_brps = 0;
- core_num_reserved_brps = 0;
core_num_wrps = 0;
return 0;
}
+ pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n",
+ core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " :
+ "", core_num_wrps);
+
ARM_DBG_READ(c1, 0, dscr);
if (dscr & ARM_DSCR_HDBGEN) {
max_watchpoint_len = 4;
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index de3dcab8610b..7cb29261249a 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -35,8 +35,8 @@
#include <linux/list.h>
#include <linux/kallsyms.h>
#include <linux/proc_fs.h>
-#include <linux/ftrace.h>
+#include <asm/exception.h>
#include <asm/system.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
@@ -59,9 +59,6 @@ int arch_show_interrupts(struct seq_file *p, int prec)
#ifdef CONFIG_SMP
show_ipi_list(p, prec);
#endif
-#ifdef CONFIG_LOCAL_TIMERS
- show_local_irqs(p, prec);
-#endif
seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
return 0;
}
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 79203ee1d039..9fe8910308af 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -60,6 +60,7 @@
#include <linux/kernel.h>
#include <linux/kprobes.h>
+#include <linux/module.h>
#include "kprobes.h"
@@ -971,6 +972,9 @@ const union decode_item kprobe_decode_arm_table[] = {
DECODE_END
};
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
+#endif
static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
{
diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c
new file mode 100644
index 000000000000..fc82de8bdcce
--- /dev/null
+++ b/arch/arm/kernel/kprobes-test-arm.c
@@ -0,0 +1,1323 @@
+/*
+ * arch/arm/kernel/kprobes-test-arm.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * 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/module.h>
+
+#include "kprobes-test.h"
+
+
+#define TEST_ISA "32"
+
+#define TEST_ARM_TO_THUMB_INTERWORK_R(code1, reg, val, code2) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_REG(14, 99f) \
+ TEST_ARG_END("") \
+ "50: nop \n\t" \
+ "1: "code1 #reg code2" \n\t" \
+ " bx lr \n\t" \
+ ".thumb \n\t" \
+ "3: adr lr, 2f \n\t" \
+ " bx lr \n\t" \
+ ".arm \n\t" \
+ "2: nop \n\t" \
+ TESTCASE_END
+
+#define TEST_ARM_TO_THUMB_INTERWORK_P(code1, reg, val, code2) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_PTR(reg, val) \
+ TEST_ARG_REG(14, 99f) \
+ TEST_ARG_MEM(15, 3f+1) \
+ TEST_ARG_END("") \
+ "50: nop \n\t" \
+ "1: "code1 #reg code2" \n\t" \
+ " bx lr \n\t" \
+ ".thumb \n\t" \
+ "3: adr lr, 2f \n\t" \
+ " bx lr \n\t" \
+ ".arm \n\t" \
+ "2: nop \n\t" \
+ TESTCASE_END
+
+
+void kprobe_arm_test_cases(void)
+{
+ kprobe_test_flags = 0;
+
+ TEST_GROUP("Data-processing (register), (register-shifted register), (immediate)")
+
+#define _DATA_PROCESSING_DNM(op,s,val) \
+ TEST_RR( op "eq" s " r0, r",1, VAL1,", r",2, val, "") \
+ TEST_RR( op "ne" s " r1, r",1, VAL1,", r",2, val, ", lsl #3") \
+ TEST_RR( op "cs" s " r2, r",3, VAL1,", r",2, val, ", lsr #4") \
+ TEST_RR( op "cc" s " r3, r",3, VAL1,", r",2, val, ", asr #5") \
+ TEST_RR( op "mi" s " r4, r",5, VAL1,", r",2, N(val),", asr #6") \
+ TEST_RR( op "pl" s " r5, r",5, VAL1,", r",2, val, ", ror #7") \
+ TEST_RR( op "vs" s " r6, r",7, VAL1,", r",2, val, ", rrx") \
+ TEST_R( op "vc" s " r6, r",7, VAL1,", pc, lsl #3") \
+ TEST_R( op "vc" s " r6, r",7, VAL1,", sp, lsr #4") \
+ TEST_R( op "vc" s " r6, pc, r",7, VAL1,", asr #5") \
+ TEST_R( op "vc" s " r6, sp, r",7, VAL1,", ror #6") \
+ TEST_RRR( op "hi" s " r8, r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")\
+ TEST_RRR( op "ls" s " r9, r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")\
+ TEST_RRR( op "ge" s " r10, r",11,VAL1,", r",14,val, ", asr r",7, 5,"")\
+ TEST_RRR( op "lt" s " r11, r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")\
+ TEST_RR( op "gt" s " r12, r13" ", r",14,val, ", ror r",14,7,"")\
+ TEST_RR( op "le" s " r14, r",0, val, ", r13" ", lsl r",14,8,"")\
+ TEST_RR( op s " r12, pc" ", r",14,val, ", ror r",14,7,"")\
+ TEST_RR( op s " r14, r",0, val, ", pc" ", lsl r",14,8,"")\
+ TEST_R( op "eq" s " r0, r",11,VAL1,", #0xf5") \
+ TEST_R( op "ne" s " r11, r",0, VAL1,", #0xf5000000") \
+ TEST_R( op s " r7, r",8, VAL2,", #0x000af000") \
+ TEST( op s " r4, pc" ", #0x00005a00")
+
+#define DATA_PROCESSING_DNM(op,val) \
+ _DATA_PROCESSING_DNM(op,"",val) \
+ _DATA_PROCESSING_DNM(op,"s",val)
+
+#define DATA_PROCESSING_NM(op,val) \
+ TEST_RR( op "ne r",1, VAL1,", r",2, val, "") \
+ TEST_RR( op "eq r",1, VAL1,", r",2, val, ", lsl #3") \
+ TEST_RR( op "cc r",3, VAL1,", r",2, val, ", lsr #4") \
+ TEST_RR( op "cs r",3, VAL1,", r",2, val, ", asr #5") \
+ TEST_RR( op "pl r",5, VAL1,", r",2, N(val),", asr #6") \
+ TEST_RR( op "mi r",5, VAL1,", r",2, val, ", ror #7") \
+ TEST_RR( op "vc r",7, VAL1,", r",2, val, ", rrx") \
+ TEST_R ( op "vs r",7, VAL1,", pc, lsl #3") \
+ TEST_R ( op "vs r",7, VAL1,", sp, lsr #4") \
+ TEST_R( op "vs pc, r",7, VAL1,", asr #5") \
+ TEST_R( op "vs sp, r",7, VAL1,", ror #6") \
+ TEST_RRR( op "ls r",9, VAL1,", r",14,val, ", lsl r",0, 3,"") \
+ TEST_RRR( op "hi r",9, VAL1,", r",14,val, ", lsr r",7, 4,"") \
+ TEST_RRR( op "lt r",11,VAL1,", r",14,val, ", asr r",7, 5,"") \
+ TEST_RRR( op "ge r",11,VAL1,", r",14,N(val),", asr r",7, 6,"") \
+ TEST_RR( op "le r13" ", r",14,val, ", ror r",14,7,"") \
+ TEST_RR( op "gt r",0, val, ", r13" ", lsl r",14,8,"") \
+ TEST_RR( op " pc" ", r",14,val, ", ror r",14,7,"") \
+ TEST_RR( op " r",0, val, ", pc" ", lsl r",14,8,"") \
+ TEST_R( op "eq r",11,VAL1,", #0xf5") \
+ TEST_R( op "ne r",0, VAL1,", #0xf5000000") \
+ TEST_R( op " r",8, VAL2,", #0x000af000")
+
+#define _DATA_PROCESSING_DM(op,s,val) \
+ TEST_R( op "eq" s " r0, r",1, val, "") \
+ TEST_R( op "ne" s " r1, r",1, val, ", lsl #3") \
+ TEST_R( op "cs" s " r2, r",3, val, ", lsr #4") \
+ TEST_R( op "cc" s " r3, r",3, val, ", asr #5") \
+ TEST_R( op "mi" s " r4, r",5, N(val),", asr #6") \
+ TEST_R( op "pl" s " r5, r",5, val, ", ror #7") \
+ TEST_R( op "vs" s " r6, r",10,val, ", rrx") \
+ TEST( op "vs" s " r7, pc, lsl #3") \
+ TEST( op "vs" s " r7, sp, lsr #4") \
+ TEST_RR( op "vc" s " r8, r",7, val, ", lsl r",0, 3,"") \
+ TEST_RR( op "hi" s " r9, r",9, val, ", lsr r",7, 4,"") \
+ TEST_RR( op "ls" s " r10, r",9, val, ", asr r",7, 5,"") \
+ TEST_RR( op "ge" s " r11, r",11,N(val),", asr r",7, 6,"") \
+ TEST_RR( op "lt" s " r12, r",11,val, ", ror r",14,7,"") \
+ TEST_R( op "gt" s " r14, r13" ", lsl r",14,8,"") \
+ TEST_R( op "le" s " r14, pc" ", lsl r",14,8,"") \
+ TEST( op "eq" s " r0, #0xf5") \
+ TEST( op "ne" s " r11, #0xf5000000") \
+ TEST( op s " r7, #0x000af000") \
+ TEST( op s " r4, #0x00005a00")
+
+#define DATA_PROCESSING_DM(op,val) \
+ _DATA_PROCESSING_DM(op,"",val) \
+ _DATA_PROCESSING_DM(op,"s",val)
+
+ DATA_PROCESSING_DNM("and",0xf00f00ff)
+ DATA_PROCESSING_DNM("eor",0xf00f00ff)
+ DATA_PROCESSING_DNM("sub",VAL2)
+ DATA_PROCESSING_DNM("rsb",VAL2)
+ DATA_PROCESSING_DNM("add",VAL2)
+ DATA_PROCESSING_DNM("adc",VAL2)
+ DATA_PROCESSING_DNM("sbc",VAL2)
+ DATA_PROCESSING_DNM("rsc",VAL2)
+ DATA_PROCESSING_NM("tst",0xf00f00ff)
+ DATA_PROCESSING_NM("teq",0xf00f00ff)
+ DATA_PROCESSING_NM("cmp",VAL2)
+ DATA_PROCESSING_NM("cmn",VAL2)
+ DATA_PROCESSING_DNM("orr",0xf00f00ff)
+ DATA_PROCESSING_DM("mov",VAL2)
+ DATA_PROCESSING_DNM("bic",0xf00f00ff)
+ DATA_PROCESSING_DM("mvn",VAL2)
+
+ TEST("mov ip, sp") /* This has special case emulation code */
+
+ TEST_SUPPORTED("mov pc, #0x1000");
+ TEST_SUPPORTED("mov sp, #0x1000");
+ TEST_SUPPORTED("cmp pc, #0x1000");
+ TEST_SUPPORTED("cmp sp, #0x1000");
+
+ /* Data-processing with PC as shift*/
+ TEST_UNSUPPORTED(".word 0xe15c0f1e @ cmp r12, r14, asl pc")
+ TEST_UNSUPPORTED(".word 0xe1a0cf1e @ mov r12, r14, asl pc")
+ TEST_UNSUPPORTED(".word 0xe08caf1e @ add r10, r12, r14, asl pc")
+
+ /* Data-processing with PC as shift*/
+ TEST_UNSUPPORTED("movs pc, r1")
+ TEST_UNSUPPORTED("movs pc, r1, lsl r2")
+ TEST_UNSUPPORTED("movs pc, #0x10000")
+ TEST_UNSUPPORTED("adds pc, lr, r1")
+ TEST_UNSUPPORTED("adds pc, lr, r1, lsl r2")
+ TEST_UNSUPPORTED("adds pc, lr, #4")
+
+ /* Data-processing with SP as target */
+ TEST("add sp, sp, #16")
+ TEST("sub sp, sp, #8")
+ TEST("bic sp, sp, #0x20")
+ TEST("orr sp, sp, #0x20")
+ TEST_PR( "add sp, r",10,0,", r",11,4,"")
+ TEST_PRR("add sp, r",10,0,", r",11,4,", asl r",12,1,"")
+ TEST_P( "mov sp, r",10,0,"")
+ TEST_PR( "mov sp, r",10,0,", asl r",12,0,"")
+
+ /* Data-processing with PC as target */
+ TEST_BF( "add pc, pc, #2f-1b-8")
+ TEST_BF_R ("add pc, pc, r",14,2f-1f-8,"")
+ TEST_BF_R ("add pc, r",14,2f-1f-8,", pc")
+ TEST_BF_R ("mov pc, r",0,2f,"")
+ TEST_BF_RR("mov pc, r",0,2f,", asl r",1,0,"")
+ TEST_BB( "sub pc, pc, #1b-2b+8")
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before ARMv6 */
+#endif
+ TEST_BB_R( "sub pc, pc, r",14, 1f-2f+8,"")
+ TEST_BB_R( "rsb pc, r",14,1f-2f+8,", pc")
+ TEST_RR( "add pc, pc, r",10,-2,", asl r",11,1,"")
+#ifdef CONFIG_THUMB2_KERNEL
+ TEST_ARM_TO_THUMB_INTERWORK_R("add pc, pc, r",0,3f-1f-8+1,"")
+ TEST_ARM_TO_THUMB_INTERWORK_R("sub pc, r",0,3f+8+1,", #8")
+#endif
+ TEST_GROUP("Miscellaneous instructions")
+
+ TEST("mrs r0, cpsr")
+ TEST("mrspl r7, cpsr")
+ TEST("mrs r14, cpsr")
+ TEST_UNSUPPORTED(".word 0xe10ff000 @ mrs r15, cpsr")
+ TEST_UNSUPPORTED("mrs r0, spsr")
+ TEST_UNSUPPORTED("mrs lr, spsr")
+
+ TEST_UNSUPPORTED("msr cpsr, r0")
+ TEST_UNSUPPORTED("msr cpsr_f, lr")
+ TEST_UNSUPPORTED("msr spsr, r0")
+
+ TEST_BF_R("bx r",0,2f,"")
+ TEST_BB_R("bx r",7,2f,"")
+ TEST_BF_R("bxeq r",14,2f,"")
+
+ TEST_R("clz r0, r",0, 0x0,"")
+ TEST_R("clzeq r7, r",14,0x1,"")
+ TEST_R("clz lr, r",7, 0xffffffff,"")
+ TEST( "clz r4, sp")
+ TEST_UNSUPPORTED(".word 0x016fff10 @ clz pc, r0")
+ TEST_UNSUPPORTED(".word 0x016f0f1f @ clz r0, pc")
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_UNSUPPORTED("bxj r0")
+#endif
+
+ TEST_BF_R("blx r",0,2f,"")
+ TEST_BB_R("blx r",7,2f,"")
+ TEST_BF_R("blxeq r",14,2f,"")
+ TEST_UNSUPPORTED(".word 0x0120003f @ blx pc")
+
+ TEST_RR( "qadd r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "qaddvs lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_R( "qadd lr, r",9, VAL2,", r13")
+ TEST_RR( "qsub r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "qsubvs lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_R( "qsub lr, r",9, VAL2,", r13")
+ TEST_RR( "qdadd r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "qdaddvs lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_R( "qdadd lr, r",9, VAL2,", r13")
+ TEST_RR( "qdsub r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "qdsubvs lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_R( "qdsub lr, r",9, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe101f050 @ qadd pc, r0, r1")
+ TEST_UNSUPPORTED(".word 0xe121f050 @ qsub pc, r0, r1")
+ TEST_UNSUPPORTED(".word 0xe141f050 @ qdadd pc, r0, r1")
+ TEST_UNSUPPORTED(".word 0xe161f050 @ qdsub pc, r0, r1")
+ TEST_UNSUPPORTED(".word 0xe16f2050 @ qdsub r2, r0, pc")
+ TEST_UNSUPPORTED(".word 0xe161205f @ qdsub r2, pc, r1")
+
+ TEST_UNSUPPORTED("bkpt 0xffff")
+ TEST_UNSUPPORTED("bkpt 0x0000")
+
+ TEST_UNSUPPORTED(".word 0xe1600070 @ smc #0")
+
+ TEST_GROUP("Halfword multiply and multiply-accumulate")
+
+ TEST_RRR( "smlabb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlabbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlabb lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe10f3281 @ smlabb pc, r1, r2, r3")
+ TEST_RRR( "smlatb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlatbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlatb lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe10f32a1 @ smlatb pc, r1, r2, r3")
+ TEST_RRR( "smlabt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlabtge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlabt lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe10f32c1 @ smlabt pc, r1, r2, r3")
+ TEST_RRR( "smlatt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlattge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlatt lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe10f32e1 @ smlatt pc, r1, r2, r3")
+
+ TEST_RRR( "smlawb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlawbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlawb lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe12f3281 @ smlawb pc, r1, r2, r3")
+ TEST_RRR( "smlawt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlawtge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smlawt lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe12f32c1 @ smlawt pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe12032cf @ smlawt r0, pc, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe1203fc1 @ smlawt r0, r1, pc, r3")
+ TEST_UNSUPPORTED(".word 0xe120f2c1 @ smlawt r0, r1, r2, pc")
+
+ TEST_RR( "smulwb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulwbge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smulwb lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe12f02a1 @ smulwb pc, r1, r2")
+ TEST_RR( "smulwt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulwtge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smulwt lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe12f02e1 @ smulwt pc, r1, r2")
+
+ TEST_RRRR( "smlalbb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalbble r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlalbb r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe14f1382 @ smlalbb pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe141f382 @ smlalbb r1, pc, r2, r3")
+ TEST_RRRR( "smlaltb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlaltble r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlaltb r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe14f13a2 @ smlaltb pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe141f3a2 @ smlaltb r1, pc, r2, r3")
+ TEST_RRRR( "smlalbt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalbtle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlalbt r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe14f13c2 @ smlalbt pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe141f3c2 @ smlalbt r1, pc, r2, r3")
+ TEST_RRRR( "smlaltt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalttle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlaltt r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe14f13e2 @ smlalbb pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe140f3e2 @ smlalbb r0, pc, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe14013ef @ smlalbb r0, r1, pc, r3")
+ TEST_UNSUPPORTED(".word 0xe1401fe2 @ smlalbb r0, r1, r2, pc")
+
+ TEST_RR( "smulbb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulbbge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smulbb lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe16f0281 @ smulbb pc, r1, r2")
+ TEST_RR( "smultb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smultbge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smultb lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe16f02a1 @ smultb pc, r1, r2")
+ TEST_RR( "smulbt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulbtge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smulbt lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe16f02c1 @ smultb pc, r1, r2")
+ TEST_RR( "smultt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulttge r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_R( "smultt lr, r",1, VAL2,", r13")
+ TEST_UNSUPPORTED(".word 0xe16f02e1 @ smultt pc, r1, r2")
+ TEST_UNSUPPORTED(".word 0xe16002ef @ smultt r0, pc, r2")
+ TEST_UNSUPPORTED(".word 0xe1600fe1 @ smultt r0, r1, pc")
+
+ TEST_GROUP("Multiply and multiply-accumulate")
+
+ TEST_RR( "mul r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "mulls r7, r",8, VAL2,", r",9, VAL2,"")
+ TEST_R( "mul lr, r",4, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe00f0291 @ mul pc, r1, r2")
+ TEST_UNSUPPORTED(".word 0xe000029f @ mul r0, pc, r2")
+ TEST_UNSUPPORTED(".word 0xe0000f91 @ mul r0, r1, pc")
+ TEST_RR( "muls r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "mullss r7, r",8, VAL2,", r",9, VAL2,"")
+ TEST_R( "muls lr, r",4, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe01f0291 @ muls pc, r1, r2")
+
+ TEST_RRR( "mla r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "mlahi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "mla lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe02f3291 @ mla pc, r1, r2, r3")
+ TEST_RRR( "mlas r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "mlahis r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "mlas lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe03f3291 @ mlas pc, r1, r2, r3")
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_RR( "umaal r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "umaalls r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_R( "umaal lr, r12, r",11,VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe041f392 @ umaal pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0500090 @ undef")
+ TEST_UNSUPPORTED(".word 0xe05fff9f @ undef")
+
+ TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "mlshi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "mls lr, r",1, VAL2,", r",2, VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe06f3291 @ mls pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe060329f @ mls r0, pc, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0603f91 @ mls r0, r1, pc, r3")
+ TEST_UNSUPPORTED(".word 0xe060f291 @ mls r0, r1, r2, pc")
+#endif
+
+ TEST_UNSUPPORTED(".word 0xe0700090 @ undef")
+ TEST_UNSUPPORTED(".word 0xe07fff9f @ undef")
+
+ TEST_RR( "umull r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "umullls r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_R( "umull lr, r12, r",11,VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe081f392 @ umull pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe08f1392 @ umull r1, pc, r2, r3")
+ TEST_RR( "umulls r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "umulllss r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_R( "umulls lr, r12, r",11,VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe091f392 @ umulls pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe09f1392 @ umulls r1, pc, r2, r3")
+
+ TEST_RRRR( "umlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "umlalle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "umlal r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe0af1392 @ umlal pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0a1f392 @ umlal r1, pc, r2, r3")
+ TEST_RRRR( "umlals r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "umlalles r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "umlals r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe0bf1392 @ umlals pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0b1f392 @ umlals r1, pc, r2, r3")
+
+ TEST_RR( "smull r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "smullls r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_R( "smull lr, r12, r",11,VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe0c1f392 @ smull pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0cf1392 @ smull r1, pc, r2, r3")
+ TEST_RR( "smulls r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "smulllss r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_R( "smulls lr, r12, r",11,VAL3,", r13")
+ TEST_UNSUPPORTED(".word 0xe0d1f392 @ smulls pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0df1392 @ smulls r1, pc, r2, r3")
+
+ TEST_RRRR( "smlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlal r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe0ef1392 @ smlal pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0e1f392 @ smlal r1, pc, r2, r3")
+ TEST_RRRR( "smlals r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalles r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRR( "smlals r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+ TEST_UNSUPPORTED(".word 0xe0ff1392 @ smlals pc, r1, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0f0f392 @ smlals r0, pc, r2, r3")
+ TEST_UNSUPPORTED(".word 0xe0f0139f @ smlals r0, r1, pc, r3")
+ TEST_UNSUPPORTED(".word 0xe0f01f92 @ smlals r0, r1, r2, pc")
+
+ TEST_GROUP("Synchronization primitives")
+
+ /*
+ * Use hard coded constants for SWP instructions to avoid warnings
+ * about deprecated instructions.
+ */
+ TEST_RP( ".word 0xe108e097 @ swp lr, r",7,VAL2,", [r",8,0,"]")
+ TEST_R( ".word 0x610d0091 @ swpvs r0, r",1,VAL1,", [sp]")
+ TEST_RP( ".word 0xe10cd09e @ swp sp, r",14,VAL2,", [r",12,13*4,"]")
+ TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]")
+ TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]")
+ TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]")
+ TEST_RP( ".word 0xe148e097 @ swpb lr, r",7,VAL2,", [r",8,0,"]")
+ TEST_R( ".word 0x614d0091 @ swpvsb r0, r",1,VAL1,", [sp]")
+ TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]")
+
+ TEST_UNSUPPORTED(".word 0xe1100090") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe1200090") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe1300090") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe1500090") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe1600090") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe1700090") /* Unallocated space */
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_UNSUPPORTED("ldrex r2, [sp]")
+ TEST_UNSUPPORTED("strexd r0, r2, r3, [sp]")
+ TEST_UNSUPPORTED("ldrexd r2, r3, [sp]")
+ TEST_UNSUPPORTED("strexb r0, r2, [sp]")
+ TEST_UNSUPPORTED("ldrexb r2, [sp]")
+ TEST_UNSUPPORTED("strexh r0, r2, [sp]")
+ TEST_UNSUPPORTED("ldrexh r2, [sp]")
+#endif
+ TEST_GROUP("Extra load/store instructions")
+
+ TEST_RPR( "strh r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")
+ TEST_RPR( "streqh r",14,VAL2,", [r",13,0, ", r",12, 48,"]")
+ TEST_RPR( "strh r",1, VAL1,", [r",2, 24,", r",3, 48,"]!")
+ TEST_RPR( "strneh r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
+ TEST_RPR( "strh r",2, VAL1,", [r",3, 24,"], r",4, 48,"")
+ TEST_RPR( "strh r",10,VAL2,", [r",9, 48,"], -r",11,24,"")
+ TEST_UNSUPPORTED(".word 0xe1afc0ba @ strh r12, [pc, r10]!")
+ TEST_UNSUPPORTED(".word 0xe089f0bb @ strh pc, [r9], r11")
+ TEST_UNSUPPORTED(".word 0xe089a0bf @ strh r10, [r9], pc")
+
+ TEST_PR( "ldrh r0, [r",0, 48,", -r",2, 24,"]")
+ TEST_PR( "ldrcsh r14, [r",13,0, ", r",12, 48,"]")
+ TEST_PR( "ldrh r1, [r",2, 24,", r",3, 48,"]!")
+ TEST_PR( "ldrcch r12, [r",11,48,", -r",10,24,"]!")
+ TEST_PR( "ldrh r2, [r",3, 24,"], r",4, 48,"")
+ TEST_PR( "ldrh r10, [r",9, 48,"], -r",11,24,"")
+ TEST_UNSUPPORTED(".word 0xe1bfc0ba @ ldrh r12, [pc, r10]!")
+ TEST_UNSUPPORTED(".word 0xe099f0bb @ ldrh pc, [r9], r11")
+ TEST_UNSUPPORTED(".word 0xe099a0bf @ ldrh r10, [r9], pc")
+
+ TEST_RP( "strh r",0, VAL1,", [r",1, 24,", #-2]")
+ TEST_RP( "strmih r",14,VAL2,", [r",13,0, ", #2]")
+ TEST_RP( "strh r",1, VAL1,", [r",2, 24,", #4]!")
+ TEST_RP( "strplh r",12,VAL2,", [r",11,24,", #-4]!")
+ TEST_RP( "strh r",2, VAL1,", [r",3, 24,"], #48")
+ TEST_RP( "strh r",10,VAL2,", [r",9, 64,"], #-48")
+ TEST_UNSUPPORTED(".word 0xe1efc3b0 @ strh r12, [pc, #48]!")
+ TEST_UNSUPPORTED(".word 0xe0c9f3b0 @ strh pc, [r9], #48")
+
+ TEST_P( "ldrh r0, [r",0, 24,", #-2]")
+ TEST_P( "ldrvsh r14, [r",13,0, ", #2]")
+ TEST_P( "ldrh r1, [r",2, 24,", #4]!")
+ TEST_P( "ldrvch r12, [r",11,24,", #-4]!")
+ TEST_P( "ldrh r2, [r",3, 24,"], #48")
+ TEST_P( "ldrh r10, [r",9, 64,"], #-48")
+ TEST( "ldrh r0, [pc, #0]")
+ TEST_UNSUPPORTED(".word 0xe1ffc3b0 @ ldrh r12, [pc, #48]!")
+ TEST_UNSUPPORTED(".word 0xe0d9f3b0 @ ldrh pc, [r9], #48")
+
+ TEST_PR( "ldrsb r0, [r",0, 48,", -r",2, 24,"]")
+ TEST_PR( "ldrhisb r14, [r",13,0,", r",12, 48,"]")
+ TEST_PR( "ldrsb r1, [r",2, 24,", r",3, 48,"]!")
+ TEST_PR( "ldrlssb r12, [r",11,48,", -r",10,24,"]!")
+ TEST_PR( "ldrsb r2, [r",3, 24,"], r",4, 48,"")
+ TEST_PR( "ldrsb r10, [r",9, 48,"], -r",11,24,"")
+ TEST_UNSUPPORTED(".word 0xe1bfc0da @ ldrsb r12, [pc, r10]!")
+ TEST_UNSUPPORTED(".word 0xe099f0db @ ldrsb pc, [r9], r11")
+
+ TEST_P( "ldrsb r0, [r",0, 24,", #-1]")
+ TEST_P( "ldrgesb r14, [r",13,0, ", #1]")
+ TEST_P( "ldrsb r1, [r",2, 24,", #4]!")
+ TEST_P( "ldrltsb r12, [r",11,24,", #-4]!")
+ TEST_P( "ldrsb r2, [r",3, 24,"], #48")
+ TEST_P( "ldrsb r10, [r",9, 64,"], #-48")
+ TEST( "ldrsb r0, [pc, #0]")
+ TEST_UNSUPPORTED(".word 0xe1ffc3d0 @ ldrsb r12, [pc, #48]!")
+ TEST_UNSUPPORTED(".word 0xe0d9f3d0 @ ldrsb pc, [r9], #48")
+
+ TEST_PR( "ldrsh r0, [r",0, 48,", -r",2, 24,"]")
+ TEST_PR( "ldrgtsh r14, [r",13,0, ", r",12, 48,"]")
+ TEST_PR( "ldrsh r1, [r",2, 24,", r",3, 48,"]!")
+ TEST_PR( "ldrlesh r12, [r",11,48,", -r",10,24,"]!")
+ TEST_PR( "ldrsh r2, [r",3, 24,"], r",4, 48,"")
+ TEST_PR( "ldrsh r10, [r",9, 48,"], -r",11,24,"")
+ TEST_UNSUPPORTED(".word 0xe1bfc0fa @ ldrsh r12, [pc, r10]!")
+ TEST_UNSUPPORTED(".word 0xe099f0fb @ ldrsh pc, [r9], r11")
+
+ TEST_P( "ldrsh r0, [r",0, 24,", #-1]")
+ TEST_P( "ldreqsh r14, [r",13,0 ,", #1]")
+ TEST_P( "ldrsh r1, [r",2, 24,", #4]!")
+ TEST_P( "ldrnesh r12, [r",11,24,", #-4]!")
+ TEST_P( "ldrsh r2, [r",3, 24,"], #48")
+ TEST_P( "ldrsh r10, [r",9, 64,"], #-48")
+ TEST( "ldrsh r0, [pc, #0]")
+ TEST_UNSUPPORTED(".word 0xe1ffc3f0 @ ldrsh r12, [pc, #48]!")
+ TEST_UNSUPPORTED(".word 0xe0d9f3f0 @ ldrsh pc, [r9], #48")
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_UNSUPPORTED("strht r1, [r2], r3")
+ TEST_UNSUPPORTED("ldrht r1, [r2], r3")
+ TEST_UNSUPPORTED("strht r1, [r2], #48")
+ TEST_UNSUPPORTED("ldrht r1, [r2], #48")
+ TEST_UNSUPPORTED("ldrsbt r1, [r2], r3")
+ TEST_UNSUPPORTED("ldrsbt r1, [r2], #48")
+ TEST_UNSUPPORTED("ldrsht r1, [r2], r3")
+ TEST_UNSUPPORTED("ldrsht r1, [r2], #48")
+#endif
+
+ TEST_RPR( "strd r",0, VAL1,", [r",1, 48,", -r",2,24,"]")
+ TEST_RPR( "strccd r",8, VAL2,", [r",13,0, ", r",12,48,"]")
+ TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!")
+ TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
+ TEST_RPR( "strd r",2, VAL1,", [r",3, 24,"], r",4,48,"")
+ TEST_RPR( "strd r",10,VAL2,", [r",9, 48,"], -r",7,24,"")
+ TEST_UNSUPPORTED(".word 0xe1afc0fa @ strd r12, [pc, r10]!")
+
+ TEST_PR( "ldrd r0, [r",0, 48,", -r",2,24,"]")
+ TEST_PR( "ldrmid r8, [r",13,0, ", r",12,48,"]")
+ TEST_PR( "ldrd r4, [r",2, 24,", r",3, 48,"]!")
+ TEST_PR( "ldrpld r6, [r",11,48,", -r",10,24,"]!")
+ TEST_PR( "ldrd r2, [r",5, 24,"], r",4,48,"")
+ TEST_PR( "ldrd r10, [r",9,48,"], -r",7,24,"")
+ TEST_UNSUPPORTED(".word 0xe1afc0da @ ldrd r12, [pc, r10]!")
+ TEST_UNSUPPORTED(".word 0xe089f0db @ ldrd pc, [r9], r11")
+ TEST_UNSUPPORTED(".word 0xe089e0db @ ldrd lr, [r9], r11")
+ TEST_UNSUPPORTED(".word 0xe089c0df @ ldrd r12, [r9], pc")
+
+ TEST_RP( "strd r",0, VAL1,", [r",1, 24,", #-8]")
+ TEST_RP( "strvsd r",8, VAL2,", [r",13,0, ", #8]")
+ TEST_RP( "strd r",4, VAL1,", [r",2, 24,", #16]!")
+ TEST_RP( "strvcd r",12,VAL2,", [r",11,24,", #-16]!")
+ TEST_RP( "strd r",2, VAL1,", [r",4, 24,"], #48")
+ TEST_RP( "strd r",10,VAL2,", [r",9, 64,"], #-48")
+ TEST_UNSUPPORTED(".word 0xe1efc3f0 @ strd r12, [pc, #48]!")
+
+ TEST_P( "ldrd r0, [r",0, 24,", #-8]")
+ TEST_P( "ldrhid r8, [r",13,0, ", #8]")
+ TEST_P( "ldrd r4, [r",2, 24,", #16]!")
+ TEST_P( "ldrlsd r6, [r",11,24,", #-16]!")
+ TEST_P( "ldrd r2, [r",5, 24,"], #48")
+ TEST_P( "ldrd r10, [r",9,6,"], #-48")
+ TEST_UNSUPPORTED(".word 0xe1efc3d0 @ ldrd r12, [pc, #48]!")
+ TEST_UNSUPPORTED(".word 0xe0c9f3d0 @ ldrd pc, [r9], #48")
+ TEST_UNSUPPORTED(".word 0xe0c9e3d0 @ ldrd lr, [r9], #48")
+
+ TEST_GROUP("Miscellaneous")
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST("movw r0, #0")
+ TEST("movw r0, #0xffff")
+ TEST("movw lr, #0xffff")
+ TEST_UNSUPPORTED(".word 0xe300f000 @ movw pc, #0")
+ TEST_R("movt r",0, VAL1,", #0")
+ TEST_R("movt r",0, VAL2,", #0xffff")
+ TEST_R("movt r",14,VAL1,", #0xffff")
+ TEST_UNSUPPORTED(".word 0xe340f000 @ movt pc, #0")
+#endif
+
+ TEST_UNSUPPORTED("msr cpsr, 0x13")
+ TEST_UNSUPPORTED("msr cpsr_f, 0xf0000000")
+ TEST_UNSUPPORTED("msr spsr, 0x13")
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_SUPPORTED("yield")
+ TEST("sev")
+ TEST("nop")
+ TEST("wfi")
+ TEST_SUPPORTED("wfe")
+ TEST_UNSUPPORTED("dbg #0")
+#endif
+
+ TEST_GROUP("Load/store word and unsigned byte")
+
+#define LOAD_STORE(byte) \
+ TEST_RP( "str"byte" r",0, VAL1,", [r",1, 24,", #-2]") \
+ TEST_RP( "str"byte" r",14,VAL2,", [r",13,0, ", #2]") \
+ TEST_RP( "str"byte" r",1, VAL1,", [r",2, 24,", #4]!") \
+ TEST_RP( "str"byte" r",12,VAL2,", [r",11,24,", #-4]!") \
+ TEST_RP( "str"byte" r",2, VAL1,", [r",3, 24,"], #48") \
+ TEST_RP( "str"byte" r",10,VAL2,", [r",9, 64,"], #-48") \
+ TEST_RPR("str"byte" r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") \
+ TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 48,"]") \
+ TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") \
+ TEST_RPR("str"byte" r",12,VAL2,", [r",11,48,", -r",10,24,"]!") \
+ TEST_RPR("str"byte" r",2, VAL1,", [r",3, 24,"], r",4, 48,"") \
+ TEST_RPR("str"byte" r",10,VAL2,", [r",9, 48,"], -r",11,24,"") \
+ TEST_RPR("str"byte" r",0, VAL1,", [r",1, 24,", r",2, 32,", asl #1]")\
+ TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\
+ TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 32,", asr #3]!")\
+ TEST_RPR("str"byte" r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\
+ TEST_P( "ldr"byte" r0, [r",0, 24,", #-2]") \
+ TEST_P( "ldr"byte" r14, [r",13,0, ", #2]") \
+ TEST_P( "ldr"byte" r1, [r",2, 24,", #4]!") \
+ TEST_P( "ldr"byte" r12, [r",11,24,", #-4]!") \
+ TEST_P( "ldr"byte" r2, [r",3, 24,"], #48") \
+ TEST_P( "ldr"byte" r10, [r",9, 64,"], #-48") \
+ TEST_PR( "ldr"byte" r0, [r",0, 48,", -r",2, 24,"]") \
+ TEST_PR( "ldr"byte" r14, [r",13,0, ", r",12, 48,"]") \
+ TEST_PR( "ldr"byte" r1, [r",2, 24,", r",3, 48,"]!") \
+ TEST_PR( "ldr"byte" r12, [r",11,48,", -r",10,24,"]!") \
+ TEST_PR( "ldr"byte" r2, [r",3, 24,"], r",4, 48,"") \
+ TEST_PR( "ldr"byte" r10, [r",9, 48,"], -r",11,24,"") \
+ TEST_PR( "ldr"byte" r0, [r",0, 24,", r",2, 32,", asl #1]") \
+ TEST_PR( "ldr"byte" r14, [r",13,0, ", r",12, 32,", lsr #2]") \
+ TEST_PR( "ldr"byte" r1, [r",2, 24,", r",3, 32,", asr #3]!") \
+ TEST_PR( "ldr"byte" r12, [r",11,24,", r",10, 4,", ror #31]!") \
+ TEST( "ldr"byte" r0, [pc, #0]") \
+ TEST_R( "ldr"byte" r12, [pc, r",14,0,"]")
+
+ LOAD_STORE("")
+ TEST_P( "str pc, [r",0,0,", #15*4]")
+ TEST_R( "str pc, [sp, r",2,15*4,"]")
+ TEST_BF( "ldr pc, [sp, #15*4]")
+ TEST_BF_R("ldr pc, [sp, r",2,15*4,"]")
+
+ TEST_P( "str sp, [r",0,0,", #13*4]")
+ TEST_R( "str sp, [sp, r",2,13*4,"]")
+ TEST_BF( "ldr sp, [sp, #13*4]")
+ TEST_BF_R("ldr sp, [sp, r",2,13*4,"]")
+
+#ifdef CONFIG_THUMB2_KERNEL
+ TEST_ARM_TO_THUMB_INTERWORK_P("ldr pc, [r",0,0,", #15*4]")
+#endif
+ TEST_UNSUPPORTED(".word 0xe5af6008 @ str r6, [pc, #8]!")
+ TEST_UNSUPPORTED(".word 0xe7af6008 @ str r6, [pc, r8]!")
+ TEST_UNSUPPORTED(".word 0xe5bf6008 @ ldr r6, [pc, #8]!")
+ TEST_UNSUPPORTED(".word 0xe7bf6008 @ ldr r6, [pc, r8]!")
+ TEST_UNSUPPORTED(".word 0xe788600f @ str r6, [r8, pc]")
+ TEST_UNSUPPORTED(".word 0xe798600f @ ldr r6, [r8, pc]")
+
+ LOAD_STORE("b")
+ TEST_UNSUPPORTED(".word 0xe5f7f008 @ ldrb pc, [r7, #8]!")
+ TEST_UNSUPPORTED(".word 0xe7f7f008 @ ldrb pc, [r7, r8]!")
+ TEST_UNSUPPORTED(".word 0xe5ef6008 @ strb r6, [pc, #8]!")
+ TEST_UNSUPPORTED(".word 0xe7ef6008 @ strb r6, [pc, r3]!")
+ TEST_UNSUPPORTED(".word 0xe5ff6008 @ ldrb r6, [pc, #8]!")
+ TEST_UNSUPPORTED(".word 0xe7ff6008 @ ldrb r6, [pc, r3]!")
+
+ TEST_UNSUPPORTED("ldrt r0, [r1], #4")
+ TEST_UNSUPPORTED("ldrt r1, [r2], r3")
+ TEST_UNSUPPORTED("strt r2, [r3], #4")
+ TEST_UNSUPPORTED("strt r3, [r4], r5")
+ TEST_UNSUPPORTED("ldrbt r4, [r5], #4")
+ TEST_UNSUPPORTED("ldrbt r5, [r6], r7")
+ TEST_UNSUPPORTED("strbt r6, [r7], #4")
+ TEST_UNSUPPORTED("strbt r7, [r8], r9")
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_GROUP("Parallel addition and subtraction, signed")
+
+ TEST_UNSUPPORTED(".word 0xe6000010") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe60fffff") /* Unallocated space */
+
+ TEST_RR( "sadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cff1a @ sadd16 pc, r12, r10")
+ TEST_RR( "sasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cff3a @ sasx pc, r12, r10")
+ TEST_RR( "ssax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "ssax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cff5a @ ssax pc, r12, r10")
+ TEST_RR( "ssub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "ssub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cff7a @ ssub16 pc, r12, r10")
+ TEST_RR( "sadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cff9a @ sadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe61000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe61fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe61000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe61fffdf") /* Unallocated space */
+ TEST_RR( "ssub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "ssub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe61cfffa @ ssub8 pc, r12, r10")
+
+ TEST_RR( "qadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cff1a @ qadd16 pc, r12, r10")
+ TEST_RR( "qasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cff3a @ qasx pc, r12, r10")
+ TEST_RR( "qsax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qsax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cff5a @ qsax pc, r12, r10")
+ TEST_RR( "qsub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qsub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cff7a @ qsub16 pc, r12, r10")
+ TEST_RR( "qadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cff9a @ qadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe62000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe62fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe62000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe62fffdf") /* Unallocated space */
+ TEST_RR( "qsub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "qsub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe62cfffa @ qsub8 pc, r12, r10")
+
+ TEST_RR( "shadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cff1a @ shadd16 pc, r12, r10")
+ TEST_RR( "shasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cff3a @ shasx pc, r12, r10")
+ TEST_RR( "shsax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shsax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cff5a @ shsax pc, r12, r10")
+ TEST_RR( "shsub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shsub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cff7a @ shsub16 pc, r12, r10")
+ TEST_RR( "shadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cff9a @ shadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe63000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe63fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe63000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe63fffdf") /* Unallocated space */
+ TEST_RR( "shsub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "shsub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe63cfffa @ shsub8 pc, r12, r10")
+
+ TEST_GROUP("Parallel addition and subtraction, unsigned")
+
+ TEST_UNSUPPORTED(".word 0xe6400010") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe64fffff") /* Unallocated space */
+
+ TEST_RR( "uadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cff1a @ uadd16 pc, r12, r10")
+ TEST_RR( "uasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cff3a @ uasx pc, r12, r10")
+ TEST_RR( "usax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "usax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cff5a @ usax pc, r12, r10")
+ TEST_RR( "usub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "usub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cff7a @ usub16 pc, r12, r10")
+ TEST_RR( "uadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cff9a @ uadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe65000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe65fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe65000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe65fffdf") /* Unallocated space */
+ TEST_RR( "usub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "usub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe65cfffa @ usub8 pc, r12, r10")
+
+ TEST_RR( "uqadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cff1a @ uqadd16 pc, r12, r10")
+ TEST_RR( "uqasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cff3a @ uqasx pc, r12, r10")
+ TEST_RR( "uqsax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqsax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cff5a @ uqsax pc, r12, r10")
+ TEST_RR( "uqsub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqsub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cff7a @ uqsub16 pc, r12, r10")
+ TEST_RR( "uqadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cff9a @ uqadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe66000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe66fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe66000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe66fffdf") /* Unallocated space */
+ TEST_RR( "uqsub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uqsub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe66cfffa @ uqsub8 pc, r12, r10")
+
+ TEST_RR( "uhadd16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhadd16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cff1a @ uhadd16 pc, r12, r10")
+ TEST_RR( "uhasx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhasx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cff3a @ uhasx pc, r12, r10")
+ TEST_RR( "uhsax r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhsax r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cff5a @ uhsax pc, r12, r10")
+ TEST_RR( "uhsub16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhsub16 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cff7a @ uhsub16 pc, r12, r10")
+ TEST_RR( "uhadd8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhadd8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cff9a @ uhadd8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe67000b0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe67fffbf") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe67000d0") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe67fffdf") /* Unallocated space */
+ TEST_RR( "uhsub8 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uhsub8 r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe67cfffa @ uhsub8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe67feffa @ uhsub8 r14, pc, r10")
+ TEST_UNSUPPORTED(".word 0xe67cefff @ uhsub8 r14, r12, pc")
+#endif /* __LINUX_ARM_ARCH__ >= 7 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_GROUP("Packing, unpacking, saturation, and reversal")
+
+ TEST_RR( "pkhbt r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "pkhbt r14,r",12, HH1,", r",10,HH2,", lsl #2")
+ TEST_UNSUPPORTED(".word 0xe68cf11a @ pkhbt pc, r12, r10, lsl #2")
+ TEST_RR( "pkhtb r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "pkhtb r14,r",12, HH1,", r",10,HH2,", asr #2")
+ TEST_UNSUPPORTED(".word 0xe68cf15a @ pkhtb pc, r12, r10, asr #2")
+ TEST_UNSUPPORTED(".word 0xe68fe15a @ pkhtb r14, pc, r10, asr #2")
+ TEST_UNSUPPORTED(".word 0xe68ce15f @ pkhtb r14, r12, pc, asr #2")
+ TEST_UNSUPPORTED(".word 0xe6900010") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe69fffdf") /* Unallocated space */
+
+ TEST_R( "ssat r0, #24, r",0, VAL1,"")
+ TEST_R( "ssat r14, #24, r",12, VAL2,"")
+ TEST_R( "ssat r0, #24, r",0, VAL1,", lsl #8")
+ TEST_R( "ssat r14, #24, r",12, VAL2,", asr #8")
+ TEST_UNSUPPORTED(".word 0xe6b7f01c @ ssat pc, #24, r12")
+
+ TEST_R( "usat r0, #24, r",0, VAL1,"")
+ TEST_R( "usat r14, #24, r",12, VAL2,"")
+ TEST_R( "usat r0, #24, r",0, VAL1,", lsl #8")
+ TEST_R( "usat r14, #24, r",12, VAL2,", asr #8")
+ TEST_UNSUPPORTED(".word 0xe6f7f01c @ usat pc, #24, r12")
+
+ TEST_RR( "sxtab16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxtb16 r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe68cf47a @ sxtab16 pc,r12, r10, ror #8")
+
+ TEST_RR( "sel r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "sel r14, r",12,VAL1,", r",10, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe68cffba @ sel pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe68fefba @ sel r14, pc, r10")
+ TEST_UNSUPPORTED(".word 0xe68cefbf @ sel r14, r12, pc")
+
+ TEST_R( "ssat16 r0, #12, r",0, HH1,"")
+ TEST_R( "ssat16 r14, #12, r",12, HH2,"")
+ TEST_UNSUPPORTED(".word 0xe6abff3c @ ssat16 pc, #12, r12")
+
+ TEST_RR( "sxtab r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxtb r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe6acf47a @ sxtab pc,r12, r10, ror #8")
+
+ TEST_R( "rev r0, r",0, VAL1,"")
+ TEST_R( "rev r14, r",12, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe6bfff3c @ rev pc, r12")
+
+ TEST_RR( "sxtah r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxth r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe6bcf47a @ sxtah pc,r12, r10, ror #8")
+
+ TEST_R( "rev16 r0, r",0, VAL1,"")
+ TEST_R( "rev16 r14, r",12, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe6bfffbc @ rev16 pc, r12")
+
+ TEST_RR( "uxtab16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxtb16 r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe6ccf47a @ uxtab16 pc,r12, r10, ror #8")
+
+ TEST_R( "usat16 r0, #12, r",0, HH1,"")
+ TEST_R( "usat16 r14, #12, r",12, HH2,"")
+ TEST_UNSUPPORTED(".word 0xe6ecff3c @ usat16 pc, #12, r12")
+ TEST_UNSUPPORTED(".word 0xe6ecef3f @ usat16 r14, #12, pc")
+
+ TEST_RR( "uxtab r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxtb r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe6ecf47a @ uxtab pc,r12, r10, ror #8")
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_R( "rbit r0, r",0, VAL1,"")
+ TEST_R( "rbit r14, r",12, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe6ffff3c @ rbit pc, r12")
+#endif
+
+ TEST_RR( "uxtah r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxth r8, r",7, HH1,"")
+ TEST_UNSUPPORTED(".word 0xe6fff077 @ uxth pc, r7")
+ TEST_UNSUPPORTED(".word 0xe6ff807f @ uxth r8, pc")
+ TEST_UNSUPPORTED(".word 0xe6fcf47a @ uxtah pc, r12, r10, ror #8")
+ TEST_UNSUPPORTED(".word 0xe6fce47f @ uxtah r14, r12, pc, ror #8")
+
+ TEST_R( "revsh r0, r",0, VAL1,"")
+ TEST_R( "revsh r14, r",12, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe6ffff3c @ revsh pc, r12")
+ TEST_UNSUPPORTED(".word 0xe6ffef3f @ revsh r14, pc")
+
+ TEST_UNSUPPORTED(".word 0xe6900070") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe69fff7f") /* Unallocated space */
+
+ TEST_UNSUPPORTED(".word 0xe6d00070") /* Unallocated space */
+ TEST_UNSUPPORTED(".word 0xe6dfff7f") /* Unallocated space */
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_GROUP("Signed multiplies")
+
+ TEST_RRR( "smlad r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlad r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe70f8a1c @ smlad pc, r12, r10, r8")
+ TEST_RRR( "smladx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smladx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe70f8a3c @ smladx pc, r12, r10, r8")
+
+ TEST_RR( "smuad r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smuad r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe70ffa1c @ smuad pc, r12, r10")
+ TEST_RR( "smuadx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smuadx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe70ffa3c @ smuadx pc, r12, r10")
+
+ TEST_RRR( "smlsd r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlsd r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe70f8a5c @ smlsd pc, r12, r10, r8")
+ TEST_RRR( "smlsdx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlsdx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe70f8a7c @ smlsdx pc, r12, r10, r8")
+
+ TEST_RR( "smusd r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smusd r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe70ffa5c @ smusd pc, r12, r10")
+ TEST_RR( "smusdx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smusdx r14, r",12,HH2,", r",10,HH1,"")
+ TEST_UNSUPPORTED(".word 0xe70ffa7c @ smusdx pc, r12, r10")
+
+ TEST_RRRR( "smlald r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlald r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+ TEST_UNSUPPORTED(".word 0xe74af819 @ smlald pc, r10, r9, r8")
+ TEST_UNSUPPORTED(".word 0xe74fb819 @ smlald r11, pc, r9, r8")
+ TEST_UNSUPPORTED(".word 0xe74ab81f @ smlald r11, r10, pc, r8")
+ TEST_UNSUPPORTED(".word 0xe74abf19 @ smlald r11, r10, r9, pc")
+
+ TEST_RRRR( "smlaldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlaldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+ TEST_UNSUPPORTED(".word 0xe74af839 @ smlaldx pc, r10, r9, r8")
+ TEST_UNSUPPORTED(".word 0xe74fb839 @ smlaldx r11, pc, r9, r8")
+
+ TEST_RRR( "smmla r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmla r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe75f8a1c @ smmla pc, r12, r10, r8")
+ TEST_RRR( "smmlar r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmlar r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe75f8a3c @ smmlar pc, r12, r10, r8")
+
+ TEST_RR( "smmul r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "smmul r14, r",12,VAL2,", r",10,VAL1,"")
+ TEST_UNSUPPORTED(".word 0xe75ffa1c @ smmul pc, r12, r10")
+ TEST_RR( "smmulr r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "smmulr r14, r",12,VAL2,", r",10,VAL1,"")
+ TEST_UNSUPPORTED(".word 0xe75ffa3c @ smmulr pc, r12, r10")
+
+ TEST_RRR( "smmls r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmls r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe75f8adc @ smmls pc, r12, r10, r8")
+ TEST_RRR( "smmlsr r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmlsr r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_UNSUPPORTED(".word 0xe75f8afc @ smmlsr pc, r12, r10, r8")
+ TEST_UNSUPPORTED(".word 0xe75e8aff @ smmlsr r14, pc, r10, r8")
+ TEST_UNSUPPORTED(".word 0xe75e8ffc @ smmlsr r14, r12, pc, r8")
+ TEST_UNSUPPORTED(".word 0xe75efafc @ smmlsr r14, r12, r10, pc")
+
+ TEST_RR( "usad8 r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "usad8 r14, r",12,VAL2,", r",10,VAL1,"")
+ TEST_UNSUPPORTED(".word 0xe75ffa1c @ usad8 pc, r12, r10")
+ TEST_UNSUPPORTED(".word 0xe75efa1f @ usad8 r14, pc, r10")
+ TEST_UNSUPPORTED(".word 0xe75eff1c @ usad8 r14, r12, pc")
+
+ TEST_RRR( "usada8 r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL3,"")
+ TEST_RRR( "usada8 r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
+ TEST_UNSUPPORTED(".word 0xe78f8a1c @ usada8 pc, r12, r10, r8")
+ TEST_UNSUPPORTED(".word 0xe78e8a1f @ usada8 r14, pc, r10, r8")
+ TEST_UNSUPPORTED(".word 0xe78e8f1c @ usada8 r14, r12, pc, r8")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_GROUP("Bit Field")
+
+ TEST_R( "sbfx r0, r",0 , VAL1,", #0, #31")
+ TEST_R( "sbfxeq r14, r",12, VAL2,", #8, #16")
+ TEST_R( "sbfx r4, r",10, VAL1,", #16, #15")
+ TEST_UNSUPPORTED(".word 0xe7aff45c @ sbfx pc, r12, #8, #16")
+
+ TEST_R( "ubfx r0, r",0 , VAL1,", #0, #31")
+ TEST_R( "ubfxcs r14, r",12, VAL2,", #8, #16")
+ TEST_R( "ubfx r4, r",10, VAL1,", #16, #15")
+ TEST_UNSUPPORTED(".word 0xe7eff45c @ ubfx pc, r12, #8, #16")
+ TEST_UNSUPPORTED(".word 0xe7efc45f @ ubfx r12, pc, #8, #16")
+
+ TEST_R( "bfc r",0, VAL1,", #4, #20")
+ TEST_R( "bfcvs r",14,VAL2,", #4, #20")
+ TEST_R( "bfc r",7, VAL1,", #0, #31")
+ TEST_R( "bfc r",8, VAL2,", #0, #31")
+ TEST_UNSUPPORTED(".word 0xe7def01f @ bfc pc, #0, #31");
+
+ TEST_RR( "bfi r",0, VAL1,", r",0 , VAL2,", #0, #31")
+ TEST_RR( "bfipl r",12,VAL1,", r",14 , VAL2,", #4, #20")
+ TEST_UNSUPPORTED(".word 0xe7d7f21e @ bfi pc, r14, #4, #20")
+
+ TEST_UNSUPPORTED(".word 0x07f000f0") /* Permanently UNDEFINED */
+ TEST_UNSUPPORTED(".word 0x07ffffff") /* Permanently UNDEFINED */
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+ TEST_GROUP("Branch, branch with link, and block data transfer")
+
+ TEST_P( "stmda r",0, 16*4,", {r0}")
+ TEST_P( "stmeqda r",4, 16*4,", {r0-r15}")
+ TEST_P( "stmneda r",8, 16*4,"!, {r8-r15}")
+ TEST_P( "stmda r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_P( "stmda r",13,0, "!, {pc}")
+
+ TEST_P( "ldmda r",0, 16*4,", {r0}")
+ TEST_BF_P("ldmcsda r",4, 15*4,", {r0-r15}")
+ TEST_BF_P("ldmccda r",7, 15*4,"!, {r8-r15}")
+ TEST_P( "ldmda r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmda r",14,15*4,"!, {pc}")
+
+ TEST_P( "stmia r",0, 16*4,", {r0}")
+ TEST_P( "stmmiia r",4, 16*4,", {r0-r15}")
+ TEST_P( "stmplia r",8, 16*4,"!, {r8-r15}")
+ TEST_P( "stmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_P( "stmia r",14,0, "!, {pc}")
+
+ TEST_P( "ldmia r",0, 16*4,", {r0}")
+ TEST_BF_P("ldmvsia r",4, 0, ", {r0-r15}")
+ TEST_BF_P("ldmvcia r",7, 8*4, "!, {r8-r15}")
+ TEST_P( "ldmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmia r",14,15*4,"!, {pc}")
+
+ TEST_P( "stmdb r",0, 16*4,", {r0}")
+ TEST_P( "stmhidb r",4, 16*4,", {r0-r15}")
+ TEST_P( "stmlsdb r",8, 16*4,"!, {r8-r15}")
+ TEST_P( "stmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_P( "stmdb r",13,4, "!, {pc}")
+
+ TEST_P( "ldmdb r",0, 16*4,", {r0}")
+ TEST_BF_P("ldmgedb r",4, 16*4,", {r0-r15}")
+ TEST_BF_P("ldmltdb r",7, 16*4,"!, {r8-r15}")
+ TEST_P( "ldmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmdb r",14,16*4,"!, {pc}")
+
+ TEST_P( "stmib r",0, 16*4,", {r0}")
+ TEST_P( "stmgtib r",4, 16*4,", {r0-r15}")
+ TEST_P( "stmleib r",8, 16*4,"!, {r8-r15}")
+ TEST_P( "stmib r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_P( "stmib r",13,-4, "!, {pc}")
+
+ TEST_P( "ldmib r",0, 16*4,", {r0}")
+ TEST_BF_P("ldmeqib r",4, -4,", {r0-r15}")
+ TEST_BF_P("ldmneib r",7, 7*4,"!, {r8-r15}")
+ TEST_P( "ldmib r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmib r",14,14*4,"!, {pc}")
+
+ TEST_P( "stmdb r",13,16*4,"!, {r3-r12,lr}")
+ TEST_P( "stmeqdb r",13,16*4,"!, {r3-r12}")
+ TEST_P( "stmnedb r",2, 16*4,", {r3-r12,lr}")
+ TEST_P( "stmdb r",13,16*4,"!, {r2-r12,lr}")
+ TEST_P( "stmdb r",0, 16*4,", {r0-r12}")
+ TEST_P( "stmdb r",0, 16*4,", {r0-r12,lr}")
+
+ TEST_BF_P("ldmia r",13,5*4, "!, {r3-r12,pc}")
+ TEST_P( "ldmccia r",13,5*4, "!, {r3-r12}")
+ TEST_BF_P("ldmcsia r",2, 5*4, "!, {r3-r12,pc}")
+ TEST_BF_P("ldmia r",13,4*4, "!, {r2-r12,pc}")
+ TEST_P( "ldmia r",0, 16*4,", {r0-r12}")
+ TEST_P( "ldmia r",0, 16*4,", {r0-r12,lr}")
+
+#ifdef CONFIG_THUMB2_KERNEL
+ TEST_ARM_TO_THUMB_INTERWORK_P("ldmplia r",0,15*4,", {pc}")
+ TEST_ARM_TO_THUMB_INTERWORK_P("ldmmiia r",13,0,", {r0-r15}")
+#endif
+ TEST_BF("b 2f")
+ TEST_BF("bl 2f")
+ TEST_BB("b 2b")
+ TEST_BB("bl 2b")
+
+ TEST_BF("beq 2f")
+ TEST_BF("bleq 2f")
+ TEST_BB("bne 2b")
+ TEST_BB("blne 2b")
+
+ TEST_BF("bgt 2f")
+ TEST_BF("blgt 2f")
+ TEST_BB("blt 2b")
+ TEST_BB("bllt 2b")
+
+ TEST_GROUP("Supervisor Call, and coprocessor instructions")
+
+ /*
+ * We can't really test these by executing them, so all
+ * we can do is check that probes are, or are not allowed.
+ * At the moment none are allowed...
+ */
+#define TEST_COPROCESSOR(code) TEST_UNSUPPORTED(code)
+
+#define COPROCESSOR_INSTRUCTIONS_ST_LD(two,cc) \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #4]") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #-4]") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #4]!") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #-4]!") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13], #4") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13], #-4") \
+ TEST_COPROCESSOR("stc"two" 0, cr0, [r13], {1}") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #4]") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #-4]") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #4]!") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #-4]!") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], #4") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], #-4") \
+ TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], {1}") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #4]") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #-4]") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #4]!") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #-4]!") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], #4") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], #-4") \
+ TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], {1}") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #4]") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #-4]") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #4]!") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #-4]!") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], #4") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], #-4") \
+ TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], {1}") \
+ \
+ TEST_COPROCESSOR( "stc"two" 0, cr0, [r15, #4]") \
+ TEST_COPROCESSOR( "stc"two" 0, cr0, [r15, #-4]") \
+ TEST_UNSUPPORTED(".word 0x"cc"daf0001 @ stc"two" 0, cr0, [r15, #4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"d2f0001 @ stc"two" 0, cr0, [r15, #-4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"caf0001 @ stc"two" 0, cr0, [r15], #4") \
+ TEST_UNSUPPORTED(".word 0x"cc"c2f0001 @ stc"two" 0, cr0, [r15], #-4") \
+ TEST_COPROCESSOR( "stc"two" 0, cr0, [r15], {1}") \
+ TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15, #4]") \
+ TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15, #-4]") \
+ TEST_UNSUPPORTED(".word 0x"cc"def0001 @ stc"two"l 0, cr0, [r15, #4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"d6f0001 @ stc"two"l 0, cr0, [r15, #-4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"cef0001 @ stc"two"l 0, cr0, [r15], #4") \
+ TEST_UNSUPPORTED(".word 0x"cc"c6f0001 @ stc"two"l 0, cr0, [r15], #-4") \
+ TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15], {1}") \
+ TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15, #4]") \
+ TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15, #-4]") \
+ TEST_UNSUPPORTED(".word 0x"cc"dbf0001 @ ldc"two" 0, cr0, [r15, #4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"d3f0001 @ ldc"two" 0, cr0, [r15, #-4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"cbf0001 @ ldc"two" 0, cr0, [r15], #4") \
+ TEST_UNSUPPORTED(".word 0x"cc"c3f0001 @ ldc"two" 0, cr0, [r15], #-4") \
+ TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15], {1}") \
+ TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15, #4]") \
+ TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15, #-4]") \
+ TEST_UNSUPPORTED(".word 0x"cc"dff0001 @ ldc"two"l 0, cr0, [r15, #4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"d7f0001 @ ldc"two"l 0, cr0, [r15, #-4]!") \
+ TEST_UNSUPPORTED(".word 0x"cc"cff0001 @ ldc"two"l 0, cr0, [r15], #4") \
+ TEST_UNSUPPORTED(".word 0x"cc"c7f0001 @ ldc"two"l 0, cr0, [r15], #-4") \
+ TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15], {1}")
+
+#define COPROCESSOR_INSTRUCTIONS_MC_MR(two,cc) \
+ \
+ TEST_COPROCESSOR( "mcrr"two" 0, 15, r0, r14, cr0") \
+ TEST_COPROCESSOR( "mcrr"two" 15, 0, r14, r0, cr15") \
+ TEST_UNSUPPORTED(".word 0x"cc"c4f00f0 @ mcrr"two" 0, 15, r0, r15, cr0") \
+ TEST_UNSUPPORTED(".word 0x"cc"c40ff0f @ mcrr"two" 15, 0, r15, r0, cr15") \
+ TEST_COPROCESSOR( "mrrc"two" 0, 15, r0, r14, cr0") \
+ TEST_COPROCESSOR( "mrrc"two" 15, 0, r14, r0, cr15") \
+ TEST_UNSUPPORTED(".word 0x"cc"c5f00f0 @ mrrc"two" 0, 15, r0, r15, cr0") \
+ TEST_UNSUPPORTED(".word 0x"cc"c50ff0f @ mrrc"two" 15, 0, r15, r0, cr15") \
+ TEST_COPROCESSOR( "cdp"two" 15, 15, cr15, cr15, cr15, 7") \
+ TEST_COPROCESSOR( "cdp"two" 0, 0, cr0, cr0, cr0, 0") \
+ TEST_COPROCESSOR( "mcr"two" 15, 7, r15, cr15, cr15, 7") \
+ TEST_COPROCESSOR( "mcr"two" 0, 0, r0, cr0, cr0, 0") \
+ TEST_COPROCESSOR( "mrc"two" 15, 7, r15, cr15, cr15, 7") \
+ TEST_COPROCESSOR( "mrc"two" 0, 0, r0, cr0, cr0, 0")
+
+ COPROCESSOR_INSTRUCTIONS_ST_LD("","e")
+ COPROCESSOR_INSTRUCTIONS_MC_MR("","e")
+ TEST_UNSUPPORTED("svc 0")
+ TEST_UNSUPPORTED("svc 0xffffff")
+
+ TEST_UNSUPPORTED("svc 0")
+
+ TEST_GROUP("Unconditional instruction")
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_UNSUPPORTED("srsda sp, 0x13")
+ TEST_UNSUPPORTED("srsdb sp, 0x13")
+ TEST_UNSUPPORTED("srsia sp, 0x13")
+ TEST_UNSUPPORTED("srsib sp, 0x13")
+ TEST_UNSUPPORTED("srsda sp!, 0x13")
+ TEST_UNSUPPORTED("srsdb sp!, 0x13")
+ TEST_UNSUPPORTED("srsia sp!, 0x13")
+ TEST_UNSUPPORTED("srsib sp!, 0x13")
+
+ TEST_UNSUPPORTED("rfeda sp")
+ TEST_UNSUPPORTED("rfedb sp")
+ TEST_UNSUPPORTED("rfeia sp")
+ TEST_UNSUPPORTED("rfeib sp")
+ TEST_UNSUPPORTED("rfeda sp!")
+ TEST_UNSUPPORTED("rfedb sp!")
+ TEST_UNSUPPORTED("rfeia sp!")
+ TEST_UNSUPPORTED("rfeib sp!")
+ TEST_UNSUPPORTED(".word 0xf81d0a00 @ rfeda pc")
+ TEST_UNSUPPORTED(".word 0xf91d0a00 @ rfedb pc")
+ TEST_UNSUPPORTED(".word 0xf89d0a00 @ rfeia pc")
+ TEST_UNSUPPORTED(".word 0xf99d0a00 @ rfeib pc")
+ TEST_UNSUPPORTED(".word 0xf83d0a00 @ rfeda pc!")
+ TEST_UNSUPPORTED(".word 0xf93d0a00 @ rfedb pc!")
+ TEST_UNSUPPORTED(".word 0xf8bd0a00 @ rfeia pc!")
+ TEST_UNSUPPORTED(".word 0xf9bd0a00 @ rfeib pc!")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_X( "blx __dummy_thumb_subroutine_even",
+ ".thumb \n\t"
+ ".space 4 \n\t"
+ ".type __dummy_thumb_subroutine_even, %%function \n\t"
+ "__dummy_thumb_subroutine_even: \n\t"
+ "mov r0, pc \n\t"
+ "bx lr \n\t"
+ ".arm \n\t"
+ )
+ TEST( "blx __dummy_thumb_subroutine_even")
+
+ TEST_X( "blx __dummy_thumb_subroutine_odd",
+ ".thumb \n\t"
+ ".space 2 \n\t"
+ ".type __dummy_thumb_subroutine_odd, %%function \n\t"
+ "__dummy_thumb_subroutine_odd: \n\t"
+ "mov r0, pc \n\t"
+ "bx lr \n\t"
+ ".arm \n\t"
+ )
+ TEST( "blx __dummy_thumb_subroutine_odd")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+ COPROCESSOR_INSTRUCTIONS_ST_LD("2","f")
+#if __LINUX_ARM_ARCH__ >= 6
+ COPROCESSOR_INSTRUCTIONS_MC_MR("2","f")
+#endif
+
+ TEST_GROUP("Miscellaneous instructions, memory hints, and Advanced SIMD instructions")
+
+#if __LINUX_ARM_ARCH__ >= 6
+ TEST_UNSUPPORTED("cps 0x13")
+ TEST_UNSUPPORTED("cpsie i")
+ TEST_UNSUPPORTED("cpsid i")
+ TEST_UNSUPPORTED("cpsie i,0x13")
+ TEST_UNSUPPORTED("cpsid i,0x13")
+ TEST_UNSUPPORTED("setend le")
+ TEST_UNSUPPORTED("setend be")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_P("pli [r",0,0b,", #16]")
+ TEST( "pli [pc, #0]")
+ TEST_RR("pli [r",12,0b,", r",0, 16,"]")
+ TEST_RR("pli [r",0, 0b,", -r",12,16,", lsl #4]")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 5
+ TEST_P("pld [r",0,32,", #-16]")
+ TEST( "pld [pc, #0]")
+ TEST_PR("pld [r",7, 24, ", r",0, 16,"]")
+ TEST_PR("pld [r",8, 24, ", -r",12,16,", lsl #4]")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_SUPPORTED( ".word 0xf590f000 @ pldw [r0, #0]")
+ TEST_SUPPORTED( ".word 0xf797f000 @ pldw [r7, r0]")
+ TEST_SUPPORTED( ".word 0xf798f18c @ pldw [r8, r12, lsl #3]");
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+ TEST_UNSUPPORTED("clrex")
+ TEST_UNSUPPORTED("dsb")
+ TEST_UNSUPPORTED("dmb")
+ TEST_UNSUPPORTED("isb")
+#endif
+
+ verbose("\n");
+}
+
diff --git a/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/kernel/kprobes-test-thumb.c
new file mode 100644
index 000000000000..5e726c31c45a
--- /dev/null
+++ b/arch/arm/kernel/kprobes-test-thumb.c
@@ -0,0 +1,1187 @@
+/*
+ * arch/arm/kernel/kprobes-test-thumb.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * 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/module.h>
+
+#include "kprobes-test.h"
+
+
+#define TEST_ISA "16"
+
+#define DONT_TEST_IN_ITBLOCK(tests) \
+ kprobe_test_flags |= TEST_FLAG_NO_ITBLOCK; \
+ tests \
+ kprobe_test_flags &= ~TEST_FLAG_NO_ITBLOCK;
+
+#define CONDITION_INSTRUCTIONS(cc_pos, tests) \
+ kprobe_test_cc_position = cc_pos; \
+ DONT_TEST_IN_ITBLOCK(tests) \
+ kprobe_test_cc_position = 0;
+
+#define TEST_ITBLOCK(code) \
+ kprobe_test_flags |= TEST_FLAG_FULL_ITBLOCK; \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ "50: nop \n\t" \
+ "1: "code" \n\t" \
+ " mov r1, #0x11 \n\t" \
+ " mov r2, #0x22 \n\t" \
+ " mov r3, #0x33 \n\t" \
+ "2: nop \n\t" \
+ TESTCASE_END \
+ kprobe_test_flags &= ~TEST_FLAG_FULL_ITBLOCK;
+
+#define TEST_THUMB_TO_ARM_INTERWORK_P(code1, reg, val, code2) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_PTR(reg, val) \
+ TEST_ARG_REG(14, 99f+1) \
+ TEST_ARG_MEM(15, 3f) \
+ TEST_ARG_END("") \
+ " nop \n\t" /* To align 1f */ \
+ "50: nop \n\t" \
+ "1: "code1 #reg code2" \n\t" \
+ " bx lr \n\t" \
+ ".arm \n\t" \
+ "3: adr lr, 2f+1 \n\t" \
+ " bx lr \n\t" \
+ ".thumb \n\t" \
+ "2: nop \n\t" \
+ TESTCASE_END
+
+
+void kprobe_thumb16_test_cases(void)
+{
+ kprobe_test_flags = TEST_FLAG_NARROW_INSTR;
+
+ TEST_GROUP("Shift (immediate), add, subtract, move, and compare")
+
+ TEST_R( "lsls r7, r",0,VAL1,", #5")
+ TEST_R( "lsls r0, r",7,VAL2,", #11")
+ TEST_R( "lsrs r7, r",0,VAL1,", #5")
+ TEST_R( "lsrs r0, r",7,VAL2,", #11")
+ TEST_R( "asrs r7, r",0,VAL1,", #5")
+ TEST_R( "asrs r0, r",7,VAL2,", #11")
+ TEST_RR( "adds r2, r",0,VAL1,", r",7,VAL2,"")
+ TEST_RR( "adds r5, r",7,VAL2,", r",0,VAL2,"")
+ TEST_RR( "subs r2, r",0,VAL1,", r",7,VAL2,"")
+ TEST_RR( "subs r5, r",7,VAL2,", r",0,VAL2,"")
+ TEST_R( "adds r7, r",0,VAL1,", #5")
+ TEST_R( "adds r0, r",7,VAL2,", #2")
+ TEST_R( "subs r7, r",0,VAL1,", #5")
+ TEST_R( "subs r0, r",7,VAL2,", #2")
+ TEST( "movs.n r0, #0x5f")
+ TEST( "movs.n r7, #0xa0")
+ TEST_R( "cmp.n r",0,0x5e, ", #0x5f")
+ TEST_R( "cmp.n r",5,0x15f,", #0x5f")
+ TEST_R( "cmp.n r",7,0xa0, ", #0xa0")
+ TEST_R( "adds.n r",0,VAL1,", #0x5f")
+ TEST_R( "adds.n r",7,VAL2,", #0xa0")
+ TEST_R( "subs.n r",0,VAL1,", #0x5f")
+ TEST_R( "subs.n r",7,VAL2,", #0xa0")
+
+ TEST_GROUP("16-bit Thumb data-processing instructions")
+
+#define DATA_PROCESSING16(op,val) \
+ TEST_RR( op" r",0,VAL1,", r",7,val,"") \
+ TEST_RR( op" r",7,VAL2,", r",0,val,"")
+
+ DATA_PROCESSING16("ands",0xf00f00ff)
+ DATA_PROCESSING16("eors",0xf00f00ff)
+ DATA_PROCESSING16("lsls",11)
+ DATA_PROCESSING16("lsrs",11)
+ DATA_PROCESSING16("asrs",11)
+ DATA_PROCESSING16("adcs",VAL2)
+ DATA_PROCESSING16("sbcs",VAL2)
+ DATA_PROCESSING16("rors",11)
+ DATA_PROCESSING16("tst",0xf00f00ff)
+ TEST_R("rsbs r",0,VAL1,", #0")
+ TEST_R("rsbs r",7,VAL2,", #0")
+ DATA_PROCESSING16("cmp",0xf00f00ff)
+ DATA_PROCESSING16("cmn",0xf00f00ff)
+ DATA_PROCESSING16("orrs",0xf00f00ff)
+ DATA_PROCESSING16("muls",VAL2)
+ DATA_PROCESSING16("bics",0xf00f00ff)
+ DATA_PROCESSING16("mvns",VAL2)
+
+ TEST_GROUP("Special data instructions and branch and exchange")
+
+ TEST_RR( "add r",0, VAL1,", r",7,VAL2,"")
+ TEST_RR( "add r",3, VAL2,", r",8,VAL3,"")
+ TEST_RR( "add r",8, VAL3,", r",0,VAL1,"")
+ TEST_R( "add sp" ", r",8,-8, "")
+ TEST_R( "add r",14,VAL1,", pc")
+ TEST_BF_R("add pc" ", r",0,2f-1f-8,"")
+ TEST_UNSUPPORTED(".short 0x44ff @ add pc, pc")
+
+ TEST_RR( "cmp r",3,VAL1,", r",8,VAL2,"")
+ TEST_RR( "cmp r",8,VAL2,", r",0,VAL1,"")
+ TEST_R( "cmp sp" ", r",8,-8, "")
+
+ TEST_R( "mov r0, r",7,VAL2,"")
+ TEST_R( "mov r3, r",8,VAL3,"")
+ TEST_R( "mov r8, r",0,VAL1,"")
+ TEST_P( "mov sp, r",8,-8, "")
+ TEST( "mov lr, pc")
+ TEST_BF_R("mov pc, r",0,2f, "")
+
+ TEST_BF_R("bx r",0, 2f+1,"")
+ TEST_BF_R("bx r",14,2f+1,"")
+ TESTCASE_START("bx pc")
+ TEST_ARG_REG(14, 99f+1)
+ TEST_ARG_END("")
+ " nop \n\t" /* To align the bx pc*/
+ "50: nop \n\t"
+ "1: bx pc \n\t"
+ " bx lr \n\t"
+ ".arm \n\t"
+ " adr lr, 2f+1 \n\t"
+ " bx lr \n\t"
+ ".thumb \n\t"
+ "2: nop \n\t"
+ TESTCASE_END
+
+ TEST_BF_R("blx r",0, 2f+1,"")
+ TEST_BB_R("blx r",14,2f+1,"")
+ TEST_UNSUPPORTED(".short 0x47f8 @ blx pc")
+
+ TEST_GROUP("Load from Literal Pool")
+
+ TEST_X( "ldr r0, 3f",
+ ".align \n\t"
+ "3: .word "__stringify(VAL1))
+ TEST_X( "ldr r7, 3f",
+ ".space 128 \n\t"
+ ".align \n\t"
+ "3: .word "__stringify(VAL2))
+
+ TEST_GROUP("16-bit Thumb Load/store instructions")
+
+ TEST_RPR("str r",0, VAL1,", [r",1, 24,", r",2, 48,"]")
+ TEST_RPR("str r",7, VAL2,", [r",6, 24,", r",5, 48,"]")
+ TEST_RPR("strh r",0, VAL1,", [r",1, 24,", r",2, 48,"]")
+ TEST_RPR("strh r",7, VAL2,", [r",6, 24,", r",5, 48,"]")
+ TEST_RPR("strb r",0, VAL1,", [r",1, 24,", r",2, 48,"]")
+ TEST_RPR("strb r",7, VAL2,", [r",6, 24,", r",5, 48,"]")
+ TEST_PR( "ldrsb r0, [r",1, 24,", r",2, 48,"]")
+ TEST_PR( "ldrsb r7, [r",6, 24,", r",5, 50,"]")
+ TEST_PR( "ldr r0, [r",1, 24,", r",2, 48,"]")
+ TEST_PR( "ldr r7, [r",6, 24,", r",5, 48,"]")
+ TEST_PR( "ldrh r0, [r",1, 24,", r",2, 48,"]")
+ TEST_PR( "ldrh r7, [r",6, 24,", r",5, 50,"]")
+ TEST_PR( "ldrb r0, [r",1, 24,", r",2, 48,"]")
+ TEST_PR( "ldrb r7, [r",6, 24,", r",5, 50,"]")
+ TEST_PR( "ldrsh r0, [r",1, 24,", r",2, 48,"]")
+ TEST_PR( "ldrsh r7, [r",6, 24,", r",5, 50,"]")
+
+ TEST_RP("str r",0, VAL1,", [r",1, 24,", #120]")
+ TEST_RP("str r",7, VAL2,", [r",6, 24,", #120]")
+ TEST_P( "ldr r0, [r",1, 24,", #120]")
+ TEST_P( "ldr r7, [r",6, 24,", #120]")
+ TEST_RP("strb r",0, VAL1,", [r",1, 24,", #30]")
+ TEST_RP("strb r",7, VAL2,", [r",6, 24,", #30]")
+ TEST_P( "ldrb r0, [r",1, 24,", #30]")
+ TEST_P( "ldrb r7, [r",6, 24,", #30]")
+ TEST_RP("strh r",0, VAL1,", [r",1, 24,", #60]")
+ TEST_RP("strh r",7, VAL2,", [r",6, 24,", #60]")
+ TEST_P( "ldrh r0, [r",1, 24,", #60]")
+ TEST_P( "ldrh r7, [r",6, 24,", #60]")
+
+ TEST_R( "str r",0, VAL1,", [sp, #0]")
+ TEST_R( "str r",7, VAL2,", [sp, #160]")
+ TEST( "ldr r0, [sp, #0]")
+ TEST( "ldr r7, [sp, #160]")
+
+ TEST_RP("str r",0, VAL1,", [r",0, 24,"]")
+ TEST_P( "ldr r0, [r",0, 24,"]")
+
+ TEST_GROUP("Generate PC-/SP-relative address")
+
+ TEST("add r0, pc, #4")
+ TEST("add r7, pc, #1020")
+ TEST("add r0, sp, #4")
+ TEST("add r7, sp, #1020")
+
+ TEST_GROUP("Miscellaneous 16-bit instructions")
+
+ TEST_UNSUPPORTED( "cpsie i")
+ TEST_UNSUPPORTED( "cpsid i")
+ TEST_UNSUPPORTED( "setend le")
+ TEST_UNSUPPORTED( "setend be")
+
+ TEST("add sp, #"__stringify(TEST_MEMORY_SIZE)) /* Assumes TEST_MEMORY_SIZE < 0x400 */
+ TEST("sub sp, #0x7f*4")
+
+DONT_TEST_IN_ITBLOCK(
+ TEST_BF_R( "cbnz r",0,0, ", 2f")
+ TEST_BF_R( "cbz r",2,-1,", 2f")
+ TEST_BF_RX( "cbnz r",4,1, ", 2f",0x20)
+ TEST_BF_RX( "cbz r",7,0, ", 2f",0x40)
+)
+ TEST_R("sxth r0, r",7, HH1,"")
+ TEST_R("sxth r7, r",0, HH2,"")
+ TEST_R("sxtb r0, r",7, HH1,"")
+ TEST_R("sxtb r7, r",0, HH2,"")
+ TEST_R("uxth r0, r",7, HH1,"")
+ TEST_R("uxth r7, r",0, HH2,"")
+ TEST_R("uxtb r0, r",7, HH1,"")
+ TEST_R("uxtb r7, r",0, HH2,"")
+ TEST_R("rev r0, r",7, VAL1,"")
+ TEST_R("rev r7, r",0, VAL2,"")
+ TEST_R("rev16 r0, r",7, VAL1,"")
+ TEST_R("rev16 r7, r",0, VAL2,"")
+ TEST_UNSUPPORTED(".short 0xba80")
+ TEST_UNSUPPORTED(".short 0xbabf")
+ TEST_R("revsh r0, r",7, VAL1,"")
+ TEST_R("revsh r7, r",0, VAL2,"")
+
+#define TEST_POPPC(code, offset) \
+ TESTCASE_START(code) \
+ TEST_ARG_PTR(13, offset) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_F(code,0) \
+ TESTCASE_END
+
+ TEST("push {r0}")
+ TEST("push {r7}")
+ TEST("push {r14}")
+ TEST("push {r0-r7,r14}")
+ TEST("push {r0,r2,r4,r6,r14}")
+ TEST("push {r1,r3,r5,r7}")
+ TEST("pop {r0}")
+ TEST("pop {r7}")
+ TEST("pop {r0,r2,r4,r6}")
+ TEST_POPPC("pop {pc}",15*4)
+ TEST_POPPC("pop {r0-r7,pc}",7*4)
+ TEST_POPPC("pop {r1,r3,r5,r7,pc}",11*4)
+ TEST_THUMB_TO_ARM_INTERWORK_P("pop {pc} @ ",13,15*4,"")
+ TEST_THUMB_TO_ARM_INTERWORK_P("pop {r0-r7,pc} @ ",13,7*4,"")
+
+ TEST_UNSUPPORTED("bkpt.n 0")
+ TEST_UNSUPPORTED("bkpt.n 255")
+
+ TEST_SUPPORTED("yield")
+ TEST("sev")
+ TEST("nop")
+ TEST("wfi")
+ TEST_SUPPORTED("wfe")
+ TEST_UNSUPPORTED(".short 0xbf50") /* Unassigned hints */
+ TEST_UNSUPPORTED(".short 0xbff0") /* Unassigned hints */
+
+#define TEST_IT(code, code2) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ "50: nop \n\t" \
+ "1: "code" \n\t" \
+ " "code2" \n\t" \
+ "2: nop \n\t" \
+ TESTCASE_END
+
+DONT_TEST_IN_ITBLOCK(
+ TEST_IT("it eq","moveq r0,#0")
+ TEST_IT("it vc","movvc r0,#0")
+ TEST_IT("it le","movle r0,#0")
+ TEST_IT("ite eq","moveq r0,#0\n\t movne r1,#1")
+ TEST_IT("itet vc","movvc r0,#0\n\t movvs r1,#1\n\t movvc r2,#2")
+ TEST_IT("itete le","movle r0,#0\n\t movgt r1,#1\n\t movle r2,#2\n\t movgt r3,#3")
+ TEST_IT("itttt le","movle r0,#0\n\t movle r1,#1\n\t movle r2,#2\n\t movle r3,#3")
+ TEST_IT("iteee le","movle r0,#0\n\t movgt r1,#1\n\t movgt r2,#2\n\t movgt r3,#3")
+)
+
+ TEST_GROUP("Load and store multiple")
+
+ TEST_P("ldmia r",4, 16*4,"!, {r0,r7}")
+ TEST_P("ldmia r",7, 16*4,"!, {r0-r6}")
+ TEST_P("stmia r",4, 16*4,"!, {r0,r7}")
+ TEST_P("stmia r",0, 16*4,"!, {r0-r7}")
+
+ TEST_GROUP("Conditional branch and Supervisor Call instructions")
+
+CONDITION_INSTRUCTIONS(8,
+ TEST_BF("beq 2f")
+ TEST_BB("bne 2b")
+ TEST_BF("bgt 2f")
+ TEST_BB("blt 2b")
+)
+ TEST_UNSUPPORTED(".short 0xde00")
+ TEST_UNSUPPORTED(".short 0xdeff")
+ TEST_UNSUPPORTED("svc #0x00")
+ TEST_UNSUPPORTED("svc #0xff")
+
+ TEST_GROUP("Unconditional branch")
+
+ TEST_BF( "b 2f")
+ TEST_BB( "b 2b")
+ TEST_BF_X("b 2f", 0x400)
+ TEST_BB_X("b 2b", 0x400)
+
+ TEST_GROUP("Testing instructions in IT blocks")
+
+ TEST_ITBLOCK("subs.n r0, r0")
+
+ verbose("\n");
+}
+
+
+void kprobe_thumb32_test_cases(void)
+{
+ kprobe_test_flags = 0;
+
+ TEST_GROUP("Load/store multiple")
+
+ TEST_UNSUPPORTED("rfedb sp")
+ TEST_UNSUPPORTED("rfeia sp")
+ TEST_UNSUPPORTED("rfedb sp!")
+ TEST_UNSUPPORTED("rfeia sp!")
+
+ TEST_P( "stmia r",0, 16*4,", {r0,r8}")
+ TEST_P( "stmia r",4, 16*4,", {r0-r12,r14}")
+ TEST_P( "stmia r",7, 16*4,"!, {r8-r12,r14}")
+ TEST_P( "stmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+
+ TEST_P( "ldmia r",0, 16*4,", {r0,r8}")
+ TEST_P( "ldmia r",4, 0, ", {r0-r12,r14}")
+ TEST_BF_P("ldmia r",5, 8*4, "!, {r6-r12,r15}")
+ TEST_P( "ldmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmia r",14,14*4,"!, {r4,pc}")
+
+ TEST_P( "stmdb r",0, 16*4,", {r0,r8}")
+ TEST_P( "stmdb r",4, 16*4,", {r0-r12,r14}")
+ TEST_P( "stmdb r",5, 16*4,"!, {r8-r12,r14}")
+ TEST_P( "stmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+
+ TEST_P( "ldmdb r",0, 16*4,", {r0,r8}")
+ TEST_P( "ldmdb r",4, 16*4,", {r0-r12,r14}")
+ TEST_BF_P("ldmdb r",5, 16*4,"!, {r6-r12,r15}")
+ TEST_P( "ldmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+ TEST_BF_P("ldmdb r",14,16*4,"!, {r4,pc}")
+
+ TEST_P( "stmdb r",13,16*4,"!, {r3-r12,lr}")
+ TEST_P( "stmdb r",13,16*4,"!, {r3-r12}")
+ TEST_P( "stmdb r",2, 16*4,", {r3-r12,lr}")
+ TEST_P( "stmdb r",13,16*4,"!, {r2-r12,lr}")
+ TEST_P( "stmdb r",0, 16*4,", {r0-r12}")
+ TEST_P( "stmdb r",0, 16*4,", {r0-r12,lr}")
+
+ TEST_BF_P("ldmia r",13,5*4, "!, {r3-r12,pc}")
+ TEST_P( "ldmia r",13,5*4, "!, {r3-r12}")
+ TEST_BF_P("ldmia r",2, 5*4, "!, {r3-r12,pc}")
+ TEST_BF_P("ldmia r",13,4*4, "!, {r2-r12,pc}")
+ TEST_P( "ldmia r",0, 16*4,", {r0-r12}")
+ TEST_P( "ldmia r",0, 16*4,", {r0-r12,lr}")
+
+ TEST_THUMB_TO_ARM_INTERWORK_P("ldmia r",0,14*4,", {r12,pc}")
+ TEST_THUMB_TO_ARM_INTERWORK_P("ldmia r",13,2*4,", {r0-r12,pc}")
+
+ TEST_UNSUPPORTED(".short 0xe88f,0x0101 @ stmia pc, {r0,r8}")
+ TEST_UNSUPPORTED(".short 0xe92f,0x5f00 @ stmdb pc!, {r8-r12,r14}")
+ TEST_UNSUPPORTED(".short 0xe8bd,0xc000 @ ldmia r13!, {r14,pc}")
+ TEST_UNSUPPORTED(".short 0xe93e,0xc000 @ ldmdb r14!, {r14,pc}")
+ TEST_UNSUPPORTED(".short 0xe8a7,0x3f00 @ stmia r7!, {r8-r12,sp}")
+ TEST_UNSUPPORTED(".short 0xe8a7,0x9f00 @ stmia r7!, {r8-r12,pc}")
+ TEST_UNSUPPORTED(".short 0xe93e,0x2010 @ ldmdb r14!, {r4,sp}")
+
+ TEST_GROUP("Load/store double or exclusive, table branch")
+
+ TEST_P( "ldrd r0, r1, [r",1, 24,", #-16]")
+ TEST( "ldrd r12, r14, [sp, #16]")
+ TEST_P( "ldrd r1, r0, [r",7, 24,", #-16]!")
+ TEST( "ldrd r14, r12, [sp, #16]!")
+ TEST_P( "ldrd r1, r0, [r",7, 24,"], #16")
+ TEST( "ldrd r7, r8, [sp], #-16")
+
+ TEST_X( "ldrd r12, r14, 3f",
+ ".align 3 \n\t"
+ "3: .word "__stringify(VAL1)" \n\t"
+ " .word "__stringify(VAL2))
+
+ TEST_UNSUPPORTED(".short 0xe9ff,0xec04 @ ldrd r14, r12, [pc, #16]!")
+ TEST_UNSUPPORTED(".short 0xe8ff,0xec04 @ ldrd r14, r12, [pc], #16")
+ TEST_UNSUPPORTED(".short 0xe9d4,0xd800 @ ldrd sp, r8, [r4]")
+ TEST_UNSUPPORTED(".short 0xe9d4,0xf800 @ ldrd pc, r8, [r4]")
+ TEST_UNSUPPORTED(".short 0xe9d4,0x7d00 @ ldrd r7, sp, [r4]")
+ TEST_UNSUPPORTED(".short 0xe9d4,0x7f00 @ ldrd r7, pc, [r4]")
+
+ TEST_RRP("strd r",0, VAL1,", r",1, VAL2,", [r",1, 24,", #-16]")
+ TEST_RR( "strd r",12,VAL2,", r",14,VAL1,", [sp, #16]")
+ TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,", #-16]!")
+ TEST_RR( "strd r",14,VAL2,", r",12,VAL1,", [sp, #16]!")
+ TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16")
+ TEST_RR( "strd r",7, VAL2,", r",8, VAL1,", [sp], #-16")
+ TEST_UNSUPPORTED(".short 0xe9ef,0xec04 @ strd r14, r12, [pc, #16]!")
+ TEST_UNSUPPORTED(".short 0xe8ef,0xec04 @ strd r14, r12, [pc], #16")
+
+ TEST_RX("tbb [pc, r",0, (9f-(1f+4)),"]",
+ "9: \n\t"
+ ".byte (2f-1b-4)>>1 \n\t"
+ ".byte (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_RX("tbb [pc, r",4, (9f-(1f+4)+1),"]",
+ "9: \n\t"
+ ".byte (2f-1b-4)>>1 \n\t"
+ ".byte (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_RRX("tbb [r",1,9f,", r",2,0,"]",
+ "9: \n\t"
+ ".byte (2f-1b-4)>>1 \n\t"
+ ".byte (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_RX("tbh [pc, r",7, (9f-(1f+4))>>1,"]",
+ "9: \n\t"
+ ".short (2f-1b-4)>>1 \n\t"
+ ".short (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_RX("tbh [pc, r",12, ((9f-(1f+4))>>1)+1,"]",
+ "9: \n\t"
+ ".short (2f-1b-4)>>1 \n\t"
+ ".short (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_RRX("tbh [r",1,9f, ", r",14,1,"]",
+ "9: \n\t"
+ ".short (2f-1b-4)>>1 \n\t"
+ ".short (3f-1b-4)>>1 \n\t"
+ "3: mvn r0, r0 \n\t"
+ "2: nop \n\t")
+
+ TEST_UNSUPPORTED(".short 0xe8d1,0xf01f @ tbh [r1, pc]")
+ TEST_UNSUPPORTED(".short 0xe8d1,0xf01d @ tbh [r1, sp]")
+ TEST_UNSUPPORTED(".short 0xe8dd,0xf012 @ tbh [sp, r2]")
+
+ TEST_UNSUPPORTED("strexb r0, r1, [r2]")
+ TEST_UNSUPPORTED("strexh r0, r1, [r2]")
+ TEST_UNSUPPORTED("strexd r0, r1, [r2]")
+ TEST_UNSUPPORTED("ldrexb r0, [r1]")
+ TEST_UNSUPPORTED("ldrexh r0, [r1]")
+ TEST_UNSUPPORTED("ldrexd r0, [r1]")
+
+ TEST_GROUP("Data-processing (shifted register) and (modified immediate)")
+
+#define _DATA_PROCESSING32_DNM(op,s,val) \
+ TEST_RR(op s".w r0, r",1, VAL1,", r",2, val, "") \
+ TEST_RR(op s" r1, r",1, VAL1,", r",2, val, ", lsl #3") \
+ TEST_RR(op s" r2, r",3, VAL1,", r",2, val, ", lsr #4") \
+ TEST_RR(op s" r3, r",3, VAL1,", r",2, val, ", asr #5") \
+ TEST_RR(op s" r4, r",5, VAL1,", r",2, N(val),", asr #6") \
+ TEST_RR(op s" r5, r",5, VAL1,", r",2, val, ", ror #7") \
+ TEST_RR(op s" r8, r",9, VAL1,", r",10,val, ", rrx") \
+ TEST_R( op s" r0, r",11,VAL1,", #0x00010001") \
+ TEST_R( op s" r11, r",0, VAL1,", #0xf5000000") \
+ TEST_R( op s" r7, r",8, VAL2,", #0x000af000")
+
+#define DATA_PROCESSING32_DNM(op,val) \
+ _DATA_PROCESSING32_DNM(op,"",val) \
+ _DATA_PROCESSING32_DNM(op,"s",val)
+
+#define DATA_PROCESSING32_NM(op,val) \
+ TEST_RR(op".w r",1, VAL1,", r",2, val, "") \
+ TEST_RR(op" r",1, VAL1,", r",2, val, ", lsl #3") \
+ TEST_RR(op" r",3, VAL1,", r",2, val, ", lsr #4") \
+ TEST_RR(op" r",3, VAL1,", r",2, val, ", asr #5") \
+ TEST_RR(op" r",5, VAL1,", r",2, N(val),", asr #6") \
+ TEST_RR(op" r",5, VAL1,", r",2, val, ", ror #7") \
+ TEST_RR(op" r",9, VAL1,", r",10,val, ", rrx") \
+ TEST_R( op" r",11,VAL1,", #0x00010001") \
+ TEST_R( op" r",0, VAL1,", #0xf5000000") \
+ TEST_R( op" r",8, VAL2,", #0x000af000")
+
+#define _DATA_PROCESSING32_DM(op,s,val) \
+ TEST_R( op s".w r0, r",14, val, "") \
+ TEST_R( op s" r1, r",12, val, ", lsl #3") \
+ TEST_R( op s" r2, r",11, val, ", lsr #4") \
+ TEST_R( op s" r3, r",10, val, ", asr #5") \
+ TEST_R( op s" r4, r",9, N(val),", asr #6") \
+ TEST_R( op s" r5, r",8, val, ", ror #7") \
+ TEST_R( op s" r8, r",7,val, ", rrx") \
+ TEST( op s" r0, #0x00010001") \
+ TEST( op s" r11, #0xf5000000") \
+ TEST( op s" r7, #0x000af000") \
+ TEST( op s" r4, #0x00005a00")
+
+#define DATA_PROCESSING32_DM(op,val) \
+ _DATA_PROCESSING32_DM(op,"",val) \
+ _DATA_PROCESSING32_DM(op,"s",val)
+
+ DATA_PROCESSING32_DNM("and",0xf00f00ff)
+ DATA_PROCESSING32_NM("tst",0xf00f00ff)
+ DATA_PROCESSING32_DNM("bic",0xf00f00ff)
+ DATA_PROCESSING32_DNM("orr",0xf00f00ff)
+ DATA_PROCESSING32_DM("mov",VAL2)
+ DATA_PROCESSING32_DNM("orn",0xf00f00ff)
+ DATA_PROCESSING32_DM("mvn",VAL2)
+ DATA_PROCESSING32_DNM("eor",0xf00f00ff)
+ DATA_PROCESSING32_NM("teq",0xf00f00ff)
+ DATA_PROCESSING32_DNM("add",VAL2)
+ DATA_PROCESSING32_NM("cmn",VAL2)
+ DATA_PROCESSING32_DNM("adc",VAL2)
+ DATA_PROCESSING32_DNM("sbc",VAL2)
+ DATA_PROCESSING32_DNM("sub",VAL2)
+ DATA_PROCESSING32_NM("cmp",VAL2)
+ DATA_PROCESSING32_DNM("rsb",VAL2)
+
+ TEST_RR("pkhbt r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR("pkhbt r14,r",12, HH1,", r",10,HH2,", lsl #2")
+ TEST_RR("pkhtb r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR("pkhtb r14,r",12, HH1,", r",10,HH2,", asr #2")
+
+ TEST_UNSUPPORTED(".short 0xea17,0x0f0d @ tst.w r7, sp")
+ TEST_UNSUPPORTED(".short 0xea17,0x0f0f @ tst.w r7, pc")
+ TEST_UNSUPPORTED(".short 0xea1d,0x0f07 @ tst.w sp, r7")
+ TEST_UNSUPPORTED(".short 0xea1f,0x0f07 @ tst.w pc, r7")
+ TEST_UNSUPPORTED(".short 0xf01d,0x1f08 @ tst sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf01f,0x1f08 @ tst pc, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xea97,0x0f0d @ teq.w r7, sp")
+ TEST_UNSUPPORTED(".short 0xea97,0x0f0f @ teq.w r7, pc")
+ TEST_UNSUPPORTED(".short 0xea9d,0x0f07 @ teq.w sp, r7")
+ TEST_UNSUPPORTED(".short 0xea9f,0x0f07 @ teq.w pc, r7")
+ TEST_UNSUPPORTED(".short 0xf09d,0x1f08 @ tst sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf09f,0x1f08 @ tst pc, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xeb17,0x0f0d @ cmn.w r7, sp")
+ TEST_UNSUPPORTED(".short 0xeb17,0x0f0f @ cmn.w r7, pc")
+ TEST_P("cmn.w sp, r",7,0,"")
+ TEST_UNSUPPORTED(".short 0xeb1f,0x0f07 @ cmn.w pc, r7")
+ TEST( "cmn sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf11f,0x1f08 @ cmn pc, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xebb7,0x0f0d @ cmp.w r7, sp")
+ TEST_UNSUPPORTED(".short 0xebb7,0x0f0f @ cmp.w r7, pc")
+ TEST_P("cmp.w sp, r",7,0,"")
+ TEST_UNSUPPORTED(".short 0xebbf,0x0f07 @ cmp.w pc, r7")
+ TEST( "cmp sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf1bf,0x1f08 @ cmp pc, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xea5f,0x070d @ movs.w r7, sp")
+ TEST_UNSUPPORTED(".short 0xea5f,0x070f @ movs.w r7, pc")
+ TEST_UNSUPPORTED(".short 0xea5f,0x0d07 @ movs.w sp, r7")
+ TEST_UNSUPPORTED(".short 0xea4f,0x0f07 @ mov.w pc, r7")
+ TEST_UNSUPPORTED(".short 0xf04f,0x1d08 @ mov sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf04f,0x1f08 @ mov pc, #0x00080008")
+
+ TEST_R("add.w r0, sp, r",1, 4,"")
+ TEST_R("adds r0, sp, r",1, 4,", asl #3")
+ TEST_R("add r0, sp, r",1, 4,", asl #4")
+ TEST_R("add r0, sp, r",1, 16,", ror #1")
+ TEST_R("add.w sp, sp, r",1, 4,"")
+ TEST_R("add sp, sp, r",1, 4,", asl #3")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x1d01 @ add sp, sp, r1, asl #4")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x0d71 @ add sp, sp, r1, ror #1")
+ TEST( "add.w r0, sp, #24")
+ TEST( "add.w sp, sp, #24")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x0f01 @ add pc, sp, r1")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x000f @ add r0, sp, pc")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x000d @ add r0, sp, sp")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x0d0f @ add sp, sp, pc")
+ TEST_UNSUPPORTED(".short 0xeb0d,0x0d0d @ add sp, sp, sp")
+
+ TEST_R("sub.w r0, sp, r",1, 4,"")
+ TEST_R("subs r0, sp, r",1, 4,", asl #3")
+ TEST_R("sub r0, sp, r",1, 4,", asl #4")
+ TEST_R("sub r0, sp, r",1, 16,", ror #1")
+ TEST_R("sub.w sp, sp, r",1, 4,"")
+ TEST_R("sub sp, sp, r",1, 4,", asl #3")
+ TEST_UNSUPPORTED(".short 0xebad,0x1d01 @ sub sp, sp, r1, asl #4")
+ TEST_UNSUPPORTED(".short 0xebad,0x0d71 @ sub sp, sp, r1, ror #1")
+ TEST_UNSUPPORTED(".short 0xebad,0x0f01 @ sub pc, sp, r1")
+ TEST( "sub.w r0, sp, #24")
+ TEST( "sub.w sp, sp, #24")
+
+ TEST_UNSUPPORTED(".short 0xea02,0x010f @ and r1, r2, pc")
+ TEST_UNSUPPORTED(".short 0xea0f,0x0103 @ and r1, pc, r3")
+ TEST_UNSUPPORTED(".short 0xea02,0x0f03 @ and pc, r2, r3")
+ TEST_UNSUPPORTED(".short 0xea02,0x010d @ and r1, r2, sp")
+ TEST_UNSUPPORTED(".short 0xea0d,0x0103 @ and r1, sp, r3")
+ TEST_UNSUPPORTED(".short 0xea02,0x0d03 @ and sp, r2, r3")
+ TEST_UNSUPPORTED(".short 0xf00d,0x1108 @ and r1, sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf00f,0x1108 @ and r1, pc, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf002,0x1d08 @ and sp, r8, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf002,0x1f08 @ and pc, r8, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xeb02,0x010f @ add r1, r2, pc")
+ TEST_UNSUPPORTED(".short 0xeb0f,0x0103 @ add r1, pc, r3")
+ TEST_UNSUPPORTED(".short 0xeb02,0x0f03 @ add pc, r2, r3")
+ TEST_UNSUPPORTED(".short 0xeb02,0x010d @ add r1, r2, sp")
+ TEST_SUPPORTED( ".short 0xeb0d,0x0103 @ add r1, sp, r3")
+ TEST_UNSUPPORTED(".short 0xeb02,0x0d03 @ add sp, r2, r3")
+ TEST_SUPPORTED( ".short 0xf10d,0x1108 @ add r1, sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf10d,0x1f08 @ add pc, sp, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf10f,0x1108 @ add r1, pc, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf102,0x1d08 @ add sp, r8, #0x00080008")
+ TEST_UNSUPPORTED(".short 0xf102,0x1f08 @ add pc, r8, #0x00080008")
+
+ TEST_UNSUPPORTED(".short 0xeaa0,0x0000")
+ TEST_UNSUPPORTED(".short 0xeaf0,0x0000")
+ TEST_UNSUPPORTED(".short 0xeb20,0x0000")
+ TEST_UNSUPPORTED(".short 0xeb80,0x0000")
+ TEST_UNSUPPORTED(".short 0xebe0,0x0000")
+
+ TEST_UNSUPPORTED(".short 0xf0a0,0x0000")
+ TEST_UNSUPPORTED(".short 0xf0c0,0x0000")
+ TEST_UNSUPPORTED(".short 0xf0f0,0x0000")
+ TEST_UNSUPPORTED(".short 0xf120,0x0000")
+ TEST_UNSUPPORTED(".short 0xf180,0x0000")
+ TEST_UNSUPPORTED(".short 0xf1e0,0x0000")
+
+ TEST_GROUP("Coprocessor instructions")
+
+ TEST_UNSUPPORTED(".short 0xec00,0x0000")
+ TEST_UNSUPPORTED(".short 0xeff0,0x0000")
+ TEST_UNSUPPORTED(".short 0xfc00,0x0000")
+ TEST_UNSUPPORTED(".short 0xfff0,0x0000")
+
+ TEST_GROUP("Data-processing (plain binary immediate)")
+
+ TEST_R("addw r0, r",1, VAL1,", #0x123")
+ TEST( "addw r14, sp, #0xf5a")
+ TEST( "addw sp, sp, #0x20")
+ TEST( "addw r7, pc, #0x888")
+ TEST_UNSUPPORTED(".short 0xf20f,0x1f20 @ addw pc, pc, #0x120")
+ TEST_UNSUPPORTED(".short 0xf20d,0x1f20 @ addw pc, sp, #0x120")
+ TEST_UNSUPPORTED(".short 0xf20f,0x1d20 @ addw sp, pc, #0x120")
+ TEST_UNSUPPORTED(".short 0xf200,0x1d20 @ addw sp, r0, #0x120")
+
+ TEST_R("subw r0, r",1, VAL1,", #0x123")
+ TEST( "subw r14, sp, #0xf5a")
+ TEST( "subw sp, sp, #0x20")
+ TEST( "subw r7, pc, #0x888")
+ TEST_UNSUPPORTED(".short 0xf2af,0x1f20 @ subw pc, pc, #0x120")
+ TEST_UNSUPPORTED(".short 0xf2ad,0x1f20 @ subw pc, sp, #0x120")
+ TEST_UNSUPPORTED(".short 0xf2af,0x1d20 @ subw sp, pc, #0x120")
+ TEST_UNSUPPORTED(".short 0xf2a0,0x1d20 @ subw sp, r0, #0x120")
+
+ TEST("movw r0, #0")
+ TEST("movw r0, #0xffff")
+ TEST("movw lr, #0xffff")
+ TEST_UNSUPPORTED(".short 0xf240,0x0d00 @ movw sp, #0")
+ TEST_UNSUPPORTED(".short 0xf240,0x0f00 @ movw pc, #0")
+
+ TEST_R("movt r",0, VAL1,", #0")
+ TEST_R("movt r",0, VAL2,", #0xffff")
+ TEST_R("movt r",14,VAL1,", #0xffff")
+ TEST_UNSUPPORTED(".short 0xf2c0,0x0d00 @ movt sp, #0")
+ TEST_UNSUPPORTED(".short 0xf2c0,0x0f00 @ movt pc, #0")
+
+ TEST_R( "ssat r0, #24, r",0, VAL1,"")
+ TEST_R( "ssat r14, #24, r",12, VAL2,"")
+ TEST_R( "ssat r0, #24, r",0, VAL1,", lsl #8")
+ TEST_R( "ssat r14, #24, r",12, VAL2,", asr #8")
+ TEST_UNSUPPORTED(".short 0xf30c,0x0d17 @ ssat sp, #24, r12")
+ TEST_UNSUPPORTED(".short 0xf30c,0x0f17 @ ssat pc, #24, r12")
+ TEST_UNSUPPORTED(".short 0xf30d,0x0c17 @ ssat r12, #24, sp")
+ TEST_UNSUPPORTED(".short 0xf30f,0x0c17 @ ssat r12, #24, pc")
+
+ TEST_R( "usat r0, #24, r",0, VAL1,"")
+ TEST_R( "usat r14, #24, r",12, VAL2,"")
+ TEST_R( "usat r0, #24, r",0, VAL1,", lsl #8")
+ TEST_R( "usat r14, #24, r",12, VAL2,", asr #8")
+ TEST_UNSUPPORTED(".short 0xf38c,0x0d17 @ usat sp, #24, r12")
+ TEST_UNSUPPORTED(".short 0xf38c,0x0f17 @ usat pc, #24, r12")
+ TEST_UNSUPPORTED(".short 0xf38d,0x0c17 @ usat r12, #24, sp")
+ TEST_UNSUPPORTED(".short 0xf38f,0x0c17 @ usat r12, #24, pc")
+
+ TEST_R( "ssat16 r0, #12, r",0, HH1,"")
+ TEST_R( "ssat16 r14, #12, r",12, HH2,"")
+ TEST_UNSUPPORTED(".short 0xf32c,0x0d0b @ ssat16 sp, #12, r12")
+ TEST_UNSUPPORTED(".short 0xf32c,0x0f0b @ ssat16 pc, #12, r12")
+ TEST_UNSUPPORTED(".short 0xf32d,0x0c0b @ ssat16 r12, #12, sp")
+ TEST_UNSUPPORTED(".short 0xf32f,0x0c0b @ ssat16 r12, #12, pc")
+
+ TEST_R( "usat16 r0, #12, r",0, HH1,"")
+ TEST_R( "usat16 r14, #12, r",12, HH2,"")
+ TEST_UNSUPPORTED(".short 0xf3ac,0x0d0b @ usat16 sp, #12, r12")
+ TEST_UNSUPPORTED(".short 0xf3ac,0x0f0b @ usat16 pc, #12, r12")
+ TEST_UNSUPPORTED(".short 0xf3ad,0x0c0b @ usat16 r12, #12, sp")
+ TEST_UNSUPPORTED(".short 0xf3af,0x0c0b @ usat16 r12, #12, pc")
+
+ TEST_R( "sbfx r0, r",0 , VAL1,", #0, #31")
+ TEST_R( "sbfx r14, r",12, VAL2,", #8, #16")
+ TEST_R( "sbfx r4, r",10, VAL1,", #16, #15")
+ TEST_UNSUPPORTED(".short 0xf34c,0x2d0f @ sbfx sp, r12, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf34c,0x2f0f @ sbfx pc, r12, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf34d,0x2c0f @ sbfx r12, sp, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf34f,0x2c0f @ sbfx r12, pc, #8, #16")
+
+ TEST_R( "ubfx r0, r",0 , VAL1,", #0, #31")
+ TEST_R( "ubfx r14, r",12, VAL2,", #8, #16")
+ TEST_R( "ubfx r4, r",10, VAL1,", #16, #15")
+ TEST_UNSUPPORTED(".short 0xf3cc,0x2d0f @ ubfx sp, r12, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf3cc,0x2f0f @ ubfx pc, r12, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf3cd,0x2c0f @ ubfx r12, sp, #8, #16")
+ TEST_UNSUPPORTED(".short 0xf3cf,0x2c0f @ ubfx r12, pc, #8, #16")
+
+ TEST_R( "bfc r",0, VAL1,", #4, #20")
+ TEST_R( "bfc r",14,VAL2,", #4, #20")
+ TEST_R( "bfc r",7, VAL1,", #0, #31")
+ TEST_R( "bfc r",8, VAL2,", #0, #31")
+ TEST_UNSUPPORTED(".short 0xf36f,0x0d1e @ bfc sp, #0, #31")
+ TEST_UNSUPPORTED(".short 0xf36f,0x0f1e @ bfc pc, #0, #31")
+
+ TEST_RR( "bfi r",0, VAL1,", r",0 , VAL2,", #0, #31")
+ TEST_RR( "bfi r",12,VAL1,", r",14 , VAL2,", #4, #20")
+ TEST_UNSUPPORTED(".short 0xf36e,0x1d17 @ bfi sp, r14, #4, #20")
+ TEST_UNSUPPORTED(".short 0xf36e,0x1f17 @ bfi pc, r14, #4, #20")
+ TEST_UNSUPPORTED(".short 0xf36d,0x1e17 @ bfi r14, sp, #4, #20")
+
+ TEST_GROUP("Branches and miscellaneous control")
+
+CONDITION_INSTRUCTIONS(22,
+ TEST_BF("beq.w 2f")
+ TEST_BB("bne.w 2b")
+ TEST_BF("bgt.w 2f")
+ TEST_BB("blt.w 2b")
+ TEST_BF_X("bpl.w 2f",0x1000)
+)
+
+ TEST_UNSUPPORTED("msr cpsr, r0")
+ TEST_UNSUPPORTED("msr cpsr_f, r1")
+ TEST_UNSUPPORTED("msr spsr, r2")
+
+ TEST_UNSUPPORTED("cpsie.w i")
+ TEST_UNSUPPORTED("cpsid.w i")
+ TEST_UNSUPPORTED("cps 0x13")
+
+ TEST_SUPPORTED("yield.w")
+ TEST("sev.w")
+ TEST("nop.w")
+ TEST("wfi.w")
+ TEST_SUPPORTED("wfe.w")
+ TEST_UNSUPPORTED("dbg.w #0")
+
+ TEST_UNSUPPORTED("clrex")
+ TEST_UNSUPPORTED("dsb")
+ TEST_UNSUPPORTED("dmb")
+ TEST_UNSUPPORTED("isb")
+
+ TEST_UNSUPPORTED("bxj r0")
+
+ TEST_UNSUPPORTED("subs pc, lr, #4")
+
+ TEST("mrs r0, cpsr")
+ TEST("mrs r14, cpsr")
+ TEST_UNSUPPORTED(".short 0xf3ef,0x8d00 @ mrs sp, spsr")
+ TEST_UNSUPPORTED(".short 0xf3ef,0x8f00 @ mrs pc, spsr")
+ TEST_UNSUPPORTED("mrs r0, spsr")
+ TEST_UNSUPPORTED("mrs lr, spsr")
+
+ TEST_UNSUPPORTED(".short 0xf7f0,0x8000 @ smc #0")
+
+ TEST_UNSUPPORTED(".short 0xf7f0,0xa000 @ undefeined")
+
+ TEST_BF( "b.w 2f")
+ TEST_BB( "b.w 2b")
+ TEST_BF_X("b.w 2f", 0x1000)
+
+ TEST_BF( "bl.w 2f")
+ TEST_BB( "bl.w 2b")
+ TEST_BB_X("bl.w 2b", 0x1000)
+
+ TEST_X( "blx __dummy_arm_subroutine",
+ ".arm \n\t"
+ ".align \n\t"
+ ".type __dummy_arm_subroutine, %%function \n\t"
+ "__dummy_arm_subroutine: \n\t"
+ "mov r0, pc \n\t"
+ "bx lr \n\t"
+ ".thumb \n\t"
+ )
+ TEST( "blx __dummy_arm_subroutine")
+
+ TEST_GROUP("Store single data item")
+
+#define SINGLE_STORE(size) \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,-1024,", #1024]") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, -1024,", #1080]") \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,256, ", #-120]") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]") \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,24, "], #120") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, "], #128") \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,24, "], #-120") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, "], #-128") \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,24, ", #120]!") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, ", #128]!") \
+ TEST_RP( "str"size" r",0, VAL1,", [r",11,256, ", #-120]!") \
+ TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]!") \
+ TEST_RPR("str"size".w r",0, VAL1,", [r",1, 0,", r",2, 4,"]") \
+ TEST_RPR("str"size" r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]") \
+ TEST_R( "str"size".w r",7, VAL1,", [sp, #24]") \
+ TEST_RP( "str"size".w r",0, VAL2,", [r",0,0, "]") \
+ TEST_UNSUPPORTED("str"size"t r0, [r1, #4]")
+
+ SINGLE_STORE("b")
+ SINGLE_STORE("h")
+ SINGLE_STORE("")
+
+ TEST("str sp, [sp]")
+ TEST_UNSUPPORTED(".short 0xf8cf,0xe000 @ str r14, [pc]")
+ TEST_UNSUPPORTED(".short 0xf8ce,0xf000 @ str pc, [r14]")
+
+ TEST_GROUP("Advanced SIMD element or structure load/store instructions")
+
+ TEST_UNSUPPORTED(".short 0xf900,0x0000")
+ TEST_UNSUPPORTED(".short 0xf92f,0xffff")
+ TEST_UNSUPPORTED(".short 0xf980,0x0000")
+ TEST_UNSUPPORTED(".short 0xf9ef,0xffff")
+
+ TEST_GROUP("Load single data item and memory hints")
+
+#define SINGLE_LOAD(size) \
+ TEST_P( "ldr"size" r0, [r",11,-1024, ", #1024]") \
+ TEST_P( "ldr"size" r14, [r",1, -1024,", #1080]") \
+ TEST_P( "ldr"size" r0, [r",11,256, ", #-120]") \
+ TEST_P( "ldr"size" r14, [r",1, 256, ", #-128]") \
+ TEST_P( "ldr"size" r0, [r",11,24, "], #120") \
+ TEST_P( "ldr"size" r14, [r",1, 24, "], #128") \
+ TEST_P( "ldr"size" r0, [r",11,24, "], #-120") \
+ TEST_P( "ldr"size" r14, [r",1,24, "], #-128") \
+ TEST_P( "ldr"size" r0, [r",11,24, ", #120]!") \
+ TEST_P( "ldr"size" r14, [r",1, 24, ", #128]!") \
+ TEST_P( "ldr"size" r0, [r",11,256, ", #-120]!") \
+ TEST_P( "ldr"size" r14, [r",1, 256, ", #-128]!") \
+ TEST_PR("ldr"size".w r0, [r",1, 0,", r",2, 4,"]") \
+ TEST_PR("ldr"size" r14, [r",10,0,", r",11,4,", lsl #1]") \
+ TEST_X( "ldr"size".w r0, 3f", \
+ ".align 3 \n\t" \
+ "3: .word "__stringify(VAL1)) \
+ TEST_X( "ldr"size".w r14, 3f", \
+ ".align 3 \n\t" \
+ "3: .word "__stringify(VAL2)) \
+ TEST( "ldr"size".w r7, 3b") \
+ TEST( "ldr"size".w r7, [sp, #24]") \
+ TEST_P( "ldr"size".w r0, [r",0,0, "]") \
+ TEST_UNSUPPORTED("ldr"size"t r0, [r1, #4]")
+
+ SINGLE_LOAD("b")
+ SINGLE_LOAD("sb")
+ SINGLE_LOAD("h")
+ SINGLE_LOAD("sh")
+ SINGLE_LOAD("")
+
+ TEST_BF_P("ldr pc, [r",14, 15*4,"]")
+ TEST_P( "ldr sp, [r",14, 13*4,"]")
+ TEST_BF_R("ldr pc, [sp, r",14, 15*4,"]")
+ TEST_R( "ldr sp, [sp, r",14, 13*4,"]")
+ TEST_THUMB_TO_ARM_INTERWORK_P("ldr pc, [r",0,0,", #15*4]")
+ TEST_SUPPORTED("ldr sp, 99f")
+ TEST_SUPPORTED("ldr pc, 99f")
+
+ TEST_UNSUPPORTED(".short 0xf854,0x700d @ ldr r7, [r4, sp]")
+ TEST_UNSUPPORTED(".short 0xf854,0x700f @ ldr r7, [r4, pc]")
+ TEST_UNSUPPORTED(".short 0xf814,0x700d @ ldrb r7, [r4, sp]")
+ TEST_UNSUPPORTED(".short 0xf814,0x700f @ ldrb r7, [r4, pc]")
+ TEST_UNSUPPORTED(".short 0xf89f,0xd004 @ ldrb sp, 99f")
+ TEST_UNSUPPORTED(".short 0xf814,0xd008 @ ldrb sp, [r4, r8]")
+ TEST_UNSUPPORTED(".short 0xf894,0xd000 @ ldrb sp, [r4]")
+
+ TEST_UNSUPPORTED(".short 0xf860,0x0000") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xf9ff,0xffff") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xf950,0x0000") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xf95f,0xffff") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xf800,0x0800") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xf97f,0xfaff") /* Unallocated space */
+
+ TEST( "pli [pc, #4]")
+ TEST( "pli [pc, #-4]")
+ TEST( "pld [pc, #4]")
+ TEST( "pld [pc, #-4]")
+
+ TEST_P( "pld [r",0,-1024,", #1024]")
+ TEST( ".short 0xf8b0,0xf400 @ pldw [r0, #1024]")
+ TEST_P( "pli [r",4, 0b,", #1024]")
+ TEST_P( "pld [r",7, 120,", #-120]")
+ TEST( ".short 0xf837,0xfc78 @ pldw [r7, #-120]")
+ TEST_P( "pli [r",11,120,", #-120]")
+ TEST( "pld [sp, #0]")
+
+ TEST_PR("pld [r",7, 24, ", r",0, 16,"]")
+ TEST_PR("pld [r",8, 24, ", r",12,16,", lsl #3]")
+ TEST_SUPPORTED(".short 0xf837,0xf000 @ pldw [r7, r0]")
+ TEST_SUPPORTED(".short 0xf838,0xf03c @ pldw [r8, r12, lsl #3]");
+ TEST_RR("pli [r",12,0b,", r",0, 16,"]")
+ TEST_RR("pli [r",0, 0b,", r",12,16,", lsl #3]")
+ TEST_R( "pld [sp, r",1, 16,"]")
+ TEST_UNSUPPORTED(".short 0xf817,0xf00d @pld [r7, sp]")
+ TEST_UNSUPPORTED(".short 0xf817,0xf00f @pld [r7, pc]")
+
+ TEST_GROUP("Data-processing (register)")
+
+#define SHIFTS32(op) \
+ TEST_RR(op" r0, r",1, VAL1,", r",2, 3, "") \
+ TEST_RR(op" r14, r",12,VAL2,", r",11,10,"")
+
+ SHIFTS32("lsl")
+ SHIFTS32("lsls")
+ SHIFTS32("lsr")
+ SHIFTS32("lsrs")
+ SHIFTS32("asr")
+ SHIFTS32("asrs")
+ SHIFTS32("ror")
+ SHIFTS32("rors")
+
+ TEST_UNSUPPORTED(".short 0xfa01,0xff02 @ lsl pc, r1, r2")
+ TEST_UNSUPPORTED(".short 0xfa01,0xfd02 @ lsl sp, r1, r2")
+ TEST_UNSUPPORTED(".short 0xfa0f,0xf002 @ lsl r0, pc, r2")
+ TEST_UNSUPPORTED(".short 0xfa0d,0xf002 @ lsl r0, sp, r2")
+ TEST_UNSUPPORTED(".short 0xfa01,0xf00f @ lsl r0, r1, pc")
+ TEST_UNSUPPORTED(".short 0xfa01,0xf00d @ lsl r0, r1, sp")
+
+ TEST_RR( "sxtah r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxth r8, r",7, HH1,"")
+
+ TEST_UNSUPPORTED(".short 0xfa0f,0xff87 @ sxth pc, r7");
+ TEST_UNSUPPORTED(".short 0xfa0f,0xfd87 @ sxth sp, r7");
+ TEST_UNSUPPORTED(".short 0xfa0f,0xf88f @ sxth r8, pc");
+ TEST_UNSUPPORTED(".short 0xfa0f,0xf88d @ sxth r8, sp");
+
+ TEST_RR( "uxtah r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtah r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxth r8, r",7, HH1,"")
+
+ TEST_RR( "sxtab16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxtb16 r8, r",7, HH1,"")
+
+ TEST_RR( "uxtab16 r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxtb16 r8, r",7, HH1,"")
+
+ TEST_RR( "sxtab r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "sxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "sxtb r8, r",7, HH1,"")
+
+ TEST_RR( "uxtab r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "uxtab r14,r",12, HH2,", r",10,HH1,", ror #8")
+ TEST_R( "uxtb r8, r",7, HH1,"")
+
+ TEST_UNSUPPORTED(".short 0xfa60,0x00f0")
+ TEST_UNSUPPORTED(".short 0xfa7f,0xffff")
+
+#define PARALLEL_ADD_SUB(op) \
+ TEST_RR( op"add16 r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"add16 r14, r",12,HH2,", r",10,HH1,"") \
+ TEST_RR( op"asx r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"asx r14, r",12,HH2,", r",10,HH1,"") \
+ TEST_RR( op"sax r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"sax r14, r",12,HH2,", r",10,HH1,"") \
+ TEST_RR( op"sub16 r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"sub16 r14, r",12,HH2,", r",10,HH1,"") \
+ TEST_RR( op"add8 r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"add8 r14, r",12,HH2,", r",10,HH1,"") \
+ TEST_RR( op"sub8 r0, r",0, HH1,", r",1, HH2,"") \
+ TEST_RR( op"sub8 r14, r",12,HH2,", r",10,HH1,"")
+
+ TEST_GROUP("Parallel addition and subtraction, signed")
+
+ PARALLEL_ADD_SUB("s")
+ PARALLEL_ADD_SUB("q")
+ PARALLEL_ADD_SUB("sh")
+
+ TEST_GROUP("Parallel addition and subtraction, unsigned")
+
+ PARALLEL_ADD_SUB("u")
+ PARALLEL_ADD_SUB("uq")
+ PARALLEL_ADD_SUB("uh")
+
+ TEST_GROUP("Miscellaneous operations")
+
+ TEST_RR("qadd r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR("qadd lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_RR("qsub r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR("qsub lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_RR("qdadd r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR("qdadd lr, r",9, VAL2,", r",8, VAL1,"")
+ TEST_RR("qdsub r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR("qdsub lr, r",9, VAL2,", r",8, VAL1,"")
+
+ TEST_R("rev.w r0, r",0, VAL1,"")
+ TEST_R("rev r14, r",12, VAL2,"")
+ TEST_R("rev16.w r0, r",0, VAL1,"")
+ TEST_R("rev16 r14, r",12, VAL2,"")
+ TEST_R("rbit r0, r",0, VAL1,"")
+ TEST_R("rbit r14, r",12, VAL2,"")
+ TEST_R("revsh.w r0, r",0, VAL1,"")
+ TEST_R("revsh r14, r",12, VAL2,"")
+
+ TEST_UNSUPPORTED(".short 0xfa9c,0xff8c @ rev pc, r12");
+ TEST_UNSUPPORTED(".short 0xfa9c,0xfd8c @ rev sp, r12");
+ TEST_UNSUPPORTED(".short 0xfa9f,0xfe8f @ rev r14, pc");
+ TEST_UNSUPPORTED(".short 0xfa9d,0xfe8d @ rev r14, sp");
+
+ TEST_RR("sel r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR("sel r14, r",12,VAL1,", r",10, VAL2,"")
+
+ TEST_R("clz r0, r",0, 0x0,"")
+ TEST_R("clz r7, r",14,0x1,"")
+ TEST_R("clz lr, r",7, 0xffffffff,"")
+
+ TEST_UNSUPPORTED(".short 0xfa80,0xf030") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfab0,0xf000") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */
+
+ TEST_GROUP("Multiply, multiply accumulate, and absolute difference operations")
+
+ TEST_RR( "mul r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "mul r7, r",8, VAL2,", r",9, VAL2,"")
+ TEST_UNSUPPORTED(".short 0xfb08,0xff09 @ mul pc, r8, r9")
+ TEST_UNSUPPORTED(".short 0xfb08,0xfd09 @ mul sp, r8, r9")
+ TEST_UNSUPPORTED(".short 0xfb0f,0xf709 @ mul r7, pc, r9")
+ TEST_UNSUPPORTED(".short 0xfb0d,0xf709 @ mul r7, sp, r9")
+ TEST_UNSUPPORTED(".short 0xfb08,0xf70f @ mul r7, r8, pc")
+ TEST_UNSUPPORTED(".short 0xfb08,0xf70d @ mul r7, r8, sp")
+
+ TEST_RRR( "mla r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "mla r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_UNSUPPORTED(".short 0xfb08,0xaf09 @ mla pc, r8, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb08,0xad09 @ mla sp, r8, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb0f,0xa709 @ mla r7, pc, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb0d,0xa709 @ mla r7, sp, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb08,0xa70f @ mla r7, r8, pc, r10");
+ TEST_UNSUPPORTED(".short 0xfb08,0xa70d @ mla r7, r8, sp, r10");
+ TEST_UNSUPPORTED(".short 0xfb08,0xd709 @ mla r7, r8, r9, sp");
+
+ TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "mls r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+
+ TEST_RRR( "smlabb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlabb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RRR( "smlatb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlatb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RRR( "smlabt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlabt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RRR( "smlatt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlatt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smulbb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulbb r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_RR( "smultb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smultb r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_RR( "smulbt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulbt r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_RR( "smultt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smultt r7, r",8, VAL3,", r",9, VAL1,"")
+
+ TEST_RRR( "smlad r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlad r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_RRR( "smladx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smladx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_RR( "smuad r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smuad r14, r",12,HH2,", r",10,HH1,"")
+ TEST_RR( "smuadx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smuadx r14, r",12,HH2,", r",10,HH1,"")
+
+ TEST_RRR( "smlawb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlawb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RRR( "smlawt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"")
+ TEST_RRR( "smlawt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+ TEST_RR( "smulwb r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulwb r7, r",8, VAL3,", r",9, VAL1,"")
+ TEST_RR( "smulwt r0, r",1, VAL1,", r",2, VAL2,"")
+ TEST_RR( "smulwt r7, r",8, VAL3,", r",9, VAL1,"")
+
+ TEST_RRR( "smlsd r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlsd r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_RRR( "smlsdx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"")
+ TEST_RRR( "smlsdx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+ TEST_RR( "smusd r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smusd r14, r",12,HH2,", r",10,HH1,"")
+ TEST_RR( "smusdx r0, r",0, HH1,", r",1, HH2,"")
+ TEST_RR( "smusdx r14, r",12,HH2,", r",10,HH1,"")
+
+ TEST_RRR( "smmla r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmla r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_RRR( "smmlar r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmlar r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_RR( "smmul r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "smmul r14, r",12,VAL2,", r",10,VAL1,"")
+ TEST_RR( "smmulr r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "smmulr r14, r",12,VAL2,", r",10,VAL1,"")
+
+ TEST_RRR( "smmls r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmls r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+ TEST_RRR( "smmlsr r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"")
+ TEST_RRR( "smmlsr r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+
+ TEST_RRR( "usada8 r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL3,"")
+ TEST_RRR( "usada8 r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
+ TEST_RR( "usad8 r0, r",0, VAL1,", r",1, VAL2,"")
+ TEST_RR( "usad8 r14, r",12,VAL2,", r",10,VAL1,"")
+
+ TEST_UNSUPPORTED(".short 0xfb00,0xf010") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfb0f,0xff1f") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfb70,0xf010") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfb70,0x0010") /* Unallocated space */
+ TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */
+
+ TEST_GROUP("Long multiply, long multiply accumulate, and divide")
+
+ TEST_RR( "smull r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "smull r7, r8, r",9, VAL2,", r",10, VAL1,"")
+ TEST_UNSUPPORTED(".short 0xfb89,0xf80a @ smull pc, r8, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb89,0xd80a @ smull sp, r8, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb89,0x7f0a @ smull r7, pc, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb89,0x7d0a @ smull r7, sp, r9, r10");
+ TEST_UNSUPPORTED(".short 0xfb8f,0x780a @ smull r7, r8, pc, r10");
+ TEST_UNSUPPORTED(".short 0xfb8d,0x780a @ smull r7, r8, sp, r10");
+ TEST_UNSUPPORTED(".short 0xfb89,0x780f @ smull r7, r8, r9, pc");
+ TEST_UNSUPPORTED(".short 0xfb89,0x780d @ smull r7, r8, r9, sp");
+
+ TEST_RR( "umull r0, r1, r",2, VAL1,", r",3, VAL2,"")
+ TEST_RR( "umull r7, r8, r",9, VAL2,", r",10, VAL1,"")
+
+ TEST_RRRR( "smlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+ TEST_RRRR( "smlalbb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalbb r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRRR( "smlalbt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlalbt r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRRR( "smlaltb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlaltb r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRRR( "smlaltt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "smlaltt r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+ TEST_RRRR( "smlald r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlald r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+ TEST_RRRR( "smlaldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlaldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+
+ TEST_RRRR( "smlsld r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlsld r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+ TEST_RRRR( "smlsldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+ TEST_RRRR( "smlsldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+
+ TEST_RRRR( "umlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "umlal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+ TEST_RRRR( "umaal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+ TEST_RRRR( "umaal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+ TEST_GROUP("Coprocessor instructions")
+
+ TEST_UNSUPPORTED(".short 0xfc00,0x0000")
+ TEST_UNSUPPORTED(".short 0xffff,0xffff")
+
+ TEST_GROUP("Testing instructions in IT blocks")
+
+ TEST_ITBLOCK("sub.w r0, r0")
+
+ verbose("\n");
+}
+
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
new file mode 100644
index 000000000000..e17cdd6d90d8
--- /dev/null
+++ b/arch/arm/kernel/kprobes-test.c
@@ -0,0 +1,1748 @@
+/*
+ * arch/arm/kernel/kprobes-test.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * 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 file contains test code for ARM kprobes.
+ *
+ * The top level function run_all_tests() executes tests for all of the
+ * supported instruction sets: ARM, 16-bit Thumb, and 32-bit Thumb. These tests
+ * fall into two categories; run_api_tests() checks basic functionality of the
+ * kprobes API, and run_test_cases() is a comprehensive test for kprobes
+ * instruction decoding and simulation.
+ *
+ * run_test_cases() first checks the kprobes decoding table for self consistency
+ * (using table_test()) then executes a series of test cases for each of the CPU
+ * instruction forms. coverage_start() and coverage_end() are used to verify
+ * that these test cases cover all of the possible combinations of instructions
+ * described by the kprobes decoding tables.
+ *
+ * The individual test cases are in kprobes-test-arm.c and kprobes-test-thumb.c
+ * which use the macros defined in kprobes-test.h. The rest of this
+ * documentation will describe the operation of the framework used by these
+ * test cases.
+ */
+
+/*
+ * TESTING METHODOLOGY
+ * -------------------
+ *
+ * The methodology used to test an ARM instruction 'test_insn' is to use
+ * inline assembler like:
+ *
+ * test_before: nop
+ * test_case: test_insn
+ * test_after: nop
+ *
+ * When the test case is run a kprobe is placed of each nop. The
+ * post-handler of the test_before probe is used to modify the saved CPU
+ * register context to that which we require for the test case. The
+ * pre-handler of the of the test_after probe saves a copy of the CPU
+ * register context. In this way we can execute test_insn with a specific
+ * register context and see the results afterwards.
+ *
+ * To actually test the kprobes instruction emulation we perform the above
+ * step a second time but with an additional kprobe on the test_case
+ * instruction itself. If the emulation is accurate then the results seen
+ * by the test_after probe will be identical to the first run which didn't
+ * have a probe on test_case.
+ *
+ * Each test case is run several times with a variety of variations in the
+ * flags value of stored in CPSR, and for Thumb code, different ITState.
+ *
+ * For instructions which can modify PC, a second test_after probe is used
+ * like this:
+ *
+ * test_before: nop
+ * test_case: test_insn
+ * test_after: nop
+ * b test_done
+ * test_after2: nop
+ * test_done:
+ *
+ * The test case is constructed such that test_insn branches to
+ * test_after2, or, if testing a conditional instruction, it may just
+ * continue to test_after. The probes inserted at both locations let us
+ * determine which happened. A similar approach is used for testing
+ * backwards branches...
+ *
+ * b test_before
+ * b test_done @ helps to cope with off by 1 branches
+ * test_after2: nop
+ * b test_done
+ * test_before: nop
+ * test_case: test_insn
+ * test_after: nop
+ * test_done:
+ *
+ * The macros used to generate the assembler instructions describe above
+ * are TEST_INSTRUCTION, TEST_BRANCH_F (branch forwards) and TEST_BRANCH_B
+ * (branch backwards). In these, the local variables numbered 1, 50, 2 and
+ * 99 represent: test_before, test_case, test_after2 and test_done.
+ *
+ * FRAMEWORK
+ * ---------
+ *
+ * Each test case is wrapped between the pair of macros TESTCASE_START and
+ * TESTCASE_END. As well as performing the inline assembler boilerplate,
+ * these call out to the kprobes_test_case_start() and
+ * kprobes_test_case_end() functions which drive the execution of the test
+ * case. The specific arguments to use for each test case are stored as
+ * inline data constructed using the various TEST_ARG_* macros. Putting
+ * this all together, a simple test case may look like:
+ *
+ * TESTCASE_START("Testing mov r0, r7")
+ * TEST_ARG_REG(7, 0x12345678) // Set r7=0x12345678
+ * TEST_ARG_END("")
+ * TEST_INSTRUCTION("mov r0, r7")
+ * TESTCASE_END
+ *
+ * Note, in practice the single convenience macro TEST_R would be used for this
+ * instead.
+ *
+ * The above would expand to assembler looking something like:
+ *
+ * @ TESTCASE_START
+ * bl __kprobes_test_case_start
+ * @ start of inline data...
+ * .ascii "mov r0, r7" @ text title for test case
+ * .byte 0
+ * .align 2
+ *
+ * @ TEST_ARG_REG
+ * .byte ARG_TYPE_REG
+ * .byte 7
+ * .short 0
+ * .word 0x1234567
+ *
+ * @ TEST_ARG_END
+ * .byte ARG_TYPE_END
+ * .byte TEST_ISA @ flags, including ISA being tested
+ * .short 50f-0f @ offset of 'test_before'
+ * .short 2f-0f @ offset of 'test_after2' (if relevent)
+ * .short 99f-0f @ offset of 'test_done'
+ * @ start of test case code...
+ * 0:
+ * .code TEST_ISA @ switch to ISA being tested
+ *
+ * @ TEST_INSTRUCTION
+ * 50: nop @ location for 'test_before' probe
+ * 1: mov r0, r7 @ the test case instruction 'test_insn'
+ * nop @ location for 'test_after' probe
+ *
+ * // TESTCASE_END
+ * 2:
+ * 99: bl __kprobes_test_case_end_##TEST_ISA
+ * .code NONMAL_ISA
+ *
+ * When the above is execute the following happens...
+ *
+ * __kprobes_test_case_start() is an assembler wrapper which sets up space
+ * for a stack buffer and calls the C function kprobes_test_case_start().
+ * This C function will do some initial processing of the inline data and
+ * setup some global state. It then inserts the test_before and test_after
+ * kprobes and returns a value which causes the assembler wrapper to jump
+ * to the start of the test case code, (local label '0').
+ *
+ * When the test case code executes, the test_before probe will be hit and
+ * test_before_post_handler will call setup_test_context(). This fills the
+ * stack buffer and CPU registers with a test pattern and then processes
+ * the test case arguments. In our example there is one TEST_ARG_REG which
+ * indicates that R7 should be loaded with the value 0x12345678.
+ *
+ * When the test_before probe ends, the test case continues and executes
+ * the "mov r0, r7" instruction. It then hits the test_after probe and the
+ * pre-handler for this (test_after_pre_handler) will save a copy of the
+ * CPU register context. This should now have R0 holding the same value as
+ * R7.
+ *
+ * Finally we get to the call to __kprobes_test_case_end_{32,16}. This is
+ * an assembler wrapper which switches back to the ISA used by the test
+ * code and calls the C function kprobes_test_case_end().
+ *
+ * For each run through the test case, test_case_run_count is incremented
+ * by one. For even runs, kprobes_test_case_end() saves a copy of the
+ * register and stack buffer contents from the test case just run. It then
+ * inserts a kprobe on the test case instruction 'test_insn' and returns a
+ * value to cause the test case code to be re-run.
+ *
+ * For odd numbered runs, kprobes_test_case_end() compares the register and
+ * stack buffer contents to those that were saved on the previous even
+ * numbered run (the one without the kprobe on test_insn). These should be
+ * the same if the kprobe instruction simulation routine is correct.
+ *
+ * The pair of test case runs is repeated with different combinations of
+ * flag values in CPSR and, for Thumb, different ITState. This is
+ * controlled by test_context_cpsr().
+ *
+ * BUILDING TEST CASES
+ * -------------------
+ *
+ *
+ * As an aid to building test cases, the stack buffer is initialised with
+ * some special values:
+ *
+ * [SP+13*4] Contains SP+120. This can be used to test instructions
+ * which load a value into SP.
+ *
+ * [SP+15*4] When testing branching instructions using TEST_BRANCH_{F,B},
+ * this holds the target address of the branch, 'test_after2'.
+ * This can be used to test instructions which load a PC value
+ * from memory.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+#include "kprobes-test.h"
+
+
+#define BENCHMARKING 1
+
+
+/*
+ * Test basic API
+ */
+
+static bool test_regs_ok;
+static int test_func_instance;
+static int pre_handler_called;
+static int post_handler_called;
+static int jprobe_func_called;
+static int kretprobe_handler_called;
+
+#define FUNC_ARG1 0x12345678
+#define FUNC_ARG2 0xabcdef
+
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+long arm_func(long r0, long r1);
+
+static void __used __naked __arm_kprobes_test_func(void)
+{
+ __asm__ __volatile__ (
+ ".arm \n\t"
+ ".type arm_func, %%function \n\t"
+ "arm_func: \n\t"
+ "adds r0, r0, r1 \n\t"
+ "bx lr \n\t"
+ ".code "NORMAL_ISA /* Back to Thumb if necessary */
+ : : : "r0", "r1", "cc"
+ );
+}
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+long thumb16_func(long r0, long r1);
+long thumb32even_func(long r0, long r1);
+long thumb32odd_func(long r0, long r1);
+
+static void __used __naked __thumb_kprobes_test_funcs(void)
+{
+ __asm__ __volatile__ (
+ ".type thumb16_func, %%function \n\t"
+ "thumb16_func: \n\t"
+ "adds.n r0, r0, r1 \n\t"
+ "bx lr \n\t"
+
+ ".align \n\t"
+ ".type thumb32even_func, %%function \n\t"
+ "thumb32even_func: \n\t"
+ "adds.w r0, r0, r1 \n\t"
+ "bx lr \n\t"
+
+ ".align \n\t"
+ "nop.n \n\t"
+ ".type thumb32odd_func, %%function \n\t"
+ "thumb32odd_func: \n\t"
+ "adds.w r0, r0, r1 \n\t"
+ "bx lr \n\t"
+
+ : : : "r0", "r1", "cc"
+ );
+}
+
+#endif /* CONFIG_THUMB2_KERNEL */
+
+
+static int call_test_func(long (*func)(long, long), bool check_test_regs)
+{
+ long ret;
+
+ ++test_func_instance;
+ test_regs_ok = false;
+
+ ret = (*func)(FUNC_ARG1, FUNC_ARG2);
+ if (ret != FUNC_ARG1 + FUNC_ARG2) {
+ pr_err("FAIL: call_test_func: func returned %lx\n", ret);
+ return false;
+ }
+
+ if (check_test_regs && !test_regs_ok) {
+ pr_err("FAIL: test regs not OK\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int __kprobes pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ pre_handler_called = test_func_instance;
+ if (regs->ARM_r0 == FUNC_ARG1 && regs->ARM_r1 == FUNC_ARG2)
+ test_regs_ok = true;
+ return 0;
+}
+
+static void __kprobes post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
+{
+ post_handler_called = test_func_instance;
+ if (regs->ARM_r0 != FUNC_ARG1 + FUNC_ARG2 || regs->ARM_r1 != FUNC_ARG2)
+ test_regs_ok = false;
+}
+
+static struct kprobe the_kprobe = {
+ .addr = 0,
+ .pre_handler = pre_handler,
+ .post_handler = post_handler
+};
+
+static int test_kprobe(long (*func)(long, long))
+{
+ int ret;
+
+ the_kprobe.addr = (kprobe_opcode_t *)func;
+ ret = register_kprobe(&the_kprobe);
+ if (ret < 0) {
+ pr_err("FAIL: register_kprobe failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = call_test_func(func, true);
+
+ unregister_kprobe(&the_kprobe);
+ the_kprobe.flags = 0; /* Clear disable flag to allow reuse */
+
+ if (!ret)
+ return -EINVAL;
+ if (pre_handler_called != test_func_instance) {
+ pr_err("FAIL: kprobe pre_handler not called\n");
+ return -EINVAL;
+ }
+ if (post_handler_called != test_func_instance) {
+ pr_err("FAIL: kprobe post_handler not called\n");
+ return -EINVAL;
+ }
+ if (!call_test_func(func, false))
+ return -EINVAL;
+ if (pre_handler_called == test_func_instance ||
+ post_handler_called == test_func_instance) {
+ pr_err("FAIL: probe called after unregistering\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void __kprobes jprobe_func(long r0, long r1)
+{
+ jprobe_func_called = test_func_instance;
+ if (r0 == FUNC_ARG1 && r1 == FUNC_ARG2)
+ test_regs_ok = true;
+ jprobe_return();
+}
+
+static struct jprobe the_jprobe = {
+ .entry = jprobe_func,
+};
+
+static int test_jprobe(long (*func)(long, long))
+{
+ int ret;
+
+ the_jprobe.kp.addr = (kprobe_opcode_t *)func;
+ ret = register_jprobe(&the_jprobe);
+ if (ret < 0) {
+ pr_err("FAIL: register_jprobe failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = call_test_func(func, true);
+
+ unregister_jprobe(&the_jprobe);
+ the_jprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
+
+ if (!ret)
+ return -EINVAL;
+ if (jprobe_func_called != test_func_instance) {
+ pr_err("FAIL: jprobe handler function not called\n");
+ return -EINVAL;
+ }
+ if (!call_test_func(func, false))
+ return -EINVAL;
+ if (jprobe_func_called == test_func_instance) {
+ pr_err("FAIL: probe called after unregistering\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __kprobes
+kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ kretprobe_handler_called = test_func_instance;
+ if (regs_return_value(regs) == FUNC_ARG1 + FUNC_ARG2)
+ test_regs_ok = true;
+ return 0;
+}
+
+static struct kretprobe the_kretprobe = {
+ .handler = kretprobe_handler,
+};
+
+static int test_kretprobe(long (*func)(long, long))
+{
+ int ret;
+
+ the_kretprobe.kp.addr = (kprobe_opcode_t *)func;
+ ret = register_kretprobe(&the_kretprobe);
+ if (ret < 0) {
+ pr_err("FAIL: register_kretprobe failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = call_test_func(func, true);
+
+ unregister_kretprobe(&the_kretprobe);
+ the_kretprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
+
+ if (!ret)
+ return -EINVAL;
+ if (kretprobe_handler_called != test_func_instance) {
+ pr_err("FAIL: kretprobe handler not called\n");
+ return -EINVAL;
+ }
+ if (!call_test_func(func, false))
+ return -EINVAL;
+ if (jprobe_func_called == test_func_instance) {
+ pr_err("FAIL: kretprobe called after unregistering\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int run_api_tests(long (*func)(long, long))
+{
+ int ret;
+
+ pr_info(" kprobe\n");
+ ret = test_kprobe(func);
+ if (ret < 0)
+ return ret;
+
+ pr_info(" jprobe\n");
+ ret = test_jprobe(func);
+ if (ret < 0)
+ return ret;
+
+ pr_info(" kretprobe\n");
+ ret = test_kretprobe(func);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+
+/*
+ * Benchmarking
+ */
+
+#if BENCHMARKING
+
+static void __naked benchmark_nop(void)
+{
+ __asm__ __volatile__ (
+ "nop \n\t"
+ "bx lr"
+ );
+}
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define wide ".w"
+#else
+#define wide
+#endif
+
+static void __naked benchmark_pushpop1(void)
+{
+ __asm__ __volatile__ (
+ "stmdb"wide" sp!, {r3-r11,lr} \n\t"
+ "ldmia"wide" sp!, {r3-r11,pc}"
+ );
+}
+
+static void __naked benchmark_pushpop2(void)
+{
+ __asm__ __volatile__ (
+ "stmdb"wide" sp!, {r0-r8,lr} \n\t"
+ "ldmia"wide" sp!, {r0-r8,pc}"
+ );
+}
+
+static void __naked benchmark_pushpop3(void)
+{
+ __asm__ __volatile__ (
+ "stmdb"wide" sp!, {r4,lr} \n\t"
+ "ldmia"wide" sp!, {r4,pc}"
+ );
+}
+
+static void __naked benchmark_pushpop4(void)
+{
+ __asm__ __volatile__ (
+ "stmdb"wide" sp!, {r0,lr} \n\t"
+ "ldmia"wide" sp!, {r0,pc}"
+ );
+}
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+static void __naked benchmark_pushpop_thumb(void)
+{
+ __asm__ __volatile__ (
+ "push.n {r0-r7,lr} \n\t"
+ "pop.n {r0-r7,pc}"
+ );
+}
+
+#endif
+
+static int __kprobes
+benchmark_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ return 0;
+}
+
+static int benchmark(void(*fn)(void))
+{
+ unsigned n, i, t, t0;
+
+ for (n = 1000; ; n *= 2) {
+ t0 = sched_clock();
+ for (i = n; i > 0; --i)
+ fn();
+ t = sched_clock() - t0;
+ if (t >= 250000000)
+ break; /* Stop once we took more than 0.25 seconds */
+ }
+ return t / n; /* Time for one iteration in nanoseconds */
+};
+
+static int kprobe_benchmark(void(*fn)(void), unsigned offset)
+{
+ struct kprobe k = {
+ .addr = (kprobe_opcode_t *)((uintptr_t)fn + offset),
+ .pre_handler = benchmark_pre_handler,
+ };
+
+ int ret = register_kprobe(&k);
+ if (ret < 0) {
+ pr_err("FAIL: register_kprobe failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = benchmark(fn);
+
+ unregister_kprobe(&k);
+ return ret;
+};
+
+struct benchmarks {
+ void (*fn)(void);
+ unsigned offset;
+ const char *title;
+};
+
+static int run_benchmarks(void)
+{
+ int ret;
+ struct benchmarks list[] = {
+ {&benchmark_nop, 0, "nop"},
+ /*
+ * benchmark_pushpop{1,3} will have the optimised
+ * instruction emulation, whilst benchmark_pushpop{2,4} will
+ * be the equivalent unoptimised instructions.
+ */
+ {&benchmark_pushpop1, 0, "stmdb sp!, {r3-r11,lr}"},
+ {&benchmark_pushpop1, 4, "ldmia sp!, {r3-r11,pc}"},
+ {&benchmark_pushpop2, 0, "stmdb sp!, {r0-r8,lr}"},
+ {&benchmark_pushpop2, 4, "ldmia sp!, {r0-r8,pc}"},
+ {&benchmark_pushpop3, 0, "stmdb sp!, {r4,lr}"},
+ {&benchmark_pushpop3, 4, "ldmia sp!, {r4,pc}"},
+ {&benchmark_pushpop4, 0, "stmdb sp!, {r0,lr}"},
+ {&benchmark_pushpop4, 4, "ldmia sp!, {r0,pc}"},
+#ifdef CONFIG_THUMB2_KERNEL
+ {&benchmark_pushpop_thumb, 0, "push.n {r0-r7,lr}"},
+ {&benchmark_pushpop_thumb, 2, "pop.n {r0-r7,pc}"},
+#endif
+ {0}
+ };
+
+ struct benchmarks *b;
+ for (b = list; b->fn; ++b) {
+ ret = kprobe_benchmark(b->fn, b->offset);
+ if (ret < 0)
+ return ret;
+ pr_info(" %dns for kprobe %s\n", ret, b->title);
+ }
+
+ pr_info("\n");
+ return 0;
+}
+
+#endif /* BENCHMARKING */
+
+
+/*
+ * Decoding table self-consistency tests
+ */
+
+static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
+ [DECODE_TYPE_TABLE] = sizeof(struct decode_table),
+ [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom),
+ [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate),
+ [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate),
+ [DECODE_TYPE_OR] = sizeof(struct decode_or),
+ [DECODE_TYPE_REJECT] = sizeof(struct decode_reject)
+};
+
+static int table_iter(const union decode_item *table,
+ int (*fn)(const struct decode_header *, void *),
+ void *args)
+{
+ const struct decode_header *h = (struct decode_header *)table;
+ int result;
+
+ for (;;) {
+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+ if (type == DECODE_TYPE_END)
+ return 0;
+
+ result = fn(h, args);
+ if (result)
+ return result;
+
+ h = (struct decode_header *)
+ ((uintptr_t)h + decode_struct_sizes[type]);
+
+ }
+}
+
+static int table_test_fail(const struct decode_header *h, const char* message)
+{
+
+ pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n",
+ message, h->mask.bits, h->value.bits);
+ return -EINVAL;
+}
+
+struct table_test_args {
+ const union decode_item *root_table;
+ u32 parent_mask;
+ u32 parent_value;
+};
+
+static int table_test_fn(const struct decode_header *h, void *args)
+{
+ struct table_test_args *a = (struct table_test_args *)args;
+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+ if (h->value.bits & ~h->mask.bits)
+ return table_test_fail(h, "Match value has bits not in mask");
+
+ if ((h->mask.bits & a->parent_mask) != a->parent_mask)
+ return table_test_fail(h, "Mask has bits not in parent mask");
+
+ if ((h->value.bits ^ a->parent_value) & a->parent_mask)
+ return table_test_fail(h, "Value is inconsistent with parent");
+
+ if (type == DECODE_TYPE_TABLE) {
+ struct decode_table *d = (struct decode_table *)h;
+ struct table_test_args args2 = *a;
+ args2.parent_mask = h->mask.bits;
+ args2.parent_value = h->value.bits;
+ return table_iter(d->table.table, table_test_fn, &args2);
+ }
+
+ return 0;
+}
+
+static int table_test(const union decode_item *table)
+{
+ struct table_test_args args = {
+ .root_table = table,
+ .parent_mask = 0,
+ .parent_value = 0
+ };
+ return table_iter(args.root_table, table_test_fn, &args);
+}
+
+
+/*
+ * Decoding table test coverage analysis
+ *
+ * coverage_start() builds a coverage_table which contains a list of
+ * coverage_entry's to match each entry in the specified kprobes instruction
+ * decoding table.
+ *
+ * When test cases are run, coverage_add() is called to process each case.
+ * This looks up the corresponding entry in the coverage_table and sets it as
+ * being matched, as well as clearing the regs flag appropriate for the test.
+ *
+ * After all test cases have been run, coverage_end() is called to check that
+ * all entries in coverage_table have been matched and that all regs flags are
+ * cleared. I.e. that all possible combinations of instructions described by
+ * the kprobes decoding tables have had a test case executed for them.
+ */
+
+bool coverage_fail;
+
+#define MAX_COVERAGE_ENTRIES 256
+
+struct coverage_entry {
+ const struct decode_header *header;
+ unsigned regs;
+ unsigned nesting;
+ char matched;
+};
+
+struct coverage_table {
+ struct coverage_entry *base;
+ unsigned num_entries;
+ unsigned nesting;
+};
+
+struct coverage_table coverage;
+
+#define COVERAGE_ANY_REG (1<<0)
+#define COVERAGE_SP (1<<1)
+#define COVERAGE_PC (1<<2)
+#define COVERAGE_PCWB (1<<3)
+
+static const char coverage_register_lookup[16] = {
+ [REG_TYPE_ANY] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
+ [REG_TYPE_SAMEAS16] = COVERAGE_ANY_REG,
+ [REG_TYPE_SP] = COVERAGE_SP,
+ [REG_TYPE_PC] = COVERAGE_PC,
+ [REG_TYPE_NOSP] = COVERAGE_ANY_REG | COVERAGE_SP,
+ [REG_TYPE_NOSPPC] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
+ [REG_TYPE_NOPC] = COVERAGE_ANY_REG | COVERAGE_PC,
+ [REG_TYPE_NOPCWB] = COVERAGE_ANY_REG | COVERAGE_PC | COVERAGE_PCWB,
+ [REG_TYPE_NOPCX] = COVERAGE_ANY_REG,
+ [REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP,
+};
+
+unsigned coverage_start_registers(const struct decode_header *h)
+{
+ unsigned regs = 0;
+ int i;
+ for (i = 0; i < 20; i += 4) {
+ int r = (h->type_regs.bits >> (DECODE_TYPE_BITS + i)) & 0xf;
+ regs |= coverage_register_lookup[r] << i;
+ }
+ return regs;
+}
+
+static int coverage_start_fn(const struct decode_header *h, void *args)
+{
+ struct coverage_table *coverage = (struct coverage_table *)args;
+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+ struct coverage_entry *entry = coverage->base + coverage->num_entries;
+
+ if (coverage->num_entries == MAX_COVERAGE_ENTRIES - 1) {
+ pr_err("FAIL: Out of space for test coverage data");
+ return -ENOMEM;
+ }
+
+ ++coverage->num_entries;
+
+ entry->header = h;
+ entry->regs = coverage_start_registers(h);
+ entry->nesting = coverage->nesting;
+ entry->matched = false;
+
+ if (type == DECODE_TYPE_TABLE) {
+ struct decode_table *d = (struct decode_table *)h;
+ int ret;
+ ++coverage->nesting;
+ ret = table_iter(d->table.table, coverage_start_fn, coverage);
+ --coverage->nesting;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int coverage_start(const union decode_item *table)
+{
+ coverage.base = kmalloc(MAX_COVERAGE_ENTRIES *
+ sizeof(struct coverage_entry), GFP_KERNEL);
+ coverage.num_entries = 0;
+ coverage.nesting = 0;
+ return table_iter(table, coverage_start_fn, &coverage);
+}
+
+static void
+coverage_add_registers(struct coverage_entry *entry, kprobe_opcode_t insn)
+{
+ int regs = entry->header->type_regs.bits >> DECODE_TYPE_BITS;
+ int i;
+ for (i = 0; i < 20; i += 4) {
+ enum decode_reg_type reg_type = (regs >> i) & 0xf;
+ int reg = (insn >> i) & 0xf;
+ int flag;
+
+ if (!reg_type)
+ continue;
+
+ if (reg == 13)
+ flag = COVERAGE_SP;
+ else if (reg == 15)
+ flag = COVERAGE_PC;
+ else
+ flag = COVERAGE_ANY_REG;
+ entry->regs &= ~(flag << i);
+
+ switch (reg_type) {
+
+ case REG_TYPE_NONE:
+ case REG_TYPE_ANY:
+ case REG_TYPE_SAMEAS16:
+ break;
+
+ case REG_TYPE_SP:
+ if (reg != 13)
+ return;
+ break;
+
+ case REG_TYPE_PC:
+ if (reg != 15)
+ return;
+ break;
+
+ case REG_TYPE_NOSP:
+ if (reg == 13)
+ return;
+ break;
+
+ case REG_TYPE_NOSPPC:
+ case REG_TYPE_NOSPPCX:
+ if (reg == 13 || reg == 15)
+ return;
+ break;
+
+ case REG_TYPE_NOPCWB:
+ if (!is_writeback(insn))
+ break;
+ if (reg == 15) {
+ entry->regs &= ~(COVERAGE_PCWB << i);
+ return;
+ }
+ break;
+
+ case REG_TYPE_NOPC:
+ case REG_TYPE_NOPCX:
+ if (reg == 15)
+ return;
+ break;
+ }
+
+ }
+}
+
+static void coverage_add(kprobe_opcode_t insn)
+{
+ struct coverage_entry *entry = coverage.base;
+ struct coverage_entry *end = coverage.base + coverage.num_entries;
+ bool matched = false;
+ unsigned nesting = 0;
+
+ for (; entry < end; ++entry) {
+ const struct decode_header *h = entry->header;
+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+ if (entry->nesting > nesting)
+ continue; /* Skip sub-table we didn't match */
+
+ if (entry->nesting < nesting)
+ break; /* End of sub-table we were scanning */
+
+ if (!matched) {
+ if ((insn & h->mask.bits) != h->value.bits)
+ continue;
+ entry->matched = true;
+ }
+
+ switch (type) {
+
+ case DECODE_TYPE_TABLE:
+ ++nesting;
+ break;
+
+ case DECODE_TYPE_CUSTOM:
+ case DECODE_TYPE_SIMULATE:
+ case DECODE_TYPE_EMULATE:
+ coverage_add_registers(entry, insn);
+ return;
+
+ case DECODE_TYPE_OR:
+ matched = true;
+ break;
+
+ case DECODE_TYPE_REJECT:
+ default:
+ return;
+ }
+
+ }
+}
+
+static void coverage_end(void)
+{
+ struct coverage_entry *entry = coverage.base;
+ struct coverage_entry *end = coverage.base + coverage.num_entries;
+
+ for (; entry < end; ++entry) {
+ u32 mask = entry->header->mask.bits;
+ u32 value = entry->header->value.bits;
+
+ if (entry->regs) {
+ pr_err("FAIL: Register test coverage missing for %08x %08x (%05x)\n",
+ mask, value, entry->regs);
+ coverage_fail = true;
+ }
+ if (!entry->matched) {
+ pr_err("FAIL: Test coverage entry missing for %08x %08x\n",
+ mask, value);
+ coverage_fail = true;
+ }
+ }
+
+ kfree(coverage.base);
+}
+
+
+/*
+ * Framework for instruction set test cases
+ */
+
+void __naked __kprobes_test_case_start(void)
+{
+ __asm__ __volatile__ (
+ "stmdb sp!, {r4-r11} \n\t"
+ "sub sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+ "bic r0, lr, #1 @ r0 = inline title string \n\t"
+ "mov r1, sp \n\t"
+ "bl kprobes_test_case_start \n\t"
+ "bx r0 \n\t"
+ );
+}
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+void __naked __kprobes_test_case_end_32(void)
+{
+ __asm__ __volatile__ (
+ "mov r4, lr \n\t"
+ "bl kprobes_test_case_end \n\t"
+ "cmp r0, #0 \n\t"
+ "movne pc, r0 \n\t"
+ "mov r0, r4 \n\t"
+ "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+ "ldmia sp!, {r4-r11} \n\t"
+ "mov pc, r0 \n\t"
+ );
+}
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+void __naked __kprobes_test_case_end_16(void)
+{
+ __asm__ __volatile__ (
+ "mov r4, lr \n\t"
+ "bl kprobes_test_case_end \n\t"
+ "cmp r0, #0 \n\t"
+ "bxne r0 \n\t"
+ "mov r0, r4 \n\t"
+ "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+ "ldmia sp!, {r4-r11} \n\t"
+ "bx r0 \n\t"
+ );
+}
+
+void __naked __kprobes_test_case_end_32(void)
+{
+ __asm__ __volatile__ (
+ ".arm \n\t"
+ "orr lr, lr, #1 @ will return to Thumb code \n\t"
+ "ldr pc, 1f \n\t"
+ "1: \n\t"
+ ".word __kprobes_test_case_end_16 \n\t"
+ );
+}
+
+#endif
+
+
+int kprobe_test_flags;
+int kprobe_test_cc_position;
+
+static int test_try_count;
+static int test_pass_count;
+static int test_fail_count;
+
+static struct pt_regs initial_regs;
+static struct pt_regs expected_regs;
+static struct pt_regs result_regs;
+
+static u32 expected_memory[TEST_MEMORY_SIZE/sizeof(u32)];
+
+static const char *current_title;
+static struct test_arg *current_args;
+static u32 *current_stack;
+static uintptr_t current_branch_target;
+
+static uintptr_t current_code_start;
+static kprobe_opcode_t current_instruction;
+
+
+#define TEST_CASE_PASSED -1
+#define TEST_CASE_FAILED -2
+
+static int test_case_run_count;
+static bool test_case_is_thumb;
+static int test_instance;
+
+/*
+ * We ignore the state of the imprecise abort disable flag (CPSR.A) because this
+ * can change randomly as the kernel doesn't take care to preserve or initialise
+ * this across context switches. Also, with Security Extentions, the flag may
+ * not be under control of the kernel; for this reason we ignore the state of
+ * the FIQ disable flag CPSR.F as well.
+ */
+#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
+
+static unsigned long test_check_cc(int cc, unsigned long cpsr)
+{
+ unsigned long temp;
+
+ switch (cc) {
+ case 0x0: /* eq */
+ return cpsr & PSR_Z_BIT;
+
+ case 0x1: /* ne */
+ return (~cpsr) & PSR_Z_BIT;
+
+ case 0x2: /* cs */
+ return cpsr & PSR_C_BIT;
+
+ case 0x3: /* cc */
+ return (~cpsr) & PSR_C_BIT;
+
+ case 0x4: /* mi */
+ return cpsr & PSR_N_BIT;
+
+ case 0x5: /* pl */
+ return (~cpsr) & PSR_N_BIT;
+
+ case 0x6: /* vs */
+ return cpsr & PSR_V_BIT;
+
+ case 0x7: /* vc */
+ return (~cpsr) & PSR_V_BIT;
+
+ case 0x8: /* hi */
+ cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+ return cpsr & PSR_C_BIT;
+
+ case 0x9: /* ls */
+ cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+ return (~cpsr) & PSR_C_BIT;
+
+ case 0xa: /* ge */
+ cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ return (~cpsr) & PSR_N_BIT;
+
+ case 0xb: /* lt */
+ cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ return cpsr & PSR_N_BIT;
+
+ case 0xc: /* gt */
+ temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
+ return (~temp) & PSR_N_BIT;
+
+ case 0xd: /* le */
+ temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+ temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
+ return temp & PSR_N_BIT;
+
+ case 0xe: /* al */
+ case 0xf: /* unconditional */
+ return true;
+ }
+ BUG();
+ return false;
+}
+
+static int is_last_scenario;
+static int probe_should_run; /* 0 = no, 1 = yes, -1 = unknown */
+static int memory_needs_checking;
+
+static unsigned long test_context_cpsr(int scenario)
+{
+ unsigned long cpsr;
+
+ probe_should_run = 1;
+
+ /* Default case is that we cycle through 16 combinations of flags */
+ cpsr = (scenario & 0xf) << 28; /* N,Z,C,V flags */
+ cpsr |= (scenario & 0xf) << 16; /* GE flags */
+ cpsr |= (scenario & 0x1) << 27; /* Toggle Q flag */
+
+ if (!test_case_is_thumb) {
+ /* Testing ARM code */
+ probe_should_run = test_check_cc(current_instruction >> 28, cpsr) != 0;
+ if (scenario == 15)
+ is_last_scenario = true;
+
+ } else if (kprobe_test_flags & TEST_FLAG_NO_ITBLOCK) {
+ /* Testing Thumb code without setting ITSTATE */
+ if (kprobe_test_cc_position) {
+ int cc = (current_instruction >> kprobe_test_cc_position) & 0xf;
+ probe_should_run = test_check_cc(cc, cpsr) != 0;
+ }
+
+ if (scenario == 15)
+ is_last_scenario = true;
+
+ } else if (kprobe_test_flags & TEST_FLAG_FULL_ITBLOCK) {
+ /* Testing Thumb code with all combinations of ITSTATE */
+ unsigned x = (scenario >> 4);
+ unsigned cond_base = x % 7; /* ITSTATE<7:5> */
+ unsigned mask = x / 7 + 2; /* ITSTATE<4:0>, bits reversed */
+
+ if (mask > 0x1f) {
+ /* Finish by testing state from instruction 'itt al' */
+ cond_base = 7;
+ mask = 0x4;
+ if ((scenario & 0xf) == 0xf)
+ is_last_scenario = true;
+ }
+
+ cpsr |= cond_base << 13; /* ITSTATE<7:5> */
+ cpsr |= (mask & 0x1) << 12; /* ITSTATE<4> */
+ cpsr |= (mask & 0x2) << 10; /* ITSTATE<3> */
+ cpsr |= (mask & 0x4) << 8; /* ITSTATE<2> */
+ cpsr |= (mask & 0x8) << 23; /* ITSTATE<1> */
+ cpsr |= (mask & 0x10) << 21; /* ITSTATE<0> */
+
+ probe_should_run = test_check_cc((cpsr >> 12) & 0xf, cpsr) != 0;
+
+ } else {
+ /* Testing Thumb code with several combinations of ITSTATE */
+ switch (scenario) {
+ case 16: /* Clear NZCV flags and 'it eq' state (false as Z=0) */
+ cpsr = 0x00000800;
+ probe_should_run = 0;
+ break;
+ case 17: /* Set NZCV flags and 'it vc' state (false as V=1) */
+ cpsr = 0xf0007800;
+ probe_should_run = 0;
+ break;
+ case 18: /* Clear NZCV flags and 'it ls' state (true as C=0) */
+ cpsr = 0x00009800;
+ break;
+ case 19: /* Set NZCV flags and 'it cs' state (true as C=1) */
+ cpsr = 0xf0002800;
+ is_last_scenario = true;
+ break;
+ }
+ }
+
+ return cpsr;
+}
+
+static void setup_test_context(struct pt_regs *regs)
+{
+ int scenario = test_case_run_count>>1;
+ unsigned long val;
+ struct test_arg *args;
+ int i;
+
+ is_last_scenario = false;
+ memory_needs_checking = false;
+
+ /* Initialise test memory on stack */
+ val = (scenario & 1) ? VALM : ~VALM;
+ for (i = 0; i < TEST_MEMORY_SIZE / sizeof(current_stack[0]); ++i)
+ current_stack[i] = val + (i << 8);
+ /* Put target of branch on stack for tests which load PC from memory */
+ if (current_branch_target)
+ current_stack[15] = current_branch_target;
+ /* Put a value for SP on stack for tests which load SP from memory */
+ current_stack[13] = (u32)current_stack + 120;
+
+ /* Initialise register values to their default state */
+ val = (scenario & 2) ? VALR : ~VALR;
+ for (i = 0; i < 13; ++i)
+ regs->uregs[i] = val ^ (i << 8);
+ regs->ARM_lr = val ^ (14 << 8);
+ regs->ARM_cpsr &= ~(APSR_MASK | PSR_IT_MASK);
+ regs->ARM_cpsr |= test_context_cpsr(scenario);
+
+ /* Perform testcase specific register setup */
+ args = current_args;
+ for (; args[0].type != ARG_TYPE_END; ++args)
+ switch (args[0].type) {
+ case ARG_TYPE_REG: {
+ struct test_arg_regptr *arg =
+ (struct test_arg_regptr *)args;
+ regs->uregs[arg->reg] = arg->val;
+ break;
+ }
+ case ARG_TYPE_PTR: {
+ struct test_arg_regptr *arg =
+ (struct test_arg_regptr *)args;
+ regs->uregs[arg->reg] =
+ (unsigned long)current_stack + arg->val;
+ memory_needs_checking = true;
+ break;
+ }
+ case ARG_TYPE_MEM: {
+ struct test_arg_mem *arg = (struct test_arg_mem *)args;
+ current_stack[arg->index] = arg->val;
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+struct test_probe {
+ struct kprobe kprobe;
+ bool registered;
+ int hit;
+};
+
+static void unregister_test_probe(struct test_probe *probe)
+{
+ if (probe->registered) {
+ unregister_kprobe(&probe->kprobe);
+ probe->kprobe.flags = 0; /* Clear disable flag to allow reuse */
+ }
+ probe->registered = false;
+}
+
+static int register_test_probe(struct test_probe *probe)
+{
+ int ret;
+
+ if (probe->registered)
+ BUG();
+
+ ret = register_kprobe(&probe->kprobe);
+ if (ret >= 0) {
+ probe->registered = true;
+ probe->hit = -1;
+ }
+ return ret;
+}
+
+static int __kprobes
+test_before_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ container_of(p, struct test_probe, kprobe)->hit = test_instance;
+ return 0;
+}
+
+static void __kprobes
+test_before_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
+{
+ setup_test_context(regs);
+ initial_regs = *regs;
+ initial_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+}
+
+static int __kprobes
+test_case_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ container_of(p, struct test_probe, kprobe)->hit = test_instance;
+ return 0;
+}
+
+static int __kprobes
+test_after_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ if (container_of(p, struct test_probe, kprobe)->hit == test_instance)
+ return 0; /* Already run for this test instance */
+
+ result_regs = *regs;
+ result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+
+ /* Undo any changes done to SP by the test case */
+ regs->ARM_sp = (unsigned long)current_stack;
+
+ container_of(p, struct test_probe, kprobe)->hit = test_instance;
+ return 0;
+}
+
+static struct test_probe test_before_probe = {
+ .kprobe.pre_handler = test_before_pre_handler,
+ .kprobe.post_handler = test_before_post_handler,
+};
+
+static struct test_probe test_case_probe = {
+ .kprobe.pre_handler = test_case_pre_handler,
+};
+
+static struct test_probe test_after_probe = {
+ .kprobe.pre_handler = test_after_pre_handler,
+};
+
+static struct test_probe test_after2_probe = {
+ .kprobe.pre_handler = test_after_pre_handler,
+};
+
+static void test_case_cleanup(void)
+{
+ unregister_test_probe(&test_before_probe);
+ unregister_test_probe(&test_case_probe);
+ unregister_test_probe(&test_after_probe);
+ unregister_test_probe(&test_after2_probe);
+}
+
+static void print_registers(struct pt_regs *regs)
+{
+ pr_err("r0 %08lx | r1 %08lx | r2 %08lx | r3 %08lx\n",
+ regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
+ pr_err("r4 %08lx | r5 %08lx | r6 %08lx | r7 %08lx\n",
+ regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
+ pr_err("r8 %08lx | r9 %08lx | r10 %08lx | r11 %08lx\n",
+ regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp);
+ pr_err("r12 %08lx | sp %08lx | lr %08lx | pc %08lx\n",
+ regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc);
+ pr_err("cpsr %08lx\n", regs->ARM_cpsr);
+}
+
+static void print_memory(u32 *mem, size_t size)
+{
+ int i;
+ for (i = 0; i < size / sizeof(u32); i += 4)
+ pr_err("%08x %08x %08x %08x\n", mem[i], mem[i+1],
+ mem[i+2], mem[i+3]);
+}
+
+static size_t expected_memory_size(u32 *sp)
+{
+ size_t size = sizeof(expected_memory);
+ int offset = (uintptr_t)sp - (uintptr_t)current_stack;
+ if (offset > 0)
+ size -= offset;
+ return size;
+}
+
+static void test_case_failed(const char *message)
+{
+ test_case_cleanup();
+
+ pr_err("FAIL: %s\n", message);
+ pr_err("FAIL: Test %s\n", current_title);
+ pr_err("FAIL: Scenario %d\n", test_case_run_count >> 1);
+}
+
+static unsigned long next_instruction(unsigned long pc)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+ if ((pc & 1) && !is_wide_instruction(*(u16 *)(pc - 1)))
+ return pc + 2;
+ else
+#endif
+ return pc + 4;
+}
+
+static uintptr_t __used kprobes_test_case_start(const char *title, void *stack)
+{
+ struct test_arg *args;
+ struct test_arg_end *end_arg;
+ unsigned long test_code;
+
+ args = (struct test_arg *)PTR_ALIGN(title + strlen(title) + 1, 4);
+
+ current_title = title;
+ current_args = args;
+ current_stack = stack;
+
+ ++test_try_count;
+
+ while (args->type != ARG_TYPE_END)
+ ++args;
+ end_arg = (struct test_arg_end *)args;
+
+ test_code = (unsigned long)(args + 1); /* Code starts after args */
+
+ test_case_is_thumb = end_arg->flags & ARG_FLAG_THUMB;
+ if (test_case_is_thumb)
+ test_code |= 1;
+
+ current_code_start = test_code;
+
+ current_branch_target = 0;
+ if (end_arg->branch_offset != end_arg->end_offset)
+ current_branch_target = test_code + end_arg->branch_offset;
+
+ test_code += end_arg->code_offset;
+ test_before_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+ test_code = next_instruction(test_code);
+ test_case_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+ if (test_case_is_thumb) {
+ u16 *p = (u16 *)(test_code & ~1);
+ current_instruction = p[0];
+ if (is_wide_instruction(current_instruction)) {
+ current_instruction <<= 16;
+ current_instruction |= p[1];
+ }
+ } else {
+ current_instruction = *(u32 *)test_code;
+ }
+
+ if (current_title[0] == '.')
+ verbose("%s\n", current_title);
+ else
+ verbose("%s\t@ %0*x\n", current_title,
+ test_case_is_thumb ? 4 : 8,
+ current_instruction);
+
+ test_code = next_instruction(test_code);
+ test_after_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+ if (kprobe_test_flags & TEST_FLAG_NARROW_INSTR) {
+ if (!test_case_is_thumb ||
+ is_wide_instruction(current_instruction)) {
+ test_case_failed("expected 16-bit instruction");
+ goto fail;
+ }
+ } else {
+ if (test_case_is_thumb &&
+ !is_wide_instruction(current_instruction)) {
+ test_case_failed("expected 32-bit instruction");
+ goto fail;
+ }
+ }
+
+ coverage_add(current_instruction);
+
+ if (end_arg->flags & ARG_FLAG_UNSUPPORTED) {
+ if (register_test_probe(&test_case_probe) < 0)
+ goto pass;
+ test_case_failed("registered probe for unsupported instruction");
+ goto fail;
+ }
+
+ if (end_arg->flags & ARG_FLAG_SUPPORTED) {
+ if (register_test_probe(&test_case_probe) >= 0)
+ goto pass;
+ test_case_failed("couldn't register probe for supported instruction");
+ goto fail;
+ }
+
+ if (register_test_probe(&test_before_probe) < 0) {
+ test_case_failed("register test_before_probe failed");
+ goto fail;
+ }
+ if (register_test_probe(&test_after_probe) < 0) {
+ test_case_failed("register test_after_probe failed");
+ goto fail;
+ }
+ if (current_branch_target) {
+ test_after2_probe.kprobe.addr =
+ (kprobe_opcode_t *)current_branch_target;
+ if (register_test_probe(&test_after2_probe) < 0) {
+ test_case_failed("register test_after2_probe failed");
+ goto fail;
+ }
+ }
+
+ /* Start first run of test case */
+ test_case_run_count = 0;
+ ++test_instance;
+ return current_code_start;
+pass:
+ test_case_run_count = TEST_CASE_PASSED;
+ return (uintptr_t)test_after_probe.kprobe.addr;
+fail:
+ test_case_run_count = TEST_CASE_FAILED;
+ return (uintptr_t)test_after_probe.kprobe.addr;
+}
+
+static bool check_test_results(void)
+{
+ size_t mem_size = 0;
+ u32 *mem = 0;
+
+ if (memcmp(&expected_regs, &result_regs, sizeof(expected_regs))) {
+ test_case_failed("registers differ");
+ goto fail;
+ }
+
+ if (memory_needs_checking) {
+ mem = (u32 *)result_regs.ARM_sp;
+ mem_size = expected_memory_size(mem);
+ if (memcmp(expected_memory, mem, mem_size)) {
+ test_case_failed("test memory differs");
+ goto fail;
+ }
+ }
+
+ return true;
+
+fail:
+ pr_err("initial_regs:\n");
+ print_registers(&initial_regs);
+ pr_err("expected_regs:\n");
+ print_registers(&expected_regs);
+ pr_err("result_regs:\n");
+ print_registers(&result_regs);
+
+ if (mem) {
+ pr_err("current_stack=%p\n", current_stack);
+ pr_err("expected_memory:\n");
+ print_memory(expected_memory, mem_size);
+ pr_err("result_memory:\n");
+ print_memory(mem, mem_size);
+ }
+
+ return false;
+}
+
+static uintptr_t __used kprobes_test_case_end(void)
+{
+ if (test_case_run_count < 0) {
+ if (test_case_run_count == TEST_CASE_PASSED)
+ /* kprobes_test_case_start did all the needed testing */
+ goto pass;
+ else
+ /* kprobes_test_case_start failed */
+ goto fail;
+ }
+
+ if (test_before_probe.hit != test_instance) {
+ test_case_failed("test_before_handler not run");
+ goto fail;
+ }
+
+ if (test_after_probe.hit != test_instance &&
+ test_after2_probe.hit != test_instance) {
+ test_case_failed("test_after_handler not run");
+ goto fail;
+ }
+
+ /*
+ * Even numbered test runs ran without a probe on the test case so
+ * we can gather reference results. The subsequent odd numbered run
+ * will have the probe inserted.
+ */
+ if ((test_case_run_count & 1) == 0) {
+ /* Save results from run without probe */
+ u32 *mem = (u32 *)result_regs.ARM_sp;
+ expected_regs = result_regs;
+ memcpy(expected_memory, mem, expected_memory_size(mem));
+
+ /* Insert probe onto test case instruction */
+ if (register_test_probe(&test_case_probe) < 0) {
+ test_case_failed("register test_case_probe failed");
+ goto fail;
+ }
+ } else {
+ /* Check probe ran as expected */
+ if (probe_should_run == 1) {
+ if (test_case_probe.hit != test_instance) {
+ test_case_failed("test_case_handler not run");
+ goto fail;
+ }
+ } else if (probe_should_run == 0) {
+ if (test_case_probe.hit == test_instance) {
+ test_case_failed("test_case_handler ran");
+ goto fail;
+ }
+ }
+
+ /* Remove probe for any subsequent reference run */
+ unregister_test_probe(&test_case_probe);
+
+ if (!check_test_results())
+ goto fail;
+
+ if (is_last_scenario)
+ goto pass;
+ }
+
+ /* Do next test run */
+ ++test_case_run_count;
+ ++test_instance;
+ return current_code_start;
+fail:
+ ++test_fail_count;
+ goto end;
+pass:
+ ++test_pass_count;
+end:
+ test_case_cleanup();
+ return 0;
+}
+
+
+/*
+ * Top level test functions
+ */
+
+static int run_test_cases(void (*tests)(void), const union decode_item *table)
+{
+ int ret;
+
+ pr_info(" Check decoding tables\n");
+ ret = table_test(table);
+ if (ret)
+ return ret;
+
+ pr_info(" Run test cases\n");
+ ret = coverage_start(table);
+ if (ret)
+ return ret;
+
+ tests();
+
+ coverage_end();
+ return 0;
+}
+
+
+static int __init run_all_tests(void)
+{
+ int ret = 0;
+
+ pr_info("Begining kprobe tests...\n");
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+ pr_info("Probe ARM code\n");
+ ret = run_api_tests(arm_func);
+ if (ret)
+ goto out;
+
+ pr_info("ARM instruction simulation\n");
+ ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table);
+ if (ret)
+ goto out;
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+ pr_info("Probe 16-bit Thumb code\n");
+ ret = run_api_tests(thumb16_func);
+ if (ret)
+ goto out;
+
+ pr_info("Probe 32-bit Thumb code, even halfword\n");
+ ret = run_api_tests(thumb32even_func);
+ if (ret)
+ goto out;
+
+ pr_info("Probe 32-bit Thumb code, odd halfword\n");
+ ret = run_api_tests(thumb32odd_func);
+ if (ret)
+ goto out;
+
+ pr_info("16-bit Thumb instruction simulation\n");
+ ret = run_test_cases(kprobe_thumb16_test_cases,
+ kprobe_decode_thumb16_table);
+ if (ret)
+ goto out;
+
+ pr_info("32-bit Thumb instruction simulation\n");
+ ret = run_test_cases(kprobe_thumb32_test_cases,
+ kprobe_decode_thumb32_table);
+ if (ret)
+ goto out;
+#endif
+
+ pr_info("Total instruction simulation tests=%d, pass=%d fail=%d\n",
+ test_try_count, test_pass_count, test_fail_count);
+ if (test_fail_count) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+#if BENCHMARKING
+ pr_info("Benchmarks\n");
+ ret = run_benchmarks();
+ if (ret)
+ goto out;
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+ /* We are able to run all test cases so coverage should be complete */
+ if (coverage_fail) {
+ pr_err("FAIL: Test coverage checks failed\n");
+ ret = -EINVAL;
+ goto out;
+ }
+#endif
+
+out:
+ if (ret == 0)
+ pr_info("Finished kprobe tests OK\n");
+ else
+ pr_err("kprobe tests failed\n");
+
+ return ret;
+}
+
+
+/*
+ * Module setup
+ */
+
+#ifdef MODULE
+
+static void __exit kprobe_test_exit(void)
+{
+}
+
+module_init(run_all_tests)
+module_exit(kprobe_test_exit)
+MODULE_LICENSE("GPL");
+
+#else /* !MODULE */
+
+late_initcall(run_all_tests);
+
+#endif
diff --git a/arch/arm/kernel/kprobes-test.h b/arch/arm/kernel/kprobes-test.h
new file mode 100644
index 000000000000..0dc5d77b9356
--- /dev/null
+++ b/arch/arm/kernel/kprobes-test.h
@@ -0,0 +1,392 @@
+/*
+ * arch/arm/kernel/kprobes-test.h
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define VERBOSE 0 /* Set to '1' for more logging of test cases */
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define NORMAL_ISA "16"
+#else
+#define NORMAL_ISA "32"
+#endif
+
+
+/* Flags used in kprobe_test_flags */
+#define TEST_FLAG_NO_ITBLOCK (1<<0)
+#define TEST_FLAG_FULL_ITBLOCK (1<<1)
+#define TEST_FLAG_NARROW_INSTR (1<<2)
+
+extern int kprobe_test_flags;
+extern int kprobe_test_cc_position;
+
+
+#define TEST_MEMORY_SIZE 256
+
+
+/*
+ * Test case structures.
+ *
+ * The arguments given to test cases can be one of three types.
+ *
+ * ARG_TYPE_REG
+ * Load a register with the given value.
+ *
+ * ARG_TYPE_PTR
+ * Load a register with a pointer into the stack buffer (SP + given value).
+ *
+ * ARG_TYPE_MEM
+ * Store the given value into the stack buffer at [SP+index].
+ *
+ */
+
+#define ARG_TYPE_END 0
+#define ARG_TYPE_REG 1
+#define ARG_TYPE_PTR 2
+#define ARG_TYPE_MEM 3
+
+#define ARG_FLAG_UNSUPPORTED 0x01
+#define ARG_FLAG_SUPPORTED 0x02
+#define ARG_FLAG_THUMB 0x10 /* Must be 16 so TEST_ISA can be used */
+#define ARG_FLAG_ARM 0x20 /* Must be 32 so TEST_ISA can be used */
+
+struct test_arg {
+ u8 type; /* ARG_TYPE_x */
+ u8 _padding[7];
+};
+
+struct test_arg_regptr {
+ u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR */
+ u8 reg;
+ u8 _padding[2];
+ u32 val;
+};
+
+struct test_arg_mem {
+ u8 type; /* ARG_TYPE_MEM */
+ u8 index;
+ u8 _padding[2];
+ u32 val;
+};
+
+struct test_arg_end {
+ u8 type; /* ARG_TYPE_END */
+ u8 flags; /* ARG_FLAG_x */
+ u16 code_offset;
+ u16 branch_offset;
+ u16 end_offset;
+};
+
+
+/*
+ * Building blocks for test cases.
+ *
+ * Each test case is wrapped between TESTCASE_START and TESTCASE_END.
+ *
+ * To specify arguments for a test case the TEST_ARG_{REG,PTR,MEM} macros are
+ * used followed by a terminating TEST_ARG_END.
+ *
+ * After this, the instruction to be tested is defined with TEST_INSTRUCTION.
+ * Or for branches, TEST_BRANCH_B and TEST_BRANCH_F (branch forwards/backwards).
+ *
+ * Some specific test cases may make use of other custom constructs.
+ */
+
+#if VERBOSE
+#define verbose(fmt, ...) pr_info(fmt, ##__VA_ARGS__)
+#else
+#define verbose(fmt, ...)
+#endif
+
+#define TEST_GROUP(title) \
+ verbose("\n"); \
+ verbose(title"\n"); \
+ verbose("---------------------------------------------------------\n");
+
+#define TESTCASE_START(title) \
+ __asm__ __volatile__ ( \
+ "bl __kprobes_test_case_start \n\t" \
+ /* don't use .asciz here as 'title' may be */ \
+ /* multiple strings to be concatenated. */ \
+ ".ascii "#title" \n\t" \
+ ".byte 0 \n\t" \
+ ".align 2 \n\t"
+
+#define TEST_ARG_REG(reg, val) \
+ ".byte "__stringify(ARG_TYPE_REG)" \n\t" \
+ ".byte "#reg" \n\t" \
+ ".short 0 \n\t" \
+ ".word "#val" \n\t"
+
+#define TEST_ARG_PTR(reg, val) \
+ ".byte "__stringify(ARG_TYPE_PTR)" \n\t" \
+ ".byte "#reg" \n\t" \
+ ".short 0 \n\t" \
+ ".word "#val" \n\t"
+
+#define TEST_ARG_MEM(index, val) \
+ ".byte "__stringify(ARG_TYPE_MEM)" \n\t" \
+ ".byte "#index" \n\t" \
+ ".short 0 \n\t" \
+ ".word "#val" \n\t"
+
+#define TEST_ARG_END(flags) \
+ ".byte "__stringify(ARG_TYPE_END)" \n\t" \
+ ".byte "TEST_ISA flags" \n\t" \
+ ".short 50f-0f \n\t" \
+ ".short 2f-0f \n\t" \
+ ".short 99f-0f \n\t" \
+ ".code "TEST_ISA" \n\t" \
+ "0: \n\t"
+
+#define TEST_INSTRUCTION(instruction) \
+ "50: nop \n\t" \
+ "1: "instruction" \n\t" \
+ " nop \n\t"
+
+#define TEST_BRANCH_F(instruction, xtra_dist) \
+ TEST_INSTRUCTION(instruction) \
+ ".if "#xtra_dist" \n\t" \
+ " b 99f \n\t" \
+ ".space "#xtra_dist" \n\t" \
+ ".endif \n\t" \
+ " b 99f \n\t" \
+ "2: nop \n\t"
+
+#define TEST_BRANCH_B(instruction, xtra_dist) \
+ " b 50f \n\t" \
+ " b 99f \n\t" \
+ "2: nop \n\t" \
+ " b 99f \n\t" \
+ ".if "#xtra_dist" \n\t" \
+ ".space "#xtra_dist" \n\t" \
+ ".endif \n\t" \
+ TEST_INSTRUCTION(instruction)
+
+#define TESTCASE_END \
+ "2: \n\t" \
+ "99: \n\t" \
+ " bl __kprobes_test_case_end_"TEST_ISA" \n\t" \
+ ".code "NORMAL_ISA" \n\t" \
+ : : \
+ : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" \
+ );
+
+
+/*
+ * Macros to define test cases.
+ *
+ * Those of the form TEST_{R,P,M}* can be used to define test cases
+ * which take combinations of the three basic types of arguments. E.g.
+ *
+ * TEST_R One register argument
+ * TEST_RR Two register arguments
+ * TEST_RPR A register, a pointer, then a register argument
+ *
+ * For testing instructions which may branch, there are macros TEST_BF_*
+ * and TEST_BB_* for branching forwards and backwards.
+ *
+ * TEST_SUPPORTED and TEST_UNSUPPORTED don't cause the code to be executed,
+ * the just verify that a kprobe is or is not allowed on the given instruction.
+ */
+
+#define TEST(code) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code) \
+ TESTCASE_END
+
+#define TEST_UNSUPPORTED(code) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("|"__stringify(ARG_FLAG_UNSUPPORTED)) \
+ TEST_INSTRUCTION(code) \
+ TESTCASE_END
+
+#define TEST_SUPPORTED(code) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("|"__stringify(ARG_FLAG_SUPPORTED)) \
+ TEST_INSTRUCTION(code) \
+ TESTCASE_END
+
+#define TEST_R(code1, reg, val, code2) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg code2) \
+ TESTCASE_END
+
+#define TEST_RR(code1, reg1, val1, code2, reg2, val2, code3) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \
+ TESTCASE_END
+
+#define TEST_RRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_REG(reg3, val3) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TESTCASE_END
+
+#define TEST_RRRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4, reg4, val4) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_REG(reg3, val3) \
+ TEST_ARG_REG(reg4, val4) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \
+ TESTCASE_END
+
+#define TEST_P(code1, reg1, val1, code2) \
+ TESTCASE_START(code1 #reg1 code2) \
+ TEST_ARG_PTR(reg1, val1) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2) \
+ TESTCASE_END
+
+#define TEST_PR(code1, reg1, val1, code2, reg2, val2, code3) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
+ TEST_ARG_PTR(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \
+ TESTCASE_END
+
+#define TEST_RP(code1, reg1, val1, code2, reg2, val2, code3) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_PTR(reg2, val2) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \
+ TESTCASE_END
+
+#define TEST_PRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TEST_ARG_PTR(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_REG(reg3, val3) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TESTCASE_END
+
+#define TEST_RPR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_PTR(reg2, val2) \
+ TEST_ARG_REG(reg3, val3) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TESTCASE_END
+
+#define TEST_RRP(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_PTR(reg3, val3) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \
+ TESTCASE_END
+
+#define TEST_BF_P(code1, reg1, val1, code2) \
+ TESTCASE_START(code1 #reg1 code2) \
+ TEST_ARG_PTR(reg1, val1) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_F(code1 #reg1 code2, 0) \
+ TESTCASE_END
+
+#define TEST_BF_X(code, xtra_dist) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_F(code, xtra_dist) \
+ TESTCASE_END
+
+#define TEST_BB_X(code, xtra_dist) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_B(code, xtra_dist) \
+ TESTCASE_END
+
+#define TEST_BF_RX(code1, reg, val, code2, xtra_dist) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_F(code1 #reg code2, xtra_dist) \
+ TESTCASE_END
+
+#define TEST_BB_RX(code1, reg, val, code2, xtra_dist) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_B(code1 #reg code2, xtra_dist) \
+ TESTCASE_END
+
+#define TEST_BF(code) TEST_BF_X(code, 0)
+#define TEST_BB(code) TEST_BB_X(code, 0)
+
+#define TEST_BF_R(code1, reg, val, code2) TEST_BF_RX(code1, reg, val, code2, 0)
+#define TEST_BB_R(code1, reg, val, code2) TEST_BB_RX(code1, reg, val, code2, 0)
+
+#define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_END("") \
+ TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3, 0) \
+ TESTCASE_END
+
+#define TEST_X(code, codex) \
+ TESTCASE_START(code) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code) \
+ " b 99f \n\t" \
+ " "codex" \n\t" \
+ TESTCASE_END
+
+#define TEST_RX(code1, reg, val, code2, codex) \
+ TESTCASE_START(code1 #reg code2) \
+ TEST_ARG_REG(reg, val) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 __stringify(reg) code2) \
+ " b 99f \n\t" \
+ " "codex" \n\t" \
+ TESTCASE_END
+
+#define TEST_RRX(code1, reg1, val1, code2, reg2, val2, code3, codex) \
+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
+ TEST_ARG_REG(reg1, val1) \
+ TEST_ARG_REG(reg2, val2) \
+ TEST_ARG_END("") \
+ TEST_INSTRUCTION(code1 __stringify(reg1) code2 __stringify(reg2) code3) \
+ " b 99f \n\t" \
+ " "codex" \n\t" \
+ TESTCASE_END
+
+
+/* Various values used in test cases... */
+#define N(val) (val ^ 0xffffffff)
+#define VAL1 0x12345678
+#define VAL2 N(VAL1)
+#define VAL3 0xa5f801
+#define VAL4 N(VAL3)
+#define VALM 0x456789ab
+#define VALR 0xdeaddead
+#define HH1 0x0123fecb
+#define HH2 0xa9874567
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+void kprobe_thumb16_test_cases(void);
+void kprobe_thumb32_test_cases(void);
+#else
+void kprobe_arm_test_cases(void);
+#endif
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 902ca59e8b11..8f96ec778e8d 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/kprobes.h>
+#include <linux/module.h>
#include "kprobes.h"
@@ -943,6 +944,9 @@ const union decode_item kprobe_decode_thumb32_table[] = {
*/
DECODE_END
};
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table);
+#endif
static void __kprobes
t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
@@ -1423,6 +1427,9 @@ const union decode_item kprobe_decode_thumb16_table[] = {
DECODE_END
};
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
+#endif
static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
{
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index a6aeda0a6c7f..38945f78f9f1 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -413,6 +413,14 @@ struct decode_reject {
DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
+#ifdef CONFIG_THUMB2_KERNEL
+extern const union decode_item kprobe_decode_thumb16_table[];
+extern const union decode_item kprobe_decode_thumb32_table[];
+#else
+extern const union decode_item kprobe_decode_arm_table[];
+#endif
+
+
int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
const union decode_item *table, bool thumb16);
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index e59bbd496c39..c1b4463dcc83 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -32,6 +32,24 @@ static atomic_t waiting_for_crash_ipi;
int machine_kexec_prepare(struct kimage *image)
{
+ unsigned long page_list;
+ void *reboot_code_buffer;
+ page_list = image->head & PAGE_MASK;
+
+ reboot_code_buffer = page_address(image->control_code_page);
+
+ /* Prepare parameters for reboot_code_buffer*/
+ kexec_start_address = image->start;
+ kexec_indirection_page = page_list;
+ kexec_mach_type = machine_arch_type;
+ kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
+
+ /* copy our kernel relocation code to the control code page */
+ memcpy(reboot_code_buffer,
+ relocate_new_kernel, relocate_new_kernel_size);
+
+ flush_icache_range((unsigned long) reboot_code_buffer,
+ (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
return 0;
}
@@ -82,31 +100,14 @@ void (*kexec_reinit)(void);
void machine_kexec(struct kimage *image)
{
- unsigned long page_list;
unsigned long reboot_code_buffer_phys;
void *reboot_code_buffer;
-
- page_list = image->head & PAGE_MASK;
-
/* we need both effective and real address here */
reboot_code_buffer_phys =
page_to_pfn(image->control_code_page) << PAGE_SHIFT;
reboot_code_buffer = page_address(image->control_code_page);
- /* Prepare parameters for reboot_code_buffer*/
- kexec_start_address = image->start;
- kexec_indirection_page = page_list;
- kexec_mach_type = machine_arch_type;
- kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
-
- /* copy our kernel relocation code to the control code page */
- memcpy(reboot_code_buffer,
- relocate_new_kernel, relocate_new_kernel_size);
-
-
- flush_icache_range((unsigned long) reboot_code_buffer,
- (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
printk(KERN_INFO "Bye!\n");
if (kexec_reinit)
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index cc2020c2c709..1e9be5d25e56 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -33,7 +33,7 @@
* recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off.
*/
#undef MODULES_VADDR
-#define MODULES_VADDR (((unsigned long)_etext + ~PGDIR_MASK) & PGDIR_MASK)
+#define MODULES_VADDR (((unsigned long)_etext + ~PMD_MASK) & PMD_MASK)
#endif
#ifdef CONFIG_MMU
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 53c9c2610cbc..e6e5d7c84f1a 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -12,6 +12,7 @@
*/
#define pr_fmt(fmt) "hw perfevents: " fmt
+#include <linux/bitmap.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -26,16 +27,8 @@
#include <asm/pmu.h>
#include <asm/stacktrace.h>
-static struct platform_device *pmu_device;
-
-/*
- * Hardware lock to serialize accesses to PMU registers. Needed for the
- * read/modify/write sequences.
- */
-static DEFINE_RAW_SPINLOCK(pmu_lock);
-
/*
- * ARMv6 supports a maximum of 3 events, starting from index 1. If we add
+ * ARMv6 supports a maximum of 3 events, starting from index 0. If we add
* another platform that supports more, we need to increase this to be the
* largest of all platforms.
*
@@ -43,62 +36,24 @@ static DEFINE_RAW_SPINLOCK(pmu_lock);
* cycle counter CCNT + 31 events counters CNT0..30.
* Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters.
*/
-#define ARMPMU_MAX_HWEVENTS 33
+#define ARMPMU_MAX_HWEVENTS 32
-/* The events for a given CPU. */
-struct cpu_hw_events {
- /*
- * The events that are active on the CPU for the given index. Index 0
- * is reserved.
- */
- struct perf_event *events[ARMPMU_MAX_HWEVENTS];
-
- /*
- * A 1 bit for an index indicates that the counter is being used for
- * an event. A 0 means that the counter can be used.
- */
- unsigned long used_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
+static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
+static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
+static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
- /*
- * A 1 bit for an index indicates that the counter is actively being
- * used.
- */
- unsigned long active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
-};
-static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
-
-struct arm_pmu {
- enum arm_perf_pmu_ids id;
- const char *name;
- irqreturn_t (*handle_irq)(int irq_num, void *dev);
- void (*enable)(struct hw_perf_event *evt, int idx);
- void (*disable)(struct hw_perf_event *evt, int idx);
- int (*get_event_idx)(struct cpu_hw_events *cpuc,
- struct hw_perf_event *hwc);
- u32 (*read_counter)(int idx);
- void (*write_counter)(int idx, u32 val);
- void (*start)(void);
- void (*stop)(void);
- void (*reset)(void *);
- const unsigned (*cache_map)[PERF_COUNT_HW_CACHE_MAX]
- [PERF_COUNT_HW_CACHE_OP_MAX]
- [PERF_COUNT_HW_CACHE_RESULT_MAX];
- const unsigned (*event_map)[PERF_COUNT_HW_MAX];
- u32 raw_event_mask;
- int num_events;
- u64 max_period;
-};
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
/* Set at runtime when we know what CPU type we are. */
-static const struct arm_pmu *armpmu;
+static struct arm_pmu *cpu_pmu;
enum arm_perf_pmu_ids
armpmu_get_pmu_id(void)
{
int id = -ENODEV;
- if (armpmu != NULL)
- id = armpmu->id;
+ if (cpu_pmu != NULL)
+ id = cpu_pmu->id;
return id;
}
@@ -109,8 +64,8 @@ armpmu_get_max_events(void)
{
int max_events = 0;
- if (armpmu != NULL)
- max_events = armpmu->num_events;
+ if (cpu_pmu != NULL)
+ max_events = cpu_pmu->num_events;
return max_events;
}
@@ -130,7 +85,11 @@ EXPORT_SYMBOL_GPL(perf_num_counters);
#define CACHE_OP_UNSUPPORTED 0xFFFF
static int
-armpmu_map_cache_event(u64 config)
+armpmu_map_cache_event(const unsigned (*cache_map)
+ [PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX],
+ u64 config)
{
unsigned int cache_type, cache_op, cache_result, ret;
@@ -146,7 +105,7 @@ armpmu_map_cache_event(u64 config)
if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
return -EINVAL;
- ret = (int)(*armpmu->cache_map)[cache_type][cache_op][cache_result];
+ ret = (int)(*cache_map)[cache_type][cache_op][cache_result];
if (ret == CACHE_OP_UNSUPPORTED)
return -ENOENT;
@@ -155,23 +114,46 @@ armpmu_map_cache_event(u64 config)
}
static int
-armpmu_map_event(u64 config)
+armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
{
- int mapping = (*armpmu->event_map)[config];
- return mapping == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : mapping;
+ int mapping = (*event_map)[config];
+ return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
}
static int
-armpmu_map_raw_event(u64 config)
+armpmu_map_raw_event(u32 raw_event_mask, u64 config)
{
- return (int)(config & armpmu->raw_event_mask);
+ return (int)(config & raw_event_mask);
}
-static int
+static int map_cpu_event(struct perf_event *event,
+ const unsigned (*event_map)[PERF_COUNT_HW_MAX],
+ const unsigned (*cache_map)
+ [PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX],
+ u32 raw_event_mask)
+{
+ u64 config = event->attr.config;
+
+ switch (event->attr.type) {
+ case PERF_TYPE_HARDWARE:
+ return armpmu_map_event(event_map, config);
+ case PERF_TYPE_HW_CACHE:
+ return armpmu_map_cache_event(cache_map, config);
+ case PERF_TYPE_RAW:
+ return armpmu_map_raw_event(raw_event_mask, config);
+ }
+
+ return -ENOENT;
+}
+
+int
armpmu_event_set_period(struct perf_event *event,
struct hw_perf_event *hwc,
int idx)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
s64 left = local64_read(&hwc->period_left);
s64 period = hwc->sample_period;
int ret = 0;
@@ -202,11 +184,12 @@ armpmu_event_set_period(struct perf_event *event,
return ret;
}
-static u64
+u64
armpmu_event_update(struct perf_event *event,
struct hw_perf_event *hwc,
int idx, int overflow)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
u64 delta, prev_raw_count, new_raw_count;
again:
@@ -246,11 +229,9 @@ armpmu_read(struct perf_event *event)
static void
armpmu_stop(struct perf_event *event, int flags)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
- if (!armpmu)
- return;
-
/*
* ARM pmu always has to update the counter, so ignore
* PERF_EF_UPDATE, see comments in armpmu_start().
@@ -266,11 +247,9 @@ armpmu_stop(struct perf_event *event, int flags)
static void
armpmu_start(struct perf_event *event, int flags)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
- if (!armpmu)
- return;
-
/*
* ARM pmu always has to reprogram the period, so ignore
* PERF_EF_RELOAD, see the comment below.
@@ -293,16 +272,16 @@ armpmu_start(struct perf_event *event, int flags)
static void
armpmu_del(struct perf_event *event, int flags)
{
- struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+ struct pmu_hw_events *hw_events = armpmu->get_hw_events();
struct hw_perf_event *hwc = &event->hw;
int idx = hwc->idx;
WARN_ON(idx < 0);
- clear_bit(idx, cpuc->active_mask);
armpmu_stop(event, PERF_EF_UPDATE);
- cpuc->events[idx] = NULL;
- clear_bit(idx, cpuc->used_mask);
+ hw_events->events[idx] = NULL;
+ clear_bit(idx, hw_events->used_mask);
perf_event_update_userpage(event);
}
@@ -310,7 +289,8 @@ armpmu_del(struct perf_event *event, int flags)
static int
armpmu_add(struct perf_event *event, int flags)
{
- struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+ struct pmu_hw_events *hw_events = armpmu->get_hw_events();
struct hw_perf_event *hwc = &event->hw;
int idx;
int err = 0;
@@ -318,7 +298,7 @@ armpmu_add(struct perf_event *event, int flags)
perf_pmu_disable(event->pmu);
/* If we don't have a space for the counter then finish early. */
- idx = armpmu->get_event_idx(cpuc, hwc);
+ idx = armpmu->get_event_idx(hw_events, hwc);
if (idx < 0) {
err = idx;
goto out;
@@ -330,8 +310,7 @@ armpmu_add(struct perf_event *event, int flags)
*/
event->hw.idx = idx;
armpmu->disable(hwc, idx);
- cpuc->events[idx] = event;
- set_bit(idx, cpuc->active_mask);
+ hw_events->events[idx] = event;
hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
if (flags & PERF_EF_START)
@@ -345,25 +324,25 @@ out:
return err;
}
-static struct pmu pmu;
-
static int
-validate_event(struct cpu_hw_events *cpuc,
+validate_event(struct pmu_hw_events *hw_events,
struct perf_event *event)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct hw_perf_event fake_event = event->hw;
+ struct pmu *leader_pmu = event->group_leader->pmu;
- if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
+ if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
return 1;
- return armpmu->get_event_idx(cpuc, &fake_event) >= 0;
+ return armpmu->get_event_idx(hw_events, &fake_event) >= 0;
}
static int
validate_group(struct perf_event *event)
{
struct perf_event *sibling, *leader = event->group_leader;
- struct cpu_hw_events fake_pmu;
+ struct pmu_hw_events fake_pmu;
memset(&fake_pmu, 0, sizeof(fake_pmu));
@@ -383,110 +362,119 @@ validate_group(struct perf_event *event)
static irqreturn_t armpmu_platform_irq(int irq, void *dev)
{
- struct arm_pmu_platdata *plat = dev_get_platdata(&pmu_device->dev);
+ struct arm_pmu *armpmu = (struct arm_pmu *) dev;
+ struct platform_device *plat_device = armpmu->plat_device;
+ struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev);
return plat->handle_irq(irq, dev, armpmu->handle_irq);
}
+static void
+armpmu_release_hardware(struct arm_pmu *armpmu)
+{
+ int i, irq, irqs;
+ struct platform_device *pmu_device = armpmu->plat_device;
+
+ irqs = min(pmu_device->num_resources, num_possible_cpus());
+
+ for (i = 0; i < irqs; ++i) {
+ if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
+ continue;
+ irq = platform_get_irq(pmu_device, i);
+ if (irq >= 0)
+ free_irq(irq, armpmu);
+ }
+
+ release_pmu(armpmu->type);
+}
+
static int
-armpmu_reserve_hardware(void)
+armpmu_reserve_hardware(struct arm_pmu *armpmu)
{
struct arm_pmu_platdata *plat;
irq_handler_t handle_irq;
- int i, err = -ENODEV, irq;
+ int i, err, irq, irqs;
+ struct platform_device *pmu_device = armpmu->plat_device;
- pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU);
- if (IS_ERR(pmu_device)) {
+ err = reserve_pmu(armpmu->type);
+ if (err) {
pr_warning("unable to reserve pmu\n");
- return PTR_ERR(pmu_device);
+ return err;
}
- init_pmu(ARM_PMU_DEVICE_CPU);
-
plat = dev_get_platdata(&pmu_device->dev);
if (plat && plat->handle_irq)
handle_irq = armpmu_platform_irq;
else
handle_irq = armpmu->handle_irq;
- if (pmu_device->num_resources < 1) {
+ irqs = min(pmu_device->num_resources, num_possible_cpus());
+ if (irqs < 1) {
pr_err("no irqs for PMUs defined\n");
return -ENODEV;
}
- for (i = 0; i < pmu_device->num_resources; ++i) {
+ for (i = 0; i < irqs; ++i) {
+ err = 0;
irq = platform_get_irq(pmu_device, i);
if (irq < 0)
continue;
+ /*
+ * If we have a single PMU interrupt that we can't shift,
+ * assume that we're running on a uniprocessor machine and
+ * continue. Otherwise, continue without this interrupt.
+ */
+ if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
+ pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
+ irq, i);
+ continue;
+ }
+
err = request_irq(irq, handle_irq,
IRQF_DISABLED | IRQF_NOBALANCING,
- "armpmu", NULL);
+ "arm-pmu", armpmu);
if (err) {
- pr_warning("unable to request IRQ%d for ARM perf "
- "counters\n", irq);
- break;
+ pr_err("unable to request IRQ%d for ARM PMU counters\n",
+ irq);
+ armpmu_release_hardware(armpmu);
+ return err;
}
- }
- if (err) {
- for (i = i - 1; i >= 0; --i) {
- irq = platform_get_irq(pmu_device, i);
- if (irq >= 0)
- free_irq(irq, NULL);
- }
- release_pmu(ARM_PMU_DEVICE_CPU);
- pmu_device = NULL;
+ cpumask_set_cpu(i, &armpmu->active_irqs);
}
- return err;
+ return 0;
}
static void
-armpmu_release_hardware(void)
+hw_perf_event_destroy(struct perf_event *event)
{
- int i, irq;
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+ atomic_t *active_events = &armpmu->active_events;
+ struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex;
- for (i = pmu_device->num_resources - 1; i >= 0; --i) {
- irq = platform_get_irq(pmu_device, i);
- if (irq >= 0)
- free_irq(irq, NULL);
+ if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) {
+ armpmu_release_hardware(armpmu);
+ mutex_unlock(pmu_reserve_mutex);
}
- armpmu->stop();
-
- release_pmu(ARM_PMU_DEVICE_CPU);
- pmu_device = NULL;
}
-static atomic_t active_events = ATOMIC_INIT(0);
-static DEFINE_MUTEX(pmu_reserve_mutex);
-
-static void
-hw_perf_event_destroy(struct perf_event *event)
+static int
+event_requires_mode_exclusion(struct perf_event_attr *attr)
{
- if (atomic_dec_and_mutex_lock(&active_events, &pmu_reserve_mutex)) {
- armpmu_release_hardware();
- mutex_unlock(&pmu_reserve_mutex);
- }
+ return attr->exclude_idle || attr->exclude_user ||
+ attr->exclude_kernel || attr->exclude_hv;
}
static int
__hw_perf_event_init(struct perf_event *event)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
int mapping, err;
- /* Decode the generic type into an ARM event identifier. */
- if (PERF_TYPE_HARDWARE == event->attr.type) {
- mapping = armpmu_map_event(event->attr.config);
- } else if (PERF_TYPE_HW_CACHE == event->attr.type) {
- mapping = armpmu_map_cache_event(event->attr.config);
- } else if (PERF_TYPE_RAW == event->attr.type) {
- mapping = armpmu_map_raw_event(event->attr.config);
- } else {
- pr_debug("event type %x not supported\n", event->attr.type);
- return -EOPNOTSUPP;
- }
+ mapping = armpmu->map_event(event);
if (mapping < 0) {
pr_debug("event %x:%llx not supported\n", event->attr.type,
@@ -495,34 +483,31 @@ __hw_perf_event_init(struct perf_event *event)
}
/*
+ * We don't assign an index until we actually place the event onto
+ * hardware. Use -1 to signify that we haven't decided where to put it
+ * yet. For SMP systems, each core has it's own PMU so we can't do any
+ * clever allocation or constraints checking at this point.
+ */
+ hwc->idx = -1;
+ hwc->config_base = 0;
+ hwc->config = 0;
+ hwc->event_base = 0;
+
+ /*
* Check whether we need to exclude the counter from certain modes.
- * The ARM performance counters are on all of the time so if someone
- * has asked us for some excludes then we have to fail.
*/
- if (event->attr.exclude_kernel || event->attr.exclude_user ||
- event->attr.exclude_hv || event->attr.exclude_idle) {
+ if ((!armpmu->set_event_filter ||
+ armpmu->set_event_filter(hwc, &event->attr)) &&
+ event_requires_mode_exclusion(&event->attr)) {
pr_debug("ARM performance counters do not support "
"mode exclusion\n");
return -EPERM;
}
/*
- * We don't assign an index until we actually place the event onto
- * hardware. Use -1 to signify that we haven't decided where to put it
- * yet. For SMP systems, each core has it's own PMU so we can't do any
- * clever allocation or constraints checking at this point.
+ * Store the event encoding into the config_base field.
*/
- hwc->idx = -1;
-
- /*
- * Store the event encoding into the config_base field. config and
- * event_base are unused as the only 2 things we need to know are
- * the event mapping and the counter to use. The counter to use is
- * also the indx and the config_base is the event type.
- */
- hwc->config_base = (unsigned long)mapping;
- hwc->config = 0;
- hwc->event_base = 0;
+ hwc->config_base |= (unsigned long)mapping;
if (!hwc->sample_period) {
hwc->sample_period = armpmu->max_period;
@@ -542,32 +527,23 @@ __hw_perf_event_init(struct perf_event *event)
static int armpmu_event_init(struct perf_event *event)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
int err = 0;
+ atomic_t *active_events = &armpmu->active_events;
- switch (event->attr.type) {
- case PERF_TYPE_RAW:
- case PERF_TYPE_HARDWARE:
- case PERF_TYPE_HW_CACHE:
- break;
-
- default:
+ if (armpmu->map_event(event) == -ENOENT)
return -ENOENT;
- }
-
- if (!armpmu)
- return -ENODEV;
event->destroy = hw_perf_event_destroy;
- if (!atomic_inc_not_zero(&active_events)) {
- mutex_lock(&pmu_reserve_mutex);
- if (atomic_read(&active_events) == 0) {
- err = armpmu_reserve_hardware();
- }
+ if (!atomic_inc_not_zero(active_events)) {
+ mutex_lock(&armpmu->reserve_mutex);
+ if (atomic_read(active_events) == 0)
+ err = armpmu_reserve_hardware(armpmu);
if (!err)
- atomic_inc(&active_events);
- mutex_unlock(&pmu_reserve_mutex);
+ atomic_inc(active_events);
+ mutex_unlock(&armpmu->reserve_mutex);
}
if (err)
@@ -582,22 +558,9 @@ static int armpmu_event_init(struct perf_event *event)
static void armpmu_enable(struct pmu *pmu)
{
- /* Enable all of the perf events on hardware. */
- int idx, enabled = 0;
- struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-
- if (!armpmu)
- return;
-
- for (idx = 0; idx <= armpmu->num_events; ++idx) {
- struct perf_event *event = cpuc->events[idx];
-
- if (!event)
- continue;
-
- armpmu->enable(&event->hw, idx);
- enabled = 1;
- }
+ struct arm_pmu *armpmu = to_arm_pmu(pmu);
+ struct pmu_hw_events *hw_events = armpmu->get_hw_events();
+ int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
if (enabled)
armpmu->start();
@@ -605,20 +568,32 @@ static void armpmu_enable(struct pmu *pmu)
static void armpmu_disable(struct pmu *pmu)
{
- if (armpmu)
- armpmu->stop();
+ struct arm_pmu *armpmu = to_arm_pmu(pmu);
+ armpmu->stop();
}
-static struct pmu pmu = {
- .pmu_enable = armpmu_enable,
- .pmu_disable = armpmu_disable,
- .event_init = armpmu_event_init,
- .add = armpmu_add,
- .del = armpmu_del,
- .start = armpmu_start,
- .stop = armpmu_stop,
- .read = armpmu_read,
-};
+static void __init armpmu_init(struct arm_pmu *armpmu)
+{
+ atomic_set(&armpmu->active_events, 0);
+ mutex_init(&armpmu->reserve_mutex);
+
+ armpmu->pmu = (struct pmu) {
+ .pmu_enable = armpmu_enable,
+ .pmu_disable = armpmu_disable,
+ .event_init = armpmu_event_init,
+ .add = armpmu_add,
+ .del = armpmu_del,
+ .start = armpmu_start,
+ .stop = armpmu_stop,
+ .read = armpmu_read,
+ };
+}
+
+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+{
+ armpmu_init(armpmu);
+ return perf_pmu_register(&armpmu->pmu, name, type);
+}
/* Include the PMU-specific implementations. */
#include "perf_event_xscale.c"
@@ -630,14 +605,72 @@ static struct pmu pmu = {
* This requires SMP to be available, so exists as a separate initcall.
*/
static int __init
-armpmu_reset(void)
+cpu_pmu_reset(void)
+{
+ if (cpu_pmu && cpu_pmu->reset)
+ return on_each_cpu(cpu_pmu->reset, NULL, 1);
+ return 0;
+}
+arch_initcall(cpu_pmu_reset);
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id armpmu_of_device_ids[] = {
+ {.compatible = "arm,cortex-a9-pmu"},
+ {.compatible = "arm,cortex-a8-pmu"},
+ {.compatible = "arm,arm1136-pmu"},
+ {.compatible = "arm,arm1176-pmu"},
+ {},
+};
+
+static struct platform_device_id armpmu_plat_device_ids[] = {
+ {.name = "arm-pmu"},
+ {},
+};
+
+static int __devinit armpmu_device_probe(struct platform_device *pdev)
{
- if (armpmu && armpmu->reset)
- return on_each_cpu(armpmu->reset, NULL, 1);
+ cpu_pmu->plat_device = pdev;
return 0;
}
-arch_initcall(armpmu_reset);
+static struct platform_driver armpmu_driver = {
+ .driver = {
+ .name = "arm-pmu",
+ .of_match_table = armpmu_of_device_ids,
+ },
+ .probe = armpmu_device_probe,
+ .id_table = armpmu_plat_device_ids,
+};
+
+static int __init register_pmu_driver(void)
+{
+ return platform_driver_register(&armpmu_driver);
+}
+device_initcall(register_pmu_driver);
+
+static struct pmu_hw_events *armpmu_get_cpu_events(void)
+{
+ return &__get_cpu_var(cpu_hw_events);
+}
+
+static void __init cpu_pmu_init(struct arm_pmu *armpmu)
+{
+ int cpu;
+ for_each_possible_cpu(cpu) {
+ struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
+ events->events = per_cpu(hw_events, cpu);
+ events->used_mask = per_cpu(used_mask, cpu);
+ raw_spin_lock_init(&events->pmu_lock);
+ }
+ armpmu->get_hw_events = armpmu_get_cpu_events;
+ armpmu->type = ARM_PMU_DEVICE_CPU;
+}
+
+/*
+ * CPU PMU identification and registration.
+ */
static int __init
init_hw_perf_events(void)
{
@@ -651,22 +684,22 @@ init_hw_perf_events(void)
case 0xB360: /* ARM1136 */
case 0xB560: /* ARM1156 */
case 0xB760: /* ARM1176 */
- armpmu = armv6pmu_init();
+ cpu_pmu = armv6pmu_init();
break;
case 0xB020: /* ARM11mpcore */
- armpmu = armv6mpcore_pmu_init();
+ cpu_pmu = armv6mpcore_pmu_init();
break;
case 0xC080: /* Cortex-A8 */
- armpmu = armv7_a8_pmu_init();
+ cpu_pmu = armv7_a8_pmu_init();
break;
case 0xC090: /* Cortex-A9 */
- armpmu = armv7_a9_pmu_init();
+ cpu_pmu = armv7_a9_pmu_init();
break;
case 0xC050: /* Cortex-A5 */
- armpmu = armv7_a5_pmu_init();
+ cpu_pmu = armv7_a5_pmu_init();
break;
case 0xC0F0: /* Cortex-A15 */
- armpmu = armv7_a15_pmu_init();
+ cpu_pmu = armv7_a15_pmu_init();
break;
}
/* Intel CPUs [xscale]. */
@@ -674,23 +707,23 @@ init_hw_perf_events(void)
part_number = (cpuid >> 13) & 0x7;
switch (part_number) {
case 1:
- armpmu = xscale1pmu_init();
+ cpu_pmu = xscale1pmu_init();
break;
case 2:
- armpmu = xscale2pmu_init();
+ cpu_pmu = xscale2pmu_init();
break;
}
}
- if (armpmu) {
+ if (cpu_pmu) {
pr_info("enabled with %s PMU driver, %d counters available\n",
- armpmu->name, armpmu->num_events);
+ cpu_pmu->name, cpu_pmu->num_events);
+ cpu_pmu_init(cpu_pmu);
+ armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
} else {
pr_info("no hardware support available\n");
}
- perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
-
return 0;
}
early_initcall(init_hw_perf_events);
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index dd7f3b9f4cb3..e63d8115c01b 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -54,7 +54,7 @@ enum armv6_perf_types {
};
enum armv6_counters {
- ARMV6_CYCLE_COUNTER = 1,
+ ARMV6_CYCLE_COUNTER = 0,
ARMV6_COUNTER0,
ARMV6_COUNTER1,
};
@@ -433,6 +433,7 @@ armv6pmu_enable_event(struct hw_perf_event *hwc,
int idx)
{
unsigned long val, mask, evt, flags;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
if (ARMV6_CYCLE_COUNTER == idx) {
mask = 0;
@@ -454,12 +455,29 @@ armv6pmu_enable_event(struct hw_perf_event *hwc,
* Mask out the current event and set the counter to count the event
* that we're interested in.
*/
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = armv6_pmcr_read();
val &= ~mask;
val |= evt;
armv6_pmcr_write(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static int counter_is_active(unsigned long pmcr, int idx)
+{
+ unsigned long mask = 0;
+ if (idx == ARMV6_CYCLE_COUNTER)
+ mask = ARMV6_PMCR_CCOUNT_IEN;
+ else if (idx == ARMV6_COUNTER0)
+ mask = ARMV6_PMCR_COUNT0_IEN;
+ else if (idx == ARMV6_COUNTER1)
+ mask = ARMV6_PMCR_COUNT1_IEN;
+
+ if (mask)
+ return pmcr & mask;
+
+ WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+ return 0;
}
static irqreturn_t
@@ -468,7 +486,7 @@ armv6pmu_handle_irq(int irq_num,
{
unsigned long pmcr = armv6_pmcr_read();
struct perf_sample_data data;
- struct cpu_hw_events *cpuc;
+ struct pmu_hw_events *cpuc;
struct pt_regs *regs;
int idx;
@@ -487,11 +505,11 @@ armv6pmu_handle_irq(int irq_num,
perf_sample_data_init(&data, 0);
cpuc = &__get_cpu_var(cpu_hw_events);
- for (idx = 0; idx <= armpmu->num_events; ++idx) {
+ for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;
- if (!test_bit(idx, cpuc->active_mask))
+ if (!counter_is_active(pmcr, idx))
continue;
/*
@@ -508,7 +526,7 @@ armv6pmu_handle_irq(int irq_num,
continue;
if (perf_event_overflow(event, &data, regs))
- armpmu->disable(hwc, idx);
+ cpu_pmu->disable(hwc, idx);
}
/*
@@ -527,28 +545,30 @@ static void
armv6pmu_start(void)
{
unsigned long flags, val;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = armv6_pmcr_read();
val |= ARMV6_PMCR_ENABLE;
armv6_pmcr_write(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static void
armv6pmu_stop(void)
{
unsigned long flags, val;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = armv6_pmcr_read();
val &= ~ARMV6_PMCR_ENABLE;
armv6_pmcr_write(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static int
-armv6pmu_get_event_idx(struct cpu_hw_events *cpuc,
+armv6pmu_get_event_idx(struct pmu_hw_events *cpuc,
struct hw_perf_event *event)
{
/* Always place a cycle counter into the cycle counter. */
@@ -578,6 +598,7 @@ armv6pmu_disable_event(struct hw_perf_event *hwc,
int idx)
{
unsigned long val, mask, evt, flags;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
if (ARMV6_CYCLE_COUNTER == idx) {
mask = ARMV6_PMCR_CCOUNT_IEN;
@@ -598,12 +619,12 @@ armv6pmu_disable_event(struct hw_perf_event *hwc,
* of ETM bus signal assertion cycles. The external reporting should
* be disabled and so this should never increment.
*/
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = armv6_pmcr_read();
val &= ~mask;
val |= evt;
armv6_pmcr_write(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static void
@@ -611,6 +632,7 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
int idx)
{
unsigned long val, mask, flags, evt = 0;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
if (ARMV6_CYCLE_COUNTER == idx) {
mask = ARMV6_PMCR_CCOUNT_IEN;
@@ -627,15 +649,21 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
* Unlike UP ARMv6, we don't have a way of stopping the counters. We
* simply disable the interrupt reporting.
*/
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = armv6_pmcr_read();
val &= ~mask;
val |= evt;
armv6_pmcr_write(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static int armv6_map_event(struct perf_event *event)
+{
+ return map_cpu_event(event, &armv6_perf_map,
+ &armv6_perf_cache_map, 0xFF);
}
-static const struct arm_pmu armv6pmu = {
+static struct arm_pmu armv6pmu = {
.id = ARM_PERF_PMU_ID_V6,
.name = "v6",
.handle_irq = armv6pmu_handle_irq,
@@ -646,14 +674,12 @@ static const struct arm_pmu armv6pmu = {
.get_event_idx = armv6pmu_get_event_idx,
.start = armv6pmu_start,
.stop = armv6pmu_stop,
- .cache_map = &armv6_perf_cache_map,
- .event_map = &armv6_perf_map,
- .raw_event_mask = 0xFF,
+ .map_event = armv6_map_event,
.num_events = 3,
.max_period = (1LLU << 32) - 1,
};
-static const struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__init armv6pmu_init(void)
{
return &armv6pmu;
}
@@ -665,7 +691,14 @@ static const struct arm_pmu *__init armv6pmu_init(void)
* disable the interrupt reporting and update the event. When unthrottling we
* reset the period and enable the interrupt reporting.
*/
-static const struct arm_pmu armv6mpcore_pmu = {
+
+static int armv6mpcore_map_event(struct perf_event *event)
+{
+ return map_cpu_event(event, &armv6mpcore_perf_map,
+ &armv6mpcore_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu armv6mpcore_pmu = {
.id = ARM_PERF_PMU_ID_V6MP,
.name = "v6mpcore",
.handle_irq = armv6pmu_handle_irq,
@@ -676,24 +709,22 @@ static const struct arm_pmu armv6mpcore_pmu = {
.get_event_idx = armv6pmu_get_event_idx,
.start = armv6pmu_start,
.stop = armv6pmu_stop,
- .cache_map = &armv6mpcore_perf_cache_map,
- .event_map = &armv6mpcore_perf_map,
- .raw_event_mask = 0xFF,
+ .map_event = armv6mpcore_map_event,
.num_events = 3,
.max_period = (1LLU << 32) - 1,
};
-static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__init armv6mpcore_pmu_init(void)
{
return &armv6mpcore_pmu;
}
#else
-static const struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__init armv6pmu_init(void)
{
return NULL;
}
-static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__init armv6mpcore_pmu_init(void)
{
return NULL;
}
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 6be3e2e4d838..1ef6d0034b85 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -17,6 +17,9 @@
*/
#ifdef CONFIG_CPU_V7
+
+static struct arm_pmu armv7pmu;
+
/*
* Common ARMv7 event types
*
@@ -676,23 +679,24 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
};
/*
- * Perf Events counters
+ * Perf Events' indices
*/
-enum armv7_counters {
- ARMV7_CYCLE_COUNTER = 1, /* Cycle counter */
- ARMV7_COUNTER0 = 2, /* First event counter */
-};
+#define ARMV7_IDX_CYCLE_COUNTER 0
+#define ARMV7_IDX_COUNTER0 1
+#define ARMV7_IDX_COUNTER_LAST (ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1)
+
+#define ARMV7_MAX_COUNTERS 32
+#define ARMV7_COUNTER_MASK (ARMV7_MAX_COUNTERS - 1)
/*
- * The cycle counter is ARMV7_CYCLE_COUNTER.
- * The first event counter is ARMV7_COUNTER0.
- * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1).
+ * ARMv7 low level PMNC access
*/
-#define ARMV7_COUNTER_LAST (ARMV7_COUNTER0 + armpmu->num_events - 1)
/*
- * ARMv7 low level PMNC access
+ * Perf Event to low level counters mapping
*/
+#define ARMV7_IDX_TO_COUNTER(x) \
+ (((x) - ARMV7_IDX_COUNTER0) & ARMV7_COUNTER_MASK)
/*
* Per-CPU PMNC: config reg
@@ -708,103 +712,76 @@ enum armv7_counters {
#define ARMV7_PMNC_MASK 0x3f /* Mask for writable bits */
/*
- * Available counters
- */
-#define ARMV7_CNT0 0 /* First event counter */
-#define ARMV7_CCNT 31 /* Cycle counter */
-
-/* Perf Event to low level counters mapping */
-#define ARMV7_EVENT_CNT_TO_CNTx (ARMV7_COUNTER0 - ARMV7_CNT0)
-
-/*
- * CNTENS: counters enable reg
- */
-#define ARMV7_CNTENS_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_CNTENS_C (1 << ARMV7_CCNT)
-
-/*
- * CNTENC: counters disable reg
- */
-#define ARMV7_CNTENC_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_CNTENC_C (1 << ARMV7_CCNT)
-
-/*
- * INTENS: counters overflow interrupt enable reg
- */
-#define ARMV7_INTENS_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_INTENS_C (1 << ARMV7_CCNT)
-
-/*
- * INTENC: counters overflow interrupt disable reg
- */
-#define ARMV7_INTENC_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_INTENC_C (1 << ARMV7_CCNT)
-
-/*
- * EVTSEL: Event selection reg
+ * FLAG: counters overflow flag status reg
*/
-#define ARMV7_EVTSEL_MASK 0xff /* Mask for writable bits */
+#define ARMV7_FLAG_MASK 0xffffffff /* Mask for writable bits */
+#define ARMV7_OVERFLOWED_MASK ARMV7_FLAG_MASK
/*
- * SELECT: Counter selection reg
+ * PMXEVTYPER: Event selection reg
*/
-#define ARMV7_SELECT_MASK 0x1f /* Mask for writable bits */
+#define ARMV7_EVTYPE_MASK 0xc00000ff /* Mask for writable bits */
+#define ARMV7_EVTYPE_EVENT 0xff /* Mask for EVENT bits */
/*
- * FLAG: counters overflow flag status reg
+ * Event filters for PMUv2
*/
-#define ARMV7_FLAG_P(idx) (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_FLAG_C (1 << ARMV7_CCNT)
-#define ARMV7_FLAG_MASK 0xffffffff /* Mask for writable bits */
-#define ARMV7_OVERFLOWED_MASK ARMV7_FLAG_MASK
+#define ARMV7_EXCLUDE_PL1 (1 << 31)
+#define ARMV7_EXCLUDE_USER (1 << 30)
+#define ARMV7_INCLUDE_HYP (1 << 27)
-static inline unsigned long armv7_pmnc_read(void)
+static inline u32 armv7_pmnc_read(void)
{
u32 val;
asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
return val;
}
-static inline void armv7_pmnc_write(unsigned long val)
+static inline void armv7_pmnc_write(u32 val)
{
val &= ARMV7_PMNC_MASK;
isb();
asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
}
-static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
+static inline int armv7_pmnc_has_overflowed(u32 pmnc)
{
return pmnc & ARMV7_OVERFLOWED_MASK;
}
-static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
- enum armv7_counters counter)
+static inline int armv7_pmnc_counter_valid(int idx)
+{
+ return idx >= ARMV7_IDX_CYCLE_COUNTER && idx <= ARMV7_IDX_COUNTER_LAST;
+}
+
+static inline int armv7_pmnc_counter_has_overflowed(u32 pmnc, int idx)
{
int ret = 0;
+ u32 counter;
- if (counter == ARMV7_CYCLE_COUNTER)
- ret = pmnc & ARMV7_FLAG_C;
- else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST))
- ret = pmnc & ARMV7_FLAG_P(counter);
- else
+ if (!armv7_pmnc_counter_valid(idx)) {
pr_err("CPU%u checking wrong counter %d overflow status\n",
- smp_processor_id(), counter);
+ smp_processor_id(), idx);
+ } else {
+ counter = ARMV7_IDX_TO_COUNTER(idx);
+ ret = pmnc & BIT(counter);
+ }
return ret;
}
-static inline int armv7_pmnc_select_counter(unsigned int idx)
+static inline int armv7_pmnc_select_counter(int idx)
{
- u32 val;
+ u32 counter;
- if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
- pr_err("CPU%u selecting wrong PMNC counter"
- " %d\n", smp_processor_id(), idx);
- return -1;
+ if (!armv7_pmnc_counter_valid(idx)) {
+ pr_err("CPU%u selecting wrong PMNC counter %d\n",
+ smp_processor_id(), idx);
+ return -EINVAL;
}
- val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
- asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
+ counter = ARMV7_IDX_TO_COUNTER(idx);
+ asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (counter));
isb();
return idx;
@@ -812,124 +789,95 @@ static inline int armv7_pmnc_select_counter(unsigned int idx)
static inline u32 armv7pmu_read_counter(int idx)
{
- unsigned long value = 0;
+ u32 value = 0;
- if (idx == ARMV7_CYCLE_COUNTER)
- asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
- else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
- if (armv7_pmnc_select_counter(idx) == idx)
- asm volatile("mrc p15, 0, %0, c9, c13, 2"
- : "=r" (value));
- } else
+ if (!armv7_pmnc_counter_valid(idx))
pr_err("CPU%u reading wrong counter %d\n",
smp_processor_id(), idx);
+ else if (idx == ARMV7_IDX_CYCLE_COUNTER)
+ asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
+ else if (armv7_pmnc_select_counter(idx) == idx)
+ asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (value));
return value;
}
static inline void armv7pmu_write_counter(int idx, u32 value)
{
- if (idx == ARMV7_CYCLE_COUNTER)
- asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
- else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
- if (armv7_pmnc_select_counter(idx) == idx)
- asm volatile("mcr p15, 0, %0, c9, c13, 2"
- : : "r" (value));
- } else
+ if (!armv7_pmnc_counter_valid(idx))
pr_err("CPU%u writing wrong counter %d\n",
smp_processor_id(), idx);
+ else if (idx == ARMV7_IDX_CYCLE_COUNTER)
+ asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
+ else if (armv7_pmnc_select_counter(idx) == idx)
+ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value));
}
-static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
+static inline void armv7_pmnc_write_evtsel(int idx, u32 val)
{
if (armv7_pmnc_select_counter(idx) == idx) {
- val &= ARMV7_EVTSEL_MASK;
+ val &= ARMV7_EVTYPE_MASK;
asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
}
}
-static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
+static inline int armv7_pmnc_enable_counter(int idx)
{
- u32 val;
+ u32 counter;
- if ((idx != ARMV7_CYCLE_COUNTER) &&
- ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
- pr_err("CPU%u enabling wrong PMNC counter"
- " %d\n", smp_processor_id(), idx);
- return -1;
+ if (!armv7_pmnc_counter_valid(idx)) {
+ pr_err("CPU%u enabling wrong PMNC counter %d\n",
+ smp_processor_id(), idx);
+ return -EINVAL;
}
- if (idx == ARMV7_CYCLE_COUNTER)
- val = ARMV7_CNTENS_C;
- else
- val = ARMV7_CNTENS_P(idx);
-
- asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
-
+ counter = ARMV7_IDX_TO_COUNTER(idx);
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (BIT(counter)));
return idx;
}
-static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
+static inline int armv7_pmnc_disable_counter(int idx)
{
- u32 val;
-
+ u32 counter;
- if ((idx != ARMV7_CYCLE_COUNTER) &&
- ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
- pr_err("CPU%u disabling wrong PMNC counter"
- " %d\n", smp_processor_id(), idx);
- return -1;
+ if (!armv7_pmnc_counter_valid(idx)) {
+ pr_err("CPU%u disabling wrong PMNC counter %d\n",
+ smp_processor_id(), idx);
+ return -EINVAL;
}
- if (idx == ARMV7_CYCLE_COUNTER)
- val = ARMV7_CNTENC_C;
- else
- val = ARMV7_CNTENC_P(idx);
-
- asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
-
+ counter = ARMV7_IDX_TO_COUNTER(idx);
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (BIT(counter)));
return idx;
}
-static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
+static inline int armv7_pmnc_enable_intens(int idx)
{
- u32 val;
+ u32 counter;
- if ((idx != ARMV7_CYCLE_COUNTER) &&
- ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
- pr_err("CPU%u enabling wrong PMNC counter"
- " interrupt enable %d\n", smp_processor_id(), idx);
- return -1;
+ if (!armv7_pmnc_counter_valid(idx)) {
+ pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n",
+ smp_processor_id(), idx);
+ return -EINVAL;
}
- if (idx == ARMV7_CYCLE_COUNTER)
- val = ARMV7_INTENS_C;
- else
- val = ARMV7_INTENS_P(idx);
-
- asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
-
+ counter = ARMV7_IDX_TO_COUNTER(idx);
+ asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (BIT(counter)));
return idx;
}
-static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
+static inline int armv7_pmnc_disable_intens(int idx)
{
- u32 val;
+ u32 counter;
- if ((idx != ARMV7_CYCLE_COUNTER) &&
- ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
- pr_err("CPU%u disabling wrong PMNC counter"
- " interrupt enable %d\n", smp_processor_id(), idx);
- return -1;
+ if (!armv7_pmnc_counter_valid(idx)) {
+ pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n",
+ smp_processor_id(), idx);
+ return -EINVAL;
}
- if (idx == ARMV7_CYCLE_COUNTER)
- val = ARMV7_INTENC_C;
- else
- val = ARMV7_INTENC_P(idx);
-
- asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
-
+ counter = ARMV7_IDX_TO_COUNTER(idx);
+ asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter)));
return idx;
}
@@ -973,14 +921,14 @@ static void armv7_pmnc_dump_regs(void)
asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
printk(KERN_INFO "CCNT =0x%08x\n", val);
- for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) {
+ for (cnt = ARMV7_IDX_COUNTER0; cnt <= ARMV7_IDX_COUNTER_LAST; cnt++) {
armv7_pmnc_select_counter(cnt);
asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
printk(KERN_INFO "CNT[%d] count =0x%08x\n",
- cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+ ARMV7_IDX_TO_COUNTER(cnt), val);
asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
- cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+ ARMV7_IDX_TO_COUNTER(cnt), val);
}
}
#endif
@@ -988,12 +936,13 @@ static void armv7_pmnc_dump_regs(void)
static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
{
unsigned long flags;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
/*
* Enable counter and interrupt, and set the counter to count
* the event that we're interested in.
*/
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
/*
* Disable counter
@@ -1002,9 +951,10 @@ static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
/*
* Set event (if destined for PMNx counters)
- * We don't need to set the event if it's a cycle count
+ * We only need to set the event for the cycle counter if we
+ * have the ability to perform event filtering.
*/
- if (idx != ARMV7_CYCLE_COUNTER)
+ if (armv7pmu.set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER)
armv7_pmnc_write_evtsel(idx, hwc->config_base);
/*
@@ -1017,17 +967,18 @@ static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
*/
armv7_pmnc_enable_counter(idx);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
{
unsigned long flags;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
/*
* Disable counter and interrupt
*/
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
/*
* Disable counter
@@ -1039,14 +990,14 @@ static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
*/
armv7_pmnc_disable_intens(idx);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
{
- unsigned long pmnc;
+ u32 pmnc;
struct perf_sample_data data;
- struct cpu_hw_events *cpuc;
+ struct pmu_hw_events *cpuc;
struct pt_regs *regs;
int idx;
@@ -1069,13 +1020,10 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
perf_sample_data_init(&data, 0);
cpuc = &__get_cpu_var(cpu_hw_events);
- for (idx = 0; idx <= armpmu->num_events; ++idx) {
+ for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;
- if (!test_bit(idx, cpuc->active_mask))
- continue;
-
/*
* We have a single interrupt for all counters. Check that
* each counter has overflowed before we process it.
@@ -1090,7 +1038,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
continue;
if (perf_event_overflow(event, &data, regs))
- armpmu->disable(hwc, idx);
+ cpu_pmu->disable(hwc, idx);
}
/*
@@ -1108,61 +1056,114 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
static void armv7pmu_start(void)
{
unsigned long flags;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
/* Enable all counters */
armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static void armv7pmu_stop(void)
{
unsigned long flags;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
/* Disable all counters */
armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
-static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
+static int armv7pmu_get_event_idx(struct pmu_hw_events *cpuc,
struct hw_perf_event *event)
{
int idx;
+ unsigned long evtype = event->config_base & ARMV7_EVTYPE_EVENT;
/* Always place a cycle counter into the cycle counter. */
- if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) {
- if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask))
+ if (evtype == ARMV7_PERFCTR_CPU_CYCLES) {
+ if (test_and_set_bit(ARMV7_IDX_CYCLE_COUNTER, cpuc->used_mask))
return -EAGAIN;
- return ARMV7_CYCLE_COUNTER;
- } else {
- /*
- * For anything other than a cycle counter, try and use
- * the events counters
- */
- for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) {
- if (!test_and_set_bit(idx, cpuc->used_mask))
- return idx;
- }
+ return ARMV7_IDX_CYCLE_COUNTER;
+ }
- /* The counters are all in use. */
- return -EAGAIN;
+ /*
+ * For anything other than a cycle counter, try and use
+ * the events counters
+ */
+ for (idx = ARMV7_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) {
+ if (!test_and_set_bit(idx, cpuc->used_mask))
+ return idx;
}
+
+ /* The counters are all in use. */
+ return -EAGAIN;
+}
+
+/*
+ * Add an event filter to a given event. This will only work for PMUv2 PMUs.
+ */
+static int armv7pmu_set_event_filter(struct hw_perf_event *event,
+ struct perf_event_attr *attr)
+{
+ unsigned long config_base = 0;
+
+ if (attr->exclude_idle)
+ return -EPERM;
+ if (attr->exclude_user)
+ config_base |= ARMV7_EXCLUDE_USER;
+ if (attr->exclude_kernel)
+ config_base |= ARMV7_EXCLUDE_PL1;
+ if (!attr->exclude_hv)
+ config_base |= ARMV7_INCLUDE_HYP;
+
+ /*
+ * Install the filter into config_base as this is used to
+ * construct the event type.
+ */
+ event->config_base = config_base;
+
+ return 0;
}
static void armv7pmu_reset(void *info)
{
- u32 idx, nb_cnt = armpmu->num_events;
+ u32 idx, nb_cnt = cpu_pmu->num_events;
/* The counter and interrupt enable registers are unknown at reset. */
- for (idx = 1; idx < nb_cnt; ++idx)
+ for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx)
armv7pmu_disable_event(NULL, idx);
/* Initialize & Reset PMNC: C and P bits */
armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
}
+static int armv7_a8_map_event(struct perf_event *event)
+{
+ return map_cpu_event(event, &armv7_a8_perf_map,
+ &armv7_a8_perf_cache_map, 0xFF);
+}
+
+static int armv7_a9_map_event(struct perf_event *event)
+{
+ return map_cpu_event(event, &armv7_a9_perf_map,
+ &armv7_a9_perf_cache_map, 0xFF);
+}
+
+static int armv7_a5_map_event(struct perf_event *event)
+{
+ return map_cpu_event(event, &armv7_a5_perf_map,
+ &armv7_a5_perf_cache_map, 0xFF);
+}
+
+static int armv7_a15_map_event(struct perf_event *event)
+{
+ return map_cpu_event(event, &armv7_a15_perf_map,
+ &armv7_a15_perf_cache_map, 0xFF);
+}
+
static struct arm_pmu armv7pmu = {
.handle_irq = armv7pmu_handle_irq,
.enable = armv7pmu_enable_event,
@@ -1173,7 +1174,6 @@ static struct arm_pmu armv7pmu = {
.start = armv7pmu_start,
.stop = armv7pmu_stop,
.reset = armv7pmu_reset,
- .raw_event_mask = 0xFF,
.max_period = (1LLU << 32) - 1,
};
@@ -1188,62 +1188,59 @@ static u32 __init armv7_read_num_pmnc_events(void)
return nb_cnt + 1;
}
-static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__init armv7_a8_pmu_init(void)
{
armv7pmu.id = ARM_PERF_PMU_ID_CA8;
armv7pmu.name = "ARMv7 Cortex-A8";
- armv7pmu.cache_map = &armv7_a8_perf_cache_map;
- armv7pmu.event_map = &armv7_a8_perf_map;
+ armv7pmu.map_event = armv7_a8_map_event;
armv7pmu.num_events = armv7_read_num_pmnc_events();
return &armv7pmu;
}
-static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__init armv7_a9_pmu_init(void)
{
armv7pmu.id = ARM_PERF_PMU_ID_CA9;
armv7pmu.name = "ARMv7 Cortex-A9";
- armv7pmu.cache_map = &armv7_a9_perf_cache_map;
- armv7pmu.event_map = &armv7_a9_perf_map;
+ armv7pmu.map_event = armv7_a9_map_event;
armv7pmu.num_events = armv7_read_num_pmnc_events();
return &armv7pmu;
}
-static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__init armv7_a5_pmu_init(void)
{
armv7pmu.id = ARM_PERF_PMU_ID_CA5;
armv7pmu.name = "ARMv7 Cortex-A5";
- armv7pmu.cache_map = &armv7_a5_perf_cache_map;
- armv7pmu.event_map = &armv7_a5_perf_map;
+ armv7pmu.map_event = armv7_a5_map_event;
armv7pmu.num_events = armv7_read_num_pmnc_events();
return &armv7pmu;
}
-static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__init armv7_a15_pmu_init(void)
{
armv7pmu.id = ARM_PERF_PMU_ID_CA15;
armv7pmu.name = "ARMv7 Cortex-A15";
- armv7pmu.cache_map = &armv7_a15_perf_cache_map;
- armv7pmu.event_map = &armv7_a15_perf_map;
+ armv7pmu.map_event = armv7_a15_map_event;
armv7pmu.num_events = armv7_read_num_pmnc_events();
+ armv7pmu.set_event_filter = armv7pmu_set_event_filter;
return &armv7pmu;
}
#else
-static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__init armv7_a8_pmu_init(void)
{
return NULL;
}
-static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__init armv7_a9_pmu_init(void)
{
return NULL;
}
-static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__init armv7_a5_pmu_init(void)
{
return NULL;
}
-static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__init armv7_a15_pmu_init(void)
{
return NULL;
}
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index 3c4397491d08..e0cca10a8411 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -40,7 +40,7 @@ enum xscale_perf_types {
};
enum xscale_counters {
- XSCALE_CYCLE_COUNTER = 1,
+ XSCALE_CYCLE_COUNTER = 0,
XSCALE_COUNTER0,
XSCALE_COUNTER1,
XSCALE_COUNTER2,
@@ -222,7 +222,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
{
unsigned long pmnc;
struct perf_sample_data data;
- struct cpu_hw_events *cpuc;
+ struct pmu_hw_events *cpuc;
struct pt_regs *regs;
int idx;
@@ -249,13 +249,10 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
perf_sample_data_init(&data, 0);
cpuc = &__get_cpu_var(cpu_hw_events);
- for (idx = 0; idx <= armpmu->num_events; ++idx) {
+ for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;
- if (!test_bit(idx, cpuc->active_mask))
- continue;
-
if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
continue;
@@ -266,7 +263,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
continue;
if (perf_event_overflow(event, &data, regs))
- armpmu->disable(hwc, idx);
+ cpu_pmu->disable(hwc, idx);
}
irq_work_run();
@@ -284,6 +281,7 @@ static void
xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
{
unsigned long val, mask, evt, flags;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
switch (idx) {
case XSCALE_CYCLE_COUNTER:
@@ -305,18 +303,19 @@ xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
return;
}
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = xscale1pmu_read_pmnc();
val &= ~mask;
val |= evt;
xscale1pmu_write_pmnc(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static void
xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
{
unsigned long val, mask, evt, flags;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
switch (idx) {
case XSCALE_CYCLE_COUNTER:
@@ -336,16 +335,16 @@ xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
return;
}
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = xscale1pmu_read_pmnc();
val &= ~mask;
val |= evt;
xscale1pmu_write_pmnc(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static int
-xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc,
+xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
struct hw_perf_event *event)
{
if (XSCALE_PERFCTR_CCNT == event->config_base) {
@@ -368,24 +367,26 @@ static void
xscale1pmu_start(void)
{
unsigned long flags, val;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = xscale1pmu_read_pmnc();
val |= XSCALE_PMU_ENABLE;
xscale1pmu_write_pmnc(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static void
xscale1pmu_stop(void)
{
unsigned long flags, val;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = xscale1pmu_read_pmnc();
val &= ~XSCALE_PMU_ENABLE;
xscale1pmu_write_pmnc(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static inline u32
@@ -424,7 +425,13 @@ xscale1pmu_write_counter(int counter, u32 val)
}
}
-static const struct arm_pmu xscale1pmu = {
+static int xscale_map_event(struct perf_event *event)
+{
+ return map_cpu_event(event, &xscale_perf_map,
+ &xscale_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu xscale1pmu = {
.id = ARM_PERF_PMU_ID_XSCALE1,
.name = "xscale1",
.handle_irq = xscale1pmu_handle_irq,
@@ -435,14 +442,12 @@ static const struct arm_pmu xscale1pmu = {
.get_event_idx = xscale1pmu_get_event_idx,
.start = xscale1pmu_start,
.stop = xscale1pmu_stop,
- .cache_map = &xscale_perf_cache_map,
- .event_map = &xscale_perf_map,
- .raw_event_mask = 0xFF,
+ .map_event = xscale_map_event,
.num_events = 3,
.max_period = (1LLU << 32) - 1,
};
-static const struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__init xscale1pmu_init(void)
{
return &xscale1pmu;
}
@@ -560,7 +565,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
{
unsigned long pmnc, of_flags;
struct perf_sample_data data;
- struct cpu_hw_events *cpuc;
+ struct pmu_hw_events *cpuc;
struct pt_regs *regs;
int idx;
@@ -581,13 +586,10 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
perf_sample_data_init(&data, 0);
cpuc = &__get_cpu_var(cpu_hw_events);
- for (idx = 0; idx <= armpmu->num_events; ++idx) {
+ for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;
- if (!test_bit(idx, cpuc->active_mask))
- continue;
-
if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx))
continue;
@@ -598,7 +600,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
continue;
if (perf_event_overflow(event, &data, regs))
- armpmu->disable(hwc, idx);
+ cpu_pmu->disable(hwc, idx);
}
irq_work_run();
@@ -616,6 +618,7 @@ static void
xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
{
unsigned long flags, ien, evtsel;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
ien = xscale2pmu_read_int_enable();
evtsel = xscale2pmu_read_event_select();
@@ -649,16 +652,17 @@ xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
return;
}
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
xscale2pmu_write_event_select(evtsel);
xscale2pmu_write_int_enable(ien);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static void
xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
{
unsigned long flags, ien, evtsel;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
ien = xscale2pmu_read_int_enable();
evtsel = xscale2pmu_read_event_select();
@@ -692,14 +696,14 @@ xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
return;
}
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
xscale2pmu_write_event_select(evtsel);
xscale2pmu_write_int_enable(ien);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static int
-xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc,
+xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc,
struct hw_perf_event *event)
{
int idx = xscale1pmu_get_event_idx(cpuc, event);
@@ -718,24 +722,26 @@ static void
xscale2pmu_start(void)
{
unsigned long flags, val;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
val |= XSCALE_PMU_ENABLE;
xscale2pmu_write_pmnc(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static void
xscale2pmu_stop(void)
{
unsigned long flags, val;
+ struct pmu_hw_events *events = cpu_pmu->get_hw_events();
- raw_spin_lock_irqsave(&pmu_lock, flags);
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
val = xscale2pmu_read_pmnc();
val &= ~XSCALE_PMU_ENABLE;
xscale2pmu_write_pmnc(val);
- raw_spin_unlock_irqrestore(&pmu_lock, flags);
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}
static inline u32
@@ -786,7 +792,7 @@ xscale2pmu_write_counter(int counter, u32 val)
}
}
-static const struct arm_pmu xscale2pmu = {
+static struct arm_pmu xscale2pmu = {
.id = ARM_PERF_PMU_ID_XSCALE2,
.name = "xscale2",
.handle_irq = xscale2pmu_handle_irq,
@@ -797,24 +803,22 @@ static const struct arm_pmu xscale2pmu = {
.get_event_idx = xscale2pmu_get_event_idx,
.start = xscale2pmu_start,
.stop = xscale2pmu_stop,
- .cache_map = &xscale_perf_cache_map,
- .event_map = &xscale_perf_map,
- .raw_event_mask = 0xFF,
+ .map_event = xscale_map_event,
.num_events = 5,
.max_period = (1LLU << 32) - 1,
};
-static const struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__init xscale2pmu_init(void)
{
return &xscale2pmu;
}
#else
-static const struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__init xscale1pmu_init(void)
{
return NULL;
}
-static const struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__init xscale2pmu_init(void)
{
return NULL;
}
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c
index c53474fe84df..2c3407ee8576 100644
--- a/arch/arm/kernel/pmu.c
+++ b/arch/arm/kernel/pmu.c
@@ -10,192 +10,26 @@
*
*/
-#define pr_fmt(fmt) "PMU: " fmt
-
-#include <linux/cpumask.h>
#include <linux/err.h>
-#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
#include <asm/pmu.h>
-static volatile long pmu_lock;
-
-static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES];
-
-static int __devinit pmu_register(struct platform_device *pdev,
- enum arm_pmu_type type)
-{
- if (type < 0 || type >= ARM_NUM_PMU_DEVICES) {
- pr_warning("received registration request for unknown "
- "PMU device type %d\n", type);
- return -EINVAL;
- }
-
- if (pmu_devices[type]) {
- pr_warning("rejecting duplicate registration of PMU device "
- "type %d.", type);
- return -ENOSPC;
- }
-
- pr_info("registered new PMU device of type %d\n", type);
- pmu_devices[type] = pdev;
- return 0;
-}
-
-#define OF_MATCH_PMU(_name, _type) { \
- .compatible = _name, \
- .data = (void *)_type, \
-}
-
-#define OF_MATCH_CPU(name) OF_MATCH_PMU(name, ARM_PMU_DEVICE_CPU)
-
-static struct of_device_id armpmu_of_device_ids[] = {
- OF_MATCH_CPU("arm,cortex-a9-pmu"),
- OF_MATCH_CPU("arm,cortex-a8-pmu"),
- OF_MATCH_CPU("arm,arm1136-pmu"),
- OF_MATCH_CPU("arm,arm1176-pmu"),
- {},
-};
-
-#define PLAT_MATCH_PMU(_name, _type) { \
- .name = _name, \
- .driver_data = _type, \
-}
-
-#define PLAT_MATCH_CPU(_name) PLAT_MATCH_PMU(_name, ARM_PMU_DEVICE_CPU)
-
-static struct platform_device_id armpmu_plat_device_ids[] = {
- PLAT_MATCH_CPU("arm-pmu"),
- {},
-};
-
-enum arm_pmu_type armpmu_device_type(struct platform_device *pdev)
-{
- const struct of_device_id *of_id;
- const struct platform_device_id *pdev_id;
-
- /* provided by of_device_id table */
- if (pdev->dev.of_node) {
- of_id = of_match_device(armpmu_of_device_ids, &pdev->dev);
- BUG_ON(!of_id);
- return (enum arm_pmu_type)of_id->data;
- }
-
- /* Provided by platform_device_id table */
- pdev_id = platform_get_device_id(pdev);
- BUG_ON(!pdev_id);
- return pdev_id->driver_data;
-}
-
-static int __devinit armpmu_device_probe(struct platform_device *pdev)
-{
- return pmu_register(pdev, armpmu_device_type(pdev));
-}
-
-static struct platform_driver armpmu_driver = {
- .driver = {
- .name = "arm-pmu",
- .of_match_table = armpmu_of_device_ids,
- },
- .probe = armpmu_device_probe,
- .id_table = armpmu_plat_device_ids,
-};
-
-static int __init register_pmu_driver(void)
-{
- return platform_driver_register(&armpmu_driver);
-}
-device_initcall(register_pmu_driver);
+/*
+ * PMU locking to ensure mutual exclusion between different subsystems.
+ */
+static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)];
-struct platform_device *
+int
reserve_pmu(enum arm_pmu_type type)
{
- struct platform_device *pdev;
-
- if (test_and_set_bit_lock(type, &pmu_lock)) {
- pdev = ERR_PTR(-EBUSY);
- } else if (pmu_devices[type] == NULL) {
- clear_bit_unlock(type, &pmu_lock);
- pdev = ERR_PTR(-ENODEV);
- } else {
- pdev = pmu_devices[type];
- }
-
- return pdev;
+ return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0;
}
EXPORT_SYMBOL_GPL(reserve_pmu);
-int
+void
release_pmu(enum arm_pmu_type type)
{
- if (WARN_ON(!pmu_devices[type]))
- return -EINVAL;
- clear_bit_unlock(type, &pmu_lock);
- return 0;
-}
-EXPORT_SYMBOL_GPL(release_pmu);
-
-static int
-set_irq_affinity(int irq,
- unsigned int cpu)
-{
-#ifdef CONFIG_SMP
- int err = irq_set_affinity(irq, cpumask_of(cpu));
- if (err)
- pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
- irq, cpu);
- return err;
-#else
- return -EINVAL;
-#endif
-}
-
-static int
-init_cpu_pmu(void)
-{
- int i, irqs, err = 0;
- struct platform_device *pdev = pmu_devices[ARM_PMU_DEVICE_CPU];
-
- if (!pdev)
- return -ENODEV;
-
- irqs = pdev->num_resources;
-
- /*
- * If we have a single PMU interrupt that we can't shift, assume that
- * we're running on a uniprocessor machine and continue.
- */
- if (irqs == 1 && !irq_can_set_affinity(platform_get_irq(pdev, 0)))
- return 0;
-
- for (i = 0; i < irqs; ++i) {
- err = set_irq_affinity(platform_get_irq(pdev, i), i);
- if (err)
- break;
- }
-
- return err;
-}
-
-int
-init_pmu(enum arm_pmu_type type)
-{
- int err = 0;
-
- switch (type) {
- case ARM_PMU_DEVICE_CPU:
- err = init_cpu_pmu();
- break;
- default:
- pr_warning("attempt to initialise PMU of unknown "
- "type %d\n", type);
- err = -EINVAL;
- }
-
- return err;
+ clear_bit_unlock(type, pmu_lock);
}
-EXPORT_SYMBOL_GPL(init_pmu);
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 1a347f481e5e..fd0814076ff6 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -319,7 +319,7 @@ void show_regs(struct pt_regs * regs)
printk("\n");
printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm);
__show_regs(regs);
- __backtrace();
+ dump_stack();
}
ATOMIC_NOTIFIER_HEAD(thread_notify_head);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index e514c76043b4..bda0a218f4a5 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -29,6 +29,8 @@
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/memblock.h>
+#include <linux/bug.h>
+#include <linux/compiler.h>
#include <asm/unified.h>
#include <asm/cpu.h>
@@ -42,6 +44,7 @@
#include <asm/cacheflush.h>
#include <asm/cachetype.h>
#include <asm/tlbflush.h>
+#include <asm/system.h>
#include <asm/prom.h>
#include <asm/mach/arch.h>
@@ -115,6 +118,13 @@ struct outer_cache_fns outer_cache __read_mostly;
EXPORT_SYMBOL(outer_cache);
#endif
+/*
+ * Cached cpu_architecture() result for use by assembler code.
+ * C code should use the cpu_architecture() function instead of accessing this
+ * variable directly.
+ */
+int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN;
+
struct stack {
u32 irq[3];
u32 abt[3];
@@ -210,7 +220,7 @@ static const char *proc_arch[] = {
"?(17)",
};
-int cpu_architecture(void)
+static int __get_cpu_architecture(void)
{
int cpu_arch;
@@ -243,11 +253,22 @@ int cpu_architecture(void)
return cpu_arch;
}
+int __pure cpu_architecture(void)
+{
+ BUG_ON(__cpu_architecture == CPU_ARCH_UNKNOWN);
+
+ return __cpu_architecture;
+}
+
static int cpu_has_aliasing_icache(unsigned int arch)
{
int aliasing_icache;
unsigned int id_reg, num_sets, line_size;
+ /* PIPT caches never alias. */
+ if (icache_is_pipt())
+ return 0;
+
/* arch specifies the register format */
switch (arch) {
case CPU_ARCH_ARMv7:
@@ -282,8 +303,14 @@ static void __init cacheid_init(void)
/* ARMv7 register format */
arch = CPU_ARCH_ARMv7;
cacheid = CACHEID_VIPT_NONALIASING;
- if ((cachetype & (3 << 14)) == 1 << 14)
+ switch (cachetype & (3 << 14)) {
+ case (1 << 14):
cacheid |= CACHEID_ASID_TAGGED;
+ break;
+ case (3 << 14):
+ cacheid |= CACHEID_PIPT;
+ break;
+ }
} else {
arch = CPU_ARCH_ARMv6;
if (cachetype & (1 << 23))
@@ -300,10 +327,11 @@ static void __init cacheid_init(void)
printk("CPU: %s data cache, %s instruction cache\n",
cache_is_vivt() ? "VIVT" :
cache_is_vipt_aliasing() ? "VIPT aliasing" :
- cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
+ cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
cache_is_vivt() ? "VIVT" :
icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
icache_is_vipt_aliasing() ? "VIPT aliasing" :
+ icache_is_pipt() ? "PIPT" :
cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
}
@@ -414,6 +442,7 @@ static void __init setup_processor(void)
}
cpu_name = list->cpu_name;
+ __cpu_architecture = __get_cpu_architecture();
#ifdef MULTI_CPU
processor = *list->proc;
@@ -820,25 +849,8 @@ static struct machine_desc * __init setup_machine_tags(unsigned int nr)
if (__atags_pointer)
tags = phys_to_virt(__atags_pointer);
- else if (mdesc->boot_params) {
-#ifdef CONFIG_MMU
- /*
- * We still are executing with a minimal MMU mapping created
- * with the presumption that the machine default for this
- * is located in the first MB of RAM. Anything else will
- * fault and silently hang the kernel at this point.
- */
- if (mdesc->boot_params < PHYS_OFFSET ||
- mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {
- printk(KERN_WARNING
- "Default boot params at physical 0x%08lx out of reach\n",
- mdesc->boot_params);
- } else
-#endif
- {
- tags = phys_to_virt(mdesc->boot_params);
- }
- }
+ else if (mdesc->atag_offset)
+ tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
/*
@@ -861,7 +873,7 @@ static struct machine_desc * __init setup_machine_tags(unsigned int nr)
}
if (mdesc->fixup)
- mdesc->fixup(mdesc, tags, &from, &meminfo);
+ mdesc->fixup(tags, &from, &meminfo);
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index dc902f2c6845..020e99c845e7 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -8,92 +8,61 @@
.text
/*
- * Save CPU state for a suspend
- * r1 = v:p offset
- * r2 = suspend function arg0
- * r3 = suspend function
+ * Save CPU state for a suspend. This saves the CPU general purpose
+ * registers, and allocates space on the kernel stack to save the CPU
+ * specific registers and some other data for resume.
+ * r0 = suspend function arg0
+ * r1 = suspend function
*/
ENTRY(__cpu_suspend)
stmfd sp!, {r4 - r11, lr}
#ifdef MULTI_CPU
ldr r10, =processor
- ldr r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
- ldr ip, [r10, #CPU_DO_RESUME] @ virtual resume function
+ ldr r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
#else
- ldr r5, =cpu_suspend_size
- ldr ip, =cpu_do_resume
+ ldr r4, =cpu_suspend_size
#endif
- mov r6, sp @ current virtual SP
- sub sp, sp, r5 @ allocate CPU state on stack
- mov r0, sp @ save pointer to CPU save block
- add ip, ip, r1 @ convert resume fn to phys
- stmfd sp!, {r1, r6, ip} @ save v:p, virt SP, phys resume fn
- ldr r5, =sleep_save_sp
- add r6, sp, r1 @ convert SP to phys
- stmfd sp!, {r2, r3} @ save suspend func arg and pointer
+ mov r5, sp @ current virtual SP
+ add r4, r4, #12 @ Space for pgd, virt sp, phys resume fn
+ sub sp, sp, r4 @ allocate CPU state on stack
+ stmfd sp!, {r0, r1} @ save suspend func arg and pointer
+ add r0, sp, #8 @ save pointer to save block
+ mov r1, r4 @ size of save block
+ mov r2, r5 @ virtual SP
+ ldr r3, =sleep_save_sp
#ifdef CONFIG_SMP
ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
ALT_UP(mov lr, #0)
and lr, lr, #15
- str r6, [r5, lr, lsl #2] @ save phys SP
-#else
- str r6, [r5] @ save phys SP
-#endif
-#ifdef MULTI_CPU
- mov lr, pc
- ldr pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
-#else
- bl cpu_do_suspend
-#endif
-
- @ flush data cache
-#ifdef MULTI_CACHE
- ldr r10, =cpu_cache
- mov lr, pc
- ldr pc, [r10, #CACHE_FLUSH_KERN_ALL]
-#else
- bl __cpuc_flush_kern_all
+ add r3, r3, lr, lsl #2
#endif
+ bl __cpu_suspend_save
adr lr, BSYM(cpu_suspend_abort)
ldmfd sp!, {r0, pc} @ call suspend fn
ENDPROC(__cpu_suspend)
.ltorg
cpu_suspend_abort:
- ldmia sp!, {r1 - r3} @ pop v:p, virt SP, phys resume fn
+ ldmia sp!, {r1 - r3} @ pop phys pgd, virt SP, phys resume fn
+ teq r0, #0
+ moveq r0, #1 @ force non-zero value
mov sp, r2
ldmfd sp!, {r4 - r11, pc}
ENDPROC(cpu_suspend_abort)
/*
* r0 = control register value
- * r1 = v:p offset (preserved by cpu_do_resume)
- * r2 = phys page table base
- * r3 = L1 section flags
*/
+ .align 5
ENTRY(cpu_resume_mmu)
- adr r4, cpu_resume_turn_mmu_on
- mov r4, r4, lsr #20
- orr r3, r3, r4, lsl #20
- ldr r5, [r2, r4, lsl #2] @ save old mapping
- str r3, [r2, r4, lsl #2] @ setup 1:1 mapping for mmu code
- sub r2, r2, r1
ldr r3, =cpu_resume_after_mmu
- bic r1, r0, #CR_C @ ensure D-cache is disabled
- b cpu_resume_turn_mmu_on
-ENDPROC(cpu_resume_mmu)
- .ltorg
- .align 5
-cpu_resume_turn_mmu_on:
- mcr p15, 0, r1, c1, c0, 0 @ turn on MMU, I-cache, etc
- mrc p15, 0, r1, c0, c0, 0 @ read id reg
- mov r1, r1
- mov r1, r1
+ mcr p15, 0, r0, c1, c0, 0 @ turn on MMU, I-cache, etc
+ mrc p15, 0, r0, c0, c0, 0 @ read id reg
+ mov r0, r0
+ mov r0, r0
mov pc, r3 @ jump to virtual address
-ENDPROC(cpu_resume_turn_mmu_on)
+ENDPROC(cpu_resume_mmu)
cpu_resume_after_mmu:
- str r5, [r2, r4, lsl #2] @ restore old mapping
- mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache
bl cpu_init @ restore the und/abt/irq banked regs
mov r0, #0 @ return zero on success
ldmfd sp!, {r4 - r11, pc}
@@ -119,7 +88,7 @@ ENTRY(cpu_resume)
ldr r0, sleep_save_sp @ stack phys addr
#endif
setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off
- @ load v:p, stack, resume fn
+ @ load phys pgd, stack, resume fn
ARM( ldmia r0!, {r1, sp, pc} )
THUMB( ldmia r0!, {r1, r2, r3} )
THUMB( mov sp, r2 )
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index d88ff0230e82..ef5640b9e218 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -16,7 +16,6 @@
#include <linux/cache.h>
#include <linux/profile.h>
#include <linux/errno.h>
-#include <linux/ftrace.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/cpu.h>
@@ -31,6 +30,8 @@
#include <asm/cacheflush.h>
#include <asm/cpu.h>
#include <asm/cputype.h>
+#include <asm/exception.h>
+#include <asm/topology.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -39,6 +40,7 @@
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
#include <asm/localtimer.h>
+#include <asm/smp_plat.h>
/*
* as from 2.5, kernels no longer have an init_tasks structure
@@ -259,6 +261,20 @@ void __ref cpu_die(void)
}
#endif /* CONFIG_HOTPLUG_CPU */
+int __cpu_logical_map[NR_CPUS];
+
+void __init smp_setup_processor_id(void)
+{
+ int i;
+ u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
+
+ cpu_logical_map(0) = cpu;
+ for (i = 1; i < NR_CPUS; ++i)
+ cpu_logical_map(i) = i == cpu ? 0 : i;
+
+ printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
+}
+
/*
* Called by both boot and secondaries to move global data into
* per-processor storage.
@@ -268,6 +284,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
cpu_info->loops_per_jiffy = loops_per_jiffy;
+
+ store_cpu_topology(cpuid);
}
/*
@@ -301,17 +319,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
*/
platform_secondary_init(cpu);
- /*
- * Enable local interrupts.
- */
notify_cpu_starting(cpu);
- local_irq_enable();
- local_fiq_enable();
-
- /*
- * Setup the percpu timer for this CPU.
- */
- percpu_timer_setup();
calibrate_delay();
@@ -323,10 +331,23 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
* before we continue.
*/
set_cpu_online(cpu, true);
+
+ /*
+ * Setup the percpu timer for this CPU.
+ */
+ percpu_timer_setup();
+
while (!cpu_active(cpu))
cpu_relax();
/*
+ * cpu_active bit is set, so it's safe to enalbe interrupts
+ * now.
+ */
+ local_irq_enable();
+ local_fiq_enable();
+
+ /*
* OK, it's off to the idle thread for us
*/
cpu_idle();
@@ -358,6 +379,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
{
unsigned int ncores = num_possible_cpus();
+ init_cpu_topology();
+
smp_store_cpu_info(smp_processor_id());
/*
@@ -437,10 +460,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
for (i = 0; i < NR_IPI; i++)
sum += __get_irq_stat(cpu, ipi_irqs[i]);
-#ifdef CONFIG_LOCAL_TIMERS
- sum += __get_irq_stat(cpu, local_timer_irqs);
-#endif
-
return sum;
}
@@ -457,33 +476,6 @@ static void ipi_timer(void)
irq_exit();
}
-#ifdef CONFIG_LOCAL_TIMERS
-asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
-{
- struct pt_regs *old_regs = set_irq_regs(regs);
- int cpu = smp_processor_id();
-
- if (local_timer_ack()) {
- __inc_irq_stat(cpu, local_timer_irqs);
- ipi_timer();
- }
-
- set_irq_regs(old_regs);
-}
-
-void show_local_irqs(struct seq_file *p, int prec)
-{
- unsigned int cpu;
-
- seq_printf(p, "%*s: ", prec, "LOC");
-
- for_each_present_cpu(cpu)
- seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));
-
- seq_printf(p, " Local timer interrupts\n");
-}
-#endif
-
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
static void smp_timer_broadcast(const struct cpumask *mask)
{
@@ -534,11 +526,11 @@ static void percpu_timer_stop(void)
unsigned int cpu = smp_processor_id();
struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
- evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+ local_timer_stop(evt);
}
#endif
-static DEFINE_SPINLOCK(stop_lock);
+static DEFINE_RAW_SPINLOCK(stop_lock);
/*
* ipi_cpu_stop - handle IPI from smp_send_stop()
@@ -547,10 +539,10 @@ static void ipi_cpu_stop(unsigned int cpu)
{
if (system_state == SYSTEM_BOOTING ||
system_state == SYSTEM_RUNNING) {
- spin_lock(&stop_lock);
+ raw_spin_lock(&stop_lock);
printk(KERN_CRIT "CPU%u: stopping\n", cpu);
dump_stack();
- spin_unlock(&stop_lock);
+ raw_spin_unlock(&stop_lock);
}
set_cpu_online(cpu, false);
@@ -567,6 +559,11 @@ static void ipi_cpu_stop(unsigned int cpu)
*/
asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
{
+ handle_IPI(ipinr, regs);
+}
+
+void handle_IPI(int ipinr, struct pt_regs *regs)
+{
unsigned int cpu = smp_processor_id();
struct pt_regs *old_regs = set_irq_regs(regs);
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c
index 7fcddb75c877..8f5dd7963356 100644
--- a/arch/arm/kernel/smp_scu.c
+++ b/arch/arm/kernel/smp_scu.c
@@ -34,7 +34,7 @@ unsigned int __init scu_get_core_count(void __iomem *scu_base)
/*
* Enable the SCU
*/
-void __init scu_enable(void __iomem *scu_base)
+void scu_enable(void __iomem *scu_base)
{
u32 scu_ctrl;
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 01c186222f3b..a8a6682d6b52 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -19,6 +19,7 @@
#include <linux/io.h>
#include <asm/smp_twd.h>
+#include <asm/localtimer.h>
#include <asm/hardware/gic.h>
/* set up by the platform code */
@@ -26,6 +27,8 @@ void __iomem *twd_base;
static unsigned long twd_timer_rate;
+static struct clock_event_device __percpu **twd_evt;
+
static void twd_set_mode(enum clock_event_mode mode,
struct clock_event_device *clk)
{
@@ -80,6 +83,12 @@ int twd_timer_ack(void)
return 0;
}
+void twd_timer_stop(struct clock_event_device *clk)
+{
+ twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+ disable_percpu_irq(clk->irq);
+}
+
static void __cpuinit twd_calibrate_rate(void)
{
unsigned long count;
@@ -119,11 +128,43 @@ static void __cpuinit twd_calibrate_rate(void)
}
}
+static irqreturn_t twd_handler(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+
+ if (twd_timer_ack()) {
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
/*
* Setup the local clock events for a CPU.
*/
void __cpuinit twd_timer_setup(struct clock_event_device *clk)
{
+ struct clock_event_device **this_cpu_clk;
+
+ if (!twd_evt) {
+ int err;
+
+ twd_evt = alloc_percpu(struct clock_event_device *);
+ if (!twd_evt) {
+ pr_err("twd: can't allocate memory\n");
+ return;
+ }
+
+ err = request_percpu_irq(clk->irq, twd_handler,
+ "twd", twd_evt);
+ if (err) {
+ pr_err("twd: can't register interrupt %d (%d)\n",
+ clk->irq, err);
+ return;
+ }
+ }
+
twd_calibrate_rate();
clk->name = "local_timer";
@@ -137,8 +178,10 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
+ this_cpu_clk = __this_cpu_ptr(twd_evt);
+ *this_cpu_clk = clk;
+
clockevents_register_device(clk);
- /* Make sure our local interrupt controller has this enabled */
- gic_enable_ppi(clk->irq);
+ enable_percpu_irq(clk->irq, 0);
}
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c
new file mode 100644
index 000000000000..93a22d282c16
--- /dev/null
+++ b/arch/arm/kernel/suspend.c
@@ -0,0 +1,72 @@
+#include <linux/init.h>
+
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/memory.h>
+#include <asm/suspend.h>
+#include <asm/tlbflush.h>
+
+static pgd_t *suspend_pgd;
+
+extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
+extern void cpu_resume_mmu(void);
+
+/*
+ * This is called by __cpu_suspend() to save the state, and do whatever
+ * flushing is required to ensure that when the CPU goes to sleep we have
+ * the necessary data available when the caches are not searched.
+ */
+void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
+{
+ *save_ptr = virt_to_phys(ptr);
+
+ /* This must correspond to the LDM in cpu_resume() assembly */
+ *ptr++ = virt_to_phys(suspend_pgd);
+ *ptr++ = sp;
+ *ptr++ = virt_to_phys(cpu_do_resume);
+
+ cpu_do_suspend(ptr);
+
+ flush_cache_all();
+ outer_clean_range(*save_ptr, *save_ptr + ptrsz);
+ outer_clean_range(virt_to_phys(save_ptr),
+ virt_to_phys(save_ptr) + sizeof(*save_ptr));
+}
+
+/*
+ * Hide the first two arguments to __cpu_suspend - these are an implementation
+ * detail which platform code shouldn't have to know about.
+ */
+int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
+{
+ struct mm_struct *mm = current->active_mm;
+ int ret;
+
+ if (!suspend_pgd)
+ return -EINVAL;
+
+ /*
+ * Provide a temporary page table with an identity mapping for
+ * the MMU-enable code, required for resuming. On successful
+ * resume (indicated by a zero return code), we need to switch
+ * back to the correct page tables.
+ */
+ ret = __cpu_suspend(arg, fn);
+ if (ret == 0) {
+ cpu_switch_mm(mm->pgd, mm);
+ local_flush_tlb_all();
+ }
+
+ return ret;
+}
+
+static int __init cpu_suspend_init(void)
+{
+ suspend_pgd = pgd_alloc(&init_mm);
+ if (suspend_pgd) {
+ unsigned long addr = virt_to_phys(cpu_resume_mmu);
+ identity_mapping_add(suspend_pgd, addr, addr + SECTION_SIZE);
+ }
+ return suspend_pgd ? 0 : -ENOMEM;
+}
+core_initcall(cpu_suspend_init);
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index cb634c3e28e9..5a54b95d6bd2 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -39,13 +39,11 @@
*/
static struct sys_timer *system_timer;
-#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
+#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \
+ defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)
/* this needs a better home */
DEFINE_SPINLOCK(rtc_lock);
-
-#ifdef CONFIG_RTC_DRV_CMOS_MODULE
EXPORT_SYMBOL(rtc_lock);
-#endif
#endif /* pc-style 'CMOS' RTC support */
/* change this if you have some constant time drift */
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
new file mode 100644
index 000000000000..1040c00405d0
--- /dev/null
+++ b/arch/arm/kernel/topology.c
@@ -0,0 +1,148 @@
+/*
+ * arch/arm/kernel/topology.c
+ *
+ * Copyright (C) 2011 Linaro Limited.
+ * Written by: Vincent Guittot
+ *
+ * based on arch/sh/kernel/topology.c
+ *
+ * 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/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/sched.h>
+
+#include <asm/cputype.h>
+#include <asm/topology.h>
+
+#define MPIDR_SMP_BITMASK (0x3 << 30)
+#define MPIDR_SMP_VALUE (0x2 << 30)
+
+#define MPIDR_MT_BITMASK (0x1 << 24)
+
+/*
+ * These masks reflect the current use of the affinity levels.
+ * The affinity level can be up to 16 bits according to ARM ARM
+ */
+
+#define MPIDR_LEVEL0_MASK 0x3
+#define MPIDR_LEVEL0_SHIFT 0
+
+#define MPIDR_LEVEL1_MASK 0xF
+#define MPIDR_LEVEL1_SHIFT 8
+
+#define MPIDR_LEVEL2_MASK 0xFF
+#define MPIDR_LEVEL2_SHIFT 16
+
+struct cputopo_arm cpu_topology[NR_CPUS];
+
+const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
+{
+ return &cpu_topology[cpu].core_sibling;
+}
+
+/*
+ * store_cpu_topology is called at boot when only one cpu is running
+ * and with the mutex cpu_hotplug.lock locked, when several cpus have booted,
+ * which prevents simultaneous write access to cpu_topology array
+ */
+void store_cpu_topology(unsigned int cpuid)
+{
+ struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid];
+ unsigned int mpidr;
+ unsigned int cpu;
+
+ /* If the cpu topology has been already set, just return */
+ if (cpuid_topo->core_id != -1)
+ return;
+
+ mpidr = read_cpuid_mpidr();
+
+ /* create cpu topology mapping */
+ if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) {
+ /*
+ * This is a multiprocessor system
+ * multiprocessor format & multiprocessor mode field are set
+ */
+
+ if (mpidr & MPIDR_MT_BITMASK) {
+ /* core performance interdependency */
+ cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT)
+ & MPIDR_LEVEL0_MASK;
+ cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT)
+ & MPIDR_LEVEL1_MASK;
+ cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT)
+ & MPIDR_LEVEL2_MASK;
+ } else {
+ /* largely independent cores */
+ cpuid_topo->thread_id = -1;
+ cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT)
+ & MPIDR_LEVEL0_MASK;
+ cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT)
+ & MPIDR_LEVEL1_MASK;
+ }
+ } else {
+ /*
+ * This is an uniprocessor system
+ * we are in multiprocessor format but uniprocessor system
+ * or in the old uniprocessor format
+ */
+ cpuid_topo->thread_id = -1;
+ cpuid_topo->core_id = 0;
+ cpuid_topo->socket_id = -1;
+ }
+
+ /* update core and thread sibling masks */
+ for_each_possible_cpu(cpu) {
+ struct cputopo_arm *cpu_topo = &cpu_topology[cpu];
+
+ if (cpuid_topo->socket_id == cpu_topo->socket_id) {
+ cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
+ if (cpu != cpuid)
+ cpumask_set_cpu(cpu,
+ &cpuid_topo->core_sibling);
+
+ if (cpuid_topo->core_id == cpu_topo->core_id) {
+ cpumask_set_cpu(cpuid,
+ &cpu_topo->thread_sibling);
+ if (cpu != cpuid)
+ cpumask_set_cpu(cpu,
+ &cpuid_topo->thread_sibling);
+ }
+ }
+ }
+ smp_wmb();
+
+ printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",
+ cpuid, cpu_topology[cpuid].thread_id,
+ cpu_topology[cpuid].core_id,
+ cpu_topology[cpuid].socket_id, mpidr);
+}
+
+/*
+ * init_cpu_topology is called at boot when only one cpu is running
+ * which prevent simultaneous write access to cpu_topology array
+ */
+void init_cpu_topology(void)
+{
+ unsigned int cpu;
+
+ /* init core mask */
+ for_each_possible_cpu(cpu) {
+ struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]);
+
+ cpu_topo->thread_id = -1;
+ cpu_topo->core_id = -1;
+ cpu_topo->socket_id = -1;
+ cpumask_clear(&cpu_topo->core_sibling);
+ cpumask_clear(&cpu_topo->thread_sibling);
+ }
+ smp_wmb();
+}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index bc9f9da782cb..99a572702509 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -21,12 +21,14 @@
#include <linux/kdebug.h>
#include <linux/module.h>
#include <linux/kexec.h>
+#include <linux/bug.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/atomic.h>
#include <asm/cacheflush.h>
+#include <asm/exception.h>
#include <asm/system.h>
#include <asm/unistd.h>
#include <asm/traps.h>
@@ -255,7 +257,7 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt
return ret;
}
-static DEFINE_SPINLOCK(die_lock);
+static DEFINE_RAW_SPINLOCK(die_lock);
/*
* This function is protected against re-entrancy.
@@ -267,9 +269,11 @@ void die(const char *str, struct pt_regs *regs, int err)
oops_enter();
- spin_lock_irq(&die_lock);
+ raw_spin_lock_irq(&die_lock);
console_verbose();
bust_spinlocks(1);
+ if (!user_mode(regs))
+ report_bug(regs->ARM_pc, regs);
ret = __die(str, err, thread, regs);
if (regs && kexec_should_crash(thread->task))
@@ -277,7 +281,7 @@ void die(const char *str, struct pt_regs *regs, int err)
bust_spinlocks(0);
add_taint(TAINT_DIE);
- spin_unlock_irq(&die_lock);
+ raw_spin_unlock_irq(&die_lock);
oops_exit();
if (in_interrupt())
@@ -301,25 +305,43 @@ void arm_notify_die(const char *str, struct pt_regs *regs,
}
}
+#ifdef CONFIG_GENERIC_BUG
+
+int is_valid_bugaddr(unsigned long pc)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+ unsigned short bkpt;
+#else
+ unsigned long bkpt;
+#endif
+
+ if (probe_kernel_address((unsigned *)pc, bkpt))
+ return 0;
+
+ return bkpt == BUG_INSTR_VALUE;
+}
+
+#endif
+
static LIST_HEAD(undef_hook);
-static DEFINE_SPINLOCK(undef_lock);
+static DEFINE_RAW_SPINLOCK(undef_lock);
void register_undef_hook(struct undef_hook *hook)
{
unsigned long flags;
- spin_lock_irqsave(&undef_lock, flags);
+ raw_spin_lock_irqsave(&undef_lock, flags);
list_add(&hook->node, &undef_hook);
- spin_unlock_irqrestore(&undef_lock, flags);
+ raw_spin_unlock_irqrestore(&undef_lock, flags);
}
void unregister_undef_hook(struct undef_hook *hook)
{
unsigned long flags;
- spin_lock_irqsave(&undef_lock, flags);
+ raw_spin_lock_irqsave(&undef_lock, flags);
list_del(&hook->node);
- spin_unlock_irqrestore(&undef_lock, flags);
+ raw_spin_unlock_irqrestore(&undef_lock, flags);
}
static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
@@ -328,12 +350,12 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
unsigned long flags;
int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL;
- spin_lock_irqsave(&undef_lock, flags);
+ raw_spin_lock_irqsave(&undef_lock, flags);
list_for_each_entry(hook, &undef_hook, node)
if ((instr & hook->instr_mask) == hook->instr_val &&
(regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val)
fn = hook->fn;
- spin_unlock_irqrestore(&undef_lock, flags);
+ raw_spin_unlock_irqrestore(&undef_lock, flags);
return fn ? fn(regs, instr) : 1;
}
@@ -706,16 +728,6 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
arm_notify_die("unknown data abort code", regs, &info, instr, 0);
}
-void __attribute__((noreturn)) __bug(const char *file, int line)
-{
- printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
- *(int *)0 = 0;
-
- /* Avoid "noreturn function does return" */
- for (;;);
-}
-EXPORT_SYMBOL(__bug);
-
void __readwrite_bug(const char *fn)
{
printk("%s called, but not implemented\n", fn);
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 4e66f62b8d41..20b3041e0860 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -21,7 +21,8 @@
#define ARM_CPU_KEEP(x)
#endif
-#if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)
+#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \
+ defined(CONFIG_GENERIC_BUG)
#define ARM_EXIT_KEEP(x) x
#define ARM_EXIT_DISCARD(x)
#else
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index a673297b0cf1..cd07b5814c23 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -22,15 +22,10 @@
#define mask r7
#define offset r8
-ENTRY(__backtrace)
- mov r1, #0x10
- mov r0, fp
-
ENTRY(c_backtrace)
#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
mov pc, lr
-ENDPROC(__backtrace)
ENDPROC(c_backtrace)
#else
stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location...
@@ -107,7 +102,6 @@ for_each_frame: tst frame, mask @ Check for address exceptions
mov r1, frame
bl printk
no_frame: ldmfd sp!, {r4 - r8, pc}
-ENDPROC(__backtrace)
ENDPROC(c_backtrace)
.pushsection __ex_table,"a"
diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S
index faa7748142da..e55c4842c290 100644
--- a/arch/arm/lib/div64.S
+++ b/arch/arm/lib/div64.S
@@ -13,6 +13,7 @@
*/
#include <linux/linkage.h>
+#include <asm/unwind.h>
#ifdef __ARMEB__
#define xh r0
@@ -44,6 +45,7 @@
*/
ENTRY(__do_div64)
+UNWIND(.fnstart)
@ Test for easy paths first.
subs ip, r4, #1
@@ -189,7 +191,12 @@ ENTRY(__do_div64)
moveq yh, xh
moveq xh, #0
moveq pc, lr
+UNWIND(.fnend)
+UNWIND(.fnstart)
+UNWIND(.pad #4)
+UNWIND(.save {lr})
+Ldiv0_64:
@ Division by 0:
str lr, [sp, #-8]!
bl __div0
@@ -200,4 +207,5 @@ ENTRY(__do_div64)
mov xh, #0
ldr pc, [sp], #8
+UNWIND(.fnend)
ENDPROC(__do_div64)
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c
index 8b9b13649f81..025f742dd4df 100644
--- a/arch/arm/lib/uaccess_with_memcpy.c
+++ b/arch/arm/lib/uaccess_with_memcpy.c
@@ -17,6 +17,7 @@
#include <linux/sched.h>
#include <linux/hardirq.h> /* for in_atomic() */
#include <linux/gfp.h>
+#include <linux/highmem.h>
#include <asm/current.h>
#include <asm/page.h>
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 22484670e7ba..a6b7991d7fe8 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -182,6 +182,11 @@ config MACH_ECO920
help
Select this if you are using the eco920 board
+config MACH_RSI_EWS
+ bool "RSI Embedded Webserver"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using RSIs EWS board.
endif
# ----------------------------------------------------------
@@ -381,6 +386,14 @@ config MACH_GSIA18S
This enables support for the GS_IA18_S board
produced by GeoSIG Ltd company. This is an internet accelerograph.
<http://www.geosig.com>
+
+config MACH_USB_A9G20
+ bool "CALAO USB-A9G20"
+ depends on ARCH_AT91SAM9G20
+ help
+ Select this if you are using a Calao Systems USB-A9G20.
+ <http://www.calao-systems.com>
+
endif
if (ARCH_AT91SAM9260 || ARCH_AT91SAM9G20)
@@ -442,6 +455,17 @@ endif
# ----------------------------------------------------------
+comment "Generic Board Type"
+
+config MACH_AT91SAM_DT
+ bool "Atmel AT91SAM Evaluation Kits with device-tree support"
+ select USE_OF
+ help
+ Select this if you want to experiment device-tree with
+ an Atmel Evaluation Kit.
+
+# ----------------------------------------------------------
+
comment "AT91 Board Options"
config MTD_AT91_DATAFLASH_CARD
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index bf57e8b1c9d0..242174f9f355 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -36,12 +36,13 @@ obj-$(CONFIG_MACH_ECBAT91) += board-ecbat91.o
obj-$(CONFIG_MACH_YL9200) += board-yl-9200.o
obj-$(CONFIG_MACH_CPUAT91) += board-cpuat91.o
obj-$(CONFIG_MACH_ECO920) += board-eco920.o
+obj-$(CONFIG_MACH_RSI_EWS) += board-rsi-ews.o
# AT91SAM9260 board-specific support
obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
obj-$(CONFIG_MACH_CAM60) += board-cam60.o
obj-$(CONFIG_MACH_SAM9_L9260) += board-sam9-l9260.o
-obj-$(CONFIG_MACH_USB_A9260) += board-usb-a9260.o
+obj-$(CONFIG_MACH_USB_A9260) += board-usb-a926x.o
obj-$(CONFIG_MACH_QIL_A9260) += board-qil-a9260.o
obj-$(CONFIG_MACH_AFEB9260) += board-afeb-9260v1.o
obj-$(CONFIG_MACH_CPU9260) += board-cpu9krea.o
@@ -53,7 +54,7 @@ obj-$(CONFIG_MACH_AT91SAM9G10EK) += board-sam9261ek.o
# AT91SAM9263 board-specific support
obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o
-obj-$(CONFIG_MACH_USB_A9263) += board-usb-a9263.o
+obj-$(CONFIG_MACH_USB_A9263) += board-usb-a926x.o
obj-$(CONFIG_MACH_NEOCORE926) += board-neocore926.o
# AT91SAM9RL board-specific support
@@ -67,6 +68,7 @@ obj-$(CONFIG_MACH_STAMP9G20) += board-stamp9g20.o
obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o
obj-$(CONFIG_MACH_PCONTROL_G20) += board-pcontrol-g20.o board-stamp9g20.o
obj-$(CONFIG_MACH_GSIA18S) += board-gsia18s.o board-stamp9g20.o
+obj-$(CONFIG_MACH_USB_A9G20) += board-usb-a926x.o
# AT91SAM9260/AT91SAM9G20 board-specific support
obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o
@@ -74,6 +76,9 @@ obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o
# AT91SAM9G45 board-specific support
obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
+# AT91SAM board with device-tree
+obj-$(CONFIG_MACH_AT91SAM_DT) += board-dt.o
+
# AT91CAP9 board-specific support
obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o
diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
index 3462b815054a..8ddafadfdc7d 100644
--- a/arch/arm/mach-at91/Makefile.boot
+++ b/arch/arm/mach-at91/Makefile.boot
@@ -4,15 +4,17 @@
# INITRD_PHYS must be in RAM
ifeq ($(CONFIG_ARCH_AT91CAP9),y)
- zreladdr-y := 0x70008000
+ zreladdr-y += 0x70008000
params_phys-y := 0x70000100
initrd_phys-y := 0x70410000
else ifeq ($(CONFIG_ARCH_AT91SAM9G45),y)
- zreladdr-y := 0x70008000
+ zreladdr-y += 0x70008000
params_phys-y := 0x70000100
initrd_phys-y := 0x70410000
else
- zreladdr-y := 0x20008000
+ zreladdr-y += 0x20008000
params_phys-y := 0x20000100
initrd_phys-y := 0x20410000
endif
+
+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb usb_a9g20.dtb
diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c
index bfc684441ef8..ecdd54dd68c6 100644
--- a/arch/arm/mach-at91/at91cap9.c
+++ b/arch/arm/mach-at91/at91cap9.c
@@ -219,6 +219,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+ /* fake hclk clock */
+ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index dba0d8d8a4bd..a4401d6b5b07 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -16,6 +16,7 @@
#include <asm/mach/irq.h>
#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
@@ -23,7 +24,6 @@
#include <mach/board.h>
#include <mach/cpu.h>
-#include <mach/gpio.h>
#include <mach/at91cap9.h>
#include <mach/at91cap9_matrix.h>
#include <mach/at91sam9_smc.h>
@@ -80,6 +80,12 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
at91_set_gpio_output(data->vbus_pin[i], 0);
}
+ /* Enable overcurrent notification */
+ for (i = 0; i < data->ports; i++) {
+ if (data->overcurrent_pin[i])
+ at91_set_gpio_input(data->overcurrent_pin[i], 1);
+ }
+
usbh_data = *data;
platform_device_register(&at91_usbh_device);
}
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index f73302dbc6a5..713d3bdbd284 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -193,6 +193,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
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),
+ /* fake hclk clock */
+ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 7227755ffec6..01d8bbd1468b 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -14,11 +14,11 @@
#include <asm/mach/map.h>
#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91rm9200.h>
#include <mach/at91rm9200_mc.h>
@@ -60,9 +60,17 @@ static struct platform_device at91rm9200_usbh_device = {
void __init at91_add_device_usbh(struct at91_usbh_data *data)
{
+ int i;
+
if (!data)
return;
+ /* Enable overcurrent notification */
+ for (i = 0; i < data->ports; i++) {
+ if (data->overcurrent_pin[i])
+ at91_set_gpio_input(data->overcurrent_pin[i], 1);
+ }
+
usbh_data = *data;
platform_device_register(&at91rm9200_usbh_device);
}
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index cb397be14448..b84a9f642f59 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -199,6 +199,16 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t4_clk", "atmel_tcb.1", &tc4_clk),
CLKDEV_CON_DEV_ID("t5_clk", "atmel_tcb.1", &tc5_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
+ /* more usart lookup table for DT entries */
+ CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
+ CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffb4000.serial", &usart1_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffb8000.serial", &usart2_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk),
+ /* fake hclk clock */
+ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 39f81f47b4ba..24b6f8c0440d 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -13,11 +13,11 @@
#include <asm/mach/map.h>
#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/cpu.h>
#include <mach/at91sam9260.h>
#include <mach/at91sam9260_matrix.h>
@@ -61,9 +61,17 @@ static struct platform_device at91_usbh_device = {
void __init at91_add_device_usbh(struct at91_usbh_data *data)
{
+ int i;
+
if (!data)
return;
+ /* Enable overcurrent notification */
+ for (i = 0; i < data->ports; i++) {
+ if (data->overcurrent_pin[i])
+ at91_set_gpio_input(data->overcurrent_pin[i], 1);
+ }
+
usbh_data = *data;
platform_device_register(&at91_usbh_device);
}
@@ -319,7 +327,7 @@ void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
if (!data)
return;
- for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
if (data->slot[i].bus_width) {
/* input/irq */
if (data->slot[i].detect_pin) {
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 6c8e3b5f669f..658a5185abfd 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -129,6 +129,20 @@ static struct clk lcdc_clk = {
.type = CLK_TYPE_PERIPHERAL,
};
+/* HClocks */
+static struct clk hck0 = {
+ .name = "hck0",
+ .pmc_mask = AT91_PMC_HCK0,
+ .type = CLK_TYPE_SYSTEM,
+ .id = 0,
+};
+static struct clk hck1 = {
+ .name = "hck1",
+ .pmc_mask = AT91_PMC_HCK1,
+ .type = CLK_TYPE_SYSTEM,
+ .id = 1,
+};
+
static struct clk *periph_clocks[] __initdata = {
&pioA_clk,
&pioB_clk,
@@ -161,6 +175,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
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("hclk", "at91_ohci", &hck0),
};
static struct clk_lookup usart_clocks_lookups[] = {
@@ -199,20 +214,6 @@ static struct clk pck3 = {
.id = 3,
};
-/* HClocks */
-static struct clk hck0 = {
- .name = "hck0",
- .pmc_mask = AT91_PMC_HCK0,
- .type = CLK_TYPE_SYSTEM,
- .id = 0,
-};
-static struct clk hck1 = {
- .name = "hck1",
- .pmc_mask = AT91_PMC_HCK1,
- .type = CLK_TYPE_SYSTEM,
- .id = 1,
-};
-
static void __init at91sam9261_register_clocks(void)
{
int i;
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 0f917928eeb7..3b70b3897d95 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -14,6 +14,7 @@
#include <asm/mach/map.h>
#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
@@ -21,7 +22,6 @@
#include <video/atmel_lcdc.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9261.h>
#include <mach/at91sam9261_matrix.h>
#include <mach/at91sam9_smc.h>
@@ -64,9 +64,17 @@ static struct platform_device at91sam9261_usbh_device = {
void __init at91_add_device_usbh(struct at91_usbh_data *data)
{
+ int i;
+
if (!data)
return;
+ /* Enable overcurrent notification */
+ for (i = 0; i < data->ports; i++) {
+ if (data->overcurrent_pin[i])
+ at91_set_gpio_input(data->overcurrent_pin[i], 1);
+ }
+
usbh_data = *data;
platform_device_register(&at91sam9261_usbh_device);
}
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 044f3c927e64..f83fbb0ee0c5 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -189,6 +189,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
+ /* fake hclk clock */
+ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index a050f41fc860..3faa1fde9ad9 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -13,6 +13,7 @@
#include <asm/mach/map.h>
#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
@@ -20,7 +21,6 @@
#include <video/atmel_lcdc.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9263.h>
#include <mach/at91sam9263_matrix.h>
#include <mach/at91sam9_smc.h>
@@ -74,6 +74,12 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
at91_set_gpio_output(data->vbus_pin[i], 0);
}
+ /* Enable overcurrent notification */
+ for (i = 0; i < data->ports; i++) {
+ if (data->overcurrent_pin[i])
+ at91_set_gpio_input(data->overcurrent_pin[i], 1);
+ }
+
usbh_data = *data;
platform_device_register(&at91_usbh_device);
}
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index e04c5fb6f1ee..318b0407ea04 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/pm.h>
+#include <linux/dma-mapping.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
@@ -53,6 +54,11 @@ static struct clk pioDE_clk = {
.pmc_mask = 1 << AT91SAM9G45_ID_PIODE,
.type = CLK_TYPE_PERIPHERAL,
};
+static struct clk trng_clk = {
+ .name = "trng_clk",
+ .pmc_mask = 1 << AT91SAM9G45_ID_TRNG,
+ .type = CLK_TYPE_PERIPHERAL,
+};
static struct clk usart0_clk = {
.name = "usart0_clk",
.pmc_mask = 1 << AT91SAM9G45_ID_US0,
@@ -176,6 +182,7 @@ static struct clk *periph_clocks[] __initdata = {
&pioB_clk,
&pioC_clk,
&pioDE_clk,
+ &trng_clk,
&usart0_clk,
&usart1_clk,
&usart2_clk,
@@ -215,6 +222,15 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+ CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
+ /* more usart lookup table for DT entries */
+ CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
+ CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
+ CLKDEV_CON_DEV_ID("usart", "fff90000.serial", &usart1_clk),
+ CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk),
+ CLKDEV_CON_DEV_ID("usart", "fff98000.serial", &usart3_clk),
+ /* fake hclk clock */
+ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
@@ -319,6 +335,7 @@ static void at91sam9g45_poweroff(void)
static void __init at91sam9g45_map_io(void)
{
at91_init_sram(0, AT91SAM9G45_SRAM_BASE, AT91SAM9G45_SRAM_SIZE);
+ init_consistent_dma_size(SZ_4M);
}
static void __init at91sam9g45_initialize(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 600bffb01edb..000b5e1da965 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -13,6 +13,7 @@
#include <asm/mach/map.h>
#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
#include <linux/atmel-mci.h>
@@ -21,7 +22,6 @@
#include <video/atmel_lcdc.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9g45.h>
#include <mach/at91sam9g45_matrix.h>
#include <mach/at91sam9_smc.h>
@@ -124,6 +124,12 @@ void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
at91_set_gpio_output(data->vbus_pin[i], 0);
}
+ /* Enable overcurrent notification */
+ for (i = 0; i < data->ports; i++) {
+ if (data->overcurrent_pin[i])
+ at91_set_gpio_input(data->overcurrent_pin[i], 1);
+ }
+
usbh_ohci_data = *data;
platform_device_register(&at91_usbh_ohci_device);
}
@@ -1095,6 +1101,34 @@ static void __init at91_add_device_rtt(void)
/* --------------------------------------------------------------------
+ * TRNG
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_HW_RANDOM_ATMEL) || defined(CONFIG_HW_RANDOM_ATMEL_MODULE)
+static struct resource trng_resources[] = {
+ {
+ .start = AT91SAM9G45_BASE_TRNG,
+ .end = AT91SAM9G45_BASE_TRNG + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device at91sam9g45_trng_device = {
+ .name = "atmel-trng",
+ .id = -1,
+ .resource = trng_resources,
+ .num_resources = ARRAY_SIZE(trng_resources),
+};
+
+static void __init at91_add_device_trng(void)
+{
+ platform_device_register(&at91sam9g45_trng_device);
+}
+#else
+static void __init at91_add_device_trng(void) {}
+#endif
+
+/* --------------------------------------------------------------------
* Watchdog
* -------------------------------------------------------------------- */
@@ -1583,6 +1617,7 @@ static int __init at91_add_standard_devices(void)
at91_add_device_hdmac();
at91_add_device_rtc();
at91_add_device_rtt();
+ at91_add_device_trng();
at91_add_device_watchdog();
at91_add_device_tc();
return 0;
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index aacb19dc9225..305a851b5bff 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -10,6 +10,7 @@
#include <asm/mach/map.h>
#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
@@ -17,7 +18,6 @@
#include <video/atmel_lcdc.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9rl.h>
#include <mach/at91sam9rl_matrix.h>
#include <mach/at91sam9_smc.h>
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index 5aa58851eb39..367d5cd5e362 100644
--- a/arch/arm/mach-at91/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -19,6 +19,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -34,7 +35,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/cpu.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index b0c796d42e49..0487ea10c2d6 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -25,6 +25,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -43,7 +44,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index d1abd5898e85..747b2eaa9737 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -21,6 +21,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -38,7 +39,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include "sam9_smc.h"
diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c
index 679b0b743e92..062670351a6a 100644
--- a/arch/arm/mach-at91/board-cap9adk.c
+++ b/arch/arm/mach-at91/board-cap9adk.c
@@ -22,6 +22,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -41,7 +42,6 @@
#include <asm/mach/map.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91cap9_matrix.h>
#include <mach/at91sam9_smc.h>
#include <mach/system_rev.h>
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index c578c5d90728..774c87fcbd5b 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -20,6 +20,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -35,7 +36,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index f4da8a16d5dc..fc885a4ce243 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -21,6 +21,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -40,7 +41,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include <mach/at91sam9260_matrix.h>
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index 2d919f5a4f57..d35e65b08ccd 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -19,6 +19,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -36,7 +37,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91rm9200_mc.h>
#include <mach/cpu.h>
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index 17654d5e94e6..c3936665e645 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -19,6 +19,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -38,7 +39,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index 72b55674616c..586100e2acbb 100644
--- a/arch/arm/mach-at91/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -20,6 +20,7 @@
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/gpio.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -35,7 +36,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
new file mode 100644
index 000000000000..0b7d32778210
--- /dev/null
+++ b/arch/arm/mach-at91/board-dt.c
@@ -0,0 +1,123 @@
+/*
+ * Setup code for AT91SAM Evaluation Kits with Device Tree support
+ *
+ * Covers: * AT91SAM9G45-EKES board
+ * * AT91SAM9M10-EKES board
+ * * AT91SAM9M10G45-EK board
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/system_rev.h>
+#include <mach/at91sam9_smc.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init ek_init_early(void)
+{
+ /* Initialize processor: 12.000 MHz crystal */
+ at91_initialize(12000000);
+
+ /* DGBU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* set serial console to ttyS0 (ie, DBGU) */
+ at91_set_serial_console(0);
+}
+
+/* det_pin is not connected */
+static struct atmel_nand_data __initdata ek_nand_data = {
+ .ale = 21,
+ .cle = 22,
+ .rdy_pin = AT91_PIN_PC8,
+ .enable_pin = AT91_PIN_PC14,
+};
+
+static struct sam9_smc_config __initdata ek_nand_smc_config = {
+ .ncs_read_setup = 0,
+ .nrd_setup = 2,
+ .ncs_write_setup = 0,
+ .nwe_setup = 2,
+
+ .ncs_read_pulse = 4,
+ .nrd_pulse = 4,
+ .ncs_write_pulse = 4,
+ .nwe_pulse = 4,
+
+ .read_cycle = 7,
+ .write_cycle = 7,
+
+ .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
+ .tdf_cycles = 3,
+};
+
+static void __init ek_add_device_nand(void)
+{
+ ek_nand_data.bus_width_16 = board_have_nand_16bit();
+ /* setup bus-width (8 or 16) */
+ if (ek_nand_data.bus_width_16)
+ ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
+ else
+ ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
+
+ /* configure chip-select 3 (NAND) */
+ sam9_smc_configure(3, &ek_nand_smc_config);
+
+ at91_add_device_nand(&ek_nand_data);
+}
+
+static const struct of_device_id aic_of_match[] __initconst = {
+ { .compatible = "atmel,at91rm9200-aic", },
+ {},
+};
+
+static void __init at91_dt_init_irq(void)
+{
+ irq_domain_generate_simple(aic_of_match, 0xfffff000, 0);
+ at91_init_irq_default();
+}
+
+static void __init at91_dt_device_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+ /* NAND */
+ ek_add_device_nand();
+}
+
+static const char *at91_dt_board_compat[] __initdata = {
+ "atmel,at91sam9m10g45ek",
+ "calao,usb-a9g20",
+ NULL
+};
+
+DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
+ /* Maintainer: Atmel */
+ .timer = &at91sam926x_timer,
+ .map_io = at91_map_io,
+ .init_early = ek_init_early,
+ .init_irq = at91_dt_init_irq,
+ .init_machine = at91_dt_device_init,
+ .dt_compat = at91_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index 01170a2766a8..45db7a3dbef0 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -20,6 +20,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -35,7 +36,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index 7c0313c51f26..2f9c16d29212 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -20,6 +20,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -37,7 +38,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/cpu.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index 4a170890b3b1..3bae73e63633 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -19,6 +19,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -34,7 +35,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/cpu.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index 9dc8d496ead1..15a3f1a87ab0 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -20,6 +20,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -35,7 +36,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/cpu.h>
#include <mach/at91rm9200_mc.h>
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index 9bc6ab32e0ac..6094496f7edb 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -21,6 +21,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -44,7 +45,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include "sam9_smc.h"
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index b7b8390e8a00..0a8fe6a1b7c8 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -20,6 +20,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -37,7 +38,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91rm9200_mc.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index 81f911033681..938cc390bea3 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -21,6 +21,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -40,7 +41,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include <mach/at91_shdwc.h>
diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
index 6f08faadb474..b4ac30e38a9e 100644
--- a/arch/arm/mach-at91/board-rm9200dk.c
+++ b/arch/arm/mach-at91/board-rm9200dk.c
@@ -22,6 +22,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -39,7 +40,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91rm9200_mc.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
index 85bcccd7b9e4..99fd7f8aee0e 100644
--- a/arch/arm/mach-at91/board-rm9200ek.c
+++ b/arch/arm/mach-at91/board-rm9200ek.c
@@ -22,6 +22,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -39,7 +40,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91rm9200_mc.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
new file mode 100644
index 000000000000..e927df0175df
--- /dev/null
+++ b/arch/arm/mach-at91/board-rsi-ews.c
@@ -0,0 +1,233 @@
+/*
+ * board-rsi-ews.c
+ *
+ * Copyright (C)
+ * 2005 SAN People,
+ * 2008-2011 R-S-I Elektrotechnik GmbH & Co. KG
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+
+#include <linux/gpio.h>
+
+#include "generic.h"
+
+static void __init rsi_ews_init_early(void)
+{
+ /* Initialize processor: 18.432 MHz crystal */
+ at91_initialize(18432000);
+
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
+
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ /* This one is for debugging */
+ at91_register_uart(0, 0, 0);
+
+ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+ /* Dialin/-out modem interface */
+ at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
+ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+ | ATMEL_UART_RI);
+
+ /* USART3 on ttyS4. (Rx, Tx, RTS) */
+ /* RS485 communication */
+ at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_RTS);
+
+ /* set serial console to ttyS0 (ie, DBGU) */
+ at91_set_serial_console(0);
+}
+
+/*
+ * Ethernet
+ */
+static struct at91_eth_data rsi_ews_eth_data __initdata = {
+ .phy_irq_pin = AT91_PIN_PC4,
+ .is_rmii = 1,
+};
+
+/*
+ * USB Host
+ */
+static struct at91_usbh_data rsi_ews_usbh_data __initdata = {
+ .ports = 1,
+};
+
+/*
+ * SD/MC
+ */
+static struct at91_mmc_data rsi_ews_mmc_data __initdata = {
+ .slot_b = 0,
+ .wire4 = 1,
+ .det_pin = AT91_PIN_PB27,
+ .wp_pin = AT91_PIN_PB29,
+};
+
+/*
+ * I2C
+ */
+static struct i2c_board_info rsi_ews_i2c_devices[] __initdata = {
+ {
+ I2C_BOARD_INFO("ds1337", 0x68),
+ },
+ {
+ I2C_BOARD_INFO("24c01", 0x50),
+ }
+};
+
+/*
+ * LEDs
+ */
+static struct gpio_led rsi_ews_leds[] = {
+ {
+ .name = "led0",
+ .gpio = AT91_PIN_PB6,
+ .active_low = 0,
+ },
+ {
+ .name = "led1",
+ .gpio = AT91_PIN_PB7,
+ .active_low = 0,
+ },
+ {
+ .name = "led2",
+ .gpio = AT91_PIN_PB8,
+ .active_low = 0,
+ },
+ {
+ .name = "led3",
+ .gpio = AT91_PIN_PB9,
+ .active_low = 0,
+ },
+};
+
+/*
+ * DataFlash
+ */
+static struct spi_board_info rsi_ews_spi_devices[] = {
+ { /* DataFlash chip 1*/
+ .modalias = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 5 * 1000 * 1000,
+ },
+ { /* DataFlash chip 2*/
+ .modalias = "mtd_dataflash",
+ .chip_select = 1,
+ .max_speed_hz = 5 * 1000 * 1000,
+ },
+};
+
+/*
+ * NOR flash
+ */
+static struct mtd_partition rsiews_nor_partitions[] = {
+ {
+ .name = "boot",
+ .offset = 0,
+ .size = 3 * SZ_128K,
+ .mask_flags = MTD_WRITEABLE
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_2M - (3 * SZ_128K)
+ },
+ {
+ .name = "root",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_8M
+ },
+ {
+ .name = "kernelupd",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 3 * SZ_512K,
+ .mask_flags = MTD_WRITEABLE
+ },
+ {
+ .name = "rootupd",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 9 * SZ_512K,
+ .mask_flags = MTD_WRITEABLE
+ },
+};
+
+static struct physmap_flash_data rsiews_nor_data = {
+ .width = 2,
+ .parts = rsiews_nor_partitions,
+ .nr_parts = ARRAY_SIZE(rsiews_nor_partitions),
+};
+
+#define NOR_BASE AT91_CHIPSELECT_0
+#define NOR_SIZE SZ_16M
+
+static struct resource nor_flash_resources[] = {
+ {
+ .start = NOR_BASE,
+ .end = NOR_BASE + NOR_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device rsiews_nor_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &rsiews_nor_data,
+ },
+ .resource = nor_flash_resources,
+ .num_resources = ARRAY_SIZE(nor_flash_resources),
+};
+
+/*
+ * Init Func
+ */
+static void __init rsi_ews_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ at91_set_gpio_output(AT91_PIN_PA21, 0);
+ /* Ethernet */
+ at91_add_device_eth(&rsi_ews_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&rsi_ews_usbh_data);
+ /* I2C */
+ at91_add_device_i2c(rsi_ews_i2c_devices,
+ ARRAY_SIZE(rsi_ews_i2c_devices));
+ /* SPI */
+ at91_add_device_spi(rsi_ews_spi_devices,
+ ARRAY_SIZE(rsi_ews_spi_devices));
+ /* MMC */
+ at91_add_device_mmc(0, &rsi_ews_mmc_data);
+ /* NOR Flash */
+ platform_device_register(&rsiews_nor_flash);
+ /* LEDs */
+ at91_gpio_leds(rsi_ews_leds, ARRAY_SIZE(rsi_ews_leds));
+}
+
+MACHINE_START(RSI_EWS, "RSI EWS")
+ /* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */
+ .timer = &at91rm9200_timer,
+ .map_io = at91_map_io,
+ .init_early = rsi_ews_init_early,
+ .init_irq = at91_init_irq_default,
+ .init_machine = rsi_ews_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index 4d3a02f1289e..2a21e790250e 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -21,6 +21,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -37,7 +38,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include "sam9_smc.h"
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index 8a50c3e67186..89c8b579bfda 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -20,6 +20,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -41,7 +42,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include <mach/at91_shdwc.h>
#include <mach/system_rev.h>
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 5096a0ec50c1..3741f43cdae9 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -20,6 +20,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -45,7 +46,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include <mach/at91_shdwc.h>
#include <mach/system_rev.h>
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index ea8f185d3b9d..a580dd451a41 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -20,6 +20,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -44,7 +45,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include <mach/at91_shdwc.h>
#include <mach/system_rev.h>
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 817f59d7251b..8d77c2ff96b2 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -18,6 +18,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -41,7 +42,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include <mach/system_rev.h>
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index ad234ccbf57e..2d6203ac1a42 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -14,6 +14,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -38,7 +39,6 @@
#include <asm/mach/irq.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include <mach/at91_shdwc.h>
#include <mach/system_rev.h>
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 4f14b54b93a8..39a28effc3df 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -8,6 +8,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -30,7 +31,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include <mach/at91_shdwc.h>
diff --git a/arch/arm/mach-at91/board-usb-a9260.c b/arch/arm/mach-at91/board-usb-a9260.c
deleted file mode 100644
index 8c4c1a02c4be..000000000000
--- a/arch/arm/mach-at91/board-usb-a9260.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-usb-a9260.c
- *
- * Copyright (C) 2005 SAN People
- * Copyright (C) 2006 Atmel
- * Copyright (C) 2007 Calao-systems
- *
- * 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/clk.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/gpio.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
-
-#include "sam9_smc.h"
-#include "generic.h"
-
-
-static void __init ek_init_early(void)
-{
- /* Initialize processor: 12.000 MHz crystal */
- at91_initialize(12000000);
-
- /* DBGU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
- .ports = 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
- .vbus_pin = AT91_PIN_PC5,
- .pullup_pin = 0, /* pull-up driven by UDC */
-};
-
-/*
- * MACB Ethernet device
- */
-static struct at91_eth_data __initdata ek_macb_data = {
- .phy_irq_pin = AT91_PIN_PA31,
- .is_rmii = 1,
-};
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
- {
- .name = "Uboot & Kernel",
- .offset = 0,
- .size = SZ_16M,
- },
- {
- .name = "Root FS",
- .offset = MTDPART_OFS_NXTBLK,
- .size = 120 * SZ_1M,
- },
- {
- .name = "FS",
- .offset = MTDPART_OFS_NXTBLK,
- .size = 120 * SZ_1M,
- }
-};
-
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
- *num_partitions = ARRAY_SIZE(ek_nand_partition);
- return ek_nand_partition;
-}
-
-static struct atmel_nand_data __initdata ek_nand_data = {
- .ale = 21,
- .cle = 22,
-// .det_pin = ... not connected
- .rdy_pin = AT91_PIN_PC13,
- .enable_pin = AT91_PIN_PC14,
- .partition_info = nand_partitions,
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
- .ncs_read_setup = 0,
- .nrd_setup = 1,
- .ncs_write_setup = 0,
- .nwe_setup = 1,
-
- .ncs_read_pulse = 3,
- .nrd_pulse = 3,
- .ncs_write_pulse = 3,
- .nwe_pulse = 3,
-
- .read_cycle = 5,
- .write_cycle = 5,
-
- .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
- .tdf_cycles = 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
- /* configure chip-select 3 (NAND) */
- sam9_smc_configure(3, &ek_nand_smc_config);
-
- at91_add_device_nand(&ek_nand_data);
-}
-
-/*
- * GPIO Buttons
- */
-
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
- { /* USER PUSH BUTTON */
- .code = KEY_ENTER,
- .gpio = AT91_PIN_PB10,
- .active_low = 1,
- .desc = "user_pb",
- .wakeup = 1,
- }
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
- .buttons = ek_buttons,
- .nbuttons = ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
- .name = "gpio-keys",
- .id = -1,
- .num_resources = 0,
- .dev = {
- .platform_data = &ek_button_data,
- }
-};
-
-static void __init ek_add_device_buttons(void)
-{
- at91_set_GPIO_periph(AT91_PIN_PB10, 1); /* user push button, pull up enabled */
- at91_set_deglitch(AT91_PIN_PB10, 1);
-
- platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
- { /* user_led (green) */
- .name = "user_led",
- .gpio = AT91_PIN_PB21,
- .active_low = 0,
- .default_trigger = "heartbeat",
- }
-};
-
-static void __init ek_board_init(void)
-{
- /* Serial */
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&ek_usbh_data);
- /* USB Device */
- at91_add_device_udc(&ek_udc_data);
- /* NAND */
- ek_add_device_nand();
- /* I2C */
- at91_add_device_i2c(NULL, 0);
- /* Ethernet */
- at91_add_device_eth(&ek_macb_data);
- /* Push Buttons */
- ek_add_device_buttons();
- /* LEDs */
- at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
- /* shutdown controller, wakeup button (5 msec low) */
- at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10) | AT91_SHDW_WKMODE0_LOW
- | AT91_SHDW_RTTWKEN);
-}
-
-MACHINE_START(USB_A9260, "CALAO USB_A9260")
- /* Maintainer: calao-systems */
- .timer = &at91sam926x_timer,
- .map_io = at91_map_io,
- .init_early = ek_init_early,
- .init_irq = at91_init_irq_default,
- .init_machine = ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-usb-a9263.c b/arch/arm/mach-at91/board-usb-a926x.c
index 25e793782a4e..5852d3d9890c 100644
--- a/arch/arm/mach-at91/board-usb-a9263.c
+++ b/arch/arm/mach-at91/board-usb-a926x.c
@@ -1,9 +1,10 @@
/*
- * linux/arch/arm/mach-at91/board-usb-a9263.c
+ * linux/arch/arm/mach-at91/board-usb-a926x.c
*
* Copyright (C) 2005 SAN People
* Copyright (C) 2007 Atmel Corporation.
* Copyright (C) 2007 Calao-systems
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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
@@ -27,7 +28,9 @@
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
#include <linux/input.h>
+#include <linux/spi/mmc_spi.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
@@ -39,7 +42,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91sam9_smc.h>
#include <mach/at91_shdwc.h>
@@ -74,10 +76,42 @@ static struct at91_udc_data __initdata ek_udc_data = {
.pullup_pin = 0, /* pull-up driven by UDC */
};
+static void __init ek_add_device_udc(void)
+{
+ if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+ ek_udc_data.vbus_pin = AT91_PIN_PC5;
+
+ at91_add_device_udc(&ek_udc_data);
+}
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+#define MMC_SPI_CARD_DETECT_INT AT91_PIN_PC4
+static int at91_mmc_spi_init(struct device *dev,
+ irqreturn_t (*detect_int)(int, void *), void *data)
+{
+ /* Configure Interrupt pin as input, no pull-up */
+ at91_set_gpio_input(MMC_SPI_CARD_DETECT_INT, 0);
+ return request_irq(gpio_to_irq(MMC_SPI_CARD_DETECT_INT), detect_int,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "mmc-spi-detect", data);
+}
+
+static void at91_mmc_spi_exit(struct device *dev, void *data)
+{
+ free_irq(gpio_to_irq(MMC_SPI_CARD_DETECT_INT), data);
+}
+
+static struct mmc_spi_platform_data at91_mmc_spi_pdata = {
+ .init = at91_mmc_spi_init,
+ .exit = at91_mmc_spi_exit,
+ .detect_delay = 100, /* msecs */
+};
+#endif
+
/*
* SPI devices.
*/
-static struct spi_board_info ek_spi_devices[] = {
+static struct spi_board_info usb_a9263_spi_devices[] = {
#if !defined(CONFIG_MMC_AT91)
{ /* DataFlash chip */
.modalias = "mtd_dataflash",
@@ -88,6 +122,27 @@ static struct spi_board_info ek_spi_devices[] = {
#endif
};
+static struct spi_board_info usb_a9g20_spi_devices[] = {
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+ {
+ .modalias = "mmc_spi",
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 0,
+ .platform_data = &at91_mmc_spi_pdata,
+ .mode = SPI_MODE_3,
+ },
+#endif
+};
+
+static void __init ek_add_device_spi(void)
+{
+ if (machine_is_usb_a9263())
+ at91_add_device_spi(usb_a9263_spi_devices, ARRAY_SIZE(usb_a9263_spi_devices));
+ else if (machine_is_usb_a9g20())
+ at91_add_device_spi(usb_a9g20_spi_devices, ARRAY_SIZE(usb_a9g20_spi_devices));
+}
+
/*
* MACB Ethernet device
*/
@@ -96,24 +151,42 @@ static struct at91_eth_data __initdata ek_macb_data = {
.is_rmii = 1,
};
+static void __init ek_add_device_eth(void)
+{
+ if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+ ek_macb_data.phy_irq_pin = AT91_PIN_PA31;
+
+ at91_add_device_eth(&ek_macb_data);
+}
+
/*
* NAND flash
*/
static struct mtd_partition __initdata ek_nand_partition[] = {
{
- .name = "Linux Kernel",
+ .name = "barebox",
.offset = 0,
- .size = SZ_16M,
- },
- {
- .name = "Root FS",
+ .size = 3 * SZ_128K,
+ }, {
+ .name = "bareboxenv",
.offset = MTDPART_OFS_NXTBLK,
- .size = 120 * SZ_1M,
- },
- {
- .name = "FS",
+ .size = SZ_128K,
+ }, {
+ .name = "bareboxenv2",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_128K,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 4 * SZ_1M,
+ }, {
+ .name = "rootfs",
.offset = MTDPART_OFS_NXTBLK,
.size = 120 * SZ_1M,
+ }, {
+ .name = "data",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL,
}
};
@@ -132,7 +205,7 @@ static struct atmel_nand_data __initdata ek_nand_data = {
.partition_info = nand_partitions,
};
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
+static struct sam9_smc_config __initdata usb_a9260_nand_smc_config = {
.ncs_read_setup = 0,
.nrd_setup = 1,
.ncs_write_setup = 0,
@@ -150,10 +223,36 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
.tdf_cycles = 2,
};
+static struct sam9_smc_config __initdata usb_a9g20_nand_smc_config = {
+ .ncs_read_setup = 0,
+ .nrd_setup = 2,
+ .ncs_write_setup = 0,
+ .nwe_setup = 2,
+
+ .ncs_read_pulse = 4,
+ .nrd_pulse = 4,
+ .ncs_write_pulse = 4,
+ .nwe_pulse = 4,
+
+ .read_cycle = 7,
+ .write_cycle = 7,
+
+ .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
+ .tdf_cycles = 3,
+};
+
static void __init ek_add_device_nand(void)
{
+ if (machine_is_usb_a9260() || machine_is_usb_a9g20()) {
+ ek_nand_data.rdy_pin = AT91_PIN_PC13;
+ ek_nand_data.enable_pin = AT91_PIN_PC14;
+ }
+
/* configure chip-select 3 (NAND) */
- sam9_smc_configure(3, &ek_nand_smc_config);
+ if (machine_is_usb_a9g20())
+ sam9_smc_configure(3, &usb_a9g20_nand_smc_config);
+ else
+ sam9_smc_configure(3, &usb_a9260_nand_smc_config);
at91_add_device_nand(&ek_nand_data);
}
@@ -210,6 +309,19 @@ static struct gpio_led ek_leds[] = {
}
};
+static struct i2c_board_info __initdata ek_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("rv3029c2", 0x56),
+ },
+};
+
+static void __init ek_add_device_leds(void)
+{
+ if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+ ek_leds[0].active_low = 0;
+
+ at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+}
static void __init ek_board_init(void)
{
@@ -218,22 +330,29 @@ static void __init ek_board_init(void)
/* USB Host */
at91_add_device_usbh(&ek_usbh_data);
/* USB Device */
- at91_add_device_udc(&ek_udc_data);
+ ek_add_device_udc();
/* SPI */
- at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+ ek_add_device_spi();
/* Ethernet */
- at91_add_device_eth(&ek_macb_data);
+ ek_add_device_eth();
/* NAND */
ek_add_device_nand();
- /* I2C */
- at91_add_device_i2c(NULL, 0);
/* Push Buttons */
ek_add_device_buttons();
/* LEDs */
- at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
- /* shutdown controller, wakeup button (5 msec low) */
- at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10) | AT91_SHDW_WKMODE0_LOW
+ ek_add_device_leds();
+
+ if (machine_is_usb_a9g20()) {
+ /* I2C */
+ at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
+ } else {
+ /* I2C */
+ at91_add_device_i2c(NULL, 0);
+ /* shutdown controller, wakeup button (5 msec low) */
+ at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10)
+ | AT91_SHDW_WKMODE0_LOW
| AT91_SHDW_RTTWKEN);
+ }
}
MACHINE_START(USB_A9263, "CALAO USB_A9263")
@@ -244,3 +363,21 @@ MACHINE_START(USB_A9263, "CALAO USB_A9263")
.init_irq = at91_init_irq_default,
.init_machine = ek_board_init,
MACHINE_END
+
+MACHINE_START(USB_A9260, "CALAO USB_A9260")
+ /* Maintainer: calao-systems */
+ .timer = &at91sam926x_timer,
+ .map_io = at91_map_io,
+ .init_early = ek_init_early,
+ .init_irq = at91_init_irq_default,
+ .init_machine = ek_board_init,
+MACHINE_END
+
+MACHINE_START(USB_A9G20, "CALAO USB_A92G0")
+ /* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */
+ .timer = &at91sam926x_timer,
+ .map_io = at91_map_io,
+ .init_early = ek_init_early,
+ .init_irq = at91_init_irq_default,
+ .init_machine = ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index 95edcbd2aec6..3c288b396fc4 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -22,6 +22,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -43,7 +44,6 @@
#include <mach/hardware.h>
#include <mach/board.h>
-#include <mach/gpio.h>
#include <mach/at91rm9200_mc.h>
#include <mach/cpu.h>
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index 4615528205c8..224e9e2f8674 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -11,6 +11,7 @@
#include <linux/clk.h>
#include <linux/errno.h>
+#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/debugfs.h>
@@ -22,9 +23,6 @@
#include <mach/hardware.h>
#include <mach/at91_pio.h>
-#include <mach/gpio.h>
-
-#include <asm/gpio.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h
index 2c611b9a0138..406bb6496805 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9g45.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h
@@ -128,8 +128,6 @@
#define AT91SAM9G45_EHCI_BASE 0x00800000 /* USB Host controller (EHCI) */
#define AT91SAM9G45_VDEC_BASE 0x00900000 /* Video Decoder Controller */
-#define CONSISTENT_DMA_SIZE SZ_4M
-
/*
* DMA peripheral identifiers
* for hardware handshaking interface
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index ed544a0d5a1d..d07767f4052e 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -98,6 +98,11 @@ extern void __init at91_add_device_eth(struct at91_eth_data *data);
struct at91_usbh_data {
u8 ports; /* number of ports on root hub */
u8 vbus_pin[2]; /* port power-control pin */
+ u8 vbus_pin_inverted;
+ u8 overcurrent_supported;
+ u8 overcurrent_pin[2];
+ u8 overcurrent_status[2];
+ u8 overcurrent_changed[2];
};
extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
diff --git a/arch/arm/mach-at91/include/mach/debug-macro.S b/arch/arm/mach-at91/include/mach/debug-macro.S
index bc1e0b2e2f4f..0ed8648c6452 100644
--- a/arch/arm/mach-at91/include/mach/debug-macro.S
+++ b/arch/arm/mach-at91/include/mach/debug-macro.S
@@ -14,7 +14,7 @@
#include <mach/hardware.h>
#include <mach/at91_dbgu.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =(AT91_BASE_SYS + AT91_DBGU) @ System peripherals (phys address)
ldr \rv, =(AT91_VA_BASE_SYS + AT91_DBGU) @ System peripherals (virt address)
.endm
diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h
index 056dc6674b6b..2b9a1f51210f 100644
--- a/arch/arm/mach-at91/include/mach/gpio.h
+++ b/arch/arm/mach-at91/include/mach/gpio.h
@@ -214,11 +214,6 @@ extern void at91_gpio_resume(void);
*/
#include <asm/errno.h>
-#include <asm-generic/gpio.h> /* cansleep wrappers */
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq(gpio) (gpio)
#define irq_to_gpio(irq) (irq)
diff --git a/arch/arm/mach-at91/include/mach/timex.h b/arch/arm/mach-at91/include/mach/timex.h
index 31ac2d97f14c..85820ad801cc 100644
--- a/arch/arm/mach-at91/include/mach/timex.h
+++ b/arch/arm/mach-at91/include/mach/timex.h
@@ -64,7 +64,12 @@
#elif defined(CONFIG_ARCH_AT91SAM9G20)
+#if defined(CONFIG_MACH_USB_A9G20)
+#define AT91SAM9_MASTER_CLOCK 133000000
+#else
#define AT91SAM9_MASTER_CLOCK 132096000
+#endif
+
#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16)
#elif defined(CONFIG_ARCH_AT91SAM9G45)
diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c
index 0415a839e1ad..8dfafe76ffe6 100644
--- a/arch/arm/mach-at91/leds.c
+++ b/arch/arm/mach-at91/leds.c
@@ -9,13 +9,13 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <mach/board.h>
-#include <mach/gpio.h>
/* ------------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 4159eca78945..7046158109d7 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -10,6 +10,7 @@
* (at your option) any later version.
*/
+#include <linux/gpio.h>
#include <linux/suspend.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
@@ -25,7 +26,6 @@
#include <asm/mach/irq.h>
#include <mach/at91_pmc.h>
-#include <mach/gpio.h>
#include <mach/cpu.h>
#include "generic.h"
diff --git a/arch/arm/mach-bcmring/Kconfig b/arch/arm/mach-bcmring/Kconfig
index 457b4384913e..9170d16dca50 100644
--- a/arch/arm/mach-bcmring/Kconfig
+++ b/arch/arm/mach-bcmring/Kconfig
@@ -17,5 +17,3 @@ config BCM_ZRELADDR
hex "Compressed ZREL ADDR"
endmenu
-
-# source "drivers/char/bcmring/Kconfig"
diff --git a/arch/arm/mach-bcmring/Makefile.boot b/arch/arm/mach-bcmring/Makefile.boot
index fb53b283bebb..aef2467757fa 100644
--- a/arch/arm/mach-bcmring/Makefile.boot
+++ b/arch/arm/mach-bcmring/Makefile.boot
@@ -1,6 +1,6 @@
# Address where decompressor will be written and eventually executed.
#
# default to SDRAM
-zreladdr-y := $(CONFIG_BCM_ZRELADDR)
+zreladdr-y += $(CONFIG_BCM_ZRELADDR)
params_phys-y := 0x00000800
diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c
index a604b9ebb501..31a143592c81 100644
--- a/arch/arm/mach-bcmring/arch.c
+++ b/arch/arm/mach-bcmring/arch.c
@@ -136,8 +136,8 @@ static void __init bcmring_init_machine(void)
*
*****************************************************************************/
-static void __init bcmring_fixup(struct machine_desc *desc,
- struct tag *t, char **cmdline, struct meminfo *mi) {
+static void __init bcmring_fixup(struct tag *t, char **cmdline,
+ struct meminfo *mi) {
#ifdef CONFIG_BLK_DEV_INITRD
printk(KERN_NOTICE "bcmring_fixup\n");
t->hdr.tag = ATAG_CORE;
diff --git a/arch/arm/mach-bcmring/include/mach/hardware.h b/arch/arm/mach-bcmring/include/mach/hardware.h
index ed78aabb8e9f..6ae20a649a97 100644
--- a/arch/arm/mach-bcmring/include/mach/hardware.h
+++ b/arch/arm/mach-bcmring/include/mach/hardware.h
@@ -22,7 +22,6 @@
#define __ASM_ARCH_HARDWARE_H
#include <asm/sizes.h>
-#include <mach/memory.h>
#include <cfg_global.h>
#include <mach/csp/mm_io.h>
@@ -31,7 +30,7 @@
* *_SIZE is the size of the region
* *_BASE is the virtual address
*/
-#define RAM_START PLAT_PHYS_OFFSET
+#define RAM_START PHYS_OFFSET
#define RAM_SIZE (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED)
#define RAM_BASE PAGE_OFFSET
diff --git a/arch/arm/mach-bcmring/include/mach/memory.h b/arch/arm/mach-bcmring/include/mach/memory.h
deleted file mode 100644
index 15162e4c75f9..000000000000
--- a/arch/arm/mach-bcmring/include/mach/memory.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*****************************************************************************
-* Copyright 2005 - 2008 Broadcom Corporation. All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <cfg_global.h>
-
-/*
- * Physical vs virtual RAM address space conversion. These are
- * private definitions which should NOT be used outside memory.h
- * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
- */
-
-#define PLAT_PHYS_OFFSET CFG_GLOBAL_RAM_BASE
-
-/*
- * Maximum DMA memory allowed is 14M
- */
-#define CONSISTENT_DMA_SIZE (SZ_16M - SZ_2M)
-
-#endif
diff --git a/arch/arm/mach-bcmring/irq.c b/arch/arm/mach-bcmring/irq.c
index c48feaf4e8e9..437fa683bcb2 100644
--- a/arch/arm/mach-bcmring/irq.c
+++ b/arch/arm/mach-bcmring/irq.c
@@ -20,7 +20,6 @@
#include <linux/stddef.h>
#include <linux/list.h>
#include <linux/timer.h>
-#include <linux/version.h>
#include <linux/io.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-bcmring/mm.c b/arch/arm/mach-bcmring/mm.c
index 0f1c37e4523a..8616876abb9f 100644
--- a/arch/arm/mach-bcmring/mm.c
+++ b/arch/arm/mach-bcmring/mm.c
@@ -13,6 +13,7 @@
*****************************************************************************/
#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
#include <asm/mach/map.h>
#include <mach/hardware.h>
@@ -53,4 +54,6 @@ void __init bcmring_map_io(void)
{
iotable_init(bcmring_io_desc, ARRAY_SIZE(bcmring_io_desc));
+ /* Maximum DMA memory allowed is 14M */
+ init_consistent_dma_size(14 << 20);
}
diff --git a/arch/arm/mach-bcmring/timer.c b/arch/arm/mach-bcmring/timer.c
index 2d415d2a8e68..af9c3d7e2a0c 100644
--- a/arch/arm/mach-bcmring/timer.c
+++ b/arch/arm/mach-bcmring/timer.c
@@ -12,7 +12,6 @@
* consent.
*****************************************************************************/
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/module.h>
#include <csp/tmrHw.h>
diff --git a/arch/arm/mach-clps711x/Makefile.boot b/arch/arm/mach-clps711x/Makefile.boot
index a51fcef64fe0..9398e859b5af 100644
--- a/arch/arm/mach-clps711x/Makefile.boot
+++ b/arch/arm/mach-clps711x/Makefile.boot
@@ -1,5 +1,5 @@
# The standard locations for stuff on CLPS711x type processors
- zreladdr-y := 0xc0028000
+ zreladdr-y += 0xc0028000
params_phys-y := 0xc0000100
# Should probably have some agreement on these...
initrd_phys-$(CONFIG_ARCH_P720T) := 0xc0400000
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
index 4a74b2c959bd..0276091b7f86 100644
--- a/arch/arm/mach-clps711x/autcpu12.c
+++ b/arch/arm/mach-clps711x/autcpu12.c
@@ -64,7 +64,7 @@ void __init autcpu12_map_io(void)
MACHINE_START(AUTCPU12, "autronix autcpu12")
/* Maintainer: Thomas Gleixner */
- .boot_params = 0xc0020000,
+ .atag_offset = 0x20000,
.map_io = autcpu12_map_io,
.init_irq = clps711x_init_irq,
.timer = &clps711x_timer,
diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
index 5a1689d48793..25b3bfd0e85a 100644
--- a/arch/arm/mach-clps711x/cdb89712.c
+++ b/arch/arm/mach-clps711x/cdb89712.c
@@ -55,7 +55,7 @@ static void __init cdb89712_map_io(void)
MACHINE_START(CDB89712, "Cirrus-CDB89712")
/* Maintainer: Ray Lehtiniemi */
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.map_io = cdb89712_map_io,
.init_irq = clps711x_init_irq,
.timer = &clps711x_timer,
diff --git a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c
index 16481cf3e931..1df9ec67aa92 100644
--- a/arch/arm/mach-clps711x/ceiva.c
+++ b/arch/arm/mach-clps711x/ceiva.c
@@ -56,7 +56,7 @@ static void __init ceiva_map_io(void)
MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame")
/* Maintainer: Rob Scott */
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.map_io = ceiva_map_io,
.init_irq = clps711x_init_irq,
.timer = &clps711x_timer,
diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c
index 67b5abb4a60a..80496c09ac59 100644
--- a/arch/arm/mach-clps711x/clep7312.c
+++ b/arch/arm/mach-clps711x/clep7312.c
@@ -26,8 +26,7 @@
#include "common.h"
static void __init
-fixup_clep7312(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+fixup_clep7312(struct tag *tags, char **cmdline, struct meminfo *mi)
{
mi->nr_banks=1;
mi->bank[0].start = 0xc0000000;
@@ -37,7 +36,7 @@ fixup_clep7312(struct machine_desc *desc, struct tag *tags,
MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
/* Maintainer: Nobody */
- .boot_params = 0xc0000100,
+ .atag_offset = 0x0100,
.fixup = fixup_clep7312,
.map_io = clps711x_map_io,
.init_irq = clps711x_init_irq,
diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c
index 98ca5b2e940d..9721f6111dc0 100644
--- a/arch/arm/mach-clps711x/edb7211-arch.c
+++ b/arch/arm/mach-clps711x/edb7211-arch.c
@@ -37,8 +37,7 @@ static void __init edb7211_reserve(void)
}
static void __init
-fixup_edb7211(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+fixup_edb7211(struct tag *tags, char **cmdline, struct meminfo *mi)
{
/*
* Bank start addresses are not present in the information
@@ -57,7 +56,7 @@ fixup_edb7211(struct machine_desc *desc, struct tag *tags,
MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
/* Maintainer: Jon McClintock */
- .boot_params = 0xc0020100, /* 0xc0000000 - 0xc001ffff can be video RAM */
+ .atag_offset = 0x20100, /* 0xc0000000 - 0xc001ffff can be video RAM */
.fixup = fixup_edb7211,
.map_io = edb7211_map_io,
.reserve = edb7211_reserve,
diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c
index b1cb479e71e9..d99256687298 100644
--- a/arch/arm/mach-clps711x/fortunet.c
+++ b/arch/arm/mach-clps711x/fortunet.c
@@ -57,8 +57,7 @@ typedef struct tag_IMAGE_PARAMS
#define IMAGE_PARAMS_PHYS 0xC01F0000
static void __init
-fortunet_fixup(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+fortunet_fixup(struct tag *tags, char **cmdline, struct meminfo *mi)
{
IMAGE_PARAMS *ip = phys_to_virt(IMAGE_PARAMS_PHYS);
*cmdline = phys_to_virt(ip->command_line);
@@ -75,7 +74,6 @@ fortunet_fixup(struct machine_desc *desc, struct tag *tags,
MACHINE_START(FORTUNET, "ARM-FortuNet")
/* Maintainer: FortuNet Inc. */
- .boot_params = 0x00000000,
.fixup = fortunet_fixup,
.map_io = clps711x_map_io,
.init_irq = clps711x_init_irq,
diff --git a/arch/arm/mach-clps711x/include/mach/debug-macro.S b/arch/arm/mach-clps711x/include/mach/debug-macro.S
index 507c6873b7ee..b802e8a51831 100644
--- a/arch/arm/mach-clps711x/include/mach/debug-macro.S
+++ b/arch/arm/mach-clps711x/include/mach/debug-macro.S
@@ -14,7 +14,7 @@
#include <mach/hardware.h>
#include <asm/hardware/clps7111.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
#ifndef CONFIG_DEBUG_CLPS711X_UART2
mov \rp, #0x0000 @ UART1
#else
diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
index cefbce0480b9..6ecea95f38b2 100644
--- a/arch/arm/mach-clps711x/p720t.c
+++ b/arch/arm/mach-clps711x/p720t.c
@@ -56,8 +56,7 @@ static struct map_desc p720t_io_desc[] __initdata = {
};
static void __init
-fixup_p720t(struct machine_desc *desc, struct tag *tag,
- char **cmdline, struct meminfo *mi)
+fixup_p720t(struct tag *tag, char **cmdline, struct meminfo *mi)
{
/*
* Our bootloader doesn't setup any tags (yet).
@@ -89,7 +88,7 @@ static void __init p720t_map_io(void)
MACHINE_START(P720T, "ARM-Prospector720T")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.fixup = fixup_p720t,
.map_io = p720t_map_io,
.init_irq = clps711x_init_irq,
diff --git a/arch/arm/mach-cns3xxx/Makefile.boot b/arch/arm/mach-cns3xxx/Makefile.boot
index 777012865220..d079de0b6e3b 100644
--- a/arch/arm/mach-cns3xxx/Makefile.boot
+++ b/arch/arm/mach-cns3xxx/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00C00000
diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index 3e7d1496cb47..55f7b4b08ab9 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -197,7 +197,7 @@ static void __init cns3420_map_io(void)
}
MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = cns3420_map_io,
.init_irq = cns3xxx_init_irq,
.timer = &cns3xxx_timer,
diff --git a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
index 56d828634db5..d04c150baa1c 100644
--- a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
+++ b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
@@ -10,7 +10,7 @@
* published by the Free Software Foundation.
*/
- .macro addruart,rp,rv
+ .macro addruart,rp,rv,tmp
mov \rp, #0x00009000
orr \rv, \rp, #0xf0000000 @ virtual base
orr \rp, \rp, #0x10000000
diff --git a/arch/arm/mach-cns3xxx/include/mach/memory.h b/arch/arm/mach-cns3xxx/include/mach/memory.h
deleted file mode 100644
index dc16c5c5d86b..000000000000
--- a/arch/arm/mach-cns3xxx/include/mach/memory.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2003 ARM Limited
- * Copyright 2008 Cavium Networks
- *
- * This file 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 __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#define __phys_to_bus(x) ((x) + PHYS_OFFSET)
-#define __bus_to_phys(x) ((x) - PHYS_OFFSET)
-
-#define __virt_to_bus(v) __phys_to_bus(__virt_to_phys(v))
-#define __bus_to_virt(b) __phys_to_virt(__bus_to_phys(b))
-#define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p))
-#define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b))
-
-#endif
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index c0deacae778d..32d837d8eab9 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -192,6 +192,16 @@ config DA850_UI_RMII
endchoice
+config DA850_WL12XX
+ bool "AM18x wl1271 daughter board"
+ depends on MACH_DAVINCI_DA850_EVM
+ help
+ The wl1271 daughter card for AM18x EVMs is a combo wireless
+ connectivity add-on card, based on the LS Research TiWi module with
+ Texas Instruments' wl1271 solution.
+ Say Y if you want to use a wl1271 expansion card connected to the
+ AM18x EVM.
+
config GPIO_PCA953X
default MACH_DAVINCI_DA850_EVM
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index 0b87a1ca2bb3..495e31306fc0 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -5,7 +5,7 @@
# Common objects
obj-y := time.o clock.o serial.o io.o psc.o \
- gpio.o dma.o usb.o common.o sram.o aemif.o
+ dma.o usb.o common.o sram.o aemif.o
obj-$(CONFIG_DAVINCI_MUX) += mux.o
@@ -17,7 +17,6 @@ obj-$(CONFIG_ARCH_DAVINCI_DM365) += dm365.o devices.o
obj-$(CONFIG_ARCH_DAVINCI_DA830) += da830.o devices-da8xx.o
obj-$(CONFIG_ARCH_DAVINCI_DA850) += da850.o devices-da8xx.o
obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += tnetv107x.o devices-tnetv107x.o
-obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
obj-$(CONFIG_AINTC) += irq.o
obj-$(CONFIG_CP_INTC) += cp_intc.o
diff --git a/arch/arm/mach-davinci/Makefile.boot b/arch/arm/mach-davinci/Makefile.boot
index db97ef2c6477..04a6c4e67b14 100644
--- a/arch/arm/mach-davinci/Makefile.boot
+++ b/arch/arm/mach-davinci/Makefile.boot
@@ -2,12 +2,12 @@ ifeq ($(CONFIG_ARCH_DAVINCI_DA8XX),y)
ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y)
$(error Cannot enable DaVinci and DA8XX platforms concurrently)
else
- zreladdr-y := 0xc0008000
+ zreladdr-y += 0xc0008000
params_phys-y := 0xc0000100
initrd_phys-y := 0xc0800000
endif
else
- zreladdr-y := 0x80008000
+ zreladdr-y += 0x80008000
params_phys-y := 0x80000100
initrd_phys-y := 0x80800000
endif
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 84fd78684868..26d94c0b555c 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -676,7 +676,7 @@ static void __init da830_evm_map_io(void)
}
MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
- .boot_params = (DA8XX_DDR_BASE + 0x100),
+ .atag_offset = 0x100,
.map_io = da830_evm_map_io,
.init_irq = cp_intc_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 008d51407cd7..ec21663f8ddc 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -31,6 +31,8 @@
#include <linux/input/tps6507x-ts.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
+#include <linux/delay.h>
+#include <linux/wl12xx.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -49,6 +51,9 @@
#define DA850_MMCSD_CD_PIN GPIO_TO_PIN(4, 0)
#define DA850_MMCSD_WP_PIN GPIO_TO_PIN(4, 1)
+#define DA850_WLAN_EN GPIO_TO_PIN(6, 9)
+#define DA850_WLAN_IRQ GPIO_TO_PIN(6, 10)
+
#define DA850_MII_MDIO_CLKEN_PIN GPIO_TO_PIN(2, 6)
static struct mtd_partition da850evm_spiflash_part[] = {
@@ -1143,6 +1148,110 @@ static __init int da850_evm_init_cpufreq(void)
static __init int da850_evm_init_cpufreq(void) { return 0; }
#endif
+#ifdef CONFIG_DA850_WL12XX
+
+static void wl12xx_set_power(int index, bool power_on)
+{
+ static bool power_state;
+
+ pr_debug("Powering %s wl12xx", power_on ? "on" : "off");
+
+ if (power_on == power_state)
+ return;
+ power_state = power_on;
+
+ if (power_on) {
+ /* Power up sequence required for wl127x devices */
+ gpio_set_value(DA850_WLAN_EN, 1);
+ usleep_range(15000, 15000);
+ gpio_set_value(DA850_WLAN_EN, 0);
+ usleep_range(1000, 1000);
+ gpio_set_value(DA850_WLAN_EN, 1);
+ msleep(70);
+ } else {
+ gpio_set_value(DA850_WLAN_EN, 0);
+ }
+}
+
+static struct davinci_mmc_config da850_wl12xx_mmc_config = {
+ .set_power = wl12xx_set_power,
+ .wires = 4,
+ .max_freq = 25000000,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NONREMOVABLE |
+ MMC_CAP_POWER_OFF_CARD,
+ .version = MMC_CTLR_VERSION_2,
+};
+
+static const short da850_wl12xx_pins[] __initconst = {
+ DA850_MMCSD1_DAT_0, DA850_MMCSD1_DAT_1, DA850_MMCSD1_DAT_2,
+ DA850_MMCSD1_DAT_3, DA850_MMCSD1_CLK, DA850_MMCSD1_CMD,
+ DA850_GPIO6_9, DA850_GPIO6_10,
+ -1
+};
+
+static struct wl12xx_platform_data da850_wl12xx_wlan_data __initdata = {
+ .irq = -1,
+ .board_ref_clock = WL12XX_REFCLOCK_38,
+ .platform_quirks = WL12XX_PLATFORM_QUIRK_EDGE_IRQ,
+};
+
+static __init int da850_wl12xx_init(void)
+{
+ int ret;
+
+ ret = davinci_cfg_reg_list(da850_wl12xx_pins);
+ if (ret) {
+ pr_err("wl12xx/mmc mux setup failed: %d\n", ret);
+ goto exit;
+ }
+
+ ret = da850_register_mmcsd1(&da850_wl12xx_mmc_config);
+ if (ret) {
+ pr_err("wl12xx/mmc registration failed: %d\n", ret);
+ goto exit;
+ }
+
+ ret = gpio_request_one(DA850_WLAN_EN, GPIOF_OUT_INIT_LOW, "wl12xx_en");
+ if (ret) {
+ pr_err("Could not request wl12xx enable gpio: %d\n", ret);
+ goto exit;
+ }
+
+ ret = gpio_request_one(DA850_WLAN_IRQ, GPIOF_IN, "wl12xx_irq");
+ if (ret) {
+ pr_err("Could not request wl12xx irq gpio: %d\n", ret);
+ goto free_wlan_en;
+ }
+
+ da850_wl12xx_wlan_data.irq = gpio_to_irq(DA850_WLAN_IRQ);
+
+ ret = wl12xx_set_platform_data(&da850_wl12xx_wlan_data);
+ if (ret) {
+ pr_err("Could not set wl12xx data: %d\n", ret);
+ goto free_wlan_irq;
+ }
+
+ return 0;
+
+free_wlan_irq:
+ gpio_free(DA850_WLAN_IRQ);
+
+free_wlan_en:
+ gpio_free(DA850_WLAN_EN);
+
+exit:
+ return ret;
+}
+
+#else /* CONFIG_DA850_WL12XX */
+
+static __init int da850_wl12xx_init(void)
+{
+ return 0;
+}
+
+#endif /* CONFIG_DA850_WL12XX */
+
#define DA850EVM_SATA_REFCLKPN_RATE (100 * 1000 * 1000)
static __init void da850_evm_init(void)
@@ -1197,6 +1306,11 @@ static __init void da850_evm_init(void)
if (ret)
pr_warning("da850_evm_init: mmcsd0 registration failed:"
" %d\n", ret);
+
+ ret = da850_wl12xx_init();
+ if (ret)
+ pr_warning("da850_evm_init: wl12xx initialization"
+ " failed: %d\n", ret);
}
davinci_serial_init(&da850_evm_uart_config);
@@ -1291,7 +1405,7 @@ static void __init da850_evm_map_io(void)
}
MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
- .boot_params = (DA8XX_DDR_BASE + 0x100),
+ .atag_offset = 0x100,
.map_io = da850_evm_map_io,
.init_irq = cp_intc_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index 241a6bd67408..65566280b7c9 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -351,7 +351,7 @@ static __init void dm355_evm_init(void)
}
MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
- .boot_params = (0x80000100),
+ .atag_offset = 0x100,
.map_io = dm355_evm_map_io,
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index bee284ca7fd6..b307470b071d 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -270,7 +270,7 @@ static __init void dm355_leopard_init(void)
}
MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
- .boot_params = (0x80000100),
+ .atag_offset = 0x100,
.map_io = dm355_leopard_map_io,
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 9818f214d4f0..04c43abcca66 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -612,7 +612,7 @@ static __init void dm365_evm_init(void)
}
MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
- .boot_params = (0x80000100),
+ .atag_offset = 0x100,
.map_io = dm365_evm_map_io,
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 95607a191e03..a005e7691ddd 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -712,7 +712,7 @@ static __init void davinci_evm_init(void)
MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
/* Maintainer: MontaVista Software <source@mvista.com> */
- .boot_params = (DAVINCI_DDR_BASE + 0x100),
+ .atag_offset = 0x100,
.map_io = davinci_evm_map_io,
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 993a3146fd35..337c45e3e44d 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -792,7 +792,7 @@ static __init void evm_init(void)
}
MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
- .boot_params = (0x80000100),
+ .atag_offset = 0x100,
.map_io = davinci_map_io,
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
@@ -801,7 +801,7 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
MACHINE_END
MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
- .boot_params = (0x80000100),
+ .atag_offset = 0x100,
.map_io = davinci_map_io,
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index c278226627ad..6efc84cceca0 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -566,7 +566,7 @@ static void __init mityomapl138_map_io(void)
}
MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
- .boot_params = (DA8XX_DDR_BASE + 0x100),
+ .atag_offset = 0x100,
.map_io = mityomapl138_map_io,
.init_irq = cp_intc_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index d60a80028ba3..38d6f644d8b9 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -272,7 +272,7 @@ static __init void davinci_ntosd2_init(void)
MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
/* Maintainer: Neuros Technologies <neuros@groups.google.com> */
- .boot_params = (DAVINCI_DDR_BASE + 0x100),
+ .atag_offset = 0x100,
.map_io = davinci_ntosd2_map_io,
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index 237332a11421..c6701e4a795c 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -338,7 +338,7 @@ static void __init omapl138_hawk_map_io(void)
}
MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
- .boot_params = (DA8XX_DDR_BASE + 0x100),
+ .atag_offset = 0x100,
.map_io = omapl138_hawk_map_io,
.init_irq = cp_intc_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 5f4385c0a089..5dd4da9d2308 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -151,7 +151,7 @@ static __init void davinci_sffsdr_init(void)
MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
/* Maintainer: Hugo Villeneuve hugo.villeneuve@lyrtech.com */
- .boot_params = (DAVINCI_DDR_BASE + 0x100),
+ .atag_offset = 0x100,
.map_io = davinci_sffsdr_map_io,
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index 782892065682..90ee7b5aabdc 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -277,7 +277,7 @@ console_initcall(tnetv107x_evm_console_init);
#endif
MACHINE_START(TNETV107X, "TNETV107X EVM")
- .boot_params = (TNETV107X_DDR_BASE + 0x100),
+ .atag_offset = 0x100,
.map_io = tnetv107x_init,
.init_irq = cp_intc_init,
.timer = &davinci_timer,
diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c
index 1d2557394235..865ffe5899ac 100644
--- a/arch/arm/mach-davinci/common.c
+++ b/arch/arm/mach-davinci/common.c
@@ -12,6 +12,7 @@
#include <linux/io.h>
#include <linux/etherdevice.h>
#include <linux/davinci_emac.h>
+#include <linux/dma-mapping.h>
#include <asm/tlb.h>
#include <asm/mach/map.h>
@@ -86,6 +87,8 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info)
iotable_init(davinci_soc_info.io_desc,
davinci_soc_info.io_desc_num);
+ init_consistent_dma_size(14 << 20);
+
/*
* Normally devicemaps_init() would flush caches and tlb after
* mdesc->map_io(), but we must also do it here because of the CPU
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
index bd59f31b8a95..0b314bf16f7f 100644
--- a/arch/arm/mach-davinci/cpuidle.c
+++ b/arch/arm/mach-davinci/cpuidle.c
@@ -19,7 +19,7 @@
#include <asm/proc-fns.h>
#include <mach/cpuidle.h>
-#include <mach/memory.h>
+#include <mach/ddr2.h>
#define DAVINCI_CPUIDLE_MAX_STATES 2
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index 2ed2f822fc40..a6bf5dcaef13 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -8,6 +8,7 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/clk.h>
@@ -19,7 +20,7 @@
#include <mach/common.h>
#include <mach/time.h>
#include <mach/da8xx.h>
-#include <mach/gpio.h>
+#include <mach/gpio-davinci.h>
#include "clock.h"
#include "mux.h"
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 935dbed5c541..b047f8702278 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -11,6 +11,7 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
@@ -27,7 +28,7 @@
#include <mach/da8xx.h>
#include <mach/cpufreq.h>
#include <mach/pm.h>
-#include <mach/gpio.h>
+#include <mach/gpio-davinci.h>
#include "clock.h"
#include "mux.h"
@@ -535,6 +536,13 @@ static const struct mux_config da850_pins[] = {
MUX_CFG(DA850, MMCSD0_DAT_3, 10, 20, 15, 2, false)
MUX_CFG(DA850, MMCSD0_CLK, 10, 0, 15, 2, false)
MUX_CFG(DA850, MMCSD0_CMD, 10, 4, 15, 2, false)
+ /* MMC/SD1 function */
+ MUX_CFG(DA850, MMCSD1_DAT_0, 18, 8, 15, 2, false)
+ MUX_CFG(DA850, MMCSD1_DAT_1, 19, 16, 15, 2, false)
+ MUX_CFG(DA850, MMCSD1_DAT_2, 19, 12, 15, 2, false)
+ MUX_CFG(DA850, MMCSD1_DAT_3, 19, 8, 15, 2, false)
+ MUX_CFG(DA850, MMCSD1_CLK, 18, 12, 15, 2, false)
+ MUX_CFG(DA850, MMCSD1_CMD, 18, 16, 15, 2, false)
/* EMIF2.5/EMIFA function */
MUX_CFG(DA850, EMA_D_7, 9, 0, 15, 1, false)
MUX_CFG(DA850, EMA_D_6, 9, 4, 15, 1, false)
@@ -593,6 +601,8 @@ static const struct mux_config da850_pins[] = {
MUX_CFG(DA850, GPIO3_13, 7, 8, 15, 8, false)
MUX_CFG(DA850, GPIO4_0, 10, 28, 15, 8, false)
MUX_CFG(DA850, GPIO4_1, 10, 24, 15, 8, false)
+ MUX_CFG(DA850, GPIO6_9, 13, 24, 15, 8, false)
+ MUX_CFG(DA850, GPIO6_10, 13, 20, 15, 8, false)
MUX_CFG(DA850, GPIO6_13, 13, 8, 15, 8, false)
MUX_CFG(DA850, RTC_ALARM, 0, 28, 15, 2, false)
#endif
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 2f7e719636f1..68def7188868 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -136,6 +136,7 @@ static struct edma_soc_info da830_edma_cc0_info = {
.n_cc = 1,
.queue_tc_mapping = da8xx_queue_tc_mapping,
.queue_priority_mapping = da8xx_queue_priority_mapping,
+ .default_queue = EVENTQ_1,
};
static struct edma_soc_info *da830_edma_info[EDMA_MAX_CC] = {
@@ -151,6 +152,7 @@ static struct edma_soc_info da850_edma_cc_info[] = {
.n_cc = 1,
.queue_tc_mapping = da8xx_queue_tc_mapping,
.queue_priority_mapping = da8xx_queue_priority_mapping,
+ .default_queue = EVENTQ_1,
},
{
.n_channel = 32,
@@ -160,6 +162,7 @@ static struct edma_soc_info da850_edma_cc_info[] = {
.n_cc = 1,
.queue_tc_mapping = da850_queue_tc_mapping,
.queue_priority_mapping = da850_queue_priority_mapping,
+ .default_queue = EVENTQ_0,
},
};
diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
index 6162cae7f868..29b17f7d3a5f 100644
--- a/arch/arm/mach-davinci/devices-tnetv107x.c
+++ b/arch/arm/mach-davinci/devices-tnetv107x.c
@@ -80,6 +80,7 @@ static struct edma_soc_info edma_cc0_info = {
.n_cc = 1,
.queue_tc_mapping = edma_tc_mapping,
.queue_priority_mapping = edma_priority_mapping,
+ .default_queue = EVENTQ_1,
};
static struct edma_soc_info *tnetv107x_edma_info[EDMA_MAX_CC] = {
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index a3a94e9c9378..fe520d4167a2 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -13,7 +13,6 @@
#include <linux/serial_8250.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
#include <linux/spi/spi.h>
@@ -30,6 +29,7 @@
#include <mach/common.h>
#include <mach/asp.h>
#include <mach/spi.h>
+#include <mach/gpio-davinci.h>
#include "clock.h"
#include "mux.h"
@@ -591,6 +591,7 @@ static struct edma_soc_info edma_cc0_info = {
.n_cc = 1,
.queue_tc_mapping = queue_tc_mapping,
.queue_priority_mapping = queue_priority_mapping,
+ .default_queue = EVENTQ_1,
};
static struct edma_soc_info *dm355_edma_info[EDMA_MAX_CC] = {
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 4604e72d7d99..679e168dce34 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -17,7 +17,6 @@
#include <linux/serial_8250.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <asm/mach/map.h>
@@ -34,7 +33,7 @@
#include <mach/asp.h>
#include <mach/keyscan.h>
#include <mach/spi.h>
-
+#include <mach/gpio-davinci.h>
#include "clock.h"
#include "mux.h"
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 4c82c2716293..3470983aa343 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -12,7 +12,6 @@
#include <linux/clk.h>
#include <linux/serial_8250.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
#include <asm/mach/map.h>
@@ -26,6 +25,7 @@
#include <mach/serial.h>
#include <mach/common.h>
#include <mach/asp.h>
+#include <mach/gpio-davinci.h>
#include "clock.h"
#include "mux.h"
@@ -514,6 +514,7 @@ static struct edma_soc_info edma_cc0_info = {
.n_cc = 1,
.queue_tc_mapping = queue_tc_mapping,
.queue_priority_mapping = queue_priority_mapping,
+ .default_queue = EVENTQ_1,
};
static struct edma_soc_info *dm644x_edma_info[EDMA_MAX_CC] = {
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 1802e711a2b8..0b68ed534f8e 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -13,7 +13,6 @@
#include <linux/clk.h>
#include <linux/serial_8250.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
#include <asm/mach/map.h>
@@ -27,6 +26,7 @@
#include <mach/serial.h>
#include <mach/common.h>
#include <mach/asp.h>
+#include <mach/gpio-davinci.h>
#include "clock.h"
#include "mux.h"
@@ -555,6 +555,7 @@ static struct edma_soc_info edma_cc0_info = {
.n_cc = 1,
.queue_tc_mapping = dm646x_queue_tc_mapping,
.queue_priority_mapping = dm646x_queue_priority_mapping,
+ .default_queue = EVENTQ_1,
};
static struct edma_soc_info *dm646x_edma_info[EDMA_MAX_CC] = {
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 6b9669869c46..da90103a313d 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -1435,12 +1435,11 @@ static int __init edma_probe(struct platform_device *pdev)
goto fail1;
}
- edma_cc[j] = kmalloc(sizeof(struct edma), GFP_KERNEL);
+ edma_cc[j] = kzalloc(sizeof(struct edma), GFP_KERNEL);
if (!edma_cc[j]) {
status = -ENOMEM;
goto fail1;
}
- memset(edma_cc[j], 0, sizeof(struct edma));
edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
EDMA_MAX_DMACH);
@@ -1450,8 +1449,6 @@ static int __init edma_probe(struct platform_device *pdev)
EDMA_MAX_CC);
edma_cc[j]->default_queue = info[j]->default_queue;
- if (!edma_cc[j]->default_queue)
- edma_cc[j]->default_queue = EVENTQ_1;
dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
edmacc_regs_base[j]);
diff --git a/arch/arm/mach-davinci/include/mach/ddr2.h b/arch/arm/mach-davinci/include/mach/ddr2.h
new file mode 100644
index 000000000000..c19e047d0e6a
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/ddr2.h
@@ -0,0 +1,4 @@
+#define DDR2_SDRCR_OFFSET 0xc
+#define DDR2_SRPD_BIT (1 << 23)
+#define DDR2_MCLKSTOPEN_BIT (1 << 30)
+#define DDR2_LPMODEN_BIT (1 << 31)
diff --git a/arch/arm/mach-davinci/include/mach/debug-macro.S b/arch/arm/mach-davinci/include/mach/debug-macro.S
index f8b7ea4f6235..cf94552d5274 100644
--- a/arch/arm/mach-davinci/include/mach/debug-macro.S
+++ b/arch/arm/mach-davinci/include/mach/debug-macro.S
@@ -18,56 +18,50 @@
#include <linux/serial_reg.h>
-#include <asm/memory.h>
-
#include <mach/serial.h>
#define UART_SHIFT 2
-#define davinci_uart_v2p(x) ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
-#define davinci_uart_p2v(x) ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
-
.pushsection .data
davinci_uart_phys: .word 0
davinci_uart_virt: .word 0
.popsection
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
/* Use davinci_uart_phys/virt if already configured */
-10: mrc p15, 0, \rp, c1, c0
- tst \rp, #1 @ MMU enabled?
- ldreq \rp, =davinci_uart_v2p(davinci_uart_phys)
- ldrne \rp, =davinci_uart_phys
- add \rv, \rp, #4 @ davinci_uart_virt
- ldr \rp, [\rp, #0]
- ldr \rv, [\rv, #0]
+10: adr \rp, 99f @ get effective addr of 99f
+ ldr \rv, [\rp] @ get absolute addr of 99f
+ sub \rv, \rv, \rp @ offset between the two
+ ldr \rp, [\rp, #4] @ abs addr of omap_uart_phys
+ sub \tmp, \rp, \rv @ make it effective
+ ldr \rp, [\tmp, #0] @ davinci_uart_phys
+ ldr \rv, [\tmp, #4] @ davinci_uart_virt
cmp \rp, #0 @ is port configured?
cmpne \rv, #0
- bne 99f @ already configured
+ bne 100f @ already configured
/* Check the debug UART address set in uncompress.h */
- mrc p15, 0, \rp, c1, c0
- tst \rp, #1 @ MMU enabled?
+ and \rp, pc, #0xff000000
+ ldr \rv, =DAVINCI_UART_INFO_OFS
+ add \rp, \rp, \rv
/* Copy uart phys address from decompressor uart info */
- ldreq \rv, =davinci_uart_v2p(davinci_uart_phys)
- ldrne \rv, =davinci_uart_phys
- ldreq \rp, =DAVINCI_UART_INFO
- ldrne \rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
- ldr \rp, [\rp, #0]
- str \rp, [\rv]
+ ldr \rv, [\rp, #0]
+ str \rv, [\tmp, #0]
/* Copy uart virt address from decompressor uart info */
- ldreq \rv, =davinci_uart_v2p(davinci_uart_virt)
- ldrne \rv, =davinci_uart_virt
- ldreq \rp, =DAVINCI_UART_INFO
- ldrne \rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
- ldr \rp, [\rp, #4]
- str \rp, [\rv]
+ ldr \rv, [\rp, #4]
+ str \rv, [\tmp, #4]
b 10b
-99:
+
+ .align
+99: .word .
+ .word davinci_uart_phys
+ .ltorg
+
+100:
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-davinci/include/mach/gpio-davinci.h b/arch/arm/mach-davinci/include/mach/gpio-davinci.h
new file mode 100644
index 000000000000..1fdd1fd35448
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/gpio-davinci.h
@@ -0,0 +1,91 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __DAVINCI_DAVINCI_GPIO_H
+#define __DAVINCI_DAVINCI_GPIO_H
+
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm-generic/gpio.h>
+
+#include <mach/irqs.h>
+#include <mach/common.h>
+
+#define DAVINCI_GPIO_BASE 0x01C67000
+
+enum davinci_gpio_type {
+ GPIO_TYPE_DAVINCI = 0,
+ GPIO_TYPE_TNETV107X,
+};
+
+/*
+ * basic gpio routines
+ *
+ * board-specific init should be done by arch/.../.../board-XXX.c (maybe
+ * initializing banks together) rather than boot loaders; kexec() won't
+ * go through boot loaders.
+ *
+ * the gpio clock will be turned on when gpios are used, and you may also
+ * need to pay attention to PINMUX registers to be sure those pins are
+ * used as gpios, not with other peripherals.
+ *
+ * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation,
+ * and maybe for later updates, code may write GPIO(N). These may be
+ * all 1.8V signals, all 3.3V ones, or a mix of the two. A given chip
+ * may not support all the GPIOs in that range.
+ *
+ * GPIOs can also be on external chips, numbered after the ones built-in
+ * to the DaVinci chip. For now, they won't be usable as IRQ sources.
+ */
+#define GPIO(X) (X) /* 0 <= X <= (DAVINCI_N_GPIO - 1) */
+
+/* Convert GPIO signal to GPIO pin number */
+#define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio))
+
+struct davinci_gpio_controller {
+ struct gpio_chip chip;
+ int irq_base;
+ spinlock_t lock;
+ void __iomem *regs;
+ void __iomem *set_data;
+ void __iomem *clr_data;
+ void __iomem *in_data;
+};
+
+/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
+ * with constant parameters; or in outlined code they execute at runtime.
+ *
+ * You'd access the controller directly when reading or writing more than
+ * one gpio value at a time, and to support wired logic where the value
+ * being driven by the cpu need not match the value read back.
+ *
+ * These are NOT part of the cross-platform GPIO interface
+ */
+static inline struct davinci_gpio_controller *
+__gpio_to_controller(unsigned gpio)
+{
+ struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs;
+ int index = gpio / 32;
+
+ if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num)
+ return NULL;
+
+ return ctlrs + index;
+}
+
+static inline u32 __gpio_mask(unsigned gpio)
+{
+ return 1 << (gpio % 32);
+}
+
+#endif /* __DAVINCI_DAVINCI_GPIO_H */
diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h
index fbece126c2bf..fbaae4772b91 100644
--- a/arch/arm/mach-davinci/include/mach/gpio.h
+++ b/arch/arm/mach-davinci/include/mach/gpio.h
@@ -13,80 +13,10 @@
#ifndef __DAVINCI_GPIO_H
#define __DAVINCI_GPIO_H
-#include <linux/io.h>
-#include <linux/spinlock.h>
-
#include <asm-generic/gpio.h>
-#include <mach/irqs.h>
-#include <mach/common.h>
-
-#define DAVINCI_GPIO_BASE 0x01C67000
-
-enum davinci_gpio_type {
- GPIO_TYPE_DAVINCI = 0,
- GPIO_TYPE_TNETV107X,
-};
-
-/*
- * basic gpio routines
- *
- * board-specific init should be done by arch/.../.../board-XXX.c (maybe
- * initializing banks together) rather than boot loaders; kexec() won't
- * go through boot loaders.
- *
- * the gpio clock will be turned on when gpios are used, and you may also
- * need to pay attention to PINMUX registers to be sure those pins are
- * used as gpios, not with other peripherals.
- *
- * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation,
- * and maybe for later updates, code may write GPIO(N). These may be
- * all 1.8V signals, all 3.3V ones, or a mix of the two. A given chip
- * may not support all the GPIOs in that range.
- *
- * GPIOs can also be on external chips, numbered after the ones built-in
- * to the DaVinci chip. For now, they won't be usable as IRQ sources.
- */
-#define GPIO(X) (X) /* 0 <= X <= (DAVINCI_N_GPIO - 1) */
-
-/* Convert GPIO signal to GPIO pin number */
-#define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio))
-
-struct davinci_gpio_controller {
- struct gpio_chip chip;
- int irq_base;
- spinlock_t lock;
- void __iomem *regs;
- void __iomem *set_data;
- void __iomem *clr_data;
- void __iomem *in_data;
-};
-
-/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
- * with constant parameters; or in outlined code they execute at runtime.
- *
- * You'd access the controller directly when reading or writing more than
- * one gpio value at a time, and to support wired logic where the value
- * being driven by the cpu need not match the value read back.
- *
- * These are NOT part of the cross-platform GPIO interface
- */
-static inline struct davinci_gpio_controller *
-__gpio_to_controller(unsigned gpio)
-{
- struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs;
- int index = gpio / 32;
-
- if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num)
- return NULL;
-
- return ctlrs + index;
-}
-
-static inline u32 __gpio_mask(unsigned gpio)
-{
- return 1 << (gpio % 32);
-}
+/* The inline versions use the static inlines in the driver header */
+#include "gpio-davinci.h"
/*
* The get/set/clear functions will inline when called with constant
@@ -147,11 +77,6 @@ static inline int gpio_cansleep(unsigned gpio)
return __gpio_cansleep(gpio);
}
-static inline int gpio_to_irq(unsigned gpio)
-{
- return __gpio_to_irq(gpio);
-}
-
static inline int irq_to_gpio(unsigned irq)
{
/* don't support the reverse mapping */
diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h
deleted file mode 100644
index 78731944a70c..000000000000
--- a/arch/arm/mach-davinci/include/mach/memory.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * DaVinci memory space definitions
- *
- * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
- *
- * 2007 (c) MontaVista Software, 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.
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/**************************************************************************
- * Included Files
- **************************************************************************/
-#include <asm/page.h>
-#include <asm/sizes.h>
-
-/**************************************************************************
- * Definitions
- **************************************************************************/
-#define DAVINCI_DDR_BASE 0x80000000
-#define DA8XX_DDR_BASE 0xc0000000
-
-#if defined(CONFIG_ARCH_DAVINCI_DA8XX) && defined(CONFIG_ARCH_DAVINCI_DMx)
-#error Cannot enable DaVinci and DA8XX platforms concurrently
-#elif defined(CONFIG_ARCH_DAVINCI_DA8XX)
-#define PLAT_PHYS_OFFSET DA8XX_DDR_BASE
-#else
-#define PLAT_PHYS_OFFSET DAVINCI_DDR_BASE
-#endif
-
-#define DDR2_SDRCR_OFFSET 0xc
-#define DDR2_SRPD_BIT BIT(23)
-#define DDR2_MCLKSTOPEN_BIT BIT(30)
-#define DDR2_LPMODEN_BIT BIT(31)
-
-/*
- * Increase size of DMA-consistent memory region
- */
-#define CONSISTENT_DMA_SIZE (14<<20)
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-davinci/include/mach/mmc.h b/arch/arm/mach-davinci/include/mach/mmc.h
index d4f1e9675069..5ba6b22ce338 100644
--- a/arch/arm/mach-davinci/include/mach/mmc.h
+++ b/arch/arm/mach-davinci/include/mach/mmc.h
@@ -12,6 +12,9 @@ struct davinci_mmc_config {
/* get_cd()/get_wp() may sleep */
int (*get_cd)(int module);
int (*get_ro)(int module);
+
+ void (*set_power)(int module, bool on);
+
/* wires == 0 is equivalent to wires == 4 (4-bit parallel) */
u8 wires;
diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
index 5d4e0fed828a..a7e92fca32e6 100644
--- a/arch/arm/mach-davinci/include/mach/mux.h
+++ b/arch/arm/mach-davinci/include/mach/mux.h
@@ -857,6 +857,14 @@ enum davinci_da850_index {
DA850_MMCSD0_CLK,
DA850_MMCSD0_CMD,
+ /* MMC/SD1 function */
+ DA850_MMCSD1_DAT_0,
+ DA850_MMCSD1_DAT_1,
+ DA850_MMCSD1_DAT_2,
+ DA850_MMCSD1_DAT_3,
+ DA850_MMCSD1_CLK,
+ DA850_MMCSD1_CMD,
+
/* EMIF2.5/EMIFA function */
DA850_EMA_D_7,
DA850_EMA_D_6,
@@ -916,6 +924,8 @@ enum davinci_da850_index {
DA850_GPIO3_13,
DA850_GPIO4_0,
DA850_GPIO4_1,
+ DA850_GPIO6_9,
+ DA850_GPIO6_10,
DA850_GPIO6_13,
DA850_RTC_ALARM,
};
diff --git a/arch/arm/mach-davinci/include/mach/serial.h b/arch/arm/mach-davinci/include/mach/serial.h
index c9e6ce185a66..e347d88fef91 100644
--- a/arch/arm/mach-davinci/include/mach/serial.h
+++ b/arch/arm/mach-davinci/include/mach/serial.h
@@ -21,8 +21,9 @@
* macros in debug-macro.S.
*
* This area sits just below the page tables (see arch/arm/kernel/head.S).
+ * We define it as a relative offset from start of usable RAM.
*/
-#define DAVINCI_UART_INFO (PLAT_PHYS_OFFSET + 0x3ff8)
+#define DAVINCI_UART_INFO_OFS 0x3ff8
#define DAVINCI_UART0_BASE (IO_PHYS + 0x20000)
#define DAVINCI_UART1_BASE (IO_PHYS + 0x20400)
diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h
index 78d80683cdc2..9dc7cf9664fe 100644
--- a/arch/arm/mach-davinci/include/mach/uncompress.h
+++ b/arch/arm/mach-davinci/include/mach/uncompress.h
@@ -43,7 +43,12 @@ static inline void flush(void)
static inline void set_uart_info(u32 phys, void * __iomem virt)
{
- u32 *uart_info = (u32 *)(DAVINCI_UART_INFO);
+ /*
+ * Get address of some.bss variable and round it down
+ * a la CONFIG_AUTO_ZRELADDR.
+ */
+ u32 ram_start = (u32)&uart & 0xf8000000;
+ u32 *uart_info = (u32 *)(ram_start + DAVINCI_UART_INFO_OFS);
uart = (u32 *)phys;
uart_info[0] = phys;
diff --git a/arch/arm/mach-davinci/sleep.S b/arch/arm/mach-davinci/sleep.S
index 5f1e045a3ad1..d4e9316ecacb 100644
--- a/arch/arm/mach-davinci/sleep.S
+++ b/arch/arm/mach-davinci/sleep.S
@@ -22,7 +22,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <mach/psc.h>
-#include <mach/memory.h>
+#include <mach/ddr2.h>
#include "clock.h"
diff --git a/arch/arm/mach-davinci/tnetv107x.c b/arch/arm/mach-davinci/tnetv107x.c
index 1b28fdd892a6..409bb869c7c7 100644
--- a/arch/arm/mach-davinci/tnetv107x.c
+++ b/arch/arm/mach-davinci/tnetv107x.c
@@ -12,6 +12,7 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
@@ -27,9 +28,9 @@
#include <mach/psc.h>
#include <mach/cp_intc.h>
#include <mach/irqs.h>
-#include <mach/gpio.h>
#include <mach/hardware.h>
#include <mach/tnetv107x.h>
+#include <mach/gpio-davinci.h>
#include "clock.h"
#include "mux.h"
diff --git a/arch/arm/mach-dove/Makefile.boot b/arch/arm/mach-dove/Makefile.boot
index 67039c3e0c48..760a0efe7580 100644
--- a/arch/arm/mach-dove/Makefile.boot
+++ b/arch/arm/mach-dove/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-dove/cm-a510.c b/arch/arm/mach-dove/cm-a510.c
index 03e11f9dca97..c8a406f7e946 100644
--- a/arch/arm/mach-dove/cm-a510.c
+++ b/arch/arm/mach-dove/cm-a510.c
@@ -87,7 +87,7 @@ static void __init cm_a510_init(void)
}
MACHINE_START(CM_A510, "Compulab CM-A510 Board")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = cm_a510_init,
.map_io = dove_map_io,
.init_early = dove_init_early,
diff --git a/arch/arm/mach-dove/dove-db-setup.c b/arch/arm/mach-dove/dove-db-setup.c
index 2ac34ecfa745..11ea34e4fc76 100644
--- a/arch/arm/mach-dove/dove-db-setup.c
+++ b/arch/arm/mach-dove/dove-db-setup.c
@@ -94,7 +94,7 @@ static void __init dove_db_init(void)
}
MACHINE_START(DOVE_DB, "Marvell DB-MV88AP510-BP Development Board")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = dove_db_init,
.map_io = dove_map_io,
.init_early = dove_init_early,
diff --git a/arch/arm/mach-dove/include/mach/debug-macro.S b/arch/arm/mach-dove/include/mach/debug-macro.S
index da8bf2bad3b1..5929cbc59161 100644
--- a/arch/arm/mach-dove/include/mach/debug-macro.S
+++ b/arch/arm/mach-dove/include/mach/debug-macro.S
@@ -8,7 +8,7 @@
#include <mach/bridge-regs.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =DOVE_SB_REGS_PHYS_BASE
ldr \rv, =DOVE_SB_REGS_VIRT_BASE
orr \rp, \rp, #0x00012000
diff --git a/arch/arm/mach-dove/include/mach/memory.h b/arch/arm/mach-dove/include/mach/memory.h
deleted file mode 100644
index bbc93fee6c75..000000000000
--- a/arch/arm/mach-dove/include/mach/memory.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-dove/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-ebsa110/Makefile.boot b/arch/arm/mach-ebsa110/Makefile.boot
index 232126044935..83cf07c38ada 100644
--- a/arch/arm/mach-ebsa110/Makefile.boot
+++ b/arch/arm/mach-ebsa110/Makefile.boot
@@ -1,4 +1,4 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000400
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index 087bc771ac23..d0ce8abdd4b6 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -280,7 +280,7 @@ arch_initcall(ebsa110_init);
MACHINE_START(EBSA110, "EBSA110")
/* Maintainer: Russell King */
- .boot_params = 0x00000400,
+ .atag_offset = 0x400,
.reserve_lp0 = 1,
.reserve_lp2 = 1,
.soft_reboot = 1,
diff --git a/arch/arm/mach-ebsa110/include/mach/debug-macro.S b/arch/arm/mach-ebsa110/include/mach/debug-macro.S
index 7ef5690fd08c..bb02c05e6812 100644
--- a/arch/arm/mach-ebsa110/include/mach/debug-macro.S
+++ b/arch/arm/mach-ebsa110/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
*
**/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0xf0000000
orr \rp, \rp, #0x00000be0
mov \rp, \rv
diff --git a/arch/arm/mach-ebsa110/include/mach/io.h b/arch/arm/mach-ebsa110/include/mach/io.h
index f68daa632af0..44679db672fb 100644
--- a/arch/arm/mach-ebsa110/include/mach/io.h
+++ b/arch/arm/mach-ebsa110/include/mach/io.h
@@ -13,8 +13,6 @@
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
-#define IO_SPACE_LIMIT 0xffff
-
u8 __inb8(unsigned int port);
void __outb8(u8 val, unsigned int port);
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index 3a08b18f6433..97a249395b5a 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -182,6 +182,13 @@ config MACH_TS72XX
Say 'Y' here if you want your kernel to support the
Technologic Systems TS-72xx board.
+config MACH_VISION_EP9307
+ bool "Support Vision Engraving Systems EP9307 SoM"
+ depends on EP93XX_SDCE0_PHYS_OFFSET
+ help
+ Say 'Y' here if you want your kernel to support the
+ Vision Engraving Systems EP9307 SoM.
+
choice
prompt "Select a UART for early kernel messages"
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 3cedcf2d39e5..574209d9e246 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_MACH_MICRO9) += micro9.o
obj-$(CONFIG_MACH_SIM_ONE) += simone.o
obj-$(CONFIG_MACH_SNAPPER_CL15) += snappercl15.o
obj-$(CONFIG_MACH_TS72XX) += ts72xx.o
+obj-$(CONFIG_MACH_VISION_EP9307)+= vision_ep9307.o
diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot
index 0ad33f15c622..d3113a71cb40 100644
--- a/arch/arm/mach-ep93xx/Makefile.boot
+++ b/arch/arm/mach-ep93xx/Makefile.boot
@@ -1,14 +1,14 @@
- zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) := 0x00008000
+ zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) += 0x00008000
params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) := 0x00000100
- zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) := 0xc0008000
+ zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) += 0xc0008000
params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) := 0xc0000100
- zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) := 0xd0008000
+ zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) += 0xd0008000
params_phys-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) := 0xd0000100
- zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) := 0xe0008000
+ zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) += 0xe0008000
params_phys-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) := 0xe0000100
- zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) := 0xf0008000
+ zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) += 0xf0008000
params_phys-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) := 0xf0000100
diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c
index 61b98ce4b673..0713448206a5 100644
--- a/arch/arm/mach-ep93xx/adssphere.c
+++ b/arch/arm/mach-ep93xx/adssphere.c
@@ -33,7 +33,7 @@ static void __init adssphere_init_machine(void)
MACHINE_START(ADSSPHERE, "ADS Sphere board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index c60f081e930b..94c78bc66275 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -38,6 +38,7 @@
#include <mach/fb.h>
#include <mach/ep93xx_keypad.h>
#include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 9969bb115f60..70ef8c527d27 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -37,6 +37,7 @@
#include <mach/hardware.h>
#include <mach/fb.h>
#include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -159,6 +160,11 @@ static void __init edb93xx_register_spi(void)
/*************************************************************************
* EDB93xx I2S
*************************************************************************/
+static struct platform_device edb93xx_audio_device = {
+ .name = "edb93xx-audio",
+ .id = -1,
+};
+
static int __init edb93xx_has_audio(void)
{
return (machine_is_edb9301() || machine_is_edb9302() ||
@@ -170,6 +176,7 @@ static void __init edb93xx_register_i2s(void)
{
if (edb93xx_has_audio()) {
ep93xx_register_i2s();
+ platform_device_register(&edb93xx_audio_device);
}
}
@@ -240,7 +247,7 @@ static void __init edb93xx_init_machine(void)
#ifdef CONFIG_MACH_EDB9301
MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
@@ -251,7 +258,7 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9302
MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
/* Maintainer: George Kashperko <george@chas.com.ua> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
@@ -262,7 +269,7 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9302A
MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
@@ -273,7 +280,7 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9307
MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
@@ -284,7 +291,7 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9307A
MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
- .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
@@ -295,7 +302,7 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9312
MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
@@ -306,7 +313,7 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9315
MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
@@ -317,7 +324,7 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9315A
MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c
index 9bd3152bff9a..45ee205856f8 100644
--- a/arch/arm/mach-ep93xx/gesbc9312.c
+++ b/arch/arm/mach-ep93xx/gesbc9312.c
@@ -33,7 +33,7 @@ static void __init gesbc9312_init_machine(void)
MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
diff --git a/arch/arm/mach-ep93xx/include/mach/debug-macro.S b/arch/arm/mach-ep93xx/include/mach/debug-macro.S
index b25bc9076367..af54e43132cf 100644
--- a/arch/arm/mach-ep93xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ep93xx/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
*/
#include <mach/ep93xx-regs.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =EP93XX_APB_PHYS_BASE @ Physical base
ldr \rv, =EP93XX_APB_VIRT_BASE @ virtual base
orr \rp, \rp, #0x000c0000
diff --git a/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h b/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
new file mode 100644
index 000000000000..8aff2ea35877
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
@@ -0,0 +1,100 @@
+/* Include file for the EP93XX GPIO controller machine specifics */
+
+#ifndef __GPIO_EP93XX_H
+#define __GPIO_EP93XX_H
+
+/* GPIO port A. */
+#define EP93XX_GPIO_LINE_A(x) ((x) + 0)
+#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0)
+#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1)
+#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2)
+#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3)
+#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4)
+#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5)
+#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6)
+#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7)
+
+/* GPIO port B. */
+#define EP93XX_GPIO_LINE_B(x) ((x) + 8)
+#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0)
+#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1)
+#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2)
+#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3)
+#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4)
+#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5)
+#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6)
+#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7)
+
+/* GPIO port C. */
+#define EP93XX_GPIO_LINE_C(x) ((x) + 40)
+#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0)
+#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1)
+#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2)
+#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3)
+#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4)
+#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5)
+#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6)
+#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7)
+
+/* GPIO port D. */
+#define EP93XX_GPIO_LINE_D(x) ((x) + 24)
+#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0)
+#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1)
+#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2)
+#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3)
+#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4)
+#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5)
+#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6)
+#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7)
+
+/* GPIO port E. */
+#define EP93XX_GPIO_LINE_E(x) ((x) + 32)
+#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0)
+#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1)
+#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2)
+#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3)
+#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4)
+#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5)
+#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6)
+#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7)
+
+/* GPIO port F. */
+#define EP93XX_GPIO_LINE_F(x) ((x) + 16)
+#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0)
+#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1)
+#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2)
+#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3)
+#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4)
+#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5)
+#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6)
+#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7)
+
+/* GPIO port G. */
+#define EP93XX_GPIO_LINE_G(x) ((x) + 48)
+#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0)
+#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1)
+#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2)
+#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3)
+#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4)
+#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5)
+#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6)
+#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7)
+
+/* GPIO port H. */
+#define EP93XX_GPIO_LINE_H(x) ((x) + 56)
+#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0)
+#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1)
+#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2)
+#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3)
+#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4)
+#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5)
+#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6)
+#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for gpio line identifiers */
+#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for irq capable line identifiers */
+#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7)
+
+#endif /* __GPIO_EP93XX_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h
index c57152c231f1..40a8c178f10d 100644
--- a/arch/arm/mach-ep93xx/include/mach/gpio.h
+++ b/arch/arm/mach-ep93xx/include/mach/gpio.h
@@ -1,120 +1 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/gpio.h
- */
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-/* GPIO port A. */
-#define EP93XX_GPIO_LINE_A(x) ((x) + 0)
-#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0)
-#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1)
-#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2)
-#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3)
-#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4)
-#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5)
-#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6)
-#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7)
-
-/* GPIO port B. */
-#define EP93XX_GPIO_LINE_B(x) ((x) + 8)
-#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0)
-#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1)
-#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2)
-#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3)
-#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4)
-#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5)
-#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6)
-#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7)
-
-/* GPIO port C. */
-#define EP93XX_GPIO_LINE_C(x) ((x) + 40)
-#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0)
-#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1)
-#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2)
-#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3)
-#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4)
-#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5)
-#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6)
-#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7)
-
-/* GPIO port D. */
-#define EP93XX_GPIO_LINE_D(x) ((x) + 24)
-#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0)
-#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1)
-#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2)
-#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3)
-#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4)
-#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5)
-#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6)
-#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7)
-
-/* GPIO port E. */
-#define EP93XX_GPIO_LINE_E(x) ((x) + 32)
-#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0)
-#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1)
-#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2)
-#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3)
-#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4)
-#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5)
-#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6)
-#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7)
-
-/* GPIO port F. */
-#define EP93XX_GPIO_LINE_F(x) ((x) + 16)
-#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0)
-#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1)
-#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2)
-#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3)
-#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4)
-#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5)
-#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6)
-#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7)
-
-/* GPIO port G. */
-#define EP93XX_GPIO_LINE_G(x) ((x) + 48)
-#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0)
-#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1)
-#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2)
-#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3)
-#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4)
-#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5)
-#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6)
-#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7)
-
-/* GPIO port H. */
-#define EP93XX_GPIO_LINE_H(x) ((x) + 56)
-#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0)
-#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1)
-#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2)
-#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3)
-#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4)
-#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5)
-#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6)
-#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7)
-
-/* maximum value for gpio line identifiers */
-#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7)
-
-/* maximum value for irq capable line identifiers */
-#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7)
-
-/* new generic GPIO API - see Documentation/gpio.txt */
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-
-/*
- * Map GPIO A0..A7 (0..7) to irq 64..71,
- * B0..B7 (7..15) to irq 72..79, and
- * F0..F7 (16..24) to irq 80..87.
- */
-#define gpio_to_irq(gpio) \
- (((gpio) <= EP93XX_GPIO_LINE_MAX_IRQ) ? (64 + (gpio)) : -EINVAL)
-
-#define irq_to_gpio(irq) ((irq) - gpio_to_irq(0))
-
-#endif
+/* empty */
diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c
index 7adea6258efe..e72f7368876e 100644
--- a/arch/arm/mach-ep93xx/micro9.c
+++ b/arch/arm/mach-ep93xx/micro9.c
@@ -77,7 +77,7 @@ static void __init micro9_init_machine(void)
#ifdef CONFIG_MACH_MICRO9H
MACHINE_START(MICRO9, "Contec Micro9-High")
/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
@@ -88,7 +88,7 @@ MACHINE_END
#ifdef CONFIG_MACH_MICRO9M
MACHINE_START(MICRO9M, "Contec Micro9-Mid")
/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
@@ -99,7 +99,7 @@ MACHINE_END
#ifdef CONFIG_MACH_MICRO9L
MACHINE_START(MICRO9L, "Contec Micro9-Lite")
/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
@@ -110,7 +110,7 @@ MACHINE_END
#ifdef CONFIG_MACH_MICRO9S
MACHINE_START(MICRO9S, "Contec Micro9-Slim")
/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
index 8392e95d7cea..52e090dc9d27 100644
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -18,12 +18,12 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <mach/hardware.h>
#include <mach/fb.h>
+#include <mach/gpio-ep93xx.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -53,6 +53,17 @@ static struct i2c_board_info __initdata simone_i2c_board_info[] = {
},
};
+static struct platform_device simone_audio_device = {
+ .name = "simone-audio",
+ .id = -1,
+};
+
+static void __init simone_register_audio(void)
+{
+ ep93xx_register_ac97();
+ platform_device_register(&simone_audio_device);
+}
+
static void __init simone_init_machine(void)
{
ep93xx_init_devices();
@@ -61,12 +72,12 @@ static void __init simone_init_machine(void)
ep93xx_register_fb(&simone_fb_info);
ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
ARRAY_SIZE(simone_i2c_board_info));
- ep93xx_register_ac97();
+ simone_register_audio();
}
MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
-/* Maintainer: Ryan Mallon */
- .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
+ /* Maintainer: Ryan Mallon */
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
index 2e9c614757e4..8121e3aedc0a 100644
--- a/arch/arm/mach-ep93xx/snappercl15.c
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -20,7 +20,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
-#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/fb.h>
@@ -30,6 +29,7 @@
#include <mach/hardware.h>
#include <mach/fb.h>
+#include <mach/gpio-ep93xx.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -150,6 +150,17 @@ static struct ep93xxfb_mach_info __initdata snappercl15_fb_info = {
.bpp = 16,
};
+static struct platform_device snappercl15_audio_device = {
+ .name = "snappercl15-audio",
+ .id = -1,
+};
+
+static void __init snappercl15_register_audio(void)
+{
+ ep93xx_register_i2s();
+ platform_device_register(&snappercl15_audio_device);
+}
+
static void __init snappercl15_init_machine(void)
{
ep93xx_init_devices();
@@ -157,13 +168,13 @@ static void __init snappercl15_init_machine(void)
ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data,
ARRAY_SIZE(snappercl15_i2c_data));
ep93xx_register_fb(&snappercl15_fb_info);
- ep93xx_register_i2s();
+ snappercl15_register_audio();
platform_device_register(&snappercl15_nand_device);
}
MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
/* Maintainer: Ryan Mallon */
- .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
+ .atag_offset = 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index c2d2cf40ead9..1ade3c340507 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -257,7 +257,7 @@ static void __init ts72xx_init_machine(void)
MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+ .atag_offset = 0x100,
.map_io = ts72xx_map_io,
.init_irq = ep93xx_init_irq,
.timer = &ep93xx_timer,
diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c
new file mode 100644
index 000000000000..d96e4dbec6a8
--- /dev/null
+++ b/arch/arm/mach-ep93xx/vision_ep9307.c
@@ -0,0 +1,364 @@
+/*
+ * arch/arm/mach-ep93xx/vision_ep9307.c
+ * Vision Engraving Systems EP9307 SoM support.
+ *
+ * Copyright (C) 2008-2011 Vision Engraving Systems
+ * H Hartley Sweeten <hsweeten@visionengravers.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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/mtd/partitions.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/host.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_spi.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * Static I/O mappings for the FPGA
+ *************************************************************************/
+#define VISION_PHYS_BASE EP93XX_CS7_PHYS_BASE
+#define VISION_VIRT_BASE 0xfebff000
+
+static struct map_desc vision_io_desc[] __initdata = {
+ {
+ .virtual = VISION_VIRT_BASE,
+ .pfn = __phys_to_pfn(VISION_PHYS_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static void __init vision_map_io(void)
+{
+ ep93xx_map_io();
+
+ iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc));
+}
+
+/*************************************************************************
+ * Ethernet
+ *************************************************************************/
+static struct ep93xx_eth_data vision_eth_data __initdata = {
+ .phy_id = 1,
+};
+
+/*************************************************************************
+ * Framebuffer
+ *************************************************************************/
+#define VISION_LCD_ENABLE EP93XX_GPIO_LINE_EGPIO1
+
+static int vision_lcd_setup(struct platform_device *pdev)
+{
+ int err;
+
+ err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH,
+ dev_name(&pdev->dev));
+ if (err)
+ return err;
+
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS |
+ EP93XX_SYSCON_DEVCFG_RASONP3 |
+ EP93XX_SYSCON_DEVCFG_EXVC);
+
+ return 0;
+}
+
+static void vision_lcd_teardown(struct platform_device *pdev)
+{
+ gpio_free(VISION_LCD_ENABLE);
+}
+
+static void vision_lcd_blank(int blank_mode, struct fb_info *info)
+{
+ if (blank_mode)
+ gpio_set_value(VISION_LCD_ENABLE, 0);
+ else
+ gpio_set_value(VISION_LCD_ENABLE, 1);
+}
+
+static struct ep93xxfb_mach_info ep93xxfb_info __initdata = {
+ .num_modes = EP93XXFB_USE_MODEDB,
+ .bpp = 16,
+ .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
+ .setup = vision_lcd_setup,
+ .teardown = vision_lcd_teardown,
+ .blank = vision_lcd_blank,
+};
+
+
+/*************************************************************************
+ * GPIO Expanders
+ *************************************************************************/
+#define PCA9539_74_GPIO_BASE (EP93XX_GPIO_LINE_MAX + 1)
+#define PCA9539_75_GPIO_BASE (PCA9539_74_GPIO_BASE + 16)
+#define PCA9539_76_GPIO_BASE (PCA9539_75_GPIO_BASE + 16)
+#define PCA9539_77_GPIO_BASE (PCA9539_76_GPIO_BASE + 16)
+
+static struct pca953x_platform_data pca953x_74_gpio_data = {
+ .gpio_base = PCA9539_74_GPIO_BASE,
+ .irq_base = EP93XX_BOARD_IRQ(0),
+};
+
+static struct pca953x_platform_data pca953x_75_gpio_data = {
+ .gpio_base = PCA9539_75_GPIO_BASE,
+ .irq_base = -1,
+};
+
+static struct pca953x_platform_data pca953x_76_gpio_data = {
+ .gpio_base = PCA9539_76_GPIO_BASE,
+ .irq_base = -1,
+};
+
+static struct pca953x_platform_data pca953x_77_gpio_data = {
+ .gpio_base = PCA9539_77_GPIO_BASE,
+ .irq_base = -1,
+};
+
+/*************************************************************************
+ * I2C Bus
+ *************************************************************************/
+static struct i2c_gpio_platform_data vision_i2c_gpio_data __initdata = {
+ .sda_pin = EP93XX_GPIO_LINE_EEDAT,
+ .scl_pin = EP93XX_GPIO_LINE_EECLK,
+};
+
+static struct i2c_board_info vision_i2c_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("isl1208", 0x6f),
+ .irq = IRQ_EP93XX_EXT1,
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x74),
+ .platform_data = &pca953x_74_gpio_data,
+ .irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7)),
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x75),
+ .platform_data = &pca953x_75_gpio_data,
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x76),
+ .platform_data = &pca953x_76_gpio_data,
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x77),
+ .platform_data = &pca953x_77_gpio_data,
+ },
+};
+
+/*************************************************************************
+ * SPI Flash
+ *************************************************************************/
+#define VISION_SPI_FLASH_CS EP93XX_GPIO_LINE_EGPIO7
+
+static struct mtd_partition vision_spi_flash_partitions[] = {
+ {
+ .name = "SPI bootstrap",
+ .offset = 0,
+ .size = SZ_4K,
+ }, {
+ .name = "Bootstrap config",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4K,
+ }, {
+ .name = "System config",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data vision_spi_flash_data = {
+ .name = "SPI Flash",
+ .parts = vision_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(vision_spi_flash_partitions),
+};
+
+static int vision_spi_flash_hw_setup(struct spi_device *spi)
+{
+ return gpio_request_one(VISION_SPI_FLASH_CS, GPIOF_INIT_HIGH,
+ spi->modalias);
+}
+
+static void vision_spi_flash_hw_cleanup(struct spi_device *spi)
+{
+ gpio_free(VISION_SPI_FLASH_CS);
+}
+
+static void vision_spi_flash_hw_cs_control(struct spi_device *spi, int value)
+{
+ gpio_set_value(VISION_SPI_FLASH_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_flash_hw = {
+ .setup = vision_spi_flash_hw_setup,
+ .cleanup = vision_spi_flash_hw_cleanup,
+ .cs_control = vision_spi_flash_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI SD/MMC host
+ *************************************************************************/
+#define VISION_SPI_MMC_CS EP93XX_GPIO_LINE_G(2)
+#define VISION_SPI_MMC_WP EP93XX_GPIO_LINE_F(0)
+#define VISION_SPI_MMC_CD EP93XX_GPIO_LINE_EGPIO15
+
+static struct gpio vision_spi_mmc_gpios[] = {
+ { VISION_SPI_MMC_WP, GPIOF_DIR_IN, "mmc_spi:wp" },
+ { VISION_SPI_MMC_CD, GPIOF_DIR_IN, "mmc_spi:cd" },
+};
+
+static int vision_spi_mmc_init(struct device *pdev,
+ irqreturn_t (*func)(int, void *), void *pdata)
+{
+ int err;
+
+ err = gpio_request_array(vision_spi_mmc_gpios,
+ ARRAY_SIZE(vision_spi_mmc_gpios));
+ if (err)
+ return err;
+
+ err = gpio_set_debounce(VISION_SPI_MMC_CD, 1);
+ if (err)
+ goto exit_err;
+
+ err = request_irq(gpio_to_irq(VISION_SPI_MMC_CD), func,
+ IRQ_TYPE_EDGE_BOTH, "mmc_spi:cd", pdata);
+ if (err)
+ goto exit_err;
+
+ return 0;
+
+exit_err:
+ gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+ return err;
+
+}
+
+static void vision_spi_mmc_exit(struct device *pdev, void *pdata)
+{
+ free_irq(gpio_to_irq(VISION_SPI_MMC_CD), pdata);
+ gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+}
+
+static int vision_spi_mmc_get_ro(struct device *pdev)
+{
+ return !!gpio_get_value(VISION_SPI_MMC_WP);
+}
+
+static int vision_spi_mmc_get_cd(struct device *pdev)
+{
+ return !gpio_get_value(VISION_SPI_MMC_CD);
+}
+
+static struct mmc_spi_platform_data vision_spi_mmc_data = {
+ .init = vision_spi_mmc_init,
+ .exit = vision_spi_mmc_exit,
+ .get_ro = vision_spi_mmc_get_ro,
+ .get_cd = vision_spi_mmc_get_cd,
+ .detect_delay = 100,
+ .powerup_msecs = 100,
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static int vision_spi_mmc_hw_setup(struct spi_device *spi)
+{
+ return gpio_request_one(VISION_SPI_MMC_CS, GPIOF_INIT_HIGH,
+ spi->modalias);
+}
+
+static void vision_spi_mmc_hw_cleanup(struct spi_device *spi)
+{
+ gpio_free(VISION_SPI_MMC_CS);
+}
+
+static void vision_spi_mmc_hw_cs_control(struct spi_device *spi, int value)
+{
+ gpio_set_value(VISION_SPI_MMC_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_mmc_hw = {
+ .setup = vision_spi_mmc_hw_setup,
+ .cleanup = vision_spi_mmc_hw_cleanup,
+ .cs_control = vision_spi_mmc_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI Bus
+ *************************************************************************/
+static struct spi_board_info vision_spi_board_info[] __initdata = {
+ {
+ .modalias = "sst25l",
+ .platform_data = &vision_spi_flash_data,
+ .controller_data = &vision_spi_flash_hw,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ }, {
+ .modalias = "mmc_spi",
+ .platform_data = &vision_spi_mmc_data,
+ .controller_data = &vision_spi_mmc_hw,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_3,
+ },
+};
+
+static struct ep93xx_spi_info vision_spi_master __initdata = {
+ .num_chipselect = ARRAY_SIZE(vision_spi_board_info),
+};
+
+/*************************************************************************
+ * Machine Initialization
+ *************************************************************************/
+static void __init vision_init_machine(void)
+{
+ ep93xx_init_devices();
+ ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M);
+ ep93xx_register_eth(&vision_eth_data, 1);
+ ep93xx_register_fb(&ep93xxfb_info);
+ ep93xx_register_pwm(1, 0);
+
+ /*
+ * Request the gpio expander's interrupt gpio line now to prevent
+ * the kernel from doing a WARN in gpiolib:gpio_ensure_requested().
+ */
+ if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN,
+ "pca9539:74"))
+ pr_warn("cannot request interrupt gpio for pca9539:74\n");
+
+ ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info,
+ ARRAY_SIZE(vision_i2c_info));
+ ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
+ ARRAY_SIZE(vision_spi_board_info));
+}
+
+MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
+ /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+ .atag_offset = 0x100,
+ .map_io = vision_map_io,
+ .init_irq = ep93xx_init_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = vision_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 0c77ab99fa16..a65273598036 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -12,9 +12,20 @@ if ARCH_EXYNOS4
config CPU_EXYNOS4210
bool
select S3C_PL330_DMA
+ select ARM_CPU_SUSPEND if PM
help
Enable EXYNOS4210 CPU support
+config SOC_EXYNOS4212
+ bool
+ help
+ Enable EXYNOS4212 SoC support
+
+config SOC_EXYNOS4412
+ bool
+ help
+ Enable EXYNOS4412 SoC support
+
config EXYNOS4_MCT
bool
default y
@@ -111,24 +122,11 @@ config EXYNOS4_SETUP_USB_PHY
menu "EXYNOS4 Machines"
+comment "EXYNOS4210 Boards"
+
config MACH_SMDKC210
bool "SMDKC210"
- select CPU_EXYNOS4210
- select S5P_DEV_FIMD0
- select S3C_DEV_RTC
- select S3C_DEV_WDT
- select S3C_DEV_I2C1
- select S3C_DEV_HSMMC
- select S3C_DEV_HSMMC1
- select S3C_DEV_HSMMC2
- select S3C_DEV_HSMMC3
- select SAMSUNG_DEV_PWM
- select SAMSUNG_DEV_BACKLIGHT
- select EXYNOS4_DEV_PD
- select EXYNOS4_DEV_SYSMMU
- select EXYNOS4_SETUP_FIMD0
- select EXYNOS4_SETUP_I2C1
- select EXYNOS4_SETUP_SDHCI
+ select MACH_SMDKV310
help
Machine support for Samsung SMDKC210
@@ -218,6 +216,48 @@ config MACH_NURI
help
Machine support for Samsung Mobile NURI Board.
+config MACH_ORIGEN
+ bool "ORIGEN"
+ select CPU_EXYNOS4210
+ select S3C_DEV_RTC
+ select S3C_DEV_WDT
+ select S3C_DEV_HSMMC2
+ select EXYNOS4_SETUP_SDHCI
+ help
+ Machine support for ORIGEN based on Samsung EXYNOS4210
+
+comment "EXYNOS4212 Boards"
+
+config MACH_SMDK4212
+ bool "SMDK4212"
+ select SOC_EXYNOS4212
+ select S3C_DEV_HSMMC2
+ select S3C_DEV_HSMMC3
+ select S3C_DEV_I2C1
+ select S3C_DEV_I2C3
+ select S3C_DEV_I2C7
+ select S3C_DEV_RTC
+ select S3C_DEV_WDT
+ select SAMSUNG_DEV_BACKLIGHT
+ select SAMSUNG_DEV_KEYPAD
+ select SAMSUNG_DEV_PWM
+ select EXYNOS4_SETUP_I2C1
+ select EXYNOS4_SETUP_I2C3
+ select EXYNOS4_SETUP_I2C7
+ select EXYNOS4_SETUP_KEYPAD
+ select EXYNOS4_SETUP_SDHCI
+ help
+ Machine support for Samsung SMDK4212
+
+comment "EXYNOS4412 Boards"
+
+config MACH_SMDK4412
+ bool "SMDK4412"
+ select SOC_EXYNOS4412
+ select MACH_SMDK4212
+ help
+ Machine support for Samsung SMDK4412
+
endmenu
comment "Configuration for HSMMC bus width"
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index b7fe1d7b0b1f..c9b2e1f97e44 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -12,8 +12,10 @@ obj- :=
# Core support for EXYNOS4 system
-obj-$(CONFIG_CPU_EXYNOS4210) += cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o irq-eint.o dma.o pmu.o
+obj-$(CONFIG_ARCH_EXYNOS4) += cpu.o init.o clock.o irq-combiner.o
+obj-$(CONFIG_ARCH_EXYNOS4) += setup-i2c0.o irq-eint.o dma.o pmu.o
+obj-$(CONFIG_CPU_EXYNOS4210) += clock-exynos4210.o
+obj-$(CONFIG_SOC_EXYNOS4212) += clock-exynos4212.o
obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
@@ -25,11 +27,15 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
# machine support
-obj-$(CONFIG_MACH_SMDKC210) += mach-smdkc210.o
+obj-$(CONFIG_MACH_SMDKC210) += mach-smdkv310.o
obj-$(CONFIG_MACH_SMDKV310) += mach-smdkv310.o
obj-$(CONFIG_MACH_ARMLEX4210) += mach-armlex4210.o
obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o
obj-$(CONFIG_MACH_NURI) += mach-nuri.o
+obj-$(CONFIG_MACH_ORIGEN) += mach-origen.o
+
+obj-$(CONFIG_MACH_SMDK4212) += mach-smdk4x12.o
+obj-$(CONFIG_MACH_SMDK4412) += mach-smdk4x12.o
# device support
diff --git a/arch/arm/mach-exynos4/Makefile.boot b/arch/arm/mach-exynos4/Makefile.boot
index d65956ffb43d..b9862e22bf10 100644
--- a/arch/arm/mach-exynos4/Makefile.boot
+++ b/arch/arm/mach-exynos4/Makefile.boot
@@ -1,2 +1,2 @@
- zreladdr-y := 0x40008000
+ zreladdr-y += 0x40008000
params_phys-y := 0x40000100
diff --git a/arch/arm/mach-exynos4/clock-exynos4210.c b/arch/arm/mach-exynos4/clock-exynos4210.c
new file mode 100644
index 000000000000..b9d5ef670eb4
--- /dev/null
+++ b/arch/arm/mach-exynos4/clock-exynos4210.c
@@ -0,0 +1,139 @@
+/*
+ * linux/arch/arm/mach-exynos4/clock-exynos4210.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS4210 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4210_clock_save[] = {
+ SAVE_ITEM(S5P_CLKSRC_IMAGE),
+ SAVE_ITEM(S5P_CLKSRC_LCD1),
+ SAVE_ITEM(S5P_CLKDIV_IMAGE),
+ SAVE_ITEM(S5P_CLKDIV_LCD1),
+ SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
+ SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4210),
+ SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
+ SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4210),
+};
+
+static struct clksrc_clk *sysclks[] = {
+ /* nothing here yet */
+};
+
+static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
+}
+
+static struct clksrc_clk clksrcs[] = {
+ {
+ .clk = {
+ .name = "sclk_sata",
+ .id = -1,
+ .enable = exynos4_clksrc_mask_fsys_ctrl,
+ .ctrlbit = (1 << 24),
+ },
+ .sources = &clkset_mout_corebus,
+ .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
+ .reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_fimd",
+ .devname = "exynos4-fb.1",
+ .enable = exynos4_clksrc_mask_lcd1_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
+ },
+};
+
+static struct clk init_clocks_off[] = {
+ {
+ .name = "sataphy",
+ .id = -1,
+ .parent = &clk_aclk_133.clk,
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 3),
+ }, {
+ .name = "sata",
+ .id = -1,
+ .parent = &clk_aclk_133.clk,
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 10),
+ }, {
+ .name = "fimd",
+ .devname = "exynos4-fb.1",
+ .enable = exynos4_clk_ip_lcd1_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4210_clock_suspend(void)
+{
+ s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
+
+ return 0;
+}
+
+static void exynos4210_clock_resume(void)
+{
+ s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
+}
+
+#else
+#define exynos4210_clock_suspend NULL
+#define exynos4210_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4210_clock_syscore_ops = {
+ .suspend = exynos4210_clock_suspend,
+ .resume = exynos4210_clock_resume,
+};
+
+void __init exynos4210_register_clocks(void)
+{
+ int ptr;
+
+ clk_mout_mpll.reg_src.reg = S5P_CLKSRC_CPU;
+ clk_mout_mpll.reg_src.shift = 8;
+ clk_mout_mpll.reg_src.size = 1;
+
+ for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+ s3c_register_clksrc(sysclks[ptr], 1);
+
+ s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+
+ s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+ register_syscore_ops(&exynos4210_clock_syscore_ops);
+}
diff --git a/arch/arm/mach-exynos4/clock-exynos4212.c b/arch/arm/mach-exynos4/clock-exynos4212.c
new file mode 100644
index 000000000000..77d5decb34fd
--- /dev/null
+++ b/arch/arm/mach-exynos4/clock-exynos4212.c
@@ -0,0 +1,118 @@
+/*
+ * linux/arch/arm/mach-exynos4/clock-exynos4212.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS4212 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4212_clock_save[] = {
+ SAVE_ITEM(S5P_CLKSRC_IMAGE),
+ SAVE_ITEM(S5P_CLKDIV_IMAGE),
+ SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4212),
+ SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4212),
+};
+
+static struct clk *clk_src_mpll_user_list[] = {
+ [0] = &clk_fin_mpll,
+ [1] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clk_src_mpll_user = {
+ .sources = clk_src_mpll_user_list,
+ .nr_sources = ARRAY_SIZE(clk_src_mpll_user_list),
+};
+
+static struct clksrc_clk clk_mout_mpll_user = {
+ .clk = {
+ .name = "mout_mpll_user",
+ },
+ .sources = &clk_src_mpll_user,
+ .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 24, .size = 1 },
+};
+
+static struct clksrc_clk *sysclks[] = {
+ &clk_mout_mpll_user,
+};
+
+static struct clksrc_clk clksrcs[] = {
+ /* nothing here yet */
+};
+
+static struct clk init_clocks_off[] = {
+ /* nothing here yet */
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4212_clock_suspend(void)
+{
+ s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
+
+ return 0;
+}
+
+static void exynos4212_clock_resume(void)
+{
+ s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
+}
+
+#else
+#define exynos4212_clock_suspend NULL
+#define exynos4212_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4212_clock_syscore_ops = {
+ .suspend = exynos4212_clock_suspend,
+ .resume = exynos4212_clock_resume,
+};
+
+void __init exynos4212_register_clocks(void)
+{
+ int ptr;
+
+ /* usbphy1 is removed */
+ clkset_group_list[4] = NULL;
+
+ /* mout_mpll_user is used */
+ clkset_group_list[6] = &clk_mout_mpll_user.clk;
+ clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
+
+ clk_mout_mpll.reg_src.reg = S5P_CLKSRC_DMC;
+ clk_mout_mpll.reg_src.shift = 12;
+ clk_mout_mpll.reg_src.size = 1;
+
+ for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+ s3c_register_clksrc(sysclks[ptr], 1);
+
+ s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+
+ s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+ register_syscore_ops(&exynos4212_clock_syscore_ops);
+}
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index 86964d2e9e1b..0d59be3fa1fe 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/syscore_ops.h>
#include <plat/cpu-freq.h>
#include <plat/clock.h>
@@ -20,26 +21,93 @@
#include <plat/pll.h>
#include <plat/s5p-clock.h>
#include <plat/clock-clksrc.h>
+#include <plat/exynos4.h>
+#include <plat/pm.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
#include <mach/sysmmu.h>
-
-static struct clk clk_sclk_hdmi27m = {
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4_clock_save[] = {
+ SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
+ SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
+ SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
+ SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
+ SAVE_ITEM(S5P_CLKSRC_TOP0),
+ SAVE_ITEM(S5P_CLKSRC_TOP1),
+ SAVE_ITEM(S5P_CLKSRC_CAM),
+ SAVE_ITEM(S5P_CLKSRC_TV),
+ SAVE_ITEM(S5P_CLKSRC_MFC),
+ SAVE_ITEM(S5P_CLKSRC_G3D),
+ SAVE_ITEM(S5P_CLKSRC_LCD0),
+ SAVE_ITEM(S5P_CLKSRC_MAUDIO),
+ SAVE_ITEM(S5P_CLKSRC_FSYS),
+ SAVE_ITEM(S5P_CLKSRC_PERIL0),
+ SAVE_ITEM(S5P_CLKSRC_PERIL1),
+ SAVE_ITEM(S5P_CLKDIV_CAM),
+ SAVE_ITEM(S5P_CLKDIV_TV),
+ SAVE_ITEM(S5P_CLKDIV_MFC),
+ SAVE_ITEM(S5P_CLKDIV_G3D),
+ SAVE_ITEM(S5P_CLKDIV_LCD0),
+ SAVE_ITEM(S5P_CLKDIV_MAUDIO),
+ SAVE_ITEM(S5P_CLKDIV_FSYS0),
+ SAVE_ITEM(S5P_CLKDIV_FSYS1),
+ SAVE_ITEM(S5P_CLKDIV_FSYS2),
+ SAVE_ITEM(S5P_CLKDIV_FSYS3),
+ SAVE_ITEM(S5P_CLKDIV_PERIL0),
+ SAVE_ITEM(S5P_CLKDIV_PERIL1),
+ SAVE_ITEM(S5P_CLKDIV_PERIL2),
+ SAVE_ITEM(S5P_CLKDIV_PERIL3),
+ SAVE_ITEM(S5P_CLKDIV_PERIL4),
+ SAVE_ITEM(S5P_CLKDIV_PERIL5),
+ SAVE_ITEM(S5P_CLKDIV_TOP),
+ SAVE_ITEM(S5P_CLKSRC_MASK_TOP),
+ SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
+ SAVE_ITEM(S5P_CLKSRC_MASK_TV),
+ SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
+ SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
+ SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
+ SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
+ SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
+ SAVE_ITEM(S5P_CLKDIV2_RATIO),
+ SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
+ SAVE_ITEM(S5P_CLKGATE_IP_CAM),
+ SAVE_ITEM(S5P_CLKGATE_IP_TV),
+ SAVE_ITEM(S5P_CLKGATE_IP_MFC),
+ SAVE_ITEM(S5P_CLKGATE_IP_G3D),
+ SAVE_ITEM(S5P_CLKGATE_IP_LCD0),
+ SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
+ SAVE_ITEM(S5P_CLKGATE_IP_GPS),
+ SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
+ SAVE_ITEM(S5P_CLKGATE_BLOCK),
+ SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
+ SAVE_ITEM(S5P_CLKSRC_DMC),
+ SAVE_ITEM(S5P_CLKDIV_DMC0),
+ SAVE_ITEM(S5P_CLKDIV_DMC1),
+ SAVE_ITEM(S5P_CLKGATE_IP_DMC),
+ SAVE_ITEM(S5P_CLKSRC_CPU),
+ SAVE_ITEM(S5P_CLKDIV_CPU),
+ SAVE_ITEM(S5P_CLKDIV_CPU + 0x4),
+ SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
+ SAVE_ITEM(S5P_CLKGATE_IP_CPU),
+};
+
+struct clk clk_sclk_hdmi27m = {
.name = "sclk_hdmi27m",
.rate = 27000000,
};
-static struct clk clk_sclk_hdmiphy = {
+struct clk clk_sclk_hdmiphy = {
.name = "sclk_hdmiphy",
};
-static struct clk clk_sclk_usbphy0 = {
+struct clk clk_sclk_usbphy0 = {
.name = "sclk_usbphy0",
.rate = 27000000,
};
-static struct clk clk_sclk_usbphy1 = {
+struct clk clk_sclk_usbphy1 = {
.name = "sclk_usbphy1",
};
@@ -58,12 +126,7 @@ static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable);
}
-static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
+int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable);
}
@@ -103,12 +166,12 @@ static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable);
}
-static int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
+int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
}
-static int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
+int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable);
}
@@ -133,7 +196,7 @@ static struct clksrc_clk clk_mout_apll = {
.reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
};
-static struct clksrc_clk clk_sclk_apll = {
+struct clksrc_clk clk_sclk_apll = {
.clk = {
.name = "sclk_apll",
.parent = &clk_mout_apll.clk,
@@ -141,7 +204,7 @@ static struct clksrc_clk clk_sclk_apll = {
.reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
};
-static struct clksrc_clk clk_mout_epll = {
+struct clksrc_clk clk_mout_epll = {
.clk = {
.name = "mout_epll",
},
@@ -149,12 +212,13 @@ static struct clksrc_clk clk_mout_epll = {
.reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
};
-static struct clksrc_clk clk_mout_mpll = {
+struct clksrc_clk clk_mout_mpll = {
.clk = {
.name = "mout_mpll",
},
.sources = &clk_src_mpll,
- .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
+
+ /* reg_src will be added in each SoCs' clock */
};
static struct clk *clkset_moutcore_list[] = {
@@ -224,12 +288,12 @@ static struct clksrc_clk clk_periphclk = {
/* Core list of CMU_CORE side */
-static struct clk *clkset_corebus_list[] = {
+struct clk *clkset_corebus_list[] = {
[0] = &clk_mout_mpll.clk,
[1] = &clk_sclk_apll.clk,
};
-static struct clksrc_sources clkset_mout_corebus = {
+struct clksrc_sources clkset_mout_corebus = {
.sources = clkset_corebus_list,
.nr_sources = ARRAY_SIZE(clkset_corebus_list),
};
@@ -284,12 +348,12 @@ static struct clksrc_clk clk_pclk_acp = {
/* Core list of CMU_TOP side */
-static struct clk *clkset_aclk_top_list[] = {
+struct clk *clkset_aclk_top_list[] = {
[0] = &clk_mout_mpll.clk,
[1] = &clk_sclk_apll.clk,
};
-static struct clksrc_sources clkset_aclk = {
+struct clksrc_sources clkset_aclk = {
.sources = clkset_aclk_top_list,
.nr_sources = ARRAY_SIZE(clkset_aclk_top_list),
};
@@ -321,7 +385,7 @@ static struct clksrc_clk clk_aclk_160 = {
.reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
};
-static struct clksrc_clk clk_aclk_133 = {
+struct clksrc_clk clk_aclk_133 = {
.clk = {
.name = "aclk_133",
},
@@ -360,7 +424,7 @@ static struct clksrc_sources clkset_sclk_vpll = {
.nr_sources = ARRAY_SIZE(clkset_sclk_vpll_list),
};
-static struct clksrc_clk clk_sclk_vpll = {
+struct clksrc_clk clk_sclk_vpll = {
.clk = {
.name = "sclk_vpll",
},
@@ -410,16 +474,6 @@ static struct clk init_clocks_off[] = {
.enable = exynos4_clk_ip_lcd0_ctrl,
.ctrlbit = (1 << 0),
}, {
- .name = "fimd",
- .devname = "exynos4-fb.1",
- .enable = exynos4_clk_ip_lcd1_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "sataphy",
- .parent = &clk_aclk_133.clk,
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 3),
- }, {
.name = "hsmmc",
.devname = "s3c-sdhci.0",
.parent = &clk_aclk_133.clk,
@@ -449,11 +503,6 @@ static struct clk init_clocks_off[] = {
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 9),
}, {
- .name = "sata",
- .parent = &clk_aclk_133.clk,
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 10),
- }, {
.name = "pdma",
.devname = "s3c-pl330.0",
.enable = exynos4_clk_ip_fsys_ctrl,
@@ -673,7 +722,7 @@ static struct clk init_clocks[] = {
}
};
-static struct clk *clkset_group_list[] = {
+struct clk *clkset_group_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_xusbxti,
[2] = &clk_sclk_hdmi27m,
@@ -685,7 +734,7 @@ static struct clk *clkset_group_list[] = {
[8] = &clk_sclk_vpll.clk,
};
-static struct clksrc_sources clkset_group = {
+struct clksrc_sources clkset_group = {
.sources = clkset_group_list,
.nr_sources = ARRAY_SIZE(clkset_group_list),
};
@@ -967,25 +1016,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
}, {
.clk = {
- .name = "sclk_fimd",
- .devname = "exynos4-fb.1",
- .enable = exynos4_clksrc_mask_lcd1_ctrl,
- .ctrlbit = (1 << 0),
- },
- .sources = &clkset_group,
- .reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
- .reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_sata",
- .enable = exynos4_clksrc_mask_fsys_ctrl,
- .ctrlbit = (1 << 24),
- },
- .sources = &clkset_mout_corebus,
- .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
- .reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
- }, {
- .clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.0",
.enable = exynos4_clksrc_mask_peril1_ctrl,
@@ -1114,7 +1144,13 @@ static int xtal_rate;
static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
{
- return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), pll_4508);
+ if (soc_is_exynos4210())
+ return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0),
+ pll_4508);
+ else if (soc_is_exynos4212() || soc_is_exynos4412())
+ return s5p_get_pll35xx(xtal_rate, __raw_readl(S5P_APLL_CON0));
+ else
+ return 0;
}
static struct clk_ops exynos4_fout_apll_ops = {
@@ -1124,10 +1160,10 @@ static struct clk_ops exynos4_fout_apll_ops = {
void __init_or_cpufreq exynos4_setup_clocks(void)
{
struct clk *xtal_clk;
- unsigned long apll;
- unsigned long mpll;
- unsigned long epll;
- unsigned long vpll;
+ unsigned long apll = 0;
+ unsigned long mpll = 0;
+ unsigned long epll = 0;
+ unsigned long vpll = 0;
unsigned long vpllsrc;
unsigned long xtal;
unsigned long armclk;
@@ -1151,14 +1187,29 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
- apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
- mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
- epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
- __raw_readl(S5P_EPLL_CON1), pll_4600);
-
- vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
- vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
- __raw_readl(S5P_VPLL_CON1), pll_4650c);
+ if (soc_is_exynos4210()) {
+ apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0),
+ pll_4508);
+ mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0),
+ pll_4508);
+ epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
+ __raw_readl(S5P_EPLL_CON1), pll_4600);
+
+ vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+ vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+ __raw_readl(S5P_VPLL_CON1), pll_4650c);
+ } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
+ apll = s5p_get_pll35xx(xtal, __raw_readl(S5P_APLL_CON0));
+ mpll = s5p_get_pll35xx(xtal, __raw_readl(S5P_MPLL_CON0));
+ epll = s5p_get_pll36xx(xtal, __raw_readl(S5P_EPLL_CON0),
+ __raw_readl(S5P_EPLL_CON1));
+
+ vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+ vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+ __raw_readl(S5P_VPLL_CON1));
+ } else {
+ /* nothing */
+ }
clk_fout_apll.ops = &exynos4_fout_apll_ops;
clk_fout_mpll.rate = mpll;
@@ -1193,6 +1244,28 @@ static struct clk *clks[] __initdata = {
/* Nothing here yet */
};
+#ifdef CONFIG_PM_SLEEP
+static int exynos4_clock_suspend(void)
+{
+ s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
+ return 0;
+}
+
+static void exynos4_clock_resume(void)
+{
+ s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
+}
+
+#else
+#define exynos4_clock_suspend NULL
+#define exynos4_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4_clock_syscore_ops = {
+ .suspend = exynos4_clock_suspend,
+ .resume = exynos4_clock_resume,
+};
+
void __init exynos4_register_clocks(void)
{
int ptr;
@@ -1208,5 +1281,6 @@ void __init exynos4_register_clocks(void)
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ register_syscore_ops(&exynos4_clock_syscore_ops);
s3c_pwmclk_init();
}
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 746d6fc6d397..a348434f17b5 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -32,6 +32,8 @@
#include <mach/regs-irq.h>
#include <mach/regs-pmu.h>
+unsigned int gic_bank_offset __read_mostly;
+
extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
unsigned int irq_start);
extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
@@ -44,11 +46,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.length = SZ_4K,
.type = MT_DEVICE,
}, {
- .virtual = (unsigned long)S5P_VA_SYSRAM,
- .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
.virtual = (unsigned long)S5P_VA_CMU,
.pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
.length = SZ_128K,
@@ -121,6 +118,24 @@ static struct map_desc exynos4_iodesc[] __initdata = {
},
};
+static struct map_desc exynos4_iodesc0[] __initdata = {
+ {
+ .virtual = (unsigned long)S5P_VA_SYSRAM,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static struct map_desc exynos4_iodesc1[] __initdata = {
+ {
+ .virtual = (unsigned long)S5P_VA_SYSRAM,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
static void exynos4_idle(void)
{
if (!need_resched())
@@ -143,6 +158,11 @@ void __init exynos4_map_io(void)
{
iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
+ if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
+ iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0));
+ else
+ iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
+
/* initialize device information early */
exynos4_default_sdhci0();
exynos4_default_sdhci1();
@@ -170,24 +190,37 @@ void __init exynos4_init_clocks(int xtal)
s3c24xx_register_baseclocks(xtal);
s5p_register_clocks(xtal);
+
+ if (soc_is_exynos4210())
+ exynos4210_register_clocks();
+ else if (soc_is_exynos4212() || soc_is_exynos4412())
+ exynos4212_register_clocks();
+
exynos4_register_clocks();
exynos4_setup_clocks();
}
-static void exynos4_gic_irq_eoi(struct irq_data *d)
+static void exynos4_gic_irq_fix_base(struct irq_data *d)
{
struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
gic_data->cpu_base = S5P_VA_GIC_CPU +
- (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+ (gic_bank_offset * smp_processor_id());
+
+ gic_data->dist_base = S5P_VA_GIC_DIST +
+ (gic_bank_offset * smp_processor_id());
}
void __init exynos4_init_irq(void)
{
int irq;
- gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
- gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
+ gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
+
+ gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+ gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base;
+ gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base;
+ gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base;
for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
@@ -223,7 +256,11 @@ static int __init exynos4_l2x0_cache_init(void)
{
/* TAG, Data Latency Control: 2cycle */
__raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
- __raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+
+ if (soc_is_exynos4210())
+ __raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+ else if (soc_is_exynos4212() || soc_is_exynos4412())
+ __raw_writel(0x120, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
/* L2X0 Prefetch Control */
__raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
diff --git a/arch/arm/mach-exynos4/hotplug.c b/arch/arm/mach-exynos4/hotplug.c
index 7490789784c9..da70e7e39937 100644
--- a/arch/arm/mach-exynos4/hotplug.c
+++ b/arch/arm/mach-exynos4/hotplug.c
@@ -75,7 +75,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
:
: "memory", "cc");
- if (pen_release == cpu) {
+ if (pen_release == cpu_logical_map(cpu)) {
/*
* OK, proper wakeup, we're done
*/
diff --git a/arch/arm/mach-exynos4/include/mach/debug-macro.S b/arch/arm/mach-exynos4/include/mach/debug-macro.S
index a442ef861167..6cacf16a67a6 100644
--- a/arch/arm/mach-exynos4/include/mach/debug-macro.S
+++ b/arch/arm/mach-exynos4/include/mach/debug-macro.S
@@ -20,7 +20,7 @@
* aligned and add in the offset when we load the value here.
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, = S3C_PA_UART
ldr \rv, = S3C_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
index d7a1e281ce7a..f5e9fd8e37b4 100644
--- a/arch/arm/mach-exynos4/include/mach/entry-macro.S
+++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
@@ -17,12 +17,25 @@
.endm
.macro get_irqnr_preamble, base, tmp
- ldr \base, =gic_cpu_base_addr
+ mov \tmp, #0
+
+ mrc p15, 0, \base, c0, c0, 5
+ and \base, \base, #3
+ cmp \base, #0
+ beq 1f
+
+ ldr \tmp, =gic_bank_offset
+ ldr \tmp, [\tmp]
+ cmp \base, #1
+ beq 1f
+
+ cmp \base, #2
+ addeq \tmp, \tmp, \tmp
+ addne \tmp, \tmp, \tmp, LSL #1
+
+1: ldr \base, =gic_cpu_base_addr
ldr \base, [\base]
- mrc p15, 0, \tmp, c0, c0, 5
- and \tmp, \tmp, #3
- cmp \tmp, #1
- addeq \base, \base, #EXYNOS4_GIC_BANK_OFFSET
+ add \base, \base, \tmp
.endm
.macro arch_ret_to_user, tmp1, tmp2
@@ -55,7 +68,7 @@
bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #29
+ cmp \irqnr, #15
cmpcc \irqnr, \irqnr
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
@@ -76,8 +89,3 @@
strcc \irqstat, [\base, #GIC_CPU_EOI]
cmpcs \irqnr, \irqnr
.endm
-
- /* As above, this assumes that irqstat and base are preserved.. */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- .endm
diff --git a/arch/arm/mach-exynos4/include/mach/exynos4-clock.h b/arch/arm/mach-exynos4/include/mach/exynos4-clock.h
new file mode 100644
index 000000000000..a07fcbf55251
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/exynos4-clock.h
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/arm/mach-exynos4/include/mach/exynos4-clock.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Header file for exynos4 clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+extern struct clk clk_sclk_hdmi27m;
+extern struct clk clk_sclk_usbphy0;
+extern struct clk clk_sclk_usbphy1;
+extern struct clk clk_sclk_hdmiphy;
+
+extern struct clksrc_clk clk_sclk_apll;
+extern struct clksrc_clk clk_mout_mpll;
+extern struct clksrc_clk clk_aclk_133;
+extern struct clksrc_clk clk_mout_epll;
+extern struct clksrc_clk clk_sclk_vpll;
+
+extern struct clk *clkset_corebus_list[];
+extern struct clksrc_sources clkset_mout_corebus;
+
+extern struct clk *clkset_aclk_top_list[];
+extern struct clksrc_sources clkset_aclk;
+
+extern struct clk *clkset_group_list[];
+extern struct clksrc_sources clkset_group;
+
+extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
+
+#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-exynos4/include/mach/gpio.h b/arch/arm/mach-exynos4/include/mach/gpio.h
index be9266b10fdb..80523ca9bb49 100644
--- a/arch/arm/mach-exynos4/include/mach/gpio.h
+++ b/arch/arm/mach-exynos4/include/mach/gpio.h
@@ -13,11 +13,6 @@
#ifndef __ASM_ARCH_GPIO_H
#define __ASM_ARCH_GPIO_H __FILE__
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
/* Practically, GPIO banks up to GPZ are the configurable gpio banks */
/* GPIO bank sizes */
@@ -151,6 +146,4 @@ enum s5p_gpio_number {
#define ARCH_NR_GPIOS (EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) + \
CONFIG_SAMSUNG_GPIO_EXTRA + 1)
-#include <asm-generic/gpio.h>
-
#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index f8952f8f3757..2d3f6bcd9bc0 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -19,6 +19,8 @@
#define IRQ_PPI(x) S5P_IRQ(x+16)
+#define IRQ_MCT_LOCALTIMER IRQ_PPI(12)
+
/* SPI: Shared Peripheral Interrupt */
#define IRQ_SPI(x) S5P_IRQ(x+32)
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index d32296dc65e2..9f97eb8499ee 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -23,7 +23,8 @@
#include <plat/map-s5p.h>
-#define EXYNOS4_PA_SYSRAM 0x02020000
+#define EXYNOS4_PA_SYSRAM0 0x02025000
+#define EXYNOS4_PA_SYSRAM1 0x02020000
#define EXYNOS4_PA_FIMC0 0x11800000
#define EXYNOS4_PA_FIMC1 0x11810000
@@ -61,7 +62,6 @@
#define EXYNOS4_PA_GIC_CPU 0x10480000
#define EXYNOS4_PA_GIC_DIST 0x10490000
-#define EXYNOS4_GIC_BANK_OFFSET 0x8000
#define EXYNOS4_PA_COREPERI 0x10500000
#define EXYNOS4_PA_TWD 0x10500600
diff --git a/arch/arm/mach-exynos4/include/mach/regs-clock.h b/arch/arm/mach-exynos4/include/mach/regs-clock.h
index d493fdb422ff..6c37ebe94829 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-clock.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-clock.h
@@ -13,6 +13,7 @@
#ifndef __ASM_ARCH_REGS_CLOCK_H
#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+#include <plat/cpu.h>
#include <mach/map.h>
#define S5P_CLKREG(x) (S5P_VA_CMU + (x))
@@ -41,12 +42,20 @@
#define S5P_CLKSRC_G3D S5P_CLKREG(0x0C22C)
#define S5P_CLKSRC_IMAGE S5P_CLKREG(0x0C230)
#define S5P_CLKSRC_LCD0 S5P_CLKREG(0x0C234)
-#define S5P_CLKSRC_LCD1 S5P_CLKREG(0x0C238)
#define S5P_CLKSRC_MAUDIO S5P_CLKREG(0x0C23C)
#define S5P_CLKSRC_FSYS S5P_CLKREG(0x0C240)
#define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x0C250)
#define S5P_CLKSRC_PERIL1 S5P_CLKREG(0x0C254)
+#define S5P_CLKSRC_MASK_TOP S5P_CLKREG(0x0C310)
+#define S5P_CLKSRC_MASK_CAM S5P_CLKREG(0x0C320)
+#define S5P_CLKSRC_MASK_TV S5P_CLKREG(0x0C324)
+#define S5P_CLKSRC_MASK_LCD0 S5P_CLKREG(0x0C334)
+#define S5P_CLKSRC_MASK_MAUDIO S5P_CLKREG(0x0C33C)
+#define S5P_CLKSRC_MASK_FSYS S5P_CLKREG(0x0C340)
+#define S5P_CLKSRC_MASK_PERIL0 S5P_CLKREG(0x0C350)
+#define S5P_CLKSRC_MASK_PERIL1 S5P_CLKREG(0x0C354)
+
#define S5P_CLKDIV_TOP S5P_CLKREG(0x0C510)
#define S5P_CLKDIV_CAM S5P_CLKREG(0x0C520)
#define S5P_CLKDIV_TV S5P_CLKREG(0x0C524)
@@ -54,7 +63,6 @@
#define S5P_CLKDIV_G3D S5P_CLKREG(0x0C52C)
#define S5P_CLKDIV_IMAGE S5P_CLKREG(0x0C530)
#define S5P_CLKDIV_LCD0 S5P_CLKREG(0x0C534)
-#define S5P_CLKDIV_LCD1 S5P_CLKREG(0x0C538)
#define S5P_CLKDIV_MAUDIO S5P_CLKREG(0x0C53C)
#define S5P_CLKDIV_FSYS0 S5P_CLKREG(0x0C540)
#define S5P_CLKDIV_FSYS1 S5P_CLKREG(0x0C544)
@@ -68,16 +76,6 @@
#define S5P_CLKDIV_PERIL5 S5P_CLKREG(0x0C564)
#define S5P_CLKDIV2_RATIO S5P_CLKREG(0x0C580)
-#define S5P_CLKSRC_MASK_TOP S5P_CLKREG(0x0C310)
-#define S5P_CLKSRC_MASK_CAM S5P_CLKREG(0x0C320)
-#define S5P_CLKSRC_MASK_TV S5P_CLKREG(0x0C324)
-#define S5P_CLKSRC_MASK_LCD0 S5P_CLKREG(0x0C334)
-#define S5P_CLKSRC_MASK_LCD1 S5P_CLKREG(0x0C338)
-#define S5P_CLKSRC_MASK_MAUDIO S5P_CLKREG(0x0C33C)
-#define S5P_CLKSRC_MASK_FSYS S5P_CLKREG(0x0C340)
-#define S5P_CLKSRC_MASK_PERIL0 S5P_CLKREG(0x0C350)
-#define S5P_CLKSRC_MASK_PERIL1 S5P_CLKREG(0x0C354)
-
#define S5P_CLKDIV_STAT_TOP S5P_CLKREG(0x0C610)
#define S5P_CLKGATE_SCLKCAM S5P_CLKREG(0x0C820)
@@ -85,13 +83,20 @@
#define S5P_CLKGATE_IP_TV S5P_CLKREG(0x0C924)
#define S5P_CLKGATE_IP_MFC S5P_CLKREG(0x0C928)
#define S5P_CLKGATE_IP_G3D S5P_CLKREG(0x0C92C)
-#define S5P_CLKGATE_IP_IMAGE S5P_CLKREG(0x0C930)
+#define S5P_CLKGATE_IP_IMAGE (soc_is_exynos4210() ? \
+ S5P_CLKREG(0x0C930) : \
+ S5P_CLKREG(0x04930))
+#define S5P_CLKGATE_IP_IMAGE_4210 S5P_CLKREG(0x0C930)
+#define S5P_CLKGATE_IP_IMAGE_4212 S5P_CLKREG(0x04930)
#define S5P_CLKGATE_IP_LCD0 S5P_CLKREG(0x0C934)
-#define S5P_CLKGATE_IP_LCD1 S5P_CLKREG(0x0C938)
#define S5P_CLKGATE_IP_FSYS S5P_CLKREG(0x0C940)
#define S5P_CLKGATE_IP_GPS S5P_CLKREG(0x0C94C)
#define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x0C950)
-#define S5P_CLKGATE_IP_PERIR S5P_CLKREG(0x0C960)
+#define S5P_CLKGATE_IP_PERIR (soc_is_exynos4210() ? \
+ S5P_CLKREG(0x0C960) : \
+ S5P_CLKREG(0x08960))
+#define S5P_CLKGATE_IP_PERIR_4210 S5P_CLKREG(0x0C960)
+#define S5P_CLKGATE_IP_PERIR_4212 S5P_CLKREG(0x08960)
#define S5P_CLKGATE_BLOCK S5P_CLKREG(0x0C970)
#define S5P_CLKSRC_MASK_DMC S5P_CLKREG(0x10300)
@@ -102,11 +107,17 @@
#define S5P_CLKGATE_IP_DMC S5P_CLKREG(0x10900)
#define S5P_APLL_LOCK S5P_CLKREG(0x14000)
-#define S5P_MPLL_LOCK S5P_CLKREG(0x14004)
+#define S5P_MPLL_LOCK (soc_is_exynos4210() ? \
+ S5P_CLKREG(0x14004) : \
+ S5P_CLKREG(0x10008))
#define S5P_APLL_CON0 S5P_CLKREG(0x14100)
#define S5P_APLL_CON1 S5P_CLKREG(0x14104)
-#define S5P_MPLL_CON0 S5P_CLKREG(0x14108)
-#define S5P_MPLL_CON1 S5P_CLKREG(0x1410C)
+#define S5P_MPLL_CON0 (soc_is_exynos4210() ? \
+ S5P_CLKREG(0x14108) : \
+ S5P_CLKREG(0x10108))
+#define S5P_MPLL_CON1 (soc_is_exynos4210() ? \
+ S5P_CLKREG(0x1410C) : \
+ S5P_CLKREG(0x1010C))
#define S5P_CLKSRC_CPU S5P_CLKREG(0x14200)
#define S5P_CLKMUX_STATCPU S5P_CLKREG(0x14400)
@@ -183,6 +194,13 @@
#define S5P_CLKDIV_BUS_GPLR_SHIFT (4)
#define S5P_CLKDIV_BUS_GPLR_MASK (0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
+/* Only for EXYNOS4210 */
+
+#define S5P_CLKSRC_LCD1 S5P_CLKREG(0x0C238)
+#define S5P_CLKSRC_MASK_LCD1 S5P_CLKREG(0x0C338)
+#define S5P_CLKDIV_LCD1 S5P_CLKREG(0x0C538)
+#define S5P_CLKGATE_IP_LCD1 S5P_CLKREG(0x0C938)
+
/* Compatibility defines and inclusion */
#include <mach/regs-pmu.h>
diff --git a/arch/arm/mach-exynos4/include/mach/regs-mct.h b/arch/arm/mach-exynos4/include/mach/regs-mct.h
index ca9c8434b023..80dd02ad6d61 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-mct.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-mct.h
@@ -31,8 +31,9 @@
#define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248)
#define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C)
-#define EXYNOS4_MCT_L0_BASE EXYNOS4_MCTREG(0x300)
-#define EXYNOS4_MCT_L1_BASE EXYNOS4_MCTREG(0x400)
+#define _EXYNOS4_MCT_L_BASE EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * x))
+#define EXYNOS4_MCT_L_MASK (0xffffff00)
#define MCT_L_TCNTB_OFFSET (0x00)
#define MCT_L_ICNTB_OFFSET (0x08)
diff --git a/arch/arm/mach-exynos4/mach-armlex4210.c b/arch/arm/mach-exynos4/mach-armlex4210.c
index b482c6285fc4..f0ca6c157d29 100644
--- a/arch/arm/mach-exynos4/mach-armlex4210.c
+++ b/arch/arm/mach-exynos4/mach-armlex4210.c
@@ -207,7 +207,7 @@ static void __init armlex4210_machine_init(void)
MACHINE_START(ARMLEX4210, "ARMLEX4210")
/* Maintainer: Alim Akhtar <alim.akhtar@samsung.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = exynos4_init_irq,
.map_io = armlex4210_map_io,
.init_machine = armlex4210_machine_init,
diff --git a/arch/arm/mach-exynos4/mach-nuri.c b/arch/arm/mach-exynos4/mach-nuri.c
index 43be71b799cb..6e0536818bf5 100644
--- a/arch/arm/mach-exynos4/mach-nuri.c
+++ b/arch/arm/mach-exynos4/mach-nuri.c
@@ -1152,7 +1152,7 @@ static void __init nuri_machine_init(void)
MACHINE_START(NURI, "NURI")
/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = exynos4_init_irq,
.map_io = nuri_map_io,
.init_machine = nuri_machine_init,
diff --git a/arch/arm/mach-exynos4/mach-origen.c b/arch/arm/mach-exynos4/mach-origen.c
new file mode 100644
index 000000000000..b5f6f38557c9
--- /dev/null
+++ b/arch/arm/mach-exynos4/mach-origen.c
@@ -0,0 +1,108 @@
+/* linux/arch/arm/mach-exynos4/mach-origen.c
+ *
+ * Copyright (c) 2011 Insignal Co., Ltd.
+ * http://www.insignal.co.kr/
+ *
+ * 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/serial_core.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/input.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define ORIGEN_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
+ S3C2410_UCON_RXILEVEL | \
+ S3C2410_UCON_TXIRQMODE | \
+ S3C2410_UCON_RXIRQMODE | \
+ S3C2410_UCON_RXFIFO_TOI | \
+ S3C2443_UCON_RXERR_IRQEN)
+
+#define ORIGEN_ULCON_DEFAULT S3C2410_LCON_CS8
+
+#define ORIGEN_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
+ S5PV210_UFCON_TXTRIG4 | \
+ S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = ORIGEN_UCON_DEFAULT,
+ .ulcon = ORIGEN_ULCON_DEFAULT,
+ .ufcon = ORIGEN_UFCON_DEFAULT,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = ORIGEN_UCON_DEFAULT,
+ .ulcon = ORIGEN_ULCON_DEFAULT,
+ .ufcon = ORIGEN_UFCON_DEFAULT,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = ORIGEN_UCON_DEFAULT,
+ .ulcon = ORIGEN_ULCON_DEFAULT,
+ .ufcon = ORIGEN_UFCON_DEFAULT,
+ },
+ [3] = {
+ .hwport = 3,
+ .flags = 0,
+ .ucon = ORIGEN_UCON_DEFAULT,
+ .ulcon = ORIGEN_ULCON_DEFAULT,
+ .ufcon = ORIGEN_UFCON_DEFAULT,
+ },
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
+ .cd_type = S3C_SDHCI_CD_GPIO,
+ .ext_cd_gpio = EXYNOS4_GPK2(2),
+ .ext_cd_gpio_invert = 1,
+ .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct platform_device *origen_devices[] __initdata = {
+ &s3c_device_hsmmc2,
+ &s3c_device_rtc,
+ &s3c_device_wdt,
+};
+
+static void __init origen_map_io(void)
+{
+ s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+ s3c24xx_init_clocks(24000000);
+ s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
+}
+
+static void __init origen_machine_init(void)
+{
+ s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
+ platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
+}
+
+MACHINE_START(ORIGEN, "ORIGEN")
+ /* Maintainer: JeongHyeon Kim <jhkim@insignal.co.kr> */
+ .atag_offset = 0x100,
+ .init_irq = exynos4_init_irq,
+ .map_io = origen_map_io,
+ .init_machine = origen_machine_init,
+ .timer = &exynos4_timer,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdk4x12.c b/arch/arm/mach-exynos4/mach-smdk4x12.c
new file mode 100644
index 000000000000..fcf2e0e23d53
--- /dev/null
+++ b/arch/arm/mach-exynos4/mach-smdk4x12.c
@@ -0,0 +1,302 @@
+/*
+ * linux/arch/arm/mach-exynos4/mach-smdk4x12.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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/gpio.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/machine.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/backlight.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/exynos4.h>
+#include <plat/gpio-cfg.h>
+#include <plat/iic.h>
+#include <plat/keypad.h>
+#include <plat/regs-serial.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define SMDK4X12_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
+ S3C2410_UCON_RXILEVEL | \
+ S3C2410_UCON_TXIRQMODE | \
+ S3C2410_UCON_RXIRQMODE | \
+ S3C2410_UCON_RXFIFO_TOI | \
+ S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDK4X12_ULCON_DEFAULT S3C2410_LCON_CS8
+
+#define SMDK4X12_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
+ S5PV210_UFCON_TXTRIG4 | \
+ S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdk4x12_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = SMDK4X12_UCON_DEFAULT,
+ .ulcon = SMDK4X12_ULCON_DEFAULT,
+ .ufcon = SMDK4X12_UFCON_DEFAULT,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = SMDK4X12_UCON_DEFAULT,
+ .ulcon = SMDK4X12_ULCON_DEFAULT,
+ .ufcon = SMDK4X12_UFCON_DEFAULT,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = SMDK4X12_UCON_DEFAULT,
+ .ulcon = SMDK4X12_ULCON_DEFAULT,
+ .ufcon = SMDK4X12_UFCON_DEFAULT,
+ },
+ [3] = {
+ .hwport = 3,
+ .flags = 0,
+ .ucon = SMDK4X12_UCON_DEFAULT,
+ .ulcon = SMDK4X12_ULCON_DEFAULT,
+ .ufcon = SMDK4X12_UFCON_DEFAULT,
+ },
+};
+
+static struct s3c_sdhci_platdata smdk4x12_hsmmc2_pdata __initdata = {
+ .cd_type = S3C_SDHCI_CD_INTERNAL,
+ .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
+ .max_width = 8,
+ .host_caps = MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdk4x12_hsmmc3_pdata __initdata = {
+ .cd_type = S3C_SDHCI_CD_INTERNAL,
+ .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct regulator_consumer_supply max8997_buck1 =
+ REGULATOR_SUPPLY("vdd_arm", NULL);
+
+static struct regulator_consumer_supply max8997_buck2 =
+ REGULATOR_SUPPLY("vdd_int", NULL);
+
+static struct regulator_consumer_supply max8997_buck3 =
+ REGULATOR_SUPPLY("vdd_g3d", NULL);
+
+static struct regulator_init_data max8997_buck1_data = {
+ .constraints = {
+ .name = "VDD_ARM_SMDK4X12",
+ .min_uV = 925000,
+ .max_uV = 1350000,
+ .always_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &max8997_buck1,
+};
+
+static struct regulator_init_data max8997_buck2_data = {
+ .constraints = {
+ .name = "VDD_INT_SMDK4X12",
+ .min_uV = 950000,
+ .max_uV = 1150000,
+ .always_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &max8997_buck2,
+};
+
+static struct regulator_init_data max8997_buck3_data = {
+ .constraints = {
+ .name = "VDD_G3D_SMDK4X12",
+ .min_uV = 950000,
+ .max_uV = 1150000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &max8997_buck3,
+};
+
+static struct max8997_regulator_data smdk4x12_max8997_regulators[] = {
+ { MAX8997_BUCK1, &max8997_buck1_data },
+ { MAX8997_BUCK2, &max8997_buck2_data },
+ { MAX8997_BUCK3, &max8997_buck3_data },
+};
+
+static struct max8997_platform_data smdk4x12_max8997_pdata = {
+ .num_regulators = ARRAY_SIZE(smdk4x12_max8997_regulators),
+ .regulators = smdk4x12_max8997_regulators,
+
+ .buck1_voltage[0] = 1100000, /* 1.1V */
+ .buck1_voltage[1] = 1100000, /* 1.1V */
+ .buck1_voltage[2] = 1100000, /* 1.1V */
+ .buck1_voltage[3] = 1100000, /* 1.1V */
+ .buck1_voltage[4] = 1100000, /* 1.1V */
+ .buck1_voltage[5] = 1100000, /* 1.1V */
+ .buck1_voltage[6] = 1000000, /* 1.0V */
+ .buck1_voltage[7] = 950000, /* 0.95V */
+
+ .buck2_voltage[0] = 1100000, /* 1.1V */
+ .buck2_voltage[1] = 1000000, /* 1.0V */
+ .buck2_voltage[2] = 950000, /* 0.95V */
+ .buck2_voltage[3] = 900000, /* 0.9V */
+ .buck2_voltage[4] = 1100000, /* 1.1V */
+ .buck2_voltage[5] = 1000000, /* 1.0V */
+ .buck2_voltage[6] = 950000, /* 0.95V */
+ .buck2_voltage[7] = 900000, /* 0.9V */
+
+ .buck5_voltage[0] = 1100000, /* 1.1V */
+ .buck5_voltage[1] = 1100000, /* 1.1V */
+ .buck5_voltage[2] = 1100000, /* 1.1V */
+ .buck5_voltage[3] = 1100000, /* 1.1V */
+ .buck5_voltage[4] = 1100000, /* 1.1V */
+ .buck5_voltage[5] = 1100000, /* 1.1V */
+ .buck5_voltage[6] = 1100000, /* 1.1V */
+ .buck5_voltage[7] = 1100000, /* 1.1V */
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs0[] __initdata = {
+ {
+ I2C_BOARD_INFO("max8997", 0x66),
+ .platform_data = &smdk4x12_max8997_pdata,
+ }
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs1[] __initdata = {
+ { I2C_BOARD_INFO("wm8994", 0x1a), }
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs3[] __initdata = {
+ /* nothing here yet */
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs7[] __initdata = {
+ /* nothing here yet */
+};
+
+static struct samsung_bl_gpio_info smdk4x12_bl_gpio_info = {
+ .no = EXYNOS4_GPD0(1),
+ .func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdk4x12_bl_data = {
+ .pwm_id = 1,
+ .pwm_period_ns = 1000,
+};
+
+static uint32_t smdk4x12_keymap[] __initdata = {
+ /* KEY(row, col, keycode) */
+ KEY(1, 0, KEY_D), KEY(1, 1, KEY_A), KEY(1, 2, KEY_B),
+ KEY(1, 3, KEY_E), KEY(1, 4, KEY_C)
+};
+
+static struct matrix_keymap_data smdk4x12_keymap_data __initdata = {
+ .keymap = smdk4x12_keymap,
+ .keymap_size = ARRAY_SIZE(smdk4x12_keymap),
+};
+
+static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = {
+ .keymap_data = &smdk4x12_keymap_data,
+ .rows = 2,
+ .cols = 5,
+};
+
+static struct platform_device *smdk4x12_devices[] __initdata = {
+ &s3c_device_hsmmc2,
+ &s3c_device_hsmmc3,
+ &s3c_device_i2c0,
+ &s3c_device_i2c1,
+ &s3c_device_i2c3,
+ &s3c_device_i2c7,
+ &s3c_device_rtc,
+ &s3c_device_wdt,
+ &samsung_device_keypad,
+};
+
+static void __init smdk4x12_map_io(void)
+{
+ clk_xusbxti.rate = 24000000;
+
+ s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+ s3c24xx_init_clocks(clk_xusbxti.rate);
+ s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
+}
+
+static void __init smdk4x12_machine_init(void)
+{
+ s3c_i2c0_set_platdata(NULL);
+ i2c_register_board_info(0, smdk4x12_i2c_devs0,
+ ARRAY_SIZE(smdk4x12_i2c_devs0));
+
+ s3c_i2c1_set_platdata(NULL);
+ i2c_register_board_info(1, smdk4x12_i2c_devs1,
+ ARRAY_SIZE(smdk4x12_i2c_devs1));
+
+ s3c_i2c3_set_platdata(NULL);
+ i2c_register_board_info(3, smdk4x12_i2c_devs3,
+ ARRAY_SIZE(smdk4x12_i2c_devs3));
+
+ s3c_i2c7_set_platdata(NULL);
+ i2c_register_board_info(7, smdk4x12_i2c_devs7,
+ ARRAY_SIZE(smdk4x12_i2c_devs7));
+
+ samsung_bl_set(&smdk4x12_bl_gpio_info, &smdk4x12_bl_data);
+
+ samsung_keypad_set_platdata(&smdk4x12_keypad_data);
+
+ s3c_sdhci2_set_platdata(&smdk4x12_hsmmc2_pdata);
+ s3c_sdhci3_set_platdata(&smdk4x12_hsmmc3_pdata);
+
+ platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices));
+}
+
+MACHINE_START(SMDK4212, "SMDK4212")
+ /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+ .atag_offset = 0x100,
+ .init_irq = exynos4_init_irq,
+ .map_io = smdk4x12_map_io,
+ .init_machine = smdk4x12_machine_init,
+ .timer = &exynos4_timer,
+MACHINE_END
+
+MACHINE_START(SMDK4412, "SMDK4412")
+ /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+ /* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
+ .atag_offset = 0x100,
+ .init_irq = exynos4_init_irq,
+ .map_io = smdk4x12_map_io,
+ .init_machine = smdk4x12_machine_init,
+ .timer = &exynos4_timer,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdkc210.c b/arch/arm/mach-exynos4/mach-smdkc210.c
deleted file mode 100644
index a7c65e05c1eb..000000000000
--- a/arch/arm/mach-exynos4/mach-smdkc210.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/* linux/arch/arm/mach-exynos4/mach-smdkc210.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.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/serial_core.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/lcd.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/smsc911x.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/pwm_backlight.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <video/platform_lcd.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-srom.h>
-#include <plat/regs-fb-v4.h>
-#include <plat/exynos4.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/fb.h>
-#include <plat/sdhci.h>
-#include <plat/iic.h>
-#include <plat/pd.h>
-#include <plat/gpio-cfg.h>
-#include <plat/backlight.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKC210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
- S3C2410_UCON_RXILEVEL | \
- S3C2410_UCON_TXIRQMODE | \
- S3C2410_UCON_RXIRQMODE | \
- S3C2410_UCON_RXFIFO_TOI | \
- S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKC210_ULCON_DEFAULT S3C2410_LCON_CS8
-
-#define SMDKC210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
- S5PV210_UFCON_TXTRIG4 | \
- S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkc210_uartcfgs[] __initdata = {
- [0] = {
- .hwport = 0,
- .flags = 0,
- .ucon = SMDKC210_UCON_DEFAULT,
- .ulcon = SMDKC210_ULCON_DEFAULT,
- .ufcon = SMDKC210_UFCON_DEFAULT,
- },
- [1] = {
- .hwport = 1,
- .flags = 0,
- .ucon = SMDKC210_UCON_DEFAULT,
- .ulcon = SMDKC210_ULCON_DEFAULT,
- .ufcon = SMDKC210_UFCON_DEFAULT,
- },
- [2] = {
- .hwport = 2,
- .flags = 0,
- .ucon = SMDKC210_UCON_DEFAULT,
- .ulcon = SMDKC210_ULCON_DEFAULT,
- .ufcon = SMDKC210_UFCON_DEFAULT,
- },
- [3] = {
- .hwport = 3,
- .flags = 0,
- .ucon = SMDKC210_UCON_DEFAULT,
- .ulcon = SMDKC210_ULCON_DEFAULT,
- .ufcon = SMDKC210_UFCON_DEFAULT,
- },
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc0_pdata __initdata = {
- .cd_type = S3C_SDHCI_CD_GPIO,
- .ext_cd_gpio = EXYNOS4_GPK0(2),
- .ext_cd_gpio_invert = 1,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
- .max_width = 8,
- .host_caps = MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc1_pdata __initdata = {
- .cd_type = S3C_SDHCI_CD_GPIO,
- .ext_cd_gpio = EXYNOS4_GPK0(2),
- .ext_cd_gpio_invert = 1,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc2_pdata __initdata = {
- .cd_type = S3C_SDHCI_CD_GPIO,
- .ext_cd_gpio = EXYNOS4_GPK2(2),
- .ext_cd_gpio_invert = 1,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
- .max_width = 8,
- .host_caps = MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
- .cd_type = S3C_SDHCI_CD_GPIO,
- .ext_cd_gpio = EXYNOS4_GPK2(2),
- .ext_cd_gpio_invert = 1,
- .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
- unsigned int power)
-{
- if (power) {
-#if !defined(CONFIG_BACKLIGHT_PWM)
- gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
- gpio_free(EXYNOS4_GPD0(1));
-#endif
- /* fire nRESET on power up */
- gpio_request(EXYNOS4_GPX0(6), "GPX0");
-
- gpio_direction_output(EXYNOS4_GPX0(6), 1);
- mdelay(100);
-
- gpio_set_value(EXYNOS4_GPX0(6), 0);
- mdelay(10);
-
- gpio_set_value(EXYNOS4_GPX0(6), 1);
- mdelay(10);
-
- gpio_free(EXYNOS4_GPX0(6));
- } else {
-#if !defined(CONFIG_BACKLIGHT_PWM)
- gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
- gpio_free(EXYNOS4_GPD0(1));
-#endif
- }
-}
-
-static struct plat_lcd_data smdkc210_lcd_lte480wv_data = {
- .set_power = lcd_lte480wv_set_power,
-};
-
-static struct platform_device smdkc210_lcd_lte480wv = {
- .name = "platform-lcd",
- .dev.parent = &s5p_device_fimd0.dev,
- .dev.platform_data = &smdkc210_lcd_lte480wv_data,
-};
-
-static struct s3c_fb_pd_win smdkc210_fb_win0 = {
- .win_mode = {
- .left_margin = 13,
- .right_margin = 8,
- .upper_margin = 7,
- .lower_margin = 5,
- .hsync_len = 3,
- .vsync_len = 1,
- .xres = 800,
- .yres = 480,
- },
- .max_bpp = 32,
- .default_bpp = 24,
-};
-
-static struct s3c_fb_platdata smdkc210_lcd0_pdata __initdata = {
- .win[0] = &smdkc210_fb_win0,
- .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
- .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
- .setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
-};
-
-static struct resource smdkc210_smsc911x_resources[] = {
- [0] = {
- .start = EXYNOS4_PA_SROM_BANK(1),
- .end = EXYNOS4_PA_SROM_BANK(1) + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_EINT(5),
- .end = IRQ_EINT(5),
- .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
- },
-};
-
-static struct smsc911x_platform_config smsc9215_config = {
- .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
- .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
- .flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
- .phy_interface = PHY_INTERFACE_MODE_MII,
- .mac = {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
-};
-
-static struct platform_device smdkc210_smsc911x = {
- .name = "smsc911x",
- .id = -1,
- .num_resources = ARRAY_SIZE(smdkc210_smsc911x_resources),
- .resource = smdkc210_smsc911x_resources,
- .dev = {
- .platform_data = &smsc9215_config,
- },
-};
-
-static struct i2c_board_info i2c_devs1[] __initdata = {
- {I2C_BOARD_INFO("wm8994", 0x1a),},
-};
-
-static struct platform_device *smdkc210_devices[] __initdata = {
- &s3c_device_hsmmc0,
- &s3c_device_hsmmc1,
- &s3c_device_hsmmc2,
- &s3c_device_hsmmc3,
- &s3c_device_i2c1,
- &s3c_device_rtc,
- &s3c_device_wdt,
- &exynos4_device_ac97,
- &exynos4_device_i2s0,
- &exynos4_device_pd[PD_MFC],
- &exynos4_device_pd[PD_G3D],
- &exynos4_device_pd[PD_LCD0],
- &exynos4_device_pd[PD_LCD1],
- &exynos4_device_pd[PD_CAM],
- &exynos4_device_pd[PD_TV],
- &exynos4_device_pd[PD_GPS],
- &exynos4_device_sysmmu,
- &samsung_asoc_dma,
- &s5p_device_fimd0,
- &smdkc210_lcd_lte480wv,
- &smdkc210_smsc911x,
-};
-
-static void __init smdkc210_smsc911x_init(void)
-{
- u32 cs1;
-
- /* configure nCS1 width to 16 bits */
- cs1 = __raw_readl(S5P_SROM_BW) &
- ~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
- cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
- (1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
- (1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
- S5P_SROM_BW__NCS1__SHIFT;
- __raw_writel(cs1, S5P_SROM_BW);
-
- /* set timing for nCS1 suitable for ethernet chip */
- __raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
- (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
- (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
- (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
- (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
- (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
- (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
-}
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdkc210_bl_gpio_info = {
- .no = EXYNOS4_GPD0(1),
- .func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdkc210_bl_data = {
- .pwm_id = 1,
- .pwm_period_ns = 1000,
-};
-
-static void __init smdkc210_map_io(void)
-{
- s5p_init_io(NULL, 0, S5P_VA_CHIPID);
- s3c24xx_init_clocks(24000000);
- s3c24xx_init_uarts(smdkc210_uartcfgs, ARRAY_SIZE(smdkc210_uartcfgs));
-}
-
-static void __init smdkc210_machine_init(void)
-{
- s3c_i2c1_set_platdata(NULL);
- i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
- smdkc210_smsc911x_init();
-
- s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata);
- s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata);
- s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata);
- s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
-
- samsung_bl_set(&smdkc210_bl_gpio_info, &smdkc210_bl_data);
- s5p_fimd0_set_platdata(&smdkc210_lcd0_pdata);
-
- platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
-}
-
-MACHINE_START(SMDKC210, "SMDKC210")
- /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
- .init_irq = exynos4_init_irq,
- .map_io = smdkc210_map_io,
- .init_machine = smdkc210_machine_init,
- .timer = &exynos4_timer,
-MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c
index ea4149556860..2c1a076c6a73 100644
--- a/arch/arm/mach-exynos4/mach-smdkv310.c
+++ b/arch/arm/mach-exynos4/mach-smdkv310.c
@@ -9,7 +9,9 @@
*/
#include <linux/serial_core.h>
+#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/lcd.h>
#include <linux/mmc/host.h>
#include <linux/platform_device.h>
#include <linux/smsc911x.h>
@@ -21,11 +23,14 @@
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
+#include <video/platform_lcd.h>
#include <plat/regs-serial.h>
#include <plat/regs-srom.h>
+#include <plat/regs-fb-v4.h>
#include <plat/exynos4.h>
#include <plat/cpu.h>
#include <plat/devs.h>
+#include <plat/fb.h>
#include <plat/keypad.h>
#include <plat/sdhci.h>
#include <plat/iic.h>
@@ -112,6 +117,67 @@ static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
.clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
+static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
+ unsigned int power)
+{
+ if (power) {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+ gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
+ gpio_free(EXYNOS4_GPD0(1));
+#endif
+ /* fire nRESET on power up */
+ gpio_request(EXYNOS4_GPX0(6), "GPX0");
+
+ gpio_direction_output(EXYNOS4_GPX0(6), 1);
+ mdelay(100);
+
+ gpio_set_value(EXYNOS4_GPX0(6), 0);
+ mdelay(10);
+
+ gpio_set_value(EXYNOS4_GPX0(6), 1);
+ mdelay(10);
+
+ gpio_free(EXYNOS4_GPX0(6));
+ } else {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+ gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
+ gpio_free(EXYNOS4_GPD0(1));
+#endif
+ }
+}
+
+static struct plat_lcd_data smdkv310_lcd_lte480wv_data = {
+ .set_power = lcd_lte480wv_set_power,
+};
+
+static struct platform_device smdkv310_lcd_lte480wv = {
+ .name = "platform-lcd",
+ .dev.parent = &s5p_device_fimd0.dev,
+ .dev.platform_data = &smdkv310_lcd_lte480wv_data,
+};
+
+static struct s3c_fb_pd_win smdkv310_fb_win0 = {
+ .win_mode = {
+ .left_margin = 13,
+ .right_margin = 8,
+ .upper_margin = 7,
+ .lower_margin = 5,
+ .hsync_len = 3,
+ .vsync_len = 1,
+ .xres = 800,
+ .yres = 480,
+ },
+ .max_bpp = 32,
+ .default_bpp = 24,
+};
+
+static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = {
+ .win[0] = &smdkv310_fb_win0,
+ .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+ .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+ .setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
+};
+
static struct resource smdkv310_smsc911x_resources[] = {
[0] = {
.start = EXYNOS4_PA_SROM_BANK(1),
@@ -188,6 +254,8 @@ static struct platform_device *smdkv310_devices[] __initdata = {
&exynos4_device_sysmmu,
&samsung_asoc_dma,
&samsung_asoc_idma,
+ &s5p_device_fimd0,
+ &smdkv310_lcd_lte480wv,
&smdkv310_smsc911x,
&exynos4_device_ahci,
};
@@ -248,6 +316,7 @@ static void __init smdkv310_machine_init(void)
samsung_keypad_set_platdata(&smdkv310_keypad_data);
samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
+ s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata);
platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
}
@@ -255,7 +324,16 @@ static void __init smdkv310_machine_init(void)
MACHINE_START(SMDKV310, "SMDKV310")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
+ .init_irq = exynos4_init_irq,
+ .map_io = smdkv310_map_io,
+ .init_machine = smdkv310_machine_init,
+ .timer = &exynos4_timer,
+MACHINE_END
+
+MACHINE_START(SMDKC210, "SMDKC210")
+ /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+ .atag_offset = 0x100,
.init_irq = exynos4_init_irq,
.map_io = smdkv310_map_io,
.init_machine = smdkv310_machine_init,
diff --git a/arch/arm/mach-exynos4/mach-universal_c210.c b/arch/arm/mach-exynos4/mach-universal_c210.c
index b3b5d8911004..2aac6f755c8e 100644
--- a/arch/arm/mach-exynos4/mach-universal_c210.c
+++ b/arch/arm/mach-exynos4/mach-universal_c210.c
@@ -762,7 +762,7 @@ static void __init universal_machine_init(void)
MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = exynos4_init_irq,
.map_io = universal_map_io,
.init_machine = universal_machine_init,
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
index ddd86864fb83..f191608b28d6 100644
--- a/arch/arm/mach-exynos4/mct.c
+++ b/arch/arm/mach-exynos4/mct.c
@@ -20,19 +20,31 @@
#include <linux/delay.h>
#include <linux/percpu.h>
+#include <asm/hardware/gic.h>
+
+#include <plat/cpu.h>
+
#include <mach/map.h>
+#include <mach/irqs.h>
#include <mach/regs-mct.h>
#include <asm/mach/time.h>
+enum {
+ MCT_INT_SPI,
+ MCT_INT_PPI
+};
+
static unsigned long clk_cnt_per_tick;
static unsigned long clk_rate;
+static unsigned int mct_int_type;
struct mct_clock_event_device {
struct clock_event_device *evt;
void __iomem *base;
+ char name[10];
};
-struct mct_clock_event_device mct_tick[2];
+struct mct_clock_event_device mct_tick[NR_CPUS];
static void exynos4_mct_write(unsigned int value, void *addr)
{
@@ -42,57 +54,53 @@ static void exynos4_mct_write(unsigned int value, void *addr)
__raw_writel(value, addr);
- switch ((u32) addr) {
- case (u32) EXYNOS4_MCT_G_TCON:
- stat_addr = EXYNOS4_MCT_G_WSTAT;
- mask = 1 << 16; /* G_TCON write status */
- break;
- case (u32) EXYNOS4_MCT_G_COMP0_L:
- stat_addr = EXYNOS4_MCT_G_WSTAT;
- mask = 1 << 0; /* G_COMP0_L write status */
- break;
- case (u32) EXYNOS4_MCT_G_COMP0_U:
- stat_addr = EXYNOS4_MCT_G_WSTAT;
- mask = 1 << 1; /* G_COMP0_U write status */
- break;
- case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
- stat_addr = EXYNOS4_MCT_G_WSTAT;
- mask = 1 << 2; /* G_COMP0_ADD_INCR write status */
- break;
- case (u32) EXYNOS4_MCT_G_CNT_L:
- stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
- mask = 1 << 0; /* G_CNT_L write status */
- break;
- case (u32) EXYNOS4_MCT_G_CNT_U:
- stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
- mask = 1 << 1; /* G_CNT_U write status */
- break;
- case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET):
- stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 3; /* L0_TCON write status */
- break;
- case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET):
- stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 3; /* L1_TCON write status */
- break;
- case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET):
- stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 0; /* L0_TCNTB write status */
- break;
- case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET):
- stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 0; /* L1_TCNTB write status */
- break;
- case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET):
- stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 1; /* L0_ICNTB write status */
- break;
- case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET):
- stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 1; /* L1_ICNTB write status */
- break;
- default:
- return;
+ if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
+ u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
+ switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
+ case (u32) MCT_L_TCON_OFFSET:
+ stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 3; /* L_TCON write status */
+ break;
+ case (u32) MCT_L_ICNTB_OFFSET:
+ stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 1; /* L_ICNTB write status */
+ break;
+ case (u32) MCT_L_TCNTB_OFFSET:
+ stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 0; /* L_TCNTB write status */
+ break;
+ default:
+ return;
+ }
+ } else {
+ switch ((u32) addr) {
+ case (u32) EXYNOS4_MCT_G_TCON:
+ stat_addr = EXYNOS4_MCT_G_WSTAT;
+ mask = 1 << 16; /* G_TCON write status */
+ break;
+ case (u32) EXYNOS4_MCT_G_COMP0_L:
+ stat_addr = EXYNOS4_MCT_G_WSTAT;
+ mask = 1 << 0; /* G_COMP0_L write status */
+ break;
+ case (u32) EXYNOS4_MCT_G_COMP0_U:
+ stat_addr = EXYNOS4_MCT_G_WSTAT;
+ mask = 1 << 1; /* G_COMP0_U write status */
+ break;
+ case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
+ stat_addr = EXYNOS4_MCT_G_WSTAT;
+ mask = 1 << 2; /* G_COMP0_ADD_INCR w status */
+ break;
+ case (u32) EXYNOS4_MCT_G_CNT_L:
+ stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+ mask = 1 << 0; /* G_CNT_L write status */
+ break;
+ case (u32) EXYNOS4_MCT_G_CNT_U:
+ stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+ mask = 1 << 1; /* G_CNT_U write status */
+ break;
+ default:
+ return;
+ }
}
/* Wait maximum 1 ms until written values are applied */
@@ -321,9 +329,8 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
}
}
-static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
{
- struct mct_clock_event_device *mevt = dev_id;
struct clock_event_device *evt = mevt->evt;
/*
@@ -335,7 +342,20 @@ static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
exynos4_mct_tick_stop(mevt);
/* Clear the MCT tick interrupt */
- exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+ if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+ exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+{
+ struct mct_clock_event_device *mevt = dev_id;
+ struct clock_event_device *evt = mevt->evt;
+
+ exynos4_mct_tick_clear(mevt);
evt->event_handler(evt);
@@ -360,14 +380,10 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
mct_tick[cpu].evt = evt;
- if (cpu == 0) {
- mct_tick[cpu].base = EXYNOS4_MCT_L0_BASE;
- evt->name = "mct_tick0";
- } else {
- mct_tick[cpu].base = EXYNOS4_MCT_L1_BASE;
- evt->name = "mct_tick1";
- }
+ mct_tick[cpu].base = EXYNOS4_MCT_L_BASE(cpu);
+ sprintf(mct_tick[cpu].name, "mct_tick%d", cpu);
+ evt->name = mct_tick[cpu].name;
evt->cpumask = cpumask_of(cpu);
evt->set_next_event = exynos4_tick_set_next_event;
evt->set_mode = exynos4_tick_set_mode;
@@ -384,13 +400,19 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET);
- if (cpu == 0) {
- mct_tick0_event_irq.dev_id = &mct_tick[cpu];
- setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+ if (mct_int_type == MCT_INT_SPI) {
+ if (cpu == 0) {
+ mct_tick0_event_irq.dev_id = &mct_tick[cpu];
+ evt->irq = IRQ_MCT_L0;
+ setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+ } else {
+ mct_tick1_event_irq.dev_id = &mct_tick[cpu];
+ evt->irq = IRQ_MCT_L1;
+ setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+ irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
+ }
} else {
- mct_tick1_event_irq.dev_id = &mct_tick[cpu];
- setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
- irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
+ gic_enable_ppi(IRQ_MCT_LOCALTIMER);
}
}
@@ -402,9 +424,10 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
return 0;
}
-int local_timer_ack(void)
+void local_timer_stop(struct clock_event_device *evt)
{
- return 0;
+ evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+ disable_irq(evt->irq);
}
#endif /* CONFIG_LOCAL_TIMERS */
@@ -419,6 +442,11 @@ static void __init exynos4_timer_resources(void)
static void __init exynos4_timer_init(void)
{
+ if (soc_is_exynos4210())
+ mct_int_type = MCT_INT_SPI;
+ else
+ mct_int_type = MCT_INT_PPI;
+
exynos4_timer_resources();
exynos4_clocksource_init();
exynos4_clockevent_init();
diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c
index df6ef1b2f98b..05595407e9ff 100644
--- a/arch/arm/mach-exynos4/platsmp.c
+++ b/arch/arm/mach-exynos4/platsmp.c
@@ -30,9 +30,13 @@
#include <mach/regs-clock.h>
#include <mach/regs-pmu.h>
+#include <plat/cpu.h>
+
+extern unsigned int gic_bank_offset;
extern void exynos4_secondary_startup(void);
-#define CPU1_BOOT_REG S5P_VA_SYSRAM
+#define CPU1_BOOT_REG (samsung_rev() == EXYNOS4210_REV_1_1 ? \
+ S5P_INFORM5 : S5P_VA_SYSRAM)
/*
* control for which core is the next to come out of the secondary
@@ -64,9 +68,9 @@ static DEFINE_SPINLOCK(boot_lock);
static void __cpuinit exynos4_gic_secondary_init(void)
{
void __iomem *dist_base = S5P_VA_GIC_DIST +
- (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+ (gic_bank_offset * smp_processor_id());
void __iomem *cpu_base = S5P_VA_GIC_CPU +
- (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+ (gic_bank_offset * smp_processor_id());
int i;
/*
@@ -128,7 +132,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
* Note that "pen_release" is the hardware CPU ID, whereas
* "cpu" is Linux's internal ID.
*/
- write_pen_release(cpu);
+ write_pen_release(cpu_logical_map(cpu));
if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
__raw_writel(S5P_CORE_LOCAL_PWR_EN,
@@ -193,12 +197,10 @@ void __init smp_init_cpus(void)
ncores = scu_base ? scu_get_core_count(scu_base) : 1;
/* sanity check */
- if (ncores > NR_CPUS) {
- printk(KERN_WARNING
- "EXYNOS4: no. of cores (%d) greater than configured "
- "maximum of %d - clipping\n",
- ncores, NR_CPUS);
- ncores = NR_CPUS;
+ if (ncores > nr_cpu_ids) {
+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+ ncores, nr_cpu_ids);
+ ncores = nr_cpu_ids;
}
for (i = 0; i < ncores; i++)
@@ -218,5 +220,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
* until it receives a soft interrupt, and then the
* secondary CPU branches to this address.
*/
- __raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)), S5P_VA_SYSRAM);
+ __raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
+ CPU1_BOOT_REG);
}
diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c
index bc6ca9482de1..62e4f4363006 100644
--- a/arch/arm/mach-exynos4/pm.c
+++ b/arch/arm/mach-exynos4/pm.c
@@ -41,7 +41,6 @@ static struct sleep_save exynos4_set_clksrc[] = {
{ .reg = S5P_CLKSRC_MASK_CAM , .val = 0x11111111, },
{ .reg = S5P_CLKSRC_MASK_TV , .val = 0x00000111, },
{ .reg = S5P_CLKSRC_MASK_LCD0 , .val = 0x00001111, },
- { .reg = S5P_CLKSRC_MASK_LCD1 , .val = 0x00001111, },
{ .reg = S5P_CLKSRC_MASK_MAUDIO , .val = 0x00000001, },
{ .reg = S5P_CLKSRC_MASK_FSYS , .val = 0x01011111, },
{ .reg = S5P_CLKSRC_MASK_PERIL0 , .val = 0x01111111, },
@@ -49,6 +48,10 @@ static struct sleep_save exynos4_set_clksrc[] = {
{ .reg = S5P_CLKSRC_MASK_DMC , .val = 0x00010000, },
};
+static struct sleep_save exynos4210_set_clksrc[] = {
+ { .reg = S5P_CLKSRC_MASK_LCD1 , .val = 0x00001111, },
+};
+
static struct sleep_save exynos4_epll_save[] = {
SAVE_ITEM(S5P_EPLL_CON0),
SAVE_ITEM(S5P_EPLL_CON1),
@@ -60,77 +63,6 @@ static struct sleep_save exynos4_vpll_save[] = {
};
static struct sleep_save exynos4_core_save[] = {
- /* CMU side */
- SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
- SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
- SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
- SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
- SAVE_ITEM(S5P_CLKSRC_TOP0),
- SAVE_ITEM(S5P_CLKSRC_TOP1),
- SAVE_ITEM(S5P_CLKSRC_CAM),
- SAVE_ITEM(S5P_CLKSRC_TV),
- SAVE_ITEM(S5P_CLKSRC_MFC),
- SAVE_ITEM(S5P_CLKSRC_G3D),
- SAVE_ITEM(S5P_CLKSRC_IMAGE),
- SAVE_ITEM(S5P_CLKSRC_LCD0),
- SAVE_ITEM(S5P_CLKSRC_LCD1),
- SAVE_ITEM(S5P_CLKSRC_MAUDIO),
- SAVE_ITEM(S5P_CLKSRC_FSYS),
- SAVE_ITEM(S5P_CLKSRC_PERIL0),
- SAVE_ITEM(S5P_CLKSRC_PERIL1),
- SAVE_ITEM(S5P_CLKDIV_CAM),
- SAVE_ITEM(S5P_CLKDIV_TV),
- SAVE_ITEM(S5P_CLKDIV_MFC),
- SAVE_ITEM(S5P_CLKDIV_G3D),
- SAVE_ITEM(S5P_CLKDIV_IMAGE),
- SAVE_ITEM(S5P_CLKDIV_LCD0),
- SAVE_ITEM(S5P_CLKDIV_LCD1),
- SAVE_ITEM(S5P_CLKDIV_MAUDIO),
- SAVE_ITEM(S5P_CLKDIV_FSYS0),
- SAVE_ITEM(S5P_CLKDIV_FSYS1),
- SAVE_ITEM(S5P_CLKDIV_FSYS2),
- SAVE_ITEM(S5P_CLKDIV_FSYS3),
- SAVE_ITEM(S5P_CLKDIV_PERIL0),
- SAVE_ITEM(S5P_CLKDIV_PERIL1),
- SAVE_ITEM(S5P_CLKDIV_PERIL2),
- SAVE_ITEM(S5P_CLKDIV_PERIL3),
- SAVE_ITEM(S5P_CLKDIV_PERIL4),
- SAVE_ITEM(S5P_CLKDIV_PERIL5),
- SAVE_ITEM(S5P_CLKDIV_TOP),
- SAVE_ITEM(S5P_CLKSRC_MASK_TOP),
- SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
- SAVE_ITEM(S5P_CLKSRC_MASK_TV),
- SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
- SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
- SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
- SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
- SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
- SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
- SAVE_ITEM(S5P_CLKDIV2_RATIO),
- SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
- SAVE_ITEM(S5P_CLKGATE_IP_CAM),
- SAVE_ITEM(S5P_CLKGATE_IP_TV),
- SAVE_ITEM(S5P_CLKGATE_IP_MFC),
- SAVE_ITEM(S5P_CLKGATE_IP_G3D),
- SAVE_ITEM(S5P_CLKGATE_IP_IMAGE),
- SAVE_ITEM(S5P_CLKGATE_IP_LCD0),
- SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
- SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
- SAVE_ITEM(S5P_CLKGATE_IP_GPS),
- SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
- SAVE_ITEM(S5P_CLKGATE_IP_PERIR),
- SAVE_ITEM(S5P_CLKGATE_BLOCK),
- SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
- SAVE_ITEM(S5P_CLKSRC_DMC),
- SAVE_ITEM(S5P_CLKDIV_DMC0),
- SAVE_ITEM(S5P_CLKDIV_DMC1),
- SAVE_ITEM(S5P_CLKGATE_IP_DMC),
- SAVE_ITEM(S5P_CLKSRC_CPU),
- SAVE_ITEM(S5P_CLKDIV_CPU),
- SAVE_ITEM(S5P_CLKDIV_CPU + 0x4),
- SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
- SAVE_ITEM(S5P_CLKGATE_IP_CPU),
-
/* GIC side */
SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
@@ -268,6 +200,9 @@ static void exynos4_pm_prepare(void)
s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
+ if (soc_is_exynos4210())
+ s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_set_clksrc));
+
}
static int exynos4_pm_add(struct sys_device *sysdev)
diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig
index c8e7afcf14ec..f643ef819da6 100644
--- a/arch/arm/mach-footbridge/Kconfig
+++ b/arch/arm/mach-footbridge/Kconfig
@@ -4,8 +4,8 @@ menu "Footbridge Implementations"
config ARCH_CATS
bool "CATS"
- select CLKSRC_I8253
select CLKEVT_I8253
+ select CLKSRC_I8253
select FOOTBRIDGE_HOST
select ISA
select ISA_DMA
@@ -61,8 +61,8 @@ config ARCH_EBSA285_HOST
config ARCH_NETWINDER
bool "NetWinder"
- select CLKSRC_I8253
select CLKEVT_I8253
+ select CLKSRC_I8253
select FOOTBRIDGE_HOST
select ISA
select ISA_DMA
diff --git a/arch/arm/mach-footbridge/Makefile.boot b/arch/arm/mach-footbridge/Makefile.boot
index c7e75acfe6c9..ff0a4b5b0a82 100644
--- a/arch/arm/mach-footbridge/Makefile.boot
+++ b/arch/arm/mach-footbridge/Makefile.boot
@@ -1,4 +1,4 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index 5b1a8db779be..d5f178540928 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -76,8 +76,7 @@ __initcall(cats_hw_init);
* hard reboots fail on early boards.
*/
static void __init
-fixup_cats(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+fixup_cats(struct tag *tags, char **cmdline, struct meminfo *mi)
{
screen_info.orig_video_lines = 25;
screen_info.orig_video_points = 16;
@@ -86,7 +85,7 @@ fixup_cats(struct machine_desc *desc, struct tag *tags,
MACHINE_START(CATS, "Chalice-CATS")
/* Maintainer: Philip Blundell */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.soft_reboot = 1,
.fixup = fixup_cats,
.map_io = footbridge_map_io,
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
index 2ef69ff44ba8..012210cf7d16 100644
--- a/arch/arm/mach-footbridge/ebsa285.c
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -15,7 +15,7 @@
MACHINE_START(EBSA285, "EBSA285")
/* Maintainer: Russell King */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.video_start = 0x000a0000,
.video_end = 0x000bffff,
.map_io = footbridge_map_io,
diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S
index 1be2eeb7a0a0..e5acde25ffc5 100644
--- a/arch/arm/mach-footbridge/include/mach/debug-macro.S
+++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S
@@ -15,7 +15,7 @@
#ifndef CONFIG_DEBUG_DC21285_PORT
/* For NetWinder debugging */
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x000003f8
orr \rv, \rp, #0xff000000 @ virtual
orr \rp, \rp, #0x7c000000 @ physical
@@ -31,7 +31,7 @@
.equ dc21285_high, ARMCSR_BASE & 0xff000000
.equ dc21285_low, ARMCSR_BASE & 0x00ffffff
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
.if dc21285_low
mov \rp, #dc21285_low
.else
diff --git a/arch/arm/mach-footbridge/include/mach/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h
index 15d54981674c..e3d6ccac2162 100644
--- a/arch/arm/mach-footbridge/include/mach/hardware.h
+++ b/arch/arm/mach-footbridge/include/mach/hardware.h
@@ -93,7 +93,7 @@
#define CPLD_FLASH_WR_ENABLE 1
#ifndef __ASSEMBLY__
-extern spinlock_t nw_gpio_lock;
+extern raw_spinlock_t nw_gpio_lock;
extern void nw_gpio_modify_op(unsigned int mask, unsigned int set);
extern void nw_gpio_modify_io(unsigned int mask, unsigned int in);
extern unsigned int nw_gpio_read(void);
diff --git a/arch/arm/mach-footbridge/include/mach/io.h b/arch/arm/mach-footbridge/include/mach/io.h
index 32e4cc397c28..15a70396c27d 100644
--- a/arch/arm/mach-footbridge/include/mach/io.h
+++ b/arch/arm/mach-footbridge/include/mach/io.h
@@ -23,8 +23,6 @@
#define PCIO_SIZE 0x00100000
#define PCIO_BASE MMU_IO(0xff000000, 0x7c000000)
-#define IO_SPACE_LIMIT 0xffff
-
/*
* Translation of various region addresses to virtual addresses
*/
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index 06e514f372d0..0d3846f3b60d 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -68,7 +68,7 @@ static inline void wb977_ww(int reg, int val)
/*
* This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
*/
-DEFINE_SPINLOCK(nw_gpio_lock);
+DEFINE_RAW_SPINLOCK(nw_gpio_lock);
EXPORT_SYMBOL(nw_gpio_lock);
static unsigned int current_gpio_op;
@@ -327,9 +327,9 @@ static inline void wb977_init_gpio(void)
/*
* Set Group1/Group2 outputs
*/
- spin_lock_irqsave(&nw_gpio_lock, flags);
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
nw_gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
- spin_unlock_irqrestore(&nw_gpio_lock, flags);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
/*
@@ -390,9 +390,9 @@ static void __init cpld_init(void)
{
unsigned long flags;
- spin_lock_irqsave(&nw_gpio_lock, flags);
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
nw_cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
- spin_unlock_irqrestore(&nw_gpio_lock, flags);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
static unsigned char rwa_unlock[] __initdata =
@@ -616,9 +616,9 @@ static int __init nw_hw_init(void)
cpld_init();
rwa010_init();
- spin_lock_irqsave(&nw_gpio_lock, flags);
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
nw_gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
- spin_unlock_irqrestore(&nw_gpio_lock, flags);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
return 0;
}
@@ -631,8 +631,7 @@ __initcall(nw_hw_init);
* the parameter page.
*/
static void __init
-fixup_netwinder(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+fixup_netwinder(struct tag *tags, char **cmdline, struct meminfo *mi)
{
#ifdef CONFIG_ISAPNP
extern int isapnp_disable;
@@ -648,7 +647,7 @@ fixup_netwinder(struct machine_desc *desc, struct tag *tags,
MACHINE_START(NETWINDER, "Rebel-NetWinder")
/* Maintainer: Russell King/Rebel.com */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.video_start = 0x000a0000,
.video_end = 0x000bffff,
.reserve_lp0 = 1,
diff --git a/arch/arm/mach-footbridge/netwinder-leds.c b/arch/arm/mach-footbridge/netwinder-leds.c
index 00269fe0be8a..e57102e871fc 100644
--- a/arch/arm/mach-footbridge/netwinder-leds.c
+++ b/arch/arm/mach-footbridge/netwinder-leds.c
@@ -31,13 +31,13 @@
static char led_state;
static char hw_led_state;
-static DEFINE_SPINLOCK(leds_lock);
+static DEFINE_RAW_SPINLOCK(leds_lock);
static void netwinder_leds_event(led_event_t evt)
{
unsigned long flags;
- spin_lock_irqsave(&leds_lock, flags);
+ raw_spin_lock_irqsave(&leds_lock, flags);
switch (evt) {
case led_start:
@@ -117,12 +117,12 @@ static void netwinder_leds_event(led_event_t evt)
break;
}
- spin_unlock_irqrestore(&leds_lock, flags);
+ raw_spin_unlock_irqrestore(&leds_lock, flags);
if (led_state & LED_STATE_ENABLED) {
- spin_lock_irqsave(&nw_gpio_lock, flags);
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
nw_gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
- spin_unlock_irqrestore(&nw_gpio_lock, flags);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
}
diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c
index 3285e91ca8c1..f41dba39b327 100644
--- a/arch/arm/mach-footbridge/personal.c
+++ b/arch/arm/mach-footbridge/personal.c
@@ -15,7 +15,7 @@
MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
/* Maintainer: Jamey Hicks / George France */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = footbridge_map_io,
.init_irq = footbridge_init_irq,
.timer = &footbridge_timer,
diff --git a/arch/arm/mach-gemini/Makefile.boot b/arch/arm/mach-gemini/Makefile.boot
index 22a52c228d93..683f52b20e3d 100644
--- a/arch/arm/mach-gemini/Makefile.boot
+++ b/arch/arm/mach-gemini/Makefile.boot
@@ -1,9 +1,9 @@
ifeq ($(CONFIG_GEMINI_MEM_SWAP),y)
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
else
- zreladdr-y := 0x10008000
+ zreladdr-y += 0x10008000
params_phys-y := 0x10000100
initrd_phys-y := 0x10800000
endif
diff --git a/arch/arm/mach-gemini/board-nas4220b.c b/arch/arm/mach-gemini/board-nas4220b.c
index 0cf7a07c3f3f..5927d3c253aa 100644
--- a/arch/arm/mach-gemini/board-nas4220b.c
+++ b/arch/arm/mach-gemini/board-nas4220b.c
@@ -102,7 +102,7 @@ static void __init ib4220b_init(void)
}
MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
- .boot_params = 0x100,
+ .atag_offset = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
.timer = &ib4220b_timer,
diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c
index 4fa09af99495..cd7437a1cea0 100644
--- a/arch/arm/mach-gemini/board-rut1xx.c
+++ b/arch/arm/mach-gemini/board-rut1xx.c
@@ -86,7 +86,7 @@ static void __init rut1xx_init(void)
}
MACHINE_START(RUT100, "Teltonika RUT100")
- .boot_params = 0x100,
+ .atag_offset = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
.timer = &rut1xx_timer,
diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c
index 88cc422ee444..a367880368f1 100644
--- a/arch/arm/mach-gemini/board-wbd111.c
+++ b/arch/arm/mach-gemini/board-wbd111.c
@@ -129,7 +129,7 @@ static void __init wbd111_init(void)
}
MACHINE_START(WBD111, "Wiliboard WBD-111")
- .boot_params = 0x100,
+ .atag_offset = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
.timer = &wbd111_timer,
diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c
index 3a220347bc88..f382811c1319 100644
--- a/arch/arm/mach-gemini/board-wbd222.c
+++ b/arch/arm/mach-gemini/board-wbd222.c
@@ -129,7 +129,7 @@ static void __init wbd222_init(void)
}
MACHINE_START(WBD222, "Wiliboard WBD-222")
- .boot_params = 0x100,
+ .atag_offset = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
.timer = &wbd222_timer,
diff --git a/arch/arm/mach-gemini/include/mach/debug-macro.S b/arch/arm/mach-gemini/include/mach/debug-macro.S
index f40e006d296e..837670763b85 100644
--- a/arch/arm/mach-gemini/include/mach/debug-macro.S
+++ b/arch/arm/mach-gemini/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
*/
#include <mach/hardware.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =GEMINI_UART_BASE @ physical
ldr \rv, =IO_ADDRESS(GEMINI_UART_BASE) @ virtual
.endm
diff --git a/arch/arm/mach-gemini/include/mach/gpio.h b/arch/arm/mach-gemini/include/mach/gpio.h
index 3bc2c70f2989..40a0527bada7 100644
--- a/arch/arm/mach-gemini/include/mach/gpio.h
+++ b/arch/arm/mach-gemini/include/mach/gpio.h
@@ -13,11 +13,6 @@
#define __MACH_GPIO_H__
#include <mach/irqs.h>
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq(x) ((x) + GPIO_IRQ_BASE)
#define irq_to_gpio(x) ((x) - GPIO_IRQ_BASE)
diff --git a/arch/arm/mach-gemini/include/mach/memory.h b/arch/arm/mach-gemini/include/mach/memory.h
deleted file mode 100644
index a50915f764d8..000000000000
--- a/arch/arm/mach-gemini/include/mach/memory.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2001-2006 Storlink, Corp.
- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * 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 __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-#ifdef CONFIG_GEMINI_MEM_SWAP
-# define PLAT_PHYS_OFFSET UL(0x00000000)
-#else
-# define PLAT_PHYS_OFFSET UL(0x10000000)
-#endif
-
-#endif /* __MACH_MEMORY_H */
diff --git a/arch/arm/mach-h720x/Makefile.boot b/arch/arm/mach-h720x/Makefile.boot
index 52984017bd91..d875a7094dfe 100644
--- a/arch/arm/mach-h720x/Makefile.boot
+++ b/arch/arm/mach-h720x/Makefile.boot
@@ -1,2 +1,2 @@
- zreladdr-$(CONFIG_ARCH_H720X) := 0x40008000
+ zreladdr-$(CONFIG_ARCH_H720X) += 0x40008000
diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
index 65f1bea958e5..9886f19805f4 100644
--- a/arch/arm/mach-h720x/h7201-eval.c
+++ b/arch/arm/mach-h720x/h7201-eval.c
@@ -29,7 +29,7 @@
MACHINE_START(H7201, "Hynix GMS30C7201")
/* Maintainer: Robert Schwebel, Pengutronix */
- .boot_params = 0xc0001000,
+ .atag_offset = 0x1000,
.map_io = h720x_map_io,
.init_irq = h720x_init_irq,
.timer = &h7201_timer,
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
index 884584a09752..284a134819e1 100644
--- a/arch/arm/mach-h720x/h7202-eval.c
+++ b/arch/arm/mach-h720x/h7202-eval.c
@@ -71,7 +71,7 @@ static void __init init_eval_h7202(void)
MACHINE_START(H7202, "Hynix HMS30C7202")
/* Maintainer: Robert Schwebel, Pengutronix */
- .boot_params = 0x40000100,
+ .atag_offset = 0x100,
.map_io = h720x_map_io,
.init_irq = h7202_init_irq,
.timer = &h7202_timer,
diff --git a/arch/arm/mach-h720x/include/mach/debug-macro.S b/arch/arm/mach-h720x/include/mach/debug-macro.S
index c2093e835720..8a46157b0582 100644
--- a/arch/arm/mach-h720x/include/mach/debug-macro.S
+++ b/arch/arm/mach-h720x/include/mach/debug-macro.S
@@ -16,7 +16,7 @@
.equ io_virt, IO_VIRT
.equ io_phys, IO_PHYS
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00020000 @ UART1
add \rv, \rp, #io_virt @ virtual address
add \rp, \rp, #io_phys @ physical base address
diff --git a/arch/arm/mach-h720x/include/mach/memory.h b/arch/arm/mach-h720x/include/mach/memory.h
deleted file mode 100644
index 96dcf50c51d3..000000000000
--- a/arch/arm/mach-h720x/include/mach/memory.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/memory.h
- *
- * Copyright (c) 2000 Jungjun Kim
- *
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x40000000)
-#endif
diff --git a/arch/arm/mach-highbank/Makefile b/arch/arm/mach-highbank/Makefile
new file mode 100644
index 000000000000..986958a5a720
--- /dev/null
+++ b/arch/arm/mach-highbank/Makefile
@@ -0,0 +1,6 @@
+obj-y := clock.o highbank.o system.o
+obj-$(CONFIG_DEBUG_HIGHBANK_UART) += lluart.o
+obj-$(CONFIG_SMP) += platsmp.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_PM_SLEEP) += pm.o
diff --git a/arch/arm/mach-highbank/Makefile.boot b/arch/arm/mach-highbank/Makefile.boot
new file mode 100644
index 000000000000..dae9661a7689
--- /dev/null
+++ b/arch/arm/mach-highbank/Makefile.boot
@@ -0,0 +1 @@
+zreladdr-y := 0x00008000
diff --git a/arch/arm/mach-highbank/clock.c b/arch/arm/mach-highbank/clock.c
new file mode 100644
index 000000000000..c25a2ae4fde1
--- /dev/null
+++ b/arch/arm/mach-highbank/clock.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Calxeda, 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+
+struct clk {
+ unsigned long rate;
+};
+
+int clk_enable(struct clk *clk)
+{
+ return 0;
+}
+
+void clk_disable(struct clk *clk)
+{}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ return clk->rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ return 0;
+}
+
+static struct clk eclk = { .rate = 200000000 };
+static struct clk pclk = { .rate = 150000000 };
+
+static struct clk_lookup lookups[] = {
+ { .clk = &pclk, .con_id = "apb_pclk", },
+ { .clk = &pclk, .dev_id = "sp804", },
+ { .clk = &eclk, .dev_id = "ffe0e000.sdhci", },
+ { .clk = &pclk, .dev_id = "fff36000.serial", },
+};
+
+void __init highbank_clocks_init(void)
+{
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+}
diff --git a/arch/arm/mach-highbank/core.h b/arch/arm/mach-highbank/core.h
new file mode 100644
index 000000000000..7e33fc94cd1e
--- /dev/null
+++ b/arch/arm/mach-highbank/core.h
@@ -0,0 +1,9 @@
+extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
+extern void highbank_clocks_init(void);
+extern void __iomem *scu_base_addr;
+#ifdef CONFIG_DEBUG_HIGHBANK_UART
+extern void highbank_lluart_map_io(void);
+#else
+static inline void highbank_lluart_map_io(void) {}
+#endif
+
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
new file mode 100644
index 000000000000..b82dcf08e747
--- /dev/null
+++ b/arch/arm/mach-highbank/highbank.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2010-2011 Calxeda, 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/unified.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/arm_timer.h>
+#include <asm/hardware/timer-sp.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+void __iomem *sregs_base;
+
+#define HB_SCU_VIRT_BASE 0xfee00000
+void __iomem *scu_base_addr = ((void __iomem *)(HB_SCU_VIRT_BASE));
+
+static struct map_desc scu_io_desc __initdata = {
+ .virtual = HB_SCU_VIRT_BASE,
+ .pfn = 0, /* run-time */
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+};
+
+static void __init highbank_scu_map_io(void)
+{
+ unsigned long base;
+
+ /* Get SCU base */
+ asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+ scu_io_desc.pfn = __phys_to_pfn(base);
+ iotable_init(&scu_io_desc, 1);
+}
+
+static void __init highbank_map_io(void)
+{
+ highbank_scu_map_io();
+ highbank_lluart_map_io();
+}
+
+#define HB_JUMP_TABLE_PHYS(cpu) (0x40 + (0x10 * (cpu)))
+#define HB_JUMP_TABLE_VIRT(cpu) phys_to_virt(HB_JUMP_TABLE_PHYS(cpu))
+
+void highbank_set_cpu_jump(int cpu, void *jump_addr)
+{
+ writel(BSYM(virt_to_phys(jump_addr)), HB_JUMP_TABLE_VIRT(cpu));
+ __cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
+ outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
+ HB_JUMP_TABLE_PHYS(cpu) + 15);
+}
+
+const static struct of_device_id irq_match[] = {
+ { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+ {}
+};
+
+static void __init highbank_init_irq(void)
+{
+ of_irq_init(irq_match);
+ l2x0_of_init(0, ~0UL);
+}
+
+static void __init highbank_timer_init(void)
+{
+ int irq;
+ struct device_node *np;
+ void __iomem *timer_base;
+
+ /* Map system registers */
+ np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
+ sregs_base = of_iomap(np, 0);
+ WARN_ON(!sregs_base);
+
+ np = of_find_compatible_node(NULL, NULL, "arm,sp804");
+ timer_base = of_iomap(np, 0);
+ WARN_ON(!timer_base);
+ irq = irq_of_parse_and_map(np, 0);
+
+ highbank_clocks_init();
+
+ sp804_clocksource_init(timer_base + 0x20, "timer1");
+ sp804_clockevents_init(timer_base, irq, "timer0");
+}
+
+static struct sys_timer highbank_timer = {
+ .init = highbank_timer_init,
+};
+
+static void highbank_power_off(void)
+{
+ hignbank_set_pwr_shutdown();
+ scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+
+ while (1)
+ cpu_do_idle();
+}
+
+static void __init highbank_init(void)
+{
+ pm_power_off = highbank_power_off;
+
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *highbank_match[] __initconst = {
+ "calxeda,highbank",
+ NULL,
+};
+
+DT_MACHINE_START(HIGHBANK, "Highbank")
+ .map_io = highbank_map_io,
+ .init_irq = highbank_init_irq,
+ .timer = &highbank_timer,
+ .init_machine = highbank_init,
+ .dt_compat = highbank_match,
+MACHINE_END
diff --git a/arch/arm/mach-highbank/hotplug.c b/arch/arm/mach-highbank/hotplug.c
new file mode 100644
index 000000000000..977cebbea580
--- /dev/null
+++ b/arch/arm/mach-highbank/hotplug.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Calxeda, 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/smp_scu.h>
+#include <asm/cacheflush.h>
+
+#include "core.h"
+
+extern void secondary_startup(void);
+
+int platform_cpu_kill(unsigned int cpu)
+{
+ return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+ flush_cache_all();
+
+ highbank_set_cpu_jump(cpu, secondary_startup);
+ scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+
+ cpu_do_idle();
+
+ /* We should never return from idle */
+ panic("highbank: cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+ /*
+ * CPU0 should not be shut down via hotplug. cpu_idle can WFI
+ * or a proper shutdown or hibernate should be used.
+ */
+ return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-highbank/include/mach/debug-macro.S b/arch/arm/mach-highbank/include/mach/debug-macro.S
new file mode 100644
index 000000000000..cb57fe5bcd04
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/debug-macro.S
@@ -0,0 +1,19 @@
+/*
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+ .macro addruart,rp,rv,tmp
+ movw \rv, #0x6000
+ movt \rv, #0xfee3
+ movw \rp, #0x6000
+ movt \rp, #0xfff3
+ .endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-highbank/include/mach/entry-macro.S b/arch/arm/mach-highbank/include/mach/entry-macro.S
new file mode 100644
index 000000000000..73c11297509e
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/entry-macro.S
@@ -0,0 +1,7 @@
+#include <asm/hardware/entry-macro-gic.S>
+
+ .macro disable_fiq
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
diff --git a/arch/um/include/asm/ftrace.h b/arch/arm/mach-highbank/include/mach/gpio.h
index 40a8c178f10d..40a8c178f10d 100644
--- a/arch/um/include/asm/ftrace.h
+++ b/arch/arm/mach-highbank/include/mach/gpio.h
diff --git a/arch/arm/mach-highbank/include/mach/io.h b/arch/arm/mach-highbank/include/mach/io.h
new file mode 100644
index 000000000000..70cfa3ba7697
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/io.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_IO_H
+#define __MACH_IO_H
+
+#define __io(a) ({ (void)(a); __typesafe_io(0); })
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/irqs.h b/arch/arm/mach-highbank/include/mach/irqs.h
new file mode 100644
index 000000000000..9746aab14e9a
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/irqs.h
@@ -0,0 +1,6 @@
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define NR_IRQS 192
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/memory.h b/arch/arm/mach-highbank/include/mach/memory.h
new file mode 100644
index 000000000000..40a8c178f10d
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/memory.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-highbank/include/mach/system.h b/arch/arm/mach-highbank/include/mach/system.h
new file mode 100644
index 000000000000..7e8192296cae
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/system.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010-2011 Calxeda, 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __MACH_SYSTEM_H
+#define __MACH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+extern void arch_reset(char mode, const char *cmd);
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/timex.h b/arch/arm/mach-highbank/include/mach/timex.h
new file mode 100644
index 000000000000..88dac7a55a97
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/timex.h
@@ -0,0 +1,6 @@
+#ifndef __MACH_TIMEX_H
+#define __MACH_TIMEX_H
+
+#define CLOCK_TICK_RATE 1000000
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/uncompress.h b/arch/arm/mach-highbank/include/mach/uncompress.h
new file mode 100644
index 000000000000..bbe20e696325
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/uncompress.h
@@ -0,0 +1,9 @@
+#ifndef __MACH_UNCOMPRESS_H
+#define __MACH_UNCOMPRESS_H
+
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/vmalloc.h b/arch/arm/mach-highbank/include/mach/vmalloc.h
new file mode 100644
index 000000000000..1969e954277a
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/vmalloc.h
@@ -0,0 +1 @@
+#define VMALLOC_END 0xFEE00000UL
diff --git a/arch/arm/mach-highbank/lluart.c b/arch/arm/mach-highbank/lluart.c
new file mode 100644
index 000000000000..371575019f33
--- /dev/null
+++ b/arch/arm/mach-highbank/lluart.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 Calxeda, 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+
+#define HB_DEBUG_LL_PHYS_BASE 0xfff36000
+#define HB_DEBUG_LL_VIRT_BASE 0xfee36000
+
+static struct map_desc lluart_io_desc __initdata = {
+ .virtual = HB_DEBUG_LL_VIRT_BASE,
+ .pfn = __phys_to_pfn(HB_DEBUG_LL_PHYS_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+};
+
+void __init highbank_lluart_map_io(void)
+{
+ iotable_init(&lluart_io_desc, 1);
+}
diff --git a/arch/arm/mach-highbank/localtimer.c b/arch/arm/mach-highbank/localtimer.c
new file mode 100644
index 000000000000..5a00e7945fdf
--- /dev/null
+++ b/arch/arm/mach-highbank/localtimer.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Based on localtimer.c, Copyright (C) 2002 ARM 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/smp_twd.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+ if (!twd_base) {
+ twd_base = of_iomap(np, 0);
+ WARN_ON(!twd_base);
+ }
+ evt->irq = irq_of_parse_and_map(np, 0);
+ twd_timer_setup(evt);
+ return 0;
+}
diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c
new file mode 100644
index 000000000000..d01364c72b45
--- /dev/null
+++ b/arch/arm/mach-highbank/platsmp.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Based on platsmp.c, Copyright (C) 2002 ARM 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+
+#include "core.h"
+
+extern void secondary_startup(void);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+ gic_secondary_init(0);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ gic_raise_softirq(cpumask_of(cpu), 0);
+ return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+ unsigned int i, ncores;
+
+ ncores = scu_get_core_count(scu_base_addr);
+
+ /* sanity check */
+ if (ncores > NR_CPUS) {
+ printk(KERN_WARNING
+ "highbank: no. of cores (%d) greater than configured "
+ "maximum of %d - clipping\n",
+ ncores, NR_CPUS);
+ ncores = NR_CPUS;
+ }
+
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+
+ set_smp_cross_call(gic_raise_softirq);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+ int i;
+
+ scu_enable(scu_base_addr);
+
+ /*
+ * Write the address of secondary startup into the jump table
+ * The cores are in wfi and wait until they receive a soft interrupt
+ * and a non-zero value to jump to. Then the secondary CPU branches
+ * to this address.
+ */
+ for (i = 1; i < max_cpus; i++)
+ highbank_set_cpu_jump(i, secondary_startup);
+}
diff --git a/arch/arm/mach-highbank/pm.c b/arch/arm/mach-highbank/pm.c
new file mode 100644
index 000000000000..33b3beb89982
--- /dev/null
+++ b/arch/arm/mach-highbank/pm.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 Calxeda, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+
+#include <asm/proc-fns.h>
+#include <asm/smp_scu.h>
+#include <asm/suspend.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+static int highbank_suspend_finish(unsigned long val)
+{
+ cpu_do_idle();
+ return 0;
+}
+
+static int highbank_pm_enter(suspend_state_t state)
+{
+ hignbank_set_pwr_suspend();
+ highbank_set_cpu_jump(0, cpu_resume);
+
+ scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+ cpu_suspend(0, highbank_suspend_finish);
+
+ return 0;
+}
+
+static const struct platform_suspend_ops highbank_pm_ops = {
+ .enter = highbank_pm_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+static int __init highbank_pm_init(void)
+{
+ suspend_set_ops(&highbank_pm_ops);
+ return 0;
+}
+module_init(highbank_pm_init);
diff --git a/arch/arm/mach-highbank/sysregs.h b/arch/arm/mach-highbank/sysregs.h
new file mode 100644
index 000000000000..0e913389f445
--- /dev/null
+++ b/arch/arm/mach-highbank/sysregs.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 Calxeda, 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _MACH_HIGHBANK__SYSREGS_H_
+#define _MACH_HIGHBANK__SYSREGS_H_
+
+#include <linux/io.h>
+
+extern void __iomem *sregs_base;
+
+#define HB_SREG_A9_PWR_REQ 0xf00
+#define HB_SREG_A9_BOOT_STAT 0xf04
+#define HB_SREG_A9_BOOT_DATA 0xf08
+
+#define HB_PWR_SUSPEND 0
+#define HB_PWR_SOFT_RESET 1
+#define HB_PWR_HARD_RESET 2
+#define HB_PWR_SHUTDOWN 3
+
+static inline void hignbank_set_pwr_suspend(void)
+{
+ writel(HB_PWR_SUSPEND, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_shutdown(void)
+{
+ writel(HB_PWR_SHUTDOWN, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_soft_reset(void)
+{
+ writel(HB_PWR_SOFT_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_hard_reset(void)
+{
+ writel(HB_PWR_HARD_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+#endif
diff --git a/arch/arm/mach-highbank/system.c b/arch/arm/mach-highbank/system.c
new file mode 100644
index 000000000000..53f0c4c5ef1c
--- /dev/null
+++ b/arch/arm/mach-highbank/system.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Calxeda, 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/io.h>
+#include <asm/smp_scu.h>
+#include <asm/proc-fns.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+void arch_reset(char mode, const char *cmd)
+{
+ if (mode == 'h')
+ hignbank_set_pwr_hard_reset();
+ else
+ hignbank_set_pwr_soft_reset();
+
+ scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+ cpu_do_idle();
+}
+
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 0519dd7f034b..5f7f9c2a34ae 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -1,10 +1,32 @@
config IMX_HAVE_DMA_V1
bool
+
+config HAVE_IMX_GPC
+ bool
+
+config HAVE_IMX_MMDC
+ bool
+
+config HAVE_IMX_SRC
+ bool
+
#
# ARCH_MX31 and ARCH_MX35 are left for compatibility
# Some usages assume that having one of them implies not having (e.g.) ARCH_MX2.
# To easily distinguish good and reviewed from unreviewed usages new (and IMHO
# more sensible) names are used: SOC_IMX31 and SOC_IMX35
+config ARCH_MX1
+ bool
+
+config MACH_MX21
+ bool
+
+config ARCH_MX25
+ bool
+
+config MACH_MX27
+ bool
+
config ARCH_MX31
bool
@@ -13,6 +35,7 @@ config ARCH_MX35
config SOC_IMX1
bool
+ select ARCH_MX1
select CPU_ARM920T
select IMX_HAVE_DMA_V1
select IMX_HAVE_IOMUX_V1
@@ -20,6 +43,7 @@ config SOC_IMX1
config SOC_IMX21
bool
+ select MACH_MX21
select CPU_ARM926T
select ARCH_MXC_AUDMUX_V1
select IMX_HAVE_DMA_V1
@@ -28,6 +52,7 @@ config SOC_IMX21
config SOC_IMX25
bool
+ select ARCH_MX25
select CPU_ARM926T
select ARCH_MXC_AUDMUX_V2
select ARCH_MXC_IOMUX_V3
@@ -35,6 +60,7 @@ config SOC_IMX25
config SOC_IMX27
bool
+ select MACH_MX27
select CPU_ARM926T
select ARCH_MXC_AUDMUX_V1
select IMX_HAVE_DMA_V1
@@ -48,6 +74,7 @@ config SOC_IMX31
select ARCH_MXC_AUDMUX_V2
select ARCH_MX31
select MXC_AVIC
+ select SMP_ON_UP if SMP
config SOC_IMX35
bool
@@ -57,9 +84,10 @@ config SOC_IMX35
select HAVE_EPIT
select ARCH_MX35
select MXC_AVIC
+ select SMP_ON_UP if SMP
-if ARCH_MX1
+if ARCH_IMX_V4_V5
comment "MX1 platforms:"
config MACH_MXLADS
@@ -87,30 +115,6 @@ config MACH_APF9328
help
Say Yes here if you are using the Armadeus APF9328 development board
-endif
-
-if ARCH_MX2
-
-choice
- prompt "CPUs:"
- default MACH_MX21
-
-config MACH_MX21
- bool "i.MX21 support"
- help
- This enables support for Freescale's MX2 based i.MX21 processor.
-
-config MACH_MX27
- bool "i.MX27 support"
- help
- This enables support for Freescale's MX2 based i.MX27 processor.
-
-endchoice
-
-endif
-
-if MACH_MX21
-
comment "MX21 platforms:"
config MACH_MX21ADS
@@ -124,15 +128,12 @@ config MACH_MX21ADS
Include support for MX21ADS platform. This includes specific
configurations for the board and its peripherals.
-endif
-
-if ARCH_MX25
-
comment "MX25 platforms:"
config MACH_MX25_3DS
bool "Support MX25PDK (3DS) Platform"
select SOC_IMX25
+ select IMX_HAVE_PLATFORM_FLEXCAN
select IMX_HAVE_PLATFORM_FSL_USB2_UDC
select IMX_HAVE_PLATFORM_IMX2_WDT
select IMX_HAVE_PLATFORM_IMXDI_RTC
@@ -174,10 +175,6 @@ config MACH_EUKREA_MBIMXSD25_BASEBOARD
endchoice
-endif
-
-if MACH_MX27
-
comment "MX27 platforms:"
config MACH_MX27ADS
@@ -356,7 +353,7 @@ config MACH_IMX27IPCAM
endif
-if ARCH_MX3
+if ARCH_IMX_V6_V7
comment "MX31 platforms:"
@@ -449,6 +446,7 @@ config MACH_MX31_3DS
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_IPU_CORE
select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_MXC_MMC
select IMX_HAVE_PLATFORM_MXC_NAND
select IMX_HAVE_PLATFORM_SPI_IMX
select MXC_ULPI if USB_ULPI
@@ -485,6 +483,7 @@ config MACH_QONG
bool "Support Dave/DENX QongEVB-LITE platform"
select SOC_IMX31
select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_IMX2_WDT
help
Include support for Dave/DENX QongEVB-LITE platform. This includes
specific configurations for the board and its peripherals.
@@ -605,4 +604,20 @@ config MACH_VPR200
Include support for VPR200 platform. This includes specific
configurations for the board and its peripherals.
+comment "i.MX6 family:"
+
+config SOC_IMX6Q
+ bool "i.MX6 Quad support"
+ select ARM_GIC
+ select CACHE_L2X0
+ select CPU_V7
+ select HAVE_ARM_SCU
+ select HAVE_IMX_GPC
+ select HAVE_IMX_MMDC
+ select HAVE_IMX_SRC
+ select USE_OF
+
+ help
+ This enables support for Freescale i.MX6 Quad processor.
+
endif
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index e9eb36dad888..aba73214c2a8 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -1,16 +1,15 @@
obj-$(CONFIG_IMX_HAVE_DMA_V1) += dma-v1.o
-obj-$(CONFIG_ARCH_MX1) += clock-imx1.o mm-imx1.o
-obj-$(CONFIG_MACH_MX21) += clock-imx21.o mm-imx21.o
+obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o
+obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
-obj-$(CONFIG_ARCH_MX25) += clock-imx25.o mm-imx25.o ehci-imx25.o
+obj-$(CONFIG_SOC_IMX25) += clock-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
-obj-$(CONFIG_MACH_MX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
+obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
+obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
-obj-$(CONFIG_SOC_IMX31) += mm-imx31.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
-obj-$(CONFIG_SOC_IMX35) += mm-imx35.o cpu-imx35.o clock-imx35.o ehci-imx35.o
-obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
+obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
+obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
# Support for CMOS sensor interface
obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
@@ -61,3 +60,14 @@ obj-$(CONFIG_MACH_MX35_3DS) += mach-mx35_3ds.o
obj-$(CONFIG_MACH_EUKREA_CPUIMX35) += mach-cpuimx35.o
obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
+
+obj-$(CONFIG_DEBUG_LL) += lluart.o
+obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
+obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
+obj-$(CONFIG_HAVE_IMX_SRC) += src.o
+obj-$(CONFIG_CPU_V7) += head-v7.o
+AFLAGS_head-v7.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SMP) += platsmp.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o pm-imx6q.o
diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot
index ebee18b3884c..22d85889f622 100644
--- a/arch/arm/mach-imx/Makefile.boot
+++ b/arch/arm/mach-imx/Makefile.boot
@@ -1,19 +1,23 @@
-zreladdr-$(CONFIG_ARCH_MX1) := 0x08008000
+zreladdr-$(CONFIG_ARCH_MX1) += 0x08008000
params_phys-$(CONFIG_ARCH_MX1) := 0x08000100
initrd_phys-$(CONFIG_ARCH_MX1) := 0x08800000
-zreladdr-$(CONFIG_MACH_MX21) := 0xC0008000
+zreladdr-$(CONFIG_MACH_MX21) += 0xC0008000
params_phys-$(CONFIG_MACH_MX21) := 0xC0000100
initrd_phys-$(CONFIG_MACH_MX21) := 0xC0800000
-zreladdr-$(CONFIG_ARCH_MX25) := 0x80008000
+zreladdr-$(CONFIG_ARCH_MX25) += 0x80008000
params_phys-$(CONFIG_ARCH_MX25) := 0x80000100
initrd_phys-$(CONFIG_ARCH_MX25) := 0x80800000
-zreladdr-$(CONFIG_MACH_MX27) := 0xA0008000
+zreladdr-$(CONFIG_MACH_MX27) += 0xA0008000
params_phys-$(CONFIG_MACH_MX27) := 0xA0000100
initrd_phys-$(CONFIG_MACH_MX27) := 0xA0800000
-zreladdr-$(CONFIG_ARCH_MX3) := 0x80008000
+zreladdr-$(CONFIG_ARCH_MX3) += 0x80008000
params_phys-$(CONFIG_ARCH_MX3) := 0x80000100
initrd_phys-$(CONFIG_ARCH_MX3) := 0x80800000
+
+zreladdr-$(CONFIG_SOC_IMX6Q) += 0x10008000
+params_phys-$(CONFIG_SOC_IMX6Q) := 0x10000100
+initrd_phys-$(CONFIG_SOC_IMX6Q) := 0x10800000
diff --git a/arch/arm/mach-imx/cache-l2x0.c b/arch/arm/mach-imx/cache-l2x0.c
deleted file mode 100644
index 69d1322add3c..000000000000
--- a/arch/arm/mach-imx/cache-l2x0.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Sascha Hauer <s.hauer@pengutronix.de>
- * Juergen Beisert <j.beisert@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-
-#include <asm/hardware/cache-l2x0.h>
-
-#include <mach/hardware.h>
-
-static int mxc_init_l2x0(void)
-{
- void __iomem *l2x0_base;
- void __iomem *clkctl_base;
-
- if (!cpu_is_mx31() && !cpu_is_mx35())
- return 0;
-
-/*
- * First of all, we must repair broken chip settings. There are some
- * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
- * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
- * Workaraound is to setup the correct register setting prior enabling the
- * L2 cache. This should not hurt already working CPUs, as they are using the
- * same value.
- */
-#define L2_MEM_VAL 0x10
-
- clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
- if (clkctl_base != NULL) {
- writel(0x00000515, clkctl_base + L2_MEM_VAL);
- iounmap(clkctl_base);
- } else {
- pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
- }
-
- l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
- if (IS_ERR(l2x0_base)) {
- printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
- PTR_ERR(l2x0_base));
- return 0;
- }
-
- l2x0_init(l2x0_base, 0x00030024, 0x00000000);
-
- return 0;
-}
-arch_initcall(mxc_init_l2x0);
diff --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c
index e63e23504fe5..b0fec74c8c91 100644
--- a/arch/arm/mach-imx/clock-imx25.c
+++ b/arch/arm/mach-imx/clock-imx25.c
@@ -263,6 +263,7 @@ DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0, NULL, NULL, NULL);
DEFINE_CLOCK(csi_clk, 0, CCM_CGCR1, 4, get_rate_csi, NULL, &csi_per_clk);
DEFINE_CLOCK(can1_clk, 0, CCM_CGCR1, 2, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(can2_clk, 1, CCM_CGCR1, 3, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(iim_clk, 0, CCM_CGCR1, 26, NULL, NULL, NULL);
#define _REGISTER_CLOCK(d, n, c) \
{ \
@@ -310,6 +311,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
/* i.mx25 has the i.mx35 type sdma */
_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
+ _REGISTER_CLOCK(NULL, "iim", iim_clk)
};
int __init mx25_clocks_init(void)
@@ -334,6 +336,10 @@ int __init mx25_clocks_init(void)
/* Clock source for gpt is ahb_div */
__raw_writel(__raw_readl(CRM_BASE+0x64) & ~(1 << 5), CRM_BASE + 0x64);
+ clk_enable(&iim_clk);
+ imx_print_silicon_rev("i.MX25", mx25_revision());
+ clk_disable(&iim_clk);
+
mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
return 0;
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 6912b821b37b..88fe00a146e3 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -583,7 +583,7 @@ DEFINE_CLOCK(emi_clk, 0, PCCR1, 19, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(dma_clk1, 0, PCCR1, 20, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(csi_clk1, 0, PCCR1, 21, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(brom_clk, 0, PCCR1, 22, NULL, NULL, &ahb_clk);
-DEFINE_CLOCK(ata_clk, 0, PCCR1, 23, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(pata_clk, 0, PCCR1, 23, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(wdog_clk, 0, PCCR1, 24, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(usb_clk, 0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk);
DEFINE_CLOCK(uart6_clk1, 0, PCCR1, 26, NULL, NULL, &ipg_clk);
@@ -666,7 +666,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
_REGISTER_CLOCK(NULL, "emi", emi_clk)
_REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
- _REGISTER_CLOCK(NULL, "ata", ata_clk)
+ _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
_REGISTER_CLOCK(NULL, "mstick", mstick_clk)
_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
_REGISTER_CLOCK(NULL, "gpio", gpio_clk)
@@ -751,6 +751,8 @@ int __init mx27_clocks_init(unsigned long fref)
clk_enable(&gpio_clk);
clk_enable(&emi_clk);
clk_enable(&iim_clk);
+ imx_print_silicon_rev("i.MX27", mx27_revision());
+ clk_disable(&iim_clk);
#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
clk_enable(&uart1_clk);
diff --git a/arch/arm/mach-imx/clock-imx31.c b/arch/arm/mach-imx/clock-imx31.c
index d973770b1f96..988a28178d4c 100644
--- a/arch/arm/mach-imx/clock-imx31.c
+++ b/arch/arm/mach-imx/clock-imx31.c
@@ -476,7 +476,7 @@ DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CGR0, 4, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(epit1_clk, 0, MXC_CCM_CGR0, 6, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(epit2_clk, 1, MXC_CCM_CGR0, 8, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(iim_clk, 0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(ata_clk, 0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(sdma_clk1, 0, MXC_CCM_CGR0, 14, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(cspi3_clk, 2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(rng_clk, 0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
@@ -562,7 +562,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
_REGISTER_CLOCK(NULL, "firi", firi_clk)
- _REGISTER_CLOCK(NULL, "ata", ata_clk)
+ _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
_REGISTER_CLOCK(NULL, "rng", rng_clk)
_REGISTER_CLOCK("imx31-sdma", NULL, sdma_clk1)
@@ -611,11 +611,11 @@ int __init mx31_clocks_init(unsigned long fref)
clk_enable(&gpt_clk);
clk_enable(&emi_clk);
clk_enable(&iim_clk);
+ mx31_revision();
+ clk_disable(&iim_clk);
clk_enable(&serial_pll_clk);
- mx31_read_cpu_rev();
-
if (mx31_revision() >= IMX_CHIP_REVISION_2_0) {
reg = __raw_readl(MXC_CCM_PMCR1);
/* No PLL restart on DVFS switch; enable auto EMI handshake */
diff --git a/arch/arm/mach-imx/clock-imx35.c b/arch/arm/mach-imx/clock-imx35.c
index 88b62a071aea..8116f119517d 100644
--- a/arch/arm/mach-imx/clock-imx35.c
+++ b/arch/arm/mach-imx/clock-imx35.c
@@ -354,7 +354,7 @@ static void clk_cgr_disable(struct clk *clk)
}
DEFINE_CLOCK(asrc_clk, 0, CCM_CGR0, 0, NULL, NULL);
-DEFINE_CLOCK(ata_clk, 0, CCM_CGR0, 2, get_rate_ipg, NULL);
+DEFINE_CLOCK(pata_clk, 0, CCM_CGR0, 2, get_rate_ipg, NULL);
/* DEFINE_CLOCK(audmux_clk, 0, CCM_CGR0, 4, NULL, NULL); */
DEFINE_CLOCK(can1_clk, 0, CCM_CGR0, 6, get_rate_ipg, NULL);
DEFINE_CLOCK(can2_clk, 1, CCM_CGR0, 8, get_rate_ipg, NULL);
@@ -447,7 +447,7 @@ static struct clk nfc_clk = {
static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "asrc", asrc_clk)
- _REGISTER_CLOCK(NULL, "ata", ata_clk)
+ _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
@@ -537,7 +537,8 @@ int __init mx35_clocks_init()
__raw_writel(cgr3, CCM_BASE + CCM_CGR3);
clk_enable(&iim_clk);
- mx35_read_cpu_rev();
+ imx_print_silicon_rev("i.MX35", mx35_revision());
+ clk_disable(&iim_clk);
#ifdef CONFIG_MXC_USE_EPIT
epit_timer_init(&epit1_clk,
diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c
new file mode 100644
index 000000000000..e0b926dfeced
--- /dev/null
+++ b/arch/arm/mach-imx/clock-imx6q.c
@@ -0,0 +1,2012 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/div64.h>
+#include <asm/mach/map.h>
+#include <mach/clock.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+#define PLL_BASE IMX_IO_ADDRESS(MX6Q_ANATOP_BASE_ADDR)
+#define PLL1_SYS (PLL_BASE + 0x000)
+#define PLL2_BUS (PLL_BASE + 0x030)
+#define PLL3_USB_OTG (PLL_BASE + 0x010)
+#define PLL4_AUDIO (PLL_BASE + 0x070)
+#define PLL5_VIDEO (PLL_BASE + 0x0a0)
+#define PLL6_MLB (PLL_BASE + 0x0d0)
+#define PLL7_USB_HOST (PLL_BASE + 0x020)
+#define PLL8_ENET (PLL_BASE + 0x0e0)
+#define PFD_480 (PLL_BASE + 0x0f0)
+#define PFD_528 (PLL_BASE + 0x100)
+#define PLL_NUM_OFFSET 0x010
+#define PLL_DENOM_OFFSET 0x020
+
+#define PFD0 7
+#define PFD1 15
+#define PFD2 23
+#define PFD3 31
+#define PFD_FRAC_MASK 0x3f
+
+#define BM_PLL_BYPASS (0x1 << 16)
+#define BM_PLL_ENABLE (0x1 << 13)
+#define BM_PLL_POWER_DOWN (0x1 << 12)
+#define BM_PLL_LOCK (0x1 << 31)
+#define BP_PLL_SYS_DIV_SELECT 0
+#define BM_PLL_SYS_DIV_SELECT (0x7f << 0)
+#define BP_PLL_BUS_DIV_SELECT 0
+#define BM_PLL_BUS_DIV_SELECT (0x1 << 0)
+#define BP_PLL_USB_DIV_SELECT 0
+#define BM_PLL_USB_DIV_SELECT (0x3 << 0)
+#define BP_PLL_AV_DIV_SELECT 0
+#define BM_PLL_AV_DIV_SELECT (0x7f << 0)
+#define BP_PLL_ENET_DIV_SELECT 0
+#define BM_PLL_ENET_DIV_SELECT (0x3 << 0)
+#define BM_PLL_ENET_EN_PCIE (0x1 << 19)
+#define BM_PLL_ENET_EN_SATA (0x1 << 20)
+
+#define CCM_BASE IMX_IO_ADDRESS(MX6Q_CCM_BASE_ADDR)
+#define CCR (CCM_BASE + 0x00)
+#define CCDR (CCM_BASE + 0x04)
+#define CSR (CCM_BASE + 0x08)
+#define CCSR (CCM_BASE + 0x0c)
+#define CACRR (CCM_BASE + 0x10)
+#define CBCDR (CCM_BASE + 0x14)
+#define CBCMR (CCM_BASE + 0x18)
+#define CSCMR1 (CCM_BASE + 0x1c)
+#define CSCMR2 (CCM_BASE + 0x20)
+#define CSCDR1 (CCM_BASE + 0x24)
+#define CS1CDR (CCM_BASE + 0x28)
+#define CS2CDR (CCM_BASE + 0x2c)
+#define CDCDR (CCM_BASE + 0x30)
+#define CHSCCDR (CCM_BASE + 0x34)
+#define CSCDR2 (CCM_BASE + 0x38)
+#define CSCDR3 (CCM_BASE + 0x3c)
+#define CSCDR4 (CCM_BASE + 0x40)
+#define CWDR (CCM_BASE + 0x44)
+#define CDHIPR (CCM_BASE + 0x48)
+#define CDCR (CCM_BASE + 0x4c)
+#define CTOR (CCM_BASE + 0x50)
+#define CLPCR (CCM_BASE + 0x54)
+#define CISR (CCM_BASE + 0x58)
+#define CIMR (CCM_BASE + 0x5c)
+#define CCOSR (CCM_BASE + 0x60)
+#define CGPR (CCM_BASE + 0x64)
+#define CCGR0 (CCM_BASE + 0x68)
+#define CCGR1 (CCM_BASE + 0x6c)
+#define CCGR2 (CCM_BASE + 0x70)
+#define CCGR3 (CCM_BASE + 0x74)
+#define CCGR4 (CCM_BASE + 0x78)
+#define CCGR5 (CCM_BASE + 0x7c)
+#define CCGR6 (CCM_BASE + 0x80)
+#define CCGR7 (CCM_BASE + 0x84)
+#define CMEOR (CCM_BASE + 0x88)
+
+#define CG0 0
+#define CG1 2
+#define CG2 4
+#define CG3 6
+#define CG4 8
+#define CG5 10
+#define CG6 12
+#define CG7 14
+#define CG8 16
+#define CG9 18
+#define CG10 20
+#define CG11 22
+#define CG12 24
+#define CG13 26
+#define CG14 28
+#define CG15 30
+
+#define BM_CCSR_PLL1_SW_SEL (0x1 << 2)
+#define BM_CCSR_STEP_SEL (0x1 << 8)
+
+#define BP_CACRR_ARM_PODF 0
+#define BM_CACRR_ARM_PODF (0x7 << 0)
+
+#define BP_CBCDR_PERIPH2_CLK2_PODF 0
+#define BM_CBCDR_PERIPH2_CLK2_PODF (0x7 << 0)
+#define BP_CBCDR_MMDC_CH1_AXI_PODF 3
+#define BM_CBCDR_MMDC_CH1_AXI_PODF (0x7 << 3)
+#define BP_CBCDR_AXI_SEL 6
+#define BM_CBCDR_AXI_SEL (0x3 << 6)
+#define BP_CBCDR_IPG_PODF 8
+#define BM_CBCDR_IPG_PODF (0x3 << 8)
+#define BP_CBCDR_AHB_PODF 10
+#define BM_CBCDR_AHB_PODF (0x7 << 10)
+#define BP_CBCDR_AXI_PODF 16
+#define BM_CBCDR_AXI_PODF (0x7 << 16)
+#define BP_CBCDR_MMDC_CH0_AXI_PODF 19
+#define BM_CBCDR_MMDC_CH0_AXI_PODF (0x7 << 19)
+#define BP_CBCDR_PERIPH_CLK_SEL 25
+#define BM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
+#define BP_CBCDR_PERIPH2_CLK_SEL 26
+#define BM_CBCDR_PERIPH2_CLK_SEL (0x1 << 26)
+#define BP_CBCDR_PERIPH_CLK2_PODF 27
+#define BM_CBCDR_PERIPH_CLK2_PODF (0x7 << 27)
+
+#define BP_CBCMR_GPU2D_AXI_SEL 0
+#define BM_CBCMR_GPU2D_AXI_SEL (0x1 << 0)
+#define BP_CBCMR_GPU3D_AXI_SEL 1
+#define BM_CBCMR_GPU3D_AXI_SEL (0x1 << 1)
+#define BP_CBCMR_GPU3D_CORE_SEL 4
+#define BM_CBCMR_GPU3D_CORE_SEL (0x3 << 4)
+#define BP_CBCMR_GPU3D_SHADER_SEL 8
+#define BM_CBCMR_GPU3D_SHADER_SEL (0x3 << 8)
+#define BP_CBCMR_PCIE_AXI_SEL 10
+#define BM_CBCMR_PCIE_AXI_SEL (0x1 << 10)
+#define BP_CBCMR_VDO_AXI_SEL 11
+#define BM_CBCMR_VDO_AXI_SEL (0x1 << 11)
+#define BP_CBCMR_PERIPH_CLK2_SEL 12
+#define BM_CBCMR_PERIPH_CLK2_SEL (0x3 << 12)
+#define BP_CBCMR_VPU_AXI_SEL 14
+#define BM_CBCMR_VPU_AXI_SEL (0x3 << 14)
+#define BP_CBCMR_GPU2D_CORE_SEL 16
+#define BM_CBCMR_GPU2D_CORE_SEL (0x3 << 16)
+#define BP_CBCMR_PRE_PERIPH_CLK_SEL 18
+#define BM_CBCMR_PRE_PERIPH_CLK_SEL (0x3 << 18)
+#define BP_CBCMR_PERIPH2_CLK2_SEL 20
+#define BM_CBCMR_PERIPH2_CLK2_SEL (0x1 << 20)
+#define BP_CBCMR_PRE_PERIPH2_CLK_SEL 21
+#define BM_CBCMR_PRE_PERIPH2_CLK_SEL (0x3 << 21)
+#define BP_CBCMR_GPU2D_CORE_PODF 23
+#define BM_CBCMR_GPU2D_CORE_PODF (0x7 << 23)
+#define BP_CBCMR_GPU3D_CORE_PODF 26
+#define BM_CBCMR_GPU3D_CORE_PODF (0x7 << 26)
+#define BP_CBCMR_GPU3D_SHADER_PODF 29
+#define BM_CBCMR_GPU3D_SHADER_PODF (0x7 << 29)
+
+#define BP_CSCMR1_PERCLK_PODF 0
+#define BM_CSCMR1_PERCLK_PODF (0x3f << 0)
+#define BP_CSCMR1_SSI1_SEL 10
+#define BM_CSCMR1_SSI1_SEL (0x3 << 10)
+#define BP_CSCMR1_SSI2_SEL 12
+#define BM_CSCMR1_SSI2_SEL (0x3 << 12)
+#define BP_CSCMR1_SSI3_SEL 14
+#define BM_CSCMR1_SSI3_SEL (0x3 << 14)
+#define BP_CSCMR1_USDHC1_SEL 16
+#define BM_CSCMR1_USDHC1_SEL (0x1 << 16)
+#define BP_CSCMR1_USDHC2_SEL 17
+#define BM_CSCMR1_USDHC2_SEL (0x1 << 17)
+#define BP_CSCMR1_USDHC3_SEL 18
+#define BM_CSCMR1_USDHC3_SEL (0x1 << 18)
+#define BP_CSCMR1_USDHC4_SEL 19
+#define BM_CSCMR1_USDHC4_SEL (0x1 << 19)
+#define BP_CSCMR1_EMI_PODF 20
+#define BM_CSCMR1_EMI_PODF (0x7 << 20)
+#define BP_CSCMR1_EMI_SLOW_PODF 23
+#define BM_CSCMR1_EMI_SLOW_PODF (0x7 << 23)
+#define BP_CSCMR1_EMI_SEL 27
+#define BM_CSCMR1_EMI_SEL (0x3 << 27)
+#define BP_CSCMR1_EMI_SLOW_SEL 29
+#define BM_CSCMR1_EMI_SLOW_SEL (0x3 << 29)
+
+#define BP_CSCMR2_CAN_PODF 2
+#define BM_CSCMR2_CAN_PODF (0x3f << 2)
+#define BM_CSCMR2_LDB_DI0_IPU_DIV (0x1 << 10)
+#define BM_CSCMR2_LDB_DI1_IPU_DIV (0x1 << 11)
+#define BP_CSCMR2_ESAI_SEL 19
+#define BM_CSCMR2_ESAI_SEL (0x3 << 19)
+
+#define BP_CSCDR1_UART_PODF 0
+#define BM_CSCDR1_UART_PODF (0x3f << 0)
+#define BP_CSCDR1_USDHC1_PODF 11
+#define BM_CSCDR1_USDHC1_PODF (0x7 << 11)
+#define BP_CSCDR1_USDHC2_PODF 16
+#define BM_CSCDR1_USDHC2_PODF (0x7 << 16)
+#define BP_CSCDR1_USDHC3_PODF 19
+#define BM_CSCDR1_USDHC3_PODF (0x7 << 19)
+#define BP_CSCDR1_USDHC4_PODF 22
+#define BM_CSCDR1_USDHC4_PODF (0x7 << 22)
+#define BP_CSCDR1_VPU_AXI_PODF 25
+#define BM_CSCDR1_VPU_AXI_PODF (0x7 << 25)
+
+#define BP_CS1CDR_SSI1_PODF 0
+#define BM_CS1CDR_SSI1_PODF (0x3f << 0)
+#define BP_CS1CDR_SSI1_PRED 6
+#define BM_CS1CDR_SSI1_PRED (0x7 << 6)
+#define BP_CS1CDR_ESAI_PRED 9
+#define BM_CS1CDR_ESAI_PRED (0x7 << 9)
+#define BP_CS1CDR_SSI3_PODF 16
+#define BM_CS1CDR_SSI3_PODF (0x3f << 16)
+#define BP_CS1CDR_SSI3_PRED 22
+#define BM_CS1CDR_SSI3_PRED (0x7 << 22)
+#define BP_CS1CDR_ESAI_PODF 25
+#define BM_CS1CDR_ESAI_PODF (0x7 << 25)
+
+#define BP_CS2CDR_SSI2_PODF 0
+#define BM_CS2CDR_SSI2_PODF (0x3f << 0)
+#define BP_CS2CDR_SSI2_PRED 6
+#define BM_CS2CDR_SSI2_PRED (0x7 << 6)
+#define BP_CS2CDR_LDB_DI0_SEL 9
+#define BM_CS2CDR_LDB_DI0_SEL (0x7 << 9)
+#define BP_CS2CDR_LDB_DI1_SEL 12
+#define BM_CS2CDR_LDB_DI1_SEL (0x7 << 12)
+#define BP_CS2CDR_ENFC_SEL 16
+#define BM_CS2CDR_ENFC_SEL (0x3 << 16)
+#define BP_CS2CDR_ENFC_PRED 18
+#define BM_CS2CDR_ENFC_PRED (0x7 << 18)
+#define BP_CS2CDR_ENFC_PODF 21
+#define BM_CS2CDR_ENFC_PODF (0x3f << 21)
+
+#define BP_CDCDR_ASRC_SERIAL_SEL 7
+#define BM_CDCDR_ASRC_SERIAL_SEL (0x3 << 7)
+#define BP_CDCDR_ASRC_SERIAL_PODF 9
+#define BM_CDCDR_ASRC_SERIAL_PODF (0x7 << 9)
+#define BP_CDCDR_ASRC_SERIAL_PRED 12
+#define BM_CDCDR_ASRC_SERIAL_PRED (0x7 << 12)
+#define BP_CDCDR_SPDIF_SEL 20
+#define BM_CDCDR_SPDIF_SEL (0x3 << 20)
+#define BP_CDCDR_SPDIF_PODF 22
+#define BM_CDCDR_SPDIF_PODF (0x7 << 22)
+#define BP_CDCDR_SPDIF_PRED 25
+#define BM_CDCDR_SPDIF_PRED (0x7 << 25)
+#define BP_CDCDR_HSI_TX_PODF 29
+#define BM_CDCDR_HSI_TX_PODF (0x7 << 29)
+#define BP_CDCDR_HSI_TX_SEL 28
+#define BM_CDCDR_HSI_TX_SEL (0x1 << 28)
+
+#define BP_CHSCCDR_IPU1_DI0_SEL 0
+#define BM_CHSCCDR_IPU1_DI0_SEL (0x7 << 0)
+#define BP_CHSCCDR_IPU1_DI0_PRE_PODF 3
+#define BM_CHSCCDR_IPU1_DI0_PRE_PODF (0x7 << 3)
+#define BP_CHSCCDR_IPU1_DI0_PRE_SEL 6
+#define BM_CHSCCDR_IPU1_DI0_PRE_SEL (0x7 << 6)
+#define BP_CHSCCDR_IPU1_DI1_SEL 9
+#define BM_CHSCCDR_IPU1_DI1_SEL (0x7 << 9)
+#define BP_CHSCCDR_IPU1_DI1_PRE_PODF 12
+#define BM_CHSCCDR_IPU1_DI1_PRE_PODF (0x7 << 12)
+#define BP_CHSCCDR_IPU1_DI1_PRE_SEL 15
+#define BM_CHSCCDR_IPU1_DI1_PRE_SEL (0x7 << 15)
+
+#define BP_CSCDR2_IPU2_DI0_SEL 0
+#define BM_CSCDR2_IPU2_DI0_SEL (0x7)
+#define BP_CSCDR2_IPU2_DI0_PRE_PODF 3
+#define BM_CSCDR2_IPU2_DI0_PRE_PODF (0x7 << 3)
+#define BP_CSCDR2_IPU2_DI0_PRE_SEL 6
+#define BM_CSCDR2_IPU2_DI0_PRE_SEL (0x7 << 6)
+#define BP_CSCDR2_IPU2_DI1_SEL 9
+#define BM_CSCDR2_IPU2_DI1_SEL (0x7 << 9)
+#define BP_CSCDR2_IPU2_DI1_PRE_PODF 12
+#define BM_CSCDR2_IPU2_DI1_PRE_PODF (0x7 << 12)
+#define BP_CSCDR2_IPU2_DI1_PRE_SEL 15
+#define BM_CSCDR2_IPU2_DI1_PRE_SEL (0x7 << 15)
+#define BP_CSCDR2_ECSPI_CLK_PODF 19
+#define BM_CSCDR2_ECSPI_CLK_PODF (0x3f << 19)
+
+#define BP_CSCDR3_IPU1_HSP_SEL 9
+#define BM_CSCDR3_IPU1_HSP_SEL (0x3 << 9)
+#define BP_CSCDR3_IPU1_HSP_PODF 11
+#define BM_CSCDR3_IPU1_HSP_PODF (0x7 << 11)
+#define BP_CSCDR3_IPU2_HSP_SEL 14
+#define BM_CSCDR3_IPU2_HSP_SEL (0x3 << 14)
+#define BP_CSCDR3_IPU2_HSP_PODF 16
+#define BM_CSCDR3_IPU2_HSP_PODF (0x7 << 16)
+
+#define BM_CDHIPR_AXI_PODF_BUSY (0x1 << 0)
+#define BM_CDHIPR_AHB_PODF_BUSY (0x1 << 1)
+#define BM_CDHIPR_MMDC_CH1_PODF_BUSY (0x1 << 2)
+#define BM_CDHIPR_PERIPH2_SEL_BUSY (0x1 << 3)
+#define BM_CDHIPR_MMDC_CH0_PODF_BUSY (0x1 << 4)
+#define BM_CDHIPR_PERIPH_SEL_BUSY (0x1 << 5)
+#define BM_CDHIPR_ARM_PODF_BUSY (0x1 << 16)
+
+#define BP_CLPCR_LPM 0
+#define BM_CLPCR_LPM (0x3 << 0)
+#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
+#define BM_CLPCR_SBYOS (0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
+#define BM_CLPCR_VSTBY (0x1 << 8)
+#define BP_CLPCR_STBY_COUNT 9
+#define BM_CLPCR_STBY_COUNT (0x3 << 9)
+#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
+#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
+#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
+#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
+#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
+#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
+#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
+#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
+#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
+#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
+
+#define FREQ_480M 480000000
+#define FREQ_528M 528000000
+#define FREQ_594M 594000000
+#define FREQ_650M 650000000
+#define FREQ_1300M 1300000000
+
+static struct clk pll1_sys;
+static struct clk pll2_bus;
+static struct clk pll3_usb_otg;
+static struct clk pll4_audio;
+static struct clk pll5_video;
+static struct clk pll6_mlb;
+static struct clk pll7_usb_host;
+static struct clk pll8_enet;
+static struct clk apbh_dma_clk;
+static struct clk arm_clk;
+static struct clk ipg_clk;
+static struct clk ahb_clk;
+static struct clk axi_clk;
+static struct clk mmdc_ch0_axi_clk;
+static struct clk mmdc_ch1_axi_clk;
+static struct clk periph_clk;
+static struct clk periph_pre_clk;
+static struct clk periph_clk2_clk;
+static struct clk periph2_clk;
+static struct clk periph2_pre_clk;
+static struct clk periph2_clk2_clk;
+static struct clk gpu2d_core_clk;
+static struct clk gpu3d_core_clk;
+static struct clk gpu3d_shader_clk;
+static struct clk ipg_perclk;
+static struct clk emi_clk;
+static struct clk emi_slow_clk;
+static struct clk can1_clk;
+static struct clk uart_clk;
+static struct clk usdhc1_clk;
+static struct clk usdhc2_clk;
+static struct clk usdhc3_clk;
+static struct clk usdhc4_clk;
+static struct clk vpu_clk;
+static struct clk hsi_tx_clk;
+static struct clk ipu1_di0_pre_clk;
+static struct clk ipu1_di1_pre_clk;
+static struct clk ipu2_di0_pre_clk;
+static struct clk ipu2_di1_pre_clk;
+static struct clk ipu1_clk;
+static struct clk ipu2_clk;
+static struct clk ssi1_clk;
+static struct clk ssi3_clk;
+static struct clk esai_clk;
+static struct clk ssi2_clk;
+static struct clk spdif_clk;
+static struct clk asrc_serial_clk;
+static struct clk gpu2d_axi_clk;
+static struct clk gpu3d_axi_clk;
+static struct clk pcie_clk;
+static struct clk vdo_axi_clk;
+static struct clk ldb_di0_clk;
+static struct clk ldb_di1_clk;
+static struct clk ipu1_di0_clk;
+static struct clk ipu1_di1_clk;
+static struct clk ipu2_di0_clk;
+static struct clk ipu2_di1_clk;
+static struct clk enfc_clk;
+static struct clk dummy_clk = {};
+
+static unsigned long external_high_reference;
+static unsigned long external_low_reference;
+static unsigned long oscillator_reference;
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+ return oscillator_reference;
+}
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+ return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+ return external_low_reference;
+}
+
+static struct clk ckil_clk = {
+ .get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk ckih_clk = {
+ .get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+ .get_rate = get_oscillator_reference_clock_rate,
+};
+
+static inline void __iomem *pll_get_reg_addr(struct clk *pll)
+{
+ if (pll == &pll1_sys)
+ return PLL1_SYS;
+ else if (pll == &pll2_bus)
+ return PLL2_BUS;
+ else if (pll == &pll3_usb_otg)
+ return PLL3_USB_OTG;
+ else if (pll == &pll4_audio)
+ return PLL4_AUDIO;
+ else if (pll == &pll5_video)
+ return PLL5_VIDEO;
+ else if (pll == &pll6_mlb)
+ return PLL6_MLB;
+ else if (pll == &pll7_usb_host)
+ return PLL7_USB_HOST;
+ else if (pll == &pll8_enet)
+ return PLL8_ENET;
+ else
+ BUG();
+
+ return NULL;
+}
+
+static int pll_enable(struct clk *clk)
+{
+ int timeout = 0x100000;
+ void __iomem *reg;
+ u32 val;
+
+ reg = pll_get_reg_addr(clk);
+ val = readl_relaxed(reg);
+ val &= ~BM_PLL_BYPASS;
+ val &= ~BM_PLL_POWER_DOWN;
+ /* 480MHz PLLs have the opposite definition for power bit */
+ if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
+ val |= BM_PLL_POWER_DOWN;
+ writel_relaxed(val, reg);
+
+ /* Wait for PLL to lock */
+ while (!(readl_relaxed(reg) & BM_PLL_LOCK) && --timeout)
+ cpu_relax();
+
+ if (unlikely(!timeout))
+ return -EBUSY;
+
+ /* Enable the PLL output now */
+ val = readl_relaxed(reg);
+ val |= BM_PLL_ENABLE;
+ writel_relaxed(val, reg);
+
+ return 0;
+}
+
+static void pll_disable(struct clk *clk)
+{
+ void __iomem *reg;
+ u32 val;
+
+ reg = pll_get_reg_addr(clk);
+ val = readl_relaxed(reg);
+ val &= ~BM_PLL_ENABLE;
+ val |= BM_PLL_BYPASS;
+ val |= BM_PLL_POWER_DOWN;
+ if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
+ val &= ~BM_PLL_POWER_DOWN;
+ writel_relaxed(val, reg);
+}
+
+static unsigned long pll1_sys_get_rate(struct clk *clk)
+{
+ u32 div = (readl_relaxed(PLL1_SYS) & BM_PLL_SYS_DIV_SELECT) >>
+ BP_PLL_SYS_DIV_SELECT;
+
+ return clk_get_rate(clk->parent) * div / 2;
+}
+
+static int pll1_sys_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val, div;
+
+ if (rate < FREQ_650M || rate > FREQ_1300M)
+ return -EINVAL;
+
+ div = rate * 2 / clk_get_rate(clk->parent);
+ val = readl_relaxed(PLL1_SYS);
+ val &= ~BM_PLL_SYS_DIV_SELECT;
+ val |= div << BP_PLL_SYS_DIV_SELECT;
+ writel_relaxed(val, PLL1_SYS);
+
+ return 0;
+}
+
+static unsigned long pll8_enet_get_rate(struct clk *clk)
+{
+ u32 div = (readl_relaxed(PLL8_ENET) & BM_PLL_ENET_DIV_SELECT) >>
+ BP_PLL_ENET_DIV_SELECT;
+
+ switch (div) {
+ case 0:
+ return 25000000;
+ case 1:
+ return 50000000;
+ case 2:
+ return 100000000;
+ case 3:
+ return 125000000;
+ }
+
+ return 0;
+}
+
+static int pll8_enet_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val, div;
+
+ switch (rate) {
+ case 25000000:
+ div = 0;
+ break;
+ case 50000000:
+ div = 1;
+ break;
+ case 100000000:
+ div = 2;
+ break;
+ case 125000000:
+ div = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ val = readl_relaxed(PLL8_ENET);
+ val &= ~BM_PLL_ENET_DIV_SELECT;
+ val |= div << BP_PLL_ENET_DIV_SELECT;
+ writel_relaxed(val, PLL8_ENET);
+
+ return 0;
+}
+
+static unsigned long pll_av_get_rate(struct clk *clk)
+{
+ void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ u32 mfn = readl_relaxed(reg + PLL_NUM_OFFSET);
+ u32 mfd = readl_relaxed(reg + PLL_DENOM_OFFSET);
+ u32 div = (readl_relaxed(reg) & BM_PLL_AV_DIV_SELECT) >>
+ BP_PLL_AV_DIV_SELECT;
+
+ return (parent_rate * div) + ((parent_rate / mfd) * mfn);
+}
+
+static int pll_av_set_rate(struct clk *clk, unsigned long rate)
+{
+ void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+ u32 val, div;
+ u32 mfn, mfd = 1000000;
+ s64 temp64;
+
+ if (rate < FREQ_650M || rate > FREQ_1300M)
+ return -EINVAL;
+
+ div = rate / parent_rate;
+ temp64 = (u64) (rate - div * parent_rate);
+ temp64 *= mfd;
+ do_div(temp64, parent_rate);
+ mfn = temp64;
+
+ val = readl_relaxed(reg);
+ val &= ~BM_PLL_AV_DIV_SELECT;
+ val |= div << BP_PLL_AV_DIV_SELECT;
+ writel_relaxed(val, reg);
+ writel_relaxed(mfn, reg + PLL_NUM_OFFSET);
+ writel_relaxed(mfd, reg + PLL_DENOM_OFFSET);
+
+ return 0;
+}
+
+static void __iomem *pll_get_div_reg_bit(struct clk *clk, u32 *bp, u32 *bm)
+{
+ void __iomem *reg;
+
+ if (clk == &pll2_bus) {
+ reg = PLL2_BUS;
+ *bp = BP_PLL_BUS_DIV_SELECT;
+ *bm = BM_PLL_BUS_DIV_SELECT;
+ } else if (clk == &pll3_usb_otg) {
+ reg = PLL3_USB_OTG;
+ *bp = BP_PLL_USB_DIV_SELECT;
+ *bm = BM_PLL_USB_DIV_SELECT;
+ } else if (clk == &pll7_usb_host) {
+ reg = PLL7_USB_HOST;
+ *bp = BP_PLL_USB_DIV_SELECT;
+ *bm = BM_PLL_USB_DIV_SELECT;
+ } else {
+ BUG();
+ }
+
+ return reg;
+}
+
+static unsigned long pll_get_rate(struct clk *clk)
+{
+ void __iomem *reg;
+ u32 div, bp, bm;
+
+ reg = pll_get_div_reg_bit(clk, &bp, &bm);
+ div = (readl_relaxed(reg) & bm) >> bp;
+
+ return (div == 1) ? clk_get_rate(clk->parent) * 22 :
+ clk_get_rate(clk->parent) * 20;
+}
+
+static int pll_set_rate(struct clk *clk, unsigned long rate)
+{
+ void __iomem *reg;
+ u32 val, div, bp, bm;
+
+ if (rate == FREQ_528M)
+ div = 1;
+ else if (rate == FREQ_480M)
+ div = 0;
+ else
+ return -EINVAL;
+
+ reg = pll_get_div_reg_bit(clk, &bp, &bm);
+ val = readl_relaxed(reg);
+ val &= ~bm;
+ val |= div << bp;
+ writel_relaxed(val, reg);
+
+ return 0;
+}
+
+#define pll2_bus_get_rate pll_get_rate
+#define pll2_bus_set_rate pll_set_rate
+#define pll3_usb_otg_get_rate pll_get_rate
+#define pll3_usb_otg_set_rate pll_set_rate
+#define pll7_usb_host_get_rate pll_get_rate
+#define pll7_usb_host_set_rate pll_set_rate
+#define pll4_audio_get_rate pll_av_get_rate
+#define pll4_audio_set_rate pll_av_set_rate
+#define pll5_video_get_rate pll_av_get_rate
+#define pll5_video_set_rate pll_av_set_rate
+#define pll6_mlb_get_rate NULL
+#define pll6_mlb_set_rate NULL
+
+#define DEF_PLL(name) \
+ static struct clk name = { \
+ .enable = pll_enable, \
+ .disable = pll_disable, \
+ .get_rate = name##_get_rate, \
+ .set_rate = name##_set_rate, \
+ .parent = &osc_clk, \
+ }
+
+DEF_PLL(pll1_sys);
+DEF_PLL(pll2_bus);
+DEF_PLL(pll3_usb_otg);
+DEF_PLL(pll4_audio);
+DEF_PLL(pll5_video);
+DEF_PLL(pll6_mlb);
+DEF_PLL(pll7_usb_host);
+DEF_PLL(pll8_enet);
+
+static unsigned long pfd_get_rate(struct clk *clk)
+{
+ u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
+ u32 frac, bp_frac;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ bp_frac = clk->enable_shift - 7;
+ frac = readl_relaxed(clk->enable_reg) >> bp_frac & PFD_FRAC_MASK;
+ do_div(tmp, frac);
+
+ return tmp;
+}
+
+static int pfd_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val, frac, bp_frac;
+ u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ /*
+ * Round up the divider so that we don't set a rate
+ * higher than what is requested
+ */
+ tmp += rate / 2;
+ do_div(tmp, rate);
+ frac = tmp;
+ frac = (frac < 12) ? 12 : frac;
+ frac = (frac > 35) ? 35 : frac;
+
+ /*
+ * The frac field always starts from 7 bits lower
+ * position of enable bit
+ */
+ bp_frac = clk->enable_shift - 7;
+ val = readl_relaxed(clk->enable_reg);
+ val &= ~(PFD_FRAC_MASK << bp_frac);
+ val |= frac << bp_frac;
+ writel_relaxed(val, clk->enable_reg);
+
+ tmp = (u64) clk_get_rate(clk->parent) * 18;
+ do_div(tmp, frac);
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+
+ return 0;
+}
+
+static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 frac;
+ u64 tmp;
+
+ tmp = (u64) clk_get_rate(clk->parent) * 18;
+ tmp += rate / 2;
+ do_div(tmp, rate);
+ frac = tmp;
+ frac = (frac < 12) ? 12 : frac;
+ frac = (frac > 35) ? 35 : frac;
+ tmp = (u64) clk_get_rate(clk->parent) * 18;
+ do_div(tmp, frac);
+
+ return tmp;
+}
+
+static int pfd_enable(struct clk *clk)
+{
+ u32 val;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ val = readl_relaxed(clk->enable_reg);
+ val &= ~(1 << clk->enable_shift);
+ writel_relaxed(val, clk->enable_reg);
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+
+ return 0;
+}
+
+static void pfd_disable(struct clk *clk)
+{
+ u32 val;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ val = readl_relaxed(clk->enable_reg);
+ val |= 1 << clk->enable_shift;
+ writel_relaxed(val, clk->enable_reg);
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+}
+
+#define DEF_PFD(name, er, es, p) \
+ static struct clk name = { \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .enable = pfd_enable, \
+ .disable = pfd_disable, \
+ .get_rate = pfd_get_rate, \
+ .set_rate = pfd_set_rate, \
+ .round_rate = pfd_round_rate, \
+ .parent = p, \
+ }
+
+DEF_PFD(pll2_pfd_352m, PFD_528, PFD0, &pll2_bus);
+DEF_PFD(pll2_pfd_594m, PFD_528, PFD1, &pll2_bus);
+DEF_PFD(pll2_pfd_400m, PFD_528, PFD2, &pll2_bus);
+DEF_PFD(pll3_pfd_720m, PFD_480, PFD0, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_540m, PFD_480, PFD1, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg);
+
+static unsigned long pll2_200m_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk pll2_200m = {
+ .parent = &pll2_pfd_400m,
+ .get_rate = pll2_200m_get_rate,
+};
+
+static unsigned long pll3_120m_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 4;
+}
+
+static struct clk pll3_120m = {
+ .parent = &pll3_usb_otg,
+ .get_rate = pll3_120m_get_rate,
+};
+
+static unsigned long pll3_80m_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 6;
+}
+
+static struct clk pll3_80m = {
+ .parent = &pll3_usb_otg,
+ .get_rate = pll3_80m_get_rate,
+};
+
+static unsigned long pll3_60m_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 8;
+}
+
+static struct clk pll3_60m = {
+ .parent = &pll3_usb_otg,
+ .get_rate = pll3_60m_get_rate,
+};
+
+static int pll1_sw_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 val = readl_relaxed(CCSR);
+
+ if (parent == &pll1_sys) {
+ val &= ~BM_CCSR_PLL1_SW_SEL;
+ val &= ~BM_CCSR_STEP_SEL;
+ } else if (parent == &osc_clk) {
+ val |= BM_CCSR_PLL1_SW_SEL;
+ val &= ~BM_CCSR_STEP_SEL;
+ } else if (parent == &pll2_pfd_400m) {
+ val |= BM_CCSR_PLL1_SW_SEL;
+ val |= BM_CCSR_STEP_SEL;
+ } else {
+ return -EINVAL;
+ }
+
+ writel_relaxed(val, CCSR);
+
+ return 0;
+}
+
+static struct clk pll1_sw_clk = {
+ .parent = &pll1_sys,
+ .set_parent = pll1_sw_clk_set_parent,
+};
+
+static void calc_pred_podf_dividers(u32 div, u32 *pred, u32 *podf)
+{
+ u32 min_pred, temp_pred, old_err, err;
+
+ if (div >= 512) {
+ *pred = 8;
+ *podf = 64;
+ } else if (div >= 8) {
+ min_pred = (div - 1) / 64 + 1;
+ old_err = 8;
+ for (temp_pred = 8; temp_pred >= min_pred; temp_pred--) {
+ err = div % temp_pred;
+ if (err == 0) {
+ *pred = temp_pred;
+ break;
+ }
+ err = temp_pred - err;
+ if (err < old_err) {
+ old_err = err;
+ *pred = temp_pred;
+ }
+ }
+ *podf = (div + *pred - 1) / *pred;
+ } else if (div < 8) {
+ *pred = div;
+ *podf = 1;
+ }
+}
+
+static int _clk_enable(struct clk *clk)
+{
+ u32 reg;
+ reg = readl_relaxed(clk->enable_reg);
+ reg |= 0x3 << clk->enable_shift;
+ writel_relaxed(reg, clk->enable_reg);
+
+ return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+ u32 reg;
+ reg = readl_relaxed(clk->enable_reg);
+ reg &= ~(0x3 << clk->enable_shift);
+ writel_relaxed(reg, clk->enable_reg);
+}
+
+struct divider {
+ struct clk *clk;
+ void __iomem *reg;
+ u32 bp_pred;
+ u32 bm_pred;
+ u32 bp_podf;
+ u32 bm_podf;
+};
+
+#define DEF_CLK_DIV1(d, c, r, b) \
+ static struct divider d = { \
+ .clk = c, \
+ .reg = r, \
+ .bp_podf = BP_##r##_##b##_PODF, \
+ .bm_podf = BM_##r##_##b##_PODF, \
+ }
+
+DEF_CLK_DIV1(arm_div, &arm_clk, CACRR, ARM);
+DEF_CLK_DIV1(ipg_div, &ipg_clk, CBCDR, IPG);
+DEF_CLK_DIV1(ahb_div, &ahb_clk, CBCDR, AHB);
+DEF_CLK_DIV1(axi_div, &axi_clk, CBCDR, AXI);
+DEF_CLK_DIV1(mmdc_ch0_axi_div, &mmdc_ch0_axi_clk, CBCDR, MMDC_CH0_AXI);
+DEF_CLK_DIV1(mmdc_ch1_axi_div, &mmdc_ch1_axi_clk, CBCDR, MMDC_CH1_AXI);
+DEF_CLK_DIV1(periph_clk2_div, &periph_clk2_clk, CBCDR, PERIPH_CLK2);
+DEF_CLK_DIV1(periph2_clk2_div, &periph2_clk2_clk, CBCDR, PERIPH2_CLK2);
+DEF_CLK_DIV1(gpu2d_core_div, &gpu2d_core_clk, CBCMR, GPU2D_CORE);
+DEF_CLK_DIV1(gpu3d_core_div, &gpu3d_core_clk, CBCMR, GPU3D_CORE);
+DEF_CLK_DIV1(gpu3d_shader_div, &gpu3d_shader_clk, CBCMR, GPU3D_SHADER);
+DEF_CLK_DIV1(ipg_perclk_div, &ipg_perclk, CSCMR1, PERCLK);
+DEF_CLK_DIV1(emi_div, &emi_clk, CSCMR1, EMI);
+DEF_CLK_DIV1(emi_slow_div, &emi_slow_clk, CSCMR1, EMI_SLOW);
+DEF_CLK_DIV1(can_div, &can1_clk, CSCMR2, CAN);
+DEF_CLK_DIV1(uart_div, &uart_clk, CSCDR1, UART);
+DEF_CLK_DIV1(usdhc1_div, &usdhc1_clk, CSCDR1, USDHC1);
+DEF_CLK_DIV1(usdhc2_div, &usdhc2_clk, CSCDR1, USDHC2);
+DEF_CLK_DIV1(usdhc3_div, &usdhc3_clk, CSCDR1, USDHC3);
+DEF_CLK_DIV1(usdhc4_div, &usdhc4_clk, CSCDR1, USDHC4);
+DEF_CLK_DIV1(vpu_div, &vpu_clk, CSCDR1, VPU_AXI);
+DEF_CLK_DIV1(hsi_tx_div, &hsi_tx_clk, CDCDR, HSI_TX);
+DEF_CLK_DIV1(ipu1_di0_pre_div, &ipu1_di0_pre_clk, CHSCCDR, IPU1_DI0_PRE);
+DEF_CLK_DIV1(ipu1_di1_pre_div, &ipu1_di1_pre_clk, CHSCCDR, IPU1_DI1_PRE);
+DEF_CLK_DIV1(ipu2_di0_pre_div, &ipu2_di0_pre_clk, CSCDR2, IPU2_DI0_PRE);
+DEF_CLK_DIV1(ipu2_di1_pre_div, &ipu2_di1_pre_clk, CSCDR2, IPU2_DI1_PRE);
+DEF_CLK_DIV1(ipu1_div, &ipu1_clk, CSCDR3, IPU1_HSP);
+DEF_CLK_DIV1(ipu2_div, &ipu2_clk, CSCDR3, IPU2_HSP);
+
+#define DEF_CLK_DIV2(d, c, r, b) \
+ static struct divider d = { \
+ .clk = c, \
+ .reg = r, \
+ .bp_pred = BP_##r##_##b##_PRED, \
+ .bm_pred = BM_##r##_##b##_PRED, \
+ .bp_podf = BP_##r##_##b##_PODF, \
+ .bm_podf = BM_##r##_##b##_PODF, \
+ }
+
+DEF_CLK_DIV2(ssi1_div, &ssi1_clk, CS1CDR, SSI1);
+DEF_CLK_DIV2(ssi3_div, &ssi3_clk, CS1CDR, SSI3);
+DEF_CLK_DIV2(esai_div, &esai_clk, CS1CDR, ESAI);
+DEF_CLK_DIV2(ssi2_div, &ssi2_clk, CS2CDR, SSI2);
+DEF_CLK_DIV2(enfc_div, &enfc_clk, CS2CDR, ENFC);
+DEF_CLK_DIV2(spdif_div, &spdif_clk, CDCDR, SPDIF);
+DEF_CLK_DIV2(asrc_serial_div, &asrc_serial_clk, CDCDR, ASRC_SERIAL);
+
+static struct divider *dividers[] = {
+ &arm_div,
+ &ipg_div,
+ &ahb_div,
+ &axi_div,
+ &mmdc_ch0_axi_div,
+ &mmdc_ch1_axi_div,
+ &periph_clk2_div,
+ &periph2_clk2_div,
+ &gpu2d_core_div,
+ &gpu3d_core_div,
+ &gpu3d_shader_div,
+ &ipg_perclk_div,
+ &emi_div,
+ &emi_slow_div,
+ &can_div,
+ &uart_div,
+ &usdhc1_div,
+ &usdhc2_div,
+ &usdhc3_div,
+ &usdhc4_div,
+ &vpu_div,
+ &hsi_tx_div,
+ &ipu1_di0_pre_div,
+ &ipu1_di1_pre_div,
+ &ipu2_di0_pre_div,
+ &ipu2_di1_pre_div,
+ &ipu1_div,
+ &ipu2_div,
+ &ssi1_div,
+ &ssi3_div,
+ &esai_div,
+ &ssi2_div,
+ &enfc_div,
+ &spdif_div,
+ &asrc_serial_div,
+};
+
+static unsigned long ldb_di_clk_get_rate(struct clk *clk)
+{
+ u32 val = readl_relaxed(CSCMR2);
+
+ val &= (clk == &ldb_di0_clk) ? BM_CSCMR2_LDB_DI0_IPU_DIV :
+ BM_CSCMR2_LDB_DI1_IPU_DIV;
+ if (val)
+ return clk_get_rate(clk->parent) / 7;
+ else
+ return clk_get_rate(clk->parent) * 2 / 7;
+}
+
+static int ldb_di_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ u32 val = readl_relaxed(CSCMR2);
+
+ if (rate * 7 <= parent_rate + parent_rate / 20)
+ val |= BM_CSCMR2_LDB_DI0_IPU_DIV;
+ else
+ val &= ~BM_CSCMR2_LDB_DI0_IPU_DIV;
+
+ writel_relaxed(val, CSCMR2);
+
+ return 0;
+}
+
+static unsigned long ldb_di_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+
+ if (rate * 7 <= parent_rate + parent_rate / 20)
+ return parent_rate / 7;
+ else
+ return 2 * parent_rate / 7;
+}
+
+static unsigned long _clk_get_rate(struct clk *clk)
+{
+ struct divider *d;
+ u32 val, pred, podf;
+ int i, num;
+
+ if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+ return ldb_di_clk_get_rate(clk);
+
+ num = ARRAY_SIZE(dividers);
+ for (i = 0; i < num; i++)
+ if (dividers[i]->clk == clk) {
+ d = dividers[i];
+ break;
+ }
+ if (i == num)
+ return clk_get_rate(clk->parent);
+
+ val = readl_relaxed(d->reg);
+ pred = ((val & d->bm_pred) >> d->bp_pred) + 1;
+ podf = ((val & d->bm_podf) >> d->bp_podf) + 1;
+
+ return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int clk_busy_wait(struct clk *clk)
+{
+ int timeout = 0x100000;
+ u32 bm;
+
+ if (clk == &axi_clk)
+ bm = BM_CDHIPR_AXI_PODF_BUSY;
+ else if (clk == &ahb_clk)
+ bm = BM_CDHIPR_AHB_PODF_BUSY;
+ else if (clk == &mmdc_ch0_axi_clk)
+ bm = BM_CDHIPR_MMDC_CH0_PODF_BUSY;
+ else if (clk == &periph_clk)
+ bm = BM_CDHIPR_PERIPH_SEL_BUSY;
+ else if (clk == &arm_clk)
+ bm = BM_CDHIPR_ARM_PODF_BUSY;
+ else
+ return -EINVAL;
+
+ while ((readl_relaxed(CDHIPR) & bm) && --timeout)
+ cpu_relax();
+
+ if (unlikely(!timeout))
+ return -EBUSY;
+
+ return 0;
+}
+
+static int _clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ struct divider *d;
+ u32 val, div, max_div, pred = 0, podf;
+ int i, num;
+
+ if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+ return ldb_di_clk_set_rate(clk, rate);
+
+ num = ARRAY_SIZE(dividers);
+ for (i = 0; i < num; i++)
+ if (dividers[i]->clk == clk) {
+ d = dividers[i];
+ break;
+ }
+ if (i == num)
+ return -EINVAL;
+
+ max_div = ((d->bm_pred >> d->bp_pred) + 1) *
+ ((d->bm_pred >> d->bp_pred) + 1);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+
+ if ((parent_rate / div != rate) || div > max_div)
+ return -EINVAL;
+
+ if (d->bm_pred) {
+ calc_pred_podf_dividers(div, &pred, &podf);
+ } else {
+ pred = 1;
+ podf = div;
+ }
+
+ val = readl_relaxed(d->reg);
+ val &= ~(d->bm_pred | d->bm_podf);
+ val |= (pred - 1) << d->bp_pred | (podf - 1) << d->bp_podf;
+ writel_relaxed(val, d->reg);
+
+ if (clk == &axi_clk || clk == &ahb_clk ||
+ clk == &mmdc_ch0_axi_clk || clk == &arm_clk)
+ return clk_busy_wait(clk);
+
+ return 0;
+}
+
+static unsigned long _clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+ u32 div_max, pred = 0, podf;
+ struct divider *d;
+ int i, num;
+
+ if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+ return ldb_di_clk_round_rate(clk, rate);
+
+ num = ARRAY_SIZE(dividers);
+ for (i = 0; i < num; i++)
+ if (dividers[i]->clk == clk) {
+ d = dividers[i];
+ break;
+ }
+ if (i == num)
+ return -EINVAL;
+
+ if (div == 0 || parent_rate % rate)
+ div++;
+
+ if (d->bm_pred) {
+ calc_pred_podf_dividers(div, &pred, &podf);
+ div = pred * podf;
+ } else {
+ div_max = (d->bm_podf >> d->bp_podf) + 1;
+ if (div > div_max)
+ div = div_max;
+ }
+
+ return parent_rate / div;
+}
+
+struct multiplexer {
+ struct clk *clk;
+ void __iomem *reg;
+ u32 bp;
+ u32 bm;
+ int pnum;
+ struct clk *parents[];
+};
+
+static struct multiplexer axi_mux = {
+ .clk = &axi_clk,
+ .reg = CBCDR,
+ .bp = BP_CBCDR_AXI_SEL,
+ .bm = BM_CBCDR_AXI_SEL,
+ .parents = {
+ &periph_clk,
+ &pll2_pfd_400m,
+ &pll3_pfd_540m,
+ NULL
+ },
+};
+
+static struct multiplexer periph_mux = {
+ .clk = &periph_clk,
+ .reg = CBCDR,
+ .bp = BP_CBCDR_PERIPH_CLK_SEL,
+ .bm = BM_CBCDR_PERIPH_CLK_SEL,
+ .parents = {
+ &periph_pre_clk,
+ &periph_clk2_clk,
+ NULL
+ },
+};
+
+static struct multiplexer periph_pre_mux = {
+ .clk = &periph_pre_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_PRE_PERIPH_CLK_SEL,
+ .bm = BM_CBCMR_PRE_PERIPH_CLK_SEL,
+ .parents = {
+ &pll2_bus,
+ &pll2_pfd_400m,
+ &pll2_pfd_352m,
+ &pll2_200m,
+ NULL
+ },
+};
+
+static struct multiplexer periph_clk2_mux = {
+ .clk = &periph_clk2_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_PERIPH_CLK2_SEL,
+ .bm = BM_CBCMR_PERIPH_CLK2_SEL,
+ .parents = {
+ &pll3_usb_otg,
+ &osc_clk,
+ NULL
+ },
+};
+
+static struct multiplexer periph2_mux = {
+ .clk = &periph2_clk,
+ .reg = CBCDR,
+ .bp = BP_CBCDR_PERIPH2_CLK_SEL,
+ .bm = BM_CBCDR_PERIPH2_CLK_SEL,
+ .parents = {
+ &periph2_pre_clk,
+ &periph2_clk2_clk,
+ NULL
+ },
+};
+
+static struct multiplexer periph2_pre_mux = {
+ .clk = &periph2_pre_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_PRE_PERIPH2_CLK_SEL,
+ .bm = BM_CBCMR_PRE_PERIPH2_CLK_SEL,
+ .parents = {
+ &pll2_bus,
+ &pll2_pfd_400m,
+ &pll2_pfd_352m,
+ &pll2_200m,
+ NULL
+ },
+};
+
+static struct multiplexer periph2_clk2_mux = {
+ .clk = &periph2_clk2_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_PERIPH2_CLK2_SEL,
+ .bm = BM_CBCMR_PERIPH2_CLK2_SEL,
+ .parents = {
+ &pll3_usb_otg,
+ &osc_clk,
+ NULL
+ },
+};
+
+static struct multiplexer gpu2d_axi_mux = {
+ .clk = &gpu2d_axi_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_GPU2D_AXI_SEL,
+ .bm = BM_CBCMR_GPU2D_AXI_SEL,
+ .parents = {
+ &axi_clk,
+ &ahb_clk,
+ NULL
+ },
+};
+
+static struct multiplexer gpu3d_axi_mux = {
+ .clk = &gpu3d_axi_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_GPU3D_AXI_SEL,
+ .bm = BM_CBCMR_GPU3D_AXI_SEL,
+ .parents = {
+ &axi_clk,
+ &ahb_clk,
+ NULL
+ },
+};
+
+static struct multiplexer gpu3d_core_mux = {
+ .clk = &gpu3d_core_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_GPU3D_CORE_SEL,
+ .bm = BM_CBCMR_GPU3D_CORE_SEL,
+ .parents = {
+ &mmdc_ch0_axi_clk,
+ &pll3_usb_otg,
+ &pll2_pfd_594m,
+ &pll2_pfd_400m,
+ NULL
+ },
+};
+
+static struct multiplexer gpu3d_shader_mux = {
+ .clk = &gpu3d_shader_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_GPU3D_SHADER_SEL,
+ .bm = BM_CBCMR_GPU3D_SHADER_SEL,
+ .parents = {
+ &mmdc_ch0_axi_clk,
+ &pll3_usb_otg,
+ &pll2_pfd_594m,
+ &pll3_pfd_720m,
+ NULL
+ },
+};
+
+static struct multiplexer pcie_axi_mux = {
+ .clk = &pcie_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_PCIE_AXI_SEL,
+ .bm = BM_CBCMR_PCIE_AXI_SEL,
+ .parents = {
+ &axi_clk,
+ &ahb_clk,
+ NULL
+ },
+};
+
+static struct multiplexer vdo_axi_mux = {
+ .clk = &vdo_axi_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_VDO_AXI_SEL,
+ .bm = BM_CBCMR_VDO_AXI_SEL,
+ .parents = {
+ &axi_clk,
+ &ahb_clk,
+ NULL
+ },
+};
+
+static struct multiplexer vpu_axi_mux = {
+ .clk = &vpu_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_VPU_AXI_SEL,
+ .bm = BM_CBCMR_VPU_AXI_SEL,
+ .parents = {
+ &axi_clk,
+ &pll2_pfd_400m,
+ &pll2_pfd_352m,
+ NULL
+ },
+};
+
+static struct multiplexer gpu2d_core_mux = {
+ .clk = &gpu2d_core_clk,
+ .reg = CBCMR,
+ .bp = BP_CBCMR_GPU2D_CORE_SEL,
+ .bm = BM_CBCMR_GPU2D_CORE_SEL,
+ .parents = {
+ &axi_clk,
+ &pll3_usb_otg,
+ &pll2_pfd_352m,
+ &pll2_pfd_400m,
+ NULL
+ },
+};
+
+#define DEF_SSI_MUX(id) \
+ static struct multiplexer ssi##id##_mux = { \
+ .clk = &ssi##id##_clk, \
+ .reg = CSCMR1, \
+ .bp = BP_CSCMR1_SSI##id##_SEL, \
+ .bm = BM_CSCMR1_SSI##id##_SEL, \
+ .parents = { \
+ &pll3_pfd_508m, \
+ &pll3_pfd_454m, \
+ &pll4_audio, \
+ NULL \
+ }, \
+ }
+
+DEF_SSI_MUX(1);
+DEF_SSI_MUX(2);
+DEF_SSI_MUX(3);
+
+#define DEF_USDHC_MUX(id) \
+ static struct multiplexer usdhc##id##_mux = { \
+ .clk = &usdhc##id##_clk, \
+ .reg = CSCMR1, \
+ .bp = BP_CSCMR1_USDHC##id##_SEL, \
+ .bm = BM_CSCMR1_USDHC##id##_SEL, \
+ .parents = { \
+ &pll2_pfd_400m, \
+ &pll2_pfd_352m, \
+ NULL \
+ }, \
+ }
+
+DEF_USDHC_MUX(1);
+DEF_USDHC_MUX(2);
+DEF_USDHC_MUX(3);
+DEF_USDHC_MUX(4);
+
+static struct multiplexer emi_mux = {
+ .clk = &emi_clk,
+ .reg = CSCMR1,
+ .bp = BP_CSCMR1_EMI_SEL,
+ .bm = BM_CSCMR1_EMI_SEL,
+ .parents = {
+ &axi_clk,
+ &pll3_usb_otg,
+ &pll2_pfd_400m,
+ &pll2_pfd_352m,
+ NULL
+ },
+};
+
+static struct multiplexer emi_slow_mux = {
+ .clk = &emi_slow_clk,
+ .reg = CSCMR1,
+ .bp = BP_CSCMR1_EMI_SLOW_SEL,
+ .bm = BM_CSCMR1_EMI_SLOW_SEL,
+ .parents = {
+ &axi_clk,
+ &pll3_usb_otg,
+ &pll2_pfd_400m,
+ &pll2_pfd_352m,
+ NULL
+ },
+};
+
+static struct multiplexer esai_mux = {
+ .clk = &esai_clk,
+ .reg = CSCMR2,
+ .bp = BP_CSCMR2_ESAI_SEL,
+ .bm = BM_CSCMR2_ESAI_SEL,
+ .parents = {
+ &pll4_audio,
+ &pll3_pfd_508m,
+ &pll3_pfd_454m,
+ &pll3_usb_otg,
+ NULL
+ },
+};
+
+#define DEF_LDB_DI_MUX(id) \
+ static struct multiplexer ldb_di##id##_mux = { \
+ .clk = &ldb_di##id##_clk, \
+ .reg = CS2CDR, \
+ .bp = BP_CS2CDR_LDB_DI##id##_SEL, \
+ .bm = BM_CS2CDR_LDB_DI##id##_SEL, \
+ .parents = { \
+ &pll5_video, \
+ &pll2_pfd_352m, \
+ &pll2_pfd_400m, \
+ &pll3_pfd_540m, \
+ &pll3_usb_otg, \
+ NULL \
+ }, \
+ }
+
+DEF_LDB_DI_MUX(0);
+DEF_LDB_DI_MUX(1);
+
+static struct multiplexer enfc_mux = {
+ .clk = &enfc_clk,
+ .reg = CS2CDR,
+ .bp = BP_CS2CDR_ENFC_SEL,
+ .bm = BM_CS2CDR_ENFC_SEL,
+ .parents = {
+ &pll2_pfd_352m,
+ &pll2_bus,
+ &pll3_usb_otg,
+ &pll2_pfd_400m,
+ NULL
+ },
+};
+
+static struct multiplexer spdif_mux = {
+ .clk = &spdif_clk,
+ .reg = CDCDR,
+ .bp = BP_CDCDR_SPDIF_SEL,
+ .bm = BM_CDCDR_SPDIF_SEL,
+ .parents = {
+ &pll4_audio,
+ &pll3_pfd_508m,
+ &pll3_pfd_454m,
+ &pll3_usb_otg,
+ NULL
+ },
+};
+
+static struct multiplexer asrc_serial_mux = {
+ .clk = &asrc_serial_clk,
+ .reg = CDCDR,
+ .bp = BP_CDCDR_ASRC_SERIAL_SEL,
+ .bm = BM_CDCDR_ASRC_SERIAL_SEL,
+ .parents = {
+ &pll4_audio,
+ &pll3_pfd_508m,
+ &pll3_pfd_454m,
+ &pll3_usb_otg,
+ NULL
+ },
+};
+
+static struct multiplexer hsi_tx_mux = {
+ .clk = &hsi_tx_clk,
+ .reg = CDCDR,
+ .bp = BP_CDCDR_HSI_TX_SEL,
+ .bm = BM_CDCDR_HSI_TX_SEL,
+ .parents = {
+ &pll3_120m,
+ &pll2_pfd_400m,
+ NULL
+ },
+};
+
+#define DEF_IPU_DI_PRE_MUX(r, i, d) \
+ static struct multiplexer ipu##i##_di##d##_pre_mux = { \
+ .clk = &ipu##i##_di##d##_pre_clk, \
+ .reg = r, \
+ .bp = BP_##r##_IPU##i##_DI##d##_PRE_SEL, \
+ .bm = BM_##r##_IPU##i##_DI##d##_PRE_SEL, \
+ .parents = { \
+ &mmdc_ch0_axi_clk, \
+ &pll3_usb_otg, \
+ &pll5_video, \
+ &pll2_pfd_352m, \
+ &pll2_pfd_400m, \
+ &pll3_pfd_540m, \
+ NULL \
+ }, \
+ }
+
+DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 0);
+DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 1);
+DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 0);
+DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 1);
+
+#define DEF_IPU_DI_MUX(r, i, d) \
+ static struct multiplexer ipu##i##_di##d##_mux = { \
+ .clk = &ipu##i##_di##d##_clk, \
+ .reg = r, \
+ .bp = BP_##r##_IPU##i##_DI##d##_SEL, \
+ .bm = BM_##r##_IPU##i##_DI##d##_SEL, \
+ .parents = { \
+ &ipu##i##_di##d##_pre_clk, \
+ &dummy_clk, \
+ &dummy_clk, \
+ &ldb_di0_clk, \
+ &ldb_di1_clk, \
+ NULL \
+ }, \
+ }
+
+DEF_IPU_DI_MUX(CHSCCDR, 1, 0);
+DEF_IPU_DI_MUX(CHSCCDR, 1, 1);
+DEF_IPU_DI_MUX(CSCDR2, 2, 0);
+DEF_IPU_DI_MUX(CSCDR2, 2, 1);
+
+#define DEF_IPU_MUX(id) \
+ static struct multiplexer ipu##id##_mux = { \
+ .clk = &ipu##id##_clk, \
+ .reg = CSCDR3, \
+ .bp = BP_CSCDR3_IPU##id##_HSP_SEL, \
+ .bm = BM_CSCDR3_IPU##id##_HSP_SEL, \
+ .parents = { \
+ &mmdc_ch0_axi_clk, \
+ &pll2_pfd_400m, \
+ &pll3_120m, \
+ &pll3_pfd_540m, \
+ NULL \
+ }, \
+ }
+
+DEF_IPU_MUX(1);
+DEF_IPU_MUX(2);
+
+static struct multiplexer *multiplexers[] = {
+ &axi_mux,
+ &periph_mux,
+ &periph_pre_mux,
+ &periph_clk2_mux,
+ &periph2_mux,
+ &periph2_pre_mux,
+ &periph2_clk2_mux,
+ &gpu2d_axi_mux,
+ &gpu3d_axi_mux,
+ &gpu3d_core_mux,
+ &gpu3d_shader_mux,
+ &pcie_axi_mux,
+ &vdo_axi_mux,
+ &vpu_axi_mux,
+ &gpu2d_core_mux,
+ &ssi1_mux,
+ &ssi2_mux,
+ &ssi3_mux,
+ &usdhc1_mux,
+ &usdhc2_mux,
+ &usdhc3_mux,
+ &usdhc4_mux,
+ &emi_mux,
+ &emi_slow_mux,
+ &esai_mux,
+ &ldb_di0_mux,
+ &ldb_di1_mux,
+ &enfc_mux,
+ &spdif_mux,
+ &asrc_serial_mux,
+ &hsi_tx_mux,
+ &ipu1_di0_pre_mux,
+ &ipu1_di0_mux,
+ &ipu1_di1_pre_mux,
+ &ipu1_di1_mux,
+ &ipu2_di0_pre_mux,
+ &ipu2_di0_mux,
+ &ipu2_di1_pre_mux,
+ &ipu2_di1_mux,
+ &ipu1_mux,
+ &ipu2_mux,
+};
+
+static int _clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct multiplexer *m;
+ int i, num;
+ u32 val;
+
+ num = ARRAY_SIZE(multiplexers);
+ for (i = 0; i < num; i++)
+ if (multiplexers[i]->clk == clk) {
+ m = multiplexers[i];
+ break;
+ }
+ if (i == num)
+ return -EINVAL;
+
+ i = 0;
+ while (m->parents[i]) {
+ if (parent == m->parents[i])
+ break;
+ i++;
+ }
+ if (!m->parents[i])
+ return -EINVAL;
+
+ val = readl_relaxed(m->reg);
+ val &= ~m->bm;
+ val |= i << m->bp;
+ writel_relaxed(val, m->reg);
+
+ if (clk == &periph_clk)
+ return clk_busy_wait(clk);
+
+ return 0;
+}
+
+#define DEF_NG_CLK(name, p) \
+ static struct clk name = { \
+ .get_rate = _clk_get_rate, \
+ .set_rate = _clk_set_rate, \
+ .round_rate = _clk_round_rate, \
+ .set_parent = _clk_set_parent, \
+ .parent = p, \
+ }
+
+DEF_NG_CLK(periph_clk2_clk, &osc_clk);
+DEF_NG_CLK(periph_pre_clk, &pll2_bus);
+DEF_NG_CLK(periph_clk, &periph_pre_clk);
+DEF_NG_CLK(periph2_clk2_clk, &osc_clk);
+DEF_NG_CLK(periph2_pre_clk, &pll2_bus);
+DEF_NG_CLK(periph2_clk, &periph2_pre_clk);
+DEF_NG_CLK(axi_clk, &periph_clk);
+DEF_NG_CLK(emi_clk, &axi_clk);
+DEF_NG_CLK(arm_clk, &pll1_sw_clk);
+DEF_NG_CLK(ahb_clk, &periph_clk);
+DEF_NG_CLK(ipg_clk, &ahb_clk);
+DEF_NG_CLK(ipg_perclk, &ipg_clk);
+DEF_NG_CLK(ipu1_di0_pre_clk, &pll3_pfd_540m);
+DEF_NG_CLK(ipu1_di1_pre_clk, &pll3_pfd_540m);
+DEF_NG_CLK(ipu2_di0_pre_clk, &pll3_pfd_540m);
+DEF_NG_CLK(ipu2_di1_pre_clk, &pll3_pfd_540m);
+DEF_NG_CLK(asrc_serial_clk, &pll3_usb_otg);
+
+#define DEF_CLK(name, er, es, p, s) \
+ static struct clk name = { \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .enable = _clk_enable, \
+ .disable = _clk_disable, \
+ .get_rate = _clk_get_rate, \
+ .set_rate = _clk_set_rate, \
+ .round_rate = _clk_round_rate, \
+ .set_parent = _clk_set_parent, \
+ .parent = p, \
+ .secondary = s, \
+ }
+
+DEF_CLK(aips_tz1_clk, CCGR0, CG0, &ahb_clk, NULL);
+DEF_CLK(aips_tz2_clk, CCGR0, CG1, &ahb_clk, NULL);
+DEF_CLK(apbh_dma_clk, CCGR0, CG2, &ahb_clk, NULL);
+DEF_CLK(asrc_clk, CCGR0, CG3, &pll4_audio, NULL);
+DEF_CLK(can1_serial_clk, CCGR0, CG8, &pll3_usb_otg, NULL);
+DEF_CLK(can1_clk, CCGR0, CG7, &pll3_usb_otg, &can1_serial_clk);
+DEF_CLK(can2_serial_clk, CCGR0, CG10, &pll3_usb_otg, NULL);
+DEF_CLK(can2_clk, CCGR0, CG9, &pll3_usb_otg, &can2_serial_clk);
+DEF_CLK(ecspi1_clk, CCGR1, CG0, &pll3_60m, NULL);
+DEF_CLK(ecspi2_clk, CCGR1, CG1, &pll3_60m, NULL);
+DEF_CLK(ecspi3_clk, CCGR1, CG2, &pll3_60m, NULL);
+DEF_CLK(ecspi4_clk, CCGR1, CG3, &pll3_60m, NULL);
+DEF_CLK(ecspi5_clk, CCGR1, CG4, &pll3_60m, NULL);
+DEF_CLK(enet_clk, CCGR1, CG5, &ipg_clk, NULL);
+DEF_CLK(esai_clk, CCGR1, CG8, &pll3_usb_otg, NULL);
+DEF_CLK(gpt_serial_clk, CCGR1, CG11, &ipg_perclk, NULL);
+DEF_CLK(gpt_clk, CCGR1, CG10, &ipg_perclk, &gpt_serial_clk);
+DEF_CLK(gpu2d_core_clk, CCGR1, CG12, &pll2_pfd_352m, &gpu2d_axi_clk);
+DEF_CLK(gpu3d_core_clk, CCGR1, CG13, &pll2_pfd_594m, &gpu3d_axi_clk);
+DEF_CLK(gpu3d_shader_clk, CCGR1, CG13, &pll3_pfd_720m, &gpu3d_axi_clk);
+DEF_CLK(hdmi_iahb_clk, CCGR2, CG0, &ahb_clk, NULL);
+DEF_CLK(hdmi_isfr_clk, CCGR2, CG2, &pll3_pfd_540m, &hdmi_iahb_clk);
+DEF_CLK(i2c1_clk, CCGR2, CG3, &ipg_perclk, NULL);
+DEF_CLK(i2c2_clk, CCGR2, CG4, &ipg_perclk, NULL);
+DEF_CLK(i2c3_clk, CCGR2, CG5, &ipg_perclk, NULL);
+DEF_CLK(iim_clk, CCGR2, CG6, &ipg_clk, NULL);
+DEF_CLK(enfc_clk, CCGR2, CG7, &pll2_pfd_352m, NULL);
+DEF_CLK(ipu1_clk, CCGR3, CG0, &mmdc_ch0_axi_clk, NULL);
+DEF_CLK(ipu1_di0_clk, CCGR3, CG1, &ipu1_di0_pre_clk, NULL);
+DEF_CLK(ipu1_di1_clk, CCGR3, CG2, &ipu1_di1_pre_clk, NULL);
+DEF_CLK(ipu2_clk, CCGR3, CG3, &mmdc_ch0_axi_clk, NULL);
+DEF_CLK(ipu2_di0_clk, CCGR3, CG4, &ipu2_di0_pre_clk, NULL);
+DEF_CLK(ipu2_di1_clk, CCGR3, CG5, &ipu2_di1_pre_clk, NULL);
+DEF_CLK(ldb_di0_clk, CCGR3, CG6, &pll3_pfd_540m, NULL);
+DEF_CLK(ldb_di1_clk, CCGR3, CG7, &pll3_pfd_540m, NULL);
+DEF_CLK(hsi_tx_clk, CCGR3, CG8, &pll2_pfd_400m, NULL);
+DEF_CLK(mlb_clk, CCGR3, CG9, &pll6_mlb, NULL);
+DEF_CLK(mmdc_ch0_ipg_clk, CCGR3, CG12, &ipg_clk, NULL);
+DEF_CLK(mmdc_ch0_axi_clk, CCGR3, CG10, &periph_clk, &mmdc_ch0_ipg_clk);
+DEF_CLK(mmdc_ch1_ipg_clk, CCGR3, CG13, &ipg_clk, NULL);
+DEF_CLK(mmdc_ch1_axi_clk, CCGR3, CG11, &periph2_clk, &mmdc_ch1_ipg_clk);
+DEF_CLK(openvg_axi_clk, CCGR3, CG13, &axi_clk, NULL);
+DEF_CLK(pwm1_clk, CCGR4, CG8, &ipg_perclk, NULL);
+DEF_CLK(pwm2_clk, CCGR4, CG9, &ipg_perclk, NULL);
+DEF_CLK(pwm3_clk, CCGR4, CG10, &ipg_perclk, NULL);
+DEF_CLK(pwm4_clk, CCGR4, CG11, &ipg_perclk, NULL);
+DEF_CLK(gpmi_bch_apb_clk, CCGR4, CG12, &usdhc3_clk, NULL);
+DEF_CLK(gpmi_bch_clk, CCGR4, CG13, &usdhc4_clk, &gpmi_bch_apb_clk);
+DEF_CLK(gpmi_apb_clk, CCGR4, CG15, &usdhc3_clk, &gpmi_bch_clk);
+DEF_CLK(gpmi_io_clk, CCGR4, CG14, &enfc_clk, &gpmi_apb_clk);
+DEF_CLK(sdma_clk, CCGR5, CG3, &ahb_clk, NULL);
+DEF_CLK(spba_clk, CCGR5, CG6, &ipg_clk, NULL);
+DEF_CLK(spdif_clk, CCGR5, CG7, &pll3_usb_otg, &spba_clk);
+DEF_CLK(ssi1_clk, CCGR5, CG9, &pll3_pfd_508m, NULL);
+DEF_CLK(ssi2_clk, CCGR5, CG10, &pll3_pfd_508m, NULL);
+DEF_CLK(ssi3_clk, CCGR5, CG11, &pll3_pfd_508m, NULL);
+DEF_CLK(uart_serial_clk, CCGR5, CG13, &pll3_usb_otg, NULL);
+DEF_CLK(uart_clk, CCGR5, CG12, &pll3_80m, &uart_serial_clk);
+DEF_CLK(usboh3_clk, CCGR6, CG0, &ipg_clk, NULL);
+DEF_CLK(usdhc1_clk, CCGR6, CG1, &pll2_pfd_400m, NULL);
+DEF_CLK(usdhc2_clk, CCGR6, CG2, &pll2_pfd_400m, NULL);
+DEF_CLK(usdhc3_clk, CCGR6, CG3, &pll2_pfd_400m, NULL);
+DEF_CLK(usdhc4_clk, CCGR6, CG4, &pll2_pfd_400m, NULL);
+DEF_CLK(emi_slow_clk, CCGR6, CG5, &axi_clk, NULL);
+DEF_CLK(vdo_axi_clk, CCGR6, CG6, &axi_clk, NULL);
+DEF_CLK(vpu_clk, CCGR6, CG7, &axi_clk, NULL);
+
+static int pcie_clk_enable(struct clk *clk)
+{
+ u32 val;
+
+ val = readl_relaxed(PLL8_ENET);
+ val |= BM_PLL_ENET_EN_PCIE;
+ writel_relaxed(val, PLL8_ENET);
+
+ return _clk_enable(clk);
+}
+
+static void pcie_clk_disable(struct clk *clk)
+{
+ u32 val;
+
+ _clk_disable(clk);
+
+ val = readl_relaxed(PLL8_ENET);
+ val &= BM_PLL_ENET_EN_PCIE;
+ writel_relaxed(val, PLL8_ENET);
+}
+
+static struct clk pcie_clk = {
+ .enable_reg = CCGR4,
+ .enable_shift = CG0,
+ .enable = pcie_clk_enable,
+ .disable = pcie_clk_disable,
+ .set_parent = _clk_set_parent,
+ .parent = &axi_clk,
+ .secondary = &pll8_enet,
+};
+
+static int sata_clk_enable(struct clk *clk)
+{
+ u32 val;
+
+ val = readl_relaxed(PLL8_ENET);
+ val |= BM_PLL_ENET_EN_SATA;
+ writel_relaxed(val, PLL8_ENET);
+
+ return _clk_enable(clk);
+}
+
+static void sata_clk_disable(struct clk *clk)
+{
+ u32 val;
+
+ _clk_disable(clk);
+
+ val = readl_relaxed(PLL8_ENET);
+ val &= BM_PLL_ENET_EN_SATA;
+ writel_relaxed(val, PLL8_ENET);
+}
+
+static struct clk sata_clk = {
+ .enable_reg = CCGR5,
+ .enable_shift = CG2,
+ .enable = sata_clk_enable,
+ .disable = sata_clk_disable,
+ .parent = &ipg_clk,
+ .secondary = &pll8_enet,
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+ { \
+ .dev_id = d, \
+ .con_id = n, \
+ .clk = &c, \
+ }
+
+static struct clk_lookup lookups[] = {
+ _REGISTER_CLOCK("2020000.uart", NULL, uart_clk),
+ _REGISTER_CLOCK("21e8000.uart", NULL, uart_clk),
+ _REGISTER_CLOCK("21ec000.uart", NULL, uart_clk),
+ _REGISTER_CLOCK("21f0000.uart", NULL, uart_clk),
+ _REGISTER_CLOCK("21f4000.uart", NULL, uart_clk),
+ _REGISTER_CLOCK("2188000.enet", NULL, enet_clk),
+ _REGISTER_CLOCK("2190000.usdhc", NULL, usdhc1_clk),
+ _REGISTER_CLOCK("2194000.usdhc", NULL, usdhc2_clk),
+ _REGISTER_CLOCK("2198000.usdhc", NULL, usdhc3_clk),
+ _REGISTER_CLOCK("219c000.usdhc", NULL, usdhc4_clk),
+ _REGISTER_CLOCK("21a0000.i2c", NULL, i2c1_clk),
+ _REGISTER_CLOCK("21a4000.i2c", NULL, i2c2_clk),
+ _REGISTER_CLOCK("21a8000.i2c", NULL, i2c3_clk),
+ _REGISTER_CLOCK("2008000.ecspi", NULL, ecspi1_clk),
+ _REGISTER_CLOCK("200c000.ecspi", NULL, ecspi2_clk),
+ _REGISTER_CLOCK("2010000.ecspi", NULL, ecspi3_clk),
+ _REGISTER_CLOCK("2014000.ecspi", NULL, ecspi4_clk),
+ _REGISTER_CLOCK("2018000.ecspi", NULL, ecspi5_clk),
+ _REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk),
+ _REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk),
+ _REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk),
+ _REGISTER_CLOCK(NULL, "ckih", ckih_clk),
+ _REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk),
+ _REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk),
+ _REGISTER_CLOCK(NULL, "aips_tz2_clk", aips_tz2_clk),
+ _REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk),
+ _REGISTER_CLOCK(NULL, "can2_clk", can2_clk),
+ _REGISTER_CLOCK(NULL, "hdmi_isfr_clk", hdmi_isfr_clk),
+ _REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
+ _REGISTER_CLOCK(NULL, "mlb_clk", mlb_clk),
+ _REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk),
+ _REGISTER_CLOCK(NULL, "pwm1_clk", pwm1_clk),
+ _REGISTER_CLOCK(NULL, "pwm2_clk", pwm2_clk),
+ _REGISTER_CLOCK(NULL, "pwm3_clk", pwm3_clk),
+ _REGISTER_CLOCK(NULL, "pwm4_clk", pwm4_clk),
+ _REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk),
+ _REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk),
+ _REGISTER_CLOCK(NULL, "sata_clk", sata_clk),
+};
+
+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
+{
+ u32 val = readl_relaxed(CLPCR);
+
+ val &= ~BM_CLPCR_LPM;
+ switch (mode) {
+ case WAIT_CLOCKED:
+ break;
+ case WAIT_UNCLOCKED:
+ val |= 0x1 << BP_CLPCR_LPM;
+ break;
+ case STOP_POWER_ON:
+ val |= 0x2 << BP_CLPCR_LPM;
+ break;
+ case WAIT_UNCLOCKED_POWER_OFF:
+ val |= 0x1 << BP_CLPCR_LPM;
+ val &= ~BM_CLPCR_VSTBY;
+ val &= ~BM_CLPCR_SBYOS;
+ val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ break;
+ case STOP_POWER_OFF:
+ val |= 0x2 << BP_CLPCR_LPM;
+ val |= 0x3 << BP_CLPCR_STBY_COUNT;
+ val |= BM_CLPCR_VSTBY;
+ val |= BM_CLPCR_SBYOS;
+ val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ break;
+ default:
+ return -EINVAL;
+ }
+ writel_relaxed(val, CLPCR);
+
+ return 0;
+}
+
+static struct map_desc imx6q_clock_desc[] = {
+ imx_map_entry(MX6Q, CCM, MT_DEVICE),
+ imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
+};
+
+int __init mx6q_clocks_init(void)
+{
+ struct device_node *np;
+ void __iomem *base;
+ int i, irq;
+
+ iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
+
+ /* 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-ckil"))
+ external_low_reference = rate;
+ else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+ external_high_reference = rate;
+ else if (of_device_is_compatible(np, "fsl,imx-osc"))
+ oscillator_reference = rate;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
+
+ /* only keep necessary clocks on */
+ writel_relaxed(0x3 << CG0 | 0x3 << CG1 | 0x3 << CG2, CCGR0);
+ writel_relaxed(0x3 << CG8 | 0x3 << CG9 | 0x3 << CG10, CCGR2);
+ writel_relaxed(0x3 << CG10 | 0x3 << CG12, CCGR3);
+ writel_relaxed(0x3 << CG4 | 0x3 << CG6 | 0x3 << CG7, CCGR4);
+ writel_relaxed(0x3 << CG0, CCGR5);
+ writel_relaxed(0, CCGR6);
+ writel_relaxed(0, CCGR7);
+
+ clk_enable(&uart_clk);
+ clk_enable(&mmdc_ch0_axi_clk);
+
+ clk_set_rate(&pll4_audio, FREQ_650M);
+ clk_set_rate(&pll5_video, FREQ_650M);
+ clk_set_parent(&ipu1_di0_clk, &ipu1_di0_pre_clk);
+ clk_set_parent(&ipu1_di0_pre_clk, &pll5_video);
+ clk_set_parent(&gpu3d_shader_clk, &pll2_pfd_594m);
+ clk_set_rate(&gpu3d_shader_clk, FREQ_594M);
+ clk_set_parent(&gpu3d_core_clk, &mmdc_ch0_axi_clk);
+ clk_set_rate(&gpu3d_core_clk, FREQ_528M);
+ clk_set_parent(&asrc_serial_clk, &pll3_usb_otg);
+ clk_set_rate(&asrc_serial_clk, 1500000);
+ clk_set_rate(&enfc_clk, 11000000);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
+ base = of_iomap(np, 0);
+ WARN_ON(!base);
+ irq = irq_of_parse_and_map(np, 0);
+ mxc_timer_init(&gpt_clk, base, irq);
+
+ return 0;
+}
diff --git a/arch/arm/mach-imx/cpu-imx25.c b/arch/arm/mach-imx/cpu-imx25.c
new file mode 100644
index 000000000000..6914bcbf84e4
--- /dev/null
+++ b/arch/arm/mach-imx/cpu-imx25.c
@@ -0,0 +1,41 @@
+/*
+ * MX25 CPU type detection
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/iim.h>
+
+static int mx25_cpu_rev = -1;
+
+static int mx25_read_cpu_rev(void)
+{
+ u32 rev;
+
+ rev = __raw_readl(MX25_IO_ADDRESS(MX25_IIM_BASE_ADDR + MXC_IIMSREV));
+ switch (rev) {
+ case 0x00:
+ return IMX_CHIP_REVISION_1_0;
+ case 0x01:
+ return IMX_CHIP_REVISION_1_1;
+ default:
+ return IMX_CHIP_REVISION_UNKNOWN;
+ }
+}
+
+int mx25_revision(void)
+{
+ if (mx25_cpu_rev == -1)
+ mx25_cpu_rev = mx25_read_cpu_rev();
+
+ return mx25_cpu_rev;
+}
+EXPORT_SYMBOL(mx25_revision);
diff --git a/arch/arm/mach-imx/cpu-imx27.c b/arch/arm/mach-imx/cpu-imx27.c
index 3b117be37bd2..ff38e1505f67 100644
--- a/arch/arm/mach-imx/cpu-imx27.c
+++ b/arch/arm/mach-imx/cpu-imx27.c
@@ -26,12 +26,12 @@
#include <mach/hardware.h>
-static int cpu_silicon_rev = -1;
-static int cpu_partnumber;
+static int mx27_cpu_rev = -1;
+static int mx27_cpu_partnumber;
#define SYS_CHIP_ID 0x00 /* The offset of CHIP ID register */
-static void query_silicon_parameter(void)
+static int mx27_read_cpu_rev(void)
{
u32 val;
/*
@@ -42,20 +42,18 @@ static void query_silicon_parameter(void)
val = __raw_readl(MX27_IO_ADDRESS(MX27_SYSCTRL_BASE_ADDR
+ SYS_CHIP_ID));
+ mx27_cpu_partnumber = (int)((val >> 12) & 0xFFFF);
+
switch (val >> 28) {
case 0:
- cpu_silicon_rev = IMX_CHIP_REVISION_1_0;
- break;
+ return IMX_CHIP_REVISION_1_0;
case 1:
- cpu_silicon_rev = IMX_CHIP_REVISION_2_0;
- break;
+ return IMX_CHIP_REVISION_2_0;
case 2:
- cpu_silicon_rev = IMX_CHIP_REVISION_2_1;
- break;
+ return IMX_CHIP_REVISION_2_1;
default:
- cpu_silicon_rev = IMX_CHIP_REVISION_UNKNOWN;
+ return IMX_CHIP_REVISION_UNKNOWN;
}
- cpu_partnumber = (int)((val >> 12) & 0xFFFF);
}
/*
@@ -65,12 +63,12 @@ static void query_silicon_parameter(void)
*/
int mx27_revision(void)
{
- if (cpu_silicon_rev == -1)
- query_silicon_parameter();
+ if (mx27_cpu_rev == -1)
+ mx27_cpu_rev = mx27_read_cpu_rev();
- if (cpu_partnumber != 0x8821)
+ if (mx27_cpu_partnumber != 0x8821)
return -EINVAL;
- return cpu_silicon_rev;
+ return mx27_cpu_rev;
}
EXPORT_SYMBOL(mx27_revision);
diff --git a/arch/arm/mach-imx/cpu-imx31.c b/arch/arm/mach-imx/cpu-imx31.c
index a3780700a882..3f2345f0cdaf 100644
--- a/arch/arm/mach-imx/cpu-imx31.c
+++ b/arch/arm/mach-imx/cpu-imx31.c
@@ -13,45 +13,50 @@
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/iim.h>
+#include <mach/common.h>
-unsigned int mx31_cpu_rev;
-EXPORT_SYMBOL(mx31_cpu_rev);
+static int mx31_cpu_rev = -1;
static struct {
u8 srev;
const char *name;
- const char *v;
unsigned int rev;
-} mx31_cpu_type[] __initdata = {
- { .srev = 0x00, .name = "i.MX31(L)", .v = "1.0", .rev = IMX_CHIP_REVISION_1_0 },
- { .srev = 0x10, .name = "i.MX31", .v = "1.1", .rev = IMX_CHIP_REVISION_1_1 },
- { .srev = 0x11, .name = "i.MX31L", .v = "1.1", .rev = IMX_CHIP_REVISION_1_1 },
- { .srev = 0x12, .name = "i.MX31", .v = "1.15", .rev = IMX_CHIP_REVISION_1_1 },
- { .srev = 0x13, .name = "i.MX31L", .v = "1.15", .rev = IMX_CHIP_REVISION_1_1 },
- { .srev = 0x14, .name = "i.MX31", .v = "1.2", .rev = IMX_CHIP_REVISION_1_2 },
- { .srev = 0x15, .name = "i.MX31L", .v = "1.2", .rev = IMX_CHIP_REVISION_1_2 },
- { .srev = 0x28, .name = "i.MX31", .v = "2.0", .rev = IMX_CHIP_REVISION_2_0 },
- { .srev = 0x29, .name = "i.MX31L", .v = "2.0", .rev = IMX_CHIP_REVISION_2_0 },
+} mx31_cpu_type[] = {
+ { .srev = 0x00, .name = "i.MX31(L)", .rev = IMX_CHIP_REVISION_1_0 },
+ { .srev = 0x10, .name = "i.MX31", .rev = IMX_CHIP_REVISION_1_1 },
+ { .srev = 0x11, .name = "i.MX31L", .rev = IMX_CHIP_REVISION_1_1 },
+ { .srev = 0x12, .name = "i.MX31", .rev = IMX_CHIP_REVISION_1_1 },
+ { .srev = 0x13, .name = "i.MX31L", .rev = IMX_CHIP_REVISION_1_1 },
+ { .srev = 0x14, .name = "i.MX31", .rev = IMX_CHIP_REVISION_1_2 },
+ { .srev = 0x15, .name = "i.MX31L", .rev = IMX_CHIP_REVISION_1_2 },
+ { .srev = 0x28, .name = "i.MX31", .rev = IMX_CHIP_REVISION_2_0 },
+ { .srev = 0x29, .name = "i.MX31L", .rev = IMX_CHIP_REVISION_2_0 },
};
-void __init mx31_read_cpu_rev(void)
+static int mx31_read_cpu_rev(void)
{
u32 i, srev;
/* read SREV register from IIM module */
srev = __raw_readl(MX31_IO_ADDRESS(MX31_IIM_BASE_ADDR + MXC_IIMSREV));
+ srev &= 0xff;
for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
if (srev == mx31_cpu_type[i].srev) {
- printk(KERN_INFO
- "CPU identified as %s, silicon rev %s\n",
- mx31_cpu_type[i].name, mx31_cpu_type[i].v);
-
- mx31_cpu_rev = mx31_cpu_type[i].rev;
- return;
+ imx_print_silicon_rev(mx31_cpu_type[i].name,
+ mx31_cpu_type[i].rev);
+ return mx31_cpu_type[i].rev;
}
- mx31_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
+ imx_print_silicon_rev("i.MX31", IMX_CHIP_REVISION_UNKNOWN);
+ return IMX_CHIP_REVISION_UNKNOWN;
+}
+
+int mx31_revision(void)
+{
+ if (mx31_cpu_rev == -1)
+ mx31_cpu_rev = mx31_read_cpu_rev();
- printk(KERN_WARNING "Unknown CPU identifier. srev = %02x\n", srev);
+ return mx31_cpu_rev;
}
+EXPORT_SYMBOL(mx31_revision);
diff --git a/arch/arm/mach-imx/cpu-imx35.c b/arch/arm/mach-imx/cpu-imx35.c
index 6637cd819ecb..846e46eb8cbf 100644
--- a/arch/arm/mach-imx/cpu-imx35.c
+++ b/arch/arm/mach-imx/cpu-imx35.c
@@ -13,32 +13,30 @@
#include <mach/hardware.h>
#include <mach/iim.h>
-unsigned int mx35_cpu_rev;
-EXPORT_SYMBOL(mx35_cpu_rev);
+static int mx35_cpu_rev = -1;
-void __init mx35_read_cpu_rev(void)
+static int mx35_read_cpu_rev(void)
{
u32 rev;
- char *srev;
rev = __raw_readl(MX35_IO_ADDRESS(MX35_IIM_BASE_ADDR + MXC_IIMSREV));
switch (rev) {
case 0x00:
- mx35_cpu_rev = IMX_CHIP_REVISION_1_0;
- srev = "1.0";
- break;
+ return IMX_CHIP_REVISION_1_0;
case 0x10:
- mx35_cpu_rev = IMX_CHIP_REVISION_2_0;
- srev = "2.0";
- break;
+ return IMX_CHIP_REVISION_2_0;
case 0x11:
- mx35_cpu_rev = IMX_CHIP_REVISION_2_1;
- srev = "2.1";
- break;
+ return IMX_CHIP_REVISION_2_1;
default:
- mx35_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
- srev = "unknown";
+ return IMX_CHIP_REVISION_UNKNOWN;
}
+}
+
+int mx35_revision(void)
+{
+ if (mx35_cpu_rev == -1)
+ mx35_cpu_rev = mx35_read_cpu_rev();
- printk(KERN_INFO "CPU identified as i.MX35, silicon rev %s\n", srev);
+ return mx35_cpu_rev;
}
+EXPORT_SYMBOL(mx35_revision);
diff --git a/arch/arm/mach-imx/devices-imx27.h b/arch/arm/mach-imx/devices-imx27.h
index 7f97a3cdd41d..2f727d7c380c 100644
--- a/arch/arm/mach-imx/devices-imx27.h
+++ b/arch/arm/mach-imx/devices-imx27.h
@@ -76,3 +76,7 @@ extern const struct imx_spi_imx_data imx27_cspi_data[];
#define imx27_add_spi_imx0(pdata) imx27_add_cspi(0, pdata)
#define imx27_add_spi_imx1(pdata) imx27_add_cspi(1, pdata)
#define imx27_add_spi_imx2(pdata) imx27_add_cspi(2, pdata)
+
+extern const struct imx_pata_imx_data imx27_pata_imx_data;
+#define imx27_add_pata_imx() \
+ imx_add_pata_imx(&imx27_pata_imx_data)
diff --git a/arch/arm/mach-imx/devices-imx31.h b/arch/arm/mach-imx/devices-imx31.h
index dbe940d9c53a..488e241a6db6 100644
--- a/arch/arm/mach-imx/devices-imx31.h
+++ b/arch/arm/mach-imx/devices-imx31.h
@@ -78,3 +78,7 @@ extern const struct imx_spi_imx_data imx31_cspi_data[];
#define imx31_add_spi_imx0(pdata) imx31_add_cspi(0, pdata)
#define imx31_add_spi_imx1(pdata) imx31_add_cspi(1, pdata)
#define imx31_add_spi_imx2(pdata) imx31_add_cspi(2, pdata)
+
+extern const struct imx_pata_imx_data imx31_pata_imx_data;
+#define imx31_add_pata_imx() \
+ imx_add_pata_imx(&imx31_pata_imx_data)
diff --git a/arch/arm/mach-imx/devices-imx35.h b/arch/arm/mach-imx/devices-imx35.h
index 234cbd3c18af..7b99ef0bb501 100644
--- a/arch/arm/mach-imx/devices-imx35.h
+++ b/arch/arm/mach-imx/devices-imx35.h
@@ -81,3 +81,7 @@ extern const struct imx_spi_imx_data imx35_cspi_data[];
imx_add_spi_imx(&imx35_cspi_data[id], pdata)
#define imx35_add_spi_imx0(pdata) imx35_add_cspi(0, pdata)
#define imx35_add_spi_imx1(pdata) imx35_add_cspi(1, pdata)
+
+extern const struct imx_pata_imx_data imx35_pata_imx_data;
+#define imx35_add_pata_imx() \
+ imx_add_pata_imx(&imx35_pata_imx_data)
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
new file mode 100644
index 000000000000..e1537f9e45b8
--- /dev/null
+++ b/arch/arm/mach-imx/gpc.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/hardware/gic.h>
+
+#define GPC_IMR1 0x008
+#define GPC_PGC_CPU_PDN 0x2a0
+
+#define IMR_NUM 4
+
+static void __iomem *gpc_base;
+static u32 gpc_wake_irqs[IMR_NUM];
+static u32 gpc_saved_imrs[IMR_NUM];
+
+void imx_gpc_pre_suspend(void)
+{
+ void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+ int i;
+
+ /* Tell GPC to power off ARM core when suspend */
+ writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+
+ for (i = 0; i < IMR_NUM; i++) {
+ gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
+ writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4);
+ }
+}
+
+void imx_gpc_post_resume(void)
+{
+ void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+ int i;
+
+ /* Keep ARM core powered on for other low-power modes */
+ writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+
+ for (i = 0; i < IMR_NUM; i++)
+ writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
+}
+
+static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ unsigned int idx = d->irq / 32 - 1;
+ u32 mask;
+
+ /* Sanity check for SPI irq */
+ if (d->irq < 32)
+ return -EINVAL;
+
+ mask = 1 << d->irq % 32;
+ gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
+ gpc_wake_irqs[idx] & ~mask;
+
+ return 0;
+}
+
+static void imx_gpc_irq_unmask(struct irq_data *d)
+{
+ void __iomem *reg;
+ u32 val;
+
+ /* Sanity check for SPI irq */
+ if (d->irq < 32)
+ return;
+
+ reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+ val = readl_relaxed(reg);
+ val &= ~(1 << d->irq % 32);
+ writel_relaxed(val, reg);
+}
+
+static void imx_gpc_irq_mask(struct irq_data *d)
+{
+ void __iomem *reg;
+ u32 val;
+
+ /* Sanity check for SPI irq */
+ if (d->irq < 32)
+ return;
+
+ reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+ val = readl_relaxed(reg);
+ val |= 1 << (d->irq % 32);
+ writel_relaxed(val, reg);
+}
+
+void __init imx_gpc_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+ gpc_base = of_iomap(np, 0);
+ WARN_ON(!gpc_base);
+
+ /* Register GPC as the secondary interrupt controller behind GIC */
+ gic_arch_extn.irq_mask = imx_gpc_irq_mask;
+ gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
+ gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
+}
diff --git a/arch/arm/mach-imx/head-v7.S b/arch/arm/mach-imx/head-v7.S
new file mode 100644
index 000000000000..6229efbc70cb
--- /dev/null
+++ b/arch/arm/mach-imx/head-v7.S
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
+
+ .section ".text.head", "ax"
+ __CPUINIT
+
+/*
+ * The secondary kernel init calls v7_flush_dcache_all before it enables
+ * the L1; however, the L1 comes out of reset in an undefined state, so
+ * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
+ * of cache lines with uninitialized data and uninitialized tags to get
+ * written out to memory, which does really unpleasant things to the main
+ * processor. We fix this by performing an invalidate, rather than a
+ * clean + invalidate, before jumping into the kernel.
+ *
+ * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
+ * to be called for both secondary cores startup and primary core resume
+ * procedures. Ideally, it should be moved into arch/arm/mm/cache-v7.S.
+ */
+ENTRY(v7_invalidate_l1)
+ mov r0, #0
+ mcr p15, 2, r0, c0, c0, 0
+ mrc p15, 1, r0, c0, c0, 0
+
+ ldr r1, =0x7fff
+ and r2, r1, r0, lsr #13
+
+ ldr r1, =0x3ff
+
+ and r3, r1, r0, lsr #3 @ NumWays - 1
+ add r2, r2, #1 @ NumSets
+
+ and r0, r0, #0x7
+ add r0, r0, #4 @ SetShift
+
+ clz r1, r3 @ WayShift
+ add r4, r3, #1 @ NumWays
+1: sub r2, r2, #1 @ NumSets--
+ mov r3, r4 @ Temp = NumWays
+2: subs r3, r3, #1 @ Temp--
+ mov r5, r3, lsl r1
+ mov r6, r2, lsl r0
+ orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+ mcr p15, 0, r5, c7, c6, 2
+ bgt 2b
+ cmp r2, #0
+ bgt 1b
+ dsb
+ isb
+ mov pc, lr
+ENDPROC(v7_invalidate_l1)
+
+#ifdef CONFIG_SMP
+ENTRY(v7_secondary_startup)
+ bl v7_invalidate_l1
+ b secondary_startup
+ENDPROC(v7_secondary_startup)
+#endif
+
+/*
+ * The following code is located into the .data section. This is to
+ * allow phys_l2x0_saved_regs to be accessed with a relative load
+ * as we are running on physical address here.
+ */
+ .data
+ .align
+
+ .macro pl310_resume
+ ldr r2, phys_l2x0_saved_regs
+ ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0
+ ldr r1, [r2, #L2X0_R_AUX_CTRL] @ get aux_ctrl value
+ str r1, [r0, #L2X0_AUX_CTRL] @ restore aux_ctrl
+ mov r1, #0x1
+ str r1, [r0, #L2X0_CTRL] @ re-enable L2
+ .endm
+
+ENTRY(v7_cpu_resume)
+ bl v7_invalidate_l1
+ pl310_resume
+ b cpu_resume
+ENDPROC(v7_cpu_resume)
+
+ .globl phys_l2x0_saved_regs
+phys_l2x0_saved_regs:
+ .long 0
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
new file mode 100644
index 000000000000..89493abd497c
--- /dev/null
+++ b/arch/arm/mach-imx/hotplug.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/errno.h>
+#include <asm/cacheflush.h>
+#include <mach/common.h>
+
+int platform_cpu_kill(unsigned int cpu)
+{
+ return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+ flush_cache_all();
+ imx_enable_cpu(cpu, false);
+ cpu_do_idle();
+
+ /* We should never return from idle */
+ panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+ /*
+ * we don't allow CPU 0 to be shutdown (it is still too special
+ * e.g. clock tick interrupts)
+ */
+ return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-imx/iomux-imx31.c b/arch/arm/mach-imx/iomux-imx31.c
index cf8f8099ebd7..82bd4403b450 100644
--- a/arch/arm/mach-imx/iomux-imx31.c
+++ b/arch/arm/mach-imx/iomux-imx31.c
@@ -17,13 +17,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
-
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <mach/hardware.h>
-#include <mach/gpio.h>
#include <mach/iomux-mx3.h>
/*
diff --git a/arch/arm/mach-imx/lluart.c b/arch/arm/mach-imx/lluart.c
new file mode 100644
index 000000000000..d4ab6f29a766
--- /dev/null
+++ b/arch/arm/mach-imx/lluart.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+#include <mach/hardware.h>
+
+static struct map_desc imx_lluart_desc = {
+#ifdef CONFIG_DEBUG_IMX6Q_UART
+ .virtual = MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
+ .pfn = __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
+ .length = MX6Q_UART4_SIZE,
+ .type = MT_DEVICE,
+#endif
+};
+
+void __init imx_lluart_map_io(void)
+{
+ if (imx_lluart_desc.virtual)
+ iotable_init(&imx_lluart_desc, 1);
+}
diff --git a/arch/arm/mach-imx/localtimer.c b/arch/arm/mach-imx/localtimer.c
new file mode 100644
index 000000000000..3a163515d41f
--- /dev/null
+++ b/arch/arm/mach-imx/localtimer.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/smp_twd.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+ if (!twd_base) {
+ twd_base = of_iomap(np, 0);
+ WARN_ON(!twd_base);
+ }
+ evt->irq = irq_of_parse_and_map(np, 0);
+ twd_timer_setup(evt);
+
+ return 0;
+}
diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c
index a404c89485ca..1e486e67dabb 100644
--- a/arch/arm/mach-imx/mach-apf9328.c
+++ b/arch/arm/mach-imx/mach-apf9328.c
@@ -136,6 +136,7 @@ MACHINE_START(APF9328, "Armadeus APF9328")
.map_io = mx1_map_io,
.init_early = imx1_init_early,
.init_irq = mx1_init_irq,
+ .handle_irq = imx1_handle_irq,
.timer = &apf9328_timer,
.init_machine = apf9328_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index ede2710f8b76..c9a9cf67755e 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -314,25 +314,19 @@ static struct mtd_partition armadillo5x0_nor_flash_partitions[] = {
},
};
-static struct physmap_flash_data armadillo5x0_nor_flash_pdata = {
+static const struct physmap_flash_data
+ armadillo5x0_nor_flash_pdata __initconst = {
.width = 2,
.parts = armadillo5x0_nor_flash_partitions,
.nr_parts = ARRAY_SIZE(armadillo5x0_nor_flash_partitions),
};
-static struct resource armadillo5x0_nor_flash_resource = {
+static const struct resource armadillo5x0_nor_flash_resource __initconst = {
.flags = IORESOURCE_MEM,
.start = MX31_CS0_BASE_ADDR,
.end = MX31_CS0_BASE_ADDR + SZ_64M - 1,
};
-static struct platform_device armadillo5x0_nor_flash = {
- .name = "physmap-flash",
- .id = -1,
- .num_resources = 1,
- .resource = &armadillo5x0_nor_flash_resource,
-};
-
/*
* FB support
*/
@@ -514,8 +508,10 @@ static void __init armadillo5x0_init(void)
imx31_add_mx3_sdc_fb(&mx3fb_pdata);
/* Register NOR Flash */
- mxc_register_device(&armadillo5x0_nor_flash,
- &armadillo5x0_nor_flash_pdata);
+ platform_device_register_resndata(NULL, "physmap-flash", -1,
+ &armadillo5x0_nor_flash_resource, 1,
+ &armadillo5x0_nor_flash_pdata,
+ sizeof(armadillo5x0_nor_flash_pdata));
/* Register NAND Flash */
imx31_add_mxc_nand(&armadillo5x0_nand_board_info);
@@ -558,10 +554,11 @@ static struct sys_timer armadillo5x0_timer = {
MACHINE_START(ARMADILLO5X0, "Armadillo-500")
/* Maintainer: Alberto Panizzo */
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx31_map_io,
.init_early = imx31_init_early,
.init_irq = mx31_init_irq,
+ .handle_irq = imx31_handle_irq,
.timer = &armadillo5x0_timer,
.init_machine = armadillo5x0_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-bug.c b/arch/arm/mach-imx/mach-bug.c
index f49470553bdf..313f62ddc1ef 100644
--- a/arch/arm/mach-imx/mach-bug.c
+++ b/arch/arm/mach-imx/mach-bug.c
@@ -62,6 +62,7 @@ MACHINE_START(BUG, "BugLabs BUGBase")
.map_io = mx31_map_io,
.init_early = imx31_init_early,
.init_irq = mx31_init_irq,
+ .handle_irq = imx31_handle_irq,
.timer = &bug_timer,
.init_machine = bug_board_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index f851fe903687..edb373052576 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -311,10 +311,11 @@ static struct sys_timer eukrea_cpuimx27_timer = {
};
MACHINE_START(EUKREA_CPUIMX27, "EUKREA CPUIMX27")
- .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx27_map_io,
.init_early = imx27_init_early,
.init_irq = mx27_init_irq,
+ .handle_irq = imx27_handle_irq,
.timer = &eukrea_cpuimx27_timer,
.init_machine = eukrea_cpuimx27_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c
index 4bd083ba9af2..66af2e8f7e57 100644
--- a/arch/arm/mach-imx/mach-cpuimx35.c
+++ b/arch/arm/mach-imx/mach-cpuimx35.c
@@ -66,7 +66,7 @@ static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
I2C_BOARD_INFO("tsc2007", 0x48),
.type = "tsc2007",
.platform_data = &tsc2007_info,
- .irq = gpio_to_irq(TSC2007_IRQGPIO),
+ .irq = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
},
};
@@ -194,10 +194,11 @@ struct sys_timer eukrea_cpuimx35_timer = {
MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35")
/* Maintainer: Eukrea Electromatique */
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx35_map_io,
.init_early = imx35_init_early,
.init_irq = mx35_init_irq,
+ .handle_irq = imx35_handle_irq,
.timer = &eukrea_cpuimx35_timer,
.init_machine = eukrea_cpuimx35_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
index 2442d5da883d..ab8fbcc472b5 100644
--- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
+++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
@@ -163,10 +163,11 @@ static struct sys_timer eukrea_cpuimx25_timer = {
MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25")
/* Maintainer: Eukrea Electromatique */
- .boot_params = MX25_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx25_map_io,
.init_early = imx25_init_early,
.init_irq = mx25_init_irq,
+ .handle_irq = imx25_handle_irq,
.timer = &eukrea_cpuimx25_timer,
.init_machine = eukrea_cpuimx25_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index 6778f8193bc6..38eb9e45110b 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -275,10 +275,11 @@ static struct sys_timer visstrim_m10_timer = {
};
MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
- .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx27_map_io,
.init_early = imx27_init_early,
.init_irq = mx27_init_irq,
+ .handle_irq = imx27_handle_irq,
.timer = &visstrim_m10_timer,
.init_machine = visstrim_m10_board_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c
index 272f793e9247..7052155d0557 100644
--- a/arch/arm/mach-imx/mach-imx27ipcam.c
+++ b/arch/arm/mach-imx/mach-imx27ipcam.c
@@ -71,10 +71,11 @@ static struct sys_timer mx27ipcam_timer = {
MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
/* maintainer: Freescale Semiconductor, Inc. */
- .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx27_map_io,
.init_early = imx27_init_early,
.init_irq = mx27_init_irq,
+ .handle_irq = imx27_handle_irq,
.timer = &mx27ipcam_timer,
.init_machine = mx27ipcam_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
index d81a769fe895..8d6a63521f17 100644
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ b/arch/arm/mach-imx/mach-imx27lite.c
@@ -77,10 +77,11 @@ static struct sys_timer mx27lite_timer = {
};
MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
- .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx27_map_io,
.init_early = imx27_init_early,
.init_irq = mx27_init_irq,
+ .handle_irq = imx27_handle_irq,
.timer = &mx27lite_timer,
.init_machine = mx27lite_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
new file mode 100644
index 000000000000..8bf5fa349484
--- /dev/null
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+static void __init imx6q_init_machine(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+ imx6q_pm_init();
+}
+
+static void __init imx6q_map_io(void)
+{
+ imx_lluart_map_io();
+ imx_scu_map_io();
+}
+
+static void __init imx6q_gpio_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS -
+ 32 * 7; /* imx6q gets 7 gpio ports */
+
+ irq_domain_add_simple(np, gpio_irq_base);
+ gpio_irq_base += 32;
+}
+
+static const struct of_device_id imx6q_irq_match[] __initconst = {
+ { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+ { .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, },
+ { /* sentinel */ }
+};
+
+static void __init imx6q_init_irq(void)
+{
+ l2x0_of_init(0, ~0UL);
+ imx_src_init();
+ imx_gpc_init();
+ of_irq_init(imx6q_irq_match);
+}
+
+static void __init imx6q_timer_init(void)
+{
+ mx6q_clocks_init();
+}
+
+static struct sys_timer imx6q_timer = {
+ .init = imx6q_timer_init,
+};
+
+static const char *imx6q_dt_compat[] __initdata = {
+ "fsl,imx6q-sabreauto",
+ NULL,
+};
+
+DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
+ .map_io = imx6q_map_io,
+ .init_irq = imx6q_init_irq,
+ .handle_irq = imx6q_handle_irq,
+ .timer = &imx6q_timer,
+ .init_machine = imx6q_init_machine,
+ .dt_compat = imx6q_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c
index e472a1d88058..5f37f89e40fa 100644
--- a/arch/arm/mach-imx/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c
@@ -36,6 +36,7 @@
#include <mach/clock.h>
#include <mach/common.h>
+#include <mach/hardware.h>
#include <mach/iomux-mx3.h>
#include "devices-imx31.h"
@@ -271,10 +272,11 @@ static struct sys_timer kzm_timer = {
};
MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = kzm_map_io,
.init_early = imx31_init_early,
.init_irq = mx31_init_irq,
+ .handle_irq = imx31_handle_irq,
.timer = &kzm_timer,
.init_machine = kzm_board_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 5cd8bee46960..fc49785e7340 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -68,23 +68,16 @@ static const struct imxuart_platform_data uart1_pdata __initconst = {
* Physmap flash
*/
-static struct physmap_flash_data mx1ads_flash_data = {
+static const struct physmap_flash_data mx1ads_flash_data __initconst = {
.width = 4, /* bankwidth in bytes */
};
-static struct resource flash_resource = {
+static const struct resource flash_resource __initconst = {
.start = MX1_CS0_PHYS,
.end = MX1_CS0_PHYS + SZ_32M - 1,
.flags = IORESOURCE_MEM,
};
-static struct platform_device flash_device = {
- .name = "physmap-flash",
- .id = 0,
- .resource = &flash_resource,
- .num_resources = 1,
-};
-
/*
* I2C
*/
@@ -125,7 +118,9 @@ static void __init mx1ads_init(void)
imx1_add_imx_uart1(&uart1_pdata);
/* Physmap flash */
- mxc_register_device(&flash_device, &mx1ads_flash_data);
+ platform_device_register_resndata(NULL, "physmap-flash", 0,
+ &flash_resource, 1,
+ &mx1ads_flash_data, sizeof(mx1ads_flash_data));
/* I2C */
i2c_register_board_info(0, mx1ads_i2c_devices,
@@ -145,19 +140,21 @@ struct sys_timer mx1ads_timer = {
MACHINE_START(MX1ADS, "Freescale MX1ADS")
/* Maintainer: Sascha Hauer, Pengutronix */
- .boot_params = MX1_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx1_map_io,
.init_early = imx1_init_early,
.init_irq = mx1_init_irq,
+ .handle_irq = imx1_handle_irq,
.timer = &mx1ads_timer,
.init_machine = mx1ads_init,
MACHINE_END
MACHINE_START(MXLADS, "Freescale MXLADS")
- .boot_params = MX1_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx1_map_io,
.init_early = imx1_init_early,
.init_irq = mx1_init_irq,
+ .handle_irq = imx1_handle_irq,
.timer = &mx1ads_timer,
.init_machine = mx1ads_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index d389ecf9b5a8..25f84028d055 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -305,10 +305,11 @@ static struct sys_timer mx21ads_timer = {
MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
/* maintainer: Freescale Semiconductor, Inc. */
- .boot_params = MX21_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx21ads_map_io,
.init_early = imx21_init_early,
.init_irq = mx21_init_irq,
+ .handle_irq = imx21_handle_irq,
.timer = &mx21ads_timer,
.init_machine = mx21ads_board_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index 7f66a91df361..88dccf122243 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -43,6 +43,8 @@
#include "devices-imx25.h"
+#define MX25PDK_CAN_PWDN IMX_GPIO_NR(4, 6)
+
static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
@@ -108,6 +110,11 @@ static iomux_v3_cfg_t mx25pdk_pads[] = {
/* I2C1 */
MX25_PAD_I2C1_CLK__I2C1_CLK,
MX25_PAD_I2C1_DAT__I2C1_DAT,
+
+ /* CAN1 */
+ MX25_PAD_GPIO_A__CAN1_TX,
+ MX25_PAD_GPIO_B__CAN1_RX,
+ MX25_PAD_D14__GPIO_4_6, /* CAN_PWDN */
};
static const struct fec_platform_data mx25_fec_pdata __initconst = {
@@ -240,6 +247,9 @@ static void __init mx25pdk_init(void)
imx25_add_sdhci_esdhc_imx(0, &mx25pdk_esdhc_pdata);
imx25_add_imx_i2c0(&mx25_3ds_i2c0_data);
+
+ gpio_request_one(MX25PDK_CAN_PWDN, GPIOF_OUT_INIT_LOW, "can-pwdn");
+ imx25_add_flexcan0(NULL);
}
static void __init mx25pdk_timer_init(void)
@@ -253,10 +263,11 @@ static struct sys_timer mx25pdk_timer = {
MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
/* Maintainer: Freescale Semiconductor, Inc. */
- .boot_params = MX25_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx25_map_io,
.init_early = imx25_init_early,
.init_irq = mx25_init_irq,
+ .handle_irq = imx25_handle_irq,
.timer = &mx25pdk_timer,
.init_machine = mx25pdk_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 535bfebb20cf..ba232d79fa81 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -241,7 +241,7 @@ static struct regulator_init_data gpo_init = {
};
static struct regulator_consumer_supply vmmc1_consumers[] = {
- REGULATOR_SUPPLY("lcd_2v8", NULL),
+ REGULATOR_SUPPLY("vcore", "spi0.0"),
};
static struct regulator_init_data vmmc1_init = {
@@ -257,7 +257,7 @@ static struct regulator_init_data vmmc1_init = {
};
static struct regulator_consumer_supply vgen_consumers[] = {
- REGULATOR_SUPPLY("vdd_lcdio", NULL),
+ REGULATOR_SUPPLY("vdd", "spi0.0"),
};
static struct regulator_init_data vgen_init = {
@@ -347,8 +347,6 @@ static const struct imx_fb_platform_data mx27_3ds_fb_data __initconst = {
static struct l4f00242t03_pdata mx27_3ds_lcd_pdata = {
.reset_gpio = LCD_RESET,
.data_enable_gpio = LCD_ENABLE,
- .core_supply = "lcd_2v8",
- .io_supply = "vdd_lcdio",
};
static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
@@ -358,7 +356,7 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
.bus_num = 1,
.chip_select = 0, /* SS0 */
.platform_data = &mc13783_pdata,
- .irq = gpio_to_irq(PMIC_INT),
+ .irq = IMX_GPIO_TO_IRQ(PMIC_INT),
.mode = SPI_CS_HIGH,
}, {
.modalias = "l4f00242t03",
@@ -420,10 +418,11 @@ static struct sys_timer mx27pdk_timer = {
MACHINE_START(MX27_3DS, "Freescale MX27PDK")
/* maintainer: Freescale Semiconductor, Inc. */
- .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx27_map_io,
.init_early = imx27_init_early,
.init_irq = mx27_init_irq,
+ .handle_irq = imx27_handle_irq,
.timer = &mx27pdk_timer,
.init_machine = mx27pdk_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index fc26ed71b9ed..74dd5731eb61 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -13,7 +13,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
@@ -27,7 +27,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <mach/iomux-mx27.h>
#include "devices-imx27.h"
@@ -345,10 +344,11 @@ static void __init mx27ads_map_io(void)
MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
/* maintainer: Freescale Semiconductor, Inc. */
- .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx27ads_map_io,
.init_early = imx27_init_early,
.init_irq = mx27_init_irq,
+ .handle_irq = imx27_handle_irq,
.timer = &mx27ads_timer,
.init_machine = mx27ads_board_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 7d078b4320c2..b8c54b840185 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -285,8 +285,6 @@ static struct mx3fb_platform_data mx3fb_pdata __initdata = {
static struct l4f00242t03_pdata mx31_3ds_l4f00242t03_pdata = {
.reset_gpio = IOMUX_TO_GPIO(MX31_PIN_LCS1),
.data_enable_gpio = IOMUX_TO_GPIO(MX31_PIN_SER_RS),
- .core_supply = "lcd_2v8",
- .io_supply = "vdd_lcdio",
};
/*
@@ -411,7 +409,7 @@ static struct regulator_init_data vmmc2_init = {
};
static struct regulator_consumer_supply vmmc1_consumers[] = {
- REGULATOR_SUPPLY("lcd_2v8", NULL),
+ REGULATOR_SUPPLY("vcore", "spi0.0"),
REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
};
@@ -428,7 +426,7 @@ static struct regulator_init_data vmmc1_init = {
};
static struct regulator_consumer_supply vgen_consumers[] = {
- REGULATOR_SUPPLY("vdd_lcdio", NULL),
+ REGULATOR_SUPPLY("vdd", "spi0.0"),
};
static struct regulator_init_data vgen_init = {
@@ -542,7 +540,7 @@ static const struct mxc_nand_platform_data
mx31_3ds_nand_board_info __initconst = {
.width = 1,
.hw_ecc = 1,
-#ifdef MACH_MX31_3DS_MXC_NAND_USE_BBT
+#ifdef CONFIG_MACH_MX31_3DS_MXC_NAND_USE_BBT
.flash_bbt = 1,
#endif
};
@@ -764,10 +762,11 @@ static void __init mx31_3ds_reserve(void)
MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
/* Maintainer: Freescale Semiconductor, Inc. */
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx31_map_io,
.init_early = imx31_init_early,
.init_irq = mx31_init_irq,
+ .handle_irq = imx31_handle_irq,
.timer = &mx31_3ds_timer,
.init_machine = mx31_3ds_init,
.reserve = mx31_3ds_reserve,
diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c
index 29ca8907a780..9cc1a49053bb 100644
--- a/arch/arm/mach-imx/mach-mx31ads.c
+++ b/arch/arm/mach-imx/mach-mx31ads.c
@@ -535,10 +535,11 @@ static struct sys_timer mx31ads_timer = {
MACHINE_START(MX31ADS, "Freescale MX31ADS")
/* Maintainer: Freescale Semiconductor, Inc. */
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx31ads_map_io,
.init_early = imx31_init_early,
.init_irq = mx31ads_init_irq,
+ .handle_irq = imx31_handle_irq,
.timer = &mx31ads_timer,
.init_machine = mx31ads_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c
index 126913ad106a..5defd8e70fc4 100644
--- a/arch/arm/mach-imx/mach-mx31lilly.c
+++ b/arch/arm/mach-imx/mach-mx31lilly.c
@@ -295,10 +295,11 @@ static struct sys_timer mx31lilly_timer = {
};
MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx31_map_io,
.init_early = imx31_init_early,
.init_irq = mx31_init_irq,
+ .handle_irq = imx31_handle_irq,
.timer = &mx31lilly_timer,
.init_machine = mx31lilly_board_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index 0ea0bdaf74c3..05f1c71ba409 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -279,10 +279,11 @@ struct sys_timer mx31lite_timer = {
MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
/* Maintainer: Freescale Semiconductor, Inc. */
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx31lite_map_io,
.init_early = imx31_init_early,
.init_irq = mx31_init_irq,
+ .handle_irq = imx31_handle_irq,
.timer = &mx31lite_timer,
.init_machine = mx31lite_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index f7e302d718b4..07034f44466a 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -28,6 +28,9 @@
#include <linux/spi/spi.h>
#include <linux/types.h>
#include <linux/memblock.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
#include <linux/input.h>
#include <linux/usb/otg.h>
@@ -497,6 +500,18 @@ err:
}
+static void mx31moboard_poweroff(void)
+{
+ struct clk *clk = clk_get_sys("imx2-wdt.0", NULL);
+
+ if (!IS_ERR(clk))
+ clk_enable(clk);
+
+ mxc_iomux_mode(MX31_PIN_WATCHDOG_RST__WATCHDOG_RST);
+
+ __raw_writew(1 << 6 | 1 << 2, MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
+}
+
static int mx31moboard_baseboard;
core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
@@ -535,6 +550,8 @@ static void __init mx31moboard_init(void)
moboard_usbh2_init();
+ pm_power_off = mx31moboard_poweroff;
+
switch (mx31moboard_baseboard) {
case MX31NOBOARD:
break;
@@ -574,11 +591,12 @@ static void __init mx31moboard_reserve(void)
MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
/* Maintainer: Valentin Longchamp, EPFL Mobots group */
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.reserve = mx31moboard_reserve,
.map_io = mx31_map_io,
.init_early = imx31_init_early,
.init_irq = mx31_init_irq,
+ .handle_irq = imx31_handle_irq,
.timer = &mx31moboard_timer,
.init_machine = mx31moboard_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c
index b3b9bd8ac2a3..7a462025a0f7 100644
--- a/arch/arm/mach-imx/mach-mx35_3ds.c
+++ b/arch/arm/mach-imx/mach-mx35_3ds.c
@@ -217,10 +217,11 @@ struct sys_timer mx35pdk_timer = {
MACHINE_START(MX35_3DS, "Freescale MX35PDK")
/* Maintainer: Freescale Semiconductor, Inc */
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx35_map_io,
.init_early = imx35_init_early,
.init_irq = mx35_init_irq,
+ .handle_irq = imx35_handle_irq,
.timer = &mx35pdk_timer,
.init_machine = mx35_3ds_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c
index c85876fed663..125c19643b0f 100644
--- a/arch/arm/mach-imx/mach-mxt_td60.c
+++ b/arch/arm/mach-imx/mach-mxt_td60.c
@@ -267,10 +267,11 @@ static struct sys_timer mxt_td60_timer = {
MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
/* maintainer: Maxtrack Industrial */
- .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx27_map_io,
.init_early = imx27_init_early,
.init_irq = mx27_init_irq,
+ .handle_irq = imx27_handle_irq,
.timer = &mxt_td60_timer,
.init_machine = mxt_td60_board_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index 71083aa16038..26072f4b02e3 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -435,10 +435,11 @@ static struct sys_timer pca100_timer = {
};
MACHINE_START(PCA100, "phyCARD-i.MX27")
- .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx27_map_io,
.init_early = imx27_init_early,
.init_irq = mx27_init_irq,
+ .handle_irq = imx27_handle_irq,
.init_machine = pca100_init,
.timer = &pca100_timer,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index f45b7cd72c8a..efd6b536ef6a 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -688,11 +688,12 @@ static void __init pcm037_reserve(void)
MACHINE_START(PCM037, "Phytec Phycore pcm037")
/* Maintainer: Pengutronix */
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.reserve = pcm037_reserve,
.map_io = mx31_map_io,
.init_early = imx31_init_early,
.init_irq = mx31_init_irq,
+ .handle_irq = imx31_handle_irq,
.timer = &pcm037_timer,
.init_machine = pcm037_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 5ef49de326a2..a17e9c7dfca0 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -176,7 +176,9 @@ static struct platform_device *platform_devices[] __initdata = {
* setup other stuffs to access the sram. */
static void __init pcm038_init_sram(void)
{
- mx27_setup_weimcs(1, 0x0000d843, 0x22252521, 0x22220a00);
+ __raw_writel(0x0000d843, MX27_IO_ADDRESS(MX27_WEIM_CSCRxU(1)));
+ __raw_writel(0x22252521, MX27_IO_ADDRESS(MX27_WEIM_CSCRxL(1)));
+ __raw_writel(0x22220a00, MX27_IO_ADDRESS(MX27_WEIM_CSCRxA(1)));
}
static const struct imxi2c_platform_data pcm038_i2c1_data __initconst = {
@@ -348,10 +350,11 @@ static struct sys_timer pcm038_timer = {
};
MACHINE_START(PCM038, "phyCORE-i.MX27")
- .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx27_map_io,
.init_early = imx27_init_early,
.init_irq = mx27_init_irq,
+ .handle_irq = imx27_handle_irq,
.timer = &pcm038_timer,
.init_machine = pcm038_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 660ec3e80cf8..7366c2ae3ea5 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -418,10 +418,11 @@ struct sys_timer pcm043_timer = {
MACHINE_START(PCM043, "Phytec Phycore pcm043")
/* Maintainer: Pengutronix */
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx35_map_io,
.init_early = imx35_init_early,
.init_irq = mx35_init_irq,
+ .handle_irq = imx35_handle_irq,
.timer = &pcm043_timer,
.init_machine = pcm043_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c
index 3626f486498a..4ff5faf102a8 100644
--- a/arch/arm/mach-imx/mach-qong.c
+++ b/arch/arm/mach-imx/mach-qong.c
@@ -190,7 +190,10 @@ static struct platform_device qong_nand_device = {
static void __init qong_init_nand_mtd(void)
{
/* init CS */
- mx31_setup_weimcs(3, 0x00004f00, 0x20013b31, 0x00020800);
+ __raw_writel(0x00004f00, MX31_IO_ADDRESS(MX31_WEIM_CSCRxU(3)));
+ __raw_writel(0x20013b31, MX31_IO_ADDRESS(MX31_WEIM_CSCRxL(3)));
+ __raw_writel(0x00020800, MX31_IO_ADDRESS(MX31_WEIM_CSCRxA(3)));
+
mxc_iomux_set_gpr(MUX_SDCTL_CSD1_SEL, true);
/* enable pin */
@@ -249,6 +252,7 @@ static void __init qong_init(void)
mxc_init_imx_uart();
qong_init_nor_mtd();
qong_init_fpga();
+ imx31_add_imx2_wdt(NULL);
}
static void __init qong_timer_init(void)
@@ -262,10 +266,11 @@ static struct sys_timer qong_timer = {
MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
/* Maintainer: DENX Software Engineering GmbH */
- .boot_params = MX3x_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx31_map_io,
.init_early = imx31_init_early,
.init_irq = mx31_init_irq,
+ .handle_irq = imx31_handle_irq,
.timer = &qong_timer,
.init_machine = qong_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c
index db2d60470e15..bb6e5b25d8d0 100644
--- a/arch/arm/mach-imx/mach-scb9328.c
+++ b/arch/arm/mach-imx/mach-scb9328.c
@@ -137,10 +137,11 @@ static struct sys_timer scb9328_timer = {
MACHINE_START(SCB9328, "Synertronixx scb9328")
/* Sascha Hauer */
- .boot_params = 0x08000100,
+ .atag_offset = 100,
.map_io = mx1_map_io,
.init_early = imx1_init_early,
.init_irq = mx1_init_irq,
+ .handle_irq = imx1_handle_irq,
.timer = &scb9328_timer,
.init_machine = scb9328_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c
index 7d8e012a6335..69092458f2d9 100644
--- a/arch/arm/mach-imx/mach-vpr200.c
+++ b/arch/arm/mach-imx/mach-vpr200.c
@@ -162,7 +162,7 @@ static struct i2c_board_info vpr200_i2c_devices[] = {
}, {
I2C_BOARD_INFO("mc13892", 0x08),
.platform_data = &vpr200_pmic,
- .irq = gpio_to_irq(GPIO_PMIC_INT),
+ .irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT),
}
};
@@ -319,6 +319,7 @@ MACHINE_START(VPR200, "VPR200")
.map_io = mx35_map_io,
.init_early = imx35_init_early,
.init_irq = mx35_init_irq,
+ .handle_irq = imx35_handle_irq,
.timer = &vpr200_timer,
.init_machine = vpr200_board_init,
MACHINE_END
diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c
new file mode 100644
index 000000000000..9f0e82ec3398
--- /dev/null
+++ b/arch/arm/mach-imx/mm-imx3.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 1999,2000 Arm Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ * Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * - add MX31 specific definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/err.h>
+
+#include <asm/pgtable.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/map.h>
+
+#include <mach/common.h>
+#include <mach/devices-common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-v3.h>
+#include <mach/irqs.h>
+
+static void imx3_idle(void)
+{
+ unsigned long reg = 0;
+ __asm__ __volatile__(
+ /* disable I and D cache */
+ "mrc p15, 0, %0, c1, c0, 0\n"
+ "bic %0, %0, #0x00001000\n"
+ "bic %0, %0, #0x00000004\n"
+ "mcr p15, 0, %0, c1, c0, 0\n"
+ /* invalidate I cache */
+ "mov %0, #0\n"
+ "mcr p15, 0, %0, c7, c5, 0\n"
+ /* clear and invalidate D cache */
+ "mov %0, #0\n"
+ "mcr p15, 0, %0, c7, c14, 0\n"
+ /* WFI */
+ "mov %0, #0\n"
+ "mcr p15, 0, %0, c7, c0, 4\n"
+ "nop\n" "nop\n" "nop\n" "nop\n"
+ "nop\n" "nop\n" "nop\n"
+ /* enable I and D cache */
+ "mrc p15, 0, %0, c1, c0, 0\n"
+ "orr %0, %0, #0x00001000\n"
+ "orr %0, %0, #0x00000004\n"
+ "mcr p15, 0, %0, c1, c0, 0\n"
+ : "=r" (reg));
+}
+
+static void __iomem *imx3_ioremap(unsigned long phys_addr, size_t size,
+ unsigned int mtype)
+{
+ if (mtype == MT_DEVICE) {
+ /*
+ * Access all peripherals below 0x80000000 as nonshared device
+ * on mx3, but leave l2cc alone. Otherwise cache corruptions
+ * can occur.
+ */
+ if (phys_addr < 0x80000000 &&
+ !addr_in_module(phys_addr, MX3x_L2CC))
+ mtype = MT_DEVICE_NONSHARED;
+ }
+
+ return __arm_ioremap(phys_addr, size, mtype);
+}
+
+void imx3_init_l2x0(void)
+{
+ void __iomem *l2x0_base;
+ void __iomem *clkctl_base;
+
+/*
+ * First of all, we must repair broken chip settings. There are some
+ * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
+ * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
+ * Workaraound is to setup the correct register setting prior enabling the
+ * L2 cache. This should not hurt already working CPUs, as they are using the
+ * same value.
+ */
+#define L2_MEM_VAL 0x10
+
+ clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
+ if (clkctl_base != NULL) {
+ writel(0x00000515, clkctl_base + L2_MEM_VAL);
+ iounmap(clkctl_base);
+ } else {
+ pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
+ }
+
+ l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
+ if (IS_ERR(l2x0_base)) {
+ printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
+ PTR_ERR(l2x0_base));
+ return;
+ }
+
+ l2x0_init(l2x0_base, 0x00030024, 0x00000000);
+}
+
+static struct map_desc mx31_io_desc[] __initdata = {
+ imx_map_entry(MX31, X_MEMC, MT_DEVICE),
+ imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx31_map_io(void)
+{
+ iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
+}
+
+static struct map_desc mx35_io_desc[] __initdata = {
+ imx_map_entry(MX35, X_MEMC, MT_DEVICE),
+ imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
+ imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+void __init mx35_map_io(void)
+{
+ iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
+}
+
+void __init imx31_init_early(void)
+{
+ mxc_set_cpu_type(MXC_CPU_MX31);
+ mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
+ imx_idle = imx3_idle;
+ imx_ioremap = imx3_ioremap;
+}
+
+void __init imx35_init_early(void)
+{
+ mxc_set_cpu_type(MXC_CPU_MX35);
+ mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
+ mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
+ imx_idle = imx3_idle;
+ imx_ioremap = imx3_ioremap;
+}
+
+void __init mx31_init_irq(void)
+{
+ mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
+}
+
+void __init mx35_init_irq(void)
+{
+ mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
+ .per_2_per_addr = 1677,
+};
+
+static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
+ .ap_2_ap_addr = 423,
+ .ap_2_bp_addr = 829,
+ .bp_2_ap_addr = 1029,
+};
+
+static struct sdma_platform_data imx31_sdma_pdata __initdata = {
+ .fw_name = "sdma-imx31-to2.bin",
+ .script_addrs = &imx31_to2_sdma_script,
+};
+
+void __init imx31_soc_init(void)
+{
+ int to_version = mx31_revision() >> 4;
+
+ imx3_init_l2x0();
+
+ mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
+ mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
+ mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
+
+ if (to_version == 1) {
+ strncpy(imx31_sdma_pdata.fw_name, "sdma-imx31-to1.bin",
+ strlen(imx31_sdma_pdata.fw_name));
+ imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
+ }
+
+ imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
+}
+
+static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
+ .ap_2_ap_addr = 642,
+ .uart_2_mcu_addr = 817,
+ .mcu_2_app_addr = 747,
+ .uartsh_2_mcu_addr = 1183,
+ .per_2_shp_addr = 1033,
+ .mcu_2_shp_addr = 961,
+ .ata_2_mcu_addr = 1333,
+ .mcu_2_ata_addr = 1252,
+ .app_2_mcu_addr = 683,
+ .shp_2_per_addr = 1111,
+ .shp_2_mcu_addr = 892,
+};
+
+static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
+ .ap_2_ap_addr = 729,
+ .uart_2_mcu_addr = 904,
+ .per_2_app_addr = 1597,
+ .mcu_2_app_addr = 834,
+ .uartsh_2_mcu_addr = 1270,
+ .per_2_shp_addr = 1120,
+ .mcu_2_shp_addr = 1048,
+ .ata_2_mcu_addr = 1429,
+ .mcu_2_ata_addr = 1339,
+ .app_2_per_addr = 1531,
+ .app_2_mcu_addr = 770,
+ .shp_2_per_addr = 1198,
+ .shp_2_mcu_addr = 979,
+};
+
+static struct sdma_platform_data imx35_sdma_pdata __initdata = {
+ .fw_name = "sdma-imx35-to2.bin",
+ .script_addrs = &imx35_to2_sdma_script,
+};
+
+void __init imx35_soc_init(void)
+{
+ int to_version = mx35_revision() >> 4;
+
+ imx3_init_l2x0();
+
+ /* i.mx35 has the i.mx31 type gpio */
+ mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
+ mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
+ mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
+
+ if (to_version == 1) {
+ strncpy(imx35_sdma_pdata.fw_name, "sdma-imx35-to1.bin",
+ strlen(imx35_sdma_pdata.fw_name));
+ imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
+ }
+
+ imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
+}
diff --git a/arch/arm/mach-imx/mm-imx31.c b/arch/arm/mach-imx/mm-imx31.c
deleted file mode 100644
index b7c55e7db000..000000000000
--- a/arch/arm/mach-imx/mm-imx31.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 1999,2000 Arm Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd
- * Copyright (C) 2002 Shane Nay (shane@minirl.com)
- * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * - add MX31 specific definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/err.h>
-
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-static struct map_desc mx31_io_desc[] __initdata = {
- imx_map_entry(MX31, X_MEMC, MT_DEVICE),
- imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
- imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
- imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
- imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx31_map_io(void)
-{
- iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
-}
-
-void __init imx31_init_early(void)
-{
- mxc_set_cpu_type(MXC_CPU_MX31);
- mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
-}
-
-void __init mx31_init_irq(void)
-{
- mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
- .per_2_per_addr = 1677,
-};
-
-static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
- .ap_2_ap_addr = 423,
- .ap_2_bp_addr = 829,
- .bp_2_ap_addr = 1029,
-};
-
-static struct sdma_platform_data imx31_sdma_pdata __initdata = {
- .fw_name = "sdma-imx31-to2.bin",
- .script_addrs = &imx31_to2_sdma_script,
-};
-
-void __init imx31_soc_init(void)
-{
- int to_version = mx31_revision() >> 4;
-
- mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
- mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
- mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
-
- if (to_version == 1) {
- strncpy(imx31_sdma_pdata.fw_name, "sdma-imx31-to1.bin",
- strlen(imx31_sdma_pdata.fw_name));
- imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
- }
-
- imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
-}
diff --git a/arch/arm/mach-imx/mm-imx35.c b/arch/arm/mach-imx/mm-imx35.c
deleted file mode 100644
index f49bac7a1ede..000000000000
--- a/arch/arm/mach-imx/mm-imx35.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 1999,2000 Arm Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd
- * Copyright (C) 2002 Shane Nay (shane@minirl.com)
- * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * - add MX31 specific definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/err.h>
-
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-#include <asm/hardware/cache-l2x0.h>
-
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-static struct map_desc mx35_io_desc[] __initdata = {
- imx_map_entry(MX35, X_MEMC, MT_DEVICE),
- imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
- imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
- imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
- imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
-};
-
-void __init mx35_map_io(void)
-{
- iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
-}
-
-void __init imx35_init_early(void)
-{
- mxc_set_cpu_type(MXC_CPU_MX35);
- mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
- mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
-}
-
-void __init mx35_init_irq(void)
-{
- mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
- .ap_2_ap_addr = 642,
- .uart_2_mcu_addr = 817,
- .mcu_2_app_addr = 747,
- .uartsh_2_mcu_addr = 1183,
- .per_2_shp_addr = 1033,
- .mcu_2_shp_addr = 961,
- .ata_2_mcu_addr = 1333,
- .mcu_2_ata_addr = 1252,
- .app_2_mcu_addr = 683,
- .shp_2_per_addr = 1111,
- .shp_2_mcu_addr = 892,
-};
-
-static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
- .ap_2_ap_addr = 729,
- .uart_2_mcu_addr = 904,
- .per_2_app_addr = 1597,
- .mcu_2_app_addr = 834,
- .uartsh_2_mcu_addr = 1270,
- .per_2_shp_addr = 1120,
- .mcu_2_shp_addr = 1048,
- .ata_2_mcu_addr = 1429,
- .mcu_2_ata_addr = 1339,
- .app_2_per_addr = 1531,
- .app_2_mcu_addr = 770,
- .shp_2_per_addr = 1198,
- .shp_2_mcu_addr = 979,
-};
-
-static struct sdma_platform_data imx35_sdma_pdata __initdata = {
- .fw_name = "sdma-imx35-to2.bin",
- .script_addrs = &imx35_to2_sdma_script,
-};
-
-void __init imx35_soc_init(void)
-{
- int to_version = mx35_revision() >> 4;
-
- /* i.mx35 has the i.mx31 type gpio */
- mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
- mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
- mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
-
- if (to_version == 1) {
- strncpy(imx35_sdma_pdata.fw_name, "sdma-imx35-to1.bin",
- strlen(imx35_sdma_pdata.fw_name));
- imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
- }
-
- imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
-}
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
new file mode 100644
index 000000000000..c461e98496c3
--- /dev/null
+++ b/arch/arm/mach-imx/mmdc.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+
+#define MMDC_MAPSR 0x404
+#define BP_MMDC_MAPSR_PSD 0
+#define BP_MMDC_MAPSR_PSS 4
+
+static int __devinit imx_mmdc_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ void __iomem *mmdc_base, *reg;
+ u32 val;
+ int timeout = 0x400;
+
+ mmdc_base = of_iomap(np, 0);
+ WARN_ON(!mmdc_base);
+
+ reg = mmdc_base + MMDC_MAPSR;
+
+ /* Enable automatic power saving */
+ val = readl_relaxed(reg);
+ val &= ~(1 << BP_MMDC_MAPSR_PSD);
+ writel_relaxed(val, reg);
+
+ /* Ensure it's successfully enabled */
+ while (!(readl_relaxed(reg) & 1 << BP_MMDC_MAPSR_PSS) && --timeout)
+ cpu_relax();
+
+ if (unlikely(!timeout)) {
+ pr_warn("%s: failed to enable automatic power saving\n",
+ __func__);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static struct of_device_id imx_mmdc_dt_ids[] = {
+ { .compatible = "fsl,imx6q-mmdc", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver imx_mmdc_driver = {
+ .driver = {
+ .name = "imx-mmdc",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_mmdc_dt_ids,
+ },
+ .probe = imx_mmdc_probe,
+};
+
+static int __init imx_mmdc_init(void)
+{
+ return platform_driver_register(&imx_mmdc_driver);
+}
+postcore_initcall(imx_mmdc_init);
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
new file mode 100644
index 000000000000..ab98c6fec9eb
--- /dev/null
+++ b/arch/arm/mach-imx/platsmp.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <asm/page.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+static void __iomem *scu_base;
+
+static struct map_desc scu_io_desc __initdata = {
+ /* .virtual and .pfn are run-time assigned */
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+};
+
+void __init imx_scu_map_io(void)
+{
+ unsigned long base;
+
+ /* Get SCU base */
+ asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+ scu_io_desc.virtual = IMX_IO_P2V(base);
+ scu_io_desc.pfn = __phys_to_pfn(base);
+ iotable_init(&scu_io_desc, 1);
+
+ scu_base = IMX_IO_ADDRESS(base);
+}
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+ /*
+ * if any interrupts are already enabled for the primary
+ * core (e.g. timer irq), then they will not have been enabled
+ * for us: do so
+ */
+ gic_secondary_init(0);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ imx_set_cpu_jump(cpu, v7_secondary_startup);
+ imx_enable_cpu(cpu, true);
+ return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+ int i, ncores;
+
+ ncores = scu_get_core_count(scu_base);
+
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+
+ set_smp_cross_call(gic_raise_softirq);
+}
+
+void imx_smp_prepare(void)
+{
+ scu_enable(scu_base);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+ imx_smp_prepare();
+}
diff --git a/arch/arm/mach-imx/pm-imx27.c b/arch/arm/mach-imx/pm-imx27.c
index acf17691d2cc..e455d2f855bf 100644
--- a/arch/arm/mach-imx/pm-imx27.c
+++ b/arch/arm/mach-imx/pm-imx27.c
@@ -11,7 +11,7 @@
#include <linux/suspend.h>
#include <linux/io.h>
#include <mach/system.h>
-#include <mach/mx27.h>
+#include <mach/hardware.h>
static int mx27_suspend_enter(suspend_state_t state)
{
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
new file mode 100644
index 000000000000..f20f191d7cca
--- /dev/null
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+extern unsigned long phys_l2x0_saved_regs;
+
+static int imx6q_suspend_finish(unsigned long val)
+{
+ cpu_do_idle();
+ return 0;
+}
+
+static int imx6q_pm_enter(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ imx6q_set_lpm(STOP_POWER_OFF);
+ imx_gpc_pre_suspend();
+ imx_set_cpu_jump(0, v7_cpu_resume);
+ /* Zzz ... */
+ cpu_suspend(0, imx6q_suspend_finish);
+ imx_smp_prepare();
+ imx_gpc_post_resume();
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct platform_suspend_ops imx6q_pm_ops = {
+ .enter = imx6q_pm_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+void __init imx6q_pm_init(void)
+{
+ /*
+ * The l2x0 core code provides an infrastucture to save and restore
+ * l2x0 registers across suspend/resume cycle. But because imx6q
+ * retains L2 content during suspend and needs to resume L2 before
+ * MMU is enabled, it can only utilize register saving support and
+ * have to take care of restoring on its own. So we save physical
+ * address of the data structure used by l2x0 core to save registers,
+ * and later restore the necessary ones in imx6q resume entry.
+ */
+ phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
+
+ suspend_set_ops(&imx6q_pm_ops);
+}
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
new file mode 100644
index 000000000000..36cacbd0dcc2
--- /dev/null
+++ b/arch/arm/mach-imx/src.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/unified.h>
+
+#define SRC_SCR 0x000
+#define SRC_GPR1 0x020
+#define BP_SRC_SCR_CORE1_RST 14
+#define BP_SRC_SCR_CORE1_ENABLE 22
+
+static void __iomem *src_base;
+
+void imx_enable_cpu(int cpu, bool enable)
+{
+ u32 mask, val;
+
+ mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
+ val = readl_relaxed(src_base + SRC_SCR);
+ val = enable ? val | mask : val & ~mask;
+ writel_relaxed(val, src_base + SRC_SCR);
+}
+
+void imx_set_cpu_jump(int cpu, void *jump_addr)
+{
+ writel_relaxed(BSYM(virt_to_phys(jump_addr)),
+ src_base + SRC_GPR1 + cpu * 8);
+}
+
+void __init imx_src_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
+ src_base = of_iomap(np, 0);
+ WARN_ON(!src_base);
+}
diff --git a/arch/arm/mach-integrator/Makefile.boot b/arch/arm/mach-integrator/Makefile.boot
index c7e75acfe6c9..ff0a4b5b0a82 100644
--- a/arch/arm/mach-integrator/Makefile.boot
+++ b/arch/arm/mach-integrator/Makefile.boot
@@ -1,4 +1,4 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 77315b995681..4b38e13667ac 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -126,6 +126,10 @@ static struct clk_lookup lookups[] = {
{ /* Bus clock */
.con_id = "apb_pclk",
.clk = &dummy_apb_pclk,
+ }, {
+ /* Integrator/AP timer frequency */
+ .dev_id = "ap_timer",
+ .clk = &clk24mhz,
}, { /* UART0 */
.dev_id = "mb:16",
.clk = &uartclk,
@@ -205,7 +209,7 @@ static struct amba_pl010_data integrator_uart_data = {
#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL)
-static DEFINE_SPINLOCK(cm_lock);
+static DEFINE_RAW_SPINLOCK(cm_lock);
/**
* cm_control - update the CM_CTRL register.
@@ -217,10 +221,10 @@ void cm_control(u32 mask, u32 set)
unsigned long flags;
u32 val;
- spin_lock_irqsave(&cm_lock, flags);
+ raw_spin_lock_irqsave(&cm_lock, flags);
val = readl(CM_CTRL) & ~mask;
writel(val | set, CM_CTRL);
- spin_unlock_irqrestore(&cm_lock, flags);
+ raw_spin_unlock_irqrestore(&cm_lock, flags);
}
EXPORT_SYMBOL(cm_control);
diff --git a/arch/arm/mach-integrator/include/mach/debug-macro.S b/arch/arm/mach-integrator/include/mach/debug-macro.S
index a1f598fd3a56..411b116077e4 100644
--- a/arch/arm/mach-integrator/include/mach/debug-macro.S
+++ b/arch/arm/mach-integrator/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
*
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x16000000 @ physical base address
mov \rv, #0xf0000000 @ virtual base
add \rv, \rv, #0x16000000 >> 4
diff --git a/arch/arm/mach-integrator/include/mach/io.h b/arch/arm/mach-integrator/include/mach/io.h
index f21bb5493dd9..37beed3fa3ed 100644
--- a/arch/arm/mach-integrator/include/mach/io.h
+++ b/arch/arm/mach-integrator/include/mach/io.h
@@ -20,8 +20,6 @@
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
-#define IO_SPACE_LIMIT 0xffff
-
/*
* WARNING: this has to mirror definitions in platform.h
*/
diff --git a/arch/arm/mach-integrator/include/mach/platform.h b/arch/arm/mach-integrator/include/mach/platform.h
index 5e6ea5cfea6e..ec467baade09 100644
--- a/arch/arm/mach-integrator/include/mach/platform.h
+++ b/arch/arm/mach-integrator/include/mach/platform.h
@@ -13,9 +13,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* DO NOT EDIT!! - this file automatically generated
- * from .s file by awk -f s2h.awk
- */
/**************************************************************************
* * Copyright © ARM Limited 1998. All rights reserved.
* ***********************************************************************/
@@ -399,15 +396,6 @@
#define INTEGRATOR_TIMER1_BASE (INTEGRATOR_CT_BASE + 0x100)
#define INTEGRATOR_TIMER2_BASE (INTEGRATOR_CT_BASE + 0x200)
-#define TICKS_PER_uSEC 24
-
-/*
- * These are useconds NOT ticks.
- *
- */
-#define mSEC_1 1000
-#define mSEC_10 (mSEC_1 * 10)
-
#define INTEGRATOR_CSR_BASE 0x10000000
#define INTEGRATOR_CSR_SIZE 0x10000000
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 8cdc730dcb3a..a1769f35a86e 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -32,6 +32,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mtd/physmap.h>
+#include <linux/clk.h>
#include <video/vga.h>
#include <mach/hardware.h>
@@ -322,27 +323,16 @@ static void __init ap_init(void)
#define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE)
#define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE)
-/*
- * How long is the timer interval?
- */
-#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
-#if TIMER_INTERVAL >= 0x100000
-#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
-#elif TIMER_INTERVAL >= 0x10000
-#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
-#else
-#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
-#endif
-
static unsigned long timer_reload;
-static void integrator_clocksource_init(u32 khz)
+static void integrator_clocksource_init(unsigned long inrate)
{
void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
+ unsigned long rate = inrate;
- if (khz >= 1500) {
- khz /= 16;
+ if (rate >= 1500000) {
+ rate /= 16;
ctrl |= TIMER_CTRL_DIV16;
}
@@ -350,7 +340,7 @@ static void integrator_clocksource_init(u32 khz)
writel(ctrl, base + TIMER_CTRL);
clocksource_mmio_init(base + TIMER_VALUE, "timer2",
- khz * 1000, 200, 16, clocksource_mmio_readl_down);
+ rate, 200, 16, clocksource_mmio_readl_down);
}
static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
@@ -374,15 +364,29 @@ static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_devic
{
u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
- BUG_ON(mode == CLOCK_EVT_MODE_ONESHOT);
+ /* Disable timer */
+ writel(ctrl, clkevt_base + TIMER_CTRL);
- if (mode == CLOCK_EVT_MODE_PERIODIC) {
- writel(ctrl, clkevt_base + TIMER_CTRL);
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ /* Enable the timer and start the periodic tick */
writel(timer_reload, clkevt_base + TIMER_LOAD);
ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
+ writel(ctrl, clkevt_base + TIMER_CTRL);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* Leave the timer disabled, .set_next_event will enable it */
+ ctrl &= ~TIMER_CTRL_PERIODIC;
+ writel(ctrl, clkevt_base + TIMER_CTRL);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ default:
+ /* Just leave in disabled state */
+ break;
}
- writel(ctrl, clkevt_base + TIMER_CTRL);
}
static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
@@ -398,12 +402,10 @@ static int clkevt_set_next_event(unsigned long next, struct clock_event_device *
static struct clock_event_device integrator_clockevent = {
.name = "timer1",
- .shift = 34,
- .features = CLOCK_EVT_FEAT_PERIODIC,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_mode = clkevt_set_mode,
.set_next_event = clkevt_set_next_event,
.rating = 300,
- .cpumask = cpu_all_mask,
};
static struct irqaction integrator_timer_irq = {
@@ -413,29 +415,27 @@ static struct irqaction integrator_timer_irq = {
.dev_id = &integrator_clockevent,
};
-static void integrator_clockevent_init(u32 khz)
+static void integrator_clockevent_init(unsigned long inrate)
{
- struct clock_event_device *evt = &integrator_clockevent;
+ unsigned long rate = inrate;
unsigned int ctrl = 0;
- if (khz * 1000 > 0x100000 * HZ) {
- khz /= 256;
+ /* Calculate and program a divisor */
+ if (rate > 0x100000 * HZ) {
+ rate /= 256;
ctrl |= TIMER_CTRL_DIV256;
- } else if (khz * 1000 > 0x10000 * HZ) {
- khz /= 16;
+ } else if (rate > 0x10000 * HZ) {
+ rate /= 16;
ctrl |= TIMER_CTRL_DIV16;
}
-
- timer_reload = khz * 1000 / HZ;
+ timer_reload = rate / HZ;
writel(ctrl, clkevt_base + TIMER_CTRL);
- evt->irq = IRQ_TIMERINT1;
- evt->mult = div_sc(khz, NSEC_PER_MSEC, evt->shift);
- evt->max_delta_ns = clockevent_delta2ns(0xffff, evt);
- evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
-
setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
- clockevents_register_device(evt);
+ clockevents_config_and_register(&integrator_clockevent,
+ rate,
+ 1,
+ 0xffffU);
}
/*
@@ -443,14 +443,20 @@ static void integrator_clockevent_init(u32 khz)
*/
static void __init ap_init_timer(void)
{
- u32 khz = TICKS_PER_uSEC * 1000;
+ struct clk *clk;
+ unsigned long rate;
+
+ clk = clk_get_sys("ap_timer", NULL);
+ BUG_ON(IS_ERR(clk));
+ clk_enable(clk);
+ rate = clk_get_rate(clk);
writel(0, TIMER0_VA_BASE + TIMER_CTRL);
writel(0, TIMER1_VA_BASE + TIMER_CTRL);
writel(0, TIMER2_VA_BASE + TIMER_CTRL);
- integrator_clocksource_init(khz);
- integrator_clockevent_init(khz);
+ integrator_clocksource_init(rate);
+ integrator_clockevent_init(rate);
}
static struct sys_timer ap_timer = {
@@ -459,7 +465,7 @@ static struct sys_timer ap_timer = {
MACHINE_START(INTEGRATOR, "ARM-Integrator")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.reserve = integrator_reserve,
.map_io = ap_map_io,
.init_early = integrator_init_early,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 4eb03ab5cb46..5de49c33e4d4 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -492,7 +492,7 @@ static struct sys_timer cp_timer = {
MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.reserve = integrator_reserve,
.map_io = intcp_map_io,
.init_early = intcp_init_early,
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index 11b86e5b71c2..b4d8f8b8a085 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -163,7 +163,7 @@
* 7:2 register number
*
*/
-static DEFINE_SPINLOCK(v3_lock);
+static DEFINE_RAW_SPINLOCK(v3_lock);
#define PCI_BUS_NONMEM_START 0x00000000
#define PCI_BUS_NONMEM_SIZE SZ_256M
@@ -284,7 +284,7 @@ static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
unsigned long flags;
u32 v;
- spin_lock_irqsave(&v3_lock, flags);
+ raw_spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(bus, devfn, where);
switch (size) {
@@ -302,7 +302,7 @@ static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
}
v3_close_config_window();
- spin_unlock_irqrestore(&v3_lock, flags);
+ raw_spin_unlock_irqrestore(&v3_lock, flags);
*val = v;
return PCIBIOS_SUCCESSFUL;
@@ -314,7 +314,7 @@ static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
unsigned long addr;
unsigned long flags;
- spin_lock_irqsave(&v3_lock, flags);
+ raw_spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(bus, devfn, where);
switch (size) {
@@ -335,7 +335,7 @@ static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
}
v3_close_config_window();
- spin_unlock_irqrestore(&v3_lock, flags);
+ raw_spin_unlock_irqrestore(&v3_lock, flags);
return PCIBIOS_SUCCESSFUL;
}
@@ -513,7 +513,7 @@ void __init pci_v3_preinit(void)
hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
- spin_lock_irqsave(&v3_lock, flags);
+ raw_spin_lock_irqsave(&v3_lock, flags);
/*
* Unlock V3 registers, but only if they were previously locked.
@@ -586,7 +586,7 @@ void __init pci_v3_preinit(void)
printk(KERN_ERR "PCI: unable to grab PCI error "
"interrupt: %d\n", ret);
- spin_unlock_irqrestore(&v3_lock, flags);
+ raw_spin_unlock_irqrestore(&v3_lock, flags);
}
void __init pci_v3_postinit(void)
diff --git a/arch/arm/mach-iop13xx/Makefile.boot b/arch/arm/mach-iop13xx/Makefile.boot
index 0b0e19fdfe6c..3a8c38c3189c 100644
--- a/arch/arm/mach-iop13xx/Makefile.boot
+++ b/arch/arm/mach-iop13xx/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-iop13xx/include/mach/debug-macro.S b/arch/arm/mach-iop13xx/include/mach/debug-macro.S
index e664466d51bf..d869a6f67e5c 100644
--- a/arch/arm/mach-iop13xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-iop13xx/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
* published by the Free Software Foundation.
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00002300
orr \rp, \rp, #0x00000040
orr \rv, \rp, #0xfe000000 @ virtual
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c
index 23dfaffc586c..4cf2cc477eae 100644
--- a/arch/arm/mach-iop13xx/iq81340mc.c
+++ b/arch/arm/mach-iop13xx/iq81340mc.c
@@ -91,7 +91,7 @@ static struct sys_timer iq81340mc_timer = {
MACHINE_START(IQ81340MC, "Intel IQ81340MC")
/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = iop13xx_map_io,
.init_irq = iop13xx_init_irq,
.timer = &iq81340mc_timer,
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c
index df3492a9c280..cd9e27499a1e 100644
--- a/arch/arm/mach-iop13xx/iq81340sc.c
+++ b/arch/arm/mach-iop13xx/iq81340sc.c
@@ -93,7 +93,7 @@ static struct sys_timer iq81340sc_timer = {
MACHINE_START(IQ81340SC, "Intel IQ81340SC")
/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = iop13xx_map_io,
.init_irq = iop13xx_init_irq,
.timer = &iq81340sc_timer,
diff --git a/arch/arm/mach-iop32x/Makefile.boot b/arch/arm/mach-iop32x/Makefile.boot
index 47000dccd61f..0a833b11e38c 100644
--- a/arch/arm/mach-iop32x/Makefile.boot
+++ b/arch/arm/mach-iop32x/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0xa0008000
+ zreladdr-y += 0xa0008000
params_phys-y := 0xa0000100
initrd_phys-y := 0xa0800000
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 6cbffbfc2bba..4325055d4e19 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -203,7 +203,7 @@ static void __init em7210_init_machine(void)
}
MACHINE_START(EM7210, "Lanner EM7210")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = em7210_map_io,
.init_irq = iop32x_init_irq,
.timer = &em7210_timer,
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index ceef5d4dce1a..0edc88020577 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -207,7 +207,7 @@ static void __init glantank_init_machine(void)
MACHINE_START(GLANTANK, "GLAN Tank")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = glantank_map_io,
.init_irq = iop32x_init_irq,
.timer = &glantank_timer,
diff --git a/arch/arm/mach-iop32x/include/mach/debug-macro.S b/arch/arm/mach-iop32x/include/mach/debug-macro.S
index ff9e76c09f35..363bdf90b34d 100644
--- a/arch/arm/mach-iop32x/include/mach/debug-macro.S
+++ b/arch/arm/mach-iop32x/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
* published by the Free Software Foundation.
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0xfe000000 @ physical as well as virtual
orr \rp, \rp, #0x00800000 @ location of the UART
mov \rv, \rp
diff --git a/arch/arm/mach-iop32x/include/mach/memory.h b/arch/arm/mach-iop32x/include/mach/memory.h
deleted file mode 100644
index 169cc239f76c..000000000000
--- a/arch/arm/mach-iop32x/include/mach/memory.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-iop32x/include/mach/memory.h
- */
-
-#ifndef __MEMORY_H
-#define __MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0xa0000000)
-
-#endif
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index 3a62514dae7c..9e7aaccfeba0 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -313,7 +313,7 @@ __setup("force_ep80219", force_ep80219_setup);
MACHINE_START(IQ31244, "Intel IQ31244")
/* Maintainer: Intel Corp. */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = iq31244_map_io,
.init_irq = iop32x_init_irq,
.timer = &iq31244_timer,
@@ -327,7 +327,7 @@ MACHINE_END
*/
MACHINE_START(EP80219, "Intel EP80219")
/* Maintainer: Intel Corp. */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = iq31244_map_io,
.init_irq = iop32x_init_irq,
.timer = &iq31244_timer,
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index 35b7e6914d3b..53ea86f649dd 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -186,7 +186,7 @@ static void __init iq80321_init_machine(void)
MACHINE_START(IQ80321, "Intel IQ80321")
/* Maintainer: Intel Corp. */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = iq80321_map_io,
.init_irq = iop32x_init_irq,
.timer = &iq80321_timer,
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 1a374eab6007..d7269279968c 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -327,7 +327,7 @@ static void __init n2100_init_machine(void)
MACHINE_START(N2100, "Thecus N2100")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = n2100_map_io,
.init_irq = iop32x_init_irq,
.timer = &n2100_timer,
diff --git a/arch/arm/mach-iop33x/Makefile.boot b/arch/arm/mach-iop33x/Makefile.boot
index 67039c3e0c48..760a0efe7580 100644
--- a/arch/arm/mach-iop33x/Makefile.boot
+++ b/arch/arm/mach-iop33x/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-iop33x/include/mach/debug-macro.S b/arch/arm/mach-iop33x/include/mach/debug-macro.S
index 40c500dd1fac..361be1f6026e 100644
--- a/arch/arm/mach-iop33x/include/mach/debug-macro.S
+++ b/arch/arm/mach-iop33x/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
* published by the Free Software Foundation.
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00ff0000
orr \rp, \rp, #0x0000f700
orr \rv, #0xfe000000 @ virtual
diff --git a/arch/arm/mach-iop33x/include/mach/memory.h b/arch/arm/mach-iop33x/include/mach/memory.h
deleted file mode 100644
index 8e1daf7006b6..000000000000
--- a/arch/arm/mach-iop33x/include/mach/memory.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-iop33x/include/mach/memory.h
- */
-
-#ifndef __MEMORY_H
-#define __MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
index 637c0272d5e0..9e14ccc56f8e 100644
--- a/arch/arm/mach-iop33x/iq80331.c
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -141,7 +141,7 @@ static void __init iq80331_init_machine(void)
MACHINE_START(IQ80331, "Intel IQ80331")
/* Maintainer: Intel Corp. */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = iop3xx_map_io,
.init_irq = iop33x_init_irq,
.timer = &iq80331_timer,
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
index 90a0436d7255..09c899a2523f 100644
--- a/arch/arm/mach-iop33x/iq80332.c
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -141,7 +141,7 @@ static void __init iq80332_init_machine(void)
MACHINE_START(IQ80332, "Intel IQ80332")
/* Maintainer: Intel Corp. */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = iop3xx_map_io,
.init_irq = iop33x_init_irq,
.timer = &iq80332_timer,
diff --git a/arch/arm/mach-ixp2000/Makefile.boot b/arch/arm/mach-ixp2000/Makefile.boot
index d84c5807a43d..9c7af91d93da 100644
--- a/arch/arm/mach-ixp2000/Makefile.boot
+++ b/arch/arm/mach-ixp2000/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 4068166c8993..59a512672bb9 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -13,7 +13,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
@@ -39,7 +39,7 @@
#include <asm/mach/time.h>
#include <asm/mach/irq.h>
-#include <mach/gpio.h>
+#include <mach/gpio-ixp2000.h>
static DEFINE_SPINLOCK(ixp2000_slowport_lock);
static unsigned long ixp2000_slowport_irq_flags;
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
index 62c60ade5274..af9994537e01 100644
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -254,7 +254,7 @@ static void __init enp2611_init_machine(void)
MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = enp2611_map_io,
.init_irq = ixp2000_init_irq,
.timer = &enp2611_timer,
diff --git a/arch/arm/mach-ixp2000/include/mach/debug-macro.S b/arch/arm/mach-ixp2000/include/mach/debug-macro.S
index 0ef533b20972..bdd3ccdc2890 100644
--- a/arch/arm/mach-ixp2000/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp2000/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
*
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00030000
#ifdef __ARMEB__
orr \rp, \rp, #0x00000003
diff --git a/arch/arm/mach-ixp2000/include/mach/gpio.h b/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h
index 4a88d2c33dac..af836c76c3f1 100644
--- a/arch/arm/mach-ixp2000/include/mach/gpio.h
+++ b/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 Intel Corporation.
*
- * This program is free software, you can redistribute it and/or modify
+ * 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.
*/
@@ -11,7 +11,7 @@
/*
* IXP2000 GPIO in/out, edge/level detection for IRQs:
* IRQs are generated on Falling-edge, Rising-Edge, Level-low, Level-High
- * or both Falling-edge and Rising-edge.
+ * or both Falling-edge and Rising-edge.
* This must be called *before* the corresponding IRQ is registerd.
* Use this instead of directly setting the GPIO registers.
* GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
index 5bad1a8419b7..f7dfd9700141 100644
--- a/arch/arm/mach-ixp2000/ixdp2400.c
+++ b/arch/arm/mach-ixp2000/ixdp2400.c
@@ -171,7 +171,7 @@ void __init ixdp2400_init_irq(void)
MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = ixdp2x00_map_io,
.init_irq = ixdp2400_init_irq,
.timer = &ixdp2400_timer,
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
index 3d3cef876467..d33bcac1ec92 100644
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -286,7 +286,7 @@ void __init ixdp2800_init_irq(void)
MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = ixdp2x00_map_io,
.init_irq = ixdp2800_init_irq,
.timer = &ixdp2800_timer,
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
index 235638f800e5..634b6c852f68 100644
--- a/arch/arm/mach-ixp2000/ixdp2x00.c
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -14,6 +14,7 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
@@ -40,8 +41,7 @@
#include <asm/mach/flash.h>
#include <asm/mach/arch.h>
-#include <mach/gpio.h>
-
+#include <mach/gpio-ixp2000.h>
/*************************************************************************
* IXDP2x00 IRQ Initialization
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index be2a254f1374..61a28676b5be 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -417,7 +417,7 @@ static void __init ixdp2x01_init_machine(void)
#ifdef CONFIG_ARCH_IXDP2401
MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = ixdp2x01_map_io,
.init_irq = ixdp2x01_init_irq,
.timer = &ixdp2x01_timer,
@@ -428,7 +428,7 @@ MACHINE_END
#ifdef CONFIG_ARCH_IXDP2801
MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = ixdp2x01_map_io,
.init_irq = ixdp2x01_init_irq,
.timer = &ixdp2x01_timer,
@@ -441,7 +441,7 @@ MACHINE_END
*/
MACHINE_START(IXDP28X5, "Intel IXDP2805/2855 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = ixdp2x01_map_io,
.init_irq = ixdp2x01_init_irq,
.timer = &ixdp2x01_timer,
diff --git a/arch/arm/mach-ixp23xx/Makefile.boot b/arch/arm/mach-ixp23xx/Makefile.boot
index d5561ad15bad..44fb4a717c3f 100644
--- a/arch/arm/mach-ixp23xx/Makefile.boot
+++ b/arch/arm/mach-ixp23xx/Makefile.boot
@@ -1,2 +1,2 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
index e25e5fe183ba..30dd31652e9d 100644
--- a/arch/arm/mach-ixp23xx/espresso.c
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -88,6 +88,6 @@ MACHINE_START(ESPRESSO, "IP Fabrics Double Espresso")
.map_io = ixp23xx_map_io,
.init_irq = ixp23xx_init_irq,
.timer = &ixp23xx_timer,
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = espresso_init,
MACHINE_END
diff --git a/arch/arm/mach-ixp23xx/include/mach/debug-macro.S b/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
index f7c6eef7fa22..5ff524c13744 100644
--- a/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
@@ -12,7 +12,7 @@
*/
#include <mach/ixp23xx.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =IXP23XX_PERIPHERAL_PHYS @ physical
ldr \rv, =IXP23XX_PERIPHERAL_VIRT @ virtual
#ifdef __ARMEB__
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
index ec028e35f401..b3a57e0f3419 100644
--- a/arch/arm/mach-ixp23xx/ixdp2351.c
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -331,6 +331,6 @@ MACHINE_START(IXDP2351, "Intel IXDP2351 Development Platform")
.map_io = ixdp2351_map_io,
.init_irq = ixdp2351_init_irq,
.timer = &ixp23xx_timer,
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = ixdp2351_init,
MACHINE_END
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
index 844551d2368b..8f4dcbba9025 100644
--- a/arch/arm/mach-ixp23xx/roadrunner.c
+++ b/arch/arm/mach-ixp23xx/roadrunner.c
@@ -175,6 +175,6 @@ MACHINE_START(ROADRUNNER, "ADI Engineering RoadRunner Development Platform")
.map_io = ixp23xx_map_io,
.init_irq = ixp23xx_init_irq,
.timer = &ixp23xx_timer,
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = roadrunner_init,
MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 6f991c5ae863..fd5e7b6881bf 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -179,6 +179,25 @@ config MACH_GTWX5715
"High Speed" UART is n/c (as far as I can tell)
20 Pin ARM/Xscale JTAG interface on J2
+config MACH_DEVIXP
+ bool "Omicron DEVIXP"
+ help
+ Say 'Y' here if you want your kernel to support the DEVIXP
+ board from OMICRON electronics GmbH.
+
+config MACH_MICCPT
+ bool "Omicron MICCPT"
+ select PCI
+ help
+ Say 'Y' here if you want your kernel to support the MICCPT
+ board from OMICRON electronics GmbH.
+
+config MACH_MIC256
+ bool "Omicron MIC256"
+ help
+ Say 'Y' here if you want your kernel to support the MIC256
+ board from OMICRON electronics GmbH.
+
comment "IXP4xx Options"
config IXP4XX_INDIRECT_PCI
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index d807fc367dd3..eded94c96dd4 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -10,6 +10,7 @@ obj-pci-$(CONFIG_MACH_AVILA) += avila-pci.o
obj-pci-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o
obj-pci-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o
obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o
+obj-pci-$(CONFIG_MACH_MICCPT) += miccpt-pci.o
obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o
obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o
obj-pci-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o
@@ -25,6 +26,9 @@ obj-$(CONFIG_MACH_AVILA) += avila-setup.o
obj-$(CONFIG_MACH_IXDPG425) += coyote-setup.o
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o
obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o
+obj-$(CONFIG_MACH_DEVIXP) += omixp-setup.o
+obj-$(CONFIG_MACH_MICCPT) += omixp-setup.o
+obj-$(CONFIG_MACH_MIC256) += omixp-setup.o
obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o
obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o
obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o
diff --git a/arch/arm/mach-ixp4xx/Makefile.boot b/arch/arm/mach-ixp4xx/Makefile.boot
index d84c5807a43d..9c7af91d93da 100644
--- a/arch/arm/mach-ixp4xx/Makefile.boot
+++ b/arch/arm/mach-ixp4xx/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
index ee19c1d383aa..37609a22c450 100644
--- a/arch/arm/mach-ixp4xx/avila-setup.c
+++ b/arch/arm/mach-ixp4xx/avila-setup.c
@@ -167,7 +167,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = avila_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
@@ -185,7 +185,7 @@ MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = avila_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index 2131832ee6ba..f72a3a893c47 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -54,7 +54,7 @@ unsigned long ixp4xx_pci_reg_base = 0;
* these transactions are atomic or we will end up
* with corrupt data on the bus or in a driver.
*/
-static DEFINE_SPINLOCK(ixp4xx_pci_lock);
+static DEFINE_RAW_SPINLOCK(ixp4xx_pci_lock);
/*
* Read from PCI config space
@@ -62,10 +62,10 @@ static DEFINE_SPINLOCK(ixp4xx_pci_lock);
static void crp_read(u32 ad_cbe, u32 *data)
{
unsigned long flags;
- spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+ raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
*PCI_CRP_AD_CBE = ad_cbe;
*data = *PCI_CRP_RDATA;
- spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+ raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
}
/*
@@ -74,10 +74,10 @@ static void crp_read(u32 ad_cbe, u32 *data)
static void crp_write(u32 ad_cbe, u32 data)
{
unsigned long flags;
- spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+ raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
*PCI_CRP_AD_CBE = CRP_AD_CBE_WRITE | ad_cbe;
*PCI_CRP_WDATA = data;
- spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+ raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
}
static inline int check_master_abort(void)
@@ -101,7 +101,7 @@ int ixp4xx_pci_read_errata(u32 addr, u32 cmd, u32* data)
int retval = 0;
int i;
- spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+ raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
*PCI_NP_AD = addr;
@@ -118,7 +118,7 @@ int ixp4xx_pci_read_errata(u32 addr, u32 cmd, u32* data)
if(check_master_abort())
retval = 1;
- spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+ raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
return retval;
}
@@ -127,7 +127,7 @@ int ixp4xx_pci_read_no_errata(u32 addr, u32 cmd, u32* data)
unsigned long flags;
int retval = 0;
- spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+ raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
*PCI_NP_AD = addr;
@@ -140,7 +140,7 @@ int ixp4xx_pci_read_no_errata(u32 addr, u32 cmd, u32* data)
if(check_master_abort())
retval = 1;
- spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+ raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
return retval;
}
@@ -149,7 +149,7 @@ int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data)
unsigned long flags;
int retval = 0;
- spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+ raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
*PCI_NP_AD = addr;
@@ -162,7 +162,7 @@ int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data)
if(check_master_abort())
retval = 1;
- spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+ raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
return retval;
}
@@ -397,7 +397,8 @@ void __init ixp4xx_pci_preinit(void)
local_write_config(PCI_BASE_ADDRESS_0, 4, PHYS_OFFSET);
local_write_config(PCI_BASE_ADDRESS_1, 4, PHYS_OFFSET + SZ_16M);
local_write_config(PCI_BASE_ADDRESS_2, 4, PHYS_OFFSET + SZ_32M);
- local_write_config(PCI_BASE_ADDRESS_3, 4, PHYS_OFFSET + SZ_48M);
+ local_write_config(PCI_BASE_ADDRESS_3, 4,
+ PHYS_OFFSET + SZ_32M + SZ_16M);
/*
* Enable CSR window at 64 MiB to allow PCI masters
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index e24564b5d935..81dfec31842b 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -112,7 +112,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = coyote_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
@@ -130,7 +130,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = coyote_init,
MACHINE_END
#endif
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 03e54515e8b3..8837fbca27ce 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -16,7 +16,7 @@
* Author: Rod Whitby <rod@whitby.id.au>
* Maintainers: http://www.nslu2-linux.org/
*/
-
+#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
@@ -31,7 +31,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/time.h>
-#include <asm/gpio.h>
#define DSMG600_SDA_PIN 5
#define DSMG600_SCL_PIN 4
@@ -279,7 +278,7 @@ static void __init dsmg600_init(void)
MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
/* Maintainer: www.nslu2-linux.org */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &dsmg600_timer,
diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c
index 23a8b3614568..2887c3578c17 100644
--- a/arch/arm/mach-ixp4xx/fsg-setup.c
+++ b/arch/arm/mach-ixp4xx/fsg-setup.c
@@ -14,7 +14,7 @@
* Maintainers: http://www.nslu2-linux.org/
*
*/
-
+#include <linux/gpio.h>
#include <linux/if_ether.h>
#include <linux/irq.h>
#include <linux/serial.h>
@@ -27,7 +27,6 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
-#include <asm/gpio.h>
#define FSG_SDA_PIN 12
#define FSG_SCL_PIN 13
@@ -273,7 +272,7 @@ MACHINE_START(FSG, "Freecom FSG-3")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = fsg_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
index d4f851bdd9a4..d69d1b053bb7 100644
--- a/arch/arm/mach-ixp4xx/gateway7001-setup.c
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -99,7 +99,7 @@ MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = gateway7001_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c
index 7548d9a2efe2..bf6678d1a929 100644
--- a/arch/arm/mach-ixp4xx/goramo_mlr.c
+++ b/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -499,7 +499,7 @@ MACHINE_START(GORAMO_MLR, "MultiLink")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = gmlr_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 3790dffd3c30..aa029fc19140 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -167,7 +167,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = gtwx5715_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
diff --git a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
index b974a49c0aff..8c9f8d564492 100644
--- a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
@@ -10,7 +10,7 @@
* published by the Free Software Foundation.
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
#ifdef __ARMEB__
mov \rp, #3 @ Uart regs are at off set of 3 if
@ byte writes used - Big Endian.
diff --git a/arch/arm/mach-ixp4xx/include/mach/gpio.h b/arch/arm/mach-ixp4xx/include/mach/gpio.h
index a5f87ded2f28..83d6b4ed60bb 100644
--- a/arch/arm/mach-ixp4xx/include/mach/gpio.h
+++ b/arch/arm/mach-ixp4xx/include/mach/gpio.h
@@ -28,6 +28,8 @@
#include <linux/kernel.h>
#include <mach/hardware.h>
+#define __ARM_GPIOLIB_COMPLEX
+
static inline int gpio_request(unsigned gpio, const char *label)
{
return 0;
@@ -70,6 +72,7 @@ static inline void gpio_set_value(unsigned gpio, int value)
#include <asm-generic/gpio.h> /* cansleep wrappers */
extern int gpio_to_irq(int gpio);
+#define gpio_to_irq gpio_to_irq
extern int irq_to_gpio(unsigned int irq);
#endif
diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h
index 57b5410c31f4..ffb9d6afb89f 100644
--- a/arch/arm/mach-ixp4xx/include/mach/io.h
+++ b/arch/arm/mach-ixp4xx/include/mach/io.h
@@ -17,8 +17,6 @@
#include <mach/hardware.h>
-#define IO_SPACE_LIMIT 0x0000ffff
-
extern int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data);
extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data);
diff --git a/arch/arm/mach-ixp4xx/include/mach/memory.h b/arch/arm/mach-ixp4xx/include/mach/memory.h
deleted file mode 100644
index 4caf1761f1e2..000000000000
--- a/arch/arm/mach-ixp4xx/include/mach/memory.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/include/mach/memory.h
- *
- * Copyright (c) 2001-2004 MontaVista Software, Inc.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <asm/sizes.h>
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-ixp4xx/include/mach/uncompress.h b/arch/arm/mach-ixp4xx/include/mach/uncompress.h
index 219d7c1dcdba..eb945a926d07 100644
--- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h
+++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h
@@ -41,7 +41,8 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
* Some boards are using UART2 as console
*/
if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
- machine_is_gateway7001() || machine_is_wg302v2())
+ machine_is_gateway7001() || machine_is_wg302v2() ||
+ machine_is_devixp() || machine_is_miccpt() || machine_is_mic256())
uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
else
uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 6a2927956bf6..f235f829dfa6 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -256,7 +256,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = ixdp425_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
@@ -270,7 +270,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = ixdp425_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
@@ -284,7 +284,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = ixdp425_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
@@ -298,7 +298,7 @@ MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = ixdp425_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
diff --git a/arch/arm/mach-ixp4xx/miccpt-pci.c b/arch/arm/mach-ixp4xx/miccpt-pci.c
new file mode 100644
index 000000000000..ca0bae7fca90
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/miccpt-pci.c
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-ixp4xx/miccpt-pci.c
+ *
+ * MICCPT board-level PCI initialization
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * Copyright (C) 2006 OMICRON electronics GmbH
+ *
+ * Author: Michael Jochum <michael.jochum@omicron.at>
+ *
+ * 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/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV 4
+#define IRQ_LINES 4
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA 1
+#define INTB 2
+#define INTC 3
+#define INTD 4
+
+
+void __init miccpt_pci_preinit(void)
+{
+ irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+ irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+ irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+ irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+ ixp4xx_pci_preinit();
+}
+
+static int __init miccpt_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ static int pci_irq_table[IRQ_LINES] = {
+ IXP4XX_GPIO_IRQ(INTA),
+ IXP4XX_GPIO_IRQ(INTB),
+ IXP4XX_GPIO_IRQ(INTC),
+ IXP4XX_GPIO_IRQ(INTD)
+ };
+
+ if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+ return pci_irq_table[(slot + pin - 2) % 4];
+
+ return -1;
+}
+
+struct hw_pci miccpt_pci __initdata = {
+ .nr_controllers = 1,
+ .preinit = miccpt_pci_preinit,
+ .swizzle = pci_std_swizzle,
+ .setup = ixp4xx_setup,
+ .scan = ixp4xx_scan_bus,
+ .map_irq = miccpt_map_irq,
+};
+
+int __init miccpt_pci_init(void)
+{
+ if (machine_is_miccpt())
+ pci_common_init(&miccpt_pci);
+ return 0;
+}
+
+subsys_initcall(miccpt_pci_init);
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index afb51879d9a4..de716fa1aab6 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -17,7 +17,7 @@
* Maintainers: http://www.nslu2-linux.org/
*
*/
-
+#include <linux/gpio.h>
#include <linux/if_ether.h>
#include <linux/irq.h>
#include <linux/jiffies.h>
@@ -32,7 +32,6 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
-#include <asm/gpio.h>
#define NAS100D_SDA_PIN 5
#define NAS100D_SCL_PIN 6
@@ -314,7 +313,7 @@ static void __init nas100d_init(void)
MACHINE_START(NAS100D, "Iomega NAS 100d")
/* Maintainer: www.nslu2-linux.org */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 69e40f2cf092..ac81ccb26bfe 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -16,7 +16,7 @@
* Maintainers: http://www.nslu2-linux.org/
*
*/
-
+#include <linux/gpio.h>
#include <linux/if_ether.h>
#include <linux/irq.h>
#include <linux/serial.h>
@@ -30,7 +30,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/time.h>
-#include <asm/gpio.h>
#define NSLU2_SDA_PIN 7
#define NSLU2_SCL_PIN 6
@@ -300,7 +299,7 @@ static void __init nslu2_init(void)
MACHINE_START(NSLU2, "Linksys NSLU2")
/* Maintainer: www.nslu2-linux.org */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &nslu2_timer,
diff --git a/arch/arm/mach-ixp4xx/omixp-setup.c b/arch/arm/mach-ixp4xx/omixp-setup.c
new file mode 100644
index 000000000000..3b6a81a696fc
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/omixp-setup.c
@@ -0,0 +1,273 @@
+/*
+ * arch/arm/mach-ixp4xx/omixp-setup.c
+ *
+ * omicron ixp4xx board setup
+ * Copyright (C) 2009 OMICRON electronics GmbH
+ *
+ * based nslu2-setup.c, ixdp425-setup.c:
+ * Copyright (C) 2003-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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#ifdef CONFIG_LEDS_CLASS
+#include <linux/leds.h>
+#endif
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct resource omixp_flash_resources[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ }, {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct mtd_partition omixp_partitions[] = {
+ {
+ .name = "Recovery Bootloader",
+ .size = 0x00020000,
+ .offset = 0,
+ }, {
+ .name = "Calibration Data",
+ .size = 0x00020000,
+ .offset = 0x00020000,
+ }, {
+ .name = "Recovery FPGA",
+ .size = 0x00020000,
+ .offset = 0x00040000,
+ }, {
+ .name = "Release Bootloader",
+ .size = 0x00020000,
+ .offset = 0x00060000,
+ }, {
+ .name = "Release FPGA",
+ .size = 0x00020000,
+ .offset = 0x00080000,
+ }, {
+ .name = "Kernel",
+ .size = 0x00160000,
+ .offset = 0x000a0000,
+ }, {
+ .name = "Filesystem",
+ .size = 0x00C00000,
+ .offset = 0x00200000,
+ }, {
+ .name = "Persistent Storage",
+ .size = 0x00200000,
+ .offset = 0x00E00000,
+ },
+};
+
+static struct flash_platform_data omixp_flash_data[] = {
+ {
+ .map_name = "cfi_probe",
+ .parts = omixp_partitions,
+ .nr_parts = ARRAY_SIZE(omixp_partitions),
+ }, {
+ .map_name = "cfi_probe",
+ .parts = NULL,
+ .nr_parts = 0,
+ },
+};
+
+static struct platform_device omixp_flash_device[] = {
+ {
+ .name = "IXP4XX-Flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &omixp_flash_data[0],
+ },
+ .resource = &omixp_flash_resources[0],
+ .num_resources = 1,
+ }, {
+ .name = "IXP4XX-Flash",
+ .id = 1,
+ .dev = {
+ .platform_data = &omixp_flash_data[1],
+ },
+ .resource = &omixp_flash_resources[1],
+ .num_resources = 1,
+ },
+};
+
+/* Swap UART's - These boards have the console on UART2. The following
+ * configuration is used:
+ * ttyS0 .. UART2
+ * ttyS1 .. UART1
+ * This way standard images can be used with the kernel that expect
+ * the console on ttyS0.
+ */
+static struct resource omixp_uart_resources[] = {
+ {
+ .start = IXP4XX_UART2_BASE_PHYS,
+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IXP4XX_UART1_BASE_PHYS,
+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct plat_serial8250_port omixp_uart_data[] = {
+ {
+ .mapbase = IXP4XX_UART2_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART2,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ }, {
+ .mapbase = IXP4XX_UART1_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART1,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ }, {
+ /* list termination */
+ }
+};
+
+static struct platform_device omixp_uart = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev.platform_data = omixp_uart_data,
+ .num_resources = 2,
+ .resource = omixp_uart_resources,
+};
+
+static struct gpio_led mic256_led_pins[] = {
+ {
+ .name = "LED-A",
+ .gpio = 7,
+ },
+};
+
+static struct gpio_led_platform_data mic256_led_data = {
+ .num_leds = ARRAY_SIZE(mic256_led_pins),
+ .leds = mic256_led_pins,
+};
+
+static struct platform_device mic256_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev.platform_data = &mic256_led_data,
+};
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info ixdp425_plat_eth[] = {
+ {
+ .phy = 0,
+ .rxq = 3,
+ .txreadyq = 20,
+ }, {
+ .phy = 1,
+ .rxq = 4,
+ .txreadyq = 21,
+ },
+};
+
+static struct platform_device ixdp425_eth[] = {
+ {
+ .name = "ixp4xx_eth",
+ .id = IXP4XX_ETH_NPEB,
+ .dev.platform_data = ixdp425_plat_eth,
+ }, {
+ .name = "ixp4xx_eth",
+ .id = IXP4XX_ETH_NPEC,
+ .dev.platform_data = ixdp425_plat_eth + 1,
+ },
+};
+
+
+static struct platform_device *devixp_pldev[] __initdata = {
+ &omixp_uart,
+ &omixp_flash_device[0],
+ &ixdp425_eth[0],
+ &ixdp425_eth[1],
+};
+
+static struct platform_device *mic256_pldev[] __initdata = {
+ &omixp_uart,
+ &omixp_flash_device[0],
+ &mic256_leds,
+ &ixdp425_eth[0],
+ &ixdp425_eth[1],
+};
+
+static struct platform_device *miccpt_pldev[] __initdata = {
+ &omixp_uart,
+ &omixp_flash_device[0],
+ &omixp_flash_device[1],
+ &ixdp425_eth[0],
+ &ixdp425_eth[1],
+};
+
+static void __init omixp_init(void)
+{
+ ixp4xx_sys_init();
+
+ /* 16MiB Boot Flash */
+ omixp_flash_resources[0].start = IXP4XX_EXP_BUS_BASE(0);
+ omixp_flash_resources[0].end = IXP4XX_EXP_BUS_END(0);
+
+ /* 32 MiB Data Flash */
+ omixp_flash_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
+ omixp_flash_resources[1].end = IXP4XX_EXP_BUS_END(2);
+
+ if (machine_is_devixp())
+ platform_add_devices(devixp_pldev, ARRAY_SIZE(devixp_pldev));
+ else if (machine_is_miccpt())
+ platform_add_devices(miccpt_pldev, ARRAY_SIZE(miccpt_pldev));
+ else if (machine_is_mic256())
+ platform_add_devices(mic256_pldev, ARRAY_SIZE(mic256_pldev));
+}
+
+#ifdef CONFIG_MACH_DEVIXP
+MACHINE_START(DEVIXP, "Omicron DEVIXP")
+ .atag_offset = 0x100,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .init_machine = omixp_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICCPT
+MACHINE_START(MICCPT, "Omicron MICCPT")
+ .atag_offset = 0x100,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .init_machine = omixp_init,
+#if defined(CONFIG_PCI)
+ .dma_zone_size = SZ_64M,
+#endif
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MIC256
+MACHINE_START(MIC256, "Omicron MIC256")
+ .atag_offset = 0x100,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .init_machine = omixp_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ixp4xx/vulcan-setup.c b/arch/arm/mach-ixp4xx/vulcan-setup.c
index 045336c833af..27e469ef4523 100644
--- a/arch/arm/mach-ixp4xx/vulcan-setup.c
+++ b/arch/arm/mach-ixp4xx/vulcan-setup.c
@@ -239,7 +239,7 @@ MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = vulcan_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
index 40b9fad800b8..b14144b967a7 100644
--- a/arch/arm/mach-ixp4xx/wg302v2-setup.c
+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -100,7 +100,7 @@ MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
- .boot_params = 0x0100,
+ .atag_offset = 0x100,
.init_machine = wg302v2_init,
#if defined(CONFIG_PCI)
.dma_zone_size = SZ_64M,
diff --git a/arch/arm/mach-kirkwood/Makefile.boot b/arch/arm/mach-kirkwood/Makefile.boot
index 67039c3e0c48..760a0efe7580 100644
--- a/arch/arm/mach-kirkwood/Makefile.boot
+++ b/arch/arm/mach-kirkwood/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-kirkwood/d2net_v2-setup.c b/arch/arm/mach-kirkwood/d2net_v2-setup.c
index 043cfd5e140b..f457e07a65f0 100644
--- a/arch/arm/mach-kirkwood/d2net_v2-setup.c
+++ b/arch/arm/mach-kirkwood/d2net_v2-setup.c
@@ -221,7 +221,7 @@ static void __init d2net_v2_init(void)
}
MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = d2net_v2_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
index bff04e04d679..ff4c21c1f923 100644
--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
+++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
@@ -97,7 +97,7 @@ subsys_initcall(db88f6281_pci_init);
MACHINE_START(DB88F6281_BP, "Marvell DB-88F6281-BP Development Board")
/* Maintainer: Saeed Bishara <saeed@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = db88f6281_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
index f14dfb8508c5..e4d199b2b1e8 100644
--- a/arch/arm/mach-kirkwood/dockstar-setup.c
+++ b/arch/arm/mach-kirkwood/dockstar-setup.c
@@ -102,7 +102,7 @@ static void __init dockstar_init(void)
}
MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = dockstar_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/guruplug-setup.c b/arch/arm/mach-kirkwood/guruplug-setup.c
index 41d1b40696a3..6c40f784b516 100644
--- a/arch/arm/mach-kirkwood/guruplug-setup.c
+++ b/arch/arm/mach-kirkwood/guruplug-setup.c
@@ -121,7 +121,7 @@ static void __init guruplug_init(void)
MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board")
/* Maintainer: Siddarth Gore <gores@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = guruplug_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/include/mach/debug-macro.S b/arch/arm/mach-kirkwood/include/mach/debug-macro.S
index db06ae437d08..f785d401a607 100644
--- a/arch/arm/mach-kirkwood/include/mach/debug-macro.S
+++ b/arch/arm/mach-kirkwood/include/mach/debug-macro.S
@@ -8,7 +8,7 @@
#include <mach/bridge-regs.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =KIRKWOOD_REGS_PHYS_BASE
ldr \rv, =KIRKWOOD_REGS_VIRT_BASE
orr \rp, \rp, #0x00012000
diff --git a/arch/arm/mach-kirkwood/include/mach/memory.h b/arch/arm/mach-kirkwood/include/mach/memory.h
deleted file mode 100644
index 4600b44e3ad3..000000000000
--- a/arch/arm/mach-kirkwood/include/mach/memory.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-kirkwood/irq.c b/arch/arm/mach-kirkwood/irq.c
index 05d193a25b25..c4c68e5b94f1 100644
--- a/arch/arm/mach-kirkwood/irq.c
+++ b/arch/arm/mach-kirkwood/irq.c
@@ -7,14 +7,13 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <mach/bridge-regs.h>
#include <plat/irq.h>
-#include <asm/gpio.h>
#include "common.h"
static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
diff --git a/arch/arm/mach-kirkwood/mpp.c b/arch/arm/mach-kirkwood/mpp.c
index b0a7d979a8ed..cc431fa22ccb 100644
--- a/arch/arm/mach-kirkwood/mpp.c
+++ b/arch/arm/mach-kirkwood/mpp.c
@@ -7,12 +7,11 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mbus.h>
#include <linux/io.h>
-#include <asm/gpio.h>
#include <mach/hardware.h>
#include <plat/mpp.h>
#include "common.h"
diff --git a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
index 00cca22eca6f..9a1e917352f7 100644
--- a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
+++ b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
@@ -163,7 +163,7 @@ subsys_initcall(mv88f6281gtw_ge_pci_init);
MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = mv88f6281gtw_ge_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
index 7cdab5776452..8849bcc7328e 100644
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -258,7 +258,7 @@ static void __init netspace_v2_init(void)
#ifdef CONFIG_MACH_NETSPACE_V2
MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = netspace_v2_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
@@ -269,7 +269,7 @@ MACHINE_END
#ifdef CONFIG_MACH_INETSPACE_V2
MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = netspace_v2_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
@@ -280,7 +280,7 @@ MACHINE_END
#ifdef CONFIG_MACH_NETSPACE_MAX_V2
MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = netspace_v2_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
index 6be627deb0fc..1ba12c4dff8f 100644
--- a/arch/arm/mach-kirkwood/netxbig_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
@@ -399,7 +399,7 @@ static void __init netxbig_v2_init(void)
#ifdef CONFIG_MACH_NET2BIG_V2
MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = netxbig_v2_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
@@ -410,7 +410,7 @@ MACHINE_END
#ifdef CONFIG_MACH_NET5BIG_V2
MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = netxbig_v2_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index f69beeff4450..5660ca6c3d88 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -214,7 +214,7 @@ subsys_initcall(openrd_pci_init);
#ifdef CONFIG_MACH_OPENRD_BASE
MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = openrd_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
@@ -226,7 +226,7 @@ MACHINE_END
#ifdef CONFIG_MACH_OPENRD_CLIENT
MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = openrd_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
@@ -238,7 +238,7 @@ MACHINE_END
#ifdef CONFIG_MACH_OPENRD_ULTIMATE
MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = openrd_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
index 75c6601b8d87..6663869773ab 100644
--- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
@@ -79,7 +79,7 @@ subsys_initcall(rd88f6192_pci_init);
MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
/* Maintainer: Saeed Bishara <saeed@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = rd88f6192_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
index 0f75494d5902..66b3c05e37a6 100644
--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c
@@ -115,7 +115,7 @@ subsys_initcall(rd88f6281_pci_init);
MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
/* Maintainer: Saeed Bishara <saeed@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = rd88f6281_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
index 17de0bf53c08..8b102d62e82c 100644
--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
+++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
@@ -138,7 +138,7 @@ static void __init sheevaplug_init(void)
#ifdef CONFIG_MACH_SHEEVAPLUG
MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
/* Maintainer: shadi Ammouri <shadi@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = sheevaplug_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
@@ -149,7 +149,7 @@ MACHINE_END
#ifdef CONFIG_MACH_ESATA_SHEEVAPLUG
MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = sheevaplug_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/t5325-setup.c b/arch/arm/mach-kirkwood/t5325-setup.c
index e6b9b1b22a35..ea104fb5ec3d 100644
--- a/arch/arm/mach-kirkwood/t5325-setup.c
+++ b/arch/arm/mach-kirkwood/t5325-setup.c
@@ -201,7 +201,7 @@ subsys_initcall(hp_t5325_pci_init);
MACHINE_START(T5325, "HP t5325 Thin Client")
/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = hp_t5325_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c
index 68f32f2bf552..262c034836d4 100644
--- a/arch/arm/mach-kirkwood/ts219-setup.c
+++ b/arch/arm/mach-kirkwood/ts219-setup.c
@@ -132,7 +132,7 @@ subsys_initcall(ts219_pci_init);
MACHINE_START(TS219, "QNAP TS-119/TS-219")
/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = qnap_ts219_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c
index d5d009970705..b68f5b4a9ec8 100644
--- a/arch/arm/mach-kirkwood/ts41x-setup.c
+++ b/arch/arm/mach-kirkwood/ts41x-setup.c
@@ -176,7 +176,7 @@ subsys_initcall(ts41x_pci_init);
MACHINE_START(TS41X, "QNAP TS-41x")
/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = qnap_ts41x_init,
.map_io = kirkwood_map_io,
.init_early = kirkwood_init_early,
diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
index 7e3e8160ed30..853efd9133c6 100644
--- a/arch/arm/mach-ks8695/Makefile
+++ b/arch/arm/mach-ks8695/Makefile
@@ -3,7 +3,7 @@
# Makefile for KS8695 architecture support
#
-obj-y := cpu.o irq.o time.o gpio.o devices.o
+obj-y := cpu.o irq.o time.o devices.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/mach-ks8695/Makefile.boot b/arch/arm/mach-ks8695/Makefile.boot
index 48eb2cb3ac77..c9b0bebcf237 100644
--- a/arch/arm/mach-ks8695/Makefile.boot
+++ b/arch/arm/mach-ks8695/Makefile.boot
@@ -3,6 +3,6 @@
# PARAMS_PHYS must be within 4MB of ZRELADDR
# INITRD_PHYS must be in RAM
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c
index 3ca4f8e6f54f..a91f99d265aa 100644
--- a/arch/arm/mach-ks8695/board-acs5k.c
+++ b/arch/arm/mach-ks8695/board-acs5k.c
@@ -10,7 +10,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
@@ -34,7 +34,7 @@
#include <asm/mach/irq.h>
#include <mach/devices.h>
-#include <mach/gpio.h>
+#include <mach/gpio-ks8695.h>
#include "generic.h"
@@ -223,7 +223,7 @@ static void __init acs5k_init(void)
MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board")
/* Maintainer: Simtec Electronics. */
- .boot_params = KS8695_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = ks8695_map_io,
.init_irq = ks8695_init_irq,
.init_machine = acs5k_init,
diff --git a/arch/arm/mach-ks8695/board-dsm320.c b/arch/arm/mach-ks8695/board-dsm320.c
index 1338cb3e9827..d24bcef2e2dd 100644
--- a/arch/arm/mach-ks8695/board-dsm320.c
+++ b/arch/arm/mach-ks8695/board-dsm320.c
@@ -10,7 +10,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
@@ -29,7 +29,7 @@
#include <asm/mach/irq.h>
#include <mach/devices.h>
-#include <mach/gpio.h>
+#include <mach/gpio-ks8695.h>
#include "generic.h"
@@ -121,7 +121,7 @@ static void __init dsm320_init(void)
MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player")
/* Maintainer: Simtec Electronics. */
- .boot_params = KS8695_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = ks8695_map_io,
.init_irq = ks8695_init_irq,
.init_machine = dsm320_init,
diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c
index e2e3cba8dcdb..16c95657f8fd 100644
--- a/arch/arm/mach-ks8695/board-micrel.c
+++ b/arch/arm/mach-ks8695/board-micrel.c
@@ -5,7 +5,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
@@ -18,7 +18,7 @@
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
-#include <mach/gpio.h>
+#include <mach/gpio-ks8695.h>
#include <mach/devices.h>
#include "generic.h"
@@ -53,7 +53,7 @@ static void __init micrel_init(void)
MACHINE_START(KS8695, "KS8695 Centaur Development Board")
/* Maintainer: Micrel Semiconductor Inc. */
- .boot_params = KS8695_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = ks8695_map_io,
.init_irq = ks8695_init_irq,
.init_machine = micrel_init,
diff --git a/arch/arm/mach-ks8695/devices.c b/arch/arm/mach-ks8695/devices.c
index b89fb6d46ccc..73bd63812878 100644
--- a/arch/arm/mach-ks8695/devices.c
+++ b/arch/arm/mach-ks8695/devices.c
@@ -20,6 +20,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <mach/irqs.h>
diff --git a/arch/arm/mach-ks8695/include/mach/debug-macro.S b/arch/arm/mach-ks8695/include/mach/debug-macro.S
index bf516adf1925..a79e48981202 100644
--- a/arch/arm/mach-ks8695/include/mach/debug-macro.S
+++ b/arch/arm/mach-ks8695/include/mach/debug-macro.S
@@ -14,7 +14,7 @@
#include <mach/hardware.h>
#include <mach/regs-uart.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =KS8695_UART_PA @ physical base address
ldr \rv, =KS8695_UART_VA @ virtual base address
.endm
diff --git a/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h b/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h
new file mode 100644
index 000000000000..6eb034d60325
--- /dev/null
+++ b/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * 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 __MACH_KS8659_GPIO_H
+#define __MACH_KS8659_GPIO_H
+
+#include <linux/kernel.h>
+
+#define KS8695_GPIO_0 0
+#define KS8695_GPIO_1 1
+#define KS8695_GPIO_2 2
+#define KS8695_GPIO_3 3
+#define KS8695_GPIO_4 4
+#define KS8695_GPIO_5 5
+#define KS8695_GPIO_6 6
+#define KS8695_GPIO_7 7
+#define KS8695_GPIO_8 8
+#define KS8695_GPIO_9 9
+#define KS8695_GPIO_10 10
+#define KS8695_GPIO_11 11
+#define KS8695_GPIO_12 12
+#define KS8695_GPIO_13 13
+#define KS8695_GPIO_14 14
+#define KS8695_GPIO_15 15
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
+
+/* Register the GPIOs */
+extern void ks8695_register_gpios(void);
+
+#endif /* __MACH_KS8659_GPIO_H */
diff --git a/arch/arm/mach-ks8695/include/mach/gpio.h b/arch/arm/mach-ks8695/include/mach/gpio.h
index 86312d476bc6..f5fda36e4512 100644
--- a/arch/arm/mach-ks8695/include/mach/gpio.h
+++ b/arch/arm/mach-ks8695/include/mach/gpio.h
@@ -11,47 +11,9 @@
#ifndef __ASM_ARCH_GPIO_H_
#define __ASM_ARCH_GPIO_H_
-#include <linux/kernel.h>
-
-#define KS8695_GPIO_0 0
-#define KS8695_GPIO_1 1
-#define KS8695_GPIO_2 2
-#define KS8695_GPIO_3 3
-#define KS8695_GPIO_4 4
-#define KS8695_GPIO_5 5
-#define KS8695_GPIO_6 6
-#define KS8695_GPIO_7 7
-#define KS8695_GPIO_8 8
-#define KS8695_GPIO_9 9
-#define KS8695_GPIO_10 10
-#define KS8695_GPIO_11 11
-#define KS8695_GPIO_12 12
-#define KS8695_GPIO_13 13
-#define KS8695_GPIO_14 14
-#define KS8695_GPIO_15 15
-
-/*
- * Configure GPIO pin as external interrupt source.
- */
-extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
-
/*
* Map IRQ number to GPIO line.
*/
extern int irq_to_gpio(unsigned int irq);
-#include <asm-generic/gpio.h>
-
-/* If it turns out that we need to optimise GPIO access for the
- * Micrel's GPIOs, then these can be changed to check their argument
- * directly as static inlines. However for now it's probably not
- * worthwhile.
- */
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_to_irq __gpio_to_irq
-
-/* Register the GPIOs */
-extern void ks8695_register_gpios(void);
-
#endif
diff --git a/arch/arm/mach-ks8695/leds.c b/arch/arm/mach-ks8695/leds.c
index 184ef74e4bee..d6f6502ac9b5 100644
--- a/arch/arm/mach-ks8695/leds.c
+++ b/arch/arm/mach-ks8695/leds.c
@@ -7,14 +7,14 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/gpio.h>
#include <asm/leds.h>
#include <mach/devices.h>
-#include <mach/gpio.h>
static inline void ks8695_led_on(unsigned int led)
diff --git a/arch/arm/mach-l7200/include/mach/debug-macro.S b/arch/arm/mach-l7200/include/mach/debug-macro.S
index b0a2db77d392..0b4e760159b9 100644
--- a/arch/arm/mach-l7200/include/mach/debug-macro.S
+++ b/arch/arm/mach-l7200/include/mach/debug-macro.S
@@ -14,7 +14,7 @@
.equ io_virt, IO_BASE
.equ io_phys, IO_START
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00044000 @ UART1
@ mov \rp, #0x00045000 @ UART2
add \rv, \rp, #io_virt @ virtual address
diff --git a/arch/arm/mach-lpc32xx/Makefile b/arch/arm/mach-lpc32xx/Makefile
index a5fc5d0eeaeb..f5db805ab958 100644
--- a/arch/arm/mach-lpc32xx/Makefile
+++ b/arch/arm/mach-lpc32xx/Makefile
@@ -3,6 +3,6 @@
#
obj-y := timer.o irq.o common.o serial.o clock.o
-obj-y += gpiolib.o pm.o suspend.o
+obj-y += pm.o suspend.o
obj-y += phy3250.o
diff --git a/arch/arm/mach-lpc32xx/Makefile.boot b/arch/arm/mach-lpc32xx/Makefile.boot
index b796b41ebf8f..2cfe0ee635c5 100644
--- a/arch/arm/mach-lpc32xx/Makefile.boot
+++ b/arch/arm/mach-lpc32xx/Makefile.boot
@@ -1,4 +1,4 @@
- zreladdr-y := 0x80008000
+ zreladdr-y += 0x80008000
params_phys-y := 0x80000100
initrd_phys-y := 0x82000000
diff --git a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
index 629e744aeb9e..351bd6c84909 100644
--- a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
@@ -20,7 +20,7 @@
* Debug output is hardcoded to standard UART 5
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldreq \rp, =0x40090000
ldrne \rv, =0xF4090000
.endm
diff --git a/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h b/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h
new file mode 100644
index 000000000000..1816e22a3479
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h
@@ -0,0 +1,50 @@
+/*
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_GPIO_LPC32XX_H
+#define __MACH_GPIO_LPC32XX_H
+
+/*
+ * Note!
+ * Muxed GP pins need to be setup to the GP state in the board level
+ * code prior to using this driver.
+ * GPI pins : 28xP3 group
+ * GPO pins : 24xP3 group
+ * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group
+ */
+
+#define LPC32XX_GPIO_P0_MAX 8
+#define LPC32XX_GPIO_P1_MAX 24
+#define LPC32XX_GPIO_P2_MAX 13
+#define LPC32XX_GPIO_P3_MAX 6
+#define LPC32XX_GPI_P3_MAX 28
+#define LPC32XX_GPO_P3_MAX 24
+
+#define LPC32XX_GPIO_P0_GRP 0
+#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
+#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
+#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
+#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
+#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
+
+/*
+ * A specific GPIO can be selected with this macro
+ * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
+ * See the LPC32x0 User's guide for GPIO group numbers
+ */
+#define LPC32XX_GPIO(x, y) ((x) + (y))
+
+#endif /* __MACH_GPIO_LPC32XX_H */
diff --git a/arch/arm/mach-lpc32xx/include/mach/gpio.h b/arch/arm/mach-lpc32xx/include/mach/gpio.h
index 67d03da1eee9..40a8c178f10d 100644
--- a/arch/arm/mach-lpc32xx/include/mach/gpio.h
+++ b/arch/arm/mach-lpc32xx/include/mach/gpio.h
@@ -1,74 +1 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/gpio.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-/*
- * Note!
- * Muxed GP pins need to be setup to the GP state in the board level
- * code prior to using this driver.
- * GPI pins : 28xP3 group
- * GPO pins : 24xP3 group
- * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group
- */
-
-#define LPC32XX_GPIO_P0_MAX 8
-#define LPC32XX_GPIO_P1_MAX 24
-#define LPC32XX_GPIO_P2_MAX 13
-#define LPC32XX_GPIO_P3_MAX 6
-#define LPC32XX_GPI_P3_MAX 28
-#define LPC32XX_GPO_P3_MAX 24
-
-#define LPC32XX_GPIO_P0_GRP 0
-#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
-#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
-#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
-#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
-#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
-
-/*
- * A specific GPIO can be selected with this macro
- * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
- * See the LPC32x0 User's guide for GPIO group numbers
- */
-#define LPC32XX_GPIO(x, y) ((x) + (y))
-
-static inline int gpio_get_value(unsigned gpio)
-{
- return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
- __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
- return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
- return __gpio_to_irq(gpio);
-}
-
-#endif
+/* empty */
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
index 7993b096778e..6d2f0d1b9373 100644
--- a/arch/arm/mach-lpc32xx/phy3250.c
+++ b/arch/arm/mach-lpc32xx/phy3250.c
@@ -37,6 +37,7 @@
#include <mach/hardware.h>
#include <mach/platform.h>
+#include <mach/gpio-lpc32xx.h>
#include "common.h"
/*
@@ -382,7 +383,7 @@ arch_initcall(lpc32xx_display_uid);
MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
/* Maintainer: Kevin Wells, NXP Semiconductors */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.map_io = lpc32xx_map_io,
.init_irq = lpc32xx_init_irq,
.timer = &lpc32xx_timer,
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 56ef5f6c8116..323d4c9e9f44 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -77,7 +77,7 @@ config MACH_TETON_BGA
Say 'Y' here if you want to support the Marvell PXA168-based
Teton BGA Development Board.
-config MACH_SHEEVAD
+config MACH_GPLUGD
bool "Marvell's PXA168 GuruPlug Display (gplugD) Board"
select CPU_PXA168
help
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index b0ac942327aa..8f948f981646 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -19,4 +19,4 @@ obj-$(CONFIG_MACH_BROWNSTONE) += brownstone.o
obj-$(CONFIG_MACH_FLINT) += flint.o
obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
obj-$(CONFIG_MACH_TETON_BGA) += teton_bga.o
-obj-$(CONFIG_MACH_SHEEVAD) += gplugd.o
+obj-$(CONFIG_MACH_GPLUGD) += gplugd.o
diff --git a/arch/arm/mach-mmp/Makefile.boot b/arch/arm/mach-mmp/Makefile.boot
index 574a4aa8321a..5edf03e2beed 100644
--- a/arch/arm/mach-mmp/Makefile.boot
+++ b/arch/arm/mach-mmp/Makefile.boot
@@ -1 +1 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 06b5fa853c93..06b5ad774604 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -8,7 +8,7 @@
* it under the terms of the GNU General Public License version 2 as
* publishhed by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
@@ -17,13 +17,13 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/interrupt.h>
+#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/addr-map.h>
#include <mach/mfp-pxa168.h>
#include <mach/pxa168.h>
-#include <mach/gpio.h>
#include <video/pxa168fb.h>
#include <linux/input.h>
#include <plat/pxa27x_keypad.h>
@@ -160,7 +160,7 @@ static struct mtd_partition aspenite_nand_partitions[] = {
}, {
.name = "filesystem",
.offset = MTDPART_OFS_APPEND,
- .size = SZ_48M,
+ .size = SZ_32M + SZ_16M,
.mask_flags = 0,
}
};
diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c
index c79162a50f28..e411252e3d39 100644
--- a/arch/arm/mach-mmp/brownstone.c
+++ b/arch/arm/mach-mmp/brownstone.c
@@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/gpio.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/max8649.h>
#include <linux/regulator/fixed.h>
diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h
index 3143e994e672..149b30cd1469 100644
--- a/arch/arm/mach-mmp/clock.h
+++ b/arch/arm/mach-mmp/clock.h
@@ -30,7 +30,7 @@ extern struct clkops apmu_clk_ops;
#define APBC_CLK(_name, _reg, _fnclksel, _rate) \
struct clk clk_##_name = { \
- .clk_rst = (void __iomem *)APBC_##_reg, \
+ .clk_rst = APBC_##_reg, \
.fnclksel = _fnclksel, \
.rate = _rate, \
.ops = &apbc_clk_ops, \
@@ -38,7 +38,7 @@ struct clk clk_##_name = { \
#define APBC_CLK_OPS(_name, _reg, _fnclksel, _rate, _ops) \
struct clk clk_##_name = { \
- .clk_rst = (void __iomem *)APBC_##_reg, \
+ .clk_rst = APBC_##_reg, \
.fnclksel = _fnclksel, \
.rate = _rate, \
.ops = _ops, \
@@ -46,7 +46,7 @@ struct clk clk_##_name = { \
#define APMU_CLK(_name, _reg, _eval, _rate) \
struct clk clk_##_name = { \
- .clk_rst = (void __iomem *)APMU_##_reg, \
+ .clk_rst = APMU_##_reg, \
.enable_val = _eval, \
.rate = _rate, \
.ops = &apmu_clk_ops, \
@@ -54,7 +54,7 @@ struct clk clk_##_name = { \
#define APMU_CLK_OPS(_name, _reg, _eval, _rate, _ops) \
struct clk clk_##_name = { \
- .clk_rst = (void __iomem *)APMU_##_reg, \
+ .clk_rst = APMU_##_reg, \
.enable_val = _eval, \
.rate = _rate, \
.ops = _ops, \
diff --git a/arch/arm/mach-mmp/common.c b/arch/arm/mach-mmp/common.c
index 0ec0ca80bb3e..5720674739f0 100644
--- a/arch/arm/mach-mmp/common.c
+++ b/arch/arm/mach-mmp/common.c
@@ -27,12 +27,12 @@ EXPORT_SYMBOL(mmp_chip_id);
static struct map_desc standard_io_desc[] __initdata = {
{
.pfn = __phys_to_pfn(APB_PHYS_BASE),
- .virtual = APB_VIRT_BASE,
+ .virtual = (unsigned long)APB_VIRT_BASE,
.length = APB_PHYS_SIZE,
.type = MT_DEVICE,
}, {
.pfn = __phys_to_pfn(AXI_PHYS_BASE),
- .virtual = AXI_VIRT_BASE,
+ .virtual = (unsigned long)AXI_VIRT_BASE,
.length = AXI_PHYS_SIZE,
.type = MT_DEVICE,
},
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index 98e25d9aaab6..69156568bc41 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -9,11 +9,11 @@
*/
#include <linux/init.h>
+#include <linux/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
-#include <mach/gpio.h>
#include <mach/pxa168.h>
#include <mach/mfp-pxa168.h>
@@ -188,7 +188,7 @@ static void __init gplugd_init(void)
pxa168_add_eth(&gplugd_eth_platform_data);
}
-MACHINE_START(SHEEVAD, "PXA168-based GuruPlug Display (gplugD) Platform")
+MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform")
.map_io = mmp_map_io,
.nr_irqs = IRQ_BOARD_START,
.init_irq = pxa168_init_irq,
diff --git a/arch/arm/mach-mmp/include/mach/addr-map.h b/arch/arm/mach-mmp/include/mach/addr-map.h
index 3254089a644d..3e404acd6ff4 100644
--- a/arch/arm/mach-mmp/include/mach/addr-map.h
+++ b/arch/arm/mach-mmp/include/mach/addr-map.h
@@ -11,6 +11,12 @@
#ifndef __ASM_MACH_ADDR_MAP_H
#define __ASM_MACH_ADDR_MAP_H
+#ifndef __ASSEMBLER__
+#define IOMEM(x) ((void __iomem *)(x))
+#else
+#define IOMEM(x) (x)
+#endif
+
/* APB - Application Subsystem Peripheral Bus
*
* NOTE: the DMA controller registers are actually on the AXI fabric #1
@@ -18,11 +24,11 @@
* peripherals on APB, let's count it into the ABP mapping area.
*/
#define APB_PHYS_BASE 0xd4000000
-#define APB_VIRT_BASE 0xfe000000
+#define APB_VIRT_BASE IOMEM(0xfe000000)
#define APB_PHYS_SIZE 0x00200000
#define AXI_PHYS_BASE 0xd4200000
-#define AXI_VIRT_BASE 0xfe200000
+#define AXI_VIRT_BASE IOMEM(0xfe200000)
#define AXI_PHYS_SIZE 0x00200000
/* Static Memory Controller - Chip Select 0 and 1 */
diff --git a/arch/arm/mach-mmp/include/mach/debug-macro.S b/arch/arm/mach-mmp/include/mach/debug-macro.S
index 7e2ebd3efc7c..b6f14d203c25 100644
--- a/arch/arm/mach-mmp/include/mach/debug-macro.S
+++ b/arch/arm/mach-mmp/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
#include <mach/addr-map.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =APB_PHYS_BASE @ physical
ldr \rv, =APB_VIRT_BASE @ virtual
orr \rp, \rp, #0x00017000
diff --git a/arch/arm/mach-mmp/include/mach/gpio-pxa.h b/arch/arm/mach-mmp/include/mach/gpio-pxa.h
new file mode 100644
index 000000000000..d14eeaf16322
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/gpio-pxa.h
@@ -0,0 +1,30 @@
+#ifndef __ASM_MACH_GPIO_PXA_H
+#define __ASM_MACH_GPIO_PXA_H
+
+#include <mach/addr-map.h>
+#include <mach/irqs.h>
+
+#define GPIO_REGS_VIRT (APB_VIRT_BASE + 0x19000)
+
+#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x) (GPIO_REGS_VIRT + (x))
+
+#define NR_BUILTIN_GPIO IRQ_GPIO_NUM
+
+#define gpio_to_bank(gpio) ((gpio) >> 5)
+
+/* NOTE: these macros are defined here to make optimization of
+ * gpio_{get,set}_value() to work when 'gpio' is a constant.
+ * Usage of these macros otherwise is no longer recommended,
+ * use generic GPIO API whenever possible.
+ */
+#define GPIO_bit(gpio) (1 << ((gpio) & 0x1f))
+
+#define GPLR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
+#define GPDR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
+#define GPSR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
+#define GPCR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
+
+#include <plat/gpio-pxa.h>
+
+#endif /* __ASM_MACH_GPIO_PXA_H */
diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h
index 7bfb827f3fe3..681262359d1c 100644
--- a/arch/arm/mach-mmp/include/mach/gpio.h
+++ b/arch/arm/mach-mmp/include/mach/gpio.h
@@ -1,36 +1,13 @@
#ifndef __ASM_MACH_GPIO_H
#define __ASM_MACH_GPIO_H
-#include <mach/addr-map.h>
-#include <mach/irqs.h>
#include <asm-generic/gpio.h>
-#define GPIO_REGS_VIRT (APB_VIRT_BASE + 0x19000)
-
-#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x) (*((volatile u32 *)(GPIO_REGS_VIRT + (x))))
-
-#define NR_BUILTIN_GPIO IRQ_GPIO_NUM
-
-#define gpio_to_bank(gpio) ((gpio) >> 5)
#define gpio_to_irq(gpio) (IRQ_GPIO_START + (gpio))
#define irq_to_gpio(irq) ((irq) - IRQ_GPIO_START)
-
#define __gpio_is_inverted(gpio) (0)
#define __gpio_is_occupied(gpio) (0)
-/* NOTE: these macros are defined here to make optimization of
- * gpio_{get,set}_value() to work when 'gpio' is a constant.
- * Usage of these macros otherwise is no longer recommended,
- * use generic GPIO API whenever possible.
- */
-#define GPIO_bit(gpio) (1 << ((gpio) & 0x1f))
-
-#define GPLR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
-#define GPDR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
-#define GPSR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
-#define GPCR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
-
#include <plat/gpio.h>
#endif /* __ASM_MACH_GPIO_H */
diff --git a/arch/arm/mach-mmp/include/mach/memory.h b/arch/arm/mach-mmp/include/mach/memory.h
deleted file mode 100644
index d68b50a2d6a0..000000000000
--- a/arch/arm/mach-mmp/include/mach/memory.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * linux/arch/arm/mach-mmp/include/mach/memory.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_MACH_MEMORY_H
-#define __ASM_MACH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif /* __ASM_MACH_MEMORY_H */
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index 7f005843a707..7fb568d2845b 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -35,6 +35,13 @@ extern struct pxa_device_desc pxa168_device_fb;
extern struct pxa_device_desc pxa168_device_keypad;
extern struct pxa_device_desc pxa168_device_eth;
+struct pxa168_usb_pdata {
+ /* If NULL, default phy init routine for PXA168 would be called */
+ int (*phy_init)(void __iomem *usb_phy_reg_base);
+};
+/* pdata can be NULL */
+int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata);
+
static inline int pxa168_add_uart(int id)
{
struct pxa_device_desc *d = NULL;
diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
index 5d6421d63254..8bfac6612623 100644
--- a/arch/arm/mach-mmp/jasper.c
+++ b/arch/arm/mach-mmp/jasper.c
@@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/gpio.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/max8649.h>
#include <linux/mfd/max8925.h>
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index 079c18861d5c..7a7e8e4dde41 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -9,7 +9,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -25,7 +24,7 @@
#include <mach/irqs.h>
#include <mach/dma.h>
#include <mach/mfp.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
#include <mach/devices.h>
#include <mach/mmp2.h>
@@ -87,7 +86,8 @@ static struct mfp_addr_map mmp2_addr_map[] __initdata = {
void mmp2_clear_pmic_int(void)
{
- unsigned long mfpr_pmic, data;
+ void __iomem *mfpr_pmic;
+ unsigned long data;
mfpr_pmic = APB_VIRT_BASE + 0x1e000 + 0x2c4;
data = __raw_readl(mfpr_pmic);
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index 0156f535dae7..76ca15c00e45 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -7,7 +7,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -21,10 +20,13 @@
#include <mach/regs-apbc.h>
#include <mach/regs-apmu.h>
#include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
#include <mach/dma.h>
#include <mach/devices.h>
#include <mach/mfp.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <mach/pxa168.h>
#include "common.h"
#include "clock.h"
@@ -83,6 +85,7 @@ static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
static APMU_CLK(nand, NAND, 0x19b, 156000000);
static APMU_CLK(lcd, LCD, 0x7f, 312000000);
static APMU_CLK(eth, ETH, 0x09, 0);
+static APMU_CLK(usb, USB, 0x12, 0);
/* device and clock bindings */
static struct clk_lookup pxa168_clkregs[] = {
@@ -104,6 +107,7 @@ static struct clk_lookup pxa168_clkregs[] = {
INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"),
+ INIT_CLKREG(&clk_usb, "pxa168-ehci", "PXA168-USBCLK"),
};
static int __init pxa168_init(void)
@@ -169,3 +173,44 @@ PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61);
PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c);
PXA168_DEVICE(eth, "pxa168-eth", -1, MFU, 0xc0800000, 0x0fff);
+
+struct resource pxa168_usb_host_resources[] = {
+ /* USB Host conroller register base */
+ [0] = {
+ .start = 0xd4209000,
+ .end = 0xd4209000 + 0x200,
+ .flags = IORESOURCE_MEM,
+ .name = "pxa168-usb-host",
+ },
+ /* USB PHY register base */
+ [1] = {
+ .start = 0xd4206000,
+ .end = 0xd4206000 + 0xff,
+ .flags = IORESOURCE_MEM,
+ .name = "pxa168-usb-phy",
+ },
+ [2] = {
+ .start = IRQ_PXA168_USB2,
+ .end = IRQ_PXA168_USB2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 pxa168_usb_host_dmamask = DMA_BIT_MASK(32);
+struct platform_device pxa168_device_usb_host = {
+ .name = "pxa168-ehci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &pxa168_usb_host_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+
+ .num_resources = ARRAY_SIZE(pxa168_usb_host_resources),
+ .resource = pxa168_usb_host_resources,
+};
+
+int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata)
+{
+ pxa168_device_usb_host.dev.platform_data = pdata;
+ return platform_device_register(&pxa168_device_usb_host);
+}
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index 1464607aa60d..4ebbfbba39fc 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -7,7 +7,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -20,7 +19,7 @@
#include <mach/regs-apmu.h>
#include <mach/cputype.h>
#include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
#include <mach/dma.h>
#include <mach/mfp.h>
#include <mach/devices.h>
diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c
index c296b75c4453..eb5be879fd8c 100644
--- a/arch/arm/mach-mmp/tavorevb.c
+++ b/arch/arm/mach-mmp/tavorevb.c
@@ -7,18 +7,18 @@
* it under the terms of the GNU General Public License version 2 as
* publishhed by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/smc91x.h>
+#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/addr-map.h>
#include <mach/mfp-pxa910.h>
#include <mach/pxa910.h>
-#include <mach/gpio.h>
#include "common.h"
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index 6bd37a27e5fc..176515a76989 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -93,7 +93,7 @@ static struct mtd_partition ttc_dkb_onenand_partitions[] = {
}, {
.name = "filesystem",
.offset = MTDPART_OFS_APPEND,
- .size = SZ_48M,
+ .size = SZ_32M + SZ_16M,
.mask_flags = 0,
}
};
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 24dfbf8c07c4..9b803a578b4d 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x10008000
+ zreladdr-y += 0x10008000
params_phys-y := 0x10000100
initrd_phys-y := 0x10800000
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index 18a3c97bc863..a60ab6d04ec5 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -78,8 +78,8 @@ static void __init halibut_init(void)
platform_add_devices(devices, ARRAY_SIZE(devices));
}
-static void __init halibut_fixup(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+static void __init halibut_fixup(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
mi->nr_banks=1;
mi->bank[0].start = PHYS_OFFSET;
@@ -93,7 +93,7 @@ static void __init halibut_map_io(void)
}
MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
- .boot_params = 0x10000100,
+ .atag_offset = 0x100,
.fixup = halibut_fixup,
.map_io = halibut_map_io,
.init_irq = halibut_init_irq,
diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c
index 7a9a03eb189c..5a4882fc6f7a 100644
--- a/arch/arm/mach-msm/board-mahimahi.c
+++ b/arch/arm/mach-msm/board-mahimahi.c
@@ -53,8 +53,8 @@ static void __init mahimahi_init(void)
platform_add_devices(devices, ARRAY_SIZE(devices));
}
-static void __init mahimahi_fixup(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+static void __init mahimahi_fixup(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
mi->nr_banks = 2;
mi->bank[0].start = PHYS_OFFSET;
@@ -74,7 +74,7 @@ static void __init mahimahi_map_io(void)
extern struct sys_timer msm_timer;
MACHINE_START(MAHIMAHI, "mahimahi")
- .boot_params = 0x20000100,
+ .atag_offset = 0x100,
.fixup = mahimahi_fixup,
.map_io = mahimahi_map_io,
.init_irq = msm_init_irq,
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index c03f269e2e4b..6d84ee740df4 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -13,7 +13,7 @@
* GNU General Public License for more details.
*
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -34,7 +34,6 @@
#include <mach/vreg.h>
#include <mach/mpp.h>
-#include <mach/gpio.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
@@ -130,7 +129,7 @@ static void __init msm7x2x_map_io(void)
}
MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = msm7x2x_map_io,
.init_irq = msm7x2x_init_irq,
.init_machine = msm7x2x_init,
@@ -138,7 +137,7 @@ MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
MACHINE_END
MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = msm7x2x_map_io,
.init_irq = msm7x2x_init_irq,
.init_machine = msm7x2x_init,
@@ -146,7 +145,7 @@ MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
MACHINE_END
MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = msm7x2x_map_io,
.init_irq = msm7x2x_init_irq,
.init_machine = msm7x2x_init,
@@ -154,7 +153,7 @@ MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
MACHINE_END
MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA")
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = msm7x2x_map_io,
.init_irq = msm7x2x_init_irq,
.init_machine = msm7x2x_init,
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index b7a84966b711..71de5062c71e 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -14,7 +14,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/gpio.h>
@@ -24,13 +24,13 @@
#include <linux/smsc911x.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/clkdev.h>
+#include <linux/memblock.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/memory.h>
#include <asm/setup.h>
-#include <mach/gpio.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
#include <mach/dma.h>
@@ -42,6 +42,21 @@
extern struct sys_timer msm_timer;
+static void __init msm7x30_fixup(struct machine_desc *desc, struct tag *tag,
+ char **cmdline, struct meminfo *mi)
+{
+ for (; tag->hdr.size; tag = tag_next(tag))
+ if (tag->hdr.tag == ATAG_MEM && tag->u.mem.start == 0x200000) {
+ tag->u.mem.start = 0;
+ tag->u.mem.size += SZ_2M;
+ }
+}
+
+static void __init msm7x30_reserve(void)
+{
+ memblock_remove(0x0, SZ_2M);
+}
+
static int hsusb_phy_init_seq[] = {
0x30, 0x32, /* Enable and set Pre-Emphasis Depth to 20% */
0x02, 0x36, /* Disable CDR Auto Reset feature */
@@ -106,7 +121,9 @@ static void __init msm7x30_map_io(void)
}
MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
+ .fixup = msm7x30_fixup,
+ .reserve = msm7x30_reserve,
.map_io = msm7x30_map_io,
.init_irq = msm7x30_init_irq,
.init_machine = msm7x30_init,
@@ -114,7 +131,9 @@ MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
MACHINE_END
MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
+ .fixup = msm7x30_fixup,
+ .reserve = msm7x30_reserve,
.map_io = msm7x30_map_io,
.init_irq = msm7x30_init_irq,
.init_machine = msm7x30_init,
@@ -122,7 +141,9 @@ MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
MACHINE_END
MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
+ .fixup = msm7x30_fixup,
+ .reserve = msm7x30_reserve,
.map_io = msm7x30_map_io,
.init_irq = msm7x30_init_irq,
.init_machine = msm7x30_init,
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 35c7ceeb3f29..b04468e7d00e 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -20,16 +20,34 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/clkdev.h>
+#include <linux/memblock.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
+#include <asm/setup.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
#include "devices.h"
+static void __init msm8960_fixup(struct machine_desc *desc, struct tag *tag,
+ char **cmdline, struct meminfo *mi)
+{
+ for (; tag->hdr.size; tag = tag_next(tag))
+ if (tag->hdr.tag == ATAG_MEM &&
+ tag->u.mem.start == 0x40200000) {
+ tag->u.mem.start = 0x40000000;
+ tag->u.mem.size += SZ_2M;
+ }
+}
+
+static void __init msm8960_reserve(void)
+{
+ memblock_remove(0x40000000, SZ_2M);
+}
+
static void __init msm8960_map_io(void)
{
msm_map_msm8960_io();
@@ -76,6 +94,8 @@ static void __init msm8960_rumi3_init(void)
}
MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
+ .fixup = msm8960_fixup,
+ .reserve = msm8960_reserve,
.map_io = msm8960_map_io,
.init_irq = msm8960_init_irq,
.timer = &msm_timer,
@@ -83,6 +103,8 @@ MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
MACHINE_END
MACHINE_START(MSM8960_RUMI3, "QCT MSM8960 RUMI3")
+ .fixup = msm8960_fixup,
+ .reserve = msm8960_reserve,
.map_io = msm8960_map_io,
.init_irq = msm8960_init_irq,
.timer = &msm_timer,
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 1163b6fd05d2..cf38e2284fa9 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -8,26 +8,41 @@
* but WITHOUT 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/kernel.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/memblock.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
+#include <asm/setup.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
+static void __init msm8x60_fixup(struct machine_desc *desc, struct tag *tag,
+ char **cmdline, struct meminfo *mi)
+{
+ for (; tag->hdr.size; tag = tag_next(tag))
+ if (tag->hdr.tag == ATAG_MEM &&
+ tag->u.mem.start == 0x40200000) {
+ tag->u.mem.start = 0x40000000;
+ tag->u.mem.size += SZ_2M;
+ }
+}
+
+static void __init msm8x60_reserve(void)
+{
+ memblock_remove(0x40000000, SZ_2M);
+}
static void __init msm8x60_map_io(void)
{
@@ -36,8 +51,6 @@ static void __init msm8x60_map_io(void)
static void __init msm8x60_init_irq(void)
{
- unsigned int i;
-
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
(void *)MSM_QGIC_CPU_BASE);
@@ -49,22 +62,50 @@ static void __init msm8x60_init_irq(void)
*/
if (!machine_is_msm8x60_sim())
writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-
- /* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
- * as they are configured as level, which does not play nice with
- * handle_percpu_irq.
- */
- for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
- if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
- irq_set_handler(i, handle_percpu_irq);
- }
}
static void __init msm8x60_init(void)
{
}
+#ifdef CONFIG_OF
+static struct of_dev_auxdata msm_auxdata_lookup[] __initdata = {
+ {}
+};
+
+static struct of_device_id msm_dt_gic_match[] __initdata = {
+ { .compatible = "qcom,msm-8660-qgic", },
+ {}
+};
+
+static void __init msm8x60_dt_init(void)
+{
+ struct device_node *node;
+
+ node = of_find_matching_node_by_address(NULL, msm_dt_gic_match,
+ MSM8X60_QGIC_DIST_PHYS);
+ if (node)
+ irq_domain_add_simple(node, GIC_SPI_START);
+
+ if (of_machine_is_compatible("qcom,msm8660-surf")) {
+ printk(KERN_INFO "Init surf UART registers\n");
+ msm8x60_init_uart12dm();
+ }
+
+ of_platform_populate(NULL, of_default_bus_match_table,
+ msm_auxdata_lookup, NULL);
+}
+
+static const char *msm8x60_fluid_match[] __initdata = {
+ "qcom,msm8660-fluid",
+ "qcom,msm8660-surf",
+ NULL
+};
+#endif /* CONFIG_OF */
+
MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
+ .fixup = msm8x60_fixup,
+ .reserve = msm8x60_reserve,
.map_io = msm8x60_map_io,
.init_irq = msm8x60_init_irq,
.init_machine = msm8x60_init,
@@ -72,6 +113,8 @@ MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
MACHINE_END
MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF")
+ .fixup = msm8x60_fixup,
+ .reserve = msm8x60_reserve,
.map_io = msm8x60_map_io,
.init_irq = msm8x60_init_irq,
.init_machine = msm8x60_init,
@@ -79,6 +122,8 @@ MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF")
MACHINE_END
MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR")
+ .fixup = msm8x60_fixup,
+ .reserve = msm8x60_reserve,
.map_io = msm8x60_map_io,
.init_irq = msm8x60_init_irq,
.init_machine = msm8x60_init,
@@ -86,8 +131,21 @@ MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR")
MACHINE_END
MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA")
+ .fixup = msm8x60_fixup,
+ .reserve = msm8x60_reserve,
.map_io = msm8x60_map_io,
.init_irq = msm8x60_init_irq,
.init_machine = msm8x60_init,
.timer = &msm_timer,
MACHINE_END
+
+#ifdef CONFIG_OF
+/* TODO: General device tree support for all MSM. */
+DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
+ .map_io = msm8x60_map_io,
+ .init_irq = msm8x60_init_irq,
+ .init_machine = msm8x60_dt_init,
+ .timer = &msm_timer,
+ .dt_compat = msm8x60_fluid_match,
+MACHINE_END
+#endif /* CONFIG_OF */
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 6a96911b0ad5..7e8909c978c3 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -14,7 +14,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/gpio.h>
@@ -32,7 +32,6 @@
#include <mach/board.h>
#include <mach/irqs.h>
#include <mach/sirc.h>
-#include <mach/gpio.h>
#include <mach/vreg.h>
#include <mach/mmc.h>
@@ -193,7 +192,7 @@ static void __init qsd8x50_init(void)
}
MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = qsd8x50_map_io,
.init_irq = qsd8x50_init_irq,
.init_machine = qsd8x50_init,
@@ -201,7 +200,7 @@ MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
MACHINE_END
MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = qsd8x50_map_io,
.init_irq = qsd8x50_init_irq,
.init_machine = qsd8x50_init,
diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c
index 68f930f07d77..32b465763dbd 100644
--- a/arch/arm/mach-msm/board-sapphire.c
+++ b/arch/arm/mach-msm/board-sapphire.c
@@ -11,7 +11,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -22,7 +22,6 @@
#include <linux/delay.h>
-#include <asm/gpio.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -77,8 +76,8 @@ static struct map_desc sapphire_io_desc[] __initdata = {
}
};
-static void __init sapphire_fixup(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+static void __init sapphire_fixup(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
int smi_sz = parse_tag_smi((const struct tag *)tags);
@@ -105,7 +104,7 @@ static void __init sapphire_map_io(void)
MACHINE_START(SAPPHIRE, "sapphire")
/* Maintainer: Brian Swetland <swetland@google.com> */
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.fixup = sapphire_fixup,
.map_io = sapphire_map_io,
.init_irq = sapphire_init_irq,
diff --git a/arch/arm/mach-msm/board-trout-mmc.c b/arch/arm/mach-msm/board-trout-mmc.c
index f7a9724788b0..8650342b7493 100644
--- a/arch/arm/mach-msm/board-trout-mmc.c
+++ b/arch/arm/mach-msm/board-trout-mmc.c
@@ -1,7 +1,7 @@
/* linux/arch/arm/mach-msm/board-trout-mmc.c
** Author: Brian Swetland <swetland@google.com>
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -11,7 +11,6 @@
#include <linux/err.h>
#include <linux/debugfs.h>
-#include <asm/gpio.h>
#include <asm/io.h>
#include <mach/vreg.h>
diff --git a/arch/arm/mach-msm/board-trout-panel.c b/arch/arm/mach-msm/board-trout-panel.c
index 729bb49a44ca..25105c1027fe 100644
--- a/arch/arm/mach-msm/board-trout-panel.c
+++ b/arch/arm/mach-msm/board-trout-panel.c
@@ -1,7 +1,7 @@
/* linux/arch/arm/mach-msm/board-trout-mddi.c
** Author: Brian Swetland <swetland@google.com>
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -11,7 +11,6 @@
#include <linux/err.h>
#include <asm/io.h>
-#include <asm/gpio.h>
#include <asm/mach-types.h>
#include <mach/msm_fb.h>
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c
index 814386772c66..6b9b227c87c5 100644
--- a/arch/arm/mach-msm/board-trout.c
+++ b/arch/arm/mach-msm/board-trout.c
@@ -48,8 +48,8 @@ static void __init trout_init_irq(void)
msm_init_irq();
}
-static void __init trout_fixup(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+static void __init trout_fixup(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
mi->nr_banks = 1;
mi->bank[0].start = PHYS_OFFSET;
@@ -93,7 +93,7 @@ static void __init trout_map_io(void)
}
MACHINE_START(TROUT, "HTC Dream")
- .boot_params = 0x10000100,
+ .atag_offset = 0x100,
.fixup = trout_fixup,
.map_io = trout_map_io,
.init_irq = trout_init_irq,
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 22a537669624..d9145dfc2a3b 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -18,7 +18,7 @@
#include <linux/list.h>
#include <linux/err.h>
#include <linux/spinlock.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/string.h>
diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c
index c4f5e26feb4d..993780f490ad 100644
--- a/arch/arm/mach-msm/devices-msm7x00.c
+++ b/arch/arm/mach-msm/devices-msm7x00.c
@@ -176,12 +176,6 @@ static struct resource resources_sdc1[] = {
.name = "cmd_irq",
},
{
- .start = INT_SDC1_1,
- .end = INT_SDC1_1,
- .flags = IORESOURCE_IRQ,
- .name = "pio_irq",
- },
- {
.flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
.name = "status_irq"
},
@@ -204,12 +198,6 @@ static struct resource resources_sdc2[] = {
.flags = IORESOURCE_IRQ,
.name = "cmd_irq",
},
- {
- .start = INT_SDC2_1,
- .end = INT_SDC2_1,
- .flags = IORESOURCE_IRQ,
- .name = "pio_irq",
- },
{
.flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
.name = "status_irq"
@@ -233,12 +221,6 @@ static struct resource resources_sdc3[] = {
.flags = IORESOURCE_IRQ,
.name = "cmd_irq",
},
- {
- .start = INT_SDC3_1,
- .end = INT_SDC3_1,
- .flags = IORESOURCE_IRQ,
- .name = "pio_irq",
- },
{
.flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
.name = "status_irq"
@@ -262,12 +244,6 @@ static struct resource resources_sdc4[] = {
.flags = IORESOURCE_IRQ,
.name = "cmd_irq",
},
- {
- .start = INT_SDC4_1,
- .end = INT_SDC4_1,
- .flags = IORESOURCE_IRQ,
- .name = "pio_irq",
- },
{
.flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
.name = "status_irq"
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 12d8deb78d9c..131633b12a34 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -140,12 +140,6 @@ static struct resource resources_sdc1[] = {
.name = "cmd_irq",
},
{
- .start = INT_SDC1_1,
- .end = INT_SDC1_1,
- .flags = IORESOURCE_IRQ,
- .name = "pio_irq",
- },
- {
.flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
.name = "status_irq"
},
@@ -168,12 +162,6 @@ static struct resource resources_sdc2[] = {
.flags = IORESOURCE_IRQ,
.name = "cmd_irq",
},
- {
- .start = INT_SDC2_1,
- .end = INT_SDC2_1,
- .flags = IORESOURCE_IRQ,
- .name = "pio_irq",
- },
{
.flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
.name = "status_irq"
@@ -197,12 +185,6 @@ static struct resource resources_sdc3[] = {
.flags = IORESOURCE_IRQ,
.name = "cmd_irq",
},
- {
- .start = INT_SDC3_1,
- .end = INT_SDC3_1,
- .flags = IORESOURCE_IRQ,
- .name = "pio_irq",
- },
{
.flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
.name = "status_irq"
@@ -226,12 +208,6 @@ static struct resource resources_sdc4[] = {
.flags = IORESOURCE_IRQ,
.name = "cmd_irq",
},
- {
- .start = INT_SDC4_1,
- .end = INT_SDC4_1,
- .flags = IORESOURCE_IRQ,
- .name = "pio_irq",
- },
{
.flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
.name = "status_irq"
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 5a31f70dfb8e..41c252de0215 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -37,7 +37,7 @@ static inline void platform_do_lowpower(unsigned int cpu)
:
: "memory", "cc");
- if (pen_release == cpu) {
+ if (pen_release == cpu_logical_map(cpu)) {
/*
* OK, proper wakeup, we're done
*/
diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S
index 646b99ebc773..2dc73ccddb11 100644
--- a/arch/arm/mach-msm/include/mach/debug-macro.S
+++ b/arch/arm/mach-msm/include/mach/debug-macro.S
@@ -20,7 +20,7 @@
#include <mach/msm_iomap.h>
#if defined(CONFIG_HAS_MSM_DEBUG_UART_PHYS) && !defined(CONFIG_MSM_DEBUG_UART_NONE)
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =MSM_DEBUG_UART_PHYS
ldr \rv, =MSM_DEBUG_UART_BASE
.endm
@@ -37,7 +37,7 @@
beq 1001b
.endm
#else
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rv, #0xff000000
orr \rv, \rv, #0x00f00000
.endm
diff --git a/arch/arm/mach-msm/include/mach/entry-macro-qgic.S b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
index 12467157afb9..717076f3ca73 100644
--- a/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
+++ b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
@@ -8,81 +8,10 @@
* warranty of any kind, whether express or implied.
*/
-#include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
.macro disable_fiq
.endm
- .macro get_irqnr_preamble, base, tmp
- ldr \base, =gic_cpu_base_addr
- ldr \base, [\base]
- .endm
-
.macro arch_ret_to_user, tmp1, tmp2
.endm
-
- /*
- * The interrupt numbering scheme is defined in the
- * interrupt controller spec. To wit:
- *
- * Migrated the code from ARM MP port to be more consistent
- * with interrupt processing , the following still holds true
- * however, all interrupts are treated the same regardless of
- * if they are local IPI or PPI
- *
- * Interrupts 0-15 are IPI
- * 16-31 are PPI
- * (16-18 are the timers)
- * 32-1020 are global
- * 1021-1022 are reserved
- * 1023 is "spurious" (no interrupt)
- *
- * A simple read from the controller will tell us the number of the
- * highest priority enabled interrupt. We then just need to check
- * whether it is in the valid range for an IRQ (0-1020 inclusive).
- *
- * Base ARM code assumes that the local (private) peripheral interrupts
- * are not valid, we treat them differently, in that the privates are
- * handled like normal shared interrupts with the exception that only
- * one processor can register the interrupt and the handler must be
- * the same for all processors.
- */
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU,
- 9-0 =int # */
-
- bic \irqnr, \irqstat, #0x1c00 @mask src
- cmp \irqnr, #15
- ldr \tmp, =1021
- cmpcc \irqnr, \irqnr
- cmpne \irqnr, \tmp
- cmpcs \irqnr, \irqnr
-
- .endm
-
- /* We assume that irqstat (the raw value of the IRQ acknowledge
- * register) is preserved from the macro above.
- * If there is an IPI, we immediately signal end of interrupt on the
- * controller, since this requires the original irqstat value which
- * we won't easily be able to recreate later.
- */
- .macro test_for_ipi, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #16
- strcc \irqstat, [\base, #GIC_CPU_EOI]
- cmpcs \irqnr, \irqnr
- .endm
-
- /* As above, this assumes that irqstat and base are preserved.. */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #16
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
index 36ad50d3bfaa..40a8c178f10d 100644
--- a/arch/arm/mach-msm/include/mach/gpio.h
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -1,26 +1 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-#ifndef __ASM_ARCH_MSM_GPIO_H
-#define __ASM_ARCH_MSM_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
-#endif /* __ASM_ARCH_MSM_GPIO_H */
+/* empty */
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
deleted file mode 100644
index f2f8d299ba95..000000000000
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* arch/arm/mach-msm/include/mach/memory.h
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * 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 __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/* physical offset of RAM */
-#if defined(CONFIG_ARCH_QSD8X50) && defined(CONFIG_MSM_SOC_REV_A)
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-#elif defined(CONFIG_ARCH_QSD8X50)
-#define PLAT_PHYS_OFFSET UL(0x20000000)
-#elif defined(CONFIG_ARCH_MSM7X30)
-#define PLAT_PHYS_OFFSET UL(0x00200000)
-#elif defined(CONFIG_ARCH_MSM8X60)
-#define PLAT_PHYS_OFFSET UL(0x40200000)
-#elif defined(CONFIG_ARCH_MSM8960)
-#define PLAT_PHYS_OFFSET UL(0x40200000)
-#else
-#define PLAT_PHYS_OFFSET UL(0x10000000)
-#endif
-
-#endif
-
diff --git a/arch/arm/mach-msm/include/mach/mmc.h b/arch/arm/mach-msm/include/mach/mmc.h
index 5631b51cec46..ffcd9e3a6a7e 100644
--- a/arch/arm/mach-msm/include/mach/mmc.h
+++ b/arch/arm/mach-msm/include/mach/mmc.h
@@ -8,13 +8,6 @@
#include <linux/mmc/card.h>
#include <linux/mmc/sdio_func.h>
-struct embedded_sdio_data {
- struct sdio_cis cis;
- struct sdio_cccr cccr;
- struct sdio_embedded_func *funcs;
- int num_funcs;
-};
-
struct msm_mmc_gpio {
unsigned no;
const char *name;
@@ -29,9 +22,9 @@ struct msm_mmc_platform_data {
unsigned int ocr_mask; /* available voltages */
u32 (*translate_vdd)(struct device *, unsigned int);
unsigned int (*status)(struct device *);
- struct embedded_sdio_data *embedded_sdio;
int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
struct msm_mmc_gpio_data *gpio_data;
+ void (*init_card)(struct mmc_card *card);
};
#endif
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 1a1af9e56250..fdec58aaa35c 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -117,7 +117,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
* Note that "pen_release" is the hardware CPU ID, whereas
* "cpu" is Linux's internal ID.
*/
- pen_release = cpu;
+ pen_release = cpu_logical_map(cpu);
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
@@ -156,6 +156,12 @@ void __init smp_init_cpus(void)
{
unsigned int i, ncores = get_core_count();
+ if (ncores > nr_cpu_ids) {
+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+ ncores, nr_cpu_ids);
+ ncores = nr_cpu_ids;
+ }
+
for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 63621f152c98..afeeca52fc66 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -71,12 +71,16 @@ enum timer_location {
struct msm_clock {
struct clock_event_device clockevent;
struct clocksource clocksource;
- struct irqaction irq;
+ unsigned int irq;
void __iomem *regbase;
uint32_t freq;
uint32_t shift;
void __iomem *global_counter;
void __iomem *local_counter;
+ union {
+ struct clock_event_device *evt;
+ struct clock_event_device __percpu **percpu_evt;
+ };
};
enum {
@@ -87,13 +91,10 @@ enum {
static struct msm_clock msm_clocks[];
-static struct clock_event_device *local_clock_event;
static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *evt = dev_id;
- if (smp_processor_id() != 0)
- evt = local_clock_event;
+ struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
if (evt->event_handler == NULL)
return IRQ_HANDLED;
evt->event_handler(evt);
@@ -171,13 +172,7 @@ static struct msm_clock msm_clocks[] = {
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
},
- .irq = {
- .name = "gp_timer",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING,
- .handler = msm_timer_interrupt,
- .dev_id = &msm_clocks[0].clockevent,
- .irq = INT_GP_TIMER_EXP
- },
+ .irq = INT_GP_TIMER_EXP,
.freq = GPT_HZ,
},
[MSM_CLOCK_DGT] = {
@@ -196,13 +191,7 @@ static struct msm_clock msm_clocks[] = {
.mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
},
- .irq = {
- .name = "dg_timer",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING,
- .handler = msm_timer_interrupt,
- .dev_id = &msm_clocks[1].clockevent,
- .irq = INT_DEBUG_TIMER_EXP
- },
+ .irq = INT_DEBUG_TIMER_EXP,
.freq = DGT_HZ >> MSM_DGT_SHIFT,
.shift = MSM_DGT_SHIFT,
}
@@ -261,10 +250,30 @@ static void __init msm_timer_init(void)
printk(KERN_ERR "msm_timer_init: clocksource_register "
"failed for %s\n", cs->name);
- res = setup_irq(clock->irq.irq, &clock->irq);
+ ce->irq = clock->irq;
+ if (cpu_is_msm8x60() || cpu_is_msm8960()) {
+ clock->percpu_evt = alloc_percpu(struct clock_event_device *);
+ if (!clock->percpu_evt) {
+ pr_err("msm_timer_init: memory allocation "
+ "failed for %s\n", ce->name);
+ continue;
+ }
+
+ *__this_cpu_ptr(clock->percpu_evt) = ce;
+ res = request_percpu_irq(ce->irq, msm_timer_interrupt,
+ ce->name, clock->percpu_evt);
+ if (!res)
+ enable_percpu_irq(ce->irq, 0);
+ } else {
+ clock->evt = ce;
+ res = request_irq(ce->irq, msm_timer_interrupt,
+ IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
+ ce->name, &clock->evt);
+ }
+
if (res)
- printk(KERN_ERR "msm_timer_init: setup_irq "
- "failed for %s\n", cs->name);
+ pr_err("msm_timer_init: request_irq failed for %s\n",
+ ce->name);
clockevents_register_device(ce);
}
@@ -273,6 +282,7 @@ static void __init msm_timer_init(void)
#ifdef CONFIG_SMP
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
+ static bool local_timer_inited;
struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER];
/* Use existing clock_event for cpu 0 */
@@ -281,12 +291,13 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
- if (!local_clock_event) {
+ if (!local_timer_inited) {
writel(0, clock->regbase + TIMER_ENABLE);
writel(0, clock->regbase + TIMER_CLEAR);
writel(~0, clock->regbase + TIMER_MATCH_VAL);
+ local_timer_inited = true;
}
- evt->irq = clock->irq.irq;
+ evt->irq = clock->irq;
evt->name = "local_timer";
evt->features = CLOCK_EVT_FEAT_ONESHOT;
evt->rating = clock->clockevent.rating;
@@ -298,17 +309,17 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
evt->min_delta_ns = clockevent_delta2ns(4, evt);
- local_clock_event = evt;
-
- gic_enable_ppi(clock->irq.irq);
+ *__this_cpu_ptr(clock->percpu_evt) = evt;
+ enable_percpu_irq(evt->irq, 0);
clockevents_register_device(evt);
return 0;
}
-inline int local_timer_ack(void)
+void local_timer_stop(struct clock_event_device *evt)
{
- return 1;
+ evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+ disable_percpu_irq(evt->irq);
}
#endif
diff --git a/arch/arm/mach-mv78xx0/Makefile.boot b/arch/arm/mach-mv78xx0/Makefile.boot
index 67039c3e0c48..760a0efe7580 100644
--- a/arch/arm/mach-mv78xx0/Makefile.boot
+++ b/arch/arm/mach-mv78xx0/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
index 20f3f125ed2b..0e94268d6e6f 100644
--- a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
+++ b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
@@ -145,7 +145,7 @@ subsys_initcall(wxl_pci_init);
MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL")
/* Maintainer: Sebastien Requiem <sebastien@requiem.fr> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = wxl_init,
.map_io = mv78xx0_map_io,
.init_early = mv78xx0_init_early,
diff --git a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
index df5aebe5b0fa..50b85ae2da52 100644
--- a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
+++ b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
@@ -93,7 +93,7 @@ subsys_initcall(db78x00_pci_init);
MACHINE_START(DB78X00_BP, "Marvell DB-78x00-BP Development Board")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = db78x00_init,
.map_io = mv78xx0_map_io,
.init_early = mv78xx0_init_early,
diff --git a/arch/arm/mach-mv78xx0/include/mach/debug-macro.S b/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
index 04891428e48b..a7df02b049b7 100644
--- a/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
+++ b/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
@@ -8,7 +8,7 @@
#include <mach/mv78xx0.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =MV78XX0_REGS_PHYS_BASE
ldr \rv, =MV78XX0_REGS_VIRT_BASE
orr \rp, \rp, #0x00012000
diff --git a/arch/arm/mach-mv78xx0/include/mach/memory.h b/arch/arm/mach-mv78xx0/include/mach/memory.h
deleted file mode 100644
index a648c51f2e42..000000000000
--- a/arch/arm/mach-mv78xx0/include/mach/memory.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-mv78xx0/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-mv78xx0/irq.c b/arch/arm/mach-mv78xx0/irq.c
index 3e24431bb5ea..e421b701663b 100644
--- a/arch/arm/mach-mv78xx0/irq.c
+++ b/arch/arm/mach-mv78xx0/irq.c
@@ -7,12 +7,11 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/irq.h>
-#include <asm/gpio.h>
#include <mach/bridge-regs.h>
#include <plat/irq.h>
#include "common.h"
diff --git a/arch/arm/mach-mv78xx0/mpp.c b/arch/arm/mach-mv78xx0/mpp.c
index 59b7686b9209..cf4e494d44bf 100644
--- a/arch/arm/mach-mv78xx0/mpp.c
+++ b/arch/arm/mach-mv78xx0/mpp.c
@@ -7,13 +7,12 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mbus.h>
#include <linux/io.h>
#include <plat/mpp.h>
-#include <asm/gpio.h>
#include <mach/hardware.h>
#include "common.h"
#include "mpp.h"
diff --git a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
index d927f14c6810..e85222e53578 100644
--- a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
+++ b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
@@ -78,7 +78,7 @@ subsys_initcall(rd78x00_pci_init);
MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = rd78x00_masa_init,
.map_io = mv78xx0_map_io,
.init_early = mv78xx0_init_early,
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index b4e7c58bbb38..af0c212e3c7b 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -1,8 +1,9 @@
-if ARCH_MX503 || ARCH_MX51
+if ARCH_MX5
+
# ARCH_MX5/50/53 are left to mark places where prevent multi-soc in single
# image. So for most time, SOC_IMX50/51/53 should be used.
-config ARCH_MX5
+config ARCH_MX51
bool
config ARCH_MX50
@@ -19,7 +20,6 @@ config SOC_IMX50
select ARCH_MXC_IOMUX_V3
select ARCH_MXC_AUDMUX_V2
select ARCH_HAS_CPUFREQ
- select ARCH_MX5
select ARCH_MX50
config SOC_IMX51
@@ -30,7 +30,7 @@ config SOC_IMX51
select ARCH_MXC_IOMUX_V3
select ARCH_MXC_AUDMUX_V2
select ARCH_HAS_CPUFREQ
- select ARCH_MX5
+ select ARCH_MX51
config SOC_IMX53
bool
@@ -38,10 +38,8 @@ config SOC_IMX53
select ARM_L1_CACHE_SHIFT_6
select MXC_TZIC
select ARCH_MXC_IOMUX_V3
- select ARCH_MX5
select ARCH_MX53
-if ARCH_MX50_SUPPORTED
#comment "i.MX50 machines:"
config MACH_MX50_RDP
@@ -52,22 +50,29 @@ config MACH_MX50_RDP
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
select IMX_HAVE_PLATFORM_SPI_IMX
- select IMX_HAVE_PLATFORM_FEC
help
Include support for MX50 reference design platform (RDP) board. This
includes specific configurations for the board and its peripherals.
-endif # ARCH_MX50_SUPPORTED
-
-if ARCH_MX51
comment "i.MX51 machines:"
+config MACH_IMX51_DT
+ bool "Support i.MX51 platforms from device tree"
+ select SOC_IMX51
+ select USE_OF
+ select MACH_MX51_BABBAGE
+ help
+ Include support for Freescale i.MX51 based platforms
+ using the device tree for discovery
+
config MACH_MX51_BABBAGE
bool "Support MX51 BABBAGE platforms"
select SOC_IMX51
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
select IMX_HAVE_PLATFORM_IMX2_WDT
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_EHCI
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
select IMX_HAVE_PLATFORM_SPI_IMX
help
@@ -91,8 +96,10 @@ config MACH_MX51_3DS
config MACH_EUKREA_CPUIMX51
bool "Support Eukrea CPUIMX51 module"
select SOC_IMX51
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_EHCI
select IMX_HAVE_PLATFORM_MXC_NAND
select IMX_HAVE_PLATFORM_SPI_IMX
help
@@ -119,10 +126,12 @@ endchoice
config MACH_EUKREA_CPUIMX51SD
bool "Support Eukrea CPUIMX51SD module"
select SOC_IMX51
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
select IMX_HAVE_PLATFORM_IMX_I2C
- select IMX_HAVE_PLATFORM_SPI_IMX
select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_EHCI
select IMX_HAVE_PLATFORM_MXC_NAND
+ select IMX_HAVE_PLATFORM_SPI_IMX
help
Include support for Eukrea CPUIMX51SD platform. This includes
specific configurations for the module and its peripherals.
@@ -147,6 +156,8 @@ config MX51_EFIKA_COMMON
bool
select SOC_IMX51
select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_PATA_IMX
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
select IMX_HAVE_PLATFORM_SPI_IMX
select MXC_ULPI if USB_ULPI
@@ -167,11 +178,20 @@ config MACH_MX51_EFIKASB
Include support for Genesi Efika Smartbook. This includes specific
configurations for the board and its peripherals.
-endif # ARCH_MX51
-
-if ARCH_MX53_SUPPORTED
comment "i.MX53 machines:"
+config MACH_IMX53_DT
+ bool "Support i.MX53 platforms from device tree"
+ select SOC_IMX53
+ select USE_OF
+ select MACH_MX53_ARD
+ select MACH_MX53_EVK
+ select MACH_MX53_LOCO
+ select MACH_MX53_SMD
+ help
+ Include support for Freescale i.MX53 based platforms
+ using the device tree for discovery
+
config MACH_MX53_EVK
bool "Support MX53 EVK platforms"
select SOC_IMX53
@@ -221,6 +241,4 @@ config MACH_MX53_ARD
Include support for MX53 ARD platform. This includes specific
configurations for the board and its peripherals.
-endif # ARCH_MX53_SUPPORTED
-
endif
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 383e7cd3fbcb..0fc60807fa2b 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -3,8 +3,7 @@
#
# Object file lists.
-obj-y := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
-obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
+obj-y := cpu.o mm.o clock-mx51-mx53.o ehci.o system.o
obj-$(CONFIG_PM) += pm-imx5.o
obj-$(CONFIG_CPU_FREQ_IMX) += cpu_op-mx51.o
@@ -22,3 +21,6 @@ obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
obj-$(CONFIG_MACH_MX51_EFIKASB) += board-mx51_efikasb.o
obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
+
+obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
+obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
diff --git a/arch/arm/mach-mx5/Makefile.boot b/arch/arm/mach-mx5/Makefile.boot
index e928be1b6757..ca207ca305ec 100644
--- a/arch/arm/mach-mx5/Makefile.boot
+++ b/arch/arm/mach-mx5/Makefile.boot
@@ -1,9 +1,9 @@
- zreladdr-$(CONFIG_ARCH_MX50) := 0x70008000
+ zreladdr-$(CONFIG_ARCH_MX50) += 0x70008000
params_phys-$(CONFIG_ARCH_MX50) := 0x70000100
initrd_phys-$(CONFIG_ARCH_MX50) := 0x70800000
- zreladdr-$(CONFIG_ARCH_MX51) := 0x90008000
+ zreladdr-$(CONFIG_ARCH_MX51) += 0x90008000
params_phys-$(CONFIG_ARCH_MX51) := 0x90000100
initrd_phys-$(CONFIG_ARCH_MX51) := 0x90800000
- zreladdr-$(CONFIG_ARCH_MX53) := 0x70008000
+ zreladdr-$(CONFIG_ARCH_MX53) += 0x70008000
params_phys-$(CONFIG_ARCH_MX53) := 0x70000100
initrd_phys-$(CONFIG_ARCH_MX53) := 0x70800000
diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c
index 68934ea8725a..1fc110348040 100644
--- a/arch/arm/mach-mx5/board-cpuimx51.c
+++ b/arch/arm/mach-mx5/board-cpuimx51.c
@@ -22,21 +22,18 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <mach/eukrea-baseboards.h>
#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/iomux-mx51.h>
-#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include "devices-imx51.h"
-#include "devices.h"
#define CPUIMX51_USBH1_STP IMX_GPIO_NR(1, 27)
#define CPUIMX51_QUARTA_GPIO IMX_GPIO_NR(3, 28)
@@ -57,7 +54,7 @@
static struct plat_serial8250_port serial_platform_data[] = {
{
.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
- .irq = gpio_to_irq(CPUIMX51_QUARTA_GPIO),
+ .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
.irqflags = IRQF_TRIGGER_HIGH,
.uartclk = CPUIMX51_QUART_XTAL,
.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -65,7 +62,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
}, {
.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
- .irq = gpio_to_irq(CPUIMX51_QUARTB_GPIO),
+ .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
.irqflags = IRQF_TRIGGER_HIGH,
.uartclk = CPUIMX51_QUART_XTAL,
.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -73,7 +70,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
}, {
.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
- .irq = gpio_to_irq(CPUIMX51_QUARTC_GPIO),
+ .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
.irqflags = IRQF_TRIGGER_HIGH,
.uartclk = CPUIMX51_QUART_XTAL,
.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -81,7 +78,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
}, {
.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
- .irq = gpio_to_irq(CPUIMX51_QUARTD_GPIO),
+ .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
.irqflags = IRQF_TRIGGER_HIGH,
.uartclk = CPUIMX51_QUART_XTAL,
.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -167,7 +164,7 @@ static int initialize_otg_port(struct platform_device *pdev)
void __iomem *usb_base;
void __iomem *usbother_base;
- usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
if (!usb_base)
return -ENOMEM;
usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -190,7 +187,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
void __iomem *usb_base;
void __iomem *usbother_base;
- usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
if (!usb_base)
return -ENOMEM;
usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -206,17 +203,17 @@ static int initialize_usbh1_port(struct platform_device *pdev)
MXC_EHCI_ITC_NO_THRESHOLD);
}
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
.init = initialize_otg_port,
.portsc = MXC_EHCI_UTMI_16BIT,
};
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
.operating_mode = FSL_USB2_DR_DEVICE,
.phy_mode = FSL_USB2_PHY_UTMI_WIDE,
};
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
.init = initialize_usbh1_port,
.portsc = MXC_EHCI_MODE_ULPI,
};
@@ -270,12 +267,12 @@ static void __init eukrea_cpuimx51_init(void)
ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
if (otg_mode_host)
- mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+ imx51_add_mxc_ehci_otg(&dr_utmi_config);
else {
initialize_otg_port(NULL);
- mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+ imx51_add_fsl_usb2_udc(&usb_pdata);
}
- mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+ imx51_add_mxc_ehci_hs(1, &usbh1_config);
#ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
eukrea_mbimx51_baseboard_init();
@@ -293,10 +290,11 @@ static struct sys_timer mxc_timer = {
MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
/* Maintainer: Eric Bénard <eric@eukrea.com> */
- .boot_params = MX51_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx51_map_io,
.init_early = imx51_init_early,
.init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
.timer = &mxc_timer,
.init_machine = eukrea_cpuimx51_init,
MACHINE_END
diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
index ff096d587299..52a11c1898e6 100644
--- a/arch/arm/mach-mx5/board-cpuimx51sd.c
+++ b/arch/arm/mach-mx5/board-cpuimx51sd.c
@@ -22,7 +22,6 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/i2c-gpio.h>
#include <linux/spi/spi.h>
#include <linux/can/platform/mcp251x.h>
@@ -32,14 +31,12 @@
#include <mach/hardware.h>
#include <mach/iomux-mx51.h>
-#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include "devices-imx51.h"
-#include "devices.h"
#include "cpu_op-mx51.h"
#define USBH1_RST IMX_GPIO_NR(2, 28)
@@ -108,7 +105,7 @@ static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
/* Touchscreen */
/* IRQ */
- _MX51_PAD_GPIO_NAND__GPIO_NAND | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+ NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
PAD_CTL_PKE | PAD_CTL_SRE_FAST |
PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
};
@@ -129,7 +126,7 @@ static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
I2C_BOARD_INFO("tsc2007", 0x49),
.type = "tsc2007",
.platform_data = &tsc2007_info,
- .irq = gpio_to_irq(TSC2007_IRQGPIO),
+ .irq = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
},
};
@@ -149,7 +146,7 @@ static int initialize_otg_port(struct platform_device *pdev)
void __iomem *usb_base;
void __iomem *usbother_base;
- usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
if (!usb_base)
return -ENOMEM;
usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -172,7 +169,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
void __iomem *usb_base;
void __iomem *usbother_base;
- usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
if (!usb_base)
return -ENOMEM;
usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -189,17 +186,17 @@ static int initialize_usbh1_port(struct platform_device *pdev)
MXC_EHCI_ITC_NO_THRESHOLD);
}
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
.init = initialize_otg_port,
.portsc = MXC_EHCI_UTMI_16BIT,
};
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
.operating_mode = FSL_USB2_DR_DEVICE,
.phy_mode = FSL_USB2_PHY_UTMI_WIDE,
};
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
.init = initialize_usbh1_port,
.portsc = MXC_EHCI_MODE_ULPI,
};
@@ -245,7 +242,7 @@ static struct spi_board_info cpuimx51sd_spi_device[] = {
.mode = SPI_MODE_0,
.chip_select = 0,
.platform_data = &mcp251x_info,
- .irq = gpio_to_irq(CAN_IRQGPIO)
+ .irq = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
},
};
@@ -303,17 +300,17 @@ static void __init eukrea_cpuimx51sd_init(void)
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
if (otg_mode_host)
- mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+ imx51_add_mxc_ehci_otg(&dr_utmi_config);
else {
initialize_otg_port(NULL);
- mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+ imx51_add_fsl_usb2_udc(&usb_pdata);
}
gpio_request(USBH1_RST, "usb_rst");
gpio_direction_output(USBH1_RST, 0);
msleep(20);
gpio_set_value(USBH1_RST, 1);
- mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+ imx51_add_mxc_ehci_hs(1, &usbh1_config);
#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
eukrea_mbimxsd51_baseboard_init();
@@ -331,10 +328,11 @@ static struct sys_timer mxc_timer = {
MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
/* Maintainer: Eric Bénard <eric@eukrea.com> */
- .boot_params = MX51_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx51_map_io,
.init_early = imx51_init_early,
.init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
.timer = &mxc_timer,
.init_machine = eukrea_cpuimx51sd_init,
MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c
index 7de25c6712eb..fc3621d90bde 100644
--- a/arch/arm/mach-mx5/board-mx50_rdp.c
+++ b/arch/arm/mach-mx5/board-mx50_rdp.c
@@ -219,6 +219,7 @@ MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
.map_io = mx50_map_io,
.init_early = imx50_init_early,
.init_irq = mx50_init_irq,
+ .handle_irq = imx50_handle_irq,
.timer = &mx50_rdp_timer,
.init_machine = mx50_rdp_board_init,
MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c
index 07a38154da21..05783906db2b 100644
--- a/arch/arm/mach-mx5/board-mx51_3ds.c
+++ b/arch/arm/mach-mx5/board-mx51_3ds.c
@@ -25,7 +25,6 @@
#include <mach/3ds_debugboard.h>
#include "devices-imx51.h"
-#include "devices.h"
#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(1, 6))
#define MX51_3DS_ECSPI2_CS (GPIO_PORTC + 28)
@@ -169,10 +168,11 @@ static struct sys_timer mx51_3ds_timer = {
MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
/* Maintainer: Freescale Semiconductor, Inc. */
- .boot_params = MX51_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx51_map_io,
.init_early = imx51_init_early,
.init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
.timer = &mx51_3ds_timer,
.init_machine = mx51_3ds_init,
MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 11b0ff67f89d..5c837603ff0f 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -24,14 +24,12 @@
#include <mach/hardware.h>
#include <mach/iomux-mx51.h>
-#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include "devices-imx51.h"
-#include "devices.h"
#include "cpu_op-mx51.h"
#define BABBAGE_USB_HUB_RESET IMX_GPIO_NR(1, 7)
@@ -176,7 +174,7 @@ static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
.bitrate = 100000,
};
-static struct imxi2c_platform_data babbage_hsi2c_data = {
+static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
.bitrate = 400000,
};
@@ -249,7 +247,7 @@ static int initialize_otg_port(struct platform_device *pdev)
void __iomem *usb_base;
void __iomem *usbother_base;
- usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
if (!usb_base)
return -ENOMEM;
usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -272,7 +270,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
void __iomem *usb_base;
void __iomem *usbother_base;
- usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
if (!usb_base)
return -ENOMEM;
usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -288,17 +286,17 @@ static int initialize_usbh1_port(struct platform_device *pdev)
MXC_EHCI_ITC_NO_THRESHOLD);
}
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
.init = initialize_otg_port,
.portsc = MXC_EHCI_UTMI_16BIT,
};
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
.operating_mode = FSL_USB2_DR_DEVICE,
.phy_mode = FSL_USB2_PHY_UTMI_WIDE,
};
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
.init = initialize_usbh1_port,
.portsc = MXC_EHCI_MODE_ULPI,
};
@@ -351,22 +349,27 @@ static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
.wp_type = ESDHC_WP_GPIO,
};
+void __init imx51_babbage_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
+ ARRAY_SIZE(mx51babbage_pads));
+}
+
/*
* Board specific initialization.
*/
static void __init mx51_babbage_init(void)
{
iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
- iomux_v3_cfg_t power_key = _MX51_PAD_EIM_A27__GPIO2_21 |
- MUX_PAD_CTRL(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP);
+ iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
+ PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP);
imx51_soc_init();
#if defined(CONFIG_CPU_FREQ_IMX)
get_cpu_op = mx51_get_cpu_op;
#endif
- mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
- ARRAY_SIZE(mx51babbage_pads));
+ imx51_babbage_common_init();
imx51_add_imx_uart(0, &uart_pdata);
imx51_add_imx_uart(1, NULL);
@@ -381,17 +384,17 @@ static void __init mx51_babbage_init(void)
imx51_add_imx_i2c(0, &babbage_i2c_data);
imx51_add_imx_i2c(1, &babbage_i2c_data);
- mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data);
+ imx51_add_hsi2c(&babbage_hsi2c_data);
if (otg_mode_host)
- mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+ imx51_add_mxc_ehci_otg(&dr_utmi_config);
else {
initialize_otg_port(NULL);
- mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+ imx51_add_fsl_usb2_udc(&usb_pdata);
}
gpio_usbh1_active();
- mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+ imx51_add_mxc_ehci_hs(1, &usbh1_config);
/* setback USBH1_STP to be function */
mxc_iomux_v3_setup_pad(usbh1stp);
babbage_usbhub_reset();
@@ -416,10 +419,11 @@ static struct sys_timer mx51_babbage_timer = {
MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
- .boot_params = MX51_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx51_map_io,
.init_early = imx51_init_early,
.init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
.timer = &mx51_babbage_timer,
.init_machine = mx51_babbage_init,
MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
index 551daf85ff8c..a9e48662cf75 100644
--- a/arch/arm/mach-mx5/board-mx51_efikamx.c
+++ b/arch/arm/mach-mx5/board-mx51_efikamx.c
@@ -32,14 +32,12 @@
#include <mach/hardware.h>
#include <mach/iomux-mx51.h>
-#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include "devices-imx51.h"
-#include "devices.h"
#include "efika.h"
#define EFIKAMX_PCBID0 IMX_GPIO_NR(3, 16)
@@ -163,6 +161,11 @@ static const struct gpio_led_platform_data
.num_leds = ARRAY_SIZE(mx51_efikamx_leds),
};
+static struct esdhc_platform_data sd_pdata = {
+ .cd_type = ESDHC_CD_CONTROLLER,
+ .wp_type = ESDHC_WP_CONTROLLER,
+};
+
static struct gpio_keys_button mx51_efikamx_powerkey[] = {
{
.code = KEY_POWER,
@@ -239,9 +242,11 @@ static void __init mx51_efikamx_init(void)
/* on < 1.2 boards both SD controllers are used */
if (system_rev < 0x12) {
- imx51_add_sdhci_esdhc_imx(1, NULL);
+ imx51_add_sdhci_esdhc_imx(0, NULL);
+ imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
mx51_efikamx_leds[2].default_trigger = "mmc1";
- }
+ } else
+ imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
gpio_led_register_device(-1, &mx51_efikamx_leds_data);
imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
@@ -280,10 +285,11 @@ static struct sys_timer mx51_efikamx_timer = {
MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
/* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
- .boot_params = MX51_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx51_map_io,
.init_early = imx51_init_early,
.init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
.timer = &mx51_efikamx_timer,
.init_machine = mx51_efikamx_init,
MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c
index 8a9bca22beb5..38c4a3e28d3c 100644
--- a/arch/arm/mach-mx5/board-mx51_efikasb.c
+++ b/arch/arm/mach-mx5/board-mx51_efikasb.c
@@ -35,14 +35,12 @@
#include <mach/hardware.h>
#include <mach/iomux-mx51.h>
-#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include "devices-imx51.h"
-#include "devices.h"
#include "efika.h"
#define EFIKASB_USBH2_STP IMX_GPIO_NR(2, 20)
@@ -56,6 +54,7 @@
#define EFIKASB_RFKILL IMX_GPIO_NR(3, 1)
#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0, 0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+#define MX51_PAD_SD1_CD IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
static iomux_v3_cfg_t mx51efikasb_pads[] = {
/* USB HOST2 */
@@ -97,6 +96,8 @@ static iomux_v3_cfg_t mx51efikasb_pads[] = {
/* BT */
MX51_PAD_EIM_A17__GPIO2_11,
+
+ MX51_PAD_SD1_CD,
};
static int initialize_usbh2_port(struct platform_device *pdev)
@@ -119,7 +120,7 @@ static int initialize_usbh2_port(struct platform_device *pdev)
return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
}
-static struct mxc_usbh_platform_data usbh2_config = {
+static struct mxc_usbh_platform_data usbh2_config __initdata = {
.init = initialize_usbh2_port,
.portsc = MXC_EHCI_MODE_ULPI,
};
@@ -129,7 +130,7 @@ static void __init mx51_efikasb_usb(void)
usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
if (usbh2_config.otg)
- mxc_register_device(&mxc_usbh2_device, &usbh2_config);
+ imx51_add_mxc_ehci_hs(2, &usbh2_config);
}
static const struct gpio_led mx51_efikasb_leds[] __initconst = {
@@ -182,6 +183,18 @@ static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst =
.nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
};
+static struct esdhc_platform_data sd0_pdata = {
+#define EFIKASB_SD1_CD IMX_GPIO_NR(2, 27)
+ .cd_gpio = EFIKASB_SD1_CD,
+ .cd_type = ESDHC_CD_GPIO,
+ .wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct esdhc_platform_data sd1_pdata = {
+ .cd_type = ESDHC_CD_CONTROLLER,
+ .wp_type = ESDHC_WP_CONTROLLER,
+};
+
static struct regulator *pwgt1, *pwgt2;
static void mx51_efikasb_power_off(void)
@@ -250,7 +263,8 @@ static void __init efikasb_board_init(void)
mx51_efikasb_board_id();
mx51_efikasb_usb();
- imx51_add_sdhci_esdhc_imx(1, NULL);
+ imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
+ imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
gpio_led_register_device(-1, &mx51_efikasb_leds_data);
imx_add_gpio_keys(&mx51_efikasb_keys_data);
@@ -266,10 +280,11 @@ static struct sys_timer mx51_efikasb_timer = {
};
MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
- .boot_params = MX51_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
.map_io = mx51_map_io,
.init_early = imx51_init_early,
.init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
.init_machine = efikasb_board_init,
.timer = &mx51_efikasb_timer,
MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_ard.c b/arch/arm/mach-mx5/board-mx53_ard.c
index 76a67c4a2a0b..0d7f0fffb23a 100644
--- a/arch/arm/mach-mx5/board-mx53_ard.c
+++ b/arch/arm/mach-mx5/board-mx53_ard.c
@@ -134,8 +134,8 @@ static struct resource ard_smsc911x_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- .start = gpio_to_irq(ARD_ETHERNET_INT_B),
- .end = gpio_to_irq(ARD_ETHERNET_INT_B),
+ .start = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+ .end = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
.flags = IORESOURCE_IRQ,
},
};
@@ -171,9 +171,6 @@ static struct imxi2c_platform_data mx53_ard_i2c3_data = {
static void __init mx53_ard_io_init(void)
{
- mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
- ARRAY_SIZE(mx53_ard_pads));
-
gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
gpio_direction_input(ARD_ETHERNET_INT_B);
@@ -216,6 +213,13 @@ static int weim_cs_config(void)
return 0;
}
+void __init imx53_ard_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
+ ARRAY_SIZE(mx53_ard_pads));
+ weim_cs_config();
+}
+
static struct platform_device *devices[] __initdata = {
&ard_smsc_lan9220_device,
};
@@ -225,8 +229,8 @@ static void __init mx53_ard_board_init(void)
imx53_soc_init();
imx53_add_imx_uart(0, NULL);
+ imx53_ard_common_init();
mx53_ard_io_init();
- weim_cs_config();
platform_add_devices(devices, ARRAY_SIZE(devices));
imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
@@ -234,6 +238,7 @@ static void __init mx53_ard_board_init(void)
imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
imx_add_gpio_keys(&ard_button_data);
+ imx53_add_ahci_imx();
}
static void __init mx53_ard_timer_init(void)
@@ -249,6 +254,7 @@ MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
.map_io = mx53_map_io,
.init_early = imx53_init_early,
.init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
.timer = &mx53_ard_timer,
.init_machine = mx53_ard_board_init,
MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c
index 1b417b06b736..6bea31ab8f85 100644
--- a/arch/arm/mach-mx5/board-mx53_evk.c
+++ b/arch/arm/mach-mx5/board-mx53_evk.c
@@ -131,12 +131,17 @@ static const struct spi_imx_master mx53_evk_spi_data __initconst = {
.num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
};
+void __init imx53_evk_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
+ ARRAY_SIZE(mx53_evk_pads));
+}
+
static void __init mx53_evk_board_init(void)
{
imx53_soc_init();
+ imx53_evk_common_init();
- mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
- ARRAY_SIZE(mx53_evk_pads));
mx53_evk_init_uart();
mx53_evk_fec_reset();
imx53_add_fec(&mx53_evk_fec_pdata);
@@ -167,6 +172,7 @@ MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
.map_io = mx53_map_io,
.init_early = imx53_init_early,
.init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
.timer = &mx53_evk_timer,
.init_machine = mx53_evk_board_init,
MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 4e1d51d252dc..7678f7734db6 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -22,6 +22,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/i2c.h>
#include <mach/common.h>
#include <mach/hardware.h>
@@ -42,6 +43,7 @@
#define LOCO_SD3_CD IMX_GPIO_NR(3, 11)
#define LOCO_SD3_WP IMX_GPIO_NR(3, 12)
#define LOCO_SD1_CD IMX_GPIO_NR(3, 13)
+#define LOCO_ACCEL_EN IMX_GPIO_NR(6, 14)
static iomux_v3_cfg_t mx53_loco_pads[] = {
/* FEC */
@@ -64,6 +66,10 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
+ /* I2C1 */
+ MX53_PAD_CSI0_DAT8__I2C1_SDA,
+ MX53_PAD_CSI0_DAT9__I2C1_SCL,
+ MX53_PAD_NANDF_CS1__GPIO6_14, /* Accelerometer Enable */
/* I2C2 */
MX53_PAD_KEY_COL3__I2C2_SCL,
MX53_PAD_KEY_ROW3__I2C2_SDA,
@@ -257,22 +263,42 @@ static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
.num_leds = ARRAY_SIZE(mx53loco_leds),
};
+void __init imx53_qsb_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
+ ARRAY_SIZE(mx53_loco_pads));
+}
+
+static struct i2c_board_info mx53loco_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("mma8450", 0x1C),
+ },
+};
+
static void __init mx53_loco_board_init(void)
{
+ int ret;
imx53_soc_init();
+ imx53_qsb_common_init();
- mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
- ARRAY_SIZE(mx53_loco_pads));
imx53_add_imx_uart(0, NULL);
mx53_loco_fec_reset();
imx53_add_fec(&mx53_loco_fec_data);
imx53_add_imx2_wdt(0, NULL);
+
+ ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
+ if (ret)
+ pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
+
+ i2c_register_board_info(0, mx53loco_i2c_devices,
+ ARRAY_SIZE(mx53loco_i2c_devices));
imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
imx_add_gpio_keys(&loco_button_data);
gpio_led_register_device(-1, &mx53loco_leds_data);
+ imx53_add_ahci_imx();
}
static void __init mx53_loco_timer_init(void)
@@ -288,6 +314,7 @@ MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
.map_io = mx53_map_io,
.init_early = imx53_init_early,
.init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
.timer = &mx53_loco_timer,
.init_machine = mx53_loco_board_init,
MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c
index bc02894eafef..59c0845eb4a6 100644
--- a/arch/arm/mach-mx5/board-mx53_smd.c
+++ b/arch/arm/mach-mx5/board-mx53_smd.c
@@ -35,6 +35,7 @@
#include "devices-imx53.h"
#define SMD_FEC_PHY_RST IMX_GPIO_NR(7, 6)
+#define MX53_SMD_SATA_PWR_EN IMX_GPIO_NR(3, 3)
static iomux_v3_cfg_t mx53_smd_pads[] = {
MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
@@ -111,12 +112,30 @@ static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
.bitrate = 100000,
};
+static inline void mx53_smd_ahci_pwr_on(void)
+{
+ int ret;
+
+ /* Enable SATA PWR */
+ ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
+ GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
+ if (ret) {
+ pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
+ return;
+ }
+}
+
+void __init imx53_smd_common_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
+ ARRAY_SIZE(mx53_smd_pads));
+}
+
static void __init mx53_smd_board_init(void)
{
imx53_soc_init();
+ imx53_smd_common_init();
- mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
- ARRAY_SIZE(mx53_smd_pads));
mx53_smd_init_uart();
mx53_smd_fec_reset();
imx53_add_fec(&mx53_smd_fec_data);
@@ -125,6 +144,8 @@ static void __init mx53_smd_board_init(void)
imx53_add_sdhci_esdhc_imx(0, NULL);
imx53_add_sdhci_esdhc_imx(1, NULL);
imx53_add_sdhci_esdhc_imx(2, NULL);
+ mx53_smd_ahci_pwr_on();
+ imx53_add_ahci_imx();
}
static void __init mx53_smd_timer_init(void)
@@ -140,6 +161,7 @@ MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
.map_io = mx53_map_io,
.init_early = imx53_init_early,
.init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
.timer = &mx53_smd_timer,
.init_machine = mx53_smd_board_init,
MACHINE_END
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index f7bf996f463b..2aacf41c48e7 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -15,6 +15,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
+#include <linux/of.h>
#include <asm/div64.h>
@@ -1401,6 +1402,22 @@ static struct clk esdhc4_mx53_clk = {
.secondary = &esdhc4_ipg_clk,
};
+static struct clk sata_clk = {
+ .parent = &ipg_clk,
+ .enable = _clk_max_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_max_disable,
+};
+
+static struct clk ahci_phy_clk = {
+ .parent = &usb_phy1_clk,
+};
+
+static struct clk ahci_dma_clk = {
+ .parent = &ahb_clk,
+};
+
DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
@@ -1418,6 +1435,10 @@ DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
NULL, NULL, &pll3_sw_clk, NULL);
+/* PATA */
+DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
+ NULL, NULL, &ipg_clk, &spba_clk);
+
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
@@ -1474,6 +1495,7 @@ static struct clk_lookup mx51_lookups[] = {
_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
_REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
+ _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
};
static struct clk_lookup mx53_lookups[] = {
@@ -1507,6 +1529,10 @@ static struct clk_lookup mx53_lookups[] = {
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
+ _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
+ _REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
+ _REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
+ _REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
};
static void clk_tree_init(void)
@@ -1548,9 +1574,8 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
clk_enable(&main_bus_clk);
clk_enable(&iim_clk);
- mx51_revision();
+ imx_print_silicon_rev("i.MX51", mx51_revision());
clk_disable(&iim_clk);
- mx51_display_revision();
/* move usb_phy_clk to 24MHz */
clk_set_parent(&usb_phy1_clk, &osc_clk);
@@ -1568,7 +1593,7 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
/* System timer */
mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
- MX51_MXC_INT_GPT);
+ MX51_INT_GPT);
return 0;
}
@@ -1592,9 +1617,8 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
clk_enable(&main_bus_clk);
clk_enable(&iim_clk);
- mx53_revision();
+ imx_print_silicon_rev("i.MX53", mx53_revision());
clk_disable(&iim_clk);
- mx53_display_revision();
/* Set SDHC parents to be PLL2 */
clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
@@ -1609,3 +1633,41 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
MX53_INT_GPT);
return 0;
}
+
+static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
+ unsigned long *ckih1, unsigned long *ckih2)
+{
+ struct device_node *np;
+
+ /* 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-ckil"))
+ *ckil = rate;
+ else if (of_device_is_compatible(np, "fsl,imx-osc"))
+ *osc = rate;
+ else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+ *ckih1 = rate;
+ else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
+ *ckih2 = rate;
+ }
+}
+
+int __init mx51_clocks_init_dt(void)
+{
+ unsigned long ckil, osc, ckih1, ckih2;
+
+ clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+ return mx51_clocks_init(ckil, osc, ckih1, ckih2);
+}
+
+int __init mx53_clocks_init_dt(void)
+{
+ unsigned long ckil, osc, ckih1, ckih2;
+
+ clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+ return mx53_clocks_init(ckil, osc, ckih1, ckih2);
+}
diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c
index 86f87da59c64..5c5328257dca 100644
--- a/arch/arm/mach-mx5/cpu.c
+++ b/arch/arm/mach-mx5/cpu.c
@@ -18,7 +18,7 @@
#include <mach/hardware.h>
#include <asm/io.h>
-static int cpu_silicon_rev = -1;
+static int mx5_cpu_rev = -1;
#define IIM_SREV 0x24
#define MX50_HW_ADADIG_DIGPROG 0xB0
@@ -28,11 +28,14 @@ static int get_mx51_srev(void)
void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
u32 rev = readl(iim_base + IIM_SREV) & 0xff;
- if (rev == 0x0)
+ switch (rev) {
+ case 0x0:
return IMX_CHIP_REVISION_2_0;
- else if (rev == 0x10)
+ case 0x10:
return IMX_CHIP_REVISION_3_0;
- return 0;
+ default:
+ return IMX_CHIP_REVISION_UNKNOWN;
+ }
}
/*
@@ -45,33 +48,13 @@ int mx51_revision(void)
if (!cpu_is_mx51())
return -EINVAL;
- if (cpu_silicon_rev == -1)
- cpu_silicon_rev = get_mx51_srev();
+ if (mx5_cpu_rev == -1)
+ mx5_cpu_rev = get_mx51_srev();
- return cpu_silicon_rev;
+ return mx5_cpu_rev;
}
EXPORT_SYMBOL(mx51_revision);
-void mx51_display_revision(void)
-{
- int rev;
- char *srev;
- rev = mx51_revision();
-
- switch (rev) {
- case IMX_CHIP_REVISION_2_0:
- srev = IMX_CHIP_REVISION_2_0_STRING;
- break;
- case IMX_CHIP_REVISION_3_0:
- srev = IMX_CHIP_REVISION_3_0_STRING;
- break;
- default:
- srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
- }
- printk(KERN_INFO "CPU identified as i.MX51, silicon rev %s\n", srev);
-}
-EXPORT_SYMBOL(mx51_display_revision);
-
#ifdef CONFIG_NEON
/*
@@ -121,10 +104,10 @@ int mx53_revision(void)
if (!cpu_is_mx53())
return -EINVAL;
- if (cpu_silicon_rev == -1)
- cpu_silicon_rev = get_mx53_srev();
+ if (mx5_cpu_rev == -1)
+ mx5_cpu_rev = get_mx53_srev();
- return cpu_silicon_rev;
+ return mx5_cpu_rev;
}
EXPORT_SYMBOL(mx53_revision);
@@ -134,7 +117,7 @@ static int get_mx50_srev(void)
u32 rev;
if (!anatop) {
- cpu_silicon_rev = -EINVAL;
+ mx5_cpu_rev = -EINVAL;
return 0;
}
@@ -159,36 +142,13 @@ int mx50_revision(void)
if (!cpu_is_mx50())
return -EINVAL;
- if (cpu_silicon_rev == -1)
- cpu_silicon_rev = get_mx50_srev();
+ if (mx5_cpu_rev == -1)
+ mx5_cpu_rev = get_mx50_srev();
- return cpu_silicon_rev;
+ return mx5_cpu_rev;
}
EXPORT_SYMBOL(mx50_revision);
-void mx53_display_revision(void)
-{
- int rev;
- char *srev;
- rev = mx53_revision();
-
- switch (rev) {
- case IMX_CHIP_REVISION_1_0:
- srev = IMX_CHIP_REVISION_1_0_STRING;
- break;
- case IMX_CHIP_REVISION_2_0:
- srev = IMX_CHIP_REVISION_2_0_STRING;
- break;
- case IMX_CHIP_REVISION_2_1:
- srev = IMX_CHIP_REVISION_2_1_STRING;
- break;
- default:
- srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
- }
- printk(KERN_INFO "CPU identified as i.MX53, silicon rev %s\n", srev);
-}
-EXPORT_SYMBOL(mx53_display_revision);
-
static int __init post_cpu_init(void)
{
unsigned int reg;
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
index e11bc0e0ec49..af488bc0e225 100644
--- a/arch/arm/mach-mx5/devices-imx51.h
+++ b/arch/arm/mach-mx5/devices-imx51.h
@@ -13,9 +13,15 @@ extern const struct imx_fec_data imx51_fec_data;
#define imx51_add_fec(pdata) \
imx_add_fec(&imx51_fec_data, pdata)
+extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
+#define imx51_add_fsl_usb2_udc(pdata) \
+ imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
+
extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
#define imx51_add_imx_i2c(id, pdata) \
imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+#define imx51_add_hsi2c(pdata) \
+ imx51_add_imx_i2c(2, pdata)
extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
#define imx51_add_imx_ssi(id, pdata) \
@@ -25,6 +31,13 @@ extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[];
#define imx51_add_imx_uart(id, pdata) \
imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
+#define imx51_add_mxc_ehci_otg(pdata) \
+ imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
+#define imx51_add_mxc_ehci_hs(id, pdata) \
+ imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
+
extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
#define imx51_add_mxc_nand(pdata) \
imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
@@ -52,3 +65,7 @@ extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
#define imx51_add_imx_keypad(pdata) \
imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx51_pata_imx_data;
+#define imx51_add_pata_imx() \
+ imx_add_pata_imx(&imx51_pata_imx_data)
diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h
index c27fe8bb4762..6e1e5d1f8c3a 100644
--- a/arch/arm/mach-mx5/devices-imx53.h
+++ b/arch/arm/mach-mx5/devices-imx53.h
@@ -40,3 +40,9 @@ extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
#define imx53_add_imx_keypad(pdata) \
imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx53_pata_imx_data;
+#define imx53_add_pata_imx() \
+ imx_add_pata_imx(&imx53_pata_imx_data)
+
+extern struct platform_device *__init imx53_add_ahci_imx(void);
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
deleted file mode 100644
index 371ca8c8414c..000000000000
--- a/arch/arm/mach-mx5/devices.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2009 Amit Kucheria <amit.kucheria@canonical.com>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * 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/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/imx-uart.h>
-#include <mach/irqs.h>
-
-static struct resource mxc_hsi2c_resources[] = {
- {
- .start = MX51_HSI2C_DMA_BASE_ADDR,
- .end = MX51_HSI2C_DMA_BASE_ADDR + SZ_16K - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = MX51_MXC_INT_HS_I2C,
- .end = MX51_MXC_INT_HS_I2C,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_hsi2c_device = {
- .name = "imx-i2c",
- .id = 2,
- .num_resources = ARRAY_SIZE(mxc_hsi2c_resources),
- .resource = mxc_hsi2c_resources
-};
-
-static u64 usb_dma_mask = DMA_BIT_MASK(32);
-
-static struct resource usbotg_resources[] = {
- {
- .start = MX51_OTG_BASE_ADDR,
- .end = MX51_OTG_BASE_ADDR + 0x1ff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = MX51_MXC_INT_USB_OTG,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-/* OTG gadget device */
-struct platform_device mxc_usbdr_udc_device = {
- .name = "fsl-usb2-udc",
- .id = -1,
- .num_resources = ARRAY_SIZE(usbotg_resources),
- .resource = usbotg_resources,
- .dev = {
- .dma_mask = &usb_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-struct platform_device mxc_usbdr_host_device = {
- .name = "mxc-ehci",
- .id = 0,
- .num_resources = ARRAY_SIZE(usbotg_resources),
- .resource = usbotg_resources,
- .dev = {
- .dma_mask = &usb_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-static struct resource usbh1_resources[] = {
- {
- .start = MX51_OTG_BASE_ADDR + 0x200,
- .end = MX51_OTG_BASE_ADDR + 0x200 + 0x1ff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = MX51_MXC_INT_USB_H1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_usbh1_device = {
- .name = "mxc-ehci",
- .id = 1,
- .num_resources = ARRAY_SIZE(usbh1_resources),
- .resource = usbh1_resources,
- .dev = {
- .dma_mask = &usb_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-static struct resource usbh2_resources[] = {
- {
- .start = MX51_OTG_BASE_ADDR + 0x400,
- .end = MX51_OTG_BASE_ADDR + 0x400 + 0x1ff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = MX51_MXC_INT_USB_H2,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_usbh2_device = {
- .name = "mxc-ehci",
- .id = 2,
- .num_resources = ARRAY_SIZE(usbh2_resources),
- .resource = usbh2_resources,
- .dev = {
- .dma_mask = &usb_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h
deleted file mode 100644
index 55a5129bc29f..000000000000
--- a/arch/arm/mach-mx5/devices.h
+++ /dev/null
@@ -1,5 +0,0 @@
-extern struct platform_device mxc_usbdr_host_device;
-extern struct platform_device mxc_usbh1_device;
-extern struct platform_device mxc_usbh2_device;
-extern struct platform_device mxc_usbdr_udc_device;
-extern struct platform_device mxc_hsi2c_device;
diff --git a/arch/arm/mach-mx5/ehci.c b/arch/arm/mach-mx5/ehci.c
index 7ce12c804a32..c17fa131728b 100644
--- a/arch/arm/mach-mx5/ehci.c
+++ b/arch/arm/mach-mx5/ehci.c
@@ -52,7 +52,7 @@ int mx51_initialize_usb_hw(int port, unsigned int flags)
void __iomem *usbother_base;
int ret = 0;
- usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
if (!usb_base) {
printk(KERN_ERR "%s(): ioremap failed\n", __func__);
return -ENOMEM;
diff --git a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
index bbf4564bd050..a6a3ab8f1b1c 100644
--- a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
@@ -28,7 +28,6 @@
#include <asm/mach/arch.h>
#include "devices-imx51.h"
-#include "devices.h"
#define MBIMX51_TSC2007_GPIO IMX_GPIO_NR(3, 30)
#define MBIMX51_LED0 IMX_GPIO_NR(3, 5)
@@ -160,7 +159,7 @@ struct tsc2007_platform_data tsc2007_data = {
static struct i2c_board_info mbimx51_i2c_devices[] = {
{
I2C_BOARD_INFO("tsc2007", 0x49),
- .irq = gpio_to_irq(MBIMX51_TSC2007_GPIO),
+ .irq = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
.platform_data = &tsc2007_data,
}, {
I2C_BOARD_INFO("tlv320aic23", 0x1a),
diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
index 261923997643..d817fc80b986 100644
--- a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
@@ -24,7 +24,6 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/input.h>
@@ -41,13 +40,12 @@
#include <mach/audmux.h>
#include "devices-imx51.h"
-#include "devices.h"
static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
/* LED */
MX51_PAD_NANDF_D10__GPIO3_30,
/* SWITCH */
- _MX51_PAD_NANDF_D9__GPIO3_31 | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+ NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP |
PAD_CTL_PKE | PAD_CTL_SRE_FAST |
PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
/* UART2 */
@@ -66,7 +64,7 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
MX51_PAD_SD1_DATA2__SD1_DATA2,
MX51_PAD_SD1_DATA3__SD1_DATA3,
/* SD1 CD */
- _MX51_PAD_GPIO1_0__SD1_CD | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+ NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
PAD_CTL_PKE | PAD_CTL_SRE_FAST |
PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
};
diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c
new file mode 100644
index 000000000000..ccc61585659b
--- /dev/null
+++ b/arch/arm/mach-mx5/imx51-dt.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate(). Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+ OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+ OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+ { /* sentinel */ }
+};
+
+static void __init imx51_tzic_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ irq_domain_add_simple(np, 0);
+}
+
+static void __init imx51_gpio_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS -
+ 32 * 4; /* imx51 gets 4 gpio ports */
+
+ irq_domain_add_simple(np, gpio_irq_base);
+ gpio_irq_base += 32;
+}
+
+static const struct of_device_id imx51_irq_match[] __initconst = {
+ { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
+ { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
+ { /* sentinel */ }
+};
+
+static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
+ { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
+ { /* sentinel */ }
+};
+
+static void __init imx51_dt_init(void)
+{
+ struct device_node *node;
+ const struct of_device_id *of_id;
+ void (*func)(void);
+
+ of_irq_init(imx51_irq_match);
+
+ node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
+ if (node) {
+ of_id = of_match_node(imx51_iomuxc_of_match, node);
+ func = of_id->data;
+ func();
+ of_node_put(node);
+ }
+
+ of_platform_populate(NULL, of_default_bus_match_table,
+ imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+ mx51_clocks_init_dt();
+}
+
+static struct sys_timer imx51_timer = {
+ .init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+ "fsl,imx51-babbage",
+ NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+ .map_io = mx51_map_io,
+ .init_early = imx51_init_early,
+ .init_irq = mx51_init_irq,
+ .handle_irq = imx51_handle_irq,
+ .timer = &imx51_timer,
+ .init_machine = imx51_dt_init,
+ .dt_compat = imx51_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/imx53-dt.c b/arch/arm/mach-mx5/imx53-dt.c
new file mode 100644
index 000000000000..ccaa0b81b768
--- /dev/null
+++ b/arch/arm/mach-mx5/imx53-dt.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx53.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate(). Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+ OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+ { /* sentinel */ }
+};
+
+static void __init imx53_tzic_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ irq_domain_add_simple(np, 0);
+}
+
+static void __init imx53_gpio_add_irq_domain(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS -
+ 32 * 7; /* imx53 gets 7 gpio ports */
+
+ irq_domain_add_simple(np, gpio_irq_base);
+ gpio_irq_base += 32;
+}
+
+static const struct of_device_id imx53_irq_match[] __initconst = {
+ { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
+ { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
+ { /* sentinel */ }
+};
+
+static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
+ { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
+ { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
+ { .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
+ { .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
+ { /* sentinel */ }
+};
+
+static void __init imx53_dt_init(void)
+{
+ struct device_node *node;
+ const struct of_device_id *of_id;
+ void (*func)(void);
+
+ of_irq_init(imx53_irq_match);
+
+ node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
+ if (node) {
+ of_id = of_match_node(imx53_iomuxc_of_match, node);
+ func = of_id->data;
+ func();
+ of_node_put(node);
+ }
+
+ of_platform_populate(NULL, of_default_bus_match_table,
+ imx53_auxdata_lookup, NULL);
+}
+
+static void __init imx53_timer_init(void)
+{
+ mx53_clocks_init_dt();
+}
+
+static struct sys_timer imx53_timer = {
+ .init = imx53_timer_init,
+};
+
+static const char *imx53_dt_board_compat[] __initdata = {
+ "fsl,imx53-ard",
+ "fsl,imx53-evk",
+ "fsl,imx53-qsb",
+ "fsl,imx53-smd",
+ NULL
+};
+
+DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
+ .map_io = mx53_map_io,
+ .init_early = imx53_init_early,
+ .init_irq = mx53_init_irq,
+ .handle_irq = imx53_handle_irq,
+ .timer = &imx53_timer,
+ .init_machine = imx53_dt_init,
+ .dt_compat = imx53_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/mm-mx50.c b/arch/arm/mach-mx5/mm-mx50.c
deleted file mode 100644
index 77e374c726fa..000000000000
--- a/arch/arm/mach-mx5/mm-mx50.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; 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.
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-/*
- * Define the MX50 memory map.
- */
-static struct map_desc mx50_io_desc[] __initdata = {
- imx_map_entry(MX50, TZIC, MT_DEVICE),
- imx_map_entry(MX50, SPBA0, MT_DEVICE),
- imx_map_entry(MX50, AIPS1, MT_DEVICE),
- imx_map_entry(MX50, AIPS2, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx50_map_io(void)
-{
- iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
-}
-
-void __init imx50_init_early(void)
-{
- mxc_set_cpu_type(MXC_CPU_MX50);
- mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
- mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
-}
-
-void __init mx50_init_irq(void)
-{
- tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-}
-
-void __init imx50_soc_init(void)
-{
- /* i.mx50 has the i.mx31 type gpio */
- mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
- mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
- mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
- mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
- mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
- mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
-}
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
index baea6e5cddd9..26eacc9d0d90 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -21,12 +21,27 @@
#include <mach/devices-common.h>
#include <mach/iomux-v3.h>
+static void imx5_idle(void)
+{
+ mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+}
+
+/*
+ * Define the MX50 memory map.
+ */
+static struct map_desc mx50_io_desc[] __initdata = {
+ imx_map_entry(MX50, TZIC, MT_DEVICE),
+ imx_map_entry(MX50, SPBA0, MT_DEVICE),
+ imx_map_entry(MX50, AIPS1, MT_DEVICE),
+ imx_map_entry(MX50, AIPS2, MT_DEVICE),
+};
+
/*
* Define the MX51 memory map.
*/
static struct map_desc mx51_io_desc[] __initdata = {
+ imx_map_entry(MX51, TZIC, MT_DEVICE),
imx_map_entry(MX51, IRAM, MT_DEVICE),
- imx_map_entry(MX51, DEBUG, MT_DEVICE),
imx_map_entry(MX51, AIPS1, MT_DEVICE),
imx_map_entry(MX51, SPBA0, MT_DEVICE),
imx_map_entry(MX51, AIPS2, MT_DEVICE),
@@ -36,6 +51,7 @@ static struct map_desc mx51_io_desc[] __initdata = {
* Define the MX53 memory map.
*/
static struct map_desc mx53_io_desc[] __initdata = {
+ imx_map_entry(MX53, TZIC, MT_DEVICE),
imx_map_entry(MX53, AIPS1, MT_DEVICE),
imx_map_entry(MX53, SPBA0, MT_DEVICE),
imx_map_entry(MX53, AIPS2, MT_DEVICE),
@@ -46,21 +62,34 @@ static struct map_desc mx53_io_desc[] __initdata = {
* system startup to create static physical to virtual memory mappings
* for the IO modules.
*/
+void __init mx50_map_io(void)
+{
+ iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
+}
+
void __init mx51_map_io(void)
{
iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
}
+void __init mx53_map_io(void)
+{
+ iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+}
+
+void __init imx50_init_early(void)
+{
+ mxc_set_cpu_type(MXC_CPU_MX50);
+ mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
+ mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
+}
+
void __init imx51_init_early(void)
{
mxc_set_cpu_type(MXC_CPU_MX51);
mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
-}
-
-void __init mx53_map_io(void)
-{
- iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+ imx_idle = imx5_idle;
}
void __init imx53_init_early(void)
@@ -70,35 +99,19 @@ void __init imx53_init_early(void)
mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
}
-void __init mx51_init_irq(void)
+void __init mx50_init_irq(void)
{
- unsigned long tzic_addr;
- void __iomem *tzic_virt;
-
- if (mx51_revision() < IMX_CHIP_REVISION_2_0)
- tzic_addr = MX51_TZIC_BASE_ADDR_TO1;
- else
- tzic_addr = MX51_TZIC_BASE_ADDR;
-
- tzic_virt = ioremap(tzic_addr, SZ_16K);
- if (!tzic_virt)
- panic("unable to map TZIC interrupt controller\n");
+ tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
+}
- tzic_init_irq(tzic_virt);
+void __init mx51_init_irq(void)
+{
+ tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
}
void __init mx53_init_irq(void)
{
- unsigned long tzic_addr;
- void __iomem *tzic_virt;
-
- tzic_addr = MX53_TZIC_BASE_ADDR;
-
- tzic_virt = ioremap(tzic_addr, SZ_16K);
- if (!tzic_virt)
- panic("unable to map TZIC interrupt controller\n");
-
- tzic_init_irq(tzic_virt);
+ tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
}
static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
@@ -138,13 +151,24 @@ static struct sdma_platform_data imx53_sdma_pdata __initdata = {
.script_addrs = &imx53_sdma_script,
};
+void __init imx50_soc_init(void)
+{
+ /* i.mx50 has the i.mx31 type gpio */
+ mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
+ mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
+ mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
+ mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
+ mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
+ mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
+}
+
void __init imx51_soc_init(void)
{
/* i.mx51 has the i.mx31 type gpio */
- mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
- mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
- mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
- mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
+ mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
+ mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
+ mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
+ mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
/* i.mx51 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
diff --git a/arch/arm/mach-mx5/mx51_efika.c b/arch/arm/mach-mx5/mx51_efika.c
index 8e1ded2420bc..ec6ca91b299b 100644
--- a/arch/arm/mach-mx5/mx51_efika.c
+++ b/arch/arm/mach-mx5/mx51_efika.c
@@ -34,14 +34,12 @@
#include <linux/usb/ulpi.h>
#include <mach/ulpi.h>
-#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include "devices-imx51.h"
-#include "devices.h"
#include "efika.h"
#include "cpu_op-mx51.h"
@@ -133,7 +131,7 @@ static int initialize_otg_port(struct platform_device *pdev)
u32 v;
void __iomem *usb_base;
void __iomem *usbother_base;
- usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
if (!usb_base)
return -ENOMEM;
usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
@@ -150,7 +148,7 @@ static int initialize_otg_port(struct platform_device *pdev)
return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
}
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
.init = initialize_otg_port,
.portsc = MXC_EHCI_UTMI_16BIT,
};
@@ -170,7 +168,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
gpio_set_value(EFIKAMX_USBH1_STP, 1);
msleep(1);
- usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
/* The clock for the USBH1 ULPI port will come externally */
@@ -189,7 +187,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
}
-static struct mxc_usbh_platform_data usbh1_config = {
+static struct mxc_usbh_platform_data usbh1_config __initdata = {
.init = initialize_usbh1_port,
.portsc = MXC_EHCI_MODE_ULPI,
};
@@ -217,9 +215,9 @@ static void __init mx51_efika_usb(void)
usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
- mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+ imx51_add_mxc_ehci_otg(&dr_utmi_config);
if (usbh1_config.otg)
- mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+ imx51_add_mxc_ehci_hs(1, &usbh1_config);
}
static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
@@ -589,7 +587,7 @@ static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
.bus_num = 0,
.chip_select = 0,
.platform_data = &mx51_efika_mc13892_data,
- .irq = gpio_to_irq(EFIKAMX_PMIC),
+ .irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
},
};
@@ -609,7 +607,6 @@ void __init efika_board_common_init(void)
ARRAY_SIZE(mx51efika_pads));
imx51_add_imx_uart(0, &uart_pdata);
mx51_efika_usb();
- imx51_add_sdhci_esdhc_imx(0, NULL);
/* FIXME: comes from original code. check this. */
if (mx51_revision() < IMX_CHIP_REVISION_2_0)
@@ -627,8 +624,9 @@ void __init efika_board_common_init(void)
ARRAY_SIZE(mx51_efika_spi_board_info));
imx51_add_ecspi(0, &mx51_efika_spi_pdata);
+ imx51_add_pata_imx();
+
#if defined(CONFIG_CPU_FREQ_IMX)
get_cpu_op = mx51_get_cpu_op;
#endif
}
-
diff --git a/arch/arm/mach-mx5/pm-imx5.c b/arch/arm/mach-mx5/pm-imx5.c
index e4529af0da72..98052fc852c7 100644
--- a/arch/arm/mach-mx5/pm-imx5.c
+++ b/arch/arm/mach-mx5/pm-imx5.c
@@ -14,14 +14,19 @@
#include <linux/err.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
-#include <mach/system.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
#include "crm_regs.h"
static struct clk *gpc_dvfs_clk;
+static int mx5_suspend_prepare(void)
+{
+ return clk_enable(gpc_dvfs_clk);
+}
+
static int mx5_suspend_enter(suspend_state_t state)
{
- clk_enable(gpc_dvfs_clk);
switch (state) {
case PM_SUSPEND_MEM:
mx5_cpu_lp_set(STOP_POWER_OFF);
@@ -42,11 +47,14 @@ static int mx5_suspend_enter(suspend_state_t state)
__raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
}
cpu_do_idle();
- clk_disable(gpc_dvfs_clk);
-
return 0;
}
+static void mx5_suspend_finish(void)
+{
+ clk_disable(gpc_dvfs_clk);
+}
+
static int mx5_pm_valid(suspend_state_t state)
{
return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
@@ -54,7 +62,9 @@ static int mx5_pm_valid(suspend_state_t state)
static const struct platform_suspend_ops mx5_suspend_ops = {
.valid = mx5_pm_valid,
+ .prepare = mx5_suspend_prepare,
.enter = mx5_suspend_enter,
+ .finish = mx5_suspend_finish,
};
static int __init mx5_pm_init(void)
diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c
index 76ae8dc33e00..144ebebc4a61 100644
--- a/arch/arm/mach-mx5/system.c
+++ b/arch/arm/mach-mx5/system.c
@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <mach/hardware.h>
+#include <mach/common.h>
#include "crm_regs.h"
/* set cpu low power mode before WFI instruction. This function is called
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index 4cd0231ee539..cf00b3e3be85 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -23,6 +23,7 @@ config MACH_STMP378X_DEVB
select MXS_HAVE_AMBA_DUART
select MXS_HAVE_PLATFORM_AUART
select MXS_HAVE_PLATFORM_MXS_MMC
+ select MXS_HAVE_PLATFORM_RTC_STMP3XXX
help
Include support for STMP378x-devb platform. This includes specific
configurations for the board and its peripherals.
@@ -34,6 +35,7 @@ config MACH_MX23EVK
select MXS_HAVE_PLATFORM_AUART
select MXS_HAVE_PLATFORM_MXS_MMC
select MXS_HAVE_PLATFORM_MXSFB
+ select MXS_HAVE_PLATFORM_RTC_STMP3XXX
help
Include support for MX23EVK platform. This includes specific
configurations for the board and its peripherals.
@@ -48,6 +50,9 @@ config MACH_MX28EVK
select MXS_HAVE_PLATFORM_FLEXCAN
select MXS_HAVE_PLATFORM_MXS_MMC
select MXS_HAVE_PLATFORM_MXSFB
+ select MXS_HAVE_PLATFORM_MXS_SAIF
+ select MXS_HAVE_PLATFORM_MXS_I2C
+ select MXS_HAVE_PLATFORM_RTC_STMP3XXX
select MXS_OCOTP
help
Include support for MX28EVK platform. This includes specific
@@ -63,9 +68,27 @@ config MODULE_TX28
select MXS_HAVE_PLATFORM_MXS_I2C
select MXS_HAVE_PLATFORM_MXS_MMC
select MXS_HAVE_PLATFORM_MXS_PWM
+ select MXS_HAVE_PLATFORM_RTC_STMP3XXX
+
+config MODULE_M28
+ bool
+ select SOC_IMX28
+ select LEDS_GPIO_REGISTER
+ select MXS_HAVE_AMBA_DUART
+ select MXS_HAVE_PLATFORM_AUART
+ select MXS_HAVE_PLATFORM_FEC
+ select MXS_HAVE_PLATFORM_FLEXCAN
+ select MXS_HAVE_PLATFORM_MXS_I2C
+ select MXS_HAVE_PLATFORM_MXS_MMC
+ select MXS_HAVE_PLATFORM_MXSFB
+ select MXS_OCOTP
config MACH_TX28
bool "Ka-Ro TX28 module"
select MODULE_TX28
+config MACH_M28EVK
+ bool "Support DENX M28EVK Platform"
+ select MODULE_M28
+
endif
diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
index 6c38262a3aaa..8c93b24896bf 100644
--- a/arch/arm/mach-mxs/Makefile
+++ b/arch/arm/mach-mxs/Makefile
@@ -1,15 +1,16 @@
# Common support
-obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o
+obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o mm.o
obj-$(CONFIG_MXS_OCOTP) += ocotp.o
obj-$(CONFIG_PM) += pm.o
-obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
-obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
+obj-$(CONFIG_SOC_IMX23) += clock-mx23.o
+obj-$(CONFIG_SOC_IMX28) += clock-mx28.o
obj-$(CONFIG_MACH_STMP378X_DEVB) += mach-stmp378x_devb.o
obj-$(CONFIG_MACH_MX23EVK) += mach-mx23evk.o
obj-$(CONFIG_MACH_MX28EVK) += mach-mx28evk.o
+obj-$(CONFIG_MACH_M28EVK) += mach-m28evk.o
obj-$(CONFIG_MODULE_TX28) += module-tx28.o
obj-$(CONFIG_MACH_TX28) += mach-tx28.o
diff --git a/arch/arm/mach-mxs/Makefile.boot b/arch/arm/mach-mxs/Makefile.boot
index eb541e0291da..07b11fe6453f 100644
--- a/arch/arm/mach-mxs/Makefile.boot
+++ b/arch/arm/mach-mxs/Makefile.boot
@@ -1 +1 @@
-zreladdr-y := 0x40008000
+zreladdr-y += 0x40008000
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index 5dcc59d5b9ec..229ae3494216 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -349,7 +349,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
\
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr); \
reg &= ~BM_CLKCTRL_##fr##_##fs##FRAC; \
- reg |= frac; \
+ reg |= frac << BP_CLKCTRL_##fr##_##fs##FRAC; \
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr); \
} \
\
@@ -640,6 +640,8 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "lradc", lradc_clk)
_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
_REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk)
+ _REGISTER_CLOCK("mxs-saif.0", NULL, saif0_clk)
+ _REGISTER_CLOCK("mxs-saif.1", NULL, saif1_clk)
};
static int clk_misc_init(void)
@@ -708,11 +710,11 @@ static int clk_misc_init(void)
/* SAIF has to use frac div for functional operation */
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0);
- reg &= ~BM_CLKCTRL_SAIF0_DIV_FRAC_EN;
+ reg |= BM_CLKCTRL_SAIF0_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0);
reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
- reg &= ~BM_CLKCTRL_SAIF1_DIV_FRAC_EN;
+ reg |= BM_CLKCTRL_SAIF1_DIV_FRAC_EN;
__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
/*
@@ -738,11 +740,17 @@ static int clk_misc_init(void)
__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET);
- /* Extra fec clock setting */
- reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
- reg &= ~BM_CLKCTRL_ENET_SLEEP;
- reg |= BM_CLKCTRL_ENET_CLK_OUT_EN;
- __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+ /*
+ * Extra fec clock setting
+ * The DENX M28 uses an external clock source
+ * and the clock output must not be enabled
+ */
+ if (!machine_is_m28evk()) {
+ reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+ reg &= ~BM_CLKCTRL_ENET_SLEEP;
+ reg |= BM_CLKCTRL_ENET_CLK_OUT_EN;
+ __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+ }
/*
* 480 MHz seems too high to be ssp clock source directly,
@@ -774,6 +782,8 @@ int __init mx28_clocks_init(void)
clk_enable(&uart_clk);
clk_set_parent(&lcdif_clk, &ref_pix_clk);
+ clk_set_parent(&saif0_clk, &pll0_clk);
+ clk_set_parent(&saif1_clk, &pll0_clk);
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
index c6f345febd39..3fa651d2c994 100644
--- a/arch/arm/mach-mxs/devices-mx23.h
+++ b/arch/arm/mach-mxs/devices-mx23.h
@@ -29,3 +29,5 @@ extern const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst;
struct platform_device *__init mx23_add_mxsfb(
const struct mxsfb_platform_data *pdata);
+
+struct platform_device *__init mx23_add_rtc_stmp3xxx(void);
diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
index 79b94523954a..c8887103f0e3 100644
--- a/arch/arm/mach-mxs/devices-mx28.h
+++ b/arch/arm/mach-mxs/devices-mx28.h
@@ -45,3 +45,8 @@ extern const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst;
struct platform_device *__init mx28_add_mxsfb(
const struct mxsfb_platform_data *pdata);
+
+extern const struct mxs_saif_data mx28_saif_data[] __initconst;
+#define mx28_add_saif(id) mxs_add_saif(&mx28_saif_data[id])
+
+struct platform_device *__init mx28_add_rtc_stmp3xxx(void);
diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
index acf9eea124c0..18b6bf526a27 100644
--- a/arch/arm/mach-mxs/devices/Kconfig
+++ b/arch/arm/mach-mxs/devices/Kconfig
@@ -23,3 +23,9 @@ config MXS_HAVE_PLATFORM_MXS_PWM
config MXS_HAVE_PLATFORM_MXSFB
bool
+
+config MXS_HAVE_PLATFORM_MXS_SAIF
+ bool
+
+config MXS_HAVE_PLATFORM_RTC_STMP3XXX
+ bool
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index 351915c683ff..f52e3e53baec 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -8,3 +8,5 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
obj-y += platform-gpio-mxs.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_SAIF) += platform-mxs-saif.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_RTC_STMP3XXX) += platform-rtc-stmp3xxx.o
diff --git a/arch/arm/mach-mxs/devices/platform-mxs-saif.c b/arch/arm/mach-mxs/devices/platform-mxs-saif.c
new file mode 100644
index 000000000000..1ec965e9fe92
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-mxs-saif.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_saif_data_entry_single(soc, _id) \
+ { \
+ .id = _id, \
+ .iobase = soc ## _SAIF ## _id ## _BASE_ADDR, \
+ .irq = soc ## _INT_SAIF ## _id, \
+ .dma = soc ## _DMA_SAIF ## _id, \
+ .dmairq = soc ## _INT_SAIF ## _id ##_DMA, \
+ }
+
+#define mxs_saif_data_entry(soc, _id) \
+ [_id] = mxs_saif_data_entry_single(soc, _id)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_saif_data mx28_saif_data[] __initconst = {
+ mxs_saif_data_entry(MX28, 0),
+ mxs_saif_data_entry(MX28, 1),
+};
+#endif
+
+struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = data->dma,
+ .end = data->dma,
+ .flags = IORESOURCE_DMA,
+ }, {
+ .start = data->dmairq,
+ .end = data->dmairq,
+ .flags = IORESOURCE_IRQ,
+ },
+
+ };
+
+ return mxs_add_platform_device("mxs-saif", data->id, res,
+ ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c b/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
new file mode 100644
index 000000000000..639eaee15553
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Pengutronix, Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <asm/sizes.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#ifdef CONFIG_SOC_IMX23
+struct platform_device *__init mx23_add_rtc_stmp3xxx(void)
+{
+ struct resource res[] = {
+ {
+ .start = MX23_RTC_BASE_ADDR,
+ .end = MX23_RTC_BASE_ADDR + SZ_8K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = MX23_INT_RTC_ALARM,
+ .end = MX23_INT_RTC_ALARM,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
+ NULL, 0);
+}
+#endif /* CONFIG_SOC_IMX23 */
+
+#ifdef CONFIG_SOC_IMX28
+struct platform_device *__init mx28_add_rtc_stmp3xxx(void)
+{
+ struct resource res[] = {
+ {
+ .start = MX28_RTC_BASE_ADDR,
+ .end = MX28_RTC_BASE_ADDR + SZ_8K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = MX28_INT_RTC_ALARM,
+ .end = MX28_INT_RTC_ALARM,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
+ NULL, 0);
+}
+#endif /* CONFIG_SOC_IMX28 */
diff --git a/arch/arm/mach-mxs/include/mach/debug-macro.S b/arch/arm/mach-mxs/include/mach/debug-macro.S
index 79650a1ad78d..90c6b7836ad3 100644
--- a/arch/arm/mach-mxs/include/mach/debug-macro.S
+++ b/arch/arm/mach-mxs/include/mach/debug-macro.S
@@ -14,23 +14,15 @@
#include <mach/mx23.h>
#include <mach/mx28.h>
-#ifdef CONFIG_SOC_IMX23
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#ifdef CONFIG_DEBUG_IMX23_UART
#define UART_PADDR MX23_DUART_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX28
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX28_UART)
#define UART_PADDR MX28_DUART_BASE_ADDR
#endif
#define UART_VADDR MXS_IO_ADDRESS(UART_PADDR)
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =UART_PADDR @ physical
ldr \rv, =UART_VADDR @ virtual
.endm
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
index 812d7a813a78..a8080f44c03d 100644
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -92,3 +92,15 @@ struct platform_device *__init mxs_add_mxs_mmc(
/* pwm */
struct platform_device *__init mxs_add_mxs_pwm(
resource_size_t iobase, int id);
+
+/* saif */
+struct mxs_saif_data {
+ int id;
+ resource_size_t iobase;
+ resource_size_t irq;
+ resource_size_t dma;
+ resource_size_t dmairq;
+};
+
+struct platform_device *__init mxs_add_saif(
+ const struct mxs_saif_data *data);
diff --git a/arch/arm/mach-mxs/include/mach/gpio.h b/arch/arm/mach-mxs/include/mach/gpio.h
index 828ccccb6aad..40a8c178f10d 100644
--- a/arch/arm/mach-mxs/include/mach/gpio.h
+++ b/arch/arm/mach-mxs/include/mach/gpio.h
@@ -1,35 +1 @@
-/*
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __MACH_MXS_GPIO_H__
-#define __MACH_MXS_GPIO_H__
-
-#include <asm-generic/gpio.h>
-
-#define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr))
-
-/* use gpiolib dispatchers */
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
-#define irq_to_gpio(irq) ((irq) - MXS_GPIO_IRQ_START)
-
-#endif /* __MACH_MXS_GPIO_H__ */
+/* empty */
diff --git a/arch/arm/mach-mxs/include/mach/mxs.h b/arch/arm/mach-mxs/include/mach/mxs.h
index 35a89dd27242..0d2d2b470998 100644
--- a/arch/arm/mach-mxs/include/mach/mxs.h
+++ b/arch/arm/mach-mxs/include/mach/mxs.h
@@ -33,6 +33,7 @@
0)
#define cpu_is_mx28() ( \
machine_is_mx28evk() || \
+ machine_is_m28evk() || \
machine_is_tx28() || \
0)
@@ -86,6 +87,8 @@
.type = _type, \
}
+#define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr))
+
#define MXS_SET_ADDR 0x4
#define MXS_CLR_ADDR 0x8
#define MXS_TOG_ADDR 0xc
diff --git a/arch/arm/mach-mxs/include/mach/uncompress.h b/arch/arm/mach-mxs/include/mach/uncompress.h
index 7f8bf6539646..67776746f143 100644
--- a/arch/arm/mach-mxs/include/mach/uncompress.h
+++ b/arch/arm/mach-mxs/include/mach/uncompress.h
@@ -63,6 +63,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
mxs_duart_base = MX23_DUART_BASE_ADDR;
break;
case MACH_TYPE_MX28EVK:
+ case MACH_TYPE_M28EVK:
case MACH_TYPE_TX28:
mxs_duart_base = MX28_DUART_BASE_ADDR;
break;
diff --git a/arch/arm/mach-mxs/mach-m28evk.c b/arch/arm/mach-mxs/mach-m28evk.c
new file mode 100644
index 000000000000..3b1681e4f49a
--- /dev/null
+++ b/arch/arm/mach-mxs/mach-m28evk.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2011
+ * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
+ *
+ * based on: mach-mx28_evk.c
+ * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/iomux-mx28.h>
+
+#include "devices-mx28.h"
+
+#define M28EVK_GPIO_USERLED1 MXS_GPIO_NR(3, 16)
+#define M28EVK_GPIO_USERLED2 MXS_GPIO_NR(3, 17)
+
+#define MX28EVK_BL_ENABLE MXS_GPIO_NR(3, 18)
+#define M28EVK_LCD_ENABLE MXS_GPIO_NR(3, 28)
+
+#define MX28EVK_MMC0_WRITE_PROTECT MXS_GPIO_NR(2, 12)
+#define MX28EVK_MMC1_WRITE_PROTECT MXS_GPIO_NR(0, 28)
+
+static const iomux_cfg_t m28evk_pads[] __initconst = {
+ /* duart */
+ MX28_PAD_AUART0_CTS__DUART_RX | MXS_PAD_CTRL,
+ MX28_PAD_AUART0_RTS__DUART_TX | MXS_PAD_CTRL,
+
+ /* auart0 */
+ MX28_PAD_AUART0_RX__AUART0_RX | MXS_PAD_CTRL,
+ MX28_PAD_AUART0_TX__AUART0_TX | MXS_PAD_CTRL,
+
+ /* auart3 */
+ MX28_PAD_AUART3_RX__AUART3_RX | MXS_PAD_CTRL,
+ MX28_PAD_AUART3_TX__AUART3_TX | MXS_PAD_CTRL,
+ MX28_PAD_AUART3_CTS__AUART3_CTS | MXS_PAD_CTRL,
+ MX28_PAD_AUART3_RTS__AUART3_RTS | MXS_PAD_CTRL,
+
+#define MXS_PAD_FEC (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP)
+ /* fec0 */
+ MX28_PAD_ENET0_MDC__ENET0_MDC | MXS_PAD_FEC,
+ MX28_PAD_ENET0_MDIO__ENET0_MDIO | MXS_PAD_FEC,
+ MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MXS_PAD_FEC,
+ MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MXS_PAD_FEC,
+ MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MXS_PAD_FEC,
+ MX28_PAD_ENET_CLK__CLKCTRL_ENET | MXS_PAD_FEC,
+ /* fec1 */
+ MX28_PAD_ENET0_CRS__ENET1_RX_EN | MXS_PAD_FEC,
+ MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_COL__ENET1_TX_EN | MXS_PAD_FEC,
+ MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MXS_PAD_FEC,
+ MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MXS_PAD_FEC,
+
+ /* flexcan0 */
+ MX28_PAD_GPMI_RDY2__CAN0_TX,
+ MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+ /* flexcan1 */
+ MX28_PAD_GPMI_CE2N__CAN1_TX,
+ MX28_PAD_GPMI_CE3N__CAN1_RX,
+
+ /* I2C */
+ MX28_PAD_I2C0_SCL__I2C0_SCL,
+ MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+ /* mxsfb (lcdif) */
+ MX28_PAD_LCD_D00__LCD_D0 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D01__LCD_D1 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D02__LCD_D2 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D03__LCD_D3 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D04__LCD_D4 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D05__LCD_D5 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D06__LCD_D6 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D07__LCD_D7 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D08__LCD_D8 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D09__LCD_D9 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D18__LCD_D18 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D19__LCD_D19 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D20__LCD_D20 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D21__LCD_D21 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D22__LCD_D22 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D23__LCD_D23 | MXS_PAD_CTRL,
+
+ MX28_PAD_LCD_ENABLE__LCD_ENABLE | MXS_PAD_CTRL,
+ MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MXS_PAD_CTRL,
+
+ /* mmc0 */
+ MX28_PAD_SSP0_DATA0__SSP0_D0 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA1__SSP0_D1 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA2__SSP0_D2 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA3__SSP0_D3 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA4__SSP0_D4 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA5__SSP0_D5 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA6__SSP0_D6 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DATA7__SSP0_D7 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_CMD__SSP0_CMD |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+ MX28_PAD_SSP0_SCK__SSP0_SCK |
+ (MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+ /* mmc1 */
+ MX28_PAD_GPMI_D00__SSP1_D0 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D01__SSP1_D1 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D02__SSP1_D2 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D03__SSP1_D3 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D04__SSP1_D4 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D05__SSP1_D5 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D06__SSP1_D6 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_D07__SSP1_D7 |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_RDY1__SSP1_CMD |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_WRN__SSP1_SCK |
+ (MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+ /* write protect */
+ MX28_PAD_GPMI_RESETN__GPIO_0_28 |
+ (MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+ /* slot power enable */
+ MX28_PAD_PWM4__GPIO_3_29 |
+ (MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+ /* led */
+ MX28_PAD_PWM0__GPIO_3_16 | MXS_PAD_CTRL,
+ MX28_PAD_PWM1__GPIO_3_17 | MXS_PAD_CTRL,
+
+ /* nand */
+ MX28_PAD_GPMI_D00__GPMI_D0 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D01__GPMI_D1 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D02__GPMI_D2 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D03__GPMI_D3 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D04__GPMI_D4 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D05__GPMI_D5 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D06__GPMI_D6 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_D07__GPMI_D7 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_CE0N__GPMI_CE0N |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_RDY0__GPMI_READY0 |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+ MX28_PAD_GPMI_RDN__GPMI_RDN |
+ (MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_WRN__GPMI_WRN |
+ (MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_ALE__GPMI_ALE |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_CLE__GPMI_CLE |
+ (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+ MX28_PAD_GPMI_RESETN__GPMI_RESETN |
+ (MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+
+ /* Backlight */
+ MX28_PAD_PWM3__GPIO_3_28 | MXS_PAD_CTRL,
+};
+
+/* led */
+static const struct gpio_led m28evk_leds[] __initconst = {
+ {
+ .name = "user-led1",
+ .default_trigger = "heartbeat",
+ .gpio = M28EVK_GPIO_USERLED1,
+ },
+ {
+ .name = "user-led2",
+ .default_trigger = "heartbeat",
+ .gpio = M28EVK_GPIO_USERLED2,
+ },
+};
+
+static const struct gpio_led_platform_data m28evk_led_data __initconst = {
+ .leds = m28evk_leds,
+ .num_leds = ARRAY_SIZE(m28evk_leds),
+};
+
+static struct fec_platform_data mx28_fec_pdata[] __initdata = {
+ {
+ /* fec0 */
+ .phy = PHY_INTERFACE_MODE_RMII,
+ }, {
+ /* fec1 */
+ .phy = PHY_INTERFACE_MODE_RMII,
+ },
+};
+
+static int __init m28evk_fec_get_mac(void)
+{
+ int i;
+ u32 val;
+ const u32 *ocotp = mxs_get_ocotp();
+
+ if (!ocotp) {
+ pr_err("%s: timeout when reading fec mac from OCOTP\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+
+ /*
+ * OCOTP only stores the last 4 octets for each mac address,
+ * so hard-code DENX OUI (C0:E5:4E) here.
+ */
+ for (i = 0; i < 2; i++) {
+ val = ocotp[i * 4];
+ mx28_fec_pdata[i].mac[0] = 0xC0;
+ mx28_fec_pdata[i].mac[1] = 0xE5;
+ mx28_fec_pdata[i].mac[2] = 0x4E;
+ mx28_fec_pdata[i].mac[3] = (val >> 16) & 0xff;
+ mx28_fec_pdata[i].mac[4] = (val >> 8) & 0xff;
+ mx28_fec_pdata[i].mac[5] = (val >> 0) & 0xff;
+ }
+
+ return 0;
+}
+
+/* mxsfb (lcdif) */
+static struct fb_videomode m28evk_video_modes[] = {
+ {
+ .name = "Ampire AM-800480R2TMQW-T01H",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 30066, /* picosecond (33.26 MHz) */
+ .left_margin = 0,
+ .right_margin = 256,
+ .upper_margin = 0,
+ .lower_margin = 45,
+ .hsync_len = 1,
+ .vsync_len = 1,
+ .sync = FB_SYNC_DATA_ENABLE_HIGH_ACT,
+ },
+};
+
+static const struct mxsfb_platform_data m28evk_mxsfb_pdata __initconst = {
+ .mode_list = m28evk_video_modes,
+ .mode_count = ARRAY_SIZE(m28evk_video_modes),
+ .default_bpp = 16,
+ .ld_intf_width = STMLCDIF_18BIT,
+};
+
+static struct at24_platform_data m28evk_eeprom = {
+ .byte_len = 16384,
+ .page_size = 32,
+ .flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info m28_stk5v3_i2c_boardinfo[] __initdata = {
+ {
+ I2C_BOARD_INFO("at24", 0x51), /* E0=1, E1=0, E2=0 */
+ .platform_data = &m28evk_eeprom,
+ },
+};
+
+static struct mxs_mmc_platform_data m28evk_mmc_pdata[] __initdata = {
+ {
+ /* mmc0 */
+ .wp_gpio = MX28EVK_MMC0_WRITE_PROTECT,
+ .flags = SLOTF_8_BIT_CAPABLE,
+ }, {
+ /* mmc1 */
+ .wp_gpio = MX28EVK_MMC1_WRITE_PROTECT,
+ .flags = SLOTF_8_BIT_CAPABLE,
+ },
+};
+
+static void __init m28evk_init(void)
+{
+ mxs_iomux_setup_multiple_pads(m28evk_pads, ARRAY_SIZE(m28evk_pads));
+
+ mx28_add_duart();
+ mx28_add_auart0();
+ mx28_add_auart3();
+
+ if (!m28evk_fec_get_mac()) {
+ mx28_add_fec(0, &mx28_fec_pdata[0]);
+ mx28_add_fec(1, &mx28_fec_pdata[1]);
+ }
+
+ mx28_add_flexcan(0, NULL);
+ mx28_add_flexcan(1, NULL);
+
+ mx28_add_mxsfb(&m28evk_mxsfb_pdata);
+
+ mx28_add_mxs_mmc(0, &m28evk_mmc_pdata[0]);
+ mx28_add_mxs_mmc(1, &m28evk_mmc_pdata[1]);
+
+ gpio_led_register_device(0, &m28evk_led_data);
+
+ /* I2C */
+ mx28_add_mxs_i2c(0);
+ i2c_register_board_info(0, m28_stk5v3_i2c_boardinfo,
+ ARRAY_SIZE(m28_stk5v3_i2c_boardinfo));
+}
+
+static void __init m28evk_timer_init(void)
+{
+ mx28_clocks_init();
+}
+
+static struct sys_timer m28evk_timer = {
+ .init = m28evk_timer_init,
+};
+
+MACHINE_START(M28EVK, "DENX M28 EVK")
+ .map_io = mx28_map_io,
+ .init_irq = mx28_init_irq,
+ .init_machine = m28evk_init,
+ .timer = &m28evk_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
index 3c2de33803ab..c325fbe4e4c6 100644
--- a/arch/arm/mach-mxs/mach-mx23evk.c
+++ b/arch/arm/mach-mxs/mach-mx23evk.c
@@ -15,7 +15,6 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
-#include <linux/irq.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -167,6 +166,7 @@ static void __init mx23evk_init(void)
gpio_set_value(MX23EVK_BL_ENABLE, 1);
mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
+ mx23_add_rtc_stmp3xxx();
}
static void __init mx23evk_timer_init(void)
@@ -182,6 +182,6 @@ MACHINE_START(MX23EVK, "Freescale MX23 EVK")
/* Maintainer: Freescale Semiconductor, Inc. */
.map_io = mx23_map_io,
.init_irq = mx23_init_irq,
- .init_machine = mx23evk_init,
.timer = &mx23evk_timer,
+ .init_machine = mx23evk_init,
MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index eaaf6ff28990..ac2316d53d3c 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -16,8 +16,10 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/leds.h>
-#include <linux/irq.h>
#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -183,6 +185,24 @@ static const iomux_cfg_t mx28evk_pads[] __initconst = {
/* led */
MX28_PAD_AUART1_TX__GPIO_3_5 | MXS_PAD_CTRL,
+
+ /* I2C */
+ MX28_PAD_I2C0_SCL__I2C0_SCL |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_I2C0_SDA__I2C0_SDA |
+ (MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+
+ /* saif0 & saif1 */
+ MX28_PAD_SAIF0_MCLK__SAIF0_MCLK |
+ (MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK |
+ (MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK |
+ (MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 |
+ (MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+ MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 |
+ (MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
};
/* led */
@@ -352,6 +372,55 @@ static struct mxs_mmc_platform_data mx28evk_mmc_pdata[] __initdata = {
},
};
+static struct i2c_board_info mxs_i2c0_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("sgtl5000", 0x0a),
+ },
+};
+
+#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
+static struct regulator_consumer_supply mx28evk_audio_consumer_supplies[] = {
+ REGULATOR_SUPPLY("VDDA", "0-000a"),
+ REGULATOR_SUPPLY("VDDIO", "0-000a"),
+};
+
+static struct regulator_init_data mx28evk_vdd_reg_init_data = {
+ .constraints = {
+ .name = "3V3",
+ .always_on = 1,
+ },
+ .consumer_supplies = mx28evk_audio_consumer_supplies,
+ .num_consumer_supplies = ARRAY_SIZE(mx28evk_audio_consumer_supplies),
+};
+
+static struct fixed_voltage_config mx28evk_vdd_pdata = {
+ .supply_name = "board-3V3",
+ .microvolts = 3300000,
+ .gpio = -EINVAL,
+ .enabled_at_boot = 1,
+ .init_data = &mx28evk_vdd_reg_init_data,
+};
+static struct platform_device mx28evk_voltage_regulator = {
+ .name = "reg-fixed-voltage",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &mx28evk_vdd_pdata,
+ },
+};
+static void __init mx28evk_add_regulators(void)
+{
+ platform_device_register(&mx28evk_voltage_regulator);
+}
+#else
+static void __init mx28evk_add_regulators(void) {}
+#endif
+
+static struct gpio mx28evk_lcd_gpios[] = {
+ { MX28EVK_LCD_ENABLE, GPIOF_OUT_INIT_HIGH, "lcd-enable" },
+ { MX28EVK_BL_ENABLE, GPIOF_OUT_INIT_HIGH, "bl-enable" },
+};
+
static void __init mx28evk_init(void)
{
int ret;
@@ -378,19 +447,24 @@ static void __init mx28evk_init(void)
mx28_add_flexcan(1, &mx28evk_flexcan_pdata[1]);
}
- ret = gpio_request_one(MX28EVK_LCD_ENABLE, GPIOF_DIR_OUT, "lcd-enable");
+ ret = gpio_request_array(mx28evk_lcd_gpios,
+ ARRAY_SIZE(mx28evk_lcd_gpios));
if (ret)
- pr_warn("failed to request gpio lcd-enable: %d\n", ret);
+ pr_warn("failed to request gpio pins for lcd: %d\n", ret);
else
- gpio_set_value(MX28EVK_LCD_ENABLE, 1);
+ mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
- ret = gpio_request_one(MX28EVK_BL_ENABLE, GPIOF_DIR_OUT, "bl-enable");
- if (ret)
- pr_warn("failed to request gpio bl-enable: %d\n", ret);
- else
- gpio_set_value(MX28EVK_BL_ENABLE, 1);
+ mx28_add_saif(0);
+ mx28_add_saif(1);
+
+ mx28_add_mxs_i2c(0);
+ i2c_register_board_info(0, mxs_i2c0_board_info,
+ ARRAY_SIZE(mxs_i2c0_board_info));
- mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
+ mx28evk_add_regulators();
+
+ mxs_add_platform_device("mxs-sgtl5000", 0, NULL, 0,
+ NULL, 0);
/* power on mmc slot by writing 0 to the gpio */
ret = gpio_request_one(MX28EVK_MMC0_SLOT_POWER, GPIOF_OUT_INIT_LOW,
@@ -403,7 +477,11 @@ static void __init mx28evk_init(void)
"mmc1-slot-power");
if (ret)
pr_warn("failed to request gpio mmc1-slot-power: %d\n", ret);
+ else
+ mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
+
mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
+ mx28_add_rtc_stmp3xxx();
gpio_led_register_device(0, &mx28evk_led_data);
}
@@ -421,6 +499,6 @@ MACHINE_START(MX28EVK, "Freescale MX28 EVK")
/* Maintainer: Freescale Semiconductor, Inc. */
.map_io = mx28_map_io,
.init_irq = mx28_init_irq,
- .init_machine = mx28evk_init,
.timer = &mx28evk_timer,
+ .init_machine = mx28evk_init,
MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-stmp378x_devb.c b/arch/arm/mach-mxs/mach-stmp378x_devb.c
index 7f38d82b69af..177e53123a02 100644
--- a/arch/arm/mach-mxs/mach-stmp378x_devb.c
+++ b/arch/arm/mach-mxs/mach-stmp378x_devb.c
@@ -19,7 +19,6 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
-#include <linux/irq.h>
#include <linux/spi/spi.h>
#include <asm/mach-types.h>
@@ -91,6 +90,7 @@ static void __init stmp378x_dvb_init(void)
mx23_add_duart();
mx23_add_auart0();
+ mx23_add_rtc_stmp3xxx();
/* power on mmc slot */
ret = gpio_request_one(STMP378X_DEVB_MMC0_SLOT_POWER,
diff --git a/arch/arm/mach-mxs/mach-tx28.c b/arch/arm/mach-mxs/mach-tx28.c
index 515a423f82cd..9a1f0e7a338e 100644
--- a/arch/arm/mach-mxs/mach-tx28.c
+++ b/arch/arm/mach-mxs/mach-tx28.c
@@ -161,6 +161,7 @@ static void __init tx28_stk5v3_init(void)
i2c_register_board_info(0, tx28_stk5v3_i2c_boardinfo,
ARRAY_SIZE(tx28_stk5v3_i2c_boardinfo));
mx28_add_mxs_mmc(0, &tx28_mmc0_pdata);
+ mx28_add_rtc_stmp3xxx();
}
static void __init tx28_timer_init(void)
@@ -175,6 +176,6 @@ static struct sys_timer tx28_timer = {
MACHINE_START(TX28, "Ka-Ro electronics TX28 module")
.map_io = mx28_map_io,
.init_irq = mx28_init_irq,
- .init_machine = tx28_stk5v3_init,
.timer = &tx28_timer,
+ .init_machine = tx28_stk5v3_init,
MACHINE_END
diff --git a/arch/arm/mach-mxs/mm-mx28.c b/arch/arm/mach-mxs/mm-mx28.c
deleted file mode 100644
index b6e18ddb92c0..000000000000
--- a/arch/arm/mach-mxs/mm-mx28.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * 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
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/mx28.h>
-#include <mach/common.h>
-#include <mach/iomux.h>
-
-/*
- * Define the MX28 memory map.
- */
-static struct map_desc mx28_io_desc[] __initdata = {
- mxs_map_entry(MX28, OCRAM, MT_DEVICE),
- mxs_map_entry(MX28, IO, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx28_map_io(void)
-{
- iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
-}
-
-void __init mx28_init_irq(void)
-{
- icoll_init_irq();
-}
diff --git a/arch/arm/mach-mxs/mm-mx23.c b/arch/arm/mach-mxs/mm.c
index 1b2345ac1a87..50af5ceebf6d 100644
--- a/arch/arm/mach-mxs/mm-mx23.c
+++ b/arch/arm/mach-mxs/mm.c
@@ -17,6 +17,7 @@
#include <asm/mach/map.h>
#include <mach/mx23.h>
+#include <mach/mx28.h>
#include <mach/common.h>
#include <mach/iomux.h>
@@ -29,6 +30,14 @@ static struct map_desc mx23_io_desc[] __initdata = {
};
/*
+ * Define the MX28 memory map.
+ */
+static struct map_desc mx28_io_desc[] __initdata = {
+ mxs_map_entry(MX28, OCRAM, MT_DEVICE),
+ mxs_map_entry(MX28, IO, MT_DEVICE),
+};
+
+/*
* This function initializes the memory map. It is called during the
* system startup to create static physical to virtual memory mappings
* for the IO modules.
@@ -42,3 +51,13 @@ void __init mx23_init_irq(void)
{
icoll_init_irq();
}
+
+void __init mx28_map_io(void)
+{
+ iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
+}
+
+void __init mx28_init_irq(void)
+{
+ icoll_init_irq();
+}
diff --git a/arch/arm/mach-netx/Makefile.boot b/arch/arm/mach-netx/Makefile.boot
index b81cf6aff0ac..534a4d27055e 100644
--- a/arch/arm/mach-netx/Makefile.boot
+++ b/arch/arm/mach-netx/Makefile.boot
@@ -1,2 +1,2 @@
- zreladdr-y := 0x80008000
+ zreladdr-y += 0x80008000
diff --git a/arch/arm/mach-netx/include/mach/debug-macro.S b/arch/arm/mach-netx/include/mach/debug-macro.S
index 56a915228180..247781e096e2 100644
--- a/arch/arm/mach-netx/include/mach/debug-macro.S
+++ b/arch/arm/mach-netx/include/mach/debug-macro.S
@@ -13,7 +13,7 @@
#include "hardware.h"
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00000a00
orr \rv, \rp, #io_p2v(0x00100000) @ virtual
orr \rp, \rp, #0x00100000 @ physical
diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c
index ca8b203a3c99..90903dd44cbc 100644
--- a/arch/arm/mach-netx/nxdb500.c
+++ b/arch/arm/mach-netx/nxdb500.c
@@ -200,7 +200,7 @@ static void __init nxdb500_init(void)
}
MACHINE_START(NXDB500, "Hilscher nxdb500")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.map_io = netx_map_io,
.init_irq = netx_init_irq,
.timer = &netx_timer,
diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c
index d775cbe07278..c63384aba500 100644
--- a/arch/arm/mach-netx/nxdkn.c
+++ b/arch/arm/mach-netx/nxdkn.c
@@ -93,7 +93,7 @@ static void __init nxdkn_init(void)
}
MACHINE_START(NXDKN, "Hilscher nxdkn")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.map_io = netx_map_io,
.init_irq = netx_init_irq,
.timer = &netx_timer,
diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c
index de369cd1dcbe..8f548ec83ad2 100644
--- a/arch/arm/mach-netx/nxeb500hmi.c
+++ b/arch/arm/mach-netx/nxeb500hmi.c
@@ -177,7 +177,7 @@ static void __init nxeb500hmi_init(void)
}
MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.map_io = netx_map_io,
.init_irq = netx_init_irq,
.timer = &netx_timer,
diff --git a/arch/arm/mach-nomadik/Makefile.boot b/arch/arm/mach-nomadik/Makefile.boot
index c7e75acfe6c9..ff0a4b5b0a82 100644
--- a/arch/arm/mach-nomadik/Makefile.boot
+++ b/arch/arm/mach-nomadik/Makefile.boot
@@ -1,4 +1,4 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index 139930350d93..0cbb74c96ef7 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -27,6 +27,7 @@
#include <asm/mach/irq.h>
#include <asm/mach/flash.h>
+#include <plat/gpio-nomadik.h>
#include <plat/mtu.h>
#include <mach/setup.h>
@@ -276,7 +277,7 @@ static void __init nhk8815_platform_init(void)
MACHINE_START(NOMADIK, "NHK8815")
/* Maintainer: ST MicroElectronics */
- .boot_params = 0x100,
+ .atag_offset = 0x100,
.map_io = cpu8815_map_io,
.init_irq = cpu8815_init_irq,
.timer = &nomadik_timer,
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c
index ac58e3b03b1a..dc67717db6f0 100644
--- a/arch/arm/mach-nomadik/cpu-8815.c
+++ b/arch/arm/mach-nomadik/cpu-8815.c
@@ -21,8 +21,8 @@
#include <linux/device.h>
#include <linux/amba/bus.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
+#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c
index abfe25a08d6b..0fc2f6f1cc97 100644
--- a/arch/arm/mach-nomadik/i2c-8815nhk.c
+++ b/arch/arm/mach-nomadik/i2c-8815nhk.c
@@ -3,8 +3,8 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/i2c-gpio.h>
-#include <linux/gpio.h>
#include <linux/platform_device.h>
+#include <plat/gpio-nomadik.h>
/*
* There are two busses in the 8815NHK.
diff --git a/arch/arm/mach-nomadik/include/mach/debug-macro.S b/arch/arm/mach-nomadik/include/mach/debug-macro.S
index e7151b4b8889..735417922ce2 100644
--- a/arch/arm/mach-nomadik/include/mach/debug-macro.S
+++ b/arch/arm/mach-nomadik/include/mach/debug-macro.S
@@ -10,7 +10,7 @@
*
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00100000
add \rp, \rp, #0x000fb000
add \rv, \rp, #0xf0000000 @ virtual base
diff --git a/arch/arm/mach-nomadik/include/mach/gpio.h b/arch/arm/mach-nomadik/include/mach/gpio.h
index 7a81a0420343..efdde0ae0a4f 100644
--- a/arch/arm/mach-nomadik/include/mach/gpio.h
+++ b/arch/arm/mach-nomadik/include/mach/gpio.h
@@ -1,6 +1,4 @@
#ifndef __ASM_ARCH_GPIO_H
#define __ASM_ARCH_GPIO_H
-#include <plat/gpio.h>
-
#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-nuc93x/Kconfig b/arch/arm/mach-nuc93x/Kconfig
deleted file mode 100644
index 2bc40a280fad..000000000000
--- a/arch/arm/mach-nuc93x/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-if ARCH_NUC93X
-
-config CPU_NUC932
- bool
- help
- Support for NUC932 of Nuvoton NUC93X CPUs.
-
-menu "NUC932 Machines"
-
-config MACH_NUC932EVB
- bool "Nuvoton NUC932 Evaluation Board"
- default y
- select CPU_NUC932
- help
- Say Y here if you are using the Nuvoton NUC932EVB
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-nuc93x/Makefile b/arch/arm/mach-nuc93x/Makefile
deleted file mode 100644
index 440e2dec6c8a..000000000000
--- a/arch/arm/mach-nuc93x/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y := irq.o time.o dev.o cpu.o clock.o
-# NUC932 CPU support files
-
-obj-$(CONFIG_CPU_NUC932) += nuc932.o
-
-# machine support
-
-obj-$(CONFIG_MACH_NUC932EVB) += mach-nuc932evb.o
diff --git a/arch/arm/mach-nuc93x/Makefile.boot b/arch/arm/mach-nuc93x/Makefile.boot
deleted file mode 100644
index a057b546b6e5..000000000000
--- a/arch/arm/mach-nuc93x/Makefile.boot
+++ /dev/null
@@ -1,3 +0,0 @@
-zreladdr-y := 0x00008000
-params_phys-y := 0x00000100
-
diff --git a/arch/arm/mach-nuc93x/clock.c b/arch/arm/mach-nuc93x/clock.c
deleted file mode 100644
index 0521efbc48c9..000000000000
--- a/arch/arm/mach-nuc93x/clock.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/clock.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@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.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-
-#include "clock.h"
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-int clk_enable(struct clk *clk)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&clocks_lock, flags);
- if (clk->enabled++ == 0)
- (clk->enable)(clk, 1);
- spin_unlock_irqrestore(&clocks_lock, flags);
-
- return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
- unsigned long flags;
-
- WARN_ON(clk->enabled == 0);
-
- spin_lock_irqsave(&clocks_lock, flags);
- if (--clk->enabled == 0)
- (clk->enable)(clk, 0);
- spin_unlock_irqrestore(&clocks_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- return 27000000;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-void nuc93x_clk_enable(struct clk *clk, int enable)
-{
- unsigned int clocks = clk->cken;
- unsigned long clken;
-
- clken = __raw_readl(NUC93X_VA_CLKPWR);
-
- if (enable)
- clken |= clocks;
- else
- clken &= ~clocks;
-
- __raw_writel(clken, NUC93X_VA_CLKPWR);
-}
-
-void clks_register(struct clk_lookup *clks, size_t num)
-{
- int i;
-
- for (i = 0; i < num; i++)
- clkdev_add(&clks[i]);
-}
diff --git a/arch/arm/mach-nuc93x/clock.h b/arch/arm/mach-nuc93x/clock.h
deleted file mode 100644
index 4de1f1da9dc5..000000000000
--- a/arch/arm/mach-nuc93x/clock.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/clock.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@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.
- */
-
-#include <linux/clkdev.h>
-
-void nuc93x_clk_enable(struct clk *clk, int enable);
-void clks_register(struct clk_lookup *clks, size_t num);
-
-struct clk {
- unsigned long cken;
- unsigned int enabled;
- void (*enable)(struct clk *, int enable);
-};
-
-#define DEFINE_CLK(_name, _ctrlbit) \
-struct clk clk_##_name = { \
- .enable = nuc93x_clk_enable, \
- .cken = (1 << _ctrlbit), \
- }
-
-#define DEF_CLKLOOK(_clk, _devname, _conname) \
- { \
- .clk = _clk, \
- .dev_id = _devname, \
- .con_id = _conname, \
- }
-
diff --git a/arch/arm/mach-nuc93x/cpu.c b/arch/arm/mach-nuc93x/cpu.c
deleted file mode 100644
index f6ff5d87354c..000000000000
--- a/arch/arm/mach-nuc93x/cpu.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/cpu.c
- *
- * Copyright (c) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC93x series cpu common support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/serial_8250.h>
-#include <linux/delay.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-serial.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-ebi.h>
-
-#include "cpu.h"
-#include "clock.h"
-
-/* Initial IO mappings */
-
-static struct map_desc nuc93x_iodesc[] __initdata = {
- IODESC_ENT(IRQ),
- IODESC_ENT(GCR),
- IODESC_ENT(UART),
- IODESC_ENT(TIMER),
- IODESC_ENT(EBI),
-};
-
-/* Initial nuc932 clock declarations. */
-static DEFINE_CLK(audio, 2);
-static DEFINE_CLK(sd, 3);
-static DEFINE_CLK(jpg, 4);
-static DEFINE_CLK(video, 5);
-static DEFINE_CLK(vpost, 6);
-static DEFINE_CLK(2d, 7);
-static DEFINE_CLK(gpu, 8);
-static DEFINE_CLK(gdma, 9);
-static DEFINE_CLK(adc, 10);
-static DEFINE_CLK(uart, 11);
-static DEFINE_CLK(spi, 12);
-static DEFINE_CLK(pwm, 13);
-static DEFINE_CLK(timer, 14);
-static DEFINE_CLK(wdt, 15);
-static DEFINE_CLK(ac97, 16);
-static DEFINE_CLK(i2s, 16);
-static DEFINE_CLK(usbck, 17);
-static DEFINE_CLK(usb48, 18);
-static DEFINE_CLK(usbh, 19);
-static DEFINE_CLK(i2c, 20);
-static DEFINE_CLK(ext, 0);
-
-static struct clk_lookup nuc932_clkregs[] = {
- DEF_CLKLOOK(&clk_audio, "nuc932-audio", NULL),
- DEF_CLKLOOK(&clk_sd, "nuc932-sd", NULL),
- DEF_CLKLOOK(&clk_jpg, "nuc932-jpg", "NULL"),
- DEF_CLKLOOK(&clk_video, "nuc932-video", "NULL"),
- DEF_CLKLOOK(&clk_vpost, "nuc932-vpost", NULL),
- DEF_CLKLOOK(&clk_2d, "nuc932-2d", NULL),
- DEF_CLKLOOK(&clk_gpu, "nuc932-gpu", NULL),
- DEF_CLKLOOK(&clk_gdma, "nuc932-gdma", "NULL"),
- DEF_CLKLOOK(&clk_adc, "nuc932-adc", NULL),
- DEF_CLKLOOK(&clk_uart, NULL, "uart"),
- DEF_CLKLOOK(&clk_spi, "nuc932-spi", NULL),
- DEF_CLKLOOK(&clk_pwm, "nuc932-pwm", NULL),
- DEF_CLKLOOK(&clk_timer, NULL, "timer"),
- DEF_CLKLOOK(&clk_wdt, "nuc932-wdt", NULL),
- DEF_CLKLOOK(&clk_ac97, "nuc932-ac97", NULL),
- DEF_CLKLOOK(&clk_i2s, "nuc932-i2s", NULL),
- DEF_CLKLOOK(&clk_usbck, "nuc932-usbck", NULL),
- DEF_CLKLOOK(&clk_usb48, "nuc932-usb48", NULL),
- DEF_CLKLOOK(&clk_usbh, "nuc932-usbh", NULL),
- DEF_CLKLOOK(&clk_i2c, "nuc932-i2c", NULL),
- DEF_CLKLOOK(&clk_ext, NULL, "ext"),
-};
-
-/* Initial serial platform data */
-
-struct plat_serial8250_port nuc93x_uart_data[] = {
- NUC93X_8250PORT(UART0),
- {},
-};
-
-struct platform_device nuc93x_serial_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = nuc93x_uart_data,
- },
-};
-
-/*Init NUC93x evb io*/
-
-void __init nuc93x_map_io(struct map_desc *mach_desc, int mach_size)
-{
- unsigned long idcode = 0x0;
-
- iotable_init(mach_desc, mach_size);
- iotable_init(nuc93x_iodesc, ARRAY_SIZE(nuc93x_iodesc));
-
- idcode = __raw_readl(NUC93XPDID);
- if (idcode == NUC932_CPUID)
- printk(KERN_INFO "CPU type 0x%08lx is NUC910\n", idcode);
- else
- printk(KERN_ERR "CPU type detect error!\n");
-
-}
-
-/*Init NUC93x clock*/
-
-void __init nuc93x_init_clocks(void)
-{
- clks_register(nuc932_clkregs, ARRAY_SIZE(nuc932_clkregs));
-}
-
diff --git a/arch/arm/mach-nuc93x/cpu.h b/arch/arm/mach-nuc93x/cpu.h
deleted file mode 100644
index 9def28197bc9..000000000000
--- a/arch/arm/mach-nuc93x/cpu.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/cpu.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Header file for NUC93X CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#define IODESC_ENT(y) \
-{ \
- .virtual = (unsigned long)NUC93X_VA_##y, \
- .pfn = __phys_to_pfn(NUC93X_PA_##y), \
- .length = NUC93X_SZ_##y, \
- .type = MT_DEVICE, \
-}
-
-#define NUC93X_8250PORT(name) \
-{ \
- .membase = name##_BA, \
- .mapbase = name##_PA, \
- .irq = IRQ_##name, \
- .uartclk = 57139200, \
- .regshift = 2, \
- .iotype = UPIO_MEM, \
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \
-}
-
-/*Cpu identifier register*/
-
-#define NUC93XPDID NUC93X_VA_GCR
-#define NUC932_CPUID 0x29550091
-
-/* extern file from cpu.c */
-
-extern void nuc93x_clock_source(struct device *dev, unsigned char *src);
-extern void nuc93x_init_clocks(void);
-extern void nuc93x_map_io(struct map_desc *mach_desc, int mach_size);
-extern void nuc93x_board_init(struct platform_device **device, int size);
-extern struct platform_device nuc93x_serial_device;
-
diff --git a/arch/arm/mach-nuc93x/dev.c b/arch/arm/mach-nuc93x/dev.c
deleted file mode 100644
index a962ae9578d6..000000000000
--- a/arch/arm/mach-nuc93x/dev.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/dev.c
- *
- * Copyright (C) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@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;version 2 of the License.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach-types.h>
-
-#include "cpu.h"
-
-/*Here should be your evb resourse,such as LCD*/
-
-static struct platform_device *nuc93x_public_dev[] __initdata = {
- &nuc93x_serial_device,
-};
-
-/* Provide adding specific CPU platform devices API */
-
-void __init nuc93x_board_init(struct platform_device **device, int size)
-{
- platform_add_devices(device, size);
- platform_add_devices(nuc93x_public_dev, ARRAY_SIZE(nuc93x_public_dev));
-}
-
diff --git a/arch/arm/mach-nuc93x/include/mach/entry-macro.S b/arch/arm/mach-nuc93x/include/mach/entry-macro.S
deleted file mode 100644
index 1352cbda3797..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/entry-macro.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/entry-macro.S
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- *
- */
-
-#include <mach/hardware.h>
-#include <mach/regs-irq.h>
-
- .macro get_irqnr_preamble, base, tmp
- .endm
-
- .macro arch_ret_to_user, tmp1, tmp2
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- mov \base, #AIC_BA
-
- ldr \irqnr, [ \base, #AIC_IPER]
- ldr \irqnr, [ \base, #AIC_ISNR]
- cmp \irqnr, #0
-
- .endm
-
- /* currently don't need an disable_fiq macro */
-
- .macro disable_fiq
- .endm
diff --git a/arch/arm/mach-nuc93x/include/mach/hardware.h b/arch/arm/mach-nuc93x/include/mach/hardware.h
deleted file mode 100644
index fb5c6fcb142e..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/hardware.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/hardware.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/io.h b/arch/arm/mach-nuc93x/include/mach/io.h
deleted file mode 100644
index 72e5051c7534..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/io.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/io.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * 1:1 mapping for ioremapped regions.
- */
-
-#define __mem_pci(a) (a)
-#define __io(a) __typesafe_io(a)
-
-#endif
diff --git a/arch/arm/mach-nuc93x/include/mach/irqs.h b/arch/arm/mach-nuc93x/include/mach/irqs.h
deleted file mode 100644
index 7c4aa71edb44..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/irqs.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/irqs.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@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;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#define NUC93X_IRQ(x) (x)
-
-/* Main cpu interrupts */
-
-#define IRQ_WDT NUC93X_IRQ(1)
-#define IRQ_IRQ0 NUC93X_IRQ(2)
-#define IRQ_IRQ1 NUC93X_IRQ(3)
-#define IRQ_IRQ2 NUC93X_IRQ(4)
-#define IRQ_IRQ3 NUC93X_IRQ(5)
-#define IRQ_USBH NUC93X_IRQ(6)
-#define IRQ_APU NUC93X_IRQ(7)
-#define IRQ_VPOST NUC93X_IRQ(8)
-#define IRQ_ADC NUC93X_IRQ(9)
-#define IRQ_UART0 NUC93X_IRQ(10)
-#define IRQ_TIMER0 NUC93X_IRQ(11)
-#define IRQ_GPU0 NUC93X_IRQ(12)
-#define IRQ_GPU1 NUC93X_IRQ(13)
-#define IRQ_GPU2 NUC93X_IRQ(14)
-#define IRQ_GPU3 NUC93X_IRQ(15)
-#define IRQ_GPU4 NUC93X_IRQ(16)
-#define IRQ_VIN NUC93X_IRQ(17)
-#define IRQ_USBD NUC93X_IRQ(18)
-#define IRQ_VRAMLD NUC93X_IRQ(19)
-#define IRQ_GDMA0 NUC93X_IRQ(20)
-#define IRQ_GDMA1 NUC93X_IRQ(21)
-#define IRQ_SDIO NUC93X_IRQ(22)
-#define IRQ_FMI NUC93X_IRQ(22)
-#define IRQ_JPEG NUC93X_IRQ(23)
-#define IRQ_SPI0 NUC93X_IRQ(24)
-#define IRQ_SPI1 NUC93X_IRQ(25)
-#define IRQ_RTC NUC93X_IRQ(26)
-#define IRQ_PWM0 NUC93X_IRQ(27)
-#define IRQ_PWM1 NUC93X_IRQ(28)
-#define IRQ_PWM2 NUC93X_IRQ(29)
-#define IRQ_PWM3 NUC93X_IRQ(30)
-#define IRQ_I2SAC97 NUC93X_IRQ(31)
-#define IRQ_CAP0 IRQ_PWM0
-#define IRQ_CAP1 IRQ_PWM1
-#define IRQ_CAP2 IRQ_PWM2
-#define IRQ_CAP3 IRQ_PWM3
-#define NR_IRQS (IRQ_I2SAC97 + 1)
-
-#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/map.h b/arch/arm/mach-nuc93x/include/mach/map.h
deleted file mode 100644
index fd0b5e89f0e7..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/map.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/map.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@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;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H
-
-#define MAP_OFFSET (0xfff00000)
-#define CLK_OFFSET (0x10)
-
-#ifndef __ASSEMBLY__
-#define NUC93X_ADDR(x) ((void __iomem *)(0xF0000000 + ((x)&(~MAP_OFFSET))))
-#else
-#define NUC93X_ADDR(x) (0xF0000000 + ((x)&(~MAP_OFFSET)))
-#endif
-
- /*
- * nuc932 hardware register definition
- */
-
-#define NUC93X_PA_IRQ (0xFFF83000)
-#define NUC93X_PA_GCR (0xFFF00000)
-#define NUC93X_PA_EBI (0xFFF01000)
-#define NUC93X_PA_UART (0xFFF80000)
-#define NUC93X_PA_TIMER (0xFFF81000)
-#define NUC93X_PA_GPIO (0xFFF84000)
-#define NUC93X_PA_GDMA (0xFFF03000)
-#define NUC93X_PA_USBHOST (0xFFF0d000)
-#define NUC93X_PA_I2C (0xFFF89000)
-#define NUC93X_PA_LCD (0xFFF06000)
-#define NUC93X_PA_GE (0xFFF05000)
-#define NUC93X_PA_ADC (0xFFF85000)
-#define NUC93X_PA_RTC (0xFFF87000)
-#define NUC93X_PA_PWM (0xFFF82000)
-#define NUC93X_PA_ACTL (0xFFF0a000)
-#define NUC93X_PA_USBDEV (0xFFF0C000)
-#define NUC93X_PA_JEPEG (0xFFF0e000)
-#define NUC93X_PA_CACHE_T (0xFFF60000)
-#define NUC93X_PA_VRAM (0xFFF0b000)
-#define NUC93X_PA_DMAC (0xFFF09000)
-#define NUC93X_PA_I2SM (0xFFF08000)
-#define NUC93X_PA_CACHE (0xFFF02000)
-#define NUC93X_PA_GPU (0xFFF04000)
-#define NUC93X_PA_VIDEOIN (0xFFF07000)
-#define NUC93X_PA_SPI0 (0xFFF86000)
-#define NUC93X_PA_SPI1 (0xFFF88000)
-
- /*
- * nuc932 virtual address mapping.
- * interrupt controller is the first thing we put in, to make
- * the assembly code for the irq detection easier
- */
-
-#define NUC93X_VA_IRQ NUC93X_ADDR(0x00000000)
-#define NUC93X_SZ_IRQ SZ_4K
-
-#define NUC93X_VA_GCR NUC93X_ADDR(NUC93X_PA_IRQ)
-#define NUC93X_VA_CLKPWR (NUC93X_VA_GCR+CLK_OFFSET)
-#define NUC93X_SZ_GCR SZ_4K
-
-/* EBI management */
-
-#define NUC93X_VA_EBI NUC93X_ADDR(NUC93X_PA_EBI)
-#define NUC93X_SZ_EBI SZ_4K
-
-/* UARTs */
-
-#define NUC93X_VA_UART NUC93X_ADDR(NUC93X_PA_UART)
-#define NUC93X_SZ_UART SZ_4K
-
-/* Timers */
-
-#define NUC93X_VA_TIMER NUC93X_ADDR(NUC93X_PA_TIMER)
-#define NUC93X_SZ_TIMER SZ_4K
-
-/* GPIO ports */
-
-#define NUC93X_VA_GPIO NUC93X_ADDR(NUC93X_PA_GPIO)
-#define NUC93X_SZ_GPIO SZ_4K
-
-/* GDMA control */
-
-#define NUC93X_VA_GDMA NUC93X_ADDR(NUC93X_PA_GDMA)
-#define NUC93X_SZ_GDMA SZ_4K
-
-/* I2C hardware controller */
-
-#define NUC93X_VA_I2C NUC93X_ADDR(NUC93X_PA_I2C)
-#define NUC93X_SZ_I2C SZ_4K
-
-/* LCD controller*/
-
-#define NUC93X_VA_LCD NUC93X_ADDR(NUC93X_PA_LCD)
-#define NUC93X_SZ_LCD SZ_4K
-
-/* 2D controller*/
-
-#define NUC93X_VA_GE NUC93X_ADDR(NUC93X_PA_GE)
-#define NUC93X_SZ_GE SZ_4K
-
-/* ADC */
-
-#define NUC93X_VA_ADC NUC93X_ADDR(NUC93X_PA_ADC)
-#define NUC93X_SZ_ADC SZ_4K
-
-/* RTC */
-
-#define NUC93X_VA_RTC NUC93X_ADDR(NUC93X_PA_RTC)
-#define NUC93X_SZ_RTC SZ_4K
-
-/* Pulse Width Modulation(PWM) Registers */
-
-#define NUC93X_VA_PWM NUC93X_ADDR(NUC93X_PA_PWM)
-#define NUC93X_SZ_PWM SZ_4K
-
-/* Audio Controller controller */
-
-#define NUC93X_VA_ACTL NUC93X_ADDR(NUC93X_PA_ACTL)
-#define NUC93X_SZ_ACTL SZ_4K
-
-/* USB Device port */
-
-#define NUC93X_VA_USBDEV NUC93X_ADDR(NUC93X_PA_USBDEV)
-#define NUC93X_SZ_USBDEV SZ_4K
-
-/* USB host controller*/
-#define NUC93X_VA_USBHOST NUC93X_ADDR(NUC93X_PA_USBHOST)
-#define NUC93X_SZ_USBHOST SZ_4K
-
-#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/memory.h b/arch/arm/mach-nuc93x/include/mach/memory.h
deleted file mode 100644
index ef9864b002a6..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/memory.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/memory.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-nuc93x/include/mach/regs-clock.h b/arch/arm/mach-nuc93x/include/mach/regs-clock.h
deleted file mode 100644
index 5cb2954fbec2..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/regs-clock.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-clock.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@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;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H
-
-/* Clock Control Registers */
-#define CLK_BA NUC93X_VA_CLKPWR
-#define REG_CLKEN (CLK_BA + 0x00)
-#define REG_CLKSEL (CLK_BA + 0x04)
-#define REG_CLKDIV (CLK_BA + 0x08)
-#define REG_PLLCON0 (CLK_BA + 0x0C)
-#define REG_PLLCON1 (CLK_BA + 0x10)
-#define REG_PMCON (CLK_BA + 0x14)
-#define REG_IRQWAKECON (CLK_BA + 0x18)
-#define REG_IRQWAKEFLAG (CLK_BA + 0x1C)
-#define REG_IPSRST (CLK_BA + 0x20)
-#define REG_CLKEN1 (CLK_BA + 0x24)
-#define REG_CLKDIV1 (CLK_BA + 0x28)
-
-/* Define PLL freq setting */
-#define PLL_DISABLE 0x12B63
-#define PLL_66MHZ 0x2B63
-#define PLL_100MHZ 0x4F64
-#define PLL_120MHZ 0x4F63
-#define PLL_166MHZ 0x4124
-#define PLL_200MHZ 0x4F24
-
-/* Define AHB:CPUFREQ ratio */
-#define AHB_CPUCLK_1_1 0x00
-#define AHB_CPUCLK_1_2 0x01
-#define AHB_CPUCLK_1_4 0x02
-#define AHB_CPUCLK_1_8 0x03
-
-/* Define APB:AHB ratio */
-#define APB_AHB_1_2 0x01
-#define APB_AHB_1_4 0x02
-#define APB_AHB_1_8 0x03
-
-/* Define clock skew */
-#define DEFAULTSKEW 0x48
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/regs-ebi.h b/arch/arm/mach-nuc93x/include/mach/regs-ebi.h
deleted file mode 100644
index 3c72550e28e4..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/regs-ebi.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-ebi.h
- *
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@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;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_EBI_H
-#define __ASM_ARCH_REGS_EBI_H
-
-/* EBI Control Registers */
-
-#define EBI_BA NUC93X_VA_EBI
-#define REG_EBICON (EBI_BA + 0x00)
-#define REG_ROMCON (EBI_BA + 0x04)
-#define REG_SDCONF0 (EBI_BA + 0x08)
-#define REG_SDCONF1 (EBI_BA + 0x0C)
-#define REG_SDTIME0 (EBI_BA + 0x10)
-#define REG_SDTIME1 (EBI_BA + 0x14)
-#define REG_EXT0CON (EBI_BA + 0x18)
-#define REG_EXT1CON (EBI_BA + 0x1C)
-#define REG_EXT2CON (EBI_BA + 0x20)
-#define REG_EXT3CON (EBI_BA + 0x24)
-#define REG_EXT4CON (EBI_BA + 0x28)
-#define REG_CKSKEW (EBI_BA + 0x2C)
-
-#endif /* __ASM_ARCH_REGS_EBI_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/regs-irq.h b/arch/arm/mach-nuc93x/include/mach/regs-irq.h
deleted file mode 100644
index 23021592de51..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/regs-irq.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-irq.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef ___ASM_ARCH_REGS_IRQ_H
-#define ___ASM_ARCH_REGS_IRQ_H
-
-/* Advance Interrupt Controller (AIC) Registers */
-
-#define AIC_BA NUC93X_VA_IRQ
-
-#define REG_AIC_IRQSC (AIC_BA+0x80)
-#define REG_AIC_GEN (AIC_BA+0x84)
-#define REG_AIC_GASR (AIC_BA+0x88)
-#define REG_AIC_GSCR (AIC_BA+0x8C)
-#define REG_AIC_IRSR (AIC_BA+0x100)
-#define REG_AIC_IASR (AIC_BA+0x104)
-#define REG_AIC_ISR (AIC_BA+0x108)
-#define REG_AIC_IPER (AIC_BA+0x10C)
-#define REG_AIC_ISNR (AIC_BA+0x110)
-#define REG_AIC_IMR (AIC_BA+0x114)
-#define REG_AIC_OISR (AIC_BA+0x118)
-#define REG_AIC_MECR (AIC_BA+0x120)
-#define REG_AIC_MDCR (AIC_BA+0x124)
-#define REG_AIC_SSCR (AIC_BA+0x128)
-#define REG_AIC_SCCR (AIC_BA+0x12C)
-#define REG_AIC_EOSCR (AIC_BA+0x130)
-#define AIC_IPER (0x10C)
-#define AIC_ISNR (0x110)
-
-#endif /* ___ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/regs-serial.h b/arch/arm/mach-nuc93x/include/mach/regs-serial.h
deleted file mode 100644
index 767a047a8bc2..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/regs-serial.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-serial.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARM_REGS_SERIAL_H
-#define __ASM_ARM_REGS_SERIAL_H
-
-#define UART0_BA NUC93X_VA_UART
-#define UART1_BA (NUC93X_VA_UART+0x100)
-
-#define UART0_PA NUC93X_PA_UART
-#define UART1_PA (NUC93X_PA_UART+0x100)
-
-
-#ifndef __ASSEMBLY__
-
-struct nuc93x_uart_clksrc {
- const char *name;
- unsigned int divisor;
- unsigned int min_baud;
- unsigned int max_baud;
-};
-
-struct nuc93x_uartcfg {
- unsigned char hwport;
- unsigned char unused;
- unsigned short flags;
- unsigned long uart_flags;
-
- unsigned long ucon;
- unsigned long ulcon;
- unsigned long ufcon;
-
- struct nuc93x_uart_clksrc *clocks;
- unsigned int clocks_size;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_ARM_REGS_SERIAL_H */
-
diff --git a/arch/arm/mach-nuc93x/include/mach/regs-timer.h b/arch/arm/mach-nuc93x/include/mach/regs-timer.h
deleted file mode 100644
index 394be9614d36..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/regs-timer.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-timer.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_TIMER_H
-#define __ASM_ARCH_REGS_TIMER_H
-
-/* Timer Registers */
-
-#define TMR_BA NUC93X_VA_TIMER
-#define REG_TCSR0 (TMR_BA+0x00)
-#define REG_TICR0 (TMR_BA+0x08)
-#define REG_TDR0 (TMR_BA+0x10)
-#define REG_TISR (TMR_BA+0x18)
-#define REG_WTCR (TMR_BA+0x1C)
-
-#endif /* __ASM_ARCH_REGS_TIMER_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/system.h b/arch/arm/mach-nuc93x/include/mach/system.h
deleted file mode 100644
index d26bd9a52844..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/system.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/machnuc93x/include/mach/system.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/system.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#include <asm/proc-fns.h>
-
-static void arch_idle(void)
-{
-}
-
-static void arch_reset(char mode, const char *cmd)
-{
- cpu_reset(0);
-}
-
diff --git a/arch/arm/mach-nuc93x/include/mach/timex.h b/arch/arm/mach-nuc93x/include/mach/timex.h
deleted file mode 100644
index 0c719cc91aa9..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/timex.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/timex.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/timex.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/* CLOCK_TICK_RATE Now, I don't use it. */
-
-#define CLOCK_TICK_RATE 27000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/uncompress.h b/arch/arm/mach-nuc93x/include/mach/uncompress.h
deleted file mode 100644
index 381cb9baadd5..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/uncompress.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/uncompress.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/uncompress.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-/* Defines for UART registers */
-
-#include <mach/regs-serial.h>
-#include <mach/map.h>
-#include <linux/serial_reg.h>
-
-#define arch_decomp_wdog()
-
-#define TX_DONE (UART_LSR_TEMT | UART_LSR_THRE)
-static u32 * const uart_base = (u32 *)UART0_PA;
-
-static void putc(int ch)
-{
- /* Check THRE and TEMT bits before we transmit the character.
- */
- while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
- barrier();
-
- *uart_base = ch;
-}
-
-static inline void flush(void)
-{
-}
-
-static void arch_decomp_setup(void)
-{
-}
-
-#endif/* __ASM_NUC93X_UNCOMPRESS_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/vmalloc.h b/arch/arm/mach-nuc93x/include/mach/vmalloc.h
deleted file mode 100644
index 7d11a5f07696..000000000000
--- a/arch/arm/mach-nuc93x/include/mach/vmalloc.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/vmalloc.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/vmalloc.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END 0xE0000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-nuc93x/irq.c b/arch/arm/mach-nuc93x/irq.c
deleted file mode 100644
index aa279f23e342..000000000000
--- a/arch/arm/mach-nuc93x/irq.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/irq.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@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;version 2 of the License.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-irq.h>
-
-static void nuc93x_irq_mask(struct irq_data *d)
-{
- __raw_writel(1 << d->irq, REG_AIC_MDCR);
-}
-
-/*
- * By the w90p910 spec,any irq,only write 1
- * to REG_AIC_EOSCR for ACK
- */
-
-static void nuc93x_irq_ack(struct irq_data *d)
-{
- __raw_writel(0x01, REG_AIC_EOSCR);
-}
-
-static void nuc93x_irq_unmask(struct irq_data *d)
-{
- __raw_writel(1 << d->irq, REG_AIC_MECR);
-
-}
-
-static struct irq_chip nuc93x_irq_chip = {
- .irq_ack = nuc93x_irq_ack,
- .irq_mask = nuc93x_irq_mask,
- .irq_unmask = nuc93x_irq_unmask,
-};
-
-void __init nuc93x_init_irq(void)
-{
- int irqno;
-
- __raw_writel(0xFFFFFFFE, REG_AIC_MDCR);
-
- for (irqno = IRQ_WDT; irqno <= NR_IRQS; irqno++) {
- irq_set_chip_and_handler(irqno, &nuc93x_irq_chip,
- handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-}
diff --git a/arch/arm/mach-nuc93x/mach-nuc932evb.c b/arch/arm/mach-nuc93x/mach-nuc932evb.c
deleted file mode 100644
index d70257042480..000000000000
--- a/arch/arm/mach-nuc93x/mach-nuc932evb.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * linux/arch/arm/mach-w90x900/mach-nuc910evb.c
- *
- * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche
- *
- * Copyright (C) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@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;version 2 of the License.
- *
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach-types.h>
-#include <mach/map.h>
-
-#include "nuc932.h"
-
-static void __init nuc932evb_map_io(void)
-{
- nuc932_map_io();
- nuc932_init_clocks();
- nuc932_init_uartclk();
-}
-
-static void __init nuc932evb_init(void)
-{
- nuc932_board_init();
-}
-
-MACHINE_START(NUC932EVB, "NUC932EVB")
- /* Maintainer: Wan ZongShun */
- .boot_params = 0,
- .map_io = nuc932evb_map_io,
- .init_irq = nuc93x_init_irq,
- .init_machine = nuc932evb_init,
- .timer = &nuc93x_timer,
-MACHINE_END
diff --git a/arch/arm/mach-nuc93x/nuc932.c b/arch/arm/mach-nuc93x/nuc932.c
deleted file mode 100644
index 3966ead686fc..000000000000
--- a/arch/arm/mach-nuc93x/nuc932.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/nuc932.c
- *
- * Copyright (c) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC932 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/mach/map.h>
-#include <mach/hardware.h>
-
-#include "cpu.h"
-#include "clock.h"
-
-/* define specific CPU platform device */
-
-static struct platform_device *nuc932_dev[] __initdata = {
-};
-
-/* define specific CPU platform io map */
-
-static struct map_desc nuc932evb_iodesc[] __initdata = {
-};
-
-/*Init NUC932 evb io*/
-
-void __init nuc932_map_io(void)
-{
- nuc93x_map_io(nuc932evb_iodesc, ARRAY_SIZE(nuc932evb_iodesc));
-}
-
-/*Init NUC932 clock*/
-
-void __init nuc932_init_clocks(void)
-{
- nuc93x_init_clocks();
-}
-
-/*enable NUC932 uart clock*/
-
-void __init nuc932_init_uartclk(void)
-{
- struct clk *ck_uart = clk_get(NULL, "uart");
- BUG_ON(IS_ERR(ck_uart));
-
- clk_enable(ck_uart);
-}
-
-/*Init NUC932 board info*/
-
-void __init nuc932_board_init(void)
-{
- nuc93x_board_init(nuc932_dev, ARRAY_SIZE(nuc932_dev));
-}
diff --git a/arch/arm/mach-nuc93x/nuc932.h b/arch/arm/mach-nuc93x/nuc932.h
deleted file mode 100644
index 9a66edd5338f..000000000000
--- a/arch/arm/mach-nuc93x/nuc932.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/nuc932.h
- *
- * Copyright (c) 2008 Nuvoton corporation
- *
- * Header file for NUC93x CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-struct map_desc;
-struct sys_timer;
-
-/* core initialisation functions */
-
-extern void nuc93x_init_irq(void);
-extern struct sys_timer nuc93x_timer;
-
-/* extern file from nuc932.c */
-
-extern void nuc932_board_init(void);
-extern void nuc932_init_clocks(void);
-extern void nuc932_map_io(void);
-extern void nuc932_init_uartclk(void);
diff --git a/arch/arm/mach-nuc93x/time.c b/arch/arm/mach-nuc93x/time.c
deleted file mode 100644
index 2f90f9dc6e30..000000000000
--- a/arch/arm/mach-nuc93x/time.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/time.c
- *
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@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/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/leds.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-#include <mach/system.h>
-#include <mach/map.h>
-#include <mach/regs-timer.h>
-
-#define RESETINT 0x01
-#define PERIOD (0x01 << 27)
-#define ONESHOT (0x00 << 27)
-#define COUNTEN (0x01 << 30)
-#define INTEN (0x01 << 29)
-
-#define TICKS_PER_SEC 100
-#define PRESCALE 0x63 /* Divider = prescale + 1 */
-
-unsigned int timer0_load;
-
-static unsigned long nuc93x_gettimeoffset(void)
-{
- return 0;
-}
-
-/*IRQ handler for the timer*/
-
-static irqreturn_t nuc93x_timer_interrupt(int irq, void *dev_id)
-{
- timer_tick();
- __raw_writel(0x01, REG_TISR); /* clear TIF0 */
- return IRQ_HANDLED;
-}
-
-static struct irqaction nuc93x_timer_irq = {
- .name = "nuc93x Timer Tick",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = nuc93x_timer_interrupt,
-};
-
-/*Set up timer reg.*/
-
-static void nuc93x_timer_setup(void)
-{
- struct clk *ck_ext = clk_get(NULL, "ext");
- struct clk *ck_timer = clk_get(NULL, "timer");
- unsigned int rate, val = 0;
-
- BUG_ON(IS_ERR(ck_ext) || IS_ERR(ck_timer));
-
- clk_enable(ck_timer);
- rate = clk_get_rate(ck_ext);
- clk_put(ck_ext);
- rate = rate / (PRESCALE + 0x01);
-
- /* set a known state */
- __raw_writel(0x00, REG_TCSR0);
- __raw_writel(RESETINT, REG_TISR);
-
- timer0_load = (rate / TICKS_PER_SEC);
- __raw_writel(timer0_load, REG_TICR0);
-
- val |= (PERIOD | COUNTEN | INTEN | PRESCALE);;
- __raw_writel(val, REG_TCSR0);
-
-}
-
-static void __init nuc93x_timer_init(void)
-{
- nuc93x_timer_setup();
- setup_irq(IRQ_TIMER0, &nuc93x_timer_irq);
-}
-
-struct sys_timer nuc93x_timer = {
- .init = nuc93x_timer_init,
- .offset = nuc93x_gettimeoffset,
- .resume = nuc93x_timer_setup
-};
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 5b114d1558c8..11c85cd2731a 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -4,7 +4,7 @@
# Common support
obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
-obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o
+obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
diff --git a/arch/arm/mach-omap1/Makefile.boot b/arch/arm/mach-omap1/Makefile.boot
index 292d56c5a888..13bda8dbd604 100644
--- a/arch/arm/mach-omap1/Makefile.boot
+++ b/arch/arm/mach-omap1/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x10008000
+ zreladdr-y += 0x10008000
params_phys-y := 0x10000100
initrd_phys-y := 0x10800000
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 312ea6b0409d..1f1db76d704a 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -11,7 +11,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/input.h>
@@ -30,7 +30,6 @@
#include <plat/io.h>
#include <plat/board-ams-delta.h>
-#include <mach/gpio.h>
#include <plat/keypad.h>
#include <plat/mux.h>
#include <plat/usb.h>
@@ -135,12 +134,6 @@ void ams_delta_latch2_write(u16 mask, u16 value)
*(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg;
}
-static void __init ams_delta_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
static struct map_desc ams_delta_io_desc[] __initdata = {
/* AMS_DELTA_LATCH1 */
{
@@ -379,17 +372,13 @@ static int __init ams_delta_modem_init(void)
}
arch_initcall(ams_delta_modem_init);
-static void __init ams_delta_map_io(void)
-{
- omap1_map_common_io();
-}
-
MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
/* Maintainer: Jonathan McDowell <noodles@earth.li> */
- .boot_params = 0x10000100,
- .map_io = ams_delta_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap15xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = ams_delta_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = ams_delta_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index a6b1bea50371..23178275f96b 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -10,7 +10,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -28,7 +28,6 @@
#include <asm/mach/map.h>
#include <plat/tc.h>
-#include <mach/gpio.h>
#include <plat/mux.h>
#include <plat/flash.h>
#include <plat/fpga.h>
@@ -297,6 +296,39 @@ static struct omap_board_config_kernel fsample_config[] __initdata = {
static void __init omap_fsample_init(void)
{
+ /* Early, board-dependent init */
+
+ /*
+ * Hold GSM Reset until needed
+ */
+ omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
+
+ /*
+ * UARTs -> done automagically by 8250 driver
+ */
+
+ /*
+ * CSx timings, GPIO Mux ... setup
+ */
+
+ /* Flash: CS0 timings setup */
+ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
+ omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
+
+ /*
+ * Ethernet support through the debug board
+ * CS1 timings setup
+ */
+ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
+ omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
+
+ /*
+ * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+ * It is used as the Ethernet controller interrupt
+ */
+ omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF,
+ OMAP7XX_IO_CONF_9);
+
fsample_init_smc91x();
if (gpio_request(FSAMPLE_NAND_RB_GPIO_PIN, "NAND ready") < 0)
@@ -326,12 +358,6 @@ static void __init omap_fsample_init(void)
omap_register_i2c_bus(1, 100, NULL, 0);
}
-static void __init omap_fsample_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
/* Only FPGA needs to be mapped here. All others are done with ioremap */
static struct map_desc omap_fsample_io_desc[] __initdata = {
{
@@ -350,49 +376,18 @@ static struct map_desc omap_fsample_io_desc[] __initdata = {
static void __init omap_fsample_map_io(void)
{
- omap1_map_common_io();
+ omap15xx_map_io();
iotable_init(omap_fsample_io_desc,
ARRAY_SIZE(omap_fsample_io_desc));
-
- /* Early, board-dependent init */
-
- /*
- * Hold GSM Reset until needed
- */
- omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
-
- /*
- * UARTs -> done automagically by 8250 driver
- */
-
- /*
- * CSx timings, GPIO Mux ... setup
- */
-
- /* Flash: CS0 timings setup */
- omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
- omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
-
- /*
- * Ethernet support through the debug board
- * CS1 timings setup
- */
- omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
- omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
-
- /*
- * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
- * It is used as the Ethernet controller interrupt
- */
- omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9);
}
MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
/* Maintainer: Brian Swetland <swetland@google.com> */
- .boot_params = 0x10000100,
+ .atag_offset = 0x100,
.map_io = omap_fsample_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = omap_fsample_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = omap_fsample_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 04fc356c40fa..dc5b75de531c 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -12,7 +12,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -22,18 +22,11 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <plat/mux.h>
#include <plat/usb.h>
#include <plat/board.h>
#include <plat/common.h>
-static void __init omap_generic_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
/* assume no Mini-AB port */
#ifdef CONFIG_ARCH_OMAP15XX
@@ -87,17 +80,13 @@ static void __init omap_generic_init(void)
omap_register_i2c_bus(1, 100, NULL, 0);
}
-static void __init omap_generic_map_io(void)
-{
- omap1_map_common_io();
-}
-
MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
/* Maintainer: Tony Lindgren <tony@atomide.com> */
- .boot_params = 0x10000100,
- .map_io = omap_generic_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap16xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = omap_generic_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = omap_generic_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c
index f2fc43d8382b..da0e37d40823 100644
--- a/arch/arm/mach-omap1/board-h2-mmc.c
+++ b/arch/arm/mach-omap1/board-h2-mmc.c
@@ -11,13 +11,12 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/i2c/tps65010.h>
#include <plat/mmc.h>
-#include <mach/gpio.h>
#include "board-h2.h"
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index cb7fb1aa3dca..b334b1481678 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -18,7 +18,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
@@ -32,7 +32,6 @@
#include <linux/smc91x.h>
#include <mach/hardware.h>
-#include <asm/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -373,12 +372,6 @@ static struct i2c_board_info __initdata h2_i2c_board_info[] = {
},
};
-static void __init h2_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
static struct omap_usb_config h2_usb_config __initdata = {
/* usb1 has a Mini-AB port and external isp1301 transceiver */
.otg = 2,
@@ -454,17 +447,13 @@ static void __init h2_init(void)
h2_mmc_init();
}
-static void __init h2_map_io(void)
-{
- omap1_map_common_io();
-}
-
MACHINE_START(OMAP_H2, "TI-H2")
/* Maintainer: Imre Deak <imre.deak@nokia.com> */
- .boot_params = 0x10000100,
- .map_io = h2_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap16xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = h2_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = h2_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c
index 2098525e7cc5..f8242aa9b763 100644
--- a/arch/arm/mach-omap1/board-h3-mmc.c
+++ b/arch/arm/mach-omap1/board-h3-mmc.c
@@ -11,13 +11,12 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/i2c/tps65010.h>
#include <plat/mmc.h>
-#include <mach/gpio.h>
#include "board-h3.h"
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 31f34875ffad..74ebe72c9848 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -13,7 +13,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/major.h>
@@ -34,7 +34,6 @@
#include <asm/setup.h>
#include <asm/page.h>
#include <mach/hardware.h>
-#include <asm/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -436,23 +435,13 @@ static void __init h3_init(void)
h3_mmc_init();
}
-static void __init h3_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
-static void __init h3_map_io(void)
-{
- omap1_map_common_io();
-}
-
MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
/* Maintainer: Texas Instruments, Inc. */
- .boot_params = 0x10000100,
- .map_io = h3_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap16xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = h3_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = h3_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index 36e06ea7ec65..3e91baab1a89 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -23,7 +23,6 @@
* 02110-1301, USA.
*
*/
-
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -500,7 +499,7 @@ static void __init htcherald_lcd_init(void)
static void __init htcherald_map_io(void)
{
- omap1_map_common_io();
+ omap7xx_map_io();
/*
* The LCD panel must be disabled and DMA turned off here, as doing
@@ -601,20 +600,14 @@ static void __init htcherald_init(void)
#endif
}
-static void __init htcherald_init_irq(void)
-{
- printk(KERN_INFO "htcherald_init_irq.\n");
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
MACHINE_START(HERALD, "HTC Herald")
/* Maintainer: Cory Maccarrone <darkstar6262@gmail.com> */
/* Maintainer: wing-linux.sourceforge.net */
- .boot_params = 0x10000100,
+ .atag_offset = 0x100,
.map_io = htcherald_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = htcherald_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = htcherald_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 0b1ba462d388..273153dba15b 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -15,7 +15,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -34,7 +34,6 @@
#include <plat/mux.h>
#include <plat/flash.h>
#include <plat/fpga.h>
-#include <mach/gpio.h>
#include <plat/tc.h>
#include <plat/usb.h>
#include <plat/keypad.h>
@@ -289,12 +288,6 @@ static void __init innovator_init_smc91x(void)
}
}
-static void __init innovator_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
#ifdef CONFIG_ARCH_OMAP15XX
static struct omap_usb_config innovator1510_usb_config __initdata = {
/* for bundled non-standard host and peripheral cables */
@@ -439,30 +432,32 @@ static void __init innovator_init(void)
innovator_mmc_init();
}
+/*
+ * REVISIT: Assume 15xx for now, we don't want to do revision check
+ * until later on. The right way to fix this is to set up a different
+ * machine_id for 16xx Innovator, or use device tree.
+ */
static void __init innovator_map_io(void)
{
- omap1_map_common_io();
+ omap15xx_map_io();
-#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
- iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
- udelay(10); /* Delay needed for FPGA */
-
- /* Dump the Innovator FPGA rev early - useful info for support. */
- printk("Innovator FPGA Rev %d.%d Board Rev %d\n",
- fpga_read(OMAP1510_FPGA_REV_HIGH),
- fpga_read(OMAP1510_FPGA_REV_LOW),
- fpga_read(OMAP1510_FPGA_BOARD_REV));
- }
-#endif
+ iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
+ udelay(10); /* Delay needed for FPGA */
+
+ /* Dump the Innovator FPGA rev early - useful info for support. */
+ pr_debug("Innovator FPGA Rev %d.%d Board Rev %d\n",
+ fpga_read(OMAP1510_FPGA_REV_HIGH),
+ fpga_read(OMAP1510_FPGA_REV_LOW),
+ fpga_read(OMAP1510_FPGA_BOARD_REV));
}
MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
/* Maintainer: MontaVista Software, Inc. */
- .boot_params = 0x10000100,
+ .atag_offset = 0x100,
.map_io = innovator_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = innovator_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = innovator_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 5469ce247ffe..6798b8488315 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -7,7 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mutex.h>
@@ -26,7 +26,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <plat/mux.h>
#include <plat/usb.h>
#include <plat/board.h>
@@ -39,21 +38,6 @@
#define ADS7846_PENDOWN_GPIO 15
-static void __init omap_nokia770_init_irq(void)
-{
- /* On Nokia 770, the SleepX signal is masked with an
- * MPUIO line by default. It has to be unmasked for it
- * to become functional */
-
- /* SleepX mask direction */
- omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
- /* Unmask SleepX signal */
- omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
-
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
static const unsigned int nokia770_keymap[] = {
KEY(1, 0, GROUP_0 | KEY_UP),
KEY(2, 0, GROUP_1 | KEY_F5),
@@ -246,6 +230,15 @@ static inline void nokia770_mmc_init(void)
static void __init omap_nokia770_init(void)
{
+ /* On Nokia 770, the SleepX signal is masked with an
+ * MPUIO line by default. It has to be unmasked for it
+ * to become functional */
+
+ /* SleepX mask direction */
+ omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+ /* Unmask SleepX signal */
+ omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+
platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
spi_register_board_info(nokia770_spi_board_info,
ARRAY_SIZE(nokia770_spi_board_info));
@@ -258,16 +251,12 @@ static void __init omap_nokia770_init(void)
nokia770_mmc_init();
}
-static void __init omap_nokia770_map_io(void)
-{
- omap1_map_common_io();
-}
-
MACHINE_START(NOKIA770, "Nokia 770")
- .boot_params = 0x10000100,
- .map_io = omap_nokia770_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap16xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = omap_nokia770_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = omap_nokia770_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index b08a21380772..c3859278d257 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -25,7 +25,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -42,7 +42,6 @@
#include <linux/i2c/tps65010.h>
#include <mach/hardware.h>
-#include <asm/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -279,12 +278,6 @@ static void __init osk_init_cf(void)
irq_set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING);
}
-static void __init osk_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
static struct omap_usb_config osk_usb_config __initdata = {
/* has usb host connector (A) ... for development it can also
* be used, with a NONSTANDARD gender-bending cable/dongle, as
@@ -576,17 +569,13 @@ static void __init osk_init(void)
osk_mistral_init();
}
-static void __init osk_map_io(void)
-{
- omap1_map_common_io();
-}
-
MACHINE_START(OMAP_OSK, "TI-OSK")
/* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
- .boot_params = 0x10000100,
- .map_io = osk_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap16xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = osk_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = osk_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 459cb6bfed55..f9c44cb15b47 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -16,7 +16,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/input.h>
@@ -33,7 +33,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <plat/flash.h>
#include <plat/mux.h>
#include <plat/usb.h>
@@ -59,12 +58,6 @@
#define PALMTE_MMC2_GPIO OMAP_MPUIO(7)
#define PALMTE_MMC3_GPIO OMAP_MPUIO(11)
-static void __init omap_palmte_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
static const unsigned int palmte_keymap[] = {
KEY(0, 0, KEY_F1), /* Calendar */
KEY(1, 0, KEY_F2), /* Contacts */
@@ -269,16 +262,12 @@ static void __init omap_palmte_init(void)
omap_register_i2c_bus(1, 100, NULL, 0);
}
-static void __init omap_palmte_map_io(void)
-{
- omap1_map_common_io();
-}
-
MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
- .boot_params = 0x10000100,
- .map_io = omap_palmte_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap15xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = omap_palmte_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = omap_palmte_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index b214f45f646c..11a98539f7bb 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -12,6 +12,7 @@
*/
#include <linux/delay.h>
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -30,7 +31,6 @@
#include <asm/mach/map.h>
#include <plat/led.h>
-#include <mach/gpio.h>
#include <plat/flash.h>
#include <plat/mux.h>
#include <plat/usb.h>
@@ -263,12 +263,6 @@ static struct spi_board_info __initdata palmtt_boardinfo[] = {
}
};
-static void __init omap_palmtt_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
static struct omap_usb_config palmtt_usb_config __initdata = {
.register_dev = 1,
.hmc_mode = 0,
@@ -315,16 +309,12 @@ static void __init omap_palmtt_init(void)
omap_register_i2c_bus(1, 100, NULL, 0);
}
-static void __init omap_palmtt_map_io(void)
-{
- omap1_map_common_io();
-}
-
MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
- .boot_params = 0x10000100,
- .map_io = omap_palmtt_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap15xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = omap_palmtt_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = omap_palmtt_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index 9b0ea48d35fd..c6fe61dfe856 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -15,6 +15,7 @@
*/
#include <linux/delay.h>
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -32,7 +33,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <plat/flash.h>
#include <plat/mux.h>
#include <plat/usb.h>
@@ -57,13 +57,6 @@
#define PALMZ71_SLIDER_GPIO OMAP_MPUIO(3)
#define PALMZ71_MMC_IN_GPIO OMAP_MPUIO(4)
-static void __init
-omap_palmz71_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
static const unsigned int palmz71_keymap[] = {
KEY(0, 0, KEY_F1),
KEY(1, 0, KEY_F2),
@@ -334,17 +327,12 @@ omap_palmz71_init(void)
palmz71_gpio_setup(0);
}
-static void __init
-omap_palmz71_map_io(void)
-{
- omap1_map_common_io();
-}
-
MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
- .boot_params = 0x10000100,
- .map_io = omap_palmz71_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap15xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = omap_palmz71_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = omap_palmz71_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 67acd4142639..203ae07550db 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -10,7 +10,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -28,7 +28,6 @@
#include <asm/mach/map.h>
#include <plat/tc.h>
-#include <mach/gpio.h>
#include <plat/mux.h>
#include <plat/fpga.h>
#include <plat/flash.h>
@@ -265,6 +264,39 @@ static void __init perseus2_init_smc91x(void)
static void __init omap_perseus2_init(void)
{
+ /* Early, board-dependent init */
+
+ /*
+ * Hold GSM Reset until needed
+ */
+ omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
+
+ /*
+ * UARTs -> done automagically by 8250 driver
+ */
+
+ /*
+ * CSx timings, GPIO Mux ... setup
+ */
+
+ /* Flash: CS0 timings setup */
+ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
+ omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
+
+ /*
+ * Ethernet support through the debug board
+ * CS1 timings setup
+ */
+ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
+ omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
+
+ /*
+ * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+ * It is used as the Ethernet controller interrupt
+ */
+ omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF,
+ OMAP7XX_IO_CONF_9);
+
perseus2_init_smc91x();
if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0)
@@ -294,11 +326,6 @@ static void __init omap_perseus2_init(void)
omap_register_i2c_bus(1, 100, NULL, 0);
}
-static void __init omap_perseus2_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
/* Only FPGA needs to be mapped here. All others are done with ioremap */
static struct map_desc omap_perseus2_io_desc[] __initdata = {
{
@@ -311,49 +338,18 @@ static struct map_desc omap_perseus2_io_desc[] __initdata = {
static void __init omap_perseus2_map_io(void)
{
- omap1_map_common_io();
+ omap7xx_map_io();
iotable_init(omap_perseus2_io_desc,
ARRAY_SIZE(omap_perseus2_io_desc));
-
- /* Early, board-dependent init */
-
- /*
- * Hold GSM Reset until needed
- */
- omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
-
- /*
- * UARTs -> done automagically by 8250 driver
- */
-
- /*
- * CSx timings, GPIO Mux ... setup
- */
-
- /* Flash: CS0 timings setup */
- omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
- omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
-
- /*
- * Ethernet support through the debug board
- * CS1 timings setup
- */
- omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
- omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
-
- /*
- * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
- * It is used as the Ethernet controller interrupt
- */
- omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9);
}
MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
/* Maintainer: Kevin Hilman <kjh@hilman.org> */
- .boot_params = 0x10000100,
+ .atag_offset = 0x100,
.map_io = omap_perseus2_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = omap_perseus2_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = omap_perseus2_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c
index e8ddd86e3fda..b59f78850e69 100644
--- a/arch/arm/mach-omap1/board-sx1-mmc.c
+++ b/arch/arm/mach-omap1/board-sx1-mmc.c
@@ -12,11 +12,11 @@
* published by the Free Software Foundation.
*/
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <mach/hardware.h>
#include <plat/mmc.h>
-#include <mach/gpio.h>
#include <plat/board-sx1.h>
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 9c3b7c52d9cf..667a7cbdb11c 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -14,7 +14,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/input.h>
@@ -32,7 +32,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <plat/flash.h>
#include <plat/mux.h>
#include <plat/dma.h>
@@ -407,24 +406,13 @@ static void __init omap_sx1_init(void)
gpio_direction_output(11, 0); /*A_SWITCH = 0 */
gpio_direction_output(15, 0); /*A_USB_ON = 0 */
}
-/*----------------------------------------*/
-static void __init omap_sx1_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-/*----------------------------------------*/
-
-static void __init omap_sx1_map_io(void)
-{
- omap1_map_common_io();
-}
MACHINE_START(SX1, "OMAP310 based Siemens SX1")
- .boot_params = 0x10000100,
- .map_io = omap_sx1_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap15xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = omap_sx1_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = omap_sx1_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 036edc0ee9b6..2a6545ba61c4 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -13,6 +13,7 @@
*/
#include <linux/delay.h>
+#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -33,7 +34,6 @@
#include <plat/board-voiceblue.h>
#include <plat/common.h>
-#include <mach/gpio.h>
#include <plat/flash.h>
#include <plat/mux.h>
#include <plat/tc.h>
@@ -159,17 +159,6 @@ static struct omap_usb_config voiceblue_usb_config __initdata = {
static struct omap_board_config_kernel voiceblue_config[] = {
};
-static void __init voiceblue_init_irq(void)
-{
- omap1_init_common_hw();
- omap1_init_irq();
-}
-
-static void __init voiceblue_map_io(void)
-{
- omap1_map_common_io();
-}
-
#define MACHINE_PANICED 1
#define MACHINE_REBOOTING 2
#define MACHINE_REBOOT 4
@@ -301,10 +290,11 @@ static void __init voiceblue_init(void)
MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
/* Maintainer: Ladislav Michl <michl@2n.cz> */
- .boot_params = 0x10000100,
- .map_io = voiceblue_map_io,
+ .atag_offset = 0x100,
+ .map_io = omap15xx_map_io,
+ .init_early = omap1_init_early,
.reserve = omap_reserve,
- .init_irq = voiceblue_init_irq,
+ .init_irq = omap1_init_irq,
.init_machine = voiceblue_init,
.timer = &omap1_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index 36f26c3fa25e..48ef9888e820 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -10,6 +10,7 @@
*/
#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -21,10 +22,10 @@
#include <mach/hardware.h>
#include <asm/mach/map.h>
+#include <plat/common.h>
#include <plat/tc.h>
#include <plat/board.h>
#include <plat/mux.h>
-#include <mach/gpio.h>
#include <plat/mmc.h>
#include <plat/omap7xx.h>
#include <plat/mcbsp.h>
@@ -291,6 +292,8 @@ static int __init omap1_init_devices(void)
if (!cpu_class_is_omap1())
return -ENODEV;
+ omap_sram_init();
+
/* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through.
*/
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
index cddbf8b089ce..0a17a1a7e00d 100644
--- a/arch/arm/mach-omap1/fpga.c
+++ b/arch/arm/mach-omap1/fpga.c
@@ -17,6 +17,7 @@
*/
#include <linux/types.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
@@ -28,7 +29,6 @@
#include <asm/mach/irq.h>
#include <plat/fpga.h>
-#include <mach/gpio.h>
static void fpga_mask_irq(struct irq_data *d)
{
diff --git a/arch/arm/mach-omap1/include/mach/debug-macro.S b/arch/arm/mach-omap1/include/mach/debug-macro.S
index 62856044eb63..2b36a281dc84 100644
--- a/arch/arm/mach-omap1/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap1/include/mach/debug-macro.S
@@ -13,13 +13,8 @@
#include <linux/serial_reg.h>
-#include <asm/memory.h>
-
#include <plat/serial.h>
-#define omap_uart_v2p(x) ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
-#define omap_uart_p2v(x) ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
-
.pushsection .data
omap_uart_phys: .word 0x0
omap_uart_virt: .word 0x0
@@ -31,26 +26,24 @@ omap_uart_virt: .word 0x0
* the desired UART phys and virt addresses temporarily into
* the omap_uart_phys and omap_uart_virt above.
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
/* Use omap_uart_phys/virt if already configured */
-9: mrc p15, 0, \rp, c1, c0
- tst \rp, #1 @ MMU enabled?
- ldreq \rp, =omap_uart_v2p(omap_uart_phys) @ MMU disabled
- ldrne \rp, =omap_uart_phys @ MMU enabled
- add \rv, \rp, #4 @ omap_uart_virt
- ldr \rp, [\rp, #0]
- ldr \rv, [\rv, #0]
+9: adr \rp, 99f @ get effective addr of 99f
+ ldr \rv, [\rp] @ get absolute addr of 99f
+ sub \rv, \rv, \rp @ offset between the two
+ ldr \rp, [\rp, #4] @ abs addr of omap_uart_phys
+ sub \tmp, \rp, \rv @ make it effective
+ ldr \rp, [\tmp, #0] @ omap_uart_phys
+ ldr \rv, [\tmp, #4] @ omap_uart_virt
cmp \rp, #0 @ is port configured?
cmpne \rv, #0
- bne 99f @ already configured
+ bne 100f @ already configured
/* Check the debug UART configuration set in uncompress.h */
- mrc p15, 0, \rp, c1, c0
- tst \rp, #1 @ MMU enabled?
- ldreq \rp, =OMAP_UART_INFO @ MMU not enabled
- ldrne \rp, =omap_uart_p2v(OMAP_UART_INFO) @ MMU enabled
- ldr \rp, [\rp, #0]
+ and \rp, pc, #0xff000000
+ ldr \rv, =OMAP_UART_INFO_OFS
+ ldr \rp, [\rp, \rv]
/* Select the UART to use based on the UART1 scratchpad value */
10: cmp \rp, #0 @ no port configured?
@@ -74,17 +67,18 @@ omap_uart_virt: .word 0x0
/* Store both phys and virt address for the uart */
98: add \rp, \rp, #0xff000000 @ phys base
- mrc p15, 0, \rv, c1, c0
- tst \rv, #1 @ MMU enabled?
- ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled
- ldrne \rv, =omap_uart_phys @ MMU enabled
- str \rp, [\rv, #0]
+ str \rp, [\tmp, #0] @ omap_uart_phys
sub \rp, \rp, #0xff000000 @ phys base
add \rp, \rp, #0xfe000000 @ virt base
- add \rv, \rv, #4 @ omap_uart_lsr
- str \rp, [\rv, #0]
+ str \rp, [\tmp, #4] @ omap_uart_virt
b 9b
-99:
+
+ .align
+99: .word .
+ .word omap_uart_phys
+ .ltorg
+
+100:
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-omap1/include/mach/memory.h b/arch/arm/mach-omap1/include/mach/memory.h
index e9b600c113ef..c6337645ba8a 100644
--- a/arch/arm/mach-omap1/include/mach/memory.h
+++ b/arch/arm/mach-omap1/include/mach/memory.h
@@ -2,4 +2,55 @@
* arch/arm/mach-omap1/include/mach/memory.h
*/
-#include <plat/memory.h>
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PLAT_PHYS_OFFSET UL(0x10000000)
+
+/*
+ * Bus address is physical address, except for OMAP-1510 Local Bus.
+ * OMAP-1510 bus address is translated into a Local Bus address if the
+ * OMAP bus type is lbus. We do the address translation based on the
+ * device overriding the defaults used in the dma-mapping API.
+ * Note that the is_lbus_device() test is not very efficient on 1510
+ * because of the strncmp().
+ */
+#ifdef CONFIG_ARCH_OMAP15XX
+
+/*
+ * OMAP-1510 Local Bus address offset
+ */
+#define OMAP1510_LB_OFFSET UL(0x30000000)
+
+#define virt_to_lbus(x) ((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
+#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
+#define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
+
+#define __arch_pfn_to_dma(dev, pfn) \
+ ({ dma_addr_t __dma = __pfn_to_phys(pfn); \
+ if (is_lbus_device(dev)) \
+ __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
+ __dma; })
+
+#define __arch_dma_to_pfn(dev, addr) \
+ ({ dma_addr_t __dma = addr; \
+ if (is_lbus_device(dev)) \
+ __dma += PHYS_OFFSET - OMAP1510_LB_OFFSET; \
+ __phys_to_pfn(__dma); \
+ })
+
+#define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \
+ lbus_to_virt(addr) : \
+ __phys_to_virt(addr)); })
+
+#define __arch_virt_to_dma(dev, addr) ({ unsigned long __addr = (unsigned long)(addr); \
+ (dma_addr_t) (is_lbus_device(dev) ? \
+ virt_to_lbus(__addr) : \
+ __virt_to_phys(__addr)); })
+
+#endif /* CONFIG_ARCH_OMAP15XX */
+
+#endif
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 870886a29594..7969cfda4454 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -21,7 +21,6 @@
#include "clock.h"
extern void omap_check_revision(void);
-extern void omap_sram_init(void);
/*
* The machine specific code may provide the extra mapping besides the
@@ -85,50 +84,45 @@ static struct map_desc omap16xx_io_desc[] __initdata = {
#endif
/*
- * Maps common IO regions for omap1. This should only get called from
- * board specific init.
+ * Maps common IO regions for omap1
*/
-void __init omap1_map_common_io(void)
+static void __init omap1_map_common_io(void)
{
iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
-
- /* Normally devicemaps_init() would flush caches and tlb after
- * mdesc->map_io(), but we must also do it here because of the CPU
- * revision check below.
- */
- local_flush_tlb_all();
- flush_cache_all();
-
- /* We want to check CPU revision early for cpu_is_omapxxxx() macros.
- * IO space mapping must be initialized before we can do that.
- */
- omap_check_revision();
+}
#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
- if (cpu_is_omap7xx()) {
- iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
- }
+void __init omap7xx_map_io(void)
+{
+ omap1_map_common_io();
+ iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
+}
#endif
+
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap15xx()) {
- iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
- }
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
- if (cpu_is_omap16xx()) {
- iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
- }
+void __init omap15xx_map_io(void)
+{
+ omap1_map_common_io();
+ iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
+}
#endif
- omap_sram_init();
+#if defined(CONFIG_ARCH_OMAP16XX)
+void __init omap16xx_map_io(void)
+{
+ omap1_map_common_io();
+ iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
}
+#endif
/*
- * Common low-level hardware init for omap1. This should only get called from
- * board specific init.
+ * Common low-level hardware init for omap1.
*/
-void __init omap1_init_common_hw(void)
+void omap1_init_early(void)
{
+ omap_check_revision();
+ omap_ioremap_init();
+
/* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
* on a Posted Write in the TIPB Bridge".
*/
@@ -138,8 +132,8 @@ void __init omap1_init_common_hw(void)
/* Must init clocks early to assure that timer interrupt works
*/
omap1_clk_init();
-
omap1_mux_init();
+ omap_init_consistent_dma_size();
}
/*
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index e2b9c901ab67..e5b104b7fce6 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -35,7 +35,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
@@ -45,7 +45,6 @@
#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
-#include <mach/gpio.h>
#include <plat/cpu.h>
#define IRQ_BANK(irq) ((irq) >> 5)
diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c
index b4f9be52e1e8..4b818eb9f911 100644
--- a/arch/arm/mach-omap1/leds-h2p2-debug.c
+++ b/arch/arm/mach-omap1/leds-h2p2-debug.c
@@ -9,6 +9,7 @@
* The "surfer" expansion board and H2 sample board also have two-color
* green+red LEDs (in parallel), used here for timer and idle indicators.
*/
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/sched.h>
@@ -20,7 +21,6 @@
#include <asm/mach-types.h>
#include <plat/fpga.h>
-#include <mach/gpio.h>
#include "leds.h"
diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c
index 499d7ad8697d..da09f4364979 100644
--- a/arch/arm/mach-omap1/leds-osk.c
+++ b/arch/arm/mach-omap1/leds-osk.c
@@ -3,14 +3,13 @@
*
* LED driver for OSK with optional Mistral QVGA board
*/
+#include <linux/gpio.h>
#include <linux/init.h>
#include <mach/hardware.h>
#include <asm/leds.h>
#include <asm/system.h>
-#include <mach/gpio.h>
-
#include "leds.h"
diff --git a/arch/arm/mach-omap1/leds.c b/arch/arm/mach-omap1/leds.c
index 22eb11dde9e7..ae6dd93b8ddc 100644
--- a/arch/arm/mach-omap1/leds.c
+++ b/arch/arm/mach-omap1/leds.c
@@ -3,13 +3,13 @@
*
* OMAP LEDs dispatcher
*/
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/leds.h>
#include <asm/mach-types.h>
-#include <mach/gpio.h>
#include <plat/mux.h>
#include "leds.h"
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index ab7395d84bc8..91f9abbd3250 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -31,6 +31,7 @@
static int dsp_use;
static struct clk *api_clk;
static struct clk *dsp_clk;
+static struct platform_device **omap_mcbsp_devices;
static void omap1_mcbsp_request(unsigned int id)
{
@@ -78,6 +79,17 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = {
.free = omap1_mcbsp_free,
};
+#define OMAP7XX_MCBSP1_BASE 0xfffb1000
+#define OMAP7XX_MCBSP2_BASE 0xfffb1800
+
+#define OMAP1510_MCBSP1_BASE 0xe1011800
+#define OMAP1510_MCBSP2_BASE 0xfffb1000
+#define OMAP1510_MCBSP3_BASE 0xe1017000
+
+#define OMAP1610_MCBSP1_BASE 0xe1011800
+#define OMAP1610_MCBSP2_BASE 0xfffb1000
+#define OMAP1610_MCBSP3_BASE 0xe1017000
+
#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
struct resource omap7xx_mcbsp_res[][6] = {
{
@@ -369,6 +381,39 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
#define OMAP16XX_MCBSP_COUNT 0
#endif
+static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
+ struct omap_mcbsp_platform_data *config, int size)
+{
+ int i;
+
+ omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
+ GFP_KERNEL);
+ if (!omap_mcbsp_devices) {
+ printk(KERN_ERR "Could not register McBSP devices\n");
+ return;
+ }
+
+ for (i = 0; i < size; i++) {
+ struct platform_device *new_mcbsp;
+ int ret;
+
+ new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
+ if (!new_mcbsp)
+ continue;
+ platform_device_add_resources(new_mcbsp, &res[i * res_count],
+ res_count);
+ config[i].reg_size = 2;
+ config[i].reg_step = 2;
+ new_mcbsp->dev.platform_data = &config[i];
+ ret = platform_device_add(new_mcbsp);
+ if (ret) {
+ platform_device_put(new_mcbsp);
+ continue;
+ }
+ omap_mcbsp_devices[i] = new_mcbsp;
+ }
+}
+
static int __init omap1_mcbsp_init(void)
{
if (!cpu_class_is_omap1())
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
index 943072d5a1d5..7868e75ad077 100644
--- a/arch/arm/mach-omap1/pm_bus.c
+++ b/arch/arm/mach-omap1/pm_bus.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/clk.h>
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index 550ca9d9991d..93ae8f29727e 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -7,7 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -24,7 +24,6 @@
#include <plat/board.h>
#include <plat/mux.h>
-#include <mach/gpio.h>
#include <plat/fpga.h>
#include "pm.h"
diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c
new file mode 100644
index 000000000000..6e90665a7c47
--- /dev/null
+++ b/arch/arm/mach-omap1/timer.c
@@ -0,0 +1,173 @@
+/**
+ * OMAP1 Dual-Mode Timers - platform device registration
+ *
+ * Contains first level initialization routines which internally
+ * generates timer device information and registers with linux
+ * device model. It also has low level function to chnage the timer
+ * input clock source.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@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.
+ *
+ * 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/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+
+#include <plat/dmtimer.h>
+
+#define OMAP1610_GPTIMER1_BASE 0xfffb1400
+#define OMAP1610_GPTIMER2_BASE 0xfffb1c00
+#define OMAP1610_GPTIMER3_BASE 0xfffb2400
+#define OMAP1610_GPTIMER4_BASE 0xfffb2c00
+#define OMAP1610_GPTIMER5_BASE 0xfffb3400
+#define OMAP1610_GPTIMER6_BASE 0xfffb3c00
+#define OMAP1610_GPTIMER7_BASE 0xfffb7400
+#define OMAP1610_GPTIMER8_BASE 0xfffbd400
+
+#define OMAP1_DM_TIMER_COUNT 8
+
+static int omap1_dm_timer_set_src(struct platform_device *pdev,
+ int source)
+{
+ int n = (pdev->id - 1) << 1;
+ u32 l;
+
+ l = __raw_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+ l |= source << n;
+ __raw_writel(l, MOD_CONF_CTRL_1);
+
+ return 0;
+}
+
+
+int __init omap1_dm_timer_init(void)
+{
+ int i;
+ int ret;
+ struct dmtimer_platform_data *pdata;
+ struct platform_device *pdev;
+
+ if (!cpu_is_omap16xx())
+ return 0;
+
+ for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) {
+ struct resource res[2];
+ u32 base, irq;
+
+ switch (i) {
+ case 1:
+ base = OMAP1610_GPTIMER1_BASE;
+ irq = INT_1610_GPTIMER1;
+ break;
+ case 2:
+ base = OMAP1610_GPTIMER2_BASE;
+ irq = INT_1610_GPTIMER2;
+ break;
+ case 3:
+ base = OMAP1610_GPTIMER3_BASE;
+ irq = INT_1610_GPTIMER3;
+ break;
+ case 4:
+ base = OMAP1610_GPTIMER4_BASE;
+ irq = INT_1610_GPTIMER4;
+ break;
+ case 5:
+ base = OMAP1610_GPTIMER5_BASE;
+ irq = INT_1610_GPTIMER5;
+ break;
+ case 6:
+ base = OMAP1610_GPTIMER6_BASE;
+ irq = INT_1610_GPTIMER6;
+ break;
+ case 7:
+ base = OMAP1610_GPTIMER7_BASE;
+ irq = INT_1610_GPTIMER7;
+ break;
+ case 8:
+ base = OMAP1610_GPTIMER8_BASE;
+ irq = INT_1610_GPTIMER8;
+ break;
+ default:
+ /*
+ * not supposed to reach here.
+ * this is to remove warning.
+ */
+ return -EINVAL;
+ }
+
+ pdev = platform_device_alloc("omap_timer", i);
+ if (!pdev) {
+ pr_err("%s: Failed to device alloc for dmtimer%d\n",
+ __func__, i);
+ return -ENOMEM;
+ }
+
+ memset(res, 0, 2 * sizeof(struct resource));
+ res[0].start = base;
+ res[0].end = base + 0x46;
+ res[0].flags = IORESOURCE_MEM;
+ res[1].start = irq;
+ res[1].end = irq;
+ res[1].flags = IORESOURCE_IRQ;
+ ret = platform_device_add_resources(pdev, res,
+ ARRAY_SIZE(res));
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Failed to add resources.\n",
+ __func__);
+ goto err_free_pdev;
+ }
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&pdev->dev, "%s: Failed to allocate pdata.\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_free_pdata;
+ }
+
+ pdata->set_timer_src = omap1_dm_timer_set_src;
+ pdata->needs_manual_reset = 1;
+
+ ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Failed to add platform data.\n",
+ __func__);
+ goto err_free_pdata;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Failed to add platform device.\n",
+ __func__);
+ goto err_free_pdata;
+ }
+
+ dev_dbg(&pdev->dev, " Registered.\n");
+ }
+
+ return 0;
+
+err_free_pdata:
+ kfree(pdata);
+
+err_free_pdev:
+ platform_device_unregister(pdev);
+
+ return ret;
+}
+arch_initcall(omap1_dm_timer_init);
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 1aee224c9e47..503414718905 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -35,6 +35,7 @@ config ARCH_OMAP3
select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
select ARCH_HAS_OPP
select PM_OPP if PM
+ select ARM_CPU_SUSPEND if PM
config ARCH_OMAP4
bool "TI OMAP4"
@@ -49,6 +50,7 @@ config ARCH_OMAP4
select ARCH_HAS_OPP
select PM_OPP if PM
select USB_ARCH_HAS_EHCI
+ select ARM_CPU_SUSPEND if PM
comment "OMAP Core Type"
depends on ARCH_OMAP2
@@ -105,9 +107,13 @@ comment "OMAP Board Type"
depends on ARCH_OMAP2PLUS
config MACH_OMAP_GENERIC
- bool "Generic OMAP board"
- depends on ARCH_OMAP2
+ bool "Generic OMAP2+ board"
+ depends on ARCH_OMAP2PLUS
+ select USE_OF
default y
+ help
+ Support for generic TI OMAP2+ boards using Flattened Device Tree.
+ More information at Documentation/devicetree
config MACH_OMAP2_TUSB6010
bool
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index f34336560437..69ab1c069134 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -89,14 +89,13 @@ obj-$(CONFIG_ARCH_OMAP4) += prcm.o cm2xxx_3xxx.o cminst44xx.o \
vp44xx_data.o
# OMAP voltage domains
-ifeq ($(CONFIG_PM),y)
-voltagedomain-common := voltage.o
-obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common)
+voltagedomain-common := voltage.o vc.o vp.o
+obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common) \
+ voltagedomains2xxx_data.o
obj-$(CONFIG_ARCH_OMAP3) += $(voltagedomain-common) \
voltagedomains3xxx_data.o
obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common) \
voltagedomains44xx_data.o
-endif
# OMAP powerdomain framework
powerdomain-common += powerdomain.o powerdomain-common.o
@@ -116,9 +115,12 @@ obj-$(CONFIG_ARCH_OMAP4) += $(powerdomain-common) \
obj-$(CONFIG_ARCH_OMAP2) += clockdomain.o \
clockdomain2xxx_3xxx.o \
clockdomains2xxx_3xxx_data.o
+obj-$(CONFIG_SOC_OMAP2420) += clockdomains2420_data.o
+obj-$(CONFIG_SOC_OMAP2430) += clockdomains2430_data.o
obj-$(CONFIG_ARCH_OMAP3) += clockdomain.o \
clockdomain2xxx_3xxx.o \
- clockdomains2xxx_3xxx_data.o
+ clockdomains2xxx_3xxx_data.o \
+ clockdomains3xxx_data.o
obj-$(CONFIG_ARCH_OMAP4) += clockdomain.o \
clockdomain44xx.o \
clockdomains44xx_data.o
@@ -185,81 +187,67 @@ endif
# Specific board support
obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
-obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o \
- hsmmc.o
+obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o
obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
-obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \
- hsmmc.o
-obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o \
- hsmmc.o
-obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o \
- board-flash.o \
- hsmmc.o
-obj-$(CONFIG_MACH_OMAP3530_LV_SOM) += board-omap3logic.o \
- hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_TORPEDO) += board-omap3logic.o \
- hsmmc.o
-obj-$(CONFIG_MACH_OVERO) += board-overo.o \
- hsmmc.o
-obj-$(CONFIG_MACH_OMAP3EVM) += board-omap3evm.o \
- hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \
- hsmmc.o
-obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \
- hsmmc.o \
- board-flash.o
+obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o
+obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o
+obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o
+obj-$(CONFIG_MACH_OMAP3530_LV_SOM) += board-omap3logic.o
+obj-$(CONFIG_MACH_OMAP3_TORPEDO) += board-omap3logic.o
+obj-$(CONFIG_MACH_ENCORE) += board-omap3encore.o
+obj-$(CONFIG_MACH_OVERO) += board-overo.o
+obj-$(CONFIG_MACH_OMAP3EVM) += board-omap3evm.o
+obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o
+obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o
obj-$(CONFIG_MACH_NOKIA_N8X0) += board-n8x0.o
obj-$(CONFIG_MACH_NOKIA_RM680) += board-rm680.o \
- sdram-nokia.o \
- hsmmc.o
+ sdram-nokia.o
obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \
sdram-nokia.o \
board-rx51-peripherals.o \
- board-rx51-video.o \
- hsmmc.o
+ board-rx51-video.o
obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom.o \
board-zoom-peripherals.o \
board-zoom-display.o \
- board-flash.o \
- hsmmc.o \
board-zoom-debugboard.o
obj-$(CONFIG_MACH_OMAP_ZOOM3) += board-zoom.o \
board-zoom-peripherals.o \
board-zoom-display.o \
- board-flash.o \
- hsmmc.o \
board-zoom-debugboard.o
obj-$(CONFIG_MACH_OMAP_3630SDP) += board-3630sdp.o \
board-zoom-peripherals.o \
- board-zoom-display.o \
- board-flash.o \
- hsmmc.o
-obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o \
- hsmmc.o
+ board-zoom-display.o
+obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o
obj-$(CONFIG_MACH_CM_T3517) += board-cm-t3517.o
-obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o \
- hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o \
- hsmmc.o
-obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o \
- hsmmc.o \
- omap_phy_internal.o
-obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o \
- hsmmc.o \
- omap_phy_internal.o
-
-obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o \
- omap_phy_internal.o \
+obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o
+obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o
+obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o
+obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o
+
+obj-$(CONFIG_MACH_PCM049) += board-omap4pcm049.o
+
+obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o
obj-$(CONFIG_MACH_CRANEBOARD) += board-am3517crane.o
-obj-$(CONFIG_MACH_SBC3530) += board-omap3stalker.o \
- hsmmc.o
+obj-$(CONFIG_MACH_SBC3530) += board-omap3stalker.o
obj-$(CONFIG_MACH_TI8168EVM) += board-ti8168evm.o
+
# Platform specific device init code
+
+omap-flash-$(CONFIG_MTD_NAND_OMAP2) := board-flash.o
+omap-flash-$(CONFIG_MTD_ONENAND_OMAP2) := board-flash.o
+obj-y += $(omap-flash-y) $(omap-flash-m)
+
+omap-hsmmc-$(CONFIG_MMC_OMAP_HS) := hsmmc.o
+obj-y += $(omap-hsmmc-m) $(omap-hsmmc-y)
+
+
usbfs-$(CONFIG_ARCH_OMAP_OTG) := usb-fs.o
obj-y += $(usbfs-m) $(usbfs-y)
obj-y += usb-musb.o
+obj-y += omap_phy_internal.o
+
obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o
obj-y += usb-host.o
diff --git a/arch/arm/mach-omap2/Makefile.boot b/arch/arm/mach-omap2/Makefile.boot
index 565aff7f37a9..b03e562acc60 100644
--- a/arch/arm/mach-omap2/Makefile.boot
+++ b/arch/arm/mach-omap2/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x80008000
+ zreladdr-y += 0x80008000
params_phys-y := 0x80000100
initrd_phys-y := 0x80800000
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index f79b7d2a8ed4..d704f0ac328d 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -39,6 +39,9 @@
#include <plat/usb.h>
#include <plat/gpmc-smc91x.h>
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
#include "mux.h"
#include "hsmmc.h"
#include "common-board-devices.h"
@@ -99,20 +102,72 @@ static struct platform_device sdp2430_flash_device = {
.resource = &sdp2430_flash_resource,
};
-static struct platform_device sdp2430_lcd_device = {
- .name = "sdp2430_lcd",
- .id = -1,
-};
-
static struct platform_device *sdp2430_devices[] __initdata = {
&sdp2430_flash_device,
+};
+
+/* LCD */
+#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91
+#define SDP2430_LCD_PANEL_ENABLE_GPIO 154
+
+static int sdp2430_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+ gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 1);
+ gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 1);
+
+ return 0;
+}
+
+static void sdp2430_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+ gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 0);
+ gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 0);
+}
+
+static struct panel_generic_dpi_data sdp2430_panel_data = {
+ .name = "nec_nl2432dr22-11b",
+ .platform_enable = sdp2430_panel_enable_lcd,
+ .platform_disable = sdp2430_panel_disable_lcd,
+};
+
+static struct omap_dss_device sdp2430_lcd_device = {
+ .name = "lcd",
+ .driver_name = "generic_dpi_panel",
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .phy.dpi.data_lines = 16,
+ .data = &sdp2430_panel_data,
+};
+
+static struct omap_dss_device *sdp2430_dss_devices[] = {
&sdp2430_lcd_device,
};
-static struct omap_lcd_config sdp2430_lcd_config __initdata = {
- .ctrl_name = "internal",
+static struct omap_dss_board_info sdp2430_dss_data = {
+ .num_devices = ARRAY_SIZE(sdp2430_dss_devices),
+ .devices = sdp2430_dss_devices,
+ .default_device = &sdp2430_lcd_device,
};
+static void __init sdp2430_display_init(void)
+{
+ int r;
+
+ static struct gpio gpios[] __initdata = {
+ { SDP2430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
+ "LCD reset" },
+ { SDP2430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW,
+ "LCD Backlight" },
+ };
+
+ r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+ if (r) {
+ pr_err("Cannot request LCD GPIOs, error %d\n", r);
+ return;
+ }
+
+ omap_display_init(&sdp2430_dss_data);
+}
+
#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
static struct omap_smc91x_platform_data board_smc91x_data = {
@@ -137,16 +192,6 @@ static inline void board_smc91x_init(void)
#endif
-static struct omap_board_config_kernel sdp2430_config[] __initdata = {
- {OMAP_TAG_LCD, &sdp2430_lcd_config},
-};
-
-static void __init omap_2430sdp_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
-
static struct regulator_consumer_supply sdp2430_vmmc1_supplies[] = {
REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
@@ -229,13 +274,11 @@ static void __init omap_2430sdp_init(void)
{
omap2430_mux_init(board_mux, OMAP_PACKAGE_ZAC);
- omap_board_config = sdp2430_config;
- omap_board_config_size = ARRAY_SIZE(sdp2430_config);
-
omap2430_i2c_init();
platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
omap_serial_init();
+ omap_sdrc_init(NULL, NULL);
omap2_hsmmc_init(mmc);
omap2_usbfs_init(&sdp2430_usb_config);
@@ -247,20 +290,16 @@ static void __init omap_2430sdp_init(void)
/* Turn off secondary LCD backlight */
gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW,
"Secondary LCD backlight");
-}
-static void __init omap_2430sdp_map_io(void)
-{
- omap2_set_globals_243x();
- omap243x_map_common_io();
+ sdp2430_display_init();
}
MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
/* Maintainer: Syed Khasim - Texas Instruments Inc */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
- .map_io = omap_2430sdp_map_io,
- .init_early = omap_2430sdp_init_early,
+ .map_io = omap243x_map_io,
+ .init_early = omap2430_init_early,
.init_irq = omap2_init_irq,
.init_machine = omap_2430sdp_init,
.timer = &omap2_timer,
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index bd600cfb7f80..77142c13fa13 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -37,7 +37,7 @@
#include <plat/dma.h>
#include <plat/gpmc.h>
#include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
#include <plat/gpmc-smc91x.h>
@@ -186,8 +186,7 @@ static struct omap_dss_device sdp3430_lcd_device = {
.platform_disable = sdp3430_panel_disable_lcd,
};
-static struct panel_generic_dpi_data dvi_panel = {
- .name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
.platform_enable = sdp3430_panel_enable_dvi,
.platform_disable = sdp3430_panel_disable_dvi,
};
@@ -195,7 +194,7 @@ static struct panel_generic_dpi_data dvi_panel = {
static struct omap_dss_device sdp3430_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "generic_dpi_panel",
+ .driver_name = "dvi",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -225,12 +224,6 @@ static struct omap_dss_board_info sdp3430_dss_data = {
static struct omap_board_config_kernel sdp3430_config[] __initdata = {
};
-static void __init omap_3430sdp_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(hyb18m512160af6_sdrc_params, NULL);
-}
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
@@ -719,6 +712,7 @@ static void __init omap_3430sdp_init(void)
gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1;
omap_ads7846_init(1, gpio_pendown, 310, NULL);
board_serial_init();
+ omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
usb_musb_init(NULL);
board_smc91x_init();
board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
@@ -729,10 +723,10 @@ static void __init omap_3430sdp_init(void)
MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
/* Maintainer: Syed Khasim - Texas Instruments Inc */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = omap_3430sdp_init_early,
+ .init_early = omap3430_init_early,
.init_irq = omap3_init_irq,
.init_machine = omap_3430sdp_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index e4f37b57a0c4..f552305162fc 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -70,13 +70,6 @@ static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
static struct omap_board_config_kernel sdp_config[] __initdata = {
};
-static void __init omap_sdp_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
- h8mbx00u0mer0em_sdrc_params);
-}
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -207,6 +200,8 @@ static void __init omap_sdp_init(void)
omap_board_config = sdp_config;
omap_board_config_size = ARRAY_SIZE(sdp_config);
zoom_peripherals_init();
+ omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
+ h8mbx00u0mer0em_sdrc_params);
zoom_display_init();
board_smc91x_init();
board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
@@ -215,10 +210,10 @@ static void __init omap_sdp_init(void)
}
MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = omap_sdp_init_early,
+ .init_early = omap3630_init_early,
.init_irq = omap3_init_irq,
.init_machine = omap_sdp_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index c7cef44c75d4..515646886b59 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -38,6 +38,8 @@
#include <plat/mmc.h>
#include <plat/omap4-keypad.h>
#include <video/omapdss.h>
+#include <video/omap-panel-nokia-dsi.h>
+#include <video/omap-panel-picodlp.h>
#include <linux/wl12xx.h>
#include "mux.h"
@@ -52,6 +54,8 @@
#define OMAP4_SFH7741_ENABLE_GPIO 188
#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define DISPLAY_SEL_GPIO 59 /* LCD2/PicoDLP switch */
+#define DLP_POWER_ON_GPIO 40
#define GPIO_WIFI_PMENA 54
#define GPIO_WIFI_IRQ 53
@@ -129,7 +133,7 @@ static const int sdp4430_keymap[] = {
KEY(7, 6, KEY_OK),
KEY(7, 7, KEY_DOWN),
};
-static struct omap_device_pad keypad_pads[] __initdata = {
+static struct omap_device_pad keypad_pads[] = {
{ .name = "kpd_col1.kpd_col1",
.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
},
@@ -340,11 +344,6 @@ static int __init omap_ethernet_init(void)
return status;
}
-static struct platform_device sdp4430_lcd_device = {
- .name = "sdp4430_lcd",
- .id = -1,
-};
-
static struct regulator_consumer_supply sdp4430_vbat_supply[] = {
REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"),
REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"),
@@ -374,27 +373,12 @@ static struct platform_device sdp4430_vbat = {
};
static struct platform_device *sdp4430_devices[] __initdata = {
- &sdp4430_lcd_device,
&sdp4430_gpio_keys_device,
&sdp4430_leds_gpio,
&sdp4430_leds_pwm,
&sdp4430_vbat,
};
-static struct omap_lcd_config sdp4430_lcd_config __initdata = {
- .ctrl_name = "internal",
-};
-
-static struct omap_board_config_kernel sdp4430_config[] __initdata = {
- { OMAP_TAG_LCD, &sdp4430_lcd_config },
-};
-
-static void __init omap_4430sdp_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
-
static struct omap_musb_board_data musb_board_data = {
.interface_type = MUSB_INTERFACE_UTMI,
.mode = MUSB_OTG,
@@ -648,37 +632,202 @@ static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
gpio_free(HDMI_GPIO_HPD);
}
-static struct omap_dss_device sdp4430_hdmi_device = {
- .name = "hdmi",
- .driver_name = "hdmi_panel",
- .type = OMAP_DISPLAY_TYPE_HDMI,
- .clocks = {
- .dispc = {
+static struct nokia_dsi_panel_data dsi1_panel = {
+ .name = "taal",
+ .reset_gpio = 102,
+ .use_ext_te = false,
+ .ext_te_gpio = 101,
+ .esd_interval = 0,
+};
+
+static struct omap_dss_device sdp4430_lcd_device = {
+ .name = "lcd",
+ .driver_name = "taal",
+ .type = OMAP_DISPLAY_TYPE_DSI,
+ .data = &dsi1_panel,
+ .phy.dsi = {
+ .clk_lane = 1,
+ .clk_pol = 0,
+ .data1_lane = 2,
+ .data1_pol = 0,
+ .data2_lane = 3,
+ .data2_pol = 0,
+
+ .module = 0,
+ },
+
+ .clocks = {
+ .dispc = {
+ .channel = {
+ /* Logic Clock = 172.8 MHz */
+ .lck_div = 1,
+ /* Pixel Clock = 34.56 MHz */
+ .pck_div = 5,
+ .lcd_clk_src = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,
+ },
+ .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
+ },
+
+ .dsi = {
+ .regn = 16, /* Fint = 2.4 MHz */
+ .regm = 180, /* DDR Clock = 216 MHz */
+ .regm_dispc = 5, /* PLL1_CLK1 = 172.8 MHz */
+ .regm_dsi = 5, /* PLL1_CLK2 = 172.8 MHz */
+
+ .lp_clk_div = 10, /* LP Clock = 8.64 MHz */
+ .dsi_fclk_src = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
+ },
+ },
+ .channel = OMAP_DSS_CHANNEL_LCD,
+};
+
+static struct nokia_dsi_panel_data dsi2_panel = {
+ .name = "taal",
+ .reset_gpio = 104,
+ .use_ext_te = false,
+ .ext_te_gpio = 103,
+ .esd_interval = 0,
+};
+
+static struct omap_dss_device sdp4430_lcd2_device = {
+ .name = "lcd2",
+ .driver_name = "taal",
+ .type = OMAP_DISPLAY_TYPE_DSI,
+ .data = &dsi2_panel,
+ .phy.dsi = {
+ .clk_lane = 1,
+ .clk_pol = 0,
+ .data1_lane = 2,
+ .data1_pol = 0,
+ .data2_lane = 3,
+ .data2_pol = 0,
+
+ .module = 1,
+ },
+
+ .clocks = {
+ .dispc = {
+ .channel = {
+ /* Logic Clock = 172.8 MHz */
+ .lck_div = 1,
+ /* Pixel Clock = 34.56 MHz */
+ .pck_div = 5,
+ .lcd_clk_src = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC,
+ },
.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
},
- .hdmi = {
- .regn = 15,
- .regm2 = 1,
+
+ .dsi = {
+ .regn = 16, /* Fint = 2.4 MHz */
+ .regm = 180, /* DDR Clock = 216 MHz */
+ .regm_dispc = 5, /* PLL1_CLK1 = 172.8 MHz */
+ .regm_dsi = 5, /* PLL1_CLK2 = 172.8 MHz */
+
+ .lp_clk_div = 10, /* LP Clock = 8.64 MHz */
+ .dsi_fclk_src = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI,
},
},
+ .channel = OMAP_DSS_CHANNEL_LCD2,
+};
+
+static void sdp4430_lcd_init(void)
+{
+ int r;
+
+ r = gpio_request_one(dsi1_panel.reset_gpio, GPIOF_DIR_OUT,
+ "lcd1_reset_gpio");
+ if (r)
+ pr_err("%s: Could not get lcd1_reset_gpio\n", __func__);
+
+ r = gpio_request_one(dsi2_panel.reset_gpio, GPIOF_DIR_OUT,
+ "lcd2_reset_gpio");
+ if (r)
+ pr_err("%s: Could not get lcd2_reset_gpio\n", __func__);
+}
+
+static struct omap_dss_device sdp4430_hdmi_device = {
+ .name = "hdmi",
+ .driver_name = "hdmi_panel",
+ .type = OMAP_DISPLAY_TYPE_HDMI,
.platform_enable = sdp4430_panel_enable_hdmi,
.platform_disable = sdp4430_panel_disable_hdmi,
.channel = OMAP_DSS_CHANNEL_DIGIT,
};
+static struct picodlp_panel_data sdp4430_picodlp_pdata = {
+ .picodlp_adapter_id = 2,
+ .emu_done_gpio = 44,
+ .pwrgood_gpio = 45,
+};
+
+static void sdp4430_picodlp_init(void)
+{
+ int r;
+ const struct gpio picodlp_gpios[] = {
+ {DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW,
+ "DLP POWER ON"},
+ {sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN,
+ "DLP EMU DONE"},
+ {sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW,
+ "DLP PWRGOOD"},
+ };
+
+ r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios));
+ if (r)
+ pr_err("Cannot request PicoDLP GPIOs, error %d\n", r);
+}
+
+static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev)
+{
+ gpio_set_value(DISPLAY_SEL_GPIO, 0);
+ gpio_set_value(DLP_POWER_ON_GPIO, 1);
+
+ return 0;
+}
+
+static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev)
+{
+ gpio_set_value(DLP_POWER_ON_GPIO, 0);
+ gpio_set_value(DISPLAY_SEL_GPIO, 1);
+}
+
+static struct omap_dss_device sdp4430_picodlp_device = {
+ .name = "picodlp",
+ .driver_name = "picodlp_panel",
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .phy.dpi.data_lines = 24,
+ .channel = OMAP_DSS_CHANNEL_LCD2,
+ .platform_enable = sdp4430_panel_enable_picodlp,
+ .platform_disable = sdp4430_panel_disable_picodlp,
+ .data = &sdp4430_picodlp_pdata,
+};
+
static struct omap_dss_device *sdp4430_dss_devices[] = {
+ &sdp4430_lcd_device,
+ &sdp4430_lcd2_device,
&sdp4430_hdmi_device,
+ &sdp4430_picodlp_device,
};
static struct omap_dss_board_info sdp4430_dss_data = {
.num_devices = ARRAY_SIZE(sdp4430_dss_devices),
.devices = sdp4430_dss_devices,
- .default_device = &sdp4430_hdmi_device,
+ .default_device = &sdp4430_lcd_device,
};
-void omap_4430sdp_display_init(void)
+static void omap_4430sdp_display_init(void)
{
+ int r;
+
+ /* Enable LCD2 by default (instead of Pico DLP) */
+ r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH,
+ "display_sel");
+ if (r)
+ pr_err("%s: Could not get display_sel GPIO\n", __func__);
+
+ sdp4430_lcd_init();
sdp4430_hdmi_mux_init();
+ sdp4430_picodlp_init();
omap_display_init(&sdp4430_dss_data);
}
@@ -802,13 +951,11 @@ static void __init omap_4430sdp_init(void)
package = OMAP_PACKAGE_CBL;
omap4_mux_init(board_mux, NULL, package);
- omap_board_config = sdp4430_config;
- omap_board_config_size = ARRAY_SIZE(sdp4430_config);
-
omap4_i2c_init();
omap_sfh7741prox_init();
platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
board_serial_init();
+ omap_sdrc_init(NULL, NULL);
omap4_sdp4430_wifi_init();
omap4_twl6030_hsmmc_init(mmc);
@@ -830,18 +977,12 @@ static void __init omap_4430sdp_init(void)
omap_4430sdp_display_init();
}
-static void __init omap_4430sdp_map_io(void)
-{
- omap2_set_globals_443x();
- omap44xx_map_common_io();
-}
-
MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
- .map_io = omap_4430sdp_map_io,
- .init_early = omap_4430sdp_init_early,
+ .map_io = omap4_map_io,
+ .init_early = omap4430_init_early,
.init_irq = gic_init_irq,
.init_machine = omap_4430sdp_init,
.timer = &omap4_timer,
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index 933e9353cb37..7834536ab416 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -47,12 +47,6 @@ static struct omap_board_mux board_mux[] __initdata = {
};
#endif
-static void __init am3517_crane_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
-
static struct usbhs_omap_board_data usbhs_bdata __initdata = {
.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -70,6 +64,7 @@ static void __init am3517_crane_init(void)
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap_serial_init();
+ omap_sdrc_init(NULL, NULL);
omap_board_config = am3517_crane_config;
omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
@@ -98,10 +93,10 @@ static void __init am3517_crane_init(void)
}
MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = am3517_crane_init_early,
+ .init_early = am35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = am3517_crane_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index f3006c304150..d314f033c9df 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -36,6 +36,7 @@
#include <plat/usb.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
#include "mux.h"
#include "control.h"
@@ -333,8 +334,7 @@ static void am3517_evm_panel_disable_dvi(struct omap_dss_device *dssdev)
dvi_enabled = 0;
}
-static struct panel_generic_dpi_data dvi_panel = {
- .name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
.platform_enable = am3517_evm_panel_enable_dvi,
.platform_disable = am3517_evm_panel_disable_dvi,
};
@@ -342,7 +342,7 @@ static struct panel_generic_dpi_data dvi_panel = {
static struct omap_dss_device am3517_evm_dvi_device = {
.type = OMAP_DISPLAY_TYPE_DPI,
.name = "dvi",
- .driver_name = "generic_dpi_panel",
+ .driver_name = "dvi",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -362,11 +362,6 @@ static struct omap_dss_board_info am3517_evm_dss_data = {
/*
* Board initialization
*/
-static void __init am3517_evm_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
static struct omap_musb_board_data musb_board_data = {
.interface_type = MUSB_INTERFACE_ULPI,
@@ -469,6 +464,7 @@ static void __init am3517_evm_init(void)
am3517_evm_i2c_init();
omap_display_init(&am3517_evm_dss_data);
omap_serial_init();
+ omap_sdrc_init(NULL, NULL);
/* Configure GPIO for EHCI port */
omap_mux_init_gpio(57, OMAP_PIN_OUTPUT);
@@ -490,10 +486,10 @@ static void __init am3517_evm_init(void)
}
MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = am3517_evm_init_early,
+ .init_early = am35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = am3517_evm_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 70211703ff9f..de8134b7f580 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -40,6 +40,9 @@
#include <plat/common.h>
#include <plat/gpmc.h>
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
#include "mux.h"
#include "control.h"
@@ -149,11 +152,6 @@ static struct platform_device apollon_smc91x_device = {
.resource = apollon_smc91x_resources,
};
-static struct platform_device apollon_lcd_device = {
- .name = "apollon_lcd",
- .id = -1,
-};
-
static struct omap_led_config apollon_led_config[] = {
{
.cdev = {
@@ -191,7 +189,6 @@ static struct platform_device apollon_led_device = {
static struct platform_device *apollon_devices[] __initdata = {
&apollon_onenand_device,
&apollon_smc91x_device,
- &apollon_lcd_device,
&apollon_led_device,
};
@@ -265,19 +262,27 @@ static struct omap_usb_config apollon_usb_config __initdata = {
.pins[0] = 6,
};
-static struct omap_lcd_config apollon_lcd_config __initdata = {
- .ctrl_name = "internal",
+static struct panel_generic_dpi_data apollon_panel_data = {
+ .name = "apollon",
};
-static struct omap_board_config_kernel apollon_config[] __initdata = {
- { OMAP_TAG_LCD, &apollon_lcd_config },
+static struct omap_dss_device apollon_lcd_device = {
+ .name = "lcd",
+ .driver_name = "generic_dpi_panel",
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .phy.dpi.data_lines = 18,
+ .data = &apollon_panel_data,
};
-static void __init omap_apollon_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
+static struct omap_dss_device *apollon_dss_devices[] = {
+ &apollon_lcd_device,
+};
+
+static struct omap_dss_board_info apollon_dss_data = {
+ .num_devices = ARRAY_SIZE(apollon_dss_devices),
+ .devices = apollon_dss_devices,
+ .default_device = &apollon_lcd_device,
+};
static struct gpio apollon_gpio_leds[] __initdata = {
{ LED0_GPIO13, GPIOF_OUT_INIT_LOW, "LED0" }, /* LED0 - AA10 */
@@ -314,8 +319,6 @@ static void __init omap_apollon_init(void)
u32 v;
omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
- omap_board_config = apollon_config;
- omap_board_config_size = ARRAY_SIZE(apollon_config);
apollon_init_smc91x();
apollon_led_init();
@@ -340,20 +343,16 @@ static void __init omap_apollon_init(void)
*/
platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
omap_serial_init();
-}
-
-static void __init omap_apollon_map_io(void)
-{
- omap2_set_globals_242x();
- omap242x_map_common_io();
+ omap_sdrc_init(NULL, NULL);
+ omap_display_init(&apollon_dss_data);
}
MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
- .map_io = omap_apollon_map_io,
- .init_early = omap_apollon_init_early,
+ .map_io = omap242x_map_io,
+ .init_early = omap2420_init_early,
.init_irq = omap2_init_irq,
.init_machine = omap_apollon_init,
.timer = &omap2_timer,
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 3af8aab435b5..bd1bcacb40f9 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -43,6 +43,7 @@
#include <plat/usb.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
#include <plat/mcspi.h>
#include <mach/hardware.h>
@@ -242,8 +243,7 @@ static struct omap_dss_device cm_t35_lcd_device = {
.phy.dpi.data_lines = 18,
};
-static struct panel_generic_dpi_data dvi_panel = {
- .name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
.platform_enable = cm_t35_panel_enable_dvi,
.platform_disable = cm_t35_panel_disable_dvi,
};
@@ -251,7 +251,7 @@ static struct panel_generic_dpi_data dvi_panel = {
static struct omap_dss_device cm_t35_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "generic_dpi_panel",
+ .driver_name = "dvi",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -471,13 +471,6 @@ static void __init cm_t35_init_i2c(void)
omap3_pmic_init("tps65930", &cm_t35_twldata);
}
-static void __init cm_t35_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
- mt46h32m32lf6_sdrc_params);
-}
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
/* nCS and IRQ for CM-T35 ethernet */
@@ -610,6 +603,8 @@ static void __init cm_t3x_common_init(void)
omap_board_config_size = ARRAY_SIZE(cm_t35_config);
omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
omap_serial_init();
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+ mt46h32m32lf6_sdrc_params);
cm_t35_init_i2c();
omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
cm_t35_init_ethernet();
@@ -634,20 +629,20 @@ static void __init cm_t3730_init(void)
}
MACHINE_START(CM_T35, "Compulab CM-T35")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = cm_t35_init_early,
+ .init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = cm_t35_init,
.timer = &omap3_timer,
MACHINE_END
MACHINE_START(CM_T3730, "Compulab CM-T3730")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = cm_t35_init_early,
+ .init_early = omap3630_init_early,
.init_irq = omap3_init_irq,
.init_machine = cm_t3730_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 05c72f4c1b57..3f4dc6626845 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -251,12 +251,6 @@ static inline void cm_t3517_init_nand(void) {}
static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
};
-static void __init cm_t3517_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
/* GPIO186 - Green LED */
@@ -289,6 +283,7 @@ static void __init cm_t3517_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap_serial_init();
+ omap_sdrc_init(NULL, NULL);
omap_board_config = cm_t3517_config;
omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
cm_t3517_init_leds();
@@ -299,10 +294,10 @@ static void __init cm_t3517_init(void)
}
MACHINE_START(CM_T3517, "Compulab CM-T3517")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = cm_t3517_init_early,
+ .init_early = am35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = cm_t3517_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index b6002ec31c6a..42918940c530 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -47,6 +47,7 @@
#include <plat/usb.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
#include <plat/mcspi.h>
#include <linux/input/matrix_keypad.h>
@@ -139,7 +140,7 @@ static struct regulator_consumer_supply devkit8000_vio_supply[] = {
};
static struct panel_generic_dpi_data lcd_panel = {
- .name = "generic",
+ .name = "innolux_at070tn83",
.platform_enable = devkit8000_panel_enable_lcd,
.platform_disable = devkit8000_panel_disable_lcd,
};
@@ -152,8 +153,7 @@ static struct omap_dss_device devkit8000_lcd_device = {
.phy.dpi.data_lines = 24,
};
-static struct panel_generic_dpi_data dvi_panel = {
- .name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
.platform_enable = devkit8000_panel_enable_dvi,
.platform_disable = devkit8000_panel_disable_dvi,
};
@@ -161,7 +161,7 @@ static struct panel_generic_dpi_data dvi_panel = {
static struct omap_dss_device devkit8000_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "generic_dpi_panel",
+ .driver_name = "dvi",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -267,7 +267,7 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = {
static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = {
REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
- REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
};
/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -397,19 +397,6 @@ static struct platform_device keys_gpio = {
},
};
-
-static void __init devkit8000_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
- mt46h32m32lf6_sdrc_params);
-}
-
-static void __init devkit8000_init_irq(void)
-{
- omap3_init_irq();
-}
-
#define OMAP_DM9000_BASE 0x2c000000
static struct resource omap_dm9000_resources[] = {
@@ -645,6 +632,8 @@ static void __init devkit8000_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
omap_serial_init();
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+ mt46h32m32lf6_sdrc_params);
omap_dm9000_init();
@@ -667,11 +656,11 @@ static void __init devkit8000_init(void)
}
MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = devkit8000_init_early,
- .init_irq = devkit8000_init_irq,
+ .init_early = omap35xx_init_early,
+ .init_irq = omap3_init_irq,
.init_machine = devkit8000_init,
.timer = &omap3_secure_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index aa1b0cbe19d2..30a6f527510c 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -148,11 +148,6 @@ __init board_nand_init(struct mtd_partition *nand_parts,
board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
gpmc_nand_init(&board_nand_data);
}
-#else
-void
-__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, int nand_type)
-{
-}
#endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
/**
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index c240a3f8d163..d25503a98417 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -24,7 +24,26 @@ struct flash_partitions {
int nr_parts;
};
+#if defined(CONFIG_MTD_NAND_OMAP2) || \
+ defined(CONFIG_MTD_NAND_OMAP2_MODULE) || \
+ defined(CONFIG_MTD_ONENAND_OMAP2) || \
+ defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
extern void board_flash_init(struct flash_partitions [],
char chip_sel[][GPMC_CS_NUM], int nand_type);
+#else
+static inline void board_flash_init(struct flash_partitions part[],
+ char chip_sel[][GPMC_CS_NUM], int nand_type)
+{
+}
+#endif
+
+#if defined(CONFIG_MTD_NAND_OMAP2) || \
+ defined(CONFIG_MTD_NAND_OMAP2_MODULE)
extern void board_nand_init(struct mtd_partition *nand_parts,
u8 nr_parts, u8 cs, int nand_type);
+#else
+static inline void board_nand_init(struct mtd_partition *nand_parts,
+ u8 nr_parts, u8 cs, int nand_type)
+{
+}
+#endif
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 54db41a84a9b..0cc9094e5ee0 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -1,76 +1,157 @@
/*
- * linux/arch/arm/mach-omap2/board-generic.c
- *
* Copyright (C) 2005 Nokia Corporation
* Author: Paul Mundt <paul.mundt@nokia.com>
*
- * Modified from mach-omap/omap1/board-generic.c
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
*
- * Code for generic OMAP2 board. Should work on many OMAP2 systems where
- * the bootloader passes the board-specific data to the kernel.
- * Do not put any board specific code to this file; create a new machine
- * type if you need custom low-level initializations.
+ * Modified from the original mach-omap/omap2/board-generic.c did by Paul
+ * to support the OMAP2+ device tree boards with an unique board 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 <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/irqdomain.h>
+#include <linux/i2c/twl.h>
#include <mach/hardware.h>
-#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/gpio.h>
-#include <plat/usb.h>
#include <plat/board.h>
#include <plat/common.h>
+#include <mach/omap4-common.h>
+#include "common-board-devices.h"
+
+/*
+ * XXX: Still needed to boot until the i2c & twl driver is adapted to
+ * device-tree
+ */
+static struct twl4030_platform_data sdp4430_twldata = {
+ .irq_base = TWL6030_IRQ_BASE,
+ .irq_end = TWL6030_IRQ_END,
+};
-static struct omap_board_config_kernel generic_config[] = {
+static void __init omap4_i2c_init(void)
+{
+ omap4_pmic_init("twl6030", &sdp4430_twldata);
+}
+
+static struct twl4030_platform_data beagle_twldata = {
+ .irq_base = TWL4030_IRQ_BASE,
+ .irq_end = TWL4030_IRQ_END,
};
-static void __init omap_generic_init_early(void)
+static void __init omap3_i2c_init(void)
{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
+ omap3_pmic_init("twl4030", &beagle_twldata);
}
+static struct of_device_id omap_dt_match_table[] __initdata = {
+ { .compatible = "simple-bus", },
+ { .compatible = "ti,omap-infra", },
+ { }
+};
+
+static struct of_device_id intc_match[] __initdata = {
+ { .compatible = "ti,omap3-intc", },
+ { .compatible = "arm,cortex-a9-gic", },
+ { }
+};
+
static void __init omap_generic_init(void)
{
+ struct device_node *node = of_find_matching_node(NULL, intc_match);
+ if (node)
+ irq_domain_add_simple(node, 0);
+
omap_serial_init();
- omap_board_config = generic_config;
- omap_board_config_size = ARRAY_SIZE(generic_config);
+ omap_sdrc_init(NULL, NULL);
+
+ of_platform_populate(NULL, omap_dt_match_table, NULL, NULL);
}
-static void __init omap_generic_map_io(void)
+static void __init omap4_init(void)
{
- if (cpu_is_omap242x()) {
- omap2_set_globals_242x();
- omap242x_map_common_io();
- } else if (cpu_is_omap243x()) {
- omap2_set_globals_243x();
- omap243x_map_common_io();
- } else if (cpu_is_omap34xx()) {
- omap2_set_globals_3xxx();
- omap34xx_map_common_io();
- } else if (cpu_is_omap44xx()) {
- omap2_set_globals_443x();
- omap44xx_map_common_io();
- }
+ omap4_i2c_init();
+ omap_generic_init();
}
-/* XXX This machine entry name should be updated */
-MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
- /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
- .boot_params = 0x80000100,
+static void __init omap3_init(void)
+{
+ omap3_i2c_init();
+ omap_generic_init();
+}
+
+#if defined(CONFIG_SOC_OMAP2420)
+static const char *omap242x_boards_compat[] __initdata = {
+ "ti,omap2420",
+ NULL,
+};
+
+DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
+ .atag_offset = 0x100,
+ .reserve = omap_reserve,
+ .map_io = omap242x_map_io,
+ .init_early = omap2420_init_early,
+ .init_irq = omap2_init_irq,
+ .init_machine = omap_generic_init,
+ .timer = &omap2_timer,
+ .dt_compat = omap242x_boards_compat,
+MACHINE_END
+#endif
+
+#if defined(CONFIG_SOC_OMAP2430)
+static const char *omap243x_boards_compat[] __initdata = {
+ "ti,omap2430",
+ NULL,
+};
+
+DT_MACHINE_START(OMAP243X_DT, "Generic OMAP2430 (Flattened Device Tree)")
+ .atag_offset = 0x100,
.reserve = omap_reserve,
- .map_io = omap_generic_map_io,
- .init_early = omap_generic_init_early,
+ .map_io = omap243x_map_io,
+ .init_early = omap2430_init_early,
.init_irq = omap2_init_irq,
.init_machine = omap_generic_init,
.timer = &omap2_timer,
+ .dt_compat = omap243x_boards_compat,
+MACHINE_END
+#endif
+
+#if defined(CONFIG_ARCH_OMAP3)
+static const char *omap3_boards_compat[] __initdata = {
+ "ti,omap3",
+ NULL,
+};
+
+DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
+ .atag_offset = 0x100,
+ .reserve = omap_reserve,
+ .map_io = omap3_map_io,
+ .init_early = omap3430_init_early,
+ .init_irq = omap3_init_irq,
+ .init_machine = omap3_init,
+ .timer = &omap3_timer,
+ .dt_compat = omap3_boards_compat,
+MACHINE_END
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+static const char *omap4_boards_compat[] __initdata = {
+ "ti,omap4",
+ NULL,
+};
+
+DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
+ .atag_offset = 0x100,
+ .reserve = omap_reserve,
+ .map_io = omap4_map_io,
+ .init_early = omap4430_init_early,
+ .init_irq = gic_init_irq,
+ .init_machine = omap4_init,
+ .timer = &omap4_timer,
+ .dt_compat = omap4_boards_compat,
MACHINE_END
+#endif
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 45de2b319ec9..c12666ee7017 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -10,7 +10,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -31,7 +31,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <plat/usb.h>
#include <plat/board.h>
#include <plat/common.h>
@@ -40,6 +39,9 @@
#include <plat/dma.h>
#include <plat/gpmc.h>
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
#include "mux.h"
#include "control.h"
@@ -157,17 +159,33 @@ static struct platform_device h4_kp_device = {
},
};
-static struct platform_device h4_lcd_device = {
- .name = "lcd_h4",
- .id = -1,
-};
-
static struct platform_device *h4_devices[] __initdata = {
&h4_flash_device,
&h4_kp_device,
+};
+
+static struct panel_generic_dpi_data h4_panel_data = {
+ .name = "h4",
+};
+
+static struct omap_dss_device h4_lcd_device = {
+ .name = "lcd",
+ .driver_name = "generic_dpi_panel",
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .phy.dpi.data_lines = 16,
+ .data = &h4_panel_data,
+};
+
+static struct omap_dss_device *h4_dss_devices[] = {
&h4_lcd_device,
};
+static struct omap_dss_board_info h4_dss_data = {
+ .num_devices = ARRAY_SIZE(h4_dss_devices),
+ .devices = h4_dss_devices,
+ .default_device = &h4_lcd_device,
+};
+
/* 2420 Sysboot setup (2430 is different) */
static u32 get_sysboot_value(void)
{
@@ -271,10 +289,6 @@ static void __init h4_init_flash(void)
h4_flash_resource.end = base + SZ_64M - 1;
}
-static struct omap_lcd_config h4_lcd_config __initdata = {
- .ctrl_name = "internal",
-};
-
static struct omap_usb_config h4_usb_config __initdata = {
/* S1.10 OFF -- usb "download port"
* usb0 switched to Mini-B port and isp1105 transceiver;
@@ -286,21 +300,6 @@ static struct omap_usb_config h4_usb_config __initdata = {
.hmc_mode = 0x00, /* 0:dev|otg 1:disable 2:disable */
};
-static struct omap_board_config_kernel h4_config[] __initdata = {
- { OMAP_TAG_LCD, &h4_lcd_config },
-};
-
-static void __init omap_h4_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
-
-static void __init omap_h4_init_irq(void)
-{
- omap2_init_irq();
-}
-
static struct at24_platform_data m24c01 = {
.byte_len = SZ_1K / 8,
.page_size = 16,
@@ -331,9 +330,6 @@ static void __init omap_h4_init(void)
{
omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAF);
- omap_board_config = h4_config;
- omap_board_config_size = ARRAY_SIZE(h4_config);
-
/*
* Make sure the serial ports are muxed on at this point.
* You have to mux them off in device drivers later on
@@ -371,22 +367,19 @@ static void __init omap_h4_init(void)
platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
omap2_usbfs_init(&h4_usb_config);
omap_serial_init();
+ omap_sdrc_init(NULL, NULL);
h4_init_flash();
-}
-static void __init omap_h4_map_io(void)
-{
- omap2_set_globals_242x();
- omap242x_map_common_io();
+ omap_display_init(&h4_dss_data);
}
MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
- .map_io = omap_h4_map_io,
- .init_early = omap_h4_init_early,
- .init_irq = omap_h4_init_irq,
+ .map_io = omap242x_map_io,
+ .init_early = omap2420_init_early,
+ .init_irq = omap2_init_irq,
.init_machine = omap_h4_init,
.timer = &omap2_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 35be778caf1b..d0a3f78a9b69 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -32,7 +32,7 @@
#include <plat/gpmc.h>
#include <plat/usb.h>
#include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
#include <plat/onenand.h>
#include "mux.h"
@@ -455,16 +455,16 @@ static void igep2_disable_dvi(struct omap_dss_device *dssdev)
gpio_direction_output(IGEP2_GPIO_DVI_PUP, 0);
}
-static struct panel_generic_dpi_data dvi_panel = {
- .name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
.platform_enable = igep2_enable_dvi,
.platform_disable = igep2_disable_dvi,
+ .i2c_bus_num = 3,
};
static struct omap_dss_device igep2_dvi_device = {
.type = OMAP_DISPLAY_TYPE_DPI,
.name = "dvi",
- .driver_name = "generic_dpi_panel",
+ .driver_name = "dvi",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -491,13 +491,6 @@ static struct platform_device *igep_devices[] __initdata = {
&igep_vwlan_device,
};
-static void __init igep_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(m65kxxxxam_sdrc_params,
- m65kxxxxam_sdrc_params);
-}
-
static int igep2_keymap[] = {
KEY(0, 0, KEY_LEFT),
KEY(0, 1, KEY_RIGHT),
@@ -650,6 +643,8 @@ static void __init igep_init(void)
igep_i2c_init();
platform_add_devices(igep_devices, ARRAY_SIZE(igep_devices));
omap_serial_init();
+ omap_sdrc_init(m65kxxxxam_sdrc_params,
+ m65kxxxxam_sdrc_params);
usb_musb_init(NULL);
igep_flash_init();
@@ -672,20 +667,20 @@ static void __init igep_init(void)
}
MACHINE_START(IGEP0020, "IGEP v2 board")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = igep_init_early,
+ .init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = igep_init,
.timer = &omap3_timer,
MACHINE_END
MACHINE_START(IGEP0030, "IGEP OMAP3 module")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = igep_init_early,
+ .init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = igep_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 218764c9377e..e179da0c4da5 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -10,7 +10,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -27,6 +27,7 @@
#include <linux/io.h>
#include <linux/smsc911x.h>
#include <linux/mmc/host.h>
+#include <linux/gpio.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -34,7 +35,6 @@
#include <asm/mach/map.h>
#include <plat/mcspi.h>
-#include <mach/gpio.h>
#include <plat/board.h>
#include <plat/common.h>
#include <plat/gpmc.h>
@@ -44,6 +44,9 @@
#include <plat/usb.h>
#include <plat/gpmc-smsc911x.h>
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
#include "board-flash.h"
#include "mux.h"
#include "hsmmc.h"
@@ -180,29 +183,102 @@ static inline void __init ldp_init_smsc911x(void)
gpmc_smsc911x_init(&smsc911x_cfg);
}
-static struct platform_device ldp_lcd_device = {
- .name = "ldp_lcd",
- .id = -1,
+/* LCD */
+
+static int ldp_backlight_gpio;
+static int ldp_lcd_enable_gpio;
+
+#define LCD_PANEL_RESET_GPIO 55
+#define LCD_PANEL_QVGA_GPIO 56
+
+static int ldp_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+ if (gpio_is_valid(ldp_lcd_enable_gpio))
+ gpio_direction_output(ldp_lcd_enable_gpio, 1);
+ if (gpio_is_valid(ldp_backlight_gpio))
+ gpio_direction_output(ldp_backlight_gpio, 1);
+
+ return 0;
+}
+
+static void ldp_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+ if (gpio_is_valid(ldp_lcd_enable_gpio))
+ gpio_direction_output(ldp_lcd_enable_gpio, 0);
+ if (gpio_is_valid(ldp_backlight_gpio))
+ gpio_direction_output(ldp_backlight_gpio, 0);
+}
+
+static struct panel_generic_dpi_data ldp_panel_data = {
+ .name = "nec_nl2432dr22-11b",
+ .platform_enable = ldp_panel_enable_lcd,
+ .platform_disable = ldp_panel_disable_lcd,
+};
+
+static struct omap_dss_device ldp_lcd_device = {
+ .name = "lcd",
+ .driver_name = "generic_dpi_panel",
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .phy.dpi.data_lines = 18,
+ .data = &ldp_panel_data,
};
-static struct omap_lcd_config ldp_lcd_config __initdata = {
- .ctrl_name = "internal",
+static struct omap_dss_device *ldp_dss_devices[] = {
+ &ldp_lcd_device,
};
-static struct omap_board_config_kernel ldp_config[] __initdata = {
- { OMAP_TAG_LCD, &ldp_lcd_config },
+static struct omap_dss_board_info ldp_dss_data = {
+ .num_devices = ARRAY_SIZE(ldp_dss_devices),
+ .devices = ldp_dss_devices,
+ .default_device = &ldp_lcd_device,
};
-static void __init omap_ldp_init_early(void)
+static void __init ldp_display_init(void)
+{
+ int r;
+
+ static struct gpio gpios[] __initdata = {
+ {LCD_PANEL_RESET_GPIO, GPIOF_OUT_INIT_HIGH, "LCD RESET"},
+ {LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "LCD QVGA"},
+ };
+
+ r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+ if (r) {
+ pr_err("Cannot request LCD GPIOs, error %d\n", r);
+ return;
+ }
+
+ omap_display_init(&ldp_dss_data);
+}
+
+static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
+ int r;
+
+ struct gpio gpios[] = {
+ {gpio + 7 , GPIOF_OUT_INIT_LOW, "LCD ENABLE"},
+ {gpio + 15, GPIOF_OUT_INIT_LOW, "LCD BACKLIGHT"},
+ };
+
+ r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+ if (r) {
+ pr_err("Cannot request LCD GPIOs, error %d\n", r);
+ ldp_backlight_gpio = -EINVAL;
+ ldp_lcd_enable_gpio = -EINVAL;
+ return r;
+ }
+
+ ldp_backlight_gpio = gpio + 15;
+ ldp_lcd_enable_gpio = gpio + 7;
+
+ return 0;
}
static struct twl4030_gpio_platform_data ldp_gpio_data = {
.gpio_base = OMAP_MAX_GPIO_LINES,
.irq_base = TWL4030_GPIO_IRQ_BASE,
.irq_end = TWL4030_GPIO_IRQ_END,
+ .setup = ldp_twl_gpio_setup,
};
static struct regulator_consumer_supply ldp_vmmc1_supply[] = {
@@ -244,10 +320,31 @@ static struct regulator_init_data ldp_vaux1 = {
.consumer_supplies = ldp_vaux1_supplies,
};
+static struct regulator_consumer_supply ldp_vpll2_supplies[] = {
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
+
+static struct regulator_init_data ldp_vpll2 = {
+ .constraints = {
+ .name = "VDVI",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = true,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldp_vpll2_supplies),
+ .consumer_supplies = ldp_vpll2_supplies,
+};
+
static struct twl4030_platform_data ldp_twldata = {
/* platform_data for children goes here */
.vmmc1 = &ldp_vmmc1,
.vaux1 = &ldp_vaux1,
+ .vpll2 = &ldp_vpll2,
.gpio = &ldp_gpio_data,
.keypad = &ldp_kp_twl4030_data,
};
@@ -273,7 +370,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
};
static struct platform_device *ldp_devices[] __initdata = {
- &ldp_lcd_device,
&ldp_gpio_keys_device,
};
@@ -318,25 +414,25 @@ static struct mtd_partition ldp_nand_partitions[] = {
static void __init omap_ldp_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
- omap_board_config = ldp_config;
- omap_board_config_size = ARRAY_SIZE(ldp_config);
ldp_init_smsc911x();
omap_i2c_init();
platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices));
omap_ads7846_init(1, 54, 310, NULL);
omap_serial_init();
+ omap_sdrc_init(NULL, NULL);
usb_musb_init(NULL);
board_nand_init(ldp_nand_partitions,
ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
omap2_hsmmc_init(mmc);
+ ldp_display_init();
}
MACHINE_START(OMAP_LDP, "OMAP LDP board")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = omap_ldp_init_early,
+ .init_early = omap3430_init_early,
.init_irq = omap3_init_irq,
.init_machine = omap_ldp_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index e11f0c5d608a..e9d5f4a3d064 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -616,18 +616,6 @@ static struct i2c_board_info n810_i2c_board_info_2[] __initdata = {
},
};
-static void __init n8x0_map_io(void)
-{
- omap2_set_globals_242x();
- omap242x_map_common_io();
-}
-
-static void __init n8x0_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
/* I2S codec port pins for McBSP block */
@@ -689,36 +677,37 @@ static void __init n8x0_init_machine(void)
i2c_register_board_info(2, n810_i2c_board_info_2,
ARRAY_SIZE(n810_i2c_board_info_2));
board_serial_init();
+ omap_sdrc_init(NULL, NULL);
gpmc_onenand_init(board_onenand_data);
n8x0_mmc_init();
n8x0_usb_init();
}
MACHINE_START(NOKIA_N800, "Nokia N800")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
- .map_io = n8x0_map_io,
- .init_early = n8x0_init_early,
+ .map_io = omap242x_map_io,
+ .init_early = omap2420_init_early,
.init_irq = omap2_init_irq,
.init_machine = n8x0_init_machine,
.timer = &omap2_timer,
MACHINE_END
MACHINE_START(NOKIA_N810, "Nokia N810")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
- .map_io = n8x0_map_io,
- .init_early = n8x0_init_early,
+ .map_io = omap242x_map_io,
+ .init_early = omap2420_init_early,
.init_irq = omap2_init_irq,
.init_machine = n8x0_init_machine,
.timer = &omap2_timer,
MACHINE_END
MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
- .map_io = n8x0_map_io,
- .init_early = n8x0_init_early,
+ .map_io = omap242x_map_io,
+ .init_early = omap2420_init_early,
.init_irq = omap2_init_irq,
.init_machine = n8x0_init_machine,
.timer = &omap2_timer,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 9cc9fa9315d4..4a71cb7e42d4 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -42,7 +42,7 @@
#include <plat/board.h>
#include <plat/common.h>
#include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
#include <plat/gpmc.h>
#include <plat/nand.h>
#include <plat/usb.h>
@@ -203,16 +203,16 @@ static void beagle_disable_dvi(struct omap_dss_device *dssdev)
gpio_set_value(dssdev->reset_gpio, 0);
}
-static struct panel_generic_dpi_data dvi_panel = {
- .name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
.platform_enable = beagle_enable_dvi,
.platform_disable = beagle_disable_dvi,
+ .i2c_bus_num = 3,
};
static struct omap_dss_device beagle_dvi_device = {
.type = OMAP_DISPLAY_TYPE_DPI,
.name = "dvi",
- .driver_name = "generic_dpi_panel",
+ .driver_name = "dvi",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
.reset_gpio = -EINVAL,
@@ -445,18 +445,6 @@ static struct platform_device keys_gpio = {
},
};
-static void __init omap3_beagle_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
- mt46h32m32lf6_sdrc_params);
-}
-
-static void __init omap3_beagle_init_irq(void)
-{
- omap3_init_irq();
-}
-
static struct platform_device madc_hwmon = {
.name = "twl4030_madc_hwmon",
.id = -1,
@@ -500,8 +488,8 @@ static void __init beagle_opp_init(void)
if (cpu_is_omap3630()) {
struct device *mpu_dev, *iva_dev;
- mpu_dev = omap2_get_mpuss_device();
- iva_dev = omap2_get_iva_device();
+ mpu_dev = omap_device_get_by_hwmod_name("mpu");
+ iva_dev = omap_device_get_by_hwmod_name("iva");
if (!mpu_dev || !iva_dev) {
pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
@@ -541,6 +529,8 @@ static void __init omap3_beagle_init(void)
ARRAY_SIZE(omap3_beagle_devices));
omap_display_init(&beagle_dss_data);
omap_serial_init();
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+ mt46h32m32lf6_sdrc_params);
omap_mux_init_gpio(170, OMAP_PIN_INPUT);
/* REVISIT leave DVI powered down until it's needed ... */
@@ -564,11 +554,11 @@ static void __init omap3_beagle_init(void)
MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = omap3_beagle_init_early,
- .init_irq = omap3_beagle_init_irq,
+ .init_early = omap3_init_early,
+ .init_irq = omap3_init_irq,
.init_machine = omap3_beagle_init,
.timer = &omap3_secure_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index c452b3f3331a..2d24e287e8c1 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -45,7 +45,7 @@
#include <plat/common.h>
#include <plat/mcspi.h>
#include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
#include "mux.h"
#include "sdram-micron-mt46h32m32lf-6.h"
@@ -247,8 +247,7 @@ static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev)
dvi_enabled = 0;
}
-static struct panel_generic_dpi_data dvi_panel = {
- .name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
.platform_enable = omap3_evm_enable_dvi,
.platform_disable = omap3_evm_disable_dvi,
};
@@ -256,7 +255,7 @@ static struct panel_generic_dpi_data dvi_panel = {
static struct omap_dss_device omap3_evm_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "generic_dpi_panel",
+ .driver_name = "dvi",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -520,12 +519,6 @@ static int __init omap3_evm_i2c_init(void)
static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
};
-static void __init omap3_evm_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
-}
-
static struct usbhs_omap_board_data usbhs_bdata __initdata = {
.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -640,6 +633,7 @@ static void __init omap3_evm_init(void)
omap_display_init(&omap3_evm_dss_data);
omap_serial_init();
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
/* OMAP3EVM uses ISP1504 phy and so register nop transceiver */
usb_nop_xceiv_register();
@@ -681,10 +675,10 @@ static void __init omap3_evm_init(void)
MACHINE_START(OMAP3EVM, "OMAP3 EVM")
/* Maintainer: Syed Mohammed Khasim - Texas Instruments */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = omap3_evm_init_early,
+ .init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = omap3_evm_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 703aeb5b8fd4..7c0f193f246d 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -182,12 +182,6 @@ static inline void __init board_smsc911x_init(void)
gpmc_smsc911x_init(&board_smsc911x_data);
}
-static void __init omap3logic_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -200,6 +194,7 @@ static void __init omap3logic_init(void)
omap3torpedo_fix_pbias_voltage();
omap3logic_i2c_init();
omap_serial_init();
+ omap_sdrc_init(NULL, NULL);
board_mmc_init();
board_smsc911x_init();
@@ -209,18 +204,18 @@ static void __init omap3logic_init(void)
}
MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.map_io = omap3_map_io,
- .init_early = omap3logic_init_early,
+ .init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = omap3logic_init,
.timer = &omap3_timer,
MACHINE_END
MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.map_io = omap3_map_io,
- .init_early = omap3logic_init_early,
+ .init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = omap3logic_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 080d7bd6795e..f7811f4cfc3d 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -335,7 +335,7 @@ static struct regulator_consumer_supply pandora_vmmc3_supply[] = {
static struct regulator_consumer_supply pandora_vdds_supplies[] = {
REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
- REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
};
static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = {
@@ -525,13 +525,6 @@ static struct spi_board_info omap3pandora_spi_board_info[] __initdata = {
}
};
-static void __init omap3pandora_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
- mt46h32m32lf6_sdrc_params);
-}
-
static void __init pandora_wl1251_init(void)
{
struct wl12xx_platform_data pandora_wl1251_pdata;
@@ -593,6 +586,8 @@ static void __init omap3pandora_init(void)
ARRAY_SIZE(omap3pandora_devices));
omap_display_init(&pandora_dss_data);
omap_serial_init();
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+ mt46h32m32lf6_sdrc_params);
spi_register_board_info(omap3pandora_spi_board_info,
ARRAY_SIZE(omap3pandora_spi_board_info));
omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
@@ -606,10 +601,10 @@ static void __init omap3pandora_init(void)
}
MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = omap3pandora_init_early,
+ .init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = omap3pandora_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 8e104980ea26..ddb7d6663c6d 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -41,6 +41,7 @@
#include <plat/usb.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
#include <plat/mcspi.h>
#include <linux/input/matrix_keypad.h>
@@ -107,39 +108,6 @@ static void __init omap3_stalker_display_init(void)
return;
}
-static int omap3_stalker_enable_lcd(struct omap_dss_device *dssdev)
-{
- if (dvi_enabled) {
- printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
- return -EINVAL;
- }
- gpio_set_value(DSS_ENABLE_GPIO, 1);
- gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 1);
- lcd_enabled = 1;
- return 0;
-}
-
-static void omap3_stalker_disable_lcd(struct omap_dss_device *dssdev)
-{
- gpio_set_value(DSS_ENABLE_GPIO, 0);
- gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 0);
- lcd_enabled = 0;
-}
-
-static struct panel_generic_dpi_data lcd_panel = {
- .name = "generic",
- .platform_enable = omap3_stalker_enable_lcd,
- .platform_disable = omap3_stalker_disable_lcd,
-};
-
-static struct omap_dss_device omap3_stalker_lcd_device = {
- .name = "lcd",
- .driver_name = "generic_dpi_panel",
- .data = &lcd_panel,
- .phy.dpi.data_lines = 24,
- .type = OMAP_DISPLAY_TYPE_DPI,
-};
-
static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev)
{
return 0;
@@ -179,8 +147,7 @@ static void omap3_stalker_disable_dvi(struct omap_dss_device *dssdev)
dvi_enabled = 0;
}
-static struct panel_generic_dpi_data dvi_panel = {
- .name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
.platform_enable = omap3_stalker_enable_dvi,
.platform_disable = omap3_stalker_disable_dvi,
};
@@ -188,13 +155,12 @@ static struct panel_generic_dpi_data dvi_panel = {
static struct omap_dss_device omap3_stalker_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "generic_dpi_panel",
+ .driver_name = "dvi",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
static struct omap_dss_device *omap3_stalker_dss_devices[] = {
- &omap3_stalker_lcd_device,
&omap3_stalker_tv_device,
&omap3_stalker_dvi_device,
};
@@ -428,17 +394,6 @@ static int __init omap3_stalker_i2c_init(void)
static struct omap_board_config_kernel omap3_stalker_config[] __initdata = {
};
-static void __init omap3_stalker_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
-}
-
-static void __init omap3_stalker_init_irq(void)
-{
- omap3_init_irq();
-}
-
static struct platform_device *omap3_stalker_devices[] __initdata = {
&keys_gpio,
};
@@ -478,6 +433,7 @@ static void __init omap3_stalker_init(void)
omap_display_init(&omap3_stalker_dss_data);
omap_serial_init();
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
usb_musb_init(NULL);
usbhs_init(&usbhs_bdata);
omap_ads7846_init(1, OMAP3_STALKER_TS_GPIO, 310, NULL);
@@ -494,10 +450,10 @@ static void __init omap3_stalker_init(void)
MACHINE_START(SBC3530, "OMAP3 STALKER")
/* Maintainer: Jason Lam -lzg@ema-tech.com */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.map_io = omap3_map_io,
- .init_early = omap3_stalker_init_early,
- .init_irq = omap3_stalker_init_irq,
+ .init_early = omap35xx_init_early,
+ .init_irq = omap3_init_irq,
.init_machine = omap3_stalker_init,
.timer = &omap3_secure_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 852ea0464057..a2d0d1971e27 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -104,15 +104,6 @@ static struct omap2_hsmmc_info mmc[] = {
{} /* Terminator */
};
-static struct platform_device omap3_touchbook_lcd_device = {
- .name = "omap3touchbook_lcd",
- .id = -1,
-};
-
-static struct omap_lcd_config omap3_touchbook_lcd_config __initdata = {
- .ctrl_name = "internal",
-};
-
static struct regulator_consumer_supply touchbook_vmmc1_supply[] = {
REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
};
@@ -165,14 +156,12 @@ static struct twl4030_gpio_platform_data touchbook_gpio_data = {
static struct regulator_consumer_supply touchbook_vdac_supply[] = {
{
.supply = "vdac",
- .dev = &omap3_touchbook_lcd_device.dev,
},
};
static struct regulator_consumer_supply touchbook_vdvi_supply[] = {
{
.supply = "vdvi",
- .dev = &omap3_touchbook_lcd_device.dev,
},
};
@@ -316,30 +305,13 @@ static struct platform_device keys_gpio = {
},
};
-static struct omap_board_config_kernel omap3_touchbook_config[] __initdata = {
- { OMAP_TAG_LCD, &omap3_touchbook_lcd_config },
-};
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
#endif
-static void __init omap3_touchbook_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
- mt46h32m32lf6_sdrc_params);
-}
-
-static void __init omap3_touchbook_init_irq(void)
-{
- omap3_init_irq();
-}
-
static struct platform_device *omap3_touchbook_devices[] __initdata = {
- &omap3_touchbook_lcd_device,
&leds_gpio,
&keys_gpio,
};
@@ -376,8 +348,6 @@ early_param("tbr", early_touchbook_revision);
static void __init omap3_touchbook_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
- omap_board_config = omap3_touchbook_config;
- omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config);
pm_power_off = omap3_touchbook_poweroff;
@@ -385,6 +355,8 @@ static void __init omap3_touchbook_init(void)
platform_add_devices(omap3_touchbook_devices,
ARRAY_SIZE(omap3_touchbook_devices));
omap_serial_init();
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+ mt46h32m32lf6_sdrc_params);
omap_mux_init_gpio(170, OMAP_PIN_INPUT);
/* REVISIT leave DVI powered down until it's needed ... */
@@ -404,11 +376,11 @@ static void __init omap3_touchbook_init(void)
MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
/* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = omap3_touchbook_init_early,
- .init_irq = omap3_touchbook_init_irq,
+ .init_early = omap3430_init_early,
+ .init_irq = omap3_init_irq,
.init_machine = omap3_touchbook_init,
.timer = &omap3_secure_timer,
MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 9aaa96057666..a8c2c4263e38 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -40,7 +40,7 @@
#include <plat/common.h>
#include <plat/usb.h>
#include <plat/mmc.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
#include "hsmmc.h"
#include "control.h"
@@ -95,12 +95,6 @@ static struct platform_device *panda_devices[] __initdata = {
&wl1271_device,
};
-static void __init omap4_panda_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
-
static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -455,16 +449,16 @@ static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev)
}
/* Using generic display panel */
-static struct panel_generic_dpi_data omap4_dvi_panel = {
- .name = "generic",
+static struct panel_dvi_platform_data omap4_dvi_panel = {
.platform_enable = omap4_panda_enable_dvi,
.platform_disable = omap4_panda_disable_dvi,
+ .i2c_bus_num = 3,
};
struct omap_dss_device omap4_panda_dvi_device = {
.type = OMAP_DISPLAY_TYPE_DPI,
.name = "dvi",
- .driver_name = "generic_dpi_panel",
+ .driver_name = "dvi",
.data = &omap4_dvi_panel,
.phy.dpi.data_lines = 24,
.reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO,
@@ -569,24 +563,19 @@ static void __init omap4_panda_init(void)
platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
platform_device_register(&omap_vwlan_device);
board_serial_init();
+ omap_sdrc_init(NULL, NULL);
omap4_twl6030_hsmmc_init(mmc);
omap4_ehci_init();
usb_musb_init(&musb_board_data);
omap4_panda_display_init();
}
-static void __init omap4_panda_map_io(void)
-{
- omap2_set_globals_443x();
- omap44xx_map_common_io();
-}
-
MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
/* Maintainer: David Anders - Texas Instruments Inc */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
- .map_io = omap4_panda_map_io,
- .init_early = omap4_panda_init_early,
+ .map_io = omap4_map_io,
+ .init_early = omap4430_init_early,
.init_irq = gic_init_irq,
.init_machine = omap4_panda_init,
.timer = &omap4_timer,
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index f949a9954d76..4cf7aeabab86 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -46,6 +46,7 @@
#include <plat/common.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
#include <plat/gpmc.h>
#include <mach/hardware.h>
#include <plat/nand.h>
@@ -182,16 +183,16 @@ static void overo_panel_disable_dvi(struct omap_dss_device *dssdev)
dvi_enabled = 0;
}
-static struct panel_generic_dpi_data dvi_panel = {
- .name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
.platform_enable = overo_panel_enable_dvi,
.platform_disable = overo_panel_disable_dvi,
+ .i2c_bus_num = 3,
};
static struct omap_dss_device overo_dvi_device = {
.name = "dvi",
.type = OMAP_DISPLAY_TYPE_DPI,
- .driver_name = "generic_dpi_panel",
+ .driver_name = "dvi",
.data = &dvi_panel,
.phy.dpi.data_lines = 24,
};
@@ -478,13 +479,6 @@ static int __init overo_spi_init(void)
return 0;
}
-static void __init overo_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
- mt46h32m32lf6_sdrc_params);
-}
-
static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
@@ -514,6 +508,8 @@ static void __init overo_init(void)
overo_i2c_init();
omap_display_init(&overo_dss_data);
omap_serial_init();
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+ mt46h32m32lf6_sdrc_params);
omap_nand_flash_init(0, overo_nand_partitions,
ARRAY_SIZE(overo_nand_partitions));
usb_musb_init(NULL);
@@ -561,10 +557,10 @@ static void __init overo_init(void)
}
MACHINE_START(OVERO, "Gumstix Overo")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = overo_init_early,
+ .init_early = omap35xx_init_early,
.init_irq = omap3_init_irq,
.init_machine = overo_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 7dfed24ee12e..616fb39763b0 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -123,15 +123,6 @@ static void __init rm680_peripherals_init(void)
omap2_hsmmc_init(mmc);
}
-static void __init rm680_init_early(void)
-{
- struct omap_sdrc_params *sdrc_params;
-
- omap2_init_common_infrastructure();
- sdrc_params = nokia_get_sdram_timings();
- omap2_init_common_devices(sdrc_params, sdrc_params);
-}
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -140,23 +131,23 @@ static struct omap_board_mux board_mux[] __initdata = {
static void __init rm680_init(void)
{
+ struct omap_sdrc_params *sdrc_params;
+
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap_serial_init();
+
+ sdrc_params = nokia_get_sdram_timings();
+ omap_sdrc_init(sdrc_params, sdrc_params);
+
usb_musb_init(NULL);
rm680_peripherals_init();
}
-static void __init rm680_map_io(void)
-{
- omap2_set_globals_3xxx();
- omap34xx_map_common_io();
-}
-
MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
- .map_io = rm680_map_io,
- .init_early = rm680_init_early,
+ .map_io = omap3_map_io,
+ .init_early = omap3630_init_early,
.init_irq = omap3_init_irq,
.init_machine = rm680_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 5a886cd2c598..ba1aa07bdb29 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -900,7 +900,6 @@ static struct twl4030_platform_data rx51_twldata __initdata = {
};
static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata_or_module = {
- .id = TPA6130A2,
.power_gpio = 98,
};
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 5ea142f9bc97..4af7c4b2881a 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -79,38 +79,6 @@ static struct cpuidle_params rx51_cpuidle_params[] = {
{7505 + 15274, 484329, 1},
};
-static struct omap_lcd_config rx51_lcd_config = {
- .ctrl_name = "internal",
-};
-
-static struct omap_fbmem_config rx51_fbmem0_config = {
- .size = 752 * 1024,
-};
-
-static struct omap_fbmem_config rx51_fbmem1_config = {
- .size = 752 * 1024,
-};
-
-static struct omap_fbmem_config rx51_fbmem2_config = {
- .size = 752 * 1024,
-};
-
-static struct omap_board_config_kernel rx51_config[] = {
- { OMAP_TAG_FBMEM, &rx51_fbmem0_config },
- { OMAP_TAG_FBMEM, &rx51_fbmem1_config },
- { OMAP_TAG_FBMEM, &rx51_fbmem2_config },
- { OMAP_TAG_LCD, &rx51_lcd_config },
-};
-
-static void __init rx51_init_early(void)
-{
- struct omap_sdrc_params *sdrc_params;
-
- omap2_init_common_infrastructure();
- sdrc_params = nokia_get_sdram_timings();
- omap2_init_common_devices(sdrc_params, sdrc_params);
-}
-
extern void __init rx51_peripherals_init(void);
#ifdef CONFIG_OMAP_MUX
@@ -127,11 +95,15 @@ static struct omap_musb_board_data musb_board_data = {
static void __init rx51_init(void)
{
+ struct omap_sdrc_params *sdrc_params;
+
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
- omap_board_config = rx51_config;
- omap_board_config_size = ARRAY_SIZE(rx51_config);
omap3_pm_init_cpuidle(rx51_cpuidle_params);
omap_serial_init();
+
+ sdrc_params = nokia_get_sdram_timings();
+ omap_sdrc_init(sdrc_params, sdrc_params);
+
usb_musb_init(&musb_board_data);
rx51_peripherals_init();
@@ -142,12 +114,6 @@ static void __init rx51_init(void)
platform_device_register(&leds_gpio);
}
-static void __init rx51_map_io(void)
-{
- omap2_set_globals_3xxx();
- omap34xx_map_common_io();
-}
-
static void __init rx51_reserve(void)
{
rx51_video_mem_init();
@@ -156,10 +122,10 @@ static void __init rx51_reserve(void)
MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
/* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = rx51_reserve,
- .map_io = rx51_map_io,
- .init_early = rx51_init_early,
+ .map_io = omap3_map_io,
+ .init_early = omap3430_init_early,
.init_irq = omap3_init_irq,
.init_machine = rx51_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
index a85d5b0b11da..e6ee8842285c 100644
--- a/arch/arm/mach-omap2/board-ti8168evm.c
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -27,30 +27,24 @@
static struct omap_board_config_kernel ti8168_evm_config[] __initdata = {
};
-static void __init ti8168_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
-
static void __init ti8168_evm_init(void)
{
omap_serial_init();
+ omap_sdrc_init(NULL, NULL);
omap_board_config = ti8168_evm_config;
omap_board_config_size = ARRAY_SIZE(ti8168_evm_config);
}
static void __init ti8168_evm_map_io(void)
{
- omap2_set_globals_ti816x();
omapti816x_map_common_io();
}
MACHINE_START(TI8168EVM, "ti8168evm")
/* Maintainer: Texas Instruments */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.map_io = ti8168_evm_map_io,
- .init_early = ti8168_init_early,
+ .init_early = ti816x_init_early,
.init_irq = ti816x_init_irq,
.timer = &omap3_timer,
.init_machine = ti8168_evm_init,
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 8a98c3c303fc..be6684dc4f55 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -34,17 +34,6 @@
#define ZOOM3_EHCI_RESET_GPIO 64
-static void __init omap_zoom_init_early(void)
-{
- omap2_init_common_infrastructure();
- if (machine_is_omap_zoom2())
- omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
- mt46h32m32lf6_sdrc_params);
- else if (machine_is_omap_zoom3())
- omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
- h8mbx00u0mer0em_sdrc_params);
-}
-
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
/* WLAN IRQ - GPIO 162 */
@@ -129,24 +118,32 @@ static void __init omap_zoom_init(void)
ZOOM_NAND_CS, NAND_BUSWIDTH_16);
zoom_debugboard_init();
zoom_peripherals_init();
+
+ if (machine_is_omap_zoom2())
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+ mt46h32m32lf6_sdrc_params);
+ else if (machine_is_omap_zoom3())
+ omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
+ h8mbx00u0mer0em_sdrc_params);
+
zoom_display_init();
}
MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = omap_zoom_init_early,
+ .init_early = omap3430_init_early,
.init_irq = omap3_init_irq,
.init_machine = omap_zoom_init,
.timer = &omap3_timer,
MACHINE_END
MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.reserve = omap_reserve,
.map_io = omap3_map_io,
- .init_early = omap_zoom_init_early,
+ .init_early = omap3630_init_early,
.init_irq = omap3_init_irq,
.init_machine = omap_zoom_init,
.timer = &omap3_timer,
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index debc040872f1..14a6277dd184 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1898,6 +1898,54 @@ static struct omap_clk omap2420_clks[] = {
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("omap_timer.1", "fck", &gpt1_fck, CK_242X),
+ CLK("omap_timer.2", "fck", &gpt2_fck, CK_242X),
+ CLK("omap_timer.3", "fck", &gpt3_fck, CK_242X),
+ CLK("omap_timer.4", "fck", &gpt4_fck, CK_242X),
+ CLK("omap_timer.5", "fck", &gpt5_fck, CK_242X),
+ CLK("omap_timer.6", "fck", &gpt6_fck, CK_242X),
+ CLK("omap_timer.7", "fck", &gpt7_fck, CK_242X),
+ CLK("omap_timer.8", "fck", &gpt8_fck, CK_242X),
+ CLK("omap_timer.9", "fck", &gpt9_fck, CK_242X),
+ CLK("omap_timer.10", "fck", &gpt10_fck, CK_242X),
+ CLK("omap_timer.11", "fck", &gpt11_fck, CK_242X),
+ CLK("omap_timer.12", "fck", &gpt12_fck, CK_242X),
+ CLK("omap_timer.1", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.2", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.3", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.4", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.5", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.6", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.7", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.8", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.9", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.10", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.11", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.12", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.1", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.2", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.3", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.4", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.5", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.6", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.7", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.8", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.9", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.10", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.11", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.12", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.1", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.2", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.3", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.4", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.5", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.6", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.7", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.8", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.9", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.10", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.11", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.12", "alt_ck", &alt_ck, CK_243X),
};
/*
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 96a942e42db1..ea6717cfa3c8 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1998,6 +1998,54 @@ static struct omap_clk omap2430_clks[] = {
CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X),
CLK("omap_hsmmc.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X),
CLK("omap_hsmmc.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X),
+ CLK("omap_timer.1", "fck", &gpt1_fck, CK_243X),
+ CLK("omap_timer.2", "fck", &gpt2_fck, CK_243X),
+ CLK("omap_timer.3", "fck", &gpt3_fck, CK_243X),
+ CLK("omap_timer.4", "fck", &gpt4_fck, CK_243X),
+ CLK("omap_timer.5", "fck", &gpt5_fck, CK_243X),
+ CLK("omap_timer.6", "fck", &gpt6_fck, CK_243X),
+ CLK("omap_timer.7", "fck", &gpt7_fck, CK_243X),
+ CLK("omap_timer.8", "fck", &gpt8_fck, CK_243X),
+ CLK("omap_timer.9", "fck", &gpt9_fck, CK_243X),
+ CLK("omap_timer.10", "fck", &gpt10_fck, CK_243X),
+ CLK("omap_timer.11", "fck", &gpt11_fck, CK_243X),
+ CLK("omap_timer.12", "fck", &gpt12_fck, CK_243X),
+ CLK("omap_timer.1", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.2", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.3", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.4", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.5", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.6", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.7", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.8", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.9", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.10", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.11", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.12", "32k_ck", &func_32k_ck, CK_243X),
+ CLK("omap_timer.1", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.2", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.3", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.4", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.5", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.6", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.7", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.8", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.9", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.10", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.11", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.12", "sys_ck", &sys_ck, CK_243X),
+ CLK("omap_timer.1", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.2", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.3", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.4", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.5", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.6", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.7", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.8", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.9", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.10", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.11", "alt_ck", &alt_ck, CK_243X),
+ CLK("omap_timer.12", "alt_ck", &alt_ck, CK_243X),
};
/*
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index b9b844683147..65dd363163bc 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3464,6 +3464,42 @@ static struct omap_clk omap3xxx_clks[] = {
CLK("musb-am35x", "fck", &hsotgusb_fck_am35xx, CK_AM35XX),
CLK(NULL, "hecc_ck", &hecc_ck, CK_AM35XX),
CLK(NULL, "uart4_ick", &uart4_ick_am35xx, CK_AM35XX),
+ CLK("omap_timer.1", "fck", &gpt1_fck, CK_3XXX),
+ CLK("omap_timer.2", "fck", &gpt2_fck, CK_3XXX),
+ CLK("omap_timer.3", "fck", &gpt3_fck, CK_3XXX),
+ CLK("omap_timer.4", "fck", &gpt4_fck, CK_3XXX),
+ CLK("omap_timer.5", "fck", &gpt5_fck, CK_3XXX),
+ CLK("omap_timer.6", "fck", &gpt6_fck, CK_3XXX),
+ CLK("omap_timer.7", "fck", &gpt7_fck, CK_3XXX),
+ CLK("omap_timer.8", "fck", &gpt8_fck, CK_3XXX),
+ CLK("omap_timer.9", "fck", &gpt9_fck, CK_3XXX),
+ CLK("omap_timer.10", "fck", &gpt10_fck, CK_3XXX),
+ CLK("omap_timer.11", "fck", &gpt11_fck, CK_3XXX),
+ CLK("omap_timer.12", "fck", &gpt12_fck, CK_3XXX),
+ CLK("omap_timer.1", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.2", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.3", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.4", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.5", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.6", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.7", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.8", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.9", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.10", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.11", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.12", "32k_ck", &omap_32k_fck, CK_3XXX),
+ CLK("omap_timer.1", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.2", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.3", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.4", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.5", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.6", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.7", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.8", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.9", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.10", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.11", "sys_ck", &sys_ck, CK_3XXX),
+ CLK("omap_timer.12", "sys_ck", &sys_ck, CK_3XXX),
};
@@ -3472,7 +3508,16 @@ int __init omap3xxx_clk_init(void)
struct omap_clk *c;
u32 cpu_clkflg = 0;
- if (cpu_is_omap3517()) {
+ /*
+ * 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 (cpu_is_omap3505()) {
+ cpu_mask = RATE_IN_34XX;
+ cpu_clkflg = CK_3505;
+ } else if (cpu_is_omap3517()) {
cpu_mask = RATE_IN_34XX;
cpu_clkflg = CK_3517;
} else if (cpu_is_omap3505()) {
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index c0b6fbda3408..946bf04a956d 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3363,6 +3363,39 @@ static struct omap_clk omap44xx_clks[] = {
CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X),
CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X),
CLK("omap_wdt", "ick", &dummy_ck, CK_443X),
+ CLK("omap_timer.1", "fck", &timer1_fck, CK_443X),
+ CLK("omap_timer.2", "fck", &timer2_fck, CK_443X),
+ CLK("omap_timer.3", "fck", &timer3_fck, CK_443X),
+ CLK("omap_timer.4", "fck", &timer4_fck, CK_443X),
+ CLK("omap_timer.5", "fck", &timer5_fck, CK_443X),
+ CLK("omap_timer.6", "fck", &timer6_fck, CK_443X),
+ CLK("omap_timer.7", "fck", &timer7_fck, CK_443X),
+ CLK("omap_timer.8", "fck", &timer8_fck, CK_443X),
+ CLK("omap_timer.9", "fck", &timer9_fck, CK_443X),
+ CLK("omap_timer.10", "fck", &timer10_fck, CK_443X),
+ CLK("omap_timer.11", "fck", &timer11_fck, CK_443X),
+ CLK("omap_timer.1", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.2", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.3", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.4", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.5", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.6", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.7", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.8", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.9", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.10", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.11", "32k_ck", &sys_32k_ck, CK_443X),
+ CLK("omap_timer.1", "sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.2", "sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.3", "sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.4", "sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.9", "sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.10", "sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.11", "sys_ck", &sys_clkin_ck, CK_443X),
+ CLK("omap_timer.5", "sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK("omap_timer.6", "sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK("omap_timer.7", "sys_ck", &syc_clk_div_ck, CK_443X),
+ CLK("omap_timer.8", "sys_ck", &syc_clk_div_ck, CK_443X),
};
int __init omap4xxx_clk_init(void)
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 8f0890685d7b..8480ee4344ea 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -73,9 +73,6 @@ static int _clkdm_register(struct clockdomain *clkdm)
if (!clkdm || !clkdm->name)
return -EINVAL;
- if (!omap_chip_is(clkdm->omap_chip))
- return -EINVAL;
-
pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
if (!pwrdm) {
pr_err("clockdomain: %s: powerdomain %s does not exist\n",
@@ -105,13 +102,10 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
{
struct clkdm_dep *cd;
- if (!clkdm || !deps || !omap_chip_is(clkdm->omap_chip))
+ if (!clkdm || !deps)
return ERR_PTR(-EINVAL);
for (cd = deps; cd->clkdm_name; cd++) {
- if (!omap_chip_is(cd->omap_chip))
- continue;
-
if (!cd->clkdm && cd->clkdm_name)
cd->clkdm = _clkdm_lookup(cd->clkdm_name);
@@ -148,9 +142,6 @@ static void _autodep_lookup(struct clkdm_autodep *autodep)
if (!autodep)
return;
- if (!omap_chip_is(autodep->omap_chip))
- return;
-
clkdm = clkdm_lookup(autodep->clkdm.name);
if (!clkdm) {
pr_err("clockdomain: autodeps: clockdomain %s does not exist\n",
@@ -182,9 +173,6 @@ void _clkdm_add_autodeps(struct clockdomain *clkdm)
if (IS_ERR(autodep->clkdm.ptr))
continue;
- if (!omap_chip_is(autodep->omap_chip))
- continue;
-
pr_debug("clockdomain: adding %s sleepdep/wkdep for "
"clkdm %s\n", autodep->clkdm.ptr->name,
clkdm->name);
@@ -216,9 +204,6 @@ void _clkdm_del_autodeps(struct clockdomain *clkdm)
if (IS_ERR(autodep->clkdm.ptr))
continue;
- if (!omap_chip_is(autodep->omap_chip))
- continue;
-
pr_debug("clockdomain: removing %s sleepdep/wkdep for "
"clkdm %s\n", autodep->clkdm.ptr->name,
clkdm->name);
@@ -243,8 +228,6 @@ static void _resolve_clkdm_deps(struct clockdomain *clkdm,
struct clkdm_dep *cd;
for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
- if (!omap_chip_is(cd->omap_chip))
- continue;
if (cd->clkdm)
continue;
cd->clkdm = _clkdm_lookup(cd->clkdm_name);
@@ -257,43 +240,113 @@ static void _resolve_clkdm_deps(struct clockdomain *clkdm,
/* Public functions */
/**
- * clkdm_init - set up the clockdomain layer
- * @clkdms: optional pointer to an array of clockdomains to register
- * @init_autodeps: optional pointer to an array of autodeps to register
- * @custom_funcs: func pointers for arch specific implementations
- *
- * Set up internal state. If a pointer to an array of clockdomains
- * @clkdms was supplied, loop through the list of clockdomains,
- * register all that are available on the current platform. Similarly,
- * if a pointer to an array of clockdomain autodependencies
- * @init_autodeps was provided, register those. No return value.
+ * clkdm_register_platform_funcs - register clockdomain implementation fns
+ * @co: func pointers for arch specific implementations
+ *
+ * Register the list of function pointers used to implement the
+ * clockdomain functions on different OMAP SoCs. Should be called
+ * before any other clkdm_register*() function. Returns -EINVAL if
+ * @co is null, -EEXIST if platform functions have already been
+ * registered, or 0 upon success.
+ */
+int clkdm_register_platform_funcs(struct clkdm_ops *co)
+{
+ if (!co)
+ return -EINVAL;
+
+ if (arch_clkdm)
+ return -EEXIST;
+
+ arch_clkdm = co;
+
+ return 0;
+};
+
+/**
+ * clkdm_register_clkdms - register SoC clockdomains
+ * @cs: pointer to an array of struct clockdomain to register
+ *
+ * Register the clockdomains available on a particular OMAP SoC. Must
+ * be called after clkdm_register_platform_funcs(). May be called
+ * multiple times. Returns -EACCES if called before
+ * clkdm_register_platform_funcs(); -EINVAL if the argument @cs is
+ * null; or 0 upon success.
*/
-void clkdm_init(struct clockdomain **clkdms,
- struct clkdm_autodep *init_autodeps,
- struct clkdm_ops *custom_funcs)
+int clkdm_register_clkdms(struct clockdomain **cs)
{
struct clockdomain **c = NULL;
- struct clockdomain *clkdm;
- struct clkdm_autodep *autodep = NULL;
- if (!custom_funcs)
- WARN(1, "No custom clkdm functions registered\n");
- else
- arch_clkdm = custom_funcs;
+ if (!arch_clkdm)
+ return -EACCES;
+
+ if (!cs)
+ return -EINVAL;
+
+ for (c = cs; *c; c++)
+ _clkdm_register(*c);
+
+ return 0;
+}
+
+/**
+ * clkdm_register_autodeps - register autodeps (if required)
+ * @ia: pointer to a static array of struct clkdm_autodep to register
+ *
+ * Register clockdomain "automatic dependencies." These are
+ * clockdomain wakeup and sleep dependencies that are automatically
+ * added whenever the first clock inside a clockdomain is enabled, and
+ * removed whenever the last clock inside a clockdomain is disabled.
+ * These are currently only used on OMAP3 devices, and are deprecated,
+ * since they waste energy. However, until the OMAP2/3 IP block
+ * enable/disable sequence can be converted to match the OMAP4
+ * sequence, they are needed.
+ *
+ * Must be called only after all of the SoC clockdomains are
+ * registered, since the function will resolve autodep clockdomain
+ * names into clockdomain pointers.
+ *
+ * The struct clkdm_autodep @ia array must be static, as this function
+ * does not copy the array elements.
+ *
+ * Returns -EACCES if called before any clockdomains have been
+ * registered, -EINVAL if called with a null @ia argument, -EEXIST if
+ * autodeps have already been registered, or 0 upon success.
+ */
+int clkdm_register_autodeps(struct clkdm_autodep *ia)
+{
+ struct clkdm_autodep *a = NULL;
- if (clkdms)
- for (c = clkdms; *c; c++)
- _clkdm_register(*c);
+ if (list_empty(&clkdm_list))
+ return -EACCES;
+
+ if (!ia)
+ return -EINVAL;
- autodeps = init_autodeps;
if (autodeps)
- for (autodep = autodeps; autodep->clkdm.ptr; autodep++)
- _autodep_lookup(autodep);
+ return -EEXIST;
+
+ autodeps = ia;
+ for (a = autodeps; a->clkdm.ptr; a++)
+ _autodep_lookup(a);
+
+ return 0;
+}
+
+/**
+ * clkdm_complete_init - set up the clockdomain layer
+ *
+ * Put all clockdomains into software-supervised mode; PM code should
+ * later enable hardware-supervised mode as appropriate. Must be
+ * called after clkdm_register_clkdms(). Returns -EACCES if called
+ * before clkdm_register_clkdms(), or 0 upon success.
+ */
+int clkdm_complete_init(void)
+{
+ struct clockdomain *clkdm;
+
+ if (list_empty(&clkdm_list))
+ return -EACCES;
- /*
- * Put all clockdomains into software-supervised mode; PM code
- * should later enable hardware-supervised mode as appropriate
- */
list_for_each_entry(clkdm, &clkdm_list, node) {
if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
clkdm_wakeup(clkdm);
@@ -306,6 +359,8 @@ void clkdm_init(struct clockdomain **clkdms,
_resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
clkdm_clear_all_sleepdeps(clkdm);
}
+
+ return 0;
}
/**
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 1e50c88b8a07..f7b58609bad8 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -45,7 +45,6 @@
/**
* struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode
* @clkdm: clockdomain to add wkdep+sleepdep on - set name member only
- * @omap_chip: OMAP chip types that this autodep is valid on
*
* A clockdomain that should have wkdeps and sleepdeps added when a
* clockdomain should stay active in hwsup mode; and conversely,
@@ -60,14 +59,12 @@ struct clkdm_autodep {
const char *name;
struct clockdomain *ptr;
} clkdm;
- const struct omap_chip_id omap_chip;
};
/**
* struct clkdm_dep - encode dependencies between clockdomains
* @clkdm_name: clockdomain name
* @clkdm: pointer to the struct clockdomain of @clkdm_name
- * @omap_chip: OMAP chip types that this dependency is valid on
* @wkdep_usecount: Number of wakeup dependencies causing this clkdm to wake
* @sleepdep_usecount: Number of sleep deps that could prevent clkdm from idle
*
@@ -81,7 +78,6 @@ struct clkdm_dep {
struct clockdomain *clkdm;
atomic_t wkdep_usecount;
atomic_t sleepdep_usecount;
- const struct omap_chip_id omap_chip;
};
/* Possible flags for struct clockdomain._flags */
@@ -101,7 +97,6 @@ struct clkdm_dep {
* @clkdm_offs: (OMAP4 only) CM clockdomain register offset
* @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up
* @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact
- * @omap_chip: OMAP chip types that this clockdomain is valid on
* @usecount: Usecount tracking
* @node: list_head to link all clockdomains together
*
@@ -126,7 +121,6 @@ struct clockdomain {
const u16 clkdm_offs;
struct clkdm_dep *wkdep_srcs;
struct clkdm_dep *sleepdep_srcs;
- const struct omap_chip_id omap_chip;
atomic_t usecount;
struct list_head node;
spinlock_t lock;
@@ -166,8 +160,11 @@ struct clkdm_ops {
int (*clkdm_clk_disable)(struct clockdomain *clkdm);
};
-void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps,
- struct clkdm_ops *custom_funcs);
+int clkdm_register_platform_funcs(struct clkdm_ops *co);
+int clkdm_register_autodeps(struct clkdm_autodep *ia);
+int clkdm_register_clkdms(struct clockdomain **c);
+int clkdm_complete_init(void);
+
struct clockdomain *clkdm_lookup(const char *name);
int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
@@ -195,7 +192,8 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
-extern void __init omap2xxx_clockdomains_init(void);
+extern void __init omap242x_clockdomains_init(void);
+extern void __init omap243x_clockdomains_init(void);
extern void __init omap3xxx_clockdomains_init(void);
extern void __init omap44xx_clockdomains_init(void);
extern void _clkdm_add_autodeps(struct clockdomain *clkdm);
@@ -205,4 +203,10 @@ extern struct clkdm_ops omap2_clkdm_operations;
extern struct clkdm_ops omap3_clkdm_operations;
extern struct clkdm_ops omap4_clkdm_operations;
+extern struct clkdm_dep gfx_24xx_wkdeps[];
+extern struct clkdm_dep dsp_24xx_wkdeps[];
+extern struct clockdomain wkup_common_clkdm;
+extern struct clockdomain prm_common_clkdm;
+extern struct clockdomain cm_common_clkdm;
+
#endif
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
index f740edb111f4..a0d68dbecfa3 100644
--- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
@@ -52,8 +52,6 @@ static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
u32 mask = 0;
for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
- if (!omap_chip_is(cd->omap_chip))
- continue;
if (!cd->clkdm)
continue; /* only happens if data is erroneous */
@@ -98,8 +96,6 @@ static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
u32 mask = 0;
for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
- if (!omap_chip_is(cd->omap_chip))
- continue;
if (!cd->clkdm)
continue; /* only happens if data is erroneous */
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
index b43706aa08bd..935c7f03dab9 100644
--- a/arch/arm/mach-omap2/clockdomain44xx.c
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
@@ -52,8 +52,6 @@ static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
u32 mask = 0;
for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
- if (!omap_chip_is(cd->omap_chip))
- continue;
if (!cd->clkdm)
continue; /* only happens if data is erroneous */
diff --git a/arch/arm/mach-omap2/clockdomains2420_data.c b/arch/arm/mach-omap2/clockdomains2420_data.c
new file mode 100644
index 000000000000..0ab8e46d5b2b
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains2420_data.c
@@ -0,0 +1,154 @@
+/*
+ * OMAP2420 clockdomains
+ *
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This file contains clockdomains and clockdomain wakeup dependencies
+ * for OMAP2420 chips. Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs must have a dep_bit assigned. So
+ * wkdep_srcs are really just software-controllable dependencies.
+ * Non-software-controllable dependencies do exist, but they are not
+ * encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}. The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ * from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* Wakeup dependency source arrays */
+
+/* 2420-specific possible wakeup dependencies */
+
+/* 2420 PM_WKDEP_MPU: CORE, DSP, WKUP */
+static struct clkdm_dep mpu_2420_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "dsp_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/* 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP */
+static struct clkdm_dep core_2420_wkdeps[] = {
+ { .clkdm_name = "dsp_clkdm" },
+ { .clkdm_name = "gfx_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/*
+ * 2420-only clockdomains
+ */
+
+static struct clockdomain mpu_2420_clkdm = {
+ .name = "mpu_clkdm",
+ .pwrdm = { .name = "mpu_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .wkdep_srcs = mpu_2420_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+};
+
+static struct clockdomain iva1_2420_clkdm = {
+ .name = "iva1_clkdm",
+ .pwrdm = { .name = "dsp_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+ .wkdep_srcs = dsp_24xx_wkdeps,
+ .clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
+};
+
+static struct clockdomain dsp_2420_clkdm = {
+ .name = "dsp_clkdm",
+ .pwrdm = { .name = "dsp_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+};
+
+static struct clockdomain gfx_2420_clkdm = {
+ .name = "gfx_clkdm",
+ .pwrdm = { .name = "gfx_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = gfx_24xx_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+};
+
+static struct clockdomain core_l3_2420_clkdm = {
+ .name = "core_l3_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .wkdep_srcs = core_2420_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+};
+
+static struct clockdomain core_l4_2420_clkdm = {
+ .name = "core_l4_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .wkdep_srcs = core_2420_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+};
+
+static struct clockdomain dss_2420_clkdm = {
+ .name = "dss_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+};
+
+static struct clockdomain *clockdomains_omap242x[] __initdata = {
+ &wkup_common_clkdm,
+ &cm_common_clkdm,
+ &prm_common_clkdm,
+ &mpu_2420_clkdm,
+ &iva1_2420_clkdm,
+ &dsp_2420_clkdm,
+ &gfx_2420_clkdm,
+ &core_l3_2420_clkdm,
+ &core_l4_2420_clkdm,
+ &dss_2420_clkdm,
+ NULL,
+};
+
+void __init omap242x_clockdomains_init(void)
+{
+ if (!cpu_is_omap242x())
+ return;
+
+ clkdm_register_platform_funcs(&omap2_clkdm_operations);
+ clkdm_register_clkdms(clockdomains_omap242x);
+ clkdm_complete_init();
+}
diff --git a/arch/arm/mach-omap2/clockdomains2430_data.c b/arch/arm/mach-omap2/clockdomains2430_data.c
new file mode 100644
index 000000000000..3645ed044890
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains2430_data.c
@@ -0,0 +1,181 @@
+/*
+ * OMAP2xxx clockdomains
+ *
+ * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This file contains clockdomains and clockdomain wakeup dependencies
+ * for OMAP2xxx chips. Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs must have a dep_bit assigned. So
+ * wkdep_srcs are really just software-controllable dependencies.
+ * Non-software-controllable dependencies do exist, but they are not
+ * encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}. The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ * from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* Wakeup dependency source arrays */
+
+/* 2430-specific possible wakeup dependencies */
+
+/* 2430 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP, MDM */
+static struct clkdm_dep core_2430_wkdeps[] = {
+ { .clkdm_name = "dsp_clkdm" },
+ { .clkdm_name = "gfx_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { .clkdm_name = "mdm_clkdm" },
+ { NULL },
+};
+
+/* 2430 PM_WKDEP_MPU: CORE, DSP, WKUP, MDM */
+static struct clkdm_dep mpu_2430_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "dsp_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { .clkdm_name = "mdm_clkdm" },
+ { NULL },
+};
+
+/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
+static struct clkdm_dep mdm_2430_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/*
+ * 2430-only clockdomains
+ */
+
+static struct clockdomain mpu_2430_clkdm = {
+ .name = "mpu_clkdm",
+ .pwrdm = { .name = "mpu_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = mpu_2430_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+};
+
+/* Another case of bit name collisions between several registers: EN_MDM */
+static struct clockdomain mdm_clkdm = {
+ .name = "mdm_clkdm",
+ .pwrdm = { .name = "mdm_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
+ .wkdep_srcs = mdm_2430_wkdeps,
+ .clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
+};
+
+static struct clockdomain dsp_2430_clkdm = {
+ .name = "dsp_clkdm",
+ .pwrdm = { .name = "dsp_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+ .wkdep_srcs = dsp_24xx_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+};
+
+static struct clockdomain gfx_2430_clkdm = {
+ .name = "gfx_clkdm",
+ .pwrdm = { .name = "gfx_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = gfx_24xx_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l3_2430_clkdm = {
+ .name = "core_l3_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .dep_bit = OMAP24XX_EN_CORE_SHIFT,
+ .wkdep_srcs = core_2430_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l4_2430_clkdm = {
+ .name = "core_l4_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .dep_bit = OMAP24XX_EN_CORE_SHIFT,
+ .wkdep_srcs = core_2430_wkdeps,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+};
+
+static struct clockdomain dss_2430_clkdm = {
+ .name = "dss_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+};
+
+static struct clockdomain *clockdomains_omap243x[] __initdata = {
+ &wkup_common_clkdm,
+ &cm_common_clkdm,
+ &prm_common_clkdm,
+ &mpu_2430_clkdm,
+ &mdm_clkdm,
+ &dsp_2430_clkdm,
+ &gfx_2430_clkdm,
+ &core_l3_2430_clkdm,
+ &core_l4_2430_clkdm,
+ &dss_2430_clkdm,
+ NULL,
+};
+
+void __init omap243x_clockdomains_init(void)
+{
+ if (!cpu_is_omap243x())
+ return;
+
+ clkdm_register_platform_funcs(&omap2_clkdm_operations);
+ clkdm_register_clkdms(clockdomains_omap243x);
+ clkdm_complete_init();
+}
+
diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
index 13bde95b6790..0a6a04897d89 100644
--- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
@@ -1,7 +1,7 @@
/*
- * OMAP2/3 clockdomains
+ * OMAP2/3 clockdomain common data
*
- * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
* Copyright (C) 2008-2010 Nokia Corporation
*
* Paul Walmsley, Jouni Högander
@@ -51,374 +51,28 @@
* changed in software) are not included here yet, but should be.
*/
-/* OMAP2/3-common wakeup dependencies */
-
-/*
- * 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
- * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
- * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
- * These can share data since they will never be present simultaneously
- * on the same device.
- */
-static struct clkdm_dep gfx_sgx_wkdeps[] = {
- {
- .clkdm_name = "core_l3_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "core_l4_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "iva2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
- CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
- CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-
-/* 24XX-specific possible dependencies */
-
-#ifdef CONFIG_ARCH_OMAP2
-
/* Wakeup dependency source arrays */
-/* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP */
-static struct clkdm_dep dsp_24xx_wkdeps[] = {
- {
- .clkdm_name = "core_l3_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "core_l4_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- { NULL },
-};
-
-/*
- * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
- * 2430 adds MDM
- */
-static struct clkdm_dep mpu_24xx_wkdeps[] = {
- {
- .clkdm_name = "core_l3_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "core_l4_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "dsp_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "mdm_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
- },
- { NULL },
-};
-
-/*
- * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
- * 2430 adds MDM
- */
-static struct clkdm_dep core_24xx_wkdeps[] = {
- {
- .clkdm_name = "dsp_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "gfx_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "mdm_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
- },
- { NULL },
-};
-
-#endif /* CONFIG_ARCH_OMAP2 */
-
-/* 2430-specific possible wakeup dependencies */
+/* 2xxx-specific possible dependencies */
-#ifdef CONFIG_SOC_OMAP2430
-
-/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
-static struct clkdm_dep mdm_2430_wkdeps[] = {
- {
- .clkdm_name = "core_l3_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "core_l4_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- {
- .clkdm_name = "wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
- },
- { NULL },
-};
-
-#endif /* CONFIG_SOC_OMAP2430 */
-
-
-/* OMAP3-specific possible dependencies */
-
-#ifdef CONFIG_ARCH_OMAP3
-
-/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
-static struct clkdm_dep per_wkdeps[] = {
- {
- .clkdm_name = "core_l3_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "core_l4_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "iva2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
-static struct clkdm_dep usbhost_wkdeps[] = {
- {
- .clkdm_name = "core_l3_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "core_l4_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "iva2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
+/* 2xxx PM_WKDEP_GFX: CORE, MPU, WKUP */
+struct clkdm_dep gfx_24xx_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
{ NULL },
};
-/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
-static struct clkdm_dep mpu_3xxx_wkdeps[] = {
- {
- .clkdm_name = "core_l3_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "core_l4_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "iva2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "dss_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "per_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
+/* 2xxx PM_WKDEP_DSP: CORE, MPU, WKUP */
+struct clkdm_dep dsp_24xx_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
{ NULL },
};
-/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
-static struct clkdm_dep iva2_wkdeps[] = {
- {
- .clkdm_name = "core_l3_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "core_l4_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "dss_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "per_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-
-/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
-static struct clkdm_dep cam_wkdeps[] = {
- {
- .clkdm_name = "iva2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
-static struct clkdm_dep dss_wkdeps[] = {
- {
- .clkdm_name = "iva2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-/* 3430: PM_WKDEP_NEON: MPU */
-static struct clkdm_dep neon_wkdeps[] = {
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-
-/* Sleep dependency source arrays for OMAP3-specific clkdms */
-
-/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
-static struct clkdm_dep dss_sleepdeps[] = {
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "iva2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
-static struct clkdm_dep per_sleepdeps[] = {
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "iva2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
-static struct clkdm_dep usbhost_sleepdeps[] = {
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm_name = "iva2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-/* 3430: CM_SLEEPDEP_CAM: MPU */
-static struct clkdm_dep cam_sleepdeps[] = {
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-/*
- * 3430ES1: CM_SLEEPDEP_GFX: MPU
- * 3430ES2: CM_SLEEPDEP_SGX: MPU
- * These can share data since they will never be present simultaneously
- * on the same device.
- */
-static struct clkdm_dep gfx_sgx_sleepdeps[] = {
- {
- .clkdm_name = "mpu_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- { NULL },
-};
-
-#endif /* CONFIG_ARCH_OMAP3 */
-
/*
* OMAP2/3-common clockdomains
@@ -430,439 +84,18 @@ static struct clkdm_dep gfx_sgx_sleepdeps[] = {
*/
/* This is an implicit clockdomain - it is never defined as such in TRM */
-static struct clockdomain wkup_clkdm = {
+struct clockdomain wkup_common_clkdm = {
.name = "wkup_clkdm",
.pwrdm = { .name = "wkup_pwrdm" },
.dep_bit = OMAP_EN_WKUP_SHIFT,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
};
-static struct clockdomain prm_clkdm = {
+struct clockdomain prm_common_clkdm = {
.name = "prm_clkdm",
.pwrdm = { .name = "wkup_pwrdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
};
-static struct clockdomain cm_clkdm = {
+struct clockdomain cm_common_clkdm = {
.name = "cm_clkdm",
.pwrdm = { .name = "core_pwrdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
};
-
-/*
- * 2420-only clockdomains
- */
-
-#if defined(CONFIG_SOC_OMAP2420)
-
-static struct clockdomain mpu_2420_clkdm = {
- .name = "mpu_clkdm",
- .pwrdm = { .name = "mpu_pwrdm" },
- .flags = CLKDM_CAN_HWSUP,
- .wkdep_srcs = mpu_24xx_wkdeps,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain iva1_2420_clkdm = {
- .name = "iva1_clkdm",
- .pwrdm = { .name = "dsp_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .dep_bit = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
- .wkdep_srcs = dsp_24xx_wkdeps,
- .clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain dsp_2420_clkdm = {
- .name = "dsp_clkdm",
- .pwrdm = { .name = "dsp_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain gfx_2420_clkdm = {
- .name = "gfx_clkdm",
- .pwrdm = { .name = "gfx_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .wkdep_srcs = gfx_sgx_wkdeps,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain core_l3_2420_clkdm = {
- .name = "core_l3_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .flags = CLKDM_CAN_HWSUP,
- .wkdep_srcs = core_24xx_wkdeps,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain core_l4_2420_clkdm = {
- .name = "core_l4_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .flags = CLKDM_CAN_HWSUP,
- .wkdep_srcs = core_24xx_wkdeps,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain dss_2420_clkdm = {
- .name = "dss_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .flags = CLKDM_CAN_HWSUP,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-#endif /* CONFIG_SOC_OMAP2420 */
-
-
-/*
- * 2430-only clockdomains
- */
-
-#if defined(CONFIG_SOC_OMAP2430)
-
-static struct clockdomain mpu_2430_clkdm = {
- .name = "mpu_clkdm",
- .pwrdm = { .name = "mpu_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .wkdep_srcs = mpu_24xx_wkdeps,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/* Another case of bit name collisions between several registers: EN_MDM */
-static struct clockdomain mdm_clkdm = {
- .name = "mdm_clkdm",
- .pwrdm = { .name = "mdm_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .dep_bit = OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
- .wkdep_srcs = mdm_2430_wkdeps,
- .clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain dsp_2430_clkdm = {
- .name = "dsp_clkdm",
- .pwrdm = { .name = "dsp_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .dep_bit = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
- .wkdep_srcs = dsp_24xx_wkdeps,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain gfx_2430_clkdm = {
- .name = "gfx_clkdm",
- .pwrdm = { .name = "gfx_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .wkdep_srcs = gfx_sgx_wkdeps,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l3_2430_clkdm = {
- .name = "core_l3_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .flags = CLKDM_CAN_HWSUP,
- .dep_bit = OMAP24XX_EN_CORE_SHIFT,
- .wkdep_srcs = core_24xx_wkdeps,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l4_2430_clkdm = {
- .name = "core_l4_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .flags = CLKDM_CAN_HWSUP,
- .dep_bit = OMAP24XX_EN_CORE_SHIFT,
- .wkdep_srcs = core_24xx_wkdeps,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain dss_2430_clkdm = {
- .name = "dss_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .flags = CLKDM_CAN_HWSUP,
- .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-#endif /* CONFIG_SOC_OMAP2430 */
-
-
-/*
- * OMAP3 clockdomains
- */
-
-#if defined(CONFIG_ARCH_OMAP3)
-
-static struct clockdomain mpu_3xxx_clkdm = {
- .name = "mpu_clkdm",
- .pwrdm = { .name = "mpu_pwrdm" },
- .flags = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
- .dep_bit = OMAP3430_EN_MPU_SHIFT,
- .wkdep_srcs = mpu_3xxx_wkdeps,
- .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain neon_clkdm = {
- .name = "neon_clkdm",
- .pwrdm = { .name = "neon_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .wkdep_srcs = neon_wkdeps,
- .clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain iva2_clkdm = {
- .name = "iva2_clkdm",
- .pwrdm = { .name = "iva2_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
- .wkdep_srcs = iva2_wkdeps,
- .clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain gfx_3430es1_clkdm = {
- .name = "gfx_clkdm",
- .pwrdm = { .name = "gfx_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .wkdep_srcs = gfx_sgx_wkdeps,
- .sleepdep_srcs = gfx_sgx_sleepdeps,
- .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
-};
-
-static struct clockdomain sgx_clkdm = {
- .name = "sgx_clkdm",
- .pwrdm = { .name = "sgx_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .wkdep_srcs = gfx_sgx_wkdeps,
- .sleepdep_srcs = gfx_sgx_sleepdeps,
- .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-/*
- * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
- * then that information was removed from the 34xx ES2+ TRM. It is
- * unclear whether the core is still there, but the clockdomain logic
- * is there, and must be programmed to an appropriate state if the
- * CORE clockdomain is to become inactive.
- */
-static struct clockdomain d2d_clkdm = {
- .name = "d2d_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l3_3xxx_clkdm = {
- .name = "core_l3_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .flags = CLKDM_CAN_HWSUP,
- .dep_bit = OMAP3430_EN_CORE_SHIFT,
- .clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l4_3xxx_clkdm = {
- .name = "core_l4_clkdm",
- .pwrdm = { .name = "core_pwrdm" },
- .flags = CLKDM_CAN_HWSUP,
- .dep_bit = OMAP3430_EN_CORE_SHIFT,
- .clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/* Another case of bit name collisions between several registers: EN_DSS */
-static struct clockdomain dss_3xxx_clkdm = {
- .name = "dss_clkdm",
- .pwrdm = { .name = "dss_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
- .wkdep_srcs = dss_wkdeps,
- .sleepdep_srcs = dss_sleepdeps,
- .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain cam_clkdm = {
- .name = "cam_clkdm",
- .pwrdm = { .name = "cam_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .wkdep_srcs = cam_wkdeps,
- .sleepdep_srcs = cam_sleepdeps,
- .clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain usbhost_clkdm = {
- .name = "usbhost_clkdm",
- .pwrdm = { .name = "usbhost_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .wkdep_srcs = usbhost_wkdeps,
- .sleepdep_srcs = usbhost_sleepdeps,
- .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-static struct clockdomain per_clkdm = {
- .name = "per_clkdm",
- .pwrdm = { .name = "per_pwrdm" },
- .flags = CLKDM_CAN_HWSUP_SWSUP,
- .dep_bit = OMAP3430_EN_PER_SHIFT,
- .wkdep_srcs = per_wkdeps,
- .sleepdep_srcs = per_sleepdeps,
- .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
- * switched of even if sdti is in use
- */
-static struct clockdomain emu_clkdm = {
- .name = "emu_clkdm",
- .pwrdm = { .name = "emu_pwrdm" },
- .flags = /* CLKDM_CAN_ENABLE_AUTO | */CLKDM_CAN_SWSUP,
- .clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll1_clkdm = {
- .name = "dpll1_clkdm",
- .pwrdm = { .name = "dpll1_pwrdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll2_clkdm = {
- .name = "dpll2_clkdm",
- .pwrdm = { .name = "dpll2_pwrdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll3_clkdm = {
- .name = "dpll3_clkdm",
- .pwrdm = { .name = "dpll3_pwrdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll4_clkdm = {
- .name = "dpll4_clkdm",
- .pwrdm = { .name = "dpll4_pwrdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll5_clkdm = {
- .name = "dpll5_clkdm",
- .pwrdm = { .name = "dpll5_pwrdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-#endif /* CONFIG_ARCH_OMAP3 */
-
-/*
- * Clockdomain hwsup dependencies (OMAP3 only)
- */
-
-static struct clkdm_autodep clkdm_autodeps[] = {
- {
- .clkdm = { .name = "mpu_clkdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm = { .name = "iva2_clkdm" },
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
- },
- {
- .clkdm = { .name = NULL },
- }
-};
-
-static struct clockdomain *clockdomains_omap2[] __initdata = {
- &wkup_clkdm,
- &cm_clkdm,
- &prm_clkdm,
-
-#ifdef CONFIG_SOC_OMAP2420
- &mpu_2420_clkdm,
- &iva1_2420_clkdm,
- &dsp_2420_clkdm,
- &gfx_2420_clkdm,
- &core_l3_2420_clkdm,
- &core_l4_2420_clkdm,
- &dss_2420_clkdm,
-#endif
-
-#ifdef CONFIG_SOC_OMAP2430
- &mpu_2430_clkdm,
- &mdm_clkdm,
- &dsp_2430_clkdm,
- &gfx_2430_clkdm,
- &core_l3_2430_clkdm,
- &core_l4_2430_clkdm,
- &dss_2430_clkdm,
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
- &mpu_3xxx_clkdm,
- &neon_clkdm,
- &iva2_clkdm,
- &gfx_3430es1_clkdm,
- &sgx_clkdm,
- &d2d_clkdm,
- &core_l3_3xxx_clkdm,
- &core_l4_3xxx_clkdm,
- &dss_3xxx_clkdm,
- &cam_clkdm,
- &usbhost_clkdm,
- &per_clkdm,
- &emu_clkdm,
- &dpll1_clkdm,
- &dpll2_clkdm,
- &dpll3_clkdm,
- &dpll4_clkdm,
- &dpll5_clkdm,
-#endif
- NULL,
-};
-
-void __init omap2xxx_clockdomains_init(void)
-{
- clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap2_clkdm_operations);
-}
-
-void __init omap3xxx_clockdomains_init(void)
-{
- clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap3_clkdm_operations);
-}
diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c
new file mode 100644
index 000000000000..b84e138d99c8
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c
@@ -0,0 +1,398 @@
+/*
+ * OMAP3xxx clockdomains
+ *
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This file contains clockdomains and clockdomain wakeup/sleep
+ * dependencies for the OMAP3xxx chips. Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs or sleepdep_srcs array must have a
+ * dep_bit assigned. So wkdep_srcs/sleepdep_srcs are really just
+ * software-controllable dependencies. Non-software-controllable
+ * dependencies do exist, but they are not encoded below (yet).
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}. The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ * from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-34xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps/sleepdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* OMAP3-specific possible dependencies */
+
+/*
+ * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
+ * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
+ */
+static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = {
+ { .clkdm_name = "iva2_clkdm", },
+ { .clkdm_name = "mpu_clkdm", },
+ { .clkdm_name = "wkup_clkdm", },
+ { NULL },
+};
+
+/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep per_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep usbhost_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
+static struct clkdm_dep mpu_3xxx_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "dss_clkdm" },
+ { .clkdm_name = "per_clkdm" },
+ { NULL },
+};
+
+/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
+static struct clkdm_dep iva2_wkdeps[] = {
+ { .clkdm_name = "core_l3_clkdm" },
+ { .clkdm_name = "core_l4_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { .clkdm_name = "dss_clkdm" },
+ { .clkdm_name = "per_clkdm" },
+ { NULL },
+};
+
+/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
+static struct clkdm_dep cam_wkdeps[] = {
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
+static struct clkdm_dep dss_wkdeps[] = {
+ { .clkdm_name = "iva2_clkdm" },
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "wkup_clkdm" },
+ { NULL },
+};
+
+/* 3430: PM_WKDEP_NEON: MPU */
+static struct clkdm_dep neon_wkdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { NULL },
+};
+
+/* Sleep dependency source arrays for OMAP3-specific clkdms */
+
+/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
+static struct clkdm_dep dss_sleepdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { NULL },
+};
+
+/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
+static struct clkdm_dep per_sleepdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { NULL },
+};
+
+/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
+static struct clkdm_dep usbhost_sleepdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { .clkdm_name = "iva2_clkdm" },
+ { NULL },
+};
+
+/* 3430: CM_SLEEPDEP_CAM: MPU */
+static struct clkdm_dep cam_sleepdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { NULL },
+};
+
+/*
+ * 3430ES1: CM_SLEEPDEP_GFX: MPU
+ * 3430ES2: CM_SLEEPDEP_SGX: MPU
+ * These can share data since they will never be present simultaneously
+ * on the same device.
+ */
+static struct clkdm_dep gfx_sgx_sleepdeps[] = {
+ { .clkdm_name = "mpu_clkdm" },
+ { NULL },
+};
+
+/*
+ * OMAP3 clockdomains
+ */
+
+static struct clockdomain mpu_3xxx_clkdm = {
+ .name = "mpu_clkdm",
+ .pwrdm = { .name = "mpu_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
+ .dep_bit = OMAP3430_EN_MPU_SHIFT,
+ .wkdep_srcs = mpu_3xxx_wkdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
+};
+
+static struct clockdomain neon_clkdm = {
+ .name = "neon_clkdm",
+ .pwrdm = { .name = "neon_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = neon_wkdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
+};
+
+static struct clockdomain iva2_clkdm = {
+ .name = "iva2_clkdm",
+ .pwrdm = { .name = "iva2_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
+ .wkdep_srcs = iva2_wkdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
+};
+
+static struct clockdomain gfx_3430es1_clkdm = {
+ .name = "gfx_clkdm",
+ .pwrdm = { .name = "gfx_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = gfx_sgx_3xxx_wkdeps,
+ .sleepdep_srcs = gfx_sgx_sleepdeps,
+ .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
+};
+
+static struct clockdomain sgx_clkdm = {
+ .name = "sgx_clkdm",
+ .pwrdm = { .name = "sgx_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = gfx_sgx_3xxx_wkdeps,
+ .sleepdep_srcs = gfx_sgx_sleepdeps,
+ .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
+};
+
+/*
+ * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
+ * then that information was removed from the 34xx ES2+ TRM. It is
+ * unclear whether the core is still there, but the clockdomain logic
+ * is there, and must be programmed to an appropriate state if the
+ * CORE clockdomain is to become inactive.
+ */
+static struct clockdomain d2d_clkdm = {
+ .name = "d2d_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l3_3xxx_clkdm = {
+ .name = "core_l3_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .dep_bit = OMAP3430_EN_CORE_SHIFT,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l4_3xxx_clkdm = {
+ .name = "core_l4_clkdm",
+ .pwrdm = { .name = "core_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP,
+ .dep_bit = OMAP3430_EN_CORE_SHIFT,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
+};
+
+/* Another case of bit name collisions between several registers: EN_DSS */
+static struct clockdomain dss_3xxx_clkdm = {
+ .name = "dss_clkdm",
+ .pwrdm = { .name = "dss_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
+ .wkdep_srcs = dss_wkdeps,
+ .sleepdep_srcs = dss_sleepdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
+};
+
+static struct clockdomain cam_clkdm = {
+ .name = "cam_clkdm",
+ .pwrdm = { .name = "cam_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = cam_wkdeps,
+ .sleepdep_srcs = cam_sleepdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
+};
+
+static struct clockdomain usbhost_clkdm = {
+ .name = "usbhost_clkdm",
+ .pwrdm = { .name = "usbhost_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .wkdep_srcs = usbhost_wkdeps,
+ .sleepdep_srcs = usbhost_sleepdeps,
+ .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
+};
+
+static struct clockdomain per_clkdm = {
+ .name = "per_clkdm",
+ .pwrdm = { .name = "per_pwrdm" },
+ .flags = CLKDM_CAN_HWSUP_SWSUP,
+ .dep_bit = OMAP3430_EN_PER_SHIFT,
+ .wkdep_srcs = per_wkdeps,
+ .sleepdep_srcs = per_sleepdeps,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
+};
+
+/*
+ * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
+ * switched of even if sdti is in use
+ */
+static struct clockdomain emu_clkdm = {
+ .name = "emu_clkdm",
+ .pwrdm = { .name = "emu_pwrdm" },
+ .flags = /* CLKDM_CAN_ENABLE_AUTO | */CLKDM_CAN_SWSUP,
+ .clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
+};
+
+static struct clockdomain dpll1_clkdm = {
+ .name = "dpll1_clkdm",
+ .pwrdm = { .name = "dpll1_pwrdm" },
+};
+
+static struct clockdomain dpll2_clkdm = {
+ .name = "dpll2_clkdm",
+ .pwrdm = { .name = "dpll2_pwrdm" },
+};
+
+static struct clockdomain dpll3_clkdm = {
+ .name = "dpll3_clkdm",
+ .pwrdm = { .name = "dpll3_pwrdm" },
+};
+
+static struct clockdomain dpll4_clkdm = {
+ .name = "dpll4_clkdm",
+ .pwrdm = { .name = "dpll4_pwrdm" },
+};
+
+static struct clockdomain dpll5_clkdm = {
+ .name = "dpll5_clkdm",
+ .pwrdm = { .name = "dpll5_pwrdm" },
+};
+
+/*
+ * Clockdomain hwsup dependencies
+ */
+
+static struct clkdm_autodep clkdm_autodeps[] = {
+ {
+ .clkdm = { .name = "mpu_clkdm" },
+ },
+ {
+ .clkdm = { .name = "iva2_clkdm" },
+ },
+ {
+ .clkdm = { .name = NULL },
+ }
+};
+
+/*
+ *
+ */
+
+static struct clockdomain *clockdomains_omap3430_common[] __initdata = {
+ &wkup_common_clkdm,
+ &cm_common_clkdm,
+ &prm_common_clkdm,
+ &mpu_3xxx_clkdm,
+ &neon_clkdm,
+ &iva2_clkdm,
+ &d2d_clkdm,
+ &core_l3_3xxx_clkdm,
+ &core_l4_3xxx_clkdm,
+ &dss_3xxx_clkdm,
+ &cam_clkdm,
+ &per_clkdm,
+ &emu_clkdm,
+ &dpll1_clkdm,
+ &dpll2_clkdm,
+ &dpll3_clkdm,
+ &dpll4_clkdm,
+ NULL
+};
+
+static struct clockdomain *clockdomains_omap3430es1[] __initdata = {
+ &gfx_3430es1_clkdm,
+ NULL,
+};
+
+static struct clockdomain *clockdomains_omap3430es2plus[] __initdata = {
+ &sgx_clkdm,
+ &dpll5_clkdm,
+ &usbhost_clkdm,
+ NULL,
+};
+
+void __init omap3xxx_clockdomains_init(void)
+{
+ struct clockdomain **sc;
+
+ if (!cpu_is_omap34xx())
+ return;
+
+ clkdm_register_platform_funcs(&omap3_clkdm_operations);
+ clkdm_register_clkdms(clockdomains_omap3430_common);
+
+ sc = (omap_rev() == OMAP3430_REV_ES1_0) ? clockdomains_omap3430es1 :
+ clockdomains_omap3430es2plus;
+
+ clkdm_register_clkdms(sc);
+
+ clkdm_register_autodeps(clkdm_autodeps);
+ clkdm_complete_init();
+}
diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c
index dccc651fa0d0..9299ac291d28 100644
--- a/arch/arm/mach-omap2/clockdomains44xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains44xx_data.c
@@ -34,350 +34,122 @@
/* Static Dependencies for OMAP4 Clock Domains */
static struct clkdm_dep d2d_wkup_sleep_deps[] = {
- {
- .clkdm_name = "abe_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "ivahd_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_1_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_init_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_cfg_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_per_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "abe_clkdm" },
+ { .clkdm_name = "ivahd_clkdm" },
+ { .clkdm_name = "l3_1_clkdm" },
+ { .clkdm_name = "l3_2_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
+ { .clkdm_name = "l3_init_clkdm" },
+ { .clkdm_name = "l4_cfg_clkdm" },
+ { .clkdm_name = "l4_per_clkdm" },
{ NULL },
};
static struct clkdm_dep ducati_wkup_sleep_deps[] = {
- {
- .clkdm_name = "abe_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "ivahd_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_1_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_dss_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_gfx_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_init_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_cfg_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_per_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_secure_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "tesla_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "abe_clkdm" },
+ { .clkdm_name = "ivahd_clkdm" },
+ { .clkdm_name = "l3_1_clkdm" },
+ { .clkdm_name = "l3_2_clkdm" },
+ { .clkdm_name = "l3_dss_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
+ { .clkdm_name = "l3_gfx_clkdm" },
+ { .clkdm_name = "l3_init_clkdm" },
+ { .clkdm_name = "l4_cfg_clkdm" },
+ { .clkdm_name = "l4_per_clkdm" },
+ { .clkdm_name = "l4_secure_clkdm" },
+ { .clkdm_name = "l4_wkup_clkdm" },
+ { .clkdm_name = "tesla_clkdm" },
{ NULL },
};
static struct clkdm_dep iss_wkup_sleep_deps[] = {
- {
- .clkdm_name = "ivahd_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_1_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "ivahd_clkdm" },
+ { .clkdm_name = "l3_1_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
{ NULL },
};
static struct clkdm_dep ivahd_wkup_sleep_deps[] = {
- {
- .clkdm_name = "l3_1_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "l3_1_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
{ NULL },
};
static struct clkdm_dep l3_dma_wkup_sleep_deps[] = {
- {
- .clkdm_name = "abe_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "ducati_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "ivahd_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_1_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_dss_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_init_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_cfg_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_per_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_secure_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "abe_clkdm" },
+ { .clkdm_name = "ducati_clkdm" },
+ { .clkdm_name = "ivahd_clkdm" },
+ { .clkdm_name = "l3_1_clkdm" },
+ { .clkdm_name = "l3_dss_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
+ { .clkdm_name = "l3_init_clkdm" },
+ { .clkdm_name = "l4_cfg_clkdm" },
+ { .clkdm_name = "l4_per_clkdm" },
+ { .clkdm_name = "l4_secure_clkdm" },
+ { .clkdm_name = "l4_wkup_clkdm" },
{ NULL },
};
static struct clkdm_dep l3_dss_wkup_sleep_deps[] = {
- {
- .clkdm_name = "ivahd_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "ivahd_clkdm" },
+ { .clkdm_name = "l3_2_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
{ NULL },
};
static struct clkdm_dep l3_gfx_wkup_sleep_deps[] = {
- {
- .clkdm_name = "ivahd_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_1_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "ivahd_clkdm" },
+ { .clkdm_name = "l3_1_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
{ NULL },
};
static struct clkdm_dep l3_init_wkup_sleep_deps[] = {
- {
- .clkdm_name = "abe_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "ivahd_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_cfg_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_per_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_secure_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "abe_clkdm" },
+ { .clkdm_name = "ivahd_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
+ { .clkdm_name = "l4_cfg_clkdm" },
+ { .clkdm_name = "l4_per_clkdm" },
+ { .clkdm_name = "l4_secure_clkdm" },
+ { .clkdm_name = "l4_wkup_clkdm" },
{ NULL },
};
static struct clkdm_dep l4_secure_wkup_sleep_deps[] = {
- {
- .clkdm_name = "l3_1_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_per_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "l3_1_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
+ { .clkdm_name = "l4_per_clkdm" },
{ NULL },
};
static struct clkdm_dep mpu_wkup_sleep_deps[] = {
- {
- .clkdm_name = "abe_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "ducati_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "ivahd_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_1_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_dss_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_gfx_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_init_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_cfg_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_per_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_secure_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "tesla_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "abe_clkdm" },
+ { .clkdm_name = "ducati_clkdm" },
+ { .clkdm_name = "ivahd_clkdm" },
+ { .clkdm_name = "l3_1_clkdm" },
+ { .clkdm_name = "l3_2_clkdm" },
+ { .clkdm_name = "l3_dss_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
+ { .clkdm_name = "l3_gfx_clkdm" },
+ { .clkdm_name = "l3_init_clkdm" },
+ { .clkdm_name = "l4_cfg_clkdm" },
+ { .clkdm_name = "l4_per_clkdm" },
+ { .clkdm_name = "l4_secure_clkdm" },
+ { .clkdm_name = "l4_wkup_clkdm" },
+ { .clkdm_name = "tesla_clkdm" },
{ NULL },
};
static struct clkdm_dep tesla_wkup_sleep_deps[] = {
- {
- .clkdm_name = "abe_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "ivahd_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_1_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_2_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_emif_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l3_init_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_cfg_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_per_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
- {
- .clkdm_name = "l4_wkup_clkdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
- },
+ { .clkdm_name = "abe_clkdm" },
+ { .clkdm_name = "ivahd_clkdm" },
+ { .clkdm_name = "l3_1_clkdm" },
+ { .clkdm_name = "l3_2_clkdm" },
+ { .clkdm_name = "l3_emif_clkdm" },
+ { .clkdm_name = "l3_init_clkdm" },
+ { .clkdm_name = "l4_cfg_clkdm" },
+ { .clkdm_name = "l4_per_clkdm" },
+ { .clkdm_name = "l4_wkup_clkdm" },
{ NULL },
};
@@ -388,7 +160,6 @@ static struct clockdomain l4_cefuse_44xx_clkdm = {
.cm_inst = OMAP4430_CM2_CEFUSE_INST,
.clkdm_offs = OMAP4430_CM2_CEFUSE_CEFUSE_CDOFFS,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l4_cfg_44xx_clkdm = {
@@ -399,7 +170,6 @@ static struct clockdomain l4_cfg_44xx_clkdm = {
.clkdm_offs = OMAP4430_CM2_CORE_L4CFG_CDOFFS,
.dep_bit = OMAP4430_L4CFG_STATDEP_SHIFT,
.flags = CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain tesla_44xx_clkdm = {
@@ -412,7 +182,6 @@ static struct clockdomain tesla_44xx_clkdm = {
.wkdep_srcs = tesla_wkup_sleep_deps,
.sleepdep_srcs = tesla_wkup_sleep_deps,
.flags = CLKDM_CAN_HWSUP_SWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_gfx_44xx_clkdm = {
@@ -425,7 +194,6 @@ static struct clockdomain l3_gfx_44xx_clkdm = {
.wkdep_srcs = l3_gfx_wkup_sleep_deps,
.sleepdep_srcs = l3_gfx_wkup_sleep_deps,
.flags = CLKDM_CAN_HWSUP_SWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain ivahd_44xx_clkdm = {
@@ -438,7 +206,6 @@ static struct clockdomain ivahd_44xx_clkdm = {
.wkdep_srcs = ivahd_wkup_sleep_deps,
.sleepdep_srcs = ivahd_wkup_sleep_deps,
.flags = CLKDM_CAN_HWSUP_SWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l4_secure_44xx_clkdm = {
@@ -451,7 +218,6 @@ static struct clockdomain l4_secure_44xx_clkdm = {
.wkdep_srcs = l4_secure_wkup_sleep_deps,
.sleepdep_srcs = l4_secure_wkup_sleep_deps,
.flags = CLKDM_CAN_HWSUP_SWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l4_per_44xx_clkdm = {
@@ -462,7 +228,6 @@ static struct clockdomain l4_per_44xx_clkdm = {
.clkdm_offs = OMAP4430_CM2_L4PER_L4PER_CDOFFS,
.dep_bit = OMAP4430_L4PER_STATDEP_SHIFT,
.flags = CLKDM_CAN_HWSUP_SWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain abe_44xx_clkdm = {
@@ -473,7 +238,6 @@ static struct clockdomain abe_44xx_clkdm = {
.clkdm_offs = OMAP4430_CM1_ABE_ABE_CDOFFS,
.dep_bit = OMAP4430_ABE_STATDEP_SHIFT,
.flags = CLKDM_CAN_HWSUP_SWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_instr_44xx_clkdm = {
@@ -482,7 +246,6 @@ static struct clockdomain l3_instr_44xx_clkdm = {
.prcm_partition = OMAP4430_CM2_PARTITION,
.cm_inst = OMAP4430_CM2_CORE_INST,
.clkdm_offs = OMAP4430_CM2_CORE_L3INSTR_CDOFFS,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_init_44xx_clkdm = {
@@ -495,7 +258,6 @@ static struct clockdomain l3_init_44xx_clkdm = {
.wkdep_srcs = l3_init_wkup_sleep_deps,
.sleepdep_srcs = l3_init_wkup_sleep_deps,
.flags = CLKDM_CAN_HWSUP_SWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain d2d_44xx_clkdm = {
@@ -507,7 +269,6 @@ static struct clockdomain d2d_44xx_clkdm = {
.wkdep_srcs = d2d_wkup_sleep_deps,
.sleepdep_srcs = d2d_wkup_sleep_deps,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain mpu0_44xx_clkdm = {
@@ -517,7 +278,6 @@ static struct clockdomain mpu0_44xx_clkdm = {
.cm_inst = OMAP4430_PRCM_MPU_CPU0_INST,
.clkdm_offs = OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain mpu1_44xx_clkdm = {
@@ -527,7 +287,6 @@ static struct clockdomain mpu1_44xx_clkdm = {
.cm_inst = OMAP4430_PRCM_MPU_CPU1_INST,
.clkdm_offs = OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_emif_44xx_clkdm = {
@@ -538,7 +297,6 @@ static struct clockdomain l3_emif_44xx_clkdm = {
.clkdm_offs = OMAP4430_CM2_CORE_MEMIF_CDOFFS,
.dep_bit = OMAP4430_MEMIF_STATDEP_SHIFT,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l4_ao_44xx_clkdm = {
@@ -548,7 +306,6 @@ static struct clockdomain l4_ao_44xx_clkdm = {
.cm_inst = OMAP4430_CM2_ALWAYS_ON_INST,
.clkdm_offs = OMAP4430_CM2_ALWAYS_ON_ALWON_CDOFFS,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain ducati_44xx_clkdm = {
@@ -561,7 +318,6 @@ static struct clockdomain ducati_44xx_clkdm = {
.wkdep_srcs = ducati_wkup_sleep_deps,
.sleepdep_srcs = ducati_wkup_sleep_deps,
.flags = CLKDM_CAN_HWSUP_SWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain mpu_44xx_clkdm = {
@@ -573,7 +329,6 @@ static struct clockdomain mpu_44xx_clkdm = {
.wkdep_srcs = mpu_wkup_sleep_deps,
.sleepdep_srcs = mpu_wkup_sleep_deps,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_2_44xx_clkdm = {
@@ -584,7 +339,6 @@ static struct clockdomain l3_2_44xx_clkdm = {
.clkdm_offs = OMAP4430_CM2_CORE_L3_2_CDOFFS,
.dep_bit = OMAP4430_L3_2_STATDEP_SHIFT,
.flags = CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_1_44xx_clkdm = {
@@ -595,7 +349,6 @@ static struct clockdomain l3_1_44xx_clkdm = {
.clkdm_offs = OMAP4430_CM2_CORE_L3_1_CDOFFS,
.dep_bit = OMAP4430_L3_1_STATDEP_SHIFT,
.flags = CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain iss_44xx_clkdm = {
@@ -607,7 +360,6 @@ static struct clockdomain iss_44xx_clkdm = {
.wkdep_srcs = iss_wkup_sleep_deps,
.sleepdep_srcs = iss_wkup_sleep_deps,
.flags = CLKDM_CAN_HWSUP_SWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_dss_44xx_clkdm = {
@@ -620,7 +372,6 @@ static struct clockdomain l3_dss_44xx_clkdm = {
.wkdep_srcs = l3_dss_wkup_sleep_deps,
.sleepdep_srcs = l3_dss_wkup_sleep_deps,
.flags = CLKDM_CAN_HWSUP_SWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l4_wkup_44xx_clkdm = {
@@ -631,7 +382,6 @@ static struct clockdomain l4_wkup_44xx_clkdm = {
.clkdm_offs = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS,
.dep_bit = OMAP4430_L4WKUP_STATDEP_SHIFT,
.flags = CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain emu_sys_44xx_clkdm = {
@@ -641,7 +391,6 @@ static struct clockdomain emu_sys_44xx_clkdm = {
.cm_inst = OMAP4430_PRM_EMU_CM_INST,
.clkdm_offs = OMAP4430_PRM_EMU_CM_EMU_CDOFFS,
.flags = CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_dma_44xx_clkdm = {
@@ -653,7 +402,6 @@ static struct clockdomain l3_dma_44xx_clkdm = {
.wkdep_srcs = l3_dma_wkup_sleep_deps,
.sleepdep_srcs = l3_dma_wkup_sleep_deps,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* As clockdomains are added or removed above, this list must also be changed */
@@ -685,7 +433,10 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = {
NULL
};
+
void __init omap44xx_clockdomains_init(void)
{
- clkdm_init(clockdomains_omap44xx, NULL, &omap4_clkdm_operations);
+ clkdm_register_platform_funcs(&omap4_clkdm_operations);
+ clkdm_register_clkdms(clockdomains_omap44xx);
+ clkdm_complete_init();
}
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
index 3f20cbb9967b..110e5b9db145 100644
--- a/arch/arm/mach-omap2/common.c
+++ b/arch/arm/mach-omap2/common.c
@@ -45,17 +45,22 @@ static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
static struct omap_globals omap242x_globals = {
.class = OMAP242X_CLASS,
.tap = OMAP2_L4_IO_ADDRESS(0x48014000),
- .sdrc = OMAP2420_SDRC_BASE,
- .sms = OMAP2420_SMS_BASE,
- .ctrl = OMAP242X_CTRL_BASE,
- .prm = OMAP2420_PRM_BASE,
- .cm = OMAP2420_CM_BASE,
+ .sdrc = OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE),
+ .sms = OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE),
+ .ctrl = OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE),
+ .prm = OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE),
+ .cm = OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE),
};
void __init omap2_set_globals_242x(void)
{
__omap2_set_globals(&omap242x_globals);
}
+
+void __init omap242x_map_io(void)
+{
+ omap242x_map_common_io();
+}
#endif
#if defined(CONFIG_SOC_OMAP2430)
@@ -63,17 +68,22 @@ void __init omap2_set_globals_242x(void)
static struct omap_globals omap243x_globals = {
.class = OMAP243X_CLASS,
.tap = OMAP2_L4_IO_ADDRESS(0x4900a000),
- .sdrc = OMAP243X_SDRC_BASE,
- .sms = OMAP243X_SMS_BASE,
- .ctrl = OMAP243X_CTRL_BASE,
- .prm = OMAP2430_PRM_BASE,
- .cm = OMAP2430_CM_BASE,
+ .sdrc = OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE),
+ .sms = OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE),
+ .ctrl = OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE),
+ .prm = OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE),
+ .cm = OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE),
};
void __init omap2_set_globals_243x(void)
{
__omap2_set_globals(&omap243x_globals);
}
+
+void __init omap243x_map_io(void)
+{
+ omap243x_map_common_io();
+}
#endif
#if defined(CONFIG_ARCH_OMAP3)
@@ -81,11 +91,11 @@ void __init omap2_set_globals_243x(void)
static struct omap_globals omap3_globals = {
.class = OMAP343X_CLASS,
.tap = OMAP2_L4_IO_ADDRESS(0x4830A000),
- .sdrc = OMAP343X_SDRC_BASE,
- .sms = OMAP343X_SMS_BASE,
- .ctrl = OMAP343X_CTRL_BASE,
- .prm = OMAP3430_PRM_BASE,
- .cm = OMAP3430_CM_BASE,
+ .sdrc = OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE),
+ .sms = OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE),
+ .ctrl = OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE),
+ .prm = OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE),
+ .cm = OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE),
};
void __init omap2_set_globals_3xxx(void)
@@ -95,7 +105,6 @@ void __init omap2_set_globals_3xxx(void)
void __init omap3_map_io(void)
{
- omap2_set_globals_3xxx();
omap34xx_map_common_io();
}
@@ -110,9 +119,9 @@ void __init omap3_map_io(void)
static struct omap_globals ti816x_globals = {
.class = OMAP343X_CLASS,
.tap = OMAP2_L4_IO_ADDRESS(TI816X_TAP_BASE),
- .ctrl = TI816X_CTRL_BASE,
- .prm = TI816X_PRCM_BASE,
- .cm = TI816X_PRCM_BASE,
+ .ctrl = OMAP2_L4_IO_ADDRESS(TI816X_CTRL_BASE),
+ .prm = OMAP2_L4_IO_ADDRESS(TI816X_PRCM_BASE),
+ .cm = OMAP2_L4_IO_ADDRESS(TI816X_PRCM_BASE),
};
void __init omap2_set_globals_ti816x(void)
@@ -125,11 +134,11 @@ void __init omap2_set_globals_ti816x(void)
static struct omap_globals omap4_globals = {
.class = OMAP443X_CLASS,
.tap = OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
- .ctrl = OMAP443X_SCM_BASE,
- .ctrl_pad = OMAP443X_CTRL_BASE,
- .prm = OMAP4430_PRM_BASE,
- .cm = OMAP4430_CM_BASE,
- .cm2 = OMAP4430_CM2_BASE,
+ .ctrl = OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
+ .ctrl_pad = OMAP2_L4_IO_ADDRESS(OMAP443X_CTRL_BASE),
+ .prm = OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE),
+ .cm = OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE),
+ .cm2 = OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE),
};
void __init omap2_set_globals_443x(void)
@@ -138,5 +147,10 @@ void __init omap2_set_globals_443x(void)
omap2_set_globals_control(&omap4_globals);
omap2_set_globals_prcm(&omap4_globals);
}
+
+void __init omap4_map_io(void)
+{
+ omap44xx_map_common_io();
+}
#endif
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index aab884fecc55..e34d27f8c49c 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -149,17 +149,11 @@ static struct omap3_control_regs control_context;
void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
{
- /* Static mapping, never released */
- if (omap2_globals->ctrl) {
- omap2_ctrl_base = ioremap(omap2_globals->ctrl, SZ_4K);
- WARN_ON(!omap2_ctrl_base);
- }
+ if (omap2_globals->ctrl)
+ omap2_ctrl_base = omap2_globals->ctrl;
- /* Static mapping, never released */
- if (omap2_globals->ctrl_pad) {
- omap4_ctrl_pad_base = ioremap(omap2_globals->ctrl_pad, SZ_4K);
- WARN_ON(!omap4_ctrl_pad_base);
- }
+ if (omap2_globals->ctrl_pad)
+ omap4_ctrl_pad_base = omap2_globals->ctrl_pad;
}
void __iomem *omap_ctrl_base_get(void)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 1077ad663f93..68ec03152d5f 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -8,7 +8,7 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -16,6 +16,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/of.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
@@ -26,7 +27,6 @@
#include <plat/tc.h>
#include <plat/board.h>
#include <plat/mcbsp.h>
-#include <mach/gpio.h>
#include <plat/mmc.h>
#include <plat/dma.h>
#include <plat/omap_hwmod.h>
@@ -44,7 +44,7 @@ static int __init omap3_l3_init(void)
{
int l;
struct omap_hwmod *oh;
- struct omap_device *od;
+ struct platform_device *pdev;
char oh_name[L3_MODULES_MAX_LEN];
/*
@@ -61,12 +61,12 @@ static int __init omap3_l3_init(void)
if (!oh)
pr_err("could not look up %s\n", oh_name);
- od = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
+ pdev = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
NULL, 0, 0);
- WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+ WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
- return IS_ERR(od) ? PTR_ERR(od) : 0;
+ return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
}
postcore_initcall(omap3_l3_init);
@@ -74,9 +74,13 @@ static int __init omap4_l3_init(void)
{
int l, i;
struct omap_hwmod *oh[3];
- struct omap_device *od;
+ struct platform_device *pdev;
char oh_name[L3_MODULES_MAX_LEN];
+ /* If dtb is there, the devices will be created dynamically */
+ if (of_have_populated_dt())
+ return -ENODEV;
+
/*
* To avoid code running on other OMAPs in
* multi-omap builds
@@ -92,12 +96,12 @@ static int __init omap4_l3_init(void)
pr_err("could not look up %s\n", oh_name);
}
- od = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
+ pdev = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
0, NULL, 0, 0);
- WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+ WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
- return IS_ERR(od) ? PTR_ERR(od) : 0;
+ return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
}
postcore_initcall(omap4_l3_init);
@@ -221,18 +225,10 @@ static inline void omap_init_camera(void)
#endif
}
-struct omap_device_pm_latency omap_keyboard_latency[] = {
- {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
-};
-
int __init omap4_keyboard_init(struct omap4_keypad_platform_data
*sdp4430_keypad_data, struct omap_board_data *bdata)
{
- struct omap_device *od;
+ struct platform_device *pdev;
struct omap_hwmod *oh;
struct omap4_keypad_platform_data *keypad_data;
unsigned int id = -1;
@@ -247,15 +243,13 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data
keypad_data = sdp4430_keypad_data;
- od = omap_device_build(name, id, oh, keypad_data,
- sizeof(struct omap4_keypad_platform_data),
- omap_keyboard_latency,
- ARRAY_SIZE(omap_keyboard_latency), 0);
+ pdev = omap_device_build(name, id, oh, keypad_data,
+ sizeof(struct omap4_keypad_platform_data), NULL, 0, 0);
- if (IS_ERR(od)) {
+ if (IS_ERR(pdev)) {
WARN(1, "Can't build omap_device for %s:%s.\n",
name, oh->name);
- return PTR_ERR(od);
+ return PTR_ERR(pdev);
}
oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
@@ -263,18 +257,10 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data
}
#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
-static struct omap_device_pm_latency mbox_latencies[] = {
- [0] = {
- .activate_func = omap_device_enable_hwmods,
- .deactivate_func = omap_device_idle_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
-};
-
static inline void omap_init_mbox(void)
{
struct omap_hwmod *oh;
- struct omap_device *od;
+ struct platform_device *pdev;
oh = omap_hwmod_lookup("mailbox");
if (!oh) {
@@ -282,10 +268,9 @@ static inline void omap_init_mbox(void)
return;
}
- od = omap_device_build("omap-mailbox", -1, oh, NULL, 0,
- mbox_latencies, ARRAY_SIZE(mbox_latencies), 0);
- WARN(IS_ERR(od), "%s: could not build device, err %ld\n",
- __func__, PTR_ERR(od));
+ pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0, NULL, 0, 0);
+ WARN(IS_ERR(pdev), "%s: could not build device, err %ld\n",
+ __func__, PTR_ERR(pdev));
}
#else
static inline void omap_init_mbox(void) { }
@@ -330,21 +315,45 @@ static void omap_init_audio(void)
static inline void omap_init_audio(void) {}
#endif
-#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
-
-#include <plat/mcspi.h>
+#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
+ defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
-struct omap_device_pm_latency omap_mcspi_latency[] = {
- [0] = {
+static struct omap_device_pm_latency omap_mcpdm_latency[] = {
+ {
.deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
},
};
-static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
+static void omap_init_mcpdm(void)
{
+ struct omap_hwmod *oh;
struct omap_device *od;
+
+ oh = omap_hwmod_lookup("mcpdm");
+ if (!oh) {
+ printk(KERN_ERR "Could not look up mcpdm hw_mod\n");
+ return;
+ }
+
+ od = omap_device_build("omap-mcpdm", -1, oh, NULL, 0,
+ omap_mcpdm_latency,
+ ARRAY_SIZE(omap_mcpdm_latency), 0);
+ if (IS_ERR(od))
+ printk(KERN_ERR "Could not build omap_device for omap-mcpdm-dai\n");
+}
+#else
+static inline void omap_init_mcpdm(void) {}
+#endif
+
+#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
+
+#include <plat/mcspi.h>
+
+static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
+{
+ struct platform_device *pdev;
char *name = "omap2_mcspi";
struct omap2_mcspi_platform_config *pdata;
static int spi_num;
@@ -371,10 +380,9 @@ static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
}
spi_num++;
- od = omap_device_build(name, spi_num, oh, pdata,
- sizeof(*pdata), omap_mcspi_latency,
- ARRAY_SIZE(omap_mcspi_latency), 0);
- WARN(IS_ERR(od), "Can't build omap_device for %s:%s\n",
+ pdev = omap_device_build(name, spi_num, oh, pdata,
+ sizeof(*pdata), NULL, 0, 0);
+ WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s\n",
name, oh->name);
kfree(pdata);
return 0;
@@ -683,6 +691,7 @@ static int __init omap2_init_devices(void)
* in alphabetical order so they're easier to sort through.
*/
omap_init_audio();
+ omap_init_mcpdm();
omap_init_camera();
omap_init_mbox();
omap_init_mcspi();
@@ -698,18 +707,10 @@ static int __init omap2_init_devices(void)
arch_initcall(omap2_init_devices);
#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-static struct omap_device_pm_latency omap_wdt_latency[] = {
- [0] = {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
-};
-
static int __init omap_init_wdt(void)
{
int id = -1;
- struct omap_device *od;
+ struct platform_device *pdev;
struct omap_hwmod *oh;
char *oh_name = "wd_timer2";
char *dev_name = "omap_wdt";
@@ -723,10 +724,8 @@ static int __init omap_init_wdt(void)
return -EINVAL;
}
- od = omap_device_build(dev_name, id, oh, NULL, 0,
- omap_wdt_latency,
- ARRAY_SIZE(omap_wdt_latency), 0);
- WARN(IS_ERR(od), "Can't build omap_device for %s:%s.\n",
+ pdev = omap_device_build(dev_name, id, oh, NULL, 0, NULL, 0, 0);
+ WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
dev_name, oh->name);
return 0;
}
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index a5b7a236aa5b..4036821a01f3 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -27,6 +27,8 @@
#include <plat/omap_device.h>
#include <plat/omap-pm.h>
+#include "control.h"
+
static struct platform_device omap_display_device = {
.name = "omapdss",
.id = -1,
@@ -35,14 +37,6 @@ static struct platform_device omap_display_device = {
},
};
-static struct omap_device_pm_latency omap_dss_latency[] = {
- [0] = {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
-};
-
struct omap_dss_hwmod_data {
const char *oh_name;
const char *dev_name;
@@ -61,7 +55,7 @@ static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = {
{ "dss_dispc", "omapdss_dispc", -1 },
{ "dss_rfbi", "omapdss_rfbi", -1 },
{ "dss_venc", "omapdss_venc", -1 },
- { "dss_dsi1", "omapdss_dsi1", -1 },
+ { "dss_dsi1", "omapdss_dsi", 0 },
};
static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
@@ -69,16 +63,63 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
{ "dss_dispc", "omapdss_dispc", -1 },
{ "dss_rfbi", "omapdss_rfbi", -1 },
{ "dss_venc", "omapdss_venc", -1 },
- { "dss_dsi1", "omapdss_dsi1", -1 },
- { "dss_dsi2", "omapdss_dsi2", -1 },
+ { "dss_dsi1", "omapdss_dsi", 0 },
+ { "dss_dsi2", "omapdss_dsi", 1 },
{ "dss_hdmi", "omapdss_hdmi", -1 },
};
+static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+{
+ u32 enable_mask, enable_shift;
+ u32 pipd_mask, pipd_shift;
+ u32 reg;
+
+ if (dsi_id == 0) {
+ enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
+ enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
+ pipd_mask = OMAP4_DSI1_PIPD_MASK;
+ pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
+ } else if (dsi_id == 1) {
+ enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
+ enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
+ pipd_mask = OMAP4_DSI2_PIPD_MASK;
+ pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
+ } else {
+ return -ENODEV;
+ }
+
+ reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+ reg &= ~enable_mask;
+ reg &= ~pipd_mask;
+
+ reg |= (lanes << enable_shift) & enable_mask;
+ reg |= (lanes << pipd_shift) & pipd_mask;
+
+ omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+ return 0;
+}
+
+static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
+{
+ if (cpu_is_omap44xx())
+ return omap4_dsi_mux_pads(dsi_id, lane_mask);
+
+ return 0;
+}
+
+static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
+{
+ if (cpu_is_omap44xx())
+ omap4_dsi_mux_pads(dsi_id, 0);
+}
+
int __init omap_display_init(struct omap_dss_board_info *board_data)
{
int r = 0;
struct omap_hwmod *oh;
- struct omap_device *od;
+ struct platform_device *pdev;
int i, oh_count;
struct omap_display_platform_data pdata;
const struct omap_dss_hwmod_data *curr_dss_hwmod;
@@ -96,6 +137,11 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
}
+ if (board_data->dsi_enable_pads == NULL)
+ board_data->dsi_enable_pads = omap_dsi_enable_pads;
+ if (board_data->dsi_disable_pads == NULL)
+ board_data->dsi_disable_pads = omap_dsi_disable_pads;
+
pdata.board_data = board_data;
pdata.board_data->get_context_loss_count =
omap_pm_get_dev_context_loss_count;
@@ -108,13 +154,12 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
return -ENODEV;
}
- od = omap_device_build(curr_dss_hwmod[i].dev_name,
+ pdev = omap_device_build(curr_dss_hwmod[i].dev_name,
curr_dss_hwmod[i].id, oh, &pdata,
sizeof(struct omap_display_platform_data),
- omap_dss_latency,
- ARRAY_SIZE(omap_dss_latency), 0);
+ NULL, 0, 0);
- if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n",
+ if (WARN((IS_ERR(pdev)), "Could not build omap_device for %s\n",
curr_dss_hwmod[i].oh_name))
return -ENODEV;
}
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index c9ff0e79703d..a59a45a0096e 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -87,14 +87,6 @@ static u16 reg_map[] = {
[CCDN] = 0xd8,
};
-static struct omap_device_pm_latency omap2_dma_latency[] = {
- {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
-};
-
static void __iomem *dma_base;
static inline void dma_write(u32 val, int reg, int lch)
{
@@ -228,7 +220,7 @@ static u32 configure_dma_errata(void)
/* One time initializations */
static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
{
- struct omap_device *od;
+ struct platform_device *pdev;
struct omap_system_dma_plat_info *p;
struct resource *mem;
char *name = "omap_dma_system";
@@ -258,23 +250,22 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
p->errata = configure_dma_errata();
- od = omap_device_build(name, 0, oh, p, sizeof(*p),
- omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
+ pdev = omap_device_build(name, 0, oh, p, sizeof(*p), NULL, 0, 0);
kfree(p);
- if (IS_ERR(od)) {
+ if (IS_ERR(pdev)) {
pr_err("%s: Can't build omap_device for %s:%s.\n",
__func__, name, oh->name);
- return PTR_ERR(od);
+ return PTR_ERR(pdev);
}
- mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
- dev_err(&od->pdev.dev, "%s: no mem resource\n", __func__);
+ dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
return -EINVAL;
}
dma_base = ioremap(mem->start, resource_size(mem));
if (!dma_base) {
- dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__);
+ dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
return -ENOMEM;
}
@@ -283,7 +274,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
(d->lch_count), GFP_KERNEL);
if (!d->chan) {
- dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
+ dev_err(&pdev->dev, "%s: kzalloc fail\n", __func__);
return -ENOMEM;
}
return 0;
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 2765cdc3152d..8cbfbc2918ce 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -24,17 +24,9 @@
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
-static struct omap_device_pm_latency omap_gpio_latency[] = {
- [0] = {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
-};
-
static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
{
- struct omap_device *od;
+ struct platform_device *pdev;
struct omap_gpio_platform_data *pdata;
struct omap_gpio_dev_attr *dev_attr;
char *name = "omap_gpio";
@@ -107,19 +99,17 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
return -EINVAL;
}
- od = omap_device_build(name, id - 1, oh, pdata,
- sizeof(*pdata), omap_gpio_latency,
- ARRAY_SIZE(omap_gpio_latency),
- false);
+ pdev = omap_device_build(name, id - 1, oh, pdata,
+ sizeof(*pdata), NULL, 0, false);
kfree(pdata);
- if (IS_ERR(od)) {
+ if (IS_ERR(pdev)) {
WARN(1, "Can't build omap_device for %s:%s.\n",
name, oh->name);
- return PTR_ERR(od);
+ return PTR_ERR(pdev);
}
- omap_device_disable_idle_on_suspend(od);
+ omap_device_disable_idle_on_suspend(pdev);
gpio_bank_count++;
return 0;
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 097a42d81e59..77085847e4e7 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -409,31 +409,17 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
return 0;
}
-static struct omap_device_pm_latency omap_hsmmc_latency[] = {
- [0] = {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
- /*
- * XXX There should also be an entry here to power off/on the
- * MMC regulators/PBIAS cells, etc.
- */
-};
-
#define MAX_OMAP_MMC_HWMOD_NAME_LEN 16
void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
{
struct omap_hwmod *oh;
- struct omap_device *od;
- struct omap_device_pm_latency *ohl;
+ struct platform_device *pdev;
char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
struct omap_mmc_platform_data *mmc_data;
struct omap_mmc_dev_attr *mmc_dev_attr;
char *name;
int l;
- int ohl_cnt = 0;
mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL);
if (!mmc_data) {
@@ -448,8 +434,6 @@ void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
name = "omap_hsmmc";
- ohl = omap_hsmmc_latency;
- ohl_cnt = ARRAY_SIZE(omap_hsmmc_latency);
l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
"mmc%d", ctrl_nr);
@@ -467,9 +451,9 @@ void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
mmc_data->controller_flags = mmc_dev_attr->flags;
}
- od = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
- sizeof(struct omap_mmc_platform_data), ohl, ohl_cnt, false);
- if (IS_ERR(od)) {
+ pdev = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
+ sizeof(struct omap_mmc_platform_data), NULL, 0, false);
+ if (IS_ERR(pdev)) {
WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name);
kfree(mmc_data->slots[0].name);
goto done;
@@ -478,7 +462,7 @@ void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
* return device handle to board setup code
* required to populate for regulator framework structure
*/
- hsmmcinfo->dev = &od->pdev.dev;
+ hsmmcinfo->dev = &pdev->dev;
done:
kfree(mmc_data);
diff --git a/arch/arm/mach-omap2/hwspinlock.c b/arch/arm/mach-omap2/hwspinlock.c
index 06d4a80660a5..454dfce125ca 100644
--- a/arch/arm/mach-omap2/hwspinlock.c
+++ b/arch/arm/mach-omap2/hwspinlock.c
@@ -19,23 +19,20 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/hwspinlock.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
-struct omap_device_pm_latency omap_spinlock_latency[] = {
- {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- }
+static struct hwspinlock_pdata omap_hwspinlock_pdata __initdata = {
+ .base_id = 0,
};
int __init hwspinlocks_init(void)
{
int retval = 0;
struct omap_hwmod *oh;
- struct omap_device *od;
+ struct platform_device *pdev;
const char *oh_name = "spinlock";
const char *dev_name = "omap_hwspinlock";
@@ -48,13 +45,13 @@ int __init hwspinlocks_init(void)
if (oh == NULL)
return -EINVAL;
- od = omap_device_build(dev_name, 0, oh, NULL, 0,
- omap_spinlock_latency,
- ARRAY_SIZE(omap_spinlock_latency), false);
- if (IS_ERR(od)) {
+ pdev = omap_device_build(dev_name, 0, oh, &omap_hwspinlock_pdata,
+ sizeof(struct hwspinlock_pdata),
+ NULL, 0, false);
+ if (IS_ERR(pdev)) {
pr_err("Can't build omap_device for %s:%s\n", dev_name,
oh_name);
- retval = PTR_ERR(od);
+ retval = PTR_ERR(pdev);
}
return retval;
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 37efb8696927..d27daf921c7e 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -28,7 +28,6 @@
#include "control.h"
-static struct omap_chip_id omap_chip;
static unsigned int omap_revision;
u32 omap_features;
@@ -39,19 +38,6 @@ unsigned int omap_rev(void)
}
EXPORT_SYMBOL(omap_rev);
-/**
- * omap_chip_is - test whether currently running OMAP matches a chip type
- * @oc: omap_chip_t to test against
- *
- * Test whether the currently-running OMAP chip matches the supplied
- * chip type 'oc'. Returns 1 upon a match; 0 upon failure.
- */
-int omap_chip_is(struct omap_chip_id oci)
-{
- return (oci.oc & omap_chip.oc) ? 1 : 0;
-}
-EXPORT_SYMBOL(omap_chip_is);
-
int omap_type(void)
{
u32 val = 0;
@@ -242,14 +228,12 @@ static void __init ti816x_check_features(void)
omap_features = OMAP3_HAS_NEON;
}
-static void __init omap3_check_revision(void)
+static void __init omap3_check_revision(const char **cpu_rev)
{
u32 cpuid, idcode;
u16 hawkeye;
u8 rev;
- omap_chip.oc = CHIP_IS_OMAP3430;
-
/*
* We cannot access revision registers on ES1.0.
* If the processor type is Cortex-A8 and the revision is 0x0
@@ -258,7 +242,7 @@ static void __init omap3_check_revision(void)
cpuid = read_cpuid(CPUID_ID);
if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) {
omap_revision = OMAP3430_REV_ES1_0;
- omap_chip.oc |= CHIP_IS_OMAP3430ES1;
+ *cpu_rev = "1.0";
return;
}
@@ -279,77 +263,85 @@ static void __init omap3_check_revision(void)
case 0: /* Take care of early samples */
case 1:
omap_revision = OMAP3430_REV_ES2_0;
- omap_chip.oc |= CHIP_IS_OMAP3430ES2;
+ *cpu_rev = "2.0";
break;
case 2:
omap_revision = OMAP3430_REV_ES2_1;
- omap_chip.oc |= CHIP_IS_OMAP3430ES2;
+ *cpu_rev = "2.1";
break;
case 3:
omap_revision = OMAP3430_REV_ES3_0;
- omap_chip.oc |= CHIP_IS_OMAP3430ES3_0;
+ *cpu_rev = "3.0";
break;
case 4:
omap_revision = OMAP3430_REV_ES3_1;
- omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+ *cpu_rev = "3.1";
break;
case 7:
/* FALLTHROUGH */
default:
/* Use the latest known revision as default */
omap_revision = OMAP3430_REV_ES3_1_2;
-
- /* REVISIT: Add CHIP_IS_OMAP3430ES3_1_2? */
- omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+ *cpu_rev = "3.1.2";
}
break;
case 0xb868:
- /* Handle OMAP35xx/AM35xx devices
+ /*
+ * Handle OMAP/AM 3505/3517 devices
*
- * Set the device to be OMAP3505 here. Actual device
+ * Set the device to be OMAP3517 here. Actual device
* is identified later based on the features.
- *
- * REVISIT: AM3505/AM3517 should have their own CHIP_IS
*/
- omap_revision = OMAP3505_REV(rev);
- omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+ switch (rev) {
+ case 0:
+ omap_revision = OMAP3517_REV_ES1_0;
+ *cpu_rev = "1.0";
+ break;
+ case 1:
+ /* FALLTHROUGH */
+ default:
+ omap_revision = OMAP3517_REV_ES1_1;
+ *cpu_rev = "1.1";
+ }
break;
case 0xb891:
/* Handle 36xx devices */
- omap_chip.oc |= CHIP_IS_OMAP3630ES1;
switch(rev) {
case 0: /* Take care of early samples */
omap_revision = OMAP3630_REV_ES1_0;
+ *cpu_rev = "1.0";
break;
case 1:
omap_revision = OMAP3630_REV_ES1_1;
- omap_chip.oc |= CHIP_IS_OMAP3630ES1_1;
+ *cpu_rev = "1.1";
break;
case 2:
+ /* FALLTHROUGH */
default:
- omap_revision = OMAP3630_REV_ES1_2;
- omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
+ omap_revision = OMAP3630_REV_ES1_2;
+ *cpu_rev = "1.2";
}
break;
case 0xb81e:
- omap_chip.oc = CHIP_IS_TI816X;
-
switch (rev) {
case 0:
omap_revision = TI8168_REV_ES1_0;
+ *cpu_rev = "1.0";
break;
case 1:
+ /* FALLTHROUGH */
+ default:
omap_revision = TI8168_REV_ES1_1;
+ *cpu_rev = "1.1";
break;
- default:
- omap_revision = TI8168_REV_ES1_1;
}
break;
default:
- /* Unknown default to latest silicon rev as default*/
- omap_revision = OMAP3630_REV_ES1_2;
- omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
+ /* Unknown default to latest silicon rev as default */
+ omap_revision = OMAP3630_REV_ES1_2;
+ *cpu_rev = "1.2";
+ pr_warn("Warning: unknown chip type; assuming OMAP3630ES1.2\n");
}
}
@@ -382,24 +374,20 @@ static void __init omap4_check_revision(void)
switch (rev) {
case 0:
omap_revision = OMAP4430_REV_ES1_0;
- omap_chip.oc |= CHIP_IS_OMAP4430ES1;
break;
case 1:
default:
omap_revision = OMAP4430_REV_ES2_0;
- omap_chip.oc |= CHIP_IS_OMAP4430ES2;
}
break;
case 0xb95c:
switch (rev) {
case 3:
omap_revision = OMAP4430_REV_ES2_1;
- omap_chip.oc |= CHIP_IS_OMAP4430ES2_1;
break;
case 4:
default:
omap_revision = OMAP4430_REV_ES2_2;
- omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
}
break;
case 0xb94e:
@@ -407,14 +395,12 @@ static void __init omap4_check_revision(void)
case 0:
default:
omap_revision = OMAP4460_REV_ES1_0;
- omap_chip.oc |= CHIP_IS_OMAP4460ES1_0;
break;
}
break;
default:
/* Unknown default to latest silicon rev as default */
omap_revision = OMAP4430_REV_ES2_2;
- omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
}
pr_info("OMAP%04x ES%d.%d\n", omap_rev() >> 16,
@@ -425,94 +411,33 @@ static void __init omap4_check_revision(void)
if (omap3_has_ ##feat()) \
printk(#feat" ");
-static void __init omap3_cpuinfo(void)
+static void __init omap3_cpuinfo(const char *cpu_rev)
{
- u8 rev = GET_OMAP_REVISION();
- char cpu_name[16], cpu_rev[16];
+ const char *cpu_name;
- /* OMAP3430 and OMAP3530 are assumed to be same.
+ /*
+ * OMAP3430 and OMAP3530 are assumed to be same.
*
* OMAP3525, OMAP3515 and OMAP3503 can be detected only based
* on available features. Upon detection, update the CPU id
* and CPU class bits.
*/
if (cpu_is_omap3630()) {
- strcpy(cpu_name, "OMAP3630");
- } else if (cpu_is_omap3505()) {
- /*
- * AM35xx devices
- */
- if (omap3_has_sgx()) {
- omap_revision = OMAP3517_REV(rev);
- strcpy(cpu_name, "AM3517");
- } else {
- /* Already set in omap3_check_revision() */
- strcpy(cpu_name, "AM3505");
- }
+ cpu_name = "OMAP3630";
+ } else if (cpu_is_omap3517()) {
+ /* AM35xx devices */
+ cpu_name = (omap3_has_sgx()) ? "AM3517" : "AM3505";
} else if (cpu_is_ti816x()) {
- strcpy(cpu_name, "TI816X");
+ cpu_name = "TI816X";
} else if (omap3_has_iva() && omap3_has_sgx()) {
/* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */
- strcpy(cpu_name, "OMAP3430/3530");
+ cpu_name = "OMAP3430/3530";
} else if (omap3_has_iva()) {
- omap_revision = OMAP3525_REV(rev);
- strcpy(cpu_name, "OMAP3525");
+ cpu_name = "OMAP3525";
} else if (omap3_has_sgx()) {
- omap_revision = OMAP3515_REV(rev);
- strcpy(cpu_name, "OMAP3515");
+ cpu_name = "OMAP3515";
} else {
- omap_revision = OMAP3503_REV(rev);
- strcpy(cpu_name, "OMAP3503");
- }
-
- if (cpu_is_omap3630() || cpu_is_ti816x()) {
- switch (rev) {
- case OMAP_REVBITS_00:
- strcpy(cpu_rev, "1.0");
- break;
- case OMAP_REVBITS_01:
- strcpy(cpu_rev, "1.1");
- break;
- case OMAP_REVBITS_02:
- /* FALLTHROUGH */
- default:
- /* Use the latest known revision as default */
- strcpy(cpu_rev, "1.2");
- }
- } else if (cpu_is_omap3505() || cpu_is_omap3517()) {
- switch (rev) {
- case OMAP_REVBITS_00:
- strcpy(cpu_rev, "1.0");
- break;
- case OMAP_REVBITS_01:
- /* FALLTHROUGH */
- default:
- /* Use the latest known revision as default */
- strcpy(cpu_rev, "1.1");
- }
- } else {
- switch (rev) {
- case OMAP_REVBITS_00:
- strcpy(cpu_rev, "1.0");
- break;
- case OMAP_REVBITS_01:
- strcpy(cpu_rev, "2.0");
- break;
- case OMAP_REVBITS_02:
- strcpy(cpu_rev, "2.1");
- break;
- case OMAP_REVBITS_03:
- strcpy(cpu_rev, "3.0");
- break;
- case OMAP_REVBITS_04:
- strcpy(cpu_rev, "3.1");
- break;
- case OMAP_REVBITS_05:
- /* FALLTHROUGH */
- default:
- /* Use the latest known revision as default */
- strcpy(cpu_rev, "3.1.2");
- }
+ cpu_name = "OMAP3503";
}
/* Print verbose information */
@@ -533,6 +458,8 @@ static void __init omap3_cpuinfo(void)
*/
void __init omap2_check_revision(void)
{
+ const char *cpu_rev;
+
/*
* At this point we have an idea about the processor revision set
* earlier with omap2_set_globals_tap().
@@ -540,7 +467,7 @@ void __init omap2_check_revision(void)
if (cpu_is_omap24xx()) {
omap24xx_check_revision();
} else if (cpu_is_omap34xx()) {
- omap3_check_revision();
+ omap3_check_revision(&cpu_rev);
/* TI816X doesn't have feature register */
if (!cpu_is_ti816x())
@@ -548,7 +475,7 @@ void __init omap2_check_revision(void)
else
ti816x_check_features();
- omap3_cpuinfo();
+ omap3_cpuinfo(cpu_rev);
return;
} else if (cpu_is_omap44xx()) {
omap4_check_revision();
@@ -557,22 +484,6 @@ void __init omap2_check_revision(void)
} else {
pr_err("OMAP revision unknown, please fix!\n");
}
-
- /*
- * OK, now we know the exact revision. Initialize omap_chip bits
- * for powerdowmain and clockdomain code.
- */
- if (cpu_is_omap243x()) {
- /* Currently only supports 2430ES2.1 and 2430-all */
- omap_chip.oc |= CHIP_IS_OMAP2430;
- return;
- } else if (cpu_is_omap242x()) {
- /* Currently only supports 2420ES2.1.1 and 2420-all */
- omap_chip.oc |= CHIP_IS_OMAP2420;
- return;
- }
-
- pr_err("Uninitialized omap_chip, please fix!\n");
}
/*
diff --git a/arch/arm/mach-omap2/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S
index 48adfe9fe4f3..13f98e59cfef 100644
--- a/arch/arm/mach-omap2/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap2/include/mach/debug-macro.S
@@ -13,15 +13,10 @@
#include <linux/serial_reg.h>
-#include <asm/memory.h>
-
#include <plat/serial.h>
#define UART_OFFSET(addr) ((addr) & 0x00ffffff)
-#define omap_uart_v2p(x) ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
-#define omap_uart_p2v(x) ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
-
.pushsection .data
omap_uart_phys: .word 0
omap_uart_virt: .word 0
@@ -34,26 +29,25 @@ omap_uart_lsr: .word 0
* the desired UART phys and virt addresses temporarily into
* the omap_uart_phys and omap_uart_virt above.
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
/* Use omap_uart_phys/virt if already configured */
-10: mrc p15, 0, \rp, c1, c0
- tst \rp, #1 @ MMU enabled?
- ldreq \rp, =omap_uart_v2p(omap_uart_phys) @ MMU disabled
- ldrne \rp, =omap_uart_phys @ MMU enabled
- add \rv, \rp, #4 @ omap_uart_virt
- ldr \rp, [\rp, #0]
- ldr \rv, [\rv, #0]
+10: adr \rp, 99f @ get effective addr of 99f
+ ldr \rv, [\rp] @ get absolute addr of 99f
+ sub \rv, \rv, \rp @ offset between the two
+ ldr \rp, [\rp, #4] @ abs addr of omap_uart_phys
+ sub \tmp, \rp, \rv @ make it effective
+ ldr \rp, [\tmp, #0] @ omap_uart_phys
+ ldr \rv, [\tmp, #4] @ omap_uart_virt
cmp \rp, #0 @ is port configured?
cmpne \rv, #0
- bne 99f @ already configured
+ bne 100f @ already configured
/* Check the debug UART configuration set in uncompress.h */
- mrc p15, 0, \rp, c1, c0
- tst \rp, #1 @ MMU enabled?
- ldreq \rp, =OMAP_UART_INFO @ MMU not enabled
- ldrne \rp, =omap_uart_p2v(OMAP_UART_INFO) @ MMU enabled
- ldr \rp, [\rp, #0]
+ mov \rp, pc
+ ldr \rv, =OMAP_UART_INFO_OFS
+ and \rp, \rp, #0xff000000
+ ldr \rp, [\rp, \rv]
/* Select the UART to use based on the UART1 scratchpad value */
cmp \rp, #0 @ no port configured?
@@ -106,50 +100,47 @@ omap_uart_lsr: .word 0
b 98f
83: mov \rp, #UART_OFFSET(TI816X_UART3_BASE)
b 98f
+
95: ldr \rp, =ZOOM_UART_BASE
- mrc p15, 0, \rv, c1, c0
- tst \rv, #1 @ MMU enabled?
- ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled
- ldrne \rv, =omap_uart_phys @ MMU enabled
- str \rp, [\rv, #0]
+ str \rp, [\tmp, #0] @ omap_uart_phys
ldr \rp, =ZOOM_UART_VIRT
- add \rv, \rv, #4 @ omap_uart_virt
- str \rp, [\rv, #0]
+ str \rp, [\tmp, #4] @ omap_uart_virt
mov \rp, #(UART_LSR << ZOOM_PORT_SHIFT)
- add \rv, \rv, #4 @ omap_uart_lsr
- str \rp, [\rv, #0]
+ str \rp, [\tmp, #8] @ omap_uart_lsr
b 10b
/* Store both phys and virt address for the uart */
98: add \rp, \rp, #0x48000000 @ phys base
- mrc p15, 0, \rv, c1, c0
- tst \rv, #1 @ MMU enabled?
- ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled
- ldrne \rv, =omap_uart_phys @ MMU enabled
- str \rp, [\rv, #0]
+ str \rp, [\tmp, #0] @ omap_uart_phys
sub \rp, \rp, #0x48000000 @ phys base
add \rp, \rp, #0xfa000000 @ virt base
- add \rv, \rv, #4 @ omap_uart_virt
- str \rp, [\rv, #0]
+ str \rp, [\tmp, #4] @ omap_uart_virt
mov \rp, #(UART_LSR << OMAP_PORT_SHIFT)
- add \rv, \rv, #4 @ omap_uart_lsr
- str \rp, [\rv, #0]
+ str \rp, [\tmp, #8] @ omap_uart_lsr
b 10b
-99:
+
+ .align
+99: .word .
+ .word omap_uart_phys
+ .ltorg
+
+100: /* Pass the UART_LSR reg address */
+ ldr \tmp, [\tmp, #8] @ omap_uart_lsr
+ add \rp, \rp, \tmp
+ add \rv, \rv, \tmp
.endm
.macro senduart,rd,rx
- strb \rd, [\rx]
+ orr \rd, \rd, \rx, lsl #24 @ preserve LSR reg offset
+ bic \rx, \rx, #0xff @ get base (THR) reg address
+ strb \rd, [\rx] @ send lower byte of rd
+ orr \rx, \rx, \rd, lsr #24 @ restore original rx (LSR)
+ bic \rd, \rd, #(0xff << 24) @ restore original rd
.endm
.macro busyuart,rd,rx
-1001: mrc p15, 0, \rd, c1, c0
- tst \rd, #1 @ MMU enabled?
- ldreq \rd, =omap_uart_v2p(omap_uart_lsr) @ MMU disabled
- ldrne \rd, =omap_uart_lsr @ MMU enabled
- ldr \rd, [\rd, #0]
- ldrb \rd, [\rx, \rd]
+1001: ldrb \rd, [\rx] @ rx contains UART_LSR address
and \rd, \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
teq \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
bne 1001b
diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S
index ceb8b7e593d7..feb90a10945a 100644
--- a/arch/arm/mach-omap2/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap2/include/mach/entry-macro.S
@@ -78,7 +78,7 @@
4401: ldr \irqstat, [\base, #GIC_CPU_INTACK]
ldr \tmp, =1021
bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #29
+ cmp \irqnr, #15
cmpcc \irqnr, \irqnr
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
@@ -101,18 +101,6 @@
it cs
cmpcs \irqnr, \irqnr
.endm
-
- /* As above, this assumes that irqstat and base are preserved */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #29
- itt eq
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
#endif /* CONFIG_SMP */
#else /* MULTI_OMAP2 */
diff --git a/arch/arm/mach-omap2/include/mach/memory.h b/arch/arm/mach-omap2/include/mach/memory.h
deleted file mode 100644
index ca6d32a917dd..000000000000
--- a/arch/arm/mach-omap2/include/mach/memory.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap2/include/mach/memory.h
- */
-
-#include <plat/memory.h>
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 2ce1ce6fb4db..a5d8dce2a70b 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -16,7 +16,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -35,14 +34,16 @@
#include "clock2xxx.h"
#include "clock3xxx.h"
#include "clock44xx.h"
-#include "io.h"
+#include <plat/common.h>
#include <plat/omap-pm.h>
+#include "voltage.h"
#include "powerdomain.h"
#include "clockdomain.h"
#include <plat/omap_hwmod.h>
#include <plat/multi.h>
+#include <plat/common.h>
/*
* The machine specific code may provide the extra mapping besides the
@@ -239,25 +240,11 @@ static struct map_desc omap44xx_io_desc[] __initdata = {
};
#endif
-static void __init _omap2_map_common_io(void)
-{
- /* Normally devicemaps_init() would flush caches and tlb after
- * mdesc->map_io(), but we must also do it here because of the CPU
- * revision check below.
- */
- local_flush_tlb_all();
- flush_cache_all();
-
- omap2_check_revision();
- omap_sram_init();
-}
-
#ifdef CONFIG_SOC_OMAP2420
void __init omap242x_map_common_io(void)
{
iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc));
- _omap2_map_common_io();
}
#endif
@@ -266,7 +253,6 @@ void __init omap243x_map_common_io(void)
{
iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc));
- _omap2_map_common_io();
}
#endif
@@ -274,7 +260,6 @@ void __init omap243x_map_common_io(void)
void __init omap34xx_map_common_io(void)
{
iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc));
- _omap2_map_common_io();
}
#endif
@@ -282,7 +267,6 @@ void __init omap34xx_map_common_io(void)
void __init omapti816x_map_common_io(void)
{
iotable_init(omapti816x_io_desc, ARRAY_SIZE(omapti816x_io_desc));
- _omap2_map_common_io();
}
#endif
@@ -290,7 +274,6 @@ void __init omapti816x_map_common_io(void)
void __init omap44xx_map_common_io(void)
{
iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc));
- _omap2_map_common_io();
}
#endif
@@ -336,29 +319,16 @@ static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
/* See irq.c, omap4-common.c and entry-macro.S */
void __iomem *omap_irq_base;
-void __init omap2_init_common_infrastructure(void)
+static void __init omap_common_init_early(void)
{
- u8 postsetup_state;
+ omap2_check_revision();
+ omap_ioremap_init();
+ omap_init_consistent_dma_size();
+}
- if (cpu_is_omap242x()) {
- omap2xxx_powerdomains_init();
- omap2xxx_clockdomains_init();
- omap2420_hwmod_init();
- } else if (cpu_is_omap243x()) {
- omap2xxx_powerdomains_init();
- omap2xxx_clockdomains_init();
- omap2430_hwmod_init();
- } else if (cpu_is_omap34xx()) {
- omap3xxx_powerdomains_init();
- omap3xxx_clockdomains_init();
- omap3xxx_hwmod_init();
- } else if (cpu_is_omap44xx()) {
- omap44xx_powerdomains_init();
- omap44xx_clockdomains_init();
- omap44xx_hwmod_init();
- } else {
- pr_err("Could not init hwmod data - unknown SoC\n");
- }
+static void __init omap_hwmod_init_postsetup(void)
+{
+ u8 postsetup_state;
/* Set the default postsetup state for all hwmods */
#ifdef CONFIG_PM_RUNTIME
@@ -376,7 +346,7 @@ void __init omap2_init_common_infrastructure(void)
* omap_hwmod_late_init(), so boards that desire full watchdog
* coverage of kernel initialization can reprogram the
* postsetup_state between the calls to
- * omap2_init_common_infra() and omap2_init_common_devices().
+ * omap2_init_common_infra() and omap_sdrc_init().
*
* XXX ideally we could detect whether the MPU WDT was currently
* enabled here and make this conditional
@@ -387,27 +357,101 @@ void __init omap2_init_common_infrastructure(void)
&postsetup_state);
omap_pm_if_early_init();
+}
+
+void __init omap2420_init_early(void)
+{
+ omap2_set_globals_242x();
+ omap_common_init_early();
+ omap2xxx_voltagedomains_init();
+ omap242x_powerdomains_init();
+ omap242x_clockdomains_init();
+ omap2420_hwmod_init();
+ omap_hwmod_init_postsetup();
+ omap2420_clk_init();
+}
+
+void __init omap2430_init_early(void)
+{
+ omap2_set_globals_243x();
+ omap_common_init_early();
+ omap2xxx_voltagedomains_init();
+ omap243x_powerdomains_init();
+ omap243x_clockdomains_init();
+ omap2430_hwmod_init();
+ omap_hwmod_init_postsetup();
+ omap2430_clk_init();
+}
+
+/*
+ * Currently only board-omap3beagle.c should call this because of the
+ * same machine_id for 34xx and 36xx beagle.. Will get fixed with DT.
+ */
+void __init omap3_init_early(void)
+{
+ omap2_set_globals_3xxx();
+ omap_common_init_early();
+ omap3xxx_voltagedomains_init();
+ omap3xxx_powerdomains_init();
+ omap3xxx_clockdomains_init();
+ omap3xxx_hwmod_init();
+ omap_hwmod_init_postsetup();
+ omap3xxx_clk_init();
+}
+
+void __init omap3430_init_early(void)
+{
+ omap3_init_early();
+}
+
+void __init omap35xx_init_early(void)
+{
+ omap3_init_early();
+}
+
+void __init omap3630_init_early(void)
+{
+ omap3_init_early();
+}
+
+void __init am35xx_init_early(void)
+{
+ omap3_init_early();
+}
- if (cpu_is_omap2420())
- omap2420_clk_init();
- else if (cpu_is_omap2430())
- omap2430_clk_init();
- else if (cpu_is_omap34xx())
- omap3xxx_clk_init();
- else if (cpu_is_omap44xx())
- omap4xxx_clk_init();
- else
- pr_err("Could not init clock framework - unknown SoC\n");
+void __init ti816x_init_early(void)
+{
+ omap2_set_globals_ti816x();
+ omap_common_init_early();
+ omap3xxx_voltagedomains_init();
+ omap3xxx_powerdomains_init();
+ omap3xxx_clockdomains_init();
+ omap3xxx_hwmod_init();
+ omap_hwmod_init_postsetup();
+ omap3xxx_clk_init();
}
-void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
+void __init omap4430_init_early(void)
+{
+ omap2_set_globals_443x();
+ omap_common_init_early();
+ omap44xx_voltagedomains_init();
+ omap44xx_powerdomains_init();
+ omap44xx_clockdomains_init();
+ omap44xx_hwmod_init();
+ omap_hwmod_init_postsetup();
+ omap4xxx_clk_init();
+}
+
+void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
struct omap_sdrc_params *sdrc_cs1)
{
+ omap_sram_init();
+
if (cpu_is_omap24xx() || omap3_has_sdrc()) {
omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
_omap2_init_reprogram_sdrc();
}
-
}
/*
diff --git a/arch/arm/mach-omap2/io.h b/arch/arm/mach-omap2/io.h
index fd230c6cded5..e69de29bb2d1 100644
--- a/arch/arm/mach-omap2/io.h
+++ b/arch/arm/mach-omap2/io.h
@@ -1,7 +0,0 @@
-
-#ifndef __MACH_OMAP2_IO_H__
-#define __MACH_OMAP2_IO_H__
-
-extern int __init omap_sram_init(void);
-
-#endif /* __MACH_OMAP2_IO_H__ */
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index f286012783c6..eefc37912ef3 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -66,7 +66,7 @@
((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0)
-static void __iommu_set_twl(struct iommu *obj, bool on)
+static void __iommu_set_twl(struct omap_iommu *obj, bool on)
{
u32 l = iommu_read_reg(obj, MMU_CNTL);
@@ -85,7 +85,7 @@ static void __iommu_set_twl(struct iommu *obj, bool on)
}
-static int omap2_iommu_enable(struct iommu *obj)
+static int omap2_iommu_enable(struct omap_iommu *obj)
{
u32 l, pa;
unsigned long timeout;
@@ -127,7 +127,7 @@ static int omap2_iommu_enable(struct iommu *obj)
return 0;
}
-static void omap2_iommu_disable(struct iommu *obj)
+static void omap2_iommu_disable(struct omap_iommu *obj)
{
u32 l = iommu_read_reg(obj, MMU_CNTL);
@@ -138,12 +138,12 @@ static void omap2_iommu_disable(struct iommu *obj)
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
-static void omap2_iommu_set_twl(struct iommu *obj, bool on)
+static void omap2_iommu_set_twl(struct omap_iommu *obj, bool on)
{
__iommu_set_twl(obj, false);
}
-static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
+static u32 omap2_iommu_fault_isr(struct omap_iommu *obj, u32 *ra)
{
u32 stat, da;
u32 errs = 0;
@@ -173,13 +173,13 @@ static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
return errs;
}
-static void omap2_tlb_read_cr(struct iommu *obj, struct cr_regs *cr)
+static void omap2_tlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
{
cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
}
-static void omap2_tlb_load_cr(struct iommu *obj, struct cr_regs *cr)
+static void omap2_tlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
{
iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
iommu_write_reg(obj, cr->ram, MMU_RAM);
@@ -193,7 +193,8 @@ static u32 omap2_cr_to_virt(struct cr_regs *cr)
return cr->cam & mask;
}
-static struct cr_regs *omap2_alloc_cr(struct iommu *obj, struct iotlb_entry *e)
+static struct cr_regs *omap2_alloc_cr(struct omap_iommu *obj,
+ struct iotlb_entry *e)
{
struct cr_regs *cr;
@@ -230,7 +231,8 @@ static u32 omap2_get_pte_attr(struct iotlb_entry *e)
return attr;
}
-static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
+static ssize_t
+omap2_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, char *buf)
{
char *p = buf;
@@ -254,7 +256,8 @@ static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
goto out; \
} while (0)
-static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len)
+static ssize_t
+omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
{
char *p = buf;
@@ -280,7 +283,7 @@ out:
return p - buf;
}
-static void omap2_iommu_save_ctx(struct iommu *obj)
+static void omap2_iommu_save_ctx(struct omap_iommu *obj)
{
int i;
u32 *p = obj->ctx;
@@ -293,7 +296,7 @@ static void omap2_iommu_save_ctx(struct iommu *obj)
BUG_ON(p[0] != IOMMU_ARCH_VERSION);
}
-static void omap2_iommu_restore_ctx(struct iommu *obj)
+static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
{
int i;
u32 *p = obj->ctx;
@@ -343,13 +346,13 @@ static const struct iommu_functions omap2_iommu_ops = {
static int __init omap2_iommu_init(void)
{
- return install_iommu_arch(&omap2_iommu_ops);
+ return omap_install_iommu_arch(&omap2_iommu_ops);
}
module_init(omap2_iommu_init);
static void __exit omap2_iommu_exit(void)
{
- uninstall_iommu_arch(&omap2_iommu_ops);
+ omap_uninstall_iommu_arch(&omap2_iommu_ops);
}
module_exit(omap2_iommu_exit);
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 3a12f7586a4c..65f1be6a182c 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -165,8 +165,8 @@ static void __init omap_init_irq(u32 base, int nr_irqs)
omap_irq_bank_init_one(bank);
- for (i = 0, j = 0; i < bank->nr_irqs; i += 32, j += 0x20)
- omap_alloc_gc(bank->base_reg + j, i, 32);
+ for (j = 0; j < bank->nr_irqs; j += 32)
+ omap_alloc_gc(bank->base_reg + j, j, 32);
nr_of_irqs += bank->nr_irqs;
nr_banks++;
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 4a6ef6ab8458..292eee3be15f 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -27,66 +27,69 @@
#include "control.h"
-/* McBSP internal signal muxing functions */
+/*
+ * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle.
+ * Sidetone needs non-gated ICLK and sidetone autoidle is broken.
+ */
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-34xx.h"
-void omap2_mcbsp1_mux_clkr_src(u8 mux)
+/* McBSP internal signal muxing function */
+static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal,
+ const char *src)
{
u32 v;
v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
- if (mux == CLKR_SRC_CLKR)
- v &= ~OMAP2_MCBSP1_CLKR_MASK;
- else if (mux == CLKR_SRC_CLKX)
- v |= OMAP2_MCBSP1_CLKR_MASK;
- omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
-}
-EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
-void omap2_mcbsp1_mux_fsr_src(u8 mux)
-{
- u32 v;
+ if (!strcmp(signal, "clkr")) {
+ if (!strcmp(src, "clkr"))
+ v &= ~OMAP2_MCBSP1_CLKR_MASK;
+ else if (!strcmp(src, "clkx"))
+ v |= OMAP2_MCBSP1_CLKR_MASK;
+ else
+ return -EINVAL;
+ } else if (!strcmp(signal, "fsr")) {
+ if (!strcmp(src, "fsr"))
+ v &= ~OMAP2_MCBSP1_FSR_MASK;
+ else if (!strcmp(src, "fsx"))
+ v |= OMAP2_MCBSP1_FSR_MASK;
+ else
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
- v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
- if (mux == FSR_SRC_FSR)
- v &= ~OMAP2_MCBSP1_FSR_MASK;
- else if (mux == FSR_SRC_FSX)
- v |= OMAP2_MCBSP1_FSR_MASK;
omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
+
+ return 0;
}
-EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
/* McBSP CLKS source switching function */
-
-int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk,
+ const char *src)
{
- struct omap_mcbsp *mcbsp;
struct clk *fck_src;
char *fck_src_name;
int r;
- if (!omap_mcbsp_check_valid_id(id)) {
- pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
- return -EINVAL;
- }
- mcbsp = id_to_mcbsp_ptr(id);
-
- if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+ if (!strcmp(src, "clks_ext"))
fck_src_name = "pad_fck";
- else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+ else if (!strcmp(src, "clks_fclk"))
fck_src_name = "prcm_fck";
else
return -EINVAL;
- fck_src = clk_get(mcbsp->dev, fck_src_name);
+ fck_src = clk_get(dev, fck_src_name);
if (IS_ERR_OR_NULL(fck_src)) {
pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks",
fck_src_name);
return -EINVAL;
}
- pm_runtime_put_sync(mcbsp->dev);
+ pm_runtime_put_sync(dev);
- r = clk_set_parent(mcbsp->fclk, fck_src);
+ r = clk_set_parent(clk, fck_src);
if (IS_ERR_VALUE(r)) {
pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n",
"clks", fck_src_name);
@@ -94,21 +97,30 @@ int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
return -EINVAL;
}
- pm_runtime_get_sync(mcbsp->dev);
+ pm_runtime_get_sync(dev);
clk_put(fck_src);
return 0;
}
-EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
-struct omap_device_pm_latency omap2_mcbsp_latency[] = {
- {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
-};
+static int omap3_enable_st_clock(unsigned int id, bool enable)
+{
+ unsigned int w;
+
+ /*
+ * Sidetone uses McBSP ICLK - which must not idle when sidetones
+ * are enabled or sidetones start sounding ugly.
+ */
+ w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+ if (enable)
+ w &= ~(1 << (id - 2));
+ else
+ w |= 1 << (id - 2);
+ omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+
+ return 0;
+}
static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
{
@@ -116,7 +128,7 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
char *name = "omap-mcbsp";
struct omap_hwmod *oh_device[2];
struct omap_mcbsp_platform_data *pdata = NULL;
- struct omap_device *od;
+ struct platform_device *pdev;
sscanf(oh->name, "mcbsp%d", &id);
@@ -126,7 +138,13 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
return -ENOMEM;
}
- pdata->mcbsp_config_type = oh->class->rev;
+ pdata->reg_step = 4;
+ if (oh->class->rev < MCBSP_CONFIG_TYPE2) {
+ pdata->reg_size = 2;
+ } else {
+ pdata->reg_size = 4;
+ pdata->has_ccr = true;
+ }
if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
if (id == 2)
@@ -137,22 +155,28 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
pdata->buffer_size = 0x80;
}
+ if (oh->class->rev >= MCBSP_CONFIG_TYPE3)
+ pdata->has_wakeup = true;
+
oh_device[0] = oh;
if (oh->dev_attr) {
oh_device[1] = omap_hwmod_lookup((
(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
+ pdata->enable_st_clock = omap3_enable_st_clock;
count++;
}
- od = omap_device_build_ss(name, id, oh_device, count, pdata,
- sizeof(*pdata), omap2_mcbsp_latency,
- ARRAY_SIZE(omap2_mcbsp_latency), false);
+ pdev = omap_device_build_ss(name, id, oh_device, count, pdata,
+ sizeof(*pdata), NULL, 0, false);
kfree(pdata);
- if (IS_ERR(od)) {
+ if (IS_ERR(pdev)) {
pr_err("%s: Can't build omap_device for %s:%s.\n", __func__,
name, oh->name);
- return PTR_ERR(od);
+ return PTR_ERR(pdev);
}
+ pdata->set_clk_src = omap2_mcbsp_set_clk_src;
+ if (id == 1)
+ pdata->mux_signal = omap2_mcbsp1_mux_rx_clk;
omap_mcbsp_count++;
return 0;
}
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index ce65e9329c7b..4412ddb7b3f6 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -102,19 +102,20 @@ void __init smp_init_cpus(void)
{
unsigned int i, ncores;
- /* Never released */
- scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256);
+ /*
+ * Currently we can't call ioremap here because
+ * SoC detection won't work until after init_early.
+ */
+ scu_base = OMAP2_L4_IO_ADDRESS(OMAP44XX_SCU_BASE);
BUG_ON(!scu_base);
ncores = scu_get_core_count(scu_base);
/* sanity check */
- if (ncores > NR_CPUS) {
- printk(KERN_WARNING
- "OMAP4: no. of cores (%d) greater than configured "
- "maximum of %d - clipping\n",
- ncores, NR_CPUS);
- ncores = NR_CPUS;
+ if (ncores > nr_cpu_ids) {
+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+ ncores, nr_cpu_ids);
+ ncores = nr_cpu_ids;
}
for (i = 0; i < ncores; i++)
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 84cc0bdda3ae..d71380705080 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1954,9 +1954,6 @@ int __init omap_hwmod_register(struct omap_hwmod **ohs)
i = 0;
do {
- if (!omap_chip_is(ohs[i]->omap_chip))
- continue;
-
r = _register(ohs[i]);
WARN(r, "omap_hwmod: %s: _register returned %d\n", ohs[i]->name,
r);
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index a015c69068f6..6d7206213525 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -100,7 +100,6 @@ static struct omap_hwmod omap2420_l3_main_hwmod = {
.masters_cnt = ARRAY_SIZE(omap2420_l3_main_masters),
.slaves = omap2420_l3_main_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_l3_main_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
.flags = HWMOD_NO_IDLEST,
};
@@ -206,7 +205,6 @@ static struct omap_hwmod omap2420_l4_core_hwmod = {
.masters_cnt = ARRAY_SIZE(omap2420_l4_core_masters),
.slaves = omap2420_l4_core_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_l4_core_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
.flags = HWMOD_NO_IDLEST,
};
@@ -227,7 +225,6 @@ static struct omap_hwmod omap2420_l4_wkup_hwmod = {
.masters_cnt = ARRAY_SIZE(omap2420_l4_wkup_masters),
.slaves = omap2420_l4_wkup_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_l4_wkup_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
.flags = HWMOD_NO_IDLEST,
};
@@ -243,7 +240,6 @@ static struct omap_hwmod omap2420_mpu_hwmod = {
.main_clk = "mpu_ck",
.masters = omap2420_mpu_masters,
.masters_cnt = ARRAY_SIZE(omap2420_mpu_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/*
@@ -271,7 +267,16 @@ static struct omap_hwmod omap2420_iva_hwmod = {
.class = &iva_hwmod_class,
.masters = omap2420_iva_masters,
.masters_cnt = ARRAY_SIZE(omap2420_iva_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+ .timer_capability = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+ .timer_capability = OMAP_TIMER_HAS_PWM,
};
/* timer1 */
@@ -314,10 +319,10 @@ static struct omap_hwmod omap2420_timer1_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2420_timer1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer1_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer2 */
@@ -351,10 +356,10 @@ static struct omap_hwmod omap2420_timer2_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2420_timer2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer2_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer3 */
@@ -388,10 +393,10 @@ static struct omap_hwmod omap2420_timer3_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2420_timer3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer3_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer4 */
@@ -425,10 +430,10 @@ static struct omap_hwmod omap2420_timer4_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2420_timer4_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer4_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer5 */
@@ -462,10 +467,10 @@ static struct omap_hwmod omap2420_timer5_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2420_timer5_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer5_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
@@ -500,10 +505,10 @@ static struct omap_hwmod omap2420_timer6_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2420_timer6_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer6_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer7 */
@@ -537,10 +542,10 @@ static struct omap_hwmod omap2420_timer7_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2420_timer7_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer7_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer8 */
@@ -574,10 +579,10 @@ static struct omap_hwmod omap2420_timer8_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2420_timer8_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer8_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer9 */
@@ -611,10 +616,10 @@ static struct omap_hwmod omap2420_timer9_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap2420_timer9_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer9_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer10 */
@@ -648,10 +653,10 @@ static struct omap_hwmod omap2420_timer10_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap2420_timer10_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer10_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer11 */
@@ -685,10 +690,10 @@ static struct omap_hwmod omap2420_timer11_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap2420_timer11_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer11_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* timer12 */
@@ -722,10 +727,10 @@ static struct omap_hwmod omap2420_timer12_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap2420_timer12_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_timer12_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
};
/* l4_wkup -> wd_timer2 */
@@ -766,7 +771,6 @@ static struct omap_hwmod omap2420_wd_timer2_hwmod = {
},
.slaves = omap2420_wd_timer2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_wd_timer2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* UART1 */
@@ -792,7 +796,6 @@ static struct omap_hwmod omap2420_uart1_hwmod = {
.slaves = omap2420_uart1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_uart1_slaves),
.class = &omap2_uart_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* UART2 */
@@ -818,7 +821,6 @@ static struct omap_hwmod omap2420_uart2_hwmod = {
.slaves = omap2420_uart2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_uart2_slaves),
.class = &omap2_uart_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* UART3 */
@@ -844,7 +846,6 @@ static struct omap_hwmod omap2420_uart3_hwmod = {
.slaves = omap2420_uart3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_uart3_slaves),
.class = &omap2_uart_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* dss */
@@ -898,7 +899,6 @@ static struct omap_hwmod omap2420_dss_core_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2420_dss_slaves),
.masters = omap2420_dss_masters,
.masters_cnt = ARRAY_SIZE(omap2420_dss_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
.flags = HWMOD_NO_IDLEST,
};
@@ -938,7 +938,6 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = {
},
.slaves = omap2420_dss_dispc_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_dss_dispc_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
.flags = HWMOD_NO_IDLEST,
};
@@ -975,7 +974,6 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
},
.slaves = omap2420_dss_rfbi_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_dss_rfbi_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
.flags = HWMOD_NO_IDLEST,
};
@@ -1013,7 +1011,6 @@ static struct omap_hwmod omap2420_dss_venc_hwmod = {
},
.slaves = omap2420_dss_venc_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_dss_venc_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
.flags = HWMOD_NO_IDLEST,
};
@@ -1064,7 +1061,6 @@ static struct omap_hwmod omap2420_i2c1_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2420_i2c1_slaves),
.class = &i2c_class,
.dev_attr = &i2c_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
.flags = HWMOD_16BIT_REG,
};
@@ -1092,7 +1088,6 @@ static struct omap_hwmod omap2420_i2c2_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2420_i2c2_slaves),
.class = &i2c_class,
.dev_attr = &i2c_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
.flags = HWMOD_16BIT_REG,
};
@@ -1197,7 +1192,6 @@ static struct omap_hwmod omap2420_gpio1_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2420_gpio1_slaves),
.class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* gpio2 */
@@ -1223,7 +1217,6 @@ static struct omap_hwmod omap2420_gpio2_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2420_gpio2_slaves),
.class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* gpio3 */
@@ -1249,7 +1242,6 @@ static struct omap_hwmod omap2420_gpio3_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2420_gpio3_slaves),
.class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* gpio4 */
@@ -1275,7 +1267,6 @@ static struct omap_hwmod omap2420_gpio4_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2420_gpio4_slaves),
.class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* dma attributes */
@@ -1322,7 +1313,6 @@ static struct omap_hwmod omap2420_dma_system_hwmod = {
.masters = omap2420_dma_system_masters,
.masters_cnt = ARRAY_SIZE(omap2420_dma_system_masters),
.dev_attr = &dma_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
.flags = HWMOD_NO_IDLEST,
};
@@ -1363,7 +1353,6 @@ static struct omap_hwmod omap2420_mailbox_hwmod = {
},
.slaves = omap2420_mailbox_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_mailbox_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* mcspi1 */
@@ -1393,7 +1382,6 @@ static struct omap_hwmod omap2420_mcspi1_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2420_mcspi1_slaves),
.class = &omap2xxx_mcspi_class,
.dev_attr = &omap_mcspi1_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* mcspi2 */
@@ -1423,7 +1411,6 @@ static struct omap_hwmod omap2420_mcspi2_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2420_mcspi2_slaves),
.class = &omap2xxx_mcspi_class,
.dev_attr = &omap_mcspi2_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/*
@@ -1473,7 +1460,6 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod = {
},
.slaves = omap2420_mcbsp1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_mcbsp1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
/* mcbsp2 */
@@ -1514,7 +1500,6 @@ static struct omap_hwmod omap2420_mcbsp2_hwmod = {
},
.slaves = omap2420_mcbsp2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2420_mcbsp2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
static __initdata struct omap_hwmod *omap2420_hwmods[] = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 408193d8e044..a2580d01c3ff 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -110,7 +110,6 @@ static struct omap_hwmod omap2430_l3_main_hwmod = {
.masters_cnt = ARRAY_SIZE(omap2430_l3_main_masters),
.slaves = omap2430_l3_main_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_l3_main_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
.flags = HWMOD_NO_IDLEST,
};
@@ -250,7 +249,6 @@ static struct omap_hwmod omap2430_l4_core_hwmod = {
.masters_cnt = ARRAY_SIZE(omap2430_l4_core_masters),
.slaves = omap2430_l4_core_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_l4_core_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
.flags = HWMOD_NO_IDLEST,
};
@@ -301,7 +299,6 @@ static struct omap_hwmod omap2430_l4_wkup_hwmod = {
.masters_cnt = ARRAY_SIZE(omap2430_l4_wkup_masters),
.slaves = omap2430_l4_wkup_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_l4_wkup_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
.flags = HWMOD_NO_IDLEST,
};
@@ -317,7 +314,6 @@ static struct omap_hwmod omap2430_mpu_hwmod = {
.main_clk = "mpu_ck",
.masters = omap2430_mpu_masters,
.masters_cnt = ARRAY_SIZE(omap2430_mpu_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/*
@@ -345,7 +341,16 @@ static struct omap_hwmod omap2430_iva_hwmod = {
.class = &iva_hwmod_class,
.masters = omap2430_iva_masters,
.masters_cnt = ARRAY_SIZE(omap2430_iva_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+ .timer_capability = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+ .timer_capability = OMAP_TIMER_HAS_PWM,
};
/* timer1 */
@@ -388,10 +393,10 @@ static struct omap_hwmod omap2430_timer1_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2430_timer1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer1_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer2 */
@@ -425,10 +430,10 @@ static struct omap_hwmod omap2430_timer2_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2430_timer2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer2_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer3 */
@@ -462,10 +467,10 @@ static struct omap_hwmod omap2430_timer3_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2430_timer3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer3_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer4 */
@@ -499,10 +504,10 @@ static struct omap_hwmod omap2430_timer4_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2430_timer4_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer4_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer5 */
@@ -536,10 +541,10 @@ static struct omap_hwmod omap2430_timer5_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2430_timer5_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer5_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer6 */
@@ -573,10 +578,10 @@ static struct omap_hwmod omap2430_timer6_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2430_timer6_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer6_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer7 */
@@ -610,10 +615,10 @@ static struct omap_hwmod omap2430_timer7_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2430_timer7_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer7_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer8 */
@@ -647,10 +652,10 @@ static struct omap_hwmod omap2430_timer8_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap2430_timer8_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer8_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer9 */
@@ -684,10 +689,10 @@ static struct omap_hwmod omap2430_timer9_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap2430_timer9_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer9_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer10 */
@@ -721,10 +726,10 @@ static struct omap_hwmod omap2430_timer10_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap2430_timer10_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer10_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer11 */
@@ -758,10 +763,10 @@ static struct omap_hwmod omap2430_timer11_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap2430_timer11_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer11_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* timer12 */
@@ -795,10 +800,10 @@ static struct omap_hwmod omap2430_timer12_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap2430_timer12_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_timer12_slaves),
.class = &omap2xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/* l4_wkup -> wd_timer2 */
@@ -839,7 +844,6 @@ static struct omap_hwmod omap2430_wd_timer2_hwmod = {
},
.slaves = omap2430_wd_timer2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_wd_timer2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* UART1 */
@@ -865,7 +869,6 @@ static struct omap_hwmod omap2430_uart1_hwmod = {
.slaves = omap2430_uart1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_uart1_slaves),
.class = &omap2_uart_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* UART2 */
@@ -891,7 +894,6 @@ static struct omap_hwmod omap2430_uart2_hwmod = {
.slaves = omap2430_uart2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_uart2_slaves),
.class = &omap2_uart_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* UART3 */
@@ -917,7 +919,6 @@ static struct omap_hwmod omap2430_uart3_hwmod = {
.slaves = omap2430_uart3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_uart3_slaves),
.class = &omap2_uart_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* dss */
@@ -965,7 +966,6 @@ static struct omap_hwmod omap2430_dss_core_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_dss_slaves),
.masters = omap2430_dss_masters,
.masters_cnt = ARRAY_SIZE(omap2430_dss_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
.flags = HWMOD_NO_IDLEST,
};
@@ -999,7 +999,6 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = {
},
.slaves = omap2430_dss_dispc_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_dss_dispc_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
.flags = HWMOD_NO_IDLEST,
};
@@ -1030,7 +1029,6 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
},
.slaves = omap2430_dss_rfbi_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_dss_rfbi_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
.flags = HWMOD_NO_IDLEST,
};
@@ -1062,7 +1060,6 @@ static struct omap_hwmod omap2430_dss_venc_hwmod = {
},
.slaves = omap2430_dss_venc_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_dss_venc_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
.flags = HWMOD_NO_IDLEST,
};
@@ -1123,7 +1120,6 @@ static struct omap_hwmod omap2430_i2c1_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_i2c1_slaves),
.class = &i2c_class,
.dev_attr = &i2c_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* I2C2 */
@@ -1151,7 +1147,6 @@ static struct omap_hwmod omap2430_i2c2_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_i2c2_slaves),
.class = &i2c_class,
.dev_attr = &i2c_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* l4_wkup -> gpio1 */
@@ -1273,7 +1268,6 @@ static struct omap_hwmod omap2430_gpio1_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_gpio1_slaves),
.class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* gpio2 */
@@ -1299,7 +1293,6 @@ static struct omap_hwmod omap2430_gpio2_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_gpio2_slaves),
.class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* gpio3 */
@@ -1325,7 +1318,6 @@ static struct omap_hwmod omap2430_gpio3_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_gpio3_slaves),
.class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* gpio4 */
@@ -1351,7 +1343,6 @@ static struct omap_hwmod omap2430_gpio4_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_gpio4_slaves),
.class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* gpio5 */
@@ -1382,7 +1373,6 @@ static struct omap_hwmod omap2430_gpio5_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_gpio5_slaves),
.class = &omap2xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* dma attributes */
@@ -1429,7 +1419,6 @@ static struct omap_hwmod omap2430_dma_system_hwmod = {
.masters = omap2430_dma_system_masters,
.masters_cnt = ARRAY_SIZE(omap2430_dma_system_masters),
.dev_attr = &dma_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
.flags = HWMOD_NO_IDLEST,
};
@@ -1469,7 +1458,6 @@ static struct omap_hwmod omap2430_mailbox_hwmod = {
},
.slaves = omap2430_mailbox_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mailbox_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* mcspi1 */
@@ -1499,7 +1487,6 @@ static struct omap_hwmod omap2430_mcspi1_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_mcspi1_slaves),
.class = &omap2xxx_mcspi_class,
.dev_attr = &omap_mcspi1_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* mcspi2 */
@@ -1529,7 +1516,6 @@ static struct omap_hwmod omap2430_mcspi2_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_mcspi2_slaves),
.class = &omap2xxx_mcspi_class,
.dev_attr = &omap_mcspi2_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* mcspi3 */
@@ -1572,7 +1558,6 @@ static struct omap_hwmod omap2430_mcspi3_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap2430_mcspi3_slaves),
.class = &omap2xxx_mcspi_class,
.dev_attr = &omap_mcspi3_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/*
@@ -1628,7 +1613,6 @@ static struct omap_hwmod omap2430_usbhsotg_hwmod = {
*/
.flags = HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
| HWMOD_SWSUP_MSTANDBY,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
};
/*
@@ -1689,7 +1673,6 @@ static struct omap_hwmod omap2430_mcbsp1_hwmod = {
},
.slaves = omap2430_mcbsp1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mcbsp1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* mcbsp2 */
@@ -1731,7 +1714,6 @@ static struct omap_hwmod omap2430_mcbsp2_hwmod = {
},
.slaves = omap2430_mcbsp2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mcbsp2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* mcbsp3 */
@@ -1783,7 +1765,6 @@ static struct omap_hwmod omap2430_mcbsp3_hwmod = {
},
.slaves = omap2430_mcbsp3_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mcbsp3_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* mcbsp4 */
@@ -1841,7 +1822,6 @@ static struct omap_hwmod omap2430_mcbsp4_hwmod = {
},
.slaves = omap2430_mcbsp4_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mcbsp4_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* mcbsp5 */
@@ -1899,7 +1879,6 @@ static struct omap_hwmod omap2430_mcbsp5_hwmod = {
},
.slaves = omap2430_mcbsp5_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mcbsp5_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* MMC/SD/SDIO common */
@@ -1966,7 +1945,6 @@ static struct omap_hwmod omap2430_mmc1_hwmod = {
.slaves = omap2430_mmc1_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mmc1_slaves),
.class = &omap2430_mmc_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* MMC/SD/SDIO2 */
@@ -2010,7 +1988,6 @@ static struct omap_hwmod omap2430_mmc2_hwmod = {
.slaves = omap2430_mmc2_slaves,
.slaves_cnt = ARRAY_SIZE(omap2430_mmc2_slaves),
.class = &omap2430_mmc_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
static __initdata struct omap_hwmod *omap2430_hwmods[] = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 25bf43b5a4ec..3008e1672c7a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -156,7 +156,6 @@ static struct omap_hwmod omap3xxx_l3_main_hwmod = {
.masters_cnt = ARRAY_SIZE(omap3xxx_l3_main_masters),
.slaves = omap3xxx_l3_main_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_l3_main_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.flags = HWMOD_NO_IDLEST,
};
@@ -459,7 +458,6 @@ static struct omap_hwmod omap3xxx_l4_core_hwmod = {
.class = &l4_hwmod_class,
.slaves = omap3xxx_l4_core_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_l4_core_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.flags = HWMOD_NO_IDLEST,
};
@@ -474,7 +472,6 @@ static struct omap_hwmod omap3xxx_l4_per_hwmod = {
.class = &l4_hwmod_class,
.slaves = omap3xxx_l4_per_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_l4_per_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.flags = HWMOD_NO_IDLEST,
};
@@ -489,7 +486,6 @@ static struct omap_hwmod omap3xxx_l4_wkup_hwmod = {
.class = &l4_hwmod_class,
.slaves = omap3xxx_l4_wkup_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_l4_wkup_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.flags = HWMOD_NO_IDLEST,
};
@@ -505,7 +501,6 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = {
.main_clk = "arm_fck",
.masters = omap3xxx_mpu_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_mpu_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/*
@@ -533,7 +528,6 @@ static struct omap_hwmod omap3xxx_iva_hwmod = {
.class = &iva_hwmod_class,
.masters = omap3xxx_iva_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_iva_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer class */
@@ -570,6 +564,21 @@ static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
.rev = OMAP_TIMER_IP_VERSION_1,
};
+/* secure timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
+ .timer_capability = OMAP_TIMER_SECURE,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+ .timer_capability = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+ .timer_capability = OMAP_TIMER_HAS_PWM,
+};
+
/* timer1 */
static struct omap_hwmod omap3xxx_timer1_hwmod;
@@ -610,10 +619,10 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap3xxx_timer1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer1_slaves),
.class = &omap3xxx_timer_1ms_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer2 */
@@ -656,10 +665,10 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap3xxx_timer2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer2_slaves),
.class = &omap3xxx_timer_1ms_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer3 */
@@ -702,10 +711,10 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap3xxx_timer3_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer3_slaves),
.class = &omap3xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer4 */
@@ -748,10 +757,10 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap3xxx_timer4_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer4_slaves),
.class = &omap3xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer5 */
@@ -794,10 +803,10 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap3xxx_timer5_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer5_slaves),
.class = &omap3xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer6 */
@@ -840,10 +849,10 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap3xxx_timer6_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer6_slaves),
.class = &omap3xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer7 */
@@ -886,10 +895,10 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap3xxx_timer7_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer7_slaves),
.class = &omap3xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer8 */
@@ -932,10 +941,10 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap3xxx_timer8_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer8_slaves),
.class = &omap3xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer9 */
@@ -978,10 +987,10 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap3xxx_timer9_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer9_slaves),
.class = &omap3xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer10 */
@@ -1015,10 +1024,10 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap3xxx_timer10_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer10_slaves),
.class = &omap3xxx_timer_1ms_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer11 */
@@ -1052,10 +1061,10 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap3xxx_timer11_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer11_slaves),
.class = &omap3xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* timer12*/
@@ -1102,10 +1111,10 @@ static struct omap_hwmod omap3xxx_timer12_hwmod = {
.idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT,
},
},
+ .dev_attr = &capability_secure_dev_attr,
.slaves = omap3xxx_timer12_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_timer12_slaves),
.class = &omap3xxx_timer_hwmod_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* l4_wkup -> wd_timer2 */
@@ -1182,7 +1191,6 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
},
.slaves = omap3xxx_wd_timer2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
/*
* XXX: Use software supervised mode, HW supervised smartidle seems to
* block CORE power domain idle transitions. Maybe a HW bug in wdt2?
@@ -1213,7 +1221,6 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = {
.slaves = omap3xxx_uart1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_uart1_slaves),
.class = &omap2_uart_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* UART2 */
@@ -1239,7 +1246,6 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = {
.slaves = omap3xxx_uart2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_uart2_slaves),
.class = &omap2_uart_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* UART3 */
@@ -1265,7 +1271,6 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
.slaves = omap3xxx_uart3_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_uart3_slaves),
.class = &omap2_uart_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* UART4 */
@@ -1302,7 +1307,6 @@ static struct omap_hwmod omap3xxx_uart4_hwmod = {
.slaves = omap3xxx_uart4_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_uart4_slaves),
.class = &omap2_uart_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
};
static struct omap_hwmod_class i2c_class = {
@@ -1390,7 +1394,6 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3430es1_dss_slaves),
.masters = omap3xxx_dss_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_dss_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
.flags = HWMOD_NO_IDLEST,
};
@@ -1415,8 +1418,6 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3xxx_dss_slaves),
.masters = omap3xxx_dss_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_dss_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2 |
- CHIP_IS_OMAP3630ES1 | CHIP_GE_OMAP3630ES1_1),
};
/* l4_core -> dss_dispc */
@@ -1454,9 +1455,6 @@ static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
},
.slaves = omap3xxx_dss_dispc_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
- CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
- CHIP_GE_OMAP3630ES1_1),
.flags = HWMOD_NO_IDLEST,
};
@@ -1518,9 +1516,6 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
},
.slaves = omap3xxx_dss_dsi1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
- CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
- CHIP_GE_OMAP3630ES1_1),
.flags = HWMOD_NO_IDLEST,
};
@@ -1558,9 +1553,6 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
},
.slaves = omap3xxx_dss_rfbi_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
- CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
- CHIP_GE_OMAP3630ES1_1),
.flags = HWMOD_NO_IDLEST,
};
@@ -1599,9 +1591,6 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
},
.slaves = omap3xxx_dss_venc_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_dss_venc_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
- CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
- CHIP_GE_OMAP3630ES1_1),
.flags = HWMOD_NO_IDLEST,
};
@@ -1637,7 +1626,6 @@ static struct omap_hwmod omap3xxx_i2c1_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3xxx_i2c1_slaves),
.class = &i2c_class,
.dev_attr = &i2c1_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* I2C2 */
@@ -1672,7 +1660,6 @@ static struct omap_hwmod omap3xxx_i2c2_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3xxx_i2c2_slaves),
.class = &i2c_class,
.dev_attr = &i2c2_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* I2C3 */
@@ -1718,7 +1705,6 @@ static struct omap_hwmod omap3xxx_i2c3_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3xxx_i2c3_slaves),
.class = &i2c_class,
.dev_attr = &i2c3_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* l4_wkup -> gpio1 */
@@ -1880,7 +1866,6 @@ static struct omap_hwmod omap3xxx_gpio1_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3xxx_gpio1_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* gpio2 */
@@ -1912,7 +1897,6 @@ static struct omap_hwmod omap3xxx_gpio2_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3xxx_gpio2_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* gpio3 */
@@ -1944,7 +1928,6 @@ static struct omap_hwmod omap3xxx_gpio3_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3xxx_gpio3_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* gpio4 */
@@ -1976,7 +1959,6 @@ static struct omap_hwmod omap3xxx_gpio4_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3xxx_gpio4_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* gpio5 */
@@ -2013,7 +1995,6 @@ static struct omap_hwmod omap3xxx_gpio5_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3xxx_gpio5_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* gpio6 */
@@ -2050,7 +2031,6 @@ static struct omap_hwmod omap3xxx_gpio6_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap3xxx_gpio6_slaves),
.class = &omap3xxx_gpio_hwmod_class,
.dev_attr = &gpio_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* dma_system -> L3 */
@@ -2134,7 +2114,6 @@ static struct omap_hwmod omap3xxx_dma_system_hwmod = {
.masters = omap3xxx_dma_system_masters,
.masters_cnt = ARRAY_SIZE(omap3xxx_dma_system_masters),
.dev_attr = &dma_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.flags = HWMOD_NO_IDLEST,
};
@@ -2207,7 +2186,6 @@ static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
},
.slaves = omap3xxx_mcbsp1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* mcbsp2 */
@@ -2264,7 +2242,6 @@ static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
.slaves = omap3xxx_mcbsp2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp2_slaves),
.dev_attr = &omap34xx_mcbsp2_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* mcbsp3 */
@@ -2321,7 +2298,6 @@ static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
.slaves = omap3xxx_mcbsp3_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp3_slaves),
.dev_attr = &omap34xx_mcbsp3_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* mcbsp4 */
@@ -2379,7 +2355,6 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
},
.slaves = omap3xxx_mcbsp4_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp4_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* mcbsp5 */
@@ -2437,7 +2412,6 @@ static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
},
.slaves = omap3xxx_mcbsp5_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp5_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* 'mcbsp sidetone' class */
@@ -2498,7 +2472,6 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
},
.slaves = omap3xxx_mcbsp2_sidetone_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* mcbsp3_sidetone */
@@ -2547,7 +2520,6 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
},
.slaves = omap3xxx_mcbsp3_sidetone_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
@@ -2597,7 +2569,7 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
.name = "sr1_hwmod",
.class = &omap34xx_smartreflex_hwmod_class,
.main_clk = "sr1_fck",
- .vdd_name = "mpu",
+ .vdd_name = "mpu_iva",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@@ -2609,9 +2581,6 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
},
.slaves = omap3_sr1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
- CHIP_IS_OMAP3430ES3_0 |
- CHIP_IS_OMAP3430ES3_1),
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
};
@@ -2619,7 +2588,7 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
.name = "sr1_hwmod",
.class = &omap36xx_smartreflex_hwmod_class,
.main_clk = "sr1_fck",
- .vdd_name = "mpu",
+ .vdd_name = "mpu_iva",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@@ -2631,7 +2600,6 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
},
.slaves = omap3_sr1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
};
/* SR2 */
@@ -2655,9 +2623,6 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
},
.slaves = omap3_sr2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
- CHIP_IS_OMAP3430ES3_0 |
- CHIP_IS_OMAP3430ES3_1),
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
};
@@ -2677,7 +2642,6 @@ static struct omap_hwmod omap36xx_sr2_hwmod = {
},
.slaves = omap3_sr2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
};
/*
@@ -2745,7 +2709,6 @@ static struct omap_hwmod omap3xxx_mailbox_hwmod = {
},
.slaves = omap3xxx_mailbox_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mailbox_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* l4 core -> mcspi1 interface */
@@ -2843,7 +2806,6 @@ static struct omap_hwmod omap34xx_mcspi1 = {
.slaves_cnt = ARRAY_SIZE(omap34xx_mcspi1_slaves),
.class = &omap34xx_mcspi_class,
.dev_attr = &omap_mcspi1_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* mcspi2 */
@@ -2873,7 +2835,6 @@ static struct omap_hwmod omap34xx_mcspi2 = {
.slaves_cnt = ARRAY_SIZE(omap34xx_mcspi2_slaves),
.class = &omap34xx_mcspi_class,
.dev_attr = &omap_mcspi2_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* mcspi3 */
@@ -2916,7 +2877,6 @@ static struct omap_hwmod omap34xx_mcspi3 = {
.slaves_cnt = ARRAY_SIZE(omap34xx_mcspi3_slaves),
.class = &omap34xx_mcspi_class,
.dev_attr = &omap_mcspi3_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* SPI4 */
@@ -2957,7 +2917,6 @@ static struct omap_hwmod omap34xx_mcspi4 = {
.slaves_cnt = ARRAY_SIZE(omap34xx_mcspi4_slaves),
.class = &omap34xx_mcspi_class,
.dev_attr = &omap_mcspi4_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/*
@@ -3014,7 +2973,6 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
*/
.flags = HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
| HWMOD_SWSUP_MSTANDBY,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
};
/* usb_otg_hs */
@@ -3042,7 +3000,6 @@ static struct omap_hwmod am35xx_usbhsotg_hwmod = {
.slaves = am35xx_usbhsotg_slaves,
.slaves_cnt = ARRAY_SIZE(am35xx_usbhsotg_slaves),
.class = &am35xx_usbotg_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES3_1)
};
/* MMC/SD/SDIO common */
@@ -3108,7 +3065,6 @@ static struct omap_hwmod omap3xxx_mmc1_hwmod = {
.slaves = omap3xxx_mmc1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mmc1_slaves),
.class = &omap34xx_mmc_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* MMC/SD/SDIO2 */
@@ -3151,7 +3107,6 @@ static struct omap_hwmod omap3xxx_mmc2_hwmod = {
.slaves = omap3xxx_mmc2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mmc2_slaves),
.class = &omap34xx_mmc_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
/* MMC/SD/SDIO3 */
@@ -3193,7 +3148,6 @@ static struct omap_hwmod omap3xxx_mmc3_hwmod = {
.slaves = omap3xxx_mmc3_slaves,
.slaves_cnt = ARRAY_SIZE(omap3xxx_mmc3_slaves),
.class = &omap34xx_mmc_class,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
@@ -3224,10 +3178,7 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
&omap3xxx_uart1_hwmod,
&omap3xxx_uart2_hwmod,
&omap3xxx_uart3_hwmod,
- &omap3xxx_uart4_hwmod,
/* dss class */
- &omap3430es1_dss_core_hwmod,
- &omap3xxx_dss_core_hwmod,
&omap3xxx_dss_dispc_hwmod,
&omap3xxx_dss_dsi1_hwmod,
&omap3xxx_dss_rfbi_hwmod,
@@ -3239,9 +3190,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
&omap3xxx_i2c3_hwmod,
&omap34xx_sr1_hwmod,
&omap34xx_sr2_hwmod,
- &omap36xx_sr1_hwmod,
- &omap36xx_sr2_hwmod,
-
/* gpio class */
&omap3xxx_gpio1_hwmod,
@@ -3272,16 +3220,96 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
&omap34xx_mcspi3,
&omap34xx_mcspi4,
- /* usbotg class */
+ NULL,
+};
+
+/* 3430ES1-only hwmods */
+static __initdata struct omap_hwmod *omap3430es1_hwmods[] = {
+ &omap3430es1_dss_core_hwmod,
+ NULL
+};
+
+/* 3430ES2+-only hwmods */
+static __initdata struct omap_hwmod *omap3430es2plus_hwmods[] = {
+ &omap3xxx_dss_core_hwmod,
&omap3xxx_usbhsotg_hwmod,
+ NULL
+};
- /* usbotg for am35x */
- &am35xx_usbhsotg_hwmod,
+/* 34xx-only hwmods (all ES revisions) */
+static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
+ &omap34xx_sr1_hwmod,
+ &omap34xx_sr2_hwmod,
+ NULL
+};
- NULL,
+/* 36xx-only hwmods (all ES revisions) */
+static __initdata struct omap_hwmod *omap36xx_hwmods[] = {
+ &omap3xxx_uart4_hwmod,
+ &omap3xxx_dss_core_hwmod,
+ &omap36xx_sr1_hwmod,
+ &omap36xx_sr2_hwmod,
+ &omap3xxx_usbhsotg_hwmod,
+ NULL
+};
+
+static __initdata struct omap_hwmod *am35xx_hwmods[] = {
+ &omap3xxx_dss_core_hwmod, /* XXX ??? */
+ &am35xx_usbhsotg_hwmod,
+ NULL
};
int __init omap3xxx_hwmod_init(void)
{
- return omap_hwmod_register(omap3xxx_hwmods);
+ int r;
+ struct omap_hwmod **h = NULL;
+ unsigned int rev;
+
+ /* Register hwmods common to all OMAP3 */
+ r = omap_hwmod_register(omap3xxx_hwmods);
+ if (!r)
+ return r;
+
+ rev = omap_rev();
+
+ /*
+ * Register hwmods common to individual OMAP3 families, all
+ * silicon revisions (e.g., 34xx, or AM3505/3517, or 36xx)
+ * All possible revisions should be included in this conditional.
+ */
+ if (rev == OMAP3430_REV_ES1_0 || rev == OMAP3430_REV_ES2_0 ||
+ rev == OMAP3430_REV_ES2_1 || rev == OMAP3430_REV_ES3_0 ||
+ rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2) {
+ h = omap34xx_hwmods;
+ } else if (rev == OMAP3517_REV_ES1_0 || rev == OMAP3517_REV_ES1_1) {
+ h = am35xx_hwmods;
+ } else if (rev == OMAP3630_REV_ES1_0 || rev == OMAP3630_REV_ES1_1 ||
+ rev == OMAP3630_REV_ES1_2) {
+ h = omap36xx_hwmods;
+ } else {
+ WARN(1, "OMAP3 hwmod family init: unknown chip type\n");
+ return -EINVAL;
+ };
+
+ r = omap_hwmod_register(h);
+ if (!r)
+ return r;
+
+ /*
+ * Register hwmods specific to certain ES levels of a
+ * particular family of silicon (e.g., 34xx ES1.0)
+ */
+ h = NULL;
+ if (rev == OMAP3430_REV_ES1_0) {
+ h = omap3430es1_hwmods;
+ } else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
+ rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 ||
+ rev == OMAP3430_REV_ES3_1_2) {
+ h = omap3430es2plus_hwmods;
+ };
+
+ if (h)
+ r = omap_hwmod_register(h);
+
+ return r;
}
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6201422c0606..7695e5d43316 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -29,6 +29,7 @@
#include <plat/mcbsp.h>
#include <plat/mmc.h>
#include <plat/i2c.h>
+#include <plat/dmtimer.h>
#include "omap_hwmod_common_data.h"
@@ -133,7 +134,6 @@ static struct omap_hwmod omap44xx_dmm_hwmod = {
.slaves = omap44xx_dmm_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_dmm_slaves),
.mpu_irqs = omap44xx_dmm_irqs,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -189,7 +189,6 @@ static struct omap_hwmod omap44xx_emif_fw_hwmod = {
},
.slaves = omap44xx_emif_fw_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_emif_fw_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -236,7 +235,6 @@ static struct omap_hwmod omap44xx_l3_instr_hwmod = {
},
.slaves = omap44xx_l3_instr_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l3_instr_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* l3_main_1 */
@@ -336,7 +334,6 @@ static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
},
.slaves = omap44xx_l3_main_1_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l3_main_1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* l3_main_2 */
@@ -438,7 +435,6 @@ static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
},
.slaves = omap44xx_l3_main_2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l3_main_2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* l3_main_3 */
@@ -496,7 +492,6 @@ static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
},
.slaves = omap44xx_l3_main_3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l3_main_3_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -559,7 +554,6 @@ static struct omap_hwmod omap44xx_l4_abe_hwmod = {
},
.slaves = omap44xx_l4_abe_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l4_abe_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* l4_cfg */
@@ -588,7 +582,6 @@ static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
},
.slaves = omap44xx_l4_cfg_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l4_cfg_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* l4_per */
@@ -617,7 +610,6 @@ static struct omap_hwmod omap44xx_l4_per_hwmod = {
},
.slaves = omap44xx_l4_per_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l4_per_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* l4_wkup */
@@ -646,7 +638,6 @@ static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
},
.slaves = omap44xx_l4_wkup_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_l4_wkup_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -677,7 +668,6 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = {
.clkdm_name = "mpuss_clkdm",
.slaves = omap44xx_mpu_private_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mpu_private_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -828,7 +818,6 @@ static struct omap_hwmod omap44xx_aess_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_aess_slaves),
.masters = omap44xx_aess_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_aess_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -856,7 +845,6 @@ static struct omap_hwmod omap44xx_bandgap_hwmod = {
},
.opt_clks = bandgap_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(bandgap_opt_clks),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -917,7 +905,6 @@ static struct omap_hwmod omap44xx_counter_32k_hwmod = {
},
.slaves = omap44xx_counter_32k_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_counter_32k_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -1005,7 +992,6 @@ static struct omap_hwmod omap44xx_dma_system_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_dma_system_slaves),
.masters = omap44xx_dma_system_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_dma_system_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -1098,7 +1084,6 @@ static struct omap_hwmod omap44xx_dmic_hwmod = {
},
.slaves = omap44xx_dmic_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_dmic_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -1164,7 +1149,6 @@ static struct omap_hwmod omap44xx_dsp_c0_hwmod = {
.rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
},
},
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct omap_hwmod omap44xx_dsp_hwmod = {
@@ -1187,7 +1171,6 @@ static struct omap_hwmod omap44xx_dsp_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_dsp_slaves),
.masters = omap44xx_dsp_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_dsp_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -1278,7 +1261,6 @@ static struct omap_hwmod omap44xx_dss_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_dss_slaves),
.masters = omap44xx_dss_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_dss_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -1381,7 +1363,6 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
.opt_clks_cnt = ARRAY_SIZE(dss_dispc_opt_clks),
.slaves = omap44xx_dss_dispc_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_dss_dispc_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -1480,7 +1461,6 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
.opt_clks_cnt = ARRAY_SIZE(dss_dsi1_opt_clks),
.slaves = omap44xx_dss_dsi1_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* dss_dsi2 */
@@ -1558,7 +1538,6 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
.opt_clks_cnt = ARRAY_SIZE(dss_dsi2_opt_clks),
.slaves = omap44xx_dss_dsi2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -1656,7 +1635,6 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
.opt_clks_cnt = ARRAY_SIZE(dss_hdmi_opt_clks),
.slaves = omap44xx_dss_hdmi_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -1748,7 +1726,6 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
.opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks),
.slaves = omap44xx_dss_rfbi_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -1817,7 +1794,6 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
},
.slaves = omap44xx_dss_venc_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_dss_venc_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -1901,7 +1877,6 @@ static struct omap_hwmod omap44xx_gpio1_hwmod = {
.dev_attr = &gpio_dev_attr,
.slaves = omap44xx_gpio1_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_gpio1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* gpio2 */
@@ -1957,7 +1932,6 @@ static struct omap_hwmod omap44xx_gpio2_hwmod = {
.dev_attr = &gpio_dev_attr,
.slaves = omap44xx_gpio2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_gpio2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* gpio3 */
@@ -2013,7 +1987,6 @@ static struct omap_hwmod omap44xx_gpio3_hwmod = {
.dev_attr = &gpio_dev_attr,
.slaves = omap44xx_gpio3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_gpio3_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* gpio4 */
@@ -2069,7 +2042,6 @@ static struct omap_hwmod omap44xx_gpio4_hwmod = {
.dev_attr = &gpio_dev_attr,
.slaves = omap44xx_gpio4_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_gpio4_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* gpio5 */
@@ -2125,7 +2097,6 @@ static struct omap_hwmod omap44xx_gpio5_hwmod = {
.dev_attr = &gpio_dev_attr,
.slaves = omap44xx_gpio5_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_gpio5_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* gpio6 */
@@ -2181,7 +2152,6 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = {
.dev_attr = &gpio_dev_attr,
.slaves = omap44xx_gpio6_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_gpio6_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -2261,7 +2231,6 @@ static struct omap_hwmod omap44xx_hsi_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_hsi_slaves),
.masters = omap44xx_hsi_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_hsi_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -2345,7 +2314,6 @@ static struct omap_hwmod omap44xx_i2c1_hwmod = {
.slaves = omap44xx_i2c1_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_i2c1_slaves),
.dev_attr = &i2c_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* i2c2 */
@@ -2402,7 +2370,6 @@ static struct omap_hwmod omap44xx_i2c2_hwmod = {
.slaves = omap44xx_i2c2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_i2c2_slaves),
.dev_attr = &i2c_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* i2c3 */
@@ -2459,7 +2426,6 @@ static struct omap_hwmod omap44xx_i2c3_hwmod = {
.slaves = omap44xx_i2c3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_i2c3_slaves),
.dev_attr = &i2c_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* i2c4 */
@@ -2516,7 +2482,6 @@ static struct omap_hwmod omap44xx_i2c4_hwmod = {
.slaves = omap44xx_i2c4_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_i2c4_slaves),
.dev_attr = &i2c_dev_attr,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -2577,7 +2542,6 @@ static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
},
},
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* Pseudo hwmod for reset control purpose only */
@@ -2593,7 +2557,6 @@ static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
},
},
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct omap_hwmod omap44xx_ipu_hwmod = {
@@ -2616,7 +2579,6 @@ static struct omap_hwmod omap44xx_ipu_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_ipu_slaves),
.masters = omap44xx_ipu_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_ipu_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -2706,7 +2668,6 @@ static struct omap_hwmod omap44xx_iss_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_iss_slaves),
.masters = omap44xx_iss_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_iss_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -2781,7 +2742,6 @@ static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
},
},
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* Pseudo hwmod for reset control purpose only */
@@ -2797,7 +2757,6 @@ static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
},
},
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct omap_hwmod omap44xx_iva_hwmod = {
@@ -2820,7 +2779,6 @@ static struct omap_hwmod omap44xx_iva_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_iva_slaves),
.masters = omap44xx_iva_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_iva_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -2890,7 +2848,6 @@ static struct omap_hwmod omap44xx_kbd_hwmod = {
},
.slaves = omap44xx_kbd_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_kbd_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -2956,7 +2913,6 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = {
},
.slaves = omap44xx_mailbox_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mailbox_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -3051,7 +3007,6 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
},
.slaves = omap44xx_mcbsp1_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* mcbsp2 */
@@ -3127,7 +3082,6 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
},
.slaves = omap44xx_mcbsp2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* mcbsp3 */
@@ -3203,7 +3157,6 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
},
.slaves = omap44xx_mcbsp3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp3_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* mcbsp4 */
@@ -3258,7 +3211,6 @@ static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
},
.slaves = omap44xx_mcbsp4_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp4_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -3353,7 +3305,6 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
},
.slaves = omap44xx_mcpdm_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcpdm_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -3442,7 +3393,6 @@ static struct omap_hwmod omap44xx_mcspi1_hwmod = {
.dev_attr = &mcspi1_dev_attr,
.slaves = omap44xx_mcspi1_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcspi1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* mcspi2 */
@@ -3505,7 +3455,6 @@ static struct omap_hwmod omap44xx_mcspi2_hwmod = {
.dev_attr = &mcspi2_dev_attr,
.slaves = omap44xx_mcspi2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcspi2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* mcspi3 */
@@ -3568,7 +3517,6 @@ static struct omap_hwmod omap44xx_mcspi3_hwmod = {
.dev_attr = &mcspi3_dev_attr,
.slaves = omap44xx_mcspi3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcspi3_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* mcspi4 */
@@ -3629,7 +3577,6 @@ static struct omap_hwmod omap44xx_mcspi4_hwmod = {
.dev_attr = &mcspi4_dev_attr,
.slaves = omap44xx_mcspi4_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcspi4_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -3718,7 +3665,6 @@ static struct omap_hwmod omap44xx_mmc1_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_mmc1_slaves),
.masters = omap44xx_mmc1_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_mmc1_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* mmc2 */
@@ -3779,7 +3725,6 @@ static struct omap_hwmod omap44xx_mmc2_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_mmc2_slaves),
.masters = omap44xx_mmc2_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_mmc2_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* mmc3 */
@@ -3834,7 +3779,6 @@ static struct omap_hwmod omap44xx_mmc3_hwmod = {
},
.slaves = omap44xx_mmc3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mmc3_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* mmc4 */
@@ -3890,7 +3834,6 @@ static struct omap_hwmod omap44xx_mmc4_hwmod = {
},
.slaves = omap44xx_mmc4_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mmc4_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* mmc5 */
@@ -3945,7 +3888,6 @@ static struct omap_hwmod omap44xx_mmc5_hwmod = {
},
.slaves = omap44xx_mmc5_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mmc5_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -3987,7 +3929,6 @@ static struct omap_hwmod omap44xx_mpu_hwmod = {
},
.masters = omap44xx_mpu_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_mpu_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -4063,7 +4004,6 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
},
.slaves = omap44xx_smartreflex_core_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* smartreflex_iva */
@@ -4112,7 +4052,6 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
},
.slaves = omap44xx_smartreflex_iva_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* smartreflex_mpu */
@@ -4161,7 +4100,6 @@ static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
},
.slaves = omap44xx_smartreflex_mpu_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -4224,7 +4162,6 @@ static struct omap_hwmod omap44xx_spinlock_hwmod = {
},
.slaves = omap44xx_spinlock_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_spinlock_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -4265,6 +4202,16 @@ static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
.sysc = &omap44xx_timer_sysc,
};
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+ .timer_capability = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+ .timer_capability = OMAP_TIMER_HAS_PWM,
+};
+
/* timer1 */
static struct omap_hwmod omap44xx_timer1_hwmod;
static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
@@ -4308,9 +4255,9 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap44xx_timer1_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* timer2 */
@@ -4356,9 +4303,9 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap44xx_timer2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* timer3 */
@@ -4404,9 +4351,9 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap44xx_timer3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer3_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* timer4 */
@@ -4452,9 +4399,9 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap44xx_timer4_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer4_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* timer5 */
@@ -4519,9 +4466,9 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap44xx_timer5_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer5_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* timer6 */
@@ -4587,9 +4534,9 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap44xx_timer6_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer6_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* timer7 */
@@ -4654,9 +4601,9 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_alwon_dev_attr,
.slaves = omap44xx_timer7_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer7_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* timer8 */
@@ -4721,9 +4668,9 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap44xx_timer8_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer8_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* timer9 */
@@ -4769,9 +4716,9 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap44xx_timer9_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer9_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* timer10 */
@@ -4817,9 +4764,9 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap44xx_timer10_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer10_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* timer11 */
@@ -4865,9 +4812,9 @@ static struct omap_hwmod omap44xx_timer11_hwmod = {
.modulemode = MODULEMODE_SWCTRL,
},
},
+ .dev_attr = &capability_pwm_dev_attr,
.slaves = omap44xx_timer11_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_timer11_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -4944,7 +4891,6 @@ static struct omap_hwmod omap44xx_uart1_hwmod = {
},
.slaves = omap44xx_uart1_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_uart1_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* uart2 */
@@ -4999,7 +4945,6 @@ static struct omap_hwmod omap44xx_uart2_hwmod = {
},
.slaves = omap44xx_uart2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_uart2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* uart3 */
@@ -5055,7 +5000,6 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
},
.slaves = omap44xx_uart3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_uart3_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* uart4 */
@@ -5110,7 +5054,6 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
},
.slaves = omap44xx_uart4_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_uart4_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -5195,7 +5138,6 @@ static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {
.slaves_cnt = ARRAY_SIZE(omap44xx_usb_otg_hs_slaves),
.masters = omap44xx_usb_otg_hs_masters,
.masters_cnt = ARRAY_SIZE(omap44xx_usb_otg_hs_masters),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/*
@@ -5266,7 +5208,6 @@ static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
},
.slaves = omap44xx_wd_timer2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_wd_timer2_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
/* wd_timer3 */
@@ -5333,7 +5274,6 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
},
.slaves = omap44xx_wd_timer3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_wd_timer3_slaves),
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
@@ -5430,7 +5370,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
&omap44xx_mcbsp4_hwmod,
/* mcpdm class */
-/* &omap44xx_mcpdm_hwmod, */
+ &omap44xx_mcpdm_hwmod,
/* mcspi class */
&omap44xx_mcspi1_hwmod,
diff --git a/arch/arm/mach-omap2/omap_l3_noc.c b/arch/arm/mach-omap2/omap_l3_noc.c
index 7b9f1909ddb2..c8b1bef92e5a 100644
--- a/arch/arm/mach-omap2/omap_l3_noc.c
+++ b/arch/arm/mach-omap2/omap_l3_noc.c
@@ -1,25 +1,25 @@
/*
- * OMAP4XXX L3 Interconnect error handling driver
- *
- * Copyright (C) 2011 Texas Corporation
- * Santosh Shilimkar <santosh.shilimkar@ti.com>
- * Sricharan <r.sricharan@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; 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
- */
+ * OMAP4XXX L3 Interconnect error handling driver
+ *
+ * Copyright (C) 2011 Texas Corporation
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ * Sricharan <r.sricharan@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; 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/init.h>
#include <linux/io.h>
#include <linux/platform_device.h>
@@ -55,12 +55,12 @@
static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
{
- struct omap4_l3 *l3 = _l3;
- int inttype, i, j;
+ struct omap4_l3 *l3 = _l3;
+ int inttype, i, k;
int err_src = 0;
- u32 std_err_main_addr, std_err_main, err_reg;
- u32 base, slave_addr, clear;
- char *source_name;
+ u32 std_err_main, err_reg, clear, masterid;
+ void __iomem *base, *l3_targ_base;
+ char *target_name, *master_name = "UN IDENTIFIED";
/* Get the Type of interrupt */
inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
@@ -70,43 +70,50 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
* Read the regerr register of the clock domain
* to determine the source
*/
- base = (u32)l3->l3_base[i];
- err_reg = readl(base + l3_flagmux[i] + (inttype << 3));
+ base = l3->l3_base[i];
+ err_reg = __raw_readl(base + l3_flagmux[i] +
+ + L3_FLAGMUX_REGERR0 + (inttype << 3));
/* Get the corresponding error and analyse */
if (err_reg) {
/* Identify the source from control status register */
- for (j = 0; !(err_reg & (1 << j)); j++)
- ;
+ err_src = __ffs(err_reg);
- err_src = j;
/* Read the stderrlog_main_source from clk domain */
- std_err_main_addr = base + *(l3_targ[i] + err_src);
- std_err_main = readl(std_err_main_addr);
+ l3_targ_base = base + *(l3_targ[i] + err_src);
+ std_err_main = __raw_readl(l3_targ_base +
+ L3_TARG_STDERRLOG_MAIN);
+ masterid = __raw_readl(l3_targ_base +
+ L3_TARG_STDERRLOG_MSTADDR);
switch (std_err_main & CUSTOM_ERROR) {
case STANDARD_ERROR:
- source_name =
- l3_targ_stderrlog_main_name[i][err_src];
-
- slave_addr = std_err_main_addr +
- L3_SLAVE_ADDRESS_OFFSET;
- WARN(true, "L3 standard error: SOURCE:%s at address 0x%x\n",
- source_name, readl(slave_addr));
+ target_name =
+ l3_targ_inst_name[i][err_src];
+ WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
+ target_name,
+ __raw_readl(l3_targ_base +
+ L3_TARG_STDERRLOG_SLVOFSLSB));
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, std_err_main_addr);
+ writel(clear, l3_targ_base +
+ L3_TARG_STDERRLOG_MAIN);
break;
case CUSTOM_ERROR:
- source_name =
- l3_targ_stderrlog_main_name[i][err_src];
-
- WARN(true, "CUSTOM SRESP error with SOURCE:%s\n",
- source_name);
+ target_name =
+ l3_targ_inst_name[i][err_src];
+ for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
+ if (masterid == l3_masters[k].id)
+ master_name =
+ l3_masters[k].name;
+ }
+ WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
+ master_name, target_name);
/* clear the std error log*/
clear = std_err_main | CLEAR_STDERR_LOG;
- writel(clear, std_err_main_addr);
+ writel(clear, l3_targ_base +
+ L3_TARG_STDERRLOG_MAIN);
break;
default:
@@ -120,12 +127,11 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
return IRQ_HANDLED;
}
-static int __init omap4_l3_probe(struct platform_device *pdev)
+static int __devinit omap4_l3_probe(struct platform_device *pdev)
{
- static struct omap4_l3 *l3;
- struct resource *res;
- int ret;
- int irq;
+ static struct omap4_l3 *l3;
+ struct resource *res;
+ int ret;
l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
if (!l3)
@@ -177,27 +183,25 @@ static int __init omap4_l3_probe(struct platform_device *pdev)
/*
* Setup interrupt Handlers
*/
- irq = platform_get_irq(pdev, 0);
- ret = request_irq(irq,
+ l3->debug_irq = platform_get_irq(pdev, 0);
+ ret = request_irq(l3->debug_irq,
l3_interrupt_handler,
IRQF_DISABLED, "l3-dbg-irq", l3);
if (ret) {
pr_crit("L3: request_irq failed to register for 0x%x\n",
- OMAP44XX_IRQ_L3_DBG);
+ OMAP44XX_IRQ_L3_DBG);
goto err3;
}
- l3->debug_irq = irq;
- irq = platform_get_irq(pdev, 1);
- ret = request_irq(irq,
+ l3->app_irq = platform_get_irq(pdev, 1);
+ ret = request_irq(l3->app_irq,
l3_interrupt_handler,
IRQF_DISABLED, "l3-app-irq", l3);
if (ret) {
pr_crit("L3: request_irq failed to register for 0x%x\n",
- OMAP44XX_IRQ_L3_APP);
+ OMAP44XX_IRQ_L3_APP);
goto err4;
}
- l3->app_irq = irq;
return 0;
@@ -214,9 +218,9 @@ err0:
return ret;
}
-static int __exit omap4_l3_remove(struct platform_device *pdev)
+static int __devexit omap4_l3_remove(struct platform_device *pdev)
{
- struct omap4_l3 *l3 = platform_get_drvdata(pdev);
+ struct omap4_l3 *l3 = platform_get_drvdata(pdev);
free_irq(l3->app_irq, l3);
free_irq(l3->debug_irq, l3);
@@ -228,16 +232,29 @@ static int __exit omap4_l3_remove(struct platform_device *pdev)
return 0;
}
+#if defined(CONFIG_OF)
+static const struct of_device_id l3_noc_match[] = {
+ {.compatible = "ti,omap4-l3-noc", },
+ {},
+}
+MODULE_DEVICE_TABLE(of, l3_noc_match);
+#else
+#define l3_noc_match NULL
+#endif
+
static struct platform_driver omap4_l3_driver = {
- .remove = __exit_p(omap4_l3_remove),
+ .probe = omap4_l3_probe,
+ .remove = __devexit_p(omap4_l3_remove),
.driver = {
- .name = "omap_l3_noc",
+ .name = "omap_l3_noc",
+ .owner = THIS_MODULE,
+ .of_match_table = l3_noc_match,
},
};
static int __init omap4_l3_init(void)
{
- return platform_driver_probe(&omap4_l3_driver, omap4_l3_probe);
+ return platform_driver_register(&omap4_l3_driver);
}
postcore_initcall_sync(omap4_l3_init);
diff --git a/arch/arm/mach-omap2/omap_l3_noc.h b/arch/arm/mach-omap2/omap_l3_noc.h
index 359b83348aed..90b50984cd2e 100644
--- a/arch/arm/mach-omap2/omap_l3_noc.h
+++ b/arch/arm/mach-omap2/omap_l3_noc.h
@@ -1,132 +1,162 @@
- /*
- * OMAP4XXX L3 Interconnect error handling driver header
- *
- * Copyright (C) 2011 Texas Corporation
- * Santosh Shilimkar <santosh.shilimkar@ti.com>
- * sricharan <r.sricharan@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; 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
- */
+/*
+ * OMAP4XXX L3 Interconnect error handling driver header
+ *
+ * Copyright (C) 2011 Texas Corporation
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ * sricharan <r.sricharan@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; 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 __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
-/*
- * L3 register offsets
- */
#define L3_MODULES 3
#define CLEAR_STDERR_LOG (1 << 31)
#define CUSTOM_ERROR 0x2
#define STANDARD_ERROR 0x0
#define INBAND_ERROR 0x0
-#define EMIF_KERRLOG_OFFSET 0x10
-#define L3_SLAVE_ADDRESS_OFFSET 0x14
-#define LOGICAL_ADDR_ERRORLOG 0x4
#define L3_APPLICATION_ERROR 0x0
#define L3_DEBUG_ERROR 0x1
-u32 l3_flagmux[L3_MODULES] = {
- 0x50C,
- 0x100C,
- 0X020C
+/* L3 TARG register offsets */
+#define L3_TARG_STDERRLOG_MAIN 0x48
+#define L3_TARG_STDERRLOG_SLVOFSLSB 0x5c
+#define L3_TARG_STDERRLOG_MSTADDR 0x68
+#define L3_FLAGMUX_REGERR0 0xc
+
+#define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0]))
+
+static u32 l3_flagmux[L3_MODULES] = {
+ 0x500,
+ 0x1000,
+ 0X0200
};
-/*
- * L3 Target standard Error register offsets
- */
-u32 l3_targ_stderrlog_main_clk1[] = {
- 0x148, /* DMM1 */
- 0x248, /* DMM2 */
- 0x348, /* ABE */
- 0x448, /* L4CFG */
- 0x648 /* CLK2 PWR DISC */
+/* L3 Target standard Error register offsets */
+static u32 l3_targ_inst_clk1[] = {
+ 0x100, /* DMM1 */
+ 0x200, /* DMM2 */
+ 0x300, /* ABE */
+ 0x400, /* L4CFG */
+ 0x600 /* CLK2 PWR DISC */
};
-u32 l3_targ_stderrlog_main_clk2[] = {
- 0x548, /* CORTEX M3 */
- 0x348, /* DSS */
- 0x148, /* GPMC */
- 0x448, /* ISS */
- 0x748, /* IVAHD */
- 0xD48, /* missing in TRM corresponds to AES1*/
- 0x948, /* L4 PER0*/
- 0x248, /* OCMRAM */
- 0x148, /* missing in TRM corresponds to GPMC sERROR*/
- 0x648, /* SGX */
- 0x848, /* SL2 */
- 0x1648, /* C2C */
- 0x1148, /* missing in TRM corresponds PWR DISC CLK1*/
- 0xF48, /* missing in TRM corrsponds to SHA1*/
- 0xE48, /* missing in TRM corresponds to AES2*/
- 0xC48, /* L4 PER3 */
- 0xA48, /* L4 PER1*/
- 0xB48 /* L4 PER2*/
+static u32 l3_targ_inst_clk2[] = {
+ 0x500, /* CORTEX M3 */
+ 0x300, /* DSS */
+ 0x100, /* GPMC */
+ 0x400, /* ISS */
+ 0x700, /* IVAHD */
+ 0xD00, /* missing in TRM corresponds to AES1*/
+ 0x900, /* L4 PER0*/
+ 0x200, /* OCMRAM */
+ 0x100, /* missing in TRM corresponds to GPMC sERROR*/
+ 0x600, /* SGX */
+ 0x800, /* SL2 */
+ 0x1600, /* C2C */
+ 0x1100, /* missing in TRM corresponds PWR DISC CLK1*/
+ 0xF00, /* missing in TRM corrsponds to SHA1*/
+ 0xE00, /* missing in TRM corresponds to AES2*/
+ 0xC00, /* L4 PER3 */
+ 0xA00, /* L4 PER1*/
+ 0xB00 /* L4 PER2*/
};
-u32 l3_targ_stderrlog_main_clk3[] = {
- 0x0148 /* EMUSS */
+static u32 l3_targ_inst_clk3[] = {
+ 0x0100 /* EMUSS */
};
-char *l3_targ_stderrlog_main_name[L3_MODULES][18] = {
+static struct l3_masters_data {
+ u32 id;
+ char name[10];
+} l3_masters[] = {
+ { 0x0 , "MPU"},
+ { 0x10, "CS_ADP"},
+ { 0x14, "xxx"},
+ { 0x20, "DSP"},
+ { 0x30, "IVAHD"},
+ { 0x40, "ISS"},
+ { 0x44, "DucatiM3"},
+ { 0x48, "FaceDetect"},
+ { 0x50, "SDMA_Rd"},
+ { 0x54, "SDMA_Wr"},
+ { 0x58, "xxx"},
+ { 0x5C, "xxx"},
+ { 0x60, "SGX"},
+ { 0x70, "DSS"},
+ { 0x80, "C2C"},
+ { 0x88, "xxx"},
+ { 0x8C, "xxx"},
+ { 0x90, "HSI"},
+ { 0xA0, "MMC1"},
+ { 0xA4, "MMC2"},
+ { 0xA8, "MMC6"},
+ { 0xB0, "UNIPRO1"},
+ { 0xC0, "USBHOSTHS"},
+ { 0xC4, "USBOTGHS"},
+ { 0xC8, "USBHOSTFS"}
+};
+
+static char *l3_targ_inst_name[L3_MODULES][18] = {
{
- "DMM1",
- "DMM2",
- "ABE",
- "L4CFG",
- "CLK2 PWR DISC",
+ "DMM1",
+ "DMM2",
+ "ABE",
+ "L4CFG",
+ "CLK2 PWR DISC",
},
{
- "CORTEX M3" ,
- "DSS ",
- "GPMC ",
- "ISS ",
- "IVAHD ",
- "AES1",
- "L4 PER0",
- "OCMRAM ",
- "GPMC sERROR",
- "SGX ",
- "SL2 ",
- "C2C ",
- "PWR DISC CLK1",
- "SHA1",
- "AES2",
- "L4 PER3",
- "L4 PER1",
- "L4 PER2",
+ "CORTEX M3" ,
+ "DSS ",
+ "GPMC ",
+ "ISS ",
+ "IVAHD ",
+ "AES1",
+ "L4 PER0",
+ "OCMRAM ",
+ "GPMC sERROR",
+ "SGX ",
+ "SL2 ",
+ "C2C ",
+ "PWR DISC CLK1",
+ "SHA1",
+ "AES2",
+ "L4 PER3",
+ "L4 PER1",
+ "L4 PER2",
},
{
- "EMUSS",
+ "EMUSS",
},
};
-u32 *l3_targ[L3_MODULES] = {
- l3_targ_stderrlog_main_clk1,
- l3_targ_stderrlog_main_clk2,
- l3_targ_stderrlog_main_clk3,
+static u32 *l3_targ[L3_MODULES] = {
+ l3_targ_inst_clk1,
+ l3_targ_inst_clk2,
+ l3_targ_inst_clk3,
};
struct omap4_l3 {
- struct device *dev;
- struct clk *ick;
+ struct device *dev;
+ struct clk *ick;
/* memory base */
- void __iomem *l3_base[4];
+ void __iomem *l3_base[L3_MODULES];
- int debug_irq;
- int app_irq;
+ int debug_irq;
+ int app_irq;
};
-
#endif
diff --git a/arch/arm/mach-omap2/omap_l3_smx.c b/arch/arm/mach-omap2/omap_l3_smx.c
index 873c0e33b512..a05a62f9ee5b 100644
--- a/arch/arm/mach-omap2/omap_l3_smx.c
+++ b/arch/arm/mach-omap2/omap_l3_smx.c
@@ -1,26 +1,26 @@
- /*
- * OMAP3XXX L3 Interconnect Driver
- *
- * Copyright (C) 2011 Texas Corporation
- * Felipe Balbi <balbi@ti.com>
- * Santosh Shilimkar <santosh.shilimkar@ti.com>
- * Sricharan <r.sricharan@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; 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
- */
+/*
+ * OMAP3XXX L3 Interconnect Driver
+ *
+ * Copyright (C) 2011 Texas Corporation
+ * Felipe Balbi <balbi@ti.com>
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ * Sricharan <r.sricharan@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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -135,7 +135,7 @@ static char *omap3_l3_initiator_string(u8 initid)
}
}
-/**
+/*
* omap3_l3_block_irq - handles a register block's irq
* @l3: struct omap3_l3 *
* @base: register block base address
@@ -150,30 +150,29 @@ static char *omap3_l3_initiator_string(u8 initid)
static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
u64 error, int error_addr)
{
- u8 code = omap3_l3_decode_error_code(error);
- u8 initid = omap3_l3_decode_initid(error);
- u8 multi = error & L3_ERROR_LOG_MULTI;
- u32 address = omap3_l3_decode_addr(error_addr);
+ u8 code = omap3_l3_decode_error_code(error);
+ u8 initid = omap3_l3_decode_initid(error);
+ u8 multi = error & L3_ERROR_LOG_MULTI;
+ u32 address = omap3_l3_decode_addr(error_addr);
WARN(true, "%s seen by %s %s at address %x\n",
- omap3_l3_code_string(code),
- omap3_l3_initiator_string(initid),
- multi ? "Multiple Errors" : "",
- address);
+ omap3_l3_code_string(code),
+ omap3_l3_initiator_string(initid),
+ multi ? "Multiple Errors" : "", address);
return IRQ_HANDLED;
}
static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
{
- struct omap3_l3 *l3 = _l3;
- u64 status, clear;
- u64 error;
- u64 error_addr;
- u64 err_source = 0;
- void __iomem *base;
- int int_type;
- irqreturn_t ret = IRQ_NONE;
+ struct omap3_l3 *l3 = _l3;
+ u64 status, clear;
+ u64 error;
+ u64 error_addr;
+ u64 err_source = 0;
+ void __iomem *base;
+ int int_type;
+ irqreturn_t ret = IRQ_NONE;
int_type = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
if (!int_type) {
@@ -191,14 +190,12 @@ static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
}
/* identify the error source */
- for (err_source = 0; !(status & (1 << err_source)); err_source++)
- ;
+ err_source = __ffs(status);
- base = l3->rt + *(omap3_l3_bases[int_type] + err_source);
+ base = l3->rt + omap3_l3_bases[int_type][err_source];
error = omap3_l3_readll(base, L3_ERROR_LOG);
if (error) {
error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
-
ret |= omap3_l3_block_irq(l3, error, error_addr);
}
@@ -215,9 +212,9 @@ static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
static int __init omap3_l3_probe(struct platform_device *pdev)
{
- struct omap3_l3 *l3;
- struct resource *res;
- int ret;
+ struct omap3_l3 *l3;
+ struct resource *res;
+ int ret;
l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
if (!l3)
diff --git a/arch/arm/mach-omap2/omap_l3_smx.h b/arch/arm/mach-omap2/omap_l3_smx.h
index ba2ed9a850cc..4f3cebca4179 100644
--- a/arch/arm/mach-omap2/omap_l3_smx.h
+++ b/arch/arm/mach-omap2/omap_l3_smx.h
@@ -1,26 +1,26 @@
- /*
- * OMAP3XXX L3 Interconnect Driver header
- *
- * Copyright (C) 2011 Texas Corporation
- * Felipe Balbi <balbi@ti.com>
- * Santosh Shilimkar <santosh.shilimkar@ti.com>
- * sricharan <r.sricharan@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; 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
- */
+/*
+ * OMAP3XXX L3 Interconnect Driver header
+ *
+ * Copyright (C) 2011 Texas Corporation
+ * Felipe Balbi <balbi@ti.com>
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ * sricharan <r.sricharan@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; 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 __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
@@ -40,7 +40,7 @@
#define L3_SI_CONTROL 0x020
#define L3_SI_FLAG_STATUS_0 0x510
-const u64 shift = 1;
+static const u64 shift = 1;
#define L3_STATUS_0_MPUIA_BRST (shift << 0)
#define L3_STATUS_0_MPUIA_RSP (shift << 1)
@@ -78,32 +78,32 @@ const u64 shift = 1;
#define L3_STATUS_0_L4EMUTA_REQ (shift << 60)
#define L3_STATUS_0_MAD2DTA_REQ (shift << 61)
-#define L3_STATUS_0_TIMEOUT_MASK (L3_STATUS_0_MPUIA_BRST \
- | L3_STATUS_0_MPUIA_RSP \
- | L3_STATUS_0_IVAIA_BRST \
- | L3_STATUS_0_IVAIA_RSP \
- | L3_STATUS_0_SGXIA_BRST \
- | L3_STATUS_0_SGXIA_RSP \
- | L3_STATUS_0_CAMIA_BRST \
- | L3_STATUS_0_CAMIA_RSP \
- | L3_STATUS_0_DISPIA_BRST \
- | L3_STATUS_0_DISPIA_RSP \
- | L3_STATUS_0_DMARDIA_BRST \
- | L3_STATUS_0_DMARDIA_RSP \
- | L3_STATUS_0_DMAWRIA_BRST \
- | L3_STATUS_0_DMAWRIA_RSP \
- | L3_STATUS_0_USBOTGIA_BRST \
- | L3_STATUS_0_USBOTGIA_RSP \
- | L3_STATUS_0_USBHOSTIA_BRST \
- | L3_STATUS_0_SMSTA_REQ \
- | L3_STATUS_0_GPMCTA_REQ \
- | L3_STATUS_0_OCMRAMTA_REQ \
- | L3_STATUS_0_OCMROMTA_REQ \
- | L3_STATUS_0_IVATA_REQ \
- | L3_STATUS_0_SGXTA_REQ \
- | L3_STATUS_0_L4CORETA_REQ \
- | L3_STATUS_0_L4PERTA_REQ \
- | L3_STATUS_0_L4EMUTA_REQ \
+#define L3_STATUS_0_TIMEOUT_MASK (L3_STATUS_0_MPUIA_BRST \
+ | L3_STATUS_0_MPUIA_RSP \
+ | L3_STATUS_0_IVAIA_BRST \
+ | L3_STATUS_0_IVAIA_RSP \
+ | L3_STATUS_0_SGXIA_BRST \
+ | L3_STATUS_0_SGXIA_RSP \
+ | L3_STATUS_0_CAMIA_BRST \
+ | L3_STATUS_0_CAMIA_RSP \
+ | L3_STATUS_0_DISPIA_BRST \
+ | L3_STATUS_0_DISPIA_RSP \
+ | L3_STATUS_0_DMARDIA_BRST \
+ | L3_STATUS_0_DMARDIA_RSP \
+ | L3_STATUS_0_DMAWRIA_BRST \
+ | L3_STATUS_0_DMAWRIA_RSP \
+ | L3_STATUS_0_USBOTGIA_BRST \
+ | L3_STATUS_0_USBOTGIA_RSP \
+ | L3_STATUS_0_USBHOSTIA_BRST \
+ | L3_STATUS_0_SMSTA_REQ \
+ | L3_STATUS_0_GPMCTA_REQ \
+ | L3_STATUS_0_OCMRAMTA_REQ \
+ | L3_STATUS_0_OCMROMTA_REQ \
+ | L3_STATUS_0_IVATA_REQ \
+ | L3_STATUS_0_SGXTA_REQ \
+ | L3_STATUS_0_L4CORETA_REQ \
+ | L3_STATUS_0_L4PERTA_REQ \
+ | L3_STATUS_0_L4EMUTA_REQ \
| L3_STATUS_0_MAD2DTA_REQ)
#define L3_SI_FLAG_STATUS_1 0x530
@@ -137,19 +137,19 @@ const u64 shift = 1;
enum omap3_l3_initiator_id {
/* LCD has 1 ID */
- OMAP_L3_LCD = 29,
+ OMAP_L3_LCD = 29,
/* SAD2D has 1 ID */
- OMAP_L3_SAD2D = 28,
+ OMAP_L3_SAD2D = 28,
/* MPU has 5 IDs */
- OMAP_L3_IA_MPU_SS_1 = 27,
- OMAP_L3_IA_MPU_SS_2 = 26,
- OMAP_L3_IA_MPU_SS_3 = 25,
- OMAP_L3_IA_MPU_SS_4 = 24,
- OMAP_L3_IA_MPU_SS_5 = 23,
+ OMAP_L3_IA_MPU_SS_1 = 27,
+ OMAP_L3_IA_MPU_SS_2 = 26,
+ OMAP_L3_IA_MPU_SS_3 = 25,
+ OMAP_L3_IA_MPU_SS_4 = 24,
+ OMAP_L3_IA_MPU_SS_5 = 23,
/* IVA2.2 SS has 3 IDs*/
- OMAP_L3_IA_IVA_SS_1 = 22,
- OMAP_L3_IA_IVA_SS_2 = 21,
- OMAP_L3_IA_IVA_SS_3 = 20,
+ OMAP_L3_IA_IVA_SS_1 = 22,
+ OMAP_L3_IA_IVA_SS_2 = 21,
+ OMAP_L3_IA_IVA_SS_3 = 20,
/* IVA 2.2 SS DMA has 6 IDS */
OMAP_L3_IA_IVA_SS_DMA_1 = 19,
OMAP_L3_IA_IVA_SS_DMA_2 = 18,
@@ -158,25 +158,25 @@ enum omap3_l3_initiator_id {
OMAP_L3_IA_IVA_SS_DMA_5 = 15,
OMAP_L3_IA_IVA_SS_DMA_6 = 14,
/* SGX has 1 ID */
- OMAP_L3_IA_SGX = 13,
+ OMAP_L3_IA_SGX = 13,
/* CAM has 3 ID */
- OMAP_L3_IA_CAM_1 = 12,
- OMAP_L3_IA_CAM_2 = 11,
- OMAP_L3_IA_CAM_3 = 10,
+ OMAP_L3_IA_CAM_1 = 12,
+ OMAP_L3_IA_CAM_2 = 11,
+ OMAP_L3_IA_CAM_3 = 10,
/* DAP has 1 ID */
- OMAP_L3_IA_DAP = 9,
+ OMAP_L3_IA_DAP = 9,
/* SDMA WR has 2 IDs */
- OMAP_L3_SDMA_WR_1 = 8,
- OMAP_L3_SDMA_WR_2 = 7,
+ OMAP_L3_SDMA_WR_1 = 8,
+ OMAP_L3_SDMA_WR_2 = 7,
/* SDMA RD has 4 IDs */
- OMAP_L3_SDMA_RD_1 = 6,
- OMAP_L3_SDMA_RD_2 = 5,
- OMAP_L3_SDMA_RD_3 = 4,
- OMAP_L3_SDMA_RD_4 = 3,
+ OMAP_L3_SDMA_RD_1 = 6,
+ OMAP_L3_SDMA_RD_2 = 5,
+ OMAP_L3_SDMA_RD_3 = 4,
+ OMAP_L3_SDMA_RD_4 = 3,
/* HSUSB OTG has 1 ID */
- OMAP_L3_USBOTG = 2,
+ OMAP_L3_USBOTG = 2,
/* HSUSB HOST has 1 ID */
- OMAP_L3_USBHOST = 1,
+ OMAP_L3_USBHOST = 1,
};
enum omap3_l3_code {
@@ -192,21 +192,21 @@ enum omap3_l3_code {
};
struct omap3_l3 {
- struct device *dev;
- struct clk *ick;
+ struct device *dev;
+ struct clk *ick;
/* memory base*/
- void __iomem *rt;
+ void __iomem *rt;
- int debug_irq;
- int app_irq;
+ int debug_irq;
+ int app_irq;
/* true when and inband functional error occurs */
- unsigned inband:1;
+ unsigned inband:1;
};
/* offsets for l3 agents in order with the Flag status register */
-unsigned int __iomem omap3_l3_app_bases[] = {
+static unsigned int omap3_l3_app_bases[] = {
/* MPU IA */
0x1400,
0x1400,
@@ -305,7 +305,7 @@ unsigned int __iomem omap3_l3_app_bases[] = {
0,
};
-unsigned int __iomem omap3_l3_debug_bases[] = {
+static unsigned int omap3_l3_debug_bases[] = {
/* MPU DATA IA */
0x1400,
/* RESERVED */
@@ -321,7 +321,7 @@ unsigned int __iomem omap3_l3_debug_bases[] = {
/* REST RESERVED */
};
-u32 *omap3_l3_bases[] = {
+static u32 *omap3_l3_bases[] = {
omap3_l3_app_bases,
omap3_l3_debug_bases,
};
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index 07d6140baa9d..f515a1a056d5 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -42,8 +42,11 @@
#define OMAP4_SRI2C_SLAVE_ADDR 0x12
#define OMAP4_VDD_MPU_SR_VOLT_REG 0x55
+#define OMAP4_VDD_MPU_SR_CMD_REG 0x56
#define OMAP4_VDD_IVA_SR_VOLT_REG 0x5B
+#define OMAP4_VDD_IVA_SR_CMD_REG 0x5C
#define OMAP4_VDD_CORE_SR_VOLT_REG 0x61
+#define OMAP4_VDD_CORE_SR_CMD_REG 0x62
#define OMAP4_VP_CONFIG_ERROROFFSET 0x00
#define OMAP4_VP_VSTEPMIN_VSTEPMIN 0x01
@@ -95,6 +98,8 @@ static unsigned long twl6030_vsel_to_uv(const u8 vsel)
is_offset_valid = true;
}
+ if (!vsel)
+ return 0;
/*
* There is no specific formula for voltage to vsel
* conversion above 1.3V. There are special hardcoded
@@ -106,9 +111,9 @@ static unsigned long twl6030_vsel_to_uv(const u8 vsel)
return 1350000;
if (smps_offset & 0x8)
- return ((((vsel - 1) * 125) + 7000)) * 100;
+ return ((((vsel - 1) * 1266) + 70900)) * 10;
else
- return ((((vsel - 1) * 125) + 6000)) * 100;
+ return ((((vsel - 1) * 1266) + 60770)) * 10;
}
static u8 twl6030_uv_to_vsel(unsigned long uv)
@@ -127,6 +132,8 @@ static u8 twl6030_uv_to_vsel(unsigned long uv)
is_offset_valid = true;
}
+ if (!uv)
+ return 0x00;
/*
* There is no specific formula for voltage to vsel
* conversion above 1.3V. There are special hardcoded
@@ -134,16 +141,21 @@ static u8 twl6030_uv_to_vsel(unsigned long uv)
* hardcoding only for 1.35 V which is used for 1GH OPP for
* OMAP4430.
*/
- if (uv == 1350000)
+ if (uv > twl6030_vsel_to_uv(0x39)) {
+ if (uv == 1350000)
+ return 0x3A;
+ pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n",
+ __func__, uv, twl6030_vsel_to_uv(0x39));
return 0x3A;
+ }
if (smps_offset & 0x8)
- return DIV_ROUND_UP(uv - 700000, 12500) + 1;
+ return DIV_ROUND_UP(uv - 709000, 12660) + 1;
else
- return DIV_ROUND_UP(uv - 600000, 12500) + 1;
+ return DIV_ROUND_UP(uv - 607700, 12660) + 1;
}
-static struct omap_volt_pmic_info omap3_mpu_volt_info = {
+static struct omap_voltdm_pmic omap3_mpu_pmic = {
.slew_rate = 4000,
.step_size = 12500,
.on_volt = 1200000,
@@ -158,12 +170,13 @@ static struct omap_volt_pmic_info omap3_mpu_volt_info = {
.vp_vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX,
.vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
- .pmic_reg = OMAP3_VDD_MPU_SR_CONTROL_REG,
+ .volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG,
+ .i2c_high_speed = true,
.vsel_to_uv = twl4030_vsel_to_uv,
.uv_to_vsel = twl4030_uv_to_vsel,
};
-static struct omap_volt_pmic_info omap3_core_volt_info = {
+static struct omap_voltdm_pmic omap3_core_pmic = {
.slew_rate = 4000,
.step_size = 12500,
.on_volt = 1200000,
@@ -178,18 +191,19 @@ static struct omap_volt_pmic_info omap3_core_volt_info = {
.vp_vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX,
.vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
- .pmic_reg = OMAP3_VDD_CORE_SR_CONTROL_REG,
+ .volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG,
+ .i2c_high_speed = true,
.vsel_to_uv = twl4030_vsel_to_uv,
.uv_to_vsel = twl4030_uv_to_vsel,
};
-static struct omap_volt_pmic_info omap4_mpu_volt_info = {
+static struct omap_voltdm_pmic omap4_mpu_pmic = {
.slew_rate = 4000,
- .step_size = 12500,
- .on_volt = 1350000,
- .onlp_volt = 1350000,
- .ret_volt = 837500,
- .off_volt = 600000,
+ .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,
@@ -198,18 +212,20 @@ static struct omap_volt_pmic_info omap4_mpu_volt_info = {
.vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
- .pmic_reg = OMAP4_VDD_MPU_SR_VOLT_REG,
+ .volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG,
+ .cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG,
+ .i2c_high_speed = true,
.vsel_to_uv = twl6030_vsel_to_uv,
.uv_to_vsel = twl6030_uv_to_vsel,
};
-static struct omap_volt_pmic_info omap4_iva_volt_info = {
+static struct omap_voltdm_pmic omap4_iva_pmic = {
.slew_rate = 4000,
- .step_size = 12500,
- .on_volt = 1100000,
- .onlp_volt = 1100000,
- .ret_volt = 837500,
- .off_volt = 600000,
+ .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,
@@ -218,18 +234,20 @@ static struct omap_volt_pmic_info omap4_iva_volt_info = {
.vp_vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
- .pmic_reg = OMAP4_VDD_IVA_SR_VOLT_REG,
+ .volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG,
+ .cmd_reg_addr = OMAP4_VDD_IVA_SR_CMD_REG,
+ .i2c_high_speed = true,
.vsel_to_uv = twl6030_vsel_to_uv,
.uv_to_vsel = twl6030_uv_to_vsel,
};
-static struct omap_volt_pmic_info omap4_core_volt_info = {
+static struct omap_voltdm_pmic omap4_core_pmic = {
.slew_rate = 4000,
- .step_size = 12500,
- .on_volt = 1100000,
- .onlp_volt = 1100000,
- .ret_volt = 837500,
- .off_volt = 600000,
+ .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,
@@ -238,7 +256,8 @@ static struct omap_volt_pmic_info omap4_core_volt_info = {
.vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
- .pmic_reg = OMAP4_VDD_CORE_SR_VOLT_REG,
+ .volt_reg_addr = OMAP4_VDD_CORE_SR_VOLT_REG,
+ .cmd_reg_addr = OMAP4_VDD_CORE_SR_CMD_REG,
.vsel_to_uv = twl6030_vsel_to_uv,
.uv_to_vsel = twl6030_uv_to_vsel,
};
@@ -250,14 +269,14 @@ int __init omap4_twl_init(void)
if (!cpu_is_omap44xx())
return -ENODEV;
- voltdm = omap_voltage_domain_lookup("mpu");
- omap_voltage_register_pmic(voltdm, &omap4_mpu_volt_info);
+ voltdm = voltdm_lookup("mpu");
+ omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic);
- voltdm = omap_voltage_domain_lookup("iva");
- omap_voltage_register_pmic(voltdm, &omap4_iva_volt_info);
+ voltdm = voltdm_lookup("iva");
+ omap_voltage_register_pmic(voltdm, &omap4_iva_pmic);
- voltdm = omap_voltage_domain_lookup("core");
- omap_voltage_register_pmic(voltdm, &omap4_core_volt_info);
+ voltdm = voltdm_lookup("core");
+ omap_voltage_register_pmic(voltdm, &omap4_core_pmic);
return 0;
}
@@ -270,10 +289,10 @@ int __init omap3_twl_init(void)
return -ENODEV;
if (cpu_is_omap3630()) {
- omap3_mpu_volt_info.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
- omap3_mpu_volt_info.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
- omap3_core_volt_info.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
- omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
+ 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;
}
/*
@@ -288,11 +307,11 @@ int __init omap3_twl_init(void)
if (!twl_sr_enable_autoinit)
omap3_twl_set_sr_bit(true);
- voltdm = omap_voltage_domain_lookup("mpu");
- omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info);
+ voltdm = voltdm_lookup("mpu_iva");
+ omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
- voltdm = omap_voltage_domain_lookup("core");
- omap_voltage_register_pmic(voltdm, &omap3_core_volt_info);
+ voltdm = voltdm_lookup("core");
+ omap_voltage_register_pmic(voltdm, &omap3_core_pmic);
return 0;
}
diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
index ab8b35b780b5..9262a6b47702 100644
--- a/arch/arm/mach-omap2/opp.c
+++ b/arch/arm/mach-omap2/opp.c
@@ -69,7 +69,7 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
opp_def->hwmod_name, i);
return -EINVAL;
}
- dev = &oh->od->pdev.dev;
+ dev = &oh->od->pdev->dev;
r = opp_add(dev, opp_def->freq, opp_def->u_volt);
if (r) {
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 472bf22d5e84..2ab7a9e17fe2 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -26,54 +26,21 @@
static struct omap_device_pm_latency *pm_lats;
-static struct device *mpu_dev;
-static struct device *iva_dev;
-static struct device *l3_dev;
-static struct device *dsp_dev;
-
-struct device *omap2_get_mpuss_device(void)
-{
- WARN_ON_ONCE(!mpu_dev);
- return mpu_dev;
-}
-
-struct device *omap2_get_iva_device(void)
-{
- WARN_ON_ONCE(!iva_dev);
- return iva_dev;
-}
-
-struct device *omap2_get_l3_device(void)
-{
- WARN_ON_ONCE(!l3_dev);
- return l3_dev;
-}
-
-struct device *omap4_get_dsp_device(void)
-{
- WARN_ON_ONCE(!dsp_dev);
- return dsp_dev;
-}
-EXPORT_SYMBOL(omap4_get_dsp_device);
-
-/* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
-static int _init_omap_device(char *name, struct device **new_dev)
+static int _init_omap_device(char *name)
{
struct omap_hwmod *oh;
- struct omap_device *od;
+ struct platform_device *pdev;
oh = omap_hwmod_lookup(name);
if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
__func__, name))
return -ENODEV;
- od = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false);
- if (WARN(IS_ERR(od), "%s: could not build omap_device for %s\n",
+ pdev = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false);
+ if (WARN(IS_ERR(pdev), "%s: could not build omap_device for %s\n",
__func__, name))
return -ENODEV;
- *new_dev = &od->pdev.dev;
-
return 0;
}
@@ -82,16 +49,16 @@ static int _init_omap_device(char *name, struct device **new_dev)
*/
static void omap2_init_processor_devices(void)
{
- _init_omap_device("mpu", &mpu_dev);
+ _init_omap_device("mpu");
if (omap3_has_iva())
- _init_omap_device("iva", &iva_dev);
+ _init_omap_device("iva");
if (cpu_is_omap44xx()) {
- _init_omap_device("l3_main_1", &l3_dev);
- _init_omap_device("dsp", &dsp_dev);
- _init_omap_device("iva", &iva_dev);
+ _init_omap_device("l3_main_1");
+ _init_omap_device("dsp");
+ _init_omap_device("iva");
} else {
- _init_omap_device("l3_main", &l3_dev);
+ _init_omap_device("l3_main");
}
}
@@ -136,8 +103,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
ret = pwrdm_set_next_pwrst(pwrdm, state);
if (ret) {
- printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
- pwrdm->name);
+ pr_err("%s: unable to set state of powerdomain: %s\n",
+ __func__, pwrdm->name);
goto err;
}
@@ -161,37 +128,44 @@ err:
}
/*
- * This API is to be called during init to put the various voltage
+ * This API is to be called during init to set the various voltage
* domains to the voltage as per the opp table. Typically we boot up
* at the nominal voltage. So this function finds out the rate of
* the clock associated with the voltage domain, finds out the correct
- * opp entry and puts the voltage domain to the voltage specifies
+ * opp entry and sets the voltage domain to the voltage specified
* in the opp entry
*/
static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
- struct device *dev)
+ const char *oh_name)
{
struct voltagedomain *voltdm;
struct clk *clk;
struct opp *opp;
unsigned long freq, bootup_volt;
+ struct device *dev;
+
+ if (!vdd_name || !clk_name || !oh_name) {
+ pr_err("%s: invalid parameters\n", __func__);
+ goto exit;
+ }
- if (!vdd_name || !clk_name || !dev) {
- printk(KERN_ERR "%s: Invalid parameters!\n", __func__);
+ dev = omap_device_get_by_hwmod_name(oh_name);
+ if (IS_ERR(dev)) {
+ pr_err("%s: Unable to get dev pointer for hwmod %s\n",
+ __func__, oh_name);
goto exit;
}
- voltdm = omap_voltage_domain_lookup(vdd_name);
+ voltdm = voltdm_lookup(vdd_name);
if (IS_ERR(voltdm)) {
- printk(KERN_ERR "%s: Unable to get vdd pointer for vdd_%s\n",
+ pr_err("%s: unable to get vdd pointer for vdd_%s\n",
__func__, vdd_name);
goto exit;
}
clk = clk_get(NULL, clk_name);
if (IS_ERR(clk)) {
- printk(KERN_ERR "%s: unable to get clk %s\n",
- __func__, clk_name);
+ pr_err("%s: unable to get clk %s\n", __func__, clk_name);
goto exit;
}
@@ -200,24 +174,23 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
opp = opp_find_freq_ceil(dev, &freq);
if (IS_ERR(opp)) {
- printk(KERN_ERR "%s: unable to find boot up OPP for vdd_%s\n",
+ pr_err("%s: unable to find boot up OPP for vdd_%s\n",
__func__, vdd_name);
goto exit;
}
bootup_volt = opp_get_voltage(opp);
if (!bootup_volt) {
- printk(KERN_ERR "%s: unable to find voltage corresponding"
+ pr_err("%s: unable to find voltage corresponding "
"to the bootup OPP for vdd_%s\n", __func__, vdd_name);
goto exit;
}
- omap_voltage_scale_vdd(voltdm, bootup_volt);
+ voltdm_scale(voltdm, bootup_volt);
return 0;
exit:
- printk(KERN_ERR "%s: Unable to put vdd_%s to its init voltage\n\n",
- __func__, vdd_name);
+ pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name);
return -EINVAL;
}
@@ -226,8 +199,8 @@ static void __init omap3_init_voltages(void)
if (!cpu_is_omap34xx())
return;
- omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev);
- omap2_set_init_voltage("core", "l3_ick", l3_dev);
+ omap2_set_init_voltage("mpu_iva", "dpll1_ck", "mpu");
+ omap2_set_init_voltage("core", "l3_ick", "l3_main");
}
static void __init omap4_init_voltages(void)
@@ -235,14 +208,15 @@ static void __init omap4_init_voltages(void)
if (!cpu_is_omap44xx())
return;
- omap2_set_init_voltage("mpu", "dpll_mpu_ck", mpu_dev);
- omap2_set_init_voltage("core", "l3_div_ck", l3_dev);
- omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", iva_dev);
+ omap2_set_init_voltage("mpu", "dpll_mpu_ck", "mpu");
+ omap2_set_init_voltage("core", "l3_div_ck", "l3_main_1");
+ omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva");
}
static int __init omap2_common_pm_init(void)
{
- omap2_init_processor_devices();
+ if (!of_have_populated_dt())
+ omap2_init_processor_devices();
omap_pm_if_init();
return 0;
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index bf089e743ed9..cf0c216132ab 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -53,8 +53,6 @@
#include "powerdomain.h"
#include "clockdomain.h"
-static int omap2_pm_debug;
-
#ifdef CONFIG_SUSPEND
static suspend_state_t suspend_state = PM_SUSPEND_ON;
static inline bool is_suspending(void)
@@ -96,7 +94,6 @@ static int omap2_fclks_active(void)
static void omap2_enter_full_retention(void)
{
u32 l;
- struct timespec ts_preidle, ts_postidle, ts_idle;
/* There is 1 reference hold for all children of the oscillator
* clock, the following will remove it. If no one else uses the
@@ -124,10 +121,6 @@ static void omap2_enter_full_retention(void)
omap2_gpio_prepare_for_idle(0);
- if (omap2_pm_debug) {
- getnstimeofday(&ts_preidle);
- }
-
/* One last check for pending IRQs to avoid extra latency due
* to sleeping unnecessarily. */
if (omap_irq_pending())
@@ -155,13 +148,6 @@ static void omap2_enter_full_retention(void)
console_unlock();
no_sleep:
- if (omap2_pm_debug) {
- unsigned long long tmp;
-
- getnstimeofday(&ts_postidle);
- ts_idle = timespec_sub(ts_postidle, ts_preidle);
- tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
- }
omap2_gpio_resume_after_idle();
clk_enable(osc_ck);
@@ -219,7 +205,6 @@ static int omap2_allow_mpu_retention(void)
static void omap2_enter_mpu_retention(void)
{
int only_idle = 0;
- struct timespec ts_preidle, ts_postidle, ts_idle;
/* Putting MPU into the WFI state while a transfer is active
* seems to cause the I2C block to timeout. Why? Good question. */
@@ -246,19 +231,7 @@ static void omap2_enter_mpu_retention(void)
only_idle = 1;
}
- if (omap2_pm_debug) {
- getnstimeofday(&ts_preidle);
- }
-
omap2_sram_idle();
-
- if (omap2_pm_debug) {
- unsigned long long tmp;
-
- getnstimeofday(&ts_postidle);
- ts_idle = timespec_sub(ts_postidle, ts_preidle);
- tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
- }
}
static int omap2_can_sleep(void)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7255d9bce868..c8cbd00a41af 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -55,7 +55,7 @@
static suspend_state_t suspend_state = PM_SUSPEND_ON;
static inline bool is_suspending(void)
{
- return (suspend_state != PM_SUSPEND_ON);
+ return (suspend_state != PM_SUSPEND_ON) && console_suspend_enabled;
}
#else
static inline bool is_suspending(void)
diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
index 171fccd208c7..f97afff68d6d 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -1,9 +1,8 @@
/*
- * linux/arch/arm/mach-omap2/powerdomain-common.c
- * Contains common powerdomain framework functions
+ * Common powerdomain framework functions
*
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2010-2011 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
*
* Derived from mach-omap2/powerdomain.c written by Paul Walmsley
*
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index ef71fdd40fc4..5164d587ef52 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1,7 +1,7 @@
/*
* OMAP powerdomain control
*
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
* Copyright (C) 2007-2011 Nokia Corporation
*
* Written by Paul Walmsley
@@ -77,13 +77,11 @@ static struct powerdomain *_pwrdm_lookup(const char *name)
static int _pwrdm_register(struct powerdomain *pwrdm)
{
int i;
+ struct voltagedomain *voltdm;
if (!pwrdm || !pwrdm->name)
return -EINVAL;
- if (!omap_chip_is(pwrdm->omap_chip))
- return -EINVAL;
-
if (cpu_is_omap44xx() &&
pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) {
pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n",
@@ -94,6 +92,16 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
if (_pwrdm_lookup(pwrdm->name))
return -EEXIST;
+ voltdm = voltdm_lookup(pwrdm->voltdm.name);
+ if (!voltdm) {
+ pr_err("powerdomain: %s: voltagedomain %s does not exist\n",
+ pwrdm->name, pwrdm->voltdm.name);
+ return -EINVAL;
+ }
+ pwrdm->voltdm.ptr = voltdm;
+ INIT_LIST_HEAD(&pwrdm->voltdm_node);
+ voltdm_add_pwrdm(voltdm, pwrdm);
+
list_add(&pwrdm->node, &pwrdm_list);
/* Initialize the powerdomain's state counter */
@@ -194,36 +202,76 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
/* Public functions */
/**
- * pwrdm_init - set up the powerdomain layer
- * @pwrdms: array of struct powerdomain pointers to register
- * @custom_funcs: func pointers for arch specific implementations
+ * pwrdm_register_platform_funcs - register powerdomain implementation fns
+ * @po: func pointers for arch specific implementations
*
- * Loop through the array of powerdomains @pwrdms, registering all
- * that are available on the current CPU. Also, program all
- * powerdomain target state as ON; this is to prevent domains from
- * hitting low power states (if bootloader has target states set to
- * something other than ON) and potentially even losing context while
- * PM is not fully initialized. The PM late init code can then program
- * the desired target state for all the power domains. No return
- * value.
+ * Register the list of function pointers used to implement the
+ * powerdomain functions on different OMAP SoCs. Should be called
+ * before any other pwrdm_register*() function. Returns -EINVAL if
+ * @po is null, -EEXIST if platform functions have already been
+ * registered, or 0 upon success.
*/
-void pwrdm_init(struct powerdomain **pwrdms, struct pwrdm_ops *custom_funcs)
+int pwrdm_register_platform_funcs(struct pwrdm_ops *po)
+{
+ if (!po)
+ return -EINVAL;
+
+ if (arch_pwrdm)
+ return -EEXIST;
+
+ arch_pwrdm = po;
+
+ return 0;
+}
+
+/**
+ * pwrdm_register_pwrdms - register SoC powerdomains
+ * @ps: pointer to an array of struct powerdomain to register
+ *
+ * Register the powerdomains available on a particular OMAP SoC. Must
+ * be called after pwrdm_register_platform_funcs(). May be called
+ * multiple times. Returns -EACCES if called before
+ * pwrdm_register_platform_funcs(); -EINVAL if the argument @ps is
+ * null; or 0 upon success.
+ */
+int pwrdm_register_pwrdms(struct powerdomain **ps)
{
struct powerdomain **p = NULL;
- struct powerdomain *temp_p;
- if (!custom_funcs)
- WARN(1, "powerdomain: No custom pwrdm functions registered\n");
- else
- arch_pwrdm = custom_funcs;
+ if (!arch_pwrdm)
+ return -EEXIST;
- if (pwrdms) {
- for (p = pwrdms; *p; p++)
- _pwrdm_register(*p);
- }
+ if (!ps)
+ return -EINVAL;
+
+ for (p = ps; *p; p++)
+ _pwrdm_register(*p);
+
+ return 0;
+}
+
+/**
+ * pwrdm_complete_init - set up the powerdomain layer
+ *
+ * Do whatever is necessary to initialize registered powerdomains and
+ * powerdomain code. Currently, this programs the next power state
+ * for each powerdomain to ON. This prevents powerdomains from
+ * unexpectedly losing context or entering high wakeup latency modes
+ * with non-power-management-enabled kernels. Must be called after
+ * pwrdm_register_pwrdms(). Returns -EACCES if called before
+ * pwrdm_register_pwrdms(), or 0 upon success.
+ */
+int pwrdm_complete_init(void)
+{
+ struct powerdomain *temp_p;
+
+ if (list_empty(&pwrdm_list))
+ return -EACCES;
list_for_each_entry(temp_p, &pwrdm_list, node)
pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
+
+ return 0;
}
/**
@@ -390,6 +438,18 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
}
/**
+ * pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in
+ * @pwrdm: struct powerdomain *
+ *
+ * Return a pointer to the struct voltageomain that the specified powerdomain
+ * @pwrdm exists in.
+ */
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm)
+{
+ return pwrdm->voltdm.ptr;
+}
+
+/**
* pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
* @pwrdm: struct powerdomain *
*
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index d23d979b9c34..42e6dd8f2a78 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -24,6 +24,8 @@
#include <plat/cpu.h>
+#include "voltage.h"
+
/* Powerdomain basic power states */
#define PWRDM_POWER_OFF 0x0
#define PWRDM_POWER_RET 0x1
@@ -78,7 +80,7 @@ struct powerdomain;
/**
* struct powerdomain - OMAP powerdomain
* @name: Powerdomain name
- * @omap_chip: represents the OMAP chip types containing this pwrdm
+ * @voltdm: voltagedomain containing this powerdomain
* @prcm_offs: the address offset from CM_BASE/PRM_BASE
* @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs
* @pwrsts: Possible powerdomain power states
@@ -89,6 +91,7 @@ struct powerdomain;
* @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
* @pwrdm_clkdms: Clockdomains in this powerdomain
* @node: list_head linking all powerdomains
+ * @voltdm_node: list_head linking all powerdomains in a voltagedomain
* @state:
* @state_counter:
* @timer:
@@ -98,7 +101,10 @@ struct powerdomain;
*/
struct powerdomain {
const char *name;
- const struct omap_chip_id omap_chip;
+ union {
+ const char *name;
+ struct voltagedomain *ptr;
+ } voltdm;
const s16 prcm_offs;
const u8 pwrsts;
const u8 pwrsts_logic_ret;
@@ -109,6 +115,7 @@ struct powerdomain {
const u8 prcm_partition;
struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
struct list_head node;
+ struct list_head voltdm_node;
int state;
unsigned state_counter[PWRDM_MAX_PWRSTS];
unsigned ret_logic_off_counter;
@@ -162,7 +169,9 @@ struct pwrdm_ops {
int (*pwrdm_wait_transition)(struct powerdomain *pwrdm);
};
-void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs);
+int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
+int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
+int pwrdm_complete_init(void);
struct powerdomain *pwrdm_lookup(const char *name);
@@ -176,6 +185,7 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
int (*fn)(struct powerdomain *pwrdm,
struct clockdomain *clkdm));
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
@@ -210,7 +220,8 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
-extern void omap2xxx_powerdomains_init(void);
+extern void omap242x_powerdomains_init(void);
+extern void omap243x_powerdomains_init(void);
extern void omap3xxx_powerdomains_init(void);
extern void omap44xx_powerdomains_init(void);
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index cf600e22bf8e..6a17e4ca1d79 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -1,7 +1,7 @@
/*
* OMAP2 and OMAP3 powerdomain control
*
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
* Copyright (C) 2007-2009 Nokia Corporation
*
* Derived from mach-omap2/powerdomain.c written by Paul Walmsley
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
index 4210c3399769..d3a5399091ad 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
@@ -1,7 +1,7 @@
/*
* OMAP2/3 common powerdomain definitions
*
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
* Copyright (C) 2007-2011 Nokia Corporation
*
* Paul Walmsley, Jouni Högander
@@ -12,20 +12,6 @@
*/
/*
- * To Do List
- * -> Move the Sleep/Wakeup dependencies from Power Domain framework to
- * Clock Domain Framework
- */
-
-/*
- * This file contains all of the powerdomains that have some element
- * of software control for the OMAP24xx and OMAP34xx chips.
- *
- * This is not an exhaustive listing of powerdomains on the chips; only
- * powerdomains that can be controlled in software.
- */
-
-/*
* The names for the DSP/IVA2 powerdomains are confusing.
*
* Most OMAP chips have an on-board DSP.
@@ -59,8 +45,6 @@
struct powerdomain gfx_omap2_pwrdm = {
.name = "gfx_pwrdm",
.prcm_offs = GFX_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
- CHIP_IS_OMAP3430ES1),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_RET,
.banks = 1,
@@ -70,11 +54,12 @@ struct powerdomain gfx_omap2_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEMONSTATE */
},
+ .voltdm = { .name = "core" },
};
struct powerdomain wkup_omap2_pwrdm = {
.name = "wkup_pwrdm",
.prcm_offs = WKUP_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
.pwrsts = PWRSTS_ON,
+ .voltdm = { .name = "wakeup" },
};
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c
index cc389fb2005d..2385c1f009ee 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c
@@ -1,7 +1,7 @@
/*
* OMAP2XXX powerdomain definitions
*
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
* Copyright (C) 2007-2011 Nokia Corporation
*
* Paul Walmsley, Jouni Högander
@@ -28,7 +28,6 @@
static struct powerdomain dsp_pwrdm = {
.name = "dsp_pwrdm",
.prcm_offs = OMAP24XX_DSP_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_RET,
.banks = 1,
@@ -38,12 +37,12 @@ static struct powerdomain dsp_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON,
},
+ .voltdm = { .name = "core" },
};
static struct powerdomain mpu_24xx_pwrdm = {
.name = "mpu_pwrdm",
.prcm_offs = MPU_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
@@ -53,12 +52,12 @@ static struct powerdomain mpu_24xx_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON,
},
+ .voltdm = { .name = "core" },
};
static struct powerdomain core_24xx_pwrdm = {
.name = "core_pwrdm",
.prcm_offs = CORE_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
.pwrsts = PWRSTS_OFF_RET_ON,
.banks = 3,
.pwrsts_mem_ret = {
@@ -71,6 +70,7 @@ static struct powerdomain core_24xx_pwrdm = {
[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
[2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
},
+ .voltdm = { .name = "core" },
};
@@ -78,14 +78,11 @@ static struct powerdomain core_24xx_pwrdm = {
* 2430-specific powerdomains
*/
-#ifdef CONFIG_SOC_OMAP2430
-
/* XXX 2430 KILLDOMAINWKUP bit? No current users apparently */
static struct powerdomain mdm_pwrdm = {
.name = "mdm_pwrdm",
.prcm_offs = OMAP2430_MDM_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_RET,
.banks = 1,
@@ -95,29 +92,44 @@ static struct powerdomain mdm_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEMONSTATE */
},
+ .voltdm = { .name = "core" },
};
-#endif /* CONFIG_SOC_OMAP2430 */
-
-/* As powerdomains are added or removed above, this list must also be changed */
-static struct powerdomain *powerdomains_omap2xxx[] __initdata = {
+/*
+ *
+ */
+static struct powerdomain *powerdomains_omap24xx[] __initdata = {
&wkup_omap2_pwrdm,
&gfx_omap2_pwrdm,
-
-#ifdef CONFIG_ARCH_OMAP2
&dsp_pwrdm,
&mpu_24xx_pwrdm,
&core_24xx_pwrdm,
-#endif
+ NULL
+};
-#ifdef CONFIG_SOC_OMAP2430
+static struct powerdomain *powerdomains_omap2430[] __initdata = {
&mdm_pwrdm,
-#endif
NULL
};
-void __init omap2xxx_powerdomains_init(void)
+void __init omap242x_powerdomains_init(void)
+{
+ if (!cpu_is_omap2420())
+ return;
+
+ pwrdm_register_platform_funcs(&omap2_pwrdm_operations);
+ pwrdm_register_pwrdms(powerdomains_omap24xx);
+ pwrdm_complete_init();
+}
+
+void __init omap243x_powerdomains_init(void)
{
- pwrdm_init(powerdomains_omap2xxx, &omap2_pwrdm_operations);
+ if (!cpu_is_omap2430())
+ return;
+
+ pwrdm_register_platform_funcs(&omap2_pwrdm_operations);
+ pwrdm_register_pwrdms(powerdomains_omap24xx);
+ pwrdm_register_pwrdms(powerdomains_omap2430);
+ pwrdm_complete_init();
}
diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index 469a920a74dc..8ef26daeed68 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -1,7 +1,7 @@
/*
* OMAP3 powerdomain definitions
*
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
* Copyright (C) 2007-2011 Nokia Corporation
*
* Paul Walmsley, Jouni Högander
@@ -14,6 +14,8 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <plat/cpu.h>
+
#include "powerdomain.h"
#include "powerdomains2xxx_3xxx_data.h"
@@ -27,8 +29,6 @@
* 34XX-specific powerdomains, dependencies
*/
-#ifdef CONFIG_ARCH_OMAP3
-
/*
* Powerdomains
*/
@@ -36,7 +36,6 @@
static struct powerdomain iva2_pwrdm = {
.name = "iva2_pwrdm",
.prcm_offs = OMAP3430_IVA2_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 4,
@@ -52,12 +51,12 @@ static struct powerdomain iva2_pwrdm = {
[2] = PWRSTS_OFF_ON,
[3] = PWRSTS_ON,
},
+ .voltdm = { .name = "mpu_iva" },
};
static struct powerdomain mpu_3xxx_pwrdm = {
.name = "mpu_pwrdm",
.prcm_offs = MPU_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.flags = PWRDM_HAS_MPU_QUIRK,
@@ -68,6 +67,7 @@ static struct powerdomain mpu_3xxx_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_OFF_ON,
},
+ .voltdm = { .name = "mpu_iva" },
};
/*
@@ -83,10 +83,6 @@ static struct powerdomain mpu_3xxx_pwrdm = {
static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
.name = "core_pwrdm",
.prcm_offs = CORE_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
- CHIP_IS_OMAP3430ES2 |
- CHIP_IS_OMAP3430ES3_0 |
- CHIP_IS_OMAP3630ES1),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 2,
@@ -98,13 +94,12 @@ static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
},
+ .voltdm = { .name = "core" },
};
static struct powerdomain core_3xxx_es3_1_pwrdm = {
.name = "core_pwrdm",
.prcm_offs = CORE_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES3_1 |
- CHIP_GE_OMAP3630ES1_1),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
/*
@@ -121,11 +116,11 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
},
+ .voltdm = { .name = "core" },
};
static struct powerdomain dss_pwrdm = {
.name = "dss_pwrdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.prcm_offs = OMAP3430_DSS_MOD,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_RET,
@@ -136,6 +131,7 @@ static struct powerdomain dss_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEMONSTATE */
},
+ .voltdm = { .name = "core" },
};
/*
@@ -146,7 +142,6 @@ static struct powerdomain dss_pwrdm = {
static struct powerdomain sgx_pwrdm = {
.name = "sgx_pwrdm",
.prcm_offs = OMAP3430ES2_SGX_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
/* XXX This is accurate for 3430 SGX, but what about GFX? */
.pwrsts = PWRSTS_OFF_ON,
.pwrsts_logic_ret = PWRSTS_RET,
@@ -157,11 +152,11 @@ static struct powerdomain sgx_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEMONSTATE */
},
+ .voltdm = { .name = "core" },
};
static struct powerdomain cam_pwrdm = {
.name = "cam_pwrdm",
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.prcm_offs = OMAP3430_CAM_MOD,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_RET,
@@ -172,12 +167,12 @@ static struct powerdomain cam_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEMONSTATE */
},
+ .voltdm = { .name = "core" },
};
static struct powerdomain per_pwrdm = {
.name = "per_pwrdm",
.prcm_offs = OMAP3430_PER_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
@@ -187,26 +182,26 @@ static struct powerdomain per_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEMONSTATE */
},
+ .voltdm = { .name = "core" },
};
static struct powerdomain emu_pwrdm = {
.name = "emu_pwrdm",
.prcm_offs = OMAP3430_EMU_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+ .voltdm = { .name = "core" },
};
static struct powerdomain neon_pwrdm = {
.name = "neon_pwrdm",
.prcm_offs = OMAP3430_NEON_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_RET,
+ .voltdm = { .name = "mpu_iva" },
};
static struct powerdomain usbhost_pwrdm = {
.name = "usbhost_pwrdm",
.prcm_offs = OMAP3430ES2_USBHOST_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_RET,
/*
@@ -223,65 +218,103 @@ static struct powerdomain usbhost_pwrdm = {
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEMONSTATE */
},
+ .voltdm = { .name = "core" },
};
static struct powerdomain dpll1_pwrdm = {
.name = "dpll1_pwrdm",
.prcm_offs = MPU_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+ .voltdm = { .name = "mpu_iva" },
};
static struct powerdomain dpll2_pwrdm = {
.name = "dpll2_pwrdm",
.prcm_offs = OMAP3430_IVA2_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+ .voltdm = { .name = "mpu_iva" },
};
static struct powerdomain dpll3_pwrdm = {
.name = "dpll3_pwrdm",
.prcm_offs = PLL_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+ .voltdm = { .name = "core" },
};
static struct powerdomain dpll4_pwrdm = {
.name = "dpll4_pwrdm",
.prcm_offs = PLL_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+ .voltdm = { .name = "core" },
};
static struct powerdomain dpll5_pwrdm = {
.name = "dpll5_pwrdm",
.prcm_offs = PLL_MOD,
- .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+ .voltdm = { .name = "core" },
};
/* As powerdomains are added or removed above, this list must also be changed */
-static struct powerdomain *powerdomains_omap3xxx[] __initdata = {
-
+static struct powerdomain *powerdomains_omap3430_common[] __initdata = {
&wkup_omap2_pwrdm,
- &gfx_omap2_pwrdm,
&iva2_pwrdm,
&mpu_3xxx_pwrdm,
&neon_pwrdm,
- &core_3xxx_pre_es3_1_pwrdm,
- &core_3xxx_es3_1_pwrdm,
&cam_pwrdm,
&dss_pwrdm,
&per_pwrdm,
&emu_pwrdm,
- &sgx_pwrdm,
- &usbhost_pwrdm,
&dpll1_pwrdm,
&dpll2_pwrdm,
&dpll3_pwrdm,
&dpll4_pwrdm,
+ NULL
+};
+
+static struct powerdomain *powerdomains_omap3430es1[] __initdata = {
+ &gfx_omap2_pwrdm,
+ &core_3xxx_pre_es3_1_pwrdm,
+ NULL
+};
+
+/* also includes 3630ES1.0 */
+static struct powerdomain *powerdomains_omap3430es2_es3_0[] __initdata = {
+ &core_3xxx_pre_es3_1_pwrdm,
+ &sgx_pwrdm,
+ &usbhost_pwrdm,
&dpll5_pwrdm,
-#endif
NULL
};
+/* also includes 3630ES1.1+ */
+static struct powerdomain *powerdomains_omap3430es3_1plus[] __initdata = {
+ &core_3xxx_es3_1_pwrdm,
+ &sgx_pwrdm,
+ &usbhost_pwrdm,
+ &dpll5_pwrdm,
+ NULL
+};
void __init omap3xxx_powerdomains_init(void)
{
- pwrdm_init(powerdomains_omap3xxx, &omap3_pwrdm_operations);
+ unsigned int rev;
+
+ if (!cpu_is_omap34xx())
+ return;
+
+ pwrdm_register_platform_funcs(&omap3_pwrdm_operations);
+ pwrdm_register_pwrdms(powerdomains_omap3430_common);
+
+ rev = omap_rev();
+
+ if (rev == OMAP3430_REV_ES1_0)
+ pwrdm_register_pwrdms(powerdomains_omap3430es1);
+ else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
+ rev == OMAP3430_REV_ES3_0 || rev == OMAP3630_REV_ES1_0)
+ pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0);
+ else if (rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2 ||
+ rev == OMAP3517_REV_ES1_0 || rev == OMAP3517_REV_ES1_1 ||
+ rev == OMAP3630_REV_ES1_1 || rev == OMAP3630_REV_ES1_2)
+ pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus);
+ else
+ WARN(1, "OMAP3 powerdomain init: unknown chip type\n");
+
+ pwrdm_complete_init();
}
diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c
index 247e79495115..704664c0e259 100644
--- a/arch/arm/mach-omap2/powerdomains44xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains44xx_data.c
@@ -33,9 +33,9 @@
/* core_44xx_pwrdm: CORE power domain */
static struct powerdomain core_44xx_pwrdm = {
.name = "core_pwrdm",
+ .voltdm = { .name = "core" },
.prcm_offs = OMAP4430_PRM_CORE_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 5,
@@ -59,9 +59,9 @@ static struct powerdomain core_44xx_pwrdm = {
/* gfx_44xx_pwrdm: 3D accelerator power domain */
static struct powerdomain gfx_44xx_pwrdm = {
.name = "gfx_pwrdm",
+ .voltdm = { .name = "core" },
.prcm_offs = OMAP4430_PRM_GFX_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_ON,
.banks = 1,
.pwrsts_mem_ret = {
@@ -76,9 +76,9 @@ static struct powerdomain gfx_44xx_pwrdm = {
/* abe_44xx_pwrdm: Audio back end power domain */
static struct powerdomain abe_44xx_pwrdm = {
.name = "abe_pwrdm",
+ .voltdm = { .name = "iva" },
.prcm_offs = OMAP4430_PRM_ABE_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF,
.banks = 2,
@@ -96,9 +96,9 @@ static struct powerdomain abe_44xx_pwrdm = {
/* dss_44xx_pwrdm: Display subsystem power domain */
static struct powerdomain dss_44xx_pwrdm = {
.name = "dss_pwrdm",
+ .voltdm = { .name = "core" },
.prcm_offs = OMAP4430_PRM_DSS_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF,
.banks = 1,
@@ -114,9 +114,9 @@ static struct powerdomain dss_44xx_pwrdm = {
/* tesla_44xx_pwrdm: Tesla processor power domain */
static struct powerdomain tesla_44xx_pwrdm = {
.name = "tesla_pwrdm",
+ .voltdm = { .name = "iva" },
.prcm_offs = OMAP4430_PRM_TESLA_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 3,
@@ -136,9 +136,9 @@ static struct powerdomain tesla_44xx_pwrdm = {
/* wkup_44xx_pwrdm: Wake-up power domain */
static struct powerdomain wkup_44xx_pwrdm = {
.name = "wkup_pwrdm",
+ .voltdm = { .name = "wakeup" },
.prcm_offs = OMAP4430_PRM_WKUP_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_ON,
.banks = 1,
.pwrsts_mem_ret = {
@@ -152,9 +152,9 @@ static struct powerdomain wkup_44xx_pwrdm = {
/* cpu0_44xx_pwrdm: MPU0 processor and Neon coprocessor power domain */
static struct powerdomain cpu0_44xx_pwrdm = {
.name = "cpu0_pwrdm",
+ .voltdm = { .name = "mpu" },
.prcm_offs = OMAP4430_PRCM_MPU_CPU0_INST,
.prcm_partition = OMAP4430_PRCM_MPU_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
@@ -169,9 +169,9 @@ static struct powerdomain cpu0_44xx_pwrdm = {
/* cpu1_44xx_pwrdm: MPU1 processor and Neon coprocessor power domain */
static struct powerdomain cpu1_44xx_pwrdm = {
.name = "cpu1_pwrdm",
+ .voltdm = { .name = "mpu" },
.prcm_offs = OMAP4430_PRCM_MPU_CPU1_INST,
.prcm_partition = OMAP4430_PRCM_MPU_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
@@ -186,9 +186,9 @@ static struct powerdomain cpu1_44xx_pwrdm = {
/* emu_44xx_pwrdm: Emulation power domain */
static struct powerdomain emu_44xx_pwrdm = {
.name = "emu_pwrdm",
+ .voltdm = { .name = "wakeup" },
.prcm_offs = OMAP4430_PRM_EMU_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_ON,
.banks = 1,
.pwrsts_mem_ret = {
@@ -202,9 +202,9 @@ static struct powerdomain emu_44xx_pwrdm = {
/* mpu_44xx_pwrdm: Modena processor and the Neon coprocessor power domain */
static struct powerdomain mpu_44xx_pwrdm = {
.name = "mpu_pwrdm",
+ .voltdm = { .name = "mpu" },
.prcm_offs = OMAP4430_PRM_MPU_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 3,
@@ -223,9 +223,9 @@ static struct powerdomain mpu_44xx_pwrdm = {
/* ivahd_44xx_pwrdm: IVA-HD power domain */
static struct powerdomain ivahd_44xx_pwrdm = {
.name = "ivahd_pwrdm",
+ .voltdm = { .name = "iva" },
.prcm_offs = OMAP4430_PRM_IVAHD_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF,
.banks = 4,
@@ -247,9 +247,9 @@ static struct powerdomain ivahd_44xx_pwrdm = {
/* cam_44xx_pwrdm: Camera subsystem power domain */
static struct powerdomain cam_44xx_pwrdm = {
.name = "cam_pwrdm",
+ .voltdm = { .name = "core" },
.prcm_offs = OMAP4430_PRM_CAM_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_ON,
.banks = 1,
.pwrsts_mem_ret = {
@@ -264,9 +264,9 @@ static struct powerdomain cam_44xx_pwrdm = {
/* l3init_44xx_pwrdm: L3 initators pheripherals power domain */
static struct powerdomain l3init_44xx_pwrdm = {
.name = "l3init_pwrdm",
+ .voltdm = { .name = "core" },
.prcm_offs = OMAP4430_PRM_L3INIT_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
@@ -282,9 +282,9 @@ static struct powerdomain l3init_44xx_pwrdm = {
/* l4per_44xx_pwrdm: Target peripherals power domain */
static struct powerdomain l4per_44xx_pwrdm = {
.name = "l4per_pwrdm",
+ .voltdm = { .name = "core" },
.prcm_offs = OMAP4430_PRM_L4PER_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 2,
@@ -305,18 +305,18 @@ static struct powerdomain l4per_44xx_pwrdm = {
*/
static struct powerdomain always_on_core_44xx_pwrdm = {
.name = "always_on_core_pwrdm",
+ .voltdm = { .name = "core" },
.prcm_offs = OMAP4430_PRM_ALWAYS_ON_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_ON,
};
/* cefuse_44xx_pwrdm: Customer efuse controller power domain */
static struct powerdomain cefuse_44xx_pwrdm = {
.name = "cefuse_pwrdm",
+ .voltdm = { .name = "core" },
.prcm_offs = OMAP4430_PRM_CEFUSE_INST,
.prcm_partition = OMAP4430_PRM_PARTITION,
- .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_ON,
.flags = PWRDM_HAS_LOWPOWERSTATECHANGE,
};
@@ -352,5 +352,7 @@ static struct powerdomain *powerdomains_omap44xx[] __initdata = {
void __init omap44xx_powerdomains_init(void)
{
- pwrdm_init(powerdomains_omap44xx, &omap4_pwrdm_operations);
+ pwrdm_register_platform_funcs(&omap4_pwrdm_operations);
+ pwrdm_register_pwrdms(powerdomains_omap44xx);
+ pwrdm_complete_init();
}
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 2e40a5cf0163..8db5f035eb0a 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -151,17 +151,10 @@ int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
{
- /* Static mapping, never released */
- if (omap2_globals->prm) {
- prm_base = ioremap(omap2_globals->prm, SZ_8K);
- WARN_ON(!prm_base);
- }
- if (omap2_globals->cm) {
- cm_base = ioremap(omap2_globals->cm, SZ_8K);
- WARN_ON(!cm_base);
- }
- if (omap2_globals->cm2) {
- cm2_base = ioremap(omap2_globals->cm2, SZ_8K);
- WARN_ON(!cm2_base);
- }
+ if (omap2_globals->prm)
+ prm_base = omap2_globals->prm;
+ if (omap2_globals->cm)
+ cm_base = omap2_globals->cm;
+ if (omap2_globals->cm2)
+ cm2_base = omap2_globals->cm2;
}
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index 051213fbc346..f02d87f68e54 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -20,6 +20,8 @@
#include <plat/cpu.h>
#include <plat/prcm.h>
+#include "vp.h"
+
#include "prm2xxx_3xxx.h"
#include "cm2xxx_3xxx.h"
#include "prm-regbits-24xx.h"
@@ -156,3 +158,57 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
}
+
+/* PRM VP */
+
+/*
+ * struct omap3_vp - OMAP3 VP register access description.
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ */
+struct omap3_vp {
+ u32 tranxdone_status;
+};
+
+static struct omap3_vp omap3_vp[] = {
+ [OMAP3_VP_VDD_MPU_ID] = {
+ .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+ },
+ [OMAP3_VP_VDD_CORE_ID] = {
+ .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
+ },
+};
+
+#define MAX_VP_ID ARRAY_SIZE(omap3_vp);
+
+u32 omap3_prm_vp_check_txdone(u8 vp_id)
+{
+ struct omap3_vp *vp = &omap3_vp[vp_id];
+ u32 irqstatus;
+
+ irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
+ OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+ return irqstatus & vp->tranxdone_status;
+}
+
+void omap3_prm_vp_clear_txdone(u8 vp_id)
+{
+ struct omap3_vp *vp = &omap3_vp[vp_id];
+
+ omap2_prm_write_mod_reg(vp->tranxdone_status,
+ OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+}
+
+u32 omap3_prm_vcvp_read(u8 offset)
+{
+ return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
+}
+
+void omap3_prm_vcvp_write(u32 val, u8 offset)
+{
+ omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
+}
+
+u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
+{
+ return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
+}
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
index a1fc62a39dbb..cef533df0861 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -303,7 +303,19 @@ extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
+/* OMAP3-specific VP functions */
+u32 omap3_prm_vp_check_txdone(u8 vp_id);
+void omap3_prm_vp_clear_txdone(u8 vp_id);
+
+/*
+ * OMAP3 access functions for voltage controller (VC) and
+ * voltage proccessor (VP) in the PRM.
+ */
+extern u32 omap3_prm_vcvp_read(u8 offset);
+extern void omap3_prm_vcvp_write(u32 val, u8 offset);
+extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
#endif /* CONFIG_ARCH_OMAP4 */
+
#endif
/*
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index 00165558fc4d..495a31a7e8a7 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -21,8 +21,11 @@
#include <plat/cpu.h>
#include <plat/prcm.h>
+#include "vp.h"
#include "prm44xx.h"
#include "prm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "prminst44xx.h"
/* PRM low-level functions */
@@ -50,3 +53,71 @@ u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
return v;
}
+
+/* PRM VP */
+
+/*
+ * struct omap4_vp - OMAP4 VP register access description.
+ * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ */
+struct omap4_vp {
+ u32 irqstatus_mpu;
+ u32 tranxdone_status;
+};
+
+static struct omap4_vp omap4_vp[] = {
+ [OMAP4_VP_VDD_MPU_ID] = {
+ .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
+ .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
+ },
+ [OMAP4_VP_VDD_IVA_ID] = {
+ .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+ .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
+ },
+ [OMAP4_VP_VDD_CORE_ID] = {
+ .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+ .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
+ },
+};
+
+u32 omap4_prm_vp_check_txdone(u8 vp_id)
+{
+ struct omap4_vp *vp = &omap4_vp[vp_id];
+ u32 irqstatus;
+
+ irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_OCP_SOCKET_INST,
+ vp->irqstatus_mpu);
+ return irqstatus & vp->tranxdone_status;
+}
+
+void omap4_prm_vp_clear_txdone(u8 vp_id)
+{
+ struct omap4_vp *vp = &omap4_vp[vp_id];
+
+ omap4_prminst_write_inst_reg(vp->tranxdone_status,
+ OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_OCP_SOCKET_INST,
+ vp->irqstatus_mpu);
+};
+
+u32 omap4_prm_vcvp_read(u8 offset)
+{
+ return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST, offset);
+}
+
+void omap4_prm_vcvp_write(u32 val, u8 offset)
+{
+ omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST, offset);
+}
+
+u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
+{
+ return omap4_prminst_rmw_inst_reg_bits(mask, bits,
+ OMAP4430_PRM_PARTITION,
+ OMAP4430_PRM_DEVICE_INST,
+ offset);
+}
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index 7dfa379b625d..3d66ccd849d2 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -751,6 +751,18 @@ extern u32 omap4_prm_read_inst_reg(s16 inst, u16 idx);
extern void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 idx);
extern u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
+/* OMAP4-specific VP functions */
+u32 omap4_prm_vp_check_txdone(u8 vp_id);
+void omap4_prm_vp_clear_txdone(u8 vp_id);
+
+/*
+ * OMAP4 access functions for voltage controller (VC) and
+ * voltage proccessor (VP) in the PRM.
+ */
+extern u32 omap4_prm_vcvp_read(u8 offset);
+extern void omap4_prm_vcvp_write(u32 val, u8 offset);
+extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
+
# endif
#endif
diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
index da6f3a63b5d5..8f2782874771 100644
--- a/arch/arm/mach-omap2/sdrc.c
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -117,15 +117,10 @@ int omap2_sdrc_get_params(unsigned long r,
void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
{
- /* Static mapping, never released */
- if (omap2_globals->sdrc) {
- omap2_sdrc_base = ioremap(omap2_globals->sdrc, SZ_64K);
- WARN_ON(!omap2_sdrc_base);
- }
- if (omap2_globals->sms) {
- omap2_sms_base = ioremap(omap2_globals->sms, SZ_64K);
- WARN_ON(!omap2_sms_base);
- }
+ if (omap2_globals->sdrc)
+ omap2_sdrc_base = omap2_globals->sdrc;
+ if (omap2_globals->sms)
+ omap2_sms_base = omap2_globals->sms;
}
/**
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 466fc722fa0f..9992dbfdfdb3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -107,28 +107,6 @@ struct omap_uart_state {
static LIST_HEAD(uart_list);
static u8 num_uarts;
-static int uart_idle_hwmod(struct omap_device *od)
-{
- omap_hwmod_idle(od->hwmods[0]);
-
- return 0;
-}
-
-static int uart_enable_hwmod(struct omap_device *od)
-{
- omap_hwmod_enable(od->hwmods[0]);
-
- return 0;
-}
-
-static struct omap_device_pm_latency omap_uart_latency[] = {
- {
- .deactivate_func = uart_idle_hwmod,
- .activate_func = uart_enable_hwmod,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
-};
-
static inline unsigned int __serial_read_reg(struct uart_port *up,
int offset)
{
@@ -711,7 +689,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
{
struct omap_uart_state *uart;
struct omap_hwmod *oh;
- struct omap_device *od;
+ struct platform_device *pdev;
void *pdata = NULL;
u32 pdata_size = 0;
char *name;
@@ -799,20 +777,19 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
if (WARN_ON(!oh))
return;
- od = omap_device_build(name, uart->num, oh, pdata, pdata_size,
- omap_uart_latency,
- ARRAY_SIZE(omap_uart_latency), false);
- WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
+ pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
+ NULL, 0, false);
+ WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n",
name, oh->name);
- omap_device_disable_idle_on_suspend(od);
+ omap_device_disable_idle_on_suspend(pdev);
oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
uart->irq = oh->mpu_irqs[0].irq;
uart->regshift = 2;
uart->mapbase = oh->slaves[0]->addr->pa_start;
uart->membase = omap_hwmod_get_mpu_rt_va(oh);
- uart->pdev = &od->pdev;
+ uart->pdev = pdev;
oh->dev_attr = uart;
@@ -846,8 +823,8 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
if ((cpu_is_omap34xx() && uart->padconf) ||
(uart->wk_en && uart->wk_mask)) {
- device_init_wakeup(&od->pdev.dev, true);
- DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
+ device_init_wakeup(&pdev->dev, true);
+ DEV_CREATE_FILE(&pdev->dev, &dev_attr_sleep_timeout);
}
/* Enable the MDR1 errata for OMAP3 */
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index f438cf4d847b..53d9d0a5b39d 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -15,7 +15,7 @@
static int sr_class3_enable(struct voltagedomain *voltdm)
{
- unsigned long volt = omap_voltage_get_nom_volt(voltdm);
+ unsigned long volt = voltdm_get_voltage(voltdm);
if (!volt) {
pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
@@ -32,7 +32,7 @@ static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset)
omap_vp_disable(voltdm);
sr_disable(voltdm);
if (is_volt_reset)
- omap_voltage_reset(voltdm);
+ voltdm_reset(voltdm);
return 0;
}
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 34c01a7de810..0347b93211e6 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -62,6 +62,7 @@ static LIST_HEAD(sr_list);
static struct omap_sr_class_data *sr_class;
static struct omap_sr_pmic_data *sr_pmic_data;
+static struct dentry *sr_dbg_dir;
static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
{
@@ -247,7 +248,7 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
* driver register and sr device intializtion API's. Only one call
* will ultimately succeed.
*
- * Currently this function registers interrrupt handler for a particular SR
+ * Currently this function registers interrupt handler for a particular SR
* if smartreflex class driver is already registered and has
* requested for interrupts and the SR interrupt line in present.
*/
@@ -826,9 +827,10 @@ static int __init omap_sr_probe(struct platform_device *pdev)
struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
struct omap_sr_data *pdata = pdev->dev.platform_data;
struct resource *mem, *irq;
- struct dentry *vdd_dbg_dir, *nvalue_dir;
+ struct dentry *nvalue_dir;
struct omap_volt_data *volt_data;
int i, ret = 0;
+ char *name;
if (!sr_info) {
dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
@@ -899,18 +901,25 @@ static int __init omap_sr_probe(struct platform_device *pdev)
}
dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
+ if (!sr_dbg_dir) {
+ sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
+ if (!sr_dbg_dir) {
+ ret = PTR_ERR(sr_dbg_dir);
+ pr_err("%s:sr debugfs dir creation failed(%d)\n",
+ __func__, ret);
+ goto err_iounmap;
+ }
+ }
- /*
- * If the voltage domain debugfs directory is not created, do
- * not try to create rest of the debugfs entries.
- */
- vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm);
- if (!vdd_dbg_dir) {
- ret = -EINVAL;
+ name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
+ if (!name) {
+ dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n",
+ __func__);
+ ret = -ENOMEM;
goto err_iounmap;
}
-
- sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
+ sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
+ kfree(name);
if (IS_ERR(sr_info->dbg_dir)) {
dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
__func__);
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index 10d3c5ee8018..9f43fcc05d3e 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -31,14 +31,6 @@
static bool sr_enable_on_init;
-static struct omap_device_pm_latency omap_sr_latency[] = {
- {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
- },
-};
-
/* Read EFUSE values from control registers for OMAP3430 */
static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
struct omap_sr_data *sr_data)
@@ -80,7 +72,7 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
static int sr_dev_init(struct omap_hwmod *oh, void *user)
{
struct omap_sr_data *sr_data;
- struct omap_device *od;
+ struct platform_device *pdev;
struct omap_volt_data *volt_data;
char *name = "smartreflex";
static int i;
@@ -102,7 +94,7 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
sr_data->senn_mod = 0x1;
sr_data->senp_mod = 0x1;
- sr_data->voltdm = omap_voltage_domain_lookup(oh->vdd_name);
+ sr_data->voltdm = voltdm_lookup(oh->vdd_name);
if (IS_ERR(sr_data->voltdm)) {
pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
__func__, oh->vdd_name);
@@ -120,10 +112,9 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
sr_data->enable_on_init = sr_enable_on_init;
- od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
- omap_sr_latency,
- ARRAY_SIZE(omap_sr_latency), 0);
- if (IS_ERR(od))
+ pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
+ NULL, 0, 0);
+ if (IS_ERR(pdev))
pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
__func__, name, oh->name);
exit:
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index cf1de7d2630d..e49fc7be2229 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -35,6 +35,7 @@
#include <linux/irq.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
+#include <linux/slab.h>
#include <asm/mach/time.h>
#include <plat/dmtimer.h>
@@ -42,6 +43,10 @@
#include <asm/sched_clock.h>
#include <plat/common.h>
#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#include "powerdomain.h"
/* Parent clocks, eventually these will come from the clock framework */
@@ -67,7 +72,7 @@
/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
#define MAX_GPTIMER_ID 12
-u32 sys_timer_reserved;
+static u32 sys_timer_reserved;
/* Clockevent code */
@@ -78,7 +83,7 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = &clockevent_gpt;
- __omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+ __omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
evt->event_handler(evt);
return IRQ_HANDLED;
@@ -93,7 +98,7 @@ static struct irqaction omap2_gp_timer_irq = {
static int omap2_gp_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
- __omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST,
+ __omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
0xffffffff - cycles, 1);
return 0;
@@ -104,16 +109,16 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
{
u32 period;
- __omap_dm_timer_stop(clkev.io_base, 1, clkev.rate);
+ __omap_dm_timer_stop(&clkev, 1, clkev.rate);
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
period = clkev.rate / HZ;
period -= 1;
/* Looks like we need to first set the load value separately */
- __omap_dm_timer_write(clkev.io_base, OMAP_TIMER_LOAD_REG,
+ __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
0xffffffff - period, 1);
- __omap_dm_timer_load_start(clkev.io_base,
+ __omap_dm_timer_load_start(&clkev,
OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
0xffffffff - period, 1);
break;
@@ -189,7 +194,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
clk_put(src);
}
}
- __omap_dm_timer_reset(timer->io_base, 1, 1);
+ __omap_dm_timer_init_regs(timer);
+ __omap_dm_timer_reset(timer, 1, 1);
timer->posted = 1;
timer->rate = clk_get_rate(timer->fclk);
@@ -210,7 +216,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
omap2_gp_timer_irq.dev_id = (void *)&clkev;
setup_irq(clkev.irq, &omap2_gp_timer_irq);
- __omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+ __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
clockevent_gpt.shift);
@@ -251,7 +257,7 @@ static struct omap_dm_timer clksrc;
static DEFINE_CLOCK_DATA(cd);
static cycle_t clocksource_read_cycles(struct clocksource *cs)
{
- return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1);
+ return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1);
}
static struct clocksource clocksource_gpt = {
@@ -266,7 +272,7 @@ static void notrace dmtimer_update_sched_clock(void)
{
u32 cyc;
- cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+ cyc = __omap_dm_timer_read_counter(&clksrc, 1);
update_sched_clock(&cd, cyc, (u32)~0);
}
@@ -276,7 +282,7 @@ unsigned long long notrace sched_clock(void)
u32 cyc = 0;
if (clksrc.reserved)
- cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+ cyc = __omap_dm_timer_read_counter(&clksrc, 1);
return cyc_to_sched_clock(&cd, cyc, (u32)~0);
}
@@ -293,7 +299,7 @@ static void __init omap2_gp_clocksource_init(int gptimer_id,
pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
gptimer_id, clksrc.rate);
- __omap_dm_timer_load_start(clksrc.io_base,
+ __omap_dm_timer_load_start(&clksrc,
OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
@@ -341,3 +347,167 @@ static void __init omap4_timer_init(void)
}
OMAP_SYS_TIMER(4)
#endif
+
+/**
+ * omap2_dm_timer_set_src - change the timer input clock source
+ * @pdev: timer platform device pointer
+ * @source: array index of parent clock source
+ */
+static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
+{
+ int ret;
+ struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+ struct clk *fclk, *parent;
+ char *parent_name = NULL;
+
+ fclk = clk_get(&pdev->dev, "fck");
+ if (IS_ERR_OR_NULL(fclk)) {
+ dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ switch (source) {
+ case OMAP_TIMER_SRC_SYS_CLK:
+ parent_name = "sys_ck";
+ break;
+
+ case OMAP_TIMER_SRC_32_KHZ:
+ parent_name = "32k_ck";
+ break;
+
+ case OMAP_TIMER_SRC_EXT_CLK:
+ if (pdata->timer_ip_version == OMAP_TIMER_IP_VERSION_1) {
+ parent_name = "alt_ck";
+ break;
+ }
+ dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
+ __func__, __LINE__);
+ clk_put(fclk);
+ return -EINVAL;
+ }
+
+ parent = clk_get(&pdev->dev, parent_name);
+ if (IS_ERR_OR_NULL(parent)) {
+ dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
+ __func__, __LINE__, parent_name);
+ clk_put(fclk);
+ return -EINVAL;
+ }
+
+ ret = clk_set_parent(fclk, parent);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
+ __func__, parent_name);
+ ret = -EINVAL;
+ }
+
+ clk_put(parent);
+ clk_put(fclk);
+
+ return ret;
+}
+
+struct omap_device_pm_latency omap2_dmtimer_latency[] = {
+ {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+/**
+ * omap_timer_init - build and register timer device with an
+ * associated timer hwmod
+ * @oh: timer hwmod pointer to be used to build timer device
+ * @user: parameter that can be passed from calling hwmod API
+ *
+ * Called by omap_hwmod_for_each_by_class to register each of the timer
+ * devices present in the system. The number of timer devices is known
+ * by parsing through the hwmod database for a given class name. At the
+ * end of function call memory is allocated for timer device and it is
+ * registered to the framework ready to be proved by the driver.
+ */
+static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
+{
+ int id;
+ int ret = 0;
+ char *name = "omap_timer";
+ struct dmtimer_platform_data *pdata;
+ struct platform_device *pdev;
+ struct omap_timer_capability_dev_attr *timer_dev_attr;
+ struct powerdomain *pwrdm;
+
+ pr_debug("%s: %s\n", __func__, oh->name);
+
+ /* on secure device, do not register secure timer */
+ timer_dev_attr = oh->dev_attr;
+ if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
+ if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
+ return ret;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+ return -ENOMEM;
+ }
+
+ /*
+ * Extract the IDs from name field in hwmod database
+ * and use the same for constructing ids' for the
+ * timer devices. In a way, we are avoiding usage of
+ * static variable witin the function to do the same.
+ * CAUTION: We have to be careful and make sure the
+ * name in hwmod database does not change in which case
+ * we might either make corresponding change here or
+ * switch back static variable mechanism.
+ */
+ sscanf(oh->name, "timer%2d", &id);
+
+ pdata->set_timer_src = omap2_dm_timer_set_src;
+ pdata->timer_ip_version = oh->class->rev;
+
+ /* Mark clocksource and clockevent timers as reserved */
+ if ((sys_timer_reserved >> (id - 1)) & 0x1)
+ pdata->reserved = 1;
+
+ pwrdm = omap_hwmod_get_pwrdm(oh);
+ pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
+#ifdef CONFIG_PM
+ pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
+#endif
+ pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+ omap2_dmtimer_latency,
+ ARRAY_SIZE(omap2_dmtimer_latency),
+ 0);
+
+ if (IS_ERR(pdev)) {
+ pr_err("%s: Can't build omap_device for %s: %s.\n",
+ __func__, name, oh->name);
+ ret = -EINVAL;
+ }
+
+ kfree(pdata);
+
+ return ret;
+}
+
+/**
+ * omap2_dm_timer_init - top level regular device initialization
+ *
+ * Uses dedicated hwmod api to parse through hwmod database for
+ * given class name and then build and register the timer device.
+ */
+static int __init omap2_dm_timer_init(void)
+{
+ int ret;
+
+ ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
+ if (unlikely(ret)) {
+ pr_err("%s: device registration failed.\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+arch_initcall(omap2_dm_timer_init);
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index daa056ed8738..522435772168 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -99,7 +99,7 @@ static struct regulator_init_data omap3_vdac_idata = {
static struct regulator_consumer_supply omap3_vpll2_supplies[] = {
REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
- REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
};
static struct regulator_init_data omap3_vpll2_idata = {
@@ -235,6 +235,12 @@ static struct regulator_init_data omap4_vana_idata = {
},
};
+static struct regulator_consumer_supply omap4_vcxio_supply[] = {
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.1"),
+};
+
static struct regulator_init_data omap4_vcxio_idata = {
.constraints = {
.min_uV = 1800000,
@@ -243,7 +249,10 @@ static struct regulator_init_data omap4_vcxio_idata = {
| REGULATOR_MODE_STANDBY,
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
+ .always_on = true,
},
+ .num_consumer_supplies = ARRAY_SIZE(omap4_vcxio_supply),
+ .consumer_supplies = omap4_vcxio_supply,
};
static struct regulator_init_data omap4_vusb_idata = {
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 19e4dac62a8c..47fb5d607630 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -60,14 +60,6 @@ static struct musb_hdrc_platform_data musb_plat = {
static u64 musb_dmamask = DMA_BIT_MASK(32);
-static struct omap_device_pm_latency omap_musb_latency[] = {
- {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
-};
-
static void usb_musb_mux_init(struct omap_musb_board_data *board_data)
{
switch (board_data->interface_type) {
@@ -115,7 +107,6 @@ static struct omap_musb_board_data musb_default_board_data = {
void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
{
struct omap_hwmod *oh;
- struct omap_device *od;
struct platform_device *pdev;
struct device *dev;
int bus_id = -1;
@@ -145,22 +136,19 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
name = "musb-omap2430";
}
- oh = omap_hwmod_lookup(oh_name);
- if (!oh) {
- pr_err("Could not look up %s\n", oh_name);
- return;
- }
+ oh = omap_hwmod_lookup(oh_name);
+ if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
+ __func__, oh_name))
+ return;
- od = omap_device_build(name, bus_id, oh, &musb_plat,
- sizeof(musb_plat), omap_musb_latency,
- ARRAY_SIZE(omap_musb_latency), false);
- if (IS_ERR(od)) {
+ pdev = omap_device_build(name, bus_id, oh, &musb_plat,
+ sizeof(musb_plat), NULL, 0, false);
+ if (IS_ERR(pdev)) {
pr_err("Could not build omap_device for %s %s\n",
name, oh_name);
return;
}
- pdev = &od->pdev;
dev = &pdev->dev;
get_device(dev);
dev->dma_mask = &musb_dmamask;
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
new file mode 100644
index 000000000000..031d116fbf10
--- /dev/null
+++ b/arch/arm/mach-omap2/vc.c
@@ -0,0 +1,367 @@
+/*
+ * OMAP Voltage Controller (VC) interface
+ *
+ * Copyright (C) 2011 Texas Instruments, 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.
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <plat/cpu.h>
+
+#include "voltage.h"
+#include "vc.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+/**
+ * struct omap_vc_channel_cfg - describe the cfg_channel bitfield
+ * @sa: bit for slave address
+ * @rav: bit for voltage configuration register
+ * @rac: bit for command configuration register
+ * @racen: enable bit for RAC
+ * @cmd: bit for command value set selection
+ *
+ * Channel configuration bits, common for OMAP3+
+ * OMAP3 register: PRM_VC_CH_CONF
+ * OMAP4 register: PRM_VC_CFG_CHANNEL
+ * OMAP5 register: PRM_VC_SMPS_<voltdm>_CONFIG
+ */
+struct omap_vc_channel_cfg {
+ u8 sa;
+ u8 rav;
+ u8 rac;
+ u8 racen;
+ u8 cmd;
+};
+
+static struct omap_vc_channel_cfg vc_default_channel_cfg = {
+ .sa = BIT(0),
+ .rav = BIT(1),
+ .rac = BIT(2),
+ .racen = BIT(3),
+ .cmd = BIT(4),
+};
+
+/*
+ * On OMAP3+, all VC channels have the above default bitfield
+ * configuration, except the OMAP4 MPU channel. This appears
+ * to be a freak accident as every other VC channel has the
+ * default configuration, thus creating a mutant channel config.
+ */
+static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
+ .sa = BIT(0),
+ .rav = BIT(2),
+ .rac = BIT(3),
+ .racen = BIT(4),
+ .cmd = BIT(1),
+};
+
+static struct omap_vc_channel_cfg *vc_cfg_bits;
+#define CFG_CHANNEL_MASK 0x1f
+
+/**
+ * omap_vc_config_channel - configure VC channel to PMIC mappings
+ * @voltdm: pointer to voltagdomain defining the desired VC channel
+ *
+ * Configures the VC channel to PMIC mappings for the following
+ * PMIC settings
+ * - i2c slave address (SA)
+ * - voltage configuration address (RAV)
+ * - command configuration address (RAC) and enable bit (RACEN)
+ * - command values for ON, ONLP, RET and OFF (CMD)
+ *
+ * This function currently only allows flexible configuration of the
+ * non-default channel. Starting with OMAP4, there are more than 2
+ * channels, with one defined as the default (on OMAP4, it's MPU.)
+ * Only the non-default channel can be configured.
+ */
+static int omap_vc_config_channel(struct voltagedomain *voltdm)
+{
+ struct omap_vc_channel *vc = voltdm->vc;
+
+ /*
+ * For default channel, the only configurable bit is RACEN.
+ * All others must stay at zero (see function comment above.)
+ */
+ if (vc->flags & OMAP_VC_CHANNEL_DEFAULT)
+ vc->cfg_channel &= vc_cfg_bits->racen;
+
+ voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift,
+ vc->cfg_channel << vc->cfg_channel_sa_shift,
+ vc->cfg_channel_reg);
+
+ return 0;
+}
+
+/* Voltage scale and accessory APIs */
+int omap_vc_pre_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt,
+ u8 *target_vsel, u8 *current_vsel)
+{
+ struct omap_vc_channel *vc = voltdm->vc;
+ u32 vc_cmdval;
+
+ /* Check if sufficient pmic info is available for this vdd */
+ if (!voltdm->pmic) {
+ pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
+ __func__, voltdm->name);
+ return -EINVAL;
+ }
+
+ if (!voltdm->pmic->uv_to_vsel) {
+ pr_err("%s: PMIC function to convert voltage in uV to"
+ "vsel not registered. Hence unable to scale voltage"
+ "for vdd_%s\n", __func__, voltdm->name);
+ return -ENODATA;
+ }
+
+ if (!voltdm->read || !voltdm->write) {
+ pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return -EINVAL;
+ }
+
+ *target_vsel = voltdm->pmic->uv_to_vsel(target_volt);
+ *current_vsel = voltdm->pmic->uv_to_vsel(voltdm->nominal_volt);
+
+ /* Setting the ON voltage to the new target voltage */
+ vc_cmdval = voltdm->read(vc->cmdval_reg);
+ vc_cmdval &= ~vc->common->cmd_on_mask;
+ vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
+ voltdm->write(vc_cmdval, vc->cmdval_reg);
+
+ omap_vp_update_errorgain(voltdm, target_volt);
+
+ return 0;
+}
+
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt,
+ u8 target_vsel, u8 current_vsel)
+{
+ u32 smps_steps = 0, smps_delay = 0;
+
+ smps_steps = abs(target_vsel - current_vsel);
+ /* SMPS slew rate / step size. 2us added as buffer. */
+ smps_delay = ((smps_steps * voltdm->pmic->step_size) /
+ voltdm->pmic->slew_rate) + 2;
+ udelay(smps_delay);
+}
+
+/* vc_bypass_scale - VC bypass method of voltage scaling */
+int omap_vc_bypass_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt)
+{
+ struct omap_vc_channel *vc = voltdm->vc;
+ u32 loop_cnt = 0, retries_cnt = 0;
+ u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
+ u8 target_vsel, current_vsel;
+ int ret;
+
+ ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+ if (ret)
+ return ret;
+
+ vc_valid = vc->common->valid;
+ vc_bypass_val_reg = vc->common->bypass_val_reg;
+ vc_bypass_value = (target_vsel << vc->common->data_shift) |
+ (vc->volt_reg_addr << vc->common->regaddr_shift) |
+ (vc->i2c_slave_addr << vc->common->slaveaddr_shift);
+
+ voltdm->write(vc_bypass_value, vc_bypass_val_reg);
+ voltdm->write(vc_bypass_value | vc_valid, vc_bypass_val_reg);
+
+ vc_bypass_value = voltdm->read(vc_bypass_val_reg);
+ /*
+ * Loop till the bypass command is acknowledged from the SMPS.
+ * NOTE: This is legacy code. The loop count and retry count needs
+ * to be revisited.
+ */
+ while (!(vc_bypass_value & vc_valid)) {
+ loop_cnt++;
+
+ if (retries_cnt > 10) {
+ pr_warning("%s: Retry count exceeded\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ if (loop_cnt > 50) {
+ retries_cnt++;
+ loop_cnt = 0;
+ udelay(10);
+ }
+ vc_bypass_value = voltdm->read(vc_bypass_val_reg);
+ }
+
+ omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+ return 0;
+}
+
+static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
+{
+ /*
+ * Voltage Manager FSM parameters init
+ * XXX This data should be passed in from the board file
+ */
+ voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
+ voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
+ voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+}
+
+static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+{
+ static bool is_initialized;
+
+ if (is_initialized)
+ return;
+
+ omap3_vfsm_init(voltdm);
+
+ is_initialized = true;
+}
+
+
+/* OMAP4 specific voltage init functions */
+static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
+{
+ static bool is_initialized;
+ u32 vc_val;
+
+ if (is_initialized)
+ 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);
+
+ is_initialized = true;
+}
+
+/**
+ * omap_vc_i2c_init - initialize I2C interface to PMIC
+ * @voltdm: voltage domain containing VC data
+ *
+ * Use PMIC supplied seetings for I2C high-speed mode and
+ * master code (if set) and program the VC I2C configuration
+ * register.
+ *
+ * The VC I2C configuration is common to all VC channels,
+ * so this function only configures I2C for the first VC
+ * channel registers. All other VC channels will use the
+ * same configuration.
+ */
+static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
+{
+ struct omap_vc_channel *vc = voltdm->vc;
+ static bool initialized;
+ static bool i2c_high_speed;
+ u8 mcode;
+
+ if (initialized) {
+ if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
+ pr_warn("%s: I2C config for all channels must match.",
+ __func__);
+ return;
+ }
+
+ i2c_high_speed = voltdm->pmic->i2c_high_speed;
+ if (i2c_high_speed)
+ voltdm->rmw(vc->common->i2c_cfg_hsen_mask,
+ vc->common->i2c_cfg_hsen_mask,
+ vc->common->i2c_cfg_reg);
+
+ mcode = voltdm->pmic->i2c_mcode;
+ if (mcode)
+ voltdm->rmw(vc->common->i2c_mcode_mask,
+ mcode << __ffs(vc->common->i2c_mcode_mask),
+ vc->common->i2c_cfg_reg);
+
+ initialized = true;
+}
+
+void __init omap_vc_init_channel(struct voltagedomain *voltdm)
+{
+ struct omap_vc_channel *vc = voltdm->vc;
+ u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
+ u32 val;
+
+ if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
+ pr_err("%s: PMIC info requried to configure vc for"
+ "vdd_%s not populated.Hence cannot initialize vc\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ if (!voltdm->read || !voltdm->write) {
+ pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ vc->cfg_channel = 0;
+ if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT)
+ vc_cfg_bits = &vc_mutant_channel_cfg;
+ else
+ vc_cfg_bits = &vc_default_channel_cfg;
+
+ /* get PMIC/board specific settings */
+ 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,
+ vc->i2c_slave_addr << __ffs(vc->smps_sa_mask),
+ vc->smps_sa_reg);
+ vc->cfg_channel |= vc_cfg_bits->sa;
+
+ /*
+ * Configure the PMIC register addresses.
+ */
+ voltdm->rmw(vc->smps_volra_mask,
+ vc->volt_reg_addr << __ffs(vc->smps_volra_mask),
+ vc->smps_volra_reg);
+ vc->cfg_channel |= vc_cfg_bits->rav;
+
+ if (vc->cmd_reg_addr) {
+ 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;
+ }
+
+ /* 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);
+ val = ((on_vsel << vc->common->cmd_on_shift) |
+ (onlp_vsel << vc->common->cmd_onlp_shift) |
+ (ret_vsel << vc->common->cmd_ret_shift) |
+ (off_vsel << vc->common->cmd_off_shift));
+ voltdm->write(val, vc->cmdval_reg);
+ vc->cfg_channel |= vc_cfg_bits->cmd;
+
+ /* 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())
+ omap3_vc_init_channel(voltdm);
+ else if (cpu_is_omap44xx())
+ omap4_vc_init_channel(voltdm);
+}
+
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
index e7767771de49..478bf6b432c4 100644
--- a/arch/arm/mach-omap2/vc.h
+++ b/arch/arm/mach-omap2/vc.h
@@ -19,12 +19,12 @@
#include <linux/kernel.h>
+struct voltagedomain;
+
/**
- * struct omap_vc_common_data - per-VC register/bitfield data
+ * struct omap_vc_common - per-VC register/bitfield data
* @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register
* @valid: VALID bitmask in PRM_VC_BYPASS_VAL register
- * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
- * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
* @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start
* @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register
* @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register
@@ -33,15 +33,16 @@
* @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register
* @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
* @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
+ * @i2c_cfg_reg: I2C configuration register offset
+ * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register
+ * @i2c_mcode_mask: MCODE field mask for I2C config register
*
* XXX One of cmd_on_mask and cmd_on_shift are not needed
* XXX VALID should probably be a shift, not a mask
*/
-struct omap_vc_common_data {
+struct omap_vc_common {
u32 cmd_on_mask;
u32 valid;
- u8 smps_sa_reg;
- u8 smps_volra_reg;
u8 bypass_val_reg;
u8 data_shift;
u8 slaveaddr_shift;
@@ -50,34 +51,75 @@ struct omap_vc_common_data {
u8 cmd_onlp_shift;
u8 cmd_ret_shift;
u8 cmd_off_shift;
+ u8 i2c_cfg_reg;
+ u8 i2c_cfg_hsen_mask;
+ u8 i2c_mcode_mask;
};
+/* omap_vc_channel.flags values */
+#define OMAP_VC_CHANNEL_DEFAULT BIT(0)
+#define OMAP_VC_CHANNEL_CFG_MUTANT BIT(1)
+
/**
- * struct omap_vc_instance_data - VC per-instance data
- * @vc_common: pointer to VC common data for this platform
- * @smps_sa_mask: SA* bitmask in the PRM_VC_SMPS_SA register
- * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
- * @smps_sa_shift: SA* field shift in the PRM_VC_SMPS_SA register
- * @smps_volra_shift: VOLRA* field shift in the PRM_VC_VOL_RA register
+ * struct omap_vc_channel - VC per-instance data
+ * @i2c_slave_addr: I2C slave address of PMIC for this VC channel
+ * @volt_reg_addr: voltage configuration register address
+ * @cmd_reg_addr: command configuration register address
+ * @setup_time: setup time (in sys_clk cycles) of regulator for this channel
+ * @cfg_channel: current value of VC channel configuration register
+ * @i2c_high_speed: whether or not to use I2C high-speed mode
*
- * XXX It is not necessary to have both a *_mask and a *_shift -
- * remove one
+ * @common: pointer to VC common data for this platform
+ * @smps_sa_mask: i2c slave address bitmask in the PRM_VC_SMPS_SA register
+ * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
+ * @smps_cmdra_mask: CMDRA* bitmask in the PRM_VC_CMD_RA register
+ * @cmdval_reg: register for on/ret/off voltage level values for this channel
+ * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
+ * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
+ * @smps_cmdra_reg: Offset of PRM_VC_SMPS_CMD_RA reg from PRM start
+ * @cfg_channel_reg: VC channel configuration register
+ * @cfg_channel_sa_shift: bit shift for slave address cfg_channel register
+ * @flags: VC channel-specific flags (optional)
*/
-struct omap_vc_instance_data {
- const struct omap_vc_common_data *vc_common;
+struct omap_vc_channel {
+ /* channel state */
+ u16 i2c_slave_addr;
+ u16 volt_reg_addr;
+ u16 cmd_reg_addr;
+ u16 setup_time;
+ u8 cfg_channel;
+ bool i2c_high_speed;
+
+ /* register access data */
+ const struct omap_vc_common *common;
u32 smps_sa_mask;
u32 smps_volra_mask;
+ u32 smps_cmdra_mask;
u8 cmdval_reg;
- u8 smps_sa_shift;
- u8 smps_volra_shift;
+ u8 smps_sa_reg;
+ u8 smps_volra_reg;
+ u8 smps_cmdra_reg;
+ u8 cfg_channel_reg;
+ u8 cfg_channel_sa_shift;
+ u8 flags;
};
-extern struct omap_vc_instance_data omap3_vc1_data;
-extern struct omap_vc_instance_data omap3_vc2_data;
+extern struct omap_vc_channel omap3_vc_mpu;
+extern struct omap_vc_channel omap3_vc_core;
+
+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_instance_data omap4_vc_mpu_data;
-extern struct omap_vc_instance_data omap4_vc_iva_data;
-extern struct omap_vc_instance_data omap4_vc_core_data;
+void omap_vc_init_channel(struct voltagedomain *voltdm);
+int omap_vc_pre_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt,
+ u8 *target_vsel, u8 *current_vsel);
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt,
+ u8 target_vsel, u8 current_vsel);
+int omap_vc_bypass_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt);
#endif
diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c
index f37dc4bc379a..cfe348e1af0e 100644
--- a/arch/arm/mach-omap2/vc3xxx_data.c
+++ b/arch/arm/mach-omap2/vc3xxx_data.c
@@ -29,9 +29,7 @@
* VC data common to 34xx/36xx chips
* XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
*/
-static struct omap_vc_common_data omap3_vc_common = {
- .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET,
- .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+static struct omap_vc_common omap3_vc_common = {
.bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET,
.data_shift = OMAP3430_DATA_SHIFT,
.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT,
@@ -42,22 +40,33 @@ static struct omap_vc_common_data omap3_vc_common = {
.cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT,
.cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT,
.cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT,
+ .i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK,
+ .i2c_cfg_reg = OMAP3_PRM_VC_I2C_CFG_OFFSET,
+ .i2c_mcode_mask = OMAP3430_MCODE_MASK,
};
-struct omap_vc_instance_data omap3_vc1_data = {
- .vc_common = &omap3_vc_common,
+struct omap_vc_channel omap3_vc_mpu = {
+ .common = &omap3_vc_common,
+ .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+ .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+ .smps_cmdra_reg = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
+ .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET,
- .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK,
- .smps_volra_shift = OMAP3430_VOLRA0_SHIFT,
.smps_volra_mask = OMAP3430_VOLRA0_MASK,
+ .smps_cmdra_mask = OMAP3430_CMDRA0_MASK,
+ .cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
};
-struct omap_vc_instance_data omap3_vc2_data = {
- .vc_common = &omap3_vc_common,
+struct omap_vc_channel omap3_vc_core = {
+ .common = &omap3_vc_common,
+ .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+ .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+ .smps_cmdra_reg = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
+ .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET,
- .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK,
- .smps_volra_shift = OMAP3430_VOLRA1_SHIFT,
.smps_volra_mask = OMAP3430_VOLRA1_MASK,
+ .smps_cmdra_mask = OMAP3430_CMDRA1_MASK,
+ .cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
};
diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c
index a98da8ddec52..2740a968145e 100644
--- a/arch/arm/mach-omap2/vc44xx_data.c
+++ b/arch/arm/mach-omap2/vc44xx_data.c
@@ -30,9 +30,7 @@
* VC data common to 44xx chips
* XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
*/
-static const struct omap_vc_common_data omap4_vc_common = {
- .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
- .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+static const struct omap_vc_common omap4_vc_common = {
.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET,
.data_shift = OMAP4430_DATA_SHIFT,
.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT,
@@ -43,33 +41,49 @@ static const struct omap_vc_common_data omap4_vc_common = {
.cmd_onlp_shift = OMAP4430_ONLP_SHIFT,
.cmd_ret_shift = OMAP4430_RET_SHIFT,
.cmd_off_shift = OMAP4430_OFF_SHIFT,
+ .i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET,
+ .i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK,
+ .i2c_mcode_mask = OMAP4430_HSMCODE_MASK,
};
/* VC instance data for each controllable voltage line */
-struct omap_vc_instance_data omap4_vc_mpu_data = {
- .vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_mpu = {
+ .flags = OMAP_VC_CHANNEL_DEFAULT | OMAP_VC_CHANNEL_CFG_MUTANT,
+ .common = &omap4_vc_common,
+ .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+ .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+ .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+ .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET,
- .smps_sa_shift = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT,
.smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK,
- .smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT,
.smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK,
+ .smps_cmdra_mask = OMAP4430_CMDRA_VDD_MPU_L_MASK,
+ .cfg_channel_sa_shift = OMAP4430_SA_VDD_MPU_L_SHIFT,
};
-struct omap_vc_instance_data omap4_vc_iva_data = {
- .vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_iva = {
+ .common = &omap4_vc_common,
+ .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+ .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+ .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+ .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET,
- .smps_sa_shift = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT,
.smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK,
- .smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT,
.smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK,
+ .smps_cmdra_mask = OMAP4430_CMDRA_VDD_IVA_L_MASK,
+ .cfg_channel_sa_shift = OMAP4430_SA_VDD_IVA_L_SHIFT,
};
-struct omap_vc_instance_data omap4_vc_core_data = {
- .vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_core = {
+ .common = &omap4_vc_common,
+ .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+ .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+ .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+ .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET,
- .smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT,
.smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK,
- .smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT,
.smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK,
+ .smps_cmdra_mask = OMAP4430_CMDRA_VDD_CORE_L_MASK,
+ .cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT,
};
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 9ef3789ded4b..64070ac1e761 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -21,10 +21,10 @@
#include <linux/delay.h>
#include <linux/io.h>
-#include <linux/clk.h>
#include <linux/err.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
+#include <linux/clk.h>
#include <plat/common.h>
@@ -36,839 +36,88 @@
#include "control.h"
#include "voltage.h"
+#include "powerdomain.h"
#include "vc.h"
#include "vp.h"
-#define VOLTAGE_DIR_SIZE 16
-
-
-static struct omap_vdd_info **vdd_info;
-
-/*
- * Number of scalable voltage domains.
- */
-static int nr_scalable_vdd;
-
-/* XXX document */
-static s16 prm_mod_offs;
-static s16 prm_irqst_ocp_mod_offs;
-
-static struct dentry *voltage_dir;
-
-/* Init function pointers */
-static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
- unsigned long target_volt);
-
-static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
-{
- return omap2_prm_read_mod_reg(mod, offset);
-}
-
-static void omap3_voltage_write_reg(u32 val, u16 mod, u8 offset)
-{
- omap2_prm_write_mod_reg(val, mod, offset);
-}
-
-static u32 omap4_voltage_read_reg(u16 mod, u8 offset)
-{
- return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
- mod, offset);
-}
-
-static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset)
-{
- omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset);
-}
-
-static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)
-{
- char *sys_ck_name;
- struct clk *sys_ck;
- u32 sys_clk_speed, timeout_val, waittime;
-
- /*
- * XXX Clockfw should handle this, or this should be in a
- * struct record
- */
- if (cpu_is_omap24xx() || cpu_is_omap34xx())
- sys_ck_name = "sys_ck";
- else if (cpu_is_omap44xx())
- sys_ck_name = "sys_clkin_ck";
- else
- return -EINVAL;
-
- /*
- * Sys clk rate is require to calculate vp timeout value and
- * smpswaittimemin and smpswaittimemax.
- */
- sys_ck = clk_get(NULL, sys_ck_name);
- if (IS_ERR(sys_ck)) {
- pr_warning("%s: Could not get the sys clk to calculate"
- "various vdd_%s params\n", __func__, vdd->voltdm.name);
- return -EINVAL;
- }
- sys_clk_speed = clk_get_rate(sys_ck);
- clk_put(sys_ck);
- /* Divide to avoid overflow */
- sys_clk_speed /= 1000;
-
- /* Generic voltage parameters */
- vdd->volt_scale = vp_forceupdate_scale_voltage;
- vdd->vp_enabled = false;
-
- vdd->vp_rt_data.vpconfig_erroroffset =
- (vdd->pmic_info->vp_erroroffset <<
- vdd->vp_data->vp_common->vpconfig_erroroffset_shift);
-
- timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
- vdd->vp_rt_data.vlimitto_timeout = timeout_val;
- vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
- vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
-
- waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
- sys_clk_speed) / 1000;
- vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime;
- vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime;
- vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
- vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
-
- return 0;
-}
-
-/* Voltage debugfs support */
-static int vp_volt_debug_get(void *data, u64 *val)
-{
- struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
- u8 vsel;
-
- if (!vdd) {
- pr_warning("Wrong paramater passed\n");
- return -EINVAL;
- }
-
- vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
-
- if (!vdd->pmic_info->vsel_to_uv) {
- pr_warning("PMIC function to convert vsel to voltage"
- "in uV not registerd\n");
- return -EINVAL;
- }
-
- *val = vdd->pmic_info->vsel_to_uv(vsel);
- return 0;
-}
-
-static int nom_volt_debug_get(void *data, u64 *val)
-{
- struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
-
- if (!vdd) {
- pr_warning("Wrong paramater passed\n");
- return -EINVAL;
- }
-
- *val = omap_voltage_get_nom_volt(&vdd->voltdm);
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL,
- "%llu\n");
-static void vp_latch_vsel(struct omap_vdd_info *vdd)
-{
- u32 vpconfig;
- unsigned long uvdc;
- char vsel;
-
- uvdc = omap_voltage_get_nom_volt(&vdd->voltdm);
- if (!uvdc) {
- pr_warning("%s: unable to find current voltage for vdd_%s\n",
- __func__, vdd->voltdm.name);
- return;
- }
-
- if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
- pr_warning("%s: PMIC function to convert voltage in uV to"
- " vsel not registered\n", __func__);
- return;
- }
-
- vsel = vdd->pmic_info->uv_to_vsel(uvdc);
-
- vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
- vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask |
- vdd->vp_data->vp_common->vpconfig_initvdd);
- vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift;
-
- vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
- /* Trigger initVDD value copy to voltage processor */
- vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd),
- prm_mod_offs, vdd->vp_data->vpconfig);
-
- /* Clear initVDD copy trigger bit */
- vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-}
-
-/* Generic voltage init functions */
-static void __init vp_init(struct omap_vdd_info *vdd)
-{
- u32 vp_val;
-
- if (!vdd->read_reg || !vdd->write_reg) {
- pr_err("%s: No read/write API for accessing vdd_%s regs\n",
- __func__, vdd->voltdm.name);
- return;
- }
-
- vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
- (vdd->vp_rt_data.vpconfig_errorgain <<
- vdd->vp_data->vp_common->vpconfig_errorgain_shift) |
- vdd->vp_data->vp_common->vpconfig_timeouten;
- vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vpconfig);
-
- vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
- vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) |
- (vdd->vp_rt_data.vstepmin_stepmin <<
- vdd->vp_data->vp_common->vstepmin_stepmin_shift));
- vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmin);
-
- vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
- vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) |
- (vdd->vp_rt_data.vstepmax_stepmax <<
- vdd->vp_data->vp_common->vstepmax_stepmax_shift));
- vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmax);
-
- vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
- vdd->vp_data->vp_common->vlimitto_vddmax_shift) |
- (vdd->vp_rt_data.vlimitto_vddmin <<
- vdd->vp_data->vp_common->vlimitto_vddmin_shift) |
- (vdd->vp_rt_data.vlimitto_timeout <<
- vdd->vp_data->vp_common->vlimitto_timeout_shift));
- vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vlimitto);
-}
-
-static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
-{
- char *name;
-
- name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL);
- if (!name) {
- pr_warning("%s: Unable to allocate memory for debugfs"
- " directory name for vdd_%s",
- __func__, vdd->voltdm.name);
- return;
- }
- strcpy(name, "vdd_");
- strcat(name, vdd->voltdm.name);
-
- vdd->debug_dir = debugfs_create_dir(name, voltage_dir);
- kfree(name);
- if (IS_ERR(vdd->debug_dir)) {
- pr_warning("%s: Unable to create debugfs directory for"
- " vdd_%s\n", __func__, vdd->voltdm.name);
- vdd->debug_dir = NULL;
- return;
- }
-
- (void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_rt_data.vpconfig_errorgain));
- (void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
- vdd->debug_dir,
- &(vdd->vp_rt_data.vstepmin_smpswaittimemin));
- (void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_rt_data.vstepmin_stepmin));
- (void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
- vdd->debug_dir,
- &(vdd->vp_rt_data.vstepmax_smpswaittimemax));
- (void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_rt_data.vstepmax_stepmax));
- (void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_rt_data.vlimitto_vddmax));
- (void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_rt_data.vlimitto_vddmin));
- (void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
- &(vdd->vp_rt_data.vlimitto_timeout));
- (void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir,
- (void *) vdd, &vp_volt_debug_fops);
- (void) debugfs_create_file("curr_nominal_volt", S_IRUGO,
- vdd->debug_dir, (void *) vdd,
- &nom_volt_debug_fops);
-}
-
-/* Voltage scale and accessory APIs */
-static int _pre_volt_scale(struct omap_vdd_info *vdd,
- unsigned long target_volt, u8 *target_vsel, u8 *current_vsel)
-{
- struct omap_volt_data *volt_data;
- const struct omap_vc_common_data *vc_common;
- const struct omap_vp_common_data *vp_common;
- u32 vc_cmdval, vp_errgain_val;
-
- vc_common = vdd->vc_data->vc_common;
- vp_common = vdd->vp_data->vp_common;
-
- /* Check if suffiecient pmic info is available for this vdd */
- if (!vdd->pmic_info) {
- pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
- __func__, vdd->voltdm.name);
- return -EINVAL;
- }
-
- if (!vdd->pmic_info->uv_to_vsel) {
- pr_err("%s: PMIC function to convert voltage in uV to"
- "vsel not registered. Hence unable to scale voltage"
- "for vdd_%s\n", __func__, vdd->voltdm.name);
- return -ENODATA;
- }
-
- if (!vdd->read_reg || !vdd->write_reg) {
- pr_err("%s: No read/write API for accessing vdd_%s regs\n",
- __func__, vdd->voltdm.name);
- return -EINVAL;
- }
-
- /* Get volt_data corresponding to target_volt */
- volt_data = omap_voltage_get_voltdata(&vdd->voltdm, target_volt);
- if (IS_ERR(volt_data))
- volt_data = NULL;
-
- *target_vsel = vdd->pmic_info->uv_to_vsel(target_volt);
- *current_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
-
- /* Setting the ON voltage to the new target voltage */
- vc_cmdval = vdd->read_reg(prm_mod_offs, vdd->vc_data->cmdval_reg);
- vc_cmdval &= ~vc_common->cmd_on_mask;
- vc_cmdval |= (*target_vsel << vc_common->cmd_on_shift);
- vdd->write_reg(vc_cmdval, prm_mod_offs, vdd->vc_data->cmdval_reg);
-
- /* Setting vp errorgain based on the voltage */
- if (volt_data) {
- vp_errgain_val = vdd->read_reg(prm_mod_offs,
- vdd->vp_data->vpconfig);
- vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain;
- vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask;
- vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain <<
- vp_common->vpconfig_errorgain_shift;
- vdd->write_reg(vp_errgain_val, prm_mod_offs,
- vdd->vp_data->vpconfig);
- }
-
- return 0;
-}
-
-static void _post_volt_scale(struct omap_vdd_info *vdd,
- unsigned long target_volt, u8 target_vsel, u8 current_vsel)
-{
- u32 smps_steps = 0, smps_delay = 0;
-
- smps_steps = abs(target_vsel - current_vsel);
- /* SMPS slew rate / step size. 2us added as buffer. */
- smps_delay = ((smps_steps * vdd->pmic_info->step_size) /
- vdd->pmic_info->slew_rate) + 2;
- udelay(smps_delay);
-
- vdd->curr_volt = target_volt;
-}
-
-/* vc_bypass_scale_voltage - VC bypass method of voltage scaling */
-static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
- unsigned long target_volt)
-{
- u32 loop_cnt = 0, retries_cnt = 0;
- u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
- u8 target_vsel, current_vsel;
- int ret;
-
- ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
- if (ret)
- return ret;
-
- vc_valid = vdd->vc_data->vc_common->valid;
- vc_bypass_val_reg = vdd->vc_data->vc_common->bypass_val_reg;
- vc_bypass_value = (target_vsel << vdd->vc_data->vc_common->data_shift) |
- (vdd->pmic_info->pmic_reg <<
- vdd->vc_data->vc_common->regaddr_shift) |
- (vdd->pmic_info->i2c_slave_addr <<
- vdd->vc_data->vc_common->slaveaddr_shift);
-
- vdd->write_reg(vc_bypass_value, prm_mod_offs, vc_bypass_val_reg);
- vdd->write_reg(vc_bypass_value | vc_valid, prm_mod_offs,
- vc_bypass_val_reg);
-
- vc_bypass_value = vdd->read_reg(prm_mod_offs, vc_bypass_val_reg);
- /*
- * Loop till the bypass command is acknowledged from the SMPS.
- * NOTE: This is legacy code. The loop count and retry count needs
- * to be revisited.
- */
- while (!(vc_bypass_value & vc_valid)) {
- loop_cnt++;
-
- if (retries_cnt > 10) {
- pr_warning("%s: Retry count exceeded\n", __func__);
- return -ETIMEDOUT;
- }
-
- if (loop_cnt > 50) {
- retries_cnt++;
- loop_cnt = 0;
- udelay(10);
- }
- vc_bypass_value = vdd->read_reg(prm_mod_offs,
- vc_bypass_val_reg);
- }
-
- _post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
- return 0;
-}
-
-/* VP force update method of voltage scaling */
-static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
- unsigned long target_volt)
-{
- u32 vpconfig;
- u8 target_vsel, current_vsel, prm_irqst_reg;
- int ret, timeout = 0;
-
- ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
- if (ret)
- return ret;
-
- prm_irqst_reg = vdd->vp_data->prm_irqst_data->prm_irqst_reg;
-
- /*
- * Clear all pending TransactionDone interrupt/status. Typical latency
- * is <3us
- */
- while (timeout++ < VP_TRANXDONE_TIMEOUT) {
- vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
- prm_irqst_ocp_mod_offs, prm_irqst_reg);
- if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
- vdd->vp_data->prm_irqst_data->tranxdone_status))
- break;
- udelay(1);
- }
- if (timeout >= VP_TRANXDONE_TIMEOUT) {
- pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
- "Voltage change aborted", __func__, vdd->voltdm.name);
- return -ETIMEDOUT;
- }
-
- /* Configure for VP-Force Update */
- vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
- vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd |
- vdd->vp_data->vp_common->vpconfig_forceupdate |
- vdd->vp_data->vp_common->vpconfig_initvoltage_mask);
- vpconfig |= ((target_vsel <<
- vdd->vp_data->vp_common->vpconfig_initvoltage_shift));
- vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
- /* Trigger initVDD value copy to voltage processor */
- vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd;
- vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
- /* Force update of voltage */
- vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate;
- vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
- /*
- * Wait for TransactionDone. Typical latency is <200us.
- * Depends on SMPSWAITTIMEMIN/MAX and voltage change
- */
- timeout = 0;
- omap_test_timeout((vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
- vdd->vp_data->prm_irqst_data->tranxdone_status),
- VP_TRANXDONE_TIMEOUT, timeout);
- if (timeout >= VP_TRANXDONE_TIMEOUT)
- pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
- "TRANXDONE never got set after the voltage update\n",
- __func__, vdd->voltdm.name);
-
- _post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
-
- /*
- * Disable TransactionDone interrupt , clear all status, clear
- * control registers
- */
- timeout = 0;
- while (timeout++ < VP_TRANXDONE_TIMEOUT) {
- vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
- prm_irqst_ocp_mod_offs, prm_irqst_reg);
- if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
- vdd->vp_data->prm_irqst_data->tranxdone_status))
- break;
- udelay(1);
- }
-
- if (timeout >= VP_TRANXDONE_TIMEOUT)
- pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
- "to clear the TRANXDONE status\n",
- __func__, vdd->voltdm.name);
-
- vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
- /* Clear initVDD copy trigger bit */
- vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd;
- vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
- /* Clear force bit */
- vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate;
- vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
- return 0;
-}
-
-static void __init omap3_vfsm_init(struct omap_vdd_info *vdd)
-{
- /*
- * Voltage Manager FSM parameters init
- * XXX This data should be passed in from the board file
- */
- vdd->write_reg(OMAP3_CLKSETUP, prm_mod_offs, OMAP3_PRM_CLKSETUP_OFFSET);
- vdd->write_reg(OMAP3_VOLTOFFSET, prm_mod_offs,
- OMAP3_PRM_VOLTOFFSET_OFFSET);
- vdd->write_reg(OMAP3_VOLTSETUP2, prm_mod_offs,
- OMAP3_PRM_VOLTSETUP2_OFFSET);
-}
-
-static void __init omap3_vc_init(struct omap_vdd_info *vdd)
-{
- static bool is_initialized;
- u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
- u32 vc_val;
-
- if (is_initialized)
- return;
-
- /* Set up the on, inactive, retention and off voltage */
- on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->on_volt);
- onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->onlp_volt);
- ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->ret_volt);
- off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->off_volt);
- vc_val = ((on_vsel << vdd->vc_data->vc_common->cmd_on_shift) |
- (onlp_vsel << vdd->vc_data->vc_common->cmd_onlp_shift) |
- (ret_vsel << vdd->vc_data->vc_common->cmd_ret_shift) |
- (off_vsel << vdd->vc_data->vc_common->cmd_off_shift));
- vdd->write_reg(vc_val, prm_mod_offs, vdd->vc_data->cmdval_reg);
-
- /*
- * Generic VC parameters init
- * XXX This data should be abstracted out
- */
- vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, prm_mod_offs,
- OMAP3_PRM_VC_CH_CONF_OFFSET);
- vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, prm_mod_offs,
- OMAP3_PRM_VC_I2C_CFG_OFFSET);
-
- omap3_vfsm_init(vdd);
-
- is_initialized = true;
-}
-
-
-/* OMAP4 specific voltage init functions */
-static void __init omap4_vc_init(struct omap_vdd_info *vdd)
-{
- static bool is_initialized;
- u32 vc_val;
-
- if (is_initialized)
- return;
-
- /* TODO: Configure setup times and CMD_VAL values*/
-
- /*
- * Generic VC parameters init
- * XXX This data should be abstracted out
- */
- vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
- OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
- OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
- vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
-
- /* XXX These are magic numbers and do not belong! */
- vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
- vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
-
- is_initialized = true;
-}
-
-static void __init omap_vc_init(struct omap_vdd_info *vdd)
-{
- u32 vc_val;
-
- if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
- pr_err("%s: PMIC info requried to configure vc for"
- "vdd_%s not populated.Hence cannot initialize vc\n",
- __func__, vdd->voltdm.name);
- return;
- }
-
- if (!vdd->read_reg || !vdd->write_reg) {
- pr_err("%s: No read/write API for accessing vdd_%s regs\n",
- __func__, vdd->voltdm.name);
- return;
- }
-
- /* Set up the SMPS_SA(i2c slave address in VC */
- vc_val = vdd->read_reg(prm_mod_offs,
- vdd->vc_data->vc_common->smps_sa_reg);
- vc_val &= ~vdd->vc_data->smps_sa_mask;
- vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_data->smps_sa_shift;
- vdd->write_reg(vc_val, prm_mod_offs,
- vdd->vc_data->vc_common->smps_sa_reg);
-
- /* Setup the VOLRA(pmic reg addr) in VC */
- vc_val = vdd->read_reg(prm_mod_offs,
- vdd->vc_data->vc_common->smps_volra_reg);
- vc_val &= ~vdd->vc_data->smps_volra_mask;
- vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_data->smps_volra_shift;
- vdd->write_reg(vc_val, prm_mod_offs,
- vdd->vc_data->vc_common->smps_volra_reg);
-
- /* Configure the setup times */
- vc_val = vdd->read_reg(prm_mod_offs, vdd->vfsm->voltsetup_reg);
- vc_val &= ~vdd->vfsm->voltsetup_mask;
- vc_val |= vdd->pmic_info->volt_setup_time <<
- vdd->vfsm->voltsetup_shift;
- vdd->write_reg(vc_val, prm_mod_offs, vdd->vfsm->voltsetup_reg);
-
- if (cpu_is_omap34xx())
- omap3_vc_init(vdd);
- else if (cpu_is_omap44xx())
- omap4_vc_init(vdd);
-}
-
-static int __init omap_vdd_data_configure(struct omap_vdd_info *vdd)
-{
- int ret = -EINVAL;
-
- if (!vdd->pmic_info) {
- pr_err("%s: PMIC info requried to configure vdd_%s not"
- "populated.Hence cannot initialize vdd_%s\n",
- __func__, vdd->voltdm.name, vdd->voltdm.name);
- goto ovdc_out;
- }
-
- if (IS_ERR_VALUE(_config_common_vdd_data(vdd)))
- goto ovdc_out;
-
- if (cpu_is_omap34xx()) {
- vdd->read_reg = omap3_voltage_read_reg;
- vdd->write_reg = omap3_voltage_write_reg;
- ret = 0;
- } else if (cpu_is_omap44xx()) {
- vdd->read_reg = omap4_voltage_read_reg;
- vdd->write_reg = omap4_voltage_write_reg;
- ret = 0;
- }
-
-ovdc_out:
- return ret;
-}
+static LIST_HEAD(voltdm_list);
/* Public functions */
/**
- * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
- * @voltdm: pointer to the VDD for which current voltage info is needed
+ * voltdm_get_voltage() - Gets the current non-auto-compensated voltage
+ * @voltdm: pointer to the voltdm for which current voltage info is needed
*
- * API to get the current non-auto-compensated voltage for a VDD.
- * Returns 0 in case of error else returns the current voltage for the VDD.
+ * API to get the current non-auto-compensated voltage for a voltage domain.
+ * Returns 0 in case of error else returns the current voltage.
*/
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm)
{
- struct omap_vdd_info *vdd;
-
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return 0;
}
- vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
- return vdd->curr_volt;
+ return voltdm->nominal_volt;
}
/**
- * omap_vp_get_curr_volt() - API to get the current vp voltage.
- * @voltdm: pointer to the VDD.
- *
- * This API returns the current voltage for the specified voltage processor
- */
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
-{
- struct omap_vdd_info *vdd;
- u8 curr_vsel;
-
- if (!voltdm || IS_ERR(voltdm)) {
- pr_warning("%s: VDD specified does not exist!\n", __func__);
- return 0;
- }
-
- vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
- if (!vdd->read_reg) {
- pr_err("%s: No read API for reading vdd_%s regs\n",
- __func__, voltdm->name);
- return 0;
- }
-
- curr_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
-
- if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
- pr_warning("%s: PMIC function to convert vsel to voltage"
- "in uV not registerd\n", __func__);
- return 0;
- }
-
- return vdd->pmic_info->vsel_to_uv(curr_vsel);
-}
-
-/**
- * omap_vp_enable() - API to enable a particular VP
- * @voltdm: pointer to the VDD whose VP is to be enabled.
- *
- * This API enables a particular voltage processor. Needed by the smartreflex
- * class drivers.
- */
-void omap_vp_enable(struct voltagedomain *voltdm)
-{
- struct omap_vdd_info *vdd;
- u32 vpconfig;
-
- if (!voltdm || IS_ERR(voltdm)) {
- pr_warning("%s: VDD specified does not exist!\n", __func__);
- return;
- }
-
- vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
- if (!vdd->read_reg || !vdd->write_reg) {
- pr_err("%s: No read/write API for accessing vdd_%s regs\n",
- __func__, voltdm->name);
- return;
- }
-
- /* If VP is already enabled, do nothing. Return */
- if (vdd->vp_enabled)
- return;
-
- vp_latch_vsel(vdd);
-
- /* Enable VP */
- vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
- vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable;
- vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
- vdd->vp_enabled = true;
-}
-
-/**
- * omap_vp_disable() - API to disable a particular VP
- * @voltdm: pointer to the VDD whose VP is to be disabled.
- *
- * This API disables a particular voltage processor. Needed by the smartreflex
- * class drivers.
- */
-void omap_vp_disable(struct voltagedomain *voltdm)
-{
- struct omap_vdd_info *vdd;
- u32 vpconfig;
- int timeout;
-
- if (!voltdm || IS_ERR(voltdm)) {
- pr_warning("%s: VDD specified does not exist!\n", __func__);
- return;
- }
-
- vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
- if (!vdd->read_reg || !vdd->write_reg) {
- pr_err("%s: No read/write API for accessing vdd_%s regs\n",
- __func__, voltdm->name);
- return;
- }
-
- /* If VP is already disabled, do nothing. Return */
- if (!vdd->vp_enabled) {
- pr_warning("%s: Trying to disable VP for vdd_%s when"
- "it is already disabled\n", __func__, voltdm->name);
- return;
- }
-
- /* Disable VP */
- vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
- vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable;
- vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
- /*
- * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
- */
- omap_test_timeout((vdd->read_reg(prm_mod_offs, vdd->vp_data->vstatus)),
- VP_IDLE_TIMEOUT, timeout);
-
- if (timeout >= VP_IDLE_TIMEOUT)
- pr_warning("%s: vdd_%s idle timedout\n",
- __func__, voltdm->name);
-
- vdd->vp_enabled = false;
-
- return;
-}
-
-/**
- * omap_voltage_scale_vdd() - API to scale voltage of a particular
- * voltage domain.
- * @voltdm: pointer to the VDD which is to be scaled.
- * @target_volt: The target voltage of the voltage domain
+ * voltdm_scale() - API to scale voltage of a particular voltage domain.
+ * @voltdm: pointer to the voltage domain which is to be scaled.
+ * @target_volt: The target voltage of the voltage domain
*
* This API should be called by the kernel to do the voltage scaling
- * for a particular voltage domain during dvfs or any other situation.
+ * for a particular voltage domain during DVFS.
*/
-int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
- unsigned long target_volt)
+int voltdm_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt)
{
- struct omap_vdd_info *vdd;
+ int ret;
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return -EINVAL;
}
- vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
- if (!vdd->volt_scale) {
+ if (!voltdm->scale) {
pr_err("%s: No voltage scale API registered for vdd_%s\n",
__func__, voltdm->name);
return -ENODATA;
}
- return vdd->volt_scale(vdd, target_volt);
+ ret = voltdm->scale(voltdm, target_volt);
+ if (!ret)
+ voltdm->nominal_volt = target_volt;
+
+ return ret;
}
/**
- * omap_voltage_reset() - Resets the voltage of a particular voltage domain
- * to that of the current OPP.
- * @voltdm: pointer to the VDD whose voltage is to be reset.
+ * voltdm_reset() - Resets the voltage of a particular voltage domain
+ * to that of the current OPP.
+ * @voltdm: pointer to the voltage domain whose voltage is to be reset.
*
* This API finds out the correct voltage the voltage domain is supposed
* to be at and resets the voltage to that level. Should be used especially
* while disabling any voltage compensation modules.
*/
-void omap_voltage_reset(struct voltagedomain *voltdm)
+void voltdm_reset(struct voltagedomain *voltdm)
{
- unsigned long target_uvdc;
+ unsigned long target_volt;
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
- target_uvdc = omap_voltage_get_nom_volt(voltdm);
- if (!target_uvdc) {
+ target_volt = voltdm_get_voltage(voltdm);
+ if (!target_volt) {
pr_err("%s: unable to find current voltage for vdd_%s\n",
__func__, voltdm->name);
return;
}
- omap_voltage_scale_vdd(voltdm, target_uvdc);
+ voltdm_scale(voltdm, target_volt);
}
/**
@@ -884,18 +133,14 @@ void omap_voltage_reset(struct voltagedomain *voltdm)
*
*/
void omap_voltage_get_volttable(struct voltagedomain *voltdm,
- struct omap_volt_data **volt_data)
+ struct omap_volt_data **volt_data)
{
- struct omap_vdd_info *vdd;
-
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
- vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
- *volt_data = vdd->volt_data;
+ *volt_data = voltdm->volt_data;
}
/**
@@ -914,9 +159,8 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm,
* domain or if there is no matching entry.
*/
struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
- unsigned long volt)
+ unsigned long volt)
{
- struct omap_vdd_info *vdd;
int i;
if (!voltdm || IS_ERR(voltdm)) {
@@ -924,17 +168,15 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
return ERR_PTR(-EINVAL);
}
- vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
- if (!vdd->volt_data) {
+ if (!voltdm->volt_data) {
pr_warning("%s: voltage table does not exist for vdd_%s\n",
__func__, voltdm->name);
return ERR_PTR(-ENODATA);
}
- for (i = 0; vdd->volt_data[i].volt_nominal != 0; i++) {
- if (vdd->volt_data[i].volt_nominal == volt)
- return &vdd->volt_data[i];
+ for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
+ if (voltdm->volt_data[i].volt_nominal == volt)
+ return &voltdm->volt_data[i];
}
pr_notice("%s: Unable to match the current voltage with the voltage"
@@ -947,54 +189,25 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
* omap_voltage_register_pmic() - API to register PMIC specific data
* @voltdm: pointer to the VDD for which the PMIC specific data is
* to be registered
- * @pmic_info: the structure containing pmic info
+ * @pmic: the structure containing pmic info
*
* This API is to be called by the SOC/PMIC file to specify the
- * pmic specific info as present in omap_volt_pmic_info structure.
+ * pmic specific info as present in omap_voltdm_pmic structure.
*/
int omap_voltage_register_pmic(struct voltagedomain *voltdm,
- struct omap_volt_pmic_info *pmic_info)
+ struct omap_voltdm_pmic *pmic)
{
- struct omap_vdd_info *vdd;
-
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return -EINVAL;
}
- vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
- vdd->pmic_info = pmic_info;
+ voltdm->pmic = pmic;
return 0;
}
/**
- * omap_voltage_get_dbgdir() - API to get pointer to the debugfs directory
- * corresponding to a voltage domain.
- *
- * @voltdm: pointer to the VDD whose debug directory is required.
- *
- * This API returns pointer to the debugfs directory corresponding
- * to the voltage domain. Should be used by drivers requiring to
- * add any debug entry for a particular voltage domain. Returns NULL
- * in case of error.
- */
-struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)
-{
- struct omap_vdd_info *vdd;
-
- if (!voltdm || IS_ERR(voltdm)) {
- pr_warning("%s: VDD specified does not exist!\n", __func__);
- return NULL;
- }
-
- vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
- return vdd->debug_dir;
-}
-
-/**
* omap_change_voltscale_method() - API to change the voltage scaling method.
* @voltdm: pointer to the VDD whose voltage scaling method
* has to be changed.
@@ -1005,23 +218,19 @@ struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)
* defined in voltage.h
*/
void omap_change_voltscale_method(struct voltagedomain *voltdm,
- int voltscale_method)
+ int voltscale_method)
{
- struct omap_vdd_info *vdd;
-
if (!voltdm || IS_ERR(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
- vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
switch (voltscale_method) {
case VOLTSCALE_VPFORCEUPDATE:
- vdd->volt_scale = vp_forceupdate_scale_voltage;
+ voltdm->scale = omap_vp_forceupdate_scale;
return;
case VOLTSCALE_VCBYPASS:
- vdd->volt_scale = vc_bypass_scale_voltage;
+ voltdm->scale = omap_vc_bypass_scale;
return;
default:
pr_warning("%s: Trying to change the method of voltage scaling"
@@ -1030,77 +239,192 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm,
}
/**
- * omap_voltage_domain_lookup() - API to get the voltage domain pointer
- * @name: Name of the voltage domain
+ * omap_voltage_late_init() - Init the various voltage parameters
*
- * This API looks up in the global vdd_info struct for the
- * existence of voltage domain <name>. If it exists, the API returns
- * a pointer to the voltage domain structure corresponding to the
- * VDD<name>. Else retuns error pointer.
+ * This API is to be called in the later stages of the
+ * system boot to init the voltage controller and
+ * voltage processors.
*/
-struct voltagedomain *omap_voltage_domain_lookup(char *name)
+int __init omap_voltage_late_init(void)
{
- int i;
+ struct voltagedomain *voltdm;
- if (!vdd_info) {
- pr_err("%s: Voltage driver init not yet happened.Faulting!\n",
+ if (list_empty(&voltdm_list)) {
+ pr_err("%s: Voltage driver support not added\n",
__func__);
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
- if (!name) {
- pr_err("%s: No name to get the votage domain!\n", __func__);
- return ERR_PTR(-EINVAL);
+ list_for_each_entry(voltdm, &voltdm_list, node) {
+ struct clk *sys_ck;
+
+ if (!voltdm->scalable)
+ continue;
+
+ sys_ck = clk_get(NULL, voltdm->sys_clk.name);
+ if (IS_ERR(sys_ck)) {
+ pr_warning("%s: Could not get sys clk.\n", __func__);
+ return -EINVAL;
+ }
+ voltdm->sys_clk.rate = clk_get_rate(sys_ck);
+ WARN_ON(!voltdm->sys_clk.rate);
+ clk_put(sys_ck);
+
+ if (voltdm->vc) {
+ voltdm->scale = omap_vc_bypass_scale;
+ omap_vc_init_channel(voltdm);
+ }
+
+ if (voltdm->vp) {
+ voltdm->scale = omap_vp_forceupdate_scale;
+ omap_vp_init(voltdm);
+ }
}
- for (i = 0; i < nr_scalable_vdd; i++) {
- if (!(strcmp(name, vdd_info[i]->voltdm.name)))
- return &vdd_info[i]->voltdm;
+ return 0;
+}
+
+static struct voltagedomain *_voltdm_lookup(const char *name)
+{
+ struct voltagedomain *voltdm, *temp_voltdm;
+
+ voltdm = NULL;
+
+ list_for_each_entry(temp_voltdm, &voltdm_list, node) {
+ if (!strcmp(name, temp_voltdm->name)) {
+ voltdm = temp_voltdm;
+ break;
+ }
}
- return ERR_PTR(-EINVAL);
+ return voltdm;
}
/**
- * omap_voltage_late_init() - Init the various voltage parameters
+ * voltdm_add_pwrdm - add a powerdomain to a voltagedomain
+ * @voltdm: struct voltagedomain * to add the powerdomain to
+ * @pwrdm: struct powerdomain * to associate with a voltagedomain
*
- * This API is to be called in the later stages of the
- * system boot to init the voltage controller and
- * voltage processors.
+ * Associate the powerdomain @pwrdm with a voltagedomain @voltdm. This
+ * enables the use of voltdm_for_each_pwrdm(). Returns -EINVAL if
+ * presented with invalid pointers; -ENOMEM if memory could not be allocated;
+ * or 0 upon success.
*/
-int __init omap_voltage_late_init(void)
+int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm)
{
- int i;
+ if (!voltdm || !pwrdm)
+ return -EINVAL;
- if (!vdd_info) {
- pr_err("%s: Voltage driver support not added\n",
- __func__);
+ pr_debug("voltagedomain: associating powerdomain %s with voltagedomain "
+ "%s\n", pwrdm->name, voltdm->name);
+
+ list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list);
+
+ return 0;
+}
+
+/**
+ * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm
+ * @voltdm: struct voltagedomain * to iterate over
+ * @fn: callback function *
+ *
+ * Call the supplied function @fn for each powerdomain in the
+ * voltagedomain @voltdm. Returns -EINVAL if presented with invalid
+ * pointers; or passes along the last return value of the callback
+ * function, which should be 0 for success or anything else to
+ * indicate failure.
+ */
+int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
+ int (*fn)(struct voltagedomain *voltdm,
+ struct powerdomain *pwrdm))
+{
+ struct powerdomain *pwrdm;
+ int ret = 0;
+
+ if (!fn)
return -EINVAL;
- }
- voltage_dir = debugfs_create_dir("voltage", NULL);
- if (IS_ERR(voltage_dir))
- pr_err("%s: Unable to create voltage debugfs main dir\n",
- __func__);
- for (i = 0; i < nr_scalable_vdd; i++) {
- if (omap_vdd_data_configure(vdd_info[i]))
- continue;
- omap_vc_init(vdd_info[i]);
- vp_init(vdd_info[i]);
- vdd_debugfs_init(vdd_info[i]);
+ list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node)
+ ret = (*fn)(voltdm, pwrdm);
+
+ return ret;
+}
+
+/**
+ * voltdm_for_each - call function on each registered voltagedomain
+ * @fn: callback function *
+ *
+ * Call the supplied function @fn for each registered voltagedomain.
+ * The callback function @fn can return anything but 0 to bail out
+ * early from the iterator. Returns the last return value of the
+ * callback function, which should be 0 for success or anything else
+ * to indicate failure; or -EINVAL if the function pointer is null.
+ */
+int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
+ void *user)
+{
+ struct voltagedomain *temp_voltdm;
+ int ret = 0;
+
+ if (!fn)
+ return -EINVAL;
+
+ list_for_each_entry(temp_voltdm, &voltdm_list, node) {
+ ret = (*fn)(temp_voltdm, user);
+ if (ret)
+ break;
}
- return 0;
+ return ret;
}
-/* XXX document */
-int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_ocp_mod,
- struct omap_vdd_info *omap_vdd_array[],
- u8 omap_vdd_count)
+static int _voltdm_register(struct voltagedomain *voltdm)
{
- prm_mod_offs = prm_mod;
- prm_irqst_ocp_mod_offs = prm_irqst_ocp_mod;
- vdd_info = omap_vdd_array;
- nr_scalable_vdd = omap_vdd_count;
+ if (!voltdm || !voltdm->name)
+ return -EINVAL;
+
+ INIT_LIST_HEAD(&voltdm->pwrdm_list);
+ list_add(&voltdm->node, &voltdm_list);
+
+ pr_debug("voltagedomain: registered %s\n", voltdm->name);
+
return 0;
}
+
+/**
+ * voltdm_lookup - look up a voltagedomain by name, return a pointer
+ * @name: name of voltagedomain
+ *
+ * Find a registered voltagedomain by its name @name. Returns a pointer
+ * to the struct voltagedomain if found, or NULL otherwise.
+ */
+struct voltagedomain *voltdm_lookup(const char *name)
+{
+ struct voltagedomain *voltdm ;
+
+ if (!name)
+ return NULL;
+
+ voltdm = _voltdm_lookup(name);
+
+ return voltdm;
+}
+
+/**
+ * voltdm_init - set up the voltagedomain layer
+ * @voltdm_list: array of struct voltagedomain pointers to register
+ *
+ * Loop through the array of voltagedomains @voltdm_list, registering all
+ * that are available on the current CPU. If voltdm_list is supplied
+ * and not null, all of the referenced voltagedomains will be
+ * registered. No return value.
+ */
+void voltdm_init(struct voltagedomain **voltdms)
+{
+ struct voltagedomain **v;
+
+ if (voltdms) {
+ for (v = voltdms; *v; v++)
+ _voltdm_register(*v);
+ }
+}
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index e9f5408244e0..16a1b092cf36 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -19,6 +19,8 @@
#include "vc.h"
#include "vp.h"
+struct powerdomain;
+
/* XXX document */
#define VOLTSCALE_VPFORCEUPDATE 1
#define VOLTSCALE_VCBYPASS 2
@@ -32,29 +34,60 @@
#define OMAP3_VOLTSETUP2 0xff
/**
- * struct omap_vfsm_instance_data - per-voltage manager FSM register/bitfield
+ * struct omap_vfsm_instance - per-voltage manager FSM register/bitfield
* data
* @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
* @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
- * @voltsetup_shift: SETUP_TIME* field shift in the PRM_VOLTSETUP* register
*
* XXX What about VOLTOFFSET/VOLTCTRL?
- * XXX It is not necessary to have both a _mask and a _shift for the same
- * bitfield - remove one!
*/
-struct omap_vfsm_instance_data {
+struct omap_vfsm_instance {
u32 voltsetup_mask;
u8 voltsetup_reg;
- u8 voltsetup_shift;
};
/**
* struct voltagedomain - omap voltage domain global structure.
- * @name: Name of the voltage domain which can be used as a unique
- * identifier.
+ * @name: Name of the voltage domain which can be used as a unique identifier.
+ * @scalable: Whether or not this voltage domain is scalable
+ * @node: list_head linking all voltage domains
+ * @pwrdm_list: list_head linking all powerdomains in this voltagedomain
+ * @vc: pointer to VC channel associated with this voltagedomain
+ * @vp: pointer to VP associated with this voltagedomain
+ * @read: read a VC/VP register
+ * @write: write a VC/VP register
+ * @read: read-modify-write a VC/VP register
+ * @sys_clk: system clock name/frequency, used for various timing calculations
+ * @scale: function used to scale the voltage of the voltagedomain
+ * @nominal_volt: current nominal voltage for this voltage domain
+ * @volt_data: voltage table having the distinct voltages supported
+ * by the domain and other associated per voltage data.
*/
struct voltagedomain {
char *name;
+ bool scalable;
+ struct list_head node;
+ struct list_head pwrdm_list;
+ struct omap_vc_channel *vc;
+ const struct omap_vfsm_instance *vfsm;
+ struct omap_vp_instance *vp;
+ struct omap_voltdm_pmic *pmic;
+
+ /* VC/VP register access functions: SoC specific */
+ u32 (*read) (u8 offset);
+ void (*write) (u32 val, u8 offset);
+ u32 (*rmw)(u32 mask, u32 bits, u8 offset);
+
+ union {
+ const char *name;
+ u32 rate;
+ } sys_clk;
+
+ int (*scale) (struct voltagedomain *voltdm,
+ unsigned long target_volt);
+
+ u32 nominal_volt;
+ struct omap_volt_data *volt_data;
};
/**
@@ -77,13 +110,18 @@ struct omap_volt_data {
};
/**
- * struct omap_volt_pmic_info - PMIC specific data required by voltage driver.
+ * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
* @slew_rate: PMIC slew rate (in uv/us)
* @step_size: PMIC voltage step size (in uv)
+ * @i2c_slave_addr: I2C slave address of PMIC
+ * @volt_reg_addr: voltage configuration register address
+ * @cmd_reg_addr: command (on, on-LP, ret, off) configuration register address
+ * @i2c_high_speed: whether VC uses I2C high-speed mode to PMIC
+ * @i2c_mcode: master code value for I2C high-speed preamble transmission
* @vsel_to_uv: PMIC API to convert vsel value to actual voltage in uV.
* @uv_to_vsel: PMIC API to convert voltage in uV to vsel value.
*/
-struct omap_volt_pmic_info {
+struct omap_voltdm_pmic {
int slew_rate;
int step_size;
u32 on_volt;
@@ -91,94 +129,44 @@ struct omap_volt_pmic_info {
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;
u8 vp_timeout_us;
- u8 i2c_slave_addr;
- u8 pmic_reg;
+ bool i2c_high_speed;
+ u8 i2c_mcode;
unsigned long (*vsel_to_uv) (const u8 vsel);
u8 (*uv_to_vsel) (unsigned long uV);
};
-/**
- * omap_vdd_info - Per Voltage Domain info
- *
- * @volt_data : voltage table having the distinct voltages supported
- * by the domain and other associated per voltage data.
- * @pmic_info : pmic specific parameters which should be populted by
- * the pmic drivers.
- * @vp_data : the register values, shifts, masks for various
- * vp registers
- * @vp_rt_data : VP data derived at runtime, not predefined
- * @vc_data : structure containing various various vc registers,
- * shifts, masks etc.
- * @vfsm : voltage manager FSM data
- * @voltdm : pointer to the voltage domain structure
- * @debug_dir : debug directory for this voltage domain.
- * @curr_volt : current voltage for this vdd.
- * @vp_enabled : flag to keep track of whether vp is enabled or not
- * @volt_scale : API to scale the voltage of the vdd.
- */
-struct omap_vdd_info {
- struct omap_volt_data *volt_data;
- struct omap_volt_pmic_info *pmic_info;
- struct omap_vp_instance_data *vp_data;
- struct omap_vp_runtime_data vp_rt_data;
- struct omap_vc_instance_data *vc_data;
- const struct omap_vfsm_instance_data *vfsm;
- struct voltagedomain voltdm;
- struct dentry *debug_dir;
- u32 curr_volt;
- bool vp_enabled;
- u32 (*read_reg) (u16 mod, u8 offset);
- void (*write_reg) (u32 val, u16 mod, u8 offset);
- int (*volt_scale) (struct omap_vdd_info *vdd,
- unsigned long target_volt);
-};
-
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
-void omap_vp_enable(struct voltagedomain *voltdm);
-void omap_vp_disable(struct voltagedomain *voltdm);
-int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
- unsigned long target_volt);
-void omap_voltage_reset(struct voltagedomain *voltdm);
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,
unsigned long volt);
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
-struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
-int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod,
- struct omap_vdd_info *omap_vdd_array[],
- u8 omap_vdd_count);
-#ifdef CONFIG_PM
int omap_voltage_register_pmic(struct voltagedomain *voltdm,
- struct omap_volt_pmic_info *pmic_info);
+ struct omap_voltdm_pmic *pmic);
void omap_change_voltscale_method(struct voltagedomain *voltdm,
int voltscale_method);
-/* API to get the voltagedomain pointer */
-struct voltagedomain *omap_voltage_domain_lookup(char *name);
-
int omap_voltage_late_init(void);
-#else
-static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
- struct omap_volt_pmic_info *pmic_info)
-{
- return -EINVAL;
-}
-static inline void omap_change_voltscale_method(struct voltagedomain *voltdm,
- int voltscale_method) {}
-static inline int omap_voltage_late_init(void)
-{
- return -EINVAL;
-}
-static inline struct voltagedomain *omap_voltage_domain_lookup(char *name)
-{
- return ERR_PTR(-EINVAL);
-}
-#endif
+extern void omap2xxx_voltagedomains_init(void);
+extern void omap3xxx_voltagedomains_init(void);
+extern void omap44xx_voltagedomains_init(void);
+
+struct voltagedomain *voltdm_lookup(const char *name);
+void voltdm_init(struct voltagedomain **voltdm_list);
+int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm);
+int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
+ void *user);
+int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
+ int (*fn)(struct voltagedomain *voltdm,
+ struct powerdomain *pwrdm));
+int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
+void voltdm_reset(struct voltagedomain *voltdm);
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
#endif
diff --git a/arch/arm/mach-omap2/voltagedomains2xxx_data.c b/arch/arm/mach-omap2/voltagedomains2xxx_data.c
new file mode 100644
index 000000000000..7a41349981e5
--- /dev/null
+++ b/arch/arm/mach-omap2/voltagedomains2xxx_data.c
@@ -0,0 +1,32 @@
+/*
+ * OMAP3 voltage domain data
+ *
+ * Copyright (C) 2011 Texas Instruments, 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.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "voltage.h"
+
+static struct voltagedomain omap2_voltdm_core = {
+ .name = "core",
+};
+
+static struct voltagedomain omap2_voltdm_wkup = {
+ .name = "wakeup",
+};
+
+static struct voltagedomain *voltagedomains_omap2[] __initdata = {
+ &omap2_voltdm_core,
+ &omap2_voltdm_wkup,
+ NULL,
+};
+
+void __init omap2xxx_voltagedomains_init(void)
+{
+ voltdm_init(voltagedomains_omap2);
+}
diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
index def230fd2fde..071101debbbc 100644
--- a/arch/arm/mach-omap2/voltagedomains3xxx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
@@ -31,65 +31,70 @@
* VDD data
*/
-static const struct omap_vfsm_instance_data omap3_vdd1_vfsm_data = {
+static const struct omap_vfsm_instance omap3_vdd1_vfsm = {
.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
- .voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT,
.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK,
};
-static struct omap_vdd_info omap3_vdd1_info = {
- .vp_data = &omap3_vp1_data,
- .vc_data = &omap3_vc1_data,
- .vfsm = &omap3_vdd1_vfsm_data,
- .voltdm = {
- .name = "mpu",
- },
-};
-
-static const struct omap_vfsm_instance_data omap3_vdd2_vfsm_data = {
+static const struct omap_vfsm_instance omap3_vdd2_vfsm = {
.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
- .voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT,
.voltsetup_mask = OMAP3430_SETUP_TIME2_MASK,
};
-static struct omap_vdd_info omap3_vdd2_info = {
- .vp_data = &omap3_vp2_data,
- .vc_data = &omap3_vc2_data,
- .vfsm = &omap3_vdd2_vfsm_data,
- .voltdm = {
- .name = "core",
- },
+static struct voltagedomain omap3_voltdm_mpu = {
+ .name = "mpu_iva",
+ .scalable = true,
+ .read = omap3_prm_vcvp_read,
+ .write = omap3_prm_vcvp_write,
+ .rmw = omap3_prm_vcvp_rmw,
+ .vc = &omap3_vc_mpu,
+ .vfsm = &omap3_vdd1_vfsm,
+ .vp = &omap3_vp_mpu,
};
-/* OMAP3 VDD structures */
-static struct omap_vdd_info *omap3_vdd_info[] = {
- &omap3_vdd1_info,
- &omap3_vdd2_info,
+static struct voltagedomain omap3_voltdm_core = {
+ .name = "core",
+ .scalable = true,
+ .read = omap3_prm_vcvp_read,
+ .write = omap3_prm_vcvp_write,
+ .rmw = omap3_prm_vcvp_rmw,
+ .vc = &omap3_vc_core,
+ .vfsm = &omap3_vdd2_vfsm,
+ .vp = &omap3_vp_core,
};
-/* OMAP3 specific voltage init functions */
-static int __init omap3xxx_voltage_early_init(void)
-{
- s16 prm_mod = OMAP3430_GR_MOD;
- s16 prm_irqst_ocp_mod = OCP_MOD;
+static struct voltagedomain omap3_voltdm_wkup = {
+ .name = "wakeup",
+};
- if (!cpu_is_omap34xx())
- return 0;
+static struct voltagedomain *voltagedomains_omap3[] __initdata = {
+ &omap3_voltdm_mpu,
+ &omap3_voltdm_core,
+ &omap3_voltdm_wkup,
+ NULL,
+};
+
+static const char *sys_clk_name __initdata = "sys_ck";
+
+void __init omap3xxx_voltagedomains_init(void)
+{
+ struct voltagedomain *voltdm;
+ int i;
/*
* XXX Will depend on the process, validation, and binning
* for the currently-running IC
*/
if (cpu_is_omap3630()) {
- omap3_vdd1_info.volt_data = omap36xx_vddmpu_volt_data;
- omap3_vdd2_info.volt_data = omap36xx_vddcore_volt_data;
+ omap3_voltdm_mpu.volt_data = omap36xx_vddmpu_volt_data;
+ omap3_voltdm_core.volt_data = omap36xx_vddcore_volt_data;
} else {
- omap3_vdd1_info.volt_data = omap34xx_vddmpu_volt_data;
- omap3_vdd2_info.volt_data = omap34xx_vddcore_volt_data;
+ omap3_voltdm_mpu.volt_data = omap34xx_vddmpu_volt_data;
+ omap3_voltdm_core.volt_data = omap34xx_vddcore_volt_data;
}
- return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
- omap3_vdd_info,
- ARRAY_SIZE(omap3_vdd_info));
+ for (i = 0; voltdm = voltagedomains_omap3[i], voltdm; i++)
+ voltdm->sys_clk.name = sys_clk_name;
+
+ voltdm_init(voltagedomains_omap3);
};
-core_initcall(omap3xxx_voltage_early_init);
diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c
index cb64996de0e1..c4584e9ac717 100644
--- a/arch/arm/mach-omap2/voltagedomains44xx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c
@@ -32,71 +32,80 @@
#include "vc.h"
#include "vp.h"
-static const struct omap_vfsm_instance_data omap4_vdd_mpu_vfsm_data = {
+static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = {
.voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
};
-static struct omap_vdd_info omap4_vdd_mpu_info = {
- .vp_data = &omap4_vp_mpu_data,
- .vc_data = &omap4_vc_mpu_data,
- .vfsm = &omap4_vdd_mpu_vfsm_data,
- .voltdm = {
- .name = "mpu",
- },
+static const struct omap_vfsm_instance omap4_vdd_iva_vfsm = {
+ .voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
};
-static const struct omap_vfsm_instance_data omap4_vdd_iva_vfsm_data = {
- .voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
+static const struct omap_vfsm_instance omap4_vdd_core_vfsm = {
+ .voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
};
-static struct omap_vdd_info omap4_vdd_iva_info = {
- .vp_data = &omap4_vp_iva_data,
- .vc_data = &omap4_vc_iva_data,
- .vfsm = &omap4_vdd_iva_vfsm_data,
- .voltdm = {
- .name = "iva",
- },
+static struct voltagedomain omap4_voltdm_mpu = {
+ .name = "mpu",
+ .scalable = true,
+ .read = omap4_prm_vcvp_read,
+ .write = omap4_prm_vcvp_write,
+ .rmw = omap4_prm_vcvp_rmw,
+ .vc = &omap4_vc_mpu,
+ .vfsm = &omap4_vdd_mpu_vfsm,
+ .vp = &omap4_vp_mpu,
};
-static const struct omap_vfsm_instance_data omap4_vdd_core_vfsm_data = {
- .voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
+static struct voltagedomain omap4_voltdm_iva = {
+ .name = "iva",
+ .scalable = true,
+ .read = omap4_prm_vcvp_read,
+ .write = omap4_prm_vcvp_write,
+ .rmw = omap4_prm_vcvp_rmw,
+ .vc = &omap4_vc_iva,
+ .vfsm = &omap4_vdd_iva_vfsm,
+ .vp = &omap4_vp_iva,
};
-static struct omap_vdd_info omap4_vdd_core_info = {
- .vp_data = &omap4_vp_core_data,
- .vc_data = &omap4_vc_core_data,
- .vfsm = &omap4_vdd_core_vfsm_data,
- .voltdm = {
- .name = "core",
- },
+static struct voltagedomain omap4_voltdm_core = {
+ .name = "core",
+ .scalable = true,
+ .read = omap4_prm_vcvp_read,
+ .write = omap4_prm_vcvp_write,
+ .rmw = omap4_prm_vcvp_rmw,
+ .vc = &omap4_vc_core,
+ .vfsm = &omap4_vdd_core_vfsm,
+ .vp = &omap4_vp_core,
};
-/* OMAP4 VDD structures */
-static struct omap_vdd_info *omap4_vdd_info[] = {
- &omap4_vdd_mpu_info,
- &omap4_vdd_iva_info,
- &omap4_vdd_core_info,
+static struct voltagedomain omap4_voltdm_wkup = {
+ .name = "wakeup",
};
-/* OMAP4 specific voltage init functions */
-static int __init omap44xx_voltage_early_init(void)
-{
- s16 prm_mod = OMAP4430_PRM_DEVICE_INST;
- s16 prm_irqst_ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
+static struct voltagedomain *voltagedomains_omap4[] __initdata = {
+ &omap4_voltdm_mpu,
+ &omap4_voltdm_iva,
+ &omap4_voltdm_core,
+ &omap4_voltdm_wkup,
+ NULL,
+};
+
+static const char *sys_clk_name __initdata = "sys_clkin_ck";
- if (!cpu_is_omap44xx())
- return 0;
+void __init omap44xx_voltagedomains_init(void)
+{
+ struct voltagedomain *voltdm;
+ int i;
/*
* XXX Will depend on the process, validation, and binning
* for the currently-running IC
*/
- omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data;
- omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data;
- omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data;
+ 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;
+
+ for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++)
+ voltdm->sys_clk.name = sys_clk_name;
- return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
- omap4_vdd_info,
- ARRAY_SIZE(omap4_vdd_info));
+ voltdm_init(voltagedomains_omap4);
};
-core_initcall(omap44xx_voltage_early_init);
diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
new file mode 100644
index 000000000000..66bd700a2b98
--- /dev/null
+++ b/arch/arm/mach-omap2/vp.c
@@ -0,0 +1,278 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "voltage.h"
+#include "vp.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt)
+{
+ struct omap_vp_instance *vp = voltdm->vp;
+ u32 vpconfig;
+ char vsel;
+
+ vsel = voltdm->pmic->uv_to_vsel(volt);
+
+ vpconfig = voltdm->read(vp->vpconfig);
+ vpconfig &= ~(vp->common->vpconfig_initvoltage_mask |
+ vp->common->vpconfig_forceupdate |
+ vp->common->vpconfig_initvdd);
+ vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask);
+ voltdm->write(vpconfig, vp->vpconfig);
+
+ /* Trigger initVDD value copy to voltage processor */
+ voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
+ vp->vpconfig);
+
+ /* Clear initVDD copy trigger bit */
+ voltdm->write(vpconfig, vp->vpconfig);
+
+ return vpconfig;
+}
+
+/* Generic voltage init functions */
+void __init omap_vp_init(struct voltagedomain *voltdm)
+{
+ struct omap_vp_instance *vp = voltdm->vp;
+ u32 val, sys_clk_rate, timeout, waittime;
+ u32 vddmin, vddmax, vstepmin, vstepmax;
+
+ if (!voltdm->read || !voltdm->write) {
+ pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ vp->enabled = false;
+
+ /* Divide to avoid overflow */
+ 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;
+
+ waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) *
+ sys_clk_rate) / 1000;
+ vstepmin = voltdm->pmic->vp_vstepmin;
+ vstepmax = voltdm->pmic->vp_vstepmax;
+
+ /*
+ * VP_CONFIG: error gain is not set here, it will be updated
+ * on each scale, based on OPP.
+ */
+ val = (voltdm->pmic->vp_erroroffset <<
+ __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) |
+ vp->common->vpconfig_timeouten;
+ voltdm->write(val, vp->vpconfig);
+
+ /* VSTEPMIN */
+ val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) |
+ (vstepmin << vp->common->vstepmin_stepmin_shift);
+ voltdm->write(val, vp->vstepmin);
+
+ /* VSTEPMAX */
+ val = (vstepmax << vp->common->vstepmax_stepmax_shift) |
+ (waittime << vp->common->vstepmax_smpswaittimemax_shift);
+ voltdm->write(val, vp->vstepmax);
+
+ /* VLIMITTO */
+ val = (vddmax << vp->common->vlimitto_vddmax_shift) |
+ (vddmin << vp->common->vlimitto_vddmin_shift) |
+ (timeout << vp->common->vlimitto_timeout_shift);
+ voltdm->write(val, vp->vlimitto);
+}
+
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+ unsigned long target_volt)
+{
+ struct omap_volt_data *volt_data;
+
+ if (!voltdm->vp)
+ return -EINVAL;
+
+ /* Get volt_data corresponding to target_volt */
+ volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
+ if (IS_ERR(volt_data))
+ return -EINVAL;
+
+ /* Setting vp errorgain based on the voltage */
+ voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask,
+ volt_data->vp_errgain <<
+ __ffs(voltdm->vp->common->vpconfig_errorgain_mask),
+ voltdm->vp->vpconfig);
+
+ return 0;
+}
+
+/* VP force update method of voltage scaling */
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt)
+{
+ struct omap_vp_instance *vp = voltdm->vp;
+ u32 vpconfig;
+ u8 target_vsel, current_vsel;
+ int ret, timeout = 0;
+
+ ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+ if (ret)
+ return ret;
+
+ /*
+ * Clear all pending TransactionDone interrupt/status. Typical latency
+ * is <3us
+ */
+ while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+ vp->common->ops->clear_txdone(vp->id);
+ if (!vp->common->ops->check_txdone(vp->id))
+ break;
+ udelay(1);
+ }
+ if (timeout >= VP_TRANXDONE_TIMEOUT) {
+ pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
+ "Voltage change aborted", __func__, voltdm->name);
+ return -ETIMEDOUT;
+ }
+
+ vpconfig = _vp_set_init_voltage(voltdm, target_volt);
+
+ /* Force update of voltage */
+ voltdm->write(vpconfig | vp->common->vpconfig_forceupdate,
+ voltdm->vp->vpconfig);
+
+ /*
+ * Wait for TransactionDone. Typical latency is <200us.
+ * Depends on SMPSWAITTIMEMIN/MAX and voltage change
+ */
+ timeout = 0;
+ omap_test_timeout(vp->common->ops->check_txdone(vp->id),
+ VP_TRANXDONE_TIMEOUT, timeout);
+ if (timeout >= VP_TRANXDONE_TIMEOUT)
+ pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
+ "TRANXDONE never got set after the voltage update\n",
+ __func__, voltdm->name);
+
+ omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+
+ /*
+ * Disable TransactionDone interrupt , clear all status, clear
+ * control registers
+ */
+ timeout = 0;
+ while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+ vp->common->ops->clear_txdone(vp->id);
+ if (!vp->common->ops->check_txdone(vp->id))
+ break;
+ udelay(1);
+ }
+
+ if (timeout >= VP_TRANXDONE_TIMEOUT)
+ pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
+ "to clear the TRANXDONE status\n",
+ __func__, voltdm->name);
+
+ /* Clear force bit */
+ voltdm->write(vpconfig, vp->vpconfig);
+
+ return 0;
+}
+
+/**
+ * omap_vp_enable() - API to enable a particular VP
+ * @voltdm: pointer to the VDD whose VP is to be enabled.
+ *
+ * This API enables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_enable(struct voltagedomain *voltdm)
+{
+ struct omap_vp_instance *vp;
+ u32 vpconfig, volt;
+
+ if (!voltdm || IS_ERR(voltdm)) {
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
+ return;
+ }
+
+ vp = voltdm->vp;
+ if (!voltdm->read || !voltdm->write) {
+ pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ /* If VP is already enabled, do nothing. Return */
+ if (vp->enabled)
+ return;
+
+ volt = voltdm_get_voltage(voltdm);
+ if (!volt) {
+ pr_warning("%s: unable to find current voltage for %s\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ vpconfig = _vp_set_init_voltage(voltdm, volt);
+
+ /* Enable VP */
+ vpconfig |= vp->common->vpconfig_vpenable;
+ voltdm->write(vpconfig, vp->vpconfig);
+
+ vp->enabled = true;
+}
+
+/**
+ * omap_vp_disable() - API to disable a particular VP
+ * @voltdm: pointer to the VDD whose VP is to be disabled.
+ *
+ * This API disables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_disable(struct voltagedomain *voltdm)
+{
+ struct omap_vp_instance *vp;
+ u32 vpconfig;
+ int timeout;
+
+ if (!voltdm || IS_ERR(voltdm)) {
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
+ return;
+ }
+
+ vp = voltdm->vp;
+ if (!voltdm->read || !voltdm->write) {
+ pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+ __func__, voltdm->name);
+ return;
+ }
+
+ /* If VP is already disabled, do nothing. Return */
+ if (!vp->enabled) {
+ pr_warning("%s: Trying to disable VP for vdd_%s when"
+ "it is already disabled\n", __func__, voltdm->name);
+ return;
+ }
+
+ /* Disable VP */
+ vpconfig = voltdm->read(vp->vpconfig);
+ vpconfig &= ~vp->common->vpconfig_vpenable;
+ voltdm->write(vpconfig, vp->vpconfig);
+
+ /*
+ * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+ */
+ omap_test_timeout((voltdm->read(vp->vstatus)),
+ VP_IDLE_TIMEOUT, timeout);
+
+ if (timeout >= VP_IDLE_TIMEOUT)
+ pr_warning("%s: vdd_%s idle timedout\n",
+ __func__, voltdm->name);
+
+ vp->enabled = false;
+
+ return;
+}
diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h
index 7ce134f7de79..7c155d248aa3 100644
--- a/arch/arm/mach-omap2/vp.h
+++ b/arch/arm/mach-omap2/vp.h
@@ -19,44 +19,60 @@
#include <linux/kernel.h>
+struct voltagedomain;
+
+/*
+ * Voltage Processor (VP) identifiers
+ */
+#define OMAP3_VP_VDD_MPU_ID 0
+#define OMAP3_VP_VDD_CORE_ID 1
+#define OMAP4_VP_VDD_CORE_ID 0
+#define OMAP4_VP_VDD_IVA_ID 1
+#define OMAP4_VP_VDD_MPU_ID 2
+
/* XXX document */
#define VP_IDLE_TIMEOUT 200
#define VP_TRANXDONE_TIMEOUT 300
+/**
+ * struct omap_vp_ops - per-VP operations
+ * @check_txdone: check for VP transaction done
+ * @clear_txdone: clear VP transaction done status
+ */
+struct omap_vp_ops {
+ u32 (*check_txdone)(u8 vp_id);
+ void (*clear_txdone)(u8 vp_id);
+};
/**
- * struct omap_vp_common_data - register data common to all VDDs
+ * struct omap_vp_common - register data common to all VDDs
+ * @vpconfig_erroroffset_mask: ERROROFFSET bitmask in the PRM_VP*_CONFIG reg
* @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg
* @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg
- * @vpconfig_timeouten_mask: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_timeouten: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
* @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg
* @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg
* @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg
* @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg
* @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg
* @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg
- * @vpconfig_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
- * @vpconfig_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
- * @vpconfig_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
- * @vpconfig_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
- * @vpconfig_vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
- * @vpconfig_vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
- * @vpconfig_vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
- *
- * XXX It it not necessary to have both a mask and a shift for the same
- * bitfield - remove one
- * XXX Many of these fields are wrongly named -- e.g., vpconfig_smps* -- fix!
+ * @vstepmin_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
+ * @vstepmin_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
+ * @vstepmax_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
+ * @vstepmax_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
+ * @vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
+ * @vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
+ * @vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
+ * @vpvoltage_mask: VPVOLTAGE field mask in PRM_VP*_VOLTAGE reg
*/
-struct omap_vp_common_data {
+struct omap_vp_common {
+ u32 vpconfig_erroroffset_mask;
u32 vpconfig_errorgain_mask;
u32 vpconfig_initvoltage_mask;
- u32 vpconfig_timeouten;
- u32 vpconfig_initvdd;
- u32 vpconfig_forceupdate;
- u32 vpconfig_vpenable;
- u8 vpconfig_erroroffset_shift;
- u8 vpconfig_errorgain_shift;
- u8 vpconfig_initvoltage_shift;
+ u8 vpconfig_timeouten;
+ u8 vpconfig_initvdd;
+ u8 vpconfig_forceupdate;
+ u8 vpconfig_vpenable;
u8 vstepmin_stepmin_shift;
u8 vstepmin_smpswaittimemin_shift;
u8 vstepmax_stepmax_shift;
@@ -64,80 +80,49 @@ struct omap_vp_common_data {
u8 vlimitto_vddmin_shift;
u8 vlimitto_vddmax_shift;
u8 vlimitto_timeout_shift;
-};
+ u8 vpvoltage_mask;
-/**
- * struct omap_vp_prm_irqst_data - PRM_IRQSTATUS_MPU.VP_TRANXDONE_ST data
- * @prm_irqst_reg: reg offset for PRM_IRQSTATUS_MPU from top of PRM
- * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
- *
- * XXX prm_irqst_reg does not belong here
- * XXX Note that on OMAP3, VP_TRANXDONE interrupt may not work due to a
- * hardware bug
- * XXX This structure is probably not needed
- */
-struct omap_vp_prm_irqst_data {
- u8 prm_irqst_reg;
- u32 tranxdone_status;
+ const struct omap_vp_ops *ops;
};
/**
- * struct omap_vp_instance_data - VP register offsets (per-VDD)
- * @vp_common: pointer to struct omap_vp_common_data * for this SoC
- * @prm_irqst_data: pointer to struct omap_vp_prm_irqst_data for this VDD
+ * struct omap_vp_instance - VP register offsets (per-VDD)
+ * @common: pointer to struct omap_vp_common * for this SoC
* @vpconfig: PRM_VP*_CONFIG reg offset from PRM start
* @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start
* @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start
* @vstatus: PRM_VP*_VSTATUS reg offset from PRM start
* @voltage: PRM_VP*_VOLTAGE reg offset from PRM start
+ * @id: Unique identifier for VP instance.
+ * @enabled: flag to keep track of whether vp is enabled or not
*
* XXX vp_common is probably not needed since it is per-SoC
*/
-struct omap_vp_instance_data {
- const struct omap_vp_common_data *vp_common;
- const struct omap_vp_prm_irqst_data *prm_irqst_data;
+struct omap_vp_instance {
+ const struct omap_vp_common *common;
u8 vpconfig;
u8 vstepmin;
u8 vstepmax;
u8 vlimitto;
u8 vstatus;
u8 voltage;
+ u8 id;
+ bool enabled;
};
-/**
- * struct omap_vp_runtime_data - VP data populated at runtime by code
- * @vpconfig_erroroffset: value of ERROROFFSET bitfield in PRM_VP*_CONFIG
- * @vpconfig_errorgain: value of ERRORGAIN bitfield in PRM_VP*_CONFIG
- * @vstepmin_smpswaittimemin: value of SMPSWAITTIMEMIN bitfield in PRM_VP*_VSTEPMIN
- * @vstepmax_smpswaittimemax: value of SMPSWAITTIMEMAX bitfield in PRM_VP*_VSTEPMAX
- * @vlimitto_timeout: value of TIMEOUT bitfield in PRM_VP*_VLIMITTO
- * @vstepmin_stepmin: value of VSTEPMIN bitfield in PRM_VP*_VSTEPMIN
- * @vstepmax_stepmax: value of VSTEPMAX bitfield in PRM_VP*_VSTEPMAX
- * @vlimitto_vddmin: value of VDDMIN bitfield in PRM_VP*_VLIMITTO
- * @vlimitto_vddmax: value of VDDMAX bitfield in PRM_VP*_VLIMITTO
- *
- * XXX Is this structure really needed? Why not just program the
- * device directly? They are in PRM space, therefore in the WKUP
- * powerdomain, so register contents should not be lost in off-mode.
- * XXX Some of these fields are incorrectly named, e.g., vstep*
- */
-struct omap_vp_runtime_data {
- u32 vpconfig_erroroffset;
- u16 vpconfig_errorgain;
- u16 vstepmin_smpswaittimemin;
- u16 vstepmax_smpswaittimemax;
- u16 vlimitto_timeout;
- u8 vstepmin_stepmin;
- u8 vstepmax_stepmax;
- u8 vlimitto_vddmin;
- u8 vlimitto_vddmax;
-};
+extern struct omap_vp_instance omap3_vp_mpu;
+extern struct omap_vp_instance omap3_vp_core;
-extern struct omap_vp_instance_data omap3_vp1_data;
-extern struct omap_vp_instance_data omap3_vp2_data;
+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_instance_data omap4_vp_mpu_data;
-extern struct omap_vp_instance_data omap4_vp_iva_data;
-extern struct omap_vp_instance_data omap4_vp_core_data;
+void omap_vp_init(struct voltagedomain *voltdm);
+void omap_vp_enable(struct voltagedomain *voltdm);
+void omap_vp_disable(struct voltagedomain *voltdm);
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+ unsigned long target_volt);
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+ unsigned long target_volt);
#endif
diff --git a/arch/arm/mach-omap2/vp3xxx_data.c b/arch/arm/mach-omap2/vp3xxx_data.c
index 645217094e51..260c554b1547 100644
--- a/arch/arm/mach-omap2/vp3xxx_data.c
+++ b/arch/arm/mach-omap2/vp3xxx_data.c
@@ -25,16 +25,20 @@
#include "voltage.h"
#include "vp.h"
+#include "prm2xxx_3xxx.h"
+
+static const struct omap_vp_ops omap3_vp_ops = {
+ .check_txdone = omap3_prm_vp_check_txdone,
+ .clear_txdone = omap3_prm_vp_clear_txdone,
+};
/*
* VP data common to 34xx/36xx chips
* XXX This stuff presumably belongs in the vp3xxx.c or vp.c file.
*/
-static const struct omap_vp_common_data omap3_vp_common = {
- .vpconfig_erroroffset_shift = OMAP3430_ERROROFFSET_SHIFT,
+static const struct omap_vp_common omap3_vp_common = {
+ .vpconfig_erroroffset_mask = OMAP3430_ERROROFFSET_MASK,
.vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK,
- .vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT,
- .vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT,
.vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK,
.vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK,
.vpconfig_initvdd = OMAP3430_INITVDD_MASK,
@@ -47,36 +51,29 @@ static const struct omap_vp_common_data omap3_vp_common = {
.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT,
.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT,
.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT,
-};
+ .vpvoltage_mask = OMAP3430_VPVOLTAGE_MASK,
-static const struct omap_vp_prm_irqst_data omap3_vp1_prm_irqst_data = {
- .prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
- .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+ .ops = &omap3_vp_ops,
};
-struct omap_vp_instance_data omap3_vp1_data = {
- .vp_common = &omap3_vp_common,
+struct omap_vp_instance omap3_vp_mpu = {
+ .id = OMAP3_VP_VDD_MPU_ID,
+ .common = &omap3_vp_common,
.vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
.vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
.vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
.vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
.vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
.voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
- .prm_irqst_data = &omap3_vp1_prm_irqst_data,
-};
-
-static const struct omap_vp_prm_irqst_data omap3_vp2_prm_irqst_data = {
- .prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
- .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
};
-struct omap_vp_instance_data omap3_vp2_data = {
- .vp_common = &omap3_vp_common,
+struct omap_vp_instance omap3_vp_core = {
+ .id = OMAP3_VP_VDD_CORE_ID,
+ .common = &omap3_vp_common,
.vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
.vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
.vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
.vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
- .prm_irqst_data = &omap3_vp2_prm_irqst_data,
};
diff --git a/arch/arm/mach-omap2/vp44xx_data.c b/arch/arm/mach-omap2/vp44xx_data.c
index 65d1ad63800a..b4e77044891e 100644
--- a/arch/arm/mach-omap2/vp44xx_data.c
+++ b/arch/arm/mach-omap2/vp44xx_data.c
@@ -27,15 +27,18 @@
#include "vp.h"
+static const struct omap_vp_ops omap4_vp_ops = {
+ .check_txdone = omap4_prm_vp_check_txdone,
+ .clear_txdone = omap4_prm_vp_clear_txdone,
+};
+
/*
* VP data common to 44xx chips
* XXX This stuff presumably belongs in the vp44xx.c or vp.c file.
*/
-static const struct omap_vp_common_data omap4_vp_common = {
- .vpconfig_erroroffset_shift = OMAP4430_ERROROFFSET_SHIFT,
+static const struct omap_vp_common omap4_vp_common = {
+ .vpconfig_erroroffset_mask = OMAP4430_ERROROFFSET_MASK,
.vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK,
- .vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT,
- .vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT,
.vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK,
.vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK,
.vpconfig_initvdd = OMAP4430_INITVDD_MASK,
@@ -48,53 +51,39 @@ static const struct omap_vp_common_data omap4_vp_common = {
.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT,
.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT,
.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT,
+ .vpvoltage_mask = OMAP4430_VPVOLTAGE_MASK,
+ .ops = &omap4_vp_ops,
};
-static const struct omap_vp_prm_irqst_data omap4_vp_mpu_prm_irqst_data = {
- .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
- .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
-};
-
-struct omap_vp_instance_data omap4_vp_mpu_data = {
- .vp_common = &omap4_vp_common,
+struct omap_vp_instance omap4_vp_mpu = {
+ .id = OMAP4_VP_VDD_MPU_ID,
+ .common = &omap4_vp_common,
.vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
.vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
.vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
.vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
.vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
.voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
- .prm_irqst_data = &omap4_vp_mpu_prm_irqst_data,
};
-static const struct omap_vp_prm_irqst_data omap4_vp_iva_prm_irqst_data = {
- .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
- .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
-};
-
-struct omap_vp_instance_data omap4_vp_iva_data = {
- .vp_common = &omap4_vp_common,
+struct omap_vp_instance omap4_vp_iva = {
+ .id = OMAP4_VP_VDD_IVA_ID,
+ .common = &omap4_vp_common,
.vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
.vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
.vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
.vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
.vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
.voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
- .prm_irqst_data = &omap4_vp_iva_prm_irqst_data,
-};
-
-static const struct omap_vp_prm_irqst_data omap4_vp_core_prm_irqst_data = {
- .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
- .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
};
-struct omap_vp_instance_data omap4_vp_core_data = {
- .vp_common = &omap4_vp_common,
+struct omap_vp_instance omap4_vp_core = {
+ .id = OMAP4_VP_VDD_CORE_ID,
+ .common = &omap4_vp_common,
.vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
.vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
.vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
.vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
.vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
.voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
- .prm_irqst_data = &omap4_vp_core_prm_irqst_data,
};
-
diff --git a/arch/arm/mach-orion5x/Makefile.boot b/arch/arm/mach-orion5x/Makefile.boot
index 67039c3e0c48..760a0efe7580 100644
--- a/arch/arm/mach-orion5x/Makefile.boot
+++ b/arch/arm/mach-orion5x/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 0ab531d047fc..22ace0bf2f92 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -308,8 +308,8 @@ void __init orion5x_init(void)
* Many orion-based systems have buggy bootloader implementations.
* This is a common fixup for bogus memory tags.
*/
-void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
- char **from, struct meminfo *meminfo)
+void __init tag_fixup_mem32(struct tag *t, char **from,
+ struct meminfo *meminfo)
{
for (; t->hdr.size; t = tag_next(t))
if (t->hdr.tag == ATAG_MEM &&
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
index 3e5499dda49a..909489f4d23e 100644
--- a/arch/arm/mach-orion5x/common.h
+++ b/arch/arm/mach-orion5x/common.h
@@ -53,11 +53,9 @@ int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
-struct machine_desc;
struct meminfo;
struct tag;
-extern void __init tag_fixup_mem32(struct machine_desc *, struct tag *,
- char **, struct meminfo *);
+extern void __init tag_fixup_mem32(struct tag *, char **, struct meminfo *);
#endif
diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c
index 19cf5bf99f1b..8c8300951f46 100644
--- a/arch/arm/mach-orion5x/d2net-setup.c
+++ b/arch/arm/mach-orion5x/d2net-setup.c
@@ -336,7 +336,7 @@ static void __init d2net_init(void)
#ifdef CONFIG_MACH_D2NET
MACHINE_START(D2NET, "LaCie d2 Network")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = d2net_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
@@ -348,7 +348,7 @@ MACHINE_END
#ifdef CONFIG_MACH_BIGDISK
MACHINE_START(BIGDISK, "LaCie Big Disk Network")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = d2net_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
index a3e3e9e5e328..4b79a80d5e1f 100644
--- a/arch/arm/mach-orion5x/db88f5281-setup.c
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
@@ -9,7 +9,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -21,7 +21,6 @@
#include <linux/mv643xx_eth.h>
#include <linux/i2c.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
#include <mach/orion5x.h>
@@ -359,7 +358,7 @@ static void __init db88f5281_init(void)
MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
/* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = db88f5281_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index c105556a0ee1..343f60e9639f 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -13,7 +13,7 @@
* License, or (at your option) any later version.
*
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -30,7 +30,6 @@
#include <linux/phy.h>
#include <linux/marvell_phy.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
#include <mach/orion5x.h>
@@ -730,7 +729,7 @@ static void __init dns323_init(void)
/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
MACHINE_START(DNS323, "D-Link DNS-323")
/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = dns323_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/edmini_v2-setup.c b/arch/arm/mach-orion5x/edmini_v2-setup.c
index b67cff0d4cfe..70a4e9265f06 100644
--- a/arch/arm/mach-orion5x/edmini_v2-setup.c
+++ b/arch/arm/mach-orion5x/edmini_v2-setup.c
@@ -251,7 +251,7 @@ static void __init edmini_v2_init(void)
/* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
MACHINE_START(EDMINI_V2, "LaCie Ethernet Disk mini V2")
/* Maintainer: Christopher Moore <moore@free.fr> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = edmini_v2_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/include/mach/debug-macro.S b/arch/arm/mach-orion5x/include/mach/debug-macro.S
index 5e3bf5b68aec..f340ed8f8dd0 100644
--- a/arch/arm/mach-orion5x/include/mach/debug-macro.S
+++ b/arch/arm/mach-orion5x/include/mach/debug-macro.S
@@ -10,7 +10,7 @@
#include <mach/orion5x.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =ORION5X_REGS_PHYS_BASE
ldr \rv, =ORION5X_REGS_VIRT_BASE
orr \rp, \rp, #0x00012000
diff --git a/arch/arm/mach-orion5x/include/mach/memory.h b/arch/arm/mach-orion5x/include/mach/memory.h
deleted file mode 100644
index 6769917882fe..000000000000
--- a/arch/arm/mach-orion5x/include/mach/memory.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * arch/arm/mach-orion5x/include/mach/memory.h
- *
- * Marvell Orion memory definitions
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c
index 43cf8bc9767b..b1b45fff776e 100644
--- a/arch/arm/mach-orion5x/irq.c
+++ b/arch/arm/mach-orion5x/irq.c
@@ -9,12 +9,11 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
-#include <asm/gpio.h>
#include <mach/bridge-regs.h>
#include <plat/irq.h>
#include "common.h"
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
index 00381249d766..d3cd3f63258a 100644
--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -7,7 +7,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -21,7 +21,6 @@
#include <linux/serial_reg.h>
#include <linux/ata_platform.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
#include <mach/orion5x.h>
@@ -380,7 +379,7 @@ static void __init kurobox_pro_init(void)
#ifdef CONFIG_MACH_KUROBOX_PRO
MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = kurobox_pro_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
@@ -393,7 +392,7 @@ MACHINE_END
#ifdef CONFIG_MACH_LINKSTATION_PRO
MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = kurobox_pro_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c
index 5065803ca82a..9503fff404e3 100644
--- a/arch/arm/mach-orion5x/ls-chl-setup.c
+++ b/arch/arm/mach-orion5x/ls-chl-setup.c
@@ -318,7 +318,7 @@ static void __init lschl_init(void)
MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)")
/* Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = lschl_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c
index 8503d0a42d41..ed6d772f4a24 100644
--- a/arch/arm/mach-orion5x/ls_hgl-setup.c
+++ b/arch/arm/mach-orion5x/ls_hgl-setup.c
@@ -265,7 +265,7 @@ static void __init ls_hgl_init(void)
MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL")
/* Maintainer: Zhu Qingsen <zhuqs@cn.fujistu.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = ls_hgl_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c
index 9c82723c05c0..743f7f1db181 100644
--- a/arch/arm/mach-orion5x/lsmini-setup.c
+++ b/arch/arm/mach-orion5x/lsmini-setup.c
@@ -267,7 +267,7 @@ static void __init lsmini_init(void)
#ifdef CONFIG_MACH_LINKSTATION_MINI
MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini")
/* Maintainer: Alexey Kopytko <alexey@kopytko.ru> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = lsmini_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c
index ef3bb8e9a4c2..6020e26b1c71 100644
--- a/arch/arm/mach-orion5x/mss2-setup.c
+++ b/arch/arm/mach-orion5x/mss2-setup.c
@@ -261,7 +261,7 @@ static void __init mss2_init(void)
MACHINE_START(MSS2, "Maxtor Shared Storage II")
/* Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = mss2_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c
index 63ff10c3c464..201ae3676289 100644
--- a/arch/arm/mach-orion5x/mv2120-setup.c
+++ b/arch/arm/mach-orion5x/mv2120-setup.c
@@ -7,7 +7,7 @@
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -20,7 +20,6 @@
#include <linux/i2c.h>
#include <linux/ata_platform.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <mach/orion5x.h>
#include "common.h"
@@ -229,7 +228,7 @@ static void __init mv2120_init(void)
/* Warning: HP uses a wrong mach-type (=526) in their bootloader */
MACHINE_START(MV2120, "HP Media Vault mv2120")
/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = mv2120_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c
index e43b39cc7fe9..6197c79a2ecb 100644
--- a/arch/arm/mach-orion5x/net2big-setup.c
+++ b/arch/arm/mach-orion5x/net2big-setup.c
@@ -419,7 +419,7 @@ static void __init net2big_init(void)
/* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
MACHINE_START(NET2BIG, "LaCie 2Big Network")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = net2big_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
index 291d22bf44c9..ebd6767d8e88 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
@@ -7,7 +7,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -18,7 +18,6 @@
#include <linux/ethtool.h>
#include <net/dsa.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/leds.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
@@ -169,7 +168,7 @@ subsys_initcall(rd88f5181l_fxo_pci_init);
MACHINE_START(RD88F5181L_FXO, "Marvell Orion-VoIP FXO Reference Design")
/* Maintainer: Nicolas Pitre <nico@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = rd88f5181l_fxo_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
index 3f02362e1632..05db2d336b08 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
@@ -7,7 +7,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -19,7 +19,6 @@
#include <linux/i2c.h>
#include <net/dsa.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/leds.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
@@ -181,7 +180,7 @@ subsys_initcall(rd88f5181l_ge_pci_init);
MACHINE_START(RD88F5181L_GE, "Marvell Orion-VoIP GE Reference Design")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = rd88f5181l_ge_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
index 27fd38e658bd..e47fa0578ae3 100644
--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
@@ -9,7 +9,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -20,7 +20,6 @@
#include <linux/ata_platform.h>
#include <linux/i2c.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/leds.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
@@ -306,7 +305,7 @@ static void __init rd88f5182_init(void)
MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = rd88f5182_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
index ad2eba9286ad..64317251ec00 100644
--- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
@@ -7,7 +7,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -21,7 +21,6 @@
#include <linux/ethtool.h>
#include <net/dsa.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/leds.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
@@ -122,7 +121,7 @@ subsys_initcall(rd88f6183ap_ge_pci_init);
MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = rd88f6183ap_ge_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c
index a34e4fac72b0..29f1526f7b70 100644
--- a/arch/arm/mach-orion5x/terastation_pro2-setup.c
+++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c
@@ -8,7 +8,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -20,7 +20,6 @@
#include <linux/i2c.h>
#include <linux/serial_reg.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
#include <mach/orion5x.h>
@@ -358,7 +357,7 @@ static void __init tsp2_init(void)
MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
/* Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = tsp2_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
index c9831614e355..31e51f9b4b64 100644
--- a/arch/arm/mach-orion5x/ts209-setup.c
+++ b/arch/arm/mach-orion5x/ts209-setup.c
@@ -8,7 +8,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -23,7 +23,6 @@
#include <linux/serial_reg.h>
#include <linux/ata_platform.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
#include <mach/orion5x.h>
@@ -323,7 +322,7 @@ static void __init qnap_ts209_init(void)
MACHINE_START(TS209, "QNAP TS-109/TS-209")
/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = qnap_ts209_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c
index cc33b2222bad..0fbcc14e09d7 100644
--- a/arch/arm/mach-orion5x/ts409-setup.c
+++ b/arch/arm/mach-orion5x/ts409-setup.c
@@ -11,7 +11,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -25,7 +25,6 @@
#include <linux/i2c.h>
#include <linux/serial_reg.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
#include <mach/orion5x.h>
@@ -312,7 +311,7 @@ static void __init qnap_ts409_init(void)
MACHINE_START(TS409, "QNAP TS-409")
/* Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = qnap_ts409_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index 6b7b54116f30..6c75cd35c4c8 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -621,7 +621,7 @@ static void __init ts78xx_init(void)
MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
/* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = ts78xx_init,
.map_io = ts78xx_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c
index 2653595f901c..b8be7d8d0cf4 100644
--- a/arch/arm/mach-orion5x/wnr854t-setup.c
+++ b/arch/arm/mach-orion5x/wnr854t-setup.c
@@ -5,7 +5,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -17,7 +17,6 @@
#include <linux/ethtool.h>
#include <net/dsa.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
#include <mach/orion5x.h>
@@ -173,7 +172,7 @@ subsys_initcall(wnr854t_pci_init);
MACHINE_START(WNR854T, "Netgear WNR854T")
/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = wnr854t_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
index 251ef1543e53..faf81a039360 100644
--- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c
+++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
@@ -5,7 +5,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -20,7 +20,6 @@
#include <linux/input.h>
#include <net/dsa.h>
#include <asm/mach-types.h>
-#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
#include <mach/orion5x.h>
@@ -261,7 +260,7 @@ subsys_initcall(wrt350n_v2_pci_init);
MACHINE_START(WRT350N_V2, "Linksys WRT350N v2")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_machine = wrt350n_v2_init,
.map_io = orion5x_map_io,
.init_early = orion5x_init_early,
diff --git a/arch/arm/mach-picoxcell/Makefile b/arch/arm/mach-picoxcell/Makefile
new file mode 100644
index 000000000000..c550b6363488
--- /dev/null
+++ b/arch/arm/mach-picoxcell/Makefile
@@ -0,0 +1,3 @@
+obj-y := common.o
+obj-y += time.o
+obj-y += io.o
diff --git a/arch/arm/mach-picoxcell/Makefile.boot b/arch/arm/mach-picoxcell/Makefile.boot
new file mode 100644
index 000000000000..b3271754e9fd
--- /dev/null
+++ b/arch/arm/mach-picoxcell/Makefile.boot
@@ -0,0 +1 @@
+zreladdr-y := 0x00008000
diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c
new file mode 100644
index 000000000000..34d08347be5f
--- /dev/null
+++ b/arch/arm/mach-picoxcell/common.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/hardware/vic.h>
+
+#include <mach/map.h>
+#include <mach/picoxcell_soc.h>
+
+#include "common.h"
+
+static void __init picoxcell_init_machine(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *picoxcell_dt_match[] = {
+ "picochip,pc3x2",
+ "picochip,pc3x3",
+ NULL
+};
+
+static const struct of_device_id vic_of_match[] __initconst = {
+ { .compatible = "arm,pl192-vic" },
+ { /* Sentinel */ }
+};
+
+static void __init picoxcell_init_irq(void)
+{
+ vic_init(IO_ADDRESS(PICOXCELL_VIC0_BASE), 0, ~0, 0);
+ vic_init(IO_ADDRESS(PICOXCELL_VIC1_BASE), 32, ~0, 0);
+ irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC0_BASE, 0);
+ irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC1_BASE, 32);
+}
+
+DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
+ .map_io = picoxcell_map_io,
+ .nr_irqs = ARCH_NR_IRQS,
+ .init_irq = picoxcell_init_irq,
+ .timer = &picoxcell_timer,
+ .init_machine = picoxcell_init_machine,
+ .dt_compat = picoxcell_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-picoxcell/common.h b/arch/arm/mach-picoxcell/common.h
new file mode 100644
index 000000000000..5263f0fa095c
--- /dev/null
+++ b/arch/arm/mach-picoxcell/common.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * All enquiries to support@picochip.com
+ */
+#ifndef __PICOXCELL_COMMON_H__
+#define __PICOXCELL_COMMON_H__
+
+#include <asm/mach/time.h>
+
+extern struct sys_timer picoxcell_timer;
+extern void picoxcell_map_io(void);
+
+#endif /* __PICOXCELL_COMMON_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/debug-macro.S b/arch/arm/mach-picoxcell/include/mach/debug-macro.S
new file mode 100644
index 000000000000..8f2c234ed9d9
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/debug-macro.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
+ * accesses to the 8250.
+ */
+#include <linux/serial_reg.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#define UART_SHIFT 2
+
+ .macro addruart, rp, rv
+ ldr \rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
+ ldr \rp, =PICOXCELL_UART1_BASE
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #UART_TX << UART_SHIFT]
+ .endm
+
+ .macro busyuart,rd,rx
+1002: ldr \rd, [\rx, #UART_LSR << UART_SHIFT]
+ and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+ teq \rd, #UART_LSR_TEMT | UART_LSR_THRE
+ bne 1002b
+ .endm
+
+ /* The UART's don't have any flow control IO's wired up. */
+ .macro waituart,rd,rx
+ .endm
diff --git a/arch/arm/mach-picoxcell/include/mach/entry-macro.S b/arch/arm/mach-picoxcell/include/mach/entry-macro.S
new file mode 100644
index 000000000000..a6b09f75d9df
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/entry-macro.S
@@ -0,0 +1,19 @@
+/*
+ * entry-macro.S
+ *
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * Low-level IRQ helper macros for picoXcell platforms
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#define VA_VIC0 IO_ADDRESS(PICOXCELL_VIC0_BASE)
+#define VA_VIC1 IO_ADDRESS(PICOXCELL_VIC1_BASE)
+
+#include <asm/entry-macro-vic2.S>
diff --git a/arch/arm/mach-picoxcell/include/mach/gpio.h b/arch/arm/mach-picoxcell/include/mach/gpio.h
new file mode 100644
index 000000000000..40a8c178f10d
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/gpio.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-lpc32xx/include/mach/memory.h b/arch/arm/mach-picoxcell/include/mach/hardware.h
index a647dd624afa..70ff58192ec9 100644
--- a/arch/arm/mach-lpc32xx/include/mach/memory.h
+++ b/arch/arm/mach-picoxcell/include/mach/hardware.h
@@ -1,9 +1,7 @@
/*
- * arch/arm/mach-lpc32xx/include/mach/memory.h
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
+ * This file contains the hardware definitions of the picoXcell SoC devices.
*
* 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
@@ -15,13 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset of bank 0
- */
-#define PLAT_PHYS_OFFSET UL(0x80000000)
+#include <mach/picoxcell_soc.h>
#endif
diff --git a/arch/arm/mach-picoxcell/include/mach/io.h b/arch/arm/mach-picoxcell/include/mach/io.h
new file mode 100644
index 000000000000..7573ec7d10a3
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/io.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No ioports, but needed for driver compatibility. */
+#define __io(a) __typesafe_io(a)
+/* No PCI possible on picoxcell. */
+#define __mem_pci(a) (a)
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/arch/arm/mach-picoxcell/include/mach/irqs.h b/arch/arm/mach-picoxcell/include/mach/irqs.h
new file mode 100644
index 000000000000..4d13ed970919
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/irqs.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_IRQS 64
+#define NR_IRQS (128 + ARCH_NR_IRQS)
+
+#define IRQ_VIC0_BASE 0
+#define IRQ_VIC1_BASE 32
+
+#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-nomadik/include/mach/memory.h b/arch/arm/mach-picoxcell/include/mach/map.h
index d3325211ba6a..c06afad218bb 100644
--- a/arch/arm/mach-nomadik/include/mach/memory.h
+++ b/arch/arm/mach-picoxcell/include/mach/map.h
@@ -1,7 +1,5 @@
/*
- * mach-nomadik/include/mach/memory.h
- *
- * Copyright (C) 1999 ARM Limited
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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
@@ -12,17 +10,16 @@
* but WITHOUT 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_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
+#ifndef __PICOXCELL_MAP_H__
+#define __PICOXCELL_MAP_H__
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
+#define PHYS_TO_IO(x) (((x) & 0x00ffffff) | 0xfe000000)
+#ifdef __ASSEMBLY__
+#define IO_ADDRESS(x) PHYS_TO_IO((x))
+#else
+#define IO_ADDRESS(x) (void __iomem __force *)(PHYS_TO_IO((x)))
#endif
+
+#endif /* __PICOXCELL_MAP_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/memory.h b/arch/arm/mach-picoxcell/include/mach/memory.h
new file mode 100644
index 000000000000..40a8c178f10d
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/memory.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h b/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
new file mode 100644
index 000000000000..5566fc88ddbc
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __PICOXCELL_SOC_H__
+#define __PICOXCELL_SOC_H__
+
+#define PICOXCELL_UART1_BASE 0x80230000
+#define PICOXCELL_PERIPH_BASE 0x80000000
+#define PICOXCELL_PERIPH_LENGTH SZ_4M
+#define PICOXCELL_VIC0_BASE 0x80060000
+#define PICOXCELL_VIC1_BASE 0x80064000
+
+#endif /* __PICOXCELL_SOC_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/system.h b/arch/arm/mach-picoxcell/include/mach/system.h
new file mode 100644
index 000000000000..67c589b0c1bc
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/system.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+ /*
+ * This should do all the clock switching and wait for interrupt
+ * tricks.
+ */
+ cpu_do_idle();
+}
+
+static inline void arch_reset(int mode, const char *cmd)
+{
+ /* Watchdog reset to go here. */
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/arch/arm/mach-vexpress/include/mach/memory.h b/arch/arm/mach-picoxcell/include/mach/timex.h
index 5b7fcd439d87..6c540a69f405 100644
--- a/arch/arm/mach-vexpress/include/mach/memory.h
+++ b/arch/arm/mach-picoxcell/include/mach/timex.h
@@ -1,7 +1,5 @@
/*
- * arch/arm/mach-vexpress/include/mach/memory.h
- *
- * Copyright (C) 2003 ARM Limited
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
*
* 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
@@ -17,9 +15,11 @@
* 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_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
+#ifndef __TIMEX_H__
+#define __TIMEX_H__
+
+/* Bogus value to allow the kernel to compile. */
+#define CLOCK_TICK_RATE 1000000
-#define PLAT_PHYS_OFFSET UL(0x60000000)
+#endif /* __TIMEX_H__ */
-#endif
diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/mach-picoxcell/include/mach/uncompress.h
index 154b89b81d3e..b60b19d1d739 100644
--- a/arch/arm/include/asm/sizes.h
+++ b/arch/arm/mach-picoxcell/include/mach/uncompress.h
@@ -1,4 +1,6 @@
/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
* 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
@@ -13,9 +15,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* Size definitions
- * Copyright (C) ARM Limited 1998. All rights reserved.
- */
-#include <asm-generic/sizes.h>
-
-#define SZ_48M (SZ_32M + SZ_16M)
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-picoxcell/include/mach/vmalloc.h b/arch/arm/mach-picoxcell/include/mach/vmalloc.h
new file mode 100644
index 000000000000..0216cc4b1f0b
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/vmalloc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ */
+#define VMALLOC_END 0xfe000000UL
diff --git a/arch/arm/mach-picoxcell/io.c b/arch/arm/mach-picoxcell/io.c
new file mode 100644
index 000000000000..39e9b9e8cc37
--- /dev/null
+++ b/arch/arm/mach-picoxcell/io.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/map.h>
+#include <mach/picoxcell_soc.h>
+
+#include "common.h"
+
+void __init picoxcell_map_io(void)
+{
+ struct map_desc io_map = {
+ .virtual = PHYS_TO_IO(PICOXCELL_PERIPH_BASE),
+ .pfn = __phys_to_pfn(PICOXCELL_PERIPH_BASE),
+ .length = PICOXCELL_PERIPH_LENGTH,
+ .type = MT_DEVICE,
+ };
+
+ iotable_init(&io_map, 1);
+}
diff --git a/arch/arm/mach-picoxcell/time.c b/arch/arm/mach-picoxcell/time.c
new file mode 100644
index 000000000000..90a554ff4499
--- /dev/null
+++ b/arch/arm/mach-picoxcell/time.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/dw_apb_timer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched.h>
+
+#include <asm/mach/time.h>
+#include <asm/sched_clock.h>
+
+#include "common.h"
+
+static void timer_get_base_and_rate(struct device_node *np,
+ void __iomem **base, u32 *rate)
+{
+ *base = of_iomap(np, 0);
+
+ if (!*base)
+ panic("Unable to map regs for %s", np->name);
+
+ if (of_property_read_u32(np, "clock-freq", rate))
+ panic("No clock-freq property for %s", np->name);
+}
+
+static void picoxcell_add_clockevent(struct device_node *event_timer)
+{
+ void __iomem *iobase;
+ struct dw_apb_clock_event_device *ced;
+ u32 irq, rate;
+
+ irq = irq_of_parse_and_map(event_timer, 0);
+ if (irq == NO_IRQ)
+ panic("No IRQ for clock event timer");
+
+ timer_get_base_and_rate(event_timer, &iobase, &rate);
+
+ ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq,
+ rate);
+ if (!ced)
+ panic("Unable to initialise clockevent device");
+
+ dw_apb_clockevent_register(ced);
+}
+
+static void picoxcell_add_clocksource(struct device_node *source_timer)
+{
+ void __iomem *iobase;
+ struct dw_apb_clocksource *cs;
+ u32 rate;
+
+ timer_get_base_and_rate(source_timer, &iobase, &rate);
+
+ cs = dw_apb_clocksource_init(300, source_timer->name, iobase, rate);
+ if (!cs)
+ panic("Unable to initialise clocksource device");
+
+ dw_apb_clocksource_start(cs);
+ dw_apb_clocksource_register(cs);
+}
+
+static DEFINE_CLOCK_DATA(cd);
+static void __iomem *sched_io_base;
+
+unsigned long long notrace sched_clock(void)
+{
+ cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
+
+ return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace picoxcell_update_sched_clock(void)
+{
+ cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
+
+ update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static const struct of_device_id picoxcell_rtc_ids[] __initconst = {
+ { .compatible = "picochip,pc3x2-rtc" },
+ { /* Sentinel */ },
+};
+
+static void picoxcell_init_sched_clock(void)
+{
+ struct device_node *sched_timer;
+ u32 rate;
+
+ sched_timer = of_find_matching_node(NULL, picoxcell_rtc_ids);
+ if (!sched_timer)
+ panic("No RTC for sched clock to use");
+
+ timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
+ of_node_put(sched_timer);
+
+ init_sched_clock(&cd, picoxcell_update_sched_clock, 32, rate);
+}
+
+static const struct of_device_id picoxcell_timer_ids[] __initconst = {
+ { .compatible = "picochip,pc3x2-timer" },
+ {},
+};
+
+static void __init picoxcell_timer_init(void)
+{
+ struct device_node *event_timer, *source_timer;
+
+ event_timer = of_find_matching_node(NULL, picoxcell_timer_ids);
+ if (!event_timer)
+ panic("No timer for clockevent");
+ picoxcell_add_clockevent(event_timer);
+
+ source_timer = of_find_matching_node(event_timer, picoxcell_timer_ids);
+ if (!source_timer)
+ panic("No timer for clocksource");
+ picoxcell_add_clocksource(source_timer);
+
+ of_node_put(source_timer);
+
+ picoxcell_init_sched_clock();
+}
+
+struct sys_timer picoxcell_timer = {
+ .init = picoxcell_timer_init,
+};
diff --git a/arch/arm/mach-pnx4008/Makefile.boot b/arch/arm/mach-pnx4008/Makefile.boot
index 44c7117e20dd..9fa19baa7f2e 100644
--- a/arch/arm/mach-pnx4008/Makefile.boot
+++ b/arch/arm/mach-pnx4008/Makefile.boot
@@ -1,4 +1,4 @@
- zreladdr-y := 0x80008000
+ zreladdr-y += 0x80008000
params_phys-y := 0x80000100
initrd_phys-y := 0x80800000
diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c
index 63399755f199..cdb95e726f5c 100644
--- a/arch/arm/mach-pnx4008/core.c
+++ b/arch/arm/mach-pnx4008/core.c
@@ -264,7 +264,7 @@ extern struct sys_timer pnx4008_timer;
MACHINE_START(PNX4008, "Philips PNX4008")
/* Maintainer: MontaVista Software Inc. */
- .boot_params = 0x80000100,
+ .atag_offset = 0x100,
.map_io = pnx4008_map_io,
.init_irq = pnx4008_init_irq,
.init_machine = pnx4008_init,
diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c
index f219914f5b29..d3e71d3847b4 100644
--- a/arch/arm/mach-pnx4008/gpio.c
+++ b/arch/arm/mach-pnx4008/gpio.c
@@ -13,14 +13,13 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
-
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/platform.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pnx4008.h>
/* register definitions */
#define PIO_VA_BASE IO_ADDRESS(PNX4008_PIO_BASE)
diff --git a/arch/arm/mach-pnx4008/include/mach/debug-macro.S b/arch/arm/mach-pnx4008/include/mach/debug-macro.S
index 931afebaf064..469d60d97f5c 100644
--- a/arch/arm/mach-pnx4008/include/mach/debug-macro.S
+++ b/arch/arm/mach-pnx4008/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
*
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00090000
add \rv, \rp, #0xf4000000 @ virtual
add \rp, \rp, #0x40000000 @ physical
diff --git a/arch/arm/mach-pnx4008/include/mach/gpio.h b/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
index 9591467eb9ec..41027dd7cf74 100644
--- a/arch/arm/mach-pnx4008/include/mach/gpio.h
+++ b/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-pnx4008/include/mach/gpio.h
+ * arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
*
* PNX4008 GPIO driver - header file
*
diff --git a/arch/arm/mach-pnx4008/include/mach/memory.h b/arch/arm/mach-pnx4008/include/mach/memory.h
deleted file mode 100644
index 1275db61cee5..000000000000
--- a/arch/arm/mach-pnx4008/include/mach/memory.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/memory.h
- *
- * Copyright (c) 2005 Philips Semiconductors
- * Copyright (c) 2005 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.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x80000000)
-
-#endif
diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c
index f40961e51914..374c138ac1ac 100644
--- a/arch/arm/mach-pnx4008/serial.c
+++ b/arch/arm/mach-pnx4008/serial.c
@@ -9,7 +9,6 @@
* 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/types.h>
#include <linux/io.h>
@@ -19,8 +18,8 @@
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pnx4008.h>
#include <mach/clock.h>
#define UART_3 0
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
index 7af7fc05d565..13dd1604d951 100644
--- a/arch/arm/mach-prima2/Makefile
+++ b/arch/arm/mach-prima2/Makefile
@@ -3,5 +3,7 @@ obj-y += irq.o
obj-y += clock.o
obj-y += rstc.o
obj-y += prima2.o
+obj-y += rtciobrg.o
obj-$(CONFIG_DEBUG_LL) += lluart.o
obj-$(CONFIG_CACHE_L2X0) += l2x0.o
+obj-$(CONFIG_SUSPEND) += pm.o sleep.o
diff --git a/arch/arm/mach-prima2/Makefile.boot b/arch/arm/mach-prima2/Makefile.boot
index d023db3ae4ff..c77a4883a4ee 100644
--- a/arch/arm/mach-prima2/Makefile.boot
+++ b/arch/arm/mach-prima2/Makefile.boot
@@ -1,3 +1,3 @@
-zreladdr-y := 0x00008000
+zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-prima2/clock.c b/arch/arm/mach-prima2/clock.c
index 615a4e75ceab..aebad7e565cf 100644
--- a/arch/arm/mach-prima2/clock.c
+++ b/arch/arm/mach-prima2/clock.c
@@ -350,10 +350,10 @@ static struct clk_lookup onchip_clks[] = {
.clk = &clk_mem,
}, {
.dev_id = "sys",
- .clk = &clk_sys,
+ .clk = &clk_sys,
}, {
.dev_id = "io",
- .clk = &clk_io,
+ .clk = &clk_io,
},
};
diff --git a/arch/arm/mach-prima2/include/mach/debug-macro.S b/arch/arm/mach-prima2/include/mach/debug-macro.S
index bf75106333ff..cd97492bb075 100644
--- a/arch/arm/mach-prima2/include/mach/debug-macro.S
+++ b/arch/arm/mach-prima2/include/mach/debug-macro.S
@@ -9,7 +9,7 @@
#include <mach/hardware.h>
#include <mach/uart.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =SIRFSOC_UART1_PA_BASE @ physical
ldr \rv, =SIRFSOC_UART1_VA_BASE @ virtual
.endm
diff --git a/arch/arm/mach-prima2/include/mach/memory.h b/arch/arm/mach-prima2/include/mach/memory.h
deleted file mode 100644
index 368cd5a0601a..000000000000
--- a/arch/arm/mach-prima2/include/mach/memory.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-prima2/include/mach/memory.h
- *
- * Copyright (c) 2010 – 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-/*
- * Restrict DMA-able region to workaround silicon limitation.
- * The limitation restricts buffers available for DMA to SD/MMC
- * hardware to be below 256MB
- */
-#define ARM_DMA_ZONE_SIZE (SZ_256M)
-
-#endif
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
index 7af254d046ba..d93ceef4a50a 100644
--- a/arch/arm/mach-prima2/irq.c
+++ b/arch/arm/mach-prima2/irq.c
@@ -13,6 +13,8 @@
#include <asm/mach/irq.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/irqdomain.h>
+#include <linux/syscore_ops.h>
#define SIRFSOC_INT_RISC_MASK0 0x0018
#define SIRFSOC_INT_RISC_MASK1 0x001C
@@ -66,7 +68,48 @@ void __init sirfsoc_of_irq_init(void)
if (!sirfsoc_intc_base)
panic("unable to map intc cpu registers\n");
+ irq_domain_add_simple(np, 0);
+
of_node_put(np);
sirfsoc_irq_init();
}
+
+struct sirfsoc_irq_status {
+ u32 mask0;
+ u32 mask1;
+ u32 level0;
+ u32 level1;
+};
+
+static struct sirfsoc_irq_status sirfsoc_irq_st;
+
+static int sirfsoc_irq_suspend(void)
+{
+ sirfsoc_irq_st.mask0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+ sirfsoc_irq_st.mask1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+ sirfsoc_irq_st.level0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+ sirfsoc_irq_st.level1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+
+ return 0;
+}
+
+static void sirfsoc_irq_resume(void)
+{
+ writel_relaxed(sirfsoc_irq_st.mask0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+ writel_relaxed(sirfsoc_irq_st.mask1, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+ writel_relaxed(sirfsoc_irq_st.level0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+ writel_relaxed(sirfsoc_irq_st.level1, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+}
+
+static struct syscore_ops sirfsoc_irq_syscore_ops = {
+ .suspend = sirfsoc_irq_suspend,
+ .resume = sirfsoc_irq_resume,
+};
+
+static int __init sirfsoc_irq_pm_init(void)
+{
+ register_syscore_ops(&sirfsoc_irq_syscore_ops);
+ return 0;
+}
+device_initcall(sirfsoc_irq_pm_init);
diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c
index 9cda2057bcfb..c99837797d76 100644
--- a/arch/arm/mach-prima2/l2x0.c
+++ b/arch/arm/mach-prima2/l2x0.c
@@ -8,52 +8,24 @@
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/errno.h>
#include <linux/of.h>
-#include <linux/of_address.h>
#include <asm/hardware/cache-l2x0.h>
-#include <mach/memory.h>
-#define L2X0_ADDR_FILTERING_START 0xC00
-#define L2X0_ADDR_FILTERING_END 0xC04
-
-static struct of_device_id l2x_ids[] = {
- { .compatible = "arm,pl310-cache" },
+static struct of_device_id prima2_l2x0_ids[] = {
+ { .compatible = "sirf,prima2-pl310-cache" },
+ {},
};
-static int __init sirfsoc_of_l2x_init(void)
+static int __init sirfsoc_l2x0_init(void)
{
struct device_node *np;
- void __iomem *sirfsoc_l2x_base;
-
- np = of_find_matching_node(NULL, l2x_ids);
- if (!np)
- panic("unable to find compatible l2x node in dtb\n");
-
- sirfsoc_l2x_base = of_iomap(np, 0);
- if (!sirfsoc_l2x_base)
- panic("unable to map l2x cpu registers\n");
-
- of_node_put(np);
-
- if (!(readl_relaxed(sirfsoc_l2x_base + L2X0_CTRL) & 1)) {
- /*
- * set the physical memory windows L2 cache will cover
- */
- writel_relaxed(PLAT_PHYS_OFFSET + 1024 * 1024 * 1024,
- sirfsoc_l2x_base + L2X0_ADDR_FILTERING_END);
- writel_relaxed(PLAT_PHYS_OFFSET | 0x1,
- sirfsoc_l2x_base + L2X0_ADDR_FILTERING_START);
- writel_relaxed(0,
- sirfsoc_l2x_base + L2X0_TAG_LATENCY_CTRL);
- writel_relaxed(0,
- sirfsoc_l2x_base + L2X0_DATA_LATENCY_CTRL);
+ np = of_find_matching_node(NULL, prima2_l2x0_ids);
+ if (np) {
+ pr_info("Initializing prima2 L2 cache\n");
+ return l2x0_of_init(0x40000, 0);
}
- l2x0_init((void __iomem *)sirfsoc_l2x_base, 0x00040000,
- 0x00000000);
return 0;
}
-early_initcall(sirfsoc_of_l2x_init);
+early_initcall(sirfsoc_l2x0_init);
diff --git a/arch/arm/mach-prima2/pm.c b/arch/arm/mach-prima2/pm.c
new file mode 100644
index 000000000000..cb53160f6c5d
--- /dev/null
+++ b/arch/arm/mach-prima2/pm.c
@@ -0,0 +1,150 @@
+/*
+ * power management entry for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/rtc/sirfsoc_rtciobrg.h>
+#include <asm/suspend.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "pm.h"
+
+/*
+ * suspend asm codes will access these to make DRAM become self-refresh and
+ * system sleep
+ */
+u32 sirfsoc_pwrc_base;
+void __iomem *sirfsoc_memc_base;
+
+static void sirfsoc_set_wakeup_source(void)
+{
+ u32 pwr_trigger_en_reg;
+ pwr_trigger_en_reg = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base +
+ SIRFSOC_PWRC_TRIGGER_EN);
+#define X_ON_KEY_B (1 << 0)
+ sirfsoc_rtc_iobrg_writel(pwr_trigger_en_reg | X_ON_KEY_B,
+ sirfsoc_pwrc_base + SIRFSOC_PWRC_TRIGGER_EN);
+}
+
+static void sirfsoc_set_sleep_mode(u32 mode)
+{
+ u32 sleep_mode = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base +
+ SIRFSOC_PWRC_PDN_CTRL);
+ sleep_mode &= ~(SIRFSOC_SLEEP_MODE_MASK << 1);
+ sleep_mode |= mode << 1;
+ sirfsoc_rtc_iobrg_writel(sleep_mode, sirfsoc_pwrc_base +
+ SIRFSOC_PWRC_PDN_CTRL);
+}
+
+static int sirfsoc_pre_suspend_power_off(void)
+{
+ u32 wakeup_entry = virt_to_phys(cpu_resume);
+
+ sirfsoc_rtc_iobrg_writel(wakeup_entry, sirfsoc_pwrc_base +
+ SIRFSOC_PWRC_SCRATCH_PAD1);
+
+ sirfsoc_set_wakeup_source();
+
+ sirfsoc_set_sleep_mode(SIRFSOC_DEEP_SLEEP_MODE);
+
+ return 0;
+}
+
+static int sirfsoc_pm_enter(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ sirfsoc_pre_suspend_power_off();
+
+ outer_flush_all();
+ outer_disable();
+ /* go zzz */
+ cpu_suspend(0, sirfsoc_finish_suspend);
+ outer_resume();
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static const struct platform_suspend_ops sirfsoc_pm_ops = {
+ .enter = sirfsoc_pm_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+static int __init sirfsoc_pm_init(void)
+{
+ suspend_set_ops(&sirfsoc_pm_ops);
+ return 0;
+}
+late_initcall(sirfsoc_pm_init);
+
+static const struct of_device_id pwrc_ids[] = {
+ { .compatible = "sirf,prima2-pwrc" },
+ {}
+};
+
+static int __init sirfsoc_of_pwrc_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, pwrc_ids);
+ if (!np)
+ panic("unable to find compatible pwrc node in dtb\n");
+
+ /*
+ * pwrc behind rtciobrg is not located in memory space
+ * though the property is named reg. reg only means base
+ * offset for pwrc. then of_iomap is not suitable here.
+ */
+ if (of_property_read_u32(np, "reg", &sirfsoc_pwrc_base))
+ panic("unable to find base address of pwrc node in dtb\n");
+
+ of_node_put(np);
+
+ return 0;
+}
+postcore_initcall(sirfsoc_of_pwrc_init);
+
+static const struct of_device_id memc_ids[] = {
+ { .compatible = "sirf,prima2-memc" },
+ {}
+};
+
+static int __devinit sirfsoc_memc_probe(struct platform_device *op)
+{
+ struct device_node *np = op->dev.of_node;
+
+ sirfsoc_memc_base = of_iomap(np, 0);
+ if (!sirfsoc_memc_base)
+ panic("unable to map memc registers\n");
+
+ return 0;
+}
+
+static struct platform_driver sirfsoc_memc_driver = {
+ .probe = sirfsoc_memc_probe,
+ .driver = {
+ .name = "sirfsoc-memc",
+ .owner = THIS_MODULE,
+ .of_match_table = memc_ids,
+ },
+};
+
+static int __init sirfsoc_memc_init(void)
+{
+ return platform_driver_register(&sirfsoc_memc_driver);
+}
+postcore_initcall(sirfsoc_memc_init);
diff --git a/arch/arm/mach-prima2/pm.h b/arch/arm/mach-prima2/pm.h
new file mode 100644
index 000000000000..bae6d77e01ab
--- /dev/null
+++ b/arch/arm/mach-prima2/pm.h
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/pm.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef _MACH_PRIMA2_PM_H_
+#define _MACH_PRIMA2_PM_H_
+
+#define SIRFSOC_PWR_SLEEPFORCE 0x01
+
+#define SIRFSOC_SLEEP_MODE_MASK 0x3
+#define SIRFSOC_DEEP_SLEEP_MODE 0x1
+
+#define SIRFSOC_PWRC_PDN_CTRL 0x0
+#define SIRFSOC_PWRC_PON_OFF 0x4
+#define SIRFSOC_PWRC_TRIGGER_EN 0x8
+#define SIRFSOC_PWRC_PIN_STATUS 0x14
+#define SIRFSOC_PWRC_SCRATCH_PAD1 0x18
+#define SIRFSOC_PWRC_SCRATCH_PAD2 0x1C
+
+#ifndef __ASSEMBLY__
+extern int sirfsoc_finish_suspend(unsigned long);
+#endif
+
+#endif
+
diff --git a/arch/arm/mach-prima2/prima2.c b/arch/arm/mach-prima2/prima2.c
index f57124bdd143..ef555c041962 100644
--- a/arch/arm/mach-prima2/prima2.c
+++ b/arch/arm/mach-prima2/prima2.c
@@ -1,5 +1,5 @@
/*
- * Defines machines for CSR SiRFprimaII
+ * Defines machines for CSR SiRFprimaII
*
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
*
@@ -31,11 +31,12 @@ static const char *prima2cb_dt_match[] __initdata = {
MACHINE_START(PRIMA2_EVB, "prima2cb")
/* Maintainer: Barry Song <baohua.song@csr.com> */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.init_early = sirfsoc_of_clk_init,
.map_io = sirfsoc_map_lluart,
.init_irq = sirfsoc_of_irq_init,
.timer = &sirfsoc_timer,
+ .dma_zone_size = SZ_256M,
.init_machine = sirfsoc_mach_init,
.dt_compat = prima2cb_dt_match,
MACHINE_END
diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c
new file mode 100644
index 000000000000..9d80f1e20a98
--- /dev/null
+++ b/arch/arm/mach-prima2/rtciobrg.c
@@ -0,0 +1,139 @@
+/*
+ * RTC I/O Bridge interfaces for CSR SiRFprimaII
+ * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#define SIRFSOC_CPUIOBRG_CTRL 0x00
+#define SIRFSOC_CPUIOBRG_WRBE 0x04
+#define SIRFSOC_CPUIOBRG_ADDR 0x08
+#define SIRFSOC_CPUIOBRG_DATA 0x0c
+
+/*
+ * suspend asm codes will access this address to make system deepsleep
+ * after DRAM becomes self-refresh
+ */
+void __iomem *sirfsoc_rtciobrg_base;
+static DEFINE_SPINLOCK(rtciobrg_lock);
+
+/*
+ * symbols without lock are only used by suspend asm codes
+ * and these symbols are not exported too
+ */
+void sirfsoc_rtc_iobrg_wait_sync(void)
+{
+ while (readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL))
+ cpu_relax();
+}
+
+void sirfsoc_rtc_iobrg_besyncing(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtciobrg_lock, flags);
+
+ sirfsoc_rtc_iobrg_wait_sync();
+
+ spin_unlock_irqrestore(&rtciobrg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_besyncing);
+
+u32 __sirfsoc_rtc_iobrg_readl(u32 addr)
+{
+ sirfsoc_rtc_iobrg_wait_sync();
+
+ writel_relaxed(0x00, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
+ writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
+ writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
+
+ sirfsoc_rtc_iobrg_wait_sync();
+
+ return readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
+}
+
+u32 sirfsoc_rtc_iobrg_readl(u32 addr)
+{
+ unsigned long flags, val;
+
+ spin_lock_irqsave(&rtciobrg_lock, flags);
+
+ val = __sirfsoc_rtc_iobrg_readl(addr);
+
+ spin_unlock_irqrestore(&rtciobrg_lock, flags);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_readl);
+
+void sirfsoc_rtc_iobrg_pre_writel(u32 val, u32 addr)
+{
+ sirfsoc_rtc_iobrg_wait_sync();
+
+ writel_relaxed(0xf1, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
+ writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
+
+ writel_relaxed(val, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
+}
+
+void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtciobrg_lock, flags);
+
+ sirfsoc_rtc_iobrg_pre_writel(val, addr);
+
+ writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
+
+ sirfsoc_rtc_iobrg_wait_sync();
+
+ spin_unlock_irqrestore(&rtciobrg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel);
+
+static const struct of_device_id rtciobrg_ids[] = {
+ { .compatible = "sirf,prima2-rtciobg" },
+ {}
+};
+
+static int __devinit sirfsoc_rtciobrg_probe(struct platform_device *op)
+{
+ struct device_node *np = op->dev.of_node;
+
+ sirfsoc_rtciobrg_base = of_iomap(np, 0);
+ if (!sirfsoc_rtciobrg_base)
+ panic("unable to map rtc iobrg registers\n");
+
+ return 0;
+}
+
+static struct platform_driver sirfsoc_rtciobrg_driver = {
+ .probe = sirfsoc_rtciobrg_probe,
+ .driver = {
+ .name = "sirfsoc-rtciobrg",
+ .owner = THIS_MODULE,
+ .of_match_table = rtciobrg_ids,
+ },
+};
+
+static int __init sirfsoc_rtciobrg_init(void)
+{
+ return platform_driver_register(&sirfsoc_rtciobrg_driver);
+}
+postcore_initcall(sirfsoc_rtciobrg_init);
+
+MODULE_AUTHOR("Zhiwu Song <zhiwu.song@csr.com>, "
+ "Barry Song <baohua.song@csr.com>");
+MODULE_DESCRIPTION("CSR SiRFprimaII rtc io bridge");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-prima2/sleep.S b/arch/arm/mach-prima2/sleep.S
new file mode 100644
index 000000000000..0745abc365fc
--- /dev/null
+++ b/arch/arm/mach-prima2/sleep.S
@@ -0,0 +1,64 @@
+/*
+ * sleep mode for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/assembler.h>
+
+#include "pm.h"
+
+#define DENALI_CTL_22_OFF 0x58
+#define DENALI_CTL_112_OFF 0x1c0
+
+ .text
+
+ENTRY(sirfsoc_finish_suspend)
+ @ r5: mem controller
+ ldr r0, =sirfsoc_memc_base
+ ldr r5, [r0]
+ @ r6: pwrc base offset
+ ldr r0, =sirfsoc_pwrc_base
+ ldr r6, [r0]
+ @ r7: rtc iobrg controller
+ ldr r0, =sirfsoc_rtciobrg_base
+ ldr r7, [r0]
+
+ @ Read the power control register and set the
+ @ sleep force bit.
+ add r0, r6, #SIRFSOC_PWRC_PDN_CTRL
+ bl __sirfsoc_rtc_iobrg_readl
+ orr r0,r0,#SIRFSOC_PWR_SLEEPFORCE
+ add r1, r6, #SIRFSOC_PWRC_PDN_CTRL
+ bl sirfsoc_rtc_iobrg_pre_writel
+ mov r1, #0x1
+
+ @ read the MEM ctl register and set the self
+ @ refresh bit
+
+ ldr r2, [r5, #DENALI_CTL_22_OFF]
+ orr r2, r2, #0x1
+
+ @ Following code has to run from cache since
+ @ the RAM is going to self refresh mode
+ .align 5
+ str r2, [r5, #DENALI_CTL_22_OFF]
+
+1:
+ ldr r4, [r5, #DENALI_CTL_112_OFF]
+ tst r4, #0x1
+ bne 1b
+
+ @ write SLEEPFORCE through rtc iobridge
+
+ str r1, [r7]
+ @ wait rtc io bridge sync
+1:
+ ldr r3, [r7]
+ tst r3, #0x01
+ bne 1b
+ b .
diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c
index ed7ec48d11da..b7a6091ce791 100644
--- a/arch/arm/mach-prima2/timer.c
+++ b/arch/arm/mach-prima2/timer.c
@@ -40,6 +40,17 @@
#define SIRFSOC_TIMER_LATCH_BIT BIT(0)
+#define SIRFSOC_TIMER_REG_CNT 11
+
+static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
+ SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
+ SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
+ SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
+ SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
+};
+
+static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
+
static void __iomem *sirfsoc_timer_base;
static void __init sirfsoc_of_timer_map(void);
@@ -106,6 +117,27 @@ static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
}
}
+static void sirfsoc_clocksource_suspend(struct clocksource *cs)
+{
+ int i;
+
+ writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+
+ for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+ sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+}
+
+static void sirfsoc_clocksource_resume(struct clocksource *cs)
+{
+ int i;
+
+ for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+ writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+
+ writel_relaxed(sirfsoc_timer_reg_val[i - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
+ writel_relaxed(sirfsoc_timer_reg_val[i - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
+}
+
static struct clock_event_device sirfsoc_clockevent = {
.name = "sirfsoc_clockevent",
.rating = 200,
@@ -120,6 +152,8 @@ static struct clocksource sirfsoc_clocksource = {
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
.read = sirfsoc_timer_read,
+ .suspend = sirfsoc_clocksource_suspend,
+ .resume = sirfsoc_clocksource_resume,
};
static struct irqaction sirfsoc_timer_irq = {
@@ -133,14 +167,14 @@ static struct irqaction sirfsoc_timer_irq = {
/* Overwrite weak default sched_clock with more precise one */
unsigned long long notrace sched_clock(void)
{
- static int is_mapped = 0;
+ static int is_mapped;
/*
* sched_clock is called earlier than .init of sys_timer
* if we map timer memory in .init of sys_timer, system
* will panic due to illegal memory access
*/
- if(!is_mapped) {
+ if (!is_mapped) {
sirfsoc_of_timer_map();
is_mapped = 1;
}
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index cd19309fd3b8..61d3c72ded84 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -2,6 +2,27 @@ if ARCH_PXA
menu "Intel PXA2xx/PXA3xx Implementations"
+config ARCH_PXA_V7
+ bool "ARMv7 (PXA95x) based systems"
+
+if ARCH_PXA_V7
+comment "Marvell Dev Platforms (sorted by hardware release time)"
+config MACH_TAVOREVB3
+ bool "PXA95x Development Platform (aka TavorEVB III)"
+ select CPU_PXA955
+
+config MACH_SAARB
+ bool "PXA955 Handheld Platform (aka SAARB)"
+ select CPU_PXA955
+endif
+
+config PXA_V7_MACH_AUTO
+ def_bool y
+ depends on ARCH_PXA_V7
+ depends on !MACH_SAARB
+ select MACH_TAVOREVB3
+
+if !ARCH_PXA_V7
comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
config ARCH_LUBBOCK
@@ -41,19 +62,11 @@ config MACH_TAVOREVB
select PXA3xx
select CPU_PXA930
-config MACH_TAVOREVB3
- bool "PXA95x Development Platform (aka TavorEVB III)"
- select CPU_PXA950
-
config MACH_SAAR
bool "PXA930 Handheld Platform (aka SAAR)"
select PXA3xx
select CPU_PXA930
-config MACH_SAARB
- bool "PXA955 Handheld Platform (aka SAARB)"
- select CPU_PXA955
-
comment "Third Party Dev Platforms (sorted by vendor name)"
config ARCH_PXA_IDP
@@ -414,6 +427,7 @@ config MACH_CENTRO
bool "Palm Centro 685 (GSM)"
default y
depends on ARCH_PXA_PALM
+ select MACH_PALM27X
select PXA27x
select IWMMXT
select PALM_TREO
@@ -425,6 +439,7 @@ config MACH_TREO680
bool "Palm Treo 680"
default y
depends on ARCH_PXA_PALM
+ select MACH_PALM27X
select PXA27x
select IWMMXT
select PALM_TREO
@@ -436,15 +451,18 @@ config MACH_RAUMFELD_RC
bool "Raumfeld Controller"
select PXA3xx
select CPU_PXA300
+ select POWER_SUPPLY
select HAVE_PWM
config MACH_RAUMFELD_CONNECTOR
bool "Raumfeld Connector"
+ select POWER_SUPPLY
select PXA3xx
select CPU_PXA300
config MACH_RAUMFELD_SPEAKER
bool "Raumfeld Speaker"
+ select POWER_SUPPLY
select PXA3xx
select CPU_PXA300
@@ -598,7 +616,7 @@ config MACH_ZIPIT2
bool "Zipit Z2 Handheld"
select PXA27x
select HAVE_PWM
-
+endif
endmenu
config PXA25x
@@ -688,6 +706,8 @@ config SHARPSL_PM
config SHARPSL_PM_MAX1111
bool
select HWMON
+ select SPI
+ select SPI_MASTER
select SENSORS_MAX1111
config PXA_HAVE_ISA_IRQS
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index cc39d17b2e07..be0f7df8685c 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -19,7 +19,7 @@ endif
obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa25x.o
obj-$(CONFIG_PXA27x) += mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa27x.o
obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
-obj-$(CONFIG_PXA95x) += mfp-pxa3xx.o clock-pxa3xx.o pxa95x.o smemc.o
+obj-$(CONFIG_PXA95x) += mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o pxa95x.o smemc.o
obj-$(CONFIG_CPU_PXA300) += pxa300.o
obj-$(CONFIG_CPU_PXA320) += pxa320.o
obj-$(CONFIG_CPU_PXA930) += pxa930.o
diff --git a/arch/arm/mach-pxa/Makefile.boot b/arch/arm/mach-pxa/Makefile.boot
index 1ead67178eca..2c1ae92f2106 100644
--- a/arch/arm/mach-pxa/Makefile.boot
+++ b/arch/arm/mach-pxa/Makefile.boot
@@ -1,2 +1,2 @@
- zreladdr-y := 0xa0008000
+ zreladdr-y += 0xa0008000
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index ef3e8b1e06c1..fc0b8544e174 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -591,7 +591,7 @@ static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ct
BALLOON3_NAND_CONTROL_REG);
if (balloon3_ctl_set)
__raw_writel(balloon3_ctl_set,
- BALLOON3_NAND_CONTROL_REG |
+ BALLOON3_NAND_CONTROL_REG +
BALLOON3_FPGA_SETnCLR);
}
@@ -608,7 +608,7 @@ static void balloon3_nand_select_chip(struct mtd_info *mtd, int chip)
__raw_writew(
BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3,
- BALLOON3_NAND_CONTROL_REG | BALLOON3_FPGA_SETnCLR);
+ BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
/* Deassert correct nCE line */
__raw_writew(BALLOON3_NAND_CONTROL_FLCE0 << chip,
@@ -626,7 +626,7 @@ static int balloon3_nand_probe(struct platform_device *pdev)
int ret;
__raw_writew(BALLOON3_NAND_CONTROL2_16BIT,
- BALLOON3_NAND_CONTROL2_REG | BALLOON3_FPGA_SETnCLR);
+ BALLOON3_NAND_CONTROL2_REG + BALLOON3_FPGA_SETnCLR);
ver = __raw_readw(BALLOON3_FPGA_VER);
if (ver < 0x4f08)
@@ -649,7 +649,7 @@ static int balloon3_nand_probe(struct platform_device *pdev)
BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3 |
BALLOON3_NAND_CONTROL_FLWP,
- BALLOON3_NAND_CONTROL_REG | BALLOON3_FPGA_SETnCLR);
+ BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
return 0;
err2:
@@ -807,7 +807,7 @@ static void __init balloon3_init(void)
static struct map_desc balloon3_io_desc[] __initdata = {
{ /* CPLD/FPGA */
- .virtual = BALLOON3_FPGA_VIRT,
+ .virtual = (unsigned long)BALLOON3_FPGA_VIRT,
.pfn = __phys_to_pfn(BALLOON3_FPGA_PHYS),
.length = BALLOON3_FPGA_LENGTH,
.type = MT_DEVICE,
@@ -828,5 +828,5 @@ MACHINE_START(BALLOON3, "Balloon3")
.handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = balloon3_init,
- .boot_params = PLAT_PHYS_OFFSET + 0x100,
+ .atag_offset = 0x100,
MACHINE_END
diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c
index 648b0ab2bf77..4efc16d39c79 100644
--- a/arch/arm/mach-pxa/capc7117.c
+++ b/arch/arm/mach-pxa/capc7117.c
@@ -148,7 +148,7 @@ static void __init capc7117_init(void)
MACHINE_START(CAPC7117,
"Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
.handle_irq = pxa3xx_handle_irq,
diff --git a/arch/arm/mach-pxa/cm-x255.c b/arch/arm/mach-pxa/cm-x255.c
index 93f59f877fc6..be751470d37b 100644
--- a/arch/arm/mach-pxa/cm-x255.c
+++ b/arch/arm/mach-pxa/cm-x255.c
@@ -11,7 +11,6 @@
#include <linux/platform_device.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/nand-gpio.h>
diff --git a/arch/arm/mach-pxa/cm-x2xx-pci.c b/arch/arm/mach-pxa/cm-x2xx-pci.c
index 6bf479d9b5ac..ebd9259f5ac9 100644
--- a/arch/arm/mach-pxa/cm-x2xx-pci.c
+++ b/arch/arm/mach-pxa/cm-x2xx-pci.c
@@ -26,7 +26,7 @@
#include <asm/hardware/it8152.h>
-unsigned long it8152_base_address;
+void __iomem *it8152_base_address;
static int cmx2xx_it8152_irq_gpio;
static void cmx2xx_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index 13cf518bbbf8..f2e4190080cb 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -39,7 +39,7 @@ extern void cmx270_init(void);
#define CMX2XX_NR_IRQS (IRQ_BOARD_START + 40)
/* virtual addresses for statically mapped regions */
-#define CMX2XX_VIRT_BASE (0xe8000000)
+#define CMX2XX_VIRT_BASE (void __iomem *)(0xe8000000)
#define CMX2XX_IT8152_VIRT (CMX2XX_VIRT_BASE)
/* physical address if local-bus attached devices */
@@ -482,7 +482,7 @@ static void __init cmx2xx_init_irq(void)
/* Map PCI companion statically */
static struct map_desc cmx2xx_io_desc[] __initdata = {
[0] = { /* PCI bridge */
- .virtual = CMX2XX_IT8152_VIRT,
+ .virtual = (unsigned long)CMX2XX_IT8152_VIRT,
.pfn = __phys_to_pfn(PXA_CS4_PHYS),
.length = SZ_64M,
.type = MT_DEVICE
@@ -513,7 +513,7 @@ static void __init cmx2xx_map_io(void)
#endif
MACHINE_START(ARMCORE, "Compulab CM-X2XX")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = cmx2xx_map_io,
.nr_irqs = CMX2XX_NR_IRQS,
.init_irq = cmx2xx_init_irq,
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index b6a51340270b..3a7387f93c38 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -775,7 +775,6 @@ static struct gpio cm_x300_wi2wi_gpios[] __initdata = {
static void __init cm_x300_init_wi2wi(void)
{
- int bt_reset, wlan_en;
int err;
if (system_rev < 130) {
@@ -791,12 +790,11 @@ static void __init cm_x300_init_wi2wi(void)
}
udelay(10);
- gpio_set_value(bt_reset, 0);
+ gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 0);
udelay(10);
- gpio_set_value(bt_reset, 1);
+ gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 1);
- gpio_free(wlan_en);
- gpio_free(bt_reset);
+ gpio_free_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
}
/* MFP */
@@ -839,8 +837,8 @@ static void __init cm_x300_init(void)
cm_x300_init_bl();
}
-static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+static void __init cm_x300_fixup(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
/* Make sure that mi->bank[0].start = PHYS_ADDR */
for (; tags->hdr.size; tags = tag_next(tags))
@@ -852,7 +850,7 @@ static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
}
MACHINE_START(CM_X300, "CM-X300 module")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
.handle_irq = pxa3xx_handle_irq,
diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c
index 870920934ecf..7db66465716f 100644
--- a/arch/arm/mach-pxa/colibri-pxa270.c
+++ b/arch/arm/mach-pxa/colibri-pxa270.c
@@ -306,7 +306,7 @@ static void __init colibri_pxa270_income_init(void)
}
MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
- .boot_params = COLIBRI_SDRAM_BASE + 0x100,
+ .atag_offset = 0x100,
.init_machine = colibri_pxa270_init,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
@@ -315,7 +315,7 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
MACHINE_END
MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.init_machine = colibri_pxa270_income_init,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c
index 60a6781e7a8e..c825e8bf2db1 100644
--- a/arch/arm/mach-pxa/colibri-pxa300.c
+++ b/arch/arm/mach-pxa/colibri-pxa300.c
@@ -183,7 +183,7 @@ void __init colibri_pxa300_init(void)
}
MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
- .boot_params = COLIBRI_SDRAM_BASE + 0x100,
+ .atag_offset = 0x100,
.init_machine = colibri_pxa300_init,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c
index d2c6631915d4..692e1ffc5586 100644
--- a/arch/arm/mach-pxa/colibri-pxa320.c
+++ b/arch/arm/mach-pxa/colibri-pxa320.c
@@ -253,7 +253,7 @@ void __init colibri_pxa320_init(void)
}
MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
- .boot_params = COLIBRI_SDRAM_BASE + 0x100,
+ .atag_offset = 0x100,
.init_machine = colibri_pxa320_init,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 185a37cad254..3e9483b06053 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -705,8 +705,8 @@ static void __init corgi_init(void)
platform_add_devices(devices, ARRAY_SIZE(devices));
}
-static void __init fixup_corgi(struct machine_desc *desc,
- struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init fixup_corgi(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
sharpsl_save_param();
mi->nr_banks=1;
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index fe812eafb1f1..5e2cf39e9e4c 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -272,7 +272,7 @@ static void __init csb726_init(void)
}
MACHINE_START(CSB726, "Cogent CSB726")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
.handle_irq = pxa27x_handle_irq,
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 2e37ea52b372..94acc0b01dd6 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -1299,7 +1299,7 @@ static void __init em_x270_init(void)
}
MACHINE_START(EM_X270, "Compulab EM-X270")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
.handle_irq = pxa27x_handle_irq,
@@ -1308,7 +1308,7 @@ MACHINE_START(EM_X270, "Compulab EM-X270")
MACHINE_END
MACHINE_START(EXEDA, "Compulab eXeda")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
.handle_irq = pxa27x_handle_irq,
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index b4599ec9d619..8e697dd8accd 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -41,8 +41,7 @@
#include "clock.h"
/* Only e800 has 128MB RAM */
-void __init eseries_fixup(struct machine_desc *desc,
- struct tag *tags, char **cmdline, struct meminfo *mi)
+void __init eseries_fixup(struct tag *tags, char **cmdline, struct meminfo *mi)
{
mi->nr_banks=1;
mi->bank[0].start = 0xa0000000;
@@ -189,7 +188,7 @@ static void __init e330_init(void)
MACHINE_START(E330, "Toshiba e330")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
@@ -239,7 +238,7 @@ static void __init e350_init(void)
MACHINE_START(E350, "Toshiba e350")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
@@ -362,7 +361,7 @@ static void __init e400_init(void)
MACHINE_START(E400, "Toshiba e400")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
@@ -551,7 +550,7 @@ static void __init e740_init(void)
MACHINE_START(E740, "Toshiba e740")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
@@ -743,7 +742,7 @@ static void __init e750_init(void)
MACHINE_START(E750, "Toshiba e750")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
@@ -948,7 +947,7 @@ static void __init e800_init(void)
MACHINE_START(E800, "Toshiba e800")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa25x_map_io,
.nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/eseries.h b/arch/arm/mach-pxa/eseries.h
index 5930f5e2a123..be921965e91a 100644
--- a/arch/arm/mach-pxa/eseries.h
+++ b/arch/arm/mach-pxa/eseries.h
@@ -1,5 +1,4 @@
-void __init eseries_fixup(struct machine_desc *desc,
- struct tag *tags, char **cmdline, struct meminfo *mi);
+void __init eseries_fixup(struct tag *tags, char **cmdline, struct meminfo *mi);
extern struct pxa2xx_udc_mach_info e7xx_udc_mach_info;
extern struct pxaficp_platform_data e7xx_ficp_platform_data;
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index b73eadb9f5dc..8308eee5a924 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -797,7 +797,7 @@ static void __init a780_init(void)
}
MACHINE_START(EZX_A780, "Motorola EZX A780")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
@@ -863,7 +863,7 @@ static void __init e680_init(void)
}
MACHINE_START(EZX_E680, "Motorola EZX E680")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
@@ -929,7 +929,7 @@ static void __init a1200_init(void)
}
MACHINE_START(EZX_A1200, "Motorola EZX A1200")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
@@ -1120,7 +1120,7 @@ static void __init a910_init(void)
}
MACHINE_START(EZX_A910, "Motorola EZX A910")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
@@ -1186,7 +1186,7 @@ static void __init e6_init(void)
}
MACHINE_START(EZX_E6, "Motorola EZX E6")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
@@ -1226,7 +1226,7 @@ static void __init e2_init(void)
}
MACHINE_START(EZX_E2, "Motorola EZX E2")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index f5d91efc2965..5432ecb15def 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -16,6 +16,7 @@
* initialization stuff for PXA machines which can be overridden later if
* need be.
*/
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -26,7 +27,6 @@
#include <asm/mach-types.h>
#include <mach/reset.h>
-#include <mach/gpio.h>
#include <mach/smemc.h>
#include <mach/pxa3xx-regs.h>
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index deaa111c91f9..9c8208ca0415 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -233,7 +233,7 @@ static void __init gumstix_init(void)
}
MACHINE_START(GUMSTIX, "Gumstix")
- .boot_params = 0xa0000100, /* match u-boot bi_boot_params */
+ .atag_offset = 0x100, /* match u-boot bi_boot_params */
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
.handle_irq = pxa25x_handle_irq,
diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c
index 0a235128914d..4b5e110640b1 100644
--- a/arch/arm/mach-pxa/h5000.c
+++ b/arch/arm/mach-pxa/h5000.c
@@ -203,7 +203,7 @@ static void __init h5000_init(void)
}
MACHINE_START(H5400, "HP iPAQ H5000")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
.handle_irq = pxa25x_handle_irq,
diff --git a/arch/arm/mach-pxa/himalaya.c b/arch/arm/mach-pxa/himalaya.c
index a997d0ab2872..f2c324570844 100644
--- a/arch/arm/mach-pxa/himalaya.c
+++ b/arch/arm/mach-pxa/himalaya.c
@@ -158,7 +158,7 @@ static void __init himalaya_init(void)
MACHINE_START(HIMALAYA, "HTC Himalaya")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
.handle_irq = pxa25x_handle_irq,
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index c748a473a2ff..6f6368ece9bd 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -838,7 +838,7 @@ static void __init hx4700_init(void)
}
MACHINE_START(H4700, "HP iPAQ HX4700")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.nr_irqs = HX4700_NR_IRQS,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c
index d427429f1f34..f78d5db758da 100644
--- a/arch/arm/mach-pxa/icontrol.c
+++ b/arch/arm/mach-pxa/icontrol.c
@@ -191,7 +191,7 @@ static void __init icontrol_init(void)
}
MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
.handle_irq = pxa3xx_handle_irq,
diff --git a/arch/arm/mach-pxa/include/mach/addr-map.h b/arch/arm/mach-pxa/include/mach/addr-map.h
index f4c03659168c..bbf9df37ad4b 100644
--- a/arch/arm/mach-pxa/include/mach/addr-map.h
+++ b/arch/arm/mach-pxa/include/mach/addr-map.h
@@ -20,7 +20,7 @@
* Peripheral Bus
*/
#define PERIPH_PHYS 0x40000000
-#define PERIPH_VIRT 0xf2000000
+#define PERIPH_VIRT IOMEM(0xf2000000)
#define PERIPH_SIZE 0x02000000
/*
@@ -28,21 +28,21 @@
*/
#define PXA2XX_SMEMC_PHYS 0x48000000
#define PXA3XX_SMEMC_PHYS 0x4a000000
-#define SMEMC_VIRT 0xf6000000
+#define SMEMC_VIRT IOMEM(0xf6000000)
#define SMEMC_SIZE 0x00100000
/*
* Dynamic Memory Controller (only on PXA3xx)
*/
#define DMEMC_PHYS 0x48100000
-#define DMEMC_VIRT 0xf6100000
+#define DMEMC_VIRT IOMEM(0xf6100000)
#define DMEMC_SIZE 0x00100000
/*
* Internal Memory Controller (PXA27x and later)
*/
#define IMEMC_PHYS 0x58000000
-#define IMEMC_VIRT 0xfe000000
+#define IMEMC_VIRT IOMEM(0xfe000000)
#define IMEMC_SIZE 0x00100000
#endif /* __ASM_MACH_ADDR_MAP_H */
diff --git a/arch/arm/mach-pxa/include/mach/balloon3.h b/arch/arm/mach-pxa/include/mach/balloon3.h
index 7074e76146c9..6d7eab3d0867 100644
--- a/arch/arm/mach-pxa/include/mach/balloon3.h
+++ b/arch/arm/mach-pxa/include/mach/balloon3.h
@@ -23,7 +23,7 @@ enum balloon3_features {
};
#define BALLOON3_FPGA_PHYS PXA_CS4_PHYS
-#define BALLOON3_FPGA_VIRT (0xf1000000) /* as per balloon2 */
+#define BALLOON3_FPGA_VIRT IOMEM(0xf1000000) /* as per balloon2 */
#define BALLOON3_FPGA_LENGTH 0x01000000
#define BALLOON3_FPGA_SETnCLR (0x1000)
diff --git a/arch/arm/mach-pxa/include/mach/debug-macro.S b/arch/arm/mach-pxa/include/mach/debug-macro.S
index 7d5c75125d65..70b112e8ef68 100644
--- a/arch/arm/mach-pxa/include/mach/debug-macro.S
+++ b/arch/arm/mach-pxa/include/mach/debug-macro.S
@@ -13,7 +13,7 @@
#include "hardware.h"
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00100000
orr \rv, \rp, #io_p2v(0x40000000) @ virtual
orr \rp, \rp, #0x40000000 @ physical
diff --git a/arch/arm/mach-pxa/include/mach/gpio-pxa.h b/arch/arm/mach-pxa/include/mach/gpio-pxa.h
new file mode 100644
index 000000000000..576868f8b8c5
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/gpio-pxa.h
@@ -0,0 +1,133 @@
+/*
+ * Written by Philipp Zabel <philipp.zabel@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __MACH_PXA_GPIO_PXA_H
+#define __MACH_PXA_GPIO_PXA_H
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+
+#define GPIO_REGS_VIRT io_p2v(0x40E00000)
+
+#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x) (GPIO_REGS_VIRT + (x))
+
+/* GPIO Pin Level Registers */
+#define GPLR0 GPIO_REG(BANK_OFF(0) + 0x00)
+#define GPLR1 GPIO_REG(BANK_OFF(1) + 0x00)
+#define GPLR2 GPIO_REG(BANK_OFF(2) + 0x00)
+#define GPLR3 GPIO_REG(BANK_OFF(3) + 0x00)
+
+/* GPIO Pin Direction Registers */
+#define GPDR0 GPIO_REG(BANK_OFF(0) + 0x0c)
+#define GPDR1 GPIO_REG(BANK_OFF(1) + 0x0c)
+#define GPDR2 GPIO_REG(BANK_OFF(2) + 0x0c)
+#define GPDR3 GPIO_REG(BANK_OFF(3) + 0x0c)
+
+/* GPIO Pin Output Set Registers */
+#define GPSR0 GPIO_REG(BANK_OFF(0) + 0x18)
+#define GPSR1 GPIO_REG(BANK_OFF(1) + 0x18)
+#define GPSR2 GPIO_REG(BANK_OFF(2) + 0x18)
+#define GPSR3 GPIO_REG(BANK_OFF(3) + 0x18)
+
+/* GPIO Pin Output Clear Registers */
+#define GPCR0 GPIO_REG(BANK_OFF(0) + 0x24)
+#define GPCR1 GPIO_REG(BANK_OFF(1) + 0x24)
+#define GPCR2 GPIO_REG(BANK_OFF(2) + 0x24)
+#define GPCR3 GPIO_REG(BANK_OFF(3) + 0x24)
+
+/* GPIO Rising Edge Detect Registers */
+#define GRER0 GPIO_REG(BANK_OFF(0) + 0x30)
+#define GRER1 GPIO_REG(BANK_OFF(1) + 0x30)
+#define GRER2 GPIO_REG(BANK_OFF(2) + 0x30)
+#define GRER3 GPIO_REG(BANK_OFF(3) + 0x30)
+
+/* GPIO Falling Edge Detect Registers */
+#define GFER0 GPIO_REG(BANK_OFF(0) + 0x3c)
+#define GFER1 GPIO_REG(BANK_OFF(1) + 0x3c)
+#define GFER2 GPIO_REG(BANK_OFF(2) + 0x3c)
+#define GFER3 GPIO_REG(BANK_OFF(3) + 0x3c)
+
+/* GPIO Edge Detect Status Registers */
+#define GEDR0 GPIO_REG(BANK_OFF(0) + 0x48)
+#define GEDR1 GPIO_REG(BANK_OFF(1) + 0x48)
+#define GEDR2 GPIO_REG(BANK_OFF(2) + 0x48)
+#define GEDR3 GPIO_REG(BANK_OFF(3) + 0x48)
+
+/* GPIO Alternate Function Select Registers */
+#define GAFR0_L GPIO_REG(0x0054)
+#define GAFR0_U GPIO_REG(0x0058)
+#define GAFR1_L GPIO_REG(0x005C)
+#define GAFR1_U GPIO_REG(0x0060)
+#define GAFR2_L GPIO_REG(0x0064)
+#define GAFR2_U GPIO_REG(0x0068)
+#define GAFR3_L GPIO_REG(0x006C)
+#define GAFR3_U GPIO_REG(0x0070)
+
+/* More handy macros. The argument is a literal GPIO number. */
+
+#define GPIO_bit(x) (1 << ((x) & 0x1f))
+
+#define GPLR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
+#define GPDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
+#define GPSR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
+#define GPCR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
+#define GRER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
+#define GFER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
+#define GEDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
+#define GAFR(x) GPIO_REG(0x54 + (((x) & 0x70) >> 2))
+
+
+#define NR_BUILTIN_GPIO PXA_GPIO_IRQ_NUM
+
+#define gpio_to_bank(gpio) ((gpio) >> 5)
+
+#ifdef CONFIG_CPU_PXA26x
+/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
+ * as well as their Alternate Function value being '1' for GPIO in GAFRx.
+ */
+static inline int __gpio_is_inverted(unsigned gpio)
+{
+ return cpu_is_pxa25x() && gpio > 85;
+}
+#else
+static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
+#endif
+
+/*
+ * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
+ * function of a GPIO, and GPDRx cannot be altered once configured. It
+ * is attributed as "occupied" here (I know this terminology isn't
+ * accurate, you are welcome to propose a better one :-)
+ */
+static inline int __gpio_is_occupied(unsigned gpio)
+{
+ if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
+ int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
+ int dir = GPDR(gpio) & GPIO_bit(gpio);
+
+ if (__gpio_is_inverted(gpio))
+ return af != 1 || dir == 0;
+ else
+ return af != 0 || dir != 0;
+ } else
+ return GPDR(gpio) & GPIO_bit(gpio);
+}
+
+#include <plat/gpio-pxa.h>
+#endif /* __MACH_PXA_GPIO_PXA_H */
diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h
index c4639502efca..004cade7bb13 100644
--- a/arch/arm/mach-pxa/include/mach/gpio.h
+++ b/arch/arm/mach-pxa/include/mach/gpio.h
@@ -24,84 +24,10 @@
#ifndef __ASM_ARCH_PXA_GPIO_H
#define __ASM_ARCH_PXA_GPIO_H
-#include <mach/irqs.h>
-#include <mach/hardware.h>
#include <asm-generic/gpio.h>
+/* The defines for the driver are needed for the accelerated accessors */
+#include "gpio-pxa.h"
-#define GPIO_REGS_VIRT io_p2v(0x40E00000)
-
-#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x) (*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
-
-/* GPIO Pin Level Registers */
-#define GPLR0 GPIO_REG(BANK_OFF(0) + 0x00)
-#define GPLR1 GPIO_REG(BANK_OFF(1) + 0x00)
-#define GPLR2 GPIO_REG(BANK_OFF(2) + 0x00)
-#define GPLR3 GPIO_REG(BANK_OFF(3) + 0x00)
-
-/* GPIO Pin Direction Registers */
-#define GPDR0 GPIO_REG(BANK_OFF(0) + 0x0c)
-#define GPDR1 GPIO_REG(BANK_OFF(1) + 0x0c)
-#define GPDR2 GPIO_REG(BANK_OFF(2) + 0x0c)
-#define GPDR3 GPIO_REG(BANK_OFF(3) + 0x0c)
-
-/* GPIO Pin Output Set Registers */
-#define GPSR0 GPIO_REG(BANK_OFF(0) + 0x18)
-#define GPSR1 GPIO_REG(BANK_OFF(1) + 0x18)
-#define GPSR2 GPIO_REG(BANK_OFF(2) + 0x18)
-#define GPSR3 GPIO_REG(BANK_OFF(3) + 0x18)
-
-/* GPIO Pin Output Clear Registers */
-#define GPCR0 GPIO_REG(BANK_OFF(0) + 0x24)
-#define GPCR1 GPIO_REG(BANK_OFF(1) + 0x24)
-#define GPCR2 GPIO_REG(BANK_OFF(2) + 0x24)
-#define GPCR3 GPIO_REG(BANK_OFF(3) + 0x24)
-
-/* GPIO Rising Edge Detect Registers */
-#define GRER0 GPIO_REG(BANK_OFF(0) + 0x30)
-#define GRER1 GPIO_REG(BANK_OFF(1) + 0x30)
-#define GRER2 GPIO_REG(BANK_OFF(2) + 0x30)
-#define GRER3 GPIO_REG(BANK_OFF(3) + 0x30)
-
-/* GPIO Falling Edge Detect Registers */
-#define GFER0 GPIO_REG(BANK_OFF(0) + 0x3c)
-#define GFER1 GPIO_REG(BANK_OFF(1) + 0x3c)
-#define GFER2 GPIO_REG(BANK_OFF(2) + 0x3c)
-#define GFER3 GPIO_REG(BANK_OFF(3) + 0x3c)
-
-/* GPIO Edge Detect Status Registers */
-#define GEDR0 GPIO_REG(BANK_OFF(0) + 0x48)
-#define GEDR1 GPIO_REG(BANK_OFF(1) + 0x48)
-#define GEDR2 GPIO_REG(BANK_OFF(2) + 0x48)
-#define GEDR3 GPIO_REG(BANK_OFF(3) + 0x48)
-
-/* GPIO Alternate Function Select Registers */
-#define GAFR0_L GPIO_REG(0x0054)
-#define GAFR0_U GPIO_REG(0x0058)
-#define GAFR1_L GPIO_REG(0x005C)
-#define GAFR1_U GPIO_REG(0x0060)
-#define GAFR2_L GPIO_REG(0x0064)
-#define GAFR2_U GPIO_REG(0x0068)
-#define GAFR3_L GPIO_REG(0x006C)
-#define GAFR3_U GPIO_REG(0x0070)
-
-/* More handy macros. The argument is a literal GPIO number. */
-
-#define GPIO_bit(x) (1 << ((x) & 0x1f))
-
-#define GPLR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
-#define GPDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
-#define GPSR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
-#define GPCR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
-#define GRER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
-#define GFER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
-#define GEDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
-#define GAFR(x) GPIO_REG(0x54 + (((x) & 0x70) >> 2))
-
-
-#define NR_BUILTIN_GPIO PXA_GPIO_IRQ_NUM
-
-#define gpio_to_bank(gpio) ((gpio) >> 5)
#define gpio_to_irq(gpio) IRQ_GPIO(gpio)
static inline int irq_to_gpio(unsigned int irq)
@@ -118,37 +44,5 @@ static inline int irq_to_gpio(unsigned int irq)
return -1;
}
-#ifdef CONFIG_CPU_PXA26x
-/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
- * as well as their Alternate Function value being '1' for GPIO in GAFRx.
- */
-static inline int __gpio_is_inverted(unsigned gpio)
-{
- return cpu_is_pxa25x() && gpio > 85;
-}
-#else
-static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
-#endif
-
-/*
- * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
- * function of a GPIO, and GPDRx cannot be altered once configured. It
- * is attributed as "occupied" here (I know this terminology isn't
- * accurate, you are welcome to propose a better one :-)
- */
-static inline int __gpio_is_occupied(unsigned gpio)
-{
- if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
- int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
- int dir = GPDR(gpio) & GPIO_bit(gpio);
-
- if (__gpio_is_inverted(gpio))
- return af != 1 || dir == 0;
- else
- return af != 0 || dir != 0;
- } else
- return GPDR(gpio) & GPIO_bit(gpio);
-}
-
#include <plat/gpio.h>
#endif
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h
index de63ca3016b4..8184669dde28 100644
--- a/arch/arm/mach-pxa/include/mach/hardware.h
+++ b/arch/arm/mach-pxa/include/mach/hardware.h
@@ -36,22 +36,23 @@
* Note that not all PXA2xx chips implement all those addresses, and the
* kernel only maps the minimum needed range of this mapping.
*/
-#define io_p2v(x) (0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))
#define io_v2p(x) (0x3c000000 + ((x) & 0x01ffffff) + (((x) & 0x0e000000) << 1))
+#define io_p2v(x) IOMEM(0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))
#ifndef __ASSEMBLY__
-
-# define __REG(x) (*((volatile u32 *)io_p2v(x)))
+# define IOMEM(x) ((void __iomem *)(x))
+# define __REG(x) (*((volatile u32 __iomem *)io_p2v(x)))
/* With indexed regs we don't want to feed the index through io_p2v()
especially if it is a variable, otherwise horrible code will result. */
# define __REG2(x,y) \
- (*(volatile u32 *)((u32)&__REG(x) + (y)))
+ (*(volatile u32 __iomem*)((u32)&__REG(x) + (y)))
# define __PREG(x) (io_v2p((u32)&(x)))
#else
+# define IOMEM(x) x
# define __REG(x) io_p2v(x)
# define __PREG(x) io_v2p(x)
diff --git a/arch/arm/mach-pxa/include/mach/littleton.h b/arch/arm/mach-pxa/include/mach/littleton.h
index 2a5726c15e0e..b6238cbd8aea 100644
--- a/arch/arm/mach-pxa/include/mach/littleton.h
+++ b/arch/arm/mach-pxa/include/mach/littleton.h
@@ -1,7 +1,7 @@
#ifndef __ASM_ARCH_LITTLETON_H
#define __ASM_ARCH_LITTLETON_H
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
#define LITTLETON_ETH_PHYS 0x30000000
diff --git a/arch/arm/mach-pxa/include/mach/lpd270.h b/arch/arm/mach-pxa/include/mach/lpd270.h
index cd070092b6eb..4edc712a2de8 100644
--- a/arch/arm/mach-pxa/include/mach/lpd270.h
+++ b/arch/arm/mach-pxa/include/mach/lpd270.h
@@ -13,13 +13,13 @@
#define __ASM_ARCH_LPD270_H
#define LPD270_CPLD_PHYS PXA_CS2_PHYS
-#define LPD270_CPLD_VIRT 0xf0000000
+#define LPD270_CPLD_VIRT IOMEM(0xf0000000)
#define LPD270_CPLD_SIZE 0x00100000
#define LPD270_ETH_PHYS (PXA_CS2_PHYS + 0x01000000)
/* CPLD registers */
-#define LPD270_CPLD_REG(x) ((unsigned long)(LPD270_CPLD_VIRT + (x)))
+#define LPD270_CPLD_REG(x) (LPD270_CPLD_VIRT + (x))
#define LPD270_CONTROL LPD270_CPLD_REG(0x00)
#define LPD270_PERIPHERAL0 LPD270_CPLD_REG(0x04)
#define LPD270_PERIPHERAL1 LPD270_CPLD_REG(0x08)
diff --git a/arch/arm/mach-pxa/include/mach/memory.h b/arch/arm/mach-pxa/include/mach/memory.h
deleted file mode 100644
index d05a59727d66..000000000000
--- a/arch/arm/mach-pxa/include/mach/memory.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/mach-pxa/include/mach/memory.h
- *
- * Author: Nicolas Pitre
- * Copyright: (C) 2001 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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0xa0000000)
-
-#endif
diff --git a/arch/arm/mach-pxa/include/mach/mtd-xip.h b/arch/arm/mach-pxa/include/mach/mtd-xip.h
index 297387ec3618..990d2bf2fb45 100644
--- a/arch/arm/mach-pxa/include/mach/mtd-xip.h
+++ b/arch/arm/mach-pxa/include/mach/mtd-xip.h
@@ -16,7 +16,6 @@
#define __ARCH_PXA_MTD_XIP_H__
#include <mach/regs-ost.h>
-#include <mach/regs-intc.h>
#define xip_irqpending() (ICIP & ICMR)
diff --git a/arch/arm/mach-pxa/include/mach/palm27x.h b/arch/arm/mach-pxa/include/mach/palm27x.h
index 0a5e5eadebf5..f80bbe246afe 100644
--- a/arch/arm/mach-pxa/include/mach/palm27x.h
+++ b/arch/arm/mach-pxa/include/mach/palm27x.h
@@ -34,7 +34,7 @@ extern struct pxafb_mode_info palm_320x320_new_lcd_mode;
extern void __init palm27x_lcd_init(int power,
struct pxafb_mode_info *mode);
#else
-static inline void palm27x_lcd_init(int power, struct pxafb_mode_info *mode) {}
+#define palm27x_lcd_init(power, mode) do {} while (0)
#endif
#if defined(CONFIG_USB_GADGET_PXA27X) || \
diff --git a/arch/arm/mach-pxa/include/mach/palmtx.h b/arch/arm/mach-pxa/include/mach/palmtx.h
index 10abc4f2e8e4..7074a6ed46c6 100644
--- a/arch/arm/mach-pxa/include/mach/palmtx.h
+++ b/arch/arm/mach-pxa/include/mach/palmtx.h
@@ -71,7 +71,7 @@
/* Various addresses */
#define PALMTX_PCMCIA_PHYS 0x28000000
-#define PALMTX_PCMCIA_VIRT 0xf0000000
+#define PALMTX_PCMCIA_VIRT IOMEM(0xf0000000)
#define PALMTX_PCMCIA_SIZE 0x100000
#define PALMTX_PHYS_RAM_START 0xa0000000
@@ -84,8 +84,8 @@
#define PALMTX_NAND_ALE_PHYS (PALMTX_PHYS_NAND_START | (1 << 24))
#define PALMTX_NAND_CLE_PHYS (PALMTX_PHYS_NAND_START | (1 << 25))
-#define PALMTX_NAND_ALE_VIRT 0xff100000
-#define PALMTX_NAND_CLE_VIRT 0xff200000
+#define PALMTX_NAND_ALE_VIRT IOMEM(0xff100000)
+#define PALMTX_NAND_CLE_VIRT IOMEM(0xff200000)
/* TOUCHSCREEN */
#define AC97_LINK_FRAME 21
diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index b9b1bdc4bacc..7cff640582b8 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -1,6 +1,7 @@
#ifndef __MACH_PXA27x_H
#define __MACH_PXA27x_H
+#include <linux/suspend.h>
#include <mach/hardware.h>
#include <mach/pxa2xx-regs.h>
#include <mach/mfp-pxa27x.h>
@@ -21,6 +22,7 @@
extern void __init pxa27x_map_io(void);
extern void __init pxa27x_init_irq(void);
extern int __init pxa27x_set_pwrmode(unsigned int mode);
+extern void pxa27x_cpu_pm_enter(suspend_state_t state);
#define pxa27x_handle_irq ichp_handle_irq
diff --git a/arch/arm/mach-pxa/include/mach/pxa95x.h b/arch/arm/mach-pxa/include/mach/pxa95x.h
new file mode 100644
index 000000000000..cbb097c4cb1f
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa95x.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_PXA95X_H
+#define __MACH_PXA95X_H
+
+#include <mach/pxa3xx.h>
+#include <mach/mfp-pxa930.h>
+
+#endif /* __MACH_PXA95X_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxafb.h b/arch/arm/mach-pxa/include/mach/pxafb.h
index 01a45ac48114..486b4c519ae2 100644
--- a/arch/arm/mach-pxa/include/mach/pxafb.h
+++ b/arch/arm/mach-pxa/include/mach/pxafb.h
@@ -158,5 +158,18 @@ struct pxafb_mach_info {
void pxa_set_fb_info(struct device *, struct pxafb_mach_info *);
unsigned long pxafb_get_hsync_time(struct device *dev);
+#ifdef CONFIG_FB_PXA_SMARTPANEL
extern int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int);
extern int pxafb_smart_flush(struct fb_info *info);
+#else
+static inline int pxafb_smart_queue(struct fb_info *info,
+ uint16_t *cmds, int n)
+{
+ return 0;
+}
+
+static inline int pxafb_smart_flush(struct fb_info *info)
+{
+ return 0;
+}
+#endif
diff --git a/arch/arm/mach-pxa/include/mach/smemc.h b/arch/arm/mach-pxa/include/mach/smemc.h
index 654adc90c9a0..b7de471b273a 100644
--- a/arch/arm/mach-pxa/include/mach/smemc.h
+++ b/arch/arm/mach-pxa/include/mach/smemc.h
@@ -13,7 +13,7 @@
#define PXA2XX_SMEMC_BASE 0x48000000
#define PXA3XX_SMEMC_BASE 0x4a000000
-#define SMEMC_VIRT 0xf6000000
+#define SMEMC_VIRT IOMEM(0xf6000000)
#define MDCNFG (SMEMC_VIRT + 0x00) /* SDRAM Configuration Register 0 */
#define MDREFR (SMEMC_VIRT + 0x04) /* SDRAM Refresh Control Register */
diff --git a/arch/arm/mach-pxa/include/mach/zeus.h b/arch/arm/mach-pxa/include/mach/zeus.h
index 0641f31a56b7..56024f81d57e 100644
--- a/arch/arm/mach-pxa/include/mach/zeus.h
+++ b/arch/arm/mach-pxa/include/mach/zeus.h
@@ -68,7 +68,7 @@
* Be gentle, and remap that over 32kB...
*/
-#define ZEUS_CPLD (0xf0000000)
+#define ZEUS_CPLD IOMEM(0xf0000000)
#define ZEUS_CPLD_VERSION (ZEUS_CPLD + 0x0000)
#define ZEUS_CPLD_ISA_IRQ (ZEUS_CPLD + 0x1000)
#define ZEUS_CPLD_CONTROL (ZEUS_CPLD + 0x2000)
@@ -76,7 +76,7 @@
/* CPLD register bits */
#define ZEUS_CPLD_CONTROL_CF_RST 0x01
-#define ZEUS_PC104IO (0xf1000000)
+#define ZEUS_PC104IO IOMEM(0xf1000000)
#define ZEUS_SRAM_SIZE (256 * 1024)
diff --git a/arch/arm/mach-pxa/include/mach/zylonite.h b/arch/arm/mach-pxa/include/mach/zylonite.h
index ea24998b923c..ecca976f03d2 100644
--- a/arch/arm/mach-pxa/include/mach/zylonite.h
+++ b/arch/arm/mach-pxa/include/mach/zylonite.h
@@ -19,7 +19,7 @@ extern int wm9713_irq;
extern int lcd_id;
extern int lcd_orientation;
-#ifdef CONFIG_CPU_PXA300
+#ifdef CONFIG_MACH_ZYLONITE300
extern void zylonite_pxa300_init(void);
#else
static inline void zylonite_pxa300_init(void)
@@ -29,7 +29,7 @@ static inline void zylonite_pxa300_init(void)
}
#endif
-#ifdef CONFIG_CPU_PXA320
+#ifdef CONFIG_MACH_ZYLONITE320
extern void zylonite_pxa320_init(void);
#else
static inline void zylonite_pxa320_init(void)
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index b09e848eb6c6..532c5d3a97d2 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -11,7 +11,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
@@ -19,13 +18,15 @@
#include <linux/io.h>
#include <linux/irq.h>
+#include <asm/exception.h>
+
#include <mach/hardware.h>
#include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
#include "generic.h"
-#define IRQ_BASE (void __iomem *)io_p2v(0x40d00000)
+#define IRQ_BASE io_p2v(0x40d00000)
#define ICIP (0x000)
#define ICMR (0x004)
@@ -63,7 +64,7 @@ static inline void __iomem *irq_base(int i)
0x40d00130,
};
- return (void __iomem *)io_p2v(phys_base[i]);
+ return io_p2v(phys_base[i]);
}
void pxa_mask_irq(struct irq_data *d)
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 8f97e15e86e5..0037e57e0cec 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -437,7 +437,7 @@ static void __init littleton_init(void)
}
MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa3xx_map_io,
.nr_irqs = LITTLETON_NR_IRQS,
.init_irq = pxa3xx_init_irq,
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index c171d6ebee49..1dd530279e0b 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -12,7 +12,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/syscore_ops.h>
@@ -39,7 +39,6 @@
#include <asm/mach/flash.h>
#include <mach/pxa27x.h>
-#include <mach/gpio.h>
#include <mach/lpd270.h>
#include <mach/audio.h>
#include <mach/pxafb.h>
@@ -480,7 +479,7 @@ static void __init lpd270_init(void)
static struct map_desc lpd270_io_desc[] __initdata = {
{
- .virtual = LPD270_CPLD_VIRT,
+ .virtual = (unsigned long)LPD270_CPLD_VIRT,
.pfn = __phys_to_pfn(LPD270_CPLD_PHYS),
.length = LPD270_CPLD_SIZE,
.type = MT_DEVICE,
@@ -499,7 +498,7 @@ static void __init lpd270_map_io(void)
MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
/* Maintainer: Peter Barada */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = lpd270_map_io,
.nr_irqs = LPD270_NR_IRQS,
.init_irq = lpd270_init_irq,
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index a8c696bfc132..c48ce6da9184 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -11,6 +11,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -42,7 +43,6 @@
#include <asm/hardware/sa1111.h>
#include <mach/pxa25x.h>
-#include <mach/gpio.h>
#include <mach/audio.h>
#include <mach/lubbock.h>
#include <mach/udc.h>
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 5fe5bcd7c0a1..4b796c37af3e 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -753,7 +753,7 @@ static void __init magician_init(void)
MACHINE_START(MAGICIAN, "HTC Magician")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.nr_irqs = MAGICIAN_NR_IRQS,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 4622eb78ef25..0567d3965fda 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -12,7 +12,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/syscore_ops.h>
@@ -43,7 +43,6 @@
#include <asm/mach/flash.h>
#include <mach/pxa27x.h>
-#include <mach/gpio.h>
#include <mach/mainstone.h>
#include <mach/audio.h>
#include <mach/pxafb.h>
@@ -616,7 +615,7 @@ static void __init mainstone_map_io(void)
MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
/* Maintainer: MontaVista Software Inc. */
- .boot_params = 0xa0000100, /* BLOB boot parameter setting */
+ .atag_offset = 0x100, /* BLOB boot parameter setting */
.map_io = mainstone_map_io,
.nr_irqs = MAINSTONE_NR_IRQS,
.init_irq = mainstone_init_irq,
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
index b27544bcafcb..43a5f6861ca3 100644
--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
@@ -12,15 +12,15 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/syscore_ops.h>
-#include <mach/gpio.h>
#include <mach/pxa2xx-regs.h>
#include <mach/mfp-pxa2xx.h>
+#include <mach/gpio-pxa.h>
#include "generic.h"
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 64810f908e5b..b938fc2c316a 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -751,7 +751,7 @@ static void mioa701_machine_exit(void)
}
MACHINE_START(MIOA701, "MIO A701")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = &pxa27x_map_io,
.init_irq = &pxa27x_init_irq,
.handle_irq = &pxa27x_handle_irq,
diff --git a/arch/arm/mach-pxa/mp900.c b/arch/arm/mach-pxa/mp900.c
index fb408861dbcf..4af5d513c380 100644
--- a/arch/arm/mach-pxa/mp900.c
+++ b/arch/arm/mach-pxa/mp900.c
@@ -92,7 +92,7 @@ static void __init mp900c_init(void)
/* Maintainer - Michael Petchkovsky <mkpetch@internode.on.net> */
MACHINE_START(NEC_MP900, "MobilePro900/C")
- .boot_params = 0xa0220100,
+ .atag_offset = 0x220100,
.timer = &pxa_timer,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index 6b77365ed938..3d4a2819cae1 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -342,7 +342,7 @@ static void __init palmld_init(void)
}
MACHINE_START(PALMLD, "Palm LifeDrive")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = palmld_map_io,
.init_irq = pxa27x_init_irq,
.handle_irq = pxa27x_handle_irq,
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index 9bd3e47486fb..99d6bcf1f974 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -202,7 +202,7 @@ static void __init palmt5_init(void)
}
MACHINE_START(PALMT5, "Palm Tungsten|T5")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.reserve = palmt5_reserve,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index 6ad4a6c7bc96..6ec7caefb37c 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -537,7 +537,7 @@ static void __init palmtc_init(void)
};
MACHINE_START(PALMTC, "Palm Tungsten|C")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
.handle_irq = pxa25x_handle_irq,
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index 664232f3e62c..9376da06404c 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -356,7 +356,7 @@ static void __init palmte2_init(void)
}
MACHINE_START(PALMTE2, "Palm Tungsten|E2")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
.handle_irq = pxa25x_handle_irq,
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index bb27d4b688d8..94e9708b349d 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -423,6 +423,7 @@ static void __init palmphone_common_init(void)
palmtreo_leds_init();
}
+#ifdef CONFIG_MACH_TREO680
static void __init treo680_init(void)
{
pxa2xx_mfp_config(ARRAY_AND_SIZE(treo680_pin_config));
@@ -430,7 +431,9 @@ static void __init treo680_init(void)
palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, GPIO_NR_TREO680_SD_READONLY,
GPIO_NR_TREO680_SD_POWER, 0);
}
+#endif
+#ifdef CONFIG_MACH_CENTRO
static void __init centro_init(void)
{
pxa2xx_mfp_config(ARRAY_AND_SIZE(centro685_pin_config));
@@ -438,9 +441,11 @@ static void __init centro_init(void)
palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, -1,
GPIO_NR_CENTRO_SD_POWER, 1);
}
+#endif
+#ifdef CONFIG_MACH_TREO680
MACHINE_START(TREO680, "Palm Treo 680")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.reserve = treo_reserve,
.init_irq = pxa27x_init_irq,
@@ -448,9 +453,11 @@ MACHINE_START(TREO680, "Palm Treo 680")
.timer = &pxa_timer,
.init_machine = treo680_init,
MACHINE_END
+#endif
+#ifdef CONFIG_MACH_CENTRO
MACHINE_START(CENTRO, "Palm Centro 685")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.reserve = treo_reserve,
.init_irq = pxa27x_init_irq,
@@ -458,3 +465,4 @@ MACHINE_START(CENTRO, "Palm Centro 685")
.timer = &pxa_timer,
.init_machine = centro_init,
MACHINE_END
+#endif
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index fc4285589c1f..4e3e45927e95 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -247,7 +247,7 @@ static void palmtx_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
- unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
+ char __iomem *nandaddr = this->IO_ADDR_W;
if (cmd == NAND_CMD_NONE)
return;
@@ -315,17 +315,17 @@ static inline void palmtx_nand_init(void) {}
******************************************************************************/
static struct map_desc palmtx_io_desc[] __initdata = {
{
- .virtual = PALMTX_PCMCIA_VIRT,
+ .virtual = (unsigned long)PALMTX_PCMCIA_VIRT,
.pfn = __phys_to_pfn(PALMTX_PCMCIA_PHYS),
.length = PALMTX_PCMCIA_SIZE,
.type = MT_DEVICE,
}, {
- .virtual = PALMTX_NAND_ALE_VIRT,
+ .virtual = (unsigned long)PALMTX_NAND_ALE_VIRT,
.pfn = __phys_to_pfn(PALMTX_NAND_ALE_PHYS),
.length = SZ_1M,
.type = MT_DEVICE,
}, {
- .virtual = PALMTX_NAND_CLE_VIRT,
+ .virtual = (unsigned long)PALMTX_NAND_CLE_VIRT,
.pfn = __phys_to_pfn(PALMTX_NAND_CLE_PHYS),
.length = SZ_1M,
.type = MT_DEVICE,
@@ -364,7 +364,7 @@ static void __init palmtx_init(void)
}
MACHINE_START(PALMTX, "Palm T|X")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = palmtx_map_io,
.init_irq = pxa27x_init_irq,
.handle_irq = pxa27x_handle_irq,
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index e61c1cc05519..68e18baf8e07 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -399,7 +399,7 @@ static void __init palmz72_init(void)
}
MACHINE_START(PALMZ72, "Palm Zire72")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
.handle_irq = pxa27x_handle_irq,
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index ffa65dfb8c6f..0b825a353537 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -258,7 +258,7 @@ static void __init pcm027_map_io(void)
MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
/* Maintainer: Pengutronix */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pcm027_map_io,
.nr_irqs = PCM027_NR_IRQS,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 6d5b7e062124..9a9c539f6c01 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -19,7 +19,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
@@ -28,7 +28,6 @@
#include <media/soc_camera.h>
-#include <asm/gpio.h>
#include <mach/camera.h>
#include <asm/mach/map.h>
#include <mach/pxa27x.h>
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index a113ea9ab4ab..948ce3e729fa 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -454,8 +454,8 @@ static void __init poodle_init(void)
poodle_init_spi();
}
-static void __init fixup_poodle(struct machine_desc *desc,
- struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init fixup_poodle(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
sharpsl_save_param();
mi->nr_banks=1;
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 9c434d21a271..f05f9486b0cb 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -16,6 +16,7 @@
* initialization stuff for PXA machines which can be overridden later if
* need be.
*/
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -23,12 +24,12 @@
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
#include <linux/irq.h>
+#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <asm/suspend.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
-#include <mach/gpio.h>
#include <mach/pxa25x.h>
#include <mach/reset.h>
#include <mach/pm.h>
@@ -324,7 +325,7 @@ void __init pxa26x_init_irq(void)
static struct map_desc pxa25x_io_desc[] __initdata = {
{ /* Mem Ctl */
- .virtual = SMEMC_VIRT,
+ .virtual = (unsigned long)SMEMC_VIRT,
.pfn = __phys_to_pfn(PXA2XX_SMEMC_BASE),
.length = 0x00200000,
.type = MT_DEVICE
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 9d2400b5f503..bc5a98ebaa72 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -11,6 +11,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -20,13 +21,13 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/i2c/pxa-i2c.h>
+#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/suspend.h>
#include <mach/irqs.h>
-#include <mach/gpio.h>
#include <mach/pxa27x.h>
#include <mach/reset.h>
#include <mach/ohci.h>
@@ -390,7 +391,7 @@ void __init pxa27x_init_irq(void)
static struct map_desc pxa27x_io_desc[] __initdata = {
{ /* Mem Ctl */
- .virtual = SMEMC_VIRT,
+ .virtual = (unsigned long)SMEMC_VIRT,
.pfn = __phys_to_pfn(PXA2XX_SMEMC_BASE),
.length = 0x00200000,
.type = MT_DEVICE
diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
index ce7168b233e2..e28dfb88827f 100644
--- a/arch/arm/mach-pxa/pxa3xx-ulpi.c
+++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c
@@ -265,6 +265,7 @@ int pxa3xx_u2d_start_hc(struct usb_bus *host)
return err;
}
+EXPORT_SYMBOL_GPL(pxa3xx_u2d_start_hc);
void pxa3xx_u2d_stop_hc(struct usb_bus *host)
{
@@ -277,6 +278,7 @@ void pxa3xx_u2d_stop_hc(struct usb_bus *host)
clk_disable(u2d->clk);
}
+EXPORT_SYMBOL_GPL(pxa3xx_u2d_stop_hc);
static int pxa3xx_u2d_probe(struct platform_device *pdev)
{
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index b5cd9e5aba31..0737c59b88ae 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -12,7 +12,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -26,7 +25,7 @@
#include <asm/mach/map.h>
#include <asm/suspend.h>
#include <mach/hardware.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
#include <mach/pxa3xx-regs.h>
#include <mach/reset.h>
#include <mach/ohci.h>
@@ -394,7 +393,7 @@ void __init pxa3xx_init_irq(void)
static struct map_desc pxa3xx_io_desc[] __initdata = {
{ /* Mem Ctl */
- .virtual = SMEMC_VIRT,
+ .virtual = (unsigned long)SMEMC_VIRT,
.pfn = __phys_to_pfn(PXA3XX_SMEMC_BASE),
.length = 0x00200000,
.type = MT_DEVICE
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index 0ee166b61f81..51371b39d2a3 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -9,7 +9,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -21,7 +20,7 @@
#include <linux/syscore_ops.h>
#include <mach/hardware.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
#include <mach/pxa3xx-regs.h>
#include <mach/pxa930.h>
#include <mach/reset.h>
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index bbcd90562ebe..6810cddec927 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -1086,7 +1086,7 @@ static void __init raumfeld_speaker_init(void)
#ifdef CONFIG_MACH_RAUMFELD_RC
MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
- .boot_params = RAUMFELD_SDRAM_BASE + 0x100,
+ .atag_offset = 0x100,
.init_machine = raumfeld_controller_init,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
@@ -1097,7 +1097,7 @@ MACHINE_END
#ifdef CONFIG_MACH_RAUMFELD_CONNECTOR
MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
- .boot_params = RAUMFELD_SDRAM_BASE + 0x100,
+ .atag_offset = 0x100,
.init_machine = raumfeld_connector_init,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
@@ -1108,7 +1108,7 @@ MACHINE_END
#ifdef CONFIG_MACH_RAUMFELD_SPEAKER
MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
- .boot_params = RAUMFELD_SDRAM_BASE + 0x100,
+ .atag_offset = 0x100,
.init_machine = raumfeld_speaker_init,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index df4356e8acae..fc2c1e05af9c 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -540,7 +540,7 @@ static struct mtd_partition saar_onenand_partitions[] = {
}, {
.name = "filesystem",
.offset = MTDPART_OFS_APPEND,
- .size = SZ_48M,
+ .size = SZ_32M + SZ_16M,
.mask_flags = 0,
}
};
@@ -596,7 +596,7 @@ static void __init saar_init(void)
MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
/* Maintainer: Eric Miao <eric.miao@marvell.com> */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
.handle_irq = pxa3xx_handle_irq,
diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c
index ebd6379c4969..3e999e308a2d 100644
--- a/arch/arm/mach-pxa/saarb.c
+++ b/arch/arm/mach-pxa/saarb.c
@@ -9,12 +9,13 @@
* it under the terms of the GNU General Public License version 2 as
* publishhed by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/mfd/88pm860x.h>
+#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -23,7 +24,7 @@
#include <mach/hardware.h>
#include <mach/mfp.h>
#include <mach/mfp-pxa930.h>
-#include <mach/gpio.h>
+#include <mach/pxa95x.h>
#include "generic.h"
@@ -103,7 +104,7 @@ static void __init saarb_init(void)
}
MACHINE_START(SAARB, "PXA955 Handheld Platform (aka SAARB)")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa3xx_map_io,
.nr_irqs = SAARB_NR_IRQS,
.init_irq = pxa95x_init_irq,
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 438c7b5e451f..d8dec9113aad 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -970,8 +970,8 @@ static void __init spitz_init(void)
spitz_i2c_init();
}
-static void __init spitz_fixup(struct machine_desc *desc,
- struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init spitz_fixup(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
sharpsl_save_param();
mi->nr_banks = 1;
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index 3f8d0af9e2f7..4c9a48bef569 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -1004,7 +1004,7 @@ MACHINE_START(INTELMOTE2, "IMOTE 2")
.handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = imote2_init,
- .boot_params = 0xA0000100,
+ .atag_offset = 0x100,
MACHINE_END
#endif
@@ -1016,6 +1016,6 @@ MACHINE_START(STARGATE2, "Stargate 2")
.handle_irq = pxa27x_handle_irq,
.timer = &pxa_timer,
.init_machine = stargate2_init,
- .boot_params = 0xA0000100,
+ .atag_offset = 0x100,
MACHINE_END
#endif
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
index 32fb58e01b10..ad47bb98f30d 100644
--- a/arch/arm/mach-pxa/tavorevb.c
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -489,7 +489,7 @@ static void __init tavorevb_init(void)
MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
/* Maintainer: Eric Miao <eric.miao@marvell.com> */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa3xx_map_io,
.init_irq = pxa3xx_init_irq,
.handle_irq = pxa3xx_handle_irq,
diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c
index fd5a8eae0a87..fd569167302a 100644
--- a/arch/arm/mach-pxa/tavorevb3.c
+++ b/arch/arm/mach-pxa/tavorevb3.c
@@ -125,7 +125,7 @@ static void __init evb3_init(void)
}
MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa3xx_map_io,
.nr_irqs = TAVOREVB3_NR_IRQS,
.init_irq = pxa3xx_init_irq,
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 9f69a2682693..402b0c96613b 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -960,8 +960,8 @@ static void __init tosa_init(void)
platform_add_devices(devices, ARRAY_SIZE(devices));
}
-static void __init fixup_tosa(struct machine_desc *desc,
- struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init fixup_tosa(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
sharpsl_save_param();
mi->nr_banks=1;
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index c0417508f39d..35bbf13724b9 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -554,7 +554,7 @@ static void __init trizeps4_map_io(void)
MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
/* MAINTAINER("Jürgen Schindele") */
- .boot_params = TRIZEPS4_SDRAM_BASE + 0x100,
+ .atag_offset = 0x100,
.init_machine = trizeps4_init,
.map_io = trizeps4_map_io,
.init_irq = pxa27x_init_irq,
@@ -564,7 +564,7 @@ MACHINE_END
MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
/* MAINTAINER("Jürgen Schindele") */
- .boot_params = TRIZEPS4_SDRAM_BASE + 0x100,
+ .atag_offset = 0x100,
.init_machine = trizeps4_init,
.map_io = trizeps4_map_io,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index d4a3dc74e84a..242ddae332d3 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -992,7 +992,7 @@ static void __init viper_map_io(void)
MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
/* Maintainer: Marc Zyngier <maz@misterjones.org> */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = viper_map_io,
.init_irq = viper_init_irq,
.handle_irq = pxa25x_handle_irq,
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index 5f8490ab07cb..a7539a6ed1ff 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -716,7 +716,7 @@ static void __init vpac270_init(void)
}
MACHINE_START(VPAC270, "Voipac PXA270")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
.handle_irq = pxa27x_handle_irq,
diff --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c
index acc600f5e72f..70e1730ef282 100644
--- a/arch/arm/mach-pxa/xcep.c
+++ b/arch/arm/mach-pxa/xcep.c
@@ -142,8 +142,7 @@ static struct platform_device *devices[] __initdata = {
/* We have to state that there are HWMON devices on the I2C bus on XCEP.
* Drivers for HWMON verify capabilities of the adapter when loading and
- * refuse to attach if the adapter doesn't support HWMON class of devices.
- * See also Documentation/i2c/porting-clients. */
+ * refuse to attach if the adapter doesn't support HWMON class of devices. */
static struct i2c_pxa_platform_data xcep_i2c_platform_data = {
.class = I2C_CLASS_HWMON
};
@@ -180,7 +179,7 @@ static void __init xcep_init(void)
}
MACHINE_START(XCEP, "Iskratel XCEP")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.init_machine = xcep_init,
.map_io = pxa25x_map_io,
.init_irq = pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index 6c9275a20c91..ead32c90fec1 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -686,7 +686,8 @@ static void z2_power_off(void)
*/
PSPR = 0x0;
local_irq_disable();
- pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+ pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP);
+ pxa27x_cpu_pm_enter(PM_SUSPEND_MEM);
}
#else
#define z2_power_off NULL
@@ -718,7 +719,7 @@ static void __init z2_init(void)
}
MACHINE_START(ZIPIT2, "Zipit Z2")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa27x_map_io,
.init_irq = pxa27x_init_irq,
.handle_irq = pxa27x_handle_irq,
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index 99c49bcd9f70..498b83b089f3 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -860,25 +860,25 @@ static void __init zeus_init(void)
static struct map_desc zeus_io_desc[] __initdata = {
{
- .virtual = ZEUS_CPLD_VERSION,
+ .virtual = (unsigned long)ZEUS_CPLD_VERSION,
.pfn = __phys_to_pfn(ZEUS_CPLD_VERSION_PHYS),
.length = 0x1000,
.type = MT_DEVICE,
},
{
- .virtual = ZEUS_CPLD_ISA_IRQ,
+ .virtual = (unsigned long)ZEUS_CPLD_ISA_IRQ,
.pfn = __phys_to_pfn(ZEUS_CPLD_ISA_IRQ_PHYS),
.length = 0x1000,
.type = MT_DEVICE,
},
{
- .virtual = ZEUS_CPLD_CONTROL,
+ .virtual = (unsigned long)ZEUS_CPLD_CONTROL,
.pfn = __phys_to_pfn(ZEUS_CPLD_CONTROL_PHYS),
.length = 0x1000,
.type = MT_DEVICE,
},
{
- .virtual = ZEUS_PC104IO,
+ .virtual = (unsigned long)ZEUS_PC104IO,
.pfn = __phys_to_pfn(ZEUS_PC104IO_PHYS),
.length = 0x00800000,
.type = MT_DEVICE,
@@ -904,7 +904,7 @@ static void __init zeus_map_io(void)
MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
/* Maintainer: Marc Zyngier <maz@misterjones.org> */
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = zeus_map_io,
.nr_irqs = ZEUS_NR_IRQS,
.init_irq = zeus_init_irq,
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 15ec66b3471a..31d496891891 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -422,7 +422,7 @@ static void __init zylonite_init(void)
}
MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
- .boot_params = 0xa0000100,
+ .atag_offset = 0x100,
.map_io = pxa3xx_map_io,
.nr_irqs = ZYLONITE_NR_IRQS,
.init_irq = pxa3xx_init_irq,
diff --git a/arch/arm/mach-realview/Makefile.boot b/arch/arm/mach-realview/Makefile.boot
index d97e003d3df4..d2c3d788f688 100644
--- a/arch/arm/mach-realview/Makefile.boot
+++ b/arch/arm/mach-realview/Makefile.boot
@@ -1,9 +1,9 @@
ifeq ($(CONFIG_REALVIEW_HIGH_PHYS_OFFSET),y)
- zreladdr-y := 0x70008000
+ zreladdr-y += 0x70008000
params_phys-y := 0x70000100
initrd_phys-y := 0x70800000
else
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
endif
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 5c23450d2d1d..d5ed5d4f77d6 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -517,8 +517,7 @@ void __init realview_timer_init(unsigned int timer_irq)
/*
* Setup the memory banks.
*/
-void realview_fixup(struct machine_desc *mdesc, struct tag *tags, char **from,
- struct meminfo *meminfo)
+void realview_fixup(struct tag *tags, char **from, struct meminfo *meminfo)
{
/*
* Most RealView platforms have 512MB contiguous RAM at 0x70000000.
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 5c83d1e87a03..47259c89a75e 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -63,8 +63,8 @@ extern int realview_flash_register(struct resource *res, u32 num);
extern int realview_eth_register(const char *name, struct resource *res);
extern int realview_usb_register(struct resource *res);
extern void realview_init_early(void);
-extern void realview_fixup(struct machine_desc *mdesc, struct tag *tags,
- char **from, struct meminfo *meminfo);
+extern void realview_fixup(struct tag *tags, char **from,
+ struct meminfo *meminfo);
extern void (*realview_reset)(char);
#endif
diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c
index a87523d095e6..ac1aed2a8da4 100644
--- a/arch/arm/mach-realview/hotplug.c
+++ b/arch/arm/mach-realview/hotplug.c
@@ -69,7 +69,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
:
: "memory", "cc");
- if (pen_release == cpu) {
+ if (pen_release == cpu_logical_map(cpu)) {
/*
* OK, proper wakeup, we're done
*/
diff --git a/arch/arm/mach-realview/include/mach/board-pb1176.h b/arch/arm/mach-realview/include/mach/board-pb1176.h
index 002ab5d8c11c..2a15fef94730 100644
--- a/arch/arm/mach-realview/include/mach/board-pb1176.h
+++ b/arch/arm/mach-realview/include/mach/board-pb1176.h
@@ -70,6 +70,7 @@
#define REALVIEW_DC1176_GIC_CPU_BASE 0x10120000 /* GIC CPU interface, on devchip */
#define REALVIEW_DC1176_GIC_DIST_BASE 0x10121000 /* GIC distributor, on devchip */
+#define REALVIEW_DC1176_ROM_BASE 0x10200000 /* 16KiB NRAM preudo-ROM, on devchip */
#define REALVIEW_PB1176_GIC_CPU_BASE 0x10040000 /* GIC CPU interface, on FPGA */
#define REALVIEW_PB1176_GIC_DIST_BASE 0x10041000 /* GIC distributor, on FPGA */
#define REALVIEW_PB1176_L220_BASE 0x10110000 /* L220 registers */
diff --git a/arch/arm/mach-realview/include/mach/debug-macro.S b/arch/arm/mach-realview/include/mach/debug-macro.S
index 90b687cbe04e..8cc372dc66a8 100644
--- a/arch/arm/mach-realview/include/mach/debug-macro.S
+++ b/arch/arm/mach-realview/include/mach/debug-macro.S
@@ -10,30 +10,17 @@
* published by the Free Software Foundation.
*/
-#if defined(CONFIG_MACH_REALVIEW_EB) || \
- defined(CONFIG_MACH_REALVIEW_PB11MP) || \
- defined(CONFIG_MACH_REALVIEW_PBA8) || \
- defined(CONFIG_MACH_REALVIEW_PBX)
-#ifndef DEBUG_LL_UART_OFFSET
+#ifdef CONFIG_DEBUG_REALVIEW_STD_PORT
#define DEBUG_LL_UART_OFFSET 0x00009000
-#elif DEBUG_LL_UART_OFFSET != 0x00009000
-#warning "DEBUG_LL_UART_OFFSET already defined to a different value"
-#endif
-#endif
-
-#ifdef CONFIG_MACH_REALVIEW_PB1176
-#ifndef DEBUG_LL_UART_OFFSET
+#elif defined(CONFIG_DEBUG_REALVIEW_PB1176_PORT)
#define DEBUG_LL_UART_OFFSET 0x0010c000
-#elif DEBUG_LL_UART_OFFSET != 0x0010c000
-#warning "DEBUG_LL_UART_OFFSET already defined to a different value"
-#endif
#endif
#ifndef DEBUG_LL_UART_OFFSET
#error "Unknown RealView platform"
#endif
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #DEBUG_LL_UART_OFFSET
orr \rv, \rp, #0xfb000000 @ virtual base
orr \rp, \rp, #0x10000000 @ physical base
diff --git a/arch/arm/mach-realview/include/mach/gpio.h b/arch/arm/mach-realview/include/mach/gpio.h
index 94ff27678a46..40a8c178f10d 100644
--- a/arch/arm/mach-realview/include/mach/gpio.h
+++ b/arch/arm/mach-realview/include/mach/gpio.h
@@ -1,6 +1 @@
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
+/* empty */
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 4ae943bafa92..e83c654a58d0 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -52,12 +52,10 @@ void __init smp_init_cpus(void)
ncores = scu_base ? scu_get_core_count(scu_base) : 1;
/* sanity check */
- if (ncores > NR_CPUS) {
- printk(KERN_WARNING
- "Realview: no. of cores (%d) greater than configured "
- "maximum of %d - clipping\n",
- ncores, NR_CPUS);
- ncores = NR_CPUS;
+ if (ncores > nr_cpu_ids) {
+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+ ncores, nr_cpu_ids);
+ ncores = nr_cpu_ids;
}
for (i = 0; i < ncores; i++)
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 7a4e3b18cb3e..026c66ad7ec2 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -463,7 +463,7 @@ static void __init realview_eb_init(void)
MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .boot_params = PLAT_PHYS_OFFSET + 0x00000100,
+ .atag_offset = 0x100,
.fixup = realview_fixup,
.map_io = realview_eb_map_io,
.init_early = realview_init_early,
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index ad5671acb66a..c057540ec776 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -26,6 +26,8 @@
#include <linux/amba/pl061.h>
#include <linux/amba/mmci.h>
#include <linux/amba/pl022.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/partitions.h>
#include <linux/io.h>
#include <mach/hardware.h>
@@ -204,22 +206,48 @@ static struct amba_device *amba_devs[] __initdata = {
* RealView PB1176 platform devices
*/
static struct resource realview_pb1176_flash_resources[] = {
- [0] = {
+ {
.start = REALVIEW_PB1176_FLASH_BASE,
.end = REALVIEW_PB1176_FLASH_BASE + REALVIEW_PB1176_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
},
- [1] = {
+#ifdef CONFIG_REALVIEW_PB1176_SECURE_FLASH
+ {
.start = REALVIEW_PB1176_SEC_FLASH_BASE,
.end = REALVIEW_PB1176_SEC_FLASH_BASE + REALVIEW_PB1176_SEC_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
},
-};
-#ifdef CONFIG_REALVIEW_PB1176_SECURE_FLASH
-#define PB1176_FLASH_BLOCKS 2
-#else
-#define PB1176_FLASH_BLOCKS 1
#endif
+};
+
+static struct physmap_flash_data pb1176_rom_pdata = {
+ .probe_type = "map_rom",
+ .width = 4,
+ .nr_parts = 0,
+};
+
+static struct resource pb1176_rom_resources[] = {
+ /*
+ * This exposes the PB1176 DevChip ROM as an MTD ROM mapping.
+ * The reference manual states that this is actually a pseudo-ROM
+ * programmed in NVRAM.
+ */
+ {
+ .start = REALVIEW_DC1176_ROM_BASE,
+ .end = REALVIEW_DC1176_ROM_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device pb1176_rom_device = {
+ .name = "physmap-flash",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(pb1176_rom_resources),
+ .resource = pb1176_rom_resources,
+ .dev = {
+ .platform_data = &pb1176_rom_pdata,
+ },
+};
static struct resource realview_pb1176_smsc911x_resources[] = {
[0] = {
@@ -316,8 +344,7 @@ static void realview_pb1176_reset(char mode)
__raw_writel(REALVIEW_PB1176_SYS_SOFT_RESET, reset_ctrl);
}
-static void realview_pb1176_fixup(struct machine_desc *mdesc,
- struct tag *tags, char **from,
+static void realview_pb1176_fixup(struct tag *tags, char **from,
struct meminfo *meminfo)
{
/*
@@ -338,7 +365,8 @@ static void __init realview_pb1176_init(void)
#endif
realview_flash_register(realview_pb1176_flash_resources,
- PB1176_FLASH_BLOCKS);
+ ARRAY_SIZE(realview_pb1176_flash_resources));
+ platform_device_register(&pb1176_rom_device);
realview_eth_register(NULL, realview_pb1176_smsc911x_resources);
platform_device_register(&realview_i2c_device);
realview_usb_register(realview_pb1176_isp1761_resources);
@@ -358,7 +386,7 @@ static void __init realview_pb1176_init(void)
MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .boot_params = PLAT_PHYS_OFFSET + 0x00000100,
+ .atag_offset = 0x100,
.fixup = realview_pb1176_fixup,
.map_io = realview_pb1176_map_io,
.init_early = realview_init_early,
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index b43644b3685e..671ad6d6ff00 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -360,7 +360,7 @@ static void __init realview_pb11mp_init(void)
MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .boot_params = PLAT_PHYS_OFFSET + 0x00000100,
+ .atag_offset = 0x100,
.fixup = realview_fixup,
.map_io = realview_pb11mp_map_io,
.init_early = realview_init_early,
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 763e8f38c15d..cbf22df4ad5b 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -310,7 +310,7 @@ static void __init realview_pba8_init(void)
MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .boot_params = PLAT_PHYS_OFFSET + 0x00000100,
+ .atag_offset = 0x100,
.fixup = realview_fixup,
.map_io = realview_pba8_map_io,
.init_early = realview_init_early,
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 363b0ab56150..63c4114afae9 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -319,8 +319,8 @@ static struct sys_timer realview_pbx_timer = {
.init = realview_pbx_timer_init,
};
-static void realview_pbx_fixup(struct machine_desc *mdesc, struct tag *tags,
- char **from, struct meminfo *meminfo)
+static void realview_pbx_fixup(struct tag *tags, char **from,
+ struct meminfo *meminfo)
{
#ifdef CONFIG_SPARSEMEM
/*
@@ -335,7 +335,7 @@ static void realview_pbx_fixup(struct machine_desc *mdesc, struct tag *tags,
meminfo->bank[2].size = SZ_256M;
meminfo->nr_banks = 3;
#else
- realview_fixup(mdesc, tags, from, meminfo);
+ realview_fixup(tags, from, meminfo);
#endif
}
@@ -393,7 +393,7 @@ static void __init realview_pbx_init(void)
MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .boot_params = PLAT_PHYS_OFFSET + 0x00000100,
+ .atag_offset = 0x100,
.fixup = realview_pbx_fixup,
.map_io = realview_pbx_map_io,
.init_early = realview_init_early,
diff --git a/arch/arm/mach-rpc/Makefile.boot b/arch/arm/mach-rpc/Makefile.boot
index 9c9e7685ec7c..ae2df0d7d037 100644
--- a/arch/arm/mach-rpc/Makefile.boot
+++ b/arch/arm/mach-rpc/Makefile.boot
@@ -1,4 +1,4 @@
- zreladdr-y := 0x10008000
+ zreladdr-y += 0x10008000
params_phys-y := 0x10000100
initrd_phys-y := 0x18000000
diff --git a/arch/arm/mach-rpc/include/mach/debug-macro.S b/arch/arm/mach-rpc/include/mach/debug-macro.S
index 85effffdc2b2..6d28cc99b124 100644
--- a/arch/arm/mach-rpc/include/mach/debug-macro.S
+++ b/arch/arm/mach-rpc/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
*
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00010000
orr \rp, \rp, #0x00000fe0
orr \rv, \rp, #0xe0000000 @ virtual
diff --git a/arch/arm/mach-rpc/include/mach/hardware.h b/arch/arm/mach-rpc/include/mach/hardware.h
index dde6b3c0e299..050d63c74cc1 100644
--- a/arch/arm/mach-rpc/include/mach/hardware.h
+++ b/arch/arm/mach-rpc/include/mach/hardware.h
@@ -36,7 +36,7 @@
#define EASI_SIZE 0x08000000 /* EASI I/O */
#define EASI_START 0x08000000
-#define EASI_BASE 0xe5000000
+#define EASI_BASE IOMEM(0xe5000000)
#define IO_START 0x03000000 /* I/O */
#define IO_SIZE 0x01000000
@@ -51,21 +51,20 @@
/*
* IO Addresses
*/
-#define VIDC_BASE IOMEM(0xe0400000)
-#define EXPMASK_BASE 0xe0360000
-#define IOMD_BASE IOMEM(0xe0200000)
-#define IOC_BASE IOMEM(0xe0200000)
-#define PCIO_BASE IOMEM(0xe0010000)
-#define FLOPPYDMA_BASE IOMEM(0xe002a000)
+#define ECARD_EASI_BASE (EASI_BASE)
+#define VIDC_BASE (IO_BASE + 0x00400000)
+#define EXPMASK_BASE (IO_BASE + 0x00360000)
+#define ECARD_IOC4_BASE (IO_BASE + 0x00270000)
+#define ECARD_IOC_BASE (IO_BASE + 0x00240000)
+#define IOMD_BASE (IO_BASE + 0x00200000)
+#define IOC_BASE (IO_BASE + 0x00200000)
+#define ECARD_MEMC8_BASE (IO_BASE + 0x0002b000)
+#define FLOPPYDMA_BASE (IO_BASE + 0x0002a000)
+#define PCIO_BASE (IO_BASE + 0x00010000)
+#define ECARD_MEMC_BASE (IO_BASE + 0x00000000)
#define vidc_writel(val) __raw_writel(val, VIDC_BASE)
-#define IO_EC_EASI_BASE 0x81400000
-#define IO_EC_IOC4_BASE 0x8009c000
-#define IO_EC_IOC_BASE 0x80090000
-#define IO_EC_MEMC8_BASE 0x8000ac00
-#define IO_EC_MEMC_BASE 0x80000000
-
#define NETSLOT_BASE 0x0302b000
#define NETSLOT_SIZE 0x00001000
diff --git a/arch/arm/mach-rpc/include/mach/io.h b/arch/arm/mach-rpc/include/mach/io.h
index 20da7f486e51..695f4ed2e11b 100644
--- a/arch/arm/mach-rpc/include/mach/io.h
+++ b/arch/arm/mach-rpc/include/mach/io.h
@@ -15,195 +15,18 @@
#include <mach/hardware.h>
-#define IO_SPACE_LIMIT 0xffffffff
+#define IO_SPACE_LIMIT 0xffff
/*
- * We use two different types of addressing - PC style addresses, and ARM
- * addresses. PC style accesses the PC hardware with the normal PC IO
- * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+
- * and are translated to the start of IO. Note that all addresses are
- * shifted left!
- */
-#define __PORT_PCIO(x) (!((x) & 0x80000000))
-
-/*
- * Dynamic IO functions.
- */
-static inline void __outb (unsigned int value, unsigned int port)
-{
- unsigned long temp;
- __asm__ __volatile__(
- "tst %2, #0x80000000\n\t"
- "mov %0, %4\n\t"
- "addeq %0, %0, %3\n\t"
- "strb %1, [%0, %2, lsl #2] @ outb"
- : "=&r" (temp)
- : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
- : "cc");
-}
-
-static inline void __outw (unsigned int value, unsigned int port)
-{
- unsigned long temp;
- __asm__ __volatile__(
- "tst %2, #0x80000000\n\t"
- "mov %0, %4\n\t"
- "addeq %0, %0, %3\n\t"
- "str %1, [%0, %2, lsl #2] @ outw"
- : "=&r" (temp)
- : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
- : "cc");
-}
-
-static inline void __outl (unsigned int value, unsigned int port)
-{
- unsigned long temp;
- __asm__ __volatile__(
- "tst %2, #0x80000000\n\t"
- "mov %0, %4\n\t"
- "addeq %0, %0, %3\n\t"
- "str %1, [%0, %2, lsl #2] @ outl"
- : "=&r" (temp)
- : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
- : "cc");
-}
-
-#define DECLARE_DYN_IN(sz,fnsuffix,instr) \
-static inline unsigned sz __in##fnsuffix (unsigned int port) \
-{ \
- unsigned long temp, value; \
- __asm__ __volatile__( \
- "tst %2, #0x80000000\n\t" \
- "mov %0, %4\n\t" \
- "addeq %0, %0, %3\n\t" \
- "ldr" instr " %1, [%0, %2, lsl #2] @ in" #fnsuffix \
- : "=&r" (temp), "=r" (value) \
- : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \
- : "cc"); \
- return (unsigned sz)value; \
-}
-
-static inline void __iomem *__deprecated __ioaddr(unsigned int port)
-{
- void __iomem *ret;
- if (__PORT_PCIO(port))
- ret = PCIO_BASE;
- else
- ret = IO_BASE;
- return ret + (port << 2);
-}
-
-#define DECLARE_IO(sz,fnsuffix,instr) \
- DECLARE_DYN_IN(sz,fnsuffix,instr)
-
-DECLARE_IO(char,b,"b")
-DECLARE_IO(short,w,"")
-DECLARE_IO(int,l,"")
-
-#undef DECLARE_IO
-#undef DECLARE_DYN_IN
-
-/*
- * Constant address IO functions
+ * We need PC style IO addressing for:
+ * - floppy (at 0x3f2,0x3f4,0x3f5,0x3f7)
+ * - parport (at 0x278-0x27a, 0x27b-0x27f, 0x778-0x77a)
+ * - 8250 serial (only for compile)
*
- * These have to be macros for the 'J' constraint to work -
- * +/-4096 immediate operand.
+ * These peripherals are found in an area of MMIO which looks very much
+ * like an ISA bus, but with registers at the low byte of each word.
*/
-#define __outbc(value,port) \
-({ \
- if (__PORT_PCIO((port))) \
- __asm__ __volatile__( \
- "strb %0, [%1, %2] @ outbc" \
- : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
- else \
- __asm__ __volatile__( \
- "strb %0, [%1, %2] @ outbc" \
- : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \
-})
-
-#define __inbc(port) \
-({ \
- unsigned char result; \
- if (__PORT_PCIO((port))) \
- __asm__ __volatile__( \
- "ldrb %0, [%1, %2] @ inbc" \
- : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
- else \
- __asm__ __volatile__( \
- "ldrb %0, [%1, %2] @ inbc" \
- : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
- result; \
-})
-
-#define __outwc(value,port) \
-({ \
- unsigned long __v = value; \
- if (__PORT_PCIO((port))) \
- __asm__ __volatile__( \
- "str %0, [%1, %2] @ outwc" \
- : : "r" (__v|__v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
- else \
- __asm__ __volatile__( \
- "str %0, [%1, %2] @ outwc" \
- : : "r" (__v|__v<<16), "r" (IO_BASE), "r" ((port) << 2)); \
-})
-
-#define __inwc(port) \
-({ \
- unsigned short result; \
- if (__PORT_PCIO((port))) \
- __asm__ __volatile__( \
- "ldr %0, [%1, %2] @ inwc" \
- : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
- else \
- __asm__ __volatile__( \
- "ldr %0, [%1, %2] @ inwc" \
- : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
- result & 0xffff; \
-})
-
-#define __outlc(value,port) \
-({ \
- unsigned long __v = value; \
- if (__PORT_PCIO((port))) \
- __asm__ __volatile__( \
- "str %0, [%1, %2] @ outlc" \
- : : "r" (__v), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
- else \
- __asm__ __volatile__( \
- "str %0, [%1, %2] @ outlc" \
- : : "r" (__v), "r" (IO_BASE), "r" ((port) << 2)); \
-})
-
-#define __inlc(port) \
-({ \
- unsigned long result; \
- if (__PORT_PCIO((port))) \
- __asm__ __volatile__( \
- "ldr %0, [%1, %2] @ inlc" \
- : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
- else \
- __asm__ __volatile__( \
- "ldr %0, [%1, %2] @ inlc" \
- : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
- result; \
-})
-
-#define inb(p) (__builtin_constant_p((p)) ? __inbc(p) : __inb(p))
-#define inw(p) (__builtin_constant_p((p)) ? __inwc(p) : __inw(p))
-#define inl(p) (__builtin_constant_p((p)) ? __inlc(p) : __inl(p))
-#define outb(v,p) (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
-#define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
-#define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
-
-/* the following macro is deprecated */
-#define ioaddr(port) ((unsigned long)__ioaddr((port)))
-
-#define insb(p,d,l) __raw_readsb(__ioaddr(p),d,l)
-#define insw(p,d,l) __raw_readsw(__ioaddr(p),d,l)
-
-#define outsb(p,d,l) __raw_writesb(__ioaddr(p),d,l)
-#define outsw(p,d,l) __raw_writesw(__ioaddr(p),d,l)
+#define __io(a) (PCIO_BASE + ((a) << 2))
/*
* 1:1 mapping for ioremapped regions.
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index 580b3c73d2c7..8559598ab767 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -74,7 +74,7 @@ static struct map_desc rpc_io_desc[] __initdata = {
.length = IO_SIZE ,
.type = MT_DEVICE
}, { /* EASI space */
- .virtual = EASI_BASE,
+ .virtual = (unsigned long)EASI_BASE,
.pfn = __phys_to_pfn(EASI_START),
.length = EASI_SIZE,
.type = MT_DEVICE
@@ -218,7 +218,7 @@ extern struct sys_timer ioc_timer;
MACHINE_START(RISCPC, "Acorn-RiscPC")
/* Maintainer: Russell King */
- .boot_params = 0x10000100,
+ .atag_offset = 0x100,
.reserve_lp0 = 1,
.reserve_lp1 = 1,
.map_io = rpc_map_io,
diff --git a/arch/arm/mach-s3c2400/include/mach/memory.h b/arch/arm/mach-s3c2400/include/mach/memory.h
deleted file mode 100644
index 3f33670dd012..000000000000
--- a/arch/arm/mach-s3c2400/include/mach/memory.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* arch/arm/mach-s3c2400/include/mach/memory.h
- * from arch/arm/mach-rpc/include/mach/memory.h
- *
- * Copyright 2007 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- * Ben Dooks <ben@simtec.co.uk>
- *
- * Copyright (C) 1996,1997,1998 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x0C000000)
-
-#endif
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 7245a55795dc..3700cf32af0f 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -8,7 +8,6 @@ config CPU_S3C2410
select CPU_ARM920T
select S3C_GPIO_PULL_UP
select S3C2410_CLOCK
- select S3C2410_GPIO
select CPU_LLSERIAL_S3C2410
select S3C2410_PM if PM
select S3C2410_CPUFREQ if CPU_FREQ_S3C24XX
@@ -28,11 +27,6 @@ config S3C2410_PM
help
Power Management code common to S3C2410 and better
-config S3C2410_GPIO
- bool
- help
- GPIO code for S3C2410 and similar processors
-
config SIMTEC_NOR
bool
help
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 81695353d8f4..782fd81144e9 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_CPU_S3C2410) += s3c2410.o
obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o
-obj-$(CONFIG_S3C2410_GPIO) += gpio.o
obj-$(CONFIG_S3C2410_CPUFREQ) += cpu-freq.o
obj-$(CONFIG_S3C2410_PLLTABLE) += pll.o
diff --git a/arch/arm/mach-s3c2410/Makefile.boot b/arch/arm/mach-s3c2410/Makefile.boot
index 58c1dd7f8e1d..4457605ba04a 100644
--- a/arch/arm/mach-s3c2410/Makefile.boot
+++ b/arch/arm/mach-s3c2410/Makefile.boot
@@ -1,7 +1,7 @@
ifeq ($(CONFIG_PM_H1940),y)
- zreladdr-y := 0x30108000
+ zreladdr-y += 0x30108000
params_phys-y := 0x30100100
else
- zreladdr-y := 0x30008000
+ zreladdr-y += 0x30008000
params_phys-y := 0x30000100
endif
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 0d8e043804c2..dbe43df8cfec 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -47,38 +47,26 @@ static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
.channels[0] = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
.channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
.channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
- .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
},
[DMACH_SPI0] = {
.name = "spi0",
.channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
- .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
},
[DMACH_SPI1] = {
.name = "spi1",
.channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
- .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
},
[DMACH_UART0] = {
.name = "uart0",
.channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
},
[DMACH_UART1] = {
.name = "uart1",
.channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
},
[DMACH_UART2] = {
.name = "uart2",
.channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
},
[DMACH_TIMER] = {
.name = "timer",
@@ -90,12 +78,10 @@ static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
.name = "i2s-sdi",
.channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
.channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
- .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
},
[DMACH_I2S_OUT] = {
.name = "i2s-sdo",
.channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
},
[DMACH_USB_EP1] = {
.name = "usb-ep1",
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
deleted file mode 100644
index 9664e011dae2..000000000000
--- a/arch/arm/mach-s3c2410/gpio.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/gpio.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio-fns.h>
-#include <asm/irq.h>
-
-#include <mach/regs-gpio.h>
-
-int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
- unsigned int config)
-{
- void __iomem *reg = S3C24XX_EINFLT0;
- unsigned long flags;
- unsigned long val;
-
- if (pin < S3C2410_GPG(8) || pin > S3C2410_GPG(15))
- return -EINVAL;
-
- config &= 0xff;
-
- pin -= S3C2410_GPG(8);
- reg += pin & ~3;
-
- local_irq_save(flags);
-
- /* update filter width and clock source */
-
- val = __raw_readl(reg);
- val &= ~(0xff << ((pin & 3) * 8));
- val |= config << ((pin & 3) * 8);
- __raw_writel(val, reg);
-
- /* update filter enable */
-
- val = __raw_readl(S3C24XX_EXTINT2);
- val &= ~(1 << ((pin * 4) + 3));
- val |= on << ((pin * 4) + 3);
- __raw_writel(val, S3C24XX_EXTINT2);
-
- local_irq_restore(flags);
-
- return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/include/mach/debug-macro.S b/arch/arm/mach-s3c2410/include/mach/debug-macro.S
index 5882deaa56be..4135de87d1f7 100644
--- a/arch/arm/mach-s3c2410/include/mach/debug-macro.S
+++ b/arch/arm/mach-s3c2410/include/mach/debug-macro.S
@@ -19,7 +19,7 @@
#define S3C2410_UART1_OFF (0x4000)
#define SHIFT_2440TXF (14-9)
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, = S3C24XX_PA_UART
ldr \rv, = S3C24XX_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio.h b/arch/arm/mach-s3c2410/include/mach/gpio.h
index f7f6b07df30e..6fac70f3484e 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio.h
@@ -11,11 +11,6 @@
* published by the Free Software Foundation.
*/
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
/* some boards require extra gpio capacity to support external
* devices that need GPIO.
*/
@@ -28,7 +23,6 @@
#define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA)
#endif
-#include <asm-generic/gpio.h>
#include <mach/gpio-nrs.h>
#include <mach/gpio-fns.h>
diff --git a/arch/arm/mach-s3c2410/include/mach/h1940-latch.h b/arch/arm/mach-s3c2410/include/mach/h1940-latch.h
index 97e42bfce81e..fc897d3a056c 100644
--- a/arch/arm/mach-s3c2410/include/mach/h1940-latch.h
+++ b/arch/arm/mach-s3c2410/include/mach/h1940-latch.h
@@ -14,7 +14,7 @@
#ifndef __ASM_ARCH_H1940_LATCH_H
#define __ASM_ARCH_H1940_LATCH_H
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#define H1940_LATCH_GPIO(x) (S3C_GPIO_END + (x))
diff --git a/arch/arm/mach-s3c2410/include/mach/io.h b/arch/arm/mach-s3c2410/include/mach/io.h
index 9813dbf2ae4f..118749f37c4c 100644
--- a/arch/arm/mach-s3c2410/include/mach/io.h
+++ b/arch/arm/mach-s3c2410/include/mach/io.h
@@ -199,8 +199,6 @@ DECLARE_IO(int,l,"")
#define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
#define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
#define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p))
-/* the following macro is deprecated */
-#define ioaddr(port) __ioaddr((port))
#define insb(p,d,l) __raw_readsb(__ioaddr(p),d,l)
#define insw(p,d,l) __raw_readsw(__ioaddr(p),d,l)
diff --git a/arch/arm/mach-s3c2410/include/mach/map.h b/arch/arm/mach-s3c2410/include/mach/map.h
index 425552d84b60..4cf495f813a7 100644
--- a/arch/arm/mach-s3c2410/include/mach/map.h
+++ b/arch/arm/mach-s3c2410/include/mach/map.h
@@ -14,9 +14,53 @@
#define __ASM_ARCH_MAP_H
#include <plat/map-base.h>
-#include <plat/map.h>
-#define S3C2410_ADDR(x) S3C_ADDR(x)
+/*
+ * S3C2410 UART offset is 0x4000 but the other SoCs are 0x400.
+ * So need to define it, and here is to avoid redefinition warning.
+ */
+#define S3C_UART_OFFSET (0x4000)
+
+#include <plat/map-s3c.h>
+
+/*
+ * interrupt controller is the first thing we put in, to make
+ * the assembly code for the irq detection easier
+ */
+#define S3C2410_PA_IRQ (0x4A000000)
+#define S3C24XX_SZ_IRQ SZ_1M
+
+/* memory controller registers */
+#define S3C2410_PA_MEMCTRL (0x48000000)
+#define S3C24XX_SZ_MEMCTRL SZ_1M
+
+/* UARTs */
+#define S3C_VA_UARTx(uart) (S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
+
+/* Timers */
+#define S3C2410_PA_TIMER (0x51000000)
+#define S3C24XX_SZ_TIMER SZ_1M
+
+/* Clock and Power management */
+#define S3C24XX_SZ_CLKPWR SZ_1M
+
+/* USB Device port */
+#define S3C2410_PA_USBDEV (0x52000000)
+#define S3C24XX_SZ_USBDEV SZ_1M
+
+/* Watchdog */
+#define S3C2410_PA_WATCHDOG (0x53000000)
+#define S3C24XX_SZ_WATCHDOG SZ_1M
+
+/* Standard size definitions for peripheral blocks. */
+
+#define S3C24XX_SZ_UART SZ_1M
+#define S3C24XX_SZ_IIS SZ_1M
+#define S3C24XX_SZ_ADC SZ_1M
+#define S3C24XX_SZ_SPI SZ_1M
+#define S3C24XX_SZ_SDI SZ_1M
+#define S3C24XX_SZ_NAND SZ_1M
+#define S3C24XX_SZ_GPIO SZ_1M
/* USB host controller */
#define S3C2410_PA_USBHOST (0x49000000)
@@ -75,10 +119,8 @@
/* S3C2412 memory and IO controls */
#define S3C2412_PA_SSMC (0x4F000000)
-#define S3C2412_VA_SSMC S3C_ADDR_CPU(0x00000000)
#define S3C2412_PA_EBI (0x48800000)
-#define S3C2412_VA_EBI S3C_ADDR_CPU(0x00010000)
/* physical addresses of all the chip-select areas */
@@ -100,12 +142,10 @@
#define S3C24XX_PA_DMA S3C2410_PA_DMA
#define S3C24XX_PA_CLKPWR S3C2410_PA_CLKPWR
#define S3C24XX_PA_LCD S3C2410_PA_LCD
-#define S3C24XX_PA_UART S3C2410_PA_UART
#define S3C24XX_PA_TIMER S3C2410_PA_TIMER
#define S3C24XX_PA_USBDEV S3C2410_PA_USBDEV
#define S3C24XX_PA_WATCHDOG S3C2410_PA_WATCHDOG
#define S3C24XX_PA_IIS S3C2410_PA_IIS
-#define S3C24XX_PA_GPIO S3C2410_PA_GPIO
#define S3C24XX_PA_RTC S3C2410_PA_RTC
#define S3C24XX_PA_ADC S3C2410_PA_ADC
#define S3C24XX_PA_SPI S3C2410_PA_SPI
diff --git a/arch/arm/mach-s3c2410/include/mach/memory.h b/arch/arm/mach-s3c2410/include/mach/memory.h
deleted file mode 100644
index f92b97b89c0c..000000000000
--- a/arch/arm/mach-s3c2410/include/mach/memory.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/memory.h
- * from arch/arm/mach-rpc/include/mach/memory.h
- *
- * Copyright (C) 1996,1997,1998 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x30000000)
-
-#endif
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index dabc141243f3..79838942b0ac 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -236,7 +236,7 @@ static void __init amlm5900_init(void)
}
MACHINE_START(AML_M5900, "AML_M5900")
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = amlm5900_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = amlm5900_init,
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 1e2d536adda9..a20ae1ad4062 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -657,7 +657,7 @@ static void __init bast_init(void)
MACHINE_START(BAST, "Simtec-BAST")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = bast_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = bast_init,
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 2a2fa0620133..556c535829f0 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -744,7 +744,7 @@ static void __init h1940_init(void)
MACHINE_START(H1940, "IPAQ-H1940")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = h1940_map_io,
.reserve = h1940_reserve,
.init_irq = h1940_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 079dcaa602d3..1dc3e3234417 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -586,7 +586,7 @@ MACHINE_START(N30, "Acer-N30")
/* Maintainer: Christer Weinigel <christer@weinigel.se>,
Ben Dooks <ben-linux@fluff.org>
*/
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.timer = &s3c24xx_timer,
.init_machine = n30_init,
.init_irq = s3c24xx_init_irq,
@@ -596,7 +596,7 @@ MACHINE_END
MACHINE_START(N35, "Acer-N35")
/* Maintainer: Christer Weinigel <christer@weinigel.se>
*/
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.timer = &s3c24xx_timer,
.init_machine = n30_init,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index 0aa16cd5acbc..f03f3fd9cec9 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -116,7 +116,7 @@ static void __init otom11_init(void)
MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = otom11_map_io,
.init_machine = otom11_init,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index f44f77531b1e..367d376deb96 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -344,7 +344,7 @@ static void __init qt2410_machine_init(void)
}
MACHINE_START(QT2410, "QT2410")
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = qt2410_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = qt2410_machine_init,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index e17f03387aba..99c9dfdb71c7 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -111,7 +111,7 @@ static void __init smdk2410_init(void)
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
/* Maintainer: Jonas Dietsche */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = smdk2410_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = smdk2410_init,
diff --git a/arch/arm/mach-s3c2410/mach-tct_hammer.c b/arch/arm/mach-s3c2410/mach-tct_hammer.c
index 43c2b831b9e8..e0d0b6fb2800 100644
--- a/arch/arm/mach-s3c2410/mach-tct_hammer.c
+++ b/arch/arm/mach-s3c2410/mach-tct_hammer.c
@@ -146,7 +146,7 @@ static void __init tct_hammer_init(void)
}
MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = tct_hammer_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = tct_hammer_init,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 6ccce5a761b4..df47e8e90065 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -400,7 +400,7 @@ static void __init vr1000_init(void)
MACHINE_START(VR1000, "Thorcom-VR1000")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = vr1000_map_io,
.init_machine = vr1000_init,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
index c2cf4e569989..b8b9029e9f2d 100644
--- a/arch/arm/mach-s3c2412/Kconfig
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -9,7 +9,6 @@ config CPU_S3C2412
select CPU_LLSERIAL_S3C2440
select S3C2412_PM if PM
select S3C2412_DMA if S3C2410_DMA
- select S3C2410_GPIO
help
Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile
index 6c48a91ea39e..7e4d95fa8a97 100644
--- a/arch/arm/mach-s3c2412/Makefile
+++ b/arch/arm/mach-s3c2412/Makefile
@@ -12,7 +12,6 @@ obj- :=
obj-$(CONFIG_CPU_S3C2412) += s3c2412.o
obj-$(CONFIG_CPU_S3C2412) += irq.o
obj-$(CONFIG_CPU_S3C2412) += clock.o
-obj-$(CONFIG_CPU_S3C2412) += gpio.o
obj-$(CONFIG_S3C2412_DMA) += dma.o
obj-$(CONFIG_S3C2412_PM) += pm.o
obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep.o
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index 7abecfca0b7e..c61e3261615d 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -50,64 +50,46 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
.name = "sdi",
.channels = MAP(S3C2412_DMAREQSEL_SDI),
.channels_rx = MAP(S3C2412_DMAREQSEL_SDI),
- .hw_addr.to = S3C2410_PA_SDI + S3C2410_SDIDATA,
- .hw_addr.from = S3C2410_PA_SDI + S3C2410_SDIDATA,
},
[DMACH_SPI0] = {
.name = "spi0",
.channels = MAP(S3C2412_DMAREQSEL_SPI0TX),
.channels_rx = MAP(S3C2412_DMAREQSEL_SPI0RX),
- .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
- .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
},
[DMACH_SPI1] = {
.name = "spi1",
.channels = MAP(S3C2412_DMAREQSEL_SPI1TX),
.channels_rx = MAP(S3C2412_DMAREQSEL_SPI1RX),
- .hw_addr.to = S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPTDAT,
- .hw_addr.from = S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPRDAT,
},
[DMACH_UART0] = {
.name = "uart0",
.channels = MAP(S3C2412_DMAREQSEL_UART0_0),
.channels_rx = MAP(S3C2412_DMAREQSEL_UART0_0),
- .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
},
[DMACH_UART1] = {
.name = "uart1",
.channels = MAP(S3C2412_DMAREQSEL_UART1_0),
.channels_rx = MAP(S3C2412_DMAREQSEL_UART1_0),
- .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
},
[DMACH_UART2] = {
.name = "uart2",
.channels = MAP(S3C2412_DMAREQSEL_UART2_0),
.channels_rx = MAP(S3C2412_DMAREQSEL_UART2_0),
- .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
},
[DMACH_UART0_SRC2] = {
.name = "uart0",
.channels = MAP(S3C2412_DMAREQSEL_UART0_1),
.channels_rx = MAP(S3C2412_DMAREQSEL_UART0_1),
- .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
},
[DMACH_UART1_SRC2] = {
.name = "uart1",
.channels = MAP(S3C2412_DMAREQSEL_UART1_1),
.channels_rx = MAP(S3C2412_DMAREQSEL_UART1_1),
- .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
},
[DMACH_UART2_SRC2] = {
.name = "uart2",
.channels = MAP(S3C2412_DMAREQSEL_UART2_1),
.channels_rx = MAP(S3C2412_DMAREQSEL_UART2_1),
- .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
},
[DMACH_TIMER] = {
.name = "timer",
diff --git a/arch/arm/mach-s3c2412/gpio.c b/arch/arm/mach-s3c2412/gpio.c
deleted file mode 100644
index 3404a876b33e..000000000000
--- a/arch/arm/mach-s3c2412/gpio.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* linux/arch/arm/mach-s3c2412/gpio.c
- *
- * Copyright (c) 2007 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * http://armlinux.simtec.co.uk/.
- *
- * S3C2412/S3C2413 specific GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/hardware.h>
-
-#include <plat/gpio-core.h>
-
-int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state)
-{
- struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
- unsigned long offs = pin - chip->chip.base;
- unsigned long flags;
- unsigned long slpcon;
-
- offs *= 2;
-
- if (pin < S3C2410_GPB(0))
- return -EINVAL;
-
- if (pin >= S3C2410_GPF(0) &&
- pin <= S3C2410_GPG(16))
- return -EINVAL;
-
- if (pin > S3C2410_GPH(16))
- return -EINVAL;
-
- local_irq_save(flags);
-
- slpcon = __raw_readl(chip->base + 0x0C);
-
- slpcon &= ~(3 << offs);
- slpcon |= state << offs;
-
- __raw_writel(slpcon, chip->base + 0x0C);
-
- local_irq_restore(flags);
-
- return 0;
-}
-
-EXPORT_SYMBOL(s3c2412_gpio_set_sleepcfg);
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index 5eeb47580b0c..286ef1738c61 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -655,7 +655,7 @@ static void __init jive_machine_init(void)
MACHINE_START(JIVE, "JIVE")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = jive_map_io,
diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c
index 834cfb61bcfe..f1eec1b54932 100644
--- a/arch/arm/mach-s3c2412/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2412/mach-smdk2413.c
@@ -92,8 +92,7 @@ static struct platform_device *smdk2413_devices[] __initdata = {
&s3c_device_usbgadget,
};
-static void __init smdk2413_fixup(struct machine_desc *desc,
- struct tag *tags, char **cmdline,
+static void __init smdk2413_fixup(struct tag *tags, char **cmdline,
struct meminfo *mi)
{
if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
@@ -128,7 +127,7 @@ static void __init smdk2413_machine_init(void)
MACHINE_START(S3C2413, "S3C2413")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.fixup = smdk2413_fixup,
.init_irq = s3c24xx_init_irq,
@@ -139,7 +138,7 @@ MACHINE_END
MACHINE_START(SMDK2412, "SMDK2412")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.fixup = smdk2413_fixup,
.init_irq = s3c24xx_init_irq,
@@ -150,7 +149,7 @@ MACHINE_END
MACHINE_START(SMDK2413, "SMDK2413")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.fixup = smdk2413_fixup,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2412/mach-vstms.c b/arch/arm/mach-s3c2412/mach-vstms.c
index 83544ebe20ac..1bbb1ef5f4ff 100644
--- a/arch/arm/mach-s3c2412/mach-vstms.c
+++ b/arch/arm/mach-s3c2412/mach-vstms.c
@@ -129,9 +129,8 @@ static struct platform_device *vstms_devices[] __initdata = {
&s3c_device_nand,
};
-static void __init vstms_fixup(struct machine_desc *desc,
- struct tag *tags, char **cmdline,
- struct meminfo *mi)
+static void __init vstms_fixup(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
mi->nr_banks=1;
@@ -156,7 +155,7 @@ static void __init vstms_init(void)
}
MACHINE_START(VSTMS, "VSTMS")
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.fixup = vstms_fixup,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2416/mach-smdk2416.c b/arch/arm/mach-s3c2416/mach-smdk2416.c
index ac27ebb31c9b..a9eee531ca76 100644
--- a/arch/arm/mach-s3c2416/mach-smdk2416.c
+++ b/arch/arm/mach-s3c2416/mach-smdk2416.c
@@ -245,7 +245,7 @@ static void __init smdk2416_machine_init(void)
MACHINE_START(SMDK2416, "SMDK2416")
/* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2416_map_io,
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index 50825a3f91cc..c461fb8e15c0 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -8,7 +8,6 @@ config CPU_S3C2440
select S3C_GPIO_PULL_UP
select S3C2410_CLOCK
select S3C2410_PM if PM
- select S3C2410_GPIO
select S3C2440_DMA if S3C2410_DMA
select CPU_S3C244X
select CPU_LLSERIAL_S3C2440
@@ -20,7 +19,6 @@ config CPU_S3C2442
select CPU_ARM920T
select S3C_GPIO_PULL_DOWN
select S3C2410_CLOCK
- select S3C2410_GPIO
select S3C2410_PM if PM
select CPU_S3C244X
select CPU_LLSERIAL_S3C2440
diff --git a/arch/arm/mach-s3c2440/dma.c b/arch/arm/mach-s3c2440/dma.c
index 3b0529f54e9c..0e73f8f9d132 100644
--- a/arch/arm/mach-s3c2440/dma.c
+++ b/arch/arm/mach-s3c2440/dma.c
@@ -48,38 +48,26 @@ static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
.channels[1] = S3C2440_DCON_CH1_SDI | DMA_CH_VALID,
.channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
.channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
- .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
},
[DMACH_SPI0] = {
.name = "spi0",
.channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
- .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
},
[DMACH_SPI1] = {
.name = "spi1",
.channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
- .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
},
[DMACH_UART0] = {
.name = "uart0",
.channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
},
[DMACH_UART1] = {
.name = "uart1",
.channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
},
[DMACH_UART2] = {
.name = "uart2",
.channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
},
[DMACH_TIMER] = {
.name = "timer",
@@ -91,31 +79,26 @@ static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
.name = "i2s-sdi",
.channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
.channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
- .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
},
[DMACH_I2S_OUT] = {
.name = "i2s-sdo",
.channels[0] = S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID,
.channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
},
[DMACH_PCM_IN] = {
.name = "pcm-in",
.channels[0] = S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID,
.channels[2] = S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID,
- .hw_addr.from = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
},
[DMACH_PCM_OUT] = {
.name = "pcm-out",
.channels[1] = S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID,
.channels[3] = S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID,
- .hw_addr.to = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
},
[DMACH_MIC_IN] = {
.name = "mic-in",
.channels[2] = S3C2440_DCON_CH2_MICIN | DMA_CH_VALID,
.channels[3] = S3C2440_DCON_CH3_MICIN | DMA_CH_VALID,
- .hw_addr.from = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
},
[DMACH_USB_EP1] = {
.name = "usb-ep1",
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index d7086788b1ff..74f92fc3fd04 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -498,7 +498,7 @@ static void __init anubis_init(void)
MACHINE_START(ANUBIS, "Simtec-Anubis")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = anubis_map_io,
.init_machine = anubis_init,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-at2440evb.c b/arch/arm/mach-s3c2440/mach-at2440evb.c
index 6c98b789b8c6..38887ee0c784 100644
--- a/arch/arm/mach-s3c2440/mach-at2440evb.c
+++ b/arch/arm/mach-s3c2440/mach-at2440evb.c
@@ -233,7 +233,7 @@ static void __init at2440evb_init(void)
MACHINE_START(AT2440EVB, "AT2440EVB")
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = at2440evb_map_io,
.init_machine = at2440evb_init,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index c10ddf4ed7f1..de1e0ff46cec 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -595,7 +595,7 @@ static void __init gta02_machine_init(void)
MACHINE_START(NEO1973_GTA02, "GTA02")
/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = gta02_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = gta02_machine_init,
diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c
index fc2dc0b3d4fe..91fe0b4c95f1 100644
--- a/arch/arm/mach-s3c2440/mach-mini2440.c
+++ b/arch/arm/mach-s3c2440/mach-mini2440.c
@@ -676,7 +676,7 @@ static void __init mini2440_init(void)
MACHINE_START(MINI2440, "MINI2440")
/* Maintainer: Michel Pollet <buserror@gmail.com> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = mini2440_map_io,
.init_machine = mini2440_init,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-nexcoder.c b/arch/arm/mach-s3c2440/mach-nexcoder.c
index 37dd306fb7dc..61c0bf148165 100644
--- a/arch/arm/mach-s3c2440/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2440/mach-nexcoder.c
@@ -151,7 +151,7 @@ static void __init nexcoder_init(void)
MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = nexcoder_map_io,
.init_machine = nexcoder_init,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index d88536393310..dc142ebf8cba 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -447,7 +447,7 @@ static void __init osiris_init(void)
MACHINE_START(OSIRIS, "Simtec-OSIRIS")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = osiris_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = osiris_init,
diff --git a/arch/arm/mach-s3c2440/mach-rx1950.c b/arch/arm/mach-s3c2440/mach-rx1950.c
index 27ea95096fe1..684dbb3567f5 100644
--- a/arch/arm/mach-s3c2440/mach-rx1950.c
+++ b/arch/arm/mach-s3c2440/mach-rx1950.c
@@ -825,7 +825,7 @@ static void __init rx1950_reserve(void)
MACHINE_START(RX1950, "HP iPAQ RX1950")
/* Maintainers: Vasily Khoruzhick */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = rx1950_map_io,
.reserve = rx1950_reserve,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index 1472b1a5b2fb..e19499c2f909 100644
--- a/arch/arm/mach-s3c2440/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -218,7 +218,7 @@ static void __init rx3715_init_machine(void)
MACHINE_START(RX3715, "IPAQ-RX3715")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.map_io = rx3715_map_io,
.reserve = rx3715_reserve,
.init_irq = rx3715_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c
index eedfe0f11643..36eeb4197a84 100644
--- a/arch/arm/mach-s3c2440/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2440/mach-smdk2440.c
@@ -175,7 +175,7 @@ static void __init smdk2440_machine_init(void)
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c
index 3f658685ec16..fe52151d2e84 100644
--- a/arch/arm/mach-s3c2443/dma.c
+++ b/arch/arm/mach-s3c2443/dma.c
@@ -54,68 +54,46 @@ static struct s3c24xx_dma_map __initdata s3c2443_dma_mappings[] = {
[DMACH_SDI] = {
.name = "sdi",
.channels = MAP(S3C2443_DMAREQSEL_SDI),
- .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
- .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
},
[DMACH_SPI0] = {
.name = "spi0",
.channels = MAP(S3C2443_DMAREQSEL_SPI0TX),
- .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
- .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
},
[DMACH_SPI1] = {
.name = "spi1",
.channels = MAP(S3C2443_DMAREQSEL_SPI1TX),
- .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
- .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
},
[DMACH_UART0] = {
.name = "uart0",
.channels = MAP(S3C2443_DMAREQSEL_UART0_0),
- .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
},
[DMACH_UART1] = {
.name = "uart1",
.channels = MAP(S3C2443_DMAREQSEL_UART1_0),
- .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
},
[DMACH_UART2] = {
.name = "uart2",
.channels = MAP(S3C2443_DMAREQSEL_UART2_0),
- .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
},
[DMACH_UART3] = {
.name = "uart3",
.channels = MAP(S3C2443_DMAREQSEL_UART3_0),
- .hw_addr.to = S3C2443_PA_UART3 + S3C2410_UTXH,
- .hw_addr.from = S3C2443_PA_UART3 + S3C2410_URXH,
},
[DMACH_UART0_SRC2] = {
.name = "uart0",
.channels = MAP(S3C2443_DMAREQSEL_UART0_1),
- .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
},
[DMACH_UART1_SRC2] = {
.name = "uart1",
.channels = MAP(S3C2443_DMAREQSEL_UART1_1),
- .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
},
[DMACH_UART2_SRC2] = {
.name = "uart2",
.channels = MAP(S3C2443_DMAREQSEL_UART2_1),
- .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
},
[DMACH_UART3_SRC2] = {
.name = "uart3",
.channels = MAP(S3C2443_DMAREQSEL_UART3_1),
- .hw_addr.to = S3C2443_PA_UART3 + S3C2410_UTXH,
- .hw_addr.from = S3C2443_PA_UART3 + S3C2410_URXH,
},
[DMACH_TIMER] = {
.name = "timer",
@@ -124,27 +102,22 @@ static struct s3c24xx_dma_map __initdata s3c2443_dma_mappings[] = {
[DMACH_I2S_IN] = {
.name = "i2s-sdi",
.channels = MAP(S3C2443_DMAREQSEL_I2SRX),
- .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
},
[DMACH_I2S_OUT] = {
.name = "i2s-sdo",
.channels = MAP(S3C2443_DMAREQSEL_I2STX),
- .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
},
[DMACH_PCM_IN] = {
.name = "pcm-in",
.channels = MAP(S3C2443_DMAREQSEL_PCMIN),
- .hw_addr.from = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
},
[DMACH_PCM_OUT] = {
.name = "pcm-out",
.channels = MAP(S3C2443_DMAREQSEL_PCMOUT),
- .hw_addr.to = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
},
[DMACH_MIC_IN] = {
.name = "mic-in",
.channels = MAP(S3C2443_DMAREQSEL_MICIN),
- .hw_addr.from = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
},
};
diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c
index 514275e43ca0..bec107e00441 100644
--- a/arch/arm/mach-s3c2443/mach-smdk2443.c
+++ b/arch/arm/mach-s3c2443/mach-smdk2443.c
@@ -139,7 +139,7 @@ static void __init smdk2443_machine_init(void)
MACHINE_START(SMDK2443, "SMDK2443")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2443_map_io,
diff --git a/arch/arm/mach-s3c64xx/Makefile.boot b/arch/arm/mach-s3c64xx/Makefile.boot
index ba41fdc0a586..c642333af3ed 100644
--- a/arch/arm/mach-s3c64xx/Makefile.boot
+++ b/arch/arm/mach-s3c64xx/Makefile.boot
@@ -1,2 +1,2 @@
- zreladdr-y := 0x50008000
+ zreladdr-y += 0x50008000
params_phys-y := 0x50000100
diff --git a/arch/arm/mach-s3c64xx/cpu.c b/arch/arm/mach-s3c64xx/cpu.c
index 374e45e566b8..c7047838e112 100644
--- a/arch/arm/mach-s3c64xx/cpu.c
+++ b/arch/arm/mach-s3c64xx/cpu.c
@@ -20,6 +20,7 @@
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/map.h>
@@ -43,16 +44,16 @@ static const char name_s3c6410[] = "S3C6410";
static struct cpu_table cpu_ids[] __initdata = {
{
- .idcode = 0x36400000,
- .idmask = 0xfffff000,
+ .idcode = S3C6400_CPU_ID,
+ .idmask = S3C64XX_CPU_MASK,
.map_io = s3c6400_map_io,
.init_clocks = s3c6400_init_clocks,
.init_uarts = s3c6400_init_uarts,
.init = s3c6400_init,
.name = name_s3c6400,
}, {
- .idcode = 0x36410100,
- .idmask = 0xffffff00,
+ .idcode = S3C6410_CPU_ID,
+ .idmask = S3C64XX_CPU_MASK,
.map_io = s3c6410_map_io,
.init_clocks = s3c6410_init_clocks,
.init_uarts = s3c6410_init_uarts,
@@ -140,22 +141,15 @@ void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
{
- unsigned long idcode;
-
/* initialise the io descriptors we need for initialisation */
iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
iotable_init(mach_desc, size);
+ init_consistent_dma_size(SZ_8M);
- idcode = __raw_readl(S3C_VA_SYS + 0x118);
- if (!idcode) {
- /* S3C6400 has the ID register in a different place,
- * and needs a write before it can be read. */
-
- __raw_writel(0x0, S3C_VA_SYS + 0xA1C);
- idcode = __raw_readl(S3C_VA_SYS + 0xA1C);
- }
+ /* detect cpu id */
+ s3c64xx_init_cpu();
- s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+ s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
}
static __init int s3c64xx_sysdev_init(void)
diff --git a/arch/arm/mach-s3c64xx/dev-uart.c b/arch/arm/mach-s3c64xx/dev-uart.c
index f797f748b999..c681b99eda08 100644
--- a/arch/arm/mach-s3c64xx/dev-uart.c
+++ b/arch/arm/mach-s3c64xx/dev-uart.c
@@ -37,21 +37,10 @@ static struct resource s3c64xx_uart0_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S3CUART_RX0,
- .end = IRQ_S3CUART_RX0,
+ .start = IRQ_UART0,
+ .end = IRQ_UART0,
.flags = IORESOURCE_IRQ,
},
- [2] = {
- .start = IRQ_S3CUART_TX0,
- .end = IRQ_S3CUART_TX0,
- .flags = IORESOURCE_IRQ,
-
- },
- [3] = {
- .start = IRQ_S3CUART_ERR0,
- .end = IRQ_S3CUART_ERR0,
- .flags = IORESOURCE_IRQ,
- }
};
static struct resource s3c64xx_uart1_resource[] = {
@@ -61,19 +50,8 @@ static struct resource s3c64xx_uart1_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S3CUART_RX1,
- .end = IRQ_S3CUART_RX1,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S3CUART_TX1,
- .end = IRQ_S3CUART_TX1,
- .flags = IORESOURCE_IRQ,
-
- },
- [3] = {
- .start = IRQ_S3CUART_ERR1,
- .end = IRQ_S3CUART_ERR1,
+ .start = IRQ_UART1,
+ .end = IRQ_UART1,
.flags = IORESOURCE_IRQ,
},
};
@@ -85,19 +63,8 @@ static struct resource s3c6xx_uart2_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S3CUART_RX2,
- .end = IRQ_S3CUART_RX2,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S3CUART_TX2,
- .end = IRQ_S3CUART_TX2,
- .flags = IORESOURCE_IRQ,
-
- },
- [3] = {
- .start = IRQ_S3CUART_ERR2,
- .end = IRQ_S3CUART_ERR2,
+ .start = IRQ_UART2,
+ .end = IRQ_UART2,
.flags = IORESOURCE_IRQ,
},
};
@@ -109,19 +76,8 @@ static struct resource s3c64xx_uart3_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S3CUART_RX3,
- .end = IRQ_S3CUART_RX3,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S3CUART_TX3,
- .end = IRQ_S3CUART_TX3,
- .flags = IORESOURCE_IRQ,
-
- },
- [3] = {
- .start = IRQ_S3CUART_ERR3,
- .end = IRQ_S3CUART_ERR3,
+ .start = IRQ_UART3,
+ .end = IRQ_UART3,
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/arm/mach-s3c64xx/include/mach/debug-macro.S b/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
index a29e70550c70..c0c076a90f27 100644
--- a/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
@@ -21,7 +21,7 @@
* aligned and add in the offset when we load the value here.
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, = S3C_PA_UART
ldr \rv, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
#if CONFIG_DEBUG_S3C_UART != 0
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio.h b/arch/arm/mach-s3c64xx/include/mach/gpio.h
index 0d46e994048a..6e34c2f6e670 100644
--- a/arch/arm/mach-s3c64xx/include/mach/gpio.h
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio.h
@@ -12,11 +12,6 @@
* published by the Free Software Foundation.
*/
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
/* GPIO bank sizes */
#define S3C64XX_GPIO_A_NR (8)
#define S3C64XX_GPIO_B_NR (7)
@@ -96,5 +91,3 @@ enum s3c_gpio_number {
#define BOARD_NR_GPIOS 16
#define ARCH_NR_GPIOS (GPIO_BOARD_START + BOARD_NR_GPIOS)
-
-#include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-s3c64xx/include/mach/irqs.h b/arch/arm/mach-s3c64xx/include/mach/irqs.h
index c026f67a80de..443f85b3c203 100644
--- a/arch/arm/mach-s3c64xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c64xx/include/mach/irqs.h
@@ -27,36 +27,6 @@
#define IRQ_VIC0_BASE S3C_IRQ(0)
#define IRQ_VIC1_BASE S3C_IRQ(32)
-/* UART interrupts, each UART has 4 intterupts per channel so
- * use the space between the ISA and S3C main interrupts. Note, these
- * are not in the same order as the S3C24XX series! */
-
-#define IRQ_S3CUART_BASE0 (16)
-#define IRQ_S3CUART_BASE1 (20)
-#define IRQ_S3CUART_BASE2 (24)
-#define IRQ_S3CUART_BASE3 (28)
-
-#define UART_IRQ_RXD (0)
-#define UART_IRQ_ERR (1)
-#define UART_IRQ_TXD (2)
-#define UART_IRQ_MODEM (3)
-
-#define IRQ_S3CUART_RX0 (IRQ_S3CUART_BASE0 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX0 (IRQ_S3CUART_BASE0 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR0 (IRQ_S3CUART_BASE0 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX1 (IRQ_S3CUART_BASE1 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX1 (IRQ_S3CUART_BASE1 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR1 (IRQ_S3CUART_BASE1 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX2 (IRQ_S3CUART_BASE2 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX2 (IRQ_S3CUART_BASE2 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR2 (IRQ_S3CUART_BASE2 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX3 (IRQ_S3CUART_BASE3 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX3 (IRQ_S3CUART_BASE3 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR3 (IRQ_S3CUART_BASE3 + UART_IRQ_ERR)
-
/* VIC based IRQs */
#define S3C64XX_IRQ_VIC0(x) (IRQ_VIC0_BASE + (x))
diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h
index a1f13f02c841..23a1d71e4d53 100644
--- a/arch/arm/mach-s3c64xx/include/mach/map.h
+++ b/arch/arm/mach-s3c64xx/include/mach/map.h
@@ -16,6 +16,7 @@
#define __ASM_ARCH_MAP_H __FILE__
#include <plat/map-base.h>
+#include <plat/map-s3c.h>
/*
* Post-mux Chip Select Regions Xm0CSn_
@@ -83,7 +84,6 @@
#define S3C64XX_PA_IIC1 (0x7F00F000)
#define S3C64XX_PA_GPIO (0x7F008000)
-#define S3C64XX_VA_GPIO S3C_ADDR_CPU(0x00000000)
#define S3C64XX_SZ_GPIO SZ_4K
#define S3C64XX_PA_SDRAM (0x50000000)
@@ -94,16 +94,10 @@
#define S3C64XX_PA_VIC1 (0x71300000)
#define S3C64XX_PA_MODEM (0x74108000)
-#define S3C64XX_VA_MODEM S3C_ADDR_CPU(0x00100000)
#define S3C64XX_PA_USBHOST (0x74300000)
#define S3C64XX_PA_USB_HSPHY (0x7C100000)
-#define S3C64XX_VA_USB_HSPHY S3C_ADDR_CPU(0x00200000)
-
-/* place VICs close together */
-#define VA_VIC0 (S3C_VA_IRQ + 0x00)
-#define VA_VIC1 (S3C_VA_IRQ + 0x10000)
/* compatibiltiy defines. */
#define S3C_PA_TIMER S3C64XX_PA_TIMER
@@ -119,7 +113,6 @@
#define S3C_PA_FB S3C64XX_PA_FB
#define S3C_PA_USBHOST S3C64XX_PA_USBHOST
#define S3C_PA_USB_HSOTG S3C64XX_PA_USB_HSOTG
-#define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY
#define S3C_PA_RTC S3C64XX_PA_RTC
#define S3C_PA_WDT S3C64XX_PA_WATCHDOG
diff --git a/arch/arm/mach-s3c64xx/include/mach/memory.h b/arch/arm/mach-s3c64xx/include/mach/memory.h
deleted file mode 100644
index 4760cdae1eb6..000000000000
--- a/arch/arm/mach-s3c64xx/include/mach/memory.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* arch/arm/mach-s3c6400/include/mach/memory.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x50000000)
-
-#define CONSISTENT_DMA_SIZE SZ_8M
-
-#endif
diff --git a/arch/arm/mach-s3c64xx/irq.c b/arch/arm/mach-s3c64xx/irq.c
index 75d9a0e49193..b07357e94958 100644
--- a/arch/arm/mach-s3c64xx/irq.c
+++ b/arch/arm/mach-s3c64xx/irq.c
@@ -25,29 +25,6 @@
#include <plat/irq-uart.h>
#include <plat/cpu.h>
-static struct s3c_uart_irq uart_irqs[] = {
- [0] = {
- .regs = S3C_VA_UART0,
- .base_irq = IRQ_S3CUART_BASE0,
- .parent_irq = IRQ_UART0,
- },
- [1] = {
- .regs = S3C_VA_UART1,
- .base_irq = IRQ_S3CUART_BASE1,
- .parent_irq = IRQ_UART1,
- },
- [2] = {
- .regs = S3C_VA_UART2,
- .base_irq = IRQ_S3CUART_BASE2,
- .parent_irq = IRQ_UART2,
- },
- [3] = {
- .regs = S3C_VA_UART3,
- .base_irq = IRQ_S3CUART_BASE3,
- .parent_irq = IRQ_UART3,
- },
-};
-
/* setup the sources the vic should advertise resume for, even though it
* is not doing the wake (set_irq_wake needs to be valid) */
#define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE))
@@ -67,6 +44,4 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
/* add the timer sub-irqs */
s3c_init_vic_timer_irq(5, IRQ_TIMER0);
-
- s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
}
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index cb8864327ac4..d164a282bfb4 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -233,7 +233,7 @@ static void __init anw6410_machine_init(void)
MACHINE_START(ANW6410, "A&W6410")
/* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
- .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c6410_init_irq,
.map_io = anw6410_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index af0c2fe1ea37..806580388f30 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -329,9 +329,6 @@ static struct platform_device *crag6410_devices[] __initdata = {
&s3c_device_fb,
&s3c_device_ohci,
&s3c_device_usb_hsotg,
- &s3c_device_adc,
- &s3c_device_rtc,
- &s3c_device_ts,
&s3c_device_timer[0],
&s3c64xx_device_iis0,
&s3c64xx_device_iis1,
@@ -766,7 +763,7 @@ static void __init crag6410_machine_init(void)
MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
/* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
- .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c6410_init_irq,
.map_io = crag6410_map_io,
.init_machine = crag6410_machine_init,
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index b3d93cc8dde0..19a0887e1c1e 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -265,7 +265,7 @@ static void __init hmt_machine_init(void)
MACHINE_START(HMT, "Airgoo-HMT")
/* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
- .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c6410_init_irq,
.map_io = hmt_map_io,
.init_machine = hmt_machine_init,
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index 527f49bd1b57..fb8969aa412e 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -205,12 +205,6 @@ static struct platform_device mini6410_lcd_powerdev = {
.dev.platform_data = &mini6410_lcd_power_data,
};
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
- .delay = 10000,
- .presc = 49,
- .oversampling_shift = 2,
-};
-
static struct platform_device *mini6410_devices[] __initdata = {
&mini6410_device_eth,
&s3c_device_hsmmc0,
@@ -319,7 +313,7 @@ static void __init mini6410_machine_init(void)
s3c_nand_set_platdata(&mini6410_nand_info);
s3c_fb_set_platdata(&mini6410_lcd_pdata);
- s3c24xx_ts_set_platdata(&s3c_ts_platform);
+ s3c24xx_ts_set_platdata(NULL);
/* configure nCS1 width to 16 bits */
@@ -349,7 +343,7 @@ static void __init mini6410_machine_init(void)
MACHINE_START(MINI6410, "MINI6410")
/* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
- .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c6410_init_irq,
.map_io = mini6410_map_io,
.init_machine = mini6410_machine_init,
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index 01c6857c5b63..c30f2e5e0d85 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -97,7 +97,7 @@ static void __init ncp_machine_init(void)
MACHINE_START(NCP, "NCP")
/* Maintainer: Samsung Electronics */
- .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c6410_init_irq,
.map_io = ncp_map_io,
.init_machine = ncp_machine_init,
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index 95b04b1729e3..93170d4834e7 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -198,12 +198,6 @@ static struct platform_device *real6410_devices[] __initdata = {
&s3c_device_ohci,
};
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
- .delay = 10000,
- .presc = 49,
- .oversampling_shift = 2,
-};
-
static void __init real6410_map_io(void)
{
u32 tmp;
@@ -300,7 +294,7 @@ static void __init real6410_machine_init(void)
s3c_fb_set_platdata(&real6410_lcd_pdata);
s3c_nand_set_platdata(&real6410_nand_info);
- s3c24xx_ts_set_platdata(&s3c_ts_platform);
+ s3c24xx_ts_set_platdata(NULL);
/* configure nCS1 width to 16 bits */
@@ -329,7 +323,7 @@ static void __init real6410_machine_init(void)
MACHINE_START(REAL6410, "REAL6410")
/* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
- .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c6410_init_irq,
.map_io = real6410_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c
index 342e8dfddf8b..cbb57ded3d95 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq5.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq5.c
@@ -146,7 +146,7 @@ static void __init smartq5_machine_init(void)
MACHINE_START(SMARTQ5, "SmartQ 5")
/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
- .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c6410_init_irq,
.map_io = smartq_map_io,
.init_machine = smartq5_machine_init,
diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c
index 57963977da8e..04f914b85fdf 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq7.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq7.c
@@ -162,7 +162,7 @@ static void __init smartq7_machine_init(void)
MACHINE_START(SMARTQ7, "SmartQ 7")
/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
- .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c6410_init_irq,
.map_io = smartq_map_io,
.init_machine = smartq7_machine_init,
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index 3cca642f1e6d..6fd5e95f8f75 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -85,7 +85,7 @@ static void __init smdk6400_machine_init(void)
MACHINE_START(SMDK6400, "SMDK6400")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c6400_init_irq,
.map_io = smdk6400_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index a9f3183e0290..5f147c33edad 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -619,12 +619,6 @@ static struct i2c_board_info i2c_devs1[] __initdata = {
{ I2C_BOARD_INFO("24c128", 0x57), }, /* Samsung S524AD0XD1 */
};
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
- .delay = 10000,
- .presc = 49,
- .oversampling_shift = 2,
-};
-
/* LCD Backlight data */
static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = {
.no = S3C64XX_GPF(15),
@@ -666,7 +660,7 @@ static void __init smdk6410_machine_init(void)
samsung_keypad_set_platdata(&smdk6410_keypad_data);
- s3c24xx_ts_set_platdata(&s3c_ts_platform);
+ s3c24xx_ts_set_platdata(NULL);
/* configure nCS1 width to 16 bits */
@@ -703,7 +697,7 @@ static void __init smdk6410_machine_init(void)
MACHINE_START(SMDK6410, "SMDK6410")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .boot_params = S3C64XX_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s3c6410_init_irq,
.map_io = smdk6410_map_io,
diff --git a/arch/arm/mach-s5p64x0/Makefile.boot b/arch/arm/mach-s5p64x0/Makefile.boot
index ff90aa13bd67..79ece4055b02 100644
--- a/arch/arm/mach-s5p64x0/Makefile.boot
+++ b/arch/arm/mach-s5p64x0/Makefile.boot
@@ -1,2 +1,2 @@
- zreladdr-y := 0x20008000
+ zreladdr-y += 0x20008000
params_phys-y := 0x20000100
diff --git a/arch/arm/mach-s5p64x0/cpu.c b/arch/arm/mach-s5p64x0/cpu.c
index a5c00952ea35..8a938542c54d 100644
--- a/arch/arm/mach-s5p64x0/cpu.c
+++ b/arch/arm/mach-s5p64x0/cpu.c
@@ -20,6 +20,7 @@
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
+#include <linux/dma-mapping.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -111,6 +112,7 @@ void __init s5p6440_map_io(void)
iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+ init_consistent_dma_size(SZ_8M);
}
void __init s5p6450_map_io(void)
@@ -120,6 +122,7 @@ void __init s5p6450_map_io(void)
iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
+ init_consistent_dma_size(SZ_8M);
}
/*
diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c
index ac825e826326..1fd9c79c7dbc 100644
--- a/arch/arm/mach-s5p64x0/dev-spi.c
+++ b/arch/arm/mach-s5p64x0/dev-spi.c
@@ -21,6 +21,7 @@
#include <mach/regs-clock.h>
#include <mach/spi-clocks.h>
+#include <plat/cpu.h>
#include <plat/s3c64xx-spi.h>
#include <plat/gpio-cfg.h>
@@ -185,11 +186,8 @@ struct platform_device s5p64x0_device_spi1 = {
void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
{
- unsigned int id;
struct s3c64xx_spi_info *pd;
- id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
-
/* Reject invalid configuration */
if (!num_cs || src_clk_nr < 0
|| src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) {
@@ -199,7 +197,7 @@ void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
switch (cntrlr) {
case 0:
- if (id == 0x50000)
+ if (soc_is_s5p6450())
pd = &s5p6450_spi0_pdata;
else
pd = &s5p6440_spi0_pdata;
@@ -207,7 +205,7 @@ void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
s5p64x0_device_spi0.dev.platform_data = pd;
break;
case 1:
- if (id == 0x50000)
+ if (soc_is_s5p6450())
pd = &s5p6450_spi1_pdata;
else
pd = &s5p6440_spi1_pdata;
diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c
index d7ad944b3475..0e5b3e63e5b3 100644
--- a/arch/arm/mach-s5p64x0/dma.c
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -28,6 +28,7 @@
#include <mach/irqs.h>
#include <mach/regs-clock.h>
+#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/s3c-pl330-pdata.h>
@@ -133,11 +134,7 @@ static struct platform_device s5p64x0_device_pdma = {
static int __init s5p64x0_dma_init(void)
{
- unsigned int id;
-
- id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
-
- if (id == 0x50000)
+ if (soc_is_s5p6450())
s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
else
s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
diff --git a/arch/arm/mach-s5p64x0/gpiolib.c b/arch/arm/mach-s5p64x0/gpiolib.c
index e7fb3b004e77..700dac6c43f3 100644
--- a/arch/arm/mach-s5p64x0/gpiolib.c
+++ b/arch/arm/mach-s5p64x0/gpiolib.c
@@ -19,6 +19,7 @@
#include <mach/regs-gpio.h>
#include <mach/regs-clock.h>
+#include <plat/cpu.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
@@ -473,14 +474,10 @@ static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
static int __init s5p64x0_gpiolib_init(void)
{
- unsigned int chipid;
-
- chipid = __raw_readl(S5P64X0_SYS_ID);
-
s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
ARRAY_SIZE(s5p64x0_gpio_cfgs));
- if ((chipid & 0xff000) == 0x50000) {
+ if (soc_is_s5p6450()) {
samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit,
ARRAY_SIZE(s5p6450_gpio_2bit));
diff --git a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
index 79b04e6a6f8e..e80ba3c69814 100644
--- a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
@@ -15,7 +15,7 @@
#include <plat/regs-serial.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0xE0000000
orr \rp, \rp, #0x00100000
ldr \rp, [\rp, #0x118 ]
diff --git a/arch/arm/mach-s5p64x0/include/mach/gpio.h b/arch/arm/mach-s5p64x0/include/mach/gpio.h
index adb5f298ead8..06cd3c9b16ac 100644
--- a/arch/arm/mach-s5p64x0/include/mach/gpio.h
+++ b/arch/arm/mach-s5p64x0/include/mach/gpio.h
@@ -13,11 +13,6 @@
#ifndef __ASM_ARCH_GPIO_H
#define __ASM_ARCH_GPIO_H __FILE__
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
/* GPIO bank sizes */
#define S5P6440_GPIO_A_NR (6)
@@ -134,6 +129,4 @@ enum s5p6450_gpio_number {
#define ARCH_NR_GPIOS (S5P64X0_GPIO_END + CONFIG_SAMSUNG_GPIO_EXTRA)
-#include <asm-generic/gpio.h>
-
#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/memory.h b/arch/arm/mach-s5p64x0/include/mach/memory.h
deleted file mode 100644
index 365a6eb4b88f..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/memory.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/memory.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - Memory definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H __FILE__
-
-#define PLAT_PHYS_OFFSET UL(0x20000000)
-#define CONSISTENT_DMA_SIZE SZ_8M
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5p64x0/irq-eint.c b/arch/arm/mach-s5p64x0/irq-eint.c
index fe7380f5c3cd..494e1a8f6f6d 100644
--- a/arch/arm/mach-s5p64x0/irq-eint.c
+++ b/arch/arm/mach-s5p64x0/irq-eint.c
@@ -17,6 +17,7 @@
#include <linux/irq.h>
#include <linux/io.h>
+#include <plat/cpu.h>
#include <plat/regs-irqtype.h>
#include <plat/gpio-cfg.h>
@@ -67,7 +68,7 @@ static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type)
__raw_writel(ctrl, S5P64X0_EINT0CON0);
/* Configure the GPIO pin for 6450 or 6440 based on CPU ID */
- if (0x50000 == (__raw_readl(S5P64X0_SYS_ID) & 0xFF000))
+ if (soc_is_s5p6450())
s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2));
else
s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2));
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 346f8dfa6f35..88857f5a49f7 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -129,12 +129,6 @@ static struct i2c_board_info smdk6440_i2c_devs1[] __initdata = {
/* To be populated */
};
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
- .delay = 10000,
- .presc = 49,
- .oversampling_shift = 2,
-};
-
/* LCD Backlight data */
static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = {
.no = S5P6440_GPF(15),
@@ -155,7 +149,7 @@ static void __init smdk6440_map_io(void)
static void __init smdk6440_machine_init(void)
{
- s3c24xx_ts_set_platdata(&s3c_ts_platform);
+ s3c24xx_ts_set_platdata(NULL);
s3c_i2c0_set_platdata(&s5p6440_i2c0_data);
s3c_i2c1_set_platdata(&s5p6440_i2c1_data);
@@ -171,7 +165,7 @@ static void __init smdk6440_machine_init(void)
MACHINE_START(SMDK6440, "SMDK6440")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .boot_params = S5P64X0_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s5p6440_init_irq,
.map_io = smdk6440_map_io,
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index 33f2adf8f3fe..e1b277b94610 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -148,12 +148,6 @@ static struct i2c_board_info smdk6450_i2c_devs1[] __initdata = {
{ I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */
};
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
- .delay = 10000,
- .presc = 49,
- .oversampling_shift = 2,
-};
-
/* LCD Backlight data */
static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = {
.no = S5P6450_GPF(15),
@@ -174,7 +168,7 @@ static void __init smdk6450_map_io(void)
static void __init smdk6450_machine_init(void)
{
- s3c24xx_ts_set_platdata(&s3c_ts_platform);
+ s3c24xx_ts_set_platdata(NULL);
s3c_i2c0_set_platdata(&s5p6450_i2c0_data);
s3c_i2c1_set_platdata(&s5p6450_i2c1_data);
@@ -190,7 +184,7 @@ static void __init smdk6450_machine_init(void)
MACHINE_START(SMDK6450, "SMDK6450")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .boot_params = S5P64X0_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s5p6450_init_irq,
.map_io = smdk6450_map_io,
diff --git a/arch/arm/mach-s5pc100/Makefile.boot b/arch/arm/mach-s5pc100/Makefile.boot
index ff90aa13bd67..79ece4055b02 100644
--- a/arch/arm/mach-s5pc100/Makefile.boot
+++ b/arch/arm/mach-s5pc100/Makefile.boot
@@ -1,2 +1,2 @@
- zreladdr-y := 0x20008000
+ zreladdr-y += 0x20008000
params_phys-y := 0x20000100
diff --git a/arch/arm/mach-s5pc100/include/mach/debug-macro.S b/arch/arm/mach-s5pc100/include/mach/debug-macro.S
index b2ba95ddf8e0..694f75937000 100644
--- a/arch/arm/mach-s5pc100/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5pc100/include/mach/debug-macro.S
@@ -22,7 +22,7 @@
* aligned and add in the offset when we load the value here.
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, = S3C_PA_UART
ldr \rv, = S3C_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
diff --git a/arch/arm/mach-s5pc100/include/mach/gpio.h b/arch/arm/mach-s5pc100/include/mach/gpio.h
index 29a8a12d9b4f..5e1a924b595f 100644
--- a/arch/arm/mach-s5pc100/include/mach/gpio.h
+++ b/arch/arm/mach-s5pc100/include/mach/gpio.h
@@ -15,11 +15,6 @@
#ifndef __ASM_ARCH_GPIO_H
#define __ASM_ARCH_GPIO_H __FILE__
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
/* GPIO bank sizes */
#define S5PC100_GPIO_A0_NR (8)
#define S5PC100_GPIO_A1_NR (5)
@@ -146,6 +141,4 @@ enum s5p_gpio_number {
/* define the number of gpios we need to the one after the MP04() range */
#define ARCH_NR_GPIOS (S5PC100_GPIO_END + 1)
-#include <asm-generic/gpio.h>
-
#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/memory.h b/arch/arm/mach-s5pc100/include/mach/memory.h
deleted file mode 100644
index bda4e79fd5fc..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/memory.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/memory.h
- *
- * Copyright 2008 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * Based on mach-s3c6400/include/mach/memory.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x20000000)
-
-#endif
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 227d8908aab6..26f5c91c9427 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -203,12 +203,6 @@ static struct platform_device *smdkc100_devices[] __initdata = {
&s5pc100_device_spdif,
};
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
- .delay = 10000,
- .presc = 49,
- .oversampling_shift = 2,
-};
-
/* LCD Backlight data */
static struct samsung_bl_gpio_info smdkc100_bl_gpio_info = {
.no = S5PC100_GPD(0),
@@ -228,7 +222,7 @@ static void __init smdkc100_map_io(void)
static void __init smdkc100_machine_init(void)
{
- s3c24xx_ts_set_platdata(&s3c_ts_platform);
+ s3c24xx_ts_set_platdata(NULL);
/* I2C */
s3c_i2c0_set_platdata(NULL);
@@ -254,7 +248,7 @@ static void __init smdkc100_machine_init(void)
MACHINE_START(SMDKC100, "SMDKC100")
/* Maintainer: Byungho Min <bhmin@samsung.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s5pc100_init_irq,
.map_io = smdkc100_map_io,
.init_machine = smdkc100_machine_init,
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 69dd87cd8e22..aaeb44a73716 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -14,7 +14,6 @@ config CPU_S5PV210
select S3C_PL330_DMA
select S5P_EXT_INT
select S5P_HRT
- select S5PV210_PM if PM
help
Enable S5PV210 CPU support
@@ -169,9 +168,4 @@ config MACH_TORBRECK
endmenu
-config S5PV210_PM
- bool
- help
- Power Management code common to S5PV210
-
endif
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 599a3c0e8f6c..ef7e4668d670 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -14,7 +14,7 @@ obj- :=
obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o
obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o
-obj-$(CONFIG_S5PV210_PM) += pm.o sleep.o
+obj-$(CONFIG_PM) += pm.o sleep.o
# machine support
diff --git a/arch/arm/mach-s5pv210/Makefile.boot b/arch/arm/mach-s5pv210/Makefile.boot
index ff90aa13bd67..79ece4055b02 100644
--- a/arch/arm/mach-s5pv210/Makefile.boot
+++ b/arch/arm/mach-s5pv210/Makefile.boot
@@ -1,2 +1,2 @@
- zreladdr-y := 0x20008000
+ zreladdr-y += 0x20008000
params_phys-y := 0x20000100
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 79907ec78d43..91145720822c 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -20,6 +20,7 @@
#include <linux/sysdev.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
+#include <linux/dma-mapping.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -119,6 +120,7 @@ static void s5pv210_sw_reset(void)
void __init s5pv210_map_io(void)
{
iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
+ init_consistent_dma_size(14 << 20);
/* initialise device information early */
s5pv210_default_sdhci0();
diff --git a/arch/arm/mach-s5pv210/include/mach/debug-macro.S b/arch/arm/mach-s5pv210/include/mach/debug-macro.S
index 169fe654a59e..79e55597ab63 100644
--- a/arch/arm/mach-s5pv210/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5pv210/include/mach/debug-macro.S
@@ -21,7 +21,7 @@
* aligned and add in the offset when we load the value here.
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, = S3C_PA_UART
ldr \rv, = S3C_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
diff --git a/arch/arm/mach-s5pv210/include/mach/gpio.h b/arch/arm/mach-s5pv210/include/mach/gpio.h
index a5a1e331f8ed..6c8b903c02e4 100644
--- a/arch/arm/mach-s5pv210/include/mach/gpio.h
+++ b/arch/arm/mach-s5pv210/include/mach/gpio.h
@@ -13,11 +13,6 @@
#ifndef __ASM_ARCH_GPIO_H
#define __ASM_ARCH_GPIO_H __FILE__
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
/* Practically, GPIO banks up to MP03 are the configurable gpio banks */
/* GPIO bank sizes */
@@ -142,6 +137,4 @@ enum s5p_gpio_number {
#define ARCH_NR_GPIOS (S5PV210_MP05(S5PV210_GPIO_MP05_NR) + \
CONFIG_SAMSUNG_GPIO_EXTRA + 1)
-#include <asm-generic/gpio.h>
-
#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/memory.h b/arch/arm/mach-s5pv210/include/mach/memory.h
index 7b5fcf0da0c4..2d3cfa221d5f 100644
--- a/arch/arm/mach-s5pv210/include/mach/memory.h
+++ b/arch/arm/mach-s5pv210/include/mach/memory.h
@@ -14,7 +14,6 @@
#define __ASM_ARCH_MEMORY_H
#define PLAT_PHYS_OFFSET UL(0x20000000)
-#define CONSISTENT_DMA_SIZE (SZ_8M + SZ_4M + SZ_2M)
/*
* Sparsemem support
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 509627f25111..5811a96125f0 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -678,7 +678,7 @@ MACHINE_START(AQUILA, "Aquila")
/* Maintainers:
Marek Szyprowski <m.szyprowski@samsung.com>
Kyungmin Park <kyungmin.park@samsung.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s5pv210_init_irq,
.map_io = aquila_map_io,
.init_machine = aquila_machine_init,
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 85c2d51a0956..061cc7e4f48c 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -897,7 +897,7 @@ static void __init goni_machine_init(void)
MACHINE_START(GONI, "GONI")
/* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s5pv210_init_irq,
.map_io = goni_map_io,
.init_machine = goni_machine_init,
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index 6c412c8ceccc..f7266bb0cac8 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -136,7 +136,7 @@ static void __init smdkc110_machine_init(void)
MACHINE_START(SMDKC110, "SMDKC110")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkc110_map_io,
.init_machine = smdkc110_machine_init,
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 5e011fc6720d..a9106c392398 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -265,12 +265,6 @@ static struct i2c_board_info smdkv210_i2c_devs2[] __initdata = {
/* To Be Updated */
};
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
- .delay = 10000,
- .presc = 49,
- .oversampling_shift = 2,
-};
-
/* LCD Backlight data */
static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = {
.no = S5PV210_GPD0(3),
@@ -296,7 +290,7 @@ static void __init smdkv210_machine_init(void)
smdkv210_dm9000_init();
samsung_keypad_set_platdata(&smdkv210_keypad_data);
- s3c24xx_ts_set_platdata(&s3c_ts_platform);
+ s3c24xx_ts_set_platdata(NULL);
s3c_i2c0_set_platdata(NULL);
s3c_i2c1_set_platdata(NULL);
@@ -319,7 +313,7 @@ static void __init smdkv210_machine_init(void)
MACHINE_START(SMDKV210, "SMDKV210")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkv210_map_io,
.init_machine = smdkv210_machine_init,
diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c
index 925fc0dc6252..97cc066c5369 100644
--- a/arch/arm/mach-s5pv210/mach-torbreck.c
+++ b/arch/arm/mach-s5pv210/mach-torbreck.c
@@ -125,7 +125,7 @@ static void __init torbreck_machine_init(void)
MACHINE_START(TORBRECK, "TORBRECK")
/* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .atag_offset = 0x100,
.init_irq = s5pv210_init_irq,
.map_io = torbreck_map_io,
.init_machine = torbreck_machine_init,
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index 41252d22e659..ed7408d3216c 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -3,7 +3,7 @@
#
# Common support
-obj-y := clock.o generic.o gpio.o irq.o dma.o time.o #nmi-oopser.o
+obj-y := clock.o generic.o irq.o dma.o time.o #nmi-oopser.o
obj-m :=
obj-n :=
obj- :=
@@ -45,7 +45,6 @@ obj-$(CONFIG_SA1100_PLEB) += pleb.o
obj-$(CONFIG_SA1100_SHANNON) += shannon.o
obj-$(CONFIG_SA1100_SIMPAD) += simpad.o
-led-$(CONFIG_SA1100_SIMPAD) += leds-simpad.o
# LEDs support
obj-$(CONFIG_LEDS) += $(led-y)
diff --git a/arch/arm/mach-sa1100/Makefile.boot b/arch/arm/mach-sa1100/Makefile.boot
index a56ad0417cf2..5a616f6e5612 100644
--- a/arch/arm/mach-sa1100/Makefile.boot
+++ b/arch/arm/mach-sa1100/Makefile.boot
@@ -1,6 +1,7 @@
- zreladdr-y := 0xc0008000
ifeq ($(CONFIG_ARCH_SA1100),y)
- zreladdr-$(CONFIG_SA1111) := 0xc0208000
+ zreladdr-$(CONFIG_SA1111) += 0xc0208000
+else
+ zreladdr-y += 0xc0008000
endif
params_phys-y := 0xc0000100
initrd_phys-y := 0xc0800000
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 26257df19b63..3dd133f18415 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -301,8 +301,7 @@ static void __init get_assabet_scr(void)
}
static void __init
-fixup_assabet(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+fixup_assabet(struct tag *tags, char **cmdline, struct meminfo *mi)
{
/* This must be done before any call to machine_has_neponset() */
map_sa1100_gpio_regs();
@@ -447,7 +446,7 @@ static void __init assabet_map_io(void)
MACHINE_START(ASSABET, "Intel-Assabet")
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.fixup = fixup_assabet,
.map_io = assabet_map_io,
.init_irq = sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index b4311b0a4395..bda83e1ab078 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -302,7 +302,7 @@ static void __init badge4_map_io(void)
}
MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.map_io = badge4_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index e21f3470eece..5fa5ae1f39e1 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -9,6 +9,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -24,7 +25,6 @@
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
#include <asm/irq.h>
-#include <asm/gpio.h>
#include "generic.h"
diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c
index 03d7376cf8a0..b30733a2b82e 100644
--- a/arch/arm/mach-sa1100/h3100.c
+++ b/arch/arm/mach-sa1100/h3100.c
@@ -84,7 +84,7 @@ static void __init h3100_mach_init(void)
}
MACHINE_START(H3100, "Compaq iPAQ H3100")
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.map_io = h3100_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index 965f64a836f8..6fd324d92389 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -125,7 +125,7 @@ static void __init h3600_mach_init(void)
}
MACHINE_START(H3600, "Compaq iPAQ H3600")
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.map_io = h3600_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c
index db5e434a17db..30f4a551b8e5 100644
--- a/arch/arm/mach-sa1100/hackkit.c
+++ b/arch/arm/mach-sa1100/hackkit.c
@@ -195,7 +195,7 @@ static void __init hackkit_init(void)
*/
MACHINE_START(HACKKIT, "HackKit Cpu Board")
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.map_io = hackkit_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/include/mach/debug-macro.S b/arch/arm/mach-sa1100/include/mach/debug-macro.S
index 0cd0fc9635b6..530772d937ad 100644
--- a/arch/arm/mach-sa1100/include/mach/debug-macro.S
+++ b/arch/arm/mach-sa1100/include/mach/debug-macro.S
@@ -12,7 +12,7 @@
*/
#include <mach/hardware.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mrc p15, 0, \rp, c1, c0
tst \rp, #1 @ MMU enabled?
moveq \rp, #0x80000000 @ physical base address
diff --git a/arch/arm/mach-sa1100/include/mach/gpio.h b/arch/arm/mach-sa1100/include/mach/gpio.h
index 7befc104e9a9..703631887c94 100644
--- a/arch/arm/mach-sa1100/include/mach/gpio.h
+++ b/arch/arm/mach-sa1100/include/mach/gpio.h
@@ -28,6 +28,8 @@
#include <asm/irq.h>
#include <asm-generic/gpio.h>
+#define __ARM_GPIOLIB_COMPLEX
+
static inline int gpio_get_value(unsigned gpio)
{
if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
@@ -51,7 +53,5 @@ static inline void gpio_set_value(unsigned gpio, int value)
#define gpio_to_irq(gpio) ((gpio < 11) ? (IRQ_GPIO0 + gpio) : \
(IRQ_GPIO11 - 11 + gpio))
-#define irq_to_gpio(irq) ((irq < IRQ_GPIO11_27) ? (irq - IRQ_GPIO0) : \
- (irq - IRQ_GPIO11 + 11))
#endif
diff --git a/arch/arm/mach-sa1100/include/mach/io.h b/arch/arm/mach-sa1100/include/mach/io.h
index d8b43f3dcd2d..dfc27ff08344 100644
--- a/arch/arm/mach-sa1100/include/mach/io.h
+++ b/arch/arm/mach-sa1100/include/mach/io.h
@@ -10,11 +10,9 @@
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
-#define IO_SPACE_LIMIT 0xffffffff
-
/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
+ * __io() is required to be an equivalent mapping to __mem_pci() for
+ * SOC_COMMON to work.
*/
#define __io(a) __typesafe_io(a)
#define __mem_pci(a) (a)
diff --git a/arch/arm/mach-sa1100/include/mach/simpad.h b/arch/arm/mach-sa1100/include/mach/simpad.h
index 9296c4513ce1..db28118103eb 100644
--- a/arch/arm/mach-sa1100/include/mach/simpad.h
+++ b/arch/arm/mach-sa1100/include/mach/simpad.h
@@ -48,32 +48,80 @@
#define GPIO_SMART_CARD GPIO_GPIO10
#define IRQ_GPIO_SMARD_CARD IRQ_GPIO10
-// CS3 Latch is write only, a shadow is necessary
+/*--- ucb1x00 GPIO ---*/
+#define SIMPAD_UCB1X00_GPIO_BASE (GPIO_MAX + 1)
+#define SIMPAD_UCB1X00_GPIO_PROG1 (SIMPAD_UCB1X00_GPIO_BASE)
+#define SIMPAD_UCB1X00_GPIO_PROG2 (SIMPAD_UCB1X00_GPIO_BASE + 1)
+#define SIMPAD_UCB1X00_GPIO_UP (SIMPAD_UCB1X00_GPIO_BASE + 2)
+#define SIMPAD_UCB1X00_GPIO_DOWN (SIMPAD_UCB1X00_GPIO_BASE + 3)
+#define SIMPAD_UCB1X00_GPIO_LEFT (SIMPAD_UCB1X00_GPIO_BASE + 4)
+#define SIMPAD_UCB1X00_GPIO_RIGHT (SIMPAD_UCB1X00_GPIO_BASE + 5)
+#define SIMPAD_UCB1X00_GPIO_6 (SIMPAD_UCB1X00_GPIO_BASE + 6)
+#define SIMPAD_UCB1X00_GPIO_7 (SIMPAD_UCB1X00_GPIO_BASE + 7)
+#define SIMPAD_UCB1X00_GPIO_HEADSET (SIMPAD_UCB1X00_GPIO_BASE + 8)
+#define SIMPAD_UCB1X00_GPIO_SPEAKER (SIMPAD_UCB1X00_GPIO_BASE + 9)
+
+/*--- CS3 Latch ---*/
+#define SIMPAD_CS3_GPIO_BASE (GPIO_MAX + 11)
+#define SIMPAD_CS3_VCC_5V_EN (SIMPAD_CS3_GPIO_BASE)
+#define SIMPAD_CS3_VCC_3V_EN (SIMPAD_CS3_GPIO_BASE + 1)
+#define SIMPAD_CS3_EN1 (SIMPAD_CS3_GPIO_BASE + 2)
+#define SIMPAD_CS3_EN0 (SIMPAD_CS3_GPIO_BASE + 3)
+#define SIMPAD_CS3_DISPLAY_ON (SIMPAD_CS3_GPIO_BASE + 4)
+#define SIMPAD_CS3_PCMCIA_BUFF_DIS (SIMPAD_CS3_GPIO_BASE + 5)
+#define SIMPAD_CS3_MQ_RESET (SIMPAD_CS3_GPIO_BASE + 6)
+#define SIMPAD_CS3_PCMCIA_RESET (SIMPAD_CS3_GPIO_BASE + 7)
+#define SIMPAD_CS3_DECT_POWER_ON (SIMPAD_CS3_GPIO_BASE + 8)
+#define SIMPAD_CS3_IRDA_SD (SIMPAD_CS3_GPIO_BASE + 9)
+#define SIMPAD_CS3_RS232_ON (SIMPAD_CS3_GPIO_BASE + 10)
+#define SIMPAD_CS3_SD_MEDIAQ (SIMPAD_CS3_GPIO_BASE + 11)
+#define SIMPAD_CS3_LED2_ON (SIMPAD_CS3_GPIO_BASE + 12)
+#define SIMPAD_CS3_IRDA_MODE (SIMPAD_CS3_GPIO_BASE + 13)
+#define SIMPAD_CS3_ENABLE_5V (SIMPAD_CS3_GPIO_BASE + 14)
+#define SIMPAD_CS3_RESET_SIMCARD (SIMPAD_CS3_GPIO_BASE + 15)
+
+#define SIMPAD_CS3_PCMCIA_BVD1 (SIMPAD_CS3_GPIO_BASE + 16)
+#define SIMPAD_CS3_PCMCIA_BVD2 (SIMPAD_CS3_GPIO_BASE + 17)
+#define SIMPAD_CS3_PCMCIA_VS1 (SIMPAD_CS3_GPIO_BASE + 18)
+#define SIMPAD_CS3_PCMCIA_VS2 (SIMPAD_CS3_GPIO_BASE + 19)
+#define SIMPAD_CS3_LOCK_IND (SIMPAD_CS3_GPIO_BASE + 20)
+#define SIMPAD_CS3_CHARGING_STATE (SIMPAD_CS3_GPIO_BASE + 21)
+#define SIMPAD_CS3_PCMCIA_SHORT (SIMPAD_CS3_GPIO_BASE + 22)
+#define SIMPAD_CS3_GPIO_23 (SIMPAD_CS3_GPIO_BASE + 23)
-#define CS3BUSTYPE unsigned volatile long
#define CS3_BASE 0xf1000000
-#define VCC_5V_EN 0x0001 // For 5V PCMCIA
-#define VCC_3V_EN 0x0002 // FOR 3.3V PCMCIA
-#define EN1 0x0004 // This is only for EPROM's
-#define EN0 0x0008 // Both should be enable for 3.3V or 5V
-#define DISPLAY_ON 0x0010
-#define PCMCIA_BUFF_DIS 0x0020
-#define MQ_RESET 0x0040
-#define PCMCIA_RESET 0x0080
-#define DECT_POWER_ON 0x0100
-#define IRDA_SD 0x0200 // Shutdown for powersave
-#define RS232_ON 0x0400
-#define SD_MEDIAQ 0x0800 // Shutdown for powersave
-#define LED2_ON 0x1000
-#define IRDA_MODE 0x2000 // Fast/Slow IrDA mode
-#define ENABLE_5V 0x4000 // Enable 5V circuit
-#define RESET_SIMCARD 0x8000
-
-#define RS232_ENABLE 0x0440
-#define PCMCIAMASK 0x402f
-
-
+long simpad_get_cs3_ro(void);
+long simpad_get_cs3_shadow(void);
+void simpad_set_cs3_bit(int value);
+void simpad_clear_cs3_bit(int value);
+
+#define VCC_5V_EN 0x0001 /* For 5V PCMCIA */
+#define VCC_3V_EN 0x0002 /* FOR 3.3V PCMCIA */
+#define EN1 0x0004 /* This is only for EPROM's */
+#define EN0 0x0008 /* Both should be enable for 3.3V or 5V */
+#define DISPLAY_ON 0x0010
+#define PCMCIA_BUFF_DIS 0x0020
+#define MQ_RESET 0x0040
+#define PCMCIA_RESET 0x0080
+#define DECT_POWER_ON 0x0100
+#define IRDA_SD 0x0200 /* Shutdown for powersave */
+#define RS232_ON 0x0400
+#define SD_MEDIAQ 0x0800 /* Shutdown for powersave */
+#define LED2_ON 0x1000
+#define IRDA_MODE 0x2000 /* Fast/Slow IrDA mode */
+#define ENABLE_5V 0x4000 /* Enable 5V circuit */
+#define RESET_SIMCARD 0x8000
+
+#define PCMCIA_BVD1 0x01
+#define PCMCIA_BVD2 0x02
+#define PCMCIA_VS1 0x04
+#define PCMCIA_VS2 0x08
+#define LOCK_IND 0x10
+#define CHARGING_STATE 0x20
+#define PCMCIA_SHORT 0x40
+
+/*--- Battery ---*/
struct simpad_battery {
unsigned char ac_status; /* line connected yes/no */
unsigned char status; /* battery loading yes/no */
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 176c066aec7e..0bb520d48ed0 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -364,7 +364,7 @@ static void __init jornada720_mach_init(void)
MACHINE_START(JORNADA720, "HP Jornada 720")
/* Maintainer: Kristoffer Ericson <Kristoffer.Ericson@gmail.com> */
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.map_io = jornada720_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index 7b9556b59057..5bc59d0947ba 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -61,7 +61,7 @@ static void __init lart_map_io(void)
}
MACHINE_START(LART, "LART")
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.map_io = lart_map_io,
.init_irq = sa1100_init_irq,
.init_machine = lart_init,
diff --git a/arch/arm/mach-sa1100/leds-simpad.c b/arch/arm/mach-sa1100/leds-simpad.c
deleted file mode 100644
index d50f4eeaa12e..000000000000
--- a/arch/arm/mach-sa1100/leds-simpad.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/leds-simpad.c
- *
- * Author: Juergen Messerer <juergen.messerer@siemens.ch>
- */
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <asm/system.h>
-#include <mach/simpad.h>
-
-#include "leds.h"
-
-
-#define LED_STATE_ENABLED 1
-#define LED_STATE_CLAIMED 2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-#define LED_GREEN (1)
-#define LED_MASK (1)
-
-extern void set_cs3_bit(int value);
-extern void clear_cs3_bit(int value);
-
-void simpad_leds_event(led_event_t evt)
-{
- switch (evt)
- {
- case led_start:
- hw_led_state = LED_GREEN;
- led_state = LED_STATE_ENABLED;
- break;
-
- case led_stop:
- led_state &= ~LED_STATE_ENABLED;
- break;
-
- case led_claim:
- led_state |= LED_STATE_CLAIMED;
- hw_led_state = LED_GREEN;
- break;
-
- case led_release:
- led_state &= ~LED_STATE_CLAIMED;
- hw_led_state = LED_GREEN;
- break;
-
-#ifdef CONFIG_LEDS_TIMER
- case led_timer:
- if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state ^= LED_GREEN;
- break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
- case led_idle_start:
- break;
-
- case led_idle_end:
- break;
-#endif
-
- case led_halted:
- break;
-
- case led_green_on:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state |= LED_GREEN;
- break;
-
- case led_green_off:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state &= ~LED_GREEN;
- break;
-
- case led_amber_on:
- break;
-
- case led_amber_off:
- break;
-
- case led_red_on:
- break;
-
- case led_red_off:
- break;
-
- default:
- break;
- }
-
- if (led_state & LED_STATE_ENABLED)
- set_cs3_bit(LED2_ON);
- else
- clear_cs3_bit(LED2_ON);
-}
-
diff --git a/arch/arm/mach-sa1100/leds.c b/arch/arm/mach-sa1100/leds.c
index bbfe197fb4d6..5fe71a0f1053 100644
--- a/arch/arm/mach-sa1100/leds.c
+++ b/arch/arm/mach-sa1100/leds.c
@@ -42,8 +42,6 @@ sa1100_leds_init(void)
leds_event = adsbitsy_leds_event;
if (machine_is_pt_system3())
leds_event = system3_leds_event;
- if (machine_is_simpad())
- leds_event = simpad_leds_event; /* what about machine registry? including led, apm... -zecke */
leds_event(led_start);
return 0;
diff --git a/arch/arm/mach-sa1100/leds.h b/arch/arm/mach-sa1100/leds.h
index 68cc9f773d6d..776b6020f550 100644
--- a/arch/arm/mach-sa1100/leds.h
+++ b/arch/arm/mach-sa1100/leds.h
@@ -11,4 +11,3 @@ extern void pfs168_leds_event(led_event_t evt);
extern void graphicsmaster_leds_event(led_event_t evt);
extern void adsbitsy_leds_event(led_event_t evt);
extern void system3_leds_event(led_event_t evt);
-extern void simpad_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
index 72087f0658b7..032f3881d145 100644
--- a/arch/arm/mach-sa1100/nanoengine.c
+++ b/arch/arm/mach-sa1100/nanoengine.c
@@ -111,7 +111,7 @@ static void __init nanoengine_init(void)
}
MACHINE_START(NANOENGINE, "BSE nanoEngine")
- .boot_params = 0xc0000000,
+ .atag_offset = 0x100,
.map_io = nanoengine_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 7917b2405579..1cccbf5b9e9a 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -82,7 +82,7 @@ static void __init shannon_map_io(void)
}
MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.map_io = shannon_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index cfb76077bd25..4790f3f3d008 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -13,6 +13,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/io.h>
+#include <linux/gpio.h>
#include <asm/irq.h>
#include <mach/hardware.h>
@@ -28,35 +29,92 @@
#include <linux/serial_core.h>
#include <linux/ioport.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <linux/i2c-gpio.h>
#include "generic.h"
-long cs3_shadow;
+/*
+ * CS3 support
+ */
+
+static long cs3_shadow;
+static spinlock_t cs3_lock;
+static struct gpio_chip cs3_gpio;
+
+long simpad_get_cs3_ro(void)
+{
+ return readl(CS3_BASE);
+}
+EXPORT_SYMBOL(simpad_get_cs3_ro);
-long get_cs3_shadow(void)
+long simpad_get_cs3_shadow(void)
{
return cs3_shadow;
}
+EXPORT_SYMBOL(simpad_get_cs3_shadow);
-void set_cs3(long value)
+static void __simpad_write_cs3(void)
{
- *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value;
+ writel(cs3_shadow, CS3_BASE);
}
-void set_cs3_bit(int value)
+void simpad_set_cs3_bit(int value)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cs3_lock, flags);
cs3_shadow |= value;
- *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
+ __simpad_write_cs3();
+ spin_unlock_irqrestore(&cs3_lock, flags);
}
+EXPORT_SYMBOL(simpad_set_cs3_bit);
-void clear_cs3_bit(int value)
+void simpad_clear_cs3_bit(int value)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cs3_lock, flags);
cs3_shadow &= ~value;
- *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
+ __simpad_write_cs3();
+ spin_unlock_irqrestore(&cs3_lock, flags);
}
+EXPORT_SYMBOL(simpad_clear_cs3_bit);
-EXPORT_SYMBOL(set_cs3_bit);
-EXPORT_SYMBOL(clear_cs3_bit);
+static void cs3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ if (offset > 15)
+ return;
+ if (value)
+ simpad_set_cs3_bit(1 << offset);
+ else
+ simpad_clear_cs3_bit(1 << offset);
+};
+
+static int cs3_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ if (offset > 15)
+ return simpad_get_cs3_ro() & (1 << (offset - 16));
+ return simpad_get_cs3_shadow() & (1 << offset);
+};
+
+static int cs3_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ if (offset > 15)
+ return 0;
+ return -EINVAL;
+};
+
+static int cs3_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ if (offset > 15)
+ return -EINVAL;
+ cs3_gpio_set(chip, offset, value);
+ return 0;
+};
static struct map_desc simpad_io_desc[] __initdata = {
{ /* MQ200 */
@@ -64,9 +122,9 @@ static struct map_desc simpad_io_desc[] __initdata = {
.pfn = __phys_to_pfn(0x4b800000),
.length = 0x00800000,
.type = MT_DEVICE
- }, { /* Paules CS3, write only */
- .virtual = 0xf1000000,
- .pfn = __phys_to_pfn(0x18000000),
+ }, { /* Simpad CS3 */
+ .virtual = CS3_BASE,
+ .pfn = __phys_to_pfn(SA1100_CS3_PHYS),
.length = 0x00100000,
.type = MT_DEVICE
},
@@ -78,12 +136,12 @@ static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
if (port->mapbase == (u_int)&Ser1UTCR0) {
if (state)
{
- clear_cs3_bit(RS232_ON);
- clear_cs3_bit(DECT_POWER_ON);
+ simpad_clear_cs3_bit(RS232_ON);
+ simpad_clear_cs3_bit(DECT_POWER_ON);
}else
{
- set_cs3_bit(RS232_ON);
- set_cs3_bit(DECT_POWER_ON);
+ simpad_set_cs3_bit(RS232_ON);
+ simpad_set_cs3_bit(DECT_POWER_ON);
}
}
}
@@ -132,6 +190,7 @@ static struct resource simpad_flash_resources [] = {
static struct mcp_plat_data simpad_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
+ .gpio_base = SIMPAD_UCB1X00_GPIO_BASE,
};
@@ -142,9 +201,10 @@ static void __init simpad_map_io(void)
iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc));
- set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
- ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON);
-
+ /* Initialize CS3 */
+ cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON |
+ RS232_ON | ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON);
+ __simpad_write_cs3(); /* Spinlocks not yet initialized */
sa1100_register_uart_fns(&simpad_port_fns);
sa1100_register_uart(0, 3); /* serial interface */
@@ -170,13 +230,14 @@ static void __init simpad_map_io(void)
static void simpad_power_off(void)
{
- local_irq_disable(); // was cli
- set_cs3(0x800); /* only SD_MEDIAQ */
+ local_irq_disable();
+ cs3_shadow = SD_MEDIAQ;
+ __simpad_write_cs3(); /* Bypass spinlock here */
/* disable internal oscillator, float CS lines */
PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS);
- /* enable wake-up on GPIO0 (Assabet...) */
- PWER = GFER = GRER = 1;
+ /* enable wake-up on GPIO0 */
+ PWER = GFER = GRER = PWER_GPIO0;
/*
* set scratchpad to zero, just in case it is used as a
* restart address by the bootloader.
@@ -192,6 +253,91 @@ static void simpad_power_off(void)
}
+/*
+ * gpio_keys
+*/
+
+static struct gpio_keys_button simpad_button_table[] = {
+ { KEY_POWER, IRQ_GPIO_POWER_BUTTON, 1, "power button" },
+};
+
+static struct gpio_keys_platform_data simpad_keys_data = {
+ .buttons = simpad_button_table,
+ .nbuttons = ARRAY_SIZE(simpad_button_table),
+};
+
+static struct platform_device simpad_keys = {
+ .name = "gpio-keys",
+ .dev = {
+ .platform_data = &simpad_keys_data,
+ },
+};
+
+static struct gpio_keys_button simpad_polled_button_table[] = {
+ { KEY_PROG1, SIMPAD_UCB1X00_GPIO_PROG1, 1, "prog1 button" },
+ { KEY_PROG2, SIMPAD_UCB1X00_GPIO_PROG2, 1, "prog2 button" },
+ { KEY_UP, SIMPAD_UCB1X00_GPIO_UP, 1, "up button" },
+ { KEY_DOWN, SIMPAD_UCB1X00_GPIO_DOWN, 1, "down button" },
+ { KEY_LEFT, SIMPAD_UCB1X00_GPIO_LEFT, 1, "left button" },
+ { KEY_RIGHT, SIMPAD_UCB1X00_GPIO_RIGHT, 1, "right button" },
+};
+
+static struct gpio_keys_platform_data simpad_polled_keys_data = {
+ .buttons = simpad_polled_button_table,
+ .nbuttons = ARRAY_SIZE(simpad_polled_button_table),
+ .poll_interval = 50,
+};
+
+static struct platform_device simpad_polled_keys = {
+ .name = "gpio-keys-polled",
+ .dev = {
+ .platform_data = &simpad_polled_keys_data,
+ },
+};
+
+/*
+ * GPIO LEDs
+ */
+
+static struct gpio_led simpad_leds[] = {
+ {
+ .name = "simpad:power",
+ .gpio = SIMPAD_CS3_LED2_ON,
+ .active_low = 0,
+ .default_trigger = "default-on",
+ },
+};
+
+static struct gpio_led_platform_data simpad_led_data = {
+ .num_leds = ARRAY_SIZE(simpad_leds),
+ .leds = simpad_leds,
+};
+
+static struct platform_device simpad_gpio_leds = {
+ .name = "leds-gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &simpad_led_data,
+ },
+};
+
+/*
+ * i2c
+ */
+static struct i2c_gpio_platform_data simpad_i2c_data = {
+ .sda_pin = GPIO_GPIO21,
+ .scl_pin = GPIO_GPIO25,
+ .udelay = 10,
+ .timeout = HZ,
+};
+
+static struct platform_device simpad_i2c = {
+ .name = "i2c-gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &simpad_i2c_data,
+ },
+};
/*
* MediaQ Video Device
@@ -202,7 +348,11 @@ static struct platform_device simpad_mq200fb = {
};
static struct platform_device *devices[] __initdata = {
- &simpad_mq200fb
+ &simpad_keys,
+ &simpad_polled_keys,
+ &simpad_mq200fb,
+ &simpad_gpio_leds,
+ &simpad_i2c,
};
@@ -211,6 +361,19 @@ static int __init simpad_init(void)
{
int ret;
+ spin_lock_init(&cs3_lock);
+
+ cs3_gpio.label = "simpad_cs3";
+ cs3_gpio.base = SIMPAD_CS3_GPIO_BASE;
+ cs3_gpio.ngpio = 24;
+ cs3_gpio.set = cs3_gpio_set;
+ cs3_gpio.get = cs3_gpio_get;
+ cs3_gpio.direction_input = cs3_gpio_direction_input;
+ cs3_gpio.direction_output = cs3_gpio_direction_output;
+ ret = gpiochip_add(&cs3_gpio);
+ if (ret)
+ printk(KERN_WARNING "simpad: Unable to register cs3 GPIO device");
+
pm_power_off = simpad_power_off;
sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
@@ -229,7 +392,7 @@ arch_initcall(simpad_init);
MACHINE_START(SIMPAD, "Simpad")
/* Maintainer: Holger Freyther */
- .boot_params = 0xc0000100,
+ .atag_offset = 0x100,
.map_io = simpad_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-shark/Makefile.boot b/arch/arm/mach-shark/Makefile.boot
index 4320f8b92771..e40e24e4ca34 100644
--- a/arch/arm/mach-shark/Makefile.boot
+++ b/arch/arm/mach-shark/Makefile.boot
@@ -1,2 +1,2 @@
- zreladdr-y := 0x08008000
+ zreladdr-y += 0x08008000
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index ac2873c8014b..feda3ca7fc95 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -152,7 +152,7 @@ static struct sys_timer shark_timer = {
MACHINE_START(SHARK, "Shark")
/* Maintainer: Alexander Schulz */
- .boot_params = 0x08003000,
+ .atag_offset = 0x3000,
.map_io = shark_map_io,
.init_irq = shark_init_irq,
.timer = &shark_timer,
diff --git a/arch/arm/mach-shark/include/mach/debug-macro.S b/arch/arm/mach-shark/include/mach/debug-macro.S
index a473f55dc71f..20eb2bf2a42b 100644
--- a/arch/arm/mach-shark/include/mach/debug-macro.S
+++ b/arch/arm/mach-shark/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
*
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0xe0000000
orr \rp, \rp, #0x000003f8
mov \rv, \rp
diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c
index c9e32de4adf9..ccd49189bbd0 100644
--- a/arch/arm/mach-shark/leds.c
+++ b/arch/arm/mach-shark/leds.c
@@ -36,7 +36,7 @@ static char led_state;
static short hw_led_state;
static short saved_state;
-static DEFINE_SPINLOCK(leds_lock);
+static DEFINE_RAW_SPINLOCK(leds_lock);
short sequoia_read(int addr) {
outw(addr,0x24);
@@ -52,7 +52,7 @@ static void sequoia_leds_event(led_event_t evt)
{
unsigned long flags;
- spin_lock_irqsave(&leds_lock, flags);
+ raw_spin_lock_irqsave(&leds_lock, flags);
hw_led_state = sequoia_read(0x09);
@@ -144,7 +144,7 @@ static void sequoia_leds_event(led_event_t evt)
if (led_state & LED_STATE_ENABLED)
sequoia_write(hw_led_state,0x09);
- spin_unlock_irqrestore(&leds_lock, flags);
+ raw_spin_unlock_irqrestore(&leds_lock, flags);
}
static int __init leds_init(void)
diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot
index 1c08ee9de86a..498efd99338d 100644
--- a/arch/arm/mach-shmobile/Makefile.boot
+++ b/arch/arm/mach-shmobile/Makefile.boot
@@ -1,7 +1,7 @@
__ZRELADDR := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_MEMORY_START) + 0x8000]')
- zreladdr-y := $(__ZRELADDR)
+ zreladdr-y += $(__ZRELADDR)
# Unsupported legacy stuff
#
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index cdfdd624d21d..475342bcc95c 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -37,6 +37,7 @@
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mfd/tmio.h>
#include <linux/sh_clk.h>
+#include <linux/dma-mapping.h>
#include <video/sh_mobile_lcdc.h>
#include <video/sh_mipi_dsi.h>
#include <sound/sh_fsi.h>
@@ -354,14 +355,17 @@ static struct resource sdhi0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
+ .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT,
.start = gic_spi(83),
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
.start = gic_spi(84),
.flags = IORESOURCE_IRQ,
},
[3] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
.start = gic_spi(85),
.flags = IORESOURCE_IRQ,
},
@@ -397,14 +401,17 @@ static struct resource sdhi1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
+ .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT,
.start = gic_spi(87),
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
.start = gic_spi(88),
.flags = IORESOURCE_IRQ,
},
[3] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
.start = gic_spi(89),
.flags = IORESOURCE_IRQ,
},
@@ -447,6 +454,8 @@ static struct map_desc ag5evm_io_desc[] __initdata = {
static void __init ag5evm_map_io(void)
{
iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc));
+ /* DMA memory at 0xf6000000 - 0xffdfffff */
+ init_consistent_dma_size(158 << 20);
/* setup early devices and console here as well */
sh73a0_add_early_devices();
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 523f608eb8cf..5b7edadf4647 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -42,6 +42,8 @@
#include <linux/leds.h>
#include <linux/input/sh_keysc.h>
#include <linux/usb/r8a66597.h>
+#include <linux/pm_clock.h>
+#include <linux/dma-mapping.h>
#include <media/sh_mobile_ceu.h>
#include <media/sh_mobile_csi2.h>
@@ -1170,6 +1172,8 @@ static struct map_desc ap4evb_io_desc[] __initdata = {
static void __init ap4evb_map_io(void)
{
iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc));
+ /* DMA memory at 0xf6000000 - 0xffdfffff */
+ init_consistent_dma_size(158 << 20);
/* setup early devices and console here as well */
sh7372_add_early_devices();
@@ -1408,6 +1412,11 @@ static void __init ap4evb_init(void)
sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
+ sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
+
hdmi_init_pm_clock();
fsi_init_pm_clock();
sh7372_pm_init();
diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
index ef4613b993a2..8b620bf06221 100644
--- a/arch/arm/mach-shmobile/board-g3evm.c
+++ b/arch/arm/mach-shmobile/board-g3evm.c
@@ -32,6 +32,7 @@
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/input/sh_keysc.h>
+#include <linux/dma-mapping.h>
#include <mach/sh7367.h>
#include <mach/common.h>
#include <asm/mach-types.h>
@@ -260,6 +261,8 @@ static struct map_desc g3evm_io_desc[] __initdata = {
static void __init g3evm_map_io(void)
{
iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc));
+ /* DMA memory at 0xf6000000 - 0xffdfffff */
+ init_consistent_dma_size(158 << 20);
/* setup early devices and console here as well */
sh7367_add_early_devices();
diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
index 8e3c5559f27f..7719ddc5f591 100644
--- a/arch/arm/mach-shmobile/board-g4evm.c
+++ b/arch/arm/mach-shmobile/board-g4evm.c
@@ -33,6 +33,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/gpio.h>
+#include <linux/dma-mapping.h>
#include <mach/sh7377.h>
#include <mach/common.h>
#include <asm/mach-types.h>
@@ -274,6 +275,8 @@ static struct map_desc g4evm_io_desc[] __initdata = {
static void __init g4evm_map_io(void)
{
iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc));
+ /* DMA memory at 0xf6000000 - 0xffdfffff */
+ init_consistent_dma_size(158 << 20);
/* setup early devices and console here as well */
sh7377_add_early_devices();
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 17c19dc25604..3689ad2e9156 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -39,12 +39,13 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
-#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
#include <linux/smsc911x.h>
#include <linux/sh_intc.h>
#include <linux/tca6416_keypad.h>
#include <linux/usb/r8a66597.h>
#include <linux/usb/renesas_usbhs.h>
+#include <linux/dma-mapping.h>
#include <video/sh_mobile_hdmi.h>
#include <video/sh_mobile_lcdc.h>
@@ -810,6 +811,7 @@ static struct usbhs_private usbhs1_private = {
},
.driver_param = {
.buswait_bwait = 4,
+ .has_otg = 1,
.pipe_type = usbhs1_pipe_cfg,
.pipe_size = ARRAY_SIZE(usbhs1_pipe_cfg),
.d0_tx_id = SHDMA_SLAVE_USB1_TX,
@@ -1070,14 +1072,17 @@ static struct resource sdhi1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
+ .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT,
.start = evt2irq(0x0e80), /* SDHI1_SDHI1I0 */
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
.start = evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */
.flags = IORESOURCE_IRQ,
},
[3] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
.start = evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */
.flags = IORESOURCE_IRQ,
},
@@ -1121,14 +1126,17 @@ static struct resource sdhi2_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
+ .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT,
.start = evt2irq(0x1200), /* SDHI2_SDHI2I0 */
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
.start = evt2irq(0x1220), /* SDHI2_SDHI2I1 */
.flags = IORESOURCE_IRQ,
},
[3] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
.start = evt2irq(0x1240), /* SDHI2_SDHI2I2 */
.flags = IORESOURCE_IRQ,
},
@@ -1381,6 +1389,8 @@ static struct map_desc mackerel_io_desc[] __initdata = {
static void __init mackerel_map_io(void)
{
iotable_init(mackerel_io_desc, ARRAY_SIZE(mackerel_io_desc));
+ /* DMA memory at 0xf6000000 - 0xffdfffff */
+ init_consistent_dma_size(158 << 20);
/* setup early devices and console here as well */
sh7372_add_early_devices();
@@ -1587,7 +1597,17 @@ static void __init mackerel_init(void)
sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device);
+ sh7372_add_device_to_domain(&sh7372_a4lc, &meram_device);
sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
+#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
+ sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
+#endif
+ sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi2_device);
+ sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
hdmi_init_pm_clock();
sh7372_pm_init();
diff --git a/arch/arm/mach-shmobile/entry-intc.S b/arch/arm/mach-shmobile/entry-intc.S
index cac0a7ae2084..1a1c00ca39a2 100644
--- a/arch/arm/mach-shmobile/entry-intc.S
+++ b/arch/arm/mach-shmobile/entry-intc.S
@@ -51,7 +51,4 @@
.macro test_for_ipi, irqnr, irqstat, base, tmp
.endm
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- .endm
-
arch_irq_handler shmobile_handle_irq_intc
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 06aecb31d9c7..c0cdbf997c91 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -35,8 +35,8 @@ extern void sh7372_add_standard_devices(void);
extern void sh7372_clock_init(void);
extern void sh7372_pinmux_init(void);
extern void sh7372_pm_init(void);
-extern void sh7372_cpu_suspend(void);
-extern void sh7372_cpu_resume(void);
+extern void sh7372_resume_core_standby_a3sm(void);
+extern int sh7372_do_idle_a3sm(unsigned long unused);
extern struct clk sh7372_extal1_clk;
extern struct clk sh7372_extal2_clk;
diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S
index d791f10eeac7..8d4a416d4285 100644
--- a/arch/arm/mach-shmobile/include/mach/entry-macro.S
+++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S
@@ -27,8 +27,5 @@
.macro test_for_ipi, irqnr, irqstat, base, tmp
.endm
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- .endm
-
.macro arch_ret_to_user, tmp1, tmp2
.endm
diff --git a/arch/arm/mach-shmobile/include/mach/gpio.h b/arch/arm/mach-shmobile/include/mach/gpio.h
index 2b1bb9e43dda..7bf0890e16ba 100644
--- a/arch/arm/mach-shmobile/include/mach/gpio.h
+++ b/arch/arm/mach-shmobile/include/mach/gpio.h
@@ -18,31 +18,15 @@
#ifdef CONFIG_GPIOLIB
-static inline int gpio_get_value(unsigned gpio)
-{
- return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
- __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
- return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
- return __gpio_to_irq(gpio);
-}
-
static inline int irq_to_gpio(unsigned int irq)
{
return -ENOSYS;
}
+#else
+
+#define __ARM_GPIOLIB_COMPLEX
+
#endif /* CONFIG_GPIOLIB */
#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-shmobile/include/mach/memory.h b/arch/arm/mach-shmobile/include/mach/memory.h
index ad00c3c258f4..0ffbe8155c76 100644
--- a/arch/arm/mach-shmobile/include/mach/memory.h
+++ b/arch/arm/mach-shmobile/include/mach/memory.h
@@ -4,7 +4,4 @@
#define PLAT_PHYS_OFFSET UL(CONFIG_MEMORY_START)
#define MEM_SIZE UL(CONFIG_MEMORY_SIZE)
-/* DMA memory at 0xf6000000 - 0xffdfffff */
-#define CONSISTENT_DMA_SIZE (158 << 20)
-
#endif /* __ASM_MACH_MEMORY_H */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index 24e63a85e669..84532f9629b2 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -479,7 +479,12 @@ struct platform_device;
struct sh7372_pm_domain {
struct generic_pm_domain genpd;
+ struct dev_power_governor *gov;
+ void (*suspend)(void);
+ void (*resume)(void);
unsigned int bit_shift;
+ bool no_debug;
+ bool stay_on;
};
static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
@@ -491,16 +496,24 @@ static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
extern struct sh7372_pm_domain sh7372_a4lc;
extern struct sh7372_pm_domain sh7372_a4mp;
extern struct sh7372_pm_domain sh7372_d4;
+extern struct sh7372_pm_domain sh7372_a4r;
extern struct sh7372_pm_domain sh7372_a3rv;
extern struct sh7372_pm_domain sh7372_a3ri;
+extern struct sh7372_pm_domain sh7372_a3sp;
extern struct sh7372_pm_domain sh7372_a3sg;
extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd);
extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
struct platform_device *pdev);
+extern void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd,
+ struct sh7372_pm_domain *sh7372_sd);
#else
#define sh7372_init_pm_domain(pd) do { } while(0)
#define sh7372_add_device_to_domain(pd, pdev) do { } while(0)
+#define sh7372_pm_add_subdomain(pd, sd) do { } while(0)
#endif /* CONFIG_PM */
+extern void sh7372_intcs_suspend(void);
+extern void sh7372_intcs_resume(void);
+
#endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
index 739315e30eb9..29cdc0522d9c 100644
--- a/arch/arm/mach-shmobile/intc-sh7372.c
+++ b/arch/arm/mach-shmobile/intc-sh7372.c
@@ -606,9 +606,16 @@ static void intcs_demux(unsigned int irq, struct irq_desc *desc)
generic_handle_irq(intcs_evt2irq(evtcodeas));
}
+static void __iomem *intcs_ffd2;
+static void __iomem *intcs_ffd5;
+
void __init sh7372_init_irq(void)
{
- void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
+ void __iomem *intevtsa;
+
+ intcs_ffd2 = ioremap_nocache(0xffd20000, PAGE_SIZE);
+ intevtsa = intcs_ffd2 + 0x100;
+ intcs_ffd5 = ioremap_nocache(0xffd50000, PAGE_SIZE);
register_intc_controller(&intca_desc);
register_intc_controller(&intcs_desc);
@@ -617,3 +624,46 @@ void __init sh7372_init_irq(void)
irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
}
+
+static unsigned short ffd2[0x200];
+static unsigned short ffd5[0x100];
+
+void sh7372_intcs_suspend(void)
+{
+ int k;
+
+ for (k = 0x00; k <= 0x30; k += 4)
+ ffd2[k] = __raw_readw(intcs_ffd2 + k);
+
+ for (k = 0x80; k <= 0xb0; k += 4)
+ ffd2[k] = __raw_readb(intcs_ffd2 + k);
+
+ for (k = 0x180; k <= 0x188; k += 4)
+ ffd2[k] = __raw_readb(intcs_ffd2 + k);
+
+ for (k = 0x00; k <= 0x3c; k += 4)
+ ffd5[k] = __raw_readw(intcs_ffd5 + k);
+
+ for (k = 0x80; k <= 0x9c; k += 4)
+ ffd5[k] = __raw_readb(intcs_ffd5 + k);
+}
+
+void sh7372_intcs_resume(void)
+{
+ int k;
+
+ for (k = 0x00; k <= 0x30; k += 4)
+ __raw_writew(ffd2[k], intcs_ffd2 + k);
+
+ for (k = 0x80; k <= 0xb0; k += 4)
+ __raw_writeb(ffd2[k], intcs_ffd2 + k);
+
+ for (k = 0x180; k <= 0x188; k += 4)
+ __raw_writeb(ffd2[k], intcs_ffd2 + k);
+
+ for (k = 0x00; k <= 0x3c; k += 4)
+ __raw_writew(ffd5[k], intcs_ffd5 + k);
+
+ for (k = 0x80; k <= 0x9c; k += 4)
+ __raw_writeb(ffd5[k], intcs_ffd5 + k);
+}
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index 66f980625a33..e4e485fa2532 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -56,6 +56,12 @@ void __init smp_init_cpus(void)
unsigned int ncores = shmobile_smp_get_core_count();
unsigned int i;
+ if (ncores > nr_cpu_ids) {
+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+ ncores, nr_cpu_ids);
+ ncores = nr_cpu_ids;
+ }
+
for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 933fb411be0f..79612737c5b2 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -15,23 +15,61 @@
#include <linux/list.h>
#include <linux/err.h>
#include <linux/slab.h>
-#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/bitrev.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/tlbflush.h>
+#include <asm/suspend.h>
#include <mach/common.h>
#include <mach/sh7372.h>
-#define SMFRAM 0xe6a70000
-#define SYSTBCR 0xe6150024
-#define SBAR 0xe6180020
-#define APARMBAREA 0xe6f10020
+/* DBG */
+#define DBGREG1 0xe6100020
+#define DBGREG9 0xe6100040
+/* CPGA */
+#define SYSTBCR 0xe6150024
+#define MSTPSR0 0xe6150030
+#define MSTPSR1 0xe6150038
+#define MSTPSR2 0xe6150040
+#define MSTPSR3 0xe6150048
+#define MSTPSR4 0xe615004c
+#define PLLC01STPCR 0xe61500c8
+
+/* SYSC */
#define SPDCR 0xe6180008
#define SWUCR 0xe6180014
+#define SBAR 0xe6180020
+#define WUPRMSK 0xe6180028
+#define WUPSMSK 0xe618002c
+#define WUPSMSK2 0xe6180048
#define PSTR 0xe6180080
+#define WUPSFAC 0xe6180098
+#define IRQCR 0xe618022c
+#define IRQCR2 0xe6180238
+#define IRQCR3 0xe6180244
+#define IRQCR4 0xe6180248
+#define PDNSEL 0xe6180254
+
+/* INTC */
+#define ICR1A 0xe6900000
+#define ICR2A 0xe6900004
+#define ICR3A 0xe6900008
+#define ICR4A 0xe690000c
+#define INTMSK00A 0xe6900040
+#define INTMSK10A 0xe6900044
+#define INTMSK20A 0xe6900048
+#define INTMSK30A 0xe690004c
+
+/* MFIS */
+#define SMFRAM 0xe6a70000
+
+/* AP-System Core */
+#define APARMBAREA 0xe6f10020
#define PSTR_RETRIES 100
#define PSTR_DELAY_US 10
@@ -43,6 +81,12 @@ static int pd_power_down(struct generic_pm_domain *genpd)
struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
unsigned int mask = 1 << sh7372_pd->bit_shift;
+ if (sh7372_pd->suspend)
+ sh7372_pd->suspend();
+
+ if (sh7372_pd->stay_on)
+ return 0;
+
if (__raw_readl(PSTR) & mask) {
unsigned int retry_count;
@@ -55,8 +99,9 @@ static int pd_power_down(struct generic_pm_domain *genpd)
}
}
- pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
- mask, __raw_readl(PSTR));
+ if (!sh7372_pd->no_debug)
+ pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
+ mask, __raw_readl(PSTR));
return 0;
}
@@ -68,6 +113,9 @@ static int pd_power_up(struct generic_pm_domain *genpd)
unsigned int retry_count;
int ret = 0;
+ if (sh7372_pd->stay_on)
+ goto out;
+
if (__raw_readl(PSTR) & mask)
goto out;
@@ -84,66 +132,48 @@ static int pd_power_up(struct generic_pm_domain *genpd)
if (__raw_readl(SWUCR) & mask)
ret = -EIO;
+ if (!sh7372_pd->no_debug)
+ pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
+ mask, __raw_readl(PSTR));
+
out:
- pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
- mask, __raw_readl(PSTR));
+ if (ret == 0 && sh7372_pd->resume)
+ sh7372_pd->resume();
return ret;
}
-static int pd_power_up_a3rv(struct generic_pm_domain *genpd)
+static void sh7372_a4r_suspend(void)
{
- int ret = pd_power_up(genpd);
-
- /* force A4LC on after A3RV has been requested on */
- pm_genpd_poweron(&sh7372_a4lc.genpd);
-
- return ret;
+ sh7372_intcs_suspend();
+ __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */
}
-static int pd_power_down_a3rv(struct generic_pm_domain *genpd)
+static bool pd_active_wakeup(struct device *dev)
{
- int ret = pd_power_down(genpd);
-
- /* try to power down A4LC after A3RV is requested off */
- genpd_queue_power_off_work(&sh7372_a4lc.genpd);
-
- return ret;
+ return true;
}
-static int pd_power_down_a4lc(struct generic_pm_domain *genpd)
+static bool sh7372_power_down_forbidden(struct dev_pm_domain *domain)
{
- /* only power down A4LC if A3RV is off */
- if (!(__raw_readl(PSTR) & (1 << sh7372_a3rv.bit_shift)))
- return pd_power_down(genpd);
-
- return -EBUSY;
+ return false;
}
-static bool pd_active_wakeup(struct device *dev)
-{
- return true;
-}
+struct dev_power_governor sh7372_always_on_gov = {
+ .power_down_ok = sh7372_power_down_forbidden,
+};
void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
{
struct generic_pm_domain *genpd = &sh7372_pd->genpd;
- pm_genpd_init(genpd, NULL, false);
+ pm_genpd_init(genpd, sh7372_pd->gov, false);
genpd->stop_device = pm_clk_suspend;
genpd->start_device = pm_clk_resume;
+ genpd->dev_irq_safe = true;
genpd->active_wakeup = pd_active_wakeup;
-
- if (sh7372_pd == &sh7372_a4lc) {
- genpd->power_off = pd_power_down_a4lc;
- genpd->power_on = pd_power_up;
- } else if (sh7372_pd == &sh7372_a3rv) {
- genpd->power_off = pd_power_down_a3rv;
- genpd->power_on = pd_power_up_a3rv;
- } else {
- genpd->power_off = pd_power_down;
- genpd->power_on = pd_power_up;
- }
+ genpd->power_off = pd_power_down;
+ genpd->power_on = pd_power_up;
genpd->power_on(&sh7372_pd->genpd);
}
@@ -152,11 +182,15 @@ void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
{
struct device *dev = &pdev->dev;
- if (!dev->power.subsys_data) {
- pm_clk_init(dev);
- pm_clk_add(dev, NULL);
- }
pm_genpd_add_device(&sh7372_pd->genpd, dev);
+ if (pm_clk_no_clocks(dev))
+ pm_clk_add(dev, NULL);
+}
+
+void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd,
+ struct sh7372_pm_domain *sh7372_sd)
+{
+ pm_genpd_add_subdomain(&sh7372_pd->genpd, &sh7372_sd->genpd);
}
struct sh7372_pm_domain sh7372_a4lc = {
@@ -171,6 +205,14 @@ struct sh7372_pm_domain sh7372_d4 = {
.bit_shift = 3,
};
+struct sh7372_pm_domain sh7372_a4r = {
+ .bit_shift = 5,
+ .gov = &sh7372_always_on_gov,
+ .suspend = sh7372_a4r_suspend,
+ .resume = sh7372_intcs_resume,
+ .stay_on = true,
+};
+
struct sh7372_pm_domain sh7372_a3rv = {
.bit_shift = 6,
};
@@ -179,39 +221,187 @@ struct sh7372_pm_domain sh7372_a3ri = {
.bit_shift = 8,
};
+struct sh7372_pm_domain sh7372_a3sp = {
+ .bit_shift = 11,
+ .gov = &sh7372_always_on_gov,
+ .no_debug = true,
+};
+
struct sh7372_pm_domain sh7372_a3sg = {
.bit_shift = 13,
};
#endif /* CONFIG_PM */
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
+static int sh7372_do_idle_core_standby(unsigned long unused)
+{
+ cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */
+ return 0;
+}
+
static void sh7372_enter_core_standby(void)
{
- void __iomem *smfram = (void __iomem *)SMFRAM;
+ /* set reset vector, translate 4k */
+ __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR);
+ __raw_writel(0, APARMBAREA);
- __raw_writel(0, APARMBAREA); /* translate 4k */
- __raw_writel(__pa(sh7372_cpu_resume), SBAR); /* set reset vector */
- __raw_writel(0x10, SYSTBCR); /* enable core standby */
+ /* enter sleep mode with SYSTBCR to 0x10 */
+ __raw_writel(0x10, SYSTBCR);
+ cpu_suspend(0, sh7372_do_idle_core_standby);
+ __raw_writel(0, SYSTBCR);
- __raw_writel(0, smfram + 0x3c); /* clear page table address */
+ /* disable reset vector translation */
+ __raw_writel(0, SBAR);
+}
+#endif
+
+#ifdef CONFIG_SUSPEND
+static void sh7372_enter_a3sm_common(int pllc0_on)
+{
+ /* set reset vector, translate 4k */
+ __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR);
+ __raw_writel(0, APARMBAREA);
+
+ if (pllc0_on)
+ __raw_writel(0, PLLC01STPCR);
+ else
+ __raw_writel(1 << 28, PLLC01STPCR);
+
+ __raw_writel(0, PDNSEL); /* power-down A3SM only, not A4S */
+ __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */
+ cpu_suspend(0, sh7372_do_idle_a3sm);
+ __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */
+
+ /* disable reset vector translation */
+ __raw_writel(0, SBAR);
+}
+
+static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p)
+{
+ unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4;
+ unsigned long msk, msk2;
+
+ /* check active clocks to determine potential wakeup sources */
+
+ mstpsr0 = __raw_readl(MSTPSR0);
+ if ((mstpsr0 & 0x00000003) != 0x00000003) {
+ pr_debug("sh7372 mstpsr0 0x%08lx\n", mstpsr0);
+ return 0;
+ }
+
+ mstpsr1 = __raw_readl(MSTPSR1);
+ if ((mstpsr1 & 0xff079b7f) != 0xff079b7f) {
+ pr_debug("sh7372 mstpsr1 0x%08lx\n", mstpsr1);
+ return 0;
+ }
- sh7372_cpu_suspend();
- cpu_init();
+ mstpsr2 = __raw_readl(MSTPSR2);
+ if ((mstpsr2 & 0x000741ff) != 0x000741ff) {
+ pr_debug("sh7372 mstpsr2 0x%08lx\n", mstpsr2);
+ return 0;
+ }
- /* if page table address is non-NULL then we have been powered down */
- if (__raw_readl(smfram + 0x3c)) {
- __raw_writel(__raw_readl(smfram + 0x40),
- __va(__raw_readl(smfram + 0x3c)));
+ mstpsr3 = __raw_readl(MSTPSR3);
+ if ((mstpsr3 & 0x1a60f010) != 0x1a60f010) {
+ pr_debug("sh7372 mstpsr3 0x%08lx\n", mstpsr3);
+ return 0;
+ }
- flush_tlb_all();
- set_cr(__raw_readl(smfram + 0x38));
+ mstpsr4 = __raw_readl(MSTPSR4);
+ if ((mstpsr4 & 0x00008cf0) != 0x00008cf0) {
+ pr_debug("sh7372 mstpsr4 0x%08lx\n", mstpsr4);
+ return 0;
}
- __raw_writel(0, SYSTBCR); /* disable core standby */
- __raw_writel(0, SBAR); /* disable reset vector translation */
+ msk = 0;
+ msk2 = 0;
+
+ /* make bitmaps of limited number of wakeup sources */
+
+ if ((mstpsr2 & (1 << 23)) == 0) /* SPU2 */
+ msk |= 1 << 31;
+
+ if ((mstpsr2 & (1 << 12)) == 0) /* MFI_MFIM */
+ msk |= 1 << 21;
+
+ if ((mstpsr4 & (1 << 3)) == 0) /* KEYSC */
+ msk |= 1 << 2;
+
+ if ((mstpsr1 & (1 << 24)) == 0) /* CMT0 */
+ msk |= 1 << 1;
+
+ if ((mstpsr3 & (1 << 29)) == 0) /* CMT1 */
+ msk |= 1 << 1;
+
+ if ((mstpsr4 & (1 << 0)) == 0) /* CMT2 */
+ msk |= 1 << 1;
+
+ if ((mstpsr2 & (1 << 13)) == 0) /* MFI_MFIS */
+ msk2 |= 1 << 17;
+
+ *mskp = msk;
+ *msk2p = msk2;
+
+ return 1;
+}
+
+static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p)
+{
+ u16 tmp, irqcr1, irqcr2;
+ int k;
+
+ irqcr1 = 0;
+ irqcr2 = 0;
+
+ /* convert INTCA ICR register layout to SYSC IRQCR+IRQCR2 */
+ for (k = 0; k <= 7; k++) {
+ tmp = (icr >> ((7 - k) * 4)) & 0xf;
+ irqcr1 |= (tmp & 0x03) << (k * 2);
+ irqcr2 |= (tmp >> 2) << (k * 2);
+ }
+
+ *irqcr1p = irqcr1;
+ *irqcr2p = irqcr2;
+}
+
+static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2)
+{
+ u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high;
+ unsigned long tmp;
+
+ /* read IRQ0A -> IRQ15A mask */
+ tmp = bitrev8(__raw_readb(INTMSK00A));
+ tmp |= bitrev8(__raw_readb(INTMSK10A)) << 8;
+
+ /* setup WUPSMSK from clocks and external IRQ mask */
+ msk = (~msk & 0xc030000f) | (tmp << 4);
+ __raw_writel(msk, WUPSMSK);
+
+ /* propage level/edge trigger for external IRQ 0->15 */
+ sh7372_icr_to_irqcr(__raw_readl(ICR1A), &irqcrx_low, &irqcry_low);
+ sh7372_icr_to_irqcr(__raw_readl(ICR2A), &irqcrx_high, &irqcry_high);
+ __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR);
+ __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR2);
+
+ /* read IRQ16A -> IRQ31A mask */
+ tmp = bitrev8(__raw_readb(INTMSK20A));
+ tmp |= bitrev8(__raw_readb(INTMSK30A)) << 8;
+
+ /* setup WUPSMSK2 from clocks and external IRQ mask */
+ msk2 = (~msk2 & 0x00030000) | tmp;
+ __raw_writel(msk2, WUPSMSK2);
+
+ /* propage level/edge trigger for external IRQ 16->31 */
+ sh7372_icr_to_irqcr(__raw_readl(ICR3A), &irqcrx_low, &irqcry_low);
+ sh7372_icr_to_irqcr(__raw_readl(ICR4A), &irqcrx_high, &irqcry_high);
+ __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3);
+ __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4);
}
+#endif
#ifdef CONFIG_CPU_IDLE
+
static void sh7372_cpuidle_setup(struct cpuidle_device *dev)
{
struct cpuidle_state *state;
@@ -239,9 +429,25 @@ static void sh7372_cpuidle_init(void) {}
#endif
#ifdef CONFIG_SUSPEND
+
static int sh7372_enter_suspend(suspend_state_t suspend_state)
{
- sh7372_enter_core_standby();
+ unsigned long msk, msk2;
+
+ /* check active clocks to determine potential wakeup sources */
+ if (sh7372_a3sm_valid(&msk, &msk2)) {
+
+ /* convert INTC mask and sense to SYSC mask and sense */
+ sh7372_setup_a3sm(msk, msk2);
+
+ /* enter A3SM sleep with PLLC0 off */
+ pr_debug("entering A3SM\n");
+ sh7372_enter_a3sm_common(0);
+ } else {
+ /* default to Core Standby that supports all wakeup sources */
+ pr_debug("entering Core Standby\n");
+ sh7372_enter_core_standby();
+ }
return 0;
}
@@ -253,9 +459,6 @@ static void sh7372_suspend_init(void)
static void sh7372_suspend_init(void) {}
#endif
-#define DBGREG1 0xe6100020
-#define DBGREG9 0xe6100040
-
void __init sh7372_pm_init(void)
{
/* enable DBG hardware block to kick SYSC */
@@ -263,6 +466,9 @@ void __init sh7372_pm_init(void)
__raw_writel(0x0000a501, DBGREG9);
__raw_writel(0x00000000, DBGREG1);
+ /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
+ __raw_writel(0, PDNSEL);
+
sh7372_suspend_init();
sh7372_cpuidle_init();
}
diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c
index 6ec454e1e063..bd5c6a3b8c55 100644
--- a/arch/arm/mach-shmobile/pm_runtime.c
+++ b/arch/arm/mach-shmobile/pm_runtime.c
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
+#include <linux/pm_clock.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/sh_clk.h>
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 2d9b1b1a2538..2380389e6ac5 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -30,6 +30,7 @@
#include <linux/sh_dma.h>
#include <linux/sh_intc.h>
#include <linux/sh_timer.h>
+#include <linux/pm_domain.h>
#include <mach/hardware.h>
#include <mach/sh7372.h>
#include <asm/mach-types.h>
@@ -990,9 +991,14 @@ void __init sh7372_add_standard_devices(void)
sh7372_init_pm_domain(&sh7372_a4lc);
sh7372_init_pm_domain(&sh7372_a4mp);
sh7372_init_pm_domain(&sh7372_d4);
+ sh7372_init_pm_domain(&sh7372_a4r);
sh7372_init_pm_domain(&sh7372_a3rv);
sh7372_init_pm_domain(&sh7372_a3ri);
sh7372_init_pm_domain(&sh7372_a3sg);
+ sh7372_init_pm_domain(&sh7372_a3sp);
+
+ sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv);
+ sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc);
platform_add_devices(sh7372_early_devices,
ARRAY_SIZE(sh7372_early_devices));
@@ -1003,6 +1009,25 @@ void __init sh7372_add_standard_devices(void)
sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device);
sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device);
sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &scif0_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &scif1_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &scif2_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &scif3_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &scif4_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &scif5_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &scif6_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &iic1_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &dma0_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &dma1_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &dma2_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma0_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma1_device);
+ sh7372_add_device_to_domain(&sh7372_a4r, &iic0_device);
+ sh7372_add_device_to_domain(&sh7372_a4r, &veu0_device);
+ sh7372_add_device_to_domain(&sh7372_a4r, &veu1_device);
+ sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device);
+ sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device);
+ sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device);
}
void __init sh7372_add_early_devices(void)
diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S
index d37d3ca4d18f..f3ab3c5810ea 100644
--- a/arch/arm/mach-shmobile/sleep-sh7372.S
+++ b/arch/arm/mach-shmobile/sleep-sh7372.S
@@ -30,58 +30,20 @@
*/
#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/memory.h>
#include <asm/assembler.h>
-#define SMFRAM 0xe6a70000
-
- .align
-kernel_flush:
- .word v7_flush_dcache_all
-
- .align 3
-ENTRY(sh7372_cpu_suspend)
- stmfd sp!, {r0-r12, lr} @ save registers on stack
-
- ldr r8, =SMFRAM
-
- mov r4, sp @ Store sp
- mrs r5, spsr @ Store spsr
- mov r6, lr @ Store lr
- stmia r8!, {r4-r6}
-
- mrc p15, 0, r4, c1, c0, 2 @ Coprocessor access control register
- mrc p15, 0, r5, c2, c0, 0 @ TTBR0
- mrc p15, 0, r6, c2, c0, 1 @ TTBR1
- mrc p15, 0, r7, c2, c0, 2 @ TTBCR
- stmia r8!, {r4-r7}
-
- mrc p15, 0, r4, c3, c0, 0 @ Domain access Control Register
- mrc p15, 0, r5, c10, c2, 0 @ PRRR
- mrc p15, 0, r6, c10, c2, 1 @ NMRR
- stmia r8!,{r4-r6}
-
- mrc p15, 0, r4, c13, c0, 1 @ Context ID
- mrc p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID
- mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address
- mrs r7, cpsr @ Store current cpsr
- stmia r8!, {r4-r7}
-
- mrc p15, 0, r4, c1, c0, 0 @ save control register
- stmia r8!, {r4}
-
- /*
- * jump out to kernel flush routine
- * - reuse that code is better
- * - it executes in a cached space so is faster than refetch per-block
- * - should be faster and will change with kernel
- * - 'might' have to copy address, load and jump to it
- * Flush all data from the L1 data cache before disabling
- * SCTLR.C bit.
- */
- ldr r1, kernel_flush
- mov lr, pc
- bx r1
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
+ .align 12
+ .text
+ .global sh7372_resume_core_standby_a3sm
+sh7372_resume_core_standby_a3sm:
+ ldr pc, 1f
+1: .long cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET
+ .global sh7372_do_idle_a3sm
+sh7372_do_idle_a3sm:
/*
* Clear the SCTLR.C bit to prevent further data cache
* allocation. Clearing SCTLR.C would make all the data accesses
@@ -92,10 +54,13 @@ ENTRY(sh7372_cpu_suspend)
mcr p15, 0, r0, c1, c0, 0
isb
+ /* disable L2 cache in the aux control register */
+ mrc p15, 0, r10, c1, c0, 1
+ bic r10, r10, #2
+ mcr p15, 0, r10, c1, c0, 1
+
/*
- * Invalidate L1 data cache. Even though only invalidate is
- * necessary exported flush API is used here. Doing clean
- * on already clean cache would be almost NOP.
+ * Invalidate data cache again.
*/
ldr r1, kernel_flush
blx r1
@@ -115,146 +80,16 @@ ENTRY(sh7372_cpu_suspend)
dsb
dmb
-/*
- * ===================================
- * == WFI instruction => Enter idle ==
- * ===================================
- */
- wfi @ wait for interrupt
-
-/*
- * ===================================
- * == Resume path for non-OFF modes ==
- * ===================================
- */
- mrc p15, 0, r0, c1, c0, 0
- tst r0, #(1 << 2) @ Check C bit enabled?
- orreq r0, r0, #(1 << 2) @ Enable the C bit if cleared
- mcreq p15, 0, r0, c1, c0, 0
- isb
-
-/*
- * ===================================
- * == Exit point from non-OFF modes ==
- * ===================================
- */
- ldmfd sp!, {r0-r12, pc} @ restore regs and return
+#define SPDCR 0xe6180008
+#define A3SM (1 << 12)
- .pool
+ /* A3SM power down */
+ ldr r0, =SPDCR
+ ldr r1, =A3SM
+ str r1, [r0]
+1:
+ b 1b
- .align 12
- .text
- .global sh7372_cpu_resume
-sh7372_cpu_resume:
-
- mov r1, #0
- /*
- * Invalidate all instruction caches to PoU
- * and flush branch target cache
- */
- mcr p15, 0, r1, c7, c5, 0
-
- ldr r3, =SMFRAM
-
- ldmia r3!, {r4-r6}
- mov sp, r4 @ Restore sp
- msr spsr_cxsf, r5 @ Restore spsr
- mov lr, r6 @ Restore lr
-
- ldmia r3!, {r4-r7}
- mcr p15, 0, r4, c1, c0, 2 @ Coprocessor access Control Register
- mcr p15, 0, r5, c2, c0, 0 @ TTBR0
- mcr p15, 0, r6, c2, c0, 1 @ TTBR1
- mcr p15, 0, r7, c2, c0, 2 @ TTBCR
-
- ldmia r3!,{r4-r6}
- mcr p15, 0, r4, c3, c0, 0 @ Domain access Control Register
- mcr p15, 0, r5, c10, c2, 0 @ PRRR
- mcr p15, 0, r6, c10, c2, 1 @ NMRR
-
- ldmia r3!,{r4-r7}
- mcr p15, 0, r4, c13, c0, 1 @ Context ID
- mcr p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID
- mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address
- msr cpsr, r7 @ store cpsr
-
- /* Starting to enable MMU here */
- mrc p15, 0, r7, c2, c0, 2 @ Read TTBRControl
- /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */
- and r7, #0x7
- cmp r7, #0x0
- beq usettbr0
-ttbr_error:
- /*
- * More work needs to be done to support N[0:2] value other than 0
- * So looping here so that the error can be detected
- */
- b ttbr_error
-
- .align
-cache_pred_disable_mask:
- .word 0xFFFFE7FB
-ttbrbit_mask:
- .word 0xFFFFC000
-table_index_mask:
- .word 0xFFF00000
-table_entry:
- .word 0x00000C02
-usettbr0:
-
- mrc p15, 0, r2, c2, c0, 0
- ldr r5, ttbrbit_mask
- and r2, r5
- mov r4, pc
- ldr r5, table_index_mask
- and r4, r5 @ r4 = 31 to 20 bits of pc
- /* Extract the value to be written to table entry */
- ldr r6, table_entry
- /* r6 has the value to be written to table entry */
- add r6, r6, r4
- /* Getting the address of table entry to modify */
- lsr r4, #18
- /* r2 has the location which needs to be modified */
- add r2, r4
- ldr r4, [r2]
- str r6, [r2] /* modify the table entry */
-
- mov r7, r6
- mov r5, r2
- mov r6, r4
- /* r5 = original page table address */
- /* r6 = original page table data */
-
- mov r0, #0
- mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer
- mcr p15, 0, r0, c7, c5, 6 @ Invalidate branch predictor array
- mcr p15, 0, r0, c8, c5, 0 @ Invalidate instruction TLB
- mcr p15, 0, r0, c8, c6, 0 @ Invalidate data TLB
-
- /*
- * Restore control register. This enables the MMU.
- * The caches and prediction are not enabled here, they
- * will be enabled after restoring the MMU table entry.
- */
- ldmia r3!, {r4}
- stmia r3!, {r5} /* save original page table address */
- stmia r3!, {r6} /* save original page table data */
- stmia r3!, {r7} /* save modified page table data */
-
- ldr r2, cache_pred_disable_mask
- and r4, r2
- mcr p15, 0, r4, c1, c0, 0
- dsb
- isb
-
- ldr r0, =restoremmu_on
- bx r0
-
-/*
- * ==============================
- * == Exit point from OFF mode ==
- * ==============================
- */
-restoremmu_on:
-
- ldmfd sp!, {r0-r12, pc} @ restore regs and return
+kernel_flush:
+ .word v7_flush_dcache_all
+#endif
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 3ffdbc92ba82..be1ade76ccc8 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -74,6 +74,8 @@ void __cpuinit sh73a0_secondary_init(unsigned int cpu)
int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
{
+ cpu = cpu_logical_map(cpu);
+
/* enable cache coherency */
modify_scu_cpu_psr(0, 3 << (cpu * 8));
@@ -87,6 +89,8 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
void __init sh73a0_smp_prepare_cpus(void)
{
+ int cpu = cpu_logical_map(0);
+
scu_enable(scu_base_addr());
/* Map the reset vector (in headsmp.S) */
@@ -94,5 +98,5 @@ void __init sh73a0_smp_prepare_cpus(void)
__raw_writel(__pa(shmobile_secondary_vector), __io(SBAR));
/* enable cache coherency on CPU0 */
- modify_scu_cpu_psr(0, 3 << (0 * 8));
+ modify_scu_cpu_psr(0, 3 << (cpu * 8));
}
diff --git a/arch/arm/mach-spear3xx/Makefile.boot b/arch/arm/mach-spear3xx/Makefile.boot
index 7a1f3c0eadb8..4674a4c221db 100644
--- a/arch/arm/mach-spear3xx/Makefile.boot
+++ b/arch/arm/mach-spear3xx/Makefile.boot
@@ -1,3 +1,3 @@
-zreladdr-y := 0x00008000
+zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-spear3xx/include/mach/memory.h b/arch/arm/mach-spear3xx/include/mach/memory.h
deleted file mode 100644
index 51735221ea19..000000000000
--- a/arch/arm/mach-spear3xx/include/mach/memory.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/memory.h
- *
- * Memory map for SPEAr3xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-#include <plat/memory.h>
-
-#endif /* __MACH_MEMORY_H */
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 69006f694220..a5ff98eed1db 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -64,7 +64,7 @@ static void __init spear300_evb_init(void)
}
MACHINE_START(SPEAR300, "ST-SPEAR300-EVB")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = spear3xx_map_io,
.init_irq = spear3xx_init_irq,
.timer = &spear3xx_timer,
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index c8684ce1f9b3..45d180d59362 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -70,7 +70,7 @@ static void __init spear310_evb_init(void)
}
MACHINE_START(SPEAR310, "ST-SPEAR310-EVB")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = spear3xx_map_io,
.init_irq = spear3xx_init_irq,
.timer = &spear3xx_timer,
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index a12b353940d6..22879848d73a 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -68,7 +68,7 @@ static void __init spear320_evb_init(void)
}
MACHINE_START(SPEAR320, "ST-SPEAR320-EVB")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = spear3xx_map_io,
.init_irq = spear3xx_init_irq,
.timer = &spear3xx_timer,
diff --git a/arch/arm/mach-spear6xx/Makefile.boot b/arch/arm/mach-spear6xx/Makefile.boot
index 7a1f3c0eadb8..4674a4c221db 100644
--- a/arch/arm/mach-spear6xx/Makefile.boot
+++ b/arch/arm/mach-spear6xx/Makefile.boot
@@ -1,3 +1,3 @@
-zreladdr-y := 0x00008000
+zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-spear6xx/include/mach/memory.h b/arch/arm/mach-spear6xx/include/mach/memory.h
deleted file mode 100644
index 781f088fc228..000000000000
--- a/arch/arm/mach-spear6xx/include/mach/memory.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/memory.h
- *
- * Memory map for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-#include <plat/memory.h>
-
-#endif /* __MACH_MEMORY_H */
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index f19cefe91a2b..8238fe38e713 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -43,7 +43,7 @@ static void __init spear600_evb_init(void)
}
MACHINE_START(SPEAR600, "ST-SPEAR600-EVB")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = spear6xx_map_io,
.init_irq = spear6xx_init_irq,
.timer = &spear6xx_timer,
diff --git a/arch/arm/mach-tcc8k/Makefile.boot b/arch/arm/mach-tcc8k/Makefile.boot
index f135c9deae10..5e02d4156b04 100644
--- a/arch/arm/mach-tcc8k/Makefile.boot
+++ b/arch/arm/mach-tcc8k/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x20008000
+ zreladdr-y += 0x20008000
params_phys-y := 0x20000100
initrd_phys-y := 0x20800000
diff --git a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
index 4cb3c2dd905c..777a5bb9eed2 100644
--- a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
+++ b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
@@ -73,7 +73,7 @@ static void __init tcc8k_map_io(void)
}
MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board")
- .boot_params = PLAT_PHYS_OFFSET + 0x00000100,
+ .atag_offset = 0x100,
.map_io = tcc8k_map_io,
.init_irq = tcc8k_init_irq,
.init_machine = tcc8k_init,
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index d82ebab50e11..91aff7cb8284 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -69,6 +69,12 @@ config MACH_WARIO
help
Support for the Wario version of Seaboard
+config MACH_VENTANA
+ bool "Ventana board"
+ select MACH_TEGRA_DT
+ help
+ Support for the nVidia Ventana development platform
+
choice
prompt "Low-level debug console UART"
default TEGRA_DEBUG_UART_NONE
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index f11b9100114a..91a07e187208 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -31,6 +31,7 @@ obj-${CONFIG_MACH_SEABOARD} += board-seaboard-pinmux.o
obj-${CONFIG_MACH_TEGRA_DT} += board-dt.o
obj-${CONFIG_MACH_TEGRA_DT} += board-harmony-pinmux.o
+obj-${CONFIG_MACH_TEGRA_DT} += board-seaboard-pinmux.o
obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice.o
obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice-pinmux.o
diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot
index 428ad122be03..bd12c9fb81e8 100644
--- a/arch/arm/mach-tegra/Makefile.boot
+++ b/arch/arm/mach-tegra/Makefile.boot
@@ -1,6 +1,7 @@
-zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00008000
+zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC) += 0x00008000
params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00000100
initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00800000
dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
+dtb-$(CONFIG_MACH_VENTANA) += tegra-ventana.dtb
diff --git a/arch/arm/mach-tegra/board-dt.c b/arch/arm/mach-tegra/board-dt.c
index 9f47e04446f3..d368f8dafcfd 100644
--- a/arch/arm/mach-tegra/board-dt.c
+++ b/arch/arm/mach-tegra/board-dt.c
@@ -47,7 +47,7 @@
void harmony_pinmux_init(void);
void seaboard_pinmux_init(void);
-
+void ventana_pinmux_init(void);
struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
@@ -80,9 +80,19 @@ static struct of_device_id tegra_dt_gic_match[] __initdata = {
{}
};
+static struct {
+ char *machine;
+ void (*init)(void);
+} pinmux_configs[] = {
+ { "nvidia,harmony", harmony_pinmux_init },
+ { "nvidia,seaboard", seaboard_pinmux_init },
+ { "nvidia,ventana", ventana_pinmux_init },
+};
+
static void __init tegra_dt_init(void)
{
struct device_node *node;
+ int i;
node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
TEGRA_ARM_INT_DIST_BASE);
@@ -91,10 +101,15 @@ static void __init tegra_dt_init(void)
tegra_clk_init_from_table(tegra_dt_clk_init_table);
- if (of_machine_is_compatible("nvidia,harmony"))
- harmony_pinmux_init();
- else if (of_machine_is_compatible("nvidia,seaboard"))
- seaboard_pinmux_init();
+ for (i = 0; i < ARRAY_SIZE(pinmux_configs); i++) {
+ if (of_machine_is_compatible(pinmux_configs[i].machine)) {
+ pinmux_configs[i].init();
+ break;
+ }
+ }
+
+ WARN(i == ARRAY_SIZE(pinmux_configs),
+ "Unknown platform! Pinmuxing not initialized\n");
/*
* Finished with the static registrations now; fill in the missing
@@ -106,6 +121,7 @@ static void __init tegra_dt_init(void)
static const char * tegra_dt_board_compat[] = {
"nvidia,harmony",
"nvidia,seaboard",
+ "nvidia,ventana",
NULL
};
diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c
index 9c27b95b8d86..6db7d699ef1c 100644
--- a/arch/arm/mach-tegra/board-harmony-pcie.c
+++ b/arch/arm/mach-tegra/board-harmony-pcie.c
@@ -24,12 +24,10 @@
#include <mach/pinmux.h>
#include "board.h"
+#include "board-harmony.h"
#ifdef CONFIG_TEGRA_PCI
-/* GPIO 3 of the PMIC */
-#define EN_VDD_1V05_GPIO (TEGRA_NR_GPIOS + 2)
-
static int __init harmony_pcie_init(void)
{
struct regulator *regulator = NULL;
@@ -38,11 +36,11 @@ static int __init harmony_pcie_init(void)
if (!machine_is_harmony())
return 0;
- err = gpio_request(EN_VDD_1V05_GPIO, "EN_VDD_1V05");
+ err = gpio_request(TEGRA_GPIO_EN_VDD_1V05_GPIO, "EN_VDD_1V05");
if (err)
return err;
- gpio_direction_output(EN_VDD_1V05_GPIO, 1);
+ gpio_direction_output(TEGRA_GPIO_EN_VDD_1V05_GPIO, 1);
regulator = regulator_get(NULL, "pex_clk");
if (IS_ERR_OR_NULL(regulator))
@@ -68,7 +66,7 @@ err_pcie:
regulator_disable(regulator);
regulator_put(regulator);
err_reg:
- gpio_free(EN_VDD_1V05_GPIO);
+ gpio_free(TEGRA_GPIO_EN_VDD_1V05_GPIO);
return err;
}
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c
index 4d63e2e97a8d..e99b45618cd0 100644
--- a/arch/arm/mach-tegra/board-harmony-pinmux.c
+++ b/arch/arm/mach-tegra/board-harmony-pinmux.c
@@ -20,6 +20,7 @@
#include "gpio-names.h"
#include "board-harmony.h"
+#include "devices.h"
static struct tegra_pingroup_config harmony_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
@@ -140,6 +141,11 @@ static struct tegra_pingroup_config harmony_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
{ .gpio = TEGRA_GPIO_SD2_WP, .enable = true },
@@ -155,6 +161,8 @@ static struct tegra_gpio_table gpio_table[] = {
void harmony_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c
index 5ad8b2f94f8d..21d1285731b3 100644
--- a/arch/arm/mach-tegra/board-harmony-power.c
+++ b/arch/arm/mach-tegra/board-harmony-power.c
@@ -18,10 +18,11 @@
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
-
+#include <linux/io.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/tps6586x.h>
+#include <mach/iomap.h>
#include <mach/irqs.h>
#include "board-harmony.h"
@@ -113,6 +114,16 @@ static struct i2c_board_info __initdata harmony_regulators[] = {
int __init harmony_regulator_init(void)
{
+ void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+ u32 pmc_ctrl;
+
+ /*
+ * Configure the power management controller to trigger PMU
+ * interrupts when low
+ */
+ pmc_ctrl = readl(pmc + PMC_CTRL);
+ writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
+
i2c_register_board_info(3, harmony_regulators, 1);
return 0;
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index 846cd7d69e3e..f0bdc5e3fe52 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -49,7 +49,8 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.membase = IO_ADDRESS(TEGRA_UARTD_BASE),
.mapbase = TEGRA_UARTD_BASE,
.irq = INT_UARTD,
- .flags = UPF_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+ .type = PORT_TEGRA,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
@@ -117,14 +118,15 @@ static struct platform_device *harmony_devices[] __initdata = {
&tegra_sdhci_device1,
&tegra_sdhci_device2,
&tegra_sdhci_device4,
+ &tegra_ehci3_device,
&tegra_i2s_device1,
&tegra_das_device,
&tegra_pcm_device,
&harmony_audio_device,
};
-static void __init tegra_harmony_fixup(struct machine_desc *desc,
- struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init tegra_harmony_fixup(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
mi->nr_banks = 2;
mi->bank[0].start = PHYS_OFFSET;
@@ -140,6 +142,7 @@ static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = {
{ "pll_a_out0", "pll_a", 11289600, true },
{ "cdev1", NULL, 0, true },
{ "i2s1", "pll_a_out0", 11289600, false},
+ { "usb3", "clk_m", 12000000, true },
{ NULL, NULL, 0, 0},
};
@@ -179,7 +182,7 @@ static void __init tegra_harmony_init(void)
}
MACHINE_START(HARMONY, "harmony")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.fixup = tegra_harmony_fixup,
.map_io = tegra_map_common_io,
.init_early = tegra_init_early,
diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h
index d85142edaf6b..139d96c93843 100644
--- a/arch/arm/mach-tegra/board-harmony.h
+++ b/arch/arm/mach-tegra/board-harmony.h
@@ -17,6 +17,8 @@
#ifndef _MACH_TEGRA_BOARD_HARMONY_H
#define _MACH_TEGRA_BOARD_HARMONY_H
+#include <mach/gpio-tegra.h>
+
#define HARMONY_GPIO_TPS6586X(_x_) (TEGRA_NR_GPIOS + (_x_))
#define HARMONY_GPIO_WM8903(_x_) (HARMONY_GPIO_TPS6586X(4) + (_x_))
@@ -31,6 +33,7 @@
#define TEGRA_GPIO_HP_DET TEGRA_GPIO_PW2
#define TEGRA_GPIO_INT_MIC_EN TEGRA_GPIO_PX0
#define TEGRA_GPIO_EXT_MIC_EN TEGRA_GPIO_PX1
+#define TEGRA_GPIO_EN_VDD_1V05_GPIO HARMONY_GPIO_TPS6586X(2)
void harmony_pinmux_init(void);
int harmony_regulator_init(void);
diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c
index bdd2627dd87b..fb20894862b0 100644
--- a/arch/arm/mach-tegra/board-paz00-pinmux.c
+++ b/arch/arm/mach-tegra/board-paz00-pinmux.c
@@ -20,6 +20,7 @@
#include "gpio-names.h"
#include "board-paz00.h"
+#include "devices.h"
static struct tegra_pingroup_config paz00_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
@@ -140,15 +141,25 @@ static struct tegra_pingroup_config paz00_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD1_CD, .enable = true },
{ .gpio = TEGRA_GPIO_SD1_WP, .enable = true },
{ .gpio = TEGRA_GPIO_SD1_POWER, .enable = true },
{ .gpio = TEGRA_ULPI_RST, .enable = true },
+ { .gpio = TEGRA_WIFI_PWRN, .enable = true },
+ { .gpio = TEGRA_WIFI_RST, .enable = true },
+ { .gpio = TEGRA_WIFI_LED, .enable = true },
};
void paz00_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index ea2f79c9879b..55c55ba89f1e 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -26,6 +26,8 @@
#include <linux/pda_power.h>
#include <linux/io.h>
#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/rfkill-gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -35,7 +37,6 @@
#include <mach/iomap.h>
#include <mach/irqs.h>
#include <mach/sdhci.h>
-#include <mach/gpio.h>
#include "board.h"
#include "board-paz00.h"
@@ -45,10 +46,22 @@
static struct plat_serial8250_port debug_uart_platform_data[] = {
{
+ /* serial port on JP1 */
+ .membase = IO_ADDRESS(TEGRA_UARTA_BASE),
+ .mapbase = TEGRA_UARTA_BASE,
+ .irq = INT_UARTA,
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+ .type = PORT_TEGRA,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = 216000000,
+ }, {
+ /* serial port on mini-pcie */
.membase = IO_ADDRESS(TEGRA_UARTD_BASE),
.mapbase = TEGRA_UARTD_BASE,
.irq = INT_UARTD,
- .flags = UPF_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+ .type = PORT_TEGRA,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
@@ -65,10 +78,48 @@ static struct platform_device debug_uart = {
},
};
+static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
+ .name = "wifi_rfkill",
+ .reset_gpio = TEGRA_WIFI_RST,
+ .shutdown_gpio = TEGRA_WIFI_PWRN,
+ .type = RFKILL_TYPE_WLAN,
+};
+
+static struct platform_device wifi_rfkill_device = {
+ .name = "rfkill_gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &wifi_rfkill_platform_data,
+ },
+};
+
+static struct gpio_led gpio_leds[] = {
+ {
+ .name = "wifi-led",
+ .default_trigger = "rfkill0",
+ .gpio = TEGRA_WIFI_LED,
+ },
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+ .leds = gpio_leds,
+ .num_leds = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_led_info,
+ },
+};
+
static struct platform_device *paz00_devices[] __initdata = {
&debug_uart,
- &tegra_sdhci_device1,
&tegra_sdhci_device4,
+ &tegra_sdhci_device1,
+ &wifi_rfkill_device,
+ &leds_gpio,
};
static void paz00_i2c_init(void)
@@ -84,8 +135,8 @@ static void paz00_usb_init(void)
platform_device_register(&tegra_ehci3_device);
}
-static void __init tegra_paz00_fixup(struct machine_desc *desc,
- struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init tegra_paz00_fixup(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
mi->nr_banks = 1;
mi->bank[0].start = PHYS_OFFSET;
@@ -94,7 +145,14 @@ static void __init tegra_paz00_fixup(struct machine_desc *desc,
static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
/* name parent rate enabled */
+ { "uarta", "pll_p", 216000000, true },
{ "uartd", "pll_p", 216000000, true },
+
+ { "pll_p_out4", "pll_p", 24000000, true },
+ { "usbd", "clk_m", 12000000, false },
+ { "usb2", "clk_m", 12000000, false },
+ { "usb3", "clk_m", 12000000, false },
+
{ NULL, NULL, 0, 0},
};
@@ -127,7 +185,7 @@ static void __init tegra_paz00_init(void)
}
MACHINE_START(PAZ00, "Toshiba AC100 / Dynabook AZ")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.fixup = tegra_paz00_fixup,
.map_io = tegra_map_common_io,
.init_early = tegra_init_early,
diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h
index d4ff39ddaeb3..8aff06eb58c3 100644
--- a/arch/arm/mach-tegra/board-paz00.h
+++ b/arch/arm/mach-tegra/board-paz00.h
@@ -17,11 +17,21 @@
#ifndef _MACH_TEGRA_BOARD_PAZ00_H
#define _MACH_TEGRA_BOARD_PAZ00_H
+#include <mach/gpio-tegra.h>
+
+/* SDCARD */
#define TEGRA_GPIO_SD1_CD TEGRA_GPIO_PV5
#define TEGRA_GPIO_SD1_WP TEGRA_GPIO_PH1
#define TEGRA_GPIO_SD1_POWER TEGRA_GPIO_PT3
+
+/* ULPI */
#define TEGRA_ULPI_RST TEGRA_GPIO_PV0
+/* WIFI */
+#define TEGRA_WIFI_PWRN TEGRA_GPIO_PK5
+#define TEGRA_WIFI_RST TEGRA_GPIO_PD1
+#define TEGRA_WIFI_LED TEGRA_GPIO_PD0
+
void paz00_pinmux_init(void);
#endif
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
index 0bda495e9742..fbce31daa3c9 100644
--- a/arch/arm/mach-tegra/board-seaboard-pinmux.c
+++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2010 NVIDIA Corporation
+ * Copyright (C) 2010,2011 NVIDIA Corporation
+ * Copyright (C) 2011 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -21,6 +22,7 @@
#include "gpio-names.h"
#include "board-seaboard.h"
+#include "devices.h"
#define DEFAULT_DRIVE(_name) \
{ \
@@ -49,7 +51,7 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
{TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DDC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
@@ -133,7 +135,7 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
{TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_SPIF, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
@@ -157,24 +159,83 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static __initdata struct tegra_pingroup_config ventana_pinmux[] = {
+ {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_DDC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_DTA, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_DTB, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_DTC, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_DTD, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_GMD, TEGRA_MUX_SFLASH, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_LPW0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LPW2, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LSC1, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LSCK, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_LSDA, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_PTA, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SLXK, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
-
-static struct tegra_gpio_table gpio_table[] = {
+static struct tegra_gpio_table common_gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
{ .gpio = TEGRA_GPIO_SD2_WP, .enable = true },
{ .gpio = TEGRA_GPIO_SD2_POWER, .enable = true },
{ .gpio = TEGRA_GPIO_LIDSWITCH, .enable = true },
{ .gpio = TEGRA_GPIO_POWERKEY, .enable = true },
{ .gpio = TEGRA_GPIO_ISL29018_IRQ, .enable = true },
+ { .gpio = TEGRA_GPIO_CDC_IRQ, .enable = true },
+ { .gpio = TEGRA_GPIO_USB1, .enable = true },
};
-void __init seaboard_pinmux_init(void)
+static void __init update_pinmux(struct tegra_pingroup_config *newtbl, int size)
+{
+ int i, j;
+ struct tegra_pingroup_config *new_pingroup, *base_pingroup;
+
+ /* Update base seaboard pinmux table with secondary board
+ * specific pinmux table table.
+ */
+ for (i = 0; i < size; i++) {
+ new_pingroup = &newtbl[i];
+ for (j = 0; j < ARRAY_SIZE(seaboard_pinmux); j++) {
+ base_pingroup = &seaboard_pinmux[j];
+ if (new_pingroup->pingroup == base_pingroup->pingroup) {
+ *base_pingroup = *new_pingroup;
+ break;
+ }
+ }
+ }
+}
+
+void __init seaboard_common_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
tegra_drive_pinmux_config_table(seaboard_drive_pinmux,
ARRAY_SIZE(seaboard_drive_pinmux));
- tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
+ tegra_gpio_config(common_gpio_table, ARRAY_SIZE(common_gpio_table));
+}
+
+void __init seaboard_pinmux_init(void)
+{
+ seaboard_common_pinmux_init();
}
+
+void __init ventana_pinmux_init(void)
+{
+ update_pinmux(ventana_pinmux, ARRAY_SIZE(ventana_pinmux));
+ seaboard_common_pinmux_init();
+}
+
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
index 56cbabf6aa68..bf13ea355efc 100644
--- a/arch/arm/mach-tegra/board-seaboard.c
+++ b/arch/arm/mach-tegra/board-seaboard.c
@@ -25,9 +25,12 @@
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
+#include <sound/wm8903.h>
+
#include <mach/iomap.h>
#include <mach/irqs.h>
#include <mach/sdhci.h>
+#include <mach/tegra_wm8903_pdata.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -41,7 +44,8 @@
static struct plat_serial8250_port debug_uart_platform_data[] = {
{
/* Memory and IRQ filled in before registration */
- .flags = UPF_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+ .type = PORT_TEGRA,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
@@ -62,6 +66,12 @@ static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = {
/* name parent rate enabled */
{ "uartb", "pll_p", 216000000, true},
{ "uartd", "pll_p", 216000000, true},
+ { "pll_a", "pll_p_out1", 56448000, true },
+ { "pll_a_out0", "pll_a", 11289600, true },
+ { "cdev1", NULL, 0, true },
+ { "i2s1", "pll_a_out0", 11289600, false},
+ { "usbd", "clk_m", 12000000, true},
+ { "usb3", "clk_m", 12000000, true},
{ NULL, NULL, 0, 0},
};
@@ -117,6 +127,22 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = {
.is_8bit = 1,
};
+static struct tegra_wm8903_platform_data seaboard_audio_pdata = {
+ .gpio_spkr_en = TEGRA_GPIO_SPKR_EN,
+ .gpio_hp_det = TEGRA_GPIO_HP_DET,
+ .gpio_hp_mute = -1,
+ .gpio_int_mic_en = -1,
+ .gpio_ext_mic_en = -1,
+};
+
+static struct platform_device seaboard_audio_device = {
+ .name = "tegra-snd-wm8903",
+ .id = 0,
+ .dev = {
+ .platform_data = &seaboard_audio_pdata,
+ },
+};
+
static struct platform_device *seaboard_devices[] __initdata = {
&debug_uart,
&tegra_pmu_device,
@@ -124,6 +150,10 @@ static struct platform_device *seaboard_devices[] __initdata = {
&tegra_sdhci_device3,
&tegra_sdhci_device1,
&seaboard_gpio_keys_device,
+ &tegra_i2s_device1,
+ &tegra_das_device,
+ &tegra_pcm_device,
+ &seaboard_audio_device,
};
static struct i2c_board_info __initdata isl29018_device = {
@@ -135,12 +165,56 @@ static struct i2c_board_info __initdata adt7461_device = {
I2C_BOARD_INFO("adt7461", 0x4c),
};
+static struct wm8903_platform_data wm8903_pdata = {
+ .irq_active_low = 0,
+ .micdet_cfg = 0,
+ .micdet_delay = 100,
+ .gpio_base = SEABOARD_GPIO_WM8903(0),
+ .gpio_cfg = {
+ WM8903_GPIO_NO_CONFIG,
+ WM8903_GPIO_NO_CONFIG,
+ 0,
+ WM8903_GPIO_NO_CONFIG,
+ WM8903_GPIO_NO_CONFIG,
+ },
+};
+
+static struct i2c_board_info __initdata wm8903_device = {
+ I2C_BOARD_INFO("wm8903", 0x1a),
+ .platform_data = &wm8903_pdata,
+ .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
+};
+
+static int seaboard_ehci_init(void)
+{
+ int gpio_status;
+
+ gpio_status = gpio_request(TEGRA_GPIO_USB1, "VBUS_USB1");
+ if (gpio_status < 0) {
+ pr_err("VBUS_USB1 request GPIO FAILED\n");
+ WARN_ON(1);
+ }
+
+ gpio_status = gpio_direction_output(TEGRA_GPIO_USB1, 1);
+ if (gpio_status < 0) {
+ pr_err("VBUS_USB1 request GPIO DIRECTION FAILED\n");
+ WARN_ON(1);
+ }
+ gpio_set_value(TEGRA_GPIO_USB1, 1);
+
+ platform_device_register(&tegra_ehci1_device);
+ platform_device_register(&tegra_ehci3_device);
+
+ return 0;
+}
+
static void __init seaboard_i2c_init(void)
{
gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018");
gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ);
i2c_register_board_info(0, &isl29018_device, 1);
+ i2c_register_board_info(0, &wm8903_device, 1);
i2c_register_board_info(3, &adt7461_device, 1);
@@ -161,6 +235,8 @@ static void __init seaboard_common_init(void)
tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices));
+
+ seaboard_ehci_init();
}
static void __init tegra_seaboard_init(void)
@@ -182,6 +258,9 @@ static void __init tegra_kaen_init(void)
debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
debug_uart_platform_data[0].irq = INT_UARTB;
+ seaboard_audio_pdata.gpio_hp_mute = TEGRA_GPIO_KAEN_HP_MUTE;
+ tegra_gpio_enable(TEGRA_GPIO_KAEN_HP_MUTE);
+
seaboard_common_init();
seaboard_i2c_init();
@@ -201,7 +280,7 @@ static void __init tegra_wario_init(void)
MACHINE_START(SEABOARD, "seaboard")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = tegra_map_common_io,
.init_early = tegra_init_early,
.init_irq = tegra_init_irq,
@@ -210,7 +289,7 @@ MACHINE_START(SEABOARD, "seaboard")
MACHINE_END
MACHINE_START(KAEN, "kaen")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = tegra_map_common_io,
.init_early = tegra_init_early,
.init_irq = tegra_init_irq,
@@ -219,7 +298,7 @@ MACHINE_START(KAEN, "kaen")
MACHINE_END
MACHINE_START(WARIO, "wario")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = tegra_map_common_io,
.init_early = tegra_init_early,
.init_irq = tegra_init_irq,
diff --git a/arch/arm/mach-tegra/board-seaboard.h b/arch/arm/mach-tegra/board-seaboard.h
index d8415e1a8434..4c45d4ca3c49 100644
--- a/arch/arm/mach-tegra/board-seaboard.h
+++ b/arch/arm/mach-tegra/board-seaboard.h
@@ -17,6 +17,11 @@
#ifndef _MACH_TEGRA_BOARD_SEABOARD_H
#define _MACH_TEGRA_BOARD_SEABOARD_H
+#include <mach/gpio-tegra.h>
+
+#define SEABOARD_GPIO_TPS6586X(_x_) (TEGRA_NR_GPIOS + (_x_))
+#define SEABOARD_GPIO_WM8903(_x_) (SEABOARD_GPIO_TPS6586X(4) + (_x_))
+
#define TEGRA_GPIO_SD2_CD TEGRA_GPIO_PI5
#define TEGRA_GPIO_SD2_WP TEGRA_GPIO_PH1
#define TEGRA_GPIO_SD2_POWER TEGRA_GPIO_PI6
@@ -31,10 +36,11 @@
#define TEGRA_GPIO_MAGNETOMETER TEGRA_GPIO_PN5
#define TEGRA_GPIO_ISL29018_IRQ TEGRA_GPIO_PZ2
#define TEGRA_GPIO_AC_ONLINE TEGRA_GPIO_PV3
-
-#define TPS_GPIO_BASE TEGRA_NR_GPIOS
-
-#define TPS_GPIO_WWAN_PWR (TPS_GPIO_BASE + 2)
+#define TEGRA_GPIO_WWAN_PWR SEABOARD_GPIO_TPS6586X(2)
+#define TEGRA_GPIO_CDC_IRQ TEGRA_GPIO_PX3
+#define TEGRA_GPIO_SPKR_EN SEABOARD_GPIO_WM8903(2)
+#define TEGRA_GPIO_HP_DET TEGRA_GPIO_PX1
+#define TEGRA_GPIO_KAEN_HP_MUTE TEGRA_GPIO_PA5
void seaboard_pinmux_init(void);
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
index 47c596cdbf32..4969dd28a04c 100644
--- a/arch/arm/mach-tegra/board-trimslice-pinmux.c
+++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c
@@ -13,15 +13,15 @@
* GNU General Public License for more details.
*
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <mach/pinmux.h>
-#include <mach/gpio.h>
#include "gpio-names.h"
#include "board-trimslice.h"
+#include "devices.h"
static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
@@ -142,6 +142,11 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true }, /* mmc4 cd */
{ .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true }, /* mmc4 wp */
@@ -152,6 +157,7 @@ static struct tegra_gpio_table gpio_table[] = {
void __init trimslice_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
}
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
index 89a6d2adc1de..1a6617b7806f 100644
--- a/arch/arm/mach-tegra/board-trimslice.c
+++ b/arch/arm/mach-tegra/board-trimslice.c
@@ -32,7 +32,6 @@
#include <mach/iomap.h>
#include <mach/sdhci.h>
-#include <mach/gpio.h>
#include "board.h"
#include "clock.h"
@@ -46,7 +45,8 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
.membase = IO_ADDRESS(TEGRA_UARTA_BASE),
.mapbase = TEGRA_UARTA_BASE,
.irq = INT_UARTA,
- .flags = UPF_BOOT_AUTOCONF,
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+ .type = PORT_TEGRA,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
@@ -126,8 +126,8 @@ static void trimslice_usb_init(void)
platform_device_register(&tegra_ehci1_device);
}
-static void __init tegra_trimslice_fixup(struct machine_desc *desc,
- struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init tegra_trimslice_fixup(struct tag *tags, char **cmdline,
+ struct meminfo *mi)
{
mi->nr_banks = 2;
mi->bank[0].start = PHYS_OFFSET;
@@ -171,7 +171,7 @@ static void __init tegra_trimslice_init(void)
}
MACHINE_START(TRIMSLICE, "trimslice")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.fixup = tegra_trimslice_fixup,
.map_io = tegra_map_common_io,
.init_early = tegra_init_early,
diff --git a/arch/arm/mach-tegra/board-trimslice.h b/arch/arm/mach-tegra/board-trimslice.h
index 7a7dee86b4da..50f128d87779 100644
--- a/arch/arm/mach-tegra/board-trimslice.h
+++ b/arch/arm/mach-tegra/board-trimslice.h
@@ -17,6 +17,8 @@
#ifndef _MACH_TEGRA_BOARD_TRIMSLICE_H
#define _MACH_TEGRA_BOARD_TRIMSLICE_H
+#include <mach/gpio-tegra.h>
+
#define TRIMSLICE_GPIO_SD4_CD TEGRA_GPIO_PP1 /* mmc4 cd */
#define TRIMSLICE_GPIO_SD4_WP TEGRA_GPIO_PP2 /* mmc4 wp */
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index d5e3f89b05af..690b888be506 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -61,7 +61,7 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
{ NULL, NULL, 0, 0},
};
-void __init tegra_init_cache(void)
+static void __init tegra_init_cache(void)
{
#ifdef CONFIG_CACHE_L2X0
void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index 0e0fd4d889bd..bb5ce39b733b 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -56,12 +56,12 @@ static unsigned long target_cpu_speed[NUM_CPUS];
static DEFINE_MUTEX(tegra_cpu_lock);
static bool is_suspended;
-int tegra_verify_speed(struct cpufreq_policy *policy)
+static int tegra_verify_speed(struct cpufreq_policy *policy)
{
return cpufreq_frequency_table_verify(policy, freq_table);
}
-unsigned int tegra_getspeed(unsigned int cpu)
+static unsigned int tegra_getspeed(unsigned int cpu)
{
unsigned long rate;
@@ -129,7 +129,7 @@ static int tegra_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
- int idx;
+ unsigned int idx;
unsigned int freq;
int ret = 0;
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 57e35d20c24c..7a2a02dbd632 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -29,7 +29,93 @@
#include <mach/iomap.h>
#include <mach/dma.h>
#include <mach/usb_phy.h>
+
#include "gpio-names.h"
+#include "devices.h"
+
+static struct resource gpio_resource[] = {
+ [0] = {
+ .start = TEGRA_GPIO_BASE,
+ .end = TEGRA_GPIO_BASE + TEGRA_GPIO_SIZE-1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_GPIO1,
+ .end = INT_GPIO1,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = INT_GPIO2,
+ .end = INT_GPIO2,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = INT_GPIO3,
+ .end = INT_GPIO3,
+ .flags = IORESOURCE_IRQ,
+ },
+ [4] = {
+ .start = INT_GPIO4,
+ .end = INT_GPIO4,
+ .flags = IORESOURCE_IRQ,
+ },
+ [5] = {
+ .start = INT_GPIO5,
+ .end = INT_GPIO5,
+ .flags = IORESOURCE_IRQ,
+ },
+ [6] = {
+ .start = INT_GPIO6,
+ .end = INT_GPIO6,
+ .flags = IORESOURCE_IRQ,
+ },
+ [7] = {
+ .start = INT_GPIO7,
+ .end = INT_GPIO7,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device tegra_gpio_device = {
+ .name = "tegra-gpio",
+ .id = -1,
+ .resource = gpio_resource,
+ .num_resources = ARRAY_SIZE(gpio_resource),
+};
+
+static struct resource pinmux_resource[] = {
+ [0] = {
+ /* Tri-state registers */
+ .start = TEGRA_APB_MISC_BASE + 0x14,
+ .end = TEGRA_APB_MISC_BASE + 0x20 + 3,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* Mux registers */
+ .start = TEGRA_APB_MISC_BASE + 0x80,
+ .end = TEGRA_APB_MISC_BASE + 0x9c + 3,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ /* Pull-up/down registers */
+ .start = TEGRA_APB_MISC_BASE + 0xa0,
+ .end = TEGRA_APB_MISC_BASE + 0xb0 + 3,
+ .flags = IORESOURCE_MEM,
+ },
+ [3] = {
+ /* Pad control registers */
+ .start = TEGRA_APB_MISC_BASE + 0x868,
+ .end = TEGRA_APB_MISC_BASE + 0x90c + 3,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device tegra_pinmux_device = {
+ .name = "tegra-pinmux",
+ .id = -1,
+ .resource = pinmux_resource,
+ .num_resources = ARRAY_SIZE(pinmux_resource),
+};
static struct resource i2c_resource1[] = {
[0] = {
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index 4a7dc0a097d6..873ecb2f8ae6 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -21,6 +21,8 @@
#include <linux/platform_device.h>
+extern struct platform_device tegra_gpio_device;
+extern struct platform_device tegra_pinmux_device;
extern struct platform_device tegra_sdhci_device1;
extern struct platform_device tegra_sdhci_device2;
extern struct platform_device tegra_sdhci_device3;
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c
index f4ef5eb317bd..c0cf967e47d3 100644
--- a/arch/arm/mach-tegra/dma.c
+++ b/arch/arm/mach-tegra/dma.c
@@ -105,13 +105,17 @@
#define NV_DMA_MAX_TRASFER_SIZE 0x10000
-const unsigned int ahb_addr_wrap_table[8] = {
+static const unsigned int ahb_addr_wrap_table[8] = {
0, 32, 64, 128, 256, 512, 1024, 2048
};
-const unsigned int apb_addr_wrap_table[8] = {0, 1, 2, 4, 8, 16, 32, 64};
+static const unsigned int apb_addr_wrap_table[8] = {
+ 0, 1, 2, 4, 8, 16, 32, 64
+};
-const unsigned int bus_width_table[5] = {8, 16, 32, 64, 128};
+static const unsigned int bus_width_table[5] = {
+ 8, 16, 32, 64, 128
+};
#define TEGRA_DMA_NAME_SIZE 16
struct tegra_dma_channel {
@@ -157,7 +161,7 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch)
return;
}
-void tegra_dma_stop(struct tegra_dma_channel *ch)
+static void tegra_dma_stop(struct tegra_dma_channel *ch)
{
u32 csr;
u32 status;
@@ -174,7 +178,7 @@ void tegra_dma_stop(struct tegra_dma_channel *ch)
writel(status, ch->addr + APB_DMA_CHAN_STA);
}
-int tegra_dma_cancel(struct tegra_dma_channel *ch)
+static int tegra_dma_cancel(struct tegra_dma_channel *ch)
{
u32 csr;
unsigned long irq_flags;
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
index e0ebe65c1657..619abc63aee8 100644
--- a/arch/arm/mach-tegra/include/mach/debug-macro.S
+++ b/arch/arm/mach-tegra/include/mach/debug-macro.S
@@ -21,7 +21,7 @@
#include <mach/io.h>
#include <mach/iomap.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =IO_APB_PHYS @ physical
ldr \rv, =IO_APB_VIRT @ virtual
orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF)
diff --git a/arch/arm/mach-tegra/include/mach/memory.h b/arch/arm/mach-tegra/include/mach/gpio-tegra.h
index 537db3aa81a7..87d37fdf5084 100644
--- a/arch/arm/mach-tegra/include/mach/memory.h
+++ b/arch/arm/mach-tegra/include/mach/gpio-tegra.h
@@ -1,10 +1,9 @@
/*
- * arch/arm/mach-tegra/include/mach/memory.h
+ * arch/arm/mach-tegra/include/mach/gpio.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
@@ -18,11 +17,23 @@
*
*/
-#ifndef __MACH_TEGRA_MEMORY_H
-#define __MACH_TEGRA_MEMORY_H
+#ifndef __MACH_TEGRA_GPIO_TEGRA_H
+#define __MACH_TEGRA_GPIO_TEGRA_H
-/* physical offset of RAM */
-#define PLAT_PHYS_OFFSET UL(0)
+#include <linux/types.h>
+#include <mach/irqs.h>
-#endif
+#define TEGRA_NR_GPIOS INT_GPIO_NR
+
+#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
+
+struct tegra_gpio_table {
+ int gpio; /* GPIO number */
+ bool enable; /* Enable for GPIO at init? */
+};
+void tegra_gpio_config(struct tegra_gpio_table *table, int num);
+void tegra_gpio_enable(int gpio);
+void tegra_gpio_disable(int gpio);
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h
index 196f114dc241..40a8c178f10d 100644
--- a/arch/arm/mach-tegra/include/mach/gpio.h
+++ b/arch/arm/mach-tegra/include/mach/gpio.h
@@ -1,60 +1 @@
-/*
- * arch/arm/mach-tegra/include/mach/gpio.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- * Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_GPIO_H
-#define __MACH_TEGRA_GPIO_H
-
-#include <linux/init.h>
-#include <mach/irqs.h>
-
-#define TEGRA_NR_GPIOS INT_GPIO_NR
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-
-#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
-#define TEGRA_IRQ_TO_GPIO(irq) ((irq) - INT_GPIO_BASE)
-
-static inline int gpio_to_irq(unsigned int gpio)
-{
- if (gpio < TEGRA_NR_GPIOS)
- return INT_GPIO_BASE + gpio;
- return -EINVAL;
-}
-
-static inline int irq_to_gpio(unsigned int irq)
-{
- if ((irq >= INT_GPIO_BASE) && (irq < INT_GPIO_BASE + INT_GPIO_NR))
- return irq - INT_GPIO_BASE;
- return -EINVAL;
-}
-
-struct tegra_gpio_table {
- int gpio; /* GPIO number */
- bool enable; /* Enable for GPIO at init? */
-};
-
-void tegra_gpio_config(struct tegra_gpio_table *table, int num);
-void tegra_gpio_enable(int gpio);
-void tegra_gpio_disable(int gpio);
-
-#endif
+/* empty */
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h
index 4cea2230c8dc..35a011fbc42d 100644
--- a/arch/arm/mach-tegra/include/mach/io.h
+++ b/arch/arm/mach-tegra/include/mach/io.h
@@ -33,20 +33,26 @@
*
*/
+#ifdef __ASSEMBLY__
+#define IOMEM(x) (x)
+#else
+#define IOMEM(x) ((void __force __iomem *)(x))
+#endif
+
#define IO_IRAM_PHYS 0x40000000
-#define IO_IRAM_VIRT 0xFE400000
+#define IO_IRAM_VIRT IOMEM(0xFE400000)
#define IO_IRAM_SIZE SZ_256K
#define IO_CPU_PHYS 0x50040000
-#define IO_CPU_VIRT 0xFE000000
+#define IO_CPU_VIRT IOMEM(0xFE000000)
#define IO_CPU_SIZE SZ_16K
#define IO_PPSB_PHYS 0x60000000
-#define IO_PPSB_VIRT 0xFE200000
+#define IO_PPSB_VIRT IOMEM(0xFE200000)
#define IO_PPSB_SIZE SZ_1M
#define IO_APB_PHYS 0x70000000
-#define IO_APB_VIRT 0xFE300000
+#define IO_APB_VIRT IOMEM(0xFE300000)
#define IO_APB_SIZE SZ_1M
#define IO_TO_VIRT_BETWEEN(p, st, sz) ((p) >= (st) && (p) < ((st) + (sz)))
@@ -61,7 +67,7 @@
IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) : \
IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ? \
IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) : \
- 0)
+ NULL)
#ifndef __ASSEMBLER__
@@ -71,7 +77,7 @@
void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
void tegra_iounmap(volatile void __iomem *addr);
-#define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n))
+#define IO_ADDRESS(n) (IO_TO_VIRT(n))
#ifdef CONFIG_TEGRA_PCI
extern void __iomem *tegra_pcie_io_base;
diff --git a/arch/arm/mach-tegra/include/mach/pinmux.h b/arch/arm/mach-tegra/include/mach/pinmux.h
index defd8775defa..bb7dfdb61205 100644
--- a/arch/arm/mach-tegra/include/mach/pinmux.h
+++ b/arch/arm/mach-tegra/include/mach/pinmux.h
@@ -199,6 +199,7 @@ struct tegra_drive_pingroup_config {
struct tegra_drive_pingroup_desc {
const char *name;
+ s16 reg_bank;
s16 reg;
};
@@ -207,6 +208,9 @@ struct tegra_pingroup_desc {
int funcs[4];
int func_safe;
int vddio;
+ s16 tri_bank; /* Register bank the tri_reg exists within */
+ s16 mux_bank; /* Register bank the mux_reg exists within */
+ s16 pupd_bank; /* Register bank the pupd_reg exists within */
s16 tri_reg; /* offset into the TRISTATE_REG_* register bank */
s16 mux_reg; /* offset into the PIN_MUX_CTL_* register bank */
s16 pupd_reg; /* offset into the PULL_UPDOWN_REG_* register bank */
diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h
index 401d1b725291..39c396d2ddb0 100644
--- a/arch/arm/mach-tegra/include/mach/powergate.h
+++ b/arch/arm/mach-tegra/include/mach/powergate.h
@@ -31,7 +31,6 @@
int tegra_powergate_power_on(int id);
int tegra_powergate_power_off(int id);
-bool tegra_powergate_is_powered(int id);
int tegra_powergate_remove_clamping(int id);
/* Must be called with clk disabled, and returns with clk enabled */
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
index ea50fe28cf6a..5489f8b5d6ad 100644
--- a/arch/arm/mach-tegra/io.c
+++ b/arch/arm/mach-tegra/io.c
@@ -31,25 +31,25 @@
static struct map_desc tegra_io_desc[] __initdata = {
{
- .virtual = IO_PPSB_VIRT,
+ .virtual = (unsigned long)IO_PPSB_VIRT,
.pfn = __phys_to_pfn(IO_PPSB_PHYS),
.length = IO_PPSB_SIZE,
.type = MT_DEVICE,
},
{
- .virtual = IO_APB_VIRT,
+ .virtual = (unsigned long)IO_APB_VIRT,
.pfn = __phys_to_pfn(IO_APB_PHYS),
.length = IO_APB_SIZE,
.type = MT_DEVICE,
},
{
- .virtual = IO_CPU_VIRT,
+ .virtual = (unsigned long)IO_CPU_VIRT,
.pfn = __phys_to_pfn(IO_CPU_PHYS),
.length = IO_CPU_SIZE,
.type = MT_DEVICE,
},
{
- .virtual = IO_IRAM_VIRT,
+ .virtual = (unsigned long)IO_IRAM_VIRT,
.pfn = __phys_to_pfn(IO_IRAM_PHYS),
.length = IO_IRAM_SIZE,
.type = MT_DEVICE,
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index f1f699d86c32..f5aa173c26b3 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -41,6 +41,8 @@
#include <mach/clk.h>
#include <mach/powergate.h>
+#include "board.h"
+
/* register definitions */
#define AFI_OFFSET 0x3800
#define PADS_OFFSET 0x3000
@@ -150,9 +152,9 @@
static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
#define pmc_writel(value, reg) \
- __raw_writel(value, (u32)reg_pmc_base + (reg))
+ __raw_writel(value, reg_pmc_base + (reg))
#define pmc_readl(reg) \
- __raw_readl((u32)reg_pmc_base + (reg))
+ __raw_readl(reg_pmc_base + (reg))
/*
* Tegra2 defines 1GB in the AXI address map for PCIe.
@@ -460,7 +462,7 @@ static struct pci_bus __init *tegra_pcie_scan_bus(int nr,
struct tegra_pcie_port *pp;
if (nr >= tegra_pcie.num_ports)
- return 0;
+ return NULL;
pp = tegra_pcie.port + nr;
pp->root_bus_nr = sys->busnr;
diff --git a/arch/arm/mach-tegra/pinmux-t2-tables.c b/arch/arm/mach-tegra/pinmux-t2-tables.c
index a475367befa3..a0dc2bc28ed3 100644
--- a/arch/arm/mach-tegra/pinmux-t2-tables.c
+++ b/arch/arm/mach-tegra/pinmux-t2-tables.c
@@ -31,10 +31,16 @@
#include <mach/pinmux.h>
#include <mach/suspend.h>
+#define TRISTATE_REG_A 0x14
+#define PIN_MUX_CTL_REG_A 0x80
+#define PULLUPDOWN_REG_A 0xa0
+#define PINGROUP_REG_A 0x868
+
#define DRIVE_PINGROUP(pg_name, r) \
[TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \
.name = #pg_name, \
- .reg = r \
+ .reg_bank = 3, \
+ .reg = ((r) - PINGROUP_REG_A) \
}
const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
@@ -90,11 +96,14 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE
TEGRA_MUX_ ## f3, \
}, \
.func_safe = TEGRA_MUX_ ## f_safe, \
- .tri_reg = tri_r, \
+ .tri_bank = 0, \
+ .tri_reg = ((tri_r) - TRISTATE_REG_A), \
.tri_bit = tri_b, \
- .mux_reg = mux_r, \
+ .mux_bank = 1, \
+ .mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A), \
.mux_bit = mux_b, \
- .pupd_reg = pupd_r, \
+ .pupd_bank = 2, \
+ .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \
.pupd_bit = pupd_b, \
}
@@ -217,62 +226,3 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
PINGROUP(XM2C, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xA8, 30),
PINGROUP(XM2D, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xA8, 28),
};
-
-#ifdef CONFIG_PM
-#define TRISTATE_REG_A 0x14
-#define TRISTATE_REG_NUM 4
-#define PIN_MUX_CTL_REG_A 0x80
-#define PIN_MUX_CTL_REG_NUM 8
-#define PULLUPDOWN_REG_A 0xa0
-#define PULLUPDOWN_REG_NUM 5
-
-static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
- PULLUPDOWN_REG_NUM +
- ARRAY_SIZE(tegra_soc_drive_pingroups)];
-
-static inline unsigned long pg_readl(unsigned long offset)
-{
- return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
-}
-
-static inline void pg_writel(unsigned long value, unsigned long offset)
-{
- writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
-}
-
-void tegra_pinmux_suspend(void)
-{
- unsigned int i;
- u32 *ctx = pinmux_reg;
-
- for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
- *ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4);
-
- for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
- *ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4);
-
- for (i = 0; i < TRISTATE_REG_NUM; i++)
- *ctx++ = pg_readl(TRISTATE_REG_A + i*4);
-
- for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
- *ctx++ = pg_readl(tegra_soc_drive_pingroups[i].reg);
-}
-
-void tegra_pinmux_resume(void)
-{
- unsigned int i;
- u32 *ctx = pinmux_reg;
-
- for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
- pg_writel(*ctx++, PIN_MUX_CTL_REG_A + i*4);
-
- for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
- pg_writel(*ctx++, PULLUPDOWN_REG_A + i*4);
-
- for (i = 0; i < TRISTATE_REG_NUM; i++)
- pg_writel(*ctx++, TRISTATE_REG_A + i*4);
-
- for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
- pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg);
-}
-#endif
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c
index f80d507671bc..1d201650d7a4 100644
--- a/arch/arm/mach-tegra/pinmux.c
+++ b/arch/arm/mach-tegra/pinmux.c
@@ -20,6 +20,7 @@
#include <linux/errno.h>
#include <linux/spinlock.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include <mach/iomap.h>
#include <mach/pinmux.h>
@@ -169,15 +170,17 @@ static const char *pupd_name(unsigned long val)
}
}
+static int nbanks;
+static void __iomem **regs;
-static inline unsigned long pg_readl(unsigned long offset)
+static inline u32 pg_readl(u32 bank, u32 reg)
{
- return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+ return readl(regs[bank] + reg);
}
-static inline void pg_writel(unsigned long value, unsigned long offset)
+static inline void pg_writel(u32 val, u32 bank, u32 reg)
{
- writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+ writel(val, regs[bank] + reg);
}
static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
@@ -217,10 +220,10 @@ static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
spin_lock_irqsave(&mux_lock, flags);
- reg = pg_readl(pingroups[pg].mux_reg);
+ reg = pg_readl(pingroups[pg].mux_bank, pingroups[pg].mux_reg);
reg &= ~(0x3 << pingroups[pg].mux_bit);
reg |= mux << pingroups[pg].mux_bit;
- pg_writel(reg, pingroups[pg].mux_reg);
+ pg_writel(reg, pingroups[pg].mux_bank, pingroups[pg].mux_reg);
spin_unlock_irqrestore(&mux_lock, flags);
@@ -241,11 +244,11 @@ int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
- reg = pg_readl(pingroups[pg].tri_reg);
+ reg = pg_readl(pingroups[pg].tri_bank, pingroups[pg].tri_reg);
reg &= ~(0x1 << pingroups[pg].tri_bit);
if (tristate)
reg |= 1 << pingroups[pg].tri_bit;
- pg_writel(reg, pingroups[pg].tri_reg);
+ pg_writel(reg, pingroups[pg].tri_bank, pingroups[pg].tri_reg);
spin_unlock_irqrestore(&mux_lock, flags);
@@ -272,10 +275,10 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
- reg = pg_readl(pingroups[pg].pupd_reg);
+ reg = pg_readl(pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
reg &= ~(0x3 << pingroups[pg].pupd_bit);
reg |= pupd << pingroups[pg].pupd_bit;
- pg_writel(reg, pingroups[pg].pupd_reg);
+ pg_writel(reg, pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
spin_unlock_irqrestore(&mux_lock, flags);
@@ -362,12 +365,12 @@ static int tegra_drive_pinmux_set_hsm(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
- reg = pg_readl(drive_pingroups[pg].reg);
+ reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
if (hsm == TEGRA_HSM_ENABLE)
reg |= (1 << 2);
else
reg &= ~(1 << 2);
- pg_writel(reg, drive_pingroups[pg].reg);
+ pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@@ -387,12 +390,12 @@ static int tegra_drive_pinmux_set_schmitt(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
- reg = pg_readl(drive_pingroups[pg].reg);
+ reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
if (schmitt == TEGRA_SCHMITT_ENABLE)
reg |= (1 << 3);
else
reg &= ~(1 << 3);
- pg_writel(reg, drive_pingroups[pg].reg);
+ pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@@ -412,10 +415,10 @@ static int tegra_drive_pinmux_set_drive(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
- reg = pg_readl(drive_pingroups[pg].reg);
+ reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
reg &= ~(0x3 << 4);
reg |= drive << 4;
- pg_writel(reg, drive_pingroups[pg].reg);
+ pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@@ -435,10 +438,10 @@ static int tegra_drive_pinmux_set_pull_down(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
- reg = pg_readl(drive_pingroups[pg].reg);
+ reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
reg &= ~(0x1f << 12);
reg |= pull_down << 12;
- pg_writel(reg, drive_pingroups[pg].reg);
+ pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@@ -458,10 +461,10 @@ static int tegra_drive_pinmux_set_pull_up(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
- reg = pg_readl(drive_pingroups[pg].reg);
+ reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
reg &= ~(0x1f << 12);
reg |= pull_up << 12;
- pg_writel(reg, drive_pingroups[pg].reg);
+ pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@@ -481,10 +484,10 @@ static int tegra_drive_pinmux_set_slew_rising(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
- reg = pg_readl(drive_pingroups[pg].reg);
+ reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
reg &= ~(0x3 << 28);
reg |= slew_rising << 28;
- pg_writel(reg, drive_pingroups[pg].reg);
+ pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@@ -504,10 +507,10 @@ static int tegra_drive_pinmux_set_slew_falling(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
- reg = pg_readl(drive_pingroups[pg].reg);
+ reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
reg &= ~(0x3 << 30);
reg |= slew_falling << 30;
- pg_writel(reg, drive_pingroups[pg].reg);
+ pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@@ -665,6 +668,99 @@ void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *co
}
}
+static int __devinit tegra_pinmux_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int i;
+ int config_bad = 0;
+
+ for (i = 0; ; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res)
+ break;
+ }
+ nbanks = i;
+
+ for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+ if (pingroups[i].tri_bank >= nbanks) {
+ dev_err(&pdev->dev, "pingroup %d: bad tri_bank\n", i);
+ config_bad = 1;
+ }
+
+ if (pingroups[i].mux_bank >= nbanks) {
+ dev_err(&pdev->dev, "pingroup %d: bad mux_bank\n", i);
+ config_bad = 1;
+ }
+
+ if (pingroups[i].pupd_bank >= nbanks) {
+ dev_err(&pdev->dev, "pingroup %d: bad pupd_bank\n", i);
+ config_bad = 1;
+ }
+ }
+
+ for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) {
+ if (drive_pingroups[i].reg_bank >= nbanks) {
+ dev_err(&pdev->dev,
+ "drive pingroup %d: bad reg_bank\n", i);
+ config_bad = 1;
+ }
+ }
+
+ if (config_bad)
+ return -ENODEV;
+
+ regs = devm_kzalloc(&pdev->dev, nbanks * sizeof(*regs), GFP_KERNEL);
+ if (!regs) {
+ dev_err(&pdev->dev, "Can't alloc regs pointer\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; i < nbanks; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res) {
+ dev_err(&pdev->dev, "Missing MEM resource\n");
+ return -ENODEV;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res),
+ dev_name(&pdev->dev))) {
+ dev_err(&pdev->dev,
+ "Couldn't request MEM resource %d\n", i);
+ return -ENODEV;
+ }
+
+ regs[i] = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!regs) {
+ dev_err(&pdev->dev, "Couldn't ioremap regs %d\n", i);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static struct of_device_id tegra_pinmux_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra20-pinmux", },
+ { },
+};
+
+static struct platform_driver tegra_pinmux_driver = {
+ .driver = {
+ .name = "tegra-pinmux",
+ .owner = THIS_MODULE,
+ .of_match_table = tegra_pinmux_of_match,
+ },
+ .probe = tegra_pinmux_probe,
+};
+
+static int __init tegra_pinmux_init(void)
+{
+ return platform_driver_register(&tegra_pinmux_driver);
+}
+postcore_initcall(tegra_pinmux_init);
+
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
@@ -684,6 +780,7 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
int len;
for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+ unsigned long reg;
unsigned long tri;
unsigned long mux;
unsigned long pupd;
@@ -696,8 +793,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
seq_printf(s, "TEGRA_MUX_NONE");
len = strlen("NONE");
} else {
- mux = (pg_readl(pingroups[i].mux_reg) >>
- pingroups[i].mux_bit) & 0x3;
+ reg = pg_readl(pingroups[i].mux_bank,
+ pingroups[i].mux_reg);
+ mux = (reg >> pingroups[i].mux_bit) & 0x3;
if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
len = 5;
@@ -713,8 +811,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
seq_printf(s, "TEGRA_PUPD_NORMAL");
len = strlen("NORMAL");
} else {
- pupd = (pg_readl(pingroups[i].pupd_reg) >>
- pingroups[i].pupd_bit) & 0x3;
+ reg = pg_readl(pingroups[i].pupd_bank,
+ pingroups[i].pupd_reg);
+ pupd = (reg >> pingroups[i].pupd_bit) & 0x3;
seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
len = strlen(pupd_name(pupd));
}
@@ -723,8 +822,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
if (pingroups[i].tri_reg < 0) {
seq_printf(s, "TEGRA_TRI_NORMAL");
} else {
- tri = (pg_readl(pingroups[i].tri_reg) >>
- pingroups[i].tri_bit) & 0x1;
+ reg = pg_readl(pingroups[i].tri_bank,
+ pingroups[i].tri_reg);
+ tri = (reg >> pingroups[i].tri_bit) & 0x1;
seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
}
@@ -759,7 +859,8 @@ static int dbg_drive_pinmux_show(struct seq_file *s, void *unused)
dbg_pad_field(s, 7 - len);
- reg = pg_readl(drive_pingroups[i].reg);
+ reg = pg_readl(drive_pingroups[i].reg_bank,
+ drive_pingroups[i].reg);
if (HSM_EN(reg)) {
seq_printf(s, "TEGRA_HSM_ENABLE");
len = 16;
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 0886cbccddee..7d2b5d03c1df 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -114,10 +114,10 @@ void __init smp_init_cpus(void)
{
unsigned int i, ncores = scu_get_core_count(scu_base);
- if (ncores > NR_CPUS) {
- printk(KERN_ERR "Tegra: no. of cores (%u) greater than configured (%u), clipping\n",
- ncores, NR_CPUS);
- ncores = NR_CPUS;
+ if (ncores > nr_cpu_ids) {
+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+ ncores, nr_cpu_ids);
+ ncores = nr_cpu_ids;
}
for (i = 0; i < ncores; i++)
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index 3cee9aa1f2c8..948306491a59 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -89,12 +89,11 @@ int tegra_powergate_power_off(int id)
return tegra_powergate_set(id, false);
}
-bool tegra_powergate_is_powered(int id)
+static bool tegra_powergate_is_powered(int id)
{
u32 status;
- if (id < 0 || id >= TEGRA_NUM_POWERGATE)
- return -EINVAL;
+ WARN_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
status = pmc_read(PWRGATE_STATUS) & (1 << id);
return !!status;
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 0fe9b3ee2947..371869d8ea01 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -166,13 +166,13 @@ static DEFINE_SPINLOCK(clock_register_lock);
static int tegra_periph_clk_enable_refcount[3 * 32];
#define clk_writel(value, reg) \
- __raw_writel(value, (u32)reg_clk_base + (reg))
+ __raw_writel(value, reg_clk_base + (reg))
#define clk_readl(reg) \
- __raw_readl((u32)reg_clk_base + (reg))
+ __raw_readl(reg_clk_base + (reg))
#define pmc_writel(value, reg) \
- __raw_writel(value, (u32)reg_pmc_base + (reg))
+ __raw_writel(value, reg_pmc_base + (reg))
#define pmc_readl(reg) \
- __raw_readl((u32)reg_pmc_base + (reg))
+ __raw_readl(reg_pmc_base + (reg))
unsigned long clk_measure_input_freq(void)
{
@@ -918,7 +918,7 @@ static struct clk_ops tegra_pll_div_ops = {
static void tegra2_periph_clk_init(struct clk *c)
{
u32 val = clk_readl(c->reg);
- const struct clk_mux_sel *mux = 0;
+ const struct clk_mux_sel *mux = NULL;
const struct clk_mux_sel *sel;
if (c->flags & MUX) {
for (sel = c->inputs; sel->input != NULL; sel++) {
@@ -1459,7 +1459,7 @@ static struct clk tegra_pll_s = {
static struct clk_mux_sel tegra_clk_m_sel[] = {
{ .input = &tegra_clk_32k, .value = 0},
{ .input = &tegra_pll_s, .value = 1},
- { 0, 0},
+ { NULL , 0},
};
static struct clk tegra_clk_m = {
@@ -1861,7 +1861,7 @@ static const struct audio_sources {
{ .name = "ext_audio_clk1", .value = 6 },
{ .name = "ext_vimclk", .value = 7 },
#endif
- { 0, 0 }
+ { NULL, 0 }
};
static struct clk tegra_clk_audio = {
@@ -1885,7 +1885,7 @@ static struct clk tegra_clk_audio_2x = {
},
};
-struct clk_lookup tegra_audio_clk_lookups[] = {
+static struct clk_lookup tegra_audio_clk_lookups[] = {
{ .con_id = "audio", .clk = &tegra_clk_audio },
{ .con_id = "audio_2x", .clk = &tegra_clk_audio_2x }
};
@@ -1926,7 +1926,7 @@ static struct clk_mux_sel mux_cclk[] = {
{ .input = &tegra_pll_p_out3, .value = 6},
{ .input = &tegra_clk_d, .value = 7},
{ .input = &tegra_pll_x, .value = 8},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_sclk[] = {
@@ -1938,7 +1938,7 @@ static struct clk_mux_sel mux_sclk[] = {
{ .input = &tegra_clk_d, .value = 5},
{ .input = &tegra_clk_32k, .value = 6},
{ .input = &tegra_pll_m_out1, .value = 7},
- { 0, 0},
+ { NULL, 0},
};
static struct clk tegra_clk_cclk = {
@@ -2009,7 +2009,7 @@ static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
{ .input = &tegra_pll_c, .value = 1},
{ .input = &tegra_pll_p, .value = 2},
{ .input = &tegra_pll_a_out0, .value = 3},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = {
@@ -2017,7 +2017,7 @@ static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = {
{ .input = &tegra_pll_c, .value = 1},
{ .input = &tegra_pll_p, .value = 2},
{ .input = &tegra_clk_m, .value = 3},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
@@ -2025,7 +2025,7 @@ static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
{ .input = &tegra_pll_c, .value = 1},
{ .input = &tegra_pll_m, .value = 2},
{ .input = &tegra_clk_m, .value = 3},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = {
@@ -2033,7 +2033,7 @@ static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = {
{.input = &tegra_clk_audio_2x, .value = 1},
{.input = &tegra_pll_p, .value = 2},
{.input = &tegra_clk_m, .value = 3},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
@@ -2041,7 +2041,7 @@ static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
{.input = &tegra_pll_d_out0, .value = 1},
{.input = &tegra_pll_c, .value = 2},
{.input = &tegra_clk_m, .value = 3},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
@@ -2050,39 +2050,39 @@ static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
{.input = &tegra_clk_audio, .value = 2},
{.input = &tegra_clk_m, .value = 3},
{.input = &tegra_clk_32k, .value = 4},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_pllp_pllc_pllm[] = {
{.input = &tegra_pll_p, .value = 0},
{.input = &tegra_pll_c, .value = 1},
{.input = &tegra_pll_m, .value = 2},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_clk_m[] = {
{ .input = &tegra_clk_m, .value = 0},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_pllp_out3[] = {
{ .input = &tegra_pll_p_out3, .value = 0},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_plld[] = {
{ .input = &tegra_pll_d, .value = 0},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_clk_32k[] = {
{ .input = &tegra_clk_32k, .value = 0},
- { 0, 0},
+ { NULL, 0},
};
static struct clk_mux_sel mux_pclk[] = {
{ .input = &tegra_clk_pclk, .value = 0},
- { 0, 0},
+ { NULL, 0},
};
static struct clk tegra_clk_emc = {
@@ -2125,7 +2125,7 @@ static struct clk tegra_clk_emc = {
.parent = _parent, \
}
-struct clk tegra_list_clks[] = {
+static struct clk tegra_list_clks[] = {
PERIPH_CLK("apbdma", "tegra-dma", NULL, 34, 0, 108000000, mux_pclk, 0),
PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET),
PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0),
@@ -2221,7 +2221,7 @@ struct clk tegra_list_clks[] = {
* configuration. List those here to register them twice in the clock lookup
* table under two names.
*/
-struct clk_duplicate tegra_clk_duplicates[] = {
+static struct clk_duplicate tegra_clk_duplicates[] = {
CLK_DUPLICATE("uarta", "tegra_uart.0", NULL),
CLK_DUPLICATE("uartb", "tegra_uart.1", NULL),
CLK_DUPLICATE("uartc", "tegra_uart.2", NULL),
@@ -2252,7 +2252,7 @@ struct clk_duplicate tegra_clk_duplicates[] = {
.clk = ck, \
}
-struct clk *tegra_ptr_clks[] = {
+static struct clk *tegra_ptr_clks[] = {
&tegra_clk_32k,
&tegra_pll_s,
&tegra_clk_m,
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index 90350420c4e9..e2272d263a83 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -62,9 +62,9 @@ static struct timespec persistent_ts;
static u64 persistent_ms, last_persistent_ms;
#define timer_writel(value, reg) \
- __raw_writel(value, (u32)timer_reg_base + (reg))
+ __raw_writel(value, timer_reg_base + (reg))
#define timer_readl(reg) \
- __raw_readl((u32)timer_reg_base + (reg))
+ __raw_readl(timer_reg_base + (reg))
static int tegra_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
@@ -133,7 +133,7 @@ static void notrace tegra_update_sched_clock(void)
* tegra_rtc driver could be executing to avoid race conditions
* on the RTC shadow register
*/
-u64 tegra_rtc_read_ms(void)
+static u64 tegra_rtc_read_ms(void)
{
u32 ms = readl(rtc_base + RTC_MILLISECONDS);
u32 s = readl(rtc_base + RTC_SHADOW_SECONDS);
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index 88081bb3ec52..37576a721aeb 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -28,6 +28,7 @@
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
#include <asm/mach-types.h>
+#include <mach/gpio-tegra.h>
#include <mach/usb_phy.h>
#include <mach/iomap.h>
diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig
index 32a7b0f7e9f7..1cbcd4fc1e17 100644
--- a/arch/arm/mach-u300/Kconfig
+++ b/arch/arm/mach-u300/Kconfig
@@ -6,6 +6,9 @@ comment "ST-Ericsson Mobile Platform Products"
config MACH_U300
bool "U300"
+ select PINCTRL
+ select PINMUX_U300
+ select GPIO_U300
comment "ST-Ericsson U300/U330/U335/U365 Feature Selections"
@@ -48,39 +51,12 @@ config MACH_U300_BS365
endchoice
-choice
- prompt "Memory configuration"
- default MACH_U300_SINGLE_RAM
- ---help---
- You have to config the kernel according to the physical memory
- configuration.
-
-config MACH_U300_SINGLE_RAM
- bool "Single RAM"
- help
- Select this if you want support for Single RAM phones.
-
-config MACH_U300_DUAL_RAM
- bool "Dual RAM"
- help
- Select this if you want support for Dual RAM phones.
- This is two RAM memories on different EMIFs.
-endchoice
-
config U300_DEBUG
bool "Debug support for U300"
depends on PM
help
Debug support for U300 in sysfs, procfs etc.
-config MACH_U300_SEMI_IS_SHARED
- bool "The SEMI is used by both the access and application side"
- depends on MACH_U300
- help
- This makes it possible to use the SEMI (Shared External
- Memory Interface) from both from access and application
- side.
-
config MACH_U300_SPIDUMMY
bool "SSP/SPI dummy chip"
select SPI
@@ -93,25 +69,6 @@ config MACH_U300_SPIDUMMY
you don't need it. Selecting this will activate the
SPI framework and ARM PL022 support.
-comment "All the settings below must match the bootloader's settings"
-
-config MACH_U300_ACCESS_MEM_SIZE
- int "Access CPU memory allocation"
- range 7 25
- depends on MACH_U300_SINGLE_RAM
- default 13
- help
- How much memory in MiB that the Access side CPU has allocated
-
-config MACH_U300_2MB_ALIGNMENT_FIX
- bool "2MiB alignment fix"
- depends on MACH_U300_SINGLE_RAM
- default y
- help
- If yes and the Access side CPU has allocated an odd size in
- MiB, this fix gives you one MiB extra that would otherwise be
- lost due to Linux 2 MiB alignment policy.
-
endmenu
endif
diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile
index 8fd354aaf0a7..285538124e5e 100644
--- a/arch/arm/mach-u300/Makefile
+++ b/arch/arm/mach-u300/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux kernel, U300 machine.
#
-obj-y := core.o clock.o timer.o padmux.o
+obj-y := core.o clock.o timer.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/mach-u300/Makefile.boot b/arch/arm/mach-u300/Makefile.boot
index 6fbfc6ea2d35..87811de0bd94 100644
--- a/arch/arm/mach-u300/Makefile.boot
+++ b/arch/arm/mach-u300/Makefile.boot
@@ -1,15 +1,4 @@
-# Note: the following conditions must always be true:
-# ZRELADDR == virt_to_phys(TEXTADDR)
-# PARAMS_PHYS must be within 4MB of ZRELADDR
-# INITRD_PHYS must be in RAM
-
-ifdef CONFIG_MACH_U300_SINGLE_RAM
- zreladdr-y := 0x28E08000
- params_phys-y := 0x28E00100
-else
- zreladdr-y := 0x48008000
- params_phys-y := 0x48000100
-endif
-
+ zreladdr-y += 0x48008000
+params_phys-y := 0x48000100
# This isn't used.
-#initrd_phys-y := 0x29800000
+#initrd_phys-y := 0x48800000
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 399c89f14dfb..ac0791e924bc 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -25,6 +25,9 @@
#include <linux/err.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/fsmc.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/dma-mapping.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -37,6 +40,7 @@
#include <mach/hardware.h>
#include <mach/syscon.h>
#include <mach/dma_channels.h>
+#include <mach/gpio-u300.h>
#include "clock.h"
#include "mmc.h"
@@ -68,30 +72,13 @@ static struct map_desc u300_io_desc[] __initdata = {
.length = SZ_32K,
.type = MT_DEVICE,
},
- {
- .virtual = 0xffff2000, /* TCM memory */
- .pfn = __phys_to_pfn(0xffff2000),
- .length = SZ_16K,
- .type = MT_DEVICE,
- },
-
- /*
- * This overlaps with the IRQ vectors etc at 0xffff0000, so these
- * may have to be moved to 0x00000000 in order to use the ROM.
- */
- /*
- {
- .virtual = U300_BOOTROM_VIRT_BASE,
- .pfn = __phys_to_pfn(U300_BOOTROM_PHYS_BASE),
- .length = SZ_64K,
- .type = MT_ROM,
- },
- */
};
void __init u300_map_io(void)
{
iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));
+ /* We enable a real big DMA buffer if need be. */
+ init_consistent_dma_size(SZ_4M);
}
/*
@@ -239,7 +226,7 @@ static struct resource gpio_resources[] = {
.end = IRQ_U300_GPIO_PORT2,
.flags = IORESOURCE_IRQ,
},
-#ifdef U300_COH901571_3
+#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335)
{
.name = "gpio3",
.start = IRQ_U300_GPIO_PORT3,
@@ -252,6 +239,7 @@ static struct resource gpio_resources[] = {
.end = IRQ_U300_GPIO_PORT4,
.flags = IORESOURCE_IRQ,
},
+#endif
#ifdef CONFIG_MACH_U300_BS335
{
.name = "gpio5",
@@ -266,7 +254,6 @@ static struct resource gpio_resources[] = {
.flags = IORESOURCE_IRQ,
},
#endif /* CONFIG_MACH_U300_BS335 */
-#endif /* U300_COH901571_3 */
};
static struct resource keypad_resources[] = {
@@ -361,51 +348,6 @@ static struct resource wdog_resources[] = {
}
};
-/* TODO: These should be protected by suitable #ifdef's */
-static struct resource ave_resources[] = {
- {
- .name = "AVE3e I/O Area",
- .start = U300_VIDEOENC_BASE,
- .end = U300_VIDEOENC_BASE + SZ_512K - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "AVE3e IRQ0",
- .start = IRQ_U300_VIDEO_ENC_0,
- .end = IRQ_U300_VIDEO_ENC_0,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "AVE3e IRQ1",
- .start = IRQ_U300_VIDEO_ENC_1,
- .end = IRQ_U300_VIDEO_ENC_1,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "AVE3e Physmem Area",
- .start = 0, /* 0 will be remapped to reserved memory */
- .end = SZ_1M - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- * The AVE3e requires two regions of 256MB that it considers
- * "invisible". The hardware will not be able to access these
- * addresses, so they should never point to system RAM.
- */
- {
- .name = "AVE3e Reserved 0",
- .start = 0xd0000000,
- .end = 0xd0000000 + SZ_256M - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "AVE3e Reserved 1",
- .start = 0xe0000000,
- .end = 0xe0000000 + SZ_256M - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
static struct resource dma_resource[] = {
{
.start = U300_DMAC_BASE,
@@ -1535,6 +1477,14 @@ static struct coh901318_platform coh901318_platform = {
.max_channels = U300_DMA_CHANNELS,
};
+static struct resource pinmux_resources[] = {
+ {
+ .start = U300_SYSCON_BASE,
+ .end = U300_SYSCON_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
static struct platform_device wdog_device = {
.name = "coh901327_wdog",
.id = -1,
@@ -1556,11 +1506,35 @@ static struct platform_device i2c1_device = {
.resource = i2c1_resources,
};
+/*
+ * The different variants have a few different versions of the
+ * GPIO block, with different number of ports.
+ */
+static struct u300_gpio_platform u300_gpio_plat = {
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
+ .variant = U300_GPIO_COH901335,
+ .ports = 3,
+#endif
+#ifdef CONFIG_MACH_U300_BS335
+ .variant = U300_GPIO_COH901571_3_BS335,
+ .ports = 7,
+#endif
+#ifdef CONFIG_MACH_U300_BS365
+ .variant = U300_GPIO_COH901571_3_BS365,
+ .ports = 5,
+#endif
+ .gpio_base = 0,
+ .gpio_irq_base = IRQ_U300_GPIO_BASE,
+};
+
static struct platform_device gpio_device = {
.name = "u300-gpio",
.id = -1,
.num_resources = ARRAY_SIZE(gpio_resources),
.resource = gpio_resources,
+ .dev = {
+ .platform_data = &u300_gpio_plat,
+ },
};
static struct platform_device keypad_device = {
@@ -1612,13 +1586,6 @@ static struct platform_device nand_device = {
},
};
-static struct platform_device ave_device = {
- .name = "video_enc",
- .id = -1,
- .num_resources = ARRAY_SIZE(ave_resources),
- .resource = ave_resources,
-};
-
static struct platform_device dma_device = {
.name = "coh901318",
.id = -1,
@@ -1630,6 +1597,72 @@ static struct platform_device dma_device = {
},
};
+static struct platform_device pinmux_device = {
+ .name = "pinmux-u300",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(pinmux_resources),
+ .resource = pinmux_resources,
+};
+
+/* Pinmux settings */
+static struct pinmux_map u300_pinmux_map[] = {
+ /* anonymous maps for chip power and EMIFs */
+ PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"),
+ PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"),
+ PINMUX_MAP_PRIMARY_SYS_HOG("EMIF1", "emif1"),
+ /* per-device maps for MMC/SD, SPI and UART */
+ PINMUX_MAP_PRIMARY("MMCSD", "mmc0", "mmci"),
+ PINMUX_MAP_PRIMARY("SPI", "spi0", "pl022"),
+ PINMUX_MAP_PRIMARY("UART0", "uart0", "uart0"),
+};
+
+struct u300_mux_hog {
+ const char *name;
+ struct device *dev;
+ struct pinmux *pmx;
+};
+
+static struct u300_mux_hog u300_mux_hogs[] = {
+ {
+ .name = "uart0",
+ .dev = &uart0_device.dev,
+ },
+ {
+ .name = "spi0",
+ .dev = &pl022_device.dev,
+ },
+ {
+ .name = "mmc0",
+ .dev = &mmcsd_device.dev,
+ },
+};
+
+static int __init u300_pinmux_fetch(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(u300_mux_hogs); i++) {
+ struct pinmux *pmx;
+ int ret;
+
+ pmx = pinmux_get(u300_mux_hogs[i].dev, NULL);
+ if (IS_ERR(pmx)) {
+ pr_err("u300: could not get pinmux hog %s\n",
+ u300_mux_hogs[i].name);
+ continue;
+ }
+ ret = pinmux_enable(pmx);
+ if (ret) {
+ pr_err("u300: could enable pinmux hog %s\n",
+ u300_mux_hogs[i].name);
+ continue;
+ }
+ u300_mux_hogs[i].pmx = pmx;
+ }
+ return 0;
+}
+subsys_initcall(u300_pinmux_fetch);
+
/*
* Notice that AMBA devices are initialized before platform devices.
*
@@ -1643,10 +1676,9 @@ static struct platform_device *platform_devs[] __initdata = {
&gpio_device,
&nand_device,
&wdog_device,
- &ave_device
+ &pinmux_device,
};
-
/*
* Interrupts: the U300 platforms have two pl190 ARM PrimeCells connected
* together so some interrupts are connected to the first one and some
@@ -1666,7 +1698,7 @@ void __init u300_init_irq(void)
BUG_ON(IS_ERR(clk));
clk_enable(clk);
- for (i = 0; i < NR_IRQS; i++)
+ for (i = 0; i < U300_VIC_IRQS_END; i++)
set_bit(i, (unsigned long *) &mask[0]);
vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]);
vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]);
@@ -1828,6 +1860,10 @@ void __init u300_init_devices(void)
u300_assign_physmem();
+ /* Initialize pinmuxing */
+ pinmux_register_mappings(u300_pinmux_map,
+ ARRAY_SIZE(u300_pinmux_map));
+
/* Register subdevices on the I2C buses */
u300_i2c_register_board_devices();
@@ -1837,17 +1873,10 @@ void __init u300_init_devices(void)
/* Register subdevices on the SPI bus */
u300_spi_register_board_devices();
-#ifndef CONFIG_MACH_U300_SEMI_IS_SHARED
- /*
- * Enable SEMI self refresh. Self-refresh of the SDRAM is entered when
- * both subsystems are requesting this mode.
- * If we not share the Acc SDRAM, this is never the case. Therefore
- * enable it here from the App side.
- */
+ /* Enable SEMI self refresh */
val = readw(U300_SYSCON_VBASE + U300_SYSCON_SMCR) |
U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE;
writew(val, U300_SYSCON_VBASE + U300_SYSCON_SMCR);
-#endif /* CONFIG_MACH_U300_SEMI_IS_SHARED */
}
static int core_module_init(void)
diff --git a/arch/arm/mach-u300/include/mach/debug-macro.S b/arch/arm/mach-u300/include/mach/debug-macro.S
index df715707bead..8ae8e4ab34b0 100644
--- a/arch/arm/mach-u300/include/mach/debug-macro.S
+++ b/arch/arm/mach-u300/include/mach/debug-macro.S
@@ -10,7 +10,7 @@
*/
#include <mach/hardware.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
/* If we move the address using MMU, use this. */
ldr \rp, = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
ldr \rv, = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
diff --git a/arch/arm/mach-u300/include/mach/gpio-u300.h b/arch/arm/mach-u300/include/mach/gpio-u300.h
new file mode 100644
index 000000000000..0c2b2021951a
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/gpio-u300.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2007-2011 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * GPIO block resgister definitions and inline macros for
+ * U300 GPIO COH 901 335 or COH 901 571/3
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __MACH_U300_GPIO_U300_H
+#define __MACH_U300_GPIO_U300_H
+
+/*
+ * Individual pin assignments for the B26/S26. Notice that the
+ * actual usage of these pins depends on the PAD MUX settings, that
+ * is why the same number can potentially appear several times.
+ * In the reference design each pin is only used for one purpose.
+ * These were determined by inspecting the B26/S26 schematic:
+ * 2/1911-ROA 128 1603
+ */
+#ifdef CONFIG_MACH_U300_BS2X
+#define U300_GPIO_PIN_UART_RX 0
+#define U300_GPIO_PIN_UART_TX 1
+#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */
+#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */
+#define U300_GPIO_PIN_CAM_SLEEP 4
+#define U300_GPIO_PIN_CAM_REG_EN 5
+#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */
+#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */
+#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */
+#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */
+#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */
+#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */
+#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */
+#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */
+#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */
+#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */
+#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
+#endif
+
+/*
+ * Individual pin assignments for the B330/S330 and B365/S365.
+ * Notice that the actual usage of these pins depends on the
+ * PAD MUX settings, that is why the same number can potentially
+ * appear several times. In the reference design each pin is only
+ * used for one purpose. These were determined by inspecting the
+ * S365 schematic.
+ */
+#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
+ defined(CONFIG_MACH_U300_BS335)
+#define U300_GPIO_PIN_UART_RX 0
+#define U300_GPIO_PIN_UART_TX 1
+#define U300_GPIO_PIN_UART_CTS 2
+#define U300_GPIO_PIN_UART_RTS 3
+#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */
+#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */
+#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */
+#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */
+
+#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */
+#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */
+#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */
+#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */
+#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */
+#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */
+#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */
+#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */
+#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */
+#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */
+#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */
+#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */
+#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */
+#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */
+#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */
+#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */
+#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */
+#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */
+#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */
+#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */
+#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */
+#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */
+#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */
+#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */
+
+#ifdef CONFIG_MACH_U300_BS335
+
+#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */
+#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */
+#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */
+#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */
+#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */
+#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */
+#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */
+#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */
+#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */
+#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */
+#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */
+#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */
+#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */
+#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */
+#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */
+#endif
+
+#endif
+
+/**
+ * enum u300_gpio_variant - the type of U300 GPIO employed
+ */
+enum u300_gpio_variant {
+ U300_GPIO_COH901335,
+ U300_GPIO_COH901571_3_BS335,
+ U300_GPIO_COH901571_3_BS365,
+};
+
+/**
+ * struct u300_gpio_platform - U300 GPIO platform data
+ * @variant: IP block variant
+ * @ports: number of GPIO block ports
+ * @gpio_base: first GPIO number for this block (use a free range)
+ * @gpio_irq_base: first GPIO IRQ number for this block (use a free range)
+ */
+struct u300_gpio_platform {
+ enum u300_gpio_variant variant;
+ u8 ports;
+ int gpio_base;
+ int gpio_irq_base;
+};
+
+#endif /* __MACH_U300_GPIO_U300_H */
diff --git a/arch/arm/mach-u300/include/mach/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h
index d5a71abcbaea..40a8c178f10d 100644
--- a/arch/arm/mach-u300/include/mach/gpio.h
+++ b/arch/arm/mach-u300/include/mach/gpio.h
@@ -1,294 +1 @@
-/*
- *
- * arch/arm/mach-u300/include/mach/gpio.h
- *
- *
- * Copyright (C) 2007-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * GPIO block resgister definitions and inline macros for
- * U300 GPIO COH 901 335 or COH 901 571/3
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- */
-
-#ifndef __MACH_U300_GPIO_H
-#define __MACH_U300_GPIO_H
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-/* Switch type depending on platform/chip variant */
-#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-#define U300_COH901335
-#endif
-#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335)
-#define U300_COH901571_3
-#endif
-
-/* Get base address for regs here */
-#include "u300-regs.h"
-/* IRQ numbers */
-#include "irqs.h"
-
-/*
- * This is the GPIO block definitions. GPIO (General Purpose I/O) can be
- * used for anything, and often is. The event/enable etc figures are for
- * the lowermost pin (pin 0 on each port), shift this left to match your
- * pin if you're gonna use these values.
- */
-#ifdef U300_COH901335
-#define U300_GPIO_PORTX_SPACING (0x1C)
-/* Port X Pin Data Register 32bit, this is both input and output (R/W) */
-#define U300_GPIO_PXPDIR (0x00)
-#define U300_GPIO_PXPDOR (0x00)
-/* Port X Pin Config Register 32bit (R/W) */
-#define U300_GPIO_PXPCR (0x04)
-#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL)
-#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL)
-#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL)
-/* Port X Interrupt Event Register 32bit (R/W) */
-#define U300_GPIO_PXIEV (0x08)
-#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL)
-#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL)
-/* Port X Interrupt Enable Register 32bit (R/W) */
-#define U300_GPIO_PXIEN (0x0C)
-#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL)
-#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL)
-/* Port X Interrupt Force Register 32bit (R/W) */
-#define U300_GPIO_PXIFR (0x10)
-#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL)
-#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL)
-/* Port X Interrupt Config Register 32bit (R/W) */
-#define U300_GPIO_PXICR (0x14)
-#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL)
-/* Port X Pull-up Enable Register 32bit (R/W) */
-#define U300_GPIO_PXPER (0x18)
-#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL)
-#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL)
-/* Control Register 32bit (R/W) */
-#define U300_GPIO_CR (0x54)
-#define U300_GPIO_CR_BLOCK_CLOCK_ENABLE (0x00000001UL)
-/* three ports of 8 bits each = GPIO pins 0..23 */
-#define U300_GPIO_NUM_PORTS 3
-#define U300_GPIO_PINS_PER_PORT 8
-#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1)
-#endif
-
-#ifdef U300_COH901571_3
-/*
- * Control Register 32bit (R/W)
- * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
- * gives the number of GPIO pins.
- * bit 8-2 (mask 0x000001FC) contains the core version ID.
- */
-#define U300_GPIO_CR (0x00)
-#define U300_GPIO_CR_SYNC_SEL_ENABLE (0x00000002UL)
-#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL)
-#define U300_GPIO_PORTX_SPACING (0x30)
-/* Port X Pin Data INPUT Register 32bit (R/W) */
-#define U300_GPIO_PXPDIR (0x04)
-/* Port X Pin Data OUTPUT Register 32bit (R/W) */
-#define U300_GPIO_PXPDOR (0x08)
-/* Port X Pin Config Register 32bit (R/W) */
-#define U300_GPIO_PXPCR (0x0C)
-#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL)
-#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL)
-#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL)
-/* Port X Pull-up Enable Register 32bit (R/W) */
-#define U300_GPIO_PXPER (0x10)
-#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL)
-#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL)
-/* Port X Interrupt Event Register 32bit (R/W) */
-#define U300_GPIO_PXIEV (0x14)
-#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL)
-#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL)
-/* Port X Interrupt Enable Register 32bit (R/W) */
-#define U300_GPIO_PXIEN (0x18)
-#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL)
-#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL)
-/* Port X Interrupt Force Register 32bit (R/W) */
-#define U300_GPIO_PXIFR (0x1C)
-#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL)
-#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL)
-/* Port X Interrupt Config Register 32bit (R/W) */
-#define U300_GPIO_PXICR (0x20)
-#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL)
-#ifdef CONFIG_MACH_U300_BS335
-/* seven ports of 8 bits each = GPIO pins 0..55 */
-#define U300_GPIO_NUM_PORTS 7
-#else
-/* five ports of 8 bits each = GPIO pins 0..39 */
-#define U300_GPIO_NUM_PORTS 5
-#endif
-#define U300_GPIO_PINS_PER_PORT 8
-#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1)
-#endif
-
-/*
- * Individual pin assignments for the B26/S26. Notice that the
- * actual usage of these pins depends on the PAD MUX settings, that
- * is why the same number can potentially appear several times.
- * In the reference design each pin is only used for one purpose.
- * These were determined by inspecting the B26/S26 schematic:
- * 2/1911-ROA 128 1603
- */
-#ifdef CONFIG_MACH_U300_BS2X
-#define U300_GPIO_PIN_UART_RX 0
-#define U300_GPIO_PIN_UART_TX 1
-#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */
-#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */
-#define U300_GPIO_PIN_CAM_SLEEP 4
-#define U300_GPIO_PIN_CAM_REG_EN 5
-#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */
-#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */
-#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */
-#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */
-#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
-#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
-#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */
-#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */
-#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */
-#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */
-#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */
-#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */
-#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
-#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
-#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
-#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
-#endif
-
-/*
- * Individual pin assignments for the B330/S330 and B365/S365.
- * Notice that the actual usage of these pins depends on the
- * PAD MUX settings, that is why the same number can potentially
- * appear several times. In the reference design each pin is only
- * used for one purpose. These were determined by inspecting the
- * S365 schematic.
- */
-#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
- defined(CONFIG_MACH_U300_BS335)
-#define U300_GPIO_PIN_UART_RX 0
-#define U300_GPIO_PIN_UART_TX 1
-#define U300_GPIO_PIN_UART_CTS 2
-#define U300_GPIO_PIN_UART_RTS 3
-#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */
-#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */
-#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */
-#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */
-
-#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */
-#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */
-#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */
-#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */
-#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */
-#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */
-#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */
-#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */
-#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */
-#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */
-#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */
-#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */
-#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */
-#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */
-#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */
-#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */
-#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */
-#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */
-#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */
-#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */
-#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */
-#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */
-#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */
-#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */
-#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */
-#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */
-#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */
-#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */
-#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */
-
-#ifdef CONFIG_MACH_U300_BS335
-
-#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */
-#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */
-#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */
-#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */
-#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */
-#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */
-#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */
-#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */
-#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */
-#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */
-#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */
-#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */
-#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */
-#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */
-#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */
-#endif
-
-#endif
-
-/* translates a pin number to a port number */
-#define PIN_TO_PORT(val) (val >> 3)
-
-/* These can be found in arch/arm/mach-u300/gpio.c */
-extern int gpio_is_valid(int number);
-extern int gpio_request(unsigned gpio, const char *label);
-extern void gpio_free(unsigned gpio);
-extern int gpio_direction_input(unsigned gpio);
-extern int gpio_direction_output(unsigned gpio, int value);
-extern int gpio_register_callback(unsigned gpio,
- int (*func)(void *arg),
- void *);
-extern int gpio_unregister_callback(unsigned gpio);
-extern void enable_irq_on_gpio_pin(unsigned gpio, int edge);
-extern void disable_irq_on_gpio_pin(unsigned gpio);
-extern void gpio_pullup(unsigned gpio, int value);
-extern int gpio_get_value(unsigned gpio);
-extern void gpio_set_value(unsigned gpio, int value);
-
-#define gpio_get_value_cansleep gpio_get_value
-#define gpio_set_value_cansleep gpio_set_value
-
-/* wrappers to sleep-enable the previous two functions */
-static inline unsigned gpio_to_irq(unsigned gpio)
-{
- return PIN_TO_PORT(gpio) + IRQ_U300_GPIO_PORT0;
-}
-
-static inline unsigned irq_to_gpio(unsigned irq)
-{
- /*
- * FIXME: This is no 1-1 mapping at all, it points to the
- * whole block of 8 pins.
- */
- return (irq - IRQ_U300_GPIO_PORT0) << 3;
-}
-
-#endif
+/* empty */
diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h
index a6867b12773e..db3fbfa1d6e9 100644
--- a/arch/arm/mach-u300/include/mach/irqs.h
+++ b/arch/arm/mach-u300/include/mach/irqs.h
@@ -72,7 +72,7 @@
/* DB3150 and DB3200 have only 45 IRQs */
#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-#define U300_NR_IRQS 45
+#define U300_VIC_IRQS_END 45
#endif
/* The DB3350-specific interrupt lines */
@@ -88,7 +88,7 @@
#define IRQ_U300_GPIO_PORT4 53
#define IRQ_U300_GPIO_PORT5 54
#define IRQ_U300_GPIO_PORT6 55
-#define U300_NR_IRQS 56
+#define U300_VIC_IRQS_END 56
#endif
/* The DB3210-specific interrupt lines */
@@ -106,9 +106,17 @@
#define IRQ_U300_NFIF 45
#define IRQ_U300_NFIF2 46
#define IRQ_U300_SYSCON_PLL_LOCK 47
-#define U300_NR_IRQS 48
+#define U300_VIC_IRQS_END 48
#endif
-#define NR_IRQS U300_NR_IRQS
+/* Maximum 8*7 GPIO lines */
+#ifdef CONFIG_GPIO_U300
+#define IRQ_U300_GPIO_BASE (U300_VIC_IRQS_END)
+#define IRQ_U300_GPIO_END (IRQ_U300_GPIO_BASE + 56)
+#else
+#define IRQ_U300_GPIO_END (U300_VIC_IRQS_END)
+#endif
+
+#define NR_IRQS (IRQ_U300_GPIO_END)
#endif
diff --git a/arch/arm/mach-u300/include/mach/memory.h b/arch/arm/mach-u300/include/mach/memory.h
index 888e2e351ee1..c808f347a081 100644
--- a/arch/arm/mach-u300/include/mach/memory.h
+++ b/arch/arm/mach-u300/include/mach/memory.h
@@ -13,30 +13,7 @@
#ifndef __MACH_MEMORY_H
#define __MACH_MEMORY_H
-#ifdef CONFIG_MACH_U300_DUAL_RAM
-
-#define PLAT_PHYS_OFFSET UL(0x48000000)
-#define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100)
-
-#else
-
-#ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
-#define PLAT_PHYS_OFFSET (0x28000000 + \
- (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
- (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
-#else
-#define PLAT_PHYS_OFFSET (0x28000000 + \
- (CONFIG_MACH_U300_ACCESS_MEM_SIZE + \
- (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
-#endif
-#define BOOT_PARAMS_OFFSET (0x28000000 + \
- (CONFIG_MACH_U300_ACCESS_MEM_SIZE + \
- (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024 + 0x100)
-#endif
-
-/*
- * We enable a real big DMA buffer if need be.
- */
-#define CONSISTENT_DMA_SIZE SZ_4M
+#define PLAT_PHYS_OFFSET UL(0x48000000)
+#define BOOT_PARAMS_OFFSET 0x100
#endif
diff --git a/arch/arm/mach-u300/include/mach/syscon.h b/arch/arm/mach-u300/include/mach/syscon.h
index 7444f5c7da97..6e84f07a7c6f 100644
--- a/arch/arm/mach-u300/include/mach/syscon.h
+++ b/arch/arm/mach-u300/include/mach/syscon.h
@@ -234,91 +234,6 @@
#define U300_SYSCON_ECCR_EMIF_1_RET_OUT_CLK_EN_N_DISABLE (0x0004)
#define U300_SYSCON_ECCR_EMIF_MEMCLK_RET_EN_N_DISABLE (0x0002)
#define U300_SYSCON_ECCR_EMIF_SDRCLK_RET_EN_N_DISABLE (0x0001)
-/* PAD MUX Control register 1 (LOW) 16bit (R/W) */
-#define U300_SYSCON_PMC1LR (0x007C)
-#define U300_SYSCON_PMC1LR_MASK (0xFFFF)
-#define U300_SYSCON_PMC1LR_CDI_MASK (0xC000)
-#define U300_SYSCON_PMC1LR_CDI_CDI (0x0000)
-#define U300_SYSCON_PMC1LR_CDI_EMIF (0x4000)
-#ifdef CONFIG_MACH_U300_BS335
-#define U300_SYSCON_PMC1LR_CDI_CDI2 (0x8000)
-#define U300_SYSCON_PMC1LR_CDI_WCDMA_APP_GPIO (0xC000)
-#elif CONFIG_MACH_U300_BS365
-#define U300_SYSCON_PMC1LR_CDI_GPIO (0x8000)
-#define U300_SYSCON_PMC1LR_CDI_WCDMA (0xC000)
-#endif
-#define U300_SYSCON_PMC1LR_PDI_MASK (0x3000)
-#define U300_SYSCON_PMC1LR_PDI_PDI (0x0000)
-#define U300_SYSCON_PMC1LR_PDI_EGG (0x1000)
-#define U300_SYSCON_PMC1LR_PDI_WCDMA (0x3000)
-#define U300_SYSCON_PMC1LR_MMCSD_MASK (0x0C00)
-#define U300_SYSCON_PMC1LR_MMCSD_MMCSD (0x0000)
-#define U300_SYSCON_PMC1LR_MMCSD_MSPRO (0x0400)
-#define U300_SYSCON_PMC1LR_MMCSD_DSP (0x0800)
-#define U300_SYSCON_PMC1LR_MMCSD_WCDMA (0x0C00)
-#define U300_SYSCON_PMC1LR_ETM_MASK (0x0300)
-#define U300_SYSCON_PMC1LR_ETM_ACC (0x0000)
-#define U300_SYSCON_PMC1LR_ETM_APP (0x0100)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK (0x00C0)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC (0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF (0x0040)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM (0x0080)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB (0x00C0)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK (0x0030)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC (0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF (0x0010)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM (0x0020)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI (0x0030)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK (0x000C)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC (0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF (0x0004)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM (0x0008)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI (0x000C)
-#define U300_SYSCON_PMC1LR_EMIF_1_MASK (0x0003)
-#define U300_SYSCON_PMC1LR_EMIF_1_STATIC (0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0 (0x0001)
-#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1 (0x0002)
-#define U300_SYSCON_PMC1LR_EMIF_1 (0x0003)
-/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */
-#define U300_SYSCON_PMC1HR (0x007E)
-#define U300_SYSCON_PMC1HR_MASK (0xFFFF)
-#define U300_SYSCON_PMC1HR_MISC_2_MASK (0xC000)
-#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_MISC_2_MSPRO (0x4000)
-#define U300_SYSCON_PMC1HR_MISC_2_DSP (0x8000)
-#define U300_SYSCON_PMC1HR_MISC_2_AAIF (0xC000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK (0x3000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF (0x1000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP (0x2000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF (0x3000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK (0x0C00)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC (0x0400)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP (0x0800)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF (0x0C00)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK (0x0300)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI (0x0100)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF (0x0300)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK (0x00C0)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI (0x0040)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF (0x00C0)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK (0x0030)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI (0x0010)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP (0x0020)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF (0x0030)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK (0x000C)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0 (0x0004)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS (0x0008)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF (0x000C)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK (0x0003)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0 (0x0001)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF (0x0003)
/* Step one for killing the applications system 16bit (-/W) */
#define U300_SYSCON_KA1R (0x0080)
#define U300_SYSCON_KA1R_MASK (0xFFFF)
@@ -357,57 +272,6 @@
#define U300_SYSCON_PUCR_EMIF_1_16BIT_PU_ENABLE (0x0080)
#define U300_SYSCON_PUCR_EMIF_1_8BIT_PU_ENABLE (0x0040)
#define U300_SYSCON_PUCR_KEY_IN_PU_EN_MASK (0x003F)
-/* Padmux 2 control */
-#define U300_SYSCON_PMC2R (0x100)
-#define U300_SYSCON_PMC2R_APP_MISC_0_MASK (0x00C0)
-#define U300_SYSCON_PMC2R_APP_MISC_0_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_0_EMIF_SDRAM (0x0040)
-#define U300_SYSCON_PMC2R_APP_MISC_0_MMC (0x0080)
-#define U300_SYSCON_PMC2R_APP_MISC_0_CDI2 (0x00C0)
-#define U300_SYSCON_PMC2R_APP_MISC_1_MASK (0x0300)
-#define U300_SYSCON_PMC2R_APP_MISC_1_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_1_EMIF_SDRAM (0x0100)
-#define U300_SYSCON_PMC2R_APP_MISC_1_MMC (0x0200)
-#define U300_SYSCON_PMC2R_APP_MISC_1_CDI2 (0x0300)
-#define U300_SYSCON_PMC2R_APP_MISC_2_MASK (0x0C00)
-#define U300_SYSCON_PMC2R_APP_MISC_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_2_EMIF_SDRAM (0x0400)
-#define U300_SYSCON_PMC2R_APP_MISC_2_MMC (0x0800)
-#define U300_SYSCON_PMC2R_APP_MISC_2_CDI2 (0x0C00)
-#define U300_SYSCON_PMC2R_APP_MISC_3_MASK (0x3000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_EMIF_SDRAM (0x1000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_MMC (0x2000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_CDI2 (0x3000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_MASK (0xC000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_EMIF_SDRAM (0x4000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_MMC (0x8000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_ACC_GPIO (0xC000)
-/* TODO: More SYSCON registers missing */
-#define U300_SYSCON_PMC3R (0x10c)
-#define U300_SYSCON_PMC3R_APP_MISC_11_MASK (0xc000)
-#define U300_SYSCON_PMC3R_APP_MISC_11_SPI (0x4000)
-#define U300_SYSCON_PMC3R_APP_MISC_10_MASK (0x3000)
-#define U300_SYSCON_PMC3R_APP_MISC_10_SPI (0x1000)
-/* TODO: Missing other configs */
-#define U300_SYSCON_PMC4R (0x168)
-#define U300_SYSCON_PMC4R_APP_MISC_12_MASK (0x0003)
-#define U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_13_MASK (0x000C)
-#define U300_SYSCON_PMC4R_APP_MISC_13_CDI (0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA (0x0004)
-#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA2 (0x0008)
-#define U300_SYSCON_PMC4R_APP_MISC_13_APP_GPIO (0x000C)
-#define U300_SYSCON_PMC4R_APP_MISC_14_MASK (0x0030)
-#define U300_SYSCON_PMC4R_APP_MISC_14_CDI (0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_14_SMIA (0x0010)
-#define U300_SYSCON_PMC4R_APP_MISC_14_CDI2 (0x0020)
-#define U300_SYSCON_PMC4R_APP_MISC_14_APP_GPIO (0x0030)
-#define U300_SYSCON_PMC4R_APP_MISC_16_MASK (0x0300)
-#define U300_SYSCON_PMC4R_APP_MISC_16_APP_GPIO_13 (0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS (0x0100)
-#define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N (0x0200)
/* SYS_0_CLK_CONTROL first clock control 16bit (R/W) */
#define U300_SYSCON_S0CCR (0x120)
#define U300_SYSCON_S0CCR_FIELD_MASK (0x43FF)
diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c
index 677ccef5cd32..4d482aacc272 100644
--- a/arch/arm/mach-u300/mmc.c
+++ b/arch/arm/mach-u300/mmc.c
@@ -13,15 +13,14 @@
#include <linux/device.h>
#include <linux/amba/bus.h>
#include <linux/mmc/host.h>
-#include <linux/gpio.h>
#include <linux/dmaengine.h>
#include <linux/amba/mmci.h>
#include <linux/slab.h>
#include <mach/coh901318.h>
#include <mach/dma_channels.h>
+#include <mach/gpio-u300.h>
#include "mmc.h"
-#include "padmux.h"
static struct mmci_platform_data mmc0_plat_data = {
/*
@@ -45,24 +44,9 @@ static struct mmci_platform_data mmc0_plat_data = {
int __devinit mmc_init(struct amba_device *adev)
{
struct device *mmcsd_device = &adev->dev;
- struct pmx *pmx;
int ret = 0;
mmcsd_device->platform_data = &mmc0_plat_data;
- /*
- * Setup padmuxing for MMC. Since this must always be
- * compiled into the kernel, pmx is never released.
- */
- pmx = pmx_get(mmcsd_device, U300_APP_PMX_MMC_SETTING);
-
- if (IS_ERR(pmx))
- pr_warning("Could not get padmux handle\n");
- else {
- ret = pmx_activate(mmcsd_device, pmx);
- if (IS_ERR_VALUE(ret))
- pr_warning("Could not activate padmuxing\n");
- }
-
return ret;
}
diff --git a/arch/arm/mach-u300/padmux.c b/arch/arm/mach-u300/padmux.c
deleted file mode 100644
index 4c93c6cefd37..000000000000
--- a/arch/arm/mach-u300/padmux.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/padmux.c
- *
- *
- * Copyright (C) 2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * U300 PADMUX functions
- * Author: Martin Persson <martin.persson@stericsson.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/bug.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <mach/u300-regs.h>
-#include <mach/syscon.h>
-#include "padmux.h"
-
-static DEFINE_MUTEX(pmx_mutex);
-
-const u32 pmx_registers[] = {
- (U300_SYSCON_VBASE + U300_SYSCON_PMC1LR),
- (U300_SYSCON_VBASE + U300_SYSCON_PMC1HR),
- (U300_SYSCON_VBASE + U300_SYSCON_PMC2R),
- (U300_SYSCON_VBASE + U300_SYSCON_PMC3R),
- (U300_SYSCON_VBASE + U300_SYSCON_PMC4R)
-};
-
-/* High level functionality */
-
-/* Lazy dog:
- * onmask = {
- * {"PMC1LR" mask, "PMC1LR" value},
- * {"PMC1HR" mask, "PMC1HR" value},
- * {"PMC2R" mask, "PMC2R" value},
- * {"PMC3R" mask, "PMC3R" value},
- * {"PMC4R" mask, "PMC4R" value}
- * }
- */
-static struct pmx mmc_setting = {
- .setting = U300_APP_PMX_MMC_SETTING,
- .default_on = false,
- .activated = false,
- .name = "MMC",
- .onmask = {
- {U300_SYSCON_PMC1LR_MMCSD_MASK,
- U300_SYSCON_PMC1LR_MMCSD_MMCSD},
- {0, 0},
- {0, 0},
- {0, 0},
- {U300_SYSCON_PMC4R_APP_MISC_12_MASK,
- U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO}
- },
-};
-
-static struct pmx spi_setting = {
- .setting = U300_APP_PMX_SPI_SETTING,
- .default_on = false,
- .activated = false,
- .name = "SPI",
- .onmask = {{0, 0},
- {U300_SYSCON_PMC1HR_APP_SPI_2_MASK |
- U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK |
- U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK,
- U300_SYSCON_PMC1HR_APP_SPI_2_SPI |
- U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI |
- U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI},
- {0, 0},
- {0, 0},
- {0, 0}
- },
-};
-
-/* Available padmux settings */
-static struct pmx *pmx_settings[] = {
- &mmc_setting,
- &spi_setting,
-};
-
-static void update_registers(struct pmx *pmx, bool activate)
-{
- u16 regval, val, mask;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(pmx_registers); i++) {
- if (activate)
- val = pmx->onmask[i].val;
- else
- val = 0;
-
- mask = pmx->onmask[i].mask;
- if (mask != 0) {
- regval = readw(pmx_registers[i]);
- regval &= ~mask;
- regval |= val;
- writew(regval, pmx_registers[i]);
- }
- }
-}
-
-struct pmx *pmx_get(struct device *dev, enum pmx_settings setting)
-{
- int i;
- struct pmx *pmx = ERR_PTR(-ENOENT);
-
- if (dev == NULL)
- return ERR_PTR(-EINVAL);
-
- mutex_lock(&pmx_mutex);
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
- if (setting == pmx_settings[i]->setting) {
-
- if (pmx_settings[i]->dev != NULL) {
- WARN(1, "padmux: required setting "
- "in use by another consumer\n");
- } else {
- pmx = pmx_settings[i];
- pmx->dev = dev;
- dev_dbg(dev, "padmux: setting nr %d is now "
- "bound to %s and ready to use\n",
- setting, dev_name(dev));
- break;
- }
- }
- }
- mutex_unlock(&pmx_mutex);
-
- return pmx;
-}
-EXPORT_SYMBOL(pmx_get);
-
-int pmx_put(struct device *dev, struct pmx *pmx)
-{
- int i;
- int ret = -ENOENT;
-
- if (pmx == NULL || dev == NULL)
- return -EINVAL;
-
- mutex_lock(&pmx_mutex);
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
- if (pmx->setting == pmx_settings[i]->setting) {
-
- if (dev != pmx->dev) {
- WARN(1, "padmux: cannot release handle as "
- "it is bound to another consumer\n");
- ret = -EINVAL;
- break;
- } else {
- pmx_settings[i]->dev = NULL;
- ret = 0;
- break;
- }
- }
- }
- mutex_unlock(&pmx_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(pmx_put);
-
-int pmx_activate(struct device *dev, struct pmx *pmx)
-{
- int i, j, ret;
- ret = 0;
-
- if (pmx == NULL || dev == NULL)
- return -EINVAL;
-
- mutex_lock(&pmx_mutex);
-
- /* Make sure the required bits are not used */
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
- if (pmx_settings[i]->dev == NULL || pmx_settings[i] == pmx)
- continue;
-
- for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) {
-
- if (pmx_settings[i]->onmask[j].mask & pmx->
- onmask[j].mask) {
- /* More than one entry on the same bits */
- WARN(1, "padmux: cannot activate "
- "setting. Bit conflict with "
- "an active setting\n");
-
- ret = -EUSERS;
- goto exit;
- }
- }
- }
- update_registers(pmx, true);
- pmx->activated = true;
- dev_dbg(dev, "padmux: setting nr %d is activated\n",
- pmx->setting);
-
-exit:
- mutex_unlock(&pmx_mutex);
- return ret;
-}
-EXPORT_SYMBOL(pmx_activate);
-
-int pmx_deactivate(struct device *dev, struct pmx *pmx)
-{
- int i;
- int ret = -ENOENT;
-
- if (pmx == NULL || dev == NULL)
- return -EINVAL;
-
- mutex_lock(&pmx_mutex);
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
- if (pmx_settings[i]->dev == NULL)
- continue;
-
- if (pmx->setting == pmx_settings[i]->setting) {
-
- if (dev != pmx->dev) {
- WARN(1, "padmux: cannot deactivate "
- "pmx setting as it was activated "
- "by another consumer\n");
-
- ret = -EBUSY;
- continue;
- } else {
- update_registers(pmx, false);
- pmx_settings[i]->dev = NULL;
- pmx->activated = false;
- ret = 0;
- dev_dbg(dev, "padmux: setting nr %d is deactivated",
- pmx->setting);
- break;
- }
- }
- }
- mutex_unlock(&pmx_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(pmx_deactivate);
-
-/*
- * For internal use only. If it is to be exported,
- * it should be reentrant. Notice that pmx_activate
- * (i.e. runtime settings) always override default settings.
- */
-static int pmx_set_default(void)
-{
- /* Used to identify several entries on the same bits */
- u16 modbits[ARRAY_SIZE(pmx_registers)];
-
- int i, j;
-
- memset(modbits, 0, ARRAY_SIZE(pmx_registers) * sizeof(u16));
-
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
- if (!pmx_settings[i]->default_on)
- continue;
-
- for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) {
-
- /* Make sure there is only one entry on the same bits */
- if (modbits[j] & pmx_settings[i]->onmask[j].mask) {
- BUG();
- return -EUSERS;
- }
- modbits[j] |= pmx_settings[i]->onmask[j].mask;
- }
- update_registers(pmx_settings[i], true);
- }
- return 0;
-}
-
-#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG))
-static int pmx_show(struct seq_file *s, void *data)
-{
- int i;
- seq_printf(s, "-------------------------------------------------\n");
- seq_printf(s, "SETTING BOUND TO DEVICE STATE\n");
- seq_printf(s, "-------------------------------------------------\n");
- mutex_lock(&pmx_mutex);
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
- /* Format pmx and device name nicely */
- char cdp[33];
- int chars;
-
- chars = snprintf(&cdp[0], 17, "%s", pmx_settings[i]->name);
- while (chars < 16) {
- cdp[chars] = ' ';
- chars++;
- }
- chars = snprintf(&cdp[16], 17, "%s", pmx_settings[i]->dev ?
- dev_name(pmx_settings[i]->dev) : "N/A");
- while (chars < 16) {
- cdp[chars+16] = ' ';
- chars++;
- }
- cdp[32] = '\0';
-
- seq_printf(s,
- "%s\t%s\n",
- &cdp[0],
- pmx_settings[i]->activated ?
- "ACTIVATED" : "DEACTIVATED"
- );
-
- }
- mutex_unlock(&pmx_mutex);
- return 0;
-}
-
-static int pmx_open(struct inode *inode, struct file *file)
-{
- return single_open(file, pmx_show, NULL);
-}
-
-static const struct file_operations pmx_operations = {
- .owner = THIS_MODULE,
- .open = pmx_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int __init init_pmx_read_debugfs(void)
-{
- /* Expose a simple debugfs interface to view pmx settings */
- (void) debugfs_create_file("padmux", S_IFREG | S_IRUGO,
- NULL, NULL,
- &pmx_operations);
- return 0;
-}
-
-/*
- * This needs to come in after the core_initcall(),
- * because debugfs is not available until
- * the subsystems come up.
- */
-module_init(init_pmx_read_debugfs);
-#endif
-
-static int __init pmx_init(void)
-{
- int ret;
-
- ret = pmx_set_default();
-
- if (IS_ERR_VALUE(ret))
- pr_crit("padmux: default settings could not be set\n");
-
- return 0;
-}
-
-/* Should be initialized before consumers */
-core_initcall(pmx_init);
diff --git a/arch/arm/mach-u300/padmux.h b/arch/arm/mach-u300/padmux.h
deleted file mode 100644
index 6e8b86064097..000000000000
--- a/arch/arm/mach-u300/padmux.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/padmux.h
- *
- *
- * Copyright (C) 2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * U300 PADMUX API
- * Author: Martin Persson <martin.persson@stericsson.com>
- */
-
-#ifndef __MACH_U300_PADMUX_H
-#define __MACH_U300_PADMUX_H
-
-enum pmx_settings {
- U300_APP_PMX_MMC_SETTING,
- U300_APP_PMX_SPI_SETTING
-};
-
-struct pmx_onmask {
- u16 mask; /* Mask bits */
- u16 val; /* Value when active */
-};
-
-struct pmx {
- struct device *dev;
- enum pmx_settings setting;
- char *name;
- bool activated;
- bool default_on;
- struct pmx_onmask onmask[];
-};
-
-struct pmx *pmx_get(struct device *dev, enum pmx_settings setting);
-int pmx_put(struct device *dev, struct pmx *pmx);
-int pmx_activate(struct device *dev, struct pmx *pmx);
-int pmx_deactivate(struct device *dev, struct pmx *pmx);
-
-#endif
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
index 7b597e2b19e2..a1affacfa59c 100644
--- a/arch/arm/mach-u300/spi.c
+++ b/arch/arm/mach-u300/spi.c
@@ -14,8 +14,6 @@
#include <mach/coh901318.h>
#include <mach/dma_channels.h>
-#include "padmux.h"
-
/*
* The following is for the actual devices on the SSP/SPI bus
*/
@@ -95,25 +93,7 @@ static struct pl022_ssp_controller ssp_platform_data = {
void __init u300_spi_init(struct amba_device *adev)
{
- struct pmx *pmx;
-
adev->dev.platform_data = &ssp_platform_data;
- /*
- * Setup padmuxing for SPI. Since this must always be
- * compiled into the kernel, pmx is never released.
- */
- pmx = pmx_get(&adev->dev, U300_APP_PMX_SPI_SETTING);
-
- if (IS_ERR(pmx))
- dev_warn(&adev->dev, "Could not get padmux handle\n");
- else {
- int ret;
-
- ret = pmx_activate(&adev->dev, pmx);
- if (IS_ERR_VALUE(ret))
- dev_warn(&adev->dev, "Could not activate padmuxing\n");
- }
-
}
void __init u300_spi_register_board_devices(void)
diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c
index 48b3b7f39966..89422ee7f3a8 100644
--- a/arch/arm/mach-u300/u300.c
+++ b/arch/arm/mach-u300/u300.c
@@ -23,21 +23,6 @@
#include <asm/mach/arch.h>
#include <asm/memory.h>
-static void __init u300_reserve(void)
-{
- /*
- * U300 - This platform family can share physical memory
- * between two ARM cpus, one running Linux and the other
- * running another OS.
- */
-#ifdef CONFIG_MACH_U300_SINGLE_RAM
-#if ((CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1) == 1) && \
- CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
- memblock_reserve(PHYS_OFFSET, 0x00100000);
-#endif
-#endif
-}
-
static void __init u300_init_machine(void)
{
u300_init_devices();
@@ -61,9 +46,8 @@ static void __init u300_init_machine(void)
MACHINE_START(U300, MACH_U300_STRING)
/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
- .boot_params = BOOT_PARAMS_OFFSET,
+ .atag_offset = BOOT_PARAMS_OFFSET,
.map_io = u300_map_io,
- .reserve = u300_reserve,
.init_irq = u300_init_irq,
.timer = &u300_timer,
.init_machine = u300_init_machine,
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 1694916e6822..6bd2f451c185 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -3,7 +3,8 @@
#
obj-y := clock.o cpu.o devices.o devices-common.o \
- id.o usb.o
+ id.o usb.o timer.o
+obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \
diff --git a/arch/arm/mach-ux500/Makefile.boot b/arch/arm/mach-ux500/Makefile.boot
index c7e75acfe6c9..ff0a4b5b0a82 100644
--- a/arch/arm/mach-ux500/Makefile.boot
+++ b/arch/arm/mach-ux500/Makefile.boot
@@ -1,4 +1,4 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index f26fd76f72b4..74bfcff2bdf3 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -6,10 +6,10 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include "pins-db8500.h"
@@ -153,7 +153,7 @@ static pin_cfg_t mop500_pins_default[] = {
GPIO7_U1_RTSn | PIN_OUTPUT_HIGH,
};
-static pin_cfg_t mop500_pins_hrefv60[] = {
+static pin_cfg_t hrefv60_pins[] = {
/* WLAN */
GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */
GPIO85_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */
@@ -279,14 +279,26 @@ static pin_cfg_t snowball_pins[] = {
void __init mop500_pins_init(void)
{
nmk_config_pins(mop500_pins_common,
- ARRAY_SIZE(mop500_pins_common));
- if (machine_is_hrefv60())
- nmk_config_pins(mop500_pins_hrefv60,
- ARRAY_SIZE(mop500_pins_hrefv60));
- else if (machine_is_snowball())
- nmk_config_pins(snowball_pins,
- ARRAY_SIZE(snowball_pins));
- else
- nmk_config_pins(mop500_pins_default,
- ARRAY_SIZE(mop500_pins_default));
+ ARRAY_SIZE(mop500_pins_common));
+
+ nmk_config_pins(mop500_pins_default,
+ ARRAY_SIZE(mop500_pins_default));
+}
+
+void __init snowball_pins_init(void)
+{
+ nmk_config_pins(mop500_pins_common,
+ ARRAY_SIZE(mop500_pins_common));
+
+ nmk_config_pins(snowball_pins,
+ ARRAY_SIZE(snowball_pins));
+}
+
+void __init hrefv60_pins_init(void)
+{
+ nmk_config_pins(mop500_pins_common,
+ ARRAY_SIZE(mop500_pins_common));
+
+ nmk_config_pins(hrefv60_pins,
+ ARRAY_SIZE(hrefv60_pins));
}
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index d0cb9e5eb87c..6826faeecc68 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -216,30 +216,48 @@ void __init mop500_sdi_init(void)
/* PoP:ed eMMC on top of DB8500 v1.0 has problems with high speed */
if (!cpu_is_u8500v10())
mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
- /* sdi2 on snowball is in ATL_B mode for FSMC (LAN) */
- if (!machine_is_snowball())
- db8500_add_sdi2(&mop500_sdi2_data, periphid);
+
+ db8500_add_sdi2(&mop500_sdi2_data, periphid);
/* On-board eMMC */
db8500_add_sdi4(&mop500_sdi4_data, periphid);
- if (machine_is_hrefv60() || machine_is_snowball()) {
- if (machine_is_hrefv60()) {
- mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
- sdi0_en = HREFV60_SDMMC_EN_GPIO;
- sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
- } else if (machine_is_snowball()) {
- mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
- mop500_sdi0_data.cd_invert = true;
- sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
- sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
- }
- sdi0_configure();
- }
-
/*
* On boards with the TC35892 GPIO expander, sdi0 will finally
* be added when the TC35892 initializes and calls
* mop500_sdi_tc35892_init() above.
*/
}
+
+void __init snowball_sdi_init(void)
+{
+ u32 periphid = 0x10480180;
+
+ mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+
+ /* On-board eMMC */
+ db8500_add_sdi4(&mop500_sdi4_data, periphid);
+
+ mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
+ mop500_sdi0_data.cd_invert = true;
+ sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
+ sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
+ sdi0_configure();
+}
+
+void __init hrefv60_sdi_init(void)
+{
+ u32 periphid = 0x10480180;
+
+ mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+
+ db8500_add_sdi2(&mop500_sdi2_data, periphid);
+
+ /* On-board eMMC */
+ db8500_add_sdi4(&mop500_sdi4_data, periphid);
+
+ mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
+ sdi0_en = HREFV60_SDMMC_EN_GPIO;
+ sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
+ sdi0_configure();
+}
diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c
index 8ce46c0fdfd5..feb5744d98b7 100644
--- a/arch/arm/mach-ux500/board-mop500-u8500uib.c
+++ b/arch/arm/mach-ux500/board-mop500-u8500uib.c
@@ -4,7 +4,7 @@
* Board data for the U8500 UIB, also known as the New UIB
* License terms: GNU General Public License (GPL), version 2
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/i2c.h>
@@ -13,7 +13,6 @@
#include <linux/mfd/tc3589x.h>
#include <linux/input/matrix_keypad.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>
#include "board-mop500.h"
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index cd54abaccd96..bdd7b80dd7ad 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -37,6 +37,7 @@
#include <plat/i2c.h>
#include <plat/ste_dma40.h>
#include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include <mach/setup.h>
@@ -603,28 +604,72 @@ static void __init mop500_init_machine(void)
{
int i2c0_devs;
+ mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+
+ u8500_init_devices();
+
+ mop500_pins_init();
+
+ platform_add_devices(mop500_platform_devs,
+ ARRAY_SIZE(mop500_platform_devs));
+
+ mop500_i2c_init();
+ mop500_sdi_init();
+ mop500_spi_init();
+ mop500_uart_init();
+
+ 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));
+
+ /* This board has full regulator constraints */
+ regulator_has_full_constraints();
+}
+
+static void __init snowball_init_machine(void)
+{
+ int i2c0_devs;
+
+ u8500_init_devices();
+
+ snowball_pins_init();
+
+ platform_add_devices(snowball_platform_devs,
+ ARRAY_SIZE(snowball_platform_devs));
+
+ mop500_i2c_init();
+ snowball_sdi_init();
+ mop500_spi_init();
+ mop500_uart_init();
+
+ 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));
+
+ /* This board has full regulator constraints */
+ regulator_has_full_constraints();
+}
+
+static void __init hrefv60_init_machine(void)
+{
+ int i2c0_devs;
+
/*
* The HREFv60 board removed a GPIO expander and routed
* all these GPIO pins to the internal GPIO controller
* instead.
*/
- if (!machine_is_snowball()) {
- if (machine_is_hrefv60())
- mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
- else
- mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
- }
+ mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
u8500_init_devices();
- mop500_pins_init();
+ hrefv60_pins_init();
- if (machine_is_snowball())
- platform_add_devices(snowball_platform_devs,
- ARRAY_SIZE(snowball_platform_devs));
- else
- platform_add_devices(mop500_platform_devs,
- ARRAY_SIZE(mop500_platform_devs));
+ platform_add_devices(mop500_platform_devs,
+ ARRAY_SIZE(mop500_platform_devs));
mop500_i2c_init();
mop500_sdi_init();
@@ -632,8 +677,8 @@ static void __init mop500_init_machine(void)
mop500_uart_init();
i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
- if (machine_is_hrefv60())
- i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
+
+ i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
i2c_register_board_info(2, mop500_i2c2_devices,
@@ -645,7 +690,7 @@ static void __init mop500_init_machine(void)
MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
/* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
- .boot_params = 0x100,
+ .atag_offset = 0x100,
.map_io = u8500_map_io,
.init_irq = ux500_init_irq,
/* we re-use nomadik timer here */
@@ -654,18 +699,18 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
MACHINE_END
MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
- .boot_params = 0x100,
+ .atag_offset = 0x100,
.map_io = u8500_map_io,
.init_irq = ux500_init_irq,
.timer = &ux500_timer,
- .init_machine = mop500_init_machine,
+ .init_machine = hrefv60_init_machine,
MACHINE_END
MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
- .boot_params = 0x100,
+ .atag_offset = 0x100,
.map_io = u8500_map_io,
.init_irq = ux500_init_irq,
/* we re-use nomadik timer here */
.timer = &ux500_timer,
- .init_machine = mop500_init_machine,
+ .init_machine = snowball_init_machine,
MACHINE_END
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index ee77a8970c33..de18a2a23e6e 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -40,10 +40,13 @@
struct i2c_board_info;
extern void mop500_sdi_init(void);
+extern void snowball_sdi_init(void);
extern void mop500_sdi_tc35892_init(void);
void __init mop500_u8500uib_init(void);
void __init mop500_stuib_init(void);
void __init mop500_pins_init(void);
+void __init hrefv60_pins_init(void);
+void __init snowball_pins_init(void);
void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
unsigned n);
diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c
index 739fb4c5b160..63c3f8058ffc 100644
--- a/arch/arm/mach-ux500/board-u5500-sdi.c
+++ b/arch/arm/mach-ux500/board-u5500-sdi.c
@@ -7,9 +7,9 @@
#include <linux/amba/mmci.h>
#include <linux/mmc/host.h>
-#include <linux/gpio.h>
#include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
#include <mach/db5500-regs.h>
#include <plat/ste_dma40.h>
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
index 5c9e66502ebb..82025ba70c03 100644
--- a/arch/arm/mach-ux500/board-u5500.c
+++ b/arch/arm/mach-ux500/board-u5500.c
@@ -8,7 +8,6 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
-#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/mfd/ab5500/ab5500.h>
@@ -18,6 +17,7 @@
#include <plat/pincfg.h>
#include <plat/i2c.h>
+#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include <mach/devices.h>
@@ -145,7 +145,7 @@ static void __init u5500_init_machine(void)
}
MACHINE_START(U5500, "ST-Ericsson U5500 Platform")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = u5500_map_io,
.init_irq = ux500_init_irq,
.timer = &ux500_timer,
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c
new file mode 100644
index 000000000000..122ddde00ba7
--- /dev/null
+++ b/arch/arm/mach-ux500/cache-l2x0.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/hardware.h>
+#include <mach/id.h>
+
+static void __iomem *l2x0_base;
+
+static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
+{
+ /* wait for the operation to complete */
+ while (readl_relaxed(reg) & mask)
+ cpu_relax();
+}
+
+static inline void ux500_cache_sync(void)
+{
+ writel_relaxed(0, l2x0_base + L2X0_CACHE_SYNC);
+ ux500_cache_wait(l2x0_base + L2X0_CACHE_SYNC, 1);
+}
+
+/*
+ * The L2 cache cannot be turned off in the non-secure world.
+ * Dummy until a secure service is in place.
+ */
+static void ux500_l2x0_disable(void)
+{
+}
+
+/*
+ * This is only called when doing a kexec, just after turning off the L2
+ * and L1 cache, and it is surrounded by a spinlock in the generic version.
+ * However, we're not really turning off the L2 cache right now and the
+ * PL310 does not support exclusive accesses (used to implement the spinlock).
+ * So, the invalidation needs to be done without the spinlock.
+ */
+static void ux500_l2x0_inv_all(void)
+{
+ uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */
+
+ /* invalidate all ways */
+ writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
+ ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
+ ux500_cache_sync();
+}
+
+static int __init ux500_l2x0_unlock(void)
+{
+ int i;
+
+ /*
+ * Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions
+ * apparently locks both caches before jumping to the kernel. The
+ * l2x0 core will not touch the unlock registers if the l2x0 is
+ * already enabled, so we do it right here instead. The PL310 has
+ * 8 sets of registers, one per possible CPU.
+ */
+ for (i = 0; i < 8; i++) {
+ writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
+ i * L2X0_LOCKDOWN_STRIDE);
+ writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
+ i * L2X0_LOCKDOWN_STRIDE);
+ }
+ return 0;
+}
+
+static int __init ux500_l2x0_init(void)
+{
+ if (cpu_is_u5500())
+ l2x0_base = __io_address(U5500_L2CC_BASE);
+ else if (cpu_is_u8500())
+ l2x0_base = __io_address(U8500_L2CC_BASE);
+ else
+ ux500_unknown_soc();
+
+ /* Unlock before init */
+ ux500_l2x0_unlock();
+
+ /* 64KB way size, 8 way associativity, force WA */
+ l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
+
+ /* Override invalidate function */
+ outer_cache.disable = ux500_l2x0_disable;
+ outer_cache.inv_all = ux500_l2x0_inv_all;
+
+ return 0;
+}
+
+early_initcall(ux500_l2x0_init);
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index 22705d246fc7..9de1af008094 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -13,7 +13,7 @@
#include <asm/mach/map.h>
#include <asm/pmu.h>
-#include <plat/gpio.h>
+#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include <mach/devices.h>
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 4598b06c8c55..13e8890a8b8a 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -14,12 +14,12 @@
#include <linux/amba/bus.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <asm/mach/map.h>
#include <asm/pmu.h>
+#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index bb5653993ca2..f41857494375 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -10,14 +10,12 @@
#include <linux/clk.h>
#include <linux/mfd/db8500-prcmu.h>
#include <linux/mfd/db5500-prcmu.h>
+#include <linux/clksrc-dbx500-prcmu.h>
-#include <asm/cacheflush.h>
-#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/gic.h>
#include <asm/mach/map.h>
#include <asm/localtimer.h>
-#include <plat/mtu.h>
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
@@ -26,10 +24,6 @@
void __iomem *_PRCMU_BASE;
-#ifdef CONFIG_CACHE_L2X0
-static void __iomem *l2x0_base;
-#endif
-
void __init ux500_init_irq(void)
{
void __iomem *dist_base;
@@ -56,93 +50,3 @@ void __init ux500_init_irq(void)
db8500_prcmu_early_init();
clk_init();
}
-
-#ifdef CONFIG_CACHE_L2X0
-static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
-{
- /* wait for the operation to complete */
- while (readl_relaxed(reg) & mask)
- ;
-}
-
-static inline void ux500_cache_sync(void)
-{
- void __iomem *base = l2x0_base;
-
- writel_relaxed(0, base + L2X0_CACHE_SYNC);
- ux500_cache_wait(base + L2X0_CACHE_SYNC, 1);
-}
-
-/*
- * The L2 cache cannot be turned off in the non-secure world.
- * Dummy until a secure service is in place.
- */
-static void ux500_l2x0_disable(void)
-{
-}
-
-/*
- * This is only called when doing a kexec, just after turning off the L2
- * and L1 cache, and it is surrounded by a spinlock in the generic version.
- * However, we're not really turning off the L2 cache right now and the
- * PL310 does not support exclusive accesses (used to implement the spinlock).
- * So, the invalidation needs to be done without the spinlock.
- */
-static void ux500_l2x0_inv_all(void)
-{
- void __iomem *base = l2x0_base;
- uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */
-
- /* invalidate all ways */
- writel_relaxed(l2x0_way_mask, base + L2X0_INV_WAY);
- ux500_cache_wait(base + L2X0_INV_WAY, l2x0_way_mask);
- ux500_cache_sync();
-}
-
-static int ux500_l2x0_init(void)
-{
- if (cpu_is_u5500())
- l2x0_base = __io_address(U5500_L2CC_BASE);
- else if (cpu_is_u8500())
- l2x0_base = __io_address(U8500_L2CC_BASE);
- else
- ux500_unknown_soc();
-
- /* 64KB way size, 8 way associativity, force WA */
- l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
-
- /* Override invalidate function */
- outer_cache.disable = ux500_l2x0_disable;
- outer_cache.inv_all = ux500_l2x0_inv_all;
-
- return 0;
-}
-early_initcall(ux500_l2x0_init);
-#endif
-
-static void __init ux500_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
- /* Setup the local timer base */
- if (cpu_is_u5500())
- twd_base = __io_address(U5500_TWD_BASE);
- else if (cpu_is_u8500())
- twd_base = __io_address(U8500_TWD_BASE);
- else
- ux500_unknown_soc();
-#endif
- if (cpu_is_u5500())
- mtu_base = __io_address(U5500_MTU0_BASE);
- else if (cpu_is_u8500ed())
- mtu_base = __io_address(U8500_MTU0_BASE_ED);
- else if (cpu_is_u8500())
- mtu_base = __io_address(U8500_MTU0_BASE);
- else
- ux500_unknown_soc();
-
- nmdk_timer_init();
-}
-
-struct sys_timer ux500_timer = {
- .init = ux500_timer_init,
-};
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
index 13a4ce046ae5..c563e5418d80 100644
--- a/arch/arm/mach-ux500/devices-common.c
+++ b/arch/arm/mach-ux500/devices-common.c
@@ -13,7 +13,7 @@
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
-#include <plat/gpio.h>
+#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c
index dd8037ebccf8..572015e57cd9 100644
--- a/arch/arm/mach-ux500/hotplug.c
+++ b/arch/arm/mach-ux500/hotplug.c
@@ -24,7 +24,7 @@ static inline void platform_do_lowpower(unsigned int cpu)
for (;;) {
__asm__ __volatile__("dsb\n\t" "wfi\n\t"
: : : "memory");
- if (pen_release == cpu) {
+ if (pen_release == cpu_logical_map(cpu)) {
/*
* OK, proper wakeup, we're done
*/
diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h
index 6ad983294103..994b5fe6f85a 100644
--- a/arch/arm/mach-ux500/include/mach/db5500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h
@@ -61,6 +61,8 @@
#define U5500_SCR_BASE (U5500_PER4_BASE + 0x5000)
#define U5500_DMC_BASE (U5500_PER4_BASE + 0x6000)
#define U5500_PRCMU_BASE (U5500_PER4_BASE + 0x7000)
+#define U5500_PRCMU_TIMER_3_BASE (U5500_PER4_BASE + 0x07338)
+#define U5500_PRCMU_TIMER_4_BASE (U5500_PER4_BASE + 0x07450)
#define U5500_MSP1_BASE (U5500_PER4_BASE + 0x9000)
#define U5500_GPIO2_BASE (U5500_PER4_BASE + 0xA000)
#define U5500_CDETECT_BASE (U5500_PER4_BASE + 0xF000)
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h
index 049997109cf9..751b0e6938d4 100644
--- a/arch/arm/mach-ux500/include/mach/db8500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h
@@ -102,10 +102,13 @@
#define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000)
#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000)
#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000)
+#define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338)
+#define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450)
#define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000)
#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000)
#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000)
+
/* per3 base addresses */
#define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000)
#define U8500_SSP0_BASE (U8500_PER3_BASE + 0x2000)
diff --git a/arch/arm/mach-ux500/include/mach/debug-macro.S b/arch/arm/mach-ux500/include/mach/debug-macro.S
index 700fb05ee815..8d74d927d4e2 100644
--- a/arch/arm/mach-ux500/include/mach/debug-macro.S
+++ b/arch/arm/mach-ux500/include/mach/debug-macro.S
@@ -35,7 +35,7 @@
#define UX500_UART(n) __UX500_UART(n)
#define UART_BASE UX500_UART(CONFIG_UX500_DEBUG_UART)
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =UART_BASE @ no, physical address
ldr \rv, =IO_ADDRESS(UART_BASE) @ yes, virtual address
.endm
diff --git a/arch/arm/mach-ux500/include/mach/gpio.h b/arch/arm/mach-ux500/include/mach/gpio.h
index 3c4cd31ad9f7..7389df911b1a 100644
--- a/arch/arm/mach-ux500/include/mach/gpio.h
+++ b/arch/arm/mach-ux500/include/mach/gpio.h
@@ -7,6 +7,4 @@
*/
#define ARCH_NR_GPIOS 350
-#include <plat/gpio.h>
-
#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-ux500/include/mach/memory.h b/arch/arm/mach-ux500/include/mach/memory.h
deleted file mode 100644
index 2ef697a67006..000000000000
--- a/arch/arm/mach-ux500/include/mach/memory.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2009 ST-Ericsson
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-#define BUS_OFFSET UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h
index 7dd08074c37b..6fb3c4b0105d 100644
--- a/arch/arm/mach-ux500/include/mach/uncompress.h
+++ b/arch/arm/mach-ux500/include/mach/uncompress.h
@@ -51,15 +51,9 @@ static void flush(void)
static inline void arch_decomp_setup(void)
{
/* Check in run time if we run on an U8500 or U5500 */
- if (machine_is_u8500() ||
- machine_is_svp8500v1() ||
- machine_is_svp8500v2() ||
- machine_is_hrefv60() ||
- machine_is_snowball())
- ux500_uart_base = U8500_UART2_BASE;
- else if (machine_is_u5500())
+ if (machine_is_u5500())
ux500_uart_base = U5500_UART0_BASE;
- else /* not much can be done to help here */
+ else
ux500_uart_base = U8500_UART2_BASE;
}
diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h
index f923764ee16c..8b1d1a7a679e 100644
--- a/arch/arm/mach-ux500/pins-db8500.h
+++ b/arch/arm/mach-ux500/pins-db8500.h
@@ -35,40 +35,40 @@
#define GPIO4_GPIO PIN_CFG(4, GPIO)
#define GPIO4_U1_RXD PIN_CFG(4, ALT_A)
-#define GPIO4_I2C4_SCL PIN_CFG_PULL(4, ALT_B, UP)
+#define GPIO4_I2C4_SCL PIN_CFG_INPUT(4, ALT_B, PULLUP)
#define GPIO4_IP_TRSTn PIN_CFG(4, ALT_C)
#define GPIO5_GPIO PIN_CFG(5, GPIO)
#define GPIO5_U1_TXD PIN_CFG(5, ALT_A)
-#define GPIO5_I2C4_SDA PIN_CFG_PULL(5, ALT_B, UP)
+#define GPIO5_I2C4_SDA PIN_CFG_INPUT(5, ALT_B, PULLUP)
#define GPIO5_IP_GPIO6 PIN_CFG(5, ALT_C)
#define GPIO6_GPIO PIN_CFG(6, GPIO)
#define GPIO6_U1_CTSn PIN_CFG(6, ALT_A)
-#define GPIO6_I2C1_SCL PIN_CFG_PULL(6, ALT_B, UP)
+#define GPIO6_I2C1_SCL PIN_CFG_INPUT(6, ALT_B, PULLUP)
#define GPIO6_IP_GPIO0 PIN_CFG(6, ALT_C)
#define GPIO7_GPIO PIN_CFG(7, GPIO)
#define GPIO7_U1_RTSn PIN_CFG(7, ALT_A)
-#define GPIO7_I2C1_SDA PIN_CFG_PULL(7, ALT_B, UP)
+#define GPIO7_I2C1_SDA PIN_CFG_INPUT(7, ALT_B, PULLUP)
#define GPIO7_IP_GPIO1 PIN_CFG(7, ALT_C)
#define GPIO8_GPIO PIN_CFG(8, GPIO)
-#define GPIO8_IPI2C_SDA PIN_CFG_PULL(8, ALT_A, UP)
-#define GPIO8_I2C2_SDA PIN_CFG_PULL(8, ALT_B, UP)
+#define GPIO8_IPI2C_SDA PIN_CFG_INPUT(8, ALT_A, PULLUP)
+#define GPIO8_I2C2_SDA PIN_CFG_INPUT(8, ALT_B, PULLUP)
#define GPIO9_GPIO PIN_CFG(9, GPIO)
-#define GPIO9_IPI2C_SCL PIN_CFG_PULL(9, ALT_A, UP)
-#define GPIO9_I2C2_SCL PIN_CFG_PULL(9, ALT_B, UP)
+#define GPIO9_IPI2C_SCL PIN_CFG_INPUT(9, ALT_A, PULLUP)
+#define GPIO9_I2C2_SCL PIN_CFG_INPUT(9, ALT_B, PULLUP)
#define GPIO10_GPIO PIN_CFG(10, GPIO)
-#define GPIO10_IPI2C_SDA PIN_CFG_PULL(10, ALT_A, UP)
-#define GPIO10_I2C2_SDA PIN_CFG_PULL(10, ALT_B, UP)
+#define GPIO10_IPI2C_SDA PIN_CFG_INPUT(10, ALT_A, PULLUP)
+#define GPIO10_I2C2_SDA PIN_CFG_INPUT(10, ALT_B, PULLUP)
#define GPIO10_IP_GPIO3 PIN_CFG(10, ALT_C)
#define GPIO11_GPIO PIN_CFG(11, GPIO)
-#define GPIO11_IPI2C_SCL PIN_CFG_PULL(11, ALT_A, UP)
-#define GPIO11_I2C2_SCL PIN_CFG_PULL(11, ALT_B, UP)
+#define GPIO11_IPI2C_SCL PIN_CFG_INPUT(11, ALT_A, PULLUP)
+#define GPIO11_I2C2_SCL PIN_CFG_INPUT(11, ALT_B, PULLUP)
#define GPIO11_IP_GPIO2 PIN_CFG(11, ALT_C)
#define GPIO12_GPIO PIN_CFG(12, GPIO)
@@ -87,66 +87,66 @@
#define GPIO16_GPIO PIN_CFG(16, GPIO)
#define GPIO16_MSP0_RFS PIN_CFG(16, ALT_A)
-#define GPIO16_I2C1_SCL PIN_CFG_PULL(16, ALT_B, UP)
+#define GPIO16_I2C1_SCL PIN_CFG_INPUT(16, ALT_B, PULLUP)
#define GPIO16_SLIM0_DAT PIN_CFG(16, ALT_C)
#define GPIO17_GPIO PIN_CFG(17, GPIO)
#define GPIO17_MSP0_RCK PIN_CFG(17, ALT_A)
-#define GPIO17_I2C1_SDA PIN_CFG_PULL(17, ALT_B, UP)
+#define GPIO17_I2C1_SDA PIN_CFG_INPUT(17, ALT_B, PULLUP)
#define GPIO17_SLIM0_CLK PIN_CFG(17, ALT_C)
#define GPIO18_GPIO PIN_CFG(18, GPIO)
-#define GPIO18_MC0_CMDDIR PIN_CFG_PULL(18, ALT_A, UP)
+#define GPIO18_MC0_CMDDIR PIN_CFG_INPUT(18, ALT_A, PULLUP)
#define GPIO18_U2_RXD PIN_CFG(18, ALT_B)
#define GPIO18_MS_IEP PIN_CFG(18, ALT_C)
#define GPIO19_GPIO PIN_CFG(19, GPIO)
-#define GPIO19_MC0_DAT0DIR PIN_CFG_PULL(19, ALT_A, UP)
+#define GPIO19_MC0_DAT0DIR PIN_CFG_INPUT(19, ALT_A, PULLUP)
#define GPIO19_U2_TXD PIN_CFG(19, ALT_B)
#define GPIO19_MS_DAT0DIR PIN_CFG(19, ALT_C)
#define GPIO20_GPIO PIN_CFG(20, GPIO)
-#define GPIO20_MC0_DAT2DIR PIN_CFG_PULL(20, ALT_A, UP)
+#define GPIO20_MC0_DAT2DIR PIN_CFG_INPUT(20, ALT_A, PULLUP)
#define GPIO20_UARTMOD_TXD PIN_CFG(20, ALT_B)
#define GPIO20_IP_TRIGOUT PIN_CFG(20, ALT_C)
#define GPIO21_GPIO PIN_CFG(21, GPIO)
-#define GPIO21_MC0_DAT31DIR PIN_CFG_PULL(21, ALT_A, UP)
+#define GPIO21_MC0_DAT31DIR PIN_CFG_INPUT(21, ALT_A, PULLUP)
#define GPIO21_MSP0_SCK PIN_CFG(21, ALT_B)
#define GPIO21_MS_DAT31DIR PIN_CFG(21, ALT_C)
#define GPIO22_GPIO PIN_CFG(22, GPIO)
-#define GPIO22_MC0_FBCLK PIN_CFG_PULL(22, ALT_A, UP)
+#define GPIO22_MC0_FBCLK PIN_CFG_INPUT(22, ALT_A, PULLUP)
#define GPIO22_UARTMOD_RXD PIN_CFG(22, ALT_B)
#define GPIO22_MS_FBCLK PIN_CFG(22, ALT_C)
#define GPIO23_GPIO PIN_CFG(23, GPIO)
-#define GPIO23_MC0_CLK PIN_CFG_PULL(23, ALT_A, UP)
+#define GPIO23_MC0_CLK PIN_CFG_INPUT(23, ALT_A, PULLUP)
#define GPIO23_STMMOD_CLK PIN_CFG(23, ALT_B)
#define GPIO23_MS_CLK PIN_CFG(23, ALT_C)
#define GPIO24_GPIO PIN_CFG(24, GPIO)
-#define GPIO24_MC0_CMD PIN_CFG_PULL(24, ALT_A, UP)
+#define GPIO24_MC0_CMD PIN_CFG_INPUT(24, ALT_A, PULLUP)
#define GPIO24_UARTMOD_RXD PIN_CFG(24, ALT_B)
#define GPIO24_MS_BS PIN_CFG(24, ALT_C)
#define GPIO25_GPIO PIN_CFG(25, GPIO)
-#define GPIO25_MC0_DAT0 PIN_CFG_PULL(25, ALT_A, UP)
+#define GPIO25_MC0_DAT0 PIN_CFG_INPUT(25, ALT_A, PULLUP)
#define GPIO25_STMMOD_DAT0 PIN_CFG(25, ALT_B)
#define GPIO25_MS_DAT0 PIN_CFG(25, ALT_C)
#define GPIO26_GPIO PIN_CFG(26, GPIO)
-#define GPIO26_MC0_DAT1 PIN_CFG_PULL(26, ALT_A, UP)
+#define GPIO26_MC0_DAT1 PIN_CFG_INPUT(26, ALT_A, PULLUP)
#define GPIO26_STMMOD_DAT1 PIN_CFG(26, ALT_B)
#define GPIO26_MS_DAT1 PIN_CFG(26, ALT_C)
#define GPIO27_GPIO PIN_CFG(27, GPIO)
-#define GPIO27_MC0_DAT2 PIN_CFG_PULL(27, ALT_A, UP)
+#define GPIO27_MC0_DAT2 PIN_CFG_INPUT(27, ALT_A, PULLUP)
#define GPIO27_STMMOD_DAT2 PIN_CFG(27, ALT_B)
#define GPIO27_MS_DAT2 PIN_CFG(27, ALT_C)
#define GPIO28_GPIO PIN_CFG(28, GPIO)
-#define GPIO28_MC0_DAT3 PIN_CFG_PULL(28, ALT_A, UP)
+#define GPIO28_MC0_DAT3 PIN_CFG_INPUT(28, ALT_A, PULLUP)
#define GPIO28_STMMOD_DAT3 PIN_CFG(28, ALT_B)
#define GPIO28_MS_DAT3 PIN_CFG(28, ALT_C)
@@ -357,48 +357,48 @@
#define GPIO97_MC5_DAT7 PIN_CFG(97, ALT_C)
#define GPIO128_GPIO PIN_CFG(128, GPIO)
-#define GPIO128_MC2_CLK PIN_CFG_PULL(128, ALT_A, UP)
+#define GPIO128_MC2_CLK PIN_CFG_INPUT(128, ALT_A, PULLUP)
#define GPIO128_SM_CKO PIN_CFG(128, ALT_B)
#define GPIO129_GPIO PIN_CFG(129, GPIO)
-#define GPIO129_MC2_CMD PIN_CFG_PULL(129, ALT_A, UP)
+#define GPIO129_MC2_CMD PIN_CFG_INPUT(129, ALT_A, PULLUP)
#define GPIO129_SM_WAIT0n PIN_CFG(129, ALT_B)
#define GPIO130_GPIO PIN_CFG(130, GPIO)
-#define GPIO130_MC2_FBCLK PIN_CFG_PULL(130, ALT_A, UP)
+#define GPIO130_MC2_FBCLK PIN_CFG_INPUT(130, ALT_A, PULLUP)
#define GPIO130_SM_FBCLK PIN_CFG(130, ALT_B)
#define GPIO130_MC2_RSTN PIN_CFG(130, ALT_C)
#define GPIO131_GPIO PIN_CFG(131, GPIO)
-#define GPIO131_MC2_DAT0 PIN_CFG_PULL(131, ALT_A, UP)
+#define GPIO131_MC2_DAT0 PIN_CFG_INPUT(131, ALT_A, PULLUP)
#define GPIO131_SM_ADQ8 PIN_CFG(131, ALT_B)
#define GPIO132_GPIO PIN_CFG(132, GPIO)
-#define GPIO132_MC2_DAT1 PIN_CFG_PULL(132, ALT_A, UP)
+#define GPIO132_MC2_DAT1 PIN_CFG_INPUT(132, ALT_A, PULLUP)
#define GPIO132_SM_ADQ9 PIN_CFG(132, ALT_B)
#define GPIO133_GPIO PIN_CFG(133, GPIO)
-#define GPIO133_MC2_DAT2 PIN_CFG_PULL(133, ALT_A, UP)
+#define GPIO133_MC2_DAT2 PIN_CFG_INPUT(133, ALT_A, PULLUP)
#define GPIO133_SM_ADQ10 PIN_CFG(133, ALT_B)
#define GPIO134_GPIO PIN_CFG(134, GPIO)
-#define GPIO134_MC2_DAT3 PIN_CFG_PULL(134, ALT_A, UP)
+#define GPIO134_MC2_DAT3 PIN_CFG_INPUT(134, ALT_A, PULLUP)
#define GPIO134_SM_ADQ11 PIN_CFG(134, ALT_B)
#define GPIO135_GPIO PIN_CFG(135, GPIO)
-#define GPIO135_MC2_DAT4 PIN_CFG_PULL(135, ALT_A, UP)
+#define GPIO135_MC2_DAT4 PIN_CFG_INPUT(135, ALT_A, PULLUP)
#define GPIO135_SM_ADQ12 PIN_CFG(135, ALT_B)
#define GPIO136_GPIO PIN_CFG(136, GPIO)
-#define GPIO136_MC2_DAT5 PIN_CFG_PULL(136, ALT_A, UP)
+#define GPIO136_MC2_DAT5 PIN_CFG_INPUT(136, ALT_A, PULLUP)
#define GPIO136_SM_ADQ13 PIN_CFG(136, ALT_B)
#define GPIO137_GPIO PIN_CFG(137, GPIO)
-#define GPIO137_MC2_DAT6 PIN_CFG_PULL(137, ALT_A, UP)
+#define GPIO137_MC2_DAT6 PIN_CFG_INPUT(137, ALT_A, PULLUP)
#define GPIO137_SM_ADQ14 PIN_CFG(137, ALT_B)
#define GPIO138_GPIO PIN_CFG(138, GPIO)
-#define GPIO138_MC2_DAT7 PIN_CFG_PULL(138, ALT_A, UP)
+#define GPIO138_MC2_DAT7 PIN_CFG_INPUT(138, ALT_A, PULLUP)
#define GPIO138_SM_ADQ15 PIN_CFG(138, ALT_B)
#define GPIO139_GPIO PIN_CFG(139, GPIO)
@@ -434,10 +434,10 @@
#define GPIO146_SSP0_TXD PIN_CFG(146, ALT_A)
#define GPIO147_GPIO PIN_CFG(147, GPIO)
-#define GPIO147_I2C0_SCL PIN_CFG_PULL(147, ALT_A, UP)
+#define GPIO147_I2C0_SCL PIN_CFG_INPUT(147, ALT_A, PULLUP)
#define GPIO148_GPIO PIN_CFG(148, GPIO)
-#define GPIO148_I2C0_SDA PIN_CFG_PULL(148, ALT_A, UP)
+#define GPIO148_I2C0_SDA PIN_CFG_INPUT(148, ALT_A, PULLUP)
#define GPIO149_GPIO PIN_CFG(149, GPIO)
#define GPIO149_IP_GPIO0 PIN_CFG(149, ALT_A)
@@ -459,82 +459,82 @@
#define GPIO152_KP_O9 PIN_CFG(152, ALT_C)
#define GPIO153_GPIO PIN_CFG(153, GPIO)
-#define GPIO153_KP_I7 PIN_CFG_PULL(153, ALT_A, DOWN)
+#define GPIO153_KP_I7 PIN_CFG_INPUT(153, ALT_A, PULLDOWN)
#define GPIO153_LCD_D24 PIN_CFG(153, ALT_B)
#define GPIO153_U2_RXD PIN_CFG(153, ALT_C)
#define GPIO154_GPIO PIN_CFG(154, GPIO)
-#define GPIO154_KP_I6 PIN_CFG_PULL(154, ALT_A, DOWN)
+#define GPIO154_KP_I6 PIN_CFG_INPUT(154, ALT_A, PULLDOWN)
#define GPIO154_LCD_D25 PIN_CFG(154, ALT_B)
#define GPIO154_U2_TXD PIN_CFG(154, ALT_C)
#define GPIO155_GPIO PIN_CFG(155, GPIO)
-#define GPIO155_KP_I5 PIN_CFG_PULL(155, ALT_A, DOWN)
+#define GPIO155_KP_I5 PIN_CFG_INPUT(155, ALT_A, PULLDOWN)
#define GPIO155_LCD_D26 PIN_CFG(155, ALT_B)
#define GPIO155_STMAPE_CLK PIN_CFG(155, ALT_C)
#define GPIO156_GPIO PIN_CFG(156, GPIO)
-#define GPIO156_KP_I4 PIN_CFG_PULL(156, ALT_A, DOWN)
+#define GPIO156_KP_I4 PIN_CFG_INPUT(156, ALT_A, PULLDOWN)
#define GPIO156_LCD_D27 PIN_CFG(156, ALT_B)
#define GPIO156_STMAPE_DAT3 PIN_CFG(156, ALT_C)
#define GPIO157_GPIO PIN_CFG(157, GPIO)
-#define GPIO157_KP_O7 PIN_CFG_PULL(157, ALT_A, UP)
+#define GPIO157_KP_O7 PIN_CFG_INPUT(157, ALT_A, PULLUP)
#define GPIO157_LCD_D28 PIN_CFG(157, ALT_B)
#define GPIO157_STMAPE_DAT2 PIN_CFG(157, ALT_C)
#define GPIO158_GPIO PIN_CFG(158, GPIO)
-#define GPIO158_KP_O6 PIN_CFG_PULL(158, ALT_A, UP)
+#define GPIO158_KP_O6 PIN_CFG_INPUT(158, ALT_A, PULLUP)
#define GPIO158_LCD_D29 PIN_CFG(158, ALT_B)
#define GPIO158_STMAPE_DAT1 PIN_CFG(158, ALT_C)
#define GPIO159_GPIO PIN_CFG(159, GPIO)
-#define GPIO159_KP_O5 PIN_CFG_PULL(159, ALT_A, UP)
+#define GPIO159_KP_O5 PIN_CFG_INPUT(159, ALT_A, PULLUP)
#define GPIO159_LCD_D30 PIN_CFG(159, ALT_B)
#define GPIO159_STMAPE_DAT0 PIN_CFG(159, ALT_C)
#define GPIO160_GPIO PIN_CFG(160, GPIO)
-#define GPIO160_KP_O4 PIN_CFG_PULL(160, ALT_A, UP)
+#define GPIO160_KP_O4 PIN_CFG_INPUT(160, ALT_A, PULLUP)
#define GPIO160_LCD_D31 PIN_CFG(160, ALT_B)
#define GPIO160_NONE PIN_CFG(160, ALT_C)
#define GPIO161_GPIO PIN_CFG(161, GPIO)
-#define GPIO161_KP_I3 PIN_CFG_PULL(161, ALT_A, DOWN)
+#define GPIO161_KP_I3 PIN_CFG_INPUT(161, ALT_A, PULLDOWN)
#define GPIO161_LCD_D32 PIN_CFG(161, ALT_B)
#define GPIO161_UARTMOD_RXD PIN_CFG(161, ALT_C)
#define GPIO162_GPIO PIN_CFG(162, GPIO)
-#define GPIO162_KP_I2 PIN_CFG_PULL(162, ALT_A, DOWN)
+#define GPIO162_KP_I2 PIN_CFG_INPUT(162, ALT_A, PULLDOWN)
#define GPIO162_LCD_D33 PIN_CFG(162, ALT_B)
#define GPIO162_UARTMOD_TXD PIN_CFG(162, ALT_C)
#define GPIO163_GPIO PIN_CFG(163, GPIO)
-#define GPIO163_KP_I1 PIN_CFG_PULL(163, ALT_A, DOWN)
+#define GPIO163_KP_I1 PIN_CFG_INPUT(163, ALT_A, PULLDOWN)
#define GPIO163_LCD_D34 PIN_CFG(163, ALT_B)
#define GPIO163_STMMOD_CLK PIN_CFG(163, ALT_C)
#define GPIO164_GPIO PIN_CFG(164, GPIO)
-#define GPIO164_KP_I0 PIN_CFG_PULL(164, ALT_A, UP)
+#define GPIO164_KP_I0 PIN_CFG_INPUT(164, ALT_A, PULLUP)
#define GPIO164_LCD_D35 PIN_CFG(164, ALT_B)
#define GPIO164_STMMOD_DAT3 PIN_CFG(164, ALT_C)
#define GPIO165_GPIO PIN_CFG(165, GPIO)
-#define GPIO165_KP_O3 PIN_CFG_PULL(165, ALT_A, UP)
+#define GPIO165_KP_O3 PIN_CFG_INPUT(165, ALT_A, PULLUP)
#define GPIO165_LCD_D36 PIN_CFG(165, ALT_B)
#define GPIO165_STMMOD_DAT2 PIN_CFG(165, ALT_C)
#define GPIO166_GPIO PIN_CFG(166, GPIO)
-#define GPIO166_KP_O2 PIN_CFG_PULL(166, ALT_A, UP)
+#define GPIO166_KP_O2 PIN_CFG_INPUT(166, ALT_A, PULLUP)
#define GPIO166_LCD_D37 PIN_CFG(166, ALT_B)
#define GPIO166_STMMOD_DAT1 PIN_CFG(166, ALT_C)
#define GPIO167_GPIO PIN_CFG(167, GPIO)
-#define GPIO167_KP_O1 PIN_CFG_PULL(167, ALT_A, UP)
+#define GPIO167_KP_O1 PIN_CFG_INPUT(167, ALT_A, PULLUP)
#define GPIO167_LCD_D38 PIN_CFG(167, ALT_B)
#define GPIO167_STMMOD_DAT0 PIN_CFG(167, ALT_C)
#define GPIO168_GPIO PIN_CFG(168, GPIO)
-#define GPIO168_KP_O0 PIN_CFG_PULL(168, ALT_A, UP)
+#define GPIO168_KP_O0 PIN_CFG_INPUT(168, ALT_A, PULLUP)
#define GPIO168_LCD_D39 PIN_CFG(168, ALT_B)
#define GPIO168_NONE PIN_CFG(168, ALT_C)
@@ -569,39 +569,39 @@
#define GPIO196_MSP2_RXD PIN_CFG(196, ALT_A)
#define GPIO197_GPIO PIN_CFG(197, GPIO)
-#define GPIO197_MC4_DAT3 PIN_CFG_PULL(197, ALT_A, UP)
+#define GPIO197_MC4_DAT3 PIN_CFG_INPUT(197, ALT_A, PULLUP)
#define GPIO198_GPIO PIN_CFG(198, GPIO)
-#define GPIO198_MC4_DAT2 PIN_CFG_PULL(198, ALT_A, UP)
+#define GPIO198_MC4_DAT2 PIN_CFG_INPUT(198, ALT_A, PULLUP)
#define GPIO199_GPIO PIN_CFG(199, GPIO)
-#define GPIO199_MC4_DAT1 PIN_CFG_PULL(199, ALT_A, UP)
+#define GPIO199_MC4_DAT1 PIN_CFG_INPUT(199, ALT_A, PULLUP)
#define GPIO200_GPIO PIN_CFG(200, GPIO)
-#define GPIO200_MC4_DAT0 PIN_CFG_PULL(200, ALT_A, UP)
+#define GPIO200_MC4_DAT0 PIN_CFG_INPUT(200, ALT_A, PULLUP)
#define GPIO201_GPIO PIN_CFG(201, GPIO)
-#define GPIO201_MC4_CMD PIN_CFG_PULL(201, ALT_A, UP)
+#define GPIO201_MC4_CMD PIN_CFG_INPUT(201, ALT_A, PULLUP)
#define GPIO202_GPIO PIN_CFG(202, GPIO)
-#define GPIO202_MC4_FBCLK PIN_CFG_PULL(202, ALT_A, UP)
+#define GPIO202_MC4_FBCLK PIN_CFG_INPUT(202, ALT_A, PULLUP)
#define GPIO202_PWL PIN_CFG(202, ALT_B)
#define GPIO202_MC4_RSTN PIN_CFG(202, ALT_C)
#define GPIO203_GPIO PIN_CFG(203, GPIO)
-#define GPIO203_MC4_CLK PIN_CFG_PULL(203, ALT_A, UP)
+#define GPIO203_MC4_CLK PIN_CFG_INPUT(203, ALT_A, PULLUP)
#define GPIO204_GPIO PIN_CFG(204, GPIO)
-#define GPIO204_MC4_DAT7 PIN_CFG_PULL(204, ALT_A, UP)
+#define GPIO204_MC4_DAT7 PIN_CFG_INPUT(204, ALT_A, PULLUP)
#define GPIO205_GPIO PIN_CFG(205, GPIO)
-#define GPIO205_MC4_DAT6 PIN_CFG_PULL(205, ALT_A, UP)
+#define GPIO205_MC4_DAT6 PIN_CFG_INPUT(205, ALT_A, PULLUP)
#define GPIO206_GPIO PIN_CFG(206, GPIO)
-#define GPIO206_MC4_DAT5 PIN_CFG_PULL(206, ALT_A, UP)
+#define GPIO206_MC4_DAT5 PIN_CFG_INPUT(206, ALT_A, PULLUP)
#define GPIO207_GPIO PIN_CFG(207, GPIO)
-#define GPIO207_MC4_DAT4 PIN_CFG_PULL(207, ALT_A, UP)
+#define GPIO207_MC4_DAT4 PIN_CFG_INPUT(207, ALT_A, PULLUP)
#define GPIO208_GPIO PIN_CFG(208, GPIO)
#define GPIO208_MC1_CLK PIN_CFG(208, ALT_A)
@@ -632,21 +632,25 @@
#define GPIO215_MC1_CMDDIR PIN_CFG(215, ALT_A)
#define GPIO215_MC3_DAT2DIR PIN_CFG(215, ALT_B)
#define GPIO215_CLKOUT1 PIN_CFG(215, ALT_C)
+#define GPIO215_SPI2_TXD PIN_CFG(215, ALT_C)
#define GPIO216_GPIO PIN_CFG(216, GPIO)
#define GPIO216_MC1_DAT2DIR PIN_CFG(216, ALT_A)
#define GPIO216_MC3_CMDDIR PIN_CFG(216, ALT_B)
-#define GPIO216_I2C3_SDA PIN_CFG_PULL(216, ALT_C, UP)
+#define GPIO216_I2C3_SDA PIN_CFG_INPUT(216, ALT_C, PULLUP)
+#define GPIO216_SPI2_FRM PIN_CFG(216, ALT_C)
#define GPIO217_GPIO PIN_CFG(217, GPIO)
#define GPIO217_MC1_DAT0DIR PIN_CFG(217, ALT_A)
#define GPIO217_MC3_DAT31DIR PIN_CFG(217, ALT_B)
#define GPIO217_CLKOUT2 PIN_CFG(217, ALT_C)
+#define GPIO217_SPI2_CLK PIN_CFG(217, ALT_C)
#define GPIO218_GPIO PIN_CFG(218, GPIO)
#define GPIO218_MC1_DAT31DIR PIN_CFG(218, ALT_A)
#define GPIO218_MC3_DAT0DIR PIN_CFG(218, ALT_B)
-#define GPIO218_I2C3_SCL PIN_CFG_PULL(218, ALT_C, UP)
+#define GPIO218_I2C3_SCL PIN_CFG_INPUT(218, ALT_C, PULLUP)
+#define GPIO218_SPI2_RXD PIN_CFG(218, ALT_C)
#define GPIO219_GPIO PIN_CFG(219, GPIO)
#define GPIO219_HSIR_FLA0 PIN_CFG(219, ALT_A)
@@ -694,12 +698,12 @@
#define GPIO229_GPIO PIN_CFG(229, GPIO)
#define GPIO229_CLKOUT1 PIN_CFG(229, ALT_A)
#define GPIO229_PWL PIN_CFG(229, ALT_B)
-#define GPIO229_I2C3_SDA PIN_CFG_PULL(229, ALT_C, UP)
+#define GPIO229_I2C3_SDA PIN_CFG_INPUT(229, ALT_C, PULLUP)
#define GPIO230_GPIO PIN_CFG(230, GPIO)
#define GPIO230_CLKOUT2 PIN_CFG(230, ALT_A)
#define GPIO230_PWL PIN_CFG(230, ALT_B)
-#define GPIO230_I2C3_SCL PIN_CFG_PULL(230, ALT_C, UP)
+#define GPIO230_I2C3_SCL PIN_CFG_INPUT(230, ALT_C, PULLUP)
#define GPIO256_GPIO PIN_CFG(256, GPIO)
#define GPIO256_USB_NXT PIN_CFG(256, ALT_A)
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index a33df5f4c27a..a19e398dade3 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -96,7 +96,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
* the holding pen - release it, then wait for it to flag
* that it has been released by resetting pen_release.
*/
- write_pen_release(cpu);
+ write_pen_release(cpu_logical_map(cpu));
gic_raise_softirq(cpumask_of(cpu), 1);
@@ -156,12 +156,10 @@ void __init smp_init_cpus(void)
ncores = scu_base ? scu_get_core_count(scu_base) : 1;
/* sanity check */
- if (ncores > NR_CPUS) {
- printk(KERN_WARNING
- "U8500: no. of cores (%d) greater than configured "
- "maximum of %d - clipping\n",
- ncores, NR_CPUS);
- ncores = NR_CPUS;
+ if (ncores > nr_cpu_ids) {
+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+ ncores, nr_cpu_ids);
+ ncores = nr_cpu_ids;
}
for (i = 0; i < ncores; i++)
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
new file mode 100644
index 000000000000..aea467d04ff7
--- /dev/null
+++ b/arch/arm/mach-ux500/timer.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
+ */
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/clksrc-dbx500-prcmu.h>
+
+#include <asm/localtimer.h>
+
+#include <plat/mtu.h>
+
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+static void __init ux500_timer_init(void)
+{
+ void __iomem *prcmu_timer_base;
+
+ if (cpu_is_u5500()) {
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = __io_address(U5500_TWD_BASE);
+#endif
+ mtu_base = __io_address(U5500_MTU0_BASE);
+ prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE);
+ } else if (cpu_is_u8500()) {
+#ifdef CONFIG_LOCAL_TIMERS
+ twd_base = __io_address(U8500_TWD_BASE);
+#endif
+ mtu_base = __io_address(U8500_MTU0_BASE);
+ prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
+ } else {
+ ux500_unknown_soc();
+ }
+
+ /*
+ * Here we register the timerblocks active in the system.
+ * Localtimers (twd) is started when both cpu is up and running.
+ * MTU register a clocksource, clockevent and sched_clock.
+ * Since the MTU is located in the VAPE power domain
+ * it will be cleared in sleep which makes it unsuitable.
+ * We however need it as a timer tick (clockevent)
+ * during boot to calibrate delay until twd is started.
+ * RTC-RTT have problems as timer tick during boot since it is
+ * depending on delay which is not yet calibrated. RTC-RTT is in the
+ * always-on powerdomain and is used as clockevent instead of twd when
+ * sleeping.
+ * The PRCMU timer 4(3 for DB5500) register a clocksource and
+ * sched_clock with higher rating then MTU since is always-on.
+ *
+ */
+
+ nmdk_timer_init();
+ clksrc_dbx500_prcmu_init(prcmu_timer_base);
+}
+
+static void ux500_timer_reset(void)
+{
+ nmdk_clkevt_reset();
+ nmdk_clksrc_reset();
+}
+
+struct sys_timer ux500_timer = {
+ .init = ux500_timer_init,
+ .resume = ux500_timer_reset,
+};
diff --git a/arch/arm/mach-versatile/Makefile.boot b/arch/arm/mach-versatile/Makefile.boot
index c7e75acfe6c9..ff0a4b5b0a82 100644
--- a/arch/arm/mach-versatile/Makefile.boot
+++ b/arch/arm/mach-versatile/Makefile.boot
@@ -1,4 +1,4 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-versatile/include/mach/debug-macro.S b/arch/arm/mach-versatile/include/mach/debug-macro.S
index eb2cf7dc5c44..d0fbd7f1cb00 100644
--- a/arch/arm/mach-versatile/include/mach/debug-macro.S
+++ b/arch/arm/mach-versatile/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
*
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x001F0000
orr \rp, \rp, #0x00001000
orr \rv, \rp, #0xf1000000 @ virtual base
diff --git a/arch/arm/mach-versatile/include/mach/gpio.h b/arch/arm/mach-versatile/include/mach/gpio.h
index 94ff27678a46..40a8c178f10d 100644
--- a/arch/arm/mach-versatile/include/mach/gpio.h
+++ b/arch/arm/mach-versatile/include/mach/gpio.h
@@ -1,6 +1 @@
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
+/* empty */
diff --git a/arch/arm/mach-versatile/include/mach/memory.h b/arch/arm/mach-versatile/include/mach/memory.h
deleted file mode 100644
index dacc9d8e4e6a..000000000000
--- a/arch/arm/mach-versatile/include/mach/memory.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-versatile/include/mach/memory.h
- *
- * Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c
index f8ae64b3eed0..fda4866703cd 100644
--- a/arch/arm/mach-versatile/versatile_ab.c
+++ b/arch/arm/mach-versatile/versatile_ab.c
@@ -35,7 +35,7 @@
MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = versatile_map_io,
.init_early = versatile_init_early,
.init_irq = versatile_init_irq,
diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c
index 37c23dfeefb7..feaf9cbe60f6 100644
--- a/arch/arm/mach-versatile/versatile_pb.c
+++ b/arch/arm/mach-versatile/versatile_pb.c
@@ -103,7 +103,7 @@ static void __init versatile_pb_init(void)
MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = versatile_map_io,
.init_early = versatile_init_early,
.init_irq = versatile_init_irq,
diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot
index 07c2d9c457ec..8630b3d10a4d 100644
--- a/arch/arm/mach-vexpress/Makefile.boot
+++ b/arch/arm/mach-vexpress/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x60008000
+ zreladdr-y += 0x60008000
params_phys-y := 0x60000100
initrd_phys-y := 0x60800000
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index bfd32f52c2db..2b1e836a76ed 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -221,6 +221,12 @@ static void ct_ca9x4_init_cpu_map(void)
{
int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
+ if (ncores > nr_cpu_ids) {
+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+ ncores, nr_cpu_ids);
+ ncores = nr_cpu_ids;
+ }
+
for (i = 0; i < ncores; ++i)
set_cpu_possible(i, true);
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c
index ea4cbfb90a66..813ee08f96e6 100644
--- a/arch/arm/mach-vexpress/hotplug.c
+++ b/arch/arm/mach-vexpress/hotplug.c
@@ -13,6 +13,7 @@
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/system.h>
extern volatile int pen_release;
@@ -62,15 +63,9 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
* code will have already disabled interrupts
*/
for (;;) {
- /*
- * here's the WFI
- */
- asm(".word 0xe320f003\n"
- :
- :
- : "memory", "cc");
+ wfi();
- if (pen_release == cpu) {
+ if (pen_release == cpu_logical_map(cpu)) {
/*
* OK, proper wakeup, we're done
*/
diff --git a/arch/arm/mach-vexpress/include/mach/debug-macro.S b/arch/arm/mach-vexpress/include/mach/debug-macro.S
index 050d65e02a42..fd9e6c7ea49f 100644
--- a/arch/arm/mach-vexpress/include/mach/debug-macro.S
+++ b/arch/arm/mach-vexpress/include/mach/debug-macro.S
@@ -12,7 +12,7 @@
#define DEBUG_LL_UART_OFFSET 0x00009000
- .macro addruart,rp,rv
+ .macro addruart,rp,rv,tmp
mov \rp, #DEBUG_LL_UART_OFFSET
orr \rv, \rp, #0xf8000000 @ virtual base
orr \rp, \rp, #0x10000000 @ physical base
diff --git a/arch/arm/mach-vexpress/include/mach/gpio.h b/arch/arm/mach-vexpress/include/mach/gpio.h
new file mode 100644
index 000000000000..40a8c178f10d
--- /dev/null
+++ b/arch/arm/mach-vexpress/include/mach/gpio.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-vexpress/include/mach/io.h b/arch/arm/mach-vexpress/include/mach/io.h
index 748bb524ee71..13522d86685e 100644
--- a/arch/arm/mach-vexpress/include/mach/io.h
+++ b/arch/arm/mach-vexpress/include/mach/io.h
@@ -20,8 +20,6 @@
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
-#define IO_SPACE_LIMIT 0xffffffff
-
#define __io(a) __typesafe_io(a)
#define __mem_pci(a) (a)
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index d0d267a8d3f9..1fafc3244607 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -443,7 +443,7 @@ static void __init v2m_init(void)
}
MACHINE_START(VEXPRESS, "ARM-Versatile Express")
- .boot_params = PLAT_PHYS_OFFSET + 0x00000100,
+ .atag_offset = 0x100,
.map_io = v2m_map_io,
.init_early = v2m_init_early,
.init_irq = v2m_init_irq,
diff --git a/arch/arm/mach-vt8500/Makefile.boot b/arch/arm/mach-vt8500/Makefile.boot
index a8acc4e24902..b79c41cdfdff 100644
--- a/arch/arm/mach-vt8500/Makefile.boot
+++ b/arch/arm/mach-vt8500/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x01000000
diff --git a/arch/arm/mach-vt8500/bv07.c b/arch/arm/mach-vt8500/bv07.c
index 94a261d86bf0..a464c7584411 100644
--- a/arch/arm/mach-vt8500/bv07.c
+++ b/arch/arm/mach-vt8500/bv07.c
@@ -68,7 +68,7 @@ void __init bv07_init(void)
}
MACHINE_START(BV07, "Benign BV07 Mini Netbook")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.reserve = vt8500_reserve_mem,
.map_io = vt8500_map_io,
.init_irq = vt8500_init_irq,
diff --git a/arch/arm/mach-vt8500/include/mach/debug-macro.S b/arch/arm/mach-vt8500/include/mach/debug-macro.S
index f1191626ad51..ca292f29d4a3 100644
--- a/arch/arm/mach-vt8500/include/mach/debug-macro.S
+++ b/arch/arm/mach-vt8500/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
*
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #0x00200000
orr \rv, \rp, #0xf8000000
orr \rp, \rp, #0xd8000000
diff --git a/arch/arm/mach-vt8500/include/mach/gpio.h b/arch/arm/mach-vt8500/include/mach/gpio.h
index 94ff27678a46..40a8c178f10d 100644
--- a/arch/arm/mach-vt8500/include/mach/gpio.h
+++ b/arch/arm/mach-vt8500/include/mach/gpio.h
@@ -1,6 +1 @@
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
+/* empty */
diff --git a/arch/arm/mach-vt8500/include/mach/io.h b/arch/arm/mach-vt8500/include/mach/io.h
index 9077239f78c9..46181eecf273 100644
--- a/arch/arm/mach-vt8500/include/mach/io.h
+++ b/arch/arm/mach-vt8500/include/mach/io.h
@@ -20,8 +20,6 @@
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
-#define IO_SPACE_LIMIT 0xffff
-
#define __io(a) __typesafe_io((a) + 0xf0000000)
#define __mem_pci(a) (a)
diff --git a/arch/arm/mach-vt8500/wm8505_7in.c b/arch/arm/mach-vt8500/wm8505_7in.c
index e73aadbcafd6..cf910a956080 100644
--- a/arch/arm/mach-vt8500/wm8505_7in.c
+++ b/arch/arm/mach-vt8500/wm8505_7in.c
@@ -68,7 +68,7 @@ void __init wm8505_7in_init(void)
}
MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.reserve = wm8505_reserve_mem,
.map_io = wm8505_map_io,
.init_irq = wm8505_init_irq,
diff --git a/arch/arm/mach-w90x900/Makefile.boot b/arch/arm/mach-w90x900/Makefile.boot
index a057b546b6e5..6c3d421c2d11 100644
--- a/arch/arm/mach-w90x900/Makefile.boot
+++ b/arch/arm/mach-w90x900/Makefile.boot
@@ -1,3 +1,3 @@
-zreladdr-y := 0x00008000
+zreladdr-y += 0x00008000
params_phys-y := 0x00000100
diff --git a/arch/arm/mach-w90x900/cpu.c b/arch/arm/mach-w90x900/cpu.c
index 83c56324a472..0a235e502330 100644
--- a/arch/arm/mach-w90x900/cpu.c
+++ b/arch/arm/mach-w90x900/cpu.c
@@ -60,7 +60,7 @@ static DEFINE_CLK(emc, 7);
static DEFINE_SUBCLK(rmii, 2);
static DEFINE_CLK(usbd, 8);
static DEFINE_CLK(usbh, 9);
-static DEFINE_CLK(g2d, 10);;
+static DEFINE_CLK(g2d, 10);
static DEFINE_CLK(pwm, 18);
static DEFINE_CLK(ps2, 24);
static DEFINE_CLK(kpi, 25);
diff --git a/arch/arm/mach-w90x900/include/mach/gpio.h b/arch/arm/mach-w90x900/include/mach/gpio.h
index 034da3e390c9..5385a4203277 100644
--- a/arch/arm/mach-w90x900/include/mach/gpio.h
+++ b/arch/arm/mach-w90x900/include/mach/gpio.h
@@ -15,16 +15,12 @@
#include <mach/hardware.h>
#include <asm/irq.h>
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
static inline int gpio_to_irq(unsigned gpio)
{
return gpio;
}
+#define gpio_to_irq gpio_to_irq
static inline int irq_to_gpio(unsigned irq)
{
diff --git a/arch/arm/mach-w90x900/include/mach/memory.h b/arch/arm/mach-w90x900/include/mach/memory.h
deleted file mode 100644
index f02905ba7746..000000000000
--- a/arch/arm/mach-w90x900/include/mach/memory.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * arch/arm/mach-w90x900/include/mach/memory.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/memory.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-w90x900/mach-nuc910evb.c b/arch/arm/mach-w90x900/mach-nuc910evb.c
index 30fccde94fb8..31c109018228 100644
--- a/arch/arm/mach-w90x900/mach-nuc910evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc910evb.c
@@ -34,7 +34,6 @@ static void __init nuc910evb_init(void)
MACHINE_START(W90P910EVB, "W90P910EVB")
/* Maintainer: Wan ZongShun */
- .boot_params = 0,
.map_io = nuc910evb_map_io,
.init_irq = nuc900_init_irq,
.init_machine = nuc910evb_init,
diff --git a/arch/arm/mach-w90x900/mach-nuc950evb.c b/arch/arm/mach-w90x900/mach-nuc950evb.c
index 590c99b96dc1..4062e55a57d8 100644
--- a/arch/arm/mach-w90x900/mach-nuc950evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc950evb.c
@@ -37,7 +37,6 @@ static void __init nuc950evb_init(void)
MACHINE_START(W90P950EVB, "W90P950EVB")
/* Maintainer: Wan ZongShun */
- .boot_params = 0,
.map_io = nuc950evb_map_io,
.init_irq = nuc900_init_irq,
.init_machine = nuc950evb_init,
diff --git a/arch/arm/mach-w90x900/mach-nuc960evb.c b/arch/arm/mach-w90x900/mach-nuc960evb.c
index e09c645d61b6..0ab9995d5b58 100644
--- a/arch/arm/mach-w90x900/mach-nuc960evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc960evb.c
@@ -34,7 +34,6 @@ static void __init nuc960evb_init(void)
MACHINE_START(W90N960EVB, "W90N960EVB")
/* Maintainer: Wan ZongShun */
- .boot_params = 0,
.map_io = nuc960evb_map_io,
.init_irq = nuc900_init_irq,
.init_machine = nuc960evb_init,
diff --git a/arch/arm/mach-zynq/Makefile.boot b/arch/arm/mach-zynq/Makefile.boot
index 67039c3e0c48..760a0efe7580 100644
--- a/arch/arm/mach-zynq/Makefile.boot
+++ b/arch/arm/mach-zynq/Makefile.boot
@@ -1,3 +1,3 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/mach-zynq/include/mach/debug-macro.S
index 9f664d5eb81d..3ab0be1f6191 100644
--- a/arch/arm/mach-zynq/include/mach/debug-macro.S
+++ b/arch/arm/mach-zynq/include/mach/debug-macro.S
@@ -17,7 +17,7 @@
#include <mach/zynq_soc.h>
#include <mach/uart.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =LL_UART_PADDR @ physical
ldr \rv, =LL_UART_VADDR @ virtual
.endm
diff --git a/arch/arm/mach-zynq/include/mach/memory.h b/arch/arm/mach-zynq/include/mach/memory.h
deleted file mode 100644
index 35a92634dcc1..000000000000
--- a/arch/arm/mach-zynq/include/mach/memory.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/memory.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_MEMORY_H__
-#define __MACH_MEMORY_H__
-
-#include <asm/sizes.h>
-
-#define PLAT_PHYS_OFFSET UL(0x0)
-
-#endif
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 88633fe01a5d..67f75a0b66d6 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -819,10 +819,10 @@ config CACHE_FEROCEON_L2_WRITETHROUGH
config CACHE_L2X0
bool "Enable the L2x0 outer cache controller"
depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
- REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
+ REALVIEW_EB_A9MP || ARCH_IMX_V6_V7 || MACH_REALVIEW_PBX || \
ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \
- ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX
+ ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX || ARCH_HIGHBANK
default y
select OUTER_CACHE
select OUTER_CACHE_SYNC
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index cfbcf8b95599..c335c76e0d88 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -86,16 +86,6 @@ core_param(alignment, ai_usermode, int, 0600);
#define UM_FIXUP (1 << 1)
#define UM_SIGNAL (1 << 2)
-#ifdef CONFIG_PROC_FS
-static const char *usermode_action[] = {
- "ignored",
- "warn",
- "fixup",
- "fixup+warn",
- "signal",
- "signal+warn"
-};
-
/* Return true if and only if the ARMv6 unaligned access model is in use. */
static bool cpu_is_v6_unaligned(void)
{
@@ -123,6 +113,16 @@ static int safe_usermode(int new_usermode, bool warn)
return new_usermode;
}
+#ifdef CONFIG_PROC_FS
+static const char *usermode_action[] = {
+ "ignored",
+ "warn",
+ "fixup",
+ "fixup+warn",
+ "signal",
+ "signal+warn"
+};
+
static int alignment_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "User:\t\t%lu\n", ai_user);
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 9ecfdb511951..8ac9e9f84790 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -16,9 +16,12 @@
* 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/init.h>
#include <linux/spinlock.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
@@ -26,15 +29,23 @@
#define CACHE_LINE_SIZE 32
static void __iomem *l2x0_base;
-static DEFINE_SPINLOCK(l2x0_lock);
+static DEFINE_RAW_SPINLOCK(l2x0_lock);
static uint32_t l2x0_way_mask; /* Bitmask of active ways */
static uint32_t l2x0_size;
+struct l2x0_regs l2x0_saved_regs;
+
+struct l2x0_of_data {
+ void (*setup)(const struct device_node *, __u32 *, __u32 *);
+ void (*save)(void);
+ void (*resume)(void);
+};
+
static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
{
/* wait for cache operation by line or way to complete */
while (readl_relaxed(reg) & mask)
- ;
+ cpu_relax();
}
#ifdef CONFIG_CACHE_PL310
@@ -115,9 +126,9 @@ static void l2x0_cache_sync(void)
{
unsigned long flags;
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
cache_sync();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void __l2x0_flush_all(void)
@@ -134,9 +145,9 @@ static void l2x0_flush_all(void)
unsigned long flags;
/* clean all ways */
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
__l2x0_flush_all();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_clean_all(void)
@@ -144,11 +155,11 @@ static void l2x0_clean_all(void)
unsigned long flags;
/* clean all ways */
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY);
cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask);
cache_sync();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_inv_all(void)
@@ -156,13 +167,13 @@ static void l2x0_inv_all(void)
unsigned long flags;
/* invalidate all ways */
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
/* Invalidating when L2 is enabled is a nono */
BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1);
writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
cache_sync();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_inv_range(unsigned long start, unsigned long end)
@@ -170,7 +181,7 @@ static void l2x0_inv_range(unsigned long start, unsigned long end)
void __iomem *base = l2x0_base;
unsigned long flags;
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
if (start & (CACHE_LINE_SIZE - 1)) {
start &= ~(CACHE_LINE_SIZE - 1);
debug_writel(0x03);
@@ -195,13 +206,13 @@ static void l2x0_inv_range(unsigned long start, unsigned long end)
}
if (blk_end < end) {
- spin_unlock_irqrestore(&l2x0_lock, flags);
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
}
}
cache_wait(base + L2X0_INV_LINE_PA, 1);
cache_sync();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_clean_range(unsigned long start, unsigned long end)
@@ -214,7 +225,7 @@ static void l2x0_clean_range(unsigned long start, unsigned long end)
return;
}
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
start &= ~(CACHE_LINE_SIZE - 1);
while (start < end) {
unsigned long blk_end = start + min(end - start, 4096UL);
@@ -225,13 +236,13 @@ static void l2x0_clean_range(unsigned long start, unsigned long end)
}
if (blk_end < end) {
- spin_unlock_irqrestore(&l2x0_lock, flags);
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
}
}
cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
cache_sync();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_flush_range(unsigned long start, unsigned long end)
@@ -244,7 +255,7 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)
return;
}
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
start &= ~(CACHE_LINE_SIZE - 1);
while (start < end) {
unsigned long blk_end = start + min(end - start, 4096UL);
@@ -257,27 +268,27 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)
debug_writel(0x00);
if (blk_end < end) {
- spin_unlock_irqrestore(&l2x0_lock, flags);
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
}
}
cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
cache_sync();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_disable(void)
{
unsigned long flags;
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
__l2x0_flush_all();
writel_relaxed(0, l2x0_base + L2X0_CTRL);
dsb();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
-static void __init l2x0_unlock(__u32 cache_id)
+static void l2x0_unlock(__u32 cache_id)
{
int lockregs;
int i;
@@ -353,6 +364,8 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
/* l2x0 controller is disabled */
writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
+ l2x0_saved_regs.aux_ctrl = aux;
+
l2x0_inv_all();
/* enable L2X0 */
@@ -372,3 +385,202 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
ways, cache_id, aux, l2x0_size);
}
+
+#ifdef CONFIG_OF
+static void __init l2x0_of_setup(const struct device_node *np,
+ __u32 *aux_val, __u32 *aux_mask)
+{
+ u32 data[2] = { 0, 0 };
+ u32 tag = 0;
+ u32 dirty = 0;
+ u32 val = 0, mask = 0;
+
+ of_property_read_u32(np, "arm,tag-latency", &tag);
+ if (tag) {
+ mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK;
+ val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT;
+ }
+
+ of_property_read_u32_array(np, "arm,data-latency",
+ data, ARRAY_SIZE(data));
+ if (data[0] && data[1]) {
+ mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK |
+ L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK;
+ val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) |
+ ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT);
+ }
+
+ of_property_read_u32(np, "arm,dirty-latency", &dirty);
+ if (dirty) {
+ mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK;
+ val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
+ }
+
+ *aux_val &= ~mask;
+ *aux_val |= val;
+ *aux_mask &= ~mask;
+}
+
+static void __init pl310_of_setup(const struct device_node *np,
+ __u32 *aux_val, __u32 *aux_mask)
+{
+ u32 data[3] = { 0, 0, 0 };
+ u32 tag[3] = { 0, 0, 0 };
+ u32 filter[2] = { 0, 0 };
+
+ of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
+ if (tag[0] && tag[1] && tag[2])
+ writel_relaxed(
+ ((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
+ ((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
+ ((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
+ l2x0_base + L2X0_TAG_LATENCY_CTRL);
+
+ of_property_read_u32_array(np, "arm,data-latency",
+ data, ARRAY_SIZE(data));
+ if (data[0] && data[1] && data[2])
+ writel_relaxed(
+ ((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
+ ((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
+ ((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
+ l2x0_base + L2X0_DATA_LATENCY_CTRL);
+
+ of_property_read_u32_array(np, "arm,filter-ranges",
+ filter, ARRAY_SIZE(filter));
+ if (filter[1]) {
+ writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
+ l2x0_base + L2X0_ADDR_FILTER_END);
+ writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN,
+ l2x0_base + L2X0_ADDR_FILTER_START);
+ }
+}
+
+static void __init pl310_save(void)
+{
+ u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+ L2X0_CACHE_ID_RTL_MASK;
+
+ l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
+ L2X0_TAG_LATENCY_CTRL);
+ l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base +
+ L2X0_DATA_LATENCY_CTRL);
+ l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base +
+ L2X0_ADDR_FILTER_END);
+ l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base +
+ L2X0_ADDR_FILTER_START);
+
+ if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
+ /*
+ * From r2p0, there is Prefetch offset/control register
+ */
+ l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base +
+ L2X0_PREFETCH_CTRL);
+ /*
+ * From r3p0, there is Power control register
+ */
+ if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
+ l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base +
+ L2X0_POWER_CTRL);
+ }
+}
+
+static void l2x0_resume(void)
+{
+ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+ /* restore aux ctrl and enable l2 */
+ l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
+
+ writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base +
+ L2X0_AUX_CTRL);
+
+ l2x0_inv_all();
+
+ writel_relaxed(1, l2x0_base + L2X0_CTRL);
+ }
+}
+
+static void pl310_resume(void)
+{
+ u32 l2x0_revision;
+
+ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+ /* restore pl310 setup */
+ writel_relaxed(l2x0_saved_regs.tag_latency,
+ l2x0_base + L2X0_TAG_LATENCY_CTRL);
+ writel_relaxed(l2x0_saved_regs.data_latency,
+ l2x0_base + L2X0_DATA_LATENCY_CTRL);
+ writel_relaxed(l2x0_saved_regs.filter_end,
+ l2x0_base + L2X0_ADDR_FILTER_END);
+ writel_relaxed(l2x0_saved_regs.filter_start,
+ l2x0_base + L2X0_ADDR_FILTER_START);
+
+ l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+ L2X0_CACHE_ID_RTL_MASK;
+
+ if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
+ writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
+ l2x0_base + L2X0_PREFETCH_CTRL);
+ if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
+ writel_relaxed(l2x0_saved_regs.pwr_ctrl,
+ l2x0_base + L2X0_POWER_CTRL);
+ }
+ }
+
+ l2x0_resume();
+}
+
+static const struct l2x0_of_data pl310_data = {
+ pl310_of_setup,
+ pl310_save,
+ pl310_resume,
+};
+
+static const struct l2x0_of_data l2x0_data = {
+ l2x0_of_setup,
+ NULL,
+ l2x0_resume,
+};
+
+static const struct of_device_id l2x0_ids[] __initconst = {
+ { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
+ { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
+ { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
+ {}
+};
+
+int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+{
+ struct device_node *np;
+ struct l2x0_of_data *data;
+ struct resource res;
+
+ np = of_find_matching_node(NULL, l2x0_ids);
+ if (!np)
+ return -ENODEV;
+
+ if (of_address_to_resource(np, 0, &res))
+ return -ENODEV;
+
+ l2x0_base = ioremap(res.start, resource_size(&res));
+ if (!l2x0_base)
+ return -ENOMEM;
+
+ l2x0_saved_regs.phy_base = res.start;
+
+ data = of_match_node(l2x0_ids, np)->data;
+
+ /* L2 configuration can only be changed if the cache is disabled */
+ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+ if (data->setup)
+ data->setup(np, &aux_val, &aux_mask);
+ }
+
+ if (data->save)
+ data->save();
+
+ l2x0_init(l2x0_base, aux_val, aux_mask);
+
+ outer_cache.resume = data->resume;
+ return 0;
+}
+#endif
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index b0ee9ba3cfab..93aac068da94 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -16,7 +16,7 @@
#include <asm/mmu_context.h>
#include <asm/tlbflush.h>
-static DEFINE_SPINLOCK(cpu_asid_lock);
+static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
unsigned int cpu_last_asid = ASID_FIRST_VERSION;
#ifdef CONFIG_SMP
DEFINE_PER_CPU(struct mm_struct *, current_mm);
@@ -31,7 +31,7 @@ DEFINE_PER_CPU(struct mm_struct *, current_mm);
void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{
mm->context.id = 0;
- spin_lock_init(&mm->context.id_lock);
+ raw_spin_lock_init(&mm->context.id_lock);
}
static void flush_context(void)
@@ -58,7 +58,7 @@ static void set_mm_context(struct mm_struct *mm, unsigned int asid)
* the broadcast. This function is also called via IPI so the
* mm->context.id_lock has to be IRQ-safe.
*/
- spin_lock_irqsave(&mm->context.id_lock, flags);
+ raw_spin_lock_irqsave(&mm->context.id_lock, flags);
if (likely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) {
/*
* Old version of ASID found. Set the new one and
@@ -67,7 +67,7 @@ static void set_mm_context(struct mm_struct *mm, unsigned int asid)
mm->context.id = asid;
cpumask_clear(mm_cpumask(mm));
}
- spin_unlock_irqrestore(&mm->context.id_lock, flags);
+ raw_spin_unlock_irqrestore(&mm->context.id_lock, flags);
/*
* Set the mm_cpumask(mm) bit for the current CPU.
@@ -117,7 +117,7 @@ void __new_context(struct mm_struct *mm)
{
unsigned int asid;
- spin_lock(&cpu_asid_lock);
+ raw_spin_lock(&cpu_asid_lock);
#ifdef CONFIG_SMP
/*
* Check the ASID again, in case the change was broadcast from
@@ -125,7 +125,7 @@ void __new_context(struct mm_struct *mm)
*/
if (unlikely(((mm->context.id ^ cpu_last_asid) >> ASID_BITS) == 0)) {
cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
- spin_unlock(&cpu_asid_lock);
+ raw_spin_unlock(&cpu_asid_lock);
return;
}
#endif
@@ -153,5 +153,5 @@ void __new_context(struct mm_struct *mm)
}
set_mm_context(mm, asid);
- spin_unlock(&cpu_asid_lock);
+ raw_spin_unlock(&cpu_asid_lock);
}
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
index b8061519ce77..7d0a8c230342 100644
--- a/arch/arm/mm/copypage-v4mc.c
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -30,7 +30,7 @@
#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
L_PTE_MT_MINICACHE)
-static DEFINE_SPINLOCK(minicache_lock);
+static DEFINE_RAW_SPINLOCK(minicache_lock);
/*
* ARMv4 mini-dcache optimised copy_user_highpage
@@ -76,14 +76,14 @@ void v4_mc_copy_user_highpage(struct page *to, struct page *from,
if (!test_and_set_bit(PG_dcache_clean, &from->flags))
__flush_dcache_page(page_mapping(from), from);
- spin_lock(&minicache_lock);
+ raw_spin_lock(&minicache_lock);
set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
flush_tlb_kernel_page(0xffff8000);
mc_copy_user_page((void *)0xffff8000, kto);
- spin_unlock(&minicache_lock);
+ raw_spin_unlock(&minicache_lock);
kunmap_atomic(kto, KM_USER1);
}
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index 63cca0097130..3d9a1552cef6 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -27,7 +27,7 @@
#define from_address (0xffff8000)
#define to_address (0xffffc000)
-static DEFINE_SPINLOCK(v6_lock);
+static DEFINE_RAW_SPINLOCK(v6_lock);
/*
* Copy the user page. No aliasing to deal with so we can just
@@ -88,7 +88,7 @@ static void v6_copy_user_highpage_aliasing(struct page *to,
* Now copy the page using the same cache colour as the
* pages ultimate destination.
*/
- spin_lock(&v6_lock);
+ raw_spin_lock(&v6_lock);
set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(page_to_pfn(from), PAGE_KERNEL), 0);
set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(to), PAGE_KERNEL), 0);
@@ -101,7 +101,7 @@ static void v6_copy_user_highpage_aliasing(struct page *to,
copy_page((void *)kto, (void *)kfrom);
- spin_unlock(&v6_lock);
+ raw_spin_unlock(&v6_lock);
}
/*
@@ -121,13 +121,13 @@ static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vad
* Now clear the page using the same cache colour as
* the pages ultimate destination.
*/
- spin_lock(&v6_lock);
+ raw_spin_lock(&v6_lock);
set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(page), PAGE_KERNEL), 0);
flush_tlb_kernel_page(to);
clear_page((void *)to);
- spin_unlock(&v6_lock);
+ raw_spin_unlock(&v6_lock);
}
struct cpu_user_fns v6_user_fns __initdata = {
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index 649bbcd325bf..610c24ced310 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -32,7 +32,7 @@
#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
L_PTE_MT_MINICACHE)
-static DEFINE_SPINLOCK(minicache_lock);
+static DEFINE_RAW_SPINLOCK(minicache_lock);
/*
* XScale mini-dcache optimised copy_user_highpage
@@ -98,14 +98,14 @@ void xscale_mc_copy_user_highpage(struct page *to, struct page *from,
if (!test_and_set_bit(PG_dcache_clean, &from->flags))
__flush_dcache_page(page_mapping(from), from);
- spin_lock(&minicache_lock);
+ raw_spin_lock(&minicache_lock);
set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
flush_tlb_kernel_page(COPYPAGE_MINICACHE);
mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
- spin_unlock(&minicache_lock);
+ raw_spin_unlock(&minicache_lock);
kunmap_atomic(kto, KM_USER1);
}
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index c3ff82f92d9c..e4e7f6cba1ab 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -18,12 +18,14 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/highmem.h>
+#include <linux/slab.h>
#include <asm/memory.h>
#include <asm/highmem.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/sizes.h>
+#include <asm/mach/arch.h>
#include "mm.h"
@@ -117,26 +119,36 @@ static void __dma_free_buffer(struct page *page, size_t size)
}
#ifdef CONFIG_MMU
-/* Sanity check size */
-#if (CONSISTENT_DMA_SIZE % SZ_2M)
-#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"
-#endif
-#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
-#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
-#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
+#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - consistent_base) >> PAGE_SHIFT)
+#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PMD_SHIFT)
/*
* These are the page tables (2MB each) covering uncached, DMA consistent allocations
*/
-static pte_t *consistent_pte[NUM_CONSISTENT_PTES];
+static pte_t **consistent_pte;
+
+#define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M
+
+unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
+
+void __init init_consistent_dma_size(unsigned long size)
+{
+ unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M);
+
+ BUG_ON(consistent_pte); /* Check we're called before DMA region init */
+ BUG_ON(base < VMALLOC_END);
+
+ /* Grow region to accommodate specified size */
+ if (base < consistent_base)
+ consistent_base = base;
+}
#include "vmregion.h"
static struct arm_vmregion_head consistent_head = {
.vm_lock = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock),
.vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
- .vm_start = CONSISTENT_BASE,
.vm_end = CONSISTENT_END,
};
@@ -155,7 +167,17 @@ static int __init consistent_init(void)
pmd_t *pmd;
pte_t *pte;
int i = 0;
- u32 base = CONSISTENT_BASE;
+ unsigned long base = consistent_base;
+ unsigned long num_ptes = (CONSISTENT_END - base) >> PGDIR_SHIFT;
+
+ consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
+ if (!consistent_pte) {
+ pr_err("%s: no memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END);
+ consistent_head.vm_start = base;
do {
pgd = pgd_offset(&init_mm, base);
@@ -183,7 +205,7 @@ static int __init consistent_init(void)
}
consistent_pte[i++] = pte;
- base += (1 << PGDIR_SHIFT);
+ base += PMD_SIZE;
} while (base < CONSISTENT_END);
return ret;
@@ -198,7 +220,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)
size_t align;
int bit;
- if (!consistent_pte[0]) {
+ if (!consistent_pte) {
printk(KERN_ERR "%s: not initialised\n", __func__);
dump_stack();
return NULL;
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 3b5ea68acbb8..aa33949fef60 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -20,6 +20,7 @@
#include <linux/highmem.h>
#include <linux/perf_event.h>
+#include <asm/exception.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index f8037ba338ac..04e9a92bb47a 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -660,9 +660,6 @@ void __init mem_init(void)
" ITCM : 0x%08lx - 0x%08lx (%4ld kB)\n"
#endif
" fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
-#ifdef CONFIG_MMU
- " DMA : 0x%08lx - 0x%08lx (%4ld MB)\n"
-#endif
" vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"
" lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"
#ifdef CONFIG_HIGHMEM
@@ -681,9 +678,6 @@ void __init mem_init(void)
MLK(ITCM_OFFSET, (unsigned long) itcm_end),
#endif
MLK(FIXADDR_START, FIXADDR_TOP),
-#ifdef CONFIG_MMU
- MLM(CONSISTENT_BASE, CONSISTENT_END),
-#endif
MLM(VMALLOC_START, VMALLOC_END),
MLM(PAGE_OFFSET, (unsigned long)high_memory),
#ifdef CONFIG_HIGHMEM
@@ -706,9 +700,6 @@ void __init mem_init(void)
* be detected at build time already.
*/
#ifdef CONFIG_MMU
- BUILD_BUG_ON(VMALLOC_END > CONSISTENT_BASE);
- BUG_ON(VMALLOC_END > CONSISTENT_BASE);
-
BUILD_BUG_ON(TASK_SIZE > MODULES_VADDR);
BUG_ON(TASK_SIZE > MODULES_VADDR);
#endif
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index ab506272b2d3..bdb248c4f55c 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -289,6 +289,27 @@ __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
}
EXPORT_SYMBOL(__arm_ioremap);
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space as memory. Needed when the kernel wants to execute
+ * code in external memory. This is needed for reprogramming source
+ * clocks that would affect normal memory for example. Please see
+ * CONFIG_GENERIC_ALLOCATOR for allocating external memory.
+ */
+void __iomem *
+__arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached)
+{
+ unsigned int mtype;
+
+ if (cached)
+ mtype = MT_MEMORY;
+ else
+ mtype = MT_MEMORY_NONCACHED;
+
+ return __arm_ioremap_caller(phys_addr, size, mtype,
+ __builtin_return_address(0));
+}
+
void __iounmap(volatile void __iomem *io_addr)
{
void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index 010566799c80..ad7cce3bc431 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -12,8 +12,8 @@ static inline pmd_t *pmd_off_k(unsigned long virt)
struct mem_type {
pteval_t prot_pte;
- unsigned int prot_l1;
- unsigned int prot_sect;
+ pmdval_t prot_l1;
+ pmdval_t prot_sect;
unsigned int domain;
};
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 594d677b92c8..dc8c550e6cbd 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -60,7 +60,7 @@ EXPORT_SYMBOL(pgprot_kernel);
struct cachepolicy {
const char policy[16];
unsigned int cr_mask;
- unsigned int pmd;
+ pmdval_t pmd;
pteval_t pte;
};
@@ -273,6 +273,14 @@ static struct mem_type mem_types[] = {
.prot_l1 = PMD_TYPE_TABLE,
.domain = DOMAIN_KERNEL,
},
+ [MT_MEMORY_SO] = {
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_MT_UNCACHED,
+ .prot_l1 = PMD_TYPE_TABLE,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S |
+ PMD_SECT_UNCACHED | PMD_SECT_XN,
+ .domain = DOMAIN_KERNEL,
+ },
};
const struct mem_type *get_mem_type(unsigned int type)
@@ -288,7 +296,7 @@ static void __init build_mem_type_table(void)
{
struct cachepolicy *cp;
unsigned int cr = get_cr();
- unsigned int user_pgprot, kern_pgprot, vecs_pgprot;
+ pteval_t user_pgprot, kern_pgprot, vecs_pgprot;
int cpu_arch = cpu_architecture();
int i;
@@ -863,14 +871,14 @@ static inline void prepare_page_table(void)
/*
* Clear out all the mappings below the kernel image.
*/
- for (addr = 0; addr < MODULES_VADDR; addr += PGDIR_SIZE)
+ for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));
#ifdef CONFIG_XIP_KERNEL
/* The XIP kernel is mapped in the module area -- skip over it */
- addr = ((unsigned long)_etext + PGDIR_SIZE - 1) & PGDIR_MASK;
+ addr = ((unsigned long)_etext + PMD_SIZE - 1) & PMD_MASK;
#endif
- for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
+ for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));
/*
@@ -885,10 +893,12 @@ static inline void prepare_page_table(void)
* memory bank, up to the end of the vmalloc region.
*/
for (addr = __phys_to_virt(end);
- addr < VMALLOC_END; addr += PGDIR_SIZE)
+ addr < VMALLOC_END; addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));
}
+#define SWAPPER_PG_DIR_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
+
/*
* Reserve the special regions of memory
*/
@@ -898,7 +908,7 @@ void __init arm_mm_memblock_reserve(void)
* Reserve the page tables. These are already in use,
* and can only be in node 0.
*/
- memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
+ memblock_reserve(__pa(swapper_pg_dir), SWAPPER_PG_DIR_SIZE);
#ifdef CONFIG_SA1111
/*
@@ -926,7 +936,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
*/
vectors_page = early_alloc(PAGE_SIZE);
- for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
+ for (addr = VMALLOC_END; addr; addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));
/*
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 2e6849b41f66..88fb3d9e0640 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -379,31 +379,26 @@ ENTRY(cpu_arm920_set_pte_ext)
/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
.globl cpu_arm920_suspend_size
-.equ cpu_arm920_suspend_size, 4 * 4
+.equ cpu_arm920_suspend_size, 4 * 3
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_arm920_do_suspend)
- stmfd sp!, {r4 - r7, lr}
+ stmfd sp!, {r4 - r6, lr}
mrc p15, 0, r4, c13, c0, 0 @ PID
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
- mrc p15, 0, r6, c2, c0, 0 @ TTB address
- mrc p15, 0, r7, c1, c0, 0 @ Control register
- stmia r0, {r4 - r7}
- ldmfd sp!, {r4 - r7, pc}
+ mrc p15, 0, r6, c1, c0, 0 @ Control register
+ stmia r0, {r4 - r6}
+ ldmfd sp!, {r4 - r6, pc}
ENDPROC(cpu_arm920_do_suspend)
ENTRY(cpu_arm920_do_resume)
mov ip, #0
mcr p15, 0, ip, c8, c7, 0 @ invalidate I+D TLBs
mcr p15, 0, ip, c7, c7, 0 @ invalidate I+D caches
- ldmia r0, {r4 - r7}
+ ldmia r0, {r4 - r6}
mcr p15, 0, r4, c13, c0, 0 @ PID
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
- mcr p15, 0, r6, c2, c0, 0 @ TTB address
- mov r0, r7 @ control register
- mov r2, r6, lsr #14 @ get TTB0 base
- mov r2, r2, lsl #14
- ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+ mcr p15, 0, r1, c2, c0, 0 @ TTB address
+ mov r0, r6 @ control register
b cpu_resume_mmu
ENDPROC(cpu_arm920_do_resume)
#endif
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index cd8f79c3a282..9f8fd91f918a 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -394,31 +394,26 @@ ENTRY(cpu_arm926_set_pte_ext)
/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
.globl cpu_arm926_suspend_size
-.equ cpu_arm926_suspend_size, 4 * 4
+.equ cpu_arm926_suspend_size, 4 * 3
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_arm926_do_suspend)
- stmfd sp!, {r4 - r7, lr}
+ stmfd sp!, {r4 - r6, lr}
mrc p15, 0, r4, c13, c0, 0 @ PID
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
- mrc p15, 0, r6, c2, c0, 0 @ TTB address
- mrc p15, 0, r7, c1, c0, 0 @ Control register
- stmia r0, {r4 - r7}
- ldmfd sp!, {r4 - r7, pc}
+ mrc p15, 0, r6, c1, c0, 0 @ Control register
+ stmia r0, {r4 - r6}
+ ldmfd sp!, {r4 - r6, pc}
ENDPROC(cpu_arm926_do_suspend)
ENTRY(cpu_arm926_do_resume)
mov ip, #0
mcr p15, 0, ip, c8, c7, 0 @ invalidate I+D TLBs
mcr p15, 0, ip, c7, c7, 0 @ invalidate I+D caches
- ldmia r0, {r4 - r7}
+ ldmia r0, {r4 - r6}
mcr p15, 0, r4, c13, c0, 0 @ PID
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
- mcr p15, 0, r6, c2, c0, 0 @ TTB address
- mov r0, r7 @ control register
- mov r2, r6, lsr #14 @ get TTB0 base
- mov r2, r2, lsl #14
- ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+ mcr p15, 0, r1, c2, c0, 0 @ TTB address
+ mov r0, r6 @ control register
b cpu_resume_mmu
ENDPROC(cpu_arm926_do_resume)
#endif
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 69e7f2ef7384..7d91545d089b 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -168,20 +168,19 @@ ENTRY(cpu_sa1100_set_pte_ext)
mov pc, lr
.globl cpu_sa1100_suspend_size
-.equ cpu_sa1100_suspend_size, 4*4
+.equ cpu_sa1100_suspend_size, 4 * 3
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_sa1100_do_suspend)
- stmfd sp!, {r4 - r7, lr}
+ stmfd sp!, {r4 - r6, lr}
mrc p15, 0, r4, c3, c0, 0 @ domain ID
- mrc p15, 0, r5, c2, c0, 0 @ translation table base addr
- mrc p15, 0, r6, c13, c0, 0 @ PID
- mrc p15, 0, r7, c1, c0, 0 @ control reg
- stmia r0, {r4 - r7} @ store cp regs
- ldmfd sp!, {r4 - r7, pc}
+ mrc p15, 0, r5, c13, c0, 0 @ PID
+ mrc p15, 0, r6, c1, c0, 0 @ control reg
+ stmia r0, {r4 - r6} @ store cp regs
+ ldmfd sp!, {r4 - r6, pc}
ENDPROC(cpu_sa1100_do_suspend)
ENTRY(cpu_sa1100_do_resume)
- ldmia r0, {r4 - r7} @ load cp regs
+ ldmia r0, {r4 - r6} @ load cp regs
mov ip, #0
mcr p15, 0, ip, c8, c7, 0 @ flush I+D TLBs
mcr p15, 0, ip, c7, c7, 0 @ flush I&D cache
@@ -189,13 +188,9 @@ ENTRY(cpu_sa1100_do_resume)
mcr p15, 0, ip, c9, c0, 5 @ allow user space to use RB
mcr p15, 0, r4, c3, c0, 0 @ domain ID
- mcr p15, 0, r5, c2, c0, 0 @ translation table base addr
- mcr p15, 0, r6, c13, c0, 0 @ PID
- mov r0, r7 @ control register
- mov r2, r5, lsr #14 @ get TTB0 base
- mov r2, r2, lsl #14
- ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+ mcr p15, 0, r1, c2, c0, 0 @ translation table base addr
+ mcr p15, 0, r5, c13, c0, 0 @ PID
+ mov r0, r6 @ control register
b cpu_resume_mmu
ENDPROC(cpu_sa1100_do_resume)
#endif
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index a923aa0fd00d..d061d2fa5506 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -128,20 +128,18 @@ ENTRY(cpu_v6_set_pte_ext)
/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
.globl cpu_v6_suspend_size
-.equ cpu_v6_suspend_size, 4 * 8
+.equ cpu_v6_suspend_size, 4 * 6
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_v6_do_suspend)
- stmfd sp!, {r4 - r11, lr}
+ stmfd sp!, {r4 - r9, lr}
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
- mrc p15, 0, r5, c13, c0, 1 @ Context ID
- mrc p15, 0, r6, c3, c0, 0 @ Domain ID
- mrc p15, 0, r7, c2, c0, 0 @ Translation table base 0
- mrc p15, 0, r8, c2, c0, 1 @ Translation table base 1
- mrc p15, 0, r9, c1, c0, 1 @ auxiliary control register
- mrc p15, 0, r10, c1, c0, 2 @ co-processor access control
- mrc p15, 0, r11, c1, c0, 0 @ control register
- stmia r0, {r4 - r11}
- ldmfd sp!, {r4- r11, pc}
+ mrc p15, 0, r5, c3, c0, 0 @ Domain ID
+ mrc p15, 0, r6, c2, c0, 1 @ Translation table base 1
+ mrc p15, 0, r7, c1, c0, 1 @ auxiliary control register
+ mrc p15, 0, r8, c1, c0, 2 @ co-processor access control
+ mrc p15, 0, r9, c1, c0, 0 @ control register
+ stmia r0, {r4 - r9}
+ ldmfd sp!, {r4- r9, pc}
ENDPROC(cpu_v6_do_suspend)
ENTRY(cpu_v6_do_resume)
@@ -150,25 +148,21 @@ ENTRY(cpu_v6_do_resume)
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcr p15, 0, ip, c7, c15, 0 @ clean+invalidate cache
mcr p15, 0, ip, c7, c10, 4 @ drain write buffer
- ldmia r0, {r4 - r11}
+ mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID
+ ldmia r0, {r4 - r9}
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
- mcr p15, 0, r5, c13, c0, 1 @ Context ID
- mcr p15, 0, r6, c3, c0, 0 @ Domain ID
- mcr p15, 0, r7, c2, c0, 0 @ Translation table base 0
- mcr p15, 0, r8, c2, c0, 1 @ Translation table base 1
- mcr p15, 0, r9, c1, c0, 1 @ auxiliary control register
- mcr p15, 0, r10, c1, c0, 2 @ co-processor access control
+ mcr p15, 0, r5, c3, c0, 0 @ Domain ID
+ ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
+ ALT_UP(orr r1, r1, #TTB_FLAGS_UP)
+ mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0
+ mcr p15, 0, r6, c2, c0, 1 @ Translation table base 1
+ mcr p15, 0, r7, c1, c0, 1 @ auxiliary control register
+ mcr p15, 0, r8, c1, c0, 2 @ co-processor access control
mcr p15, 0, ip, c2, c0, 2 @ TTB control register
mcr p15, 0, ip, c7, c5, 4 @ ISB
- mov r0, r11 @ control register
- mov r2, r7, lsr #14 @ get TTB0 base
- mov r2, r2, lsl #14
- ldr r3, cpu_resume_l1_flags
+ mov r0, r9 @ control register
b cpu_resume_mmu
ENDPROC(cpu_v6_do_resume)
-cpu_resume_l1_flags:
- ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
- ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
#endif
string cpu_v6_name, "ARMv6-compatible processor"
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 9049c0764db2..2c559ac38142 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -217,56 +217,50 @@ ENDPROC(cpu_v7_set_pte_ext)
/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
.globl cpu_v7_suspend_size
-.equ cpu_v7_suspend_size, 4 * 9
-#ifdef CONFIG_PM_SLEEP
+.equ cpu_v7_suspend_size, 4 * 7
+#ifdef CONFIG_ARM_CPU_SUSPEND
ENTRY(cpu_v7_do_suspend)
- stmfd sp!, {r4 - r11, lr}
+ stmfd sp!, {r4 - r10, lr}
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
- mrc p15, 0, r5, c13, c0, 1 @ Context ID
- mrc p15, 0, r6, c13, c0, 3 @ User r/o thread ID
- stmia r0!, {r4 - r6}
+ mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID
+ stmia r0!, {r4 - r5}
mrc p15, 0, r6, c3, c0, 0 @ Domain ID
- mrc p15, 0, r7, c2, c0, 0 @ TTB 0
- mrc p15, 0, r8, c2, c0, 1 @ TTB 1
- mrc p15, 0, r9, c1, c0, 0 @ Control register
- mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
- mrc p15, 0, r11, c1, c0, 2 @ Co-processor access control
- stmia r0, {r6 - r11}
- ldmfd sp!, {r4 - r11, pc}
+ mrc p15, 0, r7, c2, c0, 1 @ TTB 1
+ mrc p15, 0, r8, c1, c0, 0 @ Control register
+ mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register
+ mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control
+ stmia r0, {r6 - r10}
+ ldmfd sp!, {r4 - r10, pc}
ENDPROC(cpu_v7_do_suspend)
ENTRY(cpu_v7_do_resume)
mov ip, #0
mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
- ldmia r0!, {r4 - r6}
+ mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID
+ ldmia r0!, {r4 - r5}
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
- mcr p15, 0, r5, c13, c0, 1 @ Context ID
- mcr p15, 0, r6, c13, c0, 3 @ User r/o thread ID
- ldmia r0, {r6 - r11}
+ mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID
+ ldmia r0, {r6 - r10}
mcr p15, 0, r6, c3, c0, 0 @ Domain ID
- mcr p15, 0, r7, c2, c0, 0 @ TTB 0
- mcr p15, 0, r8, c2, c0, 1 @ TTB 1
+ ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
+ ALT_UP(orr r1, r1, #TTB_FLAGS_UP)
+ mcr p15, 0, r1, c2, c0, 0 @ TTB 0
+ mcr p15, 0, r7, c2, c0, 1 @ TTB 1
mcr p15, 0, ip, c2, c0, 2 @ TTB control register
mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register
- teq r4, r10 @ Is it already set?
- mcrne p15, 0, r10, c1, c0, 1 @ No, so write it
- mcr p15, 0, r11, c1, c0, 2 @ Co-processor access control
+ teq r4, r9 @ Is it already set?
+ mcrne p15, 0, r9, c1, c0, 1 @ No, so write it
+ mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control
ldr r4, =PRRR @ PRRR
ldr r5, =NMRR @ NMRR
mcr p15, 0, r4, c10, c2, 0 @ write PRRR
mcr p15, 0, r5, c10, c2, 1 @ write NMRR
isb
dsb
- mov r0, r9 @ control register
- mov r2, r7, lsr #14 @ get TTB0 base
- mov r2, r2, lsl #14
- ldr r3, cpu_resume_l1_flags
+ mov r0, r8 @ control register
b cpu_resume_mmu
ENDPROC(cpu_v7_do_resume)
-cpu_resume_l1_flags:
- ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
- ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
#endif
__CPUINIT
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 755e1bf22681..abf0507a08ae 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -406,24 +406,23 @@ ENTRY(cpu_xsc3_set_pte_ext)
.align
.globl cpu_xsc3_suspend_size
-.equ cpu_xsc3_suspend_size, 4 * 7
+.equ cpu_xsc3_suspend_size, 4 * 6
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_xsc3_do_suspend)
- stmfd sp!, {r4 - r10, lr}
+ stmfd sp!, {r4 - r9, lr}
mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode
mrc p15, 0, r5, c15, c1, 0 @ CP access reg
mrc p15, 0, r6, c13, c0, 0 @ PID
mrc p15, 0, r7, c3, c0, 0 @ domain ID
- mrc p15, 0, r8, c2, c0, 0 @ translation table base addr
- mrc p15, 0, r9, c1, c0, 1 @ auxiliary control reg
- mrc p15, 0, r10, c1, c0, 0 @ control reg
+ mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg
+ mrc p15, 0, r9, c1, c0, 0 @ control reg
bic r4, r4, #2 @ clear frequency change bit
- stmia r0, {r4 - r10} @ store cp regs
- ldmia sp!, {r4 - r10, pc}
+ stmia r0, {r4 - r9} @ store cp regs
+ ldmia sp!, {r4 - r9, pc}
ENDPROC(cpu_xsc3_do_suspend)
ENTRY(cpu_xsc3_do_resume)
- ldmia r0, {r4 - r10} @ load cp regs
+ ldmia r0, {r4 - r9} @ load cp regs
mov ip, #0
mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB
mcr p15, 0, ip, c7, c10, 4 @ drain write (&fill) buffer
@@ -433,15 +432,10 @@ ENTRY(cpu_xsc3_do_resume)
mcr p15, 0, r5, c15, c1, 0 @ CP access reg
mcr p15, 0, r6, c13, c0, 0 @ PID
mcr p15, 0, r7, c3, c0, 0 @ domain ID
- mcr p15, 0, r8, c2, c0, 0 @ translation table base addr
- mcr p15, 0, r9, c1, c0, 1 @ auxiliary control reg
-
- @ temporarily map resume_turn_on_mmu into the page table,
- @ otherwise prefetch abort occurs after MMU is turned on
- mov r0, r10 @ control register
- mov r2, r8, lsr #14 @ get TTB0 base
- mov r2, r2, lsl #14
- ldr r3, =0x542e @ section flags
+ orr r1, r1, #0x18 @ cache the page table in L2
+ mcr p15, 0, r1, c2, c0, 0 @ translation table base addr
+ mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg
+ mov r0, r9 @ control register
b cpu_resume_mmu
ENDPROC(cpu_xsc3_do_resume)
#endif
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index fbc06e55b87a..3277904bebaf 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -520,24 +520,23 @@ ENTRY(cpu_xscale_set_pte_ext)
.align
.globl cpu_xscale_suspend_size
-.equ cpu_xscale_suspend_size, 4 * 7
+.equ cpu_xscale_suspend_size, 4 * 6
#ifdef CONFIG_PM_SLEEP
ENTRY(cpu_xscale_do_suspend)
- stmfd sp!, {r4 - r10, lr}
+ stmfd sp!, {r4 - r9, lr}
mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode
mrc p15, 0, r5, c15, c1, 0 @ CP access reg
mrc p15, 0, r6, c13, c0, 0 @ PID
mrc p15, 0, r7, c3, c0, 0 @ domain ID
- mrc p15, 0, r8, c2, c0, 0 @ translation table base addr
- mrc p15, 0, r9, c1, c1, 0 @ auxiliary control reg
- mrc p15, 0, r10, c1, c0, 0 @ control reg
+ mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg
+ mrc p15, 0, r9, c1, c0, 0 @ control reg
bic r4, r4, #2 @ clear frequency change bit
- stmia r0, {r4 - r10} @ store cp regs
- ldmfd sp!, {r4 - r10, pc}
+ stmia r0, {r4 - r9} @ store cp regs
+ ldmfd sp!, {r4 - r9, pc}
ENDPROC(cpu_xscale_do_suspend)
ENTRY(cpu_xscale_do_resume)
- ldmia r0, {r4 - r10} @ load cp regs
+ ldmia r0, {r4 - r9} @ load cp regs
mov ip, #0
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB
@@ -545,13 +544,9 @@ ENTRY(cpu_xscale_do_resume)
mcr p15, 0, r5, c15, c1, 0 @ CP access reg
mcr p15, 0, r6, c13, c0, 0 @ PID
mcr p15, 0, r7, c3, c0, 0 @ domain ID
- mcr p15, 0, r8, c2, c0, 0 @ translation table base addr
- mcr p15, 0, r9, c1, c1, 0 @ auxiliary control reg
- mov r0, r10 @ control register
- mov r2, r8, lsr #14 @ get TTB0 base
- mov r2, r2, lsl #14
- ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
- PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+ mcr p15, 0, r1, c2, c0, 0 @ translation table base addr
+ mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg
+ mov r0, r9 @ control register
b cpu_resume_mmu
ENDPROC(cpu_xscale_do_resume)
#endif
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index a5353fc0793f..a08a95107a63 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -4,50 +4,34 @@ source "arch/arm/plat-mxc/devices/Kconfig"
menu "Freescale MXC Implementations"
-config ARCH_MX50_SUPPORTED
- bool
-
-config ARCH_MX53_SUPPORTED
- bool
-
choice
prompt "Freescale CPU family:"
- default ARCH_MX3
-
-config ARCH_MX1
- bool "MX1-based"
- help
- This enables support for systems based on the Freescale i.MX1 family
-
-config ARCH_MX2
- bool "MX2-based"
- help
- This enables support for systems based on the Freescale i.MX2 family
+ default ARCH_IMX_V6_V7
-config ARCH_MX25
- bool "MX25-based"
+config ARCH_IMX_V4_V5
+ bool "i.MX1, i.MX21, i.MX25, i.MX27"
+ select AUTO_ZRELADDR
+ select ARM_PATCH_PHYS_VIRT
help
- This enables support for systems based on the Freescale i.MX25 family
+ This enables support for systems based on the Freescale i.MX ARMv4
+ and ARMv5 SoCs
-config ARCH_MX3
- bool "MX3-based"
+config ARCH_IMX_V6_V7
+ bool "i.MX3, i.MX6"
+ select AUTO_ZRELADDR if !ZBOOT_ROM
+ select ARM_PATCH_PHYS_VIRT
help
- This enables support for systems based on the Freescale i.MX3 family
+ This enables support for systems based on the Freescale i.MX3 and i.MX6
+ family.
-config ARCH_MX503
- bool "i.MX50 + i.MX53"
- select ARCH_MX50_SUPPORTED
- select ARCH_MX53_SUPPORTED
+config ARCH_MX5
+ bool "i.MX50, i.MX51, i.MX53"
+ select AUTO_ZRELADDR
+ select ARM_PATCH_PHYS_VIRT
help
- This enables support for machines using Freescale's i.MX50 and i.MX51
+ This enables support for machines using Freescale's i.MX50 and i.MX53
processors.
-config ARCH_MX51
- bool "i.MX51"
- select ARCH_MX51_SUPPORTED
- help
- This enables support for systems based on the Freescale i.MX51 family
-
endchoice
source "arch/arm/mach-imx/Kconfig"
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index d53c35fe2ea7..b9f0f5f499a4 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -5,7 +5,7 @@
# Common support
obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o
-# MX51 uses the TZIC interrupt controller, older platforms use AVIC
+obj-$(CONFIG_ARM_GIC) += gic.o
obj-$(CONFIG_MXC_TZIC) += tzic.o
obj-$(CONFIG_MXC_AVIC) += avic.o
diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c
index 175e3647bb27..8cced35009bd 100644
--- a/arch/arm/plat-mxc/audmux-v2.c
+++ b/arch/arm/plat-mxc/audmux-v2.c
@@ -187,18 +187,11 @@ EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port);
static int mxc_audmux_v2_init(void)
{
int ret;
-#if defined(CONFIG_ARCH_MX5)
if (cpu_is_mx51()) {
audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR);
- ret = 0;
- return ret;
- }
-#endif
-#if defined(CONFIG_ARCH_MX3)
- if (cpu_is_mx31())
+ } else if (cpu_is_mx31()) {
audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
-
- else if (cpu_is_mx35()) {
+ } else if (cpu_is_mx35()) {
audmux_clk = clk_get(NULL, "audmux");
if (IS_ERR(audmux_clk)) {
ret = PTR_ERR(audmux_clk);
@@ -207,10 +200,7 @@ static int mxc_audmux_v2_init(void)
return ret;
}
audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR);
- }
-#endif
-#if defined(CONFIG_SOC_IMX25)
- if (cpu_is_mx25()) {
+ } else if (cpu_is_mx25()) {
audmux_clk = clk_get(NULL, "audmux");
if (IS_ERR(audmux_clk)) {
ret = PTR_ERR(audmux_clk);
@@ -220,7 +210,7 @@ static int mxc_audmux_v2_init(void)
}
audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR);
}
-#endif /* if defined(CONFIG_SOC_IMX25) */
+
audmux_debugfs_init();
return 0;
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
index 55d2534ec727..8875fb415f68 100644
--- a/arch/arm/plat-mxc/avic.c
+++ b/arch/arm/plat-mxc/avic.c
@@ -50,6 +50,8 @@
void __iomem *avic_base;
+static u32 avic_saved_mask_reg[2];
+
#ifdef CONFIG_MXC_IRQ_PRIOR
static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
{
@@ -90,24 +92,8 @@ static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
}
#endif /* CONFIG_FIQ */
-/* Disable interrupt number "irq" in the AVIC */
-static void mxc_mask_irq(struct irq_data *d)
-{
- __raw_writel(d->irq, avic_base + AVIC_INTDISNUM);
-}
-/* Enable interrupt number "irq" in the AVIC */
-static void mxc_unmask_irq(struct irq_data *d)
-{
- __raw_writel(d->irq, avic_base + AVIC_INTENNUM);
-}
-
-static struct mxc_irq_chip mxc_avic_chip = {
- .base = {
- .irq_ack = mxc_mask_irq,
- .irq_mask = mxc_mask_irq,
- .irq_unmask = mxc_unmask_irq,
- },
+static struct mxc_extra_irq avic_extra_irq = {
#ifdef CONFIG_MXC_IRQ_PRIOR
.set_priority = avic_irq_set_priority,
#endif
@@ -116,6 +102,68 @@ static struct mxc_irq_chip mxc_avic_chip = {
#endif
};
+#ifdef CONFIG_PM
+static void avic_irq_suspend(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = gc->chip_types;
+ int idx = gc->irq_base >> 5;
+
+ avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask);
+ __raw_writel(gc->wake_active, avic_base + ct->regs.mask);
+}
+
+static void avic_irq_resume(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = gc->chip_types;
+ int idx = gc->irq_base >> 5;
+
+ __raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
+}
+
+#else
+#define avic_irq_suspend NULL
+#define avic_irq_resume NULL
+#endif
+
+static __init void avic_init_gc(unsigned int irq_start)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+ int idx = irq_start >> 5;
+
+ gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
+ handle_level_irq);
+ gc->private = &avic_extra_irq;
+ gc->wake_enabled = IRQ_MSK(32);
+
+ ct = gc->chip_types;
+ ct->chip.irq_mask = irq_gc_mask_clr_bit;
+ ct->chip.irq_unmask = irq_gc_mask_set_bit;
+ ct->chip.irq_ack = irq_gc_mask_clr_bit;
+ ct->chip.irq_set_wake = irq_gc_set_wake;
+ ct->chip.irq_suspend = avic_irq_suspend;
+ ct->chip.irq_resume = avic_irq_resume;
+ ct->regs.mask = !idx ? AVIC_INTENABLEL : AVIC_INTENABLEH;
+ ct->regs.ack = ct->regs.mask;
+
+ irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+}
+
+asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
+{
+ u32 nivector;
+
+ do {
+ nivector = __raw_readl(avic_base + AVIC_NIVECSR) >> 16;
+ if (nivector == 0xffff)
+ break;
+
+ handle_IRQ(nivector, regs);
+ } while (1);
+}
+
/*
* This function initializes the AVIC hardware and disables all the
* interrupts. It registers the interrupt enable and disable functions
@@ -140,11 +188,9 @@ void __init mxc_init_irq(void __iomem *irqbase)
/* all IRQ no FIQ */
__raw_writel(0, avic_base + AVIC_INTTYPEH);
__raw_writel(0, avic_base + AVIC_INTTYPEL);
- for (i = 0; i < AVIC_NUM_IRQS; i++) {
- irq_set_chip_and_handler(i, &mxc_avic_chip.base,
- handle_level_irq);
- set_irq_flags(i, IRQF_VALID);
- }
+
+ for (i = 0; i < AVIC_NUM_IRQS; i += 32)
+ avic_init_gc(i);
/* Set default priority value (0) for all IRQ's */
for (i = 0; i < 8; i++)
@@ -157,4 +203,3 @@ void __init mxc_init_irq(void __iomem *irqbase)
printk(KERN_INFO "MXC IRQ initialized\n");
}
-
diff --git a/arch/arm/plat-mxc/cpu.c b/arch/arm/plat-mxc/cpu.c
index 386e0d52cf58..f5b7e0fa237f 100644
--- a/arch/arm/plat-mxc/cpu.c
+++ b/arch/arm/plat-mxc/cpu.c
@@ -1,5 +1,6 @@
#include <linux/module.h>
+#include <mach/hardware.h>
unsigned int __mxc_cpu_type;
EXPORT_SYMBOL(__mxc_cpu_type);
@@ -9,3 +10,11 @@ void mxc_set_cpu_type(unsigned int type)
__mxc_cpu_type = type;
}
+void imx_print_silicon_rev(const char *cpu, int srev)
+{
+ if (srev == IMX_CHIP_REVISION_UNKNOWN)
+ pr_info("CPU identified as %s, unknown revision\n", cpu);
+ else
+ pr_info("CPU identified as %s, silicon rev %d.%d\n",
+ cpu, (srev >> 4) & 0xf, srev & 0xf);
+}
diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c
index 0d6ed31bdbf2..4d55a7a26e98 100644
--- a/arch/arm/plat-mxc/devices.c
+++ b/arch/arm/plat-mxc/devices.c
@@ -23,73 +23,6 @@
#include <linux/platform_device.h>
#include <mach/common.h>
-int __init mxc_register_device(struct platform_device *pdev, void *data)
-{
- int ret;
-
- pdev->dev.platform_data = data;
-
- ret = platform_device_register(pdev);
- if (ret)
- pr_debug("Unable to register platform device '%s': %d\n",
- pdev->name, ret);
-
- return ret;
-}
-
-struct platform_device *__init imx_add_platform_device_dmamask(
- const char *name, int id,
- const struct resource *res, unsigned int num_resources,
- const void *data, size_t size_data, u64 dmamask)
-{
- int ret = -ENOMEM;
- struct platform_device *pdev;
-
- pdev = platform_device_alloc(name, id);
- if (!pdev)
- goto err;
-
- if (dmamask) {
- /*
- * This memory isn't freed when the device is put,
- * I don't have a nice idea for that though. Conceptually
- * dma_mask in struct device should not be a pointer.
- * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
- */
- pdev->dev.dma_mask =
- kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
- if (!pdev->dev.dma_mask)
- /* ret is still -ENOMEM; */
- goto err;
-
- *pdev->dev.dma_mask = dmamask;
- pdev->dev.coherent_dma_mask = dmamask;
- }
-
- if (res) {
- ret = platform_device_add_resources(pdev, res, num_resources);
- if (ret)
- goto err;
- }
-
- if (data) {
- ret = platform_device_add_data(pdev, data, size_data);
- if (ret)
- goto err;
- }
-
- ret = platform_device_add(pdev);
- if (ret) {
-err:
- if (dmamask)
- kfree(pdev->dev.dma_mask);
- platform_device_put(pdev);
- return ERR_PTR(ret);
- }
-
- return pdev;
-}
-
struct device mxc_aips_bus = {
.init_name = "mxc_aips",
.parent = &platform_bus,
diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig
index bd294add932c..cb3e3eef55c0 100644
--- a/arch/arm/plat-mxc/devices/Kconfig
+++ b/arch/arm/plat-mxc/devices/Kconfig
@@ -1,6 +1,6 @@
config IMX_HAVE_PLATFORM_FEC
bool
- default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
+ default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX50 || SOC_IMX51 || SOC_IMX53
config IMX_HAVE_PLATFORM_FLEXCAN
select HAVE_CAN_FLEXCAN if CAN
@@ -31,6 +31,9 @@ config IMX_HAVE_PLATFORM_IMX_I2C
config IMX_HAVE_PLATFORM_IMX_KEYPAD
bool
+config IMX_HAVE_PLATFORM_PATA_IMX
+ bool
+
config IMX_HAVE_PLATFORM_IMX_SSI
bool
@@ -76,3 +79,7 @@ config IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
config IMX_HAVE_PLATFORM_SPI_IMX
bool
+
+config IMX_HAVE_PLATFORM_AHCI
+ bool
+ default y if ARCH_MX53
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index b41bf972b54b..c11ac8472beb 100644
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -10,6 +10,7 @@ obj-y += platform-imx-dma.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_FB) += platform-imx-fb.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_KEYPAD) += platform-imx-keypad.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_PATA_IMX) += platform-pata_imx.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UDC) += platform-imx_udc.o
@@ -25,3 +26,4 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RTC) += platform-mxc_rtc.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_W1) += platform-mxc_w1.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX) += platform-sdhci-esdhc-imx.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) += platform-spi_imx.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_AHCI) += platform-ahci-imx.o
diff --git a/arch/arm/plat-mxc/devices/platform-ahci-imx.c b/arch/arm/plat-mxc/devices/platform-ahci-imx.c
new file mode 100644
index 000000000000..d8a56aee521b
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-ahci-imx.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_ahci_imx_data_entry_single(soc, _devid) \
+ { \
+ .devid = _devid, \
+ .iobase = soc ## _SATA_BASE_ADDR, \
+ .irq = soc ## _INT_SATA, \
+ }
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_ahci_imx_data imx53_ahci_imx_data __initconst =
+ imx_ahci_imx_data_entry_single(MX53, "imx53-ahci");
+#endif
+
+enum {
+ HOST_CAP = 0x00,
+ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
+ HOST_PORTS_IMPL = 0x0c,
+ HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
+};
+
+static struct clk *sata_clk, *sata_ref_clk;
+
+/* AHCI module Initialization, if return 0, initialization is successful. */
+static int imx_sata_init(struct device *dev, void __iomem *addr)
+{
+ u32 tmpdata;
+ int ret = 0;
+ struct clk *clk;
+
+ sata_clk = clk_get(dev, "ahci");
+ if (IS_ERR(sata_clk)) {
+ dev_err(dev, "no sata clock.\n");
+ return PTR_ERR(sata_clk);
+ }
+ ret = clk_enable(sata_clk);
+ if (ret) {
+ dev_err(dev, "can't enable sata clock.\n");
+ goto put_sata_clk;
+ }
+
+ /* Get the AHCI SATA PHY CLK */
+ sata_ref_clk = clk_get(dev, "ahci_phy");
+ if (IS_ERR(sata_ref_clk)) {
+ dev_err(dev, "no sata ref clock.\n");
+ ret = PTR_ERR(sata_ref_clk);
+ goto release_sata_clk;
+ }
+ ret = clk_enable(sata_ref_clk);
+ if (ret) {
+ dev_err(dev, "can't enable sata ref clock.\n");
+ goto put_sata_ref_clk;
+ }
+
+ /* Get the AHB clock rate, and configure the TIMER1MS reg later */
+ clk = clk_get(dev, "ahci_dma");
+ if (IS_ERR(clk)) {
+ dev_err(dev, "no dma clock.\n");
+ ret = PTR_ERR(clk);
+ goto release_sata_ref_clk;
+ }
+ tmpdata = clk_get_rate(clk) / 1000;
+ clk_put(clk);
+
+ writel(tmpdata, addr + HOST_TIMER1MS);
+
+ tmpdata = readl(addr + HOST_CAP);
+ if (!(tmpdata & HOST_CAP_SSS)) {
+ tmpdata |= HOST_CAP_SSS;
+ writel(tmpdata, addr + HOST_CAP);
+ }
+
+ if (!(readl(addr + HOST_PORTS_IMPL) & 0x1))
+ writel((readl(addr + HOST_PORTS_IMPL) | 0x1),
+ addr + HOST_PORTS_IMPL);
+
+ return 0;
+
+release_sata_ref_clk:
+ clk_disable(sata_ref_clk);
+put_sata_ref_clk:
+ clk_put(sata_ref_clk);
+release_sata_clk:
+ clk_disable(sata_clk);
+put_sata_clk:
+ clk_put(sata_clk);
+
+ return ret;
+}
+
+static void imx_sata_exit(struct device *dev)
+{
+ clk_disable(sata_ref_clk);
+ clk_put(sata_ref_clk);
+
+ clk_disable(sata_clk);
+ clk_put(sata_clk);
+
+}
+struct platform_device *__init imx_add_ahci_imx(
+ const struct imx_ahci_imx_data *data,
+ const struct ahci_platform_data *pdata)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return imx_add_platform_device_dmamask(data->devid, 0,
+ res, ARRAY_SIZE(res),
+ pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
+
+struct platform_device *__init imx53_add_ahci_imx(void)
+{
+ struct ahci_platform_data pdata = {
+ .init = imx_sata_init,
+ .exit = imx_sata_exit,
+ };
+
+ return imx_add_ahci_imx(&imx53_ahci_imx_data, &pdata);
+}
diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
index 23ce08e6ffd2..848038f301fd 100644
--- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
+++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
@@ -36,6 +36,11 @@ const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst =
imx_fsl_usb2_udc_data_entry_single(MX35);
#endif /* ifdef CONFIG_SOC_IMX35 */
+#ifdef CONFIG_SOC_IMX51
+const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
+ imx_fsl_usb2_udc_data_entry_single(MX51);
+#endif
+
struct platform_device *__init imx_add_fsl_usb2_udc(
const struct imx_fsl_usb2_udc_data *data,
const struct fsl_usb2_platform_data *pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
index afe60f7244a8..19ad580c0be3 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
@@ -85,6 +85,12 @@ const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
imx_imx_i2c_data_entry(MX51, _id, _hwid, SZ_4K)
imx51_imx_i2c_data_entry(0, 1),
imx51_imx_i2c_data_entry(1, 2),
+ {
+ .id = 2,
+ .iobase = MX51_HSI2C_DMA_BASE_ADDR,
+ .iosize = SZ_16K,
+ .irq = MX51_INT_HS_I2C,
+ },
};
#endif /* ifdef CONFIG_SOC_IMX51 */
diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
index e1763e03e7cb..35851d889aca 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
@@ -49,6 +49,15 @@ const struct imx_mxc_ehci_data imx35_mxc_ehci_hs_data __initconst =
imx_mxc_ehci_data_entry_single(MX35, 1, HS);
#endif /* ifdef CONFIG_SOC_IMX35 */
+#ifdef CONFIG_SOC_IMX51
+const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data __initconst =
+ imx_mxc_ehci_data_entry_single(MX51, 0, OTG);
+const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[] __initconst = {
+ imx_mxc_ehci_data_entry_single(MX51, 1, HS1),
+ imx_mxc_ehci_data_entry_single(MX51, 2, HS2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
struct platform_device *__init imx_add_mxc_ehci(
const struct imx_mxc_ehci_data *data,
const struct mxc_usbh_platform_data *pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-pata_imx.c b/arch/arm/plat-mxc/devices/platform-pata_imx.c
new file mode 100644
index 000000000000..70e2f2a44714
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-pata_imx.c
@@ -0,0 +1,59 @@
+/*
+ * 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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_pata_imx_data_entry_single(soc, _size) \
+ { \
+ .iobase = soc ## _ATA_BASE_ADDR, \
+ .iosize = _size, \
+ .irq = soc ## _INT_ATA, \
+ }
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_pata_imx_data imx27_pata_imx_data __initconst =
+ imx_pata_imx_data_entry_single(MX27, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_pata_imx_data imx31_pata_imx_data __initconst =
+ imx_pata_imx_data_entry_single(MX31, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_pata_imx_data imx35_pata_imx_data __initconst =
+ imx_pata_imx_data_entry_single(MX35, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_pata_imx_data imx51_pata_imx_data __initconst =
+ imx_pata_imx_data_entry_single(MX51, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_pata_imx_data imx53_pata_imx_data __initconst =
+ imx_pata_imx_data_entry_single(MX53, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_pata_imx(
+ const struct imx_pata_imx_data *data)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + data->iosize - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+ return imx_add_platform_device("pata_imx", -1,
+ res, ARRAY_SIZE(res), NULL, 0);
+}
+
diff --git a/arch/arm/plat-mxc/gic.c b/arch/arm/plat-mxc/gic.c
new file mode 100644
index 000000000000..b3b8eed263b8
--- /dev/null
+++ b/arch/arm/plat-mxc/gic.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <asm/exception.h>
+#include <asm/localtimer.h>
+#include <asm/hardware/gic.h>
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#endif
+
+asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+{
+ u32 irqstat, irqnr;
+
+ do {
+ irqstat = readl_relaxed(gic_cpu_base_addr + GIC_CPU_INTACK);
+ irqnr = irqstat & 0x3ff;
+ if (irqnr == 1023)
+ break;
+
+ if (irqnr > 29 && irqnr < 1021)
+ handle_IRQ(irqnr, regs);
+#ifdef CONFIG_SMP
+ else if (irqnr < 16) {
+ writel_relaxed(irqstat, gic_cpu_base_addr +
+ GIC_CPU_EOI);
+ handle_IPI(irqnr, regs);
+ }
+#endif
+#ifdef CONFIG_LOCAL_TIMERS
+ else if (irqnr == 29) {
+ writel_relaxed(irqstat, gic_cpu_base_addr +
+ GIC_CPU_EOI);
+ handle_local_timer(regs);
+ }
+#endif
+ } while (1);
+}
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 4e3d97890d69..83b745a5e1b7 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -13,6 +13,7 @@
struct platform_device;
struct clk;
+enum mxc_cpu_pwr_mode;
extern void mx1_map_io(void);
extern void mx21_map_io(void);
@@ -64,12 +65,72 @@ 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 mx51_clocks_init_dt(void);
+extern int mx53_clocks_init_dt(void);
+extern int mx6q_clocks_init(void);
extern struct platform_device *mxc_register_gpio(char *name, int id,
resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
-extern int mxc_register_device(struct platform_device *pdev, void *data);
extern void mxc_set_cpu_type(unsigned int type);
extern void mxc_arch_reset_init(void __iomem *);
extern void mx51_efikamx_reset(void);
extern int mx53_revision(void);
extern int mx53_display_revision(void);
+
+enum mxc_cpu_pwr_mode {
+ WAIT_CLOCKED, /* wfi only */
+ WAIT_UNCLOCKED, /* WAIT */
+ WAIT_UNCLOCKED_POWER_OFF, /* WAIT + SRPG */
+ STOP_POWER_ON, /* just STOP */
+ STOP_POWER_OFF, /* STOP + SRPG */
+};
+
+extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
+extern void (*imx_idle)(void);
+extern void imx_print_silicon_rev(const char *cpu, int srev);
+
+void avic_handle_irq(struct pt_regs *);
+void tzic_handle_irq(struct pt_regs *);
+void gic_handle_irq(struct pt_regs *);
+
+#define imx1_handle_irq avic_handle_irq
+#define imx21_handle_irq avic_handle_irq
+#define imx25_handle_irq avic_handle_irq
+#define imx27_handle_irq avic_handle_irq
+#define imx31_handle_irq avic_handle_irq
+#define imx35_handle_irq avic_handle_irq
+#define imx50_handle_irq tzic_handle_irq
+#define imx51_handle_irq tzic_handle_irq
+#define imx53_handle_irq tzic_handle_irq
+#define imx6q_handle_irq gic_handle_irq
+
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+#ifdef CONFIG_DEBUG_LL
+extern void imx_lluart_map_io(void);
+#else
+static inline void imx_lluart_map_io(void) {}
+#endif
+extern void v7_cpu_resume(void);
+extern u32 *pl310_get_save_ptr(void);
+#ifdef CONFIG_SMP
+extern void v7_secondary_startup(void);
+extern void imx_scu_map_io(void);
+extern void imx_smp_prepare(void);
+#else
+static inline void imx_scu_map_io(void) {}
+static inline void imx_smp_prepare(void) {}
+#endif
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+extern void imx_src_init(void);
+extern void imx_gpc_init(void);
+extern void imx_gpc_pre_suspend(void);
+extern void imx_gpc_post_resume(void);
+extern void imx51_babbage_common_init(void);
+extern void imx53_ard_common_init(void);
+extern void imx53_evk_common_init(void);
+extern void imx53_qsb_common_init(void);
+extern void imx53_smd_common_init(void);
+extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
+extern void imx6q_pm_init(void);
#endif
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index e4dde91f0231..6e192c4a391a 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -12,49 +12,25 @@
*/
#include <mach/hardware.h>
-#ifdef CONFIG_SOC_IMX1
+#ifdef CONFIG_DEBUG_IMX1_UART
#define UART_PADDR MX1_UART1_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX25
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX25_UART)
#define UART_PADDR MX25_UART1_BASE_ADDR
-#endif
-
-#if defined(CONFIG_SOC_IMX21) || defined (CONFIG_SOC_IMX27)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX21_IMX27_UART)
#define UART_PADDR MX2x_UART1_BASE_ADDR
-#endif
-
-#if defined(CONFIG_SOC_IMX31) || defined(CONFIG_SOC_IMX35)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX31_IMX35_UART)
#define UART_PADDR MX3x_UART1_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX51
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX51_UART)
#define UART_PADDR MX51_UART1_BASE_ADDR
-#endif
-
-/* iMX50/53 have same addresses, but not iMX51 */
-#if defined(CONFIG_SOC_IMX50) || defined(CONFIG_SOC_IMX53)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
#define UART_PADDR MX53_UART1_BASE_ADDR
+#elif defined (CONFIG_DEBUG_IMX6Q_UART)
+#define UART_PADDR MX6Q_UART4_BASE_ADDR
#endif
#define UART_VADDR IMX_IO_ADDRESS(UART_PADDR)
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
ldr \rp, =UART_PADDR @ physical
ldr \rv, =UART_VADDR @ virtual
.endm
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index 524538aabc4b..def9ba53e23a 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -14,10 +14,22 @@
extern struct device mxc_aips_bus;
extern struct device mxc_ahb_bus;
-struct platform_device *imx_add_platform_device_dmamask(
+static inline struct platform_device *imx_add_platform_device_dmamask(
const char *name, int id,
const struct resource *res, unsigned int num_resources,
- const void *data, size_t size_data, u64 dmamask);
+ const void *data, size_t size_data, u64 dmamask)
+{
+ struct platform_device_info pdevinfo = {
+ .name = name,
+ .id = id,
+ .res = res,
+ .num_res = num_resources,
+ .data = data,
+ .size_data = size_data,
+ .dma_mask = dmamask,
+ };
+ return platform_device_register_full(&pdevinfo);
+}
static inline struct platform_device *imx_add_platform_device(
const char *name, int id,
@@ -251,6 +263,14 @@ struct platform_device *__init imx_add_mxc_nand(
const struct imx_mxc_nand_data *data,
const struct mxc_nand_platform_data *pdata);
+struct imx_pata_imx_data {
+ resource_size_t iobase;
+ resource_size_t iosize;
+ resource_size_t irq;
+};
+struct platform_device *__init imx_add_pata_imx(
+ const struct imx_pata_imx_data *data);
+
struct imx_mxc_pwm_data {
int id;
resource_size_t iobase;
@@ -301,3 +321,13 @@ struct platform_device *__init imx_add_spi_imx(
struct platform_device *imx_add_imx_dma(void);
struct platform_device *imx_add_imx_sdma(char *name,
resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
+
+#include <linux/ahci_platform.h>
+struct imx_ahci_imx_data {
+ const char *devid;
+ resource_size_t iobase;
+ resource_size_t irq;
+};
+struct platform_device *__init imx_add_ahci_imx(
+ const struct imx_ahci_imx_data *data,
+ const struct ahci_platform_data *pdata);
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S
index 066d464d322d..9fe0dfcf4e7e 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -9,72 +9,22 @@
* published by the Free Software Foundation.
*/
-#include <mach/hardware.h>
+/* Unused, we use CONFIG_MULTI_IRQ_HANDLER */
-#define AVIC_NIMASK 0x04
-
- @ this macro disables fast irq (not implemented)
.macro disable_fiq
.endm
.macro get_irqnr_preamble, base, tmp
-#ifndef CONFIG_MXC_TZIC
- ldr \base, =avic_base
- ldr \base, [\base]
-#ifdef CONFIG_MXC_IRQ_PRIOR
- ldr r4, [\base, #AVIC_NIMASK]
-#endif
-#elif defined CONFIG_MXC_TZIC
- ldr \base, =tzic_base
- ldr \base, [\base]
-#endif /* CONFIG_MXC_TZIC */
.endm
.macro arch_ret_to_user, tmp1, tmp2
.endm
- @ this macro checks which interrupt occurred
- @ and returns its number in irqnr
- @ and returns if an interrupt occurred in irqstat
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-#ifndef CONFIG_MXC_TZIC
- @ Load offset & priority of the highest priority
- @ interrupt pending from AVIC_NIVECSR
- ldr \irqstat, [\base, #0x40]
- @ Shift to get the decoded IRQ number, using ASR so
- @ 'no interrupt pending' becomes 0xffffffff
- mov \irqnr, \irqstat, asr #16
- @ set zero flag if IRQ + 1 == 0
- adds \tmp, \irqnr, #1
-#ifdef CONFIG_MXC_IRQ_PRIOR
- bicne \tmp, \irqstat, #0xFFFFFFE0
- strne \tmp, [\base, #AVIC_NIMASK]
- streq r4, [\base, #AVIC_NIMASK]
-#endif
-#elif defined CONFIG_MXC_TZIC
- @ Load offset & priority of the highest priority
- @ interrupt pending.
- @ 0x080 is INTSEC0 register
- @ 0xD80 is HIPND0 register
- mov \irqnr, #0
-1000: add \irqstat, \base, \irqnr, lsr #3
- ldr \tmp, [\irqstat, #0xd80]
- ldr \irqstat, [\irqstat, #0x080]
- ands \tmp, \tmp, \irqstat
- bne 1001f
- add \irqnr, \irqnr, #32
- cmp \irqnr, #128
- blo 1000b
- b 2001f
-1001: mov \irqstat, #1
-1002: tst \tmp, \irqstat
- bne 2002f
- movs \tmp, \tmp, lsr #1
- addne \irqnr, \irqnr, #1
- bne 1002b
-2001:
- mov \irqnr, #0
-2002:
- movs \irqnr, \irqnr
-#endif
+ .endm
+
+ .macro test_for_ipi, irqnr, irqstat, base, tmp
+ .endm
+
+ .macro test_for_ltirq, irqnr, irqstat, base, tmp
.endm
diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index 31c820c1b796..40a8c178f10d 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -1,39 +1 @@
-/*
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_GPIO_H__
-#define __ASM_ARCH_MXC_GPIO_H__
-
-#include <linux/spinlock.h>
-#include <mach/hardware.h>
-#include <asm-generic/gpio.h>
-
-
-/* There's a off-by-one betweem the gpio bank number and the gpiochip */
-/* range e.g. GPIO_1_5 is gpio 5 under linux */
-#define IMX_GPIO_NR(bank, nr) (((bank) - 1) * 32 + (nr))
-
-/* use gpiolib dispatchers */
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-
-#define gpio_to_irq(gpio) (MXC_GPIO_IRQ_START + (gpio))
-#define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START)
-
-#endif
+/* empty */
diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
index a8bfd565dcad..a599f01f8b92 100644
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ b/arch/arm/plat-mxc/include/mach/hardware.h
@@ -81,11 +81,21 @@
* AIPS1 0x53f00000+0x100000 -> 0xf5700000+0x100000
* AIPS2 0x63f00000+0x100000 -> 0xf5300000+0x100000
* mx51:
+ * TZIC 0xe0000000+0x004000 -> 0xf5000000+0x004000
* IRAM 0x1ffe0000+0x020000 -> 0xf4fe0000+0x020000
- * DEBUG 0x60000000+0x100000 -> 0xf5000000+0x100000
* SPBA0 0x70000000+0x100000 -> 0xf5400000+0x100000
* AIPS1 0x73f00000+0x100000 -> 0xf5700000+0x100000
* AIPS2 0x83f00000+0x100000 -> 0xf4300000+0x100000
+ * mx53:
+ * TZIC 0x0fffc000+0x004000 -> 0xf4bfc000+0x004000
+ * SPBA0 0x50000000+0x100000 -> 0xf5400000+0x100000
+ * AIPS1 0x53f00000+0x100000 -> 0xf5700000+0x100000
+ * AIPS2 0x63f00000+0x100000 -> 0xf5300000+0x100000
+ * mx6q:
+ * SCU 0x00a00000+0x001000 -> 0xf4000000+0x001000
+ * CCM 0x020c4000+0x004000 -> 0xf42c4000+0x004000
+ * ANATOP 0x020c8000+0x001000 -> 0xf42c8000+0x001000
+ * UART4 0x021f0000+0x004000 -> 0xf42f0000+0x004000
*/
#define IMX_IO_P2V(x) ( \
0xf4000000 + \
@@ -97,6 +107,7 @@
#include <mach/mxc.h>
+#include <mach/mx6q.h>
#include <mach/mx50.h>
#include <mach/mx51.h>
#include <mach/mx53.h>
@@ -116,4 +127,10 @@
.type = _type, \
}
+/* There's a off-by-one betweem the gpio bank number and the gpiochip */
+/* range e.g. GPIO_1_5 is gpio 5 under linux */
+#define IMX_GPIO_NR(bank, nr) (((bank) - 1) * 32 + (nr))
+
+#define IMX_GPIO_TO_IRQ(gpio) (MXC_GPIO_IRQ_START + (gpio))
+
#endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/i2c.h b/arch/arm/plat-mxc/include/mach/i2c.h
index 4a5dc5c6d8e8..375cdd0cf876 100644
--- a/arch/arm/plat-mxc/include/mach/i2c.h
+++ b/arch/arm/plat-mxc/include/mach/i2c.h
@@ -11,14 +11,10 @@
/**
* struct imxi2c_platform_data - structure of platform data for MXC I2C driver
- * @init: Initialise gpio's and other board specific things
- * @exit: Free everything initialised by @init
* @bitrate: Bus speed measured in Hz
*
**/
struct imxi2c_platform_data {
- int (*init)(struct device *dev);
- void (*exit)(struct device *dev);
int bitrate;
};
diff --git a/arch/arm/plat-mxc/include/mach/io.h b/arch/arm/plat-mxc/include/mach/io.h
index 4347a87d2bb0..338300b18b00 100644
--- a/arch/arm/plat-mxc/include/mach/io.h
+++ b/arch/arm/plat-mxc/include/mach/io.h
@@ -14,32 +14,22 @@
/* Allow IO space to be anywhere in the memory */
#define IO_SPACE_LIMIT 0xffffffff
-#if defined(CONFIG_SOC_IMX31) || defined(CONFIG_SOC_IMX35)
-#include <mach/hardware.h>
-
#define __arch_ioremap __imx_ioremap
#define __arch_iounmap __iounmap
#define addr_in_module(addr, mod) \
((unsigned long)(addr) - mod ## _BASE_ADDR < mod ## _SIZE)
+extern void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int);
+
static inline void __iomem *
__imx_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
{
- if (mtype == MT_DEVICE && (cpu_is_mx31() || cpu_is_mx35())) {
- /*
- * Access all peripherals below 0x80000000 as nonshared device
- * on mx3, but leave l2cc alone. Otherwise cache corruptions
- * can occur.
- */
- if (phys_addr < 0x80000000 &&
- !addr_in_module(phys_addr, MX3x_L2CC))
- mtype = MT_DEVICE_NONSHARED;
- }
-
- return __arm_ioremap(phys_addr, size, mtype);
+ if (imx_ioremap != NULL)
+ return imx_ioremap(phys_addr, size, mtype);
+ else
+ return __arm_ioremap(phys_addr, size, mtype);
}
-#endif
/* io address mapping macro */
#define __io(a) __typesafe_io(a)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
index c92f0b1f216f..63f22a009a65 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
@@ -735,6 +735,7 @@ enum iomux_pins {
#define MX31_PIN_KEY_COL5_KEY_COL5 IOMUX_MODE(MX31_PIN_KEY_COL5, IOMUX_CONFIG_FUNC)
#define MX31_PIN_KEY_COL6_KEY_COL6 IOMUX_MODE(MX31_PIN_KEY_COL6, IOMUX_CONFIG_FUNC)
#define MX31_PIN_KEY_COL7_KEY_COL7 IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_WATCHDOG_RST__WATCHDOG_RST IOMUX_MODE(MX31_PIN_WATCHDOG_RST, IOMUX_CONFIG_FUNC)
/*
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index df6acc066fb1..c7f5169a6a54 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -14,6 +14,8 @@
#define __MACH_IOMUX_MX51_H__
#include <mach/iomux-v3.h>
+#define __NA_ 0x000
+
/* Pad control groupings */
#define MX51_UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_HIGH | \
@@ -47,1521 +49,765 @@
/* Raw pin modes without pad control */
/* PAD MUX ALT INPSE PATH PADCTRL */
-#define _MX51_PAD_EIM_D16__AUD4_RXFS IOMUX_PAD(0x3f0, 0x5c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__AUD5_TXD IOMUX_PAD(0x3f0, 0x5c, 7, 0x08d8, 0, 0)
-#define _MX51_PAD_EIM_D16__EIM_D16 IOMUX_PAD(0x3f0, 0x5c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__GPIO2_0 IOMUX_PAD(0x3f0, 0x5c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__I2C1_SDA IOMUX_PAD(0x3f0, 0x5c, 0x14, 0x09b4, 0, 0)
-#define _MX51_PAD_EIM_D16__UART2_CTS IOMUX_PAD(0x3f0, 0x5c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__USBH2_DATA0 IOMUX_PAD(0x3f0, 0x5c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__AUD5_RXD IOMUX_PAD(0x3f4, 0x60, 7, 0x08d4, 0, 0)
-#define _MX51_PAD_EIM_D17__EIM_D17 IOMUX_PAD(0x3f4, 0x60, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__GPIO2_1 IOMUX_PAD(0x3f4, 0x60, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__UART2_RXD IOMUX_PAD(0x3f4, 0x60, 3, 0x09ec, 0, 0)
-#define _MX51_PAD_EIM_D17__UART3_CTS IOMUX_PAD(0x3f4, 0x60, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__USBH2_DATA1 IOMUX_PAD(0x3f4, 0x60, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__AUD5_TXC IOMUX_PAD(0x3f8, 0x64, 7, 0x08e4, 0, 0)
-#define _MX51_PAD_EIM_D18__EIM_D18 IOMUX_PAD(0x3f8, 0x64, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__GPIO2_2 IOMUX_PAD(0x3f8, 0x64, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__UART2_TXD IOMUX_PAD(0x3f8, 0x64, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__UART3_RTS IOMUX_PAD(0x3f8, 0x64, 4, 0x09f0, 1, 0)
-#define _MX51_PAD_EIM_D18__USBH2_DATA2 IOMUX_PAD(0x3f8, 0x64, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__AUD4_RXC IOMUX_PAD(0x3fc, 0x68, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__AUD5_TXFS IOMUX_PAD(0x3fc, 0x68, 7, 0x08e8, 0, 0)
-#define _MX51_PAD_EIM_D19__EIM_D19 IOMUX_PAD(0x3fc, 0x68, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__GPIO2_3 IOMUX_PAD(0x3fc, 0x68, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__I2C1_SCL IOMUX_PAD(0x3fc, 0x68, 0x14, 0x09b0, 0, 0)
-#define _MX51_PAD_EIM_D19__UART2_RTS IOMUX_PAD(0x3fc, 0x68, 3, 0x09e8, 1, 0)
-#define _MX51_PAD_EIM_D19__USBH2_DATA3 IOMUX_PAD(0x3fc, 0x68, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__AUD4_TXD IOMUX_PAD(0x400, 0x6c, 5, 0x08c8, 0, 0)
-#define _MX51_PAD_EIM_D20__EIM_D20 IOMUX_PAD(0x400, 0x6c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__GPIO2_4 IOMUX_PAD(0x400, 0x6c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__SRTC_ALARM_DEB IOMUX_PAD(0x400, 0x6c, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__USBH2_DATA4 IOMUX_PAD(0x400, 0x6c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__AUD4_RXD IOMUX_PAD(0x404, 0x70, 5, 0x08c4, 0, 0)
-#define _MX51_PAD_EIM_D21__EIM_D21 IOMUX_PAD(0x404, 0x70, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__GPIO2_5 IOMUX_PAD(0x404, 0x70, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__SRTC_ALARM_DEB IOMUX_PAD(0x404, 0x70, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__USBH2_DATA5 IOMUX_PAD(0x404, 0x70, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__AUD4_TXC IOMUX_PAD(0x408, 0x74, 5, 0x08cc, 0, 0)
-#define _MX51_PAD_EIM_D22__EIM_D22 IOMUX_PAD(0x408, 0x74, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__GPIO2_6 IOMUX_PAD(0x408, 0x74, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__USBH2_DATA6 IOMUX_PAD(0x408, 0x74, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__AUD4_TXFS IOMUX_PAD(0x40c, 0x78, 5, 0x08d0, 0, 0)
-#define _MX51_PAD_EIM_D23__EIM_D23 IOMUX_PAD(0x40c, 0x78, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__GPIO2_7 IOMUX_PAD(0x40c, 0x78, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__SPDIF_OUT1 IOMUX_PAD(0x40c, 0x78, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__USBH2_DATA7 IOMUX_PAD(0x40c, 0x78, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__AUD6_RXFS IOMUX_PAD(0x410, 0x7c, 5, 0x08f8, 0, 0)
-#define _MX51_PAD_EIM_D24__EIM_D24 IOMUX_PAD(0x410, 0x7c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__GPIO2_8 IOMUX_PAD(0x410, 0x7c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__I2C2_SDA IOMUX_PAD(0x410, 0x7c, 0x14, 0x09bc, 0, 0)
-#define _MX51_PAD_EIM_D24__UART3_CTS IOMUX_PAD(0x410, 0x7c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__USBOTG_DATA0 IOMUX_PAD(0x410, 0x7c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__EIM_D25 IOMUX_PAD(0x414, 0x80, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__KEY_COL6 IOMUX_PAD(0x414, 0x80, 1, 0x09c8, 0, 0)
-#define _MX51_PAD_EIM_D25__UART2_CTS IOMUX_PAD(0x414, 0x80, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__UART3_RXD IOMUX_PAD(0x414, 0x80, 3, 0x09f4, 0, 0)
-#define _MX51_PAD_EIM_D25__USBOTG_DATA1 IOMUX_PAD(0x414, 0x80, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__EIM_D26 IOMUX_PAD(0x418, 0x84, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__KEY_COL7 IOMUX_PAD(0x418, 0x84, 1, 0x09cc, 0, 0)
-#define _MX51_PAD_EIM_D26__UART2_RTS IOMUX_PAD(0x418, 0x84, 4, 0x09e8, 3, 0)
-#define _MX51_PAD_EIM_D26__UART3_TXD IOMUX_PAD(0x418, 0x84, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__USBOTG_DATA2 IOMUX_PAD(0x418, 0x84, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__AUD6_RXC IOMUX_PAD(0x41c, 0x88, 5, 0x08f4, 0, 0)
-#define _MX51_PAD_EIM_D27__EIM_D27 IOMUX_PAD(0x41c, 0x88, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__GPIO2_9 IOMUX_PAD(0x41c, 0x88, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__I2C2_SCL IOMUX_PAD(0x41c, 0x88, 0x14, 0x09b8, 0, 0)
-#define _MX51_PAD_EIM_D27__UART3_RTS IOMUX_PAD(0x41c, 0x88, 3, 0x09f0, 3, 0)
-#define _MX51_PAD_EIM_D27__USBOTG_DATA3 IOMUX_PAD(0x41c, 0x88, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D28__AUD6_TXD IOMUX_PAD(0x420, 0x8c, 5, 0x08f0, 0, 0)
-#define _MX51_PAD_EIM_D28__EIM_D28 IOMUX_PAD(0x420, 0x8c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D28__KEY_ROW4 IOMUX_PAD(0x420, 0x8c, 1, 0x09d0, 0, 0)
-#define _MX51_PAD_EIM_D28__USBOTG_DATA4 IOMUX_PAD(0x420, 0x8c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D29__AUD6_RXD IOMUX_PAD(0x424, 0x90, 5, 0x08ec, 0, 0)
-#define _MX51_PAD_EIM_D29__EIM_D29 IOMUX_PAD(0x424, 0x90, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D29__KEY_ROW5 IOMUX_PAD(0x424, 0x90, 1, 0x09d4, 0, 0)
-#define _MX51_PAD_EIM_D29__USBOTG_DATA5 IOMUX_PAD(0x424, 0x90, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D30__AUD6_TXC IOMUX_PAD(0x428, 0x94, 5, 0x08fc, 0, 0)
-#define _MX51_PAD_EIM_D30__EIM_D30 IOMUX_PAD(0x428, 0x94, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D30__KEY_ROW6 IOMUX_PAD(0x428, 0x94, 1, 0x09d8, 0, 0)
-#define _MX51_PAD_EIM_D30__USBOTG_DATA6 IOMUX_PAD(0x428, 0x94, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D31__AUD6_TXFS IOMUX_PAD(0x42c, 0x98, 5, 0x0900, 0, 0)
-#define _MX51_PAD_EIM_D31__EIM_D31 IOMUX_PAD(0x42c, 0x98, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D31__KEY_ROW7 IOMUX_PAD(0x42c, 0x98, 1, 0x09dc, 0, 0)
-#define _MX51_PAD_EIM_D31__USBOTG_DATA7 IOMUX_PAD(0x42c, 0x98, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__EIM_A16 IOMUX_PAD(0x430, 0x9c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__GPIO2_10 IOMUX_PAD(0x430, 0x9c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__OSC_FREQ_SEL0 IOMUX_PAD(0x430, 0x9c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__EIM_A17 IOMUX_PAD(0x434, 0xa0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__GPIO2_11 IOMUX_PAD(0x434, 0xa0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__OSC_FREQ_SEL1 IOMUX_PAD(0x434, 0xa0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__BOOT_LPB0 IOMUX_PAD(0x438, 0xa4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__EIM_A18 IOMUX_PAD(0x438, 0xa4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__GPIO2_12 IOMUX_PAD(0x438, 0xa4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__BOOT_LPB1 IOMUX_PAD(0x43c, 0xa8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__EIM_A19 IOMUX_PAD(0x43c, 0xa8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__GPIO2_13 IOMUX_PAD(0x43c, 0xa8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__BOOT_UART_SRC0 IOMUX_PAD(0x440, 0xac, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__EIM_A20 IOMUX_PAD(0x440, 0xac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__GPIO2_14 IOMUX_PAD(0x440, 0xac, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__BOOT_UART_SRC1 IOMUX_PAD(0x444, 0xb0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__EIM_A21 IOMUX_PAD(0x444, 0xb0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__GPIO2_15 IOMUX_PAD(0x444, 0xb0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A22__EIM_A22 IOMUX_PAD(0x448, 0xb4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A22__GPIO2_16 IOMUX_PAD(0x448, 0xb4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__BOOT_HPN_EN IOMUX_PAD(0x44c, 0xb8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__EIM_A23 IOMUX_PAD(0x44c, 0xb8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__GPIO2_17 IOMUX_PAD(0x44c, 0xb8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__EIM_A24 IOMUX_PAD(0x450, 0xbc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__GPIO2_18 IOMUX_PAD(0x450, 0xbc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__USBH2_CLK IOMUX_PAD(0x450, 0xbc, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__DISP1_PIN4 IOMUX_PAD(0x454, 0xc0, 6, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__EIM_A25 IOMUX_PAD(0x454, 0xc0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__GPIO2_19 IOMUX_PAD(0x454, 0xc0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__USBH2_DIR IOMUX_PAD(0x454, 0xc0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__CSI1_DATA_EN IOMUX_PAD(0x458, 0xc4, 5, 0x09a0, 0, 0)
-#define _MX51_PAD_EIM_A26__DISP2_EXT_CLK IOMUX_PAD(0x458, 0xc4, 6, 0x0908, 0, 0)
-#define _MX51_PAD_EIM_A26__EIM_A26 IOMUX_PAD(0x458, 0xc4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__GPIO2_20 IOMUX_PAD(0x458, 0xc4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__USBH2_STP IOMUX_PAD(0x458, 0xc4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__CSI2_DATA_EN IOMUX_PAD(0x45c, 0xc8, 5, 0x099c, 0, 0)
-#define _MX51_PAD_EIM_A27__DISP1_PIN1 IOMUX_PAD(0x45c, 0xc8, 6, 0x09a4, 0, 0)
-#define _MX51_PAD_EIM_A27__EIM_A27 IOMUX_PAD(0x45c, 0xc8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__GPIO2_21 IOMUX_PAD(0x45c, 0xc8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__USBH2_NXT IOMUX_PAD(0x45c, 0xc8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB0__EIM_EB0 IOMUX_PAD(0x460, 0xcc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB1__EIM_EB1 IOMUX_PAD(0x464, 0xd0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__AUD5_RXFS IOMUX_PAD(0x468, 0xd4, 6, 0x08e0, 0, 0)
-#define _MX51_PAD_EIM_EB2__CSI1_D2 IOMUX_PAD(0x468, 0xd4, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__EIM_EB2 IOMUX_PAD(0x468, 0xd4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__FEC_MDIO IOMUX_PAD(0x468, 0xd4, 3, 0x0954, 0, 0)
-#define _MX51_PAD_EIM_EB2__GPIO2_22 IOMUX_PAD(0x468, 0xd4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__GPT_CMPOUT1 IOMUX_PAD(0x468, 0xd4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__AUD5_RXC IOMUX_PAD(0x46c, 0xd8, 6, 0x08dc, 0, 0)
-#define _MX51_PAD_EIM_EB3__CSI1_D3 IOMUX_PAD(0x46c, 0xd8, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__EIM_EB3 IOMUX_PAD(0x46c, 0xd8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__FEC_RDATA1 IOMUX_PAD(0x46c, 0xd8, 3, 0x095c, 0, 0)
-#define _MX51_PAD_EIM_EB3__GPIO2_23 IOMUX_PAD(0x46c, 0xd8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__GPT_CMPOUT2 IOMUX_PAD(0x46c, 0xd8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_OE__EIM_OE IOMUX_PAD(0x470, 0xdc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_OE__GPIO2_24 IOMUX_PAD(0x470, 0xdc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS0__EIM_CS0 IOMUX_PAD(0x474, 0xe0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS0__GPIO2_25 IOMUX_PAD(0x474, 0xe0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS1__EIM_CS1 IOMUX_PAD(0x478, 0xe4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS1__GPIO2_26 IOMUX_PAD(0x478, 0xe4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__AUD5_TXD IOMUX_PAD(0x47c, 0xe8, 6, 0x08d8, 1, 0)
-#define _MX51_PAD_EIM_CS2__CSI1_D4 IOMUX_PAD(0x47c, 0xe8, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__EIM_CS2 IOMUX_PAD(0x47c, 0xe8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__FEC_RDATA2 IOMUX_PAD(0x47c, 0xe8, 3, 0x0960, 0, 0)
-#define _MX51_PAD_EIM_CS2__GPIO2_27 IOMUX_PAD(0x47c, 0xe8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__USBOTG_STP IOMUX_PAD(0x47c, 0xe8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__AUD5_RXD IOMUX_PAD(0x480, 0xec, 6, 0x08d4, 1, 0)
-#define _MX51_PAD_EIM_CS3__CSI1_D5 IOMUX_PAD(0x480, 0xec, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__EIM_CS3 IOMUX_PAD(0x480, 0xec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__FEC_RDATA3 IOMUX_PAD(0x480, 0xec, 3, 0x0964, 0, 0)
-#define _MX51_PAD_EIM_CS3__GPIO2_28 IOMUX_PAD(0x480, 0xec, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__USBOTG_NXT IOMUX_PAD(0x480, 0xec, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__AUD5_TXC IOMUX_PAD(0x484, 0xf0, 6, 0x08e4, 1, 0)
-#define _MX51_PAD_EIM_CS4__CSI1_D6 IOMUX_PAD(0x484, 0xf0, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__EIM_CS4 IOMUX_PAD(0x484, 0xf0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__FEC_RX_ER IOMUX_PAD(0x484, 0xf0, 3, 0x0970, 0, 0)
-#define _MX51_PAD_EIM_CS4__GPIO2_29 IOMUX_PAD(0x484, 0xf0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__USBOTG_CLK IOMUX_PAD(0x484, 0xf0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__AUD5_TXFS IOMUX_PAD(0x488, 0xf4, 6, 0x08e8, 1, 0)
-#define _MX51_PAD_EIM_CS5__CSI1_D7 IOMUX_PAD(0x488, 0xf4, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__DISP1_EXT_CLK IOMUX_PAD(0x488, 0xf4, 4, 0x0904, 0, 0)
-#define _MX51_PAD_EIM_CS5__EIM_CS5 IOMUX_PAD(0x488, 0xf4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__FEC_CRS IOMUX_PAD(0x488, 0xf4, 3, 0x0950, 0, 0)
-#define _MX51_PAD_EIM_CS5__GPIO2_30 IOMUX_PAD(0x488, 0xf4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__USBOTG_DIR IOMUX_PAD(0x488, 0xf4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DTACK__EIM_DTACK IOMUX_PAD(0x48c, 0xf8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DTACK__GPIO2_31 IOMUX_PAD(0x48c, 0xf8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_LBA__EIM_LBA IOMUX_PAD(0x494, 0xfc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_LBA__GPIO3_1 IOMUX_PAD(0x494, 0xfc, 1, 0x0978, 0, 0)
-#define _MX51_PAD_EIM_CRE__EIM_CRE IOMUX_PAD(0x4a0, 0x100, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CRE__GPIO3_2 IOMUX_PAD(0x4a0, 0x100, 1, 0x097c, 0, 0)
-#define _MX51_PAD_DRAM_CS1__DRAM_CS1 IOMUX_PAD(0x4d0, 0x104, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__GPIO3_3 IOMUX_PAD(0x4e4, 0x108, 3, 0x0980, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__NANDF_WE_B IOMUX_PAD(0x4e4, 0x108, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__PATA_DIOW IOMUX_PAD(0x4e4, 0x108, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__SD3_DATA0 IOMUX_PAD(0x4e4, 0x108, 2, 0x093c, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__GPIO3_4 IOMUX_PAD(0x4e8, 0x10c, 3, 0x0984, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__NANDF_RE_B IOMUX_PAD(0x4e8, 0x10c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__PATA_DIOR IOMUX_PAD(0x4e8, 0x10c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__SD3_DATA1 IOMUX_PAD(0x4e8, 0x10c, 2, 0x0940, 0, 0)
-#define _MX51_PAD_NANDF_ALE__GPIO3_5 IOMUX_PAD(0x4ec, 0x110, 3, 0x0988, 0, 0)
-#define _MX51_PAD_NANDF_ALE__NANDF_ALE IOMUX_PAD(0x4ec, 0x110, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_ALE__PATA_BUFFER_EN IOMUX_PAD(0x4ec, 0x110, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CLE__GPIO3_6 IOMUX_PAD(0x4f0, 0x114, 3, 0x098c, 0, 0)
-#define _MX51_PAD_NANDF_CLE__NANDF_CLE IOMUX_PAD(0x4f0, 0x114, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CLE__PATA_RESET_B IOMUX_PAD(0x4f0, 0x114, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__GPIO3_7 IOMUX_PAD(0x4f4, 0x118, 3, 0x0990, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__NANDF_WP_B IOMUX_PAD(0x4f4, 0x118, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__PATA_DMACK IOMUX_PAD(0x4f4, 0x118, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__SD3_DATA2 IOMUX_PAD(0x4f4, 0x118, 2, 0x0944, 0, 0)
-#define _MX51_PAD_NANDF_RB0__ECSPI2_SS1 IOMUX_PAD(0x4f8, 0x11c, 5, 0x0930, 0, 0)
-#define _MX51_PAD_NANDF_RB0__GPIO3_8 IOMUX_PAD(0x4f8, 0x11c, 3, 0x0994, 0, 0)
-#define _MX51_PAD_NANDF_RB0__NANDF_RB0 IOMUX_PAD(0x4f8, 0x11c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB0__PATA_DMARQ IOMUX_PAD(0x4f8, 0x11c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB0__SD3_DATA3 IOMUX_PAD(0x4f8, 0x11c, 2, 0x0948, 0, 0)
-#define _MX51_PAD_NANDF_RB1__CSPI_MOSI IOMUX_PAD(0x4fc, 0x120, 6, 0x091c, 0, 0)
-#define _MX51_PAD_NANDF_RB1__ECSPI2_RDY IOMUX_PAD(0x4fc, 0x120, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__GPIO3_9 IOMUX_PAD(0x4fc, 0x120, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__NANDF_RB1 IOMUX_PAD(0x4fc, 0x120, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__PATA_IORDY IOMUX_PAD(0x4fc, 0x120, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__SD4_CMD IOMUX_PAD(0x4fc, 0x120, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__DISP2_WAIT IOMUX_PAD(0x500, 0x124, 5, 0x09a8, 0, 0)
-#define _MX51_PAD_NANDF_RB2__ECSPI2_SCLK IOMUX_PAD(0x500, 0x124, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__FEC_COL IOMUX_PAD(0x500, 0x124, 1, 0x094c, 0, 0)
-#define _MX51_PAD_NANDF_RB2__GPIO3_10 IOMUX_PAD(0x500, 0x124, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__NANDF_RB2 IOMUX_PAD(0x500, 0x124, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__USBH3_H3_DP IOMUX_PAD(0x500, 0x124, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__USBH3_NXT IOMUX_PAD(0x500, 0x124, 6, 0x0a20, 0, 0)
-#define _MX51_PAD_NANDF_RB3__DISP1_WAIT IOMUX_PAD(0x504, 0x128, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__ECSPI2_MISO IOMUX_PAD(0x504, 0x128, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__FEC_RX_CLK IOMUX_PAD(0x504, 0x128, 1, 0x0968, 0, 0)
-#define _MX51_PAD_NANDF_RB3__GPIO3_11 IOMUX_PAD(0x504, 0x128, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__NANDF_RB3 IOMUX_PAD(0x504, 0x128, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__USBH3_CLK IOMUX_PAD(0x504, 0x128, 6, 0x09f8, 0, 0)
-#define _MX51_PAD_NANDF_RB3__USBH3_H3_DM IOMUX_PAD(0x504, 0x128, 7, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO_NAND__GPIO_NAND IOMUX_PAD(0x514, 0x12c, 0, 0x0998, 0, 0)
-#define _MX51_PAD_GPIO_NAND__PATA_INTRQ IOMUX_PAD(0x514, 0x12c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS0__GPIO3_16 IOMUX_PAD(0x518, 0x130, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS0__NANDF_CS0 IOMUX_PAD(0x518, 0x130, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS1__GPIO3_17 IOMUX_PAD(0x51c, 0x134, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS1__NANDF_CS1 IOMUX_PAD(0x51c, 0x134, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__CSPI_SCLK IOMUX_PAD(0x520, 0x138, 6, 0x0914, 0, 0)
-#define _MX51_PAD_NANDF_CS2__FEC_TX_ER IOMUX_PAD(0x520, 0x138, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__GPIO3_18 IOMUX_PAD(0x520, 0x138, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__NANDF_CS2 IOMUX_PAD(0x520, 0x138, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__PATA_CS_0 IOMUX_PAD(0x520, 0x138, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__SD4_CLK IOMUX_PAD(0x520, 0x138, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__USBH3_H1_DP IOMUX_PAD(0x520, 0x138, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__FEC_MDC IOMUX_PAD(0x524, 0x13c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__GPIO3_19 IOMUX_PAD(0x524, 0x13c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__NANDF_CS3 IOMUX_PAD(0x524, 0x13c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__PATA_CS_1 IOMUX_PAD(0x524, 0x13c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__SD4_DAT0 IOMUX_PAD(0x524, 0x13c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__USBH3_H1_DM IOMUX_PAD(0x524, 0x13c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__FEC_TDATA1 IOMUX_PAD(0x528, 0x140, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__GPIO3_20 IOMUX_PAD(0x528, 0x140, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__NANDF_CS4 IOMUX_PAD(0x528, 0x140, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__PATA_DA_0 IOMUX_PAD(0x528, 0x140, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__SD4_DAT1 IOMUX_PAD(0x528, 0x140, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__USBH3_STP IOMUX_PAD(0x528, 0x140, 7, 0x0a24, 0, 0)
-#define _MX51_PAD_NANDF_CS5__FEC_TDATA2 IOMUX_PAD(0x52c, 0x144, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__GPIO3_21 IOMUX_PAD(0x52c, 0x144, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__NANDF_CS5 IOMUX_PAD(0x52c, 0x144, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__PATA_DA_1 IOMUX_PAD(0x52c, 0x144, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__SD4_DAT2 IOMUX_PAD(0x52c, 0x144, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__USBH3_DIR IOMUX_PAD(0x52c, 0x144, 7, 0x0a1c, 0, 0)
-#define _MX51_PAD_NANDF_CS6__CSPI_SS3 IOMUX_PAD(0x530, 0x148, 7, 0x0928, 0, 0)
-#define _MX51_PAD_NANDF_CS6__FEC_TDATA3 IOMUX_PAD(0x530, 0x148, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__GPIO3_22 IOMUX_PAD(0x530, 0x148, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__NANDF_CS6 IOMUX_PAD(0x530, 0x148, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__PATA_DA_2 IOMUX_PAD(0x530, 0x148, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__SD4_DAT3 IOMUX_PAD(0x530, 0x148, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__FEC_TX_EN IOMUX_PAD(0x534, 0x14c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__GPIO3_23 IOMUX_PAD(0x534, 0x14c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__NANDF_CS7 IOMUX_PAD(0x534, 0x14c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__SD3_CLK IOMUX_PAD(0x534, 0x14c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 IOMUX_PAD(0x538, 0x150, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK IOMUX_PAD(0x538, 0x150, 1, 0x0974, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__GPIO3_24 IOMUX_PAD(0x538, 0x150, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT IOMUX_PAD(0x538, 0x150, 0, 0x0938, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__SD3_CMD IOMUX_PAD(0x538, 0x150, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__ECSPI2_MOSI IOMUX_PAD(0x53c, 0x154, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__GPIO3_25 IOMUX_PAD(0x53c, 0x154, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__NANDF_D15 IOMUX_PAD(0x53c, 0x154, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__PATA_DATA15 IOMUX_PAD(0x53c, 0x154, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__SD3_DAT7 IOMUX_PAD(0x53c, 0x154, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__ECSPI2_SS3 IOMUX_PAD(0x540, 0x158, 2, 0x0934, 0, 0)
-#define _MX51_PAD_NANDF_D14__GPIO3_26 IOMUX_PAD(0x540, 0x158, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__NANDF_D14 IOMUX_PAD(0x540, 0x158, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__PATA_DATA14 IOMUX_PAD(0x540, 0x158, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__SD3_DAT6 IOMUX_PAD(0x540, 0x158, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__ECSPI2_SS2 IOMUX_PAD(0x544, 0x15c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__GPIO3_27 IOMUX_PAD(0x544, 0x15c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__NANDF_D13 IOMUX_PAD(0x544, 0x15c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__PATA_DATA13 IOMUX_PAD(0x544, 0x15c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__SD3_DAT5 IOMUX_PAD(0x544, 0x15c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__ECSPI2_SS1 IOMUX_PAD(0x548, 0x160, 2, 0x0930, 1, 0)
-#define _MX51_PAD_NANDF_D12__GPIO3_28 IOMUX_PAD(0x548, 0x160, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__NANDF_D12 IOMUX_PAD(0x548, 0x160, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__PATA_DATA12 IOMUX_PAD(0x548, 0x160, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__SD3_DAT4 IOMUX_PAD(0x548, 0x160, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__FEC_RX_DV IOMUX_PAD(0x54c, 0x164, 2, 0x096c, 0, 0)
-#define _MX51_PAD_NANDF_D11__GPIO3_29 IOMUX_PAD(0x54c, 0x164, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__NANDF_D11 IOMUX_PAD(0x54c, 0x164, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__PATA_DATA11 IOMUX_PAD(0x54c, 0x164, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__SD3_DATA3 IOMUX_PAD(0x54c, 0x164, 5, 0x0948, 1, 0)
-#define _MX51_PAD_NANDF_D10__GPIO3_30 IOMUX_PAD(0x550, 0x168, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__NANDF_D10 IOMUX_PAD(0x550, 0x168, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__PATA_DATA10 IOMUX_PAD(0x550, 0x168, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__SD3_DATA2 IOMUX_PAD(0x550, 0x168, 5, 0x0944, 1, 0)
-#define _MX51_PAD_NANDF_D9__FEC_RDATA0 IOMUX_PAD(0x554, 0x16c, 0x12, 0x0958, 0, 0)
-#define _MX51_PAD_NANDF_D9__GPIO3_31 IOMUX_PAD(0x554, 0x16c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__NANDF_D9 IOMUX_PAD(0x554, 0x16c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__PATA_DATA9 IOMUX_PAD(0x554, 0x16c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__SD3_DATA1 IOMUX_PAD(0x554, 0x16c, 5, 0x0940, 1, 0)
-#define _MX51_PAD_NANDF_D8__FEC_TDATA0 IOMUX_PAD(0x558, 0x170, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__GPIO4_0 IOMUX_PAD(0x558, 0x170, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__NANDF_D8 IOMUX_PAD(0x558, 0x170, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__PATA_DATA8 IOMUX_PAD(0x558, 0x170, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__SD3_DATA0 IOMUX_PAD(0x558, 0x170, 5, 0x093c, 1, 0)
-#define _MX51_PAD_NANDF_D7__GPIO4_1 IOMUX_PAD(0x55c, 0x174, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__NANDF_D7 IOMUX_PAD(0x55c, 0x174, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__PATA_DATA7 IOMUX_PAD(0x55c, 0x174, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__USBH3_DATA0 IOMUX_PAD(0x55c, 0x174, 5, 0x09fc, 0, 0)
-#define _MX51_PAD_NANDF_D6__GPIO4_2 IOMUX_PAD(0x560, 0x178, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__NANDF_D6 IOMUX_PAD(0x560, 0x178, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__PATA_DATA6 IOMUX_PAD(0x560, 0x178, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__SD4_LCTL IOMUX_PAD(0x560, 0x178, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__USBH3_DATA1 IOMUX_PAD(0x560, 0x178, 5, 0x0a00, 0, 0)
-#define _MX51_PAD_NANDF_D5__GPIO4_3 IOMUX_PAD(0x564, 0x17c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__NANDF_D5 IOMUX_PAD(0x564, 0x17c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__PATA_DATA5 IOMUX_PAD(0x564, 0x17c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__SD4_WP IOMUX_PAD(0x564, 0x17c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__USBH3_DATA2 IOMUX_PAD(0x564, 0x17c, 5, 0x0a04, 0, 0)
-#define _MX51_PAD_NANDF_D4__GPIO4_4 IOMUX_PAD(0x568, 0x180, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__NANDF_D4 IOMUX_PAD(0x568, 0x180, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__PATA_DATA4 IOMUX_PAD(0x568, 0x180, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__SD4_CD IOMUX_PAD(0x568, 0x180, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__USBH3_DATA3 IOMUX_PAD(0x568, 0x180, 5, 0x0a08, 0, 0)
-#define _MX51_PAD_NANDF_D3__GPIO4_5 IOMUX_PAD(0x56c, 0x184, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__NANDF_D3 IOMUX_PAD(0x56c, 0x184, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__PATA_DATA3 IOMUX_PAD(0x56c, 0x184, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__SD4_DAT4 IOMUX_PAD(0x56c, 0x184, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__USBH3_DATA4 IOMUX_PAD(0x56c, 0x184, 5, 0x0a0c, 0, 0)
-#define _MX51_PAD_NANDF_D2__GPIO4_6 IOMUX_PAD(0x570, 0x188, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__NANDF_D2 IOMUX_PAD(0x570, 0x188, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__PATA_DATA2 IOMUX_PAD(0x570, 0x188, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__SD4_DAT5 IOMUX_PAD(0x570, 0x188, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__USBH3_DATA5 IOMUX_PAD(0x570, 0x188, 5, 0x0a10, 0, 0)
-#define _MX51_PAD_NANDF_D1__GPIO4_7 IOMUX_PAD(0x574, 0x18c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__NANDF_D1 IOMUX_PAD(0x574, 0x18c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__PATA_DATA1 IOMUX_PAD(0x574, 0x18c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__SD4_DAT6 IOMUX_PAD(0x574, 0x18c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__USBH3_DATA6 IOMUX_PAD(0x574, 0x18c, 5, 0x0a14, 0, 0)
-#define _MX51_PAD_NANDF_D0__GPIO4_8 IOMUX_PAD(0x578, 0x190, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__NANDF_D0 IOMUX_PAD(0x578, 0x190, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__PATA_DATA0 IOMUX_PAD(0x578, 0x190, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__SD4_DAT7 IOMUX_PAD(0x578, 0x190, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__USBH3_DATA7 IOMUX_PAD(0x578, 0x190, 5, 0x0a18, 0, 0)
-#define _MX51_PAD_CSI1_D8__CSI1_D8 IOMUX_PAD(0x57c, 0x194, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D8__GPIO3_12 IOMUX_PAD(0x57c, 0x194, 3, 0x0998, 1, 0)
-#define _MX51_PAD_CSI1_D9__CSI1_D9 IOMUX_PAD(0x580, 0x198, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D9__GPIO3_13 IOMUX_PAD(0x580, 0x198, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D10__CSI1_D10 IOMUX_PAD(0x584, 0x19c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D11__CSI1_D11 IOMUX_PAD(0x588, 0x1a0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D12__CSI1_D12 IOMUX_PAD(0x58c, 0x1a4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D13__CSI1_D13 IOMUX_PAD(0x590, 0x1a8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D14__CSI1_D14 IOMUX_PAD(0x594, 0x1ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D15__CSI1_D15 IOMUX_PAD(0x598, 0x1b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D16__CSI1_D16 IOMUX_PAD(0x59c, 0x1b4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D17__CSI1_D17 IOMUX_PAD(0x5a0, 0x1b8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D18__CSI1_D18 IOMUX_PAD(0x5a4, 0x1bc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D19__CSI1_D19 IOMUX_PAD(0x5a8, 0x1c0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_VSYNC__CSI1_VSYNC IOMUX_PAD(0x5ac, 0x1c4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_VSYNC__GPIO3_14 IOMUX_PAD(0x5ac, 0x1c4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_HSYNC__CSI1_HSYNC IOMUX_PAD(0x5b0, 0x1c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_HSYNC__GPIO3_15 IOMUX_PAD(0x5b0, 0x1c8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK IOMUX_PAD(0x5b4, 0x000, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_MCLK__CSI1_MCLK IOMUX_PAD(0x5b8, 0x000, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D12__CSI2_D12 IOMUX_PAD(0x5bc, 0x1cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D12__GPIO4_9 IOMUX_PAD(0x5bc, 0x1cc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D13__CSI2_D13 IOMUX_PAD(0x5c0, 0x1d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D13__GPIO4_10 IOMUX_PAD(0x5c0, 0x1d0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D14__CSI2_D14 IOMUX_PAD(0x5c4, 0x1d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D15__CSI2_D15 IOMUX_PAD(0x5c8, 0x1d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D16__CSI2_D16 IOMUX_PAD(0x5cc, 0x1dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D17__CSI2_D17 IOMUX_PAD(0x5d0, 0x1e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D18__CSI2_D18 IOMUX_PAD(0x5d4, 0x1e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D18__GPIO4_11 IOMUX_PAD(0x5d4, 0x1e4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D19__CSI2_D19 IOMUX_PAD(0x5d8, 0x1e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D19__GPIO4_12 IOMUX_PAD(0x5d8, 0x1e8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_VSYNC__CSI2_VSYNC IOMUX_PAD(0x5dc, 0x1ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_VSYNC__GPIO4_13 IOMUX_PAD(0x5dc, 0x1ec, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_HSYNC__CSI2_HSYNC IOMUX_PAD(0x5e0, 0x1f0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_HSYNC__GPIO4_14 IOMUX_PAD(0x5e0, 0x1f0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK IOMUX_PAD(0x5e4, 0x1f4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_PIXCLK__GPIO4_15 IOMUX_PAD(0x5e4, 0x1f4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_CLK__GPIO4_16 IOMUX_PAD(0x5e8, 0x1f8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_CLK__I2C1_CLK IOMUX_PAD(0x5e8, 0x1f8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_DAT__GPIO4_17 IOMUX_PAD(0x5ec, 0x1fc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_DAT__I2C1_DAT IOMUX_PAD(0x5ec, 0x1fc, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_TXD__AUD3_TXD IOMUX_PAD(0x5f0, 0x200, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_TXD__GPIO4_18 IOMUX_PAD(0x5f0, 0x200, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__AUD3_RXD IOMUX_PAD(0x5f4, 0x204, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__GPIO4_19 IOMUX_PAD(0x5f4, 0x204, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__UART3_RXD IOMUX_PAD(0x5f4, 0x204, 1, 0x09f4, 2, 0)
-#define _MX51_PAD_AUD3_BB_CK__AUD3_TXC IOMUX_PAD(0x5f8, 0x208, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_CK__GPIO4_20 IOMUX_PAD(0x5f8, 0x208, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__AUD3_TXFS IOMUX_PAD(0x5fc, 0x20c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__GPIO4_21 IOMUX_PAD(0x5fc, 0x20c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__UART3_TXD IOMUX_PAD(0x5fc, 0x20c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI IOMUX_PAD(0x600, 0x210, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__GPIO4_22 IOMUX_PAD(0x600, 0x210, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__I2C1_SDA IOMUX_PAD(0x600, 0x210, 0x11, 0x09b4, 1, 0)
-#define _MX51_PAD_CSPI1_MISO__AUD4_RXD IOMUX_PAD(0x604, 0x214, 1, 0x08c4, 1, 0)
-#define _MX51_PAD_CSPI1_MISO__ECSPI1_MISO IOMUX_PAD(0x604, 0x214, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MISO__GPIO4_23 IOMUX_PAD(0x604, 0x214, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS0__AUD4_TXC IOMUX_PAD(0x608, 0x218, 1, 0x08cc, 1, 0)
-#define _MX51_PAD_CSPI1_SS0__ECSPI1_SS0 IOMUX_PAD(0x608, 0x218, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS0__GPIO4_24 IOMUX_PAD(0x608, 0x218, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS1__AUD4_TXD IOMUX_PAD(0x60c, 0x21c, 1, 0x08c8, 1, 0)
-#define _MX51_PAD_CSPI1_SS1__ECSPI1_SS1 IOMUX_PAD(0x60c, 0x21c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS1__GPIO4_25 IOMUX_PAD(0x60c, 0x21c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_RDY__AUD4_TXFS IOMUX_PAD(0x610, 0x220, 1, 0x08d0, 1, 0)
-#define _MX51_PAD_CSPI1_RDY__ECSPI1_RDY IOMUX_PAD(0x610, 0x220, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_RDY__GPIO4_26 IOMUX_PAD(0x610, 0x220, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK IOMUX_PAD(0x614, 0x224, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__GPIO4_27 IOMUX_PAD(0x614, 0x224, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__I2C1_SCL IOMUX_PAD(0x614, 0x224, 0x11, 0x09b0, 1, 0)
-#define _MX51_PAD_UART1_RXD__GPIO4_28 IOMUX_PAD(0x618, 0x228, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RXD__UART1_RXD IOMUX_PAD(0x618, 0x228, 0, 0x09e4, 0, 0)
-#define _MX51_PAD_UART1_TXD__GPIO4_29 IOMUX_PAD(0x61c, 0x22c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_TXD__PWM2_PWMO IOMUX_PAD(0x61c, 0x22c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_TXD__UART1_TXD IOMUX_PAD(0x61c, 0x22c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RTS__GPIO4_30 IOMUX_PAD(0x620, 0x230, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RTS__UART1_RTS IOMUX_PAD(0x620, 0x230, 0, 0x09e0, 0, 0)
-#define _MX51_PAD_UART1_CTS__GPIO4_31 IOMUX_PAD(0x624, 0x234, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_CTS__UART1_CTS IOMUX_PAD(0x624, 0x234, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__FIRI_TXD IOMUX_PAD(0x628, 0x238, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__GPIO1_20 IOMUX_PAD(0x628, 0x238, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__UART2_RXD IOMUX_PAD(0x628, 0x238, 0, 0x09ec, 2, 0)
-#define _MX51_PAD_UART2_TXD__FIRI_RXD IOMUX_PAD(0x62c, 0x23c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_TXD__GPIO1_21 IOMUX_PAD(0x62c, 0x23c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_TXD__UART2_TXD IOMUX_PAD(0x62c, 0x23c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__CSI1_D0 IOMUX_PAD(0x630, 0x240, 2, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__GPIO1_22 IOMUX_PAD(0x630, 0x240, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__UART1_DTR IOMUX_PAD(0x630, 0x240, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__UART3_RXD IOMUX_PAD(0x630, 0x240, 1, 0x09f4, 4, 0)
-#define _MX51_PAD_UART3_TXD__CSI1_D1 IOMUX_PAD(0x634, 0x244, 2, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__GPIO1_23 IOMUX_PAD(0x634, 0x244, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__UART1_DSR IOMUX_PAD(0x634, 0x244, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__UART3_TXD IOMUX_PAD(0x634, 0x244, 1, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__GPIO1_24 IOMUX_PAD(0x638, 0x248, 3, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__OWIRE_LINE IOMUX_PAD(0x638, 0x248, 0, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__SPDIF_OUT IOMUX_PAD(0x638, 0x248, 6, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW0__KEY_ROW0 IOMUX_PAD(0x63c, 0x24c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW1__KEY_ROW1 IOMUX_PAD(0x640, 0x250, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW2__KEY_ROW2 IOMUX_PAD(0x644, 0x254, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW3__KEY_ROW3 IOMUX_PAD(0x648, 0x258, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL0__KEY_COL0 IOMUX_PAD(0x64c, 0x25c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL0__PLL1_BYP IOMUX_PAD(0x64c, 0x25c, 7, 0x090c, 0, 0)
-#define _MX51_PAD_KEY_COL1__KEY_COL1 IOMUX_PAD(0x650, 0x260, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL1__PLL2_BYP IOMUX_PAD(0x650, 0x260, 7, 0x0910, 0, 0)
-#define _MX51_PAD_KEY_COL2__KEY_COL2 IOMUX_PAD(0x654, 0x264, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL2__PLL3_BYP IOMUX_PAD(0x654, 0x264, 7, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL3__KEY_COL3 IOMUX_PAD(0x658, 0x268, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__I2C2_SCL IOMUX_PAD(0x65c, 0x26c, 0x13, 0x09b8, 1, 0)
-#define _MX51_PAD_KEY_COL4__KEY_COL4 IOMUX_PAD(0x65c, 0x26c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__SPDIF_OUT1 IOMUX_PAD(0x65c, 0x26c, 6, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__UART1_RI IOMUX_PAD(0x65c, 0x26c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__UART3_RTS IOMUX_PAD(0x65c, 0x26c, 2, 0x09f0, 4, 0)
-#define _MX51_PAD_KEY_COL5__I2C2_SDA IOMUX_PAD(0x660, 0x270, 0x13, 0x09bc, 1, 0)
-#define _MX51_PAD_KEY_COL5__KEY_COL5 IOMUX_PAD(0x660, 0x270, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL5__UART1_DCD IOMUX_PAD(0x660, 0x270, 1, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL5__UART3_CTS IOMUX_PAD(0x660, 0x270, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_CLK__CSPI_SCLK IOMUX_PAD(0x678, 0x278, 1, 0x0914, 1, 0)
-#define _MX51_PAD_USBH1_CLK__GPIO1_25 IOMUX_PAD(0x678, 0x278, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_CLK__I2C2_SCL IOMUX_PAD(0x678, 0x278, 0x15, 0x09b8, 2, 0)
-#define _MX51_PAD_USBH1_CLK__USBH1_CLK IOMUX_PAD(0x678, 0x278, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DIR__CSPI_MOSI IOMUX_PAD(0x67c, 0x27c, 1, 0x091c, 1, 0)
-#define _MX51_PAD_USBH1_DIR__GPIO1_26 IOMUX_PAD(0x67c, 0x27c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DIR__I2C2_SDA IOMUX_PAD(0x67c, 0x27c, 0x15, 0x09bc, 2, 0)
-#define _MX51_PAD_USBH1_DIR__USBH1_DIR IOMUX_PAD(0x67c, 0x27c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__CSPI_RDY IOMUX_PAD(0x680, 0x280, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__GPIO1_27 IOMUX_PAD(0x680, 0x280, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__UART3_RXD IOMUX_PAD(0x680, 0x280, 5, 0x09f4, 6, 0)
-#define _MX51_PAD_USBH1_STP__USBH1_STP IOMUX_PAD(0x680, 0x280, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__CSPI_MISO IOMUX_PAD(0x684, 0x284, 1, 0x0918, 0, 0)
-#define _MX51_PAD_USBH1_NXT__GPIO1_28 IOMUX_PAD(0x684, 0x284, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__UART3_TXD IOMUX_PAD(0x684, 0x284, 5, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__USBH1_NXT IOMUX_PAD(0x684, 0x284, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__GPIO1_11 IOMUX_PAD(0x688, 0x288, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__UART2_CTS IOMUX_PAD(0x688, 0x288, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__USBH1_DATA0 IOMUX_PAD(0x688, 0x288, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA1__GPIO1_12 IOMUX_PAD(0x68c, 0x28c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA1__UART2_RXD IOMUX_PAD(0x68c, 0x28c, 1, 0x09ec, 4, 0)
-#define _MX51_PAD_USBH1_DATA1__USBH1_DATA1 IOMUX_PAD(0x68c, 0x28c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__GPIO1_13 IOMUX_PAD(0x690, 0x290, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__UART2_TXD IOMUX_PAD(0x690, 0x290, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__USBH1_DATA2 IOMUX_PAD(0x690, 0x290, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA3__GPIO1_14 IOMUX_PAD(0x694, 0x294, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA3__UART2_RTS IOMUX_PAD(0x694, 0x294, 1, 0x09e8, 5, 0)
-#define _MX51_PAD_USBH1_DATA3__USBH1_DATA3 IOMUX_PAD(0x694, 0x294, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__CSPI_SS0 IOMUX_PAD(0x698, 0x298, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__GPIO1_15 IOMUX_PAD(0x698, 0x298, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__USBH1_DATA4 IOMUX_PAD(0x698, 0x298, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__CSPI_SS1 IOMUX_PAD(0x69c, 0x29c, 1, 0x0920, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__GPIO1_16 IOMUX_PAD(0x69c, 0x29c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__USBH1_DATA5 IOMUX_PAD(0x69c, 0x29c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA6__CSPI_SS3 IOMUX_PAD(0x6a0, 0x2a0, 1, 0x0928, 1, 0)
-#define _MX51_PAD_USBH1_DATA6__GPIO1_17 IOMUX_PAD(0x6a0, 0x2a0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA6__USBH1_DATA6 IOMUX_PAD(0x6a0, 0x2a0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__ECSPI1_SS3 IOMUX_PAD(0x6a4, 0x2a4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__ECSPI2_SS3 IOMUX_PAD(0x6a4, 0x2a4, 5, 0x0934, 1, 0)
-#define _MX51_PAD_USBH1_DATA7__GPIO1_18 IOMUX_PAD(0x6a4, 0x2a4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__USBH1_DATA7 IOMUX_PAD(0x6a4, 0x2a4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__DI1_PIN11 IOMUX_PAD(0x6a8, 0x2a8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__ECSPI1_SS2 IOMUX_PAD(0x6a8, 0x2a8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__GPIO3_0 IOMUX_PAD(0x6a8, 0x2a8, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN12__DI1_PIN12 IOMUX_PAD(0x6ac, 0x2ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN12__GPIO3_1 IOMUX_PAD(0x6ac, 0x2ac, 4, 0x0978, 1, 0)
-#define _MX51_PAD_DI1_PIN13__DI1_PIN13 IOMUX_PAD(0x6b0, 0x2b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN13__GPIO3_2 IOMUX_PAD(0x6b0, 0x2b0, 4, 0x097c, 1, 0)
-#define _MX51_PAD_DI1_D0_CS__DI1_D0_CS IOMUX_PAD(0x6b4, 0x2b4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D0_CS__GPIO3_3 IOMUX_PAD(0x6b4, 0x2b4, 4, 0x0980, 1, 0)
-#define _MX51_PAD_DI1_D1_CS__DI1_D1_CS IOMUX_PAD(0x6b8, 0x2b8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__DISP1_PIN14 IOMUX_PAD(0x6b8, 0x2b8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__DISP1_PIN5 IOMUX_PAD(0x6b8, 0x2b8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__GPIO3_4 IOMUX_PAD(0x6b8, 0x2b8, 4, 0x0984, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 IOMUX_PAD(0x6bc, 0x2bc, 2, 0x09a4, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN IOMUX_PAD(0x6bc, 0x2bc, 0, 0x09c4, 0, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__GPIO3_5 IOMUX_PAD(0x6bc, 0x2bc, 4, 0x0988, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 IOMUX_PAD(0x6c0, 0x2c0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO IOMUX_PAD(0x6c0, 0x2c0, 0, 0x09c4, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__GPIO3_6 IOMUX_PAD(0x6c0, 0x2c0, 4, 0x098c, 1, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 IOMUX_PAD(0x6c4, 0x2c4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 IOMUX_PAD(0x6c4, 0x2c4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK IOMUX_PAD(0x6c4, 0x2c4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__GPIO3_7 IOMUX_PAD(0x6c4, 0x2c4, 4, 0x0990, 1, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK IOMUX_PAD(0x6c8, 0x2c8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 IOMUX_PAD(0x6c8, 0x2c8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 IOMUX_PAD(0x6c8, 0x2c8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS IOMUX_PAD(0x6c8, 0x2c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS IOMUX_PAD(0x6c8, 0x2c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__GPIO3_8 IOMUX_PAD(0x6c8, 0x2c8, 4, 0x0994, 1, 0)
-#define _MX51_PAD_DISP1_DAT0__DISP1_DAT0 IOMUX_PAD(0x6cc, 0x2cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT1__DISP1_DAT1 IOMUX_PAD(0x6d0, 0x2d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT2__DISP1_DAT2 IOMUX_PAD(0x6d4, 0x2d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT3__DISP1_DAT3 IOMUX_PAD(0x6d8, 0x2d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT4__DISP1_DAT4 IOMUX_PAD(0x6dc, 0x2dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT5__DISP1_DAT5 IOMUX_PAD(0x6e0, 0x2e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT6__BOOT_USB_SRC IOMUX_PAD(0x6e4, 0x2e4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT6__DISP1_DAT6 IOMUX_PAD(0x6e4, 0x2e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG IOMUX_PAD(0x6e8, 0x2e8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT7__DISP1_DAT7 IOMUX_PAD(0x6e8, 0x2e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT8__BOOT_SRC0 IOMUX_PAD(0x6ec, 0x2ec, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT8__DISP1_DAT8 IOMUX_PAD(0x6ec, 0x2ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT9__BOOT_SRC1 IOMUX_PAD(0x6f0, 0x2f0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT9__DISP1_DAT9 IOMUX_PAD(0x6f0, 0x2f0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE IOMUX_PAD(0x6f4, 0x2f4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT10__DISP1_DAT10 IOMUX_PAD(0x6f4, 0x2f4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 IOMUX_PAD(0x6f8, 0x2f8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT11__DISP1_DAT11 IOMUX_PAD(0x6f8, 0x2f8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL IOMUX_PAD(0x6fc, 0x2fc, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT12__DISP1_DAT12 IOMUX_PAD(0x6fc, 0x2fc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 IOMUX_PAD(0x700, 0x300, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT13__DISP1_DAT13 IOMUX_PAD(0x700, 0x300, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 IOMUX_PAD(0x704, 0x304, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT14__DISP1_DAT14 IOMUX_PAD(0x704, 0x304, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH IOMUX_PAD(0x708, 0x308, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT15__DISP1_DAT15 IOMUX_PAD(0x708, 0x308, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 IOMUX_PAD(0x70c, 0x30c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT16__DISP1_DAT16 IOMUX_PAD(0x70c, 0x30c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 IOMUX_PAD(0x710, 0x310, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT17__DISP1_DAT17 IOMUX_PAD(0x710, 0x310, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 IOMUX_PAD(0x714, 0x314, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP1_DAT18 IOMUX_PAD(0x714, 0x314, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP2_PIN11 IOMUX_PAD(0x714, 0x314, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP2_PIN5 IOMUX_PAD(0x714, 0x314, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 IOMUX_PAD(0x718, 0x318, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP1_DAT19 IOMUX_PAD(0x718, 0x318, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP2_PIN12 IOMUX_PAD(0x718, 0x318, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP2_PIN6 IOMUX_PAD(0x718, 0x318, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 IOMUX_PAD(0x71c, 0x31c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP1_DAT20 IOMUX_PAD(0x71c, 0x31c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP2_PIN13 IOMUX_PAD(0x71c, 0x31c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP2_PIN7 IOMUX_PAD(0x71c, 0x31c, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 IOMUX_PAD(0x720, 0x320, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP1_DAT21 IOMUX_PAD(0x720, 0x320, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP2_PIN14 IOMUX_PAD(0x720, 0x320, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP2_PIN8 IOMUX_PAD(0x720, 0x320, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 IOMUX_PAD(0x724, 0x324, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP1_DAT22 IOMUX_PAD(0x724, 0x324, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP2_D0_CS IOMUX_PAD(0x724, 0x324, 6, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP2_DAT16 IOMUX_PAD(0x724, 0x324, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 IOMUX_PAD(0x728, 0x328, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP1_DAT23 IOMUX_PAD(0x728, 0x328, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_D1_CS IOMUX_PAD(0x728, 0x328, 6, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_DAT17 IOMUX_PAD(0x728, 0x328, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_SER_CS IOMUX_PAD(0x728, 0x328, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN3__DI1_PIN3 IOMUX_PAD(0x72c, 0x32c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN2__DI1_PIN2 IOMUX_PAD(0x734, 0x330, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP2__DISP1_SER_CLK IOMUX_PAD(0x740, 0x338, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP2__DISP2_WAIT IOMUX_PAD(0x740, 0x338, 2, 0x09a8, 1, 0)
-#define _MX51_PAD_DI_GP3__CSI1_DATA_EN IOMUX_PAD(0x744, 0x33c, 3, 0x09a0, 1, 0)
-#define _MX51_PAD_DI_GP3__DISP1_SER_DIO IOMUX_PAD(0x744, 0x33c, 0, 0x09c0, 0, 0)
-#define _MX51_PAD_DI_GP3__FEC_TX_ER IOMUX_PAD(0x744, 0x33c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN4__CSI2_DATA_EN IOMUX_PAD(0x748, 0x340, 3, 0x099c, 1, 0)
-#define _MX51_PAD_DI2_PIN4__DI2_PIN4 IOMUX_PAD(0x748, 0x340, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN4__FEC_CRS IOMUX_PAD(0x748, 0x340, 2, 0x0950, 1, 0)
-#define _MX51_PAD_DI2_PIN2__DI2_PIN2 IOMUX_PAD(0x74c, 0x344, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN2__FEC_MDC IOMUX_PAD(0x74c, 0x344, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN3__DI2_PIN3 IOMUX_PAD(0x750, 0x348, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN3__FEC_MDIO IOMUX_PAD(0x750, 0x348, 2, 0x0954, 1, 0)
-#define _MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK IOMUX_PAD(0x754, 0x34c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 IOMUX_PAD(0x754, 0x34c, 2, 0x095c, 1, 0)
-#define _MX51_PAD_DI_GP4__DI2_PIN15 IOMUX_PAD(0x758, 0x350, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP4__DISP1_SER_DIN IOMUX_PAD(0x758, 0x350, 0, 0x09c0, 1, 0)
-#define _MX51_PAD_DI_GP4__DISP2_PIN1 IOMUX_PAD(0x758, 0x350, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP4__FEC_RDATA2 IOMUX_PAD(0x758, 0x350, 2, 0x0960, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__DISP2_DAT0 IOMUX_PAD(0x75c, 0x354, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT0__FEC_RDATA3 IOMUX_PAD(0x75c, 0x354, 2, 0x0964, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__KEY_COL6 IOMUX_PAD(0x75c, 0x354, 4, 0x09c8, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__UART3_RXD IOMUX_PAD(0x75c, 0x354, 5, 0x09f4, 8, 0)
-#define _MX51_PAD_DISP2_DAT0__USBH3_CLK IOMUX_PAD(0x75c, 0x354, 3, 0x09f8, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__DISP2_DAT1 IOMUX_PAD(0x760, 0x358, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT1__FEC_RX_ER IOMUX_PAD(0x760, 0x358, 2, 0x0970, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__KEY_COL7 IOMUX_PAD(0x760, 0x358, 4, 0x09cc, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__UART3_TXD IOMUX_PAD(0x760, 0x358, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT1__USBH3_DIR IOMUX_PAD(0x760, 0x358, 3, 0x0a1c, 1, 0)
-#define _MX51_PAD_DISP2_DAT2__DISP2_DAT2 IOMUX_PAD(0x764, 0x35c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT3__DISP2_DAT3 IOMUX_PAD(0x768, 0x360, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT4__DISP2_DAT4 IOMUX_PAD(0x76c, 0x364, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT5__DISP2_DAT5 IOMUX_PAD(0x770, 0x368, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__DISP2_DAT6 IOMUX_PAD(0x774, 0x36c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__FEC_TDATA1 IOMUX_PAD(0x774, 0x36c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__GPIO1_19 IOMUX_PAD(0x774, 0x36c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__KEY_ROW4 IOMUX_PAD(0x774, 0x36c, 4, 0x09d0, 1, 0)
-#define _MX51_PAD_DISP2_DAT6__USBH3_STP IOMUX_PAD(0x774, 0x36c, 3, 0x0a24, 1, 0)
-#define _MX51_PAD_DISP2_DAT7__DISP2_DAT7 IOMUX_PAD(0x778, 0x370, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__FEC_TDATA2 IOMUX_PAD(0x778, 0x370, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__GPIO1_29 IOMUX_PAD(0x778, 0x370, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__KEY_ROW5 IOMUX_PAD(0x778, 0x370, 4, 0x09d4, 1, 0)
-#define _MX51_PAD_DISP2_DAT7__USBH3_NXT IOMUX_PAD(0x778, 0x370, 3, 0x0a20, 1, 0)
-#define _MX51_PAD_DISP2_DAT8__DISP2_DAT8 IOMUX_PAD(0x77c, 0x374, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__FEC_TDATA3 IOMUX_PAD(0x77c, 0x374, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__GPIO1_30 IOMUX_PAD(0x77c, 0x374, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__KEY_ROW6 IOMUX_PAD(0x77c, 0x374, 4, 0x09d8, 1, 0)
-#define _MX51_PAD_DISP2_DAT8__USBH3_DATA0 IOMUX_PAD(0x77c, 0x374, 3, 0x09fc, 1, 0)
-#define _MX51_PAD_DISP2_DAT9__AUD6_RXC IOMUX_PAD(0x780, 0x378, 4, 0x08f4, 1, 0)
-#define _MX51_PAD_DISP2_DAT9__DISP2_DAT9 IOMUX_PAD(0x780, 0x378, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__FEC_TX_EN IOMUX_PAD(0x780, 0x378, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__GPIO1_31 IOMUX_PAD(0x780, 0x378, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__USBH3_DATA1 IOMUX_PAD(0x780, 0x378, 3, 0x0a00, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__DISP2_DAT10 IOMUX_PAD(0x784, 0x37c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT10__DISP2_SER_CS IOMUX_PAD(0x784, 0x37c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT10__FEC_COL IOMUX_PAD(0x784, 0x37c, 2, 0x094c, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__KEY_ROW7 IOMUX_PAD(0x784, 0x37c, 4, 0x09dc, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__USBH3_DATA2 IOMUX_PAD(0x784, 0x37c, 3, 0x0a04, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__AUD6_TXD IOMUX_PAD(0x788, 0x380, 4, 0x08f0, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__DISP2_DAT11 IOMUX_PAD(0x788, 0x380, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT11__FEC_RX_CLK IOMUX_PAD(0x788, 0x380, 2, 0x0968, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__GPIO1_10 IOMUX_PAD(0x788, 0x380, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT11__USBH3_DATA3 IOMUX_PAD(0x788, 0x380, 3, 0x0a08, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__AUD6_RXD IOMUX_PAD(0x78c, 0x384, 4, 0x08ec, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__DISP2_DAT12 IOMUX_PAD(0x78c, 0x384, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT12__FEC_RX_DV IOMUX_PAD(0x78c, 0x384, 2, 0x096c, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__USBH3_DATA4 IOMUX_PAD(0x78c, 0x384, 3, 0x0a0c, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__AUD6_TXC IOMUX_PAD(0x790, 0x388, 4, 0x08fc, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__DISP2_DAT13 IOMUX_PAD(0x790, 0x388, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT13__FEC_TX_CLK IOMUX_PAD(0x790, 0x388, 2, 0x0974, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__USBH3_DATA5 IOMUX_PAD(0x790, 0x388, 3, 0x0a10, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__AUD6_TXFS IOMUX_PAD(0x794, 0x38c, 4, 0x0900, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__DISP2_DAT14 IOMUX_PAD(0x794, 0x38c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT14__FEC_RDATA0 IOMUX_PAD(0x794, 0x38c, 2, 0x0958, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__USBH3_DATA6 IOMUX_PAD(0x794, 0x38c, 3, 0x0a14, 1, 0)
-#define _MX51_PAD_DISP2_DAT15__AUD6_RXFS IOMUX_PAD(0x798, 0x390, 4, 0x08f8, 1, 0)
-#define _MX51_PAD_DISP2_DAT15__DISP1_SER_CS IOMUX_PAD(0x798, 0x390, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__DISP2_DAT15 IOMUX_PAD(0x798, 0x390, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__FEC_TDATA0 IOMUX_PAD(0x798, 0x390, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__USBH3_DATA7 IOMUX_PAD(0x798, 0x390, 3, 0x0a18, 1, 0)
-#define _MX51_PAD_SD1_CMD__AUD5_RXFS IOMUX_PAD(0x79c, 0x394, 1, 0x08e0, 1, 0)
-#define _MX51_PAD_SD1_CMD__CSPI_MOSI IOMUX_PAD(0x79c, 0x394, 2, 0x091c, 2, 0)
-#define _MX51_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x79c, 0x394, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_CLK__AUD5_RXC IOMUX_PAD(0x7a0, 0x398, 1, 0x08dc, 1, 0)
-#define _MX51_PAD_SD1_CLK__CSPI_SCLK IOMUX_PAD(0x7a0, 0x398, 2, 0x0914, 2, 0)
-#define _MX51_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x7a0, 0x398, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA0__AUD5_TXD IOMUX_PAD(0x7a4, 0x39c, 1, 0x08d8, 2, 0)
-#define _MX51_PAD_SD1_DATA0__CSPI_MISO IOMUX_PAD(0x7a4, 0x39c, 2, 0x0918, 1, 0)
-#define _MX51_PAD_SD1_DATA0__SD1_DATA0 IOMUX_PAD(0x7a4, 0x39c, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA0__EIM_DA0 IOMUX_PAD(0x000, 0x01c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA1__EIM_DA1 IOMUX_PAD(0x000, 0x020, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA2__EIM_DA2 IOMUX_PAD(0x000, 0x024, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA3__EIM_DA3 IOMUX_PAD(0x000, 0x028, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA1__AUD5_RXD IOMUX_PAD(0x7a8, 0x3a0, 1, 0x08d4, 2, 0)
-#define _MX51_PAD_SD1_DATA1__SD1_DATA1 IOMUX_PAD(0x7a8, 0x3a0, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA4__EIM_DA4 IOMUX_PAD(0x000, 0x02c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA5__EIM_DA5 IOMUX_PAD(0x000, 0x030, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA6__EIM_DA6 IOMUX_PAD(0x000, 0x034, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA7__EIM_DA7 IOMUX_PAD(0x000, 0x038, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA2__AUD5_TXC IOMUX_PAD(0x7ac, 0x3a4, 1, 0x08e4, 2, 0)
-#define _MX51_PAD_SD1_DATA2__SD1_DATA2 IOMUX_PAD(0x7ac, 0x3a4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA10__EIM_DA10 IOMUX_PAD(0x000, 0x044, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA11__EIM_DA11 IOMUX_PAD(0x000, 0x048, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA8__EIM_DA8 IOMUX_PAD(0x000, 0x03c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA9__EIM_DA9 IOMUX_PAD(0x000, 0x040, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA3__AUD5_TXFS IOMUX_PAD(0x7b0, 0x3a8, 1, 0x08e8, 2, 0)
-#define _MX51_PAD_SD1_DATA3__CSPI_SS1 IOMUX_PAD(0x7b0, 0x3a8, 2, 0x0920, 1, 0)
-#define _MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7b0, 0x3a8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_0__CSPI_SS2 IOMUX_PAD(0x7b4, 0x3ac, 2, 0x0924, 0, 0)
-#define _MX51_PAD_GPIO1_0__GPIO1_0 IOMUX_PAD(0x7b4, 0x3ac, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_0__SD1_CD IOMUX_PAD(0x7b4, 0x3ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_1__CSPI_MISO IOMUX_PAD(0x7b8, 0x3b0, 2, 0x0918, 2, 0)
-#define _MX51_PAD_GPIO1_1__GPIO1_1 IOMUX_PAD(0x7b8, 0x3b0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_1__SD1_WP IOMUX_PAD(0x7b8, 0x3b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA12__EIM_DA12 IOMUX_PAD(0x000, 0x04c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA13__EIM_DA13 IOMUX_PAD(0x000, 0x050, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA14__EIM_DA14 IOMUX_PAD(0x000, 0x054, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA15__EIM_DA15 IOMUX_PAD(0x000, 0x058, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_CMD__CSPI_MOSI IOMUX_PAD(0x000, 0x3b4, 2, 0x091c, 3, 0)
-#define _MX51_PAD_SD2_CMD__I2C1_SCL IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x09b0, 2, 0)
-#define _MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7bc, 0x3b4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_CLK__CSPI_SCLK IOMUX_PAD(0x7c0, 0x3b8, 2, 0x0914, 3, 0)
-#define _MX51_PAD_SD2_CLK__I2C1_SDA IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x09b4, 2, 0)
-#define _MX51_PAD_SD2_CLK__SD2_CLK IOMUX_PAD(0x7c0, 0x3b8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA0__CSPI_MISO IOMUX_PAD(0x7c4, 0x3bc, 2, 0x0918, 3, 0)
-#define _MX51_PAD_SD2_DATA0__SD1_DAT4 IOMUX_PAD(0x7c4, 0x3bc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7c4, 0x3bc, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__SD1_DAT5 IOMUX_PAD(0x7c8, 0x3c0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7c8, 0x3c0, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__USBH3_H2_DP IOMUX_PAD(0x7c8, 0x3c0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__SD1_DAT6 IOMUX_PAD(0x7cc, 0x3c4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7cc, 0x3c4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__USBH3_H2_DM IOMUX_PAD(0x7cc, 0x3c4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA3__CSPI_SS2 IOMUX_PAD(0x7d0, 0x3c8, 2, 0x0924, 1, 0)
-#define _MX51_PAD_SD2_DATA3__SD1_DAT7 IOMUX_PAD(0x7d0, 0x3c8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7d0, 0x3c8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__CCM_OUT_2 IOMUX_PAD(0x7d4, 0x3cc, 5, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__GPIO1_2 IOMUX_PAD(0x7d4, 0x3cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__I2C2_SCL IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x09b8, 3, 0)
-#define _MX51_PAD_GPIO1_2__PLL1_BYP IOMUX_PAD(0x7d4, 0x3cc, 7, 0x090c, 1, 0)
-#define _MX51_PAD_GPIO1_2__PWM1_PWMO IOMUX_PAD(0x7d4, 0x3cc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_3__GPIO1_3 IOMUX_PAD(0x7d8, 0x3d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_3__I2C2_SDA IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x09bc, 3, 0)
-#define _MX51_PAD_GPIO1_3__PLL2_BYP IOMUX_PAD(0x7d8, 0x3d0, 7, 0x0910, 1, 0)
-#define _MX51_PAD_GPIO1_3__PWM2_PWMO IOMUX_PAD(0x7d8, 0x3d0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ IOMUX_PAD(0x7fc, 0x3d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B IOMUX_PAD(0x7fc, 0x3d4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_4__DISP2_EXT_CLK IOMUX_PAD(0x804, 0x3d8, 4, 0x0908, 1, 0)
-#define _MX51_PAD_GPIO1_4__EIM_RDY IOMUX_PAD(0x804, 0x3d8, 3, 0x0938, 1, 0)
-#define _MX51_PAD_GPIO1_4__GPIO1_4 IOMUX_PAD(0x804, 0x3d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_4__WDOG1_WDOG_B IOMUX_PAD(0x804, 0x3d8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__CSI2_MCLK IOMUX_PAD(0x808, 0x3dc, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__DISP2_PIN16 IOMUX_PAD(0x808, 0x3dc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__GPIO1_5 IOMUX_PAD(0x808, 0x3dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__WDOG2_WDOG_B IOMUX_PAD(0x808, 0x3dc, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__DISP2_PIN17 IOMUX_PAD(0x80c, 0x3e0, 4, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__GPIO1_6 IOMUX_PAD(0x80c, 0x3e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__REF_EN_B IOMUX_PAD(0x80c, 0x3e0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__CCM_OUT_0 IOMUX_PAD(0x810, 0x3e4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__GPIO1_7 IOMUX_PAD(0x810, 0x3e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__SD2_WP IOMUX_PAD(0x810, 0x3e4, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__SPDIF_OUT1 IOMUX_PAD(0x810, 0x3e4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__CSI2_DATA_EN IOMUX_PAD(0x814, 0x3e8, 2, 0x099c, 2, 0)
-#define _MX51_PAD_GPIO1_8__GPIO1_8 IOMUX_PAD(0x814, 0x3e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__SD2_CD IOMUX_PAD(0x814, 0x3e8, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__USBH3_PWR IOMUX_PAD(0x814, 0x3e8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__CCM_OUT_1 IOMUX_PAD(0x818, 0x3ec, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__DISP2_D1_CS IOMUX_PAD(0x818, 0x3ec, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__DISP2_SER_CS IOMUX_PAD(0x818, 0x3ec, 7, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__GPIO1_9 IOMUX_PAD(0x818, 0x3ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__SD2_LCTL IOMUX_PAD(0x818, 0x3ec, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__USBH3_OC IOMUX_PAD(0x818, 0x3ec, 1, 0x0000, 0, 0)
/* The same pins as above but with the default pad control values applied */
-#define MX51_PAD_EIM_D16__AUD4_RXFS (_MX51_PAD_EIM_D16__AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__AUD5_TXD (_MX51_PAD_EIM_D16__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__EIM_D16 (_MX51_PAD_EIM_D16__EIM_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__GPIO2_0 (_MX51_PAD_EIM_D16__GPIO2_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__I2C1_SDA (_MX51_PAD_EIM_D16__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D16__UART2_CTS (_MX51_PAD_EIM_D16__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D16__USBH2_DATA0 (_MX51_PAD_EIM_D16__USBH2_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__AUD5_RXD (_MX51_PAD_EIM_D17__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__EIM_D17 (_MX51_PAD_EIM_D17__EIM_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__GPIO2_1 (_MX51_PAD_EIM_D17__GPIO2_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__UART2_RXD (_MX51_PAD_EIM_D17__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D17__UART3_CTS (_MX51_PAD_EIM_D17__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D17__USBH2_DATA1 (_MX51_PAD_EIM_D17__USBH2_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__AUD5_TXC (_MX51_PAD_EIM_D18__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__EIM_D18 (_MX51_PAD_EIM_D18__EIM_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__GPIO2_2 (_MX51_PAD_EIM_D18__GPIO2_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__UART2_TXD (_MX51_PAD_EIM_D18__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D18__UART3_RTS (_MX51_PAD_EIM_D18__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D18__USBH2_DATA2 (_MX51_PAD_EIM_D18__USBH2_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__AUD4_RXC (_MX51_PAD_EIM_D19__AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__AUD5_TXFS (_MX51_PAD_EIM_D19__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__EIM_D19 (_MX51_PAD_EIM_D19__EIM_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__GPIO2_3 (_MX51_PAD_EIM_D19__GPIO2_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__I2C1_SCL (_MX51_PAD_EIM_D19__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D19__UART2_RTS (_MX51_PAD_EIM_D19__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D19__USBH2_DATA3 (_MX51_PAD_EIM_D19__USBH2_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__AUD4_TXD (_MX51_PAD_EIM_D20__AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__EIM_D20 (_MX51_PAD_EIM_D20__EIM_D20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__GPIO2_4 (_MX51_PAD_EIM_D20__GPIO2_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB (_MX51_PAD_EIM_D20__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__USBH2_DATA4 (_MX51_PAD_EIM_D20__USBH2_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__AUD4_RXD (_MX51_PAD_EIM_D21__AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__EIM_D21 (_MX51_PAD_EIM_D21__EIM_D21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__GPIO2_5 (_MX51_PAD_EIM_D21__GPIO2_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB (_MX51_PAD_EIM_D21__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__USBH2_DATA5 (_MX51_PAD_EIM_D21__USBH2_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__AUD4_TXC (_MX51_PAD_EIM_D22__AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__EIM_D22 (_MX51_PAD_EIM_D22__EIM_D22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__GPIO2_6 (_MX51_PAD_EIM_D22__GPIO2_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__USBH2_DATA6 (_MX51_PAD_EIM_D22__USBH2_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__AUD4_TXFS (_MX51_PAD_EIM_D23__AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__EIM_D23 (_MX51_PAD_EIM_D23__EIM_D23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__GPIO2_7 (_MX51_PAD_EIM_D23__GPIO2_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__SPDIF_OUT1 (_MX51_PAD_EIM_D23__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__USBH2_DATA7 (_MX51_PAD_EIM_D23__USBH2_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__AUD6_RXFS (_MX51_PAD_EIM_D24__AUD6_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__EIM_D24 (_MX51_PAD_EIM_D24__EIM_D24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__GPIO2_8 (_MX51_PAD_EIM_D24__GPIO2_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__I2C2_SDA (_MX51_PAD_EIM_D24__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D24__UART3_CTS (_MX51_PAD_EIM_D24__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D24__USBOTG_DATA0 (_MX51_PAD_EIM_D24__USBOTG_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__EIM_D25 (_MX51_PAD_EIM_D25__EIM_D25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__KEY_COL6 (_MX51_PAD_EIM_D25__KEY_COL6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__UART2_CTS (_MX51_PAD_EIM_D25__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D25__UART3_RXD (_MX51_PAD_EIM_D25__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D25__USBOTG_DATA1 (_MX51_PAD_EIM_D25__USBOTG_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__EIM_D26 (_MX51_PAD_EIM_D26__EIM_D26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__KEY_COL7 (_MX51_PAD_EIM_D26__KEY_COL7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__UART2_RTS (_MX51_PAD_EIM_D26__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D26__UART3_TXD (_MX51_PAD_EIM_D26__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D26__USBOTG_DATA2 (_MX51_PAD_EIM_D26__USBOTG_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__AUD6_RXC (_MX51_PAD_EIM_D27__AUD6_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__EIM_D27 (_MX51_PAD_EIM_D27__EIM_D27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__GPIO2_9 (_MX51_PAD_EIM_D27__GPIO2_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__I2C2_SCL (_MX51_PAD_EIM_D27__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D27__UART3_RTS (_MX51_PAD_EIM_D27__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D27__USBOTG_DATA3 (_MX51_PAD_EIM_D27__USBOTG_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__AUD6_TXD (_MX51_PAD_EIM_D28__AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__EIM_D28 (_MX51_PAD_EIM_D28__EIM_D28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__KEY_ROW4 (_MX51_PAD_EIM_D28__KEY_ROW4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__USBOTG_DATA4 (_MX51_PAD_EIM_D28__USBOTG_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__AUD6_RXD (_MX51_PAD_EIM_D29__AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__EIM_D29 (_MX51_PAD_EIM_D29__EIM_D29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__KEY_ROW5 (_MX51_PAD_EIM_D29__KEY_ROW5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__USBOTG_DATA5 (_MX51_PAD_EIM_D29__USBOTG_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__AUD6_TXC (_MX51_PAD_EIM_D30__AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__EIM_D30 (_MX51_PAD_EIM_D30__EIM_D30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__KEY_ROW6 (_MX51_PAD_EIM_D30__KEY_ROW6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__USBOTG_DATA6 (_MX51_PAD_EIM_D30__USBOTG_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__AUD6_TXFS (_MX51_PAD_EIM_D31__AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__EIM_D31 (_MX51_PAD_EIM_D31__EIM_D31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__KEY_ROW7 (_MX51_PAD_EIM_D31__KEY_ROW7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__USBOTG_DATA7 (_MX51_PAD_EIM_D31__USBOTG_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__EIM_A16 (_MX51_PAD_EIM_A16__EIM_A16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__GPIO2_10 (_MX51_PAD_EIM_A16__GPIO2_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0 (_MX51_PAD_EIM_A16__OSC_FREQ_SEL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__EIM_A17 (_MX51_PAD_EIM_A17__EIM_A17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__GPIO2_11 (_MX51_PAD_EIM_A17__GPIO2_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1 (_MX51_PAD_EIM_A17__OSC_FREQ_SEL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__BOOT_LPB0 (_MX51_PAD_EIM_A18__BOOT_LPB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__EIM_A18 (_MX51_PAD_EIM_A18__EIM_A18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__GPIO2_12 (_MX51_PAD_EIM_A18__GPIO2_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__BOOT_LPB1 (_MX51_PAD_EIM_A19__BOOT_LPB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__EIM_A19 (_MX51_PAD_EIM_A19__EIM_A19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__GPIO2_13 (_MX51_PAD_EIM_A19__GPIO2_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__BOOT_UART_SRC0 (_MX51_PAD_EIM_A20__BOOT_UART_SRC0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__EIM_A20 (_MX51_PAD_EIM_A20__EIM_A20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__GPIO2_14 (_MX51_PAD_EIM_A20__GPIO2_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__BOOT_UART_SRC1 (_MX51_PAD_EIM_A21__BOOT_UART_SRC1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__EIM_A21 (_MX51_PAD_EIM_A21__EIM_A21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__GPIO2_15 (_MX51_PAD_EIM_A21__GPIO2_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A22__EIM_A22 (_MX51_PAD_EIM_A22__EIM_A22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A22__GPIO2_16 (_MX51_PAD_EIM_A22__GPIO2_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__BOOT_HPN_EN (_MX51_PAD_EIM_A23__BOOT_HPN_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__EIM_A23 (_MX51_PAD_EIM_A23__EIM_A23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__GPIO2_17 (_MX51_PAD_EIM_A23__GPIO2_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__EIM_A24 (_MX51_PAD_EIM_A24__EIM_A24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__GPIO2_18 (_MX51_PAD_EIM_A24__GPIO2_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__USBH2_CLK (_MX51_PAD_EIM_A24__USBH2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__DISP1_PIN4 (_MX51_PAD_EIM_A25__DISP1_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__EIM_A25 (_MX51_PAD_EIM_A25__EIM_A25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__GPIO2_19 (_MX51_PAD_EIM_A25__GPIO2_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__USBH2_DIR (_MX51_PAD_EIM_A25__USBH2_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__CSI1_DATA_EN (_MX51_PAD_EIM_A26__CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__DISP2_EXT_CLK (_MX51_PAD_EIM_A26__DISP2_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__EIM_A26 (_MX51_PAD_EIM_A26__EIM_A26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__GPIO2_20 (_MX51_PAD_EIM_A26__GPIO2_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__USBH2_STP (_MX51_PAD_EIM_A26__USBH2_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__CSI2_DATA_EN (_MX51_PAD_EIM_A27__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__DISP1_PIN1 (_MX51_PAD_EIM_A27__DISP1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__EIM_A27 (_MX51_PAD_EIM_A27__EIM_A27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__GPIO2_21 (_MX51_PAD_EIM_A27__GPIO2_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__USBH2_NXT (_MX51_PAD_EIM_A27__USBH2_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB0__EIM_EB0 (_MX51_PAD_EIM_EB0__EIM_EB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB1__EIM_EB1 (_MX51_PAD_EIM_EB1__EIM_EB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__AUD5_RXFS (_MX51_PAD_EIM_EB2__AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__CSI1_D2 (_MX51_PAD_EIM_EB2__CSI1_D2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__EIM_EB2 (_MX51_PAD_EIM_EB2__EIM_EB2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__FEC_MDIO (_MX51_PAD_EIM_EB2__FEC_MDIO | \
+#define MX51_PAD_EIM_D16__AUD4_RXFS IOMUX_PAD(0x3f0, 0x05c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__AUD5_TXD IOMUX_PAD(0x3f0, 0x05c, 7, 0x8d8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__EIM_D16 IOMUX_PAD(0x3f0, 0x05c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__GPIO2_0 IOMUX_PAD(0x3f0, 0x05c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__I2C1_SDA IOMUX_PAD(0x3f0, 0x05c, 0x14, 0x9b4, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D16__UART2_CTS IOMUX_PAD(0x3f0, 0x05c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D16__USBH2_DATA0 IOMUX_PAD(0x3f0, 0x05c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__AUD5_RXD IOMUX_PAD(0x3f4, 0x060, 7, 0x8d4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__EIM_D17 IOMUX_PAD(0x3f4, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__GPIO2_1 IOMUX_PAD(0x3f4, 0x060, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__UART2_RXD IOMUX_PAD(0x3f4, 0x060, 3, 0x9ec, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D17__UART3_CTS IOMUX_PAD(0x3f4, 0x060, 4, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D17__USBH2_DATA1 IOMUX_PAD(0x3f4, 0x060, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__AUD5_TXC IOMUX_PAD(0x3f8, 0x064, 7, 0x8e4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__EIM_D18 IOMUX_PAD(0x3f8, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__GPIO2_2 IOMUX_PAD(0x3f8, 0x064, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__UART2_TXD IOMUX_PAD(0x3f8, 0x064, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D18__UART3_RTS IOMUX_PAD(0x3f8, 0x064, 4, 0x9f0, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D18__USBH2_DATA2 IOMUX_PAD(0x3f8, 0x064, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__AUD4_RXC IOMUX_PAD(0x3fc, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__AUD5_TXFS IOMUX_PAD(0x3fc, 0x068, 7, 0x8e8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__EIM_D19 IOMUX_PAD(0x3fc, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__GPIO2_3 IOMUX_PAD(0x3fc, 0x068, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__I2C1_SCL IOMUX_PAD(0x3fc, 0x068, 0x14, 0x9b0, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D19__UART2_RTS IOMUX_PAD(0x3fc, 0x068, 3, 0x9e8, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D19__USBH2_DATA3 IOMUX_PAD(0x3fc, 0x068, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__AUD4_TXD IOMUX_PAD(0x400, 0x06c, 5, 0x8c8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__EIM_D20 IOMUX_PAD(0x400, 0x06c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__GPIO2_4 IOMUX_PAD(0x400, 0x06c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB IOMUX_PAD(0x400, 0x06c, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__USBH2_DATA4 IOMUX_PAD(0x400, 0x06c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__AUD4_RXD IOMUX_PAD(0x404, 0x070, 5, 0x8c4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__EIM_D21 IOMUX_PAD(0x404, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__GPIO2_5 IOMUX_PAD(0x404, 0x070, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB IOMUX_PAD(0x404, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__USBH2_DATA5 IOMUX_PAD(0x404, 0x070, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__AUD4_TXC IOMUX_PAD(0x408, 0x074, 5, 0x8cc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__EIM_D22 IOMUX_PAD(0x408, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__GPIO2_6 IOMUX_PAD(0x408, 0x074, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__USBH2_DATA6 IOMUX_PAD(0x408, 0x074, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__AUD4_TXFS IOMUX_PAD(0x40c, 0x078, 5, 0x8d0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__EIM_D23 IOMUX_PAD(0x40c, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__GPIO2_7 IOMUX_PAD(0x40c, 0x078, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__SPDIF_OUT1 IOMUX_PAD(0x40c, 0x078, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__USBH2_DATA7 IOMUX_PAD(0x40c, 0x078, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__AUD6_RXFS IOMUX_PAD(0x410, 0x07c, 5, 0x8f8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__EIM_D24 IOMUX_PAD(0x410, 0x07c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__GPIO2_8 IOMUX_PAD(0x410, 0x07c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__I2C2_SDA IOMUX_PAD(0x410, 0x07c, 0x14, 0x9bc, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D24__UART3_CTS IOMUX_PAD(0x410, 0x07c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D24__USBOTG_DATA0 IOMUX_PAD(0x410, 0x07c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__EIM_D25 IOMUX_PAD(0x414, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__KEY_COL6 IOMUX_PAD(0x414, 0x080, 1, 0x9c8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART2_CTS IOMUX_PAD(0x414, 0x080, 4, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART3_RXD IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D25__USBOTG_DATA1 IOMUX_PAD(0x414, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__EIM_D26 IOMUX_PAD(0x418, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__KEY_COL7 IOMUX_PAD(0x418, 0x084, 1, 0x9cc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART2_RTS IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART3_TXD IOMUX_PAD(0x418, 0x084, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D26__USBOTG_DATA2 IOMUX_PAD(0x418, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__AUD6_RXC IOMUX_PAD(0x41c, 0x088, 5, 0x8f4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__EIM_D27 IOMUX_PAD(0x41c, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__GPIO2_9 IOMUX_PAD(0x41c, 0x088, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__I2C2_SCL IOMUX_PAD(0x41c, 0x088, 0x14, 0x9b8, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D27__UART3_RTS IOMUX_PAD(0x41c, 0x088, 3, 0x9f0, 3, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D27__USBOTG_DATA3 IOMUX_PAD(0x41c, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__AUD6_TXD IOMUX_PAD(0x420, 0x08c, 5, 0x8f0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__EIM_D28 IOMUX_PAD(0x420, 0x08c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__KEY_ROW4 IOMUX_PAD(0x420, 0x08c, 1, 0x9d0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__USBOTG_DATA4 IOMUX_PAD(0x420, 0x08c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__AUD6_RXD IOMUX_PAD(0x424, 0x090, 5, 0x8ec, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__EIM_D29 IOMUX_PAD(0x424, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__KEY_ROW5 IOMUX_PAD(0x424, 0x090, 1, 0x9d4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__USBOTG_DATA5 IOMUX_PAD(0x424, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__AUD6_TXC IOMUX_PAD(0x428, 0x094, 5, 0x8fc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__EIM_D30 IOMUX_PAD(0x428, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__KEY_ROW6 IOMUX_PAD(0x428, 0x094, 1, 0x9d8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__USBOTG_DATA6 IOMUX_PAD(0x428, 0x094, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__AUD6_TXFS IOMUX_PAD(0x42c, 0x098, 5, 0x900, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__EIM_D31 IOMUX_PAD(0x42c, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__KEY_ROW7 IOMUX_PAD(0x42c, 0x098, 1, 0x9dc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__USBOTG_DATA7 IOMUX_PAD(0x42c, 0x098, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__EIM_A16 IOMUX_PAD(0x430, 0x09c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__GPIO2_10 IOMUX_PAD(0x430, 0x09c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0 IOMUX_PAD(0x430, 0x09c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__EIM_A17 IOMUX_PAD(0x434, 0x0a0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__GPIO2_11 IOMUX_PAD(0x434, 0x0a0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1 IOMUX_PAD(0x434, 0x0a0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__BOOT_LPB0 IOMUX_PAD(0x438, 0x0a4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__EIM_A18 IOMUX_PAD(0x438, 0x0a4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__GPIO2_12 IOMUX_PAD(0x438, 0x0a4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__BOOT_LPB1 IOMUX_PAD(0x43c, 0x0a8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__EIM_A19 IOMUX_PAD(0x43c, 0x0a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__GPIO2_13 IOMUX_PAD(0x43c, 0x0a8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__BOOT_UART_SRC0 IOMUX_PAD(0x440, 0x0ac, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__EIM_A20 IOMUX_PAD(0x440, 0x0ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__GPIO2_14 IOMUX_PAD(0x440, 0x0ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__BOOT_UART_SRC1 IOMUX_PAD(0x444, 0x0b0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__EIM_A21 IOMUX_PAD(0x444, 0x0b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__GPIO2_15 IOMUX_PAD(0x444, 0x0b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A22__EIM_A22 IOMUX_PAD(0x448, 0x0b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A22__GPIO2_16 IOMUX_PAD(0x448, 0x0b4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__BOOT_HPN_EN IOMUX_PAD(0x44c, 0x0b8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__EIM_A23 IOMUX_PAD(0x44c, 0x0b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__GPIO2_17 IOMUX_PAD(0x44c, 0x0b8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__EIM_A24 IOMUX_PAD(0x450, 0x0bc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__GPIO2_18 IOMUX_PAD(0x450, 0x0bc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__USBH2_CLK IOMUX_PAD(0x450, 0x0bc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__DISP1_PIN4 IOMUX_PAD(0x454, 0x0c0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__EIM_A25 IOMUX_PAD(0x454, 0x0c0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__GPIO2_19 IOMUX_PAD(0x454, 0x0c0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__USBH2_DIR IOMUX_PAD(0x454, 0x0c0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__CSI1_DATA_EN IOMUX_PAD(0x458, 0x0c4, 5, 0x9a0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__DISP2_EXT_CLK IOMUX_PAD(0x458, 0x0c4, 6, 0x908, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__EIM_A26 IOMUX_PAD(0x458, 0x0c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__GPIO2_20 IOMUX_PAD(0x458, 0x0c4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__USBH2_STP IOMUX_PAD(0x458, 0x0c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__CSI2_DATA_EN IOMUX_PAD(0x45c, 0x0c8, 5, 0x99c, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__DISP1_PIN1 IOMUX_PAD(0x45c, 0x0c8, 6, 0x9a4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__EIM_A27 IOMUX_PAD(0x45c, 0x0c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__GPIO2_21 IOMUX_PAD(0x45c, 0x0c8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__USBH2_NXT IOMUX_PAD(0x45c, 0x0c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB0__EIM_EB0 IOMUX_PAD(0x460, 0x0cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB1__EIM_EB1 IOMUX_PAD(0x464, 0x0d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__AUD5_RXFS IOMUX_PAD(0x468, 0x0d4, 6, 0x8e0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__CSI1_D2 IOMUX_PAD(0x468, 0x0d4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__EIM_EB2 IOMUX_PAD(0x468, 0x0d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__FEC_MDIO (IOMUX_PAD(0x468, 0x0d4, 3, 0x954, 0, 0) | \
MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP | PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS))
-#define MX51_PAD_EIM_EB2__GPIO2_22 (_MX51_PAD_EIM_EB2__GPIO2_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__GPT_CMPOUT1 (_MX51_PAD_EIM_EB2__GPT_CMPOUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__AUD5_RXC (_MX51_PAD_EIM_EB3__AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__CSI1_D3 (_MX51_PAD_EIM_EB3__CSI1_D3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__EIM_EB3 (_MX51_PAD_EIM_EB3__EIM_EB3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__FEC_RDATA1 (_MX51_PAD_EIM_EB3__FEC_RDATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__GPIO2_23 (_MX51_PAD_EIM_EB3__GPIO2_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__GPT_CMPOUT2 (_MX51_PAD_EIM_EB3__GPT_CMPOUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_OE__EIM_OE (_MX51_PAD_EIM_OE__EIM_OE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_OE__GPIO2_24 (_MX51_PAD_EIM_OE__GPIO2_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS0__EIM_CS0 (_MX51_PAD_EIM_CS0__EIM_CS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS0__GPIO2_25 (_MX51_PAD_EIM_CS0__GPIO2_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS1__EIM_CS1 (_MX51_PAD_EIM_CS1__EIM_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS1__GPIO2_26 (_MX51_PAD_EIM_CS1__GPIO2_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__AUD5_TXD (_MX51_PAD_EIM_CS2__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__CSI1_D4 (_MX51_PAD_EIM_CS2__CSI1_D4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__EIM_CS2 (_MX51_PAD_EIM_CS2__EIM_CS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__FEC_RDATA2 (_MX51_PAD_EIM_CS2__FEC_RDATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__GPIO2_27 (_MX51_PAD_EIM_CS2__GPIO2_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__USBOTG_STP (_MX51_PAD_EIM_CS2__USBOTG_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__AUD5_RXD (_MX51_PAD_EIM_CS3__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__CSI1_D5 (_MX51_PAD_EIM_CS3__CSI1_D5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__EIM_CS3 (_MX51_PAD_EIM_CS3__EIM_CS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__FEC_RDATA3 (_MX51_PAD_EIM_CS3__FEC_RDATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__GPIO2_28 (_MX51_PAD_EIM_CS3__GPIO2_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__USBOTG_NXT (_MX51_PAD_EIM_CS3__USBOTG_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__AUD5_TXC (_MX51_PAD_EIM_CS4__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__CSI1_D6 (_MX51_PAD_EIM_CS4__CSI1_D6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__EIM_CS4 (_MX51_PAD_EIM_CS4__EIM_CS4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__FEC_RX_ER (_MX51_PAD_EIM_CS4__FEC_RX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_EIM_CS4__GPIO2_29 (_MX51_PAD_EIM_CS4__GPIO2_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__USBOTG_CLK (_MX51_PAD_EIM_CS4__USBOTG_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__AUD5_TXFS (_MX51_PAD_EIM_CS5__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__CSI1_D7 (_MX51_PAD_EIM_CS5__CSI1_D7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK (_MX51_PAD_EIM_CS5__DISP1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__EIM_CS5 (_MX51_PAD_EIM_CS5__EIM_CS5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__FEC_CRS (_MX51_PAD_EIM_CS5__FEC_CRS | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_EIM_CS5__GPIO2_30 (_MX51_PAD_EIM_CS5__GPIO2_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__USBOTG_DIR (_MX51_PAD_EIM_CS5__USBOTG_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DTACK__EIM_DTACK (_MX51_PAD_EIM_DTACK__EIM_DTACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DTACK__GPIO2_31 (_MX51_PAD_EIM_DTACK__GPIO2_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_LBA__EIM_LBA (_MX51_PAD_EIM_LBA__EIM_LBA | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_LBA__GPIO3_1 (_MX51_PAD_EIM_LBA__GPIO3_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CRE__EIM_CRE (_MX51_PAD_EIM_CRE__EIM_CRE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CRE__GPIO3_2 (_MX51_PAD_EIM_CRE__GPIO3_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DRAM_CS1__DRAM_CS1 (_MX51_PAD_DRAM_CS1__DRAM_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__GPIO3_3 (_MX51_PAD_NANDF_WE_B__GPIO3_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__NANDF_WE_B (_MX51_PAD_NANDF_WE_B__NANDF_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__PATA_DIOW (_MX51_PAD_NANDF_WE_B__PATA_DIOW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__SD3_DATA0 (_MX51_PAD_NANDF_WE_B__SD3_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__GPIO3_4 (_MX51_PAD_NANDF_RE_B__GPIO3_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__NANDF_RE_B (_MX51_PAD_NANDF_RE_B__NANDF_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__PATA_DIOR (_MX51_PAD_NANDF_RE_B__PATA_DIOR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__SD3_DATA1 (_MX51_PAD_NANDF_RE_B__SD3_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_ALE__GPIO3_5 (_MX51_PAD_NANDF_ALE__GPIO3_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_ALE__NANDF_ALE (_MX51_PAD_NANDF_ALE__NANDF_ALE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN (_MX51_PAD_NANDF_ALE__PATA_BUFFER_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__GPIO3_6 (_MX51_PAD_NANDF_CLE__GPIO3_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__NANDF_CLE (_MX51_PAD_NANDF_CLE__NANDF_CLE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__PATA_RESET_B (_MX51_PAD_NANDF_CLE__PATA_RESET_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__GPIO3_7 (_MX51_PAD_NANDF_WP_B__GPIO3_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__NANDF_WP_B (_MX51_PAD_NANDF_WP_B__NANDF_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__PATA_DMACK (_MX51_PAD_NANDF_WP_B__PATA_DMACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__SD3_DATA2 (_MX51_PAD_NANDF_WP_B__SD3_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__ECSPI2_SS1 (_MX51_PAD_NANDF_RB0__ECSPI2_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__GPIO3_8 (_MX51_PAD_NANDF_RB0__GPIO3_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__NANDF_RB0 (_MX51_PAD_NANDF_RB0__NANDF_RB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__PATA_DMARQ (_MX51_PAD_NANDF_RB0__PATA_DMARQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__SD3_DATA3 (_MX51_PAD_NANDF_RB0__SD3_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__CSPI_MOSI (_MX51_PAD_NANDF_RB1__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__ECSPI2_RDY (_MX51_PAD_NANDF_RB1__ECSPI2_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__GPIO3_9 (_MX51_PAD_NANDF_RB1__GPIO3_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__NANDF_RB1 (_MX51_PAD_NANDF_RB1__NANDF_RB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__PATA_IORDY (_MX51_PAD_NANDF_RB1__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__SD4_CMD (_MX51_PAD_NANDF_RB1__SD4_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__DISP2_WAIT (_MX51_PAD_NANDF_RB2__DISP2_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK (_MX51_PAD_NANDF_RB2__ECSPI2_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__FEC_COL (_MX51_PAD_NANDF_RB2__FEC_COL | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_NANDF_RB2__GPIO3_10 (_MX51_PAD_NANDF_RB2__GPIO3_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__NANDF_RB2 (_MX51_PAD_NANDF_RB2__NANDF_RB2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__USBH3_H3_DP (_MX51_PAD_NANDF_RB2__USBH3_H3_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__USBH3_NXT (_MX51_PAD_NANDF_RB2__USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__DISP1_WAIT (_MX51_PAD_NANDF_RB3__DISP1_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__ECSPI2_MISO (_MX51_PAD_NANDF_RB3__ECSPI2_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__FEC_RX_CLK (_MX51_PAD_NANDF_RB3__FEC_RX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_NANDF_RB3__GPIO3_11 (_MX51_PAD_NANDF_RB3__GPIO3_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__NANDF_RB3 (_MX51_PAD_NANDF_RB3__NANDF_RB3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__USBH3_CLK (_MX51_PAD_NANDF_RB3__USBH3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__USBH3_H3_DM (_MX51_PAD_NANDF_RB3__USBH3_H3_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO_NAND__GPIO_NAND (_MX51_PAD_GPIO_NAND__GPIO_NAND | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_GPIO_NAND__PATA_INTRQ (_MX51_PAD_GPIO_NAND__PATA_INTRQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS0__GPIO3_16 (_MX51_PAD_NANDF_CS0__GPIO3_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS0__NANDF_CS0 (_MX51_PAD_NANDF_CS0__NANDF_CS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS1__GPIO3_17 (_MX51_PAD_NANDF_CS1__GPIO3_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS1__NANDF_CS1 (_MX51_PAD_NANDF_CS1__NANDF_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__CSPI_SCLK (_MX51_PAD_NANDF_CS2__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__FEC_TX_ER (_MX51_PAD_NANDF_CS2__FEC_TX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS2__GPIO3_18 (_MX51_PAD_NANDF_CS2__GPIO3_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__NANDF_CS2 (_MX51_PAD_NANDF_CS2__NANDF_CS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__PATA_CS_0 (_MX51_PAD_NANDF_CS2__PATA_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__SD4_CLK (_MX51_PAD_NANDF_CS2__SD4_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_NANDF_CS2__USBH3_H1_DP (_MX51_PAD_NANDF_CS2__USBH3_H1_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__FEC_MDC (_MX51_PAD_NANDF_CS3__FEC_MDC | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS3__GPIO3_19 (_MX51_PAD_NANDF_CS3__GPIO3_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__NANDF_CS3 (_MX51_PAD_NANDF_CS3__NANDF_CS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__PATA_CS_1 (_MX51_PAD_NANDF_CS3__PATA_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__SD4_DAT0 (_MX51_PAD_NANDF_CS3__SD4_DAT0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__USBH3_H1_DM (_MX51_PAD_NANDF_CS3__USBH3_H1_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__FEC_TDATA1 (_MX51_PAD_NANDF_CS4__FEC_TDATA1 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS4__GPIO3_20 (_MX51_PAD_NANDF_CS4__GPIO3_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__NANDF_CS4 (_MX51_PAD_NANDF_CS4__NANDF_CS4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__PATA_DA_0 (_MX51_PAD_NANDF_CS4__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__SD4_DAT1 (_MX51_PAD_NANDF_CS4__SD4_DAT1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__USBH3_STP (_MX51_PAD_NANDF_CS4__USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__FEC_TDATA2 (_MX51_PAD_NANDF_CS5__FEC_TDATA2 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS5__GPIO3_21 (_MX51_PAD_NANDF_CS5__GPIO3_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__NANDF_CS5 (_MX51_PAD_NANDF_CS5__NANDF_CS5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__PATA_DA_1 (_MX51_PAD_NANDF_CS5__PATA_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__SD4_DAT2 (_MX51_PAD_NANDF_CS5__SD4_DAT2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__USBH3_DIR (_MX51_PAD_NANDF_CS5__USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__CSPI_SS3 (_MX51_PAD_NANDF_CS6__CSPI_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__FEC_TDATA3 (_MX51_PAD_NANDF_CS6__FEC_TDATA3 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS6__GPIO3_22 (_MX51_PAD_NANDF_CS6__GPIO3_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__NANDF_CS6 (_MX51_PAD_NANDF_CS6__NANDF_CS6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__PATA_DA_2 (_MX51_PAD_NANDF_CS6__PATA_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__SD4_DAT3 (_MX51_PAD_NANDF_CS6__SD4_DAT3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__FEC_TX_EN (_MX51_PAD_NANDF_CS7__FEC_TX_EN | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS7__GPIO3_23 (_MX51_PAD_NANDF_CS7__GPIO3_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__NANDF_CS7 (_MX51_PAD_NANDF_CS7__NANDF_CS7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__SD3_CLK (_MX51_PAD_NANDF_CS7__SD3_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 (_MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK (_MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_NANDF_RDY_INT__GPIO3_24 (_MX51_PAD_NANDF_RDY_INT__GPIO3_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT (_MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__SD3_CMD (_MX51_PAD_NANDF_RDY_INT__SD3_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__ECSPI2_MOSI (_MX51_PAD_NANDF_D15__ECSPI2_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__GPIO3_25 (_MX51_PAD_NANDF_D15__GPIO3_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__NANDF_D15 (_MX51_PAD_NANDF_D15__NANDF_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__PATA_DATA15 (_MX51_PAD_NANDF_D15__PATA_DATA15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__SD3_DAT7 (_MX51_PAD_NANDF_D15__SD3_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__ECSPI2_SS3 (_MX51_PAD_NANDF_D14__ECSPI2_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__GPIO3_26 (_MX51_PAD_NANDF_D14__GPIO3_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__NANDF_D14 (_MX51_PAD_NANDF_D14__NANDF_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__PATA_DATA14 (_MX51_PAD_NANDF_D14__PATA_DATA14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__SD3_DAT6 (_MX51_PAD_NANDF_D14__SD3_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__ECSPI2_SS2 (_MX51_PAD_NANDF_D13__ECSPI2_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__GPIO3_27 (_MX51_PAD_NANDF_D13__GPIO3_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__NANDF_D13 (_MX51_PAD_NANDF_D13__NANDF_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__PATA_DATA13 (_MX51_PAD_NANDF_D13__PATA_DATA13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__SD3_DAT5 (_MX51_PAD_NANDF_D13__SD3_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__ECSPI2_SS1 (_MX51_PAD_NANDF_D12__ECSPI2_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__GPIO3_28 (_MX51_PAD_NANDF_D12__GPIO3_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__NANDF_D12 (_MX51_PAD_NANDF_D12__NANDF_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__PATA_DATA12 (_MX51_PAD_NANDF_D12__PATA_DATA12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__SD3_DAT4 (_MX51_PAD_NANDF_D12__SD3_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__FEC_RX_DV (_MX51_PAD_NANDF_D11__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__GPIO3_29 (_MX51_PAD_NANDF_D11__GPIO3_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__NANDF_D11 (_MX51_PAD_NANDF_D11__NANDF_D11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__PATA_DATA11 (_MX51_PAD_NANDF_D11__PATA_DATA11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__SD3_DATA3 (_MX51_PAD_NANDF_D11__SD3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__GPIO3_30 (_MX51_PAD_NANDF_D10__GPIO3_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__NANDF_D10 (_MX51_PAD_NANDF_D10__NANDF_D10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__PATA_DATA10 (_MX51_PAD_NANDF_D10__PATA_DATA10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__SD3_DATA2 (_MX51_PAD_NANDF_D10__SD3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__FEC_RDATA0 (_MX51_PAD_NANDF_D9__FEC_RDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_NANDF_D9__GPIO3_31 (_MX51_PAD_NANDF_D9__GPIO3_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__NANDF_D9 (_MX51_PAD_NANDF_D9__NANDF_D9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__PATA_DATA9 (_MX51_PAD_NANDF_D9__PATA_DATA9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__SD3_DATA1 (_MX51_PAD_NANDF_D9__SD3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__FEC_TDATA0 (_MX51_PAD_NANDF_D8__FEC_TDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_D8__GPIO4_0 (_MX51_PAD_NANDF_D8__GPIO4_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__NANDF_D8 (_MX51_PAD_NANDF_D8__NANDF_D8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__PATA_DATA8 (_MX51_PAD_NANDF_D8__PATA_DATA8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__SD3_DATA0 (_MX51_PAD_NANDF_D8__SD3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__GPIO4_1 (_MX51_PAD_NANDF_D7__GPIO4_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__NANDF_D7 (_MX51_PAD_NANDF_D7__NANDF_D7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__PATA_DATA7 (_MX51_PAD_NANDF_D7__PATA_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__USBH3_DATA0 (_MX51_PAD_NANDF_D7__USBH3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__GPIO4_2 (_MX51_PAD_NANDF_D6__GPIO4_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__NANDF_D6 (_MX51_PAD_NANDF_D6__NANDF_D6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__PATA_DATA6 (_MX51_PAD_NANDF_D6__PATA_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__SD4_LCTL (_MX51_PAD_NANDF_D6__SD4_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__USBH3_DATA1 (_MX51_PAD_NANDF_D6__USBH3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__GPIO4_3 (_MX51_PAD_NANDF_D5__GPIO4_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__NANDF_D5 (_MX51_PAD_NANDF_D5__NANDF_D5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__PATA_DATA5 (_MX51_PAD_NANDF_D5__PATA_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__SD4_WP (_MX51_PAD_NANDF_D5__SD4_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__USBH3_DATA2 (_MX51_PAD_NANDF_D5__USBH3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__GPIO4_4 (_MX51_PAD_NANDF_D4__GPIO4_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__NANDF_D4 (_MX51_PAD_NANDF_D4__NANDF_D4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__PATA_DATA4 (_MX51_PAD_NANDF_D4__PATA_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__SD4_CD (_MX51_PAD_NANDF_D4__SD4_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__USBH3_DATA3 (_MX51_PAD_NANDF_D4__USBH3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__GPIO4_5 (_MX51_PAD_NANDF_D3__GPIO4_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__NANDF_D3 (_MX51_PAD_NANDF_D3__NANDF_D3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__PATA_DATA3 (_MX51_PAD_NANDF_D3__PATA_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__SD4_DAT4 (_MX51_PAD_NANDF_D3__SD4_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__USBH3_DATA4 (_MX51_PAD_NANDF_D3__USBH3_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__GPIO4_6 (_MX51_PAD_NANDF_D2__GPIO4_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__NANDF_D2 (_MX51_PAD_NANDF_D2__NANDF_D2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__PATA_DATA2 (_MX51_PAD_NANDF_D2__PATA_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__SD4_DAT5 (_MX51_PAD_NANDF_D2__SD4_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__USBH3_DATA5 (_MX51_PAD_NANDF_D2__USBH3_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__GPIO4_7 (_MX51_PAD_NANDF_D1__GPIO4_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__NANDF_D1 (_MX51_PAD_NANDF_D1__NANDF_D1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__PATA_DATA1 (_MX51_PAD_NANDF_D1__PATA_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__SD4_DAT6 (_MX51_PAD_NANDF_D1__SD4_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__USBH3_DATA6 (_MX51_PAD_NANDF_D1__USBH3_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__GPIO4_8 (_MX51_PAD_NANDF_D0__GPIO4_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__NANDF_D0 (_MX51_PAD_NANDF_D0__NANDF_D0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__PATA_DATA0 (_MX51_PAD_NANDF_D0__PATA_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__SD4_DAT7 (_MX51_PAD_NANDF_D0__SD4_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__USBH3_DATA7 (_MX51_PAD_NANDF_D0__USBH3_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D8__CSI1_D8 (_MX51_PAD_CSI1_D8__CSI1_D8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D8__GPIO3_12 (_MX51_PAD_CSI1_D8__GPIO3_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_D9__CSI1_D9 (_MX51_PAD_CSI1_D9__CSI1_D9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D9__GPIO3_13 (_MX51_PAD_CSI1_D9__GPIO3_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_D10__CSI1_D10 (_MX51_PAD_CSI1_D10__CSI1_D10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D11__CSI1_D11 (_MX51_PAD_CSI1_D11__CSI1_D11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D12__CSI1_D12 (_MX51_PAD_CSI1_D12__CSI1_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D13__CSI1_D13 (_MX51_PAD_CSI1_D13__CSI1_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D14__CSI1_D14 (_MX51_PAD_CSI1_D14__CSI1_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D15__CSI1_D15 (_MX51_PAD_CSI1_D15__CSI1_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D16__CSI1_D16 (_MX51_PAD_CSI1_D16__CSI1_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D17__CSI1_D17 (_MX51_PAD_CSI1_D17__CSI1_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D18__CSI1_D18 (_MX51_PAD_CSI1_D18__CSI1_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D19__CSI1_D19 (_MX51_PAD_CSI1_D19__CSI1_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC (_MX51_PAD_CSI1_VSYNC__CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_VSYNC__GPIO3_14 (_MX51_PAD_CSI1_VSYNC__GPIO3_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC (_MX51_PAD_CSI1_HSYNC__CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_HSYNC__GPIO3_15 (_MX51_PAD_CSI1_HSYNC__GPIO3_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK (_MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_MCLK__CSI1_MCLK (_MX51_PAD_CSI1_MCLK__CSI1_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D12__CSI2_D12 (_MX51_PAD_CSI2_D12__CSI2_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D12__GPIO4_9 (_MX51_PAD_CSI2_D12__GPIO4_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D13__CSI2_D13 (_MX51_PAD_CSI2_D13__CSI2_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D13__GPIO4_10 (_MX51_PAD_CSI2_D13__GPIO4_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D14__CSI2_D14 (_MX51_PAD_CSI2_D14__CSI2_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D15__CSI2_D15 (_MX51_PAD_CSI2_D15__CSI2_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D16__CSI2_D16 (_MX51_PAD_CSI2_D16__CSI2_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D17__CSI2_D17 (_MX51_PAD_CSI2_D17__CSI2_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D18__CSI2_D18 (_MX51_PAD_CSI2_D18__CSI2_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D18__GPIO4_11 (_MX51_PAD_CSI2_D18__GPIO4_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D19__CSI2_D19 (_MX51_PAD_CSI2_D19__CSI2_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D19__GPIO4_12 (_MX51_PAD_CSI2_D19__GPIO4_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC (_MX51_PAD_CSI2_VSYNC__CSI2_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_VSYNC__GPIO4_13 (_MX51_PAD_CSI2_VSYNC__GPIO4_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC (_MX51_PAD_CSI2_HSYNC__CSI2_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_HSYNC__GPIO4_14 (_MX51_PAD_CSI2_HSYNC__GPIO4_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK (_MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_PIXCLK__GPIO4_15 (_MX51_PAD_CSI2_PIXCLK__GPIO4_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_CLK__GPIO4_16 (_MX51_PAD_I2C1_CLK__GPIO4_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_CLK__I2C1_CLK (_MX51_PAD_I2C1_CLK__I2C1_CLK | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_I2C1_DAT__GPIO4_17 (_MX51_PAD_I2C1_DAT__GPIO4_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_DAT__I2C1_DAT (_MX51_PAD_I2C1_DAT__I2C1_DAT | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD (_MX51_PAD_AUD3_BB_TXD__AUD3_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_TXD__GPIO4_18 (_MX51_PAD_AUD3_BB_TXD__GPIO4_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD (_MX51_PAD_AUD3_BB_RXD__AUD3_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__GPIO4_19 (_MX51_PAD_AUD3_BB_RXD__GPIO4_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__UART3_RXD (_MX51_PAD_AUD3_BB_RXD__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_CK__AUD3_TXC (_MX51_PAD_AUD3_BB_CK__AUD3_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_CK__GPIO4_20 (_MX51_PAD_AUD3_BB_CK__GPIO4_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS (_MX51_PAD_AUD3_BB_FS__AUD3_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__GPIO4_21 (_MX51_PAD_AUD3_BB_FS__GPIO4_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__UART3_TXD (_MX51_PAD_AUD3_BB_FS__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI (_MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__GPIO4_22 (_MX51_PAD_CSPI1_MOSI__GPIO4_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__I2C1_SDA (_MX51_PAD_CSPI1_MOSI__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__AUD4_RXD (_MX51_PAD_CSPI1_MISO__AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO (_MX51_PAD_CSPI1_MISO__ECSPI1_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__GPIO4_23 (_MX51_PAD_CSPI1_MISO__GPIO4_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__AUD4_TXC (_MX51_PAD_CSPI1_SS0__AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0 (_MX51_PAD_CSPI1_SS0__ECSPI1_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__GPIO4_24 (_MX51_PAD_CSPI1_SS0__GPIO4_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__AUD4_TXD (_MX51_PAD_CSPI1_SS1__AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1 (_MX51_PAD_CSPI1_SS1__ECSPI1_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__GPIO4_25 (_MX51_PAD_CSPI1_SS1__GPIO4_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__AUD4_TXFS (_MX51_PAD_CSPI1_RDY__AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY (_MX51_PAD_CSPI1_RDY__ECSPI1_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__GPIO4_26 (_MX51_PAD_CSPI1_RDY__GPIO4_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK (_MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__GPIO4_27 (_MX51_PAD_CSPI1_SCLK__GPIO4_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__I2C1_SCL (_MX51_PAD_CSPI1_SCLK__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_UART1_RXD__GPIO4_28 (_MX51_PAD_UART1_RXD__GPIO4_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_RXD__UART1_RXD (_MX51_PAD_UART1_RXD__UART1_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__GPIO4_29 (_MX51_PAD_UART1_TXD__GPIO4_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__PWM2_PWMO (_MX51_PAD_UART1_TXD__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__UART1_TXD (_MX51_PAD_UART1_TXD__UART1_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_RTS__GPIO4_30 (_MX51_PAD_UART1_RTS__GPIO4_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_RTS__UART1_RTS (_MX51_PAD_UART1_RTS__UART1_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_CTS__GPIO4_31 (_MX51_PAD_UART1_CTS__GPIO4_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_CTS__UART1_CTS (_MX51_PAD_UART1_CTS__UART1_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__FIRI_TXD (_MX51_PAD_UART2_RXD__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__GPIO1_20 (_MX51_PAD_UART2_RXD__GPIO1_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__UART2_RXD (_MX51_PAD_UART2_RXD__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__FIRI_RXD (_MX51_PAD_UART2_TXD__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__GPIO1_21 (_MX51_PAD_UART2_TXD__GPIO1_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__UART2_TXD (_MX51_PAD_UART2_TXD__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__CSI1_D0 (_MX51_PAD_UART3_RXD__CSI1_D0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__GPIO1_22 (_MX51_PAD_UART3_RXD__GPIO1_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__UART1_DTR (_MX51_PAD_UART3_RXD__UART1_DTR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__UART3_RXD (_MX51_PAD_UART3_RXD__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__CSI1_D1 (_MX51_PAD_UART3_TXD__CSI1_D1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__GPIO1_23 (_MX51_PAD_UART3_TXD__GPIO1_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__UART1_DSR (_MX51_PAD_UART3_TXD__UART1_DSR | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__UART3_TXD (_MX51_PAD_UART3_TXD__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__GPIO1_24 (_MX51_PAD_OWIRE_LINE__GPIO1_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__OWIRE_LINE (_MX51_PAD_OWIRE_LINE__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__SPDIF_OUT (_MX51_PAD_OWIRE_LINE__SPDIF_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW0__KEY_ROW0 (_MX51_PAD_KEY_ROW0__KEY_ROW0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW1__KEY_ROW1 (_MX51_PAD_KEY_ROW1__KEY_ROW1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW2__KEY_ROW2 (_MX51_PAD_KEY_ROW2__KEY_ROW2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW3__KEY_ROW3 (_MX51_PAD_KEY_ROW3__KEY_ROW3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL0__KEY_COL0 (_MX51_PAD_KEY_COL0__KEY_COL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL0__PLL1_BYP (_MX51_PAD_KEY_COL0__PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL1__KEY_COL1 (_MX51_PAD_KEY_COL1__KEY_COL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL1__PLL2_BYP (_MX51_PAD_KEY_COL1__PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL2__KEY_COL2 (_MX51_PAD_KEY_COL2__KEY_COL2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL2__PLL3_BYP (_MX51_PAD_KEY_COL2__PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL3__KEY_COL3 (_MX51_PAD_KEY_COL3__KEY_COL3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__I2C2_SCL (_MX51_PAD_KEY_COL4__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__KEY_COL4 (_MX51_PAD_KEY_COL4__KEY_COL4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__SPDIF_OUT1 (_MX51_PAD_KEY_COL4__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__UART1_RI (_MX51_PAD_KEY_COL4__UART1_RI | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__UART3_RTS (_MX51_PAD_KEY_COL4__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__I2C2_SDA (_MX51_PAD_KEY_COL5__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__KEY_COL5 (_MX51_PAD_KEY_COL5__KEY_COL5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__UART1_DCD (_MX51_PAD_KEY_COL5__UART1_DCD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__UART3_CTS (_MX51_PAD_KEY_COL5__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__CSPI_SCLK (_MX51_PAD_USBH1_CLK__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__GPIO1_25 (_MX51_PAD_USBH1_CLK__GPIO1_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__I2C2_SCL (_MX51_PAD_USBH1_CLK__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__USBH1_CLK (_MX51_PAD_USBH1_CLK__USBH1_CLK | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__CSPI_MOSI (_MX51_PAD_USBH1_DIR__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__GPIO1_26 (_MX51_PAD_USBH1_DIR__GPIO1_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__I2C2_SDA (_MX51_PAD_USBH1_DIR__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__USBH1_DIR (_MX51_PAD_USBH1_DIR__USBH1_DIR | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__CSPI_RDY (_MX51_PAD_USBH1_STP__CSPI_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__GPIO1_27 (_MX51_PAD_USBH1_STP__GPIO1_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__UART3_RXD (_MX51_PAD_USBH1_STP__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__USBH1_STP (_MX51_PAD_USBH1_STP__USBH1_STP | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__CSPI_MISO (_MX51_PAD_USBH1_NXT__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__GPIO1_28 (_MX51_PAD_USBH1_NXT__GPIO1_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__UART3_TXD (_MX51_PAD_USBH1_NXT__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__USBH1_NXT (_MX51_PAD_USBH1_NXT__USBH1_NXT | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__GPIO1_11 (_MX51_PAD_USBH1_DATA0__GPIO1_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__UART2_CTS (_MX51_PAD_USBH1_DATA0__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__USBH1_DATA0 (_MX51_PAD_USBH1_DATA0__USBH1_DATA0 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__GPIO1_12 (_MX51_PAD_USBH1_DATA1__GPIO1_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__UART2_RXD (_MX51_PAD_USBH1_DATA1__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__USBH1_DATA1 (_MX51_PAD_USBH1_DATA1__USBH1_DATA1 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__GPIO1_13 (_MX51_PAD_USBH1_DATA2__GPIO1_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__UART2_TXD (_MX51_PAD_USBH1_DATA2__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__USBH1_DATA2 (_MX51_PAD_USBH1_DATA2__USBH1_DATA2 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__GPIO1_14 (_MX51_PAD_USBH1_DATA3__GPIO1_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__UART2_RTS (_MX51_PAD_USBH1_DATA3__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__USBH1_DATA3 (_MX51_PAD_USBH1_DATA3__USBH1_DATA3 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__CSPI_SS0 (_MX51_PAD_USBH1_DATA4__CSPI_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__GPIO1_15 (_MX51_PAD_USBH1_DATA4__GPIO1_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__USBH1_DATA4 (_MX51_PAD_USBH1_DATA4__USBH1_DATA4 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__CSPI_SS1 (_MX51_PAD_USBH1_DATA5__CSPI_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__GPIO1_16 (_MX51_PAD_USBH1_DATA5__GPIO1_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__USBH1_DATA5 (_MX51_PAD_USBH1_DATA5__USBH1_DATA5 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__CSPI_SS3 (_MX51_PAD_USBH1_DATA6__CSPI_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__GPIO1_17 (_MX51_PAD_USBH1_DATA6__GPIO1_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__USBH1_DATA6 (_MX51_PAD_USBH1_DATA6__USBH1_DATA6 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3 (_MX51_PAD_USBH1_DATA7__ECSPI1_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3 (_MX51_PAD_USBH1_DATA7__ECSPI2_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__GPIO1_18 (_MX51_PAD_USBH1_DATA7__GPIO1_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__USBH1_DATA7 (_MX51_PAD_USBH1_DATA7__USBH1_DATA7 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__DI1_PIN11 (_MX51_PAD_DI1_PIN11__DI1_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__ECSPI1_SS2 (_MX51_PAD_DI1_PIN11__ECSPI1_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__GPIO3_0 (_MX51_PAD_DI1_PIN11__GPIO3_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN12__DI1_PIN12 (_MX51_PAD_DI1_PIN12__DI1_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN12__GPIO3_1 (_MX51_PAD_DI1_PIN12__GPIO3_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN13__DI1_PIN13 (_MX51_PAD_DI1_PIN13__DI1_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN13__GPIO3_2 (_MX51_PAD_DI1_PIN13__GPIO3_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_D0_CS__DI1_D0_CS (_MX51_PAD_DI1_D0_CS__DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D0_CS__GPIO3_3 (_MX51_PAD_DI1_D0_CS__GPIO3_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DI1_D1_CS (_MX51_PAD_DI1_D1_CS__DI1_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN14 (_MX51_PAD_DI1_D1_CS__DISP1_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN5 (_MX51_PAD_DI1_D1_CS__DISP1_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__GPIO3_4 (_MX51_PAD_DI1_D1_CS__GPIO3_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 (_MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN (_MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5 (_MX51_PAD_DISPB2_SER_DIN__GPIO3_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 (_MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO (_MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6 (_MX51_PAD_DISPB2_SER_DIO__GPIO3_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 (_MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 (_MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK (_MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7 (_MX51_PAD_DISPB2_SER_CLK__GPIO3_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK (_MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 (_MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 (_MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS (_MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS (_MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__GPIO3_8 (_MX51_PAD_DISPB2_SER_RS__GPIO3_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT0__DISP1_DAT0 (_MX51_PAD_DISP1_DAT0__DISP1_DAT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT1__DISP1_DAT1 (_MX51_PAD_DISP1_DAT1__DISP1_DAT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT2__DISP1_DAT2 (_MX51_PAD_DISP1_DAT2__DISP1_DAT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT3__DISP1_DAT3 (_MX51_PAD_DISP1_DAT3__DISP1_DAT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT4__DISP1_DAT4 (_MX51_PAD_DISP1_DAT4__DISP1_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT5__DISP1_DAT5 (_MX51_PAD_DISP1_DAT5__DISP1_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC (_MX51_PAD_DISP1_DAT6__BOOT_USB_SRC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT6__DISP1_DAT6 (_MX51_PAD_DISP1_DAT6__DISP1_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG (_MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT7__DISP1_DAT7 (_MX51_PAD_DISP1_DAT7__DISP1_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT8__BOOT_SRC0 (_MX51_PAD_DISP1_DAT8__BOOT_SRC0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT8__DISP1_DAT8 (_MX51_PAD_DISP1_DAT8__DISP1_DAT8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT9__BOOT_SRC1 (_MX51_PAD_DISP1_DAT9__BOOT_SRC1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT9__DISP1_DAT9 (_MX51_PAD_DISP1_DAT9__DISP1_DAT9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE (_MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT10__DISP1_DAT10 (_MX51_PAD_DISP1_DAT10__DISP1_DAT10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 (_MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT11__DISP1_DAT11 (_MX51_PAD_DISP1_DAT11__DISP1_DAT11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL (_MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT12__DISP1_DAT12 (_MX51_PAD_DISP1_DAT12__DISP1_DAT12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 (_MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT13__DISP1_DAT13 (_MX51_PAD_DISP1_DAT13__DISP1_DAT13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 (_MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT14__DISP1_DAT14 (_MX51_PAD_DISP1_DAT14__DISP1_DAT14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH (_MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT15__DISP1_DAT15 (_MX51_PAD_DISP1_DAT15__DISP1_DAT15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 (_MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT16__DISP1_DAT16 (_MX51_PAD_DISP1_DAT16__DISP1_DAT16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 (_MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT17__DISP1_DAT17 (_MX51_PAD_DISP1_DAT17__DISP1_DAT17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 (_MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP1_DAT18 (_MX51_PAD_DISP1_DAT18__DISP1_DAT18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN11 (_MX51_PAD_DISP1_DAT18__DISP2_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN5 (_MX51_PAD_DISP1_DAT18__DISP2_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 (_MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP1_DAT19 (_MX51_PAD_DISP1_DAT19__DISP1_DAT19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN12 (_MX51_PAD_DISP1_DAT19__DISP2_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN6 (_MX51_PAD_DISP1_DAT19__DISP2_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 (_MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP1_DAT20 (_MX51_PAD_DISP1_DAT20__DISP1_DAT20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN13 (_MX51_PAD_DISP1_DAT20__DISP2_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN7 (_MX51_PAD_DISP1_DAT20__DISP2_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 (_MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP1_DAT21 (_MX51_PAD_DISP1_DAT21__DISP1_DAT21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN14 (_MX51_PAD_DISP1_DAT21__DISP2_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN8 (_MX51_PAD_DISP1_DAT21__DISP2_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 (_MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP1_DAT22 (_MX51_PAD_DISP1_DAT22__DISP1_DAT22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS (_MX51_PAD_DISP1_DAT22__DISP2_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP2_DAT16 (_MX51_PAD_DISP1_DAT22__DISP2_DAT16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 (_MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP1_DAT23 (_MX51_PAD_DISP1_DAT23__DISP1_DAT23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS (_MX51_PAD_DISP1_DAT23__DISP2_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_DAT17 (_MX51_PAD_DISP1_DAT23__DISP2_DAT17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS (_MX51_PAD_DISP1_DAT23__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN3__DI1_PIN3 (_MX51_PAD_DI1_PIN3__DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN2__DI1_PIN2 (_MX51_PAD_DI1_PIN2__DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP2__DISP1_SER_CLK (_MX51_PAD_DI_GP2__DISP1_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP2__DISP2_WAIT (_MX51_PAD_DI_GP2__DISP2_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__CSI1_DATA_EN (_MX51_PAD_DI_GP3__CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__DISP1_SER_DIO (_MX51_PAD_DI_GP3__DISP1_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__FEC_TX_ER (_MX51_PAD_DI_GP3__FEC_TX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN (_MX51_PAD_DI2_PIN4__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN4__DI2_PIN4 (_MX51_PAD_DI2_PIN4__DI2_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN4__FEC_CRS (_MX51_PAD_DI2_PIN4__FEC_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN2__DI2_PIN2 (_MX51_PAD_DI2_PIN2__DI2_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN2__FEC_MDC (_MX51_PAD_DI2_PIN2__FEC_MDC | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DI2_PIN3__DI2_PIN3 (_MX51_PAD_DI2_PIN3__DI2_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN3__FEC_MDIO (_MX51_PAD_DI2_PIN3__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK (_MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 (_MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DI2_PIN15 (_MX51_PAD_DI_GP4__DI2_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DISP1_SER_DIN (_MX51_PAD_DI_GP4__DISP1_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DISP2_PIN1 (_MX51_PAD_DI_GP4__DISP2_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__FEC_RDATA2 (_MX51_PAD_DI_GP4__FEC_RDATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__DISP2_DAT0 (_MX51_PAD_DISP2_DAT0__DISP2_DAT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__FEC_RDATA3 (_MX51_PAD_DISP2_DAT0__FEC_RDATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__KEY_COL6 (_MX51_PAD_DISP2_DAT0__KEY_COL6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__UART3_RXD (_MX51_PAD_DISP2_DAT0__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__USBH3_CLK (_MX51_PAD_DISP2_DAT0__USBH3_CLK | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__DISP2_DAT1 (_MX51_PAD_DISP2_DAT1__DISP2_DAT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__FEC_RX_ER (_MX51_PAD_DISP2_DAT1__FEC_RX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__KEY_COL7 (_MX51_PAD_DISP2_DAT1__KEY_COL7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__UART3_TXD (_MX51_PAD_DISP2_DAT1__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__USBH3_DIR (_MX51_PAD_DISP2_DAT1__USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT2__DISP2_DAT2 (_MX51_PAD_DISP2_DAT2__DISP2_DAT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT3__DISP2_DAT3 (_MX51_PAD_DISP2_DAT3__DISP2_DAT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT4__DISP2_DAT4 (_MX51_PAD_DISP2_DAT4__DISP2_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT5__DISP2_DAT5 (_MX51_PAD_DISP2_DAT5__DISP2_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__DISP2_DAT6 (_MX51_PAD_DISP2_DAT6__DISP2_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__FEC_TDATA1 (_MX51_PAD_DISP2_DAT6__FEC_TDATA1 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT6__GPIO1_19 (_MX51_PAD_DISP2_DAT6__GPIO1_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__KEY_ROW4 (_MX51_PAD_DISP2_DAT6__KEY_ROW4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__USBH3_STP (_MX51_PAD_DISP2_DAT6__USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__DISP2_DAT7 (_MX51_PAD_DISP2_DAT7__DISP2_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__FEC_TDATA2 (_MX51_PAD_DISP2_DAT7__FEC_TDATA2 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT7__GPIO1_29 (_MX51_PAD_DISP2_DAT7__GPIO1_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__KEY_ROW5 (_MX51_PAD_DISP2_DAT7__KEY_ROW5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__USBH3_NXT (_MX51_PAD_DISP2_DAT7__USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__DISP2_DAT8 (_MX51_PAD_DISP2_DAT8__DISP2_DAT8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__FEC_TDATA3 (_MX51_PAD_DISP2_DAT8__FEC_TDATA3 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT8__GPIO1_30 (_MX51_PAD_DISP2_DAT8__GPIO1_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__KEY_ROW6 (_MX51_PAD_DISP2_DAT8__KEY_ROW6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__USBH3_DATA0 (_MX51_PAD_DISP2_DAT8__USBH3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__AUD6_RXC (_MX51_PAD_DISP2_DAT9__AUD6_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__DISP2_DAT9 (_MX51_PAD_DISP2_DAT9__DISP2_DAT9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__FEC_TX_EN (_MX51_PAD_DISP2_DAT9__FEC_TX_EN | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT9__GPIO1_31 (_MX51_PAD_DISP2_DAT9__GPIO1_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__USBH3_DATA1 (_MX51_PAD_DISP2_DAT9__USBH3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__DISP2_DAT10 (_MX51_PAD_DISP2_DAT10__DISP2_DAT10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS (_MX51_PAD_DISP2_DAT10__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__FEC_COL (_MX51_PAD_DISP2_DAT10__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__KEY_ROW7 (_MX51_PAD_DISP2_DAT10__KEY_ROW7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__USBH3_DATA2 (_MX51_PAD_DISP2_DAT10__USBH3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__AUD6_TXD (_MX51_PAD_DISP2_DAT11__AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__DISP2_DAT11 (_MX51_PAD_DISP2_DAT11__DISP2_DAT11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK (_MX51_PAD_DISP2_DAT11__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__GPIO1_10 (_MX51_PAD_DISP2_DAT11__GPIO1_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__USBH3_DATA3 (_MX51_PAD_DISP2_DAT11__USBH3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__AUD6_RXD (_MX51_PAD_DISP2_DAT12__AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__DISP2_DAT12 (_MX51_PAD_DISP2_DAT12__DISP2_DAT12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__FEC_RX_DV (_MX51_PAD_DISP2_DAT12__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__USBH3_DATA4 (_MX51_PAD_DISP2_DAT12__USBH3_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__AUD6_TXC (_MX51_PAD_DISP2_DAT13__AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__DISP2_DAT13 (_MX51_PAD_DISP2_DAT13__DISP2_DAT13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK (_MX51_PAD_DISP2_DAT13__FEC_TX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_DISP2_DAT13__USBH3_DATA5 (_MX51_PAD_DISP2_DAT13__USBH3_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__AUD6_TXFS (_MX51_PAD_DISP2_DAT14__AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__DISP2_DAT14 (_MX51_PAD_DISP2_DAT14__DISP2_DAT14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__FEC_RDATA0 (_MX51_PAD_DISP2_DAT14__FEC_RDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_DISP2_DAT14__USBH3_DATA6 (_MX51_PAD_DISP2_DAT14__USBH3_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__AUD6_RXFS (_MX51_PAD_DISP2_DAT15__AUD6_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS (_MX51_PAD_DISP2_DAT15__DISP1_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__DISP2_DAT15 (_MX51_PAD_DISP2_DAT15__DISP2_DAT15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__FEC_TDATA0 (_MX51_PAD_DISP2_DAT15__FEC_TDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT15__USBH3_DATA7 (_MX51_PAD_DISP2_DAT15__USBH3_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__AUD5_RXFS (_MX51_PAD_SD1_CMD__AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__CSPI_MOSI (_MX51_PAD_SD1_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__SD1_CMD (_MX51_PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__AUD5_RXC (_MX51_PAD_SD1_CLK__AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__CSPI_SCLK (_MX51_PAD_SD1_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__SD1_CLK (_MX51_PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_SD1_DATA0__AUD5_TXD (_MX51_PAD_SD1_DATA0__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA0__CSPI_MISO (_MX51_PAD_SD1_DATA0__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD1_DATA0__SD1_DATA0 (_MX51_PAD_SD1_DATA0__SD1_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_EIM_DA0__EIM_DA0 (_MX51_PAD_EIM_DA0__EIM_DA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA1__EIM_DA1 (_MX51_PAD_EIM_DA1__EIM_DA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA2__EIM_DA2 (_MX51_PAD_EIM_DA2__EIM_DA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA3__EIM_DA3 (_MX51_PAD_EIM_DA3__EIM_DA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA1__AUD5_RXD (_MX51_PAD_SD1_DATA1__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA1__SD1_DATA1 (_MX51_PAD_SD1_DATA1__SD1_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_EIM_DA4__EIM_DA4 (_MX51_PAD_EIM_DA4__EIM_DA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA5__EIM_DA5 (_MX51_PAD_EIM_DA5__EIM_DA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA6__EIM_DA6 (_MX51_PAD_EIM_DA6__EIM_DA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA7__EIM_DA7 (_MX51_PAD_EIM_DA7__EIM_DA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA2__AUD5_TXC (_MX51_PAD_SD1_DATA2__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA2__SD1_DATA2 (_MX51_PAD_SD1_DATA2__SD1_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_EIM_DA10__EIM_DA10 (_MX51_PAD_EIM_DA10__EIM_DA10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA11__EIM_DA11 (_MX51_PAD_EIM_DA11__EIM_DA11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA8__EIM_DA8 (_MX51_PAD_EIM_DA8__EIM_DA8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA9__EIM_DA9 (_MX51_PAD_EIM_DA9__EIM_DA9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__AUD5_TXFS (_MX51_PAD_SD1_DATA3__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__CSPI_SS1 (_MX51_PAD_SD1_DATA3__CSPI_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__SD1_DATA3 (_MX51_PAD_SD1_DATA3__SD1_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_GPIO1_0__CSPI_SS2 (_MX51_PAD_GPIO1_0__CSPI_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_GPIO1_0__GPIO1_0 (_MX51_PAD_GPIO1_0__GPIO1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_0__SD1_CD (_MX51_PAD_GPIO1_0__SD1_CD | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__CSPI_MISO (_MX51_PAD_GPIO1_1__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__GPIO1_1 (_MX51_PAD_GPIO1_1__GPIO1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__SD1_WP (_MX51_PAD_GPIO1_1__SD1_WP | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_EIM_DA12__EIM_DA12 (_MX51_PAD_EIM_DA12__EIM_DA12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA13__EIM_DA13 (_MX51_PAD_EIM_DA13__EIM_DA13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA14__EIM_DA14 (_MX51_PAD_EIM_DA14__EIM_DA14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA15__EIM_DA15 (_MX51_PAD_EIM_DA15__EIM_DA15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__CSPI_MOSI (_MX51_PAD_SD2_CMD__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__I2C1_SCL (_MX51_PAD_SD2_CMD__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__SD2_CMD (_MX51_PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__CSPI_SCLK (_MX51_PAD_SD2_CLK__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__I2C1_SDA (_MX51_PAD_SD2_CLK__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__SD2_CLK (_MX51_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_SD2_DATA0__CSPI_MISO (_MX51_PAD_SD2_DATA0__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA0__SD1_DAT4 (_MX51_PAD_SD2_DATA0__SD1_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA0__SD2_DATA0 (_MX51_PAD_SD2_DATA0__SD2_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__SD1_DAT5 (_MX51_PAD_SD2_DATA1__SD1_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__SD2_DATA1 (_MX51_PAD_SD2_DATA1__SD2_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__USBH3_H2_DP (_MX51_PAD_SD2_DATA1__USBH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__SD1_DAT6 (_MX51_PAD_SD2_DATA2__SD1_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__SD2_DATA2 (_MX51_PAD_SD2_DATA2__SD2_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__USBH3_H2_DM (_MX51_PAD_SD2_DATA2__USBH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__CSPI_SS2 (_MX51_PAD_SD2_DATA3__CSPI_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__SD1_DAT7 (_MX51_PAD_SD2_DATA3__SD1_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__SD2_DATA3 (_MX51_PAD_SD2_DATA3__SD2_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__CCM_OUT_2 (_MX51_PAD_GPIO1_2__CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__GPIO1_2 (_MX51_PAD_GPIO1_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__I2C2_SCL (_MX51_PAD_GPIO1_2__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__PLL1_BYP (_MX51_PAD_GPIO1_2__PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__PWM1_PWMO (_MX51_PAD_GPIO1_2__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__GPIO1_3 (_MX51_PAD_GPIO1_3__GPIO1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__I2C2_SDA (_MX51_PAD_GPIO1_3__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__PLL2_BYP (_MX51_PAD_GPIO1_3__PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__PWM2_PWMO (_MX51_PAD_GPIO1_3__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ (_MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B (_MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK (_MX51_PAD_GPIO1_4__DISP2_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__EIM_RDY (_MX51_PAD_GPIO1_4__EIM_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__GPIO1_4 (_MX51_PAD_GPIO1_4__GPIO1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B (_MX51_PAD_GPIO1_4__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__CSI2_MCLK (_MX51_PAD_GPIO1_5__CSI2_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__DISP2_PIN16 (_MX51_PAD_GPIO1_5__DISP2_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__GPIO1_5 (_MX51_PAD_GPIO1_5__GPIO1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B (_MX51_PAD_GPIO1_5__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__DISP2_PIN17 (_MX51_PAD_GPIO1_6__DISP2_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__GPIO1_6 (_MX51_PAD_GPIO1_6__GPIO1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__REF_EN_B (_MX51_PAD_GPIO1_6__REF_EN_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__CCM_OUT_0 (_MX51_PAD_GPIO1_7__CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__GPIO1_7 (_MX51_PAD_GPIO1_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__SD2_WP (_MX51_PAD_GPIO1_7__SD2_WP | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__SPDIF_OUT1 (_MX51_PAD_GPIO1_7__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__CSI2_DATA_EN (_MX51_PAD_GPIO1_8__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__GPIO1_8 (_MX51_PAD_GPIO1_8__GPIO1_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__SD2_CD (_MX51_PAD_GPIO1_8__SD2_CD | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__USBH3_PWR (_MX51_PAD_GPIO1_8__USBH3_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__CCM_OUT_1 (_MX51_PAD_GPIO1_9__CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__DISP2_D1_CS (_MX51_PAD_GPIO1_9__DISP2_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__DISP2_SER_CS (_MX51_PAD_GPIO1_9__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__GPIO1_9 (_MX51_PAD_GPIO1_9__GPIO1_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__SD2_LCTL (_MX51_PAD_GPIO1_9__SD2_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__USBH3_OC (_MX51_PAD_GPIO1_9__USBH3_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_EIM_EB2__GPIO2_22 IOMUX_PAD(0x468, 0x0d4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__GPT_CMPOUT1 IOMUX_PAD(0x468, 0x0d4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__AUD5_RXC IOMUX_PAD(0x46c, 0x0d8, 6, 0x8dc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__CSI1_D3 IOMUX_PAD(0x46c, 0x0d8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__EIM_EB3 IOMUX_PAD(0x46c, 0x0d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__FEC_RDATA1 IOMUX_PAD(0x46c, 0x0d8, 3, 0x95c, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__GPIO2_23 IOMUX_PAD(0x46c, 0x0d8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__GPT_CMPOUT2 IOMUX_PAD(0x46c, 0x0d8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_OE__EIM_OE IOMUX_PAD(0x470, 0x0dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_OE__GPIO2_24 IOMUX_PAD(0x470, 0x0dc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS0__EIM_CS0 IOMUX_PAD(0x474, 0x0e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS0__GPIO2_25 IOMUX_PAD(0x474, 0x0e0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS1__EIM_CS1 IOMUX_PAD(0x478, 0x0e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS1__GPIO2_26 IOMUX_PAD(0x478, 0x0e4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__AUD5_TXD IOMUX_PAD(0x47c, 0x0e8, 6, 0x8d8, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__CSI1_D4 IOMUX_PAD(0x47c, 0x0e8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__EIM_CS2 IOMUX_PAD(0x47c, 0x0e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__FEC_RDATA2 IOMUX_PAD(0x47c, 0x0e8, 3, 0x960, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__GPIO2_27 IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__USBOTG_STP IOMUX_PAD(0x47c, 0x0e8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__AUD5_RXD IOMUX_PAD(0x480, 0x0ec, 6, 0x8d4, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__CSI1_D5 IOMUX_PAD(0x480, 0x0ec, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__EIM_CS3 IOMUX_PAD(0x480, 0x0ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__FEC_RDATA3 IOMUX_PAD(0x480, 0x0ec, 3, 0x964, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__GPIO2_28 IOMUX_PAD(0x480, 0x0ec, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__USBOTG_NXT IOMUX_PAD(0x480, 0x0ec, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__AUD5_TXC IOMUX_PAD(0x484, 0x0f0, 6, 0x8e4, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__CSI1_D6 IOMUX_PAD(0x484, 0x0f0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__EIM_CS4 IOMUX_PAD(0x484, 0x0f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__FEC_RX_ER IOMUX_PAD(0x484, 0x0f0, 3, 0x970, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_EIM_CS4__GPIO2_29 IOMUX_PAD(0x484, 0x0f0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__USBOTG_CLK IOMUX_PAD(0x484, 0x0f0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__AUD5_TXFS IOMUX_PAD(0x488, 0x0f4, 6, 0x8e8, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__CSI1_D7 IOMUX_PAD(0x488, 0x0f4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK IOMUX_PAD(0x488, 0x0f4, 4, 0x904, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__EIM_CS5 IOMUX_PAD(0x488, 0x0f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__FEC_CRS IOMUX_PAD(0x488, 0x0f4, 3, 0x950, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_EIM_CS5__GPIO2_30 IOMUX_PAD(0x488, 0x0f4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__USBOTG_DIR IOMUX_PAD(0x488, 0x0f4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DTACK__EIM_DTACK IOMUX_PAD(0x48c, 0x0f8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DTACK__GPIO2_31 IOMUX_PAD(0x48c, 0x0f8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_LBA__EIM_LBA IOMUX_PAD(0x494, 0x0fc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_LBA__GPIO3_1 IOMUX_PAD(0x494, 0x0fc, 1, 0x978, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CRE__EIM_CRE IOMUX_PAD(0x4a0, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CRE__GPIO3_2 IOMUX_PAD(0x4a0, 0x100, 1, 0x97c, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DRAM_CS1__DRAM_CS1 IOMUX_PAD(0x4d0, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__GPIO3_3 IOMUX_PAD(0x4e4, 0x108, 3, 0x980, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__NANDF_WE_B IOMUX_PAD(0x4e4, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__PATA_DIOW IOMUX_PAD(0x4e4, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__SD3_DATA0 IOMUX_PAD(0x4e4, 0x108, 2, 0x93c, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__GPIO3_4 IOMUX_PAD(0x4e8, 0x10c, 3, 0x984, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__NANDF_RE_B IOMUX_PAD(0x4e8, 0x10c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__PATA_DIOR IOMUX_PAD(0x4e8, 0x10c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__SD3_DATA1 IOMUX_PAD(0x4e8, 0x10c, 2, 0x940, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__GPIO3_5 IOMUX_PAD(0x4ec, 0x110, 3, 0x988, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__NANDF_ALE IOMUX_PAD(0x4ec, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN IOMUX_PAD(0x4ec, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__GPIO3_6 IOMUX_PAD(0x4f0, 0x114, 3, 0x98c, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__NANDF_CLE IOMUX_PAD(0x4f0, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__PATA_RESET_B IOMUX_PAD(0x4f0, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__GPIO3_7 IOMUX_PAD(0x4f4, 0x118, 3, 0x990, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__NANDF_WP_B IOMUX_PAD(0x4f4, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__PATA_DMACK IOMUX_PAD(0x4f4, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__SD3_DATA2 IOMUX_PAD(0x4f4, 0x118, 2, 0x944, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__ECSPI2_SS1 IOMUX_PAD(0x4f8, 0x11c, 5, 0x930, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__GPIO3_8 IOMUX_PAD(0x4f8, 0x11c, 3, 0x994, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__NANDF_RB0 IOMUX_PAD(0x4f8, 0x11c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__PATA_DMARQ IOMUX_PAD(0x4f8, 0x11c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__SD3_DATA3 IOMUX_PAD(0x4f8, 0x11c, 2, 0x948, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__CSPI_MOSI IOMUX_PAD(0x4fc, 0x120, 6, 0x91c, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__ECSPI2_RDY IOMUX_PAD(0x4fc, 0x120, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__GPIO3_9 IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__NANDF_RB1 IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__PATA_IORDY IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__SD4_CMD IOMUX_PAD(0x4fc, 0x120, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__DISP2_WAIT IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__FEC_COL IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB2__GPIO3_10 IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__NANDF_RB2 IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_H3_DP IOMUX_PAD(0x500, 0x124, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_NXT IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__DISP1_WAIT IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__ECSPI2_MISO IOMUX_PAD(0x504, 0x128, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__FEC_RX_CLK IOMUX_PAD(0x504, 0x128, 1, 0x968, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB3__GPIO3_11 IOMUX_PAD(0x504, 0x128, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__NANDF_RB3 IOMUX_PAD(0x504, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_CLK IOMUX_PAD(0x504, 0x128, 6, 0x9f8, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_H3_DM IOMUX_PAD(0x504, 0x128, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_NAND__GPIO_NAND IOMUX_PAD(0x514, 0x12c, 0, 0x998, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_NAND__PATA_INTRQ IOMUX_PAD(0x514, 0x12c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS0__GPIO3_16 IOMUX_PAD(0x518, 0x130, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS0__NANDF_CS0 IOMUX_PAD(0x518, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS1__GPIO3_17 IOMUX_PAD(0x51c, 0x134, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS1__NANDF_CS1 IOMUX_PAD(0x51c, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__CSPI_SCLK IOMUX_PAD(0x520, 0x138, 6, 0x914, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__FEC_TX_ER IOMUX_PAD(0x520, 0x138, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS2__GPIO3_18 IOMUX_PAD(0x520, 0x138, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__NANDF_CS2 IOMUX_PAD(0x520, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__PATA_CS_0 IOMUX_PAD(0x520, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__SD4_CLK IOMUX_PAD(0x520, 0x138, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_NANDF_CS2__USBH3_H1_DP IOMUX_PAD(0x520, 0x138, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__FEC_MDC IOMUX_PAD(0x524, 0x13c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS3__GPIO3_19 IOMUX_PAD(0x524, 0x13c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__NANDF_CS3 IOMUX_PAD(0x524, 0x13c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__PATA_CS_1 IOMUX_PAD(0x524, 0x13c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__SD4_DAT0 IOMUX_PAD(0x524, 0x13c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__USBH3_H1_DM IOMUX_PAD(0x524, 0x13c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__FEC_TDATA1 IOMUX_PAD(0x528, 0x140, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS4__GPIO3_20 IOMUX_PAD(0x528, 0x140, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__NANDF_CS4 IOMUX_PAD(0x528, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__PATA_DA_0 IOMUX_PAD(0x528, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__SD4_DAT1 IOMUX_PAD(0x528, 0x140, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__USBH3_STP IOMUX_PAD(0x528, 0x140, 7, 0xa24, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__FEC_TDATA2 IOMUX_PAD(0x52c, 0x144, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS5__GPIO3_21 IOMUX_PAD(0x52c, 0x144, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__NANDF_CS5 IOMUX_PAD(0x52c, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__PATA_DA_1 IOMUX_PAD(0x52c, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__SD4_DAT2 IOMUX_PAD(0x52c, 0x144, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__USBH3_DIR IOMUX_PAD(0x52c, 0x144, 7, 0xa1c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__CSPI_SS3 IOMUX_PAD(0x530, 0x148, 7, 0x928, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__FEC_TDATA3 IOMUX_PAD(0x530, 0x148, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS6__GPIO3_22 IOMUX_PAD(0x530, 0x148, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__NANDF_CS6 IOMUX_PAD(0x530, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__PATA_DA_2 IOMUX_PAD(0x530, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__SD4_DAT3 IOMUX_PAD(0x530, 0x148, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__FEC_TX_EN IOMUX_PAD(0x534, 0x14c, 1, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS7__GPIO3_23 IOMUX_PAD(0x534, 0x14c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__NANDF_CS7 IOMUX_PAD(0x534, 0x14c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__SD3_CLK IOMUX_PAD(0x534, 0x14c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 IOMUX_PAD(0x538, 0x150, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK IOMUX_PAD(0x538, 0x150, 1, 0x974, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_RDY_INT__GPIO3_24 IOMUX_PAD(0x538, 0x150, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT IOMUX_PAD(0x538, 0x150, 0, 0x938, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__SD3_CMD IOMUX_PAD(0x538, 0x150, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__ECSPI2_MOSI IOMUX_PAD(0x53c, 0x154, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__GPIO3_25 IOMUX_PAD(0x53c, 0x154, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__NANDF_D15 IOMUX_PAD(0x53c, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__PATA_DATA15 IOMUX_PAD(0x53c, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__SD3_DAT7 IOMUX_PAD(0x53c, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__ECSPI2_SS3 IOMUX_PAD(0x540, 0x158, 2, 0x934, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__GPIO3_26 IOMUX_PAD(0x540, 0x158, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__NANDF_D14 IOMUX_PAD(0x540, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__PATA_DATA14 IOMUX_PAD(0x540, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__SD3_DAT6 IOMUX_PAD(0x540, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__ECSPI2_SS2 IOMUX_PAD(0x544, 0x15c, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__GPIO3_27 IOMUX_PAD(0x544, 0x15c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__NANDF_D13 IOMUX_PAD(0x544, 0x15c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__PATA_DATA13 IOMUX_PAD(0x544, 0x15c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__SD3_DAT5 IOMUX_PAD(0x544, 0x15c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__ECSPI2_SS1 IOMUX_PAD(0x548, 0x160, 2, 0x930, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__GPIO3_28 IOMUX_PAD(0x548, 0x160, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__NANDF_D12 IOMUX_PAD(0x548, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__PATA_DATA12 IOMUX_PAD(0x548, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__SD3_DAT4 IOMUX_PAD(0x548, 0x160, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__FEC_RX_DV IOMUX_PAD(0x54c, 0x164, 2, 0x96c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__GPIO3_29 IOMUX_PAD(0x54c, 0x164, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__NANDF_D11 IOMUX_PAD(0x54c, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__PATA_DATA11 IOMUX_PAD(0x54c, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__SD3_DATA3 IOMUX_PAD(0x54c, 0x164, 5, 0x948, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__GPIO3_30 IOMUX_PAD(0x550, 0x168, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__NANDF_D10 IOMUX_PAD(0x550, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__PATA_DATA10 IOMUX_PAD(0x550, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__SD3_DATA2 IOMUX_PAD(0x550, 0x168, 5, 0x944, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__FEC_RDATA0 IOMUX_PAD(0x554, 0x16c, 0x12, 0x958, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_D9__GPIO3_31 IOMUX_PAD(0x554, 0x16c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__NANDF_D9 IOMUX_PAD(0x554, 0x16c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__PATA_DATA9 IOMUX_PAD(0x554, 0x16c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__SD3_DATA1 IOMUX_PAD(0x554, 0x16c, 5, 0x940, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__FEC_TDATA0 IOMUX_PAD(0x558, 0x170, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_D8__GPIO4_0 IOMUX_PAD(0x558, 0x170, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__NANDF_D8 IOMUX_PAD(0x558, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__PATA_DATA8 IOMUX_PAD(0x558, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__SD3_DATA0 IOMUX_PAD(0x558, 0x170, 5, 0x93c, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__GPIO4_1 IOMUX_PAD(0x55c, 0x174, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__NANDF_D7 IOMUX_PAD(0x55c, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__PATA_DATA7 IOMUX_PAD(0x55c, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__USBH3_DATA0 IOMUX_PAD(0x55c, 0x174, 5, 0x9fc, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__GPIO4_2 IOMUX_PAD(0x560, 0x178, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__NANDF_D6 IOMUX_PAD(0x560, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__PATA_DATA6 IOMUX_PAD(0x560, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__SD4_LCTL IOMUX_PAD(0x560, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__USBH3_DATA1 IOMUX_PAD(0x560, 0x178, 5, 0xa00, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__GPIO4_3 IOMUX_PAD(0x564, 0x17c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__NANDF_D5 IOMUX_PAD(0x564, 0x17c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__PATA_DATA5 IOMUX_PAD(0x564, 0x17c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__SD4_WP IOMUX_PAD(0x564, 0x17c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__USBH3_DATA2 IOMUX_PAD(0x564, 0x17c, 5, 0xa04, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__GPIO4_4 IOMUX_PAD(0x568, 0x180, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__NANDF_D4 IOMUX_PAD(0x568, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__PATA_DATA4 IOMUX_PAD(0x568, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__SD4_CD IOMUX_PAD(0x568, 0x180, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__USBH3_DATA3 IOMUX_PAD(0x568, 0x180, 5, 0xa08, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__GPIO4_5 IOMUX_PAD(0x56c, 0x184, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__NANDF_D3 IOMUX_PAD(0x56c, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__PATA_DATA3 IOMUX_PAD(0x56c, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__SD4_DAT4 IOMUX_PAD(0x56c, 0x184, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__USBH3_DATA4 IOMUX_PAD(0x56c, 0x184, 5, 0xa0c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__GPIO4_6 IOMUX_PAD(0x570, 0x188, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__NANDF_D2 IOMUX_PAD(0x570, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__PATA_DATA2 IOMUX_PAD(0x570, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__SD4_DAT5 IOMUX_PAD(0x570, 0x188, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__USBH3_DATA5 IOMUX_PAD(0x570, 0x188, 5, 0xa10, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__GPIO4_7 IOMUX_PAD(0x574, 0x18c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__NANDF_D1 IOMUX_PAD(0x574, 0x18c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__PATA_DATA1 IOMUX_PAD(0x574, 0x18c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__SD4_DAT6 IOMUX_PAD(0x574, 0x18c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__USBH3_DATA6 IOMUX_PAD(0x574, 0x18c, 5, 0xa14, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__GPIO4_8 IOMUX_PAD(0x578, 0x190, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__NANDF_D0 IOMUX_PAD(0x578, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__PATA_DATA0 IOMUX_PAD(0x578, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__SD4_DAT7 IOMUX_PAD(0x578, 0x190, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__USBH3_DATA7 IOMUX_PAD(0x578, 0x190, 5, 0xa18, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D8__CSI1_D8 IOMUX_PAD(0x57c, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D8__GPIO3_12 IOMUX_PAD(0x57c, 0x194, 3, 0x998, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_D9__CSI1_D9 IOMUX_PAD(0x580, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D9__GPIO3_13 IOMUX_PAD(0x580, 0x198, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_D10__CSI1_D10 IOMUX_PAD(0x584, 0x19c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D11__CSI1_D11 IOMUX_PAD(0x588, 0x1a0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D12__CSI1_D12 IOMUX_PAD(0x58c, 0x1a4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D13__CSI1_D13 IOMUX_PAD(0x590, 0x1a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D14__CSI1_D14 IOMUX_PAD(0x594, 0x1ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D15__CSI1_D15 IOMUX_PAD(0x598, 0x1b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D16__CSI1_D16 IOMUX_PAD(0x59c, 0x1b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D17__CSI1_D17 IOMUX_PAD(0x5a0, 0x1b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D18__CSI1_D18 IOMUX_PAD(0x5a4, 0x1bc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D19__CSI1_D19 IOMUX_PAD(0x5a8, 0x1c0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC IOMUX_PAD(0x5ac, 0x1c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_VSYNC__GPIO3_14 IOMUX_PAD(0x5ac, 0x1c4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC IOMUX_PAD(0x5b0, 0x1c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_HSYNC__GPIO3_15 IOMUX_PAD(0x5b0, 0x1c8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK IOMUX_PAD(0x5b4, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_MCLK__CSI1_MCLK IOMUX_PAD(0x5b8, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D12__CSI2_D12 IOMUX_PAD(0x5bc, 0x1cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D12__GPIO4_9 IOMUX_PAD(0x5bc, 0x1cc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D13__CSI2_D13 IOMUX_PAD(0x5c0, 0x1d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D13__GPIO4_10 IOMUX_PAD(0x5c0, 0x1d0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D14__CSI2_D14 IOMUX_PAD(0x5c4, 0x1d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D15__CSI2_D15 IOMUX_PAD(0x5c8, 0x1d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D16__CSI2_D16 IOMUX_PAD(0x5cc, 0x1dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D17__CSI2_D17 IOMUX_PAD(0x5d0, 0x1e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D18__CSI2_D18 IOMUX_PAD(0x5d4, 0x1e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D18__GPIO4_11 IOMUX_PAD(0x5d4, 0x1e4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D19__CSI2_D19 IOMUX_PAD(0x5d8, 0x1e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D19__GPIO4_12 IOMUX_PAD(0x5d8, 0x1e8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC IOMUX_PAD(0x5dc, 0x1ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_VSYNC__GPIO4_13 IOMUX_PAD(0x5dc, 0x1ec, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC IOMUX_PAD(0x5e0, 0x1f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_HSYNC__GPIO4_14 IOMUX_PAD(0x5e0, 0x1f0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK IOMUX_PAD(0x5e4, 0x1f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_PIXCLK__GPIO4_15 IOMUX_PAD(0x5e4, 0x1f4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_CLK__GPIO4_16 IOMUX_PAD(0x5e8, 0x1f8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_CLK__I2C1_CLK IOMUX_PAD(0x5e8, 0x1f8, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_I2C1_DAT__GPIO4_17 IOMUX_PAD(0x5ec, 0x1fc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_DAT__I2C1_DAT IOMUX_PAD(0x5ec, 0x1fc, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD IOMUX_PAD(0x5f0, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__GPIO4_18 IOMUX_PAD(0x5f0, 0x200, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD IOMUX_PAD(0x5f4, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__GPIO4_19 IOMUX_PAD(0x5f4, 0x204, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__UART3_RXD IOMUX_PAD(0x5f4, 0x204, 1, 0x9f4, 2, MX51_UART_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__AUD3_TXC IOMUX_PAD(0x5f8, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__GPIO4_20 IOMUX_PAD(0x5f8, 0x208, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS IOMUX_PAD(0x5fc, 0x20c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__GPIO4_21 IOMUX_PAD(0x5fc, 0x20c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__UART3_TXD IOMUX_PAD(0x5fc, 0x20c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI IOMUX_PAD(0x600, 0x210, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__GPIO4_22 IOMUX_PAD(0x600, 0x210, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__I2C1_SDA IOMUX_PAD(0x600, 0x210, 0x11, 0x9b4, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__AUD4_RXD IOMUX_PAD(0x604, 0x214, 1, 0x8c4, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO IOMUX_PAD(0x604, 0x214, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__GPIO4_23 IOMUX_PAD(0x604, 0x214, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__AUD4_TXC IOMUX_PAD(0x608, 0x218, 1, 0x8cc, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0 IOMUX_PAD(0x608, 0x218, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__GPIO4_24 IOMUX_PAD(0x608, 0x218, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__AUD4_TXD IOMUX_PAD(0x60c, 0x21c, 1, 0x8c8, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1 IOMUX_PAD(0x60c, 0x21c, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__GPIO4_25 IOMUX_PAD(0x60c, 0x21c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__AUD4_TXFS IOMUX_PAD(0x610, 0x220, 1, 0x8d0, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY IOMUX_PAD(0x610, 0x220, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__GPIO4_26 IOMUX_PAD(0x610, 0x220, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK IOMUX_PAD(0x614, 0x224, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__GPIO4_27 IOMUX_PAD(0x614, 0x224, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__I2C1_SCL IOMUX_PAD(0x614, 0x224, 0x11, 0x9b0, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_UART1_RXD__GPIO4_28 IOMUX_PAD(0x618, 0x228, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_RXD__UART1_RXD IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__GPIO4_29 IOMUX_PAD(0x61c, 0x22c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__PWM2_PWMO IOMUX_PAD(0x61c, 0x22c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__UART1_TXD IOMUX_PAD(0x61c, 0x22c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_RTS__GPIO4_30 IOMUX_PAD(0x620, 0x230, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_RTS__UART1_RTS IOMUX_PAD(0x620, 0x230, 0, 0x9e0, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__GPIO4_31 IOMUX_PAD(0x624, 0x234, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__UART1_CTS IOMUX_PAD(0x624, 0x234, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__FIRI_TXD IOMUX_PAD(0x628, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__GPIO1_20 IOMUX_PAD(0x628, 0x238, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__UART2_RXD IOMUX_PAD(0x628, 0x238, 0, 0x9ec, 2, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__FIRI_RXD IOMUX_PAD(0x62c, 0x23c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__GPIO1_21 IOMUX_PAD(0x62c, 0x23c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__UART2_TXD IOMUX_PAD(0x62c, 0x23c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__CSI1_D0 IOMUX_PAD(0x630, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__GPIO1_22 IOMUX_PAD(0x630, 0x240, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__UART1_DTR IOMUX_PAD(0x630, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__UART3_RXD IOMUX_PAD(0x630, 0x240, 1, 0x9f4, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__CSI1_D1 IOMUX_PAD(0x634, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__GPIO1_23 IOMUX_PAD(0x634, 0x244, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__UART1_DSR IOMUX_PAD(0x634, 0x244, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__UART3_TXD IOMUX_PAD(0x634, 0x244, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__GPIO1_24 IOMUX_PAD(0x638, 0x248, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__OWIRE_LINE IOMUX_PAD(0x638, 0x248, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__SPDIF_OUT IOMUX_PAD(0x638, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW0__KEY_ROW0 IOMUX_PAD(0x63c, 0x24c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW1__KEY_ROW1 IOMUX_PAD(0x640, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW2__KEY_ROW2 IOMUX_PAD(0x644, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW3__KEY_ROW3 IOMUX_PAD(0x648, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL0__KEY_COL0 IOMUX_PAD(0x64c, 0x25c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL0__PLL1_BYP IOMUX_PAD(0x64c, 0x25c, 7, 0x90c, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL1__KEY_COL1 IOMUX_PAD(0x650, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL1__PLL2_BYP IOMUX_PAD(0x650, 0x260, 7, 0x910, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL2__KEY_COL2 IOMUX_PAD(0x654, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL2__PLL3_BYP IOMUX_PAD(0x654, 0x264, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL3__KEY_COL3 IOMUX_PAD(0x658, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__I2C2_SCL IOMUX_PAD(0x65c, 0x26c, 0x13, 0x9b8, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__KEY_COL4 IOMUX_PAD(0x65c, 0x26c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__SPDIF_OUT1 IOMUX_PAD(0x65c, 0x26c, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__UART1_RI IOMUX_PAD(0x65c, 0x26c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__UART3_RTS IOMUX_PAD(0x65c, 0x26c, 2, 0x9f0, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__I2C2_SDA IOMUX_PAD(0x660, 0x270, 0x13, 0x9bc, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__KEY_COL5 IOMUX_PAD(0x660, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__UART1_DCD IOMUX_PAD(0x660, 0x270, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__UART3_CTS IOMUX_PAD(0x660, 0x270, 2, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__CSPI_SCLK IOMUX_PAD(0x678, 0x278, 1, 0x914, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__GPIO1_25 IOMUX_PAD(0x678, 0x278, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__I2C2_SCL IOMUX_PAD(0x678, 0x278, 0x15, 0x9b8, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__USBH1_CLK IOMUX_PAD(0x678, 0x278, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__CSPI_MOSI IOMUX_PAD(0x67c, 0x27c, 1, 0x91c, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__GPIO1_26 IOMUX_PAD(0x67c, 0x27c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__I2C2_SDA IOMUX_PAD(0x67c, 0x27c, 0x15, 0x9bc, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__USBH1_DIR IOMUX_PAD(0x67c, 0x27c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__CSPI_RDY IOMUX_PAD(0x680, 0x280, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__GPIO1_27 IOMUX_PAD(0x680, 0x280, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__UART3_RXD IOMUX_PAD(0x680, 0x280, 5, 0x9f4, 6, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__USBH1_STP IOMUX_PAD(0x680, 0x280, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__CSPI_MISO IOMUX_PAD(0x684, 0x284, 1, 0x918, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__GPIO1_28 IOMUX_PAD(0x684, 0x284, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__UART3_TXD IOMUX_PAD(0x684, 0x284, 5, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__USBH1_NXT IOMUX_PAD(0x684, 0x284, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__GPIO1_11 IOMUX_PAD(0x688, 0x288, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__UART2_CTS IOMUX_PAD(0x688, 0x288, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__USBH1_DATA0 IOMUX_PAD(0x688, 0x288, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__GPIO1_12 IOMUX_PAD(0x68c, 0x28c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__UART2_RXD IOMUX_PAD(0x68c, 0x28c, 1, 0x9ec, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__USBH1_DATA1 IOMUX_PAD(0x68c, 0x28c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__GPIO1_13 IOMUX_PAD(0x690, 0x290, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__UART2_TXD IOMUX_PAD(0x690, 0x290, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__USBH1_DATA2 IOMUX_PAD(0x690, 0x290, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__GPIO1_14 IOMUX_PAD(0x694, 0x294, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__UART2_RTS IOMUX_PAD(0x694, 0x294, 1, 0x9e8, 5, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__USBH1_DATA3 IOMUX_PAD(0x694, 0x294, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__CSPI_SS0 IOMUX_PAD(0x698, 0x298, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__GPIO1_15 IOMUX_PAD(0x698, 0x298, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__USBH1_DATA4 IOMUX_PAD(0x698, 0x298, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__CSPI_SS1 IOMUX_PAD(0x69c, 0x29c, 1, 0x920, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__GPIO1_16 IOMUX_PAD(0x69c, 0x29c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__USBH1_DATA5 IOMUX_PAD(0x69c, 0x29c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__CSPI_SS3 IOMUX_PAD(0x6a0, 0x2a0, 1, 0x928, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__GPIO1_17 IOMUX_PAD(0x6a0, 0x2a0, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__USBH1_DATA6 IOMUX_PAD(0x6a0, 0x2a0, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3 IOMUX_PAD(0x6a4, 0x2a4, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3 IOMUX_PAD(0x6a4, 0x2a4, 5, 0x934, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__GPIO1_18 IOMUX_PAD(0x6a4, 0x2a4, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__USBH1_DATA7 IOMUX_PAD(0x6a4, 0x2a4, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__DI1_PIN11 IOMUX_PAD(0x6a8, 0x2a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__ECSPI1_SS2 IOMUX_PAD(0x6a8, 0x2a8, 7, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__GPIO3_0 IOMUX_PAD(0x6a8, 0x2a8, 4, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__DI1_PIN12 IOMUX_PAD(0x6ac, 0x2ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__GPIO3_1 IOMUX_PAD(0x6ac, 0x2ac, 4, 0x978, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__DI1_PIN13 IOMUX_PAD(0x6b0, 0x2b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__GPIO3_2 IOMUX_PAD(0x6b0, 0x2b0, 4, 0x97c, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__DI1_D0_CS IOMUX_PAD(0x6b4, 0x2b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__GPIO3_3 IOMUX_PAD(0x6b4, 0x2b4, 4, 0x980, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DI1_D1_CS IOMUX_PAD(0x6b8, 0x2b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN14 IOMUX_PAD(0x6b8, 0x2b8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN5 IOMUX_PAD(0x6b8, 0x2b8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__GPIO3_4 IOMUX_PAD(0x6b8, 0x2b8, 4, 0x984, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 IOMUX_PAD(0x6bc, 0x2bc, 2, 0x9a4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN IOMUX_PAD(0x6bc, 0x2bc, 0, 0x9c4, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5 IOMUX_PAD(0x6bc, 0x2bc, 4, 0x988, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 IOMUX_PAD(0x6c0, 0x2c0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO IOMUX_PAD(0x6c0, 0x2c0, 0, 0x9c4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6 IOMUX_PAD(0x6c0, 0x2c0, 4, 0x98c, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 IOMUX_PAD(0x6c4, 0x2c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 IOMUX_PAD(0x6c4, 0x2c4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK IOMUX_PAD(0x6c4, 0x2c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7 IOMUX_PAD(0x6c4, 0x2c4, 4, 0x990, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 IOMUX_PAD(0x6c8, 0x2c8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__GPIO3_8 IOMUX_PAD(0x6c8, 0x2c8, 4, 0x994, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT0__DISP1_DAT0 IOMUX_PAD(0x6cc, 0x2cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT1__DISP1_DAT1 IOMUX_PAD(0x6d0, 0x2d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT2__DISP1_DAT2 IOMUX_PAD(0x6d4, 0x2d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT3__DISP1_DAT3 IOMUX_PAD(0x6d8, 0x2d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT4__DISP1_DAT4 IOMUX_PAD(0x6dc, 0x2dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT5__DISP1_DAT5 IOMUX_PAD(0x6e0, 0x2e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC IOMUX_PAD(0x6e4, 0x2e4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT6__DISP1_DAT6 IOMUX_PAD(0x6e4, 0x2e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG IOMUX_PAD(0x6e8, 0x2e8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT7__DISP1_DAT7 IOMUX_PAD(0x6e8, 0x2e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT8__BOOT_SRC0 IOMUX_PAD(0x6ec, 0x2ec, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT8__DISP1_DAT8 IOMUX_PAD(0x6ec, 0x2ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT9__BOOT_SRC1 IOMUX_PAD(0x6f0, 0x2f0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT9__DISP1_DAT9 IOMUX_PAD(0x6f0, 0x2f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE IOMUX_PAD(0x6f4, 0x2f4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT10__DISP1_DAT10 IOMUX_PAD(0x6f4, 0x2f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 IOMUX_PAD(0x6f8, 0x2f8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT11__DISP1_DAT11 IOMUX_PAD(0x6f8, 0x2f8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL IOMUX_PAD(0x6fc, 0x2fc, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT12__DISP1_DAT12 IOMUX_PAD(0x6fc, 0x2fc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 IOMUX_PAD(0x700, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT13__DISP1_DAT13 IOMUX_PAD(0x700, 0x300, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 IOMUX_PAD(0x704, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT14__DISP1_DAT14 IOMUX_PAD(0x704, 0x304, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH IOMUX_PAD(0x708, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT15__DISP1_DAT15 IOMUX_PAD(0x708, 0x308, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 IOMUX_PAD(0x70c, 0x30c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT16__DISP1_DAT16 IOMUX_PAD(0x70c, 0x30c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 IOMUX_PAD(0x710, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT17__DISP1_DAT17 IOMUX_PAD(0x710, 0x310, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 IOMUX_PAD(0x714, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP1_DAT18 IOMUX_PAD(0x714, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN11 IOMUX_PAD(0x714, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN5 IOMUX_PAD(0x714, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 IOMUX_PAD(0x718, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP1_DAT19 IOMUX_PAD(0x718, 0x318, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN12 IOMUX_PAD(0x718, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN6 IOMUX_PAD(0x718, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 IOMUX_PAD(0x71c, 0x31c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP1_DAT20 IOMUX_PAD(0x71c, 0x31c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN13 IOMUX_PAD(0x71c, 0x31c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN7 IOMUX_PAD(0x71c, 0x31c, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 IOMUX_PAD(0x720, 0x320, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP1_DAT21 IOMUX_PAD(0x720, 0x320, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN14 IOMUX_PAD(0x720, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN8 IOMUX_PAD(0x720, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 IOMUX_PAD(0x724, 0x324, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP1_DAT22 IOMUX_PAD(0x724, 0x324, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS IOMUX_PAD(0x724, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP2_DAT16 IOMUX_PAD(0x724, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 IOMUX_PAD(0x728, 0x328, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP1_DAT23 IOMUX_PAD(0x728, 0x328, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS IOMUX_PAD(0x728, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_DAT17 IOMUX_PAD(0x728, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS IOMUX_PAD(0x728, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN3__DI1_PIN3 IOMUX_PAD(0x72c, 0x32c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN2__DI1_PIN2 IOMUX_PAD(0x734, 0x330, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP2__DISP1_SER_CLK IOMUX_PAD(0x740, 0x338, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP2__DISP2_WAIT IOMUX_PAD(0x740, 0x338, 2, 0x9a8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__CSI1_DATA_EN IOMUX_PAD(0x744, 0x33c, 3, 0x9a0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__DISP1_SER_DIO IOMUX_PAD(0x744, 0x33c, 0, 0x9c0, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__FEC_TX_ER IOMUX_PAD(0x744, 0x33c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN IOMUX_PAD(0x748, 0x340, 3, 0x99c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN4__DI2_PIN4 IOMUX_PAD(0x748, 0x340, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN4__FEC_CRS IOMUX_PAD(0x748, 0x340, 2, 0x950, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN2__DI2_PIN2 IOMUX_PAD(0x74c, 0x344, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN2__FEC_MDC IOMUX_PAD(0x74c, 0x344, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DI2_PIN3__DI2_PIN3 IOMUX_PAD(0x750, 0x348, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN3__FEC_MDIO IOMUX_PAD(0x750, 0x348, 2, 0x954, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK IOMUX_PAD(0x754, 0x34c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 IOMUX_PAD(0x754, 0x34c, 2, 0x95c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DI2_PIN15 IOMUX_PAD(0x758, 0x350, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DISP1_SER_DIN IOMUX_PAD(0x758, 0x350, 0, 0x9c0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DISP2_PIN1 IOMUX_PAD(0x758, 0x350, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__FEC_RDATA2 IOMUX_PAD(0x758, 0x350, 2, 0x960, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__DISP2_DAT0 IOMUX_PAD(0x75c, 0x354, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__FEC_RDATA3 IOMUX_PAD(0x75c, 0x354, 2, 0x964, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__KEY_COL6 IOMUX_PAD(0x75c, 0x354, 4, 0x9c8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__UART3_RXD IOMUX_PAD(0x75c, 0x354, 5, 0x9f4, 8, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__USBH3_CLK IOMUX_PAD(0x75c, 0x354, 3, 0x9f8, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__DISP2_DAT1 IOMUX_PAD(0x760, 0x358, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__FEC_RX_ER IOMUX_PAD(0x760, 0x358, 2, 0x970, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__KEY_COL7 IOMUX_PAD(0x760, 0x358, 4, 0x9cc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__UART3_TXD IOMUX_PAD(0x760, 0x358, 5, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__USBH3_DIR IOMUX_PAD(0x760, 0x358, 3, 0xa1c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT2__DISP2_DAT2 IOMUX_PAD(0x764, 0x35c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT3__DISP2_DAT3 IOMUX_PAD(0x768, 0x360, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT4__DISP2_DAT4 IOMUX_PAD(0x76c, 0x364, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT5__DISP2_DAT5 IOMUX_PAD(0x770, 0x368, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__DISP2_DAT6 IOMUX_PAD(0x774, 0x36c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__FEC_TDATA1 IOMUX_PAD(0x774, 0x36c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT6__GPIO1_19 IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__KEY_ROW4 IOMUX_PAD(0x774, 0x36c, 4, 0x9d0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__USBH3_STP IOMUX_PAD(0x774, 0x36c, 3, 0xa24, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__DISP2_DAT7 IOMUX_PAD(0x778, 0x370, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__FEC_TDATA2 IOMUX_PAD(0x778, 0x370, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT7__GPIO1_29 IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__KEY_ROW5 IOMUX_PAD(0x778, 0x370, 4, 0x9d4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__USBH3_NXT IOMUX_PAD(0x778, 0x370, 3, 0xa20, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__DISP2_DAT8 IOMUX_PAD(0x77c, 0x374, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__FEC_TDATA3 IOMUX_PAD(0x77c, 0x374, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT8__GPIO1_30 IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__KEY_ROW6 IOMUX_PAD(0x77c, 0x374, 4, 0x9d8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__USBH3_DATA0 IOMUX_PAD(0x77c, 0x374, 3, 0x9fc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__AUD6_RXC IOMUX_PAD(0x780, 0x378, 4, 0x8f4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__DISP2_DAT9 IOMUX_PAD(0x780, 0x378, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__FEC_TX_EN IOMUX_PAD(0x780, 0x378, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT9__GPIO1_31 IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__USBH3_DATA1 IOMUX_PAD(0x780, 0x378, 3, 0xa00, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__DISP2_DAT10 IOMUX_PAD(0x784, 0x37c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS IOMUX_PAD(0x784, 0x37c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__FEC_COL IOMUX_PAD(0x784, 0x37c, 2, 0x94c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__KEY_ROW7 IOMUX_PAD(0x784, 0x37c, 4, 0x9dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__USBH3_DATA2 IOMUX_PAD(0x784, 0x37c, 3, 0xa04, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__AUD6_TXD IOMUX_PAD(0x788, 0x380, 4, 0x8f0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__DISP2_DAT11 IOMUX_PAD(0x788, 0x380, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK IOMUX_PAD(0x788, 0x380, 2, 0x968, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__GPIO1_10 IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__USBH3_DATA3 IOMUX_PAD(0x788, 0x380, 3, 0xa08, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__AUD6_RXD IOMUX_PAD(0x78c, 0x384, 4, 0x8ec, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__DISP2_DAT12 IOMUX_PAD(0x78c, 0x384, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__FEC_RX_DV IOMUX_PAD(0x78c, 0x384, 2, 0x96c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__USBH3_DATA4 IOMUX_PAD(0x78c, 0x384, 3, 0xa0c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__AUD6_TXC IOMUX_PAD(0x790, 0x388, 4, 0x8fc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__DISP2_DAT13 IOMUX_PAD(0x790, 0x388, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK IOMUX_PAD(0x790, 0x388, 2, 0x974, 1, MX51_PAD_CTRL_4)
+#define MX51_PAD_DISP2_DAT13__USBH3_DATA5 IOMUX_PAD(0x790, 0x388, 3, 0xa10, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__AUD6_TXFS IOMUX_PAD(0x794, 0x38c, 4, 0x900, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__DISP2_DAT14 IOMUX_PAD(0x794, 0x38c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__FEC_RDATA0 IOMUX_PAD(0x794, 0x38c, 2, 0x958, 1, MX51_PAD_CTRL_4)
+#define MX51_PAD_DISP2_DAT14__USBH3_DATA6 IOMUX_PAD(0x794, 0x38c, 3, 0xa14, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__AUD6_RXFS IOMUX_PAD(0x798, 0x390, 4, 0x8f8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS IOMUX_PAD(0x798, 0x390, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__DISP2_DAT15 IOMUX_PAD(0x798, 0x390, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__FEC_TDATA0 IOMUX_PAD(0x798, 0x390, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT15__USBH3_DATA7 IOMUX_PAD(0x798, 0x390, 3, 0xa18, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__AUD5_RXFS IOMUX_PAD(0x79c, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__CSPI_MOSI IOMUX_PAD(0x79c, 0x394, 2, 0x91c, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x79c, 0x394, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__AUD5_RXC IOMUX_PAD(0x7a0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__CSPI_SCLK IOMUX_PAD(0x7a0, 0x398, 2, 0x914, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x7a0, 0x398, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD1_DATA0__AUD5_TXD IOMUX_PAD(0x7a4, 0x39c, 1, 0x8d8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__CSPI_MISO IOMUX_PAD(0x7a4, 0x39c, 2, 0x918, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0 IOMUX_PAD(0x7a4, 0x39c, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA0__EIM_DA0 IOMUX_PAD(__NA_, 0x01c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA1__EIM_DA1 IOMUX_PAD(__NA_, 0x020, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA2__EIM_DA2 IOMUX_PAD(__NA_, 0x024, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA3__EIM_DA3 IOMUX_PAD(__NA_, 0x028, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__AUD5_RXD IOMUX_PAD(0x7a8, 0x3a0, 1, 0x8d4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1 IOMUX_PAD(0x7a8, 0x3a0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA4__EIM_DA4 IOMUX_PAD(__NA_, 0x02c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA5__EIM_DA5 IOMUX_PAD(__NA_, 0x030, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA6__EIM_DA6 IOMUX_PAD(__NA_, 0x034, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA7__EIM_DA7 IOMUX_PAD(__NA_, 0x038, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__AUD5_TXC IOMUX_PAD(0x7ac, 0x3a4, 1, 0x8e4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2 IOMUX_PAD(0x7ac, 0x3a4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA10__EIM_DA10 IOMUX_PAD(__NA_, 0x044, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA11__EIM_DA11 IOMUX_PAD(__NA_, 0x048, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA8__EIM_DA8 IOMUX_PAD(__NA_, 0x03c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA9__EIM_DA9 IOMUX_PAD(__NA_, 0x040, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__AUD5_TXFS IOMUX_PAD(0x7b0, 0x3a8, 1, 0x8e8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__CSPI_SS1 IOMUX_PAD(0x7b0, 0x3a8, 2, 0x920, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7b0, 0x3a8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__CSPI_SS2 IOMUX_PAD(0x7b4, 0x3ac, 2, 0x924, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__GPIO1_0 IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__SD1_CD IOMUX_PAD(0x7b4, 0x3ac, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__CSPI_MISO IOMUX_PAD(0x7b8, 0x3b0, 2, 0x918, 2, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__GPIO1_1 IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__SD1_WP IOMUX_PAD(0x7b8, 0x3b0, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_EIM_DA12__EIM_DA12 IOMUX_PAD(__NA_, 0x04c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA13__EIM_DA13 IOMUX_PAD(__NA_, 0x050, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA14__EIM_DA14 IOMUX_PAD(__NA_, 0x054, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA15__EIM_DA15 IOMUX_PAD(__NA_, 0x058, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__CSPI_MOSI IOMUX_PAD(__NA_, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__I2C1_SCL IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x9b0, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7bc, 0x3b4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__CSPI_SCLK IOMUX_PAD(0x7c0, 0x3b8, 2, 0x914, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__I2C1_SDA IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x9b4, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK IOMUX_PAD(0x7c0, 0x3b8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD2_DATA0__CSPI_MISO IOMUX_PAD(0x7c4, 0x3bc, 2, 0x918, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD1_DAT4 IOMUX_PAD(0x7c4, 0x3bc, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7c4, 0x3bc, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD1_DAT5 IOMUX_PAD(0x7c8, 0x3c0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7c8, 0x3c0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__USBH3_H2_DP IOMUX_PAD(0x7c8, 0x3c0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD1_DAT6 IOMUX_PAD(0x7cc, 0x3c4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7cc, 0x3c4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__USBH3_H2_DM IOMUX_PAD(0x7cc, 0x3c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__CSPI_SS2 IOMUX_PAD(0x7d0, 0x3c8, 2, 0x924, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD1_DAT7 IOMUX_PAD(0x7d0, 0x3c8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7d0, 0x3c8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__CCM_OUT_2 IOMUX_PAD(0x7d4, 0x3cc, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__GPIO1_2 IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__I2C2_SCL IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x9b8, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__PLL1_BYP IOMUX_PAD(0x7d4, 0x3cc, 7, 0x90c, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__PWM1_PWMO IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__GPIO1_3 IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__I2C2_SDA IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__PLL2_BYP IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__PWM2_PWMO IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ IOMUX_PAD(0x7fc, 0x3d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B IOMUX_PAD(0x7fc, 0x3d4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK IOMUX_PAD(0x804, 0x3d8, 4, 0x908, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__EIM_RDY IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__GPIO1_4 IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__CSI2_MCLK IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__DISP2_PIN16 IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__GPIO1_5 IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__DISP2_PIN17 IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__GPIO1_6 IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__REF_EN_B IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__CCM_OUT_0 IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__GPIO1_7 IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__SD2_WP IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__SPDIF_OUT1 IOMUX_PAD(0x810, 0x3e4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__CSI2_DATA_EN IOMUX_PAD(0x814, 0x3e8, 2, 0x99c, 2, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__GPIO1_8 IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__SD2_CD IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__USBH3_PWR IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__CCM_OUT_1 IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__DISP2_D1_CS IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__DISP2_SER_CS IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__GPIO1_9 IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__SD2_LCTL IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__USBH3_OC IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
#endif /* __MACH_IOMUX_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx53.h b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
index 5408fd1fc736..527f8fe3e31b 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx53.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
@@ -23,2359 +23,1197 @@
/* These 2 defines are for pins that may not have a mux register, but could
* have a pad setting register, and vice-versa. */
-#define NON_PAD_I 0x00
+#define __NA_ 0x00
#define MX53_UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
#define MX53_SDHC_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH | \
PAD_CTL_SRE_FAST)
-#define PAD_CTRL_I2C (PAD_CTL_SRE_FAST | PAD_CTL_ODE | PAD_CTL_PKE | \
- PAD_CTL_PUE | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP \
- | PAD_CTL_HYS)
-#define _MX53_PAD_GPIO_19__KPP_COL_5 IOMUX_PAD(0x348, 0x20, 0, 0x840, 0, 0)
-#define _MX53_PAD_GPIO_19__GPIO4_5 IOMUX_PAD(0x348, 0x20, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__CCM_CLKO IOMUX_PAD(0x348, 0x20, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__SPDIF_OUT1 IOMUX_PAD(0x348, 0x20, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 IOMUX_PAD(0x348, 0x20, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__ECSPI1_RDY IOMUX_PAD(0x348, 0x20, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__FEC_TDATA_3 IOMUX_PAD(0x348, 0x20, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__SRC_INT_BOOT IOMUX_PAD(0x348, 0x20,7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__KPP_COL_0 IOMUX_PAD(0x34C, 0x24, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__GPIO4_6 IOMUX_PAD(0x34C, 0x24, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC IOMUX_PAD(0x34C, 0x24, 2, 0x758, 0, 0)
-#define _MX53_PAD_KEY_COL0__UART4_TXD_MUX IOMUX_PAD(0x34C, 0x24, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__ECSPI1_SCLK IOMUX_PAD(0x34C, 0x24, 5, 0x79C, 0, 0)
-#define _MX53_PAD_KEY_COL0__FEC_RDATA_3 IOMUX_PAD(0x34C, 0x24, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__SRC_ANY_PU_RST IOMUX_PAD(0x34C, 0x24, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW0__KPP_ROW_0 IOMUX_PAD(0x350, 0x28, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW0__GPIO4_7 IOMUX_PAD(0x350, 0x28, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD IOMUX_PAD(0x350, 0x28, 2, 0x74C, 0, 0)
-#define _MX53_PAD_KEY_ROW0__UART4_RXD_MUX IOMUX_PAD(0x350, 0x28, 4, 0x890, 1, 0)
-#define _MX53_PAD_KEY_ROW0__ECSPI1_MOSI IOMUX_PAD(0x350, 0x28, 5, 0x7A4, 0, 0)
-#define _MX53_PAD_KEY_ROW0__FEC_TX_ER IOMUX_PAD(0x350, 0x28, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__KPP_COL_1 IOMUX_PAD(0x354, 0x2C, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__GPIO4_8 IOMUX_PAD(0x354, 0x2C, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS IOMUX_PAD(0x354, 0x2C, 2, 0x75C, 0, 0)
-#define _MX53_PAD_KEY_COL1__UART5_TXD_MUX IOMUX_PAD(0x354, 0x2C, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__ECSPI1_MISO IOMUX_PAD(0x354, 0x2C, 5, 0x7A0, 0, 0)
-#define _MX53_PAD_KEY_COL1__FEC_RX_CLK IOMUX_PAD(0x354, 0x2C, 6, 0x808, 0, 0)
-#define _MX53_PAD_KEY_COL1__USBPHY1_TXREADY IOMUX_PAD(0x354, 0x2C, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW1__KPP_ROW_1 IOMUX_PAD(0x358, 0x30, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW1__GPIO4_9 IOMUX_PAD(0x358, 0x30, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD IOMUX_PAD(0x358, 0x30, 2, 0x748, 0, 0)
-#define _MX53_PAD_KEY_ROW1__UART5_RXD_MUX IOMUX_PAD(0x358, 0x30, 4, 0x898, 1, 0)
-#define _MX53_PAD_KEY_ROW1__ECSPI1_SS0 IOMUX_PAD(0x358, 0x30, 5, 0x7A8, 0, 0)
-#define _MX53_PAD_KEY_ROW1__FEC_COL IOMUX_PAD(0x358, 0x30, 6, 0x800, 0, 0)
-#define _MX53_PAD_KEY_ROW1__USBPHY1_RXVALID IOMUX_PAD(0x358, 0x30, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__KPP_COL_2 IOMUX_PAD(0x35C, 0x34, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__GPIO4_10 IOMUX_PAD(0x35C, 0x34, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__CAN1_TXCAN IOMUX_PAD(0x35C, 0x34, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__FEC_MDIO IOMUX_PAD(0x35C, 0x34, 4, 0x804, 0, 0)
-#define _MX53_PAD_KEY_COL2__ECSPI1_SS1 IOMUX_PAD(0x35C, 0x34, 5, 0x7AC, 0, 0)
-#define _MX53_PAD_KEY_COL2__FEC_RDATA_2 IOMUX_PAD(0x35C, 0x34, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE IOMUX_PAD(0x35C, 0x34, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__KPP_ROW_2 IOMUX_PAD(0x360, 0x38, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__GPIO4_11 IOMUX_PAD(0x360, 0x38, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__CAN1_RXCAN IOMUX_PAD(0x360, 0x38, 2, 0x760, 0, 0)
-#define _MX53_PAD_KEY_ROW2__FEC_MDC IOMUX_PAD(0x360, 0x38, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__ECSPI1_SS2 IOMUX_PAD(0x360, 0x38, 5, 0x7B0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__FEC_TDATA_2 IOMUX_PAD(0x360, 0x38, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__USBPHY1_RXERROR IOMUX_PAD(0x360, 0x38, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__KPP_COL_3 IOMUX_PAD(0x364, 0x3C, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__GPIO4_12 IOMUX_PAD(0x364, 0x3C, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__USBOH3_H2_DP IOMUX_PAD(0x364, 0x3C, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__SPDIF_IN1 IOMUX_PAD(0x364, 0x3C, 3, 0x870, 0, 0)
-#define _MX53_PAD_KEY_COL3__I2C2_SCL IOMUX_PAD(0x364, 0x3C, 4 | IOMUX_CONFIG_SION, 0x81C, 0, 0)
-#define _MX53_PAD_KEY_COL3__ECSPI1_SS3 IOMUX_PAD(0x364, 0x3C, 5, 0x7B4, 0, 0)
-#define _MX53_PAD_KEY_COL3__FEC_CRS IOMUX_PAD(0x364, 0x3C, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK IOMUX_PAD(0x364, 0x3C, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__KPP_ROW_3 IOMUX_PAD(0x368, 0x40, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__GPIO4_13 IOMUX_PAD(0x368, 0x40, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__USBOH3_H2_DM IOMUX_PAD(0x368, 0x40, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK IOMUX_PAD(0x368, 0x40, 3, 0x768, 0, 0)
-#define _MX53_PAD_KEY_ROW3__I2C2_SDA IOMUX_PAD(0x368, 0x40, 4 | IOMUX_CONFIG_SION, 0x820, 0, 0)
-#define _MX53_PAD_KEY_ROW3__OSC32K_32K_OUT IOMUX_PAD(0x368, 0x40, 5, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__CCM_PLL4_BYP IOMUX_PAD(0x368, 0x40, 6, 0x77C, 0, 0)
-#define _MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 IOMUX_PAD(0x368, 0x40, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__KPP_COL_4 IOMUX_PAD(0x36C, 0x44, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__GPIO4_14 IOMUX_PAD(0x36C, 0x44, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__CAN2_TXCAN IOMUX_PAD(0x36C, 0x44, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__IPU_SISG_4 IOMUX_PAD(0x36C, 0x44, 3, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__UART5_RTS IOMUX_PAD(0x36C, 0x44, 4, 0x894, 0, 0)
-#define _MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC IOMUX_PAD(0x36C, 0x44, 5, 0x89C, 0, 0)
-#define _MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 IOMUX_PAD(0x36C, 0x44, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__KPP_ROW_4 IOMUX_PAD(0x370, 0x48, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__GPIO4_15 IOMUX_PAD(0x370, 0x48, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__CAN2_RXCAN IOMUX_PAD(0x370, 0x48, 2, 0x764, 0, 0)
-#define _MX53_PAD_KEY_ROW4__IPU_SISG_5 IOMUX_PAD(0x370, 0x48, 3, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__UART5_CTS IOMUX_PAD(0x370, 0x48, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR IOMUX_PAD(0x370, 0x48, 5, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID IOMUX_PAD(0x370, 0x48, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK IOMUX_PAD(0x378, 0x4C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__GPIO4_16 IOMUX_PAD(0x378, 0x4C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR IOMUX_PAD(0x378, 0x4C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 IOMUX_PAD(0x378, 0x4C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 IOMUX_PAD(0x378, 0x4C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID IOMUX_PAD(0x378, 0x4C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 IOMUX_PAD(0x37C, 0x50, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__GPIO4_17 IOMUX_PAD(0x37C, 0x50, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC IOMUX_PAD(0x37C, 0x50, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 IOMUX_PAD(0x37C, 0x50, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 IOMUX_PAD(0x37C, 0x50, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__USBPHY1_BVALID IOMUX_PAD(0x37C, 0x50, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 IOMUX_PAD(0x380, 0x54, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__GPIO4_18 IOMUX_PAD(0x380, 0x54, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD IOMUX_PAD(0x380, 0x54, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 IOMUX_PAD(0x380, 0x54, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 IOMUX_PAD(0x380, 0x54, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION IOMUX_PAD(0x380, 0x54, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 IOMUX_PAD(0x384, 0x58, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__GPIO4_19 IOMUX_PAD(0x384, 0x58, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS IOMUX_PAD(0x384, 0x58, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 IOMUX_PAD(0x384, 0x58, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 IOMUX_PAD(0x384, 0x58, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__USBPHY1_IDDIG IOMUX_PAD(0x384, 0x58, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 IOMUX_PAD(0x388, 0x5C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__GPIO4_20 IOMUX_PAD(0x388, 0x5C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD IOMUX_PAD(0x388, 0x5C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__ESDHC1_WP IOMUX_PAD(0x388, 0x5C, 3, 0x7FC, 0, 0)
-#define _MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD IOMUX_PAD(0x388, 0x5C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 IOMUX_PAD(0x388, 0x5C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT IOMUX_PAD(0x388, 0x5C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 IOMUX_PAD(0x38C, 0x60, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__GPIO4_21 IOMUX_PAD(0x38C, 0x60, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__CSPI_SCLK IOMUX_PAD(0x38C, 0x60, 2, 0x780, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 IOMUX_PAD(0x38C, 0x60, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN IOMUX_PAD(0x38C, 0x60, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 IOMUX_PAD(0x38C, 0x60, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY IOMUX_PAD(0x38C, 0x60, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 IOMUX_PAD(0x390, 0x64, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__GPIO4_22 IOMUX_PAD(0x390, 0x64, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__CSPI_MOSI IOMUX_PAD(0x390, 0x64, 2, 0x788, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 IOMUX_PAD(0x390, 0x64, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL IOMUX_PAD(0x390, 0x64, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 IOMUX_PAD(0x390, 0x64, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID IOMUX_PAD(0x390, 0x64, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 IOMUX_PAD(0x394, 0x68, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__GPIO4_23 IOMUX_PAD(0x394, 0x68, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__CSPI_MISO IOMUX_PAD(0x394, 0x68, 2, 0x784, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 IOMUX_PAD(0x394, 0x68, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE IOMUX_PAD(0x394, 0x68, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 IOMUX_PAD(0x394, 0x68, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE IOMUX_PAD(0x394, 0x68, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 IOMUX_PAD(0x398, 0x6C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__GPIO4_24 IOMUX_PAD(0x398, 0x6C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__CSPI_SS0 IOMUX_PAD(0x398, 0x6C, 2, 0x78C, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 IOMUX_PAD(0x398, 0x6C, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR IOMUX_PAD(0x398, 0x6C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 IOMUX_PAD(0x398, 0x6C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR IOMUX_PAD(0x398, 0x6C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 IOMUX_PAD(0x39C, 0x70, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__GPIO4_25 IOMUX_PAD(0x39C, 0x70, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__CSPI_SS1 IOMUX_PAD(0x39C, 0x70, 2, 0x790, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 IOMUX_PAD(0x39C, 0x70, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB IOMUX_PAD(0x39C, 0x70, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 IOMUX_PAD(0x39C, 0x70, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK IOMUX_PAD(0x39C, 0x70, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 IOMUX_PAD(0x3A0, 0x74, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__GPIO4_26 IOMUX_PAD(0x3A0, 0x74, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__CSPI_SS2 IOMUX_PAD(0x3A0, 0x74, 2, 0x794, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 IOMUX_PAD(0x3A0, 0x74, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS IOMUX_PAD(0x3A0, 0x74, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 IOMUX_PAD(0x3A0, 0x74, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 IOMUX_PAD(0x3A0, 0x74, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 IOMUX_PAD(0x3A4, 0x78, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__GPIO4_27 IOMUX_PAD(0x3A4, 0x78, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__CSPI_SS3 IOMUX_PAD(0x3A4, 0x78, 2, 0x798, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 IOMUX_PAD(0x3A4, 0x78, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE IOMUX_PAD(0x3A4, 0x78, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 IOMUX_PAD(0x3A4, 0x78, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 IOMUX_PAD(0x3A4, 0x78, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 IOMUX_PAD(0x3A8, 0x7C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__GPIO4_28 IOMUX_PAD(0x3A8, 0x7C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__CSPI_RDY IOMUX_PAD(0x3A8, 0x7C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 IOMUX_PAD(0x3A8, 0x7C, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 IOMUX_PAD(0x3A8, 0x7C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 IOMUX_PAD(0x3A8, 0x7C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID IOMUX_PAD(0x3A8, 0x7C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 IOMUX_PAD(0x3AC, 0x80, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__GPIO4_29 IOMUX_PAD(0x3AC, 0x80, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__PWM1_PWMO IOMUX_PAD(0x3AC, 0x80, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B IOMUX_PAD(0x3AC, 0x80, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 IOMUX_PAD(0x3AC, 0x80, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 IOMUX_PAD(0x3AC, 0x80, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__USBPHY2_AVALID IOMUX_PAD(0x3AC, 0x80, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 IOMUX_PAD(0x3B0, 0x84, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__GPIO4_30 IOMUX_PAD(0x3B0, 0x84, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__PWM2_PWMO IOMUX_PAD(0x3B0, 0x84, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B IOMUX_PAD(0x3B0, 0x84, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 IOMUX_PAD(0x3B0, 0x84, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 IOMUX_PAD(0x3B0, 0x84, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 IOMUX_PAD(0x3B0, 0x84, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 IOMUX_PAD(0x3B4, 0x88, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__GPIO4_31 IOMUX_PAD(0x3B4, 0x88, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP IOMUX_PAD(0x3B4, 0x88, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 IOMUX_PAD(0x3B4, 0x88, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 IOMUX_PAD(0x3B4, 0x88, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 IOMUX_PAD(0x3B4, 0x88, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 IOMUX_PAD(0x3B8, 0x8C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__GPIO5_5 IOMUX_PAD(0x3B8, 0x8C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT IOMUX_PAD(0x3B8, 0x8C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 IOMUX_PAD(0x3B8, 0x8C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 IOMUX_PAD(0x3B8, 0x8C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 IOMUX_PAD(0x3B8, 0x8C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 IOMUX_PAD(0x3BC, 0x90, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__GPIO5_6 IOMUX_PAD(0x3BC, 0x90, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK IOMUX_PAD(0x3BC, 0x90, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 IOMUX_PAD(0x3BC, 0x90, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 IOMUX_PAD(0x3BC, 0x90, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 IOMUX_PAD(0x3BC, 0x90, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 IOMUX_PAD(0x3C0, 0x94, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__GPIO5_7 IOMUX_PAD(0x3C0, 0x94, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS IOMUX_PAD(0x3C0, 0x94, 3, 0x754, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 IOMUX_PAD(0x3C0, 0x94, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 IOMUX_PAD(0x3C0, 0x94, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 IOMUX_PAD(0x3C0, 0x94, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 IOMUX_PAD(0x3C4, 0x98, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__GPIO5_8 IOMUX_PAD(0x3C4, 0x98, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC IOMUX_PAD(0x3C4, 0x98, 3, 0x750, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 IOMUX_PAD(0x3C4, 0x98, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 IOMUX_PAD(0x3C4, 0x98, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 IOMUX_PAD(0x3C4, 0x98, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 IOMUX_PAD(0x3C8, 0x9C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__GPIO5_9 IOMUX_PAD(0x3C8, 0x9C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__ECSPI1_SS1 IOMUX_PAD(0x3C8, 0x9C, 2, 0x7AC, 1, 0)
-#define _MX53_PAD_DISP0_DAT15__ECSPI2_SS1 IOMUX_PAD(0x3C8, 0x9C, 3, 0x7C8, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 IOMUX_PAD(0x3C8, 0x9C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 IOMUX_PAD(0x3C8, 0x9C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 IOMUX_PAD(0x3C8, 0x9C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 IOMUX_PAD(0x3CC, 0xA0, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__GPIO5_10 IOMUX_PAD(0x3CC, 0xA0, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__ECSPI2_MOSI IOMUX_PAD(0x3CC, 0xA0, 2, 0x7C0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC IOMUX_PAD(0x3CC, 0xA0, 3, 0x758, 1, 0)
-#define _MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 IOMUX_PAD(0x3CC, 0xA0, 4, 0x868, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 IOMUX_PAD(0x3CC, 0xA0, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 IOMUX_PAD(0x3CC, 0xA0, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 IOMUX_PAD(0x3CC, 0xA0, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 IOMUX_PAD(0x3D0, 0xA4, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__GPIO5_11 IOMUX_PAD(0x3D0, 0xA4, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__ECSPI2_MISO IOMUX_PAD(0x3D0, 0xA4, 2, 0x7BC, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD IOMUX_PAD(0x3D0, 0xA4, 3, 0x74C, 1, 0)
-#define _MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 IOMUX_PAD(0x3D0, 0xA4, 4, 0x86C, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 IOMUX_PAD(0x3D0, 0xA4, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 IOMUX_PAD(0x3D0, 0xA4, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 IOMUX_PAD(0x3D4, 0xA8, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__GPIO5_12 IOMUX_PAD(0x3D4, 0xA8, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__ECSPI2_SS0 IOMUX_PAD(0x3D4, 0xA8, 2, 0x7C4, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS IOMUX_PAD(0x3D4, 0xA8, 3, 0x75C, 1, 0)
-#define _MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS IOMUX_PAD(0x3D4, 0xA8, 4, 0x73C, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 IOMUX_PAD(0x3D4, 0xA8, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 IOMUX_PAD(0x3D4, 0xA8, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 IOMUX_PAD(0x3D4, 0xA8, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 IOMUX_PAD(0x3D8, 0xAC, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__GPIO5_13 IOMUX_PAD(0x3D8, 0xAC, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__ECSPI2_SCLK IOMUX_PAD(0x3D8, 0xAC, 2, 0x7B8, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD IOMUX_PAD(0x3D8, 0xAC, 3, 0x748, 1, 0)
-#define _MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC IOMUX_PAD(0x3D8, 0xAC, 4, 0x738, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 IOMUX_PAD(0x3D8, 0xAC, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 IOMUX_PAD(0x3D8, 0xAC, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 IOMUX_PAD(0x3D8, 0xAC, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 IOMUX_PAD(0x3DC, 0xB0, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__GPIO5_14 IOMUX_PAD(0x3DC, 0xB0, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__ECSPI1_SCLK IOMUX_PAD(0x3DC, 0xB0, 2, 0x79C, 1, 0)
-#define _MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC IOMUX_PAD(0x3DC, 0xB0, 3, 0x740, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 IOMUX_PAD(0x3DC, 0xB0, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 IOMUX_PAD(0x3DC, 0xB0, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__SATA_PHY_TDI IOMUX_PAD(0x3DC, 0xB0, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 IOMUX_PAD(0x3E0, 0xB4, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__GPIO5_15 IOMUX_PAD(0x3E0, 0xB4, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__ECSPI1_MOSI IOMUX_PAD(0x3E0, 0xB4, 2, 0x7A4, 1, 0)
-#define _MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD IOMUX_PAD(0x3E0, 0xB4, 3, 0x734, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 IOMUX_PAD(0x3E0, 0xB4, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 IOMUX_PAD(0x3E0, 0xB4, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__SATA_PHY_TDO IOMUX_PAD(0x3E0, 0xB4, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 IOMUX_PAD(0x3E4, 0xB8, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__GPIO5_16 IOMUX_PAD(0x3E4, 0xB8, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__ECSPI1_MISO IOMUX_PAD(0x3E4, 0xB8, 2, 0x7A0, 1, 0)
-#define _MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS IOMUX_PAD(0x3E4, 0xB8, 3, 0x744, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 IOMUX_PAD(0x3E4, 0xB8, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 IOMUX_PAD(0x3E4, 0xB8, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__SATA_PHY_TCK IOMUX_PAD(0x3E4, 0xB8, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 IOMUX_PAD(0x3E8, 0xBC, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__GPIO5_17 IOMUX_PAD(0x3E8, 0xBC, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__ECSPI1_SS0 IOMUX_PAD(0x3E8, 0xBC, 2, 0x7A8, 1, 0)
-#define _MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD IOMUX_PAD(0x3E8, 0xBC, 3, 0x730, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 IOMUX_PAD(0x3E8, 0xBC, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 IOMUX_PAD(0x3E8, 0xBC, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__SATA_PHY_TMS IOMUX_PAD(0x3E8, 0xBC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK IOMUX_PAD(0x3EC, 0xC0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__GPIO5_18 IOMUX_PAD(0x3EC, 0xC0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 IOMUX_PAD(0x3EC, 0xC0, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 IOMUX_PAD(0x3EC, 0xC0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC IOMUX_PAD(0x3F0, 0xC4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__GPIO5_19 IOMUX_PAD(0x3F0, 0xC4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK IOMUX_PAD(0x3F0, 0xC4, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 IOMUX_PAD(0x3F0, 0xC4, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 IOMUX_PAD(0x3F0, 0xC4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__TPIU_TRCTL IOMUX_PAD(0x3F0, 0xC4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN IOMUX_PAD(0x3F4, 0xC8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__GPIO5_20 IOMUX_PAD(0x3F4, 0xC8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 IOMUX_PAD(0x3F4, 0xC8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 IOMUX_PAD(0x3F4, 0xC8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK IOMUX_PAD(0x3F4, 0xC8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC IOMUX_PAD(0x3F8, 0xCC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__GPIO5_21 IOMUX_PAD(0x3F8, 0xCC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 IOMUX_PAD(0x3F8, 0xCC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 IOMUX_PAD(0x3F8, 0xCC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 IOMUX_PAD(0x3F8, 0xCC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 IOMUX_PAD(0x3FC, 0xD0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__GPIO5_22 IOMUX_PAD(0x3FC, 0xD0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__KPP_COL_5 IOMUX_PAD(0x3FC, 0xD0, 2, 0x840, 1, 0)
-#define _MX53_PAD_CSI0_DAT4__ECSPI1_SCLK IOMUX_PAD(0x3FC, 0xD0, 3, 0x79C, 2, 0)
-#define _MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP IOMUX_PAD(0x3FC, 0xD0, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC IOMUX_PAD(0x3FC, 0xD0, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 IOMUX_PAD(0x3FC, 0xD0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 IOMUX_PAD(0x3FC, 0xD0, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 IOMUX_PAD(0x400, 0xD4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__GPIO5_23 IOMUX_PAD(0x400, 0xD4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__KPP_ROW_5 IOMUX_PAD(0x400, 0xD4, 2, 0x84C, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__ECSPI1_MOSI IOMUX_PAD(0x400, 0xD4, 3, 0x7A4, 2, 0)
-#define _MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT IOMUX_PAD(0x400, 0xD4, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD IOMUX_PAD(0x400, 0xD4, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 IOMUX_PAD(0x400, 0xD4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 IOMUX_PAD(0x400, 0xD4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 IOMUX_PAD(0x404, 0xD8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__GPIO5_24 IOMUX_PAD(0x404, 0xD8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__KPP_COL_6 IOMUX_PAD(0x404, 0xD8, 2, 0x844, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__ECSPI1_MISO IOMUX_PAD(0x404, 0xD8, 3, 0x7A0, 2, 0)
-#define _MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK IOMUX_PAD(0x404, 0xD8, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS IOMUX_PAD(0x404, 0xD8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 IOMUX_PAD(0x404, 0xD8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 IOMUX_PAD(0x404, 0xD8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 IOMUX_PAD(0x408, 0xDC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__GPIO5_25 IOMUX_PAD(0x408, 0xDC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__KPP_ROW_6 IOMUX_PAD(0x408, 0xDC, 2, 0x850, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__ECSPI1_SS0 IOMUX_PAD(0x408, 0xDC, 3, 0x7A8, 2, 0)
-#define _MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR IOMUX_PAD(0x408, 0xDC, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD IOMUX_PAD(0x408, 0xDC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 IOMUX_PAD(0x408, 0xDC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 IOMUX_PAD(0x408, 0xDC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 IOMUX_PAD(0x40C, 0xE0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__GPIO5_26 IOMUX_PAD(0x40C, 0xE0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__KPP_COL_7 IOMUX_PAD(0x40C, 0xE0, 2, 0x848, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__ECSPI2_SCLK IOMUX_PAD(0x40C, 0xE0, 3, 0x7B8, 1, 0)
-#define _MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC IOMUX_PAD(0x40C, 0xE0, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__I2C1_SDA IOMUX_PAD(0x40C, 0xE0, 5 | IOMUX_CONFIG_SION, 0x818, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 IOMUX_PAD(0x40C, 0xE0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 IOMUX_PAD(0x40C, 0xE0, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 IOMUX_PAD(0x410, 0xE4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__GPIO5_27 IOMUX_PAD(0x410, 0xE4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__KPP_ROW_7 IOMUX_PAD(0x410, 0xE4, 2, 0x854, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__ECSPI2_MOSI IOMUX_PAD(0x410, 0xE4, 3, 0x7C0, 1, 0)
-#define _MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR IOMUX_PAD(0x410, 0xE4, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__I2C1_SCL IOMUX_PAD(0x410, 0xE4, 5 | IOMUX_CONFIG_SION, 0x814, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 IOMUX_PAD(0x410, 0xE4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 IOMUX_PAD(0x410, 0xE4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 IOMUX_PAD(0x414, 0xE8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__GPIO5_28 IOMUX_PAD(0x414, 0xE8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__UART1_TXD_MUX IOMUX_PAD(0x414, 0xE8, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__ECSPI2_MISO IOMUX_PAD(0x414, 0xE8, 3, 0x7BC, 1, 0)
-#define _MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC IOMUX_PAD(0x414, 0xE8, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 IOMUX_PAD(0x414, 0xE8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 IOMUX_PAD(0x414, 0xE8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 IOMUX_PAD(0x414, 0xE8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 IOMUX_PAD(0x418, 0xEC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__GPIO5_29 IOMUX_PAD(0x418, 0xEC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__UART1_RXD_MUX IOMUX_PAD(0x418, 0xEC, 2, 0x878, 1, 0)
-#define _MX53_PAD_CSI0_DAT11__ECSPI2_SS0 IOMUX_PAD(0x418, 0xEC, 3, 0x7C4, 1, 0)
-#define _MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS IOMUX_PAD(0x418, 0xEC, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 IOMUX_PAD(0x418, 0xEC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 IOMUX_PAD(0x418, 0xEC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 IOMUX_PAD(0x418, 0xEC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 IOMUX_PAD(0x41C, 0xF0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__GPIO5_30 IOMUX_PAD(0x41C, 0xF0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__UART4_TXD_MUX IOMUX_PAD(0x41C, 0xF0, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 IOMUX_PAD(0x41C, 0xF0, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 IOMUX_PAD(0x41C, 0xF0, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 IOMUX_PAD(0x41C, 0xF0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 IOMUX_PAD(0x41C, 0xF0, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 IOMUX_PAD(0x420, 0xF4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__GPIO5_31 IOMUX_PAD(0x420, 0xF4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__UART4_RXD_MUX IOMUX_PAD(0x420, 0xF4, 2, 0x890, 3, 0)
-#define _MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 IOMUX_PAD(0x420, 0xF4, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 IOMUX_PAD(0x420, 0xF4, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 IOMUX_PAD(0x420, 0xF4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 IOMUX_PAD(0x420, 0xF4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 IOMUX_PAD(0x424, 0xF8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__GPIO6_0 IOMUX_PAD(0x424, 0xF8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__UART5_TXD_MUX IOMUX_PAD(0x424, 0xF8, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 IOMUX_PAD(0x424, 0xF8, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 IOMUX_PAD(0x424, 0xF8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 IOMUX_PAD(0x424, 0xF8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 IOMUX_PAD(0x424, 0xF8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 IOMUX_PAD(0x428, 0xFC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__GPIO6_1 IOMUX_PAD(0x428, 0xFC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__UART5_RXD_MUX IOMUX_PAD(0x428, 0xFC, 2, 0x898, 3, 0)
-#define _MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 IOMUX_PAD(0x428, 0xFC, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 IOMUX_PAD(0x428, 0xFC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 IOMUX_PAD(0x428, 0xFC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 IOMUX_PAD(0x428, 0xFC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 IOMUX_PAD(0x42C, 0x100, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__GPIO6_2 IOMUX_PAD(0x42C, 0x100, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__UART4_RTS IOMUX_PAD(0x42C, 0x100, 2, 0x88C, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 IOMUX_PAD(0x42C, 0x100, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 IOMUX_PAD(0x42C, 0x100, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 IOMUX_PAD(0x42C, 0x100, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 IOMUX_PAD(0x42C, 0x100, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 IOMUX_PAD(0x430, 0x104, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__GPIO6_3 IOMUX_PAD(0x430, 0x104, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__UART4_CTS IOMUX_PAD(0x430, 0x104, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 IOMUX_PAD(0x430, 0x104, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 IOMUX_PAD(0x430, 0x104, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 IOMUX_PAD(0x430, 0x104, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 IOMUX_PAD(0x430, 0x104, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 IOMUX_PAD(0x434, 0x108, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__GPIO6_4 IOMUX_PAD(0x434, 0x108, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__UART5_RTS IOMUX_PAD(0x434, 0x108, 2, 0x894, 2, 0)
-#define _MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 IOMUX_PAD(0x434, 0x108, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 IOMUX_PAD(0x434, 0x108, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 IOMUX_PAD(0x434, 0x108, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 IOMUX_PAD(0x434, 0x108, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 IOMUX_PAD(0x438, 0x10C, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__GPIO6_5 IOMUX_PAD(0x438, 0x10C, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__UART5_CTS IOMUX_PAD(0x438, 0x10C, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 IOMUX_PAD(0x438, 0x10C, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 IOMUX_PAD(0x438, 0x10C, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 IOMUX_PAD(0x438, 0x10C, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK IOMUX_PAD(0x438, 0x10C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__EMI_WEIM_A_25 IOMUX_PAD(0x458, 0x110, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__GPIO5_2 IOMUX_PAD(0x458, 0x110, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__ECSPI2_RDY IOMUX_PAD(0x458, 0x110, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__IPU_DI1_PIN12 IOMUX_PAD(0x458, 0x110, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__CSPI_SS1 IOMUX_PAD(0x458, 0x110, 4, 0x790, 1, 0)
-#define _MX53_PAD_EIM_A25__IPU_DI0_D1_CS IOMUX_PAD(0x458, 0x110, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__USBPHY1_BISTOK IOMUX_PAD(0x458, 0x110, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 IOMUX_PAD(0x45C, 0x114, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__GPIO2_30 IOMUX_PAD(0x45C, 0x114, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK IOMUX_PAD(0x45C, 0x114, 2, 0x76C, 0, 0)
-#define _MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS IOMUX_PAD(0x45C, 0x114, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__ECSPI1_SS0 IOMUX_PAD(0x45C, 0x114, 4, 0x7A8, 3, 0)
-#define _MX53_PAD_EIM_EB2__I2C2_SCL IOMUX_PAD(0x45C, 0x114, 5 | IOMUX_CONFIG_SION, 0x81C, 1, 0)
-#define _MX53_PAD_EIM_D16__EMI_WEIM_D_16 IOMUX_PAD(0x460, 0x118, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__GPIO3_16 IOMUX_PAD(0x460, 0x118, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__IPU_DI0_PIN5 IOMUX_PAD(0x460, 0x118, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK IOMUX_PAD(0x460, 0x118, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__ECSPI1_SCLK IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, 0)
-#define _MX53_PAD_EIM_D16__I2C2_SDA IOMUX_PAD(0x460, 0x118, 5 | IOMUX_CONFIG_SION, 0x820, 1, 0)
-#define _MX53_PAD_EIM_D17__EMI_WEIM_D_17 IOMUX_PAD(0x464, 0x11C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D17__GPIO3_17 IOMUX_PAD(0x464, 0x11C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D17__IPU_DI0_PIN6 IOMUX_PAD(0x464, 0x11C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, 0)
-#define _MX53_PAD_EIM_D17__ECSPI1_MISO IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, 0)
-#define _MX53_PAD_EIM_D17__I2C3_SCL IOMUX_PAD(0x464, 0x11C, 5 | IOMUX_CONFIG_SION, 0x824, 0, 0)
-#define _MX53_PAD_EIM_D18__EMI_WEIM_D_18 IOMUX_PAD(0x468, 0x120, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D18__GPIO3_18 IOMUX_PAD(0x468, 0x120, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D18__IPU_DI0_PIN7 IOMUX_PAD(0x468, 0x120, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, 0)
-#define _MX53_PAD_EIM_D18__ECSPI1_MOSI IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, 0)
-#define _MX53_PAD_EIM_D18__I2C3_SDA IOMUX_PAD(0x468, 0x120, 5 | IOMUX_CONFIG_SION, 0x828, 0, 0)
-#define _MX53_PAD_EIM_D18__IPU_DI1_D0_CS IOMUX_PAD(0x468, 0x120, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__EMI_WEIM_D_19 IOMUX_PAD(0x46C, 0x124, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__GPIO3_19 IOMUX_PAD(0x46C, 0x124, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__IPU_DI0_PIN8 IOMUX_PAD(0x46C, 0x124, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS IOMUX_PAD(0x46C, 0x124, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__ECSPI1_SS1 IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, 0)
-#define _MX53_PAD_EIM_D19__EPIT1_EPITO IOMUX_PAD(0x46C, 0x124, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__UART1_CTS IOMUX_PAD(0x46C, 0x124, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__USBOH3_USBH2_OC IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, 0)
-#define _MX53_PAD_EIM_D20__EMI_WEIM_D_20 IOMUX_PAD(0x470, 0x128, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__GPIO3_20 IOMUX_PAD(0x470, 0x128, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__IPU_DI0_PIN16 IOMUX_PAD(0x470, 0x128, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__IPU_SER_DISP0_CS IOMUX_PAD(0x470, 0x128, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__CSPI_SS0 IOMUX_PAD(0x470, 0x128, 4, 0x78C, 1, 0)
-#define _MX53_PAD_EIM_D20__EPIT2_EPITO IOMUX_PAD(0x470, 0x128, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__UART1_RTS IOMUX_PAD(0x470, 0x128, 6, 0x874, 1, 0)
-#define _MX53_PAD_EIM_D20__USBOH3_USBH2_PWR IOMUX_PAD(0x470, 0x128, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__EMI_WEIM_D_21 IOMUX_PAD(0x474, 0x12C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__GPIO3_21 IOMUX_PAD(0x474, 0x12C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__IPU_DI0_PIN17 IOMUX_PAD(0x474, 0x12C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK IOMUX_PAD(0x474, 0x12C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__CSPI_SCLK IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, 0)
-#define _MX53_PAD_EIM_D21__I2C1_SCL IOMUX_PAD(0x474, 0x12C, 5 | IOMUX_CONFIG_SION, 0x814, 1, 0)
-#define _MX53_PAD_EIM_D21__USBOH3_USBOTG_OC IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, 0)
-#define _MX53_PAD_EIM_D22__EMI_WEIM_D_22 IOMUX_PAD(0x478, 0x130, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D22__GPIO3_22 IOMUX_PAD(0x478, 0x130, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D22__IPU_DI0_PIN1 IOMUX_PAD(0x478, 0x130, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN IOMUX_PAD(0x478, 0x130, 3, 0x82C, 0, 0)
-#define _MX53_PAD_EIM_D22__CSPI_MISO IOMUX_PAD(0x478, 0x130, 4, 0x784, 1, 0)
-#define _MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR IOMUX_PAD(0x478, 0x130, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__EMI_WEIM_D_23 IOMUX_PAD(0x47C, 0x134, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__GPIO3_23 IOMUX_PAD(0x47C, 0x134, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__UART3_CTS IOMUX_PAD(0x47C, 0x134, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__UART1_DCD IOMUX_PAD(0x47C, 0x134, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_DI0_D0_CS IOMUX_PAD(0x47C, 0x134, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_DI1_PIN2 IOMUX_PAD(0x47C, 0x134, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN IOMUX_PAD(0x47C, 0x134, 6, 0x834, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_DI1_PIN14 IOMUX_PAD(0x47C, 0x134, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 IOMUX_PAD(0x480, 0x138, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__GPIO2_31 IOMUX_PAD(0x480, 0x138, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__UART3_RTS IOMUX_PAD(0x480, 0x138, 2, 0x884, 1, 0)
-#define _MX53_PAD_EIM_EB3__UART1_RI IOMUX_PAD(0x480, 0x138, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__IPU_DI1_PIN3 IOMUX_PAD(0x480, 0x138, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC IOMUX_PAD(0x480, 0x138, 6, 0x838, 0, 0)
-#define _MX53_PAD_EIM_EB3__IPU_DI1_PIN16 IOMUX_PAD(0x480, 0x138, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__EMI_WEIM_D_24 IOMUX_PAD(0x484, 0x13C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__GPIO3_24 IOMUX_PAD(0x484, 0x13C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__UART3_TXD_MUX IOMUX_PAD(0x484, 0x13C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__ECSPI1_SS2 IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, 0)
-#define _MX53_PAD_EIM_D24__CSPI_SS2 IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, 0)
-#define _MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, 0)
-#define _MX53_PAD_EIM_D24__ECSPI2_SS2 IOMUX_PAD(0x484, 0x13C, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__UART1_DTR IOMUX_PAD(0x484, 0x13C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__EMI_WEIM_D_25 IOMUX_PAD(0x488, 0x140, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__GPIO3_25 IOMUX_PAD(0x488, 0x140, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__UART3_RXD_MUX IOMUX_PAD(0x488, 0x140, 2, 0x888, 1, 0)
-#define _MX53_PAD_EIM_D25__ECSPI1_SS3 IOMUX_PAD(0x488, 0x140, 3, 0x7B4, 1, 0)
-#define _MX53_PAD_EIM_D25__CSPI_SS3 IOMUX_PAD(0x488, 0x140, 4, 0x798, 1, 0)
-#define _MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC IOMUX_PAD(0x488, 0x140, 5, 0x750, 1, 0)
-#define _MX53_PAD_EIM_D25__ECSPI2_SS3 IOMUX_PAD(0x488, 0x140, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__UART1_DSR IOMUX_PAD(0x488, 0x140, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__EMI_WEIM_D_26 IOMUX_PAD(0x48C, 0x144, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__GPIO3_26 IOMUX_PAD(0x48C, 0x144, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__UART2_TXD_MUX IOMUX_PAD(0x48C, 0x144, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__FIRI_RXD IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_CSI0_D_1 IOMUX_PAD(0x48C, 0x144, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_DI1_PIN11 IOMUX_PAD(0x48C, 0x144, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_SISG_2 IOMUX_PAD(0x48C, 0x144, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 IOMUX_PAD(0x48C, 0x144, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__EMI_WEIM_D_27 IOMUX_PAD(0x490, 0x148, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__GPIO3_27 IOMUX_PAD(0x490, 0x148, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__UART2_RXD_MUX IOMUX_PAD(0x490, 0x148, 2, 0x880, 1, 0)
-#define _MX53_PAD_EIM_D27__FIRI_TXD IOMUX_PAD(0x490, 0x148, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_CSI0_D_0 IOMUX_PAD(0x490, 0x148, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_DI1_PIN13 IOMUX_PAD(0x490, 0x148, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_SISG_3 IOMUX_PAD(0x490, 0x148, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 IOMUX_PAD(0x490, 0x148, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__EMI_WEIM_D_28 IOMUX_PAD(0x494, 0x14C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__GPIO3_28 IOMUX_PAD(0x494, 0x14C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__UART2_CTS IOMUX_PAD(0x494, 0x14C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, 0)
-#define _MX53_PAD_EIM_D28__CSPI_MOSI IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, 0)
-#define _MX53_PAD_EIM_D28__I2C1_SDA IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, 0)
-#define _MX53_PAD_EIM_D28__IPU_EXT_TRIG IOMUX_PAD(0x494, 0x14C, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__IPU_DI0_PIN13 IOMUX_PAD(0x494, 0x14C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__EMI_WEIM_D_29 IOMUX_PAD(0x498, 0x150, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__GPIO3_29 IOMUX_PAD(0x498, 0x150, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__UART2_RTS IOMUX_PAD(0x498, 0x150, 2, 0x87C, 1, 0)
-#define _MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS IOMUX_PAD(0x498, 0x150, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__CSPI_SS0 IOMUX_PAD(0x498, 0x150, 4, 0x78C, 2, 0)
-#define _MX53_PAD_EIM_D29__IPU_DI1_PIN15 IOMUX_PAD(0x498, 0x150, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__IPU_CSI1_VSYNC IOMUX_PAD(0x498, 0x150, 6, 0x83C, 0, 0)
-#define _MX53_PAD_EIM_D29__IPU_DI0_PIN14 IOMUX_PAD(0x498, 0x150, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__EMI_WEIM_D_30 IOMUX_PAD(0x49C, 0x154, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__GPIO3_30 IOMUX_PAD(0x49C, 0x154, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__UART3_CTS IOMUX_PAD(0x49C, 0x154, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__IPU_CSI0_D_3 IOMUX_PAD(0x49C, 0x154, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__IPU_DI0_PIN11 IOMUX_PAD(0x49C, 0x154, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 IOMUX_PAD(0x49C, 0x154, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__USBOH3_USBH1_OC IOMUX_PAD(0x49C, 0x154, 6, 0x8A0, 0, 0)
-#define _MX53_PAD_EIM_D30__USBOH3_USBH2_OC IOMUX_PAD(0x49C, 0x154, 7, 0x8A4, 1, 0)
-#define _MX53_PAD_EIM_D31__EMI_WEIM_D_31 IOMUX_PAD(0x4A0, 0x158, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__GPIO3_31 IOMUX_PAD(0x4A0, 0x158, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__UART3_RTS IOMUX_PAD(0x4A0, 0x158, 2, 0x884, 3, 0)
-#define _MX53_PAD_EIM_D31__IPU_CSI0_D_2 IOMUX_PAD(0x4A0, 0x158, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__IPU_DI0_PIN12 IOMUX_PAD(0x4A0, 0x158, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 IOMUX_PAD(0x4A0, 0x158, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__USBOH3_USBH1_PWR IOMUX_PAD(0x4A0, 0x158, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__USBOH3_USBH2_PWR IOMUX_PAD(0x4A0, 0x158, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__EMI_WEIM_A_24 IOMUX_PAD(0x4A8, 0x15C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__GPIO5_4 IOMUX_PAD(0x4A8, 0x15C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 IOMUX_PAD(0x4A8, 0x15C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__IPU_CSI1_D_19 IOMUX_PAD(0x4A8, 0x15C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__IPU_SISG_2 IOMUX_PAD(0x4A8, 0x15C, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__USBPHY2_BVALID IOMUX_PAD(0x4A8, 0x15C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__EMI_WEIM_A_23 IOMUX_PAD(0x4AC, 0x160, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__GPIO6_6 IOMUX_PAD(0x4AC, 0x160, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 IOMUX_PAD(0x4AC, 0x160, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__IPU_CSI1_D_18 IOMUX_PAD(0x4AC, 0x160, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__IPU_SISG_3 IOMUX_PAD(0x4AC, 0x160, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__USBPHY2_ENDSESSION IOMUX_PAD(0x4AC, 0x160, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__EMI_WEIM_A_22 IOMUX_PAD(0x4B0, 0x164, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__GPIO2_16 IOMUX_PAD(0x4B0, 0x164, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 IOMUX_PAD(0x4B0, 0x164, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__IPU_CSI1_D_17 IOMUX_PAD(0x4B0, 0x164, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__SRC_BT_CFG1_7 IOMUX_PAD(0x4B0, 0x164, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__EMI_WEIM_A_21 IOMUX_PAD(0x4B4, 0x168, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__GPIO2_17 IOMUX_PAD(0x4B4, 0x168, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 IOMUX_PAD(0x4B4, 0x168, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__IPU_CSI1_D_16 IOMUX_PAD(0x4B4, 0x168, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__SRC_BT_CFG1_6 IOMUX_PAD(0x4B4, 0x168, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__EMI_WEIM_A_20 IOMUX_PAD(0x4B8, 0x16C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__GPIO2_18 IOMUX_PAD(0x4B8, 0x16C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 IOMUX_PAD(0x4B8, 0x16C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__IPU_CSI1_D_15 IOMUX_PAD(0x4B8, 0x16C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__SRC_BT_CFG1_5 IOMUX_PAD(0x4B8, 0x16C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__EMI_WEIM_A_19 IOMUX_PAD(0x4BC, 0x170, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__GPIO2_19 IOMUX_PAD(0x4BC, 0x170, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 IOMUX_PAD(0x4BC, 0x170, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__IPU_CSI1_D_14 IOMUX_PAD(0x4BC, 0x170, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__SRC_BT_CFG1_4 IOMUX_PAD(0x4BC, 0x170, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__EMI_WEIM_A_18 IOMUX_PAD(0x4C0, 0x174, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__GPIO2_20 IOMUX_PAD(0x4C0, 0x174, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 IOMUX_PAD(0x4C0, 0x174, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__IPU_CSI1_D_13 IOMUX_PAD(0x4C0, 0x174, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__SRC_BT_CFG1_3 IOMUX_PAD(0x4C0, 0x174, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__EMI_WEIM_A_17 IOMUX_PAD(0x4C4, 0x178, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__GPIO2_21 IOMUX_PAD(0x4C4, 0x178, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 IOMUX_PAD(0x4C4, 0x178, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__IPU_CSI1_D_12 IOMUX_PAD(0x4C4, 0x178, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__SRC_BT_CFG1_2 IOMUX_PAD(0x4C4, 0x178, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__EMI_WEIM_A_16 IOMUX_PAD(0x4C8, 0x17C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__GPIO2_22 IOMUX_PAD(0x4C8, 0x17C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK IOMUX_PAD(0x4C8, 0x17C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK IOMUX_PAD(0x4C8, 0x17C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__SRC_BT_CFG1_1 IOMUX_PAD(0x4C8, 0x17C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 IOMUX_PAD(0x4CC, 0x180, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS0__GPIO2_23 IOMUX_PAD(0x4CC, 0x180, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS0__ECSPI2_SCLK IOMUX_PAD(0x4CC, 0x180, 2, 0x7B8, 2, 0)
-#define _MX53_PAD_EIM_CS0__IPU_DI1_PIN5 IOMUX_PAD(0x4CC, 0x180, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 IOMUX_PAD(0x4D0, 0x184, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS1__GPIO2_24 IOMUX_PAD(0x4D0, 0x184, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS1__ECSPI2_MOSI IOMUX_PAD(0x4D0, 0x184, 2, 0x7C0, 2, 0)
-#define _MX53_PAD_EIM_CS1__IPU_DI1_PIN6 IOMUX_PAD(0x4D0, 0x184, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__EMI_WEIM_OE IOMUX_PAD(0x4D4, 0x188, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__GPIO2_25 IOMUX_PAD(0x4D4, 0x188, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__ECSPI2_MISO IOMUX_PAD(0x4D4, 0x188, 2, 0x7BC, 2, 0)
-#define _MX53_PAD_EIM_OE__IPU_DI1_PIN7 IOMUX_PAD(0x4D4, 0x188, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__USBPHY2_IDDIG IOMUX_PAD(0x4D4, 0x188, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__EMI_WEIM_RW IOMUX_PAD(0x4D8, 0x18C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__GPIO2_26 IOMUX_PAD(0x4D8, 0x18C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__ECSPI2_SS0 IOMUX_PAD(0x4D8, 0x18C, 2, 0x7C4, 2, 0)
-#define _MX53_PAD_EIM_RW__IPU_DI1_PIN8 IOMUX_PAD(0x4D8, 0x18C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT IOMUX_PAD(0x4D8, 0x18C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__EMI_WEIM_LBA IOMUX_PAD(0x4DC, 0x190, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__GPIO2_27 IOMUX_PAD(0x4DC, 0x190, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__ECSPI2_SS1 IOMUX_PAD(0x4DC, 0x190, 2, 0x7C8, 1, 0)
-#define _MX53_PAD_EIM_LBA__IPU_DI1_PIN17 IOMUX_PAD(0x4DC, 0x190, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 IOMUX_PAD(0x4DC, 0x190, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 IOMUX_PAD(0x4E4, 0x194, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__GPIO2_28 IOMUX_PAD(0x4E4, 0x194, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 IOMUX_PAD(0x4E4, 0x194, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__IPU_CSI1_D_11 IOMUX_PAD(0x4E4, 0x194, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__GPC_PMIC_RDY IOMUX_PAD(0x4E4, 0x194, 5, 0x810, 0, 0)
-#define _MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 IOMUX_PAD(0x4E4, 0x194, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 IOMUX_PAD(0x4E8, 0x198, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__GPIO2_29 IOMUX_PAD(0x4E8, 0x198, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 IOMUX_PAD(0x4E8, 0x198, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__IPU_CSI1_D_10 IOMUX_PAD(0x4E8, 0x198, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 IOMUX_PAD(0x4E8, 0x198, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 IOMUX_PAD(0x4EC, 0x19C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__GPIO3_0 IOMUX_PAD(0x4EC, 0x19C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 IOMUX_PAD(0x4EC, 0x19C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__IPU_CSI1_D_9 IOMUX_PAD(0x4EC, 0x19C, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 IOMUX_PAD(0x4EC, 0x19C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 IOMUX_PAD(0x4F0, 0x1A0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__GPIO3_1 IOMUX_PAD(0x4F0, 0x1A0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 IOMUX_PAD(0x4F0, 0x1A0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__IPU_CSI1_D_8 IOMUX_PAD(0x4F0, 0x1A0, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 IOMUX_PAD(0x4F0, 0x1A0, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 IOMUX_PAD(0x4F4, 0x1A4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__GPIO3_2 IOMUX_PAD(0x4F4, 0x1A4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 IOMUX_PAD(0x4F4, 0x1A4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__IPU_CSI1_D_7 IOMUX_PAD(0x4F4, 0x1A4, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 IOMUX_PAD(0x4F4, 0x1A4, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 IOMUX_PAD(0x4F8, 0x1A8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__GPIO3_3 IOMUX_PAD(0x4F8, 0x1A8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 IOMUX_PAD(0x4F8, 0x1A8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__IPU_CSI1_D_6 IOMUX_PAD(0x4F8, 0x1A8, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 IOMUX_PAD(0x4F8, 0x1A8, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 IOMUX_PAD(0x4FC, 0x1AC, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__GPIO3_4 IOMUX_PAD(0x4FC, 0x1AC, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 IOMUX_PAD(0x4FC, 0x1AC, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__IPU_CSI1_D_5 IOMUX_PAD(0x4FC, 0x1AC, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 IOMUX_PAD(0x4FC, 0x1AC, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 IOMUX_PAD(0x500, 0x1B0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__GPIO3_5 IOMUX_PAD(0x500, 0x1B0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 IOMUX_PAD(0x500, 0x1B0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__IPU_CSI1_D_4 IOMUX_PAD(0x500, 0x1B0, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 IOMUX_PAD(0x500, 0x1B0, 7 | IOMUX_CONFIG_SION, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 IOMUX_PAD(0x504, 0x1B4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__GPIO3_6 IOMUX_PAD(0x504, 0x1B4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 IOMUX_PAD(0x504, 0x1B4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__IPU_CSI1_D_3 IOMUX_PAD(0x504, 0x1B4, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 IOMUX_PAD(0x504, 0x1B4, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 IOMUX_PAD(0x508, 0x1B8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__GPIO3_7 IOMUX_PAD(0x508, 0x1B8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 IOMUX_PAD(0x508, 0x1B8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__IPU_CSI1_D_2 IOMUX_PAD(0x508, 0x1B8, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 IOMUX_PAD(0x508, 0x1B8, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 IOMUX_PAD(0x50C, 0x1BC, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__GPIO3_8 IOMUX_PAD(0x50C, 0x1BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 IOMUX_PAD(0x50C, 0x1BC, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__IPU_CSI1_D_1 IOMUX_PAD(0x50C, 0x1BC, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 IOMUX_PAD(0x50C, 0x1BC, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 IOMUX_PAD(0x510, 0x1C0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__GPIO3_9 IOMUX_PAD(0x510, 0x1C0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 IOMUX_PAD(0x510, 0x1C0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__IPU_CSI1_D_0 IOMUX_PAD(0x510, 0x1C0, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 IOMUX_PAD(0x510, 0x1C0, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 IOMUX_PAD(0x514, 0x1C4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__GPIO3_10 IOMUX_PAD(0x514, 0x1C4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__IPU_DI1_PIN15 IOMUX_PAD(0x514, 0x1C4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN IOMUX_PAD(0x514, 0x1C4, 4, 0x834, 1, 0)
-#define _MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 IOMUX_PAD(0x514, 0x1C4, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 IOMUX_PAD(0x518, 0x1C8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__GPIO3_11 IOMUX_PAD(0x518, 0x1C8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__IPU_DI1_PIN2 IOMUX_PAD(0x518, 0x1C8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC IOMUX_PAD(0x518, 0x1C8, 4, 0x838, 1, 0)
-#define _MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 IOMUX_PAD(0x51C, 0x1CC, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA12__GPIO3_12 IOMUX_PAD(0x51C, 0x1CC, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA12__IPU_DI1_PIN3 IOMUX_PAD(0x51C, 0x1CC, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC IOMUX_PAD(0x51C, 0x1CC, 4, 0x83C, 1, 0)
-#define _MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 IOMUX_PAD(0x520, 0x1D0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA13__GPIO3_13 IOMUX_PAD(0x520, 0x1D0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA13__IPU_DI1_D0_CS IOMUX_PAD(0x520, 0x1D0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK IOMUX_PAD(0x520, 0x1D0, 4, 0x76C, 1, 0)
-#define _MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 IOMUX_PAD(0x524, 0x1D4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA14__GPIO3_14 IOMUX_PAD(0x524, 0x1D4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA14__IPU_DI1_D1_CS IOMUX_PAD(0x524, 0x1D4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK IOMUX_PAD(0x524, 0x1D4, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 IOMUX_PAD(0x528, 0x1D8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__GPIO3_15 IOMUX_PAD(0x528, 0x1D8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__IPU_DI1_PIN1 IOMUX_PAD(0x528, 0x1D8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__IPU_DI1_PIN4 IOMUX_PAD(0x528, 0x1D8, 4, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B IOMUX_PAD(0x52C, 0x1DC, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WE_B__GPIO6_12 IOMUX_PAD(0x52C, 0x1DC, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B IOMUX_PAD(0x530, 0x1E0, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RE_B__GPIO6_13 IOMUX_PAD(0x530, 0x1E0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT IOMUX_PAD(0x534, 0x1E4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_WAIT__GPIO5_0 IOMUX_PAD(0x534, 0x1E4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B IOMUX_PAD(0x534, 0x1E4, 2, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX3_P__GPIO6_22 IOMUX_PAD(NON_PAD_I, 0x1EC, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 IOMUX_PAD(NON_PAD_I, 0x1EC, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX2_P__GPIO6_24 IOMUX_PAD(NON_PAD_I, 0x1F0, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 IOMUX_PAD(NON_PAD_I, 0x1F0, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_CLK_P__GPIO6_26 IOMUX_PAD(NON_PAD_I, 0x1F4, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK IOMUX_PAD(NON_PAD_I, 0x1F4, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX1_P__GPIO6_28 IOMUX_PAD(NON_PAD_I, 0x1F8, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 IOMUX_PAD(NON_PAD_I, 0x1F8, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX0_P__GPIO6_30 IOMUX_PAD(NON_PAD_I, 0x1FC, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 IOMUX_PAD(NON_PAD_I, 0x1FC, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX3_P__GPIO7_22 IOMUX_PAD(NON_PAD_I, 0x200, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 IOMUX_PAD(NON_PAD_I, 0x200, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_CLK_P__GPIO7_24 IOMUX_PAD(NON_PAD_I, 0x204, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK IOMUX_PAD(NON_PAD_I, 0x204, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX2_P__GPIO7_26 IOMUX_PAD(NON_PAD_I, 0x208, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 IOMUX_PAD(NON_PAD_I, 0x208, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX1_P__GPIO7_28 IOMUX_PAD(NON_PAD_I, 0x20C, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 IOMUX_PAD(NON_PAD_I, 0x20C, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX0_P__GPIO7_30 IOMUX_PAD(NON_PAD_I, 0x210, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 IOMUX_PAD(NON_PAD_I, 0x210, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_10__GPIO4_0 IOMUX_PAD(0x540, 0x214, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_10__OSC32k_32K_OUT IOMUX_PAD(0x540, 0x214, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_11__GPIO4_1 IOMUX_PAD(0x544, 0x218, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_12__GPIO4_2 IOMUX_PAD(0x548, 0x21C, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_13__GPIO4_3 IOMUX_PAD(0x54C, 0x220, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_14__GPIO4_4 IOMUX_PAD(0x550, 0x224, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CLE__EMI_NANDF_CLE IOMUX_PAD(0x5A0, 0x228, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CLE__GPIO6_7 IOMUX_PAD(0x5A0, 0x228, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 IOMUX_PAD(0x5A0, 0x228, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_ALE__EMI_NANDF_ALE IOMUX_PAD(0x5A4, 0x22C, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_ALE__GPIO6_8 IOMUX_PAD(0x5A4, 0x22C, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 IOMUX_PAD(0x5A4, 0x22C, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B IOMUX_PAD(0x5A8, 0x230, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WP_B__GPIO6_9 IOMUX_PAD(0x5A8, 0x230, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 IOMUX_PAD(0x5A8, 0x230, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 IOMUX_PAD(0x5AC, 0x234, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RB0__GPIO6_10 IOMUX_PAD(0x5AC, 0x234, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 IOMUX_PAD(0x5AC, 0x234, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 IOMUX_PAD(0x5B0, 0x238, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS0__GPIO6_11 IOMUX_PAD(0x5B0, 0x238, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 IOMUX_PAD(0x5B0, 0x238, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 IOMUX_PAD(0x5B4, 0x23C, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS1__GPIO6_14 IOMUX_PAD(0x5B4, 0x23C, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS1__MLB_MLBCLK IOMUX_PAD(0x5B4, 0x23C, 6, 0x858, 0, 0)
-#define _MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 IOMUX_PAD(0x5B4, 0x23C, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 IOMUX_PAD(0x5B8, 0x240, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__GPIO6_15 IOMUX_PAD(0x5B8, 0x240, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__IPU_SISG_0 IOMUX_PAD(0x5B8, 0x240, 2, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__ESAI1_TX0 IOMUX_PAD(0x5B8, 0x240, 3, 0x7E4, 0, 0)
-#define _MX53_PAD_NANDF_CS2__EMI_WEIM_CRE IOMUX_PAD(0x5B8, 0x240, 4, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK IOMUX_PAD(0x5B8, 0x240, 5, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__MLB_MLBSIG IOMUX_PAD(0x5B8, 0x240, 6, 0x860, 0, 0)
-#define _MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 IOMUX_PAD(0x5B8, 0x240, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 IOMUX_PAD(0x5BC, 0x244, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__GPIO6_16 IOMUX_PAD(0x5BC, 0x244, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__IPU_SISG_1 IOMUX_PAD(0x5BC, 0x244, 2, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__ESAI1_TX1 IOMUX_PAD(0x5BC, 0x244, 3, 0x7E8, 0, 0)
-#define _MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 IOMUX_PAD(0x5BC, 0x244, 4, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__MLB_MLBDAT IOMUX_PAD(0x5BC, 0x244, 6, 0x85C, 0, 0)
-#define _MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 IOMUX_PAD(0x5BC, 0x244, 7, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__FEC_MDIO IOMUX_PAD(0x5C4, 0x248, 0, 0x804, 1, 0)
-#define _MX53_PAD_FEC_MDIO__GPIO1_22 IOMUX_PAD(0x5C4, 0x248, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__ESAI1_SCKR IOMUX_PAD(0x5C4, 0x248, 2, 0x7DC, 0, 0)
-#define _MX53_PAD_FEC_MDIO__FEC_COL IOMUX_PAD(0x5C4, 0x248, 3, 0x800, 1, 0)
-#define _MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 IOMUX_PAD(0x5C4, 0x248, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 IOMUX_PAD(0x5C4, 0x248, 5, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 IOMUX_PAD(0x5C4, 0x248, 6, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__FEC_TX_CLK IOMUX_PAD(0x5C8, 0x24C, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__GPIO1_23 IOMUX_PAD(0x5C8, 0x24C, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__ESAI1_FSR IOMUX_PAD(0x5C8, 0x24C, 2, 0x7CC, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 IOMUX_PAD(0x5C8, 0x24C, 5, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 IOMUX_PAD(0x5C8, 0x24C, 6, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__FEC_RX_ER IOMUX_PAD(0x5CC, 0x250, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__GPIO1_24 IOMUX_PAD(0x5CC, 0x250, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__ESAI1_HCKR IOMUX_PAD(0x5CC, 0x250, 2, 0x7D4, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__FEC_RX_CLK IOMUX_PAD(0x5CC, 0x250, 3, 0x808, 1, 0)
-#define _MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 IOMUX_PAD(0x5CC, 0x250, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_CRS_DV__FEC_RX_DV IOMUX_PAD(0x5D0, 0x254, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_CRS_DV__GPIO1_25 IOMUX_PAD(0x5D0, 0x254, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_CRS_DV__ESAI1_SCKT IOMUX_PAD(0x5D0, 0x254, 2, 0x7E0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__FEC_RDATA_1 IOMUX_PAD(0x5D4, 0x258, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__GPIO1_26 IOMUX_PAD(0x5D4, 0x258, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__ESAI1_FST IOMUX_PAD(0x5D4, 0x258, 2, 0x7D0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__MLB_MLBSIG IOMUX_PAD(0x5D4, 0x258, 3, 0x860, 1, 0)
-#define _MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 IOMUX_PAD(0x5D4, 0x258, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD0__FEC_RDATA_0 IOMUX_PAD(0x5D8, 0x25C, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD0__GPIO1_27 IOMUX_PAD(0x5D8, 0x25C, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD0__ESAI1_HCKT IOMUX_PAD(0x5D8, 0x25C, 2, 0x7D8, 0, 0)
-#define _MX53_PAD_FEC_RXD0__OSC32k_32K_OUT IOMUX_PAD(0x5D8, 0x25C, 3, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TX_EN__FEC_TX_EN IOMUX_PAD(0x5DC, 0x260, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TX_EN__GPIO1_28 IOMUX_PAD(0x5DC, 0x260, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 IOMUX_PAD(0x5DC, 0x260, 2, 0x7F0, 0, 0)
-#define _MX53_PAD_FEC_TXD1__FEC_TDATA_1 IOMUX_PAD(0x5E0, 0x264, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD1__GPIO1_29 IOMUX_PAD(0x5E0, 0x264, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 IOMUX_PAD(0x5E0, 0x264, 2, 0x7EC, 0, 0)
-#define _MX53_PAD_FEC_TXD1__MLB_MLBCLK IOMUX_PAD(0x5E0, 0x264, 3, 0x858, 1, 0)
-#define _MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK IOMUX_PAD(0x5E0, 0x264, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD0__FEC_TDATA_0 IOMUX_PAD(0x5E4, 0x268, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD0__GPIO1_30 IOMUX_PAD(0x5E4, 0x268, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 IOMUX_PAD(0x5E4, 0x268, 2, 0x7F4, 0, 0)
-#define _MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 IOMUX_PAD(0x5E4, 0x268, 7, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__FEC_MDC IOMUX_PAD(0x5E8, 0x26C, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__GPIO1_31 IOMUX_PAD(0x5E8, 0x26C, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 IOMUX_PAD(0x5E8, 0x26C, 2, 0x7F8, 0, 0)
-#define _MX53_PAD_FEC_MDC__MLB_MLBDAT IOMUX_PAD(0x5E8, 0x26C, 3, 0x85C, 1, 0)
-#define _MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG IOMUX_PAD(0x5E8, 0x26C, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 IOMUX_PAD(0x5E8, 0x26C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__PATA_DIOW IOMUX_PAD(0x5F0, 0x270, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__GPIO6_17 IOMUX_PAD(0x5F0, 0x270, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__UART1_TXD_MUX IOMUX_PAD(0x5F0, 0x270, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 IOMUX_PAD(0x5F0, 0x270, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMACK__PATA_DMACK IOMUX_PAD(0x5F4, 0x274, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMACK__GPIO6_18 IOMUX_PAD(0x5F4, 0x274, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMACK__UART1_RXD_MUX IOMUX_PAD(0x5F4, 0x274, 3, 0x878, 3, 0)
-#define _MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 IOMUX_PAD(0x5F4, 0x274, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__PATA_DMARQ IOMUX_PAD(0x5F8, 0x278, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__GPIO7_0 IOMUX_PAD(0x5F8, 0x278, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__UART2_TXD_MUX IOMUX_PAD(0x5F8, 0x278, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 IOMUX_PAD(0x5F8, 0x278, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 IOMUX_PAD(0x5F8, 0x278, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN IOMUX_PAD(0x5FC, 0x27C, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__GPIO7_1 IOMUX_PAD(0x5FC, 0x27C, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 IOMUX_PAD(0x5FC, 0x27C, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 IOMUX_PAD(0x5FC, 0x27C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__PATA_INTRQ IOMUX_PAD(0x600, 0x280, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__GPIO7_2 IOMUX_PAD(0x600, 0x280, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__UART2_CTS IOMUX_PAD(0x600, 0x280, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__CAN1_TXCAN IOMUX_PAD(0x600, 0x280, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 IOMUX_PAD(0x600, 0x280, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 IOMUX_PAD(0x600, 0x280, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOR__PATA_DIOR IOMUX_PAD(0x604, 0x284, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOR__GPIO7_3 IOMUX_PAD(0x604, 0x284, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOR__UART2_RTS IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, 0)
-#define _MX53_PAD_PATA_DIOR__CAN1_RXCAN IOMUX_PAD(0x604, 0x284, 4, 0x760, 1, 0)
-#define _MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 IOMUX_PAD(0x604, 0x284, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B IOMUX_PAD(0x608, 0x288, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__GPIO7_4 IOMUX_PAD(0x608, 0x288, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__ESDHC3_CMD IOMUX_PAD(0x608, 0x288, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__UART1_CTS IOMUX_PAD(0x608, 0x288, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__CAN2_TXCAN IOMUX_PAD(0x608, 0x288, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 IOMUX_PAD(0x608, 0x288, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__PATA_IORDY IOMUX_PAD(0x60C, 0x28C, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__GPIO7_5 IOMUX_PAD(0x60C, 0x28C, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__ESDHC3_CLK IOMUX_PAD(0x60C, 0x28C, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__UART1_RTS IOMUX_PAD(0x60C, 0x28C, 3, 0x874, 3, 0)
-#define _MX53_PAD_PATA_IORDY__CAN2_RXCAN IOMUX_PAD(0x60C, 0x28C, 4, 0x764, 1, 0)
-#define _MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 IOMUX_PAD(0x60C, 0x28C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__PATA_DA_0 IOMUX_PAD(0x610, 0x290, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__GPIO7_6 IOMUX_PAD(0x610, 0x290, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__ESDHC3_RST IOMUX_PAD(0x610, 0x290, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__OWIRE_LINE IOMUX_PAD(0x610, 0x290, 4, 0x864, 0, 0)
-#define _MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 IOMUX_PAD(0x610, 0x290, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__PATA_DA_1 IOMUX_PAD(0x614, 0x294, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__GPIO7_7 IOMUX_PAD(0x614, 0x294, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__ESDHC4_CMD IOMUX_PAD(0x614, 0x294, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__UART3_CTS IOMUX_PAD(0x614, 0x294, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 IOMUX_PAD(0x614, 0x294, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__PATA_DA_2 IOMUX_PAD(0x618, 0x298, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__GPIO7_8 IOMUX_PAD(0x618, 0x298, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__ESDHC4_CLK IOMUX_PAD(0x618, 0x298, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__UART3_RTS IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, 0)
-#define _MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 IOMUX_PAD(0x618, 0x298, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__PATA_CS_0 IOMUX_PAD(0x61C, 0x29C, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__GPIO7_9 IOMUX_PAD(0x61C, 0x29C, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__UART3_TXD_MUX IOMUX_PAD(0x61C, 0x29C, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 IOMUX_PAD(0x61C, 0x29C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_1__PATA_CS_1 IOMUX_PAD(0x620, 0x2A0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_1__GPIO7_10 IOMUX_PAD(0x620, 0x2A0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_1__UART3_RXD_MUX IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, 0)
-#define _MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 IOMUX_PAD(0x620, 0x2A0, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__PATA_DATA_0 IOMUX_PAD(0x628, 0x2A4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__GPIO2_0 IOMUX_PAD(0x628, 0x2A4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 IOMUX_PAD(0x628, 0x2A4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__ESDHC3_DAT4 IOMUX_PAD(0x628, 0x2A4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 IOMUX_PAD(0x628, 0x2A4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 IOMUX_PAD(0x628, 0x2A4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 IOMUX_PAD(0x628, 0x2A4, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__PATA_DATA_1 IOMUX_PAD(0x62C, 0x2A8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__GPIO2_1 IOMUX_PAD(0x62C, 0x2A8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 IOMUX_PAD(0x62C, 0x2A8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__ESDHC3_DAT5 IOMUX_PAD(0x62C, 0x2A8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 IOMUX_PAD(0x62C, 0x2A8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 IOMUX_PAD(0x62C, 0x2A8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__PATA_DATA_2 IOMUX_PAD(0x630, 0x2AC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__GPIO2_2 IOMUX_PAD(0x630, 0x2AC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 IOMUX_PAD(0x630, 0x2AC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__ESDHC3_DAT6 IOMUX_PAD(0x630, 0x2AC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 IOMUX_PAD(0x630, 0x2AC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 IOMUX_PAD(0x630, 0x2AC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__PATA_DATA_3 IOMUX_PAD(0x634, 0x2B0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__GPIO2_3 IOMUX_PAD(0x634, 0x2B0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 IOMUX_PAD(0x634, 0x2B0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__ESDHC3_DAT7 IOMUX_PAD(0x634, 0x2B0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 IOMUX_PAD(0x634, 0x2B0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 IOMUX_PAD(0x634, 0x2B0, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__PATA_DATA_4 IOMUX_PAD(0x638, 0x2B4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__GPIO2_4 IOMUX_PAD(0x638, 0x2B4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 IOMUX_PAD(0x638, 0x2B4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__ESDHC4_DAT4 IOMUX_PAD(0x638, 0x2B4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 IOMUX_PAD(0x638, 0x2B4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 IOMUX_PAD(0x638, 0x2B4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__PATA_DATA_5 IOMUX_PAD(0x63C, 0x2B8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__GPIO2_5 IOMUX_PAD(0x63C, 0x2B8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 IOMUX_PAD(0x63C, 0x2B8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__ESDHC4_DAT5 IOMUX_PAD(0x63C, 0x2B8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 IOMUX_PAD(0x63C, 0x2B8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 IOMUX_PAD(0x63C, 0x2B8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__PATA_DATA_6 IOMUX_PAD(0x640, 0x2BC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__GPIO2_6 IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 IOMUX_PAD(0x640, 0x2BC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__ESDHC4_DAT6 IOMUX_PAD(0x640, 0x2BC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 IOMUX_PAD(0x640, 0x2BC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 IOMUX_PAD(0x640, 0x2BC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__PATA_DATA_7 IOMUX_PAD(0x644, 0x2C0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__GPIO2_7 IOMUX_PAD(0x644, 0x2C0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 IOMUX_PAD(0x644, 0x2C0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__ESDHC4_DAT7 IOMUX_PAD(0x644, 0x2C0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 IOMUX_PAD(0x644, 0x2C0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 IOMUX_PAD(0x644, 0x2C0, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__PATA_DATA_8 IOMUX_PAD(0x648, 0x2C4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__GPIO2_8 IOMUX_PAD(0x648, 0x2C4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__ESDHC1_DAT4 IOMUX_PAD(0x648, 0x2C4, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 IOMUX_PAD(0x648, 0x2C4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__ESDHC3_DAT0 IOMUX_PAD(0x648, 0x2C4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 IOMUX_PAD(0x648, 0x2C4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 IOMUX_PAD(0x648, 0x2C4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__PATA_DATA_9 IOMUX_PAD(0x64C, 0x2C8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__GPIO2_9 IOMUX_PAD(0x64C, 0x2C8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__ESDHC1_DAT5 IOMUX_PAD(0x64C, 0x2C8, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 IOMUX_PAD(0x64C, 0x2C8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__ESDHC3_DAT1 IOMUX_PAD(0x64C, 0x2C8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 IOMUX_PAD(0x64C, 0x2C8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 IOMUX_PAD(0x64C, 0x2C8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__PATA_DATA_10 IOMUX_PAD(0x650, 0x2CC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__GPIO2_10 IOMUX_PAD(0x650, 0x2CC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__ESDHC1_DAT6 IOMUX_PAD(0x650, 0x2CC, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 IOMUX_PAD(0x650, 0x2CC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__ESDHC3_DAT2 IOMUX_PAD(0x650, 0x2CC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 IOMUX_PAD(0x650, 0x2CC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 IOMUX_PAD(0x650, 0x2CC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__PATA_DATA_11 IOMUX_PAD(0x654, 0x2D0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__GPIO2_11 IOMUX_PAD(0x654, 0x2D0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__ESDHC1_DAT7 IOMUX_PAD(0x654, 0x2D0, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 IOMUX_PAD(0x654, 0x2D0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__ESDHC3_DAT3 IOMUX_PAD(0x654, 0x2D0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 IOMUX_PAD(0x654, 0x2D0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 IOMUX_PAD(0x654, 0x2D0, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__PATA_DATA_12 IOMUX_PAD(0x658, 0x2D4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__GPIO2_12 IOMUX_PAD(0x658, 0x2D4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__ESDHC2_DAT4 IOMUX_PAD(0x658, 0x2D4, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 IOMUX_PAD(0x658, 0x2D4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__ESDHC4_DAT0 IOMUX_PAD(0x658, 0x2D4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 IOMUX_PAD(0x658, 0x2D4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 IOMUX_PAD(0x658, 0x2D4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__PATA_DATA_13 IOMUX_PAD(0x65C, 0x2D8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__GPIO2_13 IOMUX_PAD(0x65C, 0x2D8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__ESDHC2_DAT5 IOMUX_PAD(0x65C, 0x2D8, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 IOMUX_PAD(0x65C, 0x2D8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__ESDHC4_DAT1 IOMUX_PAD(0x65C, 0x2D8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 IOMUX_PAD(0x65C, 0x2D8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 IOMUX_PAD(0x65C, 0x2D8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__PATA_DATA_14 IOMUX_PAD(0x660, 0x2DC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__GPIO2_14 IOMUX_PAD(0x660, 0x2DC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__ESDHC2_DAT6 IOMUX_PAD(0x660, 0x2DC, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 IOMUX_PAD(0x660, 0x2DC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__ESDHC4_DAT2 IOMUX_PAD(0x660, 0x2DC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 IOMUX_PAD(0x660, 0x2DC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 IOMUX_PAD(0x660, 0x2DC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__PATA_DATA_15 IOMUX_PAD(0x664, 0x2E0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__GPIO2_15 IOMUX_PAD(0x664, 0x2E0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__ESDHC2_DAT7 IOMUX_PAD(0x664, 0x2E0, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 IOMUX_PAD(0x664, 0x2E0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__ESDHC4_DAT3 IOMUX_PAD(0x664, 0x2E0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 IOMUX_PAD(0x664, 0x2E0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 IOMUX_PAD(0x664, 0x2E0, 6, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__ESDHC1_DAT0 IOMUX_PAD(0x66C, 0x2E4, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__GPIO1_16 IOMUX_PAD(0x66C, 0x2E4, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__GPT_CAPIN1 IOMUX_PAD(0x66C, 0x2E4, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__CSPI_MISO IOMUX_PAD(0x66C, 0x2E4, 5, 0x784, 2, 0)
-#define _MX53_PAD_SD1_DATA0__CCM_PLL3_BYP IOMUX_PAD(0x66C, 0x2E4, 7, 0x778, 0, 0)
-#define _MX53_PAD_SD1_DATA1__ESDHC1_DAT1 IOMUX_PAD(0x670, 0x2E8, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA1__GPIO1_17 IOMUX_PAD(0x670, 0x2E8, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA1__GPT_CAPIN2 IOMUX_PAD(0x670, 0x2E8, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA1__CSPI_SS0 IOMUX_PAD(0x670, 0x2E8, 5, 0x78C, 3, 0)
-#define _MX53_PAD_SD1_DATA1__CCM_PLL4_BYP IOMUX_PAD(0x670, 0x2E8, 7, 0x77C, 1, 0)
-#define _MX53_PAD_SD1_CMD__ESDHC1_CMD IOMUX_PAD(0x674, 0x2EC, IOMUX_CONFIG_SION, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CMD__GPIO1_18 IOMUX_PAD(0x674, 0x2EC, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CMD__GPT_CMPOUT1 IOMUX_PAD(0x674, 0x2EC, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CMD__CSPI_MOSI IOMUX_PAD(0x674, 0x2EC, 5, 0x788, 2, 0)
-#define _MX53_PAD_SD1_CMD__CCM_PLL1_BYP IOMUX_PAD(0x674, 0x2EC, 7, 0x770, 0, 0)
-#define _MX53_PAD_SD1_DATA2__ESDHC1_DAT2 IOMUX_PAD(0x678, 0x2F0, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__GPIO1_19 IOMUX_PAD(0x678, 0x2F0, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__GPT_CMPOUT2 IOMUX_PAD(0x678, 0x2F0, 2, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__PWM2_PWMO IOMUX_PAD(0x678, 0x2F0, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__WDOG1_WDOG_B IOMUX_PAD(0x678, 0x2F0, 4, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__CSPI_SS1 IOMUX_PAD(0x678, 0x2F0, 5, 0x790, 2, 0)
-#define _MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB IOMUX_PAD(0x678, 0x2F0, 6, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__CCM_PLL2_BYP IOMUX_PAD(0x678, 0x2F0, 7, 0x774, 0, 0)
-#define _MX53_PAD_SD1_CLK__ESDHC1_CLK IOMUX_PAD(0x67C, 0x2F4, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__GPIO1_20 IOMUX_PAD(0x67C, 0x2F4, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__OSC32k_32K_OUT IOMUX_PAD(0x67C, 0x2F4, 2, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__GPT_CLKIN IOMUX_PAD(0x67C, 0x2F4, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__CSPI_SCLK IOMUX_PAD(0x67C, 0x2F4, 5, 0x780, 2, 0)
-#define _MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 IOMUX_PAD(0x67C, 0x2F4, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__ESDHC1_DAT3 IOMUX_PAD(0x680, 0x2F8, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__GPIO1_21 IOMUX_PAD(0x680, 0x2F8, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__GPT_CMPOUT3 IOMUX_PAD(0x680, 0x2F8, 2, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__PWM1_PWMO IOMUX_PAD(0x680, 0x2F8, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__WDOG2_WDOG_B IOMUX_PAD(0x680, 0x2F8, 4, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__CSPI_SS2 IOMUX_PAD(0x680, 0x2F8, 5, 0x794, 2, 0)
-#define _MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB IOMUX_PAD(0x680, 0x2F8, 6, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 IOMUX_PAD(0x680, 0x2F8, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CLK__ESDHC2_CLK IOMUX_PAD(0x688, 0x2FC, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CLK__GPIO1_10 IOMUX_PAD(0x688, 0x2FC, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CLK__KPP_COL_5 IOMUX_PAD(0x688, 0x2FC, 2, 0x840, 2, 0)
-#define _MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS IOMUX_PAD(0x688, 0x2FC, 3, 0x73C, 1, 0)
-#define _MX53_PAD_SD2_CLK__CSPI_SCLK IOMUX_PAD(0x688, 0x2FC, 5, 0x780, 3, 0)
-#define _MX53_PAD_SD2_CLK__SCC_RANDOM_V IOMUX_PAD(0x688, 0x2FC, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CMD__ESDHC2_CMD IOMUX_PAD(0x68C, 0x300, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CMD__GPIO1_11 IOMUX_PAD(0x68C, 0x300, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CMD__KPP_ROW_5 IOMUX_PAD(0x68C, 0x300, 2, 0x84C, 1, 0)
-#define _MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC IOMUX_PAD(0x68C, 0x300, 3, 0x738, 1, 0)
-#define _MX53_PAD_SD2_CMD__CSPI_MOSI IOMUX_PAD(0x68C, 0x300, 5, 0x788, 3, 0)
-#define _MX53_PAD_SD2_CMD__SCC_RANDOM IOMUX_PAD(0x68C, 0x300, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA3__ESDHC2_DAT3 IOMUX_PAD(0x690, 0x304, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA3__GPIO1_12 IOMUX_PAD(0x690, 0x304, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA3__KPP_COL_6 IOMUX_PAD(0x690, 0x304, 2, 0x844, 1, 0)
-#define _MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC IOMUX_PAD(0x690, 0x304, 3, 0x740, 1, 0)
-#define _MX53_PAD_SD2_DATA3__CSPI_SS2 IOMUX_PAD(0x690, 0x304, 5, 0x794, 3, 0)
-#define _MX53_PAD_SD2_DATA3__SJC_DONE IOMUX_PAD(0x690, 0x304, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA2__ESDHC2_DAT2 IOMUX_PAD(0x694, 0x308, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA2__GPIO1_13 IOMUX_PAD(0x694, 0x308, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA2__KPP_ROW_6 IOMUX_PAD(0x694, 0x308, 2, 0x850, 1, 0)
-#define _MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD IOMUX_PAD(0x694, 0x308, 3, 0x734, 1, 0)
-#define _MX53_PAD_SD2_DATA2__CSPI_SS1 IOMUX_PAD(0x694, 0x308, 5, 0x790, 3, 0)
-#define _MX53_PAD_SD2_DATA2__SJC_FAIL IOMUX_PAD(0x694, 0x308, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA1__ESDHC2_DAT1 IOMUX_PAD(0x698, 0x30C, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA1__GPIO1_14 IOMUX_PAD(0x698, 0x30C, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA1__KPP_COL_7 IOMUX_PAD(0x698, 0x30C, 2, 0x848, 1, 0)
-#define _MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS IOMUX_PAD(0x698, 0x30C, 3, 0x744, 0, 0)
-#define _MX53_PAD_SD2_DATA1__CSPI_SS0 IOMUX_PAD(0x698, 0x30C, 5, 0x78C, 4, 0)
-#define _MX53_PAD_SD2_DATA1__RTIC_SEC_VIO IOMUX_PAD(0x698, 0x30C, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA0__ESDHC2_DAT0 IOMUX_PAD(0x69C, 0x310, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA0__GPIO1_15 IOMUX_PAD(0x69C, 0x310, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA0__KPP_ROW_7 IOMUX_PAD(0x69C, 0x310, 2, 0x854, 1, 0)
-#define _MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD IOMUX_PAD(0x69C, 0x310, 3, 0x730, 1, 0)
-#define _MX53_PAD_SD2_DATA0__CSPI_MISO IOMUX_PAD(0x69C, 0x310, 5, 0x784, 3, 0)
-#define _MX53_PAD_SD2_DATA0__RTIC_DONE_INT IOMUX_PAD(0x69C, 0x310, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__CCM_CLKO IOMUX_PAD(0x6A4, 0x314, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__GPIO1_0 IOMUX_PAD(0x6A4, 0x314, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__KPP_COL_5 IOMUX_PAD(0x6A4, 0x314, 2, 0x840, 3, 0)
-#define _MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK IOMUX_PAD(0x6A4, 0x314, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__EPIT1_EPITO IOMUX_PAD(0x6A4, 0x314, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__SRTC_ALARM_DEB IOMUX_PAD(0x6A4, 0x314, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__USBOH3_USBH1_PWR IOMUX_PAD(0x6A4, 0x314, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__CSU_TD IOMUX_PAD(0x6A4, 0x314, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__ESAI1_SCKR IOMUX_PAD(0x6A8, 0x318, 0, 0x7DC, 1, 0)
-#define _MX53_PAD_GPIO_1__GPIO1_1 IOMUX_PAD(0x6A8, 0x318, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__KPP_ROW_5 IOMUX_PAD(0x6A8, 0x318, 2, 0x84C, 2, 0)
-#define _MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK IOMUX_PAD(0x6A8, 0x318, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__PWM2_PWMO IOMUX_PAD(0x6A8, 0x318, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__WDOG2_WDOG_B IOMUX_PAD(0x6A8, 0x318, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__ESDHC1_CD IOMUX_PAD(0x6A8, 0x318, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__SRC_TESTER_ACK IOMUX_PAD(0x6A8, 0x318, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__ESAI1_FSR IOMUX_PAD(0x6AC, 0x31C, 0, 0x7CC, 1, 0)
-#define _MX53_PAD_GPIO_9__GPIO1_9 IOMUX_PAD(0x6AC, 0x31C, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__KPP_COL_6 IOMUX_PAD(0x6AC, 0x31C, 2, 0x844, 2, 0)
-#define _MX53_PAD_GPIO_9__CCM_REF_EN_B IOMUX_PAD(0x6AC, 0x31C, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__PWM1_PWMO IOMUX_PAD(0x6AC, 0x31C, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__WDOG1_WDOG_B IOMUX_PAD(0x6AC, 0x31C, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__ESDHC1_WP IOMUX_PAD(0x6AC, 0x31C, 6, 0x7FC, 1, 0)
-#define _MX53_PAD_GPIO_9__SCC_FAIL_STATE IOMUX_PAD(0x6AC, 0x31C, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__ESAI1_HCKR IOMUX_PAD(0x6B0, 0x320, 0, 0x7D4, 1, 0)
-#define _MX53_PAD_GPIO_3__GPIO1_3 IOMUX_PAD(0x6B0, 0x320, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__I2C3_SCL IOMUX_PAD(0x6B0, 0x320, 2 | IOMUX_CONFIG_SION, 0x824, 1, 0)
-#define _MX53_PAD_GPIO_3__DPLLIP1_TOG_EN IOMUX_PAD(0x6B0, 0x320, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__CCM_CLKO2 IOMUX_PAD(0x6B0, 0x320, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 IOMUX_PAD(0x6B0, 0x320, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__USBOH3_USBH1_OC IOMUX_PAD(0x6B0, 0x320, 6, 0x8A0, 1, 0)
-#define _MX53_PAD_GPIO_3__MLB_MLBCLK IOMUX_PAD(0x6B0, 0x320, 7, 0x858, 2, 0)
-#define _MX53_PAD_GPIO_6__ESAI1_SCKT IOMUX_PAD(0x6B4, 0x324, 0, 0x7E0, 1, 0)
-#define _MX53_PAD_GPIO_6__GPIO1_6 IOMUX_PAD(0x6B4, 0x324, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__I2C3_SDA IOMUX_PAD(0x6B4, 0x324, 2 | IOMUX_CONFIG_SION, 0x828, 1, 0)
-#define _MX53_PAD_GPIO_6__CCM_CCM_OUT_0 IOMUX_PAD(0x6B4, 0x324, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__CSU_CSU_INT_DEB IOMUX_PAD(0x6B4, 0x324, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 IOMUX_PAD(0x6B4, 0x324, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__ESDHC2_LCTL IOMUX_PAD(0x6B4, 0x324, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__MLB_MLBSIG IOMUX_PAD(0x6B4, 0x324, 7, 0x860, 2, 0)
-#define _MX53_PAD_GPIO_2__ESAI1_FST IOMUX_PAD(0x6B8, 0x328, 0, 0x7D0, 1, 0)
-#define _MX53_PAD_GPIO_2__GPIO1_2 IOMUX_PAD(0x6B8, 0x328, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__KPP_ROW_6 IOMUX_PAD(0x6B8, 0x328, 2, 0x850, 2, 0)
-#define _MX53_PAD_GPIO_2__CCM_CCM_OUT_1 IOMUX_PAD(0x6B8, 0x328, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 IOMUX_PAD(0x6B8, 0x328, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 IOMUX_PAD(0x6B8, 0x328, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__ESDHC2_WP IOMUX_PAD(0x6B8, 0x328, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__MLB_MLBDAT IOMUX_PAD(0x6B8, 0x328, 7, 0x85C, 2, 0)
-#define _MX53_PAD_GPIO_4__ESAI1_HCKT IOMUX_PAD(0x6BC, 0x32C, 0, 0x7D8, 1, 0)
-#define _MX53_PAD_GPIO_4__GPIO1_4 IOMUX_PAD(0x6BC, 0x32C, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__KPP_COL_7 IOMUX_PAD(0x6BC, 0x32C, 2, 0x848, 2, 0)
-#define _MX53_PAD_GPIO_4__CCM_CCM_OUT_2 IOMUX_PAD(0x6BC, 0x32C, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 IOMUX_PAD(0x6BC, 0x32C, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 IOMUX_PAD(0x6BC, 0x32C, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__ESDHC2_CD IOMUX_PAD(0x6BC, 0x32C, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__SCC_SEC_STATE IOMUX_PAD(0x6BC, 0x32C, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__ESAI1_TX2_RX3 IOMUX_PAD(0x6C0, 0x330, 0, 0x7EC, 1, 0)
-#define _MX53_PAD_GPIO_5__GPIO1_5 IOMUX_PAD(0x6C0, 0x330, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__KPP_ROW_7 IOMUX_PAD(0x6C0, 0x330, 2, 0x854, 2, 0)
-#define _MX53_PAD_GPIO_5__CCM_CLKO IOMUX_PAD(0x6C0, 0x330, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 IOMUX_PAD(0x6C0, 0x330, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 IOMUX_PAD(0x6C0, 0x330, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__I2C3_SCL IOMUX_PAD(0x6C0, 0x330, 6 | IOMUX_CONFIG_SION, 0x824, 2, 0)
-#define _MX53_PAD_GPIO_5__CCM_PLL1_BYP IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, 0)
-#define _MX53_PAD_GPIO_7__ESAI1_TX4_RX1 IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, 0)
-#define _MX53_PAD_GPIO_7__GPIO1_7 IOMUX_PAD(0x6C4, 0x334, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__EPIT1_EPITO IOMUX_PAD(0x6C4, 0x334, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__CAN1_TXCAN IOMUX_PAD(0x6C4, 0x334, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__UART2_TXD_MUX IOMUX_PAD(0x6C4, 0x334, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__FIRI_RXD IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, 0)
-#define _MX53_PAD_GPIO_7__SPDIF_PLOCK IOMUX_PAD(0x6C4, 0x334, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__CCM_PLL2_BYP IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, 0)
-#define _MX53_PAD_GPIO_8__ESAI1_TX5_RX0 IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, 0)
-#define _MX53_PAD_GPIO_8__GPIO1_8 IOMUX_PAD(0x6C8, 0x338, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__EPIT2_EPITO IOMUX_PAD(0x6C8, 0x338, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__CAN1_RXCAN IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 3, 0)
-#define _MX53_PAD_GPIO_8__UART2_RXD_MUX IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, 0)
-#define _MX53_PAD_GPIO_8__FIRI_TXD IOMUX_PAD(0x6C8, 0x338, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__SPDIF_SRCLK IOMUX_PAD(0x6C8, 0x338, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__CCM_PLL3_BYP IOMUX_PAD(0x6C8, 0x338, 7, 0x778, 1, 0)
-#define _MX53_PAD_GPIO_16__ESAI1_TX3_RX2 IOMUX_PAD(0x6CC, 0x33C, 0, 0x7F0, 1, 0)
-#define _MX53_PAD_GPIO_16__GPIO7_11 IOMUX_PAD(0x6CC, 0x33C, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT IOMUX_PAD(0x6CC, 0x33C, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 IOMUX_PAD(0x6CC, 0x33C, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_16__SPDIF_IN1 IOMUX_PAD(0x6CC, 0x33C, 5, 0x870, 1, 0)
-#define _MX53_PAD_GPIO_16__I2C3_SDA IOMUX_PAD(0x6CC, 0x33C, 6 | IOMUX_CONFIG_SION, 0x828, 2, 0)
-#define _MX53_PAD_GPIO_16__SJC_DE_B IOMUX_PAD(0x6CC, 0x33C, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__ESAI1_TX0 IOMUX_PAD(0x6D0, 0x340, 0, 0x7E4, 1, 0)
-#define _MX53_PAD_GPIO_17__GPIO7_12 IOMUX_PAD(0x6D0, 0x340, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 IOMUX_PAD(0x6D0, 0x340, 2, 0x868, 1, 0)
-#define _MX53_PAD_GPIO_17__GPC_PMIC_RDY IOMUX_PAD(0x6D0, 0x340, 3, 0x810, 1, 0)
-#define _MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG IOMUX_PAD(0x6D0, 0x340, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__SPDIF_OUT1 IOMUX_PAD(0x6D0, 0x340, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__IPU_SNOOP2 IOMUX_PAD(0x6D0, 0x340, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__SJC_JTAG_ACT IOMUX_PAD(0x6D0, 0x340, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__ESAI1_TX1 IOMUX_PAD(0x6D4, 0x344, 0, 0x7E8, 1, 0)
-#define _MX53_PAD_GPIO_18__GPIO7_13 IOMUX_PAD(0x6D4, 0x344, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 IOMUX_PAD(0x6D4, 0x344, 2, 0x86C, 1, 0)
-#define _MX53_PAD_GPIO_18__OWIRE_LINE IOMUX_PAD(0x6D4, 0x344, 3, 0x864, 1, 0)
-#define _MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG IOMUX_PAD(0x6D4, 0x344, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK IOMUX_PAD(0x6D4, 0x344, 5, 0x768, 1, 0)
-#define _MX53_PAD_GPIO_18__ESDHC1_LCTL IOMUX_PAD(0x6D4, 0x344, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__SRC_SYSTEM_RST IOMUX_PAD(0x6D4, 0x344, 7, 0x0, 0, 0)
-#define MX53_PAD_GPIO_19__KPP_COL_5 (_MX53_PAD_GPIO_19__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__GPIO4_5 (_MX53_PAD_GPIO_19__GPIO4_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__CCM_CLKO (_MX53_PAD_GPIO_19__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__SPDIF_OUT1 (_MX53_PAD_GPIO_19__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 (_MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__ECSPI1_RDY (_MX53_PAD_GPIO_19__ECSPI1_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__FEC_TDATA_3 (_MX53_PAD_GPIO_19__FEC_TDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__SRC_INT_BOOT (_MX53_PAD_GPIO_19__SRC_INT_BOOT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__KPP_COL_0 (_MX53_PAD_KEY_COL0__KPP_COL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__GPIO4_6 (_MX53_PAD_KEY_COL0__GPIO4_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC (_MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__UART4_TXD_MUX (_MX53_PAD_KEY_COL0__UART4_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__ECSPI1_SCLK (_MX53_PAD_KEY_COL0__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__FEC_RDATA_3 (_MX53_PAD_KEY_COL0__FEC_RDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST (_MX53_PAD_KEY_COL0__SRC_ANY_PU_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__KPP_ROW_0 (_MX53_PAD_KEY_ROW0__KPP_ROW_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__GPIO4_7 (_MX53_PAD_KEY_ROW0__GPIO4_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD (_MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX (_MX53_PAD_KEY_ROW0__UART4_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI (_MX53_PAD_KEY_ROW0__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__FEC_TX_ER (_MX53_PAD_KEY_ROW0__FEC_TX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__KPP_COL_1 (_MX53_PAD_KEY_COL1__KPP_COL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__GPIO4_8 (_MX53_PAD_KEY_COL1__GPIO4_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS (_MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__UART5_TXD_MUX (_MX53_PAD_KEY_COL1__UART5_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__ECSPI1_MISO (_MX53_PAD_KEY_COL1__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__FEC_RX_CLK (_MX53_PAD_KEY_COL1__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY (_MX53_PAD_KEY_COL1__USBPHY1_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__KPP_ROW_1 (_MX53_PAD_KEY_ROW1__KPP_ROW_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__GPIO4_9 (_MX53_PAD_KEY_ROW1__GPIO4_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD (_MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX (_MX53_PAD_KEY_ROW1__UART5_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__ECSPI1_SS0 (_MX53_PAD_KEY_ROW1__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__FEC_COL (_MX53_PAD_KEY_ROW1__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID (_MX53_PAD_KEY_ROW1__USBPHY1_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__KPP_COL_2 (_MX53_PAD_KEY_COL2__KPP_COL_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__GPIO4_10 (_MX53_PAD_KEY_COL2__GPIO4_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__CAN1_TXCAN (_MX53_PAD_KEY_COL2__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__FEC_MDIO (_MX53_PAD_KEY_COL2__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__ECSPI1_SS1 (_MX53_PAD_KEY_COL2__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__FEC_RDATA_2 (_MX53_PAD_KEY_COL2__FEC_RDATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE (_MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__KPP_ROW_2 (_MX53_PAD_KEY_ROW2__KPP_ROW_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__GPIO4_11 (_MX53_PAD_KEY_ROW2__GPIO4_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__CAN1_RXCAN (_MX53_PAD_KEY_ROW2__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__FEC_MDC (_MX53_PAD_KEY_ROW2__FEC_MDC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__ECSPI1_SS2 (_MX53_PAD_KEY_ROW2__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__FEC_TDATA_2 (_MX53_PAD_KEY_ROW2__FEC_TDATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR (_MX53_PAD_KEY_ROW2__USBPHY1_RXERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__KPP_COL_3 (_MX53_PAD_KEY_COL3__KPP_COL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__GPIO4_12 (_MX53_PAD_KEY_COL3__GPIO4_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__USBOH3_H2_DP (_MX53_PAD_KEY_COL3__USBOH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__SPDIF_IN1 (_MX53_PAD_KEY_COL3__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__I2C2_SCL (_MX53_PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_KEY_COL3__ECSPI1_SS3 (_MX53_PAD_KEY_COL3__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__FEC_CRS (_MX53_PAD_KEY_COL3__FEC_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK (_MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__KPP_ROW_3 (_MX53_PAD_KEY_ROW3__KPP_ROW_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__GPIO4_13 (_MX53_PAD_KEY_ROW3__GPIO4_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM (_MX53_PAD_KEY_ROW3__USBOH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK (_MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__I2C2_SDA (_MX53_PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT (_MX53_PAD_KEY_ROW3__OSC32K_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP (_MX53_PAD_KEY_ROW3__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 (_MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__KPP_COL_4 (_MX53_PAD_KEY_COL4__KPP_COL_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__GPIO4_14 (_MX53_PAD_KEY_COL4__GPIO4_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__CAN2_TXCAN (_MX53_PAD_KEY_COL4__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__IPU_SISG_4 (_MX53_PAD_KEY_COL4__IPU_SISG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__UART5_RTS (_MX53_PAD_KEY_COL4__UART5_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC (_MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 (_MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__KPP_ROW_4 (_MX53_PAD_KEY_ROW4__KPP_ROW_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__GPIO4_15 (_MX53_PAD_KEY_ROW4__GPIO4_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__CAN2_RXCAN (_MX53_PAD_KEY_ROW4__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__IPU_SISG_5 (_MX53_PAD_KEY_ROW4__IPU_SISG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__UART5_CTS (_MX53_PAD_KEY_ROW4__UART5_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR (_MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID (_MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK (_MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__GPIO4_16 (_MX53_PAD_DI0_DISP_CLK__GPIO4_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR (_MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 (_MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 (_MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID (_MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 (_MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__GPIO4_17 (_MX53_PAD_DI0_PIN15__GPIO4_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC (_MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 (_MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 (_MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID (_MX53_PAD_DI0_PIN15__USBPHY1_BVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 (_MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__GPIO4_18 (_MX53_PAD_DI0_PIN2__GPIO4_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD (_MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 (_MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 (_MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION (_MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 (_MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__GPIO4_19 (_MX53_PAD_DI0_PIN3__GPIO4_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS (_MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 (_MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 (_MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG (_MX53_PAD_DI0_PIN3__USBPHY1_IDDIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 (_MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__GPIO4_20 (_MX53_PAD_DI0_PIN4__GPIO4_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD (_MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__ESDHC1_WP (_MX53_PAD_DI0_PIN4__ESDHC1_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD (_MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 (_MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT (_MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 (_MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__GPIO4_21 (_MX53_PAD_DISP0_DAT0__GPIO4_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__CSPI_SCLK (_MX53_PAD_DISP0_DAT0__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 (_MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN (_MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 (_MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY (_MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 (_MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__GPIO4_22 (_MX53_PAD_DISP0_DAT1__GPIO4_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__CSPI_MOSI (_MX53_PAD_DISP0_DAT1__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 (_MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL (_MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 (_MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID (_MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 (_MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__GPIO4_23 (_MX53_PAD_DISP0_DAT2__GPIO4_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__CSPI_MISO (_MX53_PAD_DISP0_DAT2__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 (_MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE (_MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 (_MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE (_MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 (_MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__GPIO4_24 (_MX53_PAD_DISP0_DAT3__GPIO4_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__CSPI_SS0 (_MX53_PAD_DISP0_DAT3__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 (_MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR (_MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 (_MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR (_MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 (_MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__GPIO4_25 (_MX53_PAD_DISP0_DAT4__GPIO4_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__CSPI_SS1 (_MX53_PAD_DISP0_DAT4__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 (_MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB (_MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 (_MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK (_MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 (_MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__GPIO4_26 (_MX53_PAD_DISP0_DAT5__GPIO4_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__CSPI_SS2 (_MX53_PAD_DISP0_DAT5__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 (_MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS (_MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 (_MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 (_MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 (_MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__GPIO4_27 (_MX53_PAD_DISP0_DAT6__GPIO4_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__CSPI_SS3 (_MX53_PAD_DISP0_DAT6__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 (_MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE (_MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 (_MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 (_MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 (_MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__GPIO4_28 (_MX53_PAD_DISP0_DAT7__GPIO4_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__CSPI_RDY (_MX53_PAD_DISP0_DAT7__CSPI_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 (_MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 (_MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 (_MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID (_MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 (_MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__GPIO4_29 (_MX53_PAD_DISP0_DAT8__GPIO4_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__PWM1_PWMO (_MX53_PAD_DISP0_DAT8__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B (_MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 (_MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 (_MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID (_MX53_PAD_DISP0_DAT8__USBPHY2_AVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 (_MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__GPIO4_30 (_MX53_PAD_DISP0_DAT9__GPIO4_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__PWM2_PWMO (_MX53_PAD_DISP0_DAT9__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B (_MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 (_MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 (_MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 (_MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 (_MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__GPIO4_31 (_MX53_PAD_DISP0_DAT10__GPIO4_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP (_MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 (_MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 (_MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 (_MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 (_MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__GPIO5_5 (_MX53_PAD_DISP0_DAT11__GPIO5_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT (_MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 (_MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 (_MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 (_MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 (_MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__GPIO5_6 (_MX53_PAD_DISP0_DAT12__GPIO5_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK (_MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 (_MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 (_MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 (_MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 (_MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__GPIO5_7 (_MX53_PAD_DISP0_DAT13__GPIO5_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS (_MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 (_MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 (_MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 (_MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 (_MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__GPIO5_8 (_MX53_PAD_DISP0_DAT14__GPIO5_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC (_MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 (_MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 (_MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 (_MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 (_MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__GPIO5_9 (_MX53_PAD_DISP0_DAT15__GPIO5_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1 (_MX53_PAD_DISP0_DAT15__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1 (_MX53_PAD_DISP0_DAT15__ECSPI2_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 (_MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 (_MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 (_MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 (_MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__GPIO5_10 (_MX53_PAD_DISP0_DAT16__GPIO5_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI (_MX53_PAD_DISP0_DAT16__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC (_MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 (_MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 (_MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 (_MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 (_MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 (_MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__GPIO5_11 (_MX53_PAD_DISP0_DAT17__GPIO5_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO (_MX53_PAD_DISP0_DAT17__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD (_MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 (_MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 (_MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 (_MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 (_MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__GPIO5_12 (_MX53_PAD_DISP0_DAT18__GPIO5_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0 (_MX53_PAD_DISP0_DAT18__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS (_MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS (_MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 (_MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 (_MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 (_MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 (_MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__GPIO5_13 (_MX53_PAD_DISP0_DAT19__GPIO5_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK (_MX53_PAD_DISP0_DAT19__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD (_MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC (_MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 (_MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 (_MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 (_MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 (_MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__GPIO5_14 (_MX53_PAD_DISP0_DAT20__GPIO5_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK (_MX53_PAD_DISP0_DAT20__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC (_MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 (_MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 (_MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI (_MX53_PAD_DISP0_DAT20__SATA_PHY_TDI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 (_MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__GPIO5_15 (_MX53_PAD_DISP0_DAT21__GPIO5_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI (_MX53_PAD_DISP0_DAT21__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD (_MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 (_MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 (_MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO (_MX53_PAD_DISP0_DAT21__SATA_PHY_TDO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 (_MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__GPIO5_16 (_MX53_PAD_DISP0_DAT22__GPIO5_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO (_MX53_PAD_DISP0_DAT22__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS (_MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 (_MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 (_MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK (_MX53_PAD_DISP0_DAT22__SATA_PHY_TCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 (_MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__GPIO5_17 (_MX53_PAD_DISP0_DAT23__GPIO5_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0 (_MX53_PAD_DISP0_DAT23__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD (_MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 (_MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 (_MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS (_MX53_PAD_DISP0_DAT23__SATA_PHY_TMS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK (_MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__GPIO5_18 (_MX53_PAD_CSI0_PIXCLK__GPIO5_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 (_MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 (_MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC (_MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__GPIO5_19 (_MX53_PAD_CSI0_MCLK__GPIO5_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK (_MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 (_MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 (_MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL (_MX53_PAD_CSI0_MCLK__TPIU_TRCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN (_MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__GPIO5_20 (_MX53_PAD_CSI0_DATA_EN__GPIO5_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 (_MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 (_MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK (_MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC (_MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__GPIO5_21 (_MX53_PAD_CSI0_VSYNC__GPIO5_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 (_MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 (_MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 (_MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 (_MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__GPIO5_22 (_MX53_PAD_CSI0_DAT4__GPIO5_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__KPP_COL_5 (_MX53_PAD_CSI0_DAT4__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK (_MX53_PAD_CSI0_DAT4__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP (_MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC (_MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 (_MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 (_MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 (_MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__GPIO5_23 (_MX53_PAD_CSI0_DAT5__GPIO5_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__KPP_ROW_5 (_MX53_PAD_CSI0_DAT5__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI (_MX53_PAD_CSI0_DAT5__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT (_MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD (_MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 (_MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 (_MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 (_MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__GPIO5_24 (_MX53_PAD_CSI0_DAT6__GPIO5_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__KPP_COL_6 (_MX53_PAD_CSI0_DAT6__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO (_MX53_PAD_CSI0_DAT6__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK (_MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS (_MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 (_MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 (_MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 (_MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__GPIO5_25 (_MX53_PAD_CSI0_DAT7__GPIO5_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__KPP_ROW_6 (_MX53_PAD_CSI0_DAT7__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0 (_MX53_PAD_CSI0_DAT7__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR (_MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD (_MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 (_MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 (_MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 (_MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__GPIO5_26 (_MX53_PAD_CSI0_DAT8__GPIO5_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__KPP_COL_7 (_MX53_PAD_CSI0_DAT8__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK (_MX53_PAD_CSI0_DAT8__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC (_MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__I2C1_SDA (_MX53_PAD_CSI0_DAT8__I2C1_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 (_MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 (_MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 (_MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__GPIO5_27 (_MX53_PAD_CSI0_DAT9__GPIO5_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__KPP_ROW_7 (_MX53_PAD_CSI0_DAT9__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI (_MX53_PAD_CSI0_DAT9__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR (_MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__I2C1_SCL (_MX53_PAD_CSI0_DAT9__I2C1_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 (_MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 (_MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 (_MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__GPIO5_28 (_MX53_PAD_CSI0_DAT10__GPIO5_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX (_MX53_PAD_CSI0_DAT10__UART1_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO (_MX53_PAD_CSI0_DAT10__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC (_MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 (_MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 (_MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 (_MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 (_MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__GPIO5_29 (_MX53_PAD_CSI0_DAT11__GPIO5_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX (_MX53_PAD_CSI0_DAT11__UART1_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0 (_MX53_PAD_CSI0_DAT11__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS (_MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 (_MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 (_MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 (_MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 (_MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__GPIO5_30 (_MX53_PAD_CSI0_DAT12__GPIO5_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX (_MX53_PAD_CSI0_DAT12__UART4_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 (_MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 (_MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 (_MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 (_MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 (_MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__GPIO5_31 (_MX53_PAD_CSI0_DAT13__GPIO5_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX (_MX53_PAD_CSI0_DAT13__UART4_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 (_MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 (_MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 (_MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 (_MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 (_MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__GPIO6_0 (_MX53_PAD_CSI0_DAT14__GPIO6_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX (_MX53_PAD_CSI0_DAT14__UART5_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 (_MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 (_MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 (_MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 (_MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 (_MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__GPIO6_1 (_MX53_PAD_CSI0_DAT15__GPIO6_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX (_MX53_PAD_CSI0_DAT15__UART5_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 (_MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 (_MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 (_MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 (_MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 (_MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__GPIO6_2 (_MX53_PAD_CSI0_DAT16__GPIO6_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__UART4_RTS (_MX53_PAD_CSI0_DAT16__UART4_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 (_MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 (_MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 (_MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 (_MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 (_MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__GPIO6_3 (_MX53_PAD_CSI0_DAT17__GPIO6_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__UART4_CTS (_MX53_PAD_CSI0_DAT17__UART4_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 (_MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 (_MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 (_MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 (_MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 (_MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__GPIO6_4 (_MX53_PAD_CSI0_DAT18__GPIO6_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__UART5_RTS (_MX53_PAD_CSI0_DAT18__UART5_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 (_MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 (_MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 (_MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 (_MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 (_MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__GPIO6_5 (_MX53_PAD_CSI0_DAT19__GPIO6_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__UART5_CTS (_MX53_PAD_CSI0_DAT19__UART5_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 (_MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 (_MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 (_MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK (_MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__EMI_WEIM_A_25 (_MX53_PAD_EIM_A25__EMI_WEIM_A_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__GPIO5_2 (_MX53_PAD_EIM_A25__GPIO5_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__ECSPI2_RDY (_MX53_PAD_EIM_A25__ECSPI2_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__IPU_DI1_PIN12 (_MX53_PAD_EIM_A25__IPU_DI1_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__CSPI_SS1 (_MX53_PAD_EIM_A25__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS (_MX53_PAD_EIM_A25__IPU_DI0_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__USBPHY1_BISTOK (_MX53_PAD_EIM_A25__USBPHY1_BISTOK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 (_MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__GPIO2_30 (_MX53_PAD_EIM_EB2__GPIO2_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK (_MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS (_MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__ECSPI1_SS0 (_MX53_PAD_EIM_EB2__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__I2C2_SCL (_MX53_PAD_EIM_EB2__I2C2_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D16__EMI_WEIM_D_16 (_MX53_PAD_EIM_D16__EMI_WEIM_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__GPIO3_16 (_MX53_PAD_EIM_D16__GPIO3_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__IPU_DI0_PIN5 (_MX53_PAD_EIM_D16__IPU_DI0_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK (_MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__ECSPI1_SCLK (_MX53_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__I2C2_SDA (_MX53_PAD_EIM_D16__I2C2_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D17__EMI_WEIM_D_17 (_MX53_PAD_EIM_D17__EMI_WEIM_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__GPIO3_17 (_MX53_PAD_EIM_D17__GPIO3_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__IPU_DI0_PIN6 (_MX53_PAD_EIM_D17__IPU_DI0_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN (_MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__ECSPI1_MISO (_MX53_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__I2C3_SCL (_MX53_PAD_EIM_D17__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D18__EMI_WEIM_D_18 (_MX53_PAD_EIM_D18__EMI_WEIM_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__GPIO3_18 (_MX53_PAD_EIM_D18__GPIO3_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__IPU_DI0_PIN7 (_MX53_PAD_EIM_D18__IPU_DI0_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO (_MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__ECSPI1_MOSI (_MX53_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__I2C3_SDA (_MX53_PAD_EIM_D18__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS (_MX53_PAD_EIM_D18__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__EMI_WEIM_D_19 (_MX53_PAD_EIM_D19__EMI_WEIM_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__GPIO3_19 (_MX53_PAD_EIM_D19__GPIO3_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__IPU_DI0_PIN8 (_MX53_PAD_EIM_D19__IPU_DI0_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS (_MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__ECSPI1_SS1 (_MX53_PAD_EIM_D19__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__EPIT1_EPITO (_MX53_PAD_EIM_D19__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__UART1_CTS (_MX53_PAD_EIM_D19__UART1_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC (_MX53_PAD_EIM_D19__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__EMI_WEIM_D_20 (_MX53_PAD_EIM_D20__EMI_WEIM_D_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__GPIO3_20 (_MX53_PAD_EIM_D20__GPIO3_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__IPU_DI0_PIN16 (_MX53_PAD_EIM_D20__IPU_DI0_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS (_MX53_PAD_EIM_D20__IPU_SER_DISP0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__CSPI_SS0 (_MX53_PAD_EIM_D20__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__EPIT2_EPITO (_MX53_PAD_EIM_D20__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__UART1_RTS (_MX53_PAD_EIM_D20__UART1_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR (_MX53_PAD_EIM_D20__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__EMI_WEIM_D_21 (_MX53_PAD_EIM_D21__EMI_WEIM_D_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__GPIO3_21 (_MX53_PAD_EIM_D21__GPIO3_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__IPU_DI0_PIN17 (_MX53_PAD_EIM_D21__IPU_DI0_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK (_MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__CSPI_SCLK (_MX53_PAD_EIM_D21__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__I2C1_SCL (_MX53_PAD_EIM_D21__I2C1_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC (_MX53_PAD_EIM_D21__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__EMI_WEIM_D_22 (_MX53_PAD_EIM_D22__EMI_WEIM_D_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__GPIO3_22 (_MX53_PAD_EIM_D22__GPIO3_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__IPU_DI0_PIN1 (_MX53_PAD_EIM_D22__IPU_DI0_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN (_MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__CSPI_MISO (_MX53_PAD_EIM_D22__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR (_MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__EMI_WEIM_D_23 (_MX53_PAD_EIM_D23__EMI_WEIM_D_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__GPIO3_23 (_MX53_PAD_EIM_D23__GPIO3_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__UART3_CTS (_MX53_PAD_EIM_D23__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D23__UART1_DCD (_MX53_PAD_EIM_D23__UART1_DCD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS (_MX53_PAD_EIM_D23__IPU_DI0_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_DI1_PIN2 (_MX53_PAD_EIM_D23__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN (_MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_DI1_PIN14 (_MX53_PAD_EIM_D23__IPU_DI1_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 (_MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__GPIO2_31 (_MX53_PAD_EIM_EB3__GPIO2_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__UART3_RTS (_MX53_PAD_EIM_EB3__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__UART1_RI (_MX53_PAD_EIM_EB3__UART1_RI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3 (_MX53_PAD_EIM_EB3__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC (_MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16 (_MX53_PAD_EIM_EB3__IPU_DI1_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__EMI_WEIM_D_24 (_MX53_PAD_EIM_D24__EMI_WEIM_D_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__GPIO3_24 (_MX53_PAD_EIM_D24__GPIO3_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__UART3_TXD_MUX (_MX53_PAD_EIM_D24__UART3_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D24__ECSPI1_SS2 (_MX53_PAD_EIM_D24__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__CSPI_SS2 (_MX53_PAD_EIM_D24__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS (_MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__ECSPI2_SS2 (_MX53_PAD_EIM_D24__ECSPI2_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__UART1_DTR (_MX53_PAD_EIM_D24__UART1_DTR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__EMI_WEIM_D_25 (_MX53_PAD_EIM_D25__EMI_WEIM_D_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__GPIO3_25 (_MX53_PAD_EIM_D25__GPIO3_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__UART3_RXD_MUX (_MX53_PAD_EIM_D25__UART3_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D25__ECSPI1_SS3 (_MX53_PAD_EIM_D25__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__CSPI_SS3 (_MX53_PAD_EIM_D25__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC (_MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__ECSPI2_SS3 (_MX53_PAD_EIM_D25__ECSPI2_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__UART1_DSR (_MX53_PAD_EIM_D25__UART1_DSR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__EMI_WEIM_D_26 (_MX53_PAD_EIM_D26__EMI_WEIM_D_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__GPIO3_26 (_MX53_PAD_EIM_D26__GPIO3_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__UART2_TXD_MUX (_MX53_PAD_EIM_D26__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D26__FIRI_RXD (_MX53_PAD_EIM_D26__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_CSI0_D_1 (_MX53_PAD_EIM_D26__IPU_CSI0_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_DI1_PIN11 (_MX53_PAD_EIM_D26__IPU_DI1_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_SISG_2 (_MX53_PAD_EIM_D26__IPU_SISG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 (_MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__EMI_WEIM_D_27 (_MX53_PAD_EIM_D27__EMI_WEIM_D_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__GPIO3_27 (_MX53_PAD_EIM_D27__GPIO3_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__UART2_RXD_MUX (_MX53_PAD_EIM_D27__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D27__FIRI_TXD (_MX53_PAD_EIM_D27__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_CSI0_D_0 (_MX53_PAD_EIM_D27__IPU_CSI0_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_DI1_PIN13 (_MX53_PAD_EIM_D27__IPU_DI1_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_SISG_3 (_MX53_PAD_EIM_D27__IPU_SISG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 (_MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__EMI_WEIM_D_28 (_MX53_PAD_EIM_D28__EMI_WEIM_D_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__GPIO3_28 (_MX53_PAD_EIM_D28__GPIO3_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__UART2_CTS (_MX53_PAD_EIM_D28__UART2_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO (_MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__CSPI_MOSI (_MX53_PAD_EIM_D28__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__I2C1_SDA (_MX53_PAD_EIM_D28__I2C1_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D28__IPU_EXT_TRIG (_MX53_PAD_EIM_D28__IPU_EXT_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__IPU_DI0_PIN13 (_MX53_PAD_EIM_D28__IPU_DI0_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__EMI_WEIM_D_29 (_MX53_PAD_EIM_D29__EMI_WEIM_D_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__GPIO3_29 (_MX53_PAD_EIM_D29__GPIO3_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__UART2_RTS (_MX53_PAD_EIM_D29__UART2_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS (_MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__CSPI_SS0 (_MX53_PAD_EIM_D29__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_DI1_PIN15 (_MX53_PAD_EIM_D29__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC (_MX53_PAD_EIM_D29__IPU_CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_DI0_PIN14 (_MX53_PAD_EIM_D29__IPU_DI0_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__EMI_WEIM_D_30 (_MX53_PAD_EIM_D30__EMI_WEIM_D_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__GPIO3_30 (_MX53_PAD_EIM_D30__GPIO3_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__UART3_CTS (_MX53_PAD_EIM_D30__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D30__IPU_CSI0_D_3 (_MX53_PAD_EIM_D30__IPU_CSI0_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__IPU_DI0_PIN11 (_MX53_PAD_EIM_D30__IPU_DI0_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 (_MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC (_MX53_PAD_EIM_D30__USBOH3_USBH1_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC (_MX53_PAD_EIM_D30__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__EMI_WEIM_D_31 (_MX53_PAD_EIM_D31__EMI_WEIM_D_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__GPIO3_31 (_MX53_PAD_EIM_D31__GPIO3_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__UART3_RTS (_MX53_PAD_EIM_D31__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D31__IPU_CSI0_D_2 (_MX53_PAD_EIM_D31__IPU_CSI0_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__IPU_DI0_PIN12 (_MX53_PAD_EIM_D31__IPU_DI0_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 (_MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR (_MX53_PAD_EIM_D31__USBOH3_USBH1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR (_MX53_PAD_EIM_D31__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__EMI_WEIM_A_24 (_MX53_PAD_EIM_A24__EMI_WEIM_A_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__GPIO5_4 (_MX53_PAD_EIM_A24__GPIO5_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 (_MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__IPU_CSI1_D_19 (_MX53_PAD_EIM_A24__IPU_CSI1_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__IPU_SISG_2 (_MX53_PAD_EIM_A24__IPU_SISG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__USBPHY2_BVALID (_MX53_PAD_EIM_A24__USBPHY2_BVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__EMI_WEIM_A_23 (_MX53_PAD_EIM_A23__EMI_WEIM_A_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__GPIO6_6 (_MX53_PAD_EIM_A23__GPIO6_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 (_MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__IPU_CSI1_D_18 (_MX53_PAD_EIM_A23__IPU_CSI1_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__IPU_SISG_3 (_MX53_PAD_EIM_A23__IPU_SISG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION (_MX53_PAD_EIM_A23__USBPHY2_ENDSESSION | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__EMI_WEIM_A_22 (_MX53_PAD_EIM_A22__EMI_WEIM_A_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__GPIO2_16 (_MX53_PAD_EIM_A22__GPIO2_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 (_MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__IPU_CSI1_D_17 (_MX53_PAD_EIM_A22__IPU_CSI1_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7 (_MX53_PAD_EIM_A22__SRC_BT_CFG1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__EMI_WEIM_A_21 (_MX53_PAD_EIM_A21__EMI_WEIM_A_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__GPIO2_17 (_MX53_PAD_EIM_A21__GPIO2_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 (_MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__IPU_CSI1_D_16 (_MX53_PAD_EIM_A21__IPU_CSI1_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6 (_MX53_PAD_EIM_A21__SRC_BT_CFG1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__EMI_WEIM_A_20 (_MX53_PAD_EIM_A20__EMI_WEIM_A_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__GPIO2_18 (_MX53_PAD_EIM_A20__GPIO2_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 (_MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__IPU_CSI1_D_15 (_MX53_PAD_EIM_A20__IPU_CSI1_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5 (_MX53_PAD_EIM_A20__SRC_BT_CFG1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__EMI_WEIM_A_19 (_MX53_PAD_EIM_A19__EMI_WEIM_A_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__GPIO2_19 (_MX53_PAD_EIM_A19__GPIO2_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 (_MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__IPU_CSI1_D_14 (_MX53_PAD_EIM_A19__IPU_CSI1_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4 (_MX53_PAD_EIM_A19__SRC_BT_CFG1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__EMI_WEIM_A_18 (_MX53_PAD_EIM_A18__EMI_WEIM_A_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__GPIO2_20 (_MX53_PAD_EIM_A18__GPIO2_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 (_MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__IPU_CSI1_D_13 (_MX53_PAD_EIM_A18__IPU_CSI1_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3 (_MX53_PAD_EIM_A18__SRC_BT_CFG1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__EMI_WEIM_A_17 (_MX53_PAD_EIM_A17__EMI_WEIM_A_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__GPIO2_21 (_MX53_PAD_EIM_A17__GPIO2_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 (_MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__IPU_CSI1_D_12 (_MX53_PAD_EIM_A17__IPU_CSI1_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2 (_MX53_PAD_EIM_A17__SRC_BT_CFG1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__EMI_WEIM_A_16 (_MX53_PAD_EIM_A16__EMI_WEIM_A_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__GPIO2_22 (_MX53_PAD_EIM_A16__GPIO2_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK (_MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK (_MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1 (_MX53_PAD_EIM_A16__SRC_BT_CFG1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 (_MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__GPIO2_23 (_MX53_PAD_EIM_CS0__GPIO2_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__ECSPI2_SCLK (_MX53_PAD_EIM_CS0__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5 (_MX53_PAD_EIM_CS0__IPU_DI1_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 (_MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__GPIO2_24 (_MX53_PAD_EIM_CS1__GPIO2_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__ECSPI2_MOSI (_MX53_PAD_EIM_CS1__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6 (_MX53_PAD_EIM_CS1__IPU_DI1_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__EMI_WEIM_OE (_MX53_PAD_EIM_OE__EMI_WEIM_OE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__GPIO2_25 (_MX53_PAD_EIM_OE__GPIO2_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__ECSPI2_MISO (_MX53_PAD_EIM_OE__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__IPU_DI1_PIN7 (_MX53_PAD_EIM_OE__IPU_DI1_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__USBPHY2_IDDIG (_MX53_PAD_EIM_OE__USBPHY2_IDDIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__EMI_WEIM_RW (_MX53_PAD_EIM_RW__EMI_WEIM_RW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__GPIO2_26 (_MX53_PAD_EIM_RW__GPIO2_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__ECSPI2_SS0 (_MX53_PAD_EIM_RW__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__IPU_DI1_PIN8 (_MX53_PAD_EIM_RW__IPU_DI1_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT (_MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA (_MX53_PAD_EIM_LBA__EMI_WEIM_LBA | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__GPIO2_27 (_MX53_PAD_EIM_LBA__GPIO2_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__ECSPI2_SS1 (_MX53_PAD_EIM_LBA__ECSPI2_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17 (_MX53_PAD_EIM_LBA__IPU_DI1_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 (_MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 (_MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__GPIO2_28 (_MX53_PAD_EIM_EB0__GPIO2_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 (_MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11 (_MX53_PAD_EIM_EB0__IPU_CSI1_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY (_MX53_PAD_EIM_EB0__GPC_PMIC_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 (_MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 (_MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__GPIO2_29 (_MX53_PAD_EIM_EB1__GPIO2_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 (_MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10 (_MX53_PAD_EIM_EB1__IPU_CSI1_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 (_MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 (_MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__GPIO3_0 (_MX53_PAD_EIM_DA0__GPIO3_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 (_MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9 (_MX53_PAD_EIM_DA0__IPU_CSI1_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 (_MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 (_MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__GPIO3_1 (_MX53_PAD_EIM_DA1__GPIO3_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 (_MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8 (_MX53_PAD_EIM_DA1__IPU_CSI1_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 (_MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 (_MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__GPIO3_2 (_MX53_PAD_EIM_DA2__GPIO3_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 (_MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7 (_MX53_PAD_EIM_DA2__IPU_CSI1_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 (_MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 (_MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__GPIO3_3 (_MX53_PAD_EIM_DA3__GPIO3_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 (_MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6 (_MX53_PAD_EIM_DA3__IPU_CSI1_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 (_MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 (_MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__GPIO3_4 (_MX53_PAD_EIM_DA4__GPIO3_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 (_MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5 (_MX53_PAD_EIM_DA4__IPU_CSI1_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 (_MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 (_MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__GPIO3_5 (_MX53_PAD_EIM_DA5__GPIO3_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 (_MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4 (_MX53_PAD_EIM_DA5__IPU_CSI1_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 (_MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 (_MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__GPIO3_6 (_MX53_PAD_EIM_DA6__GPIO3_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 (_MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3 (_MX53_PAD_EIM_DA6__IPU_CSI1_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 (_MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 (_MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__GPIO3_7 (_MX53_PAD_EIM_DA7__GPIO3_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 (_MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2 (_MX53_PAD_EIM_DA7__IPU_CSI1_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 (_MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 (_MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__GPIO3_8 (_MX53_PAD_EIM_DA8__GPIO3_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 (_MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1 (_MX53_PAD_EIM_DA8__IPU_CSI1_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 (_MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 (_MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__GPIO3_9 (_MX53_PAD_EIM_DA9__GPIO3_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 (_MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0 (_MX53_PAD_EIM_DA9__IPU_CSI1_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 (_MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 (_MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__GPIO3_10 (_MX53_PAD_EIM_DA10__GPIO3_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15 (_MX53_PAD_EIM_DA10__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN (_MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 (_MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 (_MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__GPIO3_11 (_MX53_PAD_EIM_DA11__GPIO3_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2 (_MX53_PAD_EIM_DA11__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC (_MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 (_MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__GPIO3_12 (_MX53_PAD_EIM_DA12__GPIO3_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3 (_MX53_PAD_EIM_DA12__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC (_MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 (_MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__GPIO3_13 (_MX53_PAD_EIM_DA13__GPIO3_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS (_MX53_PAD_EIM_DA13__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK (_MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 (_MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__GPIO3_14 (_MX53_PAD_EIM_DA14__GPIO3_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS (_MX53_PAD_EIM_DA14__IPU_DI1_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK (_MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 (_MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__GPIO3_15 (_MX53_PAD_EIM_DA15__GPIO3_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1 (_MX53_PAD_EIM_DA15__IPU_DI1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4 (_MX53_PAD_EIM_DA15__IPU_DI1_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B (_MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WE_B__GPIO6_12 (_MX53_PAD_NANDF_WE_B__GPIO6_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B (_MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RE_B__GPIO6_13 (_MX53_PAD_NANDF_RE_B__GPIO6_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT (_MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_WAIT__GPIO5_0 (_MX53_PAD_EIM_WAIT__GPIO5_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B (_MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX3_P__GPIO6_22 (_MX53_PAD_LVDS1_TX3_P__GPIO6_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 (_MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX2_P__GPIO6_24 (_MX53_PAD_LVDS1_TX2_P__GPIO6_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 (_MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_CLK_P__GPIO6_26 (_MX53_PAD_LVDS1_CLK_P__GPIO6_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK (_MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX1_P__GPIO6_28 (_MX53_PAD_LVDS1_TX1_P__GPIO6_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 (_MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX0_P__GPIO6_30 (_MX53_PAD_LVDS1_TX0_P__GPIO6_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 (_MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX3_P__GPIO7_22 (_MX53_PAD_LVDS0_TX3_P__GPIO7_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 (_MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_CLK_P__GPIO7_24 (_MX53_PAD_LVDS0_CLK_P__GPIO7_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK (_MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX2_P__GPIO7_26 (_MX53_PAD_LVDS0_TX2_P__GPIO7_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 (_MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX1_P__GPIO7_28 (_MX53_PAD_LVDS0_TX1_P__GPIO7_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 (_MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX0_P__GPIO7_30 (_MX53_PAD_LVDS0_TX0_P__GPIO7_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 (_MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_10__GPIO4_0 (_MX53_PAD_GPIO_10__GPIO4_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_10__OSC32k_32K_OUT (_MX53_PAD_GPIO_10__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_11__GPIO4_1 (_MX53_PAD_GPIO_11__GPIO4_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_12__GPIO4_2 (_MX53_PAD_GPIO_12__GPIO4_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_13__GPIO4_3 (_MX53_PAD_GPIO_13__GPIO4_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_14__GPIO4_4 (_MX53_PAD_GPIO_14__GPIO4_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE (_MX53_PAD_NANDF_CLE__EMI_NANDF_CLE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CLE__GPIO6_7 (_MX53_PAD_NANDF_CLE__GPIO6_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 (_MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE (_MX53_PAD_NANDF_ALE__EMI_NANDF_ALE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_ALE__GPIO6_8 (_MX53_PAD_NANDF_ALE__GPIO6_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 (_MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B (_MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WP_B__GPIO6_9 (_MX53_PAD_NANDF_WP_B__GPIO6_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 (_MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 (_MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RB0__GPIO6_10 (_MX53_PAD_NANDF_RB0__GPIO6_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 (_MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 (_MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS0__GPIO6_11 (_MX53_PAD_NANDF_CS0__GPIO6_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 (_MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 (_MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__GPIO6_14 (_MX53_PAD_NANDF_CS1__GPIO6_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__MLB_MLBCLK (_MX53_PAD_NANDF_CS1__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 (_MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 (_MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__GPIO6_15 (_MX53_PAD_NANDF_CS2__GPIO6_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__IPU_SISG_0 (_MX53_PAD_NANDF_CS2__IPU_SISG_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__ESAI1_TX0 (_MX53_PAD_NANDF_CS2__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE (_MX53_PAD_NANDF_CS2__EMI_WEIM_CRE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK (_MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__MLB_MLBSIG (_MX53_PAD_NANDF_CS2__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 (_MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 (_MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__GPIO6_16 (_MX53_PAD_NANDF_CS3__GPIO6_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__IPU_SISG_1 (_MX53_PAD_NANDF_CS3__IPU_SISG_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__ESAI1_TX1 (_MX53_PAD_NANDF_CS3__ESAI1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 (_MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__MLB_MLBDAT (_MX53_PAD_NANDF_CS3__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 (_MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__FEC_MDIO (_MX53_PAD_FEC_MDIO__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__GPIO1_22 (_MX53_PAD_FEC_MDIO__GPIO1_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__ESAI1_SCKR (_MX53_PAD_FEC_MDIO__ESAI1_SCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__FEC_COL (_MX53_PAD_FEC_MDIO__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 (_MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 (_MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 (_MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK (_MX53_PAD_FEC_REF_CLK__FEC_TX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__GPIO1_23 (_MX53_PAD_FEC_REF_CLK__GPIO1_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR (_MX53_PAD_FEC_REF_CLK__ESAI1_FSR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 (_MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 (_MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__FEC_RX_ER (_MX53_PAD_FEC_RX_ER__FEC_RX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__GPIO1_24 (_MX53_PAD_FEC_RX_ER__GPIO1_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR (_MX53_PAD_FEC_RX_ER__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK (_MX53_PAD_FEC_RX_ER__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 (_MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV (_MX53_PAD_FEC_CRS_DV__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_CRS_DV__GPIO1_25 (_MX53_PAD_FEC_CRS_DV__GPIO1_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT (_MX53_PAD_FEC_CRS_DV__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__FEC_RDATA_1 (_MX53_PAD_FEC_RXD1__FEC_RDATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__GPIO1_26 (_MX53_PAD_FEC_RXD1__GPIO1_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__ESAI1_FST (_MX53_PAD_FEC_RXD1__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__MLB_MLBSIG (_MX53_PAD_FEC_RXD1__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 (_MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__FEC_RDATA_0 (_MX53_PAD_FEC_RXD0__FEC_RDATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__GPIO1_27 (_MX53_PAD_FEC_RXD0__GPIO1_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__ESAI1_HCKT (_MX53_PAD_FEC_RXD0__ESAI1_HCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT (_MX53_PAD_FEC_RXD0__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TX_EN__FEC_TX_EN (_MX53_PAD_FEC_TX_EN__FEC_TX_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TX_EN__GPIO1_28 (_MX53_PAD_FEC_TX_EN__GPIO1_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 (_MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__FEC_TDATA_1 (_MX53_PAD_FEC_TXD1__FEC_TDATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__GPIO1_29 (_MX53_PAD_FEC_TXD1__GPIO1_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 (_MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__MLB_MLBCLK (_MX53_PAD_FEC_TXD1__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK (_MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__FEC_TDATA_0 (_MX53_PAD_FEC_TXD0__FEC_TDATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__GPIO1_30 (_MX53_PAD_FEC_TXD0__GPIO1_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 (_MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 (_MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__FEC_MDC (_MX53_PAD_FEC_MDC__FEC_MDC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__GPIO1_31 (_MX53_PAD_FEC_MDC__GPIO1_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 (_MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__MLB_MLBDAT (_MX53_PAD_FEC_MDC__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG (_MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 (_MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__PATA_DIOW (_MX53_PAD_PATA_DIOW__PATA_DIOW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__GPIO6_17 (_MX53_PAD_PATA_DIOW__GPIO6_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX (_MX53_PAD_PATA_DIOW__UART1_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 (_MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__PATA_DMACK (_MX53_PAD_PATA_DMACK__PATA_DMACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__GPIO6_18 (_MX53_PAD_PATA_DMACK__GPIO6_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX (_MX53_PAD_PATA_DMACK__UART1_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 (_MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__PATA_DMARQ (_MX53_PAD_PATA_DMARQ__PATA_DMARQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__GPIO7_0 (_MX53_PAD_PATA_DMARQ__GPIO7_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX (_MX53_PAD_PATA_DMARQ__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 (_MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 (_MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN (_MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1 (_MX53_PAD_PATA_BUFFER_EN__GPIO7_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX (_MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 (_MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 (_MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__PATA_INTRQ (_MX53_PAD_PATA_INTRQ__PATA_INTRQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__GPIO7_2 (_MX53_PAD_PATA_INTRQ__GPIO7_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__UART2_CTS (_MX53_PAD_PATA_INTRQ__UART2_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN (_MX53_PAD_PATA_INTRQ__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 (_MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 (_MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__PATA_DIOR (_MX53_PAD_PATA_DIOR__PATA_DIOR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__GPIO7_3 (_MX53_PAD_PATA_DIOR__GPIO7_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__UART2_RTS (_MX53_PAD_PATA_DIOR__UART2_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__CAN1_RXCAN (_MX53_PAD_PATA_DIOR__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 (_MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B (_MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__GPIO7_4 (_MX53_PAD_PATA_RESET_B__GPIO7_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD (_MX53_PAD_PATA_RESET_B__ESDHC3_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__UART1_CTS (_MX53_PAD_PATA_RESET_B__UART1_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN (_MX53_PAD_PATA_RESET_B__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 (_MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__PATA_IORDY (_MX53_PAD_PATA_IORDY__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__GPIO7_5 (_MX53_PAD_PATA_IORDY__GPIO7_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__ESDHC3_CLK (_MX53_PAD_PATA_IORDY__ESDHC3_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__UART1_RTS (_MX53_PAD_PATA_IORDY__UART1_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__CAN2_RXCAN (_MX53_PAD_PATA_IORDY__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 (_MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__PATA_DA_0 (_MX53_PAD_PATA_DA_0__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__GPIO7_6 (_MX53_PAD_PATA_DA_0__GPIO7_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__ESDHC3_RST (_MX53_PAD_PATA_DA_0__ESDHC3_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__OWIRE_LINE (_MX53_PAD_PATA_DA_0__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 (_MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__PATA_DA_1 (_MX53_PAD_PATA_DA_1__PATA_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__GPIO7_7 (_MX53_PAD_PATA_DA_1__GPIO7_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__ESDHC4_CMD (_MX53_PAD_PATA_DA_1__ESDHC4_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__UART3_CTS (_MX53_PAD_PATA_DA_1__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 (_MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__PATA_DA_2 (_MX53_PAD_PATA_DA_2__PATA_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__GPIO7_8 (_MX53_PAD_PATA_DA_2__GPIO7_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__ESDHC4_CLK (_MX53_PAD_PATA_DA_2__ESDHC4_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__UART3_RTS (_MX53_PAD_PATA_DA_2__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 (_MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__PATA_CS_0 (_MX53_PAD_PATA_CS_0__PATA_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__GPIO7_9 (_MX53_PAD_PATA_CS_0__GPIO7_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX (_MX53_PAD_PATA_CS_0__UART3_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 (_MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__PATA_CS_1 (_MX53_PAD_PATA_CS_1__PATA_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__GPIO7_10 (_MX53_PAD_PATA_CS_1__GPIO7_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX (_MX53_PAD_PATA_CS_1__UART3_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 (_MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__PATA_DATA_0 (_MX53_PAD_PATA_DATA0__PATA_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__GPIO2_0 (_MX53_PAD_PATA_DATA0__GPIO2_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 (_MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4 (_MX53_PAD_PATA_DATA0__ESDHC3_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 (_MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 (_MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 (_MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__PATA_DATA_1 (_MX53_PAD_PATA_DATA1__PATA_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__GPIO2_1 (_MX53_PAD_PATA_DATA1__GPIO2_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 (_MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5 (_MX53_PAD_PATA_DATA1__ESDHC3_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 (_MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 (_MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__PATA_DATA_2 (_MX53_PAD_PATA_DATA2__PATA_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__GPIO2_2 (_MX53_PAD_PATA_DATA2__GPIO2_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 (_MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6 (_MX53_PAD_PATA_DATA2__ESDHC3_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 (_MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 (_MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__PATA_DATA_3 (_MX53_PAD_PATA_DATA3__PATA_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__GPIO2_3 (_MX53_PAD_PATA_DATA3__GPIO2_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 (_MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7 (_MX53_PAD_PATA_DATA3__ESDHC3_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 (_MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 (_MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__PATA_DATA_4 (_MX53_PAD_PATA_DATA4__PATA_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__GPIO2_4 (_MX53_PAD_PATA_DATA4__GPIO2_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 (_MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4 (_MX53_PAD_PATA_DATA4__ESDHC4_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 (_MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 (_MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__PATA_DATA_5 (_MX53_PAD_PATA_DATA5__PATA_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__GPIO2_5 (_MX53_PAD_PATA_DATA5__GPIO2_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 (_MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5 (_MX53_PAD_PATA_DATA5__ESDHC4_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 (_MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 (_MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__PATA_DATA_6 (_MX53_PAD_PATA_DATA6__PATA_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__GPIO2_6 (_MX53_PAD_PATA_DATA6__GPIO2_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 (_MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6 (_MX53_PAD_PATA_DATA6__ESDHC4_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 (_MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 (_MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__PATA_DATA_7 (_MX53_PAD_PATA_DATA7__PATA_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__GPIO2_7 (_MX53_PAD_PATA_DATA7__GPIO2_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 (_MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7 (_MX53_PAD_PATA_DATA7__ESDHC4_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 (_MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 (_MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__PATA_DATA_8 (_MX53_PAD_PATA_DATA8__PATA_DATA_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__GPIO2_8 (_MX53_PAD_PATA_DATA8__GPIO2_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4 (_MX53_PAD_PATA_DATA8__ESDHC1_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 (_MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0 (_MX53_PAD_PATA_DATA8__ESDHC3_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 (_MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 (_MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__PATA_DATA_9 (_MX53_PAD_PATA_DATA9__PATA_DATA_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__GPIO2_9 (_MX53_PAD_PATA_DATA9__GPIO2_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5 (_MX53_PAD_PATA_DATA9__ESDHC1_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 (_MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1 (_MX53_PAD_PATA_DATA9__ESDHC3_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 (_MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 (_MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__PATA_DATA_10 (_MX53_PAD_PATA_DATA10__PATA_DATA_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__GPIO2_10 (_MX53_PAD_PATA_DATA10__GPIO2_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6 (_MX53_PAD_PATA_DATA10__ESDHC1_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 (_MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2 (_MX53_PAD_PATA_DATA10__ESDHC3_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 (_MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 (_MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__PATA_DATA_11 (_MX53_PAD_PATA_DATA11__PATA_DATA_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__GPIO2_11 (_MX53_PAD_PATA_DATA11__GPIO2_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7 (_MX53_PAD_PATA_DATA11__ESDHC1_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 (_MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3 (_MX53_PAD_PATA_DATA11__ESDHC3_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 (_MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 (_MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__PATA_DATA_12 (_MX53_PAD_PATA_DATA12__PATA_DATA_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__GPIO2_12 (_MX53_PAD_PATA_DATA12__GPIO2_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4 (_MX53_PAD_PATA_DATA12__ESDHC2_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 (_MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0 (_MX53_PAD_PATA_DATA12__ESDHC4_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 (_MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 (_MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__PATA_DATA_13 (_MX53_PAD_PATA_DATA13__PATA_DATA_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__GPIO2_13 (_MX53_PAD_PATA_DATA13__GPIO2_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5 (_MX53_PAD_PATA_DATA13__ESDHC2_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 (_MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1 (_MX53_PAD_PATA_DATA13__ESDHC4_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 (_MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 (_MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__PATA_DATA_14 (_MX53_PAD_PATA_DATA14__PATA_DATA_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__GPIO2_14 (_MX53_PAD_PATA_DATA14__GPIO2_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6 (_MX53_PAD_PATA_DATA14__ESDHC2_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 (_MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2 (_MX53_PAD_PATA_DATA14__ESDHC4_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 (_MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 (_MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__PATA_DATA_15 (_MX53_PAD_PATA_DATA15__PATA_DATA_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__GPIO2_15 (_MX53_PAD_PATA_DATA15__GPIO2_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7 (_MX53_PAD_PATA_DATA15__ESDHC2_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 (_MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3 (_MX53_PAD_PATA_DATA15__ESDHC4_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 (_MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 (_MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0 (_MX53_PAD_SD1_DATA0__ESDHC1_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__GPIO1_16 (_MX53_PAD_SD1_DATA0__GPIO1_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__GPT_CAPIN1 (_MX53_PAD_SD1_DATA0__GPT_CAPIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__CSPI_MISO (_MX53_PAD_SD1_DATA0__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP (_MX53_PAD_SD1_DATA0__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1 (_MX53_PAD_SD1_DATA1__ESDHC1_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__GPIO1_17 (_MX53_PAD_SD1_DATA1__GPIO1_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__GPT_CAPIN2 (_MX53_PAD_SD1_DATA1__GPT_CAPIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__CSPI_SS0 (_MX53_PAD_SD1_DATA1__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP (_MX53_PAD_SD1_DATA1__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__ESDHC1_CMD (_MX53_PAD_SD1_CMD__ESDHC1_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__GPIO1_18 (_MX53_PAD_SD1_CMD__GPIO1_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__GPT_CMPOUT1 (_MX53_PAD_SD1_CMD__GPT_CMPOUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__CSPI_MOSI (_MX53_PAD_SD1_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP (_MX53_PAD_SD1_CMD__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2 (_MX53_PAD_SD1_DATA2__ESDHC1_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__GPIO1_19 (_MX53_PAD_SD1_DATA2__GPIO1_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2 (_MX53_PAD_SD1_DATA2__GPT_CMPOUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__PWM2_PWMO (_MX53_PAD_SD1_DATA2__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B (_MX53_PAD_SD1_DATA2__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__CSPI_SS1 (_MX53_PAD_SD1_DATA2__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB (_MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP (_MX53_PAD_SD1_DATA2__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__ESDHC1_CLK (_MX53_PAD_SD1_CLK__ESDHC1_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__GPIO1_20 (_MX53_PAD_SD1_CLK__GPIO1_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT (_MX53_PAD_SD1_CLK__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__GPT_CLKIN (_MX53_PAD_SD1_CLK__GPT_CLKIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__CSPI_SCLK (_MX53_PAD_SD1_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 (_MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3 (_MX53_PAD_SD1_DATA3__ESDHC1_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__GPIO1_21 (_MX53_PAD_SD1_DATA3__GPIO1_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3 (_MX53_PAD_SD1_DATA3__GPT_CMPOUT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__PWM1_PWMO (_MX53_PAD_SD1_DATA3__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B (_MX53_PAD_SD1_DATA3__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__CSPI_SS2 (_MX53_PAD_SD1_DATA3__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB (_MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 (_MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__ESDHC2_CLK (_MX53_PAD_SD2_CLK__ESDHC2_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__GPIO1_10 (_MX53_PAD_SD2_CLK__GPIO1_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__KPP_COL_5 (_MX53_PAD_SD2_CLK__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS (_MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__CSPI_SCLK (_MX53_PAD_SD2_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__SCC_RANDOM_V (_MX53_PAD_SD2_CLK__SCC_RANDOM_V | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__ESDHC2_CMD (_MX53_PAD_SD2_CMD__ESDHC2_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__GPIO1_11 (_MX53_PAD_SD2_CMD__GPIO1_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__KPP_ROW_5 (_MX53_PAD_SD2_CMD__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC (_MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__CSPI_MOSI (_MX53_PAD_SD2_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__SCC_RANDOM (_MX53_PAD_SD2_CMD__SCC_RANDOM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3 (_MX53_PAD_SD2_DATA3__ESDHC2_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__GPIO1_12 (_MX53_PAD_SD2_DATA3__GPIO1_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__KPP_COL_6 (_MX53_PAD_SD2_DATA3__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC (_MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__CSPI_SS2 (_MX53_PAD_SD2_DATA3__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__SJC_DONE (_MX53_PAD_SD2_DATA3__SJC_DONE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2 (_MX53_PAD_SD2_DATA2__ESDHC2_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__GPIO1_13 (_MX53_PAD_SD2_DATA2__GPIO1_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__KPP_ROW_6 (_MX53_PAD_SD2_DATA2__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD (_MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__CSPI_SS1 (_MX53_PAD_SD2_DATA2__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__SJC_FAIL (_MX53_PAD_SD2_DATA2__SJC_FAIL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1 (_MX53_PAD_SD2_DATA1__ESDHC2_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__GPIO1_14 (_MX53_PAD_SD2_DATA1__GPIO1_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__KPP_COL_7 (_MX53_PAD_SD2_DATA1__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS (_MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__CSPI_SS0 (_MX53_PAD_SD2_DATA1__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO (_MX53_PAD_SD2_DATA1__RTIC_SEC_VIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0 (_MX53_PAD_SD2_DATA0__ESDHC2_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__GPIO1_15 (_MX53_PAD_SD2_DATA0__GPIO1_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__KPP_ROW_7 (_MX53_PAD_SD2_DATA0__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD (_MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__CSPI_MISO (_MX53_PAD_SD2_DATA0__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT (_MX53_PAD_SD2_DATA0__RTIC_DONE_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__CCM_CLKO (_MX53_PAD_GPIO_0__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__GPIO1_0 (_MX53_PAD_GPIO_0__GPIO1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__KPP_COL_5 (_MX53_PAD_GPIO_0__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK (_MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__EPIT1_EPITO (_MX53_PAD_GPIO_0__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB (_MX53_PAD_GPIO_0__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR (_MX53_PAD_GPIO_0__USBOH3_USBH1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__CSU_TD (_MX53_PAD_GPIO_0__CSU_TD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__ESAI1_SCKR (_MX53_PAD_GPIO_1__ESAI1_SCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__GPIO1_1 (_MX53_PAD_GPIO_1__GPIO1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__KPP_ROW_5 (_MX53_PAD_GPIO_1__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK (_MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__PWM2_PWMO (_MX53_PAD_GPIO_1__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__WDOG2_WDOG_B (_MX53_PAD_GPIO_1__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__ESDHC1_CD (_MX53_PAD_GPIO_1__ESDHC1_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__SRC_TESTER_ACK (_MX53_PAD_GPIO_1__SRC_TESTER_ACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__ESAI1_FSR (_MX53_PAD_GPIO_9__ESAI1_FSR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__GPIO1_9 (_MX53_PAD_GPIO_9__GPIO1_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__KPP_COL_6 (_MX53_PAD_GPIO_9__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__CCM_REF_EN_B (_MX53_PAD_GPIO_9__CCM_REF_EN_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__PWM1_PWMO (_MX53_PAD_GPIO_9__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__WDOG1_WDOG_B (_MX53_PAD_GPIO_9__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__ESDHC1_WP (_MX53_PAD_GPIO_9__ESDHC1_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__SCC_FAIL_STATE (_MX53_PAD_GPIO_9__SCC_FAIL_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__ESAI1_HCKR (_MX53_PAD_GPIO_3__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__GPIO1_3 (_MX53_PAD_GPIO_3__GPIO1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__I2C3_SCL (_MX53_PAD_GPIO_3__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN (_MX53_PAD_GPIO_3__DPLLIP1_TOG_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__CCM_CLKO2 (_MX53_PAD_GPIO_3__CCM_CLKO2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 (_MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC (_MX53_PAD_GPIO_3__USBOH3_USBH1_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__MLB_MLBCLK (_MX53_PAD_GPIO_3__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__ESAI1_SCKT (_MX53_PAD_GPIO_6__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__GPIO1_6 (_MX53_PAD_GPIO_6__GPIO1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__I2C3_SDA (_MX53_PAD_GPIO_6__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0 (_MX53_PAD_GPIO_6__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB (_MX53_PAD_GPIO_6__CSU_CSU_INT_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 (_MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__ESDHC2_LCTL (_MX53_PAD_GPIO_6__ESDHC2_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__MLB_MLBSIG (_MX53_PAD_GPIO_6__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__ESAI1_FST (_MX53_PAD_GPIO_2__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__GPIO1_2 (_MX53_PAD_GPIO_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__KPP_ROW_6 (_MX53_PAD_GPIO_2__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1 (_MX53_PAD_GPIO_2__CCM_CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 (_MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 (_MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__ESDHC2_WP (_MX53_PAD_GPIO_2__ESDHC2_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__MLB_MLBDAT (_MX53_PAD_GPIO_2__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__ESAI1_HCKT (_MX53_PAD_GPIO_4__ESAI1_HCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__GPIO1_4 (_MX53_PAD_GPIO_4__GPIO1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__KPP_COL_7 (_MX53_PAD_GPIO_4__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2 (_MX53_PAD_GPIO_4__CCM_CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 (_MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 (_MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__ESDHC2_CD (_MX53_PAD_GPIO_4__ESDHC2_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__SCC_SEC_STATE (_MX53_PAD_GPIO_4__SCC_SEC_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3 (_MX53_PAD_GPIO_5__ESAI1_TX2_RX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__GPIO1_5 (_MX53_PAD_GPIO_5__GPIO1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__KPP_ROW_7 (_MX53_PAD_GPIO_5__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__CCM_CLKO (_MX53_PAD_GPIO_5__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 (_MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 (_MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__I2C3_SCL (_MX53_PAD_GPIO_5__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_5__CCM_PLL1_BYP (_MX53_PAD_GPIO_5__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1 (_MX53_PAD_GPIO_7__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__GPIO1_7 (_MX53_PAD_GPIO_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__EPIT1_EPITO (_MX53_PAD_GPIO_7__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__CAN1_TXCAN (_MX53_PAD_GPIO_7__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__UART2_TXD_MUX (_MX53_PAD_GPIO_7__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_GPIO_7__FIRI_RXD (_MX53_PAD_GPIO_7__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__SPDIF_PLOCK (_MX53_PAD_GPIO_7__SPDIF_PLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__CCM_PLL2_BYP (_MX53_PAD_GPIO_7__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0 (_MX53_PAD_GPIO_8__ESAI1_TX5_RX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__GPIO1_8 (_MX53_PAD_GPIO_8__GPIO1_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__EPIT2_EPITO (_MX53_PAD_GPIO_8__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__CAN1_RXCAN (_MX53_PAD_GPIO_8__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__UART2_RXD_MUX (_MX53_PAD_GPIO_8__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_GPIO_8__FIRI_TXD (_MX53_PAD_GPIO_8__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__SPDIF_SRCLK (_MX53_PAD_GPIO_8__SPDIF_SRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__CCM_PLL3_BYP (_MX53_PAD_GPIO_8__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2 (_MX53_PAD_GPIO_16__ESAI1_TX3_RX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__GPIO7_11 (_MX53_PAD_GPIO_16__GPIO7_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT (_MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 (_MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__SPDIF_IN1 (_MX53_PAD_GPIO_16__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__I2C3_SDA (_MX53_PAD_GPIO_16__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_16__SJC_DE_B (_MX53_PAD_GPIO_16__SJC_DE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__ESAI1_TX0 (_MX53_PAD_GPIO_17__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__GPIO7_12 (_MX53_PAD_GPIO_17__GPIO7_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 (_MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__GPC_PMIC_RDY (_MX53_PAD_GPIO_17__GPC_PMIC_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG (_MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__SPDIF_OUT1 (_MX53_PAD_GPIO_17__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__IPU_SNOOP2 (_MX53_PAD_GPIO_17__IPU_SNOOP2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__SJC_JTAG_ACT (_MX53_PAD_GPIO_17__SJC_JTAG_ACT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__ESAI1_TX1 (_MX53_PAD_GPIO_18__ESAI1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__GPIO7_13 (_MX53_PAD_GPIO_18__GPIO7_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 (_MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__OWIRE_LINE (_MX53_PAD_GPIO_18__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG (_MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK (_MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__ESDHC1_LCTL (_MX53_PAD_GPIO_18__ESDHC1_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST (_MX53_PAD_GPIO_18__SRC_SYSTEM_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__KPP_COL_5 IOMUX_PAD(0x348, 0x020, 0, 0x840, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__GPIO4_5 IOMUX_PAD(0x348, 0x020, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__CCM_CLKO IOMUX_PAD(0x348, 0x020, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__SPDIF_OUT1 IOMUX_PAD(0x348, 0x020, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 IOMUX_PAD(0x348, 0x020, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__ECSPI1_RDY IOMUX_PAD(0x348, 0x020, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__FEC_TDATA_3 IOMUX_PAD(0x348, 0x020, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__SRC_INT_BOOT IOMUX_PAD(0x348, 0x020, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__KPP_COL_0 IOMUX_PAD(0x34C, 0x024, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__GPIO4_6 IOMUX_PAD(0x34C, 0x024, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC IOMUX_PAD(0x34C, 0x024, 2, 0x758, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__UART4_TXD_MUX IOMUX_PAD(0x34C, 0x024, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__ECSPI1_SCLK IOMUX_PAD(0x34C, 0x024, 5, 0x79C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__FEC_RDATA_3 IOMUX_PAD(0x34C, 0x024, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST IOMUX_PAD(0x34C, 0x024, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__KPP_ROW_0 IOMUX_PAD(0x350, 0x028, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__GPIO4_7 IOMUX_PAD(0x350, 0x028, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD IOMUX_PAD(0x350, 0x028, 2, 0x74C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX IOMUX_PAD(0x350, 0x028, 4, 0x890, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI IOMUX_PAD(0x350, 0x028, 5, 0x7A4, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__FEC_TX_ER IOMUX_PAD(0x350, 0x028, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__KPP_COL_1 IOMUX_PAD(0x354, 0x02C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__GPIO4_8 IOMUX_PAD(0x354, 0x02C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS IOMUX_PAD(0x354, 0x02C, 2, 0x75C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__UART5_TXD_MUX IOMUX_PAD(0x354, 0x02C, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__ECSPI1_MISO IOMUX_PAD(0x354, 0x02C, 5, 0x7A0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__FEC_RX_CLK IOMUX_PAD(0x354, 0x02C, 6, 0x808, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY IOMUX_PAD(0x354, 0x02C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__KPP_ROW_1 IOMUX_PAD(0x358, 0x030, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__GPIO4_9 IOMUX_PAD(0x358, 0x030, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD IOMUX_PAD(0x358, 0x030, 2, 0x748, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX IOMUX_PAD(0x358, 0x030, 4, 0x898, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__ECSPI1_SS0 IOMUX_PAD(0x358, 0x030, 5, 0x7A8, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__FEC_COL IOMUX_PAD(0x358, 0x030, 6, 0x800, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID IOMUX_PAD(0x358, 0x030, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__KPP_COL_2 IOMUX_PAD(0x35C, 0x034, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__GPIO4_10 IOMUX_PAD(0x35C, 0x034, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__CAN1_TXCAN IOMUX_PAD(0x35C, 0x034, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__FEC_MDIO IOMUX_PAD(0x35C, 0x034, 4, 0x804, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__ECSPI1_SS1 IOMUX_PAD(0x35C, 0x034, 5, 0x7AC, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__FEC_RDATA_2 IOMUX_PAD(0x35C, 0x034, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE IOMUX_PAD(0x35C, 0x034, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__KPP_ROW_2 IOMUX_PAD(0x360, 0x038, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__GPIO4_11 IOMUX_PAD(0x360, 0x038, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__CAN1_RXCAN IOMUX_PAD(0x360, 0x038, 2, 0x760, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__FEC_MDC IOMUX_PAD(0x360, 0x038, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__ECSPI1_SS2 IOMUX_PAD(0x360, 0x038, 5, 0x7B0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__FEC_TDATA_2 IOMUX_PAD(0x360, 0x038, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR IOMUX_PAD(0x360, 0x038, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__KPP_COL_3 IOMUX_PAD(0x364, 0x03C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__GPIO4_12 IOMUX_PAD(0x364, 0x03C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__USBOH3_H2_DP IOMUX_PAD(0x364, 0x03C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__SPDIF_IN1 IOMUX_PAD(0x364, 0x03C, 3, 0x870, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__I2C2_SCL IOMUX_PAD(0x364, 0x03C, 4 | IOMUX_CONFIG_SION, 0x81C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__ECSPI1_SS3 IOMUX_PAD(0x364, 0x03C, 5, 0x7B4, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__FEC_CRS IOMUX_PAD(0x364, 0x03C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK IOMUX_PAD(0x364, 0x03C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__KPP_ROW_3 IOMUX_PAD(0x368, 0x040, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__GPIO4_13 IOMUX_PAD(0x368, 0x040, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM IOMUX_PAD(0x368, 0x040, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK IOMUX_PAD(0x368, 0x040, 3, 0x768, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__I2C2_SDA IOMUX_PAD(0x368, 0x040, 4 | IOMUX_CONFIG_SION, 0x820, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT IOMUX_PAD(0x368, 0x040, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP IOMUX_PAD(0x368, 0x040, 6, 0x77C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 IOMUX_PAD(0x368, 0x040, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__KPP_COL_4 IOMUX_PAD(0x36C, 0x044, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__GPIO4_14 IOMUX_PAD(0x36C, 0x044, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__CAN2_TXCAN IOMUX_PAD(0x36C, 0x044, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__IPU_SISG_4 IOMUX_PAD(0x36C, 0x044, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__UART5_RTS IOMUX_PAD(0x36C, 0x044, 4, 0x894, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC IOMUX_PAD(0x36C, 0x044, 5, 0x89C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 IOMUX_PAD(0x36C, 0x044, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__KPP_ROW_4 IOMUX_PAD(0x370, 0x048, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__GPIO4_15 IOMUX_PAD(0x370, 0x048, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__CAN2_RXCAN IOMUX_PAD(0x370, 0x048, 2, 0x764, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__IPU_SISG_5 IOMUX_PAD(0x370, 0x048, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__UART5_CTS IOMUX_PAD(0x370, 0x048, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR IOMUX_PAD(0x370, 0x048, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID IOMUX_PAD(0x370, 0x048, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK IOMUX_PAD(0x378, 0x04C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__GPIO4_16 IOMUX_PAD(0x378, 0x04C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR IOMUX_PAD(0x378, 0x04C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 IOMUX_PAD(0x378, 0x04C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 IOMUX_PAD(0x378, 0x04C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID IOMUX_PAD(0x378, 0x04C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 IOMUX_PAD(0x37C, 0x050, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__GPIO4_17 IOMUX_PAD(0x37C, 0x050, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC IOMUX_PAD(0x37C, 0x050, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 IOMUX_PAD(0x37C, 0x050, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 IOMUX_PAD(0x37C, 0x050, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID IOMUX_PAD(0x37C, 0x050, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 IOMUX_PAD(0x380, 0x054, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__GPIO4_18 IOMUX_PAD(0x380, 0x054, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD IOMUX_PAD(0x380, 0x054, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 IOMUX_PAD(0x380, 0x054, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 IOMUX_PAD(0x380, 0x054, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION IOMUX_PAD(0x380, 0x054, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 IOMUX_PAD(0x384, 0x058, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__GPIO4_19 IOMUX_PAD(0x384, 0x058, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS IOMUX_PAD(0x384, 0x058, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 IOMUX_PAD(0x384, 0x058, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 IOMUX_PAD(0x384, 0x058, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG IOMUX_PAD(0x384, 0x058, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 IOMUX_PAD(0x388, 0x05C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__GPIO4_20 IOMUX_PAD(0x388, 0x05C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD IOMUX_PAD(0x388, 0x05C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__ESDHC1_WP IOMUX_PAD(0x388, 0x05C, 3, 0x7FC, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD IOMUX_PAD(0x388, 0x05C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 IOMUX_PAD(0x388, 0x05C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT IOMUX_PAD(0x388, 0x05C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 IOMUX_PAD(0x38C, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__GPIO4_21 IOMUX_PAD(0x38C, 0x060, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__CSPI_SCLK IOMUX_PAD(0x38C, 0x060, 2, 0x780, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 IOMUX_PAD(0x38C, 0x060, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN IOMUX_PAD(0x38C, 0x060, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 IOMUX_PAD(0x38C, 0x060, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY IOMUX_PAD(0x38C, 0x060, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 IOMUX_PAD(0x390, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__GPIO4_22 IOMUX_PAD(0x390, 0x064, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__CSPI_MOSI IOMUX_PAD(0x390, 0x064, 2, 0x788, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 IOMUX_PAD(0x390, 0x064, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL \
+ IOMUX_PAD(0x390, 0x064, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 IOMUX_PAD(0x390, 0x064, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID IOMUX_PAD(0x390, 0x064, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 IOMUX_PAD(0x394, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__GPIO4_23 IOMUX_PAD(0x394, 0x068, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__CSPI_MISO IOMUX_PAD(0x394, 0x068, 2, 0x784, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 IOMUX_PAD(0x394, 0x068, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE IOMUX_PAD(0x394, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 IOMUX_PAD(0x394, 0x068, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE IOMUX_PAD(0x394, 0x068, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 IOMUX_PAD(0x398, 0x06C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__GPIO4_24 IOMUX_PAD(0x398, 0x06C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__CSPI_SS0 IOMUX_PAD(0x398, 0x06C, 2, 0x78C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 IOMUX_PAD(0x398, 0x06C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR IOMUX_PAD(0x398, 0x06C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 IOMUX_PAD(0x398, 0x06C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR IOMUX_PAD(0x398, 0x06C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 IOMUX_PAD(0x39C, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__GPIO4_25 IOMUX_PAD(0x39C, 0x070, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__CSPI_SS1 IOMUX_PAD(0x39C, 0x070, 2, 0x790, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 IOMUX_PAD(0x39C, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB IOMUX_PAD(0x39C, 0x070, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 IOMUX_PAD(0x39C, 0x070, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK IOMUX_PAD(0x39C, 0x070, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 IOMUX_PAD(0x3A0, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__GPIO4_26 IOMUX_PAD(0x3A0, 0x074, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__CSPI_SS2 IOMUX_PAD(0x3A0, 0x074, 2, 0x794, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 IOMUX_PAD(0x3A0, 0x074, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS IOMUX_PAD(0x3A0, 0x074, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 IOMUX_PAD(0x3A0, 0x074, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 IOMUX_PAD(0x3A0, 0x074, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 IOMUX_PAD(0x3A4, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__GPIO4_27 IOMUX_PAD(0x3A4, 0x078, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__CSPI_SS3 IOMUX_PAD(0x3A4, 0x078, 2, 0x798, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 IOMUX_PAD(0x3A4, 0x078, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE IOMUX_PAD(0x3A4, 0x078, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 IOMUX_PAD(0x3A4, 0x078, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 IOMUX_PAD(0x3A4, 0x078, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 IOMUX_PAD(0x3A8, 0x07C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__GPIO4_28 IOMUX_PAD(0x3A8, 0x07C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__CSPI_RDY IOMUX_PAD(0x3A8, 0x07C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 IOMUX_PAD(0x3A8, 0x07C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 IOMUX_PAD(0x3A8, 0x07C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 IOMUX_PAD(0x3A8, 0x07C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID IOMUX_PAD(0x3A8, 0x07C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 IOMUX_PAD(0x3AC, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__GPIO4_29 IOMUX_PAD(0x3AC, 0x080, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__PWM1_PWMO IOMUX_PAD(0x3AC, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B IOMUX_PAD(0x3AC, 0x080, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 IOMUX_PAD(0x3AC, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 IOMUX_PAD(0x3AC, 0x080, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID IOMUX_PAD(0x3AC, 0x080, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 IOMUX_PAD(0x3B0, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__GPIO4_30 IOMUX_PAD(0x3B0, 0x084, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__PWM2_PWMO IOMUX_PAD(0x3B0, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B IOMUX_PAD(0x3B0, 0x084, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 IOMUX_PAD(0x3B0, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 IOMUX_PAD(0x3B0, 0x084, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 IOMUX_PAD(0x3B0, 0x084, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 IOMUX_PAD(0x3B4, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__GPIO4_31 IOMUX_PAD(0x3B4, 0x088, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP IOMUX_PAD(0x3B4, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 \
+ IOMUX_PAD(0x3B4, 0x088, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 IOMUX_PAD(0x3B4, 0x088, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 IOMUX_PAD(0x3B4, 0x088, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 IOMUX_PAD(0x3B8, 0x08C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__GPIO5_5 IOMUX_PAD(0x3B8, 0x08C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT IOMUX_PAD(0x3B8, 0x08C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 \
+ IOMUX_PAD(0x3B8, 0x08C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 IOMUX_PAD(0x3B8, 0x08C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 IOMUX_PAD(0x3B8, 0x08C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 IOMUX_PAD(0x3BC, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__GPIO5_6 IOMUX_PAD(0x3BC, 0x090, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK IOMUX_PAD(0x3BC, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 \
+ IOMUX_PAD(0x3BC, 0x090, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 IOMUX_PAD(0x3BC, 0x090, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 IOMUX_PAD(0x3BC, 0x090, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 IOMUX_PAD(0x3C0, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__GPIO5_7 IOMUX_PAD(0x3C0, 0x094, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS IOMUX_PAD(0x3C0, 0x094, 3, 0x754, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 \
+ IOMUX_PAD(0x3C0, 0x094, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 IOMUX_PAD(0x3C0, 0x094, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 IOMUX_PAD(0x3C0, 0x094, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 IOMUX_PAD(0x3C4, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__GPIO5_8 IOMUX_PAD(0x3C4, 0x098, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC IOMUX_PAD(0x3C4, 0x098, 3, 0x750, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 \
+ IOMUX_PAD(0x3C4, 0x098, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 IOMUX_PAD(0x3C4, 0x098, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 IOMUX_PAD(0x3C4, 0x098, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 IOMUX_PAD(0x3C8, 0x09C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__GPIO5_9 IOMUX_PAD(0x3C8, 0x09C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1 IOMUX_PAD(0x3C8, 0x09C, 2, 0x7AC, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1 IOMUX_PAD(0x3C8, 0x09C, 3, 0x7C8, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 \
+ IOMUX_PAD(0x3C8, 0x09C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 IOMUX_PAD(0x3C8, 0x09C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 IOMUX_PAD(0x3C8, 0x09C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 IOMUX_PAD(0x3CC, 0x0A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__GPIO5_10 IOMUX_PAD(0x3CC, 0x0A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI IOMUX_PAD(0x3CC, 0x0A0, 2, 0x7C0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC IOMUX_PAD(0x3CC, 0x0A0, 3, 0x758, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 IOMUX_PAD(0x3CC, 0x0A0, 4, 0x868, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 \
+ IOMUX_PAD(0x3CC, 0x0A0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 IOMUX_PAD(0x3CC, 0x0A0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 IOMUX_PAD(0x3CC, 0x0A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 IOMUX_PAD(0x3D0, 0x0A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__GPIO5_11 IOMUX_PAD(0x3D0, 0x0A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO IOMUX_PAD(0x3D0, 0x0A4, 2, 0x7BC, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD IOMUX_PAD(0x3D0, 0x0A4, 3, 0x74C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 IOMUX_PAD(0x3D0, 0x0A4, 4, 0x86C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 \
+ IOMUX_PAD(0x3D0, 0x0A4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 IOMUX_PAD(0x3D0, 0x0A4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 IOMUX_PAD(0x3D4, 0x0A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__GPIO5_12 IOMUX_PAD(0x3D4, 0x0A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0 IOMUX_PAD(0x3D4, 0x0A8, 2, 0x7C4, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS IOMUX_PAD(0x3D4, 0x0A8, 3, 0x75C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS IOMUX_PAD(0x3D4, 0x0A8, 4, 0x73C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 \
+ IOMUX_PAD(0x3D4, 0x0A8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 IOMUX_PAD(0x3D4, 0x0A8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 IOMUX_PAD(0x3D4, 0x0A8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 IOMUX_PAD(0x3D8, 0x0AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__GPIO5_13 IOMUX_PAD(0x3D8, 0x0AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK IOMUX_PAD(0x3D8, 0x0AC, 2, 0x7B8, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD IOMUX_PAD(0x3D8, 0x0AC, 3, 0x748, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC IOMUX_PAD(0x3D8, 0x0AC, 4, 0x738, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 \
+ IOMUX_PAD(0x3D8, 0x0AC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 IOMUX_PAD(0x3D8, 0x0AC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 IOMUX_PAD(0x3D8, 0x0AC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 IOMUX_PAD(0x3DC, 0x0B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__GPIO5_14 IOMUX_PAD(0x3DC, 0x0B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK IOMUX_PAD(0x3DC, 0x0B0, 2, 0x79C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC IOMUX_PAD(0x3DC, 0x0B0, 3, 0x740, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 \
+ IOMUX_PAD(0x3DC, 0x0B0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 IOMUX_PAD(0x3DC, 0x0B0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI IOMUX_PAD(0x3DC, 0x0B0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 IOMUX_PAD(0x3E0, 0x0B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__GPIO5_15 IOMUX_PAD(0x3E0, 0x0B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI IOMUX_PAD(0x3E0, 0x0B4, 2, 0x7A4, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD IOMUX_PAD(0x3E0, 0x0B4, 3, 0x734, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 IOMUX_PAD(0x3E0, 0x0B4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 IOMUX_PAD(0x3E0, 0x0B4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO IOMUX_PAD(0x3E0, 0x0B4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 IOMUX_PAD(0x3E4, 0x0B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__GPIO5_16 IOMUX_PAD(0x3E4, 0x0B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO IOMUX_PAD(0x3E4, 0x0B8, 2, 0x7A0, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS IOMUX_PAD(0x3E4, 0x0B8, 3, 0x744, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 IOMUX_PAD(0x3E4, 0x0B8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 IOMUX_PAD(0x3E4, 0x0B8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK IOMUX_PAD(0x3E4, 0x0B8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 IOMUX_PAD(0x3E8, 0x0BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__GPIO5_17 IOMUX_PAD(0x3E8, 0x0BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0 IOMUX_PAD(0x3E8, 0x0BC, 2, 0x7A8, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD IOMUX_PAD(0x3E8, 0x0BC, 3, 0x730, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 IOMUX_PAD(0x3E8, 0x0BC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 IOMUX_PAD(0x3E8, 0x0BC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS IOMUX_PAD(0x3E8, 0x0BC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK IOMUX_PAD(0x3EC, 0x0C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__GPIO5_18 IOMUX_PAD(0x3EC, 0x0C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 IOMUX_PAD(0x3EC, 0x0C0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 IOMUX_PAD(0x3EC, 0x0C0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC IOMUX_PAD(0x3F0, 0x0C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__GPIO5_19 IOMUX_PAD(0x3F0, 0x0C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK IOMUX_PAD(0x3F0, 0x0C4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 IOMUX_PAD(0x3F0, 0x0C4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 IOMUX_PAD(0x3F0, 0x0C4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL IOMUX_PAD(0x3F0, 0x0C4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN IOMUX_PAD(0x3F4, 0x0C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__GPIO5_20 IOMUX_PAD(0x3F4, 0x0C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 IOMUX_PAD(0x3F4, 0x0C8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 IOMUX_PAD(0x3F4, 0x0C8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK IOMUX_PAD(0x3F4, 0x0C8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC IOMUX_PAD(0x3F8, 0x0CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__GPIO5_21 IOMUX_PAD(0x3F8, 0x0CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 IOMUX_PAD(0x3F8, 0x0CC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 IOMUX_PAD(0x3F8, 0x0CC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 IOMUX_PAD(0x3F8, 0x0CC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 IOMUX_PAD(0x3FC, 0x0D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__GPIO5_22 IOMUX_PAD(0x3FC, 0x0D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__KPP_COL_5 IOMUX_PAD(0x3FC, 0x0D0, 2, 0x840, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK IOMUX_PAD(0x3FC, 0x0D0, 3, 0x79C, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP IOMUX_PAD(0x3FC, 0x0D0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC IOMUX_PAD(0x3FC, 0x0D0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 IOMUX_PAD(0x3FC, 0x0D0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 IOMUX_PAD(0x3FC, 0x0D0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 IOMUX_PAD(0x400, 0x0D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__GPIO5_23 IOMUX_PAD(0x400, 0x0D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__KPP_ROW_5 IOMUX_PAD(0x400, 0x0D4, 2, 0x84C, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI IOMUX_PAD(0x400, 0x0D4, 3, 0x7A4, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT IOMUX_PAD(0x400, 0x0D4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD IOMUX_PAD(0x400, 0x0D4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 IOMUX_PAD(0x400, 0x0D4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 IOMUX_PAD(0x400, 0x0D4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 IOMUX_PAD(0x404, 0x0D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__GPIO5_24 IOMUX_PAD(0x404, 0x0D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__KPP_COL_6 IOMUX_PAD(0x404, 0x0D8, 2, 0x844, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO IOMUX_PAD(0x404, 0x0D8, 3, 0x7A0, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK IOMUX_PAD(0x404, 0x0D8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS IOMUX_PAD(0x404, 0x0D8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 IOMUX_PAD(0x404, 0x0D8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 IOMUX_PAD(0x404, 0x0D8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 IOMUX_PAD(0x408, 0x0DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__GPIO5_25 IOMUX_PAD(0x408, 0x0DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__KPP_ROW_6 IOMUX_PAD(0x408, 0x0DC, 2, 0x850, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0 IOMUX_PAD(0x408, 0x0DC, 3, 0x7A8, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR IOMUX_PAD(0x408, 0x0DC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD IOMUX_PAD(0x408, 0x0DC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 IOMUX_PAD(0x408, 0x0DC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 IOMUX_PAD(0x408, 0x0DC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 IOMUX_PAD(0x40C, 0x0E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__GPIO5_26 IOMUX_PAD(0x40C, 0x0E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__KPP_COL_7 IOMUX_PAD(0x40C, 0x0E0, 2, 0x848, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK IOMUX_PAD(0x40C, 0x0E0, 3, 0x7B8, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC IOMUX_PAD(0x40C, 0x0E0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__I2C1_SDA IOMUX_PAD(0x40C, 0x0E0, 5 | IOMUX_CONFIG_SION, 0x818, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 IOMUX_PAD(0x40C, 0x0E0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 IOMUX_PAD(0x40C, 0x0E0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 IOMUX_PAD(0x410, 0x0E4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__GPIO5_27 IOMUX_PAD(0x410, 0x0E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__KPP_ROW_7 IOMUX_PAD(0x410, 0x0E4, 2, 0x854, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI IOMUX_PAD(0x410, 0x0E4, 3, 0x7C0, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR IOMUX_PAD(0x410, 0x0E4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__I2C1_SCL IOMUX_PAD(0x410, 0x0E4, 5 | IOMUX_CONFIG_SION, 0x814, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 IOMUX_PAD(0x410, 0x0E4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 IOMUX_PAD(0x410, 0x0E4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 IOMUX_PAD(0x414, 0x0E8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__GPIO5_28 IOMUX_PAD(0x414, 0x0E8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX IOMUX_PAD(0x414, 0x0E8, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO IOMUX_PAD(0x414, 0x0E8, 3, 0x7BC, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC IOMUX_PAD(0x414, 0x0E8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 IOMUX_PAD(0x414, 0x0E8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 IOMUX_PAD(0x414, 0x0E8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 IOMUX_PAD(0x414, 0x0E8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 IOMUX_PAD(0x418, 0x0EC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__GPIO5_29 IOMUX_PAD(0x418, 0x0EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX IOMUX_PAD(0x418, 0x0EC, 2, 0x878, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0 IOMUX_PAD(0x418, 0x0EC, 3, 0x7C4, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS IOMUX_PAD(0x418, 0x0EC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 IOMUX_PAD(0x418, 0x0EC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 IOMUX_PAD(0x418, 0x0EC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 IOMUX_PAD(0x418, 0x0EC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 IOMUX_PAD(0x41C, 0x0F0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__GPIO5_30 IOMUX_PAD(0x41C, 0x0F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX IOMUX_PAD(0x41C, 0x0F0, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 IOMUX_PAD(0x41C, 0x0F0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 IOMUX_PAD(0x41C, 0x0F0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 IOMUX_PAD(0x41C, 0x0F0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 IOMUX_PAD(0x41C, 0x0F0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 IOMUX_PAD(0x420, 0x0F4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__GPIO5_31 IOMUX_PAD(0x420, 0x0F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX IOMUX_PAD(0x420, 0x0F4, 2, 0x890, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 IOMUX_PAD(0x420, 0x0F4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 IOMUX_PAD(0x420, 0x0F4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 IOMUX_PAD(0x420, 0x0F4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 IOMUX_PAD(0x420, 0x0F4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 IOMUX_PAD(0x424, 0x0F8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__GPIO6_0 IOMUX_PAD(0x424, 0x0F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX IOMUX_PAD(0x424, 0x0F8, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 IOMUX_PAD(0x424, 0x0F8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 IOMUX_PAD(0x424, 0x0F8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 IOMUX_PAD(0x424, 0x0F8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 IOMUX_PAD(0x424, 0x0F8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 IOMUX_PAD(0x428, 0x0FC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__GPIO6_1 IOMUX_PAD(0x428, 0x0FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX IOMUX_PAD(0x428, 0x0FC, 2, 0x898, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 IOMUX_PAD(0x428, 0x0FC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 IOMUX_PAD(0x428, 0x0FC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 IOMUX_PAD(0x428, 0x0FC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 IOMUX_PAD(0x428, 0x0FC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 IOMUX_PAD(0x42C, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__GPIO6_2 IOMUX_PAD(0x42C, 0x100, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__UART4_RTS IOMUX_PAD(0x42C, 0x100, 2, 0x88C, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 IOMUX_PAD(0x42C, 0x100, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 IOMUX_PAD(0x42C, 0x100, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 IOMUX_PAD(0x42C, 0x100, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 IOMUX_PAD(0x42C, 0x100, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 IOMUX_PAD(0x430, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__GPIO6_3 IOMUX_PAD(0x430, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__UART4_CTS IOMUX_PAD(0x430, 0x104, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 IOMUX_PAD(0x430, 0x104, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 IOMUX_PAD(0x430, 0x104, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 IOMUX_PAD(0x430, 0x104, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 IOMUX_PAD(0x430, 0x104, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 IOMUX_PAD(0x434, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__GPIO6_4 IOMUX_PAD(0x434, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__UART5_RTS IOMUX_PAD(0x434, 0x108, 2, 0x894, 2, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 IOMUX_PAD(0x434, 0x108, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 IOMUX_PAD(0x434, 0x108, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 IOMUX_PAD(0x434, 0x108, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 IOMUX_PAD(0x434, 0x108, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 IOMUX_PAD(0x438, 0x10C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__GPIO6_5 IOMUX_PAD(0x438, 0x10C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__UART5_CTS IOMUX_PAD(0x438, 0x10C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 IOMUX_PAD(0x438, 0x10C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 IOMUX_PAD(0x438, 0x10C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 IOMUX_PAD(0x438, 0x10C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK IOMUX_PAD(0x438, 0x10C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__EMI_WEIM_A_25 IOMUX_PAD(0x458, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__GPIO5_2 IOMUX_PAD(0x458, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__ECSPI2_RDY IOMUX_PAD(0x458, 0x110, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__IPU_DI1_PIN12 IOMUX_PAD(0x458, 0x110, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__CSPI_SS1 IOMUX_PAD(0x458, 0x110, 4, 0x790, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS IOMUX_PAD(0x458, 0x110, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__USBPHY1_BISTOK IOMUX_PAD(0x458, 0x110, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 IOMUX_PAD(0x45C, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__GPIO2_30 IOMUX_PAD(0x45C, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK IOMUX_PAD(0x45C, 0x114, 2, 0x76C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS IOMUX_PAD(0x45C, 0x114, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__ECSPI1_SS0 IOMUX_PAD(0x45C, 0x114, 4, 0x7A8, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__I2C2_SCL IOMUX_PAD(0x45C, 0x114, 5 | IOMUX_CONFIG_SION, 0x81C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__EMI_WEIM_D_16 IOMUX_PAD(0x460, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__GPIO3_16 IOMUX_PAD(0x460, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__IPU_DI0_PIN5 IOMUX_PAD(0x460, 0x118, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK IOMUX_PAD(0x460, 0x118, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__ECSPI1_SCLK IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__I2C2_SDA IOMUX_PAD(0x460, 0x118, 5 | IOMUX_CONFIG_SION, 0x820, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__EMI_WEIM_D_17 IOMUX_PAD(0x464, 0x11C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__GPIO3_17 IOMUX_PAD(0x464, 0x11C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__IPU_DI0_PIN6 IOMUX_PAD(0x464, 0x11C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__ECSPI1_MISO IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__I2C3_SCL IOMUX_PAD(0x464, 0x11C, 5 | IOMUX_CONFIG_SION, 0x824, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__EMI_WEIM_D_18 IOMUX_PAD(0x468, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__GPIO3_18 IOMUX_PAD(0x468, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DI0_PIN7 IOMUX_PAD(0x468, 0x120, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__ECSPI1_MOSI IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__I2C3_SDA IOMUX_PAD(0x468, 0x120, 5 | IOMUX_CONFIG_SION, 0x828, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS IOMUX_PAD(0x468, 0x120, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__EMI_WEIM_D_19 IOMUX_PAD(0x46C, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__GPIO3_19 IOMUX_PAD(0x46C, 0x124, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__IPU_DI0_PIN8 IOMUX_PAD(0x46C, 0x124, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS IOMUX_PAD(0x46C, 0x124, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__ECSPI1_SS1 IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__EPIT1_EPITO IOMUX_PAD(0x46C, 0x124, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__UART1_CTS IOMUX_PAD(0x46C, 0x124, 6, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__EMI_WEIM_D_20 IOMUX_PAD(0x470, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__GPIO3_20 IOMUX_PAD(0x470, 0x128, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__IPU_DI0_PIN16 IOMUX_PAD(0x470, 0x128, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS IOMUX_PAD(0x470, 0x128, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__CSPI_SS0 IOMUX_PAD(0x470, 0x128, 4, 0x78C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__EPIT2_EPITO IOMUX_PAD(0x470, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__UART1_RTS IOMUX_PAD(0x470, 0x128, 6, 0x874, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR IOMUX_PAD(0x470, 0x128, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__EMI_WEIM_D_21 IOMUX_PAD(0x474, 0x12C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__GPIO3_21 IOMUX_PAD(0x474, 0x12C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__IPU_DI0_PIN17 IOMUX_PAD(0x474, 0x12C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK IOMUX_PAD(0x474, 0x12C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__CSPI_SCLK IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__I2C1_SCL IOMUX_PAD(0x474, 0x12C, 5 | IOMUX_CONFIG_SION, 0x814, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__EMI_WEIM_D_22 IOMUX_PAD(0x478, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__GPIO3_22 IOMUX_PAD(0x478, 0x130, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__IPU_DI0_PIN1 IOMUX_PAD(0x478, 0x130, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN IOMUX_PAD(0x478, 0x130, 3, 0x82C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__CSPI_MISO IOMUX_PAD(0x478, 0x130, 4, 0x784, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR IOMUX_PAD(0x478, 0x130, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__EMI_WEIM_D_23 IOMUX_PAD(0x47C, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__GPIO3_23 IOMUX_PAD(0x47C, 0x134, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__UART3_CTS IOMUX_PAD(0x47C, 0x134, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D23__UART1_DCD IOMUX_PAD(0x47C, 0x134, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS IOMUX_PAD(0x47C, 0x134, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN2 IOMUX_PAD(0x47C, 0x134, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN IOMUX_PAD(0x47C, 0x134, 6, 0x834, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN14 IOMUX_PAD(0x47C, 0x134, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 IOMUX_PAD(0x480, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__GPIO2_31 IOMUX_PAD(0x480, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__UART3_RTS IOMUX_PAD(0x480, 0x138, 2, 0x884, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__UART1_RI IOMUX_PAD(0x480, 0x138, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3 IOMUX_PAD(0x480, 0x138, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC IOMUX_PAD(0x480, 0x138, 6, 0x838, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16 IOMUX_PAD(0x480, 0x138, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__EMI_WEIM_D_24 IOMUX_PAD(0x484, 0x13C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__GPIO3_24 IOMUX_PAD(0x484, 0x13C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__UART3_TXD_MUX IOMUX_PAD(0x484, 0x13C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D24__ECSPI1_SS2 IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__CSPI_SS2 IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__ECSPI2_SS2 IOMUX_PAD(0x484, 0x13C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__UART1_DTR IOMUX_PAD(0x484, 0x13C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__EMI_WEIM_D_25 IOMUX_PAD(0x488, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__GPIO3_25 IOMUX_PAD(0x488, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__UART3_RXD_MUX IOMUX_PAD(0x488, 0x140, 2, 0x888, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D25__ECSPI1_SS3 IOMUX_PAD(0x488, 0x140, 3, 0x7B4, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__CSPI_SS3 IOMUX_PAD(0x488, 0x140, 4, 0x798, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC IOMUX_PAD(0x488, 0x140, 5, 0x750, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__ECSPI2_SS3 IOMUX_PAD(0x488, 0x140, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__UART1_DSR IOMUX_PAD(0x488, 0x140, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__EMI_WEIM_D_26 IOMUX_PAD(0x48C, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__GPIO3_26 IOMUX_PAD(0x48C, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__UART2_TXD_MUX IOMUX_PAD(0x48C, 0x144, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D26__FIRI_RXD IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_CSI0_D_1 IOMUX_PAD(0x48C, 0x144, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_DI1_PIN11 IOMUX_PAD(0x48C, 0x144, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_SISG_2 IOMUX_PAD(0x48C, 0x144, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 IOMUX_PAD(0x48C, 0x144, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__EMI_WEIM_D_27 IOMUX_PAD(0x490, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__GPIO3_27 IOMUX_PAD(0x490, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__UART2_RXD_MUX IOMUX_PAD(0x490, 0x148, 2, 0x880, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D27__FIRI_TXD IOMUX_PAD(0x490, 0x148, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_CSI0_D_0 IOMUX_PAD(0x490, 0x148, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_DI1_PIN13 IOMUX_PAD(0x490, 0x148, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_SISG_3 IOMUX_PAD(0x490, 0x148, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 IOMUX_PAD(0x490, 0x148, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__EMI_WEIM_D_28 IOMUX_PAD(0x494, 0x14C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__GPIO3_28 IOMUX_PAD(0x494, 0x14C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__UART2_CTS IOMUX_PAD(0x494, 0x14C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__CSPI_MOSI IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__I2C1_SDA IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, PAD_CTRL_I2C)
+#define MX53_PAD_EIM_D28__IPU_EXT_TRIG IOMUX_PAD(0x494, 0x14C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__IPU_DI0_PIN13 IOMUX_PAD(0x494, 0x14C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__EMI_WEIM_D_29 IOMUX_PAD(0x498, 0x150, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__GPIO3_29 IOMUX_PAD(0x498, 0x150, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__UART2_RTS IOMUX_PAD(0x498, 0x150, 2, 0x87C, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS IOMUX_PAD(0x498, 0x150, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__CSPI_SS0 IOMUX_PAD(0x498, 0x150, 4, 0x78C, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DI1_PIN15 IOMUX_PAD(0x498, 0x150, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC IOMUX_PAD(0x498, 0x150, 6, 0x83C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DI0_PIN14 IOMUX_PAD(0x498, 0x150, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__EMI_WEIM_D_30 IOMUX_PAD(0x49C, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__GPIO3_30 IOMUX_PAD(0x49C, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__UART3_CTS IOMUX_PAD(0x49C, 0x154, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_CSI0_D_3 IOMUX_PAD(0x49C, 0x154, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_DI0_PIN11 IOMUX_PAD(0x49C, 0x154, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 IOMUX_PAD(0x49C, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC IOMUX_PAD(0x49C, 0x154, 6, 0x8A0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC IOMUX_PAD(0x49C, 0x154, 7, 0x8A4, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__EMI_WEIM_D_31 IOMUX_PAD(0x4A0, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__GPIO3_31 IOMUX_PAD(0x4A0, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__UART3_RTS IOMUX_PAD(0x4A0, 0x158, 2, 0x884, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_CSI0_D_2 IOMUX_PAD(0x4A0, 0x158, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_DI0_PIN12 IOMUX_PAD(0x4A0, 0x158, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 IOMUX_PAD(0x4A0, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR IOMUX_PAD(0x4A0, 0x158, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR IOMUX_PAD(0x4A0, 0x158, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__EMI_WEIM_A_24 IOMUX_PAD(0x4A8, 0x15C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__GPIO5_4 IOMUX_PAD(0x4A8, 0x15C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 IOMUX_PAD(0x4A8, 0x15C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_CSI1_D_19 IOMUX_PAD(0x4A8, 0x15C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_SISG_2 IOMUX_PAD(0x4A8, 0x15C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__USBPHY2_BVALID IOMUX_PAD(0x4A8, 0x15C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__EMI_WEIM_A_23 IOMUX_PAD(0x4AC, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__GPIO6_6 IOMUX_PAD(0x4AC, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 IOMUX_PAD(0x4AC, 0x160, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_CSI1_D_18 IOMUX_PAD(0x4AC, 0x160, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_SISG_3 IOMUX_PAD(0x4AC, 0x160, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION IOMUX_PAD(0x4AC, 0x160, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__EMI_WEIM_A_22 IOMUX_PAD(0x4B0, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__GPIO2_16 IOMUX_PAD(0x4B0, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 IOMUX_PAD(0x4B0, 0x164, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__IPU_CSI1_D_17 IOMUX_PAD(0x4B0, 0x164, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7 IOMUX_PAD(0x4B0, 0x164, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__EMI_WEIM_A_21 IOMUX_PAD(0x4B4, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__GPIO2_17 IOMUX_PAD(0x4B4, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 IOMUX_PAD(0x4B4, 0x168, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__IPU_CSI1_D_16 IOMUX_PAD(0x4B4, 0x168, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6 IOMUX_PAD(0x4B4, 0x168, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__EMI_WEIM_A_20 IOMUX_PAD(0x4B8, 0x16C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__GPIO2_18 IOMUX_PAD(0x4B8, 0x16C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 IOMUX_PAD(0x4B8, 0x16C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__IPU_CSI1_D_15 IOMUX_PAD(0x4B8, 0x16C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5 IOMUX_PAD(0x4B8, 0x16C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__EMI_WEIM_A_19 IOMUX_PAD(0x4BC, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__GPIO2_19 IOMUX_PAD(0x4BC, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 IOMUX_PAD(0x4BC, 0x170, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__IPU_CSI1_D_14 IOMUX_PAD(0x4BC, 0x170, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4 IOMUX_PAD(0x4BC, 0x170, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__EMI_WEIM_A_18 IOMUX_PAD(0x4C0, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__GPIO2_20 IOMUX_PAD(0x4C0, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 IOMUX_PAD(0x4C0, 0x174, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__IPU_CSI1_D_13 IOMUX_PAD(0x4C0, 0x174, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3 IOMUX_PAD(0x4C0, 0x174, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__EMI_WEIM_A_17 IOMUX_PAD(0x4C4, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__GPIO2_21 IOMUX_PAD(0x4C4, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 IOMUX_PAD(0x4C4, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__IPU_CSI1_D_12 IOMUX_PAD(0x4C4, 0x178, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2 IOMUX_PAD(0x4C4, 0x178, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__EMI_WEIM_A_16 IOMUX_PAD(0x4C8, 0x17C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__GPIO2_22 IOMUX_PAD(0x4C8, 0x17C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK IOMUX_PAD(0x4C8, 0x17C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK IOMUX_PAD(0x4C8, 0x17C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1 IOMUX_PAD(0x4C8, 0x17C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 IOMUX_PAD(0x4CC, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__GPIO2_23 IOMUX_PAD(0x4CC, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__ECSPI2_SCLK IOMUX_PAD(0x4CC, 0x180, 2, 0x7B8, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5 IOMUX_PAD(0x4CC, 0x180, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 IOMUX_PAD(0x4D0, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__GPIO2_24 IOMUX_PAD(0x4D0, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__ECSPI2_MOSI IOMUX_PAD(0x4D0, 0x184, 2, 0x7C0, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6 IOMUX_PAD(0x4D0, 0x184, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__EMI_WEIM_OE IOMUX_PAD(0x4D4, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__GPIO2_25 IOMUX_PAD(0x4D4, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__ECSPI2_MISO IOMUX_PAD(0x4D4, 0x188, 2, 0x7BC, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__IPU_DI1_PIN7 IOMUX_PAD(0x4D4, 0x188, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__USBPHY2_IDDIG IOMUX_PAD(0x4D4, 0x188, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__EMI_WEIM_RW IOMUX_PAD(0x4D8, 0x18C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__GPIO2_26 IOMUX_PAD(0x4D8, 0x18C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__ECSPI2_SS0 IOMUX_PAD(0x4D8, 0x18C, 2, 0x7C4, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__IPU_DI1_PIN8 IOMUX_PAD(0x4D8, 0x18C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT IOMUX_PAD(0x4D8, 0x18C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA IOMUX_PAD(0x4DC, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__GPIO2_27 IOMUX_PAD(0x4DC, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__ECSPI2_SS1 IOMUX_PAD(0x4DC, 0x190, 2, 0x7C8, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17 IOMUX_PAD(0x4DC, 0x190, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 IOMUX_PAD(0x4DC, 0x190, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 IOMUX_PAD(0x4E4, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__GPIO2_28 IOMUX_PAD(0x4E4, 0x194, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 IOMUX_PAD(0x4E4, 0x194, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11 IOMUX_PAD(0x4E4, 0x194, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY IOMUX_PAD(0x4E4, 0x194, 5, 0x810, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 IOMUX_PAD(0x4E4, 0x194, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 IOMUX_PAD(0x4E8, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__GPIO2_29 IOMUX_PAD(0x4E8, 0x198, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 IOMUX_PAD(0x4E8, 0x198, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10 IOMUX_PAD(0x4E8, 0x198, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 IOMUX_PAD(0x4E8, 0x198, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 IOMUX_PAD(0x4EC, 0x19C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__GPIO3_0 IOMUX_PAD(0x4EC, 0x19C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 IOMUX_PAD(0x4EC, 0x19C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9 IOMUX_PAD(0x4EC, 0x19C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 IOMUX_PAD(0x4EC, 0x19C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 IOMUX_PAD(0x4F0, 0x1A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__GPIO3_1 IOMUX_PAD(0x4F0, 0x1A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 IOMUX_PAD(0x4F0, 0x1A0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8 IOMUX_PAD(0x4F0, 0x1A0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 IOMUX_PAD(0x4F0, 0x1A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 IOMUX_PAD(0x4F4, 0x1A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__GPIO3_2 IOMUX_PAD(0x4F4, 0x1A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 IOMUX_PAD(0x4F4, 0x1A4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7 IOMUX_PAD(0x4F4, 0x1A4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 IOMUX_PAD(0x4F4, 0x1A4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 IOMUX_PAD(0x4F8, 0x1A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__GPIO3_3 IOMUX_PAD(0x4F8, 0x1A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 IOMUX_PAD(0x4F8, 0x1A8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6 IOMUX_PAD(0x4F8, 0x1A8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 IOMUX_PAD(0x4F8, 0x1A8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 IOMUX_PAD(0x4FC, 0x1AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__GPIO3_4 IOMUX_PAD(0x4FC, 0x1AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 IOMUX_PAD(0x4FC, 0x1AC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5 IOMUX_PAD(0x4FC, 0x1AC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 IOMUX_PAD(0x4FC, 0x1AC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 IOMUX_PAD(0x500, 0x1B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__GPIO3_5 IOMUX_PAD(0x500, 0x1B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 IOMUX_PAD(0x500, 0x1B0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4 IOMUX_PAD(0x500, 0x1B0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 IOMUX_PAD(0x500, 0x1B0, 7 | IOMUX_CONFIG_SION, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 IOMUX_PAD(0x504, 0x1B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__GPIO3_6 IOMUX_PAD(0x504, 0x1B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 IOMUX_PAD(0x504, 0x1B4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3 IOMUX_PAD(0x504, 0x1B4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 IOMUX_PAD(0x504, 0x1B4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 IOMUX_PAD(0x508, 0x1B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__GPIO3_7 IOMUX_PAD(0x508, 0x1B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 IOMUX_PAD(0x508, 0x1B8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2 IOMUX_PAD(0x508, 0x1B8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 IOMUX_PAD(0x508, 0x1B8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 IOMUX_PAD(0x50C, 0x1BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__GPIO3_8 IOMUX_PAD(0x50C, 0x1BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 IOMUX_PAD(0x50C, 0x1BC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1 IOMUX_PAD(0x50C, 0x1BC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 IOMUX_PAD(0x50C, 0x1BC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 IOMUX_PAD(0x510, 0x1C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__GPIO3_9 IOMUX_PAD(0x510, 0x1C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 IOMUX_PAD(0x510, 0x1C0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0 IOMUX_PAD(0x510, 0x1C0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 IOMUX_PAD(0x510, 0x1C0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 IOMUX_PAD(0x514, 0x1C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__GPIO3_10 IOMUX_PAD(0x514, 0x1C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15 IOMUX_PAD(0x514, 0x1C4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN IOMUX_PAD(0x514, 0x1C4, 4, 0x834, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 IOMUX_PAD(0x514, 0x1C4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 IOMUX_PAD(0x518, 0x1C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__GPIO3_11 IOMUX_PAD(0x518, 0x1C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2 IOMUX_PAD(0x518, 0x1C8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC IOMUX_PAD(0x518, 0x1C8, 4, 0x838, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 IOMUX_PAD(0x51C, 0x1CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__GPIO3_12 IOMUX_PAD(0x51C, 0x1CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3 IOMUX_PAD(0x51C, 0x1CC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC IOMUX_PAD(0x51C, 0x1CC, 4, 0x83C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 IOMUX_PAD(0x520, 0x1D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__GPIO3_13 IOMUX_PAD(0x520, 0x1D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS IOMUX_PAD(0x520, 0x1D0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK IOMUX_PAD(0x520, 0x1D0, 4, 0x76C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 IOMUX_PAD(0x524, 0x1D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__GPIO3_14 IOMUX_PAD(0x524, 0x1D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS IOMUX_PAD(0x524, 0x1D4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK IOMUX_PAD(0x524, 0x1D4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 IOMUX_PAD(0x528, 0x1D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__GPIO3_15 IOMUX_PAD(0x528, 0x1D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1 IOMUX_PAD(0x528, 0x1D8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4 IOMUX_PAD(0x528, 0x1D8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B IOMUX_PAD(0x52C, 0x1DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WE_B__GPIO6_12 IOMUX_PAD(0x52C, 0x1DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B IOMUX_PAD(0x530, 0x1E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RE_B__GPIO6_13 IOMUX_PAD(0x530, 0x1E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT IOMUX_PAD(0x534, 0x1E4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__GPIO5_0 IOMUX_PAD(0x534, 0x1E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B IOMUX_PAD(0x534, 0x1E4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX3_P__GPIO6_22 IOMUX_PAD(__NA_, 0x1EC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 IOMUX_PAD(__NA_, 0x1EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX2_P__GPIO6_24 IOMUX_PAD(__NA_, 0x1F0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 IOMUX_PAD(__NA_, 0x1F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_CLK_P__GPIO6_26 IOMUX_PAD(__NA_, 0x1F4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK IOMUX_PAD(__NA_, 0x1F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX1_P__GPIO6_28 IOMUX_PAD(__NA_, 0x1F8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 IOMUX_PAD(__NA_, 0x1F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX0_P__GPIO6_30 IOMUX_PAD(__NA_, 0x1FC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 IOMUX_PAD(__NA_, 0x1FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX3_P__GPIO7_22 IOMUX_PAD(__NA_, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 IOMUX_PAD(__NA_, 0x200, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_CLK_P__GPIO7_24 IOMUX_PAD(__NA_, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK IOMUX_PAD(__NA_, 0x204, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX2_P__GPIO7_26 IOMUX_PAD(__NA_, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 IOMUX_PAD(__NA_, 0x208, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX1_P__GPIO7_28 IOMUX_PAD(__NA_, 0x20C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 IOMUX_PAD(__NA_, 0x20C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX0_P__GPIO7_30 IOMUX_PAD(__NA_, 0x210, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 IOMUX_PAD(__NA_, 0x210, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_10__GPIO4_0 IOMUX_PAD(0x540, 0x214, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_10__OSC32k_32K_OUT IOMUX_PAD(0x540, 0x214, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_11__GPIO4_1 IOMUX_PAD(0x544, 0x218, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_12__GPIO4_2 IOMUX_PAD(0x548, 0x21C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_13__GPIO4_3 IOMUX_PAD(0x54C, 0x220, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_14__GPIO4_4 IOMUX_PAD(0x550, 0x224, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE IOMUX_PAD(0x5A0, 0x228, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__GPIO6_7 IOMUX_PAD(0x5A0, 0x228, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 IOMUX_PAD(0x5A0, 0x228, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE IOMUX_PAD(0x5A4, 0x22C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__GPIO6_8 IOMUX_PAD(0x5A4, 0x22C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 IOMUX_PAD(0x5A4, 0x22C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B IOMUX_PAD(0x5A8, 0x230, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__GPIO6_9 IOMUX_PAD(0x5A8, 0x230, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 IOMUX_PAD(0x5A8, 0x230, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 IOMUX_PAD(0x5AC, 0x234, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__GPIO6_10 IOMUX_PAD(0x5AC, 0x234, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 IOMUX_PAD(0x5AC, 0x234, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 IOMUX_PAD(0x5B0, 0x238, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__GPIO6_11 IOMUX_PAD(0x5B0, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 IOMUX_PAD(0x5B0, 0x238, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 IOMUX_PAD(0x5B4, 0x23C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__GPIO6_14 IOMUX_PAD(0x5B4, 0x23C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__MLB_MLBCLK IOMUX_PAD(0x5B4, 0x23C, 6, 0x858, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 IOMUX_PAD(0x5B4, 0x23C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 IOMUX_PAD(0x5B8, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__GPIO6_15 IOMUX_PAD(0x5B8, 0x240, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__IPU_SISG_0 IOMUX_PAD(0x5B8, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__ESAI1_TX0 IOMUX_PAD(0x5B8, 0x240, 3, 0x7E4, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE IOMUX_PAD(0x5B8, 0x240, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK IOMUX_PAD(0x5B8, 0x240, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__MLB_MLBSIG IOMUX_PAD(0x5B8, 0x240, 6, 0x860, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 IOMUX_PAD(0x5B8, 0x240, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 IOMUX_PAD(0x5BC, 0x244, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__GPIO6_16 IOMUX_PAD(0x5BC, 0x244, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__IPU_SISG_1 IOMUX_PAD(0x5BC, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__ESAI1_TX1 IOMUX_PAD(0x5BC, 0x244, 3, 0x7E8, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 IOMUX_PAD(0x5BC, 0x244, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__MLB_MLBDAT IOMUX_PAD(0x5BC, 0x244, 6, 0x85C, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 IOMUX_PAD(0x5BC, 0x244, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__FEC_MDIO IOMUX_PAD(0x5C4, 0x248, 0, 0x804, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__GPIO1_22 IOMUX_PAD(0x5C4, 0x248, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__ESAI1_SCKR IOMUX_PAD(0x5C4, 0x248, 2, 0x7DC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__FEC_COL IOMUX_PAD(0x5C4, 0x248, 3, 0x800, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 IOMUX_PAD(0x5C4, 0x248, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 IOMUX_PAD(0x5C4, 0x248, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 IOMUX_PAD(0x5C4, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK IOMUX_PAD(0x5C8, 0x24C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__GPIO1_23 IOMUX_PAD(0x5C8, 0x24C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR IOMUX_PAD(0x5C8, 0x24C, 2, 0x7CC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 IOMUX_PAD(0x5C8, 0x24C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 IOMUX_PAD(0x5C8, 0x24C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__FEC_RX_ER IOMUX_PAD(0x5CC, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__GPIO1_24 IOMUX_PAD(0x5CC, 0x250, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR IOMUX_PAD(0x5CC, 0x250, 2, 0x7D4, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK IOMUX_PAD(0x5CC, 0x250, 3, 0x808, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 IOMUX_PAD(0x5CC, 0x250, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV IOMUX_PAD(0x5D0, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__GPIO1_25 IOMUX_PAD(0x5D0, 0x254, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT IOMUX_PAD(0x5D0, 0x254, 2, 0x7E0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__FEC_RDATA_1 IOMUX_PAD(0x5D4, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__GPIO1_26 IOMUX_PAD(0x5D4, 0x258, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__ESAI1_FST IOMUX_PAD(0x5D4, 0x258, 2, 0x7D0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__MLB_MLBSIG IOMUX_PAD(0x5D4, 0x258, 3, 0x860, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 IOMUX_PAD(0x5D4, 0x258, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__FEC_RDATA_0 IOMUX_PAD(0x5D8, 0x25C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__GPIO1_27 IOMUX_PAD(0x5D8, 0x25C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__ESAI1_HCKT IOMUX_PAD(0x5D8, 0x25C, 2, 0x7D8, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT IOMUX_PAD(0x5D8, 0x25C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__FEC_TX_EN IOMUX_PAD(0x5DC, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__GPIO1_28 IOMUX_PAD(0x5DC, 0x260, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 IOMUX_PAD(0x5DC, 0x260, 2, 0x7F0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__FEC_TDATA_1 IOMUX_PAD(0x5E0, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__GPIO1_29 IOMUX_PAD(0x5E0, 0x264, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 IOMUX_PAD(0x5E0, 0x264, 2, 0x7EC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__MLB_MLBCLK IOMUX_PAD(0x5E0, 0x264, 3, 0x858, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK IOMUX_PAD(0x5E0, 0x264, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__FEC_TDATA_0 IOMUX_PAD(0x5E4, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__GPIO1_30 IOMUX_PAD(0x5E4, 0x268, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 IOMUX_PAD(0x5E4, 0x268, 2, 0x7F4, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 IOMUX_PAD(0x5E4, 0x268, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__FEC_MDC IOMUX_PAD(0x5E8, 0x26C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__GPIO1_31 IOMUX_PAD(0x5E8, 0x26C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 IOMUX_PAD(0x5E8, 0x26C, 2, 0x7F8, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__MLB_MLBDAT IOMUX_PAD(0x5E8, 0x26C, 3, 0x85C, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG IOMUX_PAD(0x5E8, 0x26C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 IOMUX_PAD(0x5E8, 0x26C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__PATA_DIOW IOMUX_PAD(0x5F0, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__GPIO6_17 IOMUX_PAD(0x5F0, 0x270, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX IOMUX_PAD(0x5F0, 0x270, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 IOMUX_PAD(0x5F0, 0x270, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__PATA_DMACK IOMUX_PAD(0x5F4, 0x274, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__GPIO6_18 IOMUX_PAD(0x5F4, 0x274, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX IOMUX_PAD(0x5F4, 0x274, 3, 0x878, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 IOMUX_PAD(0x5F4, 0x274, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__PATA_DMARQ IOMUX_PAD(0x5F8, 0x278, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__GPIO7_0 IOMUX_PAD(0x5F8, 0x278, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX IOMUX_PAD(0x5F8, 0x278, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 IOMUX_PAD(0x5F8, 0x278, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 IOMUX_PAD(0x5F8, 0x278, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN IOMUX_PAD(0x5FC, 0x27C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1 IOMUX_PAD(0x5FC, 0x27C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 IOMUX_PAD(0x5FC, 0x27C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 IOMUX_PAD(0x5FC, 0x27C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__PATA_INTRQ IOMUX_PAD(0x600, 0x280, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__GPIO7_2 IOMUX_PAD(0x600, 0x280, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__UART2_CTS IOMUX_PAD(0x600, 0x280, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN IOMUX_PAD(0x600, 0x280, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 IOMUX_PAD(0x600, 0x280, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 IOMUX_PAD(0x600, 0x280, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__PATA_DIOR IOMUX_PAD(0x604, 0x284, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__GPIO7_3 IOMUX_PAD(0x604, 0x284, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__UART2_RTS IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__CAN1_RXCAN IOMUX_PAD(0x604, 0x284, 4, 0x760, 1, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 IOMUX_PAD(0x604, 0x284, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B IOMUX_PAD(0x608, 0x288, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__GPIO7_4 IOMUX_PAD(0x608, 0x288, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD IOMUX_PAD(0x608, 0x288, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__UART1_CTS IOMUX_PAD(0x608, 0x288, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN IOMUX_PAD(0x608, 0x288, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 IOMUX_PAD(0x608, 0x288, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__PATA_IORDY IOMUX_PAD(0x60C, 0x28C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__GPIO7_5 IOMUX_PAD(0x60C, 0x28C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__ESDHC3_CLK IOMUX_PAD(0x60C, 0x28C, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__UART1_RTS IOMUX_PAD(0x60C, 0x28C, 3, 0x874, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__CAN2_RXCAN IOMUX_PAD(0x60C, 0x28C, 4, 0x764, 1, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 IOMUX_PAD(0x60C, 0x28C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__PATA_DA_0 IOMUX_PAD(0x610, 0x290, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__GPIO7_6 IOMUX_PAD(0x610, 0x290, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__ESDHC3_RST IOMUX_PAD(0x610, 0x290, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__OWIRE_LINE IOMUX_PAD(0x610, 0x290, 4, 0x864, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 IOMUX_PAD(0x610, 0x290, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__PATA_DA_1 IOMUX_PAD(0x614, 0x294, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__GPIO7_7 IOMUX_PAD(0x614, 0x294, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__ESDHC4_CMD IOMUX_PAD(0x614, 0x294, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__UART3_CTS IOMUX_PAD(0x614, 0x294, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 IOMUX_PAD(0x614, 0x294, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__PATA_DA_2 IOMUX_PAD(0x618, 0x298, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__GPIO7_8 IOMUX_PAD(0x618, 0x298, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__ESDHC4_CLK IOMUX_PAD(0x618, 0x298, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__UART3_RTS IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 IOMUX_PAD(0x618, 0x298, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__PATA_CS_0 IOMUX_PAD(0x61C, 0x29C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__GPIO7_9 IOMUX_PAD(0x61C, 0x29C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX IOMUX_PAD(0x61C, 0x29C, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 IOMUX_PAD(0x61C, 0x29C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__PATA_CS_1 IOMUX_PAD(0x620, 0x2A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__GPIO7_10 IOMUX_PAD(0x620, 0x2A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 IOMUX_PAD(0x620, 0x2A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__PATA_DATA_0 IOMUX_PAD(0x628, 0x2A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__GPIO2_0 IOMUX_PAD(0x628, 0x2A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 IOMUX_PAD(0x628, 0x2A4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4 IOMUX_PAD(0x628, 0x2A4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 IOMUX_PAD(0x628, 0x2A4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 IOMUX_PAD(0x628, 0x2A4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 IOMUX_PAD(0x628, 0x2A4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__PATA_DATA_1 IOMUX_PAD(0x62C, 0x2A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__GPIO2_1 IOMUX_PAD(0x62C, 0x2A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 IOMUX_PAD(0x62C, 0x2A8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5 IOMUX_PAD(0x62C, 0x2A8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 IOMUX_PAD(0x62C, 0x2A8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 IOMUX_PAD(0x62C, 0x2A8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__PATA_DATA_2 IOMUX_PAD(0x630, 0x2AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__GPIO2_2 IOMUX_PAD(0x630, 0x2AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 IOMUX_PAD(0x630, 0x2AC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6 IOMUX_PAD(0x630, 0x2AC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 IOMUX_PAD(0x630, 0x2AC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 IOMUX_PAD(0x630, 0x2AC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__PATA_DATA_3 IOMUX_PAD(0x634, 0x2B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__GPIO2_3 IOMUX_PAD(0x634, 0x2B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 IOMUX_PAD(0x634, 0x2B0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7 IOMUX_PAD(0x634, 0x2B0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 IOMUX_PAD(0x634, 0x2B0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 IOMUX_PAD(0x634, 0x2B0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__PATA_DATA_4 IOMUX_PAD(0x638, 0x2B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__GPIO2_4 IOMUX_PAD(0x638, 0x2B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 IOMUX_PAD(0x638, 0x2B4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4 IOMUX_PAD(0x638, 0x2B4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 IOMUX_PAD(0x638, 0x2B4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 IOMUX_PAD(0x638, 0x2B4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__PATA_DATA_5 IOMUX_PAD(0x63C, 0x2B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__GPIO2_5 IOMUX_PAD(0x63C, 0x2B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 IOMUX_PAD(0x63C, 0x2B8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5 IOMUX_PAD(0x63C, 0x2B8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 IOMUX_PAD(0x63C, 0x2B8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 IOMUX_PAD(0x63C, 0x2B8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__PATA_DATA_6 IOMUX_PAD(0x640, 0x2BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__GPIO2_6 IOMUX_PAD(0x640, 0x2BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 IOMUX_PAD(0x640, 0x2BC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6 IOMUX_PAD(0x640, 0x2BC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 IOMUX_PAD(0x640, 0x2BC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 IOMUX_PAD(0x640, 0x2BC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__PATA_DATA_7 IOMUX_PAD(0x644, 0x2C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__GPIO2_7 IOMUX_PAD(0x644, 0x2C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 IOMUX_PAD(0x644, 0x2C0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7 IOMUX_PAD(0x644, 0x2C0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 IOMUX_PAD(0x644, 0x2C0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 IOMUX_PAD(0x644, 0x2C0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__PATA_DATA_8 IOMUX_PAD(0x648, 0x2C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__GPIO2_8 IOMUX_PAD(0x648, 0x2C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4 IOMUX_PAD(0x648, 0x2C4, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 IOMUX_PAD(0x648, 0x2C4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0 IOMUX_PAD(0x648, 0x2C4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 IOMUX_PAD(0x648, 0x2C4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 IOMUX_PAD(0x648, 0x2C4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__PATA_DATA_9 IOMUX_PAD(0x64C, 0x2C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__GPIO2_9 IOMUX_PAD(0x64C, 0x2C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5 IOMUX_PAD(0x64C, 0x2C8, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 IOMUX_PAD(0x64C, 0x2C8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1 IOMUX_PAD(0x64C, 0x2C8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 IOMUX_PAD(0x64C, 0x2C8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 IOMUX_PAD(0x64C, 0x2C8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__PATA_DATA_10 IOMUX_PAD(0x650, 0x2CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__GPIO2_10 IOMUX_PAD(0x650, 0x2CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6 IOMUX_PAD(0x650, 0x2CC, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 IOMUX_PAD(0x650, 0x2CC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2 IOMUX_PAD(0x650, 0x2CC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 IOMUX_PAD(0x650, 0x2CC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 IOMUX_PAD(0x650, 0x2CC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__PATA_DATA_11 IOMUX_PAD(0x654, 0x2D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__GPIO2_11 IOMUX_PAD(0x654, 0x2D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7 IOMUX_PAD(0x654, 0x2D0, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 IOMUX_PAD(0x654, 0x2D0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3 IOMUX_PAD(0x654, 0x2D0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 IOMUX_PAD(0x654, 0x2D0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 IOMUX_PAD(0x654, 0x2D0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__PATA_DATA_12 IOMUX_PAD(0x658, 0x2D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__GPIO2_12 IOMUX_PAD(0x658, 0x2D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4 IOMUX_PAD(0x658, 0x2D4, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 IOMUX_PAD(0x658, 0x2D4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0 IOMUX_PAD(0x658, 0x2D4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 IOMUX_PAD(0x658, 0x2D4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 IOMUX_PAD(0x658, 0x2D4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__PATA_DATA_13 IOMUX_PAD(0x65C, 0x2D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__GPIO2_13 IOMUX_PAD(0x65C, 0x2D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5 IOMUX_PAD(0x65C, 0x2D8, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 IOMUX_PAD(0x65C, 0x2D8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1 IOMUX_PAD(0x65C, 0x2D8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 IOMUX_PAD(0x65C, 0x2D8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 IOMUX_PAD(0x65C, 0x2D8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__PATA_DATA_14 IOMUX_PAD(0x660, 0x2DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__GPIO2_14 IOMUX_PAD(0x660, 0x2DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6 IOMUX_PAD(0x660, 0x2DC, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 IOMUX_PAD(0x660, 0x2DC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2 IOMUX_PAD(0x660, 0x2DC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 IOMUX_PAD(0x660, 0x2DC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 IOMUX_PAD(0x660, 0x2DC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__PATA_DATA_15 IOMUX_PAD(0x664, 0x2E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__GPIO2_15 IOMUX_PAD(0x664, 0x2E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7 IOMUX_PAD(0x664, 0x2E0, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 IOMUX_PAD(0x664, 0x2E0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3 IOMUX_PAD(0x664, 0x2E0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 IOMUX_PAD(0x664, 0x2E0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 IOMUX_PAD(0x664, 0x2E0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0 IOMUX_PAD(0x66C, 0x2E4, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__GPIO1_16 IOMUX_PAD(0x66C, 0x2E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__GPT_CAPIN1 IOMUX_PAD(0x66C, 0x2E4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__CSPI_MISO IOMUX_PAD(0x66C, 0x2E4, 5, 0x784, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP IOMUX_PAD(0x66C, 0x2E4, 7, 0x778, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1 IOMUX_PAD(0x670, 0x2E8, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__GPIO1_17 IOMUX_PAD(0x670, 0x2E8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__GPT_CAPIN2 IOMUX_PAD(0x670, 0x2E8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__CSPI_SS0 IOMUX_PAD(0x670, 0x2E8, 5, 0x78C, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP IOMUX_PAD(0x670, 0x2E8, 7, 0x77C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__ESDHC1_CMD IOMUX_PAD(0x674, 0x2EC, 0 | IOMUX_CONFIG_SION, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__GPIO1_18 IOMUX_PAD(0x674, 0x2EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__GPT_CMPOUT1 IOMUX_PAD(0x674, 0x2EC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__CSPI_MOSI IOMUX_PAD(0x674, 0x2EC, 5, 0x788, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP IOMUX_PAD(0x674, 0x2EC, 7, 0x770, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2 IOMUX_PAD(0x678, 0x2F0, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__GPIO1_19 IOMUX_PAD(0x678, 0x2F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2 IOMUX_PAD(0x678, 0x2F0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__PWM2_PWMO IOMUX_PAD(0x678, 0x2F0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B IOMUX_PAD(0x678, 0x2F0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__CSPI_SS1 IOMUX_PAD(0x678, 0x2F0, 5, 0x790, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB IOMUX_PAD(0x678, 0x2F0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP IOMUX_PAD(0x678, 0x2F0, 7, 0x774, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__ESDHC1_CLK IOMUX_PAD(0x67C, 0x2F4, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__GPIO1_20 IOMUX_PAD(0x67C, 0x2F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT IOMUX_PAD(0x67C, 0x2F4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__GPT_CLKIN IOMUX_PAD(0x67C, 0x2F4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__CSPI_SCLK IOMUX_PAD(0x67C, 0x2F4, 5, 0x780, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 IOMUX_PAD(0x67C, 0x2F4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3 IOMUX_PAD(0x680, 0x2F8, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__GPIO1_21 IOMUX_PAD(0x680, 0x2F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3 IOMUX_PAD(0x680, 0x2F8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__PWM1_PWMO IOMUX_PAD(0x680, 0x2F8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B IOMUX_PAD(0x680, 0x2F8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__CSPI_SS2 IOMUX_PAD(0x680, 0x2F8, 5, 0x794, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB IOMUX_PAD(0x680, 0x2F8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 IOMUX_PAD(0x680, 0x2F8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__ESDHC2_CLK IOMUX_PAD(0x688, 0x2FC, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__GPIO1_10 IOMUX_PAD(0x688, 0x2FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__KPP_COL_5 IOMUX_PAD(0x688, 0x2FC, 2, 0x840, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS IOMUX_PAD(0x688, 0x2FC, 3, 0x73C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__CSPI_SCLK IOMUX_PAD(0x688, 0x2FC, 5, 0x780, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__SCC_RANDOM_V IOMUX_PAD(0x688, 0x2FC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__ESDHC2_CMD IOMUX_PAD(0x68C, 0x300, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__GPIO1_11 IOMUX_PAD(0x68C, 0x300, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__KPP_ROW_5 IOMUX_PAD(0x68C, 0x300, 2, 0x84C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC IOMUX_PAD(0x68C, 0x300, 3, 0x738, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__CSPI_MOSI IOMUX_PAD(0x68C, 0x300, 5, 0x788, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__SCC_RANDOM IOMUX_PAD(0x68C, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3 IOMUX_PAD(0x690, 0x304, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__GPIO1_12 IOMUX_PAD(0x690, 0x304, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__KPP_COL_6 IOMUX_PAD(0x690, 0x304, 2, 0x844, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC IOMUX_PAD(0x690, 0x304, 3, 0x740, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__CSPI_SS2 IOMUX_PAD(0x690, 0x304, 5, 0x794, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__SJC_DONE IOMUX_PAD(0x690, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2 IOMUX_PAD(0x694, 0x308, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__GPIO1_13 IOMUX_PAD(0x694, 0x308, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__KPP_ROW_6 IOMUX_PAD(0x694, 0x308, 2, 0x850, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD IOMUX_PAD(0x694, 0x308, 3, 0x734, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__CSPI_SS1 IOMUX_PAD(0x694, 0x308, 5, 0x790, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__SJC_FAIL IOMUX_PAD(0x694, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1 IOMUX_PAD(0x698, 0x30C, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__GPIO1_14 IOMUX_PAD(0x698, 0x30C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__KPP_COL_7 IOMUX_PAD(0x698, 0x30C, 2, 0x848, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS IOMUX_PAD(0x698, 0x30C, 3, 0x744, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__CSPI_SS0 IOMUX_PAD(0x698, 0x30C, 5, 0x78C, 4, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO IOMUX_PAD(0x698, 0x30C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0 IOMUX_PAD(0x69C, 0x310, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__GPIO1_15 IOMUX_PAD(0x69C, 0x310, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__KPP_ROW_7 IOMUX_PAD(0x69C, 0x310, 2, 0x854, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD IOMUX_PAD(0x69C, 0x310, 3, 0x730, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__CSPI_MISO IOMUX_PAD(0x69C, 0x310, 5, 0x784, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT IOMUX_PAD(0x69C, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CCM_CLKO IOMUX_PAD(0x6A4, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__GPIO1_0 IOMUX_PAD(0x6A4, 0x314, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__KPP_COL_5 IOMUX_PAD(0x6A4, 0x314, 2, 0x840, 3, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK IOMUX_PAD(0x6A4, 0x314, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__EPIT1_EPITO IOMUX_PAD(0x6A4, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB IOMUX_PAD(0x6A4, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR IOMUX_PAD(0x6A4, 0x314, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CSU_TD IOMUX_PAD(0x6A4, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__ESAI1_SCKR IOMUX_PAD(0x6A8, 0x318, 0, 0x7DC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__GPIO1_1 IOMUX_PAD(0x6A8, 0x318, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__KPP_ROW_5 IOMUX_PAD(0x6A8, 0x318, 2, 0x84C, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK IOMUX_PAD(0x6A8, 0x318, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__PWM2_PWMO IOMUX_PAD(0x6A8, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__WDOG2_WDOG_B IOMUX_PAD(0x6A8, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__ESDHC1_CD IOMUX_PAD(0x6A8, 0x318, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__SRC_TESTER_ACK IOMUX_PAD(0x6A8, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__ESAI1_FSR IOMUX_PAD(0x6AC, 0x31C, 0, 0x7CC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__GPIO1_9 IOMUX_PAD(0x6AC, 0x31C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__KPP_COL_6 IOMUX_PAD(0x6AC, 0x31C, 2, 0x844, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__CCM_REF_EN_B IOMUX_PAD(0x6AC, 0x31C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__PWM1_PWMO IOMUX_PAD(0x6AC, 0x31C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__WDOG1_WDOG_B IOMUX_PAD(0x6AC, 0x31C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__ESDHC1_WP IOMUX_PAD(0x6AC, 0x31C, 6, 0x7FC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__SCC_FAIL_STATE IOMUX_PAD(0x6AC, 0x31C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__ESAI1_HCKR IOMUX_PAD(0x6B0, 0x320, 0, 0x7D4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__GPIO1_3 IOMUX_PAD(0x6B0, 0x320, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__I2C3_SCL IOMUX_PAD(0x6B0, 0x320, 2 | IOMUX_CONFIG_SION, 0x824, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN IOMUX_PAD(0x6B0, 0x320, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__CCM_CLKO2 IOMUX_PAD(0x6B0, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 IOMUX_PAD(0x6B0, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC IOMUX_PAD(0x6B0, 0x320, 6, 0x8A0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__MLB_MLBCLK IOMUX_PAD(0x6B0, 0x320, 7, 0x858, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__ESAI1_SCKT IOMUX_PAD(0x6B4, 0x324, 0, 0x7E0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__GPIO1_6 IOMUX_PAD(0x6B4, 0x324, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__I2C3_SDA IOMUX_PAD(0x6B4, 0x324, 2 | IOMUX_CONFIG_SION, 0x828, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0 IOMUX_PAD(0x6B4, 0x324, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB IOMUX_PAD(0x6B4, 0x324, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 IOMUX_PAD(0x6B4, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__ESDHC2_LCTL IOMUX_PAD(0x6B4, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__MLB_MLBSIG IOMUX_PAD(0x6B4, 0x324, 7, 0x860, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__ESAI1_FST IOMUX_PAD(0x6B8, 0x328, 0, 0x7D0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__GPIO1_2 IOMUX_PAD(0x6B8, 0x328, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__KPP_ROW_6 IOMUX_PAD(0x6B8, 0x328, 2, 0x850, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1 IOMUX_PAD(0x6B8, 0x328, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 IOMUX_PAD(0x6B8, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 IOMUX_PAD(0x6B8, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__ESDHC2_WP IOMUX_PAD(0x6B8, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__MLB_MLBDAT IOMUX_PAD(0x6B8, 0x328, 7, 0x85C, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__ESAI1_HCKT IOMUX_PAD(0x6BC, 0x32C, 0, 0x7D8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__GPIO1_4 IOMUX_PAD(0x6BC, 0x32C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__KPP_COL_7 IOMUX_PAD(0x6BC, 0x32C, 2, 0x848, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2 IOMUX_PAD(0x6BC, 0x32C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 IOMUX_PAD(0x6BC, 0x32C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 IOMUX_PAD(0x6BC, 0x32C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__ESDHC2_CD IOMUX_PAD(0x6BC, 0x32C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__SCC_SEC_STATE IOMUX_PAD(0x6BC, 0x32C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3 IOMUX_PAD(0x6C0, 0x330, 0, 0x7EC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__GPIO1_5 IOMUX_PAD(0x6C0, 0x330, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__KPP_ROW_7 IOMUX_PAD(0x6C0, 0x330, 2, 0x854, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CCM_CLKO IOMUX_PAD(0x6C0, 0x330, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 IOMUX_PAD(0x6C0, 0x330, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 IOMUX_PAD(0x6C0, 0x330, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__I2C3_SCL IOMUX_PAD(0x6C0, 0x330, 6 | IOMUX_CONFIG_SION, 0x824, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CCM_PLL1_BYP IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1 IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__GPIO1_7 IOMUX_PAD(0x6C4, 0x334, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__EPIT1_EPITO IOMUX_PAD(0x6C4, 0x334, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__CAN1_TXCAN IOMUX_PAD(0x6C4, 0x334, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__UART2_TXD_MUX IOMUX_PAD(0x6C4, 0x334, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_GPIO_7__FIRI_RXD IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__SPDIF_PLOCK IOMUX_PAD(0x6C4, 0x334, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__CCM_PLL2_BYP IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0 IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__GPIO1_8 IOMUX_PAD(0x6C8, 0x338, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__EPIT2_EPITO IOMUX_PAD(0x6C8, 0x338, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__CAN1_RXCAN IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 3, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__UART2_RXD_MUX IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, MX53_UART_PAD_CTRL)
+#define MX53_PAD_GPIO_8__FIRI_TXD IOMUX_PAD(0x6C8, 0x338, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__SPDIF_SRCLK IOMUX_PAD(0x6C8, 0x338, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__CCM_PLL3_BYP IOMUX_PAD(0x6C8, 0x338, 7, 0x778, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2 IOMUX_PAD(0x6CC, 0x33C, 0, 0x7F0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__GPIO7_11 IOMUX_PAD(0x6CC, 0x33C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT IOMUX_PAD(0x6CC, 0x33C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 IOMUX_PAD(0x6CC, 0x33C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__SPDIF_IN1 IOMUX_PAD(0x6CC, 0x33C, 5, 0x870, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__I2C3_SDA IOMUX_PAD(0x6CC, 0x33C, 6 | IOMUX_CONFIG_SION, 0x828, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__SJC_DE_B IOMUX_PAD(0x6CC, 0x33C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__ESAI1_TX0 IOMUX_PAD(0x6D0, 0x340, 0, 0x7E4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__GPIO7_12 IOMUX_PAD(0x6D0, 0x340, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 IOMUX_PAD(0x6D0, 0x340, 2, 0x868, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__GPC_PMIC_RDY IOMUX_PAD(0x6D0, 0x340, 3, 0x810, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG IOMUX_PAD(0x6D0, 0x340, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SPDIF_OUT1 IOMUX_PAD(0x6D0, 0x340, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__IPU_SNOOP2 IOMUX_PAD(0x6D0, 0x340, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SJC_JTAG_ACT IOMUX_PAD(0x6D0, 0x340, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__ESAI1_TX1 IOMUX_PAD(0x6D4, 0x344, 0, 0x7E8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__GPIO7_13 IOMUX_PAD(0x6D4, 0x344, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 IOMUX_PAD(0x6D4, 0x344, 2, 0x86C, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__OWIRE_LINE IOMUX_PAD(0x6D4, 0x344, 3, 0x864, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG IOMUX_PAD(0x6D4, 0x344, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK IOMUX_PAD(0x6D4, 0x344, 5, 0x768, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__ESDHC1_LCTL IOMUX_PAD(0x6D4, 0x344, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST IOMUX_PAD(0x6D4, 0x344, 7, __NA_, 0, NO_PAD_CTRL)
#endif /* __MACH_IOMUX_MX53_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h
index ebbce33097a7..2fa3b5430102 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h
@@ -80,6 +80,7 @@ typedef u64 iomux_v3_cfg_t;
((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT))
+#define NEW_PAD_CTRL(cfg, pad) (((cfg) & ~MUX_PAD_CTRL_MASK) | MUX_PAD_CTRL(pad))
/*
* Use to set PAD control
*/
@@ -89,11 +90,11 @@ typedef u64 iomux_v3_cfg_t;
#define PAD_CTL_HYS (1 << 8)
#define PAD_CTL_PKE (1 << 7)
-#define PAD_CTL_PUE (1 << 6)
-#define PAD_CTL_PUS_100K_DOWN (0 << 4)
-#define PAD_CTL_PUS_47K_UP (1 << 4)
-#define PAD_CTL_PUS_100K_UP (2 << 4)
-#define PAD_CTL_PUS_22K_UP (3 << 4)
+#define PAD_CTL_PUE (1 << 6 | PAD_CTL_PKE)
+#define PAD_CTL_PUS_100K_DOWN (0 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_47K_UP (1 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_100K_UP (2 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_22K_UP (3 << 4 | PAD_CTL_PUE)
#define PAD_CTL_ODE (1 << 3)
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index 00e812bbd81d..fd9efb044656 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -14,9 +14,15 @@
#include <asm-generic/gpio.h>
/*
- * SoCs with TZIC interrupt controller have 128 IRQs, those with AVIC have 64
+ * SoCs with GIC interrupt controller have 160 IRQs, those with TZIC
+ * have 128 IRQs, and those with AVIC have 64.
+ *
+ * To support single image, the biggest number should be defined on
+ * top of the list.
*/
-#ifdef CONFIG_MXC_TZIC
+#if defined CONFIG_ARM_GIC
+#define MXC_INTERNAL_IRQS 160
+#elif defined CONFIG_MXC_TZIC
#define MXC_INTERNAL_IRQS 128
#else
#define MXC_INTERNAL_IRQS 64
diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h
deleted file mode 100644
index 11be5cdbdd1a..000000000000
--- a/arch/arm/plat-mxc/include/mach/memory.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_MXC_MEMORY_H__
-#define __ASM_ARCH_MXC_MEMORY_H__
-
-#define MX1_PHYS_OFFSET UL(0x08000000)
-#define MX21_PHYS_OFFSET UL(0xc0000000)
-#define MX25_PHYS_OFFSET UL(0x80000000)
-#define MX27_PHYS_OFFSET UL(0xa0000000)
-#define MX3x_PHYS_OFFSET UL(0x80000000)
-#define MX50_PHYS_OFFSET UL(0x70000000)
-#define MX51_PHYS_OFFSET UL(0x90000000)
-#define MX53_PHYS_OFFSET UL(0x70000000)
-
-#if !defined(CONFIG_RUNTIME_PHYS_OFFSET)
-# if defined CONFIG_ARCH_MX1
-# define PLAT_PHYS_OFFSET MX1_PHYS_OFFSET
-# elif defined CONFIG_MACH_MX21
-# define PLAT_PHYS_OFFSET MX21_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX25
-# define PLAT_PHYS_OFFSET MX25_PHYS_OFFSET
-# elif defined CONFIG_MACH_MX27
-# define PLAT_PHYS_OFFSET MX27_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX3
-# define PLAT_PHYS_OFFSET MX3x_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX50
-# define PLAT_PHYS_OFFSET MX50_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX51
-# define PLAT_PHYS_OFFSET MX51_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX53
-# define PLAT_PHYS_OFFSET MX53_PHYS_OFFSET
-# endif
-#endif
-
-#if defined(CONFIG_MX3_VIDEO)
-/*
- * Increase size of DMA-consistent memory region.
- * This is required for mx3 camera driver to capture at least two QXGA frames.
- */
-#define CONSISTENT_DMA_SIZE SZ_8M
-
-#elif defined(CONFIG_MX1_VIDEO) || defined(CONFIG_VIDEO_MX2_HOSTSUPPORT)
-/*
- * Increase size of DMA-consistent memory region.
- * This is required for i.MX camera driver to capture at least four VGA frames.
- */
-#define CONSISTENT_DMA_SIZE SZ_4M
-#endif /* CONFIG_MX1_VIDEO || CONFIG_VIDEO_MX2_HOSTSUPPORT */
-
-#endif /* __ASM_ARCH_MXC_MEMORY_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h
index 087cd7ac8d52..ccebf5ba12f0 100644
--- a/arch/arm/plat-mxc/include/mach/mx25.h
+++ b/arch/arm/plat-mxc/include/mach/mx25.h
@@ -41,6 +41,7 @@
#define MX25_SSI2_BASE_ADDR 0x50014000
#define MX25_SSI1_BASE_ADDR 0x50034000
#define MX25_NFC_BASE_ADDR 0xbb000000
+#define MX25_IIM_BASE_ADDR 0x53ff0000
#define MX25_DRYICE_BASE_ADDR 0x53ffc000
#define MX25_ESDHC1_BASE_ADDR 0x53fb4000
#define MX25_ESDHC2_BASE_ADDR 0x53fb8000
@@ -104,4 +105,8 @@
#define MX25_DMA_REQ_SSI1_RX0 28
#define MX25_DMA_REQ_SSI1_TX0 29
+#ifndef __ASSEMBLY__
+extern int mx25_revision(void);
+#endif
+
#endif /* ifndef __MACH_MX25_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h
index 1dc1c522601b..6265357284d7 100644
--- a/arch/arm/plat-mxc/include/mach/mx27.h
+++ b/arch/arm/plat-mxc/include/mach/mx27.h
@@ -24,10 +24,6 @@
#ifndef __MACH_MX27_H__
#define __MACH_MX27_H__
-#ifndef __ASSEMBLER__
-#include <linux/io.h>
-#endif
-
#define MX27_AIPI_BASE_ADDR 0x10000000
#define MX27_AIPI_SIZE SZ_1M
#define MX27_DMA_BASE_ADDR (MX27_AIPI_BASE_ADDR + 0x01000)
@@ -131,16 +127,6 @@
#define MX27_IO_P2V(x) IMX_IO_P2V(x)
#define MX27_IO_ADDRESS(x) IOMEM(MX27_IO_P2V(x))
-#ifndef __ASSEMBLER__
-static inline void mx27_setup_weimcs(size_t cs,
- unsigned upper, unsigned lower, unsigned addional)
-{
- __raw_writel(upper, MX27_IO_ADDRESS(MX27_WEIM_CSCRxU(cs)));
- __raw_writel(lower, MX27_IO_ADDRESS(MX27_WEIM_CSCRxL(cs)));
- __raw_writel(addional, MX27_IO_ADDRESS(MX27_WEIM_CSCRxA(cs)));
-}
-#endif
-
/* fixed interrupt numbers */
#define MX27_INT_I2C2 1
#define MX27_INT_GPT6 2
diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h
index 79e7fc01bb59..e27619e442c0 100644
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ b/arch/arm/plat-mxc/include/mach/mx31.h
@@ -1,10 +1,6 @@
#ifndef __MACH_MX31_H__
#define __MACH_MX31_H__
-#ifndef __ASSEMBLER__
-#include <linux/io.h>
-#endif
-
/*
* IRAM
*/
@@ -122,16 +118,6 @@
#define MX31_IO_P2V(x) IMX_IO_P2V(x)
#define MX31_IO_ADDRESS(x) IOMEM(MX31_IO_P2V(x))
-#ifndef __ASSEMBLER__
-static inline void mx31_setup_weimcs(size_t cs,
- unsigned upper, unsigned lower, unsigned addional)
-{
- __raw_writel(upper, MX31_IO_ADDRESS(MX31_WEIM_CSCRxU(cs)));
- __raw_writel(lower, MX31_IO_ADDRESS(MX31_WEIM_CSCRxL(cs)));
- __raw_writel(addional, MX31_IO_ADDRESS(MX31_WEIM_CSCRxA(cs)));
-}
-#endif
-
#define MX31_INT_I2C3 3
#define MX31_INT_I2C2 4
#define MX31_INT_MPEG4_ENCODER 5
diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h
index d13dbfeef08a..80965a99aa55 100644
--- a/arch/arm/plat-mxc/include/mach/mx35.h
+++ b/arch/arm/plat-mxc/include/mach/mx35.h
@@ -36,7 +36,7 @@
#define MX35_UART3_BASE_ADDR (MX35_SPBA0_BASE_ADDR + 0x0c000)
#define MX35_CSPI2_BASE_ADDR (MX35_SPBA0_BASE_ADDR + 0x10000)
#define MX35_SSI2_BASE_ADDR (MX35_SPBA0_BASE_ADDR + 0x14000)
-#define MX35_ATA_DMA_BASE_ADDR (MX35_SPBA0_BASE_ADDR + 0x20000)
+#define MX35_ATA_BASE_ADDR (MX35_SPBA0_BASE_ADDR + 0x20000)
#define MX35_MSHC1_BASE_ADDR (MX35_SPBA0_BASE_ADDR + 0x24000)
#define MX35_FEC_BASE_ADDR 0x50038000
#define MX35_SPBA_CTRL_BASE_ADDR (MX35_SPBA0_BASE_ADDR + 0x3c000)
diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h
index 388a407d72d6..30dbf424583e 100644
--- a/arch/arm/plat-mxc/include/mach/mx3x.h
+++ b/arch/arm/plat-mxc/include/mach/mx3x.h
@@ -187,22 +187,8 @@
/* Mandatory defines used globally */
#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-
-extern unsigned int mx31_cpu_rev;
-extern void mx31_read_cpu_rev(void);
-
-static inline int mx31_revision(void)
-{
- return mx31_cpu_rev;
-}
-
-extern unsigned int mx35_cpu_rev;
-extern void mx35_read_cpu_rev(void);
-
-static inline int mx35_revision(void)
-{
- return mx35_cpu_rev;
-}
+extern int mx35_revision(void);
+extern int mx31_revision(void);
#endif
#endif /* ifndef __MACH_MX3x_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx51.h b/arch/arm/plat-mxc/include/mach/mx51.h
index dede19a766ff..cdf07c65ec1e 100644
--- a/arch/arm/plat-mxc/include/mach/mx51.h
+++ b/arch/arm/plat-mxc/include/mach/mx51.h
@@ -18,18 +18,6 @@
#define MX51_GPU_CTRL_BASE_ADDR 0x30000000
#define MX51_IPU_CTRL_BASE_ADDR 0x40000000
-#define MX51_DEBUG_BASE_ADDR 0x60000000
-#define MX51_DEBUG_SIZE SZ_1M
-
-#define MX51_ETB_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x01000)
-#define MX51_ETM_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x02000)
-#define MX51_TPIU_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x03000)
-#define MX51_CTI0_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x04000)
-#define MX51_CTI1_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x05000)
-#define MX51_CTI2_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x06000)
-#define MX51_CTI3_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x07000)
-#define MX51_CORTEX_DBG_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x08000)
-
/*
* SPBA global module enabled #0
*/
@@ -55,7 +43,10 @@
#define MX51_AIPS1_BASE_ADDR 0x73f00000
#define MX51_AIPS1_SIZE SZ_1M
-#define MX51_OTG_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_USB_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_USB_OTG_BASE_ADDR (MX51_USB_BASE_ADDR + 0x0000)
+#define MX51_USB_HS1_BASE_ADDR (MX51_USB_BASE_ADDR + 0x0200)
+#define MX51_USB_HS2_BASE_ADDR (MX51_USB_BASE_ADDR + 0x0400)
#define MX51_GPIO1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x84000)
#define MX51_GPIO2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x88000)
#define MX51_GPIO3_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x8c000)
@@ -132,6 +123,7 @@
#define MX51_GPU2D_BASE_ADDR 0xd0000000
#define MX51_TZIC_BASE_ADDR 0xe0000000
+#define MX51_TZIC_SIZE SZ_16K
#define MX51_IO_P2V(x) IMX_IO_P2V(x)
#define MX51_IO_ADDRESS(x) IOMEM(MX51_IO_P2V(x))
@@ -240,117 +232,114 @@
/*
* Interrupt numbers
*/
-#define MX51_MXC_INT_BASE 0
-#define MX51_MXC_INT_RESV0 0
+#define MX51_INT_BASE 0
+#define MX51_INT_RESV0 0
#define MX51_INT_ESDHC1 1
#define MX51_INT_ESDHC2 2
#define MX51_INT_ESDHC3 3
#define MX51_INT_ESDHC4 4
-#define MX51_MXC_INT_RESV5 5
+#define MX51_INT_RESV5 5
#define MX51_INT_SDMA 6
-#define MX51_MXC_INT_IOMUX 7
+#define MX51_INT_IOMUX 7
#define MX51_INT_NFC 8
-#define MX51_MXC_INT_VPU 9
+#define MX51_INT_VPU 9
#define MX51_INT_IPU_ERR 10
#define MX51_INT_IPU_SYN 11
-#define MX51_MXC_INT_GPU 12
-#define MX51_MXC_INT_RESV13 13
-#define MX51_MXC_INT_USB_H1 14
-#define MX51_MXC_INT_EMI 15
-#define MX51_MXC_INT_USB_H2 16
-#define MX51_MXC_INT_USB_H3 17
-#define MX51_MXC_INT_USB_OTG 18
-#define MX51_MXC_INT_SAHARA_H0 19
-#define MX51_MXC_INT_SAHARA_H1 20
-#define MX51_MXC_INT_SCC_SMN 21
-#define MX51_MXC_INT_SCC_STZ 22
-#define MX51_MXC_INT_SCC_SCM 23
-#define MX51_MXC_INT_SRTC_NTZ 24
-#define MX51_MXC_INT_SRTC_TZ 25
-#define MX51_MXC_INT_RTIC 26
-#define MX51_MXC_INT_CSU 27
-#define MX51_MXC_INT_SLIM_B 28
+#define MX51_INT_GPU 12
+#define MX51_INT_RESV13 13
+#define MX51_INT_USB_HS1 14
+#define MX51_INT_EMI 15
+#define MX51_INT_USB_HS2 16
+#define MX51_INT_USB_HS3 17
+#define MX51_INT_USB_OTG 18
+#define MX51_INT_SAHARA_H0 19
+#define MX51_INT_SAHARA_H1 20
+#define MX51_INT_SCC_SMN 21
+#define MX51_INT_SCC_STZ 22
+#define MX51_INT_SCC_SCM 23
+#define MX51_INT_SRTC_NTZ 24
+#define MX51_INT_SRTC_TZ 25
+#define MX51_INT_RTIC 26
+#define MX51_INT_CSU 27
+#define MX51_INT_SLIM_B 28
#define MX51_INT_SSI1 29
#define MX51_INT_SSI2 30
#define MX51_INT_UART1 31
#define MX51_INT_UART2 32
#define MX51_INT_UART3 33
-#define MX51_MXC_INT_RESV34 34
-#define MX51_MXC_INT_RESV35 35
+#define MX51_INT_RESV34 34
+#define MX51_INT_RESV35 35
#define MX51_INT_ECSPI1 36
#define MX51_INT_ECSPI2 37
#define MX51_INT_CSPI 38
-#define MX51_MXC_INT_GPT 39
-#define MX51_MXC_INT_EPIT1 40
-#define MX51_MXC_INT_EPIT2 41
-#define MX51_MXC_INT_GPIO1_INT7 42
-#define MX51_MXC_INT_GPIO1_INT6 43
-#define MX51_MXC_INT_GPIO1_INT5 44
-#define MX51_MXC_INT_GPIO1_INT4 45
-#define MX51_MXC_INT_GPIO1_INT3 46
-#define MX51_MXC_INT_GPIO1_INT2 47
-#define MX51_MXC_INT_GPIO1_INT1 48
-#define MX51_MXC_INT_GPIO1_INT0 49
-#define MX51_MXC_INT_GPIO1_LOW 50
-#define MX51_MXC_INT_GPIO1_HIGH 51
-#define MX51_MXC_INT_GPIO2_LOW 52
-#define MX51_MXC_INT_GPIO2_HIGH 53
-#define MX51_MXC_INT_GPIO3_LOW 54
-#define MX51_MXC_INT_GPIO3_HIGH 55
-#define MX51_MXC_INT_GPIO4_LOW 56
-#define MX51_MXC_INT_GPIO4_HIGH 57
-#define MX51_MXC_INT_WDOG1 58
-#define MX51_MXC_INT_WDOG2 59
+#define MX51_INT_GPT 39
+#define MX51_INT_EPIT1 40
+#define MX51_INT_EPIT2 41
+#define MX51_INT_GPIO1_INT7 42
+#define MX51_INT_GPIO1_INT6 43
+#define MX51_INT_GPIO1_INT5 44
+#define MX51_INT_GPIO1_INT4 45
+#define MX51_INT_GPIO1_INT3 46
+#define MX51_INT_GPIO1_INT2 47
+#define MX51_INT_GPIO1_INT1 48
+#define MX51_INT_GPIO1_INT0 49
+#define MX51_INT_GPIO1_LOW 50
+#define MX51_INT_GPIO1_HIGH 51
+#define MX51_INT_GPIO2_LOW 52
+#define MX51_INT_GPIO2_HIGH 53
+#define MX51_INT_GPIO3_LOW 54
+#define MX51_INT_GPIO3_HIGH 55
+#define MX51_INT_GPIO4_LOW 56
+#define MX51_INT_GPIO4_HIGH 57
+#define MX51_INT_WDOG1 58
+#define MX51_INT_WDOG2 59
#define MX51_INT_KPP 60
#define MX51_INT_PWM1 61
#define MX51_INT_I2C1 62
#define MX51_INT_I2C2 63
-#define MX51_MXC_INT_HS_I2C 64
-#define MX51_MXC_INT_RESV65 65
-#define MX51_MXC_INT_RESV66 66
-#define MX51_MXC_INT_SIM_IPB 67
-#define MX51_MXC_INT_SIM_DAT 68
-#define MX51_MXC_INT_IIM 69
-#define MX51_MXC_INT_ATA 70
-#define MX51_MXC_INT_CCM1 71
-#define MX51_MXC_INT_CCM2 72
-#define MX51_MXC_INT_GPC1 73
-#define MX51_MXC_INT_GPC2 74
-#define MX51_MXC_INT_SRC 75
-#define MX51_MXC_INT_NM 76
-#define MX51_MXC_INT_PMU 77
-#define MX51_MXC_INT_CTI_IRQ 78
-#define MX51_MXC_INT_CTI1_TG0 79
-#define MX51_MXC_INT_CTI1_TG1 80
-#define MX51_MXC_INT_MCG_ERR 81
-#define MX51_MXC_INT_MCG_TMR 82
-#define MX51_MXC_INT_MCG_FUNC 83
-#define MX51_MXC_INT_GPU2_IRQ 84
-#define MX51_MXC_INT_GPU2_BUSY 85
-#define MX51_MXC_INT_RESV86 86
+#define MX51_INT_HS_I2C 64
+#define MX51_INT_RESV65 65
+#define MX51_INT_RESV66 66
+#define MX51_INT_SIM_IPB 67
+#define MX51_INT_SIM_DAT 68
+#define MX51_INT_IIM 69
+#define MX51_INT_ATA 70
+#define MX51_INT_CCM1 71
+#define MX51_INT_CCM2 72
+#define MX51_INT_GPC1 73
+#define MX51_INT_GPC2 74
+#define MX51_INT_SRC 75
+#define MX51_INT_NM 76
+#define MX51_INT_PMU 77
+#define MX51_INT_CTI_IRQ 78
+#define MX51_INT_CTI1_TG0 79
+#define MX51_INT_CTI1_TG1 80
+#define MX51_INT_MCG_ERR 81
+#define MX51_INT_MCG_TMR 82
+#define MX51_INT_MCG_FUNC 83
+#define MX51_INT_GPU2_IRQ 84
+#define MX51_INT_GPU2_BUSY 85
+#define MX51_INT_RESV86 86
#define MX51_INT_FEC 87
-#define MX51_MXC_INT_OWIRE 88
-#define MX51_MXC_INT_CTI1_TG2 89
-#define MX51_MXC_INT_SJC 90
-#define MX51_MXC_INT_SPDIF 91
-#define MX51_MXC_INT_TVE 92
-#define MX51_MXC_INT_FIRI 93
+#define MX51_INT_OWIRE 88
+#define MX51_INT_CTI1_TG2 89
+#define MX51_INT_SJC 90
+#define MX51_INT_SPDIF 91
+#define MX51_INT_TVE 92
+#define MX51_INT_FIRI 93
#define MX51_INT_PWM2 94
-#define MX51_MXC_INT_SLIM_EXP 95
+#define MX51_INT_SLIM_EXP 95
#define MX51_INT_SSI3 96
-#define MX51_MXC_INT_EMI_BOOT 97
-#define MX51_MXC_INT_CTI1_TG3 98
-#define MX51_MXC_INT_SMC_RX 99
-#define MX51_MXC_INT_VPU_IDLE 100
-#define MX51_MXC_INT_EMI_NFC 101
-#define MX51_MXC_INT_GPU_IDLE 102
+#define MX51_INT_EMI_BOOT 97
+#define MX51_INT_CTI1_TG3 98
+#define MX51_INT_SMC_RX 99
+#define MX51_INT_VPU_IDLE 100
+#define MX51_INT_EMI_NFC 101
+#define MX51_INT_GPU_IDLE 102
#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
extern int mx51_revision(void);
extern void mx51_display_revision(void);
#endif
-/* tape-out 1 defines */
-#define MX51_TZIC_BASE_ADDR_TO1 0x8fffc000
-
#endif /* ifndef __MACH_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx53.h b/arch/arm/plat-mxc/include/mach/mx53.h
index 5e3c3236ebf3..a37e8c353994 100644
--- a/arch/arm/plat-mxc/include/mach/mx53.h
+++ b/arch/arm/plat-mxc/include/mach/mx53.h
@@ -9,6 +9,7 @@
/* TZIC */
#define MX53_TZIC_BASE_ADDR 0x0FFFC000
+#define MX53_TZIC_SIZE SZ_16K
/*
* AHCI SATA
diff --git a/arch/arm/plat-mxc/include/mach/mx6q.h b/arch/arm/plat-mxc/include/mach/mx6q.h
new file mode 100644
index 000000000000..254a561a2799
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx6q.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __MACH_MX6Q_H__
+#define __MACH_MX6Q_H__
+
+#define MX6Q_IO_P2V(x) IMX_IO_P2V(x)
+#define MX6Q_IO_ADDRESS(x) IOMEM(MX6Q_IO_P2V(x))
+
+/*
+ * The following are the blocks that need to be statically mapped.
+ * For other blocks, the base address really should be retrieved from
+ * device tree.
+ */
+#define MX6Q_SCU_BASE_ADDR 0x00a00000
+#define MX6Q_SCU_SIZE 0x1000
+#define MX6Q_CCM_BASE_ADDR 0x020c4000
+#define MX6Q_CCM_SIZE 0x4000
+#define MX6Q_ANATOP_BASE_ADDR 0x020c8000
+#define MX6Q_ANATOP_SIZE 0x1000
+#define MX6Q_UART4_BASE_ADDR 0x021f0000
+#define MX6Q_UART4_SIZE 0x4000
+
+#endif /* __MACH_MX6Q_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 09879235a9f5..00a78193c681 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -183,13 +183,6 @@ struct cpu_op {
};
int tzic_enable_wake(int is_idle);
-enum mxc_cpu_pwr_mode {
- WAIT_CLOCKED, /* wfi only */
- WAIT_UNCLOCKED, /* WAIT */
- WAIT_UNCLOCKED_POWER_OFF, /* WAIT + SRPG */
- STOP_POWER_ON, /* just STOP */
- STOP_POWER_OFF, /* STOP + SRPG */
-};
extern struct cpu_op *(*get_cpu_op)(int *op);
#endif
diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h
index 51f02a9d41a3..cf88b3593fba 100644
--- a/arch/arm/plat-mxc/include/mach/system.h
+++ b/arch/arm/plat-mxc/include/mach/system.h
@@ -17,41 +17,12 @@
#ifndef __ASM_ARCH_MXC_SYSTEM_H__
#define __ASM_ARCH_MXC_SYSTEM_H__
-#include <mach/hardware.h>
-#include <mach/common.h>
-
-extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
+extern void (*imx_idle)(void);
static inline void arch_idle(void)
{
- /* fix i.MX31 errata TLSbo65953 and i.MX35 errata ENGcm09472 */
- if (cpu_is_mx31() || cpu_is_mx35()) {
- unsigned long reg = 0;
- __asm__ __volatile__(
- /* disable I and D cache */
- "mrc p15, 0, %0, c1, c0, 0\n"
- "bic %0, %0, #0x00001000\n"
- "bic %0, %0, #0x00000004\n"
- "mcr p15, 0, %0, c1, c0, 0\n"
- /* invalidate I cache */
- "mov %0, #0\n"
- "mcr p15, 0, %0, c7, c5, 0\n"
- /* clear and invalidate D cache */
- "mov %0, #0\n"
- "mcr p15, 0, %0, c7, c14, 0\n"
- /* WFI */
- "mov %0, #0\n"
- "mcr p15, 0, %0, c7, c0, 4\n"
- "nop\n" "nop\n" "nop\n" "nop\n"
- "nop\n" "nop\n" "nop\n"
- /* enable I and D cache */
- "mrc p15, 0, %0, c1, c0, 0\n"
- "orr %0, %0, #0x00001000\n"
- "orr %0, %0, #0x00000004\n"
- "mcr p15, 0, %0, c1, c0, 0\n"
- : "=r" (reg));
- } else if (cpu_is_mx51())
- mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+ if (imx_idle != NULL)
+ (imx_idle)();
else
cpu_do_idle();
}
diff --git a/arch/arm/plat-mxc/irq-common.c b/arch/arm/plat-mxc/irq-common.c
index 96953e2e4f11..b6e11458e5ae 100644
--- a/arch/arm/plat-mxc/irq-common.c
+++ b/arch/arm/plat-mxc/irq-common.c
@@ -23,17 +23,17 @@
int imx_irq_set_priority(unsigned char irq, unsigned char prio)
{
- struct mxc_irq_chip *chip;
- struct irq_chip *base;
+ struct irq_chip_generic *gc;
+ struct mxc_extra_irq *exirq;
int ret;
ret = -ENOSYS;
- base = irq_get_chip(irq);
- if (base) {
- chip = container_of(base, struct mxc_irq_chip, base);
- if (chip->set_priority)
- ret = chip->set_priority(irq, prio);
+ gc = irq_get_chip_data(irq);
+ if (gc && gc->private) {
+ exirq = gc->private;
+ if (exirq->set_priority)
+ ret = exirq->set_priority(irq, prio);
}
return ret;
@@ -43,15 +43,16 @@ EXPORT_SYMBOL(imx_irq_set_priority);
int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
{
struct irq_chip_generic *gc;
- int (*set_irq_fiq)(unsigned int, unsigned int);
+ struct mxc_extra_irq *exirq;
int ret;
ret = -ENOSYS;
gc = irq_get_chip_data(irq);
if (gc && gc->private) {
- set_irq_fiq = gc->private;
- ret = set_irq_fiq(irq, type);
+ exirq = gc->private;
+ if (exirq->set_irq_fiq)
+ ret = exirq->set_irq_fiq(irq, type);
}
return ret;
diff --git a/arch/arm/plat-mxc/irq-common.h b/arch/arm/plat-mxc/irq-common.h
index 7203543fb1b3..6ccb3a14c693 100644
--- a/arch/arm/plat-mxc/irq-common.h
+++ b/arch/arm/plat-mxc/irq-common.h
@@ -19,9 +19,8 @@
#ifndef __PLAT_MXC_IRQ_COMMON_H__
#define __PLAT_MXC_IRQ_COMMON_H__
-struct mxc_irq_chip
+struct mxc_extra_irq
{
- struct irq_chip base;
int (*set_priority)(unsigned char irq, unsigned char prio);
int (*set_irq_fiq)(unsigned int irq, unsigned int type);
};
diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c
index 761c3c940a68..42d74ea59084 100644
--- a/arch/arm/plat-mxc/pwm.c
+++ b/arch/arm/plat-mxc/pwm.c
@@ -57,7 +57,7 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
return -EINVAL;
- if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
+ if (!(cpu_is_mx1() || cpu_is_mx21())) {
unsigned long long c;
unsigned long period_cycles, duty_cycles, prescale;
u32 cr;
diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c
index 8024f2ac177c..9dad8dcc2ea9 100644
--- a/arch/arm/plat-mxc/system.c
+++ b/arch/arm/plat-mxc/system.c
@@ -28,6 +28,9 @@
#include <asm/system.h>
#include <asm/mach-types.h>
+void (*imx_idle)(void) = NULL;
+void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int) = NULL;
+
static void __iomem *wdog_base;
/*
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index f257fccdc394..e993a184189a 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -42,7 +42,7 @@
#define TZIC_SRCCLAR0 0x0280 /* Source Clear Register 0 */
#define TZIC_PRIORITY0 0x0400 /* Priority Register 0 */
#define TZIC_PND0 0x0D00 /* Pending Register 0 */
-#define TZIC_HIPND0 0x0D80 /* High Priority Pending Register */
+#define TZIC_HIPND(i) (0x0D80+ ((i) << 2)) /* High Priority Pending Register */
#define TZIC_WAKEUP0(i) (0x0E00 + ((i) << 2)) /* Wakeup Config Register */
#define TZIC_SWINT 0x0F00 /* Software Interrupt Rigger Register */
#define TZIC_ID0 0x0FD0 /* Indentification Register 0 */
@@ -74,6 +74,12 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
static unsigned int *wakeup_intr[4];
+static struct mxc_extra_irq tzic_extra_irq = {
+#ifdef CONFIG_FIQ
+ .set_irq_fiq = tzic_set_irq_fiq,
+#endif
+};
+
static __init void tzic_init_gc(unsigned int irq_start)
{
struct irq_chip_generic *gc;
@@ -82,7 +88,7 @@ static __init void tzic_init_gc(unsigned int irq_start)
gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
handle_level_irq);
- gc->private = tzic_set_irq_fiq;
+ gc->private = &tzic_extra_irq;
gc->wake_enabled = IRQ_MSK(32);
wakeup_intr[idx] = &gc->wake_active;
@@ -96,6 +102,28 @@ static __init void tzic_init_gc(unsigned int irq_start)
irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
}
+asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
+{
+ u32 stat;
+ int i, irqofs, handled;
+
+ do {
+ handled = 0;
+
+ for (i = 0; i < 4; i++) {
+ stat = __raw_readl(tzic_base + TZIC_HIPND(i)) &
+ __raw_readl(tzic_base + TZIC_INTSEC0(i));
+
+ while (stat) {
+ handled = 1;
+ irqofs = fls(stat) - 1;
+ handle_IRQ(irqofs + i * 32, regs);
+ stat &= ~(1 << irqofs);
+ }
+ }
+ } while (handled);
+}
+
/*
* This function initializes the TZIC hardware and disables all the
* interrupts. It registers the interrupt enable and disable functions
diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig
index ce659015535e..bca4914b4b9d 100644
--- a/arch/arm/plat-nomadik/Kconfig
+++ b/arch/arm/plat-nomadik/Kconfig
@@ -15,10 +15,16 @@ if PLAT_NOMADIK
config HAS_MTU
bool
- select HAVE_SCHED_CLOCK
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
+ select HAVE_SCHED_CLOCK
+ help
+ Use the Multi Timer Unit as the sched_clock.
+
endif
diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
index d5d7e651269c..9605bf227df9 100644
--- a/arch/arm/plat-nomadik/include/plat/gpio.h
+++ b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
@@ -9,20 +9,9 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#ifndef __ASM_PLAT_GPIO_H
-#define __ASM_PLAT_GPIO_H
-#include <asm-generic/gpio.h>
-
-/*
- * These currently cause a function call to happen, they may be optimized
- * if needed by adding cpu-specific defines to identify blocks
- * (see mach-pxa/include/mach/gpio.h as an example using GPLR etc)
- */
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
+#ifndef __PLAT_NOMADIK_GPIO
+#define __PLAT_NOMADIK_GPIO
/*
* "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
@@ -78,6 +67,9 @@ extern int nmk_gpio_get_mode(int gpio);
extern void nmk_gpio_wakeups_suspend(void);
extern void nmk_gpio_wakeups_resume(void);
+extern void nmk_gpio_clocks_enable(void);
+extern void nmk_gpio_clocks_disable(void);
+
extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
/*
@@ -93,4 +85,4 @@ struct nmk_gpio_platform_data {
bool supports_sleepmode;
};
-#endif /* __ASM_PLAT_GPIO_H */
+#endif /* __PLAT_NOMADIK_GPIO */
diff --git a/arch/arm/plat-nomadik/include/plat/mtu.h b/arch/arm/plat-nomadik/include/plat/mtu.h
index 65704a3d4241..6508e7694a4b 100644
--- a/arch/arm/plat-nomadik/include/plat/mtu.h
+++ b/arch/arm/plat-nomadik/include/plat/mtu.h
@@ -1,54 +1,11 @@
#ifndef __PLAT_MTU_H
#define __PLAT_MTU_H
-/*
- * Guaranteed runtime conversion range in seconds for
- * the clocksource and clockevent.
- */
-#define MTU_MIN_RANGE 4
-
/* should be set by the platform code */
extern void __iomem *mtu_base;
-/*
- * The MTU device hosts four different counters, with 4 set of
- * registers. These are register names.
- */
-
-#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
-#define MTU_RIS 0x04 /* Raw interrupt status */
-#define MTU_MIS 0x08 /* Masked interrupt status */
-#define MTU_ICR 0x0C /* Interrupt clear register */
-
-/* per-timer registers take 0..3 as argument */
-#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
-#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
-#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
-#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
-
-/* bits for the control register */
-#define MTU_CRn_ENA 0x80
-#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */
-#define MTU_CRn_PRESCALE_MASK 0x0c
-#define MTU_CRn_PRESCALE_1 0x00
-#define MTU_CRn_PRESCALE_16 0x04
-#define MTU_CRn_PRESCALE_256 0x08
-#define MTU_CRn_32BITS 0x02
-#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
-
-/* Other registers are usual amba/primecell registers, currently not used */
-#define MTU_ITCR 0xff0
-#define MTU_ITOP 0xff4
-
-#define MTU_PERIPH_ID0 0xfe0
-#define MTU_PERIPH_ID1 0xfe4
-#define MTU_PERIPH_ID2 0xfe8
-#define MTU_PERIPH_ID3 0xfeC
-
-#define MTU_PCELL0 0xff0
-#define MTU_PCELL1 0xff4
-#define MTU_PCELL2 0xff8
-#define MTU_PCELL3 0xffC
+void nmdk_clkevt_reset(void);
+void nmdk_clksrc_reset(void);
#endif /* __PLAT_MTU_H */
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h
index 05a3936ae6d1..22cb97d2d8ad 100644
--- a/arch/arm/plat-nomadik/include/plat/pincfg.h
+++ b/arch/arm/plat-nomadik/include/plat/pincfg.h
@@ -37,7 +37,6 @@
* SLPM value = same as normal
*
* PIN_CFG - default config with alternate function
- * PIN_CFG_PULL - default config with alternate function and pull up/down
*/
typedef unsigned long pin_cfg_t;
@@ -133,10 +132,6 @@ typedef unsigned long pin_cfg_t;
(PIN_CFG_DEFAULT |\
(PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
-#define PIN_CFG_PULL(num, alt, pull) \
- ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\
- (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull))
-
extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c
index ef74e157a9d5..30b6433d910d 100644
--- a/arch/arm/plat-nomadik/timer.c
+++ b/arch/arm/plat-nomadik/timer.c
@@ -21,10 +21,59 @@
#include <asm/mach/time.h>
#include <asm/sched_clock.h>
-#include <plat/mtu.h>
+/*
+ * Guaranteed runtime conversion range in seconds for
+ * the clocksource and clockevent.
+ */
+#define MTU_MIN_RANGE 4
+
+/*
+ * The MTU device hosts four different counters, with 4 set of
+ * registers. These are register names.
+ */
+
+#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
+#define MTU_RIS 0x04 /* Raw interrupt status */
+#define MTU_MIS 0x08 /* Masked interrupt status */
+#define MTU_ICR 0x0C /* Interrupt clear register */
+
+/* per-timer registers take 0..3 as argument */
+#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
+#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
+#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
+#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
+
+/* bits for the control register */
+#define MTU_CRn_ENA 0x80
+#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */
+#define MTU_CRn_PRESCALE_MASK 0x0c
+#define MTU_CRn_PRESCALE_1 0x00
+#define MTU_CRn_PRESCALE_16 0x04
+#define MTU_CRn_PRESCALE_256 0x08
+#define MTU_CRn_32BITS 0x02
+#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
+
+/* Other registers are usual amba/primecell registers, currently not used */
+#define MTU_ITCR 0xff0
+#define MTU_ITOP 0xff4
+
+#define MTU_PERIPH_ID0 0xfe0
+#define MTU_PERIPH_ID1 0xfe4
+#define MTU_PERIPH_ID2 0xfe8
+#define MTU_PERIPH_ID3 0xfeC
+
+#define MTU_PCELL0 0xff0
+#define MTU_PCELL1 0xff4
+#define MTU_PCELL2 0xff8
+#define MTU_PCELL3 0xffC
+
+static bool clkevt_periodic;
+static u32 clk_prescale;
+static u32 nmdk_cycle; /* write-once */
void __iomem *mtu_base; /* Assigned by machine code */
+#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
/*
* Override the global weak sched_clock symbol with this
* local implementation which uses the clocksource to get some
@@ -48,32 +97,56 @@ static void notrace nomadik_update_sched_clock(void)
u32 cyc = -readl(mtu_base + MTU_VAL(0));
update_sched_clock(&cd, cyc, (u32)~0);
}
+#endif
/* Clockevent device: use one-shot mode */
+static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
+{
+ writel(1 << 1, mtu_base + MTU_IMSC);
+ writel(evt, mtu_base + MTU_LR(1));
+ /* Load highest value, enable device, enable interrupts */
+ writel(MTU_CRn_ONESHOT | clk_prescale |
+ MTU_CRn_32BITS | MTU_CRn_ENA,
+ mtu_base + MTU_CR(1));
+
+ return 0;
+}
+
+void nmdk_clkevt_reset(void)
+{
+ if (clkevt_periodic) {
+
+ /* Timer: configure load and background-load, and fire it up */
+ writel(nmdk_cycle, mtu_base + MTU_LR(1));
+ writel(nmdk_cycle, mtu_base + MTU_BGLR(1));
+
+ writel(MTU_CRn_PERIODIC | clk_prescale |
+ MTU_CRn_32BITS | MTU_CRn_ENA,
+ mtu_base + MTU_CR(1));
+ writel(1 << 1, mtu_base + MTU_IMSC);
+ } else {
+ /* Generate an interrupt to start the clockevent again */
+ (void) nmdk_clkevt_next(nmdk_cycle, NULL);
+ }
+}
+
static void nmdk_clkevt_mode(enum clock_event_mode mode,
struct clock_event_device *dev)
{
- u32 cr;
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
- pr_err("%s: periodic mode not supported\n", __func__);
+ clkevt_periodic = true;
+ nmdk_clkevt_reset();
break;
case CLOCK_EVT_MODE_ONESHOT:
- /* Load highest value, enable device, enable interrupts */
- cr = readl(mtu_base + MTU_CR(1));
- writel(0, mtu_base + MTU_LR(1));
- writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1));
- writel(1 << 1, mtu_base + MTU_IMSC);
+ clkevt_periodic = false;
break;
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
- /* disable irq */
writel(0, mtu_base + MTU_IMSC);
/* disable timer */
- cr = readl(mtu_base + MTU_CR(1));
- cr &= ~MTU_CRn_ENA;
- writel(cr, mtu_base + MTU_CR(1));
+ writel(0, mtu_base + MTU_CR(1));
/* load some high default value */
writel(0xffffffff, mtu_base + MTU_LR(1));
break;
@@ -82,16 +155,9 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode,
}
}
-static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
-{
- /* writing the value has immediate effect */
- writel(evt, mtu_base + MTU_LR(1));
- return 0;
-}
-
static struct clock_event_device nmdk_clkevt = {
.name = "mtu_1",
- .features = CLOCK_EVT_FEAT_ONESHOT,
+ .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
.rating = 200,
.set_mode = nmdk_clkevt_mode,
.set_next_event = nmdk_clkevt_next,
@@ -116,11 +182,23 @@ static struct irqaction nmdk_timer_irq = {
.dev_id = &nmdk_clkevt,
};
+void nmdk_clksrc_reset(void)
+{
+ /* Disable */
+ writel(0, mtu_base + MTU_CR(0));
+
+ /* ClockSource: configure load and background-load, and fire it up */
+ writel(nmdk_cycle, mtu_base + MTU_LR(0));
+ writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
+
+ writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
+ mtu_base + MTU_CR(0));
+}
+
void __init nmdk_timer_init(void)
{
unsigned long rate;
struct clk *clk0;
- u32 cr = MTU_CRn_32BITS;
clk0 = clk_get_sys("mtu0", NULL);
BUG_ON(IS_ERR(clk0));
@@ -138,30 +216,28 @@ void __init nmdk_timer_init(void)
rate = clk_get_rate(clk0);
if (rate > 32000000) {
rate /= 16;
- cr |= MTU_CRn_PRESCALE_16;
+ clk_prescale = MTU_CRn_PRESCALE_16;
} else {
- cr |= MTU_CRn_PRESCALE_1;
+ clk_prescale = MTU_CRn_PRESCALE_1;
}
+ nmdk_cycle = (rate + HZ/2) / HZ;
+
+
/* Timer 0 is the free running clocksource */
- writel(cr, mtu_base + MTU_CR(0));
- writel(0, mtu_base + MTU_LR(0));
- writel(0, mtu_base + MTU_BGLR(0));
- writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
+ nmdk_clksrc_reset();
if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
rate, 200, 32, clocksource_mmio_readl_down))
pr_err("timer: failed to initialize clock source %s\n",
"mtu_0");
-
+#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);
-
+#endif
/* Timer 1 is used for events */
clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);
- writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */
-
nmdk_clkevt.max_delta_ns =
clockevent_delta2ns(0xffffffff, &nmdk_clkevt);
nmdk_clkevt.min_delta_ns =
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index bb8f4a6b3e37..aa59f4247dc5 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -14,6 +14,8 @@ config ARCH_OMAP1
select CLKDEV_LOOKUP
select CLKSRC_MMIO
select GENERIC_IRQ_CHIP
+ select HAVE_IDE
+ select NEED_MACH_MEMORY_H
help
"Systems based on omap7xx, omap15xx or omap16xx"
@@ -132,18 +134,6 @@ config OMAP_MBOX_KFIFO_SIZE
This can also be changed at runtime (via the mbox_kfifo_size
module parameter).
-config OMAP_IOMMU
- tristate
-
-config OMAP_IOMMU_DEBUG
- tristate "Export OMAP IOMMU internals in DebugFS"
- depends on OMAP_IOMMU && DEBUG_FS
- help
- Select this to see extensive information about
- the internal state of OMAP IOMMU in debugfs.
-
- Say N unless you know you need this.
-
config OMAP_IOMMU_IVA2
bool
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index f0233e6abcdf..985262242f25 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -18,8 +18,6 @@ obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
-obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
-obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
diff --git a/arch/arm/plat-omap/debug-devices.c b/arch/arm/plat-omap/debug-devices.c
index 923c9621096b..caa1f7b6cc21 100644
--- a/arch/arm/plat-omap/debug-devices.c
+++ b/arch/arm/plat-omap/debug-devices.c
@@ -8,7 +8,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -18,7 +18,6 @@
#include <mach/hardware.h>
#include <plat/board.h>
-#include <mach/gpio.h>
/* Many OMAP development platforms reuse the same "debug board"; these
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c
index fc05b1022602..61a1ec2a6af4 100644
--- a/arch/arm/plat-omap/debug-leds.c
+++ b/arch/arm/plat-omap/debug-leds.c
@@ -7,7 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
@@ -19,7 +19,6 @@
#include <asm/mach-types.h>
#include <plat/fpga.h>
-#include <mach/gpio.h>
/* Many OMAP development platforms reuse the same "debug board"; these
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index ea28f98d5d6a..19719329a47b 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -8,7 +8,7 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
-
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -24,91 +24,9 @@
#include <plat/tc.h>
#include <plat/board.h>
#include <plat/mmc.h>
-#include <mach/gpio.h>
#include <plat/menelaus.h>
-#include <plat/mcbsp.h>
#include <plat/omap44xx.h>
-/*-------------------------------------------------------------------------*/
-
-#if defined(CONFIG_OMAP_MCBSP) || defined(CONFIG_OMAP_MCBSP_MODULE)
-
-static struct platform_device **omap_mcbsp_devices;
-
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
- struct omap_mcbsp_platform_data *config, int size)
-{
- int i;
-
- omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
- GFP_KERNEL);
- if (!omap_mcbsp_devices) {
- printk(KERN_ERR "Could not register McBSP devices\n");
- return;
- }
-
- for (i = 0; i < size; i++) {
- struct platform_device *new_mcbsp;
- int ret;
-
- new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
- if (!new_mcbsp)
- continue;
- platform_device_add_resources(new_mcbsp, &res[i * res_count],
- res_count);
- new_mcbsp->dev.platform_data = &config[i];
- ret = platform_device_add(new_mcbsp);
- if (ret) {
- platform_device_put(new_mcbsp);
- continue;
- }
- omap_mcbsp_devices[i] = new_mcbsp;
- }
-}
-
-#else
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
- struct omap_mcbsp_platform_data *config, int size)
-{ }
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
- defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
-
-static struct resource mcpdm_resources[] = {
- {
- .name = "mcpdm_mem",
- .start = OMAP44XX_MCPDM_BASE,
- .end = OMAP44XX_MCPDM_BASE + SZ_4K,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "mcpdm_irq",
- .start = OMAP44XX_IRQ_MCPDM,
- .end = OMAP44XX_IRQ_MCPDM,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device omap_mcpdm_device = {
- .name = "omap-mcpdm",
- .id = -1,
- .num_resources = ARRAY_SIZE(mcpdm_resources),
- .resource = mcpdm_resources,
-};
-
-static void omap_init_mcpdm(void)
-{
- (void) platform_device_register(&omap_mcpdm_device);
-}
-#else
-static inline void omap_init_mcpdm(void) {}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
@@ -291,7 +209,6 @@ static int __init omap_init_devices(void)
* in alphabetical order so they're easier to sort through.
*/
omap_init_rng();
- omap_init_mcpdm();
omap_init_uwire();
return 0;
}
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 75a847dd776a..2def4e1990ed 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -3,6 +3,12 @@
*
* OMAP Dual-Mode Timers
*
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * dmtimer adaptation to platform_driver.
+ *
* Copyright (C) 2005 Nokia Corporation
* OMAP2 support by Juha Yrjola
* API improvements and OMAP2 clock framework support by Timo Teras
@@ -29,168 +35,80 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
#include <linux/io.h>
-#include <linux/module.h>
-#include <mach/hardware.h>
-#include <plat/dmtimer.h>
-#include <mach/irqs.h>
-
-static int dm_timer_count;
-
-#ifdef CONFIG_ARCH_OMAP1
-static struct omap_dm_timer omap1_dm_timers[] = {
- { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
- { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
- { .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
- { .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
- { .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
- { .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
- { .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
- { .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
-};
-
-static const int omap1_dm_timer_count = ARRAY_SIZE(omap1_dm_timers);
-
-#else
-#define omap1_dm_timers NULL
-#define omap1_dm_timer_count 0
-#endif /* CONFIG_ARCH_OMAP1 */
-
-#ifdef CONFIG_ARCH_OMAP2
-static struct omap_dm_timer omap2_dm_timers[] = {
- { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
- { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
- { .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
- { .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
- { .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
- { .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
- { .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
- { .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
- { .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
- { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
- { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
- { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
-};
-
-static const char *omap2_dm_source_names[] __initdata = {
- "sys_ck",
- "func_32k_ck",
- "alt_ck",
- NULL
-};
-
-static struct clk *omap2_dm_source_clocks[3];
-static const int omap2_dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
-
-#else
-#define omap2_dm_timers NULL
-#define omap2_dm_timer_count 0
-#define omap2_dm_source_names NULL
-#define omap2_dm_source_clocks NULL
-#endif /* CONFIG_ARCH_OMAP2 */
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_dm_timer omap3_dm_timers[] = {
- { .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
- { .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
- { .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
- { .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
- { .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
- { .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
- { .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
- { .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
- { .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
- { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
- { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
- { .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
-};
-
-static const char *omap3_dm_source_names[] __initdata = {
- "sys_ck",
- "omap_32k_fck",
- NULL
-};
-
-static struct clk *omap3_dm_source_clocks[2];
-static const int omap3_dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
-#else
-#define omap3_dm_timers NULL
-#define omap3_dm_timer_count 0
-#define omap3_dm_source_names NULL
-#define omap3_dm_source_clocks NULL
-#endif /* CONFIG_ARCH_OMAP3 */
-
-#ifdef CONFIG_ARCH_OMAP4
-static struct omap_dm_timer omap4_dm_timers[] = {
- { .phys_base = 0x4a318000, .irq = OMAP44XX_IRQ_GPT1 },
- { .phys_base = 0x48032000, .irq = OMAP44XX_IRQ_GPT2 },
- { .phys_base = 0x48034000, .irq = OMAP44XX_IRQ_GPT3 },
- { .phys_base = 0x48036000, .irq = OMAP44XX_IRQ_GPT4 },
- { .phys_base = 0x40138000, .irq = OMAP44XX_IRQ_GPT5 },
- { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT6 },
- { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT7 },
- { .phys_base = 0x4013e000, .irq = OMAP44XX_IRQ_GPT8 },
- { .phys_base = 0x4803e000, .irq = OMAP44XX_IRQ_GPT9 },
- { .phys_base = 0x48086000, .irq = OMAP44XX_IRQ_GPT10 },
- { .phys_base = 0x48088000, .irq = OMAP44XX_IRQ_GPT11 },
- { .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 },
-};
-static const char *omap4_dm_source_names[] __initdata = {
- "sys_clkin_ck",
- "sys_32k_ck",
- NULL
-};
-static struct clk *omap4_dm_source_clocks[2];
-static const int omap4_dm_timer_count = ARRAY_SIZE(omap4_dm_timers);
-
-#else
-#define omap4_dm_timers NULL
-#define omap4_dm_timer_count 0
-#define omap4_dm_source_names NULL
-#define omap4_dm_source_clocks NULL
-#endif /* CONFIG_ARCH_OMAP4 */
-
-static struct omap_dm_timer *dm_timers;
-static const char **dm_source_names;
-static struct clk **dm_source_clocks;
+#include <plat/dmtimer.h>
-static spinlock_t dm_timer_lock;
+static LIST_HEAD(omap_timer_list);
+static DEFINE_SPINLOCK(dm_timer_lock);
-/*
- * Reads timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode write pending bit must be
- * checked. Otherwise a read of a non completed write will produce an error.
+/**
+ * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
+ * @timer: timer pointer over which read operation to perform
+ * @reg: lowest byte holds the register offset
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode write
+ * pending bit must be checked. Otherwise a read of a non completed write
+ * will produce an error.
*/
static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
{
- return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
+ WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
+ return __omap_dm_timer_read(timer, reg, timer->posted);
}
-/*
- * Writes timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode the write pending bit must be
- * checked. Otherwise a write on a register which has a pending write will be
- * lost.
+/**
+ * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
+ * @timer: timer pointer over which write operation is to perform
+ * @reg: lowest byte holds the register offset
+ * @value: data to write into the register
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode the write
+ * pending bit must be checked. Otherwise a write on a register which has a
+ * pending write will be lost.
*/
static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
u32 value)
{
- __omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
+ WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
+ __omap_dm_timer_write(timer, reg, value, timer->posted);
+}
+
+static void omap_timer_restore_context(struct omap_dm_timer *timer)
+{
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_OFFSET,
+ timer->context.tiocp_cfg);
+ if (timer->revision > 1)
+ __raw_writel(timer->context.tistat, timer->sys_stat);
+
+ __raw_writel(timer->context.tisr, timer->irq_stat);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
+ timer->context.twer);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
+ timer->context.tcrr);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
+ timer->context.tldr);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
+ timer->context.tmar);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
+ timer->context.tsicr);
+ __raw_writel(timer->context.tier, timer->irq_ena);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
+ timer->context.tclr);
}
static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
{
int c;
+ if (!timer->sys_stat)
+ return;
+
c = 0;
- while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
+ while (!(__raw_readl(timer->sys_stat) & 1)) {
c++;
if (c > 100000) {
printk(KERN_ERR "Timer failed to reset\n");
@@ -201,53 +119,65 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
static void omap_dm_timer_reset(struct omap_dm_timer *timer)
{
- int autoidle = 0, wakeup = 0;
-
- if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
+ omap_dm_timer_enable(timer);
+ if (timer->pdev->id != 1) {
omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
omap_dm_timer_wait_for_reset(timer);
}
- omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
-
- /* Enable autoidle on OMAP2+ */
- if (cpu_class_is_omap2())
- autoidle = 1;
-
- /*
- * Enable wake-up on OMAP2 CPUs.
- */
- if (cpu_class_is_omap2())
- wakeup = 1;
- __omap_dm_timer_reset(timer->io_base, autoidle, wakeup);
+ __omap_dm_timer_reset(timer, 0, 0);
+ omap_dm_timer_disable(timer);
timer->posted = 1;
}
-void omap_dm_timer_prepare(struct omap_dm_timer *timer)
+int omap_dm_timer_prepare(struct omap_dm_timer *timer)
{
- omap_dm_timer_enable(timer);
- omap_dm_timer_reset(timer);
+ struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+ int ret;
+
+ timer->fclk = clk_get(&timer->pdev->dev, "fck");
+ if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
+ timer->fclk = NULL;
+ dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+ return -EINVAL;
+ }
+
+ if (pdata->needs_manual_reset)
+ omap_dm_timer_reset(timer);
+
+ ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
+
+ timer->posted = 1;
+ return ret;
}
struct omap_dm_timer *omap_dm_timer_request(void)
{
- struct omap_dm_timer *timer = NULL;
+ struct omap_dm_timer *timer = NULL, *t;
unsigned long flags;
- int i;
+ int ret = 0;
spin_lock_irqsave(&dm_timer_lock, flags);
- for (i = 0; i < dm_timer_count; i++) {
- if (dm_timers[i].reserved)
+ list_for_each_entry(t, &omap_timer_list, node) {
+ if (t->reserved)
continue;
- timer = &dm_timers[i];
+ timer = t;
timer->reserved = 1;
break;
}
+
+ if (timer) {
+ ret = omap_dm_timer_prepare(timer);
+ if (ret) {
+ timer->reserved = 0;
+ timer = NULL;
+ }
+ }
spin_unlock_irqrestore(&dm_timer_lock, flags);
- if (timer != NULL)
- omap_dm_timer_prepare(timer);
+ if (!timer)
+ pr_debug("%s: timer request failed!\n", __func__);
return timer;
}
@@ -255,74 +185,65 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request);
struct omap_dm_timer *omap_dm_timer_request_specific(int id)
{
- struct omap_dm_timer *timer;
+ struct omap_dm_timer *timer = NULL, *t;
unsigned long flags;
+ int ret = 0;
spin_lock_irqsave(&dm_timer_lock, flags);
- if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
- spin_unlock_irqrestore(&dm_timer_lock, flags);
- printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
- __FILE__, __LINE__, __func__, id);
- dump_stack();
- return NULL;
+ list_for_each_entry(t, &omap_timer_list, node) {
+ if (t->pdev->id == id && !t->reserved) {
+ timer = t;
+ timer->reserved = 1;
+ break;
+ }
}
- timer = &dm_timers[id-1];
- timer->reserved = 1;
+ if (timer) {
+ ret = omap_dm_timer_prepare(timer);
+ if (ret) {
+ timer->reserved = 0;
+ timer = NULL;
+ }
+ }
spin_unlock_irqrestore(&dm_timer_lock, flags);
- omap_dm_timer_prepare(timer);
+ if (!timer)
+ pr_debug("%s: timer%d request failed!\n", __func__, id);
return timer;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
-void omap_dm_timer_free(struct omap_dm_timer *timer)
+int omap_dm_timer_free(struct omap_dm_timer *timer)
{
- omap_dm_timer_enable(timer);
- omap_dm_timer_reset(timer);
- omap_dm_timer_disable(timer);
+ if (unlikely(!timer))
+ return -EINVAL;
+
+ clk_put(timer->fclk);
WARN_ON(!timer->reserved);
timer->reserved = 0;
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_free);
void omap_dm_timer_enable(struct omap_dm_timer *timer)
{
- if (timer->enabled)
- return;
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
- if (cpu_class_is_omap2()) {
- clk_enable(timer->fclk);
- clk_enable(timer->iclk);
- }
-#endif
-
- timer->enabled = 1;
+ pm_runtime_get_sync(&timer->pdev->dev);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
void omap_dm_timer_disable(struct omap_dm_timer *timer)
{
- if (!timer->enabled)
- return;
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
- if (cpu_class_is_omap2()) {
- clk_disable(timer->iclk);
- clk_disable(timer->fclk);
- }
-#endif
-
- timer->enabled = 0;
+ pm_runtime_put(&timer->pdev->dev);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
{
- return timer->irq;
+ if (timer)
+ return timer->irq;
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
@@ -334,24 +255,29 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
*/
__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
{
- int i;
+ int i = 0;
+ struct omap_dm_timer *timer = NULL;
+ unsigned long flags;
/* If ARMXOR cannot be idled this function call is unnecessary */
if (!(inputmask & (1 << 1)))
return inputmask;
/* If any active timer is using ARMXOR return modified mask */
- for (i = 0; i < dm_timer_count; i++) {
+ spin_lock_irqsave(&dm_timer_lock, flags);
+ list_for_each_entry(timer, &omap_timer_list, node) {
u32 l;
- l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (l & OMAP_TIMER_CTRL_ST) {
if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
inputmask &= ~(1 << 1);
else
inputmask &= ~(1 << 2);
}
+ i++;
}
+ spin_unlock_irqrestore(&dm_timer_lock, flags);
return inputmask;
}
@@ -361,7 +287,9 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
{
- return timer->fclk;
+ if (timer)
+ return timer->fclk;
+ return NULL;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
@@ -375,70 +303,91 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
#endif
-void omap_dm_timer_trigger(struct omap_dm_timer *timer)
+int omap_dm_timer_trigger(struct omap_dm_timer *timer)
{
+ if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+ pr_err("%s: timer not available or enabled.\n", __func__);
+ return -EINVAL;
+ }
+
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
-void omap_dm_timer_start(struct omap_dm_timer *timer)
+int omap_dm_timer_start(struct omap_dm_timer *timer)
{
u32 l;
+ if (unlikely(!timer))
+ return -EINVAL;
+
+ omap_dm_timer_enable(timer);
+
+ if (timer->loses_context) {
+ u32 ctx_loss_cnt_after =
+ timer->get_context_loss_count(&timer->pdev->dev);
+ if (ctx_loss_cnt_after != timer->ctx_loss_count)
+ omap_timer_restore_context(timer);
+ }
+
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (!(l & OMAP_TIMER_CTRL_ST)) {
l |= OMAP_TIMER_CTRL_ST;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
+
+ /* Save the context */
+ timer->context.tclr = l;
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_start);
-void omap_dm_timer_stop(struct omap_dm_timer *timer)
+int omap_dm_timer_stop(struct omap_dm_timer *timer)
{
unsigned long rate = 0;
+ struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
-#ifdef CONFIG_ARCH_OMAP2PLUS
- rate = clk_get_rate(timer->fclk);
-#endif
+ if (unlikely(!timer))
+ return -EINVAL;
- __omap_dm_timer_stop(timer->io_base, timer->posted, rate);
+ if (!pdata->needs_manual_reset)
+ rate = clk_get_rate(timer->fclk);
+
+ __omap_dm_timer_stop(timer, timer->posted, rate);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
-#ifdef CONFIG_ARCH_OMAP1
-
int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
- int n = (timer - dm_timers) << 1;
- u32 l;
-
- l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
- l |= source << n;
- omap_writel(l, MOD_CONF_CTRL_1);
+ int ret;
+ struct dmtimer_platform_data *pdata;
- return 0;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
+ if (unlikely(!timer))
+ return -EINVAL;
-#else
+ pdata = timer->pdev->dev.platform_data;
-int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
-{
if (source < 0 || source >= 3)
return -EINVAL;
- return __omap_dm_timer_set_source(timer->fclk,
- dm_source_clocks[source]);
+ ret = pdata->set_timer_src(timer->pdev, source);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
-#endif
-
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
unsigned int load)
{
u32 l;
+ if (unlikely(!timer))
+ return -EINVAL;
+
+ omap_dm_timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (autoreload)
l |= OMAP_TIMER_CTRL_AR;
@@ -448,15 +397,32 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+ /* Save the context */
+ timer->context.tclr = l;
+ timer->context.tldr = load;
+ omap_dm_timer_disable(timer);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
/* Optimized set_load which removes costly spin wait in timer_start */
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
+int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
unsigned int load)
{
u32 l;
+ if (unlikely(!timer))
+ return -EINVAL;
+
+ omap_dm_timer_enable(timer);
+
+ if (timer->loses_context) {
+ u32 ctx_loss_cnt_after =
+ timer->get_context_loss_count(&timer->pdev->dev);
+ if (ctx_loss_cnt_after != timer->ctx_loss_count)
+ omap_timer_restore_context(timer);
+ }
+
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (autoreload) {
l |= OMAP_TIMER_CTRL_AR;
@@ -466,15 +432,25 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
}
l |= OMAP_TIMER_CTRL_ST;
- __omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
+ __omap_dm_timer_load_start(timer, l, load, timer->posted);
+
+ /* Save the context */
+ timer->context.tclr = l;
+ timer->context.tldr = load;
+ timer->context.tcrr = load;
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
+int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
unsigned int match)
{
u32 l;
+ if (unlikely(!timer))
+ return -EINVAL;
+
+ omap_dm_timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (enable)
l |= OMAP_TIMER_CTRL_CE;
@@ -482,14 +458,24 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
l &= ~OMAP_TIMER_CTRL_CE;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+
+ /* Save the context */
+ timer->context.tclr = l;
+ timer->context.tmar = match;
+ omap_dm_timer_disable(timer);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
+int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
int toggle, int trigger)
{
u32 l;
+ if (unlikely(!timer))
+ return -EINVAL;
+
+ omap_dm_timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
OMAP_TIMER_CTRL_PT | (0x03 << 10));
@@ -499,13 +485,22 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
l |= OMAP_TIMER_CTRL_PT;
l |= trigger << 10;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+
+ /* Save the context */
+ timer->context.tclr = l;
+ omap_dm_timer_disable(timer);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
+int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
{
u32 l;
+ if (unlikely(!timer))
+ return -EINVAL;
+
+ omap_dm_timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
if (prescaler >= 0x00 && prescaler <= 0x07) {
@@ -513,13 +508,28 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
l |= prescaler << 2;
}
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+
+ /* Save the context */
+ timer->context.tclr = l;
+ omap_dm_timer_disable(timer);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
unsigned int value)
{
- __omap_dm_timer_int_enable(timer->io_base, value);
+ if (unlikely(!timer))
+ return -EINVAL;
+
+ omap_dm_timer_enable(timer);
+ __omap_dm_timer_int_enable(timer, value);
+
+ /* Save the context */
+ timer->context.tier = value;
+ timer->context.twer = value;
+ omap_dm_timer_disable(timer);
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
@@ -527,40 +537,61 @@ unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
{
unsigned int l;
- l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+ if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+ pr_err("%s: timer not available or enabled.\n", __func__);
+ return 0;
+ }
+
+ l = __raw_readl(timer->irq_stat);
return l;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
+int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
{
- __omap_dm_timer_write_status(timer->io_base, value);
+ if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
+ return -EINVAL;
+
+ __omap_dm_timer_write_status(timer, value);
+ /* Save the context */
+ timer->context.tisr = value;
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
{
- return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
+ if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+ pr_err("%s: timer not iavailable or enabled.\n", __func__);
+ return 0;
+ }
+
+ return __omap_dm_timer_read_counter(timer, timer->posted);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
+int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
{
+ if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+ pr_err("%s: timer not available or enabled.\n", __func__);
+ return -EINVAL;
+ }
+
omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+
+ /* Save the context */
+ timer->context.tcrr = value;
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
int omap_dm_timers_active(void)
{
- int i;
-
- for (i = 0; i < dm_timer_count; i++) {
- struct omap_dm_timer *timer;
-
- timer = &dm_timers[i];
+ struct omap_dm_timer *timer;
- if (!timer->enabled)
+ list_for_each_entry(timer, &omap_timer_list, node) {
+ if (!timer->reserved)
continue;
if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
@@ -572,69 +603,147 @@ int omap_dm_timers_active(void)
}
EXPORT_SYMBOL_GPL(omap_dm_timers_active);
-static int __init omap_dm_timer_init(void)
+/**
+ * omap_dm_timer_probe - probe function called for every registered device
+ * @pdev: pointer to current timer platform device
+ *
+ * Called by driver framework at the end of device registration for all
+ * timer devices.
+ */
+static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
{
+ int ret;
+ unsigned long flags;
struct omap_dm_timer *timer;
- int i, map_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */
+ struct resource *mem, *irq, *ioarea;
+ struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
- if (!(cpu_is_omap16xx() || cpu_class_is_omap2()))
+ if (!pdata) {
+ dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
return -ENODEV;
+ }
- spin_lock_init(&dm_timer_lock);
-
- if (cpu_class_is_omap1()) {
- dm_timers = omap1_dm_timers;
- dm_timer_count = omap1_dm_timer_count;
- map_size = SZ_2K;
- } else if (cpu_is_omap24xx()) {
- dm_timers = omap2_dm_timers;
- dm_timer_count = omap2_dm_timer_count;
- dm_source_names = omap2_dm_source_names;
- dm_source_clocks = omap2_dm_source_clocks;
- } else if (cpu_is_omap34xx()) {
- dm_timers = omap3_dm_timers;
- dm_timer_count = omap3_dm_timer_count;
- dm_source_names = omap3_dm_source_names;
- dm_source_clocks = omap3_dm_source_clocks;
- } else if (cpu_is_omap44xx()) {
- dm_timers = omap4_dm_timers;
- dm_timer_count = omap4_dm_timer_count;
- dm_source_names = omap4_dm_source_names;
- dm_source_clocks = omap4_dm_source_clocks;
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (unlikely(!irq)) {
+ dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
+ return -ENODEV;
}
- if (cpu_class_is_omap2())
- for (i = 0; dm_source_names[i] != NULL; i++)
- dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(!mem)) {
+ dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
+ return -ENODEV;
+ }
- if (cpu_is_omap243x())
- dm_timers[0].phys_base = 0x49018000;
+ ioarea = request_mem_region(mem->start, resource_size(mem),
+ pdev->name);
+ if (!ioarea) {
+ dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
+ return -EBUSY;
+ }
- for (i = 0; i < dm_timer_count; i++) {
- timer = &dm_timers[i];
+ timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
+ if (!timer) {
+ dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_free_ioregion;
+ }
- /* Static mapping, never released */
- timer->io_base = ioremap(timer->phys_base, map_size);
- BUG_ON(!timer->io_base);
+ timer->io_base = ioremap(mem->start, resource_size(mem));
+ if (!timer->io_base) {
+ dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
+ ret = -ENOMEM;
+ goto err_free_mem;
+ }
-#ifdef CONFIG_ARCH_OMAP2PLUS
- if (cpu_class_is_omap2()) {
- char clk_name[16];
- sprintf(clk_name, "gpt%d_ick", i + 1);
- timer->iclk = clk_get(NULL, clk_name);
- sprintf(clk_name, "gpt%d_fck", i + 1);
- timer->fclk = clk_get(NULL, clk_name);
- }
+ timer->id = pdev->id;
+ timer->irq = irq->start;
+ timer->reserved = pdata->reserved;
+ timer->pdev = pdev;
+ timer->loses_context = pdata->loses_context;
+ timer->get_context_loss_count = pdata->get_context_loss_count;
+
+ /* Skip pm_runtime_enable for OMAP1 */
+ if (!pdata->needs_manual_reset) {
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_irq_safe(&pdev->dev);
+ }
- /* One or two timers may be set up early for sys_timer */
- if (sys_timer_reserved & (1 << i)) {
- timer->reserved = 1;
- timer->posted = 1;
- }
-#endif
+ if (!timer->reserved) {
+ pm_runtime_get_sync(&pdev->dev);
+ __omap_dm_timer_init_regs(timer);
+ pm_runtime_put(&pdev->dev);
}
+ /* add the timer element to the list */
+ spin_lock_irqsave(&dm_timer_lock, flags);
+ list_add_tail(&timer->node, &omap_timer_list);
+ spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+ dev_dbg(&pdev->dev, "Device Probed.\n");
+
return 0;
+
+err_free_mem:
+ kfree(timer);
+
+err_free_ioregion:
+ release_mem_region(mem->start, resource_size(mem));
+
+ return ret;
}
-arch_initcall(omap_dm_timer_init);
+/**
+ * omap_dm_timer_remove - cleanup a registered timer device
+ * @pdev: pointer to current timer platform device
+ *
+ * Called by driver framework whenever a timer device is unregistered.
+ * In addition to freeing platform resources it also deletes the timer
+ * entry from the local list.
+ */
+static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
+{
+ struct omap_dm_timer *timer;
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ spin_lock_irqsave(&dm_timer_lock, flags);
+ list_for_each_entry(timer, &omap_timer_list, node)
+ if (timer->pdev->id == pdev->id) {
+ list_del(&timer->node);
+ kfree(timer);
+ ret = 0;
+ break;
+ }
+ spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+ return ret;
+}
+
+static struct platform_driver omap_dm_timer_driver = {
+ .probe = omap_dm_timer_probe,
+ .remove = __devexit_p(omap_dm_timer_remove),
+ .driver = {
+ .name = "omap_timer",
+ },
+};
+
+static int __init omap_dm_timer_driver_init(void)
+{
+ return platform_driver_register(&omap_dm_timer_driver);
+}
+
+static void __exit omap_dm_timer_driver_exit(void)
+{
+ platform_driver_unregister(&omap_dm_timer_driver);
+}
+
+early_platform_init("earlytimer", &omap_dm_timer_driver);
+module_init(omap_dm_timer_driver_init);
+module_exit(omap_dm_timer_driver_exit);
+
+MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 3341ca4703e9..679cbd49c019 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -108,6 +108,22 @@ static inline int omap1_i2c_add_bus(int bus_id)
res[1].start = INT_I2C;
pdata = &i2c_pdata[bus_id - 1];
+ /* all OMAP1 have IP version 1 register set */
+ pdata->rev = OMAP_I2C_IP_VERSION_1;
+
+ /* all OMAP1 I2C are implemented like this */
+ pdata->flags = OMAP_I2C_FLAG_NO_FIFO |
+ OMAP_I2C_FLAG_SIMPLE_CLOCK |
+ OMAP_I2C_FLAG_16BIT_DATA_REG |
+ OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK;
+
+ /* how the cpu bus is wired up differs for 7xx only */
+
+ if (cpu_is_omap7xx())
+ pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_1;
+ else
+ pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2;
+
return platform_device_register(pdev);
}
@@ -123,21 +139,14 @@ static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
omap_pm_set_max_mpu_wakeup_lat(dev, t);
}
-static struct omap_device_pm_latency omap_i2c_latency[] = {
- [0] = {
- .deactivate_func = omap_device_idle_hwmods,
- .activate_func = omap_device_enable_hwmods,
- .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
- },
-};
-
static inline int omap2_i2c_add_bus(int bus_id)
{
int l;
struct omap_hwmod *oh;
- struct omap_device *od;
+ struct platform_device *pdev;
char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN];
struct omap_i2c_bus_platform_data *pdata;
+ struct omap_i2c_dev_attr *dev_attr;
omap2_i2c_mux_pins(bus_id);
@@ -152,6 +161,16 @@ static inline int omap2_i2c_add_bus(int bus_id)
pdata = &i2c_pdata[bus_id - 1];
/*
+ * pass the hwmod class's CPU-specific knowledge of I2C IP revision in
+ * use, and functionality implementation flags, up to the OMAP I2C
+ * driver via platform data
+ */
+ pdata->rev = oh->class->rev;
+
+ dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
+ pdata->flags = dev_attr->flags;
+
+ /*
* When waiting for completion of a i2c transfer, we need to
* set a wake up latency constraint for the MPU. This is to
* ensure quick enough wakeup from idle, when transfer
@@ -160,12 +179,12 @@ static inline int omap2_i2c_add_bus(int bus_id)
*/
if (cpu_is_omap34xx())
pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
- od = omap_device_build(name, bus_id, oh, pdata,
+ pdev = omap_device_build(name, bus_id, oh, pdata,
sizeof(struct omap_i2c_bus_platform_data),
- omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0);
- WARN(IS_ERR(od), "Could not build omap_device for %s\n", name);
+ NULL, 0, 0);
+ WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
- return PTR_ERR(od);
+ return PTR_ERR(pdev);
}
#else
static inline int omap2_i2c_add_bus(int bus_id)
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index df4b9683f17f..197ca03c3f7d 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -80,8 +80,6 @@ struct clkops {
*
* @div is the divisor that should be applied to the parent clock's rate
* to produce the current clock's rate.
- *
- * XXX @flags probably should be replaced with an struct omap_chip.
*/
struct clksel_rate {
u32 val;
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index 4564cc697d7f..c50df4814f6f 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -45,6 +45,18 @@ extern unsigned long long notrace omap_32k_sched_clock(void);
extern void omap_reserve(void);
+void omap2420_init_early(void);
+void omap2430_init_early(void);
+void omap3430_init_early(void);
+void omap35xx_init_early(void);
+void omap3630_init_early(void);
+void omap3_init_early(void); /* Do not use this one */
+void am35xx_init_early(void);
+void ti816x_init_early(void);
+void omap4430_init_early(void);
+
+void omap_sram_init(void);
+
/*
* IO bases for various OMAP processors
* Except the tap base, rest all the io bases
@@ -53,13 +65,13 @@ extern void omap_reserve(void);
struct omap_globals {
u32 class; /* OMAP class to detect */
void __iomem *tap; /* Control module ID code */
- unsigned long sdrc; /* SDRAM Controller */
- unsigned long sms; /* SDRAM Memory Scheduler */
- unsigned long ctrl; /* System Control Module */
- unsigned long ctrl_pad; /* PAD Control Module */
- unsigned long prm; /* Power and Reset Management */
- unsigned long cm; /* Clock Management */
- unsigned long cm2;
+ void __iomem *sdrc; /* SDRAM Controller */
+ void __iomem *sms; /* SDRAM Memory Scheduler */
+ void __iomem *ctrl; /* System Control Module */
+ void __iomem *ctrl_pad; /* PAD Control Module */
+ void __iomem *prm; /* Power and Reset Management */
+ void __iomem *cm; /* Clock Management */
+ void __iomem *cm2;
};
void omap2_set_globals_242x(void);
@@ -74,7 +86,11 @@ void omap2_set_globals_sdrc(struct omap_globals *);
void omap2_set_globals_control(struct omap_globals *);
void omap2_set_globals_prcm(struct omap_globals *);
+void omap242x_map_io(void);
+void omap243x_map_io(void);
void omap3_map_io(void);
+void omap4_map_io(void);
+
/**
* omap_test_timeout - busy-loop, testing a condition
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 67b3d75884cd..2f9026942229 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -44,13 +44,6 @@
int omap_type(void);
-struct omap_chip_id {
- u16 oc;
- u8 type;
-};
-
-#define OMAP_CHIP_INIT(x) { .oc = x }
-
/*
* omap_rev bits:
* CPU id bits (0730, 1510, 1710, 2422...) [31:16]
@@ -60,19 +53,6 @@ struct omap_chip_id {
unsigned int omap_rev(void);
/*
- * Define CPU revision bits
- *
- * Verbose meaning of the revision bits may be different for a silicon
- * family. This difference can be handled separately.
- */
-#define OMAP_REVBITS_00 0x00
-#define OMAP_REVBITS_01 0x01
-#define OMAP_REVBITS_02 0x02
-#define OMAP_REVBITS_03 0x03
-#define OMAP_REVBITS_04 0x04
-#define OMAP_REVBITS_05 0x05
-
-/*
* Get the CPU revision for OMAP devices
*/
#define GET_OMAP_REVISION() ((omap_rev() >> 8) & 0xff)
@@ -262,7 +242,7 @@ IS_OMAP_TYPE(2422, 0x2422)
IS_OMAP_TYPE(2423, 0x2423)
IS_OMAP_TYPE(2430, 0x2430)
IS_OMAP_TYPE(3430, 0x3430)
-IS_OMAP_TYPE(3505, 0x3505)
+IS_OMAP_TYPE(3505, 0x3517)
IS_OMAP_TYPE(3517, 0x3517)
#define cpu_is_omap310() 0
@@ -354,8 +334,9 @@ IS_OMAP_TYPE(3517, 0x3517)
(!omap3_has_sgx()) && \
(omap3_has_iva()))
# define cpu_is_omap3530() (cpu_is_omap3430())
-# define cpu_is_omap3505() is_omap3505()
# define cpu_is_omap3517() is_omap3517()
+# define cpu_is_omap3505() (cpu_is_omap3517() && \
+ !omap3_has_sgx())
# undef cpu_is_omap3630
# define cpu_is_omap3630() is_omap363x()
# define cpu_is_ti816x() is_ti816x()
@@ -379,35 +360,31 @@ IS_OMAP_TYPE(3517, 0x3517)
/* Various silicon revisions for omap2 */
#define OMAP242X_CLASS 0x24200024
#define OMAP2420_REV_ES1_0 OMAP242X_CLASS
-#define OMAP2420_REV_ES2_0 (OMAP242X_CLASS | (OMAP_REVBITS_01 << 8))
+#define OMAP2420_REV_ES2_0 (OMAP242X_CLASS | (0x1 << 8))
#define OMAP243X_CLASS 0x24300024
#define OMAP2430_REV_ES1_0 OMAP243X_CLASS
#define OMAP343X_CLASS 0x34300034
#define OMAP3430_REV_ES1_0 OMAP343X_CLASS
-#define OMAP3430_REV_ES2_0 (OMAP343X_CLASS | (OMAP_REVBITS_01 << 8))
-#define OMAP3430_REV_ES2_1 (OMAP343X_CLASS | (OMAP_REVBITS_02 << 8))
-#define OMAP3430_REV_ES3_0 (OMAP343X_CLASS | (OMAP_REVBITS_03 << 8))
-#define OMAP3430_REV_ES3_1 (OMAP343X_CLASS | (OMAP_REVBITS_04 << 8))
-#define OMAP3430_REV_ES3_1_2 (OMAP343X_CLASS | (OMAP_REVBITS_05 << 8))
+#define OMAP3430_REV_ES2_0 (OMAP343X_CLASS | (0x1 << 8))
+#define OMAP3430_REV_ES2_1 (OMAP343X_CLASS | (0x2 << 8))
+#define OMAP3430_REV_ES3_0 (OMAP343X_CLASS | (0x3 << 8))
+#define OMAP3430_REV_ES3_1 (OMAP343X_CLASS | (0x4 << 8))
+#define OMAP3430_REV_ES3_1_2 (OMAP343X_CLASS | (0x5 << 8))
#define OMAP363X_CLASS 0x36300034
#define OMAP3630_REV_ES1_0 OMAP363X_CLASS
-#define OMAP3630_REV_ES1_1 (OMAP363X_CLASS | (OMAP_REVBITS_01 << 8))
-#define OMAP3630_REV_ES1_2 (OMAP363X_CLASS | (OMAP_REVBITS_02 << 8))
+#define OMAP3630_REV_ES1_1 (OMAP363X_CLASS | (0x1 << 8))
+#define OMAP3630_REV_ES1_2 (OMAP363X_CLASS | (0x2 << 8))
-#define OMAP35XX_CLASS 0x35000034
-#define OMAP3503_REV(v) (OMAP35XX_CLASS | (0x3503 << 16) | (v << 8))
-#define OMAP3515_REV(v) (OMAP35XX_CLASS | (0x3515 << 16) | (v << 8))
-#define OMAP3525_REV(v) (OMAP35XX_CLASS | (0x3525 << 16) | (v << 8))
-#define OMAP3530_REV(v) (OMAP35XX_CLASS | (0x3530 << 16) | (v << 8))
-#define OMAP3505_REV(v) (OMAP35XX_CLASS | (0x3505 << 16) | (v << 8))
-#define OMAP3517_REV(v) (OMAP35XX_CLASS | (0x3517 << 16) | (v << 8))
+#define OMAP3517_CLASS 0x35170034
+#define OMAP3517_REV_ES1_0 OMAP3517_CLASS
+#define OMAP3517_REV_ES1_1 (OMAP3517_CLASS | (0x1 << 8))
#define TI816X_CLASS 0x81600034
#define TI8168_REV_ES1_0 TI816X_CLASS
-#define TI8168_REV_ES1_1 (TI816X_CLASS | (OMAP_REVBITS_01 << 8))
+#define TI8168_REV_ES1_1 (TI816X_CLASS | (0x1 << 8))
#define OMAP443X_CLASS 0x44300044
#define OMAP4430_REV_ES1_0 (OMAP443X_CLASS | (0x10 << 8))
@@ -418,61 +395,6 @@ IS_OMAP_TYPE(3517, 0x3517)
#define OMAP446X_CLASS 0x44600044
#define OMAP4460_REV_ES1_0 (OMAP446X_CLASS | (0x10 << 8))
-/*
- * omap_chip bits
- *
- * CHIP_IS_OMAP{2420,2430,3430} indicate that a particular structure is
- * valid on all chips of that type. CHIP_IS_OMAP3430ES{1,2} indicates
- * something that is only valid on that particular ES revision.
- *
- * These bits may be ORed together to indicate structures that are
- * available on multiple chip types.
- *
- * To test whether a particular structure matches the current OMAP chip type,
- * use omap_chip_is().
- *
- */
-#define CHIP_IS_OMAP2420 (1 << 0)
-#define CHIP_IS_OMAP2430 (1 << 1)
-#define CHIP_IS_OMAP3430 (1 << 2)
-#define CHIP_IS_OMAP3430ES1 (1 << 3)
-#define CHIP_IS_OMAP3430ES2 (1 << 4)
-#define CHIP_IS_OMAP3430ES3_0 (1 << 5)
-#define CHIP_IS_OMAP3430ES3_1 (1 << 6)
-#define CHIP_IS_OMAP3630ES1 (1 << 7)
-#define CHIP_IS_OMAP4430ES1 (1 << 8)
-#define CHIP_IS_OMAP3630ES1_1 (1 << 9)
-#define CHIP_IS_OMAP3630ES1_2 (1 << 10)
-#define CHIP_IS_OMAP4430ES2 (1 << 11)
-#define CHIP_IS_OMAP4430ES2_1 (1 << 12)
-#define CHIP_IS_OMAP4430ES2_2 (1 << 13)
-#define CHIP_IS_TI816X (1 << 14)
-#define CHIP_IS_OMAP4460ES1_0 (1 << 15)
-
-#define CHIP_IS_OMAP24XX (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
-
-#define CHIP_IS_OMAP4430 (CHIP_IS_OMAP4430ES1 | \
- CHIP_IS_OMAP4430ES2 | \
- CHIP_IS_OMAP4430ES2_1 | \
- CHIP_IS_OMAP4430ES2_2 | \
- CHIP_IS_OMAP4460ES1_0)
-
-/*
- * "GE" here represents "greater than or equal to" in terms of ES
- * levels. So CHIP_GE_OMAP3430ES2 is intended to match all OMAP3430
- * chips at ES2 and beyond, but not, for example, any OMAP lines after
- * OMAP3.
- */
-#define CHIP_GE_OMAP3430ES2 (CHIP_IS_OMAP3430ES2 | \
- CHIP_IS_OMAP3430ES3_0 | \
- CHIP_GE_OMAP3430ES3_1)
-#define CHIP_GE_OMAP3430ES3_1 (CHIP_IS_OMAP3430ES3_1 | \
- CHIP_IS_OMAP3630ES1 | \
- CHIP_GE_OMAP3630ES1_1)
-#define CHIP_GE_OMAP3630ES1_1 (CHIP_IS_OMAP3630ES1_1 | \
- CHIP_IS_OMAP3630ES1_2)
-
-int omap_chip_is(struct omap_chip_id oci);
void omap2_check_revision(void);
/*
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index eb5d16c60cd9..d11025e6e7a4 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/plat-omap/include/mach/dmtimer.h
+ * arch/arm/plat-omap/include/plat/dmtimer.h
*
* OMAP Dual-Mode Timers
*
@@ -35,6 +35,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#ifndef __ASM_ARCH_DMTIMER_H
#define __ASM_ARCH_DMTIMER_H
@@ -59,12 +60,56 @@
* in OMAP4 can be distinguished.
*/
#define OMAP_TIMER_IP_VERSION_1 0x1
+
+/* timer capabilities used in hwmod database */
+#define OMAP_TIMER_SECURE 0x80000000
+#define OMAP_TIMER_ALWON 0x40000000
+#define OMAP_TIMER_HAS_PWM 0x20000000
+
+struct omap_timer_capability_dev_attr {
+ u32 timer_capability;
+};
+
struct omap_dm_timer;
struct clk;
+struct timer_regs {
+ u32 tidr;
+ u32 tiocp_cfg;
+ u32 tistat;
+ u32 tisr;
+ u32 tier;
+ u32 twer;
+ u32 tclr;
+ u32 tcrr;
+ u32 tldr;
+ u32 ttrg;
+ u32 twps;
+ u32 tmar;
+ u32 tcar1;
+ u32 tsicr;
+ u32 tcar2;
+ u32 tpir;
+ u32 tnir;
+ u32 tcvr;
+ u32 tocr;
+ u32 towr;
+};
+
+struct dmtimer_platform_data {
+ int (*set_timer_src)(struct platform_device *pdev, int source);
+ int timer_ip_version;
+ u32 needs_manual_reset:1;
+ bool reserved;
+
+ bool loses_context;
+
+ u32 (*get_context_loss_count)(struct device *dev);
+};
+
struct omap_dm_timer *omap_dm_timer_request(void);
struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
-void omap_dm_timer_free(struct omap_dm_timer *timer);
+int omap_dm_timer_free(struct omap_dm_timer *timer);
void omap_dm_timer_enable(struct omap_dm_timer *timer);
void omap_dm_timer_disable(struct omap_dm_timer *timer);
@@ -73,23 +118,23 @@ int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
-void omap_dm_timer_trigger(struct omap_dm_timer *timer);
-void omap_dm_timer_start(struct omap_dm_timer *timer);
-void omap_dm_timer_stop(struct omap_dm_timer *timer);
+int omap_dm_timer_trigger(struct omap_dm_timer *timer);
+int omap_dm_timer_start(struct omap_dm_timer *timer);
+int omap_dm_timer_stop(struct omap_dm_timer *timer);
int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
+int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
+int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
+int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
+int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
+int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
int omap_dm_timers_active(void);
@@ -98,12 +143,30 @@ int omap_dm_timers_active(void);
* used by dmtimer.c and sys_timer related code.
*/
-/* register offsets */
-#define _OMAP_TIMER_ID_OFFSET 0x00
-#define _OMAP_TIMER_OCP_CFG_OFFSET 0x10
-#define _OMAP_TIMER_SYS_STAT_OFFSET 0x14
-#define _OMAP_TIMER_STAT_OFFSET 0x18
-#define _OMAP_TIMER_INT_EN_OFFSET 0x1c
+/*
+ * The interrupt registers are different between v1 and v2 ip.
+ * These registers are offsets from timer->iobase.
+ */
+#define OMAP_TIMER_ID_OFFSET 0x00
+#define OMAP_TIMER_OCP_CFG_OFFSET 0x10
+
+#define OMAP_TIMER_V1_SYS_STAT_OFFSET 0x14
+#define OMAP_TIMER_V1_STAT_OFFSET 0x18
+#define OMAP_TIMER_V1_INT_EN_OFFSET 0x1c
+
+#define OMAP_TIMER_V2_IRQSTATUS_RAW 0x24
+#define OMAP_TIMER_V2_IRQSTATUS 0x28
+#define OMAP_TIMER_V2_IRQENABLE_SET 0x2c
+#define OMAP_TIMER_V2_IRQENABLE_CLR 0x30
+
+/*
+ * The functional registers have a different base on v1 and v2 ip.
+ * These registers are offsets from timer->func_base. The func_base
+ * is samae as io_base for v1 and io_base + 0x14 for v2 ip.
+ *
+ */
+#define OMAP_TIMER_V2_FUNC_OFFSET 0x14
+
#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20
#define _OMAP_TIMER_CTRL_OFFSET 0x24
#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
@@ -147,21 +210,6 @@ int omap_dm_timers_active(void);
/* register offsets with the write pending bit encoded */
#define WPSHIFT 16
-#define OMAP_TIMER_ID_REG (_OMAP_TIMER_ID_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_OCP_CFG_REG (_OMAP_TIMER_OCP_CFG_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_SYS_STAT_REG (_OMAP_TIMER_SYS_STAT_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_STAT_REG (_OMAP_TIMER_STAT_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_INT_EN_REG (_OMAP_TIMER_INT_EN_OFFSET \
- | (WP_NONE << WPSHIFT))
-
#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \
| (WP_NONE << WPSHIFT))
@@ -209,49 +257,88 @@ int omap_dm_timers_active(void);
struct omap_dm_timer {
unsigned long phys_base;
+ int id;
int irq;
-#ifdef CONFIG_ARCH_OMAP2PLUS
struct clk *iclk, *fclk;
-#endif
- void __iomem *io_base;
+
+ void __iomem *io_base;
+ void __iomem *sys_stat; /* TISTAT timer status */
+ void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
+ void __iomem *irq_ena; /* irq enable */
+ void __iomem *irq_dis; /* irq disable, only on v2 ip */
+ void __iomem *pend; /* write pending */
+ void __iomem *func_base; /* function register base */
+
unsigned long rate;
unsigned reserved:1;
- unsigned enabled:1;
unsigned posted:1;
+ struct timer_regs context;
+ bool loses_context;
+ int ctx_loss_count;
+ int revision;
+ struct platform_device *pdev;
+ struct list_head node;
+
+ u32 (*get_context_loss_count)(struct device *dev);
};
-extern u32 sys_timer_reserved;
-void omap_dm_timer_prepare(struct omap_dm_timer *timer);
+int omap_dm_timer_prepare(struct omap_dm_timer *timer);
-static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg,
+static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
int posted)
{
if (posted)
- while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
- & (reg >> WPSHIFT))
+ while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
cpu_relax();
- return __raw_readl(base + (reg & 0xff));
+ return __raw_readl(timer->func_base + (reg & 0xff));
}
-static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
- int posted)
+static inline void __omap_dm_timer_write(struct omap_dm_timer *timer,
+ u32 reg, u32 val, int posted)
{
if (posted)
- while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
- & (reg >> WPSHIFT))
+ while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
cpu_relax();
- __raw_writel(val, base + (reg & 0xff));
+ __raw_writel(val, timer->func_base + (reg & 0xff));
+}
+
+static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
+{
+ u32 tidr;
+
+ /* Assume v1 ip if bits [31:16] are zero */
+ tidr = __raw_readl(timer->io_base);
+ if (!(tidr >> 16)) {
+ timer->revision = 1;
+ timer->sys_stat = timer->io_base +
+ OMAP_TIMER_V1_SYS_STAT_OFFSET;
+ timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
+ timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
+ timer->irq_dis = 0;
+ timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
+ timer->func_base = timer->io_base;
+ } else {
+ timer->revision = 2;
+ timer->sys_stat = 0;
+ timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
+ timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
+ timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
+ timer->pend = timer->io_base +
+ _OMAP_TIMER_WRITE_PEND_OFFSET +
+ OMAP_TIMER_V2_FUNC_OFFSET;
+ timer->func_base = timer->io_base + OMAP_TIMER_V2_FUNC_OFFSET;
+ }
}
/* Assumes the source clock has been set by caller */
-static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
- int wakeup)
+static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
+ int autoidle, int wakeup)
{
u32 l;
- l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0);
+ l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
l |= 0x02 << 3; /* Set to smart-idle mode */
l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
@@ -261,10 +348,10 @@ static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
if (wakeup)
l |= 1 << 2;
- __omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0);
+ __raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
/* Match hardware reset default of posted mode */
- __omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG,
+ __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
OMAP_TIMER_CTRL_POSTED, 0);
}
@@ -286,18 +373,18 @@ static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
return ret;
}
-static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
- unsigned long rate)
+static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
+ int posted, unsigned long rate)
{
u32 l;
- l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+ l = __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
if (l & OMAP_TIMER_CTRL_ST) {
l &= ~0x1;
- __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, l, posted);
+ __omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, l, posted);
#ifdef CONFIG_ARCH_OMAP2PLUS
/* Readback to make sure write has completed */
- __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+ __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
/*
* Wait for functional clock period x 3.5 to make sure that
* timer is stopped
@@ -307,34 +394,34 @@ static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
}
/* Ack possibly pending interrupt */
- __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG,
- OMAP_TIMER_INT_OVERFLOW, 0);
+ __raw_writel(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat);
}
-static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
- unsigned int load, int posted)
+static inline void __omap_dm_timer_load_start(struct omap_dm_timer *timer,
+ u32 ctrl, unsigned int load,
+ int posted)
{
- __omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG, load, posted);
- __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, ctrl, posted);
+ __omap_dm_timer_write(timer, OMAP_TIMER_COUNTER_REG, load, posted);
+ __omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, ctrl, posted);
}
-static inline void __omap_dm_timer_int_enable(void __iomem *base,
+static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer,
unsigned int value)
{
- __omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG, value, 0);
- __omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
+ __raw_writel(value, timer->irq_ena);
+ __omap_dm_timer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
}
-static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base,
- int posted)
+static inline unsigned int
+__omap_dm_timer_read_counter(struct omap_dm_timer *timer, int posted)
{
- return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted);
+ return __omap_dm_timer_read(timer, OMAP_TIMER_COUNTER_REG, posted);
}
-static inline void __omap_dm_timer_write_status(void __iomem *base,
+static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer,
unsigned int value)
{
- __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0);
+ __raw_writel(value, timer->irq_stat);
}
#endif /* __ASM_ARCH_DMTIMER_H */
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index 91e8de3db085..9e86ee0aed0a 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -222,26 +222,6 @@ extern void omap_gpio_restore_context(void);
#include <linux/errno.h>
#include <asm-generic/gpio.h>
-static inline int gpio_get_value(unsigned gpio)
-{
- return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
- __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
- return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
- return __gpio_to_irq(gpio);
-}
-
static inline int irq_to_gpio(unsigned irq)
{
int tmp;
diff --git a/arch/arm/plat-omap/include/plat/io.h b/arch/arm/plat-omap/include/plat/io.h
index d72ec85c97e6..7f2969eadb85 100644
--- a/arch/arm/plat-omap/include/plat/io.h
+++ b/arch/arm/plat-omap/include/plat/io.h
@@ -228,13 +228,13 @@
#define OMAP44XX_EMIF2_PHYS OMAP44XX_EMIF2_BASE
/* 0x4d000000 --> 0xfd200000 */
-#define OMAP44XX_EMIF2_VIRT (OMAP44XX_EMIF2_PHYS + OMAP4_L3_PER_IO_OFFSET)
#define OMAP44XX_EMIF2_SIZE SZ_1M
+#define OMAP44XX_EMIF2_VIRT (OMAP44XX_EMIF1_VIRT + OMAP44XX_EMIF1_SIZE)
#define OMAP44XX_DMM_PHYS OMAP44XX_DMM_BASE
/* 0x4e000000 --> 0xfd300000 */
-#define OMAP44XX_DMM_VIRT (OMAP44XX_DMM_PHYS + OMAP4_L3_PER_IO_OFFSET)
#define OMAP44XX_DMM_SIZE SZ_1M
+#define OMAP44XX_DMM_VIRT (OMAP44XX_EMIF2_VIRT + OMAP44XX_EMIF2_SIZE)
/*
* ----------------------------------------------------------------------------
* Omap specific register access
@@ -247,6 +247,8 @@
* NOTE: Please use ioremap + __raw_read/write where possible instead of these
*/
+void omap_ioremap_init(void);
+
extern u8 omap_readb(u32 pa);
extern u16 omap_readw(u32 pa);
extern u32 omap_readl(u32 pa);
@@ -256,8 +258,31 @@ extern void omap_writel(u32 v, u32 pa);
struct omap_sdrc_params;
-extern void omap1_map_common_io(void);
-extern void omap1_init_common_hw(void);
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+void omap7xx_map_io(void);
+#else
+static inline void omap_map_io(void)
+{
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP15XX
+void omap15xx_map_io(void);
+#else
+static inline void omap15xx_map_io(void)
+{
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP16XX
+void omap16xx_map_io(void);
+#else
+static inline void omap16xx_map_io(void)
+{
+}
+#endif
+
+void omap1_init_early(void);
#ifdef CONFIG_SOC_OMAP2420
extern void omap242x_map_common_io(void);
@@ -300,7 +325,7 @@ static inline void omap44xx_map_common_io(void)
#endif
extern void omap2_init_common_infrastructure(void);
-extern void omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
+extern void omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
struct omap_sdrc_params *sdrc_cs1);
#define __arch_ioremap omap_ioremap
@@ -309,6 +334,8 @@ extern void omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);
void omap_iounmap(volatile void __iomem *addr);
+extern void __init omap_init_consistent_dma_size(void);
+
#endif
#endif
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 174f1b9c8c03..a1d79ee19250 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -25,16 +25,17 @@ struct iotlb_entry {
};
};
-struct iommu {
+struct omap_iommu {
const char *name;
struct module *owner;
struct clk *clk;
void __iomem *regbase;
struct device *dev;
void *isr_priv;
+ struct iommu_domain *domain;
unsigned int refcount;
- struct mutex iommu_lock; /* global for this whole object */
+ spinlock_t iommu_lock; /* global for this whole object */
/*
* We don't change iopgd for a situation like pgd for a task,
@@ -48,8 +49,6 @@ struct iommu {
struct list_head mmap;
struct mutex mmap_lock; /* protect mmap */
- int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, void *priv);
-
void *ctx; /* iommu context: registres saved area */
u32 da_start;
u32 da_end;
@@ -81,25 +80,27 @@ struct iotlb_lock {
struct iommu_functions {
unsigned long version;
- int (*enable)(struct iommu *obj);
- void (*disable)(struct iommu *obj);
- void (*set_twl)(struct iommu *obj, bool on);
- u32 (*fault_isr)(struct iommu *obj, u32 *ra);
+ int (*enable)(struct omap_iommu *obj);
+ void (*disable)(struct omap_iommu *obj);
+ void (*set_twl)(struct omap_iommu *obj, bool on);
+ u32 (*fault_isr)(struct omap_iommu *obj, u32 *ra);
- void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr);
- void (*tlb_load_cr)(struct iommu *obj, struct cr_regs *cr);
+ void (*tlb_read_cr)(struct omap_iommu *obj, struct cr_regs *cr);
+ void (*tlb_load_cr)(struct omap_iommu *obj, struct cr_regs *cr);
- struct cr_regs *(*alloc_cr)(struct iommu *obj, struct iotlb_entry *e);
+ struct cr_regs *(*alloc_cr)(struct omap_iommu *obj,
+ struct iotlb_entry *e);
int (*cr_valid)(struct cr_regs *cr);
u32 (*cr_to_virt)(struct cr_regs *cr);
void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e);
- ssize_t (*dump_cr)(struct iommu *obj, struct cr_regs *cr, char *buf);
+ ssize_t (*dump_cr)(struct omap_iommu *obj, struct cr_regs *cr,
+ char *buf);
u32 (*get_pte_attr)(struct iotlb_entry *e);
- void (*save_ctx)(struct iommu *obj);
- void (*restore_ctx)(struct iommu *obj);
- ssize_t (*dump_ctx)(struct iommu *obj, char *buf, ssize_t len);
+ void (*save_ctx)(struct omap_iommu *obj);
+ void (*restore_ctx)(struct omap_iommu *obj);
+ ssize_t (*dump_ctx)(struct omap_iommu *obj, char *buf, ssize_t len);
};
struct iommu_platform_data {
@@ -150,40 +151,31 @@ struct iommu_platform_data {
/*
* global functions
*/
-extern u32 iommu_arch_version(void);
-
-extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
-extern u32 iotlb_cr_to_virt(struct cr_regs *cr);
-
-extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
-extern void iommu_set_twl(struct iommu *obj, bool on);
-extern void flush_iotlb_page(struct iommu *obj, u32 da);
-extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
-extern void flush_iotlb_all(struct iommu *obj);
-
-extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
-extern void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd,
- u32 **ppte);
-extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
-
-extern int iommu_set_da_range(struct iommu *obj, u32 start, u32 end);
-extern struct iommu *iommu_get(const char *name);
-extern void iommu_put(struct iommu *obj);
-extern int iommu_set_isr(const char *name,
- int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
+extern u32 omap_iommu_arch_version(void);
+
+extern void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
+
+extern int
+omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e);
+
+extern int omap_iommu_set_isr(const char *name,
+ int (*isr)(struct omap_iommu *obj, u32 da, u32 iommu_errs,
void *priv),
void *isr_priv);
-extern void iommu_save_ctx(struct iommu *obj);
-extern void iommu_restore_ctx(struct iommu *obj);
+extern void omap_iommu_save_ctx(struct omap_iommu *obj);
+extern void omap_iommu_restore_ctx(struct omap_iommu *obj);
-extern int install_iommu_arch(const struct iommu_functions *ops);
-extern void uninstall_iommu_arch(const struct iommu_functions *ops);
+extern int omap_install_iommu_arch(const struct iommu_functions *ops);
+extern void omap_uninstall_iommu_arch(const struct iommu_functions *ops);
-extern int foreach_iommu_device(void *data,
+extern int omap_foreach_iommu_device(void *data,
int (*fn)(struct device *, void *));
-extern ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len);
-extern size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t len);
+extern ssize_t
+omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len);
+extern size_t
+omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, ssize_t len);
+struct device *omap_find_iommu_device(const char *name);
#endif /* __MACH_IOMMU_H */
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
index 10ad05f410e9..d4116b595e40 100644
--- a/arch/arm/plat-omap/include/plat/iommu2.h
+++ b/arch/arm/plat-omap/include/plat/iommu2.h
@@ -83,12 +83,12 @@
/*
* register accessors
*/
-static inline u32 iommu_read_reg(struct iommu *obj, size_t offs)
+static inline u32 iommu_read_reg(struct omap_iommu *obj, size_t offs)
{
return __raw_readl(obj->regbase + offs);
}
-static inline void iommu_write_reg(struct iommu *obj, u32 val, size_t offs)
+static inline void iommu_write_reg(struct omap_iommu *obj, u32 val, size_t offs)
{
__raw_writel(val, obj->regbase + offs);
}
diff --git a/arch/arm/plat-omap/iopgtable.h b/arch/arm/plat-omap/include/plat/iopgtable.h
index c3e93bb0911f..66a813977d52 100644
--- a/arch/arm/plat-omap/iopgtable.h
+++ b/arch/arm/plat-omap/include/plat/iopgtable.h
@@ -56,6 +56,19 @@
#define IOPAGE_MASK IOPTE_MASK
+/**
+ * omap_iommu_translate() - va to pa translation
+ * @d: omap iommu descriptor
+ * @va: virtual address
+ * @mask: omap iommu descriptor mask
+ *
+ * va to pa translation
+ */
+static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
+{
+ return (d & mask) | (va & (~mask));
+}
+
/*
* some descriptor attributes.
*/
@@ -64,10 +77,15 @@
#define IOPGD_SUPER (1 << 18 | 2 << 0)
#define iopgd_is_table(x) (((x) & 3) == IOPGD_TABLE)
+#define iopgd_is_section(x) (((x) & (1 << 18 | 3)) == IOPGD_SECTION)
+#define iopgd_is_super(x) (((x) & (1 << 18 | 3)) == IOPGD_SUPER)
#define IOPTE_SMALL (2 << 0)
#define IOPTE_LARGE (1 << 0)
+#define iopte_is_small(x) (((x) & 2) == IOPTE_SMALL)
+#define iopte_is_large(x) (((x) & 3) == IOPTE_LARGE)
+
/* to find an entry in a page-table-directory */
#define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
#define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da))
@@ -97,6 +115,6 @@ static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
}
#define to_iommu(dev) \
- (struct iommu *)platform_get_drvdata(to_platform_device(dev))
+ (struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
#endif /* __PLAT_OMAP_IOMMU_H */
diff --git a/arch/arm/plat-omap/include/plat/iovmm.h b/arch/arm/plat-omap/include/plat/iovmm.h
index e992b9655fbc..6af1a91c0f36 100644
--- a/arch/arm/plat-omap/include/plat/iovmm.h
+++ b/arch/arm/plat-omap/include/plat/iovmm.h
@@ -13,8 +13,10 @@
#ifndef __IOMMU_MMAP_H
#define __IOMMU_MMAP_H
+#include <linux/iommu.h>
+
struct iovm_struct {
- struct iommu *iommu; /* iommu object which this belongs to */
+ struct omap_iommu *iommu; /* iommu object which this belongs to */
u32 da_start; /* area definition */
u32 da_end;
u32 flags; /* IOVMF_: see below */
@@ -70,20 +72,18 @@ struct iovm_struct {
#define IOVMF_DA_FIXED (1 << (4 + IOVMF_SW_SHIFT))
-extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da);
-extern u32 iommu_vmap(struct iommu *obj, u32 da,
+extern struct iovm_struct *omap_find_iovm_area(struct omap_iommu *obj, u32 da);
+extern u32
+omap_iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj, u32 da,
const struct sg_table *sgt, u32 flags);
-extern struct sg_table *iommu_vunmap(struct iommu *obj, u32 da);
-extern u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes,
- u32 flags);
-extern void iommu_vfree(struct iommu *obj, const u32 da);
-extern u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
- u32 flags);
-extern void iommu_kunmap(struct iommu *obj, u32 da);
-extern u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes,
- u32 flags);
-extern void iommu_kfree(struct iommu *obj, u32 da);
-
-extern void *da_to_va(struct iommu *obj, u32 da);
+extern struct sg_table *omap_iommu_vunmap(struct iommu_domain *domain,
+ struct omap_iommu *obj, u32 da);
+extern u32
+omap_iommu_vmalloc(struct iommu_domain *domain, struct omap_iommu *obj,
+ u32 da, size_t bytes, u32 flags);
+extern void
+omap_iommu_vfree(struct iommu_domain *domain, struct omap_iommu *obj,
+ const u32 da);
+extern void *omap_da_to_va(struct omap_iommu *obj, u32 da);
#endif /* __IOMMU_MMAP_H */
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index 9882c657b2d4..8fa74e2c9d6e 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -25,9 +25,7 @@
#define __ASM_ARCH_OMAP_MCBSP_H
#include <linux/spinlock.h>
-
-#include <mach/hardware.h>
-#include <plat/clock.h>
+#include <linux/clk.h>
/* macro for building platform_device for McBSP ports */
#define OMAP_MCBSP_PLATFORM_DEVICE(port_nr) \
@@ -40,104 +38,60 @@ static struct platform_device omap_mcbsp##port_nr = { \
#define MCBSP_CONFIG_TYPE3 0x3
#define MCBSP_CONFIG_TYPE4 0x4
-#define OMAP7XX_MCBSP1_BASE 0xfffb1000
-#define OMAP7XX_MCBSP2_BASE 0xfffb1800
-
-#define OMAP1510_MCBSP1_BASE 0xe1011800
-#define OMAP1510_MCBSP2_BASE 0xfffb1000
-#define OMAP1510_MCBSP3_BASE 0xe1017000
-
-#define OMAP1610_MCBSP1_BASE 0xe1011800
-#define OMAP1610_MCBSP2_BASE 0xfffb1000
-#define OMAP1610_MCBSP3_BASE 0xe1017000
-
-#ifdef CONFIG_ARCH_OMAP1
-
-#define OMAP_MCBSP_REG_DRR2 0x00
-#define OMAP_MCBSP_REG_DRR1 0x02
-#define OMAP_MCBSP_REG_DXR2 0x04
-#define OMAP_MCBSP_REG_DXR1 0x06
-#define OMAP_MCBSP_REG_DRR 0x02
-#define OMAP_MCBSP_REG_DXR 0x06
-#define OMAP_MCBSP_REG_SPCR2 0x08
-#define OMAP_MCBSP_REG_SPCR1 0x0a
-#define OMAP_MCBSP_REG_RCR2 0x0c
-#define OMAP_MCBSP_REG_RCR1 0x0e
-#define OMAP_MCBSP_REG_XCR2 0x10
-#define OMAP_MCBSP_REG_XCR1 0x12
-#define OMAP_MCBSP_REG_SRGR2 0x14
-#define OMAP_MCBSP_REG_SRGR1 0x16
-#define OMAP_MCBSP_REG_MCR2 0x18
-#define OMAP_MCBSP_REG_MCR1 0x1a
-#define OMAP_MCBSP_REG_RCERA 0x1c
-#define OMAP_MCBSP_REG_RCERB 0x1e
-#define OMAP_MCBSP_REG_XCERA 0x20
-#define OMAP_MCBSP_REG_XCERB 0x22
-#define OMAP_MCBSP_REG_PCR0 0x24
-#define OMAP_MCBSP_REG_RCERC 0x26
-#define OMAP_MCBSP_REG_RCERD 0x28
-#define OMAP_MCBSP_REG_XCERC 0x2A
-#define OMAP_MCBSP_REG_XCERD 0x2C
-#define OMAP_MCBSP_REG_RCERE 0x2E
-#define OMAP_MCBSP_REG_RCERF 0x30
-#define OMAP_MCBSP_REG_XCERE 0x32
-#define OMAP_MCBSP_REG_XCERF 0x34
-#define OMAP_MCBSP_REG_RCERG 0x36
-#define OMAP_MCBSP_REG_RCERH 0x38
-#define OMAP_MCBSP_REG_XCERG 0x3A
-#define OMAP_MCBSP_REG_XCERH 0x3C
-
-/* Dummy defines, these are not available on omap1 */
-#define OMAP_MCBSP_REG_XCCR 0x00
-#define OMAP_MCBSP_REG_RCCR 0x00
-
-#else
-
-#define OMAP_MCBSP_REG_DRR2 0x00
-#define OMAP_MCBSP_REG_DRR1 0x04
-#define OMAP_MCBSP_REG_DXR2 0x08
-#define OMAP_MCBSP_REG_DXR1 0x0C
-#define OMAP_MCBSP_REG_DRR 0x00
-#define OMAP_MCBSP_REG_DXR 0x08
-#define OMAP_MCBSP_REG_SPCR2 0x10
-#define OMAP_MCBSP_REG_SPCR1 0x14
-#define OMAP_MCBSP_REG_RCR2 0x18
-#define OMAP_MCBSP_REG_RCR1 0x1C
-#define OMAP_MCBSP_REG_XCR2 0x20
-#define OMAP_MCBSP_REG_XCR1 0x24
-#define OMAP_MCBSP_REG_SRGR2 0x28
-#define OMAP_MCBSP_REG_SRGR1 0x2C
-#define OMAP_MCBSP_REG_MCR2 0x30
-#define OMAP_MCBSP_REG_MCR1 0x34
-#define OMAP_MCBSP_REG_RCERA 0x38
-#define OMAP_MCBSP_REG_RCERB 0x3C
-#define OMAP_MCBSP_REG_XCERA 0x40
-#define OMAP_MCBSP_REG_XCERB 0x44
-#define OMAP_MCBSP_REG_PCR0 0x48
-#define OMAP_MCBSP_REG_RCERC 0x4C
-#define OMAP_MCBSP_REG_RCERD 0x50
-#define OMAP_MCBSP_REG_XCERC 0x54
-#define OMAP_MCBSP_REG_XCERD 0x58
-#define OMAP_MCBSP_REG_RCERE 0x5C
-#define OMAP_MCBSP_REG_RCERF 0x60
-#define OMAP_MCBSP_REG_XCERE 0x64
-#define OMAP_MCBSP_REG_XCERF 0x68
-#define OMAP_MCBSP_REG_RCERG 0x6C
-#define OMAP_MCBSP_REG_RCERH 0x70
-#define OMAP_MCBSP_REG_XCERG 0x74
-#define OMAP_MCBSP_REG_XCERH 0x78
-#define OMAP_MCBSP_REG_SYSCON 0x8C
-#define OMAP_MCBSP_REG_THRSH2 0x90
-#define OMAP_MCBSP_REG_THRSH1 0x94
-#define OMAP_MCBSP_REG_IRQST 0xA0
-#define OMAP_MCBSP_REG_IRQEN 0xA4
-#define OMAP_MCBSP_REG_WAKEUPEN 0xA8
-#define OMAP_MCBSP_REG_XCCR 0xAC
-#define OMAP_MCBSP_REG_RCCR 0xB0
-#define OMAP_MCBSP_REG_XBUFFSTAT 0xB4
-#define OMAP_MCBSP_REG_RBUFFSTAT 0xB8
-#define OMAP_MCBSP_REG_SSELCR 0xBC
+/* McBSP register numbers. Register address offset = num * reg_step */
+enum {
+ /* Common registers */
+ OMAP_MCBSP_REG_SPCR2 = 4,
+ OMAP_MCBSP_REG_SPCR1,
+ OMAP_MCBSP_REG_RCR2,
+ OMAP_MCBSP_REG_RCR1,
+ OMAP_MCBSP_REG_XCR2,
+ OMAP_MCBSP_REG_XCR1,
+ OMAP_MCBSP_REG_SRGR2,
+ OMAP_MCBSP_REG_SRGR1,
+ OMAP_MCBSP_REG_MCR2,
+ OMAP_MCBSP_REG_MCR1,
+ OMAP_MCBSP_REG_RCERA,
+ OMAP_MCBSP_REG_RCERB,
+ OMAP_MCBSP_REG_XCERA,
+ OMAP_MCBSP_REG_XCERB,
+ OMAP_MCBSP_REG_PCR0,
+ OMAP_MCBSP_REG_RCERC,
+ OMAP_MCBSP_REG_RCERD,
+ OMAP_MCBSP_REG_XCERC,
+ OMAP_MCBSP_REG_XCERD,
+ OMAP_MCBSP_REG_RCERE,
+ OMAP_MCBSP_REG_RCERF,
+ OMAP_MCBSP_REG_XCERE,
+ OMAP_MCBSP_REG_XCERF,
+ OMAP_MCBSP_REG_RCERG,
+ OMAP_MCBSP_REG_RCERH,
+ OMAP_MCBSP_REG_XCERG,
+ OMAP_MCBSP_REG_XCERH,
+
+ /* OMAP1-OMAP2420 registers */
+ OMAP_MCBSP_REG_DRR2 = 0,
+ OMAP_MCBSP_REG_DRR1,
+ OMAP_MCBSP_REG_DXR2,
+ OMAP_MCBSP_REG_DXR1,
+
+ /* OMAP2430 and onwards */
+ OMAP_MCBSP_REG_DRR = 0,
+ OMAP_MCBSP_REG_DXR = 2,
+ OMAP_MCBSP_REG_SYSCON = 35,
+ OMAP_MCBSP_REG_THRSH2,
+ OMAP_MCBSP_REG_THRSH1,
+ OMAP_MCBSP_REG_IRQST = 40,
+ OMAP_MCBSP_REG_IRQEN,
+ OMAP_MCBSP_REG_WAKEUPEN,
+ OMAP_MCBSP_REG_XCCR,
+ OMAP_MCBSP_REG_RCCR,
+ OMAP_MCBSP_REG_XBUFFSTAT,
+ OMAP_MCBSP_REG_RBUFFSTAT,
+ OMAP_MCBSP_REG_SSELCR,
+};
+/* OMAP3 sidetone control registers */
#define OMAP_ST_REG_REV 0x00
#define OMAP_ST_REG_SYSCONFIG 0x10
#define OMAP_ST_REG_IRQSTATUS 0x18
@@ -146,8 +100,6 @@ static struct platform_device omap_mcbsp##port_nr = { \
#define OMAP_ST_REG_SFIRCR 0x28
#define OMAP_ST_REG_SSELCR 0x2C
-#endif
-
/************************** McBSP SPCR1 bit definitions ***********************/
#define RRST 0x0001
#define RRDY 0x0002
@@ -344,20 +296,20 @@ typedef enum {
struct omap_mcbsp_ops {
void (*request)(unsigned int);
void (*free)(unsigned int);
- int (*set_clks_src)(u8, u8);
};
struct omap_mcbsp_platform_data {
- unsigned long phys_base;
- u8 dma_rx_sync, dma_tx_sync;
- u16 rx_irq, tx_irq;
struct omap_mcbsp_ops *ops;
-#ifdef CONFIG_ARCH_OMAP3
- /* Sidetone block for McBSP 2 and 3 */
- unsigned long phys_base_st;
-#endif
u16 buffer_size;
- unsigned int mcbsp_config_type;
+ u8 reg_size;
+ u8 reg_step;
+
+ /* McBSP platform and instance specific features */
+ bool has_wakeup; /* Wakeup capability */
+ bool has_ccr; /* Transceiver has configuration control registers */
+ int (*enable_st_clock)(unsigned int, bool);
+ int (*set_clk_src)(struct device *dev, struct clk *clk, const char *src);
+ int (*mux_signal)(struct device *dev, const char *signal, const char *src);
};
struct omap_mcbsp_st_data {
@@ -389,14 +341,12 @@ struct omap_mcbsp {
spinlock_t lock;
struct omap_mcbsp_platform_data *pdata;
struct clk *fclk;
-#ifdef CONFIG_ARCH_OMAP3
struct omap_mcbsp_st_data *st_data;
int dma_op_mode;
u16 max_tx_thres;
u16 max_rx_thres;
-#endif
void *reg_cache;
- unsigned int mcbsp_config_type;
+ int reg_cache_size;
};
/**
@@ -408,16 +358,10 @@ struct omap_mcbsp_dev_attr {
};
extern struct omap_mcbsp **mcbsp_ptr;
-extern int omap_mcbsp_count, omap_mcbsp_cache_size;
-
-#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count)
-#define id_to_mcbsp_ptr(id) mcbsp_ptr[id];
+extern int omap_mcbsp_count;
int omap_mcbsp_init(void);
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
- struct omap_mcbsp_platform_data *config, int size);
void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
-#ifdef CONFIG_ARCH_OMAP3
void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
@@ -426,18 +370,6 @@ u16 omap_mcbsp_get_fifo_size(unsigned int id);
u16 omap_mcbsp_get_tx_delay(unsigned int id);
u16 omap_mcbsp_get_rx_delay(unsigned int id);
int omap_mcbsp_get_dma_op_mode(unsigned int id);
-#else
-static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
-{ }
-static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
-{ }
-static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_fifo_size(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_tx_delay(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_rx_delay(unsigned int id) { return 0; }
-static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; }
-#endif
int omap_mcbsp_request(unsigned int id);
void omap_mcbsp_free(unsigned int id);
void omap_mcbsp_start(unsigned int id, int tx, int rx);
@@ -453,21 +385,11 @@ void omap2_mcbsp1_mux_fsr_src(u8 mux);
int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream);
int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream);
-#ifdef CONFIG_ARCH_OMAP3
/* Sidetone specific API */
int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain);
int omap_st_enable(unsigned int id);
int omap_st_disable(unsigned int id);
int omap_st_is_enabled(unsigned int id);
-#else
-static inline int omap_st_set_chgain(unsigned int id, int channel,
- s16 chgain) { return 0; }
-static inline int omap_st_get_chgain(unsigned int id, int channel,
- s16 *chgain) { return 0; }
-static inline int omap_st_enable(unsigned int id) { return 0; }
-static inline int omap_st_disable(unsigned int id) { return 0; }
-static inline int omap_st_is_enabled(unsigned int id) { return 0; }
-#endif
#endif
diff --git a/arch/arm/plat-omap/include/plat/memory.h b/arch/arm/plat-omap/include/plat/memory.h
deleted file mode 100644
index e6720aa2d553..000000000000
--- a/arch/arm/plat-omap/include/plat/memory.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/memory.h
- *
- * Memory map for OMAP-1510 and 1610
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: Greg Lonnon <glonnon@ridgerun.com>
- *
- * This file was derived from arch/arm/mach-intergrator/include/mach/memory.h
- * Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``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 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.
- *
- * You 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.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#if defined(CONFIG_ARCH_OMAP1)
-#define PLAT_PHYS_OFFSET UL(0x10000000)
-#else
-#define PLAT_PHYS_OFFSET UL(0x80000000)
-#endif
-
-/*
- * Bus address is physical address, except for OMAP-1510 Local Bus.
- * OMAP-1510 bus address is translated into a Local Bus address if the
- * OMAP bus type is lbus. We do the address translation based on the
- * device overriding the defaults used in the dma-mapping API.
- * Note that the is_lbus_device() test is not very efficient on 1510
- * because of the strncmp().
- */
-#ifdef CONFIG_ARCH_OMAP15XX
-
-/*
- * OMAP-1510 Local Bus address offset
- */
-#define OMAP1510_LB_OFFSET UL(0x30000000)
-
-#define virt_to_lbus(x) ((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
-#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
-#define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
-
-#define __arch_pfn_to_dma(dev, pfn) \
- ({ dma_addr_t __dma = __pfn_to_phys(pfn); \
- if (is_lbus_device(dev)) \
- __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
- __dma; })
-
-#define __arch_dma_to_pfn(dev, addr) \
- ({ dma_addr_t __dma = addr; \
- if (is_lbus_device(dev)) \
- __dma += PHYS_OFFSET - OMAP1510_LB_OFFSET; \
- __phys_to_pfn(__dma); \
- })
-
-#define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \
- lbus_to_virt(addr) : \
- __phys_to_virt(addr)); })
-
-#define __arch_virt_to_dma(dev, addr) ({ unsigned long __addr = (unsigned long)(addr); \
- (dma_addr_t) (is_lbus_device(dev) ? \
- virt_to_lbus(__addr) : \
- __virt_to_phys(__addr)); })
-
-#endif /* CONFIG_ARCH_OMAP15XX */
-
-/* Override the ARM default */
-#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
-
-#if (CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE == 0)
-#undef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
-#define CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE 2
-#endif
-
-#define CONSISTENT_DMA_SIZE \
- (((CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE + 1) & ~1) * 1024 * 1024)
-
-#endif
-
-#endif
-
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index c7b874186c27..94cf70afb236 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -31,7 +31,24 @@
#define OMAP_MMC_MAX_SLOTS 2
-#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(1)
+/*
+ * struct omap_mmc_dev_attr.flags possibilities
+ *
+ * OMAP_HSMMC_SUPPORTS_DUAL_VOLT: Some HSMMC controller instances can
+ * operate with either 1.8Vdc or 3.0Vdc card voltages; this flag
+ * should be set if this is the case. See for example Section 22.5.3
+ * "MMC/SD/SDIO1 Bus Voltage Selection" of the OMAP34xx Multimedia
+ * Device Silicon Revision 3.1.x Revision ZR (July 2011) (SWPU223R).
+ *
+ * OMAP_HSMMC_BROKEN_MULTIBLOCK_READ: Multiple-block read transfers
+ * don't work correctly on some MMC controller instances on some
+ * OMAP3 SoCs; this flag should be set if this is the case. See
+ * for example Advisory 2.1.1.128 "MMC: Multiple Block Read
+ * Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
+ * Revision F (October 2010) (SPRZ278F).
+ */
+#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(0)
+#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ BIT(1)
struct omap_mmc_dev_attr {
u8 flags;
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index ee405b36df4b..12c5b0c345bf 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -68,7 +68,7 @@ extern struct device omap_device_parent;
*
*/
struct omap_device {
- struct platform_device pdev;
+ struct platform_device *pdev;
struct omap_hwmod **hwmods;
struct omap_device_pm_latency *pm_lats;
u32 dev_wakeup_lat;
@@ -88,25 +88,20 @@ int omap_device_shutdown(struct platform_device *pdev);
/* Core code interface */
-int omap_device_count_resources(struct omap_device *od);
-int omap_device_fill_resources(struct omap_device *od, struct resource *res);
-
-struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
struct omap_hwmod *oh, void *pdata,
int pdata_len,
struct omap_device_pm_latency *pm_lats,
int pm_lats_cnt, int is_early_device);
-struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
struct omap_hwmod **oh, int oh_cnt,
void *pdata, int pdata_len,
struct omap_device_pm_latency *pm_lats,
int pm_lats_cnt, int is_early_device);
-int omap_device_register(struct omap_device *od);
-int omap_early_device_register(struct omap_device *od);
-
void __iomem *omap_device_get_rt_va(struct omap_device *od);
+struct device *omap_device_get_by_hwmod_name(const char *oh_name);
/* OMAP PM interface */
int omap_device_align_pm_lat(struct platform_device *pdev,
@@ -122,11 +117,6 @@ int omap_device_enable_hwmods(struct omap_device *od);
int omap_device_disable_clocks(struct omap_device *od);
int omap_device_enable_clocks(struct omap_device *od);
-static inline void omap_device_disable_idle_on_suspend(struct omap_device *od)
-{
- od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
-}
-
/*
* Entries should be kept in latency order ascending
*
@@ -157,6 +147,17 @@ struct omap_device_pm_latency {
#define OMAP_DEVICE_LATENCY_AUTO_ADJUST BIT(1)
/* Get omap_device pointer from platform_device pointer */
-#define to_omap_device(x) container_of((x), struct omap_device, pdev)
+static inline struct omap_device *to_omap_device(struct platform_device *pdev)
+{
+ return pdev ? pdev->archdata.od : NULL;
+}
+
+static inline
+void omap_device_disable_idle_on_suspend(struct platform_device *pdev)
+{
+ struct omap_device *od = to_omap_device(pdev);
+
+ od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
+}
#endif
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 0e329ca88a70..5419f1a2aaa4 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -496,7 +496,6 @@ struct omap_hwmod_class {
* @_state: internal-use hwmod state
* @_postsetup_state: internal-use state to leave the hwmod in after _setup()
* @flags: hwmod flags (documented below)
- * @omap_chip: OMAP chips this hwmod is present on
* @_lock: spinlock serializing operations on this hwmod
* @node: list node for hwmod list (internal use)
*
@@ -526,7 +525,6 @@ struct omap_hwmod {
char *clkdm_name;
struct clockdomain *clkdm;
char *vdd_name;
- struct voltagedomain *voltdm;
struct omap_hwmod_ocp_if **masters; /* connect to *_IA */
struct omap_hwmod_ocp_if **slaves; /* connect to *_TA */
void *dev_attr;
@@ -545,7 +543,6 @@ struct omap_hwmod {
u8 _int_flags;
u8 _state;
u8 _postsetup_state;
- const struct omap_chip_id omap_chip;
};
int omap_hwmod_register(struct omap_hwmod **ohs);
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index de3b10c18127..1ab9fd6abe6d 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -16,8 +16,8 @@
#include <linux/init.h>
/*
- * Memory entry used for the DEBUG_LL UART configuration. See also
- * uncompress.h and debug-macro.S.
+ * Memory entry used for the DEBUG_LL UART configuration, relative to
+ * start of RAM. See also uncompress.h and debug-macro.S.
*
* Note that using a memory location for storing the UART configuration
* has at least two limitations:
@@ -27,7 +27,7 @@
* 2. We assume printascii is called at least once before paging_init,
* and addruart has a chance to read OMAP_UART_INFO
*/
-#define OMAP_UART_INFO (PLAT_PHYS_OFFSET + 0x3ffc)
+#define OMAP_UART_INFO_OFS 0x3ffc
/* OMAP1 serial ports */
#define OMAP1_UART1_BASE 0xfffb0000
diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
index a067484cc4a2..2f472e989ec6 100644
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ b/arch/arm/plat-omap/include/plat/uncompress.h
@@ -36,7 +36,13 @@ int uart_shift;
*/
static void set_omap_uart_info(unsigned char port)
{
- *(volatile u32 *)OMAP_UART_INFO = port;
+ /*
+ * Get address of some.bss variable and round it down
+ * a la CONFIG_AUTO_ZRELADDR.
+ */
+ u32 ram_start = (u32)&uart_shift & 0xf8000000;
+ u32 *uart_info = (u32 *)(ram_start + OMAP_UART_INFO_OFS);
+ *uart_info = port;
}
static void putc(int c)
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
new file mode 100644
index 000000000000..0a6a482ec014
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -0,0 +1,20 @@
+/*
+ * OMAP Voltage Management Routines
+ *
+ * Copyright (C) 2011, Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_OMAP_VOLTAGE_H
+#define __ARCH_ARM_OMAP_VOLTAGE_H
+
+struct voltagedomain;
+
+struct voltagedomain *voltdm_lookup(const char *name);
+int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
+
+#endif
diff --git a/arch/arm/plat-omap/io.c b/arch/arm/plat-omap/io.c
index f1ecfa9fc61d..333871f59995 100644
--- a/arch/arm/plat-omap/io.c
+++ b/arch/arm/plat-omap/io.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/mm.h>
+#include <linux/dma-mapping.h>
#include <plat/omap7xx.h>
#include <plat/omap1510.h>
@@ -23,11 +24,16 @@
#define BETWEEN(p,st,sz) ((p) >= (st) && (p) < ((st) + (sz)))
#define XLATE(p,pst,vst) ((void __iomem *)((p) - (pst) + (vst)))
+static int initialized;
+
/*
* Intercept ioremap() requests for addresses in our fixed mapping regions.
*/
void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type)
{
+
+ WARN(!initialized, "Do not use ioremap before init_early\n");
+
#ifdef CONFIG_ARCH_OMAP1
if (cpu_class_is_omap1()) {
if (BETWEEN(p, OMAP1_IO_PHYS, OMAP1_IO_SIZE))
@@ -139,3 +145,15 @@ void omap_iounmap(volatile void __iomem *addr)
__iounmap(addr);
}
EXPORT_SYMBOL(omap_iounmap);
+
+void __init omap_init_consistent_dma_size(void)
+{
+#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
+ init_consistent_dma_size(CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE << 20);
+#endif
+}
+
+void __init omap_ioremap_init(void)
+{
+ initialized++;
+}
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 6c62af108710..4b15cd7926d7 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -24,45 +24,40 @@
#include <linux/slab.h>
#include <plat/mcbsp.h>
-#include <plat/omap_device.h>
#include <linux/pm_runtime.h>
-/* XXX These "sideways" includes are a sign that something is wrong */
-#include "../mach-omap2/cm2xxx_3xxx.h"
-#include "../mach-omap2/cm-regbits-34xx.h"
-
struct omap_mcbsp **mcbsp_ptr;
-int omap_mcbsp_count, omap_mcbsp_cache_size;
+int omap_mcbsp_count;
+
+#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count)
+#define id_to_mcbsp_ptr(id) mcbsp_ptr[id];
static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
{
- if (cpu_class_is_omap1()) {
- ((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)] = (u16)val;
- __raw_writew((u16)val, mcbsp->io_base + reg);
- } else if (cpu_is_omap2420()) {
- ((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)] = (u16)val;
- __raw_writew((u16)val, mcbsp->io_base + reg);
+ void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+ if (mcbsp->pdata->reg_size == 2) {
+ ((u16 *)mcbsp->reg_cache)[reg] = (u16)val;
+ __raw_writew((u16)val, addr);
} else {
- ((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)] = val;
- __raw_writel(val, mcbsp->io_base + reg);
+ ((u32 *)mcbsp->reg_cache)[reg] = val;
+ __raw_writel(val, addr);
}
}
static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
{
- if (cpu_class_is_omap1()) {
- return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
- ((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)];
- } else if (cpu_is_omap2420()) {
- return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
- ((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)];
+ void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+ if (mcbsp->pdata->reg_size == 2) {
+ return !from_cache ? __raw_readw(addr) :
+ ((u16 *)mcbsp->reg_cache)[reg];
} else {
- return !from_cache ? __raw_readl(mcbsp->io_base + reg) :
- ((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)];
+ return !from_cache ? __raw_readl(addr) :
+ ((u32 *)mcbsp->reg_cache)[reg];
}
}
-#ifdef CONFIG_ARCH_OMAP3
static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
{
__raw_writel(val, mcbsp->st_data->io_base_st + reg);
@@ -72,7 +67,6 @@ static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
{
return __raw_readl(mcbsp->st_data->io_base_st + reg);
}
-#endif
#define MCBSP_READ(mcbsp, reg) \
omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0)
@@ -187,7 +181,7 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
MCBSP_WRITE(mcbsp, MCR2, config->mcr2);
MCBSP_WRITE(mcbsp, MCR1, config->mcr1);
MCBSP_WRITE(mcbsp, PCR0, config->pcr0);
- if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ if (mcbsp->pdata->has_ccr) {
MCBSP_WRITE(mcbsp, XCCR, config->xccr);
MCBSP_WRITE(mcbsp, RCCR, config->rccr);
}
@@ -239,46 +233,28 @@ int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream)
}
mcbsp = id_to_mcbsp_ptr(id);
- data_reg = mcbsp->phys_dma_base;
-
- if (mcbsp->mcbsp_config_type < MCBSP_CONFIG_TYPE2) {
+ if (mcbsp->pdata->reg_size == 2) {
if (stream)
- data_reg += OMAP_MCBSP_REG_DRR1;
+ data_reg = OMAP_MCBSP_REG_DRR1;
else
- data_reg += OMAP_MCBSP_REG_DXR1;
+ data_reg = OMAP_MCBSP_REG_DXR1;
} else {
if (stream)
- data_reg += OMAP_MCBSP_REG_DRR;
+ data_reg = OMAP_MCBSP_REG_DRR;
else
- data_reg += OMAP_MCBSP_REG_DXR;
+ data_reg = OMAP_MCBSP_REG_DXR;
}
- return data_reg;
+ return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step;
}
EXPORT_SYMBOL(omap_mcbsp_dma_reg_params);
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_device *find_omap_device_by_dev(struct device *dev)
-{
- struct platform_device *pdev = container_of(dev,
- struct platform_device, dev);
- return container_of(pdev, struct omap_device, pdev);
-}
-
static void omap_st_on(struct omap_mcbsp *mcbsp)
{
unsigned int w;
- struct omap_device *od;
- od = find_omap_device_by_dev(mcbsp->dev);
-
- /*
- * Sidetone uses McBSP ICLK - which must not idle when sidetones
- * are enabled or sidetones start sounding ugly.
- */
- w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
- w &= ~(1 << (mcbsp->id - 2));
- omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+ if (mcbsp->pdata->enable_st_clock)
+ mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
/* Enable McBSP Sidetone */
w = MCBSP_READ(mcbsp, SSELCR);
@@ -292,9 +268,6 @@ static void omap_st_on(struct omap_mcbsp *mcbsp)
static void omap_st_off(struct omap_mcbsp *mcbsp)
{
unsigned int w;
- struct omap_device *od;
-
- od = find_omap_device_by_dev(mcbsp->dev);
w = MCBSP_ST_READ(mcbsp, SSELCR);
MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN));
@@ -302,17 +275,13 @@ static void omap_st_off(struct omap_mcbsp *mcbsp)
w = MCBSP_READ(mcbsp, SSELCR);
MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
- w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
- w |= 1 << (mcbsp->id - 2);
- omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+ if (mcbsp->pdata->enable_st_clock)
+ mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
}
static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
{
u16 val, i;
- struct omap_device *od;
-
- od = find_omap_device_by_dev(mcbsp->dev);
val = MCBSP_ST_READ(mcbsp, SSELCR);
@@ -340,9 +309,6 @@ static void omap_st_chgain(struct omap_mcbsp *mcbsp)
{
u16 w;
struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
- struct omap_device *od;
-
- od = find_omap_device_by_dev(mcbsp->dev);
w = MCBSP_ST_READ(mcbsp, SSELCR);
@@ -525,14 +491,13 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
{
struct omap_mcbsp *mcbsp;
- if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
- return;
-
if (!omap_mcbsp_check_valid_id(id)) {
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
return;
}
mcbsp = id_to_mcbsp_ptr(id);
+ if (mcbsp->pdata->buffer_size == 0)
+ return;
if (threshold && threshold <= mcbsp->max_tx_thres)
MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
@@ -548,14 +513,13 @@ void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
{
struct omap_mcbsp *mcbsp;
- if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
- return;
-
if (!omap_mcbsp_check_valid_id(id)) {
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
return;
}
mcbsp = id_to_mcbsp_ptr(id);
+ if (mcbsp->pdata->buffer_size == 0)
+ return;
if (threshold && threshold <= mcbsp->max_rx_thres)
MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
@@ -625,6 +589,8 @@ u16 omap_mcbsp_get_tx_delay(unsigned int id)
return -ENODEV;
}
mcbsp = id_to_mcbsp_ptr(id);
+ if (mcbsp->pdata->buffer_size == 0)
+ return 0;
/* Returns the number of free locations in the buffer */
buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
@@ -648,6 +614,8 @@ u16 omap_mcbsp_get_rx_delay(unsigned int id)
return -ENODEV;
}
mcbsp = id_to_mcbsp_ptr(id);
+ if (mcbsp->pdata->buffer_size == 0)
+ return 0;
/* Returns the number of used locations in the buffer */
buffstat = MCBSP_READ(mcbsp, RBUFFSTAT);
@@ -683,46 +651,6 @@ int omap_mcbsp_get_dma_op_mode(unsigned int id)
}
EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode);
-static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp)
-{
- struct omap_device *od;
-
- od = find_omap_device_by_dev(mcbsp->dev);
- /*
- * Enable wakup behavior, smart idle and all wakeups
- * REVISIT: some wakeups may be unnecessary
- */
- if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
- MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
- }
-}
-
-static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp)
-{
- struct omap_device *od;
-
- od = find_omap_device_by_dev(mcbsp->dev);
-
- /*
- * Disable wakup behavior, smart idle and all wakeups
- */
- if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
- /*
- * HW bug workaround - If no_idle mode is taken, we need to
- * go to smart_idle before going to always_idle, or the
- * device will not hit retention anymore.
- */
-
- MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
- }
-}
-#else
-static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {}
-static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {}
-static inline void omap_st_start(struct omap_mcbsp *mcbsp) {}
-static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {}
-#endif
-
int omap_mcbsp_request(unsigned int id)
{
struct omap_mcbsp *mcbsp;
@@ -735,7 +663,7 @@ int omap_mcbsp_request(unsigned int id)
}
mcbsp = id_to_mcbsp_ptr(id);
- reg_cache = kzalloc(omap_mcbsp_cache_size, GFP_KERNEL);
+ reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
if (!reg_cache) {
return -ENOMEM;
}
@@ -757,8 +685,9 @@ int omap_mcbsp_request(unsigned int id)
pm_runtime_get_sync(mcbsp->dev);
- /* Do procedure specific to omap34xx arch, if applicable */
- omap34xx_mcbsp_request(mcbsp);
+ /* Enable wakeup behavior */
+ if (mcbsp->pdata->has_wakeup)
+ MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
/*
* Make sure that transmitter, receiver and sample-rate generator are
@@ -795,8 +724,9 @@ err_clk_disable:
if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
mcbsp->pdata->ops->free(id);
- /* Do procedure specific to omap34xx arch, if applicable */
- omap34xx_mcbsp_free(mcbsp);
+ /* Disable wakeup behavior */
+ if (mcbsp->pdata->has_wakeup)
+ MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
pm_runtime_put_sync(mcbsp->dev);
@@ -825,8 +755,9 @@ void omap_mcbsp_free(unsigned int id)
if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
mcbsp->pdata->ops->free(id);
- /* Do procedure specific to omap34xx arch, if applicable */
- omap34xx_mcbsp_free(mcbsp);
+ /* Disable wakeup behavior */
+ if (mcbsp->pdata->has_wakeup)
+ MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
pm_runtime_put_sync(mcbsp->dev);
@@ -866,7 +797,7 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
}
mcbsp = id_to_mcbsp_ptr(id);
- if (cpu_is_omap34xx())
+ if (mcbsp->st_data)
omap_st_start(mcbsp);
/* Only enable SRG, if McBSP is master */
@@ -904,7 +835,7 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
}
- if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ if (mcbsp->pdata->has_ccr) {
/* Release the transmitter and receiver */
w = MCBSP_READ_CACHE(mcbsp, XCCR);
w &= ~(tx ? XDISABLE : 0);
@@ -934,7 +865,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
/* Reset transmitter */
tx &= 1;
- if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ if (mcbsp->pdata->has_ccr) {
w = MCBSP_READ_CACHE(mcbsp, XCCR);
w |= (tx ? XDISABLE : 0);
MCBSP_WRITE(mcbsp, XCCR, w);
@@ -944,7 +875,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
/* Reset receiver */
rx &= 1;
- if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ if (mcbsp->pdata->has_ccr) {
w = MCBSP_READ_CACHE(mcbsp, RCCR);
w |= (rx ? RDISABLE : 0);
MCBSP_WRITE(mcbsp, RCCR, w);
@@ -961,39 +892,72 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6));
}
- if (cpu_is_omap34xx())
+ if (mcbsp->st_data)
omap_st_stop(mcbsp);
}
EXPORT_SYMBOL(omap_mcbsp_stop);
-/*
- * The following functions are only required on an OMAP1-only build.
- * mach-omap2/mcbsp.c contains the real functions
- */
-#ifndef CONFIG_ARCH_OMAP2PLUS
int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
{
- WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
- __func__);
- return -EINVAL;
+ struct omap_mcbsp *mcbsp;
+ const char *src;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
+ return -EINVAL;
+ }
+ mcbsp = id_to_mcbsp_ptr(id);
+
+ if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+ src = "clks_ext";
+ else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+ src = "clks_fclk";
+ else
+ return -EINVAL;
+
+ if (mcbsp->pdata->set_clk_src)
+ return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src);
+ else
+ return -EINVAL;
}
+EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
void omap2_mcbsp1_mux_clkr_src(u8 mux)
{
- WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
- __func__);
- return;
+ struct omap_mcbsp *mcbsp;
+ const char *src;
+
+ if (mux == CLKR_SRC_CLKR)
+ src = "clkr";
+ else if (mux == CLKR_SRC_CLKX)
+ src = "clkx";
+ else
+ return;
+
+ mcbsp = id_to_mcbsp_ptr(0);
+ if (mcbsp->pdata->mux_signal)
+ mcbsp->pdata->mux_signal(mcbsp->dev, "clkr", src);
}
+EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
void omap2_mcbsp1_mux_fsr_src(u8 mux)
{
- WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
- __func__);
- return;
+ struct omap_mcbsp *mcbsp;
+ const char *src;
+
+ if (mux == FSR_SRC_FSR)
+ src = "fsr";
+ else if (mux == FSR_SRC_FSX)
+ src = "fsx";
+ else
+ return;
+
+ mcbsp = id_to_mcbsp_ptr(0);
+ if (mcbsp->pdata->mux_signal)
+ mcbsp->pdata->mux_signal(mcbsp->dev, "fsr", src);
}
-#endif
+EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
-#ifdef CONFIG_ARCH_OMAP3
#define max_thres(m) (mcbsp->pdata->buffer_size)
#define valid_threshold(m, val) ((val) <= max_thres(m))
#define THRESHOLD_PROP_BUILDER(prop) \
@@ -1084,6 +1048,17 @@ unlock:
static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store);
+static const struct attribute *additional_attrs[] = {
+ &dev_attr_max_tx_thres.attr,
+ &dev_attr_max_rx_thres.attr,
+ &dev_attr_dma_op_mode.attr,
+ NULL,
+};
+
+static const struct attribute_group additional_attr_group = {
+ .attrs = (struct attribute **)additional_attrs,
+};
+
static ssize_t st_taps_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1142,27 +1117,6 @@ out:
static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store);
-static const struct attribute *additional_attrs[] = {
- &dev_attr_max_tx_thres.attr,
- &dev_attr_max_rx_thres.attr,
- &dev_attr_dma_op_mode.attr,
- NULL,
-};
-
-static const struct attribute_group additional_attr_group = {
- .attrs = (struct attribute **)additional_attrs,
-};
-
-static inline int __devinit omap_additional_add(struct device *dev)
-{
- return sysfs_create_group(&dev->kobj, &additional_attr_group);
-}
-
-static inline void __devexit omap_additional_remove(struct device *dev)
-{
- sysfs_remove_group(&dev->kobj, &additional_attr_group);
-}
-
static const struct attribute *sidetone_attrs[] = {
&dev_attr_st_taps.attr,
NULL,
@@ -1172,10 +1126,9 @@ static const struct attribute_group sidetone_attr_group = {
.attrs = (struct attribute **)sidetone_attrs,
};
-static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
+static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
+ struct resource *res)
{
- struct platform_device *pdev;
- struct resource *res;
struct omap_mcbsp_st_data *st_data;
int err;
@@ -1185,9 +1138,6 @@ static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
goto err1;
}
- pdev = container_of(mcbsp->dev, struct platform_device, dev);
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
st_data->io_base_st = ioremap(res->start, resource_size(res));
if (!st_data->io_base_st) {
err = -ENOMEM;
@@ -1214,59 +1164,10 @@ static void __devexit omap_st_remove(struct omap_mcbsp *mcbsp)
{
struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
- if (st_data) {
- sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
- iounmap(st_data->io_base_st);
- kfree(st_data);
- }
-}
-
-static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp)
-{
- mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
- if (cpu_is_omap34xx()) {
- /*
- * Initially configure the maximum thresholds to a safe value.
- * The McBSP FIFO usage with these values should not go under
- * 16 locations.
- * If the whole FIFO without safety buffer is used, than there
- * is a possibility that the DMA will be not able to push the
- * new data on time, causing channel shifts in runtime.
- */
- mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
- mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
- /*
- * REVISIT: Set dmap_op_mode to THRESHOLD as default
- * for mcbsp2 instances.
- */
- if (omap_additional_add(mcbsp->dev))
- dev_warn(mcbsp->dev,
- "Unable to create additional controls\n");
-
- if (mcbsp->id == 2 || mcbsp->id == 3)
- if (omap_st_add(mcbsp))
- dev_warn(mcbsp->dev,
- "Unable to create sidetone controls\n");
-
- } else {
- mcbsp->max_tx_thres = -EINVAL;
- mcbsp->max_rx_thres = -EINVAL;
- }
-}
-
-static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp)
-{
- if (cpu_is_omap34xx()) {
- omap_additional_remove(mcbsp->dev);
-
- if (mcbsp->id == 2 || mcbsp->id == 3)
- omap_st_remove(mcbsp);
- }
+ sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+ iounmap(st_data->io_base_st);
+ kfree(st_data);
}
-#else
-static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {}
-static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {}
-#endif /* CONFIG_ARCH_OMAP3 */
/*
* McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
@@ -1316,7 +1217,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
}
}
mcbsp->phys_base = res->start;
- omap_mcbsp_cache_size = resource_size(res);
+ mcbsp->reg_cache_size = resource_size(res);
mcbsp->io_base = ioremap(res->start, resource_size(res));
if (!mcbsp->io_base) {
ret = -ENOMEM;
@@ -1364,15 +1265,52 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
mcbsp->pdata = pdata;
mcbsp->dev = &pdev->dev;
mcbsp_ptr[id] = mcbsp;
- mcbsp->mcbsp_config_type = pdata->mcbsp_config_type;
platform_set_drvdata(pdev, mcbsp);
pm_runtime_enable(mcbsp->dev);
- /* Initialize mcbsp properties for OMAP34XX if needed / applicable */
- omap34xx_device_init(mcbsp);
+ mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
+ if (mcbsp->pdata->buffer_size) {
+ /*
+ * Initially configure the maximum thresholds to a safe value.
+ * The McBSP FIFO usage with these values should not go under
+ * 16 locations.
+ * If the whole FIFO without safety buffer is used, than there
+ * is a possibility that the DMA will be not able to push the
+ * new data on time, causing channel shifts in runtime.
+ */
+ mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
+ mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
+
+ ret = sysfs_create_group(&mcbsp->dev->kobj,
+ &additional_attr_group);
+ if (ret) {
+ dev_err(mcbsp->dev,
+ "Unable to create additional controls\n");
+ goto err_thres;
+ }
+ } else {
+ mcbsp->max_tx_thres = -EINVAL;
+ mcbsp->max_rx_thres = -EINVAL;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
+ if (res) {
+ ret = omap_st_add(mcbsp, res);
+ if (ret) {
+ dev_err(mcbsp->dev,
+ "Unable to create sidetone controls\n");
+ goto err_st;
+ }
+ }
return 0;
+err_st:
+ if (mcbsp->pdata->buffer_size)
+ sysfs_remove_group(&mcbsp->dev->kobj,
+ &additional_attr_group);
+err_thres:
+ clk_put(mcbsp->fclk);
err_res:
iounmap(mcbsp->io_base);
err_ioremap:
@@ -1392,7 +1330,12 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
mcbsp->pdata->ops->free)
mcbsp->pdata->ops->free(mcbsp->id);
- omap34xx_device_exit(mcbsp);
+ if (mcbsp->pdata->buffer_size)
+ sysfs_remove_group(&mcbsp->dev->kobj,
+ &additional_attr_group);
+
+ if (mcbsp->st_data)
+ omap_st_remove(mcbsp);
clk_put(mcbsp->fclk);
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 02609eee0562..cd90bedd9306 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -85,6 +85,8 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/notifier.h>
#include <plat/omap_device.h>
#include <plat/omap_hwmod.h>
@@ -94,6 +96,23 @@
#define USE_WAKEUP_LAT 0
#define IGNORE_WAKEUP_LAT 1
+static int omap_device_register(struct platform_device *pdev);
+static int omap_early_device_register(struct platform_device *pdev);
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+ struct omap_hwmod **ohs, int oh_cnt,
+ struct omap_device_pm_latency *pm_lats,
+ int pm_lats_cnt);
+static void omap_device_delete(struct omap_device *od);
+
+
+static struct omap_device_pm_latency omap_default_latency[] = {
+ {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ }
+};
+
/* Private functions */
/**
@@ -114,7 +133,7 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
{
struct timespec a, b, c;
- pr_debug("omap_device: %s: activating\n", od->pdev.name);
+ dev_dbg(&od->pdev->dev, "omap_device: activating\n");
while (od->pm_lat_level > 0) {
struct omap_device_pm_latency *odpl;
@@ -138,25 +157,24 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
c = timespec_sub(b, a);
act_lat = timespec_to_ns(&c);
- pr_debug("omap_device: %s: pm_lat %d: activate: elapsed time "
- "%llu nsec\n", od->pdev.name, od->pm_lat_level,
- act_lat);
+ dev_dbg(&od->pdev->dev,
+ "omap_device: pm_lat %d: activate: elapsed time "
+ "%llu nsec\n", od->pm_lat_level, act_lat);
if (act_lat > odpl->activate_lat) {
odpl->activate_lat_worst = act_lat;
if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
odpl->activate_lat = act_lat;
- pr_warning("omap_device: %s.%d: new worst case "
- "activate latency %d: %llu\n",
- od->pdev.name, od->pdev.id,
- od->pm_lat_level, act_lat);
+ dev_dbg(&od->pdev->dev,
+ "new worst case activate latency "
+ "%d: %llu\n",
+ od->pm_lat_level, act_lat);
} else
- pr_warning("omap_device: %s.%d: activate "
- "latency %d higher than exptected. "
- "(%llu > %d)\n",
- od->pdev.name, od->pdev.id,
- od->pm_lat_level, act_lat,
- odpl->activate_lat);
+ dev_warn(&od->pdev->dev,
+ "activate latency %d "
+ "higher than exptected. (%llu > %d)\n",
+ od->pm_lat_level, act_lat,
+ odpl->activate_lat);
}
od->dev_wakeup_lat -= odpl->activate_lat;
@@ -183,7 +201,7 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
{
struct timespec a, b, c;
- pr_debug("omap_device: %s: deactivating\n", od->pdev.name);
+ dev_dbg(&od->pdev->dev, "omap_device: deactivating\n");
while (od->pm_lat_level < od->pm_lats_cnt) {
struct omap_device_pm_latency *odpl;
@@ -206,28 +224,26 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
c = timespec_sub(b, a);
deact_lat = timespec_to_ns(&c);
- pr_debug("omap_device: %s: pm_lat %d: deactivate: elapsed time "
- "%llu nsec\n", od->pdev.name, od->pm_lat_level,
- deact_lat);
+ dev_dbg(&od->pdev->dev,
+ "omap_device: pm_lat %d: deactivate: elapsed time "
+ "%llu nsec\n", od->pm_lat_level, deact_lat);
if (deact_lat > odpl->deactivate_lat) {
odpl->deactivate_lat_worst = deact_lat;
if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
odpl->deactivate_lat = deact_lat;
- pr_warning("omap_device: %s.%d: new worst case "
- "deactivate latency %d: %llu\n",
- od->pdev.name, od->pdev.id,
- od->pm_lat_level, deact_lat);
+ dev_dbg(&od->pdev->dev,
+ "new worst case deactivate latency "
+ "%d: %llu\n",
+ od->pm_lat_level, deact_lat);
} else
- pr_warning("omap_device: %s.%d: deactivate "
- "latency %d higher than exptected. "
- "(%llu > %d)\n",
- od->pdev.name, od->pdev.id,
- od->pm_lat_level, deact_lat,
- odpl->deactivate_lat);
+ dev_warn(&od->pdev->dev,
+ "deactivate latency %d "
+ "higher than exptected. (%llu > %d)\n",
+ od->pm_lat_level, deact_lat,
+ odpl->deactivate_lat);
}
-
od->dev_wakeup_lat += odpl->activate_lat;
od->pm_lat_level++;
@@ -245,28 +261,27 @@ static void _add_clkdev(struct omap_device *od, const char *clk_alias,
if (!clk_alias || !clk_name)
return;
- pr_debug("omap_device: %s: Creating %s -> %s\n",
- dev_name(&od->pdev.dev), clk_alias, clk_name);
+ dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name);
- r = clk_get_sys(dev_name(&od->pdev.dev), clk_alias);
+ r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
if (!IS_ERR(r)) {
- pr_warning("omap_device: %s: alias %s already exists\n",
- dev_name(&od->pdev.dev), clk_alias);
+ dev_warn(&od->pdev->dev,
+ "alias %s already exists\n", clk_alias);
clk_put(r);
return;
}
r = omap_clk_get_by_name(clk_name);
if (IS_ERR(r)) {
- pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
- dev_name(&od->pdev.dev), clk_name);
+ dev_err(&od->pdev->dev,
+ "omap_clk_get_by_name for %s failed\n", clk_name);
return;
}
- l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev.dev));
+ l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev->dev));
if (!l) {
- pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
- dev_name(&od->pdev.dev), clk_alias);
+ dev_err(&od->pdev->dev,
+ "clkdev_alloc for %s failed\n", clk_alias);
return;
}
@@ -304,6 +319,96 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od,
}
+static struct dev_pm_domain omap_device_pm_domain;
+
+/**
+ * omap_device_build_from_dt - build an omap_device with multiple hwmods
+ * @pdev_name: name of the platform_device driver to use
+ * @pdev_id: this platform_device's connection ID
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ * @is_early_device: should the device be registered as an early device or not
+ *
+ * Function for building an omap_device already registered from device-tree
+ *
+ * Returns 0 or PTR_ERR() on error.
+ */
+static int omap_device_build_from_dt(struct platform_device *pdev)
+{
+ struct omap_hwmod **hwmods;
+ struct omap_device *od;
+ struct omap_hwmod *oh;
+ struct device_node *node = pdev->dev.of_node;
+ const char *oh_name;
+ int oh_cnt, i, ret = 0;
+
+ oh_cnt = of_property_count_strings(node, "ti,hwmods");
+ if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+ dev_warn(&pdev->dev, "No 'hwmods' to build omap_device\n");
+ return -ENODEV;
+ }
+
+ hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+ if (!hwmods) {
+ ret = -ENOMEM;
+ goto odbfd_exit;
+ }
+
+ for (i = 0; i < oh_cnt; i++) {
+ of_property_read_string_index(node, "ti,hwmods", i, &oh_name);
+ oh = omap_hwmod_lookup(oh_name);
+ if (!oh) {
+ dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
+ oh_name);
+ ret = -EINVAL;
+ goto odbfd_exit1;
+ }
+ hwmods[i] = oh;
+ }
+
+ od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
+ if (!od) {
+ dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
+ oh_name);
+ ret = PTR_ERR(od);
+ goto odbfd_exit1;
+ }
+
+ if (of_get_property(node, "ti,no_idle_on_suspend", NULL))
+ omap_device_disable_idle_on_suspend(pdev);
+
+ pdev->dev.pm_domain = &omap_device_pm_domain;
+
+odbfd_exit1:
+ kfree(hwmods);
+odbfd_exit:
+ return ret;
+}
+
+static int _omap_device_notifier_call(struct notifier_block *nb,
+ unsigned long event, void *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ switch (event) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ if (pdev->dev.of_node)
+ omap_device_build_from_dt(pdev);
+ break;
+
+ case BUS_NOTIFY_DEL_DEVICE:
+ if (pdev->archdata.od)
+ omap_device_delete(pdev->archdata.od);
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+
/* Public functions for use by core code */
/**
@@ -343,7 +448,7 @@ u32 omap_device_get_context_loss_count(struct platform_device *pdev)
* much memory to allocate before calling
* omap_device_fill_resources(). Returns the count.
*/
-int omap_device_count_resources(struct omap_device *od)
+static int omap_device_count_resources(struct omap_device *od)
{
int c = 0;
int i;
@@ -352,7 +457,7 @@ int omap_device_count_resources(struct omap_device *od)
c += omap_hwmod_count_resources(od->hwmods[i]);
pr_debug("omap_device: %s: counted %d total resources across %d "
- "hwmods\n", od->pdev.name, c, od->hwmods_cnt);
+ "hwmods\n", od->pdev->name, c, od->hwmods_cnt);
return c;
}
@@ -374,7 +479,8 @@ int omap_device_count_resources(struct omap_device *od)
* functions to get device resources. Hacking around the existing
* platform_device code wastes memory. Returns 0.
*/
-int omap_device_fill_resources(struct omap_device *od, struct resource *res)
+static int omap_device_fill_resources(struct omap_device *od,
+ struct resource *res)
{
int c = 0;
int i, r;
@@ -389,6 +495,113 @@ int omap_device_fill_resources(struct omap_device *od, struct resource *res)
}
/**
+ * omap_device_alloc - allocate an omap_device
+ * @pdev: platform_device that will be included in this omap_device
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ *
+ * Convenience function for allocating an omap_device structure and filling
+ * hwmods, resources and pm_latency attributes.
+ *
+ * Returns an struct omap_device pointer or ERR_PTR() on error;
+ */
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+ struct omap_hwmod **ohs, int oh_cnt,
+ struct omap_device_pm_latency *pm_lats,
+ int pm_lats_cnt)
+{
+ int ret = -ENOMEM;
+ struct omap_device *od;
+ struct resource *res = NULL;
+ int i, res_count;
+ struct omap_hwmod **hwmods;
+
+ od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
+ if (!od) {
+ ret = -ENOMEM;
+ goto oda_exit1;
+ }
+ od->hwmods_cnt = oh_cnt;
+
+ hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+ if (!hwmods)
+ goto oda_exit2;
+
+ od->hwmods = hwmods;
+ od->pdev = pdev;
+
+ /*
+ * HACK: Ideally the resources from DT should match, and hwmod
+ * should just add the missing ones. Since the name is not
+ * properly populated by DT, stick to hwmod resources only.
+ */
+ if (pdev->num_resources && pdev->resource)
+ dev_warn(&pdev->dev, "%s(): resources already allocated %d\n",
+ __func__, pdev->num_resources);
+
+ res_count = omap_device_count_resources(od);
+ if (res_count > 0) {
+ dev_dbg(&pdev->dev, "%s(): resources allocated from hwmod %d\n",
+ __func__, res_count);
+ res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+ if (!res)
+ goto oda_exit3;
+
+ omap_device_fill_resources(od, res);
+
+ ret = platform_device_add_resources(pdev, res, res_count);
+ kfree(res);
+
+ if (ret)
+ goto oda_exit3;
+ }
+
+ if (!pm_lats) {
+ pm_lats = omap_default_latency;
+ pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
+ }
+
+ od->pm_lats_cnt = pm_lats_cnt;
+ od->pm_lats = kmemdup(pm_lats,
+ sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
+ GFP_KERNEL);
+ if (!od->pm_lats)
+ goto oda_exit3;
+
+ pdev->archdata.od = od;
+
+ for (i = 0; i < oh_cnt; i++) {
+ hwmods[i]->od = od;
+ _add_hwmod_clocks_clkdev(od, hwmods[i]);
+ }
+
+ return od;
+
+oda_exit3:
+ kfree(hwmods);
+oda_exit2:
+ kfree(od);
+oda_exit1:
+ dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
+
+ return ERR_PTR(ret);
+}
+
+static void omap_device_delete(struct omap_device *od)
+{
+ if (!od)
+ return;
+
+ od->pdev->archdata.od = NULL;
+ kfree(od->pm_lats);
+ kfree(od->hwmods);
+ kfree(od);
+}
+
+/**
* omap_device_build - build and register an omap_device with one omap_hwmod
* @pdev_name: name of the platform_device driver to use
* @pdev_id: this platform_device's connection ID
@@ -405,7 +618,7 @@ int omap_device_fill_resources(struct omap_device *od, struct resource *res)
* information. Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
* passes along the return value of omap_device_build_ss().
*/
-struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
struct omap_hwmod *oh, void *pdata,
int pdata_len,
struct omap_device_pm_latency *pm_lats,
@@ -438,18 +651,15 @@ struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
* platform_device record. Returns an ERR_PTR() on error, or passes
* along the return value of omap_device_register().
*/
-struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
struct omap_hwmod **ohs, int oh_cnt,
void *pdata, int pdata_len,
struct omap_device_pm_latency *pm_lats,
int pm_lats_cnt, int is_early_device)
{
int ret = -ENOMEM;
+ struct platform_device *pdev;
struct omap_device *od;
- char *pdev_name2;
- struct resource *res = NULL;
- int i, res_count;
- struct omap_hwmod **hwmods;
if (!ohs || oh_cnt == 0 || !pdev_name)
return ERR_PTR(-EINVAL);
@@ -457,72 +667,40 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
if (!pdata && pdata_len > 0)
return ERR_PTR(-EINVAL);
- pr_debug("omap_device: %s: building with %d hwmods\n", pdev_name,
- oh_cnt);
-
- od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
- if (!od)
- return ERR_PTR(-ENOMEM);
+ pdev = platform_device_alloc(pdev_name, pdev_id);
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto odbs_exit;
+ }
- od->hwmods_cnt = oh_cnt;
+ /* Set the dev_name early to allow dev_xxx in omap_device_alloc */
+ if (pdev->id != -1)
+ dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
+ else
+ dev_set_name(&pdev->dev, "%s", pdev->name);
- hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt,
- GFP_KERNEL);
- if (!hwmods)
+ od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
+ if (!od)
goto odbs_exit1;
- memcpy(hwmods, ohs, sizeof(struct omap_hwmod *) * oh_cnt);
- od->hwmods = hwmods;
-
- pdev_name2 = kzalloc(strlen(pdev_name) + 1, GFP_KERNEL);
- if (!pdev_name2)
- goto odbs_exit2;
- strcpy(pdev_name2, pdev_name);
-
- od->pdev.name = pdev_name2;
- od->pdev.id = pdev_id;
-
- res_count = omap_device_count_resources(od);
- if (res_count > 0) {
- res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
- if (!res)
- goto odbs_exit3;
- }
- omap_device_fill_resources(od, res);
-
- od->pdev.num_resources = res_count;
- od->pdev.resource = res;
-
- ret = platform_device_add_data(&od->pdev, pdata, pdata_len);
+ ret = platform_device_add_data(pdev, pdata, pdata_len);
if (ret)
- goto odbs_exit4;
-
- od->pm_lats = pm_lats;
- od->pm_lats_cnt = pm_lats_cnt;
+ goto odbs_exit2;
if (is_early_device)
- ret = omap_early_device_register(od);
+ ret = omap_early_device_register(pdev);
else
- ret = omap_device_register(od);
-
- for (i = 0; i < oh_cnt; i++) {
- hwmods[i]->od = od;
- _add_hwmod_clocks_clkdev(od, hwmods[i]);
- }
-
+ ret = omap_device_register(pdev);
if (ret)
- goto odbs_exit4;
+ goto odbs_exit2;
- return od;
+ return pdev;
-odbs_exit4:
- kfree(res);
-odbs_exit3:
- kfree(pdev_name2);
odbs_exit2:
- kfree(hwmods);
+ omap_device_delete(od);
odbs_exit1:
- kfree(od);
+ platform_device_put(pdev);
+odbs_exit:
pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret);
@@ -538,11 +716,11 @@ odbs_exit1:
* platform_early_add_device() on the underlying platform_device.
* Returns 0 by default.
*/
-int omap_early_device_register(struct omap_device *od)
+static int omap_early_device_register(struct platform_device *pdev)
{
struct platform_device *devices[1];
- devices[0] = &(od->pdev);
+ devices[0] = pdev;
early_platform_add_devices(devices, 1);
return 0;
}
@@ -638,13 +816,13 @@ static struct dev_pm_domain omap_device_pm_domain = {
* platform_device_register() on the underlying platform_device.
* Returns the return value of platform_device_register().
*/
-int omap_device_register(struct omap_device *od)
+static int omap_device_register(struct platform_device *pdev)
{
- pr_debug("omap_device: %s: registering\n", od->pdev.name);
+ pr_debug("omap_device: %s: registering\n", pdev->name);
- od->pdev.dev.parent = &omap_device_parent;
- od->pdev.dev.pm_domain = &omap_device_pm_domain;
- return platform_device_register(&od->pdev);
+ pdev->dev.parent = &omap_device_parent;
+ pdev->dev.pm_domain = &omap_device_pm_domain;
+ return platform_device_add(pdev);
}
@@ -671,8 +849,9 @@ int omap_device_enable(struct platform_device *pdev)
od = to_omap_device(pdev);
if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
- WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
- od->pdev.name, od->pdev.id, __func__, od->_state);
+ dev_warn(&pdev->dev,
+ "omap_device: %s() called from invalid state %d\n",
+ __func__, od->_state);
return -EINVAL;
}
@@ -710,8 +889,9 @@ int omap_device_idle(struct platform_device *pdev)
od = to_omap_device(pdev);
if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
- WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
- od->pdev.name, od->pdev.id, __func__, od->_state);
+ dev_warn(&pdev->dev,
+ "omap_device: %s() called from invalid state %d\n",
+ __func__, od->_state);
return -EINVAL;
}
@@ -742,8 +922,9 @@ int omap_device_shutdown(struct platform_device *pdev)
if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
od->_state != OMAP_DEVICE_STATE_IDLE) {
- WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
- od->pdev.name, od->pdev.id, __func__, od->_state);
+ dev_warn(&pdev->dev,
+ "omap_device: %s() called from invalid state %d\n",
+ __func__, od->_state);
return -EINVAL;
}
@@ -837,6 +1018,42 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od)
return omap_hwmod_get_mpu_rt_va(od->hwmods[0]);
}
+/**
+ * omap_device_get_by_hwmod_name() - convert a hwmod name to
+ * device pointer.
+ * @oh_name: name of the hwmod device
+ *
+ * Returns back a struct device * pointer associated with a hwmod
+ * device represented by a hwmod_name
+ */
+struct device *omap_device_get_by_hwmod_name(const char *oh_name)
+{
+ struct omap_hwmod *oh;
+
+ if (!oh_name) {
+ WARN(1, "%s: no hwmod name!\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ oh = omap_hwmod_lookup(oh_name);
+ if (IS_ERR_OR_NULL(oh)) {
+ WARN(1, "%s: no hwmod for %s\n", __func__,
+ oh_name);
+ return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
+ }
+ if (IS_ERR_OR_NULL(oh->od)) {
+ WARN(1, "%s: no omap_device for %s\n", __func__,
+ oh_name);
+ return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV);
+ }
+
+ if (IS_ERR_OR_NULL(oh->od->pdev))
+ return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV);
+
+ return &oh->od->pdev->dev;
+}
+EXPORT_SYMBOL(omap_device_get_by_hwmod_name);
+
/*
* Public functions intended for use in omap_device_pm_latency
* .activate_func and .deactivate_func function pointers
@@ -917,8 +1134,13 @@ struct device omap_device_parent = {
.parent = &platform_bus,
};
+static struct notifier_block platform_nb = {
+ .notifier_call = _omap_device_notifier_call,
+};
+
static int __init omap_device_init(void)
{
+ bus_register_notifier(&platform_bus_type, &platform_nb);
return device_register(&omap_device_parent);
}
core_initcall(omap_device_init);
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 363c91e44efb..8b28664d1c62 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -19,7 +19,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
-#include <linux/omapfb.h>
#include <asm/tlb.h>
#include <asm/cacheflush.h>
@@ -29,10 +28,8 @@
#include <plat/sram.h>
#include <plat/board.h>
#include <plat/cpu.h>
-#include <plat/vram.h>
#include "sram.h"
-#include "fb.h"
/* XXX These "sideways" includes are a sign that something is wrong */
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
@@ -41,16 +38,9 @@
#endif
#define OMAP1_SRAM_PA 0x20000000
-#define OMAP1_SRAM_VA VMALLOC_END
#define OMAP2_SRAM_PUB_PA (OMAP2_SRAM_PA + 0xf800)
-#define OMAP2_SRAM_VA 0xfe400000
-#define OMAP2_SRAM_PUB_VA (OMAP2_SRAM_VA + 0x800)
-#define OMAP3_SRAM_VA 0xfe400000
#define OMAP3_SRAM_PUB_PA (OMAP3_SRAM_PA + 0x8000)
-#define OMAP3_SRAM_PUB_VA (OMAP3_SRAM_VA + 0x8000)
-#define OMAP4_SRAM_VA 0xfe400000
#define OMAP4_SRAM_PUB_PA (OMAP4_SRAM_PA + 0x4000)
-#define OMAP4_SRAM_PUB_VA (OMAP4_SRAM_VA + 0x4000)
#if defined(CONFIG_ARCH_OMAP2PLUS)
#define SRAM_BOOTLOADER_SZ 0x00
@@ -73,9 +63,9 @@
#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
static unsigned long omap_sram_start;
-static unsigned long omap_sram_base;
+static void __iomem *omap_sram_base;
static unsigned long omap_sram_size;
-static unsigned long omap_sram_ceil;
+static void __iomem *omap_sram_ceil;
/*
* Depending on the target RAMFS firewall setup, the public usable amount of
@@ -112,12 +102,9 @@ static int is_sram_locked(void)
*/
static void __init omap_detect_sram(void)
{
- unsigned long reserved;
-
if (cpu_class_is_omap2()) {
if (is_sram_locked()) {
if (cpu_is_omap34xx()) {
- omap_sram_base = OMAP3_SRAM_PUB_VA;
omap_sram_start = OMAP3_SRAM_PUB_PA;
if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
(omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
@@ -126,25 +113,20 @@ static void __init omap_detect_sram(void)
omap_sram_size = 0x8000; /* 32K */
}
} else if (cpu_is_omap44xx()) {
- omap_sram_base = OMAP4_SRAM_PUB_VA;
omap_sram_start = OMAP4_SRAM_PUB_PA;
omap_sram_size = 0xa000; /* 40K */
} else {
- omap_sram_base = OMAP2_SRAM_PUB_VA;
omap_sram_start = OMAP2_SRAM_PUB_PA;
omap_sram_size = 0x800; /* 2K */
}
} else {
if (cpu_is_omap34xx()) {
- omap_sram_base = OMAP3_SRAM_VA;
omap_sram_start = OMAP3_SRAM_PA;
omap_sram_size = 0x10000; /* 64K */
} else if (cpu_is_omap44xx()) {
- omap_sram_base = OMAP4_SRAM_VA;
omap_sram_start = OMAP4_SRAM_PA;
omap_sram_size = 0xe000; /* 56K */
} else {
- omap_sram_base = OMAP2_SRAM_VA;
omap_sram_start = OMAP2_SRAM_PA;
if (cpu_is_omap242x())
omap_sram_size = 0xa0000; /* 640K */
@@ -153,7 +135,6 @@ static void __init omap_detect_sram(void)
}
}
} else {
- omap_sram_base = OMAP1_SRAM_VA;
omap_sram_start = OMAP1_SRAM_PA;
if (cpu_is_omap7xx())
@@ -170,35 +151,14 @@ static void __init omap_detect_sram(void)
omap_sram_size = 0x4000;
}
}
- reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base,
- omap_sram_size,
- omap_sram_start + SRAM_BOOTLOADER_SZ,
- omap_sram_size - SRAM_BOOTLOADER_SZ);
- omap_sram_size -= reserved;
-
- reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base,
- omap_sram_size,
- omap_sram_start + SRAM_BOOTLOADER_SZ,
- omap_sram_size - SRAM_BOOTLOADER_SZ);
- omap_sram_size -= reserved;
-
- omap_sram_ceil = omap_sram_base + omap_sram_size;
}
-static struct map_desc omap_sram_io_desc[] __initdata = {
- { /* .length gets filled in at runtime */
- .virtual = OMAP1_SRAM_VA,
- .pfn = __phys_to_pfn(OMAP1_SRAM_PA),
- .type = MT_MEMORY
- }
-};
-
/*
* Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
*/
static void __init omap_map_sram(void)
{
- unsigned long base;
+ int cached = 1;
if (omap_sram_size == 0)
return;
@@ -211,28 +171,18 @@ static void __init omap_map_sram(void)
* the ARM may attempt to write cache lines back to SDRAM
* which will cause the system to hang.
*/
- omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED;
+ cached = 0;
}
- omap_sram_io_desc[0].virtual = omap_sram_base;
- base = omap_sram_start;
- base = ROUND_DOWN(base, PAGE_SIZE);
- omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
- omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE);
- iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
-
- pr_info("SRAM: Mapped pa 0x%08llx to va 0x%08lx size: 0x%lx\n",
- (long long) __pfn_to_phys(omap_sram_io_desc[0].pfn),
- omap_sram_io_desc[0].virtual,
- omap_sram_io_desc[0].length);
+ omap_sram_start = ROUND_DOWN(omap_sram_start, PAGE_SIZE);
+ omap_sram_base = __arm_ioremap_exec(omap_sram_start, omap_sram_size,
+ cached);
+ if (!omap_sram_base) {
+ pr_err("SRAM: Could not map\n");
+ return;
+ }
- /*
- * Normally devicemaps_init() would flush caches and tlb after
- * mdesc->map_io(), but since we're called from map_io(), we
- * must do it here.
- */
- local_flush_tlb_all();
- flush_cache_all();
+ omap_sram_ceil = omap_sram_base + omap_sram_size;
/*
* Looks like we need to preserve some bootloader code at the
@@ -251,13 +201,18 @@ static void __init omap_map_sram(void)
*/
void *omap_sram_push_address(unsigned long size)
{
- if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
+ unsigned long available, new_ceil = (unsigned long)omap_sram_ceil;
+
+ available = omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ);
+
+ if (size > available) {
pr_err("Not enough space in SRAM\n");
return NULL;
}
- omap_sram_ceil -= size;
- omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN);
+ new_ceil -= size;
+ new_ceil = ROUND_DOWN(new_ceil, FNCPY_ALIGN);
+ omap_sram_ceil = IOMEM(new_ceil);
return (void *)omap_sram_ceil;
}
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
index 3075b9fdde83..3abf30428bee 100644
--- a/arch/arm/plat-orion/include/plat/gpio.h
+++ b/arch/arm/plat-orion/include/plat/gpio.h
@@ -12,15 +12,7 @@
#define __PLAT_GPIO_H
#include <linux/init.h>
-#include <asm-generic/gpio.h>
-
-/*
- * GENERIC_GPIO primitives.
- */
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
+#include <linux/types.h>
/*
* Orion-specific GPIO API extensions.
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
index 3aca5ba0f876..f302d048392d 100644
--- a/arch/arm/plat-pxa/Makefile
+++ b/arch/arm/plat-pxa/Makefile
@@ -4,7 +4,6 @@
obj-y := dma.o
-obj-$(CONFIG_GENERIC_GPIO) += gpio.o
obj-$(CONFIG_PXA3xx) += mfp.o
obj-$(CONFIG_PXA95x) += mfp.o
obj-$(CONFIG_ARCH_MMP) += mfp.o
diff --git a/arch/arm/plat-pxa/include/plat/gpio-pxa.h b/arch/arm/plat-pxa/include/plat/gpio-pxa.h
new file mode 100644
index 000000000000..b6390beff323
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/gpio-pxa.h
@@ -0,0 +1,44 @@
+#ifndef __PLAT_PXA_GPIO_H
+#define __PLAT_PXA_GPIO_H
+
+struct irq_data;
+
+/*
+ * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
+ * one set of registers. The register offsets are organized below:
+ *
+ * GPLR GPDR GPSR GPCR GRER GFER GEDR
+ * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048
+ * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C
+ * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050
+ *
+ * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148
+ * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C
+ * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150
+ *
+ * NOTE:
+ * BANK 3 is only available on PXA27x and later processors.
+ * BANK 4 and 5 are only available on PXA935
+ */
+
+#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n))
+
+#define GPLR_OFFSET 0x00
+#define GPDR_OFFSET 0x0C
+#define GPSR_OFFSET 0x18
+#define GPCR_OFFSET 0x24
+#define GRER_OFFSET 0x30
+#define GFER_OFFSET 0x3C
+#define GEDR_OFFSET 0x48
+
+/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
+ * Those cases currently cause holes in the GPIO number space, the
+ * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
+ */
+extern int pxa_last_gpio;
+
+typedef int (*set_wake_t)(struct irq_data *d, unsigned int on);
+
+extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
+
+#endif /* __PLAT_PXA_GPIO_H */
diff --git a/arch/arm/plat-pxa/include/plat/gpio.h b/arch/arm/plat-pxa/include/plat/gpio.h
index 1ddd2b97a729..258f77210b02 100644
--- a/arch/arm/plat-pxa/include/plat/gpio.h
+++ b/arch/arm/plat-pxa/include/plat/gpio.h
@@ -1,35 +1,10 @@
#ifndef __PLAT_GPIO_H
#define __PLAT_GPIO_H
-struct irq_data;
+#define __ARM_GPIOLIB_COMPLEX
-/*
- * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
- * one set of registers. The register offsets are organized below:
- *
- * GPLR GPDR GPSR GPCR GRER GFER GEDR
- * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048
- * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C
- * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050
- *
- * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148
- * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C
- * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150
- *
- * NOTE:
- * BANK 3 is only available on PXA27x and later processors.
- * BANK 4 and 5 are only available on PXA935
- */
-
-#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n))
-
-#define GPLR_OFFSET 0x00
-#define GPDR_OFFSET 0x0C
-#define GPSR_OFFSET 0x18
-#define GPCR_OFFSET 0x24
-#define GRER_OFFSET 0x30
-#define GFER_OFFSET 0x3C
-#define GEDR_OFFSET 0x48
+/* The individual machine provides register offsets and NR_BUILTIN_GPIO */
+#include <mach/gpio-pxa.h>
static inline int gpio_get_value(unsigned gpio)
{
@@ -52,13 +27,4 @@ static inline void gpio_set_value(unsigned gpio, int value)
#define gpio_cansleep __gpio_cansleep
-/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
- * Those cases currently cause holes in the GPIO number space, the
- * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
- */
-extern int pxa_last_gpio;
-
-typedef int (*set_wake_t)(struct irq_data *d, unsigned int on);
-
-extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
#endif /* __PLAT_GPIO_H */
diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h
index 89e68e07b0a8..5c79c29f2833 100644
--- a/arch/arm/plat-pxa/include/plat/mfp.h
+++ b/arch/arm/plat-pxa/include/plat/mfp.h
@@ -456,7 +456,7 @@ struct mfp_addr_map {
#define MFP_ADDR_END { MFP_PIN_INVALID, 0 }
-void __init mfp_init_base(unsigned long mfpr_base);
+void __init mfp_init_base(void __iomem *mfpr_base);
void __init mfp_init_addr(struct mfp_addr_map *map);
/*
diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c
index be12eadcce20..2c4dbb1f4236 100644
--- a/arch/arm/plat-pxa/mfp.c
+++ b/arch/arm/plat-pxa/mfp.c
@@ -229,7 +229,7 @@ void mfp_write(int mfp, unsigned long val)
spin_unlock_irqrestore(&mfp_spin_lock, flags);
}
-void __init mfp_init_base(unsigned long mfpr_base)
+void __init mfp_init_base(void __iomem *mfpr_base)
{
int i;
@@ -237,7 +237,7 @@ void __init mfp_init_base(unsigned long mfpr_base)
for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
mfp_table[i].config = -1;
- mfpr_mmio_base = (void __iomem *)mfpr_base;
+ mfpr_mmio_base = mfpr_base;
}
void __init mfp_init_addr(struct mfp_addr_map *map)
diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
index c1fc6c6fac72..3c6335307fb1 100644
--- a/arch/arm/plat-s3c24xx/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -215,19 +215,18 @@ static void s3c24xx_pm_restart(char mode, const char *cmd)
void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
{
- unsigned long idcode = 0x0;
-
/* initialise the io descriptors we need for initialisation */
iotable_init(mach_desc, size);
iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
if (cpu_architecture() >= CPU_ARCH_ARMv5) {
- idcode = s3c24xx_read_idcode_v5();
+ samsung_cpu_id = s3c24xx_read_idcode_v5();
} else {
- idcode = s3c24xx_read_idcode_v4();
+ samsung_cpu_id = s3c24xx_read_idcode_v4();
}
+ s3c24xx_init_cpu();
arm_pm_restart = s3c24xx_pm_restart;
- s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+ s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
}
diff --git a/arch/arm/plat-s3c24xx/include/plat/map.h b/arch/arm/plat-s3c24xx/include/plat/map.h
deleted file mode 100644
index bd534d32b993..000000000000
--- a/arch/arm/plat-s3c24xx/include/plat/map.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/map.h
- *
- * Copyright (c) 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_S3C24XX_MAP_H
-#define __ASM_PLAT_S3C24XX_MAP_H
-
-/* interrupt controller is the first thing we put in, to make
- * the assembly code for the irq detection easier
- */
-#define S3C24XX_VA_IRQ S3C_VA_IRQ
-#define S3C2410_PA_IRQ (0x4A000000)
-#define S3C24XX_SZ_IRQ SZ_1M
-
-/* memory controller registers */
-#define S3C24XX_VA_MEMCTRL S3C_VA_MEM
-#define S3C2410_PA_MEMCTRL (0x48000000)
-#define S3C24XX_SZ_MEMCTRL SZ_1M
-
-/* UARTs */
-#define S3C24XX_VA_UART S3C_VA_UART
-#define S3C2410_PA_UART (0x50000000)
-#define S3C24XX_SZ_UART SZ_1M
-#define S3C_UART_OFFSET (0x4000)
-
-#define S3C_VA_UARTx(uart) (S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
-
-/* Timers */
-#define S3C24XX_VA_TIMER S3C_VA_TIMER
-#define S3C2410_PA_TIMER (0x51000000)
-#define S3C24XX_SZ_TIMER SZ_1M
-
-/* Clock and Power management */
-#define S3C24XX_VA_CLKPWR S3C_VA_SYS
-#define S3C24XX_SZ_CLKPWR SZ_1M
-
-/* USB Device port */
-#define S3C2410_PA_USBDEV (0x52000000)
-#define S3C24XX_SZ_USBDEV SZ_1M
-
-/* Watchdog */
-#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG
-#define S3C2410_PA_WATCHDOG (0x53000000)
-#define S3C24XX_SZ_WATCHDOG SZ_1M
-
-/* Standard size definitions for peripheral blocks. */
-
-#define S3C24XX_SZ_IIS SZ_1M
-#define S3C24XX_SZ_ADC SZ_1M
-#define S3C24XX_SZ_SPI SZ_1M
-#define S3C24XX_SZ_SDI SZ_1M
-#define S3C24XX_SZ_NAND SZ_1M
-
-/* GPIO ports */
-
-/* the calculation for the VA of this must ensure that
- * it is the same distance apart from the UART in the
- * phsyical address space, as the initial mapping for the IO
- * is done as a 1:1 mapping. This puts it (currently) at
- * 0xFA800000, which is not in the way of any current mapping
- * by the base system.
-*/
-
-#define S3C2410_PA_GPIO (0x56000000)
-#define S3C24XX_VA_GPIO ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
-#define S3C24XX_SZ_GPIO SZ_1M
-
-
-/* ISA style IO, for each machine to sort out mappings for, if it
- * implements it. We reserve two 16M regions for ISA.
- */
-
-#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000)
-#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000)
-
-/* deal with the registers that move under the 2412/2413 */
-
-#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
-#ifndef __ASSEMBLY__
-extern void __iomem *s3c24xx_va_gpio2;
-#endif
-#ifdef CONFIG_CPU_S3C2412_ONLY
-#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10)
-#else
-#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
-#endif
-#else
-#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
-#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
-#endif
-
-#endif /* __ASM_PLAT_S3C24XX_MAP_H */
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 9843c954c042..9a197e55f669 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -22,7 +22,6 @@ config PLAT_S5P
select PLAT_SAMSUNG
select SAMSUNG_CLKSRC
select SAMSUNG_IRQ_VIC_TIMER
- select SAMSUNG_IRQ_UART
help
Base platform code for Samsung's S5P series SoC.
diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
index bbc2aa7449ca..7b0a28f73a68 100644
--- a/arch/arm/plat-s5p/cpu.c
+++ b/arch/arm/plat-s5p/cpu.c
@@ -33,48 +33,66 @@ static const char name_s5p6450[] = "S5P6450";
static const char name_s5pc100[] = "S5PC100";
static const char name_s5pv210[] = "S5PV210/S5PC110";
static const char name_exynos4210[] = "EXYNOS4210";
+static const char name_exynos4212[] = "EXYNOS4212";
+static const char name_exynos4412[] = "EXYNOS4412";
static struct cpu_table cpu_ids[] __initdata = {
{
- .idcode = 0x56440100,
- .idmask = 0xfffff000,
+ .idcode = S5P6440_CPU_ID,
+ .idmask = S5P64XX_CPU_MASK,
.map_io = s5p6440_map_io,
.init_clocks = s5p6440_init_clocks,
.init_uarts = s5p6440_init_uarts,
.init = s5p64x0_init,
.name = name_s5p6440,
}, {
- .idcode = 0x36450000,
- .idmask = 0xfffff000,
+ .idcode = S5P6450_CPU_ID,
+ .idmask = S5P64XX_CPU_MASK,
.map_io = s5p6450_map_io,
.init_clocks = s5p6450_init_clocks,
.init_uarts = s5p6450_init_uarts,
.init = s5p64x0_init,
.name = name_s5p6450,
}, {
- .idcode = 0x43100000,
- .idmask = 0xfffff000,
+ .idcode = S5PC100_CPU_ID,
+ .idmask = S5PC100_CPU_MASK,
.map_io = s5pc100_map_io,
.init_clocks = s5pc100_init_clocks,
.init_uarts = s5pc100_init_uarts,
.init = s5pc100_init,
.name = name_s5pc100,
}, {
- .idcode = 0x43110000,
- .idmask = 0xfffff000,
+ .idcode = S5PV210_CPU_ID,
+ .idmask = S5PV210_CPU_MASK,
.map_io = s5pv210_map_io,
.init_clocks = s5pv210_init_clocks,
.init_uarts = s5pv210_init_uarts,
.init = s5pv210_init,
.name = name_s5pv210,
}, {
- .idcode = 0x43210000,
- .idmask = 0xfffe0000,
+ .idcode = EXYNOS4210_CPU_ID,
+ .idmask = EXYNOS4_CPU_MASK,
.map_io = exynos4_map_io,
.init_clocks = exynos4_init_clocks,
.init_uarts = exynos4_init_uarts,
.init = exynos4_init,
.name = name_exynos4210,
+ }, {
+ .idcode = EXYNOS4212_CPU_ID,
+ .idmask = EXYNOS4_CPU_MASK,
+ .map_io = exynos4_map_io,
+ .init_clocks = exynos4_init_clocks,
+ .init_uarts = exynos4_init_uarts,
+ .init = exynos4_init,
+ .name = name_exynos4212,
+ }, {
+ .idcode = EXYNOS4412_CPU_ID,
+ .idmask = EXYNOS4_CPU_MASK,
+ .map_io = exynos4_map_io,
+ .init_clocks = exynos4_init_clocks,
+ .init_uarts = exynos4_init_uarts,
+ .init = exynos4_init,
+ .name = name_exynos4412,
},
};
@@ -114,13 +132,13 @@ static struct map_desc s5p_iodesc[] __initdata = {
void __init s5p_init_io(struct map_desc *mach_desc,
int size, void __iomem *cpuid_addr)
{
- unsigned long idcode;
-
/* initialize the io descriptors we need for initialization */
iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
if (mach_desc)
iotable_init(mach_desc, size);
- idcode = __raw_readl(cpuid_addr);
- s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+ /* detect cpu id and rev. */
+ s5p_init_cpu(cpuid_addr);
+
+ s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
}
diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c
index afaf87fdb93e..c9308db36183 100644
--- a/arch/arm/plat-s5p/dev-uart.c
+++ b/arch/arm/plat-s5p/dev-uart.c
@@ -32,20 +32,10 @@ static struct resource s5p_uart0_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX0,
- .end = IRQ_S5P_UART_RX0,
+ .start = IRQ_UART0,
+ .end = IRQ_UART0,
.flags = IORESOURCE_IRQ,
},
- [2] = {
- .start = IRQ_S5P_UART_TX0,
- .end = IRQ_S5P_UART_TX0,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR0,
- .end = IRQ_S5P_UART_ERR0,
- .flags = IORESOURCE_IRQ,
- }
};
static struct resource s5p_uart1_resource[] = {
@@ -55,18 +45,8 @@ static struct resource s5p_uart1_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX1,
- .end = IRQ_S5P_UART_RX1,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S5P_UART_TX1,
- .end = IRQ_S5P_UART_TX1,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR1,
- .end = IRQ_S5P_UART_ERR1,
+ .start = IRQ_UART1,
+ .end = IRQ_UART1,
.flags = IORESOURCE_IRQ,
},
};
@@ -78,18 +58,8 @@ static struct resource s5p_uart2_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX2,
- .end = IRQ_S5P_UART_RX2,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S5P_UART_TX2,
- .end = IRQ_S5P_UART_TX2,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR2,
- .end = IRQ_S5P_UART_ERR2,
+ .start = IRQ_UART2,
+ .end = IRQ_UART2,
.flags = IORESOURCE_IRQ,
},
};
@@ -102,18 +72,8 @@ static struct resource s5p_uart3_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX3,
- .end = IRQ_S5P_UART_RX3,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S5P_UART_TX3,
- .end = IRQ_S5P_UART_TX3,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR3,
- .end = IRQ_S5P_UART_ERR3,
+ .start = IRQ_UART3,
+ .end = IRQ_UART3,
.flags = IORESOURCE_IRQ,
},
#endif
@@ -127,18 +87,8 @@ static struct resource s5p_uart4_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX4,
- .end = IRQ_S5P_UART_RX4,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S5P_UART_TX4,
- .end = IRQ_S5P_UART_TX4,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR4,
- .end = IRQ_S5P_UART_ERR4,
+ .start = IRQ_UART4,
+ .end = IRQ_UART4,
.flags = IORESOURCE_IRQ,
},
#endif
@@ -152,18 +102,8 @@ static struct resource s5p_uart5_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX5,
- .end = IRQ_S5P_UART_RX5,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S5P_UART_TX5,
- .end = IRQ_S5P_UART_TX5,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR5,
- .end = IRQ_S5P_UART_ERR5,
+ .start = IRQ_UART5,
+ .end = IRQ_UART5,
.flags = IORESOURCE_IRQ,
},
#endif
diff --git a/arch/arm/plat-s5p/include/plat/exynos4.h b/arch/arm/plat-s5p/include/plat/exynos4.h
index 907caab53dcf..f680a143e38c 100644
--- a/arch/arm/plat-s5p/include/plat/exynos4.h
+++ b/arch/arm/plat-s5p/include/plat/exynos4.h
@@ -14,10 +14,11 @@
extern void exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
extern void exynos4_register_clocks(void);
+extern void exynos4210_register_clocks(void);
+extern void exynos4212_register_clocks(void);
extern void exynos4_setup_clocks(void);
-#ifdef CONFIG_CPU_EXYNOS4210
-
+#ifdef CONFIG_ARCH_EXYNOS4
extern int exynos4_init(void);
extern void exynos4_init_irq(void);
extern void exynos4_map_io(void);
diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h
index ba9121c60a2a..144dbfc6506d 100644
--- a/arch/arm/plat-s5p/include/plat/irqs.h
+++ b/arch/arm/plat-s5p/include/plat/irqs.h
@@ -37,41 +37,6 @@
#define IRQ_VIC1_BASE S5P_VIC1_BASE
#define IRQ_VIC2_BASE S5P_VIC2_BASE
-/* UART interrupts, each UART has 4 intterupts per channel so
- * use the space between the ISA and S3C main interrupts. Note, these
- * are not in the same order as the S3C24XX series! */
-
-#define IRQ_S5P_UART_BASE0 (16)
-#define IRQ_S5P_UART_BASE1 (20)
-#define IRQ_S5P_UART_BASE2 (24)
-#define IRQ_S5P_UART_BASE3 (28)
-
-#define UART_IRQ_RXD (0)
-#define UART_IRQ_ERR (1)
-#define UART_IRQ_TXD (2)
-
-#define IRQ_S5P_UART_RX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR0 (IRQ_S5P_UART_BASE0 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR1 (IRQ_S5P_UART_BASE1 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR2 (IRQ_S5P_UART_BASE2 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR3 (IRQ_S5P_UART_BASE3 + UART_IRQ_ERR)
-
-/* S3C compatibilty defines */
-#define IRQ_S3CUART_RX0 IRQ_S5P_UART_RX0
-#define IRQ_S3CUART_RX1 IRQ_S5P_UART_RX1
-#define IRQ_S3CUART_RX2 IRQ_S5P_UART_RX2
-#define IRQ_S3CUART_RX3 IRQ_S5P_UART_RX3
-
/* VIC based IRQs */
#define S5P_IRQ_VIC0(x) (S5P_VIC0_BASE + (x))
diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h
index bf28fadee7ae..3e21b9444cc5 100644
--- a/arch/arm/plat-s5p/include/plat/pll.h
+++ b/arch/arm/plat-s5p/include/plat/pll.h
@@ -12,6 +12,59 @@
* published by the Free Software Foundation.
*/
+#include <asm/div64.h>
+
+#define PLL35XX_MDIV_MASK (0x3FF)
+#define PLL35XX_PDIV_MASK (0x3F)
+#define PLL35XX_SDIV_MASK (0x7)
+#define PLL35XX_MDIV_SHIFT (16)
+#define PLL35XX_PDIV_SHIFT (8)
+#define PLL35XX_SDIV_SHIFT (0)
+
+static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
+{
+ u32 mdiv, pdiv, sdiv;
+ u64 fvco = baseclk;
+
+ mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+ pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+ sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
+
+ fvco *= mdiv;
+ do_div(fvco, (pdiv << sdiv));
+
+ return (unsigned long)fvco;
+}
+
+#define PLL36XX_KDIV_MASK (0xFFFF)
+#define PLL36XX_MDIV_MASK (0x1FF)
+#define PLL36XX_PDIV_MASK (0x3F)
+#define PLL36XX_SDIV_MASK (0x7)
+#define PLL36XX_MDIV_SHIFT (16)
+#define PLL36XX_PDIV_SHIFT (8)
+#define PLL36XX_SDIV_SHIFT (0)
+
+static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
+ u32 pll_con0, u32 pll_con1)
+{
+ unsigned long result;
+ u32 mdiv, pdiv, sdiv, kdiv;
+ u64 tmp;
+
+ mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+ pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+ sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
+ kdiv = pll_con1 & PLL36XX_KDIV_MASK;
+
+ tmp = baseclk;
+
+ tmp *= (mdiv << 16) + kdiv;
+ do_div(tmp, (pdiv << sdiv));
+ result = tmp >> 16;
+
+ return result;
+}
+
#define PLL45XX_MDIV_MASK (0x3FF)
#define PLL45XX_PDIV_MASK (0x3F)
#define PLL45XX_SDIV_MASK (0x7)
@@ -19,8 +72,6 @@
#define PLL45XX_PDIV_SHIFT (8)
#define PLL45XX_SDIV_SHIFT (0)
-#include <asm/div64.h>
-
enum pll45xx_type_t {
pll_4500,
pll_4502,
@@ -72,7 +123,6 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
- kdiv = pll_con1 & PLL46XX_KDIV_MASK;
if (pll_type == pll_4650c)
kdiv = pll_con1 & PLL4650C_KDIV_MASK;
diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c
index a97c08957f49..afdaa1082b9f 100644
--- a/arch/arm/plat-s5p/irq.c
+++ b/arch/arm/plat-s5p/irq.c
@@ -17,42 +17,10 @@
#include <asm/hardware/vic.h>
-#include <linux/serial_core.h>
#include <mach/map.h>
#include <plat/regs-timer.h>
-#include <plat/regs-serial.h>
#include <plat/cpu.h>
#include <plat/irq-vic-timer.h>
-#include <plat/irq-uart.h>
-
-/*
- * Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
- * are consecutive when looking up the interrupt in the demux routines.
- */
-static struct s3c_uart_irq uart_irqs[] = {
- [0] = {
- .regs = S5P_VA_UART0,
- .base_irq = IRQ_S5P_UART_BASE0,
- .parent_irq = IRQ_UART0,
- },
- [1] = {
- .regs = S5P_VA_UART1,
- .base_irq = IRQ_S5P_UART_BASE1,
- .parent_irq = IRQ_UART1,
- },
- [2] = {
- .regs = S5P_VA_UART2,
- .base_irq = IRQ_S5P_UART_BASE2,
- .parent_irq = IRQ_UART2,
- },
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
- [3] = {
- .regs = S5P_VA_UART3,
- .base_irq = IRQ_S5P_UART_BASE3,
- .parent_irq = IRQ_UART3,
- },
-#endif
-};
void __init s5p_init_irq(u32 *vic, u32 num_vic)
{
@@ -65,6 +33,4 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic)
#endif
s3c_init_vic_timer_irq(5, IRQ_TIMER0);
-
- s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
}
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index b3e10659e4b8..3895f9aff0dc 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -65,11 +65,6 @@ config SAMSUNG_IRQ_VIC_TIMER
help
Internal configuration to build the VIC timer interrupt code.
-config SAMSUNG_IRQ_UART
- bool
- help
- Internal configuration to build the IRQ UART demux code.
-
# options for gpio configuration support
config SAMSUNG_GPIOLIB_4BIT
@@ -367,4 +362,11 @@ config SAMSUNG_PD
help
Say Y here if you want to control Power Domain by Runtime PM.
+config DEBUG_S3C_UART
+ depends on PLAT_SAMSUNG
+ int
+ default "0" if DEBUG_S3C_UART0
+ default "1" if DEBUG_S3C_UART1
+ default "2" if DEBUG_S3C_UART2
+
endif
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 853764ba8cc5..09adb84f2718 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -11,7 +11,7 @@ obj- :=
# Objects we always build independent of SoC choice
-obj-y += init.o
+obj-y += init.o cpu.o
obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET) += time.o
obj-y += clock.o
obj-y += pwm-clock.o
@@ -21,7 +21,6 @@ obj-y += dev-asocdma.o
obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
-obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o
obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o
# ADC
diff --git a/arch/arm/plat-samsung/cpu.c b/arch/arm/plat-samsung/cpu.c
new file mode 100644
index 000000000000..81c06d44c11e
--- /dev/null
+++ b/arch/arm/plat-samsung/cpu.c
@@ -0,0 +1,58 @@
+/* linux/arch/arm/plat-samsung/cpu.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung CPU Support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+
+#include <mach/map.h>
+#include <plat/cpu.h>
+
+unsigned long samsung_cpu_id;
+static unsigned int samsung_cpu_rev;
+
+unsigned int samsung_rev(void)
+{
+ return samsung_cpu_rev;
+}
+EXPORT_SYMBOL(samsung_rev);
+
+void __init s3c24xx_init_cpu(void)
+{
+ /* nothing here yet */
+
+ samsung_cpu_rev = 0;
+}
+
+void __init s3c64xx_init_cpu(void)
+{
+ samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118);
+ if (!samsung_cpu_id) {
+ /*
+ * S3C6400 has the ID register in a different place,
+ * and needs a write before it can be read.
+ */
+ __raw_writel(0x0, S3C_VA_SYS + 0xA1C);
+ samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0xA1C);
+ }
+
+ samsung_cpu_rev = 0;
+}
+
+void __init s5p_init_cpu(void __iomem *cpuid_addr)
+{
+ samsung_cpu_id = __raw_readl(cpuid_addr);
+ samsung_cpu_rev = samsung_cpu_id & 0xFF;
+}
diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c
index db7a65c7f127..06825c4276de 100644
--- a/arch/arm/plat-samsung/dev-hsmmc.c
+++ b/arch/arm/plat-samsung/dev-hsmmc.c
@@ -58,22 +58,5 @@ struct platform_device s3c_device_hsmmc0 = {
void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
{
- struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata;
-
- set->cd_type = pd->cd_type;
- set->ext_cd_init = pd->ext_cd_init;
- set->ext_cd_cleanup = pd->ext_cd_cleanup;
- set->ext_cd_gpio = pd->ext_cd_gpio;
- set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
- if (pd->max_width)
- set->max_width = pd->max_width;
- if (pd->cfg_gpio)
- set->cfg_gpio = pd->cfg_gpio;
- if (pd->cfg_card)
- set->cfg_card = pd->cfg_card;
- if (pd->host_caps)
- set->host_caps |= pd->host_caps;
- if (pd->clk_type)
- set->clk_type = pd->clk_type;
+ s3c_sdhci_set_platdata(pd, &s3c_hsmmc0_def_platdata);
}
diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c
index 2497321f08d7..4524ef440010 100644
--- a/arch/arm/plat-samsung/dev-hsmmc1.c
+++ b/arch/arm/plat-samsung/dev-hsmmc1.c
@@ -58,22 +58,5 @@ struct platform_device s3c_device_hsmmc1 = {
void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
{
- struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata;
-
- set->cd_type = pd->cd_type;
- set->ext_cd_init = pd->ext_cd_init;
- set->ext_cd_cleanup = pd->ext_cd_cleanup;
- set->ext_cd_gpio = pd->ext_cd_gpio;
- set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
- if (pd->max_width)
- set->max_width = pd->max_width;
- if (pd->cfg_gpio)
- set->cfg_gpio = pd->cfg_gpio;
- if (pd->cfg_card)
- set->cfg_card = pd->cfg_card;
- if (pd->host_caps)
- set->host_caps |= pd->host_caps;
- if (pd->clk_type)
- set->clk_type = pd->clk_type;
+ s3c_sdhci_set_platdata(pd, &s3c_hsmmc1_def_platdata);
}
diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c
index f60aedba417c..9cede9615e48 100644
--- a/arch/arm/plat-samsung/dev-hsmmc2.c
+++ b/arch/arm/plat-samsung/dev-hsmmc2.c
@@ -59,22 +59,5 @@ struct platform_device s3c_device_hsmmc2 = {
void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
{
- struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata;
-
- set->cd_type = pd->cd_type;
- set->ext_cd_init = pd->ext_cd_init;
- set->ext_cd_cleanup = pd->ext_cd_cleanup;
- set->ext_cd_gpio = pd->ext_cd_gpio;
- set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
- if (pd->max_width)
- set->max_width = pd->max_width;
- if (pd->cfg_gpio)
- set->cfg_gpio = pd->cfg_gpio;
- if (pd->cfg_card)
- set->cfg_card = pd->cfg_card;
- if (pd->host_caps)
- set->host_caps |= pd->host_caps;
- if (pd->clk_type)
- set->clk_type = pd->clk_type;
+ s3c_sdhci_set_platdata(pd, &s3c_hsmmc2_def_platdata);
}
diff --git a/arch/arm/plat-samsung/dev-hsmmc3.c b/arch/arm/plat-samsung/dev-hsmmc3.c
index ede776f20e62..0358ef4a8f66 100644
--- a/arch/arm/plat-samsung/dev-hsmmc3.c
+++ b/arch/arm/plat-samsung/dev-hsmmc3.c
@@ -62,22 +62,5 @@ struct platform_device s3c_device_hsmmc3 = {
void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
{
- struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata;
-
- set->cd_type = pd->cd_type;
- set->ext_cd_init = pd->ext_cd_init;
- set->ext_cd_cleanup = pd->ext_cd_cleanup;
- set->ext_cd_gpio = pd->ext_cd_gpio;
- set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
- if (pd->max_width)
- set->max_width = pd->max_width;
- if (pd->cfg_gpio)
- set->cfg_gpio = pd->cfg_gpio;
- if (pd->cfg_card)
- set->cfg_card = pd->cfg_card;
- if (pd->host_caps)
- set->host_caps |= pd->host_caps;
- if (pd->clk_type)
- set->clk_type = pd->clk_type;
+ s3c_sdhci_set_platdata(pd, &s3c_hsmmc3_def_platdata);
}
diff --git a/arch/arm/plat-samsung/dev-ts.c b/arch/arm/plat-samsung/dev-ts.c
index 82543f0248ac..5f3d46a9bd88 100644
--- a/arch/arm/plat-samsung/dev-ts.c
+++ b/arch/arm/plat-samsung/dev-ts.c
@@ -43,8 +43,17 @@ struct platform_device s3c_device_ts = {
.resource = s3c_ts_resource,
};
+static struct s3c2410_ts_mach_info default_ts_data __initdata = {
+ .delay = 10000,
+ .presc = 49,
+ .oversampling_shift = 2,
+};
+
void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
{
+ if (!pd)
+ pd = &default_ts_data;
+
s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
&s3c_device_ts);
}
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index c0a5741b23e6..54f370f0fc07 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -1,9 +1,12 @@
/* linux/arch/arm/plat-samsung/include/plat/cpu.h
*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
* Copyright (c) 2004-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
- * Header file for S3C24XX CPU support
+ * Header file for Samsung CPU support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -15,6 +18,108 @@
#ifndef __SAMSUNG_PLAT_CPU_H
#define __SAMSUNG_PLAT_CPU_H
+extern unsigned long samsung_cpu_id;
+
+#define S3C24XX_CPU_ID 0x32400000
+#define S3C24XX_CPU_MASK 0xFFF00000
+
+#define S3C6400_CPU_ID 0x36400000
+#define S3C6410_CPU_ID 0x36410000
+#define S3C64XX_CPU_ID (S3C6400_CPU_ID & S3C6410_CPU_ID)
+#define S3C64XX_CPU_MASK 0xFFFFF000
+
+#define S5P6440_CPU_ID 0x56440000
+#define S5P6450_CPU_ID 0x36450000
+#define S5P64XX_CPU_MASK 0xFFFFF000
+
+#define S5PC100_CPU_ID 0x43100000
+#define S5PC100_CPU_MASK 0xFFFFF000
+
+#define S5PV210_CPU_ID 0x43110000
+#define S5PV210_CPU_MASK 0xFFFFF000
+
+#define EXYNOS4210_CPU_ID 0x43210000
+#define EXYNOS4212_CPU_ID 0x43220000
+#define EXYNOS4412_CPU_ID 0xE4412200
+#define EXYNOS4_CPU_MASK 0xFFFE0000
+
+#define IS_SAMSUNG_CPU(name, id, mask) \
+static inline int is_samsung_##name(void) \
+{ \
+ return ((samsung_cpu_id & mask) == (id & mask)); \
+}
+
+IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK)
+IS_SAMSUNG_CPU(s3c64xx, S3C64XX_CPU_ID, S3C64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK)
+IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
+
+#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
+ defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \
+ defined(CONFIG_CPU_S3C2442) || defined(CONFIG_CPU_S3C244X) || \
+ defined(CONFIG_CPU_S3C2443)
+# define soc_is_s3c24xx() is_samsung_s3c24xx()
+#else
+# define soc_is_s3c24xx() 0
+#endif
+
+#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
+# define soc_is_s3c64xx() is_samsung_s3c64xx()
+#else
+# define soc_is_s3c64xx() 0
+#endif
+
+#if defined(CONFIG_CPU_S5P6440)
+# define soc_is_s5p6440() is_samsung_s5p6440()
+#else
+# define soc_is_s5p6440() 0
+#endif
+
+#if defined(CONFIG_CPU_S5P6450)
+# define soc_is_s5p6450() is_samsung_s5p6450()
+#else
+# define soc_is_s5p6450() 0
+#endif
+
+#if defined(CONFIG_CPU_S5PC100)
+# define soc_is_s5pc100() is_samsung_s5pc100()
+#else
+# define soc_is_s5pc100() 0
+#endif
+
+#if defined(CONFIG_CPU_S5PV210)
+# define soc_is_s5pv210() is_samsung_s5pv210()
+#else
+# define soc_is_s5pv210() 0
+#endif
+
+#if defined(CONFIG_CPU_EXYNOS4210)
+# define soc_is_exynos4210() is_samsung_exynos4210()
+#else
+# define soc_is_exynos4210() 0
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS4212)
+# define soc_is_exynos4212() is_samsung_exynos4212()
+#else
+# define soc_is_exynos4212() 0
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS4412)
+# define soc_is_exynos4412() is_samsung_exynos4412()
+#else
+# define soc_is_exynos4412() 0
+#endif
+
+#define EXYNOS4210_REV_0 (0x0)
+#define EXYNOS4210_REV_1_0 (0x10)
+#define EXYNOS4210_REV_1_1 (0x11)
+
#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
#ifndef MHZ
@@ -55,6 +160,12 @@ extern void s3c64xx_init_io(struct map_desc *mach_desc, int size);
extern void s5p_init_io(struct map_desc *mach_desc,
int size, void __iomem *cpuid_addr);
+extern void s3c24xx_init_cpu(void);
+extern void s3c64xx_init_cpu(void);
+extern void s5p_init_cpu(void __iomem *cpuid_addr);
+
+extern unsigned int samsung_rev(void);
+
extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
extern void s3c24xx_init_clocks(int xtal);
diff --git a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
index 336d5ac02035..ab9bce637cbd 100644
--- a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
+++ b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
@@ -18,11 +18,6 @@ extern struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
#define DMA_CH_VALID (1<<31)
#define DMA_CH_NEVER (1<<30)
-struct s3c24xx_dma_addr {
- unsigned long from;
- unsigned long to;
-};
-
/* struct s3c24xx_dma_map
*
* this holds the mapping information for the channel selected
@@ -31,7 +26,6 @@ struct s3c24xx_dma_addr {
struct s3c24xx_dma_map {
const char *name;
- struct s3c24xx_dma_addr hw_addr;
unsigned long channels[S3C_DMA_CHANNELS];
unsigned long channels_rx[S3C_DMA_CHANNELS];
diff --git a/arch/arm/plat-samsung/include/plat/map-s3c.h b/arch/arm/plat-samsung/include/plat/map-s3c.h
new file mode 100644
index 000000000000..7d048759b772
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/map-s3c.h
@@ -0,0 +1,84 @@
+/* linux/arch/arm/plat-samsung/include/plat/map-s3c.h
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_MAP_S3C_H
+#define __ASM_PLAT_MAP_S3C_H __FILE__
+
+#define S3C24XX_VA_IRQ S3C_VA_IRQ
+#define S3C24XX_VA_MEMCTRL S3C_VA_MEM
+#define S3C24XX_VA_UART S3C_VA_UART
+
+#define S3C24XX_VA_TIMER S3C_VA_TIMER
+#define S3C24XX_VA_CLKPWR S3C_VA_SYS
+#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG
+
+#define S3C2412_VA_SSMC S3C_ADDR_CPU(0x00000000)
+#define S3C2412_VA_EBI S3C_ADDR_CPU(0x00010000)
+
+#define S3C2410_PA_UART (0x50000000)
+#define S3C24XX_PA_UART S3C2410_PA_UART
+
+#ifndef S3C_UART_OFFSET
+#define S3C_UART_OFFSET (0x400)
+#endif
+
+/*
+ * GPIO ports
+ *
+ * the calculation for the VA of this must ensure that
+ * it is the same distance apart from the UART in the
+ * phsyical address space, as the initial mapping for the IO
+ * is done as a 1:1 mapping. This puts it (currently) at
+ * 0xFA800000, which is not in the way of any current mapping
+ * by the base system.
+*/
+
+#define S3C2410_PA_GPIO (0x56000000)
+#define S3C24XX_PA_GPIO S3C2410_PA_GPIO
+
+#define S3C24XX_VA_GPIO ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
+#define S3C64XX_VA_GPIO S3C_ADDR_CPU(0x00000000)
+
+#define S3C64XX_VA_MODEM S3C_ADDR_CPU(0x00100000)
+#define S3C64XX_VA_USB_HSPHY S3C_ADDR_CPU(0x00200000)
+
+#define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY
+
+/*
+ * ISA style IO, for each machine to sort out mappings for,
+ * if it implements it. We reserve two 16M regions for ISA.
+ */
+
+#define S3C2410_ADDR(x) S3C_ADDR(x)
+
+#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000)
+#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000)
+
+/* deal with the registers that move under the 2412/2413 */
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#ifndef __ASSEMBLY__
+extern void __iomem *s3c24xx_va_gpio2;
+#endif
+#ifdef CONFIG_CPU_S3C2412_ONLY
+#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10)
+#else
+#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
+#endif
+#else
+#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
+#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
+#endif
+
+#include <plat/map-s5p.h>
+
+#endif /* __ASM_PLAT_MAP_S3C_H */
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index 36d3551173b2..c2d7bdae5891 100644
--- a/arch/arm/plat-s5p/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s5p/include/plat/map-s5p.h
+/* linux/arch/arm/plat-samsung/include/plat/map-s5p.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
@@ -40,8 +40,6 @@
#define S5P_VA_GIC_CPU S3C_ADDR(0x02810000)
#define S5P_VA_GIC_DIST S3C_ADDR(0x02820000)
-#define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000)
-
#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
#define VA_VIC0 VA_VIC(0)
#define VA_VIC1 VA_VIC(1)
@@ -58,4 +56,6 @@
#define S3C_UART_OFFSET (0x400)
#endif
+#include <plat/map-s3c.h>
+
#endif /* __ASM_PLAT_MAP_S5P_H */
diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h
index bac36fa3becb..720734847027 100644
--- a/arch/arm/plat-samsung/include/plat/regs-serial.h
+++ b/arch/arm/plat-samsung/include/plat/regs-serial.h
@@ -186,6 +186,11 @@
#define S3C64XX_UINTSP 0x34
#define S3C64XX_UINTM 0x38
+#define S3C64XX_UINTM_RXD (0)
+#define S3C64XX_UINTM_TXD (2)
+#define S3C64XX_UINTM_RXD_MSK (1 << S3C64XX_UINTM_RXD)
+#define S3C64XX_UINTM_TXD_MSK (1 << S3C64XX_UINTM_TXD)
+
/* Following are specific to S5PV210 */
#define S5PV210_UCON_CLKMASK (1<<10)
#define S5PV210_UCON_PCLK (0<<10)
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index 058e09654fe8..4a6552066c7e 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -86,6 +86,13 @@ struct s3c_sdhci_platdata {
struct mmc_card *card);
};
+/* s3c_sdhci_set_platdata() - common helper for setting SDHCI platform data
+ * @pd: The default platform data for this device.
+ * @set: Pointer to the platform data to fill in.
+ */
+extern void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
+ struct s3c_sdhci_platdata *set);
+
/**
* s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
* @pd: Platform data to register to device.
diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c
deleted file mode 100644
index 3014c7226bd1..000000000000
--- a/arch/arm/plat-samsung/irq-uart.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* arch/arm/plat-samsung/irq-uart.c
- * originally part of arch/arm/plat-s3c64xx/irq.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * Samsung- UART Interrupt 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/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/serial_core.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/map.h>
-#include <plat/irq-uart.h>
-#include <plat/regs-serial.h>
-#include <plat/cpu.h>
-
-/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
- * are consecutive when looking up the interrupt in the demux routines.
- */
-static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
-{
- struct s3c_uart_irq *uirq = desc->irq_data.handler_data;
- struct irq_chip *chip = irq_get_chip(irq);
- u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
- int base = uirq->base_irq;
-
- chained_irq_enter(chip, desc);
-
- if (pend & (1 << 0))
- generic_handle_irq(base);
- if (pend & (1 << 1))
- generic_handle_irq(base + 1);
- if (pend & (1 << 2))
- generic_handle_irq(base + 2);
- if (pend & (1 << 3))
- generic_handle_irq(base + 3);
-
- chained_irq_exit(chip, desc);
-}
-
-static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
-{
- void __iomem *reg_base = uirq->regs;
- struct irq_chip_generic *gc;
- struct irq_chip_type *ct;
-
- /* mask all interrupts at the start. */
- __raw_writel(0xf, reg_base + S3C64XX_UINTM);
-
- gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base,
- handle_level_irq);
-
- if (!gc) {
- pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n",
- __func__, uirq->base_irq);
- return;
- }
-
- ct = gc->chip_types;
- ct->chip.irq_ack = irq_gc_ack_set_bit;
- ct->chip.irq_mask = irq_gc_mask_set_bit;
- ct->chip.irq_unmask = irq_gc_mask_clr_bit;
- ct->regs.ack = S3C64XX_UINTP;
- ct->regs.mask = S3C64XX_UINTM;
- irq_setup_generic_chip(gc, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE,
- IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-
- irq_set_handler_data(uirq->parent_irq, uirq);
- irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
-}
-
-/**
- * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing
- * @irq: The interrupt data for registering
- * @nr_irqs: The number of interrupt descriptions in @irq.
- *
- * Register the UART interrupts specified by @irq including the demuxing
- * routines. This supports the S3C6400 and newer style of devices.
- */
-void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs)
-{
- for (; nr_irqs > 0; nr_irqs--, irq++)
- s3c_init_uart_irq(irq);
-}
diff --git a/arch/arm/plat-samsung/platformdata.c b/arch/arm/plat-samsung/platformdata.c
index 7cf2e1e3b20f..6de1a3825927 100644
--- a/arch/arm/plat-samsung/platformdata.c
+++ b/arch/arm/plat-samsung/platformdata.c
@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <plat/devs.h>
+#include <plat/sdhci.h>
void __init *s3c_set_platdata(void *pd, size_t pdsize,
struct platform_device *pdev)
@@ -35,3 +36,24 @@ void __init *s3c_set_platdata(void *pd, size_t pdsize,
pdev->dev.platform_data = npd;
return npd;
}
+
+void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
+ struct s3c_sdhci_platdata *set)
+{
+ set->cd_type = pd->cd_type;
+ set->ext_cd_init = pd->ext_cd_init;
+ set->ext_cd_cleanup = pd->ext_cd_cleanup;
+ set->ext_cd_gpio = pd->ext_cd_gpio;
+ set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
+
+ if (pd->max_width)
+ set->max_width = pd->max_width;
+ if (pd->cfg_gpio)
+ set->cfg_gpio = pd->cfg_gpio;
+ if (pd->cfg_card)
+ set->cfg_card = pd->cfg_card;
+ if (pd->host_caps)
+ set->host_caps |= pd->host_caps;
+ if (pd->clk_type)
+ set->clk_type = pd->clk_type;
+}
diff --git a/arch/arm/plat-spear/include/plat/debug-macro.S b/arch/arm/plat-spear/include/plat/debug-macro.S
index 8501bbf2c092..02b160a1ec9b 100644
--- a/arch/arm/plat-spear/include/plat/debug-macro.S
+++ b/arch/arm/plat-spear/include/plat/debug-macro.S
@@ -14,7 +14,7 @@
#include <linux/amba/serial.h>
#include <mach/hardware.h>
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
mov \rp, #SPEAR_DBG_UART_BASE @ Physical base
mov \rv, #VA_SPEAR_DBG_UART_BASE @ Virtual base
.endm
diff --git a/arch/arm/plat-spear/include/plat/gpio.h b/arch/arm/plat-spear/include/plat/gpio.h
index b857c91257dd..40a8c178f10d 100644
--- a/arch/arm/plat-spear/include/plat/gpio.h
+++ b/arch/arm/plat-spear/include/plat/gpio.h
@@ -1,24 +1 @@
-/*
- * arch/arm/plat-spear/include/plat/gpio.h
- *
- * GPIO macros for SPEAr platform
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __PLAT_GPIO_H
-#define __PLAT_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
-#endif /* __PLAT_GPIO_H */
+/* empty */
diff --git a/arch/arm/plat-spear/include/plat/memory.h b/arch/arm/plat-spear/include/plat/memory.h
deleted file mode 100644
index 7e3599e1104e..000000000000
--- a/arch/arm/plat-spear/include/plat/memory.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/memory.h
- *
- * Memory map for SPEAr platform
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __PLAT_MEMORY_H
-#define __PLAT_MEMORY_H
-
-/* Physical DRAM offset */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#endif /* __PLAT_MEMORY_H */
diff --git a/arch/arm/plat-tcc/include/mach/debug-macro.S b/arch/arm/plat-tcc/include/mach/debug-macro.S
index 7662f736e42b..cf17d04ec30d 100644
--- a/arch/arm/plat-tcc/include/mach/debug-macro.S
+++ b/arch/arm/plat-tcc/include/mach/debug-macro.S
@@ -9,7 +9,7 @@
*
*/
- .macro addruart, rp, rv
+ .macro addruart, rp, rv, tmp
moveq \rp, #0x90000000 @ physical base address
movne \rv, #0xF1000000 @ virtual base
orr \rp, \rp, #0x00007000 @ UART0
diff --git a/arch/arm/plat-tcc/include/mach/memory.h b/arch/arm/plat-tcc/include/mach/memory.h
deleted file mode 100644
index 28a6e0cd13b3..000000000000
--- a/arch/arm/plat-tcc/include/mach/memory.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 1999 ARM Limited
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2008-2009 Telechips
- * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de>
- *
- * Licensed under the terms of the GPL v2.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x20000000)
-
-#endif
diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c
index 51ecfea09b27..92f18d372b69 100644
--- a/arch/arm/plat-versatile/platsmp.c
+++ b/arch/arm/plat-versatile/platsmp.c
@@ -77,7 +77,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
* since we haven't sent them a soft interrupt, they shouldn't
* be there.
*/
- write_pen_release(cpu);
+ write_pen_release(cpu_logical_map(cpu));
/*
* Send the secondary CPU a soft interrupt, thereby causing
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 62cc8f981171..5bdeef969847 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,10 +12,9 @@
#
# http://www.arm.linux.org.uk/developer/machines/?action=new
#
-# XXX: This is a cut-down version of the file; it contains only machines that
-# XXX: are in mainline or have been submitted to the machine database within
-# XXX: the last 12 months. If your entry is missing please email rmk at
-# XXX: <linux@arm.linux.org.uk>
+# This is a cut-down version of the file; it contains only machines that
+# are merged into mainline or have been edited in the machine database
+# within the last 12 months. References to machine_is_NAME() do not count!
#
# Last update: Sat May 7 08:48:24 2011
#
@@ -65,6 +64,7 @@ h7201 ARCH_H7201 H7201 161
h7202 ARCH_H7202 H7202 162
iq80321 ARCH_IQ80321 IQ80321 169
ks8695 ARCH_KS8695 KS8695 180
+karo ARCH_KARO KARO 190
smdk2410 ARCH_SMDK2410 SMDK2410 193
ceiva ARCH_CEIVA CEIVA 200
voiceblue MACH_VOICEBLUE VOICEBLUE 218
@@ -188,6 +188,7 @@ omap_2430sdp MACH_OMAP_2430SDP OMAP_2430SDP 900
davinci_evm MACH_DAVINCI_EVM DAVINCI_EVM 901
palmz72 MACH_PALMZ72 PALMZ72 904
nxdb500 MACH_NXDB500 NXDB500 905
+apf9328 MACH_APF9328 APF9328 906
palmt5 MACH_PALMT5 PALMT5 917
palmtc MACH_PALMTC PALMTC 918
omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919
@@ -271,10 +272,12 @@ pcm038 MACH_PCM038 PCM038 1551
ts_x09 MACH_TS209 TS209 1565
at91cap9adk MACH_AT91CAP9ADK AT91CAP9ADK 1566
mx31moboard MACH_MX31MOBOARD MX31MOBOARD 1574
+vision_ep9307 MACH_VISION_EP9307 VISION_EP9307 1578
terastation_pro2 MACH_TERASTATION_PRO2 TERASTATION_PRO2 1584
linkstation_pro MACH_LINKSTATION_PRO LINKSTATION_PRO 1585
e350 MACH_E350 E350 1596
ts409 MACH_TS409 TS409 1601
+rsi_ews MACH_RSI_EWS RSI_EWS 1609
cm_x300 MACH_CM_X300 CM_X300 1616
at91sam9g20ek MACH_AT91SAM9G20EK AT91SAM9G20EK 1624
smdk6410 MACH_SMDK6410 SMDK6410 1626
@@ -331,6 +334,7 @@ smdkc100 MACH_SMDKC100 SMDKC100 1826
tavorevb MACH_TAVOREVB TAVOREVB 1827
saar MACH_SAAR SAAR 1828
at91sam9m10g45ek MACH_AT91SAM9M10G45EK AT91SAM9M10G45EK 1830
+usb_a9g20 MACH_USB_A9G20 USB_A9G20 1841
mxlads MACH_MXLADS MXLADS 1851
linkstation_mini MACH_LINKSTATION_MINI LINKSTATION_MINI 1858
afeb9260 MACH_AFEB9260 AFEB9260 1859
@@ -369,6 +373,7 @@ pcm043 MACH_PCM043 PCM043 2072
sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097
avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104
mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125
+tx37 MACH_TX37 TX37 2127
rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135
dm355_leopard MACH_DM355_LEOPARD DM355_LEOPARD 2138
ts219 MACH_TS219 TS219 2139
@@ -379,6 +384,7 @@ omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160
magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162
btmavb101 MACH_BTMAVB101 BTMAVB101 2172
btmawb101 MACH_BTMAWB101 BTMAWB101 2173
+tx25 MACH_TX25 TX25 2177
omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178
anw6410 MACH_ANW6410 ANW6410 2183
imx27_visstrim_m10 MACH_IMX27_VISSTRIM_M10 IMX27_VISSTRIM_M10 2187
@@ -423,6 +429,7 @@ raumfeld_rc MACH_RAUMFELD_RC RAUMFELD_RC 2413
raumfeld_connector MACH_RAUMFELD_CONNECTOR RAUMFELD_CONNECTOR 2414
raumfeld_speaker MACH_RAUMFELD_SPEAKER RAUMFELD_SPEAKER 2415
tnetv107x MACH_TNETV107X TNETV107X 2418
+mx51_m2id MACH_MX51_M2ID MX51_M2ID 2428
smdkv210 MACH_SMDKV210 SMDKV210 2456
omap_zoom3 MACH_OMAP_ZOOM3 OMAP_ZOOM3 2464
omap_3630sdp MACH_OMAP_3630SDP OMAP_3630SDP 2465
@@ -433,14 +440,17 @@ omapl138_hawkboard MACH_OMAPL138_HAWKBOARD OMAPL138_HAWKBOARD 2495
ts41x MACH_TS41X TS41X 2502
phy3250 MACH_PHY3250 PHY3250 2511
mini6410 MACH_MINI6410 MINI6410 2520
+tx51 MACH_TX51 TX51 2529
mx28evk MACH_MX28EVK MX28EVK 2531
smartq5 MACH_SMARTQ5 SMARTQ5 2534
davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548
mxt_td60 MACH_MXT_TD60 MXT_TD60 2550
riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576
riot_x37 MACH_RIOT_X37 RIOT_X37 2578
+pca101 MACH_PCA101 PCA101 2595
capc7117 MACH_CAPC7117 CAPC7117 2612
icontrol MACH_ICONTROL ICONTROL 2624
+gplugd MACH_GPLUGD GPLUGD 2625
qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627
mx23evk MACH_MX23EVK MX23EVK 2629
ap4evb MACH_AP4EVB AP4EVB 2630
@@ -1113,3 +1123,5 @@ blissc MACH_BLISSC BLISSC 3491
thales_adc MACH_THALES_ADC THALES_ADC 3492
ubisys_p9d_evp MACH_UBISYS_P9D_EVP UBISYS_P9D_EVP 3493
atdgp318 MACH_ATDGP318 ATDGP318 3494
+smdk4212 MACH_SMDK4212 SMDK4212 3638
+smdk4412 MACH_SMDK4412 SMDK4412 3765
diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile
index 6de73aab0195..a81404c09d5d 100644
--- a/arch/arm/vfp/Makefile
+++ b/arch/arm/vfp/Makefile
@@ -7,7 +7,7 @@
# ccflags-y := -DDEBUG
# asflags-y := -DDEBUG
-KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
+KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp -mfloat-abi=soft)
LDFLAGS +=--no-warn-mismatch
obj-y += vfp.o
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 79bcb4316930..0cbd5a0a9332 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/cpu.h>
+#include <linux/cpu_pm.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/signal.h>
@@ -68,7 +69,7 @@ static bool vfp_state_in_hw(unsigned int cpu, struct thread_info *thread)
/*
* Force a reload of the VFP context from the thread structure. We do
* this by ensuring that access to the VFP hardware is disabled, and
- * clear last_VFP_context. Must be called from non-preemptible context.
+ * clear vfp_current_hw_state. Must be called from non-preemptible context.
*/
static void vfp_force_reload(unsigned int cpu, struct thread_info *thread)
{
@@ -436,9 +437,7 @@ static void vfp_enable(void *unused)
set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11));
}
-#ifdef CONFIG_PM
-#include <linux/syscore_ops.h>
-
+#ifdef CONFIG_CPU_PM
static int vfp_pm_suspend(void)
{
struct thread_info *ti = current_thread_info();
@@ -468,19 +467,33 @@ static void vfp_pm_resume(void)
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
}
-static struct syscore_ops vfp_pm_syscore_ops = {
- .suspend = vfp_pm_suspend,
- .resume = vfp_pm_resume,
+static int vfp_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ switch (cmd) {
+ case CPU_PM_ENTER:
+ vfp_pm_suspend();
+ break;
+ case CPU_PM_ENTER_FAILED:
+ case CPU_PM_EXIT:
+ vfp_pm_resume();
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block vfp_cpu_pm_notifier_block = {
+ .notifier_call = vfp_cpu_pm_notifier,
};
static void vfp_pm_init(void)
{
- register_syscore_ops(&vfp_pm_syscore_ops);
+ cpu_pm_register_notifier(&vfp_cpu_pm_notifier_block);
}
#else
static inline void vfp_pm_init(void) { }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_CPU_PM */
/*
* Ensure that the VFP state stored in 'thread->vfpstate' is up to date
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index c7476295de80..abe5a9e85148 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -248,10 +248,6 @@ config HOTPLUG_CPU
depends on SMP && HOTPLUG
default y
-config HAVE_LEGACY_PER_CPU_AREA
- def_bool y
- depends on SMP
-
config BF_REV_MIN
int
default 0 if (BF51x || BF52x || (BF54x && !BF54xM))
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
index 56151b5dbc44..0e6d841b5d01 100644
--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -4,7 +4,6 @@ CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_ELF_CORE is not set
@@ -40,7 +39,6 @@ CONFIG_EBIU_MODEVAL=0x1
CONFIG_EBIU_FCTLVAL=0x6
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
-CONFIG_PM=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -55,7 +53,6 @@ CONFIG_IP_PNP=y
CONFIG_CAN=m
CONFIG_CAN_RAW=m
CONFIG_CAN_BCM=m
-CONFIG_CAN_DEV=m
CONFIG_CAN_BFIN=m
CONFIG_IRDA=m
CONFIG_IRLAN=m
@@ -67,7 +64,6 @@ CONFIG_BFIN_SIR3=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_FW_LOADER=m
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
@@ -105,12 +101,12 @@ CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_AD7877=m
CONFIG_INPUT_MISC=y
# CONFIG_SERIO is not set
-# CONFIG_DEVKMEM is not set
+# CONFIG_LEGACY_PTYS is not set
CONFIG_BFIN_JTAG_COMM=m
+# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_BFIN=y
CONFIG_SERIAL_BFIN_CONSOLE=y
CONFIG_SERIAL_BFIN_UART1=y
-# CONFIG_LEGACY_PTYS is not set
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
@@ -163,6 +159,7 @@ CONFIG_USB_DEVICEFS=y
CONFIG_USB_OTG_BLACKLIST_HUB=y
CONFIG_USB_MON=y
CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_BLACKFIN=y
CONFIG_USB_STORAGE=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=m
@@ -185,8 +182,6 @@ CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
CONFIG_CIFS=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_936=m
@@ -196,7 +191,6 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_SHIRQ=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_FTRACE is not set
CONFIG_DEBUG_MMRS=y
CONFIG_DEBUG_HWERR=y
@@ -206,5 +200,4 @@ CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
CONFIG_EARLY_PRINTK=y
CONFIG_CPLB_INFO=y
CONFIG_BFIN_PSEUDODBG_INSNS=y
-CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 7a075eaf6041..5a0625aad6a0 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -21,6 +21,7 @@ generic-y += local64.h
generic-y += local.h
generic-y += mman.h
generic-y += msgbuf.h
+generic-y += mutex.h
generic-y += param.h
generic-y += percpu.h
generic-y += pgalloc.h
diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h
index 135225696fd2..54c6e2887e9f 100644
--- a/arch/blackfin/include/asm/atomic.h
+++ b/arch/blackfin/include/asm/atomic.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2009 Analog Devices Inc.
+ * Copyright 2004-2011 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
@@ -7,111 +7,27 @@
#ifndef __ARCH_BLACKFIN_ATOMIC__
#define __ARCH_BLACKFIN_ATOMIC__
-#ifndef CONFIG_SMP
-# include <asm-generic/atomic.h>
-#else
+#ifdef CONFIG_SMP
-#include <linux/types.h>
-#include <asm/system.h> /* local_irq_XXX() */
-
-/*
- * Atomic operations that C can't guarantee us. Useful for
- * resource counting etc..
- */
-
-#define ATOMIC_INIT(i) { (i) }
-#define atomic_set(v, i) (((v)->counter) = i)
-
-#define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter)
+#include <linux/linkage.h>
asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr);
-
asmlinkage int __raw_atomic_update_asm(volatile int *ptr, int value);
-
asmlinkage int __raw_atomic_clear_asm(volatile int *ptr, int value);
-
asmlinkage int __raw_atomic_set_asm(volatile int *ptr, int value);
-
asmlinkage int __raw_atomic_xor_asm(volatile int *ptr, int value);
-
asmlinkage int __raw_atomic_test_asm(const volatile int *ptr, int value);
-static inline void atomic_add(int i, atomic_t *v)
-{
- __raw_atomic_update_asm(&v->counter, i);
-}
-
-static inline void atomic_sub(int i, atomic_t *v)
-{
- __raw_atomic_update_asm(&v->counter, -i);
-}
-
-static inline int atomic_add_return(int i, atomic_t *v)
-{
- return __raw_atomic_update_asm(&v->counter, i);
-}
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
- return __raw_atomic_update_asm(&v->counter, -i);
-}
+#define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter)
-static inline void atomic_inc(volatile atomic_t *v)
-{
- __raw_atomic_update_asm(&v->counter, 1);
-}
-
-static inline void atomic_dec(volatile atomic_t *v)
-{
- __raw_atomic_update_asm(&v->counter, -1);
-}
-
-static inline void atomic_clear_mask(int mask, atomic_t *v)
-{
- __raw_atomic_clear_asm(&v->counter, mask);
-}
-
-static inline void atomic_set_mask(int mask, atomic_t *v)
-{
- __raw_atomic_set_asm(&v->counter, mask);
-}
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec() barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc() barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
-#define atomic_dec_return(v) atomic_sub_return(1,(v))
-#define atomic_inc_return(v) atomic_add_return(1,(v))
-
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-#define __atomic_add_unless(v, a, u) \
-({ \
- int c, old; \
- c = atomic_read(v); \
- while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
- c = old; \
- c; \
-})
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
-
-#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
-#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+#define atomic_add_return(i, v) __raw_atomic_update_asm(&(v)->counter, i)
+#define atomic_sub_return(i, v) __raw_atomic_update_asm(&(v)->counter, -(i))
+#define atomic_clear_mask(m, v) __raw_atomic_clear_asm(&(v)->counter, m)
+#define atomic_set_mask(m, v) __raw_atomic_set_asm(&(v)->counter, m)
#endif
+#include <asm-generic/atomic.h>
+
#endif
diff --git a/arch/blackfin/include/asm/mutex.h b/arch/blackfin/include/asm/mutex.h
deleted file mode 100644
index ff6101aa2c71..000000000000
--- a/arch/blackfin/include/asm/mutex.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h
index 1c0d190adaef..5cc111502822 100644
--- a/arch/blackfin/include/asm/uaccess.h
+++ b/arch/blackfin/include/asm/uaccess.h
@@ -195,17 +195,17 @@ static inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long n)
{
if (access_ok(VERIFY_READ, from, n))
- memcpy(to, from, n);
+ memcpy(to, (const void __force *)from, n);
else
return n;
return 0;
}
static inline unsigned long __must_check
-copy_to_user(void *to, const void __user *from, unsigned long n)
+copy_to_user(void __user *to, const void *from, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
- memcpy(to, from, n);
+ memcpy((void __force *)to, from, n);
else
return n;
return 0;
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index b7bdc42fe1a3..1f88edd4572a 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -38,6 +38,6 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.o
# the kgdb test puts code into L2 and without linker
# relaxation, we need to force long calls to/from it
-CFLAGS_kgdb_test.o := -mlong-calls -O0
+CFLAGS_kgdb_test.o := -mlong-calls
obj-$(CONFIG_DEBUG_MMRS) += debug-mmrs.o
diff --git a/arch/blackfin/kernel/kgdb_test.c b/arch/blackfin/kernel/kgdb_test.c
index 2a6e9dbb62a5..4a7dcfea98af 100644
--- a/arch/blackfin/kernel/kgdb_test.c
+++ b/arch/blackfin/kernel/kgdb_test.c
@@ -50,8 +50,7 @@ void kgdb_l2_test(void)
#endif
-
-int kgdb_test(char *name, int len, int count, int z)
+noinline int kgdb_test(char *name, int len, int count, int z)
{
pr_alert("kgdb name(%d): %s, %d, %d\n", len, name, count, z);
count = z;
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c
index 9e9b60d969dc..1bcf3a3c57d8 100644
--- a/arch/blackfin/kernel/time-ts.c
+++ b/arch/blackfin/kernel/time-ts.c
@@ -188,8 +188,7 @@ irqreturn_t bfin_gptmr0_interrupt(int irq, void *dev_id)
static struct irqaction gptmr0_irq = {
.name = "Blackfin GPTimer0",
- .flags = IRQF_DISABLED | IRQF_TIMER | \
- IRQF_IRQPOLL | IRQF_PERCPU,
+ .flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_PERCPU,
.handler = bfin_gptmr0_interrupt,
};
@@ -297,8 +296,7 @@ irqreturn_t bfin_coretmr_interrupt(int irq, void *dev_id)
static struct irqaction coretmr_irq = {
.name = "Blackfin CoreTimer",
- .flags = IRQF_DISABLED | IRQF_TIMER | \
- IRQF_IRQPOLL | IRQF_PERCPU,
+ .flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_PERCPU,
.handler = bfin_coretmr_interrupt,
};
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index ceb2bf63dfe2..2310b249675f 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -25,7 +25,6 @@
static struct irqaction bfin_timer_irq = {
.name = "Blackfin Timer Tick",
- .flags = IRQF_DISABLED
};
#if defined(CONFIG_IPIPE)
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
index eb325ed6607e..5da5787fc4ef 100644
--- a/arch/blackfin/mach-bf533/boards/H8606.c
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -54,7 +54,8 @@ static struct resource dm9000_resources[] = {
[2] = {
.start = IRQ_PF10,
.end = IRQ_PF10,
- .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IRQF_SHARED | IRQF_TRIGGER_HIGH),
+ .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
+ IORESOURCE_IRQ_SHAREABLE),
},
};
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537e.c b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
index 44fd8409db10..9fb20d6d8f91 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537e.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
@@ -605,7 +605,7 @@ static struct platform_device bfin_mac_device = {
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 2,
- .irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+ .irq_type = IRQF_TRIGGER_HIGH,
};
static struct resource bfin_pata_resources[] = {
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537u.c b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
index 1b4ac5c64aae..5ba389fc61ae 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537u.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
@@ -570,7 +570,7 @@ static struct platform_device bfin_mac_device = {
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 2,
- .irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+ .irq_type = IRQF_TRIGGER_HIGH,
};
static struct resource bfin_pata_resources[] = {
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index b52e6728f64f..6c916a67ef68 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -962,10 +962,10 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
- || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
{
- .modalias = "ad183x",
+ .modalias = "ad1836",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 4,
@@ -984,9 +984,9 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+#if defined(CONFIG_SND_SOC_ADAV80X) || defined(CONFIG_SND_SOC_ADV80X_MODULE)
{
- .modalias = "adav80x",
+ .modalias = "adav801",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 1,
@@ -2101,7 +2101,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
},
#endif
-#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+#if defined(CONFIG_SND_SOC_ADAV80X) || defined(CONFIG_SND_SOC_ADAV80X_MODULE)
{
I2C_BOARD_INFO("adav803", 0x10),
},
@@ -2134,23 +2134,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
},
#endif
-#if defined(CONFIG_AD7414) || defined(CONFIG_AD7414_MODULE)
- {
- I2C_BOARD_INFO("ad7414", 0x9),
- .irq = IRQ_PG5,
- .irq_flags = IRQF_TRIGGER_LOW,
- },
-#endif
-
-#if defined(CONFIG_AD7416) || defined(CONFIG_AD7416_MODULE)
- {
- I2C_BOARD_INFO("ad7417", 0xb),
- .irq = IRQ_PG5,
- .irq_flags = IRQF_TRIGGER_LOW,
- .platform_data = (void *)GPIO_PF4,
- },
-#endif
-
#if defined(CONFIG_ADE7854_I2C) || defined(CONFIG_ADE7854_I2C_MODULE)
{
I2C_BOARD_INFO("ade7854", 0x38),
@@ -2161,15 +2144,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
{
I2C_BOARD_INFO("adt75", 0x9),
.irq = IRQ_PG5,
- .irq_flags = IRQF_TRIGGER_LOW,
- },
-#endif
-
-#if defined(CONFIG_ADT7408) || defined(CONFIG_ADT7408_MODULE)
- {
- I2C_BOARD_INFO("adt7408", 0x18),
- .irq = IRQ_PG5,
- .irq_flags = IRQF_TRIGGER_LOW,
},
#endif
@@ -2178,7 +2152,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
I2C_BOARD_INFO("adt7410", 0x48),
/* CT critical temperature event. line 0 */
.irq = IRQ_PG5,
- .irq_flags = IRQF_TRIGGER_LOW,
.platform_data = (void *)&adt7410_platform_data,
},
#endif
@@ -2187,7 +2160,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
{
I2C_BOARD_INFO("ad7291", 0x20),
.irq = IRQ_PG5,
- .irq_flags = IRQF_TRIGGER_LOW,
},
#endif
@@ -2275,6 +2247,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
I2C_BOARD_INFO("adau1361", 0x38),
},
#endif
+#if defined(CONFIG_SND_SOC_ADAU1701) || defined(CONFIG_SND_SOC_ADAU1701_MODULE)
+ {
+ I2C_BOARD_INFO("adau1701", 0x34),
+ },
+#endif
#if defined(CONFIG_AD525X_DPOT) || defined(CONFIG_AD525X_DPOT_MODULE)
{
I2C_BOARD_INFO("ad5258", 0x18),
@@ -2388,7 +2365,7 @@ static struct platform_device bfin_sport1_uart_device = {
#define PATA_INT IRQ_PF5
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 1,
- .irq_flags = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+ .irq_flags = IRQF_TRIGGER_HIGH,
};
static struct resource bfin_pata_resources[] = {
@@ -2540,13 +2517,21 @@ static struct platform_device bfin_ac97_pcm = {
};
#endif
-#if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
+#if defined(CONFIG_SND_SOC_AD73311) || defined(CONFIG_SND_SOC_AD73311_MODULE)
static struct platform_device bfin_ad73311_codec_device = {
.name = "ad73311",
.id = -1,
};
#endif
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) || \
+ defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X_MODULE)
+static struct platform_device bfin_eval_adav801_device = {
+ .name = "bfin-eval-adav801",
+ .id = -1,
+};
+#endif
+
#if defined(CONFIG_SND_BF5XX_SOC_I2S) || defined(CONFIG_SND_BF5XX_SOC_I2S_MODULE)
static struct platform_device bfin_i2s = {
.name = "bfin-i2s",
@@ -2661,6 +2646,20 @@ static struct platform_device iio_gpio_trigger = {
};
#endif
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) || \
+ defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373_MODULE)
+static struct platform_device bf5xx_adau1373_device = {
+ .name = "bfin-eval-adau1373",
+};
+#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) || \
+ defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701_MODULE)
+static struct platform_device bf5xx_adau1701_device = {
+ .name = "bfin-eval-adau1701",
+};
+#endif
+
static struct platform_device *stamp_devices[] __initdata = {
&bfin_dpmc,
@@ -2782,7 +2781,7 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_ac97_pcm,
#endif
-#if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
+#if defined(CONFIG_SND_SOC_AD73311) || defined(CONFIG_SND_SOC_AD73311_MODULE)
&bfin_ad73311_codec_device,
#endif
@@ -2821,6 +2820,21 @@ static struct platform_device *stamp_devices[] __initdata = {
defined(CONFIG_IIO_GPIO_TRIGGER_MODULE)
&iio_gpio_trigger,
#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) || \
+ defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373_MODULE)
+ &bf5xx_adau1373_device,
+#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) || \
+ defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701_MODULE)
+ &bf5xx_adau1701_device,
+#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) || \
+ defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X_MODULE)
+ &bfin_eval_adav801_device,
+#endif
};
static int __init net2272_init(void)
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index 9b7287abdfa1..2da0316d890e 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -572,7 +572,7 @@ static struct platform_device bfin_mac_device = {
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 2,
- .irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+ .irq_type = IRQF_TRIGGER_HIGH,
};
static struct resource bfin_pata_resources[] = {
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index e4f397d1d65b..c1b72f2d6354 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -348,7 +348,7 @@ static struct platform_device bfin_sir0_device = {
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 2,
- .irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+ .irq_type = IRQF_TRIGGER_HIGH,
};
static struct resource bfin_pata_resources[] = {
diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c
index 85abd8be1343..db22401e7605 100644
--- a/arch/blackfin/mach-bf561/smp.c
+++ b/arch/blackfin/mach-bf561/smp.c
@@ -114,7 +114,7 @@ void __init platform_request_ipi(int irq, void *handler)
int ret;
const char *name = (irq == IRQ_SUPPLE_0) ? supple0 : supple1;
- ret = request_irq(irq, handler, IRQF_DISABLED | IRQF_PERCPU, name, handler);
+ ret = request_irq(irq, handler, IRQF_PERCPU, name, handler);
if (ret)
panic("Cannot request %s for IPI service", name);
}
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index 107622aacf6b..0784a52389c8 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -295,10 +295,15 @@ EXPORT_SYMBOL_GPL(smp_call_function_single);
void smp_send_reschedule(int cpu)
{
+ cpumask_t callmap;
/* simply trigger an ipi */
if (cpu_is_offline(cpu))
return;
- platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
+
+ cpumask_clear(&callmap);
+ cpumask_set_cpu(cpu, &callmap);
+
+ smp_send_message(callmap, BFIN_IPI_RESCHEDULE, NULL, NULL, 0);
return;
}
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 17addacb169e..408b055c585f 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -282,8 +282,8 @@ config ETRAX_RTC
Enables drivers for the Real-Time Clock battery-backed chips on
some products. The kernel reads the time when booting, and
the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
- rtc_time struct (see <file:include/asm-cris/rtc.h>) on the /dev/rtc
- device. You can check the time with cat /proc/rtc, but
+ rtc_time struct (see <file:arch/cris/include/asm/rtc.h>) on the
+ /dev/rtc device. You can check the time with cat /proc/rtc, but
normal time reading should be done using libc function time and
friends.
diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig
index adc164e99339..df9a38b4f18f 100644
--- a/arch/cris/arch-v10/Kconfig
+++ b/arch/cris/arch-v10/Kconfig
@@ -24,8 +24,8 @@ config ETRAX_PA_LEDS
help
The ETRAX network driver is responsible for flashing LED's when
packets arrive and are sent. It uses macros defined in
- <file:include/asm-cris/io.h>, and those macros are defined after what
- YOU choose in this option. The actual bits used are configured
+ <file:arch/cris/include/asm/io.h>, and those macros are defined after
+ what YOU choose in this option. The actual bits used are configured
separately. Select this if the LEDs are on port PA. Some products
put the leds on PB or a memory-mapped latch (CSP0) instead.
@@ -34,8 +34,8 @@ config ETRAX_PB_LEDS
help
The ETRAX network driver is responsible for flashing LED's when
packets arrive and are sent. It uses macros defined in
- <file:include/asm-cris/io.h>, and those macros are defined after what
- YOU choose in this option. The actual bits used are configured
+ <file:arch/cris/include/asm/io.h>, and those macros are defined after
+ what YOU choose in this option. The actual bits used are configured
separately. Select this if the LEDs are on port PB. Some products
put the leds on PA or a memory-mapped latch (CSP0) instead.
@@ -44,8 +44,8 @@ config ETRAX_CSP0_LEDS
help
The ETRAX network driver is responsible for flashing LED's when
packets arrive and are sent. It uses macros defined in
- <file:include/asm-cris/io.h>, and those macros are defined after what
- YOU choose in this option. The actual bits used are configured
+ <file:arch/cris/include/asm/io.h>, and those macros are defined after
+ what YOU choose in this option. The actual bits used are configured
separately. Select this if the LEDs are on a memory-mapped latch
using chip select CSP0, this is mapped at 0x90000000.
Some products put the leds on PA or PB instead.
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index 0d7221779923..32d90867a984 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -4,6 +4,7 @@ config ETRAX_ETHERNET
bool "Ethernet support"
depends on ETRAX_ARCH_V10
select NET_ETHERNET
+ select NET_CORE
select MII
help
This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c
index b9f9c8ce2169..b579dd02e098 100644
--- a/arch/cris/arch-v10/kernel/kgdb.c
+++ b/arch/cris/arch-v10/kernel/kgdb.c
@@ -694,7 +694,7 @@ mem2hex(char *buf, unsigned char *mem, int count)
/* Valid mem address. */
for (i = 0; i < count; i++) {
ch = *mem++;
- buf = pack_hex_byte(buf, ch);
+ buf = hex_byte_pack(buf, ch);
}
}
@@ -868,7 +868,7 @@ stub_is_stopped(int sigval)
/* Send trap type (converted to signal) */
*ptr++ = 'T';
- ptr = pack_hex_byte(ptr, sigval);
+ ptr = hex_byte_pack(ptr, sigval);
/* Send register contents. We probably only need to send the
* PC, frame pointer and stack pointer here. Other registers will be
@@ -881,7 +881,7 @@ stub_is_stopped(int sigval)
status = read_register (regno, &reg_cont);
if (status == SUCCESS) {
- ptr = pack_hex_byte(ptr, regno);
+ ptr = hex_byte_pack(ptr, regno);
*ptr++ = ':';
ptr = mem2hex(ptr, (unsigned char *)&reg_cont,
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 41a2732e8b9c..e47e9c3401b0 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -4,6 +4,7 @@ config ETRAX_ETHERNET
bool "Ethernet support"
depends on ETRAX_ARCH_V32
select NET_ETHERNET
+ select NET_CORE
select MII
help
This option enables the ETRAX FS built-in 10/100Mbit Ethernet
diff --git a/arch/cris/arch-v32/kernel/kgdb.c b/arch/cris/arch-v32/kernel/kgdb.c
index c0343c3ea7f8..8c1d35cdf00a 100644
--- a/arch/cris/arch-v32/kernel/kgdb.c
+++ b/arch/cris/arch-v32/kernel/kgdb.c
@@ -677,7 +677,7 @@ mem2hex(char *buf, unsigned char *mem, int count)
/* Valid mem address. */
for (i = 0; i < count; i++) {
ch = *mem++;
- buf = pack_hex_byte(buf, ch);
+ buf = hex_byte_pack(buf, ch);
}
}
/* Terminate properly. */
@@ -695,7 +695,7 @@ mem2hex_nbo(char *buf, unsigned char *mem, int count)
mem += count - 1;
for (i = 0; i < count; i++) {
ch = *mem--;
- buf = pack_hex_byte(buf, ch);
+ buf = hex_byte_pack(buf, ch);
}
/* Terminate properly. */
@@ -880,7 +880,7 @@ stub_is_stopped(int sigval)
/* Send trap type (converted to signal) */
*ptr++ = 'T';
- ptr = pack_hex_byte(ptr, sigval);
+ ptr = hex_byte_pack(ptr, sigval);
if (((reg.exs & 0xff00) >> 8) == 0xc) {
@@ -988,26 +988,26 @@ stub_is_stopped(int sigval)
}
/* Only send PC, frame and stack pointer. */
read_register(PC, &reg_cont);
- ptr = pack_hex_byte(ptr, PC);
+ ptr = hex_byte_pack(ptr, PC);
*ptr++ = ':';
ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[PC]);
*ptr++ = ';';
read_register(R8, &reg_cont);
- ptr = pack_hex_byte(ptr, R8);
+ ptr = hex_byte_pack(ptr, R8);
*ptr++ = ':';
ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[R8]);
*ptr++ = ';';
read_register(SP, &reg_cont);
- ptr = pack_hex_byte(ptr, SP);
+ ptr = hex_byte_pack(ptr, SP);
*ptr++ = ':';
ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[SP]);
*ptr++ = ';';
/* Send ERP as well; this will save us an entire register fetch in some cases. */
read_register(ERP, &reg_cont);
- ptr = pack_hex_byte(ptr, ERP);
+ ptr = hex_byte_pack(ptr, ERP);
*ptr++ = ':';
ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[ERP]);
*ptr++ = ';';
diff --git a/arch/cris/arch-v32/lib/nand_init.S b/arch/cris/arch-v32/lib/nand_init.S
deleted file mode 100644
index d671fed451c9..000000000000
--- a/arch/cris/arch-v32/lib/nand_init.S
+++ /dev/null
@@ -1,178 +0,0 @@
-##=============================================================================
-##
-## nand_init.S
-##
-## The bootrom copies data from the NAND flash to the internal RAM but
-## due to a bug/feature we can only trust the 256 first bytes. So this
-## code copies more data from NAND flash to internal RAM. Obvioulsy this
-## code must fit in the first 256 bytes so alter with care.
-##
-## Some notes about the bug/feature for future reference:
-## The bootrom copies the first 127 KB from NAND flash to internal
-## memory. The problem is that it does a bytewise copy. NAND flashes
-## does autoincrement on the address so for a 16-bite device each
-## read/write increases the address by two. So the copy loop in the
-## bootrom will discard every second byte. This is solved by inserting
-## zeroes in every second byte in the first erase block.
-##
-## The bootrom also incorrectly assumes that it can read the flash
-## linear with only one read command but the flash will actually
-## switch between normal area and spare area if you do that so we
-## can't trust more than the first 256 bytes.
-##
-##=============================================================================
-
-#include <arch/hwregs/asm/reg_map_asm.h>
-#include <arch/hwregs/asm/gio_defs_asm.h>
-#include <arch/hwregs/asm/pinmux_defs_asm.h>
-#include <arch/hwregs/asm/bif_core_defs_asm.h>
-#include <arch/hwregs/asm/config_defs_asm.h>
-
-;; There are 8-bit NAND flashes and 16-bit NAND flashes.
-;; We need to treat them slightly different.
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
-#define PAGE_SIZE 256
-#else
-#error 2
-#define PAGE_SIZE 512
-#endif
-#define ERASE_BLOCK 16384
-
-;; GPIO pins connected to NAND flash
-#define CE 4
-#define CLE 5
-#define ALE 6
-#define BY 7
-
-;; Address space for NAND flash
-#define NAND_RD_ADDR 0x90000000
-#define NAND_WR_ADDR 0x94000000
-
-#define READ_CMD 0x00
-
-;; Readability macros
-#define CSP_MASK \
- REG_MASK(bif_core, rw_grp3_cfg, gated_csp0) | \
- REG_MASK(bif_core, rw_grp3_cfg, gated_csp1)
-#define CSP_VAL \
- REG_STATE(bif_core, rw_grp3_cfg, gated_csp0, rd) | \
- REG_STATE(bif_core, rw_grp3_cfg, gated_csp1, wr)
-
-;;----------------------------------------------------------------------------
-;; Macros to set/clear GPIO bits
-
-.macro SET x
- or.b (1<<\x),$r9
- move.d $r9, [$r2]
-.endm
-
-.macro CLR x
- and.b ~(1<<\x),$r9
- move.d $r9, [$r2]
-.endm
-
-;;----------------------------------------------------------------------------
-
-nand_boot:
- ;; Check if nand boot was selected
- move.d REG_ADDR(config, regi_config, r_bootsel), $r0
- move.d [$r0], $r0
- and.d REG_MASK(config, r_bootsel, boot_mode), $r0
- cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0
- bne normal_boot ; No NAND boot
- nop
-
-copy_nand_to_ram:
- ;; copy_nand_to_ram
- ;; Arguments
- ;; r10 - destination
- ;; r11 - source offset
- ;; r12 - size
- ;; r13 - Address to jump to after completion
- ;; Note : r10-r12 are clobbered on return
- ;; Registers used:
- ;; r0 - NAND_RD_ADDR
- ;; r1 - NAND_WR_ADDR
- ;; r2 - reg_gio_rw_pa_dout
- ;; r3 - reg_gio_r_pa_din
- ;; r4 - tmp
- ;; r5 - byte counter within a page
- ;; r6 - reg_pinmux_rw_pa
- ;; r7 - reg_gio_rw_pa_oe
- ;; r8 - reg_bif_core_rw_grp3_cfg
- ;; r9 - reg_gio_rw_pa_dout shadow
- move.d 0x90000000, $r0
- move.d 0x94000000, $r1
- move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r2
- move.d REG_ADDR(gio, regi_gio, r_pa_din), $r3
- move.d REG_ADDR(pinmux, regi_pinmux, rw_pa), $r6
- move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r7
- move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r8
-
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
- lsrq 1, $r11
-#endif
- ;; Set up GPIO
- move.d [$r2], $r9
- move.d [$r7], $r4
- or.b (1<<ALE) | (1 << CLE) | (1<<CE), $r4
- move.d $r4, [$r7]
-
- ;; Set up bif
- move.d [$r8], $r4
- and.d CSP_MASK, $r4
- or.d CSP_VAL, $r4
- move.d $r4, [$r8]
-
-1: ;; Copy one page
- CLR CE
- SET CLE
- moveq READ_CMD, $r4
- move.b $r4, [$r1]
- moveq 20, $r4
-2: bne 2b
- subq 1, $r4
- CLR CLE
- SET ALE
- clear.w [$r1] ; Column address = 0
- move.d $r11, $r4
- lsrq 8, $r4
- move.b $r4, [$r1] ; Row address
- lsrq 8, $r4
- move.b $r4, [$r1] ; Row address
- moveq 20, $r4
-2: bne 2b
- subq 1, $r4
- CLR ALE
-2: move.d [$r3], $r4
- and.d 1 << BY, $r4
- beq 2b
- movu.w PAGE_SIZE, $r5
-2: ; Copy one byte/word
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
- move.w [$r0], $r4
-#else
- move.b [$r0], $r4
-#endif
- subq 1, $r5
- bne 2b
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
- move.w $r4, [$r10+]
- subu.w PAGE_SIZE*2, $r12
-#else
- move.b $r4, [$r10+]
- subu.w PAGE_SIZE, $r12
-#endif
- bpl 1b
- addu.w PAGE_SIZE, $r11
-
- ;; End of copy
- jump $r13
- nop
-
- ;; This will warn if the code above is too large. If you consider
- ;; to remove this you don't understand the bug/feature.
- .org 256
- .org ERASE_BLOCK
-
-normal_boot:
diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c
index a4dba6b20bd0..a6d5381c94fe 100644
--- a/arch/frv/kernel/gdb-stub.c
+++ b/arch/frv/kernel/gdb-stub.c
@@ -672,7 +672,7 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
if ((uint32_t)mem&1 && count>=1) {
if (!gdbstub_read_byte(mem,ch))
return NULL;
- buf = pack_hex_byte(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[0]);
mem++;
count--;
}
@@ -680,8 +680,8 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
if ((uint32_t)mem&3 && count>=2) {
if (!gdbstub_read_word(mem,(uint16_t *)ch))
return NULL;
- buf = pack_hex_byte(buf, ch[0]);
- buf = pack_hex_byte(buf, ch[1]);
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
mem += 2;
count -= 2;
}
@@ -689,10 +689,10 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
while (count>=4) {
if (!gdbstub_read_dword(mem,(uint32_t *)ch))
return NULL;
- buf = pack_hex_byte(buf, ch[0]);
- buf = pack_hex_byte(buf, ch[1]);
- buf = pack_hex_byte(buf, ch[2]);
- buf = pack_hex_byte(buf, ch[3]);
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
+ buf = hex_byte_pack(buf, ch[2]);
+ buf = hex_byte_pack(buf, ch[3]);
mem += 4;
count -= 4;
}
@@ -700,8 +700,8 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
if (count>=2) {
if (!gdbstub_read_word(mem,(uint16_t *)ch))
return NULL;
- buf = pack_hex_byte(buf, ch[0]);
- buf = pack_hex_byte(buf, ch[1]);
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
mem += 2;
count -= 2;
}
@@ -709,7 +709,7 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa
if (count>=1) {
if (!gdbstub_read_byte(mem,ch))
return NULL;
- buf = pack_hex_byte(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[0]);
}
*buf = 0;
@@ -1498,21 +1498,21 @@ void gdbstub(int sigval)
ptr = mem2hex(title, ptr, sizeof(title) - 1,0);
hx = hex_asc_hi(brr >> 24);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(brr >> 24);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(brr >> 16);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(brr >> 16);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(brr >> 8);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(brr >> 8);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(brr);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(brr);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
*ptr = 0;
@@ -1526,10 +1526,10 @@ void gdbstub(int sigval)
/* Send trap type (converted to signal) */
*ptr++ = 'T';
- ptr = pack_hex_byte(ptr, sigval);
+ ptr = hex_byte_pack(ptr, sigval);
/* Send Error PC */
- ptr = pack_hex_byte(ptr, GDB_REG_PC);
+ ptr = hex_byte_pack(ptr, GDB_REG_PC);
*ptr++ = ':';
ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0);
*ptr++ = ';';
@@ -1537,7 +1537,7 @@ void gdbstub(int sigval)
/*
* Send frame pointer
*/
- ptr = pack_hex_byte(ptr, GDB_REG_FP);
+ ptr = hex_byte_pack(ptr, GDB_REG_FP);
*ptr++ = ':';
ptr = mem2hex(&__debug_frame->fp, ptr, 4, 0);
*ptr++ = ';';
@@ -1545,7 +1545,7 @@ void gdbstub(int sigval)
/*
* Send stack pointer
*/
- ptr = pack_hex_byte(ptr, GDB_REG_SP);
+ ptr = hex_byte_pack(ptr, GDB_REG_SP);
*ptr++ = ':';
ptr = mem2hex(&__debug_frame->sp, ptr, 4, 0);
*ptr++ = ';';
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 091ed6192ae8..d1f377f5d3b6 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -160,7 +160,7 @@ config VT_CONSOLE
config HW_CONSOLE
bool
- depends on VT && !S390 && !UM
+ depends on VT
default y
comment "Unix98 PTY support"
@@ -195,7 +195,7 @@ config UNIX98_PTYS
source "drivers/char/pcmcia/Kconfig"
-source "drivers/serial/Kconfig"
+source "drivers/tty/serial/Kconfig"
source "drivers/i2c/Kconfig"
diff --git a/arch/h8300/include/asm/gpio.h b/arch/h8300/include/asm/gpio-internal.h
index a714f0c0efbc..a714f0c0efbc 100644
--- a/arch/h8300/include/asm/gpio.h
+++ b/arch/h8300/include/asm/gpio-internal.h
diff --git a/arch/h8300/platform/h8300h/irq.c b/arch/h8300/platform/h8300h/irq.c
index e977345105d7..bc4f51bceef5 100644
--- a/arch/h8300/platform/h8300h/irq.c
+++ b/arch/h8300/platform/h8300h/irq.c
@@ -11,7 +11,7 @@
#include <asm/traps.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/gpio.h>
+#include <asm/gpio-internal.h>
#include <asm/regs306x.h>
const int __initdata h8300_saved_vectors[] = {
diff --git a/arch/h8300/platform/h8s/irq.c b/arch/h8300/platform/h8s/irq.c
index 8182f041f829..7b5f29febc07 100644
--- a/arch/h8300/platform/h8s/irq.c
+++ b/arch/h8300/platform/h8s/irq.c
@@ -14,7 +14,7 @@
#include <asm/traps.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/gpio.h>
+#include <asm/gpio-internal.h>
#include <asm/regs267x.h>
/* saved vector list */
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
new file mode 100644
index 000000000000..02513c2dd5ec
--- /dev/null
+++ b/arch/hexagon/Kconfig
@@ -0,0 +1,220 @@
+# Hexagon configuration
+comment "Linux Kernel Configuration for Hexagon"
+
+config HEXAGON
+ def_bool y
+ select HAVE_OPROFILE
+ select USE_GENERIC_SMP_HELPERS if SMP
+ # Other pending projects/to-do items.
+ # select HAVE_REGS_AND_STACK_ACCESS_API
+ # select HAVE_HW_BREAKPOINT if PERF_EVENTS
+ # select ARCH_HAS_CPU_IDLE_WAIT
+ # select ARCH_WANT_OPTIONAL_GPIOLIB
+ # select ARCH_REQUIRE_GPIOLIB
+ # select HAVE_CLK
+ # select IRQ_PER_CPU
+ select HAVE_IRQ_WORK
+ # select GENERIC_PENDING_IRQ if SMP
+ select GENERIC_ATOMIC64
+ select HAVE_PERF_EVENTS
+ select HAVE_GENERIC_HARDIRQS
+ select GENERIC_HARDIRQS_NO__DO_IRQ
+ select GENERIC_HARDIRQS_NO_DEPRECATED
+ # GENERIC_ALLOCATOR is used by dma_alloc_coherent()
+ select GENERIC_ALLOCATOR
+ select GENERIC_IRQ_SHOW
+ select HAVE_ARCH_KGDB
+ select HAVE_ARCH_TRACEHOOK
+ select NO_IOPORT
+ # mostly generic routines, with some accelerated ones
+ ---help---
+ Qualcomm Hexagon is a processor architecture designed for high
+ performance and low power across a wide variety of applications.
+
+config HEXAGON_ARCH_V1
+ bool
+
+config HEXAGON_ARCH_V2
+ bool
+
+config HEXAGON_ARCH_V3
+ bool
+
+config HEXAGON_ARCH_V4
+ bool
+
+config FRAME_POINTER
+ def_bool y
+
+config LOCKDEP_SUPPORT
+ def_bool y
+
+config PCI
+ def_bool n
+
+config EARLY_PRINTK
+ def_bool y
+
+config KTIME_SCALAR
+ def_bool y
+
+config MMU
+ def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+ def_bool y
+
+config GENERIC_CSUM
+ def_bool y
+
+#
+# Use the generic interrupt handling code in kernel/irq/:
+#
+config GENERIC_IRQ_PROBE
+ def_bool y
+
+config GENERIC_IOMAP
+ def_bool y
+
+#config ZONE_DMA
+# bool
+# default y
+
+config HAS_DMA
+ bool
+ select HAVE_DMA_ATTRS
+ default y
+
+config NEED_SG_DMA_LENGTH
+ def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+ def_bool n
+
+config RWSEM_XCHGADD_ALGORITHM
+ def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+ def_bool y
+
+config GENERIC_HWEIGHT
+ def_bool y
+
+config GENERIC_TIME
+ def_bool y
+
+config GENERIC_CLOCKEVENTS
+ def_bool y
+
+config GENERIC_CLOCKEVENTS_BROADCAST
+ def_bool y
+
+config STACKTRACE_SUPPORT
+ def_bool y
+ select STACKTRACE
+
+config GENERIC_BUG
+ def_bool y
+ depends on BUG
+
+config BUG
+ def_bool y
+
+menu "Machine selection"
+
+choice
+ prompt "System type"
+ default HEXAGON_ARCH_V2
+
+config HEXAGON_COMET
+ bool "Comet Board"
+ select HEXAGON_ARCH_V2
+ ---help---
+ Support for the Comet platform.
+
+endchoice
+
+config HEXAGON_VM
+ def_bool y
+
+config CMDLINE
+ string "Default kernel command string"
+ default ""
+ help
+ On some platforms, there is currently no way for the boot loader
+ to pass arguments to the kernel. For these, you should supply some
+ command-line options at build time by entering them here. At a
+ minimum, you should specify the memory size and the root device
+ (e.g., mem=64M root=/dev/nfs).
+
+config HEXAGON_ANGEL_TRAPS
+ bool "Use Angel Traps"
+ default n
+ ---help---
+ Enable angel debug traps (for printk's).
+
+config SMP
+ bool "Multi-Processing support"
+ ---help---
+ Enables SMP support in the kernel. If unsure, say "Y"
+
+config NR_CPUS
+ int "Maximum number of CPUs" if SMP
+ range 2 6 if SMP
+ default "1" if !SMP
+ default "6" if SMP
+ ---help---
+ This allows you to specify the maximum number of CPUs which this
+ kernel will support. The maximum supported value is 6 and the
+ minimum value which makes sense is 2.
+
+ This is purely to save memory - each supported CPU adds
+ approximately eight kilobytes to the kernel image.
+
+choice
+ prompt "Kernel page size"
+ default PAGE_SIZE_4KB
+ ---help---
+ Changes the default page size; use with caution.
+
+config PAGE_SIZE_4KB
+ bool "4KB"
+
+config PAGE_SIZE_16KB
+ bool "16KB"
+
+config PAGE_SIZE_64KB
+ bool "64KB"
+
+config PAGE_SIZE_256KB
+ bool "256KB"
+
+endchoice
+
+source "mm/Kconfig"
+
+source "kernel/Kconfig.hz"
+source "kernel/time/Kconfig"
+
+config GENERIC_GPIO
+ bool "Generic GPIO support"
+ default n
+
+endmenu
+
+source "init/Kconfig"
+source "drivers/Kconfig"
+source "fs/Kconfig"
+
+menu "Executable File Formats"
+source "fs/Kconfig.binfmt"
+endmenu
+
+source "net/Kconfig"
+source "security/Kconfig"
+source "crypto/Kconfig"
+source "lib/Kconfig"
+
+menu "Kernel hacking"
+source "lib/Kconfig.debug"
+endmenu
diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile
new file mode 100644
index 000000000000..0c4de8790fd5
--- /dev/null
+++ b/arch/hexagon/Makefile
@@ -0,0 +1,58 @@
+# Makefile for the Hexagon arch
+
+KBUILD_DEFCONFIG = comet_defconfig
+
+# Do not use GP-relative jumps
+KBUILD_CFLAGS += -G0
+LDFLAGS_vmlinux += -G0
+
+# Do not use single-byte enums; these will overflow.
+KBUILD_CFLAGS += -fno-short-enums
+
+# Modules must use either long-calls, or use pic/plt.
+# Use long-calls for now, it's easier. And faster.
+# CFLAGS_MODULE += -fPIC
+# LDFLAGS_MODULE += -shared
+CFLAGS_MODULE += -mlong-calls
+
+cflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+cflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+cflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+cflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+aflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+aflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+aflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+aflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+ldflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+ldflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+ldflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+ldflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+KBUILD_CFLAGS += $(cflags-y)
+KBUILD_AFLAGS += $(aflags-y)
+
+# no KBUILD_LDFLAGS?
+LDFLAGS += $(ldflags-y)
+
+# Thread-info register will be r19. This value is not configureable;
+# it is hard-coded in several files.
+TIR_NAME := r19
+KBUILD_CFLAGS += -ffixed-$(TIR_NAME) -DTHREADINFO_REG=$(TIR_NAME) -D__linux__
+KBUILD_AFLAGS += -DTHREADINFO_REG=$(TIR_NAME)
+
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+libs-y += $(LIBGCC)
+
+head-y := arch/hexagon/kernel/head.o \
+ arch/hexagon/kernel/init_task.o
+
+core-y += arch/hexagon/kernel/ \
+ arch/hexagon/mm/ \
+ arch/hexagon/lib/
+
+# arch/hexagon/platform/common/
+#
+#core-$(CONFIG_HEXAGON_COMET) += arch/hexagon/platform/comet/
+#machine-$(CONFIG_HEXAGON_COMET) := comet
diff --git a/arch/hexagon/configs/comet_defconfig b/arch/hexagon/configs/comet_defconfig
new file mode 100644
index 000000000000..e324f65f41e7
--- /dev/null
+++ b/arch/hexagon/configs/comet_defconfig
@@ -0,0 +1,85 @@
+CONFIG_SMP=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_HZ_100=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_CROSS_COMPILE="hexagon-"
+CONFIG_LOCALVERSION="-smp"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_PHYLIB=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_CONSOLE_TRANSLATIONS is not set
+CONFIG_LEGACY_PTY_COUNT=64
+# CONFIG_DEVKMEM is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_SPI_DEBUG=y
+CONFIG_SPI_BITBANG=y
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_LIBCRC32C=y
+CONFIG_FRAME_WARN=0
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
new file mode 100644
index 000000000000..9aa17f1917ea
--- /dev/null
+++ b/arch/hexagon/include/asm/Kbuild
@@ -0,0 +1,58 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += registers.h
+header-y += ucontext.h
+header-y += user.h
+
+generic-y += auxvec.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += cpumask.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fb.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += hardirq.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += iomap.h
+generic-y += ipcbuf.h
+generic-y += ipc.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += local64.h
+generic-y += local.h
+generic-y += local.h
+generic-y += mman.h
+generic-y += msgbuf.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += rwsem.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += sembuf.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += siginfo.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.h
+generic-y += stat.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += types.h
+generic-y += ucontext.h
+generic-y += unaligned.h
+generic-y += xor.h
diff --git a/arch/hexagon/include/asm/asm-offsets.h b/arch/hexagon/include/asm/asm-offsets.h
new file mode 100644
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/hexagon/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h
new file mode 100644
index 000000000000..e220f9053035
--- /dev/null
+++ b/arch/hexagon/include/asm/atomic.h
@@ -0,0 +1,164 @@
+/*
+ * Atomic operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_ATOMIC_H
+#define _ASM_ATOMIC_H
+
+#include <linux/types.h>
+
+#define ATOMIC_INIT(i) { (i) }
+#define atomic_set(v, i) ((v)->counter = (i))
+
+/**
+ * atomic_read - reads a word, atomically
+ * @v: pointer to atomic value
+ *
+ * Assumes all word reads on our architecture are atomic.
+ */
+#define atomic_read(v) ((v)->counter)
+
+/**
+ * atomic_xchg - atomic
+ * @v: pointer to memory to change
+ * @new: new value (technically passed in a register -- see xchg)
+ */
+#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
+
+
+/**
+ * atomic_cmpxchg - atomic compare-and-exchange values
+ * @v: pointer to value to change
+ * @old: desired old value to match
+ * @new: new value to put in
+ *
+ * Parameters are then pointer, value-in-register, value-in-register,
+ * and the output is the old value.
+ *
+ * Apparently this is complicated for archs that don't support
+ * the memw_locked like we do (or it's broken or whatever).
+ *
+ * Kind of the lynchpin of the rest of the generically defined routines.
+ * Remember V2 had that bug with dotnew predicate set by memw_locked.
+ *
+ * "old" is "expected" old val, __oldval is actual old value
+ */
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+ int __oldval;
+
+ asm volatile(
+ "1: %0 = memw_locked(%1);\n"
+ " { P0 = cmp.eq(%0,%2);\n"
+ " if (!P0.new) jump:nt 2f; }\n"
+ " memw_locked(%1,P0) = %3;\n"
+ " if (!P0) jump 1b;\n"
+ "2:\n"
+ : "=&r" (__oldval)
+ : "r" (&v->counter), "r" (old), "r" (new)
+ : "memory", "p0"
+ );
+
+ return __oldval;
+}
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+ int output;
+
+ __asm__ __volatile__ (
+ "1: %0 = memw_locked(%1);\n"
+ " %0 = add(%0,%2);\n"
+ " memw_locked(%1,P3)=%0;\n"
+ " if !P3 jump 1b;\n"
+ : "=&r" (output)
+ : "r" (&v->counter), "r" (i)
+ : "memory", "p3"
+ );
+ return output;
+
+}
+
+#define atomic_add(i, v) atomic_add_return(i, (v))
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+ int output;
+ __asm__ __volatile__ (
+ "1: %0 = memw_locked(%1);\n"
+ " %0 = sub(%0,%2);\n"
+ " memw_locked(%1,P3)=%0\n"
+ " if !P3 jump 1b;\n"
+ : "=&r" (output)
+ : "r" (&v->counter), "r" (i)
+ : "memory", "p3"
+ );
+ return output;
+}
+
+#define atomic_sub(i, v) atomic_sub_return(i, (v))
+
+/**
+ * atomic_add_unless - add unless the number is a given value
+ * @v: pointer to value
+ * @a: amount to add
+ * @u: unless value is equal to u
+ *
+ * Returns 1 if the add happened, 0 if it didn't.
+ */
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
+{
+ int output, __oldval;
+ asm volatile(
+ "1: %0 = memw_locked(%2);"
+ " {"
+ " p3 = cmp.eq(%0, %4);"
+ " if (p3.new) jump:nt 2f;"
+ " %0 = add(%0, %3);"
+ " %1 = #0;"
+ " }"
+ " memw_locked(%2, p3) = %0;"
+ " {"
+ " if !p3 jump 1b;"
+ " %1 = #1;"
+ " }"
+ "2:"
+ : "=&r" (__oldval), "=&r" (output)
+ : "r" (v), "r" (a), "r" (u)
+ : "memory", "p3"
+ );
+ return output;
+}
+
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+#define atomic_inc(v) atomic_add(1, (v))
+#define atomic_dec(v) atomic_sub(1, (v))
+
+#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, (v)) == 0)
+#define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0)
+
+
+#define atomic_inc_return(v) (atomic_add_return(1, v))
+#define atomic_dec_return(v) (atomic_sub_return(1, v))
+
+#endif
diff --git a/arch/hexagon/include/asm/bitops.h b/arch/hexagon/include/asm/bitops.h
new file mode 100644
index 000000000000..d23461e080ff
--- /dev/null
+++ b/arch/hexagon/include/asm/bitops.h
@@ -0,0 +1,301 @@
+/*
+ * Bit operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_BITOPS_H
+#define _ASM_BITOPS_H
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+#ifdef __KERNEL__
+
+#define smp_mb__before_clear_bit() barrier()
+#define smp_mb__after_clear_bit() barrier()
+
+/*
+ * The offset calculations for these are based on BITS_PER_LONG == 32
+ * (i.e. I get to shift by #5-2 (32 bits per long, 4 bytes per access),
+ * mask by 0x0000001F)
+ *
+ * Typically, R10 is clobbered for address, R11 bit nr, and R12 is temp
+ */
+
+/**
+ * test_and_clear_bit - clear a bit and return its old value
+ * @nr: bit number to clear
+ * @addr: pointer to memory
+ */
+static inline int test_and_clear_bit(int nr, volatile void *addr)
+{
+ int oldval;
+
+ __asm__ __volatile__ (
+ " {R10 = %1; R11 = asr(%2,#5); }\n"
+ " {R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+ "1: R12 = memw_locked(R10);\n"
+ " { P0 = tstbit(R12,R11); R12 = clrbit(R12,R11); }\n"
+ " memw_locked(R10,P1) = R12;\n"
+ " {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+ : "=&r" (oldval)
+ : "r" (addr), "r" (nr)
+ : "r10", "r11", "r12", "p0", "p1", "memory"
+ );
+
+ return oldval;
+}
+
+/**
+ * test_and_set_bit - set a bit and return its old value
+ * @nr: bit number to set
+ * @addr: pointer to memory
+ */
+static inline int test_and_set_bit(int nr, volatile void *addr)
+{
+ int oldval;
+
+ __asm__ __volatile__ (
+ " {R10 = %1; R11 = asr(%2,#5); }\n"
+ " {R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+ "1: R12 = memw_locked(R10);\n"
+ " { P0 = tstbit(R12,R11); R12 = setbit(R12,R11); }\n"
+ " memw_locked(R10,P1) = R12;\n"
+ " {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+ : "=&r" (oldval)
+ : "r" (addr), "r" (nr)
+ : "r10", "r11", "r12", "p0", "p1", "memory"
+ );
+
+
+ return oldval;
+
+}
+
+/**
+ * test_and_change_bit - toggle a bit and return its old value
+ * @nr: bit number to set
+ * @addr: pointer to memory
+ */
+static inline int test_and_change_bit(int nr, volatile void *addr)
+{
+ int oldval;
+
+ __asm__ __volatile__ (
+ " {R10 = %1; R11 = asr(%2,#5); }\n"
+ " {R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+ "1: R12 = memw_locked(R10);\n"
+ " { P0 = tstbit(R12,R11); R12 = togglebit(R12,R11); }\n"
+ " memw_locked(R10,P1) = R12;\n"
+ " {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+ : "=&r" (oldval)
+ : "r" (addr), "r" (nr)
+ : "r10", "r11", "r12", "p0", "p1", "memory"
+ );
+
+ return oldval;
+
+}
+
+/*
+ * Atomic, but doesn't care about the return value.
+ * Rewrite later to save a cycle or two.
+ */
+
+static inline void clear_bit(int nr, volatile void *addr)
+{
+ test_and_clear_bit(nr, addr);
+}
+
+static inline void set_bit(int nr, volatile void *addr)
+{
+ test_and_set_bit(nr, addr);
+}
+
+static inline void change_bit(int nr, volatile void *addr)
+{
+ test_and_change_bit(nr, addr);
+}
+
+
+/*
+ * These are allowed to be non-atomic. In fact the generic flavors are
+ * in non-atomic.h. Would it be better to use intrinsics for this?
+ *
+ * OK, writes in our architecture do not invalidate LL/SC, so this has to
+ * be atomic, particularly for things like slab_lock and slab_unlock.
+ *
+ */
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+ test_and_clear_bit(nr, addr);
+}
+
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+ test_and_set_bit(nr, addr);
+}
+
+static inline void __change_bit(int nr, volatile unsigned long *addr)
+{
+ test_and_change_bit(nr, addr);
+}
+
+/* Apparently, at least some of these are allowed to be non-atomic */
+static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+ return test_and_clear_bit(nr, addr);
+}
+
+static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+ return test_and_set_bit(nr, addr);
+}
+
+static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+ return test_and_change_bit(nr, addr);
+}
+
+static inline int __test_bit(int nr, const volatile unsigned long *addr)
+{
+ int retval;
+
+ asm volatile(
+ "{P0 = tstbit(%1,%2); if (P0.new) %0 = #1; if (!P0.new) %0 = #0;}\n"
+ : "=&r" (retval)
+ : "r" (addr[BIT_WORD(nr)]), "r" (nr % BITS_PER_LONG)
+ : "p0"
+ );
+
+ return retval;
+}
+
+#define test_bit(nr, addr) __test_bit(nr, addr)
+
+/*
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static inline long ffz(int x)
+{
+ int r;
+
+ asm("%0 = ct1(%1);\n"
+ : "=&r" (r)
+ : "r" (x));
+ return r;
+}
+
+/*
+ * fls - find last (most-significant) bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+static inline long fls(int x)
+{
+ int r;
+
+ asm("{ %0 = cl0(%1);}\n"
+ "%0 = sub(#32,%0);\n"
+ : "=&r" (r)
+ : "r" (x)
+ : "p0");
+
+ return r;
+}
+
+/*
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static inline long ffs(int x)
+{
+ int r;
+
+ asm("{ P0 = cmp.eq(%1,#0); %0 = ct0(%1);}\n"
+ "{ if P0 %0 = #0; if !P0 %0 = add(%0,#1);}\n"
+ : "=&r" (r)
+ : "r" (x)
+ : "p0");
+
+ return r;
+}
+
+/*
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ *
+ * bits_per_long assumed to be 32
+ * numbering starts at 0 I think (instead of 1 like ffs)
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+ int num;
+
+ asm("%0 = ct0(%1);\n"
+ : "=&r" (num)
+ : "r" (word));
+
+ return num;
+}
+
+/*
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ * bits_per_long assumed to be 32
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+ int num;
+
+ asm("%0 = cl0(%1);\n"
+ "%0 = sub(#31,%0);\n"
+ : "=&r" (num)
+ : "r" (word));
+
+ return num;
+}
+
+#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/find.h>
+
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+
+#include <asm-generic/bitops/le.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/arch/hexagon/include/asm/bitsperlong.h b/arch/hexagon/include/asm/bitsperlong.h
new file mode 100644
index 000000000000..2701cae3426e
--- /dev/null
+++ b/arch/hexagon/include/asm/bitsperlong.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_HEXAGON_BITSPERLONG_H
+#define __ASM_HEXAGON_BITSPERLONG_H
+
+#define __BITS_PER_LONG 32
+
+#include <asm-generic/bitsperlong.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/byteorder.h b/arch/hexagon/include/asm/byteorder.h
new file mode 100644
index 000000000000..0e19b9fe4ca6
--- /dev/null
+++ b/arch/hexagon/include/asm/byteorder.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_BYTEORDER_H
+#define _ASM_BYTEORDER_H
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+# define __BYTEORDER_HAS_U64__
+#endif
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_BYTEORDER_H */
diff --git a/arch/hexagon/include/asm/cache.h b/arch/hexagon/include/asm/cache.h
new file mode 100644
index 000000000000..0f01de2eb4ab
--- /dev/null
+++ b/arch/hexagon/include/asm/cache.h
@@ -0,0 +1,34 @@
+/*
+ * Cache definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_CACHE_H
+#define __ASM_CACHE_H
+
+/* Bytes per L1 cache line */
+#define L1_CACHE_SHIFT (5)
+#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+
+#define __cacheline_aligned __aligned(L1_CACHE_BYTES)
+#define ____cacheline_aligned __aligned(L1_CACHE_BYTES)
+
+/* See http://kerneltrap.org/node/15100 */
+#define __read_mostly
+
+#endif
diff --git a/arch/hexagon/include/asm/cacheflush.h b/arch/hexagon/include/asm/cacheflush.h
new file mode 100644
index 000000000000..6865c1be927a
--- /dev/null
+++ b/arch/hexagon/include/asm/cacheflush.h
@@ -0,0 +1,99 @@
+/*
+ * Cache flush operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_CACHEFLUSH_H
+#define _ASM_CACHEFLUSH_H
+
+#include <linux/cache.h>
+#include <linux/mm.h>
+#include <asm/string.h>
+#include <asm-generic/cacheflush.h>
+
+/* Cache flushing:
+ *
+ * - flush_cache_all() flushes entire cache
+ * - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ * - flush_cache_page(mm, vmaddr, pfn) flushes a single page
+ * - flush_cache_range(vma, start, end) flushes a range of pages
+ * - flush_icache_range(start, end) flush a range of instructions
+ * - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
+ * - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
+ *
+ * Need to doublecheck which one is really needed for ptrace stuff to work.
+ */
+#define LINESIZE 32
+#define LINEBITS 5
+
+/*
+ * Flush Dcache range through current map.
+ */
+extern void flush_dcache_range(unsigned long start, unsigned long end);
+
+/*
+ * Flush Icache range through current map.
+ */
+#undef flush_icache_range
+extern void flush_icache_range(unsigned long start, unsigned long end);
+
+/*
+ * Memory-management related flushes are there to ensure in non-physically
+ * indexed cache schemes that stale lines belonging to a given ASID aren't
+ * in the cache to confuse things. The prototype Hexagon Virtual Machine
+ * only uses a single ASID for all user-mode maps, which should
+ * mean that they aren't necessary. A brute-force, flush-everything
+ * implementation, with the name xxxxx_hexagon() is present in
+ * arch/hexagon/mm/cache.c, but let's not wire it up until we know
+ * it is needed.
+ */
+extern void flush_cache_all_hexagon(void);
+
+/*
+ * This may or may not ever have to be non-null, depending on the
+ * virtual machine MMU. For a native kernel, it's definitiely a no-op
+ *
+ * This is also the place where deferred cache coherency stuff seems
+ * to happen, classically... but instead we do it like ia64 and
+ * clean the cache when the PTE is set.
+ *
+ */
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep)
+{
+ /* generic_ptrace_pokedata doesn't wind up here, does it? */
+}
+
+#undef copy_to_user_page
+static inline void copy_to_user_page(struct vm_area_struct *vma,
+ struct page *page,
+ unsigned long vaddr,
+ void *dst, void *src, int len)
+{
+ memcpy(dst, src, len);
+ if (vma->vm_flags & VM_EXEC) {
+ flush_icache_range((unsigned long) dst,
+ (unsigned long) dst + len);
+ }
+}
+
+
+extern void hexagon_inv_dcache_range(unsigned long start, unsigned long end);
+extern void hexagon_clean_dcache_range(unsigned long start, unsigned long end);
+
+#endif
diff --git a/arch/hexagon/include/asm/checksum.h b/arch/hexagon/include/asm/checksum.h
new file mode 100644
index 000000000000..3ce4ecd44f82
--- /dev/null
+++ b/arch/hexagon/include/asm/checksum.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_CHECKSUM_H
+#define _ASM_CHECKSUM_H
+
+#define do_csum do_csum
+unsigned int do_csum(const void *voidptr, int len);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+#define csum_partial_copy_nocheck csum_partial_copy_nocheck
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum);
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+#define csum_tcpudp_nofold csum_tcpudp_nofold
+__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+ unsigned short len, unsigned short proto, __wsum sum);
+
+#define csum_tcpudp_magic csum_tcpudp_magic
+__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+ unsigned short len, unsigned short proto, __wsum sum);
+
+#include <asm-generic/checksum.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/delay.h b/arch/hexagon/include/asm/delay.h
new file mode 100644
index 000000000000..9ab12e9a872b
--- /dev/null
+++ b/arch/hexagon/include/asm/delay.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_DELAY_H
+#define _ASM_DELAY_H
+
+#include <asm/param.h>
+
+extern void __udelay(unsigned long usecs);
+
+#define udelay(usecs) __udelay((usecs))
+
+#endif /* _ASM_DELAY_H */
diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h
new file mode 100644
index 000000000000..448b224ba4ef
--- /dev/null
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -0,0 +1,101 @@
+/*
+ * DMA operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+#include <linux/types.h>
+#include <linux/cache.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-debug.h>
+#include <linux/dma-attrs.h>
+#include <asm/io.h>
+
+struct device;
+extern int bad_dma_address;
+
+extern struct dma_map_ops *dma_ops;
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+ if (unlikely(dev == NULL))
+ return NULL;
+
+ return dma_ops;
+}
+
+extern int dma_supported(struct device *dev, u64 mask);
+extern int dma_set_mask(struct device *dev, u64 mask);
+extern int dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
+extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+ enum dma_data_direction direction);
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+ if (!dev->dma_mask)
+ return 0;
+ return addr + size - 1 <= *dev->dma_mask;
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops->mapping_error)
+ return dma_ops->mapping_error(dev, dma_addr);
+
+ return (dma_addr == bad_dma_address);
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ void *ret;
+ struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+
+ ret = ops->alloc_coherent(dev, size, dma_handle, flag);
+
+ debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
+
+ return ret;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+{
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+
+ dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+
+ debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+#endif
diff --git a/arch/arm/mach-vt8500/include/mach/memory.h b/arch/hexagon/include/asm/dma.h
index 175f914eff93..da6d2f61a93a 100644
--- a/arch/arm/mach-vt8500/include/mach/memory.h
+++ b/arch/hexagon/include/asm/dma.h
@@ -1,12 +1,9 @@
/*
- * arch/arm/mach-vt8500/include/mach/memory.h
- *
- * Copyright (C) 2003 ARM Limited
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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.
+ * 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
@@ -15,14 +12,18 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
*/
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-/*
- * Physical DRAM offset.
- */
-#define PHYS_OFFSET UL(0x00000000)
+#ifndef _ASM_DMA_H
+#define _ASM_DMA_H
+
+#include <asm/io.h>
+
+#define MAX_DMA_CHANNELS 1
+#define MAX_DMA_ADDRESS (PAGE_OFFSET)
+
+extern size_t hexagon_coherent_pool_size;
#endif
diff --git a/arch/hexagon/include/asm/elf.h b/arch/hexagon/include/asm/elf.h
new file mode 100644
index 000000000000..37976a0d3650
--- /dev/null
+++ b/arch/hexagon/include/asm/elf.h
@@ -0,0 +1,229 @@
+/*
+ * ELF definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_ELF_H
+#define __ASM_ELF_H
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
+/*
+ * This should really be in linux/elf-em.h.
+ */
+#define EM_HEXAGON 164 /* QUALCOMM Hexagon */
+
+struct elf32_hdr;
+
+/*
+ * ELF header e_flags defines.
+ */
+
+/* should have stuff like "CPU type" and maybe "ABI version", etc */
+
+/* Hexagon relocations */
+ /* V2 */
+#define R_HEXAGON_NONE 0
+#define R_HEXAGON_B22_PCREL 1
+#define R_HEXAGON_B15_PCREL 2
+#define R_HEXAGON_B7_PCREL 3
+#define R_HEXAGON_LO16 4
+#define R_HEXAGON_HI16 5
+#define R_HEXAGON_32 6
+#define R_HEXAGON_16 7
+#define R_HEXAGON_8 8
+#define R_HEXAGON_GPREL16_0 9
+#define R_HEXAGON_GPREL16_1 10
+#define R_HEXAGON_GPREL16_2 11
+#define R_HEXAGON_GPREL16_3 12
+#define R_HEXAGON_HL16 13
+ /* V3 */
+#define R_HEXAGON_B13_PCREL 14
+ /* V4 */
+#define R_HEXAGON_B9_PCREL 15
+ /* V4 (extenders) */
+#define R_HEXAGON_B32_PCREL_X 16
+#define R_HEXAGON_32_6_X 17
+ /* V4 (extended) */
+#define R_HEXAGON_B22_PCREL_X 18
+#define R_HEXAGON_B15_PCREL_X 19
+#define R_HEXAGON_B13_PCREL_X 20
+#define R_HEXAGON_B9_PCREL_X 21
+#define R_HEXAGON_B7_PCREL_X 22
+#define R_HEXAGON_16_X 23
+#define R_HEXAGON_12_X 24
+#define R_HEXAGON_11_X 25
+#define R_HEXAGON_10_X 26
+#define R_HEXAGON_9_X 27
+#define R_HEXAGON_8_X 28
+#define R_HEXAGON_7_X 29
+#define R_HEXAGON_6_X 30
+ /* V2 PIC */
+#define R_HEXAGON_32_PCREL 31
+#define R_HEXAGON_COPY 32
+#define R_HEXAGON_GLOB_DAT 33
+#define R_HEXAGON_JMP_SLOT 34
+#define R_HEXAGON_RELATIVE 35
+#define R_HEXAGON_PLT_B22_PCREL 36
+#define R_HEXAGON_GOTOFF_LO16 37
+#define R_HEXAGON_GOTOFF_HI16 38
+#define R_HEXAGON_GOTOFF_32 39
+#define R_HEXAGON_GOT_LO16 40
+#define R_HEXAGON_GOT_HI16 41
+#define R_HEXAGON_GOT_32 42
+#define R_HEXAGON_GOT_16 43
+
+/*
+ * ELF register definitions..
+ */
+typedef unsigned long elf_greg_t;
+
+typedef struct user_regs_struct elf_gregset_t;
+#define ELF_NGREG (sizeof(elf_gregset_t)/sizeof(unsigned long))
+
+/* Placeholder */
+typedef unsigned long elf_fpregset_t;
+
+/*
+ * Bypass the whole "regsets" thing for now and use the define.
+ */
+
+#define ELF_CORE_COPY_REGS(DEST, REGS) \
+do { \
+ DEST.r0 = REGS->r00; \
+ DEST.r1 = REGS->r01; \
+ DEST.r2 = REGS->r02; \
+ DEST.r3 = REGS->r03; \
+ DEST.r4 = REGS->r04; \
+ DEST.r5 = REGS->r05; \
+ DEST.r6 = REGS->r06; \
+ DEST.r7 = REGS->r07; \
+ DEST.r8 = REGS->r08; \
+ DEST.r9 = REGS->r09; \
+ DEST.r10 = REGS->r10; \
+ DEST.r11 = REGS->r11; \
+ DEST.r12 = REGS->r12; \
+ DEST.r13 = REGS->r13; \
+ DEST.r14 = REGS->r14; \
+ DEST.r15 = REGS->r15; \
+ DEST.r16 = REGS->r16; \
+ DEST.r17 = REGS->r17; \
+ DEST.r18 = REGS->r18; \
+ DEST.r19 = REGS->r19; \
+ DEST.r20 = REGS->r20; \
+ DEST.r21 = REGS->r21; \
+ DEST.r22 = REGS->r22; \
+ DEST.r23 = REGS->r23; \
+ DEST.r24 = REGS->r24; \
+ DEST.r25 = REGS->r25; \
+ DEST.r26 = REGS->r26; \
+ DEST.r27 = REGS->r27; \
+ DEST.r28 = REGS->r28; \
+ DEST.r29 = pt_psp(REGS); \
+ DEST.r30 = REGS->r30; \
+ DEST.r31 = REGS->r31; \
+ DEST.sa0 = REGS->sa0; \
+ DEST.lc0 = REGS->lc0; \
+ DEST.sa1 = REGS->sa1; \
+ DEST.lc1 = REGS->lc1; \
+ DEST.m0 = REGS->m0; \
+ DEST.m1 = REGS->m1; \
+ DEST.usr = REGS->usr; \
+ DEST.p3_0 = REGS->preds; \
+ DEST.gp = REGS->gp; \
+ DEST.ugp = REGS->ugp; \
+ DEST.pc = pt_elr(REGS); \
+ DEST.cause = pt_cause(REGS); \
+ DEST.badva = pt_badva(REGS); \
+} while (0);
+
+
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ * Checks the machine and ABI type.
+ */
+#define elf_check_arch(hdr) ((hdr)->e_machine == EM_HEXAGON)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2LSB
+#define ELF_ARCH EM_HEXAGON
+
+#ifdef CONFIG_HEXAGON_ARCH_V2
+#define ELF_CORE_EFLAGS 0x1
+#endif
+
+#ifdef CONFIG_HEXAGON_ARCH_V3
+#define ELF_CORE_EFLAGS 0x2
+#endif
+
+#ifdef CONFIG_HEXAGON_ARCH_V4
+#define ELF_CORE_EFLAGS 0x3
+#endif
+
+/*
+ * Some architectures have ld.so set up a pointer to a function
+ * to be registered using atexit, to facilitate cleanup. So that
+ * static executables will be well-behaved, we would null the register
+ * in question here, in the pt_regs structure passed. For now,
+ * leave it a null macro.
+ */
+#define ELF_PLAT_INIT(regs, load_addr) do { } while (0)
+
+#define USE_ELF_CORE_DUMP
+#define CORE_DUMP_USE_REGSET
+
+/* Hrm is this going to cause problems for changing PAGE_SIZE? */
+#define ELF_EXEC_PAGESIZE 4096
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader. We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ */
+#define ELF_ET_DYN_BASE 0x08000000UL
+
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP (0)
+
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization. This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ */
+#define ELF_PLATFORM (NULL)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#endif
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+ int uses_interp);
+
+
+#endif
diff --git a/arch/hexagon/include/asm/fixmap.h b/arch/hexagon/include/asm/fixmap.h
new file mode 100644
index 000000000000..b27f4941645b
--- /dev/null
+++ b/arch/hexagon/include/asm/fixmap.h
@@ -0,0 +1,73 @@
+/*
+ * Fixmap support for Hexagon - enough to support highmem features
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+/*
+ * A lot of the fixmap info is already in mem-layout.h
+ */
+#include <asm/mem-layout.h>
+
+/*
+ * Full fixmap support involves set_fixmap() functions, but
+ * these may not be needed if all we're after is an area for
+ * highmem kernel mappings.
+ */
+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+extern void __this_fixmap_does_not_exist(void);
+
+/**
+ * fix_to_virt -- "index to address" translation.
+ *
+ * If anyone tries to use the idx directly without translation,
+ * we catch the bug with a NULL-deference kernel oops. Illegal
+ * ranges of incoming indices are caught too.
+ */
+static inline unsigned long fix_to_virt(const unsigned int idx)
+{
+ /*
+ * This branch gets completely eliminated after inlining,
+ * except when someone tries to use fixaddr indices in an
+ * illegal way. (such as mixing up address types or using
+ * out-of-range indices).
+ *
+ * If it doesn't get removed, the linker will complain
+ * loudly with a reasonably clear error message..
+ */
+ if (idx >= __end_of_fixed_addresses)
+ __this_fixmap_does_not_exist();
+
+ return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+ BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+ return __virt_to_fix(vaddr);
+}
+
+#define kmap_get_fixmap_pte(vaddr) \
+ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), \
+ (vaddr)), (vaddr)), (vaddr))
+
+#endif
diff --git a/arch/hexagon/include/asm/fpu.h b/arch/hexagon/include/asm/fpu.h
new file mode 100644
index 000000000000..0e135ea8c45b
--- /dev/null
+++ b/arch/hexagon/include/asm/fpu.h
@@ -0,0 +1,4 @@
+/*
+ * If the FPU is used inside the kernel,
+ * kernel_fpu_end() will be defined here.
+ */
diff --git a/arch/hexagon/include/asm/futex.h b/arch/hexagon/include/asm/futex.h
new file mode 100644
index 000000000000..7e597f8434da
--- /dev/null
+++ b/arch/hexagon/include/asm/futex.h
@@ -0,0 +1,137 @@
+#ifndef _ASM_HEXAGON_FUTEX_H
+#define _ASM_HEXAGON_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+/* XXX TODO-- need to add sync barriers! */
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile( \
+ "1: %0 = memw_locked(%3);\n" \
+ /* For example: %1 = %4 */ \
+ insn \
+ "2: memw_locked(%3,p2) = %1;\n" \
+ " if !p2 jump 1b;\n" \
+ " %1 = #0;\n" \
+ "3:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "4: %1 = #%5;\n" \
+ " jump 3b\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ ".long 1b,4b,2b,4b\n" \
+ ".previous\n" \
+ : "=&r" (oldval), "=&r" (ret), "+m" (*uaddr) \
+ : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
+ : "p2", "memory")
+
+
+static inline int
+futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret;
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ pagefault_disable();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_atomic_op("%1 = %4\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_atomic_op("%1 = add(%0,%4)\n", ret, oldval, uaddr,
+ oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_atomic_op("%1 = or(%0,%4)\n", ret, oldval, uaddr,
+ oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_atomic_op("%1 = not(%4); %1 = and(%0,%1)\n", ret,
+ oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_atomic_op("%1 = xor(%0,%4)\n", ret, oldval, uaddr,
+ oparg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ pagefault_enable();
+
+ if (!ret) {
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ:
+ ret = (oldval == cmparg);
+ break;
+ case FUTEX_OP_CMP_NE:
+ ret = (oldval != cmparg);
+ break;
+ case FUTEX_OP_CMP_LT:
+ ret = (oldval < cmparg);
+ break;
+ case FUTEX_OP_CMP_GE:
+ ret = (oldval >= cmparg);
+ break;
+ case FUTEX_OP_CMP_LE:
+ ret = (oldval <= cmparg);
+ break;
+ case FUTEX_OP_CMP_GT:
+ ret = (oldval > cmparg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+ }
+ return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval,
+ u32 newval)
+{
+ int prev;
+ int ret;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+ return -EFAULT;
+
+ __asm__ __volatile__ (
+ "1: %1 = memw_locked(%3)\n"
+ " {\n"
+ " p2 = cmp.eq(%1,%4)\n"
+ " if !p2.new jump:NT 3f\n"
+ " }\n"
+ "2: memw_locked(%3,p2) = %5\n"
+ " if !p2 jump 1b\n"
+ "3:\n"
+ ".section .fixup,\"ax\"\n"
+ "4: %0 = #%6\n"
+ " jump 3b\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ ".long 1b,4b,2b,4b\n"
+ ".previous\n"
+ : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
+ : "r" (uaddr), "r" (oldval), "r" (newval), "i"(-EFAULT)
+ : "p2", "memory");
+
+ *uval = prev;
+ return ret;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_HEXAGON_FUTEX_H */
diff --git a/arch/hexagon/include/asm/hexagon_vm.h b/arch/hexagon/include/asm/hexagon_vm.h
new file mode 100644
index 000000000000..182cb9d54769
--- /dev/null
+++ b/arch/hexagon/include/asm/hexagon_vm.h
@@ -0,0 +1,281 @@
+/*
+ * Declarations for to Hexagon Virtal Machine.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef ASM_HEXAGON_VM_H
+#define ASM_HEXAGON_VM_H
+
+/*
+ * In principle, a Linux kernel for the VM could
+ * selectively define the virtual instructions
+ * as inline assembler macros, but for a first pass,
+ * we'll use subroutines for both the VM and the native
+ * kernels. It's costing a subroutine call/return,
+ * but it makes for a single set of entry points
+ * for tracing/debugging.
+ */
+
+/*
+ * Lets make this stuff visible only if configured,
+ * so we can unconditionally include the file.
+ */
+
+#ifndef __ASSEMBLY__
+
+enum VM_CACHE_OPS {
+ ickill,
+ dckill,
+ l2kill,
+ dccleaninva,
+ icinva,
+ idsync,
+ fetch_cfg
+};
+
+enum VM_INT_OPS {
+ nop,
+ globen,
+ globdis,
+ locen,
+ locdis,
+ affinity,
+ get,
+ peek,
+ status,
+ post,
+ clear
+};
+
+extern void _K_VM_event_vector(void);
+
+void __vmrte(void);
+long __vmsetvec(void *);
+long __vmsetie(long);
+long __vmgetie(void);
+long __vmintop(enum VM_INT_OPS, long, long, long, long);
+long __vmclrmap(void *, unsigned long);
+long __vmnewmap(void *);
+long __vmcache(enum VM_CACHE_OPS op, unsigned long addr, unsigned long len);
+unsigned long long __vmgettime(void);
+long __vmsettime(unsigned long long);
+long __vmstart(void *, void *);
+void __vmstop(void);
+long __vmwait(void);
+void __vmyield(void);
+long __vmvpid(void);
+
+static inline long __vmcache_ickill(void)
+{
+ return __vmcache(ickill, 0, 0);
+}
+
+static inline long __vmcache_dckill(void)
+{
+ return __vmcache(dckill, 0, 0);
+}
+
+static inline long __vmcache_l2kill(void)
+{
+ return __vmcache(l2kill, 0, 0);
+}
+
+static inline long __vmcache_dccleaninva(unsigned long addr, unsigned long len)
+{
+ return __vmcache(dccleaninva, addr, len);
+}
+
+static inline long __vmcache_icinva(unsigned long addr, unsigned long len)
+{
+ return __vmcache(icinva, addr, len);
+}
+
+static inline long __vmcache_idsync(unsigned long addr,
+ unsigned long len)
+{
+ return __vmcache(idsync, addr, len);
+}
+
+static inline long __vmcache_fetch_cfg(unsigned long val)
+{
+ return __vmcache(fetch_cfg, val, 0);
+}
+
+/* interrupt operations */
+
+static inline long __vmintop_nop(void)
+{
+ return __vmintop(nop, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_globen(long i)
+{
+ return __vmintop(globen, i, 0, 0, 0);
+}
+
+static inline long __vmintop_globdis(long i)
+{
+ return __vmintop(globdis, i, 0, 0, 0);
+}
+
+static inline long __vmintop_locen(long i)
+{
+ return __vmintop(locen, i, 0, 0, 0);
+}
+
+static inline long __vmintop_locdis(long i)
+{
+ return __vmintop(locdis, i, 0, 0, 0);
+}
+
+static inline long __vmintop_affinity(long i, long cpu)
+{
+ return __vmintop(locdis, i, cpu, 0, 0);
+}
+
+static inline long __vmintop_get(void)
+{
+ return __vmintop(get, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_peek(void)
+{
+ return __vmintop(peek, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_status(long i)
+{
+ return __vmintop(status, i, 0, 0, 0);
+}
+
+static inline long __vmintop_post(long i)
+{
+ return __vmintop(post, i, 0, 0, 0);
+}
+
+static inline long __vmintop_clear(long i)
+{
+ return __vmintop(clear, i, 0, 0, 0);
+}
+
+#else /* Only assembly code should reference these */
+
+#define HVM_TRAP1_VMRTE 1
+#define HVM_TRAP1_VMSETVEC 2
+#define HVM_TRAP1_VMSETIE 3
+#define HVM_TRAP1_VMGETIE 4
+#define HVM_TRAP1_VMINTOP 5
+#define HVM_TRAP1_VMCLRMAP 10
+#define HVM_TRAP1_VMNEWMAP 11
+#define HVM_TRAP1_FORMERLY_VMWIRE 12
+#define HVM_TRAP1_VMCACHE 13
+#define HVM_TRAP1_VMGETTIME 14
+#define HVM_TRAP1_VMSETTIME 15
+#define HVM_TRAP1_VMWAIT 16
+#define HVM_TRAP1_VMYIELD 17
+#define HVM_TRAP1_VMSTART 18
+#define HVM_TRAP1_VMSTOP 19
+#define HVM_TRAP1_VMVPID 20
+#define HVM_TRAP1_VMSETREGS 21
+#define HVM_TRAP1_VMGETREGS 22
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Constants for virtual instruction parameters and return values
+ */
+
+/* vmsetie arguments */
+
+#define VM_INT_DISABLE 0
+#define VM_INT_ENABLE 1
+
+/* vmsetimask arguments */
+
+#define VM_INT_UNMASK 0
+#define VM_INT_MASK 1
+
+#define VM_NEWMAP_TYPE_LINEAR 0
+#define VM_NEWMAP_TYPE_PGTABLES 1
+
+
+/*
+ * Event Record definitions useful to both C and Assembler
+ */
+
+/* VMEST Layout */
+
+#define HVM_VMEST_UM_SFT 31
+#define HVM_VMEST_UM_MSK 1
+#define HVM_VMEST_IE_SFT 30
+#define HVM_VMEST_IE_MSK 1
+#define HVM_VMEST_EVENTNUM_SFT 16
+#define HVM_VMEST_EVENTNUM_MSK 0xff
+#define HVM_VMEST_CAUSE_SFT 0
+#define HVM_VMEST_CAUSE_MSK 0xffff
+
+/*
+ * The initial program gets to find a system environment descriptor
+ * on its stack when it begins exection. The first word is a version
+ * code to indicate what is there. Zero means nothing more.
+ */
+
+#define HEXAGON_VM_SED_NULL 0
+
+/*
+ * Event numbers for vector binding
+ */
+
+#define HVM_EV_RESET 0
+#define HVM_EV_MACHCHECK 1
+#define HVM_EV_GENEX 2
+#define HVM_EV_TRAP 8
+#define HVM_EV_INTR 15
+/* These shoud be nuked as soon as we know the VM is up to spec v0.1.1 */
+#define HVM_EV_INTR_0 16
+#define HVM_MAX_INTR 240
+
+/*
+ * Cause values for General Exception
+ */
+
+#define HVM_GE_C_BUS 0x01
+#define HVM_GE_C_XPROT 0x11
+#define HVM_GE_C_XUSER 0x14
+#define HVM_GE_C_INVI 0x15
+#define HVM_GE_C_PRIVI 0x1B
+#define HVM_GE_C_XMAL 0x1C
+#define HVM_GE_C_RMAL 0x20
+#define HVM_GE_C_WMAL 0x21
+#define HVM_GE_C_RPROT 0x22
+#define HVM_GE_C_WPROT 0x23
+#define HVM_GE_C_RUSER 0x24
+#define HVM_GE_C_WUSER 0x25
+#define HVM_GE_C_CACHE 0x28
+
+/*
+ * Cause codes for Machine Check
+ */
+
+#define HVM_MCHK_C_DOWN 0x00
+#define HVM_MCHK_C_BADSP 0x01
+#define HVM_MCHK_C_BADEX 0x02
+#define HVM_MCHK_C_BADPT 0x03
+#define HVM_MCHK_C_REGWR 0x29
+
+#endif
diff --git a/arch/hexagon/include/asm/intrinsics.h b/arch/hexagon/include/asm/intrinsics.h
new file mode 100644
index 000000000000..1c02186d2e9a
--- /dev/null
+++ b/arch/hexagon/include/asm/intrinsics.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_INTRINSICS_H
+#define _ASM_HEXAGON_INTRINSICS_H
+
+#define HEXAGON_P_vrmpyhacc_PP __builtin_HEXAGON_M2_vrmac_s0
+#define HEXAGON_P_vrmpyh_PP __builtin_HEXAGON_M2_vrmpy_s0
+#define HEXAGON_R_cl0_R __builtin_HEXAGON_S2_cl0
+
+#endif
diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h
new file mode 100644
index 000000000000..b3acc2cc71bf
--- /dev/null
+++ b/arch/hexagon/include/asm/io.h
@@ -0,0 +1,326 @@
+/*
+ * IO definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <asm/string.h>
+#include <asm/mem-layout.h>
+#include <asm/iomap.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+/*
+ * We don't have PCI yet.
+ * _IO_BASE is pointing at what should be unused virtual space.
+ */
+#define IO_SPACE_LIMIT 0xffff
+#define _IO_BASE ((void __iomem *)0xfe000000)
+
+extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
+ unsigned long end, unsigned long flags);
+
+extern void __iounmap(const volatile void __iomem *addr);
+
+/* Defined in lib/io.c, needed for smc91x driver. */
+extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
+
+extern void __raw_readsl(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_writesl(void __iomem *addr, const void *data, int wordlen);
+
+#define readsw(p, d, l) __raw_readsw(p, d, l)
+#define writesw(p, d, l) __raw_writesw(p, d, l)
+
+#define readsl(p, d, l) __raw_readsl(p, d, l)
+#define writesl(p, d, l) __raw_writesl(p, d, l)
+
+/*
+ * virt_to_phys - map virtual address to physical
+ * @address: address to map
+ */
+static inline unsigned long virt_to_phys(volatile void *address)
+{
+ return __pa(address);
+}
+
+/*
+ * phys_to_virt - map physical address to virtual
+ * @address: address to map
+ */
+static inline void *phys_to_virt(unsigned long address)
+{
+ return __va(address);
+}
+
+/*
+ * convert a physical pointer to a virtual kernel pointer for
+ * /dev/mem access.
+ */
+#define xlate_dev_kmem_ptr(p) __va(p)
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * IO port access primitives. Hexagon doesn't have special IO access
+ * instructions; all I/O is memory mapped.
+ *
+ * in/out are used for "ports", but we don't have "port instructions",
+ * so these are really just memory mapped too.
+ */
+
+/*
+ * readb - read byte from memory mapped device
+ * @addr: pointer to memory
+ *
+ * Operates on "I/O bus memory space"
+ */
+static inline u8 readb(const volatile void __iomem *addr)
+{
+ u8 val;
+ asm volatile(
+ "%0 = memb(%1);"
+ : "=&r" (val)
+ : "r" (addr)
+ );
+ return val;
+}
+
+static inline u16 readw(const volatile void __iomem *addr)
+{
+ u16 val;
+ asm volatile(
+ "%0 = memh(%1);"
+ : "=&r" (val)
+ : "r" (addr)
+ );
+ return val;
+}
+
+static inline u32 readl(const volatile void __iomem *addr)
+{
+ u32 val;
+ asm volatile(
+ "%0 = memw(%1);"
+ : "=&r" (val)
+ : "r" (addr)
+ );
+ return val;
+}
+
+/*
+ * writeb - write a byte to a memory location
+ * @data: data to write to
+ * @addr: pointer to memory
+ *
+ */
+static inline void writeb(u8 data, volatile void __iomem *addr)
+{
+ asm volatile(
+ "memb(%0) = %1;"
+ :
+ : "r" (addr), "r" (data)
+ : "memory"
+ );
+}
+
+static inline void writew(u16 data, volatile void __iomem *addr)
+{
+ asm volatile(
+ "memh(%0) = %1;"
+ :
+ : "r" (addr), "r" (data)
+ : "memory"
+ );
+
+}
+
+static inline void writel(u32 data, volatile void __iomem *addr)
+{
+ asm volatile(
+ "memw(%0) = %1;"
+ :
+ : "r" (addr), "r" (data)
+ : "memory"
+ );
+}
+
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+/*
+ * Need an mtype somewhere in here, for cache type deals?
+ * This is probably too long for an inline.
+ */
+void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size);
+
+static inline void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
+{
+ return ioremap_nocache(phys_addr, size);
+}
+
+static inline void iounmap(volatile void __iomem *addr)
+{
+ __iounmap(addr);
+}
+
+#define __raw_writel writel
+
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
+ int count)
+{
+ memcpy(dst, (void *) src, count);
+}
+
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
+ int count)
+{
+ memcpy((void *) dst, src, count);
+}
+
+#define PCI_IO_ADDR (volatile void __iomem *)
+
+/*
+ * inb - read byte from I/O port or something
+ * @port: address in I/O space
+ *
+ * Operates on "I/O bus I/O space"
+ */
+static inline u8 inb(unsigned long port)
+{
+ return readb(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline u16 inw(unsigned long port)
+{
+ return readw(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline u32 inl(unsigned long port)
+{
+ return readl(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+/*
+ * outb - write a byte to a memory location
+ * @data: data to write to
+ * @addr: address in I/O space
+ */
+static inline void outb(u8 data, unsigned long port)
+{
+ writeb(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline void outw(u16 data, unsigned long port)
+{
+ writew(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline void outl(u32 data, unsigned long port)
+{
+ writel(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+#define outb_p outb
+#define outw_p outw
+#define outl_p outl
+
+#define inb_p inb
+#define inw_p inw
+#define inl_p inl
+
+static inline void insb(unsigned long port, void *buffer, int count)
+{
+ if (count) {
+ u8 *buf = buffer;
+ do {
+ u8 x = inb(port);
+ *buf++ = x;
+ } while (--count);
+ }
+}
+
+static inline void insw(unsigned long port, void *buffer, int count)
+{
+ if (count) {
+ u16 *buf = buffer;
+ do {
+ u16 x = inw(port);
+ *buf++ = x;
+ } while (--count);
+ }
+}
+
+static inline void insl(unsigned long port, void *buffer, int count)
+{
+ if (count) {
+ u32 *buf = buffer;
+ do {
+ u32 x = inw(port);
+ *buf++ = x;
+ } while (--count);
+ }
+}
+
+static inline void outsb(unsigned long port, const void *buffer, int count)
+{
+ if (count) {
+ const u8 *buf = buffer;
+ do {
+ outb(*buf++, port);
+ } while (--count);
+ }
+}
+
+static inline void outsw(unsigned long port, const void *buffer, int count)
+{
+ if (count) {
+ const u16 *buf = buffer;
+ do {
+ outw(*buf++, port);
+ } while (--count);
+ }
+}
+
+static inline void outsl(unsigned long port, const void *buffer, int count)
+{
+ if (count) {
+ const u32 *buf = buffer;
+ do {
+ outl(*buf++, port);
+ } while (--count);
+ }
+}
+
+#define flush_write_buffers() do { } while (0)
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/hexagon/include/asm/irq.h b/arch/hexagon/include/asm/irq.h
new file mode 100644
index 000000000000..ded8c15cf3e5
--- /dev/null
+++ b/arch/hexagon/include/asm/irq.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_IRQ_H_
+#define _ASM_IRQ_H_
+
+/* Number of first-level interrupts associated with the CPU core. */
+#define HEXAGON_CPUINTS 32
+
+/*
+ * Must define NR_IRQS before including <asm-generic/irq.h>
+ * 64 == the two SIRC's, 176 == the two gpio's
+ *
+ * IRQ configuration is still in flux; defining this to a comfortably
+ * large number.
+ */
+#define NR_IRQS 512
+
+#include <asm-generic/irq.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/irqflags.h b/arch/hexagon/include/asm/irqflags.h
new file mode 100644
index 000000000000..ec1523655416
--- /dev/null
+++ b/arch/hexagon/include/asm/irqflags.h
@@ -0,0 +1,62 @@
+/*
+ * IRQ support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/hexagon_vm.h>
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ return __vmgetie();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ return __vmsetie(VM_INT_DISABLE);
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return !flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return !__vmgetie();
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ __vmsetie(VM_INT_ENABLE);
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ __vmsetie(VM_INT_DISABLE);
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ __vmsetie(flags);
+}
+
+#endif
diff --git a/arch/hexagon/include/asm/kgdb.h b/arch/hexagon/include/asm/kgdb.h
new file mode 100644
index 000000000000..9e8779702f10
--- /dev/null
+++ b/arch/hexagon/include/asm/kgdb.h
@@ -0,0 +1,43 @@
+/*
+ * arch/hexagon/include/asm/kgdb.h - Hexagon KGDB Support
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __HEXAGON_KGDB_H__
+#define __HEXAGON_KGDB_H__
+
+#define BREAK_INSTR_SIZE 4
+#define CACHE_FLUSH_IS_SAFE 1
+#define BUFMAX ((NUMREGBYTES * 2) + 512)
+
+static inline void arch_kgdb_breakpoint(void)
+{
+ asm("trap0(#0xDB)");
+}
+
+/* Registers:
+ * 32 gpr + sa0/1 + lc0/1 + m0/1 + gp + ugp + pred + pc = 42 total.
+ * vm regs = psp+elr+est+badva = 4
+ * syscall+restart = 2 more
+ * so 48 = 42 +4 + 2
+ */
+#define DBG_USER_REGS 42
+#define DBG_MAX_REG_NUM (DBG_USER_REGS + 6)
+#define NUMREGBYTES (DBG_MAX_REG_NUM*4)
+
+#endif /* __HEXAGON_KGDB_H__ */
diff --git a/arch/arm/mach-netx/include/mach/memory.h b/arch/hexagon/include/asm/linkage.h
index 59561496c36e..a00b85f680b8 100644
--- a/arch/arm/mach-netx/include/mach/memory.h
+++ b/arch/hexagon/include/asm/linkage.h
@@ -1,11 +1,9 @@
/*
- * arch/arm/mach-netx/include/mach/memory.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
+ * 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
@@ -14,13 +12,14 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
*/
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
-#define PLAT_PHYS_OFFSET UL(0x80000000)
+#define __ALIGN .align 4
+#define __ALIGN_STR ".align 4"
#endif
-
diff --git a/arch/hexagon/include/asm/mem-layout.h b/arch/hexagon/include/asm/mem-layout.h
new file mode 100644
index 000000000000..72e5dcda79f5
--- /dev/null
+++ b/arch/hexagon/include/asm/mem-layout.h
@@ -0,0 +1,112 @@
+/*
+ * Memory layout definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_MEM_LAYOUT_H
+#define _ASM_HEXAGON_MEM_LAYOUT_H
+
+#include <linux/const.h>
+
+/*
+ * Have to do this for ginormous numbers, else they get printed as
+ * negative numbers, which the linker no likey when you try to
+ * assign it to the location counter.
+ */
+
+#define PAGE_OFFSET _AC(0xc0000000, UL)
+
+/*
+ * LOAD_ADDRESS is the physical/linear address of where in memory
+ * the kernel gets loaded. The 12 least significant bits must be zero (0)
+ * due to limitations on setting the EVB
+ *
+ */
+
+#ifndef LOAD_ADDRESS
+#define LOAD_ADDRESS 0x00000000
+#endif
+
+#define TASK_SIZE (PAGE_OFFSET)
+
+/* not sure how these are used yet */
+#define STACK_TOP TASK_SIZE
+#define STACK_TOP_MAX TASK_SIZE
+
+#ifndef __ASSEMBLY__
+enum fixed_addresses {
+ FIX_KMAP_BEGIN,
+ FIX_KMAP_END, /* check for per-cpuism */
+ __end_of_fixed_addresses
+};
+
+#define MIN_KERNEL_SEG 0x300 /* From 0xc0000000 */
+extern int max_kernel_seg;
+
+/*
+ * Start of vmalloc virtual address space for kernel;
+ * supposed to be based on the amount of physical memory available
+ */
+
+#define VMALLOC_START (PAGE_OFFSET + VMALLOC_OFFSET + \
+ (unsigned long)high_memory)
+
+/* Gap between physical ram and vmalloc space for guard purposes. */
+#define VMALLOC_OFFSET PAGE_SIZE
+
+/*
+ * Create the space between VMALLOC_START and FIXADDR_TOP backwards
+ * from the ... "top".
+ *
+ * Permanent IO mappings will live at 0xfexx_xxxx
+ * Hypervisor occupies the last 16MB page at 0xffxxxxxx
+ */
+
+#define FIXADDR_TOP 0xfe000000
+#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
+
+/*
+ * "permanent kernel mappings", defined as long-lasting mappings of
+ * high-memory page frames into the kernel address space.
+ */
+
+#define LAST_PKMAP PTRS_PER_PTE
+#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
+#define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+/*
+ * To the "left" of the fixed map space is the kmap space
+ *
+ * "Permanent Kernel Mappings"; fancy (or less fancy) PTE table
+ * that looks like it's actually walked.
+ * Need to check the alignment/shift usage; some archs use
+ * PMD_MASK on this value
+ */
+#define PKMAP_BASE (FIXADDR_START-PAGE_SIZE*LAST_PKMAP)
+
+/*
+ * 2 pages of guard gap between where vmalloc area ends
+ * and pkmap_base begins.
+ */
+#define VMALLOC_END (PKMAP_BASE-PAGE_SIZE*2)
+#endif /* !__ASSEMBLY__ */
+
+
+#endif /* _ASM_HEXAGON_MEM_LAYOUT_H */
diff --git a/arch/hexagon/include/asm/mmu.h b/arch/hexagon/include/asm/mmu.h
new file mode 100644
index 000000000000..30a5d8d2659d
--- /dev/null
+++ b/arch/hexagon/include/asm/mmu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_MMU_H
+#define _ASM_MMU_H
+
+#include <asm/vdso.h>
+
+/*
+ * Architecture-specific state for a mm_struct.
+ * For the Hexagon Virtual Machine, it can be a copy
+ * of the pointer to the page table base.
+ */
+struct mm_context {
+ unsigned long long generation;
+ unsigned long ptbase;
+ struct hexagon_vdso *vdso;
+};
+
+typedef struct mm_context mm_context_t;
+
+#endif
diff --git a/arch/hexagon/include/asm/mmu_context.h b/arch/hexagon/include/asm/mmu_context.h
new file mode 100644
index 000000000000..b4fe5a5411b6
--- /dev/null
+++ b/arch/hexagon/include/asm/mmu_context.h
@@ -0,0 +1,100 @@
+/*
+ * MM context support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_MMU_CONTEXT_H
+#define _ASM_MMU_CONTEXT_H
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/mem-layout.h>
+
+static inline void destroy_context(struct mm_struct *mm)
+{
+}
+
+/*
+ * VM port hides all TLB management, so "lazy TLB" isn't very
+ * meaningful. Even for ports to architectures with visble TLBs,
+ * this is almost invariably a null function.
+ */
+static inline void enter_lazy_tlb(struct mm_struct *mm,
+ struct task_struct *tsk)
+{
+}
+
+/*
+ * Architecture-specific actions, if any, for memory map deactivation.
+ */
+static inline void deactivate_mm(struct task_struct *tsk,
+ struct mm_struct *mm)
+{
+}
+
+/**
+ * init_new_context - initialize context related info for new mm_struct instance
+ * @tsk: pointer to a task struct
+ * @mm: pointer to a new mm struct
+ */
+static inline int init_new_context(struct task_struct *tsk,
+ struct mm_struct *mm)
+{
+ /* mm->context is set up by pgd_alloc */
+ return 0;
+}
+
+/*
+ * Switch active mm context
+ */
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ struct task_struct *tsk)
+{
+ int l1;
+
+ /*
+ * For virtual machine, we have to update system map if it's been
+ * touched.
+ */
+ if (next->context.generation < prev->context.generation) {
+ for (l1 = MIN_KERNEL_SEG; l1 <= max_kernel_seg; l1++)
+ next->pgd[l1] = init_mm.pgd[l1];
+
+ next->context.generation = prev->context.generation;
+ }
+
+ __vmnewmap((void *)next->context.ptbase);
+}
+
+/*
+ * Activate new memory map for task
+ */
+static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ switch_mm(prev, next, current_thread_info()->task);
+ local_irq_restore(flags);
+}
+
+/* Generic hooks for arch_dup_mmap and arch_exit_mmap */
+#include <asm-generic/mm_hooks.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/module.h b/arch/hexagon/include/asm/module.h
new file mode 100644
index 000000000000..72ba494e6d7d
--- /dev/null
+++ b/arch/hexagon/include/asm/module.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_MODULE_H
+#define _ASM_MODULE_H
+
+#include <asm-generic/module.h>
+
+#define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " "
+
+#endif
diff --git a/arch/hexagon/include/asm/mutex.h b/arch/hexagon/include/asm/mutex.h
new file mode 100644
index 000000000000..58b52de1bc22
--- /dev/null
+++ b/arch/hexagon/include/asm/mutex.h
@@ -0,0 +1,8 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+#include <asm-generic/mutex-xchg.h>
diff --git a/arch/hexagon/include/asm/page.h b/arch/hexagon/include/asm/page.h
new file mode 100644
index 000000000000..edd97626c482
--- /dev/null
+++ b/arch/hexagon/include/asm/page.h
@@ -0,0 +1,157 @@
+/*
+ * Page management definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PAGE_H
+#define _ASM_PAGE_H
+
+#include <linux/const.h>
+
+/* This is probably not the most graceful way to handle this. */
+
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PAGE_SHIFT 12
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_4KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PAGE_SHIFT 14
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_16KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PAGE_SHIFT 16
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_64KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_256KB
+#define PAGE_SHIFT 18
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_256KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_1MB
+#define PAGE_SHIFT 20
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_1MB
+#endif
+
+/*
+ * These should be defined in hugetlb.h, but apparently not.
+ * "Huge" for us should be 4MB or 16MB, which are both represented
+ * in L1 PTE's. Right now, it's set up for 4MB.
+ */
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SHIFT 22
+#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE-1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
+#define HVM_HUGEPAGE_SIZE 0x5
+#endif
+
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+/*
+ * This is for PFN_DOWN, which mm.h needs. Seems the right place to pull it in.
+ */
+#include <linux/pfn.h>
+
+/*
+ * We implement a two-level architecture-specific page table structure.
+ * Null intermediate page table level (pmd, pud) definitions will come from
+ * asm-generic/pagetable-nopmd.h and asm-generic/pagetable-nopud.h
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
+
+#define pte_val(x) ((x).pte)
+#define pgd_val(x) ((x).pgd)
+#define pgprot_val(x) ((x).pgprot)
+#define __pte(x) ((pte_t) { (x) })
+#define __pgd(x) ((pgd_t) { (x) })
+#define __pgprot(x) ((pgprot_t) { (x) })
+
+/*
+ * We need a __pa and a __va routine for kernel space.
+ * MIPS says they're only used during mem_init.
+ * also, check if we need a PHYS_OFFSET.
+ */
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
+
+/* The "page frame" descriptor is defined in linux/mm.h */
+struct page;
+
+/* Returns page frame descriptor for virtual address. */
+#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(__pa(kaddr)))
+
+/* Default vm area behavior is non-executable. */
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#define pfn_valid(pfn) ((pfn) < max_mapnr)
+#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+/* Need to not use a define for linesize; may move this to another file. */
+static inline void clear_page(void *page)
+{
+ /* This can only be done on pages with L1 WB cache */
+ asm volatile(
+ " loop0(1f,%1);\n"
+ "1: { dczeroa(%0);\n"
+ " %0 = add(%0,#32); }:endloop0\n"
+ : "+r" (page)
+ : "r" (PAGE_SIZE/32)
+ : "lc0", "sa0", "memory"
+ );
+}
+
+#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
+
+/*
+ * Under assumption that kernel always "sees" user map...
+ */
+#define clear_user_page(page, vaddr, pg) clear_page(page)
+#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
+
+/*
+ * page_to_phys - convert page to physical address
+ * @page - pointer to page entry in mem_map
+ */
+#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
+
+/*
+ * For port to Hexagon Virtual Machine, MAYBE we check for attempts
+ * to reference reserved HVM space, but in any case, the VM will be
+ * protected.
+ */
+#define kern_addr_valid(addr) (1)
+
+#include <asm-generic/memory_model.h>
+/* XXX Todo: implement assembly-optimized version of getorder. */
+#include <asm-generic/getorder.h>
+
+#endif /* ifdef __ASSEMBLY__ */
+#endif /* ifdef __KERNEL__ */
+
+#endif
diff --git a/arch/hexagon/include/asm/param.h b/arch/hexagon/include/asm/param.h
new file mode 100644
index 000000000000..285344bbd036
--- /dev/null
+++ b/arch/hexagon/include/asm/param.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PARAM_H
+#define _ASM_PARAM_H
+
+#define EXEC_PAGESIZE 16384
+
+#include <asm-generic/param.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/perf_event.h b/arch/hexagon/include/asm/perf_event.h
new file mode 100644
index 000000000000..6c2910f91180
--- /dev/null
+++ b/arch/hexagon/include/asm/perf_event.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PERF_EVENT_H
+#define _ASM_PERF_EVENT_H
+
+#define PERF_EVENT_INDEX_OFFSET 0
+
+#endif /* _ASM_PERF_EVENT_H */
diff --git a/arch/hexagon/include/asm/pgalloc.h b/arch/hexagon/include/asm/pgalloc.h
new file mode 100644
index 000000000000..13443c775131
--- /dev/null
+++ b/arch/hexagon/include/asm/pgalloc.h
@@ -0,0 +1,146 @@
+/*
+ * Page table support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PGALLOC_H
+#define _ASM_PGALLOC_H
+
+#include <asm/mem-layout.h>
+#include <asm/atomic.h>
+
+#define check_pgt_cache() do {} while (0)
+
+extern unsigned long long kmap_generation;
+
+/*
+ * Page table creation interface
+ */
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+ pgd_t *pgd;
+
+ pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+
+ /*
+ * There may be better ways to do this, but to ensure
+ * that new address spaces always contain the kernel
+ * base mapping, and to ensure that the user area is
+ * initially marked invalid, initialize the new map
+ * map with a copy of the kernel's persistent map.
+ */
+
+ memcpy(pgd, swapper_pg_dir, PTRS_PER_PGD*sizeof(pgd_t *));
+ mm->context.generation = kmap_generation;
+
+ /* Physical version is what is passed to virtual machine on switch */
+ mm->context.ptbase = __pa(pgd);
+
+ return pgd;
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+ free_page((unsigned long) pgd);
+}
+
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+ unsigned long address)
+{
+ struct page *pte;
+
+ pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+
+ if (pte)
+ pgtable_page_ctor(pte);
+
+ return pte;
+}
+
+/* _kernel variant gets to use a different allocator */
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+ unsigned long address)
+{
+ gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
+ return (pte_t *) __get_free_page(flags);
+}
+
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+ pgtable_page_dtor(pte);
+ __free_page(pte);
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+ free_page((unsigned long)pte);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+ pgtable_t pte)
+{
+ /*
+ * Conveniently, zero in 3 LSB means indirect 4K page table.
+ * Not so convenient when you're trying to vary the page size.
+ */
+ set_pmd(pmd, __pmd(((unsigned long)page_to_pfn(pte) << PAGE_SHIFT) |
+ HEXAGON_L1_PTE_SIZE));
+}
+
+/*
+ * Other architectures seem to have ways of making all processes
+ * share the same pmd's for their kernel mappings, but the v0.3
+ * Hexagon VM spec has a "monolithic" L1 table for user and kernel
+ * segments. We track "generations" of the kernel map to minimize
+ * overhead, and update the "slave" copies of the kernel mappings
+ * as part of switch_mm. However, we still need to update the
+ * kernel map of the active thread who's calling pmd_populate_kernel...
+ */
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+ pte_t *pte)
+{
+ extern spinlock_t kmap_gen_lock;
+ pmd_t *ppmd;
+ int pmdindex;
+
+ spin_lock(&kmap_gen_lock);
+ kmap_generation++;
+ mm->context.generation = kmap_generation;
+ current->active_mm->context.generation = kmap_generation;
+ spin_unlock(&kmap_gen_lock);
+
+ set_pmd(pmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
+
+ /*
+ * Now the "slave" copy of the current thread.
+ * This is pointer arithmetic, not byte addresses!
+ */
+ pmdindex = (pgd_t *)pmd - mm->pgd;
+ ppmd = (pmd_t *)current->active_mm->pgd + pmdindex;
+ set_pmd(ppmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
+ if (pmdindex > max_kernel_seg)
+ max_kernel_seg = pmdindex;
+}
+
+#define __pte_free_tlb(tlb, pte, addr) \
+do { \
+ pgtable_page_dtor((pte)); \
+ tlb_remove_page((tlb), (pte)); \
+} while (0)
+
+#endif
diff --git a/arch/hexagon/include/asm/pgtable.h b/arch/hexagon/include/asm/pgtable.h
new file mode 100644
index 000000000000..ca619bf225ef
--- /dev/null
+++ b/arch/hexagon/include/asm/pgtable.h
@@ -0,0 +1,518 @@
+/*
+ * Page table support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PGTABLE_H
+#define _ASM_PGTABLE_H
+
+/*
+ * Page table definitions for Qualcomm Hexagon processor.
+ */
+#include <linux/swap.h>
+#include <asm/page.h>
+#include <asm-generic/pgtable-nopmd.h>
+
+/* A handy thing to have if one has the RAM. Declared in head.S */
+extern unsigned long empty_zero_page;
+extern unsigned long zero_page_mask;
+
+/*
+ * The PTE model described here is that of the Hexagon Virtual Machine,
+ * which autonomously walks 2-level page tables. At a lower level, we
+ * also describe the RISCish software-loaded TLB entry structure of
+ * the underlying Hexagon processor. A kernel built to run on the
+ * virtual machine has no need to know about the underlying hardware.
+ */
+#include <asm/vm_mmu.h>
+
+/*
+ * To maximize the comfort level for the PTE manipulation macros,
+ * define the "well known" architecture-specific bits.
+ */
+#define _PAGE_READ __HVM_PTE_R
+#define _PAGE_WRITE __HVM_PTE_W
+#define _PAGE_EXECUTE __HVM_PTE_X
+#define _PAGE_USER __HVM_PTE_U
+
+/*
+ * We have a total of 4 "soft" bits available in the abstract PTE.
+ * The two mandatory software bits are Dirty and Accessed.
+ * To make nonlinear swap work according to the more recent
+ * model, we want a low order "Present" bit to indicate whether
+ * the PTE describes MMU programming or swap space.
+ */
+#define _PAGE_PRESENT (1<<0)
+#define _PAGE_DIRTY (1<<1)
+#define _PAGE_ACCESSED (1<<2)
+
+/*
+ * _PAGE_FILE is only meaningful if _PAGE_PRESENT is false, while
+ * _PAGE_DIRTY is only meaningful if _PAGE_PRESENT is true.
+ * So we can overload the bit...
+ */
+#define _PAGE_FILE _PAGE_DIRTY /* set: pagecache, unset = swap */
+
+/*
+ * For now, let's say that Valid and Present are the same thing.
+ * Alternatively, we could say that it's the "or" of R, W, and X
+ * permissions.
+ */
+#define _PAGE_VALID _PAGE_PRESENT
+
+/*
+ * We're not defining _PAGE_GLOBAL here, since there's no concept
+ * of global pages or ASIDs exposed to the Hexagon Virtual Machine,
+ * and we want to use the same page table structures and macros in
+ * the native kernel as we do in the virtual machine kernel.
+ * So we'll put up with a bit of inefficiency for now...
+ */
+
+/*
+ * Top "FOURTH" level (pgd), which for the Hexagon VM is really
+ * only the second from the bottom, pgd and pud both being collapsed.
+ * Each entry represents 4MB of virtual address space, 4K of table
+ * thus maps the full 4GB.
+ */
+#define PGDIR_SHIFT 22
+#define PTRS_PER_PGD 1024
+
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PTRS_PER_PTE 1024
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PTRS_PER_PTE 256
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PTRS_PER_PTE 64
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_256KB
+#define PTRS_PER_PTE 16
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_1MB
+#define PTRS_PER_PTE 4
+#endif
+
+/* Any bigger and the PTE disappears. */
+#define pgd_ERROR(e) \
+ printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__,\
+ pgd_val(e))
+
+/*
+ * Page Protection Constants. Includes (in this variant) cache attributes.
+ */
+extern unsigned long _dflt_cache_att;
+
+#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _dflt_cache_att)
+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
+#define PAGE_COPY PAGE_READONLY
+#define PAGE_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
+#define PAGE_COPY_EXEC PAGE_EXEC
+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+ _PAGE_EXECUTE | _PAGE_WRITE | _dflt_cache_att)
+#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_READ | \
+ _PAGE_WRITE | _PAGE_EXECUTE | _dflt_cache_att)
+
+
+/*
+ * Aliases for mapping mmap() protection bits to page protections.
+ * These get used for static initialization, so using the _dflt_cache_att
+ * variable for the default cache attribute isn't workable. If the
+ * default gets changed at boot time, the boot option code has to
+ * update data structures like the protaction_map[] array.
+ */
+#define CACHEDEF (CACHE_DEFAULT << 6)
+
+/* Private (copy-on-write) page protections. */
+#define __P000 __pgprot(_PAGE_PRESENT | _PAGE_USER | CACHEDEF)
+#define __P001 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | CACHEDEF)
+#define __P010 __P000 /* Write-only copy-on-write */
+#define __P011 __P001 /* Read/Write copy-on-write */
+#define __P100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_EXECUTE | CACHEDEF)
+#define __P101 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_EXECUTE | \
+ _PAGE_READ | CACHEDEF)
+#define __P110 __P100 /* Write/execute copy-on-write */
+#define __P111 __P101 /* Read/Write/Execute, copy-on-write */
+
+/* Shared page protections. */
+#define __S000 __P000
+#define __S001 __P001
+#define __S010 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_WRITE | CACHEDEF)
+#define __S011 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+ _PAGE_WRITE | CACHEDEF)
+#define __S100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_EXECUTE | CACHEDEF)
+#define __S101 __P101
+#define __S110 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
+#define __S111 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+ _PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* located in head.S */
+
+/* Seems to be zero even in architectures where the zero page is firewalled? */
+#define FIRST_USER_ADDRESS 0
+#define pte_special(pte) 0
+#define pte_mkspecial(pte) (pte)
+
+/* HUGETLB not working currently */
+#ifdef CONFIG_HUGETLB_PAGE
+#define pte_mkhuge(pte) __pte((pte_val(pte) & ~0x3) | HVM_HUGEPAGE_SIZE)
+#endif
+
+/*
+ * For now, assume that higher-level code will do TLB/MMU invalidations
+ * and don't insert that overhead into this low-level function.
+ */
+extern void sync_icache_dcache(pte_t pte);
+
+#define pte_present_exec_user(pte) \
+ ((pte_val(pte) & (_PAGE_EXECUTE | _PAGE_USER)) == \
+ (_PAGE_EXECUTE | _PAGE_USER))
+
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+ /* should really be using pte_exec, if it weren't declared later. */
+ if (pte_present_exec_user(pteval))
+ sync_icache_dcache(pteval);
+
+ *ptep = pteval;
+}
+
+/*
+ * For the Hexagon Virtual Machine MMU (or its emulation), a null/invalid
+ * L1 PTE (PMD/PGD) has 7 in the least significant bits. For the L2 PTE
+ * (Linux PTE), the key is to have bits 11..9 all zero. We'd use 0x7
+ * as a universal null entry, but some of those least significant bits
+ * are interpreted by software.
+ */
+#define _NULL_PMD 0x7
+#define _NULL_PTE 0x0
+
+static inline void pmd_clear(pmd_t *pmd_entry_ptr)
+{
+ pmd_val(*pmd_entry_ptr) = _NULL_PMD;
+}
+
+/*
+ * Conveniently, a null PTE value is invalid.
+ */
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
+{
+ pte_val(*ptep) = _NULL_PTE;
+}
+
+#ifdef NEED_PMD_INDEX_DESPITE_BEING_2_LEVEL
+/**
+ * pmd_index - returns the index of the entry in the PMD page
+ * which would control the given virtual address
+ */
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
+#endif
+
+/**
+ * pgd_index - returns the index of the entry in the PGD page
+ * which would control the given virtual address
+ *
+ * This returns the *index* for the address in the pgd_t
+ */
+#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+/*
+ * pgd_offset - find an offset in a page-table-directory
+ */
+#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
+
+/*
+ * pgd_offset_k - get kernel (init_mm) pgd entry pointer for addr
+ */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/**
+ * pmd_none - check if pmd_entry is mapped
+ * @pmd_entry: pmd entry
+ *
+ * MIPS checks it against that "invalid pte table" thing.
+ */
+static inline int pmd_none(pmd_t pmd)
+{
+ return pmd_val(pmd) == _NULL_PMD;
+}
+
+/**
+ * pmd_present - is there a page table behind this?
+ * Essentially the inverse of pmd_none. We maybe
+ * save an inline instruction by defining it this
+ * way, instead of simply "!pmd_none".
+ */
+static inline int pmd_present(pmd_t pmd)
+{
+ return pmd_val(pmd) != (unsigned long)_NULL_PMD;
+}
+
+/**
+ * pmd_bad - check if a PMD entry is "bad". That might mean swapped out.
+ * As we have no known cause of badness, it's null, as it is for many
+ * architectures.
+ */
+static inline int pmd_bad(pmd_t pmd)
+{
+ return 0;
+}
+
+/*
+ * pmd_page - converts a PMD entry to a page pointer
+ */
+#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+/**
+ * pte_none - check if pte is mapped
+ * @pte: pte_t entry
+ */
+static inline int pte_none(pte_t pte)
+{
+ return pte_val(pte) == _NULL_PTE;
+};
+
+/*
+ * pte_present - check if page is present
+ */
+static inline int pte_present(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_PRESENT;
+}
+
+/* mk_pte - make a PTE out of a page pointer and protection bits */
+#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
+
+/* pte_page - returns a page (frame pointer/descriptor?) based on a PTE */
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+
+/* pte_mkold - mark PTE as not recently accessed */
+static inline pte_t pte_mkold(pte_t pte)
+{
+ pte_val(pte) &= ~_PAGE_ACCESSED;
+ return pte;
+}
+
+/* pte_mkyoung - mark PTE as recently accessed */
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_ACCESSED;
+ return pte;
+}
+
+/* pte_mkclean - mark page as in sync with backing store */
+static inline pte_t pte_mkclean(pte_t pte)
+{
+ pte_val(pte) &= ~_PAGE_DIRTY;
+ return pte;
+}
+
+/* pte_mkdirty - mark page as modified */
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_DIRTY;
+ return pte;
+}
+
+/* pte_young - "is PTE marked as accessed"? */
+static inline int pte_young(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_ACCESSED;
+}
+
+/* pte_dirty - "is PTE dirty?" */
+static inline int pte_dirty(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_DIRTY;
+}
+
+/* pte_modify - set protection bits on PTE */
+static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
+{
+ pte_val(pte) &= PAGE_MASK;
+ pte_val(pte) |= pgprot_val(prot);
+ return pte;
+}
+
+/* pte_wrprotect - mark page as not writable */
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+ pte_val(pte) &= ~_PAGE_WRITE;
+ return pte;
+}
+
+/* pte_mkwrite - mark page as writable */
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_WRITE;
+ return pte;
+}
+
+/* pte_mkexec - mark PTE as executable */
+static inline pte_t pte_mkexec(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_EXECUTE;
+ return pte;
+}
+
+/* pte_read - "is PTE marked as readable?" */
+static inline int pte_read(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_READ;
+}
+
+/* pte_write - "is PTE marked as writable?" */
+static inline int pte_write(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_WRITE;
+}
+
+
+/* pte_exec - "is PTE marked as executable?" */
+static inline int pte_exec(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_EXECUTE;
+}
+
+/* __pte_to_swp_entry - extract swap entry from PTE */
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+
+/* __swp_entry_to_pte - extract PTE from swap entry */
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+/* pfn_pte - convert page number and protection value to page table entry */
+#define pfn_pte(pfn, pgprot) __pte((pfn << PAGE_SHIFT) | pgprot_val(pgprot))
+
+/* pte_pfn - convert pte to page frame number */
+#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+
+/*
+ * set_pte_at - update page table and do whatever magic may be
+ * necessary to make the underlying hardware/firmware take note.
+ *
+ * VM may require a virtual instruction to alert the MMU.
+ */
+#define set_pte_at(mm, addr, ptep, pte) set_pte(ptep, pte)
+
+/*
+ * May need to invoke the virtual machine as well...
+ */
+#define pte_unmap(pte) do { } while (0)
+#define pte_unmap_nested(pte) do { } while (0)
+
+/*
+ * pte_offset_map - returns the linear address of the page table entry
+ * corresponding to an address
+ */
+#define pte_offset_map(dir, address) \
+ ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
+
+#define pte_offset_map_nested(pmd, addr) pte_offset_map(pmd, addr)
+
+/* pte_offset_kernel - kernel version of pte_offset */
+#define pte_offset_kernel(dir, address) \
+ ((pte_t *) (unsigned long) __va(pmd_val(*dir) & PAGE_MASK) \
+ + __pte_offset(address))
+
+/* ZERO_PAGE - returns the globally shared zero page */
+#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
+
+#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+/* Nothing special about IO remapping at this point */
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+/* I think this is in case we have page table caches; needed by init/main.c */
+#define pgtable_cache_init() do { } while (0)
+
+/*
+ * Swap/file PTE definitions. If _PAGE_PRESENT is zero, the rest of the
+ * PTE is interpreted as swap information. Depending on the _PAGE_FILE
+ * bit, the remaining free bits are eitehr interpreted as a file offset
+ * or a swap type/offset tuple. Rather than have the TLB fill handler
+ * test _PAGE_PRESENT, we're going to reserve the permissions bits
+ * and set them to all zeros for swap entries, which speeds up the
+ * miss handler at the cost of 3 bits of offset. That trade-off can
+ * be revisited if necessary, but Hexagon processor architecture and
+ * target applications suggest a lot of TLB misses and not much swap space.
+ *
+ * Format of swap PTE:
+ * bit 0: Present (zero)
+ * bit 1: _PAGE_FILE (zero)
+ * bits 2-6: swap type (arch independent layer uses 5 bits max)
+ * bits 7-9: bits 2:0 of offset
+ * bits 10-12: effectively _PAGE_PROTNONE (all zero)
+ * bits 13-31: bits 21:3 of swap offset
+ *
+ * Format of file PTE:
+ * bit 0: Present (zero)
+ * bit 1: _PAGE_FILE (zero)
+ * bits 2-9: bits 7:0 of offset
+ * bits 10-12: effectively _PAGE_PROTNONE (all zero)
+ * bits 13-31: bits 26:8 of swap offset
+ *
+ * The split offset makes some of the following macros a little gnarly,
+ * but there's plenty of precedent for this sort of thing.
+ */
+#define PTE_FILE_MAX_BITS 27
+
+/* Used for swap PTEs */
+#define __swp_type(swp_pte) (((swp_pte).val >> 2) & 0x1f)
+
+#define __swp_offset(swp_pte) \
+ ((((swp_pte).val >> 7) & 0x7) | (((swp_pte).val >> 10) & 0x003ffff8))
+
+#define __swp_entry(type, offset) \
+ ((swp_entry_t) { \
+ ((type << 2) | \
+ ((offset & 0x3ffff8) << 10) | ((offset & 0x7) << 7)) })
+
+/* Used for file PTEs */
+#define pte_file(pte) \
+ ((pte_val(pte) & (_PAGE_FILE | _PAGE_PRESENT)) == _PAGE_FILE)
+
+#define pte_to_pgoff(pte) \
+ (((pte_val(pte) >> 2) & 0xff) | ((pte_val(pte) >> 5) & 0x07ffff00))
+
+#define pgoff_to_pte(off) \
+ ((pte_t) { ((((off) & 0x7ffff00) << 5) | (((off) & 0xff) << 2)\
+ | _PAGE_FILE) })
+
+/* Oh boy. There are a lot of possible arch overrides found in this file. */
+#include <asm-generic/pgtable.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h
new file mode 100644
index 000000000000..20c5ddabbd8b
--- /dev/null
+++ b/arch/hexagon/include/asm/processor.h
@@ -0,0 +1,123 @@
+/*
+ * Process/processor support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PROCESSOR_H
+#define _ASM_PROCESSOR_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/mem-layout.h>
+#include <asm/registers.h>
+#include <asm/hexagon_vm.h>
+
+/* must be a macro */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+/* task_struct, defined elsewhere, is the "process descriptor" */
+struct task_struct;
+
+/* this is defined in arch/process.c */
+extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
+
+/*
+ * thread_struct is supposed to be for context switch data.
+ * Specifically, to hold the state necessary to perform switch_to...
+ */
+struct thread_struct {
+ void *switch_sp;
+};
+
+/*
+ * initializes thread_struct
+ * The only thing we have in there is switch_sp
+ * which doesn't really need to be initialized.
+ */
+
+#define INIT_THREAD { \
+}
+
+#define cpu_relax() __vmyield()
+
+/*
+ * "Unlazying all lazy status" occurs here.
+ */
+static inline void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
+/*
+ * Decides where the kernel will search for a free chunk of vm space during
+ * mmaps.
+ * See also arch_get_unmapped_area.
+ * Doesn't affect if you have MAX_FIXED in the page flags set though...
+ *
+ * Apparently the convention is that ld.so will ask for "unmapped" private
+ * memory to be allocated SOMEWHERE, but it also asks for memory explicitly
+ * via MAP_FIXED at the lower * addresses starting at VA=0x0.
+ *
+ * If the two requests collide, you get authentic segfaulting action, so
+ * you have to kick the "unmapped" base requests higher up.
+ */
+#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE/3))
+
+
+#define task_pt_regs(task) \
+ ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1)
+
+#define KSTK_EIP(tsk) (pt_elr(task_pt_regs(tsk)))
+#define KSTK_ESP(tsk) (pt_psp(task_pt_regs(tsk)))
+
+/* Free all resources held by a thread; defined in process.c */
+extern void release_thread(struct task_struct *dead_task);
+
+/* Get wait channel for task P. */
+extern unsigned long get_wchan(struct task_struct *p);
+
+/* The following stuff is pretty HEXAGON specific. */
+
+/* This is really just here for __switch_to.
+ Offsets are pulled via asm-offsets.c */
+
+/*
+ * No real reason why VM and native switch stacks should be different.
+ * Ultimately this should merge. Note that Rev C. ABI called out only
+ * R24-27 as callee saved GPRs needing explicit attention (R29-31 being
+ * dealt with automagically by allocframe), but the current ABI has
+ * more, R16-R27. By saving more, the worst case is that we waste some
+ * cycles if building with the old compilers.
+ */
+
+struct hexagon_switch_stack {
+ unsigned long long r1716;
+ unsigned long long r1918;
+ unsigned long long r2120;
+ unsigned long long r2322;
+ unsigned long long r2524;
+ unsigned long long r2726;
+ unsigned long fp;
+ unsigned long lr;
+};
+
+#endif /* !__ASSEMBLY__ */
+
+#endif
diff --git a/arch/hexagon/include/asm/ptrace.h b/arch/hexagon/include/asm/ptrace.h
new file mode 100644
index 000000000000..3d2f607cd63c
--- /dev/null
+++ b/arch/hexagon/include/asm/ptrace.h
@@ -0,0 +1,35 @@
+/*
+ * Ptrace definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PTRACE_H
+#define _ASM_PTRACE_H
+
+#include <asm/registers.h>
+
+#define instruction_pointer(regs) pt_elr(regs)
+#define user_stack_pointer(regs) ((regs)->r29)
+
+#define profile_pc(regs) instruction_pointer(regs)
+
+/* kprobe-based event tracer support */
+extern int regs_query_register_offset(const char *name);
+extern const char *regs_query_register_name(unsigned int offset);
+
+#endif
diff --git a/arch/hexagon/include/asm/registers.h b/arch/hexagon/include/asm/registers.h
new file mode 100644
index 000000000000..4dd741be855d
--- /dev/null
+++ b/arch/hexagon/include/asm/registers.h
@@ -0,0 +1,236 @@
+/*
+ * Register definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_REGISTERS_H
+#define _ASM_REGISTERS_H
+
+#define SP r29
+
+#ifndef __ASSEMBLY__
+
+/* See kernel/entry.S for further documentation. */
+
+/*
+ * Entry code copies the event record out of guest registers into
+ * this structure (which is on the stack).
+ */
+
+struct hvm_event_record {
+ unsigned long vmel; /* Event Linkage (return address) */
+ unsigned long vmest; /* Event context - pre-event SSR values */
+ unsigned long vmpsp; /* Previous stack pointer */
+ unsigned long vmbadva; /* Bad virtual address for addressing events */
+};
+
+struct pt_regs {
+ long restart_r0; /* R0 checkpoint for syscall restart */
+ long syscall_nr; /* Only used in system calls */
+ union {
+ struct {
+ unsigned long usr;
+ unsigned long preds;
+ };
+ long long int predsusr;
+ };
+ union {
+ struct {
+ unsigned long m0;
+ unsigned long m1;
+ };
+ long long int m1m0;
+ };
+ union {
+ struct {
+ unsigned long sa1;
+ unsigned long lc1;
+ };
+ long long int lc1sa1;
+ };
+ union {
+ struct {
+ unsigned long sa0;
+ unsigned long lc0;
+ };
+ long long int lc0sa0;
+ };
+ union {
+ struct {
+ unsigned long gp;
+ unsigned long ugp;
+ };
+ long long int ugpgp;
+ };
+ /*
+ * Be extremely careful with rearranging these, if at all. Some code
+ * assumes the 32 registers exist exactly like this in memory;
+ * e.g. kernel/ptrace.c
+ * e.g. kernel/signal.c (restore_sigcontext)
+ */
+ union {
+ struct {
+ unsigned long r00;
+ unsigned long r01;
+ };
+ long long int r0100;
+ };
+ union {
+ struct {
+ unsigned long r02;
+ unsigned long r03;
+ };
+ long long int r0302;
+ };
+ union {
+ struct {
+ unsigned long r04;
+ unsigned long r05;
+ };
+ long long int r0504;
+ };
+ union {
+ struct {
+ unsigned long r06;
+ unsigned long r07;
+ };
+ long long int r0706;
+ };
+ union {
+ struct {
+ unsigned long r08;
+ unsigned long r09;
+ };
+ long long int r0908;
+ };
+ union {
+ struct {
+ unsigned long r10;
+ unsigned long r11;
+ };
+ long long int r1110;
+ };
+ union {
+ struct {
+ unsigned long r12;
+ unsigned long r13;
+ };
+ long long int r1312;
+ };
+ union {
+ struct {
+ unsigned long r14;
+ unsigned long r15;
+ };
+ long long int r1514;
+ };
+ union {
+ struct {
+ unsigned long r16;
+ unsigned long r17;
+ };
+ long long int r1716;
+ };
+ union {
+ struct {
+ unsigned long r18;
+ unsigned long r19;
+ };
+ long long int r1918;
+ };
+ union {
+ struct {
+ unsigned long r20;
+ unsigned long r21;
+ };
+ long long int r2120;
+ };
+ union {
+ struct {
+ unsigned long r22;
+ unsigned long r23;
+ };
+ long long int r2322;
+ };
+ union {
+ struct {
+ unsigned long r24;
+ unsigned long r25;
+ };
+ long long int r2524;
+ };
+ union {
+ struct {
+ unsigned long r26;
+ unsigned long r27;
+ };
+ long long int r2726;
+ };
+ union {
+ struct {
+ unsigned long r28;
+ unsigned long r29;
+ };
+ long long int r2928;
+ };
+ union {
+ struct {
+ unsigned long r30;
+ unsigned long r31;
+ };
+ long long int r3130;
+ };
+ /* VM dispatch pushes event record onto stack - we can build on it */
+ struct hvm_event_record hvmer;
+};
+
+/* Defines to conveniently access the values */
+
+/*
+ * As of the VM spec 0.5, these registers are now set/retrieved via a
+ * VM call. On the in-bound side, we just fetch the values
+ * at the entry points and stuff them into the old record in pt_regs.
+ * However, on the outbound side, probably at VM rte, we set the
+ * registers back.
+ */
+
+#define pt_elr(regs) ((regs)->hvmer.vmel)
+#define pt_set_elr(regs, val) ((regs)->hvmer.vmel = (val))
+#define pt_cause(regs) ((regs)->hvmer.vmest & (HVM_VMEST_CAUSE_MSK))
+#define user_mode(regs) \
+ (((regs)->hvmer.vmest & (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT)) != 0)
+#define ints_enabled(regs) \
+ (((regs)->hvmer.vmest & (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)) != 0)
+#define pt_psp(regs) ((regs)->hvmer.vmpsp)
+#define pt_badva(regs) ((regs)->hvmer.vmbadva)
+
+#define pt_set_rte_sp(regs, sp) do {\
+ pt_psp(regs) = (sp);\
+ (regs)->SP = (unsigned long) &((regs)->hvmer);\
+ } while (0)
+
+#define pt_set_kmode(regs) \
+ (regs)->hvmer.vmest = (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
+
+#define pt_set_usermode(regs) \
+ (regs)->hvmer.vmest = (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT) \
+ | (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
+
+#endif /* ifndef __ASSEMBLY */
+
+#endif
diff --git a/arch/hexagon/include/asm/setup.h b/arch/hexagon/include/asm/setup.h
new file mode 100644
index 000000000000..3b754c50bc0a
--- /dev/null
+++ b/arch/hexagon/include/asm/setup.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SETUP_H
+#define _ASM_SETUP_H
+
+#include <linux/init.h>
+#include <asm-generic/setup.h>
+
+extern char external_cmdline_buffer;
+
+void __init setup_arch_memory(void);
+
+#endif
diff --git a/arch/hexagon/include/asm/sigcontext.h b/arch/hexagon/include/asm/sigcontext.h
new file mode 100644
index 000000000000..ce6dcd995220
--- /dev/null
+++ b/arch/hexagon/include/asm/sigcontext.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SIGCONTEXT_H
+#define _ASM_SIGCONTEXT_H
+
+#include <asm/user.h>
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked. Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+ struct user_regs_struct sc_regs;
+} __aligned(8);
+
+#endif
diff --git a/arch/hexagon/include/asm/signal.h b/arch/hexagon/include/asm/signal.h
new file mode 100644
index 000000000000..471c0562e17b
--- /dev/null
+++ b/arch/hexagon/include/asm/signal.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SIGNAL_H
+#define _ASM_SIGNAL_H
+
+extern unsigned long __rt_sigtramp_template[2];
+
+#include <asm-generic/signal.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/smp.h b/arch/hexagon/include/asm/smp.h
new file mode 100644
index 000000000000..87c869a6a897
--- /dev/null
+++ b/arch/hexagon/include/asm/smp.h
@@ -0,0 +1,44 @@
+/*
+ * SMP definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+
+#include <linux/cpumask.h>
+
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+
+enum ipi_message_type {
+ IPI_NOP = 0,
+ IPI_RESCHEDULE = 1,
+ IPI_CALL_FUNC,
+ IPI_CALL_FUNC_SINGLE,
+ IPI_CPU_STOP,
+ IPI_TIMER,
+};
+
+extern void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg);
+extern void smp_start_cpus(void);
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+extern void smp_vm_unmask_irq(void *info);
+
+#endif
diff --git a/arch/hexagon/include/asm/spinlock.h b/arch/hexagon/include/asm/spinlock.h
new file mode 100644
index 000000000000..168a920485a8
--- /dev/null
+++ b/arch/hexagon/include/asm/spinlock.h
@@ -0,0 +1,186 @@
+/*
+ * Spinlock support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SPINLOCK_H
+#define _ASM_SPINLOCK_H
+
+#include <asm/irqflags.h>
+
+/*
+ * This file is pulled in for SMP builds.
+ * Really need to check all the barrier stuff for "true" SMP
+ */
+
+/*
+ * Read locks:
+ * - load the lock value
+ * - increment it
+ * - if the lock value is still negative, go back and try again.
+ * - unsuccessful store is unsuccessful. Go back and try again. Loser.
+ * - successful store new lock value if positive -> lock acquired
+ */
+static inline void arch_read_lock(arch_rwlock_t *lock)
+{
+ __asm__ __volatile__(
+ "1: R6 = memw_locked(%0);\n"
+ " { P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
+ " { if !P3 jump 1b; }\n"
+ " memw_locked(%0,P3) = R6;\n"
+ " { if !P3 jump 1b; }\n"
+ :
+ : "r" (&lock->lock)
+ : "memory", "r6", "p3"
+ );
+
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *lock)
+{
+ __asm__ __volatile__(
+ "1: R6 = memw_locked(%0);\n"
+ " R6 = add(R6,#-1);\n"
+ " memw_locked(%0,P3) = R6\n"
+ " if !P3 jump 1b;\n"
+ :
+ : "r" (&lock->lock)
+ : "memory", "r6", "p3"
+ );
+
+}
+
+/* I think this returns 0 on fail, 1 on success. */
+static inline int arch_read_trylock(arch_rwlock_t *lock)
+{
+ int temp;
+ __asm__ __volatile__(
+ " R6 = memw_locked(%1);\n"
+ " { %0 = #0; P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
+ " { if !P3 jump 1f; }\n"
+ " memw_locked(%1,P3) = R6;\n"
+ " { %0 = P3 }\n"
+ "1:\n"
+ : "=&r" (temp)
+ : "r" (&lock->lock)
+ : "memory", "r6", "p3"
+ );
+ return temp;
+}
+
+static inline int arch_read_can_lock(arch_rwlock_t *rwlock)
+{
+ return rwlock->lock == 0;
+}
+
+static inline int arch_write_can_lock(arch_rwlock_t *rwlock)
+{
+ return rwlock->lock == 0;
+}
+
+/* Stuffs a -1 in the lock value? */
+static inline void arch_write_lock(arch_rwlock_t *lock)
+{
+ __asm__ __volatile__(
+ "1: R6 = memw_locked(%0)\n"
+ " { P3 = cmp.eq(R6,#0); R6 = #-1;}\n"
+ " { if !P3 jump 1b; }\n"
+ " memw_locked(%0,P3) = R6;\n"
+ " { if !P3 jump 1b; }\n"
+ :
+ : "r" (&lock->lock)
+ : "memory", "r6", "p3"
+ );
+}
+
+
+static inline int arch_write_trylock(arch_rwlock_t *lock)
+{
+ int temp;
+ __asm__ __volatile__(
+ " R6 = memw_locked(%1)\n"
+ " { %0 = #0; P3 = cmp.eq(R6,#0); R6 = #-1;}\n"
+ " { if !P3 jump 1f; }\n"
+ " memw_locked(%1,P3) = R6;\n"
+ " %0 = P3;\n"
+ "1:\n"
+ : "=&r" (temp)
+ : "r" (&lock->lock)
+ : "memory", "r6", "p3"
+ );
+ return temp;
+
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *lock)
+{
+ smp_mb();
+ lock->lock = 0;
+}
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+ __asm__ __volatile__(
+ "1: R6 = memw_locked(%0);\n"
+ " P3 = cmp.eq(R6,#0);\n"
+ " { if !P3 jump 1b; R6 = #1; }\n"
+ " memw_locked(%0,P3) = R6;\n"
+ " { if !P3 jump 1b; }\n"
+ :
+ : "r" (&lock->lock)
+ : "memory", "r6", "p3"
+ );
+
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+ smp_mb();
+ lock->lock = 0;
+}
+
+static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
+{
+ int temp;
+ __asm__ __volatile__(
+ " R6 = memw_locked(%1);\n"
+ " P3 = cmp.eq(R6,#0);\n"
+ " { if !P3 jump 1f; R6 = #1; %0 = #0; }\n"
+ " memw_locked(%1,P3) = R6;\n"
+ " %0 = P3;\n"
+ "1:\n"
+ : "=&r" (temp)
+ : "r" (&lock->lock)
+ : "memory", "r6", "p3"
+ );
+ return temp;
+}
+
+/*
+ * SMP spinlocks are intended to allow only a single CPU at the lock
+ */
+#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
+#define arch_spin_unlock_wait(lock) \
+ do {while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
+#define arch_spin_is_locked(x) ((x)->lock != 0)
+
+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
+#endif
diff --git a/arch/hexagon/include/asm/spinlock_types.h b/arch/hexagon/include/asm/spinlock_types.h
new file mode 100644
index 000000000000..5e937af1c4ad
--- /dev/null
+++ b/arch/hexagon/include/asm/spinlock_types.h
@@ -0,0 +1,42 @@
+/*
+ * Spinlock support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SPINLOCK_TYPES_H
+#define _ASM_SPINLOCK_TYPES_H
+
+#include <linux/version.h>
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+ volatile unsigned int lock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile unsigned int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED { 0 }
+
+#endif
diff --git a/arch/hexagon/include/asm/string.h b/arch/hexagon/include/asm/string.h
new file mode 100644
index 000000000000..f4489c15942c
--- /dev/null
+++ b/arch/hexagon/include/asm/string.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_STRING_H_
+#define _ASM_STRING_H_
+
+#ifdef __KERNEL__
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+
+/* ToDo: use dczeroa, accelerate the compiler-constant zero case */
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *__to, int c, size_t __n);
+#endif
+
+
+#endif /* _ASM_STRING_H_ */
diff --git a/arch/hexagon/include/asm/suspend.h b/arch/hexagon/include/asm/suspend.h
new file mode 100644
index 000000000000..089dd8268791
--- /dev/null
+++ b/arch/hexagon/include/asm/suspend.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SUSPEND_H
+#define _ASM_SUSPEND_H
+
+static inline int arch_prepare_suspend(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/arch/hexagon/include/asm/swab.h b/arch/hexagon/include/asm/swab.h
new file mode 100644
index 000000000000..99cf0be3fb83
--- /dev/null
+++ b/arch/hexagon/include/asm/swab.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SWAB_H
+#define _ASM_SWAB_H
+
+#define __SWAB_64_THRU_32__
+
+#endif
diff --git a/arch/hexagon/include/asm/syscall.h b/arch/hexagon/include/asm/syscall.h
new file mode 100644
index 000000000000..3e7d61d38d97
--- /dev/null
+++ b/arch/hexagon/include/asm/syscall.h
@@ -0,0 +1,54 @@
+/*
+ * Syscall support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_SYSCALL_H
+#define _ASM_HEXAGON_SYSCALL_H
+
+typedef long (*syscall_fn)(unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long, unsigned long);
+
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *argv,
+ char __user * __user *envp);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+ unsigned long parent_tidp, unsigned long child_tidp);
+
+#define sys_execve sys_execve
+#define sys_clone sys_clone
+
+#include <asm-generic/syscalls.h>
+
+extern void *sys_call_table[];
+
+static inline long syscall_get_nr(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return regs->r06;
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ unsigned long *args)
+{
+ BUG_ON(i + n > 6);
+ memcpy(args, &(&regs->r00)[i], n * sizeof(args[0]));
+}
+#endif
diff --git a/arch/hexagon/include/asm/system.h b/arch/hexagon/include/asm/system.h
new file mode 100644
index 000000000000..323ed1dd65e2
--- /dev/null
+++ b/arch/hexagon/include/asm/system.h
@@ -0,0 +1,126 @@
+/*
+ * System level definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SYSTEM_H
+#define _ASM_SYSTEM_H
+
+#include <linux/linkage.h>
+#include <linux/irqflags.h>
+#include <asm/atomic.h>
+#include <asm/hexagon_vm.h>
+
+struct thread_struct;
+
+extern struct task_struct *__switch_to(struct task_struct *,
+ struct task_struct *,
+ struct task_struct *);
+
+#define switch_to(p, n, r) do {\
+ r = __switch_to((p), (n), (r));\
+} while (0)
+
+
+#define rmb() barrier()
+#define read_barrier_depends() barrier()
+#define wmb() barrier()
+#define mb() barrier()
+#define smp_rmb() barrier()
+#define smp_read_barrier_depends() barrier()
+#define smp_wmb() barrier()
+#define smp_mb() barrier()
+#define smp_mb__before_atomic_dec() barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc() barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
+/*
+ * __xchg - atomically exchange a register and a memory location
+ * @x: value to swap
+ * @ptr: pointer to memory
+ * @size: size of the value
+ *
+ * Only 4 bytes supported currently.
+ *
+ * Note: there was an errata for V2 about .new's and memw_locked.
+ *
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+ int size)
+{
+ unsigned long retval;
+
+ /* Can't seem to use printk or panic here, so just stop */
+ if (size != 4) do { asm volatile("brkpt;\n"); } while (1);
+
+ __asm__ __volatile__ (
+ "1: %0 = memw_locked(%1);\n" /* load into retval */
+ " memw_locked(%1,P0) = %2;\n" /* store into memory */
+ " if !P0 jump 1b;\n"
+ : "=&r" (retval)
+ : "r" (ptr), "r" (x)
+ : "memory", "p0"
+ );
+ return retval;
+}
+
+/*
+ * Atomically swap the contents of a register with memory. Should be atomic
+ * between multiple CPU's and within interrupts on the same CPU.
+ */
+#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
+ sizeof(*(ptr))))
+
+/* Set a value and use a memory barrier. Used by the scheduler somewhere. */
+#define set_mb(var, value) \
+ do { var = value; mb(); } while (0)
+
+/*
+ * see rt-mutex-design.txt; cmpxchg supposedly checks if *ptr == A and swaps.
+ * looks just like atomic_cmpxchg on our arch currently with a bunch of
+ * variable casting.
+ */
+#define __HAVE_ARCH_CMPXCHG 1
+
+#define cmpxchg(ptr, old, new) \
+({ \
+ __typeof__(ptr) __ptr = (ptr); \
+ __typeof__(*(ptr)) __old = (old); \
+ __typeof__(*(ptr)) __new = (new); \
+ __typeof__(*(ptr)) __oldval = 0; \
+ \
+ asm volatile( \
+ "1: %0 = memw_locked(%1);\n" \
+ " { P0 = cmp.eq(%0,%2);\n" \
+ " if (!P0.new) jump:nt 2f; }\n" \
+ " memw_locked(%1,p0) = %3;\n" \
+ " if (!P0) jump 1b;\n" \
+ "2:\n" \
+ : "=&r" (__oldval) \
+ : "r" (__ptr), "r" (__old), "r" (__new) \
+ : "memory", "p0" \
+ ); \
+ __oldval; \
+})
+
+/* Should probably shoot for an 8-byte aligned stack pointer */
+#define STACK_MASK (~7)
+#define arch_align_stack(x) (x & STACK_MASK)
+
+#endif
diff --git a/arch/hexagon/include/asm/thread_info.h b/arch/hexagon/include/asm/thread_info.h
new file mode 100644
index 000000000000..9c2934ff5756
--- /dev/null
+++ b/arch/hexagon/include/asm/thread_info.h
@@ -0,0 +1,154 @@
+/*
+ * Thread support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#include <asm/registers.h>
+#include <asm/page.h>
+#endif
+
+#define THREAD_SHIFT 12
+#define THREAD_SIZE (1<<THREAD_SHIFT)
+
+#if THREAD_SHIFT >= PAGE_SHIFT
+#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
+#else /* don't use standard allocator */
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
+extern void free_thread_info(struct thread_info *ti);
+#endif
+
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+ unsigned long seg;
+} mm_segment_t;
+
+/*
+ * This is union'd with the "bottom" of the kernel stack.
+ * It keeps track of thread info which is handy for routines
+ * to access quickly.
+ */
+
+struct thread_info {
+ struct task_struct *task; /* main task structure */
+ struct exec_domain *exec_domain; /* execution domain */
+ unsigned long flags; /* low level flags */
+ __u32 cpu; /* current cpu */
+ int preempt_count; /* 0=>preemptible,<0=>BUG */
+ mm_segment_t addr_limit; /* segmentation sux */
+ /*
+ * used for syscalls somehow;
+ * seems to have a function pointer and four arguments
+ */
+ struct restart_block restart_block;
+ /* Points to the current pt_regs frame */
+ struct pt_regs *regs;
+ /*
+ * saved kernel sp at switch_to time;
+ * not sure if this is used (it's not in the VM model it seems;
+ * see thread_struct)
+ */
+ unsigned long sp;
+};
+
+#else /* !__ASSEMBLY__ */
+
+#include <asm/asm-offsets.h>
+
+#endif /* __ASSEMBLY__ */
+
+/* looks like "linux/hardirq.h" uses this. */
+
+#define PREEMPT_ACTIVE 0x10000000
+
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk) \
+{ \
+ .task = &tsk, \
+ .exec_domain = &default_exec_domain, \
+ .flags = 0, \
+ .cpu = 0, \
+ .preempt_count = 1, \
+ .addr_limit = KERNEL_DS, \
+ .restart_block = { \
+ .fn = do_no_restart_syscall, \
+ }, \
+ .sp = 0, \
+ .regs = NULL, \
+}
+
+#define init_thread_info (init_thread_union.thread_info)
+#define init_stack (init_thread_union.stack)
+
+/* Tacky preprocessor trickery */
+#define qqstr(s) qstr(s)
+#define qstr(s) #s
+#define QUOTED_THREADINFO_REG qqstr(THREADINFO_REG)
+
+register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
+#define current_thread_info() __current_thread_info
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files
+ * may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+
+#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
+#define TIF_SIGPENDING 2 /* signal pending */
+#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+#define TIF_SINGLESTEP 4 /* restore ss @ return to usr mode */
+#define TIF_IRET 5 /* return with iret */
+#define TIF_RESTORE_SIGMASK 6 /* restore sig mask in do_signal() */
+/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_POLLING_NRFLAG 16
+#define TIF_MEMDIE 17 /* OOM killer killed process */
+
+#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
+#define _TIF_IRET (1 << TIF_IRET)
+#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
+
+/* work to do on interrupt/exception return - All but TIF_SYSCALL_TRACE */
+#define _TIF_WORK_MASK (0x0000FFFF & ~_TIF_SYSCALL_TRACE)
+
+/* work to do on any return to u-space */
+#define _TIF_ALLWORK_MASK 0x0000FFFF
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/hexagon/include/asm/time.h b/arch/hexagon/include/asm/time.h
new file mode 100644
index 000000000000..081b82cac9a9
--- /dev/null
+++ b/arch/hexagon/include/asm/time.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef ASM_TIME_H
+#define ASM_TIME_H
+
+extern cycles_t pcycle_freq_mhz;
+extern cycles_t thread_freq_mhz;
+extern cycles_t sleep_clk_freq;
+
+void setup_percpu_clockdev(void);
+void ipi_timer(void);
+
+#endif
diff --git a/arch/hexagon/include/asm/timer-regs.h b/arch/hexagon/include/asm/timer-regs.h
new file mode 100644
index 000000000000..d80db239a7b6
--- /dev/null
+++ b/arch/hexagon/include/asm/timer-regs.h
@@ -0,0 +1,39 @@
+/*
+ * Timer support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TIMER_REGS_H
+#define _ASM_TIMER_REGS_H
+
+/* This stuff should go into a platform specific file */
+#define TCX0_CLK_RATE 19200
+#define TIMER_ENABLE 0
+#define TIMER_CLR_ON_MATCH 1
+
+/*
+ * 8x50 HDD Specs 5-8. Simulator co-sim not fixed until
+ * release 1.1, and then it's "adjustable" and probably not defaulted.
+ */
+#define RTOS_TIMER_INT 3
+#ifdef CONFIG_HEXAGON_COMET
+#define RTOS_TIMER_REGS_ADDR 0xAB000000UL
+#endif
+#define SLEEP_CLK_RATE 32000
+
+#endif
diff --git a/arch/hexagon/include/asm/timex.h b/arch/hexagon/include/asm/timex.h
new file mode 100644
index 000000000000..b11c62b23f31
--- /dev/null
+++ b/arch/hexagon/include/asm/timex.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TIMEX_H
+#define _ASM_TIMEX_H
+
+#include <asm-generic/timex.h>
+#include <asm/timer-regs.h>
+
+/* Using TCX0 as our clock. CLOCK_TICK_RATE scheduled to be removed. */
+#define CLOCK_TICK_RATE TCX0_CLK_RATE
+
+#define ARCH_HAS_READ_CURRENT_TIMER
+
+static inline int read_current_timer(unsigned long *timer_val)
+{
+ *timer_val = (unsigned long) __vmgettime();
+ return 0;
+}
+
+#endif
diff --git a/arch/hexagon/include/asm/tlb.h b/arch/hexagon/include/asm/tlb.h
new file mode 100644
index 000000000000..473abde01d62
--- /dev/null
+++ b/arch/hexagon/include/asm/tlb.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TLB_H
+#define _ASM_TLB_H
+
+#include <linux/pagemap.h>
+#include <asm/tlbflush.h>
+
+/*
+ * We don't need any special per-pte or per-vma handling...
+ */
+#define tlb_start_vma(tlb, vma) do { } while (0)
+#define tlb_end_vma(tlb, vma) do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
+
+/*
+ * .. because we flush the whole mm when it fills up
+ */
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/tlbflush.h b/arch/hexagon/include/asm/tlbflush.h
new file mode 100644
index 000000000000..b89a90251225
--- /dev/null
+++ b/arch/hexagon/include/asm/tlbflush.h
@@ -0,0 +1,58 @@
+/*
+ * TLB flush support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TLBFLUSH_H
+#define _ASM_TLBFLUSH_H
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+
+/*
+ * TLB flushing -- in "SMP", these routines get defined to be the
+ * ones from smp.c, else they are some local flavors.
+ */
+
+/*
+ * These functions are commonly macros, but in the interests of
+ * VM vs. native implementation and code size, we simply declare
+ * the function prototypes here.
+ */
+extern void tlb_flush_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tlb_one(unsigned long);
+
+/*
+ * "This is called in munmap when we have freed up some page-table pages.
+ * We don't need to do anything here..."
+ *
+ * The VM kernel doesn't walk page tables, and they are passed to the VMM
+ * by logical address. There doesn't seem to be any possibility that they
+ * could be referenced by the VM kernel based on a stale mapping, since
+ * they would only be located by consulting the mm structure, and they
+ * will have been purged from that structure by the munmap. Seems like
+ * a noop on HVM as well.
+ */
+#define flush_tlb_pgtables(mm, start, end)
+
+#endif
diff --git a/arch/hexagon/include/asm/traps.h b/arch/hexagon/include/asm/traps.h
new file mode 100644
index 000000000000..6a407f6e5e24
--- /dev/null
+++ b/arch/hexagon/include/asm/traps.h
@@ -0,0 +1,29 @@
+/*
+ * Trap support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_TRAPS_H
+#define _ASM_HEXAGON_TRAPS_H
+
+#include <asm/registers.h>
+
+extern int die(const char *str, struct pt_regs *regs, long err);
+extern int die_if_kernel(char *str, struct pt_regs *regs, long err);
+
+#endif /* _ASM_HEXAGON_TRAPS_H */
diff --git a/arch/hexagon/include/asm/uaccess.h b/arch/hexagon/include/asm/uaccess.h
new file mode 100644
index 000000000000..7e706eadbf0a
--- /dev/null
+++ b/arch/hexagon/include/asm/uaccess.h
@@ -0,0 +1,116 @@
+/*
+ * User memory access support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_UACCESS_H
+#define _ASM_UACCESS_H
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+
+/*
+ * access_ok: - Checks if a user space pointer is valid
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that
+ * %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
+ * to write to a block, it is always safe to read from it.
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only. This function may sleep.
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns true (nonzero) if the memory block *may* be valid, false (zero)
+ * if it is definitely invalid.
+ *
+ * User address space in Hexagon, like x86, goes to 0xbfffffff, so the
+ * simple MSB-based tests used by MIPS won't work. Some further
+ * optimization is probably possible here, but for now, keep it
+ * reasonably simple and not *too* slow. After all, we've got the
+ * MMU for backup.
+ */
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+#define __access_ok(addr, size) \
+ ((get_fs().seg == KERNEL_DS.seg) || \
+ (((unsigned long)addr < get_fs().seg) && \
+ (unsigned long)size < (get_fs().seg - (unsigned long)addr)))
+
+/*
+ * When a kernel-mode page fault is taken, the faulting instruction
+ * address is checked against a table of exception_table_entries.
+ * Each entry is a tuple of the address of an instruction that may
+ * be authorized to fault, and the address at which execution should
+ * be resumed instead of the faulting instruction, so as to effect
+ * a workaround.
+ */
+
+/* Assembly somewhat optimized copy routines */
+unsigned long __copy_from_user_hexagon(void *to, const void __user *from,
+ unsigned long n);
+unsigned long __copy_to_user_hexagon(void __user *to, const void *from,
+ unsigned long n);
+
+#define __copy_from_user(to, from, n) __copy_from_user_hexagon(to, from, n)
+#define __copy_to_user(to, from, n) __copy_to_user_hexagon(to, from, n)
+
+/*
+ * XXX todo: some additonal performance gain is possible by
+ * implementing __copy_to/from_user_inatomic, which is much
+ * like __copy_to/from_user, but performs slightly less checking.
+ */
+
+__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count);
+#define __clear_user(a, s) __clear_user_hexagon((a), (s))
+
+#define __strncpy_from_user(dst, src, n) hexagon_strncpy_from_user(dst, src, n)
+
+/* get around the ifndef in asm-generic/uaccess.h */
+#define __strnlen_user __strnlen_user
+
+extern long __strnlen_user(const char __user *src, long n);
+
+static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
+ long n);
+
+#include <asm-generic/uaccess.h>
+
+/* Todo: an actual accelerated version of this. */
+static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
+ long n)
+{
+ long res = __strnlen_user(src, n);
+
+ /* return from strnlen can't be zero -- that would be rubbish. */
+
+ if (res > n) {
+ copy_from_user(dst, src, n);
+ return n;
+ } else {
+ copy_from_user(dst, src, res);
+ return res-1;
+ }
+}
+
+#endif
diff --git a/arch/hexagon/include/asm/unistd.h b/arch/hexagon/include/asm/unistd.h
new file mode 100644
index 000000000000..4d0ecde3665f
--- /dev/null
+++ b/arch/hexagon/include/asm/unistd.h
@@ -0,0 +1,36 @@
+/*
+ * Syscall support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#if !defined(_ASM_HEXAGON_UNISTD_H) || defined(__SYSCALL)
+#define _ASM_HEXAGON_UNISTD_H
+
+/*
+ * The kernel pulls this unistd.h in three different ways:
+ * 1. the "normal" way which gets all the __NR defines
+ * 2. with __SYSCALL defined to produce function declarations
+ * 3. with __SYSCALL defined to produce syscall table initialization
+ * See also: syscalltab.c
+ */
+
+#define sys_mmap2 sys_mmap_pgoff
+
+#include <asm-generic/unistd.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/user.h b/arch/hexagon/include/asm/user.h
new file mode 100644
index 000000000000..3a55078543d1
--- /dev/null
+++ b/arch/hexagon/include/asm/user.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef HEXAGON_ASM_USER_H
+#define HEXAGON_ASM_USER_H
+
+/*
+ * Layout for registers passed in elf core dumps to userspace.
+ *
+ * Basically a rearranged subset of "pt_regs".
+ *
+ * Interested parties: libc, gdb...
+ */
+
+struct user_regs_struct {
+ unsigned long r0;
+ unsigned long r1;
+ unsigned long r2;
+ unsigned long r3;
+ unsigned long r4;
+ unsigned long r5;
+ unsigned long r6;
+ unsigned long r7;
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long r11;
+ unsigned long r12;
+ unsigned long r13;
+ unsigned long r14;
+ unsigned long r15;
+ unsigned long r16;
+ unsigned long r17;
+ unsigned long r18;
+ unsigned long r19;
+ unsigned long r20;
+ unsigned long r21;
+ unsigned long r22;
+ unsigned long r23;
+ unsigned long r24;
+ unsigned long r25;
+ unsigned long r26;
+ unsigned long r27;
+ unsigned long r28;
+ unsigned long r29;
+ unsigned long r30;
+ unsigned long r31;
+ unsigned long sa0;
+ unsigned long lc0;
+ unsigned long sa1;
+ unsigned long lc1;
+ unsigned long m0;
+ unsigned long m1;
+ unsigned long usr;
+ unsigned long p3_0;
+ unsigned long gp;
+ unsigned long ugp;
+ unsigned long pc;
+ unsigned long cause;
+ unsigned long badva;
+ unsigned long pad1; /* pad out to 48 words total */
+ unsigned long pad2; /* pad out to 48 words total */
+ unsigned long pad3; /* pad out to 48 words total */
+};
+
+#endif
diff --git a/arch/hexagon/include/asm/vdso.h b/arch/hexagon/include/asm/vdso.h
new file mode 100644
index 000000000000..2d95cbba3572
--- /dev/null
+++ b/arch/hexagon/include/asm/vdso.h
@@ -0,0 +1,30 @@
+/*
+ * vDSO implementation for Hexagon
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#include <linux/types.h>
+
+struct hexagon_vdso {
+ u32 rt_signal_trampoline[2];
+};
+
+#endif /* __ASM_VDSO_H */
diff --git a/arch/hexagon/include/asm/vm_fault.h b/arch/hexagon/include/asm/vm_fault.h
new file mode 100644
index 000000000000..cacda36ef5d5
--- /dev/null
+++ b/arch/hexagon/include/asm/vm_fault.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_VM_FAULT_H
+#define _ASM_HEXAGON_VM_FAULT_H
+
+extern void execute_protection_fault(struct pt_regs *);
+extern void write_protection_fault(struct pt_regs *);
+extern void read_protection_fault(struct pt_regs *);
+
+#endif
diff --git a/arch/hexagon/include/asm/vm_mmu.h b/arch/hexagon/include/asm/vm_mmu.h
new file mode 100644
index 000000000000..580462de5cca
--- /dev/null
+++ b/arch/hexagon/include/asm/vm_mmu.h
@@ -0,0 +1,111 @@
+/*
+ * Hexagon VM page table entry definitions
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_VM_MMU_H
+#define _ASM_VM_MMU_H
+
+/*
+ * Shift, mask, and other constants for the Hexagon Virtual Machine
+ * page tables.
+ *
+ * Virtual machine MMU allows first-level entries to either be
+ * single-level lookup PTEs for very large pages, or PDEs pointing
+ * to second-level PTEs for smaller pages. If PTE is single-level,
+ * the least significant bits cannot be used as software bits to encode
+ * virtual memory subsystem information about the page, and that state
+ * must be maintained in some parallel data structure.
+ */
+
+/* S or Page Size field in PDE */
+#define __HVM_PDE_S (0x7 << 0)
+#define __HVM_PDE_S_4KB 0
+#define __HVM_PDE_S_16KB 1
+#define __HVM_PDE_S_64KB 2
+#define __HVM_PDE_S_256KB 3
+#define __HVM_PDE_S_1MB 4
+#define __HVM_PDE_S_4MB 5
+#define __HVM_PDE_S_16MB 6
+#define __HVM_PDE_S_INVALID 7
+
+/* Masks for L2 page table pointer, as function of page size */
+#define __HVM_PDE_PTMASK_4KB 0xfffff000
+#define __HVM_PDE_PTMASK_16KB 0xfffffc00
+#define __HVM_PDE_PTMASK_64KB 0xffffff00
+#define __HVM_PDE_PTMASK_256KB 0xffffffc0
+#define __HVM_PDE_PTMASK_1MB 0xfffffff0
+
+/*
+ * Virtual Machine PTE Bits/Fields
+ */
+#define __HVM_PTE_T (1<<4)
+#define __HVM_PTE_U (1<<5)
+#define __HVM_PTE_C (0x7<<6)
+#define __HVM_PTE_CVAL(pte) (((pte) & __HVM_PTE_C) >> 6)
+#define __HVM_PTE_R (1<<9)
+#define __HVM_PTE_W (1<<10)
+#define __HVM_PTE_X (1<<11)
+
+/*
+ * Cache Attributes, to be shifted as necessary for virtual/physical PTEs
+ */
+
+#define __HEXAGON_C_WB 0x0 /* Write-back, no L2 */
+#define __HEXAGON_C_WT 0x1 /* Write-through, no L2 */
+#define __HEXAGON_C_DEV 0x4 /* Device register space */
+#define __HEXAGON_C_WT_L2 0x5 /* Write-through, with L2 */
+/* this really should be #if CONFIG_HEXAGON_ARCH = 2 but that's not defined */
+#if defined(CONFIG_HEXAGON_COMET) || defined(CONFIG_QDSP6_ST1)
+#define __HEXAGON_C_UNC __HEXAGON_C_DEV
+#else
+#define __HEXAGON_C_UNC 0x6 /* Uncached memory */
+#endif
+#define __HEXAGON_C_WB_L2 0x7 /* Write-back, with L2 */
+
+/*
+ * This can be overriden, but we're defaulting to the most aggressive
+ * cache policy, the better to find bugs sooner.
+ */
+
+#define CACHE_DEFAULT __HEXAGON_C_WB_L2
+
+/* Masks for physical page address, as a function of page size */
+
+#define __HVM_PTE_PGMASK_4KB 0xfffff000
+#define __HVM_PTE_PGMASK_16KB 0xffffc000
+#define __HVM_PTE_PGMASK_64KB 0xffff0000
+#define __HVM_PTE_PGMASK_256KB 0xfffc0000
+#define __HVM_PTE_PGMASK_1MB 0xfff00000
+
+/* Masks for single-level large page lookups */
+
+#define __HVM_PTE_PGMASK_4MB 0xffc00000
+#define __HVM_PTE_PGMASK_16MB 0xff000000
+
+/*
+ * "Big kernel page mappings" (see vm_init_segtable.S)
+ * are currently 16MB
+ */
+
+#define BIG_KERNEL_PAGE_SHIFT 24
+#define BIG_KERNEL_PAGE_SIZE (1 << BIG_KERNEL_PAGE_SHIFT)
+
+
+
+#endif /* _ASM_VM_MMU_H */
diff --git a/arch/hexagon/kernel/Makefile b/arch/hexagon/kernel/Makefile
new file mode 100644
index 000000000000..3689f3754d09
--- /dev/null
+++ b/arch/hexagon/kernel/Makefile
@@ -0,0 +1,18 @@
+extra-y := head.o vmlinux.lds init_task.o
+
+obj-$(CONFIG_SMP) += smp.o topology.o
+
+obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o
+obj-y += process.o syscall.o trampoline.o reset.o ptrace.o
+obj-y += vdso.o
+
+obj-$(CONFIG_KGDB) += kgdb.o
+obj-$(CONFIG_MODULES) += module.o hexagon_ksyms.o
+
+# Modules required to work with the Hexagon Virtual Machine
+obj-y += vm_entry.o vm_events.o vm_switch.o vm_ops.o vm_init_segtable.o
+obj-y += vm_vectors.o
+
+obj-$(CONFIG_HAS_DMA) += dma.o
+
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/arch/hexagon/kernel/asm-offsets.c b/arch/hexagon/kernel/asm-offsets.c
new file mode 100644
index 000000000000..89ffa514611f
--- /dev/null
+++ b/arch/hexagon/kernel/asm-offsets.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/compat.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/kbuild.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+
+/* This file is used to produce asm/linkerscript constants from header
+ files typically used in c. Specifically, it generates asm-offsets.h */
+
+int main(void)
+{
+ COMMENT("This is a comment.");
+ /* might get these from somewhere else. */
+ DEFINE(_PAGE_SIZE, PAGE_SIZE);
+ DEFINE(_PAGE_SHIFT, PAGE_SHIFT);
+ BLANK();
+
+ COMMENT("Hexagon pt_regs definitions");
+ OFFSET(_PT_SYSCALL_NR, pt_regs, syscall_nr);
+ OFFSET(_PT_UGPGP, pt_regs, ugpgp);
+ OFFSET(_PT_R3130, pt_regs, r3130);
+ OFFSET(_PT_R2928, pt_regs, r2928);
+ OFFSET(_PT_R2726, pt_regs, r2726);
+ OFFSET(_PT_R2524, pt_regs, r2524);
+ OFFSET(_PT_R2322, pt_regs, r2322);
+ OFFSET(_PT_R2120, pt_regs, r2120);
+ OFFSET(_PT_R1918, pt_regs, r1918);
+ OFFSET(_PT_R1716, pt_regs, r1716);
+ OFFSET(_PT_R1514, pt_regs, r1514);
+ OFFSET(_PT_R1312, pt_regs, r1312);
+ OFFSET(_PT_R1110, pt_regs, r1110);
+ OFFSET(_PT_R0908, pt_regs, r0908);
+ OFFSET(_PT_R0706, pt_regs, r0706);
+ OFFSET(_PT_R0504, pt_regs, r0504);
+ OFFSET(_PT_R0302, pt_regs, r0302);
+ OFFSET(_PT_R0100, pt_regs, r0100);
+ OFFSET(_PT_LC0SA0, pt_regs, lc0sa0);
+ OFFSET(_PT_LC1SA1, pt_regs, lc1sa1);
+ OFFSET(_PT_M1M0, pt_regs, m1m0);
+ OFFSET(_PT_PREDSUSR, pt_regs, predsusr);
+ OFFSET(_PT_EVREC, pt_regs, hvmer);
+ OFFSET(_PT_ER_VMEL, pt_regs, hvmer.vmel);
+ OFFSET(_PT_ER_VMEST, pt_regs, hvmer.vmest);
+ OFFSET(_PT_ER_VMPSP, pt_regs, hvmer.vmpsp);
+ OFFSET(_PT_ER_VMBADVA, pt_regs, hvmer.vmbadva);
+ DEFINE(_PT_REGS_SIZE, sizeof(struct pt_regs));
+ BLANK();
+
+ COMMENT("Hexagon thread_info definitions");
+ OFFSET(_THREAD_INFO_FLAGS, thread_info, flags);
+ OFFSET(_THREAD_INFO_PT_REGS, thread_info, regs);
+ OFFSET(_THREAD_INFO_SP, thread_info, sp);
+ DEFINE(_THREAD_SIZE, THREAD_SIZE);
+ BLANK();
+
+ COMMENT("Hexagon hexagon_switch_stack definitions");
+ OFFSET(_SWITCH_R1716, hexagon_switch_stack, r1716);
+ OFFSET(_SWITCH_R1918, hexagon_switch_stack, r1918);
+ OFFSET(_SWITCH_R2120, hexagon_switch_stack, r2120);
+ OFFSET(_SWITCH_R2322, hexagon_switch_stack, r2322);
+
+ OFFSET(_SWITCH_R2524, hexagon_switch_stack, r2524);
+ OFFSET(_SWITCH_R2726, hexagon_switch_stack, r2726);
+ OFFSET(_SWITCH_FP, hexagon_switch_stack, fp);
+ OFFSET(_SWITCH_LR, hexagon_switch_stack, lr);
+ DEFINE(_SWITCH_STACK_SIZE, sizeof(struct hexagon_switch_stack));
+ BLANK();
+
+ COMMENT("Hexagon task_struct definitions");
+ OFFSET(_TASK_THREAD_INFO, task_struct, stack);
+ OFFSET(_TASK_STRUCT_THREAD, task_struct, thread);
+
+ COMMENT("Hexagon thread_struct definitions");
+ OFFSET(_THREAD_STRUCT_SWITCH_SP, thread_struct, switch_sp);
+
+ return 0;
+}
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
new file mode 100644
index 000000000000..e711ace62fdf
--- /dev/null
+++ b/arch/hexagon/kernel/dma.c
@@ -0,0 +1,220 @@
+/*
+ * DMA implementation for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/bootmem.h>
+#include <linux/genalloc.h>
+#include <asm/dma-mapping.h>
+
+struct dma_map_ops *dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
+int bad_dma_address; /* globals are automatically initialized to zero */
+
+int dma_supported(struct device *dev, u64 mask)
+{
+ if (mask == DMA_BIT_MASK(32))
+ return 1;
+ else
+ return 0;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 mask)
+{
+ if (!dev->dma_mask || !dma_supported(dev, mask))
+ return -EIO;
+
+ *dev->dma_mask = mask;
+
+ return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
+static struct gen_pool *coherent_pool;
+
+
+/* Allocates from a pool of uncached memory that was reserved at boot time */
+
+void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_addr, gfp_t flag)
+{
+ void *ret;
+
+ if (coherent_pool == NULL) {
+ coherent_pool = gen_pool_create(PAGE_SHIFT, -1);
+
+ if (coherent_pool == NULL)
+ panic("Can't create %s() memory pool!", __func__);
+ else
+ gen_pool_add(coherent_pool,
+ (PAGE_OFFSET + (max_low_pfn << PAGE_SHIFT)),
+ hexagon_coherent_pool_size, -1);
+ }
+
+ ret = (void *) gen_pool_alloc(coherent_pool, size);
+
+ if (ret) {
+ memset(ret, 0, size);
+ *dma_addr = (dma_addr_t) (ret - PAGE_OFFSET);
+ } else
+ *dma_addr = ~0;
+
+ return ret;
+}
+
+static void hexagon_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_addr)
+{
+ gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
+}
+
+static int check_addr(const char *name, struct device *hwdev,
+ dma_addr_t bus, size_t size)
+{
+ if (hwdev && hwdev->dma_mask && !dma_capable(hwdev, bus, size)) {
+ if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
+ printk(KERN_ERR
+ "%s: overflow %Lx+%zu of device mask %Lx\n",
+ name, (long long)bus, size,
+ (long long)*hwdev->dma_mask);
+ return 0;
+ }
+ return 1;
+}
+
+static int hexagon_map_sg(struct device *hwdev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct scatterlist *s;
+ int i;
+
+ WARN_ON(nents == 0 || sg[0].length == 0);
+
+ for_each_sg(sg, s, nents, i) {
+ s->dma_address = sg_phys(s);
+ if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
+ return 0;
+
+ s->dma_length = s->length;
+
+ flush_dcache_range(PAGE_OFFSET + s->dma_address,
+ PAGE_OFFSET + s->dma_address + s->length);
+ }
+
+ return nents;
+}
+
+/*
+ * address is virtual
+ */
+static inline void dma_sync(void *addr, size_t size,
+ enum dma_data_direction dir)
+{
+ switch (dir) {
+ case DMA_TO_DEVICE:
+ hexagon_clean_dcache_range((unsigned long) addr,
+ (unsigned long) addr + size);
+ break;
+ case DMA_FROM_DEVICE:
+ hexagon_inv_dcache_range((unsigned long) addr,
+ (unsigned long) addr + size);
+ break;
+ case DMA_BIDIRECTIONAL:
+ flush_dcache_range((unsigned long) addr,
+ (unsigned long) addr + size);
+ break;
+ default:
+ BUG();
+ }
+}
+
+static inline void *dma_addr_to_virt(dma_addr_t dma_addr)
+{
+ return phys_to_virt((unsigned long) dma_addr);
+}
+
+/**
+ * hexagon_map_page() - maps an address for device DMA
+ * @dev: pointer to DMA device
+ * @page: pointer to page struct of DMA memory
+ * @offset: offset within page
+ * @size: size of memory to map
+ * @dir: transfer direction
+ * @attrs: pointer to DMA attrs (not used)
+ *
+ * Called to map a memory address to a DMA address prior
+ * to accesses to/from device.
+ *
+ * We don't particularly have many hoops to jump through
+ * so far. Straight translation between phys and virtual.
+ *
+ * DMA is not cache coherent so sync is necessary; this
+ * seems to be a convenient place to do it.
+ *
+ */
+static dma_addr_t hexagon_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ dma_addr_t bus = page_to_phys(page) + offset;
+ WARN_ON(size == 0);
+
+ if (!check_addr("map_single", dev, bus, size))
+ return bad_dma_address;
+
+ dma_sync(dma_addr_to_virt(bus), size, dir);
+
+ return bus;
+}
+
+static void hexagon_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_sync(dma_addr_to_virt(dma_handle), size, dir);
+}
+
+static void hexagon_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_sync(dma_addr_to_virt(dma_handle), size, dir);
+}
+
+struct dma_map_ops hexagon_dma_ops = {
+ .alloc_coherent = hexagon_dma_alloc_coherent,
+ .free_coherent = hexagon_free_coherent,
+ .map_sg = hexagon_map_sg,
+ .map_page = hexagon_map_page,
+ .sync_single_for_cpu = hexagon_sync_single_for_cpu,
+ .sync_single_for_device = hexagon_sync_single_for_device,
+ .is_phys = 1,
+};
+
+void __init hexagon_dma_init(void)
+{
+ if (dma_ops)
+ return;
+
+ dma_ops = &hexagon_dma_ops;
+}
diff --git a/arch/hexagon/kernel/head.S b/arch/hexagon/kernel/head.S
new file mode 100644
index 000000000000..8e6b819125a3
--- /dev/null
+++ b/arch/hexagon/kernel/head.S
@@ -0,0 +1,162 @@
+/*
+ * Early kernel startup code for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/mem-layout.h>
+#include <asm/vm_mmu.h>
+#include <asm/page.h>
+
+ __INIT
+ENTRY(stext)
+ /*
+ * VMM will already have set up true vector page, MMU, etc.
+ * To set up initial kernel identity map, we have to pass
+ * the VMM a pointer to some canonical page tables. In
+ * this implementation, we're assuming that we've got
+ * them precompiled. Generate value in R24, as we'll need
+ * it again shortly.
+ */
+ r24.L = #LO(swapper_pg_dir)
+ r24.H = #HI(swapper_pg_dir)
+
+ /*
+ * Symbol is kernel segment address, but we need
+ * the logical/physical address.
+ */
+ r24 = asl(r24, #2)
+ r24 = lsr(r24, #2)
+
+ r0 = r24
+
+ /*
+ * Initialize a 16MB PTE to make the virtual and physical
+ * addresses where the kernel was loaded be identical.
+ */
+#define PTE_BITS ( __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+ | __HEXAGON_C_WB_L2 << 6 \
+ | __HVM_PDE_S_4MB)
+
+ r1 = pc
+ r2.H = #0xffc0
+ r2.L = #0x0000
+ r1 = and(r1,r2) /* round PC to 4MB boundary */
+ r2 = lsr(r1, #22) /* 4MB page number */
+ r2 = asl(r2, #2) /* times sizeof(PTE) (4bytes) */
+ r0 = add(r0,r2) /* r0 = address of correct PTE */
+ r2 = #PTE_BITS
+ r1 = add(r1,r2) /* r1 = 4MB PTE for the first entry */
+ r2.h = #0x0040
+ r2.l = #0x0000 /* 4MB */
+ memw(r0 ++ #4) = r1
+ r1 = add(r1, r2)
+ memw(r0 ++ #4) = r1
+
+ r0 = r24
+
+ /*
+ * The subroutine wrapper around the virtual instruction touches
+ * no memory, so we should be able to use it even here.
+ */
+ call __vmnewmap;
+
+ /* Jump into virtual address range. */
+
+ r31.h = #hi(__head_s_vaddr_target)
+ r31.l = #lo(__head_s_vaddr_target)
+ jumpr r31
+
+ /* Insert trippy space effects. */
+
+__head_s_vaddr_target:
+ /*
+ * Tear down VA=PA translation now that we are running
+ * in the desgnated kernel segments.
+ */
+ r0 = #__HVM_PDE_S_INVALID
+ r1 = r24
+ loop0(1f,#0x100)
+1:
+ {
+ memw(R1 ++ #4) = R0
+ }:endloop0
+
+ r0 = r24
+ call __vmnewmap
+
+ /* Go ahead and install the trap0 return so angel calls work */
+ r0.h = #hi(_K_provisional_vec)
+ r0.l = #lo(_K_provisional_vec)
+ call __vmsetvec
+
+ /*
+ * OK, at this point we should start to be much more careful,
+ * we're going to enter C code and start touching memory
+ * in all sorts of places.
+ * This means:
+ * SGP needs to be OK
+ * Need to lock shared resources
+ * A bunch of other things that will cause
+ * all kinds of painful bugs
+ */
+
+ /*
+ * Stack pointer should be pointed at the init task's
+ * thread stack, which should have been declared in arch/init_task.c.
+ * So uhhhhh...
+ * It's accessible via the init_thread_union, which is a union
+ * of a thread_info struct and a stack; of course, the top
+ * of the stack is not for you. The end of the stack
+ * is simply init_thread_union + THREAD_SIZE.
+ */
+
+ {r29.H = #HI(init_thread_union); r0.H = #HI(_THREAD_SIZE); }
+ {r29.L = #LO(init_thread_union); r0.L = #LO(_THREAD_SIZE); }
+
+ /* initialize the register used to point to current_thread_info */
+ /* Fixme: THREADINFO_REG can't be R2 because of that memset thing. */
+ {r29 = add(r29,r0); THREADINFO_REG = r29; }
+
+ /* Hack: zero bss; */
+ { r0.L = #LO(__bss_start); r1 = #0; r2.l = #LO(__bss_stop); }
+ { r0.H = #HI(__bss_start); r2.h = #HI(__bss_stop); }
+
+ r2 = sub(r2,r0);
+ call memset;
+
+ /* Time to make the doughnuts. */
+ call start_kernel
+
+ /*
+ * Should not reach here.
+ */
+1:
+ jump 1b
+
+.p2align PAGE_SHIFT
+ENTRY(external_cmdline_buffer)
+ .fill _PAGE_SIZE,1,0
+
+.data
+.p2align PAGE_SHIFT
+ENTRY(empty_zero_page)
+ .fill _PAGE_SIZE,1,0
diff --git a/arch/hexagon/kernel/hexagon_ksyms.c b/arch/hexagon/kernel/hexagon_ksyms.c
new file mode 100644
index 000000000000..7f1892471805
--- /dev/null
+++ b/arch/hexagon/kernel/hexagon_ksyms.c
@@ -0,0 +1,40 @@
+/*
+ * Export of symbols defined in assembly files and/or libgcc.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/hexagon_vm.h>
+#include <asm/uaccess.h>
+
+EXPORT_SYMBOL(__copy_from_user_hexagon);
+EXPORT_SYMBOL(__copy_to_user_hexagon);
+EXPORT_SYMBOL(__vmgetie);
+EXPORT_SYMBOL(__vmsetie);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+
+#define DECLARE_EXPORT(name) \
+ extern void name(void); EXPORT_SYMBOL(name)
+
+/* Symbols found in libgcc that assorted kernel modules need */
+DECLARE_EXPORT(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes);
+
+DECLARE_EXPORT(__hexagon_divsi3);
+DECLARE_EXPORT(__hexagon_modsi3);
+DECLARE_EXPORT(__hexagon_udivsi3);
+DECLARE_EXPORT(__hexagon_umodsi3);
diff --git a/arch/hexagon/kernel/init_task.c b/arch/hexagon/kernel/init_task.c
new file mode 100644
index 000000000000..73283d3edf09
--- /dev/null
+++ b/arch/hexagon/kernel/init_task.c
@@ -0,0 +1,54 @@
+/*
+ * Init task definition
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+#include <asm/thread_info.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by making sure
+ * the linker maps this in the .text segment right after head.S,
+ * and making head.S ensure the proper alignment.
+ */
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"),
+ __aligned__(THREAD_SIZE))) = {
+ INIT_THREAD_INFO(init_task)
+ };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
diff --git a/arch/hexagon/kernel/irq_cpu.c b/arch/hexagon/kernel/irq_cpu.c
new file mode 100644
index 000000000000..d4416a1a431e
--- /dev/null
+++ b/arch/hexagon/kernel/irq_cpu.c
@@ -0,0 +1,90 @@
+/*
+ * First-level interrupt controller model for Hexagon.
+ *
+ * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/hexagon_vm.h>
+
+static void mask_irq(struct irq_data *data)
+{
+ __vmintop_locdis((long) data->irq);
+}
+
+static void mask_irq_num(unsigned int irq)
+{
+ __vmintop_locdis((long) irq);
+}
+
+static void unmask_irq(struct irq_data *data)
+{
+ __vmintop_locen((long) data->irq);
+}
+
+/* This is actually all we need for handle_fasteoi_irq */
+static void eoi_irq(struct irq_data *data)
+{
+ __vmintop_globen((long) data->irq);
+}
+
+/* Power mamangement wake call. We don't need this, however,
+ * if this is absent, then an -ENXIO error is returned to the
+ * msm_serial driver, and it fails to correctly initialize.
+ * This is a bug in the msm_serial driver, but, for now, we
+ * work around it here, by providing this bogus handler.
+ * XXX FIXME!!! remove this when msm_serial is fixed.
+ */
+static int set_wake(struct irq_data *data, unsigned int on)
+{
+ return 0;
+}
+
+static struct irq_chip hexagon_irq_chip = {
+ .name = "HEXAGON",
+ .irq_mask = mask_irq,
+ .irq_unmask = unmask_irq,
+ .irq_set_wake = set_wake,
+ .irq_eoi = eoi_irq
+};
+
+/**
+ * The hexagon core comes with a first-level interrupt controller
+ * with 32 total possible interrupts. When the core is embedded
+ * into different systems/platforms, it is typically wrapped by
+ * macro cells that provide one or more second-level interrupt
+ * controllers that are cascaded into one or more of the first-level
+ * interrupts handled here. The precise wiring of these other
+ * irqs varies from platform to platform, and are set up & configured
+ * in the platform-specific files.
+ *
+ * The first-level interrupt controller is wrapped by the VM, which
+ * virtualizes the interrupt controller for us. It provides a very
+ * simple, fast & efficient API, and so the fasteoi handler is
+ * appropriate for this case.
+ */
+void __init init_IRQ(void)
+{
+ int irq;
+
+ for (irq = 0; irq < HEXAGON_CPUINTS; irq++) {
+ mask_irq_num(irq);
+ irq_set_chip_and_handler(irq, &hexagon_irq_chip,
+ handle_fasteoi_irq);
+ }
+}
diff --git a/arch/hexagon/kernel/kgdb.c b/arch/hexagon/kernel/kgdb.c
new file mode 100644
index 000000000000..fe4aa1bcca50
--- /dev/null
+++ b/arch/hexagon/kernel/kgdb.c
@@ -0,0 +1,254 @@
+/*
+ * arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/kdebug.h>
+#include <linux/kgdb.h>
+
+/* All registers are 4 bytes, for now */
+#define GDB_SIZEOF_REG 4
+
+/* The register names are used during printing of the regs;
+ * Keep these at three letters to pretty-print. */
+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
+ { " r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, r00)},
+ { " r1", GDB_SIZEOF_REG, offsetof(struct pt_regs, r01)},
+ { " r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, r02)},
+ { " r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, r03)},
+ { " r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, r04)},
+ { " r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, r05)},
+ { " r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, r06)},
+ { " r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, r07)},
+ { " r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, r08)},
+ { " r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, r09)},
+ { "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, r10)},
+ { "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, r11)},
+ { "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, r12)},
+ { "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, r13)},
+ { "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, r14)},
+ { "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, r15)},
+ { "r16", GDB_SIZEOF_REG, offsetof(struct pt_regs, r16)},
+ { "r17", GDB_SIZEOF_REG, offsetof(struct pt_regs, r17)},
+ { "r18", GDB_SIZEOF_REG, offsetof(struct pt_regs, r18)},
+ { "r19", GDB_SIZEOF_REG, offsetof(struct pt_regs, r19)},
+ { "r20", GDB_SIZEOF_REG, offsetof(struct pt_regs, r20)},
+ { "r21", GDB_SIZEOF_REG, offsetof(struct pt_regs, r21)},
+ { "r22", GDB_SIZEOF_REG, offsetof(struct pt_regs, r22)},
+ { "r23", GDB_SIZEOF_REG, offsetof(struct pt_regs, r23)},
+ { "r24", GDB_SIZEOF_REG, offsetof(struct pt_regs, r24)},
+ { "r25", GDB_SIZEOF_REG, offsetof(struct pt_regs, r25)},
+ { "r26", GDB_SIZEOF_REG, offsetof(struct pt_regs, r26)},
+ { "r27", GDB_SIZEOF_REG, offsetof(struct pt_regs, r27)},
+ { "r28", GDB_SIZEOF_REG, offsetof(struct pt_regs, r28)},
+ { "r29", GDB_SIZEOF_REG, offsetof(struct pt_regs, r29)},
+ { "r30", GDB_SIZEOF_REG, offsetof(struct pt_regs, r30)},
+ { "r31", GDB_SIZEOF_REG, offsetof(struct pt_regs, r31)},
+
+ { "usr", GDB_SIZEOF_REG, offsetof(struct pt_regs, usr)},
+ { "preds", GDB_SIZEOF_REG, offsetof(struct pt_regs, preds)},
+ { " m0", GDB_SIZEOF_REG, offsetof(struct pt_regs, m0)},
+ { " m1", GDB_SIZEOF_REG, offsetof(struct pt_regs, m1)},
+ { "sa0", GDB_SIZEOF_REG, offsetof(struct pt_regs, sa0)},
+ { "sa1", GDB_SIZEOF_REG, offsetof(struct pt_regs, sa1)},
+ { "lc0", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc0)},
+ { "lc1", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc1)},
+ { " gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp)},
+ { "ugp", GDB_SIZEOF_REG, offsetof(struct pt_regs, ugp)},
+ { "psp", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmpsp)},
+ { "elr", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmel)},
+ { "est", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmest)},
+ { "badva", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmbadva)},
+ { "restart_r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, restart_r0)},
+ { "syscall_nr", GDB_SIZEOF_REG, offsetof(struct pt_regs, syscall_nr)},
+};
+
+struct kgdb_arch arch_kgdb_ops = {
+ /* trap0(#0xDB) 0x0cdb0054 */
+ .gdb_bpt_instr = {0x54, 0x00, 0xdb, 0x0c},
+};
+
+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
+{
+ if (regno >= DBG_MAX_REG_NUM || regno < 0)
+ return NULL;
+
+ *((unsigned long *) mem) = *((unsigned long *) ((void *)regs +
+ dbg_reg_def[regno].offset));
+
+ return dbg_reg_def[regno].name;
+}
+
+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
+{
+ if (regno >= DBG_MAX_REG_NUM || regno < 0)
+ return -EINVAL;
+
+ *((unsigned long *) ((void *)regs + dbg_reg_def[regno].offset)) =
+ *((unsigned long *) mem);
+
+ return 0;
+}
+
+void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
+{
+ instruction_pointer(regs) = pc;
+}
+
+#ifdef CONFIG_SMP
+
+/**
+ * kgdb_roundup_cpus - Get other CPUs into a holding pattern
+ * @flags: Current IRQ state
+ *
+ * On SMP systems, we need to get the attention of the other CPUs
+ * and get them be in a known state. This should do what is needed
+ * to get the other CPUs to call kgdb_wait(). Note that on some arches,
+ * the NMI approach is not used for rounding up all the CPUs. For example,
+ * in case of MIPS, smp_call_function() is used to roundup CPUs. In
+ * this case, we have to make sure that interrupts are enabled before
+ * calling smp_call_function(). The argument to this function is
+ * the flags that will be used when restoring the interrupts. There is
+ * local_irq_save() call before kgdb_roundup_cpus().
+ *
+ * On non-SMP systems, this is not called.
+ */
+
+static void hexagon_kgdb_nmi_hook(void *ignored)
+{
+ kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+ local_irq_enable();
+ smp_call_function(hexagon_kgdb_nmi_hook, NULL, 0);
+ local_irq_disable();
+}
+#endif
+
+
+/* Not yet working */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
+ struct task_struct *task)
+{
+ struct pt_regs *thread_regs;
+
+ if (task == NULL)
+ return;
+
+ /* Initialize to zero */
+ memset(gdb_regs, 0, NUMREGBYTES);
+
+ /* Otherwise, we have only some registers from switch_to() */
+ thread_regs = task_pt_regs(task);
+ gdb_regs[0] = thread_regs->r00;
+}
+
+/**
+ * kgdb_arch_handle_exception - Handle architecture specific GDB packets.
+ * @vector: The error vector of the exception that happened.
+ * @signo: The signal number of the exception that happened.
+ * @err_code: The error code of the exception that happened.
+ * @remcom_in_buffer: The buffer of the packet we have read.
+ * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into.
+ * @regs: The &struct pt_regs of the current process.
+ *
+ * This function MUST handle the 'c' and 's' command packets,
+ * as well packets to set / remove a hardware breakpoint, if used.
+ * If there are additional packets which the hardware needs to handle,
+ * they are handled here. The code should return -1 if it wants to
+ * process more packets, and a %0 or %1 if it wants to exit from the
+ * kgdb callback.
+ *
+ * Not yet working.
+ */
+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+ char *remcom_in_buffer, char *remcom_out_buffer,
+ struct pt_regs *linux_regs)
+{
+ switch (remcom_in_buffer[0]) {
+ case 's':
+ case 'c':
+ return 0;
+ }
+ /* Stay in the debugger. */
+ return -1;
+}
+
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+ /* cpu roundup */
+ if (atomic_read(&kgdb_active) != -1) {
+ kgdb_nmicallback(smp_processor_id(), args->regs);
+ return NOTIFY_STOP;
+ }
+
+ if (user_mode(args->regs))
+ return NOTIFY_DONE;
+
+ if (kgdb_handle_exception(args->trapnr & 0xff, args->signr, args->err,
+ args->regs))
+ return NOTIFY_DONE;
+
+ return NOTIFY_STOP;
+}
+
+static int
+kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
+{
+ unsigned long flags;
+ int ret;
+
+ local_irq_save(flags);
+ ret = __kgdb_notify(ptr, cmd);
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+static struct notifier_block kgdb_notifier = {
+ .notifier_call = kgdb_notify,
+
+ /*
+ * Lowest-prio notifier priority, we want to be notified last:
+ */
+ .priority = -INT_MAX,
+};
+
+/**
+ * kgdb_arch_init - Perform any architecture specific initalization.
+ *
+ * This function will handle the initalization of any architecture
+ * specific callbacks.
+ */
+int kgdb_arch_init(void)
+{
+ return register_die_notifier(&kgdb_notifier);
+}
+
+/**
+ * kgdb_arch_exit - Perform any architecture specific uninitalization.
+ *
+ * This function will handle the uninitalization of any architecture
+ * specific callbacks, for dynamic registration and unregistration.
+ */
+void kgdb_arch_exit(void)
+{
+ unregister_die_notifier(&kgdb_notifier);
+}
diff --git a/arch/hexagon/kernel/module.c b/arch/hexagon/kernel/module.c
new file mode 100644
index 000000000000..61a76bae3668
--- /dev/null
+++ b/arch/hexagon/kernel/module.c
@@ -0,0 +1,162 @@
+/*
+ * Kernel module loader for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/module.h>
+#include <linux/elf.h>
+#include <linux/module.h>
+#include <linux/moduleloader.h>
+#include <linux/vmalloc.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , ...)
+#endif
+
+/*
+ * module_frob_arch_sections - tweak got/plt sections.
+ * @hdr - pointer to elf header
+ * @sechdrs - pointer to elf load section headers
+ * @secstrings - symbol names
+ * @mod - pointer to module
+ */
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+ char *secstrings,
+ struct module *mod)
+{
+ unsigned int i;
+ int found = 0;
+
+ /* Look for .plt and/or .got.plt and/or .init.plt sections */
+ for (i = 0; i < hdr->e_shnum; i++) {
+ DEBUGP("Section %d is %s\n", i,
+ secstrings + sechdrs[i].sh_name);
+ if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
+ found = i+1;
+ if (strcmp(secstrings + sechdrs[i].sh_name, ".got.plt") == 0)
+ found = i+1;
+ if (strcmp(secstrings + sechdrs[i].sh_name, ".rela.plt") == 0)
+ found = i+1;
+ }
+
+ /* At this time, we don't support modules comiled with -shared */
+ if (found) {
+ printk(KERN_WARNING
+ "Module '%s' contains unexpected .plt/.got sections.\n",
+ mod->name);
+ /* return -ENOEXEC; */
+ }
+
+ return 0;
+}
+
+/*
+ * apply_relocate_add - perform rela relocations.
+ * @sechdrs - pointer to section headers
+ * @strtab - some sort of start address?
+ * @symindex - symbol index offset or something?
+ * @relsec - address to relocate to?
+ * @module - pointer to module
+ *
+ * Perform rela relocations.
+ */
+int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relsec,
+ struct module *module)
+{
+ unsigned int i;
+ Elf32_Sym *sym;
+ uint32_t *location;
+ uint32_t value;
+ unsigned int nrelocs = sechdrs[relsec].sh_size / sizeof(Elf32_Rela);
+ Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Word sym_info = sechdrs[relsec].sh_info;
+ Elf32_Sym *sym_base = (Elf32_Sym *) sechdrs[symindex].sh_addr;
+ void *loc_base = (void *) sechdrs[sym_info].sh_addr;
+
+ DEBUGP("Applying relocations in section %u to section %u base=%p\n",
+ relsec, sym_info, loc_base);
+
+ for (i = 0; i < nrelocs; i++) {
+
+ /* Symbol to relocate */
+ sym = sym_base + ELF32_R_SYM(rela[i].r_info);
+
+ /* Where to make the change */
+ location = loc_base + rela[i].r_offset;
+
+ /* `Everything is relative'. */
+ value = sym->st_value + rela[i].r_addend;
+
+ DEBUGP("%d: value=%08x loc=%p reloc=%d symbol=%s\n",
+ i, value, location, ELF32_R_TYPE(rela[i].r_info),
+ sym->st_name ?
+ &strtab[sym->st_name] : "(anonymous)");
+
+ switch (ELF32_R_TYPE(rela[i].r_info)) {
+ case R_HEXAGON_B22_PCREL: {
+ int dist = (int)(value - (uint32_t)location);
+ if ((dist < -0x00800000) ||
+ (dist >= 0x00800000)) {
+ printk(KERN_ERR
+ "%s: %s: %08x=%08x-%08x %s\n",
+ module->name,
+ "R_HEXAGON_B22_PCREL reloc out of range",
+ dist, value, (uint32_t)location,
+ sym->st_name ?
+ &strtab[sym->st_name] : "(anonymous)");
+ return -ENOEXEC;
+ }
+ DEBUGP("B22_PCREL contents: %08X.\n", *location);
+ *location &= ~0x01ff3fff;
+ *location |= 0x00003fff & dist;
+ *location |= 0x01ff0000 & (dist<<2);
+ DEBUGP("Contents after reloc: %08x\n", *location);
+ break;
+ }
+ case R_HEXAGON_HI16:
+ value = (value>>16) & 0xffff;
+ /* fallthrough */
+ case R_HEXAGON_LO16:
+ *location &= ~0x00c03fff;
+ *location |= value & 0x3fff;
+ *location |= (value & 0xc000) << 8;
+ break;
+ case R_HEXAGON_32:
+ *location = value;
+ break;
+ case R_HEXAGON_32_PCREL:
+ *location = value - (uint32_t)location;
+ break;
+ case R_HEXAGON_PLT_B22_PCREL:
+ case R_HEXAGON_GOTOFF_LO16:
+ case R_HEXAGON_GOTOFF_HI16:
+ printk(KERN_ERR "%s: GOT/PLT relocations unsupported\n",
+ module->name);
+ return -ENOEXEC;
+ default:
+ printk(KERN_ERR "%s: unknown relocation: %u\n",
+ module->name,
+ ELF32_R_TYPE(rela[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c
new file mode 100644
index 000000000000..18c4f0b0f4ba
--- /dev/null
+++ b/arch/hexagon/kernel/process.c
@@ -0,0 +1,279 @@
+/*
+ * Process creation support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/tick.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+/*
+ * Kernel thread creation. The desired kernel function is "wrapped"
+ * in the kernel_thread_helper function, which does cleanup
+ * afterwards.
+ */
+static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
+{
+ do_exit(fn(arg));
+}
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+ struct pt_regs regs;
+
+ memset(&regs, 0, sizeof(regs));
+ /*
+ * Yes, we're exploting illicit knowledge of the ABI here.
+ */
+ regs.r00 = (unsigned long) arg;
+ regs.r01 = (unsigned long) fn;
+ pt_set_elr(&regs, (unsigned long)kernel_thread_helper);
+ pt_set_kmode(&regs);
+
+ return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * Program thread launch. Often defined as a macro in processor.h,
+ * but we're shooting for a small footprint and it's not an inner-loop
+ * performance-critical operation.
+ *
+ * The Hexagon ABI specifies that R28 is zero'ed before program launch,
+ * so that gets automatically done here. If we ever stop doing that here,
+ * we'll probably want to define the ELF_PLAT_INIT macro.
+ */
+void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
+{
+ /* Set to run with user-mode data segmentation */
+ set_fs(USER_DS);
+ /* We want to zero all data-containing registers. Is this overkill? */
+ memset(regs, 0, sizeof(*regs));
+ /* We might want to also zero all Processor registers here */
+ pt_set_usermode(regs);
+ pt_set_elr(regs, pc);
+ pt_set_rte_sp(regs, sp);
+}
+
+/*
+ * Spin, or better still, do a hardware or VM wait instruction
+ * If hardware or VM offer wait termination even though interrupts
+ * are disabled.
+ */
+static void default_idle(void)
+{
+ __vmwait();
+}
+
+void (*idle_sleep)(void) = default_idle;
+
+void cpu_idle(void)
+{
+ while (1) {
+ tick_nohz_stop_sched_tick(1);
+ local_irq_disable();
+ while (!need_resched()) {
+ idle_sleep();
+ /* interrupts wake us up, but aren't serviced */
+ local_irq_enable(); /* service interrupt */
+ local_irq_disable();
+ }
+ local_irq_enable();
+ tick_nohz_restart_sched_tick();
+ schedule();
+ }
+}
+
+/*
+ * Return saved PC of a blocked thread
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+ return 0;
+}
+
+/*
+ * Copy architecture-specific thread state
+ */
+int copy_thread(unsigned long clone_flags, unsigned long usp,
+ unsigned long unused, struct task_struct *p,
+ struct pt_regs *regs)
+{
+ struct thread_info *ti = task_thread_info(p);
+ struct hexagon_switch_stack *ss;
+ struct pt_regs *childregs;
+ asmlinkage void ret_from_fork(void);
+
+ childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) -
+ sizeof(*childregs));
+
+ memcpy(childregs, regs, sizeof(*childregs));
+ ti->regs = childregs;
+
+ /*
+ * Establish kernel stack pointer and initial PC for new thread
+ */
+ ss = (struct hexagon_switch_stack *) ((unsigned long) childregs -
+ sizeof(*ss));
+ ss->lr = (unsigned long)ret_from_fork;
+ p->thread.switch_sp = ss;
+
+ /* If User mode thread, set pt_reg stack pointer as per parameter */
+ if (user_mode(childregs)) {
+ pt_set_rte_sp(childregs, usp);
+
+ /* Child sees zero return value */
+ childregs->r00 = 0;
+
+ /*
+ * The clone syscall has the C signature:
+ * int [r0] clone(int flags [r0],
+ * void *child_frame [r1],
+ * void *parent_tid [r2],
+ * void *child_tid [r3],
+ * void *thread_control_block [r4]);
+ * ugp is used to provide TLS support.
+ */
+ if (clone_flags & CLONE_SETTLS)
+ childregs->ugp = childregs->r04;
+
+ /*
+ * Parent sees new pid -- not necessary, not even possible at
+ * this point in the fork process
+ * Might also want to set things like ti->addr_limit
+ */
+ } else {
+ /*
+ * If kernel thread, resume stack is kernel stack base.
+ * Note that this is pointer arithmetic on pt_regs *
+ */
+ pt_set_rte_sp(childregs, (unsigned long)(childregs + 1));
+ /*
+ * We need the current thread_info fast path pointer
+ * set up in pt_regs. The register to be used is
+ * parametric for assembler code, but the mechanism
+ * doesn't drop neatly into C. Needs to be fixed.
+ */
+ childregs->THREADINFO_REG = (unsigned long) ti;
+ }
+
+ /*
+ * thread_info pointer is pulled out of task_struct "stack"
+ * field on switch_to.
+ */
+ p->stack = (void *)ti;
+
+ return 0;
+}
+
+/*
+ * Release any architecture-specific resources locked by thread
+ */
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * Free any architecture-specific thread data structures, etc.
+ */
+void exit_thread(void)
+{
+}
+
+/*
+ * Some archs flush debug and FPU info here
+ */
+void flush_thread(void)
+{
+}
+
+/*
+ * The "wait channel" terminology is archaic, but what we want
+ * is an identification of the point at which the scheduler
+ * was invoked by a blocked thread.
+ */
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long fp, pc;
+ unsigned long stack_page;
+ int count = 0;
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+
+ stack_page = (unsigned long)task_stack_page(p);
+ fp = ((struct hexagon_switch_stack *)p->thread.switch_sp)->fp;
+ do {
+ if (fp < (stack_page + sizeof(struct thread_info)) ||
+ fp >= (THREAD_SIZE - 8 + stack_page))
+ return 0;
+ pc = ((unsigned long *)fp)[1];
+ if (!in_sched_functions(pc))
+ return pc;
+ fp = *(unsigned long *) fp;
+ } while (count++ < 16);
+
+ return 0;
+}
+
+/*
+ * Borrowed from PowerPC -- basically allow smaller kernel stacks if we
+ * go crazy with the page sizes.
+ */
+#if THREAD_SHIFT < PAGE_SHIFT
+
+static struct kmem_cache *thread_info_cache;
+
+struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
+{
+ struct thread_info *ti;
+
+ ti = kmem_cache_alloc_node(thread_info_cache, GFP_KERNEL, node);
+ if (unlikely(ti == NULL))
+ return NULL;
+#ifdef CONFIG_DEBUG_STACK_USAGE
+ memset(ti, 0, THREAD_SIZE);
+#endif
+ return ti;
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+ kmem_cache_free(thread_info_cache, ti);
+}
+
+/* Weak symbol; called by init/main.c */
+
+void thread_info_cache_init(void)
+{
+ thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
+ THREAD_SIZE, 0, NULL);
+ BUG_ON(thread_info_cache == NULL);
+}
+
+#endif /* THREAD_SHIFT < PAGE_SHIFT */
+
+/*
+ * Required placeholder.
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
+{
+ return 0;
+}
diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c
new file mode 100644
index 000000000000..bea3f08470fd
--- /dev/null
+++ b/arch/hexagon/kernel/ptrace.c
@@ -0,0 +1,180 @@
+/*
+ * Ptrace support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <generated/compile.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/regset.h>
+#include <linux/user.h>
+
+#include <asm/system.h>
+#include <asm/user.h>
+
+static int genregs_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+ unsigned int dummy;
+ struct pt_regs *regs = task_pt_regs(target);
+
+
+ if (!regs)
+ return -EIO;
+
+ /* The general idea here is that the copyout must happen in
+ * exactly the same order in which the userspace expects these
+ * regs. Now, the sequence in userspace does not match the
+ * sequence in the kernel, so everything past the 32 gprs
+ * happens one at a time.
+ */
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &regs->r00, 0, 32*sizeof(unsigned long));
+
+#define ONEXT(KPT_REG, USR_REG) \
+ if (!ret) \
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, \
+ KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
+ offsetof(struct user_regs_struct, USR_REG) + \
+ sizeof(unsigned long));
+
+ /* Must be exactly same sequence as struct user_regs_struct */
+ ONEXT(&regs->sa0, sa0);
+ ONEXT(&regs->lc0, lc0);
+ ONEXT(&regs->sa1, sa1);
+ ONEXT(&regs->lc1, lc1);
+ ONEXT(&regs->m0, m0);
+ ONEXT(&regs->m1, m1);
+ ONEXT(&regs->usr, usr);
+ ONEXT(&regs->preds, p3_0);
+ ONEXT(&regs->gp, gp);
+ ONEXT(&regs->ugp, ugp);
+ ONEXT(&pt_elr(regs), pc);
+ dummy = pt_cause(regs);
+ ONEXT(&dummy, cause);
+ ONEXT(&pt_badva(regs), badva);
+
+ /* Pad the rest with zeros, if needed */
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ offsetof(struct user_regs_struct, pad1), -1);
+ return ret;
+}
+
+static int genregs_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+ unsigned long bucket;
+ struct pt_regs *regs = task_pt_regs(target);
+
+ if (!regs)
+ return -EIO;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &regs->r00, 0, 32*sizeof(unsigned long));
+
+#define INEXT(KPT_REG, USR_REG) \
+ if (!ret) \
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
+ KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
+ offsetof(struct user_regs_struct, USR_REG) + \
+ sizeof(unsigned long));
+
+ /* Must be exactly same sequence as struct user_regs_struct */
+ INEXT(&regs->sa0, sa0);
+ INEXT(&regs->lc0, lc0);
+ INEXT(&regs->sa1, sa1);
+ INEXT(&regs->lc1, lc1);
+ INEXT(&regs->m0, m0);
+ INEXT(&regs->m1, m1);
+ INEXT(&regs->usr, usr);
+ INEXT(&regs->preds, p3_0);
+ INEXT(&regs->gp, gp);
+ INEXT(&regs->ugp, ugp);
+ INEXT(&pt_elr(regs), pc);
+
+ /* CAUSE and BADVA aren't writeable. */
+ INEXT(&bucket, cause);
+ INEXT(&bucket, badva);
+
+ /* Ignore the rest, if needed */
+ if (!ret)
+ ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ offsetof(struct user_regs_struct, pad1), -1);
+
+ if (ret)
+ return ret;
+
+ /*
+ * This is special; SP is actually restored by the VM via the
+ * special event record which is set by the special trap.
+ */
+ regs->hvmer.vmpsp = regs->r29;
+ return 0;
+}
+
+enum hexagon_regset {
+ REGSET_GENERAL,
+};
+
+static const struct user_regset hexagon_regsets[] = {
+ [REGSET_GENERAL] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = ELF_NGREG,
+ .size = sizeof(unsigned long),
+ .align = sizeof(unsigned long),
+ .get = genregs_get,
+ .set = genregs_set,
+ },
+};
+
+static const struct user_regset_view hexagon_user_view = {
+ .name = UTS_MACHINE,
+ .e_machine = ELF_ARCH,
+ .ei_osabi = ELF_OSABI,
+ .regsets = hexagon_regsets,
+ .n = ARRAY_SIZE(hexagon_regsets)
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+ return &hexagon_user_view;
+}
+
+void ptrace_disable(struct task_struct *child)
+{
+ /* Boilerplate - resolves to null inline if no HW single-step */
+ user_disable_single_step(child);
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+ unsigned long addr, unsigned long data)
+{
+ return ptrace_request(child, request, addr, data);
+}
diff --git a/arch/hexagon/kernel/reset.c b/arch/hexagon/kernel/reset.c
new file mode 100644
index 000000000000..4d72fc58e9b1
--- /dev/null
+++ b/arch/hexagon/kernel/reset.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/smp.h>
+#include <asm/hexagon_vm.h>
+
+void machine_power_off(void)
+{
+ smp_send_stop();
+ __vmstop();
+}
+
+void machine_halt(void)
+{
+}
+
+void machine_restart(char *cmd)
+{
+}
+
+void pm_power_off(void)
+{
+}
diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c
new file mode 100644
index 000000000000..1202f78d25cb
--- /dev/null
+++ b/arch/hexagon/kernel/setup.c
@@ -0,0 +1,145 @@
+/*
+ * Arch related setup for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+#include <linux/console.h>
+#include <linux/of_fdt.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/hexagon_vm.h>
+#include <asm/vm_mmu.h>
+#include <asm/time.h>
+#ifdef CONFIG_OF
+#include <asm/prom.h>
+#endif
+
+char cmd_line[COMMAND_LINE_SIZE];
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
+
+int on_simulator;
+
+void __cpuinit calibrate_delay(void)
+{
+ loops_per_jiffy = thread_freq_mhz * 1000000 / HZ;
+}
+
+/*
+ * setup_arch - high level architectural setup routine
+ * @cmdline_p: pointer to pointer to command-line arguments
+ */
+
+void __init setup_arch(char **cmdline_p)
+{
+ char *p = &external_cmdline_buffer;
+
+ /*
+ * These will eventually be pulled in via either some hypervisor
+ * or devicetree description. Hardwiring for now.
+ */
+ pcycle_freq_mhz = 600;
+ thread_freq_mhz = 100;
+ sleep_clk_freq = 32000;
+
+ /*
+ * Set up event bindings to handle exceptions and interrupts.
+ */
+ __vmsetvec(_K_VM_event_vector);
+
+ /*
+ * Simulator has a few differences from the hardware.
+ * For now, check uninitialized-but-mapped memory
+ * prior to invoking setup_arch_memory().
+ */
+ if (*(int *)((unsigned long)_end + 8) == 0x1f1f1f1f)
+ on_simulator = 1;
+ else
+ on_simulator = 0;
+
+ if (p[0] != '\0')
+ strlcpy(boot_command_line, p, COMMAND_LINE_SIZE);
+ else
+ strlcpy(boot_command_line, default_command_line,
+ COMMAND_LINE_SIZE);
+
+ /*
+ * boot_command_line and the value set up by setup_arch
+ * are both picked up by the init code. If no reason to
+ * make them different, pass the same pointer back.
+ */
+ strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = cmd_line;
+
+ parse_early_param();
+
+ setup_arch_memory();
+
+#ifdef CONFIG_SMP
+ smp_start_cpus();
+#endif
+}
+
+/*
+ * Functions for dumping CPU info via /proc
+ * Probably should move to kernel/proc.c or something.
+ */
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ return *pos < nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+/*
+ * Eventually this will dump information about
+ * CPU properties like ISA level, TLB size, etc.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+ int cpu = (unsigned long) v - 1;
+
+ seq_printf(m, "processor\t: %d\n", cpu);
+ seq_printf(m, "model name\t: Hexagon Virtual Machine\n");
+ seq_printf(m, "BogoMips\t: %lu.%02lu\n",
+ (loops_per_jiffy * HZ) / 500000,
+ ((loops_per_jiffy * HZ) / 5000) % 100);
+ seq_printf(m, "\n");
+ return 0;
+}
+
+const struct seq_operations cpuinfo_op = {
+ .start = &c_start,
+ .next = &c_next,
+ .stop = &c_stop,
+ .show = &show_cpuinfo,
+};
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
new file mode 100644
index 000000000000..b45be3181193
--- /dev/null
+++ b/arch/hexagon/kernel/signal.c
@@ -0,0 +1,345 @@
+/*
+ * Signal support for Hexagon processor
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <linux/syscalls.h>
+#include <linux/freezer.h>
+#include <linux/tracehook.h>
+#include <asm/registers.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/cacheflush.h>
+#include <asm/signal.h>
+#include <asm/vdso.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+struct rt_sigframe {
+ unsigned long tramp[2];
+ struct siginfo info;
+ struct ucontext uc;
+};
+
+static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ size_t frame_size)
+{
+ unsigned long sp = regs->r29;
+
+ /* Switch to signal stack if appropriate */
+ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
+}
+
+static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+ unsigned long tmp;
+ int err = 0;
+
+ err |= copy_to_user(&sc->sc_regs.r0, &regs->r00,
+ 32*sizeof(unsigned long));
+
+ err |= __put_user(regs->sa0, &sc->sc_regs.sa0);
+ err |= __put_user(regs->lc0, &sc->sc_regs.lc0);
+ err |= __put_user(regs->sa1, &sc->sc_regs.sa1);
+ err |= __put_user(regs->lc1, &sc->sc_regs.lc1);
+ err |= __put_user(regs->m0, &sc->sc_regs.m0);
+ err |= __put_user(regs->m1, &sc->sc_regs.m1);
+ err |= __put_user(regs->usr, &sc->sc_regs.usr);
+ err |= __put_user(regs->preds, &sc->sc_regs.p3_0);
+ err |= __put_user(regs->gp, &sc->sc_regs.gp);
+ err |= __put_user(regs->ugp, &sc->sc_regs.ugp);
+
+ tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc);
+ tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause);
+ tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva);
+
+ return err;
+}
+
+static int restore_sigcontext(struct pt_regs *regs,
+ struct sigcontext __user *sc)
+{
+ unsigned long tmp;
+ int err = 0;
+
+ err |= copy_from_user(&regs->r00, &sc->sc_regs.r0,
+ 32 * sizeof(unsigned long));
+
+ err |= __get_user(regs->sa0, &sc->sc_regs.sa0);
+ err |= __get_user(regs->lc0, &sc->sc_regs.lc0);
+ err |= __get_user(regs->sa1, &sc->sc_regs.sa1);
+ err |= __get_user(regs->lc1, &sc->sc_regs.lc1);
+ err |= __get_user(regs->m0, &sc->sc_regs.m0);
+ err |= __get_user(regs->m1, &sc->sc_regs.m1);
+ err |= __get_user(regs->usr, &sc->sc_regs.usr);
+ err |= __get_user(regs->preds, &sc->sc_regs.p3_0);
+ err |= __get_user(regs->gp, &sc->sc_regs.gp);
+ err |= __get_user(regs->ugp, &sc->sc_regs.ugp);
+
+ err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp);
+
+ return err;
+}
+
+/*
+ * Setup signal stack frame with siginfo structure
+ */
+static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ int err = 0;
+ struct rt_sigframe __user *frame;
+ struct hexagon_vdso *vdso = current->mm->context.vdso;
+
+ frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
+ goto sigsegv;
+
+ if (copy_siginfo_to_user(&frame->info, info))
+ goto sigsegv;
+
+ /* The on-stack signal trampoline is no longer executed;
+ * however, the libgcc signal frame unwinding code checks for
+ * the presence of these two numeric magic values.
+ */
+ err |= __put_user(0x7800d166, &frame->tramp[0]);
+ err |= __put_user(0x5400c004, &frame->tramp[1]);
+ err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err)
+ goto sigsegv;
+
+ /* Load r0/r1 pair with signumber/siginfo pointer... */
+ regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
+ | (unsigned long long)signr;
+ regs->r02 = (unsigned long) &frame->uc;
+ regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
+ pt_psp(regs) = (unsigned long) frame;
+ pt_set_elr(regs, (unsigned long)ka->sa.sa_handler);
+
+ return 0;
+
+sigsegv:
+ force_sigsegv(signr, current);
+ return -EFAULT;
+}
+
+/*
+ * Setup invocation of signal handler
+ */
+static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
+ sigset_t *oldset, struct pt_regs *regs)
+{
+ int rc;
+
+ /*
+ * If we're handling a signal that aborted a system call,
+ * set up the error return value before adding the signal
+ * frame to the stack.
+ */
+
+ if (regs->syscall_nr >= 0) {
+ switch (regs->r00) {
+ case -ERESTART_RESTARTBLOCK:
+ case -ERESTARTNOHAND:
+ regs->r00 = -EINTR;
+ break;
+ case -ERESTARTSYS:
+ if (!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->r00 = -EINTR;
+ break;
+ }
+ /* Fall through */
+ case -ERESTARTNOINTR:
+ regs->r06 = regs->syscall_nr;
+ pt_set_elr(regs, pt_elr(regs) - 4);
+ regs->r00 = regs->restart_r0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Set up the stack frame; not doing the SA_SIGINFO thing. We
+ * only set up the rt_frame flavor.
+ */
+ rc = setup_rt_frame(sig, ka, info, oldset, regs);
+
+ /* If there was an error on setup, no signal was delivered. */
+ if (rc)
+ return rc;
+
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ return 0;
+}
+
+/*
+ * Called from return-from-event code.
+ */
+static void do_signal(struct pt_regs *regs)
+{
+ struct k_sigaction sigact;
+ siginfo_t info;
+ int signo;
+
+ if (!user_mode(regs))
+ return;
+
+ if (try_to_freeze())
+ goto no_signal;
+
+ signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
+
+ if (signo > 0) {
+ sigset_t *oldset;
+
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
+ oldset = &current->blocked;
+
+ if (handle_signal(signo, &info, &sigact, oldset, regs) == 0) {
+ /*
+ * Successful delivery case. The saved sigmask is
+ * stored in the signal frame, and will be restored
+ * by sigreturn. We can clear the TIF flag.
+ */
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+ tracehook_signal_handler(signo, &info, &sigact, regs,
+ test_thread_flag(TIF_SINGLESTEP));
+ }
+ return;
+ }
+
+no_signal:
+ /*
+ * If we came from a system call, handle the restart.
+ */
+ if (regs->syscall_nr >= 0) {
+ switch (regs->r00) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ regs->r06 = regs->syscall_nr;
+ break;
+ case -ERESTART_RESTARTBLOCK:
+ regs->r06 = __NR_restart_syscall;
+ break;
+ default:
+ goto no_restart;
+ }
+ pt_set_elr(regs, pt_elr(regs) - 4);
+ regs->r00 = regs->restart_r0;
+ }
+
+no_restart:
+ /* If there's no signal to deliver, put the saved sigmask back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
+}
+
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
+{
+ if (thread_info_flags & _TIF_SIGPENDING)
+ do_signal(regs);
+
+ if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+ clear_thread_flag(TIF_NOTIFY_RESUME);
+ if (current->replacement_session_keyring)
+ key_replace_session_keyring();
+ }
+}
+
+/*
+ * Architecture-specific wrappers for signal-related system calls
+ */
+asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+{
+ struct pt_regs *regs = current_thread_info()->regs;
+
+ return do_sigaltstack(uss, uoss, regs->r29);
+}
+
+asmlinkage int sys_rt_sigreturn(void)
+{
+ struct pt_regs *regs = current_thread_info()->regs;
+ struct rt_sigframe __user *frame;
+ sigset_t blocked;
+
+ frame = (struct rt_sigframe __user *)pt_psp(regs);
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked)))
+ goto badframe;
+
+ sigdelsetmask(&blocked, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = blocked;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+ goto badframe;
+
+ /* Restore the user's stack as well */
+ pt_psp(regs) = regs->r29;
+
+ /*
+ * Leave a trace in the stack frame that this was a sigreturn.
+ * If the system call is to replay, we've already restored the
+ * number in the GPR slot and it will be regenerated on the
+ * new system call trap entry. Note that if restore_sigcontext()
+ * did something other than a bulk copy of the pt_regs struct,
+ * we could avoid this assignment by simply not overwriting
+ * regs->syscall_nr.
+ */
+ regs->syscall_nr = __NR_rt_sigreturn;
+
+ /*
+ * If we were meticulous, we'd only call this if we knew that
+ * we were actually going to use an alternate stack, and we'd
+ * consider any error to be fatal. What we do here, in common
+ * with many other architectures, is call it blindly and only
+ * consider the -EFAULT return case to be proof of a problem.
+ */
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, pt_psp(regs)) == -EFAULT)
+ goto badframe;
+
+ return 0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c
new file mode 100644
index 000000000000..c871a2cffaef
--- /dev/null
+++ b/arch/hexagon/kernel/smp.c
@@ -0,0 +1,276 @@
+/*
+ * SMP support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+
+#include <asm/system.h> /* xchg */
+#include <asm/time.h> /* timer_interrupt */
+#include <asm/hexagon_vm.h>
+
+#define BASE_IPI_IRQ 26
+
+/*
+ * cpu_possible_map needs to be filled out prior to setup_per_cpu_areas
+ * (which is prior to any of our smp_prepare_cpu crap), in order to set
+ * up the... per_cpu areas.
+ */
+
+struct ipi_data {
+ unsigned long bits;
+};
+
+static DEFINE_PER_CPU(struct ipi_data, ipi_data);
+
+static inline void __handle_ipi(unsigned long *ops, struct ipi_data *ipi,
+ int cpu)
+{
+ unsigned long msg = 0;
+ do {
+ msg = find_next_bit(ops, BITS_PER_LONG, msg+1);
+
+ switch (msg) {
+
+ case IPI_TIMER:
+ ipi_timer();
+ break;
+
+ case IPI_CALL_FUNC:
+ generic_smp_call_function_interrupt();
+ break;
+
+ case IPI_CALL_FUNC_SINGLE:
+ generic_smp_call_function_single_interrupt();
+ break;
+
+ case IPI_CPU_STOP:
+ /*
+ * call vmstop()
+ */
+ __vmstop();
+ break;
+
+ case IPI_RESCHEDULE:
+ scheduler_ipi();
+ break;
+ }
+ } while (msg < BITS_PER_LONG);
+}
+
+/* Used for IPI call from other CPU's to unmask int */
+void smp_vm_unmask_irq(void *info)
+{
+ __vmintop_locen((long) info);
+}
+
+
+/*
+ * This is based on Alpha's IPI stuff.
+ * Supposed to take (int, void*) as args now.
+ * Specifically, first arg is irq, second is the irq_desc.
+ */
+
+irqreturn_t handle_ipi(int irq, void *desc)
+{
+ int cpu = smp_processor_id();
+ struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+ unsigned long ops;
+
+ while ((ops = xchg(&ipi->bits, 0)) != 0)
+ __handle_ipi(&ops, ipi, cpu);
+ return IRQ_HANDLED;
+}
+
+void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg)
+{
+ unsigned long flags;
+ unsigned long cpu;
+ unsigned long retval;
+
+ local_irq_save(flags);
+
+ for_each_cpu(cpu, cpumask) {
+ struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+
+ set_bit(msg, &ipi->bits);
+ /* Possible barrier here */
+ retval = __vmintop_post(BASE_IPI_IRQ+cpu);
+
+ if (retval != 0) {
+ printk(KERN_ERR "interrupt %ld not configured?\n",
+ BASE_IPI_IRQ+cpu);
+ }
+ }
+
+ local_irq_restore(flags);
+}
+
+static struct irqaction ipi_intdesc = {
+ .handler = handle_ipi,
+ .flags = IRQF_TRIGGER_RISING,
+ .name = "ipi_handler"
+};
+
+void __init smp_prepare_boot_cpu(void)
+{
+}
+
+/*
+ * interrupts should already be disabled from the VM
+ * SP should already be correct; need to set THREADINFO_REG
+ * to point to current thread info
+ */
+
+void __cpuinit start_secondary(void)
+{
+ unsigned int cpu;
+ unsigned long thread_ptr;
+
+ /* Calculate thread_info pointer from stack pointer */
+ __asm__ __volatile__(
+ "%0 = SP;\n"
+ : "=r" (thread_ptr)
+ );
+
+ thread_ptr = thread_ptr & ~(THREAD_SIZE-1);
+
+ __asm__ __volatile__(
+ QUOTED_THREADINFO_REG " = %0;\n"
+ :
+ : "r" (thread_ptr)
+ );
+
+ /* Set the memory struct */
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+
+ cpu = smp_processor_id();
+
+ setup_irq(BASE_IPI_IRQ + cpu, &ipi_intdesc);
+
+ /* Register the clock_event dummy */
+ setup_percpu_clockdev();
+
+ printk(KERN_INFO "%s cpu %d\n", __func__, current_thread_info()->cpu);
+
+ set_cpu_online(cpu, true);
+ while (!cpumask_test_cpu(cpu, cpu_active_mask))
+ cpu_relax();
+ local_irq_enable();
+
+ cpu_idle();
+}
+
+
+/*
+ * called once for each present cpu
+ * apparently starts up the CPU and then
+ * maintains control until "cpu_online(cpu)" is set.
+ */
+
+int __cpuinit __cpu_up(unsigned int cpu)
+{
+ struct task_struct *idle;
+ struct thread_info *thread;
+ void *stack_start;
+
+ /* Create new init task for the CPU */
+ idle = fork_idle(cpu);
+ if (IS_ERR(idle))
+ panic(KERN_ERR "fork_idle failed\n");
+
+ thread = (struct thread_info *)idle->stack;
+ thread->cpu = cpu;
+
+ /* Boot to the head. */
+ stack_start = ((void *) thread) + THREAD_SIZE;
+ __vmstart(start_secondary, stack_start);
+
+ while (!cpu_isset(cpu, cpu_online_map))
+ barrier();
+
+ return 0;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ int i;
+
+ /*
+ * should eventually have some sort of machine
+ * descriptor that has this stuff
+ */
+
+ /* Right now, let's just fake it. */
+ for (i = 0; i < max_cpus; i++)
+ cpu_set(i, cpu_present_map);
+
+ /* Also need to register the interrupts for IPI */
+ if (max_cpus > 1)
+ setup_irq(BASE_IPI_IRQ, &ipi_intdesc);
+}
+
+void smp_send_reschedule(int cpu)
+{
+ send_ipi(cpumask_of(cpu), IPI_RESCHEDULE);
+}
+
+void smp_send_stop(void)
+{
+ struct cpumask targets;
+ cpumask_copy(&targets, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &targets);
+ send_ipi(&targets, IPI_CPU_STOP);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+ send_ipi(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+ send_ipi(mask, IPI_CALL_FUNC);
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+ return -EINVAL;
+}
+
+void smp_start_cpus(void)
+{
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++)
+ cpu_set(i, cpu_possible_map);
+}
diff --git a/arch/hexagon/kernel/stacktrace.c b/arch/hexagon/kernel/stacktrace.c
new file mode 100644
index 000000000000..11c597b2ac59
--- /dev/null
+++ b/arch/hexagon/kernel/stacktrace.c
@@ -0,0 +1,66 @@
+/*
+ * Stacktrace support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <linux/module.h>
+
+register unsigned long current_frame_pointer asm("r30");
+
+struct stackframe {
+ unsigned long fp;
+ unsigned long rets;
+};
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace)
+{
+ unsigned long low, high;
+ unsigned long fp;
+ struct stackframe *frame;
+ int skip = trace->skip;
+
+ low = (unsigned long)task_stack_page(current);
+ high = low + THREAD_SIZE;
+ fp = current_frame_pointer;
+
+ while (fp >= low && fp <= (high - sizeof(*frame))) {
+ frame = (struct stackframe *)fp;
+
+ if (skip) {
+ skip--;
+ } else {
+ trace->entries[trace->nr_entries++] = frame->rets;
+ if (trace->nr_entries >= trace->max_entries)
+ break;
+ }
+
+ /*
+ * The next frame must be at a higher address than the
+ * current frame.
+ */
+ low = fp + sizeof(*frame);
+ fp = frame->fp;
+ }
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
diff --git a/arch/hexagon/kernel/syscall.c b/arch/hexagon/kernel/syscall.c
new file mode 100644
index 000000000000..620dd18197a0
--- /dev/null
+++ b/arch/hexagon/kernel/syscall.c
@@ -0,0 +1,90 @@
+/*
+ * Hexagon system calls
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/unistd.h>
+#include <asm/mman.h>
+#include <asm/registers.h>
+
+/*
+ * System calls with architecture-specific wrappers.
+ * See signal.c for signal-related system call wrappers.
+ */
+
+asmlinkage int sys_execve(char __user *ufilename,
+ const char __user *const __user *argv,
+ const char __user *const __user *envp)
+{
+ struct pt_regs *pregs = current_thread_info()->regs;
+ char *filename;
+ int retval;
+
+ filename = getname(ufilename);
+ retval = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ return retval;
+
+ retval = do_execve(filename, argv, envp, pregs);
+ putname(filename);
+
+ return retval;
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+ unsigned long parent_tidp, unsigned long child_tidp)
+{
+ struct pt_regs *pregs = current_thread_info()->regs;
+
+ if (!newsp)
+ newsp = pregs->SP;
+ return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp,
+ (int __user *)child_tidp);
+}
+
+/*
+ * Do a system call from the kernel, so as to have a proper pt_regs
+ * and recycle the sys_execvpe infrustructure.
+ */
+int kernel_execve(const char *filename,
+ const char *const argv[], const char *const envp[])
+{
+ register unsigned long __a0 asm("r0") = (unsigned long) filename;
+ register unsigned long __a1 asm("r1") = (unsigned long) argv;
+ register unsigned long __a2 asm("r2") = (unsigned long) envp;
+ int retval;
+
+ __asm__ volatile(
+ " R6 = #%4;\n"
+ " trap0(#1);\n"
+ " %0 = R0;\n"
+ : "=r" (retval)
+ : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve)
+ );
+
+ return retval;
+}
+EXPORT_SYMBOL(kernel_execve);
diff --git a/arch/hexagon/kernel/syscalltab.c b/arch/hexagon/kernel/syscalltab.c
new file mode 100644
index 000000000000..c550f4177ab8
--- /dev/null
+++ b/arch/hexagon/kernel/syscalltab.c
@@ -0,0 +1,32 @@
+/*
+ * System call table for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#include <asm/syscall.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[__NR_syscalls] = {
+#include <asm/unistd.h>
+};
diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c
new file mode 100644
index 000000000000..6bee15c9c113
--- /dev/null
+++ b/arch/hexagon/kernel/time.c
@@ -0,0 +1,250 @@
+/*
+ * Time related functions for Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/timer-regs.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * For the clocksource we need:
+ * pcycle frequency (600MHz)
+ * For the loops_per_jiffy we need:
+ * thread/cpu frequency (100MHz)
+ * And for the timer, we need:
+ * sleep clock rate
+ */
+
+cycles_t pcycle_freq_mhz;
+cycles_t thread_freq_mhz;
+cycles_t sleep_clk_freq;
+
+static struct resource rtos_timer_resources[] = {
+ {
+ .start = RTOS_TIMER_REGS_ADDR,
+ .end = RTOS_TIMER_REGS_ADDR+PAGE_SIZE-1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rtos_timer_device = {
+ .name = "rtos_timer",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtos_timer_resources),
+ .resource = rtos_timer_resources,
+};
+
+/* A lot of this stuff should move into a platform specific section. */
+struct adsp_hw_timer_struct {
+ u32 match; /* Match value */
+ u32 count;
+ u32 enable; /* [1] - CLR_ON_MATCH_EN, [0] - EN */
+ u32 clear; /* one-shot register that clears the count */
+};
+
+/* Look for "TCX0" for related constants. */
+static __iomem struct adsp_hw_timer_struct *rtos_timer;
+
+static cycle_t timer_get_cycles(struct clocksource *cs)
+{
+ return (cycle_t) __vmgettime();
+}
+
+static struct clocksource hexagon_clocksource = {
+ .name = "pcycles",
+ .rating = 250,
+ .read = timer_get_cycles,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int set_next_event(unsigned long delta, struct clock_event_device *evt)
+{
+ /* Assuming the timer will be disabled when we enter here. */
+
+ iowrite32(1, &rtos_timer->clear);
+ iowrite32(0, &rtos_timer->clear);
+
+ iowrite32(delta, &rtos_timer->match);
+ iowrite32(1 << TIMER_ENABLE, &rtos_timer->enable);
+ return 0;
+}
+
+/*
+ * Sets the mode (periodic, shutdown, oneshot, etc) of a timer.
+ */
+static void set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ /* XXX implement me */
+ default:
+ break;
+ }
+}
+
+#ifdef CONFIG_SMP
+/* Broadcast mechanism */
+static void broadcast(const struct cpumask *mask)
+{
+ send_ipi(mask, IPI_TIMER);
+}
+#endif
+
+static struct clock_event_device hexagon_clockevent_dev = {
+ .name = "clockevent",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 400,
+ .irq = RTOS_TIMER_INT,
+ .set_next_event = set_next_event,
+ .set_mode = set_mode,
+#ifdef CONFIG_SMP
+ .broadcast = broadcast,
+#endif
+};
+
+#ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct clock_event_device, clock_events);
+
+void setup_percpu_clockdev(void)
+{
+ int cpu = smp_processor_id();
+ struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+ struct clock_event_device *dummy_clock_dev =
+ &per_cpu(clock_events, cpu);
+
+ memcpy(dummy_clock_dev, ce_dev, sizeof(*dummy_clock_dev));
+ INIT_LIST_HEAD(&dummy_clock_dev->list);
+
+ dummy_clock_dev->features = CLOCK_EVT_FEAT_DUMMY;
+ dummy_clock_dev->cpumask = cpumask_of(cpu);
+ dummy_clock_dev->mode = CLOCK_EVT_MODE_UNUSED;
+
+ clockevents_register_device(dummy_clock_dev);
+}
+
+/* Called from smp.c for each CPU's timer ipi call */
+void ipi_timer(void)
+{
+ int cpu = smp_processor_id();
+ struct clock_event_device *ce_dev = &per_cpu(clock_events, cpu);
+
+ ce_dev->event_handler(ce_dev);
+}
+#endif /* CONFIG_SMP */
+
+static irqreturn_t timer_interrupt(int irq, void *devid)
+{
+ struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+
+ iowrite32(0, &rtos_timer->enable);
+ ce_dev->event_handler(ce_dev);
+
+ return IRQ_HANDLED;
+}
+
+/* This should also be pulled from devtree */
+static struct irqaction rtos_timer_intdesc = {
+ .handler = timer_interrupt,
+ .flags = IRQF_TIMER | IRQF_TRIGGER_RISING,
+ .name = "rtos_timer"
+};
+
+/*
+ * time_init_deferred - called by start_kernel to set up timer/clock source
+ *
+ * Install the IRQ handler for the clock, setup timers.
+ * This is done late, as that way, we can use ioremap().
+ *
+ * This runs just before the delay loop is calibrated, and
+ * is used for delay calibration.
+ */
+void __init time_init_deferred(void)
+{
+ struct resource *resource = NULL;
+ struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+ struct device_node *dn;
+ struct resource r;
+ int err;
+
+ ce_dev->cpumask = cpu_all_mask;
+
+ if (!resource)
+ resource = rtos_timer_device.resource;
+
+ /* ioremap here means this has to run later, after paging init */
+ rtos_timer = ioremap(resource->start, resource->end
+ - resource->start + 1);
+
+ if (!rtos_timer) {
+ release_mem_region(resource->start, resource->end
+ - resource->start + 1);
+ }
+ clocksource_register_khz(&hexagon_clocksource, pcycle_freq_mhz * 1000);
+
+ /* Note: the sim generic RTOS clock is apparently really 18750Hz */
+
+ /*
+ * Last arg is some guaranteed seconds for which the conversion will
+ * work without overflow.
+ */
+ clockevents_calc_mult_shift(ce_dev, sleep_clk_freq, 4);
+
+ ce_dev->max_delta_ns = clockevent_delta2ns(0x7fffffff, ce_dev);
+ ce_dev->min_delta_ns = clockevent_delta2ns(0xf, ce_dev);
+
+#ifdef CONFIG_SMP
+ setup_percpu_clockdev();
+#endif
+
+ clockevents_register_device(ce_dev);
+ setup_irq(ce_dev->irq, &rtos_timer_intdesc);
+}
+
+void __init time_init(void)
+{
+ late_time_init = time_init_deferred;
+}
+
+/*
+ * This could become parametric or perhaps even computed at run-time,
+ * but for now we take the observed simulator jitter.
+ */
+static long long fudgefactor = 350; /* Maybe lower if kernel optimized. */
+
+void __udelay(unsigned long usecs)
+{
+ unsigned long long start = __vmgettime();
+ unsigned long long finish = (pcycle_freq_mhz * usecs) - fudgefactor;
+
+ while ((__vmgettime() - start) < finish)
+ cpu_relax(); /* not sure how this improves readability */
+}
+EXPORT_SYMBOL(__udelay);
diff --git a/arch/hexagon/kernel/topology.c b/arch/hexagon/kernel/topology.c
new file mode 100644
index 000000000000..ba4475184432
--- /dev/null
+++ b/arch/hexagon/kernel/topology.c
@@ -0,0 +1,52 @@
+/*
+ * CPU topology for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/percpu.h>
+
+/* Swiped from MIPS. */
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+ int i, ret;
+
+ for_each_present_cpu(i) {
+
+ /*
+ * register_cpu takes a per_cpu pointer and
+ * just points it at another per_cpu struct...
+ */
+
+ ret = register_cpu(&per_cpu(cpu_devices, i), i);
+ if (ret)
+ printk(KERN_WARNING "topology_init: register_cpu %d "
+ "failed (%d)\n", i, ret);
+ }
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
diff --git a/arch/hexagon/kernel/trampoline.S b/arch/hexagon/kernel/trampoline.S
new file mode 100644
index 000000000000..06c36c036b98
--- /dev/null
+++ b/arch/hexagon/kernel/trampoline.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Trampoline sequences to be copied onto user stack.
+ * This consumes a little more space than hand-assembling
+ * immediate constants for use in C, but is more portable
+ * to future tweaks to the Hexagon instruction set.
+ */
+
+#include <asm/unistd.h>
+
+/* Sig trampolines - call sys_sigreturn or sys_rt_sigreturn as appropriate */
+
+/* plain sigreturn is gone. */
+
+ .globl __rt_sigtramp_template
+__rt_sigtramp_template:
+ r6 = #__NR_rt_sigreturn;
+ trap0(#1);
diff --git a/arch/hexagon/kernel/traps.c b/arch/hexagon/kernel/traps.c
new file mode 100644
index 000000000000..f08857d0715b
--- /dev/null
+++ b/arch/hexagon/kernel/traps.c
@@ -0,0 +1,454 @@
+/*
+ * Kernel traps/events for Hexagon processor
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/kdebug.h>
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/tracehook.h>
+#include <asm/traps.h>
+#include <asm/vm_fault.h>
+#include <asm/syscall.h>
+#include <asm/registers.h>
+#include <asm/unistd.h>
+#include <asm/sections.h>
+#ifdef CONFIG_KGDB
+# include <linux/kgdb.h>
+#endif
+
+#define TRAP_SYSCALL 1
+#define TRAP_DEBUG 0xdb
+
+void __init trap_init(void)
+{
+}
+
+#ifdef CONFIG_GENERIC_BUG
+/* Maybe should resemble arch/sh/kernel/traps.c ?? */
+int is_valid_bugaddr(unsigned long addr)
+{
+ return 1;
+}
+#endif /* CONFIG_GENERIC_BUG */
+
+static const char *ex_name(int ex)
+{
+ switch (ex) {
+ case HVM_GE_C_XPROT:
+ case HVM_GE_C_XUSER:
+ return "Execute protection fault";
+ case HVM_GE_C_RPROT:
+ case HVM_GE_C_RUSER:
+ return "Read protection fault";
+ case HVM_GE_C_WPROT:
+ case HVM_GE_C_WUSER:
+ return "Write protection fault";
+ case HVM_GE_C_XMAL:
+ return "Misaligned instruction";
+ case HVM_GE_C_RMAL:
+ return "Misaligned data load";
+ case HVM_GE_C_WMAL:
+ return "Misaligned data store";
+ case HVM_GE_C_INVI:
+ case HVM_GE_C_PRIVI:
+ return "Illegal instruction";
+ case HVM_GE_C_BUS:
+ return "Precise bus error";
+ case HVM_GE_C_CACHE:
+ return "Cache error";
+
+ case 0xdb:
+ return "Debugger trap";
+
+ default:
+ return "Unrecognized exception";
+ }
+}
+
+static void do_show_stack(struct task_struct *task, unsigned long *fp,
+ unsigned long ip)
+{
+ int kstack_depth_to_print = 24;
+ unsigned long offset, size;
+ const char *name = NULL;
+ unsigned long *newfp;
+ unsigned long low, high;
+ char tmpstr[128];
+ char *modname;
+ int i;
+
+ if (task == NULL)
+ task = current;
+
+ printk(KERN_INFO "CPU#%d, %s/%d, Call Trace:\n",
+ raw_smp_processor_id(), task->comm,
+ task_pid_nr(task));
+
+ if (fp == NULL) {
+ if (task == current) {
+ asm("%0 = r30" : "=r" (fp));
+ } else {
+ fp = (unsigned long *)
+ ((struct hexagon_switch_stack *)
+ task->thread.switch_sp)->fp;
+ }
+ }
+
+ if ((((unsigned long) fp) & 0x3) || ((unsigned long) fp < 0x1000)) {
+ printk(KERN_INFO "-- Corrupt frame pointer %p\n", fp);
+ return;
+ }
+
+ /* Saved link reg is one word above FP */
+ if (!ip)
+ ip = *(fp+1);
+
+ /* Expect kernel stack to be in-bounds */
+ low = (unsigned long)task_stack_page(task);
+ high = low + THREAD_SIZE - 8;
+ low += sizeof(struct thread_info);
+
+ for (i = 0; i < kstack_depth_to_print; i++) {
+
+ name = kallsyms_lookup(ip, &size, &offset, &modname, tmpstr);
+
+ printk(KERN_INFO "[%p] 0x%lx: %s + 0x%lx", fp, ip, name,
+ offset);
+ if (((unsigned long) fp < low) || (high < (unsigned long) fp))
+ printk(KERN_CONT " (FP out of bounds!)");
+ if (modname)
+ printk(KERN_CONT " [%s] ", modname);
+ printk(KERN_CONT "\n");
+
+ newfp = (unsigned long *) *fp;
+
+ if (((unsigned long) newfp) & 0x3) {
+ printk(KERN_INFO "-- Corrupt frame pointer %p\n",
+ newfp);
+ break;
+ }
+
+ /* Attempt to continue past exception. */
+ if (0 == newfp) {
+ struct pt_regs *regs = (struct pt_regs *) (((void *)fp)
+ + 8);
+
+ if (regs->syscall_nr != -1) {
+ printk(KERN_INFO "-- trap0 -- syscall_nr: %ld",
+ regs->syscall_nr);
+ printk(KERN_CONT " psp: %lx elr: %lx\n",
+ pt_psp(regs), pt_elr(regs));
+ break;
+ } else {
+ /* really want to see more ... */
+ kstack_depth_to_print += 6;
+ printk(KERN_INFO "-- %s (0x%lx) badva: %lx\n",
+ ex_name(pt_cause(regs)), pt_cause(regs),
+ pt_badva(regs));
+ }
+
+ newfp = (unsigned long *) regs->r30;
+ ip = pt_elr(regs);
+ } else {
+ ip = *(newfp + 1);
+ }
+
+ /* If link reg is null, we are done. */
+ if (ip == 0x0)
+ break;
+
+ /* If newfp isn't larger, we're tracing garbage. */
+ if (newfp > fp)
+ fp = newfp;
+ else
+ break;
+ }
+}
+
+void show_stack(struct task_struct *task, unsigned long *fp)
+{
+ /* Saved link reg is one word above FP */
+ do_show_stack(task, fp, 0);
+}
+
+void dump_stack(void)
+{
+ unsigned long *fp;
+ asm("%0 = r30" : "=r" (fp));
+ show_stack(current, fp);
+}
+EXPORT_SYMBOL(dump_stack);
+
+int die(const char *str, struct pt_regs *regs, long err)
+{
+ static struct {
+ spinlock_t lock;
+ int counter;
+ } die = {
+ .lock = __SPIN_LOCK_UNLOCKED(die.lock),
+ .counter = 0
+ };
+
+ console_verbose();
+ oops_enter();
+
+ spin_lock_irq(&die.lock);
+ bust_spinlocks(1);
+ printk(KERN_EMERG "Oops: %s[#%d]:\n", str, ++die.counter);
+
+ if (notify_die(DIE_OOPS, str, regs, err, pt_cause(regs), SIGSEGV) ==
+ NOTIFY_STOP)
+ return 1;
+
+ print_modules();
+ show_regs(regs);
+ do_show_stack(current, &regs->r30, pt_elr(regs));
+
+ bust_spinlocks(0);
+ add_taint(TAINT_DIE);
+
+ spin_unlock_irq(&die.lock);
+
+ if (in_interrupt())
+ panic("Fatal exception in interrupt");
+
+ if (panic_on_oops)
+ panic("Fatal exception");
+
+ oops_exit();
+ do_exit(err);
+ return 0;
+}
+
+int die_if_kernel(char *str, struct pt_regs *regs, long err)
+{
+ if (!user_mode(regs))
+ return die(str, regs, err);
+ else
+ return 0;
+}
+
+/*
+ * It's not clear that misaligned fetches are ever recoverable.
+ */
+static void misaligned_instruction(struct pt_regs *regs)
+{
+ die_if_kernel("Misaligned Instruction", regs, 0);
+ force_sig(SIGBUS, current);
+}
+
+/*
+ * Misaligned loads and stores, on the other hand, can be
+ * emulated, and probably should be, some day. But for now
+ * they will be considered fatal.
+ */
+static void misaligned_data_load(struct pt_regs *regs)
+{
+ die_if_kernel("Misaligned Data Load", regs, 0);
+ force_sig(SIGBUS, current);
+}
+
+static void misaligned_data_store(struct pt_regs *regs)
+{
+ die_if_kernel("Misaligned Data Store", regs, 0);
+ force_sig(SIGBUS, current);
+}
+
+static void illegal_instruction(struct pt_regs *regs)
+{
+ die_if_kernel("Illegal Instruction", regs, 0);
+ force_sig(SIGILL, current);
+}
+
+/*
+ * Precise bus errors may be recoverable with a a retry,
+ * but for now, treat them as irrecoverable.
+ */
+static void precise_bus_error(struct pt_regs *regs)
+{
+ die_if_kernel("Precise Bus Error", regs, 0);
+ force_sig(SIGBUS, current);
+}
+
+/*
+ * If anything is to be done here other than panic,
+ * it will probably be complex and migrate to another
+ * source module. For now, just die.
+ */
+static void cache_error(struct pt_regs *regs)
+{
+ die("Cache Error", regs, 0);
+}
+
+/*
+ * General exception handler
+ */
+void do_genex(struct pt_regs *regs)
+{
+ /*
+ * Decode Cause and Dispatch
+ */
+ switch (pt_cause(regs)) {
+ case HVM_GE_C_XPROT:
+ case HVM_GE_C_XUSER:
+ execute_protection_fault(regs);
+ break;
+ case HVM_GE_C_RPROT:
+ case HVM_GE_C_RUSER:
+ read_protection_fault(regs);
+ break;
+ case HVM_GE_C_WPROT:
+ case HVM_GE_C_WUSER:
+ write_protection_fault(regs);
+ break;
+ case HVM_GE_C_XMAL:
+ misaligned_instruction(regs);
+ break;
+ case HVM_GE_C_RMAL:
+ misaligned_data_load(regs);
+ break;
+ case HVM_GE_C_WMAL:
+ misaligned_data_store(regs);
+ break;
+ case HVM_GE_C_INVI:
+ case HVM_GE_C_PRIVI:
+ illegal_instruction(regs);
+ break;
+ case HVM_GE_C_BUS:
+ precise_bus_error(regs);
+ break;
+ case HVM_GE_C_CACHE:
+ cache_error(regs);
+ break;
+ default:
+ /* Halt and catch fire */
+ panic("Unrecognized exception 0x%lx\n", pt_cause(regs));
+ break;
+ }
+}
+
+/* Indirect system call dispatch */
+long sys_syscall(void)
+{
+ printk(KERN_ERR "sys_syscall invoked!\n");
+ return -ENOSYS;
+}
+
+void do_trap0(struct pt_regs *regs)
+{
+ unsigned long syscallret = 0;
+ syscall_fn syscall;
+
+ switch (pt_cause(regs)) {
+ case TRAP_SYSCALL:
+ /* System call is trap0 #1 */
+
+ /* allow strace to catch syscall args */
+ if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE) &&
+ tracehook_report_syscall_entry(regs)))
+ return; /* return -ENOSYS somewhere? */
+
+ /* Interrupts should be re-enabled for syscall processing */
+ __vmsetie(VM_INT_ENABLE);
+
+ /*
+ * System call number is in r6, arguments in r0..r5.
+ * Fortunately, no Linux syscall has more than 6 arguments,
+ * and Hexagon ABI passes first 6 arguments in registers.
+ * 64-bit arguments are passed in odd/even register pairs.
+ * Fortunately, we have no system calls that take more
+ * than three arguments with more than one 64-bit value.
+ * Should that change, we'd need to redesign to copy
+ * between user and kernel stacks.
+ */
+ regs->syscall_nr = regs->r06;
+
+ /*
+ * GPR R0 carries the first parameter, and is also used
+ * to report the return value. We need a backup of
+ * the user's value in case we need to do a late restart
+ * of the system call.
+ */
+ regs->restart_r0 = regs->r00;
+
+ if ((unsigned long) regs->syscall_nr >= __NR_syscalls) {
+ regs->r00 = -1;
+ } else {
+ syscall = (syscall_fn)
+ (sys_call_table[regs->syscall_nr]);
+ syscallret = syscall(regs->r00, regs->r01,
+ regs->r02, regs->r03,
+ regs->r04, regs->r05);
+ }
+
+ /*
+ * If it was a sigreturn system call, don't overwrite
+ * r0 value in stack frame with return value.
+ *
+ * __NR_sigreturn doesn't seem to exist in new unistd.h
+ */
+
+ if (regs->syscall_nr != __NR_rt_sigreturn)
+ regs->r00 = syscallret;
+
+ /* allow strace to get the syscall return state */
+ if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE)))
+ tracehook_report_syscall_exit(regs, 0);
+
+ break;
+ case TRAP_DEBUG:
+ /* Trap0 0xdb is debug breakpoint */
+ if (user_mode(regs)) {
+ struct siginfo info;
+
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ /*
+ * Some architecures add some per-thread state
+ * to distinguish between breakpoint traps and
+ * trace traps. We may want to do that, and
+ * set the si_code value appropriately, or we
+ * may want to use a different trap0 flavor.
+ */
+ info.si_code = TRAP_BRKPT;
+ info.si_addr = (void __user *) pt_elr(regs);
+ send_sig_info(SIGTRAP, &info, current);
+ } else {
+#ifdef CONFIG_KGDB
+ kgdb_handle_exception(pt_cause(regs), SIGTRAP,
+ TRAP_BRKPT, regs);
+#endif
+ }
+ break;
+ }
+ /* Ignore other trap0 codes for now, especially 0 (Angel calls) */
+}
+
+/*
+ * Machine check exception handler
+ */
+void do_machcheck(struct pt_regs *regs)
+{
+ /* Halt and catch fire */
+ __vmstop();
+}
diff --git a/arch/hexagon/kernel/vdso.c b/arch/hexagon/kernel/vdso.c
new file mode 100644
index 000000000000..16277c33308a
--- /dev/null
+++ b/arch/hexagon/kernel/vdso.c
@@ -0,0 +1,100 @@
+/*
+ * vDSO implementation for Hexagon
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#include <asm/vdso.h>
+
+static struct page *vdso_page;
+
+/* Create a vDSO page holding the signal trampoline.
+ * We want this for a non-executable stack.
+ */
+static int __init vdso_init(void)
+{
+ struct hexagon_vdso *vdso;
+
+ vdso_page = alloc_page(GFP_KERNEL);
+ if (!vdso_page)
+ panic("Cannot allocate vdso");
+
+ vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
+ if (!vdso)
+ panic("Cannot map vdso");
+ clear_page(vdso);
+
+ /* Install the signal trampoline; currently looks like this:
+ * r6 = #__NR_rt_sigreturn;
+ * trap0(#1);
+ */
+ vdso->rt_signal_trampoline[0] = __rt_sigtramp_template[0];
+ vdso->rt_signal_trampoline[1] = __rt_sigtramp_template[1];
+
+ vunmap(vdso);
+
+ return 0;
+}
+arch_initcall(vdso_init);
+
+/*
+ * Called from binfmt_elf. Create a VMA for the vDSO page.
+ */
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+ int ret;
+ unsigned long vdso_base;
+ struct mm_struct *mm = current->mm;
+
+ down_write(&mm->mmap_sem);
+
+ /* Try to get it loaded right near ld.so/glibc. */
+ vdso_base = STACK_TOP;
+
+ vdso_base = get_unmapped_area(NULL, vdso_base, PAGE_SIZE, 0, 0);
+ if (IS_ERR_VALUE(vdso_base)) {
+ ret = vdso_base;
+ goto up_fail;
+ }
+
+ /* MAYWRITE to allow gdb to COW and set breakpoints. */
+ ret = install_special_mapping(mm, vdso_base, PAGE_SIZE,
+ VM_READ|VM_EXEC|
+ VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+ VM_ALWAYSDUMP,
+ &vdso_page);
+
+ if (ret)
+ goto up_fail;
+
+ mm->context.vdso = (void *)vdso_base;
+
+up_fail:
+ up_write(&mm->mmap_sem);
+ return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+ if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+ return "[vdso]";
+ return NULL;
+}
diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S
new file mode 100644
index 000000000000..5b99066cbc8d
--- /dev/null
+++ b/arch/hexagon/kernel/vm_entry.S
@@ -0,0 +1,269 @@
+/*
+ * Event entry/exit for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/asm-offsets.h> /* assembly-safer versions of C defines */
+#include <asm/mem-layout.h> /* sigh, except for page_offset */
+#include <asm/hexagon_vm.h>
+#include <asm/thread_info.h>
+
+/*
+ * Entry into guest-mode Linux under Hexagon Virtual Machine.
+ * Stack pointer points to event record - build pt_regs on top of it,
+ * set up a plausible C stack frame, and dispatch to the C handler.
+ * On return, do vmrte virtual instruction with SP where we started.
+ *
+ * VM Spec 0.5 uses a trap to fetch HVM record now.
+ */
+
+/*
+ * Save full register state, while setting up thread_info struct
+ * pointer derived from kernel stack pointer in THREADINFO_REG
+ * register, putting prior thread_info.regs pointer in a callee-save
+ * register (R24, which had better not ever be assigned to THREADINFO_REG),
+ * and updating thread_info.regs to point to current stack frame,
+ * so as to support nested events in kernel mode.
+ *
+ * As this is common code, we set the pt_regs system call number
+ * to -1 for all events. It will be replaced with the system call
+ * number in the case where we decode a system call (trap0(#1)).
+ */
+
+#define save_pt_regs()\
+ memd(R0 + #_PT_R3130) = R31:30; \
+ { memw(R0 + #_PT_R2928) = R28; \
+ R31 = memw(R0 + #_PT_ER_VMPSP); }\
+ { memw(R0 + #(_PT_R2928 + 4)) = R31; \
+ R31 = ugp; } \
+ { memd(R0 + #_PT_R2726) = R27:26; \
+ R30 = gp ; } \
+ memd(R0 + #_PT_R2524) = R25:24; \
+ memd(R0 + #_PT_R2322) = R23:22; \
+ memd(R0 + #_PT_R2120) = R21:20; \
+ memd(R0 + #_PT_R1918) = R19:18; \
+ memd(R0 + #_PT_R1716) = R17:16; \
+ memd(R0 + #_PT_R1514) = R15:14; \
+ memd(R0 + #_PT_R1312) = R13:12; \
+ { memd(R0 + #_PT_R1110) = R11:10; \
+ R15 = lc0; } \
+ { memd(R0 + #_PT_R0908) = R9:8; \
+ R14 = sa0; } \
+ { memd(R0 + #_PT_R0706) = R7:6; \
+ R13 = lc1; } \
+ { memd(R0 + #_PT_R0504) = R5:4; \
+ R12 = sa1; } \
+ { memd(R0 + #_PT_UGPGP) = R31:30; \
+ R11 = m1; \
+ R2.H = #HI(_THREAD_SIZE); } \
+ { memd(R0 + #_PT_LC0SA0) = R15:14; \
+ R10 = m0; \
+ R2.L = #LO(_THREAD_SIZE); } \
+ { memd(R0 + #_PT_LC1SA1) = R13:12; \
+ R15 = p3:0; \
+ R2 = neg(R2); } \
+ { memd(R0 + #_PT_M1M0) = R11:10; \
+ R14 = usr; \
+ R2 = and(R0,R2); } \
+ { memd(R0 + #_PT_PREDSUSR) = R15:14; \
+ THREADINFO_REG = R2; } \
+ { r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
+ memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
+ R2 = #-1; } \
+ { memw(R0 + #_PT_SYSCALL_NR) = R2; \
+ R30 = #0; }
+
+/*
+ * Restore registers and thread_info.regs state. THREADINFO_REG
+ * is assumed to still be sane, and R24 to have been correctly
+ * preserved. Don't restore R29 (SP) until later.
+ */
+
+#define restore_pt_regs() \
+ { memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
+ R15:14 = memd(R0 + #_PT_PREDSUSR); } \
+ { R11:10 = memd(R0 + #_PT_M1M0); \
+ p3:0 = R15; } \
+ { R13:12 = memd(R0 + #_PT_LC1SA1); \
+ usr = R14; } \
+ { R15:14 = memd(R0 + #_PT_LC0SA0); \
+ m1 = R11; } \
+ { R3:2 = memd(R0 + #_PT_R0302); \
+ m0 = R10; } \
+ { R5:4 = memd(R0 + #_PT_R0504); \
+ lc1 = R13; } \
+ { R7:6 = memd(R0 + #_PT_R0706); \
+ sa1 = R12; } \
+ { R9:8 = memd(R0 + #_PT_R0908); \
+ lc0 = R15; } \
+ { R11:10 = memd(R0 + #_PT_R1110); \
+ sa0 = R14; } \
+ { R13:12 = memd(R0 + #_PT_R1312); \
+ R15:14 = memd(R0 + #_PT_R1514); } \
+ { R17:16 = memd(R0 + #_PT_R1716); \
+ R19:18 = memd(R0 + #_PT_R1918); } \
+ { R21:20 = memd(R0 + #_PT_R2120); \
+ R23:22 = memd(R0 + #_PT_R2322); } \
+ { R25:24 = memd(R0 + #_PT_R2524); \
+ R27:26 = memd(R0 + #_PT_R2726); } \
+ R31:30 = memd(R0 + #_PT_UGPGP); \
+ { R28 = memw(R0 + #_PT_R2928); \
+ ugp = R31; } \
+ { R31:30 = memd(R0 + #_PT_R3130); \
+ gp = R30; }
+
+ /*
+ * Clears off enough space for the rest of pt_regs; evrec is a part
+ * of pt_regs in HVM mode. Save R0/R1, set handler's address in R1.
+ * R0 is the address of pt_regs and is the parameter to save_pt_regs.
+ */
+
+/*
+ * Since the HVM isn't automagically pushing the EVREC onto the stack anymore,
+ * we'll subract the entire size out and then fill it in ourselves.
+ * Need to save off R0, R1, R2, R3 immediately.
+ */
+
+#define vm_event_entry(CHandler) \
+ { \
+ R29 = add(R29, #-(_PT_REGS_SIZE)); \
+ memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \
+ } \
+ { \
+ memd(R29 +#_PT_R0302) = R3:2; \
+ } \
+ trap1(#HVM_TRAP1_VMGETREGS); \
+ { \
+ memd(R29 + #_PT_ER_VMEL) = R1:0; \
+ R0 = R29; \
+ R1.L = #LO(CHandler); \
+ } \
+ { \
+ memd(R29 + #_PT_ER_VMPSP) = R3:2; \
+ R1.H = #HI(CHandler); \
+ jump event_dispatch; \
+ }
+
+.text
+ /*
+ * Do bulk save/restore in one place.
+ * Adds a jump to dispatch latency, but
+ * saves hundreds of bytes.
+ */
+
+event_dispatch:
+ save_pt_regs()
+ callr r1
+
+ /*
+ * If we were in kernel mode, we don't need to check scheduler
+ * or signals if CONFIG_PREEMPT is not set. If set, then it has
+ * to jump to a need_resched kind of block.
+ * BTW, CONFIG_PREEMPT is not supported yet.
+ */
+
+#ifdef CONFIG_PREEMPT
+ R0 = #VM_INT_DISABLE
+ trap1(#HVM_TRAP1_VMSETIE)
+#endif
+
+ /* "Nested control path" -- if the previous mode was kernel */
+ R0 = memw(R29 + #_PT_ER_VMEST);
+ P0 = tstbit(R0, #HVM_VMEST_UM_SFT);
+ if !P0 jump restore_all;
+ /*
+ * Returning from system call, normally coming back from user mode
+ */
+return_from_syscall:
+ /* Disable interrupts while checking TIF */
+ R0 = #VM_INT_DISABLE
+ trap1(#HVM_TRAP1_VMSETIE)
+
+ /*
+ * Coming back from the C-world, our thread info pointer
+ * should be in the designated register (usually R19)
+ */
+ R1.L = #LO(_TIF_ALLWORK_MASK)
+ {
+ R1.H = #HI(_TIF_ALLWORK_MASK);
+ R0 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS);
+ }
+
+ /*
+ * Compare against the "return to userspace" _TIF_WORK_MASK
+ */
+ R1 = and(R1,R0);
+ { P0 = cmp.eq(R1,#0); if (!P0.new) jump:t work_pending;}
+ jump restore_all; /* we're outta here! */
+
+work_pending:
+ {
+ P0 = tstbit(R1, #TIF_NEED_RESCHED);
+ if (!P0.new) jump:nt work_notifysig;
+ }
+ call schedule
+ jump return_from_syscall; /* check for more work */
+
+work_notifysig:
+ /* this is the part that's kind of fuzzy. */
+ R1 = and(R0, #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME));
+ P0 = cmp.eq(R1, #0);
+ if P0 jump restore_all
+ R1 = R0; /* unsigned long thread_info_flags */
+ R0 = R29; /* regs should still be at top of stack */
+ call do_notify_resume
+
+restore_all:
+ /* Disable interrupts, if they weren't already, before reg restore. */
+ R0 = #VM_INT_DISABLE
+ trap1(#HVM_TRAP1_VMSETIE)
+
+ /* do the setregs here for VM 0.5 */
+ /* R29 here should already be pointing at pt_regs */
+ R1:0 = memd(R29 + #_PT_ER_VMEL);
+ R3:2 = memd(R29 + #_PT_ER_VMPSP);
+ trap1(#HVM_TRAP1_VMSETREGS);
+
+ R0 = R29
+ restore_pt_regs()
+ R1:0 = memd(R29 + #_PT_R0100);
+ R29 = add(R29, #_PT_REGS_SIZE);
+ trap1(#HVM_TRAP1_VMRTE)
+ /* Notreached */
+
+ .globl _K_enter_genex
+_K_enter_genex:
+ vm_event_entry(do_genex)
+
+ .globl _K_enter_interrupt
+_K_enter_interrupt:
+ vm_event_entry(arch_do_IRQ)
+
+ .globl _K_enter_trap0
+_K_enter_trap0:
+ vm_event_entry(do_trap0)
+
+ .globl _K_enter_machcheck
+_K_enter_machcheck:
+ vm_event_entry(do_machcheck)
+
+
+ .globl ret_from_fork
+ret_from_fork:
+ call schedule_tail
+ jump return_from_syscall
diff --git a/arch/hexagon/kernel/vm_events.c b/arch/hexagon/kernel/vm_events.c
new file mode 100644
index 000000000000..986a081e32ec
--- /dev/null
+++ b/arch/hexagon/kernel/vm_events.c
@@ -0,0 +1,101 @@
+/*
+ * Mostly IRQ support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <asm/registers.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+#include <asm/system.h>
+
+/*
+ * show_regs - print pt_regs structure
+ * @regs: pointer to pt_regs
+ *
+ * To-do: add all the accessor definitions to registers.h
+ *
+ * Will make this routine a lot easier to write.
+ */
+void show_regs(struct pt_regs *regs)
+{
+ printk(KERN_EMERG "restart_r0: \t0x%08lx syscall_nr: %ld\n",
+ regs->restart_r0, regs->syscall_nr);
+ printk(KERN_EMERG "preds: \t\t0x%08lx\n", regs->preds);
+ printk(KERN_EMERG "lc0: \t0x%08lx sa0: 0x%08lx m0: 0x%08lx\n",
+ regs->lc0, regs->sa0, regs->m0);
+ printk(KERN_EMERG "lc1: \t0x%08lx sa1: 0x%08lx m1: 0x%08lx\n",
+ regs->lc1, regs->sa1, regs->m1);
+ printk(KERN_EMERG "gp: \t0x%08lx ugp: 0x%08lx usr: 0x%08lx\n",
+ regs->gp, regs->ugp, regs->usr);
+ printk(KERN_EMERG "r0: \t0x%08lx %08lx %08lx %08lx\n", regs->r00,
+ regs->r01,
+ regs->r02,
+ regs->r03);
+ printk(KERN_EMERG "r4: \t0x%08lx %08lx %08lx %08lx\n", regs->r04,
+ regs->r05,
+ regs->r06,
+ regs->r07);
+ printk(KERN_EMERG "r8: \t0x%08lx %08lx %08lx %08lx\n", regs->r08,
+ regs->r09,
+ regs->r10,
+ regs->r11);
+ printk(KERN_EMERG "r12: \t0x%08lx %08lx %08lx %08lx\n", regs->r12,
+ regs->r13,
+ regs->r14,
+ regs->r15);
+ printk(KERN_EMERG "r16: \t0x%08lx %08lx %08lx %08lx\n", regs->r16,
+ regs->r17,
+ regs->r18,
+ regs->r19);
+ printk(KERN_EMERG "r20: \t0x%08lx %08lx %08lx %08lx\n", regs->r20,
+ regs->r21,
+ regs->r22,
+ regs->r23);
+ printk(KERN_EMERG "r24: \t0x%08lx %08lx %08lx %08lx\n", regs->r24,
+ regs->r25,
+ regs->r26,
+ regs->r27);
+ printk(KERN_EMERG "r28: \t0x%08lx %08lx %08lx %08lx\n", regs->r28,
+ regs->r29,
+ regs->r30,
+ regs->r31);
+
+ printk(KERN_EMERG "elr: \t0x%08lx cause: 0x%08lx user_mode: %d\n",
+ pt_elr(regs), pt_cause(regs), user_mode(regs));
+ printk(KERN_EMERG "psp: \t0x%08lx badva: 0x%08lx int_enabled: %d\n",
+ pt_psp(regs), pt_badva(regs), ints_enabled(regs));
+}
+
+void dummy_handler(struct pt_regs *regs)
+{
+ unsigned int elr = pt_elr(regs);
+ printk(KERN_ERR "Unimplemented handler; ELR=0x%08x\n", elr);
+}
+
+
+void arch_do_IRQ(struct pt_regs *regs)
+{
+ int irq = pt_cause(regs);
+ struct pt_regs *old_regs = set_irq_regs(regs);
+
+ irq_enter();
+ generic_handle_irq(irq);
+ irq_exit();
+ set_irq_regs(old_regs);
+}
diff --git a/arch/hexagon/kernel/vm_init_segtable.S b/arch/hexagon/kernel/vm_init_segtable.S
new file mode 100644
index 000000000000..aebb35b6465e
--- /dev/null
+++ b/arch/hexagon/kernel/vm_init_segtable.S
@@ -0,0 +1,442 @@
+/*
+ * Initial page table for Linux kernel under Hexagon VM,
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * These tables are pre-computed and linked into kernel.
+ */
+
+#include <asm/vm_mmu.h>
+/* #include <asm/iomap.h> */
+
+/*
+ * Start with mapping PA=0 to both VA=0x0 and VA=0xc000000 as 16MB large pages.
+ * No user mode access, RWX, write-back cache. The entry needs
+ * to be replicated for all 4 virtual segments mapping to the page.
+ */
+
+/* "Big Kernel Page" */
+#define BKP(pa) (((pa) & __HVM_PTE_PGMASK_4MB) \
+ | __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+ | __HEXAGON_C_WB_L2 << 6 \
+ | __HVM_PDE_S_16MB)
+
+/* No cache version */
+
+#define BKPG_IO(pa) (((pa) & __HVM_PTE_PGMASK_16MB) \
+ | __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+ | __HVM_PDE_S_16MB | __HEXAGON_C_DEV << 6 )
+
+#define FOURK_IO(pa) (((pa) & __HVM_PTE_PGMASK_4KB) \
+ | __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+ | __HEXAGON_C_DEV << 6 )
+
+#define L2_PTR(pa) (((pa) & __HVM_PTE_PGMASK_4KB) \
+ | __HVM_PDE_S_4KB )
+
+#define X __HVM_PDE_S_INVALID
+
+ .p2align 12
+ .globl swapper_pg_dir
+ .globl _K_init_segtable
+swapper_pg_dir:
+/* VA 0x00000000 */
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/* VA 0x40000000 */
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/* VA 0x80000000 */
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/*0xa8*/.word X,X,X,X
+#ifdef CONFIG_COMET_EARLY_UART_DEBUG
+UART_PTE_ENTRY:
+/*0xa9*/.word BKPG_IO(0xa9000000),BKPG_IO(0xa9000000),BKPG_IO(0xa9000000),BKPG_IO(0xa9000000)
+#else
+/*0xa9*/.word X,X,X,X
+#endif
+/*0xaa*/.word X,X,X,X
+/*0xab*/.word X,X,X,X
+/*0xac*/.word X,X,X,X
+/*0xad*/.word X,X,X,X
+/*0xae*/.word X,X,X,X
+/*0xaf*/.word X,X,X,X
+/*0xb0*/.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+ .word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+_K_init_segtable:
+/* VA 0xC0000000 */
+ .word BKP(0x00000000), BKP(0x00400000), BKP(0x00800000), BKP(0x00c00000)
+ .word BKP(0x01000000), BKP(0x01400000), BKP(0x01800000), BKP(0x01c00000)
+ .word BKP(0x02000000), BKP(0x02400000), BKP(0x02800000), BKP(0x02c00000)
+ .word BKP(0x03000000), BKP(0x03400000), BKP(0x03800000), BKP(0x03c00000)
+ .word BKP(0x04000000), BKP(0x04400000), BKP(0x04800000), BKP(0x04c00000)
+ .word BKP(0x05000000), BKP(0x05400000), BKP(0x05800000), BKP(0x05c00000)
+ .word BKP(0x06000000), BKP(0x06400000), BKP(0x06800000), BKP(0x06c00000)
+ .word BKP(0x07000000), BKP(0x07400000), BKP(0x07800000), BKP(0x07c00000)
+
+ .word BKP(0x08000000), BKP(0x08400000), BKP(0x08800000), BKP(0x08c00000)
+ .word BKP(0x09000000), BKP(0x09400000), BKP(0x09800000), BKP(0x09c00000)
+ .word BKP(0x0a000000), BKP(0x0a400000), BKP(0x0a800000), BKP(0x0ac00000)
+ .word BKP(0x0b000000), BKP(0x0b400000), BKP(0x0b800000), BKP(0x0bc00000)
+ .word BKP(0x0c000000), BKP(0x0c400000), BKP(0x0c800000), BKP(0x0cc00000)
+ .word BKP(0x0d000000), BKP(0x0d400000), BKP(0x0d800000), BKP(0x0dc00000)
+ .word BKP(0x0e000000), BKP(0x0e400000), BKP(0x0e800000), BKP(0x0ec00000)
+ .word BKP(0x0f000000), BKP(0x0f400000), BKP(0x0f800000), BKP(0x0fc00000)
+
+ .word BKP(0x10000000), BKP(0x10400000), BKP(0x10800000), BKP(0x10c00000)
+ .word BKP(0x11000000), BKP(0x11400000), BKP(0x11800000), BKP(0x11c00000)
+ .word BKP(0x12000000), BKP(0x12400000), BKP(0x12800000), BKP(0x12c00000)
+ .word BKP(0x13000000), BKP(0x13400000), BKP(0x13800000), BKP(0x13c00000)
+ .word BKP(0x14000000), BKP(0x14400000), BKP(0x14800000), BKP(0x14c00000)
+ .word BKP(0x15000000), BKP(0x15400000), BKP(0x15800000), BKP(0x15c00000)
+ .word BKP(0x16000000), BKP(0x16400000), BKP(0x16800000), BKP(0x16c00000)
+ .word BKP(0x17000000), BKP(0x17400000), BKP(0x17800000), BKP(0x17c00000)
+
+ .word BKP(0x18000000), BKP(0x18400000), BKP(0x18800000), BKP(0x18c00000)
+ .word BKP(0x19000000), BKP(0x19400000), BKP(0x19800000), BKP(0x19c00000)
+ .word BKP(0x1a000000), BKP(0x1a400000), BKP(0x1a800000), BKP(0x1ac00000)
+ .word BKP(0x1b000000), BKP(0x1b400000), BKP(0x1b800000), BKP(0x1bc00000)
+ .word BKP(0x1c000000), BKP(0x1c400000), BKP(0x1c800000), BKP(0x1cc00000)
+ .word BKP(0x1d000000), BKP(0x1d400000), BKP(0x1d800000), BKP(0x1dc00000)
+ .word BKP(0x1e000000), BKP(0x1e400000), BKP(0x1e800000), BKP(0x1ec00000)
+ .word BKP(0x1f000000), BKP(0x1f400000), BKP(0x1f800000), BKP(0x1fc00000)
+
+ .word BKP(0x20000000), BKP(0x20400000), BKP(0x20800000), BKP(0x20c00000)
+ .word BKP(0x21000000), BKP(0x21400000), BKP(0x21800000), BKP(0x21c00000)
+ .word BKP(0x22000000), BKP(0x22400000), BKP(0x22800000), BKP(0x22c00000)
+ .word BKP(0x23000000), BKP(0x23400000), BKP(0x23800000), BKP(0x23c00000)
+ .word BKP(0x24000000), BKP(0x24400000), BKP(0x24800000), BKP(0x24c00000)
+ .word BKP(0x25000000), BKP(0x25400000), BKP(0x25800000), BKP(0x25c00000)
+ .word BKP(0x26000000), BKP(0x26400000), BKP(0x26800000), BKP(0x26c00000)
+ .word BKP(0x27000000), BKP(0x27400000), BKP(0x27800000), BKP(0x27c00000)
+
+ .word BKP(0x28000000), BKP(0x28400000), BKP(0x28800000), BKP(0x28c00000)
+ .word BKP(0x29000000), BKP(0x29400000), BKP(0x29800000), BKP(0x29c00000)
+ .word BKP(0x2a000000), BKP(0x2a400000), BKP(0x2a800000), BKP(0x2ac00000)
+ .word BKP(0x2b000000), BKP(0x2b400000), BKP(0x2b800000), BKP(0x2bc00000)
+ .word BKP(0x2c000000), BKP(0x2c400000), BKP(0x2c800000), BKP(0x2cc00000)
+ .word BKP(0x2d000000), BKP(0x2d400000), BKP(0x2d800000), BKP(0x2dc00000)
+ .word BKP(0x2e000000), BKP(0x2e400000), BKP(0x2e800000), BKP(0x2ec00000)
+ .word BKP(0x2f000000), BKP(0x2f400000), BKP(0x2f800000), BKP(0x2fc00000)
+
+ .word BKP(0x30000000), BKP(0x30400000), BKP(0x30800000), BKP(0x30c00000)
+ .word BKP(0x31000000), BKP(0x31400000), BKP(0x31800000), BKP(0x31c00000)
+ .word BKP(0x32000000), BKP(0x32400000), BKP(0x32800000), BKP(0x32c00000)
+ .word BKP(0x33000000), BKP(0x33400000), BKP(0x33800000), BKP(0x33c00000)
+ .word BKP(0x34000000), BKP(0x34400000), BKP(0x34800000), BKP(0x34c00000)
+ .word BKP(0x35000000), BKP(0x35400000), BKP(0x35800000), BKP(0x35c00000)
+ .word BKP(0x36000000), BKP(0x36400000), BKP(0x36800000), BKP(0x36c00000)
+ .word BKP(0x37000000), BKP(0x37400000), BKP(0x37800000), BKP(0x37c00000)
+
+ .word BKP(0x38000000), BKP(0x38400000), BKP(0x38800000), BKP(0x38c00000)
+ .word BKP(0x39000000), BKP(0x39400000), BKP(0x39800000), BKP(0x39c00000)
+ .word BKP(0x3a000000), BKP(0x3a400000), BKP(0x3a800000), BKP(0x3ac00000)
+ .word BKP(0x3b000000), BKP(0x3b400000), BKP(0x3b800000), BKP(0x3bc00000)
+ .word BKP(0x3c000000), BKP(0x3c400000), BKP(0x3c800000), BKP(0x3cc00000)
+ .word BKP(0x3d000000), BKP(0x3d400000), BKP(0x3d800000), BKP(0x3dc00000)
+_K_io_map:
+ .word X,X,X,X /* 0x3e000000 - device IO early remap */
+ .word X,X,X,X /* 0x3f000000 - hypervisor space*/
+
+#if 0
+/*
+ * This is in here as an example for devices which need to be mapped really
+ * early.
+ */
+ .p2align 12
+ .globl _K_io_kmap
+ .globl _K_init_devicetable
+_K_init_devicetable: /* Should be 4MB worth of entries */
+ .word FOURK_IO(MSM_GPIO1_PHYS),FOURK_IO(MSM_GPIO2_PHYS),FOURK_IO(MSM_SIRC_PHYS),X
+ .word FOURK_IO(TLMM_GPIO1_PHYS),X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+ .word X,X,X,X
+#endif
diff --git a/arch/hexagon/kernel/vm_ops.S b/arch/hexagon/kernel/vm_ops.S
new file mode 100644
index 000000000000..24d7fcac4ff2
--- /dev/null
+++ b/arch/hexagon/kernel/vm_ops.S
@@ -0,0 +1,102 @@
+/*
+ * Hexagon VM instruction support
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * C wrappers for virtual machine "instructions". These
+ * could be, and perhaps some day will be, handled as in-line
+ * macros, but for tracing/debugging it's handy to have
+ * a single point of invocation for each of them.
+ * Conveniently, they take paramters and return values
+ * consistent with the ABI calling convention.
+ */
+
+ENTRY(__vmrte)
+ trap1(#HVM_TRAP1_VMRTE);
+ jumpr R31;
+
+ENTRY(__vmsetvec)
+ trap1(#HVM_TRAP1_VMSETVEC);
+ jumpr R31;
+
+ENTRY(__vmsetie)
+ trap1(#HVM_TRAP1_VMSETIE);
+ jumpr R31;
+
+ENTRY(__vmgetie)
+ trap1(#HVM_TRAP1_VMGETIE);
+ jumpr R31;
+
+ENTRY(__vmintop)
+ trap1(#HVM_TRAP1_VMINTOP);
+ jumpr R31;
+
+ENTRY(__vmclrmap)
+ trap1(#HVM_TRAP1_VMCLRMAP);
+ jumpr R31;
+
+ENTRY(__vmnewmap)
+ r1 = #VM_NEWMAP_TYPE_PGTABLES;
+ trap1(#HVM_TRAP1_VMNEWMAP);
+ jumpr R31;
+
+ENTRY(__vmcache)
+ trap1(#HVM_TRAP1_VMCACHE);
+ jumpr R31;
+
+ENTRY(__vmgettime)
+ trap1(#HVM_TRAP1_VMGETTIME);
+ jumpr R31;
+
+ENTRY(__vmsettime)
+ trap1(#HVM_TRAP1_VMSETTIME);
+ jumpr R31;
+
+ENTRY(__vmwait)
+ trap1(#HVM_TRAP1_VMWAIT);
+ jumpr R31;
+
+ENTRY(__vmyield)
+ trap1(#HVM_TRAP1_VMYIELD);
+ jumpr R31;
+
+ENTRY(__vmstart)
+ trap1(#HVM_TRAP1_VMSTART);
+ jumpr R31;
+
+ENTRY(__vmstop)
+ trap1(#HVM_TRAP1_VMSTOP);
+ jumpr R31;
+
+ENTRY(__vmvpid)
+ trap1(#HVM_TRAP1_VMVPID);
+ jumpr R31;
+
+/* Probably not actually going to use these; see vm_entry.S */
+
+ENTRY(__vmsetregs)
+ trap1(#HVM_TRAP1_VMSETREGS);
+ jumpr R31;
+
+ENTRY(__vmgetregs)
+ trap1(#HVM_TRAP1_VMGETREGS);
+ jumpr R31;
diff --git a/arch/hexagon/kernel/vm_switch.S b/arch/hexagon/kernel/vm_switch.S
new file mode 100644
index 000000000000..0decf2f58e32
--- /dev/null
+++ b/arch/hexagon/kernel/vm_switch.S
@@ -0,0 +1,95 @@
+/*
+ * Context switch support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/asm-offsets.h>
+
+.text
+
+/*
+ * The register used as a fast-path thread information pointer
+ * is determined as a kernel configuration option. If it happens
+ * to be a callee-save register, we're going to be saving and
+ * restoring it twice here.
+ *
+ * This code anticipates a revised ABI where R20-23 are added
+ * to the set of callee-save registers, but this should be
+ * backward compatible to legacy tools.
+ */
+
+
+/*
+ * void switch_to(struct task_struct *prev,
+ * struct task_struct *next, struct task_struct *last);
+ */
+ .p2align 2
+ .globl __switch_to
+ .type __switch_to, @function
+
+/*
+ * When we exit the wormhole, we need to store the previous task
+ * in the new R0's pointer. Technically it should be R2, but they should
+ * be the same; seems like a legacy thing. In short, don't butcher
+ * R0, let it go back out unmolested.
+ */
+
+__switch_to:
+ /*
+ * Push callee-saves onto "prev" stack.
+ * Here, we're sneaky because the LR and FP
+ * storage of the thread_stack structure
+ * is automagically allocated by allocframe,
+ * so we pass struct size less 8.
+ */
+ allocframe(#(_SWITCH_STACK_SIZE - 8));
+ memd(R29+#(_SWITCH_R2726))=R27:26;
+ memd(R29+#(_SWITCH_R2524))=R25:24;
+ memd(R29+#(_SWITCH_R2322))=R23:22;
+ memd(R29+#(_SWITCH_R2120))=R21:20;
+ memd(R29+#(_SWITCH_R1918))=R19:18;
+ memd(R29+#(_SWITCH_R1716))=R17:16;
+ /* Stash thread_info pointer in task_struct */
+ memw(R0+#_TASK_THREAD_INFO) = THREADINFO_REG;
+ memw(R0 +#(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP)) = R29;
+ /* Switch to "next" stack and restore callee saves from there */
+ R29 = memw(R1 + #(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP));
+ {
+ R27:26 = memd(R29+#(_SWITCH_R2726));
+ R25:24 = memd(R29+#(_SWITCH_R2524));
+ }
+ {
+ R23:22 = memd(R29+#(_SWITCH_R2322));
+ R21:20 = memd(R29+#(_SWITCH_R2120));
+ }
+ {
+ R19:18 = memd(R29+#(_SWITCH_R1918));
+ R17:16 = memd(R29+#(_SWITCH_R1716));
+ }
+ {
+ /* THREADINFO_REG is currently one of the callee-saved regs
+ * above, and so be sure to re-load it last.
+ */
+ THREADINFO_REG = memw(R1 + #_TASK_THREAD_INFO);
+ R31:30 = memd(R29+#_SWITCH_FP);
+ }
+ {
+ R29 = add(R29,#_SWITCH_STACK_SIZE);
+ jumpr R31;
+ }
+ .size __switch_to, .-__switch_to
diff --git a/arch/hexagon/kernel/vm_vectors.S b/arch/hexagon/kernel/vm_vectors.S
new file mode 100644
index 000000000000..97a4b50b00df
--- /dev/null
+++ b/arch/hexagon/kernel/vm_vectors.S
@@ -0,0 +1,48 @@
+/*
+ * Event jump tables
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/hexagon_vm.h>
+
+.text
+
+/* This is registered early on to allow angel */
+.global _K_provisional_vec
+_K_provisional_vec:
+ jump 1f;
+ jump 1f;
+ jump 1f;
+ jump 1f;
+ jump 1f;
+ trap1(#HVM_TRAP1_VMRTE)
+ jump 1f;
+ jump 1f;
+
+
+.global _K_VM_event_vector
+_K_VM_event_vector:
+1:
+ jump 1b; /* Reset */
+ jump _K_enter_machcheck;
+ jump _K_enter_genex;
+ jump 1b; /* 3 Rsvd */
+ jump 1b; /* 4 Rsvd */
+ jump _K_enter_trap0;
+ jump 1b; /* 6 Rsvd */
+ jump _K_enter_interrupt;
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..071d3c30edfb
--- /dev/null
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -0,0 +1,88 @@
+/*
+ * Linker script for Hexagon kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define LOAD_OFFSET PAGE_OFFSET
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/asm-offsets.h> /* Most of the kernel defines are here */
+#include <asm/mem-layout.h> /* except for page_offset */
+#include <asm/cache.h> /* and now we're pulling cache line size */
+OUTPUT_ARCH(hexagon)
+ENTRY(stext)
+
+jiffies = jiffies_64;
+
+/*
+See asm-generic/vmlinux.lds.h for expansion of some of these macros.
+See asm-generic/sections.h for seemingly required labels.
+*/
+
+#define PAGE_SIZE _PAGE_SIZE
+
+/* This LOAD_OFFSET is temporary for debugging on the simulator; it may change
+ for hypervisor pseudo-physical memory. */
+
+
+SECTIONS
+{
+ . = PAGE_OFFSET + LOAD_ADDRESS;
+
+ __init_begin = .;
+ HEAD_TEXT_SECTION
+ INIT_TEXT_SECTION(PAGE_SIZE)
+ PERCPU_SECTION(L1_CACHE_BYTES)
+ __init_end = .;
+
+ . = ALIGN(_PAGE_SIZE);
+ _stext = .;
+ .text : AT(ADDR(.text) - LOAD_OFFSET) {
+ _text = .;
+ TEXT_TEXT
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ *(.fixup)
+ }
+ _etext = .;
+
+ INIT_DATA_SECTION(PAGE_SIZE)
+
+ _sdata = .;
+ RW_DATA_SECTION(32,PAGE_SIZE,PAGE_SIZE)
+ RO_DATA_SECTION(PAGE_SIZE)
+ _edata = .;
+
+ EXCEPTION_TABLE(16)
+ NOTES
+
+ BSS_SECTION(_PAGE_SIZE, _PAGE_SIZE, _PAGE_SIZE)
+
+ _end = .;
+
+ /DISCARD/ : {
+ EXIT_TEXT
+ EXIT_DATA
+ EXIT_CALL
+ }
+
+ STABS_DEBUG
+ DWARF_DEBUG
+
+}
diff --git a/arch/hexagon/lib/Makefile b/arch/hexagon/lib/Makefile
new file mode 100644
index 000000000000..874655e85671
--- /dev/null
+++ b/arch/hexagon/lib/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for hexagon-specific library files.
+#
+obj-y = checksum.o io.o memcpy.o memset.o
diff --git a/arch/hexagon/lib/checksum.c b/arch/hexagon/lib/checksum.c
new file mode 100644
index 000000000000..93005522d52b
--- /dev/null
+++ b/arch/hexagon/lib/checksum.c
@@ -0,0 +1,203 @@
+/*
+ * Checksum functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* This was derived from arch/alpha/lib/checksum.c */
+
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/byteorder.h>
+#include <net/checksum.h>
+#include <linux/uaccess.h>
+#include <asm/intrinsics.h>
+
+
+/* Vector value operations */
+#define SIGN(x, y) ((0x8000ULL*x)<<y)
+#define CARRY(x, y) ((0x0002ULL*x)<<y)
+#define SELECT(x, y) ((0x0001ULL*x)<<y)
+
+#define VR_NEGATE(a, b, c, d) (SIGN(a, 48) + SIGN(b, 32) + SIGN(c, 16) \
+ + SIGN(d, 0))
+#define VR_CARRY(a, b, c, d) (CARRY(a, 48) + CARRY(b, 32) + CARRY(c, 16) \
+ + CARRY(d, 0))
+#define VR_SELECT(a, b, c, d) (SELECT(a, 48) + SELECT(b, 32) + SELECT(c, 16) \
+ + SELECT(d, 0))
+
+
+/* optimized HEXAGON V3 intrinsic version */
+static inline unsigned short from64to16(u64 x)
+{
+ u64 sum;
+
+ sum = HEXAGON_P_vrmpyh_PP(x^VR_NEGATE(1, 1, 1, 1),
+ VR_SELECT(1, 1, 1, 1));
+ sum += VR_CARRY(0, 0, 1, 0);
+ sum = HEXAGON_P_vrmpyh_PP(sum, VR_SELECT(0, 0, 1, 1));
+
+ return 0xFFFF & sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented.
+ */
+__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+ unsigned short len, unsigned short proto,
+ __wsum sum)
+{
+ return (__force __sum16)~from64to16(
+ (__force u64)saddr + (__force u64)daddr +
+ (__force u64)sum + ((len + proto) << 8));
+}
+
+__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+ unsigned short len, unsigned short proto,
+ __wsum sum)
+{
+ u64 result;
+
+ result = (__force u64)saddr + (__force u64)daddr +
+ (__force u64)sum + ((len + proto) << 8);
+
+ /* Fold down to 32-bits so we don't lose in the typedef-less
+ network stack. */
+ /* 64 to 33 */
+ result = (result & 0xffffffffUL) + (result >> 32);
+ /* 33 to 32 */
+ result = (result & 0xffffffffUL) + (result >> 32);
+ return (__force __wsum)result;
+}
+EXPORT_SYMBOL(csum_tcpudp_nofold);
+
+/*
+ * Do a 64-bit checksum on an arbitrary memory area..
+ *
+ * This isn't a great routine, but it's not _horrible_ either. The
+ * inner loop could be unrolled a bit further, and there are better
+ * ways to do the carry, but this is reasonable.
+ */
+
+/* optimized HEXAGON intrinsic version, with over read fixed */
+unsigned int do_csum(const void *voidptr, int len)
+{
+ u64 sum0, sum1, x0, x1, *ptr8_o, *ptr8_e, *ptr8;
+ int i, start, mid, end, mask;
+ const char *ptr = voidptr;
+ unsigned short *ptr2;
+ unsigned int *ptr4;
+
+ if (len <= 0)
+ return 0;
+
+ start = 0xF & (16-(((int) ptr) & 0xF)) ;
+ mask = 0x7fffffffUL >> HEXAGON_R_cl0_R(len);
+ start = start & mask ;
+
+ mid = len - start;
+ end = mid & 0xF;
+ mid = mid>>4;
+ sum0 = mid << 18;
+ sum1 = 0;
+
+ if (start & 1)
+ sum0 += (u64) (ptr[0] << 8);
+ ptr2 = (unsigned short *) &ptr[start & 1];
+ if (start & 2)
+ sum1 += (u64) ptr2[0];
+ ptr4 = (unsigned int *) &ptr[start & 3];
+ if (start & 4) {
+ sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+ VR_NEGATE(0, 0, 1, 1)^((u64)ptr4[0]),
+ VR_SELECT(0, 0, 1, 1));
+ sum0 += VR_SELECT(0, 0, 1, 0);
+ }
+ ptr8 = (u64 *) &ptr[start & 7];
+ if (start & 8) {
+ sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+ VR_NEGATE(1, 1, 1, 1)^(ptr8[0]),
+ VR_SELECT(1, 1, 1, 1));
+ sum1 += VR_CARRY(0, 0, 1, 0);
+ }
+ ptr8_o = (u64 *) (ptr + start);
+ ptr8_e = (u64 *) (ptr + start + 8);
+
+ if (mid) {
+ x0 = *ptr8_e; ptr8_e += 2;
+ x1 = *ptr8_o; ptr8_o += 2;
+ if (mid > 1)
+ for (i = 0; i < mid-1; i++) {
+ sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+ x0^VR_NEGATE(1, 1, 1, 1),
+ VR_SELECT(1, 1, 1, 1));
+ sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+ x1^VR_NEGATE(1, 1, 1, 1),
+ VR_SELECT(1, 1, 1, 1));
+ x0 = *ptr8_e; ptr8_e += 2;
+ x1 = *ptr8_o; ptr8_o += 2;
+ }
+ sum0 = HEXAGON_P_vrmpyhacc_PP(sum0, x0^VR_NEGATE(1, 1, 1, 1),
+ VR_SELECT(1, 1, 1, 1));
+ sum1 = HEXAGON_P_vrmpyhacc_PP(sum1, x1^VR_NEGATE(1, 1, 1, 1),
+ VR_SELECT(1, 1, 1, 1));
+ }
+
+ ptr4 = (unsigned int *) &ptr[start + (mid * 16) + (end & 8)];
+ if (end & 4) {
+ sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+ VR_NEGATE(0, 0, 1, 1)^((u64)ptr4[0]),
+ VR_SELECT(0, 0, 1, 1));
+ sum1 += VR_SELECT(0, 0, 1, 0);
+ }
+ ptr2 = (unsigned short *) &ptr[start + (mid * 16) + (end & 12)];
+ if (end & 2)
+ sum0 += (u64) ptr2[0];
+
+ if (end & 1)
+ sum1 += (u64) ptr[start + (mid * 16) + (end & 14)];
+
+ ptr8 = (u64 *) &ptr[start + (mid * 16)];
+ if (end & 8) {
+ sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+ VR_NEGATE(1, 1, 1, 1)^(ptr8[0]),
+ VR_SELECT(1, 1, 1, 1));
+ sum0 += VR_CARRY(0, 0, 1, 0);
+ }
+ sum0 = HEXAGON_P_vrmpyh_PP((sum0+sum1)^VR_NEGATE(0, 0, 0, 1),
+ VR_SELECT(0, 0, 1, 1));
+ sum0 += VR_NEGATE(0, 0, 0, 1);
+ sum0 = HEXAGON_P_vrmpyh_PP(sum0, VR_SELECT(0, 0, 1, 1));
+
+ if (start & 1)
+ sum0 = (sum0 << 8) | (0xFF & (sum0 >> 8));
+
+ return 0xFFFF & sum0;
+}
+
+/*
+ * copy from ds while checksumming, otherwise like csum_partial
+ */
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
+{
+ memcpy(dst, src, len);
+ return csum_partial(dst, len, sum);
+}
diff --git a/arch/hexagon/lib/io.c b/arch/hexagon/lib/io.c
new file mode 100644
index 000000000000..8ae47ba0e705
--- /dev/null
+++ b/arch/hexagon/lib/io.c
@@ -0,0 +1,91 @@
+/*
+ * I/O access functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/io.h>
+
+/* These are all FIFO routines! */
+
+/*
+ * __raw_readsw - read words a short at a time
+ * @addr: source address
+ * @data: data address
+ * @len: number of shorts to read
+ */
+void __raw_readsw(const void __iomem *addr, void *data, int len)
+{
+ const volatile short int *src = (short int *) addr;
+ short int *dst = (short int *) data;
+
+ if ((u32)data & 0x1)
+ panic("unaligned pointer to readsw");
+
+ while (len-- > 0)
+ *dst++ = *src;
+
+}
+
+/*
+ * __raw_writesw - read words a short at a time
+ * @addr: source address
+ * @data: data address
+ * @len: number of shorts to read
+ */
+void __raw_writesw(void __iomem *addr, const void *data, int len)
+{
+ const short int *src = (short int *)data;
+ volatile short int *dst = (short int *)addr;
+
+ if ((u32)data & 0x1)
+ panic("unaligned pointer to writesw");
+
+ while (len-- > 0)
+ *dst = *src++;
+
+
+}
+
+/* Pretty sure len is pre-adjusted for the length of the access already */
+void __raw_readsl(const void __iomem *addr, void *data, int len)
+{
+ const volatile long *src = (long *) addr;
+ long *dst = (long *) data;
+
+ if ((u32)data & 0x3)
+ panic("unaligned pointer to readsl");
+
+ while (len-- > 0)
+ *dst++ = *src;
+
+
+}
+
+void __raw_writesl(void __iomem *addr, const void *data, int len)
+{
+ const long *src = (long *)data;
+ volatile long *dst = (long *)addr;
+
+ if ((u32)data & 0x3)
+ panic("unaligned pointer to writesl");
+
+ while (len-- > 0)
+ *dst = *src++;
+
+
+}
diff --git a/arch/hexagon/lib/memcpy.S b/arch/hexagon/lib/memcpy.S
new file mode 100644
index 000000000000..2101c3395665
--- /dev/null
+++ b/arch/hexagon/lib/memcpy.S
@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Description
+ *
+ * library function for memcpy where length bytes are copied from
+ * ptr_in to ptr_out. ptr_out is returned unchanged.
+ * Allows any combination of alignment on input and output pointers
+ * and length from 0 to 2^32-1
+ *
+ * Restrictions
+ * The arrays should not overlap, the program will produce undefined output
+ * if they do.
+ * For blocks less than 16 bytes a byte by byte copy is performed. For
+ * 8byte alignments, and length multiples, a dword copy is performed up to
+ * 96bytes
+ * History
+ *
+ * DJH 5/15/09 Initial version 1.0
+ * DJH 6/ 1/09 Version 1.1 modified ABI to inlcude R16-R19
+ * DJH 7/12/09 Version 1.2 optimized codesize down to 760 was 840
+ * DJH 10/14/09 Version 1.3 added special loop for aligned case, was
+ * overreading bloated codesize back up to 892
+ * DJH 4/20/10 Version 1.4 fixed Ldword_loop_epilog loop to prevent loads
+ * occuring if only 1 left outstanding, fixes bug
+ * # 3888, corrected for all alignments. Peeled off
+ * 1 32byte chunk from kernel loop and extended 8byte
+ * loop at end to solve all combinations and prevent
+ * over read. Fixed Ldword_loop_prolog to prevent
+ * overread for blocks less than 48bytes. Reduced
+ * codesize to 752 bytes
+ * DJH 4/21/10 version 1.5 1.4 fix broke code for input block ends not
+ * aligned to dword boundaries,underwriting by 1
+ * byte, added detection for this and fixed. A
+ * little bloat.
+ * DJH 4/23/10 version 1.6 corrected stack error, R20 was not being restored
+ * always, fixed the error of R20 being modified
+ * before it was being saved
+ * Natural c model
+ * ===============
+ * void * memcpy(char * ptr_out, char * ptr_in, int length) {
+ * int i;
+ * if(length) for(i=0; i < length; i++) { ptr_out[i] = ptr_in[i]; }
+ * return(ptr_out);
+ * }
+ *
+ * Optimized memcpy function
+ * =========================
+ * void * memcpy(char * ptr_out, char * ptr_in, int len) {
+ * int i, prolog, kernel, epilog, mask;
+ * u8 offset;
+ * s64 data0, dataF8, data70;
+ *
+ * s64 * ptr8_in;
+ * s64 * ptr8_out;
+ * s32 * ptr4;
+ * s16 * ptr2;
+ *
+ * offset = ((int) ptr_in) & 7;
+ * ptr8_in = (s64 *) &ptr_in[-offset]; //read in the aligned pointers
+ *
+ * data70 = *ptr8_in++;
+ * dataF8 = *ptr8_in++;
+ *
+ * data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *
+ * prolog = 32 - ((int) ptr_out);
+ * mask = 0x7fffffff >> HEXAGON_R_cl0_R(len);
+ * prolog = prolog & mask;
+ * kernel = len - prolog;
+ * epilog = kernel & 0x1F;
+ * kernel = kernel>>5;
+ *
+ * if (prolog & 1) { ptr_out[0] = (u8) data0; data0 >>= 8; ptr_out += 1;}
+ * ptr2 = (s16 *) &ptr_out[0];
+ * if (prolog & 2) { ptr2[0] = (u16) data0; data0 >>= 16; ptr_out += 2;}
+ * ptr4 = (s32 *) &ptr_out[0];
+ * if (prolog & 4) { ptr4[0] = (u32) data0; data0 >>= 32; ptr_out += 4;}
+ *
+ * offset = offset + (prolog & 7);
+ * if (offset >= 8) {
+ * data70 = dataF8;
+ * dataF8 = *ptr8_in++;
+ * }
+ * offset = offset & 0x7;
+ *
+ * prolog = prolog >> 3;
+ * if (prolog) for (i=0; i < prolog; i++) {
+ * data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ * ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ * data70 = dataF8;
+ * dataF8 = *ptr8_in++;
+ * }
+ * if(kernel) { kernel -= 1; epilog += 32; }
+ * if(kernel) for(i=0; i < kernel; i++) {
+ * data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ * ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ * data70 = *ptr8_in++;
+ *
+ * data0 = HEXAGON_P_valignb_PPp(data70, dataF8, offset);
+ * ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ * dataF8 = *ptr8_in++;
+ *
+ * data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ * ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ * data70 = *ptr8_in++;
+ *
+ * data0 = HEXAGON_P_valignb_PPp(data70, dataF8, offset);
+ * ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ * dataF8 = *ptr8_in++;
+ * }
+ * epilogdws = epilog >> 3;
+ * if (epilogdws) for (i=0; i < epilogdws; i++) {
+ * data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ * ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ * data70 = dataF8;
+ * dataF8 = *ptr8_in++;
+ * }
+ * data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *
+ * ptr4 = (s32 *) &ptr_out[0];
+ * if (epilog & 4) { ptr4[0] = (u32) data0; data0 >>= 32; ptr_out += 4;}
+ * ptr2 = (s16 *) &ptr_out[0];
+ * if (epilog & 2) { ptr2[0] = (u16) data0; data0 >>= 16; ptr_out += 2;}
+ * if (epilog & 1) { *ptr_out++ = (u8) data0; }
+ *
+ * return(ptr_out - length);
+ * }
+ *
+ * Codesize : 784 bytes
+ */
+
+
+#define ptr_out R0 /* destination pounter */
+#define ptr_in R1 /* source pointer */
+#define len R2 /* length of copy in bytes */
+
+#define data70 R13:12 /* lo 8 bytes of non-aligned transfer */
+#define dataF8 R11:10 /* hi 8 bytes of non-aligned transfer */
+#define ldata0 R7:6 /* even 8 bytes chunks */
+#define ldata1 R25:24 /* odd 8 bytes chunks */
+#define data1 R7 /* lower 8 bytes of ldata1 */
+#define data0 R6 /* lower 8 bytes of ldata0 */
+
+#define ifbyte p0 /* if transfer has bytes in epilog/prolog */
+#define ifhword p0 /* if transfer has shorts in epilog/prolog */
+#define ifword p0 /* if transfer has words in epilog/prolog */
+#define noprolog p0 /* no prolog, xfer starts at 32byte */
+#define nokernel p1 /* no 32byte multiple block in the transfer */
+#define noepilog p0 /* no epilog, xfer ends on 32byte boundary */
+#define align p2 /* alignment of input rel to 8byte boundary */
+#define kernel1 p0 /* kernel count == 1 */
+
+#define dalign R25 /* rel alignment of input to output data */
+#define star3 R16 /* number bytes in prolog - dwords */
+#define rest R8 /* length - prolog bytes */
+#define back R7 /* nr bytes > dword boundary in src block */
+#define epilog R3 /* bytes in epilog */
+#define inc R15:14 /* inc kernel by -1 and defetch ptr by 32 */
+#define kernel R4 /* number of 32byte chunks in kernel */
+#define ptr_in_p_128 R5 /* pointer for prefetch of input data */
+#define mask R8 /* mask used to determine prolog size */
+#define shift R8 /* used to work a shifter to extract bytes */
+#define shift2 R5 /* in epilog to workshifter to extract bytes */
+#define prolog R15 /* bytes in prolog */
+#define epilogdws R15 /* number dwords in epilog */
+#define shiftb R14 /* used to extract bytes */
+#define offset R9 /* same as align in reg */
+#define ptr_out_p_32 R17 /* pointer to output dczero */
+#define align888 R14 /* if simple dword loop can be used */
+#define len8 R9 /* number of dwords in length */
+#define over R20 /* nr of bytes > last inp buf dword boundary */
+
+#define ptr_in_p_128kernel R5:4 /* packed fetch pointer & kernel cnt */
+
+ .section .text
+ .p2align 4
+ .global memcpy
+ .type memcpy, @function
+memcpy:
+{
+ p2 = cmp.eq(len, #0); /* =0 */
+ align888 = or(ptr_in, ptr_out); /* %8 < 97 */
+ p0 = cmp.gtu(len, #23); /* %1, <24 */
+ p1 = cmp.eq(ptr_in, ptr_out); /* attempt to overwrite self */
+}
+{
+ p1 = or(p2, p1);
+ p3 = cmp.gtu(len, #95); /* %8 < 97 */
+ align888 = or(align888, len); /* %8 < 97 */
+ len8 = lsr(len, #3); /* %8 < 97 */
+}
+{
+ dcfetch(ptr_in); /* zero/ptrin=ptrout causes fetch */
+ p2 = bitsclr(align888, #7); /* %8 < 97 */
+ if(p1) jumpr r31; /* =0 */
+}
+{
+ p2 = and(p2,!p3); /* %8 < 97 */
+ if (p2.new) len = add(len, #-8); /* %8 < 97 */
+ if (p2.new) jump:NT .Ldwordaligned; /* %8 < 97 */
+}
+{
+ if(!p0) jump .Lbytes23orless; /* %1, <24 */
+ mask.l = #LO(0x7fffffff);
+ /* all bytes before line multiples of data */
+ prolog = sub(#0, ptr_out);
+}
+{
+ /* save r31 on stack, decrement sp by 16 */
+ allocframe(#24);
+ mask.h = #HI(0x7fffffff);
+ ptr_in_p_128 = add(ptr_in, #32);
+ back = cl0(len);
+}
+{
+ memd(sp+#0) = R17:16; /* save r16,r17 on stack6 */
+ r31.l = #LO(.Lmemcpy_return); /* set up final return pointer */
+ prolog &= lsr(mask, back);
+ offset = and(ptr_in, #7);
+}
+{
+ memd(sp+#8) = R25:24; /* save r25,r24 on stack */
+ dalign = sub(ptr_out, ptr_in);
+ r31.h = #HI(.Lmemcpy_return); /* set up final return pointer */
+}
+{
+ /* see if there if input buffer end if aligned */
+ over = add(len, ptr_in);
+ back = add(len, offset);
+ memd(sp+#16) = R21:20; /* save r20,r21 on stack */
+}
+{
+ noprolog = bitsclr(prolog, #7);
+ prolog = and(prolog, #31);
+ dcfetch(ptr_in_p_128);
+ ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+ kernel = sub(len, prolog);
+ shift = asl(prolog, #3);
+ star3 = and(prolog, #7);
+ ptr_in = and(ptr_in, #-8);
+}
+{
+ prolog = lsr(prolog, #3);
+ epilog = and(kernel, #31);
+ ptr_out_p_32 = add(ptr_out, prolog);
+ over = and(over, #7);
+}
+{
+ p3 = cmp.gtu(back, #8);
+ kernel = lsr(kernel, #5);
+ dcfetch(ptr_in_p_128);
+ ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+ p1 = cmp.eq(prolog, #0);
+ if(!p1.new) prolog = add(prolog, #1);
+ dcfetch(ptr_in_p_128); /* reserve the line 64bytes on */
+ ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+ nokernel = cmp.eq(kernel,#0);
+ dcfetch(ptr_in_p_128); /* reserve the line 64bytes on */
+ ptr_in_p_128 = add(ptr_in_p_128, #32);
+ shiftb = and(shift, #8);
+}
+{
+ dcfetch(ptr_in_p_128); /* reserve the line 64bytes on */
+ ptr_in_p_128 = add(ptr_in_p_128, #32);
+ if(nokernel) jump .Lskip64;
+ p2 = cmp.eq(kernel, #1); /* skip ovr if kernel == 0 */
+}
+{
+ dczeroa(ptr_out_p_32);
+ /* don't advance pointer */
+ if(!p2) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+ dalign = and(dalign, #31);
+ dczeroa(ptr_out_p_32);
+}
+.Lskip64:
+{
+ data70 = memd(ptr_in++#16);
+ if(p3) dataF8 = memd(ptr_in+#8);
+ if(noprolog) jump .Lnoprolog32;
+ align = offset;
+}
+/* upto initial 7 bytes */
+{
+ ldata0 = valignb(dataF8, data70, align);
+ ifbyte = tstbit(shift,#3);
+ offset = add(offset, star3);
+}
+{
+ if(ifbyte) memb(ptr_out++#1) = data0;
+ ldata0 = lsr(ldata0, shiftb);
+ shiftb = and(shift, #16);
+ ifhword = tstbit(shift,#4);
+}
+{
+ if(ifhword) memh(ptr_out++#2) = data0;
+ ldata0 = lsr(ldata0, shiftb);
+ ifword = tstbit(shift,#5);
+ p2 = cmp.gtu(offset, #7);
+}
+{
+ if(ifword) memw(ptr_out++#4) = data0;
+ if(p2) data70 = dataF8;
+ if(p2) dataF8 = memd(ptr_in++#8); /* another 8 bytes */
+ align = offset;
+}
+.Lnoprolog32:
+{
+ p3 = sp1loop0(.Ldword_loop_prolog, prolog)
+ rest = sub(len, star3); /* whats left after the loop */
+ p0 = cmp.gt(over, #0);
+}
+ if(p0) rest = add(rest, #16);
+.Ldword_loop_prolog:
+{
+ if(p3) memd(ptr_out++#8) = ldata0;
+ ldata0 = valignb(dataF8, data70, align);
+ p0 = cmp.gt(rest, #16);
+}
+{
+ data70 = dataF8;
+ if(p0) dataF8 = memd(ptr_in++#8);
+ rest = add(rest, #-8);
+}:endloop0
+.Lkernel:
+{
+ /* kernel is at least 32bytes */
+ p3 = cmp.gtu(kernel, #0);
+ /* last itn. remove edge effects */
+ if(p3.new) kernel = add(kernel, #-1);
+ /* dealt with in last dword loop */
+ if(p3.new) epilog = add(epilog, #32);
+}
+{
+ nokernel = cmp.eq(kernel, #0); /* after adjustment, recheck */
+ if(nokernel.new) jump:NT .Lepilog; /* likely not taken */
+ inc = combine(#32, #-1);
+ p3 = cmp.gtu(dalign, #24);
+}
+{
+ if(p3) jump .Lodd_alignment;
+}
+{
+ loop0(.Loword_loop_25to31, kernel);
+ kernel1 = cmp.gtu(kernel, #1);
+ rest = kernel;
+}
+ .falign
+.Loword_loop_25to31:
+{
+ dcfetch(ptr_in_p_128); /* prefetch 4 lines ahead */
+ if(kernel1) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+ dczeroa(ptr_out_p_32); /* reserve the next 32bytes in cache */
+ p3 = cmp.eq(kernel, rest);
+}
+{
+ /* kernel -= 1 */
+ ptr_in_p_128kernel = vaddw(ptr_in_p_128kernel, inc);
+ /* kill write on first iteration */
+ if(!p3) memd(ptr_out++#8) = ldata1;
+ ldata1 = valignb(dataF8, data70, align);
+ data70 = memd(ptr_in++#8);
+}
+{
+ memd(ptr_out++#8) = ldata0;
+ ldata0 = valignb(data70, dataF8, align);
+ dataF8 = memd(ptr_in++#8);
+}
+{
+ memd(ptr_out++#8) = ldata1;
+ ldata1 = valignb(dataF8, data70, align);
+ data70 = memd(ptr_in++#8);
+}
+{
+ memd(ptr_out++#8) = ldata0;
+ ldata0 = valignb(data70, dataF8, align);
+ dataF8 = memd(ptr_in++#8);
+ kernel1 = cmp.gtu(kernel, #1);
+}:endloop0
+{
+ memd(ptr_out++#8) = ldata1;
+ jump .Lepilog;
+}
+.Lodd_alignment:
+{
+ loop0(.Loword_loop_00to24, kernel);
+ kernel1 = cmp.gtu(kernel, #1);
+ rest = add(kernel, #-1);
+}
+ .falign
+.Loword_loop_00to24:
+{
+ dcfetch(ptr_in_p_128); /* prefetch 4 lines ahead */
+ ptr_in_p_128kernel = vaddw(ptr_in_p_128kernel, inc);
+ if(kernel1) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+ dczeroa(ptr_out_p_32); /* reserve the next 32bytes in cache */
+}
+{
+ memd(ptr_out++#8) = ldata0;
+ ldata0 = valignb(dataF8, data70, align);
+ data70 = memd(ptr_in++#8);
+}
+{
+ memd(ptr_out++#8) = ldata0;
+ ldata0 = valignb(data70, dataF8, align);
+ dataF8 = memd(ptr_in++#8);
+}
+{
+ memd(ptr_out++#8) = ldata0;
+ ldata0 = valignb(dataF8, data70, align);
+ data70 = memd(ptr_in++#8);
+}
+{
+ memd(ptr_out++#8) = ldata0;
+ ldata0 = valignb(data70, dataF8, align);
+ dataF8 = memd(ptr_in++#8);
+ kernel1 = cmp.gtu(kernel, #1);
+}:endloop0
+.Lepilog:
+{
+ noepilog = cmp.eq(epilog,#0);
+ epilogdws = lsr(epilog, #3);
+ kernel = and(epilog, #7);
+}
+{
+ if(noepilog) jumpr r31;
+ if(noepilog) ptr_out = sub(ptr_out, len);
+ p3 = cmp.eq(epilogdws, #0);
+ shift2 = asl(epilog, #3);
+}
+{
+ shiftb = and(shift2, #32);
+ ifword = tstbit(epilog,#2);
+ if(p3) jump .Lepilog60;
+ if(!p3) epilog = add(epilog, #-16);
+}
+{
+ loop0(.Ldword_loop_epilog, epilogdws);
+ /* stop criteria is lsbs unless = 0 then its 8 */
+ p3 = cmp.eq(kernel, #0);
+ if(p3.new) kernel= #8;
+ p1 = cmp.gt(over, #0);
+}
+ /* if not aligned to end of buffer execute 1 more iteration */
+ if(p1) kernel= #0;
+.Ldword_loop_epilog:
+{
+ memd(ptr_out++#8) = ldata0;
+ ldata0 = valignb(dataF8, data70, align);
+ p3 = cmp.gt(epilog, kernel);
+}
+{
+ data70 = dataF8;
+ if(p3) dataF8 = memd(ptr_in++#8);
+ epilog = add(epilog, #-8);
+}:endloop0
+/* copy last 7 bytes */
+.Lepilog60:
+{
+ if(ifword) memw(ptr_out++#4) = data0;
+ ldata0 = lsr(ldata0, shiftb);
+ ifhword = tstbit(epilog,#1);
+ shiftb = and(shift2, #16);
+}
+{
+ if(ifhword) memh(ptr_out++#2) = data0;
+ ldata0 = lsr(ldata0, shiftb);
+ ifbyte = tstbit(epilog,#0);
+ if(ifbyte.new) len = add(len, #-1);
+}
+{
+ if(ifbyte) memb(ptr_out) = data0;
+ ptr_out = sub(ptr_out, len); /* return dest pointer */
+ jumpr r31;
+}
+/* do byte copy for small n */
+.Lbytes23orless:
+{
+ p3 = sp1loop0(.Lbyte_copy, len);
+ len = add(len, #-1);
+}
+.Lbyte_copy:
+{
+ data0 = memb(ptr_in++#1);
+ if(p3) memb(ptr_out++#1) = data0;
+}:endloop0
+{
+ memb(ptr_out) = data0;
+ ptr_out = sub(ptr_out, len);
+ jumpr r31;
+}
+/* do dword copies for aligned in, out and length */
+.Ldwordaligned:
+{
+ p3 = sp1loop0(.Ldword_copy, len8);
+}
+.Ldword_copy:
+{
+ if(p3) memd(ptr_out++#8) = ldata0;
+ ldata0 = memd(ptr_in++#8);
+}:endloop0
+{
+ memd(ptr_out) = ldata0;
+ ptr_out = sub(ptr_out, len);
+ jumpr r31; /* return to function caller */
+}
+.Lmemcpy_return:
+ r21:20 = memd(sp+#16); /* restore r20+r21 */
+{
+ r25:24 = memd(sp+#8); /* restore r24+r25 */
+ r17:16 = memd(sp+#0); /* restore r16+r17 */
+}
+ deallocframe; /* restore r31 and incrment stack by 16 */
+ jumpr r31
diff --git a/arch/hexagon/lib/memset.S b/arch/hexagon/lib/memset.S
new file mode 100644
index 000000000000..26d961439ab0
--- /dev/null
+++ b/arch/hexagon/lib/memset.S
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+
+/* HEXAGON assembly optimized memset */
+/* Replaces the standard library function memset */
+
+
+ .macro HEXAGON_OPT_FUNC_BEGIN name
+ .text
+ .p2align 4
+ .globl \name
+ .type \name, @function
+\name:
+ .endm
+
+ .macro HEXAGON_OPT_FUNC_FINISH name
+ .size \name, . - \name
+ .endm
+
+/* FUNCTION: memset (v2 version) */
+#if __HEXAGON_ARCH__ < 3
+HEXAGON_OPT_FUNC_BEGIN memset
+ {
+ r6 = #8
+ r7 = extractu(r0, #3 , #0)
+ p0 = cmp.eq(r2, #0)
+ p1 = cmp.gtu(r2, #7)
+ }
+ {
+ r4 = vsplatb(r1)
+ r8 = r0 /* leave r0 intact for return val */
+ r9 = sub(r6, r7) /* bytes until double alignment */
+ if p0 jumpr r31 /* count == 0, so return */
+ }
+ {
+ r3 = #0
+ r7 = #0
+ p0 = tstbit(r9, #0)
+ if p1 jump 2f /* skip byte loop */
+ }
+
+/* less than 8 bytes to set, so just set a byte at a time and return */
+
+ loop0(1f, r2) /* byte loop */
+ .falign
+1: /* byte loop */
+ {
+ memb(r8++#1) = r4
+ }:endloop0
+ jumpr r31
+ .falign
+2: /* skip byte loop */
+ {
+ r6 = #1
+ p0 = tstbit(r9, #1)
+ p1 = cmp.eq(r2, #1)
+ if !p0 jump 3f /* skip initial byte store */
+ }
+ {
+ memb(r8++#1) = r4
+ r3:2 = sub(r3:2, r7:6)
+ if p1 jumpr r31
+ }
+ .falign
+3: /* skip initial byte store */
+ {
+ r6 = #2
+ p0 = tstbit(r9, #2)
+ p1 = cmp.eq(r2, #2)
+ if !p0 jump 4f /* skip initial half store */
+ }
+ {
+ memh(r8++#2) = r4
+ r3:2 = sub(r3:2, r7:6)
+ if p1 jumpr r31
+ }
+ .falign
+4: /* skip initial half store */
+ {
+ r6 = #4
+ p0 = cmp.gtu(r2, #7)
+ p1 = cmp.eq(r2, #4)
+ if !p0 jump 5f /* skip initial word store */
+ }
+ {
+ memw(r8++#4) = r4
+ r3:2 = sub(r3:2, r7:6)
+ p0 = cmp.gtu(r2, #11)
+ if p1 jumpr r31
+ }
+ .falign
+5: /* skip initial word store */
+ {
+ r10 = lsr(r2, #3)
+ p1 = cmp.eq(r3, #1)
+ if !p0 jump 7f /* skip double loop */
+ }
+ {
+ r5 = r4
+ r6 = #8
+ loop0(6f, r10) /* double loop */
+ }
+
+/* set bytes a double word at a time */
+
+ .falign
+6: /* double loop */
+ {
+ memd(r8++#8) = r5:4
+ r3:2 = sub(r3:2, r7:6)
+ p1 = cmp.eq(r2, #8)
+ }:endloop0
+ .falign
+7: /* skip double loop */
+ {
+ p0 = tstbit(r2, #2)
+ if p1 jumpr r31
+ }
+ {
+ r6 = #4
+ p0 = tstbit(r2, #1)
+ p1 = cmp.eq(r2, #4)
+ if !p0 jump 8f /* skip final word store */
+ }
+ {
+ memw(r8++#4) = r4
+ r3:2 = sub(r3:2, r7:6)
+ if p1 jumpr r31
+ }
+ .falign
+8: /* skip final word store */
+ {
+ p1 = cmp.eq(r2, #2)
+ if !p0 jump 9f /* skip final half store */
+ }
+ {
+ memh(r8++#2) = r4
+ if p1 jumpr r31
+ }
+ .falign
+9: /* skip final half store */
+ {
+ memb(r8++#1) = r4
+ jumpr r31
+ }
+HEXAGON_OPT_FUNC_FINISH memset
+#endif
+
+
+/* FUNCTION: memset (v3 and higher version) */
+#if __HEXAGON_ARCH__ >= 3
+HEXAGON_OPT_FUNC_BEGIN memset
+ {
+ r7=vsplatb(r1)
+ r6 = r0
+ if (r2==#0) jump:nt .L1
+ }
+ {
+ r5:4=combine(r7,r7)
+ p0 = cmp.gtu(r2,#8)
+ if (p0.new) jump:nt .L3
+ }
+ {
+ r3 = r0
+ loop0(.L47,r2)
+ }
+ .falign
+.L47:
+ {
+ memb(r3++#1) = r1
+ }:endloop0 /* start=.L47 */
+ jumpr r31
+.L3:
+ {
+ p0 = tstbit(r0,#0)
+ if (!p0.new) jump:nt .L8
+ p1 = cmp.eq(r2, #1)
+ }
+ {
+ r6 = add(r0, #1)
+ r2 = add(r2,#-1)
+ memb(r0) = r1
+ if (p1) jump .L1
+ }
+.L8:
+ {
+ p0 = tstbit(r6,#1)
+ if (!p0.new) jump:nt .L10
+ }
+ {
+ r2 = add(r2,#-2)
+ memh(r6++#2) = r7
+ p0 = cmp.eq(r2, #2)
+ if (p0.new) jump:nt .L1
+ }
+.L10:
+ {
+ p0 = tstbit(r6,#2)
+ if (!p0.new) jump:nt .L12
+ }
+ {
+ r2 = add(r2,#-4)
+ memw(r6++#4) = r7
+ p0 = cmp.eq(r2, #4)
+ if (p0.new) jump:nt .L1
+ }
+.L12:
+ {
+ p0 = cmp.gtu(r2,#127)
+ if (!p0.new) jump:nt .L14
+ }
+ r3 = and(r6,#31)
+ if (r3==#0) jump:nt .L17
+ {
+ memd(r6++#8) = r5:4
+ r2 = add(r2,#-8)
+ }
+ r3 = and(r6,#31)
+ if (r3==#0) jump:nt .L17
+ {
+ memd(r6++#8) = r5:4
+ r2 = add(r2,#-8)
+ }
+ r3 = and(r6,#31)
+ if (r3==#0) jump:nt .L17
+ {
+ memd(r6++#8) = r5:4
+ r2 = add(r2,#-8)
+ }
+.L17:
+ {
+ r3 = lsr(r2,#5)
+ if (r1!=#0) jump:nt .L18
+ }
+ {
+ r8 = r3
+ r3 = r6
+ loop0(.L46,r3)
+ }
+ .falign
+.L46:
+ {
+ dczeroa(r6)
+ r6 = add(r6,#32)
+ r2 = add(r2,#-32)
+ }:endloop0 /* start=.L46 */
+.L14:
+ {
+ p0 = cmp.gtu(r2,#7)
+ if (!p0.new) jump:nt .L28
+ r8 = lsr(r2,#3)
+ }
+ loop0(.L44,r8)
+ .falign
+.L44:
+ {
+ memd(r6++#8) = r5:4
+ r2 = add(r2,#-8)
+ }:endloop0 /* start=.L44 */
+.L28:
+ {
+ p0 = tstbit(r2,#2)
+ if (!p0.new) jump:nt .L33
+ }
+ {
+ r2 = add(r2,#-4)
+ memw(r6++#4) = r7
+ }
+.L33:
+ {
+ p0 = tstbit(r2,#1)
+ if (!p0.new) jump:nt .L35
+ }
+ {
+ r2 = add(r2,#-2)
+ memh(r6++#2) = r7
+ }
+.L35:
+ p0 = cmp.eq(r2,#1)
+ if (p0) memb(r6) = r1
+.L1:
+ jumpr r31
+.L18:
+ loop0(.L45,r3)
+ .falign
+.L45:
+ dczeroa(r6)
+ {
+ memd(r6++#8) = r5:4
+ r2 = add(r2,#-32)
+ }
+ memd(r6++#8) = r5:4
+ memd(r6++#8) = r5:4
+ {
+ memd(r6++#8) = r5:4
+ }:endloop0 /* start=.L45 */
+ jump .L14
+HEXAGON_OPT_FUNC_FINISH memset
+#endif
diff --git a/arch/hexagon/mm/Makefile b/arch/hexagon/mm/Makefile
new file mode 100644
index 000000000000..1a0be4d576e1
--- /dev/null
+++ b/arch/hexagon/mm/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Hexagon memory management subsystem
+#
+
+obj-y := init.o pgalloc.o ioremap.o uaccess.o vm_fault.o cache.o
+obj-y += copy_to_user.o copy_from_user.o strnlen_user.o vm_tlb.o
diff --git a/arch/hexagon/mm/cache.c b/arch/hexagon/mm/cache.c
new file mode 100644
index 000000000000..c5cf6ee27587
--- /dev/null
+++ b/arch/hexagon/mm/cache.c
@@ -0,0 +1,128 @@
+/*
+ * Cache management functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/hexagon_vm.h>
+
+#define spanlines(start, end) \
+ (((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+ unsigned long lines = spanlines(start, end-1);
+ unsigned long i, flags;
+
+ start &= ~(LINESIZE - 1);
+
+ local_irq_save(flags);
+
+ for (i = 0; i < lines; i++) {
+ __asm__ __volatile__ (
+ " dccleaninva(%0); "
+ :
+ : "r" (start)
+ );
+ start += LINESIZE;
+ }
+ local_irq_restore(flags);
+}
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+ unsigned long lines = spanlines(start, end-1);
+ unsigned long i, flags;
+
+ start &= ~(LINESIZE - 1);
+
+ local_irq_save(flags);
+
+ for (i = 0; i < lines; i++) {
+ __asm__ __volatile__ (
+ " dccleana(%0); "
+ " icinva(%0); "
+ :
+ : "r" (start)
+ );
+ start += LINESIZE;
+ }
+ __asm__ __volatile__ (
+ "isync"
+ );
+ local_irq_restore(flags);
+}
+
+void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
+{
+ unsigned long lines = spanlines(start, end-1);
+ unsigned long i, flags;
+
+ start &= ~(LINESIZE - 1);
+
+ local_irq_save(flags);
+
+ for (i = 0; i < lines; i++) {
+ __asm__ __volatile__ (
+ " dccleana(%0); "
+ :
+ : "r" (start)
+ );
+ start += LINESIZE;
+ }
+ local_irq_restore(flags);
+}
+
+void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
+{
+ unsigned long lines = spanlines(start, end-1);
+ unsigned long i, flags;
+
+ start &= ~(LINESIZE - 1);
+
+ local_irq_save(flags);
+
+ for (i = 0; i < lines; i++) {
+ __asm__ __volatile__ (
+ " dcinva(%0); "
+ :
+ : "r" (start)
+ );
+ start += LINESIZE;
+ }
+ local_irq_restore(flags);
+}
+
+
+
+
+/*
+ * This is just really brutal and shouldn't be used anyways,
+ * especially on V2. Left here just in case.
+ */
+void flush_cache_all_hexagon(void)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ __vmcache_ickill();
+ __vmcache_dckill();
+ __vmcache_l2kill();
+ local_irq_restore(flags);
+ mb();
+}
diff --git a/arch/hexagon/mm/copy_from_user.S b/arch/hexagon/mm/copy_from_user.S
new file mode 100644
index 000000000000..8eb1d4d61a3d
--- /dev/null
+++ b/arch/hexagon/mm/copy_from_user.S
@@ -0,0 +1,114 @@
+/*
+ * User memory copy functions for kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * The right way to do this involves valignb
+ * The easy way to do this is only speed up src/dest similar alignment.
+ */
+
+/*
+ * Copy to/from user are the same, except that for packets with a load and
+ * a store, I don't know how to tell which kind of exception we got.
+ * Therefore, we duplicate the function, and handle faulting addresses
+ * differently for each function
+ */
+
+/*
+ * copy from user: loads can fault
+ */
+#define src_sav r13
+#define dst_sav r12
+#define src_dst_sav r13:12
+#define d_dbuf r15:14
+#define w_dbuf r15
+
+#define dst r0
+#define src r1
+#define bytes r2
+#define loopcount r5
+
+#define FUNCNAME __copy_from_user_hexagon
+#include "copy_user_template.S"
+
+ /* LOAD FAULTS from COPY_FROM_USER */
+
+ /* Alignment loop. r2 has been updated. Return it. */
+ .falign
+1009:
+2009:
+4009:
+ {
+ r0 = r2
+ jumpr r31
+ }
+ /* Normal copy loops. Do epilog. Use src-src_sav to compute distance */
+ /* X - (A - B) == X + B - A */
+ .falign
+8089:
+ {
+ memd(dst) = d_dbuf
+ r2 += sub(src_sav,src)
+ }
+ {
+ r0 = r2
+ jumpr r31
+ }
+ .falign
+4089:
+ {
+ memw(dst) = w_dbuf
+ r2 += sub(src_sav,src)
+ }
+ {
+ r0 = r2
+ jumpr r31
+ }
+ .falign
+2089:
+ {
+ memh(dst) = w_dbuf
+ r2 += sub(src_sav,src)
+ }
+ {
+ r0 = r2
+ jumpr r31
+ }
+ .falign
+1089:
+ {
+ memb(dst) = w_dbuf
+ r2 += sub(src_sav,src)
+ }
+ {
+ r0 = r2
+ jumpr r31
+ }
+
+ /* COPY FROM USER: only loads can fail */
+
+ .section __ex_table,"a"
+ .long 1000b,1009b
+ .long 2000b,2009b
+ .long 4000b,4009b
+ .long 8080b,8089b
+ .long 4080b,4089b
+ .long 2080b,2089b
+ .long 1080b,1089b
+ .previous
diff --git a/arch/hexagon/mm/copy_to_user.S b/arch/hexagon/mm/copy_to_user.S
new file mode 100644
index 000000000000..cb9740ed9e7d
--- /dev/null
+++ b/arch/hexagon/mm/copy_to_user.S
@@ -0,0 +1,92 @@
+/*
+ * User memory copying routines for the Hexagon Kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* The right way to do this involves valignb
+ * The easy way to do this is only speed up src/dest similar alignment.
+ */
+
+/*
+ * Copy to/from user are the same, except that for packets with a load and
+ * a store, I don't know how to tell which kind of exception we got.
+ * Therefore, we duplicate the function, and handle faulting addresses
+ * differently for each function
+ */
+
+/*
+ * copy to user: stores can fault
+ */
+#define src_sav r13
+#define dst_sav r12
+#define src_dst_sav r13:12
+#define d_dbuf r15:14
+#define w_dbuf r15
+
+#define dst r0
+#define src r1
+#define bytes r2
+#define loopcount r5
+
+#define FUNCNAME __copy_to_user_hexagon
+#include "copy_user_template.S"
+
+ /* STORE FAULTS from COPY_TO_USER */
+ .falign
+1109:
+2109:
+4109:
+ /* Alignment loop. r2 has been updated. Return it. */
+ {
+ r0 = r2
+ jumpr r31
+ }
+ /* Normal copy loops. Use dst-dst_sav to compute distance */
+ /* dst holds best write, no need to unwind any loops */
+ /* X - (A - B) == X + B - A */
+ .falign
+8189:
+8199:
+4189:
+4199:
+2189:
+2199:
+1189:
+1199:
+ {
+ r2 += sub(dst_sav,dst)
+ }
+ {
+ r0 = r2
+ jumpr r31
+ }
+
+ /* COPY TO USER: only stores can fail */
+ .section __ex_table,"a"
+ .long 1100b,1109b
+ .long 2100b,2109b
+ .long 4100b,4109b
+ .long 8180b,8189b
+ .long 8190b,8199b
+ .long 4180b,4189b
+ .long 4190b,4199b
+ .long 2180b,2189b
+ .long 2190b,2199b
+ .long 1180b,1189b
+ .long 1190b,1199b
+ .previous
diff --git a/arch/hexagon/mm/copy_user_template.S b/arch/hexagon/mm/copy_user_template.S
new file mode 100644
index 000000000000..08d7d7b23daa
--- /dev/null
+++ b/arch/hexagon/mm/copy_user_template.S
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Numerology:
+ * WXYZ
+ * W: width in bytes
+ * X: Load=0, Store=1
+ * Y: Location 0=preamble,8=loop,9=epilog
+ * Z: Location=0,handler=9
+ */
+ .text
+ .global FUNCNAME
+ .type FUNCNAME, @function
+ .p2align 5
+FUNCNAME:
+ {
+ p0 = cmp.gtu(bytes,#0)
+ if (!p0.new) jump:nt .Ldone
+ r3 = or(dst,src)
+ r4 = xor(dst,src)
+ }
+ {
+ p1 = cmp.gtu(bytes,#15)
+ p0 = bitsclr(r3,#7)
+ if (!p0.new) jump:nt .Loop_not_aligned_8
+ src_dst_sav = combine(src,dst)
+ }
+
+ {
+ loopcount = lsr(bytes,#3)
+ if (!p1) jump .Lsmall
+ }
+ p3=sp1loop0(.Loop8,loopcount)
+.Loop8:
+8080:
+8180:
+ {
+ if (p3) memd(dst++#8) = d_dbuf
+ d_dbuf = memd(src++#8)
+ }:endloop0
+8190:
+ {
+ memd(dst++#8) = d_dbuf
+ bytes -= asl(loopcount,#3)
+ jump .Lsmall
+ }
+
+.Loop_not_aligned_8:
+ {
+ p0 = bitsclr(r4,#7)
+ if (p0.new) jump:nt .Lalign
+ }
+ {
+ p0 = bitsclr(r3,#3)
+ if (!p0.new) jump:nt .Loop_not_aligned_4
+ p1 = cmp.gtu(bytes,#7)
+ }
+
+ {
+ if (!p1) jump .Lsmall
+ loopcount = lsr(bytes,#2)
+ }
+ p3=sp1loop0(.Loop4,loopcount)
+.Loop4:
+4080:
+4180:
+ {
+ if (p3) memw(dst++#4) = w_dbuf
+ w_dbuf = memw(src++#4)
+ }:endloop0
+4190:
+ {
+ memw(dst++#4) = w_dbuf
+ bytes -= asl(loopcount,#2)
+ jump .Lsmall
+ }
+
+.Loop_not_aligned_4:
+ {
+ p0 = bitsclr(r3,#1)
+ if (!p0.new) jump:nt .Loop_not_aligned
+ p1 = cmp.gtu(bytes,#3)
+ }
+
+ {
+ if (!p1) jump .Lsmall
+ loopcount = lsr(bytes,#1)
+ }
+ p3=sp1loop0(.Loop2,loopcount)
+.Loop2:
+2080:
+2180:
+ {
+ if (p3) memh(dst++#2) = w_dbuf
+ w_dbuf = memuh(src++#2)
+ }:endloop0
+2190:
+ {
+ memh(dst++#2) = w_dbuf
+ bytes -= asl(loopcount,#1)
+ jump .Lsmall
+ }
+
+.Loop_not_aligned: /* Works for as small as one byte */
+ p3=sp1loop0(.Loop1,bytes)
+.Loop1:
+1080:
+1180:
+ {
+ if (p3) memb(dst++#1) = w_dbuf
+ w_dbuf = memub(src++#1)
+ }:endloop0
+ /* Done */
+1190:
+ {
+ memb(dst) = w_dbuf
+ jumpr r31
+ r0 = #0
+ }
+
+.Lsmall:
+ {
+ p0 = cmp.gtu(bytes,#0)
+ if (p0.new) jump:nt .Loop_not_aligned
+ }
+.Ldone:
+ {
+ r0 = #0
+ jumpr r31
+ }
+ .falign
+.Lalign:
+1000:
+ {
+ if (p0.new) w_dbuf = memub(src)
+ p0 = tstbit(src,#0)
+ if (!p1) jump .Lsmall
+ }
+1100:
+ {
+ if (p0) memb(dst++#1) = w_dbuf
+ if (p0) bytes = add(bytes,#-1)
+ if (p0) src = add(src,#1)
+ }
+2000:
+ {
+ if (p0.new) w_dbuf = memuh(src)
+ p0 = tstbit(src,#1)
+ if (!p1) jump .Lsmall
+ }
+2100:
+ {
+ if (p0) memh(dst++#2) = w_dbuf
+ if (p0) bytes = add(bytes,#-2)
+ if (p0) src = add(src,#2)
+ }
+4000:
+ {
+ if (p0.new) w_dbuf = memw(src)
+ p0 = tstbit(src,#2)
+ if (!p1) jump .Lsmall
+ }
+4100:
+ {
+ if (p0) memw(dst++#4) = w_dbuf
+ if (p0) bytes = add(bytes,#-4)
+ if (p0) src = add(src,#4)
+ jump FUNCNAME
+ }
+ .size FUNCNAME,.-FUNCNAME
diff --git a/arch/hexagon/mm/init.c b/arch/hexagon/mm/init.c
new file mode 100644
index 000000000000..b57d741750b2
--- /dev/null
+++ b/arch/hexagon/mm/init.c
@@ -0,0 +1,276 @@
+/*
+ * Memory subsystem initialization for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <asm/atomic.h>
+#include <linux/highmem.h>
+#include <asm/tlb.h>
+#include <asm/sections.h>
+#include <asm/vm_mmu.h>
+
+/*
+ * Define a startpg just past the end of the kernel image and a lastpg
+ * that corresponds to the end of real or simulated platform memory.
+ */
+#define bootmem_startpg (PFN_UP(((unsigned long) _end) - PAGE_OFFSET))
+
+unsigned long bootmem_lastpg; /* Should be set by platform code */
+
+/* Set as variable to limit PMD copies */
+int max_kernel_seg = 0x303;
+
+/* think this should be (page_size-1) the way it's used...*/
+unsigned long zero_page_mask;
+
+/* indicate pfn's of high memory */
+unsigned long highstart_pfn, highend_pfn;
+
+/* struct mmu_gather defined in asm-generic.h; */
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+/* Default cache attribute for newly created page tables */
+unsigned long _dflt_cache_att = CACHEDEF;
+
+/*
+ * The current "generation" of kernel map, which should not roll
+ * over until Hell freezes over. Actual bound in years needs to be
+ * calculated to confirm.
+ */
+DEFINE_SPINLOCK(kmap_gen_lock);
+
+/* checkpatch says don't init this to 0. */
+unsigned long long kmap_generation;
+
+/*
+ * mem_init - initializes memory
+ *
+ * Frees up bootmem
+ * Fixes up more stuff for HIGHMEM
+ * Calculates and displays memory available/used
+ */
+void __init mem_init(void)
+{
+ /* No idea where this is actually declared. Seems to evade LXR. */
+ totalram_pages += free_all_bootmem();
+ num_physpages = bootmem_lastpg; /* seriously, what? */
+
+ printk(KERN_INFO "totalram_pages = %ld\n", totalram_pages);
+
+ /*
+ * To-Do: someone somewhere should wipe out the bootmem map
+ * after we're done?
+ */
+
+ /*
+ * This can be moved to some more virtual-memory-specific
+ * initialization hook at some point. Set the init_mm
+ * descriptors "context" value to point to the initial
+ * kernel segment table's physical address.
+ */
+ init_mm.context.ptbase = __pa(init_mm.pgd);
+}
+
+/*
+ * free_initmem - frees memory used by stuff declared with __init
+ *
+ * Todo: free pages between __init_begin and __init_end; possibly
+ * some devtree related stuff as well.
+ */
+void __init_refok free_initmem(void)
+{
+}
+
+/*
+ * free_initrd_mem - frees... initrd memory.
+ * @start - start of init memory
+ * @end - end of init memory
+ *
+ * Apparently has to be passed the address of the initrd memory.
+ *
+ * Wrapped by #ifdef CONFIG_BLKDEV_INITRD
+ */
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+}
+
+void sync_icache_dcache(pte_t pte)
+{
+ unsigned long addr;
+ struct page *page;
+
+ page = pte_page(pte);
+ addr = (unsigned long) page_address(page);
+
+ __vmcache_idsync(addr, PAGE_SIZE);
+}
+
+/*
+ * In order to set up page allocator "nodes",
+ * somebody has to call free_area_init() for UMA.
+ *
+ * In this mode, we only have one pg_data_t
+ * structure: contig_mem_data.
+ */
+void __init paging_init(void)
+{
+ unsigned long zones_sizes[MAX_NR_ZONES] = {0, };
+
+ /*
+ * This is not particularly well documented anywhere, but
+ * give ZONE_NORMAL all the memory, including the big holes
+ * left by the kernel+bootmem_map which are already left as reserved
+ * in the bootmem_map; free_area_init should see those bits and
+ * adjust accordingly.
+ */
+
+ zones_sizes[ZONE_NORMAL] = max_low_pfn;
+
+ free_area_init(zones_sizes); /* sets up the zonelists and mem_map */
+
+ /*
+ * Start of high memory area. Will probably need something more
+ * fancy if we... get more fancy.
+ */
+ high_memory = (void *)((bootmem_lastpg + 1) << PAGE_SHIFT);
+}
+
+#ifndef DMA_RESERVE
+#define DMA_RESERVE (4)
+#endif
+
+#define DMA_CHUNKSIZE (1<<22)
+#define DMA_RESERVED_BYTES (DMA_RESERVE * DMA_CHUNKSIZE)
+
+/*
+ * Pick out the memory size. We look for mem=size,
+ * where size is "size[KkMm]"
+ */
+static int __init early_mem(char *p)
+{
+ unsigned long size;
+ char *endp;
+
+ size = memparse(p, &endp);
+
+ bootmem_lastpg = PFN_DOWN(size);
+
+ return 0;
+}
+early_param("mem", early_mem);
+
+size_t hexagon_coherent_pool_size = (size_t) (DMA_RESERVE << 22);
+
+void __init setup_arch_memory(void)
+{
+ int bootmap_size;
+ /* XXX Todo: this probably should be cleaned up */
+ u32 *segtable = (u32 *) &swapper_pg_dir[0];
+ u32 *segtable_end;
+
+ /*
+ * Set up boot memory allocator
+ *
+ * The Gorman book also talks about these functions.
+ * This needs to change for highmem setups.
+ */
+
+ /* Memory size needs to be a multiple of 16M */
+ bootmem_lastpg = PFN_DOWN((bootmem_lastpg << PAGE_SHIFT) &
+ ~((BIG_KERNEL_PAGE_SIZE) - 1));
+
+ /*
+ * Reserve the top DMA_RESERVE bytes of RAM for DMA (uncached)
+ * memory allocation
+ */
+ bootmap_size = init_bootmem(bootmem_startpg, bootmem_lastpg -
+ PFN_DOWN(DMA_RESERVED_BYTES));
+
+ printk(KERN_INFO "bootmem_startpg: 0x%08lx\n", bootmem_startpg);
+ printk(KERN_INFO "bootmem_lastpg: 0x%08lx\n", bootmem_lastpg);
+ printk(KERN_INFO "bootmap_size: %d\n", bootmap_size);
+ printk(KERN_INFO "max_low_pfn: 0x%08lx\n", max_low_pfn);
+
+ /*
+ * The default VM page tables (will be) populated with
+ * VA=PA+PAGE_OFFSET mapping. We go in and invalidate entries
+ * higher than what we have memory for.
+ */
+
+ /* this is pointer arithmetic; each entry covers 4MB */
+ segtable = segtable + (PAGE_OFFSET >> 22);
+
+ /* this actually only goes to the end of the first gig */
+ segtable_end = segtable + (1<<(30-22));
+
+ /* Move forward to the start of empty pages */
+ segtable += bootmem_lastpg >> (22-PAGE_SHIFT);
+
+ {
+ int i;
+
+ for (i = 1 ; i <= DMA_RESERVE ; i++)
+ segtable[-i] = ((segtable[-i] & __HVM_PTE_PGMASK_4MB)
+ | __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X
+ | __HEXAGON_C_UNC << 6
+ | __HVM_PDE_S_4MB);
+ }
+
+ printk(KERN_INFO "clearing segtable from %p to %p\n", segtable,
+ segtable_end);
+ while (segtable < (segtable_end-8))
+ *(segtable++) = __HVM_PDE_S_INVALID;
+ /* stop the pointer at the device I/O 4MB page */
+
+ printk(KERN_INFO "segtable = %p (should be equal to _K_io_map)\n",
+ segtable);
+
+#if 0
+ /* Other half of the early device table from vm_init_segtable. */
+ printk(KERN_INFO "&_K_init_devicetable = 0x%08x\n",
+ (unsigned long) _K_init_devicetable-PAGE_OFFSET);
+ *segtable = ((u32) (unsigned long) _K_init_devicetable-PAGE_OFFSET) |
+ __HVM_PDE_S_4KB;
+ printk(KERN_INFO "*segtable = 0x%08x\n", *segtable);
+#endif
+
+ /*
+ * Free all the memory that wasn't taken up by the bootmap, the DMA
+ * reserve, or kernel itself.
+ */
+ free_bootmem(PFN_PHYS(bootmem_startpg)+bootmap_size,
+ PFN_PHYS(bootmem_lastpg - bootmem_startpg) - bootmap_size -
+ DMA_RESERVED_BYTES);
+
+ /*
+ * The bootmem allocator seemingly just lives to feed memory
+ * to the paging system
+ */
+ printk(KERN_INFO "PAGE_SIZE=%lu\n", PAGE_SIZE);
+ paging_init(); /* See Gorman Book, 2.3 */
+
+ /*
+ * At this point, the page allocator is kind of initialized, but
+ * apparently no pages are available (just like with the bootmem
+ * allocator), and need to be freed themselves via mem_init(),
+ * which is called by start_kernel() later on in the process
+ */
+}
diff --git a/arch/hexagon/mm/ioremap.c b/arch/hexagon/mm/ioremap.c
new file mode 100644
index 000000000000..3a37bc3b0116
--- /dev/null
+++ b/arch/hexagon/mm/ioremap.c
@@ -0,0 +1,56 @@
+/*
+ * I/O remap functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+
+void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size)
+{
+ unsigned long last_addr, addr;
+ unsigned long offset = phys_addr & ~PAGE_MASK;
+ struct vm_struct *area;
+
+ pgprot_t prot = __pgprot(_PAGE_PRESENT|_PAGE_READ|_PAGE_WRITE
+ |(__HEXAGON_C_DEV << 6));
+
+ last_addr = phys_addr + size - 1;
+
+ /* Wrapping not allowed */
+ if (!size || (last_addr < phys_addr))
+ return NULL;
+
+ /* Rounds up to next page size, including whole-page offset */
+ size = PAGE_ALIGN(offset + size);
+
+ area = get_vm_area(size, VM_IOREMAP);
+ addr = (unsigned long)area->addr;
+
+ if (ioremap_page_range(addr, addr+size, phys_addr, prot)) {
+ vunmap((void *)addr);
+ return NULL;
+ }
+
+ return (void __iomem *) (offset + addr);
+}
+
+void __iounmap(const volatile void __iomem *addr)
+{
+ vunmap((void *) ((unsigned long) addr & PAGE_MASK));
+}
diff --git a/arch/hexagon/mm/pgalloc.c b/arch/hexagon/mm/pgalloc.c
new file mode 100644
index 000000000000..b175e2d42b89
--- /dev/null
+++ b/arch/hexagon/mm/pgalloc.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+
+void __init pgtable_cache_init(void)
+{
+}
diff --git a/arch/hexagon/mm/strnlen_user.S b/arch/hexagon/mm/strnlen_user.S
new file mode 100644
index 000000000000..5c6a16c7c72a
--- /dev/null
+++ b/arch/hexagon/mm/strnlen_user.S
@@ -0,0 +1,139 @@
+/*
+ * User string length functions for kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define isrc r0
+#define max r1 /* Do not change! */
+
+#define end r2
+#define tmp1 r3
+
+#define obo r6 /* off-by-one */
+#define start r7
+#define mod8 r8
+#define dbuf r15:14
+#define dcmp r13:12
+
+/*
+ * The vector mask version of this turned out *really* badly.
+ * The hardware loop version also turned out *really* badly.
+ * Seems straight pointer arithmetic basically wins here.
+ */
+
+#define fname __strnlen_user
+
+ .text
+ .global fname
+ .type fname, @function
+ .p2align 5 /* why? */
+fname:
+ {
+ mod8 = and(isrc,#7);
+ end = add(isrc,max);
+ start = isrc;
+ }
+ {
+ P0 = cmp.eq(mod8,#0);
+ mod8 = and(end,#7);
+ dcmp = #0;
+ if (P0.new) jump:t dw_loop; /* fire up the oven */
+ }
+
+alignment_loop:
+fail_1: {
+ tmp1 = memb(start++#1);
+ }
+ {
+ P0 = cmp.eq(tmp1,#0);
+ if (P0.new) jump:nt exit_found;
+ P1 = cmp.gtu(end,start);
+ mod8 = and(start,#7);
+ }
+ {
+ if (!P1) jump exit_error; /* hit the end */
+ P0 = cmp.eq(mod8,#0);
+ }
+ {
+ if (!P0) jump alignment_loop;
+ }
+
+
+
+dw_loop:
+fail_2: {
+ dbuf = memd(start);
+ obo = add(start,#1);
+ }
+ {
+ P0 = vcmpb.eq(dbuf,dcmp);
+ }
+ {
+ tmp1 = P0;
+ P0 = cmp.gtu(end,start);
+ }
+ {
+ tmp1 = ct0(tmp1);
+ mod8 = and(end,#7);
+ if (!P0) jump end_check;
+ }
+ {
+ P0 = cmp.eq(tmp1,#32);
+ if (!P0.new) jump:nt exit_found;
+ if (!P0.new) start = add(obo,tmp1);
+ }
+ {
+ start = add(start,#8);
+ jump dw_loop;
+ } /* might be nice to combine these jumps... */
+
+
+end_check:
+ {
+ P0 = cmp.gt(tmp1,mod8);
+ if (P0.new) jump:nt exit_error; /* neverfound! */
+ start = add(obo,tmp1);
+ }
+
+exit_found:
+ {
+ R0 = sub(start,isrc);
+ jumpr R31;
+ }
+
+exit_error:
+ {
+ R0 = add(max,#1);
+ jumpr R31;
+ }
+
+ /* Uh, what does the "fixup" return here? */
+ .falign
+fix_1:
+ {
+ R0 = #0;
+ jumpr R31;
+ }
+
+ .size fname,.-fname
+
+
+.section __ex_table,"a"
+.long fail_1,fix_1
+.long fail_2,fix_1
+.previous
diff --git a/arch/hexagon/mm/uaccess.c b/arch/hexagon/mm/uaccess.c
new file mode 100644
index 000000000000..e748108b47a7
--- /dev/null
+++ b/arch/hexagon/mm/uaccess.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Support for user memory access from kernel. This will
+ * probably be inlined for performance at some point, but
+ * for ease of debug, and to a lesser degree for code size,
+ * we implement here as subroutines.
+ */
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+/*
+ * For clear_user(), exploit previously defined copy_to_user function
+ * and the fact that we've got a handy zero page defined in kernel/head.S
+ *
+ * dczero here would be even faster.
+ */
+__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count)
+{
+ long uncleared;
+
+ while (count > PAGE_SIZE) {
+ uncleared = __copy_to_user_hexagon(dest, &empty_zero_page,
+ PAGE_SIZE);
+ if (uncleared)
+ return count - (PAGE_SIZE - uncleared);
+ count -= PAGE_SIZE;
+ dest += PAGE_SIZE;
+ }
+ if (count)
+ count = __copy_to_user_hexagon(dest, &empty_zero_page, count);
+
+ return count;
+}
+
+unsigned long clear_user_hexagon(void __user *dest, unsigned long count)
+{
+ if (!access_ok(VERIFY_WRITE, dest, count))
+ return count;
+ else
+ return __clear_user_hexagon(dest, count);
+}
diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c
new file mode 100644
index 000000000000..c10b76ff9d65
--- /dev/null
+++ b/arch/hexagon/mm/vm_fault.c
@@ -0,0 +1,187 @@
+/*
+ * Memory fault handling for Hexagon
+ *
+ * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Page fault handling for the Hexagon Virtual Machine.
+ * Can also be called by a native port emulating the HVM
+ * execptions.
+ */
+
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/module.h>
+#include <linux/hardirq.h>
+
+/*
+ * Decode of hardware exception sends us to one of several
+ * entry points. At each, we generate canonical arguments
+ * for handling by the abstract memory management code.
+ */
+#define FLT_IFETCH -1
+#define FLT_LOAD 0
+#define FLT_STORE 1
+
+
+/*
+ * Canonical page fault handler
+ */
+void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
+{
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = current->mm;
+ siginfo_t info;
+ int si_code = SEGV_MAPERR;
+ int fault;
+ const struct exception_table_entry *fixup;
+
+ /*
+ * If we're in an interrupt or have no user context,
+ * then must not take the fault.
+ */
+ if (unlikely(in_interrupt() || !mm))
+ goto no_context;
+
+ local_irq_enable();
+
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, address);
+ if (!vma)
+ goto bad_area;
+
+ if (vma->vm_start <= address)
+ goto good_area;
+
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+
+ if (expand_stack(vma, address))
+ goto bad_area;
+
+good_area:
+ /* Address space is OK. Now check access rights. */
+ si_code = SEGV_ACCERR;
+
+ switch (cause) {
+ case FLT_IFETCH:
+ if (!(vma->vm_flags & VM_EXEC))
+ goto bad_area;
+ break;
+ case FLT_LOAD:
+ if (!(vma->vm_flags & VM_READ))
+ goto bad_area;
+ break;
+ case FLT_STORE:
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ break;
+ }
+
+ fault = handle_mm_fault(mm, vma, address, (cause > 0));
+
+ /* The most common case -- we are done. */
+ if (likely(!(fault & VM_FAULT_ERROR))) {
+ if (fault & VM_FAULT_MAJOR)
+ current->maj_flt++;
+ else
+ current->min_flt++;
+
+ up_read(&mm->mmap_sem);
+ return;
+ }
+
+ up_read(&mm->mmap_sem);
+
+ /* Handle copyin/out exception cases */
+ if (!user_mode(regs))
+ goto no_context;
+
+ if (fault & VM_FAULT_OOM) {
+ pagefault_out_of_memory();
+ return;
+ }
+
+ /* User-mode address is in the memory map, but we are
+ * unable to fix up the page fault.
+ */
+ if (fault & VM_FAULT_SIGBUS) {
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_ADRERR;
+ }
+ /* Address is not in the memory map */
+ else {
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_ACCERR;
+ }
+ info.si_errno = 0;
+ info.si_addr = (void __user *)address;
+ force_sig_info(info.si_code, &info, current);
+ return;
+
+bad_area:
+ up_read(&mm->mmap_sem);
+
+ if (user_mode(regs)) {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = si_code;
+ info.si_addr = (void *)address;
+ force_sig_info(SIGSEGV, &info, current);
+ return;
+ }
+ /* Kernel-mode fault falls through */
+
+no_context:
+ fixup = search_exception_tables(pt_elr(regs));
+ if (fixup) {
+ pt_set_elr(regs, fixup->fixup);
+ return;
+ }
+
+ /* Things are looking very, very bad now */
+ bust_spinlocks(1);
+ printk(KERN_EMERG "Unable to handle kernel paging request at "
+ "virtual address 0x%08lx, regs %p\n", address, regs);
+ die("Bad Kernel VA", regs, SIGKILL);
+}
+
+
+void read_protection_fault(struct pt_regs *regs)
+{
+ unsigned long badvadr = pt_badva(regs);
+
+ do_page_fault(badvadr, FLT_LOAD, regs);
+}
+
+void write_protection_fault(struct pt_regs *regs)
+{
+ unsigned long badvadr = pt_badva(regs);
+
+ do_page_fault(badvadr, FLT_STORE, regs);
+}
+
+void execute_protection_fault(struct pt_regs *regs)
+{
+ unsigned long badvadr = pt_badva(regs);
+
+ do_page_fault(badvadr, FLT_IFETCH, regs);
+}
diff --git a/arch/hexagon/mm/vm_tlb.c b/arch/hexagon/mm/vm_tlb.c
new file mode 100644
index 000000000000..c6ff41575461
--- /dev/null
+++ b/arch/hexagon/mm/vm_tlb.c
@@ -0,0 +1,93 @@
+/*
+ * Hexagon Virtual Machine TLB functions
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * The Hexagon Virtual Machine conceals the real workings of
+ * the TLB, but there are one or two functions that need to
+ * be instantiated for it, differently from a native build.
+ */
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * Initial VM implementation has only one map active at a time, with
+ * TLB purgings on changes. So either we're nuking the current map,
+ * or it's a no-op. This operation is messy on true SMPs where other
+ * processors must be induced to flush the copies in their local TLBs,
+ * but Hexagon thread-based virtual processors share the same MMU.
+ */
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+
+ if (mm->context.ptbase == current->active_mm->context.ptbase)
+ __vmclrmap((void *)start, end - start);
+}
+
+/*
+ * Flush a page from the kernel virtual map - used by highmem
+ */
+void flush_tlb_one(unsigned long vaddr)
+{
+ __vmclrmap((void *)vaddr, PAGE_SIZE);
+}
+
+/*
+ * Flush all TLBs across all CPUs, virtual or real.
+ * A single Hexagon core has 6 thread contexts but
+ * only one TLB.
+ */
+void tlb_flush_all(void)
+{
+ /* should probably use that fixaddr end or whateve label */
+ __vmclrmap(0, 0xffff0000);
+}
+
+/*
+ * Flush TLB entries associated with a given mm_struct mapping.
+ */
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ /* Current Virtual Machine has only one map active at a time */
+ if (current->active_mm->context.ptbase == mm->context.ptbase)
+ tlb_flush_all();
+}
+
+/*
+ * Flush TLB state associated with a page of a vma.
+ */
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long vaddr)
+{
+ struct mm_struct *mm = vma->vm_mm;
+
+ if (mm->context.ptbase == current->active_mm->context.ptbase)
+ __vmclrmap((void *)vaddr, PAGE_SIZE);
+}
+
+/*
+ * Flush TLB entries associated with a kernel address range.
+ * Like flush range, but without the check on the vma->vm_mm.
+ */
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ __vmclrmap((void *)start, end - start);
+}
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 3ff7785b3beb..27489b6dd533 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -92,7 +92,7 @@ config HAVE_SETUP_PER_CPU_AREA
def_bool y
config GENERIC_GPIO
- def_bool y
+ bool
config DMI
bool
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index 0e5cd1405e0e..954d81e2e837 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -87,6 +87,7 @@ CONFIG_NET_ETHERNET=y
CONFIG_NET_TULIP=y
CONFIG_TULIP=m
CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
CONFIG_E100=m
CONFIG_E1000=y
CONFIG_IGB=y
@@ -234,4 +235,4 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRC_T10DIF=y
CONFIG_MISC_DEVICES=y
-CONFIG_DMAR=y
+CONFIG_INTEL_IOMMU=y
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index b11fa880e4b6..91c41ecfa6d9 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -75,6 +75,7 @@ CONFIG_NET_ETHERNET=y
CONFIG_NET_TULIP=y
CONFIG_TULIP=m
CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
CONFIG_E100=m
CONFIG_E1000=y
CONFIG_TIGON3=y
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 137a453dd508..a5a9e02e60a0 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -77,6 +77,7 @@ CONFIG_NET_ETHERNET=y
CONFIG_NET_TULIP=y
CONFIG_TULIP=m
CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
CONFIG_E100=m
CONFIG_E1000=y
CONFIG_TIGON3=y
diff --git a/arch/ia64/configs/xen_domu_defconfig b/arch/ia64/configs/xen_domu_defconfig
index 2bf76e418bc5..37b9b422caad 100644
--- a/arch/ia64/configs/xen_domu_defconfig
+++ b/arch/ia64/configs/xen_domu_defconfig
@@ -80,6 +80,7 @@ CONFIG_NET_ETHERNET=y
CONFIG_NET_TULIP=y
CONFIG_TULIP=m
CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
CONFIG_E100=m
CONFIG_E1000=y
CONFIG_TIGON3=y
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index 1d42827f9fa4..fc7aba07c2b4 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -57,6 +57,7 @@ CONFIG_TULIP_MMIO=y
CONFIG_TULIP_NAPI=y
CONFIG_TULIP_NAPI_HW_MITIGATION=y
CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
CONFIG_E100=y
CONFIG_E1000=y
CONFIG_TIGON3=y
diff --git a/arch/ia64/dig/Makefile b/arch/ia64/dig/Makefile
index 2f7caddf093e..ae16ec4f6308 100644
--- a/arch/ia64/dig/Makefile
+++ b/arch/ia64/dig/Makefile
@@ -6,7 +6,7 @@
#
obj-y := setup.o
-ifeq ($(CONFIG_DMAR), y)
+ifeq ($(CONFIG_INTEL_IOMMU), y)
obj-$(CONFIG_IA64_GENERIC) += machvec.o machvec_vtd.o
else
obj-$(CONFIG_IA64_GENERIC) += machvec.o
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 80241fe03f50..f5f4ef149aac 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -915,7 +915,7 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
* @dir: R/W or both.
* @attrs: optional dma attributes
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static dma_addr_t sba_map_page(struct device *dev, struct page *page,
unsigned long poff, size_t size,
@@ -1044,7 +1044,7 @@ sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size)
* @dir: R/W or both.
* @attrs: optional dma attributes
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
enum dma_data_direction dir, struct dma_attrs *attrs)
@@ -1127,7 +1127,7 @@ void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
* @size: number of bytes mapped in driver buffer.
* @dma_handle: IOVA of new buffer.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void *
sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
@@ -1190,7 +1190,7 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp
* @vaddr: virtual address IOVA of "consistent" buffer.
* @dma_handler: IO virtual address of "consistent" buffer.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void sba_free_coherent (struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle)
@@ -1453,7 +1453,7 @@ static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
* @dir: R/W or both.
* @attrs: optional dma attributes
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction dir,
@@ -1549,7 +1549,7 @@ static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist,
* @dir: R/W or both.
* @attrs: optional dma attributes
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction dir,
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
index 7e81966ce481..47afcc61f6e5 100644
--- a/arch/ia64/hp/sim/simeth.c
+++ b/arch/ia64/hp/sim/simeth.c
@@ -172,7 +172,7 @@ static const struct net_device_ops simeth_netdev_ops = {
.ndo_stop = simeth_close,
.ndo_start_xmit = simeth_tx,
.ndo_get_stats = simeth_get_stats,
- .ndo_set_multicast_list = set_multicast_list, /* not yet used */
+ .ndo_set_rx_mode = set_multicast_list, /* not yet used */
};
diff --git a/arch/ia64/include/asm/device.h b/arch/ia64/include/asm/device.h
index d66d446b127c..d05e78f6db94 100644
--- a/arch/ia64/include/asm/device.h
+++ b/arch/ia64/include/asm/device.h
@@ -10,7 +10,7 @@ struct dev_archdata {
#ifdef CONFIG_ACPI
void *acpi_handle;
#endif
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
void *iommu; /* hook for IOMMU specific extension */
#endif
};
diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h
index 745e095fe82e..105c93b00b1b 100644
--- a/arch/ia64/include/asm/iommu.h
+++ b/arch/ia64/include/asm/iommu.h
@@ -7,12 +7,14 @@
extern void pci_iommu_shutdown(void);
extern void no_iommu_init(void);
+#ifdef CONFIG_INTEL_IOMMU
extern int force_iommu, no_iommu;
-extern int iommu_detected;
-#ifdef CONFIG_DMAR
extern int iommu_pass_through;
+extern int iommu_detected;
#else
#define iommu_pass_through (0)
+#define no_iommu (1)
+#define iommu_detected (0)
#endif
extern void iommu_dma_init(void);
extern void machvec_init(const char *name);
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index 73b5f785e70c..127dd7be346a 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -139,7 +139,7 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14);
}
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
extern void pci_iommu_alloc(void);
#endif
#endif /* _ASM_IA64_PCI_H */
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 395c2f216dd8..d959c84904be 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -43,7 +43,7 @@ obj-$(CONFIG_IA64_ESI) += esi.o
ifneq ($(CONFIG_IA64_ESI),)
obj-y += esi_stub.o # must be in kernel proper
endif
-obj-$(CONFIG_DMAR) += pci-dma.o
+obj-$(CONFIG_INTEL_IOMMU) += pci-dma.o
obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
obj-$(CONFIG_BINFMT_ELF) += elfcore.o
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 3be485a300b1..bfb4d01e0e51 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -88,7 +88,7 @@ acpi_get_sysname(void)
struct acpi_table_rsdp *rsdp;
struct acpi_table_xsdt *xsdt;
struct acpi_table_header *hdr;
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
u64 i, nentries;
#endif
@@ -125,7 +125,7 @@ acpi_get_sysname(void)
return "xen";
}
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
/* Look for Intel IOMMU */
nentries = (hdr->length - sizeof(*hdr)) /
sizeof(xsdt->table_offset_entry[0]);
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 009df5434a7a..94e0db72d4a6 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -131,7 +131,7 @@ void arch_teardown_msi_irq(unsigned int irq)
return ia64_teardown_msi_irq(irq);
}
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
#ifdef CONFIG_SMP
static int dmar_msi_set_affinity(struct irq_data *data,
const struct cpumask *mask, bool force)
@@ -210,5 +210,5 @@ int arch_setup_dmar_msi(unsigned int irq)
"edge");
return 0;
}
-#endif /* CONFIG_DMAR */
+#endif /* CONFIG_INTEL_IOMMU */
diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index f6b1ff0aea76..c16162c70860 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -14,7 +14,7 @@
#include <asm/system.h>
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
#include <linux/kernel.h>
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 8213efe1998c..43f4c92816ef 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -33,6 +33,7 @@
#include <linux/uaccess.h>
#include <linux/iommu.h>
#include <linux/intel-iommu.h>
+#include <linux/pci.h>
#include <asm/pgtable.h>
#include <asm/gcc_intrin.h>
@@ -204,7 +205,7 @@ int kvm_dev_ioctl_check_extension(long ext)
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
break;
case KVM_CAP_IOMMU:
- r = iommu_found();
+ r = iommu_present(&pci_bus_type);
break;
default:
r = 0;
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 30862c0358cd..2de41d44266e 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -615,11 +615,15 @@ static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info)
}
}
- if (cpu == SN_HWPERF_ARG_ANY_CPU || cpu == get_cpu()) {
- /* don't care, or already on correct cpu */
+ if (cpu == SN_HWPERF_ARG_ANY_CPU) {
+ /* don't care which cpu */
sn_hwperf_call_sal(op_info);
- }
- else {
+ } else if (cpu == get_cpu()) {
+ /* already on correct cpu */
+ sn_hwperf_call_sal(op_info);
+ put_cpu();
+ } else {
+ put_cpu();
if (use_ipi) {
/* use an interprocessor interrupt to call SAL */
smp_call_function_single(cpu, sn_hwperf_call_sal,
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index b92b9445255d..6c4e9aaa70c1 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -10,6 +10,7 @@ config M32R
select HAVE_GENERIC_HARDIRQS
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
+ select GENERIC_ATOMIC64
config SBUS
bool
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 9e8ee9d2b8ca..6c28582fb98f 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -21,6 +21,15 @@ config ARCH_HAS_ILOG2_U32
config ARCH_HAS_ILOG2_U64
bool
+config GENERIC_CLOCKEVENTS
+ bool
+
+config GENERIC_CMOS_UPDATE
+ def_bool !MMU
+
+config GENERIC_GPIO
+ bool
+
config GENERIC_HWEIGHT
bool
default y
@@ -29,10 +38,16 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
+config GENERIC_IOMAP
+ def_bool MMU
+
config TIME_LOW_RES
bool
default y
+config ARCH_USES_GETTIMEOFFSET
+ def_bool MMU
+
config NO_IOPORT
def_bool y
@@ -62,13 +77,31 @@ config MMU
Select if you want MMU-based virtualised addressing space
support by paged memory management. If unsure, say 'Y'.
-menu "Platform dependent setup"
+config MMU_MOTOROLA
+ bool
+
+config MMU_SUN3
+ bool
+ depends on MMU && !MMU_MOTOROLA
+
+menu "Platform setup"
+
+source arch/m68k/Kconfig.cpu
+
+source arch/m68k/Kconfig.machine
+
+source arch/m68k/Kconfig.bus
+
+endmenu
+
+menu "Kernel Features"
-if MMU
-source arch/m68k/Kconfig.mmu
+if COLDFIRE
+source "kernel/Kconfig.preempt"
endif
-if !MMU
-source arch/m68k/Kconfig.nommu
+
+if !MMU || COLDFIRE
+source "kernel/time/Kconfig"
endif
source "mm/Kconfig"
@@ -85,9 +118,9 @@ if !MMU
menu "Power management options"
config PM
- bool "Power Management support"
- help
- Support processor power management modes
+ bool "Power Management support"
+ help
+ Support processor power management modes
endmenu
endif
@@ -96,151 +129,7 @@ source "net/Kconfig"
source "drivers/Kconfig"
-if MMU
-
-menu "Character devices"
-
-config ATARI_MFPSER
- tristate "Atari MFP serial support"
- depends on ATARI
- ---help---
- If you like to use the MFP serial ports ("Modem1", "Serial1") under
- Linux, say Y. The driver equally supports all kinds of MFP serial
- ports and automatically detects whether Serial1 is available.
-
- To compile this driver as a module, choose M here.
-
- Note for Falcon users: You also have an MFP port, it's just not
- wired to the outside... But you could use the port under Linux.
-
-config ATARI_MIDI
- tristate "Atari MIDI serial support"
- depends on ATARI
- help
- If you want to use your Atari's MIDI port in Linux, say Y.
-
- To compile this driver as a module, choose M here.
-
-config ATARI_DSP56K
- tristate "Atari DSP56k support (EXPERIMENTAL)"
- depends on ATARI && EXPERIMENTAL
- help
- If you want to be able to use the DSP56001 in Falcons, say Y. This
- driver is still experimental, and if you don't know what it is, or
- if you don't have this processor, just say N.
-
- To compile this driver as a module, choose M here.
-
-config AMIGA_BUILTIN_SERIAL
- tristate "Amiga builtin serial support"
- depends on AMIGA
- help
- If you want to use your Amiga's built-in serial port in Linux,
- answer Y.
-
- To compile this driver as a module, choose M here.
-
-config MULTIFACE_III_TTY
- tristate "Multiface Card III serial support"
- depends on AMIGA
- help
- If you want to use a Multiface III card's serial port in Linux,
- answer Y.
-
- To compile this driver as a module, choose M here.
-
-config GVPIOEXT
- tristate "GVP IO-Extender support"
- depends on PARPORT=n && ZORRO
- help
- If you want to use a GVP IO-Extender serial card in Linux, say Y.
- Otherwise, say N.
-
-config GVPIOEXT_LP
- tristate "GVP IO-Extender parallel printer support"
- depends on GVPIOEXT
- help
- Say Y to enable driving a printer from the parallel port on your
- GVP IO-Extender card, N otherwise.
-
-config GVPIOEXT_PLIP
- tristate "GVP IO-Extender PLIP support"
- depends on GVPIOEXT
- help
- Say Y to enable doing IP over the parallel port on your GVP
- IO-Extender card, N otherwise.
-
-config MAC_HID
- bool
- depends on INPUT_ADBHID
- default y
-
-config HPDCA
- tristate "HP DCA serial support"
- depends on DIO && SERIAL_8250
- help
- If you want to use the internal "DCA" serial ports on an HP300
- machine, say Y here.
-
-config HPAPCI
- tristate "HP APCI serial support"
- depends on HP300 && SERIAL_8250 && EXPERIMENTAL
- help
- If you want to use the internal "APCI" serial ports on an HP400
- machine, say Y here.
-
-config MVME147_SCC
- bool "SCC support for MVME147 serial ports"
- depends on MVME147 && BROKEN
- help
- This is the driver for the serial ports on the Motorola MVME147
- boards. Everyone using one of these boards should say Y here.
-
-config MVME162_SCC
- bool "SCC support for MVME162 serial ports"
- depends on MVME16x && BROKEN
- help
- This is the driver for the serial ports on the Motorola MVME162 and
- 172 boards. Everyone using one of these boards should say Y here.
-
-config BVME6000_SCC
- bool "SCC support for BVME6000 serial ports"
- depends on BVME6000 && BROKEN
- help
- This is the driver for the serial ports on the BVME4000 and BVME6000
- boards from BVM Ltd. Everyone using one of these boards should say
- Y here.
-
-config DN_SERIAL
- bool "Support for DN serial port (dummy)"
- depends on APOLLO
-
-config SERIAL_CONSOLE
- bool "Support for serial port console"
- depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
- ---help---
- If you say Y here, it will be possible to use a serial port as the
- system console (the system console is the device which receives all
- kernel messages and warnings and which allows logins in single user
- mode). This could be useful if some terminal or printer is connected
- to that serial port.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyS1". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
- If you don't have a VGA card installed and you say Y here, the
- kernel will automatically use the first serial line, /dev/ttyS0, as
- system console.
-
- If unsure, say N.
-
-endmenu
-
-endif
+source "arch/m68k/Kconfig.devices"
source "fs/Kconfig"
diff --git a/arch/m68k/Kconfig.bus b/arch/m68k/Kconfig.bus
new file mode 100644
index 000000000000..8294f0c1785e
--- /dev/null
+++ b/arch/m68k/Kconfig.bus
@@ -0,0 +1,55 @@
+if MMU
+
+comment "Bus Support"
+
+config NUBUS
+ bool
+ depends on MAC
+ default y
+
+config ZORRO
+ bool "Amiga Zorro (AutoConfig) bus support"
+ depends on AMIGA
+ help
+ This enables support for the Zorro bus in the Amiga. If you have
+ expansion cards in your Amiga that conform to the Amiga
+ AutoConfig(tm) specification, say Y, otherwise N. Note that even
+ expansion cards that do not fit in the Zorro slots but fit in e.g.
+ the CPU slot may fall in this category, so you have to say Y to let
+ Linux use these.
+
+config AMIGA_PCMCIA
+ bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
+ depends on AMIGA && EXPERIMENTAL
+ help
+ Include support in the kernel for pcmcia on Amiga 1200 and Amiga
+ 600. If you intend to use pcmcia cards say Y; otherwise say N.
+
+config ISA
+ bool
+ depends on Q40 || AMIGA_PCMCIA
+ default y
+ help
+ Find out whether you have ISA slots on your motherboard. ISA is the
+ name of a bus system, i.e. the way the CPU talks to the other stuff
+ inside your box. Other bus systems are PCI, EISA, MicroChannel
+ (MCA) or VESA. ISA is an older system, now being displaced by PCI;
+ newer boards don't support it. If you have ISA, say Y, otherwise N.
+
+config GENERIC_ISA_DMA
+ def_bool ISA
+
+source "drivers/pci/Kconfig"
+
+source "drivers/zorro/Kconfig"
+
+endif
+
+if !MMU
+
+config ISA_DMA_API
+ def_bool !M5272
+
+source "drivers/pcmcia/Kconfig"
+
+endif
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
new file mode 100644
index 000000000000..e632b2d12106
--- /dev/null
+++ b/arch/m68k/Kconfig.cpu
@@ -0,0 +1,429 @@
+comment "Processor Type"
+
+config M68000
+ bool
+ select CPU_HAS_NO_BITFIELDS
+ help
+ The Freescale (was Motorola) 68000 CPU is the first generation of
+ the well known M68K family of processors. The CPU core as well as
+ being available as a stand alone CPU was also used in many
+ System-On-Chip devices (eg 68328, 68302, etc). It does not contain
+ a paging MMU.
+
+config MCPU32
+ bool
+ select CPU_HAS_NO_BITFIELDS
+ help
+ The Freescale (was then Motorola) CPU32 is a CPU core that is
+ based on the 68020 processor. For the most part it is used in
+ System-On-Chip parts, and does not contain a paging MMU.
+
+config COLDFIRE
+ bool
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ select CPU_HAS_NO_BITFIELDS
+ help
+ The Freescale ColdFire family of processors is a modern derivitive
+ of the 68000 processor family. They are mainly targeted at embedded
+ applications, and are all System-On-Chip (SOC) devices, as opposed
+ to stand alone CPUs. They implement a subset of the original 68000
+ processor instruction set.
+
+config M68020
+ bool "68020 support"
+ depends on MMU
+ help
+ If you anticipate running this kernel on a computer with a MC68020
+ processor, say Y. Otherwise, say N. Note that the 68020 requires a
+ 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
+ Sun 3, which provides its own version.
+
+config M68030
+ bool "68030 support"
+ depends on MMU && !MMU_SUN3
+ help
+ If you anticipate running this kernel on a computer with a MC68030
+ processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
+ work, as it does not include an MMU (Memory Management Unit).
+
+config M68040
+ bool "68040 support"
+ depends on MMU && !MMU_SUN3
+ help
+ If you anticipate running this kernel on a computer with a MC68LC040
+ or MC68040 processor, say Y. Otherwise, say N. Note that an
+ MC68EC040 will not work, as it does not include an MMU (Memory
+ Management Unit).
+
+config M68060
+ bool "68060 support"
+ depends on MMU && !MMU_SUN3
+ help
+ If you anticipate running this kernel on a computer with a MC68060
+ processor, say Y. Otherwise, say N.
+
+config M68328
+ bool "MC68328"
+ depends on !MMU
+ select M68000
+ help
+ Motorola 68328 processor support.
+
+config M68EZ328
+ bool "MC68EZ328"
+ depends on !MMU
+ select M68000
+ help
+ Motorola 68EX328 processor support.
+
+config M68VZ328
+ bool "MC68VZ328"
+ depends on !MMU
+ select M68000
+ help
+ Motorola 68VZ328 processor support.
+
+config M68360
+ bool "MC68360"
+ depends on !MMU
+ select MCPU32
+ help
+ Motorola 68360 processor support.
+
+config M5206
+ bool "MCF5206"
+ depends on !MMU
+ select COLDFIRE
+ select COLDFIRE_SW_A7
+ select HAVE_MBAR
+ help
+ Motorola ColdFire 5206 processor support.
+
+config M5206e
+ bool "MCF5206e"
+ depends on !MMU
+ select COLDFIRE
+ select COLDFIRE_SW_A7
+ select HAVE_MBAR
+ help
+ Motorola ColdFire 5206e processor support.
+
+config M520x
+ bool "MCF520x"
+ depends on !MMU
+ select COLDFIRE
+ select GENERIC_CLOCKEVENTS
+ select HAVE_CACHE_SPLIT
+ help
+ Freescale Coldfire 5207/5208 processor support.
+
+config M523x
+ bool "MCF523x"
+ depends on !MMU
+ select COLDFIRE
+ select GENERIC_CLOCKEVENTS
+ select HAVE_CACHE_SPLIT
+ select HAVE_IPSBAR
+ help
+ Freescale Coldfire 5230/1/2/4/5 processor support
+
+config M5249
+ bool "MCF5249"
+ depends on !MMU
+ select COLDFIRE
+ select COLDFIRE_SW_A7
+ select HAVE_MBAR
+ help
+ Motorola ColdFire 5249 processor support.
+
+config M527x
+ bool
+
+config M5271
+ bool "MCF5271"
+ depends on !MMU
+ select COLDFIRE
+ select M527x
+ select HAVE_CACHE_SPLIT
+ select HAVE_IPSBAR
+ select GENERIC_CLOCKEVENTS
+ help
+ Freescale (Motorola) ColdFire 5270/5271 processor support.
+
+config M5272
+ bool "MCF5272"
+ depends on !MMU
+ select COLDFIRE
+ select COLDFIRE_SW_A7
+ select HAVE_MBAR
+ help
+ Motorola ColdFire 5272 processor support.
+
+config M5275
+ bool "MCF5275"
+ depends on !MMU
+ select COLDFIRE
+ select M527x
+ select HAVE_CACHE_SPLIT
+ select HAVE_IPSBAR
+ select GENERIC_CLOCKEVENTS
+ help
+ Freescale (Motorola) ColdFire 5274/5275 processor support.
+
+config M528x
+ bool "MCF528x"
+ depends on !MMU
+ select COLDFIRE
+ select GENERIC_CLOCKEVENTS
+ select HAVE_CACHE_SPLIT
+ select HAVE_IPSBAR
+ help
+ Motorola ColdFire 5280/5282 processor support.
+
+config M5307
+ bool "MCF5307"
+ depends on !MMU
+ select COLDFIRE
+ select COLDFIRE_SW_A7
+ select HAVE_CACHE_CB
+ select HAVE_MBAR
+ help
+ Motorola ColdFire 5307 processor support.
+
+config M532x
+ bool "MCF532x"
+ depends on !MMU
+ select COLDFIRE
+ select HAVE_CACHE_CB
+ help
+ Freescale (Motorola) ColdFire 532x processor support.
+
+config M5407
+ bool "MCF5407"
+ depends on !MMU
+ select COLDFIRE
+ select COLDFIRE_SW_A7
+ select HAVE_CACHE_CB
+ select HAVE_MBAR
+ help
+ Motorola ColdFire 5407 processor support.
+
+config M54xx
+ bool
+
+config M547x
+ bool "MCF547x"
+ depends on !MMU
+ select COLDFIRE
+ select M54xx
+ select HAVE_CACHE_CB
+ select HAVE_MBAR
+ help
+ Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
+
+config M548x
+ bool "MCF548x"
+ depends on !MMU
+ select COLDFIRE
+ select M54xx
+ select HAVE_CACHE_CB
+ select HAVE_MBAR
+ help
+ Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
+
+
+comment "Processor Specific Options"
+
+config M68KFPU_EMU
+ bool "Math emulation support (EXPERIMENTAL)"
+ depends on MMU
+ depends on EXPERIMENTAL
+ help
+ At some point in the future, this will cause floating-point math
+ instructions to be emulated by the kernel on machines that lack a
+ floating-point math coprocessor. Thrill-seekers and chronically
+ sleep-deprived psychotic hacker types can say Y now, everyone else
+ should probably wait a while.
+
+config M68KFPU_EMU_EXTRAPREC
+ bool "Math emulation extra precision"
+ depends on M68KFPU_EMU
+ help
+ The fpu uses normally a few bit more during calculations for
+ correct rounding, the emulator can (often) do the same but this
+ extra calculation can cost quite some time, so you can disable
+ it here. The emulator will then "only" calculate with a 64 bit
+ mantissa and round slightly incorrect, what is more than enough
+ for normal usage.
+
+config M68KFPU_EMU_ONLY
+ bool "Math emulation only kernel"
+ depends on M68KFPU_EMU
+ help
+ This option prevents any floating-point instructions from being
+ compiled into the kernel, thereby the kernel doesn't save any
+ floating point context anymore during task switches, so this
+ kernel will only be usable on machines without a floating-point
+ math coprocessor. This makes the kernel a bit faster as no tests
+ needs to be executed whether a floating-point instruction in the
+ kernel should be executed or not.
+
+config ADVANCED
+ bool "Advanced configuration options"
+ depends on MMU
+ ---help---
+ This gives you access to some advanced options for the CPU. The
+ defaults should be fine for most users, but these options may make
+ it possible for you to improve performance somewhat if you know what
+ you are doing.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about these options.
+
+ Most users should say N to this question.
+
+config RMW_INSNS
+ bool "Use read-modify-write instructions"
+ depends on ADVANCED
+ ---help---
+ This allows to use certain instructions that work with indivisible
+ read-modify-write bus cycles. While this is faster than the
+ workaround of disabling interrupts, it can conflict with DMA
+ ( = direct memory access) on many Amiga systems, and it is also said
+ to destabilize other machines. It is very likely that this will
+ cause serious problems on any Amiga or Atari Medusa if set. The only
+ configuration where it should work are 68030-based Ataris, where it
+ apparently improves performance. But you've been warned! Unless you
+ really know what you are doing, say N. Try Y only if you're quite
+ adventurous.
+
+config SINGLE_MEMORY_CHUNK
+ bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
+ depends on MMU
+ default y if SUN3
+ select NEED_MULTIPLE_NODES
+ help
+ Ignore all but the first contiguous chunk of physical memory for VM
+ purposes. This will save a few bytes kernel size and may speed up
+ some operations. Say N if not sure.
+
+config ARCH_DISCONTIGMEM_ENABLE
+ def_bool MMU && !SINGLE_MEMORY_CHUNK
+
+config 060_WRITETHROUGH
+ bool "Use write-through caching for 68060 supervisor accesses"
+ depends on ADVANCED && M68060
+ ---help---
+ The 68060 generally uses copyback caching of recently accessed data.
+ Copyback caching means that memory writes will be held in an on-chip
+ cache and only written back to memory some time later. Saying Y
+ here will force supervisor (kernel) accesses to use writethrough
+ caching. Writethrough caching means that data is written to memory
+ straight away, so that cache and memory data always agree.
+ Writethrough caching is less efficient, but is needed for some
+ drivers on 68060 based systems where the 68060 bus snooping signal
+ is hardwired on. The 53c710 SCSI driver is known to suffer from
+ this problem.
+
+config M68K_L2_CACHE
+ bool
+ depends on MAC
+ default y
+
+config NODES_SHIFT
+ int
+ default "3"
+ depends on !SINGLE_MEMORY_CHUNK
+
+config FPU
+ bool
+
+config COLDFIRE_SW_A7
+ bool
+
+config HAVE_CACHE_SPLIT
+ bool
+
+config HAVE_CACHE_CB
+ bool
+
+config HAVE_MBAR
+ bool
+
+config HAVE_IPSBAR
+ bool
+
+config CLOCK_SET
+ bool "Enable setting the CPU clock frequency"
+ depends on COLDFIRE
+ default n
+ help
+ On some CPU's you do not need to know what the core CPU clock
+ frequency is. On these you can disable clock setting. On some
+ traditional 68K parts, and on all ColdFire parts you need to set
+ the appropriate CPU clock frequency. On these devices many of the
+ onboard peripherals derive their timing from the master CPU clock
+ frequency.
+
+config CLOCK_FREQ
+ int "Set the core clock frequency"
+ default "66666666"
+ depends on CLOCK_SET
+ help
+ Define the CPU clock frequency in use. This is the core clock
+ frequency, it may or may not be the same as the external clock
+ crystal fitted to your board. Some processors have an internal
+ PLL and can have their frequency programmed at run time, others
+ use internal dividers. In general the kernel won't setup a PLL
+ if it is fitted (there are some exceptions). This value will be
+ specific to the exact CPU that you are using.
+
+config OLDMASK
+ bool "Old mask 5307 (1H55J) silicon"
+ depends on M5307
+ help
+ Build support for the older revision ColdFire 5307 silicon.
+ Specifically this is the 1H55J mask revision.
+
+if HAVE_CACHE_SPLIT
+choice
+ prompt "Split Cache Configuration"
+ default CACHE_I
+
+config CACHE_I
+ bool "Instruction"
+ help
+ Use all of the ColdFire CPU cache memory as an instruction cache.
+
+config CACHE_D
+ bool "Data"
+ help
+ Use all of the ColdFire CPU cache memory as a data cache.
+
+config CACHE_BOTH
+ bool "Both"
+ help
+ Split the ColdFire CPU cache, and use half as an instruction cache
+ and half as a data cache.
+endchoice
+endif
+
+if HAVE_CACHE_CB
+choice
+ prompt "Data cache mode"
+ default CACHE_WRITETHRU
+
+config CACHE_WRITETHRU
+ bool "Write-through"
+ help
+ The ColdFire CPU cache is set into Write-through mode.
+
+config CACHE_COPYBACK
+ bool "Copy-back"
+ help
+ The ColdFire CPU cache is set into Copy-back mode.
+endchoice
+endif
+
diff --git a/arch/m68k/Kconfig.devices b/arch/m68k/Kconfig.devices
new file mode 100644
index 000000000000..d214034be6a6
--- /dev/null
+++ b/arch/m68k/Kconfig.devices
@@ -0,0 +1,123 @@
+if MMU
+
+config ARCH_MAY_HAVE_PC_FDC
+ bool
+ depends on BROKEN && (Q40 || SUN3X)
+ default y
+
+menu "Platform devices"
+
+config HEARTBEAT
+ bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
+ default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
+ help
+ Use the power-on LED on your machine as a load meter. The exact
+ behavior is platform-dependent, but normally the flash frequency is
+ a hyperbolic function of the 5-minute load average.
+
+# We have a dedicated heartbeat LED. :-)
+config PROC_HARDWARE
+ bool "/proc/hardware support"
+ help
+ Say Y here to support the /proc/hardware file, which gives you
+ access to information about the machine you're running on,
+ including the model, CPU, MMU, clock speed, BogoMIPS rating,
+ and memory size.
+
+endmenu
+
+menu "Character devices"
+
+config ATARI_MFPSER
+ tristate "Atari MFP serial support"
+ depends on ATARI
+ ---help---
+ If you like to use the MFP serial ports ("Modem1", "Serial1") under
+ Linux, say Y. The driver equally supports all kinds of MFP serial
+ ports and automatically detects whether Serial1 is available.
+
+ To compile this driver as a module, choose M here.
+
+ Note for Falcon users: You also have an MFP port, it's just not
+ wired to the outside... But you could use the port under Linux.
+
+config ATARI_MIDI
+ tristate "Atari MIDI serial support"
+ depends on ATARI
+ help
+ If you want to use your Atari's MIDI port in Linux, say Y.
+
+ To compile this driver as a module, choose M here.
+
+config ATARI_DSP56K
+ tristate "Atari DSP56k support (EXPERIMENTAL)"
+ depends on ATARI && EXPERIMENTAL
+ help
+ If you want to be able to use the DSP56001 in Falcons, say Y. This
+ driver is still experimental, and if you don't know what it is, or
+ if you don't have this processor, just say N.
+
+ To compile this driver as a module, choose M here.
+
+config AMIGA_BUILTIN_SERIAL
+ tristate "Amiga builtin serial support"
+ depends on AMIGA
+ help
+ If you want to use your Amiga's built-in serial port in Linux,
+ answer Y.
+
+ To compile this driver as a module, choose M here.
+
+config MULTIFACE_III_TTY
+ tristate "Multiface Card III serial support"
+ depends on AMIGA
+ help
+ If you want to use a Multiface III card's serial port in Linux,
+ answer Y.
+
+ To compile this driver as a module, choose M here.
+
+config HPDCA
+ tristate "HP DCA serial support"
+ depends on DIO && SERIAL_8250
+ help
+ If you want to use the internal "DCA" serial ports on an HP300
+ machine, say Y here.
+
+config HPAPCI
+ tristate "HP APCI serial support"
+ depends on HP300 && SERIAL_8250 && EXPERIMENTAL
+ help
+ If you want to use the internal "APCI" serial ports on an HP400
+ machine, say Y here.
+
+config DN_SERIAL
+ bool "Support for DN serial port (dummy)"
+ depends on APOLLO
+
+config SERIAL_CONSOLE
+ bool "Support for serial port console"
+ depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || MULTIFACE_III_TTY=y || SERIAL=y || SERIAL167 || DN_SERIAL)
+ ---help---
+ If you say Y here, it will be possible to use a serial port as the
+ system console (the system console is the device which receives all
+ kernel messages and warnings and which allows logins in single user
+ mode). This could be useful if some terminal or printer is connected
+ to that serial port.
+
+ Even if you say Y here, the currently visible virtual console
+ (/dev/tty0) will still be used as the system console by default, but
+ you can alter that using a kernel command line option such as
+ "console=ttyS1". (Try "man bootparam" or see the documentation of
+ your boot loader (lilo or loadlin) about how to pass options to the
+ kernel at boot time.)
+
+ If you don't have a VGA card installed and you say Y here, the
+ kernel will automatically use the first serial line, /dev/ttyS0, as
+ system console.
+
+ If unsure, say N.
+
+endmenu
+
+endif
diff --git a/arch/m68k/Kconfig.nommu b/arch/m68k/Kconfig.machine
index ff46383112a4..ef4a26aff780 100644
--- a/arch/m68k/Kconfig.nommu
+++ b/arch/m68k/Kconfig.machine
@@ -1,297 +1,142 @@
-config FPU
- bool
- default n
-
-config GENERIC_GPIO
- bool
- default n
-
-config GENERIC_CMOS_UPDATE
- bool
- default y
-
-config GENERIC_CLOCKEVENTS
- bool
- default n
-
-config M68000
- bool
- select CPU_HAS_NO_BITFIELDS
- help
- The Freescale (was Motorola) 68000 CPU is the first generation of
- the well known M68K family of processors. The CPU core as well as
- being available as a stand alone CPU was also used in many
- System-On-Chip devices (eg 68328, 68302, etc). It does not contain
- a paging MMU.
-
-config MCPU32
- bool
- select CPU_HAS_NO_BITFIELDS
- help
- The Freescale (was then Motorola) CPU32 is a CPU core that is
- based on the 68020 processor. For the most part it is used in
- System-On-Chip parts, and does not contain a paging MMU.
-
-config COLDFIRE
- bool
- select GENERIC_GPIO
- select ARCH_REQUIRE_GPIOLIB
- select CPU_HAS_NO_BITFIELDS
- help
- The Freescale ColdFire family of processors is a modern derivitive
- of the 68000 processor family. They are mainly targeted at embedded
- applications, and are all System-On-Chip (SOC) devices, as opposed
- to stand alone CPUs. They implement a subset of the original 68000
- processor instruction set.
-
-config COLDFIRE_SW_A7
- bool
- default n
-
-config HAVE_CACHE_SPLIT
- bool
-
-config HAVE_CACHE_CB
- bool
-
-config HAVE_MBAR
- bool
-
-config HAVE_IPSBAR
- bool
-
-choice
- prompt "CPU"
- default M68EZ328
-
-config M68328
- bool "MC68328"
- select M68000
- help
- Motorola 68328 processor support.
-
-config M68EZ328
- bool "MC68EZ328"
- select M68000
- help
- Motorola 68EX328 processor support.
-
-config M68VZ328
- bool "MC68VZ328"
- select M68000
- help
- Motorola 68VZ328 processor support.
-
-config M68360
- bool "MC68360"
- select MCPU32
- help
- Motorola 68360 processor support.
-
-config M5206
- bool "MCF5206"
- select COLDFIRE
- select COLDFIRE_SW_A7
- select HAVE_MBAR
- help
- Motorola ColdFire 5206 processor support.
+comment "Machine Types"
+
+config AMIGA
+ bool "Amiga support"
+ depends on MMU
+ select MMU_MOTOROLA if MMU
+ help
+ This option enables support for the Amiga series of computers. If
+ you plan to use this kernel on an Amiga, say Y here and browse the
+ material available in <file:Documentation/m68k>; otherwise say N.
+
+config ATARI
+ bool "Atari support"
+ depends on MMU
+ select MMU_MOTOROLA if MMU
+ help
+ This option enables support for the 68000-based Atari series of
+ computers (including the TT, Falcon and Medusa). If you plan to use
+ this kernel on an Atari, say Y here and browse the material
+ available in <file:Documentation/m68k>; otherwise say N.
+
+config MAC
+ bool "Macintosh support"
+ depends on MMU
+ select MMU_MOTOROLA if MMU
+ help
+ This option enables support for the Apple Macintosh series of
+ computers (yes, there is experimental support now, at least for part
+ of the series).
+
+ Say N unless you're willing to code the remaining necessary support.
+ ;)
+
+config APOLLO
+ bool "Apollo support"
+ depends on MMU
+ select MMU_MOTOROLA if MMU
+ help
+ Say Y here if you want to run Linux on an MC680x0-based Apollo
+ Domain workstation such as the DN3500.
+
+config VME
+ bool "VME (Motorola and BVM) support"
+ depends on MMU
+ select MMU_MOTOROLA if MMU
+ help
+ Say Y here if you want to build a kernel for a 680x0 based VME
+ board. Boards currently supported include Motorola boards MVME147,
+ MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and
+ BVME6000 boards from BVM Ltd are also supported.
+
+config MVME147
+ bool "MVME147 support"
+ depends on MMU
+ depends on VME
+ help
+ Say Y to include support for early Motorola VME boards. This will
+ build a kernel which can run on MVME147 single-board computers. If
+ you select this option you will have to select the appropriate
+ drivers for SCSI, Ethernet and serial ports later on.
+
+config MVME16x
+ bool "MVME162, 166 and 167 support"
+ depends on MMU
+ depends on VME
+ help
+ Say Y to include support for Motorola VME boards. This will build a
+ kernel which can run on MVME162, MVME166, MVME167, MVME172, and
+ MVME177 boards. If you select this option you will have to select
+ the appropriate drivers for SCSI, Ethernet and serial ports later
+ on.
+
+config BVME6000
+ bool "BVME4000 and BVME6000 support"
+ depends on MMU
+ depends on VME
+ help
+ Say Y to include support for VME boards from BVM Ltd. This will
+ build a kernel which can run on BVME4000 and BVME6000 boards. If
+ you select this option you will have to select the appropriate
+ drivers for SCSI, Ethernet and serial ports later on.
+
+config HP300
+ bool "HP9000/300 and HP9000/400 support"
+ depends on MMU
+ select MMU_MOTOROLA if MMU
+ help
+ This option enables support for the HP9000/300 and HP9000/400 series
+ of workstations. Support for these machines is still somewhat
+ experimental. If you plan to try to use the kernel on such a machine
+ say Y here.
+ Everybody else says N.
+
+config SUN3X
+ bool "Sun3x support"
+ depends on MMU
+ select MMU_MOTOROLA if MMU
+ select M68030
+ help
+ This option enables support for the Sun 3x series of workstations.
+ Be warned that this support is very experimental.
+ Note that Sun 3x kernels are not compatible with Sun 3 hardware.
+ General Linux information on the Sun 3x series (now discontinued)
+ is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
+
+ If you don't want to compile a kernel for a Sun 3x, say N.
+
+config Q40
+ bool "Q40/Q60 support"
+ depends on MMU
+ select MMU_MOTOROLA if MMU
+ help
+ The Q40 is a Motorola 68040-based successor to the Sinclair QL
+ manufactured in Germany. There is an official Q40 home page at
+ <http://www.q40.de/>. This option enables support for the Q40 and
+ Q60. Select your CPU below. For 68LC060 don't forget to enable FPU
+ emulation.
+
+config SUN3
+ bool "Sun3 support"
+ depends on MMU
+ depends on !MMU_MOTOROLA
+ select MMU_SUN3 if MMU
+ select M68020
+ help
+ This option enables support for the Sun 3 series of workstations
+ (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
+ that all other hardware types must be disabled, as Sun 3 kernels
+ are incompatible with all other m68k targets (including Sun 3x!).
+
+ If you don't want to compile a kernel exclusively for a Sun 3, say N.
-config M5206e
- bool "MCF5206e"
- select COLDFIRE
- select COLDFIRE_SW_A7
- select HAVE_MBAR
- help
- Motorola ColdFire 5206e processor support.
-
-config M520x
- bool "MCF520x"
- select COLDFIRE
- select GENERIC_CLOCKEVENTS
- select HAVE_CACHE_SPLIT
- help
- Freescale Coldfire 5207/5208 processor support.
-
-config M523x
- bool "MCF523x"
- select COLDFIRE
- select GENERIC_CLOCKEVENTS
- select HAVE_CACHE_SPLIT
- select HAVE_IPSBAR
- help
- Freescale Coldfire 5230/1/2/4/5 processor support
-
-config M5249
- bool "MCF5249"
- select COLDFIRE
- select COLDFIRE_SW_A7
- select HAVE_MBAR
- help
- Motorola ColdFire 5249 processor support.
-
-config M5271
- bool "MCF5271"
- select COLDFIRE
- select HAVE_CACHE_SPLIT
- select HAVE_IPSBAR
- help
- Freescale (Motorola) ColdFire 5270/5271 processor support.
-
-config M5272
- bool "MCF5272"
- select COLDFIRE
- select COLDFIRE_SW_A7
- select HAVE_MBAR
- help
- Motorola ColdFire 5272 processor support.
-
-config M5275
- bool "MCF5275"
- select COLDFIRE
- select HAVE_CACHE_SPLIT
- select HAVE_IPSBAR
- help
- Freescale (Motorola) ColdFire 5274/5275 processor support.
-
-config M528x
- bool "MCF528x"
- select COLDFIRE
- select GENERIC_CLOCKEVENTS
- select HAVE_CACHE_SPLIT
- select HAVE_IPSBAR
- help
- Motorola ColdFire 5280/5282 processor support.
-
-config M5307
- bool "MCF5307"
- select COLDFIRE
- select COLDFIRE_SW_A7
- select HAVE_CACHE_CB
- select HAVE_MBAR
- help
- Motorola ColdFire 5307 processor support.
-
-config M532x
- bool "MCF532x"
- select COLDFIRE
- select HAVE_CACHE_CB
- help
- Freescale (Motorola) ColdFire 532x processor support.
-
-config M5407
- bool "MCF5407"
- select COLDFIRE
- select COLDFIRE_SW_A7
- select HAVE_CACHE_CB
- select HAVE_MBAR
- help
- Motorola ColdFire 5407 processor support.
-
-config M547x
- bool "MCF547x"
- select COLDFIRE
- select HAVE_CACHE_CB
- select HAVE_MBAR
- help
- Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
-
-config M548x
- bool "MCF548x"
- select COLDFIRE
- select HAVE_CACHE_CB
- select HAVE_MBAR
- help
- Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
-
-endchoice
-
-config M527x
- bool
- depends on (M5271 || M5275)
- select GENERIC_CLOCKEVENTS
- default y
-
-config M54xx
+config PILOT
bool
- depends on (M548x || M547x)
- default y
-
-config CLOCK_SET
- bool "Enable setting the CPU clock frequency"
- default n
- help
- On some CPU's you do not need to know what the core CPU clock
- frequency is. On these you can disable clock setting. On some
- traditional 68K parts, and on all ColdFire parts you need to set
- the appropriate CPU clock frequency. On these devices many of the
- onboard peripherals derive their timing from the master CPU clock
- frequency.
-
-config CLOCK_FREQ
- int "Set the core clock frequency"
- default "66666666"
- depends on CLOCK_SET
- help
- Define the CPU clock frequency in use. This is the core clock
- frequency, it may or may not be the same as the external clock
- crystal fitted to your board. Some processors have an internal
- PLL and can have their frequency programmed at run time, others
- use internal dividers. In general the kernel won't setup a PLL
- if it is fitted (there are some exceptions). This value will be
- specific to the exact CPU that you are using.
-
-config OLDMASK
- bool "Old mask 5307 (1H55J) silicon"
- depends on M5307
- help
- Build support for the older revision ColdFire 5307 silicon.
- Specifically this is the 1H55J mask revision.
-
-if HAVE_CACHE_SPLIT
-choice
- prompt "Split Cache Configuration"
- default CACHE_I
-
-config CACHE_I
- bool "Instruction"
- help
- Use all of the ColdFire CPU cache memory as an instruction cache.
-
-config CACHE_D
- bool "Data"
- help
- Use all of the ColdFire CPU cache memory as a data cache.
-
-config CACHE_BOTH
- bool "Both"
- help
- Split the ColdFire CPU cache, and use half as an instruction cache
- and half as a data cache.
-endchoice
-endif
-
-if HAVE_CACHE_CB
-choice
- prompt "Data cache mode"
- default CACHE_WRITETHRU
-
-config CACHE_WRITETHRU
- bool "Write-through"
- help
- The ColdFire CPU cache is set into Write-through mode.
-
-config CACHE_COPYBACK
- bool "Copy-back"
- help
- The ColdFire CPU cache is set into Copy-back mode.
-endchoice
-endif
-
-comment "Platform"
config PILOT3
bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support"
depends on M68328
+ select PILOT
help
Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
@@ -302,7 +147,7 @@ config XCOPILOT_BUGS
Support the bugs of Xcopilot.
config UC5272
- bool 'Arcturus Networks uC5272 dimm board support'
+ bool "Arcturus Networks uC5272 dimm board support"
depends on M5272
help
Support for the Arcturus Networks uC5272 dimm board.
@@ -356,15 +201,23 @@ config UCQUICC
help
Support for the Lineo uCquicc board.
+config ARNEWSH
+ bool
+
config ARN5206
bool "Arnewsh 5206 board support"
depends on M5206
+ select ARNEWSH
help
Support for the Arnewsh 5206 board.
+config FREESCALE
+ bool
+
config M5206eC3
bool "Motorola M5206eC3 board support"
depends on M5206e
+ select FREESCALE
help
Support for the Motorola M5206eC3 board.
@@ -377,75 +230,92 @@ config ELITE
config M5208EVB
bool "Freescale M5208EVB board support"
depends on M520x
+ select FREESCALE
help
Support for the Freescale Coldfire M5208EVB.
config M5235EVB
bool "Freescale M5235EVB support"
depends on M523x
+ select FREESCALE
help
Support for the Freescale M5235EVB board.
config M5249C3
bool "Motorola M5249C3 board support"
depends on M5249
+ select FREESCALE
help
Support for the Motorola M5249C3 board.
config M5271EVB
bool "Freescale (Motorola) M5271EVB board support"
depends on M5271
+ select FREESCALE
help
Support for the Freescale (Motorola) M5271EVB board.
config M5275EVB
bool "Freescale (Motorola) M5275EVB board support"
depends on M5275
+ select FREESCALE
help
Support for the Freescale (Motorola) M5275EVB board.
config M5272C3
bool "Motorola M5272C3 board support"
depends on M5272
+ select FREESCALE
help
Support for the Motorola M5272C3 board.
+config senTec
+ bool
+
config COBRA5272
bool "senTec COBRA5272 board support"
depends on M5272
+ select senTec
help
Support for the senTec COBRA5272 board.
+config AVNET
+ bool
+
config AVNET5282
bool "Avnet 5282 board support"
depends on M528x
+ select AVNET
help
- Support for the Avnet 5282 board.
-
+ Support for the Avnet 5282 board.
+
config M5282EVB
bool "Motorola M5282EVB board support"
depends on M528x
+ select FREESCALE
help
Support for the Motorola M5282EVB board.
config COBRA5282
bool "senTec COBRA5282 board support"
depends on M528x
+ select senTec
help
Support for the senTec COBRA5282 board.
-
+
config SOM5282EM
bool "EMAC.Inc SOM5282EM board support"
depends on M528x
+ select EMAC_INC
help
- Support for the EMAC.Inc SOM5282EM module.
-
+ Support for the EMAC.Inc SOM5282EM module.
+
config WILDFIRE
bool "Intec Automation Inc. WildFire board support"
depends on M528x
help
Support for the Intec Automation Inc. WildFire.
-
+
config WILDFIREMOD
bool "Intec Automation Inc. WildFire module support"
depends on M528x
@@ -455,12 +325,14 @@ config WILDFIREMOD
config ARN5307
bool "Arnewsh 5307 board support"
depends on M5307
+ select ARNEWSH
help
Support for the Arnewsh 5307 board.
config M5307C3
bool "Motorola M5307C3 board support"
depends on M5307
+ select FREESCALE
help
Support for the Motorola M5307C3 board.
@@ -473,6 +345,7 @@ config SECUREEDGEMP3
config M5329EVB
bool "Freescale (Motorola) M5329EVB board support"
depends on M532x
+ select FREESCALE
help
Support for the Freescale (Motorola) M5329EVB board.
@@ -485,6 +358,7 @@ config COBRA5329
config M5407C3
bool "Motorola M5407C3 board support"
depends on M5407
+ select FREESCALE
help
Support for the Motorola M5407C3 board.
@@ -524,9 +398,13 @@ config SNAPGEAR
help
Special additional support for SnapGear router boards.
+config SNEHA
+ bool
+
config CPU16B
bool "Sneha Technologies S.L. Sarasvati board support"
depends on M5272
+ select SNEHA
help
Support for the SNEHA CPU16B board.
@@ -536,63 +414,20 @@ config MOD5272
help
Support for the Netburner MOD-5272 board.
+config SAVANT
+ bool
+
config SAVANTrosie1
bool "Savant Rosie1 board support"
depends on M523x
+ select SAVANT
help
Support for the Savant Rosie1 board.
-config ROMFS_FROM_ROM
- bool "ROMFS image not RAM resident"
- depends on (NETtel || SNAPGEAR)
- help
- The ROMfs filesystem will stay resident in the FLASH/ROM, not be
- moved into RAM.
-
-config PILOT
- bool
- default y
- depends on (PILOT3 || PILOT5)
-
-config ARNEWSH
- bool
- default y
- depends on (ARN5206 || ARN5307)
-
-config FREESCALE
- bool
- default y
- depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5329EVB || M5407C3)
-
-config HW_FEITH
- bool
- default y
- depends on (CLEOPATRA || CANCam || SCALES)
-
-config senTec
- bool
- default y
- depends on (COBRA5272 || COBRA5282)
-
-config EMAC_INC
- bool
- default y
- depends on (SOM5282EM)
-config SNEHA
- bool
- default y
- depends on CPU16B
+if !MMU || COLDFIRE
-config SAVANT
- bool
- default y
- depends on SAVANTrosie1
-
-config AVNET
- bool
- default y
- depends on (AVNET5282)
+comment "Machine Options"
config UBOOT
bool "Support for U-Boot command line parameters"
@@ -673,33 +508,6 @@ config KERNELBASE
a system with the RAM based at address 0, and leaving enough room
for the theoretical maximum number of 256 vectors.
-choice
- prompt "RAM bus width"
- default RAMAUTOBIT
-
-config RAMAUTOBIT
- bool "AUTO"
- help
- Select the physical RAM data bus size. Not needed on most platforms,
- so you can generally choose AUTO.
-
-config RAM8BIT
- bool "8bit"
- help
- Configure RAM bus to be 8 bits wide.
-
-config RAM16BIT
- bool "16bit"
- help
- Configure RAM bus to be 16 bits wide.
-
-config RAM32BIT
- bool "32bit"
- help
- Configure RAM bus to be 32 bits wide.
-
-endchoice
-
comment "ROM configuration"
config ROM
@@ -772,16 +580,4 @@ config ROMKERNEL
endchoice
-if COLDFIRE
-source "kernel/Kconfig.preempt"
endif
-
-source "kernel/time/Kconfig"
-
-config ISA_DMA_API
- bool
- depends on !M5272
- default y
-
-source "drivers/pcmcia/Kconfig"
-
diff --git a/arch/m68k/Kconfig.mmu b/arch/m68k/Kconfig.mmu
deleted file mode 100644
index 13e20bbc4079..000000000000
--- a/arch/m68k/Kconfig.mmu
+++ /dev/null
@@ -1,411 +0,0 @@
-config GENERIC_IOMAP
- bool
- default y
-
-config ARCH_MAY_HAVE_PC_FDC
- bool
- depends on BROKEN && (Q40 || SUN3X)
- default y
-
-config ARCH_USES_GETTIMEOFFSET
- def_bool y
-
-config EISA
- bool
- ---help---
- The Extended Industry Standard Architecture (EISA) bus was
- developed as an open alternative to the IBM MicroChannel bus.
-
- The EISA bus provided some of the features of the IBM MicroChannel
- bus while maintaining backward compatibility with cards made for
- the older ISA bus. The EISA bus saw limited use between 1988 and
- 1995 when it was made obsolete by the PCI bus.
-
- Say Y here if you are building a kernel for an EISA-based machine.
-
- Otherwise, say N.
-
-config MCA
- bool
- help
- MicroChannel Architecture is found in some IBM PS/2 machines and
- laptops. It is a bus system similar to PCI or ISA. See
- <file:Documentation/mca.txt> (and especially the web page given
- there) before attempting to build an MCA bus kernel.
-
-config PCMCIA
- tristate
- ---help---
- Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
- computer. These are credit-card size devices such as network cards,
- modems or hard drives often used with laptops computers. There are
- actually two varieties of these cards: the older 16 bit PCMCIA cards
- and the newer 32 bit CardBus cards. If you want to use CardBus
- cards, you need to say Y here and also to "CardBus support" below.
-
- To use your PC-cards, you will need supporting software from David
- Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
- for location). Please also read the PCMCIA-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as modules, choose M here: the
- modules will be called pcmcia_core and ds.
-
-config AMIGA
- bool "Amiga support"
- select MMU_MOTOROLA if MMU
- help
- This option enables support for the Amiga series of computers. If
- you plan to use this kernel on an Amiga, say Y here and browse the
- material available in <file:Documentation/m68k>; otherwise say N.
-
-config ATARI
- bool "Atari support"
- select MMU_MOTOROLA if MMU
- help
- This option enables support for the 68000-based Atari series of
- computers (including the TT, Falcon and Medusa). If you plan to use
- this kernel on an Atari, say Y here and browse the material
- available in <file:Documentation/m68k>; otherwise say N.
-
-config MAC
- bool "Macintosh support"
- select MMU_MOTOROLA if MMU
- help
- This option enables support for the Apple Macintosh series of
- computers (yes, there is experimental support now, at least for part
- of the series).
-
- Say N unless you're willing to code the remaining necessary support.
- ;)
-
-config NUBUS
- bool
- depends on MAC
- default y
-
-config M68K_L2_CACHE
- bool
- depends on MAC
- default y
-
-config APOLLO
- bool "Apollo support"
- select MMU_MOTOROLA if MMU
- help
- Say Y here if you want to run Linux on an MC680x0-based Apollo
- Domain workstation such as the DN3500.
-
-config VME
- bool "VME (Motorola and BVM) support"
- select MMU_MOTOROLA if MMU
- help
- Say Y here if you want to build a kernel for a 680x0 based VME
- board. Boards currently supported include Motorola boards MVME147,
- MVME162, MVME166, MVME167, MVME172, and MVME177. BVME4000 and
- BVME6000 boards from BVM Ltd are also supported.
-
-config MVME147
- bool "MVME147 support"
- depends on VME
- help
- Say Y to include support for early Motorola VME boards. This will
- build a kernel which can run on MVME147 single-board computers. If
- you select this option you will have to select the appropriate
- drivers for SCSI, Ethernet and serial ports later on.
-
-config MVME16x
- bool "MVME162, 166 and 167 support"
- depends on VME
- help
- Say Y to include support for Motorola VME boards. This will build a
- kernel which can run on MVME162, MVME166, MVME167, MVME172, and
- MVME177 boards. If you select this option you will have to select
- the appropriate drivers for SCSI, Ethernet and serial ports later
- on.
-
-config BVME6000
- bool "BVME4000 and BVME6000 support"
- depends on VME
- help
- Say Y to include support for VME boards from BVM Ltd. This will
- build a kernel which can run on BVME4000 and BVME6000 boards. If
- you select this option you will have to select the appropriate
- drivers for SCSI, Ethernet and serial ports later on.
-
-config HP300
- bool "HP9000/300 and HP9000/400 support"
- select MMU_MOTOROLA if MMU
- help
- This option enables support for the HP9000/300 and HP9000/400 series
- of workstations. Support for these machines is still somewhat
- experimental. If you plan to try to use the kernel on such a machine
- say Y here.
- Everybody else says N.
-
-config DIO
- bool "DIO bus support"
- depends on HP300
- default y
- help
- Say Y here to enable support for the "DIO" expansion bus used in
- HP300 machines. If you are using such a system you almost certainly
- want this.
-
-config SUN3X
- bool "Sun3x support"
- select MMU_MOTOROLA if MMU
- select M68030
- help
- This option enables support for the Sun 3x series of workstations.
- Be warned that this support is very experimental.
- Note that Sun 3x kernels are not compatible with Sun 3 hardware.
- General Linux information on the Sun 3x series (now discontinued)
- is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
-
- If you don't want to compile a kernel for a Sun 3x, say N.
-
-config Q40
- bool "Q40/Q60 support"
- select MMU_MOTOROLA if MMU
- help
- The Q40 is a Motorola 68040-based successor to the Sinclair QL
- manufactured in Germany. There is an official Q40 home page at
- <http://www.q40.de/>. This option enables support for the Q40 and
- Q60. Select your CPU below. For 68LC060 don't forget to enable FPU
- emulation.
-
-config SUN3
- bool "Sun3 support"
- depends on !MMU_MOTOROLA
- select MMU_SUN3 if MMU
- select M68020
- help
- This option enables support for the Sun 3 series of workstations
- (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
- that all other hardware types must be disabled, as Sun 3 kernels
- are incompatible with all other m68k targets (including Sun 3x!).
-
- If you don't want to compile a kernel exclusively for a Sun 3, say N.
-
-config NATFEAT
- bool "ARAnyM emulator support"
- depends on ATARI
- help
- This option enables support for ARAnyM native features, such as
- access to a disk image as /dev/hda.
-
-config NFBLOCK
- tristate "NatFeat block device support"
- depends on BLOCK && NATFEAT
- help
- Say Y to include support for the ARAnyM NatFeat block device
- which allows direct access to the hard drives without using
- the hardware emulation.
-
-config NFCON
- tristate "NatFeat console driver"
- depends on NATFEAT
- help
- Say Y to include support for the ARAnyM NatFeat console driver
- which allows the console output to be redirected to the stderr
- output of ARAnyM.
-
-config NFETH
- tristate "NatFeat Ethernet support"
- depends on NET_ETHERNET && NATFEAT
- help
- Say Y to include support for the ARAnyM NatFeat network device
- which will emulate a regular ethernet device while presenting an
- ethertap device to the host system.
-
-comment "Processor type"
-
-config M68020
- bool "68020 support"
- help
- If you anticipate running this kernel on a computer with a MC68020
- processor, say Y. Otherwise, say N. Note that the 68020 requires a
- 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
- Sun 3, which provides its own version.
-
-config M68030
- bool "68030 support"
- depends on !MMU_SUN3
- help
- If you anticipate running this kernel on a computer with a MC68030
- processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
- work, as it does not include an MMU (Memory Management Unit).
-
-config M68040
- bool "68040 support"
- depends on !MMU_SUN3
- help
- If you anticipate running this kernel on a computer with a MC68LC040
- or MC68040 processor, say Y. Otherwise, say N. Note that an
- MC68EC040 will not work, as it does not include an MMU (Memory
- Management Unit).
-
-config M68060
- bool "68060 support"
- depends on !MMU_SUN3
- help
- If you anticipate running this kernel on a computer with a MC68060
- processor, say Y. Otherwise, say N.
-
-config MMU_MOTOROLA
- bool
-
-config MMU_SUN3
- bool
- depends on MMU && !MMU_MOTOROLA
-
-config M68KFPU_EMU
- bool "Math emulation support (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- help
- At some point in the future, this will cause floating-point math
- instructions to be emulated by the kernel on machines that lack a
- floating-point math coprocessor. Thrill-seekers and chronically
- sleep-deprived psychotic hacker types can say Y now, everyone else
- should probably wait a while.
-
-config M68KFPU_EMU_EXTRAPREC
- bool "Math emulation extra precision"
- depends on M68KFPU_EMU
- help
- The fpu uses normally a few bit more during calculations for
- correct rounding, the emulator can (often) do the same but this
- extra calculation can cost quite some time, so you can disable
- it here. The emulator will then "only" calculate with a 64 bit
- mantissa and round slightly incorrect, what is more than enough
- for normal usage.
-
-config M68KFPU_EMU_ONLY
- bool "Math emulation only kernel"
- depends on M68KFPU_EMU
- help
- This option prevents any floating-point instructions from being
- compiled into the kernel, thereby the kernel doesn't save any
- floating point context anymore during task switches, so this
- kernel will only be usable on machines without a floating-point
- math coprocessor. This makes the kernel a bit faster as no tests
- needs to be executed whether a floating-point instruction in the
- kernel should be executed or not.
-
-config ADVANCED
- bool "Advanced configuration options"
- ---help---
- This gives you access to some advanced options for the CPU. The
- defaults should be fine for most users, but these options may make
- it possible for you to improve performance somewhat if you know what
- you are doing.
-
- Note that the answer to this question won't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about these options.
-
- Most users should say N to this question.
-
-config RMW_INSNS
- bool "Use read-modify-write instructions"
- depends on ADVANCED
- ---help---
- This allows to use certain instructions that work with indivisible
- read-modify-write bus cycles. While this is faster than the
- workaround of disabling interrupts, it can conflict with DMA
- ( = direct memory access) on many Amiga systems, and it is also said
- to destabilize other machines. It is very likely that this will
- cause serious problems on any Amiga or Atari Medusa if set. The only
- configuration where it should work are 68030-based Ataris, where it
- apparently improves performance. But you've been warned! Unless you
- really know what you are doing, say N. Try Y only if you're quite
- adventurous.
-
-config SINGLE_MEMORY_CHUNK
- bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
- default y if SUN3
- select NEED_MULTIPLE_NODES
- help
- Ignore all but the first contiguous chunk of physical memory for VM
- purposes. This will save a few bytes kernel size and may speed up
- some operations. Say N if not sure.
-
-config 060_WRITETHROUGH
- bool "Use write-through caching for 68060 supervisor accesses"
- depends on ADVANCED && M68060
- ---help---
- The 68060 generally uses copyback caching of recently accessed data.
- Copyback caching means that memory writes will be held in an on-chip
- cache and only written back to memory some time later. Saying Y
- here will force supervisor (kernel) accesses to use writethrough
- caching. Writethrough caching means that data is written to memory
- straight away, so that cache and memory data always agree.
- Writethrough caching is less efficient, but is needed for some
- drivers on 68060 based systems where the 68060 bus snooping signal
- is hardwired on. The 53c710 SCSI driver is known to suffer from
- this problem.
-
-config ARCH_DISCONTIGMEM_ENABLE
- def_bool !SINGLE_MEMORY_CHUNK
-
-config NODES_SHIFT
- int
- default "3"
- depends on !SINGLE_MEMORY_CHUNK
-
-config ZORRO
- bool "Amiga Zorro (AutoConfig) bus support"
- depends on AMIGA
- help
- This enables support for the Zorro bus in the Amiga. If you have
- expansion cards in your Amiga that conform to the Amiga
- AutoConfig(tm) specification, say Y, otherwise N. Note that even
- expansion cards that do not fit in the Zorro slots but fit in e.g.
- the CPU slot may fall in this category, so you have to say Y to let
- Linux use these.
-
-config AMIGA_PCMCIA
- bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
- depends on AMIGA && EXPERIMENTAL
- help
- Include support in the kernel for pcmcia on Amiga 1200 and Amiga
- 600. If you intend to use pcmcia cards say Y; otherwise say N.
-
-config HEARTBEAT
- bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
- default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
- help
- Use the power-on LED on your machine as a load meter. The exact
- behavior is platform-dependent, but normally the flash frequency is
- a hyperbolic function of the 5-minute load average.
-
-# We have a dedicated heartbeat LED. :-)
-config PROC_HARDWARE
- bool "/proc/hardware support"
- help
- Say Y here to support the /proc/hardware file, which gives you
- access to information about the machine you're running on,
- including the model, CPU, MMU, clock speed, BogoMIPS rating,
- and memory size.
-
-config ISA
- bool
- depends on Q40 || AMIGA_PCMCIA
- default y
- help
- Find out whether you have ISA slots on your motherboard. ISA is the
- name of a bus system, i.e. the way the CPU talks to the other stuff
- inside your box. Other bus systems are PCI, EISA, MicroChannel
- (MCA) or VESA. ISA is an older system, now being displaced by PCI;
- newer boards don't support it. If you have ISA, say Y, otherwise N.
-
-config GENERIC_ISA_DMA
- bool
- depends on Q40 || AMIGA_PCMCIA
- default y
-
-source "drivers/pci/Kconfig"
-
-source "drivers/zorro/Kconfig"
-
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index be46cadd4017..cf318f20c64d 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -1,7 +1,171 @@
+#
+# m68k/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Hamish Macdonald
+# Copyright (C) 2002,2011 Greg Ungerer <gerg@snapgear.com>
+#
+
KBUILD_DEFCONFIG := multi_defconfig
+#
+# Enable processor type. Ordering of these is important - we want to
+# use the minimum processor type of the range we support. The logic
+# for 680x0 will only allow use of the -m68060 or -m68040 if no other
+# 680x0 type is specified - and no option is specified for 68030 or
+# 68020. The other m68k/ColdFire types always specify some type of
+# compiler cpu type flag.
+#
+ifndef CONFIG_M68040
+cpuflags-$(CONFIG_M68060) := -m68060
+endif
+ifndef CONFIG_M68060
+cpuflags-$(CONFIG_M68040) := -m68040
+endif
+cpuflags-$(CONFIG_M68030) :=
+cpuflags-$(CONFIG_M68020) :=
+cpuflags-$(CONFIG_M68360) := -m68332
+cpuflags-$(CONFIG_M68000) := -m68000
+cpuflags-$(CONFIG_M54xx) := $(call cc-option,-mcpu=5475,-m5200)
+cpuflags-$(CONFIG_M5407) := $(call cc-option,-mcpu=5407,-m5200)
+cpuflags-$(CONFIG_M532x) := $(call cc-option,-mcpu=532x,-m5307)
+cpuflags-$(CONFIG_M5307) := $(call cc-option,-mcpu=5307,-m5200)
+cpuflags-$(CONFIG_M528x) := $(call cc-option,-mcpu=528x,-m5307)
+cpuflags-$(CONFIG_M5275) := $(call cc-option,-mcpu=5275,-m5307)
+cpuflags-$(CONFIG_M5272) := $(call cc-option,-mcpu=5272,-m5307)
+cpuflags-$(CONFIG_M5271) := $(call cc-option,-mcpu=5271,-m5307)
+cpuflags-$(CONFIG_M523x) := $(call cc-option,-mcpu=523x,-m5307)
+cpuflags-$(CONFIG_M5249) := $(call cc-option,-mcpu=5249,-m5200)
+cpuflags-$(CONFIG_M520x) := $(call cc-option,-mcpu=5208,-m5200)
+cpuflags-$(CONFIG_M5206e) := $(call cc-option,-mcpu=5206e,-m5200)
+cpuflags-$(CONFIG_M5206) := $(call cc-option,-mcpu=5206,-m5200)
+
+KBUILD_AFLAGS += $(cpuflags-y)
+KBUILD_CFLAGS += $(cpuflags-y) -pipe
ifdef CONFIG_MMU
-include $(srctree)/arch/m68k/Makefile_mm
+# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
+KBUILD_CFLAGS += -fno-strength-reduce -ffixed-a2
+else
+# we can use a m68k-linux-gcc toolchain with these in place
+KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
+KBUILD_CFLAGS += -D__uClinux__
+KBUILD_AFLAGS += -D__uClinux__
+endif
+
+LDFLAGS := -m m68kelf
+KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
+ifneq ($(SUBARCH),$(ARCH))
+ ifeq ($(CROSS_COMPILE),)
+ CROSS_COMPILE := $(call cc-cross-prefix, \
+ m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
+ endif
+endif
+
+ifdef CONFIG_SUN3
+LDFLAGS_vmlinux = -N
+endif
+
+CHECKFLAGS += -D__mc68000__
+
+
+ifdef CONFIG_KGDB
+# If configured for kgdb support, include debugging infos and keep the
+# frame pointer
+KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
+endif
+
+#
+# Select the assembler head startup code. Order is important. The default
+# head code is first, processor specific selections can override it after.
+#
+head-y := arch/m68k/kernel/head.o
+head-$(CONFIG_SUN3) := arch/m68k/kernel/sun3-head.o
+head-$(CONFIG_M68360) := arch/m68k/platform/68360/head.o
+head-$(CONFIG_M68000) := arch/m68k/platform/68328/head.o
+head-$(CONFIG_COLDFIRE) := arch/m68k/platform/coldfire/head.o
+
+core-y += arch/m68k/kernel/ arch/m68k/mm/
+libs-y += arch/m68k/lib/
+
+core-$(CONFIG_Q40) += arch/m68k/q40/
+core-$(CONFIG_AMIGA) += arch/m68k/amiga/
+core-$(CONFIG_ATARI) += arch/m68k/atari/
+core-$(CONFIG_MAC) += arch/m68k/mac/
+core-$(CONFIG_HP300) += arch/m68k/hp300/
+core-$(CONFIG_APOLLO) += arch/m68k/apollo/
+core-$(CONFIG_MVME147) += arch/m68k/mvme147/
+core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/
+core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/
+core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/
+core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/
+core-$(CONFIG_NATFEAT) += arch/m68k/emu/
+core-$(CONFIG_M68040) += arch/m68k/fpsp040/
+core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
+core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
+core-$(CONFIG_M68360) += arch/m68k/platform/68360/
+core-$(CONFIG_M68000) += arch/m68k/platform/68328/
+core-$(CONFIG_M68EZ328) += arch/m68k/platform/68EZ328/
+core-$(CONFIG_M68VZ328) += arch/m68k/platform/68VZ328/
+core-$(CONFIG_COLDFIRE) += arch/m68k/platform/coldfire/
+core-$(CONFIG_M5206) += arch/m68k/platform/5206/
+core-$(CONFIG_M5206e) += arch/m68k/platform/5206/
+core-$(CONFIG_M520x) += arch/m68k/platform/520x/
+core-$(CONFIG_M523x) += arch/m68k/platform/523x/
+core-$(CONFIG_M5249) += arch/m68k/platform/5249/
+core-$(CONFIG_M527x) += arch/m68k/platform/527x/
+core-$(CONFIG_M5272) += arch/m68k/platform/5272/
+core-$(CONFIG_M528x) += arch/m68k/platform/528x/
+core-$(CONFIG_M5307) += arch/m68k/platform/5307/
+core-$(CONFIG_M532x) += arch/m68k/platform/532x/
+core-$(CONFIG_M5407) += arch/m68k/platform/5407/
+core-$(CONFIG_M54xx) += arch/m68k/platform/54xx/
+
+
+all: zImage
+
+lilo: vmlinux
+ if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
+ if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
+ cat vmlinux > $(INSTALL_PATH)/vmlinux
+ cp System.map $(INSTALL_PATH)/System.map
+ if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+
+zImage compressed: vmlinux.gz
+
+vmlinux.gz: vmlinux
+
+ifndef CONFIG_KGDB
+ cp vmlinux vmlinux.tmp
+ $(STRIP) vmlinux.tmp
+ gzip -9c vmlinux.tmp >vmlinux.gz
+ rm vmlinux.tmp
else
-include $(srctree)/arch/m68k/Makefile_no
+ gzip -9c vmlinux >vmlinux.gz
endif
+
+bzImage: vmlinux.bz2
+
+vmlinux.bz2: vmlinux
+
+ifndef CONFIG_KGDB
+ cp vmlinux vmlinux.tmp
+ $(STRIP) vmlinux.tmp
+ bzip2 -1c vmlinux.tmp >vmlinux.bz2
+ rm vmlinux.tmp
+else
+ bzip2 -1c vmlinux >vmlinux.bz2
+endif
+
+archclean:
+ rm -f vmlinux.gz vmlinux.bz2
+
+install:
+ sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
diff --git a/arch/m68k/Makefile_mm b/arch/m68k/Makefile_mm
deleted file mode 100644
index d449b6d5aecf..000000000000
--- a/arch/m68k/Makefile_mm
+++ /dev/null
@@ -1,121 +0,0 @@
-#
-# m68k/Makefile
-#
-# This file is included by the global makefile so that you can add your own
-# architecture-specific flags and dependencies. Remember to do have actions
-# for "archclean" and "archdep" for cleaning up and making dependencies for
-# this architecture
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1994 by Hamish Macdonald
-#
-
-# override top level makefile
-AS += -m68020
-LDFLAGS := -m m68kelf
-KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
-ifneq ($(SUBARCH),$(ARCH))
- ifeq ($(CROSS_COMPILE),)
- CROSS_COMPILE := $(call cc-cross-prefix, \
- m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
- endif
-endif
-
-ifdef CONFIG_SUN3
-LDFLAGS_vmlinux = -N
-endif
-
-CHECKFLAGS += -D__mc68000__
-
-# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
-KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
-
-# enable processor switch if compiled only for a single cpu
-ifndef CONFIG_M68020
-ifndef CONFIG_M68030
-
-ifndef CONFIG_M68060
-KBUILD_CFLAGS += -m68040
-endif
-
-ifndef CONFIG_M68040
-KBUILD_CFLAGS += -m68060
-endif
-
-endif
-endif
-
-ifdef CONFIG_KGDB
-# If configured for kgdb support, include debugging infos and keep the
-# frame pointer
-KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
-endif
-
-ifndef CONFIG_SUN3
-head-y := arch/m68k/kernel/head.o
-else
-head-y := arch/m68k/kernel/sun3-head.o
-endif
-
-core-y += arch/m68k/kernel/ arch/m68k/mm/
-libs-y += arch/m68k/lib/
-
-core-$(CONFIG_Q40) += arch/m68k/q40/
-core-$(CONFIG_AMIGA) += arch/m68k/amiga/
-core-$(CONFIG_ATARI) += arch/m68k/atari/
-core-$(CONFIG_MAC) += arch/m68k/mac/
-core-$(CONFIG_HP300) += arch/m68k/hp300/
-core-$(CONFIG_APOLLO) += arch/m68k/apollo/
-core-$(CONFIG_MVME147) += arch/m68k/mvme147/
-core-$(CONFIG_MVME16x) += arch/m68k/mvme16x/
-core-$(CONFIG_BVME6000) += arch/m68k/bvme6000/
-core-$(CONFIG_SUN3X) += arch/m68k/sun3x/ arch/m68k/sun3/
-core-$(CONFIG_SUN3) += arch/m68k/sun3/ arch/m68k/sun3/prom/
-core-$(CONFIG_NATFEAT) += arch/m68k/emu/
-core-$(CONFIG_M68040) += arch/m68k/fpsp040/
-core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
-core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
-
-all: zImage
-
-lilo: vmlinux
- if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
- if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
- cat vmlinux > $(INSTALL_PATH)/vmlinux
- cp System.map $(INSTALL_PATH)/System.map
- if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-
-zImage compressed: vmlinux.gz
-
-vmlinux.gz: vmlinux
-
-ifndef CONFIG_KGDB
- cp vmlinux vmlinux.tmp
- $(STRIP) vmlinux.tmp
- gzip -9c vmlinux.tmp >vmlinux.gz
- rm vmlinux.tmp
-else
- gzip -9c vmlinux >vmlinux.gz
-endif
-
-bzImage: vmlinux.bz2
-
-vmlinux.bz2: vmlinux
-
-ifndef CONFIG_KGDB
- cp vmlinux vmlinux.tmp
- $(STRIP) vmlinux.tmp
- bzip2 -1c vmlinux.tmp >vmlinux.bz2
- rm vmlinux.tmp
-else
- bzip2 -1c vmlinux >vmlinux.bz2
-endif
-
-archclean:
- rm -f vmlinux.gz vmlinux.bz2
-
-install:
- sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
diff --git a/arch/m68k/Makefile_no b/arch/m68k/Makefile_no
deleted file mode 100644
index 844d3f172264..000000000000
--- a/arch/m68k/Makefile_no
+++ /dev/null
@@ -1,124 +0,0 @@
-#
-# arch/m68k/Makefile
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# (C) Copyright 2002, Greg Ungerer <gerg@snapgear.com>
-#
-
-platform-$(CONFIG_M68328) := 68328
-platform-$(CONFIG_M68EZ328) := 68EZ328
-platform-$(CONFIG_M68VZ328) := 68VZ328
-platform-$(CONFIG_M68360) := 68360
-platform-$(CONFIG_M5206) := 5206
-platform-$(CONFIG_M5206e) := 5206
-platform-$(CONFIG_M520x) := 520x
-platform-$(CONFIG_M523x) := 523x
-platform-$(CONFIG_M5249) := 5249
-platform-$(CONFIG_M527x) := 527x
-platform-$(CONFIG_M5272) := 5272
-platform-$(CONFIG_M528x) := 528x
-platform-$(CONFIG_M5307) := 5307
-platform-$(CONFIG_M532x) := 532x
-platform-$(CONFIG_M5407) := 5407
-platform-$(CONFIG_M54xx) := 54xx
-PLATFORM := $(platform-y)
-
-board-$(CONFIG_PILOT) := pilot
-board-$(CONFIG_UC5272) := UC5272
-board-$(CONFIG_UC5282) := UC5282
-board-$(CONFIG_UCSIMM) := ucsimm
-board-$(CONFIG_UCDIMM) := ucdimm
-board-$(CONFIG_UCQUICC) := uCquicc
-board-$(CONFIG_DRAGEN2) := de2
-board-$(CONFIG_ARNEWSH) := ARNEWSH
-board-$(CONFIG_FREESCALE) := FREESCALE
-board-$(CONFIG_M5235EVB) := M5235EVB
-board-$(CONFIG_M5271EVB) := M5271EVB
-board-$(CONFIG_M5275EVB) := M5275EVB
-board-$(CONFIG_M5282EVB) := M5282EVB
-board-$(CONFIG_ELITE) := eLITE
-board-$(CONFIG_NETtel) := NETtel
-board-$(CONFIG_SECUREEDGEMP3) := MP3
-board-$(CONFIG_CLEOPATRA) := CLEOPATRA
-board-$(CONFIG_senTec) := senTec
-board-$(CONFIG_SNEHA) := SNEHA
-board-$(CONFIG_M5208EVB) := M5208EVB
-board-$(CONFIG_MOD5272) := MOD5272
-board-$(CONFIG_AVNET) := AVNET
-board-$(CONFIG_SAVANT) := SAVANT
-BOARD := $(board-y)
-
-model-$(CONFIG_RAMKERNEL) := ram
-model-$(CONFIG_ROMKERNEL) := rom
-MODEL := $(model-y)
-
-#
-# Some code support is grouped together for a common cpu-subclass (for
-# example all ColdFire cpu's are very similar). Determine the sub-class
-# for the selected cpu. ONLY need to define this for the non-base member
-# of the family.
-#
-cpuclass-$(CONFIG_M5206) := coldfire
-cpuclass-$(CONFIG_M5206e) := coldfire
-cpuclass-$(CONFIG_M520x) := coldfire
-cpuclass-$(CONFIG_M523x) := coldfire
-cpuclass-$(CONFIG_M5249) := coldfire
-cpuclass-$(CONFIG_M527x) := coldfire
-cpuclass-$(CONFIG_M5272) := coldfire
-cpuclass-$(CONFIG_M528x) := coldfire
-cpuclass-$(CONFIG_M5307) := coldfire
-cpuclass-$(CONFIG_M532x) := coldfire
-cpuclass-$(CONFIG_M5407) := coldfire
-cpuclass-$(CONFIG_M54xx) := coldfire
-cpuclass-$(CONFIG_M68328) := 68328
-cpuclass-$(CONFIG_M68EZ328) := 68328
-cpuclass-$(CONFIG_M68VZ328) := 68328
-cpuclass-$(CONFIG_M68360) := 68360
-CPUCLASS := $(cpuclass-y)
-
-ifneq ($(CPUCLASS),$(PLATFORM))
-CLASSDIR := arch/m68k/platform/$(cpuclass-y)/
-endif
-
-export PLATFORM BOARD MODEL CPUCLASS
-
-#
-# Some CFLAG additions based on specific CPU type.
-#
-cflags-$(CONFIG_M5206) := $(call cc-option,-mcpu=5206,-m5200)
-cflags-$(CONFIG_M5206e) := $(call cc-option,-mcpu=5206e,-m5200)
-cflags-$(CONFIG_M520x) := $(call cc-option,-mcpu=5208,-m5200)
-cflags-$(CONFIG_M523x) := $(call cc-option,-mcpu=523x,-m5307)
-cflags-$(CONFIG_M5249) := $(call cc-option,-mcpu=5249,-m5200)
-cflags-$(CONFIG_M5271) := $(call cc-option,-mcpu=5271,-m5307)
-cflags-$(CONFIG_M5272) := $(call cc-option,-mcpu=5272,-m5307)
-cflags-$(CONFIG_M5275) := $(call cc-option,-mcpu=5275,-m5307)
-cflags-$(CONFIG_M528x) := $(call cc-option,-mcpu=528x,-m5307)
-cflags-$(CONFIG_M5307) := $(call cc-option,-mcpu=5307,-m5200)
-cflags-$(CONFIG_M532x) := $(call cc-option,-mcpu=532x,-m5307)
-cflags-$(CONFIG_M5407) := $(call cc-option,-mcpu=5407,-m5200)
-cflags-$(CONFIG_M54xx) := $(call cc-option,-mcpu=5475,-m5200)
-cflags-$(CONFIG_M68328) := -m68000
-cflags-$(CONFIG_M68EZ328) := -m68000
-cflags-$(CONFIG_M68VZ328) := -m68000
-cflags-$(CONFIG_M68360) := -m68332
-
-KBUILD_AFLAGS += $(cflags-y)
-
-KBUILD_CFLAGS += $(cflags-y)
-KBUILD_CFLAGS += -D__linux__
-KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
-
-head-y := arch/m68k/platform/$(cpuclass-y)/head.o
-
-core-y += arch/m68k/kernel/ \
- arch/m68k/mm/ \
- $(CLASSDIR) \
- arch/m68k/platform/$(PLATFORM)/
-libs-y += arch/m68k/lib/
-
-archclean:
-
diff --git a/arch/m68k/include/asm/entry.h b/arch/m68k/include/asm/entry.h
index 876eec6f2b52..c3c5a8643e15 100644
--- a/arch/m68k/include/asm/entry.h
+++ b/arch/m68k/include/asm/entry.h
@@ -1,5 +1,254 @@
-#ifdef __uClinux__
-#include "entry_no.h"
+#ifndef __M68K_ENTRY_H
+#define __M68K_ENTRY_H
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#ifdef __ASSEMBLY__
+#include <asm/thread_info.h>
+#endif
+
+/*
+ * Stack layout in 'ret_from_exception':
+ *
+ * This allows access to the syscall arguments in registers d1-d5
+ *
+ * 0(sp) - d1
+ * 4(sp) - d2
+ * 8(sp) - d3
+ * C(sp) - d4
+ * 10(sp) - d5
+ * 14(sp) - a0
+ * 18(sp) - a1
+ * 1C(sp) - a2
+ * 20(sp) - d0
+ * 24(sp) - orig_d0
+ * 28(sp) - stack adjustment
+ * 2C(sp) - [ sr ] [ format & vector ]
+ * 2E(sp) - [ pc-hiword ] [ sr ]
+ * 30(sp) - [ pc-loword ] [ pc-hiword ]
+ * 32(sp) - [ format & vector ] [ pc-loword ]
+ * ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
+ * M68K COLDFIRE
+ */
+
+/* the following macro is used when enabling interrupts */
+#if defined(MACH_ATARI_ONLY)
+ /* block out HSYNC on the atari */
+#define ALLOWINT (~0x400)
+#define MAX_NOINT_IPL 3
#else
-#include "entry_mm.h"
+ /* portable version */
+#define ALLOWINT (~0x700)
+#define MAX_NOINT_IPL 0
+#endif /* machine compilation types */
+
+#ifdef __ASSEMBLY__
+/*
+ * This defines the normal kernel pt-regs layout.
+ *
+ * regs a3-a6 and d6-d7 are preserved by C code
+ * the kernel doesn't mess with usp unless it needs to
+ */
+#define SWITCH_STACK_SIZE (6*4+4) /* includes return address */
+
+#ifdef CONFIG_COLDFIRE
+#ifdef CONFIG_COLDFIRE_SW_A7
+/*
+ * This is made a little more tricky on older ColdFires. There is no
+ * separate supervisor and user stack pointers. Need to artificially
+ * construct a usp in software... When doing this we need to disable
+ * interrupts, otherwise bad things will happen.
+ */
+.globl sw_usp
+.globl sw_ksp
+
+.macro SAVE_ALL_SYS
+ move #0x2700,%sr /* disable intrs */
+ btst #5,%sp@(2) /* from user? */
+ bnes 6f /* no, skip */
+ movel %sp,sw_usp /* save user sp */
+ addql #8,sw_usp /* remove exception */
+ movel sw_ksp,%sp /* kernel sp */
+ subql #8,%sp /* room for exception */
+ clrl %sp@- /* stkadj */
+ movel %d0,%sp@- /* orig d0 */
+ movel %d0,%sp@- /* d0 */
+ lea %sp@(-32),%sp /* space for 8 regs */
+ moveml %d1-%d5/%a0-%a2,%sp@
+ movel sw_usp,%a0 /* get usp */
+ movel %a0@-,%sp@(PT_OFF_PC) /* copy exception program counter */
+ movel %a0@-,%sp@(PT_OFF_FORMATVEC)/*copy exception format/vector/sr */
+ bra 7f
+ 6:
+ clrl %sp@- /* stkadj */
+ movel %d0,%sp@- /* orig d0 */
+ movel %d0,%sp@- /* d0 */
+ lea %sp@(-32),%sp /* space for 8 regs */
+ moveml %d1-%d5/%a0-%a2,%sp@
+ 7:
+.endm
+
+.macro SAVE_ALL_INT
+ SAVE_ALL_SYS
+ moveq #-1,%d0 /* not system call entry */
+ movel %d0,%sp@(PT_OFF_ORIG_D0)
+.endm
+
+.macro RESTORE_USER
+ move #0x2700,%sr /* disable intrs */
+ movel sw_usp,%a0 /* get usp */
+ movel %sp@(PT_OFF_PC),%a0@- /* copy exception program counter */
+ movel %sp@(PT_OFF_FORMATVEC),%a0@-/*copy exception format/vector/sr */
+ moveml %sp@,%d1-%d5/%a0-%a2
+ lea %sp@(32),%sp /* space for 8 regs */
+ movel %sp@+,%d0
+ addql #4,%sp /* orig d0 */
+ addl %sp@+,%sp /* stkadj */
+ addql #8,%sp /* remove exception */
+ movel %sp,sw_ksp /* save ksp */
+ subql #8,sw_usp /* set exception */
+ movel sw_usp,%sp /* restore usp */
+ rte
+.endm
+
+.macro RDUSP
+ movel sw_usp,%a3
+.endm
+
+.macro WRUSP
+ movel %a3,sw_usp
+.endm
+
+#else /* !CONFIG_COLDFIRE_SW_A7 */
+/*
+ * Modern ColdFire parts have separate supervisor and user stack
+ * pointers. Simple load and restore macros for this case.
+ */
+.macro SAVE_ALL_SYS
+ move #0x2700,%sr /* disable intrs */
+ clrl %sp@- /* stkadj */
+ movel %d0,%sp@- /* orig d0 */
+ movel %d0,%sp@- /* d0 */
+ lea %sp@(-32),%sp /* space for 8 regs */
+ moveml %d1-%d5/%a0-%a2,%sp@
+.endm
+
+.macro SAVE_ALL_INT
+ move #0x2700,%sr /* disable intrs */
+ clrl %sp@- /* stkadj */
+ pea -1:w /* orig d0 */
+ movel %d0,%sp@- /* d0 */
+ lea %sp@(-32),%sp /* space for 8 regs */
+ moveml %d1-%d5/%a0-%a2,%sp@
+.endm
+
+.macro RESTORE_USER
+ moveml %sp@,%d1-%d5/%a0-%a2
+ lea %sp@(32),%sp /* space for 8 regs */
+ movel %sp@+,%d0
+ addql #4,%sp /* orig d0 */
+ addl %sp@+,%sp /* stkadj */
+ rte
+.endm
+
+.macro RDUSP
+ /*move %usp,%a3*/
+ .word 0x4e6b
+.endm
+
+.macro WRUSP
+ /*move %a3,%usp*/
+ .word 0x4e63
+.endm
+
+#endif /* !CONFIG_COLDFIRE_SW_A7 */
+
+.macro SAVE_SWITCH_STACK
+ lea %sp@(-24),%sp /* 6 regs */
+ moveml %a3-%a6/%d6-%d7,%sp@
+.endm
+
+.macro RESTORE_SWITCH_STACK
+ moveml %sp@,%a3-%a6/%d6-%d7
+ lea %sp@(24),%sp /* 6 regs */
+.endm
+
+#else /* !CONFIG_COLDFIRE */
+
+/*
+ * All other types of m68k parts (68000, 680x0, CPU32) have the same
+ * entry and exit code.
+ */
+
+/*
+ * a -1 in the orig_d0 field signifies
+ * that the stack frame is NOT for syscall
+ */
+.macro SAVE_ALL_INT
+ clrl %sp@- /* stk_adj */
+ pea -1:w /* orig d0 */
+ movel %d0,%sp@- /* d0 */
+ moveml %d1-%d5/%a0-%a2,%sp@-
+.endm
+
+.macro SAVE_ALL_SYS
+ clrl %sp@- /* stk_adj */
+ movel %d0,%sp@- /* orig d0 */
+ movel %d0,%sp@- /* d0 */
+ moveml %d1-%d5/%a0-%a2,%sp@-
+.endm
+
+.macro RESTORE_ALL
+ moveml %sp@+,%a0-%a2/%d1-%d5
+ movel %sp@+,%d0
+ addql #4,%sp /* orig d0 */
+ addl %sp@+,%sp /* stk adj */
+ rte
+.endm
+
+
+.macro SAVE_SWITCH_STACK
+ moveml %a3-%a6/%d6-%d7,%sp@-
+.endm
+
+.macro RESTORE_SWITCH_STACK
+ moveml %sp@+,%a3-%a6/%d6-%d7
+.endm
+
+#endif /* !CONFIG_COLDFIRE */
+
+/*
+ * Register %a2 is reserved and set to current task on MMU enabled systems.
+ * Non-MMU systems do not reserve %a2 in this way, and this definition is
+ * not used for them.
+ */
+#define curptr a2
+
+#define GET_CURRENT(tmp) get_current tmp
+.macro get_current reg=%d0
+ movel %sp,\reg
+ andw #-THREAD_SIZE,\reg
+ movel \reg,%curptr
+ movel %curptr@,%curptr
+.endm
+
+#else /* C source */
+
+#define STR(X) STR1(X)
+#define STR1(X) #X
+
+#define SAVE_ALL_INT \
+ "clrl %%sp@-;" /* stk_adj */ \
+ "pea -1:w;" /* orig d0 = -1 */ \
+ "movel %%d0,%%sp@-;" /* d0 */ \
+ "moveml %%d1-%%d5/%%a0-%%a2,%%sp@-"
+
+#define GET_CURRENT(tmp) \
+ "movel %%sp,"#tmp"\n\t" \
+ "andw #-"STR(THREAD_SIZE)","#tmp"\n\t" \
+ "movel "#tmp",%%a2\n\t" \
+ "movel %%a2@,%%a2"
+
#endif
+
+#endif /* __M68K_ENTRY_H */
diff --git a/arch/m68k/include/asm/entry_mm.h b/arch/m68k/include/asm/entry_mm.h
deleted file mode 100644
index 73b8c8fbed9c..000000000000
--- a/arch/m68k/include/asm/entry_mm.h
+++ /dev/null
@@ -1,128 +0,0 @@
-#ifndef __M68K_ENTRY_H
-#define __M68K_ENTRY_H
-
-#include <asm/setup.h>
-#include <asm/page.h>
-#ifdef __ASSEMBLY__
-#include <asm/thread_info.h>
-#endif
-
-/*
- * Stack layout in 'ret_from_exception':
- *
- * This allows access to the syscall arguments in registers d1-d5
- *
- * 0(sp) - d1
- * 4(sp) - d2
- * 8(sp) - d3
- * C(sp) - d4
- * 10(sp) - d5
- * 14(sp) - a0
- * 18(sp) - a1
- * 1C(sp) - a2
- * 20(sp) - d0
- * 24(sp) - orig_d0
- * 28(sp) - stack adjustment
- * 2C(sp) - sr
- * 2E(sp) - pc
- * 32(sp) - format & vector
- */
-
-/*
- * 97/05/14 Andreas: Register %a2 is now set to the current task throughout
- * the whole kernel.
- */
-
-/* the following macro is used when enabling interrupts */
-#if defined(MACH_ATARI_ONLY)
- /* block out HSYNC on the atari */
-#define ALLOWINT (~0x400)
-#define MAX_NOINT_IPL 3
-#else
- /* portable version */
-#define ALLOWINT (~0x700)
-#define MAX_NOINT_IPL 0
-#endif /* machine compilation types */
-
-#ifdef __ASSEMBLY__
-
-#define curptr a2
-
-LFLUSH_I_AND_D = 0x00000808
-
-#define SAVE_ALL_INT save_all_int
-#define SAVE_ALL_SYS save_all_sys
-#define RESTORE_ALL restore_all
-/*
- * This defines the normal kernel pt-regs layout.
- *
- * regs a3-a6 and d6-d7 are preserved by C code
- * the kernel doesn't mess with usp unless it needs to
- */
-
-/*
- * a -1 in the orig_d0 field signifies
- * that the stack frame is NOT for syscall
- */
-.macro save_all_int
- clrl %sp@- | stk_adj
- pea -1:w | orig d0
- movel %d0,%sp@- | d0
- moveml %d1-%d5/%a0-%a1/%curptr,%sp@-
-.endm
-
-.macro save_all_sys
- clrl %sp@- | stk_adj
- movel %d0,%sp@- | orig d0
- movel %d0,%sp@- | d0
- moveml %d1-%d5/%a0-%a1/%curptr,%sp@-
-.endm
-
-.macro restore_all
- moveml %sp@+,%a0-%a1/%curptr/%d1-%d5
- movel %sp@+,%d0
- addql #4,%sp | orig d0
- addl %sp@+,%sp | stk adj
- rte
-.endm
-
-#define SWITCH_STACK_SIZE (6*4+4) /* includes return address */
-
-#define SAVE_SWITCH_STACK save_switch_stack
-#define RESTORE_SWITCH_STACK restore_switch_stack
-#define GET_CURRENT(tmp) get_current tmp
-
-.macro save_switch_stack
- moveml %a3-%a6/%d6-%d7,%sp@-
-.endm
-
-.macro restore_switch_stack
- moveml %sp@+,%a3-%a6/%d6-%d7
-.endm
-
-.macro get_current reg=%d0
- movel %sp,\reg
- andw #-THREAD_SIZE,\reg
- movel \reg,%curptr
- movel %curptr@,%curptr
-.endm
-
-#else /* C source */
-
-#define STR(X) STR1(X)
-#define STR1(X) #X
-
-#define SAVE_ALL_INT \
- "clrl %%sp@-;" /* stk_adj */ \
- "pea -1:w;" /* orig d0 = -1 */ \
- "movel %%d0,%%sp@-;" /* d0 */ \
- "moveml %%d1-%%d5/%%a0-%%a2,%%sp@-"
-#define GET_CURRENT(tmp) \
- "movel %%sp,"#tmp"\n\t" \
- "andw #-"STR(THREAD_SIZE)","#tmp"\n\t" \
- "movel "#tmp",%%a2\n\t" \
- "movel %%a2@,%%a2"
-
-#endif
-
-#endif /* __M68K_ENTRY_H */
diff --git a/arch/m68k/include/asm/entry_no.h b/arch/m68k/include/asm/entry_no.h
deleted file mode 100644
index 68611e3dbb1d..000000000000
--- a/arch/m68k/include/asm/entry_no.h
+++ /dev/null
@@ -1,181 +0,0 @@
-#ifndef __M68KNOMMU_ENTRY_H
-#define __M68KNOMMU_ENTRY_H
-
-#include <asm/setup.h>
-#include <asm/page.h>
-
-/*
- * Stack layout in 'ret_from_exception':
- *
- * This allows access to the syscall arguments in registers d1-d5
- *
- * 0(sp) - d1
- * 4(sp) - d2
- * 8(sp) - d3
- * C(sp) - d4
- * 10(sp) - d5
- * 14(sp) - a0
- * 18(sp) - a1
- * 1C(sp) - a2
- * 20(sp) - d0
- * 24(sp) - orig_d0
- * 28(sp) - stack adjustment
- * 2C(sp) - [ sr ] [ format & vector ]
- * 2E(sp) - [ pc-hiword ] [ sr ]
- * 30(sp) - [ pc-loword ] [ pc-hiword ]
- * 32(sp) - [ format & vector ] [ pc-loword ]
- * ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
- * M68K COLDFIRE
- */
-
-#define ALLOWINT (~0x700)
-
-#ifdef __ASSEMBLY__
-
-#define SWITCH_STACK_SIZE (6*4+4) /* Includes return address */
-
-/*
- * This defines the normal kernel pt-regs layout.
- *
- * regs are a2-a6 and d6-d7 preserved by C code
- * the kernel doesn't mess with usp unless it needs to
- */
-
-#ifdef CONFIG_COLDFIRE
-#ifdef CONFIG_COLDFIRE_SW_A7
-/*
- * This is made a little more tricky on older ColdFires. There is no
- * separate supervisor and user stack pointers. Need to artificially
- * construct a usp in software... When doing this we need to disable
- * interrupts, otherwise bad things will happen.
- */
-.globl sw_usp
-.globl sw_ksp
-
-.macro SAVE_ALL
- move #0x2700,%sr /* disable intrs */
- btst #5,%sp@(2) /* from user? */
- bnes 6f /* no, skip */
- movel %sp,sw_usp /* save user sp */
- addql #8,sw_usp /* remove exception */
- movel sw_ksp,%sp /* kernel sp */
- subql #8,%sp /* room for exception */
- clrl %sp@- /* stkadj */
- movel %d0,%sp@- /* orig d0 */
- movel %d0,%sp@- /* d0 */
- lea %sp@(-32),%sp /* space for 8 regs */
- moveml %d1-%d5/%a0-%a2,%sp@
- movel sw_usp,%a0 /* get usp */
- movel %a0@-,%sp@(PT_OFF_PC) /* copy exception program counter */
- movel %a0@-,%sp@(PT_OFF_FORMATVEC)/*copy exception format/vector/sr */
- bra 7f
- 6:
- clrl %sp@- /* stkadj */
- movel %d0,%sp@- /* orig d0 */
- movel %d0,%sp@- /* d0 */
- lea %sp@(-32),%sp /* space for 8 regs */
- moveml %d1-%d5/%a0-%a2,%sp@
- 7:
-.endm
-
-.macro RESTORE_USER
- move #0x2700,%sr /* disable intrs */
- movel sw_usp,%a0 /* get usp */
- movel %sp@(PT_OFF_PC),%a0@- /* copy exception program counter */
- movel %sp@(PT_OFF_FORMATVEC),%a0@-/*copy exception format/vector/sr */
- moveml %sp@,%d1-%d5/%a0-%a2
- lea %sp@(32),%sp /* space for 8 regs */
- movel %sp@+,%d0
- addql #4,%sp /* orig d0 */
- addl %sp@+,%sp /* stkadj */
- addql #8,%sp /* remove exception */
- movel %sp,sw_ksp /* save ksp */
- subql #8,sw_usp /* set exception */
- movel sw_usp,%sp /* restore usp */
- rte
-.endm
-
-.macro RDUSP
- movel sw_usp,%a3
-.endm
-
-.macro WRUSP
- movel %a3,sw_usp
-.endm
-
-#else /* !CONFIG_COLDFIRE_SW_A7 */
-/*
- * Modern ColdFire parts have separate supervisor and user stack
- * pointers. Simple load and restore macros for this case.
- */
-.macro SAVE_ALL
- move #0x2700,%sr /* disable intrs */
- clrl %sp@- /* stkadj */
- movel %d0,%sp@- /* orig d0 */
- movel %d0,%sp@- /* d0 */
- lea %sp@(-32),%sp /* space for 8 regs */
- moveml %d1-%d5/%a0-%a2,%sp@
-.endm
-
-.macro RESTORE_USER
- moveml %sp@,%d1-%d5/%a0-%a2
- lea %sp@(32),%sp /* space for 8 regs */
- movel %sp@+,%d0
- addql #4,%sp /* orig d0 */
- addl %sp@+,%sp /* stkadj */
- rte
-.endm
-
-.macro RDUSP
- /*move %usp,%a3*/
- .word 0x4e6b
-.endm
-
-.macro WRUSP
- /*move %a3,%usp*/
- .word 0x4e63
-.endm
-
-#endif /* !CONFIG_COLDFIRE_SW_A7 */
-
-.macro SAVE_SWITCH_STACK
- lea %sp@(-24),%sp /* 6 regs */
- moveml %a3-%a6/%d6-%d7,%sp@
-.endm
-
-.macro RESTORE_SWITCH_STACK
- moveml %sp@,%a3-%a6/%d6-%d7
- lea %sp@(24),%sp /* 6 regs */
-.endm
-
-#else /* !CONFIG_COLDFIRE */
-
-/*
- * Standard 68k interrupt entry and exit macros.
- */
-.macro SAVE_ALL
- clrl %sp@- /* stkadj */
- movel %d0,%sp@- /* orig d0 */
- movel %d0,%sp@- /* d0 */
- moveml %d1-%d5/%a0-%a2,%sp@-
-.endm
-
-.macro RESTORE_ALL
- moveml %sp@+,%a0-%a2/%d1-%d5
- movel %sp@+,%d0
- addql #4,%sp /* orig d0 */
- addl %sp@+,%sp /* stkadj */
- rte
-.endm
-
-.macro SAVE_SWITCH_STACK
- moveml %a3-%a6/%d6-%d7,%sp@-
-.endm
-
-.macro RESTORE_SWITCH_STACK
- moveml %sp@+,%a3-%a6/%d6-%d7
-.endm
-
-#endif /* !COLDFIRE_SW_A7 */
-#endif /* __ASSEMBLY__ */
-#endif /* __M68KNOMMU_ENTRY_H */
diff --git a/arch/m68k/include/asm/m520xsim.h b/arch/m68k/include/asm/m520xsim.h
index b6bf2c518bac..eda62de7e607 100644
--- a/arch/m68k/include/asm/m520xsim.h
+++ b/arch/m68k/include/asm/m520xsim.h
@@ -90,15 +90,13 @@
#define MCFGPIO_PDDR_FECH 0xFC0A4013
#define MCFGPIO_PDDR_FECL 0xFC0A4014
-#define MCFGPIO_PPDSDR_BUSCTL 0xFC0A401A
-#define MCFGPIO_PPDSDR_BE 0xFC0A401B
-#define MCFGPIO_PPDSDR_CS 0xFC0A401C
-#define MCFGPIO_PPDSDR_FECI2C 0xFC0A401D
-#define MCFGPIO_PPDSDR_QSPI 0xFC0A401E
-#define MCFGPIO_PPDSDR_TIMER 0xFC0A401F
-#define MCFGPIO_PPDSDR_UART 0xFC0A4021
-#define MCFGPIO_PPDSDR_FECH 0xFC0A4021
-#define MCFGPIO_PPDSDR_FECL 0xFC0A4022
+#define MCFGPIO_PPDSDR_CS 0xFC0A401A
+#define MCFGPIO_PPDSDR_FECI2C 0xFC0A401B
+#define MCFGPIO_PPDSDR_QSPI 0xFC0A401C
+#define MCFGPIO_PPDSDR_TIMER 0xFC0A401D
+#define MCFGPIO_PPDSDR_UART 0xFC0A401E
+#define MCFGPIO_PPDSDR_FECH 0xFC0A401F
+#define MCFGPIO_PPDSDR_FECL 0xFC0A4020
#define MCFGPIO_PCLRR_BUSCTL 0xFC0A4024
#define MCFGPIO_PCLRR_BE 0xFC0A4025
@@ -113,11 +111,11 @@
/*
* Generic GPIO support
*/
-#define MCFGPIO_PODR MCFGPIO_PODR_BUSCTL
-#define MCFGPIO_PDDR MCFGPIO_PDDR_BUSCTL
-#define MCFGPIO_PPDR MCFGPIO_PPDSDR_BUSCTL
-#define MCFGPIO_SETR MCFGPIO_PPDSDR_BUSCTL
-#define MCFGPIO_CLRR MCFGPIO_PCLRR_BUSCTL
+#define MCFGPIO_PODR MCFGPIO_PODR_CS
+#define MCFGPIO_PDDR MCFGPIO_PDDR_CS
+#define MCFGPIO_PPDR MCFGPIO_PPDSDR_CS
+#define MCFGPIO_SETR MCFGPIO_PPDSDR_CS
+#define MCFGPIO_CLRR MCFGPIO_PCLRR_CS
#define MCFGPIO_PIN_MAX 80
#define MCFGPIO_IRQ_MAX 8
diff --git a/arch/m68k/include/asm/mcfqspi.h b/arch/m68k/include/asm/mcfqspi.h
index 39d90d51111d..7fe631972f1f 100644
--- a/arch/m68k/include/asm/mcfqspi.h
+++ b/arch/m68k/include/asm/mcfqspi.h
@@ -24,9 +24,11 @@
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
#define MCFQSPI_IOBASE (MCF_IPSBAR + 0x340)
#elif defined(CONFIG_M5249)
-#define MCFQSPI_IOBASE (MCF_MBAR + 0x300)
-#elif defined(CONFIG_M520x) || defined(CONFIG_M532x)
-#define MCFQSPI_IOBASE 0xFC058000
+#define MCFQSPI_IOBASE (MCF_MBAR + 0x300)
+#elif defined(CONFIG_M520x)
+#define MCFQSPI_IOBASE 0xFC05C000
+#elif defined(CONFIG_M532x)
+#define MCFQSPI_IOBASE 0xFC058000
#endif
#define MCFQSPI_IOSIZE 0x40
diff --git a/arch/m68k/include/asm/page_no.h b/arch/m68k/include/asm/page_no.h
index 90595721185f..a8d1c60eb9ce 100644
--- a/arch/m68k/include/asm/page_no.h
+++ b/arch/m68k/include/asm/page_no.h
@@ -5,6 +5,9 @@
extern unsigned long memory_start;
extern unsigned long memory_end;
+extern unsigned long _rambase;
+extern unsigned long _ramstart;
+extern unsigned long _ramend;
#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
#define free_user_page(page, addr) free_page(addr)
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index d8ef53ac03f9..568facf30276 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -135,6 +135,12 @@ do { \
wrusp(_usp); \
} while(0)
+static inline int handle_kernel_fault(struct pt_regs *regs)
+{
+ /* Any fault in kernel is fatal on non-mmu */
+ return 0;
+}
+
#endif
/* Forward declaration, a strange C thing */
diff --git a/arch/m68k/include/asm/sections.h b/arch/m68k/include/asm/sections.h
index d64967ecfec6..5277e52715ec 100644
--- a/arch/m68k/include/asm/sections.h
+++ b/arch/m68k/include/asm/sections.h
@@ -3,4 +3,6 @@
#include <asm-generic/sections.h>
+extern char _sbss[], _ebss[];
+
#endif /* _ASM_M68K_SECTIONS_H */
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index c482ebc9dd54..e7f0f2e5ad44 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -1,5 +1,21 @@
-ifdef CONFIG_MMU
-include arch/m68k/kernel/Makefile_mm
-else
-include arch/m68k/kernel/Makefile_no
+#
+# Makefile for the linux kernel.
+#
+
+extra-$(CONFIG_MMU) := head.o
+extra-$(CONFIG_SUN3) := sun3-head.o
+extra-y += vmlinux.lds
+
+obj-y := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \
+ sys_m68k.o syscalltable.o time.o traps.o
+
+obj-$(CONFIG_MMU) += ints.o devres.o vectors.o
+devres-$(CONFIG_MMU) = ../../../kernel/irq/devres.o
+
+ifndef CONFIG_MMU_SUN3
+obj-y += dma.o
endif
+ifndef CONFIG_MMU
+obj-y += init_task.o irq.o
+endif
+
diff --git a/arch/m68k/kernel/Makefile_mm b/arch/m68k/kernel/Makefile_mm
deleted file mode 100644
index aced67804579..000000000000
--- a/arch/m68k/kernel/Makefile_mm
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-ifndef CONFIG_SUN3
- extra-y := head.o
-else
- extra-y := sun3-head.o
-endif
-extra-y += vmlinux.lds
-
-obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
- sys_m68k.o time.o setup.o m68k_ksyms.o devres.o syscalltable.o
-
-devres-y = ../../../kernel/irq/devres.o
-
-obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo
diff --git a/arch/m68k/kernel/Makefile_no b/arch/m68k/kernel/Makefile_no
deleted file mode 100644
index 37c3fc074c0a..000000000000
--- a/arch/m68k/kernel/Makefile_no
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Makefile for arch/m68knommu/kernel.
-#
-
-extra-y := vmlinux.lds
-
-obj-y += dma.o entry.o init_task.o irq.o m68k_ksyms.o process.o ptrace.o \
- setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
-
-obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/m68k/kernel/entry_no.S b/arch/m68k/kernel/entry_no.S
index 5f0f6b598b5a..1b4289061a64 100644
--- a/arch/m68k/kernel/entry_no.S
+++ b/arch/m68k/kernel/entry_no.S
@@ -43,7 +43,7 @@
.globl sys_vfork
ENTRY(buserr)
- SAVE_ALL
+ SAVE_ALL_INT
moveq #-1,%d0
movel %d0,%sp@(PT_OFF_ORIG_D0)
movel %sp,%sp@- /* stack frame pointer argument */
@@ -52,7 +52,7 @@ ENTRY(buserr)
jra ret_from_exception
ENTRY(trap)
- SAVE_ALL
+ SAVE_ALL_INT
moveq #-1,%d0
movel %d0,%sp@(PT_OFF_ORIG_D0)
movel %sp,%sp@- /* stack frame pointer argument */
@@ -64,7 +64,7 @@ ENTRY(trap)
.globl dbginterrupt
ENTRY(dbginterrupt)
- SAVE_ALL
+ SAVE_ALL_INT
moveq #-1,%d0
movel %d0,%sp@(PT_OFF_ORIG_D0)
movel %sp,%sp@- /* stack frame pointer argument */
diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c
index 16b2de7f5101..2ed8c0fb1517 100644
--- a/arch/m68k/kernel/setup_no.c
+++ b/arch/m68k/kernel/setup_no.c
@@ -36,6 +36,7 @@
#include <asm/irq.h>
#include <asm/machdep.h>
#include <asm/pgtable.h>
+#include <asm/sections.h>
unsigned long memory_start;
unsigned long memory_end;
@@ -80,9 +81,6 @@ void (*mach_power_off)(void);
#define CPU_INSTR_PER_JIFFY 16
#endif
-extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
-extern int _ramstart, _ramend;
-
#if defined(CONFIG_UBOOT)
/*
* parse_uboot_commandline
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index c98add3f5f0f..89362f2bb56a 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -1,5 +1,1107 @@
-#ifdef CONFIG_MMU
-#include "traps_mm.c"
+/*
+ * linux/arch/m68k/kernel/traps.c
+ *
+ * Copyright (C) 1993, 1994 by Hamish Macdonald
+ *
+ * 68040 fixes by Michael Rausch
+ * 68040 fixes by Martin Apel
+ * 68040 fixes and writeback by Richard Zidlicky
+ * 68060 fixes by Roman Hodek
+ * 68060 fixes by Jesper Skov
+ *
+ * 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.
+ */
+
+/*
+ * Sets up all exception vectors
+ */
+
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/user.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/kallsyms.h>
+
+#include <asm/setup.h>
+#include <asm/fpu.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/traps.h>
+#include <asm/pgalloc.h>
+#include <asm/machdep.h>
+#include <asm/siginfo.h>
+
+
+static const char *vec_names[] = {
+ [VEC_RESETSP] = "RESET SP",
+ [VEC_RESETPC] = "RESET PC",
+ [VEC_BUSERR] = "BUS ERROR",
+ [VEC_ADDRERR] = "ADDRESS ERROR",
+ [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION",
+ [VEC_ZERODIV] = "ZERO DIVIDE",
+ [VEC_CHK] = "CHK",
+ [VEC_TRAP] = "TRAPcc",
+ [VEC_PRIV] = "PRIVILEGE VIOLATION",
+ [VEC_TRACE] = "TRACE",
+ [VEC_LINE10] = "LINE 1010",
+ [VEC_LINE11] = "LINE 1111",
+ [VEC_RESV12] = "UNASSIGNED RESERVED 12",
+ [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION",
+ [VEC_FORMAT] = "FORMAT ERROR",
+ [VEC_UNINT] = "UNINITIALIZED INTERRUPT",
+ [VEC_RESV16] = "UNASSIGNED RESERVED 16",
+ [VEC_RESV17] = "UNASSIGNED RESERVED 17",
+ [VEC_RESV18] = "UNASSIGNED RESERVED 18",
+ [VEC_RESV19] = "UNASSIGNED RESERVED 19",
+ [VEC_RESV20] = "UNASSIGNED RESERVED 20",
+ [VEC_RESV21] = "UNASSIGNED RESERVED 21",
+ [VEC_RESV22] = "UNASSIGNED RESERVED 22",
+ [VEC_RESV23] = "UNASSIGNED RESERVED 23",
+ [VEC_SPUR] = "SPURIOUS INTERRUPT",
+ [VEC_INT1] = "LEVEL 1 INT",
+ [VEC_INT2] = "LEVEL 2 INT",
+ [VEC_INT3] = "LEVEL 3 INT",
+ [VEC_INT4] = "LEVEL 4 INT",
+ [VEC_INT5] = "LEVEL 5 INT",
+ [VEC_INT6] = "LEVEL 6 INT",
+ [VEC_INT7] = "LEVEL 7 INT",
+ [VEC_SYS] = "SYSCALL",
+ [VEC_TRAP1] = "TRAP #1",
+ [VEC_TRAP2] = "TRAP #2",
+ [VEC_TRAP3] = "TRAP #3",
+ [VEC_TRAP4] = "TRAP #4",
+ [VEC_TRAP5] = "TRAP #5",
+ [VEC_TRAP6] = "TRAP #6",
+ [VEC_TRAP7] = "TRAP #7",
+ [VEC_TRAP8] = "TRAP #8",
+ [VEC_TRAP9] = "TRAP #9",
+ [VEC_TRAP10] = "TRAP #10",
+ [VEC_TRAP11] = "TRAP #11",
+ [VEC_TRAP12] = "TRAP #12",
+ [VEC_TRAP13] = "TRAP #13",
+ [VEC_TRAP14] = "TRAP #14",
+ [VEC_TRAP15] = "TRAP #15",
+ [VEC_FPBRUC] = "FPCP BSUN",
+ [VEC_FPIR] = "FPCP INEXACT",
+ [VEC_FPDIVZ] = "FPCP DIV BY 0",
+ [VEC_FPUNDER] = "FPCP UNDERFLOW",
+ [VEC_FPOE] = "FPCP OPERAND ERROR",
+ [VEC_FPOVER] = "FPCP OVERFLOW",
+ [VEC_FPNAN] = "FPCP SNAN",
+ [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION",
+ [VEC_MMUCFG] = "MMU CONFIGURATION ERROR",
+ [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR",
+ [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR",
+ [VEC_RESV59] = "UNASSIGNED RESERVED 59",
+ [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60",
+ [VEC_UNIMPII] = "UNASSIGNED RESERVED 61",
+ [VEC_RESV62] = "UNASSIGNED RESERVED 62",
+ [VEC_RESV63] = "UNASSIGNED RESERVED 63",
+};
+
+static const char *space_names[] = {
+ [0] = "Space 0",
+ [USER_DATA] = "User Data",
+ [USER_PROGRAM] = "User Program",
+#ifndef CONFIG_SUN3
+ [3] = "Space 3",
#else
-#include "traps_no.c"
+ [FC_CONTROL] = "Control",
+#endif
+ [4] = "Space 4",
+ [SUPER_DATA] = "Super Data",
+ [SUPER_PROGRAM] = "Super Program",
+ [CPU_SPACE] = "CPU"
+};
+
+void die_if_kernel(char *,struct pt_regs *,int);
+asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code);
+int send_fault_sig(struct pt_regs *regs);
+
+asmlinkage void trap_c(struct frame *fp);
+
+#if defined (CONFIG_M68060)
+static inline void access_error060 (struct frame *fp)
+{
+ unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
+
+#ifdef DEBUG
+ printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
+#endif
+
+ if (fslw & MMU060_BPE) {
+ /* branch prediction error -> clear branch cache */
+ __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
+ "orl #0x00400000,%/d0\n\t"
+ "movec %/d0,%/cacr"
+ : : : "d0" );
+ /* return if there's no other error */
+ if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
+ return;
+ }
+
+ if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
+ unsigned long errorcode;
+ unsigned long addr = fp->un.fmt4.effaddr;
+
+ if (fslw & MMU060_MA)
+ addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
+
+ errorcode = 1;
+ if (fslw & MMU060_DESC_ERR) {
+ __flush_tlb040_one(addr);
+ errorcode = 0;
+ }
+ if (fslw & MMU060_W)
+ errorcode |= 2;
+#ifdef DEBUG
+ printk("errorcode = %d\n", errorcode );
+#endif
+ do_page_fault(&fp->ptregs, addr, errorcode);
+ } else if (fslw & (MMU060_SEE)){
+ /* Software Emulation Error.
+ * fault during mem_read/mem_write in ifpsp060/os.S
+ */
+ send_fault_sig(&fp->ptregs);
+ } else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
+ send_fault_sig(&fp->ptregs) > 0) {
+ printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
+ printk( "68060 access error, fslw=%lx\n", fslw );
+ trap_c( fp );
+ }
+}
+#endif /* CONFIG_M68060 */
+
+#if defined (CONFIG_M68040)
+static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
+{
+ unsigned long mmusr;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(MAKE_MM_SEG(wbs));
+
+ if (iswrite)
+ asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
+ else
+ asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
+
+ asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
+
+ set_fs(old_fs);
+
+ return mmusr;
+}
+
+static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
+ unsigned long wbd)
+{
+ int res = 0;
+ mm_segment_t old_fs = get_fs();
+
+ /* set_fs can not be moved, otherwise put_user() may oops */
+ set_fs(MAKE_MM_SEG(wbs));
+
+ switch (wbs & WBSIZ_040) {
+ case BA_SIZE_BYTE:
+ res = put_user(wbd & 0xff, (char __user *)wba);
+ break;
+ case BA_SIZE_WORD:
+ res = put_user(wbd & 0xffff, (short __user *)wba);
+ break;
+ case BA_SIZE_LONG:
+ res = put_user(wbd, (int __user *)wba);
+ break;
+ }
+
+ /* set_fs can not be moved, otherwise put_user() may oops */
+ set_fs(old_fs);
+
+
+#ifdef DEBUG
+ printk("do_040writeback1, res=%d\n",res);
+#endif
+
+ return res;
+}
+
+/* after an exception in a writeback the stack frame corresponding
+ * to that exception is discarded, set a few bits in the old frame
+ * to simulate what it should look like
+ */
+static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
+{
+ fp->un.fmt7.faddr = wba;
+ fp->un.fmt7.ssw = wbs & 0xff;
+ if (wba != current->thread.faddr)
+ fp->un.fmt7.ssw |= MA_040;
+}
+
+static inline void do_040writebacks(struct frame *fp)
+{
+ int res = 0;
+#if 0
+ if (fp->un.fmt7.wb1s & WBV_040)
+ printk("access_error040: cannot handle 1st writeback. oops.\n");
+#endif
+
+ if ((fp->un.fmt7.wb2s & WBV_040) &&
+ !(fp->un.fmt7.wb2s & WBTT_040)) {
+ res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
+ fp->un.fmt7.wb2d);
+ if (res)
+ fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
+ else
+ fp->un.fmt7.wb2s = 0;
+ }
+
+ /* do the 2nd wb only if the first one was successful (except for a kernel wb) */
+ if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
+ res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
+ fp->un.fmt7.wb3d);
+ if (res)
+ {
+ fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
+
+ fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
+ fp->un.fmt7.wb3s &= (~WBV_040);
+ fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
+ fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
+ }
+ else
+ fp->un.fmt7.wb3s = 0;
+ }
+
+ if (res)
+ send_fault_sig(&fp->ptregs);
+}
+
+/*
+ * called from sigreturn(), must ensure userspace code didn't
+ * manipulate exception frame to circumvent protection, then complete
+ * pending writebacks
+ * we just clear TM2 to turn it into a userspace access
+ */
+asmlinkage void berr_040cleanup(struct frame *fp)
+{
+ fp->un.fmt7.wb2s &= ~4;
+ fp->un.fmt7.wb3s &= ~4;
+
+ do_040writebacks(fp);
+}
+
+static inline void access_error040(struct frame *fp)
+{
+ unsigned short ssw = fp->un.fmt7.ssw;
+ unsigned long mmusr;
+
+#ifdef DEBUG
+ printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
+ printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
+ fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
+ printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
+ fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
+ fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
+#endif
+
+ if (ssw & ATC_040) {
+ unsigned long addr = fp->un.fmt7.faddr;
+ unsigned long errorcode;
+
+ /*
+ * The MMU status has to be determined AFTER the address
+ * has been corrected if there was a misaligned access (MA).
+ */
+ if (ssw & MA_040)
+ addr = (addr + 7) & -8;
+
+ /* MMU error, get the MMUSR info for this access */
+ mmusr = probe040(!(ssw & RW_040), addr, ssw);
+#ifdef DEBUG
+ printk("mmusr = %lx\n", mmusr);
+#endif
+ errorcode = 1;
+ if (!(mmusr & MMU_R_040)) {
+ /* clear the invalid atc entry */
+ __flush_tlb040_one(addr);
+ errorcode = 0;
+ }
+
+ /* despite what documentation seems to say, RMW
+ * accesses have always both the LK and RW bits set */
+ if (!(ssw & RW_040) || (ssw & LK_040))
+ errorcode |= 2;
+
+ if (do_page_fault(&fp->ptregs, addr, errorcode)) {
+#ifdef DEBUG
+ printk("do_page_fault() !=0\n");
+#endif
+ if (user_mode(&fp->ptregs)){
+ /* delay writebacks after signal delivery */
+#ifdef DEBUG
+ printk(".. was usermode - return\n");
+#endif
+ return;
+ }
+ /* disable writeback into user space from kernel
+ * (if do_page_fault didn't fix the mapping,
+ * the writeback won't do good)
+ */
+disable_wb:
+#ifdef DEBUG
+ printk(".. disabling wb2\n");
+#endif
+ if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
+ fp->un.fmt7.wb2s &= ~WBV_040;
+ if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
+ fp->un.fmt7.wb3s &= ~WBV_040;
+ }
+ } else {
+ /* In case of a bus error we either kill the process or expect
+ * the kernel to catch the fault, which then is also responsible
+ * for cleaning up the mess.
+ */
+ current->thread.signo = SIGBUS;
+ current->thread.faddr = fp->un.fmt7.faddr;
+ if (send_fault_sig(&fp->ptregs) >= 0)
+ printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
+ fp->un.fmt7.faddr);
+ goto disable_wb;
+ }
+
+ do_040writebacks(fp);
+}
+#endif /* CONFIG_M68040 */
+
+#if defined(CONFIG_SUN3)
+#include <asm/sun3mmu.h>
+
+extern int mmu_emu_handle_fault (unsigned long, int, int);
+
+/* sun3 version of bus_error030 */
+
+static inline void bus_error030 (struct frame *fp)
+{
+ unsigned char buserr_type = sun3_get_buserr ();
+ unsigned long addr, errorcode;
+ unsigned short ssw = fp->un.fmtb.ssw;
+ extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
+
+#ifdef DEBUG
+ if (ssw & (FC | FB))
+ printk ("Instruction fault at %#010lx\n",
+ ssw & FC ?
+ fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
+ :
+ fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
+ if (ssw & DF)
+ printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+ ssw & RW ? "read" : "write",
+ fp->un.fmtb.daddr,
+ space_names[ssw & DFC], fp->ptregs.pc);
+#endif
+
+ /*
+ * Check if this page should be demand-mapped. This needs to go before
+ * the testing for a bad kernel-space access (demand-mapping applies
+ * to kernel accesses too).
+ */
+
+ if ((ssw & DF)
+ && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
+ if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
+ return;
+ }
+
+ /* Check for kernel-space pagefault (BAD). */
+ if (fp->ptregs.sr & PS_S) {
+ /* kernel fault must be a data fault to user space */
+ if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
+ // try checking the kernel mappings before surrender
+ if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
+ return;
+ /* instruction fault or kernel data fault! */
+ if (ssw & (FC | FB))
+ printk ("Instruction fault at %#010lx\n",
+ fp->ptregs.pc);
+ if (ssw & DF) {
+ /* was this fault incurred testing bus mappings? */
+ if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
+ (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
+ send_fault_sig(&fp->ptregs);
+ return;
+ }
+
+ printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+ ssw & RW ? "read" : "write",
+ fp->un.fmtb.daddr,
+ space_names[ssw & DFC], fp->ptregs.pc);
+ }
+ printk ("BAD KERNEL BUSERR\n");
+
+ die_if_kernel("Oops", &fp->ptregs,0);
+ force_sig(SIGKILL, current);
+ return;
+ }
+ } else {
+ /* user fault */
+ if (!(ssw & (FC | FB)) && !(ssw & DF))
+ /* not an instruction fault or data fault! BAD */
+ panic ("USER BUSERR w/o instruction or data fault");
+ }
+
+
+ /* First handle the data fault, if any. */
+ if (ssw & DF) {
+ addr = fp->un.fmtb.daddr;
+
+// errorcode bit 0: 0 -> no page 1 -> protection fault
+// errorcode bit 1: 0 -> read fault 1 -> write fault
+
+// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault
+// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault
+
+ if (buserr_type & SUN3_BUSERR_PROTERR)
+ errorcode = 0x01;
+ else if (buserr_type & SUN3_BUSERR_INVALID)
+ errorcode = 0x00;
+ else {
+#ifdef DEBUG
+ printk ("*** unexpected busfault type=%#04x\n", buserr_type);
+ printk ("invalid %s access at %#lx from pc %#lx\n",
+ !(ssw & RW) ? "write" : "read", addr,
+ fp->ptregs.pc);
+#endif
+ die_if_kernel ("Oops", &fp->ptregs, buserr_type);
+ force_sig (SIGBUS, current);
+ return;
+ }
+
+//todo: wtf is RM bit? --m
+ if (!(ssw & RW) || ssw & RM)
+ errorcode |= 0x02;
+
+ /* Handle page fault. */
+ do_page_fault (&fp->ptregs, addr, errorcode);
+
+ /* Retry the data fault now. */
+ return;
+ }
+
+ /* Now handle the instruction fault. */
+
+ /* Get the fault address. */
+ if (fp->ptregs.format == 0xA)
+ addr = fp->ptregs.pc + 4;
+ else
+ addr = fp->un.fmtb.baddr;
+ if (ssw & FC)
+ addr -= 2;
+
+ if (buserr_type & SUN3_BUSERR_INVALID) {
+ if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
+ do_page_fault (&fp->ptregs, addr, 0);
+ } else {
+#ifdef DEBUG
+ printk ("protection fault on insn access (segv).\n");
+#endif
+ force_sig (SIGSEGV, current);
+ }
+}
+#else
+#if defined(CPU_M68020_OR_M68030)
+static inline void bus_error030 (struct frame *fp)
+{
+ volatile unsigned short temp;
+ unsigned short mmusr;
+ unsigned long addr, errorcode;
+ unsigned short ssw = fp->un.fmtb.ssw;
+#ifdef DEBUG
+ unsigned long desc;
+
+ printk ("pid = %x ", current->pid);
+ printk ("SSW=%#06x ", ssw);
+
+ if (ssw & (FC | FB))
+ printk ("Instruction fault at %#010lx\n",
+ ssw & FC ?
+ fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
+ :
+ fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
+ if (ssw & DF)
+ printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+ ssw & RW ? "read" : "write",
+ fp->un.fmtb.daddr,
+ space_names[ssw & DFC], fp->ptregs.pc);
+#endif
+
+ /* ++andreas: If a data fault and an instruction fault happen
+ at the same time map in both pages. */
+
+ /* First handle the data fault, if any. */
+ if (ssw & DF) {
+ addr = fp->un.fmtb.daddr;
+
+#ifdef DEBUG
+ asm volatile ("ptestr %3,%2@,#7,%0\n\t"
+ "pmove %%psr,%1@"
+ : "=a&" (desc)
+ : "a" (&temp), "a" (addr), "d" (ssw));
+#else
+ asm volatile ("ptestr %2,%1@,#7\n\t"
+ "pmove %%psr,%0@"
+ : : "a" (&temp), "a" (addr), "d" (ssw));
+#endif
+ mmusr = temp;
+
+#ifdef DEBUG
+ printk("mmusr is %#x for addr %#lx in task %p\n",
+ mmusr, addr, current);
+ printk("descriptor address is %#lx, contents %#lx\n",
+ __va(desc), *(unsigned long *)__va(desc));
+#endif
+
+ errorcode = (mmusr & MMU_I) ? 0 : 1;
+ if (!(ssw & RW) || (ssw & RM))
+ errorcode |= 2;
+
+ if (mmusr & (MMU_I | MMU_WP)) {
+ if (ssw & 4) {
+ printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+ ssw & RW ? "read" : "write",
+ fp->un.fmtb.daddr,
+ space_names[ssw & DFC], fp->ptregs.pc);
+ goto buserr;
+ }
+ /* Don't try to do anything further if an exception was
+ handled. */
+ if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
+ return;
+ } else if (!(mmusr & MMU_I)) {
+ /* probably a 020 cas fault */
+ if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
+ printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
+ } else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
+ printk("invalid %s access at %#lx from pc %#lx\n",
+ !(ssw & RW) ? "write" : "read", addr,
+ fp->ptregs.pc);
+ die_if_kernel("Oops",&fp->ptregs,mmusr);
+ force_sig(SIGSEGV, current);
+ return;
+ } else {
+#if 0
+ static volatile long tlong;
+#endif
+
+ printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
+ !(ssw & RW) ? "write" : "read", addr,
+ fp->ptregs.pc, ssw);
+ asm volatile ("ptestr #1,%1@,#0\n\t"
+ "pmove %%psr,%0@"
+ : /* no outputs */
+ : "a" (&temp), "a" (addr));
+ mmusr = temp;
+
+ printk ("level 0 mmusr is %#x\n", mmusr);
+#if 0
+ asm volatile ("pmove %%tt0,%0@"
+ : /* no outputs */
+ : "a" (&tlong));
+ printk("tt0 is %#lx, ", tlong);
+ asm volatile ("pmove %%tt1,%0@"
+ : /* no outputs */
+ : "a" (&tlong));
+ printk("tt1 is %#lx\n", tlong);
+#endif
+#ifdef DEBUG
+ printk("Unknown SIGSEGV - 1\n");
+#endif
+ die_if_kernel("Oops",&fp->ptregs,mmusr);
+ force_sig(SIGSEGV, current);
+ return;
+ }
+
+ /* setup an ATC entry for the access about to be retried */
+ if (!(ssw & RW) || (ssw & RM))
+ asm volatile ("ploadw %1,%0@" : /* no outputs */
+ : "a" (addr), "d" (ssw));
+ else
+ asm volatile ("ploadr %1,%0@" : /* no outputs */
+ : "a" (addr), "d" (ssw));
+ }
+
+ /* Now handle the instruction fault. */
+
+ if (!(ssw & (FC|FB)))
+ return;
+
+ if (fp->ptregs.sr & PS_S) {
+ printk("Instruction fault at %#010lx\n",
+ fp->ptregs.pc);
+ buserr:
+ printk ("BAD KERNEL BUSERR\n");
+ die_if_kernel("Oops",&fp->ptregs,0);
+ force_sig(SIGKILL, current);
+ return;
+ }
+
+ /* get the fault address */
+ if (fp->ptregs.format == 10)
+ addr = fp->ptregs.pc + 4;
+ else
+ addr = fp->un.fmtb.baddr;
+ if (ssw & FC)
+ addr -= 2;
+
+ if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
+ /* Insn fault on same page as data fault. But we
+ should still create the ATC entry. */
+ goto create_atc_entry;
+
+#ifdef DEBUG
+ asm volatile ("ptestr #1,%2@,#7,%0\n\t"
+ "pmove %%psr,%1@"
+ : "=a&" (desc)
+ : "a" (&temp), "a" (addr));
+#else
+ asm volatile ("ptestr #1,%1@,#7\n\t"
+ "pmove %%psr,%0@"
+ : : "a" (&temp), "a" (addr));
+#endif
+ mmusr = temp;
+
+#ifdef DEBUG
+ printk ("mmusr is %#x for addr %#lx in task %p\n",
+ mmusr, addr, current);
+ printk ("descriptor address is %#lx, contents %#lx\n",
+ __va(desc), *(unsigned long *)__va(desc));
+#endif
+
+ if (mmusr & MMU_I)
+ do_page_fault (&fp->ptregs, addr, 0);
+ else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
+ printk ("invalid insn access at %#lx from pc %#lx\n",
+ addr, fp->ptregs.pc);
+#ifdef DEBUG
+ printk("Unknown SIGSEGV - 2\n");
+#endif
+ die_if_kernel("Oops",&fp->ptregs,mmusr);
+ force_sig(SIGSEGV, current);
+ return;
+ }
+
+create_atc_entry:
+ /* setup an ATC entry for the access about to be retried */
+ asm volatile ("ploadr #2,%0@" : /* no outputs */
+ : "a" (addr));
+}
+#endif /* CPU_M68020_OR_M68030 */
+#endif /* !CONFIG_SUN3 */
+
+asmlinkage void buserr_c(struct frame *fp)
+{
+ /* Only set esp0 if coming from user mode */
+ if (user_mode(&fp->ptregs))
+ current->thread.esp0 = (unsigned long) fp;
+
+#ifdef DEBUG
+ printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
+#endif
+
+ switch (fp->ptregs.format) {
+#if defined (CONFIG_M68060)
+ case 4: /* 68060 access error */
+ access_error060 (fp);
+ break;
+#endif
+#if defined (CONFIG_M68040)
+ case 0x7: /* 68040 access error */
+ access_error040 (fp);
+ break;
+#endif
+#if defined (CPU_M68020_OR_M68030)
+ case 0xa:
+ case 0xb:
+ bus_error030 (fp);
+ break;
+#endif
+ default:
+ die_if_kernel("bad frame format",&fp->ptregs,0);
+#ifdef DEBUG
+ printk("Unknown SIGSEGV - 4\n");
+#endif
+ force_sig(SIGSEGV, current);
+ }
+}
+
+
+static int kstack_depth_to_print = 48;
+
+void show_trace(unsigned long *stack)
+{
+ unsigned long *endstack;
+ unsigned long addr;
+ int i;
+
+ printk("Call Trace:");
+ addr = (unsigned long)stack + THREAD_SIZE - 1;
+ endstack = (unsigned long *)(addr & -THREAD_SIZE);
+ i = 0;
+ while (stack + 1 <= endstack) {
+ addr = *stack++;
+ /*
+ * If the address is either in the text segment of the
+ * kernel, or in the region which contains vmalloc'ed
+ * memory, it *may* be the address of a calling
+ * routine; if so, print it so that someone tracing
+ * down the cause of the crash will be able to figure
+ * out the call path that was taken.
+ */
+ if (__kernel_text_address(addr)) {
+#ifndef CONFIG_KALLSYMS
+ if (i % 5 == 0)
+ printk("\n ");
+#endif
+ printk(" [<%08lx>] %pS\n", addr, (void *)addr);
+ i++;
+ }
+ }
+ printk("\n");
+}
+
+void show_registers(struct pt_regs *regs)
+{
+ struct frame *fp = (struct frame *)regs;
+ mm_segment_t old_fs = get_fs();
+ u16 c, *cp;
+ unsigned long addr;
+ int i;
+
+ print_modules();
+ printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
+ printk("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2);
+ printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
+ regs->d0, regs->d1, regs->d2, regs->d3);
+ printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
+ regs->d4, regs->d5, regs->a0, regs->a1);
+
+ printk("Process %s (pid: %d, task=%p)\n",
+ current->comm, task_pid_nr(current), current);
+ addr = (unsigned long)&fp->un;
+ printk("Frame format=%X ", regs->format);
+ switch (regs->format) {
+ case 0x2:
+ printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
+ addr += sizeof(fp->un.fmt2);
+ break;
+ case 0x3:
+ printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
+ addr += sizeof(fp->un.fmt3);
+ break;
+ case 0x4:
+ printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
+ : "eff addr=%08lx pc=%08lx\n"),
+ fp->un.fmt4.effaddr, fp->un.fmt4.pc);
+ addr += sizeof(fp->un.fmt4);
+ break;
+ case 0x7:
+ printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
+ fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
+ printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
+ fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
+ printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
+ fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
+ printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
+ fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
+ printk("push data: %08lx %08lx %08lx %08lx\n",
+ fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
+ fp->un.fmt7.pd3);
+ addr += sizeof(fp->un.fmt7);
+ break;
+ case 0x9:
+ printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
+ addr += sizeof(fp->un.fmt9);
+ break;
+ case 0xa:
+ printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+ fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
+ fp->un.fmta.daddr, fp->un.fmta.dobuf);
+ addr += sizeof(fp->un.fmta);
+ break;
+ case 0xb:
+ printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+ fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
+ fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
+ printk("baddr=%08lx dibuf=%08lx ver=%x\n",
+ fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
+ addr += sizeof(fp->un.fmtb);
+ break;
+ default:
+ printk("\n");
+ }
+ show_stack(NULL, (unsigned long *)addr);
+
+ printk("Code:");
+ set_fs(KERNEL_DS);
+ cp = (u16 *)regs->pc;
+ for (i = -8; i < 16; i++) {
+ if (get_user(c, cp + i) && i >= 0) {
+ printk(" Bad PC value.");
+ break;
+ }
+ printk(i ? " %04x" : " <%04x>", c);
+ }
+ set_fs(old_fs);
+ printk ("\n");
+}
+
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+ unsigned long *p;
+ unsigned long *endstack;
+ int i;
+
+ if (!stack) {
+ if (task)
+ stack = (unsigned long *)task->thread.esp0;
+ else
+ stack = (unsigned long *)&stack;
+ }
+ endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
+
+ printk("Stack from %08lx:", (unsigned long)stack);
+ p = stack;
+ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (p + 1 > endstack)
+ break;
+ if (i % 8 == 0)
+ printk("\n ");
+ printk(" %08lx", *p++);
+ }
+ printk("\n");
+ show_trace(stack);
+}
+
+/*
+ * The architecture-independent backtrace generator
+ */
+void dump_stack(void)
+{
+ unsigned long stack;
+
+ show_trace(&stack);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+/*
+ * The vector number returned in the frame pointer may also contain
+ * the "fs" (Fault Status) bits on ColdFire. These are in the bottom
+ * 2 bits, and upper 2 bits. So we need to mask out the real vector
+ * number before using it in comparisons. You don't need to do this on
+ * real 68k parts, but it won't hurt either.
+ */
+
+void bad_super_trap (struct frame *fp)
+{
+ int vector = (fp->ptregs.vector >> 2) & 0xff;
+
+ console_verbose();
+ if (vector < ARRAY_SIZE(vec_names))
+ printk ("*** %s *** FORMAT=%X\n",
+ vec_names[vector],
+ fp->ptregs.format);
+ else
+ printk ("*** Exception %d *** FORMAT=%X\n",
+ vector, fp->ptregs.format);
+ if (vector == VEC_ADDRERR && CPU_IS_020_OR_030) {
+ unsigned short ssw = fp->un.fmtb.ssw;
+
+ printk ("SSW=%#06x ", ssw);
+
+ if (ssw & RC)
+ printk ("Pipe stage C instruction fault at %#010lx\n",
+ (fp->ptregs.format) == 0xA ?
+ fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
+ if (ssw & RB)
+ printk ("Pipe stage B instruction fault at %#010lx\n",
+ (fp->ptregs.format) == 0xA ?
+ fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
+ if (ssw & DF)
+ printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+ ssw & RW ? "read" : "write",
+ fp->un.fmtb.daddr, space_names[ssw & DFC],
+ fp->ptregs.pc);
+ }
+ printk ("Current process id is %d\n", task_pid_nr(current));
+ die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
+}
+
+asmlinkage void trap_c(struct frame *fp)
+{
+ int sig;
+ int vector = (fp->ptregs.vector >> 2) & 0xff;
+ siginfo_t info;
+
+ if (fp->ptregs.sr & PS_S) {
+ if (vector == VEC_TRACE) {
+ /* traced a trapping instruction on a 68020/30,
+ * real exception will be executed afterwards.
+ */
+ } else if (!handle_kernel_fault(&fp->ptregs))
+ bad_super_trap(fp);
+ return;
+ }
+
+ /* send the appropriate signal to the user program */
+ switch (vector) {
+ case VEC_ADDRERR:
+ info.si_code = BUS_ADRALN;
+ sig = SIGBUS;
+ break;
+ case VEC_ILLEGAL:
+ case VEC_LINE10:
+ case VEC_LINE11:
+ info.si_code = ILL_ILLOPC;
+ sig = SIGILL;
+ break;
+ case VEC_PRIV:
+ info.si_code = ILL_PRVOPC;
+ sig = SIGILL;
+ break;
+ case VEC_COPROC:
+ info.si_code = ILL_COPROC;
+ sig = SIGILL;
+ break;
+ case VEC_TRAP1:
+ case VEC_TRAP2:
+ case VEC_TRAP3:
+ case VEC_TRAP4:
+ case VEC_TRAP5:
+ case VEC_TRAP6:
+ case VEC_TRAP7:
+ case VEC_TRAP8:
+ case VEC_TRAP9:
+ case VEC_TRAP10:
+ case VEC_TRAP11:
+ case VEC_TRAP12:
+ case VEC_TRAP13:
+ case VEC_TRAP14:
+ info.si_code = ILL_ILLTRP;
+ sig = SIGILL;
+ break;
+ case VEC_FPBRUC:
+ case VEC_FPOE:
+ case VEC_FPNAN:
+ info.si_code = FPE_FLTINV;
+ sig = SIGFPE;
+ break;
+ case VEC_FPIR:
+ info.si_code = FPE_FLTRES;
+ sig = SIGFPE;
+ break;
+ case VEC_FPDIVZ:
+ info.si_code = FPE_FLTDIV;
+ sig = SIGFPE;
+ break;
+ case VEC_FPUNDER:
+ info.si_code = FPE_FLTUND;
+ sig = SIGFPE;
+ break;
+ case VEC_FPOVER:
+ info.si_code = FPE_FLTOVF;
+ sig = SIGFPE;
+ break;
+ case VEC_ZERODIV:
+ info.si_code = FPE_INTDIV;
+ sig = SIGFPE;
+ break;
+ case VEC_CHK:
+ case VEC_TRAP:
+ info.si_code = FPE_INTOVF;
+ sig = SIGFPE;
+ break;
+ case VEC_TRACE: /* ptrace single step */
+ info.si_code = TRAP_TRACE;
+ sig = SIGTRAP;
+ break;
+ case VEC_TRAP15: /* breakpoint */
+ info.si_code = TRAP_BRKPT;
+ sig = SIGTRAP;
+ break;
+ default:
+ info.si_code = ILL_ILLOPC;
+ sig = SIGILL;
+ break;
+ }
+ info.si_signo = sig;
+ info.si_errno = 0;
+ switch (fp->ptregs.format) {
+ default:
+ info.si_addr = (void *) fp->ptregs.pc;
+ break;
+ case 2:
+ info.si_addr = (void *) fp->un.fmt2.iaddr;
+ break;
+ case 7:
+ info.si_addr = (void *) fp->un.fmt7.effaddr;
+ break;
+ case 9:
+ info.si_addr = (void *) fp->un.fmt9.iaddr;
+ break;
+ case 10:
+ info.si_addr = (void *) fp->un.fmta.daddr;
+ break;
+ case 11:
+ info.si_addr = (void *) fp->un.fmtb.daddr;
+ break;
+ }
+ force_sig_info (sig, &info, current);
+}
+
+void die_if_kernel (char *str, struct pt_regs *fp, int nr)
+{
+ if (!(fp->sr & PS_S))
+ return;
+
+ console_verbose();
+ printk("%s: %08x\n",str,nr);
+ show_registers(fp);
+ add_taint(TAINT_DIE);
+ do_exit(SIGSEGV);
+}
+
+asmlinkage void set_esp0(unsigned long ssp)
+{
+ current->thread.esp0 = ssp;
+}
+
+/*
+ * This function is called if an error occur while accessing
+ * user-space from the fpsp040 code.
+ */
+asmlinkage void fpsp040_die(void)
+{
+ do_exit(SIGSEGV);
+}
+
+#ifdef CONFIG_M68KFPU_EMU
+asmlinkage void fpemu_signal(int signal, int code, void *addr)
+{
+ siginfo_t info;
+
+ info.si_signo = signal;
+ info.si_errno = 0;
+ info.si_code = code;
+ info.si_addr = addr;
+ force_sig_info(signal, &info, current);
+}
#endif
diff --git a/arch/m68k/kernel/traps_mm.c b/arch/m68k/kernel/traps_mm.c
deleted file mode 100644
index 4022bbc28878..000000000000
--- a/arch/m68k/kernel/traps_mm.c
+++ /dev/null
@@ -1,1207 +0,0 @@
-/*
- * linux/arch/m68k/kernel/traps.c
- *
- * Copyright (C) 1993, 1994 by Hamish Macdonald
- *
- * 68040 fixes by Michael Rausch
- * 68040 fixes by Martin Apel
- * 68040 fixes and writeback by Richard Zidlicky
- * 68060 fixes by Roman Hodek
- * 68060 fixes by Jesper Skov
- *
- * 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.
- */
-
-/*
- * Sets up all exception vectors
- */
-
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/user.h>
-#include <linux/string.h>
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/kallsyms.h>
-
-#include <asm/setup.h>
-#include <asm/fpu.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/traps.h>
-#include <asm/pgalloc.h>
-#include <asm/machdep.h>
-#include <asm/siginfo.h>
-
-/* assembler routines */
-asmlinkage void system_call(void);
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void nmihandler(void);
-#ifdef CONFIG_M68KFPU_EMU
-asmlinkage void fpu_emu(void);
-#endif
-
-e_vector vectors[256];
-
-/* nmi handler for the Amiga */
-asm(".text\n"
- __ALIGN_STR "\n"
- "nmihandler: rte");
-
-/*
- * this must be called very early as the kernel might
- * use some instruction that are emulated on the 060
- * and so we're prepared for early probe attempts (e.g. nf_init).
- */
-void __init base_trap_init(void)
-{
- if (MACH_IS_SUN3X) {
- extern e_vector *sun3x_prom_vbr;
-
- __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
- }
-
- /* setup the exception vector table */
- __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
-
- if (CPU_IS_060) {
- /* set up ISP entry points */
- asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
-
- vectors[VEC_UNIMPII] = unimp_vec;
- }
-
- vectors[VEC_BUSERR] = buserr;
- vectors[VEC_ILLEGAL] = trap;
- vectors[VEC_SYS] = system_call;
-}
-
-void __init trap_init (void)
-{
- int i;
-
- for (i = VEC_SPUR; i <= VEC_INT7; i++)
- vectors[i] = bad_inthandler;
-
- for (i = 0; i < VEC_USER; i++)
- if (!vectors[i])
- vectors[i] = trap;
-
- for (i = VEC_USER; i < 256; i++)
- vectors[i] = bad_inthandler;
-
-#ifdef CONFIG_M68KFPU_EMU
- if (FPU_IS_EMU)
- vectors[VEC_LINE11] = fpu_emu;
-#endif
-
- if (CPU_IS_040 && !FPU_IS_EMU) {
- /* set up FPSP entry points */
- asmlinkage void dz_vec(void) asm ("dz");
- asmlinkage void inex_vec(void) asm ("inex");
- asmlinkage void ovfl_vec(void) asm ("ovfl");
- asmlinkage void unfl_vec(void) asm ("unfl");
- asmlinkage void snan_vec(void) asm ("snan");
- asmlinkage void operr_vec(void) asm ("operr");
- asmlinkage void bsun_vec(void) asm ("bsun");
- asmlinkage void fline_vec(void) asm ("fline");
- asmlinkage void unsupp_vec(void) asm ("unsupp");
-
- vectors[VEC_FPDIVZ] = dz_vec;
- vectors[VEC_FPIR] = inex_vec;
- vectors[VEC_FPOVER] = ovfl_vec;
- vectors[VEC_FPUNDER] = unfl_vec;
- vectors[VEC_FPNAN] = snan_vec;
- vectors[VEC_FPOE] = operr_vec;
- vectors[VEC_FPBRUC] = bsun_vec;
- vectors[VEC_LINE11] = fline_vec;
- vectors[VEC_FPUNSUP] = unsupp_vec;
- }
-
- if (CPU_IS_060 && !FPU_IS_EMU) {
- /* set up IFPSP entry points */
- asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
- asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
- asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
- asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
- asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
- asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
- asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
- asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
- asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
-
- vectors[VEC_FPNAN] = snan_vec6;
- vectors[VEC_FPOE] = operr_vec6;
- vectors[VEC_FPOVER] = ovfl_vec6;
- vectors[VEC_FPUNDER] = unfl_vec6;
- vectors[VEC_FPDIVZ] = dz_vec6;
- vectors[VEC_FPIR] = inex_vec6;
- vectors[VEC_LINE11] = fline_vec6;
- vectors[VEC_FPUNSUP] = unsupp_vec6;
- vectors[VEC_UNIMPEA] = effadd_vec6;
- }
-
- /* if running on an amiga, make the NMI interrupt do nothing */
- if (MACH_IS_AMIGA) {
- vectors[VEC_INT7] = nmihandler;
- }
-}
-
-
-static const char *vec_names[] = {
- [VEC_RESETSP] = "RESET SP",
- [VEC_RESETPC] = "RESET PC",
- [VEC_BUSERR] = "BUS ERROR",
- [VEC_ADDRERR] = "ADDRESS ERROR",
- [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION",
- [VEC_ZERODIV] = "ZERO DIVIDE",
- [VEC_CHK] = "CHK",
- [VEC_TRAP] = "TRAPcc",
- [VEC_PRIV] = "PRIVILEGE VIOLATION",
- [VEC_TRACE] = "TRACE",
- [VEC_LINE10] = "LINE 1010",
- [VEC_LINE11] = "LINE 1111",
- [VEC_RESV12] = "UNASSIGNED RESERVED 12",
- [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION",
- [VEC_FORMAT] = "FORMAT ERROR",
- [VEC_UNINT] = "UNINITIALIZED INTERRUPT",
- [VEC_RESV16] = "UNASSIGNED RESERVED 16",
- [VEC_RESV17] = "UNASSIGNED RESERVED 17",
- [VEC_RESV18] = "UNASSIGNED RESERVED 18",
- [VEC_RESV19] = "UNASSIGNED RESERVED 19",
- [VEC_RESV20] = "UNASSIGNED RESERVED 20",
- [VEC_RESV21] = "UNASSIGNED RESERVED 21",
- [VEC_RESV22] = "UNASSIGNED RESERVED 22",
- [VEC_RESV23] = "UNASSIGNED RESERVED 23",
- [VEC_SPUR] = "SPURIOUS INTERRUPT",
- [VEC_INT1] = "LEVEL 1 INT",
- [VEC_INT2] = "LEVEL 2 INT",
- [VEC_INT3] = "LEVEL 3 INT",
- [VEC_INT4] = "LEVEL 4 INT",
- [VEC_INT5] = "LEVEL 5 INT",
- [VEC_INT6] = "LEVEL 6 INT",
- [VEC_INT7] = "LEVEL 7 INT",
- [VEC_SYS] = "SYSCALL",
- [VEC_TRAP1] = "TRAP #1",
- [VEC_TRAP2] = "TRAP #2",
- [VEC_TRAP3] = "TRAP #3",
- [VEC_TRAP4] = "TRAP #4",
- [VEC_TRAP5] = "TRAP #5",
- [VEC_TRAP6] = "TRAP #6",
- [VEC_TRAP7] = "TRAP #7",
- [VEC_TRAP8] = "TRAP #8",
- [VEC_TRAP9] = "TRAP #9",
- [VEC_TRAP10] = "TRAP #10",
- [VEC_TRAP11] = "TRAP #11",
- [VEC_TRAP12] = "TRAP #12",
- [VEC_TRAP13] = "TRAP #13",
- [VEC_TRAP14] = "TRAP #14",
- [VEC_TRAP15] = "TRAP #15",
- [VEC_FPBRUC] = "FPCP BSUN",
- [VEC_FPIR] = "FPCP INEXACT",
- [VEC_FPDIVZ] = "FPCP DIV BY 0",
- [VEC_FPUNDER] = "FPCP UNDERFLOW",
- [VEC_FPOE] = "FPCP OPERAND ERROR",
- [VEC_FPOVER] = "FPCP OVERFLOW",
- [VEC_FPNAN] = "FPCP SNAN",
- [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION",
- [VEC_MMUCFG] = "MMU CONFIGURATION ERROR",
- [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR",
- [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR",
- [VEC_RESV59] = "UNASSIGNED RESERVED 59",
- [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60",
- [VEC_UNIMPII] = "UNASSIGNED RESERVED 61",
- [VEC_RESV62] = "UNASSIGNED RESERVED 62",
- [VEC_RESV63] = "UNASSIGNED RESERVED 63",
-};
-
-static const char *space_names[] = {
- [0] = "Space 0",
- [USER_DATA] = "User Data",
- [USER_PROGRAM] = "User Program",
-#ifndef CONFIG_SUN3
- [3] = "Space 3",
-#else
- [FC_CONTROL] = "Control",
-#endif
- [4] = "Space 4",
- [SUPER_DATA] = "Super Data",
- [SUPER_PROGRAM] = "Super Program",
- [CPU_SPACE] = "CPU"
-};
-
-void die_if_kernel(char *,struct pt_regs *,int);
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
- unsigned long error_code);
-int send_fault_sig(struct pt_regs *regs);
-
-asmlinkage void trap_c(struct frame *fp);
-
-#if defined (CONFIG_M68060)
-static inline void access_error060 (struct frame *fp)
-{
- unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
-
-#ifdef DEBUG
- printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
-#endif
-
- if (fslw & MMU060_BPE) {
- /* branch prediction error -> clear branch cache */
- __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
- "orl #0x00400000,%/d0\n\t"
- "movec %/d0,%/cacr"
- : : : "d0" );
- /* return if there's no other error */
- if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
- return;
- }
-
- if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
- unsigned long errorcode;
- unsigned long addr = fp->un.fmt4.effaddr;
-
- if (fslw & MMU060_MA)
- addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
-
- errorcode = 1;
- if (fslw & MMU060_DESC_ERR) {
- __flush_tlb040_one(addr);
- errorcode = 0;
- }
- if (fslw & MMU060_W)
- errorcode |= 2;
-#ifdef DEBUG
- printk("errorcode = %d\n", errorcode );
-#endif
- do_page_fault(&fp->ptregs, addr, errorcode);
- } else if (fslw & (MMU060_SEE)){
- /* Software Emulation Error.
- * fault during mem_read/mem_write in ifpsp060/os.S
- */
- send_fault_sig(&fp->ptregs);
- } else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
- send_fault_sig(&fp->ptregs) > 0) {
- printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
- printk( "68060 access error, fslw=%lx\n", fslw );
- trap_c( fp );
- }
-}
-#endif /* CONFIG_M68060 */
-
-#if defined (CONFIG_M68040)
-static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
-{
- unsigned long mmusr;
- mm_segment_t old_fs = get_fs();
-
- set_fs(MAKE_MM_SEG(wbs));
-
- if (iswrite)
- asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
- else
- asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
-
- asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
-
- set_fs(old_fs);
-
- return mmusr;
-}
-
-static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
- unsigned long wbd)
-{
- int res = 0;
- mm_segment_t old_fs = get_fs();
-
- /* set_fs can not be moved, otherwise put_user() may oops */
- set_fs(MAKE_MM_SEG(wbs));
-
- switch (wbs & WBSIZ_040) {
- case BA_SIZE_BYTE:
- res = put_user(wbd & 0xff, (char __user *)wba);
- break;
- case BA_SIZE_WORD:
- res = put_user(wbd & 0xffff, (short __user *)wba);
- break;
- case BA_SIZE_LONG:
- res = put_user(wbd, (int __user *)wba);
- break;
- }
-
- /* set_fs can not be moved, otherwise put_user() may oops */
- set_fs(old_fs);
-
-
-#ifdef DEBUG
- printk("do_040writeback1, res=%d\n",res);
-#endif
-
- return res;
-}
-
-/* after an exception in a writeback the stack frame corresponding
- * to that exception is discarded, set a few bits in the old frame
- * to simulate what it should look like
- */
-static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
-{
- fp->un.fmt7.faddr = wba;
- fp->un.fmt7.ssw = wbs & 0xff;
- if (wba != current->thread.faddr)
- fp->un.fmt7.ssw |= MA_040;
-}
-
-static inline void do_040writebacks(struct frame *fp)
-{
- int res = 0;
-#if 0
- if (fp->un.fmt7.wb1s & WBV_040)
- printk("access_error040: cannot handle 1st writeback. oops.\n");
-#endif
-
- if ((fp->un.fmt7.wb2s & WBV_040) &&
- !(fp->un.fmt7.wb2s & WBTT_040)) {
- res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
- fp->un.fmt7.wb2d);
- if (res)
- fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
- else
- fp->un.fmt7.wb2s = 0;
- }
-
- /* do the 2nd wb only if the first one was successful (except for a kernel wb) */
- if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
- res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
- fp->un.fmt7.wb3d);
- if (res)
- {
- fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
-
- fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
- fp->un.fmt7.wb3s &= (~WBV_040);
- fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
- fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
- }
- else
- fp->un.fmt7.wb3s = 0;
- }
-
- if (res)
- send_fault_sig(&fp->ptregs);
-}
-
-/*
- * called from sigreturn(), must ensure userspace code didn't
- * manipulate exception frame to circumvent protection, then complete
- * pending writebacks
- * we just clear TM2 to turn it into a userspace access
- */
-asmlinkage void berr_040cleanup(struct frame *fp)
-{
- fp->un.fmt7.wb2s &= ~4;
- fp->un.fmt7.wb3s &= ~4;
-
- do_040writebacks(fp);
-}
-
-static inline void access_error040(struct frame *fp)
-{
- unsigned short ssw = fp->un.fmt7.ssw;
- unsigned long mmusr;
-
-#ifdef DEBUG
- printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
- printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
- fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
- printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
- fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
- fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
-#endif
-
- if (ssw & ATC_040) {
- unsigned long addr = fp->un.fmt7.faddr;
- unsigned long errorcode;
-
- /*
- * The MMU status has to be determined AFTER the address
- * has been corrected if there was a misaligned access (MA).
- */
- if (ssw & MA_040)
- addr = (addr + 7) & -8;
-
- /* MMU error, get the MMUSR info for this access */
- mmusr = probe040(!(ssw & RW_040), addr, ssw);
-#ifdef DEBUG
- printk("mmusr = %lx\n", mmusr);
-#endif
- errorcode = 1;
- if (!(mmusr & MMU_R_040)) {
- /* clear the invalid atc entry */
- __flush_tlb040_one(addr);
- errorcode = 0;
- }
-
- /* despite what documentation seems to say, RMW
- * accesses have always both the LK and RW bits set */
- if (!(ssw & RW_040) || (ssw & LK_040))
- errorcode |= 2;
-
- if (do_page_fault(&fp->ptregs, addr, errorcode)) {
-#ifdef DEBUG
- printk("do_page_fault() !=0\n");
-#endif
- if (user_mode(&fp->ptregs)){
- /* delay writebacks after signal delivery */
-#ifdef DEBUG
- printk(".. was usermode - return\n");
-#endif
- return;
- }
- /* disable writeback into user space from kernel
- * (if do_page_fault didn't fix the mapping,
- * the writeback won't do good)
- */
-disable_wb:
-#ifdef DEBUG
- printk(".. disabling wb2\n");
-#endif
- if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
- fp->un.fmt7.wb2s &= ~WBV_040;
- if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
- fp->un.fmt7.wb3s &= ~WBV_040;
- }
- } else {
- /* In case of a bus error we either kill the process or expect
- * the kernel to catch the fault, which then is also responsible
- * for cleaning up the mess.
- */
- current->thread.signo = SIGBUS;
- current->thread.faddr = fp->un.fmt7.faddr;
- if (send_fault_sig(&fp->ptregs) >= 0)
- printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
- fp->un.fmt7.faddr);
- goto disable_wb;
- }
-
- do_040writebacks(fp);
-}
-#endif /* CONFIG_M68040 */
-
-#if defined(CONFIG_SUN3)
-#include <asm/sun3mmu.h>
-
-extern int mmu_emu_handle_fault (unsigned long, int, int);
-
-/* sun3 version of bus_error030 */
-
-static inline void bus_error030 (struct frame *fp)
-{
- unsigned char buserr_type = sun3_get_buserr ();
- unsigned long addr, errorcode;
- unsigned short ssw = fp->un.fmtb.ssw;
- extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
-
-#ifdef DEBUG
- if (ssw & (FC | FB))
- printk ("Instruction fault at %#010lx\n",
- ssw & FC ?
- fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
- :
- fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
- if (ssw & DF)
- printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
- ssw & RW ? "read" : "write",
- fp->un.fmtb.daddr,
- space_names[ssw & DFC], fp->ptregs.pc);
-#endif
-
- /*
- * Check if this page should be demand-mapped. This needs to go before
- * the testing for a bad kernel-space access (demand-mapping applies
- * to kernel accesses too).
- */
-
- if ((ssw & DF)
- && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
- if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
- return;
- }
-
- /* Check for kernel-space pagefault (BAD). */
- if (fp->ptregs.sr & PS_S) {
- /* kernel fault must be a data fault to user space */
- if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
- // try checking the kernel mappings before surrender
- if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
- return;
- /* instruction fault or kernel data fault! */
- if (ssw & (FC | FB))
- printk ("Instruction fault at %#010lx\n",
- fp->ptregs.pc);
- if (ssw & DF) {
- /* was this fault incurred testing bus mappings? */
- if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
- (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
- send_fault_sig(&fp->ptregs);
- return;
- }
-
- printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
- ssw & RW ? "read" : "write",
- fp->un.fmtb.daddr,
- space_names[ssw & DFC], fp->ptregs.pc);
- }
- printk ("BAD KERNEL BUSERR\n");
-
- die_if_kernel("Oops", &fp->ptregs,0);
- force_sig(SIGKILL, current);
- return;
- }
- } else {
- /* user fault */
- if (!(ssw & (FC | FB)) && !(ssw & DF))
- /* not an instruction fault or data fault! BAD */
- panic ("USER BUSERR w/o instruction or data fault");
- }
-
-
- /* First handle the data fault, if any. */
- if (ssw & DF) {
- addr = fp->un.fmtb.daddr;
-
-// errorcode bit 0: 0 -> no page 1 -> protection fault
-// errorcode bit 1: 0 -> read fault 1 -> write fault
-
-// (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault
-// (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault
-
- if (buserr_type & SUN3_BUSERR_PROTERR)
- errorcode = 0x01;
- else if (buserr_type & SUN3_BUSERR_INVALID)
- errorcode = 0x00;
- else {
-#ifdef DEBUG
- printk ("*** unexpected busfault type=%#04x\n", buserr_type);
- printk ("invalid %s access at %#lx from pc %#lx\n",
- !(ssw & RW) ? "write" : "read", addr,
- fp->ptregs.pc);
-#endif
- die_if_kernel ("Oops", &fp->ptregs, buserr_type);
- force_sig (SIGBUS, current);
- return;
- }
-
-//todo: wtf is RM bit? --m
- if (!(ssw & RW) || ssw & RM)
- errorcode |= 0x02;
-
- /* Handle page fault. */
- do_page_fault (&fp->ptregs, addr, errorcode);
-
- /* Retry the data fault now. */
- return;
- }
-
- /* Now handle the instruction fault. */
-
- /* Get the fault address. */
- if (fp->ptregs.format == 0xA)
- addr = fp->ptregs.pc + 4;
- else
- addr = fp->un.fmtb.baddr;
- if (ssw & FC)
- addr -= 2;
-
- if (buserr_type & SUN3_BUSERR_INVALID) {
- if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
- do_page_fault (&fp->ptregs, addr, 0);
- } else {
-#ifdef DEBUG
- printk ("protection fault on insn access (segv).\n");
-#endif
- force_sig (SIGSEGV, current);
- }
-}
-#else
-#if defined(CPU_M68020_OR_M68030)
-static inline void bus_error030 (struct frame *fp)
-{
- volatile unsigned short temp;
- unsigned short mmusr;
- unsigned long addr, errorcode;
- unsigned short ssw = fp->un.fmtb.ssw;
-#ifdef DEBUG
- unsigned long desc;
-
- printk ("pid = %x ", current->pid);
- printk ("SSW=%#06x ", ssw);
-
- if (ssw & (FC | FB))
- printk ("Instruction fault at %#010lx\n",
- ssw & FC ?
- fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
- :
- fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
- if (ssw & DF)
- printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
- ssw & RW ? "read" : "write",
- fp->un.fmtb.daddr,
- space_names[ssw & DFC], fp->ptregs.pc);
-#endif
-
- /* ++andreas: If a data fault and an instruction fault happen
- at the same time map in both pages. */
-
- /* First handle the data fault, if any. */
- if (ssw & DF) {
- addr = fp->un.fmtb.daddr;
-
-#ifdef DEBUG
- asm volatile ("ptestr %3,%2@,#7,%0\n\t"
- "pmove %%psr,%1@"
- : "=a&" (desc)
- : "a" (&temp), "a" (addr), "d" (ssw));
-#else
- asm volatile ("ptestr %2,%1@,#7\n\t"
- "pmove %%psr,%0@"
- : : "a" (&temp), "a" (addr), "d" (ssw));
-#endif
- mmusr = temp;
-
-#ifdef DEBUG
- printk("mmusr is %#x for addr %#lx in task %p\n",
- mmusr, addr, current);
- printk("descriptor address is %#lx, contents %#lx\n",
- __va(desc), *(unsigned long *)__va(desc));
-#endif
-
- errorcode = (mmusr & MMU_I) ? 0 : 1;
- if (!(ssw & RW) || (ssw & RM))
- errorcode |= 2;
-
- if (mmusr & (MMU_I | MMU_WP)) {
- if (ssw & 4) {
- printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
- ssw & RW ? "read" : "write",
- fp->un.fmtb.daddr,
- space_names[ssw & DFC], fp->ptregs.pc);
- goto buserr;
- }
- /* Don't try to do anything further if an exception was
- handled. */
- if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
- return;
- } else if (!(mmusr & MMU_I)) {
- /* probably a 020 cas fault */
- if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
- printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
- } else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
- printk("invalid %s access at %#lx from pc %#lx\n",
- !(ssw & RW) ? "write" : "read", addr,
- fp->ptregs.pc);
- die_if_kernel("Oops",&fp->ptregs,mmusr);
- force_sig(SIGSEGV, current);
- return;
- } else {
-#if 0
- static volatile long tlong;
-#endif
-
- printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
- !(ssw & RW) ? "write" : "read", addr,
- fp->ptregs.pc, ssw);
- asm volatile ("ptestr #1,%1@,#0\n\t"
- "pmove %%psr,%0@"
- : /* no outputs */
- : "a" (&temp), "a" (addr));
- mmusr = temp;
-
- printk ("level 0 mmusr is %#x\n", mmusr);
-#if 0
- asm volatile ("pmove %%tt0,%0@"
- : /* no outputs */
- : "a" (&tlong));
- printk("tt0 is %#lx, ", tlong);
- asm volatile ("pmove %%tt1,%0@"
- : /* no outputs */
- : "a" (&tlong));
- printk("tt1 is %#lx\n", tlong);
-#endif
-#ifdef DEBUG
- printk("Unknown SIGSEGV - 1\n");
-#endif
- die_if_kernel("Oops",&fp->ptregs,mmusr);
- force_sig(SIGSEGV, current);
- return;
- }
-
- /* setup an ATC entry for the access about to be retried */
- if (!(ssw & RW) || (ssw & RM))
- asm volatile ("ploadw %1,%0@" : /* no outputs */
- : "a" (addr), "d" (ssw));
- else
- asm volatile ("ploadr %1,%0@" : /* no outputs */
- : "a" (addr), "d" (ssw));
- }
-
- /* Now handle the instruction fault. */
-
- if (!(ssw & (FC|FB)))
- return;
-
- if (fp->ptregs.sr & PS_S) {
- printk("Instruction fault at %#010lx\n",
- fp->ptregs.pc);
- buserr:
- printk ("BAD KERNEL BUSERR\n");
- die_if_kernel("Oops",&fp->ptregs,0);
- force_sig(SIGKILL, current);
- return;
- }
-
- /* get the fault address */
- if (fp->ptregs.format == 10)
- addr = fp->ptregs.pc + 4;
- else
- addr = fp->un.fmtb.baddr;
- if (ssw & FC)
- addr -= 2;
-
- if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
- /* Insn fault on same page as data fault. But we
- should still create the ATC entry. */
- goto create_atc_entry;
-
-#ifdef DEBUG
- asm volatile ("ptestr #1,%2@,#7,%0\n\t"
- "pmove %%psr,%1@"
- : "=a&" (desc)
- : "a" (&temp), "a" (addr));
-#else
- asm volatile ("ptestr #1,%1@,#7\n\t"
- "pmove %%psr,%0@"
- : : "a" (&temp), "a" (addr));
-#endif
- mmusr = temp;
-
-#ifdef DEBUG
- printk ("mmusr is %#x for addr %#lx in task %p\n",
- mmusr, addr, current);
- printk ("descriptor address is %#lx, contents %#lx\n",
- __va(desc), *(unsigned long *)__va(desc));
-#endif
-
- if (mmusr & MMU_I)
- do_page_fault (&fp->ptregs, addr, 0);
- else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
- printk ("invalid insn access at %#lx from pc %#lx\n",
- addr, fp->ptregs.pc);
-#ifdef DEBUG
- printk("Unknown SIGSEGV - 2\n");
-#endif
- die_if_kernel("Oops",&fp->ptregs,mmusr);
- force_sig(SIGSEGV, current);
- return;
- }
-
-create_atc_entry:
- /* setup an ATC entry for the access about to be retried */
- asm volatile ("ploadr #2,%0@" : /* no outputs */
- : "a" (addr));
-}
-#endif /* CPU_M68020_OR_M68030 */
-#endif /* !CONFIG_SUN3 */
-
-asmlinkage void buserr_c(struct frame *fp)
-{
- /* Only set esp0 if coming from user mode */
- if (user_mode(&fp->ptregs))
- current->thread.esp0 = (unsigned long) fp;
-
-#ifdef DEBUG
- printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
-#endif
-
- switch (fp->ptregs.format) {
-#if defined (CONFIG_M68060)
- case 4: /* 68060 access error */
- access_error060 (fp);
- break;
-#endif
-#if defined (CONFIG_M68040)
- case 0x7: /* 68040 access error */
- access_error040 (fp);
- break;
-#endif
-#if defined (CPU_M68020_OR_M68030)
- case 0xa:
- case 0xb:
- bus_error030 (fp);
- break;
-#endif
- default:
- die_if_kernel("bad frame format",&fp->ptregs,0);
-#ifdef DEBUG
- printk("Unknown SIGSEGV - 4\n");
-#endif
- force_sig(SIGSEGV, current);
- }
-}
-
-
-static int kstack_depth_to_print = 48;
-
-void show_trace(unsigned long *stack)
-{
- unsigned long *endstack;
- unsigned long addr;
- int i;
-
- printk("Call Trace:");
- addr = (unsigned long)stack + THREAD_SIZE - 1;
- endstack = (unsigned long *)(addr & -THREAD_SIZE);
- i = 0;
- while (stack + 1 <= endstack) {
- addr = *stack++;
- /*
- * If the address is either in the text segment of the
- * kernel, or in the region which contains vmalloc'ed
- * memory, it *may* be the address of a calling
- * routine; if so, print it so that someone tracing
- * down the cause of the crash will be able to figure
- * out the call path that was taken.
- */
- if (__kernel_text_address(addr)) {
-#ifndef CONFIG_KALLSYMS
- if (i % 5 == 0)
- printk("\n ");
-#endif
- printk(" [<%08lx>] %pS\n", addr, (void *)addr);
- i++;
- }
- }
- printk("\n");
-}
-
-void show_registers(struct pt_regs *regs)
-{
- struct frame *fp = (struct frame *)regs;
- mm_segment_t old_fs = get_fs();
- u16 c, *cp;
- unsigned long addr;
- int i;
-
- print_modules();
- printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
- printk("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2);
- printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
- regs->d0, regs->d1, regs->d2, regs->d3);
- printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
- regs->d4, regs->d5, regs->a0, regs->a1);
-
- printk("Process %s (pid: %d, task=%p)\n",
- current->comm, task_pid_nr(current), current);
- addr = (unsigned long)&fp->un;
- printk("Frame format=%X ", regs->format);
- switch (regs->format) {
- case 0x2:
- printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
- addr += sizeof(fp->un.fmt2);
- break;
- case 0x3:
- printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
- addr += sizeof(fp->un.fmt3);
- break;
- case 0x4:
- printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
- : "eff addr=%08lx pc=%08lx\n"),
- fp->un.fmt4.effaddr, fp->un.fmt4.pc);
- addr += sizeof(fp->un.fmt4);
- break;
- case 0x7:
- printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
- fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
- printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
- fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
- printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
- fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
- printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
- fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
- printk("push data: %08lx %08lx %08lx %08lx\n",
- fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
- fp->un.fmt7.pd3);
- addr += sizeof(fp->un.fmt7);
- break;
- case 0x9:
- printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
- addr += sizeof(fp->un.fmt9);
- break;
- case 0xa:
- printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
- fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
- fp->un.fmta.daddr, fp->un.fmta.dobuf);
- addr += sizeof(fp->un.fmta);
- break;
- case 0xb:
- printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
- fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
- fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
- printk("baddr=%08lx dibuf=%08lx ver=%x\n",
- fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
- addr += sizeof(fp->un.fmtb);
- break;
- default:
- printk("\n");
- }
- show_stack(NULL, (unsigned long *)addr);
-
- printk("Code:");
- set_fs(KERNEL_DS);
- cp = (u16 *)regs->pc;
- for (i = -8; i < 16; i++) {
- if (get_user(c, cp + i) && i >= 0) {
- printk(" Bad PC value.");
- break;
- }
- printk(i ? " %04x" : " <%04x>", c);
- }
- set_fs(old_fs);
- printk ("\n");
-}
-
-void show_stack(struct task_struct *task, unsigned long *stack)
-{
- unsigned long *p;
- unsigned long *endstack;
- int i;
-
- if (!stack) {
- if (task)
- stack = (unsigned long *)task->thread.esp0;
- else
- stack = (unsigned long *)&stack;
- }
- endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
-
- printk("Stack from %08lx:", (unsigned long)stack);
- p = stack;
- for (i = 0; i < kstack_depth_to_print; i++) {
- if (p + 1 > endstack)
- break;
- if (i % 8 == 0)
- printk("\n ");
- printk(" %08lx", *p++);
- }
- printk("\n");
- show_trace(stack);
-}
-
-/*
- * The architecture-independent backtrace generator
- */
-void dump_stack(void)
-{
- unsigned long stack;
-
- show_trace(&stack);
-}
-
-EXPORT_SYMBOL(dump_stack);
-
-void bad_super_trap (struct frame *fp)
-{
- console_verbose();
- if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
- printk ("*** %s *** FORMAT=%X\n",
- vec_names[(fp->ptregs.vector) >> 2],
- fp->ptregs.format);
- else
- printk ("*** Exception %d *** FORMAT=%X\n",
- (fp->ptregs.vector) >> 2,
- fp->ptregs.format);
- if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
- unsigned short ssw = fp->un.fmtb.ssw;
-
- printk ("SSW=%#06x ", ssw);
-
- if (ssw & RC)
- printk ("Pipe stage C instruction fault at %#010lx\n",
- (fp->ptregs.format) == 0xA ?
- fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
- if (ssw & RB)
- printk ("Pipe stage B instruction fault at %#010lx\n",
- (fp->ptregs.format) == 0xA ?
- fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
- if (ssw & DF)
- printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
- ssw & RW ? "read" : "write",
- fp->un.fmtb.daddr, space_names[ssw & DFC],
- fp->ptregs.pc);
- }
- printk ("Current process id is %d\n", task_pid_nr(current));
- die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
-}
-
-asmlinkage void trap_c(struct frame *fp)
-{
- int sig;
- siginfo_t info;
-
- if (fp->ptregs.sr & PS_S) {
- if (fp->ptregs.vector == VEC_TRACE << 2) {
- /* traced a trapping instruction on a 68020/30,
- * real exception will be executed afterwards.
- */
- } else if (!handle_kernel_fault(&fp->ptregs))
- bad_super_trap(fp);
- return;
- }
-
- /* send the appropriate signal to the user program */
- switch ((fp->ptregs.vector) >> 2) {
- case VEC_ADDRERR:
- info.si_code = BUS_ADRALN;
- sig = SIGBUS;
- break;
- case VEC_ILLEGAL:
- case VEC_LINE10:
- case VEC_LINE11:
- info.si_code = ILL_ILLOPC;
- sig = SIGILL;
- break;
- case VEC_PRIV:
- info.si_code = ILL_PRVOPC;
- sig = SIGILL;
- break;
- case VEC_COPROC:
- info.si_code = ILL_COPROC;
- sig = SIGILL;
- break;
- case VEC_TRAP1:
- case VEC_TRAP2:
- case VEC_TRAP3:
- case VEC_TRAP4:
- case VEC_TRAP5:
- case VEC_TRAP6:
- case VEC_TRAP7:
- case VEC_TRAP8:
- case VEC_TRAP9:
- case VEC_TRAP10:
- case VEC_TRAP11:
- case VEC_TRAP12:
- case VEC_TRAP13:
- case VEC_TRAP14:
- info.si_code = ILL_ILLTRP;
- sig = SIGILL;
- break;
- case VEC_FPBRUC:
- case VEC_FPOE:
- case VEC_FPNAN:
- info.si_code = FPE_FLTINV;
- sig = SIGFPE;
- break;
- case VEC_FPIR:
- info.si_code = FPE_FLTRES;
- sig = SIGFPE;
- break;
- case VEC_FPDIVZ:
- info.si_code = FPE_FLTDIV;
- sig = SIGFPE;
- break;
- case VEC_FPUNDER:
- info.si_code = FPE_FLTUND;
- sig = SIGFPE;
- break;
- case VEC_FPOVER:
- info.si_code = FPE_FLTOVF;
- sig = SIGFPE;
- break;
- case VEC_ZERODIV:
- info.si_code = FPE_INTDIV;
- sig = SIGFPE;
- break;
- case VEC_CHK:
- case VEC_TRAP:
- info.si_code = FPE_INTOVF;
- sig = SIGFPE;
- break;
- case VEC_TRACE: /* ptrace single step */
- info.si_code = TRAP_TRACE;
- sig = SIGTRAP;
- break;
- case VEC_TRAP15: /* breakpoint */
- info.si_code = TRAP_BRKPT;
- sig = SIGTRAP;
- break;
- default:
- info.si_code = ILL_ILLOPC;
- sig = SIGILL;
- break;
- }
- info.si_signo = sig;
- info.si_errno = 0;
- switch (fp->ptregs.format) {
- default:
- info.si_addr = (void *) fp->ptregs.pc;
- break;
- case 2:
- info.si_addr = (void *) fp->un.fmt2.iaddr;
- break;
- case 7:
- info.si_addr = (void *) fp->un.fmt7.effaddr;
- break;
- case 9:
- info.si_addr = (void *) fp->un.fmt9.iaddr;
- break;
- case 10:
- info.si_addr = (void *) fp->un.fmta.daddr;
- break;
- case 11:
- info.si_addr = (void *) fp->un.fmtb.daddr;
- break;
- }
- force_sig_info (sig, &info, current);
-}
-
-void die_if_kernel (char *str, struct pt_regs *fp, int nr)
-{
- if (!(fp->sr & PS_S))
- return;
-
- console_verbose();
- printk("%s: %08x\n",str,nr);
- show_registers(fp);
- add_taint(TAINT_DIE);
- do_exit(SIGSEGV);
-}
-
-/*
- * This function is called if an error occur while accessing
- * user-space from the fpsp040 code.
- */
-asmlinkage void fpsp040_die(void)
-{
- do_exit(SIGSEGV);
-}
-
-#ifdef CONFIG_M68KFPU_EMU
-asmlinkage void fpemu_signal(int signal, int code, void *addr)
-{
- siginfo_t info;
-
- info.si_signo = signal;
- info.si_errno = 0;
- info.si_code = code;
- info.si_addr = addr;
- force_sig_info(signal, &info, current);
-}
-#endif
diff --git a/arch/m68k/kernel/traps_no.c b/arch/m68k/kernel/traps_no.c
deleted file mode 100644
index e67b8c806959..000000000000
--- a/arch/m68k/kernel/traps_no.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * linux/arch/m68knommu/kernel/traps.c
- *
- * Copyright (C) 1993, 1994 by Hamish Macdonald
- *
- * 68040 fixes by Michael Rausch
- * 68040 fixes by Martin Apel
- * 68060 fixes by Roman Hodek
- * 68060 fixes by Jesper Skov
- *
- * 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.
- */
-
-/*
- * Sets up all exception vectors
- */
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/user.h>
-#include <linux/string.h>
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/kallsyms.h>
-
-#include <asm/setup.h>
-#include <asm/fpu.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/traps.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/siginfo.h>
-
-static char const * const vec_names[] = {
- "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
- "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
- "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
- "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
- "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
- "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
- "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
- "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
- "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
- "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
- "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
- "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
- "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
- "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
- "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
- "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
- "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
- "FPCP UNSUPPORTED OPERATION",
- "MMU CONFIGURATION ERROR"
-};
-
-void die_if_kernel(char *str, struct pt_regs *fp, int nr)
-{
- if (!(fp->sr & PS_S))
- return;
-
- console_verbose();
- printk(KERN_EMERG "%s: %08x\n",str,nr);
- printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n",
- fp->pc, fp->sr, fp, fp->a2);
- printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
- fp->d0, fp->d1, fp->d2, fp->d3);
- printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
- fp->d4, fp->d5, fp->a0, fp->a1);
-
- printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
- current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
- show_stack(NULL, (unsigned long *)(fp + 1));
- add_taint(TAINT_DIE);
- do_exit(SIGSEGV);
-}
-
-asmlinkage void buserr_c(struct frame *fp)
-{
- /* Only set esp0 if coming from user mode */
- if (user_mode(&fp->ptregs))
- current->thread.esp0 = (unsigned long) fp;
-
-#if defined(DEBUG)
- printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
-#endif
-
- die_if_kernel("bad frame format",&fp->ptregs,0);
-#if defined(DEBUG)
- printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
-#endif
- force_sig(SIGSEGV, current);
-}
-
-static void print_this_address(unsigned long addr, int i)
-{
-#ifdef CONFIG_KALLSYMS
- printk(KERN_EMERG " [%08lx] ", addr);
- print_symbol(KERN_CONT "%s\n", addr);
-#else
- if (i % 5)
- printk(KERN_CONT " [%08lx] ", addr);
- else
- printk(KERN_EMERG " [%08lx] ", addr);
- i++;
-#endif
-}
-
-int kstack_depth_to_print = 48;
-
-static void __show_stack(struct task_struct *task, unsigned long *stack)
-{
- unsigned long *endstack, addr;
-#ifdef CONFIG_FRAME_POINTER
- unsigned long *last_stack;
-#endif
- int i;
-
- if (!stack)
- stack = (unsigned long *)task->thread.ksp;
-
- addr = (unsigned long) stack;
- endstack = (unsigned long *) PAGE_ALIGN(addr);
-
- printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
- for (i = 0; i < kstack_depth_to_print; i++) {
- if (stack + 1 + i > endstack)
- break;
- if (i % 8 == 0)
- printk(KERN_EMERG " ");
- printk(KERN_CONT " %08lx", *(stack + i));
- }
- printk("\n");
- i = 0;
-
-#ifdef CONFIG_FRAME_POINTER
- printk(KERN_EMERG "Call Trace:\n");
-
- last_stack = stack - 1;
- while (stack <= endstack && stack > last_stack) {
-
- addr = *(stack + 1);
- print_this_address(addr, i);
- i++;
-
- last_stack = stack;
- stack = (unsigned long *)*stack;
- }
- printk("\n");
-#else
- printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
- while (stack <= endstack) {
- addr = *stack++;
- /*
- * If the address is either in the text segment of the kernel,
- * or in a region which is occupied by a module then it *may*
- * be the address of a calling routine; if so, print it so that
- * someone tracing down the cause of the crash will be able to
- * figure out the call path that was taken.
- */
- if (__kernel_text_address(addr)) {
- print_this_address(addr, i);
- i++;
- }
- }
- printk(KERN_CONT "\n");
-#endif
-}
-
-void bad_super_trap(struct frame *fp)
-{
- int vector = (fp->ptregs.vector >> 2) & 0xff;
-
- console_verbose();
- if (vector < ARRAY_SIZE(vec_names))
- printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
- vec_names[vector],
- fp->ptregs.format);
- else
- printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
- vector,
- fp->ptregs.format);
- printk (KERN_WARNING "Current process id is %d\n", current->pid);
- die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
-}
-
-asmlinkage void trap_c(struct frame *fp)
-{
- int sig;
- int vector = (fp->ptregs.vector >> 2) & 0xff;
- siginfo_t info;
-
- if (fp->ptregs.sr & PS_S) {
- if (vector == VEC_TRACE) {
- /* traced a trapping instruction */
- } else
- bad_super_trap(fp);
- return;
- }
-
- /* send the appropriate signal to the user program */
- switch (vector) {
- case VEC_ADDRERR:
- info.si_code = BUS_ADRALN;
- sig = SIGBUS;
- break;
- case VEC_ILLEGAL:
- case VEC_LINE10:
- case VEC_LINE11:
- info.si_code = ILL_ILLOPC;
- sig = SIGILL;
- break;
- case VEC_PRIV:
- info.si_code = ILL_PRVOPC;
- sig = SIGILL;
- break;
- case VEC_COPROC:
- info.si_code = ILL_COPROC;
- sig = SIGILL;
- break;
- case VEC_TRAP1: /* gdbserver breakpoint */
- fp->ptregs.pc -= 2;
- info.si_code = TRAP_TRACE;
- sig = SIGTRAP;
- break;
- case VEC_TRAP2:
- case VEC_TRAP3:
- case VEC_TRAP4:
- case VEC_TRAP5:
- case VEC_TRAP6:
- case VEC_TRAP7:
- case VEC_TRAP8:
- case VEC_TRAP9:
- case VEC_TRAP10:
- case VEC_TRAP11:
- case VEC_TRAP12:
- case VEC_TRAP13:
- case VEC_TRAP14:
- info.si_code = ILL_ILLTRP;
- sig = SIGILL;
- break;
- case VEC_FPBRUC:
- case VEC_FPOE:
- case VEC_FPNAN:
- info.si_code = FPE_FLTINV;
- sig = SIGFPE;
- break;
- case VEC_FPIR:
- info.si_code = FPE_FLTRES;
- sig = SIGFPE;
- break;
- case VEC_FPDIVZ:
- info.si_code = FPE_FLTDIV;
- sig = SIGFPE;
- break;
- case VEC_FPUNDER:
- info.si_code = FPE_FLTUND;
- sig = SIGFPE;
- break;
- case VEC_FPOVER:
- info.si_code = FPE_FLTOVF;
- sig = SIGFPE;
- break;
- case VEC_ZERODIV:
- info.si_code = FPE_INTDIV;
- sig = SIGFPE;
- break;
- case VEC_CHK:
- case VEC_TRAP:
- info.si_code = FPE_INTOVF;
- sig = SIGFPE;
- break;
- case VEC_TRACE: /* ptrace single step */
- info.si_code = TRAP_TRACE;
- sig = SIGTRAP;
- break;
- case VEC_TRAP15: /* breakpoint */
- info.si_code = TRAP_BRKPT;
- sig = SIGTRAP;
- break;
- default:
- info.si_code = ILL_ILLOPC;
- sig = SIGILL;
- break;
- }
- info.si_signo = sig;
- info.si_errno = 0;
- switch (fp->ptregs.format) {
- default:
- info.si_addr = (void *) fp->ptregs.pc;
- break;
- case 2:
- info.si_addr = (void *) fp->un.fmt2.iaddr;
- break;
- case 7:
- info.si_addr = (void *) fp->un.fmt7.effaddr;
- break;
- case 9:
- info.si_addr = (void *) fp->un.fmt9.iaddr;
- break;
- case 10:
- info.si_addr = (void *) fp->un.fmta.daddr;
- break;
- case 11:
- info.si_addr = (void *) fp->un.fmtb.daddr;
- break;
- }
- force_sig_info (sig, &info, current);
-}
-
-asmlinkage void set_esp0(unsigned long ssp)
-{
- current->thread.esp0 = ssp;
-}
-
-/*
- * The architecture-independent backtrace generator
- */
-void dump_stack(void)
-{
- /*
- * We need frame pointers for this little trick, which works as follows:
- *
- * +------------+ 0x00
- * | Next SP | -> 0x0c
- * +------------+ 0x04
- * | Caller |
- * +------------+ 0x08
- * | Local vars | -> our stack var
- * +------------+ 0x0c
- * | Next SP | -> 0x18, that is what we pass to show_stack()
- * +------------+ 0x10
- * | Caller |
- * +------------+ 0x14
- * | Local vars |
- * +------------+ 0x18
- * | ... |
- * +------------+
- */
-
- unsigned long *stack;
-
- stack = (unsigned long *)&stack;
- stack++;
- __show_stack(current, stack);
-}
-EXPORT_SYMBOL(dump_stack);
-
-void show_stack(struct task_struct *task, unsigned long *stack)
-{
- if (!stack && !task)
- dump_stack();
- else
- __show_stack(task, stack);
-}
diff --git a/arch/m68k/kernel/vectors.c b/arch/m68k/kernel/vectors.c
new file mode 100644
index 000000000000..147b03fbc71e
--- /dev/null
+++ b/arch/m68k/kernel/vectors.c
@@ -0,0 +1,145 @@
+/*
+ * vectors.c
+ *
+ * Copyright (C) 1993, 1994 by Hamish Macdonald
+ *
+ * 68040 fixes by Michael Rausch
+ * 68040 fixes by Martin Apel
+ * 68040 fixes and writeback by Richard Zidlicky
+ * 68060 fixes by Roman Hodek
+ * 68060 fixes by Jesper Skov
+ *
+ * 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.
+ */
+
+/*
+ * Sets up all exception vectors
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/kallsyms.h>
+
+#include <asm/setup.h>
+#include <asm/fpu.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+
+/* assembler routines */
+asmlinkage void system_call(void);
+asmlinkage void buserr(void);
+asmlinkage void trap(void);
+asmlinkage void nmihandler(void);
+#ifdef CONFIG_M68KFPU_EMU
+asmlinkage void fpu_emu(void);
+#endif
+
+e_vector vectors[256];
+
+/* nmi handler for the Amiga */
+asm(".text\n"
+ __ALIGN_STR "\n"
+ "nmihandler: rte");
+
+/*
+ * this must be called very early as the kernel might
+ * use some instruction that are emulated on the 060
+ * and so we're prepared for early probe attempts (e.g. nf_init).
+ */
+void __init base_trap_init(void)
+{
+ if (MACH_IS_SUN3X) {
+ extern e_vector *sun3x_prom_vbr;
+
+ __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
+ }
+
+ /* setup the exception vector table */
+ __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
+
+ if (CPU_IS_060) {
+ /* set up ISP entry points */
+ asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
+
+ vectors[VEC_UNIMPII] = unimp_vec;
+ }
+
+ vectors[VEC_BUSERR] = buserr;
+ vectors[VEC_ILLEGAL] = trap;
+ vectors[VEC_SYS] = system_call;
+}
+
+void __init trap_init (void)
+{
+ int i;
+
+ for (i = VEC_SPUR; i <= VEC_INT7; i++)
+ vectors[i] = bad_inthandler;
+
+ for (i = 0; i < VEC_USER; i++)
+ if (!vectors[i])
+ vectors[i] = trap;
+
+ for (i = VEC_USER; i < 256; i++)
+ vectors[i] = bad_inthandler;
+
+#ifdef CONFIG_M68KFPU_EMU
+ if (FPU_IS_EMU)
+ vectors[VEC_LINE11] = fpu_emu;
+#endif
+
+ if (CPU_IS_040 && !FPU_IS_EMU) {
+ /* set up FPSP entry points */
+ asmlinkage void dz_vec(void) asm ("dz");
+ asmlinkage void inex_vec(void) asm ("inex");
+ asmlinkage void ovfl_vec(void) asm ("ovfl");
+ asmlinkage void unfl_vec(void) asm ("unfl");
+ asmlinkage void snan_vec(void) asm ("snan");
+ asmlinkage void operr_vec(void) asm ("operr");
+ asmlinkage void bsun_vec(void) asm ("bsun");
+ asmlinkage void fline_vec(void) asm ("fline");
+ asmlinkage void unsupp_vec(void) asm ("unsupp");
+
+ vectors[VEC_FPDIVZ] = dz_vec;
+ vectors[VEC_FPIR] = inex_vec;
+ vectors[VEC_FPOVER] = ovfl_vec;
+ vectors[VEC_FPUNDER] = unfl_vec;
+ vectors[VEC_FPNAN] = snan_vec;
+ vectors[VEC_FPOE] = operr_vec;
+ vectors[VEC_FPBRUC] = bsun_vec;
+ vectors[VEC_LINE11] = fline_vec;
+ vectors[VEC_FPUNSUP] = unsupp_vec;
+ }
+
+ if (CPU_IS_060 && !FPU_IS_EMU) {
+ /* set up IFPSP entry points */
+ asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
+ asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
+ asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
+ asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
+ asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
+ asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
+ asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
+ asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
+ asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
+
+ vectors[VEC_FPNAN] = snan_vec6;
+ vectors[VEC_FPOE] = operr_vec6;
+ vectors[VEC_FPOVER] = ovfl_vec6;
+ vectors[VEC_FPUNDER] = unfl_vec6;
+ vectors[VEC_FPDIVZ] = dz_vec6;
+ vectors[VEC_FPIR] = inex_vec6;
+ vectors[VEC_LINE11] = fline_vec6;
+ vectors[VEC_FPUNSUP] = unsupp_vec6;
+ vectors[VEC_UNIMPEA] = effadd_vec6;
+ }
+
+ /* if running on an amiga, make the NMI interrupt do nothing */
+ if (MACH_IS_AMIGA) {
+ vectors[VEC_INT7] = nmihandler;
+ }
+}
+
diff --git a/arch/m68k/kernel/vmlinux.lds_no.S b/arch/m68k/kernel/vmlinux.lds_no.S
index 7dc4087a9545..4e2389340837 100644
--- a/arch/m68k/kernel/vmlinux.lds_no.S
+++ b/arch/m68k/kernel/vmlinux.lds_no.S
@@ -77,7 +77,6 @@ SECTIONS {
*(.rodata) *(.rodata.*)
*(__vermagic) /* Kernel version magic */
- *(__markers_strings)
*(.rodata1)
*(.rodata.str1.1)
diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c
index 064889316974..10ca051d56b8 100644
--- a/arch/m68k/lib/memcpy.c
+++ b/arch/m68k/lib/memcpy.c
@@ -22,6 +22,15 @@ void *memcpy(void *to, const void *from, size_t n)
from = cfrom;
n--;
}
+#if defined(CONFIG_M68000)
+ if ((long)from & 1) {
+ char *cto = to;
+ const char *cfrom = from;
+ for (; n; n--)
+ *cto++ = *cfrom++;
+ return xto;
+ }
+#endif
if (n > 2 && (long)to & 2) {
short *sto = to;
const short *sfrom = from;
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index 900d899f3323..f92190c159b4 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -370,7 +370,7 @@ int mac_irq_pending(unsigned int irq)
break;
case 4:
if (psc_present)
- psc_irq_pending(irq);
+ return psc_irq_pending(irq);
break;
}
return 0;
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
index e023fc6b37e5..eb915551de69 100644
--- a/arch/m68k/mac/misc.c
+++ b/arch/m68k/mac/misc.c
@@ -304,35 +304,41 @@ static void via_write_pram(int offset, __u8 data)
static long via_read_time(void)
{
union {
- __u8 cdata[4];
- long idata;
+ __u8 cdata[4];
+ long idata;
} result, last_result;
- int ct;
+ int count = 1;
+
+ via_pram_command(0x81, &last_result.cdata[3]);
+ via_pram_command(0x85, &last_result.cdata[2]);
+ via_pram_command(0x89, &last_result.cdata[1]);
+ via_pram_command(0x8D, &last_result.cdata[0]);
/*
* The NetBSD guys say to loop until you get the same reading
* twice in a row.
*/
- ct = 0;
- do {
- if (++ct > 10) {
- printk("via_read_time: couldn't get valid time, "
- "last read = 0x%08lx and 0x%08lx\n",
- last_result.idata, result.idata);
- break;
- }
-
- last_result.idata = result.idata;
- result.idata = 0;
-
+ while (1) {
via_pram_command(0x81, &result.cdata[3]);
via_pram_command(0x85, &result.cdata[2]);
via_pram_command(0x89, &result.cdata[1]);
via_pram_command(0x8D, &result.cdata[0]);
- } while (result.idata != last_result.idata);
- return result.idata - RTC_OFFSET;
+ if (result.idata == last_result.idata)
+ return result.idata - RTC_OFFSET;
+
+ if (++count > 10)
+ break;
+
+ last_result.idata = result.idata;
+ }
+
+ pr_err("via_read_time: failed to read a stable value; "
+ "got 0x%08lx then 0x%08lx\n",
+ last_result.idata, result.idata);
+
+ return 0;
}
/*
diff --git a/arch/m68k/mm/init_no.c b/arch/m68k/mm/init_no.c
index 50cd12cf28d9..1e33d39ca9a0 100644
--- a/arch/m68k/mm/init_no.c
+++ b/arch/m68k/mm/init_no.c
@@ -32,6 +32,7 @@
#include <linux/gfp.h>
#include <asm/setup.h>
+#include <asm/sections.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -44,9 +45,6 @@
*/
void *empty_zero_page;
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
/*
* paging_init() continues the virtual memory environment setup which
* was begun by the code in arch/head.S.
@@ -78,8 +76,6 @@ void __init mem_init(void)
{
int codek = 0, datak = 0, initk = 0;
unsigned long tmp;
- extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end;
- extern unsigned int _ramend, _rambase;
unsigned long len = _ramend - _rambase;
unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
unsigned long end_mem = memory_end; /* DAVIDM - this must not include kernel stack at top */
@@ -95,9 +91,9 @@ void __init mem_init(void)
/* this will put all memory onto the freelists */
totalram_pages = free_all_bootmem();
- codek = (&_etext - &_stext) >> 10;
- datak = (&_ebss - &_sdata) >> 10;
- initk = (&__init_begin - &__init_end) >> 10;
+ codek = (_etext - _stext) >> 10;
+ datak = (_ebss - _sdata) >> 10;
+ initk = (__init_begin - __init_end) >> 10;
tmp = nr_free_pages() << PAGE_SHIFT;
printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
@@ -129,22 +125,21 @@ void free_initmem(void)
{
#ifdef CONFIG_RAMKERNEL
unsigned long addr;
- extern char __init_begin, __init_end;
/*
* The following code should be cool even if these sections
* are not page aligned.
*/
- addr = PAGE_ALIGN((unsigned long)(&__init_begin));
+ addr = PAGE_ALIGN((unsigned long) __init_begin);
/* next to check that the page we free is not a partial page */
- for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
+ for (; addr + PAGE_SIZE < ((unsigned long) __init_end); addr += PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
init_page_count(virt_to_page(addr));
free_page(addr);
totalram_pages++;
}
pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n",
- (addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
- (int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
+ (addr - PAGE_ALIGN((unsigned long) __init_begin)) >> 10,
+ (int)(PAGE_ALIGN((unsigned long) __init_begin)),
(int)(addr - PAGE_SIZE));
#endif
}
diff --git a/arch/m68k/platform/520x/config.c b/arch/m68k/platform/520x/config.c
index 621238f1a219..8a98683f1b15 100644
--- a/arch/m68k/platform/520x/config.c
+++ b/arch/m68k/platform/520x/config.c
@@ -91,9 +91,9 @@ static struct resource m520x_qspi_resources[] = {
},
};
-#define MCFQSPI_CS0 62
-#define MCFQSPI_CS1 63
-#define MCFQSPI_CS2 44
+#define MCFQSPI_CS0 46
+#define MCFQSPI_CS1 47
+#define MCFQSPI_CS2 27
static int m520x_cs_setup(struct mcfqspi_cs_control *cs_control)
{
diff --git a/arch/m68k/platform/520x/gpio.c b/arch/m68k/platform/520x/gpio.c
index d757328563d1..9bcc3e4b60c5 100644
--- a/arch/m68k/platform/520x/gpio.c
+++ b/arch/m68k/platform/520x/gpio.c
@@ -38,42 +38,6 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
},
{
.gpio_chip = {
- .label = "BUSCTL",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 8,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_BUSCTL,
- .podr = (void __iomem *) MCFGPIO_PODR_BUSCTL,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
- },
- {
- .gpio_chip = {
- .label = "BE",
- .request = mcf_gpio_request,
- .free = mcf_gpio_free,
- .direction_input = mcf_gpio_direction_input,
- .direction_output = mcf_gpio_direction_output,
- .get = mcf_gpio_get_value,
- .set = mcf_gpio_set_value_fast,
- .base = 16,
- .ngpio = 4,
- },
- .pddr = (void __iomem *) MCFGPIO_PDDR_BE,
- .podr = (void __iomem *) MCFGPIO_PODR_BE,
- .ppdr = (void __iomem *) MCFGPIO_PPDSDR_BE,
- .setr = (void __iomem *) MCFGPIO_PPDSDR_BE,
- .clrr = (void __iomem *) MCFGPIO_PCLRR_BE,
- },
- {
- .gpio_chip = {
.label = "CS",
.request = mcf_gpio_request,
.free = mcf_gpio_free,
@@ -81,7 +45,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
.direction_output = mcf_gpio_direction_output,
.get = mcf_gpio_get_value,
.set = mcf_gpio_set_value_fast,
- .base = 25,
+ .base = 9,
.ngpio = 3,
},
.pddr = (void __iomem *) MCFGPIO_PDDR_CS,
@@ -99,7 +63,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
.direction_output = mcf_gpio_direction_output,
.get = mcf_gpio_get_value,
.set = mcf_gpio_set_value_fast,
- .base = 32,
+ .base = 16,
.ngpio = 4,
},
.pddr = (void __iomem *) MCFGPIO_PDDR_FECI2C,
@@ -117,7 +81,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
.direction_output = mcf_gpio_direction_output,
.get = mcf_gpio_get_value,
.set = mcf_gpio_set_value_fast,
- .base = 40,
+ .base = 24,
.ngpio = 4,
},
.pddr = (void __iomem *) MCFGPIO_PDDR_QSPI,
@@ -135,7 +99,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
.direction_output = mcf_gpio_direction_output,
.get = mcf_gpio_get_value,
.set = mcf_gpio_set_value_fast,
- .base = 48,
+ .base = 32,
.ngpio = 4,
},
.pddr = (void __iomem *) MCFGPIO_PDDR_TIMER,
@@ -153,7 +117,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
.direction_output = mcf_gpio_direction_output,
.get = mcf_gpio_get_value,
.set = mcf_gpio_set_value_fast,
- .base = 56,
+ .base = 40,
.ngpio = 8,
},
.pddr = (void __iomem *) MCFGPIO_PDDR_UART,
@@ -171,7 +135,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
.direction_output = mcf_gpio_direction_output,
.get = mcf_gpio_get_value,
.set = mcf_gpio_set_value_fast,
- .base = 64,
+ .base = 48,
.ngpio = 8,
},
.pddr = (void __iomem *) MCFGPIO_PDDR_FECH,
@@ -189,7 +153,7 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
.direction_output = mcf_gpio_direction_output,
.get = mcf_gpio_get_value,
.set = mcf_gpio_set_value_fast,
- .base = 72,
+ .base = 56,
.ngpio = 8,
},
.pddr = (void __iomem *) MCFGPIO_PDDR_FECL,
diff --git a/arch/m68k/platform/68328/Makefile b/arch/m68k/platform/68328/Makefile
index 5e5435552d56..e4dfd8fde068 100644
--- a/arch/m68k/platform/68328/Makefile
+++ b/arch/m68k/platform/68328/Makefile
@@ -2,7 +2,10 @@
# Makefile for arch/m68knommu/platform/68328.
#
-head-y = head-$(MODEL).o
+model-y := ram
+model-$(CONFIG_ROMKERNEL) := rom
+
+head-y = head-$(model-y).o
head-$(CONFIG_PILOT) = head-pilot.o
head-$(CONFIG_DRAGEN2) = head-de2.o
diff --git a/arch/m68k/platform/68328/entry.S b/arch/m68k/platform/68328/entry.S
index 293e1eba9acc..5c39b80ed7de 100644
--- a/arch/m68k/platform/68328/entry.S
+++ b/arch/m68k/platform/68328/entry.S
@@ -67,7 +67,7 @@ ret_from_signal:
jra ret_from_exception
ENTRY(system_call)
- SAVE_ALL
+ SAVE_ALL_SYS
/* save top of frame*/
pea %sp@
@@ -129,7 +129,7 @@ Lsignal_return:
* This is the main interrupt handler, responsible for calling process_int()
*/
inthandler1:
- SAVE_ALL
+ SAVE_ALL_INT
movew %sp@(PT_OFF_FORMATVEC), %d0
and #0x3ff, %d0
@@ -140,7 +140,7 @@ inthandler1:
bra ret_from_interrupt
inthandler2:
- SAVE_ALL
+ SAVE_ALL_INT
movew %sp@(PT_OFF_FORMATVEC), %d0
and #0x3ff, %d0
@@ -151,7 +151,7 @@ inthandler2:
bra ret_from_interrupt
inthandler3:
- SAVE_ALL
+ SAVE_ALL_INT
movew %sp@(PT_OFF_FORMATVEC), %d0
and #0x3ff, %d0
@@ -162,7 +162,7 @@ inthandler3:
bra ret_from_interrupt
inthandler4:
- SAVE_ALL
+ SAVE_ALL_INT
movew %sp@(PT_OFF_FORMATVEC), %d0
and #0x3ff, %d0
@@ -173,7 +173,7 @@ inthandler4:
bra ret_from_interrupt
inthandler5:
- SAVE_ALL
+ SAVE_ALL_INT
movew %sp@(PT_OFF_FORMATVEC), %d0
and #0x3ff, %d0
@@ -184,7 +184,7 @@ inthandler5:
bra ret_from_interrupt
inthandler6:
- SAVE_ALL
+ SAVE_ALL_INT
movew %sp@(PT_OFF_FORMATVEC), %d0
and #0x3ff, %d0
@@ -195,7 +195,7 @@ inthandler6:
bra ret_from_interrupt
inthandler7:
- SAVE_ALL
+ SAVE_ALL_INT
movew %sp@(PT_OFF_FORMATVEC), %d0
and #0x3ff, %d0
@@ -206,7 +206,7 @@ inthandler7:
bra ret_from_interrupt
inthandler:
- SAVE_ALL
+ SAVE_ALL_INT
movew %sp@(PT_OFF_FORMATVEC), %d0
and #0x3ff, %d0
diff --git a/arch/m68k/platform/68360/Makefile b/arch/m68k/platform/68360/Makefile
index cf5af73a5789..f6f434383049 100644
--- a/arch/m68k/platform/68360/Makefile
+++ b/arch/m68k/platform/68360/Makefile
@@ -1,10 +1,12 @@
#
# Makefile for arch/m68knommu/platform/68360.
#
+model-y := ram
+model-$(CONFIG_ROMKERNEL) := rom
obj-y := config.o commproc.o entry.o ints.o
extra-y := head.o
-$(obj)/head.o: $(obj)/head-$(MODEL).o
- ln -sf head-$(MODEL).o $(obj)/head.o
+$(obj)/head.o: $(obj)/head-$(model-y).o
+ ln -sf head-$(model-y).o $(obj)/head.o
diff --git a/arch/m68k/platform/68360/entry.S b/arch/m68k/platform/68360/entry.S
index abbb89672ea0..aa47d1d49929 100644
--- a/arch/m68k/platform/68360/entry.S
+++ b/arch/m68k/platform/68360/entry.S
@@ -63,7 +63,7 @@ ret_from_signal:
jra ret_from_exception
ENTRY(system_call)
- SAVE_ALL
+ SAVE_ALL_SYS
/* save top of frame*/
pea %sp@
@@ -125,7 +125,7 @@ Lsignal_return:
* This is the main interrupt handler, responsible for calling do_IRQ()
*/
inthandler:
- SAVE_ALL
+ SAVE_ALL_INT
movew %sp@(PT_OFF_FORMATVEC), %d0
and.l #0x3ff, %d0
lsr.l #0x02, %d0
diff --git a/arch/m68k/platform/coldfire/entry.S b/arch/m68k/platform/coldfire/entry.S
index bd27242c2f43..3157461a8d1d 100644
--- a/arch/m68k/platform/coldfire/entry.S
+++ b/arch/m68k/platform/coldfire/entry.S
@@ -61,7 +61,7 @@ enosys:
bra 1f
ENTRY(system_call)
- SAVE_ALL
+ SAVE_ALL_SYS
move #0x2000,%sr /* enable intrs again */
cmpl #NR_syscalls,%d0
@@ -165,9 +165,7 @@ Lsignal_return:
* sources). Calls up to high level code to do all the work.
*/
ENTRY(inthandler)
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(PT_OFF_ORIG_D0)
+ SAVE_ALL_INT
movew %sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */
andl #0x03fc,%d0 /* mask out vector only */
diff --git a/arch/m68k/q40/README b/arch/m68k/q40/README
index b26d5f55e91d..93f4c4cd3c45 100644
--- a/arch/m68k/q40/README
+++ b/arch/m68k/q40/README
@@ -31,7 +31,7 @@ drivers used by the Q40, apart from the very obvious (console etc.):
char/joystick/* # most of this should work, not
# in default config.in
block/q40ide.c # startup for ide
- ide* # see Documentation/ide.txt
+ ide* # see Documentation/ide/ide.txt
floppy.c # normal PC driver, DMA emu in asm/floppy.h
# and arch/m68k/kernel/entry.S
# see drivers/block/README.fd
diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h
index 8fbb0ec10233..3a3e5b886854 100644
--- a/arch/microblaze/include/asm/dma-mapping.h
+++ b/arch/microblaze/include/asm/dma-mapping.h
@@ -16,7 +16,7 @@
#define _ASM_MICROBLAZE_DMA_MAPPING_H
/*
- * See Documentation/PCI/PCI-DMA-mapping.txt and
+ * See Documentation/DMA-API-HOWTO.txt and
* Documentation/DMA-API.txt for documentation.
*/
@@ -28,12 +28,12 @@
#include <linux/dma-attrs.h>
#include <asm/io.h>
#include <asm-generic/dma-coherent.h>
+#include <asm/cacheflush.h>
#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
#define __dma_alloc_coherent(dev, gfp, size, handle) NULL
#define __dma_free_coherent(size, addr) ((void)0)
-#define __dma_sync(addr, size, rw) ((void)0)
static inline unsigned long device_to_mask(struct device *dev)
{
@@ -95,6 +95,22 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
#include <asm-generic/dma-mapping-common.h>
+static inline void __dma_sync(unsigned long paddr,
+ size_t size, enum dma_data_direction direction)
+{
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ case DMA_BIDIRECTIONAL:
+ flush_dcache_range(paddr, paddr + size);
+ break;
+ case DMA_FROM_DEVICE:
+ invalidate_dcache_range(paddr, paddr + size);
+ break;
+ default:
+ BUG();
+ }
+}
+
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
struct dma_map_ops *ops = get_dma_ops(dev);
@@ -135,7 +151,7 @@ static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction)
{
BUG_ON(direction == DMA_NONE);
- __dma_sync(vaddr, size, (int)direction);
+ __dma_sync(virt_to_phys(vaddr), size, (int)direction);
}
#endif /* _ASM_MICROBLAZE_DMA_MAPPING_H */
diff --git a/arch/microblaze/include/asm/elf.h b/arch/microblaze/include/asm/elf.h
index 098dfdde4b06..834849f59ae8 100644
--- a/arch/microblaze/include/asm/elf.h
+++ b/arch/microblaze/include/asm/elf.h
@@ -16,13 +16,15 @@
* I've snaffled the value from the microblaze binutils source code
* /binutils/microblaze/include/elf/microblaze.h
*/
-#define EM_XILINX_MICROBLAZE 0xbaab
-#define ELF_ARCH EM_XILINX_MICROBLAZE
+#define EM_MICROBLAZE 189
+#define EM_MICROBLAZE_OLD 0xbaab
+#define ELF_ARCH EM_MICROBLAZE
/*
* This is used to ensure we don't load something for the wrong architecture.
*/
-#define elf_check_arch(x) ((x)->e_machine == EM_XILINX_MICROBLAZE)
+#define elf_check_arch(x) ((x)->e_machine == EM_MICROBLAZE \
+ || (x)->e_machine == EM_MICROBLAZE_OLD)
/*
* These are used to set parameters in the core dumps.
diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h
index e6a2284571dc..5a433cbaafb3 100644
--- a/arch/microblaze/include/asm/system.h
+++ b/arch/microblaze/include/asm/system.h
@@ -17,8 +17,6 @@
#include <asm-generic/cmpxchg.h>
#include <asm-generic/cmpxchg-local.h>
-#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
-
struct task_struct;
struct thread_info;
@@ -96,11 +94,4 @@ extern struct dentry *of_debugfs_root;
#define arch_align_stack(x) (x)
-/*
- * MicroBlaze doesn't handle unaligned accesses in hardware.
- *
- * Based on this we force the IP header alignment in network drivers.
- */
-#define NET_IP_ALIGN 2
-
#endif /* _ASM_MICROBLAZE_SYSTEM_H */
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index 5bb95a11880d..072b0077abf9 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -95,7 +95,7 @@ static inline int ___range_ok(unsigned long addr, unsigned long size)
* - "addr", "addr + size" and "size" are all below the limit
*/
#define access_ok(type, addr, size) \
- (get_fs().seg > (((unsigned long)(addr)) | \
+ (get_fs().seg >= (((unsigned long)(addr)) | \
(size) | ((unsigned long)(addr) + (size))))
/* || printk("access_ok failed for %s at 0x%08lx (size %d), seg 0x%08x\n",
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c
index 44394d80a683..54194b28574a 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo.c
@@ -34,6 +34,7 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
{"8.00.a", 0x12},
{"8.00.b", 0x13},
{"8.10.a", 0x14},
+ {"8.20.a", 0x15},
{NULL, 0},
};
diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
index 393e6b2db688..dc6416d265d6 100644
--- a/arch/microblaze/kernel/dma.c
+++ b/arch/microblaze/kernel/dma.c
@@ -11,7 +11,6 @@
#include <linux/gfp.h>
#include <linux/dma-debug.h>
#include <asm/bug.h>
-#include <asm/cacheflush.h>
/*
* Generic direct DMA implementation
@@ -21,21 +20,6 @@
* can set archdata.dma_data to an unsigned long holding the offset. By
* default the offset is PCI_DRAM_OFFSET.
*/
-static inline void __dma_sync_page(unsigned long paddr, unsigned long offset,
- size_t size, enum dma_data_direction direction)
-{
- switch (direction) {
- case DMA_TO_DEVICE:
- case DMA_BIDIRECTIONAL:
- flush_dcache_range(paddr + offset, paddr + offset + size);
- break;
- case DMA_FROM_DEVICE:
- invalidate_dcache_range(paddr + offset, paddr + offset + size);
- break;
- default:
- BUG();
- }
-}
static unsigned long get_dma_direct_offset(struct device *dev)
{
@@ -91,7 +75,7 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
/* FIXME this part of code is untested */
for_each_sg(sgl, sg, nents, i) {
sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev);
- __dma_sync_page(page_to_phys(sg_page(sg)), sg->offset,
+ __dma_sync(page_to_phys(sg_page(sg)) + sg->offset,
sg->length, direction);
}
@@ -116,7 +100,7 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev,
enum dma_data_direction direction,
struct dma_attrs *attrs)
{
- __dma_sync_page(page_to_phys(page), offset, size, direction);
+ __dma_sync(page_to_phys(page) + offset, size, direction);
return page_to_phys(page) + offset + get_dma_direct_offset(dev);
}
@@ -131,7 +115,63 @@ static inline void dma_direct_unmap_page(struct device *dev,
* phys_to_virt is here because in __dma_sync_page is __virt_to_phys and
* dma_address is physical address
*/
- __dma_sync_page(dma_address, 0 , size, direction);
+ __dma_sync(dma_address, size, direction);
+}
+
+static inline void
+dma_direct_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ /*
+ * It's pointless to flush the cache as the memory segment
+ * is given to the CPU
+ */
+
+ if (direction == DMA_FROM_DEVICE)
+ __dma_sync(dma_handle, size, direction);
+}
+
+static inline void
+dma_direct_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ /*
+ * It's pointless to invalidate the cache if the device isn't
+ * supposed to write to the relevant region
+ */
+
+ if (direction == DMA_TO_DEVICE)
+ __dma_sync(dma_handle, size, direction);
+}
+
+static inline void
+dma_direct_sync_sg_for_cpu(struct device *dev,
+ struct scatterlist *sgl, int nents,
+ enum dma_data_direction direction)
+{
+ struct scatterlist *sg;
+ int i;
+
+ /* FIXME this part of code is untested */
+ if (direction == DMA_FROM_DEVICE)
+ for_each_sg(sgl, sg, nents, i)
+ __dma_sync(sg->dma_address, sg->length, direction);
+}
+
+static inline void
+dma_direct_sync_sg_for_device(struct device *dev,
+ struct scatterlist *sgl, int nents,
+ enum dma_data_direction direction)
+{
+ struct scatterlist *sg;
+ int i;
+
+ /* FIXME this part of code is untested */
+ if (direction == DMA_TO_DEVICE)
+ for_each_sg(sgl, sg, nents, i)
+ __dma_sync(sg->dma_address, sg->length, direction);
}
struct dma_map_ops dma_direct_ops = {
@@ -142,6 +182,10 @@ struct dma_map_ops dma_direct_ops = {
.dma_supported = dma_direct_dma_supported,
.map_page = dma_direct_map_page,
.unmap_page = dma_direct_unmap_page,
+ .sync_single_for_cpu = dma_direct_sync_single_for_cpu,
+ .sync_single_for_device = dma_direct_sync_single_for_device,
+ .sync_sg_for_cpu = dma_direct_sync_sg_for_cpu,
+ .sync_sg_for_device = dma_direct_sync_sg_for_device,
};
EXPORT_SYMBOL(dma_direct_ops);
diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c
index 66fad2301221..6348dc82f428 100644
--- a/arch/microblaze/kernel/exceptions.c
+++ b/arch/microblaze/kernel/exceptions.c
@@ -119,7 +119,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
case MICROBLAZE_DIV_ZERO_EXCEPTION:
if (user_mode(regs)) {
pr_debug("Divide by zero exception in user mode\n");
- _exception(SIGILL, regs, FPE_INTDIV, addr);
+ _exception(SIGFPE, regs, FPE_INTDIV, addr);
return;
}
printk(KERN_WARNING "Divide by zero exception " \
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index dbb812421d8a..95cc295976a7 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -179,6 +179,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
ti->cpu_context.msr = (childregs->msr|MSR_VM);
ti->cpu_context.msr &= ~MSR_UMS; /* switch_to to kernel mode */
+ ti->cpu_context.msr &= ~MSR_IE;
#endif
ti->cpu_context.r15 = (unsigned long)ret_from_fork - 8;
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index 6a8e0cc5c57d..043cb58f9c44 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -148,7 +148,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
ret = -1L;
if (unlikely(current->audit_context))
- audit_syscall_entry(EM_XILINX_MICROBLAZE, regs->r12,
+ audit_syscall_entry(EM_MICROBLAZE, regs->r12,
regs->r5, regs->r6,
regs->r7, regs->r8);
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index e5550ce4e0eb..af74b1113aab 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -308,7 +308,8 @@ unsigned long long notrace sched_clock(void)
{
if (timer_initialized) {
struct clocksource *cs = &clocksource_microblaze;
- cycle_t cyc = cnt32_to_63(cs->read(NULL));
+
+ cycle_t cyc = cnt32_to_63(cs->read(NULL)) & LLONG_MAX;
return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
}
return 0;
diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile
index 10c320aa908b..c13067b243c3 100644
--- a/arch/microblaze/lib/Makefile
+++ b/arch/microblaze/lib/Makefile
@@ -25,5 +25,6 @@ lib-y += lshrdi3.o
lib-y += modsi3.o
lib-y += muldi3.o
lib-y += mulsi3.o
+lib-y += ucmpdi2.o
lib-y += udivsi3.o
lib-y += umodsi3.o
diff --git a/arch/microblaze/lib/uaccess_old.S b/arch/microblaze/lib/uaccess_old.S
index 5810cec54a7a..f037266cdaf3 100644
--- a/arch/microblaze/lib/uaccess_old.S
+++ b/arch/microblaze/lib/uaccess_old.S
@@ -10,6 +10,7 @@
#include <linux/errno.h>
#include <linux/linkage.h>
+#include <asm/page.h>
/*
* int __strncpy_user(char *to, char *from, int len);
@@ -33,8 +34,8 @@ __strncpy_user:
* r3 - temp count
* r4 - temp val
*/
+ beqid r7,3f
addik r3,r7,0 /* temp_count = len */
- beqi r3,3f
1:
lbu r4,r6,r0
sb r4,r5,r0
@@ -76,8 +77,8 @@ __strncpy_user:
.type __strnlen_user, @function
.align 4;
__strnlen_user:
+ beqid r6,3f
addik r3,r6,0
- beqi r3,3f
1:
lbu r4,r5,r0
beqid r4,2f /* break on NUL */
@@ -102,6 +103,49 @@ __strnlen_user:
.section __ex_table,"a"
.word 1b,4b
+/* Loop unrolling for __copy_tofrom_user */
+#define COPY(offset) \
+1: lwi r4 , r6, 0x0000 + offset; \
+2: lwi r19, r6, 0x0004 + offset; \
+3: lwi r20, r6, 0x0008 + offset; \
+4: lwi r21, r6, 0x000C + offset; \
+5: lwi r22, r6, 0x0010 + offset; \
+6: lwi r23, r6, 0x0014 + offset; \
+7: lwi r24, r6, 0x0018 + offset; \
+8: lwi r25, r6, 0x001C + offset; \
+9: swi r4 , r5, 0x0000 + offset; \
+10: swi r19, r5, 0x0004 + offset; \
+11: swi r20, r5, 0x0008 + offset; \
+12: swi r21, r5, 0x000C + offset; \
+13: swi r22, r5, 0x0010 + offset; \
+14: swi r23, r5, 0x0014 + offset; \
+15: swi r24, r5, 0x0018 + offset; \
+16: swi r25, r5, 0x001C + offset; \
+ .section __ex_table,"a"; \
+ .word 1b, 0f; \
+ .word 2b, 0f; \
+ .word 3b, 0f; \
+ .word 4b, 0f; \
+ .word 5b, 0f; \
+ .word 6b, 0f; \
+ .word 7b, 0f; \
+ .word 8b, 0f; \
+ .word 9b, 0f; \
+ .word 10b, 0f; \
+ .word 11b, 0f; \
+ .word 12b, 0f; \
+ .word 13b, 0f; \
+ .word 14b, 0f; \
+ .word 15b, 0f; \
+ .word 16b, 0f; \
+ .text
+
+#define COPY_80(offset) \
+ COPY(0x00 + offset);\
+ COPY(0x20 + offset);\
+ COPY(0x40 + offset);\
+ COPY(0x60 + offset);
+
/*
* int __copy_tofrom_user(char *to, char *from, int len)
* Return:
@@ -119,34 +163,79 @@ __copy_tofrom_user:
* r7, r3 - count
* r4 - tempval
*/
- beqid r7, 3f /* zero size is not likely */
- andi r3, r7, 0x3 /* filter add count */
- bneid r3, 4f /* if is odd value then byte copying */
+ beqid r7, 0f /* zero size is not likely */
or r3, r5, r6 /* find if is any to/from unaligned */
- andi r3, r3, 0x3 /* mask unaligned */
- bneid r3, 1f /* it is unaligned -> then jump */
+ or r3, r3, r7 /* find if count is unaligned */
+ andi r3, r3, 0x3 /* mask last 3 bits */
+ bneid r3, bu1 /* if r3 is not zero then byte copying */
+ or r3, r0, r0
+
+ rsubi r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
+ beqid r3, page;
or r3, r0, r0
-/* at least one 4 byte copy */
-5: lw r4, r6, r3
-6: sw r4, r5, r3
+w1: lw r4, r6, r3 /* at least one 4 byte copy */
+w2: sw r4, r5, r3
addik r7, r7, -4
- bneid r7, 5b
+ bneid r7, w1
addik r3, r3, 4
addik r3, r7, 0
rtsd r15, 8
nop
-4: or r3, r0, r0
-1: lbu r4,r6,r3
-2: sb r4,r5,r3
+
+ .section __ex_table,"a"
+ .word w1, 0f;
+ .word w2, 0f;
+ .text
+
+.align 4 /* Alignment is important to keep icache happy */
+page: /* Create room on stack and save registers for storign values */
+ addik r1, r1, -32
+ swi r19, r1, 4
+ swi r20, r1, 8
+ swi r21, r1, 12
+ swi r22, r1, 16
+ swi r23, r1, 20
+ swi r24, r1, 24
+ swi r25, r1, 28
+loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
+ /* Loop unrolling to get performance boost */
+ COPY_80(0x000);
+ COPY_80(0x080);
+ COPY_80(0x100);
+ COPY_80(0x180);
+ /* copy loop */
+ addik r6, r6, 0x200
+ addik r7, r7, -0x200
+ bneid r7, loop
+ addik r5, r5, 0x200
+ /* Restore register content */
+ lwi r19, r1, 4
+ lwi r20, r1, 8
+ lwi r21, r1, 12
+ lwi r22, r1, 16
+ lwi r23, r1, 20
+ lwi r24, r1, 24
+ lwi r25, r1, 28
+ addik r1, r1, 32
+ /* return back */
+ addik r3, r7, 0
+ rtsd r15, 8
+ nop
+
+.align 4 /* Alignment is important to keep icache happy */
+bu1: lbu r4,r6,r3
+bu2: sb r4,r5,r3
addik r7,r7,-1
- bneid r7,1b
+ bneid r7,bu1
addik r3,r3,1 /* delay slot */
-3:
+0:
addik r3,r7,0
rtsd r15,8
nop
.size __copy_tofrom_user, . - __copy_tofrom_user
.section __ex_table,"a"
- .word 1b,3b,2b,3b,5b,3b,6b,3b
+ .word bu1, 0b;
+ .word bu2, 0b;
+ .text
diff --git a/arch/microblaze/lib/ucmpdi2.c b/arch/microblaze/lib/ucmpdi2.c
new file mode 100644
index 000000000000..63ca105b6713
--- /dev/null
+++ b/arch/microblaze/lib/ucmpdi2.c
@@ -0,0 +1,20 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+word_type __ucmpdi2(unsigned long long a, unsigned long long b)
+{
+ const DWunion au = {.ll = a};
+ const DWunion bu = {.ll = b};
+
+ if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
+ return 0;
+ else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
+ return 2;
+ if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
+ return 0;
+ else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
+ return 2;
+ return 1;
+}
+EXPORT_SYMBOL(__ucmpdi2);
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c
index 213f2d671669..36a133e5ee35 100644
--- a/arch/microblaze/mm/init.c
+++ b/arch/microblaze/mm/init.c
@@ -304,11 +304,11 @@ asmlinkage void __init mmu_init(void)
/* Map in all of RAM starting at CONFIG_KERNEL_START */
mapin_ram();
-#ifdef HIGHMEM_START_BOOL
- ioremap_base = HIGHMEM_START;
+#ifdef CONFIG_HIGHMEM_START_BOOL
+ ioremap_base = CONFIG_HIGHMEM_START;
#else
ioremap_base = 0xfe000000UL; /* for now, could be 0xfffff000 */
-#endif /* CONFIG_HIGHMEM */
+#endif /* CONFIG_HIGHMEM_START_BOOL */
ioremap_bot = ioremap_base;
/* Initialize the context management stuff */
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b122adc8bdbb..4cbc6d8de210 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -92,15 +92,8 @@ config BCM47XX
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
- select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
- select SSB
- select SSB_DRIVER_MIPS
- select SSB_DRIVER_EXTIF
- select SSB_EMBEDDED
- select SSB_B43_PCI_BRIDGE if PCI
- select SSB_PCICORE_HOSTMODE if PCI
select GENERIC_GPIO
select SYS_HAS_EARLY_PRINTK
select CFE
@@ -791,6 +784,7 @@ endchoice
source "arch/mips/alchemy/Kconfig"
source "arch/mips/ath79/Kconfig"
+source "arch/mips/bcm47xx/Kconfig"
source "arch/mips/bcm63xx/Kconfig"
source "arch/mips/jazz/Kconfig"
source "arch/mips/jz4740/Kconfig"
diff --git a/arch/mips/alchemy/devboards/db1200/platform.c b/arch/mips/alchemy/devboards/db1200/platform.c
index fbb55935b99e..dda090bf74e6 100644
--- a/arch/mips/alchemy/devboards/db1200/platform.c
+++ b/arch/mips/alchemy/devboards/db1200/platform.c
@@ -422,6 +422,7 @@ static struct resource au1200_psc1_res[] = {
},
};
+/* AC97 or I2S device */
static struct platform_device db1200_audio_dev = {
/* name assigned later based on switch setting */
.id = 1, /* PSC ID */
@@ -429,19 +430,32 @@ static struct platform_device db1200_audio_dev = {
.resource = au1200_psc1_res,
};
+/* DB1200 ASoC card device */
+static struct platform_device db1200_sound_dev = {
+ /* name assigned later based on switch setting */
+ .id = 1, /* PSC ID */
+};
+
static struct platform_device db1200_stac_dev = {
.name = "ac97-codec",
.id = 1, /* on PSC1 */
};
+static struct platform_device db1200_audiodma_dev = {
+ .name = "au1xpsc-pcm",
+ .id = 1, /* PSC ID */
+};
+
static struct platform_device *db1200_devs[] __initdata = {
NULL, /* PSC0, selected by S6.8 */
&db1200_ide_dev,
&db1200_eth_dev,
&db1200_rtc_dev,
&db1200_nand_dev,
+ &db1200_audiodma_dev,
&db1200_audio_dev,
&db1200_stac_dev,
+ &db1200_sound_dev,
};
static int __init db1200_dev_init(void)
@@ -501,10 +515,12 @@ static int __init db1200_dev_init(void)
if (sw == BCSR_SWITCHES_DIP_8) {
bcsr_mod(BCSR_RESETS, 0, BCSR_RESETS_PSC1MUX);
db1200_audio_dev.name = "au1xpsc_i2s";
+ db1200_sound_dev.name = "db1200-i2s";
printk(KERN_INFO " S6.7 ON : PSC1 mode I2S\n");
} else {
bcsr_mod(BCSR_RESETS, BCSR_RESETS_PSC1MUX, 0);
db1200_audio_dev.name = "au1xpsc_ac97";
+ db1200_sound_dev.name = "db1200-ac97";
printk(KERN_INFO " S6.7 OFF: PSC1 mode AC97\n");
}
diff --git a/arch/mips/alchemy/devboards/db1x00/platform.c b/arch/mips/alchemy/devboards/db1x00/platform.c
index 978d5ab3d678..7057d28f7301 100644
--- a/arch/mips/alchemy/devboards/db1x00/platform.c
+++ b/arch/mips/alchemy/devboards/db1x00/platform.c
@@ -19,8 +19,11 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1000_dma.h>
#include <asm/mach-au1x00/au1xxx.h>
#include <asm/mach-db1x00/bcsr.h>
#include "../platform.h"
@@ -85,6 +88,45 @@
#endif
#endif
+static struct resource alchemy_ac97c_res[] = {
+ [0] = {
+ .start = AU1000_AC97_PHYS_ADDR,
+ .end = AU1000_AC97_PHYS_ADDR + 0xfff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DMA_ID_AC97C_TX,
+ .end = DMA_ID_AC97C_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .start = DMA_ID_AC97C_RX,
+ .end = DMA_ID_AC97C_RX,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device alchemy_ac97c_dev = {
+ .name = "alchemy-ac97c",
+ .id = -1,
+ .resource = alchemy_ac97c_res,
+ .num_resources = ARRAY_SIZE(alchemy_ac97c_res),
+};
+
+static struct platform_device alchemy_ac97c_dma_dev = {
+ .name = "alchemy-pcm-dma",
+ .id = 0,
+};
+
+static struct platform_device db1x00_codec_dev = {
+ .name = "ac97-codec",
+ .id = -1,
+};
+
+static struct platform_device db1x00_audio_dev = {
+ .name = "db1000-audio",
+};
+
static int __init db1xxx_dev_init(void)
{
#ifdef DB1XXX_HAS_PCMCIA
@@ -113,6 +155,12 @@ static int __init db1xxx_dev_init(void)
1);
#endif
db1x_register_norflash(BOARD_FLASH_SIZE, BOARD_FLASH_WIDTH, F_SWAPPED);
+
+ platform_device_register(&db1x00_codec_dev);
+ platform_device_register(&alchemy_ac97c_dma_dev);
+ platform_device_register(&alchemy_ac97c_dev);
+ platform_device_register(&db1x00_audio_dev);
+
return 0;
}
device_initcall(db1xxx_dev_init);
diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig
new file mode 100644
index 000000000000..6210b8d84109
--- /dev/null
+++ b/arch/mips/bcm47xx/Kconfig
@@ -0,0 +1,31 @@
+if BCM47XX
+
+config BCM47XX_SSB
+ bool "SSB Support for Broadcom BCM47XX"
+ select SYS_HAS_CPU_MIPS32_R1
+ select SSB
+ select SSB_DRIVER_MIPS
+ select SSB_DRIVER_EXTIF
+ select SSB_EMBEDDED
+ select SSB_B43_PCI_BRIDGE if PCI
+ select SSB_PCICORE_HOSTMODE if PCI
+ default y
+ help
+ Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
+
+ This will generate an image with support for SSB and MIPS32 R1 instruction set.
+
+config BCM47XX_BCMA
+ bool "BCMA Support for Broadcom BCM47XX"
+ select SYS_HAS_CPU_MIPS32_R2
+ select BCMA
+ select BCMA_HOST_SOC
+ select BCMA_DRIVER_MIPS
+ select BCMA_DRIVER_PCI_HOSTMODE if PCI
+ default y
+ help
+ Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
+
+ This will generate an image with support for BCMA and MIPS32 R2 instruction set.
+
+endif
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index 7465e8a72d9a..4add17349ff9 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,4 +3,5 @@
# under Linux.
#
-obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
+obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
diff --git a/arch/mips/bcm47xx/gpio.c b/arch/mips/bcm47xx/gpio.c
index e4a5ee9c9721..57b425fd4d41 100644
--- a/arch/mips/bcm47xx/gpio.c
+++ b/arch/mips/bcm47xx/gpio.c
@@ -20,42 +20,82 @@ static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES);
int gpio_request(unsigned gpio, const char *tag)
{
- if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
- ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
- return -EINVAL;
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
+ ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+ return -EINVAL;
- if (ssb_extif_available(&ssb_bcm47xx.extif) &&
- ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
- return -EINVAL;
+ if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
+ ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+ return -EINVAL;
- if (test_and_set_bit(gpio, gpio_in_use))
- return -EBUSY;
+ if (test_and_set_bit(gpio, gpio_in_use))
+ return -EBUSY;
- return 0;
+ return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
+ return -EINVAL;
+
+ if (test_and_set_bit(gpio, gpio_in_use))
+ return -EBUSY;
+
+ return 0;
+#endif
+ }
+ return -EINVAL;
}
EXPORT_SYMBOL(gpio_request);
void gpio_free(unsigned gpio)
{
- if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
- ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
- return;
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
+ ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+ return;
+
+ if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
+ ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+ return;
- if (ssb_extif_available(&ssb_bcm47xx.extif) &&
- ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+ clear_bit(gpio, gpio_in_use);
return;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
+ return;
- clear_bit(gpio, gpio_in_use);
+ clear_bit(gpio, gpio_in_use);
+ return;
+#endif
+ }
}
EXPORT_SYMBOL(gpio_free);
int gpio_to_irq(unsigned gpio)
{
- if (ssb_chipco_available(&ssb_bcm47xx.chipco))
- return ssb_mips_irq(ssb_bcm47xx.chipco.dev) + 2;
- else if (ssb_extif_available(&ssb_bcm47xx.extif))
- return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2;
- else
- return -EINVAL;
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
+ return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
+ else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
+ return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
+ else
+ return -EINVAL;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
+#endif
+ }
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(gpio_to_irq);
diff --git a/arch/mips/bcm47xx/irq.c b/arch/mips/bcm47xx/irq.c
index 325757acd020..8cf3833b2d29 100644
--- a/arch/mips/bcm47xx/irq.c
+++ b/arch/mips/bcm47xx/irq.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/irq_cpu.h>
+#include <bcm47xx.h>
void plat_irq_dispatch(void)
{
@@ -51,5 +52,16 @@ void plat_irq_dispatch(void)
void __init arch_init_irq(void)
{
+#ifdef CONFIG_BCM47XX_BCMA
+ if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) {
+ bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core,
+ BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31);
+ /*
+ * the kernel reads the timer irq from some register and thinks
+ * it's #5, but we offset it by 2 and route to #7
+ */
+ cp0_compare_irq = 7;
+ }
+#endif
mips_cpu_irq_init();
}
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
index 54db815bc86c..a84e3bb7387f 100644
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -26,14 +26,35 @@ static char nvram_buf[NVRAM_SPACE];
/* Probe for NVRAM header */
static void early_nvram_init(void)
{
- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+#ifdef CONFIG_BCM47XX_SSB
+ struct ssb_mipscore *mcore_ssb;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ struct bcma_drv_cc *bcma_cc;
+#endif
struct nvram_header *header;
int i;
- u32 base, lim, off;
+ u32 base = 0;
+ u32 lim = 0;
+ u32 off;
u32 *src, *dst;
- base = mcore->flash_window;
- lim = mcore->flash_window_size;
+ switch (bcm47xx_bus_type) {
+#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;
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
+ base = bcma_cc->pflash.window;
+ lim = bcma_cc->pflash.window_size;
+ break;
+#endif
+ }
off = FLASH_MIN;
while (off <= lim) {
diff --git a/arch/mips/bcm47xx/serial.c b/arch/mips/bcm47xx/serial.c
index 59c11afdb2ab..57981e4fe2bc 100644
--- a/arch/mips/bcm47xx/serial.c
+++ b/arch/mips/bcm47xx/serial.c
@@ -23,10 +23,11 @@ static struct platform_device uart8250_device = {
},
};
-static int __init uart8250_init(void)
+#ifdef CONFIG_BCM47XX_SSB
+static int __init uart8250_init_ssb(void)
{
int i;
- struct ssb_mipscore *mcore = &(ssb_bcm47xx.mipscore);
+ struct ssb_mipscore *mcore = &(bcm47xx_bus.ssb.mipscore);
memset(&uart8250_data, 0, sizeof(uart8250_data));
@@ -44,6 +45,47 @@ static int __init uart8250_init(void)
}
return platform_device_register(&uart8250_device);
}
+#endif
+
+#ifdef CONFIG_BCM47XX_BCMA
+static int __init uart8250_init_bcma(void)
+{
+ int i;
+ struct bcma_drv_cc *cc = &(bcm47xx_bus.bcma.bus.drv_cc);
+
+ memset(&uart8250_data, 0, sizeof(uart8250_data));
+
+ for (i = 0; i < cc->nr_serial_ports; i++) {
+ struct plat_serial8250_port *p = &(uart8250_data[i]);
+ struct bcma_serial_port *bcma_port;
+ bcma_port = &(cc->serial_ports[i]);
+
+ p->mapbase = (unsigned int) bcma_port->regs;
+ p->membase = (void *) bcma_port->regs;
+ p->irq = bcma_port->irq + 2;
+ p->uartclk = bcma_port->baud_base;
+ p->regshift = bcma_port->reg_shift;
+ p->iotype = UPIO_MEM;
+ p->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ }
+ return platform_device_register(&uart8250_device);
+}
+#endif
+
+static int __init uart8250_init(void)
+{
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ return uart8250_init_ssb();
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return uart8250_init_bcma();
+#endif
+ }
+ return -EINVAL;
+}
module_init(uart8250_init);
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index cfae81571ded..17c3d14d7c49 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -29,21 +29,36 @@
#include <linux/types.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
+#include <linux/bcma/bcma_soc.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
#include <bcm47xx.h>
#include <asm/mach-bcm47xx/nvram.h>
-struct ssb_bus ssb_bcm47xx;
-EXPORT_SYMBOL(ssb_bcm47xx);
+union bcm47xx_bus bcm47xx_bus;
+EXPORT_SYMBOL(bcm47xx_bus);
+
+enum bcm47xx_bus_type bcm47xx_bus_type;
+EXPORT_SYMBOL(bcm47xx_bus_type);
static void bcm47xx_machine_restart(char *command)
{
printk(KERN_ALERT "Please stand by while rebooting the system...\n");
local_irq_disable();
/* Set the watchdog timer to reset immediately */
- ssb_watchdog_timer_set(&ssb_bcm47xx, 1);
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
+ break;
+#endif
+ }
while (1)
cpu_relax();
}
@@ -52,11 +67,23 @@ static void bcm47xx_machine_halt(void)
{
/* Disable interrupts and watchdog and spin forever */
local_irq_disable();
- ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0);
+ break;
+#endif
+ }
while (1)
cpu_relax();
}
+#ifdef CONFIG_BCM47XX_SSB
#define READ_FROM_NVRAM(_outvar, name, buf) \
if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
sprom->_outvar = simple_strtoul(buf, NULL, 0);
@@ -247,7 +274,7 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
return 0;
}
-void __init plat_mem_setup(void)
+static void __init bcm47xx_register_ssb(void)
{
int err;
char buf[100];
@@ -258,12 +285,12 @@ void __init plat_mem_setup(void)
printk(KERN_WARNING "bcm47xx: someone else already registered"
" a ssb SPROM callback handler (err %d)\n", err);
- err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
+ err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE,
bcm47xx_get_invariants);
if (err)
panic("Failed to initialize SSB bus (err %d)\n", err);
- mcore = &ssb_bcm47xx.mipscore;
+ mcore = &bcm47xx_bus.ssb.mipscore;
if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
if (strstr(buf, "console=ttyS1")) {
struct ssb_serial_port port;
@@ -276,8 +303,57 @@ void __init plat_mem_setup(void)
memcpy(&mcore->serial_ports[1], &port, sizeof(port));
}
}
+}
+#endif
+
+#ifdef CONFIG_BCM47XX_BCMA
+static void __init bcm47xx_register_bcma(void)
+{
+ int err;
+
+ err = bcma_host_soc_register(&bcm47xx_bus.bcma);
+ if (err)
+ panic("Failed to initialize BCMA bus (err %d)\n", err);
+}
+#endif
+
+void __init plat_mem_setup(void)
+{
+ struct cpuinfo_mips *c = &current_cpu_data;
+
+ if (c->cputype == CPU_74K) {
+ printk(KERN_INFO "bcm47xx: using bcma bus\n");
+#ifdef CONFIG_BCM47XX_BCMA
+ bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
+ bcm47xx_register_bcma();
+#endif
+ } else {
+ printk(KERN_INFO "bcm47xx: using ssb bus\n");
+#ifdef CONFIG_BCM47XX_SSB
+ bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB;
+ bcm47xx_register_ssb();
+#endif
+ }
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt;
}
+
+static int __init bcm47xx_register_bus_complete(void)
+{
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ /* Nothing to do */
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_bus_register(&bcm47xx_bus.bcma.bus);
+ break;
+#endif
+ }
+ return 0;
+}
+device_initcall(bcm47xx_register_bus_complete);
diff --git a/arch/mips/bcm47xx/time.c b/arch/mips/bcm47xx/time.c
index 0c6f47b3fd94..536374dcba78 100644
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -30,7 +30,7 @@
void __init plat_time_init(void)
{
- unsigned long hz;
+ unsigned long hz = 0;
/*
* Use deterministic values for initial counter interrupt
@@ -39,7 +39,19 @@ void __init plat_time_init(void)
write_c0_count(0);
write_c0_compare(0xffff);
- hz = ssb_cpu_clock(&ssb_bcm47xx.mipscore) / 2;
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2;
+ break;
+#endif
+ }
+
if (!hz)
hz = 100000000;
diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c
index 74d06965326f..e9f9ec8d443b 100644
--- a/arch/mips/bcm47xx/wgt634u.c
+++ b/arch/mips/bcm47xx/wgt634u.c
@@ -108,7 +108,7 @@ static irqreturn_t gpio_interrupt(int irq, void *ignored)
/* Interrupts are shared, check if the current one is
a GPIO interrupt. */
- if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco,
+ if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco,
SSB_CHIPCO_IRQ_GPIO))
return IRQ_NONE;
@@ -132,22 +132,26 @@ static int __init wgt634u_init(void)
* machine. Use the MAC address as an heuristic. Netgear Inc. has
* been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
*/
+ u8 *et0mac;
- u8 *et0mac = ssb_bcm47xx.sprom.et0mac;
+ if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
+ return -ENODEV;
+
+ et0mac = bcm47xx_bus.ssb.sprom.et0mac;
if (et0mac[0] == 0x00 &&
((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
(et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+ struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
printk(KERN_INFO "WGT634U machine detected.\n");
if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
gpio_interrupt, IRQF_SHARED,
- "WGT634U GPIO", &ssb_bcm47xx.chipco)) {
+ "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
gpio_direction_input(WGT634U_GPIO_RESET);
gpio_intmask(WGT634U_GPIO_RESET, 1);
- ssb_chipco_irq_mask(&ssb_bcm47xx.chipco,
+ ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
SSB_CHIPCO_IRQ_GPIO,
SSB_CHIPCO_IRQ_GPIO);
}
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index dbc51065df5b..b77df0366ee6 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -111,7 +111,8 @@ struct compat_statfs {
int f_bavail;
compat_fsid_t f_fsid;
int f_namelen;
- int f_spare[6];
+ int f_flags;
+ int f_spare[5];
};
#define COMPAT_RLIM_INFINITY 0x7fffffffUL
diff --git a/arch/mips/include/asm/lasat/lasat.h b/arch/mips/include/asm/lasat/lasat.h
index a1ada1c27c16..e8ff70f80e13 100644
--- a/arch/mips/include/asm/lasat/lasat.h
+++ b/arch/mips/include/asm/lasat/lasat.h
@@ -41,10 +41,8 @@ enum lasat_mtdparts {
/*
* The format of the data record in the EEPROM.
- * See Documentation/LASAT/eeprom.txt for a detailed description
- * of the fields in this struct, and the LASAT Hardware Configuration
- * field specification for a detailed description of the config
- * field.
+ * See the LASAT Hardware Configuration field specification for a detailed
+ * description of the config field.
*/
#include <linux/types.h>
diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h b/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h
index 892b7f168eb4..5a5cb7386427 100644
--- a/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h
+++ b/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h
@@ -394,19 +394,6 @@ typedef struct psc_spi {
#define PSC_SPITXRX_LC (1 << 29)
#define PSC_SPITXRX_SR (1 << 28)
-/* PSC in SMBus (I2C) Mode. */
-typedef struct psc_smb {
- u32 psc_sel;
- u32 psc_ctrl;
- u32 psc_smbcfg;
- u32 psc_smbmsk;
- u32 psc_smbpcr;
- u32 psc_smbstat;
- u32 psc_smbevnt;
- u32 psc_smbtxrx;
- u32 psc_smbtmr;
-} psc_smb_t;
-
/* SMBus Config Register. */
#define PSC_SMBCFG_RT_MASK (3 << 30)
#define PSC_SMBCFG_RT_FIFO1 (0 << 30)
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
index d008f47a28bd..de95e0723e2b 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -19,7 +19,29 @@
#ifndef __ASM_BCM47XX_H
#define __ASM_BCM47XX_H
-/* SSB bus */
-extern struct ssb_bus ssb_bcm47xx;
+#include <linux/ssb/ssb.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_soc.h>
+
+enum bcm47xx_bus_type {
+#ifdef CONFIG_BCM47XX_SSB
+ BCM47XX_BUS_TYPE_SSB,
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ BCM47XX_BUS_TYPE_BCMA,
+#endif
+};
+
+union bcm47xx_bus {
+#ifdef CONFIG_BCM47XX_SSB
+ struct ssb_bus ssb;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ struct bcma_soc bcma;
+#endif
+};
+
+extern union bcm47xx_bus bcm47xx_bus;
+extern enum bcm47xx_bus_type bcm47xx_bus_type;
#endif /* __ASM_BCM47XX_H */
diff --git a/arch/mips/include/asm/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h
index 98504142124e..76961cabeedf 100644
--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
+++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
@@ -10,6 +10,7 @@
#define __BCM47XX_GPIO_H
#include <linux/ssb/ssb_embedded.h>
+#include <linux/bcma/bcma.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
#define BCM47XX_EXTIF_GPIO_LINES 5
@@ -21,41 +22,118 @@ extern int gpio_to_irq(unsigned gpio);
static inline int gpio_get_value(unsigned gpio)
{
- return ssb_gpio_in(&ssb_bcm47xx, 1 << gpio);
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc,
+ 1 << gpio);
+#endif
+ }
+ return -EINVAL;
}
static inline void gpio_set_value(unsigned gpio, int value)
{
- ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
+ value ? 1 << gpio : 0);
+ return;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+ value ? 1 << gpio : 0);
+ return;
+#endif
+ }
}
static inline int gpio_direction_input(unsigned gpio)
{
- ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0);
- return 0;
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
+ return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+ 0);
+ return 0;
+#endif
+ }
+ return -EINVAL;
}
static inline int gpio_direction_output(unsigned gpio, int value)
{
- /* first set the gpio out value */
- ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
- /* then set the gpio mode */
- ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio);
- return 0;
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ /* first set the gpio out value */
+ ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
+ value ? 1 << gpio : 0);
+ /* then set the gpio mode */
+ ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
+ return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ /* first set the gpio out value */
+ bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+ value ? 1 << gpio : 0);
+ /* then set the gpio mode */
+ bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+ 1 << gpio);
+ return 0;
+#endif
+ }
+ return -EINVAL;
}
static inline int gpio_intmask(unsigned gpio, int value)
{
- ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio,
- value ? 1 << gpio : 0);
- return 0;
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
+ value ? 1 << gpio : 0);
+ return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc,
+ 1 << gpio, value ? 1 << gpio : 0);
+ return 0;
+#endif
+ }
+ return -EINVAL;
}
static inline int gpio_polarity(unsigned gpio, int value)
{
- ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio,
- value ? 1 << gpio : 0);
- return 0;
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
+ value ? 1 << gpio : 0);
+ return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc,
+ 1 << gpio, value ? 1 << gpio : 0);
+ return 0;
+#endif
+ }
+ return -EINVAL;
}
diff --git a/arch/mips/pci/pci-bcm47xx.c b/arch/mips/pci/pci-bcm47xx.c
index 455f8e50a007..400535a955d0 100644
--- a/arch/mips/pci/pci-bcm47xx.c
+++ b/arch/mips/pci/pci-bcm47xx.c
@@ -25,6 +25,7 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/ssb/ssb.h>
+#include <bcm47xx.h>
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
@@ -33,9 +34,13 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
int pcibios_plat_dev_init(struct pci_dev *dev)
{
+#ifdef CONFIG_BCM47XX_SSB
int res;
u8 slot, pin;
+ if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
+ return 0;
+
res = ssb_pcibios_plat_dev_init(dev);
if (res < 0) {
printk(KERN_ALERT "PCI: Failed to init device %s\n",
@@ -55,5 +60,6 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
}
dev->irq = res;
+#endif
return 0;
}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_serial.c b/arch/mips/pmc-sierra/msp71xx/msp_serial.c
index f7261628d8a6..a1c7c7da2336 100644
--- a/arch/mips/pmc-sierra/msp71xx/msp_serial.c
+++ b/arch/mips/pmc-sierra/msp71xx/msp_serial.c
@@ -27,6 +27,7 @@
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
+#include <linux/slab.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
@@ -38,6 +39,55 @@
#include <msp_int.h>
#include <msp_regs.h>
+struct msp_uart_data {
+ int last_lcr;
+};
+
+static void msp_serial_out(struct uart_port *p, int offset, int value)
+{
+ struct msp_uart_data *d = p->private_data;
+
+ if (offset == UART_LCR)
+ d->last_lcr = value;
+
+ offset <<= p->regshift;
+ writeb(value, p->membase + offset);
+}
+
+static unsigned int msp_serial_in(struct uart_port *p, int offset)
+{
+ offset <<= p->regshift;
+
+ return readb(p->membase + offset);
+}
+
+static int msp_serial_handle_irq(struct uart_port *p)
+{
+ struct msp_uart_data *d = p->private_data;
+ unsigned int iir = readb(p->membase + (UART_IIR << p->regshift));
+
+ if (serial8250_handle_irq(p, iir)) {
+ return 1;
+ } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
+ /*
+ * The DesignWare APB UART has an Busy Detect (0x07) interrupt
+ * meaning an LCR write attempt occurred while the UART was
+ * busy. The interrupt must be cleared by reading the UART
+ * status register (USR) and the LCR re-written.
+ *
+ * Note: MSP reserves 0x20 bytes of address space for the UART
+ * and the USR is mapped in a separate block at an offset of
+ * 0xc0 from the start of the UART.
+ */
+ (void)readb(p->membase + 0xc0);
+ writeb(d->last_lcr, p->membase + (UART_LCR << p->regshift));
+
+ return 1;
+ }
+
+ return 0;
+}
+
void __init msp_serial_setup(void)
{
char *s;
@@ -59,13 +109,22 @@ void __init msp_serial_setup(void)
up.irq = MSP_INT_UART0;
up.uartclk = uartclk;
up.regshift = 2;
- up.iotype = UPIO_DWAPB; /* UPIO_MEM like */
+ up.iotype = UPIO_MEM;
up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
up.type = PORT_16550A;
up.line = 0;
- up.private_data = (void*)UART0_STATUS_REG;
- if (early_serial_setup(&up))
- printk(KERN_ERR "Early serial init of port 0 failed\n");
+ up.serial_out = msp_serial_out;
+ up.serial_in = msp_serial_in;
+ up.handle_irq = msp_serial_handle_irq;
+ up.private_data = kzalloc(sizeof(struct msp_uart_data), GFP_KERNEL);
+ if (!up.private_data) {
+ pr_err("failed to allocate uart private data\n");
+ return;
+ }
+ if (early_serial_setup(&up)) {
+ kfree(up.private_data);
+ pr_err("Early serial init of port 0 failed\n");
+ }
/* Initialize the second serial port, if one exists */
switch (mips_machtype) {
@@ -88,6 +147,8 @@ void __init msp_serial_setup(void)
up.irq = MSP_INT_UART1;
up.line = 1;
up.private_data = (void*)UART1_STATUS_REG;
- if (early_serial_setup(&up))
- printk(KERN_ERR "Early serial init of port 1 failed\n");
+ if (early_serial_setup(&up)) {
+ kfree(up.private_data);
+ pr_err("Early serial init of port 1 failed\n");
+ }
}
diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c
index e9f95dcde379..ba3cec3155df 100644
--- a/arch/mips/txx9/generic/setup_tx4939.c
+++ b/arch/mips/txx9/generic/setup_tx4939.c
@@ -321,7 +321,7 @@ void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask)
static u32 tx4939_get_eth_speed(struct net_device *dev)
{
struct ethtool_cmd cmd;
- if (dev_ethtool_get_settings(dev, &cmd))
+ if (__ethtool_get_settings(dev, &cmd))
return 100; /* default 100Mbps */
return ethtool_cmd_speed(&cmd);
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 1f870340ebdd..438db84a1f7c 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -47,9 +47,6 @@ config GENERIC_CMOS_UPDATE
config GENERIC_HWEIGHT
def_bool y
-config GENERIC_TIME
- def_bool y
-
config GENERIC_CLOCKEVENTS
def_bool y
@@ -195,7 +192,7 @@ config SMP
singleprocessor machines. On a singleprocessor machine, the kernel
will run faster if you say N here.
- See also <file:Documentation/i386/IO-APIC.txt>,
+ See also <file:Documentation/x86/i386/IO-APIC.txt>,
<file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
<http://www.tldp.org/docs.html#howto>.
diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c
index 538266b2c9bc..522eb8a9b60d 100644
--- a/arch/mn10300/kernel/gdb-stub.c
+++ b/arch/mn10300/kernel/gdb-stub.c
@@ -798,7 +798,7 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
if ((u32) mem & 1 && count >= 1) {
if (gdbstub_read_byte(mem, ch) != 0)
return 0;
- buf = pack_hex_byte(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[0]);
mem++;
count--;
}
@@ -806,8 +806,8 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
if ((u32) mem & 3 && count >= 2) {
if (gdbstub_read_word(mem, ch) != 0)
return 0;
- buf = pack_hex_byte(buf, ch[0]);
- buf = pack_hex_byte(buf, ch[1]);
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
mem += 2;
count -= 2;
}
@@ -815,10 +815,10 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
while (count >= 4) {
if (gdbstub_read_dword(mem, ch) != 0)
return 0;
- buf = pack_hex_byte(buf, ch[0]);
- buf = pack_hex_byte(buf, ch[1]);
- buf = pack_hex_byte(buf, ch[2]);
- buf = pack_hex_byte(buf, ch[3]);
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
+ buf = hex_byte_pack(buf, ch[2]);
+ buf = hex_byte_pack(buf, ch[3]);
mem += 4;
count -= 4;
}
@@ -826,8 +826,8 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
if (count >= 2) {
if (gdbstub_read_word(mem, ch) != 0)
return 0;
- buf = pack_hex_byte(buf, ch[0]);
- buf = pack_hex_byte(buf, ch[1]);
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
mem += 2;
count -= 2;
}
@@ -835,7 +835,7 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
if (count >= 1) {
if (gdbstub_read_byte(mem, ch) != 0)
return 0;
- buf = pack_hex_byte(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[0]);
}
*buf = 0;
@@ -1273,13 +1273,13 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
ptr = mem2hex(title, ptr, sizeof(title) - 1, 0);
hx = hex_asc_hi(excep >> 8);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(excep >> 8);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(excep);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(excep);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
*ptr = 0;
@@ -1291,21 +1291,21 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
ptr = mem2hex(tbcberr, ptr, sizeof(tbcberr) - 1, 0);
hx = hex_asc_hi(bcberr >> 24);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(bcberr >> 24);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(bcberr >> 16);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(bcberr >> 16);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(bcberr >> 8);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(bcberr >> 8);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(bcberr);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(bcberr);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
*ptr = 0;
@@ -1321,12 +1321,12 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
* Send trap type (converted to signal)
*/
*ptr++ = 'T';
- ptr = pack_hex_byte(ptr, sigval);
+ ptr = hex_byte_pack(ptr, sigval);
/*
* Send Error PC
*/
- ptr = pack_hex_byte(ptr, GDB_REGID_PC);
+ ptr = hex_byte_pack(ptr, GDB_REGID_PC);
*ptr++ = ':';
ptr = mem2hex(&regs->pc, ptr, 4, 0);
*ptr++ = ';';
@@ -1334,7 +1334,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
/*
* Send frame pointer
*/
- ptr = pack_hex_byte(ptr, GDB_REGID_FP);
+ ptr = hex_byte_pack(ptr, GDB_REGID_FP);
*ptr++ = ':';
ptr = mem2hex(&regs->a3, ptr, 4, 0);
*ptr++ = ';';
@@ -1343,7 +1343,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
* Send stack pointer
*/
ssp = (unsigned long) (regs + 1);
- ptr = pack_hex_byte(ptr, GDB_REGID_SP);
+ ptr = hex_byte_pack(ptr, GDB_REGID_SP);
*ptr++ = ':';
ptr = mem2hex(&ssp, ptr, 4, 0);
*ptr++ = ';';
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
index 2623d19f4f4c..2381df83bd00 100644
--- a/arch/mn10300/kernel/irq.c
+++ b/arch/mn10300/kernel/irq.c
@@ -260,7 +260,6 @@ void set_intr_level(int irq, u16 level)
/*
* mark an interrupt to be ACK'd after interrupt handlers have been run rather
* than before
- * - see Documentation/mn10300/features.txt
*/
void mn10300_set_lateack_irq_type(int irq)
{
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 4558bafbd1a2..9460e1c266dd 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -1,6 +1,6 @@
#
# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/config-language.txt.
+# see Documentation/kbuild/kconfig-language.txt.
#
config OPENRISC
diff --git a/arch/openrisc/include/asm/dma-mapping.h b/arch/openrisc/include/asm/dma-mapping.h
index 60b472233900..b206ba4608b2 100644
--- a/arch/openrisc/include/asm/dma-mapping.h
+++ b/arch/openrisc/include/asm/dma-mapping.h
@@ -18,7 +18,7 @@
#define __ASM_OPENRISC_DMA_MAPPING_H
/*
- * See Documentation/PCI/PCI-DMA-mapping.txt and
+ * See Documentation/DMA-API-HOWTO.txt and
* Documentation/DMA-API.txt for documentation.
*
* This file is written with the intention of eventually moving over
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index e077b0bf56ca..fdfd8be29e95 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -169,9 +169,7 @@ config 64BIT
choice
prompt "Kernel page size"
- default PARISC_PAGE_SIZE_4KB if !64BIT
- default PARISC_PAGE_SIZE_4KB if 64BIT
-# default PARISC_PAGE_SIZE_16KB if 64BIT
+ default PARISC_PAGE_SIZE_4KB
config PARISC_PAGE_SIZE_4KB
bool "4KB"
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
index efa0b60c63fe..760f331d4fa3 100644
--- a/arch/parisc/include/asm/compat.h
+++ b/arch/parisc/include/asm/compat.h
@@ -105,7 +105,8 @@ struct compat_statfs {
__kernel_fsid_t f_fsid;
s32 f_namelen;
s32 f_frsize;
- s32 f_spare[5];
+ s32 f_flags;
+ s32 f_spare[4];
};
struct compat_sigcontext {
diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h
index 890531e32fe8..467bbd510eac 100644
--- a/arch/parisc/include/asm/dma-mapping.h
+++ b/arch/parisc/include/asm/dma-mapping.h
@@ -5,7 +5,7 @@
#include <asm/cacheflush.h>
#include <asm/scatterlist.h>
-/* See Documentation/PCI/PCI-DMA-mapping.txt */
+/* See Documentation/DMA-API-HOWTO.txt */
struct hppa_dma_ops {
int (*dma_supported)(struct device *dev, u64 mask);
void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *iova, gfp_t flag);
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index a029f74a3c5c..d047edea2504 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -2,7 +2,7 @@
** PARISC 1.1 Dynamic DMA mapping support.
** This implementation is for PA-RISC platforms that do not support
** I/O TLBs (aka DMA address translation hardware).
-** See Documentation/PCI/PCI-DMA-mapping.txt for interface definitions.
+** See Documentation/DMA-API-HOWTO.txt for interface definitions.
**
** (c) Copyright 1999,2000 Hewlett-Packard Company
** (c) Copyright 2000 Grant Grundler
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6926b61acfea..47682b67fd36 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -656,6 +656,8 @@ config SBUS
config FSL_SOC
bool
+ select HAVE_CAN_FLEXCAN if NET && CAN
+ select PPC_CLOCK if CAN_FLEXCAN
config FSL_PCI
bool
diff --git a/arch/powerpc/boot/dts/p1010rdb.dts b/arch/powerpc/boot/dts/p1010rdb.dts
index 6b33b73a5ba0..d6c669c888e9 100644
--- a/arch/powerpc/boot/dts/p1010rdb.dts
+++ b/arch/powerpc/boot/dts/p1010rdb.dts
@@ -23,6 +23,8 @@
ethernet2 = &enet2;
pci0 = &pci0;
pci1 = &pci1;
+ can0 = &can0;
+ can1 = &can1;
};
memory {
@@ -169,14 +171,6 @@
};
};
- can0@1c000 {
- fsl,flexcan-clock-source = "platform";
- };
-
- can1@1d000 {
- fsl,flexcan-clock-source = "platform";
- };
-
usb@22000 {
phy_type = "utmi";
};
diff --git a/arch/powerpc/boot/dts/p1010si.dtsi b/arch/powerpc/boot/dts/p1010si.dtsi
index 7f51104f2e36..cabe0a453ae6 100644
--- a/arch/powerpc/boot/dts/p1010si.dtsi
+++ b/arch/powerpc/boot/dts/p1010si.dtsi
@@ -140,20 +140,18 @@
interrupt-parent = <&mpic>;
};
- can0@1c000 {
- compatible = "fsl,flexcan-v1.0";
+ can0: can@1c000 {
+ compatible = "fsl,p1010-flexcan";
reg = <0x1c000 0x1000>;
interrupts = <48 0x2>;
interrupt-parent = <&mpic>;
- fsl,flexcan-clock-divider = <2>;
};
- can1@1d000 {
- compatible = "fsl,flexcan-v1.0";
+ can1: can@1d000 {
+ compatible = "fsl,p1010-flexcan";
reg = <0x1d000 0x1000>;
interrupts = <61 0x2>;
interrupt-parent = <&mpic>;
- fsl,flexcan-clock-divider = <2>;
};
L2: l2-cache-controller@20000 {
diff --git a/arch/powerpc/configs/40x/acadia_defconfig b/arch/powerpc/configs/40x/acadia_defconfig
index 4182c772340b..ed3bab72a834 100644
--- a/arch/powerpc/configs/40x/acadia_defconfig
+++ b/arch/powerpc/configs/40x/acadia_defconfig
@@ -44,12 +44,13 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
CONFIG_MII=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
-CONFIG_IBM_NEW_EMAC_DEBUG=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
+CONFIG_IBM_EMAC_DEBUG=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT is not set
diff --git a/arch/powerpc/configs/40x/ep405_defconfig b/arch/powerpc/configs/40x/ep405_defconfig
index 2dbb293163f5..17582a3420fb 100644
--- a/arch/powerpc/configs/40x/ep405_defconfig
+++ b/arch/powerpc/configs/40x/ep405_defconfig
@@ -42,8 +42,9 @@ CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
diff --git a/arch/powerpc/configs/40x/hcu4_defconfig b/arch/powerpc/configs/40x/hcu4_defconfig
index ebeb4accad65..dba263c1d3a2 100644
--- a/arch/powerpc/configs/40x/hcu4_defconfig
+++ b/arch/powerpc/configs/40x/hcu4_defconfig
@@ -43,8 +43,9 @@ CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
diff --git a/arch/powerpc/configs/40x/kilauea_defconfig b/arch/powerpc/configs/40x/kilauea_defconfig
index 532ea9d93a15..f2d4be936e08 100644
--- a/arch/powerpc/configs/40x/kilauea_defconfig
+++ b/arch/powerpc/configs/40x/kilauea_defconfig
@@ -51,10 +51,11 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT is not set
diff --git a/arch/powerpc/configs/40x/makalu_defconfig b/arch/powerpc/configs/40x/makalu_defconfig
index 3c142ac1b344..42b979355f9b 100644
--- a/arch/powerpc/configs/40x/makalu_defconfig
+++ b/arch/powerpc/configs/40x/makalu_defconfig
@@ -43,10 +43,11 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT is not set
diff --git a/arch/powerpc/configs/40x/walnut_defconfig b/arch/powerpc/configs/40x/walnut_defconfig
index ff57d4828ffc..aa1a4cac3708 100644
--- a/arch/powerpc/configs/40x/walnut_defconfig
+++ b/arch/powerpc/configs/40x/walnut_defconfig
@@ -40,8 +40,9 @@ CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
diff --git a/arch/powerpc/configs/44x/arches_defconfig b/arch/powerpc/configs/44x/arches_defconfig
index 3ed16d5c909d..329f9a3b892e 100644
--- a/arch/powerpc/configs/44x/arches_defconfig
+++ b/arch/powerpc/configs/44x/arches_defconfig
@@ -44,10 +44,11 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT is not set
diff --git a/arch/powerpc/configs/44x/bamboo_defconfig b/arch/powerpc/configs/44x/bamboo_defconfig
index b1b7d2c5c059..cef7d62560c4 100644
--- a/arch/powerpc/configs/44x/bamboo_defconfig
+++ b/arch/powerpc/configs/44x/bamboo_defconfig
@@ -32,8 +32,9 @@ CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
diff --git a/arch/powerpc/configs/44x/bluestone_defconfig b/arch/powerpc/configs/44x/bluestone_defconfig
index 30a0a8e08fdd..20c8d26d7fc0 100644
--- a/arch/powerpc/configs/44x/bluestone_defconfig
+++ b/arch/powerpc/configs/44x/bluestone_defconfig
@@ -38,10 +38,11 @@ CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=2
diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig
index a46942aac695..d5be93e6e92d 100644
--- a/arch/powerpc/configs/44x/canyonlands_defconfig
+++ b/arch/powerpc/configs/44x/canyonlands_defconfig
@@ -49,10 +49,11 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
# CONFIG_MISC_DEVICES is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT is not set
diff --git a/arch/powerpc/configs/44x/ebony_defconfig b/arch/powerpc/configs/44x/ebony_defconfig
index 07d77e51f1ba..f9269fc4ffcc 100644
--- a/arch/powerpc/configs/44x/ebony_defconfig
+++ b/arch/powerpc/configs/44x/ebony_defconfig
@@ -40,8 +40,9 @@ CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
diff --git a/arch/powerpc/configs/44x/eiger_defconfig b/arch/powerpc/configs/44x/eiger_defconfig
index 2ce7e9aff09e..9be089038fd7 100644
--- a/arch/powerpc/configs/44x/eiger_defconfig
+++ b/arch/powerpc/configs/44x/eiger_defconfig
@@ -55,10 +55,11 @@ CONFIG_FUSION=y
CONFIG_FUSION_SAS=y
CONFIG_I2O=y
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
CONFIG_E1000E=y
# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT is not set
diff --git a/arch/powerpc/configs/44x/icon_defconfig b/arch/powerpc/configs/44x/icon_defconfig
index 18730ff9de7c..82f73035a7ce 100644
--- a/arch/powerpc/configs/44x/icon_defconfig
+++ b/arch/powerpc/configs/44x/icon_defconfig
@@ -56,8 +56,9 @@ CONFIG_FUSION_SAS=y
CONFIG_FUSION_CTL=y
CONFIG_FUSION_LOGGING=y
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_WLAN is not set
diff --git a/arch/powerpc/configs/44x/katmai_defconfig b/arch/powerpc/configs/44x/katmai_defconfig
index 34c09144a699..109562c3c6be 100644
--- a/arch/powerpc/configs/44x/katmai_defconfig
+++ b/arch/powerpc/configs/44x/katmai_defconfig
@@ -42,8 +42,9 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
CONFIG_MACINTOSH_DRIVERS=y
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
diff --git a/arch/powerpc/configs/44x/redwood_defconfig b/arch/powerpc/configs/44x/redwood_defconfig
index 01cc2b1a7f9a..48802811da76 100644
--- a/arch/powerpc/configs/44x/redwood_defconfig
+++ b/arch/powerpc/configs/44x/redwood_defconfig
@@ -53,11 +53,12 @@ CONFIG_FUSION=y
CONFIG_FUSION_SAS=y
CONFIG_I2O=y
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
-CONFIG_IBM_NEW_EMAC_DEBUG=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
+CONFIG_IBM_EMAC_DEBUG=y
CONFIG_E1000E=y
# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT is not set
diff --git a/arch/powerpc/configs/44x/sam440ep_defconfig b/arch/powerpc/configs/44x/sam440ep_defconfig
index dfcffede16ad..ca088cd581af 100644
--- a/arch/powerpc/configs/44x/sam440ep_defconfig
+++ b/arch/powerpc/configs/44x/sam440ep_defconfig
@@ -44,8 +44,9 @@ CONFIG_ATA=y
# CONFIG_SATA_PMP is not set
CONFIG_SATA_SIL=y
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
CONFIG_INPUT_FF_MEMLESS=m
diff --git a/arch/powerpc/configs/44x/sequoia_defconfig b/arch/powerpc/configs/44x/sequoia_defconfig
index 47e399f2892f..b7a653b626db 100644
--- a/arch/powerpc/configs/44x/sequoia_defconfig
+++ b/arch/powerpc/configs/44x/sequoia_defconfig
@@ -46,8 +46,9 @@ CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
diff --git a/arch/powerpc/configs/44x/taishan_defconfig b/arch/powerpc/configs/44x/taishan_defconfig
index a6a002ed5681..30de97f158a4 100644
--- a/arch/powerpc/configs/44x/taishan_defconfig
+++ b/arch/powerpc/configs/44x/taishan_defconfig
@@ -40,8 +40,9 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
CONFIG_MACINTOSH_DRIVERS=y
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig
index abf74dc1f79c..105bc56f4b2b 100644
--- a/arch/powerpc/configs/44x/warp_defconfig
+++ b/arch/powerpc/configs/44x/warp_defconfig
@@ -54,9 +54,10 @@ CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
CONFIG_MII=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_EMAC=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_INPUT is not set
diff --git a/arch/powerpc/configs/ppc40x_defconfig b/arch/powerpc/configs/ppc40x_defconfig
index bfd634b5ada7..7cb703b948b1 100644
--- a/arch/powerpc/configs/ppc40x_defconfig
+++ b/arch/powerpc/configs/ppc40x_defconfig
@@ -50,8 +50,9 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
CONFIG_XILINX_SYSACE=m
CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_INPUT is not set
CONFIG_SERIO=m
# CONFIG_SERIO_I8042 is not set
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
index 47133202a625..6cdf1c0d2c8a 100644
--- a/arch/powerpc/configs/ppc44x_defconfig
+++ b/arch/powerpc/configs/ppc44x_defconfig
@@ -63,8 +63,9 @@ CONFIG_BLK_DEV_SD=m
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_NETDEVICES=y
CONFIG_TUN=m
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
# CONFIG_INPUT is not set
CONFIG_SERIO=m
# CONFIG_SERIO_I8042 is not set
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index 91010e8f8479..88e602f6430d 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -100,7 +100,8 @@ struct compat_statfs {
compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_frsize;
- int f_spare[5];
+ int f_flags;
+ int f_spare[4];
};
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
index a4f6c85431f8..08fe69edcd10 100644
--- a/arch/powerpc/include/asm/kvm.h
+++ b/arch/powerpc/include/asm/kvm.h
@@ -149,6 +149,12 @@ struct kvm_regs {
#define KVM_SREGS_E_UPDATE_DBSR (1 << 3)
/*
+ * Book3S special bits to indicate contents in the struct by maintaining
+ * backwards compatibility with older structs. If adding a new field,
+ * please make sure to add a flag for that new field */
+#define KVM_SREGS_S_HIOR (1 << 0)
+
+/*
* In KVM_SET_SREGS, reserved/pad fields must be left untouched from a
* previous KVM_GET_REGS.
*
@@ -173,6 +179,8 @@ struct kvm_sregs {
__u64 ibat[8];
__u64 dbat[8];
} ppc32;
+ __u64 flags; /* KVM_SREGS_S_ */
+ __u64 hior;
} s;
struct {
union {
@@ -276,6 +284,11 @@ struct kvm_guest_debug_arch {
#define KVM_INTERRUPT_UNSET -2U
#define KVM_INTERRUPT_SET_LEVEL -3U
+#define KVM_CPU_440 1
+#define KVM_CPU_E500V2 2
+#define KVM_CPU_3S_32 3
+#define KVM_CPU_3S_64 4
+
/* for KVM_CAP_SPAPR_TCE */
struct kvm_create_spapr_tce {
__u64 liobn;
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 98da010252a3..a384ffdf33de 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -90,6 +90,8 @@ struct kvmppc_vcpu_book3s {
#endif
int context_id[SID_CONTEXTS];
+ bool hior_sregs; /* HIOR is set by SREGS, not PVR */
+
struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE];
struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG];
struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE];
@@ -139,15 +141,14 @@ extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu);
extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn);
-extern void kvmppc_handler_lowmem_trampoline(void);
-extern void kvmppc_handler_trampoline_enter(void);
-extern void kvmppc_rmcall(ulong srr0, ulong srr1);
+extern void kvmppc_entry_trampoline(void);
extern void kvmppc_hv_entry_trampoline(void);
extern void kvmppc_load_up_fpu(void);
extern void kvmppc_load_up_altivec(void);
extern void kvmppc_load_up_vsx(void);
extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
+extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
{
@@ -382,6 +383,39 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
}
#endif
+static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
+ unsigned long pte_index)
+{
+ unsigned long rb, va_low;
+
+ rb = (v & ~0x7fUL) << 16; /* AVA field */
+ va_low = pte_index >> 3;
+ if (v & HPTE_V_SECONDARY)
+ va_low = ~va_low;
+ /* xor vsid from AVA */
+ if (!(v & HPTE_V_1TB_SEG))
+ va_low ^= v >> 12;
+ else
+ va_low ^= v >> 24;
+ va_low &= 0x7ff;
+ if (v & HPTE_V_LARGE) {
+ rb |= 1; /* L field */
+ if (cpu_has_feature(CPU_FTR_ARCH_206) &&
+ (r & 0xff000)) {
+ /* non-16MB large page, must be 64k */
+ /* (masks depend on page size) */
+ rb |= 0x1000; /* page encoding in LP field */
+ rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
+ rb |= (va_low & 0xfe); /* AVAL field (P7 doesn't seem to care) */
+ }
+ } else {
+ /* 4kB page */
+ rb |= (va_low & 0x7ff) << 12; /* remaining 11b of VA */
+ }
+ rb |= (v >> 54) & 0x300; /* B field */
+ return rb;
+}
+
/* Magic register values loaded into r3 and r4 before the 'sc' assembly
* instruction for the OSI hypercalls */
#define OSI_SC_MAGIC_R3 0x113724FA
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h
index ef7b3688c3b6..1f2f5b6156bd 100644
--- a/arch/powerpc/include/asm/kvm_book3s_asm.h
+++ b/arch/powerpc/include/asm/kvm_book3s_asm.h
@@ -75,6 +75,8 @@ struct kvmppc_host_state {
ulong scratch0;
ulong scratch1;
u8 in_guest;
+ u8 restore_hid5;
+ u8 napping;
#ifdef CONFIG_KVM_BOOK3S_64_HV
struct kvm_vcpu *kvm_vcpu;
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index cc22b282d755..bf8af5d5d5dc 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -198,21 +198,29 @@ struct kvm_arch {
*/
struct kvmppc_vcore {
int n_runnable;
- int n_blocked;
+ int n_busy;
int num_threads;
int entry_exit_count;
int n_woken;
int nap_count;
+ int napping_threads;
u16 pcpu;
- u8 vcore_running;
+ u8 vcore_state;
u8 in_guest;
struct list_head runnable_threads;
spinlock_t lock;
+ wait_queue_head_t wq;
};
#define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff)
#define VCORE_EXIT_COUNT(vc) ((vc)->entry_exit_count >> 8)
+/* Values for vcore_state */
+#define VCORE_INACTIVE 0
+#define VCORE_RUNNING 1
+#define VCORE_EXITING 2
+#define VCORE_SLEEPING 3
+
struct kvmppc_pte {
ulong eaddr;
u64 vpage;
@@ -258,14 +266,6 @@ struct kvm_vcpu_arch {
ulong host_stack;
u32 host_pid;
#ifdef CONFIG_PPC_BOOK3S
- ulong host_msr;
- ulong host_r2;
- void *host_retip;
- ulong trampoline_lowmem;
- ulong trampoline_enter;
- ulong highmem_handler;
- ulong rmcall;
- ulong host_paca_phys;
struct kvmppc_slb slb[64];
int slb_max; /* 1 + index of last valid entry in slb[] */
int slb_nr; /* total number of entries in SLB */
@@ -389,6 +389,9 @@ struct kvm_vcpu_arch {
u8 dcr_is_write;
u8 osi_needed;
u8 osi_enabled;
+ u8 papr_enabled;
+ u8 sane;
+ u8 cpu_type;
u8 hcall_needed;
u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
@@ -408,11 +411,13 @@ struct kvm_vcpu_arch {
struct dtl *dtl;
struct dtl *dtl_end;
+ wait_queue_head_t *wqp;
struct kvmppc_vcore *vcore;
int ret;
int trap;
int state;
int ptid;
+ bool timer_running;
wait_queue_head_t cpu_run;
struct kvm_vcpu_arch_shared *shared;
@@ -428,8 +433,9 @@ struct kvm_vcpu_arch {
#endif
};
-#define KVMPPC_VCPU_BUSY_IN_HOST 0
-#define KVMPPC_VCPU_BLOCKED 1
+/* Values for vcpu->arch.state */
+#define KVMPPC_VCPU_STOPPED 0
+#define KVMPPC_VCPU_BUSY_IN_HOST 1
#define KVMPPC_VCPU_RUNNABLE 2
#endif /* __POWERPC_KVM_HOST_H__ */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index d121f49d62b8..46efd1a265c9 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -66,6 +66,7 @@ extern int kvmppc_emulate_instruction(struct kvm_run *run,
extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
+extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
/* Core-specific hooks */
diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index 0947b36e534c..5e0b6d511e14 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -196,7 +196,7 @@ static inline int qe_alive_during_sleep(void)
/* Structure that defines QE firmware binary files.
*
- * See Documentation/powerpc/qe-firmware.txt for a description of these
+ * See Documentation/powerpc/qe_firmware.txt for a description of these
* fields.
*/
struct qe_firmware {
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index fa0d27a400de..559ae1ee6706 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -354,3 +354,5 @@ COMPAT_SYS_SPU(clock_adjtime)
SYSCALL_SPU(syncfs)
COMPAT_SYS_SPU(sendmmsg)
SYSCALL_SPU(setns)
+COMPAT_SYS(process_vm_readv)
+COMPAT_SYS(process_vm_writev)
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index 93e05d1b34b2..5354ae91bdde 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -54,6 +54,7 @@ extern void __init udbg_init_40x_realmode(void);
extern void __init udbg_init_cpm(void);
extern void __init udbg_init_usbgecko(void);
extern void __init udbg_init_wsp(void);
+extern void __init udbg_init_ehv_bc(void);
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_UDBG_H */
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index b8b3f599362b..d3d1b5efd7eb 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -373,10 +373,12 @@
#define __NR_syncfs 348
#define __NR_sendmmsg 349
#define __NR_setns 350
+#define __NR_process_vm_readv 351
+#define __NR_process_vm_writev 352
#ifdef __KERNEL__
-#define __NR_syscalls 351
+#define __NR_syscalls 353
#define __NR__exit __NR_exit
#define NR_syscalls __NR_syscalls
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 5f078bc2063e..69f7ffe7f674 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -44,6 +44,7 @@
#include <asm/compat.h>
#include <asm/mmu.h>
#include <asm/hvcall.h>
+#include <asm/xics.h>
#endif
#ifdef CONFIG_PPC_ISERIES
#include <asm/iseries/alpaca.h>
@@ -449,8 +450,6 @@ int main(void)
#ifdef CONFIG_PPC_BOOK3S
DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm));
DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
- DEFINE(VCPU_HOST_RETIP, offsetof(struct kvm_vcpu, arch.host_retip));
- DEFINE(VCPU_HOST_MSR, offsetof(struct kvm_vcpu, arch.host_msr));
DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr));
DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr));
DEFINE(VCPU_DSCR, offsetof(struct kvm_vcpu, arch.dscr));
@@ -458,14 +457,12 @@ int main(void)
DEFINE(VCPU_UAMOR, offsetof(struct kvm_vcpu, arch.uamor));
DEFINE(VCPU_CTRL, offsetof(struct kvm_vcpu, arch.ctrl));
DEFINE(VCPU_DABR, offsetof(struct kvm_vcpu, arch.dabr));
- DEFINE(VCPU_TRAMPOLINE_LOWMEM, offsetof(struct kvm_vcpu, arch.trampoline_lowmem));
- DEFINE(VCPU_TRAMPOLINE_ENTER, offsetof(struct kvm_vcpu, arch.trampoline_enter));
- DEFINE(VCPU_HIGHMEM_HANDLER, offsetof(struct kvm_vcpu, arch.highmem_handler));
- DEFINE(VCPU_RMCALL, offsetof(struct kvm_vcpu, arch.rmcall));
DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags));
DEFINE(VCPU_DEC, offsetof(struct kvm_vcpu, arch.dec));
DEFINE(VCPU_DEC_EXPIRES, offsetof(struct kvm_vcpu, arch.dec_expires));
DEFINE(VCPU_PENDING_EXC, offsetof(struct kvm_vcpu, arch.pending_exceptions));
+ DEFINE(VCPU_CEDED, offsetof(struct kvm_vcpu, arch.ceded));
+ DEFINE(VCPU_PRODDED, offsetof(struct kvm_vcpu, arch.prodded));
DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa));
DEFINE(VCPU_MMCR, offsetof(struct kvm_vcpu, arch.mmcr));
DEFINE(VCPU_PMC, offsetof(struct kvm_vcpu, arch.pmc));
@@ -481,6 +478,7 @@ int main(void)
DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_count));
DEFINE(VCORE_NAP_COUNT, offsetof(struct kvmppc_vcore, nap_count));
DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest));
+ DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads));
DEFINE(VCPU_SVCPU, offsetof(struct kvmppc_vcpu_book3s, shadow_vcpu) -
offsetof(struct kvmppc_vcpu_book3s, vcpu));
DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
@@ -537,6 +535,8 @@ int main(void)
HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
+ HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
+ HSTATE_FIELD(HSTATE_NAPPING, napping);
#ifdef CONFIG_KVM_BOOK3S_64_HV
HSTATE_FIELD(HSTATE_KVM_VCPU, kvm_vcpu);
@@ -549,6 +549,7 @@ int main(void)
HSTATE_FIELD(HSTATE_DSCR, host_dscr);
HSTATE_FIELD(HSTATE_DABR, dabr);
HSTATE_FIELD(HSTATE_DECEXP, dec_expires);
+ DEFINE(IPI_PRIORITY, IPI_PRIORITY);
#endif /* CONFIG_KVM_BOOK3S_64_HV */
#else /* CONFIG_PPC_BOOK3S */
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 41b02c792aa3..29ddd8b1c274 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -427,16 +427,6 @@ slb_miss_user_pseries:
b . /* prevent spec. execution */
#endif /* __DISABLED__ */
-/* KVM's trampoline code needs to be close to the interrupt handlers */
-
-#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
-#ifdef CONFIG_KVM_BOOK3S_PR
-#include "../kvm/book3s_rmhandlers.S"
-#else
-#include "../kvm/book3s_hv_rmhandlers.S"
-#endif
-#endif
-
.align 7
.globl __end_interrupts
__end_interrupts:
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index faa82c1f3f68..b4607a91d1f4 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -67,6 +67,8 @@ void __init udbg_early_init(void)
udbg_init_usbgecko();
#elif defined(CONFIG_PPC_EARLY_DEBUG_WSP)
udbg_init_wsp();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC)
+ udbg_init_ehv_bc();
#endif
#ifdef CONFIG_PPC_EARLY_DEBUG
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
index da3a1225c0ac..ca1f88b3dc59 100644
--- a/arch/powerpc/kvm/44x.c
+++ b/arch/powerpc/kvm/44x.c
@@ -78,6 +78,8 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++)
vcpu_44x->shadow_refs[i].gtlb_index = -1;
+ vcpu->arch.cpu_type = KVM_CPU_440;
+
return 0;
}
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 08428e2c188d..3688aeecc4b2 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -43,18 +43,22 @@ kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \
fpu.o \
book3s_paired_singles.o \
book3s_pr.o \
+ book3s_pr_papr.o \
book3s_emulate.o \
book3s_interrupts.o \
book3s_mmu_hpte.o \
book3s_64_mmu_host.o \
book3s_64_mmu.o \
book3s_32_mmu.o
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \
+ book3s_rmhandlers.o
kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
book3s_hv.o \
book3s_hv_interrupts.o \
book3s_64_mmu_hv.o
kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
+ book3s_hv_rmhandlers.o \
book3s_hv_rm_mmu.o \
book3s_64_vio_hv.o \
book3s_hv_builtin.o
diff --git a/arch/powerpc/kvm/book3s_32_sr.S b/arch/powerpc/kvm/book3s_32_sr.S
index 3608471ad2d8..7e06a6fc8d07 100644
--- a/arch/powerpc/kvm/book3s_32_sr.S
+++ b/arch/powerpc/kvm/book3s_32_sr.S
@@ -31,7 +31,7 @@
* R1 = host R1
* R2 = host R2
* R3 = shadow vcpu
- * all other volatile GPRS = free
+ * all other volatile GPRS = free except R4, R6
* SVCPU[CR] = guest CR
* SVCPU[XER] = guest XER
* SVCPU[CTR] = guest CTR
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index c6d3e194b6b4..b871721c0050 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -128,7 +128,13 @@ static hva_t kvmppc_mmu_book3s_64_get_pteg(
dprintk("MMU: page=0x%x sdr1=0x%llx pteg=0x%llx vsid=0x%llx\n",
page, vcpu_book3s->sdr1, pteg, slbe->vsid);
- r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT);
+ /* When running a PAPR guest, SDR1 contains a HVA address instead
+ of a GPA */
+ if (vcpu_book3s->vcpu.arch.papr_enabled)
+ r = pteg;
+ else
+ r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT);
+
if (kvm_is_error_hva(r))
return r;
return r | (pteg & ~PAGE_MASK);
diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/book3s_64_slb.S
index 04e7d3bbfe8b..f2e6e48ea463 100644
--- a/arch/powerpc/kvm/book3s_64_slb.S
+++ b/arch/powerpc/kvm/book3s_64_slb.S
@@ -53,7 +53,7 @@ slb_exit_skip_ ## num:
* R1 = host R1
* R2 = host R2
* R3 = shadow vcpu
- * all other volatile GPRS = free
+ * all other volatile GPRS = free except R4, R6
* SVCPU[CR] = guest CR
* SVCPU[XER] = guest XER
* SVCPU[CTR] = guest CTR
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 466846557089..0c9dc62532d0 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -63,6 +63,25 @@
* function pointers, so let's just disable the define. */
#undef mfsrin
+enum priv_level {
+ PRIV_PROBLEM = 0,
+ PRIV_SUPER = 1,
+ PRIV_HYPER = 2,
+};
+
+static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level)
+{
+ /* PAPR VMs only access supervisor SPRs */
+ if (vcpu->arch.papr_enabled && (level > PRIV_SUPER))
+ return false;
+
+ /* Limit user space to its own small SPR set */
+ if ((vcpu->arch.shared->msr & MSR_PR) && level > PRIV_PROBLEM)
+ return false;
+
+ return true;
+}
+
int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned int inst, int *advance)
{
@@ -296,6 +315,8 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
switch (sprn) {
case SPRN_SDR1:
+ if (!spr_allowed(vcpu, PRIV_HYPER))
+ goto unprivileged;
to_book3s(vcpu)->sdr1 = spr_val;
break;
case SPRN_DSISR:
@@ -390,6 +411,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
case SPRN_PMC4_GEKKO:
case SPRN_WPAR_GEKKO:
break;
+unprivileged:
default:
printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn);
#ifndef DEBUG_SPR
@@ -421,6 +443,8 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
break;
}
case SPRN_SDR1:
+ if (!spr_allowed(vcpu, PRIV_HYPER))
+ goto unprivileged;
kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->sdr1);
break;
case SPRN_DSISR:
@@ -449,6 +473,10 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
case SPRN_HID5:
kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[5]);
break;
+ case SPRN_CFAR:
+ case SPRN_PURR:
+ kvmppc_set_gpr(vcpu, rt, 0);
+ break;
case SPRN_GQR0:
case SPRN_GQR1:
case SPRN_GQR2:
@@ -476,6 +504,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
kvmppc_set_gpr(vcpu, rt, 0);
break;
default:
+unprivileged:
printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn);
#ifndef DEBUG_SPR
emulated = EMULATE_FAIL;
diff --git a/arch/powerpc/kvm/book3s_exports.c b/arch/powerpc/kvm/book3s_exports.c
index 88c8f26add02..f7f63a00ab1f 100644
--- a/arch/powerpc/kvm/book3s_exports.c
+++ b/arch/powerpc/kvm/book3s_exports.c
@@ -23,9 +23,7 @@
#ifdef CONFIG_KVM_BOOK3S_64_HV
EXPORT_SYMBOL_GPL(kvmppc_hv_entry_trampoline);
#else
-EXPORT_SYMBOL_GPL(kvmppc_handler_trampoline_enter);
-EXPORT_SYMBOL_GPL(kvmppc_handler_lowmem_trampoline);
-EXPORT_SYMBOL_GPL(kvmppc_rmcall);
+EXPORT_SYMBOL_GPL(kvmppc_entry_trampoline);
EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu);
#ifdef CONFIG_ALTIVEC
EXPORT_SYMBOL_GPL(kvmppc_load_up_altivec);
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index cc0d7f1b19ab..4644c7986d80 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -62,6 +62,8 @@
/* #define EXIT_DEBUG_SIMPLE */
/* #define EXIT_DEBUG_INT */
+static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
+
void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
local_paca->kvm_hstate.kvm_vcpu = vcpu;
@@ -72,40 +74,10 @@ void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
{
}
-static void kvmppc_vcpu_blocked(struct kvm_vcpu *vcpu);
-static void kvmppc_vcpu_unblocked(struct kvm_vcpu *vcpu);
-
-void kvmppc_vcpu_block(struct kvm_vcpu *vcpu)
-{
- u64 now;
- unsigned long dec_nsec;
-
- now = get_tb();
- if (now >= vcpu->arch.dec_expires && !kvmppc_core_pending_dec(vcpu))
- kvmppc_core_queue_dec(vcpu);
- if (vcpu->arch.pending_exceptions)
- return;
- if (vcpu->arch.dec_expires != ~(u64)0) {
- dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC /
- tb_ticks_per_sec;
- hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
- HRTIMER_MODE_REL);
- }
-
- kvmppc_vcpu_blocked(vcpu);
-
- kvm_vcpu_block(vcpu);
- vcpu->stat.halt_wakeup++;
-
- if (vcpu->arch.dec_expires != ~(u64)0)
- hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
-
- kvmppc_vcpu_unblocked(vcpu);
-}
-
void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
{
vcpu->arch.shregs.msr = msr;
+ kvmppc_end_cede(vcpu);
}
void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
@@ -257,15 +229,6 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
switch (req) {
case H_CEDE:
- vcpu->arch.shregs.msr |= MSR_EE;
- vcpu->arch.ceded = 1;
- smp_mb();
- if (!vcpu->arch.prodded)
- kvmppc_vcpu_block(vcpu);
- else
- vcpu->arch.prodded = 0;
- smp_mb();
- vcpu->arch.ceded = 0;
break;
case H_PROD:
target = kvmppc_get_gpr(vcpu, 4);
@@ -388,20 +351,6 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
break;
}
-
- if (!(r & RESUME_HOST)) {
- /* To avoid clobbering exit_reason, only check for signals if
- * we aren't already exiting to userspace for some other
- * reason. */
- if (signal_pending(tsk)) {
- vcpu->stat.signal_exits++;
- run->exit_reason = KVM_EXIT_INTR;
- r = -EINTR;
- } else {
- kvmppc_core_deliver_interrupts(vcpu);
- }
- }
-
return r;
}
@@ -479,13 +428,9 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
kvmppc_mmu_book3s_hv_init(vcpu);
/*
- * Some vcpus may start out in stopped state. If we initialize
- * them to busy-in-host state they will stop other vcpus in the
- * vcore from running. Instead we initialize them to blocked
- * state, effectively considering them to be stopped until we
- * see the first run ioctl for them.
+ * We consider the vcpu stopped until we see the first run ioctl for it.
*/
- vcpu->arch.state = KVMPPC_VCPU_BLOCKED;
+ vcpu->arch.state = KVMPPC_VCPU_STOPPED;
init_waitqueue_head(&vcpu->arch.cpu_run);
@@ -496,6 +441,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
if (vcore) {
INIT_LIST_HEAD(&vcore->runnable_threads);
spin_lock_init(&vcore->lock);
+ init_waitqueue_head(&vcore->wq);
}
kvm->arch.vcores[core] = vcore;
}
@@ -506,10 +452,12 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
spin_lock(&vcore->lock);
++vcore->num_threads;
- ++vcore->n_blocked;
spin_unlock(&vcore->lock);
vcpu->arch.vcore = vcore;
+ vcpu->arch.cpu_type = KVM_CPU_3S_64;
+ kvmppc_sanity_check(vcpu);
+
return vcpu;
free_vcpu:
@@ -524,30 +472,31 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
kfree(vcpu);
}
-static void kvmppc_vcpu_blocked(struct kvm_vcpu *vcpu)
+static void kvmppc_set_timer(struct kvm_vcpu *vcpu)
{
- struct kvmppc_vcore *vc = vcpu->arch.vcore;
+ unsigned long dec_nsec, now;
- spin_lock(&vc->lock);
- vcpu->arch.state = KVMPPC_VCPU_BLOCKED;
- ++vc->n_blocked;
- if (vc->n_runnable > 0 &&
- vc->n_runnable + vc->n_blocked == vc->num_threads) {
- vcpu = list_first_entry(&vc->runnable_threads, struct kvm_vcpu,
- arch.run_list);
- wake_up(&vcpu->arch.cpu_run);
+ now = get_tb();
+ if (now > vcpu->arch.dec_expires) {
+ /* decrementer has already gone negative */
+ kvmppc_core_queue_dec(vcpu);
+ kvmppc_core_deliver_interrupts(vcpu);
+ return;
}
- spin_unlock(&vc->lock);
+ dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC
+ / tb_ticks_per_sec;
+ hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
+ HRTIMER_MODE_REL);
+ vcpu->arch.timer_running = 1;
}
-static void kvmppc_vcpu_unblocked(struct kvm_vcpu *vcpu)
+static void kvmppc_end_cede(struct kvm_vcpu *vcpu)
{
- struct kvmppc_vcore *vc = vcpu->arch.vcore;
-
- spin_lock(&vc->lock);
- vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
- --vc->n_blocked;
- spin_unlock(&vc->lock);
+ vcpu->arch.ceded = 0;
+ if (vcpu->arch.timer_running) {
+ hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+ vcpu->arch.timer_running = 0;
+ }
}
extern int __kvmppc_vcore_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
@@ -562,6 +511,7 @@ static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
return;
vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
--vc->n_runnable;
+ ++vc->n_busy;
/* decrement the physical thread id of each following vcpu */
v = vcpu;
list_for_each_entry_continue(v, &vc->runnable_threads, arch.run_list)
@@ -575,15 +525,20 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu)
struct paca_struct *tpaca;
struct kvmppc_vcore *vc = vcpu->arch.vcore;
+ if (vcpu->arch.timer_running) {
+ hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+ vcpu->arch.timer_running = 0;
+ }
cpu = vc->pcpu + vcpu->arch.ptid;
tpaca = &paca[cpu];
tpaca->kvm_hstate.kvm_vcpu = vcpu;
tpaca->kvm_hstate.kvm_vcore = vc;
+ tpaca->kvm_hstate.napping = 0;
+ vcpu->cpu = vc->pcpu;
smp_wmb();
#ifdef CONFIG_PPC_ICP_NATIVE
if (vcpu->arch.ptid) {
tpaca->cpu_start = 0x80;
- tpaca->kvm_hstate.in_guest = KVM_GUEST_MODE_GUEST;
wmb();
xics_wake_cpu(cpu);
++vc->n_woken;
@@ -631,9 +586,10 @@ static int on_primary_thread(void)
*/
static int kvmppc_run_core(struct kvmppc_vcore *vc)
{
- struct kvm_vcpu *vcpu, *vnext;
+ struct kvm_vcpu *vcpu, *vcpu0, *vnext;
long ret;
u64 now;
+ int ptid;
/* don't start if any threads have a signal pending */
list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
@@ -652,29 +608,50 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
goto out;
}
+ /*
+ * Assign physical thread IDs, first to non-ceded vcpus
+ * and then to ceded ones.
+ */
+ ptid = 0;
+ vcpu0 = NULL;
+ list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
+ if (!vcpu->arch.ceded) {
+ if (!ptid)
+ vcpu0 = vcpu;
+ vcpu->arch.ptid = ptid++;
+ }
+ }
+ if (!vcpu0)
+ return 0; /* nothing to run */
+ list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+ if (vcpu->arch.ceded)
+ vcpu->arch.ptid = ptid++;
+
vc->n_woken = 0;
vc->nap_count = 0;
vc->entry_exit_count = 0;
- vc->vcore_running = 1;
+ vc->vcore_state = VCORE_RUNNING;
vc->in_guest = 0;
vc->pcpu = smp_processor_id();
+ vc->napping_threads = 0;
list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
kvmppc_start_thread(vcpu);
- vcpu = list_first_entry(&vc->runnable_threads, struct kvm_vcpu,
- arch.run_list);
+ preempt_disable();
spin_unlock(&vc->lock);
- preempt_disable();
kvm_guest_enter();
- __kvmppc_vcore_entry(NULL, vcpu);
+ __kvmppc_vcore_entry(NULL, vcpu0);
- /* wait for secondary threads to finish writing their state to memory */
spin_lock(&vc->lock);
+ /* disable sending of IPIs on virtual external irqs */
+ list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+ vcpu->cpu = -1;
+ /* wait for secondary threads to finish writing their state to memory */
if (vc->nap_count < vc->n_woken)
kvmppc_wait_for_nap(vc);
/* prevent other vcpu threads from doing kvmppc_start_thread() now */
- vc->vcore_running = 2;
+ vc->vcore_state = VCORE_EXITING;
spin_unlock(&vc->lock);
/* make sure updates to secondary vcpu structs are visible now */
@@ -690,22 +667,26 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
if (now < vcpu->arch.dec_expires &&
kvmppc_core_pending_dec(vcpu))
kvmppc_core_dequeue_dec(vcpu);
- if (!vcpu->arch.trap) {
- if (signal_pending(vcpu->arch.run_task)) {
- vcpu->arch.kvm_run->exit_reason = KVM_EXIT_INTR;
- vcpu->arch.ret = -EINTR;
- }
- continue; /* didn't get to run */
- }
- ret = kvmppc_handle_exit(vcpu->arch.kvm_run, vcpu,
- vcpu->arch.run_task);
+
+ ret = RESUME_GUEST;
+ if (vcpu->arch.trap)
+ ret = kvmppc_handle_exit(vcpu->arch.kvm_run, vcpu,
+ vcpu->arch.run_task);
+
vcpu->arch.ret = ret;
vcpu->arch.trap = 0;
+
+ if (vcpu->arch.ceded) {
+ if (ret != RESUME_GUEST)
+ kvmppc_end_cede(vcpu);
+ else
+ kvmppc_set_timer(vcpu);
+ }
}
spin_lock(&vc->lock);
out:
- vc->vcore_running = 0;
+ vc->vcore_state = VCORE_INACTIVE;
list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
arch.run_list) {
if (vcpu->arch.ret != RESUME_GUEST) {
@@ -717,82 +698,130 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
return 1;
}
-static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+/*
+ * Wait for some other vcpu thread to execute us, and
+ * wake us up when we need to handle something in the host.
+ */
+static void kvmppc_wait_for_exec(struct kvm_vcpu *vcpu, int wait_state)
{
- int ptid;
- int wait_state;
- struct kvmppc_vcore *vc;
DEFINE_WAIT(wait);
- /* No need to go into the guest when all we do is going out */
- if (signal_pending(current)) {
- kvm_run->exit_reason = KVM_EXIT_INTR;
- return -EINTR;
+ prepare_to_wait(&vcpu->arch.cpu_run, &wait, wait_state);
+ if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE)
+ schedule();
+ finish_wait(&vcpu->arch.cpu_run, &wait);
+}
+
+/*
+ * All the vcpus in this vcore are idle, so wait for a decrementer
+ * or external interrupt to one of the vcpus. vc->lock is held.
+ */
+static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
+{
+ DEFINE_WAIT(wait);
+ struct kvm_vcpu *v;
+ int all_idle = 1;
+
+ prepare_to_wait(&vc->wq, &wait, TASK_INTERRUPTIBLE);
+ vc->vcore_state = VCORE_SLEEPING;
+ spin_unlock(&vc->lock);
+ list_for_each_entry(v, &vc->runnable_threads, arch.run_list) {
+ if (!v->arch.ceded || v->arch.pending_exceptions) {
+ all_idle = 0;
+ break;
+ }
}
+ if (all_idle)
+ schedule();
+ finish_wait(&vc->wq, &wait);
+ spin_lock(&vc->lock);
+ vc->vcore_state = VCORE_INACTIVE;
+}
- /* On PPC970, check that we have an RMA region */
- if (!vcpu->kvm->arch.rma && cpu_has_feature(CPU_FTR_ARCH_201))
- return -EPERM;
+static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+ int n_ceded;
+ int prev_state;
+ struct kvmppc_vcore *vc;
+ struct kvm_vcpu *v, *vn;
kvm_run->exit_reason = 0;
vcpu->arch.ret = RESUME_GUEST;
vcpu->arch.trap = 0;
- flush_fp_to_thread(current);
- flush_altivec_to_thread(current);
- flush_vsx_to_thread(current);
-
/*
* Synchronize with other threads in this virtual core
*/
vc = vcpu->arch.vcore;
spin_lock(&vc->lock);
- /* This happens the first time this is called for a vcpu */
- if (vcpu->arch.state == KVMPPC_VCPU_BLOCKED)
- --vc->n_blocked;
- vcpu->arch.state = KVMPPC_VCPU_RUNNABLE;
- ptid = vc->n_runnable;
+ vcpu->arch.ceded = 0;
vcpu->arch.run_task = current;
vcpu->arch.kvm_run = kvm_run;
- vcpu->arch.ptid = ptid;
+ prev_state = vcpu->arch.state;
+ vcpu->arch.state = KVMPPC_VCPU_RUNNABLE;
list_add_tail(&vcpu->arch.run_list, &vc->runnable_threads);
++vc->n_runnable;
- wait_state = TASK_INTERRUPTIBLE;
- while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
- if (signal_pending(current)) {
- if (!vc->vcore_running) {
- kvm_run->exit_reason = KVM_EXIT_INTR;
- vcpu->arch.ret = -EINTR;
- break;
- }
- /* have to wait for vcore to stop executing guest */
- wait_state = TASK_UNINTERRUPTIBLE;
- smp_send_reschedule(vc->pcpu);
+ /*
+ * This happens the first time this is called for a vcpu.
+ * If the vcore is already running, we may be able to start
+ * this thread straight away and have it join in.
+ */
+ if (prev_state == KVMPPC_VCPU_STOPPED) {
+ if (vc->vcore_state == VCORE_RUNNING &&
+ VCORE_EXIT_COUNT(vc) == 0) {
+ vcpu->arch.ptid = vc->n_runnable - 1;
+ kvmppc_start_thread(vcpu);
}
- if (!vc->vcore_running &&
- vc->n_runnable + vc->n_blocked == vc->num_threads) {
- /* we can run now */
- if (kvmppc_run_core(vc))
- continue;
- }
+ } else if (prev_state == KVMPPC_VCPU_BUSY_IN_HOST)
+ --vc->n_busy;
- if (vc->vcore_running == 1 && VCORE_EXIT_COUNT(vc) == 0)
- kvmppc_start_thread(vcpu);
+ while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
+ !signal_pending(current)) {
+ if (vc->n_busy || vc->vcore_state != VCORE_INACTIVE) {
+ spin_unlock(&vc->lock);
+ kvmppc_wait_for_exec(vcpu, TASK_INTERRUPTIBLE);
+ spin_lock(&vc->lock);
+ continue;
+ }
+ n_ceded = 0;
+ list_for_each_entry(v, &vc->runnable_threads, arch.run_list)
+ n_ceded += v->arch.ceded;
+ if (n_ceded == vc->n_runnable)
+ kvmppc_vcore_blocked(vc);
+ else
+ kvmppc_run_core(vc);
+
+ list_for_each_entry_safe(v, vn, &vc->runnable_threads,
+ arch.run_list) {
+ kvmppc_core_deliver_interrupts(v);
+ if (signal_pending(v->arch.run_task)) {
+ kvmppc_remove_runnable(vc, v);
+ v->stat.signal_exits++;
+ v->arch.kvm_run->exit_reason = KVM_EXIT_INTR;
+ v->arch.ret = -EINTR;
+ wake_up(&v->arch.cpu_run);
+ }
+ }
+ }
- /* wait for other threads to come in, or wait for vcore */
- prepare_to_wait(&vcpu->arch.cpu_run, &wait, wait_state);
- spin_unlock(&vc->lock);
- schedule();
- finish_wait(&vcpu->arch.cpu_run, &wait);
- spin_lock(&vc->lock);
+ if (signal_pending(current)) {
+ if (vc->vcore_state == VCORE_RUNNING ||
+ vc->vcore_state == VCORE_EXITING) {
+ spin_unlock(&vc->lock);
+ kvmppc_wait_for_exec(vcpu, TASK_UNINTERRUPTIBLE);
+ spin_lock(&vc->lock);
+ }
+ if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
+ kvmppc_remove_runnable(vc, vcpu);
+ vcpu->stat.signal_exits++;
+ kvm_run->exit_reason = KVM_EXIT_INTR;
+ vcpu->arch.ret = -EINTR;
+ }
}
- if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE)
- kvmppc_remove_runnable(vc, vcpu);
spin_unlock(&vc->lock);
-
return vcpu->arch.ret;
}
@@ -800,6 +829,26 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
{
int r;
+ if (!vcpu->arch.sane) {
+ run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+ return -EINVAL;
+ }
+
+ /* No need to go into the guest when all we'll do is come back out */
+ if (signal_pending(current)) {
+ run->exit_reason = KVM_EXIT_INTR;
+ return -EINTR;
+ }
+
+ /* On PPC970, check that we have an RMA region */
+ if (!vcpu->kvm->arch.rma && cpu_has_feature(CPU_FTR_ARCH_201))
+ return -EPERM;
+
+ flush_fp_to_thread(current);
+ flush_altivec_to_thread(current);
+ flush_vsx_to_thread(current);
+ vcpu->arch.wqp = &vcpu->arch.vcore->wq;
+
do {
r = kvmppc_run_vcpu(run, vcpu);
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index fcfe6b055558..bacb0cfa3602 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -110,39 +110,6 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
return H_SUCCESS;
}
-static unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
- unsigned long pte_index)
-{
- unsigned long rb, va_low;
-
- rb = (v & ~0x7fUL) << 16; /* AVA field */
- va_low = pte_index >> 3;
- if (v & HPTE_V_SECONDARY)
- va_low = ~va_low;
- /* xor vsid from AVA */
- if (!(v & HPTE_V_1TB_SEG))
- va_low ^= v >> 12;
- else
- va_low ^= v >> 24;
- va_low &= 0x7ff;
- if (v & HPTE_V_LARGE) {
- rb |= 1; /* L field */
- if (cpu_has_feature(CPU_FTR_ARCH_206) &&
- (r & 0xff000)) {
- /* non-16MB large page, must be 64k */
- /* (masks depend on page size) */
- rb |= 0x1000; /* page encoding in LP field */
- rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
- rb |= (va_low & 0xfe); /* AVAL field (P7 doesn't seem to care) */
- }
- } else {
- /* 4kB page */
- rb |= (va_low & 0x7ff) << 12; /* remaining 11b of VA */
- }
- rb |= (v >> 54) & 0x300; /* B field */
- return rb;
-}
-
#define LOCK_TOKEN (*(u32 *)(&get_paca()->lock_token))
static inline int try_lock_tlbie(unsigned int *lock)
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index de2950135e6e..f422231d9235 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -20,7 +20,10 @@
#include <asm/ppc_asm.h>
#include <asm/kvm_asm.h>
#include <asm/reg.h>
+#include <asm/mmu.h>
#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/hvcall.h>
#include <asm/asm-offsets.h>
#include <asm/exception-64s.h>
@@ -49,7 +52,7 @@ kvmppc_skip_Hinterrupt:
b .
/*
- * Call kvmppc_handler_trampoline_enter in real mode.
+ * Call kvmppc_hv_entry in real mode.
* Must be called with interrupts hard-disabled.
*
* Input Registers:
@@ -89,6 +92,12 @@ _GLOBAL(kvmppc_hv_entry_trampoline)
kvm_start_guest:
ld r1,PACAEMERGSP(r13)
subi r1,r1,STACK_FRAME_OVERHEAD
+ ld r2,PACATOC(r13)
+
+ /* were we napping due to cede? */
+ lbz r0,HSTATE_NAPPING(r13)
+ cmpwi r0,0
+ bne kvm_end_cede
/* get vcpu pointer */
ld r4, HSTATE_KVM_VCPU(r13)
@@ -276,15 +285,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
cmpwi r0,0
beq 20b
- /* Set LPCR. Set the MER bit if there is a pending external irq. */
+ /* Set LPCR and RMOR. */
10: ld r8,KVM_LPCR(r9)
- ld r0,VCPU_PENDING_EXC(r4)
- li r7,(1 << BOOK3S_IRQPRIO_EXTERNAL)
- oris r7,r7,(1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h
- and. r0,r0,r7
- beq 11f
- ori r8,r8,LPCR_MER
-11: mtspr SPRN_LPCR,r8
+ mtspr SPRN_LPCR,r8
ld r8,KVM_RMOR(r9)
mtspr SPRN_RMOR,r8
isync
@@ -448,19 +451,50 @@ toc_tlbie_lock:
mtctr r6
mtxer r7
- /* Move SRR0 and SRR1 into the respective regs */
+kvmppc_cede_reentry: /* r4 = vcpu, r13 = paca */
ld r6, VCPU_SRR0(r4)
ld r7, VCPU_SRR1(r4)
- mtspr SPRN_SRR0, r6
- mtspr SPRN_SRR1, r7
-
ld r10, VCPU_PC(r4)
+ ld r11, VCPU_MSR(r4) /* r11 = vcpu->arch.msr & ~MSR_HV */
- ld r11, VCPU_MSR(r4) /* r10 = vcpu->arch.msr & ~MSR_HV */
rldicl r11, r11, 63 - MSR_HV_LG, 1
rotldi r11, r11, 1 + MSR_HV_LG
ori r11, r11, MSR_ME
+ /* Check if we can deliver an external or decrementer interrupt now */
+ ld r0,VCPU_PENDING_EXC(r4)
+ li r8,(1 << BOOK3S_IRQPRIO_EXTERNAL)
+ oris r8,r8,(1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h
+ and r0,r0,r8
+ cmpdi cr1,r0,0
+ andi. r0,r11,MSR_EE
+ beq cr1,11f
+BEGIN_FTR_SECTION
+ mfspr r8,SPRN_LPCR
+ ori r8,r8,LPCR_MER
+ mtspr SPRN_LPCR,r8
+ isync
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+ beq 5f
+ li r0,BOOK3S_INTERRUPT_EXTERNAL
+12: mr r6,r10
+ mr r10,r0
+ mr r7,r11
+ li r11,(MSR_ME << 1) | 1 /* synthesize MSR_SF | MSR_ME */
+ rotldi r11,r11,63
+ b 5f
+11: beq 5f
+ mfspr r0,SPRN_DEC
+ cmpwi r0,0
+ li r0,BOOK3S_INTERRUPT_DECREMENTER
+ blt 12b
+
+ /* Move SRR0 and SRR1 into the respective regs */
+5: mtspr SPRN_SRR0, r6
+ mtspr SPRN_SRR1, r7
+ li r0,0
+ stb r0,VCPU_CEDED(r4) /* cancel cede */
+
fast_guest_return:
mtspr SPRN_HSRR0,r10
mtspr SPRN_HSRR1,r11
@@ -574,21 +608,20 @@ kvmppc_interrupt:
/* See if this is something we can handle in real mode */
cmpwi r12,BOOK3S_INTERRUPT_SYSCALL
beq hcall_try_real_mode
-hcall_real_cont:
/* Check for mediated interrupts (could be done earlier really ...) */
BEGIN_FTR_SECTION
cmpwi r12,BOOK3S_INTERRUPT_EXTERNAL
bne+ 1f
- ld r5,VCPU_KVM(r9)
- ld r5,KVM_LPCR(r5)
andi. r0,r11,MSR_EE
beq 1f
+ mfspr r5,SPRN_LPCR
andi. r0,r5,LPCR_MER
bne bounce_ext_interrupt
1:
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+hcall_real_cont: /* r9 = vcpu, r12 = trap, r13 = paca */
/* Save DEC */
mfspr r5,SPRN_DEC
mftb r6
@@ -682,7 +715,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_201)
slbia
ptesync
-hdec_soon:
+hdec_soon: /* r9 = vcpu, r12 = trap, r13 = paca */
BEGIN_FTR_SECTION
b 32f
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
@@ -700,6 +733,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
addi r0,r3,0x100
stwcx. r0,0,r6
bne 41b
+ lwsync
/*
* At this point we have an interrupt that we have to pass
@@ -713,18 +747,39 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
* interrupt, since the other threads will already be on their
* way here in that case.
*/
+ cmpwi r3,0x100 /* Are we the first here? */
+ bge 43f
+ cmpwi r3,1 /* Are any other threads in the guest? */
+ ble 43f
cmpwi r12,BOOK3S_INTERRUPT_HV_DECREMENTER
beq 40f
- cmpwi r3,0x100 /* Are we the first here? */
- bge 40f
- cmpwi r3,1
- ble 40f
li r0,0
mtspr SPRN_HDEC,r0
40:
+ /*
+ * Send an IPI to any napping threads, since an HDEC interrupt
+ * doesn't wake CPUs up from nap.
+ */
+ lwz r3,VCORE_NAPPING_THREADS(r5)
+ lwz r4,VCPU_PTID(r9)
+ li r0,1
+ sldi r0,r0,r4
+ andc. r3,r3,r0 /* no sense IPI'ing ourselves */
+ beq 43f
+ mulli r4,r4,PACA_SIZE /* get paca for thread 0 */
+ subf r6,r4,r13
+42: andi. r0,r3,1
+ beq 44f
+ ld r8,HSTATE_XICS_PHYS(r6) /* get thread's XICS reg addr */
+ li r0,IPI_PRIORITY
+ li r7,XICS_QIRR
+ stbcix r0,r7,r8 /* trigger the IPI */
+44: srdi. r3,r3,1
+ addi r6,r6,PACA_SIZE
+ bne 42b
/* Secondary threads wait for primary to do partition switch */
- ld r4,VCPU_KVM(r9) /* pointer to struct kvm */
+43: ld r4,VCPU_KVM(r9) /* pointer to struct kvm */
ld r5,HSTATE_KVM_VCORE(r13)
lwz r3,VCPU_PTID(r9)
cmpwi r3,0
@@ -1077,7 +1132,6 @@ hcall_try_real_mode:
hcall_real_fallback:
li r12,BOOK3S_INTERRUPT_SYSCALL
ld r9, HSTATE_KVM_VCPU(r13)
- ld r11, VCPU_MSR(r9)
b hcall_real_cont
@@ -1139,7 +1193,7 @@ hcall_real_table:
.long 0 /* 0xd4 */
.long 0 /* 0xd8 */
.long 0 /* 0xdc */
- .long 0 /* 0xe0 */
+ .long .kvmppc_h_cede - hcall_real_table
.long 0 /* 0xe4 */
.long 0 /* 0xe8 */
.long 0 /* 0xec */
@@ -1168,7 +1222,8 @@ bounce_ext_interrupt:
mtspr SPRN_SRR0,r10
mtspr SPRN_SRR1,r11
li r10,BOOK3S_INTERRUPT_EXTERNAL
- LOAD_REG_IMMEDIATE(r11,MSR_SF | MSR_ME);
+ li r11,(MSR_ME << 1) | 1 /* synthesize MSR_SF | MSR_ME */
+ rotldi r11,r11,63
b fast_guest_return
_GLOBAL(kvmppc_h_set_dabr)
@@ -1177,6 +1232,178 @@ _GLOBAL(kvmppc_h_set_dabr)
li r3,0
blr
+_GLOBAL(kvmppc_h_cede)
+ ori r11,r11,MSR_EE
+ std r11,VCPU_MSR(r3)
+ li r0,1
+ stb r0,VCPU_CEDED(r3)
+ sync /* order setting ceded vs. testing prodded */
+ lbz r5,VCPU_PRODDED(r3)
+ cmpwi r5,0
+ bne 1f
+ li r0,0 /* set trap to 0 to say hcall is handled */
+ stw r0,VCPU_TRAP(r3)
+ li r0,H_SUCCESS
+ std r0,VCPU_GPR(r3)(r3)
+BEGIN_FTR_SECTION
+ b 2f /* just send it up to host on 970 */
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
+
+ /*
+ * Set our bit in the bitmask of napping threads unless all the
+ * other threads are already napping, in which case we send this
+ * up to the host.
+ */
+ ld r5,HSTATE_KVM_VCORE(r13)
+ lwz r6,VCPU_PTID(r3)
+ lwz r8,VCORE_ENTRY_EXIT(r5)
+ clrldi r8,r8,56
+ li r0,1
+ sld r0,r0,r6
+ addi r6,r5,VCORE_NAPPING_THREADS
+31: lwarx r4,0,r6
+ or r4,r4,r0
+ popcntw r7,r4
+ cmpw r7,r8
+ bge 2f
+ stwcx. r4,0,r6
+ bne 31b
+ li r0,1
+ stb r0,HSTATE_NAPPING(r13)
+ /* order napping_threads update vs testing entry_exit_count */
+ lwsync
+ mr r4,r3
+ lwz r7,VCORE_ENTRY_EXIT(r5)
+ cmpwi r7,0x100
+ bge 33f /* another thread already exiting */
+
+/*
+ * Although not specifically required by the architecture, POWER7
+ * preserves the following registers in nap mode, even if an SMT mode
+ * switch occurs: SLB entries, PURR, SPURR, AMOR, UAMOR, AMR, SPRG0-3,
+ * DAR, DSISR, DABR, DABRX, DSCR, PMCx, MMCRx, SIAR, SDAR.
+ */
+ /* Save non-volatile GPRs */
+ std r14, VCPU_GPR(r14)(r3)
+ std r15, VCPU_GPR(r15)(r3)
+ std r16, VCPU_GPR(r16)(r3)
+ std r17, VCPU_GPR(r17)(r3)
+ std r18, VCPU_GPR(r18)(r3)
+ std r19, VCPU_GPR(r19)(r3)
+ std r20, VCPU_GPR(r20)(r3)
+ std r21, VCPU_GPR(r21)(r3)
+ std r22, VCPU_GPR(r22)(r3)
+ std r23, VCPU_GPR(r23)(r3)
+ std r24, VCPU_GPR(r24)(r3)
+ std r25, VCPU_GPR(r25)(r3)
+ std r26, VCPU_GPR(r26)(r3)
+ std r27, VCPU_GPR(r27)(r3)
+ std r28, VCPU_GPR(r28)(r3)
+ std r29, VCPU_GPR(r29)(r3)
+ std r30, VCPU_GPR(r30)(r3)
+ std r31, VCPU_GPR(r31)(r3)
+
+ /* save FP state */
+ bl .kvmppc_save_fp
+
+ /*
+ * Take a nap until a decrementer or external interrupt occurs,
+ * with PECE1 (wake on decr) and PECE0 (wake on external) set in LPCR
+ */
+ li r0,0x80
+ stb r0,PACAPROCSTART(r13)
+ mfspr r5,SPRN_LPCR
+ ori r5,r5,LPCR_PECE0 | LPCR_PECE1
+ mtspr SPRN_LPCR,r5
+ isync
+ li r0, 0
+ std r0, HSTATE_SCRATCH0(r13)
+ ptesync
+ ld r0, HSTATE_SCRATCH0(r13)
+1: cmpd r0, r0
+ bne 1b
+ nap
+ b .
+
+kvm_end_cede:
+ /* Woken by external or decrementer interrupt */
+ ld r1, HSTATE_HOST_R1(r13)
+ ld r2, PACATOC(r13)
+
+ /* If we're a secondary thread and we got here by an IPI, ack it */
+ ld r4,HSTATE_KVM_VCPU(r13)
+ lwz r3,VCPU_PTID(r4)
+ cmpwi r3,0
+ beq 27f
+ mfspr r3,SPRN_SRR1
+ rlwinm r3,r3,44-31,0x7 /* extract wake reason field */
+ cmpwi r3,4 /* was it an external interrupt? */
+ bne 27f
+ ld r5, HSTATE_XICS_PHYS(r13)
+ li r0,0xff
+ li r6,XICS_QIRR
+ li r7,XICS_XIRR
+ lwzcix r8,r5,r7 /* ack the interrupt */
+ sync
+ stbcix r0,r5,r6 /* clear it */
+ stwcix r8,r5,r7 /* EOI it */
+27:
+ /* load up FP state */
+ bl kvmppc_load_fp
+
+ /* Load NV GPRS */
+ ld r14, VCPU_GPR(r14)(r4)
+ ld r15, VCPU_GPR(r15)(r4)
+ ld r16, VCPU_GPR(r16)(r4)
+ ld r17, VCPU_GPR(r17)(r4)
+ ld r18, VCPU_GPR(r18)(r4)
+ ld r19, VCPU_GPR(r19)(r4)
+ ld r20, VCPU_GPR(r20)(r4)
+ ld r21, VCPU_GPR(r21)(r4)
+ ld r22, VCPU_GPR(r22)(r4)
+ ld r23, VCPU_GPR(r23)(r4)
+ ld r24, VCPU_GPR(r24)(r4)
+ ld r25, VCPU_GPR(r25)(r4)
+ ld r26, VCPU_GPR(r26)(r4)
+ ld r27, VCPU_GPR(r27)(r4)
+ ld r28, VCPU_GPR(r28)(r4)
+ ld r29, VCPU_GPR(r29)(r4)
+ ld r30, VCPU_GPR(r30)(r4)
+ ld r31, VCPU_GPR(r31)(r4)
+
+ /* clear our bit in vcore->napping_threads */
+33: ld r5,HSTATE_KVM_VCORE(r13)
+ lwz r3,VCPU_PTID(r4)
+ li r0,1
+ sld r0,r0,r3
+ addi r6,r5,VCORE_NAPPING_THREADS
+32: lwarx r7,0,r6
+ andc r7,r7,r0
+ stwcx. r7,0,r6
+ bne 32b
+ li r0,0
+ stb r0,HSTATE_NAPPING(r13)
+
+ /* see if any other thread is already exiting */
+ lwz r0,VCORE_ENTRY_EXIT(r5)
+ cmpwi r0,0x100
+ blt kvmppc_cede_reentry /* if not go back to guest */
+
+ /* some threads are exiting, so go to the guest exit path */
+ b hcall_real_fallback
+
+ /* cede when already previously prodded case */
+1: li r0,0
+ stb r0,VCPU_PRODDED(r3)
+ sync /* order testing prodded vs. clearing ceded */
+ stb r0,VCPU_CEDED(r3)
+ li r3,H_SUCCESS
+ blr
+
+ /* we've ceded but we want to give control to the host */
+2: li r3,H_TOO_HARD
+ blr
+
secondary_too_late:
ld r5,HSTATE_KVM_VCORE(r13)
HMT_LOW
@@ -1194,14 +1421,20 @@ secondary_too_late:
slbmte r6,r5
1: addi r11,r11,16
.endr
- b 50f
secondary_nap:
- /* Clear any pending IPI */
-50: ld r5, HSTATE_XICS_PHYS(r13)
+ /* Clear any pending IPI - assume we're a secondary thread */
+ ld r5, HSTATE_XICS_PHYS(r13)
+ li r7, XICS_XIRR
+ lwzcix r3, r5, r7 /* ack any pending interrupt */
+ rlwinm. r0, r3, 0, 0xffffff /* any pending? */
+ beq 37f
+ sync
li r0, 0xff
li r6, XICS_QIRR
- stbcix r0, r5, r6
+ stbcix r0, r5, r6 /* clear the IPI */
+ stwcix r3, r5, r7 /* EOI it */
+37: sync
/* increment the nap count and then go to nap mode */
ld r4, HSTATE_KVM_VCORE(r13)
@@ -1211,13 +1444,12 @@ secondary_nap:
addi r3, r3, 1
stwcx. r3, 0, r4
bne 51b
- isync
+ li r3, LPCR_PECE0
mfspr r4, SPRN_LPCR
- li r0, LPCR_PECE
- andc r4, r4, r0
- ori r4, r4, LPCR_PECE0 /* exit nap on interrupt */
+ rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
mtspr SPRN_LPCR, r4
+ isync
li r0, 0
std r0, HSTATE_SCRATCH0(r13)
ptesync
diff --git a/arch/powerpc/kvm/book3s_interrupts.S b/arch/powerpc/kvm/book3s_interrupts.S
index c54b0e30cf3f..0a8515a5c042 100644
--- a/arch/powerpc/kvm/book3s_interrupts.S
+++ b/arch/powerpc/kvm/book3s_interrupts.S
@@ -29,27 +29,11 @@
#define ULONG_SIZE 8
#define FUNC(name) GLUE(.,name)
-#define GET_SHADOW_VCPU_R13
-
-#define DISABLE_INTERRUPTS \
- mfmsr r0; \
- rldicl r0,r0,48,1; \
- rotldi r0,r0,16; \
- mtmsrd r0,1; \
-
#elif defined(CONFIG_PPC_BOOK3S_32)
#define ULONG_SIZE 4
#define FUNC(name) name
-#define GET_SHADOW_VCPU_R13 \
- lwz r13, (THREAD + THREAD_KVM_SVCPU)(r2)
-
-#define DISABLE_INTERRUPTS \
- mfmsr r0; \
- rlwinm r0,r0,0,17,15; \
- mtmsr r0; \
-
#endif /* CONFIG_PPC_BOOK3S_XX */
@@ -108,44 +92,17 @@ kvm_start_entry:
kvm_start_lightweight:
- GET_SHADOW_VCPU_R13
- PPC_LL r3, VCPU_HIGHMEM_HANDLER(r4)
- PPC_STL r3, HSTATE_VMHANDLER(r13)
-
- PPC_LL r10, VCPU_SHADOW_MSR(r4) /* r10 = vcpu->arch.shadow_msr */
-
- DISABLE_INTERRUPTS
-
#ifdef CONFIG_PPC_BOOK3S_64
- /* Some guests may need to have dcbz set to 32 byte length.
- *
- * Usually we ensure that by patching the guest's instructions
- * to trap on dcbz and emulate it in the hypervisor.
- *
- * If we can, we should tell the CPU to use 32 byte dcbz though,
- * because that's a lot faster.
- */
-
PPC_LL r3, VCPU_HFLAGS(r4)
- rldicl. r3, r3, 0, 63 /* CR = ((r3 & 1) == 0) */
- beq no_dcbz32_on
-
- mfspr r3,SPRN_HID5
- ori r3, r3, 0x80 /* XXX HID5_dcbz32 = 0x80 */
- mtspr SPRN_HID5,r3
-
-no_dcbz32_on:
-
+ rldicl r3, r3, 0, 63 /* r3 &= 1 */
+ stb r3, HSTATE_RESTORE_HID5(r13)
#endif /* CONFIG_PPC_BOOK3S_64 */
- PPC_LL r6, VCPU_RMCALL(r4)
- mtctr r6
-
- PPC_LL r3, VCPU_TRAMPOLINE_ENTER(r4)
- LOAD_REG_IMMEDIATE(r4, MSR_KERNEL & ~(MSR_IR | MSR_DR))
+ PPC_LL r4, VCPU_SHADOW_MSR(r4) /* get shadow_msr */
/* Jump to segment patching handler and into our guest */
- bctr
+ bl FUNC(kvmppc_entry_trampoline)
+ nop
/*
* This is the handler in module memory. It gets jumped at from the
@@ -170,21 +127,6 @@ kvmppc_handler_highmem:
/* R7 = vcpu */
PPC_LL r7, GPR4(r1)
-#ifdef CONFIG_PPC_BOOK3S_64
-
- PPC_LL r5, VCPU_HFLAGS(r7)
- rldicl. r5, r5, 0, 63 /* CR = ((r5 & 1) == 0) */
- beq no_dcbz32_off
-
- li r4, 0
- mfspr r5,SPRN_HID5
- rldimi r5,r4,6,56
- mtspr SPRN_HID5,r5
-
-no_dcbz32_off:
-
-#endif /* CONFIG_PPC_BOOK3S_64 */
-
PPC_STL r14, VCPU_GPR(r14)(r7)
PPC_STL r15, VCPU_GPR(r15)(r7)
PPC_STL r16, VCPU_GPR(r16)(r7)
@@ -204,67 +146,6 @@ no_dcbz32_off:
PPC_STL r30, VCPU_GPR(r30)(r7)
PPC_STL r31, VCPU_GPR(r31)(r7)
- /* Restore host msr -> SRR1 */
- PPC_LL r6, VCPU_HOST_MSR(r7)
-
- /*
- * For some interrupts, we need to call the real Linux
- * handler, so it can do work for us. This has to happen
- * as if the interrupt arrived from the kernel though,
- * so let's fake it here where most state is restored.
- *
- * Call Linux for hardware interrupts/decrementer
- * r3 = address of interrupt handler (exit reason)
- */
-
- cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL
- beq call_linux_handler
- cmpwi r12, BOOK3S_INTERRUPT_DECREMENTER
- beq call_linux_handler
- cmpwi r12, BOOK3S_INTERRUPT_PERFMON
- beq call_linux_handler
-
- /* Back to EE=1 */
- mtmsr r6
- sync
- b kvm_return_point
-
-call_linux_handler:
-
- /*
- * If we land here we need to jump back to the handler we
- * came from.
- *
- * We have a page that we can access from real mode, so let's
- * jump back to that and use it as a trampoline to get back into the
- * interrupt handler!
- *
- * R3 still contains the exit code,
- * R5 VCPU_HOST_RETIP and
- * R6 VCPU_HOST_MSR
- */
-
- /* Restore host IP -> SRR0 */
- PPC_LL r5, VCPU_HOST_RETIP(r7)
-
- /* XXX Better move to a safe function?
- * What if we get an HTAB flush in between mtsrr0 and mtsrr1? */
-
- mtlr r12
-
- PPC_LL r4, VCPU_TRAMPOLINE_LOWMEM(r7)
- mtsrr0 r4
- LOAD_REG_IMMEDIATE(r3, MSR_KERNEL & ~(MSR_IR | MSR_DR))
- mtsrr1 r3
-
- RFI
-
-.global kvm_return_point
-kvm_return_point:
-
- /* Jump back to lightweight entry if we're supposed to */
- /* go back into the guest */
-
/* Pass the exit number as 3rd argument to kvmppc_handle_exit */
mr r5, r12
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 0c0d3f274437..d417511abfb1 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -150,16 +150,22 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
#ifdef CONFIG_PPC_BOOK3S_64
if ((pvr >= 0x330000) && (pvr < 0x70330000)) {
kvmppc_mmu_book3s_64_init(vcpu);
- to_book3s(vcpu)->hior = 0xfff00000;
+ if (!to_book3s(vcpu)->hior_sregs)
+ to_book3s(vcpu)->hior = 0xfff00000;
to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
+ vcpu->arch.cpu_type = KVM_CPU_3S_64;
} else
#endif
{
kvmppc_mmu_book3s_32_init(vcpu);
- to_book3s(vcpu)->hior = 0;
+ if (!to_book3s(vcpu)->hior_sregs)
+ to_book3s(vcpu)->hior = 0;
to_book3s(vcpu)->msr_mask = 0xffffffffULL;
+ vcpu->arch.cpu_type = KVM_CPU_3S_32;
}
+ kvmppc_sanity_check(vcpu);
+
/* If we are in hypervisor level on 970, we can tell the CPU to
* treat DCBZ as 32 bytes store */
vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32;
@@ -646,7 +652,27 @@ program_interrupt:
break;
}
case BOOK3S_INTERRUPT_SYSCALL:
- if (vcpu->arch.osi_enabled &&
+ if (vcpu->arch.papr_enabled &&
+ (kvmppc_get_last_inst(vcpu) == 0x44000022) &&
+ !(vcpu->arch.shared->msr & MSR_PR)) {
+ /* SC 1 papr hypercalls */
+ ulong cmd = kvmppc_get_gpr(vcpu, 3);
+ int i;
+
+ if (kvmppc_h_pr(vcpu, cmd) == EMULATE_DONE) {
+ r = RESUME_GUEST;
+ break;
+ }
+
+ run->papr_hcall.nr = cmd;
+ for (i = 0; i < 9; ++i) {
+ ulong gpr = kvmppc_get_gpr(vcpu, 4 + i);
+ run->papr_hcall.args[i] = gpr;
+ }
+ run->exit_reason = KVM_EXIT_PAPR_HCALL;
+ vcpu->arch.hcall_needed = 1;
+ r = RESUME_HOST;
+ } else if (vcpu->arch.osi_enabled &&
(((u32)kvmppc_get_gpr(vcpu, 3)) == OSI_SC_MAGIC_R3) &&
(((u32)kvmppc_get_gpr(vcpu, 4)) == OSI_SC_MAGIC_R4)) {
/* MOL hypercalls */
@@ -770,6 +796,9 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
}
}
+ if (sregs->u.s.flags & KVM_SREGS_S_HIOR)
+ sregs->u.s.hior = to_book3s(vcpu)->hior;
+
return 0;
}
@@ -806,6 +835,11 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
/* Flush the MMU after messing with the segments */
kvmppc_mmu_pte_flush(vcpu, 0, 0);
+ if (sregs->u.s.flags & KVM_SREGS_S_HIOR) {
+ to_book3s(vcpu)->hior_sregs = true;
+ to_book3s(vcpu)->hior = sregs->u.s.hior;
+ }
+
return 0;
}
@@ -841,8 +875,6 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
if (!p)
goto uninit_vcpu;
- vcpu->arch.host_retip = kvm_return_point;
- vcpu->arch.host_msr = mfmsr();
#ifdef CONFIG_PPC_BOOK3S_64
/* default to book3s_64 (970fx) */
vcpu->arch.pvr = 0x3C0301;
@@ -853,16 +885,6 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
vcpu->arch.slb_nr = 64;
- /* remember where some real-mode handlers are */
- vcpu->arch.trampoline_lowmem = __pa(kvmppc_handler_lowmem_trampoline);
- vcpu->arch.trampoline_enter = __pa(kvmppc_handler_trampoline_enter);
- vcpu->arch.highmem_handler = (ulong)kvmppc_handler_highmem;
-#ifdef CONFIG_PPC_BOOK3S_64
- vcpu->arch.rmcall = *(ulong*)kvmppc_rmcall;
-#else
- vcpu->arch.rmcall = (ulong)kvmppc_rmcall;
-#endif
-
vcpu->arch.shadow_msr = MSR_USER64;
err = kvmppc_mmu_init(vcpu);
@@ -908,6 +930,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
#endif
ulong ext_msr;
+ /* Check if we can run the vcpu at all */
+ if (!vcpu->arch.sane) {
+ kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+ return -EINVAL;
+ }
+
/* No need to go into the guest when all we do is going out */
if (signal_pending(current)) {
kvm_run->exit_reason = KVM_EXIT_INTR;
diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c
new file mode 100644
index 000000000000..b9589324797b
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_pr_papr.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2011. Freescale Inc. All rights reserved.
+ *
+ * Authors:
+ * Alexander Graf <agraf@suse.de>
+ * Paul Mackerras <paulus@samba.org>
+ *
+ * Description:
+ *
+ * Hypercall handling for running PAPR guests in PR KVM on Book 3S
+ * processors.
+ *
+ * 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 <asm/uaccess.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+
+static unsigned long get_pteg_addr(struct kvm_vcpu *vcpu, long pte_index)
+{
+ struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
+ unsigned long pteg_addr;
+
+ pte_index <<= 4;
+ pte_index &= ((1 << ((vcpu_book3s->sdr1 & 0x1f) + 11)) - 1) << 7 | 0x70;
+ pteg_addr = vcpu_book3s->sdr1 & 0xfffffffffffc0000ULL;
+ pteg_addr |= pte_index;
+
+ return pteg_addr;
+}
+
+static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
+{
+ long flags = kvmppc_get_gpr(vcpu, 4);
+ long pte_index = kvmppc_get_gpr(vcpu, 5);
+ unsigned long pteg[2 * 8];
+ unsigned long pteg_addr, i, *hpte;
+
+ pte_index &= ~7UL;
+ pteg_addr = get_pteg_addr(vcpu, pte_index);
+
+ copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg));
+ hpte = pteg;
+
+ if (likely((flags & H_EXACT) == 0)) {
+ pte_index &= ~7UL;
+ for (i = 0; ; ++i) {
+ if (i == 8)
+ return H_PTEG_FULL;
+ if ((*hpte & HPTE_V_VALID) == 0)
+ break;
+ hpte += 2;
+ }
+ } else {
+ i = kvmppc_get_gpr(vcpu, 5) & 7UL;
+ hpte += i * 2;
+ }
+
+ hpte[0] = kvmppc_get_gpr(vcpu, 6);
+ hpte[1] = kvmppc_get_gpr(vcpu, 7);
+ copy_to_user((void __user *)pteg_addr, pteg, sizeof(pteg));
+ kvmppc_set_gpr(vcpu, 3, H_SUCCESS);
+ kvmppc_set_gpr(vcpu, 4, pte_index | i);
+
+ return EMULATE_DONE;
+}
+
+static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
+{
+ unsigned long flags= kvmppc_get_gpr(vcpu, 4);
+ unsigned long pte_index = kvmppc_get_gpr(vcpu, 5);
+ unsigned long avpn = kvmppc_get_gpr(vcpu, 6);
+ unsigned long v = 0, pteg, rb;
+ unsigned long pte[2];
+
+ pteg = get_pteg_addr(vcpu, pte_index);
+ copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+
+ if ((pte[0] & HPTE_V_VALID) == 0 ||
+ ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != avpn) ||
+ ((flags & H_ANDCOND) && (pte[0] & avpn) != 0)) {
+ kvmppc_set_gpr(vcpu, 3, H_NOT_FOUND);
+ return EMULATE_DONE;
+ }
+
+ copy_to_user((void __user *)pteg, &v, sizeof(v));
+
+ rb = compute_tlbie_rb(pte[0], pte[1], pte_index);
+ vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
+
+ kvmppc_set_gpr(vcpu, 3, H_SUCCESS);
+ kvmppc_set_gpr(vcpu, 4, pte[0]);
+ kvmppc_set_gpr(vcpu, 5, pte[1]);
+
+ return EMULATE_DONE;
+}
+
+static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
+{
+ unsigned long flags = kvmppc_get_gpr(vcpu, 4);
+ unsigned long pte_index = kvmppc_get_gpr(vcpu, 5);
+ unsigned long avpn = kvmppc_get_gpr(vcpu, 6);
+ unsigned long rb, pteg, r, v;
+ unsigned long pte[2];
+
+ pteg = get_pteg_addr(vcpu, pte_index);
+ copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+
+ if ((pte[0] & HPTE_V_VALID) == 0 ||
+ ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != avpn)) {
+ kvmppc_set_gpr(vcpu, 3, H_NOT_FOUND);
+ return EMULATE_DONE;
+ }
+
+ v = pte[0];
+ r = pte[1];
+ r &= ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_HI |
+ HPTE_R_KEY_LO);
+ r |= (flags << 55) & HPTE_R_PP0;
+ r |= (flags << 48) & HPTE_R_KEY_HI;
+ r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
+
+ pte[1] = r;
+
+ rb = compute_tlbie_rb(v, r, pte_index);
+ vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
+ copy_to_user((void __user *)pteg, pte, sizeof(pte));
+
+ kvmppc_set_gpr(vcpu, 3, H_SUCCESS);
+
+ return EMULATE_DONE;
+}
+
+int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
+{
+ switch (cmd) {
+ case H_ENTER:
+ return kvmppc_h_pr_enter(vcpu);
+ case H_REMOVE:
+ return kvmppc_h_pr_remove(vcpu);
+ case H_PROTECT:
+ return kvmppc_h_pr_protect(vcpu);
+ case H_BULK_REMOVE:
+ /* We just flush all PTEs, so user space can
+ handle the HPT modifications */
+ kvmppc_mmu_pte_flush(vcpu, 0, 0);
+ break;
+ case H_CEDE:
+ kvm_vcpu_block(vcpu);
+ vcpu->stat.halt_wakeup++;
+ return EMULATE_DONE;
+ }
+
+ return EMULATE_FAIL;
+}
diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S
index c1f877c4a884..34187585c507 100644
--- a/arch/powerpc/kvm/book3s_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_rmhandlers.S
@@ -20,6 +20,7 @@
#include <asm/ppc_asm.h>
#include <asm/kvm_asm.h>
#include <asm/reg.h>
+#include <asm/mmu.h>
#include <asm/page.h>
#include <asm/asm-offsets.h>
@@ -35,10 +36,10 @@
#if defined(CONFIG_PPC_BOOK3S_64)
-#define LOAD_SHADOW_VCPU(reg) GET_PACA(reg)
-#define MSR_NOIRQ MSR_KERNEL & ~(MSR_IR | MSR_DR)
#define FUNC(name) GLUE(.,name)
+#define MTMSR_EERI(reg) mtmsrd (reg),1
+ .globl kvmppc_skip_interrupt
kvmppc_skip_interrupt:
/*
* Here all GPRs are unchanged from when the interrupt happened
@@ -51,6 +52,7 @@ kvmppc_skip_interrupt:
rfid
b .
+ .globl kvmppc_skip_Hinterrupt
kvmppc_skip_Hinterrupt:
/*
* Here all GPRs are unchanged from when the interrupt happened
@@ -65,8 +67,8 @@ kvmppc_skip_Hinterrupt:
#elif defined(CONFIG_PPC_BOOK3S_32)
-#define MSR_NOIRQ MSR_KERNEL
#define FUNC(name) name
+#define MTMSR_EERI(reg) mtmsr (reg)
.macro INTERRUPT_TRAMPOLINE intno
@@ -167,40 +169,24 @@ kvmppc_handler_skip_ins:
#endif
/*
- * This trampoline brings us back to a real mode handler
- *
- * Input Registers:
- *
- * R5 = SRR0
- * R6 = SRR1
- * LR = real-mode IP
+ * Call kvmppc_handler_trampoline_enter in real mode
*
+ * On entry, r4 contains the guest shadow MSR
*/
-.global kvmppc_handler_lowmem_trampoline
-kvmppc_handler_lowmem_trampoline:
-
- mtsrr0 r5
+_GLOBAL(kvmppc_entry_trampoline)
+ mfmsr r5
+ LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter)
+ toreal(r7)
+
+ li r9, MSR_RI
+ ori r9, r9, MSR_EE
+ andc r9, r5, r9 /* Clear EE and RI in MSR value */
+ li r6, MSR_IR | MSR_DR
+ ori r6, r6, MSR_EE
+ andc r6, r5, r6 /* Clear EE, DR and IR in MSR value */
+ MTMSR_EERI(r9) /* Clear EE and RI in MSR */
+ mtsrr0 r7 /* before we set srr0/1 */
mtsrr1 r6
- blr
-kvmppc_handler_lowmem_trampoline_end:
-
-/*
- * Call a function in real mode
- *
- * Input Registers:
- *
- * R3 = function
- * R4 = MSR
- * R5 = scratch register
- *
- */
-_GLOBAL(kvmppc_rmcall)
- LOAD_REG_IMMEDIATE(r5, MSR_NOIRQ)
- mtmsr r5 /* Disable relocation and interrupts, so mtsrr
- doesn't get interrupted */
- sync
- mtsrr0 r3
- mtsrr1 r4
RFI
#if defined(CONFIG_PPC_BOOK3S_32)
diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S
index aed32e517212..0676ae249b9f 100644
--- a/arch/powerpc/kvm/book3s_segment.S
+++ b/arch/powerpc/kvm/book3s_segment.S
@@ -23,6 +23,7 @@
#define GET_SHADOW_VCPU(reg) \
mr reg, r13
+#define MTMSR_EERI(reg) mtmsrd (reg),1
#elif defined(CONFIG_PPC_BOOK3S_32)
@@ -30,6 +31,7 @@
tophys(reg, r2); \
lwz reg, (THREAD + THREAD_KVM_SVCPU)(reg); \
tophys(reg, reg)
+#define MTMSR_EERI(reg) mtmsr (reg)
#endif
@@ -57,10 +59,12 @@ kvmppc_handler_trampoline_enter:
/* Required state:
*
* MSR = ~IR|DR
- * R13 = PACA
* R1 = host R1
* R2 = host R2
- * R10 = guest MSR
+ * R4 = guest shadow MSR
+ * R5 = normal host MSR
+ * R6 = current host MSR (EE, IR, DR off)
+ * LR = highmem guest exit code
* all other volatile GPRS = free
* SVCPU[CR] = guest CR
* SVCPU[XER] = guest XER
@@ -71,15 +75,15 @@ kvmppc_handler_trampoline_enter:
/* r3 = shadow vcpu */
GET_SHADOW_VCPU(r3)
+ /* Save guest exit handler address and MSR */
+ mflr r0
+ PPC_STL r0, HSTATE_VMHANDLER(r3)
+ PPC_STL r5, HSTATE_HOST_MSR(r3)
+
/* Save R1/R2 in the PACA (64-bit) or shadow_vcpu (32-bit) */
PPC_STL r1, HSTATE_HOST_R1(r3)
PPC_STL r2, HSTATE_HOST_R2(r3)
- /* Move SRR0 and SRR1 into the respective regs */
- PPC_LL r9, SVCPU_PC(r3)
- mtsrr0 r9
- mtsrr1 r10
-
/* Activate guest mode, so faults get handled by KVM */
li r11, KVM_GUEST_MODE_GUEST
stb r11, HSTATE_IN_GUEST(r3)
@@ -87,17 +91,46 @@ kvmppc_handler_trampoline_enter:
/* Switch to guest segment. This is subarch specific. */
LOAD_GUEST_SEGMENTS
+#ifdef CONFIG_PPC_BOOK3S_64
+ /* Some guests may need to have dcbz set to 32 byte length.
+ *
+ * Usually we ensure that by patching the guest's instructions
+ * to trap on dcbz and emulate it in the hypervisor.
+ *
+ * If we can, we should tell the CPU to use 32 byte dcbz though,
+ * because that's a lot faster.
+ */
+ lbz r0, HSTATE_RESTORE_HID5(r3)
+ cmpwi r0, 0
+ beq no_dcbz32_on
+
+ mfspr r0,SPRN_HID5
+ ori r0, r0, 0x80 /* XXX HID5_dcbz32 = 0x80 */
+ mtspr SPRN_HID5,r0
+no_dcbz32_on:
+
+#endif /* CONFIG_PPC_BOOK3S_64 */
+
/* Enter guest */
- PPC_LL r4, SVCPU_CTR(r3)
- PPC_LL r5, SVCPU_LR(r3)
- lwz r6, SVCPU_CR(r3)
- lwz r7, SVCPU_XER(r3)
+ PPC_LL r8, SVCPU_CTR(r3)
+ PPC_LL r9, SVCPU_LR(r3)
+ lwz r10, SVCPU_CR(r3)
+ lwz r11, SVCPU_XER(r3)
+
+ mtctr r8
+ mtlr r9
+ mtcr r10
+ mtxer r11
- mtctr r4
- mtlr r5
- mtcr r6
- mtxer r7
+ /* Move SRR0 and SRR1 into the respective regs */
+ PPC_LL r9, SVCPU_PC(r3)
+ /* First clear RI in our current MSR value */
+ li r0, MSR_RI
+ andc r6, r6, r0
+ MTMSR_EERI(r6)
+ mtsrr0 r9
+ mtsrr1 r4
PPC_LL r0, SVCPU_R0(r3)
PPC_LL r1, SVCPU_R1(r3)
@@ -213,11 +246,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
beq ld_last_inst
cmpwi r12, BOOK3S_INTERRUPT_PROGRAM
beq ld_last_inst
+ cmpwi r12, BOOK3S_INTERRUPT_SYSCALL
+ beq ld_last_prev_inst
cmpwi r12, BOOK3S_INTERRUPT_ALIGNMENT
beq- ld_last_inst
b no_ld_last_inst
+ld_last_prev_inst:
+ addi r3, r3, -4
+
ld_last_inst:
/* Save off the guest instruction we're at */
@@ -254,6 +292,43 @@ no_ld_last_inst:
/* Switch back to host MMU */
LOAD_HOST_SEGMENTS
+#ifdef CONFIG_PPC_BOOK3S_64
+
+ lbz r5, HSTATE_RESTORE_HID5(r13)
+ cmpwi r5, 0
+ beq no_dcbz32_off
+
+ li r4, 0
+ mfspr r5,SPRN_HID5
+ rldimi r5,r4,6,56
+ mtspr SPRN_HID5,r5
+
+no_dcbz32_off:
+
+#endif /* CONFIG_PPC_BOOK3S_64 */
+
+ /*
+ * For some interrupts, we need to call the real Linux
+ * handler, so it can do work for us. This has to happen
+ * as if the interrupt arrived from the kernel though,
+ * so let's fake it here where most state is restored.
+ *
+ * Having set up SRR0/1 with the address where we want
+ * to continue with relocation on (potentially in module
+ * space), we either just go straight there with rfi[d],
+ * or we jump to an interrupt handler with bctr if there
+ * is an interrupt to be handled first. In the latter
+ * case, the rfi[d] at the end of the interrupt handler
+ * will get us back to where we want to continue.
+ */
+
+ cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL
+ beq 1f
+ cmpwi r12, BOOK3S_INTERRUPT_DECREMENTER
+ beq 1f
+ cmpwi r12, BOOK3S_INTERRUPT_PERFMON
+1: mtctr r12
+
/* Register usage at this point:
*
* R1 = host R1
@@ -264,13 +339,15 @@ no_ld_last_inst:
*
*/
- /* RFI into the highmem handler */
- mfmsr r7
- ori r7, r7, MSR_IR|MSR_DR|MSR_RI|MSR_ME /* Enable paging */
- mtsrr1 r7
- /* Load highmem handler address */
+ PPC_LL r6, HSTATE_HOST_MSR(r13)
PPC_LL r8, HSTATE_VMHANDLER(r13)
+
+ /* Restore host msr -> SRR1 */
+ mtsrr1 r6
+ /* Load highmem handler address */
mtsrr0 r8
+ /* RFI into the highmem handler, or jump to interrupt handler */
+ beqctr
RFI
kvmppc_handler_trampoline_exit_end:
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index ee45fa01220e..bb6c988f010a 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -316,6 +316,11 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
{
int ret;
+ if (!vcpu->arch.sane) {
+ kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+ return -EINVAL;
+ }
+
local_irq_disable();
kvm_guest_enter();
ret = __kvmppc_vcpu_run(kvm_run, vcpu);
@@ -618,6 +623,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
int i;
+ int r;
vcpu->arch.pc = 0;
vcpu->arch.shared->msr = 0;
@@ -634,7 +640,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
kvmppc_init_timing_stats(vcpu);
- return kvmppc_core_vcpu_setup(vcpu);
+ r = kvmppc_core_vcpu_setup(vcpu);
+ kvmppc_sanity_check(vcpu);
+ return r;
}
int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index 797a7447c268..26d20903f2bc 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -73,6 +73,8 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
/* Since booke kvm only support one core, update all vcpus' PIR to 0 */
vcpu->vcpu_id = 0;
+ vcpu->arch.cpu_type = KVM_CPU_E500V2;
+
return 0;
}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index a107c9be0fb1..0d843c6ba315 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -39,12 +39,8 @@
int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
{
-#ifndef CONFIG_KVM_BOOK3S_64_HV
return !(v->arch.shared->msr & MSR_WE) ||
!!(v->arch.pending_exceptions);
-#else
- return !(v->arch.ceded) || !!(v->arch.pending_exceptions);
-#endif
}
int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
@@ -95,6 +91,31 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
return r;
}
+int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
+{
+ int r = false;
+
+ /* We have to know what CPU to virtualize */
+ if (!vcpu->arch.pvr)
+ goto out;
+
+ /* PAPR only works with book3s_64 */
+ if ((vcpu->arch.cpu_type != KVM_CPU_3S_64) && vcpu->arch.papr_enabled)
+ goto out;
+
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+ /* HV KVM can only do PAPR mode for now */
+ if (!vcpu->arch.papr_enabled)
+ goto out;
+#endif
+
+ r = true;
+
+out:
+ vcpu->arch.sane = r;
+ return r ? 0 : -EINVAL;
+}
+
int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
{
enum emulation_result er;
@@ -188,6 +209,8 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_PPC_BOOKE_SREGS:
#else
case KVM_CAP_PPC_SEGSTATE:
+ case KVM_CAP_PPC_HIOR:
+ case KVM_CAP_PPC_PAPR:
#endif
case KVM_CAP_PPC_UNSET_IRQ:
case KVM_CAP_PPC_IRQ_LEVEL:
@@ -258,6 +281,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
{
struct kvm_vcpu *vcpu;
vcpu = kvmppc_core_vcpu_create(kvm, id);
+ vcpu->arch.wqp = &vcpu->wq;
if (!IS_ERR(vcpu))
kvmppc_create_vcpu_debugfs(vcpu, id);
return vcpu;
@@ -289,8 +313,8 @@ static void kvmppc_decrementer_func(unsigned long data)
kvmppc_core_queue_dec(vcpu);
- if (waitqueue_active(&vcpu->wq)) {
- wake_up_interruptible(&vcpu->wq);
+ if (waitqueue_active(vcpu->arch.wqp)) {
+ wake_up_interruptible(vcpu->arch.wqp);
vcpu->stat.halt_wakeup++;
}
}
@@ -543,13 +567,15 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
{
- if (irq->irq == KVM_INTERRUPT_UNSET)
+ if (irq->irq == KVM_INTERRUPT_UNSET) {
kvmppc_core_dequeue_external(vcpu, irq);
- else
- kvmppc_core_queue_external(vcpu, irq);
+ return 0;
+ }
+
+ kvmppc_core_queue_external(vcpu, irq);
- if (waitqueue_active(&vcpu->wq)) {
- wake_up_interruptible(&vcpu->wq);
+ if (waitqueue_active(vcpu->arch.wqp)) {
+ wake_up_interruptible(vcpu->arch.wqp);
vcpu->stat.halt_wakeup++;
} else if (vcpu->cpu != -1) {
smp_send_reschedule(vcpu->cpu);
@@ -571,11 +597,18 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
r = 0;
vcpu->arch.osi_enabled = true;
break;
+ case KVM_CAP_PPC_PAPR:
+ r = 0;
+ vcpu->arch.papr_enabled = true;
+ break;
default:
r = -EINVAL;
break;
}
+ if (!r)
+ r = kvmppc_sanity_check(vcpu);
+
return r;
}
diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c
index fec13200868f..d7efdbf640c7 100644
--- a/arch/powerpc/mm/gup.c
+++ b/arch/powerpc/mm/gup.c
@@ -16,16 +16,6 @@
#ifdef __HAVE_ARCH_PTE_SPECIAL
-static inline void get_huge_page_tail(struct page *page)
-{
- /*
- * __split_huge_page_refcount() cannot run
- * from under us.
- */
- VM_BUG_ON(atomic_read(&page->_count) < 0);
- atomic_inc(&page->_count);
-}
-
/*
* The performance critical leaf functions are made noinline otherwise gcc
* inlines everything into a single function which results in too much
@@ -57,8 +47,6 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
put_page(page);
return 0;
}
- if (PageTail(page))
- get_huge_page_tail(page);
pages[*nr] = page;
(*nr)++;
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 0b9a5c1901b9..da5eb3885702 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -390,7 +390,7 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add
{
unsigned long mask;
unsigned long pte_end;
- struct page *head, *page;
+ struct page *head, *page, *tail;
pte_t pte;
int refs;
@@ -413,6 +413,7 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add
head = pte_page(pte);
page = head + ((addr & (sz-1)) >> PAGE_SHIFT);
+ tail = page;
do {
VM_BUG_ON(compound_head(page) != head);
pages[*nr] = page;
@@ -428,10 +429,20 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add
if (unlikely(pte_val(pte) != pte_val(*ptep))) {
/* Could be optimized better */
- while (*nr) {
- put_page(page);
- (*nr)--;
- }
+ *nr -= refs;
+ while (refs--)
+ put_page(head);
+ return 0;
+ }
+
+ /*
+ * Any tail page need their mapcount reference taken before we
+ * return.
+ */
+ while (refs--) {
+ if (PageTail(tail))
+ get_huge_page_tail(tail);
+ tail++;
}
return 1;
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index d733d7ca939c..b5d87067a58b 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -130,21 +130,21 @@ config 405GP
bool
select IBM405_ERR77
select IBM405_ERR51
- select IBM_NEW_EMAC_ZMII
+ select IBM_EMAC_ZMII
config 405EP
bool
config 405EX
bool
- select IBM_NEW_EMAC_EMAC4
- select IBM_NEW_EMAC_RGMII
+ select IBM_EMAC_EMAC4
+ select IBM_EMAC_RGMII
config 405EZ
bool
- select IBM_NEW_EMAC_NO_FLOW_CTRL
- select IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
- select IBM_NEW_EMAC_MAL_COMMON_ERR
+ select IBM_EMAC_NO_FLOW_CTRL
+ select IBM_EMAC_MAL_CLR_ICINTSTAT
+ select IBM_EMAC_MAL_COMMON_ERR
config 405GPR
bool
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index e958b6f48ec2..762322ce24a9 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -23,7 +23,7 @@ config BLUESTONE
default n
select PPC44x_SIMPLE
select APM821xx
- select IBM_NEW_EMAC_RGMII
+ select IBM_EMAC_RGMII
help
This option enables support for the APM APM821xx Evaluation board.
@@ -122,8 +122,8 @@ config CANYONLANDS
select PPC4xx_PCI_EXPRESS
select PCI_MSI
select PPC4xx_MSI
- select IBM_NEW_EMAC_RGMII
- select IBM_NEW_EMAC_ZMII
+ select IBM_EMAC_RGMII
+ select IBM_EMAC_ZMII
help
This option enables support for the AMCC PPC460EX evaluation board.
@@ -135,8 +135,8 @@ config GLACIER
select 460EX # Odd since it uses 460GT but the effects are the same
select PCI
select PPC4xx_PCI_EXPRESS
- select IBM_NEW_EMAC_RGMII
- select IBM_NEW_EMAC_ZMII
+ select IBM_EMAC_RGMII
+ select IBM_EMAC_ZMII
help
This option enables support for the AMCC PPC460GT evaluation board.
@@ -161,7 +161,7 @@ config EIGER
select 460SX
select PCI
select PPC4xx_PCI_EXPRESS
- select IBM_NEW_EMAC_RGMII
+ select IBM_EMAC_RGMII
help
This option enables support for the AMCC PPC460SX evaluation board.
@@ -260,59 +260,59 @@ config 440EP
bool
select PPC_FPU
select IBM440EP_ERR42
- select IBM_NEW_EMAC_ZMII
+ select IBM_EMAC_ZMII
select USB_ARCH_HAS_OHCI
config 440EPX
bool
select PPC_FPU
- select IBM_NEW_EMAC_EMAC4
- select IBM_NEW_EMAC_RGMII
- select IBM_NEW_EMAC_ZMII
+ select IBM_EMAC_EMAC4
+ select IBM_EMAC_RGMII
+ select IBM_EMAC_ZMII
config 440GRX
bool
- select IBM_NEW_EMAC_EMAC4
- select IBM_NEW_EMAC_RGMII
- select IBM_NEW_EMAC_ZMII
+ select IBM_EMAC_EMAC4
+ select IBM_EMAC_RGMII
+ select IBM_EMAC_ZMII
config 440GP
bool
- select IBM_NEW_EMAC_ZMII
+ select IBM_EMAC_ZMII
config 440GX
bool
- select IBM_NEW_EMAC_EMAC4
- select IBM_NEW_EMAC_RGMII
- select IBM_NEW_EMAC_ZMII #test only
- select IBM_NEW_EMAC_TAH #test only
+ select IBM_EMAC_EMAC4
+ select IBM_EMAC_RGMII
+ select IBM_EMAC_ZMII #test only
+ select IBM_EMAC_TAH #test only
config 440SP
bool
config 440SPe
bool
- select IBM_NEW_EMAC_EMAC4
+ select IBM_EMAC_EMAC4
config 460EX
bool
select PPC_FPU
- select IBM_NEW_EMAC_EMAC4
- select IBM_NEW_EMAC_TAH
+ select IBM_EMAC_EMAC4
+ select IBM_EMAC_TAH
config 460SX
bool
select PPC_FPU
- select IBM_NEW_EMAC_EMAC4
- select IBM_NEW_EMAC_RGMII
- select IBM_NEW_EMAC_ZMII
- select IBM_NEW_EMAC_TAH
+ select IBM_EMAC_EMAC4
+ select IBM_EMAC_RGMII
+ select IBM_EMAC_ZMII
+ select IBM_EMAC_TAH
config APM821xx
bool
select PPC_FPU
- select IBM_NEW_EMAC_EMAC4
- select IBM_NEW_EMAC_TAH
+ select IBM_EMAC_EMAC4
+ select IBM_EMAC_TAH
# 44x errata/workaround config symbols, selected by the CPU models above
config IBM440EP_ERR42
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index e41ebbdb3e12..cfe958e94e1e 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -66,8 +66,8 @@ struct fsl_diu_shared_fb {
bool in_use;
};
-unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
- int monitor_port)
+u32 mpc512x_get_pixel_format(enum fsl_diu_monitor_port port,
+ unsigned int bits_per_pixel)
{
switch (bits_per_pixel) {
case 32:
@@ -80,11 +80,12 @@ unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
return 0x00000400;
}
-void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base)
+void mpc512x_set_gamma_table(enum fsl_diu_monitor_port port,
+ char *gamma_table_base)
{
}
-void mpc512x_set_monitor_port(int monitor_port)
+void mpc512x_set_monitor_port(enum fsl_diu_monitor_port port)
{
}
@@ -182,14 +183,10 @@ void mpc512x_set_pixel_clock(unsigned int pixclock)
iounmap(ccm);
}
-ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf)
+enum fsl_diu_monitor_port
+mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port)
{
- return sprintf(buf, "0 - 5121 LCD\n");
-}
-
-int mpc512x_set_sysfs_monitor_port(int val)
-{
- return 0;
+ return FSL_DIU_PORT_DVI;
}
static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
@@ -256,7 +253,7 @@ void __init mpc512x_init_diu(void)
}
mode = in_be32(&diu_reg->diu_mode);
- if (mode != MFB_MODE1) {
+ if (mode == MFB_MODE0) {
pr_info("%s: DIU OFF\n", __func__);
goto out;
}
@@ -332,8 +329,7 @@ void __init mpc512x_setup_diu(void)
diu_ops.set_gamma_table = mpc512x_set_gamma_table;
diu_ops.set_monitor_port = mpc512x_set_monitor_port;
diu_ops.set_pixel_clock = mpc512x_set_pixel_clock;
- diu_ops.show_monitor_port = mpc512x_show_monitor_port;
- diu_ops.set_sysfs_monitor_port = mpc512x_set_sysfs_monitor_port;
+ diu_ops.valid_monitor_port = mpc512x_valid_monitor_port;
diu_ops.release_bootmem = mpc512x_release_bootmem;
#endif
}
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 498534cd5265..12f5932dadc9 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -80,7 +80,7 @@ config P1010_RDB
config P1022_DS
bool "Freescale P1022 DS"
select DEFAULT_UIMAGE
- select CONFIG_PHYS_64BIT # The DTS has 36-bit addresses
+ select PHYS_64BIT # The DTS has 36-bit addresses
select SWIOTLB
help
This option enables support for the Freescale P1022DS reference board.
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 266b3aadfe5e..c01c7277888c 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -93,8 +93,8 @@
* The Area Descriptor is a 32-bit value that determine which bits in each
* pixel are to be used for each color.
*/
-static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
- int monitor_port)
+static u32 p1022ds_get_pixel_format(enum fsl_diu_monitor_port port,
+ unsigned int bits_per_pixel)
{
switch (bits_per_pixel) {
case 32:
@@ -118,7 +118,8 @@ static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
* On some boards, the gamma table for some ports may need to be modified.
* This is not the case on the P1022DS, so we do nothing.
*/
-static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
+static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
+ char *gamma_table_base)
{
}
@@ -126,7 +127,7 @@ static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
* p1022ds_set_monitor_port: switch the output to a different monitor port
*
*/
-static void p1022ds_set_monitor_port(int monitor_port)
+static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
{
struct device_node *pixis_node;
void __iomem *pixis;
@@ -145,19 +146,21 @@ static void p1022ds_set_monitor_port(int monitor_port)
}
brdcfg1 = pixis + 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */
- switch (monitor_port) {
- case 0: /* DVI */
+ switch (port) {
+ case FSL_DIU_PORT_DVI:
+ printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
/* Enable the DVI port, disable the DFP and the backlight */
clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT,
PX_BRDCFG1_DVIEN);
break;
- case 1: /* Single link LVDS */
+ case FSL_DIU_PORT_LVDS:
+ printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
/* Enable the DFP port, disable the DVI and the backlight */
clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT,
PX_BRDCFG1_DFPEN);
break;
default:
- pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
+ pr_err("p1022ds: unsupported monitor port %i\n", port);
}
iounmap(pixis);
@@ -214,23 +217,18 @@ void p1022ds_set_pixel_clock(unsigned int pixclock)
}
/**
- * p1022ds_show_monitor_port: show the current monitor
- *
- * This function returns a string indicating whether the current monitor is
- * set to DVI or LVDS.
- */
-ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf)
-{
- return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n",
- monitor_port == 0 ? '*' : ' ', monitor_port == 1 ? '*' : ' ');
-}
-
-/**
- * p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs
+ * p1022ds_valid_monitor_port: set the monitor port for sysfs
*/
-int p1022ds_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
{
- return val < 2 ? val : 0;
+ switch (port) {
+ case FSL_DIU_PORT_DVI:
+ case FSL_DIU_PORT_LVDS:
+ return port;
+ default:
+ return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
+ }
}
#endif
@@ -305,8 +303,7 @@ static void __init p1022_ds_setup_arch(void)
diu_ops.set_gamma_table = p1022ds_set_gamma_table;
diu_ops.set_monitor_port = p1022ds_set_monitor_port;
diu_ops.set_pixel_clock = p1022ds_set_pixel_clock;
- diu_ops.show_monitor_port = p1022ds_show_monitor_port;
- diu_ops.set_sysfs_monitor_port = p1022ds_set_sysfs_monitor_port;
+ diu_ops.valid_monitor_port = p1022ds_valid_monitor_port;
#endif
#ifdef CONFIG_SMP
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 74e018ef724b..13fa9a6403e6 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -152,10 +152,10 @@ machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
(c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
(c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
-unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
- int monitor_port)
+u32 mpc8610hpcd_get_pixel_format(enum fsl_diu_monitor_port port,
+ unsigned int bits_per_pixel)
{
- static const unsigned long pixelformat[][3] = {
+ static const u32 pixelformat[][3] = {
{
MAKE_AD(3, 0, 2, 1, 3, 8, 8, 8, 8),
MAKE_AD(4, 2, 0, 1, 2, 8, 8, 8, 0),
@@ -170,7 +170,8 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
unsigned int arch_monitor;
/* The DVI port is mis-wired on revision 1 of this board. */
- arch_monitor = ((*pixis_arch == 0x01) && (monitor_port == 0))? 0 : 1;
+ arch_monitor =
+ ((*pixis_arch == 0x01) && (port == FSL_DIU_PORT_DVI)) ? 0 : 1;
switch (bits_per_pixel) {
case 32:
@@ -185,10 +186,11 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
}
}
-void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
+void mpc8610hpcd_set_gamma_table(enum fsl_diu_monitor_port port,
+ char *gamma_table_base)
{
int i;
- if (monitor_port == 2) { /* dual link LVDS */
+ if (port == FSL_DIU_PORT_DLVDS) {
for (i = 0; i < 256*3; i++)
gamma_table_base[i] = (gamma_table_base[i] << 2) |
((gamma_table_base[i] >> 6) & 0x03);
@@ -199,17 +201,21 @@ void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
#define PX_BRDCFG0_DLINK (1 << 4)
#define PX_BRDCFG0_DIU_MASK (PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK)
-void mpc8610hpcd_set_monitor_port(int monitor_port)
+void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port)
{
- static const u8 bdcfg[] = {
- PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK,
- PX_BRDCFG0_DLINK,
- 0,
- };
-
- if (monitor_port < 3)
+ switch (port) {
+ case FSL_DIU_PORT_DVI:
clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
- bdcfg[monitor_port]);
+ PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK);
+ break;
+ case FSL_DIU_PORT_LVDS:
+ clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
+ PX_BRDCFG0_DLINK);
+ break;
+ case FSL_DIU_PORT_DLVDS:
+ clrbits8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK);
+ break;
+ }
}
/**
@@ -262,20 +268,10 @@ void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
iounmap(guts);
}
-ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
-{
- return snprintf(buf, PAGE_SIZE,
- "%c0 - DVI\n"
- "%c1 - Single link LVDS\n"
- "%c2 - Dual link LVDS\n",
- monitor_port == 0 ? '*' : ' ',
- monitor_port == 1 ? '*' : ' ',
- monitor_port == 2 ? '*' : ' ');
-}
-
-int mpc8610hpcd_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
{
- return val < 3 ? val : 0;
+ return port;
}
#endif
@@ -307,8 +303,7 @@ static void __init mpc86xx_hpcd_setup_arch(void)
diu_ops.set_gamma_table = mpc8610hpcd_set_gamma_table;
diu_ops.set_monitor_port = mpc8610hpcd_set_monitor_port;
diu_ops.set_pixel_clock = mpc8610hpcd_set_pixel_clock;
- diu_ops.show_monitor_port = mpc8610hpcd_show_monitor_port;
- diu_ops.set_sysfs_monitor_port = mpc8610hpcd_set_sysfs_monitor_port;
+ diu_ops.valid_monitor_port = mpc8610hpcd_valid_monitor_port;
#endif
pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis");
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 67d5009b4e86..2e7ff0c5cf42 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -17,10 +17,10 @@ config PPC_CELL_NATIVE
select PPC_CELL_COMMON
select MPIC
select PPC_IO_WORKAROUNDS
- select IBM_NEW_EMAC_EMAC4
- select IBM_NEW_EMAC_RGMII
- select IBM_NEW_EMAC_ZMII #test only
- select IBM_NEW_EMAC_TAH #test only
+ select IBM_EMAC_EMAC4
+ select IBM_EMAC_RGMII
+ select IBM_EMAC_ZMII #test only
+ select IBM_EMAC_TAH #test only
default n
config PPC_IBM_CELL_BLADE
diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c
index 613070e9ddbe..f1eebcae9bf0 100644
--- a/arch/powerpc/platforms/embedded6xx/storcenter.c
+++ b/arch/powerpc/platforms/embedded6xx/storcenter.c
@@ -77,7 +77,7 @@ static void __init storcenter_setup_arch(void)
}
/*
- * Interrupt setup and service. Interrrupts on the turbostation come
+ * Interrupt setup and service. Interrupts on the turbostation come
* from the four PCI slots plus onboard 8241 devices: I2C, DUART.
*/
static void __init storcenter_init_IRQ(void)
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index c65f75aa7ff7..22ffccd8bef5 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1608,6 +1608,7 @@ int fsl_rio_setup(struct platform_device *dev)
return 0;
err:
iounmap(priv->regs_win);
+ release_resource(&port->iores);
err_res:
kfree(priv);
err_priv:
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 2ece02beb8ff..c6d00736f07f 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -22,15 +22,24 @@ struct device_node;
extern void fsl_rstcr_restart(char *cmd);
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
+/* The different ports that the DIU can be connected to */
+enum fsl_diu_monitor_port {
+ FSL_DIU_PORT_DVI, /* DVI */
+ FSL_DIU_PORT_LVDS, /* Single-link LVDS */
+ FSL_DIU_PORT_DLVDS /* Dual-link LVDS */
+};
+
struct platform_diu_data_ops {
- unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,
- int monitor_port);
- void (*set_gamma_table) (int monitor_port, char *gamma_table_base);
- void (*set_monitor_port) (int monitor_port);
- void (*set_pixel_clock) (unsigned int pixclock);
- ssize_t (*show_monitor_port) (int monitor_port, char *buf);
- int (*set_sysfs_monitor_port) (int val);
- void (*release_bootmem) (void);
+ u32 (*get_pixel_format)(enum fsl_diu_monitor_port port,
+ unsigned int bpp);
+ void (*set_gamma_table)(enum fsl_diu_monitor_port port,
+ char *gamma_table_base);
+ void (*set_monitor_port)(enum fsl_diu_monitor_port port);
+ void (*set_pixel_clock)(unsigned int pixclock);
+ enum fsl_diu_monitor_port (*valid_monitor_port)
+ (enum fsl_diu_monitor_port port);
+ void (*release_bootmem)(void);
};
extern struct platform_diu_data_ops diu_ops;
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 904c6cbaf45b..3363fbc964f8 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -382,7 +382,7 @@ static void qe_upload_microcode(const void *base,
/*
* Upload a microcode to the I-RAM at a specific address.
*
- * See Documentation/powerpc/qe-firmware.txt for information on QE microcode
+ * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
* uploading.
*
* Currently, only version 1 is supported, so the 'version' field must be
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 984cd2029158..3330feca7502 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -47,7 +47,7 @@ struct uic {
int index;
int dcrbase;
- spinlock_t lock;
+ raw_spinlock_t lock;
/* The remapper for this UIC */
struct irq_host *irqhost;
@@ -61,14 +61,14 @@ static void uic_unmask_irq(struct irq_data *d)
u32 er, sr;
sr = 1 << (31-src);
- spin_lock_irqsave(&uic->lock, flags);
+ raw_spin_lock_irqsave(&uic->lock, flags);
/* ack level-triggered interrupts here */
if (irqd_is_level_type(d))
mtdcr(uic->dcrbase + UIC_SR, sr);
er = mfdcr(uic->dcrbase + UIC_ER);
er |= sr;
mtdcr(uic->dcrbase + UIC_ER, er);
- spin_unlock_irqrestore(&uic->lock, flags);
+ raw_spin_unlock_irqrestore(&uic->lock, flags);
}
static void uic_mask_irq(struct irq_data *d)
@@ -78,11 +78,11 @@ static void uic_mask_irq(struct irq_data *d)
unsigned long flags;
u32 er;
- spin_lock_irqsave(&uic->lock, flags);
+ raw_spin_lock_irqsave(&uic->lock, flags);
er = mfdcr(uic->dcrbase + UIC_ER);
er &= ~(1 << (31 - src));
mtdcr(uic->dcrbase + UIC_ER, er);
- spin_unlock_irqrestore(&uic->lock, flags);
+ raw_spin_unlock_irqrestore(&uic->lock, flags);
}
static void uic_ack_irq(struct irq_data *d)
@@ -91,9 +91,9 @@ static void uic_ack_irq(struct irq_data *d)
unsigned int src = irqd_to_hwirq(d);
unsigned long flags;
- spin_lock_irqsave(&uic->lock, flags);
+ raw_spin_lock_irqsave(&uic->lock, flags);
mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src));
- spin_unlock_irqrestore(&uic->lock, flags);
+ raw_spin_unlock_irqrestore(&uic->lock, flags);
}
static void uic_mask_ack_irq(struct irq_data *d)
@@ -104,7 +104,7 @@ static void uic_mask_ack_irq(struct irq_data *d)
u32 er, sr;
sr = 1 << (31-src);
- spin_lock_irqsave(&uic->lock, flags);
+ raw_spin_lock_irqsave(&uic->lock, flags);
er = mfdcr(uic->dcrbase + UIC_ER);
er &= ~sr;
mtdcr(uic->dcrbase + UIC_ER, er);
@@ -118,7 +118,7 @@ static void uic_mask_ack_irq(struct irq_data *d)
*/
if (!irqd_is_level_type(d))
mtdcr(uic->dcrbase + UIC_SR, sr);
- spin_unlock_irqrestore(&uic->lock, flags);
+ raw_spin_unlock_irqrestore(&uic->lock, flags);
}
static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
@@ -152,7 +152,7 @@ static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
mask = ~(1 << (31 - src));
- spin_lock_irqsave(&uic->lock, flags);
+ raw_spin_lock_irqsave(&uic->lock, flags);
tr = mfdcr(uic->dcrbase + UIC_TR);
pr = mfdcr(uic->dcrbase + UIC_PR);
tr = (tr & mask) | (trigger << (31-src));
@@ -161,7 +161,7 @@ static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
mtdcr(uic->dcrbase + UIC_PR, pr);
mtdcr(uic->dcrbase + UIC_TR, tr);
- spin_unlock_irqrestore(&uic->lock, flags);
+ raw_spin_unlock_irqrestore(&uic->lock, flags);
return 0;
}
@@ -254,7 +254,7 @@ static struct uic * __init uic_init_one(struct device_node *node)
if (! uic)
return NULL; /* FIXME: panic? */
- spin_lock_init(&uic->lock);
+ raw_spin_lock_init(&uic->lock);
indexp = of_get_property(node, "cell-index", &len);
if (!indexp || (len != sizeof(u32))) {
printk(KERN_ERR "uic: Device node %s has missing or invalid "
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index ed5cb5af5281..a9fbd43395f7 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -91,6 +91,7 @@ config S390
select HAVE_ARCH_MUTEX_CPU_RELAX
select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
select HAVE_RCU_TABLE_FREE if SMP
+ select ARCH_SAVE_PAGE_KEYS if HIBERNATION
select ARCH_INLINE_SPIN_TRYLOCK
select ARCH_INLINE_SPIN_TRYLOCK_BH
select ARCH_INLINE_SPIN_LOCK
@@ -568,6 +569,16 @@ config KEXEC
current kernel, and to start another kernel. It is like a reboot
but is independent of hardware/microcode support.
+config CRASH_DUMP
+ bool "kernel crash dumps"
+ depends on 64BIT
+ help
+ Generate crash dump after being started by kexec.
+ Crash dump kernels are loaded in the main kernel with kexec-tools
+ into a specially reserved region and then later executed after
+ a crash by kdump/kexec.
+ For more details see Documentation/kdump/kdump.txt
+
config ZFCPDUMP
def_bool n
prompt "zfcpdump support"
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c
index 028f23ea81d1..465eca756feb 100644
--- a/arch/s390/boot/compressed/misc.c
+++ b/arch/s390/boot/compressed/misc.c
@@ -61,7 +61,7 @@ static unsigned long free_mem_end_ptr;
extern _sclp_print_early(const char *);
-int puts(const char *s)
+static int puts(const char *s)
{
_sclp_print_early(s);
return 0;
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 29c82c640a88..6cf8e26b3137 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -68,7 +68,7 @@ CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 6023c6dc1fb7..74c8f5e76ce4 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -562,10 +562,9 @@ static int dbfs_d204_create(void **data, void **data_free_ptr, size_t *size)
void *base;
buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr);
- base = vmalloc(buf_size);
+ base = vzalloc(buf_size);
if (!base)
return -ENOMEM;
- memset(base, 0, buf_size);
d204 = page_align_ptr(base + sizeof(d204->hdr)) - sizeof(d204->hdr);
rc = diag204_do_store(d204->buf, diag204_buf_pages);
if (rc) {
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 6fe874fc5f8e..481f4f76f664 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -108,9 +108,7 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
ret->i_gid = hypfs_info->gid;
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
if (mode & S_IFDIR)
- ret->i_nlink = 2;
- else
- ret->i_nlink = 1;
+ set_nlink(ret, 2);
}
return ret;
}
@@ -361,7 +359,7 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
} else if (mode & S_IFDIR) {
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
- parent->d_inode->i_nlink++;
+ inc_nlink(parent->d_inode);
} else
BUG();
inode->i_private = data;
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h
index 623f2fb71774..9381c92cc779 100644
--- a/arch/s390/include/asm/ccwdev.h
+++ b/arch/s390/include/asm/ccwdev.h
@@ -11,6 +11,7 @@
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <asm/fcx.h>
+#include <asm/irq.h>
/* structs from asm/cio.h */
struct irb;
@@ -127,6 +128,7 @@ enum uc_todo {
* @restore: callback for restoring after hibernation
* @uc_handler: callback for unit check handler
* @driver: embedded device driver structure
+ * @int_class: interruption class to use for accounting interrupts
*/
struct ccw_driver {
struct ccw_device_id *ids;
@@ -144,6 +146,7 @@ struct ccw_driver {
int (*restore)(struct ccw_device *);
enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *);
struct device_driver driver;
+ enum interruption_class int_class;
};
extern struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv,
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index da359ca6fe55..2e49748b27da 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -12,6 +12,7 @@
#define PSW32_MASK_IO 0x02000000UL
#define PSW32_MASK_EXT 0x01000000UL
#define PSW32_MASK_KEY 0x00F00000UL
+#define PSW32_MASK_BASE 0x00080000UL /* Always one */
#define PSW32_MASK_MCHECK 0x00040000UL
#define PSW32_MASK_WAIT 0x00020000UL
#define PSW32_MASK_PSTATE 0x00010000UL
@@ -19,21 +20,19 @@
#define PSW32_MASK_CC 0x00003000UL
#define PSW32_MASK_PM 0x00000f00UL
-#define PSW32_ADDR_AMODE31 0x80000000UL
+#define PSW32_MASK_USER 0x00003F00UL
+
+#define PSW32_ADDR_AMODE 0x80000000UL
#define PSW32_ADDR_INSN 0x7FFFFFFFUL
-#define PSW32_BASE_BITS 0x00080000UL
+#define PSW32_DEFAULT_KEY (((u32) PAGE_DEFAULT_ACC) << 20)
#define PSW32_ASC_PRIMARY 0x00000000UL
#define PSW32_ASC_ACCREG 0x00004000UL
#define PSW32_ASC_SECONDARY 0x00008000UL
#define PSW32_ASC_HOME 0x0000C000UL
-#define PSW32_MASK_MERGE(CURRENT,NEW) \
- (((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \
- ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM)))
-
-extern long psw32_user_bits;
+extern u32 psw32_user_bits;
#define COMPAT_USER_HZ 100
#define COMPAT_UTS_MACHINE "s390\0\0\0\0"
@@ -131,7 +130,8 @@ struct compat_statfs {
compat_fsid_t f_fsid;
s32 f_namelen;
s32 f_frsize;
- s32 f_spare[6];
+ s32 f_flags;
+ s32 f_spare[5];
};
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h
index 97cc4403fabf..6940abfbe1d9 100644
--- a/arch/s390/include/asm/ipl.h
+++ b/arch/s390/include/asm/ipl.h
@@ -168,5 +168,6 @@ enum diag308_rc {
extern int diag308(unsigned long subcode, void *addr);
extern void diag308_reset(void);
+extern void store_status(void);
#endif /* _ASM_S390_IPL_H */
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h
index ba7b01c726a3..ba6d85f88d50 100644
--- a/arch/s390/include/asm/irq.h
+++ b/arch/s390/include/asm/irq.h
@@ -8,7 +8,8 @@ enum interruption_class {
EXTERNAL_INTERRUPT,
IO_INTERRUPT,
EXTINT_CLK,
- EXTINT_IPI,
+ EXTINT_EXC,
+ EXTINT_EMS,
EXTINT_TMR,
EXTINT_TLA,
EXTINT_PFL,
@@ -17,8 +18,8 @@ enum interruption_class {
EXTINT_SCP,
EXTINT_IUC,
EXTINT_CPM,
+ IOINT_CIO,
IOINT_QAI,
- IOINT_QDI,
IOINT_DAS,
IOINT_C15,
IOINT_C70,
@@ -28,6 +29,7 @@ enum interruption_class {
IOINT_CLW,
IOINT_CTC,
IOINT_APB,
+ IOINT_CSC,
NMI_NMI,
NR_IRQS,
};
diff --git a/arch/s390/include/asm/kexec.h b/arch/s390/include/asm/kexec.h
index bb729b84a21e..cf4e47b0948c 100644
--- a/arch/s390/include/asm/kexec.h
+++ b/arch/s390/include/asm/kexec.h
@@ -30,9 +30,15 @@
/* Not more than 2GB */
#define KEXEC_CONTROL_MEMORY_LIMIT (1UL<<31)
+/* Maximum address we can use for the crash control pages */
+#define KEXEC_CRASH_CONTROL_MEMORY_LIMIT (-1UL)
+
/* Allocate one page for the pdp and the second for the code */
#define KEXEC_CONTROL_PAGE_SIZE 4096
+/* Alignment of crashkernel memory */
+#define KEXEC_CRASH_MEM_ALIGN HPAGE_SIZE
+
/* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_S390
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 00ff00dfb24c..24e18473d926 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -119,6 +119,7 @@ struct kvm_vcpu_stat {
u32 instruction_lctlg;
u32 exit_program_interruption;
u32 exit_instr_and_program;
+ u32 deliver_external_call;
u32 deliver_emergency_signal;
u32 deliver_service_signal;
u32 deliver_virtio_interrupt;
@@ -138,11 +139,13 @@ struct kvm_vcpu_stat {
u32 instruction_stfl;
u32 instruction_tprot;
u32 instruction_sigp_sense;
+ u32 instruction_sigp_external_call;
u32 instruction_sigp_emergency;
u32 instruction_sigp_stop;
u32 instruction_sigp_arch;
u32 instruction_sigp_prefix;
u32 instruction_sigp_restart;
+ u32 diagnose_10;
u32 diagnose_44;
};
@@ -174,6 +177,10 @@ struct kvm_s390_prefix_info {
__u32 address;
};
+struct kvm_s390_extcall_info {
+ __u16 code;
+};
+
struct kvm_s390_emerg_info {
__u16 code;
};
@@ -186,6 +193,7 @@ struct kvm_s390_interrupt_info {
struct kvm_s390_ext_info ext;
struct kvm_s390_pgm_info pgm;
struct kvm_s390_emerg_info emerg;
+ struct kvm_s390_extcall_info extcall;
struct kvm_s390_prefix_info prefix;
};
};
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index e85c911aabf0..9e13c7d56cc1 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -151,10 +151,8 @@ struct _lowcore {
*/
__u32 ipib; /* 0x0e00 */
__u32 ipib_checksum; /* 0x0e04 */
-
- /* 64 bit save area */
- __u64 save_area_64; /* 0x0e08 */
- __u8 pad_0x0e10[0x0f00-0x0e10]; /* 0x0e10 */
+ __u32 vmcore_info; /* 0x0e08 */
+ __u8 pad_0x0e0c[0x0f00-0x0e0c]; /* 0x0e0c */
/* Extended facility list */
__u64 stfle_fac_list[32]; /* 0x0f00 */
@@ -290,9 +288,7 @@ struct _lowcore {
*/
__u64 ipib; /* 0x0e00 */
__u32 ipib_checksum; /* 0x0e08 */
-
- /* 64 bit save area */
- __u64 save_area_64; /* 0x0e0c */
+ __u64 vmcore_info; /* 0x0e0c */
__u8 pad_0x0e14[0x0f00-0x0e14]; /* 0x0e14 */
/* Extended facility list */
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index accb372ddc7e..f7ec548c2b9d 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -177,6 +177,7 @@ static inline int page_test_and_clear_young(unsigned long pfn)
struct page;
void arch_free_page(struct page *page, int order);
void arch_alloc_page(struct page *page, int order);
+void arch_set_page_states(int make_stable);
static inline int devmem_is_allowed(unsigned long pfn)
{
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index c0cb794bb365..34ede0ea85a9 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -696,7 +696,9 @@ void gmap_disable(struct gmap *gmap);
int gmap_map_segment(struct gmap *gmap, unsigned long from,
unsigned long to, unsigned long length);
int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
+unsigned long __gmap_fault(unsigned long address, struct gmap *);
unsigned long gmap_fault(unsigned long address, struct gmap *);
+void gmap_discard(unsigned long from, unsigned long to, struct gmap *);
/*
* Certain architectures need to do special things when PTEs
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index a4b6229e5d4b..5f33d37d032c 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -33,6 +33,8 @@ static inline void get_cpu_id(struct cpuid *ptr)
extern void s390_adjust_jiffies(void);
extern int get_cpu_capability(unsigned int *);
+extern const struct seq_operations cpuinfo_op;
+extern int sysctl_ieee_emulation_warnings;
/*
* User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
@@ -118,17 +120,17 @@ struct stack_frame {
/*
* Do necessary setup to start up a new thread.
*/
-#define start_thread(regs, new_psw, new_stackp) do { \
- regs->psw.mask = psw_user_bits; \
- regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
- regs->gprs[15] = new_stackp; \
+#define start_thread(regs, new_psw, new_stackp) do { \
+ regs->psw.mask = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA; \
+ regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
+ regs->gprs[15] = new_stackp; \
} while (0)
-#define start_thread31(regs, new_psw, new_stackp) do { \
- regs->psw.mask = psw_user32_bits; \
- regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
- regs->gprs[15] = new_stackp; \
- crst_table_downgrade(current->mm, 1UL << 31); \
+#define start_thread31(regs, new_psw, new_stackp) do { \
+ regs->psw.mask = psw_user_bits | PSW_MASK_BA; \
+ regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
+ regs->gprs[15] = new_stackp; \
+ crst_table_downgrade(current->mm, 1UL << 31); \
} while (0)
/* Forward declaration, a strange C thing */
@@ -187,7 +189,6 @@ static inline void __load_psw(psw_t psw)
* Set PSW mask to specified value, while leaving the
* PSW addr pointing to the next instruction.
*/
-
static inline void __load_psw_mask (unsigned long mask)
{
unsigned long addr;
@@ -212,26 +213,37 @@ static inline void __load_psw_mask (unsigned long mask)
: "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc");
#endif /* __s390x__ */
}
-
+
/*
- * Function to stop a processor until an interruption occurred
+ * Rewind PSW instruction address by specified number of bytes.
*/
-static inline void enabled_wait(void)
+static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
{
- __load_psw_mask(PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
- PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY);
-}
+#ifndef __s390x__
+ if (psw.addr & PSW_ADDR_AMODE)
+ /* 31 bit mode */
+ return (psw.addr - ilc) | PSW_ADDR_AMODE;
+ /* 24 bit mode */
+ return (psw.addr - ilc) & ((1UL << 24) - 1);
+#else
+ unsigned long mask;
+ mask = (psw.mask & PSW_MASK_EA) ? -1UL :
+ (psw.mask & PSW_MASK_BA) ? (1UL << 31) - 1 :
+ (1UL << 24) - 1;
+ return (psw.addr - ilc) & mask;
+#endif
+}
+
/*
* Function to drop a processor into disabled wait state
*/
-
static inline void ATTRIB_NORET disabled_wait(unsigned long code)
{
unsigned long ctl_buf;
psw_t dw_psw;
- dw_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
+ dw_psw.mask = PSW_MASK_BASE | PSW_MASK_WAIT | PSW_MASK_BA | PSW_MASK_EA;
dw_psw.addr = code;
/*
* Store status and then load disabled wait psw,
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 62fd80c9e98c..a65846340d51 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -230,17 +230,21 @@ typedef struct
#define PSW_MASK_IO 0x02000000UL
#define PSW_MASK_EXT 0x01000000UL
#define PSW_MASK_KEY 0x00F00000UL
+#define PSW_MASK_BASE 0x00080000UL /* always one */
#define PSW_MASK_MCHECK 0x00040000UL
#define PSW_MASK_WAIT 0x00020000UL
#define PSW_MASK_PSTATE 0x00010000UL
#define PSW_MASK_ASC 0x0000C000UL
#define PSW_MASK_CC 0x00003000UL
#define PSW_MASK_PM 0x00000F00UL
+#define PSW_MASK_EA 0x00000000UL
+#define PSW_MASK_BA 0x00000000UL
+
+#define PSW_MASK_USER 0x00003F00UL
#define PSW_ADDR_AMODE 0x80000000UL
#define PSW_ADDR_INSN 0x7FFFFFFFUL
-#define PSW_BASE_BITS 0x00080000UL
#define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 20)
#define PSW_ASC_PRIMARY 0x00000000UL
@@ -254,6 +258,7 @@ typedef struct
#define PSW_MASK_DAT 0x0400000000000000UL
#define PSW_MASK_IO 0x0200000000000000UL
#define PSW_MASK_EXT 0x0100000000000000UL
+#define PSW_MASK_BASE 0x0000000000000000UL
#define PSW_MASK_KEY 0x00F0000000000000UL
#define PSW_MASK_MCHECK 0x0004000000000000UL
#define PSW_MASK_WAIT 0x0002000000000000UL
@@ -261,12 +266,14 @@ typedef struct
#define PSW_MASK_ASC 0x0000C00000000000UL
#define PSW_MASK_CC 0x0000300000000000UL
#define PSW_MASK_PM 0x00000F0000000000UL
+#define PSW_MASK_EA 0x0000000100000000UL
+#define PSW_MASK_BA 0x0000000080000000UL
+
+#define PSW_MASK_USER 0x00003F0180000000UL
#define PSW_ADDR_AMODE 0x0000000000000000UL
#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL
-#define PSW_BASE_BITS 0x0000000180000000UL
-#define PSW_BASE32_BITS 0x0000000080000000UL
#define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 52)
#define PSW_ASC_PRIMARY 0x0000000000000000UL
@@ -279,18 +286,7 @@ typedef struct
#ifdef __KERNEL__
extern long psw_kernel_bits;
extern long psw_user_bits;
-#ifdef CONFIG_64BIT
-extern long psw_user32_bits;
#endif
-#endif
-
-/* This macro merges a NEW PSW mask specified by the user into
- the currently active PSW mask CURRENT, modifying only those
- bits in CURRENT that the user may be allowed to change: this
- is the condition code and the program mask bits. */
-#define PSW_MASK_MERGE(CURRENT,NEW) \
- (((CURRENT) & ~(PSW_MASK_CC|PSW_MASK_PM)) | \
- ((NEW) & (PSW_MASK_CC|PSW_MASK_PM)))
/*
* The s390_regs structure is used to define the elf_gregset_t.
@@ -328,8 +324,7 @@ struct pt_regs
psw_t psw;
unsigned long gprs[NUM_GPRS];
unsigned long orig_gpr2;
- unsigned short ilc;
- unsigned short svcnr;
+ unsigned int svc_code;
};
/*
@@ -487,6 +482,8 @@ typedef struct
#define PTRACE_POKETEXT_AREA 0x5004
#define PTRACE_POKEDATA_AREA 0x5005
#define PTRACE_GET_LAST_BREAK 0x5006
+#define PTRACE_PEEK_SYSTEM_CALL 0x5007
+#define PTRACE_POKE_SYSTEM_CALL 0x5008
/*
* PT_PROT definition is loosely based on hppa bsd definition in
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index 15c97625df8d..e63d13dd3bf5 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -46,6 +46,8 @@ struct qdesfmt0 {
u32 : 16;
} __attribute__ ((packed));
+#define QDR_AC_MULTI_BUFFER_ENABLE 0x01
+
/**
* struct qdr - queue description record (QDR)
* @qfmt: queue format
@@ -123,6 +125,40 @@ struct slibe {
};
/**
+ * struct qaob - queue asynchronous operation block
+ * @res0: reserved parameters
+ * @res1: reserved parameter
+ * @res2: reserved parameter
+ * @res3: reserved parameter
+ * @aorc: asynchronous operation return code
+ * @flags: internal flags
+ * @cbtbs: control block type
+ * @sb_count: number of storage blocks
+ * @sba: storage block element addresses
+ * @dcount: size of storage block elements
+ * @user0: user defineable value
+ * @res4: reserved paramater
+ * @user1: user defineable value
+ * @user2: user defineable value
+ */
+struct qaob {
+ u64 res0[6];
+ u8 res1;
+ u8 res2;
+ u8 res3;
+ u8 aorc;
+ u8 flags;
+ u16 cbtbs;
+ u8 sb_count;
+ u64 sba[QDIO_MAX_ELEMENTS_PER_BUFFER];
+ u16 dcount[QDIO_MAX_ELEMENTS_PER_BUFFER];
+ u64 user0;
+ u64 res4[2];
+ u64 user1;
+ u64 user2;
+} __attribute__ ((packed, aligned(256)));
+
+/**
* struct slib - storage list information block (SLIB)
* @nsliba: next SLIB address (if any)
* @sla: SL address
@@ -222,9 +258,46 @@ struct slsb {
u8 val[QDIO_MAX_BUFFERS_PER_Q];
} __attribute__ ((packed, aligned(256)));
+#define CHSC_AC2_MULTI_BUFFER_AVAILABLE 0x0080
+#define CHSC_AC2_MULTI_BUFFER_ENABLED 0x0040
#define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010
#define CHSC_AC2_DATA_DIV_ENABLED 0x0002
+/**
+ * struct qdio_outbuf_state - SBAL related asynchronous operation information
+ * (for communication with upper layer programs)
+ * (only required for use with completion queues)
+ * @flags: flags indicating state of buffer
+ * @aob: pointer to QAOB used for the particular SBAL
+ * @user: pointer to upper layer program's state information related to SBAL
+ * (stored in user1 data of QAOB)
+ */
+struct qdio_outbuf_state {
+ u8 flags;
+ struct qaob *aob;
+ void *user;
+};
+
+#define QDIO_OUTBUF_STATE_FLAG_NONE 0x00
+#define QDIO_OUTBUF_STATE_FLAG_PENDING 0x01
+
+#define CHSC_AC1_INITIATE_INPUTQ 0x80
+
+
+/* qdio adapter-characteristics-1 flag */
+#define AC1_SIGA_INPUT_NEEDED 0x40 /* process input queues */
+#define AC1_SIGA_OUTPUT_NEEDED 0x20 /* process output queues */
+#define AC1_SIGA_SYNC_NEEDED 0x10 /* ask hypervisor to sync */
+#define AC1_AUTOMATIC_SYNC_ON_THININT 0x08 /* set by hypervisor */
+#define AC1_AUTOMATIC_SYNC_ON_OUT_PCI 0x04 /* set by hypervisor */
+#define AC1_SC_QEBSM_AVAILABLE 0x02 /* available for subchannel */
+#define AC1_SC_QEBSM_ENABLED 0x01 /* enabled for subchannel */
+
+#define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010
+#define CHSC_AC2_DATA_DIV_ENABLED 0x0002
+
+#define CHSC_AC3_FORMAT2_CQ_AVAILABLE 0x8000
+
struct qdio_ssqd_desc {
u8 flags;
u8:8;
@@ -243,8 +316,7 @@ struct qdio_ssqd_desc {
u64 sch_token;
u8 mro;
u8 mri;
- u8:8;
- u8 sbalic;
+ u16 qdioac3;
u16:16;
u8:8;
u8 mmwc;
@@ -280,13 +352,16 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
* @no_output_qs: number of output queues
* @input_handler: handler to be called for input queues
* @output_handler: handler to be called for output queues
+ * @queue_start_poll: polling handlers (one per input queue or NULL)
* @int_parm: interruption parameter
* @input_sbal_addr_array: address of no_input_qs * 128 pointers
* @output_sbal_addr_array: address of no_output_qs * 128 pointers
+ * @output_sbal_state_array: no_output_qs * 128 state info (for CQ or NULL)
*/
struct qdio_initialize {
struct ccw_device *cdev;
unsigned char q_format;
+ unsigned char qdr_ac;
unsigned char adapter_name[8];
unsigned int qib_param_field_format;
unsigned char *qib_param_field;
@@ -297,11 +372,12 @@ struct qdio_initialize {
unsigned int no_output_qs;
qdio_handler_t *input_handler;
qdio_handler_t *output_handler;
- void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
+ void (**queue_start_poll) (struct ccw_device *, int, unsigned long);
int scan_threshold;
unsigned long int_parm;
void **input_sbal_addr_array;
void **output_sbal_addr_array;
+ struct qdio_outbuf_state *output_sbal_state_array;
};
#define QDIO_STATE_INACTIVE 0x00000002 /* after qdio_cleanup */
@@ -316,6 +392,7 @@ struct qdio_initialize {
extern int qdio_allocate(struct qdio_initialize *);
extern int qdio_establish(struct qdio_initialize *);
extern int qdio_activate(struct ccw_device *);
+extern void qdio_release_aob(struct qaob *);
extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int,
unsigned int);
extern int qdio_start_irq(struct ccw_device *, int);
diff --git a/arch/s390/include/asm/reset.h b/arch/s390/include/asm/reset.h
index f584f4a52581..3d6ad4ad2a3f 100644
--- a/arch/s390/include/asm/reset.h
+++ b/arch/s390/include/asm/reset.h
@@ -17,5 +17,5 @@ struct reset_call {
extern void register_reset_call(struct reset_call *reset);
extern void unregister_reset_call(struct reset_call *reset);
-extern void s390_reset_system(void);
+extern void s390_reset_system(void (*func)(void *), void *data);
#endif /* _ASM_S390_RESET_H */
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index d5e2ef10537d..5a099714df04 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -26,15 +26,21 @@
#define IPL_DEVICE (*(unsigned long *) (0x10404))
#define INITRD_START (*(unsigned long *) (0x1040C))
#define INITRD_SIZE (*(unsigned long *) (0x10414))
+#define OLDMEM_BASE (*(unsigned long *) (0x1041C))
+#define OLDMEM_SIZE (*(unsigned long *) (0x10424))
#else /* __s390x__ */
#define IPL_DEVICE (*(unsigned long *) (0x10400))
#define INITRD_START (*(unsigned long *) (0x10408))
#define INITRD_SIZE (*(unsigned long *) (0x10410))
+#define OLDMEM_BASE (*(unsigned long *) (0x10418))
+#define OLDMEM_SIZE (*(unsigned long *) (0x10420))
#endif /* __s390x__ */
#define COMMAND_LINE ((char *) (0x10480))
#define CHUNK_READ_WRITE 0
#define CHUNK_READ_ONLY 1
+#define CHUNK_OLDMEM 4
+#define CHUNK_CRASHK 5
struct mem_chunk {
unsigned long addr;
@@ -48,6 +54,8 @@ extern int memory_end_set;
extern unsigned long memory_end;
void detect_memory_layout(struct mem_chunk chunk[]);
+void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr,
+ unsigned long size, int type);
#define PRIMARY_SPACE_MODE 0
#define ACCESS_REGISTER_MODE 1
@@ -106,6 +114,7 @@ extern unsigned int user_mode;
#endif /* __s390x__ */
#define ZFCPDUMP_HSA_SIZE (32UL<<20)
+#define ZFCPDUMP_HSA_SIZE_MAX (64UL<<20)
/*
* Console mode. Override with conmode=
@@ -134,10 +143,14 @@ extern char kernel_nss_name[];
#define IPL_DEVICE 0x10404
#define INITRD_START 0x1040C
#define INITRD_SIZE 0x10414
+#define OLDMEM_BASE 0x1041C
+#define OLDMEM_SIZE 0x10424
#else /* __s390x__ */
#define IPL_DEVICE 0x10400
#define INITRD_START 0x10408
#define INITRD_SIZE 0x10410
+#define OLDMEM_BASE 0x10418
+#define OLDMEM_SIZE 0x10420
#endif /* __s390x__ */
#define COMMAND_LINE 0x10480
diff --git a/arch/s390/include/asm/sfp-util.h b/arch/s390/include/asm/sfp-util.h
index 0addc6466d95..ca3f8814e361 100644
--- a/arch/s390/include/asm/sfp-util.h
+++ b/arch/s390/include/asm/sfp-util.h
@@ -72,6 +72,6 @@ extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,
#define UDIV_NEEDS_NORMALIZATION 0
-#define abort() return 0
+#define abort() BUG()
#define __BYTE_ORDER __BIG_ENDIAN
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index 045e009fc164..ab47a69fdf07 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -33,6 +33,7 @@ extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
extern void smp_switch_to_ipl_cpu(void (*func)(void *), void *);
extern void smp_switch_to_cpu(void (*)(void *), void *, unsigned long sp,
int from, int to);
+extern void smp_restart_with_online_cpu(void);
extern void smp_restart_cpu(void);
/*
@@ -64,6 +65,10 @@ static inline void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
func(data);
}
+static inline void smp_restart_with_online_cpu(void)
+{
+}
+
#define smp_vcpu_scheduled (1)
#endif /* CONFIG_SMP */
diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h
index 56612fc8186e..fd94dfec8d08 100644
--- a/arch/s390/include/asm/spinlock.h
+++ b/arch/s390/include/asm/spinlock.h
@@ -13,6 +13,8 @@
#include <linux/smp.h>
+extern int spin_retry;
+
static inline int
_raw_compare_and_swap(volatile unsigned int *lock,
unsigned int old, unsigned int new)
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
index 5c0246b955d8..b239ff53b189 100644
--- a/arch/s390/include/asm/syscall.h
+++ b/arch/s390/include/asm/syscall.h
@@ -13,6 +13,7 @@
#define _ASM_SYSCALL_H 1
#include <linux/sched.h>
+#include <linux/err.h>
#include <asm/ptrace.h>
/*
@@ -25,7 +26,8 @@ extern const unsigned int sys_call_table[];
static inline long syscall_get_nr(struct task_struct *task,
struct pt_regs *regs)
{
- return regs->svcnr ? regs->svcnr : -1;
+ return test_tsk_thread_flag(task, TIF_SYSCALL) ?
+ (regs->svc_code & 0xffff) : -1;
}
static inline void syscall_rollback(struct task_struct *task,
@@ -37,7 +39,7 @@ static inline void syscall_rollback(struct task_struct *task,
static inline long syscall_get_error(struct task_struct *task,
struct pt_regs *regs)
{
- return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0;
+ return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0;
}
static inline long syscall_get_return_value(struct task_struct *task,
diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h
index 6582f69f2389..ef573c1d71a7 100644
--- a/arch/s390/include/asm/system.h
+++ b/arch/s390/include/asm/system.h
@@ -20,6 +20,8 @@
struct task_struct;
+extern int sysctl_userprocess_debug;
+
extern struct task_struct *__switch_to(void *, void *);
extern void update_per_regs(struct task_struct *task);
@@ -114,6 +116,8 @@ extern void pfault_fini(void);
extern void cmma_init(void);
extern int memcpy_real(void *, void *, size_t);
extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
+extern int copy_to_user_real(void __user *dest, void *src, size_t count);
+extern int copy_from_user_real(void *dest, void __user *src, size_t count);
#define finish_arch_switch(prev) do { \
set_fs(current->thread.mm_segment); \
@@ -210,8 +214,10 @@ __set_psw_mask(unsigned long mask)
__load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
}
-#define local_mcck_enable() __set_psw_mask(psw_kernel_bits)
-#define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK)
+#define local_mcck_enable() \
+ __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
+#define local_mcck_disable() \
+ __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
#ifdef CONFIG_SMP
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index 1a5dbb6f1495..a23183423b14 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -48,6 +48,7 @@ struct thread_info {
unsigned int cpu; /* current CPU */
int preempt_count; /* 0 => preemptable, <0 => BUG */
struct restart_block restart_block;
+ unsigned int system_call;
__u64 user_timer;
__u64 system_timer;
unsigned long last_break; /* last breaking-event-address. */
@@ -84,10 +85,10 @@ static inline struct thread_info *current_thread_info(void)
/*
* thread information flags bit numbers
*/
+#define TIF_SYSCALL 0 /* inside a system call */
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
-#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
#define TIF_PER_TRAP 6 /* deliver sigtrap on return to user */
#define TIF_MCCK_PENDING 7 /* machine check handling is pending */
#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
@@ -103,11 +104,11 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SINGLE_STEP 20 /* This task is single stepped */
#define TIF_FREEZE 21 /* thread is freezing for suspend */
+#define _TIF_SYSCALL (1<<TIF_SYSCALL)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
-#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC)
#define _TIF_PER_TRAP (1<<TIF_PER_TRAP)
#define _TIF_MCCK_PENDING (1<<TIF_MCCK_PENDING)
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -117,7 +118,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SIE (1<<TIF_SIE)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_31BIT (1<<TIF_31BIT)
-#define _TIF_SINGLE_STEP (1<<TIF_FREEZE)
+#define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP)
#define _TIF_FREEZE (1<<TIF_FREEZE)
#ifdef CONFIG_64BIT
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
index 88829a40af6f..d610bef9c5e9 100644
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -86,6 +86,17 @@ static inline void get_clock_ext(char *clk)
asm volatile("stcke %0" : "=Q" (*clk) : : "cc");
}
+static inline unsigned long long get_clock_fast(void)
+{
+ unsigned long long clk;
+
+ if (test_facility(25))
+ asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
+ else
+ clk = get_clock();
+ return clk;
+}
+
static inline unsigned long long get_clock_xt(void)
{
unsigned char clk[16];
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h
index 304445382382..1d8648cf2fea 100644
--- a/arch/s390/include/asm/tlbflush.h
+++ b/arch/s390/include/asm/tlbflush.h
@@ -59,6 +59,7 @@ static inline void __tlb_flush_full(struct mm_struct *mm)
}
#else
#define __tlb_flush_full(mm) __tlb_flush_local()
+#define __tlb_flush_global() __tlb_flush_local()
#endif
/*
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index df3732249baa..dd4f07640919 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_FUNCTION_TRACER) += $(if $(CONFIG_64BIT),mcount64.o,mcount.o)
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
+obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
# Kexec part
S390_KEXEC_OBJS := machine_kexec.o crash.o
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 2b45591e1582..751318765e2e 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -45,8 +45,7 @@ int main(void)
DEFINE(__PT_PSW, offsetof(struct pt_regs, psw));
DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs));
DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2));
- DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc));
- DEFINE(__PT_SVCNR, offsetof(struct pt_regs, svcnr));
+ DEFINE(__PT_SVC_CODE, offsetof(struct pt_regs, svc_code));
DEFINE(__PT_SIZE, sizeof(struct pt_regs));
BLANK();
DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
@@ -141,7 +140,6 @@ int main(void)
DEFINE(__LC_FPREGS_SAVE_AREA, offsetof(struct _lowcore, floating_pt_save_area));
DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
- DEFINE(__LC_SAVE_AREA_64, offsetof(struct _lowcore, save_area_64));
#ifdef CONFIG_32BIT
DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
#else /* CONFIG_32BIT */
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
index 255435663bf8..f8828d38fa6e 100644
--- a/arch/s390/kernel/base.S
+++ b/arch/s390/kernel/base.S
@@ -86,6 +86,8 @@ s390_base_pgm_handler_fn:
ENTRY(diag308_reset)
larl %r4,.Lctlregs # Save control registers
stctg %c0,%c15,0(%r4)
+ larl %r4,.Lfpctl # Floating point control register
+ stfpc 0(%r4)
larl %r4,.Lrestart_psw # Setup restart PSW at absolute 0
lghi %r3,0
lg %r4,0(%r4) # Save PSW
@@ -99,6 +101,8 @@ ENTRY(diag308_reset)
sam64 # Switch to 64 bit addressing mode
larl %r4,.Lctlregs # Restore control registers
lctlg %c0,%c15,0(%r4)
+ larl %r4,.Lfpctl # Restore floating point ctl register
+ lfpc 0(%r4)
br %r14
.align 16
.Lrestart_psw:
@@ -110,6 +114,8 @@ ENTRY(diag308_reset)
.rept 16
.quad 0
.endr
+.Lfpctl:
+ .long 0
.previous
#else /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 53acaa86dd94..84a982898448 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -60,12 +60,9 @@
#include "compat_linux.h"
-long psw_user32_bits = (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
- PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
- PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
-long psw32_user_bits = (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME |
- PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
- PSW32_MASK_PSTATE);
+u32 psw32_user_bits = PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT |
+ PSW32_DEFAULT_KEY | PSW32_MASK_BASE | PSW32_MASK_MCHECK |
+ PSW32_MASK_PSTATE | PSW32_ASC_HOME;
/* For this source file, we want overflow handling. */
@@ -365,12 +362,7 @@ asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
if (set) {
if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
return -EFAULT;
- switch (_NSIG_WORDS) {
- case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
- case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
- case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
- case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
- }
+ s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
}
set_fs (KERNEL_DS);
ret = sys_rt_sigprocmask(how,
@@ -380,12 +372,8 @@ asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
set_fs (old_fs);
if (ret) return ret;
if (oset) {
- switch (_NSIG_WORDS) {
- case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
- case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
- case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
- case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
- }
+ s32.sig[1] = (s.sig[0] >> 32);
+ s32.sig[0] = s.sig[0];
if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
return -EFAULT;
}
@@ -404,12 +392,8 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
ret = sys_rt_sigpending((sigset_t __force __user *) &s, sigsetsize);
set_fs (old_fs);
if (!ret) {
- switch (_NSIG_WORDS) {
- case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
- case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
- case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
- case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
- }
+ s32.sig[1] = (s.sig[0] >> 32);
+ s32.sig[0] = s.sig[0];
if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
return -EFAULT;
}
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index a9a285b8c4ad..4f68c81d3ffa 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -141,7 +141,8 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
break;
case __SI_FAULT >> 16:
err |= __get_user(tmp, &from->si_addr);
- to->si_addr = (void __user *)(u64) (tmp & PSW32_ADDR_INSN);
+ to->si_addr = (void __force __user *)
+ (u64) (tmp & PSW32_ADDR_INSN);
break;
case __SI_POLL >> 16:
err |= __get_user(to->si_band, &from->si_band);
@@ -213,16 +214,8 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
ret = get_user(sa_handler, &act->sa_handler);
ret |= __copy_from_user(&set32, &act->sa_mask,
sizeof(compat_sigset_t));
- switch (_NSIG_WORDS) {
- case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
- | (((long)set32.sig[7]) << 32);
- case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
- | (((long)set32.sig[5]) << 32);
- case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
- | (((long)set32.sig[3]) << 32);
- case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
- | (((long)set32.sig[1]) << 32);
- }
+ new_ka.sa.sa_mask.sig[0] =
+ set32.sig[0] | (((long)set32.sig[1]) << 32);
ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
if (ret)
@@ -233,20 +226,8 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- switch (_NSIG_WORDS) {
- case 4:
- set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
- set32.sig[6] = old_ka.sa.sa_mask.sig[3];
- case 3:
- set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
- set32.sig[4] = old_ka.sa.sa_mask.sig[2];
- case 2:
- set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
- set32.sig[2] = old_ka.sa.sa_mask.sig[1];
- case 1:
- set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
- set32.sig[0] = old_ka.sa.sa_mask.sig[0];
- }
+ set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
+ set32.sig[0] = old_ka.sa.sa_mask.sig[0];
ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler);
ret |= __copy_to_user(&oact->sa_mask, &set32,
sizeof(compat_sigset_t));
@@ -300,9 +281,10 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
_s390_regs_common32 regs32;
int err, i;
- regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits,
- (__u32)(regs->psw.mask >> 32));
- regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
+ regs32.psw.mask = psw32_user_bits |
+ ((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER);
+ regs32.psw.addr = (__u32) regs->psw.addr |
+ (__u32)(regs->psw.mask & PSW_MASK_BA);
for (i = 0; i < NUM_GPRS; i++)
regs32.gprs[i] = (__u32) regs->gprs[i];
save_access_regs(current->thread.acrs);
@@ -327,8 +309,9 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
if (err)
return err;
- regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
- (__u64)regs32.psw.mask << 32);
+ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+ (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
+ (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
for (i = 0; i < NUM_GPRS; i++)
regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -342,7 +325,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
return err;
restore_fp_regs(&current->thread.fp_regs);
- regs->svcnr = 0; /* disable syscall checks */
+ clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */
return 0;
}
@@ -496,11 +479,11 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
- regs->gprs[14] = (__u64) ka->sa.sa_restorer;
+ regs->gprs[14] = (__u64) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
} else {
- regs->gprs[14] = (__u64) frame->retcode;
+ regs->gprs[14] = (__u64) frame->retcode | PSW32_ADDR_AMODE;
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
- (u16 __user *)(frame->retcode)))
+ (u16 __force __user *)(frame->retcode)))
goto give_sigsegv;
}
@@ -509,11 +492,12 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
goto give_sigsegv;
/* Set up registers for signal handler */
- regs->gprs[15] = (__u64) frame;
- regs->psw.addr = (__u64) ka->sa.sa_handler;
+ regs->gprs[15] = (__force __u64) frame;
+ regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */
+ regs->psw.addr = (__force __u64) ka->sa.sa_handler;
regs->gprs[2] = map_signal(sig);
- regs->gprs[3] = (__u64) &frame->sc;
+ regs->gprs[3] = (__force __u64) &frame->sc;
/* We forgot to include these in the sigcontext.
To avoid breaking binary compatibility, they are passed as args. */
@@ -521,7 +505,7 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
regs->gprs[5] = current->thread.prot_addr;
/* Place signal number on stack to allow backtrace from handler. */
- if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
+ if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
goto give_sigsegv;
return 0;
@@ -564,20 +548,21 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
} else {
regs->gprs[14] = (__u64) frame->retcode;
err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
- (u16 __user *)(frame->retcode));
+ (u16 __force __user *)(frame->retcode));
}
/* Set up backchain. */
- if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
+ if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
goto give_sigsegv;
/* Set up registers for signal handler */
- regs->gprs[15] = (__u64) frame;
+ regs->gprs[15] = (__force __u64) frame;
+ regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */
regs->psw.addr = (__u64) ka->sa.sa_handler;
regs->gprs[2] = map_signal(sig);
- regs->gprs[3] = (__u64) &frame->info;
- regs->gprs[4] = (__u64) &frame->uc;
+ regs->gprs[3] = (__force __u64) &frame->info;
+ regs->gprs[4] = (__force __u64) &frame->uc;
return 0;
give_sigsegv:
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 7526db6bf501..5006a1d9f5d0 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1623,8 +1623,7 @@ ENTRY(sys_syncfs_wrapper)
lgfr %r2,%r2 # int
jg sys_syncfs
- .globl sys_setns_wrapper
-sys_setns_wrapper:
+ENTRY(sys_setns_wrapper)
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
jg sys_setns
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
new file mode 100644
index 000000000000..39f8fd4438fc
--- /dev/null
+++ b/arch/s390/kernel/crash_dump.c
@@ -0,0 +1,426 @@
+/*
+ * S390 kdump implementation
+ *
+ * Copyright IBM Corp. 2011
+ * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
+ */
+
+#include <linux/crash_dump.h>
+#include <asm/lowcore.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/crash_dump.h>
+#include <linux/bootmem.h>
+#include <linux/elf.h>
+#include <asm/ipl.h>
+
+#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
+#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
+#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
+
+/*
+ * Copy one page from "oldmem"
+ *
+ * For the kdump reserved memory this functions performs a swap operation:
+ * - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE].
+ * - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+ size_t csize, unsigned long offset, int userbuf)
+{
+ unsigned long src;
+
+ if (!csize)
+ return 0;
+
+ src = (pfn << PAGE_SHIFT) + offset;
+ if (src < OLDMEM_SIZE)
+ src += OLDMEM_BASE;
+ else if (src > OLDMEM_BASE &&
+ src < OLDMEM_BASE + OLDMEM_SIZE)
+ src -= OLDMEM_BASE;
+ if (userbuf)
+ copy_to_user_real((void __force __user *) buf, (void *) src,
+ csize);
+ else
+ memcpy_real(buf, (void *) src, csize);
+ return csize;
+}
+
+/*
+ * Copy memory from old kernel
+ */
+static int copy_from_oldmem(void *dest, void *src, size_t count)
+{
+ unsigned long copied = 0;
+ int rc;
+
+ if ((unsigned long) src < OLDMEM_SIZE) {
+ copied = min(count, OLDMEM_SIZE - (unsigned long) src);
+ rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
+ if (rc)
+ return rc;
+ }
+ return memcpy_real(dest + copied, src + copied, count - copied);
+}
+
+/*
+ * Alloc memory and panic in case of ENOMEM
+ */
+static void *kzalloc_panic(int len)
+{
+ void *rc;
+
+ rc = kzalloc(len, GFP_KERNEL);
+ if (!rc)
+ panic("s390 kdump kzalloc (%d) failed", len);
+ return rc;
+}
+
+/*
+ * Get memory layout and create hole for oldmem
+ */
+static struct mem_chunk *get_memory_layout(void)
+{
+ struct mem_chunk *chunk_array;
+
+ chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk));
+ detect_memory_layout(chunk_array);
+ create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE, CHUNK_CRASHK);
+ return chunk_array;
+}
+
+/*
+ * Initialize ELF note
+ */
+static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len,
+ const char *name)
+{
+ Elf64_Nhdr *note;
+ u64 len;
+
+ note = (Elf64_Nhdr *)buf;
+ note->n_namesz = strlen(name) + 1;
+ note->n_descsz = d_len;
+ note->n_type = type;
+ len = sizeof(Elf64_Nhdr);
+
+ memcpy(buf + len, name, note->n_namesz);
+ len = roundup(len + note->n_namesz, 4);
+
+ memcpy(buf + len, desc, note->n_descsz);
+ len = roundup(len + note->n_descsz, 4);
+
+ return PTR_ADD(buf, len);
+}
+
+/*
+ * Initialize prstatus note
+ */
+static void *nt_prstatus(void *ptr, struct save_area *sa)
+{
+ struct elf_prstatus nt_prstatus;
+ static int cpu_nr = 1;
+
+ memset(&nt_prstatus, 0, sizeof(nt_prstatus));
+ memcpy(&nt_prstatus.pr_reg.gprs, sa->gp_regs, sizeof(sa->gp_regs));
+ memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw));
+ memcpy(&nt_prstatus.pr_reg.acrs, sa->acc_regs, sizeof(sa->acc_regs));
+ nt_prstatus.pr_pid = cpu_nr;
+ cpu_nr++;
+
+ return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus),
+ "CORE");
+}
+
+/*
+ * Initialize fpregset (floating point) note
+ */
+static void *nt_fpregset(void *ptr, struct save_area *sa)
+{
+ elf_fpregset_t nt_fpregset;
+
+ memset(&nt_fpregset, 0, sizeof(nt_fpregset));
+ memcpy(&nt_fpregset.fpc, &sa->fp_ctrl_reg, sizeof(sa->fp_ctrl_reg));
+ memcpy(&nt_fpregset.fprs, &sa->fp_regs, sizeof(sa->fp_regs));
+
+ return nt_init(ptr, NT_PRFPREG, &nt_fpregset, sizeof(nt_fpregset),
+ "CORE");
+}
+
+/*
+ * Initialize timer note
+ */
+static void *nt_s390_timer(void *ptr, struct save_area *sa)
+{
+ return nt_init(ptr, NT_S390_TIMER, &sa->timer, sizeof(sa->timer),
+ KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize TOD clock comparator note
+ */
+static void *nt_s390_tod_cmp(void *ptr, struct save_area *sa)
+{
+ return nt_init(ptr, NT_S390_TODCMP, &sa->clk_cmp,
+ sizeof(sa->clk_cmp), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize TOD programmable register note
+ */
+static void *nt_s390_tod_preg(void *ptr, struct save_area *sa)
+{
+ return nt_init(ptr, NT_S390_TODPREG, &sa->tod_reg,
+ sizeof(sa->tod_reg), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize control register note
+ */
+static void *nt_s390_ctrs(void *ptr, struct save_area *sa)
+{
+ return nt_init(ptr, NT_S390_CTRS, &sa->ctrl_regs,
+ sizeof(sa->ctrl_regs), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize prefix register note
+ */
+static void *nt_s390_prefix(void *ptr, struct save_area *sa)
+{
+ return nt_init(ptr, NT_S390_PREFIX, &sa->pref_reg,
+ sizeof(sa->pref_reg), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Fill ELF notes for one CPU with save area registers
+ */
+void *fill_cpu_elf_notes(void *ptr, struct save_area *sa)
+{
+ ptr = nt_prstatus(ptr, sa);
+ ptr = nt_fpregset(ptr, sa);
+ ptr = nt_s390_timer(ptr, sa);
+ ptr = nt_s390_tod_cmp(ptr, sa);
+ ptr = nt_s390_tod_preg(ptr, sa);
+ ptr = nt_s390_ctrs(ptr, sa);
+ ptr = nt_s390_prefix(ptr, sa);
+ return ptr;
+}
+
+/*
+ * Initialize prpsinfo note (new kernel)
+ */
+static void *nt_prpsinfo(void *ptr)
+{
+ struct elf_prpsinfo prpsinfo;
+
+ memset(&prpsinfo, 0, sizeof(prpsinfo));
+ prpsinfo.pr_sname = 'R';
+ strcpy(prpsinfo.pr_fname, "vmlinux");
+ return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo),
+ KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize vmcoreinfo note (new kernel)
+ */
+static void *nt_vmcoreinfo(void *ptr)
+{
+ char nt_name[11], *vmcoreinfo;
+ Elf64_Nhdr note;
+ void *addr;
+
+ if (copy_from_oldmem(&addr, &S390_lowcore.vmcore_info, sizeof(addr)))
+ return ptr;
+ memset(nt_name, 0, sizeof(nt_name));
+ if (copy_from_oldmem(&note, addr, sizeof(note)))
+ return ptr;
+ if (copy_from_oldmem(nt_name, addr + sizeof(note), sizeof(nt_name) - 1))
+ return ptr;
+ if (strcmp(nt_name, "VMCOREINFO") != 0)
+ return ptr;
+ vmcoreinfo = kzalloc_panic(note.n_descsz + 1);
+ if (copy_from_oldmem(vmcoreinfo, addr + 24, note.n_descsz))
+ return ptr;
+ vmcoreinfo[note.n_descsz + 1] = 0;
+ return nt_init(ptr, 0, vmcoreinfo, note.n_descsz, "VMCOREINFO");
+}
+
+/*
+ * Initialize ELF header (new kernel)
+ */
+static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt)
+{
+ memset(ehdr, 0, sizeof(*ehdr));
+ memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
+ ehdr->e_ident[EI_CLASS] = ELFCLASS64;
+ ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
+ ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+ memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
+ ehdr->e_type = ET_CORE;
+ ehdr->e_machine = EM_S390;
+ ehdr->e_version = EV_CURRENT;
+ ehdr->e_phoff = sizeof(Elf64_Ehdr);
+ ehdr->e_ehsize = sizeof(Elf64_Ehdr);
+ ehdr->e_phentsize = sizeof(Elf64_Phdr);
+ ehdr->e_phnum = mem_chunk_cnt + 1;
+ return ehdr + 1;
+}
+
+/*
+ * Return CPU count for ELF header (new kernel)
+ */
+static int get_cpu_cnt(void)
+{
+ int i, cpus = 0;
+
+ for (i = 0; zfcpdump_save_areas[i]; i++) {
+ if (zfcpdump_save_areas[i]->pref_reg == 0)
+ continue;
+ cpus++;
+ }
+ return cpus;
+}
+
+/*
+ * Return memory chunk count for ELF header (new kernel)
+ */
+static int get_mem_chunk_cnt(void)
+{
+ struct mem_chunk *chunk_array, *mem_chunk;
+ int i, cnt = 0;
+
+ chunk_array = get_memory_layout();
+ for (i = 0; i < MEMORY_CHUNKS; i++) {
+ mem_chunk = &chunk_array[i];
+ if (chunk_array[i].type != CHUNK_READ_WRITE &&
+ chunk_array[i].type != CHUNK_READ_ONLY)
+ continue;
+ if (mem_chunk->size == 0)
+ continue;
+ cnt++;
+ }
+ kfree(chunk_array);
+ return cnt;
+}
+
+/*
+ * Relocate pointer in order to allow vmcore code access the data
+ */
+static inline unsigned long relocate(unsigned long addr)
+{
+ return OLDMEM_BASE + addr;
+}
+
+/*
+ * Initialize ELF loads (new kernel)
+ */
+static int loads_init(Elf64_Phdr *phdr, u64 loads_offset)
+{
+ struct mem_chunk *chunk_array, *mem_chunk;
+ int i;
+
+ chunk_array = get_memory_layout();
+ for (i = 0; i < MEMORY_CHUNKS; i++) {
+ mem_chunk = &chunk_array[i];
+ if (mem_chunk->size == 0)
+ break;
+ if (chunk_array[i].type != CHUNK_READ_WRITE &&
+ chunk_array[i].type != CHUNK_READ_ONLY)
+ continue;
+ else
+ phdr->p_filesz = mem_chunk->size;
+ phdr->p_type = PT_LOAD;
+ phdr->p_offset = mem_chunk->addr;
+ phdr->p_vaddr = mem_chunk->addr;
+ phdr->p_paddr = mem_chunk->addr;
+ phdr->p_memsz = mem_chunk->size;
+ phdr->p_flags = PF_R | PF_W | PF_X;
+ phdr->p_align = PAGE_SIZE;
+ phdr++;
+ }
+ kfree(chunk_array);
+ return i;
+}
+
+/*
+ * Initialize notes (new kernel)
+ */
+static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
+{
+ struct save_area *sa;
+ void *ptr_start = ptr;
+ int i;
+
+ ptr = nt_prpsinfo(ptr);
+
+ for (i = 0; zfcpdump_save_areas[i]; i++) {
+ sa = zfcpdump_save_areas[i];
+ if (sa->pref_reg == 0)
+ continue;
+ ptr = fill_cpu_elf_notes(ptr, sa);
+ }
+ ptr = nt_vmcoreinfo(ptr);
+ memset(phdr, 0, sizeof(*phdr));
+ phdr->p_type = PT_NOTE;
+ phdr->p_offset = relocate(notes_offset);
+ phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start);
+ phdr->p_memsz = phdr->p_filesz;
+ return ptr;
+}
+
+/*
+ * Create ELF core header (new kernel)
+ */
+static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
+{
+ Elf64_Phdr *phdr_notes, *phdr_loads;
+ int mem_chunk_cnt;
+ void *ptr, *hdr;
+ u32 alloc_size;
+ u64 hdr_off;
+
+ mem_chunk_cnt = get_mem_chunk_cnt();
+
+ alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
+ mem_chunk_cnt * sizeof(Elf64_Phdr);
+ hdr = kzalloc_panic(alloc_size);
+ /* Init elf header */
+ ptr = ehdr_init(hdr, mem_chunk_cnt);
+ /* Init program headers */
+ phdr_notes = ptr;
+ ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr));
+ phdr_loads = ptr;
+ ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * mem_chunk_cnt);
+ /* Init notes */
+ hdr_off = PTR_DIFF(ptr, hdr);
+ ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
+ /* Init loads */
+ hdr_off = PTR_DIFF(ptr, hdr);
+ loads_init(phdr_loads, ((unsigned long) hdr) + hdr_off);
+ *elfcorebuf_sz = hdr_off;
+ *elfcorebuf = (void *) relocate((unsigned long) hdr);
+ BUG_ON(*elfcorebuf_sz > alloc_size);
+}
+
+/*
+ * Create kdump ELF core header in new kernel, if it has not been passed via
+ * the "elfcorehdr" kernel parameter
+ */
+static int setup_kdump_elfcorehdr(void)
+{
+ size_t elfcorebuf_sz;
+ char *elfcorebuf;
+
+ if (!OLDMEM_BASE || is_kdump_kernel())
+ return -EINVAL;
+ s390_elf_corehdr_create(&elfcorebuf, &elfcorebuf_sz);
+ elfcorehdr_addr = (unsigned long long) elfcorebuf;
+ elfcorehdr_size = elfcorebuf_sz;
+ return 0;
+}
+
+subsys_initcall(setup_kdump_elfcorehdr);
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index f297456dba7a..37394b3413e2 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -252,7 +252,7 @@ static noinline __init void setup_lowcore_early(void)
{
psw_t psw;
- psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+ psw.mask = PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA;
psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler;
S390_lowcore.external_new_psw = psw;
psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 02ec8fe7d03f..b13157057e02 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -43,16 +43,15 @@ SP_R13 = STACK_FRAME_OVERHEAD + __PT_GPRS + 52
SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 56
SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 60
SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
-SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR
+SP_SVC_CODE = STACK_FRAME_OVERHEAD + __PT_SVC_CODE
SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
- _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP )
+ _TIF_MCCK_PENDING | _TIF_PER_TRAP )
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING)
-_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
- _TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
+_TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
+ _TIF_SYSCALL_TRACEPOINT)
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
@@ -228,9 +227,10 @@ ENTRY(system_call)
sysc_saveall:
SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SAVE_AREA
- mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW
- mvc SP_ILC(4,%r15),__LC_SVC_ILC
l %r12,__LC_THREAD_INFO # load pointer to thread_info struct
+ mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+ mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+ oi __TI_flags+3(%r12),_TIF_SYSCALL
sysc_vtime:
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
sysc_stime:
@@ -239,17 +239,17 @@ sysc_update:
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
sysc_do_svc:
xr %r7,%r7
- icm %r7,3,SP_SVCNR(%r15) # load svc number and test for svc 0
+ icm %r7,3,SP_SVC_CODE+2(%r15)# load svc number and test for svc 0
bnz BASED(sysc_nr_ok) # svc number > 0
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
bnl BASED(sysc_nr_ok)
- sth %r1,SP_SVCNR(%r15)
+ sth %r1,SP_SVC_CODE+2(%r15)
lr %r7,%r1 # copy svc number to %r7
sysc_nr_ok:
sll %r7,2 # svc number *4
l %r10,BASED(.Lsysc_table)
- tm __TI_flags+2(%r12),_TIF_SYSCALL
+ tm __TI_flags+2(%r12),_TIF_TRACE >> 8
mvc SP_ARGS(4,%r15),SP_R7(%r15)
l %r8,0(%r7,%r10) # get system call addr.
bnz BASED(sysc_tracesys)
@@ -259,23 +259,19 @@ sysc_nr_ok:
sysc_return:
LOCKDEP_SYS_EXIT
sysc_tif:
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
+ bno BASED(sysc_restore)
tm __TI_flags+3(%r12),_TIF_WORK_SVC
bnz BASED(sysc_work) # there is work to do (signals etc.)
+ ni __TI_flags+3(%r12),255-_TIF_SYSCALL
sysc_restore:
RESTORE_ALL __LC_RETURN_PSW,1
sysc_done:
#
-# There is work to do, but first we need to check if we return to userspace.
-#
-sysc_work:
- tm SP_PSW+1(%r15),0x01 # returning to user ?
- bno BASED(sysc_restore)
-
-#
# One of the work bits is on. Find out which one.
#
-sysc_work_tif:
+sysc_work:
tm __TI_flags+3(%r12),_TIF_MCCK_PENDING
bo BASED(sysc_mcck_pending)
tm __TI_flags+3(%r12),_TIF_NEED_RESCHED
@@ -284,8 +280,6 @@ sysc_work_tif:
bo BASED(sysc_sigpending)
tm __TI_flags+3(%r12),_TIF_NOTIFY_RESUME
bo BASED(sysc_notify_resume)
- tm __TI_flags+3(%r12),_TIF_RESTART_SVC
- bo BASED(sysc_restart)
tm __TI_flags+3(%r12),_TIF_PER_TRAP
bo BASED(sysc_singlestep)
b BASED(sysc_return) # beware of critical section cleanup
@@ -314,11 +308,14 @@ sysc_sigpending:
la %r2,SP_PTREGS(%r15) # load pt_regs
l %r1,BASED(.Ldo_signal)
basr %r14,%r1 # call do_signal
- tm __TI_flags+3(%r12),_TIF_RESTART_SVC
- bo BASED(sysc_restart)
- tm __TI_flags+3(%r12),_TIF_PER_TRAP
- bo BASED(sysc_singlestep)
- b BASED(sysc_return)
+ tm __TI_flags+3(%r12),_TIF_SYSCALL
+ bno BASED(sysc_return)
+ lm %r2,%r6,SP_R2(%r15) # load svc arguments
+ xr %r7,%r7 # svc 0 returns -ENOSYS
+ clc SP_SVC_CODE+2(2,%r15),BASED(.Lnr_syscalls+2)
+ bnl BASED(sysc_nr_ok) # invalid svc number -> do svc 0
+ icm %r7,3,SP_SVC_CODE+2(%r15)# load new svc number
+ b BASED(sysc_nr_ok) # restart svc
#
# _TIF_NOTIFY_RESUME is set, call do_notify_resume
@@ -329,24 +326,11 @@ sysc_notify_resume:
la %r14,BASED(sysc_return)
br %r1 # call do_notify_resume
-
-#
-# _TIF_RESTART_SVC is set, set up registers and restart svc
-#
-sysc_restart:
- ni __TI_flags+3(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
- l %r7,SP_R2(%r15) # load new svc number
- mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
- lm %r2,%r6,SP_R2(%r15) # load svc arguments
- sth %r7,SP_SVCNR(%r15)
- b BASED(sysc_nr_ok) # restart svc
-
#
# _TIF_PER_TRAP is set, call do_per_trap
#
sysc_singlestep:
- ni __TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
- xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
+ ni __TI_flags+3(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP)
la %r2,SP_PTREGS(%r15) # address of register-save area
l %r1,BASED(.Lhandle_per) # load adr. of per handler
la %r14,BASED(sysc_return) # load adr. of system return
@@ -361,7 +345,7 @@ sysc_tracesys:
la %r2,SP_PTREGS(%r15) # load pt_regs
la %r3,0
xr %r0,%r0
- icm %r0,3,SP_SVCNR(%r15)
+ icm %r0,3,SP_SVC_CODE(%r15)
st %r0,SP_R2(%r15)
basr %r14,%r1
cl %r2,BASED(.Lnr_syscalls)
@@ -376,7 +360,7 @@ sysc_tracego:
basr %r14,%r8 # call sys_xxx
st %r2,SP_R2(%r15) # store return value
sysc_tracenogo:
- tm __TI_flags+2(%r12),_TIF_SYSCALL
+ tm __TI_flags+2(%r12),_TIF_TRACE >> 8
bz BASED(sysc_return)
l %r1,BASED(.Ltrace_exit)
la %r2,SP_PTREGS(%r15) # load pt_regs
@@ -454,7 +438,6 @@ ENTRY(pgm_check_handler)
bnz BASED(pgm_per) # got per exception -> special case
SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SAVE_AREA
- xc SP_ILC(4,%r15),SP_ILC(%r15)
mvc SP_PSW(8,%r15),__LC_PGM_OLD_PSW
l %r12,__LC_THREAD_INFO # load pointer to thread_info struct
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -530,9 +513,10 @@ pgm_exit2:
pgm_svcper:
SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SAVE_AREA
- mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW
- mvc SP_ILC(4,%r15),__LC_SVC_ILC
l %r12,__LC_THREAD_INFO # load pointer to thread_info struct
+ mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+ mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+ oi __TI_flags+3(%r12),(_TIF_SYSCALL | _TIF_PER_TRAP)
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
@@ -540,7 +524,6 @@ pgm_svcper:
mvc __THREAD_per_cause(2,%r8),__LC_PER_CAUSE
mvc __THREAD_per_address(4,%r8),__LC_PER_ADDRESS
mvc __THREAD_per_paid(1,%r8),__LC_PER_PAID
- oi __TI_flags+3(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
lm %r2,%r6,SP_R2(%r15) # load svc arguments
b BASED(sysc_do_svc)
@@ -550,7 +533,6 @@ pgm_svcper:
#
kernel_per:
REENABLE_IRQS
- xc SP_SVCNR(2,%r15),SP_SVCNR(%r15)
la %r2,SP_PTREGS(%r15) # address of register-save area
l %r1,BASED(.Lhandle_per) # load adr. of per handler
basr %r14,%r1 # branch to do_single_step
@@ -853,13 +835,13 @@ restart_go:
# PSW restart interrupt handler
#
ENTRY(psw_restart_int_handler)
- st %r15,__LC_SAVE_AREA_64(%r0) # save r15
+ st %r15,__LC_SAVE_AREA+48(%r0) # save r15
basr %r15,0
0: l %r15,.Lrestart_stack-0b(%r15) # load restart stack
l %r15,0(%r15)
ahi %r15,-SP_SIZE # make room for pt_regs
stm %r0,%r14,SP_R0(%r15) # store gprs %r0-%r14 to stack
- mvc SP_R15(4,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack
+ mvc SP_R15(4,%r15),__LC_SAVE_AREA+48(%r0)# store saved %r15 to stack
mvc SP_PSW(8,%r15),__LC_RST_OLD_PSW(%r0) # store restart old psw
xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0
basr %r14,0
@@ -965,9 +947,11 @@ cleanup_system_call:
s %r15,BASED(.Lc_spsize) # make room for registers & psw
st %r15,12(%r12)
CREATE_STACK_FRAME __LC_SAVE_AREA
- mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW
- mvc SP_ILC(4,%r15),__LC_SVC_ILC
mvc 0(4,%r12),__LC_THREAD_INFO
+ l %r12,__LC_THREAD_INFO
+ mvc SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+ mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+ oi __TI_flags+3(%r12),_TIF_SYSCALL
cleanup_vtime:
clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
bhe BASED(cleanup_stime)
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index 66729eb7bbc5..ef8fb1d6e8d7 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -5,24 +5,33 @@
#include <linux/signal.h>
#include <asm/ptrace.h>
+
+extern void (*pgm_check_table[128])(struct pt_regs *, long, unsigned long);
+extern void *restart_stack;
+
+asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
+asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);
+
void do_protection_exception(struct pt_regs *, long, unsigned long);
void do_dat_exception(struct pt_regs *, long, unsigned long);
void do_asce_exception(struct pt_regs *, long, unsigned long);
-extern int sysctl_userprocess_debug;
-
void do_per_trap(struct pt_regs *regs);
void syscall_trace(struct pt_regs *regs, int entryexit);
void kernel_stack_overflow(struct pt_regs * regs);
void do_signal(struct pt_regs *regs);
int handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
+void do_notify_resume(struct pt_regs *regs);
void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long);
+void do_restart(void);
int __cpuinit start_secondary(void *cpuvoid);
void __init startup_init(void);
void die(const char * str, struct pt_regs * regs, long err);
+void __init time_init(void);
+
struct s390_mmap_arg_struct;
struct fadvise64_64_args;
struct old_sigaction;
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 713da0760538..83a93747e2fd 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -43,19 +43,18 @@ SP_R13 = STACK_FRAME_OVERHEAD + __PT_GPRS + 104
SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 112
SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 120
SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
-SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR
+SP_SVC_CODE = STACK_FRAME_OVERHEAD + __PT_SVC_CODE
SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
- _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP )
+ _TIF_MCCK_PENDING | _TIF_PER_TRAP )
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING)
-_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
- _TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
+_TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
+ _TIF_SYSCALL_TRACEPOINT)
_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
#define BASED(name) name-system_call(%r13)
@@ -249,9 +248,10 @@ ENTRY(system_call)
sysc_saveall:
SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SAVE_AREA
- mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
- mvc SP_ILC(4,%r15),__LC_SVC_ILC
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
+ mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
+ mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+ oi __TI_flags+7(%r12),_TIF_SYSCALL
sysc_vtime:
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
sysc_stime:
@@ -260,14 +260,14 @@ sysc_update:
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
LAST_BREAK
sysc_do_svc:
- llgh %r7,SP_SVCNR(%r15)
+ llgh %r7,SP_SVC_CODE+2(%r15)
slag %r7,%r7,2 # shift and test for svc 0
jnz sysc_nr_ok
# svc 0: system call number in %r1
llgfr %r1,%r1 # clear high word in r1
cghi %r1,NR_syscalls
jnl sysc_nr_ok
- sth %r1,SP_SVCNR(%r15)
+ sth %r1,SP_SVC_CODE+2(%r15)
slag %r7,%r1,2 # shift and test for svc 0
sysc_nr_ok:
larl %r10,sys_call_table
@@ -277,7 +277,7 @@ sysc_nr_ok:
larl %r10,sys_call_table_emu # use 31 bit emulation system calls
sysc_noemu:
#endif
- tm __TI_flags+6(%r12),_TIF_SYSCALL
+ tm __TI_flags+6(%r12),_TIF_TRACE >> 8
mvc SP_ARGS(8,%r15),SP_R7(%r15)
lgf %r8,0(%r7,%r10) # load address of system call routine
jnz sysc_tracesys
@@ -287,23 +287,19 @@ sysc_noemu:
sysc_return:
LOCKDEP_SYS_EXIT
sysc_tif:
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
+ jno sysc_restore
tm __TI_flags+7(%r12),_TIF_WORK_SVC
jnz sysc_work # there is work to do (signals etc.)
+ ni __TI_flags+7(%r12),255-_TIF_SYSCALL
sysc_restore:
RESTORE_ALL __LC_RETURN_PSW,1
sysc_done:
#
-# There is work to do, but first we need to check if we return to userspace.
-#
-sysc_work:
- tm SP_PSW+1(%r15),0x01 # returning to user ?
- jno sysc_restore
-
-#
# One of the work bits is on. Find out which one.
#
-sysc_work_tif:
+sysc_work:
tm __TI_flags+7(%r12),_TIF_MCCK_PENDING
jo sysc_mcck_pending
tm __TI_flags+7(%r12),_TIF_NEED_RESCHED
@@ -312,8 +308,6 @@ sysc_work_tif:
jo sysc_sigpending
tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME
jo sysc_notify_resume
- tm __TI_flags+7(%r12),_TIF_RESTART_SVC
- jo sysc_restart
tm __TI_flags+7(%r12),_TIF_PER_TRAP
jo sysc_singlestep
j sysc_return # beware of critical section cleanup
@@ -339,11 +333,15 @@ sysc_sigpending:
ni __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
la %r2,SP_PTREGS(%r15) # load pt_regs
brasl %r14,do_signal # call do_signal
- tm __TI_flags+7(%r12),_TIF_RESTART_SVC
- jo sysc_restart
- tm __TI_flags+7(%r12),_TIF_PER_TRAP
- jo sysc_singlestep
- j sysc_return
+ tm __TI_flags+7(%r12),_TIF_SYSCALL
+ jno sysc_return
+ lmg %r2,%r6,SP_R2(%r15) # load svc arguments
+ lghi %r7,0 # svc 0 returns -ENOSYS
+ lh %r1,SP_SVC_CODE+2(%r15) # load new svc number
+ cghi %r1,NR_syscalls
+ jnl sysc_nr_ok # invalid svc number -> do svc 0
+ slag %r7,%r1,2
+ j sysc_nr_ok # restart svc
#
# _TIF_NOTIFY_RESUME is set, call do_notify_resume
@@ -354,23 +352,10 @@ sysc_notify_resume:
jg do_notify_resume # call do_notify_resume
#
-# _TIF_RESTART_SVC is set, set up registers and restart svc
-#
-sysc_restart:
- ni __TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
- lg %r7,SP_R2(%r15) # load new svc number
- mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
- lmg %r2,%r6,SP_R2(%r15) # load svc arguments
- sth %r7,SP_SVCNR(%r15)
- slag %r7,%r7,2
- j sysc_nr_ok # restart svc
-
-#
# _TIF_PER_TRAP is set, call do_per_trap
#
sysc_singlestep:
- ni __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
- xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
+ ni __TI_flags+7(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP)
la %r2,SP_PTREGS(%r15) # address of register-save area
larl %r14,sysc_return # load adr. of system return
jg do_per_trap
@@ -382,7 +367,7 @@ sysc_singlestep:
sysc_tracesys:
la %r2,SP_PTREGS(%r15) # load pt_regs
la %r3,0
- llgh %r0,SP_SVCNR(%r15)
+ llgh %r0,SP_SVC_CODE+2(%r15)
stg %r0,SP_R2(%r15)
brasl %r14,do_syscall_trace_enter
lghi %r0,NR_syscalls
@@ -397,7 +382,7 @@ sysc_tracego:
basr %r14,%r8 # call sys_xxx
stg %r2,SP_R2(%r15) # store return value
sysc_tracenogo:
- tm __TI_flags+6(%r12),_TIF_SYSCALL
+ tm __TI_flags+6(%r12),_TIF_TRACE >> 8
jz sysc_return
la %r2,SP_PTREGS(%r15) # load pt_regs
larl %r14,sysc_return # return point is sysc_return
@@ -470,7 +455,6 @@ ENTRY(pgm_check_handler)
jnz pgm_per # got per exception -> special case
SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SAVE_AREA
- xc SP_ILC(4,%r15),SP_ILC(%r15)
mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
HANDLE_SIE_INTERCEPT
@@ -550,9 +534,10 @@ pgm_exit2:
pgm_svcper:
SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SAVE_AREA
- mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
- mvc SP_ILC(4,%r15),__LC_SVC_ILC
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
+ mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
+ mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+ oi __TI_flags+7(%r12),(_TIF_SYSCALL | _TIF_PER_TRAP)
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
@@ -561,7 +546,6 @@ pgm_svcper:
mvc __THREAD_per_cause(2,%r8),__LC_PER_CAUSE
mvc __THREAD_per_address(8,%r8),__LC_PER_ADDRESS
mvc __THREAD_per_paid(1,%r8),__LC_PER_PAID
- oi __TI_flags+7(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
lmg %r2,%r6,SP_R2(%r15) # load svc arguments
j sysc_do_svc
@@ -571,7 +555,6 @@ pgm_svcper:
#
kernel_per:
REENABLE_IRQS
- xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
la %r2,SP_PTREGS(%r15) # address of register-save area
brasl %r14,do_per_trap
j pgm_exit
@@ -869,12 +852,12 @@ restart_go:
# PSW restart interrupt handler
#
ENTRY(psw_restart_int_handler)
- stg %r15,__LC_SAVE_AREA_64(%r0) # save r15
+ stg %r15,__LC_SAVE_AREA+120(%r0) # save r15
larl %r15,restart_stack # load restart stack
lg %r15,0(%r15)
aghi %r15,-SP_SIZE # make room for pt_regs
stmg %r0,%r14,SP_R0(%r15) # store gprs %r0-%r14 to stack
- mvc SP_R15(8,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack
+ mvc SP_R15(8,%r15),__LC_SAVE_AREA+120(%r0)# store saved %r15 to stack
mvc SP_PSW(16,%r15),__LC_RST_OLD_PSW(%r0)# store restart old psw
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0
brasl %r14,do_restart
@@ -972,9 +955,11 @@ cleanup_system_call:
stg %r15,32(%r12)
stg %r11,0(%r12)
CREATE_STACK_FRAME __LC_SAVE_AREA
- mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
- mvc SP_ILC(4,%r15),__LC_SVC_ILC
mvc 8(8,%r12),__LC_THREAD_INFO
+ lg %r12,__LC_THREAD_INFO
+ mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
+ mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+ oi __TI_flags+7(%r12),_TIF_SYSCALL
cleanup_vtime:
clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)
jhe cleanup_stime
@@ -1096,6 +1081,7 @@ sie_exit:
lghi %r2,0
br %r14
sie_fault:
+ lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
lg %r14,__LC_THREAD_INFO # pointer thread_info struct
ni __TI_flags+6(%r14),255-(_TIF_SIE>>8)
lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 2d781bab37bb..900068d2bf92 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -449,10 +449,28 @@ ENTRY(start)
#
.org 0x10000
ENTRY(startup)
+ j .Lep_startup_normal
+ .org 0x10008
+#
+# This is a list of s390 kernel entry points. At address 0x1000f the number of
+# valid entry points is stored.
+#
+# IMPORTANT: Do not change this table, it is s390 kernel ABI!
+#
+ .ascii "S390EP"
+ .byte 0x00,0x01
+#
+# kdump startup-code at 0x10010, running in 64 bit absolute addressing mode
+#
+ .org 0x10010
+ENTRY(startup_kdump)
+ j .Lep_startup_kdump
+.Lep_startup_normal:
basr %r13,0 # get base
.LPG0:
xc 0x200(256),0x200 # partially clear lowcore
xc 0x300(256),0x300
+ xc 0xe00(256),0xe00
stck __LC_LAST_UPDATE_CLOCK
spt 5f-.LPG0(%r13)
mvc __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
@@ -534,6 +552,8 @@ ENTRY(startup)
.align 8
5: .long 0x7fffffff,0xffffffff
+#include "head_kdump.S"
+
#
# params at 10400 (setup.h)
#
@@ -541,6 +561,8 @@ ENTRY(startup)
.long 0,0 # IPL_DEVICE
.long 0,0 # INITRD_START
.long 0,0 # INITRD_SIZE
+ .long 0,0 # OLDMEM_BASE
+ .long 0,0 # OLDMEM_SIZE
.org COMMAND_LINE
.byte "root=/dev/ram0 ro"
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index f21954b44dc1..d3f1ab7d90ad 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -92,7 +92,7 @@ ENTRY(_stext)
.LPG3:
# check control registers
stctl %c0,%c15,0(%r15)
- oi 2(%r15),0x40 # enable sigp emergency signal
+ oi 2(%r15),0x60 # enable sigp emergency & external call
oi 0(%r15),0x10 # switch on low address protection
lctl %c0,%c15,0(%r15)
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index ae5d492b069e..99348c0eaa41 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -90,7 +90,7 @@ ENTRY(_stext)
.LPG3:
# check control registers
stctg %c0,%c15,0(%r15)
- oi 6(%r15),0x40 # enable sigp emergency signal
+ oi 6(%r15),0x60 # enable sigp emergency & external call
oi 4(%r15),0x10 # switch on low address proctection
lctlg %c0,%c15,0(%r15)
diff --git a/arch/s390/kernel/head_kdump.S b/arch/s390/kernel/head_kdump.S
new file mode 100644
index 000000000000..e1ac3893e972
--- /dev/null
+++ b/arch/s390/kernel/head_kdump.S
@@ -0,0 +1,119 @@
+/*
+ * S390 kdump lowlevel functions (new kernel)
+ *
+ * Copyright IBM Corp. 2011
+ * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
+ */
+
+#define DATAMOVER_ADDR 0x4000
+#define COPY_PAGE_ADDR 0x6000
+
+#ifdef CONFIG_CRASH_DUMP
+
+#
+# kdump entry (new kernel - not yet relocated)
+#
+# Note: This code has to be position independent
+#
+
+.align 2
+.Lep_startup_kdump:
+ lhi %r1,2 # mode 2 = esame (dump)
+ sigp %r1,%r0,0x12 # Switch to esame mode
+ sam64 # Switch to 64 bit addressing
+ basr %r13,0
+.Lbase:
+ larl %r2,.Lbase_addr # Check, if we have been
+ lg %r2,0(%r2) # already relocated:
+ clgr %r2,%r13 #
+ jne .Lrelocate # No : Start data mover
+ lghi %r2,0 # Yes: Start kdump kernel
+ brasl %r14,startup_kdump_relocated
+
+.Lrelocate:
+ larl %r4,startup
+ lg %r2,0x418(%r4) # Get kdump base
+ lg %r3,0x420(%r4) # Get kdump size
+
+ larl %r10,.Lcopy_start # Source of data mover
+ lghi %r8,DATAMOVER_ADDR # Target of data mover
+ mvc 0(256,%r8),0(%r10) # Copy data mover code
+
+ agr %r8,%r2 # Copy data mover to
+ mvc 0(256,%r8),0(%r10) # reserved mem
+
+ lghi %r14,DATAMOVER_ADDR # Jump to copied data mover
+ basr %r14,%r14
+.Lbase_addr:
+ .quad .Lbase
+
+#
+# kdump data mover code (runs at address DATAMOVER_ADDR)
+#
+# r2: kdump base address
+# r3: kdump size
+#
+.Lcopy_start:
+ basr %r13,0 # Base
+0:
+ lgr %r11,%r2 # Save kdump base address
+ lgr %r12,%r2
+ agr %r12,%r3 # Compute kdump end address
+
+ lghi %r5,0
+ lghi %r10,COPY_PAGE_ADDR # Load copy page address
+1:
+ mvc 0(256,%r10),0(%r5) # Copy old kernel to tmp
+ mvc 0(256,%r5),0(%r11) # Copy new kernel to old
+ mvc 0(256,%r11),0(%r10) # Copy tmp to new
+ aghi %r11,256
+ aghi %r5,256
+ clgr %r11,%r12
+ jl 1b
+
+ lg %r14,.Lstartup_kdump-0b(%r13)
+ basr %r14,%r14 # Start relocated kernel
+.Lstartup_kdump:
+ .long 0x00000000,0x00000000 + startup_kdump_relocated
+.Lcopy_end:
+
+#
+# Startup of kdump (relocated new kernel)
+#
+.align 2
+startup_kdump_relocated:
+ basr %r13,0
+0:
+ mvc 0(8,%r0),.Lrestart_psw-0b(%r13) # Setup restart PSW
+ mvc 464(16,%r0),.Lpgm_psw-0b(%r13) # Setup pgm check PSW
+ lhi %r1,1 # Start new kernel
+ diag %r1,%r1,0x308 # with diag 308
+
+.Lno_diag308: # No diag 308
+ sam31 # Switch to 31 bit addr mode
+ sr %r1,%r1 # Erase register r1
+ sr %r2,%r2 # Erase register r2
+ sigp %r1,%r2,0x12 # Switch to 31 bit arch mode
+ lpsw 0 # Start new kernel...
+.align 8
+.Lrestart_psw:
+ .long 0x00080000,0x80000000 + startup
+.Lpgm_psw:
+ .quad 0x0000000180000000,0x0000000000000000 + .Lno_diag308
+#else
+.align 2
+.Lep_startup_kdump:
+#ifdef CONFIG_64BIT
+ larl %r13,startup_kdump_crash
+ lpswe 0(%r13)
+.align 8
+startup_kdump_crash:
+ .quad 0x0002000080000000,0x0000000000000000 + startup_kdump_crash
+#else
+ basr %r13,0
+0: lpsw startup_kdump_crash-0b(%r13)
+.align 8
+startup_kdump_crash:
+ .long 0x000a0000,0x00000000 + startup_kdump_crash
+#endif /* CONFIG_64BIT */
+#endif /* CONFIG_CRASH_DUMP */
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 48c710206366..affa8e68124a 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -16,6 +16,7 @@
#include <linux/ctype.h>
#include <linux/fs.h>
#include <linux/gfp.h>
+#include <linux/crash_dump.h>
#include <asm/ipl.h>
#include <asm/smp.h>
#include <asm/setup.h>
@@ -26,6 +27,7 @@
#include <asm/sclp.h>
#include <asm/sigp.h>
#include <asm/checksum.h>
+#include "entry.h"
#define IPL_PARM_BLOCK_VERSION 0
@@ -275,8 +277,8 @@ static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
/* VM IPL PARM routines */
-size_t reipl_get_ascii_vmparm(char *dest, size_t size,
- const struct ipl_parameter_block *ipb)
+static size_t reipl_get_ascii_vmparm(char *dest, size_t size,
+ const struct ipl_parameter_block *ipb)
{
int i;
size_t len;
@@ -338,8 +340,8 @@ static size_t scpdata_length(const char* buf, size_t count)
return count;
}
-size_t reipl_append_ascii_scpdata(char *dest, size_t size,
- const struct ipl_parameter_block *ipb)
+static size_t reipl_append_ascii_scpdata(char *dest, size_t size,
+ const struct ipl_parameter_block *ipb)
{
size_t count;
size_t i;
@@ -1738,7 +1740,11 @@ static struct kobj_attribute on_restart_attr =
void do_restart(void)
{
+ smp_restart_with_online_cpu();
smp_send_stop();
+#ifdef CONFIG_CRASH_DUMP
+ crash_kexec(NULL);
+#endif
on_restart_trigger.action->fn(&on_restart_trigger);
stop_run(&on_restart_trigger);
}
@@ -2009,7 +2015,7 @@ static void do_reset_calls(void)
u32 dump_prefix_page;
-void s390_reset_system(void)
+void s390_reset_system(void (*func)(void *), void *data)
{
struct _lowcore *lc;
@@ -2028,15 +2034,19 @@ void s390_reset_system(void)
__ctl_clear_bit(0,28);
/* Set new machine check handler */
- S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
+ S390_lowcore.mcck_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
S390_lowcore.mcck_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
/* Set new program check handler */
- S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
+ S390_lowcore.program_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
S390_lowcore.program_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
+ /* Store status at absolute zero */
+ store_status();
+
do_reset_calls();
+ if (func)
+ func(data);
}
-
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 1f4050d45f78..b9a7fdd9c814 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -33,7 +33,8 @@ static const struct irq_class intrclass_names[] = {
{.name = "EXT" },
{.name = "I/O" },
{.name = "CLK", .desc = "[EXT] Clock Comparator" },
- {.name = "IPI", .desc = "[EXT] Signal Processor" },
+ {.name = "EXC", .desc = "[EXT] External Call" },
+ {.name = "EMS", .desc = "[EXT] Emergency Signal" },
{.name = "TMR", .desc = "[EXT] CPU Timer" },
{.name = "TAL", .desc = "[EXT] Timing Alert" },
{.name = "PFL", .desc = "[EXT] Pseudo Page Fault" },
@@ -42,8 +43,8 @@ static const struct irq_class intrclass_names[] = {
{.name = "SCP", .desc = "[EXT] Service Call" },
{.name = "IUC", .desc = "[EXT] IUCV" },
{.name = "CPM", .desc = "[EXT] CPU Measurement" },
+ {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt" },
{.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" },
- {.name = "QDI", .desc = "[I/O] QDIO Interrupt" },
{.name = "DAS", .desc = "[I/O] DASD" },
{.name = "C15", .desc = "[I/O] 3215" },
{.name = "C70", .desc = "[I/O] 3270" },
@@ -53,6 +54,7 @@ static const struct irq_class intrclass_names[] = {
{.name = "CLW", .desc = "[I/O] CLAW" },
{.name = "CTC", .desc = "[I/O] CTC" },
{.name = "APB", .desc = "[I/O] AP Bus" },
+ {.name = "CSC", .desc = "[I/O] CHSC Subchannel" },
{.name = "NMI", .desc = "[NMI] Machine Check" },
};
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 1d05d669107c..64b761aef004 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -635,7 +635,7 @@ void __kprobes jprobe_return(void)
asm volatile(".word 0x0002");
}
-void __kprobes jprobe_return_end(void)
+static void __used __kprobes jprobe_return_end(void)
{
asm volatile("bcr 0,0");
}
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index b09b9c62573e..3cd0f25ab015 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -1,10 +1,11 @@
/*
* arch/s390/kernel/machine_kexec.c
*
- * Copyright IBM Corp. 2005,2006
+ * Copyright IBM Corp. 2005,2011
*
* Author(s): Rolf Adelsberger,
* Heiko Carstens <heiko.carstens@de.ibm.com>
+ * Michael Holzheu <holzheu@linux.vnet.ibm.com>
*/
#include <linux/device.h>
@@ -21,12 +22,162 @@
#include <asm/smp.h>
#include <asm/reset.h>
#include <asm/ipl.h>
+#include <asm/diag.h>
+#include <asm/asm-offsets.h>
typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long);
extern const unsigned char relocate_kernel[];
extern const unsigned long long relocate_kernel_len;
+#ifdef CONFIG_CRASH_DUMP
+
+void *fill_cpu_elf_notes(void *ptr, struct save_area *sa);
+
+/*
+ * Create ELF notes for one CPU
+ */
+static void add_elf_notes(int cpu)
+{
+ struct save_area *sa = (void *) 4608 + store_prefix();
+ void *ptr;
+
+ memcpy((void *) (4608UL + sa->pref_reg), sa, sizeof(*sa));
+ ptr = (u64 *) per_cpu_ptr(crash_notes, cpu);
+ ptr = fill_cpu_elf_notes(ptr, sa);
+ memset(ptr, 0, sizeof(struct elf_note));
+}
+
+/*
+ * Store status of next available physical CPU
+ */
+static int store_status_next(int start_cpu, int this_cpu)
+{
+ struct save_area *sa = (void *) 4608 + store_prefix();
+ int cpu, rc;
+
+ for (cpu = start_cpu; cpu < 65536; cpu++) {
+ if (cpu == this_cpu)
+ continue;
+ do {
+ rc = raw_sigp(cpu, sigp_stop_and_store_status);
+ } while (rc == sigp_busy);
+ if (rc != sigp_order_code_accepted)
+ continue;
+ if (sa->pref_reg)
+ return cpu;
+ }
+ return -1;
+}
+
+/*
+ * Initialize CPU ELF notes
+ */
+void setup_regs(void)
+{
+ unsigned long sa = S390_lowcore.prefixreg_save_area + SAVE_AREA_BASE;
+ int cpu, this_cpu, phys_cpu = 0, first = 1;
+
+ this_cpu = stap();
+
+ if (!S390_lowcore.prefixreg_save_area)
+ first = 0;
+ for_each_online_cpu(cpu) {
+ if (first) {
+ add_elf_notes(cpu);
+ first = 0;
+ continue;
+ }
+ phys_cpu = store_status_next(phys_cpu, this_cpu);
+ if (phys_cpu == -1)
+ break;
+ add_elf_notes(cpu);
+ phys_cpu++;
+ }
+ /* Copy dump CPU store status info to absolute zero */
+ memcpy((void *) SAVE_AREA_BASE, (void *) sa, sizeof(struct save_area));
+}
+
+#endif
+
+/*
+ * Start kdump: We expect here that a store status has been done on our CPU
+ */
+static void __do_machine_kdump(void *image)
+{
+#ifdef CONFIG_CRASH_DUMP
+ int (*start_kdump)(int) = (void *)((struct kimage *) image)->start;
+
+ __load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA);
+ setup_regs();
+ start_kdump(1);
+#endif
+}
+
+/*
+ * Check if kdump checksums are valid: We call purgatory with parameter "0"
+ */
+static int kdump_csum_valid(struct kimage *image)
+{
+#ifdef CONFIG_CRASH_DUMP
+ int (*start_kdump)(int) = (void *)image->start;
+ int rc;
+
+ __arch_local_irq_stnsm(0xfb); /* disable DAT */
+ rc = start_kdump(0);
+ __arch_local_irq_stosm(0x04); /* enable DAT */
+ return rc ? 0 : -EINVAL;
+#else
+ return -EINVAL;
+#endif
+}
+
+/*
+ * Map or unmap crashkernel memory
+ */
+static void crash_map_pages(int enable)
+{
+ unsigned long size = resource_size(&crashk_res);
+
+ BUG_ON(crashk_res.start % KEXEC_CRASH_MEM_ALIGN ||
+ size % KEXEC_CRASH_MEM_ALIGN);
+ if (enable)
+ vmem_add_mapping(crashk_res.start, size);
+ else
+ vmem_remove_mapping(crashk_res.start, size);
+}
+
+/*
+ * Map crashkernel memory
+ */
+void crash_map_reserved_pages(void)
+{
+ crash_map_pages(1);
+}
+
+/*
+ * Unmap crashkernel memory
+ */
+void crash_unmap_reserved_pages(void)
+{
+ crash_map_pages(0);
+}
+
+/*
+ * Give back memory to hypervisor before new kdump is loaded
+ */
+static int machine_kexec_prepare_kdump(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+ if (MACHINE_IS_VM)
+ diag10_range(PFN_DOWN(crashk_res.start),
+ PFN_DOWN(crashk_res.end - crashk_res.start + 1));
+ return 0;
+#else
+ return -EINVAL;
+#endif
+}
+
int machine_kexec_prepare(struct kimage *image)
{
void *reboot_code_buffer;
@@ -35,6 +186,9 @@ int machine_kexec_prepare(struct kimage *image)
if (ipl_flags & IPL_NSS_VALID)
return -ENOSYS;
+ if (image->type == KEXEC_TYPE_CRASH)
+ return machine_kexec_prepare_kdump();
+
/* We don't support anything but the default image type for now. */
if (image->type != KEXEC_TYPE_DEFAULT)
return -EINVAL;
@@ -51,27 +205,53 @@ void machine_kexec_cleanup(struct kimage *image)
{
}
+void arch_crash_save_vmcoreinfo(void)
+{
+ VMCOREINFO_SYMBOL(lowcore_ptr);
+ VMCOREINFO_LENGTH(lowcore_ptr, NR_CPUS);
+}
+
void machine_shutdown(void)
{
}
-static void __machine_kexec(void *data)
+/*
+ * Do normal kexec
+ */
+static void __do_machine_kexec(void *data)
{
relocate_kernel_t data_mover;
struct kimage *image = data;
- pfault_fini();
- s390_reset_system();
-
data_mover = (relocate_kernel_t) page_to_phys(image->control_code_page);
/* Call the moving routine */
(*data_mover)(&image->head, image->start);
- for (;;);
}
+/*
+ * Reset system and call either kdump or normal kexec
+ */
+static void __machine_kexec(void *data)
+{
+ struct kimage *image = data;
+
+ pfault_fini();
+ if (image->type == KEXEC_TYPE_CRASH)
+ s390_reset_system(__do_machine_kdump, data);
+ else
+ s390_reset_system(__do_machine_kexec, data);
+ disabled_wait((unsigned long) __builtin_return_address(0));
+}
+
+/*
+ * Do either kdump or normal kexec. In case of kdump we first ask
+ * purgatory, if kdump checksums are valid.
+ */
void machine_kexec(struct kimage *image)
{
+ if (image->type == KEXEC_TYPE_CRASH && !kdump_csum_valid(image))
+ return;
tracer_disable();
smp_send_stop();
smp_switch_to_ipl_cpu(__machine_kexec, image);
diff --git a/arch/s390/kernel/mem_detect.c b/arch/s390/kernel/mem_detect.c
index 0fbe4e32f7ba..19b4568f4cee 100644
--- a/arch/s390/kernel/mem_detect.c
+++ b/arch/s390/kernel/mem_detect.c
@@ -62,3 +62,72 @@ void detect_memory_layout(struct mem_chunk chunk[])
arch_local_irq_restore(flags);
}
EXPORT_SYMBOL(detect_memory_layout);
+
+/*
+ * Create memory hole with given address, size, and type
+ */
+void create_mem_hole(struct mem_chunk chunks[], unsigned long addr,
+ unsigned long size, int type)
+{
+ unsigned long start, end, new_size;
+ int i;
+
+ for (i = 0; i < MEMORY_CHUNKS; i++) {
+ if (chunks[i].size == 0)
+ continue;
+ if (addr + size < chunks[i].addr)
+ continue;
+ if (addr >= chunks[i].addr + chunks[i].size)
+ continue;
+ start = max(addr, chunks[i].addr);
+ end = min(addr + size, chunks[i].addr + chunks[i].size);
+ new_size = end - start;
+ if (new_size == 0)
+ continue;
+ if (start == chunks[i].addr &&
+ end == chunks[i].addr + chunks[i].size) {
+ /* Remove chunk */
+ chunks[i].type = type;
+ } else if (start == chunks[i].addr) {
+ /* Make chunk smaller at start */
+ if (i >= MEMORY_CHUNKS - 1)
+ panic("Unable to create memory hole");
+ memmove(&chunks[i + 1], &chunks[i],
+ sizeof(struct mem_chunk) *
+ (MEMORY_CHUNKS - (i + 1)));
+ chunks[i + 1].addr = chunks[i].addr + new_size;
+ chunks[i + 1].size = chunks[i].size - new_size;
+ chunks[i].size = new_size;
+ chunks[i].type = type;
+ i += 1;
+ } else if (end == chunks[i].addr + chunks[i].size) {
+ /* Make chunk smaller at end */
+ if (i >= MEMORY_CHUNKS - 1)
+ panic("Unable to create memory hole");
+ memmove(&chunks[i + 1], &chunks[i],
+ sizeof(struct mem_chunk) *
+ (MEMORY_CHUNKS - (i + 1)));
+ chunks[i + 1].addr = start;
+ chunks[i + 1].size = new_size;
+ chunks[i + 1].type = type;
+ chunks[i].size -= new_size;
+ i += 1;
+ } else {
+ /* Create memory hole */
+ if (i >= MEMORY_CHUNKS - 2)
+ panic("Unable to create memory hole");
+ memmove(&chunks[i + 2], &chunks[i],
+ sizeof(struct mem_chunk) *
+ (MEMORY_CHUNKS - (i + 2)));
+ chunks[i + 1].addr = addr;
+ chunks[i + 1].size = size;
+ chunks[i + 1].type = type;
+ chunks[i + 2].addr = addr + size;
+ chunks[i + 2].size =
+ chunks[i].addr + chunks[i].size - (addr + size);
+ chunks[i + 2].type = chunks[i].type;
+ chunks[i].size = addr - chunks[i].addr;
+ i += 2;
+ }
+ }
+}
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 541a7509faeb..9451b210a1b4 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/elfcore.h>
#include <linux/smp.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
@@ -117,7 +118,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
struct pt_regs regs;
memset(&regs, 0, sizeof(regs));
- regs.psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
+ regs.psw.mask = psw_kernel_bits |
+ PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
regs.gprs[9] = (unsigned long) fn;
regs.gprs[10] = (unsigned long) arg;
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index 311e9d712888..6e0073e43f54 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -74,7 +74,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
static void *c_start(struct seq_file *m, loff_t *pos)
{
- return *pos < NR_CPUS ? (void *)((unsigned long) *pos + 1) : NULL;
+ return *pos < nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL;
}
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index ef86ad243986..450931a45b68 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -42,34 +42,37 @@ enum s390_regset {
REGSET_GENERAL,
REGSET_FP,
REGSET_LAST_BREAK,
+ REGSET_SYSTEM_CALL,
REGSET_GENERAL_EXTENDED,
};
void update_per_regs(struct task_struct *task)
{
- static const struct per_regs per_single_step = {
- .control = PER_EVENT_IFETCH,
- .start = 0,
- .end = PSW_ADDR_INSN,
- };
struct pt_regs *regs = task_pt_regs(task);
struct thread_struct *thread = &task->thread;
- const struct per_regs *new;
- struct per_regs old;
-
- /* TIF_SINGLE_STEP overrides the user specified PER registers. */
- new = test_tsk_thread_flag(task, TIF_SINGLE_STEP) ?
- &per_single_step : &thread->per_user;
+ struct per_regs old, new;
+
+ /* Copy user specified PER registers */
+ new.control = thread->per_user.control;
+ new.start = thread->per_user.start;
+ new.end = thread->per_user.end;
+
+ /* merge TIF_SINGLE_STEP into user specified PER registers. */
+ if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
+ new.control |= PER_EVENT_IFETCH;
+ new.start = 0;
+ new.end = PSW_ADDR_INSN;
+ }
/* Take care of the PER enablement bit in the PSW. */
- if (!(new->control & PER_EVENT_MASK)) {
+ if (!(new.control & PER_EVENT_MASK)) {
regs->psw.mask &= ~PSW_MASK_PER;
return;
}
regs->psw.mask |= PSW_MASK_PER;
__ctl_store(old, 9, 11);
- if (memcmp(new, &old, sizeof(struct per_regs)) != 0)
- __ctl_load(*new, 9, 11);
+ if (memcmp(&new, &old, sizeof(struct per_regs)) != 0)
+ __ctl_load(new, 9, 11);
}
void user_enable_single_step(struct task_struct *task)
@@ -166,8 +169,8 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
*/
tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr);
if (addr == (addr_t) &dummy->regs.psw.mask)
- /* Remove per bit from user psw. */
- tmp &= ~PSW_MASK_PER;
+ /* Return a clean psw mask. */
+ tmp = psw_user_bits | (tmp & PSW_MASK_USER);
} else if (addr < (addr_t) &dummy->regs.orig_gpr2) {
/*
@@ -289,18 +292,17 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
* psw and gprs are stored on the stack
*/
if (addr == (addr_t) &dummy->regs.psw.mask &&
-#ifdef CONFIG_COMPAT
- data != PSW_MASK_MERGE(psw_user32_bits, data) &&
-#endif
- data != PSW_MASK_MERGE(psw_user_bits, data))
+ ((data & ~PSW_MASK_USER) != psw_user_bits ||
+ ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA))))
/* Invalid psw mask. */
return -EINVAL;
-#ifndef CONFIG_64BIT
if (addr == (addr_t) &dummy->regs.psw.addr)
- /* I'd like to reject addresses without the
- high order bit but older gdb's rely on it */
- data |= PSW_ADDR_AMODE;
-#endif
+ /*
+ * The debugger changed the instruction address,
+ * reset system call restart, see signal.c:do_signal
+ */
+ task_thread_info(child)->system_call = 0;
+
*(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;
} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
@@ -495,21 +497,21 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
__u32 tmp;
if (addr < (addr_t) &dummy32->regs.acrs) {
+ struct pt_regs *regs = task_pt_regs(child);
/*
* psw and gprs are stored on the stack
*/
if (addr == (addr_t) &dummy32->regs.psw.mask) {
/* Fake a 31 bit psw mask. */
- tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32);
- tmp = PSW32_MASK_MERGE(psw32_user_bits, tmp);
+ tmp = (__u32)(regs->psw.mask >> 32);
+ tmp = psw32_user_bits | (tmp & PSW32_MASK_USER);
} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
/* Fake a 31 bit psw address. */
- tmp = (__u32) task_pt_regs(child)->psw.addr |
- PSW32_ADDR_AMODE31;
+ tmp = (__u32) regs->psw.addr |
+ (__u32)(regs->psw.mask & PSW_MASK_BA);
} else {
/* gpr 0-15 */
- tmp = *(__u32 *)((addr_t) &task_pt_regs(child)->psw +
- addr*2 + 4);
+ tmp = *(__u32 *)((addr_t) &regs->psw + addr*2 + 4);
}
} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
/*
@@ -594,24 +596,32 @@ static int __poke_user_compat(struct task_struct *child,
addr_t offset;
if (addr < (addr_t) &dummy32->regs.acrs) {
+ struct pt_regs *regs = task_pt_regs(child);
/*
* psw, gprs, acrs and orig_gpr2 are stored on the stack
*/
if (addr == (addr_t) &dummy32->regs.psw.mask) {
/* Build a 64 bit psw mask from 31 bit mask. */
- if (tmp != PSW32_MASK_MERGE(psw32_user_bits, tmp))
+ if ((tmp & ~PSW32_MASK_USER) != psw32_user_bits)
/* Invalid psw mask. */
return -EINVAL;
- task_pt_regs(child)->psw.mask =
- PSW_MASK_MERGE(psw_user32_bits, (__u64) tmp << 32);
+ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+ (regs->psw.mask & PSW_MASK_BA) |
+ (__u64)(tmp & PSW32_MASK_USER) << 32;
} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
/* Build a 64 bit psw address from 31 bit address. */
- task_pt_regs(child)->psw.addr =
- (__u64) tmp & PSW32_ADDR_INSN;
+ regs->psw.addr = (__u64) tmp & PSW32_ADDR_INSN;
+ /* Transfer 31 bit amode bit to psw mask. */
+ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) |
+ (__u64)(tmp & PSW32_ADDR_AMODE);
+ /*
+ * The debugger changed the instruction address,
+ * reset system call restart, see signal.c:do_signal
+ */
+ task_thread_info(child)->system_call = 0;
} else {
/* gpr 0-15 */
- *(__u32*)((addr_t) &task_pt_regs(child)->psw
- + addr*2 + 4) = tmp;
+ *(__u32*)((addr_t) &regs->psw + addr*2 + 4) = tmp;
}
} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
/*
@@ -735,7 +745,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
* debugger stored an invalid system call number. Skip
* the system call and the system call restart handling.
*/
- regs->svcnr = 0;
+ clear_thread_flag(TIF_SYSCALL);
ret = -1;
}
@@ -897,6 +907,26 @@ static int s390_last_break_get(struct task_struct *target,
#endif
+static int s390_system_call_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ unsigned int *data = &task_thread_info(target)->system_call;
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ data, 0, sizeof(unsigned int));
+}
+
+static int s390_system_call_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ unsigned int *data = &task_thread_info(target)->system_call;
+ return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ data, 0, sizeof(unsigned int));
+}
+
static const struct user_regset s390_regsets[] = {
[REGSET_GENERAL] = {
.core_note_type = NT_PRSTATUS,
@@ -923,6 +953,14 @@ static const struct user_regset s390_regsets[] = {
.get = s390_last_break_get,
},
#endif
+ [REGSET_SYSTEM_CALL] = {
+ .core_note_type = NT_S390_SYSTEM_CALL,
+ .n = 1,
+ .size = sizeof(unsigned int),
+ .align = sizeof(unsigned int),
+ .get = s390_system_call_get,
+ .set = s390_system_call_set,
+ },
};
static const struct user_regset_view user_s390_view = {
@@ -1102,6 +1140,14 @@ static const struct user_regset s390_compat_regsets[] = {
.align = sizeof(long),
.get = s390_compat_last_break_get,
},
+ [REGSET_SYSTEM_CALL] = {
+ .core_note_type = NT_S390_SYSTEM_CALL,
+ .n = 1,
+ .size = sizeof(compat_uint_t),
+ .align = sizeof(compat_uint_t),
+ .get = s390_system_call_get,
+ .set = s390_system_call_set,
+ },
[REGSET_GENERAL_EXTENDED] = {
.core_note_type = NT_S390_HIGH_GPRS,
.n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
index 303d961c3bb5..ad67c214be04 100644
--- a/arch/s390/kernel/reipl.S
+++ b/arch/s390/kernel/reipl.S
@@ -10,6 +10,12 @@
#include <asm/asm-offsets.h>
#
+# store_status: Empty implementation until kdump is supported on 31 bit
+#
+ENTRY(store_status)
+ br %r14
+
+#
# do_reipl_asm
# Parameter: r2 = schid of reipl device
#
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S
index e690975403f4..732a793ec53a 100644
--- a/arch/s390/kernel/reipl64.S
+++ b/arch/s390/kernel/reipl64.S
@@ -17,11 +17,11 @@
#
ENTRY(store_status)
/* Save register one and load save area base */
- stg %r1,__LC_SAVE_AREA_64(%r0)
+ stg %r1,__LC_SAVE_AREA+120(%r0)
lghi %r1,SAVE_AREA_BASE
/* General purpose registers */
stmg %r0,%r15,__LC_GPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
- lg %r2,__LC_SAVE_AREA_64(%r0)
+ lg %r2,__LC_SAVE_AREA+120(%r0)
stg %r2,__LC_GPREGS_SAVE_AREA-SAVE_AREA_BASE+8(%r1)
/* Control registers */
stctg %c0,%c15,__LC_CREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
@@ -62,8 +62,11 @@ ENTRY(store_status)
larl %r2,store_status
stg %r2,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 8(%r1)
br %r14
-.align 8
+
+ .section .bss
+ .align 8
.Lclkcmp: .quad 0x0000000000000000
+ .previous
#
# do_reipl_asm
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 7b371c37061d..8ac6bfa2786c 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -42,6 +42,9 @@
#include <linux/reboot.h>
#include <linux/topology.h>
#include <linux/ftrace.h>
+#include <linux/kexec.h>
+#include <linux/crash_dump.h>
+#include <linux/memory.h>
#include <asm/ipl.h>
#include <asm/uaccess.h>
@@ -57,12 +60,13 @@
#include <asm/ebcdic.h>
#include <asm/compat.h>
#include <asm/kvm_virtio.h>
+#include <asm/diag.h>
-long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY |
- PSW_MASK_MCHECK | PSW_DEFAULT_KEY);
-long psw_user_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
- PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
- PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
+long psw_kernel_bits = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY |
+ PSW_MASK_EA | PSW_MASK_BA;
+long psw_user_bits = PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT |
+ PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK |
+ PSW_MASK_PSTATE | PSW_ASC_HOME;
/*
* User copy operations.
@@ -274,22 +278,14 @@ early_param("mem", early_parse_mem);
unsigned int user_mode = HOME_SPACE_MODE;
EXPORT_SYMBOL_GPL(user_mode);
-static int set_amode_and_uaccess(unsigned long user_amode,
- unsigned long user32_amode)
+static int set_amode_primary(void)
{
- psw_user_bits = PSW_BASE_BITS | PSW_MASK_DAT | user_amode |
- PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
- PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
+ psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME;
+ psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY;
#ifdef CONFIG_COMPAT
- psw_user32_bits = PSW_BASE32_BITS | PSW_MASK_DAT | user_amode |
- PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
- PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
- psw32_user_bits = PSW32_BASE_BITS | PSW32_MASK_DAT | user32_amode |
- PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
- PSW32_MASK_PSTATE;
+ psw32_user_bits =
+ (psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY;
#endif
- psw_kernel_bits = PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
- PSW_MASK_MCHECK | PSW_DEFAULT_KEY;
if (MACHINE_HAS_MVCOS) {
memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess));
@@ -325,7 +321,7 @@ early_param("user_mode", early_parse_user_mode);
static void setup_addressing_mode(void)
{
if (user_mode == PRIMARY_SPACE_MODE) {
- if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY))
+ if (set_amode_primary())
pr_info("Address spaces switched, "
"mvcos available\n");
else
@@ -344,24 +340,25 @@ setup_lowcore(void)
*/
BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);
lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
- lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+ lc->restart_psw.mask = psw_kernel_bits;
lc->restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
- if (user_mode != HOME_SPACE_MODE)
- lc->restart_psw.mask |= PSW_ASC_HOME;
- lc->external_new_psw.mask = psw_kernel_bits;
+ lc->external_new_psw.mask = psw_kernel_bits |
+ PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->external_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
- lc->svc_new_psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
+ lc->svc_new_psw.mask = psw_kernel_bits |
+ PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
- lc->program_new_psw.mask = psw_kernel_bits;
+ lc->program_new_psw.mask = psw_kernel_bits |
+ PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->program_new_psw.addr =
- PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
- lc->mcck_new_psw.mask =
- psw_kernel_bits & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
+ PSW_ADDR_AMODE | (unsigned long) pgm_check_handler;
+ lc->mcck_new_psw.mask = psw_kernel_bits;
lc->mcck_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
- lc->io_new_psw.mask = psw_kernel_bits;
+ lc->io_new_psw.mask = psw_kernel_bits |
+ PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
lc->clock_comparator = -1ULL;
lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
@@ -435,10 +432,14 @@ static void __init setup_resources(void)
for (i = 0; i < MEMORY_CHUNKS; i++) {
if (!memory_chunk[i].size)
continue;
+ if (memory_chunk[i].type == CHUNK_OLDMEM ||
+ memory_chunk[i].type == CHUNK_CRASHK)
+ continue;
res = alloc_bootmem_low(sizeof(*res));
res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
switch (memory_chunk[i].type) {
case CHUNK_READ_WRITE:
+ case CHUNK_CRASHK:
res->name = "System RAM";
break;
case CHUNK_READ_ONLY:
@@ -479,6 +480,7 @@ static void __init setup_memory_end(void)
unsigned long max_mem;
int i;
+
#ifdef CONFIG_ZFCPDUMP
if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
memory_end = ZFCPDUMP_HSA_SIZE;
@@ -545,11 +547,201 @@ static void __init setup_restart_psw(void)
* Setup restart PSW for absolute zero lowcore. This is necesary
* if PSW restart is done on an offline CPU that has lowcore zero
*/
- psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+ psw.mask = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
copy_to_absolute_zero(&S390_lowcore.restart_psw, &psw, sizeof(psw));
}
+static void __init setup_vmcoreinfo(void)
+{
+#ifdef CONFIG_KEXEC
+ unsigned long ptr = paddr_vmcoreinfo_note();
+
+ copy_to_absolute_zero(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr));
+#endif
+}
+
+#ifdef CONFIG_CRASH_DUMP
+
+/*
+ * Find suitable location for crashkernel memory
+ */
+static unsigned long __init find_crash_base(unsigned long crash_size,
+ char **msg)
+{
+ unsigned long crash_base;
+ struct mem_chunk *chunk;
+ int i;
+
+ if (memory_chunk[0].size < crash_size) {
+ *msg = "first memory chunk must be at least crashkernel size";
+ return 0;
+ }
+ if (is_kdump_kernel() && (crash_size == OLDMEM_SIZE))
+ return OLDMEM_BASE;
+
+ for (i = MEMORY_CHUNKS - 1; i >= 0; i--) {
+ chunk = &memory_chunk[i];
+ if (chunk->size == 0)
+ continue;
+ if (chunk->type != CHUNK_READ_WRITE)
+ continue;
+ if (chunk->size < crash_size)
+ continue;
+ crash_base = (chunk->addr + chunk->size) - crash_size;
+ if (crash_base < crash_size)
+ continue;
+ if (crash_base < ZFCPDUMP_HSA_SIZE_MAX)
+ continue;
+ if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE)
+ continue;
+ return crash_base;
+ }
+ *msg = "no suitable area found";
+ return 0;
+}
+
+/*
+ * Check if crash_base and crash_size is valid
+ */
+static int __init verify_crash_base(unsigned long crash_base,
+ unsigned long crash_size,
+ char **msg)
+{
+ struct mem_chunk *chunk;
+ int i;
+
+ /*
+ * Because we do the swap to zero, we must have at least 'crash_size'
+ * bytes free space before crash_base
+ */
+ if (crash_size > crash_base) {
+ *msg = "crashkernel offset must be greater than size";
+ return -EINVAL;
+ }
+
+ /* First memory chunk must be at least crash_size */
+ if (memory_chunk[0].size < crash_size) {
+ *msg = "first memory chunk must be at least crashkernel size";
+ return -EINVAL;
+ }
+ /* Check if we fit into the respective memory chunk */
+ for (i = 0; i < MEMORY_CHUNKS; i++) {
+ chunk = &memory_chunk[i];
+ if (chunk->size == 0)
+ continue;
+ if (crash_base < chunk->addr)
+ continue;
+ if (crash_base >= chunk->addr + chunk->size)
+ continue;
+ /* we have found the memory chunk */
+ if (crash_base + crash_size > chunk->addr + chunk->size) {
+ *msg = "selected memory chunk is too small for "
+ "crashkernel memory";
+ return -EINVAL;
+ }
+ return 0;
+ }
+ *msg = "invalid memory range specified";
+ return -EINVAL;
+}
+
+/*
+ * Reserve kdump memory by creating a memory hole in the mem_chunk array
+ */
+static void __init reserve_kdump_bootmem(unsigned long addr, unsigned long size,
+ int type)
+{
+
+ create_mem_hole(memory_chunk, addr, size, type);
+}
+
+/*
+ * When kdump is enabled, we have to ensure that no memory from
+ * the area [0 - crashkernel memory size] and
+ * [crashk_res.start - crashk_res.end] is set offline.
+ */
+static int kdump_mem_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct memory_notify *arg = data;
+
+ if (arg->start_pfn < PFN_DOWN(resource_size(&crashk_res)))
+ return NOTIFY_BAD;
+ if (arg->start_pfn > PFN_DOWN(crashk_res.end))
+ return NOTIFY_OK;
+ if (arg->start_pfn + arg->nr_pages - 1 < PFN_DOWN(crashk_res.start))
+ return NOTIFY_OK;
+ return NOTIFY_BAD;
+}
+
+static struct notifier_block kdump_mem_nb = {
+ .notifier_call = kdump_mem_notifier,
+};
+
+#endif
+
+/*
+ * Make sure that oldmem, where the dump is stored, is protected
+ */
+static void reserve_oldmem(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+ if (!OLDMEM_BASE)
+ return;
+
+ reserve_kdump_bootmem(OLDMEM_BASE, OLDMEM_SIZE, CHUNK_OLDMEM);
+ reserve_kdump_bootmem(OLDMEM_SIZE, memory_end - OLDMEM_SIZE,
+ CHUNK_OLDMEM);
+ if (OLDMEM_BASE + OLDMEM_SIZE == real_memory_size)
+ saved_max_pfn = PFN_DOWN(OLDMEM_BASE) - 1;
+ else
+ saved_max_pfn = PFN_DOWN(real_memory_size) - 1;
+#endif
+}
+
+/*
+ * Reserve memory for kdump kernel to be loaded with kexec
+ */
+static void __init reserve_crashkernel(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+ unsigned long long crash_base, crash_size;
+ char *msg;
+ int rc;
+
+ rc = parse_crashkernel(boot_command_line, memory_end, &crash_size,
+ &crash_base);
+ if (rc || crash_size == 0)
+ return;
+ crash_base = ALIGN(crash_base, KEXEC_CRASH_MEM_ALIGN);
+ crash_size = ALIGN(crash_size, KEXEC_CRASH_MEM_ALIGN);
+ if (register_memory_notifier(&kdump_mem_nb))
+ return;
+ if (!crash_base)
+ crash_base = find_crash_base(crash_size, &msg);
+ if (!crash_base) {
+ pr_info("crashkernel reservation failed: %s\n", msg);
+ unregister_memory_notifier(&kdump_mem_nb);
+ return;
+ }
+ if (verify_crash_base(crash_base, crash_size, &msg)) {
+ pr_info("crashkernel reservation failed: %s\n", msg);
+ unregister_memory_notifier(&kdump_mem_nb);
+ return;
+ }
+ if (!OLDMEM_BASE && MACHINE_IS_VM)
+ diag10_range(PFN_DOWN(crash_base), PFN_DOWN(crash_size));
+ crashk_res.start = crash_base;
+ crashk_res.end = crash_base + crash_size - 1;
+ insert_resource(&iomem_resource, &crashk_res);
+ reserve_kdump_bootmem(crash_base, crash_size, CHUNK_CRASHK);
+ pr_info("Reserving %lluMB of memory at %lluMB "
+ "for crashkernel (System RAM: %luMB)\n",
+ crash_size >> 20, crash_base >> 20, memory_end >> 20);
+#endif
+}
+
static void __init
setup_memory(void)
{
@@ -580,6 +772,14 @@ setup_memory(void)
if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) {
start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE;
+#ifdef CONFIG_CRASH_DUMP
+ if (OLDMEM_BASE) {
+ /* Move initrd behind kdump oldmem */
+ if (start + INITRD_SIZE > OLDMEM_BASE &&
+ start < OLDMEM_BASE + OLDMEM_SIZE)
+ start = OLDMEM_BASE + OLDMEM_SIZE;
+ }
+#endif
if (start + INITRD_SIZE > memory_end) {
pr_err("initrd extends beyond end of "
"memory (0x%08lx > 0x%08lx) "
@@ -610,7 +810,8 @@ setup_memory(void)
for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
unsigned long start_chunk, end_chunk, pfn;
- if (memory_chunk[i].type != CHUNK_READ_WRITE)
+ if (memory_chunk[i].type != CHUNK_READ_WRITE &&
+ memory_chunk[i].type != CHUNK_CRASHK)
continue;
start_chunk = PFN_DOWN(memory_chunk[i].addr);
end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size);
@@ -644,6 +845,15 @@ setup_memory(void)
reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size,
BOOTMEM_DEFAULT);
+#ifdef CONFIG_CRASH_DUMP
+ if (crashk_res.start)
+ reserve_bootmem(crashk_res.start,
+ crashk_res.end - crashk_res.start + 1,
+ BOOTMEM_DEFAULT);
+ if (is_kdump_kernel())
+ reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
+ PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
+#endif
#ifdef CONFIG_BLK_DEV_INITRD
if (INITRD_START && INITRD_SIZE) {
if (INITRD_START + INITRD_SIZE <= memory_end) {
@@ -812,8 +1022,11 @@ setup_arch(char **cmdline_p)
setup_ipl();
setup_memory_end();
setup_addressing_mode();
+ reserve_oldmem();
+ reserve_crashkernel();
setup_memory();
setup_resources();
+ setup_vmcoreinfo();
setup_restart_psw();
setup_lowcore();
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 9a40e1cc5ec3..05a85bc14c98 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -30,6 +30,7 @@
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/lowcore.h>
+#include <asm/compat.h>
#include "entry.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -116,7 +117,8 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
/* Copy a 'clean' PSW mask to the user to avoid leaking
information about whether PER is currently on. */
- user_sregs.regs.psw.mask = PSW_MASK_MERGE(psw_user_bits, regs->psw.mask);
+ user_sregs.regs.psw.mask = psw_user_bits |
+ (regs->psw.mask & PSW_MASK_USER);
user_sregs.regs.psw.addr = regs->psw.addr;
memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
memcpy(&user_sregs.regs.acrs, current->thread.acrs,
@@ -143,9 +145,13 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs));
if (err)
return err;
- regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
- user_sregs.regs.psw.mask);
- regs->psw.addr = PSW_ADDR_AMODE | user_sregs.regs.psw.addr;
+ /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
+ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+ (user_sregs.regs.psw.mask & PSW_MASK_USER);
+ /* Check for invalid amode */
+ if (regs->psw.mask & PSW_MASK_EA)
+ regs->psw.mask |= PSW_MASK_BA;
+ regs->psw.addr = user_sregs.regs.psw.addr;
memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs));
memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
sizeof(sregs->regs.acrs));
@@ -156,7 +162,7 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
current->thread.fp_regs.fpc &= FPC_VALID_MASK;
restore_fp_regs(&current->thread.fp_regs);
- regs->svcnr = 0; /* disable syscall checks */
+ clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */
return 0;
}
@@ -288,6 +294,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
/* Set up registers for signal handler */
regs->gprs[15] = (unsigned long) frame;
+ regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */
regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
regs->gprs[2] = map_signal(sig);
@@ -356,6 +363,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler */
regs->gprs[15] = (unsigned long) frame;
+ regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */
regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
regs->gprs[2] = map_signal(sig);
@@ -401,7 +409,6 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
*/
void do_signal(struct pt_regs *regs)
{
- unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
siginfo_t info;
int signr;
struct k_sigaction ka;
@@ -421,54 +428,45 @@ void do_signal(struct pt_regs *regs)
else
oldset = &current->blocked;
- /* Are we from a system call? */
- if (regs->svcnr) {
- continue_addr = regs->psw.addr;
- restart_addr = continue_addr - regs->ilc;
- retval = regs->gprs[2];
-
- /* Prepare for system call restart. We do this here so that a
- debugger will see the already changed PSW. */
- switch (retval) {
- case -ERESTARTNOHAND:
- case -ERESTARTSYS:
- case -ERESTARTNOINTR:
- regs->gprs[2] = regs->orig_gpr2;
- regs->psw.addr = restart_addr;
- break;
- case -ERESTART_RESTARTBLOCK:
- regs->gprs[2] = -EINTR;
- }
- regs->svcnr = 0; /* Don't deal with this again. */
- }
-
- /* Get signal to deliver. When running under ptrace, at this point
- the debugger may change all our registers ... */
+ /*
+ * Get signal to deliver. When running under ptrace, at this point
+ * the debugger may change all our registers, including the system
+ * call information.
+ */
+ current_thread_info()->system_call =
+ test_thread_flag(TIF_SYSCALL) ? regs->svc_code : 0;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- /* Depending on the signal settings we may need to revert the
- decision to restart the system call. */
- if (signr > 0 && regs->psw.addr == restart_addr) {
- if (retval == -ERESTARTNOHAND
- || (retval == -ERESTARTSYS
- && !(current->sighand->action[signr-1].sa.sa_flags
- & SA_RESTART))) {
- regs->gprs[2] = -EINTR;
- regs->psw.addr = continue_addr;
- }
- }
-
if (signr > 0) {
/* Whee! Actually deliver the signal. */
- int ret;
-#ifdef CONFIG_COMPAT
- if (is_compat_task()) {
- ret = handle_signal32(signr, &ka, &info, oldset, regs);
- }
- else
-#endif
- ret = handle_signal(signr, &ka, &info, oldset, regs);
- if (!ret) {
+ if (current_thread_info()->system_call) {
+ regs->svc_code = current_thread_info()->system_call;
+ /* Check for system call restarting. */
+ switch (regs->gprs[2]) {
+ case -ERESTART_RESTARTBLOCK:
+ case -ERESTARTNOHAND:
+ regs->gprs[2] = -EINTR;
+ break;
+ case -ERESTARTSYS:
+ if (!(ka.sa.sa_flags & SA_RESTART)) {
+ regs->gprs[2] = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ regs->gprs[2] = regs->orig_gpr2;
+ regs->psw.addr =
+ __rewind_psw(regs->psw,
+ regs->svc_code >> 16);
+ break;
+ }
+ /* No longer in a system call */
+ clear_thread_flag(TIF_SYSCALL);
+ }
+
+ if ((is_compat_task() ?
+ handle_signal32(signr, &ka, &info, oldset, regs) :
+ handle_signal(signr, &ka, &info, oldset, regs)) == 0) {
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
@@ -482,11 +480,32 @@ void do_signal(struct pt_regs *regs)
* Let tracing know that we've done the handler setup.
*/
tracehook_signal_handler(signr, &info, &ka, regs,
- test_thread_flag(TIF_SINGLE_STEP));
+ test_thread_flag(TIF_SINGLE_STEP));
}
return;
}
+ /* No handlers present - check for system call restart */
+ if (current_thread_info()->system_call) {
+ regs->svc_code = current_thread_info()->system_call;
+ switch (regs->gprs[2]) {
+ case -ERESTART_RESTARTBLOCK:
+ /* Restart with sys_restart_syscall */
+ regs->svc_code = __NR_restart_syscall;
+ /* fallthrough */
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ /* Restart system call with magic TIF bit. */
+ regs->gprs[2] = regs->orig_gpr2;
+ set_thread_flag(TIF_SYSCALL);
+ break;
+ default:
+ clear_thread_flag(TIF_SYSCALL);
+ break;
+ }
+ }
+
/*
* If there's no signal to deliver, we just put the saved sigmask back.
*/
@@ -494,13 +513,6 @@ void do_signal(struct pt_regs *regs)
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
-
- /* Restart a different system call. */
- if (retval == -ERESTART_RESTARTBLOCK
- && regs->psw.addr == continue_addr) {
- regs->gprs[2] = __NR_restart_syscall;
- set_thread_flag(TIF_RESTART_SVC);
- }
}
void do_notify_resume(struct pt_regs *regs)
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 6ab16ac64d29..3ea872890da2 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -38,6 +38,7 @@
#include <linux/timex.h>
#include <linux/bootmem.h>
#include <linux/slab.h>
+#include <linux/crash_dump.h>
#include <asm/asm-offsets.h>
#include <asm/ipl.h>
#include <asm/setup.h>
@@ -97,6 +98,29 @@ static inline int cpu_stopped(int cpu)
return raw_cpu_stopped(cpu_logical_map(cpu));
}
+/*
+ * Ensure that PSW restart is done on an online CPU
+ */
+void smp_restart_with_online_cpu(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ if (stap() == __cpu_logical_map[cpu]) {
+ /* We are online: Enable DAT again and return */
+ __load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
+ return;
+ }
+ }
+ /* We are not online: Do PSW restart on an online CPU */
+ while (sigp(cpu, sigp_restart) == sigp_busy)
+ cpu_relax();
+ /* And stop ourself */
+ while (raw_sigp(stap(), sigp_stop) == sigp_busy)
+ cpu_relax();
+ for (;;);
+}
+
void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
{
struct _lowcore *lc, *current_lc;
@@ -106,14 +130,16 @@ void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
if (smp_processor_id() == 0)
func(data);
- __load_psw_mask(PSW_BASE_BITS | PSW_DEFAULT_KEY);
+ __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE |
+ PSW_MASK_EA | PSW_MASK_BA);
/* Disable lowcore protection */
__ctl_clear_bit(0, 28);
current_lc = lowcore_ptr[smp_processor_id()];
lc = lowcore_ptr[0];
if (!lc)
lc = current_lc;
- lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+ lc->restart_psw.mask =
+ PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu;
if (!cpu_online(0))
smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]);
@@ -135,7 +161,7 @@ void smp_send_stop(void)
int cpu, rc;
/* Disable all interrupts/machine checks */
- __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
+ __load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
trace_hardirqs_off();
/* stop all processors */
@@ -161,7 +187,10 @@ static void do_ext_call_interrupt(unsigned int ext_int_code,
{
unsigned long bits;
- kstat_cpu(smp_processor_id()).irqs[EXTINT_IPI]++;
+ if (ext_int_code == 0x1202)
+ kstat_cpu(smp_processor_id()).irqs[EXTINT_EXC]++;
+ else
+ kstat_cpu(smp_processor_id()).irqs[EXTINT_EMS]++;
/*
* handle bit signal external calls
*/
@@ -183,12 +212,19 @@ static void do_ext_call_interrupt(unsigned int ext_int_code,
*/
static void smp_ext_bitcall(int cpu, int sig)
{
+ int order;
+
/*
* Set signaling bit in lowcore of target cpu and kick it
*/
set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
- while (sigp(cpu, sigp_emergency_signal) == sigp_busy)
+ while (1) {
+ order = smp_vcpu_scheduled(cpu) ?
+ sigp_external_call : sigp_emergency_signal;
+ if (sigp(cpu, order) != sigp_busy)
+ break;
udelay(10);
+ }
}
void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -281,11 +317,13 @@ void smp_ctl_clear_bit(int cr, int bit)
}
EXPORT_SYMBOL(smp_ctl_clear_bit);
-#ifdef CONFIG_ZFCPDUMP
+#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_CRASH_DUMP)
static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
{
- if (ipl_info.type != IPL_TYPE_FCP_DUMP)
+ if (ipl_info.type != IPL_TYPE_FCP_DUMP && !OLDMEM_BASE)
+ return;
+ if (is_kdump_kernel())
return;
if (cpu >= NR_CPUS) {
pr_warning("CPU %i exceeds the maximum %i and is excluded from "
@@ -403,6 +441,18 @@ static void __init smp_detect_cpus(void)
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
panic("smp_detect_cpus failed to allocate memory\n");
+#ifdef CONFIG_CRASH_DUMP
+ if (OLDMEM_BASE && !is_kdump_kernel()) {
+ struct save_area *save_area;
+
+ save_area = kmalloc(sizeof(*save_area), GFP_KERNEL);
+ if (!save_area)
+ panic("could not allocate memory for save area\n");
+ copy_oldmem_page(1, (void *) save_area, sizeof(*save_area),
+ 0x200, 0);
+ zfcpdump_save_areas[0] = save_area;
+ }
+#endif
/* Use sigp detection algorithm if sclp doesn't work. */
if (sclp_get_cpu_info(info)) {
smp_use_sigp_detection = 1;
@@ -463,7 +513,8 @@ int __cpuinit start_secondary(void *cpuvoid)
set_cpu_online(smp_processor_id(), true);
ipi_call_unlock();
__ctl_clear_bit(0, 28); /* Disable lowcore protection */
- S390_lowcore.restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+ S390_lowcore.restart_psw.mask =
+ PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
S390_lowcore.restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
__ctl_set_bit(0, 28); /* Enable lowcore protection */
@@ -511,7 +562,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
memset((char *)lowcore + 512, 0, sizeof(*lowcore) - 512);
lowcore->async_stack = async_stack + ASYNC_SIZE;
lowcore->panic_stack = panic_stack + PAGE_SIZE;
- lowcore->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+ lowcore->restart_psw.mask =
+ PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
lowcore->restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
if (user_mode != HOME_SPACE_MODE)
@@ -712,6 +764,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
/* request the 0x1201 emergency signal external interrupt */
if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
panic("Couldn't request external interrupt 0x1201");
+ /* request the 0x1202 external call external interrupt */
+ if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0)
+ panic("Couldn't request external interrupt 0x1202");
/* Reallocate current lowcore, but keep its contents. */
lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER);
diff --git a/arch/s390/kernel/suspend.c b/arch/s390/kernel/suspend.c
index cf9e5c6d5527..47df775c844d 100644
--- a/arch/s390/kernel/suspend.c
+++ b/arch/s390/kernel/suspend.c
@@ -7,6 +7,8 @@
*/
#include <linux/pfn.h>
+#include <linux/suspend.h>
+#include <linux/mm.h>
#include <asm/system.h>
/*
@@ -14,6 +16,123 @@
*/
extern const void __nosave_begin, __nosave_end;
+/*
+ * The restore of the saved pages in an hibernation image will set
+ * the change and referenced bits in the storage key for each page.
+ * Overindication of the referenced bits after an hibernation cycle
+ * does not cause any harm but the overindication of the change bits
+ * would cause trouble.
+ * Use the ARCH_SAVE_PAGE_KEYS hooks to save the storage key of each
+ * page to the most significant byte of the associated page frame
+ * number in the hibernation image.
+ */
+
+/*
+ * Key storage is allocated as a linked list of pages.
+ * The size of the keys array is (PAGE_SIZE - sizeof(long))
+ */
+struct page_key_data {
+ struct page_key_data *next;
+ unsigned char data[];
+};
+
+#define PAGE_KEY_DATA_SIZE (PAGE_SIZE - sizeof(struct page_key_data *))
+
+static struct page_key_data *page_key_data;
+static struct page_key_data *page_key_rp, *page_key_wp;
+static unsigned long page_key_rx, page_key_wx;
+
+/*
+ * For each page in the hibernation image one additional byte is
+ * stored in the most significant byte of the page frame number.
+ * On suspend no additional memory is required but on resume the
+ * keys need to be memorized until the page data has been restored.
+ * Only then can the storage keys be set to their old state.
+ */
+unsigned long page_key_additional_pages(unsigned long pages)
+{
+ return DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
+}
+
+/*
+ * Free page_key_data list of arrays.
+ */
+void page_key_free(void)
+{
+ struct page_key_data *pkd;
+
+ while (page_key_data) {
+ pkd = page_key_data;
+ page_key_data = pkd->next;
+ free_page((unsigned long) pkd);
+ }
+}
+
+/*
+ * Allocate page_key_data list of arrays with enough room to store
+ * one byte for each page in the hibernation image.
+ */
+int page_key_alloc(unsigned long pages)
+{
+ struct page_key_data *pk;
+ unsigned long size;
+
+ size = DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
+ while (size--) {
+ pk = (struct page_key_data *) get_zeroed_page(GFP_KERNEL);
+ if (!pk) {
+ page_key_free();
+ return -ENOMEM;
+ }
+ pk->next = page_key_data;
+ page_key_data = pk;
+ }
+ page_key_rp = page_key_wp = page_key_data;
+ page_key_rx = page_key_wx = 0;
+ return 0;
+}
+
+/*
+ * Save the storage key into the upper 8 bits of the page frame number.
+ */
+void page_key_read(unsigned long *pfn)
+{
+ unsigned long addr;
+
+ addr = (unsigned long) page_address(pfn_to_page(*pfn));
+ *(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr);
+}
+
+/*
+ * Extract the storage key from the upper 8 bits of the page frame number
+ * and store it in the page_key_data list of arrays.
+ */
+void page_key_memorize(unsigned long *pfn)
+{
+ page_key_wp->data[page_key_wx] = *(unsigned char *) pfn;
+ *(unsigned char *) pfn = 0;
+ if (++page_key_wx < PAGE_KEY_DATA_SIZE)
+ return;
+ page_key_wp = page_key_wp->next;
+ page_key_wx = 0;
+}
+
+/*
+ * Get the next key from the page_key_data list of arrays and set the
+ * storage key of the page referred by @address. If @address refers to
+ * a "safe" page the swsusp_arch_resume code will transfer the storage
+ * key from the buffer page to the original page.
+ */
+void page_key_write(void *address)
+{
+ page_set_storage_key((unsigned long) address,
+ page_key_rp->data[page_key_rx], 0);
+ if (++page_key_rx >= PAGE_KEY_DATA_SIZE)
+ return;
+ page_key_rp = page_key_rp->next;
+ page_key_rx = 0;
+}
+
int pfn_is_nosave(unsigned long pfn)
{
unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index 51bcdb50a230..acb78cdee896 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -136,11 +136,14 @@ ENTRY(swsusp_arch_resume)
0:
lg %r2,8(%r1)
lg %r4,0(%r1)
+ iske %r0,%r4
lghi %r3,PAGE_SIZE
lghi %r5,PAGE_SIZE
1:
mvcle %r2,%r4,0
jo 1b
+ lg %r2,8(%r1)
+ sske %r0,%r2
lg %r1,16(%r1)
ltgr %r1,%r1
jnz 0b
diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c
index 5c9e439bf3f6..2a94b774695c 100644
--- a/arch/s390/kernel/sysinfo.c
+++ b/arch/s390/kernel/sysinfo.c
@@ -442,7 +442,7 @@ void s390_adjust_jiffies(void)
*/
FP_UNPACK_SP(SA, &fmil);
if ((info->capability >> 23) == 0)
- FP_FROM_INT_S(SB, info->capability, 32, int);
+ FP_FROM_INT_S(SB, (long) info->capability, 64, long);
else
FP_UNPACK_SP(SB, &info->capability);
FP_DIV_S(SR, SA, SB);
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index dff933065ab6..ebbfab3c6e5a 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -48,6 +48,7 @@
#include <asm/timer.h>
#include <asm/etr.h>
#include <asm/cio.h>
+#include "entry.h"
/* change this if you have some constant time drift */
#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ)
@@ -109,10 +110,14 @@ static void fixup_clock_comparator(unsigned long long delta)
set_clock_comparator(S390_lowcore.clock_comparator);
}
-static int s390_next_event(unsigned long delta,
+static int s390_next_ktime(ktime_t expires,
struct clock_event_device *evt)
{
- S390_lowcore.clock_comparator = get_clock() + delta;
+ u64 nsecs;
+
+ nsecs = ktime_to_ns(ktime_sub(expires, ktime_get_monotonic_offset()));
+ do_div(nsecs, 125);
+ S390_lowcore.clock_comparator = TOD_UNIX_EPOCH + (nsecs << 9);
set_clock_comparator(S390_lowcore.clock_comparator);
return 0;
}
@@ -137,14 +142,15 @@ void init_cpu_timer(void)
cpu = smp_processor_id();
cd = &per_cpu(comparators, cpu);
cd->name = "comparator";
- cd->features = CLOCK_EVT_FEAT_ONESHOT;
+ cd->features = CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_KTIME;
cd->mult = 16777;
cd->shift = 12;
cd->min_delta_ns = 1;
cd->max_delta_ns = LONG_MAX;
cd->rating = 400;
cd->cpumask = cpumask_of(cpu);
- cd->set_next_event = s390_next_event;
+ cd->set_next_ktime = s390_next_ktime;
cd->set_mode = s390_set_mode;
clockevents_register_device(cd);
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 0cd340b72632..77b8942b9a15 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -299,8 +299,8 @@ out:
}
__initcall(init_topology_update);
-static void alloc_masks(struct sysinfo_15_1_x *info, struct mask_info *mask,
- int offset)
+static void __init alloc_masks(struct sysinfo_15_1_x *info,
+ struct mask_info *mask, int offset)
{
int i, nr_masks;
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index ffabcd9d3363..a9807dd86276 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -200,7 +200,7 @@ void show_registers(struct pt_regs *regs)
mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
#ifdef CONFIG_64BIT
- printk(" EA:%x", mask_bits(regs, PSW_BASE_BITS));
+ printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
#endif
printk("\n%s GPRS: " FOURLONG, mode,
regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
@@ -334,7 +334,8 @@ void __kprobes do_per_trap(struct pt_regs *regs)
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_HWBKPT;
- info.si_addr = (void *) current->thread.per_event.address;
+ info.si_addr =
+ (void __force __user *) current->thread.per_event.address;
force_sig_info(SIGTRAP, &info, current);
}
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 2d6228f60cd6..bb48977f5469 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -170,7 +170,8 @@ void __kprobes vtime_stop_cpu(void)
psw_t psw;
/* Wait for external, I/O or machine check interrupt. */
- psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT;
+ psw.mask = psw_kernel_bits | PSW_MASK_WAIT |
+ PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
idle->nohz_delay = 0;
@@ -183,7 +184,8 @@ void __kprobes vtime_stop_cpu(void)
* set_cpu_timer(VTIMER_MAX_SLICE);
* idle->idle_enter = get_clock();
* __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
- * PSW_MASK_IO | PSW_MASK_EXT);
+ * PSW_MASK_DAT | PSW_MASK_IO |
+ * PSW_MASK_EXT | PSW_MASK_MCHECK);
* The difference is that the inline assembly makes sure that
* the last three instruction are stpt, stck and lpsw in that
* order. This is done to increase the precision.
@@ -216,7 +218,8 @@ void __kprobes vtime_stop_cpu(void)
* vq->idle = get_cpu_timer();
* idle->idle_enter = get_clock();
* __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
- * PSW_MASK_IO | PSW_MASK_EXT);
+ * PSW_MASK_DAT | PSW_MASK_IO |
+ * PSW_MASK_EXT | PSW_MASK_MCHECK);
* The difference is that the inline assembly makes sure that
* the last three instruction are stpt, stck and lpsw in that
* order. This is done to increase the precision.
@@ -458,7 +461,7 @@ void add_virt_timer_periodic(void *new)
}
EXPORT_SYMBOL(add_virt_timer_periodic);
-int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
+static int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
{
struct vtimer_queue *vq;
unsigned long flags;
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index 9e4c84187cf5..87cedd61be04 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -1,7 +1,7 @@
/*
* diag.c - handling diagnose instructions
*
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2011
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (version 2 only)
@@ -15,6 +15,34 @@
#include <linux/kvm_host.h>
#include "kvm-s390.h"
+static int diag_release_pages(struct kvm_vcpu *vcpu)
+{
+ unsigned long start, end;
+ unsigned long prefix = vcpu->arch.sie_block->prefix;
+
+ start = vcpu->arch.guest_gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
+ end = vcpu->arch.guest_gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
+
+ if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end
+ || start < 2 * PAGE_SIZE)
+ return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+ VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end);
+ vcpu->stat.diagnose_10++;
+
+ /* we checked for start > end above */
+ if (end < prefix || start >= prefix + 2 * PAGE_SIZE) {
+ gmap_discard(start, end, vcpu->arch.gmap);
+ } else {
+ if (start < prefix)
+ gmap_discard(start, prefix, vcpu->arch.gmap);
+ if (end >= prefix)
+ gmap_discard(prefix + 2 * PAGE_SIZE,
+ end, vcpu->arch.gmap);
+ }
+ return 0;
+}
+
static int __diag_time_slice_end(struct kvm_vcpu *vcpu)
{
VCPU_EVENT(vcpu, 5, "%s", "diag time slice end");
@@ -57,6 +85,8 @@ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16;
switch (code) {
+ case 0x10:
+ return diag_release_pages(vcpu);
case 0x44:
return __diag_time_slice_end(vcpu);
case 0x308:
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index c9aeb4b4d0b8..87c16705b381 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -38,6 +38,11 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
switch (inti->type) {
+ case KVM_S390_INT_EXTERNAL_CALL:
+ if (psw_extint_disabled(vcpu))
+ return 0;
+ if (vcpu->arch.sie_block->gcr[0] & 0x2000ul)
+ return 1;
case KVM_S390_INT_EMERGENCY:
if (psw_extint_disabled(vcpu))
return 0;
@@ -98,6 +103,7 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
switch (inti->type) {
+ case KVM_S390_INT_EXTERNAL_CALL:
case KVM_S390_INT_EMERGENCY:
case KVM_S390_INT_SERVICE:
case KVM_S390_INT_VIRTIO:
@@ -143,6 +149,28 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
exception = 1;
break;
+ case KVM_S390_INT_EXTERNAL_CALL:
+ VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
+ vcpu->stat.deliver_external_call++;
+ rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1202);
+ if (rc == -EFAULT)
+ exception = 1;
+
+ rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, inti->extcall.code);
+ if (rc == -EFAULT)
+ exception = 1;
+
+ rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+ if (rc == -EFAULT)
+ exception = 1;
+
+ rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+ __LC_EXT_NEW_PSW, sizeof(psw_t));
+ if (rc == -EFAULT)
+ exception = 1;
+ break;
+
case KVM_S390_INT_SERVICE:
VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
inti->ext.ext_params);
@@ -522,6 +550,7 @@ int kvm_s390_inject_vm(struct kvm *kvm,
break;
case KVM_S390_PROGRAM_INT:
case KVM_S390_SIGP_STOP:
+ case KVM_S390_INT_EXTERNAL_CALL:
case KVM_S390_INT_EMERGENCY:
default:
kfree(inti);
@@ -581,6 +610,7 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
break;
case KVM_S390_SIGP_STOP:
case KVM_S390_RESTART:
+ case KVM_S390_INT_EXTERNAL_CALL:
case KVM_S390_INT_EMERGENCY:
VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
inti->type = s390int->type;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index dc2b580e27bc..0bd3bea1e4cd 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -46,6 +46,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "instruction_lctlg", VCPU_STAT(instruction_lctlg) },
{ "instruction_lctl", VCPU_STAT(instruction_lctl) },
{ "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
+ { "deliver_external_call", VCPU_STAT(deliver_external_call) },
{ "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
{ "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) },
{ "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) },
@@ -64,11 +65,13 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "instruction_stfl", VCPU_STAT(instruction_stfl) },
{ "instruction_tprot", VCPU_STAT(instruction_tprot) },
{ "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
+ { "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) },
{ "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
{ "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
{ "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) },
{ "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) },
{ "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
+ { "diagnose_10", VCPU_STAT(diagnose_10) },
{ "diagnose_44", VCPU_STAT(diagnose_44) },
{ NULL }
};
@@ -175,6 +178,8 @@ int kvm_arch_init_vm(struct kvm *kvm)
if (rc)
goto out_err;
+ rc = -ENOMEM;
+
kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
if (!kvm->arch.sca)
goto out_err;
@@ -312,11 +317,17 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
unsigned int id)
{
- struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
- int rc = -ENOMEM;
+ struct kvm_vcpu *vcpu;
+ int rc = -EINVAL;
+
+ if (id >= KVM_MAX_VCPUS)
+ goto out;
+ rc = -ENOMEM;
+
+ vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
if (!vcpu)
- goto out_nomem;
+ goto out;
vcpu->arch.sie_block = (struct kvm_s390_sie_block *)
get_zeroed_page(GFP_KERNEL);
@@ -352,7 +363,7 @@ out_free_sie_block:
free_page((unsigned long)(vcpu->arch.sie_block));
out_free_cpu:
kfree(vcpu);
-out_nomem:
+out:
return ERR_PTR(rc);
}
@@ -386,6 +397,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
{
memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
+ restore_access_regs(vcpu->arch.guest_acrs);
return 0;
}
@@ -401,6 +413,7 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
{
memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
vcpu->arch.guest_fpregs.fpc = fpu->fpc;
+ restore_fp_regs(&vcpu->arch.guest_fpregs);
return 0;
}
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index d6a50c1fb2e6..f815118835f3 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -87,6 +87,7 @@ static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr)
return -ENOMEM;
inti->type = KVM_S390_INT_EMERGENCY;
+ inti->emerg.code = vcpu->vcpu_id;
spin_lock(&fi->lock);
li = fi->local_int[cpu_addr];
@@ -103,9 +104,47 @@ static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr)
wake_up_interruptible(&li->wq);
spin_unlock_bh(&li->lock);
rc = 0; /* order accepted */
+ VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr);
+unlock:
+ spin_unlock(&fi->lock);
+ return rc;
+}
+
+static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr)
+{
+ struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+ struct kvm_s390_local_interrupt *li;
+ struct kvm_s390_interrupt_info *inti;
+ int rc;
+
+ if (cpu_addr >= KVM_MAX_VCPUS)
+ return 3; /* not operational */
+
+ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+ if (!inti)
+ return -ENOMEM;
+
+ inti->type = KVM_S390_INT_EXTERNAL_CALL;
+ inti->extcall.code = vcpu->vcpu_id;
+
+ spin_lock(&fi->lock);
+ li = fi->local_int[cpu_addr];
+ if (li == NULL) {
+ rc = 3; /* not operational */
+ kfree(inti);
+ goto unlock;
+ }
+ spin_lock_bh(&li->lock);
+ list_add_tail(&inti->list, &li->list);
+ atomic_set(&li->active, 1);
+ atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
+ if (waitqueue_active(&li->wq))
+ wake_up_interruptible(&li->wq);
+ spin_unlock_bh(&li->lock);
+ rc = 0; /* order accepted */
+ VCPU_EVENT(vcpu, 4, "sent sigp ext call to cpu %x", cpu_addr);
unlock:
spin_unlock(&fi->lock);
- VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr);
return rc;
}
@@ -267,6 +306,10 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
rc = __sigp_sense(vcpu, cpu_addr,
&vcpu->arch.guest_gprs[r1]);
break;
+ case SIGP_EXTERNAL_CALL:
+ vcpu->stat.instruction_sigp_external_call++;
+ rc = __sigp_external_call(vcpu, cpu_addr);
+ break;
case SIGP_EMERGENCY:
vcpu->stat.instruction_sigp_emergency++;
rc = __sigp_emergency(vcpu, cpu_addr);
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index a65229d91c92..db92f044024c 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -32,7 +32,8 @@ static void __udelay_disabled(unsigned long long usecs)
u64 clock_saved;
u64 end;
- mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
+ mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_WAIT |
+ PSW_MASK_EXT | PSW_MASK_MCHECK;
end = get_clock() + (usecs << 12);
clock_saved = local_tick_disable();
__ctl_store(cr0_saved, 0, 0);
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 74833831417f..342ae35a5ba9 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -342,7 +342,8 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
if (segment_eq(get_fs(), KERNEL_DS))
return __futex_atomic_op_pt(op, uaddr, oparg, old);
spin_lock(&current->mm->page_table_lock);
- uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+ uaddr = (u32 __force __user *)
+ __dat_user_addr((__force unsigned long) uaddr);
if (!uaddr) {
spin_unlock(&current->mm->page_table_lock);
return -EFAULT;
@@ -378,7 +379,8 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
if (segment_eq(get_fs(), KERNEL_DS))
return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
spin_lock(&current->mm->page_table_lock);
- uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+ uaddr = (u32 __force __user *)
+ __dat_user_addr((__force unsigned long) uaddr);
if (!uaddr) {
spin_unlock(&current->mm->page_table_lock);
return -EFAULT;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 9564fc779b27..1766def5bc3f 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -307,7 +307,7 @@ static inline int do_exception(struct pt_regs *regs, int access,
#ifdef CONFIG_PGSTE
if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) {
- address = gmap_fault(address,
+ address = __gmap_fault(address,
(struct gmap *) S390_lowcore.gmap);
if (address == -EFAULT) {
fault = VM_FAULT_BADMAP;
@@ -393,7 +393,7 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long pgm_int_code,
int fault;
/* Protection exception is suppressing, decrement psw address. */
- regs->psw.addr -= (pgm_int_code >> 16);
+ regs->psw.addr = __rewind_psw(regs->psw, pgm_int_code >> 16);
/*
* Check for low-address protection. This needs to be treated
* as a special case because the translation exception code
@@ -454,7 +454,7 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
struct pt_regs regs;
int access, fault;
- regs.psw.mask = psw_kernel_bits;
+ regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK;
if (!irqs_disabled())
regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
regs.psw.addr = (unsigned long) __builtin_return_address(0);
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
index 45b405ca2567..65cb06e2af4e 100644
--- a/arch/s390/mm/gup.c
+++ b/arch/s390/mm/gup.c
@@ -52,7 +52,7 @@ static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
unsigned long end, int write, struct page **pages, int *nr)
{
unsigned long mask, result;
- struct page *head, *page;
+ struct page *head, *page, *tail;
int refs;
result = write ? 0 : _SEGMENT_ENTRY_RO;
@@ -64,6 +64,7 @@ static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
refs = 0;
head = pmd_page(pmd);
page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
+ tail = page;
do {
VM_BUG_ON(compound_head(page) != head);
pages[*nr] = page;
@@ -81,6 +82,17 @@ static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
*nr -= refs;
while (refs--)
put_page(head);
+ return 0;
+ }
+
+ /*
+ * Any tail page need their mapcount reference taken before we
+ * return.
+ */
+ while (refs--) {
+ if (PageTail(tail))
+ get_huge_page_tail(tail);
+ tail++;
}
return 1;
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index 5dbbaa6e594c..1cb8427bedfb 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/gfp.h>
#include <asm/system.h>
/*
@@ -60,6 +61,9 @@ long probe_kernel_write(void *dst, const void *src, size_t size)
return copied < 0 ? -EFAULT : 0;
}
+/*
+ * Copy memory in real mode (kernel to kernel)
+ */
int memcpy_real(void *dest, void *src, size_t count)
{
register unsigned long _dest asm("2") = (unsigned long) dest;
@@ -101,3 +105,55 @@ void copy_to_absolute_zero(void *dest, void *src, size_t count)
__ctl_load(cr0, 0, 0);
preempt_enable();
}
+
+/*
+ * Copy memory from kernel (real) to user (virtual)
+ */
+int copy_to_user_real(void __user *dest, void *src, size_t count)
+{
+ int offs = 0, size, rc;
+ char *buf;
+
+ buf = (char *) __get_free_page(GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ rc = -EFAULT;
+ while (offs < count) {
+ size = min(PAGE_SIZE, count - offs);
+ if (memcpy_real(buf, src + offs, size))
+ goto out;
+ if (copy_to_user(dest + offs, buf, size))
+ goto out;
+ offs += size;
+ }
+ rc = 0;
+out:
+ free_page((unsigned long) buf);
+ return rc;
+}
+
+/*
+ * Copy memory from user (virtual) to kernel (real)
+ */
+int copy_from_user_real(void *dest, void __user *src, size_t count)
+{
+ int offs = 0, size, rc;
+ char *buf;
+
+ buf = (char *) __get_free_page(GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ rc = -EFAULT;
+ while (offs < count) {
+ size = min(PAGE_SIZE, count - offs);
+ if (copy_from_user(buf, src + offs, size))
+ goto out;
+ if (memcpy_real(dest + offs, buf, size))
+ goto out;
+ offs += size;
+ }
+ rc = 0;
+out:
+ free_page((unsigned long) buf);
+ return rc;
+}
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index c9a9f7f18188..f09c74881b7e 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -26,6 +26,7 @@
#include <linux/personality.h>
#include <linux/mm.h>
+#include <linux/mman.h>
#include <linux/module.h>
#include <linux/random.h>
#include <asm/pgalloc.h>
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index d013ed39743b..b36537a5f43e 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -5,6 +5,7 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
+#include <asm/cacheflush.h>
#include <asm/pgtable.h>
static void change_page_attr(unsigned long addr, int numpages,
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 5d56c2b95b14..301c84d3b542 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -1,5 +1,5 @@
/*
- * Copyright IBM Corp. 2007,2009
+ * Copyright IBM Corp. 2007,2011
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
@@ -222,6 +222,7 @@ void gmap_free(struct gmap *gmap)
/* Free all segment & region tables. */
down_read(&gmap->mm->mmap_sem);
+ spin_lock(&gmap->mm->page_table_lock);
list_for_each_entry_safe(page, next, &gmap->crst_list, lru) {
table = (unsigned long *) page_to_phys(page);
if ((*table & _REGION_ENTRY_TYPE_MASK) == 0)
@@ -230,6 +231,7 @@ void gmap_free(struct gmap *gmap)
gmap_unlink_segment(gmap, table);
__free_pages(page, ALLOC_ORDER);
}
+ spin_unlock(&gmap->mm->page_table_lock);
up_read(&gmap->mm->mmap_sem);
list_del(&gmap->list);
kfree(gmap);
@@ -256,6 +258,9 @@ void gmap_disable(struct gmap *gmap)
}
EXPORT_SYMBOL_GPL(gmap_disable);
+/*
+ * gmap_alloc_table is assumed to be called with mmap_sem held
+ */
static int gmap_alloc_table(struct gmap *gmap,
unsigned long *table, unsigned long init)
{
@@ -267,14 +272,12 @@ static int gmap_alloc_table(struct gmap *gmap,
return -ENOMEM;
new = (unsigned long *) page_to_phys(page);
crst_table_init(new, init);
- down_read(&gmap->mm->mmap_sem);
if (*table & _REGION_ENTRY_INV) {
list_add(&page->lru, &gmap->crst_list);
*table = (unsigned long) new | _REGION_ENTRY_LENGTH |
(*table & _REGION_ENTRY_TYPE_MASK);
} else
__free_pages(page, ALLOC_ORDER);
- up_read(&gmap->mm->mmap_sem);
return 0;
}
@@ -299,6 +302,7 @@ int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
flush = 0;
down_read(&gmap->mm->mmap_sem);
+ spin_lock(&gmap->mm->page_table_lock);
for (off = 0; off < len; off += PMD_SIZE) {
/* Walk the guest addr space page table */
table = gmap->table + (((to + off) >> 53) & 0x7ff);
@@ -320,6 +324,7 @@ int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
*table = _SEGMENT_ENTRY_INV;
}
out:
+ spin_unlock(&gmap->mm->page_table_lock);
up_read(&gmap->mm->mmap_sem);
if (flush)
gmap_flush_tlb(gmap);
@@ -350,6 +355,7 @@ int gmap_map_segment(struct gmap *gmap, unsigned long from,
flush = 0;
down_read(&gmap->mm->mmap_sem);
+ spin_lock(&gmap->mm->page_table_lock);
for (off = 0; off < len; off += PMD_SIZE) {
/* Walk the gmap address space page table */
table = gmap->table + (((to + off) >> 53) & 0x7ff);
@@ -373,19 +379,24 @@ int gmap_map_segment(struct gmap *gmap, unsigned long from,
flush |= gmap_unlink_segment(gmap, table);
*table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | (from + off);
}
+ spin_unlock(&gmap->mm->page_table_lock);
up_read(&gmap->mm->mmap_sem);
if (flush)
gmap_flush_tlb(gmap);
return 0;
out_unmap:
+ spin_unlock(&gmap->mm->page_table_lock);
up_read(&gmap->mm->mmap_sem);
gmap_unmap_segment(gmap, to, len);
return -ENOMEM;
}
EXPORT_SYMBOL_GPL(gmap_map_segment);
-unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
+/*
+ * this function is assumed to be called with mmap_sem held
+ */
+unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
{
unsigned long *table, vmaddr, segment;
struct mm_struct *mm;
@@ -445,16 +456,75 @@ unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
page = pmd_page(*pmd);
mp = (struct gmap_pgtable *) page->index;
rmap->entry = table;
+ spin_lock(&mm->page_table_lock);
list_add(&rmap->list, &mp->mapper);
+ spin_unlock(&mm->page_table_lock);
/* Set gmap segment table entry to page table. */
*table = pmd_val(*pmd) & PAGE_MASK;
return vmaddr | (address & ~PMD_MASK);
}
return -EFAULT;
+}
+unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
+{
+ unsigned long rc;
+
+ down_read(&gmap->mm->mmap_sem);
+ rc = __gmap_fault(address, gmap);
+ up_read(&gmap->mm->mmap_sem);
+
+ return rc;
}
EXPORT_SYMBOL_GPL(gmap_fault);
+void gmap_discard(unsigned long from, unsigned long to, struct gmap *gmap)
+{
+
+ unsigned long *table, address, size;
+ struct vm_area_struct *vma;
+ struct gmap_pgtable *mp;
+ struct page *page;
+
+ down_read(&gmap->mm->mmap_sem);
+ address = from;
+ while (address < to) {
+ /* Walk the gmap address space page table */
+ table = gmap->table + ((address >> 53) & 0x7ff);
+ if (unlikely(*table & _REGION_ENTRY_INV)) {
+ address = (address + PMD_SIZE) & PMD_MASK;
+ continue;
+ }
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + ((address >> 42) & 0x7ff);
+ if (unlikely(*table & _REGION_ENTRY_INV)) {
+ address = (address + PMD_SIZE) & PMD_MASK;
+ continue;
+ }
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + ((address >> 31) & 0x7ff);
+ if (unlikely(*table & _REGION_ENTRY_INV)) {
+ address = (address + PMD_SIZE) & PMD_MASK;
+ continue;
+ }
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ table = table + ((address >> 20) & 0x7ff);
+ if (unlikely(*table & _SEGMENT_ENTRY_INV)) {
+ address = (address + PMD_SIZE) & PMD_MASK;
+ continue;
+ }
+ page = pfn_to_page(*table >> PAGE_SHIFT);
+ mp = (struct gmap_pgtable *) page->index;
+ vma = find_vma(gmap->mm, mp->vmaddr);
+ size = min(to - address, PMD_SIZE - (address & ~PMD_MASK));
+ zap_page_range(vma, mp->vmaddr | (address & ~PMD_MASK),
+ size, NULL);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ }
+ up_read(&gmap->mm->mmap_sem);
+}
+EXPORT_SYMBOL_GPL(gmap_discard);
+
void gmap_unmap_notifier(struct mm_struct *mm, unsigned long *table)
{
struct gmap_rmap *rmap, *next;
@@ -662,8 +732,9 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table)
void __tlb_remove_table(void *_table)
{
- void *table = (void *)((unsigned long) _table & PAGE_MASK);
- unsigned type = (unsigned long) _table & ~PAGE_MASK;
+ const unsigned long mask = (FRAG_MASK << 4) | FRAG_MASK;
+ void *table = (void *)((unsigned long) _table & ~mask);
+ unsigned type = (unsigned long) _table & mask;
if (type)
__page_table_free_rcu(table, type);
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 781ff5169560..4799383e2df9 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -335,6 +335,9 @@ void __init vmem_map_init(void)
ro_start = ((unsigned long)&_stext) & PAGE_MASK;
ro_end = PFN_ALIGN((unsigned long)&_eshared);
for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+ if (memory_chunk[i].type == CHUNK_CRASHK ||
+ memory_chunk[i].type == CHUNK_OLDMEM)
+ continue;
start = memory_chunk[i].addr;
end = memory_chunk[i].addr + memory_chunk[i].size;
if (start >= ro_end || end <= ro_start)
@@ -368,6 +371,9 @@ static int __init vmem_convert_memory_chunk(void)
for (i = 0; i < MEMORY_CHUNKS; i++) {
if (!memory_chunk[i].size)
continue;
+ if (memory_chunk[i].type == CHUNK_CRASHK ||
+ memory_chunk[i].type == CHUNK_OLDMEM)
+ continue;
seg = kzalloc(sizeof(*seg), GFP_KERNEL);
if (!seg)
panic("Out of memory...\n");
diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c
index 4552ce40c81a..f43c0e4282af 100644
--- a/arch/s390/oprofile/hwsampler.c
+++ b/arch/s390/oprofile/hwsampler.c
@@ -994,7 +994,7 @@ allocate_error:
*
* Returns 0 on success, !0 on failure.
*/
-int hwsampler_deallocate()
+int hwsampler_deallocate(void)
{
int rc;
@@ -1035,7 +1035,7 @@ unsigned long hwsampler_get_sample_overflow_count(unsigned int cpu)
return cb->sample_overflow;
}
-int hwsampler_setup()
+int hwsampler_setup(void)
{
int rc;
int cpu;
@@ -1102,7 +1102,7 @@ setup_exit:
return rc;
}
-int hwsampler_shutdown()
+int hwsampler_shutdown(void)
{
int rc;
@@ -1203,7 +1203,7 @@ start_all_exit:
*
* Returns 0 on success, !0 on failure.
*/
-int hwsampler_stop_all()
+int hwsampler_stop_all(void)
{
int tmp_rc, rc, cpu;
struct hws_cpu_buffer *cb;
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index ff9177c8f643..5629e2099130 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -101,10 +101,6 @@ config GENERIC_LOCKBREAK
def_bool y
depends on SMP && PREEMPT
-config SYS_SUPPORTS_PM
- bool
- depends on !SMP
-
config ARCH_SUSPEND_POSSIBLE
def_bool n
@@ -649,7 +645,7 @@ config CRASH_DUMP
a specially reserved region and then later executed after
a crash by kdump/kexec. The crash dump kernel must be compiled
to a memory address not used by the main kernel using
- MEMORY_START.
+ PHYSICAL_START.
For more details see Documentation/kdump/kdump.txt
@@ -660,6 +656,17 @@ config KEXEC_JUMP
Jump between original kernel and kexeced kernel and invoke
code via KEXEC
+config PHYSICAL_START
+ hex "Physical address where the kernel is loaded" if (EXPERT || CRASH_DUMP)
+ default MEMORY_START
+ ---help---
+ This gives the physical address where the kernel is loaded
+ and is ordinarily the same as MEMORY_START.
+
+ Different values are primarily used in the case of kexec on panic
+ where the fail safe kernel needs to run at a different address
+ than the panic-ed kernel.
+
config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode"
depends on PROC_FS
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 99385d0b3f3b..3fc0f413777c 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -80,6 +80,7 @@ defaultimage-$(CONFIG_SH_RSK) := uImage
defaultimage-$(CONFIG_SH_URQUELL) := uImage
defaultimage-$(CONFIG_SH_MIGOR) := uImage
defaultimage-$(CONFIG_SH_AP325RXA) := uImage
+defaultimage-$(CONFIG_SH_SH7757LCR) := uImage
defaultimage-$(CONFIG_SH_7724_SOLUTION_ENGINE) := uImage
defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE) := vmlinux
defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE) := vmlinux
diff --git a/arch/sh/boards/board-espt.c b/arch/sh/boards/board-espt.c
index 9da92ac36533..b3ae9d38cbc0 100644
--- a/arch/sh/boards/board-espt.c
+++ b/arch/sh/boards/board-espt.c
@@ -13,9 +13,9 @@
#include <linux/interrupt.h>
#include <linux/mtd/physmap.h>
#include <linux/io.h>
+#include <linux/sh_eth.h>
#include <asm/machvec.h>
#include <asm/sizes.h>
-#include <asm/sh_eth.h>
/* NOR Flash */
static struct mtd_partition espt_nor_flash_partitions[] = {
diff --git a/arch/sh/boards/board-secureedge5410.c b/arch/sh/boards/board-secureedge5410.c
index f968f17891a4..03820c3c93d4 100644
--- a/arch/sh/boards/board-secureedge5410.c
+++ b/arch/sh/boards/board-secureedge5410.c
@@ -41,8 +41,7 @@ static int __init eraseconfig_init(void)
printk("SnapGear: EraseConfig init\n");
/* Setup "EraseConfig" switch on external IRQ 0 */
- if (request_irq(irq, eraseconfig_interrupt, IRQF_DISABLED,
- "Erase Config", NULL))
+ if (request_irq(irq, eraseconfig_interrupt, 0, "Erase Config", NULL))
printk("SnapGear: failed to register IRQ%d for Reset witch\n",
irq);
else
diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c
index fa2a208ec6cb..ec8c84c14b17 100644
--- a/arch/sh/boards/board-sh7757lcr.c
+++ b/arch/sh/boards/board-sh7757lcr.c
@@ -18,8 +18,8 @@
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mmcif.h>
#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/sh_eth.h>
#include <cpu/sh7757.h>
-#include <asm/sh_eth.h>
#include <asm/heartbeat.h>
static struct resource heartbeat_resource = {
diff --git a/arch/sh/boards/mach-cayman/irq.c b/arch/sh/boards/mach-cayman/irq.c
index 311bcebdbd07..724e8b7271f4 100644
--- a/arch/sh/boards/mach-cayman/irq.c
+++ b/arch/sh/boards/mach-cayman/irq.c
@@ -46,13 +46,11 @@ static irqreturn_t cayman_interrupt_pci2(int irq, void *dev_id)
static struct irqaction cayman_action_smsc = {
.name = "Cayman SMSC Mux",
.handler = cayman_interrupt_smsc,
- .flags = IRQF_DISABLED,
};
static struct irqaction cayman_action_pci2 = {
.name = "Cayman PCI2 Mux",
.handler = cayman_interrupt_pci2,
- .flags = IRQF_DISABLED,
};
static void enable_cayman_irq(struct irq_data *data)
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index b24d69d509e7..92ddce4b3456 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -28,13 +28,13 @@
#include <linux/spi/mmc_spi.h>
#include <linux/input.h>
#include <linux/input/sh_keysc.h>
+#include <linux/sh_eth.h>
#include <video/sh_mobile_lcdc.h>
#include <sound/sh_fsi.h>
#include <media/sh_mobile_ceu.h>
#include <media/tw9910.h>
#include <media/mt9t112.h>
#include <asm/heartbeat.h>
-#include <asm/sh_eth.h>
#include <asm/clock.h>
#include <asm/suspend.h>
#include <cpu/sh7724.h>
@@ -248,6 +248,10 @@ static struct renesas_usbhs_platform_info usbhs_info = {
.driver_param = {
.buswait_bwait = 4,
.detection_delay = 5,
+ .d0_tx_id = SHDMA_SLAVE_USB1D0_TX,
+ .d0_rx_id = SHDMA_SLAVE_USB1D0_RX,
+ .d1_tx_id = SHDMA_SLAVE_USB1D1_TX,
+ .d1_rx_id = SHDMA_SLAVE_USB1D1_RX,
},
};
diff --git a/arch/sh/boards/mach-hp6xx/hp6xx_apm.c b/arch/sh/boards/mach-hp6xx/hp6xx_apm.c
index b49535c0ddd9..865d8d6e823f 100644
--- a/arch/sh/boards/mach-hp6xx/hp6xx_apm.c
+++ b/arch/sh/boards/mach-hp6xx/hp6xx_apm.c
@@ -86,7 +86,7 @@ static int __init hp6x0_apm_init(void)
int ret;
ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
- IRQF_DISABLED, MODNAME, NULL);
+ 0, MODNAME, NULL);
if (unlikely(ret < 0)) {
printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
HP680_BTN_IRQ);
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index d00756728bd2..b747c0ab9264 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -23,12 +23,12 @@
#include <linux/input.h>
#include <linux/input/sh_keysc.h>
#include <linux/usb/r8a66597.h>
+#include <linux/sh_eth.h>
#include <video/sh_mobile_lcdc.h>
#include <media/sh_mobile_ceu.h>
#include <sound/sh_fsi.h>
#include <asm/io.h>
#include <asm/heartbeat.h>
-#include <asm/sh_eth.h>
#include <asm/clock.h>
#include <asm/suspend.h>
#include <cpu/sh7724.h>
diff --git a/arch/sh/boards/mach-sh7763rdp/setup.c b/arch/sh/boards/mach-sh7763rdp/setup.c
index f3d828f133e5..dd036f1661db 100644
--- a/arch/sh/boards/mach-sh7763rdp/setup.c
+++ b/arch/sh/boards/mach-sh7763rdp/setup.c
@@ -17,8 +17,8 @@
#include <linux/mtd/physmap.h>
#include <linux/fb.h>
#include <linux/io.h>
+#include <linux/sh_eth.h>
#include <mach/sh7763rdp.h>
-#include <asm/sh_eth.h>
#include <asm/sh7760fb.h>
/* NOR Flash */
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
index ba515d800245..e4ea31a62c55 100644
--- a/arch/sh/boot/Makefile
+++ b/arch/sh/boot/Makefile
@@ -19,6 +19,7 @@ CONFIG_MEMORY_START ?= 0x0c000000
CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
CONFIG_ZERO_PAGE_OFFSET ?= 0x00001000
CONFIG_ENTRY_OFFSET ?= 0x00001000
+CONFIG_PHYSICAL_START ?= $(CONFIG_MEMORY_START)
suffix-y := bin
suffix-$(CONFIG_KERNEL_GZIP) := gz
@@ -48,7 +49,7 @@ $(obj)/romimage/vmlinux: $(obj)/zImage FORCE
$(Q)$(MAKE) $(build)=$(obj)/romimage $@
KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
- $$[$(CONFIG_MEMORY_START) & 0x1fffffff]')
+ $$[$(CONFIG_PHYSICAL_START) & 0x1fffffff]')
KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_PAGE_OFFSET) + \
@@ -114,4 +115,5 @@ $(obj)/uImage: $(obj)/uImage.$(suffix-y)
@echo ' Image $@ is ready'
export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
- CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY suffix-y
+ CONFIG_PHYSICAL_START CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET \
+ KERNEL_MEMORY suffix-y
diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c
index af7bb589c2c8..be9ca7ca0ce4 100644
--- a/arch/sh/drivers/dma/dma-g2.c
+++ b/arch/sh/drivers/dma/dma-g2.c
@@ -170,7 +170,7 @@ static int __init g2_dma_init(void)
{
int ret;
- ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, IRQF_DISABLED,
+ ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, 0,
"g2 DMA handler", &g2_dma_info);
if (unlikely(ret))
return -EINVAL;
diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c
index 3cee58e7f1e5..706a3434af7a 100644
--- a/arch/sh/drivers/dma/dma-pvr2.c
+++ b/arch/sh/drivers/dma/dma-pvr2.c
@@ -70,7 +70,6 @@ static int pvr2_xfer_dma(struct dma_channel *chan)
static struct irqaction pvr2_dma_irq = {
.name = "pvr2 DMA handler",
.handler = pvr2_dma_interrupt,
- .flags = IRQF_DISABLED,
};
static struct dma_ops pvr2_dma_ops = {
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index 827208781ed5..a60da6dd4d17 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -95,7 +95,7 @@ static int sh_dmac_request_dma(struct dma_channel *chan)
#if defined(CONFIG_SH_DMA_IRQ_MULTI)
IRQF_SHARED,
#else
- IRQF_DISABLED,
+ 0,
#endif
chan->dev_id, chan);
}
@@ -305,7 +305,7 @@ static int __init sh_dmac_init(void)
#if defined(CONFIG_SH_DMA_IRQ_MULTI)
IRQF_SHARED,
#else
- IRQF_DISABLED,
+ 0,
#endif
dmae_name[n], (void *)dmae_name[n]);
if (unlikely(i < 0)) {
diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c
index 6ab9c4a15439..3d66a32ce610 100644
--- a/arch/sh/drivers/dma/dmabrg.c
+++ b/arch/sh/drivers/dma/dmabrg.c
@@ -174,17 +174,17 @@ static int __init dmabrg_init(void)
or = __raw_readl(DMAOR);
__raw_writel(or | DMAOR_BRG | DMAOR_DMEN, DMAOR);
- ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED,
+ ret = request_irq(DMABRGI0, dmabrg_irq, 0,
"DMABRG USB address error", NULL);
if (ret)
goto out0;
- ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED,
+ ret = request_irq(DMABRGI1, dmabrg_irq, 0,
"DMABRG Transfer End", NULL);
if (ret)
goto out1;
- ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED,
+ ret = request_irq(DMABRGI2, dmabrg_irq, 0,
"DMABRG Transfer Half", NULL);
if (ret == 0)
return ret;
diff --git a/arch/sh/drivers/pci/pci-sh5.c b/arch/sh/drivers/pci/pci-sh5.c
index 0bf296c78795..16c1e721bf54 100644
--- a/arch/sh/drivers/pci/pci-sh5.c
+++ b/arch/sh/drivers/pci/pci-sh5.c
@@ -107,13 +107,13 @@ static int __init sh5pci_init(void)
u32 uval;
if (request_irq(IRQ_ERR, pcish5_err_irq,
- IRQF_DISABLED, "PCI Error",NULL) < 0) {
+ 0, "PCI Error",NULL) < 0) {
printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n");
return -EINVAL;
}
if (request_irq(IRQ_SERR, pcish5_serr_irq,
- IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) {
+ 0, "PCI SERR interrupt", NULL) < 0) {
printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n");
return -EINVAL;
}
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
index edb7cca14882..fa7b978cc727 100644
--- a/arch/sh/drivers/pci/pci-sh7780.c
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -172,7 +172,7 @@ static int __init sh7780_pci_setup_irqs(struct pci_channel *hose)
PCI_STATUS_SIG_TARGET_ABORT | \
PCI_STATUS_PARITY, hose->reg_base + PCI_STATUS);
- ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, IRQF_DISABLED,
+ ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, 0,
"PCI SERR interrupt", hose);
if (unlikely(ret)) {
printk(KERN_ERR "PCI: Failed hooking SERR IRQ\n");
diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c
index afc24556572b..637b79b09657 100644
--- a/arch/sh/drivers/push-switch.c
+++ b/arch/sh/drivers/push-switch.c
@@ -63,7 +63,7 @@ static int switch_drv_probe(struct platform_device *pdev)
BUG_ON(!psw_info);
ret = request_irq(irq, psw_info->irq_handler,
- IRQF_DISABLED | psw_info->irq_flags,
+ psw_info->irq_flags,
psw_info->name ? psw_info->name : DRV_NAME, pdev);
if (unlikely(ret < 0))
goto err;
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h
index 822d6084195b..0dca9a5c6be6 100644
--- a/arch/sh/include/asm/page.h
+++ b/arch/sh/include/asm/page.h
@@ -113,6 +113,16 @@ typedef struct page *pgtable_t;
#define __MEMORY_SIZE CONFIG_MEMORY_SIZE
/*
+ * PHYSICAL_OFFSET is the offset in physical memory where the base
+ * of the kernel is loaded.
+ */
+#ifdef CONFIG_PHYSICAL_START
+#define PHYSICAL_OFFSET (CONFIG_PHYSICAL_START - __MEMORY_START)
+#else
+#define PHYSICAL_OFFSET 0
+#endif
+
+/*
* PAGE_OFFSET is the virtual address of the start of kernel address
* space.
*/
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
index 3b097b09a3ba..19222dae8233 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
@@ -113,7 +113,14 @@ static struct clk_lookup lookups[] = {
/* MSTP32 clocks */
CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]),
- CLKDEV_CON_ID("riic", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic0", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic1", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic2", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic3", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic4", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic5", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic6", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic7", &mstp_clks[MSTP000]),
CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP113]),
CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP114]),
@@ -121,6 +128,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP111]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]),
+ CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]),
CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
};
diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c
index de865cac02ee..03f2b55757cf 100644
--- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c
@@ -79,7 +79,7 @@ static void shx3_prepare_cpus(unsigned int max_cpus)
for (i = 0; i < SMP_MSG_NR; i++)
request_irq(104 + i, ipi_interrupt_handler,
- IRQF_DISABLED | IRQF_PERCPU, "IPI", (void *)(long)i);
+ IRQF_PERCPU, "IPI", (void *)(long)i);
for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true);
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 58bff45d1156..1a0e946679a4 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -211,13 +211,16 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
}
/*
- * We don't know which RAM region contains kernel data,
- * so we try it repeatedly and let the resource manager
- * test it.
+ * We don't know which RAM region contains kernel data or
+ * the reserved crashkernel region, so try it repeatedly
+ * and let the resource manager test it.
*/
request_resource(res, &code_resource);
request_resource(res, &data_resource);
request_resource(res, &bss_resource);
+#ifdef CONFIG_KEXEC
+ request_resource(res, &crashk_res);
+#endif
/*
* Also make sure that there is a PMB mapping that covers this
diff --git a/arch/sh/kernel/topology.c b/arch/sh/kernel/topology.c
index 38e862852dd0..ecc2d3d0f54a 100644
--- a/arch/sh/kernel/topology.c
+++ b/arch/sh/kernel/topology.c
@@ -11,6 +11,7 @@
#include <linux/cpumask.h>
#include <linux/init.h>
#include <linux/percpu.h>
+#include <linux/topology.h>
#include <linux/node.h>
#include <linux/nodemask.h>
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 731c10ce67b5..c98905f71e28 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -23,7 +23,7 @@ OUTPUT_ARCH(sh)
ENTRY(_start)
SECTIONS
{
- . = PAGE_OFFSET + MEMORY_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
+ . = PAGE_OFFSET + MEMORY_OFFSET + PHYSICAL_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
_text = .; /* Text and read-only data */
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 58a93fb3d965..c9dbace35b16 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -287,6 +287,8 @@ static void __init do_init_bootmem(void)
static void __init early_reserve_mem(void)
{
unsigned long start_pfn;
+ u32 zero_base = (u32)__MEMORY_START + (u32)PHYSICAL_OFFSET;
+ u32 start = zero_base + (u32)CONFIG_ZERO_PAGE_OFFSET;
/*
* Partially used pages are not usable - thus
@@ -300,15 +302,13 @@ static void __init early_reserve_mem(void)
* this catches the (definitely buggy) case of us accidentally
* initializing the bootmem allocator with an invalid RAM area.
*/
- memblock_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
- (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) -
- (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
+ memblock_reserve(start, (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - start);
/*
* Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
*/
if (CONFIG_ZERO_PAGE_OFFSET != 0)
- memblock_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET);
+ memblock_reserve(zero_base, CONFIG_ZERO_PAGE_OFFSET);
/*
* Handle additional early reservations
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index 6f57325bb883..b8be20d42a0a 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -134,7 +134,8 @@ struct compat_statfs {
compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_frsize;
- int f_spare[5];
+ int f_flags;
+ int f_spare[4];
};
#define COMPAT_RLIM_INFINITY 0x7fffffff
diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c
index 32b626c9d815..73370674ccff 100644
--- a/arch/sparc/kernel/visemul.c
+++ b/arch/sparc/kernel/visemul.c
@@ -713,17 +713,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
s16 b = (rs2 >> (i * 16)) & 0xffff;
if (a > b)
- rd_val |= 1 << i;
+ rd_val |= 8 >> i;
}
break;
case FCMPGT32_OPF:
for (i = 0; i < 2; i++) {
- s32 a = (rs1 >> (i * 32)) & 0xffff;
- s32 b = (rs2 >> (i * 32)) & 0xffff;
+ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
if (a > b)
- rd_val |= 1 << i;
+ rd_val |= 2 >> i;
}
break;
@@ -733,17 +733,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
s16 b = (rs2 >> (i * 16)) & 0xffff;
if (a <= b)
- rd_val |= 1 << i;
+ rd_val |= 8 >> i;
}
break;
case FCMPLE32_OPF:
for (i = 0; i < 2; i++) {
- s32 a = (rs1 >> (i * 32)) & 0xffff;
- s32 b = (rs2 >> (i * 32)) & 0xffff;
+ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
if (a <= b)
- rd_val |= 1 << i;
+ rd_val |= 2 >> i;
}
break;
@@ -753,17 +753,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
s16 b = (rs2 >> (i * 16)) & 0xffff;
if (a != b)
- rd_val |= 1 << i;
+ rd_val |= 8 >> i;
}
break;
case FCMPNE32_OPF:
for (i = 0; i < 2; i++) {
- s32 a = (rs1 >> (i * 32)) & 0xffff;
- s32 b = (rs2 >> (i * 32)) & 0xffff;
+ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
if (a != b)
- rd_val |= 1 << i;
+ rd_val |= 2 >> i;
}
break;
@@ -773,17 +773,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
s16 b = (rs2 >> (i * 16)) & 0xffff;
if (a == b)
- rd_val |= 1 << i;
+ rd_val |= 8 >> i;
}
break;
case FCMPEQ32_OPF:
for (i = 0; i < 2; i++) {
- s32 a = (rs1 >> (i * 32)) & 0xffff;
- s32 b = (rs2 >> (i * 32)) & 0xffff;
+ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
if (a == b)
- rd_val |= 1 << i;
+ rd_val |= 2 >> i;
}
break;
}
diff --git a/arch/sparc/lib/memcpy.S b/arch/sparc/lib/memcpy.S
index 34fe65751737..4d8c497517bd 100644
--- a/arch/sparc/lib/memcpy.S
+++ b/arch/sparc/lib/memcpy.S
@@ -7,40 +7,12 @@
* Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
-#ifdef __KERNEL__
-
-#define FUNC(x) \
+#define FUNC(x) \
.globl x; \
.type x,@function; \
- .align 4; \
+ .align 4; \
x:
-#undef FASTER_REVERSE
-#undef FASTER_NONALIGNED
-#define FASTER_ALIGNED
-
-/* In kernel these functions don't return a value.
- * One should use macros in asm/string.h for that purpose.
- * We return 0, so that bugs are more apparent.
- */
-#define SETUP_RETL
-#define RETL_INSN clr %o0
-
-#else
-
-/* libc */
-
-#include "DEFS.h"
-
-#define FASTER_REVERSE
-#define FASTER_NONALIGNED
-#define FASTER_ALIGNED
-
-#define SETUP_RETL mov %o0, %g6
-#define RETL_INSN mov %g6, %o0
-
-#endif
-
/* Both these macros have to start with exactly the same insn */
#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
ldd [%src + (offset) + 0x00], %t0; \
@@ -164,30 +136,6 @@ x:
.text
.align 4
-#ifdef FASTER_REVERSE
-
-70: /* rdword_align */
-
- andcc %o1, 1, %g0
- be 4f
- andcc %o1, 2, %g0
-
- ldub [%o1 - 1], %g2
- sub %o1, 1, %o1
- stb %g2, [%o0 - 1]
- sub %o2, 1, %o2
- be 3f
- sub %o0, 1, %o0
-4:
- lduh [%o1 - 2], %g2
- sub %o1, 2, %o1
- sth %g2, [%o0 - 2]
- sub %o2, 2, %o2
- b 3f
- sub %o0, 2, %o0
-
-#endif /* FASTER_REVERSE */
-
0:
retl
nop ! Only bcopy returns here and it retuns void...
@@ -198,7 +146,7 @@ FUNC(__memmove)
#endif
FUNC(memmove)
cmp %o0, %o1
- SETUP_RETL
+ mov %o0, %g7
bleu 9f
sub %o0, %o1, %o4
@@ -207,8 +155,6 @@ FUNC(memmove)
bleu 0f
andcc %o4, 3, %o5
-#ifndef FASTER_REVERSE
-
add %o1, %o2, %o1
add %o0, %o2, %o0
sub %o1, 1, %o1
@@ -224,295 +170,7 @@ FUNC(memmove)
sub %o0, 1, %o0
retl
- RETL_INSN
-
-#else /* FASTER_REVERSE */
-
- add %o1, %o2, %o1
- add %o0, %o2, %o0
- bne 77f
- cmp %o2, 15
- bleu 91f
- andcc %o1, 3, %g0
- bne 70b
-3:
- andcc %o1, 4, %g0
-
- be 2f
- mov %o2, %g1
-
- ld [%o1 - 4], %o4
- sub %g1, 4, %g1
- st %o4, [%o0 - 4]
- sub %o1, 4, %o1
- sub %o0, 4, %o0
-2:
- andcc %g1, 0xffffff80, %g7
- be 3f
- andcc %o0, 4, %g0
-
- be 74f + 4
-5:
- RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
- subcc %g7, 128, %g7
- sub %o1, 128, %o1
- bne 5b
- sub %o0, 128, %o0
-3:
- andcc %g1, 0x70, %g7
- be 72f
- andcc %g1, 8, %g0
-
- sethi %hi(72f), %o5
- srl %g7, 1, %o4
- add %g7, %o4, %o4
- sub %o1, %g7, %o1
- sub %o5, %o4, %o5
- jmpl %o5 + %lo(72f), %g0
- sub %o0, %g7, %o0
-
-71: /* rmemcpy_table */
- RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
-
-72: /* rmemcpy_table_end */
-
- be 73f
- andcc %g1, 4, %g0
-
- ldd [%o1 - 0x08], %g2
- sub %o0, 8, %o0
- sub %o1, 8, %o1
- st %g2, [%o0]
- st %g3, [%o0 + 0x04]
-
-73: /* rmemcpy_last7 */
-
- be 1f
- andcc %g1, 2, %g0
-
- ld [%o1 - 4], %g2
- sub %o1, 4, %o1
- st %g2, [%o0 - 4]
- sub %o0, 4, %o0
-1:
- be 1f
- andcc %g1, 1, %g0
-
- lduh [%o1 - 2], %g2
- sub %o1, 2, %o1
- sth %g2, [%o0 - 2]
- sub %o0, 2, %o0
-1:
- be 1f
- nop
-
- ldub [%o1 - 1], %g2
- stb %g2, [%o0 - 1]
-1:
- retl
- RETL_INSN
-
-74: /* rldd_std */
- RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
- subcc %g7, 128, %g7
- sub %o1, 128, %o1
- bne 74b
- sub %o0, 128, %o0
-
- andcc %g1, 0x70, %g7
- be 72b
- andcc %g1, 8, %g0
-
- sethi %hi(72b), %o5
- srl %g7, 1, %o4
- add %g7, %o4, %o4
- sub %o1, %g7, %o1
- sub %o5, %o4, %o5
- jmpl %o5 + %lo(72b), %g0
- sub %o0, %g7, %o0
-
-75: /* rshort_end */
-
- and %o2, 0xe, %o3
-2:
- sethi %hi(76f), %o5
- sll %o3, 3, %o4
- sub %o0, %o3, %o0
- sub %o5, %o4, %o5
- sub %o1, %o3, %o1
- jmpl %o5 + %lo(76f), %g0
- andcc %o2, 1, %g0
-
- RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
-
-76: /* rshort_table_end */
-
- be 1f
- nop
- ldub [%o1 - 1], %g2
- stb %g2, [%o0 - 1]
-1:
- retl
- RETL_INSN
-
-91: /* rshort_aligned_end */
-
- bne 75b
- andcc %o2, 8, %g0
-
- be 1f
- andcc %o2, 4, %g0
-
- ld [%o1 - 0x08], %g2
- ld [%o1 - 0x04], %g3
- sub %o1, 8, %o1
- st %g2, [%o0 - 0x08]
- st %g3, [%o0 - 0x04]
- sub %o0, 8, %o0
-1:
- b 73b
- mov %o2, %g1
-
-77: /* rnon_aligned */
- cmp %o2, 15
- bleu 75b
- andcc %o0, 3, %g0
- be 64f
- andcc %o0, 1, %g0
- be 63f
- andcc %o0, 2, %g0
- ldub [%o1 - 1], %g5
- sub %o1, 1, %o1
- stb %g5, [%o0 - 1]
- sub %o0, 1, %o0
- be 64f
- sub %o2, 1, %o2
-63:
- ldub [%o1 - 1], %g5
- sub %o1, 2, %o1
- stb %g5, [%o0 - 1]
- sub %o0, 2, %o0
- ldub [%o1], %g5
- sub %o2, 2, %o2
- stb %g5, [%o0]
-64:
- and %o1, 3, %g2
- and %o1, -4, %o1
- and %o2, 0xc, %g3
- add %o1, 4, %o1
- cmp %g3, 4
- sll %g2, 3, %g4
- mov 32, %g2
- be 4f
- sub %g2, %g4, %g7
-
- blu 3f
- cmp %g3, 8
-
- be 2f
- srl %o2, 2, %g3
-
- ld [%o1 - 4], %o3
- add %o0, -8, %o0
- ld [%o1 - 8], %o4
- add %o1, -16, %o1
- b 7f
- add %g3, 1, %g3
-2:
- ld [%o1 - 4], %o4
- add %o0, -4, %o0
- ld [%o1 - 8], %g1
- add %o1, -12, %o1
- b 8f
- add %g3, 2, %g3
-3:
- ld [%o1 - 4], %o5
- add %o0, -12, %o0
- ld [%o1 - 8], %o3
- add %o1, -20, %o1
- b 6f
- srl %o2, 2, %g3
-4:
- ld [%o1 - 4], %g1
- srl %o2, 2, %g3
- ld [%o1 - 8], %o5
- add %o1, -24, %o1
- add %o0, -16, %o0
- add %g3, -1, %g3
-
- ld [%o1 + 12], %o3
-5:
- sll %o5, %g4, %g2
- srl %g1, %g7, %g5
- or %g2, %g5, %g2
- st %g2, [%o0 + 12]
-6:
- ld [%o1 + 8], %o4
- sll %o3, %g4, %g2
- srl %o5, %g7, %g5
- or %g2, %g5, %g2
- st %g2, [%o0 + 8]
-7:
- ld [%o1 + 4], %g1
- sll %o4, %g4, %g2
- srl %o3, %g7, %g5
- or %g2, %g5, %g2
- st %g2, [%o0 + 4]
-8:
- ld [%o1], %o5
- sll %g1, %g4, %g2
- srl %o4, %g7, %g5
- addcc %g3, -4, %g3
- or %g2, %g5, %g2
- add %o1, -16, %o1
- st %g2, [%o0]
- add %o0, -16, %o0
- bne,a 5b
- ld [%o1 + 12], %o3
- sll %o5, %g4, %g2
- srl %g1, %g7, %g5
- srl %g4, 3, %g3
- or %g2, %g5, %g2
- add %o1, %g3, %o1
- andcc %o2, 2, %g0
- st %g2, [%o0 + 12]
- be 1f
- andcc %o2, 1, %g0
-
- ldub [%o1 + 15], %g5
- add %o1, -2, %o1
- stb %g5, [%o0 + 11]
- add %o0, -2, %o0
- ldub [%o1 + 16], %g5
- stb %g5, [%o0 + 12]
-1:
- be 1f
- nop
- ldub [%o1 + 15], %g5
- stb %g5, [%o0 + 11]
-1:
- retl
- RETL_INSN
-
-#endif /* FASTER_REVERSE */
+ mov %g7, %o0
/* NOTE: This code is executed just for the cases,
where %src (=%o1) & 3 is != 0.
@@ -546,7 +204,7 @@ FUNC(memmove)
FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
sub %o0, %o1, %o4
- SETUP_RETL
+ mov %o0, %g7
9:
andcc %o4, 3, %o5
0:
@@ -569,7 +227,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
add %o1, 4, %o1
add %o0, 4, %o0
2:
- andcc %g1, 0xffffff80, %g7
+ andcc %g1, 0xffffff80, %g0
be 3f
andcc %o0, 4, %g0
@@ -579,22 +237,23 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
- subcc %g7, 128, %g7
+ sub %g1, 128, %g1
add %o1, 128, %o1
- bne 5b
+ cmp %g1, 128
+ bge 5b
add %o0, 128, %o0
3:
- andcc %g1, 0x70, %g7
+ andcc %g1, 0x70, %g4
be 80f
andcc %g1, 8, %g0
sethi %hi(80f), %o5
- srl %g7, 1, %o4
- add %g7, %o4, %o4
- add %o1, %g7, %o1
+ srl %g4, 1, %o4
+ add %g4, %o4, %o4
+ add %o1, %g4, %o1
sub %o5, %o4, %o5
jmpl %o5 + %lo(80f), %g0
- add %o0, %g7, %o0
+ add %o0, %g4, %o0
79: /* memcpy_table */
@@ -641,43 +300,28 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
stb %g2, [%o0]
1:
retl
- RETL_INSN
+ mov %g7, %o0
82: /* ldd_std */
MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
- subcc %g7, 128, %g7
+ subcc %g1, 128, %g1
add %o1, 128, %o1
- bne 82b
+ cmp %g1, 128
+ bge 82b
add %o0, 128, %o0
-#ifndef FASTER_ALIGNED
-
- andcc %g1, 0x70, %g7
- be 80b
- andcc %g1, 8, %g0
-
- sethi %hi(80b), %o5
- srl %g7, 1, %o4
- add %g7, %o4, %o4
- add %o1, %g7, %o1
- sub %o5, %o4, %o5
- jmpl %o5 + %lo(80b), %g0
- add %o0, %g7, %o0
-
-#else /* FASTER_ALIGNED */
-
- andcc %g1, 0x70, %g7
+ andcc %g1, 0x70, %g4
be 84f
andcc %g1, 8, %g0
sethi %hi(84f), %o5
- add %o1, %g7, %o1
- sub %o5, %g7, %o5
+ add %o1, %g4, %o1
+ sub %o5, %g4, %o5
jmpl %o5 + %lo(84f), %g0
- add %o0, %g7, %o0
+ add %o0, %g4, %o0
83: /* amemcpy_table */
@@ -721,382 +365,132 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
stb %g2, [%o0]
1:
retl
- RETL_INSN
-
-#endif /* FASTER_ALIGNED */
+ mov %g7, %o0
86: /* non_aligned */
cmp %o2, 6
bleu 88f
+ nop
-#ifdef FASTER_NONALIGNED
-
- cmp %o2, 256
- bcc 87f
-
-#endif /* FASTER_NONALIGNED */
-
- andcc %o0, 3, %g0
+ save %sp, -96, %sp
+ andcc %i0, 3, %g0
be 61f
- andcc %o0, 1, %g0
+ andcc %i0, 1, %g0
be 60f
- andcc %o0, 2, %g0
+ andcc %i0, 2, %g0
- ldub [%o1], %g5
- add %o1, 1, %o1
- stb %g5, [%o0]
- sub %o2, 1, %o2
+ ldub [%i1], %g5
+ add %i1, 1, %i1
+ stb %g5, [%i0]
+ sub %i2, 1, %i2
bne 61f
- add %o0, 1, %o0
+ add %i0, 1, %i0
60:
- ldub [%o1], %g3
- add %o1, 2, %o1
- stb %g3, [%o0]
- sub %o2, 2, %o2
- ldub [%o1 - 1], %g3
- add %o0, 2, %o0
- stb %g3, [%o0 - 1]
+ ldub [%i1], %g3
+ add %i1, 2, %i1
+ stb %g3, [%i0]
+ sub %i2, 2, %i2
+ ldub [%i1 - 1], %g3
+ add %i0, 2, %i0
+ stb %g3, [%i0 - 1]
61:
- and %o1, 3, %g2
- and %o2, 0xc, %g3
- and %o1, -4, %o1
+ and %i1, 3, %g2
+ and %i2, 0xc, %g3
+ and %i1, -4, %i1
cmp %g3, 4
sll %g2, 3, %g4
mov 32, %g2
be 4f
- sub %g2, %g4, %g7
+ sub %g2, %g4, %l0
blu 3f
cmp %g3, 0x8
be 2f
- srl %o2, 2, %g3
+ srl %i2, 2, %g3
- ld [%o1], %o3
- add %o0, -8, %o0
- ld [%o1 + 4], %o4
+ ld [%i1], %i3
+ add %i0, -8, %i0
+ ld [%i1 + 4], %i4
b 8f
add %g3, 1, %g3
2:
- ld [%o1], %o4
- add %o0, -12, %o0
- ld [%o1 + 4], %o5
+ ld [%i1], %i4
+ add %i0, -12, %i0
+ ld [%i1 + 4], %i5
add %g3, 2, %g3
b 9f
- add %o1, -4, %o1
+ add %i1, -4, %i1
3:
- ld [%o1], %g1
- add %o0, -4, %o0
- ld [%o1 + 4], %o3
- srl %o2, 2, %g3
+ ld [%i1], %g1
+ add %i0, -4, %i0
+ ld [%i1 + 4], %i3
+ srl %i2, 2, %g3
b 7f
- add %o1, 4, %o1
+ add %i1, 4, %i1
4:
- ld [%o1], %o5
- cmp %o2, 7
- ld [%o1 + 4], %g1
- srl %o2, 2, %g3
+ ld [%i1], %i5
+ cmp %i2, 7
+ ld [%i1 + 4], %g1
+ srl %i2, 2, %g3
bleu 10f
- add %o1, 8, %o1
+ add %i1, 8, %i1
- ld [%o1], %o3
+ ld [%i1], %i3
add %g3, -1, %g3
5:
- sll %o5, %g4, %g2
- srl %g1, %g7, %g5
+ sll %i5, %g4, %g2
+ srl %g1, %l0, %g5
or %g2, %g5, %g2
- st %g2, [%o0]
+ st %g2, [%i0]
7:
- ld [%o1 + 4], %o4
+ ld [%i1 + 4], %i4
sll %g1, %g4, %g2
- srl %o3, %g7, %g5
+ srl %i3, %l0, %g5
or %g2, %g5, %g2
- st %g2, [%o0 + 4]
+ st %g2, [%i0 + 4]
8:
- ld [%o1 + 8], %o5
- sll %o3, %g4, %g2
- srl %o4, %g7, %g5
+ ld [%i1 + 8], %i5
+ sll %i3, %g4, %g2
+ srl %i4, %l0, %g5
or %g2, %g5, %g2
- st %g2, [%o0 + 8]
+ st %g2, [%i0 + 8]
9:
- ld [%o1 + 12], %g1
- sll %o4, %g4, %g2
- srl %o5, %g7, %g5
+ ld [%i1 + 12], %g1
+ sll %i4, %g4, %g2
+ srl %i5, %l0, %g5
addcc %g3, -4, %g3
or %g2, %g5, %g2
- add %o1, 16, %o1
- st %g2, [%o0 + 12]
- add %o0, 16, %o0
+ add %i1, 16, %i1
+ st %g2, [%i0 + 12]
+ add %i0, 16, %i0
bne,a 5b
- ld [%o1], %o3
+ ld [%i1], %i3
10:
- sll %o5, %g4, %g2
- srl %g1, %g7, %g5
- srl %g7, 3, %g3
+ sll %i5, %g4, %g2
+ srl %g1, %l0, %g5
+ srl %l0, 3, %g3
or %g2, %g5, %g2
- sub %o1, %g3, %o1
- andcc %o2, 2, %g0
- st %g2, [%o0]
+ sub %i1, %g3, %i1
+ andcc %i2, 2, %g0
+ st %g2, [%i0]
be 1f
- andcc %o2, 1, %g0
-
- ldub [%o1], %g2
- add %o1, 2, %o1
- stb %g2, [%o0 + 4]
- add %o0, 2, %o0
- ldub [%o1 - 1], %g2
- stb %g2, [%o0 + 3]
+ andcc %i2, 1, %g0
+
+ ldub [%i1], %g2
+ add %i1, 2, %i1
+ stb %g2, [%i0 + 4]
+ add %i0, 2, %i0
+ ldub [%i1 - 1], %g2
+ stb %g2, [%i0 + 3]
1:
be 1f
nop
- ldub [%o1], %g2
- stb %g2, [%o0 + 4]
-1:
- retl
- RETL_INSN
-
-#ifdef FASTER_NONALIGNED
-
-87: /* faster_nonaligned */
-
- andcc %o1, 3, %g0
- be 3f
- andcc %o1, 1, %g0
-
- be 4f
- andcc %o1, 2, %g0
-
- ldub [%o1], %g2
- add %o1, 1, %o1
- stb %g2, [%o0]
- sub %o2, 1, %o2
- bne 3f
- add %o0, 1, %o0
-4:
- lduh [%o1], %g2
- add %o1, 2, %o1
- srl %g2, 8, %g3
- sub %o2, 2, %o2
- stb %g3, [%o0]
- add %o0, 2, %o0
- stb %g2, [%o0 - 1]
-3:
- andcc %o1, 4, %g0
-
- bne 2f
- cmp %o5, 1
-
- ld [%o1], %o4
- srl %o4, 24, %g2
- stb %g2, [%o0]
- srl %o4, 16, %g3
- stb %g3, [%o0 + 1]
- srl %o4, 8, %g2
- stb %g2, [%o0 + 2]
- sub %o2, 4, %o2
- stb %o4, [%o0 + 3]
- add %o1, 4, %o1
- add %o0, 4, %o0
-2:
- be 33f
- cmp %o5, 2
- be 32f
- sub %o2, 4, %o2
-31:
- ld [%o1], %g2
- add %o1, 4, %o1
- srl %g2, 24, %g3
- and %o0, 7, %g5
- stb %g3, [%o0]
- cmp %g5, 7
- sll %g2, 8, %g1
- add %o0, 4, %o0
- be 41f
- and %o2, 0xffffffc0, %o3
- ld [%o0 - 7], %o4
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 4b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 16, %g2
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 16, %g2
-1:
- st %o4, [%o0 - 7]
- sth %g2, [%o0 - 3]
- srl %g1, 8, %g4
- b 88f
- stb %g4, [%o0 - 1]
-32:
- ld [%o1], %g2
- add %o1, 4, %o1
- srl %g2, 16, %g3
- and %o0, 7, %g5
- sth %g3, [%o0]
- cmp %g5, 6
- sll %g2, 16, %g1
- add %o0, 4, %o0
- be 42f
- and %o2, 0xffffffc0, %o3
- ld [%o0 - 6], %o4
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 4b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 16, %g2
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 16, %g2
-1:
- st %o4, [%o0 - 6]
- b 88f
- sth %g2, [%o0 - 2]
-33:
- ld [%o1], %g2
- sub %o2, 4, %o2
- srl %g2, 24, %g3
- and %o0, 7, %g5
- stb %g3, [%o0]
- cmp %g5, 5
- srl %g2, 8, %g4
- sll %g2, 24, %g1
- sth %g4, [%o0 + 1]
- add %o1, 4, %o1
- be 43f
- and %o2, 0xffffffc0, %o3
-
- ld [%o0 - 1], %o4
- add %o0, 4, %o0
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 4b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 24, %g2
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 24, %g2
-1:
- st %o4, [%o0 - 5]
- b 88f
- stb %g2, [%o0 - 1]
-41:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 41b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 16, %g2
-4:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 16, %g2
+ ldub [%i1], %g2
+ stb %g2, [%i0 + 4]
1:
- sth %g2, [%o0 - 3]
- srl %g1, 8, %g4
- b 88f
- stb %g4, [%o0 - 1]
-43:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 43b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 24, %g2
-4:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 24, %g2
-1:
- stb %g2, [%o0 + 3]
- b 88f
- add %o0, 4, %o0
-42:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 42b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 16, %g2
-4:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 16, %g2
-1:
- sth %g2, [%o0 - 2]
-
- /* Fall through */
-
-#endif /* FASTER_NONALIGNED */
+ ret
+ restore %g7, %g0, %o0
88: /* short_end */
@@ -1127,7 +521,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
stb %g2, [%o0]
1:
retl
- RETL_INSN
+ mov %g7, %o0
90: /* short_aligned_end */
bne 88b
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
index a986b5d05712..42c55df3aec3 100644
--- a/arch/sparc/mm/gup.c
+++ b/arch/sparc/mm/gup.c
@@ -56,6 +56,8 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
put_page(head);
return 0;
}
+ if (head != page)
+ get_huge_page_tail(page);
pages[*nr] = page;
(*nr)++;
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index b30f71ac0d06..70a0de46cd1b 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -46,9 +46,6 @@ config NEED_PER_CPU_PAGE_FIRST_CHUNK
config SYS_SUPPORTS_HUGETLBFS
def_bool y
-config GENERIC_TIME
- def_bool y
-
config GENERIC_CLOCKEVENTS
def_bool y
diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig
index 2ad73fb707b9..dafdbbae1124 100644
--- a/arch/tile/configs/tilegx_defconfig
+++ b/arch/tile/configs/tilegx_defconfig
@@ -11,7 +11,6 @@ CONFIG_HAVE_ARCH_ALLOC_REMAP=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
CONFIG_SYS_SUPPORTS_HUGETLBFS=y
-CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_DEFAULT_MIGRATION_COST=10000000
diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig
index f58dc362b944..6f05f969b564 100644
--- a/arch/tile/configs/tilepro_defconfig
+++ b/arch/tile/configs/tilepro_defconfig
@@ -11,7 +11,6 @@ CONFIG_HAVE_ARCH_ALLOC_REMAP=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
CONFIG_SYS_SUPPORTS_HUGETLBFS=y
-CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_DEFAULT_MIGRATION_COST=10000000
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
index 70dabd1e0652..b9d7c4276682 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -1,5 +1,4 @@
-
-menu "Character Devices"
+menu "UML Character Devices"
config STDERR_CONSOLE
bool "stderr console"
@@ -105,92 +104,6 @@ config SSL_CHAN
this if you expect the UML that you build to be run in environments
which don't have a set of /dev/pty* devices.
-config UNIX98_PTYS
- bool "Unix98 PTY support"
- help
- A pseudo terminal (PTY) is a software device consisting of two
- halves: a master and a slave. The slave device behaves identical to
- a physical terminal; the master device is used by a process to
- read data from and write data to the slave, thereby emulating a
- terminal. Typical programs for the master side are telnet servers
- and xterms.
-
- Linux has traditionally used the BSD-like names /dev/ptyxx for
- masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
- has a number of problems. The GNU C library glibc 2.1 and later,
- however, supports the Unix98 naming standard: in order to acquire a
- pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
- terminal is then made available to the process and the pseudo
- terminal slave can be accessed as /dev/pts/<number>. What was
- traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
- All modern Linux systems use the Unix98 ptys. Say Y unless
- you're on an embedded system and want to conserve memory.
-
-config LEGACY_PTYS
- bool "Legacy (BSD) PTY support"
- default y
- help
- A pseudo terminal (PTY) is a software device consisting of two
- halves: a master and a slave. The slave device behaves identical to
- a physical terminal; the master device is used by a process to
- read data from and write data to the slave, thereby emulating a
- terminal. Typical programs for the master side are telnet servers
- and xterms.
-
- Linux has traditionally used the BSD-like names /dev/ptyxx
- for masters and /dev/ttyxx for slaves of pseudo
- terminals. This scheme has a number of problems, including
- security. This option enables these legacy devices; on most
- systems, it is safe to say N.
-
-config RAW_DRIVER
- tristate "RAW driver (/dev/raw/rawN)"
- depends on BLOCK
- help
- The raw driver permits block devices to be bound to /dev/raw/rawN.
- Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
- See the raw(8) manpage for more details.
-
- Applications should preferably open the device (eg /dev/hda1)
- with the O_DIRECT flag.
-
-config MAX_RAW_DEVS
- int "Maximum number of RAW devices to support (1-8192)"
- depends on RAW_DRIVER
- default "256"
- help
- The maximum number of RAW devices that are supported.
- Default is 256. Increase this number in case you need lots of
- raw devices.
-
-config LEGACY_PTY_COUNT
- int "Maximum number of legacy PTY in use"
- depends on LEGACY_PTYS
- default "256"
- help
- The maximum number of legacy PTYs that can be used at any one time.
- The default is 256, and should be more than enough. Embedded
- systems may want to reduce this to save memory.
-
- When not in use, each legacy PTY occupies 12 bytes on 32-bit
- architectures and 24 bytes on 64-bit architectures.
-
-config WATCHDOG
- bool "Watchdog Timer Support"
-
-config WATCHDOG_NOWAYOUT
- bool "Disable watchdog shutdown on close"
- depends on WATCHDOG
-
-config SOFT_WATCHDOG
- tristate "Software Watchdog"
- depends on WATCHDOG
-
-config UML_WATCHDOG
- tristate "UML watchdog"
- depends on WATCHDOG
-
config UML_SOUND
tristate "Sound support"
help
@@ -211,29 +124,4 @@ config HOSTAUDIO
tristate
default UML_SOUND
-#It is selected elsewhere, so kconfig would warn without this.
-config HW_RANDOM
- tristate
- default n
-
-config UML_RANDOM
- tristate "Hardware random number generator"
- help
- This option enables UML's "hardware" random number generator. It
- attaches itself to the host's /dev/random, supplying as much entropy
- as the host has, rather than the small amount the UML gets from its
- own drivers. It registers itself as a standard hardware random number
- generator, major 10, minor 183, and the canonical device name is
- /dev/hwrng.
- The way to make use of this is to install the rng-tools package
- (check your distro, or download from
- http://sourceforge.net/projects/gkernel/). rngd periodically reads
- /dev/hwrng and injects the entropy into /dev/random.
-
-config MMAPPER
- tristate "iomem emulation driver"
- help
- This driver allows a host file to be used as emulated IO memory inside
- UML.
-
endmenu
diff --git a/arch/um/Kconfig.rest b/arch/um/Kconfig.rest
index 0ccad0ff6d6e..567eb5fc21df 100644
--- a/arch/um/Kconfig.rest
+++ b/arch/um/Kconfig.rest
@@ -2,20 +2,14 @@ source "init/Kconfig"
source "kernel/Kconfig.freezer"
-source "drivers/block/Kconfig"
-
source "arch/um/Kconfig.char"
-source "drivers/base/Kconfig"
+source "drivers/Kconfig"
source "net/Kconfig"
source "arch/um/Kconfig.net"
-source "drivers/net/Kconfig"
-
-source "drivers/connector/Kconfig"
-
source "fs/Kconfig"
source "security/Kconfig"
@@ -24,19 +18,4 @@ source "crypto/Kconfig"
source "lib/Kconfig"
-source "drivers/scsi/Kconfig"
-
-source "drivers/md/Kconfig"
-
-if BROKEN
- source "drivers/mtd/Kconfig"
-endif
-
-source "drivers/leds/Kconfig"
-
-#This is just to shut up some Kconfig warnings, so no prompt.
-config INPUT
- tristate
- default n
-
source "arch/um/Kconfig.debug"
diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um
index b5e675e370c6..70fd690964e4 100644
--- a/arch/um/Kconfig.um
+++ b/arch/um/Kconfig.um
@@ -148,5 +148,11 @@ config KERNEL_STACK_ORDER
be 1 << order pages. The default is OK unless you're running Valgrind
on UML, in which case, set this to 3.
+config MMAPPER
+ tristate "iomem emulation driver"
+ help
+ This driver allows a host file to be used as emulated IO memory inside
+ UML.
+
config NO_DMA
def_bool y
diff --git a/arch/um/Makefile b/arch/um/Makefile
index c0f712cc7c5f..7730af6ec13f 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -20,15 +20,27 @@ core-y += $(ARCH_DIR)/kernel/ \
MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/shared/skas
+HEADER_ARCH := $(SUBARCH)
+
+# Additional ARCH settings for x86
+ifeq ($(SUBARCH),i386)
+ HEADER_ARCH := x86
+endif
+ifeq ($(SUBARCH),x86_64)
+ HEADER_ARCH := x86
+endif
+
+HOST_DIR := arch/$(HEADER_ARCH)
+
include $(srctree)/$(ARCH_DIR)/Makefile-skas
+include $(srctree)/$(HOST_DIR)/Makefile.um
+
+core-y += $(HOST_DIR)/um/
SHARED_HEADERS := $(ARCH_DIR)/include/shared
ARCH_INCLUDE := -I$(srctree)/$(SHARED_HEADERS)
-ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)/shared
-ifneq ($(KBUILD_SRC),)
-ARCH_INCLUDE += -I$(SHARED_HEADERS)
-endif
-KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)
+ARCH_INCLUDE += -I$(srctree)/$(HOST_DIR)/um/shared
+KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um
# -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so
# named - it's a common symbol in libpcap, so we get a binary which crashes.
@@ -47,14 +59,12 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
$(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
- $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64
-
-include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
+ $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 -idirafter include
#This will adjust *FLAGS accordingly to the platform.
include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
-KBUILD_CPPFLAGS += -I$(srctree)/arch/$(HEADER_ARCH)/include
+KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/include
# -Derrno=kernel_errno - This turns all kernel references to errno into
# kernel_errno to separate them from the libc errno. This allows -fno-common
@@ -84,10 +94,9 @@ define archhelp
echo ' find in the kernel root.'
endef
-KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH)
+KBUILD_KCONFIG := $(HOST_DIR)/um/Kconfig
-archprepare: $(SHARED_HEADERS)/user_constants.h
-archprepare: $(SHARED_HEADERS)/kern_constants.h
+archprepare: include/generated/user_constants.h
LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
@@ -118,9 +127,7 @@ endef
# When cleaning we don't include .config, so we don't include
# TT or skas makefiles and don't clean skas_ptregs.h.
-CLEAN_FILES += linux x.i gmon.out \
- $(SHARED_HEADERS)/user_constants.h \
- $(SHARED_HEADERS)/kern_constants.h
+CLEAN_FILES += linux x.i gmon.out
archclean:
@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
@@ -128,8 +135,8 @@ archclean:
# Generated files
-$(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE
- $(Q)$(MAKE) $(build)=$(ARCH_DIR)/sys-$(SUBARCH) $@
+$(HOST_DIR)/um/user-offsets.s: FORCE
+ $(Q)$(MAKE) $(build)=$(HOST_DIR)/um $@
define filechk_gen-asm-offsets
(set -e; \
@@ -144,11 +151,7 @@ define filechk_gen-asm-offsets
echo ""; )
endef
-$(SHARED_HEADERS)/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
+include/generated/user_constants.h: $(HOST_DIR)/um/user-offsets.s
$(call filechk,gen-asm-offsets)
-$(SHARED_HEADERS)/kern_constants.h:
- $(Q)mkdir -p $(dir $@)
- $(Q)echo '#include "../../../../include/generated/asm-offsets.h"' >$@
-
-export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH
+export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS DEV_NULL_PATH
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
deleted file mode 100644
index a9cd7e77a7ab..000000000000
--- a/arch/um/Makefile-x86_64
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2003 - 2004 Pathscale, Inc
-# Released under the GPL
-
-core-y += arch/um/sys-x86_64/ arch/x86/crypto/
-START := 0x60000000
-
-_extra_flags_ = -fno-builtin -m64
-
-KBUILD_CFLAGS += $(_extra_flags_)
-
-CHECKFLAGS += -m64 -D__x86_64__
-KBUILD_AFLAGS += -m64
-LDFLAGS += -m elf_x86_64
-KBUILD_CPPFLAGS += -m64
-
-ELF_ARCH := i386:x86-64
-ELF_FORMAT := elf64-x86-64
-HEADER_ARCH := x86
-
-# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
-
-LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
-LINK-y += -m64
-
-# Do unit-at-a-time unconditionally on x86_64, following the host
-KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 9f7634f08cf3..761f5e1a657e 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -13,7 +13,6 @@ CONFIG_LOCKDEP_SUPPORT=y
# CONFIG_STACKTRACE_SUPPORT is not set
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_BUG=y
-CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_IRQ_RELEASE_METHOD=y
CONFIG_HZ=100
diff --git a/arch/um/include/shared/chan_kern.h b/arch/um/drivers/chan.h
index 1e651457e049..8df0fd9024dc 100644
--- a/arch/um/include/shared/chan_kern.h
+++ b/arch/um/drivers/chan.h
@@ -6,9 +6,9 @@
#ifndef __CHAN_KERN_H__
#define __CHAN_KERN_H__
-#include "linux/tty.h"
-#include "linux/list.h"
-#include "linux/console.h"
+#include <linux/tty.h>
+#include <linux/list.h>
+#include <linux/console.h>
#include "chan_user.h"
#include "line.h"
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index d4191fe1cede..420e2c800799 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -6,7 +6,7 @@
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
-#include "chan_kern.h"
+#include "chan.h"
#include "os.h"
#ifdef CONFIG_NOCONFIG_CHAN
@@ -358,11 +358,11 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
return 0;
}
-static void free_one_chan(struct chan *chan, int delay_free_irq)
+static void free_one_chan(struct chan *chan)
{
list_del(&chan->list);
- close_one_chan(chan, delay_free_irq);
+ close_one_chan(chan, 0);
if (chan->ops->free != NULL)
(*chan->ops->free)(chan->data);
@@ -372,14 +372,14 @@ static void free_one_chan(struct chan *chan, int delay_free_irq)
kfree(chan);
}
-static void free_chan(struct list_head *chans, int delay_free_irq)
+static void free_chan(struct list_head *chans)
{
struct list_head *ele, *next;
struct chan *chan;
list_for_each_safe(ele, next, chans) {
chan = list_entry(ele, struct chan, list);
- free_one_chan(chan, delay_free_irq);
+ free_one_chan(chan);
}
}
@@ -547,7 +547,7 @@ int parse_chan_pair(char *str, struct line *line, int device,
char *in, *out;
if (!list_empty(chans)) {
- free_chan(chans, 0);
+ free_chan(chans);
INIT_LIST_HEAD(chans);
}
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index cfeb3f4a44af..f180813ce2c7 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -11,10 +11,8 @@
#include <termios.h>
#include <sys/ioctl.h>
#include "chan_user.h"
-#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
-#include "user.h"
void generic_close(int fd, void *unused)
{
@@ -283,7 +281,12 @@ void register_winch(int fd, struct tty_struct *tty)
return;
pid = tcgetpgrp(fd);
- if (!is_skas_winch(pid, fd, tty) && (pid == -1)) {
+ if (is_skas_winch(pid, fd, tty)) {
+ register_winch_irq(-1, fd, -1, tty, 0);
+ return;
+ }
+
+ if (pid == -1) {
thread = winch_tramp(fd, tty, &thread_fd, &stack);
if (thread < 0)
return;
diff --git a/arch/um/include/shared/chan_user.h b/arch/um/drivers/chan_user.h
index 9b9ced85b703..9b9ced85b703 100644
--- a/arch/um/include/shared/chan_user.h
+++ b/arch/um/drivers/chan_user.h
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index f5701fd2ef90..7f2ed0b8824a 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -3,7 +3,6 @@
#include "kern_util.h"
#include "os.h"
-#include "user.h"
#include "um_malloc.h"
static inline void *cow_malloc(int size)
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index f8e85e0bdace..a4fd7bc14af7 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -17,7 +17,6 @@
#include "net_user.h"
#include "os.h"
#include "um_malloc.h"
-#include "user.h"
enum request_type { REQ_NEW_CONTROL };
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index f5a981a16240..5b81d2574415 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -9,10 +9,8 @@
#include <errno.h>
#include <termios.h>
#include "chan_user.h"
-#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
-#include "user.h"
struct fd_chan {
int fd;
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index 84dce3fc590c..0345d6206d40 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -7,7 +7,6 @@
#include <unistd.h>
#include <errno.h>
#include "os.h"
-#include "user.h"
struct dog_data {
int stdin;
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 364c8a15c4c3..c1cf2206b84b 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -7,7 +7,7 @@
#include "linux/kd.h"
#include "linux/sched.h"
#include "linux/slab.h"
-#include "chan_kern.h"
+#include "chan.h"
#include "irq_kern.h"
#include "irq_user.h"
#include "kern_util.h"
diff --git a/arch/um/include/shared/line.h b/arch/um/drivers/line.h
index 63df3ca02ac2..63df3ca02ac2 100644
--- a/arch/um/include/shared/line.h
+++ b/arch/um/drivers/line.h
diff --git a/arch/um/include/shared/mconsole.h b/arch/um/drivers/mconsole.h
index c139ae1d6826..c139ae1d6826 100644
--- a/arch/um/include/shared/mconsole.h
+++ b/arch/um/drivers/mconsole.h
diff --git a/arch/um/include/shared/mconsole_kern.h b/arch/um/drivers/mconsole_kern.h
index d2fe07e78958..d2fe07e78958 100644
--- a/arch/um/include/shared/mconsole_kern.h
+++ b/arch/um/drivers/mconsole_kern.h
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index f8cf4c8bedef..99209826adb1 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -10,9 +10,7 @@
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/un.h>
-#include "kern_constants.h"
#include "mconsole.h"
-#include "user.h"
static struct mconsole_command commands[] = {
/*
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 22745b47c829..a492e59883a3 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -368,7 +368,7 @@ static const struct net_device_ops uml_netdev_ops = {
.ndo_open = uml_net_open,
.ndo_stop = uml_net_close,
.ndo_start_xmit = uml_net_start_xmit,
- .ndo_set_multicast_list = uml_net_set_multicast_list,
+ .ndo_set_rx_mode = uml_net_set_multicast_list,
.ndo_tx_timeout = uml_net_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = uml_net_change_mtu,
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 520118888f16..05090c37fa84 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -12,10 +12,8 @@
#include <sys/socket.h>
#include <sys/wait.h>
#include "net_user.h"
-#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
-#include "user.h"
int tap_open_common(void *dev, char *gate_addr)
{
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index 5f903587d69e..702a75b190ee 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -9,9 +9,7 @@
#include <asm/types.h>
#include "net_user.h"
#include "pcap_user.h"
-#include "kern_constants.h"
#include "um_malloc.h"
-#include "user.h"
#define PCAP_FD(p) (*(int *)(p))
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index b49bf56a56aa..7b010b76ddf0 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -10,11 +10,9 @@
#include <unistd.h>
#include <netinet/in.h>
#include "chan_user.h"
-#include "kern_constants.h"
#include "os.h"
#include "port.h"
#include "um_malloc.h"
-#include "user.h"
struct port_chan {
int raw;
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 1113911dcb2b..cff2b75d31fd 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -12,10 +12,8 @@
#include <termios.h>
#include <sys/stat.h>
#include "chan_user.h"
-#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
-#include "user.h"
struct pty_chan {
void (*announce)(char *dev_name, int dev);
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index cbacfc4e63e6..932b4d69bec2 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -11,12 +11,10 @@
#include <string.h>
#include <sys/termios.h>
#include <sys/wait.h>
-#include "kern_constants.h"
#include "net_user.h"
#include "os.h"
#include "slip.h"
#include "um_malloc.h"
-#include "user.h"
static int slip_user_init(void *data, void *dev)
{
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index a0ada8fec72a..db4adb639ff8 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -7,11 +7,9 @@
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
-#include "kern_constants.h"
#include "net_user.h"
#include "os.h"
#include "slirp.h"
-#include "user.h"
static int slirp_user_init(void *data, void *dev)
{
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index f1786e64607f..9d8c20af6f80 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -12,10 +12,8 @@
#include "linux/console.h"
#include "asm/termbits.h"
#include "asm/irq.h"
-#include "line.h"
#include "ssl.h"
-#include "chan_kern.h"
-#include "kern.h"
+#include "chan.h"
#include "init.h"
#include "irq_user.h"
#include "mconsole_kern.h"
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 49266f6108c4..088776f01908 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -20,8 +20,7 @@
#include "asm/current.h"
#include "asm/irq.h"
#include "stdio_console.h"
-#include "line.h"
-#include "chan_kern.h"
+#include "chan.h"
#include "irq_user.h"
#include "mconsole_kern.h"
#include "init.h"
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index 495858a090e4..a97391f9ec54 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -7,10 +7,8 @@
#include <fcntl.h>
#include <termios.h>
#include "chan_user.h"
-#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
-#include "user.h"
struct tty_chan {
char *dev;
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 620f5b70957d..944453a3ec99 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -46,7 +46,6 @@
#include "asm/tlbflush.h"
#include "mem_user.h"
#include "kern_util.h"
-#include "kern.h"
#include "mconsole_kern.h"
#include "init.h"
#include "irq_user.h"
@@ -54,7 +53,6 @@
#include "ubd_user.h"
#include "os.h"
#include "mem.h"
-#include "mem_kern.h"
#include "cow.h"
enum ubd_req { UBD_READ, UBD_WRITE };
@@ -513,8 +511,37 @@ __uml_exitcall(kill_io_thread);
static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
{
char *file;
+ int fd;
+ int err;
+
+ __u32 version;
+ __u32 align;
+ char *backing_file;
+ time_t mtime;
+ unsigned long long size;
+ int sector_size;
+ int bitmap_offset;
+
+ if (ubd_dev->file && ubd_dev->cow.file) {
+ file = ubd_dev->cow.file;
+
+ goto out;
+ }
- file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
+ fd = os_open_file(ubd_dev->file, global_openflags, 0);
+ if (fd < 0)
+ return fd;
+
+ err = read_cow_header(file_reader, &fd, &version, &backing_file, \
+ &mtime, &size, &sector_size, &align, &bitmap_offset);
+ os_close_file(fd);
+
+ if(err == -EINVAL)
+ file = ubd_dev->file;
+ else
+ file = backing_file;
+
+out:
return os_file_size(file, size_out);
}
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index b591bb9c41dd..007b94d97726 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -16,7 +16,6 @@
#include <sys/mman.h>
#include <sys/param.h>
#include "asm/types.h"
-#include "user.h"
#include "ubd_user.h"
#include "os.h"
#include "cow.h"
diff --git a/arch/um/include/shared/ubd_user.h b/arch/um/drivers/ubd_user.h
index 3845051f1b10..3845051f1b10 100644
--- a/arch/um/include/shared/ubd_user.h
+++ b/arch/um/drivers/ubd_user.h
diff --git a/arch/um/drivers/umcast_user.c b/arch/um/drivers/umcast_user.c
index 59c56fd6f52a..010fa2d849ec 100644
--- a/arch/um/drivers/umcast_user.c
+++ b/arch/um/drivers/umcast_user.c
@@ -15,11 +15,9 @@
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
-#include "kern_constants.h"
#include "umcast.h"
#include "net_user.h"
#include "um_malloc.h"
-#include "user.h"
static struct sockaddr_in *new_addr(char *addr, unsigned short port)
{
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c
index c5c43253e6ce..b8c286748d3d 100644
--- a/arch/um/drivers/vde_user.c
+++ b/arch/um/drivers/vde_user.c
@@ -6,10 +6,8 @@
#include <stddef.h>
#include <errno.h>
#include <libvdeplug.h>
-#include "kern_constants.h"
#include "net_user.h"
#include "um_malloc.h"
-#include "user.h"
#include "vde.h"
static int vde_user_init(void *data, void *dev)
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 2e1de5728604..969110e56487 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -11,10 +11,8 @@
#include <string.h>
#include <termios.h>
#include "chan_user.h"
-#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
-#include "user.h"
#include "xterm.h"
struct xterm_chan {
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
new file mode 100644
index 000000000000..451f4517b334
--- /dev/null
+++ b/arch/um/include/asm/Kbuild
@@ -0,0 +1,3 @@
+generic-y += bug.h cputime.h device.h emergency-restart.h futex.h hardirq.h
+generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
+generic-y += ftrace.h
diff --git a/arch/um/include/asm/bug.h b/arch/um/include/asm/bug.h
deleted file mode 100644
index 9e33b864c359..000000000000
--- a/arch/um/include/asm/bug.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_BUG_H
-#define __UM_BUG_H
-
-#include <asm-generic/bug.h>
-
-#endif
diff --git a/arch/um/include/asm/checksum.h b/arch/um/include/asm/checksum.h
deleted file mode 100644
index 5b501361e361..000000000000
--- a/arch/um/include/asm/checksum.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_CHECKSUM_H
-#define __UM_CHECKSUM_H
-
-#include "sysdep/checksum.h"
-
-#endif
diff --git a/arch/um/include/asm/cputime.h b/arch/um/include/asm/cputime.h
deleted file mode 100644
index c84acbadfa2f..000000000000
--- a/arch/um/include/asm/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_CPUTIME_H
-#define __UM_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __UM_CPUTIME_H */
diff --git a/arch/um/include/asm/device.h b/arch/um/include/asm/device.h
deleted file mode 100644
index d8f9872b0e2d..000000000000
--- a/arch/um/include/asm/device.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/um/include/asm/emergency-restart.h b/arch/um/include/asm/emergency-restart.h
deleted file mode 100644
index 108d8c48e42e..000000000000
--- a/arch/um/include/asm/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/um/include/asm/futex.h b/arch/um/include/asm/futex.h
deleted file mode 100644
index 6a332a9f099c..000000000000
--- a/arch/um/include/asm/futex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <asm-generic/futex.h>
-
-#endif
diff --git a/arch/um/include/asm/hardirq.h b/arch/um/include/asm/hardirq.h
deleted file mode 100644
index fb3c05a0cbbf..000000000000
--- a/arch/um/include/asm/hardirq.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hardirq.h>
diff --git a/arch/um/include/asm/hw_irq.h b/arch/um/include/asm/hw_irq.h
deleted file mode 100644
index 1cf84cf5f21a..000000000000
--- a/arch/um/include/asm/hw_irq.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_UM_HW_IRQ_H
-#define _ASM_UM_HW_IRQ_H
-
-#include "asm/irq.h"
-#include "asm/archparam.h"
-
-#endif
diff --git a/arch/um/include/asm/irq_regs.h b/arch/um/include/asm/irq_regs.h
deleted file mode 100644
index 3dd9c0b70270..000000000000
--- a/arch/um/include/asm/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/um/include/asm/irqflags.h b/arch/um/include/asm/irqflags.h
index 659b9abdfdba..c780d8a16773 100644
--- a/arch/um/include/asm/irqflags.h
+++ b/arch/um/include/asm/irqflags.h
@@ -1,6 +1,42 @@
#ifndef __UM_IRQFLAGS_H
#define __UM_IRQFLAGS_H
-/* Empty for now */
+extern int get_signals(void);
+extern int set_signals(int enable);
+extern void block_signals(void);
+extern void unblock_signals(void);
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ return get_signals();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ set_signals(flags);
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ unblock_signals();
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ block_signals();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags;
+ flags = arch_local_save_flags();
+ arch_local_irq_disable();
+ return flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_local_save_flags() == 0;
+}
#endif
diff --git a/arch/um/include/asm/kdebug.h b/arch/um/include/asm/kdebug.h
deleted file mode 100644
index 6ece1b037665..000000000000
--- a/arch/um/include/asm/kdebug.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/um/include/asm/mmu.h b/arch/um/include/asm/mmu.h
index cf259de51531..30509b9f37fd 100644
--- a/arch/um/include/asm/mmu.h
+++ b/arch/um/include/asm/mmu.h
@@ -1,12 +1,24 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#ifndef __MMU_H
-#define __MMU_H
+#ifndef __ARCH_UM_MMU_H
+#define __ARCH_UM_MMU_H
-#include "um_mmu.h"
+#include "mm_id.h"
+#include <asm/mm_context.h>
-#endif
+typedef struct mm_context {
+ struct mm_id id;
+ struct uml_arch_mm_context arch;
+ struct page **stub_pages;
+} mm_context_t;
+
+extern void __switch_mm(struct mm_id * mm_idp);
+/* Avoid tangled inclusion with asm/ldt.h */
+extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
+extern void free_ldt(struct mm_context *mm);
+
+#endif
diff --git a/arch/um/include/asm/mmu_context.h b/arch/um/include/asm/mmu_context.h
index 34d813011b7a..591b3d8d7614 100644
--- a/arch/um/include/asm/mmu_context.h
+++ b/arch/um/include/asm/mmu_context.h
@@ -6,15 +6,12 @@
#ifndef __UM_MMU_CONTEXT_H
#define __UM_MMU_CONTEXT_H
-#include "linux/sched.h"
-#include "um_mmu.h"
+#include <linux/sched.h>
+#include <asm/mmu.h>
extern void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
extern void arch_exit_mmap(struct mm_struct *mm);
-#define get_mmu_context(task) do ; while(0)
-#define activate_context(tsk) do ; while(0)
-
#define deactivate_mm(tsk,mm) do { } while (0)
extern void force_flush_all(void);
diff --git a/arch/um/include/asm/page.h b/arch/um/include/asm/page.h
index 4cc9b6cf480a..7cfc3cedce84 100644
--- a/arch/um/include/asm/page.h
+++ b/arch/um/include/asm/page.h
@@ -19,7 +19,7 @@
struct page;
#include <linux/types.h>
-#include <sysdep/vm-flags.h>
+#include <asm/vm-flags.h>
/*
* These are used to make use of C type-checking..
diff --git a/arch/um/include/asm/page_offset.h b/arch/um/include/asm/page_offset.h
deleted file mode 100644
index 1c168dfbf359..000000000000
--- a/arch/um/include/asm/page_offset.h
+++ /dev/null
@@ -1 +0,0 @@
-#define PAGE_OFFSET_RAW (uml_physmem)
diff --git a/arch/um/include/asm/pda.h b/arch/um/include/asm/pda.h
deleted file mode 100644
index ddcd774fc2a0..000000000000
--- a/arch/um/include/asm/pda.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PDA_X86_64_H
-#define __UM_PDA_X86_64_H
-
-/* XXX */
-struct foo {
- unsigned int __softirq_pending;
- unsigned int __nmi_count;
-};
-
-extern struct foo me;
-
-#define read_pda(me) (&me)
-
-#endif
-
diff --git a/arch/um/include/asm/percpu.h b/arch/um/include/asm/percpu.h
deleted file mode 100644
index efe7508d8abd..000000000000
--- a/arch/um/include/asm/percpu.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_PERCPU_H
-#define __UM_PERCPU_H
-
-#include <asm-generic/percpu.h>
-
-#endif /* __UM_PERCPU_H */
diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h
index 1a7d2757fe05..f605d3c4844c 100644
--- a/arch/um/include/asm/ptrace-generic.h
+++ b/arch/um/include/asm/ptrace-generic.h
@@ -23,17 +23,10 @@ struct pt_regs {
#define PT_REGS_IP(r) UPT_IP(&(r)->regs)
#define PT_REGS_SP(r) UPT_SP(&(r)->regs)
-#define PT_REG(r, reg) UPT_REG(&(r)->regs, reg)
-#define PT_REGS_SET(r, reg, val) UPT_SET(&(r)->regs, reg, val)
-
-#define PT_REGS_SET_SYSCALL_RETURN(r, res) \
- UPT_SET_SYSCALL_RETURN(&(r)->regs, res)
#define PT_REGS_RESTART_SYSCALL(r) UPT_RESTART_SYSCALL(&(r)->regs)
#define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs)
-#define PT_REGS_SC(r) UPT_SC(&(r)->regs)
-
#define instruction_pointer(regs) PT_REGS_IP(regs)
struct task_struct;
diff --git a/arch/um/include/asm/sections.h b/arch/um/include/asm/sections.h
deleted file mode 100644
index 6b0231eefea8..000000000000
--- a/arch/um/include/asm/sections.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _UM_SECTIONS_H
-#define _UM_SECTIONS_H
-
-/* nothing to see, move along */
-#include <asm-generic/sections.h>
-
-#endif
diff --git a/arch/um/include/asm/system.h b/arch/um/include/asm/system.h
deleted file mode 100644
index 68a90ecd1450..000000000000
--- a/arch/um/include/asm/system.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef __UM_SYSTEM_GENERIC_H
-#define __UM_SYSTEM_GENERIC_H
-
-#include "sysdep/system.h"
-
-extern int get_signals(void);
-extern int set_signals(int enable);
-extern void block_signals(void);
-extern void unblock_signals(void);
-
-static inline unsigned long arch_local_save_flags(void)
-{
- return get_signals();
-}
-
-static inline void arch_local_irq_restore(unsigned long flags)
-{
- set_signals(flags);
-}
-
-static inline void arch_local_irq_enable(void)
-{
- unblock_signals();
-}
-
-static inline void arch_local_irq_disable(void)
-{
- block_signals();
-}
-
-static inline unsigned long arch_local_irq_save(void)
-{
- unsigned long flags;
- flags = arch_local_save_flags();
- arch_local_irq_disable();
- return flags;
-}
-
-static inline bool arch_irqs_disabled(void)
-{
- return arch_local_save_flags() == 0;
-}
-
-extern void *_switch_to(void *prev, void *next, void *last);
-#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
-
-#endif
diff --git a/arch/um/include/asm/topology.h b/arch/um/include/asm/topology.h
deleted file mode 100644
index 0905e4f21d42..000000000000
--- a/arch/um/include/asm/topology.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_UM_TOPOLOGY_H
-#define _ASM_UM_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif
diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h
index b9a895d6fa1d..3f22fbf7ca1d 100644
--- a/arch/um/include/asm/uaccess.h
+++ b/arch/um/include/asm/uaccess.h
@@ -6,15 +6,15 @@
#ifndef __UM_UACCESS_H
#define __UM_UACCESS_H
-#include <asm/errno.h>
-#include <asm/processor.h>
-
/* thread_info has a mm_segment_t in it, so put the definition up here */
typedef struct {
unsigned long seg;
} mm_segment_t;
-#include "linux/thread_info.h"
+#include <linux/thread_info.h>
+#include <linux/errno.h>
+#include <asm/processor.h>
+#include <asm/elf.h>
#define VERIFY_READ 0
#define VERIFY_WRITE 1
@@ -38,7 +38,86 @@ typedef struct {
#define segment_eq(a, b) ((a).seg == (b).seg)
-#include "um_uaccess.h"
+#define __under_task_size(addr, size) \
+ (((unsigned long) (addr) < TASK_SIZE) && \
+ (((unsigned long) (addr) + (size)) < TASK_SIZE))
+
+#define __access_ok_vsyscall(type, addr, size) \
+ ((type == VERIFY_READ) && \
+ ((unsigned long) (addr) >= FIXADDR_USER_START) && \
+ ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
+ ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))
+
+#define __addr_range_nowrap(addr, size) \
+ ((unsigned long) (addr) <= ((unsigned long) (addr) + (size)))
+
+#define access_ok(type, addr, size) \
+ (__addr_range_nowrap(addr, size) && \
+ (__under_task_size(addr, size) || \
+ __access_ok_vsyscall(type, addr, size) || \
+ segment_eq(get_fs(), KERNEL_DS)))
+
+extern int copy_from_user(void *to, const void __user *from, int n);
+extern int copy_to_user(void __user *to, const void *from, int n);
+
+/*
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst: Destination address, in kernel space. This buffer must be at
+ * least @count bytes long.
+ * @src: Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+
+extern int strncpy_from_user(char *dst, const char __user *src, int count);
+
+/*
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to: Destination address, in user space.
+ * @n: Number of bytes to zero.
+ *
+ * Zero a block of memory in user space. Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+extern int __clear_user(void __user *mem, int len);
+
+/*
+ * clear_user: - Zero a block of memory in user space.
+ * @to: Destination address, in user space.
+ * @n: Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+extern int clear_user(void __user *mem, int len);
+
+/*
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ * @n: The maximum valid length
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than @n.
+ */
+extern int strnlen_user(const void __user *str, int len);
#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
diff --git a/arch/um/include/asm/xor.h b/arch/um/include/asm/xor.h
deleted file mode 100644
index a19db3e17241..000000000000
--- a/arch/um/include/asm/xor.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_XOR_H
-#define __UM_XOR_H
-
-#include "asm-generic/xor.h"
-
-#endif
diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h
index a92b678503cf..896e16602176 100644
--- a/arch/um/include/shared/as-layout.h
+++ b/arch/um/include/shared/as-layout.h
@@ -6,7 +6,7 @@
#ifndef __START_H__
#define __START_H__
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
/*
* Stolen from linux/const.h, which can't be directly included since
diff --git a/arch/um/include/shared/common-offsets.h b/arch/um/include/shared/common-offsets.h
index 72009c7e3210..d7fe563aa7e7 100644
--- a/arch/um/include/shared/common-offsets.h
+++ b/arch/um/include/shared/common-offsets.h
@@ -2,7 +2,6 @@
DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
-OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
OFFSET(HOST_TASK_PID, task_struct, pid);
DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
diff --git a/arch/um/include/shared/initrd.h b/arch/um/include/shared/initrd.h
deleted file mode 100644
index 22673bcc273d..000000000000
--- a/arch/um/include/shared/initrd.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __INITRD_USER_H__
-#define __INITRD_USER_H__
-
-extern int load_initrd(char *filename, void *buf, int size);
-
-#endif
-
diff --git a/arch/um/include/shared/kern.h b/arch/um/include/shared/kern.h
index 4ce3fc650e57..6cd01240bbf0 100644
--- a/arch/um/include/shared/kern.h
+++ b/arch/um/include/shared/kern.h
@@ -13,28 +13,10 @@
* includes.
*/
-extern int errno;
-
-extern int clone(int (*proc)(void *), void *sp, int flags, void *data);
-extern int sleep(int);
extern int printf(const char *fmt, ...);
-extern char *strerror(int errnum);
-extern char *ptsname(int __fd);
-extern int munmap(void *, int);
extern void *sbrk(int increment);
-extern void *malloc(int size);
-extern void perror(char *err);
-extern int kill(int pid, int sig);
-extern int getuid(void);
-extern int getgid(void);
extern int pause(void);
-extern int write(int, const void *, int);
extern void exit(int);
-extern int close(int);
-extern int read(unsigned int, char *, int);
-extern int pipe(int *);
-extern int sched_yield(void);
-extern int ptrace(int op, int pid, long addr, long data);
#endif
diff --git a/arch/um/include/shared/kern_util.h b/arch/um/include/shared/kern_util.h
index 3c341222d252..0f1483852460 100644
--- a/arch/um/include/shared/kern_util.h
+++ b/arch/um/include/shared/kern_util.h
@@ -21,7 +21,6 @@ extern unsigned long alloc_stack(int order, int atomic);
extern void free_stack(unsigned long stack, int order);
extern int do_signal(void);
-extern void copy_sc(struct uml_pt_regs *regs, void *from);
extern void interrupt_end(void);
extern void relay_signal(int sig, struct uml_pt_regs *regs);
diff --git a/arch/um/include/shared/ldt.h b/arch/um/include/shared/ldt.h
deleted file mode 100644
index a7f999a58774..000000000000
--- a/arch/um/include/shared/ldt.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Licensed under the GPL
- *
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- */
-
-#ifndef __ASM_LDT_H
-#define __ASM_LDT_H
-
-#include <linux/mutex.h>
-#include <sysdep/host_ldt.h>
-
-extern void ldt_host_info(void);
-
-#define LDT_PAGES_MAX \
- ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
-#define LDT_ENTRIES_PER_PAGE \
- (PAGE_SIZE/LDT_ENTRY_SIZE)
-#define LDT_DIRECT_ENTRIES \
- ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
-
-struct ldt_entry {
- __u32 a;
- __u32 b;
-};
-
-typedef struct uml_ldt {
- int entry_count;
- struct mutex lock;
- union {
- struct ldt_entry * pages[LDT_PAGES_MAX];
- struct ldt_entry entries[LDT_DIRECT_ENTRIES];
- } u;
-} uml_ldt_t;
-
-#endif
diff --git a/arch/um/include/shared/mem_kern.h b/arch/um/include/shared/mem_kern.h
deleted file mode 100644
index 69be0fd0ce4b..000000000000
--- a/arch/um/include/shared/mem_kern.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __MEM_KERN_H__
-#define __MEM_KERN_H__
-
-#include "linux/list.h"
-#include "linux/types.h"
-
-struct remapper {
- struct list_head list;
- int (*proc)(int, unsigned long, int, __u64);
-};
-
-extern void register_remapper(struct remapper *info);
-
-#endif
-
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 83c7c2ecd614..89b686c1a3ea 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -10,7 +10,6 @@
#include "irq_user.h"
#include "longjmp.h"
#include "mm_id.h"
-#include "sysdep/tls.h"
#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
@@ -203,12 +202,6 @@ extern int os_drop_memory(void *addr, int length);
extern int can_drop_memory(void);
extern void os_flush_stdout(void);
-/* uaccess.c */
-extern unsigned long __do_user_copy(void *to, const void *from, int n,
- void **fault_addr, jmp_buf **fault_catcher,
- void (*op)(void *to, const void *from,
- int n), int *faulted_out);
-
/* execvp.c */
extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
/* helper.c */
@@ -218,10 +211,6 @@ extern int run_helper_thread(int (*proc)(void *), void *arg,
extern int helper_wait(int pid);
-/* tls.c */
-extern int os_set_thread_area(user_desc_t *info, int pid);
-extern int os_get_thread_area(user_desc_t *info, int pid);
-
/* umid.c */
extern int umid_file_name(char *name, char *buf, int len);
extern int set_umid(char *name);
@@ -231,7 +220,7 @@ extern char *get_umid(void);
extern void timer_init(void);
extern void set_sigstack(void *sig_stack, int size);
extern void remove_sigstack(void);
-extern void set_handler(int sig, void (*handler)(int), int flags, ...);
+extern void set_handler(int sig);
extern int change_sig(int signal, int on);
extern void block_signals(void);
extern void unblock_signals(void);
diff --git a/arch/um/include/shared/process.h b/arch/um/include/shared/process.h
deleted file mode 100644
index bb873a51262e..000000000000
--- a/arch/um/include/shared/process.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __PROCESS_H__
-#define __PROCESS_H__
-
-#include <signal.h>
-
-/* Copied from linux/compiler-gcc.h since we can't include it directly */
-#define barrier() __asm__ __volatile__("": : :"memory")
-
-extern void sig_handler(int sig, struct sigcontext *sc);
-extern void alarm_handler(int sig, struct sigcontext *sc);
-
-#endif
diff --git a/arch/um/include/shared/ptrace_user.h b/arch/um/include/shared/ptrace_user.h
index 7fd8539bc19a..56b2f284b108 100644
--- a/arch/um/include/shared/ptrace_user.h
+++ b/arch/um/include/shared/ptrace_user.h
@@ -6,7 +6,8 @@
#ifndef __PTRACE_USER_H__
#define __PTRACE_USER_H__
-#include "sysdep/ptrace_user.h"
+#include <sys/ptrace.h>
+#include <sysdep/ptrace_user.h>
extern int ptrace_getregs(long pid, unsigned long *regs_out);
extern int ptrace_setregs(long pid, unsigned long *regs_in);
diff --git a/arch/um/include/shared/skas_ptregs.h b/arch/um/include/shared/skas_ptregs.h
deleted file mode 100644
index 73db19e9c077..000000000000
--- a/arch/um/include/shared/skas_ptregs.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SKAS_PT_REGS_
-#define __SKAS_PT_REGS_
-
-#include <user_constants.h>
-
-#endif
diff --git a/arch/um/include/shared/syscall.h b/arch/um/include/shared/syscall.h
deleted file mode 100644
index dda1df901a08..000000000000
--- a/arch/um/include/shared/syscall.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSCALL_USER_H
-#define __SYSCALL_USER_H
-
-extern int record_syscall_start(int syscall);
-extern void record_syscall_end(int index, long result);
-
-#endif
diff --git a/arch/um/include/shared/task.h b/arch/um/include/shared/task.h
deleted file mode 100644
index 3fe726b3cf48..000000000000
--- a/arch/um/include/shared/task.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __TASK_H
-#define __TASK_H
-
-#include <kern_constants.h>
-
-#define TASK_REGS(task) ((struct uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS]))
-#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
-
-#endif
diff --git a/arch/um/include/shared/tlb.h b/arch/um/include/shared/tlb.h
deleted file mode 100644
index ecd2265b301b..000000000000
--- a/arch/um/include/shared/tlb.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TLB_H__
-#define __TLB_H__
-
-#include "um_mmu.h"
-
-extern void force_flush_all(void);
-extern int flush_tlb_kernel_range_common(unsigned long start,
- unsigned long end);
-
-#endif
diff --git a/arch/um/include/shared/um_malloc.h b/arch/um/include/shared/um_malloc.h
index c554d706d106..6395fef6b69b 100644
--- a/arch/um/include/shared/um_malloc.h
+++ b/arch/um/include/shared/um_malloc.h
@@ -6,7 +6,7 @@
#ifndef __UM_MALLOC_H__
#define __UM_MALLOC_H__
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
extern void *uml_kmalloc(int size, int flags);
extern void kfree(const void *ptr);
diff --git a/arch/um/include/shared/um_mmu.h b/arch/um/include/shared/um_mmu.h
deleted file mode 100644
index b1a7e47d1027..000000000000
--- a/arch/um/include/shared/um_mmu.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __ARCH_UM_MMU_H
-#define __ARCH_UM_MMU_H
-
-#include "mm_id.h"
-#include "ldt.h"
-
-typedef struct mm_context {
- struct mm_id id;
- struct uml_ldt ldt;
- struct page **stub_pages;
-} mm_context_t;
-
-extern void __switch_mm(struct mm_id * mm_idp);
-
-/* Avoid tangled inclusion with asm/ldt.h */
-extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
-extern void free_ldt(struct mm_context *mm);
-
-#endif
diff --git a/arch/um/include/shared/um_uaccess.h b/arch/um/include/shared/um_uaccess.h
deleted file mode 100644
index 45c04999d670..000000000000
--- a/arch/um/include/shared/um_uaccess.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __ARCH_UM_UACCESS_H
-#define __ARCH_UM_UACCESS_H
-
-#include <asm/elf.h>
-#include <asm/fixmap.h>
-#include "sysdep/archsetjmp.h"
-
-#define __under_task_size(addr, size) \
- (((unsigned long) (addr) < TASK_SIZE) && \
- (((unsigned long) (addr) + (size)) < TASK_SIZE))
-
-#define __access_ok_vsyscall(type, addr, size) \
- ((type == VERIFY_READ) && \
- ((unsigned long) (addr) >= FIXADDR_USER_START) && \
- ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
- ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))
-
-#define __addr_range_nowrap(addr, size) \
- ((unsigned long) (addr) <= ((unsigned long) (addr) + (size)))
-
-#define access_ok(type, addr, size) \
- (__addr_range_nowrap(addr, size) && \
- (__under_task_size(addr, size) || \
- __access_ok_vsyscall(type, addr, size) || \
- segment_eq(get_fs(), KERNEL_DS)))
-
-extern int copy_from_user(void *to, const void __user *from, int n);
-extern int copy_to_user(void __user *to, const void *from, int n);
-
-extern int __do_copy_to_user(void *to, const void *from, int n,
- void **fault_addr, jmp_buf **fault_catcher);
-
-/*
- * strncpy_from_user: - Copy a NUL terminated string from userspace.
- * @dst: Destination address, in kernel space. This buffer must be at
- * least @count bytes long.
- * @src: Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
-
-extern int strncpy_from_user(char *dst, const char __user *src, int count);
-
-/*
- * __clear_user: - Zero a block of memory in user space, with less checking.
- * @to: Destination address, in user space.
- * @n: Number of bytes to zero.
- *
- * Zero a block of memory in user space. Caller must check
- * the specified block with access_ok() before calling this function.
- *
- * Returns number of bytes that could not be cleared.
- * On success, this will be zero.
- */
-extern int __clear_user(void __user *mem, int len);
-
-/*
- * clear_user: - Zero a block of memory in user space.
- * @to: Destination address, in user space.
- * @n: Number of bytes to zero.
- *
- * Zero a block of memory in user space.
- *
- * Returns number of bytes that could not be cleared.
- * On success, this will be zero.
- */
-extern int clear_user(void __user *mem, int len);
-
-/*
- * strlen_user: - Get the size of a string in user space.
- * @str: The string to measure.
- * @n: The maximum valid length
- *
- * Get the size of a NUL-terminated string in user space.
- *
- * Returns the size of the string INCLUDING the terminating NUL.
- * On exception, returns 0.
- * If the string is too long, returns a value greater than @n.
- */
-extern int strnlen_user(const void __user *str, int len);
-
-#endif
diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h
index 293f7c794faa..4fa82c055aab 100644
--- a/arch/um/include/shared/user.h
+++ b/arch/um/include/shared/user.h
@@ -6,7 +6,7 @@
#ifndef __USER_H__
#define __USER_H__
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
/*
* The usual definition - copied here because the kernel provides its own,
@@ -36,10 +36,11 @@ static inline int printk(const char *fmt, ...)
}
#endif
-extern void schedule(void);
extern int in_aton(char *str);
-extern int open_gdb_chan(void);
extern size_t strlcpy(char *, const char *, size_t);
extern size_t strlcat(char *, const char *, size_t);
+/* Copied from linux/compiler-gcc.h since we can't include it directly */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
#endif
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index c4491c15afb2..bc494741b1f3 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -11,7 +11,7 @@ clean-files :=
obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
physmem.o process.o ptrace.o reboot.o sigio.o \
- signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
+ signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
um_arch.o umid.o skas/
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 939a4a67f0fd..6cade9366364 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -3,14 +3,15 @@
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/fs.h"
-#include "linux/ptrace.h"
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "asm/current.h"
-#include "asm/processor.h"
-#include "asm/uaccess.h"
+#include <linux/stddef.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/current.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
#include "as-layout.h"
#include "mem_user.h"
#include "skas.h"
@@ -41,6 +42,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
PT_REGS_IP(regs) = eip;
PT_REGS_SP(regs) = esp;
}
+EXPORT_SYMBOL(start_thread);
static long execve1(const char *file,
const char __user *const __user *argv,
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 72eccd2a4113..e9bcf247bcee 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -7,18 +7,3 @@
extern void __bb_init_func(void *) __attribute__((weak));
EXPORT_SYMBOL(__bb_init_func);
-
-/*
- * This is defined (and referred to in profiling stub code) only by some GCC
- * versions in libgcov.
- *
- * Since SuSE backported the fix, we cannot handle it depending on GCC version.
- * So, unconditionally export it. But also give it a weak declaration, which
- * will be overridden by any other one.
- */
-
-extern void __gcov_init(void *) __attribute__((weak));
-EXPORT_SYMBOL(__gcov_init);
-
-extern void __gcov_merge_add(void *) __attribute__((weak));
-EXPORT_SYMBOL(__gcov_merge_add);
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index d386c75c88eb..10cc18f729fd 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -7,12 +7,12 @@
#include "linux/bootmem.h"
#include "linux/initrd.h"
#include "asm/types.h"
-#include "initrd.h"
#include "init.h"
#include "os.h"
/* Changed by uml_initrd_setup, which is a setup */
static char *initrd __initdata = NULL;
+static int load_initrd(char *filename, void *buf, int size);
static int __init read_initrd(void)
{
@@ -62,7 +62,7 @@ __uml_setup("initrd=", uml_initrd_setup,
" name of the file containing the image.\n\n"
);
-int load_initrd(char *filename, void *buf, int size)
+static int load_initrd(char *filename, void *buf, int size)
{
int fd, n;
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 9e485c770308..71b8c947e5ef 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -258,6 +258,7 @@ void deactivate_fd(int fd, int irqnum)
ignore_sigio_fd(fd);
}
+EXPORT_SYMBOL(deactivate_fd);
/*
* Called just before shutdown in order to provide a clean exec
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 0ae0dfcfbffb..e17bea0b22e1 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -3,33 +3,11 @@
* Licensed under the GPL
*/
-#include "linux/module.h"
-#include "linux/syscalls.h"
-#include "asm/tlbflush.h"
-#include "asm/uaccess.h"
-#include "as-layout.h"
-#include "kern_util.h"
-#include "mem_user.h"
+#include <linux/module.h>
#include "os.h"
-EXPORT_SYMBOL(uml_physmem);
EXPORT_SYMBOL(set_signals);
EXPORT_SYMBOL(get_signals);
-EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(sys_waitpid);
-EXPORT_SYMBOL(flush_tlb_range);
-
-EXPORT_SYMBOL(high_physmem);
-EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(handle_page_fault);
-EXPORT_SYMBOL(find_iomem);
-
-EXPORT_SYMBOL(strnlen_user);
-EXPORT_SYMBOL(strncpy_from_user);
-EXPORT_SYMBOL(copy_to_user);
-EXPORT_SYMBOL(copy_from_user);
-EXPORT_SYMBOL(clear_user);
-EXPORT_SYMBOL(uml_strdup);
EXPORT_SYMBOL(os_stat_fd);
EXPORT_SYMBOL(os_stat_file);
@@ -57,24 +35,10 @@ EXPORT_SYMBOL(os_connect_socket);
EXPORT_SYMBOL(os_accept_connection);
EXPORT_SYMBOL(os_rcv_fd);
EXPORT_SYMBOL(run_helper);
-EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(os_major);
EXPORT_SYMBOL(os_minor);
EXPORT_SYMBOL(os_makedev);
EXPORT_SYMBOL(add_sigio_fd);
EXPORT_SYMBOL(ignore_sigio_fd);
-EXPORT_SYMBOL(deactivate_fd);
EXPORT_SYMBOL(sigio_broken);
-
-#ifdef CONFIG_SMP
-
-/* required for SMP */
-
-extern void __write_lock_failed(rwlock_t *rw);
-EXPORT_SYMBOL(__write_lock_failed);
-
-extern void __read_lock_failed(rwlock_t *rw);
-EXPORT_SYMBOL(__read_lock_failed);
-
-#endif
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 8137ccc9635b..ebb86b218445 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -4,6 +4,7 @@
*/
#include <linux/stddef.h>
+#include <linux/module.h>
#include <linux/bootmem.h>
#include <linux/highmem.h>
#include <linux/mm.h>
@@ -20,6 +21,7 @@
/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
unsigned long *empty_zero_page = NULL;
+EXPORT_SYMBOL(empty_zero_page);
/* allocated in paging_init and unchanged thereafter */
static unsigned long *empty_bad_page = NULL;
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index a1a9090254c2..f116db15d402 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -3,20 +3,22 @@
* Licensed under the GPL
*/
-#include "linux/bootmem.h"
-#include "linux/mm.h"
-#include "linux/pfn.h"
-#include "asm/page.h"
-#include "as-layout.h"
-#include "init.h"
-#include "kern.h"
-#include "mem_user.h"
-#include "os.h"
+#include <linux/module.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/pfn.h>
+#include <asm/page.h>
+#include <as-layout.h>
+#include <init.h>
+#include <kern.h>
+#include <mem_user.h>
+#include <os.h>
static int physmem_fd = -1;
/* Changed during early boot */
unsigned long high_physmem;
+EXPORT_SYMBOL(high_physmem);
extern unsigned long long physmem_size;
@@ -184,6 +186,7 @@ unsigned long find_iomem(char *driver, unsigned long *len_out)
return 0;
}
+EXPORT_SYMBOL(find_iomem);
static int setup_iomem(void)
{
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 21c1ae7c3d75..c5338351aecd 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -20,12 +20,12 @@
#include <linux/threads.h>
#include <asm/current.h>
#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
#include <asm/uaccess.h>
#include "as-layout.h"
#include "kern_util.h"
#include "os.h"
#include "skas.h"
-#include "tlb.h"
/*
* This is a per-cpu array. A processor only modifies its entry and it only
@@ -78,6 +78,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
&current->thread.regs, 0, NULL, NULL);
return pid;
}
+EXPORT_SYMBOL(kernel_thread);
static inline void set_current(struct task_struct *task)
{
@@ -286,6 +287,7 @@ char *uml_strdup(const char *string)
{
return kstrdup(string, GFP_KERNEL);
}
+EXPORT_SYMBOL(uml_strdup);
int copy_to_user_proc(void __user *to, void *from, int size)
{
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index b5c094c4ade4..e8b889d3bce7 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -11,7 +11,6 @@
#include <asm/unistd.h>
#include "frame_kern.h"
#include "kern_util.h"
-#include <sysdep/sigcontext.h>
EXPORT_SYMBOL(block_signals);
EXPORT_SYMBOL(unblock_signals);
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index 2c8583c1a344..e1fd066a3525 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -8,7 +8,6 @@
#include <asm/unistd.h>
#include <sys/time.h>
#include "as-layout.h"
-#include "kern_constants.h"
#include "ptrace_user.h"
#include "stub-data.h"
#include "sysdep/stub.h"
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 696634214dc6..9fefd924fb49 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -6,6 +6,7 @@
#include <linux/err.h>
#include <linux/highmem.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <asm/current.h>
#include <asm/page.h>
@@ -149,6 +150,7 @@ int copy_from_user(void *to, const void __user *from, int n)
buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
n;
}
+EXPORT_SYMBOL(copy_from_user);
static int copy_chunk_to_user(unsigned long to, int len, void *arg)
{
@@ -170,6 +172,7 @@ int copy_to_user(void __user *to, const void *from, int n)
buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
n;
}
+EXPORT_SYMBOL(copy_to_user);
static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
{
@@ -204,6 +207,7 @@ int strncpy_from_user(char *dst, const char __user *src, int count)
return -EFAULT;
return strnlen(dst, count);
}
+EXPORT_SYMBOL(strncpy_from_user);
static int clear_chunk(unsigned long addr, int len, void *unused)
{
@@ -226,6 +230,7 @@ int clear_user(void __user *mem, int len)
return access_ok(VERIFY_WRITE, mem, len) ?
buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len;
}
+EXPORT_SYMBOL(clear_user);
static int strnlen_chunk(unsigned long str, int len, void *arg)
{
@@ -251,3 +256,4 @@ int strnlen_user(const void __user *str, int len)
return count + 1;
return -EFAULT;
}
+EXPORT_SYMBOL(strnlen_user);
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index d175d0566af0..7f3d4d86431a 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -4,6 +4,7 @@
*/
#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
@@ -11,7 +12,6 @@
#include "mem_user.h"
#include "os.h"
#include "skas.h"
-#include "tlb.h"
struct host_vm_change {
struct host_vm_op {
@@ -287,7 +287,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
}
}
-int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
+static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
{
struct mm_struct *mm;
pgd_t *pgd;
@@ -499,6 +499,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
flush_tlb_kernel_range_common(start, end);
else fix_range(vma->vm_mm, start, end, 0);
}
+EXPORT_SYMBOL(flush_tlb_range);
void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
unsigned long end)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 8c7b8823d1f0..dafc94715950 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -6,6 +6,7 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/hardirq.h>
+#include <linux/module.h>
#include <asm/current.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
@@ -14,7 +15,6 @@
#include "kern_util.h"
#include "os.h"
#include "skas.h"
-#include "sysdep/sigcontext.h"
/*
* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by
@@ -112,6 +112,7 @@ out_of_memory:
pagefault_out_of_memory();
return 0;
}
+EXPORT_SYMBOL(handle_page_fault);
static void show_segv_info(struct uml_pt_regs *regs)
{
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
deleted file mode 100644
index dd33f040c526..000000000000
--- a/arch/um/kernel/uaccess.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-/*
- * These are here rather than tt/uaccess.c because skas mode needs them in
- * order to do SIGBUS recovery when a tmpfs mount runs out of room.
- */
-
-#include <linux/string.h>
-#include "os.h"
-
-static void __do_copy(void *to, const void *from, int n)
-{
- memcpy(to, from, n);
-}
-
-
-int __do_copy_to_user(void *to, const void *from, int n,
- void **fault_addr, jmp_buf **fault_catcher)
-{
- unsigned long fault;
- int faulted;
-
- fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
- __do_copy, &faulted);
- if (!faulted)
- return 0;
- else
- return n - (fault - (unsigned long) to);
-}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 8d84250324b3..ba00eae45aad 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -102,6 +102,8 @@ const struct seq_operations cpuinfo_op = {
/* Set in linux_main */
unsigned long uml_physmem;
+EXPORT_SYMBOL(uml_physmem);
+
unsigned long uml_reserved; /* Also modified in mem_init */
unsigned long start_vm;
unsigned long end_vm;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index b33f4dfe7ae5..dd764101e488 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,14 +4,14 @@
#
obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
- registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
- umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
+ registers.o sigio.o signal.o start_up.o time.o tty.o \
+ umid.o user_syms.o util.o drivers/ skas/
obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
- tty.o tls.o uaccess.o umid.o util.o
+ tty.o umid.o util.o
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 57e3d46c989c..c5d039e1ff3b 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -11,10 +11,8 @@
#include <asm/unistd.h>
#include "aio.h"
#include "init.h"
-#include "kern_constants.h"
#include "kern_util.h"
#include "os.h"
-#include "user.h"
struct aio_thread_req {
enum aio_type type;
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index cc72cb2c1af6..db3d6481375a 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -13,11 +13,9 @@
#include <sys/socket.h>
#include <sys/wait.h>
#include "etap.h"
-#include "kern_constants.h"
#include "os.h"
#include "net_user.h"
#include "um_malloc.h"
-#include "user.h"
#define MAX_PACKET ETH_MAX_PACKET
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 2448be03fd7a..a2aacffdd907 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -13,11 +13,9 @@
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/uio.h>
-#include "kern_constants.h"
#include "kern_util.h"
#include "os.h"
#include "tuntap.h"
-#include "user.h"
static int tuntap_user_init(void *data, void *dev)
{
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 953323799381..d895271ad6f7 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -12,7 +12,6 @@
#include "init.h"
#include "elf_user.h"
#include "mem_user.h"
-#include <kern_constants.h>
typedef Elf32_auxv_t elf_auxv_t;
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 140e587bc0ad..b049a63bb74b 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -13,9 +13,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
-#include "kern_constants.h"
#include "os.h"
-#include "user.h"
static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
{
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index feff22d64672..cf26c4a9a43a 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -10,11 +10,9 @@
#include <linux/limits.h>
#include <sys/socket.h>
#include <sys/wait.h>
-#include "kern_constants.h"
#include "kern_util.h"
#include "os.h"
#include "um_malloc.h"
-#include "user.h"
struct helper_data {
void (*pre_exec)(void*);
diff --git a/arch/um/os-Linux/internal.h b/arch/um/os-Linux/internal.h
new file mode 100644
index 000000000000..2c3c3ecd8c01
--- /dev/null
+++ b/arch/um/os-Linux/internal.h
@@ -0,0 +1 @@
+void alarm_handler(int, mcontext_t *);
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index 0348b975e81c..9a49908b576c 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -9,11 +9,8 @@
#include <signal.h>
#include <string.h>
#include "irq_user.h"
-#include "kern_constants.h"
#include "os.h"
-#include "process.h"
#include "um_malloc.h"
-#include "user.h"
/*
* Locked by irq_lock in arch/um/kernel/irq.c. Changed by os_create_pollfd
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 8471b817d94f..7a86dd516eb1 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -12,7 +12,6 @@
#include <sys/resource.h>
#include "as-layout.h"
#include "init.h"
-#include "kern_constants.h"
#include "kern_util.h"
#include "os.h"
#include "um_malloc.h"
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 62878cf1d33f..8e421e1d6d36 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -14,9 +14,7 @@
#include <sys/mman.h>
#include <sys/param.h>
#include "init.h"
-#include "kern_constants.h"
#include "os.h"
-#include "user.h"
/* Modified by which_tmpdir, which is called during early boot */
static char *default_tmpdir = "/tmp";
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 0c45dc8efb05..307f173e7f82 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -13,12 +13,9 @@
#include <sys/wait.h>
#include <asm/unistd.h>
#include "init.h"
-#include "kern_constants.h"
#include "longjmp.h"
#include "os.h"
-#include "process.h"
#include "skas_ptrace.h"
-#include "user.h"
#define ARBITRARY_ADDR -1
#define FAILURE_PID -1
@@ -237,21 +234,13 @@ out:
void init_new_thread_signals(void)
{
- set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK,
- SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK,
- SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK,
- SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK,
- SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK,
- SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
+ set_handler(SIGSEGV);
+ set_handler(SIGTRAP);
+ set_handler(SIGFPE);
+ set_handler(SIGILL);
+ set_handler(SIGBUS);
signal(SIGHUP, SIG_IGN);
-
- set_handler(SIGIO, (__sighandler_t) sig_handler,
- SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
- SIGVTALRM, -1);
+ set_handler(SIGIO);
signal(SIGWINCH, SIG_IGN);
signal(SIGTERM, SIG_DFL);
}
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 63d299df152b..3c161218c671 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -11,14 +11,11 @@
#include <sched.h>
#include <signal.h>
#include <string.h>
-#include "kern_constants.h"
#include "kern_util.h"
#include "init.h"
#include "os.h"
-#include "process.h"
#include "sigio.h"
#include "um_malloc.h"
-#include "user.h"
/*
* Protected by sigio_lock(), also used by sigio_cleanup, which is an
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 6ae180703a63..2d22f1fcd8e2 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -12,13 +12,7 @@
#include "as-layout.h"
#include "kern_util.h"
#include "os.h"
-#include "process.h"
-#include "sysdep/barrier.h"
-#include "sysdep/sigcontext.h"
-#include "user.h"
-
-/* Copied from linux/compiler-gcc.h since we can't include it directly */
-#define barrier() __asm__ __volatile__("": : :"memory")
+#include "sysdep/mcontext.h"
void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
[SIGTRAP] = relay_signal,
@@ -30,7 +24,7 @@ void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
[SIGIO] = sigio_handler,
[SIGVTALRM] = timer_handler };
-static void sig_handler_common(int sig, struct sigcontext *sc)
+static void sig_handler_common(int sig, mcontext_t *mc)
{
struct uml_pt_regs r;
int save_errno = errno;
@@ -38,8 +32,8 @@ static void sig_handler_common(int sig, struct sigcontext *sc)
r.is_user = 0;
if (sig == SIGSEGV) {
/* For segfaults, we want the data from the sigcontext. */
- copy_sc(&r, sc);
- GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
+ get_regs_from_mc(&r, mc);
+ GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
}
/* enable signals if sig isn't IRQ signal */
@@ -66,7 +60,7 @@ static void sig_handler_common(int sig, struct sigcontext *sc)
static int signals_enabled;
static unsigned int signals_pending;
-void sig_handler(int sig, struct sigcontext *sc)
+void sig_handler(int sig, mcontext_t *mc)
{
int enabled;
@@ -78,23 +72,23 @@ void sig_handler(int sig, struct sigcontext *sc)
block_signals();
- sig_handler_common(sig, sc);
+ sig_handler_common(sig, mc);
set_signals(enabled);
}
-static void real_alarm_handler(struct sigcontext *sc)
+static void real_alarm_handler(mcontext_t *mc)
{
struct uml_pt_regs regs;
- if (sc != NULL)
- copy_sc(&regs, sc);
+ if (mc != NULL)
+ get_regs_from_mc(&regs, mc);
regs.is_user = 0;
unblock_signals();
timer_handler(SIGVTALRM, &regs);
}
-void alarm_handler(int sig, struct sigcontext *sc)
+void alarm_handler(int sig, mcontext_t *mc)
{
int enabled;
@@ -106,14 +100,13 @@ void alarm_handler(int sig, struct sigcontext *sc)
block_signals();
- real_alarm_handler(sc);
+ real_alarm_handler(mc);
set_signals(enabled);
}
void timer_init(void)
{
- set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
- SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
+ set_handler(SIGVTALRM);
}
void set_sigstack(void *sig_stack, int size)
@@ -126,10 +119,23 @@ void set_sigstack(void *sig_stack, int size)
panic("enabling signal stack failed, errno = %d\n", errno);
}
-static void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = {
+ [SIGSEGV] = sig_handler,
+ [SIGBUS] = sig_handler,
+ [SIGILL] = sig_handler,
+ [SIGFPE] = sig_handler,
+ [SIGTRAP] = sig_handler,
+
+ [SIGIO] = sig_handler,
+ [SIGWINCH] = sig_handler,
+ [SIGVTALRM] = alarm_handler
+};
+
-void handle_signal(int sig, struct sigcontext *sc)
+static void hard_handler(int sig, siginfo_t *info, void *p)
{
+ struct ucontext *uc = p;
+ mcontext_t *mc = &uc->uc_mcontext;
unsigned long pending = 1UL << sig;
do {
@@ -155,7 +161,7 @@ void handle_signal(int sig, struct sigcontext *sc)
while ((sig = ffs(pending)) != 0){
sig--;
pending &= ~(1 << sig);
- (*handlers[sig])(sig, sc);
+ (*handlers[sig])(sig, mc);
}
/*
@@ -169,28 +175,26 @@ void handle_signal(int sig, struct sigcontext *sc)
} while (pending);
}
-extern void hard_handler(int sig);
-
-void set_handler(int sig, void (*handler)(int), int flags, ...)
+void set_handler(int sig)
{
struct sigaction action;
- va_list ap;
+ int flags = SA_SIGINFO | SA_ONSTACK;
sigset_t sig_mask;
- int mask;
- handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
- action.sa_handler = hard_handler;
+ action.sa_sigaction = hard_handler;
+ /* block irq ones */
sigemptyset(&action.sa_mask);
-
- va_start(ap, flags);
- while ((mask = va_arg(ap, int)) != -1)
- sigaddset(&action.sa_mask, mask);
- va_end(ap);
+ sigaddset(&action.sa_mask, SIGVTALRM);
+ sigaddset(&action.sa_mask, SIGIO);
+ sigaddset(&action.sa_mask, SIGWINCH);
if (sig == SIGSEGV)
flags |= SA_NODEFER;
+ if (sigismember(&action.sa_mask, sig))
+ flags |= SA_RESTART; /* if it's an irq signal */
+
action.sa_flags = flags;
action.sa_restorer = NULL;
if (sigaction(sig, &action, NULL) < 0)
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index e771398be5f3..c0afff7af4bd 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -9,7 +9,6 @@
#include <string.h>
#include <sys/mman.h>
#include "init.h"
-#include "kern_constants.h"
#include "as-layout.h"
#include "mm_id.h"
#include "os.h"
@@ -17,7 +16,6 @@
#include "ptrace_user.h"
#include "registers.h"
#include "skas.h"
-#include "user.h"
#include "sysdep/ptrace.h"
#include "sysdep/stub.h"
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index dee0e8cf8ad0..cd65727854eb 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -9,31 +9,23 @@
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
-#include <sys/ptrace.h>
#include <sys/wait.h>
#include <asm/unistd.h>
#include "as-layout.h"
-#include "chan_user.h"
-#include "kern_constants.h"
+#include "init.h"
#include "kern_util.h"
#include "mem.h"
#include "os.h"
-#include "process.h"
#include "proc_mm.h"
#include "ptrace_user.h"
#include "registers.h"
#include "skas.h"
#include "skas_ptrace.h"
-#include "user.h"
#include "sysdep/stub.h"
int is_skas_winch(int pid, int fd, void *data)
{
- if (pid != getpgrp())
- return 0;
-
- register_winch_irq(-1, fd, -1, data, 0);
- return 1;
+ return pid == getpgrp();
}
static int ptrace_dump_regs(int pid)
@@ -169,7 +161,7 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
if (!local_using_sysemu)
{
- err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+ err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
__NR_getpid);
if (err < 0) {
printk(UM_KERN_ERR "handle_trap - nullifying syscall "
@@ -257,8 +249,8 @@ static int userspace_tramp(void *stack)
set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_ONSTACK | SA_NODEFER;
- sa.sa_handler = (void *) v;
+ sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;
+ sa.sa_sigaction = (void *) v;
sa.sa_restorer = NULL;
if (sigaction(SIGSEGV, &sa, NULL) < 0) {
printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
@@ -661,8 +653,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
{
int n;
- set_handler(SIGWINCH, (__sighandler_t) sig_handler,
- SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1);
+ set_handler(SIGWINCH);
/*
* Can't use UML_SETJMP or UML_LONGJMP here because they save
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 02ee9adff54a..425162e22af5 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -13,12 +13,10 @@
#include <signal.h>
#include <string.h>
#include <sys/mman.h>
-#include <sys/ptrace.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <asm/unistd.h>
#include "init.h"
-#include "kern_constants.h"
#include "os.h"
#include "mem_user.h"
#include "ptrace_user.h"
@@ -225,7 +223,7 @@ static void __init check_sysemu(void)
goto fail;
}
- n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
+ n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
if (n < 0) {
non_fatal("check_sysemu : failed to modify system call "
"return");
@@ -261,7 +259,7 @@ static void __init check_sysemu(void)
"doesn't singlestep");
goto fail;
}
- n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
+ n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
os_getpid());
if (n < 0)
fatal_perror("check_sysemu : failed to modify "
@@ -317,10 +315,10 @@ static void __init check_ptrace(void)
fatal("check_ptrace : expected (SIGTRAP|0x80), "
"got status = %d", status);
- syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
+ syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
0);
if (syscall == __NR_getpid) {
- n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+ n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
__NR_getppid);
if (n < 0)
fatal_perror("check_ptrace : failed to modify "
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c
deleted file mode 100644
index f311609f93da..000000000000
--- a/arch/um/os-Linux/sys-i386/signal.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-
-extern void handle_signal(int sig, struct sigcontext *sc);
-
-void hard_handler(int sig)
-{
- handle_signal(sig, (struct sigcontext *) (&sig + 1));
-}
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
deleted file mode 100644
index a44a47f8f57b..000000000000
--- a/arch/um/os-Linux/sys-x86_64/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-# Licensed under the GPL
-#
-
-obj-y = registers.o prctl.o signal.o task_size.o
-
-USER_OBJS := $(obj-y)
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
deleted file mode 100644
index 594d97ad02b3..000000000000
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2006 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <sys/ptrace.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
-#include "kern_constants.h"
-#include "longjmp.h"
-#include "user.h"
-
-int save_fp_registers(int pid, unsigned long *fp_regs)
-{
- if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
- return -errno;
- return 0;
-}
-
-int restore_fp_registers(int pid, unsigned long *fp_regs)
-{
- if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
- return -errno;
- return 0;
-}
-
-unsigned long get_thread_reg(int reg, jmp_buf *buf)
-{
- switch (reg) {
- case RIP:
- return buf[0]->__rip;
- case RSP:
- return buf[0]->__rsp;
- case RBP:
- return buf[0]->__rbp;
- default:
- printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
- reg);
- return 0;
- }
-}
-
-int get_fp_registers(int pid, unsigned long *regs)
-{
- return save_fp_registers(pid, regs);
-}
-
-int put_fp_registers(int pid, unsigned long *regs)
-{
- return restore_fp_registers(pid, regs);
-}
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c
deleted file mode 100644
index 82a388822cd3..000000000000
--- a/arch/um/os-Linux/sys-x86_64/signal.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-
-extern void handle_signal(int sig, struct sigcontext *sc);
-
-void hard_handler(int sig)
-{
- struct ucontext *uc;
- asm("movq %%rdx, %0" : "=r" (uc));
-
- handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext);
-}
diff --git a/arch/um/os-Linux/sys-x86_64/task_size.c b/arch/um/os-Linux/sys-x86_64/task_size.c
deleted file mode 100644
index 26a0dd1f349c..000000000000
--- a/arch/um/os-Linux/sys-x86_64/task_size.c
+++ /dev/null
@@ -1,5 +0,0 @@
-unsigned long os_get_top_address(unsigned long shift)
-{
- /* The old value of CONFIG_TOP_ADDR */
- return 0x7fc0000000;
-}
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 6e3359d6a839..910499d76a67 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -8,11 +8,9 @@
#include <signal.h>
#include <time.h>
#include <sys/time.h>
-#include "kern_constants.h"
#include "kern_util.h"
#include "os.h"
-#include "process.h"
-#include "user.h"
+#include "internal.h"
int set_interval(void)
{
diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c
deleted file mode 100644
index 73277801ef14..000000000000
--- a/arch/um/os-Linux/tls.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <errno.h>
-#include <sys/ptrace.h>
-#include "sysdep/tls.h"
-
-/* TLS support - we basically rely on the host's one.*/
-
-#ifndef PTRACE_GET_THREAD_AREA
-#define PTRACE_GET_THREAD_AREA 25
-#endif
-
-#ifndef PTRACE_SET_THREAD_AREA
-#define PTRACE_SET_THREAD_AREA 26
-#endif
-
-int os_set_thread_area(user_desc_t *info, int pid)
-{
- int ret;
-
- ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
- (unsigned long) info);
- if (ret < 0)
- ret = -errno;
- return ret;
-}
-
-int os_get_thread_area(user_desc_t *info, int pid)
-{
- int ret;
-
- ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
- (unsigned long) info);
- if (ret < 0)
- ret = -errno;
- return ret;
-}
diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
index b09ff66a77ee..dd12b99dcb59 100644
--- a/arch/um/os-Linux/tty.c
+++ b/arch/um/os-Linux/tty.c
@@ -7,10 +7,8 @@
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
-#include "kern_constants.h"
#include "kern_util.h"
#include "os.h"
-#include "user.h"
struct grantpt_info {
int fd;
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
deleted file mode 100644
index 087ed74ffca5..000000000000
--- a/arch/um/os-Linux/uaccess.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <stddef.h>
-#include "longjmp.h"
-
-unsigned long __do_user_copy(void *to, const void *from, int n,
- void **fault_addr, jmp_buf **fault_catcher,
- void (*op)(void *to, const void *from,
- int n), int *faulted_out)
-{
- unsigned long *faddrp = (unsigned long *) fault_addr, ret;
-
- jmp_buf jbuf;
- *fault_catcher = &jbuf;
- if (UML_SETJMP(&jbuf) == 0) {
- (*op)(to, from, n);
- ret = 0;
- *faulted_out = 0;
- }
- else {
- ret = *faddrp;
- *faulted_out = 1;
- }
- *fault_addr = NULL;
- *fault_catcher = NULL;
- return ret;
-}
-
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index a27defb81884..4832eb519f8d 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -13,9 +13,7 @@
#include <unistd.h>
#include <sys/stat.h>
#include "init.h"
-#include "kern_constants.h"
#include "os.h"
-#include "user.h"
#define UML_DIR "~/.uml/"
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 5803b1887672..9e3b43bb84c9 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -13,9 +13,7 @@
#include <wait.h>
#include <sys/mman.h>
#include <sys/utsname.h>
-#include "kern_constants.h"
#include "os.h"
-#include "user.h"
void stack_protections(unsigned long address)
{
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 61107b68e05b..2eb2843b0634 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS:.o=.%): \
- c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(basetarget).o)
+ c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o)
$(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
-Dunix -D__unix__ -D__$(SUBARCH)__ $(CF)
@@ -25,8 +25,3 @@ $(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
define unprofile
$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
endef
-
-ifdef subarch-obj-y
-obj-y += subarch.o
-subarch-y = $(addprefix ../../$(HEADER_ARCH)/,$(subarch-obj-y))
-endif
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
deleted file mode 100644
index 3923cfb87649..000000000000
--- a/arch/um/sys-i386/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-#
-
-obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
- ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
- sys_call_table.o tls.o atomic64_cx8_32.o mem.o
-
-obj-$(CONFIG_BINFMT_ELF) += elfcore.o
-
-subarch-obj-y = lib/string_32.o
-subarch-obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += lib/rwsem.o
-subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
-subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-
-USER_OBJS := bugs.o ptrace_user.o fault.o
-
-USER_OBJS += user-offsets.s
-extra-y += user-offsets.s
-
-UNPROFILE_OBJS := stub_segv.o
-CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h
deleted file mode 100644
index 42305551d204..000000000000
--- a/arch/um/sys-i386/asm/elf.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-#ifndef __UM_ELF_I386_H
-#define __UM_ELF_I386_H
-
-#include <asm/user.h>
-#include "skas.h"
-
-#define R_386_NONE 0
-#define R_386_32 1
-#define R_386_PC32 2
-#define R_386_GOT32 3
-#define R_386_PLT32 4
-#define R_386_COPY 5
-#define R_386_GLOB_DAT 6
-#define R_386_JMP_SLOT 7
-#define R_386_RELATIVE 8
-#define R_386_GOTOFF 9
-#define R_386_GOTPC 10
-#define R_386_NUM 11
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_i387_struct elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
- (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
-
-#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2LSB
-#define ELF_ARCH EM_386
-
-#define ELF_PLAT_INIT(regs, load_addr) do { \
- PT_REGS_EBX(regs) = 0; \
- PT_REGS_ECX(regs) = 0; \
- PT_REGS_EDX(regs) = 0; \
- PT_REGS_ESI(regs) = 0; \
- PT_REGS_EDI(regs) = 0; \
- PT_REGS_EBP(regs) = 0; \
- PT_REGS_EAX(regs) = 0; \
-} while (0)
-
-#define ELF_EXEC_PAGESIZE 4096
-
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
-/* Shamelessly stolen from include/asm-i386/elf.h */
-
-#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \
- pr_reg[0] = PT_REGS_EBX(regs); \
- pr_reg[1] = PT_REGS_ECX(regs); \
- pr_reg[2] = PT_REGS_EDX(regs); \
- pr_reg[3] = PT_REGS_ESI(regs); \
- pr_reg[4] = PT_REGS_EDI(regs); \
- pr_reg[5] = PT_REGS_EBP(regs); \
- pr_reg[6] = PT_REGS_EAX(regs); \
- pr_reg[7] = PT_REGS_DS(regs); \
- pr_reg[8] = PT_REGS_ES(regs); \
- /* fake once used fs and gs selectors? */ \
- pr_reg[9] = PT_REGS_DS(regs); \
- pr_reg[10] = PT_REGS_DS(regs); \
- pr_reg[11] = PT_REGS_SYSCALL_NR(regs); \
- pr_reg[12] = PT_REGS_IP(regs); \
- pr_reg[13] = PT_REGS_CS(regs); \
- pr_reg[14] = PT_REGS_EFLAGS(regs); \
- pr_reg[15] = PT_REGS_SP(regs); \
- pr_reg[16] = PT_REGS_SS(regs); \
-} while (0);
-
-#define task_pt_regs(t) (&(t)->thread.regs)
-
-struct task_struct;
-
-extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
-
-#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
-
-extern long elf_aux_hwcap;
-#define ELF_HWCAP (elf_aux_hwcap)
-
-extern char * elf_aux_platform;
-#define ELF_PLATFORM (elf_aux_platform)
-
-#define SET_PERSONALITY(ex) do { } while (0)
-
-extern unsigned long vsyscall_ehdr;
-extern unsigned long vsyscall_end;
-extern unsigned long __kernel_vsyscall;
-
-#define VSYSCALL_BASE vsyscall_ehdr
-#define VSYSCALL_END vsyscall_end
-
-/*
- * This is the range that is readable by user mode, and things
- * acting like user mode such as get_user_pages.
- */
-#define FIXADDR_USER_START VSYSCALL_BASE
-#define FIXADDR_USER_END VSYSCALL_END
-
-#define __HAVE_ARCH_GATE_AREA 1
-
-/*
- * Architecture-neutral AT_ values in 0-17, leave some room
- * for more of them, start the x86-specific ones at 32.
- */
-#define AT_SYSINFO 32
-#define AT_SYSINFO_EHDR 33
-
-#define ARCH_DLINFO \
-do { \
- if ( vsyscall_ehdr ) { \
- NEW_AUX_ENT(AT_SYSINFO, __kernel_vsyscall); \
- NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr); \
- } \
-} while (0)
-
-#endif
diff --git a/arch/um/sys-i386/asm/module.h b/arch/um/sys-i386/asm/module.h
deleted file mode 100644
index 5ead4a0b2e35..000000000000
--- a/arch/um/sys-i386/asm/module.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __UM_MODULE_I386_H
-#define __UM_MODULE_I386_H
-
-/* UML is simple */
-struct mod_arch_specific
-{
-};
-
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-
-#endif
diff --git a/arch/um/sys-i386/atomic64_cx8_32.S b/arch/um/sys-i386/atomic64_cx8_32.S
deleted file mode 100644
index 1e901d3d4a95..000000000000
--- a/arch/um/sys-i386/atomic64_cx8_32.S
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * atomic64_t for 586+
- *
- * Copied from arch/x86/lib/atomic64_cx8_32.S
- *
- * Copyright © 2010 Luca Barbieri
- *
- * 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/linkage.h>
-#include <asm/alternative-asm.h>
-#include <asm/dwarf2.h>
-
-.macro SAVE reg
- pushl_cfi %\reg
- CFI_REL_OFFSET \reg, 0
-.endm
-
-.macro RESTORE reg
- popl_cfi %\reg
- CFI_RESTORE \reg
-.endm
-
-.macro read64 reg
- movl %ebx, %eax
- movl %ecx, %edx
-/* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */
- LOCK_PREFIX
- cmpxchg8b (\reg)
-.endm
-
-ENTRY(atomic64_read_cx8)
- CFI_STARTPROC
-
- read64 %ecx
- ret
- CFI_ENDPROC
-ENDPROC(atomic64_read_cx8)
-
-ENTRY(atomic64_set_cx8)
- CFI_STARTPROC
-
-1:
-/* we don't need LOCK_PREFIX since aligned 64-bit writes
- * are atomic on 586 and newer */
- cmpxchg8b (%esi)
- jne 1b
-
- ret
- CFI_ENDPROC
-ENDPROC(atomic64_set_cx8)
-
-ENTRY(atomic64_xchg_cx8)
- CFI_STARTPROC
-
- movl %ebx, %eax
- movl %ecx, %edx
-1:
- LOCK_PREFIX
- cmpxchg8b (%esi)
- jne 1b
-
- ret
- CFI_ENDPROC
-ENDPROC(atomic64_xchg_cx8)
-
-.macro addsub_return func ins insc
-ENTRY(atomic64_\func\()_return_cx8)
- CFI_STARTPROC
- SAVE ebp
- SAVE ebx
- SAVE esi
- SAVE edi
-
- movl %eax, %esi
- movl %edx, %edi
- movl %ecx, %ebp
-
- read64 %ebp
-1:
- movl %eax, %ebx
- movl %edx, %ecx
- \ins\()l %esi, %ebx
- \insc\()l %edi, %ecx
- LOCK_PREFIX
- cmpxchg8b (%ebp)
- jne 1b
-
-10:
- movl %ebx, %eax
- movl %ecx, %edx
- RESTORE edi
- RESTORE esi
- RESTORE ebx
- RESTORE ebp
- ret
- CFI_ENDPROC
-ENDPROC(atomic64_\func\()_return_cx8)
-.endm
-
-addsub_return add add adc
-addsub_return sub sub sbb
-
-.macro incdec_return func ins insc
-ENTRY(atomic64_\func\()_return_cx8)
- CFI_STARTPROC
- SAVE ebx
-
- read64 %esi
-1:
- movl %eax, %ebx
- movl %edx, %ecx
- \ins\()l $1, %ebx
- \insc\()l $0, %ecx
- LOCK_PREFIX
- cmpxchg8b (%esi)
- jne 1b
-
-10:
- movl %ebx, %eax
- movl %ecx, %edx
- RESTORE ebx
- ret
- CFI_ENDPROC
-ENDPROC(atomic64_\func\()_return_cx8)
-.endm
-
-incdec_return inc add adc
-incdec_return dec sub sbb
-
-ENTRY(atomic64_dec_if_positive_cx8)
- CFI_STARTPROC
- SAVE ebx
-
- read64 %esi
-1:
- movl %eax, %ebx
- movl %edx, %ecx
- subl $1, %ebx
- sbb $0, %ecx
- js 2f
- LOCK_PREFIX
- cmpxchg8b (%esi)
- jne 1b
-
-2:
- movl %ebx, %eax
- movl %ecx, %edx
- RESTORE ebx
- ret
- CFI_ENDPROC
-ENDPROC(atomic64_dec_if_positive_cx8)
-
-ENTRY(atomic64_add_unless_cx8)
- CFI_STARTPROC
- SAVE ebp
- SAVE ebx
-/* these just push these two parameters on the stack */
- SAVE edi
- SAVE esi
-
- movl %ecx, %ebp
- movl %eax, %esi
- movl %edx, %edi
-
- read64 %ebp
-1:
- cmpl %eax, 0(%esp)
- je 4f
-2:
- movl %eax, %ebx
- movl %edx, %ecx
- addl %esi, %ebx
- adcl %edi, %ecx
- LOCK_PREFIX
- cmpxchg8b (%ebp)
- jne 1b
-
- movl $1, %eax
-3:
- addl $8, %esp
- CFI_ADJUST_CFA_OFFSET -8
- RESTORE ebx
- RESTORE ebp
- ret
-4:
- cmpl %edx, 4(%esp)
- jne 2b
- xorl %eax, %eax
- jmp 3b
- CFI_ENDPROC
-ENDPROC(atomic64_add_unless_cx8)
-
-ENTRY(atomic64_inc_not_zero_cx8)
- CFI_STARTPROC
- SAVE ebx
-
- read64 %esi
-1:
- testl %eax, %eax
- je 4f
-2:
- movl %eax, %ebx
- movl %edx, %ecx
- addl $1, %ebx
- adcl $0, %ecx
- LOCK_PREFIX
- cmpxchg8b (%esi)
- jne 1b
-
- movl $1, %eax
-3:
- RESTORE ebx
- ret
-4:
- testl %edx, %edx
- jne 2b
- jmp 3b
- CFI_ENDPROC
-ENDPROC(atomic64_inc_not_zero_cx8)
diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c
deleted file mode 100644
index 8d4f273f1219..000000000000
--- a/arch/um/sys-i386/bug.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL V2
- */
-
-#include <linux/uaccess.h>
-#include <asm/errno.h>
-
-/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
- * that's not relevant in skas mode.
- */
-
-int is_valid_bugaddr(unsigned long eip)
-{
- unsigned short ud2;
-
- if (probe_kernel_address((unsigned short __user *)eip, ud2))
- return 0;
-
- return ud2 == 0x0b0f;
-}
diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c
deleted file mode 100644
index bfbefd30db8f..000000000000
--- a/arch/um/sys-i386/ksyms.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "linux/module.h"
-#include "asm/checksum.h"
-
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial);
diff --git a/arch/um/sys-i386/shared/sysdep/barrier.h b/arch/um/sys-i386/shared/sysdep/barrier.h
deleted file mode 100644
index b58d52c5b2f4..000000000000
--- a/arch/um/sys-i386/shared/sysdep/barrier.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __SYSDEP_I386_BARRIER_H
-#define __SYSDEP_I386_BARRIER_H
-
-/* Copied from include/asm-i386 for use by userspace. i386 has the option
- * of using mfence, but I'm just using this, which works everywhere, for now.
- */
-#define mb() asm volatile("lock; addl $0,0(%esp)")
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/host_ldt.h b/arch/um/sys-i386/shared/sysdep/host_ldt.h
deleted file mode 100644
index 0953cc4df652..000000000000
--- a/arch/um/sys-i386/shared/sysdep/host_ldt.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __ASM_HOST_LDT_I386_H
-#define __ASM_HOST_LDT_I386_H
-
-#include <asm/ldt.h>
-
-/*
- * macros stolen from include/asm-i386/desc.h
- */
-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- 0x7000)
-
-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 )
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/ptrace_user.h b/arch/um/sys-i386/shared/sysdep/ptrace_user.h
deleted file mode 100644
index ef56247e4143..000000000000
--- a/arch/um/sys-i386/shared/sysdep/ptrace_user.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_I386_PTRACE_USER_H__
-#define __SYSDEP_I386_PTRACE_USER_H__
-
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-#include <asm/ptrace.h>
-#include "user_constants.h"
-
-#define PT_OFFSET(r) ((r) * sizeof(long))
-
-#define PT_SYSCALL_NR(regs) ((regs)[ORIG_EAX])
-#define PT_SYSCALL_NR_OFFSET PT_OFFSET(ORIG_EAX)
-
-#define PT_SYSCALL_ARG1_OFFSET PT_OFFSET(EBX)
-#define PT_SYSCALL_ARG2_OFFSET PT_OFFSET(ECX)
-#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX)
-#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI)
-#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI)
-#define PT_SYSCALL_ARG6_OFFSET PT_OFFSET(EBP)
-
-#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX)
-
-#define REGS_SYSCALL_NR EAX /* This is used before a system call */
-#define REGS_SYSCALL_ARG1 EBX
-#define REGS_SYSCALL_ARG2 ECX
-#define REGS_SYSCALL_ARG3 EDX
-#define REGS_SYSCALL_ARG4 ESI
-#define REGS_SYSCALL_ARG5 EDI
-#define REGS_SYSCALL_ARG6 EBP
-
-#define REGS_IP_INDEX EIP
-#define REGS_SP_INDEX UESP
-
-#define PT_IP_OFFSET PT_OFFSET(EIP)
-#define PT_IP(regs) ((regs)[EIP])
-#define PT_SP_OFFSET PT_OFFSET(UESP)
-#define PT_SP(regs) ((regs)[UESP])
-
-#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
-
-#ifndef FRAME_SIZE
-#define FRAME_SIZE (17)
-#endif
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/sc.h b/arch/um/sys-i386/shared/sysdep/sc.h
deleted file mode 100644
index c57d1780ad37..000000000000
--- a/arch/um/sys-i386/shared/sysdep/sc.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef __SYSDEP_I386_SC_H
-#define __SYSDEP_I386_SC_H
-
-#include <user_constants.h>
-
-#define SC_OFFSET(sc, field) \
- *((unsigned long *) &(((char *) (sc))[HOST_##field]))
-#define SC_FP_OFFSET(sc, field) \
- *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field]))
-#define SC_FP_OFFSET_PTR(sc, field, type) \
- ((type *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field]))
-
-#define SC_IP(sc) SC_OFFSET(sc, SC_IP)
-#define SC_SP(sc) SC_OFFSET(sc, SC_SP)
-#define SC_FS(sc) SC_OFFSET(sc, SC_FS)
-#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
-#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
-#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
-#define SC_CS(sc) SC_OFFSET(sc, SC_CS)
-#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
-#define SC_EAX(sc) SC_OFFSET(sc, SC_EAX)
-#define SC_EBX(sc) SC_OFFSET(sc, SC_EBX)
-#define SC_ECX(sc) SC_OFFSET(sc, SC_ECX)
-#define SC_EDX(sc) SC_OFFSET(sc, SC_EDX)
-#define SC_EDI(sc) SC_OFFSET(sc, SC_EDI)
-#define SC_ESI(sc) SC_OFFSET(sc, SC_ESI)
-#define SC_EBP(sc) SC_OFFSET(sc, SC_EBP)
-#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO)
-#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR)
-#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2)
-#define SC_FPSTATE(sc) SC_OFFSET(sc, SC_FPSTATE)
-#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
-#define SC_FP_CW(sc) SC_FP_OFFSET(sc, SC_FP_CW)
-#define SC_FP_SW(sc) SC_FP_OFFSET(sc, SC_FP_SW)
-#define SC_FP_TAG(sc) SC_FP_OFFSET(sc, SC_FP_TAG)
-#define SC_FP_IPOFF(sc) SC_FP_OFFSET(sc, SC_FP_IPOFF)
-#define SC_FP_CSSEL(sc) SC_FP_OFFSET(sc, SC_FP_CSSEL)
-#define SC_FP_DATAOFF(sc) SC_FP_OFFSET(sc, SC_FP_DATAOFF)
-#define SC_FP_DATASEL(sc) SC_FP_OFFSET(sc, SC_FP_DATASEL)
-#define SC_FP_ST(sc) SC_FP_OFFSET_PTR(sc, SC_FP_ST, struct _fpstate)
-#define SC_FXSR_ENV(sc) SC_FP_OFFSET_PTR(sc, SC_FXSR_ENV, void)
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/sigcontext.h b/arch/um/sys-i386/shared/sysdep/sigcontext.h
deleted file mode 100644
index f583c87111a0..000000000000
--- a/arch/um/sys-i386/shared/sysdep/sigcontext.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYS_SIGCONTEXT_I386_H
-#define __SYS_SIGCONTEXT_I386_H
-
-#include "sysdep/sc.h"
-
-#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-
-#define GET_FAULTINFO_FROM_SC(fi, sc) \
- { \
- (fi).cr2 = SC_CR2(sc); \
- (fi).error_code = SC_ERR(sc); \
- (fi).trap_no = SC_TRAPNO(sc); \
- }
-
-/* This is Page Fault */
-#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
-
-/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
-#define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo)
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/system.h b/arch/um/sys-i386/shared/sysdep/system.h
deleted file mode 100644
index d1b93c436200..000000000000
--- a/arch/um/sys-i386/shared/sysdep/system.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H_
-#define _ASM_X86_SYSTEM_H_
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#ifdef CONFIG_IA32_EMULATION
-# define AT_VECTOR_SIZE_ARCH 2
-#else
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-void default_idle(void);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb() asm volatile("mfence":::"memory")
-#define rmb() asm volatile("lfence":::"memory")
-#define wmb() asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier. All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads. This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies. See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- * CPU 0 CPU 1
- *
- * b = 2;
- * memory_barrier();
- * p = &b; q = p;
- * read_barrier_depends();
- * d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends(). However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- * CPU 0 CPU 1
- *
- * a = 2;
- * memory_barrier();
- * b = 3; y = b;
- * read_barrier_depends();
- * x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b". Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb() rmb()
-#else
-# define smp_rmb() barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb() wmb()
-#else
-# define smp_wmb() barrier()
-#endif
-#define smp_read_barrier_depends() read_barrier_depends()
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static inline void rdtsc_barrier(void)
-{
- alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
- alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/vm-flags.h b/arch/um/sys-i386/shared/sysdep/vm-flags.h
deleted file mode 100644
index e0d24c568dbc..000000000000
--- a/arch/um/sys-i386/shared/sysdep/vm-flags.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __VM_FLAGS_I386_H
-#define __VM_FLAGS_I386_H
-
-#define VM_DATA_DEFAULT_FLAGS \
- (VM_READ | VM_WRITE | \
- ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
-#endif
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
deleted file mode 100644
index 28ccf737a79f..000000000000
--- a/arch/um/sys-i386/stub_segv.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "sysdep/stub.h"
-#include "sysdep/sigcontext.h"
-
-void __attribute__ ((__section__ (".__syscall_stub")))
-stub_segv_handler(int sig)
-{
- struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
-
- GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc);
-
- trap_myself();
-}
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c
deleted file mode 100644
index 5f883bfe773f..000000000000
--- a/arch/um/sys-i386/user-offsets.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <stdio.h>
-#include <stddef.h>
-#include <signal.h>
-#include <sys/poll.h>
-#include <sys/user.h>
-#include <sys/mman.h>
-#include <asm/ptrace.h>
-
-#define DEFINE(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_LONGS(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
-
-#define OFFSET(sym, str, mem) \
- DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
- OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
- OFFSET(HOST_SC_ERR, sigcontext, err);
- OFFSET(HOST_SC_CR2, sigcontext, cr2);
-
- DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
- DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
-
- DEFINE(HOST_IP, EIP);
- DEFINE(HOST_SP, UESP);
- DEFINE(HOST_EFLAGS, EFL);
- DEFINE(HOST_EAX, EAX);
- DEFINE(HOST_EBX, EBX);
- DEFINE(HOST_ECX, ECX);
- DEFINE(HOST_EDX, EDX);
- DEFINE(HOST_ESI, ESI);
- DEFINE(HOST_EDI, EDI);
- DEFINE(HOST_EBP, EBP);
- DEFINE(HOST_CS, CS);
- DEFINE(HOST_SS, SS);
- DEFINE(HOST_DS, DS);
- DEFINE(HOST_FS, FS);
- DEFINE(HOST_ES, ES);
- DEFINE(HOST_GS, GS);
- DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
-
- /* XXX Duplicated between i386 and x86_64 */
- DEFINE(UM_POLLIN, POLLIN);
- DEFINE(UM_POLLPRI, POLLPRI);
- DEFINE(UM_POLLOUT, POLLOUT);
-
- DEFINE(UM_PROT_READ, PROT_READ);
- DEFINE(UM_PROT_WRITE, PROT_WRITE);
- DEFINE(UM_PROT_EXEC, PROT_EXEC);
-}
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
deleted file mode 100644
index bd4d1d3ba919..000000000000
--- a/arch/um/sys-x86_64/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright 2003 PathScale, Inc.
-#
-# Licensed under the GPL
-#
-
-obj-y = bug.o bugs.o delay.o fault.o ldt.o ptrace.o ptrace_user.o mem.o \
- setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
- sysrq.o ksyms.o tls.o
-
-obj-y += vdso/
-
-subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \
- lib/rwsem.o
-subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-
-ldt-y = ../sys-i386/ldt.o
-
-USER_OBJS := ptrace_user.o
-
-USER_OBJS += user-offsets.s
-extra-y += user-offsets.s
-
-UNPROFILE_OBJS := stub_segv.o
-CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/sys-x86_64/asm/archparam.h b/arch/um/sys-x86_64/asm/archparam.h
deleted file mode 100644
index 6c083663b8d9..000000000000
--- a/arch/um/sys-x86_64/asm/archparam.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_ARCHPARAM_X86_64_H
-#define __UM_ARCHPARAM_X86_64_H
-
-
-/* No user-accessible fixmap addresses, i.e. vsyscall */
-#define FIXADDR_USER_START 0
-#define FIXADDR_USER_END 0
-
-#endif
-
diff --git a/arch/um/sys-x86_64/asm/module.h b/arch/um/sys-x86_64/asm/module.h
deleted file mode 100644
index 8eb79c2d07d5..000000000000
--- a/arch/um/sys-x86_64/asm/module.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_MODULE_X86_64_H
-#define __UM_MODULE_X86_64_H
-
-/* UML is simple */
-struct mod_arch_specific
-{
-};
-
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Sym Elf64_Sym
-#define Elf_Ehdr Elf64_Ehdr
-
-#endif
-
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
deleted file mode 100644
index f3fe1a688f7e..000000000000
--- a/arch/um/sys-x86_64/delay.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- * Mostly copied from arch/x86/lib/delay.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/param.h>
-
-void __delay(unsigned long loops)
-{
- asm volatile(
- "test %0,%0\n"
- "jz 3f\n"
- "jmp 1f\n"
-
- ".align 16\n"
- "1: jmp 2f\n"
-
- ".align 16\n"
- "2: dec %0\n"
- " jnz 2b\n"
- "3: dec %0\n"
-
- : /* we don't need output */
- : "a" (loops)
- );
-}
-EXPORT_SYMBOL(__delay);
-
-inline void __const_udelay(unsigned long xloops)
-{
- int d0;
-
- xloops *= 4;
- asm("mull %%edx"
- : "=d" (xloops), "=&a" (d0)
- : "1" (xloops), "0"
- (loops_per_jiffy * (HZ/4)));
-
- __delay(++xloops);
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
- __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
- __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c
deleted file mode 100644
index ce85117fc64e..000000000000
--- a/arch/um/sys-x86_64/fault.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include "sysdep/ptrace.h"
-
-/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
-struct exception_table_entry
-{
- unsigned long insn;
- unsigned long fixup;
-};
-
-const struct exception_table_entry *search_exception_tables(unsigned long add);
-
-int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
-{
- const struct exception_table_entry *fixup;
-
- fixup = search_exception_tables(address);
- if (fixup != 0) {
- UPT_IP(regs) = fixup->fixup;
- return 1;
- }
- return 0;
-}
diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
deleted file mode 100644
index c57a496d3f5b..000000000000
--- a/arch/um/sys-x86_64/ptrace_user.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include "ptrace_user.h"
-
-int ptrace_getregs(long pid, unsigned long *regs_out)
-{
- if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
- return -errno;
- return(0);
-}
-
-int ptrace_setregs(long pid, unsigned long *regs_out)
-{
- if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0)
- return -errno;
- return(0);
-}
diff --git a/arch/um/sys-x86_64/shared/sysdep/barrier.h b/arch/um/sys-x86_64/shared/sysdep/barrier.h
deleted file mode 100644
index 7b610befdc8f..000000000000
--- a/arch/um/sys-x86_64/shared/sysdep/barrier.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __SYSDEP_X86_64_BARRIER_H
-#define __SYSDEP_X86_64_BARRIER_H
-
-/* Copied from include/asm-x86_64 for use by userspace. */
-#define mb() asm volatile("mfence":::"memory")
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/host_ldt.h b/arch/um/sys-x86_64/shared/sysdep/host_ldt.h
deleted file mode 100644
index e8b1be1e154f..000000000000
--- a/arch/um/sys-x86_64/shared/sysdep/host_ldt.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef __ASM_HOST_LDT_X86_64_H
-#define __ASM_HOST_LDT_X86_64_H
-
-#include <asm/ldt.h>
-
-/*
- * macros stolen from include/asm-x86_64/desc.h
- */
-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-/* Don't allow setting of the lm bit. It is useless anyways because
- * 64bit system calls require __USER_CS. */
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- /* ((info)->lm << 21) | */ \
- 0x7000)
-
-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 && \
- (info)->lm == 0)
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h b/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h
deleted file mode 100644
index a307237b7964..000000000000
--- a/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/elf.h>
-#include <linux/crypto.h>
-#include <asm/page.h>
-#include <asm/mman.h>
-
-#define DEFINE(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_STR1(x) #x
-#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : )
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
- DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-#include <common-offsets.h>
-}
diff --git a/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h b/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h
deleted file mode 100644
index 4dbccdb58f48..000000000000
--- a/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_PTRACE_USER_H__
-#define __SYSDEP_X86_64_PTRACE_USER_H__
-
-#define __FRAME_OFFSETS
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-#include <asm/ptrace.h>
-#undef __FRAME_OFFSETS
-#include "user_constants.h"
-
-#define PT_INDEX(off) ((off) / sizeof(unsigned long))
-
-#define PT_SYSCALL_NR(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-#define PT_SYSCALL_NR_OFFSET (ORIG_RAX)
-
-#define PT_SYSCALL_ARG1(regs) (((unsigned long *) (regs))[PT_INDEX(RDI)])
-#define PT_SYSCALL_ARG1_OFFSET (RDI)
-
-#define PT_SYSCALL_ARG2(regs) (((unsigned long *) (regs))[PT_INDEX(RSI)])
-#define PT_SYSCALL_ARG2_OFFSET (RSI)
-
-#define PT_SYSCALL_ARG3(regs) (((unsigned long *) (regs))[PT_INDEX(RDX)])
-#define PT_SYSCALL_ARG3_OFFSET (RDX)
-
-#define PT_SYSCALL_ARG4(regs) (((unsigned long *) (regs))[PT_INDEX(RCX)])
-#define PT_SYSCALL_ARG4_OFFSET (RCX)
-
-#define PT_SYSCALL_ARG5(regs) (((unsigned long *) (regs))[PT_INDEX(R8)])
-#define PT_SYSCALL_ARG5_OFFSET (R8)
-
-#define PT_SYSCALL_ARG6(regs) (((unsigned long *) (regs))[PT_INDEX(R9)])
-#define PT_SYSCALL_ARG6_OFFSET (R9)
-
-#define PT_SYSCALL_RET_OFFSET (RAX)
-
-#define PT_IP_OFFSET (RIP)
-#define PT_IP(regs) ((regs)[PT_INDEX(RIP)])
-
-#define PT_SP_OFFSET (RSP)
-#define PT_SP(regs) ((regs)[PT_INDEX(RSP)])
-
-#define PT_ORIG_RAX_OFFSET (ORIG_RAX)
-#define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-
-/*
- * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
- * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
- * 2.4 name and value for 2.4 host compatibility.
- */
-#ifndef PTRACE_OLDSETOPTIONS
-#define PTRACE_OLDSETOPTIONS 21
-#endif
-
-/*
- * These are before the system call, so the system call number is RAX
- * rather than ORIG_RAX, and arg4 is R10 rather than RCX
- */
-#define REGS_SYSCALL_NR PT_INDEX(RAX)
-#define REGS_SYSCALL_ARG1 PT_INDEX(RDI)
-#define REGS_SYSCALL_ARG2 PT_INDEX(RSI)
-#define REGS_SYSCALL_ARG3 PT_INDEX(RDX)
-#define REGS_SYSCALL_ARG4 PT_INDEX(R10)
-#define REGS_SYSCALL_ARG5 PT_INDEX(R8)
-#define REGS_SYSCALL_ARG6 PT_INDEX(R9)
-
-#define REGS_IP_INDEX PT_INDEX(RIP)
-#define REGS_SP_INDEX PT_INDEX(RSP)
-
-#define FP_SIZE (HOST_FP_SIZE)
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/sc.h b/arch/um/sys-x86_64/shared/sysdep/sc.h
deleted file mode 100644
index 8aee45b07434..000000000000
--- a/arch/um/sys-x86_64/shared/sysdep/sc.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef __SYSDEP_X86_64_SC_H
-#define __SYSDEP_X86_64_SC_H
-
-/* Copyright (C) 2003 - 2004 PathScale, Inc
- * Released under the GPL
- */
-
-#include <user_constants.h>
-
-#define SC_OFFSET(sc, field) \
- *((unsigned long *) &(((char *) (sc))[HOST_##field]))
-
-#define SC_RBX(sc) SC_OFFSET(sc, SC_RBX)
-#define SC_RCX(sc) SC_OFFSET(sc, SC_RCX)
-#define SC_RDX(sc) SC_OFFSET(sc, SC_RDX)
-#define SC_RSI(sc) SC_OFFSET(sc, SC_RSI)
-#define SC_RDI(sc) SC_OFFSET(sc, SC_RDI)
-#define SC_RBP(sc) SC_OFFSET(sc, SC_RBP)
-#define SC_RAX(sc) SC_OFFSET(sc, SC_RAX)
-#define SC_R8(sc) SC_OFFSET(sc, SC_R8)
-#define SC_R9(sc) SC_OFFSET(sc, SC_R9)
-#define SC_R10(sc) SC_OFFSET(sc, SC_R10)
-#define SC_R11(sc) SC_OFFSET(sc, SC_R11)
-#define SC_R12(sc) SC_OFFSET(sc, SC_R12)
-#define SC_R13(sc) SC_OFFSET(sc, SC_R13)
-#define SC_R14(sc) SC_OFFSET(sc, SC_R14)
-#define SC_R15(sc) SC_OFFSET(sc, SC_R15)
-#define SC_IP(sc) SC_OFFSET(sc, SC_IP)
-#define SC_SP(sc) SC_OFFSET(sc, SC_SP)
-#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2)
-#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR)
-#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO)
-#define SC_CS(sc) SC_OFFSET(sc, SC_CS)
-#define SC_FS(sc) SC_OFFSET(sc, SC_FS)
-#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
-#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
-#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
-#if 0
-#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX)
-#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
-#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#endif
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/sigcontext.h b/arch/um/sys-x86_64/shared/sysdep/sigcontext.h
deleted file mode 100644
index 0155133b1458..000000000000
--- a/arch/um/sys-x86_64/shared/sysdep/sigcontext.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SIGCONTEXT_H
-#define __SYSDEP_X86_64_SIGCONTEXT_H
-
-#include <sysdep/sc.h>
-
-#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-
-#define GET_FAULTINFO_FROM_SC(fi, sc) \
- { \
- (fi).cr2 = SC_CR2(sc); \
- (fi).error_code = SC_ERR(sc); \
- (fi).trap_no = SC_TRAPNO(sc); \
- }
-
-/* This is Page Fault */
-#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
-
-/* No broken SKAS API, which doesn't pass trap_no, here. */
-#define SEGV_MAYBE_FIXABLE(fi) 0
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h b/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h
deleted file mode 100644
index 95db4be786e4..000000000000
--- a/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SKAS_PTRACE_H
-#define __SYSDEP_X86_64_SKAS_PTRACE_H
-
-struct ptrace_faultinfo {
- int is_write;
- unsigned long addr;
-};
-
-struct ptrace_ldt {
- int func;
- void *ptr;
- unsigned long bytecount;
-};
-
-#define PTRACE_LDT 54
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/tls.h b/arch/um/sys-x86_64/shared/sysdep/tls.h
deleted file mode 100644
index 18c000d0357a..000000000000
--- a/arch/um/sys-x86_64/shared/sysdep/tls.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _SYSDEP_TLS_H
-#define _SYSDEP_TLS_H
-
-# ifndef __KERNEL__
-
-/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
- * may be named user_desc (but in 2.4 and in header matching its API was named
- * modify_ldt_ldt_s). */
-
-typedef struct um_dup_user_desc {
- unsigned int entry_number;
- unsigned int base_addr;
- unsigned int limit;
- unsigned int seg_32bit:1;
- unsigned int contents:2;
- unsigned int read_exec_only:1;
- unsigned int limit_in_pages:1;
- unsigned int seg_not_present:1;
- unsigned int useable:1;
- unsigned int lm:1;
-} user_desc_t;
-
-# else /* __KERNEL__ */
-
-# include <ldt.h>
-typedef struct user_desc user_desc_t;
-
-# endif /* __KERNEL__ */
-#endif /* _SYSDEP_TLS_H */
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
deleted file mode 100644
index b6b65c7c7a7d..000000000000
--- a/arch/um/sys-x86_64/signal.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <linux/personality.h>
-#include <linux/ptrace.h>
-#include <linux/kernel.h>
-#include <asm/unistd.h>
-#include <asm/uaccess.h>
-#include <asm/ucontext.h>
-#include "frame_kern.h"
-#include "skas.h"
-
-void copy_sc(struct uml_pt_regs *regs, void *from)
-{
- struct sigcontext *sc = from;
-
-#define GETREG(regs, regno, sc, regname) \
- (regs)->gp[(regno) / sizeof(unsigned long)] = (sc)->regname
-
- GETREG(regs, R8, sc, r8);
- GETREG(regs, R9, sc, r9);
- GETREG(regs, R10, sc, r10);
- GETREG(regs, R11, sc, r11);
- GETREG(regs, R12, sc, r12);
- GETREG(regs, R13, sc, r13);
- GETREG(regs, R14, sc, r14);
- GETREG(regs, R15, sc, r15);
- GETREG(regs, RDI, sc, di);
- GETREG(regs, RSI, sc, si);
- GETREG(regs, RBP, sc, bp);
- GETREG(regs, RBX, sc, bx);
- GETREG(regs, RDX, sc, dx);
- GETREG(regs, RAX, sc, ax);
- GETREG(regs, RCX, sc, cx);
- GETREG(regs, RSP, sc, sp);
- GETREG(regs, RIP, sc, ip);
- GETREG(regs, EFLAGS, sc, flags);
- GETREG(regs, CS, sc, cs);
-
-#undef GETREG
-}
-
-static int copy_sc_from_user(struct pt_regs *regs,
- struct sigcontext __user *from,
- struct _fpstate __user *fpp)
-{
- struct user_i387_struct fp;
- int err = 0;
-
-#define GETREG(regs, regno, sc, regname) \
- __get_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \
- &(sc)->regname)
-
- err |= GETREG(regs, R8, from, r8);
- err |= GETREG(regs, R9, from, r9);
- err |= GETREG(regs, R10, from, r10);
- err |= GETREG(regs, R11, from, r11);
- err |= GETREG(regs, R12, from, r12);
- err |= GETREG(regs, R13, from, r13);
- err |= GETREG(regs, R14, from, r14);
- err |= GETREG(regs, R15, from, r15);
- err |= GETREG(regs, RDI, from, di);
- err |= GETREG(regs, RSI, from, si);
- err |= GETREG(regs, RBP, from, bp);
- err |= GETREG(regs, RBX, from, bx);
- err |= GETREG(regs, RDX, from, dx);
- err |= GETREG(regs, RAX, from, ax);
- err |= GETREG(regs, RCX, from, cx);
- err |= GETREG(regs, RSP, from, sp);
- err |= GETREG(regs, RIP, from, ip);
- err |= GETREG(regs, EFLAGS, from, flags);
- err |= GETREG(regs, CS, from, cs);
- if (err)
- return 1;
-
-#undef GETREG
-
- err = copy_from_user(&fp, fpp, sizeof(struct user_i387_struct));
- if (err)
- return 1;
-
- err = restore_fp_registers(userspace_pid[current_thread_info()->cpu],
- (unsigned long *) &fp);
- if (err < 0) {
- printk(KERN_ERR "copy_sc_from_user - "
- "restore_fp_registers failed, errno = %d\n",
- -err);
- return 1;
- }
-
- return 0;
-}
-
-static int copy_sc_to_user(struct sigcontext __user *to,
- struct _fpstate __user *to_fp, struct pt_regs *regs,
- unsigned long mask, unsigned long sp)
-{
- struct faultinfo * fi = &current->thread.arch.faultinfo;
- struct user_i387_struct fp;
- int err = 0;
-
- err |= __put_user(0, &to->gs);
- err |= __put_user(0, &to->fs);
-
-#define PUTREG(regs, regno, sc, regname) \
- __put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \
- &(sc)->regname)
-
- err |= PUTREG(regs, RDI, to, di);
- err |= PUTREG(regs, RSI, to, si);
- err |= PUTREG(regs, RBP, to, bp);
- /*
- * Must use original RSP, which is passed in, rather than what's in
- * the pt_regs, because that's already been updated to point at the
- * signal frame.
- */
- err |= __put_user(sp, &to->sp);
- err |= PUTREG(regs, RBX, to, bx);
- err |= PUTREG(regs, RDX, to, dx);
- err |= PUTREG(regs, RCX, to, cx);
- err |= PUTREG(regs, RAX, to, ax);
- err |= PUTREG(regs, R8, to, r8);
- err |= PUTREG(regs, R9, to, r9);
- err |= PUTREG(regs, R10, to, r10);
- err |= PUTREG(regs, R11, to, r11);
- err |= PUTREG(regs, R12, to, r12);
- err |= PUTREG(regs, R13, to, r13);
- err |= PUTREG(regs, R14, to, r14);
- err |= PUTREG(regs, R15, to, r15);
- err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */
-
- err |= __put_user(fi->cr2, &to->cr2);
- err |= __put_user(fi->error_code, &to->err);
- err |= __put_user(fi->trap_no, &to->trapno);
-
- err |= PUTREG(regs, RIP, to, ip);
- err |= PUTREG(regs, EFLAGS, to, flags);
-#undef PUTREG
-
- err |= __put_user(mask, &to->oldmask);
- if (err)
- return 1;
-
- err = save_fp_registers(userspace_pid[current_thread_info()->cpu],
- (unsigned long *) &fp);
- if (err < 0) {
- printk(KERN_ERR "copy_sc_from_user - restore_fp_registers "
- "failed, errno = %d\n", -err);
- return 1;
- }
-
- if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
- return 1;
-
- return err;
-}
-
-struct rt_sigframe
-{
- char __user *pretcode;
- struct ucontext uc;
- struct siginfo info;
- struct _fpstate fpstate;
-};
-
-int setup_signal_stack_si(unsigned long stack_top, int sig,
- struct k_sigaction *ka, struct pt_regs * regs,
- siginfo_t *info, sigset_t *set)
-{
- struct rt_sigframe __user *frame;
- unsigned long save_sp = PT_REGS_RSP(regs);
- int err = 0;
- struct task_struct *me = current;
-
- frame = (struct rt_sigframe __user *)
- round_down(stack_top - sizeof(struct rt_sigframe), 16);
- /* Subtract 128 for a red zone and 8 for proper alignment */
- frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto out;
-
- if (ka->sa.sa_flags & SA_SIGINFO) {
- err |= copy_siginfo_to_user(&frame->info, info);
- if (err)
- goto out;
- }
-
- /*
- * Update SP now because the page fault handler refuses to extend
- * the stack if the faulting address is too far below the current
- * SP, which frame now certainly is. If there's an error, the original
- * value is restored on the way out.
- * When writing the sigcontext to the stack, we have to write the
- * original value, so that's passed to copy_sc_to_user, which does
- * the right thing with it.
- */
- PT_REGS_RSP(regs) = (unsigned long) frame;
-
- /* Create the ucontext. */
- err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(0, &frame->uc.uc_link);
- err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(save_sp),
- &frame->uc.uc_stack.ss_flags);
- err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
- set->sig[0], save_sp);
- err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
- if (sizeof(*set) == 16) {
- __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
- __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
- }
- else
- err |= __copy_to_user(&frame->uc.uc_sigmask, set,
- sizeof(*set));
-
- /*
- * Set up to return from userspace. If provided, use a stub
- * already in userspace.
- */
- /* x86-64 should always use SA_RESTORER. */
- if (ka->sa.sa_flags & SA_RESTORER)
- err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
- else
- /* could use a vstub here */
- goto restore_sp;
-
- if (err)
- goto restore_sp;
-
- /* Set up registers for signal handler */
- {
- struct exec_domain *ed = current_thread_info()->exec_domain;
- if (unlikely(ed && ed->signal_invmap && sig < 32))
- sig = ed->signal_invmap[sig];
- }
-
- PT_REGS_RDI(regs) = sig;
- /* In case the signal handler was declared without prototypes */
- PT_REGS_RAX(regs) = 0;
-
- /*
- * This also works for non SA_SIGINFO handlers because they expect the
- * next argument after the signal number on the stack.
- */
- PT_REGS_RSI(regs) = (unsigned long) &frame->info;
- PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
- PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
- out:
- return err;
-
-restore_sp:
- PT_REGS_RSP(regs) = save_sp;
- return err;
-}
-
-long sys_rt_sigreturn(struct pt_regs *regs)
-{
- unsigned long sp = PT_REGS_SP(&current->thread.regs);
- struct rt_sigframe __user *frame =
- (struct rt_sigframe __user *)(sp - 8);
- struct ucontext __user *uc = &frame->uc;
- sigset_t set;
-
- if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
- goto segfault;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
- &frame->fpstate))
- goto segfault;
-
- /* Avoid ERESTART handling */
- PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
- return PT_REGS_SYSCALL_RET(&current->thread.regs);
-
- segfault:
- force_sig(SIGSEGV, current);
- return 0;
-}
diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h
index 4bd87f3d13d4..1a5c5a5eb39c 100644
--- a/arch/unicore32/include/asm/io.h
+++ b/arch/unicore32/include/asm/io.h
@@ -32,7 +32,7 @@ extern void __uc32_iounmap(volatile void __iomem *addr);
* ioremap and friends.
*
* ioremap takes a PCI memory address, as specified in
- * Documentation/IO-mapping.txt.
+ * Documentation/io-mapping.txt.
*
*/
#define ioremap(cookie, size) __uc32_ioremap(cookie, size)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 6a47bb22657f..77f7a384c0b5 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -64,10 +64,12 @@ config X86
select HAVE_TEXT_POKE_SMP
select HAVE_GENERIC_HARDIRQS
select HAVE_SPARSE_IRQ
+ select SPARSE_IRQ
select GENERIC_FIND_FIRST_BIT
select GENERIC_IRQ_PROBE
select GENERIC_PENDING_IRQ if SMP
select GENERIC_IRQ_SHOW
+ select GENERIC_CLOCKEVENTS_MIN_ADJUST
select IRQ_FORCED_THREADING
select USE_GENERIC_SMP_HELPERS if SMP
select HAVE_BPF_JIT if (X86_64 && NET)
@@ -130,7 +132,7 @@ config SBUS
bool
config NEED_DMA_MAP_STATE
- def_bool (X86_64 || DMAR || DMA_API_DEBUG)
+ def_bool (X86_64 || INTEL_IOMMU || DMA_API_DEBUG)
config NEED_SG_DMA_LENGTH
def_bool y
@@ -220,7 +222,7 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC
config HAVE_INTEL_TXT
def_bool y
- depends on EXPERIMENTAL && DMAR && ACPI
+ depends on EXPERIMENTAL && INTEL_IOMMU && ACPI
config X86_32_SMP
def_bool y
@@ -279,7 +281,7 @@ config SMP
Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
Management" code will be disabled if you say Y here.
- See also <file:Documentation/i386/IO-APIC.txt>,
+ See also <file:Documentation/x86/i386/IO-APIC.txt>,
<file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
<http://www.tldp.org/docs.html#howto>.
@@ -287,7 +289,7 @@ config SMP
config X86_X2APIC
bool "Support x2apic"
- depends on X86_LOCAL_APIC && X86_64 && INTR_REMAP
+ depends on X86_LOCAL_APIC && X86_64 && IRQ_REMAP
---help---
This enables x2apic support on CPUs that have this feature.
@@ -1452,6 +1454,15 @@ config ARCH_USES_PG_UNCACHED
def_bool y
depends on X86_PAT
+config ARCH_RANDOM
+ def_bool y
+ prompt "x86 architectural random number generator" if EXPERT
+ ---help---
+ Enable the x86 architectural RDRAND instruction
+ (Intel Bull Mountain technology) to generate random numbers.
+ If supported, this is a high bandwidth, cryptographically
+ secure hardware random number generator.
+
config EFI
bool "EFI runtime service support"
depends on ACPI
@@ -2064,6 +2075,20 @@ config OLPC_XO15_SCI
- AC adapter status updates
- Battery status updates
+config ALIX
+ bool "PCEngines ALIX System Support (LED setup)"
+ select GPIOLIB
+ ---help---
+ This option enables system support for the PCEngines ALIX.
+ At present this just sets up LEDs for GPIO control on
+ ALIX2/3/6 boards. However, other system specific setup should
+ get added here.
+
+ Note: You must still enable the drivers for GPIO and LED support
+ (GPIO_CS5535 & LEDS_GPIO) to actually use the LEDs
+
+ Note: You have to set alix.force=1 for boards with Award BIOS.
+
endif # X86_32
config AMD_NB
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index c0f8a5c88910..bf56e1793272 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -139,7 +139,7 @@ config IOMMU_DEBUG
code. When you use it make sure you have a big enough
IOMMU/AGP aperture. Most of the options enabled by this can
be set more finegrained using the iommu= command line
- options. See Documentation/x86_64/boot-options.txt for more
+ options. See Documentation/x86/x86_64/boot-options.txt for more
details.
config IOMMU_STRESS
diff --git a/arch/um/Makefile-i386 b/arch/x86/Makefile.um
index 302cbe504543..36ddec6a41c9 100644
--- a/arch/um/Makefile-i386
+++ b/arch/x86/Makefile.um
@@ -1,14 +1,11 @@
-core-y += arch/um/sys-i386/ arch/x86/crypto/
-
-TOP_ADDR := $(CONFIG_TOP_ADDR)
+core-y += arch/x86/crypto/
+ifeq ($(CONFIG_X86_32),y)
START := 0x8048000
LDFLAGS += -m elf_i386
-ELF_ARCH := $(SUBARCH)
-ELF_FORMAT := elf32-$(SUBARCH)
-OBJCOPYFLAGS := -O binary -R .note -R .comment -S
-HEADER_ARCH := x86
+ELF_ARCH := i386
+ELF_FORMAT := elf32-i386
CHECKFLAGS += -D__i386__
ifeq ("$(origin SUBARCH)", "command line")
@@ -16,9 +13,8 @@ ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
KBUILD_CFLAGS += $(call cc-option,-m32)
KBUILD_AFLAGS += $(call cc-option,-m32)
LINK-y += $(call cc-option,-m32)
-UML_OBJCOPYFLAGS += -F $(ELF_FORMAT)
-export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS
+export LDFLAGS
endif
endif
@@ -40,3 +36,26 @@ KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
else echo $(call cc-option,-funit-at-a-time); fi ;)
KBUILD_CFLAGS += $(cflags-y)
+
+else
+
+START := 0x60000000
+
+KBUILD_CFLAGS += -fno-builtin -m64
+
+CHECKFLAGS += -m64 -D__x86_64__
+KBUILD_AFLAGS += -m64
+LDFLAGS += -m elf_x86_64
+KBUILD_CPPFLAGS += -m64
+
+ELF_ARCH := i386:x86-64
+ELF_FORMAT := elf64-x86-64
+
+# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
+
+LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
+LINK-y += -m64
+
+# Do unit-at-a-time unconditionally on x86_64, following the host
+KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
+endif
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 93e689f4bd86..bdb4d458ec8c 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -129,7 +129,7 @@ start_sys_seg: .word SYSSEG # obsolete and meaningless, but just
type_of_loader: .byte 0 # 0 means ancient bootloader, newer
# bootloaders know to change this.
- # See Documentation/i386/boot.txt for
+ # See Documentation/x86/boot.txt for
# assigned ids
# flags, unused bits must be zero (RFU) bit within loadflags
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 22a0dc8e51dd..058a35b8286c 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -67,8 +67,8 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_X86_ACPI_CPUFREQ=y
CONFIG_PCI_MMCONFIG=y
-CONFIG_DMAR=y
-# CONFIG_DMAR_DEFAULT_ON is not set
+CONFIG_INTEL_IOMMU=y
+# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
CONFIG_PCIEPORTBUS=y
CONFIG_PCCARD=y
CONFIG_YENTA=y
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index c04f1b7a9139..3537d4b91f74 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -7,21 +7,33 @@ obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
+obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
+obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o
obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o
obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o
obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o
+obj-$(CONFIG_CRYPTO_SHA1_SSSE3) += sha1-ssse3.o
aes-i586-y := aes-i586-asm_32.o aes_glue.o
twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o
aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
+blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
+twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o
salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
+
+# enable AVX support only when $(AS) can actually assemble the instructions
+ifeq ($(call as-instr,vpxor %xmm0$(comma)%xmm1$(comma)%xmm2,yes,no),yes)
+AFLAGS_sha1_ssse3_asm.o += -DSHA1_ENABLE_AVX_SUPPORT
+CFLAGS_sha1_ssse3_glue.o += -DSHA1_ENABLE_AVX_SUPPORT
+endif
+sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c
index 49ae9fe32b22..b0b6950cc8c8 100644
--- a/arch/x86/crypto/aes_glue.c
+++ b/arch/x86/crypto/aes_glue.c
@@ -4,6 +4,7 @@
*/
#include <crypto/aes.h>
+#include <asm/aes.h>
asmlinkage void aes_enc_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
asmlinkage void aes_dec_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
diff --git a/arch/x86/crypto/blowfish-x86_64-asm_64.S b/arch/x86/crypto/blowfish-x86_64-asm_64.S
new file mode 100644
index 000000000000..391d245dc086
--- /dev/null
+++ b/arch/x86/crypto/blowfish-x86_64-asm_64.S
@@ -0,0 +1,390 @@
+/*
+ * Blowfish Cipher Algorithm (x86_64)
+ *
+ * Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ */
+
+.file "blowfish-x86_64-asm.S"
+.text
+
+/* structure of crypto context */
+#define p 0
+#define s0 ((16 + 2) * 4)
+#define s1 ((16 + 2 + (1 * 256)) * 4)
+#define s2 ((16 + 2 + (2 * 256)) * 4)
+#define s3 ((16 + 2 + (3 * 256)) * 4)
+
+/* register macros */
+#define CTX %rdi
+#define RIO %rsi
+
+#define RX0 %rax
+#define RX1 %rbx
+#define RX2 %rcx
+#define RX3 %rdx
+
+#define RX0d %eax
+#define RX1d %ebx
+#define RX2d %ecx
+#define RX3d %edx
+
+#define RX0bl %al
+#define RX1bl %bl
+#define RX2bl %cl
+#define RX3bl %dl
+
+#define RX0bh %ah
+#define RX1bh %bh
+#define RX2bh %ch
+#define RX3bh %dh
+
+#define RT0 %rbp
+#define RT1 %rsi
+#define RT2 %r8
+#define RT3 %r9
+
+#define RT0d %ebp
+#define RT1d %esi
+#define RT2d %r8d
+#define RT3d %r9d
+
+#define RKEY %r10
+
+/***********************************************************************
+ * 1-way blowfish
+ ***********************************************************************/
+#define F() \
+ rorq $16, RX0; \
+ movzbl RX0bh, RT0d; \
+ movzbl RX0bl, RT1d; \
+ rolq $16, RX0; \
+ movl s0(CTX,RT0,4), RT0d; \
+ addl s1(CTX,RT1,4), RT0d; \
+ movzbl RX0bh, RT1d; \
+ movzbl RX0bl, RT2d; \
+ rolq $32, RX0; \
+ xorl s2(CTX,RT1,4), RT0d; \
+ addl s3(CTX,RT2,4), RT0d; \
+ xorq RT0, RX0;
+
+#define add_roundkey_enc(n) \
+ xorq p+4*(n)(CTX), RX0;
+
+#define round_enc(n) \
+ add_roundkey_enc(n); \
+ \
+ F(); \
+ F();
+
+#define add_roundkey_dec(n) \
+ movq p+4*(n-1)(CTX), RT0; \
+ rorq $32, RT0; \
+ xorq RT0, RX0;
+
+#define round_dec(n) \
+ add_roundkey_dec(n); \
+ \
+ F(); \
+ F(); \
+
+#define read_block() \
+ movq (RIO), RX0; \
+ rorq $32, RX0; \
+ bswapq RX0;
+
+#define write_block() \
+ bswapq RX0; \
+ movq RX0, (RIO);
+
+#define xor_block() \
+ bswapq RX0; \
+ xorq RX0, (RIO);
+
+.align 8
+.global __blowfish_enc_blk
+.type __blowfish_enc_blk,@function;
+
+__blowfish_enc_blk:
+ /* input:
+ * %rdi: ctx, CTX
+ * %rsi: dst
+ * %rdx: src
+ * %rcx: bool, if true: xor output
+ */
+ movq %rbp, %r11;
+
+ movq %rsi, %r10;
+ movq %rdx, RIO;
+
+ read_block();
+
+ round_enc(0);
+ round_enc(2);
+ round_enc(4);
+ round_enc(6);
+ round_enc(8);
+ round_enc(10);
+ round_enc(12);
+ round_enc(14);
+ add_roundkey_enc(16);
+
+ movq %r11, %rbp;
+
+ movq %r10, RIO;
+ test %cl, %cl;
+ jnz __enc_xor;
+
+ write_block();
+ ret;
+__enc_xor:
+ xor_block();
+ ret;
+
+.align 8
+.global blowfish_dec_blk
+.type blowfish_dec_blk,@function;
+
+blowfish_dec_blk:
+ /* input:
+ * %rdi: ctx, CTX
+ * %rsi: dst
+ * %rdx: src
+ */
+ movq %rbp, %r11;
+
+ movq %rsi, %r10;
+ movq %rdx, RIO;
+
+ read_block();
+
+ round_dec(17);
+ round_dec(15);
+ round_dec(13);
+ round_dec(11);
+ round_dec(9);
+ round_dec(7);
+ round_dec(5);
+ round_dec(3);
+ add_roundkey_dec(1);
+
+ movq %r10, RIO;
+ write_block();
+
+ movq %r11, %rbp;
+
+ ret;
+
+/**********************************************************************
+ 4-way blowfish, four blocks parallel
+ **********************************************************************/
+
+/* F() for 4-way. Slower when used alone/1-way, but faster when used
+ * parallel/4-way (tested on AMD Phenom II & Intel Xeon E7330).
+ */
+#define F4(x) \
+ movzbl x ## bh, RT1d; \
+ movzbl x ## bl, RT3d; \
+ rorq $16, x; \
+ movzbl x ## bh, RT0d; \
+ movzbl x ## bl, RT2d; \
+ rorq $16, x; \
+ movl s0(CTX,RT0,4), RT0d; \
+ addl s1(CTX,RT2,4), RT0d; \
+ xorl s2(CTX,RT1,4), RT0d; \
+ addl s3(CTX,RT3,4), RT0d; \
+ xorq RT0, x;
+
+#define add_preloaded_roundkey4() \
+ xorq RKEY, RX0; \
+ xorq RKEY, RX1; \
+ xorq RKEY, RX2; \
+ xorq RKEY, RX3;
+
+#define preload_roundkey_enc(n) \
+ movq p+4*(n)(CTX), RKEY;
+
+#define add_roundkey_enc4(n) \
+ add_preloaded_roundkey4(); \
+ preload_roundkey_enc(n + 2);
+
+#define round_enc4(n) \
+ add_roundkey_enc4(n); \
+ \
+ F4(RX0); \
+ F4(RX1); \
+ F4(RX2); \
+ F4(RX3); \
+ \
+ F4(RX0); \
+ F4(RX1); \
+ F4(RX2); \
+ F4(RX3);
+
+#define preload_roundkey_dec(n) \
+ movq p+4*((n)-1)(CTX), RKEY; \
+ rorq $32, RKEY;
+
+#define add_roundkey_dec4(n) \
+ add_preloaded_roundkey4(); \
+ preload_roundkey_dec(n - 2);
+
+#define round_dec4(n) \
+ add_roundkey_dec4(n); \
+ \
+ F4(RX0); \
+ F4(RX1); \
+ F4(RX2); \
+ F4(RX3); \
+ \
+ F4(RX0); \
+ F4(RX1); \
+ F4(RX2); \
+ F4(RX3);
+
+#define read_block4() \
+ movq (RIO), RX0; \
+ rorq $32, RX0; \
+ bswapq RX0; \
+ \
+ movq 8(RIO), RX1; \
+ rorq $32, RX1; \
+ bswapq RX1; \
+ \
+ movq 16(RIO), RX2; \
+ rorq $32, RX2; \
+ bswapq RX2; \
+ \
+ movq 24(RIO), RX3; \
+ rorq $32, RX3; \
+ bswapq RX3;
+
+#define write_block4() \
+ bswapq RX0; \
+ movq RX0, (RIO); \
+ \
+ bswapq RX1; \
+ movq RX1, 8(RIO); \
+ \
+ bswapq RX2; \
+ movq RX2, 16(RIO); \
+ \
+ bswapq RX3; \
+ movq RX3, 24(RIO);
+
+#define xor_block4() \
+ bswapq RX0; \
+ xorq RX0, (RIO); \
+ \
+ bswapq RX1; \
+ xorq RX1, 8(RIO); \
+ \
+ bswapq RX2; \
+ xorq RX2, 16(RIO); \
+ \
+ bswapq RX3; \
+ xorq RX3, 24(RIO);
+
+.align 8
+.global __blowfish_enc_blk_4way
+.type __blowfish_enc_blk_4way,@function;
+
+__blowfish_enc_blk_4way:
+ /* input:
+ * %rdi: ctx, CTX
+ * %rsi: dst
+ * %rdx: src
+ * %rcx: bool, if true: xor output
+ */
+ pushq %rbp;
+ pushq %rbx;
+ pushq %rcx;
+
+ preload_roundkey_enc(0);
+
+ movq %rsi, %r11;
+ movq %rdx, RIO;
+
+ read_block4();
+
+ round_enc4(0);
+ round_enc4(2);
+ round_enc4(4);
+ round_enc4(6);
+ round_enc4(8);
+ round_enc4(10);
+ round_enc4(12);
+ round_enc4(14);
+ add_preloaded_roundkey4();
+
+ popq %rbp;
+ movq %r11, RIO;
+
+ test %bpl, %bpl;
+ jnz __enc_xor4;
+
+ write_block4();
+
+ popq %rbx;
+ popq %rbp;
+ ret;
+
+__enc_xor4:
+ xor_block4();
+
+ popq %rbx;
+ popq %rbp;
+ ret;
+
+.align 8
+.global blowfish_dec_blk_4way
+.type blowfish_dec_blk_4way,@function;
+
+blowfish_dec_blk_4way:
+ /* input:
+ * %rdi: ctx, CTX
+ * %rsi: dst
+ * %rdx: src
+ */
+ pushq %rbp;
+ pushq %rbx;
+ preload_roundkey_dec(17);
+
+ movq %rsi, %r11;
+ movq %rdx, RIO;
+
+ read_block4();
+
+ round_dec4(17);
+ round_dec4(15);
+ round_dec4(13);
+ round_dec4(11);
+ round_dec4(9);
+ round_dec4(7);
+ round_dec4(5);
+ round_dec4(3);
+ add_preloaded_roundkey4();
+
+ movq %r11, RIO;
+ write_block4();
+
+ popq %rbx;
+ popq %rbp;
+
+ ret;
+
diff --git a/arch/x86/crypto/blowfish_glue.c b/arch/x86/crypto/blowfish_glue.c
new file mode 100644
index 000000000000..b05aa163d55a
--- /dev/null
+++ b/arch/x86/crypto/blowfish_glue.c
@@ -0,0 +1,492 @@
+/*
+ * Glue Code for assembler optimized version of Blowfish
+ *
+ * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * CTR part based on code (crypto/ctr.c) by:
+ * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ */
+
+#include <crypto/blowfish.h>
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+
+/* regular block cipher functions */
+asmlinkage void __blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src,
+ bool xor);
+asmlinkage void blowfish_dec_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src);
+
+/* 4-way parallel cipher functions */
+asmlinkage void __blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
+ const u8 *src, bool xor);
+asmlinkage void blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst,
+ const u8 *src);
+
+static inline void blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src)
+{
+ __blowfish_enc_blk(ctx, dst, src, false);
+}
+
+static inline void blowfish_enc_blk_xor(struct bf_ctx *ctx, u8 *dst,
+ const u8 *src)
+{
+ __blowfish_enc_blk(ctx, dst, src, true);
+}
+
+static inline void blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
+ const u8 *src)
+{
+ __blowfish_enc_blk_4way(ctx, dst, src, false);
+}
+
+static inline void blowfish_enc_blk_xor_4way(struct bf_ctx *ctx, u8 *dst,
+ const u8 *src)
+{
+ __blowfish_enc_blk_4way(ctx, dst, src, true);
+}
+
+static void blowfish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ blowfish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static void blowfish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ blowfish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static struct crypto_alg bf_alg = {
+ .cra_name = "blowfish",
+ .cra_driver_name = "blowfish-asm",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = BF_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct bf_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(bf_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = BF_MIN_KEY_SIZE,
+ .cia_max_keysize = BF_MAX_KEY_SIZE,
+ .cia_setkey = blowfish_setkey,
+ .cia_encrypt = blowfish_encrypt,
+ .cia_decrypt = blowfish_decrypt,
+ }
+ }
+};
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+ void (*fn)(struct bf_ctx *, u8 *, const u8 *),
+ void (*fn_4way)(struct bf_ctx *, u8 *, const u8 *))
+{
+ struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = BF_BLOCK_SIZE;
+ unsigned int nbytes;
+ int err;
+
+ err = blkcipher_walk_virt(desc, walk);
+
+ while ((nbytes = walk->nbytes)) {
+ u8 *wsrc = walk->src.virt.addr;
+ u8 *wdst = walk->dst.virt.addr;
+
+ /* Process four block batch */
+ if (nbytes >= bsize * 4) {
+ do {
+ fn_4way(ctx, wdst, wsrc);
+
+ wsrc += bsize * 4;
+ wdst += bsize * 4;
+ nbytes -= bsize * 4;
+ } while (nbytes >= bsize * 4);
+
+ if (nbytes < bsize)
+ goto done;
+ }
+
+ /* Handle leftovers */
+ do {
+ fn(ctx, wdst, wsrc);
+
+ wsrc += bsize;
+ wdst += bsize;
+ nbytes -= bsize;
+ } while (nbytes >= bsize);
+
+done:
+ err = blkcipher_walk_done(desc, walk, nbytes);
+ }
+
+ return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_crypt(desc, &walk, blowfish_enc_blk, blowfish_enc_blk_4way);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_crypt(desc, &walk, blowfish_dec_blk, blowfish_dec_blk_4way);
+}
+
+static struct crypto_alg blk_ecb_alg = {
+ .cra_name = "ecb(blowfish)",
+ .cra_driver_name = "ecb-blowfish-asm",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = BF_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct bf_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(blk_ecb_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = BF_MIN_KEY_SIZE,
+ .max_keysize = BF_MAX_KEY_SIZE,
+ .setkey = blowfish_setkey,
+ .encrypt = ecb_encrypt,
+ .decrypt = ecb_decrypt,
+ },
+ },
+};
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk)
+{
+ struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = BF_BLOCK_SIZE;
+ unsigned int nbytes = walk->nbytes;
+ u64 *src = (u64 *)walk->src.virt.addr;
+ u64 *dst = (u64 *)walk->dst.virt.addr;
+ u64 *iv = (u64 *)walk->iv;
+
+ do {
+ *dst = *src ^ *iv;
+ blowfish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
+ iv = dst;
+
+ src += 1;
+ dst += 1;
+ nbytes -= bsize;
+ } while (nbytes >= bsize);
+
+ *(u64 *)walk->iv = *iv;
+ return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+
+ while ((nbytes = walk.nbytes)) {
+ nbytes = __cbc_encrypt(desc, &walk);
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk)
+{
+ struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = BF_BLOCK_SIZE;
+ unsigned int nbytes = walk->nbytes;
+ u64 *src = (u64 *)walk->src.virt.addr;
+ u64 *dst = (u64 *)walk->dst.virt.addr;
+ u64 ivs[4 - 1];
+ u64 last_iv;
+
+ /* Start of the last block. */
+ src += nbytes / bsize - 1;
+ dst += nbytes / bsize - 1;
+
+ last_iv = *src;
+
+ /* Process four block batch */
+ if (nbytes >= bsize * 4) {
+ do {
+ nbytes -= bsize * 4 - bsize;
+ src -= 4 - 1;
+ dst -= 4 - 1;
+
+ ivs[0] = src[0];
+ ivs[1] = src[1];
+ ivs[2] = src[2];
+
+ blowfish_dec_blk_4way(ctx, (u8 *)dst, (u8 *)src);
+
+ dst[1] ^= ivs[0];
+ dst[2] ^= ivs[1];
+ dst[3] ^= ivs[2];
+
+ nbytes -= bsize;
+ if (nbytes < bsize)
+ goto done;
+
+ *dst ^= *(src - 1);
+ src -= 1;
+ dst -= 1;
+ } while (nbytes >= bsize * 4);
+
+ if (nbytes < bsize)
+ goto done;
+ }
+
+ /* Handle leftovers */
+ for (;;) {
+ blowfish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
+
+ nbytes -= bsize;
+ if (nbytes < bsize)
+ break;
+
+ *dst ^= *(src - 1);
+ src -= 1;
+ dst -= 1;
+ }
+
+done:
+ *dst ^= *(u64 *)walk->iv;
+ *(u64 *)walk->iv = last_iv;
+
+ return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+
+ while ((nbytes = walk.nbytes)) {
+ nbytes = __cbc_decrypt(desc, &walk);
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ return err;
+}
+
+static struct crypto_alg blk_cbc_alg = {
+ .cra_name = "cbc(blowfish)",
+ .cra_driver_name = "cbc-blowfish-asm",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = BF_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct bf_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(blk_cbc_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = BF_MIN_KEY_SIZE,
+ .max_keysize = BF_MAX_KEY_SIZE,
+ .ivsize = BF_BLOCK_SIZE,
+ .setkey = blowfish_setkey,
+ .encrypt = cbc_encrypt,
+ .decrypt = cbc_decrypt,
+ },
+ },
+};
+
+static void ctr_crypt_final(struct bf_ctx *ctx, struct blkcipher_walk *walk)
+{
+ u8 *ctrblk = walk->iv;
+ u8 keystream[BF_BLOCK_SIZE];
+ u8 *src = walk->src.virt.addr;
+ u8 *dst = walk->dst.virt.addr;
+ unsigned int nbytes = walk->nbytes;
+
+ blowfish_enc_blk(ctx, keystream, ctrblk);
+ crypto_xor(keystream, src, nbytes);
+ memcpy(dst, keystream, nbytes);
+
+ crypto_inc(ctrblk, BF_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk)
+{
+ struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = BF_BLOCK_SIZE;
+ unsigned int nbytes = walk->nbytes;
+ u64 *src = (u64 *)walk->src.virt.addr;
+ u64 *dst = (u64 *)walk->dst.virt.addr;
+ u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
+ __be64 ctrblocks[4];
+
+ /* Process four block batch */
+ if (nbytes >= bsize * 4) {
+ do {
+ if (dst != src) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ }
+
+ /* create ctrblks for parallel encrypt */
+ ctrblocks[0] = cpu_to_be64(ctrblk++);
+ ctrblocks[1] = cpu_to_be64(ctrblk++);
+ ctrblocks[2] = cpu_to_be64(ctrblk++);
+ ctrblocks[3] = cpu_to_be64(ctrblk++);
+
+ blowfish_enc_blk_xor_4way(ctx, (u8 *)dst,
+ (u8 *)ctrblocks);
+
+ src += 4;
+ dst += 4;
+ } while ((nbytes -= bsize * 4) >= bsize * 4);
+
+ if (nbytes < bsize)
+ goto done;
+ }
+
+ /* Handle leftovers */
+ do {
+ if (dst != src)
+ *dst = *src;
+
+ ctrblocks[0] = cpu_to_be64(ctrblk++);
+
+ blowfish_enc_blk_xor(ctx, (u8 *)dst, (u8 *)ctrblocks);
+
+ src += 1;
+ dst += 1;
+ } while ((nbytes -= bsize) >= bsize);
+
+done:
+ *(__be64 *)walk->iv = cpu_to_be64(ctrblk);
+ return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, BF_BLOCK_SIZE);
+
+ while ((nbytes = walk.nbytes) >= BF_BLOCK_SIZE) {
+ nbytes = __ctr_crypt(desc, &walk);
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ if (walk.nbytes) {
+ ctr_crypt_final(crypto_blkcipher_ctx(desc->tfm), &walk);
+ err = blkcipher_walk_done(desc, &walk, 0);
+ }
+
+ return err;
+}
+
+static struct crypto_alg blk_ctr_alg = {
+ .cra_name = "ctr(blowfish)",
+ .cra_driver_name = "ctr-blowfish-asm",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct bf_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(blk_ctr_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = BF_MIN_KEY_SIZE,
+ .max_keysize = BF_MAX_KEY_SIZE,
+ .ivsize = BF_BLOCK_SIZE,
+ .setkey = blowfish_setkey,
+ .encrypt = ctr_crypt,
+ .decrypt = ctr_crypt,
+ },
+ },
+};
+
+static int __init init(void)
+{
+ int err;
+
+ err = crypto_register_alg(&bf_alg);
+ if (err)
+ goto bf_err;
+ err = crypto_register_alg(&blk_ecb_alg);
+ if (err)
+ goto ecb_err;
+ err = crypto_register_alg(&blk_cbc_alg);
+ if (err)
+ goto cbc_err;
+ err = crypto_register_alg(&blk_ctr_alg);
+ if (err)
+ goto ctr_err;
+
+ return 0;
+
+ctr_err:
+ crypto_unregister_alg(&blk_cbc_alg);
+cbc_err:
+ crypto_unregister_alg(&blk_ecb_alg);
+ecb_err:
+ crypto_unregister_alg(&bf_alg);
+bf_err:
+ return err;
+}
+
+static void __exit fini(void)
+{
+ crypto_unregister_alg(&blk_ctr_alg);
+ crypto_unregister_alg(&blk_cbc_alg);
+ crypto_unregister_alg(&blk_ecb_alg);
+ crypto_unregister_alg(&bf_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher Algorithm, asm optimized");
+MODULE_ALIAS("blowfish");
+MODULE_ALIAS("blowfish-asm");
diff --git a/arch/x86/crypto/sha1_ssse3_asm.S b/arch/x86/crypto/sha1_ssse3_asm.S
new file mode 100644
index 000000000000..b2c2f57d70e8
--- /dev/null
+++ b/arch/x86/crypto/sha1_ssse3_asm.S
@@ -0,0 +1,558 @@
+/*
+ * This is a SIMD SHA-1 implementation. It requires the Intel(R) Supplemental
+ * SSE3 instruction set extensions introduced in Intel Core Microarchitecture
+ * processors. CPUs supporting Intel(R) AVX extensions will get an additional
+ * boost.
+ *
+ * This work was inspired by the vectorized implementation of Dean Gaudet.
+ * Additional information on it can be found at:
+ * http://www.arctic.org/~dean/crypto/sha1.html
+ *
+ * It was improved upon with more efficient vectorization of the message
+ * scheduling. This implementation has also been optimized for all current and
+ * several future generations of Intel CPUs.
+ *
+ * See this article for more information about the implementation details:
+ * http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1/
+ *
+ * Copyright (C) 2010, Intel Corp.
+ * Authors: Maxim Locktyukhin <maxim.locktyukhin@intel.com>
+ * Ronen Zohar <ronen.zohar@intel.com>
+ *
+ * Converted to AT&T syntax and adapted for inclusion in the Linux kernel:
+ * Author: Mathias Krause <minipli@googlemail.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.
+ */
+
+#define CTX %rdi // arg1
+#define BUF %rsi // arg2
+#define CNT %rdx // arg3
+
+#define REG_A %ecx
+#define REG_B %esi
+#define REG_C %edi
+#define REG_D %ebp
+#define REG_E %edx
+
+#define REG_T1 %eax
+#define REG_T2 %ebx
+
+#define K_BASE %r8
+#define HASH_PTR %r9
+#define BUFFER_PTR %r10
+#define BUFFER_END %r11
+
+#define W_TMP1 %xmm0
+#define W_TMP2 %xmm9
+
+#define W0 %xmm1
+#define W4 %xmm2
+#define W8 %xmm3
+#define W12 %xmm4
+#define W16 %xmm5
+#define W20 %xmm6
+#define W24 %xmm7
+#define W28 %xmm8
+
+#define XMM_SHUFB_BSWAP %xmm10
+
+/* we keep window of 64 w[i]+K pre-calculated values in a circular buffer */
+#define WK(t) (((t) & 15) * 4)(%rsp)
+#define W_PRECALC_AHEAD 16
+
+/*
+ * This macro implements the SHA-1 function's body for single 64-byte block
+ * param: function's name
+ */
+.macro SHA1_VECTOR_ASM name
+ .global \name
+ .type \name, @function
+ .align 32
+\name:
+ push %rbx
+ push %rbp
+ push %r12
+
+ mov %rsp, %r12
+ sub $64, %rsp # allocate workspace
+ and $~15, %rsp # align stack
+
+ mov CTX, HASH_PTR
+ mov BUF, BUFFER_PTR
+
+ shl $6, CNT # multiply by 64
+ add BUF, CNT
+ mov CNT, BUFFER_END
+
+ lea K_XMM_AR(%rip), K_BASE
+ xmm_mov BSWAP_SHUFB_CTL(%rip), XMM_SHUFB_BSWAP
+
+ SHA1_PIPELINED_MAIN_BODY
+
+ # cleanup workspace
+ mov $8, %ecx
+ mov %rsp, %rdi
+ xor %rax, %rax
+ rep stosq
+
+ mov %r12, %rsp # deallocate workspace
+
+ pop %r12
+ pop %rbp
+ pop %rbx
+ ret
+
+ .size \name, .-\name
+.endm
+
+/*
+ * This macro implements 80 rounds of SHA-1 for one 64-byte block
+ */
+.macro SHA1_PIPELINED_MAIN_BODY
+ INIT_REGALLOC
+
+ mov (HASH_PTR), A
+ mov 4(HASH_PTR), B
+ mov 8(HASH_PTR), C
+ mov 12(HASH_PTR), D
+ mov 16(HASH_PTR), E
+
+ .set i, 0
+ .rept W_PRECALC_AHEAD
+ W_PRECALC i
+ .set i, (i+1)
+ .endr
+
+.align 4
+1:
+ RR F1,A,B,C,D,E,0
+ RR F1,D,E,A,B,C,2
+ RR F1,B,C,D,E,A,4
+ RR F1,E,A,B,C,D,6
+ RR F1,C,D,E,A,B,8
+
+ RR F1,A,B,C,D,E,10
+ RR F1,D,E,A,B,C,12
+ RR F1,B,C,D,E,A,14
+ RR F1,E,A,B,C,D,16
+ RR F1,C,D,E,A,B,18
+
+ RR F2,A,B,C,D,E,20
+ RR F2,D,E,A,B,C,22
+ RR F2,B,C,D,E,A,24
+ RR F2,E,A,B,C,D,26
+ RR F2,C,D,E,A,B,28
+
+ RR F2,A,B,C,D,E,30
+ RR F2,D,E,A,B,C,32
+ RR F2,B,C,D,E,A,34
+ RR F2,E,A,B,C,D,36
+ RR F2,C,D,E,A,B,38
+
+ RR F3,A,B,C,D,E,40
+ RR F3,D,E,A,B,C,42
+ RR F3,B,C,D,E,A,44
+ RR F3,E,A,B,C,D,46
+ RR F3,C,D,E,A,B,48
+
+ RR F3,A,B,C,D,E,50
+ RR F3,D,E,A,B,C,52
+ RR F3,B,C,D,E,A,54
+ RR F3,E,A,B,C,D,56
+ RR F3,C,D,E,A,B,58
+
+ add $64, BUFFER_PTR # move to the next 64-byte block
+ cmp BUFFER_END, BUFFER_PTR # if the current is the last one use
+ cmovae K_BASE, BUFFER_PTR # dummy source to avoid buffer overrun
+
+ RR F4,A,B,C,D,E,60
+ RR F4,D,E,A,B,C,62
+ RR F4,B,C,D,E,A,64
+ RR F4,E,A,B,C,D,66
+ RR F4,C,D,E,A,B,68
+
+ RR F4,A,B,C,D,E,70
+ RR F4,D,E,A,B,C,72
+ RR F4,B,C,D,E,A,74
+ RR F4,E,A,B,C,D,76
+ RR F4,C,D,E,A,B,78
+
+ UPDATE_HASH (HASH_PTR), A
+ UPDATE_HASH 4(HASH_PTR), B
+ UPDATE_HASH 8(HASH_PTR), C
+ UPDATE_HASH 12(HASH_PTR), D
+ UPDATE_HASH 16(HASH_PTR), E
+
+ RESTORE_RENAMED_REGS
+ cmp K_BASE, BUFFER_PTR # K_BASE means, we reached the end
+ jne 1b
+.endm
+
+.macro INIT_REGALLOC
+ .set A, REG_A
+ .set B, REG_B
+ .set C, REG_C
+ .set D, REG_D
+ .set E, REG_E
+ .set T1, REG_T1
+ .set T2, REG_T2
+.endm
+
+.macro RESTORE_RENAMED_REGS
+ # order is important (REG_C is where it should be)
+ mov B, REG_B
+ mov D, REG_D
+ mov A, REG_A
+ mov E, REG_E
+.endm
+
+.macro SWAP_REG_NAMES a, b
+ .set _T, \a
+ .set \a, \b
+ .set \b, _T
+.endm
+
+.macro F1 b, c, d
+ mov \c, T1
+ SWAP_REG_NAMES \c, T1
+ xor \d, T1
+ and \b, T1
+ xor \d, T1
+.endm
+
+.macro F2 b, c, d
+ mov \d, T1
+ SWAP_REG_NAMES \d, T1
+ xor \c, T1
+ xor \b, T1
+.endm
+
+.macro F3 b, c ,d
+ mov \c, T1
+ SWAP_REG_NAMES \c, T1
+ mov \b, T2
+ or \b, T1
+ and \c, T2
+ and \d, T1
+ or T2, T1
+.endm
+
+.macro F4 b, c, d
+ F2 \b, \c, \d
+.endm
+
+.macro UPDATE_HASH hash, val
+ add \hash, \val
+ mov \val, \hash
+.endm
+
+/*
+ * RR does two rounds of SHA-1 back to back with W[] pre-calc
+ * t1 = F(b, c, d); e += w(i)
+ * e += t1; b <<= 30; d += w(i+1);
+ * t1 = F(a, b, c);
+ * d += t1; a <<= 5;
+ * e += a;
+ * t1 = e; a >>= 7;
+ * t1 <<= 5;
+ * d += t1;
+ */
+.macro RR F, a, b, c, d, e, round
+ add WK(\round), \e
+ \F \b, \c, \d # t1 = F(b, c, d);
+ W_PRECALC (\round + W_PRECALC_AHEAD)
+ rol $30, \b
+ add T1, \e
+ add WK(\round + 1), \d
+
+ \F \a, \b, \c
+ W_PRECALC (\round + W_PRECALC_AHEAD + 1)
+ rol $5, \a
+ add \a, \e
+ add T1, \d
+ ror $7, \a # (a <<r 5) >>r 7) => a <<r 30)
+
+ mov \e, T1
+ SWAP_REG_NAMES \e, T1
+
+ rol $5, T1
+ add T1, \d
+
+ # write: \a, \b
+ # rotate: \a<=\d, \b<=\e, \c<=\a, \d<=\b, \e<=\c
+.endm
+
+.macro W_PRECALC r
+ .set i, \r
+
+ .if (i < 20)
+ .set K_XMM, 0
+ .elseif (i < 40)
+ .set K_XMM, 16
+ .elseif (i < 60)
+ .set K_XMM, 32
+ .elseif (i < 80)
+ .set K_XMM, 48
+ .endif
+
+ .if ((i < 16) || ((i >= 80) && (i < (80 + W_PRECALC_AHEAD))))
+ .set i, ((\r) % 80) # pre-compute for the next iteration
+ .if (i == 0)
+ W_PRECALC_RESET
+ .endif
+ W_PRECALC_00_15
+ .elseif (i<32)
+ W_PRECALC_16_31
+ .elseif (i < 80) // rounds 32-79
+ W_PRECALC_32_79
+ .endif
+.endm
+
+.macro W_PRECALC_RESET
+ .set W, W0
+ .set W_minus_04, W4
+ .set W_minus_08, W8
+ .set W_minus_12, W12
+ .set W_minus_16, W16
+ .set W_minus_20, W20
+ .set W_minus_24, W24
+ .set W_minus_28, W28
+ .set W_minus_32, W
+.endm
+
+.macro W_PRECALC_ROTATE
+ .set W_minus_32, W_minus_28
+ .set W_minus_28, W_minus_24
+ .set W_minus_24, W_minus_20
+ .set W_minus_20, W_minus_16
+ .set W_minus_16, W_minus_12
+ .set W_minus_12, W_minus_08
+ .set W_minus_08, W_minus_04
+ .set W_minus_04, W
+ .set W, W_minus_32
+.endm
+
+.macro W_PRECALC_SSSE3
+
+.macro W_PRECALC_00_15
+ W_PRECALC_00_15_SSSE3
+.endm
+.macro W_PRECALC_16_31
+ W_PRECALC_16_31_SSSE3
+.endm
+.macro W_PRECALC_32_79
+ W_PRECALC_32_79_SSSE3
+.endm
+
+/* message scheduling pre-compute for rounds 0-15 */
+.macro W_PRECALC_00_15_SSSE3
+ .if ((i & 3) == 0)
+ movdqu (i*4)(BUFFER_PTR), W_TMP1
+ .elseif ((i & 3) == 1)
+ pshufb XMM_SHUFB_BSWAP, W_TMP1
+ movdqa W_TMP1, W
+ .elseif ((i & 3) == 2)
+ paddd (K_BASE), W_TMP1
+ .elseif ((i & 3) == 3)
+ movdqa W_TMP1, WK(i&~3)
+ W_PRECALC_ROTATE
+ .endif
+.endm
+
+/* message scheduling pre-compute for rounds 16-31
+ *
+ * - calculating last 32 w[i] values in 8 XMM registers
+ * - pre-calculate K+w[i] values and store to mem, for later load by ALU add
+ * instruction
+ *
+ * some "heavy-lifting" vectorization for rounds 16-31 due to w[i]->w[i-3]
+ * dependency, but improves for 32-79
+ */
+.macro W_PRECALC_16_31_SSSE3
+ # blended scheduling of vector and scalar instruction streams, one 4-wide
+ # vector iteration / 4 scalar rounds
+ .if ((i & 3) == 0)
+ movdqa W_minus_12, W
+ palignr $8, W_minus_16, W # w[i-14]
+ movdqa W_minus_04, W_TMP1
+ psrldq $4, W_TMP1 # w[i-3]
+ pxor W_minus_08, W
+ .elseif ((i & 3) == 1)
+ pxor W_minus_16, W_TMP1
+ pxor W_TMP1, W
+ movdqa W, W_TMP2
+ movdqa W, W_TMP1
+ pslldq $12, W_TMP2
+ .elseif ((i & 3) == 2)
+ psrld $31, W
+ pslld $1, W_TMP1
+ por W, W_TMP1
+ movdqa W_TMP2, W
+ psrld $30, W_TMP2
+ pslld $2, W
+ .elseif ((i & 3) == 3)
+ pxor W, W_TMP1
+ pxor W_TMP2, W_TMP1
+ movdqa W_TMP1, W
+ paddd K_XMM(K_BASE), W_TMP1
+ movdqa W_TMP1, WK(i&~3)
+ W_PRECALC_ROTATE
+ .endif
+.endm
+
+/* message scheduling pre-compute for rounds 32-79
+ *
+ * in SHA-1 specification: w[i] = (w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]) rol 1
+ * instead we do equal: w[i] = (w[i-6] ^ w[i-16] ^ w[i-28] ^ w[i-32]) rol 2
+ * allows more efficient vectorization since w[i]=>w[i-3] dependency is broken
+ */
+.macro W_PRECALC_32_79_SSSE3
+ .if ((i & 3) == 0)
+ movdqa W_minus_04, W_TMP1
+ pxor W_minus_28, W # W is W_minus_32 before xor
+ palignr $8, W_minus_08, W_TMP1
+ .elseif ((i & 3) == 1)
+ pxor W_minus_16, W
+ pxor W_TMP1, W
+ movdqa W, W_TMP1
+ .elseif ((i & 3) == 2)
+ psrld $30, W
+ pslld $2, W_TMP1
+ por W, W_TMP1
+ .elseif ((i & 3) == 3)
+ movdqa W_TMP1, W
+ paddd K_XMM(K_BASE), W_TMP1
+ movdqa W_TMP1, WK(i&~3)
+ W_PRECALC_ROTATE
+ .endif
+.endm
+
+.endm // W_PRECALC_SSSE3
+
+
+#define K1 0x5a827999
+#define K2 0x6ed9eba1
+#define K3 0x8f1bbcdc
+#define K4 0xca62c1d6
+
+.section .rodata
+.align 16
+
+K_XMM_AR:
+ .long K1, K1, K1, K1
+ .long K2, K2, K2, K2
+ .long K3, K3, K3, K3
+ .long K4, K4, K4, K4
+
+BSWAP_SHUFB_CTL:
+ .long 0x00010203
+ .long 0x04050607
+ .long 0x08090a0b
+ .long 0x0c0d0e0f
+
+
+.section .text
+
+W_PRECALC_SSSE3
+.macro xmm_mov a, b
+ movdqu \a,\b
+.endm
+
+/* SSSE3 optimized implementation:
+ * extern "C" void sha1_transform_ssse3(u32 *digest, const char *data, u32 *ws,
+ * unsigned int rounds);
+ */
+SHA1_VECTOR_ASM sha1_transform_ssse3
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+
+.macro W_PRECALC_AVX
+
+.purgem W_PRECALC_00_15
+.macro W_PRECALC_00_15
+ W_PRECALC_00_15_AVX
+.endm
+.purgem W_PRECALC_16_31
+.macro W_PRECALC_16_31
+ W_PRECALC_16_31_AVX
+.endm
+.purgem W_PRECALC_32_79
+.macro W_PRECALC_32_79
+ W_PRECALC_32_79_AVX
+.endm
+
+.macro W_PRECALC_00_15_AVX
+ .if ((i & 3) == 0)
+ vmovdqu (i*4)(BUFFER_PTR), W_TMP1
+ .elseif ((i & 3) == 1)
+ vpshufb XMM_SHUFB_BSWAP, W_TMP1, W
+ .elseif ((i & 3) == 2)
+ vpaddd (K_BASE), W, W_TMP1
+ .elseif ((i & 3) == 3)
+ vmovdqa W_TMP1, WK(i&~3)
+ W_PRECALC_ROTATE
+ .endif
+.endm
+
+.macro W_PRECALC_16_31_AVX
+ .if ((i & 3) == 0)
+ vpalignr $8, W_minus_16, W_minus_12, W # w[i-14]
+ vpsrldq $4, W_minus_04, W_TMP1 # w[i-3]
+ vpxor W_minus_08, W, W
+ vpxor W_minus_16, W_TMP1, W_TMP1
+ .elseif ((i & 3) == 1)
+ vpxor W_TMP1, W, W
+ vpslldq $12, W, W_TMP2
+ vpslld $1, W, W_TMP1
+ .elseif ((i & 3) == 2)
+ vpsrld $31, W, W
+ vpor W, W_TMP1, W_TMP1
+ vpslld $2, W_TMP2, W
+ vpsrld $30, W_TMP2, W_TMP2
+ .elseif ((i & 3) == 3)
+ vpxor W, W_TMP1, W_TMP1
+ vpxor W_TMP2, W_TMP1, W
+ vpaddd K_XMM(K_BASE), W, W_TMP1
+ vmovdqu W_TMP1, WK(i&~3)
+ W_PRECALC_ROTATE
+ .endif
+.endm
+
+.macro W_PRECALC_32_79_AVX
+ .if ((i & 3) == 0)
+ vpalignr $8, W_minus_08, W_minus_04, W_TMP1
+ vpxor W_minus_28, W, W # W is W_minus_32 before xor
+ .elseif ((i & 3) == 1)
+ vpxor W_minus_16, W_TMP1, W_TMP1
+ vpxor W_TMP1, W, W
+ .elseif ((i & 3) == 2)
+ vpslld $2, W, W_TMP1
+ vpsrld $30, W, W
+ vpor W, W_TMP1, W
+ .elseif ((i & 3) == 3)
+ vpaddd K_XMM(K_BASE), W, W_TMP1
+ vmovdqu W_TMP1, WK(i&~3)
+ W_PRECALC_ROTATE
+ .endif
+.endm
+
+.endm // W_PRECALC_AVX
+
+W_PRECALC_AVX
+.purgem xmm_mov
+.macro xmm_mov a, b
+ vmovdqu \a,\b
+.endm
+
+
+/* AVX optimized implementation:
+ * extern "C" void sha1_transform_avx(u32 *digest, const char *data, u32 *ws,
+ * unsigned int rounds);
+ */
+SHA1_VECTOR_ASM sha1_transform_avx
+
+#endif
diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c
new file mode 100644
index 000000000000..f916499d0abe
--- /dev/null
+++ b/arch/x86/crypto/sha1_ssse3_glue.c
@@ -0,0 +1,240 @@
+/*
+ * Cryptographic API.
+ *
+ * Glue code for the SHA1 Secure Hash Algorithm assembler implementation using
+ * Supplemental SSE3 instructions.
+ *
+ * This file is based on sha1_generic.c
+ *
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) Mathias Krause <minipli@googlemail.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.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+#include <asm/i387.h>
+#include <asm/xcr.h>
+#include <asm/xsave.h>
+
+
+asmlinkage void sha1_transform_ssse3(u32 *digest, const char *data,
+ unsigned int rounds);
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+asmlinkage void sha1_transform_avx(u32 *digest, const char *data,
+ unsigned int rounds);
+#endif
+
+static asmlinkage void (*sha1_transform_asm)(u32 *, const char *, unsigned int);
+
+
+static int sha1_ssse3_init(struct shash_desc *desc)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+
+ *sctx = (struct sha1_state){
+ .state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
+ };
+
+ return 0;
+}
+
+static int __sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len, unsigned int partial)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+ unsigned int done = 0;
+
+ sctx->count += len;
+
+ if (partial) {
+ done = SHA1_BLOCK_SIZE - partial;
+ memcpy(sctx->buffer + partial, data, done);
+ sha1_transform_asm(sctx->state, sctx->buffer, 1);
+ }
+
+ if (len - done >= SHA1_BLOCK_SIZE) {
+ const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
+
+ sha1_transform_asm(sctx->state, data + done, rounds);
+ done += rounds * SHA1_BLOCK_SIZE;
+ }
+
+ memcpy(sctx->buffer, data + done, len - done);
+
+ return 0;
+}
+
+static int sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+ unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+ int res;
+
+ /* Handle the fast case right here */
+ if (partial + len < SHA1_BLOCK_SIZE) {
+ sctx->count += len;
+ memcpy(sctx->buffer + partial, data, len);
+
+ return 0;
+ }
+
+ if (!irq_fpu_usable()) {
+ res = crypto_sha1_update(desc, data, len);
+ } else {
+ kernel_fpu_begin();
+ res = __sha1_ssse3_update(desc, data, len, partial);
+ kernel_fpu_end();
+ }
+
+ return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha1_ssse3_final(struct shash_desc *desc, u8 *out)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+ unsigned int i, index, padlen;
+ __be32 *dst = (__be32 *)out;
+ __be64 bits;
+ static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
+
+ bits = cpu_to_be64(sctx->count << 3);
+
+ /* Pad out to 56 mod 64 and append length */
+ index = sctx->count % SHA1_BLOCK_SIZE;
+ padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
+ if (!irq_fpu_usable()) {
+ crypto_sha1_update(desc, padding, padlen);
+ crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits));
+ } else {
+ kernel_fpu_begin();
+ /* We need to fill a whole block for __sha1_ssse3_update() */
+ if (padlen <= 56) {
+ sctx->count += padlen;
+ memcpy(sctx->buffer + index, padding, padlen);
+ } else {
+ __sha1_ssse3_update(desc, padding, padlen, index);
+ }
+ __sha1_ssse3_update(desc, (const u8 *)&bits, sizeof(bits), 56);
+ kernel_fpu_end();
+ }
+
+ /* Store state in digest */
+ for (i = 0; i < 5; i++)
+ dst[i] = cpu_to_be32(sctx->state[i]);
+
+ /* Wipe context */
+ memset(sctx, 0, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha1_ssse3_export(struct shash_desc *desc, void *out)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(out, sctx, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha1_ssse3_import(struct shash_desc *desc, const void *in)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(sctx, in, sizeof(*sctx));
+
+ return 0;
+}
+
+static struct shash_alg alg = {
+ .digestsize = SHA1_DIGEST_SIZE,
+ .init = sha1_ssse3_init,
+ .update = sha1_ssse3_update,
+ .final = sha1_ssse3_final,
+ .export = sha1_ssse3_export,
+ .import = sha1_ssse3_import,
+ .descsize = sizeof(struct sha1_state),
+ .statesize = sizeof(struct sha1_state),
+ .base = {
+ .cra_name = "sha1",
+ .cra_driver_name= "sha1-ssse3",
+ .cra_priority = 150,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+};
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+static bool __init avx_usable(void)
+{
+ u64 xcr0;
+
+ if (!cpu_has_avx || !cpu_has_osxsave)
+ return false;
+
+ xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
+ if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
+ pr_info("AVX detected but unusable.\n");
+
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+static int __init sha1_ssse3_mod_init(void)
+{
+ /* test for SSSE3 first */
+ if (cpu_has_ssse3)
+ sha1_transform_asm = sha1_transform_ssse3;
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+ /* allow AVX to override SSSE3, it's a little faster */
+ if (avx_usable())
+ sha1_transform_asm = sha1_transform_avx;
+#endif
+
+ if (sha1_transform_asm) {
+ pr_info("Using %s optimized SHA-1 implementation\n",
+ sha1_transform_asm == sha1_transform_ssse3 ? "SSSE3"
+ : "AVX");
+ return crypto_register_shash(&alg);
+ }
+ pr_info("Neither AVX nor SSSE3 is available/usable.\n");
+
+ return -ENODEV;
+}
+
+static void __exit sha1_ssse3_mod_fini(void)
+{
+ crypto_unregister_shash(&alg);
+}
+
+module_init(sha1_ssse3_mod_init);
+module_exit(sha1_ssse3_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, Supplemental SSE3 accelerated");
+
+MODULE_ALIAS("sha1");
diff --git a/arch/x86/crypto/twofish-i586-asm_32.S b/arch/x86/crypto/twofish-i586-asm_32.S
index 575331cb2a8a..658af4bb35c9 100644
--- a/arch/x86/crypto/twofish-i586-asm_32.S
+++ b/arch/x86/crypto/twofish-i586-asm_32.S
@@ -26,7 +26,7 @@
#define in_blk 12 /* input byte array address parameter*/
#define out_blk 8 /* output byte array address parameter*/
-#define tfm 4 /* Twofish context structure */
+#define ctx 4 /* Twofish context structure */
#define a_offset 0
#define b_offset 4
@@ -229,8 +229,8 @@ twofish_enc_blk:
push %esi
push %edi
- mov tfm + 16(%esp), %ebp /* abuse the base pointer: set new base bointer to the crypto tfm */
- add $crypto_tfm_ctx_offset, %ebp /* ctx address */
+ mov ctx + 16(%esp), %ebp /* abuse the base pointer: set new base
+ * pointer to the ctx address */
mov in_blk+16(%esp),%edi /* input address in edi */
mov (%edi), %eax
@@ -285,8 +285,8 @@ twofish_dec_blk:
push %edi
- mov tfm + 16(%esp), %ebp /* abuse the base pointer: set new base bointer to the crypto tfm */
- add $crypto_tfm_ctx_offset, %ebp /* ctx address */
+ mov ctx + 16(%esp), %ebp /* abuse the base pointer: set new base
+ * pointer to the ctx address */
mov in_blk+16(%esp),%edi /* input address in edi */
mov (%edi), %eax
diff --git a/arch/x86/crypto/twofish-x86_64-asm_64-3way.S b/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
new file mode 100644
index 000000000000..5b012a2c5119
--- /dev/null
+++ b/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
@@ -0,0 +1,316 @@
+/*
+ * Twofish Cipher 3-way parallel algorithm (x86_64)
+ *
+ * Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ */
+
+.file "twofish-x86_64-asm-3way.S"
+.text
+
+/* structure of crypto context */
+#define s0 0
+#define s1 1024
+#define s2 2048
+#define s3 3072
+#define w 4096
+#define k 4128
+
+/**********************************************************************
+ 3-way twofish
+ **********************************************************************/
+#define CTX %rdi
+#define RIO %rdx
+
+#define RAB0 %rax
+#define RAB1 %rbx
+#define RAB2 %rcx
+
+#define RAB0d %eax
+#define RAB1d %ebx
+#define RAB2d %ecx
+
+#define RAB0bh %ah
+#define RAB1bh %bh
+#define RAB2bh %ch
+
+#define RAB0bl %al
+#define RAB1bl %bl
+#define RAB2bl %cl
+
+#define RCD0 %r8
+#define RCD1 %r9
+#define RCD2 %r10
+
+#define RCD0d %r8d
+#define RCD1d %r9d
+#define RCD2d %r10d
+
+#define RX0 %rbp
+#define RX1 %r11
+#define RX2 %r12
+
+#define RX0d %ebp
+#define RX1d %r11d
+#define RX2d %r12d
+
+#define RY0 %r13
+#define RY1 %r14
+#define RY2 %r15
+
+#define RY0d %r13d
+#define RY1d %r14d
+#define RY2d %r15d
+
+#define RT0 %rdx
+#define RT1 %rsi
+
+#define RT0d %edx
+#define RT1d %esi
+
+#define do16bit_ror(rot, op1, op2, T0, T1, tmp1, tmp2, ab, dst) \
+ movzbl ab ## bl, tmp2 ## d; \
+ movzbl ab ## bh, tmp1 ## d; \
+ rorq $(rot), ab; \
+ op1##l T0(CTX, tmp2, 4), dst ## d; \
+ op2##l T1(CTX, tmp1, 4), dst ## d;
+
+/*
+ * Combined G1 & G2 function. Reordered with help of rotates to have moves
+ * at begining.
+ */
+#define g1g2_3(ab, cd, Tx0, Tx1, Tx2, Tx3, Ty0, Ty1, Ty2, Ty3, x, y) \
+ /* G1,1 && G2,1 */ \
+ do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 0, ab ## 0, x ## 0); \
+ do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 0, ab ## 0, y ## 0); \
+ \
+ do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 1, ab ## 1, x ## 1); \
+ do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 1, ab ## 1, y ## 1); \
+ \
+ do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 2, ab ## 2, x ## 2); \
+ do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 2, ab ## 2, y ## 2); \
+ \
+ /* G1,2 && G2,2 */ \
+ do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 0, x ## 0); \
+ do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 0, y ## 0); \
+ xchgq cd ## 0, ab ## 0; \
+ \
+ do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 1, x ## 1); \
+ do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 1, y ## 1); \
+ xchgq cd ## 1, ab ## 1; \
+ \
+ do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 2, x ## 2); \
+ do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 2, y ## 2); \
+ xchgq cd ## 2, ab ## 2;
+
+#define enc_round_end(ab, x, y, n) \
+ addl y ## d, x ## d; \
+ addl x ## d, y ## d; \
+ addl k+4*(2*(n))(CTX), x ## d; \
+ xorl ab ## d, x ## d; \
+ addl k+4*(2*(n)+1)(CTX), y ## d; \
+ shrq $32, ab; \
+ roll $1, ab ## d; \
+ xorl y ## d, ab ## d; \
+ shlq $32, ab; \
+ rorl $1, x ## d; \
+ orq x, ab;
+
+#define dec_round_end(ba, x, y, n) \
+ addl y ## d, x ## d; \
+ addl x ## d, y ## d; \
+ addl k+4*(2*(n))(CTX), x ## d; \
+ addl k+4*(2*(n)+1)(CTX), y ## d; \
+ xorl ba ## d, y ## d; \
+ shrq $32, ba; \
+ roll $1, ba ## d; \
+ xorl x ## d, ba ## d; \
+ shlq $32, ba; \
+ rorl $1, y ## d; \
+ orq y, ba;
+
+#define encrypt_round3(ab, cd, n) \
+ g1g2_3(ab, cd, s0, s1, s2, s3, s0, s1, s2, s3, RX, RY); \
+ \
+ enc_round_end(ab ## 0, RX0, RY0, n); \
+ enc_round_end(ab ## 1, RX1, RY1, n); \
+ enc_round_end(ab ## 2, RX2, RY2, n);
+
+#define decrypt_round3(ba, dc, n) \
+ g1g2_3(ba, dc, s1, s2, s3, s0, s3, s0, s1, s2, RY, RX); \
+ \
+ dec_round_end(ba ## 0, RX0, RY0, n); \
+ dec_round_end(ba ## 1, RX1, RY1, n); \
+ dec_round_end(ba ## 2, RX2, RY2, n);
+
+#define encrypt_cycle3(ab, cd, n) \
+ encrypt_round3(ab, cd, n*2); \
+ encrypt_round3(ab, cd, (n*2)+1);
+
+#define decrypt_cycle3(ba, dc, n) \
+ decrypt_round3(ba, dc, (n*2)+1); \
+ decrypt_round3(ba, dc, (n*2));
+
+#define inpack3(in, n, xy, m) \
+ movq 4*(n)(in), xy ## 0; \
+ xorq w+4*m(CTX), xy ## 0; \
+ \
+ movq 4*(4+(n))(in), xy ## 1; \
+ xorq w+4*m(CTX), xy ## 1; \
+ \
+ movq 4*(8+(n))(in), xy ## 2; \
+ xorq w+4*m(CTX), xy ## 2;
+
+#define outunpack3(op, out, n, xy, m) \
+ xorq w+4*m(CTX), xy ## 0; \
+ op ## q xy ## 0, 4*(n)(out); \
+ \
+ xorq w+4*m(CTX), xy ## 1; \
+ op ## q xy ## 1, 4*(4+(n))(out); \
+ \
+ xorq w+4*m(CTX), xy ## 2; \
+ op ## q xy ## 2, 4*(8+(n))(out);
+
+#define inpack_enc3() \
+ inpack3(RIO, 0, RAB, 0); \
+ inpack3(RIO, 2, RCD, 2);
+
+#define outunpack_enc3(op) \
+ outunpack3(op, RIO, 2, RAB, 6); \
+ outunpack3(op, RIO, 0, RCD, 4);
+
+#define inpack_dec3() \
+ inpack3(RIO, 0, RAB, 4); \
+ rorq $32, RAB0; \
+ rorq $32, RAB1; \
+ rorq $32, RAB2; \
+ inpack3(RIO, 2, RCD, 6); \
+ rorq $32, RCD0; \
+ rorq $32, RCD1; \
+ rorq $32, RCD2;
+
+#define outunpack_dec3() \
+ rorq $32, RCD0; \
+ rorq $32, RCD1; \
+ rorq $32, RCD2; \
+ outunpack3(mov, RIO, 0, RCD, 0); \
+ rorq $32, RAB0; \
+ rorq $32, RAB1; \
+ rorq $32, RAB2; \
+ outunpack3(mov, RIO, 2, RAB, 2);
+
+.align 8
+.global __twofish_enc_blk_3way
+.type __twofish_enc_blk_3way,@function;
+
+__twofish_enc_blk_3way:
+ /* input:
+ * %rdi: ctx, CTX
+ * %rsi: dst
+ * %rdx: src, RIO
+ * %rcx: bool, if true: xor output
+ */
+ pushq %r15;
+ pushq %r14;
+ pushq %r13;
+ pushq %r12;
+ pushq %rbp;
+ pushq %rbx;
+
+ pushq %rcx; /* bool xor */
+ pushq %rsi; /* dst */
+
+ inpack_enc3();
+
+ encrypt_cycle3(RAB, RCD, 0);
+ encrypt_cycle3(RAB, RCD, 1);
+ encrypt_cycle3(RAB, RCD, 2);
+ encrypt_cycle3(RAB, RCD, 3);
+ encrypt_cycle3(RAB, RCD, 4);
+ encrypt_cycle3(RAB, RCD, 5);
+ encrypt_cycle3(RAB, RCD, 6);
+ encrypt_cycle3(RAB, RCD, 7);
+
+ popq RIO; /* dst */
+ popq %rbp; /* bool xor */
+
+ testb %bpl, %bpl;
+ jnz __enc_xor3;
+
+ outunpack_enc3(mov);
+
+ popq %rbx;
+ popq %rbp;
+ popq %r12;
+ popq %r13;
+ popq %r14;
+ popq %r15;
+ ret;
+
+__enc_xor3:
+ outunpack_enc3(xor);
+
+ popq %rbx;
+ popq %rbp;
+ popq %r12;
+ popq %r13;
+ popq %r14;
+ popq %r15;
+ ret;
+
+.global twofish_dec_blk_3way
+.type twofish_dec_blk_3way,@function;
+
+twofish_dec_blk_3way:
+ /* input:
+ * %rdi: ctx, CTX
+ * %rsi: dst
+ * %rdx: src, RIO
+ */
+ pushq %r15;
+ pushq %r14;
+ pushq %r13;
+ pushq %r12;
+ pushq %rbp;
+ pushq %rbx;
+
+ pushq %rsi; /* dst */
+
+ inpack_dec3();
+
+ decrypt_cycle3(RAB, RCD, 7);
+ decrypt_cycle3(RAB, RCD, 6);
+ decrypt_cycle3(RAB, RCD, 5);
+ decrypt_cycle3(RAB, RCD, 4);
+ decrypt_cycle3(RAB, RCD, 3);
+ decrypt_cycle3(RAB, RCD, 2);
+ decrypt_cycle3(RAB, RCD, 1);
+ decrypt_cycle3(RAB, RCD, 0);
+
+ popq RIO; /* dst */
+
+ outunpack_dec3();
+
+ popq %rbx;
+ popq %rbp;
+ popq %r12;
+ popq %r13;
+ popq %r14;
+ popq %r15;
+ ret;
+
diff --git a/arch/x86/crypto/twofish-x86_64-asm_64.S b/arch/x86/crypto/twofish-x86_64-asm_64.S
index 573aa102542e..7bcf3fcc3668 100644
--- a/arch/x86/crypto/twofish-x86_64-asm_64.S
+++ b/arch/x86/crypto/twofish-x86_64-asm_64.S
@@ -221,10 +221,9 @@
twofish_enc_blk:
pushq R1
- /* %rdi contains the crypto tfm address */
+ /* %rdi contains the ctx address */
/* %rsi contains the output address */
/* %rdx contains the input address */
- add $crypto_tfm_ctx_offset, %rdi /* set ctx address */
/* ctx address is moved to free one non-rex register
as target for the 8bit high operations */
mov %rdi, %r11
@@ -274,10 +273,9 @@ twofish_enc_blk:
twofish_dec_blk:
pushq R1
- /* %rdi contains the crypto tfm address */
+ /* %rdi contains the ctx address */
/* %rsi contains the output address */
/* %rdx contains the input address */
- add $crypto_tfm_ctx_offset, %rdi /* set ctx address */
/* ctx address is moved to free one non-rex register
as target for the 8bit high operations */
mov %rdi, %r11
diff --git a/arch/x86/crypto/twofish_glue.c b/arch/x86/crypto/twofish_glue.c
index cefaf8b9aa18..dc6b3fb817fc 100644
--- a/arch/x86/crypto/twofish_glue.c
+++ b/arch/x86/crypto/twofish_glue.c
@@ -44,17 +44,21 @@
#include <linux/module.h>
#include <linux/types.h>
-asmlinkage void twofish_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-asmlinkage void twofish_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
+ const u8 *src);
+EXPORT_SYMBOL_GPL(twofish_enc_blk);
+asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
+ const u8 *src);
+EXPORT_SYMBOL_GPL(twofish_dec_blk);
static void twofish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
- twofish_enc_blk(tfm, dst, src);
+ twofish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
}
static void twofish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
- twofish_dec_blk(tfm, dst, src);
+ twofish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
}
static struct crypto_alg alg = {
diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c
new file mode 100644
index 000000000000..5ede9c444c3e
--- /dev/null
+++ b/arch/x86/crypto/twofish_glue_3way.c
@@ -0,0 +1,472 @@
+/*
+ * Glue Code for 3-way parallel assembler optimized version of Twofish
+ *
+ * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * CTR part based on code (crypto/ctr.c) by:
+ * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ */
+
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/twofish.h>
+#include <crypto/b128ops.h>
+
+/* regular block cipher functions from twofish_x86_64 module */
+asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
+ const u8 *src);
+asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
+ const u8 *src);
+
+/* 3-way parallel cipher functions */
+asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+ const u8 *src, bool xor);
+asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+ const u8 *src);
+
+static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+ const u8 *src)
+{
+ __twofish_enc_blk_3way(ctx, dst, src, false);
+}
+
+static inline void twofish_enc_blk_xor_3way(struct twofish_ctx *ctx, u8 *dst,
+ const u8 *src)
+{
+ __twofish_enc_blk_3way(ctx, dst, src, true);
+}
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+ void (*fn)(struct twofish_ctx *, u8 *, const u8 *),
+ void (*fn_3way)(struct twofish_ctx *, u8 *, const u8 *))
+{
+ struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = TF_BLOCK_SIZE;
+ unsigned int nbytes;
+ int err;
+
+ err = blkcipher_walk_virt(desc, walk);
+
+ while ((nbytes = walk->nbytes)) {
+ u8 *wsrc = walk->src.virt.addr;
+ u8 *wdst = walk->dst.virt.addr;
+
+ /* Process three block batch */
+ if (nbytes >= bsize * 3) {
+ do {
+ fn_3way(ctx, wdst, wsrc);
+
+ wsrc += bsize * 3;
+ wdst += bsize * 3;
+ nbytes -= bsize * 3;
+ } while (nbytes >= bsize * 3);
+
+ if (nbytes < bsize)
+ goto done;
+ }
+
+ /* Handle leftovers */
+ do {
+ fn(ctx, wdst, wsrc);
+
+ wsrc += bsize;
+ wdst += bsize;
+ nbytes -= bsize;
+ } while (nbytes >= bsize);
+
+done:
+ err = blkcipher_walk_done(desc, walk, nbytes);
+ }
+
+ return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_crypt(desc, &walk, twofish_enc_blk, twofish_enc_blk_3way);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_crypt(desc, &walk, twofish_dec_blk, twofish_dec_blk_3way);
+}
+
+static struct crypto_alg blk_ecb_alg = {
+ .cra_name = "ecb(twofish)",
+ .cra_driver_name = "ecb-twofish-3way",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = TF_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct twofish_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(blk_ecb_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = TF_MIN_KEY_SIZE,
+ .max_keysize = TF_MAX_KEY_SIZE,
+ .setkey = twofish_setkey,
+ .encrypt = ecb_encrypt,
+ .decrypt = ecb_decrypt,
+ },
+ },
+};
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk)
+{
+ struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = TF_BLOCK_SIZE;
+ unsigned int nbytes = walk->nbytes;
+ u128 *src = (u128 *)walk->src.virt.addr;
+ u128 *dst = (u128 *)walk->dst.virt.addr;
+ u128 *iv = (u128 *)walk->iv;
+
+ do {
+ u128_xor(dst, src, iv);
+ twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
+ iv = dst;
+
+ src += 1;
+ dst += 1;
+ nbytes -= bsize;
+ } while (nbytes >= bsize);
+
+ u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv);
+ return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+
+ while ((nbytes = walk.nbytes)) {
+ nbytes = __cbc_encrypt(desc, &walk);
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk)
+{
+ struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = TF_BLOCK_SIZE;
+ unsigned int nbytes = walk->nbytes;
+ u128 *src = (u128 *)walk->src.virt.addr;
+ u128 *dst = (u128 *)walk->dst.virt.addr;
+ u128 ivs[3 - 1];
+ u128 last_iv;
+
+ /* Start of the last block. */
+ src += nbytes / bsize - 1;
+ dst += nbytes / bsize - 1;
+
+ last_iv = *src;
+
+ /* Process three block batch */
+ if (nbytes >= bsize * 3) {
+ do {
+ nbytes -= bsize * (3 - 1);
+ src -= 3 - 1;
+ dst -= 3 - 1;
+
+ ivs[0] = src[0];
+ ivs[1] = src[1];
+
+ twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
+
+ u128_xor(dst + 1, dst + 1, ivs + 0);
+ u128_xor(dst + 2, dst + 2, ivs + 1);
+
+ nbytes -= bsize;
+ if (nbytes < bsize)
+ goto done;
+
+ u128_xor(dst, dst, src - 1);
+ src -= 1;
+ dst -= 1;
+ } while (nbytes >= bsize * 3);
+
+ if (nbytes < bsize)
+ goto done;
+ }
+
+ /* Handle leftovers */
+ for (;;) {
+ twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
+
+ nbytes -= bsize;
+ if (nbytes < bsize)
+ break;
+
+ u128_xor(dst, dst, src - 1);
+ src -= 1;
+ dst -= 1;
+ }
+
+done:
+ u128_xor(dst, dst, (u128 *)walk->iv);
+ *(u128 *)walk->iv = last_iv;
+
+ return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+
+ while ((nbytes = walk.nbytes)) {
+ nbytes = __cbc_decrypt(desc, &walk);
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ return err;
+}
+
+static struct crypto_alg blk_cbc_alg = {
+ .cra_name = "cbc(twofish)",
+ .cra_driver_name = "cbc-twofish-3way",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = TF_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct twofish_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(blk_cbc_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = TF_MIN_KEY_SIZE,
+ .max_keysize = TF_MAX_KEY_SIZE,
+ .ivsize = TF_BLOCK_SIZE,
+ .setkey = twofish_setkey,
+ .encrypt = cbc_encrypt,
+ .decrypt = cbc_decrypt,
+ },
+ },
+};
+
+static inline void u128_to_be128(be128 *dst, const u128 *src)
+{
+ dst->a = cpu_to_be64(src->a);
+ dst->b = cpu_to_be64(src->b);
+}
+
+static inline void be128_to_u128(u128 *dst, const be128 *src)
+{
+ dst->a = be64_to_cpu(src->a);
+ dst->b = be64_to_cpu(src->b);
+}
+
+static inline void u128_inc(u128 *i)
+{
+ i->b++;
+ if (!i->b)
+ i->a++;
+}
+
+static void ctr_crypt_final(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk)
+{
+ struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ u8 *ctrblk = walk->iv;
+ u8 keystream[TF_BLOCK_SIZE];
+ u8 *src = walk->src.virt.addr;
+ u8 *dst = walk->dst.virt.addr;
+ unsigned int nbytes = walk->nbytes;
+
+ twofish_enc_blk(ctx, keystream, ctrblk);
+ crypto_xor(keystream, src, nbytes);
+ memcpy(dst, keystream, nbytes);
+
+ crypto_inc(ctrblk, TF_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk)
+{
+ struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = TF_BLOCK_SIZE;
+ unsigned int nbytes = walk->nbytes;
+ u128 *src = (u128 *)walk->src.virt.addr;
+ u128 *dst = (u128 *)walk->dst.virt.addr;
+ u128 ctrblk;
+ be128 ctrblocks[3];
+
+ be128_to_u128(&ctrblk, (be128 *)walk->iv);
+
+ /* Process three block batch */
+ if (nbytes >= bsize * 3) {
+ do {
+ if (dst != src) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ }
+
+ /* create ctrblks for parallel encrypt */
+ u128_to_be128(&ctrblocks[0], &ctrblk);
+ u128_inc(&ctrblk);
+ u128_to_be128(&ctrblocks[1], &ctrblk);
+ u128_inc(&ctrblk);
+ u128_to_be128(&ctrblocks[2], &ctrblk);
+ u128_inc(&ctrblk);
+
+ twofish_enc_blk_xor_3way(ctx, (u8 *)dst,
+ (u8 *)ctrblocks);
+
+ src += 3;
+ dst += 3;
+ nbytes -= bsize * 3;
+ } while (nbytes >= bsize * 3);
+
+ if (nbytes < bsize)
+ goto done;
+ }
+
+ /* Handle leftovers */
+ do {
+ if (dst != src)
+ *dst = *src;
+
+ u128_to_be128(&ctrblocks[0], &ctrblk);
+ u128_inc(&ctrblk);
+
+ twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
+ u128_xor(dst, dst, (u128 *)ctrblocks);
+
+ src += 1;
+ dst += 1;
+ nbytes -= bsize;
+ } while (nbytes >= bsize);
+
+done:
+ u128_to_be128((be128 *)walk->iv, &ctrblk);
+ return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, TF_BLOCK_SIZE);
+
+ while ((nbytes = walk.nbytes) >= TF_BLOCK_SIZE) {
+ nbytes = __ctr_crypt(desc, &walk);
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ if (walk.nbytes) {
+ ctr_crypt_final(desc, &walk);
+ err = blkcipher_walk_done(desc, &walk, 0);
+ }
+
+ return err;
+}
+
+static struct crypto_alg blk_ctr_alg = {
+ .cra_name = "ctr(twofish)",
+ .cra_driver_name = "ctr-twofish-3way",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct twofish_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(blk_ctr_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = TF_MIN_KEY_SIZE,
+ .max_keysize = TF_MAX_KEY_SIZE,
+ .ivsize = TF_BLOCK_SIZE,
+ .setkey = twofish_setkey,
+ .encrypt = ctr_crypt,
+ .decrypt = ctr_crypt,
+ },
+ },
+};
+
+int __init init(void)
+{
+ int err;
+
+ err = crypto_register_alg(&blk_ecb_alg);
+ if (err)
+ goto ecb_err;
+ err = crypto_register_alg(&blk_cbc_alg);
+ if (err)
+ goto cbc_err;
+ err = crypto_register_alg(&blk_ctr_alg);
+ if (err)
+ goto ctr_err;
+
+ return 0;
+
+ctr_err:
+ crypto_unregister_alg(&blk_cbc_alg);
+cbc_err:
+ crypto_unregister_alg(&blk_ecb_alg);
+ecb_err:
+ return err;
+}
+
+void __exit fini(void)
+{
+ crypto_unregister_alg(&blk_ctr_alg);
+ crypto_unregister_alg(&blk_cbc_alg);
+ crypto_unregister_alg(&blk_ecb_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized");
+MODULE_ALIAS("twofish");
+MODULE_ALIAS("twofish-asm");
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 54edb207ff3a..a6253ec1b284 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -850,4 +850,6 @@ ia32_sys_call_table:
.quad sys_syncfs
.quad compat_sys_sendmmsg /* 345 */
.quad sys_setns
+ .quad compat_sys_process_vm_readv
+ .quad compat_sys_process_vm_writev
ia32_syscall_end:
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
index 67f87f257611..8e41071704a5 100644
--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -19,9 +19,15 @@ extern int amd_numa_init(void);
extern int amd_get_subcaches(int);
extern int amd_set_subcaches(int, int);
+struct amd_l3_cache {
+ unsigned indices;
+ u8 subcaches[4];
+};
+
struct amd_northbridge {
struct pci_dev *misc;
struct pci_dev *link;
+ struct amd_l3_cache l3_cache;
};
struct amd_northbridge_info {
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 7b3ca8324b69..9b7273cb2193 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -495,7 +495,7 @@ static inline void default_wait_for_init_deassert(atomic_t *deassert)
return;
}
-extern struct apic *generic_bigsmp_probe(void);
+extern void generic_bigsmp_probe(void);
#ifdef CONFIG_X86_LOCAL_APIC
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 34595d5e1038..3925d8007864 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -100,7 +100,9 @@
#define APIC_TIMER_BASE_CLKIN 0x0
#define APIC_TIMER_BASE_TMBASE 0x1
#define APIC_TIMER_BASE_DIV 0x2
+#define APIC_LVT_TIMER_ONESHOT (0 << 17)
#define APIC_LVT_TIMER_PERIODIC (1 << 17)
+#define APIC_LVT_TIMER_TSCDEADLINE (2 << 17)
#define APIC_LVT_MASKED (1 << 16)
#define APIC_LVT_LEVEL_TRIGGER (1 << 15)
#define APIC_LVT_REMOTE_IRR (1 << 14)
diff --git a/arch/x86/include/asm/archrandom.h b/arch/x86/include/asm/archrandom.h
new file mode 100644
index 000000000000..0d9ec770f2f8
--- /dev/null
+++ b/arch/x86/include/asm/archrandom.h
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the Linux kernel.
+ *
+ * Copyright (c) 2011, Intel Corporation
+ * Authors: Fenghua Yu <fenghua.yu@intel.com>,
+ * H. Peter Anvin <hpa@linux.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 ASM_X86_ARCHRANDOM_H
+#define ASM_X86_ARCHRANDOM_H
+
+#include <asm/processor.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative.h>
+#include <asm/nops.h>
+
+#define RDRAND_RETRY_LOOPS 10
+
+#define RDRAND_INT ".byte 0x0f,0xc7,0xf0"
+#ifdef CONFIG_X86_64
+# define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0"
+#else
+# define RDRAND_LONG RDRAND_INT
+#endif
+
+#ifdef CONFIG_ARCH_RANDOM
+
+#define GET_RANDOM(name, type, rdrand, nop) \
+static inline int name(type *v) \
+{ \
+ int ok; \
+ alternative_io("movl $0, %0\n\t" \
+ nop, \
+ "\n1: " rdrand "\n\t" \
+ "jc 2f\n\t" \
+ "decl %0\n\t" \
+ "jnz 1b\n\t" \
+ "2:", \
+ X86_FEATURE_RDRAND, \
+ ASM_OUTPUT2("=r" (ok), "=a" (*v)), \
+ "0" (RDRAND_RETRY_LOOPS)); \
+ return ok; \
+}
+
+#ifdef CONFIG_X86_64
+
+GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5);
+GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4);
+
+#else
+
+GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3);
+GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3);
+
+#endif /* CONFIG_X86_64 */
+
+#endif /* CONFIG_ARCH_RANDOM */
+
+extern void x86_init_rdrand(struct cpuinfo_x86 *c);
+
+#endif /* ASM_X86_ARCHRANDOM_H */
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h
index 10572e309ab2..58cb6d4085f7 100644
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -172,18 +172,14 @@ static inline int atomic_add_negative(int i, atomic_t *v)
*/
static inline int atomic_add_return(int i, atomic_t *v)
{
- int __i;
#ifdef CONFIG_M386
+ int __i;
unsigned long flags;
if (unlikely(boot_cpu_data.x86 <= 3))
goto no_xadd;
#endif
/* Modern 486+ processor */
- __i = i;
- asm volatile(LOCK_PREFIX "xaddl %0, %1"
- : "+r" (i), "+m" (v->counter)
- : : "memory");
- return i + __i;
+ return i + xadd(&v->counter, i);
#ifdef CONFIG_M386
no_xadd: /* Legacy 386 processor */
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h
index 017594d403f6..0e1cbfc8ee06 100644
--- a/arch/x86/include/asm/atomic64_64.h
+++ b/arch/x86/include/asm/atomic64_64.h
@@ -170,11 +170,7 @@ static inline int atomic64_add_negative(long i, atomic64_t *v)
*/
static inline long atomic64_add_return(long i, atomic64_t *v)
{
- long __i = i;
- asm volatile(LOCK_PREFIX "xaddq %0, %1;"
- : "+r" (i), "+m" (v->counter)
- : : "memory");
- return i + __i;
+ return i + xadd(&v->counter, i);
}
static inline long atomic64_sub_return(long i, atomic64_t *v)
diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h
index a460fa088d4c..5d3acdf5a7a6 100644
--- a/arch/x86/include/asm/cmpxchg.h
+++ b/arch/x86/include/asm/cmpxchg.h
@@ -1,5 +1,210 @@
+#ifndef ASM_X86_CMPXCHG_H
+#define ASM_X86_CMPXCHG_H
+
+#include <linux/compiler.h>
+#include <asm/alternative.h> /* Provides LOCK_PREFIX */
+
+/*
+ * Non-existant functions to indicate usage errors at link time
+ * (or compile-time if the compiler implements __compiletime_error().
+ */
+extern void __xchg_wrong_size(void)
+ __compiletime_error("Bad argument size for xchg");
+extern void __cmpxchg_wrong_size(void)
+ __compiletime_error("Bad argument size for cmpxchg");
+extern void __xadd_wrong_size(void)
+ __compiletime_error("Bad argument size for xadd");
+
+/*
+ * Constants for operation sizes. On 32-bit, the 64-bit size it set to
+ * -1 because sizeof will never return -1, thereby making those switch
+ * case statements guaranteeed dead code which the compiler will
+ * eliminate, and allowing the "missing symbol in the default case" to
+ * indicate a usage error.
+ */
+#define __X86_CASE_B 1
+#define __X86_CASE_W 2
+#define __X86_CASE_L 4
+#ifdef CONFIG_64BIT
+#define __X86_CASE_Q 8
+#else
+#define __X86_CASE_Q -1 /* sizeof will never return -1 */
+#endif
+
+/*
+ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
+ * Since this is generally used to protect other memory information, we
+ * use "asm volatile" and "memory" clobbers to prevent gcc from moving
+ * information around.
+ */
+#define __xchg(x, ptr, size) \
+({ \
+ __typeof(*(ptr)) __x = (x); \
+ switch (size) { \
+ case __X86_CASE_B: \
+ { \
+ volatile u8 *__ptr = (volatile u8 *)(ptr); \
+ asm volatile("xchgb %0,%1" \
+ : "=q" (__x), "+m" (*__ptr) \
+ : "0" (__x) \
+ : "memory"); \
+ break; \
+ } \
+ case __X86_CASE_W: \
+ { \
+ volatile u16 *__ptr = (volatile u16 *)(ptr); \
+ asm volatile("xchgw %0,%1" \
+ : "=r" (__x), "+m" (*__ptr) \
+ : "0" (__x) \
+ : "memory"); \
+ break; \
+ } \
+ case __X86_CASE_L: \
+ { \
+ volatile u32 *__ptr = (volatile u32 *)(ptr); \
+ asm volatile("xchgl %0,%1" \
+ : "=r" (__x), "+m" (*__ptr) \
+ : "0" (__x) \
+ : "memory"); \
+ break; \
+ } \
+ case __X86_CASE_Q: \
+ { \
+ volatile u64 *__ptr = (volatile u64 *)(ptr); \
+ asm volatile("xchgq %0,%1" \
+ : "=r" (__x), "+m" (*__ptr) \
+ : "0" (__x) \
+ : "memory"); \
+ break; \
+ } \
+ default: \
+ __xchg_wrong_size(); \
+ } \
+ __x; \
+})
+
+#define xchg(ptr, v) \
+ __xchg((v), (ptr), sizeof(*ptr))
+
+/*
+ * Atomic compare and exchange. Compare OLD with MEM, if identical,
+ * store NEW in MEM. Return the initial value in MEM. Success is
+ * indicated by comparing RETURN with OLD.
+ */
+#define __raw_cmpxchg(ptr, old, new, size, lock) \
+({ \
+ __typeof__(*(ptr)) __ret; \
+ __typeof__(*(ptr)) __old = (old); \
+ __typeof__(*(ptr)) __new = (new); \
+ switch (size) { \
+ case __X86_CASE_B: \
+ { \
+ volatile u8 *__ptr = (volatile u8 *)(ptr); \
+ asm volatile(lock "cmpxchgb %2,%1" \
+ : "=a" (__ret), "+m" (*__ptr) \
+ : "q" (__new), "0" (__old) \
+ : "memory"); \
+ break; \
+ } \
+ case __X86_CASE_W: \
+ { \
+ volatile u16 *__ptr = (volatile u16 *)(ptr); \
+ asm volatile(lock "cmpxchgw %2,%1" \
+ : "=a" (__ret), "+m" (*__ptr) \
+ : "r" (__new), "0" (__old) \
+ : "memory"); \
+ break; \
+ } \
+ case __X86_CASE_L: \
+ { \
+ volatile u32 *__ptr = (volatile u32 *)(ptr); \
+ asm volatile(lock "cmpxchgl %2,%1" \
+ : "=a" (__ret), "+m" (*__ptr) \
+ : "r" (__new), "0" (__old) \
+ : "memory"); \
+ break; \
+ } \
+ case __X86_CASE_Q: \
+ { \
+ volatile u64 *__ptr = (volatile u64 *)(ptr); \
+ asm volatile(lock "cmpxchgq %2,%1" \
+ : "=a" (__ret), "+m" (*__ptr) \
+ : "r" (__new), "0" (__old) \
+ : "memory"); \
+ break; \
+ } \
+ default: \
+ __cmpxchg_wrong_size(); \
+ } \
+ __ret; \
+})
+
+#define __cmpxchg(ptr, old, new, size) \
+ __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
+
+#define __sync_cmpxchg(ptr, old, new, size) \
+ __raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
+
+#define __cmpxchg_local(ptr, old, new, size) \
+ __raw_cmpxchg((ptr), (old), (new), (size), "")
+
#ifdef CONFIG_X86_32
# include "cmpxchg_32.h"
#else
# include "cmpxchg_64.h"
#endif
+
+#ifdef __HAVE_ARCH_CMPXCHG
+#define cmpxchg(ptr, old, new) \
+ __cmpxchg((ptr), (old), (new), sizeof(*ptr))
+
+#define sync_cmpxchg(ptr, old, new) \
+ __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
+
+#define cmpxchg_local(ptr, old, new) \
+ __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
+#endif
+
+#define __xadd(ptr, inc, lock) \
+ ({ \
+ __typeof__ (*(ptr)) __ret = (inc); \
+ switch (sizeof(*(ptr))) { \
+ case __X86_CASE_B: \
+ asm volatile (lock "xaddb %b0, %1\n" \
+ : "+r" (__ret), "+m" (*(ptr)) \
+ : : "memory", "cc"); \
+ break; \
+ case __X86_CASE_W: \
+ asm volatile (lock "xaddw %w0, %1\n" \
+ : "+r" (__ret), "+m" (*(ptr)) \
+ : : "memory", "cc"); \
+ break; \
+ case __X86_CASE_L: \
+ asm volatile (lock "xaddl %0, %1\n" \
+ : "+r" (__ret), "+m" (*(ptr)) \
+ : : "memory", "cc"); \
+ break; \
+ case __X86_CASE_Q: \
+ asm volatile (lock "xaddq %q0, %1\n" \
+ : "+r" (__ret), "+m" (*(ptr)) \
+ : : "memory", "cc"); \
+ break; \
+ default: \
+ __xadd_wrong_size(); \
+ } \
+ __ret; \
+ })
+
+/*
+ * xadd() adds "inc" to "*ptr" and atomically returns the previous
+ * value of "*ptr".
+ *
+ * xadd() is locked when multiple CPUs are online
+ * xadd_sync() is always locked
+ * xadd_local() is never locked
+ */
+#define xadd(ptr, inc) __xadd((ptr), (inc), LOCK_PREFIX)
+#define xadd_sync(ptr, inc) __xadd((ptr), (inc), "lock; ")
+#define xadd_local(ptr, inc) __xadd((ptr), (inc), "")
+
+#endif /* ASM_X86_CMPXCHG_H */
diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h
index 3deb7250624c..fbebb07dd80b 100644
--- a/arch/x86/include/asm/cmpxchg_32.h
+++ b/arch/x86/include/asm/cmpxchg_32.h
@@ -1,61 +1,11 @@
#ifndef _ASM_X86_CMPXCHG_32_H
#define _ASM_X86_CMPXCHG_32_H
-#include <linux/bitops.h> /* for LOCK_PREFIX */
-
/*
* Note: if you use set64_bit(), __cmpxchg64(), or their variants, you
* you need to test for the feature in boot_cpu_data.
*/
-extern void __xchg_wrong_size(void);
-
-/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
- * Since this is generally used to protect other memory information, we
- * use "asm volatile" and "memory" clobbers to prevent gcc from moving
- * information around.
- */
-#define __xchg(x, ptr, size) \
-({ \
- __typeof(*(ptr)) __x = (x); \
- switch (size) { \
- case 1: \
- { \
- volatile u8 *__ptr = (volatile u8 *)(ptr); \
- asm volatile("xchgb %0,%1" \
- : "=q" (__x), "+m" (*__ptr) \
- : "0" (__x) \
- : "memory"); \
- break; \
- } \
- case 2: \
- { \
- volatile u16 *__ptr = (volatile u16 *)(ptr); \
- asm volatile("xchgw %0,%1" \
- : "=r" (__x), "+m" (*__ptr) \
- : "0" (__x) \
- : "memory"); \
- break; \
- } \
- case 4: \
- { \
- volatile u32 *__ptr = (volatile u32 *)(ptr); \
- asm volatile("xchgl %0,%1" \
- : "=r" (__x), "+m" (*__ptr) \
- : "0" (__x) \
- : "memory"); \
- break; \
- } \
- default: \
- __xchg_wrong_size(); \
- } \
- __x; \
-})
-
-#define xchg(ptr, v) \
- __xchg((v), (ptr), sizeof(*ptr))
-
/*
* CMPXCHG8B only writes to the target if we had the previous
* value in registers, otherwise it acts as a read and gives us the
@@ -84,72 +34,8 @@ static inline void set_64bit(volatile u64 *ptr, u64 value)
: "memory");
}
-extern void __cmpxchg_wrong_size(void);
-
-/*
- * Atomic compare and exchange. Compare OLD with MEM, if identical,
- * store NEW in MEM. Return the initial value in MEM. Success is
- * indicated by comparing RETURN with OLD.
- */
-#define __raw_cmpxchg(ptr, old, new, size, lock) \
-({ \
- __typeof__(*(ptr)) __ret; \
- __typeof__(*(ptr)) __old = (old); \
- __typeof__(*(ptr)) __new = (new); \
- switch (size) { \
- case 1: \
- { \
- volatile u8 *__ptr = (volatile u8 *)(ptr); \
- asm volatile(lock "cmpxchgb %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "q" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- case 2: \
- { \
- volatile u16 *__ptr = (volatile u16 *)(ptr); \
- asm volatile(lock "cmpxchgw %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "r" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- case 4: \
- { \
- volatile u32 *__ptr = (volatile u32 *)(ptr); \
- asm volatile(lock "cmpxchgl %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "r" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- default: \
- __cmpxchg_wrong_size(); \
- } \
- __ret; \
-})
-
-#define __cmpxchg(ptr, old, new, size) \
- __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
-
-#define __sync_cmpxchg(ptr, old, new, size) \
- __raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
-
-#define __cmpxchg_local(ptr, old, new, size) \
- __raw_cmpxchg((ptr), (old), (new), (size), "")
-
#ifdef CONFIG_X86_CMPXCHG
#define __HAVE_ARCH_CMPXCHG 1
-
-#define cmpxchg(ptr, old, new) \
- __cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define sync_cmpxchg(ptr, old, new) \
- __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define cmpxchg_local(ptr, old, new) \
- __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
#endif
#ifdef CONFIG_X86_CMPXCHG64
diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h
index 7cf5c0a24434..285da02c38fa 100644
--- a/arch/x86/include/asm/cmpxchg_64.h
+++ b/arch/x86/include/asm/cmpxchg_64.h
@@ -1,144 +1,13 @@
#ifndef _ASM_X86_CMPXCHG_64_H
#define _ASM_X86_CMPXCHG_64_H
-#include <asm/alternative.h> /* Provides LOCK_PREFIX */
-
static inline void set_64bit(volatile u64 *ptr, u64 val)
{
*ptr = val;
}
-extern void __xchg_wrong_size(void);
-extern void __cmpxchg_wrong_size(void);
-
-/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
- * Since this is generally used to protect other memory information, we
- * use "asm volatile" and "memory" clobbers to prevent gcc from moving
- * information around.
- */
-#define __xchg(x, ptr, size) \
-({ \
- __typeof(*(ptr)) __x = (x); \
- switch (size) { \
- case 1: \
- { \
- volatile u8 *__ptr = (volatile u8 *)(ptr); \
- asm volatile("xchgb %0,%1" \
- : "=q" (__x), "+m" (*__ptr) \
- : "0" (__x) \
- : "memory"); \
- break; \
- } \
- case 2: \
- { \
- volatile u16 *__ptr = (volatile u16 *)(ptr); \
- asm volatile("xchgw %0,%1" \
- : "=r" (__x), "+m" (*__ptr) \
- : "0" (__x) \
- : "memory"); \
- break; \
- } \
- case 4: \
- { \
- volatile u32 *__ptr = (volatile u32 *)(ptr); \
- asm volatile("xchgl %0,%1" \
- : "=r" (__x), "+m" (*__ptr) \
- : "0" (__x) \
- : "memory"); \
- break; \
- } \
- case 8: \
- { \
- volatile u64 *__ptr = (volatile u64 *)(ptr); \
- asm volatile("xchgq %0,%1" \
- : "=r" (__x), "+m" (*__ptr) \
- : "0" (__x) \
- : "memory"); \
- break; \
- } \
- default: \
- __xchg_wrong_size(); \
- } \
- __x; \
-})
-
-#define xchg(ptr, v) \
- __xchg((v), (ptr), sizeof(*ptr))
-
#define __HAVE_ARCH_CMPXCHG 1
-/*
- * Atomic compare and exchange. Compare OLD with MEM, if identical,
- * store NEW in MEM. Return the initial value in MEM. Success is
- * indicated by comparing RETURN with OLD.
- */
-#define __raw_cmpxchg(ptr, old, new, size, lock) \
-({ \
- __typeof__(*(ptr)) __ret; \
- __typeof__(*(ptr)) __old = (old); \
- __typeof__(*(ptr)) __new = (new); \
- switch (size) { \
- case 1: \
- { \
- volatile u8 *__ptr = (volatile u8 *)(ptr); \
- asm volatile(lock "cmpxchgb %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "q" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- case 2: \
- { \
- volatile u16 *__ptr = (volatile u16 *)(ptr); \
- asm volatile(lock "cmpxchgw %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "r" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- case 4: \
- { \
- volatile u32 *__ptr = (volatile u32 *)(ptr); \
- asm volatile(lock "cmpxchgl %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "r" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- case 8: \
- { \
- volatile u64 *__ptr = (volatile u64 *)(ptr); \
- asm volatile(lock "cmpxchgq %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "r" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- default: \
- __cmpxchg_wrong_size(); \
- } \
- __ret; \
-})
-
-#define __cmpxchg(ptr, old, new, size) \
- __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
-
-#define __sync_cmpxchg(ptr, old, new, size) \
- __raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
-
-#define __cmpxchg_local(ptr, old, new, size) \
- __raw_cmpxchg((ptr), (old), (new), (size), "")
-
-#define cmpxchg(ptr, old, new) \
- __cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define sync_cmpxchg(ptr, old, new) \
- __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define cmpxchg_local(ptr, old, new) \
- __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
-
#define cmpxchg64(ptr, o, n) \
({ \
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index 1d9cd27c2920..30d737ef2a42 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -108,7 +108,8 @@ struct compat_statfs {
compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_frsize;
- int f_spare[5];
+ int f_flags;
+ int f_spare[4];
};
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 88b23a43f340..f3444f700f36 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -114,12 +114,14 @@
#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */
#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */
#define X86_FEATURE_PDCM (4*32+15) /* Performance Capabilities */
+#define X86_FEATURE_PCID (4*32+17) /* Process Context Identifiers */
#define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */
#define X86_FEATURE_XMM4_1 (4*32+19) /* "sse4_1" SSE-4.1 */
#define X86_FEATURE_XMM4_2 (4*32+20) /* "sse4_2" SSE-4.2 */
#define X86_FEATURE_X2APIC (4*32+21) /* x2APIC */
#define X86_FEATURE_MOVBE (4*32+22) /* MOVBE instruction */
#define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE_TIMER (4*32+24) /* Tsc deadline timer */
#define X86_FEATURE_AES (4*32+25) /* AES instructions */
#define X86_FEATURE_XSAVE (4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
#define X86_FEATURE_OSXSAVE (4*32+27) /* "" XSAVE enabled in the OS */
@@ -257,7 +259,9 @@ extern const char * const x86_power_flags[32];
#define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM)
#define cpu_has_xmm2 boot_cpu_has(X86_FEATURE_XMM2)
#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3)
+#define cpu_has_ssse3 boot_cpu_has(X86_FEATURE_SSSE3)
#define cpu_has_aes boot_cpu_has(X86_FEATURE_AES)
+#define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX)
#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT)
#define cpu_has_mp boot_cpu_has(X86_FEATURE_MP)
#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX)
@@ -285,6 +289,7 @@ extern const char * const x86_power_flags[32];
#define cpu_has_xmm4_2 boot_cpu_has(X86_FEATURE_XMM4_2)
#define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC)
#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE)
+#define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE)
#define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR)
#define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ)
#define cpu_has_perfctr_core boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h
index 029f230ab637..63a2a03d7d51 100644
--- a/arch/x86/include/asm/device.h
+++ b/arch/x86/include/asm/device.h
@@ -8,7 +8,7 @@ struct dev_archdata {
#ifdef CONFIG_X86_64
struct dma_map_ops *dma_ops;
#endif
-#if defined(CONFIG_DMAR) || defined(CONFIG_AMD_IOMMU)
+#if defined(CONFIG_INTEL_IOMMU) || defined(CONFIG_AMD_IOMMU)
void *iommu; /* hook for IOMMU specific extension */
#endif
};
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index d4c419f883a0..ed3065fd6314 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -2,7 +2,7 @@
#define _ASM_X86_DMA_MAPPING_H
/*
- * IOMMU interface. See Documentation/PCI/PCI-DMA-mapping.txt and
+ * IOMMU interface. See Documentation/DMA-API-HOWTO.txt and
* Documentation/DMA-API.txt for documentation.
*/
diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h
index 326099199318..f6f15986df6c 100644
--- a/arch/x86/include/asm/dwarf2.h
+++ b/arch/x86/include/asm/dwarf2.h
@@ -27,6 +27,7 @@
#define CFI_REMEMBER_STATE .cfi_remember_state
#define CFI_RESTORE_STATE .cfi_restore_state
#define CFI_UNDEFINED .cfi_undefined
+#define CFI_ESCAPE .cfi_escape
#ifdef CONFIG_AS_CFI_SIGNAL_FRAME
#define CFI_SIGNAL_FRAME .cfi_signal_frame
@@ -68,6 +69,7 @@
#define CFI_REMEMBER_STATE cfi_ignore
#define CFI_RESTORE_STATE cfi_ignore
#define CFI_UNDEFINED cfi_ignore
+#define CFI_ESCAPE cfi_ignore
#define CFI_SIGNAL_FRAME cfi_ignore
#endif
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index f2ad2163109d..5f962df30d0f 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -4,6 +4,7 @@
/*
* ELF register definitions..
*/
+#include <linux/thread_info.h>
#include <asm/ptrace.h>
#include <asm/user.h>
@@ -320,4 +321,34 @@ extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
extern unsigned long arch_randomize_brk(struct mm_struct *mm);
#define arch_randomize_brk arch_randomize_brk
+/*
+ * True on X86_32 or when emulating IA32 on X86_64
+ */
+static inline int mmap_is_ia32(void)
+{
+#ifdef CONFIG_X86_32
+ return 1;
+#endif
+#ifdef CONFIG_IA32_EMULATION
+ if (test_thread_flag(TIF_IA32))
+ return 1;
+#endif
+ return 0;
+}
+
+/* The first two values are special, do not change. See align_addr() */
+enum align_flags {
+ ALIGN_VA_32 = BIT(0),
+ ALIGN_VA_64 = BIT(1),
+ ALIGN_VDSO = BIT(2),
+ ALIGN_TOPDOWN = BIT(3),
+};
+
+struct va_alignment {
+ int flags;
+ unsigned long mask;
+} ____cacheline_aligned;
+
+extern struct va_alignment va_align;
+extern unsigned long align_addr(unsigned long, struct file *, enum align_flags);
#endif /* _ASM_X86_ELF_H */
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index 09199052060f..eb92a6ed2be7 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -119,7 +119,7 @@ struct irq_cfg {
cpumask_var_t old_domain;
u8 vector;
u8 move_in_progress : 1;
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
struct irq_2_iommu irq_2_iommu;
#endif
};
diff --git a/arch/x86/include/asm/hyperv.h b/arch/x86/include/asm/hyperv.h
index 5df477ac3af7..b80420bcd09d 100644
--- a/arch/x86/include/asm/hyperv.h
+++ b/arch/x86/include/asm/hyperv.h
@@ -189,5 +189,6 @@
#define HV_STATUS_INVALID_HYPERCALL_CODE 2
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
#define HV_STATUS_INVALID_ALIGNMENT 4
+#define HV_STATUS_INSUFFICIENT_BUFFERS 19
#endif
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
index 1c23360fb2d8..47d99934580f 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -3,7 +3,8 @@
#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
+static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
static inline void prepare_irte(struct irte *irte, int vector,
unsigned int dest)
{
@@ -36,6 +37,9 @@ static inline bool irq_remapped(struct irq_cfg *cfg)
{
return false;
}
+static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip)
+{
+}
#endif
#endif /* _ASM_X86_IRQ_REMAPPING_H */
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 7e50f06393aa..4b4448761e88 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -160,19 +160,11 @@ static inline int invalid_vm86_irq(int irq)
#define IO_APIC_VECTOR_LIMIT ( 32 * MAX_IO_APICS )
#ifdef CONFIG_X86_IO_APIC
-# ifdef CONFIG_SPARSE_IRQ
-# define CPU_VECTOR_LIMIT (64 * NR_CPUS)
-# define NR_IRQS \
+# define CPU_VECTOR_LIMIT (64 * NR_CPUS)
+# define NR_IRQS \
(CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ? \
(NR_VECTORS + CPU_VECTOR_LIMIT) : \
(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
-# else
-# define CPU_VECTOR_LIMIT (32 * NR_CPUS)
-# define NR_IRQS \
- (CPU_VECTOR_LIMIT < IO_APIC_VECTOR_LIMIT ? \
- (NR_VECTORS + CPU_VECTOR_LIMIT) : \
- (NR_VECTORS + IO_APIC_VECTOR_LIMIT))
-# endif
#else /* !CONFIG_X86_IO_APIC: */
# define NR_IRQS NR_IRQS_LEGACY
#endif
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 6040d115ef51..a026507893e9 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -262,7 +262,7 @@ struct x86_emulate_ctxt {
struct operand dst;
bool has_seg_override;
u8 seg_override;
- unsigned int d;
+ u64 d;
int (*execute)(struct x86_emulate_ctxt *ctxt);
int (*check_perm)(struct x86_emulate_ctxt *ctxt);
/* modrm */
@@ -275,6 +275,8 @@ struct x86_emulate_ctxt {
unsigned long _eip;
/* Fields above regs are cleared together. */
unsigned long regs[NR_VCPU_REGS];
+ struct operand memop;
+ struct operand *memopp;
struct fetch_cache fetch;
struct read_cache io_read;
struct read_cache mem_read;
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index dd51c83aa5de..b4973f4dab98 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -26,7 +26,8 @@
#include <asm/mtrr.h>
#include <asm/msr-index.h>
-#define KVM_MAX_VCPUS 64
+#define KVM_MAX_VCPUS 254
+#define KVM_SOFT_MAX_VCPUS 64
#define KVM_MEMORY_SLOTS 32
/* memory slots that does not exposed to userspace */
#define KVM_PRIVATE_MEM_SLOTS 4
@@ -264,6 +265,7 @@ struct kvm_mmu {
void (*new_cr3)(struct kvm_vcpu *vcpu);
void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long root);
unsigned long (*get_cr3)(struct kvm_vcpu *vcpu);
+ u64 (*get_pdptr)(struct kvm_vcpu *vcpu, int index);
int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err,
bool prefault);
void (*inject_page_fault)(struct kvm_vcpu *vcpu,
@@ -411,8 +413,9 @@ struct kvm_vcpu_arch {
u32 tsc_catchup_mult;
s8 tsc_catchup_shift;
- bool nmi_pending;
- bool nmi_injected;
+ atomic_t nmi_queued; /* unprocessed asynchronous NMIs */
+ unsigned nmi_pending; /* NMI queued after currently running handler */
+ bool nmi_injected; /* Trying to inject an NMI this entry */
struct mtrr_state_type mtrr_state;
u32 pat;
@@ -628,14 +631,13 @@ struct kvm_x86_ops {
void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc);
+ u64 (*read_l1_tsc)(struct kvm_vcpu *vcpu);
void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
int (*check_intercept)(struct kvm_vcpu *vcpu,
struct x86_instruction_info *info,
enum x86_intercept_stage stage);
-
- const struct trace_print_flags *exit_reasons_str;
};
struct kvm_arch_async_pf {
@@ -672,6 +674,8 @@ u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
extern bool tdp_enabled;
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+
/* control of guest tsc rate supported? */
extern bool kvm_has_tsc_control;
/* minimum supported tsc_khz for guests */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index d52609aeeab8..a6962d9161a0 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -229,6 +229,8 @@
#define MSR_IA32_APICBASE_ENABLE (1<<11)
#define MSR_IA32_APICBASE_BASE (0xfffff<<12)
+#define MSR_IA32_TSCDEADLINE 0x000006e0
+
#define MSR_IA32_UCODE_WRITE 0x00000079
#define MSR_IA32_UCODE_REV 0x0000008b
diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h
index 4886a68f267e..fd3f9f18cf3f 100644
--- a/arch/x86/include/asm/nmi.h
+++ b/arch/x86/include/asm/nmi.h
@@ -22,27 +22,26 @@ void arch_trigger_all_cpu_backtrace(void);
#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
#endif
-/*
- * Define some priorities for the nmi notifier call chain.
- *
- * Create a local nmi bit that has a higher priority than
- * external nmis, because the local ones are more frequent.
- *
- * Also setup some default high/normal/low settings for
- * subsystems to registers with. Using 4 bits to separate
- * the priorities. This can go a lot higher if needed be.
- */
-
-#define NMI_LOCAL_SHIFT 16 /* randomly picked */
-#define NMI_LOCAL_BIT (1ULL << NMI_LOCAL_SHIFT)
-#define NMI_HIGH_PRIOR (1ULL << 8)
-#define NMI_NORMAL_PRIOR (1ULL << 4)
-#define NMI_LOW_PRIOR (1ULL << 0)
-#define NMI_LOCAL_HIGH_PRIOR (NMI_LOCAL_BIT | NMI_HIGH_PRIOR)
-#define NMI_LOCAL_NORMAL_PRIOR (NMI_LOCAL_BIT | NMI_NORMAL_PRIOR)
-#define NMI_LOCAL_LOW_PRIOR (NMI_LOCAL_BIT | NMI_LOW_PRIOR)
+#define NMI_FLAG_FIRST 1
+
+enum {
+ NMI_LOCAL=0,
+ NMI_UNKNOWN,
+ NMI_MAX
+};
+
+#define NMI_DONE 0
+#define NMI_HANDLED 1
+
+typedef int (*nmi_handler_t)(unsigned int, struct pt_regs *);
+
+int register_nmi_handler(unsigned int, nmi_handler_t, unsigned long,
+ const char *);
+
+void unregister_nmi_handler(unsigned int, const char *);
void stop_nmi(void);
void restart_nmi(void);
+void local_touch_nmi(void);
#endif /* _ASM_X86_NMI_H */
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index 704526734bef..e38197806853 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -99,10 +99,10 @@ struct pci_raw_ops {
int reg, int len, u32 val);
};
-extern struct pci_raw_ops *raw_pci_ops;
-extern struct pci_raw_ops *raw_pci_ext_ops;
+extern const struct pci_raw_ops *raw_pci_ops;
+extern const struct pci_raw_ops *raw_pci_ext_ops;
-extern struct pci_raw_ops pci_direct_conf1;
+extern const struct pci_raw_ops pci_direct_conf1;
extern bool port_cf9_safe;
/* arch_initcall level */
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 094fb30817ab..f61c62f7d5d8 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -29,6 +29,9 @@
#define ARCH_PERFMON_EVENTSEL_INV (1ULL << 23)
#define ARCH_PERFMON_EVENTSEL_CMASK 0xFF000000ULL
+#define AMD_PERFMON_EVENTSEL_GUESTONLY (1ULL << 40)
+#define AMD_PERFMON_EVENTSEL_HOSTONLY (1ULL << 41)
+
#define AMD64_EVENTSEL_EVENT \
(ARCH_PERFMON_EVENTSEL_EVENT | (0x0FULL << 32))
#define INTEL_ARCH_EVENT_MASK \
@@ -43,14 +46,17 @@
#define AMD64_RAW_EVENT_MASK \
(X86_RAW_EVENT_MASK | \
AMD64_EVENTSEL_EVENT)
+#define AMD64_NUM_COUNTERS 4
+#define AMD64_NUM_COUNTERS_F15H 6
+#define AMD64_NUM_COUNTERS_MAX AMD64_NUM_COUNTERS_F15H
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
(1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
-#define ARCH_PERFMON_BRANCH_MISSES_RETIRED 6
+#define ARCH_PERFMON_BRANCH_MISSES_RETIRED 6
/*
* Intel "Architectural Performance Monitoring" CPUID
@@ -110,6 +116,35 @@ union cpuid10_edx {
*/
#define X86_PMC_IDX_FIXED_BTS (X86_PMC_IDX_FIXED + 16)
+/*
+ * IBS cpuid feature detection
+ */
+
+#define IBS_CPUID_FEATURES 0x8000001b
+
+/*
+ * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
+ * bit 0 is used to indicate the existence of IBS.
+ */
+#define IBS_CAPS_AVAIL (1U<<0)
+#define IBS_CAPS_FETCHSAM (1U<<1)
+#define IBS_CAPS_OPSAM (1U<<2)
+#define IBS_CAPS_RDWROPCNT (1U<<3)
+#define IBS_CAPS_OPCNT (1U<<4)
+#define IBS_CAPS_BRNTRGT (1U<<5)
+#define IBS_CAPS_OPCNTEXT (1U<<6)
+
+#define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \
+ | IBS_CAPS_FETCHSAM \
+ | IBS_CAPS_OPSAM)
+
+/*
+ * IBS APIC setup
+ */
+#define IBSCTL 0x1cc
+#define IBSCTL_LVT_OFFSET_VALID (1ULL<<8)
+#define IBSCTL_LVT_OFFSET_MASK 0x0F
+
/* IbsFetchCtl bits/masks */
#define IBS_FETCH_RAND_EN (1ULL<<57)
#define IBS_FETCH_VAL (1ULL<<49)
@@ -124,6 +159,8 @@ union cpuid10_edx {
#define IBS_OP_MAX_CNT 0x0000FFFFULL
#define IBS_OP_MAX_CNT_EXT 0x007FFFFFULL /* not a register bit mask */
+extern u32 get_ibs_caps(void);
+
#ifdef CONFIG_PERF_EVENTS
extern void perf_events_lapic_init(void);
@@ -159,7 +196,19 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs);
); \
}
+struct perf_guest_switch_msr {
+ unsigned msr;
+ u64 host, guest;
+};
+
+extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr);
#else
+static inline perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
+{
+ *nr = 0;
+ return NULL;
+}
+
static inline void perf_events_lapic_init(void) { }
#endif
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 0d1171c97729..b650435ffb53 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -111,6 +111,7 @@ struct cpuinfo_x86 {
/* Index into per_cpu list: */
u16 cpu_index;
#endif
+ u32 microcode;
} __attribute__((__aligned__(SMP_CACHE_BYTES)));
#define X86_VENDOR_INTEL 0
@@ -179,7 +180,8 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
"=b" (*ebx),
"=c" (*ecx),
"=d" (*edx)
- : "0" (*eax), "2" (*ecx));
+ : "0" (*eax), "2" (*ecx)
+ : "memory");
}
static inline void load_cr3(pgd_t *pgdir)
diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h
index 3250e3d605d9..92f297069e87 100644
--- a/arch/x86/include/asm/reboot.h
+++ b/arch/x86/include/asm/reboot.h
@@ -23,7 +23,7 @@ void machine_real_restart(unsigned int type);
#define MRR_BIOS 0
#define MRR_APM 1
-typedef void (*nmi_shootdown_cb)(int, struct die_args*);
+typedef void (*nmi_shootdown_cb)(int, struct pt_regs*);
void nmi_shootdown_cpus(nmi_shootdown_cb callback);
#endif /* _ASM_X86_REBOOT_H */
diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h
index df4cd32b4cc6..2dbe4a721ce5 100644
--- a/arch/x86/include/asm/rwsem.h
+++ b/arch/x86/include/asm/rwsem.h
@@ -204,13 +204,7 @@ static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
*/
static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
{
- long tmp = delta;
-
- asm volatile(LOCK_PREFIX "xadd %0,%1"
- : "+r" (tmp), "+m" (sem->count)
- : : "memory");
-
- return tmp + delta;
+ return delta + xadd(&sem->count, delta);
}
#endif /* __KERNEL__ */
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
index ee67edf86fdd..972c260919a3 100644
--- a/arch/x86/include/asm/spinlock.h
+++ b/arch/x86/include/asm/spinlock.h
@@ -49,109 +49,49 @@
* issues and should be optimal for the uncontended case. Note the tail must be
* in the high part, because a wide xadd increment of the low part would carry
* up and contaminate the high part.
- *
- * With fewer than 2^8 possible CPUs, we can use x86's partial registers to
- * save some instructions and make the code more elegant. There really isn't
- * much between them in performance though, especially as locks are out of line.
*/
-#if (NR_CPUS < 256)
-#define TICKET_SHIFT 8
-
static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
{
- short inc = 0x0100;
-
- asm volatile (
- LOCK_PREFIX "xaddw %w0, %1\n"
- "1:\t"
- "cmpb %h0, %b0\n\t"
- "je 2f\n\t"
- "rep ; nop\n\t"
- "movb %1, %b0\n\t"
- /* don't need lfence here, because loads are in-order */
- "jmp 1b\n"
- "2:"
- : "+Q" (inc), "+m" (lock->slock)
- :
- : "memory", "cc");
+ register struct __raw_tickets inc = { .tail = 1 };
+
+ inc = xadd(&lock->tickets, inc);
+
+ for (;;) {
+ if (inc.head == inc.tail)
+ break;
+ cpu_relax();
+ inc.head = ACCESS_ONCE(lock->tickets.head);
+ }
+ barrier(); /* make sure nothing creeps before the lock is taken */
}
static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
{
- int tmp, new;
-
- asm volatile("movzwl %2, %0\n\t"
- "cmpb %h0,%b0\n\t"
- "leal 0x100(%" REG_PTR_MODE "0), %1\n\t"
- "jne 1f\n\t"
- LOCK_PREFIX "cmpxchgw %w1,%2\n\t"
- "1:"
- "sete %b1\n\t"
- "movzbl %b1,%0\n\t"
- : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
- :
- : "memory", "cc");
+ arch_spinlock_t old, new;
+
+ old.tickets = ACCESS_ONCE(lock->tickets);
+ if (old.tickets.head != old.tickets.tail)
+ return 0;
+
+ new.head_tail = old.head_tail + (1 << TICKET_SHIFT);
- return tmp;
+ /* cmpxchg is a full barrier, so nothing can move before it */
+ return cmpxchg(&lock->head_tail, old.head_tail, new.head_tail) == old.head_tail;
}
+#if (NR_CPUS < 256)
static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
{
asm volatile(UNLOCK_LOCK_PREFIX "incb %0"
- : "+m" (lock->slock)
+ : "+m" (lock->head_tail)
:
: "memory", "cc");
}
#else
-#define TICKET_SHIFT 16
-
-static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
-{
- int inc = 0x00010000;
- int tmp;
-
- asm volatile(LOCK_PREFIX "xaddl %0, %1\n"
- "movzwl %w0, %2\n\t"
- "shrl $16, %0\n\t"
- "1:\t"
- "cmpl %0, %2\n\t"
- "je 2f\n\t"
- "rep ; nop\n\t"
- "movzwl %1, %2\n\t"
- /* don't need lfence here, because loads are in-order */
- "jmp 1b\n"
- "2:"
- : "+r" (inc), "+m" (lock->slock), "=&r" (tmp)
- :
- : "memory", "cc");
-}
-
-static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
-{
- int tmp;
- int new;
-
- asm volatile("movl %2,%0\n\t"
- "movl %0,%1\n\t"
- "roll $16, %0\n\t"
- "cmpl %0,%1\n\t"
- "leal 0x00010000(%" REG_PTR_MODE "0), %1\n\t"
- "jne 1f\n\t"
- LOCK_PREFIX "cmpxchgl %1,%2\n\t"
- "1:"
- "sete %b1\n\t"
- "movzbl %b1,%0\n\t"
- : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
- :
- : "memory", "cc");
-
- return tmp;
-}
-
static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
{
asm volatile(UNLOCK_LOCK_PREFIX "incw %0"
- : "+m" (lock->slock)
+ : "+m" (lock->head_tail)
:
: "memory", "cc");
}
@@ -159,16 +99,16 @@ static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
static inline int __ticket_spin_is_locked(arch_spinlock_t *lock)
{
- int tmp = ACCESS_ONCE(lock->slock);
+ struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
- return !!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1 << TICKET_SHIFT) - 1));
+ return !!(tmp.tail ^ tmp.head);
}
static inline int __ticket_spin_is_contended(arch_spinlock_t *lock)
{
- int tmp = ACCESS_ONCE(lock->slock);
+ struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
- return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1;
+ return ((tmp.tail - tmp.head) & TICKET_MASK) > 1;
}
#ifndef CONFIG_PARAVIRT_SPINLOCKS
diff --git a/arch/x86/include/asm/spinlock_types.h b/arch/x86/include/asm/spinlock_types.h
index 7c7a486fcb68..8ebd5df7451e 100644
--- a/arch/x86/include/asm/spinlock_types.h
+++ b/arch/x86/include/asm/spinlock_types.h
@@ -5,11 +5,29 @@
# error "please don't include this file directly"
#endif
+#include <linux/types.h>
+
+#if (CONFIG_NR_CPUS < 256)
+typedef u8 __ticket_t;
+typedef u16 __ticketpair_t;
+#else
+typedef u16 __ticket_t;
+typedef u32 __ticketpair_t;
+#endif
+
+#define TICKET_SHIFT (sizeof(__ticket_t) * 8)
+#define TICKET_MASK ((__ticket_t)((1 << TICKET_SHIFT) - 1))
+
typedef struct arch_spinlock {
- unsigned int slock;
+ union {
+ __ticketpair_t head_tail;
+ struct __raw_tickets {
+ __ticket_t head, tail;
+ } tickets;
+ };
} arch_spinlock_t;
-#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
+#define __ARCH_SPIN_LOCK_UNLOCKED { { 0 } }
#include <asm/rwlock.h>
diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
index 593485b38ab3..599c77d38f33 100644
--- a/arch/x86/include/asm/unistd_32.h
+++ b/arch/x86/include/asm/unistd_32.h
@@ -352,10 +352,12 @@
#define __NR_syncfs 344
#define __NR_sendmmsg 345
#define __NR_setns 346
+#define __NR_process_vm_readv 347
+#define __NR_process_vm_writev 348
#ifdef __KERNEL__
-#define NR_syscalls 347
+#define NR_syscalls 349
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
index 201040573444..0431f193c3f2 100644
--- a/arch/x86/include/asm/unistd_64.h
+++ b/arch/x86/include/asm/unistd_64.h
@@ -624,7 +624,6 @@ __SYSCALL(__NR_vmsplice, sys_vmsplice)
__SYSCALL(__NR_move_pages, sys_move_pages)
#define __NR_utimensat 280
__SYSCALL(__NR_utimensat, sys_utimensat)
-#define __IGNORE_getcpu /* implemented as a vsyscall */
#define __NR_epoll_pwait 281
__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
#define __NR_signalfd 282
@@ -683,6 +682,10 @@ __SYSCALL(__NR_sendmmsg, sys_sendmmsg)
__SYSCALL(__NR_setns, sys_setns)
#define __NR_getcpu 309
__SYSCALL(__NR_getcpu, sys_getcpu)
+#define __NR_process_vm_readv 310
+__SYSCALL(__NR_process_vm_readv, sys_process_vm_readv)
+#define __NR_process_vm_writev 311
+__SYSCALL(__NR_process_vm_writev, sys_process_vm_writev)
#ifndef __NO_STUBS
#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h
index 37d369859c8e..8e862aaf0d90 100644
--- a/arch/x86/include/asm/uv/uv_bau.h
+++ b/arch/x86/include/asm/uv/uv_bau.h
@@ -55,6 +55,7 @@
#define UV_BAU_TUNABLES_DIR "sgi_uv"
#define UV_BAU_TUNABLES_FILE "bau_tunables"
#define WHITESPACE " \t\n"
+#define uv_mmask ((1UL << uv_hub_info->m_val) - 1)
#define uv_physnodeaddr(x) ((__pa((unsigned long)(x)) & uv_mmask))
#define cpubit_isset(cpu, bau_local_cpumask) \
test_bit((cpu), (bau_local_cpumask).bits)
@@ -656,11 +657,7 @@ static inline int atomic_read_short(const struct atomic_short *v)
*/
static inline int atom_asr(short i, struct atomic_short *v)
{
- short __i = i;
- asm volatile(LOCK_PREFIX "xaddw %0, %1"
- : "+r" (i), "+m" (v->counter)
- : : "memory");
- return i + __i;
+ return i + xadd(&v->counter, i);
}
/*
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index f26544a15214..54a13aaebc40 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -46,6 +46,13 @@
* PNODE - the low N bits of the GNODE. The PNODE is the most useful variant
* of the nasid for socket usage.
*
+ * GPA - (global physical address) a socket physical address converted
+ * so that it can be used by the GRU as a global address. Socket
+ * physical addresses 1) need additional NASID (node) bits added
+ * to the high end of the address, and 2) unaliased if the
+ * partition does not have a physical address 0. In addition, on
+ * UV2 rev 1, GPAs need the gnode left shifted to bits 39 or 40.
+ *
*
* NumaLink Global Physical Address Format:
* +--------------------------------+---------------------+
@@ -141,6 +148,8 @@ struct uv_hub_info_s {
unsigned int gnode_extra;
unsigned char hub_revision;
unsigned char apic_pnode_shift;
+ unsigned char m_shift;
+ unsigned char n_lshift;
unsigned long gnode_upper;
unsigned long lowmem_remap_top;
unsigned long lowmem_remap_base;
@@ -177,6 +186,16 @@ static inline int is_uv2_hub(void)
return uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE;
}
+static inline int is_uv2_1_hub(void)
+{
+ return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE;
+}
+
+static inline int is_uv2_2_hub(void)
+{
+ return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE + 1;
+}
+
union uvh_apicid {
unsigned long v;
struct uvh_apicid_s {
@@ -276,7 +295,10 @@ static inline unsigned long uv_soc_phys_ram_to_gpa(unsigned long paddr)
{
if (paddr < uv_hub_info->lowmem_remap_top)
paddr |= uv_hub_info->lowmem_remap_base;
- return paddr | uv_hub_info->gnode_upper;
+ paddr |= uv_hub_info->gnode_upper;
+ paddr = ((paddr << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
+ ((paddr >> uv_hub_info->m_val) << uv_hub_info->n_lshift);
+ return paddr;
}
@@ -300,16 +322,19 @@ static inline unsigned long uv_gpa_to_soc_phys_ram(unsigned long gpa)
unsigned long remap_base = uv_hub_info->lowmem_remap_base;
unsigned long remap_top = uv_hub_info->lowmem_remap_top;
+ gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
+ ((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
+ gpa = gpa & uv_hub_info->gpa_mask;
if (paddr >= remap_base && paddr < remap_base + remap_top)
paddr -= remap_base;
return paddr;
}
-/* gnode -> pnode */
+/* gpa -> pnode */
static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
{
- return gpa >> uv_hub_info->m_val;
+ return gpa >> uv_hub_info->n_lshift;
}
/* gpa -> pnode */
@@ -320,6 +345,12 @@ static inline int uv_gpa_to_pnode(unsigned long gpa)
return uv_gpa_to_gnode(gpa) & n_mask;
}
+/* gpa -> node offset*/
+static inline unsigned long uv_gpa_to_offset(unsigned long gpa)
+{
+ return (gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift;
+}
+
/* pnode, offset --> socket virtual */
static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
{
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 2caf290e9895..31f180c21ce9 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -350,6 +350,18 @@ enum vmcs_field {
#define DEBUG_REG_ACCESS_REG(eq) (((eq) >> 8) & 0xf) /* 11:8, general purpose reg. */
+/*
+ * Exit Qualifications for APIC-Access
+ */
+#define APIC_ACCESS_OFFSET 0xfff /* 11:0, offset within the APIC page */
+#define APIC_ACCESS_TYPE 0xf000 /* 15:12, access type */
+#define TYPE_LINEAR_APIC_INST_READ (0 << 12)
+#define TYPE_LINEAR_APIC_INST_WRITE (1 << 12)
+#define TYPE_LINEAR_APIC_INST_FETCH (2 << 12)
+#define TYPE_LINEAR_APIC_EVENT (3 << 12)
+#define TYPE_PHYSICAL_APIC_EVENT (10 << 12)
+#define TYPE_PHYSICAL_APIC_INST (15 << 12)
+
/* segment AR */
#define SEGMENT_AR_L_MASK (1 << 13)
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index 7ff4669580cf..c34f96c2f7a0 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -12,6 +12,7 @@
#include <asm/pgtable.h>
#include <xen/interface/xen.h>
+#include <xen/grant_table.h>
#include <xen/features.h>
/* Xen machine address */
@@ -48,14 +49,11 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s,
unsigned long pfn_e);
extern int m2p_add_override(unsigned long mfn, struct page *page,
- bool clear_pte);
+ struct gnttab_map_grant_ref *kmap_op);
extern int m2p_remove_override(struct page *page, bool clear_pte);
extern struct page *m2p_find_override(unsigned long mfn);
extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
-#ifdef CONFIG_XEN_DEBUG_FS
-extern int p2m_dump_show(struct seq_file *m, void *v);
-#endif
static inline unsigned long pfn_to_mfn(unsigned long pfn)
{
unsigned long mfn;
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 82f2912155a5..8baca3c4871c 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -19,7 +19,7 @@ endif
obj-y := process_$(BITS).o signal.o entry_$(BITS).o
obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
-obj-y += time.o ioport.o ldt.o dumpstack.o
+obj-y += time.o ioport.o ldt.o dumpstack.o nmi.o
obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o
obj-$(CONFIG_IRQ_WORK) += irq_work.o
obj-y += probe_roms.o
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index 8a439d364b94..b1e7c7f7a0af 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -5,7 +5,7 @@
* This allows to use PCI devices that only support 32bit addresses on systems
* with more than 4GB.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt for the interface specification.
+ * See Documentation/DMA-API-HOWTO.txt for the interface specification.
*
* Copyright 2002 Andi Kleen, SuSE Labs.
* Subject to the GNU General Public License v2 only.
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 52fa56399a50..a2fd72e0ab35 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1437,27 +1437,21 @@ void enable_x2apic(void)
int __init enable_IR(void)
{
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
if (!intr_remapping_supported()) {
pr_debug("intr-remapping not supported\n");
- return 0;
+ return -1;
}
if (!x2apic_preenabled && skip_ioapic_setup) {
pr_info("Skipped enabling intr-remap because of skipping "
"io-apic setup\n");
- return 0;
+ return -1;
}
- if (enable_intr_remapping(x2apic_supported()))
- return 0;
-
- pr_info("Enabled Interrupt-remapping\n");
-
- return 1;
-
+ return enable_intr_remapping();
#endif
- return 0;
+ return -1;
}
void __init enable_IR_x2apic(void)
@@ -1481,11 +1475,11 @@ void __init enable_IR_x2apic(void)
mask_ioapic_entries();
if (dmar_table_init_ret)
- ret = 0;
+ ret = -1;
else
ret = enable_IR();
- if (!ret) {
+ if (ret < 0) {
/* IR is required if there is APIC ID > 255 even when running
* under KVM
*/
@@ -1499,6 +1493,9 @@ void __init enable_IR_x2apic(void)
x2apic_force_phys();
}
+ if (ret == IRQ_REMAP_XAPIC_MODE)
+ goto nox2apic;
+
x2apic_enabled = 1;
if (x2apic_supported() && !x2apic_mode) {
@@ -1508,19 +1505,21 @@ void __init enable_IR_x2apic(void)
}
nox2apic:
- if (!ret) /* IR enabling failed */
+ if (ret < 0) /* IR enabling failed */
restore_ioapic_entries();
legacy_pic->restore_mask();
local_irq_restore(flags);
out:
- if (x2apic_enabled)
+ if (x2apic_enabled || !x2apic_supported())
return;
if (x2apic_preenabled)
panic("x2apic: enabled by BIOS but kernel init failed.");
- else if (cpu_has_x2apic)
- pr_info("Not enabling x2apic, Intr-remapping init failed.\n");
+ else if (ret == IRQ_REMAP_XAPIC_MODE)
+ pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
+ else if (ret < 0)
+ pr_info("x2apic not enabled, IRQ remapping init failed\n");
}
#ifdef CONFIG_X86_64
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index efd737e827f4..521bead01137 100644
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -255,12 +255,24 @@ static struct apic apic_bigsmp = {
.x86_32_early_logical_apicid = bigsmp_early_logical_apicid,
};
-struct apic * __init generic_bigsmp_probe(void)
+void __init generic_bigsmp_probe(void)
{
- if (probe_bigsmp())
- return &apic_bigsmp;
+ unsigned int cpu;
- return NULL;
+ if (!probe_bigsmp())
+ return;
+
+ apic = &apic_bigsmp;
+
+ for_each_possible_cpu(cpu) {
+ if (early_per_cpu(x86_cpu_to_logical_apicid,
+ cpu) == BAD_APICID)
+ continue;
+ early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
+ bigsmp_early_logical_apicid(cpu);
+ }
+
+ pr_info("Overriding APIC driver with %s\n", apic_bigsmp.name);
}
apic_driver(apic_bigsmp);
diff --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c
index d5e57db0f7be..31cb9ae992b7 100644
--- a/arch/x86/kernel/apic/hw_nmi.c
+++ b/arch/x86/kernel/apic/hw_nmi.c
@@ -60,22 +60,10 @@ void arch_trigger_all_cpu_backtrace(void)
}
static int __kprobes
-arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self,
- unsigned long cmd, void *__args)
+arch_trigger_all_cpu_backtrace_handler(unsigned int cmd, struct pt_regs *regs)
{
- struct die_args *args = __args;
- struct pt_regs *regs;
int cpu;
- switch (cmd) {
- case DIE_NMI:
- break;
-
- default:
- return NOTIFY_DONE;
- }
-
- regs = args->regs;
cpu = smp_processor_id();
if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
@@ -86,21 +74,16 @@ arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self,
show_regs(regs);
arch_spin_unlock(&lock);
cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
- return NOTIFY_STOP;
+ return NMI_HANDLED;
}
- return NOTIFY_DONE;
+ return NMI_DONE;
}
-static __read_mostly struct notifier_block backtrace_notifier = {
- .notifier_call = arch_trigger_all_cpu_backtrace_handler,
- .next = NULL,
- .priority = NMI_LOCAL_LOW_PRIOR,
-};
-
static int __init register_trigger_all_cpu_backtrace(void)
{
- register_die_notifier(&backtrace_notifier);
+ register_nmi_handler(NMI_LOCAL, arch_trigger_all_cpu_backtrace_handler,
+ 0, "arch_bt");
return 0;
}
early_initcall(register_trigger_all_cpu_backtrace);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 8eb863e27ea6..3c31fa98af6d 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -92,21 +92,21 @@ static struct ioapic {
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} ioapics[MAX_IO_APICS];
-#define mpc_ioapic_ver(id) ioapics[id].mp_config.apicver
+#define mpc_ioapic_ver(ioapic_idx) ioapics[ioapic_idx].mp_config.apicver
-int mpc_ioapic_id(int id)
+int mpc_ioapic_id(int ioapic_idx)
{
- return ioapics[id].mp_config.apicid;
+ return ioapics[ioapic_idx].mp_config.apicid;
}
-unsigned int mpc_ioapic_addr(int id)
+unsigned int mpc_ioapic_addr(int ioapic_idx)
{
- return ioapics[id].mp_config.apicaddr;
+ return ioapics[ioapic_idx].mp_config.apicaddr;
}
-struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int id)
+struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int ioapic_idx)
{
- return &ioapics[id].gsi_config;
+ return &ioapics[ioapic_idx].gsi_config;
}
int nr_ioapics;
@@ -186,11 +186,7 @@ static struct irq_pin_list *alloc_irq_pin_list(int node)
/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-#ifdef CONFIG_SPARSE_IRQ
static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
-#else
-static struct irq_cfg irq_cfgx[NR_IRQS];
-#endif
int __init arch_early_irq_init(void)
{
@@ -234,7 +230,6 @@ int __init arch_early_irq_init(void)
return 0;
}
-#ifdef CONFIG_SPARSE_IRQ
static struct irq_cfg *irq_cfg(unsigned int irq)
{
return irq_get_chip_data(irq);
@@ -269,22 +264,6 @@ static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg)
kfree(cfg);
}
-#else
-
-struct irq_cfg *irq_cfg(unsigned int irq)
-{
- return irq < nr_irqs ? irq_cfgx + irq : NULL;
-}
-
-static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
-{
- return irq_cfgx + irq;
-}
-
-static inline void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) { }
-
-#endif
-
static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
{
int res = irq_alloc_desc_at(at, node);
@@ -394,13 +373,21 @@ union entry_union {
struct IO_APIC_route_entry entry;
};
+static struct IO_APIC_route_entry __ioapic_read_entry(int apic, int pin)
+{
+ union entry_union eu;
+
+ eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+ eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+ return eu.entry;
+}
+
static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
{
union entry_union eu;
unsigned long flags;
raw_spin_lock_irqsave(&ioapic_lock, flags);
- eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
- eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+ eu.entry = __ioapic_read_entry(apic, pin);
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
return eu.entry;
}
@@ -529,18 +516,6 @@ static void io_apic_modify_irq(struct irq_cfg *cfg,
__io_apic_modify_irq(entry, mask_and, mask_or, final);
}
-static void __mask_and_edge_IO_APIC_irq(struct irq_pin_list *entry)
-{
- __io_apic_modify_irq(entry, ~IO_APIC_REDIR_LEVEL_TRIGGER,
- IO_APIC_REDIR_MASKED, NULL);
-}
-
-static void __unmask_and_level_IO_APIC_irq(struct irq_pin_list *entry)
-{
- __io_apic_modify_irq(entry, ~IO_APIC_REDIR_MASKED,
- IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
-}
-
static void io_apic_sync(struct irq_pin_list *entry)
{
/*
@@ -585,6 +560,66 @@ static void unmask_ioapic_irq(struct irq_data *data)
unmask_ioapic(data->chip_data);
}
+/*
+ * IO-APIC versions below 0x20 don't support EOI register.
+ * For the record, here is the information about various versions:
+ * 0Xh 82489DX
+ * 1Xh I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
+ * 2Xh I/O(x)APIC which is PCI 2.2 Compliant
+ * 30h-FFh Reserved
+ *
+ * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic
+ * version as 0x2. This is an error with documentation and these ICH chips
+ * use io-apic's of version 0x20.
+ *
+ * For IO-APIC's with EOI register, we use that to do an explicit EOI.
+ * Otherwise, we simulate the EOI message manually by changing the trigger
+ * mode to edge and then back to level, with RTE being masked during this.
+ */
+static void __eoi_ioapic_pin(int apic, int pin, int vector, struct irq_cfg *cfg)
+{
+ if (mpc_ioapic_ver(apic) >= 0x20) {
+ /*
+ * Intr-remapping uses pin number as the virtual vector
+ * in the RTE. Actual vector is programmed in
+ * intr-remapping table entry. Hence for the io-apic
+ * EOI we use the pin number.
+ */
+ if (cfg && irq_remapped(cfg))
+ io_apic_eoi(apic, pin);
+ else
+ io_apic_eoi(apic, vector);
+ } else {
+ struct IO_APIC_route_entry entry, entry1;
+
+ entry = entry1 = __ioapic_read_entry(apic, pin);
+
+ /*
+ * Mask the entry and change the trigger mode to edge.
+ */
+ entry1.mask = 1;
+ entry1.trigger = IOAPIC_EDGE;
+
+ __ioapic_write_entry(apic, pin, entry1);
+
+ /*
+ * Restore the previous level triggered entry.
+ */
+ __ioapic_write_entry(apic, pin, entry);
+ }
+}
+
+static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+{
+ struct irq_pin_list *entry;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&ioapic_lock, flags);
+ for_each_irq_pin(entry, cfg->irq_2_pin)
+ __eoi_ioapic_pin(entry->apic, entry->pin, cfg->vector, cfg);
+ raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
{
struct IO_APIC_route_entry entry;
@@ -593,10 +628,44 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
entry = ioapic_read_entry(apic, pin);
if (entry.delivery_mode == dest_SMI)
return;
+
+ /*
+ * Make sure the entry is masked and re-read the contents to check
+ * if it is a level triggered pin and if the remote-IRR is set.
+ */
+ if (!entry.mask) {
+ entry.mask = 1;
+ ioapic_write_entry(apic, pin, entry);
+ entry = ioapic_read_entry(apic, pin);
+ }
+
+ if (entry.irr) {
+ unsigned long flags;
+
+ /*
+ * Make sure the trigger mode is set to level. Explicit EOI
+ * doesn't clear the remote-IRR if the trigger mode is not
+ * set to level.
+ */
+ if (!entry.trigger) {
+ entry.trigger = IOAPIC_LEVEL;
+ ioapic_write_entry(apic, pin, entry);
+ }
+
+ raw_spin_lock_irqsave(&ioapic_lock, flags);
+ __eoi_ioapic_pin(apic, pin, entry.vector, NULL);
+ raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+
/*
- * Disable it in the IO-APIC irq-routing table:
+ * Clear the rest of the bits in the IO-APIC RTE except for the mask
+ * bit.
*/
ioapic_mask_entry(apic, pin);
+ entry = ioapic_read_entry(apic, pin);
+ if (entry.irr)
+ printk(KERN_ERR "Unable to reset IRR for apic: %d, pin :%d\n",
+ mpc_ioapic_id(apic), pin);
}
static void clear_IO_APIC (void)
@@ -712,13 +781,13 @@ int restore_ioapic_entries(void)
/*
* Find the IRQ entry number of a certain pin.
*/
-static int find_irq_entry(int apic, int pin, int type)
+static int find_irq_entry(int ioapic_idx, int pin, int type)
{
int i;
for (i = 0; i < mp_irq_entries; i++)
if (mp_irqs[i].irqtype == type &&
- (mp_irqs[i].dstapic == mpc_ioapic_id(apic) ||
+ (mp_irqs[i].dstapic == mpc_ioapic_id(ioapic_idx) ||
mp_irqs[i].dstapic == MP_APIC_ALL) &&
mp_irqs[i].dstirq == pin)
return i;
@@ -757,12 +826,13 @@ static int __init find_isa_irq_apic(int irq, int type)
(mp_irqs[i].srcbusirq == irq))
break;
}
+
if (i < mp_irq_entries) {
- int apic;
- for(apic = 0; apic < nr_ioapics; apic++) {
- if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic)
- return apic;
- }
+ int ioapic_idx;
+
+ for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic)
+ return ioapic_idx;
}
return -1;
@@ -977,7 +1047,7 @@ static int pin_2_irq(int idx, int apic, int pin)
int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
struct io_apic_irq_attr *irq_attr)
{
- int apic, i, best_guess = -1;
+ int ioapic_idx, i, best_guess = -1;
apic_printk(APIC_DEBUG,
"querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -990,8 +1060,8 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].srcbus;
- for (apic = 0; apic < nr_ioapics; apic++)
- if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic ||
+ for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic ||
mp_irqs[i].dstapic == MP_APIC_ALL)
break;
@@ -999,13 +1069,13 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
!mp_irqs[i].irqtype &&
(bus == lbus) &&
(slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
- int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
+ int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
- if (!(apic || IO_APIC_IRQ(irq)))
+ if (!(ioapic_idx || IO_APIC_IRQ(irq)))
continue;
if (pin == (mp_irqs[i].srcbusirq & 3)) {
- set_io_apic_irq_attr(irq_attr, apic,
+ set_io_apic_irq_attr(irq_attr, ioapic_idx,
mp_irqs[i].dstirq,
irq_trigger(i),
irq_polarity(i));
@@ -1016,7 +1086,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
* best-guess fuzzy result for broken mptables.
*/
if (best_guess < 0) {
- set_io_apic_irq_attr(irq_attr, apic,
+ set_io_apic_irq_attr(irq_attr, ioapic_idx,
mp_irqs[i].dstirq,
irq_trigger(i),
irq_polarity(i));
@@ -1202,7 +1272,6 @@ void __setup_vector_irq(int cpu)
}
static struct irq_chip ioapic_chip;
-static struct irq_chip ir_ioapic_chip;
#ifdef CONFIG_X86_32
static inline int IO_APIC_irq_trigger(int irq)
@@ -1246,7 +1315,7 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg,
if (irq_remapped(cfg)) {
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
- chip = &ir_ioapic_chip;
+ irq_remap_modify_chip_defaults(chip);
fasteoi = trigger != 0;
}
@@ -1255,77 +1324,100 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg,
fasteoi ? "fasteoi" : "edge");
}
-static int setup_ioapic_entry(int apic_id, int irq,
- struct IO_APIC_route_entry *entry,
- unsigned int destination, int trigger,
- int polarity, int vector, int pin)
+
+static int setup_ir_ioapic_entry(int irq,
+ struct IR_IO_APIC_route_entry *entry,
+ unsigned int destination, int vector,
+ struct io_apic_irq_attr *attr)
{
- /*
- * add it to the IO-APIC irq-routing table:
- */
- memset(entry,0,sizeof(*entry));
+ int index;
+ struct irte irte;
+ int ioapic_id = mpc_ioapic_id(attr->ioapic);
+ struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id);
- if (intr_remapping_enabled) {
- struct intel_iommu *iommu = map_ioapic_to_ir(apic_id);
- struct irte irte;
- struct IR_IO_APIC_route_entry *ir_entry =
- (struct IR_IO_APIC_route_entry *) entry;
- int index;
+ if (!iommu) {
+ pr_warn("No mapping iommu for ioapic %d\n", ioapic_id);
+ return -ENODEV;
+ }
- if (!iommu)
- panic("No mapping iommu for ioapic %d\n", apic_id);
+ index = alloc_irte(iommu, irq, 1);
+ if (index < 0) {
+ pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id);
+ return -ENOMEM;
+ }
- index = alloc_irte(iommu, irq, 1);
- if (index < 0)
- panic("Failed to allocate IRTE for ioapic %d\n", apic_id);
+ prepare_irte(&irte, vector, destination);
- prepare_irte(&irte, vector, destination);
+ /* Set source-id of interrupt request */
+ set_ioapic_sid(&irte, ioapic_id);
- /* Set source-id of interrupt request */
- set_ioapic_sid(&irte, apic_id);
+ modify_irte(irq, &irte);
- modify_irte(irq, &irte);
+ apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
+ "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
+ "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
+ "Avail:%X Vector:%02X Dest:%08X "
+ "SID:%04X SQ:%X SVT:%X)\n",
+ attr->ioapic, irte.present, irte.fpd, irte.dst_mode,
+ irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
+ irte.avail, irte.vector, irte.dest_id,
+ irte.sid, irte.sq, irte.svt);
+
+ memset(entry, 0, sizeof(*entry));
+
+ entry->index2 = (index >> 15) & 0x1;
+ entry->zero = 0;
+ entry->format = 1;
+ entry->index = (index & 0x7fff);
+ /*
+ * IO-APIC RTE will be configured with virtual vector.
+ * irq handler will do the explicit EOI to the io-apic.
+ */
+ entry->vector = attr->ioapic_pin;
+ entry->mask = 0; /* enable IRQ */
+ entry->trigger = attr->trigger;
+ entry->polarity = attr->polarity;
- ir_entry->index2 = (index >> 15) & 0x1;
- ir_entry->zero = 0;
- ir_entry->format = 1;
- ir_entry->index = (index & 0x7fff);
- /*
- * IO-APIC RTE will be configured with virtual vector.
- * irq handler will do the explicit EOI to the io-apic.
- */
- ir_entry->vector = pin;
-
- apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
- "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
- "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
- "Avail:%X Vector:%02X Dest:%08X "
- "SID:%04X SQ:%X SVT:%X)\n",
- apic_id, irte.present, irte.fpd, irte.dst_mode,
- irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
- irte.avail, irte.vector, irte.dest_id,
- irte.sid, irte.sq, irte.svt);
- } else {
- entry->delivery_mode = apic->irq_delivery_mode;
- entry->dest_mode = apic->irq_dest_mode;
- entry->dest = destination;
- entry->vector = vector;
- }
+ /* Mask level triggered irqs.
+ * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+ */
+ if (attr->trigger)
+ entry->mask = 1;
- entry->mask = 0; /* enable IRQ */
- entry->trigger = trigger;
- entry->polarity = polarity;
+ return 0;
+}
- /* Mask level triggered irqs.
+static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
+ unsigned int destination, int vector,
+ struct io_apic_irq_attr *attr)
+{
+ if (intr_remapping_enabled)
+ return setup_ir_ioapic_entry(irq,
+ (struct IR_IO_APIC_route_entry *)entry,
+ destination, vector, attr);
+
+ memset(entry, 0, sizeof(*entry));
+
+ entry->delivery_mode = apic->irq_delivery_mode;
+ entry->dest_mode = apic->irq_dest_mode;
+ entry->dest = destination;
+ entry->vector = vector;
+ entry->mask = 0; /* enable IRQ */
+ entry->trigger = attr->trigger;
+ entry->polarity = attr->polarity;
+
+ /*
+ * Mask level triggered irqs.
* Use IRQ_DELAYED_DISABLE for edge triggered irqs.
*/
- if (trigger)
+ if (attr->trigger)
entry->mask = 1;
+
return 0;
}
-static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
- struct irq_cfg *cfg, int trigger, int polarity)
+static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
+ struct io_apic_irq_attr *attr)
{
struct IO_APIC_route_entry entry;
unsigned int dest;
@@ -1348,49 +1440,48 @@ static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
apic_printk(APIC_VERBOSE,KERN_DEBUG
"IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
"IRQ %d Mode:%i Active:%i Dest:%d)\n",
- apic_id, mpc_ioapic_id(apic_id), pin, cfg->vector,
- irq, trigger, polarity, dest);
-
+ attr->ioapic, mpc_ioapic_id(attr->ioapic), attr->ioapic_pin,
+ cfg->vector, irq, attr->trigger, attr->polarity, dest);
- if (setup_ioapic_entry(mpc_ioapic_id(apic_id), irq, &entry,
- dest, trigger, polarity, cfg->vector, pin)) {
- printk("Failed to setup ioapic entry for ioapic %d, pin %d\n",
- mpc_ioapic_id(apic_id), pin);
+ if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) {
+ pr_warn("Failed to setup ioapic entry for ioapic %d, pin %d\n",
+ mpc_ioapic_id(attr->ioapic), attr->ioapic_pin);
__clear_irq_vector(irq, cfg);
+
return;
}
- ioapic_register_intr(irq, cfg, trigger);
+ ioapic_register_intr(irq, cfg, attr->trigger);
if (irq < legacy_pic->nr_legacy_irqs)
legacy_pic->mask(irq);
- ioapic_write_entry(apic_id, pin, entry);
+ ioapic_write_entry(attr->ioapic, attr->ioapic_pin, entry);
}
-static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin)
+static bool __init io_apic_pin_not_connected(int idx, int ioapic_idx, int pin)
{
if (idx != -1)
return false;
apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
- mpc_ioapic_id(apic_id), pin);
+ mpc_ioapic_id(ioapic_idx), pin);
return true;
}
-static void __init __io_apic_setup_irqs(unsigned int apic_id)
+static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
{
int idx, node = cpu_to_node(0);
struct io_apic_irq_attr attr;
unsigned int pin, irq;
- for (pin = 0; pin < ioapics[apic_id].nr_registers; pin++) {
- idx = find_irq_entry(apic_id, pin, mp_INT);
- if (io_apic_pin_not_connected(idx, apic_id, pin))
+ for (pin = 0; pin < ioapics[ioapic_idx].nr_registers; pin++) {
+ idx = find_irq_entry(ioapic_idx, pin, mp_INT);
+ if (io_apic_pin_not_connected(idx, ioapic_idx, pin))
continue;
- irq = pin_2_irq(idx, apic_id, pin);
+ irq = pin_2_irq(idx, ioapic_idx, pin);
- if ((apic_id > 0) && (irq > 16))
+ if ((ioapic_idx > 0) && (irq > 16))
continue;
/*
@@ -1398,10 +1489,10 @@ static void __init __io_apic_setup_irqs(unsigned int apic_id)
* installed and if it returns 1:
*/
if (apic->multi_timer_check &&
- apic->multi_timer_check(apic_id, irq))
+ apic->multi_timer_check(ioapic_idx, irq))
continue;
- set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+ set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
irq_polarity(idx));
io_apic_setup_irq_pin(irq, node, &attr);
@@ -1410,12 +1501,12 @@ static void __init __io_apic_setup_irqs(unsigned int apic_id)
static void __init setup_IO_APIC_irqs(void)
{
- unsigned int apic_id;
+ unsigned int ioapic_idx;
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
- for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
- __io_apic_setup_irqs(apic_id);
+ for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ __io_apic_setup_irqs(ioapic_idx);
}
/*
@@ -1425,28 +1516,28 @@ static void __init setup_IO_APIC_irqs(void)
*/
void setup_IO_APIC_irq_extra(u32 gsi)
{
- int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
+ int ioapic_idx = 0, pin, idx, irq, node = cpu_to_node(0);
struct io_apic_irq_attr attr;
/*
* Convert 'gsi' to 'ioapic.pin'.
*/
- apic_id = mp_find_ioapic(gsi);
- if (apic_id < 0)
+ ioapic_idx = mp_find_ioapic(gsi);
+ if (ioapic_idx < 0)
return;
- pin = mp_find_ioapic_pin(apic_id, gsi);
- idx = find_irq_entry(apic_id, pin, mp_INT);
+ pin = mp_find_ioapic_pin(ioapic_idx, gsi);
+ idx = find_irq_entry(ioapic_idx, pin, mp_INT);
if (idx == -1)
return;
- irq = pin_2_irq(idx, apic_id, pin);
+ irq = pin_2_irq(idx, ioapic_idx, pin);
/* Only handle the non legacy irqs on secondary ioapics */
- if (apic_id == 0 || irq < NR_IRQS_LEGACY)
+ if (ioapic_idx == 0 || irq < NR_IRQS_LEGACY)
return;
- set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+ set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
irq_polarity(idx));
io_apic_setup_irq_pin_once(irq, node, &attr);
@@ -1455,8 +1546,8 @@ void setup_IO_APIC_irq_extra(u32 gsi)
/*
* Set up the timer pin, possibly with the 8259A-master behind.
*/
-static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin,
- int vector)
+static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
+ unsigned int pin, int vector)
{
struct IO_APIC_route_entry entry;
@@ -1487,45 +1578,29 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin,
/*
* Add it to the IO-APIC irq-routing table:
*/
- ioapic_write_entry(apic_id, pin, entry);
+ ioapic_write_entry(ioapic_idx, pin, entry);
}
-
-__apicdebuginit(void) print_IO_APIC(void)
+__apicdebuginit(void) print_IO_APIC(int ioapic_idx)
{
- int apic, i;
+ int i;
union IO_APIC_reg_00 reg_00;
union IO_APIC_reg_01 reg_01;
union IO_APIC_reg_02 reg_02;
union IO_APIC_reg_03 reg_03;
unsigned long flags;
- struct irq_cfg *cfg;
- unsigned int irq;
-
- printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
- for (i = 0; i < nr_ioapics; i++)
- printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
- mpc_ioapic_id(i), ioapics[i].nr_registers);
-
- /*
- * We are a bit conservative about what we expect. We have to
- * know about every hardware change ASAP.
- */
- printk(KERN_INFO "testing the IO APIC.......................\n");
-
- for (apic = 0; apic < nr_ioapics; apic++) {
raw_spin_lock_irqsave(&ioapic_lock, flags);
- reg_00.raw = io_apic_read(apic, 0);
- reg_01.raw = io_apic_read(apic, 1);
+ reg_00.raw = io_apic_read(ioapic_idx, 0);
+ reg_01.raw = io_apic_read(ioapic_idx, 1);
if (reg_01.bits.version >= 0x10)
- reg_02.raw = io_apic_read(apic, 2);
+ reg_02.raw = io_apic_read(ioapic_idx, 2);
if (reg_01.bits.version >= 0x20)
- reg_03.raw = io_apic_read(apic, 3);
+ reg_03.raw = io_apic_read(ioapic_idx, 3);
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
printk("\n");
- printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(apic));
+ printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(ioapic_idx));
printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID);
printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type);
@@ -1575,7 +1650,7 @@ __apicdebuginit(void) print_IO_APIC(void)
struct IO_APIC_route_entry entry;
struct IR_IO_APIC_route_entry *ir_entry;
- entry = ioapic_read_entry(apic, i);
+ entry = ioapic_read_entry(ioapic_idx, i);
ir_entry = (struct IR_IO_APIC_route_entry *) &entry;
printk(KERN_DEBUG " %02x %04X ",
i,
@@ -1596,7 +1671,7 @@ __apicdebuginit(void) print_IO_APIC(void)
} else {
struct IO_APIC_route_entry entry;
- entry = ioapic_read_entry(apic, i);
+ entry = ioapic_read_entry(ioapic_idx, i);
printk(KERN_DEBUG " %02x %02X ",
i,
entry.dest
@@ -1614,7 +1689,28 @@ __apicdebuginit(void) print_IO_APIC(void)
);
}
}
- }
+}
+
+__apicdebuginit(void) print_IO_APICs(void)
+{
+ int ioapic_idx;
+ struct irq_cfg *cfg;
+ unsigned int irq;
+
+ printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+ for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
+ mpc_ioapic_id(ioapic_idx),
+ ioapics[ioapic_idx].nr_registers);
+
+ /*
+ * We are a bit conservative about what we expect. We have to
+ * know about every hardware change ASAP.
+ */
+ printk(KERN_INFO "testing the IO APIC.......................\n");
+
+ for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ print_IO_APIC(ioapic_idx);
printk(KERN_DEBUG "IRQ to pin mappings:\n");
for_each_active_irq(irq) {
@@ -1633,8 +1729,6 @@ __apicdebuginit(void) print_IO_APIC(void)
}
printk(KERN_INFO ".................................... done.\n");
-
- return;
}
__apicdebuginit(void) print_APIC_field(int base)
@@ -1828,7 +1922,7 @@ __apicdebuginit(int) print_ICs(void)
return 0;
print_local_APICs(show_lapic);
- print_IO_APIC();
+ print_IO_APICs();
return 0;
}
@@ -1953,7 +2047,7 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
{
union IO_APIC_reg_00 reg_00;
physid_mask_t phys_id_present_map;
- int apic_id;
+ int ioapic_idx;
int i;
unsigned char old_id;
unsigned long flags;
@@ -1967,21 +2061,20 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
/*
* Set the IOAPIC ID to the value stored in the MPC table.
*/
- for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
-
+ for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) {
/* Read the register 0 value */
raw_spin_lock_irqsave(&ioapic_lock, flags);
- reg_00.raw = io_apic_read(apic_id, 0);
+ reg_00.raw = io_apic_read(ioapic_idx, 0);
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
- old_id = mpc_ioapic_id(apic_id);
+ old_id = mpc_ioapic_id(ioapic_idx);
- if (mpc_ioapic_id(apic_id) >= get_physical_broadcast()) {
+ if (mpc_ioapic_id(ioapic_idx) >= get_physical_broadcast()) {
printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
- apic_id, mpc_ioapic_id(apic_id));
+ ioapic_idx, mpc_ioapic_id(ioapic_idx));
printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
reg_00.bits.ID);
- ioapics[apic_id].mp_config.apicid = reg_00.bits.ID;
+ ioapics[ioapic_idx].mp_config.apicid = reg_00.bits.ID;
}
/*
@@ -1990,9 +2083,9 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
* 'stuck on smp_invalidate_needed IPI wait' messages.
*/
if (apic->check_apicid_used(&phys_id_present_map,
- mpc_ioapic_id(apic_id))) {
+ mpc_ioapic_id(ioapic_idx))) {
printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
- apic_id, mpc_ioapic_id(apic_id));
+ ioapic_idx, mpc_ioapic_id(ioapic_idx));
for (i = 0; i < get_physical_broadcast(); i++)
if (!physid_isset(i, phys_id_present_map))
break;
@@ -2001,14 +2094,14 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
i);
physid_set(i, phys_id_present_map);
- ioapics[apic_id].mp_config.apicid = i;
+ ioapics[ioapic_idx].mp_config.apicid = i;
} else {
physid_mask_t tmp;
- apic->apicid_to_cpu_present(mpc_ioapic_id(apic_id),
+ apic->apicid_to_cpu_present(mpc_ioapic_id(ioapic_idx),
&tmp);
apic_printk(APIC_VERBOSE, "Setting %d in the "
"phys_id_present_map\n",
- mpc_ioapic_id(apic_id));
+ mpc_ioapic_id(ioapic_idx));
physids_or(phys_id_present_map, phys_id_present_map, tmp);
}
@@ -2016,35 +2109,35 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
* We need to adjust the IRQ routing table
* if the ID changed.
*/
- if (old_id != mpc_ioapic_id(apic_id))
+ if (old_id != mpc_ioapic_id(ioapic_idx))
for (i = 0; i < mp_irq_entries; i++)
if (mp_irqs[i].dstapic == old_id)
mp_irqs[i].dstapic
- = mpc_ioapic_id(apic_id);
+ = mpc_ioapic_id(ioapic_idx);
/*
* Update the ID register according to the right value
* from the MPC table if they are different.
*/
- if (mpc_ioapic_id(apic_id) == reg_00.bits.ID)
+ if (mpc_ioapic_id(ioapic_idx) == reg_00.bits.ID)
continue;
apic_printk(APIC_VERBOSE, KERN_INFO
"...changing IO-APIC physical APIC ID to %d ...",
- mpc_ioapic_id(apic_id));
+ mpc_ioapic_id(ioapic_idx));
- reg_00.bits.ID = mpc_ioapic_id(apic_id);
+ reg_00.bits.ID = mpc_ioapic_id(ioapic_idx);
raw_spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic_id, 0, reg_00.raw);
+ io_apic_write(ioapic_idx, 0, reg_00.raw);
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
/*
* Sanity check
*/
raw_spin_lock_irqsave(&ioapic_lock, flags);
- reg_00.raw = io_apic_read(apic_id, 0);
+ reg_00.raw = io_apic_read(ioapic_idx, 0);
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
- if (reg_00.bits.ID != mpc_ioapic_id(apic_id))
+ if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx))
printk("could not set ID!\n");
else
apic_printk(APIC_VERBOSE, " ok.\n");
@@ -2255,7 +2348,7 @@ ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
return ret;
}
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
/*
* Migrate the IO-APIC irq in the presence of intr-remapping.
@@ -2267,6 +2360,9 @@ ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
* updated vector information), by using a virtual vector (io-apic pin number).
* Real vector that is used for interrupting cpu will be coming from
* the interrupt-remapping table entry.
+ *
+ * As the migration is a simple atomic update of IRTE, the same mechanism
+ * is used to migrate MSI irq's in the presence of interrupt-remapping.
*/
static int
ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
@@ -2291,10 +2387,16 @@ ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
irte.dest_id = IRTE_DEST(dest);
/*
- * Modified the IRTE and flushes the Interrupt entry cache.
+ * Atomically updates the IRTE with the new destination, vector
+ * and flushes the interrupt entry cache.
*/
modify_irte(irq, &irte);
+ /*
+ * After this point, all the interrupts will start arriving
+ * at the new destination. So, time to cleanup the previous
+ * vector allocation.
+ */
if (cfg->move_in_progress)
send_cleanup_vector(cfg);
@@ -2407,48 +2509,6 @@ static void ack_apic_edge(struct irq_data *data)
atomic_t irq_mis_count;
-/*
- * IO-APIC versions below 0x20 don't support EOI register.
- * For the record, here is the information about various versions:
- * 0Xh 82489DX
- * 1Xh I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
- * 2Xh I/O(x)APIC which is PCI 2.2 Compliant
- * 30h-FFh Reserved
- *
- * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic
- * version as 0x2. This is an error with documentation and these ICH chips
- * use io-apic's of version 0x20.
- *
- * For IO-APIC's with EOI register, we use that to do an explicit EOI.
- * Otherwise, we simulate the EOI message manually by changing the trigger
- * mode to edge and then back to level, with RTE being masked during this.
-*/
-static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
-{
- struct irq_pin_list *entry;
- unsigned long flags;
-
- raw_spin_lock_irqsave(&ioapic_lock, flags);
- for_each_irq_pin(entry, cfg->irq_2_pin) {
- if (mpc_ioapic_ver(entry->apic) >= 0x20) {
- /*
- * Intr-remapping uses pin number as the virtual vector
- * in the RTE. Actual vector is programmed in
- * intr-remapping table entry. Hence for the io-apic
- * EOI we use the pin number.
- */
- if (irq_remapped(cfg))
- io_apic_eoi(entry->apic, entry->pin);
- else
- io_apic_eoi(entry->apic, cfg->vector);
- } else {
- __mask_and_edge_IO_APIC_irq(entry);
- __unmask_and_level_IO_APIC_irq(entry);
- }
- }
- raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
static void ack_apic_level(struct irq_data *data)
{
struct irq_cfg *cfg = data->chip_data;
@@ -2552,7 +2612,7 @@ static void ack_apic_level(struct irq_data *data)
}
}
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
static void ir_ack_apic_edge(struct irq_data *data)
{
ack_APIC_irq();
@@ -2563,7 +2623,23 @@ static void ir_ack_apic_level(struct irq_data *data)
ack_APIC_irq();
eoi_ioapic_irq(data->irq, data->chip_data);
}
-#endif /* CONFIG_INTR_REMAP */
+
+static void ir_print_prefix(struct irq_data *data, struct seq_file *p)
+{
+ seq_printf(p, " IR-%s", data->chip->name);
+}
+
+static void irq_remap_modify_chip_defaults(struct irq_chip *chip)
+{
+ chip->irq_print_chip = ir_print_prefix;
+ chip->irq_ack = ir_ack_apic_edge;
+ chip->irq_eoi = ir_ack_apic_level;
+
+#ifdef CONFIG_SMP
+ chip->irq_set_affinity = ir_ioapic_set_affinity;
+#endif
+}
+#endif /* CONFIG_IRQ_REMAP */
static struct irq_chip ioapic_chip __read_mostly = {
.name = "IO-APIC",
@@ -2578,21 +2654,6 @@ static struct irq_chip ioapic_chip __read_mostly = {
.irq_retrigger = ioapic_retrigger_irq,
};
-static struct irq_chip ir_ioapic_chip __read_mostly = {
- .name = "IR-IO-APIC",
- .irq_startup = startup_ioapic_irq,
- .irq_mask = mask_ioapic_irq,
- .irq_unmask = unmask_ioapic_irq,
-#ifdef CONFIG_INTR_REMAP
- .irq_ack = ir_ack_apic_edge,
- .irq_eoi = ir_ack_apic_level,
-#ifdef CONFIG_SMP
- .irq_set_affinity = ir_ioapic_set_affinity,
-#endif
-#endif
- .irq_retrigger = ioapic_retrigger_irq,
-};
-
static inline void init_IO_APIC_traps(void)
{
struct irq_cfg *cfg;
@@ -2944,27 +3005,26 @@ static int __init io_apic_bug_finalize(void)
late_initcall(io_apic_bug_finalize);
-static void resume_ioapic_id(int ioapic_id)
+static void resume_ioapic_id(int ioapic_idx)
{
unsigned long flags;
union IO_APIC_reg_00 reg_00;
-
raw_spin_lock_irqsave(&ioapic_lock, flags);
- reg_00.raw = io_apic_read(ioapic_id, 0);
- if (reg_00.bits.ID != mpc_ioapic_id(ioapic_id)) {
- reg_00.bits.ID = mpc_ioapic_id(ioapic_id);
- io_apic_write(ioapic_id, 0, reg_00.raw);
+ reg_00.raw = io_apic_read(ioapic_idx, 0);
+ if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx)) {
+ reg_00.bits.ID = mpc_ioapic_id(ioapic_idx);
+ io_apic_write(ioapic_idx, 0, reg_00.raw);
}
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
}
static void ioapic_resume(void)
{
- int ioapic_id;
+ int ioapic_idx;
- for (ioapic_id = nr_ioapics - 1; ioapic_id >= 0; ioapic_id--)
- resume_ioapic_id(ioapic_id);
+ for (ioapic_idx = nr_ioapics - 1; ioapic_idx >= 0; ioapic_idx--)
+ resume_ioapic_id(ioapic_idx);
restore_ioapic_entries();
}
@@ -3144,45 +3204,6 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
return 0;
}
-#ifdef CONFIG_INTR_REMAP
-/*
- * Migrate the MSI irq to another cpumask. This migration is
- * done in the process context using interrupt-remapping hardware.
- */
-static int
-ir_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
- bool force)
-{
- struct irq_cfg *cfg = data->chip_data;
- unsigned int dest, irq = data->irq;
- struct irte irte;
-
- if (get_irte(irq, &irte))
- return -1;
-
- if (__ioapic_set_affinity(data, mask, &dest))
- return -1;
-
- irte.vector = cfg->vector;
- irte.dest_id = IRTE_DEST(dest);
-
- /*
- * atomically update the IRTE with the new destination and vector.
- */
- modify_irte(irq, &irte);
-
- /*
- * After this point, all the interrupts will start arriving
- * at the new destination. So, time to cleanup the previous
- * vector allocation.
- */
- if (cfg->move_in_progress)
- send_cleanup_vector(cfg);
-
- return 0;
-}
-
-#endif
#endif /* CONFIG_SMP */
/*
@@ -3200,19 +3221,6 @@ static struct irq_chip msi_chip = {
.irq_retrigger = ioapic_retrigger_irq,
};
-static struct irq_chip msi_ir_chip = {
- .name = "IR-PCI-MSI",
- .irq_unmask = unmask_msi_irq,
- .irq_mask = mask_msi_irq,
-#ifdef CONFIG_INTR_REMAP
- .irq_ack = ir_ack_apic_edge,
-#ifdef CONFIG_SMP
- .irq_set_affinity = ir_msi_set_affinity,
-#endif
-#endif
- .irq_retrigger = ioapic_retrigger_irq,
-};
-
/*
* Map the PCI dev to the corresponding remapping hardware unit
* and allocate 'nvec' consecutive interrupt-remapping table entries
@@ -3255,7 +3263,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
if (irq_remapped(irq_get_chip_data(irq))) {
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
- chip = &msi_ir_chip;
+ irq_remap_modify_chip_defaults(chip);
}
irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
@@ -3328,7 +3336,7 @@ void native_teardown_msi_irq(unsigned int irq)
destroy_irq(irq);
}
-#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
+#ifdef CONFIG_DMAR_TABLE
#ifdef CONFIG_SMP
static int
dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
@@ -3409,19 +3417,6 @@ static int hpet_msi_set_affinity(struct irq_data *data,
#endif /* CONFIG_SMP */
-static struct irq_chip ir_hpet_msi_type = {
- .name = "IR-HPET_MSI",
- .irq_unmask = hpet_msi_unmask,
- .irq_mask = hpet_msi_mask,
-#ifdef CONFIG_INTR_REMAP
- .irq_ack = ir_ack_apic_edge,
-#ifdef CONFIG_SMP
- .irq_set_affinity = ir_msi_set_affinity,
-#endif
-#endif
- .irq_retrigger = ioapic_retrigger_irq,
-};
-
static struct irq_chip hpet_msi_type = {
.name = "HPET_MSI",
.irq_unmask = hpet_msi_unmask,
@@ -3458,7 +3453,7 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
hpet_msi_write(irq_get_handler_data(irq), &msg);
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
if (irq_remapped(irq_get_chip_data(irq)))
- chip = &ir_hpet_msi_type;
+ irq_remap_modify_chip_defaults(chip);
irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
return 0;
@@ -3566,26 +3561,25 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
return -EINVAL;
ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin);
if (!ret)
- setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg,
- attr->trigger, attr->polarity);
+ setup_ioapic_irq(irq, cfg, attr);
return ret;
}
int io_apic_setup_irq_pin_once(unsigned int irq, int node,
struct io_apic_irq_attr *attr)
{
- unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
+ unsigned int ioapic_idx = attr->ioapic, pin = attr->ioapic_pin;
int ret;
/* Avoid redundant programming */
- if (test_bit(pin, ioapics[id].pin_programmed)) {
+ if (test_bit(pin, ioapics[ioapic_idx].pin_programmed)) {
pr_debug("Pin %d-%d already programmed\n",
- mpc_ioapic_id(id), pin);
+ mpc_ioapic_id(ioapic_idx), pin);
return 0;
}
ret = io_apic_setup_irq_pin(irq, node, attr);
if (!ret)
- set_bit(pin, ioapics[id].pin_programmed);
+ set_bit(pin, ioapics[ioapic_idx].pin_programmed);
return ret;
}
@@ -3621,7 +3615,6 @@ int get_nr_irqs_gsi(void)
return nr_irqs_gsi;
}
-#ifdef CONFIG_SPARSE_IRQ
int __init arch_probe_nr_irqs(void)
{
int nr;
@@ -3641,7 +3634,6 @@ int __init arch_probe_nr_irqs(void)
return NR_IRQS_LEGACY;
}
-#endif
int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr)
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index b5254ad044ab..0787bb3412f4 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -200,14 +200,8 @@ void __init default_setup_apic_routing(void)
* - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
*/
- if (!cmdline_apic && apic == &apic_default) {
- struct apic *bigsmp = generic_bigsmp_probe();
- if (bigsmp) {
- apic = bigsmp;
- printk(KERN_INFO "Overriding APIC driver with %s\n",
- apic->name);
- }
- }
+ if (!cmdline_apic && apic == &apic_default)
+ generic_bigsmp_probe();
#endif
if (apic->setup_apic_routing)
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 34b18594e724..62ae3001ae02 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -672,18 +672,11 @@ void __cpuinit uv_cpu_init(void)
/*
* When NMI is received, print a stack trace.
*/
-int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
+int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
{
unsigned long real_uv_nmi;
int bid;
- if (reason != DIE_NMIUNKNOWN)
- return NOTIFY_OK;
-
- if (in_crash_kexec)
- /* do nothing if entering the crash kernel */
- return NOTIFY_OK;
-
/*
* Each blade has an MMR that indicates when an NMI has been sent
* to cpus on the blade. If an NMI is detected, atomically
@@ -704,7 +697,7 @@ int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
}
if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))
- return NOTIFY_DONE;
+ return NMI_DONE;
__get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
@@ -717,17 +710,12 @@ int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
dump_stack();
spin_unlock(&uv_nmi_lock);
- return NOTIFY_STOP;
+ return NMI_HANDLED;
}
-static struct notifier_block uv_dump_stack_nmi_nb = {
- .notifier_call = uv_handle_nmi,
- .priority = NMI_LOCAL_LOW_PRIOR - 1,
-};
-
void uv_register_nmi_notifier(void)
{
- if (register_die_notifier(&uv_dump_stack_nmi_nb))
+ if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
printk(KERN_WARNING "UV NMI handler failed to register\n");
}
@@ -832,6 +820,10 @@ void __init uv_system_init(void)
uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
uv_cpu_hub_info(cpu)->hub_revision = uv_hub_info->hub_revision;
+ uv_cpu_hub_info(cpu)->m_shift = 64 - m_val;
+ uv_cpu_hub_info(cpu)->n_lshift = is_uv2_1_hub() ?
+ (m_val == 40 ? 40 : 39) : m_val;
+
pnode = uv_apicid_to_pnode(apicid);
blade = boot_pnode_to_blade(pnode);
lcpu = uv_blade_info[blade].nr_possible_cpus;
@@ -862,8 +854,7 @@ void __init uv_system_init(void)
if (uv_node_to_blade[nid] >= 0)
continue;
paddr = node_start_pfn(nid) << PAGE_SHIFT;
- paddr = uv_soc_phys_ram_to_gpa(paddr);
- pnode = (paddr >> m_val) & pnode_mask;
+ pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr));
blade = boot_pnode_to_blade(pnode);
uv_node_to_blade[nid] = blade;
}
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 0371c484bb8a..a46bd383953c 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -249,8 +249,6 @@ extern int (*console_blank_hook)(int);
#define APM_MINOR_DEV 134
/*
- * See Documentation/Config.help for the configuration options.
- *
* Various options can be changed at boot time as follows:
* (We allow underscores for compatibility with the modules code)
* apm=on/off enable/disable APM
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 6042981d0309..25f24dccdcfa 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -15,6 +15,7 @@ CFLAGS_common.o := $(nostackp)
obj-y := intel_cacheinfo.o scattered.o topology.o
obj-y += proc.o capflags.o powerflags.o common.o
obj-y += vmware.o hypervisor.o sched.o mshyperv.o
+obj-y += rdrand.o
obj-$(CONFIG_X86_32) += bugs.o
obj-$(CONFIG_X86_64) += bugs_64.o
@@ -28,10 +29,15 @@ obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
+ifdef CONFIG_PERF_EVENTS
+obj-$(CONFIG_CPU_SUP_AMD) += perf_event_amd.o
+obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_p6.o perf_event_p4.o perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
+endif
+
obj-$(CONFIG_X86_MCE) += mcheck/
obj-$(CONFIG_MTRR) += mtrr/
-obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o
+obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o perf_event_amd_ibs.o
quiet_cmd_mkcapflags = MKCAP $@
cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index b13ed393dfce..46ae4f65fc7f 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1,5 +1,6 @@
#include <linux/init.h>
#include <linux/bitops.h>
+#include <linux/elf.h>
#include <linux/mm.h>
#include <linux/io.h>
@@ -410,8 +411,38 @@ static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c)
#endif
}
+static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c)
+{
+ if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+
+ if (c->x86 > 0x10 ||
+ (c->x86 == 0x10 && c->x86_model >= 0x2)) {
+ u64 val;
+
+ rdmsrl(MSR_K7_HWCR, val);
+ if (!(val & BIT(24)))
+ printk(KERN_WARNING FW_BUG "TSC doesn't count "
+ "with P0 frequency!\n");
+ }
+ }
+
+ if (c->x86 == 0x15) {
+ unsigned long upperbit;
+ u32 cpuid, assoc;
+
+ cpuid = cpuid_edx(0x80000005);
+ assoc = cpuid >> 16 & 0xff;
+ upperbit = ((cpuid >> 24) << 10) / assoc;
+
+ va_align.mask = (upperbit - 1) & PAGE_MASK;
+ va_align.flags = ALIGN_VA_32 | ALIGN_VA_64;
+ }
+}
+
static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
{
+ u32 dummy;
+
early_init_amd_mc(c);
/*
@@ -442,22 +473,7 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
}
#endif
- /* We need to do the following only once */
- if (c != &boot_cpu_data)
- return;
-
- if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
-
- if (c->x86 > 0x10 ||
- (c->x86 == 0x10 && c->x86_model >= 0x2)) {
- u64 val;
-
- rdmsrl(MSR_K7_HWCR, val);
- if (!(val & BIT(24)))
- printk(KERN_WARNING FW_BUG "TSC doesn't count "
- "with P0 frequency!\n");
- }
- }
+ rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
}
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
@@ -679,6 +695,7 @@ static const struct cpu_dev __cpuinitconst amd_cpu_dev = {
.c_size_cache = amd_size_cache,
#endif
.c_early_init = early_init_amd,
+ .c_bsp_init = bsp_init_amd,
.c_init = init_amd,
.c_x86_vendor = X86_VENDOR_AMD,
};
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 62184390a601..aa003b13a831 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -15,6 +15,7 @@
#include <asm/stackprotector.h>
#include <asm/perf_event.h>
#include <asm/mmu_context.h>
+#include <asm/archrandom.h>
#include <asm/hypervisor.h>
#include <asm/processor.h>
#include <asm/sections.h>
@@ -681,6 +682,9 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
filter_cpuid_features(c, false);
setup_smep(c);
+
+ if (this_cpu->c_bsp_init)
+ this_cpu->c_bsp_init(c);
}
void __init early_cpu_init(void)
@@ -857,6 +861,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
#endif
init_hypervisor(c);
+ x86_init_rdrand(c);
/*
* Clear/Set all flags overriden by options, need do it
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index e765633f210e..1b22dcc51af4 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -18,6 +18,7 @@ struct cpu_dev {
struct cpu_model_info c_models[4];
void (*c_early_init)(struct cpuinfo_x86 *);
+ void (*c_bsp_init)(struct cpuinfo_x86 *);
void (*c_init)(struct cpuinfo_x86 *);
void (*c_identify)(struct cpuinfo_x86 *);
unsigned int (*c_size_cache)(struct cpuinfo_x86 *, unsigned int);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index ed6086eedf1d..523131213f08 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -47,6 +47,15 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
(c->x86 == 0x6 && c->x86_model >= 0x0e))
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64)) {
+ unsigned lower_word;
+
+ wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+ /* Required by the SDM */
+ sync_core();
+ rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode);
+ }
+
/*
* Atom erratum AAE44/AAF40/AAG38/AAH41:
*
@@ -55,17 +64,10 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
* need the microcode to have already been loaded... so if it is
* not, recommend a BIOS update and disable large pages.
*/
- if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2) {
- u32 ucode, junk;
-
- wrmsr(MSR_IA32_UCODE_REV, 0, 0);
- sync_core();
- rdmsr(MSR_IA32_UCODE_REV, junk, ucode);
-
- if (ucode < 0x20e) {
- printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
- clear_cpu_cap(c, X86_FEATURE_PSE);
- }
+ if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2 &&
+ c->microcode < 0x20e) {
+ printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
+ clear_cpu_cap(c, X86_FEATURE_PSE);
}
#ifdef CONFIG_X86_64
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index c105c533ed94..a3b0811693c9 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -151,28 +151,17 @@ union _cpuid4_leaf_ecx {
u32 full;
};
-struct amd_l3_cache {
- struct amd_northbridge *nb;
- unsigned indices;
- u8 subcaches[4];
-};
-
-struct _cpuid4_info {
+struct _cpuid4_info_regs {
union _cpuid4_leaf_eax eax;
union _cpuid4_leaf_ebx ebx;
union _cpuid4_leaf_ecx ecx;
unsigned long size;
- struct amd_l3_cache *l3;
- DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
+ struct amd_northbridge *nb;
};
-/* subset of above _cpuid4_info w/o shared_cpu_map */
-struct _cpuid4_info_regs {
- union _cpuid4_leaf_eax eax;
- union _cpuid4_leaf_ebx ebx;
- union _cpuid4_leaf_ecx ecx;
- unsigned long size;
- struct amd_l3_cache *l3;
+struct _cpuid4_info {
+ struct _cpuid4_info_regs base;
+ DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
};
unsigned short num_cache_leaves;
@@ -314,16 +303,23 @@ struct _cache_attr {
/*
* L3 cache descriptors
*/
-static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
+static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb)
{
+ struct amd_l3_cache *l3 = &nb->l3_cache;
unsigned int sc0, sc1, sc2, sc3;
u32 val = 0;
- pci_read_config_dword(l3->nb->misc, 0x1C4, &val);
+ pci_read_config_dword(nb->misc, 0x1C4, &val);
/* calculate subcache sizes */
l3->subcaches[0] = sc0 = !(val & BIT(0));
l3->subcaches[1] = sc1 = !(val & BIT(4));
+
+ if (boot_cpu_data.x86 == 0x15) {
+ l3->subcaches[0] = sc0 += !(val & BIT(1));
+ l3->subcaches[1] = sc1 += !(val & BIT(5));
+ }
+
l3->subcaches[2] = sc2 = !(val & BIT(8)) + !(val & BIT(9));
l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
@@ -333,33 +329,16 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf,
int index)
{
- static struct amd_l3_cache *__cpuinitdata l3_caches;
int node;
/* only for L3, and not in virtualized environments */
- if (index < 3 || amd_nb_num() == 0)
+ if (index < 3)
return;
- /*
- * Strictly speaking, the amount in @size below is leaked since it is
- * never freed but this is done only on shutdown so it doesn't matter.
- */
- if (!l3_caches) {
- int size = amd_nb_num() * sizeof(struct amd_l3_cache);
-
- l3_caches = kzalloc(size, GFP_ATOMIC);
- if (!l3_caches)
- return;
- }
-
node = amd_get_nb_id(smp_processor_id());
-
- if (!l3_caches[node].nb) {
- l3_caches[node].nb = node_to_amd_nb(node);
- amd_calc_l3_indices(&l3_caches[node]);
- }
-
- this_leaf->l3 = &l3_caches[node];
+ this_leaf->nb = node_to_amd_nb(node);
+ if (this_leaf->nb && !this_leaf->nb->l3_cache.indices)
+ amd_calc_l3_indices(this_leaf->nb);
}
/*
@@ -369,11 +348,11 @@ static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf,
*
* @returns: the disabled index if used or negative value if slot free.
*/
-int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot)
+int amd_get_l3_disable_slot(struct amd_northbridge *nb, unsigned slot)
{
unsigned int reg = 0;
- pci_read_config_dword(l3->nb->misc, 0x1BC + slot * 4, &reg);
+ pci_read_config_dword(nb->misc, 0x1BC + slot * 4, &reg);
/* check whether this slot is activated already */
if (reg & (3UL << 30))
@@ -387,11 +366,10 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
{
int index;
- if (!this_leaf->l3 ||
- !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
+ if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
return -EINVAL;
- index = amd_get_l3_disable_slot(this_leaf->l3, slot);
+ index = amd_get_l3_disable_slot(this_leaf->base.nb, slot);
if (index >= 0)
return sprintf(buf, "%d\n", index);
@@ -408,7 +386,7 @@ show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf, \
SHOW_CACHE_DISABLE(0)
SHOW_CACHE_DISABLE(1)
-static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
+static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu,
unsigned slot, unsigned long idx)
{
int i;
@@ -421,10 +399,10 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
for (i = 0; i < 4; i++) {
u32 reg = idx | (i << 20);
- if (!l3->subcaches[i])
+ if (!nb->l3_cache.subcaches[i])
continue;
- pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg);
+ pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
/*
* We need to WBINVD on a core on the node containing the L3
@@ -434,7 +412,7 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
wbinvd_on_cpu(cpu);
reg |= BIT(31);
- pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg);
+ pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
}
}
@@ -448,24 +426,24 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
*
* @return: 0 on success, error status on failure
*/
-int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot,
+int amd_set_l3_disable_slot(struct amd_northbridge *nb, int cpu, unsigned slot,
unsigned long index)
{
int ret = 0;
/* check if @slot is already used or the index is already disabled */
- ret = amd_get_l3_disable_slot(l3, slot);
+ ret = amd_get_l3_disable_slot(nb, slot);
if (ret >= 0)
return -EINVAL;
- if (index > l3->indices)
+ if (index > nb->l3_cache.indices)
return -EINVAL;
/* check whether the other slot has disabled the same index already */
- if (index == amd_get_l3_disable_slot(l3, !slot))
+ if (index == amd_get_l3_disable_slot(nb, !slot))
return -EINVAL;
- amd_l3_disable_index(l3, cpu, slot, index);
+ amd_l3_disable_index(nb, cpu, slot, index);
return 0;
}
@@ -480,8 +458,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (!this_leaf->l3 ||
- !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
+ if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
return -EINVAL;
cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
@@ -489,7 +466,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
if (strict_strtoul(buf, 10, &val) < 0)
return -EINVAL;
- err = amd_set_l3_disable_slot(this_leaf->l3, cpu, slot, val);
+ err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val);
if (err) {
if (err == -EEXIST)
printk(KERN_WARNING "L3 disable slot %d in use!\n",
@@ -518,7 +495,7 @@ static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
static ssize_t
show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu)
{
- if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+ if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
return -EINVAL;
return sprintf(buf, "%x\n", amd_get_subcaches(cpu));
@@ -533,7 +510,7 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+ if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
return -EINVAL;
if (strict_strtoul(buf, 16, &val) < 0)
@@ -769,7 +746,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
return;
}
this_leaf = CPUID4_INFO_IDX(cpu, index);
- num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
+ num_threads_sharing = 1 + this_leaf->base.eax.split.num_threads_sharing;
if (num_threads_sharing == 1)
cpumask_set_cpu(cpu, to_cpumask(this_leaf->shared_cpu_map));
@@ -820,29 +797,19 @@ static void __cpuinit free_cache_attributes(unsigned int cpu)
for (i = 0; i < num_cache_leaves; i++)
cache_remove_shared_cpu_map(cpu, i);
- kfree(per_cpu(ici_cpuid4_info, cpu)->l3);
kfree(per_cpu(ici_cpuid4_info, cpu));
per_cpu(ici_cpuid4_info, cpu) = NULL;
}
-static int
-__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
-{
- struct _cpuid4_info_regs *leaf_regs =
- (struct _cpuid4_info_regs *)this_leaf;
-
- return cpuid4_cache_lookup_regs(index, leaf_regs);
-}
-
static void __cpuinit get_cpu_leaves(void *_retval)
{
int j, *retval = _retval, cpu = smp_processor_id();
/* Do cpuid and store the results */
for (j = 0; j < num_cache_leaves; j++) {
- struct _cpuid4_info *this_leaf;
- this_leaf = CPUID4_INFO_IDX(cpu, j);
- *retval = cpuid4_cache_lookup(j, this_leaf);
+ struct _cpuid4_info *this_leaf = CPUID4_INFO_IDX(cpu, j);
+
+ *retval = cpuid4_cache_lookup_regs(j, &this_leaf->base);
if (unlikely(*retval < 0)) {
int i;
@@ -900,16 +867,16 @@ static ssize_t show_##file_name(struct _cpuid4_info *this_leaf, char *buf, \
return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \
}
-show_one_plus(level, eax.split.level, 0);
-show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1);
-show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
-show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
-show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
+show_one_plus(level, base.eax.split.level, 0);
+show_one_plus(coherency_line_size, base.ebx.split.coherency_line_size, 1);
+show_one_plus(physical_line_partition, base.ebx.split.physical_line_partition, 1);
+show_one_plus(ways_of_associativity, base.ebx.split.ways_of_associativity, 1);
+show_one_plus(number_of_sets, base.ecx.split.number_of_sets, 1);
static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf,
unsigned int cpu)
{
- return sprintf(buf, "%luK\n", this_leaf->size / 1024);
+ return sprintf(buf, "%luK\n", this_leaf->base.size / 1024);
}
static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
@@ -946,7 +913,7 @@ static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf,
static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf,
unsigned int cpu)
{
- switch (this_leaf->eax.split.type) {
+ switch (this_leaf->base.eax.split.type) {
case CACHE_TYPE_DATA:
return sprintf(buf, "Data\n");
case CACHE_TYPE_INST:
@@ -1135,7 +1102,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
ktype_cache.default_attrs = default_attrs;
#ifdef CONFIG_AMD_NB
- if (this_leaf->l3)
+ if (this_leaf->base.nb)
ktype_cache.default_attrs = amd_l3_attrs();
#endif
retval = kobject_init_and_add(&(this_object->kobj),
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c
index 0ed633c5048b..6199232161cf 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-inject.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -78,27 +78,20 @@ static void raise_exception(struct mce *m, struct pt_regs *pregs)
static cpumask_var_t mce_inject_cpumask;
-static int mce_raise_notify(struct notifier_block *self,
- unsigned long val, void *data)
+static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs)
{
- struct die_args *args = (struct die_args *)data;
int cpu = smp_processor_id();
struct mce *m = &__get_cpu_var(injectm);
- if (val != DIE_NMI || !cpumask_test_cpu(cpu, mce_inject_cpumask))
- return NOTIFY_DONE;
+ if (!cpumask_test_cpu(cpu, mce_inject_cpumask))
+ return NMI_DONE;
cpumask_clear_cpu(cpu, mce_inject_cpumask);
if (m->inject_flags & MCJ_EXCEPTION)
- raise_exception(m, args->regs);
+ raise_exception(m, regs);
else if (m->status)
raise_poll(m);
- return NOTIFY_STOP;
+ return NMI_HANDLED;
}
-static struct notifier_block mce_raise_nb = {
- .notifier_call = mce_raise_notify,
- .priority = NMI_LOCAL_NORMAL_PRIOR,
-};
-
/* Inject mce on current CPU */
static int raise_local(void)
{
@@ -216,7 +209,8 @@ static int inject_init(void)
return -ENOMEM;
printk(KERN_INFO "Machine check injector initialized\n");
mce_chrdev_ops.write = mce_write;
- register_die_notifier(&mce_raise_nb);
+ register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0,
+ "mce_notify");
return 0;
}
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 08363b042122..864830e1dd65 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -36,7 +36,6 @@
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/debugfs.h>
-#include <linux/edac_mce.h>
#include <linux/irq_work.h>
#include <asm/processor.h>
@@ -144,23 +143,20 @@ static struct mce_log mcelog = {
void mce_log(struct mce *mce)
{
unsigned next, entry;
+ int ret = 0;
/* Emit the trace record: */
trace_mce_record(mce);
+ ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce);
+ if (ret == NOTIFY_STOP)
+ return;
+
mce->finished = 0;
wmb();
for (;;) {
entry = rcu_dereference_check_mce(mcelog.next);
for (;;) {
- /*
- * If edac_mce is enabled, it will check the error type
- * and will process it, if it is a known error.
- * Otherwise, the error will be sent through mcelog
- * interface
- */
- if (edac_mce_parse(mce))
- return;
/*
* When the buffer fills up discard new entries.
@@ -217,8 +213,13 @@ static void print_mce(struct mce *m)
pr_cont("MISC %llx ", m->misc);
pr_cont("\n");
- pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
- m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid);
+ /*
+ * Note this output is parsed by external tools and old fields
+ * should not be changed.
+ */
+ pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x microcode %x\n",
+ m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid,
+ cpu_data(m->extcpu).microcode);
/*
* Print out human-readable details about the MCE error,
@@ -551,10 +552,8 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
* Don't get the IP here because it's unlikely to
* have anything to do with the actual error location.
*/
- if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) {
+ if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce)
mce_log(&m);
- atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, &m);
- }
/*
* Clear state for this bank.
@@ -908,9 +907,6 @@ void do_machine_check(struct pt_regs *regs, long error_code)
percpu_inc(mce_exception_count);
- if (notify_die(DIE_NMI, "machine check", regs, error_code,
- 18, SIGKILL) == NOTIFY_STOP)
- goto out;
if (!banks)
goto out;
@@ -1140,6 +1136,15 @@ static void mce_start_timer(unsigned long data)
add_timer_on(t, smp_processor_id());
}
+/* Must not be called in IRQ context where del_timer_sync() can deadlock */
+static void mce_timer_delete_all(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu)
+ del_timer_sync(&per_cpu(mce_timer, cpu));
+}
+
static void mce_do_trigger(struct work_struct *work)
{
call_usermodehelper(mce_helper, mce_helper_argv, NULL, UMH_NO_WAIT);
@@ -1750,7 +1755,6 @@ static struct syscore_ops mce_syscore_ops = {
static void mce_cpu_restart(void *data)
{
- del_timer_sync(&__get_cpu_var(mce_timer));
if (!mce_available(__this_cpu_ptr(&cpu_info)))
return;
__mcheck_cpu_init_generic();
@@ -1760,16 +1764,15 @@ static void mce_cpu_restart(void *data)
/* Reinit MCEs after user configuration changes */
static void mce_restart(void)
{
+ mce_timer_delete_all();
on_each_cpu(mce_cpu_restart, NULL, 1);
}
/* Toggle features for corrected errors */
-static void mce_disable_ce(void *all)
+static void mce_disable_cmci(void *data)
{
if (!mce_available(__this_cpu_ptr(&cpu_info)))
return;
- if (all)
- del_timer_sync(&__get_cpu_var(mce_timer));
cmci_clear();
}
@@ -1852,7 +1855,8 @@ static ssize_t set_ignore_ce(struct sys_device *s,
if (mce_ignore_ce ^ !!new) {
if (new) {
/* disable ce features */
- on_each_cpu(mce_disable_ce, (void *)1, 1);
+ mce_timer_delete_all();
+ on_each_cpu(mce_disable_cmci, NULL, 1);
mce_ignore_ce = 1;
} else {
/* enable ce features */
@@ -1875,7 +1879,7 @@ static ssize_t set_cmci_disabled(struct sys_device *s,
if (mce_cmci_disabled ^ !!new) {
if (new) {
/* disable cmci */
- on_each_cpu(mce_disable_ce, NULL, 1);
+ on_each_cpu(mce_disable_cmci, NULL, 1);
mce_cmci_disabled = 1;
} else {
/* enable cmci */
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 8694ef56459d..38e49bc95ffc 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -28,7 +28,7 @@ static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
* cmci_discover_lock protects against parallel discovery attempts
* which could race against each other.
*/
-static DEFINE_SPINLOCK(cmci_discover_lock);
+static DEFINE_RAW_SPINLOCK(cmci_discover_lock);
#define CMCI_THRESHOLD 1
@@ -85,7 +85,7 @@ static void cmci_discover(int banks, int boot)
int hdr = 0;
int i;
- spin_lock_irqsave(&cmci_discover_lock, flags);
+ raw_spin_lock_irqsave(&cmci_discover_lock, flags);
for (i = 0; i < banks; i++) {
u64 val;
@@ -116,7 +116,7 @@ static void cmci_discover(int banks, int boot)
WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
}
}
- spin_unlock_irqrestore(&cmci_discover_lock, flags);
+ raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
if (hdr)
printk(KERN_CONT "\n");
}
@@ -150,7 +150,7 @@ void cmci_clear(void)
if (!cmci_supported(&banks))
return;
- spin_lock_irqsave(&cmci_discover_lock, flags);
+ raw_spin_lock_irqsave(&cmci_discover_lock, flags);
for (i = 0; i < banks; i++) {
if (!test_bit(i, __get_cpu_var(mce_banks_owned)))
continue;
@@ -160,7 +160,7 @@ void cmci_clear(void)
wrmsrl(MSR_IA32_MCx_CTL2(i), val);
__clear_bit(i, __get_cpu_var(mce_banks_owned));
}
- spin_unlock_irqrestore(&cmci_discover_lock, flags);
+ raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
}
/*
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index d944bf6c50e9..0a630dd4b620 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -11,6 +11,8 @@
*/
#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/clocksource.h>
#include <linux/module.h>
#include <asm/processor.h>
#include <asm/hypervisor.h>
@@ -36,6 +38,25 @@ static bool __init ms_hyperv_platform(void)
!memcmp("Microsoft Hv", hyp_signature, 12);
}
+static cycle_t read_hv_clock(struct clocksource *arg)
+{
+ cycle_t current_tick;
+ /*
+ * Read the partition counter to get the current tick count. This count
+ * is set to 0 when the partition is created and is incremented in
+ * 100 nanosecond units.
+ */
+ rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
+ return current_tick;
+}
+
+static struct clocksource hyperv_cs = {
+ .name = "hyperv_clocksource",
+ .rating = 400, /* use this when running on Hyperv*/
+ .read = read_hv_clock,
+ .mask = CLOCKSOURCE_MASK(64),
+};
+
static void __init ms_hyperv_init_platform(void)
{
/*
@@ -46,6 +67,8 @@ static void __init ms_hyperv_init_platform(void)
printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
ms_hyperv.features, ms_hyperv.hints);
+
+ clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
}
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index cfa62ec090ec..640891014b2a 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -32,6 +32,8 @@
#include <asm/smp.h>
#include <asm/alternative.h>
+#include "perf_event.h"
+
#if 0
#undef wrmsrl
#define wrmsrl(msr, val) \
@@ -43,283 +45,17 @@ do { \
} while (0)
#endif
-/*
- * | NHM/WSM | SNB |
- * register -------------------------------
- * | HT | no HT | HT | no HT |
- *-----------------------------------------
- * offcore | core | core | cpu | core |
- * lbr_sel | core | core | cpu | core |
- * ld_lat | cpu | core | cpu | core |
- *-----------------------------------------
- *
- * Given that there is a small number of shared regs,
- * we can pre-allocate their slot in the per-cpu
- * per-core reg tables.
- */
-enum extra_reg_type {
- EXTRA_REG_NONE = -1, /* not used */
-
- EXTRA_REG_RSP_0 = 0, /* offcore_response_0 */
- EXTRA_REG_RSP_1 = 1, /* offcore_response_1 */
-
- EXTRA_REG_MAX /* number of entries needed */
-};
-
-struct event_constraint {
- union {
- unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
- u64 idxmsk64;
- };
- u64 code;
- u64 cmask;
- int weight;
-};
-
-struct amd_nb {
- int nb_id; /* NorthBridge id */
- int refcnt; /* reference count */
- struct perf_event *owners[X86_PMC_IDX_MAX];
- struct event_constraint event_constraints[X86_PMC_IDX_MAX];
-};
-
-struct intel_percore;
-
-#define MAX_LBR_ENTRIES 16
-
-struct cpu_hw_events {
- /*
- * Generic x86 PMC bits
- */
- struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */
- unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
- unsigned long running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
- int enabled;
-
- int n_events;
- int n_added;
- int n_txn;
- int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
- u64 tags[X86_PMC_IDX_MAX];
- struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
-
- unsigned int group_flag;
-
- /*
- * Intel DebugStore bits
- */
- struct debug_store *ds;
- u64 pebs_enabled;
-
- /*
- * Intel LBR bits
- */
- int lbr_users;
- void *lbr_context;
- struct perf_branch_stack lbr_stack;
- struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES];
-
- /*
- * manage shared (per-core, per-cpu) registers
- * used on Intel NHM/WSM/SNB
- */
- struct intel_shared_regs *shared_regs;
-
- /*
- * AMD specific bits
- */
- struct amd_nb *amd_nb;
-};
-
-#define __EVENT_CONSTRAINT(c, n, m, w) {\
- { .idxmsk64 = (n) }, \
- .code = (c), \
- .cmask = (m), \
- .weight = (w), \
-}
-
-#define EVENT_CONSTRAINT(c, n, m) \
- __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n))
-
-/*
- * Constraint on the Event code.
- */
-#define INTEL_EVENT_CONSTRAINT(c, n) \
- EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT)
-
-/*
- * Constraint on the Event code + UMask + fixed-mask
- *
- * filter mask to validate fixed counter events.
- * the following filters disqualify for fixed counters:
- * - inv
- * - edge
- * - cnt-mask
- * The other filters are supported by fixed counters.
- * The any-thread option is supported starting with v3.
- */
-#define FIXED_EVENT_CONSTRAINT(c, n) \
- EVENT_CONSTRAINT(c, (1ULL << (32+n)), X86_RAW_EVENT_MASK)
-
-/*
- * Constraint on the Event code + UMask
- */
-#define INTEL_UEVENT_CONSTRAINT(c, n) \
- EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
-
-#define EVENT_CONSTRAINT_END \
- EVENT_CONSTRAINT(0, 0, 0)
-
-#define for_each_event_constraint(e, c) \
- for ((e) = (c); (e)->weight; (e)++)
-
-/*
- * Per register state.
- */
-struct er_account {
- raw_spinlock_t lock; /* per-core: protect structure */
- u64 config; /* extra MSR config */
- u64 reg; /* extra MSR number */
- atomic_t ref; /* reference count */
-};
-
-/*
- * Extra registers for specific events.
- *
- * Some events need large masks and require external MSRs.
- * Those extra MSRs end up being shared for all events on
- * a PMU and sometimes between PMU of sibling HT threads.
- * In either case, the kernel needs to handle conflicting
- * accesses to those extra, shared, regs. The data structure
- * to manage those registers is stored in cpu_hw_event.
- */
-struct extra_reg {
- unsigned int event;
- unsigned int msr;
- u64 config_mask;
- u64 valid_mask;
- int idx; /* per_xxx->regs[] reg index */
-};
-
-#define EVENT_EXTRA_REG(e, ms, m, vm, i) { \
- .event = (e), \
- .msr = (ms), \
- .config_mask = (m), \
- .valid_mask = (vm), \
- .idx = EXTRA_REG_##i \
- }
-
-#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx) \
- EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx)
-
-#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0)
-
-union perf_capabilities {
- struct {
- u64 lbr_format : 6;
- u64 pebs_trap : 1;
- u64 pebs_arch_reg : 1;
- u64 pebs_format : 4;
- u64 smm_freeze : 1;
- };
- u64 capabilities;
-};
-
-/*
- * struct x86_pmu - generic x86 pmu
- */
-struct x86_pmu {
- /*
- * Generic x86 PMC bits
- */
- const char *name;
- int version;
- int (*handle_irq)(struct pt_regs *);
- void (*disable_all)(void);
- void (*enable_all)(int added);
- void (*enable)(struct perf_event *);
- void (*disable)(struct perf_event *);
- int (*hw_config)(struct perf_event *event);
- int (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign);
- unsigned eventsel;
- unsigned perfctr;
- u64 (*event_map)(int);
- int max_events;
- int num_counters;
- int num_counters_fixed;
- int cntval_bits;
- u64 cntval_mask;
- int apic;
- u64 max_period;
- struct event_constraint *
- (*get_event_constraints)(struct cpu_hw_events *cpuc,
- struct perf_event *event);
-
- void (*put_event_constraints)(struct cpu_hw_events *cpuc,
- struct perf_event *event);
- struct event_constraint *event_constraints;
- void (*quirks)(void);
- int perfctr_second_write;
-
- int (*cpu_prepare)(int cpu);
- void (*cpu_starting)(int cpu);
- void (*cpu_dying)(int cpu);
- void (*cpu_dead)(int cpu);
-
- /*
- * Intel Arch Perfmon v2+
- */
- u64 intel_ctrl;
- union perf_capabilities intel_cap;
+struct x86_pmu x86_pmu __read_mostly;
- /*
- * Intel DebugStore bits
- */
- int bts, pebs;
- int bts_active, pebs_active;
- int pebs_record_size;
- void (*drain_pebs)(struct pt_regs *regs);
- struct event_constraint *pebs_constraints;
-
- /*
- * Intel LBR
- */
- unsigned long lbr_tos, lbr_from, lbr_to; /* MSR base regs */
- int lbr_nr; /* hardware stack size */
-
- /*
- * Extra registers for events
- */
- struct extra_reg *extra_regs;
- unsigned int er_flags;
-};
-
-#define ERF_NO_HT_SHARING 1
-#define ERF_HAS_RSP_1 2
-
-static struct x86_pmu x86_pmu __read_mostly;
-
-static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
+DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
.enabled = 1,
};
-static int x86_perf_event_set_period(struct perf_event *event);
-
-/*
- * Generalized hw caching related hw_event table, filled
- * in on a per model basis. A value of 0 means
- * 'not supported', -1 means 'hw_event makes no sense on
- * this CPU', any other value means the raw hw_event
- * ID.
- */
-
-#define C(x) PERF_COUNT_HW_CACHE_##x
-
-static u64 __read_mostly hw_cache_event_ids
+u64 __read_mostly hw_cache_event_ids
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX];
-static u64 __read_mostly hw_cache_extra_regs
+u64 __read_mostly hw_cache_extra_regs
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX];
@@ -329,8 +65,7 @@ static u64 __read_mostly hw_cache_extra_regs
* Can only be executed on the CPU where the event is active.
* Returns the delta events processed.
*/
-static u64
-x86_perf_event_update(struct perf_event *event)
+u64 x86_perf_event_update(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
int shift = 64 - x86_pmu.cntval_bits;
@@ -373,30 +108,6 @@ again:
return new_raw_count;
}
-static inline int x86_pmu_addr_offset(int index)
-{
- int offset;
-
- /* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */
- alternative_io(ASM_NOP2,
- "shll $1, %%eax",
- X86_FEATURE_PERFCTR_CORE,
- "=a" (offset),
- "a" (index));
-
- return offset;
-}
-
-static inline unsigned int x86_pmu_config_addr(int index)
-{
- return x86_pmu.eventsel + x86_pmu_addr_offset(index);
-}
-
-static inline unsigned int x86_pmu_event_addr(int index)
-{
- return x86_pmu.perfctr + x86_pmu_addr_offset(index);
-}
-
/*
* Find and validate any extra registers to set up.
*/
@@ -532,9 +243,6 @@ msr_fail:
return false;
}
-static void reserve_ds_buffers(void);
-static void release_ds_buffers(void);
-
static void hw_perf_event_destroy(struct perf_event *event)
{
if (atomic_dec_and_mutex_lock(&active_events, &pmc_reserve_mutex)) {
@@ -583,7 +291,7 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event)
return x86_pmu_extra_regs(val, event);
}
-static int x86_setup_perfctr(struct perf_event *event)
+int x86_setup_perfctr(struct perf_event *event)
{
struct perf_event_attr *attr = &event->attr;
struct hw_perf_event *hwc = &event->hw;
@@ -647,7 +355,7 @@ static int x86_setup_perfctr(struct perf_event *event)
return 0;
}
-static int x86_pmu_hw_config(struct perf_event *event)
+int x86_pmu_hw_config(struct perf_event *event)
{
if (event->attr.precise_ip) {
int precise = 0;
@@ -723,7 +431,7 @@ static int __x86_pmu_event_init(struct perf_event *event)
return x86_pmu.hw_config(event);
}
-static void x86_pmu_disable_all(void)
+void x86_pmu_disable_all(void)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int idx;
@@ -758,15 +466,7 @@ static void x86_pmu_disable(struct pmu *pmu)
x86_pmu.disable_all();
}
-static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
- u64 enable_mask)
-{
- if (hwc->extra_reg.reg)
- wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
- wrmsrl(hwc->config_base, hwc->config | enable_mask);
-}
-
-static void x86_pmu_enable_all(int added)
+void x86_pmu_enable_all(int added)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int idx;
@@ -788,7 +488,7 @@ static inline int is_x86_event(struct perf_event *event)
return event->pmu == &pmu;
}
-static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
{
struct event_constraint *c, *constraints[X86_PMC_IDX_MAX];
unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
@@ -959,7 +659,6 @@ static inline int match_prev_assignment(struct hw_perf_event *hwc,
}
static void x86_pmu_start(struct perf_event *event, int flags);
-static void x86_pmu_stop(struct perf_event *event, int flags);
static void x86_pmu_enable(struct pmu *pmu)
{
@@ -1031,21 +730,13 @@ static void x86_pmu_enable(struct pmu *pmu)
x86_pmu.enable_all(added);
}
-static inline void x86_pmu_disable_event(struct perf_event *event)
-{
- struct hw_perf_event *hwc = &event->hw;
-
- wrmsrl(hwc->config_base, hwc->config);
-}
-
static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left);
/*
* Set the next IRQ period, based on the hwc->period_left value.
* To be called with the event disabled in hw:
*/
-static int
-x86_perf_event_set_period(struct perf_event *event)
+int x86_perf_event_set_period(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
s64 left = local64_read(&hwc->period_left);
@@ -1105,7 +796,7 @@ x86_perf_event_set_period(struct perf_event *event)
return ret;
}
-static void x86_pmu_enable_event(struct perf_event *event)
+void x86_pmu_enable_event(struct perf_event *event)
{
if (__this_cpu_read(cpu_hw_events.enabled))
__x86_pmu_enable_event(&event->hw,
@@ -1244,7 +935,7 @@ void perf_event_print_debug(void)
local_irq_restore(flags);
}
-static void x86_pmu_stop(struct perf_event *event, int flags)
+void x86_pmu_stop(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct hw_perf_event *hwc = &event->hw;
@@ -1297,7 +988,7 @@ static void x86_pmu_del(struct perf_event *event, int flags)
perf_event_update_userpage(event);
}
-static int x86_pmu_handle_irq(struct pt_regs *regs)
+int x86_pmu_handle_irq(struct pt_regs *regs)
{
struct perf_sample_data data;
struct cpu_hw_events *cpuc;
@@ -1367,109 +1058,28 @@ void perf_events_lapic_init(void)
apic_write(APIC_LVTPC, APIC_DM_NMI);
}
-struct pmu_nmi_state {
- unsigned int marked;
- int handled;
-};
-
-static DEFINE_PER_CPU(struct pmu_nmi_state, pmu_nmi);
-
static int __kprobes
-perf_event_nmi_handler(struct notifier_block *self,
- unsigned long cmd, void *__args)
+perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs)
{
- struct die_args *args = __args;
- unsigned int this_nmi;
- int handled;
-
if (!atomic_read(&active_events))
- return NOTIFY_DONE;
-
- switch (cmd) {
- case DIE_NMI:
- break;
- case DIE_NMIUNKNOWN:
- this_nmi = percpu_read(irq_stat.__nmi_count);
- if (this_nmi != __this_cpu_read(pmu_nmi.marked))
- /* let the kernel handle the unknown nmi */
- return NOTIFY_DONE;
- /*
- * This one is a PMU back-to-back nmi. Two events
- * trigger 'simultaneously' raising two back-to-back
- * NMIs. If the first NMI handles both, the latter
- * will be empty and daze the CPU. So, we drop it to
- * avoid false-positive 'unknown nmi' messages.
- */
- return NOTIFY_STOP;
- default:
- return NOTIFY_DONE;
- }
-
- handled = x86_pmu.handle_irq(args->regs);
- if (!handled)
- return NOTIFY_DONE;
-
- this_nmi = percpu_read(irq_stat.__nmi_count);
- if ((handled > 1) ||
- /* the next nmi could be a back-to-back nmi */
- ((__this_cpu_read(pmu_nmi.marked) == this_nmi) &&
- (__this_cpu_read(pmu_nmi.handled) > 1))) {
- /*
- * We could have two subsequent back-to-back nmis: The
- * first handles more than one counter, the 2nd
- * handles only one counter and the 3rd handles no
- * counter.
- *
- * This is the 2nd nmi because the previous was
- * handling more than one counter. We will mark the
- * next (3rd) and then drop it if unhandled.
- */
- __this_cpu_write(pmu_nmi.marked, this_nmi + 1);
- __this_cpu_write(pmu_nmi.handled, handled);
- }
+ return NMI_DONE;
- return NOTIFY_STOP;
+ return x86_pmu.handle_irq(regs);
}
-static __read_mostly struct notifier_block perf_event_nmi_notifier = {
- .notifier_call = perf_event_nmi_handler,
- .next = NULL,
- .priority = NMI_LOCAL_LOW_PRIOR,
-};
-
-static struct event_constraint unconstrained;
-static struct event_constraint emptyconstraint;
-
-static struct event_constraint *
-x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
-{
- struct event_constraint *c;
-
- if (x86_pmu.event_constraints) {
- for_each_event_constraint(c, x86_pmu.event_constraints) {
- if ((event->hw.config & c->cmask) == c->code)
- return c;
- }
- }
-
- return &unconstrained;
-}
-
-#include "perf_event_amd.c"
-#include "perf_event_p6.c"
-#include "perf_event_p4.c"
-#include "perf_event_intel_lbr.c"
-#include "perf_event_intel_ds.c"
-#include "perf_event_intel.c"
+struct event_constraint emptyconstraint;
+struct event_constraint unconstrained;
static int __cpuinit
x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
{
unsigned int cpu = (long)hcpu;
+ struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
int ret = NOTIFY_OK;
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_UP_PREPARE:
+ cpuc->kfree_on_online = NULL;
if (x86_pmu.cpu_prepare)
ret = x86_pmu.cpu_prepare(cpu);
break;
@@ -1479,6 +1089,10 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
x86_pmu.cpu_starting(cpu);
break;
+ case CPU_ONLINE:
+ kfree(cpuc->kfree_on_online);
+ break;
+
case CPU_DYING:
if (x86_pmu.cpu_dying)
x86_pmu.cpu_dying(cpu);
@@ -1557,7 +1171,7 @@ static int __init init_hw_perf_events(void)
((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED;
perf_events_lapic_init();
- register_die_notifier(&perf_event_nmi_notifier);
+ register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
unconstrained = (struct event_constraint)
__EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
new file mode 100644
index 000000000000..b9698d40ac4b
--- /dev/null
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -0,0 +1,505 @@
+/*
+ * Performance events x86 architecture header
+ *
+ * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
+ * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
+ * Copyright (C) 2009 Jaswinder Singh Rajput
+ * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
+ * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
+ * Copyright (C) 2009 Google, Inc., Stephane Eranian
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+
+/*
+ * | NHM/WSM | SNB |
+ * register -------------------------------
+ * | HT | no HT | HT | no HT |
+ *-----------------------------------------
+ * offcore | core | core | cpu | core |
+ * lbr_sel | core | core | cpu | core |
+ * ld_lat | cpu | core | cpu | core |
+ *-----------------------------------------
+ *
+ * Given that there is a small number of shared regs,
+ * we can pre-allocate their slot in the per-cpu
+ * per-core reg tables.
+ */
+enum extra_reg_type {
+ EXTRA_REG_NONE = -1, /* not used */
+
+ EXTRA_REG_RSP_0 = 0, /* offcore_response_0 */
+ EXTRA_REG_RSP_1 = 1, /* offcore_response_1 */
+
+ EXTRA_REG_MAX /* number of entries needed */
+};
+
+struct event_constraint {
+ union {
+ unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+ u64 idxmsk64;
+ };
+ u64 code;
+ u64 cmask;
+ int weight;
+};
+
+struct amd_nb {
+ int nb_id; /* NorthBridge id */
+ int refcnt; /* reference count */
+ struct perf_event *owners[X86_PMC_IDX_MAX];
+ struct event_constraint event_constraints[X86_PMC_IDX_MAX];
+};
+
+/* The maximal number of PEBS events: */
+#define MAX_PEBS_EVENTS 4
+
+/*
+ * A debug store configuration.
+ *
+ * We only support architectures that use 64bit fields.
+ */
+struct debug_store {
+ u64 bts_buffer_base;
+ u64 bts_index;
+ u64 bts_absolute_maximum;
+ u64 bts_interrupt_threshold;
+ u64 pebs_buffer_base;
+ u64 pebs_index;
+ u64 pebs_absolute_maximum;
+ u64 pebs_interrupt_threshold;
+ u64 pebs_event_reset[MAX_PEBS_EVENTS];
+};
+
+/*
+ * Per register state.
+ */
+struct er_account {
+ raw_spinlock_t lock; /* per-core: protect structure */
+ u64 config; /* extra MSR config */
+ u64 reg; /* extra MSR number */
+ atomic_t ref; /* reference count */
+};
+
+/*
+ * Per core/cpu state
+ *
+ * Used to coordinate shared registers between HT threads or
+ * among events on a single PMU.
+ */
+struct intel_shared_regs {
+ struct er_account regs[EXTRA_REG_MAX];
+ int refcnt; /* per-core: #HT threads */
+ unsigned core_id; /* per-core: core id */
+};
+
+#define MAX_LBR_ENTRIES 16
+
+struct cpu_hw_events {
+ /*
+ * Generic x86 PMC bits
+ */
+ struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */
+ unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+ unsigned long running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+ int enabled;
+
+ int n_events;
+ int n_added;
+ int n_txn;
+ int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
+ u64 tags[X86_PMC_IDX_MAX];
+ struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
+
+ unsigned int group_flag;
+
+ /*
+ * Intel DebugStore bits
+ */
+ struct debug_store *ds;
+ u64 pebs_enabled;
+
+ /*
+ * Intel LBR bits
+ */
+ int lbr_users;
+ void *lbr_context;
+ struct perf_branch_stack lbr_stack;
+ struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES];
+
+ /*
+ * Intel host/guest exclude bits
+ */
+ u64 intel_ctrl_guest_mask;
+ u64 intel_ctrl_host_mask;
+ struct perf_guest_switch_msr guest_switch_msrs[X86_PMC_IDX_MAX];
+
+ /*
+ * manage shared (per-core, per-cpu) registers
+ * used on Intel NHM/WSM/SNB
+ */
+ struct intel_shared_regs *shared_regs;
+
+ /*
+ * AMD specific bits
+ */
+ struct amd_nb *amd_nb;
+
+ void *kfree_on_online;
+};
+
+#define __EVENT_CONSTRAINT(c, n, m, w) {\
+ { .idxmsk64 = (n) }, \
+ .code = (c), \
+ .cmask = (m), \
+ .weight = (w), \
+}
+
+#define EVENT_CONSTRAINT(c, n, m) \
+ __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n))
+
+/*
+ * Constraint on the Event code.
+ */
+#define INTEL_EVENT_CONSTRAINT(c, n) \
+ EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT)
+
+/*
+ * Constraint on the Event code + UMask + fixed-mask
+ *
+ * filter mask to validate fixed counter events.
+ * the following filters disqualify for fixed counters:
+ * - inv
+ * - edge
+ * - cnt-mask
+ * The other filters are supported by fixed counters.
+ * The any-thread option is supported starting with v3.
+ */
+#define FIXED_EVENT_CONSTRAINT(c, n) \
+ EVENT_CONSTRAINT(c, (1ULL << (32+n)), X86_RAW_EVENT_MASK)
+
+/*
+ * Constraint on the Event code + UMask
+ */
+#define INTEL_UEVENT_CONSTRAINT(c, n) \
+ EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
+
+#define EVENT_CONSTRAINT_END \
+ EVENT_CONSTRAINT(0, 0, 0)
+
+#define for_each_event_constraint(e, c) \
+ for ((e) = (c); (e)->weight; (e)++)
+
+/*
+ * Extra registers for specific events.
+ *
+ * Some events need large masks and require external MSRs.
+ * Those extra MSRs end up being shared for all events on
+ * a PMU and sometimes between PMU of sibling HT threads.
+ * In either case, the kernel needs to handle conflicting
+ * accesses to those extra, shared, regs. The data structure
+ * to manage those registers is stored in cpu_hw_event.
+ */
+struct extra_reg {
+ unsigned int event;
+ unsigned int msr;
+ u64 config_mask;
+ u64 valid_mask;
+ int idx; /* per_xxx->regs[] reg index */
+};
+
+#define EVENT_EXTRA_REG(e, ms, m, vm, i) { \
+ .event = (e), \
+ .msr = (ms), \
+ .config_mask = (m), \
+ .valid_mask = (vm), \
+ .idx = EXTRA_REG_##i \
+ }
+
+#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx) \
+ EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx)
+
+#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0)
+
+union perf_capabilities {
+ struct {
+ u64 lbr_format:6;
+ u64 pebs_trap:1;
+ u64 pebs_arch_reg:1;
+ u64 pebs_format:4;
+ u64 smm_freeze:1;
+ };
+ u64 capabilities;
+};
+
+/*
+ * struct x86_pmu - generic x86 pmu
+ */
+struct x86_pmu {
+ /*
+ * Generic x86 PMC bits
+ */
+ const char *name;
+ int version;
+ int (*handle_irq)(struct pt_regs *);
+ void (*disable_all)(void);
+ void (*enable_all)(int added);
+ void (*enable)(struct perf_event *);
+ void (*disable)(struct perf_event *);
+ int (*hw_config)(struct perf_event *event);
+ int (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign);
+ unsigned eventsel;
+ unsigned perfctr;
+ u64 (*event_map)(int);
+ int max_events;
+ int num_counters;
+ int num_counters_fixed;
+ int cntval_bits;
+ u64 cntval_mask;
+ int apic;
+ u64 max_period;
+ struct event_constraint *
+ (*get_event_constraints)(struct cpu_hw_events *cpuc,
+ struct perf_event *event);
+
+ void (*put_event_constraints)(struct cpu_hw_events *cpuc,
+ struct perf_event *event);
+ struct event_constraint *event_constraints;
+ void (*quirks)(void);
+ int perfctr_second_write;
+
+ int (*cpu_prepare)(int cpu);
+ void (*cpu_starting)(int cpu);
+ void (*cpu_dying)(int cpu);
+ void (*cpu_dead)(int cpu);
+
+ /*
+ * Intel Arch Perfmon v2+
+ */
+ u64 intel_ctrl;
+ union perf_capabilities intel_cap;
+
+ /*
+ * Intel DebugStore bits
+ */
+ int bts, pebs;
+ int bts_active, pebs_active;
+ int pebs_record_size;
+ void (*drain_pebs)(struct pt_regs *regs);
+ struct event_constraint *pebs_constraints;
+
+ /*
+ * Intel LBR
+ */
+ unsigned long lbr_tos, lbr_from, lbr_to; /* MSR base regs */
+ int lbr_nr; /* hardware stack size */
+
+ /*
+ * Extra registers for events
+ */
+ struct extra_reg *extra_regs;
+ unsigned int er_flags;
+
+ /*
+ * Intel host/guest support (KVM)
+ */
+ struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
+};
+
+#define ERF_NO_HT_SHARING 1
+#define ERF_HAS_RSP_1 2
+
+extern struct x86_pmu x86_pmu __read_mostly;
+
+DECLARE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+
+int x86_perf_event_set_period(struct perf_event *event);
+
+/*
+ * Generalized hw caching related hw_event table, filled
+ * in on a per model basis. A value of 0 means
+ * 'not supported', -1 means 'hw_event makes no sense on
+ * this CPU', any other value means the raw hw_event
+ * ID.
+ */
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+extern u64 __read_mostly hw_cache_event_ids
+ [PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX];
+extern u64 __read_mostly hw_cache_extra_regs
+ [PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX];
+
+u64 x86_perf_event_update(struct perf_event *event);
+
+static inline int x86_pmu_addr_offset(int index)
+{
+ int offset;
+
+ /* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */
+ alternative_io(ASM_NOP2,
+ "shll $1, %%eax",
+ X86_FEATURE_PERFCTR_CORE,
+ "=a" (offset),
+ "a" (index));
+
+ return offset;
+}
+
+static inline unsigned int x86_pmu_config_addr(int index)
+{
+ return x86_pmu.eventsel + x86_pmu_addr_offset(index);
+}
+
+static inline unsigned int x86_pmu_event_addr(int index)
+{
+ return x86_pmu.perfctr + x86_pmu_addr_offset(index);
+}
+
+int x86_setup_perfctr(struct perf_event *event);
+
+int x86_pmu_hw_config(struct perf_event *event);
+
+void x86_pmu_disable_all(void);
+
+static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
+ u64 enable_mask)
+{
+ if (hwc->extra_reg.reg)
+ wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
+ wrmsrl(hwc->config_base, hwc->config | enable_mask);
+}
+
+void x86_pmu_enable_all(int added);
+
+int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
+
+void x86_pmu_stop(struct perf_event *event, int flags);
+
+static inline void x86_pmu_disable_event(struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ wrmsrl(hwc->config_base, hwc->config);
+}
+
+void x86_pmu_enable_event(struct perf_event *event);
+
+int x86_pmu_handle_irq(struct pt_regs *regs);
+
+extern struct event_constraint emptyconstraint;
+
+extern struct event_constraint unconstrained;
+
+#ifdef CONFIG_CPU_SUP_AMD
+
+int amd_pmu_init(void);
+
+#else /* CONFIG_CPU_SUP_AMD */
+
+static inline int amd_pmu_init(void)
+{
+ return 0;
+}
+
+#endif /* CONFIG_CPU_SUP_AMD */
+
+#ifdef CONFIG_CPU_SUP_INTEL
+
+int intel_pmu_save_and_restart(struct perf_event *event);
+
+struct event_constraint *
+x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event);
+
+struct intel_shared_regs *allocate_shared_regs(int cpu);
+
+int intel_pmu_init(void);
+
+void init_debug_store_on_cpu(int cpu);
+
+void fini_debug_store_on_cpu(int cpu);
+
+void release_ds_buffers(void);
+
+void reserve_ds_buffers(void);
+
+extern struct event_constraint bts_constraint;
+
+void intel_pmu_enable_bts(u64 config);
+
+void intel_pmu_disable_bts(void);
+
+int intel_pmu_drain_bts_buffer(void);
+
+extern struct event_constraint intel_core2_pebs_event_constraints[];
+
+extern struct event_constraint intel_atom_pebs_event_constraints[];
+
+extern struct event_constraint intel_nehalem_pebs_event_constraints[];
+
+extern struct event_constraint intel_westmere_pebs_event_constraints[];
+
+extern struct event_constraint intel_snb_pebs_event_constraints[];
+
+struct event_constraint *intel_pebs_constraints(struct perf_event *event);
+
+void intel_pmu_pebs_enable(struct perf_event *event);
+
+void intel_pmu_pebs_disable(struct perf_event *event);
+
+void intel_pmu_pebs_enable_all(void);
+
+void intel_pmu_pebs_disable_all(void);
+
+void intel_ds_init(void);
+
+void intel_pmu_lbr_reset(void);
+
+void intel_pmu_lbr_enable(struct perf_event *event);
+
+void intel_pmu_lbr_disable(struct perf_event *event);
+
+void intel_pmu_lbr_enable_all(void);
+
+void intel_pmu_lbr_disable_all(void);
+
+void intel_pmu_lbr_read(void);
+
+void intel_pmu_lbr_init_core(void);
+
+void intel_pmu_lbr_init_nhm(void);
+
+void intel_pmu_lbr_init_atom(void);
+
+int p4_pmu_init(void);
+
+int p6_pmu_init(void);
+
+#else /* CONFIG_CPU_SUP_INTEL */
+
+static inline void reserve_ds_buffers(void)
+{
+}
+
+static inline void release_ds_buffers(void)
+{
+}
+
+static inline int intel_pmu_init(void)
+{
+ return 0;
+}
+
+static inline struct intel_shared_regs *allocate_shared_regs(int cpu)
+{
+ return NULL;
+}
+
+#endif /* CONFIG_CPU_SUP_INTEL */
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index 941caa2e449b..aeefd45697a2 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -1,4 +1,10 @@
-#ifdef CONFIG_CPU_SUP_AMD
+#include <linux/perf_event.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/apicdef.h>
+
+#include "perf_event.h"
static __initconst const u64 amd_hw_cache_event_ids
[PERF_COUNT_HW_CACHE_MAX]
@@ -132,6 +138,19 @@ static int amd_pmu_hw_config(struct perf_event *event)
if (ret)
return ret;
+ if (event->attr.exclude_host && event->attr.exclude_guest)
+ /*
+ * When HO == GO == 1 the hardware treats that as GO == HO == 0
+ * and will count in both modes. We don't want to count in that
+ * case so we emulate no-counting by setting US = OS = 0.
+ */
+ event->hw.config &= ~(ARCH_PERFMON_EVENTSEL_USR |
+ ARCH_PERFMON_EVENTSEL_OS);
+ else if (event->attr.exclude_host)
+ event->hw.config |= AMD_PERFMON_EVENTSEL_GUESTONLY;
+ else if (event->attr.exclude_guest)
+ event->hw.config |= AMD_PERFMON_EVENTSEL_HOSTONLY;
+
if (event->attr.type != PERF_TYPE_RAW)
return 0;
@@ -350,7 +369,7 @@ static void amd_pmu_cpu_starting(int cpu)
continue;
if (nb->nb_id == nb_id) {
- kfree(cpuc->amd_nb);
+ cpuc->kfree_on_online = cpuc->amd_nb;
cpuc->amd_nb = nb;
break;
}
@@ -392,7 +411,7 @@ static __initconst const struct x86_pmu amd_pmu = {
.perfctr = MSR_K7_PERFCTR0,
.event_map = amd_pmu_event_map,
.max_events = ARRAY_SIZE(amd_perfmon_event_map),
- .num_counters = 4,
+ .num_counters = AMD64_NUM_COUNTERS,
.cntval_bits = 48,
.cntval_mask = (1ULL << 48) - 1,
.apic = 1,
@@ -556,7 +575,7 @@ static __initconst const struct x86_pmu amd_pmu_f15h = {
.perfctr = MSR_F15H_PERF_CTR,
.event_map = amd_pmu_event_map,
.max_events = ARRAY_SIZE(amd_perfmon_event_map),
- .num_counters = 6,
+ .num_counters = AMD64_NUM_COUNTERS_F15H,
.cntval_bits = 48,
.cntval_mask = (1ULL << 48) - 1,
.apic = 1,
@@ -573,7 +592,7 @@ static __initconst const struct x86_pmu amd_pmu_f15h = {
#endif
};
-static __init int amd_pmu_init(void)
+__init int amd_pmu_init(void)
{
/* Performance-monitoring supported from K7 and later: */
if (boot_cpu_data.x86 < 6)
@@ -602,12 +621,3 @@ static __init int amd_pmu_init(void)
return 0;
}
-
-#else /* CONFIG_CPU_SUP_AMD */
-
-static int amd_pmu_init(void)
-{
- return 0;
-}
-
-#endif
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
new file mode 100644
index 000000000000..ab6343d21825
--- /dev/null
+++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
@@ -0,0 +1,294 @@
+/*
+ * Performance events - AMD IBS
+ *
+ * Copyright (C) 2011 Advanced Micro Devices, Inc., Robert Richter
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <asm/apic.h>
+
+static u32 ibs_caps;
+
+#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
+
+static struct pmu perf_ibs;
+
+static int perf_ibs_init(struct perf_event *event)
+{
+ if (perf_ibs.type != event->attr.type)
+ return -ENOENT;
+ return 0;
+}
+
+static int perf_ibs_add(struct perf_event *event, int flags)
+{
+ return 0;
+}
+
+static void perf_ibs_del(struct perf_event *event, int flags)
+{
+}
+
+static struct pmu perf_ibs = {
+ .event_init= perf_ibs_init,
+ .add= perf_ibs_add,
+ .del= perf_ibs_del,
+};
+
+static __init int perf_event_ibs_init(void)
+{
+ if (!ibs_caps)
+ return -ENODEV; /* ibs not supported by the cpu */
+
+ perf_pmu_register(&perf_ibs, "ibs", -1);
+ printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps);
+
+ return 0;
+}
+
+#else /* defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) */
+
+static __init int perf_event_ibs_init(void) { return 0; }
+
+#endif
+
+/* IBS - apic initialization, for perf and oprofile */
+
+static __init u32 __get_ibs_caps(void)
+{
+ u32 caps;
+ unsigned int max_level;
+
+ if (!boot_cpu_has(X86_FEATURE_IBS))
+ return 0;
+
+ /* check IBS cpuid feature flags */
+ max_level = cpuid_eax(0x80000000);
+ if (max_level < IBS_CPUID_FEATURES)
+ return IBS_CAPS_DEFAULT;
+
+ caps = cpuid_eax(IBS_CPUID_FEATURES);
+ if (!(caps & IBS_CAPS_AVAIL))
+ /* cpuid flags not valid */
+ return IBS_CAPS_DEFAULT;
+
+ return caps;
+}
+
+u32 get_ibs_caps(void)
+{
+ return ibs_caps;
+}
+
+EXPORT_SYMBOL(get_ibs_caps);
+
+static inline int get_eilvt(int offset)
+{
+ return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
+}
+
+static inline int put_eilvt(int offset)
+{
+ return !setup_APIC_eilvt(offset, 0, 0, 1);
+}
+
+/*
+ * Check and reserve APIC extended interrupt LVT offset for IBS if available.
+ */
+static inline int ibs_eilvt_valid(void)
+{
+ int offset;
+ u64 val;
+ int valid = 0;
+
+ preempt_disable();
+
+ rdmsrl(MSR_AMD64_IBSCTL, val);
+ offset = val & IBSCTL_LVT_OFFSET_MASK;
+
+ if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
+ pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
+ smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
+ goto out;
+ }
+
+ if (!get_eilvt(offset)) {
+ pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
+ smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
+ goto out;
+ }
+
+ valid = 1;
+out:
+ preempt_enable();
+
+ return valid;
+}
+
+static int setup_ibs_ctl(int ibs_eilvt_off)
+{
+ struct pci_dev *cpu_cfg;
+ int nodes;
+ u32 value = 0;
+
+ nodes = 0;
+ cpu_cfg = NULL;
+ do {
+ cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_10H_NB_MISC,
+ cpu_cfg);
+ if (!cpu_cfg)
+ break;
+ ++nodes;
+ pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
+ | IBSCTL_LVT_OFFSET_VALID);
+ pci_read_config_dword(cpu_cfg, IBSCTL, &value);
+ if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
+ pci_dev_put(cpu_cfg);
+ printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
+ "IBSCTL = 0x%08x\n", value);
+ return -EINVAL;
+ }
+ } while (1);
+
+ if (!nodes) {
+ printk(KERN_DEBUG "No CPU node configured for IBS\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/*
+ * This runs only on the current cpu. We try to find an LVT offset and
+ * setup the local APIC. For this we must disable preemption. On
+ * success we initialize all nodes with this offset. This updates then
+ * the offset in the IBS_CTL per-node msr. The per-core APIC setup of
+ * the IBS interrupt vector is handled by perf_ibs_cpu_notifier that
+ * is using the new offset.
+ */
+static int force_ibs_eilvt_setup(void)
+{
+ int offset;
+ int ret;
+
+ preempt_disable();
+ /* find the next free available EILVT entry, skip offset 0 */
+ for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
+ if (get_eilvt(offset))
+ break;
+ }
+ preempt_enable();
+
+ if (offset == APIC_EILVT_NR_MAX) {
+ printk(KERN_DEBUG "No EILVT entry available\n");
+ return -EBUSY;
+ }
+
+ ret = setup_ibs_ctl(offset);
+ if (ret)
+ goto out;
+
+ if (!ibs_eilvt_valid()) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset);
+ pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
+
+ return 0;
+out:
+ preempt_disable();
+ put_eilvt(offset);
+ preempt_enable();
+ return ret;
+}
+
+static inline int get_ibs_lvt_offset(void)
+{
+ u64 val;
+
+ rdmsrl(MSR_AMD64_IBSCTL, val);
+ if (!(val & IBSCTL_LVT_OFFSET_VALID))
+ return -EINVAL;
+
+ return val & IBSCTL_LVT_OFFSET_MASK;
+}
+
+static void setup_APIC_ibs(void *dummy)
+{
+ int offset;
+
+ offset = get_ibs_lvt_offset();
+ if (offset < 0)
+ goto failed;
+
+ if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
+ return;
+failed:
+ pr_warn("perf: IBS APIC setup failed on cpu #%d\n",
+ smp_processor_id());
+}
+
+static void clear_APIC_ibs(void *dummy)
+{
+ int offset;
+
+ offset = get_ibs_lvt_offset();
+ if (offset >= 0)
+ setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
+}
+
+static int __cpuinit
+perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
+{
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_STARTING:
+ setup_APIC_ibs(NULL);
+ break;
+ case CPU_DYING:
+ clear_APIC_ibs(NULL);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static __init int amd_ibs_init(void)
+{
+ u32 caps;
+ int ret;
+
+ caps = __get_ibs_caps();
+ if (!caps)
+ return -ENODEV; /* ibs not supported by the cpu */
+
+ if (!ibs_eilvt_valid()) {
+ ret = force_ibs_eilvt_setup();
+ if (ret) {
+ pr_err("Failed to setup IBS, %d\n", ret);
+ return ret;
+ }
+ }
+
+ get_online_cpus();
+ ibs_caps = caps;
+ /* make ibs_caps visible to other cpus: */
+ smp_mb();
+ perf_cpu_notifier(perf_ibs_cpu_notifier);
+ smp_call_function(setup_APIC_ibs, NULL, 1);
+ put_online_cpus();
+
+ return perf_event_ibs_init();
+}
+
+/* Since we need the pci subsystem to init ibs we can't do this earlier: */
+device_initcall(amd_ibs_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index f88af2c2a561..e09ca20e86ee 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1,16 +1,19 @@
-#ifdef CONFIG_CPU_SUP_INTEL
-
/*
* Per core/cpu state
*
* Used to coordinate shared registers between HT threads or
* among events on a single PMU.
*/
-struct intel_shared_regs {
- struct er_account regs[EXTRA_REG_MAX];
- int refcnt; /* per-core: #HT threads */
- unsigned core_id; /* per-core: core id */
-};
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+#include <asm/hardirq.h>
+#include <asm/apic.h>
+
+#include "perf_event.h"
/*
* Intel PerfMon, used on Core and later.
@@ -746,7 +749,8 @@ static void intel_pmu_enable_all(int added)
intel_pmu_pebs_enable_all();
intel_pmu_lbr_enable_all();
- wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
+ wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL,
+ x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask);
if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
struct perf_event *event =
@@ -869,6 +873,7 @@ static void intel_pmu_disable_fixed(struct hw_perf_event *hwc)
static void intel_pmu_disable_event(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
intel_pmu_disable_bts();
@@ -876,6 +881,9 @@ static void intel_pmu_disable_event(struct perf_event *event)
return;
}
+ cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx);
+ cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx);
+
if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
intel_pmu_disable_fixed(hwc);
return;
@@ -921,6 +929,7 @@ static void intel_pmu_enable_fixed(struct hw_perf_event *hwc)
static void intel_pmu_enable_event(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
if (!__this_cpu_read(cpu_hw_events.enabled))
@@ -930,6 +939,11 @@ static void intel_pmu_enable_event(struct perf_event *event)
return;
}
+ if (event->attr.exclude_host)
+ cpuc->intel_ctrl_guest_mask |= (1ull << hwc->idx);
+ if (event->attr.exclude_guest)
+ cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx);
+
if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
intel_pmu_enable_fixed(hwc);
return;
@@ -945,7 +959,7 @@ static void intel_pmu_enable_event(struct perf_event *event)
* Save and restart an expired event. Called by NMI contexts,
* so it has to be careful about preempting normal event ops:
*/
-static int intel_pmu_save_and_restart(struct perf_event *event)
+int intel_pmu_save_and_restart(struct perf_event *event)
{
x86_perf_event_update(event);
return x86_perf_event_set_period(event);
@@ -1197,6 +1211,21 @@ intel_shared_regs_constraints(struct cpu_hw_events *cpuc,
return c;
}
+struct event_constraint *
+x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+{
+ struct event_constraint *c;
+
+ if (x86_pmu.event_constraints) {
+ for_each_event_constraint(c, x86_pmu.event_constraints) {
+ if ((event->hw.config & c->cmask) == c->code)
+ return c;
+ }
+ }
+
+ return &unconstrained;
+}
+
static struct event_constraint *
intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
{
@@ -1284,12 +1313,84 @@ static int intel_pmu_hw_config(struct perf_event *event)
return 0;
}
+struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
+{
+ if (x86_pmu.guest_get_msrs)
+ return x86_pmu.guest_get_msrs(nr);
+ *nr = 0;
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(perf_guest_get_msrs);
+
+static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr)
+{
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
+
+ arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL;
+ arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask;
+ arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask;
+
+ *nr = 1;
+ return arr;
+}
+
+static struct perf_guest_switch_msr *core_guest_get_msrs(int *nr)
+{
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
+ int idx;
+
+ for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+ struct perf_event *event = cpuc->events[idx];
+
+ arr[idx].msr = x86_pmu_config_addr(idx);
+ arr[idx].host = arr[idx].guest = 0;
+
+ if (!test_bit(idx, cpuc->active_mask))
+ continue;
+
+ arr[idx].host = arr[idx].guest =
+ event->hw.config | ARCH_PERFMON_EVENTSEL_ENABLE;
+
+ if (event->attr.exclude_host)
+ arr[idx].host &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+ else if (event->attr.exclude_guest)
+ arr[idx].guest &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+ }
+
+ *nr = x86_pmu.num_counters;
+ return arr;
+}
+
+static void core_pmu_enable_event(struct perf_event *event)
+{
+ if (!event->attr.exclude_host)
+ x86_pmu_enable_event(event);
+}
+
+static void core_pmu_enable_all(int added)
+{
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ int idx;
+
+ for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+ struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
+
+ if (!test_bit(idx, cpuc->active_mask) ||
+ cpuc->events[idx]->attr.exclude_host)
+ continue;
+
+ __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
+ }
+}
+
static __initconst const struct x86_pmu core_pmu = {
.name = "core",
.handle_irq = x86_pmu_handle_irq,
.disable_all = x86_pmu_disable_all,
- .enable_all = x86_pmu_enable_all,
- .enable = x86_pmu_enable_event,
+ .enable_all = core_pmu_enable_all,
+ .enable = core_pmu_enable_event,
.disable = x86_pmu_disable_event,
.hw_config = x86_pmu_hw_config,
.schedule_events = x86_schedule_events,
@@ -1307,9 +1408,10 @@ static __initconst const struct x86_pmu core_pmu = {
.get_event_constraints = intel_get_event_constraints,
.put_event_constraints = intel_put_event_constraints,
.event_constraints = intel_core_event_constraints,
+ .guest_get_msrs = core_guest_get_msrs,
};
-static struct intel_shared_regs *allocate_shared_regs(int cpu)
+struct intel_shared_regs *allocate_shared_regs(int cpu)
{
struct intel_shared_regs *regs;
int i;
@@ -1362,7 +1464,7 @@ static void intel_pmu_cpu_starting(int cpu)
pc = per_cpu(cpu_hw_events, i).shared_regs;
if (pc && pc->core_id == core_id) {
- kfree(cpuc->shared_regs);
+ cpuc->kfree_on_online = cpuc->shared_regs;
cpuc->shared_regs = pc;
break;
}
@@ -1413,6 +1515,7 @@ static __initconst const struct x86_pmu intel_pmu = {
.cpu_prepare = intel_pmu_cpu_prepare,
.cpu_starting = intel_pmu_cpu_starting,
.cpu_dying = intel_pmu_cpu_dying,
+ .guest_get_msrs = intel_guest_get_msrs,
};
static void intel_clovertown_quirks(void)
@@ -1441,7 +1544,7 @@ static void intel_clovertown_quirks(void)
x86_pmu.pebs_constraints = NULL;
}
-static __init int intel_pmu_init(void)
+__init int intel_pmu_init(void)
{
union cpuid10_edx edx;
union cpuid10_eax eax;
@@ -1597,7 +1700,7 @@ static __init int intel_pmu_init(void)
intel_pmu_lbr_init_nhm();
x86_pmu.event_constraints = intel_snb_event_constraints;
- x86_pmu.pebs_constraints = intel_snb_pebs_events;
+ x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints;
x86_pmu.extra_regs = intel_snb_extra_regs;
/* all extra regs are per-cpu when HT is on */
x86_pmu.er_flags |= ERF_HAS_RSP_1;
@@ -1628,16 +1731,3 @@ static __init int intel_pmu_init(void)
}
return 0;
}
-
-#else /* CONFIG_CPU_SUP_INTEL */
-
-static int intel_pmu_init(void)
-{
- return 0;
-}
-
-static struct intel_shared_regs *allocate_shared_regs(int cpu)
-{
- return NULL;
-}
-#endif /* CONFIG_CPU_SUP_INTEL */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 1b1ef3addcfd..c0d238f49db8 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -1,7 +1,10 @@
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/slab.h>
-/* The maximal number of PEBS events: */
-#define MAX_PEBS_EVENTS 4
+#include <asm/perf_event.h>
+
+#include "perf_event.h"
/* The size of a BTS record in bytes: */
#define BTS_RECORD_SIZE 24
@@ -37,24 +40,7 @@ struct pebs_record_nhm {
u64 status, dla, dse, lat;
};
-/*
- * A debug store configuration.
- *
- * We only support architectures that use 64bit fields.
- */
-struct debug_store {
- u64 bts_buffer_base;
- u64 bts_index;
- u64 bts_absolute_maximum;
- u64 bts_interrupt_threshold;
- u64 pebs_buffer_base;
- u64 pebs_index;
- u64 pebs_absolute_maximum;
- u64 pebs_interrupt_threshold;
- u64 pebs_event_reset[MAX_PEBS_EVENTS];
-};
-
-static void init_debug_store_on_cpu(int cpu)
+void init_debug_store_on_cpu(int cpu)
{
struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
@@ -66,7 +52,7 @@ static void init_debug_store_on_cpu(int cpu)
(u32)((u64)(unsigned long)ds >> 32));
}
-static void fini_debug_store_on_cpu(int cpu)
+void fini_debug_store_on_cpu(int cpu)
{
if (!per_cpu(cpu_hw_events, cpu).ds)
return;
@@ -175,7 +161,7 @@ static void release_ds_buffer(int cpu)
kfree(ds);
}
-static void release_ds_buffers(void)
+void release_ds_buffers(void)
{
int cpu;
@@ -194,7 +180,7 @@ static void release_ds_buffers(void)
put_online_cpus();
}
-static void reserve_ds_buffers(void)
+void reserve_ds_buffers(void)
{
int bts_err = 0, pebs_err = 0;
int cpu;
@@ -260,10 +246,10 @@ static void reserve_ds_buffers(void)
* BTS
*/
-static struct event_constraint bts_constraint =
+struct event_constraint bts_constraint =
EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0);
-static void intel_pmu_enable_bts(u64 config)
+void intel_pmu_enable_bts(u64 config)
{
unsigned long debugctlmsr;
@@ -282,7 +268,7 @@ static void intel_pmu_enable_bts(u64 config)
update_debugctlmsr(debugctlmsr);
}
-static void intel_pmu_disable_bts(void)
+void intel_pmu_disable_bts(void)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
unsigned long debugctlmsr;
@@ -299,7 +285,7 @@ static void intel_pmu_disable_bts(void)
update_debugctlmsr(debugctlmsr);
}
-static int intel_pmu_drain_bts_buffer(void)
+int intel_pmu_drain_bts_buffer(void)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct debug_store *ds = cpuc->ds;
@@ -361,7 +347,7 @@ static int intel_pmu_drain_bts_buffer(void)
/*
* PEBS
*/
-static struct event_constraint intel_core2_pebs_event_constraints[] = {
+struct event_constraint intel_core2_pebs_event_constraints[] = {
INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
INTEL_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
@@ -370,14 +356,14 @@ static struct event_constraint intel_core2_pebs_event_constraints[] = {
EVENT_CONSTRAINT_END
};
-static struct event_constraint intel_atom_pebs_event_constraints[] = {
+struct event_constraint intel_atom_pebs_event_constraints[] = {
INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */
EVENT_CONSTRAINT_END
};
-static struct event_constraint intel_nehalem_pebs_event_constraints[] = {
+struct event_constraint intel_nehalem_pebs_event_constraints[] = {
INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */
INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */
INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
@@ -392,7 +378,7 @@ static struct event_constraint intel_nehalem_pebs_event_constraints[] = {
EVENT_CONSTRAINT_END
};
-static struct event_constraint intel_westmere_pebs_event_constraints[] = {
+struct event_constraint intel_westmere_pebs_event_constraints[] = {
INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */
INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */
INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
@@ -407,7 +393,7 @@ static struct event_constraint intel_westmere_pebs_event_constraints[] = {
EVENT_CONSTRAINT_END
};
-static struct event_constraint intel_snb_pebs_events[] = {
+struct event_constraint intel_snb_pebs_event_constraints[] = {
INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
@@ -428,8 +414,7 @@ static struct event_constraint intel_snb_pebs_events[] = {
EVENT_CONSTRAINT_END
};
-static struct event_constraint *
-intel_pebs_constraints(struct perf_event *event)
+struct event_constraint *intel_pebs_constraints(struct perf_event *event)
{
struct event_constraint *c;
@@ -446,7 +431,7 @@ intel_pebs_constraints(struct perf_event *event)
return &emptyconstraint;
}
-static void intel_pmu_pebs_enable(struct perf_event *event)
+void intel_pmu_pebs_enable(struct perf_event *event)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct hw_perf_event *hwc = &event->hw;
@@ -460,7 +445,7 @@ static void intel_pmu_pebs_enable(struct perf_event *event)
intel_pmu_lbr_enable(event);
}
-static void intel_pmu_pebs_disable(struct perf_event *event)
+void intel_pmu_pebs_disable(struct perf_event *event)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct hw_perf_event *hwc = &event->hw;
@@ -475,7 +460,7 @@ static void intel_pmu_pebs_disable(struct perf_event *event)
intel_pmu_lbr_disable(event);
}
-static void intel_pmu_pebs_enable_all(void)
+void intel_pmu_pebs_enable_all(void)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -483,7 +468,7 @@ static void intel_pmu_pebs_enable_all(void)
wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
}
-static void intel_pmu_pebs_disable_all(void)
+void intel_pmu_pebs_disable_all(void)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -576,8 +561,6 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
return 0;
}
-static int intel_pmu_save_and_restart(struct perf_event *event);
-
static void __intel_pmu_pebs_event(struct perf_event *event,
struct pt_regs *iregs, void *__pebs)
{
@@ -716,7 +699,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
* BTS, PEBS probe and setup
*/
-static void intel_ds_init(void)
+void intel_ds_init(void)
{
/*
* No support for 32bit formats
@@ -749,15 +732,3 @@ static void intel_ds_init(void)
}
}
}
-
-#else /* CONFIG_CPU_SUP_INTEL */
-
-static void reserve_ds_buffers(void)
-{
-}
-
-static void release_ds_buffers(void)
-{
-}
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index d202c1bece1a..3fab3de3ce96 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -1,4 +1,10 @@
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+#include <asm/perf_event.h>
+#include <asm/msr.h>
+
+#include "perf_event.h"
enum {
LBR_FORMAT_32 = 0x00,
@@ -48,7 +54,7 @@ static void intel_pmu_lbr_reset_64(void)
}
}
-static void intel_pmu_lbr_reset(void)
+void intel_pmu_lbr_reset(void)
{
if (!x86_pmu.lbr_nr)
return;
@@ -59,7 +65,7 @@ static void intel_pmu_lbr_reset(void)
intel_pmu_lbr_reset_64();
}
-static void intel_pmu_lbr_enable(struct perf_event *event)
+void intel_pmu_lbr_enable(struct perf_event *event)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -81,7 +87,7 @@ static void intel_pmu_lbr_enable(struct perf_event *event)
cpuc->lbr_users++;
}
-static void intel_pmu_lbr_disable(struct perf_event *event)
+void intel_pmu_lbr_disable(struct perf_event *event)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -95,7 +101,7 @@ static void intel_pmu_lbr_disable(struct perf_event *event)
__intel_pmu_lbr_disable();
}
-static void intel_pmu_lbr_enable_all(void)
+void intel_pmu_lbr_enable_all(void)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -103,7 +109,7 @@ static void intel_pmu_lbr_enable_all(void)
__intel_pmu_lbr_enable();
}
-static void intel_pmu_lbr_disable_all(void)
+void intel_pmu_lbr_disable_all(void)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -178,7 +184,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
cpuc->lbr_stack.nr = i;
}
-static void intel_pmu_lbr_read(void)
+void intel_pmu_lbr_read(void)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -191,7 +197,7 @@ static void intel_pmu_lbr_read(void)
intel_pmu_lbr_read_64(cpuc);
}
-static void intel_pmu_lbr_init_core(void)
+void intel_pmu_lbr_init_core(void)
{
x86_pmu.lbr_nr = 4;
x86_pmu.lbr_tos = 0x01c9;
@@ -199,7 +205,7 @@ static void intel_pmu_lbr_init_core(void)
x86_pmu.lbr_to = 0x60;
}
-static void intel_pmu_lbr_init_nhm(void)
+void intel_pmu_lbr_init_nhm(void)
{
x86_pmu.lbr_nr = 16;
x86_pmu.lbr_tos = 0x01c9;
@@ -207,12 +213,10 @@ static void intel_pmu_lbr_init_nhm(void)
x86_pmu.lbr_to = 0x6c0;
}
-static void intel_pmu_lbr_init_atom(void)
+void intel_pmu_lbr_init_atom(void)
{
x86_pmu.lbr_nr = 8;
x86_pmu.lbr_tos = 0x01c9;
x86_pmu.lbr_from = 0x40;
x86_pmu.lbr_to = 0x60;
}
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index 7809d2bcb209..492bf1358a7c 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -7,9 +7,13 @@
* For licencing details see kernel-base/COPYING
*/
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/perf_event.h>
#include <asm/perf_event_p4.h>
+#include <asm/hardirq.h>
+#include <asm/apic.h>
+
+#include "perf_event.h"
#define P4_CNTR_LIMIT 3
/*
@@ -1303,7 +1307,7 @@ static __initconst const struct x86_pmu p4_pmu = {
.perfctr_second_write = 1,
};
-static __init int p4_pmu_init(void)
+__init int p4_pmu_init(void)
{
unsigned int low, high;
@@ -1326,5 +1330,3 @@ static __init int p4_pmu_init(void)
return 0;
}
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
index 20c097e33860..c7181befecde 100644
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -1,4 +1,7 @@
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+#include "perf_event.h"
/*
* Not sure about some of these
@@ -114,7 +117,7 @@ static __initconst const struct x86_pmu p6_pmu = {
.event_constraints = p6_event_constraints,
};
-static __init int p6_pmu_init(void)
+__init int p6_pmu_init(void)
{
switch (boot_cpu_data.x86_model) {
case 1:
@@ -138,5 +141,3 @@ static __init int p6_pmu_init(void)
return 0;
}
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 62ac8cb6ba27..14b23140e81f 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -85,6 +85,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "stepping\t: %d\n", c->x86_mask);
else
seq_printf(m, "stepping\t: unknown\n");
+ if (c->microcode)
+ seq_printf(m, "microcode\t: 0x%x\n", c->microcode);
if (cpu_has(c, X86_FEATURE_TSC)) {
unsigned int freq = cpufreq_quick_get(cpu);
diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c
new file mode 100644
index 000000000000..feca286c2bb4
--- /dev/null
+++ b/arch/x86/kernel/cpu/rdrand.c
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the Linux kernel.
+ *
+ * Copyright (c) 2011, Intel Corporation
+ * Authors: Fenghua Yu <fenghua.yu@intel.com>,
+ * H. Peter Anvin <hpa@linux.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.
+ *
+ */
+
+#include <asm/processor.h>
+#include <asm/archrandom.h>
+#include <asm/sections.h>
+
+static int __init x86_rdrand_setup(char *s)
+{
+ setup_clear_cpu_cap(X86_FEATURE_RDRAND);
+ return 1;
+}
+__setup("nordrand", x86_rdrand_setup);
+
+/* We can't use arch_get_random_long() here since alternatives haven't run */
+static inline int rdrand_long(unsigned long *v)
+{
+ int ok;
+ asm volatile("1: " RDRAND_LONG "\n\t"
+ "jc 2f\n\t"
+ "decl %0\n\t"
+ "jnz 1b\n\t"
+ "2:"
+ : "=r" (ok), "=a" (*v)
+ : "0" (RDRAND_RETRY_LOOPS));
+ return ok;
+}
+
+/*
+ * Force a reseed cycle; we are architecturally guaranteed a reseed
+ * after no more than 512 128-bit chunks of random data. This also
+ * acts as a test of the CPU capability.
+ */
+#define RESEED_LOOP ((512*128)/sizeof(unsigned long))
+
+void __cpuinit x86_init_rdrand(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_ARCH_RANDOM
+ unsigned long tmp;
+ int i, count, ok;
+
+ if (!cpu_has(c, X86_FEATURE_RDRAND))
+ return; /* Nothing to do */
+
+ for (count = i = 0; i < RESEED_LOOP; i++) {
+ ok = rdrand_long(&tmp);
+ if (ok)
+ count++;
+ }
+
+ if (count != RESEED_LOOP)
+ clear_cpu_cap(c, X86_FEATURE_RDRAND);
+#endif
+}
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 764c7c2b1811..13ad89971d47 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -32,15 +32,12 @@ int in_crash_kexec;
#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
-static void kdump_nmi_callback(int cpu, struct die_args *args)
+static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
{
- struct pt_regs *regs;
#ifdef CONFIG_X86_32
struct pt_regs fixed_regs;
#endif
- regs = args->regs;
-
#ifdef CONFIG_X86_32
if (!user_mode_vm(regs)) {
crash_fixup_ss_esp(&fixed_regs, regs);
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 6419bb05ecd5..faf8d5e74b0b 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -331,10 +331,15 @@ ENDPROC(native_usergs_sysret64)
1: incl PER_CPU_VAR(irq_count)
jne 2f
mov PER_CPU_VAR(irq_stack_ptr),%rsp
- EMPTY_FRAME 0
+ CFI_DEF_CFA_REGISTER rsi
2: /* Store previous stack value */
pushq %rsi
+ CFI_ESCAPE 0x0f /* DW_CFA_def_cfa_expression */, 6, \
+ 0x77 /* DW_OP_breg7 */, 0, \
+ 0x06 /* DW_OP_deref */, \
+ 0x08 /* DW_OP_const1u */, SS+8-RBP, \
+ 0x22 /* DW_OP_plus */
/* We entered an interrupt context - irqs are off: */
TRACE_IRQS_OFF
.endm
@@ -788,7 +793,6 @@ END(interrupt)
subq $ORIG_RAX-RBP, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
SAVE_ARGS_IRQ
- PARTIAL_FRAME 0
call \func
.endm
@@ -813,10 +817,10 @@ ret_from_intr:
/* Restore saved previous stack */
popq %rsi
- leaq 16(%rsi), %rsp
-
+ CFI_DEF_CFA_REGISTER rsi
+ leaq ARGOFFSET-RBP(%rsi), %rsp
CFI_DEF_CFA_REGISTER rsp
- CFI_ADJUST_CFA_OFFSET -16
+ CFI_ADJUST_CFA_OFFSET RBP-ARGOFFSET
exit_intr:
GET_THREAD_INFO(%rcx)
diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c
index 3fee346ef545..cacdd46d184d 100644
--- a/arch/x86/kernel/jump_label.c
+++ b/arch/x86/kernel/jump_label.c
@@ -42,7 +42,7 @@ void arch_jump_label_transform(struct jump_entry *entry,
put_online_cpus();
}
-void arch_jump_label_text_poke_early(jump_label_t addr)
+void __init_or_module arch_jump_label_text_poke_early(jump_label_t addr)
{
text_poke_early((void *)addr, ideal_nops[NOP_ATOMIC5],
JUMP_LABEL_NOP_SIZE);
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 00354d4919a9..faba5771acad 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -511,28 +511,37 @@ single_step_cont(struct pt_regs *regs, struct die_args *args)
static int was_in_debug_nmi[NR_CPUS];
-static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+static int kgdb_nmi_handler(unsigned int cmd, struct pt_regs *regs)
{
- struct pt_regs *regs = args->regs;
-
switch (cmd) {
- case DIE_NMI:
+ case NMI_LOCAL:
if (atomic_read(&kgdb_active) != -1) {
/* KGDB CPU roundup */
kgdb_nmicallback(raw_smp_processor_id(), regs);
was_in_debug_nmi[raw_smp_processor_id()] = 1;
touch_nmi_watchdog();
- return NOTIFY_STOP;
+ return NMI_HANDLED;
}
- return NOTIFY_DONE;
+ break;
- case DIE_NMIUNKNOWN:
+ case NMI_UNKNOWN:
if (was_in_debug_nmi[raw_smp_processor_id()]) {
was_in_debug_nmi[raw_smp_processor_id()] = 0;
- return NOTIFY_STOP;
+ return NMI_HANDLED;
}
- return NOTIFY_DONE;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ return NMI_DONE;
+}
+
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+ struct pt_regs *regs = args->regs;
+ switch (cmd) {
case DIE_DEBUG:
if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
if (user_mode(regs))
@@ -590,11 +599,6 @@ kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
static struct notifier_block kgdb_notifier = {
.notifier_call = kgdb_notify,
-
- /*
- * Lowest-prio notifier priority, we want to be notified last:
- */
- .priority = NMI_LOCAL_LOW_PRIOR,
};
/**
@@ -605,7 +609,31 @@ static struct notifier_block kgdb_notifier = {
*/
int kgdb_arch_init(void)
{
- return register_die_notifier(&kgdb_notifier);
+ int retval;
+
+ retval = register_die_notifier(&kgdb_notifier);
+ if (retval)
+ goto out;
+
+ retval = register_nmi_handler(NMI_LOCAL, kgdb_nmi_handler,
+ 0, "kgdb");
+ if (retval)
+ goto out1;
+
+ retval = register_nmi_handler(NMI_UNKNOWN, kgdb_nmi_handler,
+ 0, "kgdb");
+
+ if (retval)
+ goto out2;
+
+ return retval;
+
+out2:
+ unregister_nmi_handler(NMI_LOCAL, "kgdb");
+out1:
+ unregister_die_notifier(&kgdb_notifier);
+out:
+ return retval;
}
static void kgdb_hw_overflow_handler(struct perf_event *event,
@@ -673,6 +701,8 @@ void kgdb_arch_exit(void)
breakinfo[i].pev = NULL;
}
}
+ unregister_nmi_handler(NMI_UNKNOWN, "kgdb");
+ unregister_nmi_handler(NMI_LOCAL, "kgdb");
unregister_die_notifier(&kgdb_notifier);
}
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index f1a6244d7d93..7da647d8b64c 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -75,8 +75,11 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
/*
* Undefined/reserved opcodes, conditional jump, Opcode Extension
* Groups, and some special opcodes can not boost.
+ * This is non-const and volatile to keep gcc from statically
+ * optimizing it out, as variable_test_bit makes gcc think only
+ * *(unsigned long*) is used.
*/
-static const u32 twobyte_is_boostable[256 / 32] = {
+static volatile u32 twobyte_is_boostable[256 / 32] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ---------------------------------------------- */
W(0x00, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0) | /* 00 */
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 591be0ee1934..d494799aafcd 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -74,14 +74,13 @@ static struct equiv_cpu_entry *equiv_cpu_table;
static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
- u32 dummy;
if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
pr_warning("CPU%d: family %d not supported\n", cpu, c->x86);
return -1;
}
- rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy);
+ csig->rev = c->microcode;
pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
return 0;
@@ -130,6 +129,7 @@ static int apply_microcode_amd(int cpu)
int cpu_num = raw_smp_processor_id();
struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
struct microcode_amd *mc_amd = uci->mc;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
/* We should bind the task to the CPU */
BUG_ON(cpu_num != cpu);
@@ -150,6 +150,7 @@ static int apply_microcode_amd(int cpu)
pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
uci->cpu_sig.rev = rev;
+ c->microcode = rev;
return 0;
}
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index f9242800bc84..f2d2a664e797 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -483,7 +483,13 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
pr_debug("CPU%d removed\n", cpu);
break;
- case CPU_DEAD:
+
+ /*
+ * When a CPU goes offline, don't free up or invalidate the copy of
+ * the microcode in kernel memory, so that we can reuse it when the
+ * CPU comes back online without unnecessarily requesting the userspace
+ * for it again.
+ */
case CPU_UP_CANCELED_FROZEN:
/* The CPU refused to come up during a system resume */
microcode_fini_cpu(cpu);
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index 1a1b606d3e92..3ca42d0e43a2 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -161,12 +161,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
csig->pf = 1 << ((val[1] >> 18) & 7);
}
- wrmsr(MSR_IA32_UCODE_REV, 0, 0);
- /* see notes above for revision 1.07. Apparent chip bug */
- sync_core();
- /* get the current revision from MSR 0x8B */
- rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev);
-
+ csig->rev = c->microcode;
pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n",
cpu_num, csig->sig, csig->pf, csig->rev);
@@ -299,9 +294,9 @@ static int apply_microcode(int cpu)
struct microcode_intel *mc_intel;
struct ucode_cpu_info *uci;
unsigned int val[2];
- int cpu_num;
+ int cpu_num = raw_smp_processor_id();
+ struct cpuinfo_x86 *c = &cpu_data(cpu_num);
- cpu_num = raw_smp_processor_id();
uci = ucode_cpu_info + cpu;
mc_intel = uci->mc;
@@ -317,7 +312,7 @@ static int apply_microcode(int cpu)
(unsigned long) mc_intel->bits >> 16 >> 16);
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
- /* see notes above for revision 1.07. Apparent chip bug */
+ /* As documented in the SDM: Do a CPUID 1 here */
sync_core();
/* get the current revision from MSR 0x8B */
@@ -335,6 +330,7 @@ static int apply_microcode(int cpu)
(mc_intel->hdr.date >> 16) & 0xff);
uci->cpu_sig.rev = val[1];
+ c->microcode = val[1];
return 0;
}
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
new file mode 100644
index 000000000000..7ec5bd140b87
--- /dev/null
+++ b/arch/x86/kernel/nmi.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ * Copyright (C) 2011 Don Zickus Red Hat, Inc.
+ *
+ * Pentium III FXSR, SSE support
+ * Gareth Hughes <gareth@valinux.com>, May 2000
+ */
+
+/*
+ * Handle hardware traps and faults.
+ */
+#include <linux/spinlock.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
+#include <linux/nmi.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+#include <linux/slab.h>
+
+#include <linux/mca.h>
+
+#if defined(CONFIG_EDAC)
+#include <linux/edac.h>
+#endif
+
+#include <linux/atomic.h>
+#include <asm/traps.h>
+#include <asm/mach_traps.h>
+#include <asm/nmi.h>
+
+#define NMI_MAX_NAMELEN 16
+struct nmiaction {
+ struct list_head list;
+ nmi_handler_t handler;
+ unsigned int flags;
+ char *name;
+};
+
+struct nmi_desc {
+ spinlock_t lock;
+ struct list_head head;
+};
+
+static struct nmi_desc nmi_desc[NMI_MAX] =
+{
+ {
+ .lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[0].lock),
+ .head = LIST_HEAD_INIT(nmi_desc[0].head),
+ },
+ {
+ .lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[1].lock),
+ .head = LIST_HEAD_INIT(nmi_desc[1].head),
+ },
+
+};
+
+struct nmi_stats {
+ unsigned int normal;
+ unsigned int unknown;
+ unsigned int external;
+ unsigned int swallow;
+};
+
+static DEFINE_PER_CPU(struct nmi_stats, nmi_stats);
+
+static int ignore_nmis;
+
+int unknown_nmi_panic;
+/*
+ * Prevent NMI reason port (0x61) being accessed simultaneously, can
+ * only be used in NMI handler.
+ */
+static DEFINE_RAW_SPINLOCK(nmi_reason_lock);
+
+static int __init setup_unknown_nmi_panic(char *str)
+{
+ unknown_nmi_panic = 1;
+ return 1;
+}
+__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
+
+#define nmi_to_desc(type) (&nmi_desc[type])
+
+static int notrace __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2b)
+{
+ struct nmi_desc *desc = nmi_to_desc(type);
+ struct nmiaction *a;
+ int handled=0;
+
+ rcu_read_lock();
+
+ /*
+ * NMIs are edge-triggered, which means if you have enough
+ * of them concurrently, you can lose some because only one
+ * can be latched at any given time. Walk the whole list
+ * to handle those situations.
+ */
+ list_for_each_entry_rcu(a, &desc->head, list)
+ handled += a->handler(type, regs);
+
+ rcu_read_unlock();
+
+ /* return total number of NMI events handled */
+ return handled;
+}
+
+static int __setup_nmi(unsigned int type, struct nmiaction *action)
+{
+ struct nmi_desc *desc = nmi_to_desc(type);
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+
+ /*
+ * most handlers of type NMI_UNKNOWN never return because
+ * they just assume the NMI is theirs. Just a sanity check
+ * to manage expectations
+ */
+ WARN_ON_ONCE(type == NMI_UNKNOWN && !list_empty(&desc->head));
+
+ /*
+ * some handlers need to be executed first otherwise a fake
+ * event confuses some handlers (kdump uses this flag)
+ */
+ if (action->flags & NMI_FLAG_FIRST)
+ list_add_rcu(&action->list, &desc->head);
+ else
+ list_add_tail_rcu(&action->list, &desc->head);
+
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return 0;
+}
+
+static struct nmiaction *__free_nmi(unsigned int type, const char *name)
+{
+ struct nmi_desc *desc = nmi_to_desc(type);
+ struct nmiaction *n;
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+
+ list_for_each_entry_rcu(n, &desc->head, list) {
+ /*
+ * the name passed in to describe the nmi handler
+ * is used as the lookup key
+ */
+ if (!strcmp(n->name, name)) {
+ WARN(in_nmi(),
+ "Trying to free NMI (%s) from NMI context!\n", n->name);
+ list_del_rcu(&n->list);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&desc->lock, flags);
+ synchronize_rcu();
+ return (n);
+}
+
+int register_nmi_handler(unsigned int type, nmi_handler_t handler,
+ unsigned long nmiflags, const char *devname)
+{
+ struct nmiaction *action;
+ int retval = -ENOMEM;
+
+ if (!handler)
+ return -EINVAL;
+
+ action = kzalloc(sizeof(struct nmiaction), GFP_KERNEL);
+ if (!action)
+ goto fail_action;
+
+ action->handler = handler;
+ action->flags = nmiflags;
+ action->name = kstrndup(devname, NMI_MAX_NAMELEN, GFP_KERNEL);
+ if (!action->name)
+ goto fail_action_name;
+
+ retval = __setup_nmi(type, action);
+
+ if (retval)
+ goto fail_setup_nmi;
+
+ return retval;
+
+fail_setup_nmi:
+ kfree(action->name);
+fail_action_name:
+ kfree(action);
+fail_action:
+
+ return retval;
+}
+EXPORT_SYMBOL_GPL(register_nmi_handler);
+
+void unregister_nmi_handler(unsigned int type, const char *name)
+{
+ struct nmiaction *a;
+
+ a = __free_nmi(type, name);
+ if (a) {
+ kfree(a->name);
+ kfree(a);
+ }
+}
+
+EXPORT_SYMBOL_GPL(unregister_nmi_handler);
+
+static notrace __kprobes void
+pci_serr_error(unsigned char reason, struct pt_regs *regs)
+{
+ pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
+ reason, smp_processor_id());
+
+ /*
+ * On some machines, PCI SERR line is used to report memory
+ * errors. EDAC makes use of it.
+ */
+#if defined(CONFIG_EDAC)
+ if (edac_handler_set()) {
+ edac_atomic_assert_error();
+ return;
+ }
+#endif
+
+ if (panic_on_unrecovered_nmi)
+ panic("NMI: Not continuing");
+
+ pr_emerg("Dazed and confused, but trying to continue\n");
+
+ /* Clear and disable the PCI SERR error line. */
+ reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_SERR;
+ outb(reason, NMI_REASON_PORT);
+}
+
+static notrace __kprobes void
+io_check_error(unsigned char reason, struct pt_regs *regs)
+{
+ unsigned long i;
+
+ pr_emerg(
+ "NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
+ reason, smp_processor_id());
+ show_registers(regs);
+
+ if (panic_on_io_nmi)
+ panic("NMI IOCK error: Not continuing");
+
+ /* Re-enable the IOCK line, wait for a few seconds */
+ reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
+ outb(reason, NMI_REASON_PORT);
+
+ i = 20000;
+ while (--i) {
+ touch_nmi_watchdog();
+ udelay(100);
+ }
+
+ reason &= ~NMI_REASON_CLEAR_IOCHK;
+ outb(reason, NMI_REASON_PORT);
+}
+
+static notrace __kprobes void
+unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
+{
+ int handled;
+
+ /*
+ * Use 'false' as back-to-back NMIs are dealt with one level up.
+ * Of course this makes having multiple 'unknown' handlers useless
+ * as only the first one is ever run (unless it can actually determine
+ * if it caused the NMI)
+ */
+ handled = nmi_handle(NMI_UNKNOWN, regs, false);
+ if (handled) {
+ __this_cpu_add(nmi_stats.unknown, handled);
+ return;
+ }
+
+ __this_cpu_add(nmi_stats.unknown, 1);
+
+#ifdef CONFIG_MCA
+ /*
+ * Might actually be able to figure out what the guilty party
+ * is:
+ */
+ if (MCA_bus) {
+ mca_handle_nmi();
+ return;
+ }
+#endif
+ pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+ reason, smp_processor_id());
+
+ pr_emerg("Do you have a strange power saving mode enabled?\n");
+ if (unknown_nmi_panic || panic_on_unrecovered_nmi)
+ panic("NMI: Not continuing");
+
+ pr_emerg("Dazed and confused, but trying to continue\n");
+}
+
+static DEFINE_PER_CPU(bool, swallow_nmi);
+static DEFINE_PER_CPU(unsigned long, last_nmi_rip);
+
+static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+{
+ unsigned char reason = 0;
+ int handled;
+ bool b2b = false;
+
+ /*
+ * CPU-specific NMI must be processed before non-CPU-specific
+ * NMI, otherwise we may lose it, because the CPU-specific
+ * NMI can not be detected/processed on other CPUs.
+ */
+
+ /*
+ * Back-to-back NMIs are interesting because they can either
+ * be two NMI or more than two NMIs (any thing over two is dropped
+ * due to NMI being edge-triggered). If this is the second half
+ * of the back-to-back NMI, assume we dropped things and process
+ * more handlers. Otherwise reset the 'swallow' NMI behaviour
+ */
+ if (regs->ip == __this_cpu_read(last_nmi_rip))
+ b2b = true;
+ else
+ __this_cpu_write(swallow_nmi, false);
+
+ __this_cpu_write(last_nmi_rip, regs->ip);
+
+ handled = nmi_handle(NMI_LOCAL, regs, b2b);
+ __this_cpu_add(nmi_stats.normal, handled);
+ if (handled) {
+ /*
+ * There are cases when a NMI handler handles multiple
+ * events in the current NMI. One of these events may
+ * be queued for in the next NMI. Because the event is
+ * already handled, the next NMI will result in an unknown
+ * NMI. Instead lets flag this for a potential NMI to
+ * swallow.
+ */
+ if (handled > 1)
+ __this_cpu_write(swallow_nmi, true);
+ return;
+ }
+
+ /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
+ raw_spin_lock(&nmi_reason_lock);
+ reason = get_nmi_reason();
+
+ if (reason & NMI_REASON_MASK) {
+ if (reason & NMI_REASON_SERR)
+ pci_serr_error(reason, regs);
+ else if (reason & NMI_REASON_IOCHK)
+ io_check_error(reason, regs);
+#ifdef CONFIG_X86_32
+ /*
+ * Reassert NMI in case it became active
+ * meanwhile as it's edge-triggered:
+ */
+ reassert_nmi();
+#endif
+ __this_cpu_add(nmi_stats.external, 1);
+ raw_spin_unlock(&nmi_reason_lock);
+ return;
+ }
+ raw_spin_unlock(&nmi_reason_lock);
+
+ /*
+ * Only one NMI can be latched at a time. To handle
+ * this we may process multiple nmi handlers at once to
+ * cover the case where an NMI is dropped. The downside
+ * to this approach is we may process an NMI prematurely,
+ * while its real NMI is sitting latched. This will cause
+ * an unknown NMI on the next run of the NMI processing.
+ *
+ * We tried to flag that condition above, by setting the
+ * swallow_nmi flag when we process more than one event.
+ * This condition is also only present on the second half
+ * of a back-to-back NMI, so we flag that condition too.
+ *
+ * If both are true, we assume we already processed this
+ * NMI previously and we swallow it. Otherwise we reset
+ * the logic.
+ *
+ * There are scenarios where we may accidentally swallow
+ * a 'real' unknown NMI. For example, while processing
+ * a perf NMI another perf NMI comes in along with a
+ * 'real' unknown NMI. These two NMIs get combined into
+ * one (as descibed above). When the next NMI gets
+ * processed, it will be flagged by perf as handled, but
+ * noone will know that there was a 'real' unknown NMI sent
+ * also. As a result it gets swallowed. Or if the first
+ * perf NMI returns two events handled then the second
+ * NMI will get eaten by the logic below, again losing a
+ * 'real' unknown NMI. But this is the best we can do
+ * for now.
+ */
+ if (b2b && __this_cpu_read(swallow_nmi))
+ __this_cpu_add(nmi_stats.swallow, 1);
+ else
+ unknown_nmi_error(reason, regs);
+}
+
+dotraplinkage notrace __kprobes void
+do_nmi(struct pt_regs *regs, long error_code)
+{
+ nmi_enter();
+
+ inc_irq_stat(__nmi_count);
+
+ if (!ignore_nmis)
+ default_do_nmi(regs);
+
+ nmi_exit();
+}
+
+void stop_nmi(void)
+{
+ ignore_nmis++;
+}
+
+void restart_nmi(void)
+{
+ ignore_nmis--;
+}
+
+/* reset the back-to-back NMI logic */
+void local_touch_nmi(void)
+{
+ __this_cpu_write(last_nmi_rip, 0);
+}
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index b49d00da2aed..622872054fbe 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -117,8 +117,8 @@ again:
}
/*
- * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
- * documentation.
+ * See <Documentation/x86/x86_64/boot-options.txt> for the iommu kernel
+ * parameter documentation.
*/
static __init int iommu_setup(char *p)
{
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index e7e3b019c439..b9b3b1a51643 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -49,7 +49,7 @@ void free_thread_xstate(struct task_struct *tsk)
void free_thread_info(struct thread_info *ti)
{
free_thread_xstate(ti->task);
- free_pages((unsigned long)ti, get_order(THREAD_SIZE));
+ free_pages((unsigned long)ti, THREAD_ORDER);
}
void arch_task_cache_init(void)
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 7a3b65107a27..795b79f984c2 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -57,6 +57,7 @@
#include <asm/idle.h>
#include <asm/syscalls.h>
#include <asm/debugreg.h>
+#include <asm/nmi.h>
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
@@ -107,6 +108,7 @@ void cpu_idle(void)
if (cpu_is_offline(cpu))
play_dead();
+ local_touch_nmi();
local_irq_disable();
/* Don't trace irqs off for idle */
stop_critical_timings();
@@ -262,7 +264,7 @@ EXPORT_SYMBOL_GPL(start_thread);
/*
- * switch_to(x,yn) should switch tasks from x to y.
+ * switch_to(x,y) should switch tasks from x to y.
*
* We fsave/fwait so that an exception goes off at the right time
* (as a call from the fsave or fwait in effect) rather than to
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index f693e44e1bf6..3bd7e6eebf31 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -51,6 +51,7 @@
#include <asm/idle.h>
#include <asm/syscalls.h>
#include <asm/debugreg.h>
+#include <asm/nmi.h>
asmlinkage extern void ret_from_fork(void);
@@ -133,6 +134,7 @@ void cpu_idle(void)
* from here on, until they go to idle.
* Otherwise, idle callbacks can misfire.
*/
+ local_touch_nmi();
local_irq_disable();
enter_idle();
/* Don't trace irqs off for idle */
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 9242436e9937..e334be1182b9 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -464,7 +464,7 @@ static inline void kb_wait(void)
}
}
-static void vmxoff_nmi(int cpu, struct die_args *args)
+static void vmxoff_nmi(int cpu, struct pt_regs *regs)
{
cpu_emergency_vmxoff();
}
@@ -736,14 +736,10 @@ static nmi_shootdown_cb shootdown_callback;
static atomic_t waiting_for_crash_ipi;
-static int crash_nmi_callback(struct notifier_block *self,
- unsigned long val, void *data)
+static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)
{
int cpu;
- if (val != DIE_NMI)
- return NOTIFY_OK;
-
cpu = raw_smp_processor_id();
/* Don't do anything if this handler is invoked on crashing cpu.
@@ -751,10 +747,10 @@ static int crash_nmi_callback(struct notifier_block *self,
* an NMI if system was initially booted with nmi_watchdog parameter.
*/
if (cpu == crashing_cpu)
- return NOTIFY_STOP;
+ return NMI_HANDLED;
local_irq_disable();
- shootdown_callback(cpu, (struct die_args *)data);
+ shootdown_callback(cpu, regs);
atomic_dec(&waiting_for_crash_ipi);
/* Assume hlt works */
@@ -762,7 +758,7 @@ static int crash_nmi_callback(struct notifier_block *self,
for (;;)
cpu_relax();
- return 1;
+ return NMI_HANDLED;
}
static void smp_send_nmi_allbutself(void)
@@ -770,12 +766,6 @@ static void smp_send_nmi_allbutself(void)
apic->send_IPI_allbutself(NMI_VECTOR);
}
-static struct notifier_block crash_nmi_nb = {
- .notifier_call = crash_nmi_callback,
- /* we want to be the first one called */
- .priority = NMI_LOCAL_HIGH_PRIOR+1,
-};
-
/* Halt all other CPUs, calling the specified function on each of them
*
* This function can be used to halt all other CPUs on crash
@@ -794,7 +784,8 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback)
atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
/* Would it be better to replace the trap vector here? */
- if (register_die_notifier(&crash_nmi_nb))
+ if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback,
+ NMI_FLAG_FIRST, "crash"))
return; /* return what? */
/* Ensure the new callback function is set before sending
* out the NMI
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
index ff14a5044ce6..051489082d59 100644
--- a/arch/x86/kernel/sys_x86_64.c
+++ b/arch/x86/kernel/sys_x86_64.c
@@ -14,10 +14,73 @@
#include <linux/personality.h>
#include <linux/random.h>
#include <linux/uaccess.h>
+#include <linux/elf.h>
#include <asm/ia32.h>
#include <asm/syscalls.h>
+/*
+ * Align a virtual address to avoid aliasing in the I$ on AMD F15h.
+ *
+ * @flags denotes the allocation direction - bottomup or topdown -
+ * or vDSO; see call sites below.
+ */
+unsigned long align_addr(unsigned long addr, struct file *filp,
+ enum align_flags flags)
+{
+ unsigned long tmp_addr;
+
+ /* handle 32- and 64-bit case with a single conditional */
+ if (va_align.flags < 0 || !(va_align.flags & (2 - mmap_is_ia32())))
+ return addr;
+
+ if (!(current->flags & PF_RANDOMIZE))
+ return addr;
+
+ if (!((flags & ALIGN_VDSO) || filp))
+ return addr;
+
+ tmp_addr = addr;
+
+ /*
+ * We need an address which is <= than the original
+ * one only when in topdown direction.
+ */
+ if (!(flags & ALIGN_TOPDOWN))
+ tmp_addr += va_align.mask;
+
+ tmp_addr &= ~va_align.mask;
+
+ return tmp_addr;
+}
+
+static int __init control_va_addr_alignment(char *str)
+{
+ /* guard against enabling this on other CPU families */
+ if (va_align.flags < 0)
+ return 1;
+
+ if (*str == 0)
+ return 1;
+
+ if (*str == '=')
+ str++;
+
+ if (!strcmp(str, "32"))
+ va_align.flags = ALIGN_VA_32;
+ else if (!strcmp(str, "64"))
+ va_align.flags = ALIGN_VA_64;
+ else if (!strcmp(str, "off"))
+ va_align.flags = 0;
+ else if (!strcmp(str, "on"))
+ va_align.flags = ALIGN_VA_32 | ALIGN_VA_64;
+ else
+ return 0;
+
+ return 1;
+}
+__setup("align_va_addr", control_va_addr_alignment);
+
SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags,
unsigned long, fd, unsigned long, off)
@@ -92,6 +155,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
start_addr = addr;
full_search:
+
+ addr = align_addr(addr, filp, 0);
+
for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
if (end - len < addr) {
@@ -117,6 +183,7 @@ full_search:
mm->cached_hole_size = vma->vm_start - addr;
addr = vma->vm_end;
+ addr = align_addr(addr, filp, 0);
}
}
@@ -161,10 +228,13 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
/* make sure it can fit in the remaining address space */
if (addr > len) {
- vma = find_vma(mm, addr-len);
- if (!vma || addr <= vma->vm_start)
+ unsigned long tmp_addr = align_addr(addr - len, filp,
+ ALIGN_TOPDOWN);
+
+ vma = find_vma(mm, tmp_addr);
+ if (!vma || tmp_addr + len <= vma->vm_start)
/* remember the address as a hint for next time */
- return mm->free_area_cache = addr-len;
+ return mm->free_area_cache = tmp_addr;
}
if (mm->mmap_base < len)
@@ -173,6 +243,8 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
addr = mm->mmap_base-len;
do {
+ addr = align_addr(addr, filp, ALIGN_TOPDOWN);
+
/*
* Lookup failure means no vma is above this address,
* else if new region fits below vma->vm_start,
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index bc19be332bc9..9a0e31293920 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -346,3 +346,5 @@ ENTRY(sys_call_table)
.long sys_syncfs
.long sys_sendmmsg /* 345 */
.long sys_setns
+ .long sys_process_vm_readv
+ .long sys_process_vm_writev
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 6913369c234c..a8e3eb83466c 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -81,15 +81,6 @@ gate_desc idt_table[NR_VECTORS] __page_aligned_data = { { { { 0, 0 } } }, };
DECLARE_BITMAP(used_vectors, NR_VECTORS);
EXPORT_SYMBOL_GPL(used_vectors);
-static int ignore_nmis;
-
-int unknown_nmi_panic;
-/*
- * Prevent NMI reason port (0x61) being accessed simultaneously, can
- * only be used in NMI handler.
- */
-static DEFINE_RAW_SPINLOCK(nmi_reason_lock);
-
static inline void conditional_sti(struct pt_regs *regs)
{
if (regs->flags & X86_EFLAGS_IF)
@@ -307,152 +298,6 @@ gp_in_kernel:
die("general protection fault", regs, error_code);
}
-static int __init setup_unknown_nmi_panic(char *str)
-{
- unknown_nmi_panic = 1;
- return 1;
-}
-__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
-
-static notrace __kprobes void
-pci_serr_error(unsigned char reason, struct pt_regs *regs)
-{
- pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
- reason, smp_processor_id());
-
- /*
- * On some machines, PCI SERR line is used to report memory
- * errors. EDAC makes use of it.
- */
-#if defined(CONFIG_EDAC)
- if (edac_handler_set()) {
- edac_atomic_assert_error();
- return;
- }
-#endif
-
- if (panic_on_unrecovered_nmi)
- panic("NMI: Not continuing");
-
- pr_emerg("Dazed and confused, but trying to continue\n");
-
- /* Clear and disable the PCI SERR error line. */
- reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_SERR;
- outb(reason, NMI_REASON_PORT);
-}
-
-static notrace __kprobes void
-io_check_error(unsigned char reason, struct pt_regs *regs)
-{
- unsigned long i;
-
- pr_emerg(
- "NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
- reason, smp_processor_id());
- show_registers(regs);
-
- if (panic_on_io_nmi)
- panic("NMI IOCK error: Not continuing");
-
- /* Re-enable the IOCK line, wait for a few seconds */
- reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
- outb(reason, NMI_REASON_PORT);
-
- i = 20000;
- while (--i) {
- touch_nmi_watchdog();
- udelay(100);
- }
-
- reason &= ~NMI_REASON_CLEAR_IOCHK;
- outb(reason, NMI_REASON_PORT);
-}
-
-static notrace __kprobes void
-unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
-{
- if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) ==
- NOTIFY_STOP)
- return;
-#ifdef CONFIG_MCA
- /*
- * Might actually be able to figure out what the guilty party
- * is:
- */
- if (MCA_bus) {
- mca_handle_nmi();
- return;
- }
-#endif
- pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
- reason, smp_processor_id());
-
- pr_emerg("Do you have a strange power saving mode enabled?\n");
- if (unknown_nmi_panic || panic_on_unrecovered_nmi)
- panic("NMI: Not continuing");
-
- pr_emerg("Dazed and confused, but trying to continue\n");
-}
-
-static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
-{
- unsigned char reason = 0;
-
- /*
- * CPU-specific NMI must be processed before non-CPU-specific
- * NMI, otherwise we may lose it, because the CPU-specific
- * NMI can not be detected/processed on other CPUs.
- */
- if (notify_die(DIE_NMI, "nmi", regs, 0, 2, SIGINT) == NOTIFY_STOP)
- return;
-
- /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
- raw_spin_lock(&nmi_reason_lock);
- reason = get_nmi_reason();
-
- if (reason & NMI_REASON_MASK) {
- if (reason & NMI_REASON_SERR)
- pci_serr_error(reason, regs);
- else if (reason & NMI_REASON_IOCHK)
- io_check_error(reason, regs);
-#ifdef CONFIG_X86_32
- /*
- * Reassert NMI in case it became active
- * meanwhile as it's edge-triggered:
- */
- reassert_nmi();
-#endif
- raw_spin_unlock(&nmi_reason_lock);
- return;
- }
- raw_spin_unlock(&nmi_reason_lock);
-
- unknown_nmi_error(reason, regs);
-}
-
-dotraplinkage notrace __kprobes void
-do_nmi(struct pt_regs *regs, long error_code)
-{
- nmi_enter();
-
- inc_irq_stat(__nmi_count);
-
- if (!ignore_nmis)
- default_do_nmi(regs);
-
- nmi_exit();
-}
-
-void stop_nmi(void)
-{
- ignore_nmis++;
-}
-
-void restart_nmi(void)
-{
- ignore_nmis--;
-}
-
/* May run on IST stack. */
dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
{
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 8b4cc5f067de..f1e3be18a08f 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -29,6 +29,39 @@
#include "tss.h"
/*
+ * Operand types
+ */
+#define OpNone 0ull
+#define OpImplicit 1ull /* No generic decode */
+#define OpReg 2ull /* Register */
+#define OpMem 3ull /* Memory */
+#define OpAcc 4ull /* Accumulator: AL/AX/EAX/RAX */
+#define OpDI 5ull /* ES:DI/EDI/RDI */
+#define OpMem64 6ull /* Memory, 64-bit */
+#define OpImmUByte 7ull /* Zero-extended 8-bit immediate */
+#define OpDX 8ull /* DX register */
+#define OpCL 9ull /* CL register (for shifts) */
+#define OpImmByte 10ull /* 8-bit sign extended immediate */
+#define OpOne 11ull /* Implied 1 */
+#define OpImm 12ull /* Sign extended immediate */
+#define OpMem16 13ull /* Memory operand (16-bit). */
+#define OpMem32 14ull /* Memory operand (32-bit). */
+#define OpImmU 15ull /* Immediate operand, zero extended */
+#define OpSI 16ull /* SI/ESI/RSI */
+#define OpImmFAddr 17ull /* Immediate far address */
+#define OpMemFAddr 18ull /* Far address in memory */
+#define OpImmU16 19ull /* Immediate operand, 16 bits, zero extended */
+#define OpES 20ull /* ES */
+#define OpCS 21ull /* CS */
+#define OpSS 22ull /* SS */
+#define OpDS 23ull /* DS */
+#define OpFS 24ull /* FS */
+#define OpGS 25ull /* GS */
+
+#define OpBits 5 /* Width of operand field */
+#define OpMask ((1ull << OpBits) - 1)
+
+/*
* Opcode effective-address decode tables.
* Note that we only emulate instructions that have at least one memory
* operand (excluding implicit stack references). We assume that stack
@@ -40,37 +73,35 @@
/* Operand sizes: 8-bit operands or specified/overridden size. */
#define ByteOp (1<<0) /* 8-bit operands. */
/* Destination operand type. */
-#define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */
-#define DstReg (2<<1) /* Register operand. */
-#define DstMem (3<<1) /* Memory operand. */
-#define DstAcc (4<<1) /* Destination Accumulator */
-#define DstDI (5<<1) /* Destination is in ES:(E)DI */
-#define DstMem64 (6<<1) /* 64bit memory operand */
-#define DstImmUByte (7<<1) /* 8-bit unsigned immediate operand */
-#define DstDX (8<<1) /* Destination is in DX register */
-#define DstMask (0xf<<1)
+#define DstShift 1
+#define ImplicitOps (OpImplicit << DstShift)
+#define DstReg (OpReg << DstShift)
+#define DstMem (OpMem << DstShift)
+#define DstAcc (OpAcc << DstShift)
+#define DstDI (OpDI << DstShift)
+#define DstMem64 (OpMem64 << DstShift)
+#define DstImmUByte (OpImmUByte << DstShift)
+#define DstDX (OpDX << DstShift)
+#define DstMask (OpMask << DstShift)
/* Source operand type. */
-#define SrcNone (0<<5) /* No source operand. */
-#define SrcReg (1<<5) /* Register operand. */
-#define SrcMem (2<<5) /* Memory operand. */
-#define SrcMem16 (3<<5) /* Memory operand (16-bit). */
-#define SrcMem32 (4<<5) /* Memory operand (32-bit). */
-#define SrcImm (5<<5) /* Immediate operand. */
-#define SrcImmByte (6<<5) /* 8-bit sign-extended immediate operand. */
-#define SrcOne (7<<5) /* Implied '1' */
-#define SrcImmUByte (8<<5) /* 8-bit unsigned immediate operand. */
-#define SrcImmU (9<<5) /* Immediate operand, unsigned */
-#define SrcSI (0xa<<5) /* Source is in the DS:RSI */
-#define SrcImmFAddr (0xb<<5) /* Source is immediate far address */
-#define SrcMemFAddr (0xc<<5) /* Source is far address in memory */
-#define SrcAcc (0xd<<5) /* Source Accumulator */
-#define SrcImmU16 (0xe<<5) /* Immediate operand, unsigned, 16 bits */
-#define SrcDX (0xf<<5) /* Source is in DX register */
-#define SrcMask (0xf<<5)
-/* Generic ModRM decode. */
-#define ModRM (1<<9)
-/* Destination is only written; never read. */
-#define Mov (1<<10)
+#define SrcShift 6
+#define SrcNone (OpNone << SrcShift)
+#define SrcReg (OpReg << SrcShift)
+#define SrcMem (OpMem << SrcShift)
+#define SrcMem16 (OpMem16 << SrcShift)
+#define SrcMem32 (OpMem32 << SrcShift)
+#define SrcImm (OpImm << SrcShift)
+#define SrcImmByte (OpImmByte << SrcShift)
+#define SrcOne (OpOne << SrcShift)
+#define SrcImmUByte (OpImmUByte << SrcShift)
+#define SrcImmU (OpImmU << SrcShift)
+#define SrcSI (OpSI << SrcShift)
+#define SrcImmFAddr (OpImmFAddr << SrcShift)
+#define SrcMemFAddr (OpMemFAddr << SrcShift)
+#define SrcAcc (OpAcc << SrcShift)
+#define SrcImmU16 (OpImmU16 << SrcShift)
+#define SrcDX (OpDX << SrcShift)
+#define SrcMask (OpMask << SrcShift)
#define BitOp (1<<11)
#define MemAbs (1<<12) /* Memory operand is absolute displacement */
#define String (1<<13) /* String instruction (rep capable) */
@@ -81,6 +112,10 @@
#define Prefix (3<<15) /* Instruction varies with 66/f2/f3 prefix */
#define RMExt (4<<15) /* Opcode extension in ModRM r/m if mod == 3 */
#define Sse (1<<18) /* SSE Vector instruction */
+/* Generic ModRM decode. */
+#define ModRM (1<<19)
+/* Destination is only written; never read. */
+#define Mov (1<<20)
/* Misc flags */
#define Prot (1<<21) /* instruction generates #UD if not in prot-mode */
#define VendorSpecific (1<<22) /* Vendor specific instruction */
@@ -91,12 +126,19 @@
#define Priv (1<<27) /* instruction generates #GP if current CPL != 0 */
#define No64 (1<<28)
/* Source 2 operand type */
-#define Src2None (0<<29)
-#define Src2CL (1<<29)
-#define Src2ImmByte (2<<29)
-#define Src2One (3<<29)
-#define Src2Imm (4<<29)
-#define Src2Mask (7<<29)
+#define Src2Shift (29)
+#define Src2None (OpNone << Src2Shift)
+#define Src2CL (OpCL << Src2Shift)
+#define Src2ImmByte (OpImmByte << Src2Shift)
+#define Src2One (OpOne << Src2Shift)
+#define Src2Imm (OpImm << Src2Shift)
+#define Src2ES (OpES << Src2Shift)
+#define Src2CS (OpCS << Src2Shift)
+#define Src2SS (OpSS << Src2Shift)
+#define Src2DS (OpDS << Src2Shift)
+#define Src2FS (OpFS << Src2Shift)
+#define Src2GS (OpGS << Src2Shift)
+#define Src2Mask (OpMask << Src2Shift)
#define X2(x...) x, x
#define X3(x...) X2(x), x
@@ -108,8 +150,8 @@
#define X16(x...) X8(x), X8(x)
struct opcode {
- u32 flags;
- u8 intercept;
+ u64 flags : 56;
+ u64 intercept : 8;
union {
int (*execute)(struct x86_emulate_ctxt *ctxt);
struct opcode *group;
@@ -205,105 +247,100 @@ struct gprefix {
#define ON64(x)
#endif
-#define ____emulate_2op(_op, _src, _dst, _eflags, _x, _y, _suffix, _dsttype) \
+#define ____emulate_2op(ctxt, _op, _x, _y, _suffix, _dsttype) \
do { \
__asm__ __volatile__ ( \
_PRE_EFLAGS("0", "4", "2") \
_op _suffix " %"_x"3,%1; " \
_POST_EFLAGS("0", "4", "2") \
- : "=m" (_eflags), "+q" (*(_dsttype*)&(_dst).val),\
+ : "=m" ((ctxt)->eflags), \
+ "+q" (*(_dsttype*)&(ctxt)->dst.val), \
"=&r" (_tmp) \
- : _y ((_src).val), "i" (EFLAGS_MASK)); \
+ : _y ((ctxt)->src.val), "i" (EFLAGS_MASK)); \
} while (0)
/* Raw emulation: instruction has two explicit operands. */
-#define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \
+#define __emulate_2op_nobyte(ctxt,_op,_wx,_wy,_lx,_ly,_qx,_qy) \
do { \
unsigned long _tmp; \
\
- switch ((_dst).bytes) { \
+ switch ((ctxt)->dst.bytes) { \
case 2: \
- ____emulate_2op(_op,_src,_dst,_eflags,_wx,_wy,"w",u16);\
+ ____emulate_2op(ctxt,_op,_wx,_wy,"w",u16); \
break; \
case 4: \
- ____emulate_2op(_op,_src,_dst,_eflags,_lx,_ly,"l",u32);\
+ ____emulate_2op(ctxt,_op,_lx,_ly,"l",u32); \
break; \
case 8: \
- ON64(____emulate_2op(_op,_src,_dst,_eflags,_qx,_qy,"q",u64)); \
+ ON64(____emulate_2op(ctxt,_op,_qx,_qy,"q",u64)); \
break; \
} \
} while (0)
-#define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \
+#define __emulate_2op(ctxt,_op,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \
do { \
unsigned long _tmp; \
- switch ((_dst).bytes) { \
+ switch ((ctxt)->dst.bytes) { \
case 1: \
- ____emulate_2op(_op,_src,_dst,_eflags,_bx,_by,"b",u8); \
+ ____emulate_2op(ctxt,_op,_bx,_by,"b",u8); \
break; \
default: \
- __emulate_2op_nobyte(_op, _src, _dst, _eflags, \
+ __emulate_2op_nobyte(ctxt, _op, \
_wx, _wy, _lx, _ly, _qx, _qy); \
break; \
} \
} while (0)
/* Source operand is byte-sized and may be restricted to just %cl. */
-#define emulate_2op_SrcB(_op, _src, _dst, _eflags) \
- __emulate_2op(_op, _src, _dst, _eflags, \
- "b", "c", "b", "c", "b", "c", "b", "c")
+#define emulate_2op_SrcB(ctxt, _op) \
+ __emulate_2op(ctxt, _op, "b", "c", "b", "c", "b", "c", "b", "c")
/* Source operand is byte, word, long or quad sized. */
-#define emulate_2op_SrcV(_op, _src, _dst, _eflags) \
- __emulate_2op(_op, _src, _dst, _eflags, \
- "b", "q", "w", "r", _LO32, "r", "", "r")
+#define emulate_2op_SrcV(ctxt, _op) \
+ __emulate_2op(ctxt, _op, "b", "q", "w", "r", _LO32, "r", "", "r")
/* Source operand is word, long or quad sized. */
-#define emulate_2op_SrcV_nobyte(_op, _src, _dst, _eflags) \
- __emulate_2op_nobyte(_op, _src, _dst, _eflags, \
- "w", "r", _LO32, "r", "", "r")
+#define emulate_2op_SrcV_nobyte(ctxt, _op) \
+ __emulate_2op_nobyte(ctxt, _op, "w", "r", _LO32, "r", "", "r")
/* Instruction has three operands and one operand is stored in ECX register */
-#define __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, _suffix, _type) \
+#define __emulate_2op_cl(ctxt, _op, _suffix, _type) \
do { \
unsigned long _tmp; \
- _type _clv = (_cl).val; \
- _type _srcv = (_src).val; \
- _type _dstv = (_dst).val; \
+ _type _clv = (ctxt)->src2.val; \
+ _type _srcv = (ctxt)->src.val; \
+ _type _dstv = (ctxt)->dst.val; \
\
__asm__ __volatile__ ( \
_PRE_EFLAGS("0", "5", "2") \
_op _suffix " %4,%1 \n" \
_POST_EFLAGS("0", "5", "2") \
- : "=m" (_eflags), "+r" (_dstv), "=&r" (_tmp) \
+ : "=m" ((ctxt)->eflags), "+r" (_dstv), "=&r" (_tmp) \
: "c" (_clv) , "r" (_srcv), "i" (EFLAGS_MASK) \
); \
\
- (_cl).val = (unsigned long) _clv; \
- (_src).val = (unsigned long) _srcv; \
- (_dst).val = (unsigned long) _dstv; \
+ (ctxt)->src2.val = (unsigned long) _clv; \
+ (ctxt)->src2.val = (unsigned long) _srcv; \
+ (ctxt)->dst.val = (unsigned long) _dstv; \
} while (0)
-#define emulate_2op_cl(_op, _cl, _src, _dst, _eflags) \
+#define emulate_2op_cl(ctxt, _op) \
do { \
- switch ((_dst).bytes) { \
+ switch ((ctxt)->dst.bytes) { \
case 2: \
- __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \
- "w", unsigned short); \
+ __emulate_2op_cl(ctxt, _op, "w", u16); \
break; \
case 4: \
- __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \
- "l", unsigned int); \
+ __emulate_2op_cl(ctxt, _op, "l", u32); \
break; \
case 8: \
- ON64(__emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \
- "q", unsigned long)); \
+ ON64(__emulate_2op_cl(ctxt, _op, "q", ulong)); \
break; \
} \
} while (0)
-#define __emulate_1op(_op, _dst, _eflags, _suffix) \
+#define __emulate_1op(ctxt, _op, _suffix) \
do { \
unsigned long _tmp; \
\
@@ -311,39 +348,27 @@ struct gprefix {
_PRE_EFLAGS("0", "3", "2") \
_op _suffix " %1; " \
_POST_EFLAGS("0", "3", "2") \
- : "=m" (_eflags), "+m" ((_dst).val), \
+ : "=m" ((ctxt)->eflags), "+m" ((ctxt)->dst.val), \
"=&r" (_tmp) \
: "i" (EFLAGS_MASK)); \
} while (0)
/* Instruction has only one explicit operand (no source operand). */
-#define emulate_1op(_op, _dst, _eflags) \
+#define emulate_1op(ctxt, _op) \
do { \
- switch ((_dst).bytes) { \
- case 1: __emulate_1op(_op, _dst, _eflags, "b"); break; \
- case 2: __emulate_1op(_op, _dst, _eflags, "w"); break; \
- case 4: __emulate_1op(_op, _dst, _eflags, "l"); break; \
- case 8: ON64(__emulate_1op(_op, _dst, _eflags, "q")); break; \
+ switch ((ctxt)->dst.bytes) { \
+ case 1: __emulate_1op(ctxt, _op, "b"); break; \
+ case 2: __emulate_1op(ctxt, _op, "w"); break; \
+ case 4: __emulate_1op(ctxt, _op, "l"); break; \
+ case 8: ON64(__emulate_1op(ctxt, _op, "q")); break; \
} \
} while (0)
-#define __emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags, _suffix) \
- do { \
- unsigned long _tmp; \
- \
- __asm__ __volatile__ ( \
- _PRE_EFLAGS("0", "4", "1") \
- _op _suffix " %5; " \
- _POST_EFLAGS("0", "4", "1") \
- : "=m" (_eflags), "=&r" (_tmp), \
- "+a" (_rax), "+d" (_rdx) \
- : "i" (EFLAGS_MASK), "m" ((_src).val), \
- "a" (_rax), "d" (_rdx)); \
- } while (0)
-
-#define __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, _eflags, _suffix, _ex) \
+#define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex) \
do { \
unsigned long _tmp; \
+ ulong *rax = &(ctxt)->regs[VCPU_REGS_RAX]; \
+ ulong *rdx = &(ctxt)->regs[VCPU_REGS_RDX]; \
\
__asm__ __volatile__ ( \
_PRE_EFLAGS("0", "5", "1") \
@@ -356,53 +381,27 @@ struct gprefix {
"jmp 2b \n\t" \
".popsection \n\t" \
_ASM_EXTABLE(1b, 3b) \
- : "=m" (_eflags), "=&r" (_tmp), \
- "+a" (_rax), "+d" (_rdx), "+qm"(_ex) \
- : "i" (EFLAGS_MASK), "m" ((_src).val), \
- "a" (_rax), "d" (_rdx)); \
+ : "=m" ((ctxt)->eflags), "=&r" (_tmp), \
+ "+a" (*rax), "+d" (*rdx), "+qm"(_ex) \
+ : "i" (EFLAGS_MASK), "m" ((ctxt)->src.val), \
+ "a" (*rax), "d" (*rdx)); \
} while (0)
/* instruction has only one source operand, destination is implicit (e.g. mul, div, imul, idiv) */
-#define emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags) \
+#define emulate_1op_rax_rdx(ctxt, _op, _ex) \
do { \
- switch((_src).bytes) { \
+ switch((ctxt)->src.bytes) { \
case 1: \
- __emulate_1op_rax_rdx(_op, _src, _rax, _rdx, \
- _eflags, "b"); \
+ __emulate_1op_rax_rdx(ctxt, _op, "b", _ex); \
break; \
case 2: \
- __emulate_1op_rax_rdx(_op, _src, _rax, _rdx, \
- _eflags, "w"); \
+ __emulate_1op_rax_rdx(ctxt, _op, "w", _ex); \
break; \
case 4: \
- __emulate_1op_rax_rdx(_op, _src, _rax, _rdx, \
- _eflags, "l"); \
- break; \
- case 8: \
- ON64(__emulate_1op_rax_rdx(_op, _src, _rax, _rdx, \
- _eflags, "q")); \
- break; \
- } \
- } while (0)
-
-#define emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, _eflags, _ex) \
- do { \
- switch((_src).bytes) { \
- case 1: \
- __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
- _eflags, "b", _ex); \
- break; \
- case 2: \
- __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
- _eflags, "w", _ex); \
- break; \
- case 4: \
- __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
- _eflags, "l", _ex); \
+ __emulate_1op_rax_rdx(ctxt, _op, "l", _ex); \
break; \
case 8: ON64( \
- __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
- _eflags, "q", _ex)); \
+ __emulate_1op_rax_rdx(ctxt, _op, "q", _ex)); \
break; \
} \
} while (0)
@@ -651,41 +650,50 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
}
-static int do_insn_fetch_byte(struct x86_emulate_ctxt *ctxt,
- unsigned long eip, u8 *dest)
+/*
+ * Fetch the next byte of the instruction being emulated which is pointed to
+ * by ctxt->_eip, then increment ctxt->_eip.
+ *
+ * Also prefetch the remaining bytes of the instruction without crossing page
+ * boundary if they are not in fetch_cache yet.
+ */
+static int do_insn_fetch_byte(struct x86_emulate_ctxt *ctxt, u8 *dest)
{
struct fetch_cache *fc = &ctxt->fetch;
int rc;
int size, cur_size;
- if (eip == fc->end) {
+ if (ctxt->_eip == fc->end) {
unsigned long linear;
- struct segmented_address addr = { .seg=VCPU_SREG_CS, .ea=eip};
+ struct segmented_address addr = { .seg = VCPU_SREG_CS,
+ .ea = ctxt->_eip };
cur_size = fc->end - fc->start;
- size = min(15UL - cur_size, PAGE_SIZE - offset_in_page(eip));
+ size = min(15UL - cur_size,
+ PAGE_SIZE - offset_in_page(ctxt->_eip));
rc = __linearize(ctxt, addr, size, false, true, &linear);
- if (rc != X86EMUL_CONTINUE)
+ if (unlikely(rc != X86EMUL_CONTINUE))
return rc;
rc = ctxt->ops->fetch(ctxt, linear, fc->data + cur_size,
size, &ctxt->exception);
- if (rc != X86EMUL_CONTINUE)
+ if (unlikely(rc != X86EMUL_CONTINUE))
return rc;
fc->end += size;
}
- *dest = fc->data[eip - fc->start];
+ *dest = fc->data[ctxt->_eip - fc->start];
+ ctxt->_eip++;
return X86EMUL_CONTINUE;
}
static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
- unsigned long eip, void *dest, unsigned size)
+ void *dest, unsigned size)
{
int rc;
/* x86 instructions are limited to 15 bytes. */
- if (eip + size - ctxt->eip > 15)
+ if (unlikely(ctxt->_eip + size - ctxt->eip > 15))
return X86EMUL_UNHANDLEABLE;
while (size--) {
- rc = do_insn_fetch_byte(ctxt, eip++, dest++);
+ rc = do_insn_fetch_byte(ctxt, dest++);
if (rc != X86EMUL_CONTINUE)
return rc;
}
@@ -693,20 +701,18 @@ static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
}
/* Fetch next part of the instruction being emulated. */
-#define insn_fetch(_type, _size, _eip) \
+#define insn_fetch(_type, _ctxt) \
({ unsigned long _x; \
- rc = do_insn_fetch(ctxt, (_eip), &_x, (_size)); \
+ rc = do_insn_fetch(_ctxt, &_x, sizeof(_type)); \
if (rc != X86EMUL_CONTINUE) \
goto done; \
- (_eip) += (_size); \
(_type)_x; \
})
-#define insn_fetch_arr(_arr, _size, _eip) \
-({ rc = do_insn_fetch(ctxt, (_eip), _arr, (_size)); \
+#define insn_fetch_arr(_arr, _size, _ctxt) \
+({ rc = do_insn_fetch(_ctxt, _arr, (_size)); \
if (rc != X86EMUL_CONTINUE) \
goto done; \
- (_eip) += (_size); \
})
/*
@@ -894,7 +900,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
ctxt->modrm_rm = base_reg = (ctxt->rex_prefix & 1) << 3; /* REG.B */
}
- ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+ ctxt->modrm = insn_fetch(u8, ctxt);
ctxt->modrm_mod |= (ctxt->modrm & 0xc0) >> 6;
ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
ctxt->modrm_rm |= (ctxt->modrm & 0x07);
@@ -928,13 +934,13 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
switch (ctxt->modrm_mod) {
case 0:
if (ctxt->modrm_rm == 6)
- modrm_ea += insn_fetch(u16, 2, ctxt->_eip);
+ modrm_ea += insn_fetch(u16, ctxt);
break;
case 1:
- modrm_ea += insn_fetch(s8, 1, ctxt->_eip);
+ modrm_ea += insn_fetch(s8, ctxt);
break;
case 2:
- modrm_ea += insn_fetch(u16, 2, ctxt->_eip);
+ modrm_ea += insn_fetch(u16, ctxt);
break;
}
switch (ctxt->modrm_rm) {
@@ -971,13 +977,13 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
} else {
/* 32/64-bit ModR/M decode. */
if ((ctxt->modrm_rm & 7) == 4) {
- sib = insn_fetch(u8, 1, ctxt->_eip);
+ sib = insn_fetch(u8, ctxt);
index_reg |= (sib >> 3) & 7;
base_reg |= sib & 7;
scale = sib >> 6;
if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)
- modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
+ modrm_ea += insn_fetch(s32, ctxt);
else
modrm_ea += ctxt->regs[base_reg];
if (index_reg != 4)
@@ -990,13 +996,13 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
switch (ctxt->modrm_mod) {
case 0:
if (ctxt->modrm_rm == 5)
- modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
+ modrm_ea += insn_fetch(s32, ctxt);
break;
case 1:
- modrm_ea += insn_fetch(s8, 1, ctxt->_eip);
+ modrm_ea += insn_fetch(s8, ctxt);
break;
case 2:
- modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
+ modrm_ea += insn_fetch(s32, ctxt);
break;
}
}
@@ -1013,13 +1019,13 @@ static int decode_abs(struct x86_emulate_ctxt *ctxt,
op->type = OP_MEM;
switch (ctxt->ad_bytes) {
case 2:
- op->addr.mem.ea = insn_fetch(u16, 2, ctxt->_eip);
+ op->addr.mem.ea = insn_fetch(u16, ctxt);
break;
case 4:
- op->addr.mem.ea = insn_fetch(u32, 4, ctxt->_eip);
+ op->addr.mem.ea = insn_fetch(u32, ctxt);
break;
case 8:
- op->addr.mem.ea = insn_fetch(u64, 8, ctxt->_eip);
+ op->addr.mem.ea = insn_fetch(u64, ctxt);
break;
}
done:
@@ -1452,15 +1458,18 @@ static int em_popf(struct x86_emulate_ctxt *ctxt)
return emulate_popf(ctxt, &ctxt->dst.val, ctxt->op_bytes);
}
-static int emulate_push_sreg(struct x86_emulate_ctxt *ctxt, int seg)
+static int em_push_sreg(struct x86_emulate_ctxt *ctxt)
{
+ int seg = ctxt->src2.val;
+
ctxt->src.val = get_segment_selector(ctxt, seg);
return em_push(ctxt);
}
-static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt, int seg)
+static int em_pop_sreg(struct x86_emulate_ctxt *ctxt)
{
+ int seg = ctxt->src2.val;
unsigned long selector;
int rc;
@@ -1674,64 +1683,74 @@ static int em_grp2(struct x86_emulate_ctxt *ctxt)
{
switch (ctxt->modrm_reg) {
case 0: /* rol */
- emulate_2op_SrcB("rol", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcB(ctxt, "rol");
break;
case 1: /* ror */
- emulate_2op_SrcB("ror", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcB(ctxt, "ror");
break;
case 2: /* rcl */
- emulate_2op_SrcB("rcl", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcB(ctxt, "rcl");
break;
case 3: /* rcr */
- emulate_2op_SrcB("rcr", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcB(ctxt, "rcr");
break;
case 4: /* sal/shl */
case 6: /* sal/shl */
- emulate_2op_SrcB("sal", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcB(ctxt, "sal");
break;
case 5: /* shr */
- emulate_2op_SrcB("shr", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcB(ctxt, "shr");
break;
case 7: /* sar */
- emulate_2op_SrcB("sar", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcB(ctxt, "sar");
break;
}
return X86EMUL_CONTINUE;
}
-static int em_grp3(struct x86_emulate_ctxt *ctxt)
+static int em_not(struct x86_emulate_ctxt *ctxt)
+{
+ ctxt->dst.val = ~ctxt->dst.val;
+ return X86EMUL_CONTINUE;
+}
+
+static int em_neg(struct x86_emulate_ctxt *ctxt)
+{
+ emulate_1op(ctxt, "neg");
+ return X86EMUL_CONTINUE;
+}
+
+static int em_mul_ex(struct x86_emulate_ctxt *ctxt)
+{
+ u8 ex = 0;
+
+ emulate_1op_rax_rdx(ctxt, "mul", ex);
+ return X86EMUL_CONTINUE;
+}
+
+static int em_imul_ex(struct x86_emulate_ctxt *ctxt)
+{
+ u8 ex = 0;
+
+ emulate_1op_rax_rdx(ctxt, "imul", ex);
+ return X86EMUL_CONTINUE;
+}
+
+static int em_div_ex(struct x86_emulate_ctxt *ctxt)
{
- unsigned long *rax = &ctxt->regs[VCPU_REGS_RAX];
- unsigned long *rdx = &ctxt->regs[VCPU_REGS_RDX];
u8 de = 0;
- switch (ctxt->modrm_reg) {
- case 0 ... 1: /* test */
- emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags);
- break;
- case 2: /* not */
- ctxt->dst.val = ~ctxt->dst.val;
- break;
- case 3: /* neg */
- emulate_1op("neg", ctxt->dst, ctxt->eflags);
- break;
- case 4: /* mul */
- emulate_1op_rax_rdx("mul", ctxt->src, *rax, *rdx, ctxt->eflags);
- break;
- case 5: /* imul */
- emulate_1op_rax_rdx("imul", ctxt->src, *rax, *rdx, ctxt->eflags);
- break;
- case 6: /* div */
- emulate_1op_rax_rdx_ex("div", ctxt->src, *rax, *rdx,
- ctxt->eflags, de);
- break;
- case 7: /* idiv */
- emulate_1op_rax_rdx_ex("idiv", ctxt->src, *rax, *rdx,
- ctxt->eflags, de);
- break;
- default:
- return X86EMUL_UNHANDLEABLE;
- }
+ emulate_1op_rax_rdx(ctxt, "div", de);
+ if (de)
+ return emulate_de(ctxt);
+ return X86EMUL_CONTINUE;
+}
+
+static int em_idiv_ex(struct x86_emulate_ctxt *ctxt)
+{
+ u8 de = 0;
+
+ emulate_1op_rax_rdx(ctxt, "idiv", de);
if (de)
return emulate_de(ctxt);
return X86EMUL_CONTINUE;
@@ -1743,10 +1762,10 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt)
switch (ctxt->modrm_reg) {
case 0: /* inc */
- emulate_1op("inc", ctxt->dst, ctxt->eflags);
+ emulate_1op(ctxt, "inc");
break;
case 1: /* dec */
- emulate_1op("dec", ctxt->dst, ctxt->eflags);
+ emulate_1op(ctxt, "dec");
break;
case 2: /* call near abs */ {
long int old_eip;
@@ -1812,8 +1831,9 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt)
return rc;
}
-static int emulate_load_segment(struct x86_emulate_ctxt *ctxt, int seg)
+static int em_lseg(struct x86_emulate_ctxt *ctxt)
{
+ int seg = ctxt->src2.val;
unsigned short sel;
int rc;
@@ -2452,7 +2472,7 @@ static int em_das(struct x86_emulate_ctxt *ctxt)
ctxt->src.type = OP_IMM;
ctxt->src.val = 0;
ctxt->src.bytes = 1;
- emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "or");
ctxt->eflags &= ~(X86_EFLAGS_AF | X86_EFLAGS_CF);
if (cf)
ctxt->eflags |= X86_EFLAGS_CF;
@@ -2502,49 +2522,49 @@ static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
static int em_add(struct x86_emulate_ctxt *ctxt)
{
- emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "add");
return X86EMUL_CONTINUE;
}
static int em_or(struct x86_emulate_ctxt *ctxt)
{
- emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "or");
return X86EMUL_CONTINUE;
}
static int em_adc(struct x86_emulate_ctxt *ctxt)
{
- emulate_2op_SrcV("adc", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "adc");
return X86EMUL_CONTINUE;
}
static int em_sbb(struct x86_emulate_ctxt *ctxt)
{
- emulate_2op_SrcV("sbb", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "sbb");
return X86EMUL_CONTINUE;
}
static int em_and(struct x86_emulate_ctxt *ctxt)
{
- emulate_2op_SrcV("and", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "and");
return X86EMUL_CONTINUE;
}
static int em_sub(struct x86_emulate_ctxt *ctxt)
{
- emulate_2op_SrcV("sub", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "sub");
return X86EMUL_CONTINUE;
}
static int em_xor(struct x86_emulate_ctxt *ctxt)
{
- emulate_2op_SrcV("xor", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "xor");
return X86EMUL_CONTINUE;
}
static int em_cmp(struct x86_emulate_ctxt *ctxt)
{
- emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "cmp");
/* Disable writeback. */
ctxt->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
@@ -2552,7 +2572,9 @@ static int em_cmp(struct x86_emulate_ctxt *ctxt)
static int em_test(struct x86_emulate_ctxt *ctxt)
{
- emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "test");
+ /* Disable writeback. */
+ ctxt->dst.type = OP_NONE;
return X86EMUL_CONTINUE;
}
@@ -2570,7 +2592,7 @@ static int em_xchg(struct x86_emulate_ctxt *ctxt)
static int em_imul(struct x86_emulate_ctxt *ctxt)
{
- emulate_2op_SrcV_nobyte("imul", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV_nobyte(ctxt, "imul");
return X86EMUL_CONTINUE;
}
@@ -3025,9 +3047,14 @@ static struct opcode group1A[] = {
};
static struct opcode group3[] = {
- D(DstMem | SrcImm | ModRM), D(DstMem | SrcImm | ModRM),
- D(DstMem | SrcNone | ModRM | Lock), D(DstMem | SrcNone | ModRM | Lock),
- X4(D(SrcMem | ModRM)),
+ I(DstMem | SrcImm | ModRM, em_test),
+ I(DstMem | SrcImm | ModRM, em_test),
+ I(DstMem | SrcNone | ModRM | Lock, em_not),
+ I(DstMem | SrcNone | ModRM | Lock, em_neg),
+ I(SrcMem | ModRM, em_mul_ex),
+ I(SrcMem | ModRM, em_imul_ex),
+ I(SrcMem | ModRM, em_div_ex),
+ I(SrcMem | ModRM, em_idiv_ex),
};
static struct opcode group4[] = {
@@ -3090,16 +3117,20 @@ static struct gprefix pfx_0f_6f_0f_7f = {
static struct opcode opcode_table[256] = {
/* 0x00 - 0x07 */
I6ALU(Lock, em_add),
- D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
+ I(ImplicitOps | Stack | No64 | Src2ES, em_push_sreg),
+ I(ImplicitOps | Stack | No64 | Src2ES, em_pop_sreg),
/* 0x08 - 0x0F */
I6ALU(Lock, em_or),
- D(ImplicitOps | Stack | No64), N,
+ I(ImplicitOps | Stack | No64 | Src2CS, em_push_sreg),
+ N,
/* 0x10 - 0x17 */
I6ALU(Lock, em_adc),
- D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
+ I(ImplicitOps | Stack | No64 | Src2SS, em_push_sreg),
+ I(ImplicitOps | Stack | No64 | Src2SS, em_pop_sreg),
/* 0x18 - 0x1F */
I6ALU(Lock, em_sbb),
- D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
+ I(ImplicitOps | Stack | No64 | Src2DS, em_push_sreg),
+ I(ImplicitOps | Stack | No64 | Src2DS, em_pop_sreg),
/* 0x20 - 0x27 */
I6ALU(Lock, em_and), N, N,
/* 0x28 - 0x2F */
@@ -3167,7 +3198,8 @@ static struct opcode opcode_table[256] = {
D2bv(DstMem | SrcImmByte | ModRM),
I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm),
I(ImplicitOps | Stack, em_ret),
- D(DstReg | SrcMemFAddr | ModRM | No64), D(DstReg | SrcMemFAddr | ModRM | No64),
+ I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg),
+ I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),
G(ByteOp, group11), G(0, group11),
/* 0xC8 - 0xCF */
N, N, N, I(ImplicitOps | Stack, em_ret_far),
@@ -3242,20 +3274,22 @@ static struct opcode twobyte_table[256] = {
/* 0x90 - 0x9F */
X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)),
/* 0xA0 - 0xA7 */
- D(ImplicitOps | Stack), D(ImplicitOps | Stack),
+ I(Stack | Src2FS, em_push_sreg), I(Stack | Src2FS, em_pop_sreg),
DI(ImplicitOps, cpuid), D(DstMem | SrcReg | ModRM | BitOp),
D(DstMem | SrcReg | Src2ImmByte | ModRM),
D(DstMem | SrcReg | Src2CL | ModRM), N, N,
/* 0xA8 - 0xAF */
- D(ImplicitOps | Stack), D(ImplicitOps | Stack),
+ I(Stack | Src2GS, em_push_sreg), I(Stack | Src2GS, em_pop_sreg),
DI(ImplicitOps, rsm), D(DstMem | SrcReg | ModRM | BitOp | Lock),
D(DstMem | SrcReg | Src2ImmByte | ModRM),
D(DstMem | SrcReg | Src2CL | ModRM),
D(ModRM), I(DstReg | SrcMem | ModRM, em_imul),
/* 0xB0 - 0xB7 */
D2bv(DstMem | SrcReg | ModRM | Lock),
- D(DstReg | SrcMemFAddr | ModRM), D(DstMem | SrcReg | ModRM | BitOp | Lock),
- D(DstReg | SrcMemFAddr | ModRM), D(DstReg | SrcMemFAddr | ModRM),
+ I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg),
+ D(DstMem | SrcReg | ModRM | BitOp | Lock),
+ I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg),
+ I(DstReg | SrcMemFAddr | ModRM | Src2GS, em_lseg),
D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
/* 0xB8 - 0xBF */
N, N,
@@ -3309,13 +3343,13 @@ static int decode_imm(struct x86_emulate_ctxt *ctxt, struct operand *op,
/* NB. Immediates are sign-extended as necessary. */
switch (op->bytes) {
case 1:
- op->val = insn_fetch(s8, 1, ctxt->_eip);
+ op->val = insn_fetch(s8, ctxt);
break;
case 2:
- op->val = insn_fetch(s16, 2, ctxt->_eip);
+ op->val = insn_fetch(s16, ctxt);
break;
case 4:
- op->val = insn_fetch(s32, 4, ctxt->_eip);
+ op->val = insn_fetch(s32, ctxt);
break;
}
if (!sign_extension) {
@@ -3335,6 +3369,125 @@ done:
return rc;
}
+static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
+ unsigned d)
+{
+ int rc = X86EMUL_CONTINUE;
+
+ switch (d) {
+ case OpReg:
+ decode_register_operand(ctxt, op,
+ op == &ctxt->dst &&
+ ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
+ break;
+ case OpImmUByte:
+ rc = decode_imm(ctxt, op, 1, false);
+ break;
+ case OpMem:
+ ctxt->memop.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+ mem_common:
+ *op = ctxt->memop;
+ ctxt->memopp = op;
+ if ((ctxt->d & BitOp) && op == &ctxt->dst)
+ fetch_bit_operand(ctxt);
+ op->orig_val = op->val;
+ break;
+ case OpMem64:
+ ctxt->memop.bytes = 8;
+ goto mem_common;
+ case OpAcc:
+ op->type = OP_REG;
+ op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+ op->addr.reg = &ctxt->regs[VCPU_REGS_RAX];
+ fetch_register_operand(op);
+ op->orig_val = op->val;
+ break;
+ case OpDI:
+ op->type = OP_MEM;
+ op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+ op->addr.mem.ea =
+ register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
+ op->addr.mem.seg = VCPU_SREG_ES;
+ op->val = 0;
+ break;
+ case OpDX:
+ op->type = OP_REG;
+ op->bytes = 2;
+ op->addr.reg = &ctxt->regs[VCPU_REGS_RDX];
+ fetch_register_operand(op);
+ break;
+ case OpCL:
+ op->bytes = 1;
+ op->val = ctxt->regs[VCPU_REGS_RCX] & 0xff;
+ break;
+ case OpImmByte:
+ rc = decode_imm(ctxt, op, 1, true);
+ break;
+ case OpOne:
+ op->bytes = 1;
+ op->val = 1;
+ break;
+ case OpImm:
+ rc = decode_imm(ctxt, op, imm_size(ctxt), true);
+ break;
+ case OpMem16:
+ ctxt->memop.bytes = 2;
+ goto mem_common;
+ case OpMem32:
+ ctxt->memop.bytes = 4;
+ goto mem_common;
+ case OpImmU16:
+ rc = decode_imm(ctxt, op, 2, false);
+ break;
+ case OpImmU:
+ rc = decode_imm(ctxt, op, imm_size(ctxt), false);
+ break;
+ case OpSI:
+ op->type = OP_MEM;
+ op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+ op->addr.mem.ea =
+ register_address(ctxt, ctxt->regs[VCPU_REGS_RSI]);
+ op->addr.mem.seg = seg_override(ctxt);
+ op->val = 0;
+ break;
+ case OpImmFAddr:
+ op->type = OP_IMM;
+ op->addr.mem.ea = ctxt->_eip;
+ op->bytes = ctxt->op_bytes + 2;
+ insn_fetch_arr(op->valptr, op->bytes, ctxt);
+ break;
+ case OpMemFAddr:
+ ctxt->memop.bytes = ctxt->op_bytes + 2;
+ goto mem_common;
+ case OpES:
+ op->val = VCPU_SREG_ES;
+ break;
+ case OpCS:
+ op->val = VCPU_SREG_CS;
+ break;
+ case OpSS:
+ op->val = VCPU_SREG_SS;
+ break;
+ case OpDS:
+ op->val = VCPU_SREG_DS;
+ break;
+ case OpFS:
+ op->val = VCPU_SREG_FS;
+ break;
+ case OpGS:
+ op->val = VCPU_SREG_GS;
+ break;
+ case OpImplicit:
+ /* Special instructions do their own operand decoding. */
+ default:
+ op->type = OP_NONE; /* Disable writeback. */
+ break;
+ }
+
+done:
+ return rc;
+}
+
int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
{
int rc = X86EMUL_CONTINUE;
@@ -3342,8 +3495,9 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
bool op_prefix = false;
struct opcode opcode;
- struct operand memop = { .type = OP_NONE }, *memopp = NULL;
+ ctxt->memop.type = OP_NONE;
+ ctxt->memopp = NULL;
ctxt->_eip = ctxt->eip;
ctxt->fetch.start = ctxt->_eip;
ctxt->fetch.end = ctxt->fetch.start + insn_len;
@@ -3366,7 +3520,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
break;
#endif
default:
- return -1;
+ return EMULATION_FAILED;
}
ctxt->op_bytes = def_op_bytes;
@@ -3374,7 +3528,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
/* Legacy prefixes. */
for (;;) {
- switch (ctxt->b = insn_fetch(u8, 1, ctxt->_eip)) {
+ switch (ctxt->b = insn_fetch(u8, ctxt)) {
case 0x66: /* operand-size override */
op_prefix = true;
/* switch between 2/4 bytes */
@@ -3430,7 +3584,7 @@ done_prefixes:
/* Two-byte opcode? */
if (ctxt->b == 0x0f) {
ctxt->twobyte = 1;
- ctxt->b = insn_fetch(u8, 1, ctxt->_eip);
+ ctxt->b = insn_fetch(u8, ctxt);
opcode = twobyte_table[ctxt->b];
}
ctxt->d = opcode.flags;
@@ -3438,13 +3592,13 @@ done_prefixes:
while (ctxt->d & GroupMask) {
switch (ctxt->d & GroupMask) {
case Group:
- ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+ ctxt->modrm = insn_fetch(u8, ctxt);
--ctxt->_eip;
goffset = (ctxt->modrm >> 3) & 7;
opcode = opcode.u.group[goffset];
break;
case GroupDual:
- ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+ ctxt->modrm = insn_fetch(u8, ctxt);
--ctxt->_eip;
goffset = (ctxt->modrm >> 3) & 7;
if ((ctxt->modrm >> 6) == 3)
@@ -3458,7 +3612,7 @@ done_prefixes:
break;
case Prefix:
if (ctxt->rep_prefix && op_prefix)
- return X86EMUL_UNHANDLEABLE;
+ return EMULATION_FAILED;
simd_prefix = op_prefix ? 0x66 : ctxt->rep_prefix;
switch (simd_prefix) {
case 0x00: opcode = opcode.u.gprefix->pfx_no; break;
@@ -3468,10 +3622,10 @@ done_prefixes:
}
break;
default:
- return X86EMUL_UNHANDLEABLE;
+ return EMULATION_FAILED;
}
- ctxt->d &= ~GroupMask;
+ ctxt->d &= ~(u64)GroupMask;
ctxt->d |= opcode.flags;
}
@@ -3481,10 +3635,10 @@ done_prefixes:
/* Unrecognised? */
if (ctxt->d == 0 || (ctxt->d & Undefined))
- return -1;
+ return EMULATION_FAILED;
if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
- return -1;
+ return EMULATION_FAILED;
if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
ctxt->op_bytes = 8;
@@ -3501,96 +3655,27 @@ done_prefixes:
/* ModRM and SIB bytes. */
if (ctxt->d & ModRM) {
- rc = decode_modrm(ctxt, &memop);
+ rc = decode_modrm(ctxt, &ctxt->memop);
if (!ctxt->has_seg_override)
set_seg_override(ctxt, ctxt->modrm_seg);
} else if (ctxt->d & MemAbs)
- rc = decode_abs(ctxt, &memop);
+ rc = decode_abs(ctxt, &ctxt->memop);
if (rc != X86EMUL_CONTINUE)
goto done;
if (!ctxt->has_seg_override)
set_seg_override(ctxt, VCPU_SREG_DS);
- memop.addr.mem.seg = seg_override(ctxt);
+ ctxt->memop.addr.mem.seg = seg_override(ctxt);
- if (memop.type == OP_MEM && ctxt->ad_bytes != 8)
- memop.addr.mem.ea = (u32)memop.addr.mem.ea;
+ if (ctxt->memop.type == OP_MEM && ctxt->ad_bytes != 8)
+ ctxt->memop.addr.mem.ea = (u32)ctxt->memop.addr.mem.ea;
/*
* Decode and fetch the source operand: register, memory
* or immediate.
*/
- switch (ctxt->d & SrcMask) {
- case SrcNone:
- break;
- case SrcReg:
- decode_register_operand(ctxt, &ctxt->src, 0);
- break;
- case SrcMem16:
- memop.bytes = 2;
- goto srcmem_common;
- case SrcMem32:
- memop.bytes = 4;
- goto srcmem_common;
- case SrcMem:
- memop.bytes = (ctxt->d & ByteOp) ? 1 :
- ctxt->op_bytes;
- srcmem_common:
- ctxt->src = memop;
- memopp = &ctxt->src;
- break;
- case SrcImmU16:
- rc = decode_imm(ctxt, &ctxt->src, 2, false);
- break;
- case SrcImm:
- rc = decode_imm(ctxt, &ctxt->src, imm_size(ctxt), true);
- break;
- case SrcImmU:
- rc = decode_imm(ctxt, &ctxt->src, imm_size(ctxt), false);
- break;
- case SrcImmByte:
- rc = decode_imm(ctxt, &ctxt->src, 1, true);
- break;
- case SrcImmUByte:
- rc = decode_imm(ctxt, &ctxt->src, 1, false);
- break;
- case SrcAcc:
- ctxt->src.type = OP_REG;
- ctxt->src.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
- ctxt->src.addr.reg = &ctxt->regs[VCPU_REGS_RAX];
- fetch_register_operand(&ctxt->src);
- break;
- case SrcOne:
- ctxt->src.bytes = 1;
- ctxt->src.val = 1;
- break;
- case SrcSI:
- ctxt->src.type = OP_MEM;
- ctxt->src.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
- ctxt->src.addr.mem.ea =
- register_address(ctxt, ctxt->regs[VCPU_REGS_RSI]);
- ctxt->src.addr.mem.seg = seg_override(ctxt);
- ctxt->src.val = 0;
- break;
- case SrcImmFAddr:
- ctxt->src.type = OP_IMM;
- ctxt->src.addr.mem.ea = ctxt->_eip;
- ctxt->src.bytes = ctxt->op_bytes + 2;
- insn_fetch_arr(ctxt->src.valptr, ctxt->src.bytes, ctxt->_eip);
- break;
- case SrcMemFAddr:
- memop.bytes = ctxt->op_bytes + 2;
- goto srcmem_common;
- break;
- case SrcDX:
- ctxt->src.type = OP_REG;
- ctxt->src.bytes = 2;
- ctxt->src.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
- fetch_register_operand(&ctxt->src);
- break;
- }
-
+ rc = decode_operand(ctxt, &ctxt->src, (ctxt->d >> SrcShift) & OpMask);
if (rc != X86EMUL_CONTINUE)
goto done;
@@ -3598,85 +3683,18 @@ done_prefixes:
* Decode and fetch the second source operand: register, memory
* or immediate.
*/
- switch (ctxt->d & Src2Mask) {
- case Src2None:
- break;
- case Src2CL:
- ctxt->src2.bytes = 1;
- ctxt->src2.val = ctxt->regs[VCPU_REGS_RCX] & 0xff;
- break;
- case Src2ImmByte:
- rc = decode_imm(ctxt, &ctxt->src2, 1, true);
- break;
- case Src2One:
- ctxt->src2.bytes = 1;
- ctxt->src2.val = 1;
- break;
- case Src2Imm:
- rc = decode_imm(ctxt, &ctxt->src2, imm_size(ctxt), true);
- break;
- }
-
+ rc = decode_operand(ctxt, &ctxt->src2, (ctxt->d >> Src2Shift) & OpMask);
if (rc != X86EMUL_CONTINUE)
goto done;
/* Decode and fetch the destination operand: register or memory. */
- switch (ctxt->d & DstMask) {
- case DstReg:
- decode_register_operand(ctxt, &ctxt->dst,
- ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
- break;
- case DstImmUByte:
- ctxt->dst.type = OP_IMM;
- ctxt->dst.addr.mem.ea = ctxt->_eip;
- ctxt->dst.bytes = 1;
- ctxt->dst.val = insn_fetch(u8, 1, ctxt->_eip);
- break;
- case DstMem:
- case DstMem64:
- ctxt->dst = memop;
- memopp = &ctxt->dst;
- if ((ctxt->d & DstMask) == DstMem64)
- ctxt->dst.bytes = 8;
- else
- ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
- if (ctxt->d & BitOp)
- fetch_bit_operand(ctxt);
- ctxt->dst.orig_val = ctxt->dst.val;
- break;
- case DstAcc:
- ctxt->dst.type = OP_REG;
- ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
- ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RAX];
- fetch_register_operand(&ctxt->dst);
- ctxt->dst.orig_val = ctxt->dst.val;
- break;
- case DstDI:
- ctxt->dst.type = OP_MEM;
- ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
- ctxt->dst.addr.mem.ea =
- register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
- ctxt->dst.addr.mem.seg = VCPU_SREG_ES;
- ctxt->dst.val = 0;
- break;
- case DstDX:
- ctxt->dst.type = OP_REG;
- ctxt->dst.bytes = 2;
- ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
- fetch_register_operand(&ctxt->dst);
- break;
- case ImplicitOps:
- /* Special instructions do their own operand decoding. */
- default:
- ctxt->dst.type = OP_NONE; /* Disable writeback. */
- break;
- }
+ rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
done:
- if (memopp && memopp->type == OP_MEM && ctxt->rip_relative)
- memopp->addr.mem.ea += ctxt->_eip;
+ if (ctxt->memopp && ctxt->memopp->type == OP_MEM && ctxt->rip_relative)
+ ctxt->memopp->addr.mem.ea += ctxt->_eip;
- return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
+ return (rc != X86EMUL_CONTINUE) ? EMULATION_FAILED : EMULATION_OK;
}
static bool string_insn_completed(struct x86_emulate_ctxt *ctxt)
@@ -3825,32 +3843,11 @@ special_insn:
goto twobyte_insn;
switch (ctxt->b) {
- case 0x06: /* push es */
- rc = emulate_push_sreg(ctxt, VCPU_SREG_ES);
- break;
- case 0x07: /* pop es */
- rc = emulate_pop_sreg(ctxt, VCPU_SREG_ES);
- break;
- case 0x0e: /* push cs */
- rc = emulate_push_sreg(ctxt, VCPU_SREG_CS);
- break;
- case 0x16: /* push ss */
- rc = emulate_push_sreg(ctxt, VCPU_SREG_SS);
- break;
- case 0x17: /* pop ss */
- rc = emulate_pop_sreg(ctxt, VCPU_SREG_SS);
- break;
- case 0x1e: /* push ds */
- rc = emulate_push_sreg(ctxt, VCPU_SREG_DS);
- break;
- case 0x1f: /* pop ds */
- rc = emulate_pop_sreg(ctxt, VCPU_SREG_DS);
- break;
case 0x40 ... 0x47: /* inc r16/r32 */
- emulate_1op("inc", ctxt->dst, ctxt->eflags);
+ emulate_1op(ctxt, "inc");
break;
case 0x48 ... 0x4f: /* dec r16/r32 */
- emulate_1op("dec", ctxt->dst, ctxt->eflags);
+ emulate_1op(ctxt, "dec");
break;
case 0x63: /* movsxd */
if (ctxt->mode != X86EMUL_MODE_PROT64)
@@ -3891,12 +3888,6 @@ special_insn:
case 0xc0 ... 0xc1:
rc = em_grp2(ctxt);
break;
- case 0xc4: /* les */
- rc = emulate_load_segment(ctxt, VCPU_SREG_ES);
- break;
- case 0xc5: /* lds */
- rc = emulate_load_segment(ctxt, VCPU_SREG_DS);
- break;
case 0xcc: /* int3 */
rc = emulate_int(ctxt, 3);
break;
@@ -3953,9 +3944,6 @@ special_insn:
/* complement carry flag from eflags reg */
ctxt->eflags ^= EFLG_CF;
break;
- case 0xf6 ... 0xf7: /* Grp3 */
- rc = em_grp3(ctxt);
- break;
case 0xf8: /* clc */
ctxt->eflags &= ~EFLG_CF;
break;
@@ -4103,36 +4091,24 @@ twobyte_insn:
case 0x90 ... 0x9f: /* setcc r/m8 */
ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
break;
- case 0xa0: /* push fs */
- rc = emulate_push_sreg(ctxt, VCPU_SREG_FS);
- break;
- case 0xa1: /* pop fs */
- rc = emulate_pop_sreg(ctxt, VCPU_SREG_FS);
- break;
case 0xa3:
bt: /* bt */
ctxt->dst.type = OP_NONE;
/* only subword offset */
ctxt->src.val &= (ctxt->dst.bytes << 3) - 1;
- emulate_2op_SrcV_nobyte("bt", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV_nobyte(ctxt, "bt");
break;
case 0xa4: /* shld imm8, r, r/m */
case 0xa5: /* shld cl, r, r/m */
- emulate_2op_cl("shld", ctxt->src2, ctxt->src, ctxt->dst, ctxt->eflags);
- break;
- case 0xa8: /* push gs */
- rc = emulate_push_sreg(ctxt, VCPU_SREG_GS);
- break;
- case 0xa9: /* pop gs */
- rc = emulate_pop_sreg(ctxt, VCPU_SREG_GS);
+ emulate_2op_cl(ctxt, "shld");
break;
case 0xab:
bts: /* bts */
- emulate_2op_SrcV_nobyte("bts", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV_nobyte(ctxt, "bts");
break;
case 0xac: /* shrd imm8, r, r/m */
case 0xad: /* shrd cl, r, r/m */
- emulate_2op_cl("shrd", ctxt->src2, ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_cl(ctxt, "shrd");
break;
case 0xae: /* clflush */
break;
@@ -4143,7 +4119,7 @@ twobyte_insn:
*/
ctxt->src.orig_val = ctxt->src.val;
ctxt->src.val = ctxt->regs[VCPU_REGS_RAX];
- emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "cmp");
if (ctxt->eflags & EFLG_ZF) {
/* Success: write back to memory. */
ctxt->dst.val = ctxt->src.orig_val;
@@ -4153,18 +4129,9 @@ twobyte_insn:
ctxt->dst.addr.reg = (unsigned long *)&ctxt->regs[VCPU_REGS_RAX];
}
break;
- case 0xb2: /* lss */
- rc = emulate_load_segment(ctxt, VCPU_SREG_SS);
- break;
case 0xb3:
btr: /* btr */
- emulate_2op_SrcV_nobyte("btr", ctxt->src, ctxt->dst, ctxt->eflags);
- break;
- case 0xb4: /* lfs */
- rc = emulate_load_segment(ctxt, VCPU_SREG_FS);
- break;
- case 0xb5: /* lgs */
- rc = emulate_load_segment(ctxt, VCPU_SREG_GS);
+ emulate_2op_SrcV_nobyte(ctxt, "btr");
break;
case 0xb6 ... 0xb7: /* movzx */
ctxt->dst.bytes = ctxt->op_bytes;
@@ -4185,7 +4152,7 @@ twobyte_insn:
break;
case 0xbb:
btc: /* btc */
- emulate_2op_SrcV_nobyte("btc", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV_nobyte(ctxt, "btc");
break;
case 0xbc: { /* bsf */
u8 zf;
@@ -4217,7 +4184,7 @@ twobyte_insn:
(s16) ctxt->src.val;
break;
case 0xc0 ... 0xc1: /* xadd */
- emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags);
+ emulate_2op_SrcV(ctxt, "add");
/* Write back the register source. */
ctxt->src.val = ctxt->dst.orig_val;
write_register_operand(&ctxt->src);
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index efad72385058..76e3f1cd0369 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -713,14 +713,16 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
kvm_iodevice_init(&pit->dev, &pit_dev_ops);
- ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &pit->dev);
+ ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, KVM_PIT_BASE_ADDRESS,
+ KVM_PIT_MEM_LENGTH, &pit->dev);
if (ret < 0)
goto fail;
if (flags & KVM_PIT_SPEAKER_DUMMY) {
kvm_iodevice_init(&pit->speaker_dev, &speaker_dev_ops);
ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS,
- &pit->speaker_dev);
+ KVM_SPEAKER_BASE_ADDRESS, 4,
+ &pit->speaker_dev);
if (ret < 0)
goto fail_unregister;
}
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 19fe855e7953..cac4746d7ffb 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -34,6 +34,9 @@
#include <linux/kvm_host.h>
#include "trace.h"
+#define pr_pic_unimpl(fmt, ...) \
+ pr_err_ratelimited("kvm: pic: " fmt, ## __VA_ARGS__)
+
static void pic_irq_request(struct kvm *kvm, int level);
static void pic_lock(struct kvm_pic *s)
@@ -306,10 +309,10 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
}
s->init_state = 1;
if (val & 0x02)
- printk(KERN_ERR "single mode not supported");
+ pr_pic_unimpl("single mode not supported");
if (val & 0x08)
- printk(KERN_ERR
- "level sensitive irq not supported");
+ pr_pic_unimpl(
+ "level sensitive irq not supported");
} else if (val & 0x08) {
if (val & 0x04)
s->poll = 1;
@@ -459,22 +462,15 @@ static int picdev_in_range(gpa_t addr)
}
}
-static inline struct kvm_pic *to_pic(struct kvm_io_device *dev)
-{
- return container_of(dev, struct kvm_pic, dev);
-}
-
-static int picdev_write(struct kvm_io_device *this,
+static int picdev_write(struct kvm_pic *s,
gpa_t addr, int len, const void *val)
{
- struct kvm_pic *s = to_pic(this);
unsigned char data = *(unsigned char *)val;
if (!picdev_in_range(addr))
return -EOPNOTSUPP;
if (len != 1) {
- if (printk_ratelimit())
- printk(KERN_ERR "PIC: non byte write\n");
+ pr_pic_unimpl("non byte write\n");
return 0;
}
pic_lock(s);
@@ -494,17 +490,15 @@ static int picdev_write(struct kvm_io_device *this,
return 0;
}
-static int picdev_read(struct kvm_io_device *this,
+static int picdev_read(struct kvm_pic *s,
gpa_t addr, int len, void *val)
{
- struct kvm_pic *s = to_pic(this);
unsigned char data = 0;
if (!picdev_in_range(addr))
return -EOPNOTSUPP;
if (len != 1) {
- if (printk_ratelimit())
- printk(KERN_ERR "PIC: non byte read\n");
+ pr_pic_unimpl("non byte read\n");
return 0;
}
pic_lock(s);
@@ -525,6 +519,48 @@ static int picdev_read(struct kvm_io_device *this,
return 0;
}
+static int picdev_master_write(struct kvm_io_device *dev,
+ gpa_t addr, int len, const void *val)
+{
+ return picdev_write(container_of(dev, struct kvm_pic, dev_master),
+ addr, len, val);
+}
+
+static int picdev_master_read(struct kvm_io_device *dev,
+ gpa_t addr, int len, void *val)
+{
+ return picdev_read(container_of(dev, struct kvm_pic, dev_master),
+ addr, len, val);
+}
+
+static int picdev_slave_write(struct kvm_io_device *dev,
+ gpa_t addr, int len, const void *val)
+{
+ return picdev_write(container_of(dev, struct kvm_pic, dev_slave),
+ addr, len, val);
+}
+
+static int picdev_slave_read(struct kvm_io_device *dev,
+ gpa_t addr, int len, void *val)
+{
+ return picdev_read(container_of(dev, struct kvm_pic, dev_slave),
+ addr, len, val);
+}
+
+static int picdev_eclr_write(struct kvm_io_device *dev,
+ gpa_t addr, int len, const void *val)
+{
+ return picdev_write(container_of(dev, struct kvm_pic, dev_eclr),
+ addr, len, val);
+}
+
+static int picdev_eclr_read(struct kvm_io_device *dev,
+ gpa_t addr, int len, void *val)
+{
+ return picdev_read(container_of(dev, struct kvm_pic, dev_eclr),
+ addr, len, val);
+}
+
/*
* callback when PIC0 irq status changed
*/
@@ -537,9 +573,19 @@ static void pic_irq_request(struct kvm *kvm, int level)
s->output = level;
}
-static const struct kvm_io_device_ops picdev_ops = {
- .read = picdev_read,
- .write = picdev_write,
+static const struct kvm_io_device_ops picdev_master_ops = {
+ .read = picdev_master_read,
+ .write = picdev_master_write,
+};
+
+static const struct kvm_io_device_ops picdev_slave_ops = {
+ .read = picdev_slave_read,
+ .write = picdev_slave_write,
+};
+
+static const struct kvm_io_device_ops picdev_eclr_ops = {
+ .read = picdev_eclr_read,
+ .write = picdev_eclr_write,
};
struct kvm_pic *kvm_create_pic(struct kvm *kvm)
@@ -560,16 +606,39 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
/*
* Initialize PIO device
*/
- kvm_iodevice_init(&s->dev, &picdev_ops);
+ kvm_iodevice_init(&s->dev_master, &picdev_master_ops);
+ kvm_iodevice_init(&s->dev_slave, &picdev_slave_ops);
+ kvm_iodevice_init(&s->dev_eclr, &picdev_eclr_ops);
mutex_lock(&kvm->slots_lock);
- ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &s->dev);
+ ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, 0x20, 2,
+ &s->dev_master);
+ if (ret < 0)
+ goto fail_unlock;
+
+ ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, 0xa0, 2, &s->dev_slave);
+ if (ret < 0)
+ goto fail_unreg_2;
+
+ ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, 0x4d0, 2, &s->dev_eclr);
+ if (ret < 0)
+ goto fail_unreg_1;
+
mutex_unlock(&kvm->slots_lock);
- if (ret < 0) {
- kfree(s);
- return NULL;
- }
return s;
+
+fail_unreg_1:
+ kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &s->dev_slave);
+
+fail_unreg_2:
+ kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &s->dev_master);
+
+fail_unlock:
+ mutex_unlock(&kvm->slots_lock);
+
+ kfree(s);
+
+ return NULL;
}
void kvm_destroy_pic(struct kvm *kvm)
@@ -577,7 +646,9 @@ void kvm_destroy_pic(struct kvm *kvm)
struct kvm_pic *vpic = kvm->arch.vpic;
if (vpic) {
- kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev);
+ kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_master);
+ kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_slave);
+ kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_eclr);
kvm->arch.vpic = NULL;
kfree(vpic);
}
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 53e2d084bffb..2086f2bfba33 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -66,7 +66,9 @@ struct kvm_pic {
struct kvm *kvm;
struct kvm_kpic_state pics[2]; /* 0 is master pic, 1 is slave pic */
int output; /* intr from master PIC */
- struct kvm_io_device dev;
+ struct kvm_io_device dev_master;
+ struct kvm_io_device dev_slave;
+ struct kvm_io_device dev_eclr;
void (*ack_notifier)(void *opaque, int irq);
unsigned long irq_states[16];
};
diff --git a/arch/x86/kvm/kvm_cache_regs.h b/arch/x86/kvm/kvm_cache_regs.h
index 3377d53fcd36..544076c4f44b 100644
--- a/arch/x86/kvm/kvm_cache_regs.h
+++ b/arch/x86/kvm/kvm_cache_regs.h
@@ -45,13 +45,6 @@ static inline u64 kvm_pdptr_read(struct kvm_vcpu *vcpu, int index)
return vcpu->arch.walk_mmu->pdptrs[index];
}
-static inline u64 kvm_pdptr_read_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, int index)
-{
- load_pdptrs(vcpu, mmu, mmu->get_cr3(vcpu));
-
- return mmu->pdptrs[index];
-}
-
static inline ulong kvm_read_cr0_bits(struct kvm_vcpu *vcpu, ulong mask)
{
ulong tmask = mask & KVM_POSSIBLE_CR0_GUEST_BITS;
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
index 64bc6ea78d90..497dbaa366d4 100644
--- a/arch/x86/kvm/kvm_timer.h
+++ b/arch/x86/kvm/kvm_timer.h
@@ -2,6 +2,8 @@
struct kvm_timer {
struct hrtimer timer;
s64 period; /* unit: ns */
+ u32 timer_mode_mask;
+ u64 tscdeadline;
atomic_t pending; /* accumulated triggered timers */
bool reinject;
struct kvm_timer_ops *t_ops;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 57dcbd4308fa..54abb40199d6 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -68,6 +68,9 @@
#define VEC_POS(v) ((v) & (32 - 1))
#define REG_POS(v) (((v) >> 5) << 4)
+static unsigned int min_timer_period_us = 500;
+module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR);
+
static inline u32 apic_get_reg(struct kvm_lapic *apic, int reg_off)
{
return *((u32 *) (apic->regs + reg_off));
@@ -135,9 +138,23 @@ static inline int apic_lvt_vector(struct kvm_lapic *apic, int lvt_type)
return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
}
+static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
+{
+ return ((apic_get_reg(apic, APIC_LVTT) &
+ apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT);
+}
+
static inline int apic_lvtt_period(struct kvm_lapic *apic)
{
- return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
+ return ((apic_get_reg(apic, APIC_LVTT) &
+ apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC);
+}
+
+static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
+{
+ return ((apic_get_reg(apic, APIC_LVTT) &
+ apic->lapic_timer.timer_mode_mask) ==
+ APIC_LVT_TIMER_TSCDEADLINE);
}
static inline int apic_lvt_nmi_mode(u32 lvt_val)
@@ -166,7 +183,7 @@ static inline int apic_x2apic_mode(struct kvm_lapic *apic)
}
static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
- LVT_MASK | APIC_LVT_TIMER_PERIODIC, /* LVTT */
+ LVT_MASK , /* part LVTT mask, timer mode mask added at runtime */
LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */
LVT_MASK | APIC_MODE_MASK, /* LVTPC */
LINT_MASK, LINT_MASK, /* LVT0-1 */
@@ -316,8 +333,8 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
result = 1;
break;
default:
- printk(KERN_WARNING "Bad DFR vcpu %d: %08x\n",
- apic->vcpu->vcpu_id, apic_get_reg(apic, APIC_DFR));
+ apic_debug("Bad DFR vcpu %d: %08x\n",
+ apic->vcpu->vcpu_id, apic_get_reg(apic, APIC_DFR));
break;
}
@@ -354,8 +371,8 @@ int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
result = (target != source);
break;
default:
- printk(KERN_WARNING "Bad dest shorthand value %x\n",
- short_hand);
+ apic_debug("kvm: apic: Bad dest shorthand value %x\n",
+ short_hand);
break;
}
@@ -401,11 +418,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
break;
case APIC_DM_REMRD:
- printk(KERN_DEBUG "Ignoring delivery mode 3\n");
+ apic_debug("Ignoring delivery mode 3\n");
break;
case APIC_DM_SMI:
- printk(KERN_DEBUG "Ignoring guest SMI\n");
+ apic_debug("Ignoring guest SMI\n");
break;
case APIC_DM_NMI:
@@ -565,11 +582,13 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
val = kvm_apic_id(apic) << 24;
break;
case APIC_ARBPRI:
- printk(KERN_WARNING "Access APIC ARBPRI register "
- "which is for P6\n");
+ apic_debug("Access APIC ARBPRI register which is for P6\n");
break;
case APIC_TMCCT: /* Timer CCR */
+ if (apic_lvtt_tscdeadline(apic))
+ return 0;
+
val = apic_get_tmcct(apic);
break;
@@ -664,29 +683,40 @@ static void update_divide_count(struct kvm_lapic *apic)
static void start_apic_timer(struct kvm_lapic *apic)
{
- ktime_t now = apic->lapic_timer.timer.base->get_time();
-
- apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) *
- APIC_BUS_CYCLE_NS * apic->divide_count;
+ ktime_t now;
atomic_set(&apic->lapic_timer.pending, 0);
- if (!apic->lapic_timer.period)
- return;
- /*
- * Do not allow the guest to program periodic timers with small
- * interval, since the hrtimers are not throttled by the host
- * scheduler.
- */
- if (apic_lvtt_period(apic)) {
- if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
- apic->lapic_timer.period = NSEC_PER_MSEC/2;
- }
+ if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
+ /* lapic timer in oneshot or peroidic mode */
+ now = apic->lapic_timer.timer.base->get_time();
+ apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT)
+ * APIC_BUS_CYCLE_NS * apic->divide_count;
+
+ if (!apic->lapic_timer.period)
+ return;
+ /*
+ * Do not allow the guest to program periodic timers with small
+ * interval, since the hrtimers are not throttled by the host
+ * scheduler.
+ */
+ if (apic_lvtt_period(apic)) {
+ s64 min_period = min_timer_period_us * 1000LL;
+
+ if (apic->lapic_timer.period < min_period) {
+ pr_info_ratelimited(
+ "kvm: vcpu %i: requested %lld ns "
+ "lapic timer period limited to %lld ns\n",
+ apic->vcpu->vcpu_id,
+ apic->lapic_timer.period, min_period);
+ apic->lapic_timer.period = min_period;
+ }
+ }
- hrtimer_start(&apic->lapic_timer.timer,
- ktime_add_ns(now, apic->lapic_timer.period),
- HRTIMER_MODE_ABS);
+ hrtimer_start(&apic->lapic_timer.timer,
+ ktime_add_ns(now, apic->lapic_timer.period),
+ HRTIMER_MODE_ABS);
- apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+ apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
PRIx64 ", "
"timer initial count 0x%x, period %lldns, "
"expire @ 0x%016" PRIx64 ".\n", __func__,
@@ -695,6 +725,30 @@ static void start_apic_timer(struct kvm_lapic *apic)
apic->lapic_timer.period,
ktime_to_ns(ktime_add_ns(now,
apic->lapic_timer.period)));
+ } else if (apic_lvtt_tscdeadline(apic)) {
+ /* lapic timer in tsc deadline mode */
+ u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
+ u64 ns = 0;
+ struct kvm_vcpu *vcpu = apic->vcpu;
+ unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+ unsigned long flags;
+
+ if (unlikely(!tscdeadline || !this_tsc_khz))
+ return;
+
+ local_irq_save(flags);
+
+ now = apic->lapic_timer.timer.base->get_time();
+ guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+ if (likely(tscdeadline > guest_tsc)) {
+ ns = (tscdeadline - guest_tsc) * 1000000ULL;
+ do_div(ns, this_tsc_khz);
+ }
+ hrtimer_start(&apic->lapic_timer.timer,
+ ktime_add_ns(now, ns), HRTIMER_MODE_ABS);
+
+ local_irq_restore(flags);
+ }
}
static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -782,7 +836,6 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
case APIC_LVT0:
apic_manage_nmi_watchdog(apic, val);
- case APIC_LVTT:
case APIC_LVTTHMR:
case APIC_LVTPC:
case APIC_LVT1:
@@ -796,7 +849,22 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
break;
+ case APIC_LVTT:
+ if ((apic_get_reg(apic, APIC_LVTT) &
+ apic->lapic_timer.timer_mode_mask) !=
+ (val & apic->lapic_timer.timer_mode_mask))
+ hrtimer_cancel(&apic->lapic_timer.timer);
+
+ if (!apic_sw_enabled(apic))
+ val |= APIC_LVT_MASKED;
+ val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
+ apic_set_reg(apic, APIC_LVTT, val);
+ break;
+
case APIC_TMICT:
+ if (apic_lvtt_tscdeadline(apic))
+ break;
+
hrtimer_cancel(&apic->lapic_timer.timer);
apic_set_reg(apic, APIC_TMICT, val);
start_apic_timer(apic);
@@ -804,14 +872,14 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
case APIC_TDCR:
if (val & 4)
- printk(KERN_ERR "KVM_WRITE:TDCR %x\n", val);
+ apic_debug("KVM_WRITE:TDCR %x\n", val);
apic_set_reg(apic, APIC_TDCR, val);
update_divide_count(apic);
break;
case APIC_ESR:
if (apic_x2apic_mode(apic) && val != 0) {
- printk(KERN_ERR "KVM_WRITE:ESR not zero %x\n", val);
+ apic_debug("KVM_WRITE:ESR not zero %x\n", val);
ret = 1;
}
break;
@@ -864,6 +932,15 @@ static int apic_mmio_write(struct kvm_io_device *this,
return 0;
}
+void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu)
+{
+ struct kvm_lapic *apic = vcpu->arch.apic;
+
+ if (apic)
+ apic_reg_write(vcpu->arch.apic, APIC_EOI, 0);
+}
+EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
+
void kvm_free_lapic(struct kvm_vcpu *vcpu)
{
if (!vcpu->arch.apic)
@@ -883,6 +960,32 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
*----------------------------------------------------------------------
*/
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
+{
+ struct kvm_lapic *apic = vcpu->arch.apic;
+ if (!apic)
+ return 0;
+
+ if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+ return 0;
+
+ return apic->lapic_timer.tscdeadline;
+}
+
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
+{
+ struct kvm_lapic *apic = vcpu->arch.apic;
+ if (!apic)
+ return;
+
+ if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+ return;
+
+ hrtimer_cancel(&apic->lapic_timer.timer);
+ apic->lapic_timer.tscdeadline = data;
+ start_apic_timer(apic);
+}
+
void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
{
struct kvm_lapic *apic = vcpu->arch.apic;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 52c9e6b9e725..138e8cc6fea6 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -26,6 +26,7 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu);
void kvm_lapic_reset(struct kvm_vcpu *vcpu);
u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
+void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu);
void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
void kvm_apic_set_version(struct kvm_vcpu *vcpu);
@@ -41,6 +42,9 @@ int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
bool kvm_apic_present(struct kvm_vcpu *vcpu);
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
+
void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 8e8da7960dbe..f1b36cf3e3d0 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2770,7 +2770,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
ASSERT(!VALID_PAGE(root));
if (vcpu->arch.mmu.root_level == PT32E_ROOT_LEVEL) {
- pdptr = kvm_pdptr_read_mmu(vcpu, &vcpu->arch.mmu, i);
+ pdptr = vcpu->arch.mmu.get_pdptr(vcpu, i);
if (!is_present_gpte(pdptr)) {
vcpu->arch.mmu.pae_root[i] = 0;
continue;
@@ -3318,6 +3318,7 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
context->direct_map = true;
context->set_cr3 = kvm_x86_ops->set_tdp_cr3;
context->get_cr3 = get_cr3;
+ context->get_pdptr = kvm_pdptr_read;
context->inject_page_fault = kvm_inject_page_fault;
context->nx = is_nx(vcpu);
@@ -3376,6 +3377,7 @@ static int init_kvm_softmmu(struct kvm_vcpu *vcpu)
vcpu->arch.walk_mmu->set_cr3 = kvm_x86_ops->set_cr3;
vcpu->arch.walk_mmu->get_cr3 = get_cr3;
+ vcpu->arch.walk_mmu->get_pdptr = kvm_pdptr_read;
vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault;
return r;
@@ -3386,6 +3388,7 @@ static int init_kvm_nested_mmu(struct kvm_vcpu *vcpu)
struct kvm_mmu *g_context = &vcpu->arch.nested_mmu;
g_context->get_cr3 = get_cr3;
+ g_context->get_pdptr = kvm_pdptr_read;
g_context->inject_page_fault = kvm_inject_page_fault;
/*
diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c
index 2460a265be23..746ec259d024 100644
--- a/arch/x86/kvm/mmu_audit.c
+++ b/arch/x86/kvm/mmu_audit.c
@@ -121,16 +121,16 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level)
static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)
{
+ static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10);
unsigned long *rmapp;
struct kvm_mmu_page *rev_sp;
gfn_t gfn;
-
rev_sp = page_header(__pa(sptep));
gfn = kvm_mmu_page_get_gfn(rev_sp, sptep - rev_sp->spt);
if (!gfn_to_memslot(kvm, gfn)) {
- if (!printk_ratelimit())
+ if (!__ratelimit(&ratelimit_state))
return;
audit_printk(kvm, "no memslot for gfn %llx\n", gfn);
audit_printk(kvm, "index %ld of sp (gfn=%llx)\n",
@@ -141,7 +141,7 @@ static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)
rmapp = gfn_to_rmap(kvm, gfn, rev_sp->role.level);
if (!*rmapp) {
- if (!printk_ratelimit())
+ if (!__ratelimit(&ratelimit_state))
return;
audit_printk(kvm, "no rmap for writable spte %llx\n",
*sptep);
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 507e2b844cfa..92994100638b 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -147,7 +147,7 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
gfn_t table_gfn;
unsigned index, pt_access, uninitialized_var(pte_access);
gpa_t pte_gpa;
- bool eperm;
+ bool eperm, last_gpte;
int offset;
const int write_fault = access & PFERR_WRITE_MASK;
const int user_fault = access & PFERR_USER_MASK;
@@ -163,7 +163,7 @@ retry_walk:
#if PTTYPE == 64
if (walker->level == PT32E_ROOT_LEVEL) {
- pte = kvm_pdptr_read_mmu(vcpu, mmu, (addr >> 30) & 3);
+ pte = mmu->get_pdptr(vcpu, (addr >> 30) & 3);
trace_kvm_mmu_paging_element(pte, walker->level);
if (!is_present_gpte(pte))
goto error;
@@ -221,6 +221,17 @@ retry_walk:
eperm = true;
#endif
+ last_gpte = FNAME(is_last_gpte)(walker, vcpu, mmu, pte);
+ if (last_gpte) {
+ pte_access = pt_access &
+ FNAME(gpte_access)(vcpu, pte, true);
+ /* check if the kernel is fetching from user page */
+ if (unlikely(pte_access & PT_USER_MASK) &&
+ kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))
+ if (fetch_fault && !user_fault)
+ eperm = true;
+ }
+
if (!eperm && unlikely(!(pte & PT_ACCESSED_MASK))) {
int ret;
trace_kvm_mmu_set_accessed_bit(table_gfn, index,
@@ -238,18 +249,12 @@ retry_walk:
walker->ptes[walker->level - 1] = pte;
- if (FNAME(is_last_gpte)(walker, vcpu, mmu, pte)) {
+ if (last_gpte) {
int lvl = walker->level;
gpa_t real_gpa;
gfn_t gfn;
u32 ac;
- /* check if the kernel is fetching from user page */
- if (unlikely(pte_access & PT_USER_MASK) &&
- kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))
- if (fetch_fault && !user_fault)
- eperm = true;
-
gfn = gpte_to_gfn_lvl(pte, lvl);
gfn += (addr & PT_LVL_OFFSET_MASK(lvl)) >> PAGE_SHIFT;
@@ -295,7 +300,6 @@ retry_walk:
walker->ptes[walker->level - 1] = pte;
}
- pte_access = pt_access & FNAME(gpte_access)(vcpu, pte, true);
walker->pt_access = pt_access;
walker->pte_access = pte_access;
pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 475d1c948501..e32243eac2f4 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1084,7 +1084,6 @@ static void init_vmcb(struct vcpu_svm *svm)
if (npt_enabled) {
/* Setup VMCB for Nested Paging */
control->nested_ctl = 1;
- clr_intercept(svm, INTERCEPT_TASK_SWITCH);
clr_intercept(svm, INTERCEPT_INVLPG);
clr_exception_intercept(svm, PF_VECTOR);
clr_cr_intercept(svm, INTERCEPT_CR3_READ);
@@ -1844,6 +1843,20 @@ static unsigned long nested_svm_get_tdp_cr3(struct kvm_vcpu *vcpu)
return svm->nested.nested_cr3;
}
+static u64 nested_svm_get_tdp_pdptr(struct kvm_vcpu *vcpu, int index)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ u64 cr3 = svm->nested.nested_cr3;
+ u64 pdpte;
+ int ret;
+
+ ret = kvm_read_guest_page(vcpu->kvm, gpa_to_gfn(cr3), &pdpte,
+ offset_in_page(cr3) + index * 8, 8);
+ if (ret)
+ return 0;
+ return pdpte;
+}
+
static void nested_svm_set_tdp_cr3(struct kvm_vcpu *vcpu,
unsigned long root)
{
@@ -1875,6 +1888,7 @@ static int nested_svm_init_mmu_context(struct kvm_vcpu *vcpu)
vcpu->arch.mmu.set_cr3 = nested_svm_set_tdp_cr3;
vcpu->arch.mmu.get_cr3 = nested_svm_get_tdp_cr3;
+ vcpu->arch.mmu.get_pdptr = nested_svm_get_tdp_pdptr;
vcpu->arch.mmu.inject_page_fault = nested_svm_inject_npf_exit;
vcpu->arch.mmu.shadow_root_level = get_npt_level();
vcpu->arch.walk_mmu = &vcpu->arch.nested_mmu;
@@ -2182,7 +2196,8 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
vmcb->control.exit_info_1,
vmcb->control.exit_info_2,
vmcb->control.exit_int_info,
- vmcb->control.exit_int_info_err);
+ vmcb->control.exit_int_info_err,
+ KVM_ISA_SVM);
nested_vmcb = nested_svm_map(svm, svm->nested.vmcb, &page);
if (!nested_vmcb)
@@ -2894,15 +2909,20 @@ static int cr8_write_interception(struct vcpu_svm *svm)
return 0;
}
+u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu)
+{
+ struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu));
+ return vmcb->control.tsc_offset +
+ svm_scale_tsc(vcpu, native_read_tsc());
+}
+
static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
{
struct vcpu_svm *svm = to_svm(vcpu);
switch (ecx) {
case MSR_IA32_TSC: {
- struct vmcb *vmcb = get_host_vmcb(svm);
-
- *data = vmcb->control.tsc_offset +
+ *data = svm->vmcb->control.tsc_offset +
svm_scale_tsc(vcpu, native_read_tsc());
break;
@@ -3314,8 +3334,6 @@ static int handle_exit(struct kvm_vcpu *vcpu)
struct kvm_run *kvm_run = vcpu->run;
u32 exit_code = svm->vmcb->control.exit_code;
- trace_kvm_exit(exit_code, vcpu, KVM_ISA_SVM);
-
if (!is_cr_intercept(svm, INTERCEPT_CR0_WRITE))
vcpu->arch.cr0 = svm->vmcb->save.cr0;
if (npt_enabled)
@@ -3335,7 +3353,8 @@ static int handle_exit(struct kvm_vcpu *vcpu)
svm->vmcb->control.exit_info_1,
svm->vmcb->control.exit_info_2,
svm->vmcb->control.exit_int_info,
- svm->vmcb->control.exit_int_info_err);
+ svm->vmcb->control.exit_int_info_err,
+ KVM_ISA_SVM);
vmexit = nested_svm_exit_special(svm);
@@ -3768,6 +3787,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
+ trace_kvm_exit(svm->vmcb->control.exit_code, vcpu, KVM_ISA_SVM);
+
if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
kvm_before_handle_nmi(&svm->vcpu);
@@ -3897,60 +3918,6 @@ static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
}
}
-static const struct trace_print_flags svm_exit_reasons_str[] = {
- { SVM_EXIT_READ_CR0, "read_cr0" },
- { SVM_EXIT_READ_CR3, "read_cr3" },
- { SVM_EXIT_READ_CR4, "read_cr4" },
- { SVM_EXIT_READ_CR8, "read_cr8" },
- { SVM_EXIT_WRITE_CR0, "write_cr0" },
- { SVM_EXIT_WRITE_CR3, "write_cr3" },
- { SVM_EXIT_WRITE_CR4, "write_cr4" },
- { SVM_EXIT_WRITE_CR8, "write_cr8" },
- { SVM_EXIT_READ_DR0, "read_dr0" },
- { SVM_EXIT_READ_DR1, "read_dr1" },
- { SVM_EXIT_READ_DR2, "read_dr2" },
- { SVM_EXIT_READ_DR3, "read_dr3" },
- { SVM_EXIT_WRITE_DR0, "write_dr0" },
- { SVM_EXIT_WRITE_DR1, "write_dr1" },
- { SVM_EXIT_WRITE_DR2, "write_dr2" },
- { SVM_EXIT_WRITE_DR3, "write_dr3" },
- { SVM_EXIT_WRITE_DR5, "write_dr5" },
- { SVM_EXIT_WRITE_DR7, "write_dr7" },
- { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" },
- { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" },
- { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" },
- { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" },
- { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" },
- { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" },
- { SVM_EXIT_INTR, "interrupt" },
- { SVM_EXIT_NMI, "nmi" },
- { SVM_EXIT_SMI, "smi" },
- { SVM_EXIT_INIT, "init" },
- { SVM_EXIT_VINTR, "vintr" },
- { SVM_EXIT_CPUID, "cpuid" },
- { SVM_EXIT_INVD, "invd" },
- { SVM_EXIT_HLT, "hlt" },
- { SVM_EXIT_INVLPG, "invlpg" },
- { SVM_EXIT_INVLPGA, "invlpga" },
- { SVM_EXIT_IOIO, "io" },
- { SVM_EXIT_MSR, "msr" },
- { SVM_EXIT_TASK_SWITCH, "task_switch" },
- { SVM_EXIT_SHUTDOWN, "shutdown" },
- { SVM_EXIT_VMRUN, "vmrun" },
- { SVM_EXIT_VMMCALL, "hypercall" },
- { SVM_EXIT_VMLOAD, "vmload" },
- { SVM_EXIT_VMSAVE, "vmsave" },
- { SVM_EXIT_STGI, "stgi" },
- { SVM_EXIT_CLGI, "clgi" },
- { SVM_EXIT_SKINIT, "skinit" },
- { SVM_EXIT_WBINVD, "wbinvd" },
- { SVM_EXIT_MONITOR, "monitor" },
- { SVM_EXIT_MWAIT, "mwait" },
- { SVM_EXIT_XSETBV, "xsetbv" },
- { SVM_EXIT_NPF, "npf" },
- { -1, NULL }
-};
-
static int svm_get_lpage_level(void)
{
return PT_PDPE_LEVEL;
@@ -4223,7 +4190,6 @@ static struct kvm_x86_ops svm_x86_ops = {
.get_mt_mask = svm_get_mt_mask,
.get_exit_info = svm_get_exit_info,
- .exit_reasons_str = svm_exit_reasons_str,
.get_lpage_level = svm_get_lpage_level,
@@ -4239,6 +4205,7 @@ static struct kvm_x86_ops svm_x86_ops = {
.write_tsc_offset = svm_write_tsc_offset,
.adjust_tsc_offset = svm_adjust_tsc_offset,
.compute_tsc_offset = svm_compute_tsc_offset,
+ .read_l1_tsc = svm_read_l1_tsc,
.set_tdp_cr3 = set_tdp_cr3,
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index 3ff898c104f7..911d2641f14c 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -2,6 +2,8 @@
#define _TRACE_KVM_H
#include <linux/tracepoint.h>
+#include <asm/vmx.h>
+#include <asm/svm.h>
#undef TRACE_SYSTEM
#define TRACE_SYSTEM kvm
@@ -181,6 +183,95 @@ TRACE_EVENT(kvm_apic,
#define KVM_ISA_VMX 1
#define KVM_ISA_SVM 2
+#define VMX_EXIT_REASONS \
+ { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
+ { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \
+ { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \
+ { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \
+ { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \
+ { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
+ { EXIT_REASON_CPUID, "CPUID" }, \
+ { EXIT_REASON_HLT, "HLT" }, \
+ { EXIT_REASON_INVLPG, "INVLPG" }, \
+ { EXIT_REASON_RDPMC, "RDPMC" }, \
+ { EXIT_REASON_RDTSC, "RDTSC" }, \
+ { EXIT_REASON_VMCALL, "VMCALL" }, \
+ { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \
+ { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \
+ { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \
+ { EXIT_REASON_VMPTRST, "VMPTRST" }, \
+ { EXIT_REASON_VMREAD, "VMREAD" }, \
+ { EXIT_REASON_VMRESUME, "VMRESUME" }, \
+ { EXIT_REASON_VMWRITE, "VMWRITE" }, \
+ { EXIT_REASON_VMOFF, "VMOFF" }, \
+ { EXIT_REASON_VMON, "VMON" }, \
+ { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \
+ { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \
+ { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
+ { EXIT_REASON_MSR_READ, "MSR_READ" }, \
+ { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
+ { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
+ { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
+ { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
+ { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
+ { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
+ { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
+ { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
+ { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
+ { EXIT_REASON_WBINVD, "WBINVD" }
+
+#define SVM_EXIT_REASONS \
+ { SVM_EXIT_READ_CR0, "read_cr0" }, \
+ { SVM_EXIT_READ_CR3, "read_cr3" }, \
+ { SVM_EXIT_READ_CR4, "read_cr4" }, \
+ { SVM_EXIT_READ_CR8, "read_cr8" }, \
+ { SVM_EXIT_WRITE_CR0, "write_cr0" }, \
+ { SVM_EXIT_WRITE_CR3, "write_cr3" }, \
+ { SVM_EXIT_WRITE_CR4, "write_cr4" }, \
+ { SVM_EXIT_WRITE_CR8, "write_cr8" }, \
+ { SVM_EXIT_READ_DR0, "read_dr0" }, \
+ { SVM_EXIT_READ_DR1, "read_dr1" }, \
+ { SVM_EXIT_READ_DR2, "read_dr2" }, \
+ { SVM_EXIT_READ_DR3, "read_dr3" }, \
+ { SVM_EXIT_WRITE_DR0, "write_dr0" }, \
+ { SVM_EXIT_WRITE_DR1, "write_dr1" }, \
+ { SVM_EXIT_WRITE_DR2, "write_dr2" }, \
+ { SVM_EXIT_WRITE_DR3, "write_dr3" }, \
+ { SVM_EXIT_WRITE_DR5, "write_dr5" }, \
+ { SVM_EXIT_WRITE_DR7, "write_dr7" }, \
+ { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
+ { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
+ { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
+ { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
+ { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
+ { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
+ { SVM_EXIT_INTR, "interrupt" }, \
+ { SVM_EXIT_NMI, "nmi" }, \
+ { SVM_EXIT_SMI, "smi" }, \
+ { SVM_EXIT_INIT, "init" }, \
+ { SVM_EXIT_VINTR, "vintr" }, \
+ { SVM_EXIT_CPUID, "cpuid" }, \
+ { SVM_EXIT_INVD, "invd" }, \
+ { SVM_EXIT_HLT, "hlt" }, \
+ { SVM_EXIT_INVLPG, "invlpg" }, \
+ { SVM_EXIT_INVLPGA, "invlpga" }, \
+ { SVM_EXIT_IOIO, "io" }, \
+ { SVM_EXIT_MSR, "msr" }, \
+ { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
+ { SVM_EXIT_SHUTDOWN, "shutdown" }, \
+ { SVM_EXIT_VMRUN, "vmrun" }, \
+ { SVM_EXIT_VMMCALL, "hypercall" }, \
+ { SVM_EXIT_VMLOAD, "vmload" }, \
+ { SVM_EXIT_VMSAVE, "vmsave" }, \
+ { SVM_EXIT_STGI, "stgi" }, \
+ { SVM_EXIT_CLGI, "clgi" }, \
+ { SVM_EXIT_SKINIT, "skinit" }, \
+ { SVM_EXIT_WBINVD, "wbinvd" }, \
+ { SVM_EXIT_MONITOR, "monitor" }, \
+ { SVM_EXIT_MWAIT, "mwait" }, \
+ { SVM_EXIT_XSETBV, "xsetbv" }, \
+ { SVM_EXIT_NPF, "npf" }
+
/*
* Tracepoint for kvm guest exit:
*/
@@ -205,8 +296,9 @@ TRACE_EVENT(kvm_exit,
),
TP_printk("reason %s rip 0x%lx info %llx %llx",
- ftrace_print_symbols_seq(p, __entry->exit_reason,
- kvm_x86_ops->exit_reasons_str),
+ (__entry->isa == KVM_ISA_VMX) ?
+ __print_symbolic(__entry->exit_reason, VMX_EXIT_REASONS) :
+ __print_symbolic(__entry->exit_reason, SVM_EXIT_REASONS),
__entry->guest_rip, __entry->info1, __entry->info2)
);
@@ -486,9 +578,9 @@ TRACE_EVENT(kvm_nested_intercepts,
TRACE_EVENT(kvm_nested_vmexit,
TP_PROTO(__u64 rip, __u32 exit_code,
__u64 exit_info1, __u64 exit_info2,
- __u32 exit_int_info, __u32 exit_int_info_err),
+ __u32 exit_int_info, __u32 exit_int_info_err, __u32 isa),
TP_ARGS(rip, exit_code, exit_info1, exit_info2,
- exit_int_info, exit_int_info_err),
+ exit_int_info, exit_int_info_err, isa),
TP_STRUCT__entry(
__field( __u64, rip )
@@ -497,6 +589,7 @@ TRACE_EVENT(kvm_nested_vmexit,
__field( __u64, exit_info2 )
__field( __u32, exit_int_info )
__field( __u32, exit_int_info_err )
+ __field( __u32, isa )
),
TP_fast_assign(
@@ -506,12 +599,14 @@ TRACE_EVENT(kvm_nested_vmexit,
__entry->exit_info2 = exit_info2;
__entry->exit_int_info = exit_int_info;
__entry->exit_int_info_err = exit_int_info_err;
+ __entry->isa = isa;
),
TP_printk("rip: 0x%016llx reason: %s ext_inf1: 0x%016llx "
"ext_inf2: 0x%016llx ext_int: 0x%08x ext_int_err: 0x%08x",
__entry->rip,
- ftrace_print_symbols_seq(p, __entry->exit_code,
- kvm_x86_ops->exit_reasons_str),
+ (__entry->isa == KVM_ISA_VMX) ?
+ __print_symbolic(__entry->exit_code, VMX_EXIT_REASONS) :
+ __print_symbolic(__entry->exit_code, SVM_EXIT_REASONS),
__entry->exit_info1, __entry->exit_info2,
__entry->exit_int_info, __entry->exit_int_info_err)
);
@@ -522,9 +617,9 @@ TRACE_EVENT(kvm_nested_vmexit,
TRACE_EVENT(kvm_nested_vmexit_inject,
TP_PROTO(__u32 exit_code,
__u64 exit_info1, __u64 exit_info2,
- __u32 exit_int_info, __u32 exit_int_info_err),
+ __u32 exit_int_info, __u32 exit_int_info_err, __u32 isa),
TP_ARGS(exit_code, exit_info1, exit_info2,
- exit_int_info, exit_int_info_err),
+ exit_int_info, exit_int_info_err, isa),
TP_STRUCT__entry(
__field( __u32, exit_code )
@@ -532,6 +627,7 @@ TRACE_EVENT(kvm_nested_vmexit_inject,
__field( __u64, exit_info2 )
__field( __u32, exit_int_info )
__field( __u32, exit_int_info_err )
+ __field( __u32, isa )
),
TP_fast_assign(
@@ -540,12 +636,14 @@ TRACE_EVENT(kvm_nested_vmexit_inject,
__entry->exit_info2 = exit_info2;
__entry->exit_int_info = exit_int_info;
__entry->exit_int_info_err = exit_int_info_err;
+ __entry->isa = isa;
),
TP_printk("reason: %s ext_inf1: 0x%016llx "
"ext_inf2: 0x%016llx ext_int: 0x%08x ext_int_err: 0x%08x",
- ftrace_print_symbols_seq(p, __entry->exit_code,
- kvm_x86_ops->exit_reasons_str),
+ (__entry->isa == KVM_ISA_VMX) ?
+ __print_symbolic(__entry->exit_code, VMX_EXIT_REASONS) :
+ __print_symbolic(__entry->exit_code, SVM_EXIT_REASONS),
__entry->exit_info1, __entry->exit_info2,
__entry->exit_int_info, __entry->exit_int_info_err)
);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index e65a158dee64..a0d6bd9ad442 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -71,6 +71,9 @@ module_param(vmm_exclusive, bool, S_IRUGO);
static int __read_mostly yield_on_hlt = 1;
module_param(yield_on_hlt, bool, S_IRUGO);
+static int __read_mostly fasteoi = 1;
+module_param(fasteoi, bool, S_IRUGO);
+
/*
* If nested=1, nested virtualization is supported, i.e., guests may use
* VMX and be a hypervisor for its own guests. If nested=0, guests may not
@@ -1748,6 +1751,21 @@ static u64 guest_read_tsc(void)
}
/*
+ * Like guest_read_tsc, but always returns L1's notion of the timestamp
+ * counter, even if a nested guest (L2) is currently running.
+ */
+u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu)
+{
+ u64 host_tsc, tsc_offset;
+
+ rdtscll(host_tsc);
+ tsc_offset = is_guest_mode(vcpu) ?
+ to_vmx(vcpu)->nested.vmcs01_tsc_offset :
+ vmcs_read64(TSC_OFFSET);
+ return host_tsc + tsc_offset;
+}
+
+/*
* Empty call-back. Needs to be implemented when VMX enables the SET_TSC_KHZ
* ioctl. In this case the call-back should update internal vmx state to make
* the changes effective.
@@ -1762,15 +1780,23 @@ static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
*/
static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
{
- vmcs_write64(TSC_OFFSET, offset);
- if (is_guest_mode(vcpu))
+ if (is_guest_mode(vcpu)) {
/*
- * We're here if L1 chose not to trap the TSC MSR. Since
- * prepare_vmcs12() does not copy tsc_offset, we need to also
- * set the vmcs12 field here.
+ * We're here if L1 chose not to trap WRMSR to TSC. According
+ * to the spec, this should set L1's TSC; The offset that L1
+ * set for L2 remains unchanged, and still needs to be added
+ * to the newly set TSC to get L2's TSC.
*/
- get_vmcs12(vcpu)->tsc_offset = offset -
- to_vmx(vcpu)->nested.vmcs01_tsc_offset;
+ struct vmcs12 *vmcs12;
+ to_vmx(vcpu)->nested.vmcs01_tsc_offset = offset;
+ /* recalculate vmcs02.TSC_OFFSET: */
+ vmcs12 = get_vmcs12(vcpu);
+ vmcs_write64(TSC_OFFSET, offset +
+ (nested_cpu_has(vmcs12, CPU_BASED_USE_TSC_OFFSETING) ?
+ vmcs12->tsc_offset : 0));
+ } else {
+ vmcs_write64(TSC_OFFSET, offset);
+ }
}
static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment)
@@ -2736,8 +2762,8 @@ static void enter_lmode(struct kvm_vcpu *vcpu)
guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
- printk(KERN_DEBUG "%s: tss fixup for long mode. \n",
- __func__);
+ pr_debug_ratelimited("%s: tss fixup for long mode. \n",
+ __func__);
vmcs_write32(GUEST_TR_AR_BYTES,
(guest_tr_ar & ~AR_TYPE_MASK)
| AR_TYPE_BUSY_64_TSS);
@@ -4115,8 +4141,7 @@ static int handle_exception(struct kvm_vcpu *vcpu)
error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
if (is_page_fault(intr_info)) {
/* EPT won't cause page fault directly */
- if (enable_ept)
- BUG();
+ BUG_ON(enable_ept);
cr2 = vmcs_readl(EXIT_QUALIFICATION);
trace_kvm_page_fault(cr2, error_code);
@@ -4518,6 +4543,24 @@ static int handle_xsetbv(struct kvm_vcpu *vcpu)
static int handle_apic_access(struct kvm_vcpu *vcpu)
{
+ if (likely(fasteoi)) {
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ int access_type, offset;
+
+ access_type = exit_qualification & APIC_ACCESS_TYPE;
+ offset = exit_qualification & APIC_ACCESS_OFFSET;
+ /*
+ * Sane guest uses MOV to write EOI, with written value
+ * not cared. So make a short-circuit here by avoiding
+ * heavy instruction emulation.
+ */
+ if ((access_type == TYPE_LINEAR_APIC_INST_WRITE) &&
+ (offset == APIC_EOI)) {
+ kvm_lapic_set_eoi(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+ }
return emulate_instruction(vcpu, 0) == EMULATE_DONE;
}
@@ -5591,8 +5634,8 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
return 0;
if (unlikely(vmx->fail)) {
- printk(KERN_INFO "%s failed vm entry %x\n",
- __func__, vmcs_read32(VM_INSTRUCTION_ERROR));
+ pr_info_ratelimited("%s failed vm entry %x\n", __func__,
+ vmcs_read32(VM_INSTRUCTION_ERROR));
return 1;
}
@@ -5696,8 +5739,6 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
u32 exit_reason = vmx->exit_reason;
u32 vectoring_info = vmx->idt_vectoring_info;
- trace_kvm_exit(exit_reason, vcpu, KVM_ISA_VMX);
-
/* If guest state is invalid, start emulating */
if (vmx->emulation_required && emulate_invalid_guest_state)
return handle_invalid_guest_state(vcpu);
@@ -6101,6 +6142,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
vmx->loaded_vmcs->launched = 1;
vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
+ trace_kvm_exit(vmx->exit_reason, vcpu, KVM_ISA_VMX);
vmx_complete_atomic_exit(vmx);
vmx_recover_nmi_blocking(vmx);
@@ -6241,49 +6283,6 @@ static u64 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
return ret;
}
-#define _ER(x) { EXIT_REASON_##x, #x }
-
-static const struct trace_print_flags vmx_exit_reasons_str[] = {
- _ER(EXCEPTION_NMI),
- _ER(EXTERNAL_INTERRUPT),
- _ER(TRIPLE_FAULT),
- _ER(PENDING_INTERRUPT),
- _ER(NMI_WINDOW),
- _ER(TASK_SWITCH),
- _ER(CPUID),
- _ER(HLT),
- _ER(INVLPG),
- _ER(RDPMC),
- _ER(RDTSC),
- _ER(VMCALL),
- _ER(VMCLEAR),
- _ER(VMLAUNCH),
- _ER(VMPTRLD),
- _ER(VMPTRST),
- _ER(VMREAD),
- _ER(VMRESUME),
- _ER(VMWRITE),
- _ER(VMOFF),
- _ER(VMON),
- _ER(CR_ACCESS),
- _ER(DR_ACCESS),
- _ER(IO_INSTRUCTION),
- _ER(MSR_READ),
- _ER(MSR_WRITE),
- _ER(MWAIT_INSTRUCTION),
- _ER(MONITOR_INSTRUCTION),
- _ER(PAUSE_INSTRUCTION),
- _ER(MCE_DURING_VMENTRY),
- _ER(TPR_BELOW_THRESHOLD),
- _ER(APIC_ACCESS),
- _ER(EPT_VIOLATION),
- _ER(EPT_MISCONFIG),
- _ER(WBINVD),
- { -1, NULL }
-};
-
-#undef _ER
-
static int vmx_get_lpage_level(void)
{
if (enable_ept && !cpu_has_vmx_ept_1g_page())
@@ -6514,8 +6513,11 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
set_cr4_guest_host_mask(vmx);
- vmcs_write64(TSC_OFFSET,
- vmx->nested.vmcs01_tsc_offset + vmcs12->tsc_offset);
+ if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
+ vmcs_write64(TSC_OFFSET,
+ vmx->nested.vmcs01_tsc_offset + vmcs12->tsc_offset);
+ else
+ vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset);
if (enable_vpid) {
/*
@@ -6610,9 +6612,8 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
if (vmcs12->vm_entry_msr_load_count > 0 ||
vmcs12->vm_exit_msr_load_count > 0 ||
vmcs12->vm_exit_msr_store_count > 0) {
- if (printk_ratelimit())
- printk(KERN_WARNING
- "%s: VMCS MSR_{LOAD,STORE} unsupported\n", __func__);
+ pr_warn_ratelimited("%s: VMCS MSR_{LOAD,STORE} unsupported\n",
+ __func__);
nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
return 1;
}
@@ -6922,7 +6923,7 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu)
load_vmcs12_host_state(vcpu, vmcs12);
- /* Update TSC_OFFSET if vmx_adjust_tsc_offset() was used while L2 ran */
+ /* Update TSC_OFFSET if TSC was changed while L2 ran */
vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset);
/* This is needed for same reason as it was needed in prepare_vmcs02 */
@@ -7039,7 +7040,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
.get_mt_mask = vmx_get_mt_mask,
.get_exit_info = vmx_get_exit_info,
- .exit_reasons_str = vmx_exit_reasons_str,
.get_lpage_level = vmx_get_lpage_level,
@@ -7055,6 +7055,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
.write_tsc_offset = vmx_write_tsc_offset,
.adjust_tsc_offset = vmx_adjust_tsc_offset,
.compute_tsc_offset = vmx_compute_tsc_offset,
+ .read_l1_tsc = vmx_read_l1_tsc,
.set_tdp_cr3 = vmx_set_cr3,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 84a28ea45fa4..c38efd7b792e 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -44,6 +44,7 @@
#include <linux/perf_event.h>
#include <linux/uaccess.h>
#include <linux/hash.h>
+#include <linux/pci.h>
#include <trace/events/kvm.h>
#define CREATE_TRACE_POINTS
@@ -83,6 +84,7 @@ static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE);
static void update_cr8_intercept(struct kvm_vcpu *vcpu);
static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
struct kvm_cpuid_entry2 __user *entries);
+static void process_nmi(struct kvm_vcpu *vcpu);
struct kvm_x86_ops *kvm_x86_ops;
EXPORT_SYMBOL_GPL(kvm_x86_ops);
@@ -359,8 +361,8 @@ void kvm_propagate_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault)
void kvm_inject_nmi(struct kvm_vcpu *vcpu)
{
- kvm_make_request(KVM_REQ_EVENT, vcpu);
- vcpu->arch.nmi_pending = 1;
+ atomic_inc(&vcpu->arch.nmi_queued);
+ kvm_make_request(KVM_REQ_NMI, vcpu);
}
EXPORT_SYMBOL_GPL(kvm_inject_nmi);
@@ -599,6 +601,8 @@ static bool guest_cpuid_has_fsgsbase(struct kvm_vcpu *vcpu)
static void update_cpuid(struct kvm_vcpu *vcpu)
{
struct kvm_cpuid_entry2 *best;
+ struct kvm_lapic *apic = vcpu->arch.apic;
+ u32 timer_mode_mask;
best = kvm_find_cpuid_entry(vcpu, 1, 0);
if (!best)
@@ -610,6 +614,16 @@ static void update_cpuid(struct kvm_vcpu *vcpu)
if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
best->ecx |= bit(X86_FEATURE_OSXSAVE);
}
+
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+ best->function == 0x1) {
+ best->ecx |= bit(X86_FEATURE_TSC_DEADLINE_TIMER);
+ timer_mode_mask = 3 << 17;
+ } else
+ timer_mode_mask = 1 << 17;
+
+ if (apic)
+ apic->lapic_timer.timer_mode_mask = timer_mode_mask;
}
int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -825,6 +839,7 @@ static u32 msrs_to_save[] = {
static unsigned num_msrs_to_save;
static u32 emulated_msrs[] = {
+ MSR_IA32_TSCDEADLINE,
MSR_IA32_MISC_ENABLE,
MSR_IA32_MCG_STATUS,
MSR_IA32_MCG_CTL,
@@ -1000,7 +1015,7 @@ static inline int kvm_tsc_changes_freq(void)
return ret;
}
-static u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
{
if (vcpu->arch.virtual_tsc_khz)
return vcpu->arch.virtual_tsc_khz;
@@ -1098,7 +1113,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
/* Keep irq disabled to prevent changes to the clock */
local_irq_save(flags);
- kvm_get_msr(v, MSR_IA32_TSC, &tsc_timestamp);
+ tsc_timestamp = kvm_x86_ops->read_l1_tsc(v);
kernel_ns = get_kernel_ns();
this_tsc_khz = vcpu_tsc_khz(v);
if (unlikely(this_tsc_khz == 0)) {
@@ -1564,6 +1579,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
break;
case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
return kvm_x2apic_msr_write(vcpu, msr, data);
+ case MSR_IA32_TSCDEADLINE:
+ kvm_set_lapic_tscdeadline_msr(vcpu, data);
+ break;
case MSR_IA32_MISC_ENABLE:
vcpu->arch.ia32_misc_enable_msr = data;
break;
@@ -1825,6 +1843,9 @@ static int get_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata);
case HV_X64_MSR_TPR:
return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata);
+ case HV_X64_MSR_APIC_ASSIST_PAGE:
+ data = vcpu->arch.hv_vapic;
+ break;
default:
pr_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
return 1;
@@ -1839,7 +1860,6 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
switch (msr) {
case MSR_IA32_PLATFORM_ID:
- case MSR_IA32_UCODE_REV:
case MSR_IA32_EBL_CR_POWERON:
case MSR_IA32_DEBUGCTLMSR:
case MSR_IA32_LASTBRANCHFROMIP:
@@ -1860,6 +1880,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
case MSR_FAM10H_MMIO_CONF_BASE:
data = 0;
break;
+ case MSR_IA32_UCODE_REV:
+ data = 0x100000000ULL;
+ break;
case MSR_MTRRcap:
data = 0x500 | KVM_NR_VAR_MTRR;
break;
@@ -1888,6 +1911,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
return kvm_x2apic_msr_read(vcpu, msr, pdata);
break;
+ case MSR_IA32_TSCDEADLINE:
+ data = kvm_get_lapic_tscdeadline_msr(vcpu);
+ break;
case MSR_IA32_MISC_ENABLE:
data = vcpu->arch.ia32_misc_enable_msr;
break;
@@ -2086,6 +2112,9 @@ int kvm_dev_ioctl_check_extension(long ext)
r = !kvm_x86_ops->cpu_has_accelerated_tpr();
break;
case KVM_CAP_NR_VCPUS:
+ r = KVM_SOFT_MAX_VCPUS;
+ break;
+ case KVM_CAP_MAX_VCPUS:
r = KVM_MAX_VCPUS;
break;
case KVM_CAP_NR_MEMSLOTS:
@@ -2095,7 +2124,7 @@ int kvm_dev_ioctl_check_extension(long ext)
r = 0;
break;
case KVM_CAP_IOMMU:
- r = iommu_found();
+ r = iommu_present(&pci_bus_type);
break;
case KVM_CAP_MCE:
r = KVM_MAX_MCE_BANKS;
@@ -2210,7 +2239,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
s64 tsc_delta;
u64 tsc;
- kvm_get_msr(vcpu, MSR_IA32_TSC, &tsc);
+ tsc = kvm_x86_ops->read_l1_tsc(vcpu);
tsc_delta = !vcpu->arch.last_guest_tsc ? 0 :
tsc - vcpu->arch.last_guest_tsc;
@@ -2234,7 +2263,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
{
kvm_x86_ops->vcpu_put(vcpu);
kvm_put_guest_fpu(vcpu);
- kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc);
+ vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
}
static int is_efer_nx(void)
@@ -2819,6 +2848,7 @@ static int kvm_vcpu_ioctl_x86_set_mce(struct kvm_vcpu *vcpu,
static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
struct kvm_vcpu_events *events)
{
+ process_nmi(vcpu);
events->exception.injected =
vcpu->arch.exception.pending &&
!kvm_exception_is_soft(vcpu->arch.exception.nr);
@@ -2836,7 +2866,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
KVM_X86_SHADOW_INT_MOV_SS | KVM_X86_SHADOW_INT_STI);
events->nmi.injected = vcpu->arch.nmi_injected;
- events->nmi.pending = vcpu->arch.nmi_pending;
+ events->nmi.pending = vcpu->arch.nmi_pending != 0;
events->nmi.masked = kvm_x86_ops->get_nmi_mask(vcpu);
events->nmi.pad = 0;
@@ -2856,6 +2886,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
| KVM_VCPUEVENT_VALID_SHADOW))
return -EINVAL;
+ process_nmi(vcpu);
vcpu->arch.exception.pending = events->exception.injected;
vcpu->arch.exception.nr = events->exception.nr;
vcpu->arch.exception.has_error_code = events->exception.has_error_code;
@@ -3556,7 +3587,11 @@ long kvm_arch_vm_ioctl(struct file *filp,
if (r) {
mutex_lock(&kvm->slots_lock);
kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
- &vpic->dev);
+ &vpic->dev_master);
+ kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
+ &vpic->dev_slave);
+ kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
+ &vpic->dev_eclr);
mutex_unlock(&kvm->slots_lock);
kfree(vpic);
goto create_irqchip_unlock;
@@ -4045,84 +4080,105 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
return 0;
}
-static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
- unsigned long addr,
- void *val,
- unsigned int bytes,
- struct x86_exception *exception)
+int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
+ const void *val, int bytes)
{
- struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
- gpa_t gpa;
- int handled, ret;
+ int ret;
+ ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes);
+ if (ret < 0)
+ return 0;
+ kvm_mmu_pte_write(vcpu, gpa, val, bytes, 1);
+ return 1;
+}
+
+struct read_write_emulator_ops {
+ int (*read_write_prepare)(struct kvm_vcpu *vcpu, void *val,
+ int bytes);
+ int (*read_write_emulate)(struct kvm_vcpu *vcpu, gpa_t gpa,
+ void *val, int bytes);
+ int (*read_write_mmio)(struct kvm_vcpu *vcpu, gpa_t gpa,
+ int bytes, void *val);
+ int (*read_write_exit_mmio)(struct kvm_vcpu *vcpu, gpa_t gpa,
+ void *val, int bytes);
+ bool write;
+};
+
+static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes)
+{
if (vcpu->mmio_read_completed) {
memcpy(val, vcpu->mmio_data, bytes);
trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes,
vcpu->mmio_phys_addr, *(u64 *)val);
vcpu->mmio_read_completed = 0;
- return X86EMUL_CONTINUE;
+ return 1;
}
- ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, false);
-
- if (ret < 0)
- return X86EMUL_PROPAGATE_FAULT;
-
- if (ret)
- goto mmio;
-
- if (kvm_read_guest_virt(ctxt, addr, val, bytes, exception)
- == X86EMUL_CONTINUE)
- return X86EMUL_CONTINUE;
+ return 0;
+}
-mmio:
- /*
- * Is this MMIO handled locally?
- */
- handled = vcpu_mmio_read(vcpu, gpa, bytes, val);
+static int read_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
+ void *val, int bytes)
+{
+ return !kvm_read_guest(vcpu->kvm, gpa, val, bytes);
+}
- if (handled == bytes)
- return X86EMUL_CONTINUE;
+static int write_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
+ void *val, int bytes)
+{
+ return emulator_write_phys(vcpu, gpa, val, bytes);
+}
- gpa += handled;
- bytes -= handled;
- val += handled;
+static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val)
+{
+ trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
+ return vcpu_mmio_write(vcpu, gpa, bytes, val);
+}
+static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
+ void *val, int bytes)
+{
trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
-
- vcpu->mmio_needed = 1;
- vcpu->run->exit_reason = KVM_EXIT_MMIO;
- vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
- vcpu->mmio_size = bytes;
- vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
- vcpu->run->mmio.is_write = vcpu->mmio_is_write = 0;
- vcpu->mmio_index = 0;
-
return X86EMUL_IO_NEEDED;
}
-int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
- const void *val, int bytes)
+static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
+ void *val, int bytes)
{
- int ret;
-
- ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes);
- if (ret < 0)
- return 0;
- kvm_mmu_pte_write(vcpu, gpa, val, bytes, 1);
- return 1;
+ memcpy(vcpu->mmio_data, val, bytes);
+ memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
+ return X86EMUL_CONTINUE;
}
-static int emulator_write_emulated_onepage(unsigned long addr,
- const void *val,
- unsigned int bytes,
- struct x86_exception *exception,
- struct kvm_vcpu *vcpu)
+static struct read_write_emulator_ops read_emultor = {
+ .read_write_prepare = read_prepare,
+ .read_write_emulate = read_emulate,
+ .read_write_mmio = vcpu_mmio_read,
+ .read_write_exit_mmio = read_exit_mmio,
+};
+
+static struct read_write_emulator_ops write_emultor = {
+ .read_write_emulate = write_emulate,
+ .read_write_mmio = write_mmio,
+ .read_write_exit_mmio = write_exit_mmio,
+ .write = true,
+};
+
+static int emulator_read_write_onepage(unsigned long addr, void *val,
+ unsigned int bytes,
+ struct x86_exception *exception,
+ struct kvm_vcpu *vcpu,
+ struct read_write_emulator_ops *ops)
{
gpa_t gpa;
int handled, ret;
+ bool write = ops->write;
- ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, true);
+ if (ops->read_write_prepare &&
+ ops->read_write_prepare(vcpu, val, bytes))
+ return X86EMUL_CONTINUE;
+
+ ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, write);
if (ret < 0)
return X86EMUL_PROPAGATE_FAULT;
@@ -4131,15 +4187,14 @@ static int emulator_write_emulated_onepage(unsigned long addr,
if (ret)
goto mmio;
- if (emulator_write_phys(vcpu, gpa, val, bytes))
+ if (ops->read_write_emulate(vcpu, gpa, val, bytes))
return X86EMUL_CONTINUE;
mmio:
- trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
/*
* Is this MMIO handled locally?
*/
- handled = vcpu_mmio_write(vcpu, gpa, bytes, val);
+ handled = ops->read_write_mmio(vcpu, gpa, bytes, val);
if (handled == bytes)
return X86EMUL_CONTINUE;
@@ -4148,23 +4203,20 @@ mmio:
val += handled;
vcpu->mmio_needed = 1;
- memcpy(vcpu->mmio_data, val, bytes);
vcpu->run->exit_reason = KVM_EXIT_MMIO;
vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
vcpu->mmio_size = bytes;
vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
- vcpu->run->mmio.is_write = vcpu->mmio_is_write = 1;
- memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
+ vcpu->run->mmio.is_write = vcpu->mmio_is_write = write;
vcpu->mmio_index = 0;
- return X86EMUL_CONTINUE;
+ return ops->read_write_exit_mmio(vcpu, gpa, val, bytes);
}
-int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
- unsigned long addr,
- const void *val,
- unsigned int bytes,
- struct x86_exception *exception)
+int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
+ void *val, unsigned int bytes,
+ struct x86_exception *exception,
+ struct read_write_emulator_ops *ops)
{
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
@@ -4173,16 +4225,38 @@ int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
int rc, now;
now = -addr & ~PAGE_MASK;
- rc = emulator_write_emulated_onepage(addr, val, now, exception,
- vcpu);
+ rc = emulator_read_write_onepage(addr, val, now, exception,
+ vcpu, ops);
+
if (rc != X86EMUL_CONTINUE)
return rc;
addr += now;
val += now;
bytes -= now;
}
- return emulator_write_emulated_onepage(addr, val, bytes, exception,
- vcpu);
+
+ return emulator_read_write_onepage(addr, val, bytes, exception,
+ vcpu, ops);
+}
+
+static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
+ unsigned long addr,
+ void *val,
+ unsigned int bytes,
+ struct x86_exception *exception)
+{
+ return emulator_read_write(ctxt, addr, val, bytes,
+ exception, &read_emultor);
+}
+
+int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
+ unsigned long addr,
+ const void *val,
+ unsigned int bytes,
+ struct x86_exception *exception)
+{
+ return emulator_read_write(ctxt, addr, (void *)val, bytes,
+ exception, &write_emultor);
}
#define CMPXCHG_TYPE(t, ptr, old, new) \
@@ -4712,7 +4786,7 @@ int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip)
kvm_set_rflags(vcpu, ctxt->eflags);
if (irq == NMI_VECTOR)
- vcpu->arch.nmi_pending = false;
+ vcpu->arch.nmi_pending = 0;
else
vcpu->arch.interrupt.pending = false;
@@ -4788,7 +4862,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
trace_kvm_emulate_insn_start(vcpu);
++vcpu->stat.insn_emulation;
- if (r) {
+ if (r != EMULATION_OK) {
if (emulation_type & EMULTYPE_TRAP_UD)
return EMULATE_FAIL;
if (reexecute_instruction(vcpu, cr2))
@@ -5521,7 +5595,7 @@ static void inject_pending_event(struct kvm_vcpu *vcpu)
/* try to inject new event if pending */
if (vcpu->arch.nmi_pending) {
if (kvm_x86_ops->nmi_allowed(vcpu)) {
- vcpu->arch.nmi_pending = false;
+ --vcpu->arch.nmi_pending;
vcpu->arch.nmi_injected = true;
kvm_x86_ops->set_nmi(vcpu);
}
@@ -5553,10 +5627,26 @@ static void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu)
}
}
+static void process_nmi(struct kvm_vcpu *vcpu)
+{
+ unsigned limit = 2;
+
+ /*
+ * x86 is limited to one NMI running, and one NMI pending after it.
+ * If an NMI is already in progress, limit further NMIs to just one.
+ * Otherwise, allow two (and we'll inject the first one immediately).
+ */
+ if (kvm_x86_ops->get_nmi_mask(vcpu) || vcpu->arch.nmi_injected)
+ limit = 1;
+
+ vcpu->arch.nmi_pending += atomic_xchg(&vcpu->arch.nmi_queued, 0);
+ vcpu->arch.nmi_pending = min(vcpu->arch.nmi_pending, limit);
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+}
+
static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
{
int r;
- bool nmi_pending;
bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
vcpu->run->request_interrupt_window;
@@ -5596,6 +5686,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
}
if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu))
record_steal_time(vcpu);
+ if (kvm_check_request(KVM_REQ_NMI, vcpu))
+ process_nmi(vcpu);
}
@@ -5603,19 +5695,11 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
if (unlikely(r))
goto out;
- /*
- * An NMI can be injected between local nmi_pending read and
- * vcpu->arch.nmi_pending read inside inject_pending_event().
- * But in that case, KVM_REQ_EVENT will be set, which makes
- * the race described above benign.
- */
- nmi_pending = ACCESS_ONCE(vcpu->arch.nmi_pending);
-
if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
inject_pending_event(vcpu);
/* enable NMI/IRQ window open exits if needed */
- if (nmi_pending)
+ if (vcpu->arch.nmi_pending)
kvm_x86_ops->enable_nmi_window(vcpu);
else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
kvm_x86_ops->enable_irq_window(vcpu);
@@ -5678,7 +5762,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
if (hw_breakpoint_active())
hw_breakpoint_restore();
- kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc);
+ vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
vcpu->mode = OUTSIDE_GUEST_MODE;
smp_wmb();
@@ -6323,7 +6407,8 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
{
- vcpu->arch.nmi_pending = false;
+ atomic_set(&vcpu->arch.nmi_queued, 0);
+ vcpu->arch.nmi_pending = 0;
vcpu->arch.nmi_injected = false;
vcpu->arch.switch_db_regs = 0;
@@ -6598,7 +6683,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
!vcpu->arch.apf.halted)
|| !list_empty_careful(&vcpu->async_pf.done)
|| vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED
- || vcpu->arch.nmi_pending ||
+ || atomic_read(&vcpu->arch.nmi_queued) ||
(kvm_arch_interrupt_allowed(vcpu) &&
kvm_cpu_has_interrupt(vcpu));
}
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 13ee258442ae..f63da5ef217c 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -70,6 +70,7 @@
#include <asm/i387.h>
#include <asm/stackprotector.h>
#include <asm/reboot.h> /* for struct machine_ops */
+#include <asm/kvm_para.h>
/*G:010
* Welcome to the Guest!
@@ -455,6 +456,15 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
*ax &= 0xFFFFF0FF;
*ax |= 0x00000500;
break;
+
+ /*
+ * This is used to detect if we're running under KVM. We might be,
+ * but that's a Host matter, not us. So say we're not.
+ */
+ case KVM_CPUID_SIGNATURE:
+ *bx = *cx = *dx = 0;
+ break;
+
/*
* 0x80000000 returns the highest Extended Function, so we futureproof
* like we do above by limiting it to known fields.
diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c
index 9f33b984d0ef..374562ed6704 100644
--- a/arch/x86/lib/insn.c
+++ b/arch/x86/lib/insn.c
@@ -22,14 +22,23 @@
#include <asm/inat.h>
#include <asm/insn.h>
-#define get_next(t, insn) \
- ({t r; r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
+/* Verify next sizeof(t) bytes can be on the same instruction */
+#define validate_next(t, insn, n) \
+ ((insn)->next_byte + sizeof(t) + n - (insn)->kaddr <= MAX_INSN_SIZE)
+
+#define __get_next(t, insn) \
+ ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
+
+#define __peek_nbyte_next(t, insn, n) \
+ ({ t r = *(t*)((insn)->next_byte + n); r; })
-#define peek_next(t, insn) \
- ({t r; r = *(t*)insn->next_byte; r; })
+#define get_next(t, insn) \
+ ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
#define peek_nbyte_next(t, insn, n) \
- ({t r; r = *(t*)((insn)->next_byte + n); r; })
+ ({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); })
+
+#define peek_next(t, insn) peek_nbyte_next(t, insn, 0)
/**
* insn_init() - initialize struct insn
@@ -158,6 +167,8 @@ vex_end:
insn->vex_prefix.got = 1;
prefixes->got = 1;
+
+err_out:
return;
}
@@ -208,6 +219,9 @@ void insn_get_opcode(struct insn *insn)
insn->attr = 0; /* This instruction is bad */
end:
opcode->got = 1;
+
+err_out:
+ return;
}
/**
@@ -241,6 +255,9 @@ void insn_get_modrm(struct insn *insn)
if (insn->x86_64 && inat_is_force64(insn->attr))
insn->opnd_bytes = 8;
modrm->got = 1;
+
+err_out:
+ return;
}
@@ -290,6 +307,9 @@ void insn_get_sib(struct insn *insn)
}
}
insn->sib.got = 1;
+
+err_out:
+ return;
}
@@ -351,6 +371,9 @@ void insn_get_displacement(struct insn *insn)
}
out:
insn->displacement.got = 1;
+
+err_out:
+ return;
}
/* Decode moffset16/32/64 */
@@ -373,6 +396,9 @@ static void __get_moffset(struct insn *insn)
break;
}
insn->moffset1.got = insn->moffset2.got = 1;
+
+err_out:
+ return;
}
/* Decode imm v32(Iz) */
@@ -389,6 +415,9 @@ static void __get_immv32(struct insn *insn)
insn->immediate.nbytes = 4;
break;
}
+
+err_out:
+ return;
}
/* Decode imm v64(Iv/Ov) */
@@ -411,6 +440,9 @@ static void __get_immv(struct insn *insn)
break;
}
insn->immediate1.got = insn->immediate2.got = 1;
+
+err_out:
+ return;
}
/* Decode ptr16:16/32(Ap) */
@@ -432,6 +464,9 @@ static void __get_immptr(struct insn *insn)
insn->immediate2.value = get_next(unsigned short, insn);
insn->immediate2.nbytes = 2;
insn->immediate1.got = insn->immediate2.got = 1;
+
+err_out:
+ return;
}
/**
@@ -496,6 +531,9 @@ void insn_get_immediate(struct insn *insn)
}
done:
insn->immediate.got = 1;
+
+err_out:
+ return;
}
/**
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 0d17c8c50acd..5db0490deb07 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -17,7 +17,7 @@
#include <asm/traps.h> /* dotraplinkage, ... */
#include <asm/pgalloc.h> /* pgd_*(), ... */
#include <asm/kmemcheck.h> /* kmemcheck_*(), ... */
-#include <asm/vsyscall.h>
+#include <asm/fixmap.h> /* VSYSCALL_START */
/*
* Page fault error code bits:
@@ -420,12 +420,14 @@ static noinline __kprobes int vmalloc_fault(unsigned long address)
return 0;
}
+#ifdef CONFIG_CPU_SUP_AMD
static const char errata93_warning[] =
KERN_ERR
"******* Your BIOS seems to not contain a fix for K8 errata #93\n"
"******* Working around it, but it may cause SEGVs or burn power.\n"
"******* Please consider a BIOS update.\n"
"******* Disabling USB legacy in the BIOS may also help.\n";
+#endif
/*
* No vm86 mode in 64-bit mode:
@@ -505,7 +507,11 @@ bad:
*/
static int is_errata93(struct pt_regs *regs, unsigned long address)
{
-#ifdef CONFIG_X86_64
+#if defined(CONFIG_X86_64) && defined(CONFIG_CPU_SUP_AMD)
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD
+ || boot_cpu_data.x86 != 0xf)
+ return 0;
+
if (address != regs->ip)
return 0;
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
index dbe34b931374..ea305856151c 100644
--- a/arch/x86/mm/gup.c
+++ b/arch/x86/mm/gup.c
@@ -108,16 +108,6 @@ static inline void get_head_page_multiple(struct page *page, int nr)
SetPageReferenced(page);
}
-static inline void get_huge_page_tail(struct page *page)
-{
- /*
- * __split_huge_page_refcount() cannot run
- * from under us.
- */
- VM_BUG_ON(atomic_read(&page->_count) < 0);
- atomic_inc(&page->_count);
-}
-
static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,
unsigned long end, int write, struct page **pages, int *nr)
{
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 1dab5194fd9d..4b5ba85eb5c9 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,10 @@
#include <linux/sched.h>
#include <asm/elf.h>
+struct __read_mostly va_alignment va_align = {
+ .flags = -1,
+};
+
static unsigned int stack_maxrandom_size(void)
{
unsigned int max = 0;
@@ -42,7 +46,6 @@ static unsigned int stack_maxrandom_size(void)
return max;
}
-
/*
* Top of mmap area (just below the process stack).
*
@@ -51,21 +54,6 @@ static unsigned int stack_maxrandom_size(void)
#define MIN_GAP (128*1024*1024UL + stack_maxrandom_size())
#define MAX_GAP (TASK_SIZE/6*5)
-/*
- * True on X86_32 or when emulating IA32 on X86_64
- */
-static int mmap_is_ia32(void)
-{
-#ifdef CONFIG_X86_32
- return 1;
-#endif
-#ifdef CONFIG_IA32_EMULATION
- if (test_thread_flag(TIF_IA32))
- return 1;
-#endif
- return 0;
-}
-
static int mmap_is_legacy(void)
{
if (current->personality & ADDR_COMPAT_LAYOUT)
diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c
index 67421f38a215..de54b9b278a7 100644
--- a/arch/x86/mm/mmio-mod.c
+++ b/arch/x86/mm/mmio-mod.c
@@ -29,7 +29,6 @@
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
-#include <linux/version.h>
#include <linux/kallsyms.h>
#include <asm/pgtable.h>
#include <linux/mmiotrace.h>
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 68894fdc034b..75f9528e0372 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -61,26 +61,15 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model,
}
-static int profile_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data)
+static int profile_exceptions_notify(unsigned int val, struct pt_regs *regs)
{
- struct die_args *args = (struct die_args *)data;
- int ret = NOTIFY_DONE;
-
- switch (val) {
- case DIE_NMI:
- if (ctr_running)
- model->check_ctrs(args->regs, &__get_cpu_var(cpu_msrs));
- else if (!nmi_enabled)
- break;
- else
- model->stop(&__get_cpu_var(cpu_msrs));
- ret = NOTIFY_STOP;
- break;
- default:
- break;
- }
- return ret;
+ if (ctr_running)
+ model->check_ctrs(regs, &__get_cpu_var(cpu_msrs));
+ else if (!nmi_enabled)
+ return NMI_DONE;
+ else
+ model->stop(&__get_cpu_var(cpu_msrs));
+ return NMI_HANDLED;
}
static void nmi_cpu_save_registers(struct op_msrs *msrs)
@@ -355,20 +344,14 @@ static void nmi_cpu_setup(void *dummy)
int cpu = smp_processor_id();
struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu);
nmi_cpu_save_registers(msrs);
- spin_lock(&oprofilefs_lock);
+ raw_spin_lock(&oprofilefs_lock);
model->setup_ctrs(model, msrs);
nmi_cpu_setup_mux(cpu, msrs);
- spin_unlock(&oprofilefs_lock);
+ raw_spin_unlock(&oprofilefs_lock);
per_cpu(saved_lvtpc, cpu) = apic_read(APIC_LVTPC);
apic_write(APIC_LVTPC, APIC_DM_NMI);
}
-static struct notifier_block profile_exceptions_nb = {
- .notifier_call = profile_exceptions_notify,
- .next = NULL,
- .priority = NMI_LOCAL_LOW_PRIOR,
-};
-
static void nmi_cpu_restore_registers(struct op_msrs *msrs)
{
struct op_msr *counters = msrs->counters;
@@ -402,8 +385,6 @@ static void nmi_cpu_shutdown(void *dummy)
apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu));
apic_write(APIC_LVTERR, v);
nmi_cpu_restore_registers(msrs);
- if (model->cpu_down)
- model->cpu_down();
}
static void nmi_cpu_up(void *dummy)
@@ -508,7 +489,8 @@ static int nmi_setup(void)
ctr_running = 0;
/* make variables visible to the nmi handler: */
smp_mb();
- err = register_die_notifier(&profile_exceptions_nb);
+ err = register_nmi_handler(NMI_LOCAL, profile_exceptions_notify,
+ 0, "oprofile");
if (err)
goto fail;
@@ -538,7 +520,7 @@ static void nmi_shutdown(void)
put_online_cpus();
/* make variables visible to the nmi handler: */
smp_mb();
- unregister_die_notifier(&profile_exceptions_nb);
+ unregister_nmi_handler(NMI_LOCAL, "oprofile");
msrs = &get_cpu_var(cpu_msrs);
model->shutdown(msrs);
free_msrs();
diff --git a/arch/x86/oprofile/nmi_timer_int.c b/arch/x86/oprofile/nmi_timer_int.c
index 720bf5a53c51..7f8052cd6620 100644
--- a/arch/x86/oprofile/nmi_timer_int.c
+++ b/arch/x86/oprofile/nmi_timer_int.c
@@ -18,32 +18,16 @@
#include <asm/apic.h>
#include <asm/ptrace.h>
-static int profile_timer_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data)
+static int profile_timer_exceptions_notify(unsigned int val, struct pt_regs *regs)
{
- struct die_args *args = (struct die_args *)data;
- int ret = NOTIFY_DONE;
-
- switch (val) {
- case DIE_NMI:
- oprofile_add_sample(args->regs, 0);
- ret = NOTIFY_STOP;
- break;
- default:
- break;
- }
- return ret;
+ oprofile_add_sample(regs, 0);
+ return NMI_HANDLED;
}
-static struct notifier_block profile_timer_exceptions_nb = {
- .notifier_call = profile_timer_exceptions_notify,
- .next = NULL,
- .priority = NMI_LOW_PRIOR,
-};
-
static int timer_start(void)
{
- if (register_die_notifier(&profile_timer_exceptions_nb))
+ if (register_nmi_handler(NMI_LOCAL, profile_timer_exceptions_notify,
+ 0, "oprofile-timer"))
return 1;
return 0;
}
@@ -51,7 +35,7 @@ static int timer_start(void)
static void timer_stop(void)
{
- unregister_die_notifier(&profile_timer_exceptions_nb);
+ unregister_nmi_handler(NMI_LOCAL, "oprofile-timer");
synchronize_sched(); /* Allow already-started NMIs to complete. */
}
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index 9cbb710dc94b..303f08637826 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -29,8 +29,6 @@
#include "op_x86_model.h"
#include "op_counter.h"
-#define NUM_COUNTERS 4
-#define NUM_COUNTERS_F15H 6
#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
#define NUM_VIRT_COUNTERS 32
#else
@@ -70,62 +68,12 @@ static struct ibs_config ibs_config;
static struct ibs_state ibs_state;
/*
- * IBS cpuid feature detection
- */
-
-#define IBS_CPUID_FEATURES 0x8000001b
-
-/*
- * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
- * bit 0 is used to indicate the existence of IBS.
- */
-#define IBS_CAPS_AVAIL (1U<<0)
-#define IBS_CAPS_FETCHSAM (1U<<1)
-#define IBS_CAPS_OPSAM (1U<<2)
-#define IBS_CAPS_RDWROPCNT (1U<<3)
-#define IBS_CAPS_OPCNT (1U<<4)
-#define IBS_CAPS_BRNTRGT (1U<<5)
-#define IBS_CAPS_OPCNTEXT (1U<<6)
-
-#define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \
- | IBS_CAPS_FETCHSAM \
- | IBS_CAPS_OPSAM)
-
-/*
- * IBS APIC setup
- */
-#define IBSCTL 0x1cc
-#define IBSCTL_LVT_OFFSET_VALID (1ULL<<8)
-#define IBSCTL_LVT_OFFSET_MASK 0x0F
-
-/*
* IBS randomization macros
*/
#define IBS_RANDOM_BITS 12
#define IBS_RANDOM_MASK ((1ULL << IBS_RANDOM_BITS) - 1)
#define IBS_RANDOM_MAXCNT_OFFSET (1ULL << (IBS_RANDOM_BITS - 5))
-static u32 get_ibs_caps(void)
-{
- u32 ibs_caps;
- unsigned int max_level;
-
- if (!boot_cpu_has(X86_FEATURE_IBS))
- return 0;
-
- /* check IBS cpuid feature flags */
- max_level = cpuid_eax(0x80000000);
- if (max_level < IBS_CPUID_FEATURES)
- return IBS_CAPS_DEFAULT;
-
- ibs_caps = cpuid_eax(IBS_CPUID_FEATURES);
- if (!(ibs_caps & IBS_CAPS_AVAIL))
- /* cpuid flags not valid */
- return IBS_CAPS_DEFAULT;
-
- return ibs_caps;
-}
-
/*
* 16-bit Linear Feedback Shift Register (LFSR)
*
@@ -316,81 +264,6 @@ static void op_amd_stop_ibs(void)
wrmsrl(MSR_AMD64_IBSOPCTL, 0);
}
-static inline int get_eilvt(int offset)
-{
- return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
-}
-
-static inline int put_eilvt(int offset)
-{
- return !setup_APIC_eilvt(offset, 0, 0, 1);
-}
-
-static inline int ibs_eilvt_valid(void)
-{
- int offset;
- u64 val;
- int valid = 0;
-
- preempt_disable();
-
- rdmsrl(MSR_AMD64_IBSCTL, val);
- offset = val & IBSCTL_LVT_OFFSET_MASK;
-
- if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
- pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
- smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
- goto out;
- }
-
- if (!get_eilvt(offset)) {
- pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
- smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
- goto out;
- }
-
- valid = 1;
-out:
- preempt_enable();
-
- return valid;
-}
-
-static inline int get_ibs_offset(void)
-{
- u64 val;
-
- rdmsrl(MSR_AMD64_IBSCTL, val);
- if (!(val & IBSCTL_LVT_OFFSET_VALID))
- return -EINVAL;
-
- return val & IBSCTL_LVT_OFFSET_MASK;
-}
-
-static void setup_APIC_ibs(void)
-{
- int offset;
-
- offset = get_ibs_offset();
- if (offset < 0)
- goto failed;
-
- if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
- return;
-failed:
- pr_warn("oprofile: IBS APIC setup failed on cpu #%d\n",
- smp_processor_id());
-}
-
-static void clear_APIC_ibs(void)
-{
- int offset;
-
- offset = get_ibs_offset();
- if (offset >= 0)
- setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
-}
-
#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
@@ -439,7 +312,7 @@ static int op_amd_fill_in_addresses(struct op_msrs * const msrs)
goto fail;
}
/* both registers must be reserved */
- if (num_counters == NUM_COUNTERS_F15H) {
+ if (num_counters == AMD64_NUM_COUNTERS_F15H) {
msrs->counters[i].addr = MSR_F15H_PERF_CTR + (i << 1);
msrs->controls[i].addr = MSR_F15H_PERF_CTL + (i << 1);
} else {
@@ -504,15 +377,6 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
val |= op_x86_get_ctrl(model, &counter_config[virt]);
wrmsrl(msrs->controls[i].addr, val);
}
-
- if (ibs_caps)
- setup_APIC_ibs();
-}
-
-static void op_amd_cpu_shutdown(void)
-{
- if (ibs_caps)
- clear_APIC_ibs();
}
static int op_amd_check_ctrs(struct pt_regs * const regs,
@@ -575,86 +439,6 @@ static void op_amd_stop(struct op_msrs const * const msrs)
op_amd_stop_ibs();
}
-static int setup_ibs_ctl(int ibs_eilvt_off)
-{
- struct pci_dev *cpu_cfg;
- int nodes;
- u32 value = 0;
-
- nodes = 0;
- cpu_cfg = NULL;
- do {
- cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD,
- PCI_DEVICE_ID_AMD_10H_NB_MISC,
- cpu_cfg);
- if (!cpu_cfg)
- break;
- ++nodes;
- pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
- | IBSCTL_LVT_OFFSET_VALID);
- pci_read_config_dword(cpu_cfg, IBSCTL, &value);
- if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
- pci_dev_put(cpu_cfg);
- printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
- "IBSCTL = 0x%08x\n", value);
- return -EINVAL;
- }
- } while (1);
-
- if (!nodes) {
- printk(KERN_DEBUG "No CPU node configured for IBS\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-/*
- * This runs only on the current cpu. We try to find an LVT offset and
- * setup the local APIC. For this we must disable preemption. On
- * success we initialize all nodes with this offset. This updates then
- * the offset in the IBS_CTL per-node msr. The per-core APIC setup of
- * the IBS interrupt vector is called from op_amd_setup_ctrs()/op_-
- * amd_cpu_shutdown() using the new offset.
- */
-static int force_ibs_eilvt_setup(void)
-{
- int offset;
- int ret;
-
- preempt_disable();
- /* find the next free available EILVT entry, skip offset 0 */
- for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
- if (get_eilvt(offset))
- break;
- }
- preempt_enable();
-
- if (offset == APIC_EILVT_NR_MAX) {
- printk(KERN_DEBUG "No EILVT entry available\n");
- return -EBUSY;
- }
-
- ret = setup_ibs_ctl(offset);
- if (ret)
- goto out;
-
- if (!ibs_eilvt_valid()) {
- ret = -EFAULT;
- goto out;
- }
-
- pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset);
- pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
-
- return 0;
-out:
- preempt_disable();
- put_eilvt(offset);
- preempt_enable();
- return ret;
-}
-
/*
* check and reserve APIC extended interrupt LVT offset for IBS if
* available
@@ -667,17 +451,6 @@ static void init_ibs(void)
if (!ibs_caps)
return;
- if (ibs_eilvt_valid())
- goto out;
-
- if (!force_ibs_eilvt_setup())
- goto out;
-
- /* Failed to setup ibs */
- ibs_caps = 0;
- return;
-
-out:
printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
}
@@ -741,9 +514,9 @@ static int op_amd_init(struct oprofile_operations *ops)
ops->create_files = setup_ibs_files;
if (boot_cpu_data.x86 == 0x15) {
- num_counters = NUM_COUNTERS_F15H;
+ num_counters = AMD64_NUM_COUNTERS_F15H;
} else {
- num_counters = NUM_COUNTERS;
+ num_counters = AMD64_NUM_COUNTERS;
}
op_amd_spec.num_counters = num_counters;
@@ -760,7 +533,6 @@ struct op_x86_model_spec op_amd_spec = {
.init = op_amd_init,
.fill_in_addresses = &op_amd_fill_in_addresses,
.setup_ctrs = &op_amd_setup_ctrs,
- .cpu_down = &op_amd_cpu_shutdown,
.check_ctrs = &op_amd_check_ctrs,
.start = &op_amd_start,
.stop = &op_amd_stop,
diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c
index 94b745045e45..d90528ea5412 100644
--- a/arch/x86/oprofile/op_model_ppro.c
+++ b/arch/x86/oprofile/op_model_ppro.c
@@ -28,7 +28,7 @@ static int counter_width = 32;
#define MSR_PPRO_EVENTSEL_RESERVED ((0xFFFFFFFFULL<<32)|(1ULL<<21))
-static u64 *reset_value;
+static u64 reset_value[OP_MAX_COUNTER];
static void ppro_shutdown(struct op_msrs const * const msrs)
{
@@ -40,10 +40,6 @@ static void ppro_shutdown(struct op_msrs const * const msrs)
release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
}
- if (reset_value) {
- kfree(reset_value);
- reset_value = NULL;
- }
}
static int ppro_fill_in_addresses(struct op_msrs * const msrs)
@@ -79,13 +75,6 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model,
u64 val;
int i;
- if (!reset_value) {
- reset_value = kzalloc(sizeof(reset_value[0]) * num_counters,
- GFP_ATOMIC);
- if (!reset_value)
- return;
- }
-
if (cpu_has_arch_perfmon) {
union cpuid10_eax eax;
eax.full = cpuid_eax(0xa);
@@ -141,13 +130,6 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
u64 val;
int i;
- /*
- * This can happen if perf counters are in use when
- * we steal the die notifier NMI.
- */
- if (unlikely(!reset_value))
- goto out;
-
for (i = 0; i < num_counters; ++i) {
if (!reset_value[i])
continue;
@@ -158,7 +140,6 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
wrmsrl(msrs->counters[i].addr, -reset_value[i]);
}
-out:
/* Only P6 based Pentium M need to re-unmask the apic vector but it
* doesn't hurt other P6 variant */
apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
@@ -179,8 +160,6 @@ static void ppro_start(struct op_msrs const * const msrs)
u64 val;
int i;
- if (!reset_value)
- return;
for (i = 0; i < num_counters; ++i) {
if (reset_value[i]) {
rdmsrl(msrs->controls[i].addr, val);
@@ -196,8 +175,6 @@ static void ppro_stop(struct op_msrs const * const msrs)
u64 val;
int i;
- if (!reset_value)
- return;
for (i = 0; i < num_counters; ++i) {
if (!reset_value[i])
continue;
@@ -242,7 +219,7 @@ static void arch_perfmon_setup_counters(void)
eax.split.bit_width = 40;
}
- num_counters = eax.split.num_counters;
+ num_counters = min((int)eax.split.num_counters, OP_MAX_COUNTER);
op_arch_perfmon_spec.num_counters = num_counters;
op_arch_perfmon_spec.num_controls = num_counters;
diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h
index 89017fa1fd63..71e8a67337e2 100644
--- a/arch/x86/oprofile/op_x86_model.h
+++ b/arch/x86/oprofile/op_x86_model.h
@@ -43,7 +43,6 @@ struct op_x86_model_spec {
int (*fill_in_addresses)(struct op_msrs * const msrs);
void (*setup_ctrs)(struct op_x86_model_spec const *model,
struct op_msrs const * const msrs);
- void (*cpu_down)(void);
int (*check_ctrs)(struct pt_regs * const regs,
struct op_msrs const * const msrs);
void (*start)(struct op_msrs const * const msrs);
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c
index 99176094500b..41bd2a2d2c50 100644
--- a/arch/x86/pci/ce4100.c
+++ b/arch/x86/pci/ce4100.c
@@ -304,7 +304,7 @@ static int ce4100_conf_write(unsigned int seg, unsigned int bus,
return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
}
-struct pci_raw_ops ce4100_pci_conf = {
+static const struct pci_raw_ops ce4100_pci_conf = {
.read = ce4100_conf_read,
.write = ce4100_conf_write,
};
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 92df322e0b57..7962ccb4d9b2 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -33,8 +33,8 @@ int noioapicreroute = 1;
int pcibios_last_bus = -1;
unsigned long pirq_table_addr;
struct pci_bus *pci_root_bus;
-struct pci_raw_ops *raw_pci_ops;
-struct pci_raw_ops *raw_pci_ext_ops;
+const struct pci_raw_ops *__read_mostly raw_pci_ops;
+const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 *val)
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c
index 4f2c70439d7f..15460590b8c5 100644
--- a/arch/x86/pci/direct.c
+++ b/arch/x86/pci/direct.c
@@ -79,7 +79,7 @@ static int pci_conf1_write(unsigned int seg, unsigned int bus,
#undef PCI_CONF1_ADDRESS
-struct pci_raw_ops pci_direct_conf1 = {
+const struct pci_raw_ops pci_direct_conf1 = {
.read = pci_conf1_read,
.write = pci_conf1_write,
};
@@ -175,7 +175,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus,
#undef PCI_CONF2_ADDRESS
-struct pci_raw_ops pci_direct_conf2 = {
+static const struct pci_raw_ops pci_direct_conf2 = {
.read = pci_conf2_read,
.write = pci_conf2_write,
};
@@ -191,7 +191,7 @@ struct pci_raw_ops pci_direct_conf2 = {
* This should be close to trivial, but it isn't, because there are buggy
* chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
*/
-static int __init pci_sanity_check(struct pci_raw_ops *o)
+static int __init pci_sanity_check(const struct pci_raw_ops *o)
{
u32 x = 0;
int year, devfn;
diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c
index a3d9c54792ae..5372e86834c0 100644
--- a/arch/x86/pci/mmconfig_32.c
+++ b/arch/x86/pci/mmconfig_32.c
@@ -117,7 +117,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
return 0;
}
-static struct pci_raw_ops pci_mmcfg = {
+static const struct pci_raw_ops pci_mmcfg = {
.read = pci_mmcfg_read,
.write = pci_mmcfg_write,
};
diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c
index e783841bd1d7..915a493502cb 100644
--- a/arch/x86/pci/mmconfig_64.c
+++ b/arch/x86/pci/mmconfig_64.c
@@ -81,7 +81,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
return 0;
}
-static struct pci_raw_ops pci_mmcfg = {
+static const struct pci_raw_ops pci_mmcfg = {
.read = pci_mmcfg_read,
.write = pci_mmcfg_write,
};
diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c
index 512a88c41501..51abf02f9226 100644
--- a/arch/x86/pci/numaq_32.c
+++ b/arch/x86/pci/numaq_32.c
@@ -110,7 +110,7 @@ static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
#undef PCI_CONF1_MQ_ADDRESS
-static struct pci_raw_ops pci_direct_conf1_mq = {
+static const struct pci_raw_ops pci_direct_conf1_mq = {
.read = pci_conf1_mq_read,
.write = pci_conf1_mq_write
};
diff --git a/arch/x86/pci/olpc.c b/arch/x86/pci/olpc.c
index 5262603b04d9..7043a4f0e98a 100644
--- a/arch/x86/pci/olpc.c
+++ b/arch/x86/pci/olpc.c
@@ -301,7 +301,7 @@ static int pci_olpc_write(unsigned int seg, unsigned int bus,
return 0;
}
-static struct pci_raw_ops pci_olpc_conf = {
+static const struct pci_raw_ops pci_olpc_conf = {
.read = pci_olpc_read,
.write = pci_olpc_write,
};
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c
index f68553551467..db0e9a51e611 100644
--- a/arch/x86/pci/pcbios.c
+++ b/arch/x86/pci/pcbios.c
@@ -303,7 +303,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
* Function table for BIOS32 access
*/
-static struct pci_raw_ops pci_bios_access = {
+static const struct pci_raw_ops pci_bios_access = {
.read = pci_bios_read,
.write = pci_bios_write
};
@@ -312,7 +312,7 @@ static struct pci_raw_ops pci_bios_access = {
* Try to find PCI BIOS.
*/
-static struct pci_raw_ops * __devinit pci_find_bios(void)
+static const struct pci_raw_ops * __devinit pci_find_bios(void)
{
union bios32 *check;
unsigned char sum;
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 1017c7bee388..492ade8c978e 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -175,8 +175,10 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
"pcifront-msi-x" :
"pcifront-msi",
DOMID_SELF);
- if (irq < 0)
+ if (irq < 0) {
+ ret = irq;
goto free;
+ }
i++;
}
kfree(v);
@@ -221,8 +223,10 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
if (msg.data != XEN_PIRQ_MSI_DATA ||
xen_irq_from_pirq(pirq) < 0) {
pirq = xen_allocate_pirq_msi(dev, msidesc);
- if (pirq < 0)
+ if (pirq < 0) {
+ irq = -ENODEV;
goto error;
+ }
xen_msi_compose_msg(dev, pirq, &msg);
__write_msi_msg(msidesc, &msg);
dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
@@ -244,10 +248,12 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
error:
dev_err(&dev->dev,
"Xen PCI frontend has not registered MSI/MSI-X support!\n");
- return -ENODEV;
+ return irq;
}
#ifdef CONFIG_XEN_DOM0
+static bool __read_mostly pci_seg_supported = true;
+
static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
int ret = 0;
@@ -265,10 +271,11 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
memset(&map_irq, 0, sizeof(map_irq));
map_irq.domid = domid;
- map_irq.type = MAP_PIRQ_TYPE_MSI;
+ map_irq.type = MAP_PIRQ_TYPE_MSI_SEG;
map_irq.index = -1;
map_irq.pirq = -1;
- map_irq.bus = dev->bus->number;
+ map_irq.bus = dev->bus->number |
+ (pci_domain_nr(dev->bus) << 16);
map_irq.devfn = dev->devfn;
if (type == PCI_CAP_ID_MSIX) {
@@ -285,7 +292,20 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
}
- ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
+ ret = -EINVAL;
+ if (pci_seg_supported)
+ ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
+ &map_irq);
+ if (ret == -EINVAL && !pci_domain_nr(dev->bus)) {
+ map_irq.type = MAP_PIRQ_TYPE_MSI;
+ map_irq.index = -1;
+ map_irq.pirq = -1;
+ map_irq.bus = dev->bus->number;
+ ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
+ &map_irq);
+ if (ret != -EINVAL)
+ pci_seg_supported = false;
+ }
if (ret) {
dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n",
ret, domid);
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile
index 021eee91c056..8d874396cb29 100644
--- a/arch/x86/platform/Makefile
+++ b/arch/x86/platform/Makefile
@@ -1,6 +1,7 @@
# Platform specific code goes here
obj-y += ce4100/
obj-y += efi/
+obj-y += geode/
obj-y += iris/
obj-y += mrst/
obj-y += olpc/
diff --git a/arch/x86/platform/geode/Makefile b/arch/x86/platform/geode/Makefile
new file mode 100644
index 000000000000..07c9cd05021a
--- /dev/null
+++ b/arch/x86/platform/geode/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ALIX) += alix.o
diff --git a/arch/x86/platform/geode/alix.c b/arch/x86/platform/geode/alix.c
new file mode 100644
index 000000000000..ca1973699d3d
--- /dev/null
+++ b/arch/x86/platform/geode/alix.c
@@ -0,0 +1,142 @@
+/*
+ * System Specific setup for PCEngines ALIX.
+ * At the moment this means setup of GPIO control of LEDs
+ * on Alix.2/3/6 boards.
+ *
+ *
+ * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
+ * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
+ *
+ * TODO: There are large similarities with leds-net5501.c
+ * by Alessandro Zummo <a.zummo@towertech.it>
+ * In the future leds-net5501.c should be migrated over to platform
+ *
+ * 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/io.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/geode.h>
+
+static int force = 0;
+module_param(force, bool, 0444);
+/* FIXME: Award bios is not automatically detected as Alix platform */
+MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform");
+
+static struct gpio_led alix_leds[] = {
+ {
+ .name = "alix:1",
+ .gpio = 6,
+ .default_trigger = "default-on",
+ .active_low = 1,
+ },
+ {
+ .name = "alix:2",
+ .gpio = 25,
+ .default_trigger = "default-off",
+ .active_low = 1,
+ },
+ {
+ .name = "alix:3",
+ .gpio = 27,
+ .default_trigger = "default-off",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data alix_leds_data = {
+ .num_leds = ARRAY_SIZE(alix_leds),
+ .leds = alix_leds,
+};
+
+static struct platform_device alix_leds_dev = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev.platform_data = &alix_leds_data,
+};
+
+static void __init register_alix(void)
+{
+ /* Setup LED control through leds-gpio driver */
+ platform_device_register(&alix_leds_dev);
+}
+
+static int __init alix_present(unsigned long bios_phys,
+ const char *alix_sig,
+ size_t alix_sig_len)
+{
+ const size_t bios_len = 0x00010000;
+ const char *bios_virt;
+ const char *scan_end;
+ const char *p;
+ char name[64];
+
+ if (force) {
+ printk(KERN_NOTICE "%s: forced to skip BIOS test, "
+ "assume system is ALIX.2/ALIX.3\n",
+ KBUILD_MODNAME);
+ return 1;
+ }
+
+ bios_virt = phys_to_virt(bios_phys);
+ scan_end = bios_virt + bios_len - (alix_sig_len + 2);
+ for (p = bios_virt; p < scan_end; p++) {
+ const char *tail;
+ char *a;
+
+ if (memcmp(p, alix_sig, alix_sig_len) != 0)
+ continue;
+
+ memcpy(name, p, sizeof(name));
+
+ /* remove the first \0 character from string */
+ a = strchr(name, '\0');
+ if (a)
+ *a = ' ';
+
+ /* cut the string at a newline */
+ a = strchr(name, '\r');
+ if (a)
+ *a = '\0';
+
+ tail = p + alix_sig_len;
+ if ((tail[0] == '2' || tail[0] == '3')) {
+ printk(KERN_INFO
+ "%s: system is recognized as \"%s\"\n",
+ KBUILD_MODNAME, name);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int __init alix_init(void)
+{
+ const char tinybios_sig[] = "PC Engines ALIX.";
+ const char coreboot_sig[] = "PC Engines\0ALIX.";
+
+ if (!is_geode())
+ return 0;
+
+ if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
+ alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
+ register_alix();
+
+ return 0;
+}
+
+module_init(alix_init);
+
+MODULE_AUTHOR("Ed Wildgoose <kernel@wildgooses.com>");
+MODULE_DESCRIPTION("PCEngines ALIX System Setup");
+MODULE_LICENSE("GPL");
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
index 8a7cb3259562..6ed7afdaf4af 100644
--- a/arch/x86/platform/mrst/mrst.c
+++ b/arch/x86/platform/mrst/mrst.c
@@ -14,6 +14,8 @@
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
#include <linux/sfi.h>
#include <linux/intel_pmic_gpio.h>
#include <linux/spi/spi.h>
@@ -394,6 +396,7 @@ static void __init *max3111_platform_data(void *info)
struct spi_board_info *spi_info = info;
int intr = get_gpio_by_name("max3111_int");
+ spi_info->mode = SPI_MODE_0;
if (intr == -1)
return NULL;
spi_info->irq = intr + MRST_IRQ_OFFSET;
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index db8b915f54bc..5b552198f774 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -115,9 +115,6 @@ early_param("nobau", setup_nobau);
/* base pnode in this partition */
static int uv_base_pnode __read_mostly;
-/* position of pnode (which is nasid>>1): */
-static int uv_nshift __read_mostly;
-static unsigned long uv_mmask __read_mostly;
static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
static DEFINE_PER_CPU(struct bau_control, bau_control);
@@ -1435,7 +1432,7 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
{
int i;
int cpu;
- unsigned long pa;
+ unsigned long gpa;
unsigned long m;
unsigned long n;
size_t dsize;
@@ -1451,9 +1448,9 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
bau_desc = kmalloc_node(dsize, GFP_KERNEL, node);
BUG_ON(!bau_desc);
- pa = uv_gpa(bau_desc); /* need the real nasid*/
- n = pa >> uv_nshift;
- m = pa & uv_mmask;
+ gpa = uv_gpa(bau_desc);
+ n = uv_gpa_to_gnode(gpa);
+ m = uv_gpa_to_offset(gpa);
/* the 14-bit pnode */
write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m));
@@ -1525,9 +1522,9 @@ static void pq_init(int node, int pnode)
bcp->queue_last = pqp + (DEST_Q_SIZE - 1);
}
/*
- * need the pnode of where the memory was really allocated
+ * need the gnode of where the memory was really allocated
*/
- pn = uv_gpa(pqp) >> uv_nshift;
+ pn = uv_gpa_to_gnode(uv_gpa(pqp));
first = uv_physnodeaddr(pqp);
pn_first = ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | first;
last = uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1));
@@ -1837,8 +1834,6 @@ static int __init uv_bau_init(void)
zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
}
- uv_nshift = uv_hub_info->m_val;
- uv_mmask = (1UL << uv_hub_info->m_val) - 1;
nuvhubs = uv_num_possible_blades();
spin_lock_init(&disable_lock);
congested_cycles = usec_2_cycles(congested_respns_us);
diff --git a/arch/um/Kconfig.x86 b/arch/x86/um/Kconfig
index 21bebe63df66..21bebe63df66 100644
--- a/arch/um/Kconfig.x86
+++ b/arch/x86/um/Kconfig
diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile
new file mode 100644
index 000000000000..8fb58400e415
--- /dev/null
+++ b/arch/x86/um/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+#
+
+ifeq ($(CONFIG_X86_32),y)
+ BITS := 32
+else
+ BITS := 64
+endif
+
+obj-y = bug.o bugs_$(BITS).o delay.o fault.o ksyms.o ldt.o \
+ ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \
+ stub_$(BITS).o stub_segv.o syscalls_$(BITS).o \
+ sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \
+ mem_$(BITS).o subarch.o os-$(OS)/
+
+ifeq ($(CONFIG_X86_32),y)
+
+obj-y += checksum_32.o
+obj-$(CONFIG_BINFMT_ELF) += elfcore.o
+
+subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
+subarch-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += ../lib/rwsem.o
+subarch-$(CONFIG_HIGHMEM) += ../mm/highmem_32.o
+
+else
+
+obj-y += vdso/
+
+subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../lib/thunk_64.o \
+ ../lib/rwsem.o
+
+endif
+
+subarch-$(CONFIG_MODULES) += ../kernel/module.o
+
+USER_OBJS := bugs_$(BITS).o ptrace_user.o fault.o
+
+extra-y += user-offsets.s
+$(obj)/user-offsets.s: c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS)
+
+UNPROFILE_OBJS := stub_segv.o
+CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
+
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/include/asm/apic.h b/arch/x86/um/asm/apic.h
index 876dee84ab11..876dee84ab11 100644
--- a/arch/um/include/asm/apic.h
+++ b/arch/x86/um/asm/apic.h
diff --git a/arch/um/include/asm/arch_hweight.h b/arch/x86/um/asm/arch_hweight.h
index c656cf443f4a..c656cf443f4a 100644
--- a/arch/um/include/asm/arch_hweight.h
+++ b/arch/x86/um/asm/arch_hweight.h
diff --git a/arch/um/sys-i386/asm/archparam.h b/arch/x86/um/asm/archparam.h
index 2a18a884ca1b..c17cf68dda0f 100644
--- a/arch/um/sys-i386/asm/archparam.h
+++ b/arch/x86/um/asm/archparam.h
@@ -1,10 +1,13 @@
/*
* Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright 2003 PathScale, Inc.
* Licensed under the GPL
*/
-#ifndef __UM_ARCHPARAM_I386_H
-#define __UM_ARCHPARAM_I386_H
+#ifndef __UM_ARCHPARAM_H
+#define __UM_ARCHPARAM_H
+
+#ifdef CONFIG_X86_32
#ifdef CONFIG_X86_PAE
#define LAST_PKMAP 512
@@ -14,3 +17,4 @@
#endif
+#endif
diff --git a/arch/x86/um/asm/checksum.h b/arch/x86/um/asm/checksum.h
new file mode 100644
index 000000000000..b6efe2381b5d
--- /dev/null
+++ b/arch/x86/um/asm/checksum.h
@@ -0,0 +1,10 @@
+#ifndef __UM_CHECKSUM_H
+#define __UM_CHECKSUM_H
+
+#ifdef CONFIG_X86_32
+# include "checksum_32.h"
+#else
+# include "checksum_64.h"
+#endif
+
+#endif
diff --git a/arch/um/sys-i386/shared/sysdep/checksum.h b/arch/x86/um/asm/checksum_32.h
index ed47445f3905..caab74252e27 100644
--- a/arch/um/sys-i386/shared/sysdep/checksum.h
+++ b/arch/x86/um/asm/checksum_32.h
@@ -1,4 +1,4 @@
-/*
+/*
* Licensed under the GPL
*/
diff --git a/arch/um/sys-x86_64/shared/sysdep/checksum.h b/arch/x86/um/asm/checksum_64.h
index a5be9031ea85..a5be9031ea85 100644
--- a/arch/um/sys-x86_64/shared/sysdep/checksum.h
+++ b/arch/x86/um/asm/checksum_64.h
diff --git a/arch/um/include/asm/desc.h b/arch/x86/um/asm/desc.h
index 4ec34a51b62c..4ec34a51b62c 100644
--- a/arch/um/include/asm/desc.h
+++ b/arch/x86/um/asm/desc.h
diff --git a/arch/um/sys-x86_64/asm/elf.h b/arch/x86/um/asm/elf.h
index 11a2bfb38859..f3b0633b69a1 100644
--- a/arch/um/sys-x86_64/asm/elf.h
+++ b/arch/x86/um/asm/elf.h
@@ -1,15 +1,103 @@
/*
- * Copyright 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- *
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#ifndef __UM_ELF_X86_64_H
-#define __UM_ELF_X86_64_H
+#ifndef __UM_ELF_X86_H
+#define __UM_ELF_X86_H
#include <asm/user.h>
#include "skas.h"
+#ifdef CONFIG_X86_32
+
+#define R_386_NONE 0
+#define R_386_32 1
+#define R_386_PC32 2
+#define R_386_GOT32 3
+#define R_386_PLT32 4
+#define R_386_COPY 5
+#define R_386_GLOB_DAT 6
+#define R_386_JMP_SLOT 7
+#define R_386_RELATIVE 8
+#define R_386_GOTOFF 9
+#define R_386_GOTPC 10
+#define R_386_NUM 11
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+ (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2LSB
+#define ELF_ARCH EM_386
+
+#define ELF_PLAT_INIT(regs, load_addr) do { \
+ PT_REGS_EBX(regs) = 0; \
+ PT_REGS_ECX(regs) = 0; \
+ PT_REGS_EDX(regs) = 0; \
+ PT_REGS_ESI(regs) = 0; \
+ PT_REGS_EDI(regs) = 0; \
+ PT_REGS_EBP(regs) = 0; \
+ PT_REGS_EAX(regs) = 0; \
+} while (0)
+
+/* Shamelessly stolen from include/asm-i386/elf.h */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \
+ pr_reg[0] = PT_REGS_EBX(regs); \
+ pr_reg[1] = PT_REGS_ECX(regs); \
+ pr_reg[2] = PT_REGS_EDX(regs); \
+ pr_reg[3] = PT_REGS_ESI(regs); \
+ pr_reg[4] = PT_REGS_EDI(regs); \
+ pr_reg[5] = PT_REGS_EBP(regs); \
+ pr_reg[6] = PT_REGS_EAX(regs); \
+ pr_reg[7] = PT_REGS_DS(regs); \
+ pr_reg[8] = PT_REGS_ES(regs); \
+ /* fake once used fs and gs selectors? */ \
+ pr_reg[9] = PT_REGS_DS(regs); \
+ pr_reg[10] = PT_REGS_DS(regs); \
+ pr_reg[11] = PT_REGS_SYSCALL_NR(regs); \
+ pr_reg[12] = PT_REGS_IP(regs); \
+ pr_reg[13] = PT_REGS_CS(regs); \
+ pr_reg[14] = PT_REGS_EFLAGS(regs); \
+ pr_reg[15] = PT_REGS_SP(regs); \
+ pr_reg[16] = PT_REGS_SS(regs); \
+} while (0);
+
+extern char * elf_aux_platform;
+#define ELF_PLATFORM (elf_aux_platform)
+
+extern unsigned long vsyscall_ehdr;
+extern unsigned long vsyscall_end;
+extern unsigned long __kernel_vsyscall;
+
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START vsyscall_ehdr
+#define FIXADDR_USER_END vsyscall_end
+
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO 32
+#define AT_SYSINFO_EHDR 33
+
+#define ARCH_DLINFO \
+do { \
+ if ( vsyscall_ehdr ) { \
+ NEW_AUX_ENT(AT_SYSINFO, __kernel_vsyscall); \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr); \
+ } \
+} while (0)
+
+#else
+
/* x86-64 relocation types, taken from asm-x86_64/elf.h */
#define R_X86_64_NONE 0 /* No reloc */
#define R_X86_64_64 1 /* Direct 64 bit */
@@ -31,13 +119,6 @@
#define R_X86_64_NUM 16
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_i387_struct elf_fpregset_t;
-
/*
* This is used to ensure we don't load something for the wrong architecture.
*/
@@ -95,6 +176,30 @@ typedef struct user_i387_struct elf_fpregset_t;
(pr_reg)[25] = 0; \
(pr_reg)[26] = 0;
+#define ELF_PLATFORM "x86_64"
+
+/* No user-accessible fixmap addresses, i.e. vsyscall */
+#define FIXADDR_USER_START 0
+#define FIXADDR_USER_END 0
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+ int uses_interp);
+
+extern unsigned long um_vdso_addr;
+#define AT_SYSINFO_EHDR 33
+#define ARCH_DLINFO NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
+
+#endif
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_i387_struct elf_fpregset_t;
+
#define task_pt_regs(t) (&(t)->thread.regs)
struct task_struct;
@@ -103,11 +208,6 @@ extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
-#ifdef TIF_IA32 /* XXX */
-#error XXX, indeed
- clear_thread_flag(TIF_IA32);
-#endif
-
#define ELF_EXEC_PAGESIZE 4096
#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
@@ -115,18 +215,7 @@ extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
extern long elf_aux_hwcap;
#define ELF_HWCAP (elf_aux_hwcap)
-#define ELF_PLATFORM "x86_64"
-
#define SET_PERSONALITY(ex) do ; while(0)
-
#define __HAVE_ARCH_GATE_AREA 1
-#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
-struct linux_binprm;
-extern int arch_setup_additional_pages(struct linux_binprm *bprm,
- int uses_interp);
-
-extern unsigned long um_vdso_addr;
-#define AT_SYSINFO_EHDR 33
-#define ARCH_DLINFO NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
#endif
diff --git a/arch/um/include/asm/irq_vectors.h b/arch/x86/um/asm/irq_vectors.h
index 272a81e0ce14..272a81e0ce14 100644
--- a/arch/um/include/asm/irq_vectors.h
+++ b/arch/x86/um/asm/irq_vectors.h
diff --git a/arch/x86/um/asm/mm_context.h b/arch/x86/um/asm/mm_context.h
new file mode 100644
index 000000000000..4a73d63e4760
--- /dev/null
+++ b/arch/x86/um/asm/mm_context.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Licensed under the GPL
+ *
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ */
+
+#ifndef __ASM_LDT_H
+#define __ASM_LDT_H
+
+#include <linux/mutex.h>
+#include <asm/ldt.h>
+
+extern void ldt_host_info(void);
+
+#define LDT_PAGES_MAX \
+ ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
+#define LDT_ENTRIES_PER_PAGE \
+ (PAGE_SIZE/LDT_ENTRY_SIZE)
+#define LDT_DIRECT_ENTRIES \
+ ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
+
+struct ldt_entry {
+ __u32 a;
+ __u32 b;
+};
+
+typedef struct uml_ldt {
+ int entry_count;
+ struct mutex lock;
+ union {
+ struct ldt_entry * pages[LDT_PAGES_MAX];
+ struct ldt_entry entries[LDT_DIRECT_ENTRIES];
+ } u;
+} uml_ldt_t;
+
+#define LDT_entry_a(info) \
+ ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+
+#define LDT_entry_b(info) \
+ (((info)->base_addr & 0xff000000) | \
+ (((info)->base_addr & 0x00ff0000) >> 16) | \
+ ((info)->limit & 0xf0000) | \
+ (((info)->read_exec_only ^ 1) << 9) | \
+ ((info)->contents << 10) | \
+ (((info)->seg_not_present ^ 1) << 15) | \
+ ((info)->seg_32bit << 22) | \
+ ((info)->limit_in_pages << 23) | \
+ ((info)->useable << 20) | \
+ 0x7000)
+
+#define _LDT_empty(info) (\
+ (info)->base_addr == 0 && \
+ (info)->limit == 0 && \
+ (info)->contents == 0 && \
+ (info)->read_exec_only == 1 && \
+ (info)->seg_32bit == 0 && \
+ (info)->limit_in_pages == 0 && \
+ (info)->seg_not_present == 1 && \
+ (info)->useable == 0 )
+
+#ifdef CONFIG_X86_64
+#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+#else
+#define LDT_empty(info) (_LDT_empty(info))
+#endif
+
+struct uml_arch_mm_context {
+ uml_ldt_t ldt;
+};
+
+#endif
diff --git a/arch/x86/um/asm/module.h b/arch/x86/um/asm/module.h
new file mode 100644
index 000000000000..61af80e932eb
--- /dev/null
+++ b/arch/x86/um/asm/module.h
@@ -0,0 +1,23 @@
+#ifndef __UM_MODULE_H
+#define __UM_MODULE_H
+
+/* UML is simple */
+struct mod_arch_specific
+{
+};
+
+#ifdef CONFIG_X86_32
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#else
+
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Ehdr Elf64_Ehdr
+
+#endif
+
+#endif
diff --git a/arch/x86/um/asm/processor.h b/arch/x86/um/asm/processor.h
new file mode 100644
index 000000000000..118c143a9cb4
--- /dev/null
+++ b/arch/x86/um/asm/processor.h
@@ -0,0 +1,22 @@
+#ifndef __UM_PROCESSOR_H
+#define __UM_PROCESSOR_H
+
+/* include faultinfo structure */
+#include <sysdep/faultinfo.h>
+
+#ifdef CONFIG_X86_32
+# include "processor_32.h"
+#else
+# include "processor_64.h"
+#endif
+
+#define KSTK_EIP(tsk) KSTK_REG(tsk, HOST_IP)
+#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_IP)
+#define KSTK_EBP(tsk) KSTK_REG(tsk, HOST_BP)
+
+#define ARCH_IS_STACKGROW(address) \
+ (address + 65536 + 32 * sizeof(unsigned long) >= UPT_SP(&current->thread.regs.regs))
+
+#include <asm/processor-generic.h>
+
+#endif
diff --git a/arch/um/sys-i386/asm/processor.h b/arch/x86/um/asm/processor_32.h
index 82a9061ab5be..018f732704dd 100644
--- a/arch/um/sys-i386/asm/processor.h
+++ b/arch/x86/um/asm/processor_32.h
@@ -6,15 +6,12 @@
#ifndef __UM_PROCESSOR_I386_H
#define __UM_PROCESSOR_I386_H
-#include "linux/string.h"
-#include <sysdep/host_ldt.h>
-#include "asm/segment.h"
+#include <linux/string.h>
+#include <asm/segment.h>
+#include <asm/ldt.h>
extern int host_has_cmov;
-/* include faultinfo structure */
-#include "sysdep/faultinfo.h"
-
struct uml_tls_struct {
struct user_desc tls;
unsigned flushed:1;
@@ -66,13 +63,4 @@ static inline void rep_nop(void)
#define current_text_addr() \
({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
-#define ARCH_IS_STACKGROW(address) \
- (address + 32 >= UPT_SP(&current->thread.regs.regs))
-
-#define KSTK_EIP(tsk) KSTK_REG(tsk, EIP)
-#define KSTK_ESP(tsk) KSTK_REG(tsk, UESP)
-#define KSTK_EBP(tsk) KSTK_REG(tsk, EBP)
-
-#include "asm/processor-generic.h"
-
#endif
diff --git a/arch/um/sys-x86_64/asm/processor.h b/arch/x86/um/asm/processor_64.h
index 875a26a62614..61de92d916c3 100644
--- a/arch/um/sys-x86_64/asm/processor.h
+++ b/arch/x86/um/asm/processor_64.h
@@ -7,9 +7,6 @@
#ifndef __UM_PROCESSOR_X86_64_H
#define __UM_PROCESSOR_X86_64_H
-/* include faultinfo structure */
-#include "sysdep/faultinfo.h"
-
struct arch_thread {
unsigned long debugregs[8];
int debugregs_seq;
@@ -45,12 +42,4 @@ static inline void arch_copy_thread(struct arch_thread *from,
#define current_text_addr() \
({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; })
-#define ARCH_IS_STACKGROW(address) \
- (address + 128 >= UPT_SP(&current->thread.regs.regs))
-
-#define KSTK_EIP(tsk) KSTK_REG(tsk, RIP)
-#define KSTK_ESP(tsk) KSTK_REG(tsk, RSP)
-
-#include "asm/processor-generic.h"
-
#endif
diff --git a/arch/x86/um/asm/ptrace.h b/arch/x86/um/asm/ptrace.h
new file mode 100644
index 000000000000..c8aca8c501b0
--- /dev/null
+++ b/arch/x86/um/asm/ptrace.h
@@ -0,0 +1,5 @@
+#ifdef CONFIG_X86_32
+# include "ptrace_32.h"
+#else
+# include "ptrace_64.h"
+#endif
diff --git a/arch/um/sys-i386/asm/ptrace.h b/arch/x86/um/asm/ptrace_32.h
index 5d2a59112537..5d2a59112537 100644
--- a/arch/um/sys-i386/asm/ptrace.h
+++ b/arch/x86/um/asm/ptrace_32.h
diff --git a/arch/um/sys-x86_64/asm/ptrace.h b/arch/x86/um/asm/ptrace_64.h
index 83d8c473b905..706a0d80545c 100644
--- a/arch/um/sys-x86_64/asm/ptrace.h
+++ b/arch/x86/um/asm/ptrace_64.h
@@ -40,7 +40,7 @@
#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs)
#define PT_REGS_RIP(r) UPT_IP(&(r)->regs)
-#define PT_REGS_RSP(r) UPT_SP(&(r)->regs)
+#define PT_REGS_SP(r) UPT_SP(&(r)->regs)
#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
diff --git a/arch/um/include/asm/required-features.h b/arch/x86/um/asm/required-features.h
index dfb967b2d2f3..dfb967b2d2f3 100644
--- a/arch/um/include/asm/required-features.h
+++ b/arch/x86/um/asm/required-features.h
diff --git a/arch/um/include/asm/segment.h b/arch/x86/um/asm/segment.h
index 45183fcd10b6..45183fcd10b6 100644
--- a/arch/um/include/asm/segment.h
+++ b/arch/x86/um/asm/segment.h
diff --git a/arch/um/sys-x86_64/shared/sysdep/system.h b/arch/x86/um/asm/system.h
index d1b93c436200..a459fd9b7598 100644
--- a/arch/um/sys-x86_64/shared/sysdep/system.h
+++ b/arch/x86/um/asm/system.h
@@ -129,4 +129,7 @@ static inline void rdtsc_barrier(void)
alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
}
+extern void *_switch_to(void *prev, void *next, void *last);
+#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
+
#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h b/arch/x86/um/asm/vm-flags.h
index 3978e55132d2..7c297e9e2413 100644
--- a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
+++ b/arch/x86/um/asm/vm-flags.h
@@ -4,8 +4,17 @@
* Licensed under the GPL
*/
-#ifndef __VM_FLAGS_X86_64_H
-#define __VM_FLAGS_X86_64_H
+#ifndef __VM_FLAGS_X86_H
+#define __VM_FLAGS_X86_H
+
+#ifdef CONFIG_X86_32
+
+#define VM_DATA_DEFAULT_FLAGS \
+ (VM_READ | VM_WRITE | \
+ ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#else
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
@@ -13,3 +22,4 @@
VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#endif
+#endif
diff --git a/arch/um/sys-x86_64/bug.c b/arch/x86/um/bug.c
index e8034e363d83..e8034e363d83 100644
--- a/arch/um/sys-x86_64/bug.c
+++ b/arch/x86/um/bug.c
diff --git a/arch/um/sys-i386/bugs.c b/arch/x86/um/bugs_32.c
index 2c6d0d731c12..a1fba5fb9dbe 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/x86/um/bugs_32.c
@@ -4,17 +4,17 @@
*/
#include <signal.h>
-#include "kern_constants.h"
#include "kern_util.h"
#include "longjmp.h"
-#include "task.h"
-#include "user.h"
#include "sysdep/ptrace.h"
+#include <generated/asm-offsets.h>
/* Set during early boot */
static int host_has_cmov = 1;
static jmp_buf cmov_test_return;
+#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
+
static void cmov_sigill_test_handler(int sig)
{
host_has_cmov = 0;
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/x86/um/bugs_64.c
index 44e02ba2a265..44e02ba2a265 100644
--- a/arch/um/sys-x86_64/bugs.c
+++ b/arch/x86/um/bugs_64.c
diff --git a/arch/um/sys-i386/checksum.S b/arch/x86/um/checksum_32.S
index f058d2f82e18..f058d2f82e18 100644
--- a/arch/um/sys-i386/checksum.S
+++ b/arch/x86/um/checksum_32.S
diff --git a/arch/um/sys-i386/delay.c b/arch/x86/um/delay.c
index f3fe1a688f7e..f3fe1a688f7e 100644
--- a/arch/um/sys-i386/delay.c
+++ b/arch/x86/um/delay.c
diff --git a/arch/um/sys-i386/elfcore.c b/arch/x86/um/elfcore.c
index 6bb49b687c97..6bb49b687c97 100644
--- a/arch/um/sys-i386/elfcore.c
+++ b/arch/x86/um/elfcore.c
diff --git a/arch/um/sys-i386/fault.c b/arch/x86/um/fault.c
index d670f68532f4..d670f68532f4 100644
--- a/arch/um/sys-i386/fault.c
+++ b/arch/x86/um/fault.c
diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/x86/um/ksyms.c
index 1db2fce00948..2e8f43ec6214 100644
--- a/arch/um/sys-x86_64/ksyms.c
+++ b/arch/x86/um/ksyms.c
@@ -2,10 +2,12 @@
#include <asm/string.h>
#include <asm/checksum.h>
+#ifndef CONFIG_X86_32
/*XXX: we need them because they would be exported by x86_64 */
#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
EXPORT_SYMBOL(memcpy);
#else
EXPORT_SYMBOL(__memcpy);
#endif
+#endif
EXPORT_SYMBOL(csum_partial);
diff --git a/arch/um/sys-i386/ldt.c b/arch/x86/um/ldt.c
index 3f2bf208d884..26b0e39d2ce9 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/x86/um/ldt.c
@@ -137,7 +137,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
{
int i, err = 0;
unsigned long size;
- uml_ldt_t * ldt = &current->mm->context.ldt;
+ uml_ldt_t *ldt = &current->mm->context.arch.ldt;
if (!ldt->entry_count)
goto out;
@@ -205,7 +205,7 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount)
static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
{
- uml_ldt_t * ldt = &current->mm->context.ldt;
+ uml_ldt_t *ldt = &current->mm->context.arch.ldt;
struct mm_id * mm_idp = &current->mm->context.id;
int i, err;
struct user_desc ldt_info;
@@ -397,7 +397,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
if (!ptrace_ldt)
- mutex_init(&new_mm->ldt.lock);
+ mutex_init(&new_mm->arch.ldt.lock);
if (!from_mm) {
memset(&desc, 0, sizeof(desc));
@@ -429,7 +429,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
break;
}
}
- new_mm->ldt.entry_count = 0;
+ new_mm->arch.ldt.entry_count = 0;
goto out;
}
@@ -457,26 +457,26 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
* i.e., we have to use the stub for modify_ldt, which
* can't handle the big read buffer of up to 64kB.
*/
- mutex_lock(&from_mm->ldt.lock);
- if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
- memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
- sizeof(new_mm->ldt.u.entries));
+ mutex_lock(&from_mm->arch.ldt.lock);
+ if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES)
+ memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries,
+ sizeof(new_mm->arch.ldt.u.entries));
else {
- i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+ i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
while (i-->0) {
page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
if (!page) {
err = -ENOMEM;
break;
}
- new_mm->ldt.u.pages[i] =
+ new_mm->arch.ldt.u.pages[i] =
(struct ldt_entry *) page;
- memcpy(new_mm->ldt.u.pages[i],
- from_mm->ldt.u.pages[i], PAGE_SIZE);
+ memcpy(new_mm->arch.ldt.u.pages[i],
+ from_mm->arch.ldt.u.pages[i], PAGE_SIZE);
}
}
- new_mm->ldt.entry_count = from_mm->ldt.entry_count;
- mutex_unlock(&from_mm->ldt.lock);
+ new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count;
+ mutex_unlock(&from_mm->arch.ldt.lock);
}
out:
@@ -488,12 +488,12 @@ void free_ldt(struct mm_context *mm)
{
int i;
- if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) {
- i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+ if (!ptrace_ldt && mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) {
+ i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
while (i-- > 0)
- free_page((long) mm->ldt.u.pages[i]);
+ free_page((long) mm->arch.ldt.u.pages[i]);
}
- mm->ldt.entry_count = 0;
+ mm->arch.ldt.entry_count = 0;
}
int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
diff --git a/arch/um/sys-i386/mem.c b/arch/x86/um/mem_32.c
index 639900a6fde9..639900a6fde9 100644
--- a/arch/um/sys-i386/mem.c
+++ b/arch/x86/um/mem_32.c
diff --git a/arch/um/sys-x86_64/mem.c b/arch/x86/um/mem_64.c
index 546518727a73..546518727a73 100644
--- a/arch/um/sys-x86_64/mem.c
+++ b/arch/x86/um/mem_64.c
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/x86/um/os-Linux/Makefile
index b4bc6ac4f30b..253bfb8cb702 100644
--- a/arch/um/os-Linux/sys-i386/Makefile
+++ b/arch/x86/um/os-Linux/Makefile
@@ -3,7 +3,10 @@
# Licensed under the GPL
#
-obj-y = registers.o signal.o task_size.o tls.o
+obj-y = registers.o task_size.o mcontext.o
+
+obj-$(CONFIG_X86_32) += tls.o
+obj-$(CONFIG_64BIT) += prctl.o
USER_OBJS := $(obj-y)
diff --git a/arch/x86/um/os-Linux/mcontext.c b/arch/x86/um/os-Linux/mcontext.c
new file mode 100644
index 000000000000..1d33d72c6284
--- /dev/null
+++ b/arch/x86/um/os-Linux/mcontext.c
@@ -0,0 +1,31 @@
+#include <sys/ucontext.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <sysdep/ptrace.h>
+
+void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
+{
+#ifdef __i386__
+#define COPY2(X,Y) regs->gp[X] = mc->gregs[REG_##Y]
+#define COPY(X) regs->gp[X] = mc->gregs[REG_##X]
+#define COPY_SEG(X) regs->gp[X] = mc->gregs[REG_##X] & 0xffff;
+#define COPY_SEG_CPL3(X) regs->gp[X] = (mc->gregs[REG_##X] & 0xffff) | 3;
+ COPY_SEG(GS); COPY_SEG(FS); COPY_SEG(ES); COPY_SEG(DS);
+ COPY(EDI); COPY(ESI); COPY(EBP);
+ COPY2(UESP, ESP); /* sic */
+ COPY(EBX); COPY(EDX); COPY(ECX); COPY(EAX);
+ COPY(EIP); COPY_SEG_CPL3(CS); COPY(EFL); COPY_SEG_CPL3(SS);
+#else
+#define COPY2(X,Y) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##Y]
+#define COPY(X) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##X]
+ COPY(R8); COPY(R9); COPY(R10); COPY(R11);
+ COPY(R12); COPY(R13); COPY(R14); COPY(R15);
+ COPY(RDI); COPY(RSI); COPY(RBP); COPY(RBX);
+ COPY(RDX); COPY(RAX); COPY(RCX); COPY(RSP);
+ COPY(RIP);
+ COPY2(EFLAGS, EFL);
+ COPY2(CS, CSGSFS);
+ regs->gp[CS / sizeof(unsigned long)] &= 0xffff;
+ regs->gp[CS / sizeof(unsigned long)] |= 3;
+#endif
+}
diff --git a/arch/um/os-Linux/sys-x86_64/prctl.c b/arch/x86/um/os-Linux/prctl.c
index 9d34eddb517f..9d34eddb517f 100644
--- a/arch/um/os-Linux/sys-x86_64/prctl.c
+++ b/arch/x86/um/os-Linux/prctl.c
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/x86/um/os-Linux/registers.c
index 229f7a53d8da..0cdbb86b012b 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/x86/um/os-Linux/registers.c
@@ -6,10 +6,10 @@
#include <errno.h>
#include <sys/ptrace.h>
+#ifdef __i386__
#include <sys/user.h>
-#include "kern_constants.h"
+#endif
#include "longjmp.h"
-#include "user.h"
#include "sysdep/ptrace_user.h"
int save_fp_registers(int pid, unsigned long *fp_regs)
@@ -26,6 +26,8 @@ int restore_fp_registers(int pid, unsigned long *fp_regs)
return 0;
}
+#ifdef __i386__
+int have_fpx_regs = 1;
int save_fpx_registers(int pid, unsigned long *fp_regs)
{
if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
@@ -40,24 +42,6 @@ int restore_fpx_registers(int pid, unsigned long *fp_regs)
return 0;
}
-unsigned long get_thread_reg(int reg, jmp_buf *buf)
-{
- switch (reg) {
- case EIP:
- return buf[0]->__eip;
- case UESP:
- return buf[0]->__esp;
- case EBP:
- return buf[0]->__ebp;
- default:
- printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
- reg);
- return 0;
- }
-}
-
-int have_fpx_regs = 1;
-
int get_fp_registers(int pid, unsigned long *regs)
{
if (have_fpx_regs)
@@ -89,3 +73,41 @@ void arch_init_registers(int pid)
have_fpx_regs = 0;
}
+#else
+
+int get_fp_registers(int pid, unsigned long *regs)
+{
+ return save_fp_registers(pid, regs);
+}
+
+int put_fp_registers(int pid, unsigned long *regs)
+{
+ return restore_fp_registers(pid, regs);
+}
+
+#endif
+
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
+{
+ switch (reg) {
+#ifdef __i386__
+ case HOST_IP:
+ return buf[0]->__eip;
+ case HOST_SP:
+ return buf[0]->__esp;
+ case HOST_BP:
+ return buf[0]->__ebp;
+#else
+ case HOST_IP:
+ return buf[0]->__rip;
+ case HOST_SP:
+ return buf[0]->__rsp;
+ case HOST_BP:
+ return buf[0]->__rbp;
+#endif
+ default:
+ printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
+ reg);
+ return 0;
+ }
+}
diff --git a/arch/um/os-Linux/sys-i386/task_size.c b/arch/x86/um/os-Linux/task_size.c
index be04c1e183bf..efb16c5c9bcf 100644
--- a/arch/um/os-Linux/sys-i386/task_size.c
+++ b/arch/x86/um/os-Linux/task_size.c
@@ -3,7 +3,8 @@
#include <signal.h>
#include <sys/mman.h>
#include "longjmp.h"
-#include "kern_constants.h"
+
+#ifdef __i386__
static jmp_buf buf;
@@ -137,3 +138,13 @@ out:
return top;
}
+
+#else
+
+unsigned long os_get_top_address(void)
+{
+ /* The old value of CONFIG_TOP_ADDR */
+ return 0x7fc0000000;
+}
+
+#endif
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/x86/um/os-Linux/tls.c
index 32ed41ec1a3d..82276b6071af 100644
--- a/arch/um/os-Linux/sys-i386/tls.c
+++ b/arch/x86/um/os-Linux/tls.c
@@ -1,16 +1,25 @@
#include <errno.h>
#include <linux/unistd.h>
+#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <unistd.h>
#include "sysdep/tls.h"
-#include "user.h"
+
+#ifndef PTRACE_GET_THREAD_AREA
+#define PTRACE_GET_THREAD_AREA 25
+#endif
+
+#ifndef PTRACE_SET_THREAD_AREA
+#define PTRACE_SET_THREAD_AREA 26
+#endif
/* Checks whether host supports TLS, and sets *tls_min according to the value
* valid on the host.
* i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
-void check_host_supports_tls(int *supports_tls, int *tls_min) {
+void check_host_supports_tls(int *supports_tls, int *tls_min)
+{
/* Values for x86 and x86_64.*/
int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
int i;
@@ -34,3 +43,25 @@ void check_host_supports_tls(int *supports_tls, int *tls_min) {
*supports_tls = 0;
}
+
+int os_set_thread_area(user_desc_t *info, int pid)
+{
+ int ret;
+
+ ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
+ (unsigned long) info);
+ if (ret < 0)
+ ret = -errno;
+ return ret;
+}
+
+int os_get_thread_area(user_desc_t *info, int pid)
+{
+ int ret;
+
+ ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
+ (unsigned long) info);
+ if (ret < 0)
+ ret = -errno;
+ return ret;
+}
diff --git a/arch/um/sys-i386/ptrace.c b/arch/x86/um/ptrace_32.c
index 3375c2717851..3b949daa095c 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/x86/um/ptrace_32.c
@@ -50,20 +50,47 @@ int is_syscall(unsigned long addr)
/* 1 = access 0 = no access */
#define FLAG_MASK 0x00044dd5
+static const int reg_offsets[] = {
+ [EBX] = HOST_BX,
+ [ECX] = HOST_CX,
+ [EDX] = HOST_DX,
+ [ESI] = HOST_SI,
+ [EDI] = HOST_DI,
+ [EBP] = HOST_BP,
+ [EAX] = HOST_AX,
+ [DS] = HOST_DS,
+ [ES] = HOST_ES,
+ [FS] = HOST_FS,
+ [GS] = HOST_GS,
+ [EIP] = HOST_IP,
+ [CS] = HOST_CS,
+ [EFL] = HOST_EFLAGS,
+ [UESP] = HOST_SP,
+ [SS] = HOST_SS,
+};
+
int putreg(struct task_struct *child, int regno, unsigned long value)
{
regno >>= 2;
switch (regno) {
+ case EBX:
+ case ECX:
+ case EDX:
+ case ESI:
+ case EDI:
+ case EBP:
+ case EAX:
+ case EIP:
+ case UESP:
+ break;
case FS:
if (value && (value & 3) != 3)
return -EIO;
- PT_REGS_FS(&child->thread.regs) = value;
- return 0;
+ break;
case GS:
if (value && (value & 3) != 3)
return -EIO;
- PT_REGS_GS(&child->thread.regs) = value;
- return 0;
+ break;
case DS:
case ES:
if (value && (value & 3) != 3)
@@ -78,10 +105,15 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
break;
case EFL:
value &= FLAG_MASK;
- value |= PT_REGS_EFLAGS(&child->thread.regs);
- break;
+ child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
+ return 0;
+ case ORIG_EAX:
+ child->thread.regs.regs.syscall = value;
+ return 0;
+ default :
+ panic("Bad register in putreg() : %d\n", regno);
}
- PT_REGS_SET(&child->thread.regs, regno, value);
+ child->thread.regs.regs.gp[reg_offsets[regno]] = value;
return 0;
}
@@ -106,22 +138,35 @@ int poke_user(struct task_struct *child, long addr, long data)
unsigned long getreg(struct task_struct *child, int regno)
{
- unsigned long retval = ~0UL;
+ unsigned long mask = ~0UL;
regno >>= 2;
switch (regno) {
+ case ORIG_EAX:
+ return child->thread.regs.regs.syscall;
case FS:
case GS:
case DS:
case ES:
case SS:
case CS:
- retval = 0xffff;
- /* fall through */
+ mask = 0xffff;
+ break;
+ case EIP:
+ case UESP:
+ case EAX:
+ case EBX:
+ case ECX:
+ case EDX:
+ case ESI:
+ case EDI:
+ case EBP:
+ case EFL:
+ break;
default:
- retval &= PT_REG(&child->thread.regs, regno);
+ panic("Bad register in getreg() : %d\n", regno);
}
- return retval;
+ return mask & child->thread.regs.regs.gp[reg_offsets[regno]];
}
/* read the word at location addr in the USER area. */
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/x86/um/ptrace_64.c
index 4005506834fd..3b52bf0b418a 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/x86/um/ptrace_64.c
@@ -18,10 +18,39 @@
*/
#define FLAG_MASK 0x44dd5UL
-int putreg(struct task_struct *child, int regno, unsigned long value)
+static const int reg_offsets[] =
{
- unsigned long tmp;
+ [R8 >> 3] = HOST_R8,
+ [R9 >> 3] = HOST_R9,
+ [R10 >> 3] = HOST_R10,
+ [R11 >> 3] = HOST_R11,
+ [R12 >> 3] = HOST_R12,
+ [R13 >> 3] = HOST_R13,
+ [R14 >> 3] = HOST_R14,
+ [R15 >> 3] = HOST_R15,
+ [RIP >> 3] = HOST_IP,
+ [RSP >> 3] = HOST_SP,
+ [RAX >> 3] = HOST_AX,
+ [RBX >> 3] = HOST_BX,
+ [RCX >> 3] = HOST_CX,
+ [RDX >> 3] = HOST_DX,
+ [RSI >> 3] = HOST_SI,
+ [RDI >> 3] = HOST_DI,
+ [RBP >> 3] = HOST_BP,
+ [CS >> 3] = HOST_CS,
+ [SS >> 3] = HOST_SS,
+ [FS_BASE >> 3] = HOST_FS_BASE,
+ [GS_BASE >> 3] = HOST_GS_BASE,
+ [DS >> 3] = HOST_DS,
+ [ES >> 3] = HOST_ES,
+ [FS >> 3] = HOST_FS,
+ [GS >> 3] = HOST_GS,
+ [EFLAGS >> 3] = HOST_EFLAGS,
+ [ORIG_RAX >> 3] = HOST_ORIG_AX,
+};
+int putreg(struct task_struct *child, int regno, unsigned long value)
+{
#ifdef TIF_IA32
/*
* Some code in the 64bit emulation may not be 64bit clean.
@@ -31,6 +60,26 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
value &= 0xffffffff;
#endif
switch (regno) {
+ case R8:
+ case R9:
+ case R10:
+ case R11:
+ case R12:
+ case R13:
+ case R14:
+ case R15:
+ case RIP:
+ case RSP:
+ case RAX:
+ case RBX:
+ case RCX:
+ case RDX:
+ case RSI:
+ case RDI:
+ case RBP:
+ case ORIG_RAX:
+ break;
+
case FS:
case GS:
case DS:
@@ -50,12 +99,14 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
case EFLAGS:
value &= FLAG_MASK;
- tmp = PT_REGS_EFLAGS(&child->thread.regs) & ~FLAG_MASK;
- value |= tmp;
- break;
+ child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
+ return 0;
+
+ default:
+ panic("Bad register in putreg(): %d\n", regno);
}
- PT_REGS_SET(&child->thread.regs, regno, value);
+ child->thread.regs.regs.gp[reg_offsets[regno >> 3]] = value;
return 0;
}
@@ -80,24 +131,46 @@ int poke_user(struct task_struct *child, long addr, long data)
unsigned long getreg(struct task_struct *child, int regno)
{
- unsigned long retval = ~0UL;
+ unsigned long mask = ~0UL;
+#ifdef TIF_IA32
+ if (test_tsk_thread_flag(child, TIF_IA32))
+ mask = 0xffffffff;
+#endif
switch (regno) {
+ case R8:
+ case R9:
+ case R10:
+ case R11:
+ case R12:
+ case R13:
+ case R14:
+ case R15:
+ case RIP:
+ case RSP:
+ case RAX:
+ case RBX:
+ case RCX:
+ case RDX:
+ case RSI:
+ case RDI:
+ case RBP:
+ case ORIG_RAX:
+ case EFLAGS:
+ case FS_BASE:
+ case GS_BASE:
+ break;
case FS:
case GS:
case DS:
case ES:
case SS:
case CS:
- retval = 0xffff;
- /* fall through */
+ mask = 0xffff;
+ break;
default:
- retval &= PT_REG(&child->thread.regs, regno);
-#ifdef TIF_IA32
- if (test_tsk_thread_flag(child, TIF_IA32))
- retval &= 0xffffffff;
-#endif
+ panic("Bad register in getreg: %d\n", regno);
}
- return retval;
+ return mask & child->thread.regs.regs.gp[reg_offsets[regno >> 3]];
}
int peek_user(struct task_struct *child, long addr, long data)
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/x86/um/ptrace_user.c
index 0b10c3e74028..3960ca1dd35a 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/x86/um/ptrace_user.c
@@ -4,7 +4,7 @@
*/
#include <errno.h>
-#include <sys/ptrace.h>
+#include "ptrace_user.h"
int ptrace_getregs(long pid, unsigned long *regs_out)
{
diff --git a/arch/um/sys-i386/setjmp.S b/arch/x86/um/setjmp_32.S
index b766792c9933..b766792c9933 100644
--- a/arch/um/sys-i386/setjmp.S
+++ b/arch/x86/um/setjmp_32.S
diff --git a/arch/um/sys-x86_64/setjmp.S b/arch/x86/um/setjmp_64.S
index 45f547b4043e..45f547b4043e 100644
--- a/arch/um/sys-x86_64/setjmp.S
+++ b/arch/x86/um/setjmp_64.S
diff --git a/arch/x86/um/shared/sysdep/archsetjmp.h b/arch/x86/um/shared/sysdep/archsetjmp.h
new file mode 100644
index 000000000000..ff7766d28226
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/archsetjmp.h
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "archsetjmp_32.h"
+#else
+#include "archsetjmp_64.h"
+#endif
diff --git a/arch/um/sys-i386/shared/sysdep/archsetjmp.h b/arch/x86/um/shared/sysdep/archsetjmp_32.h
index 0f312085ce1d..0f312085ce1d 100644
--- a/arch/um/sys-i386/shared/sysdep/archsetjmp.h
+++ b/arch/x86/um/shared/sysdep/archsetjmp_32.h
diff --git a/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h b/arch/x86/um/shared/sysdep/archsetjmp_64.h
index 2af8f12ca161..2af8f12ca161 100644
--- a/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h
+++ b/arch/x86/um/shared/sysdep/archsetjmp_64.h
diff --git a/arch/x86/um/shared/sysdep/faultinfo.h b/arch/x86/um/shared/sysdep/faultinfo.h
new file mode 100644
index 000000000000..862ecb1c7781
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/faultinfo.h
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "faultinfo_32.h"
+#else
+#include "faultinfo_64.h"
+#endif
diff --git a/arch/um/sys-i386/shared/sysdep/faultinfo.h b/arch/x86/um/shared/sysdep/faultinfo_32.h
index db437cc373bc..a26086b8a800 100644
--- a/arch/um/sys-i386/shared/sysdep/faultinfo.h
+++ b/arch/x86/um/shared/sysdep/faultinfo_32.h
@@ -24,6 +24,12 @@ struct faultinfo {
#define FAULT_WRITE(fi) ((fi).error_code & 2)
#define FAULT_ADDRESS(fi) ((fi).cr2)
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
+
+/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
+#define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo)
+
#define PTRACE_FULL_FAULTINFO 0
#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/faultinfo.h b/arch/x86/um/shared/sysdep/faultinfo_64.h
index cb917b0d5660..f811cbe15d62 100644
--- a/arch/um/sys-x86_64/shared/sysdep/faultinfo.h
+++ b/arch/x86/um/shared/sysdep/faultinfo_64.h
@@ -24,6 +24,12 @@ struct faultinfo {
#define FAULT_WRITE(fi) ((fi).error_code & 2)
#define FAULT_ADDRESS(fi) ((fi).cr2)
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
+
+/* No broken SKAS API, which doesn't pass trap_no, here. */
+#define SEGV_MAYBE_FIXABLE(fi) 0
+
#define PTRACE_FULL_FAULTINFO 1
#endif
diff --git a/arch/um/sys-i386/shared/sysdep/kernel-offsets.h b/arch/x86/um/shared/sysdep/kernel-offsets.h
index 5868526b5eef..5868526b5eef 100644
--- a/arch/um/sys-i386/shared/sysdep/kernel-offsets.h
+++ b/arch/x86/um/shared/sysdep/kernel-offsets.h
diff --git a/arch/x86/um/shared/sysdep/mcontext.h b/arch/x86/um/shared/sysdep/mcontext.h
new file mode 100644
index 000000000000..b724c54da316
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/mcontext.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYS_SIGCONTEXT_X86_H
+#define __SYS_SIGCONTEXT_X86_H
+
+extern void get_regs_from_mc(struct uml_pt_regs *, mcontext_t *);
+
+#ifdef __i386__
+
+#define GET_FAULTINFO_FROM_MC(fi, mc) \
+ { \
+ (fi).cr2 = (mc)->cr2; \
+ (fi).error_code = (mc)->gregs[REG_ERR]; \
+ (fi).trap_no = (mc)->gregs[REG_TRAPNO]; \
+ }
+
+#else
+
+#define GET_FAULTINFO_FROM_MC(fi, mc) \
+ { \
+ (fi).cr2 = (mc)->gregs[REG_CR2]; \
+ (fi).error_code = (mc)->gregs[REG_ERR]; \
+ (fi).trap_no = (mc)->gregs[REG_TRAPNO]; \
+ }
+
+#endif
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/ptrace.h b/arch/x86/um/shared/sysdep/ptrace.h
new file mode 100644
index 000000000000..711b1621747f
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/ptrace.h
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "ptrace_32.h"
+#else
+#include "ptrace_64.h"
+#endif
diff --git a/arch/um/sys-i386/shared/sysdep/ptrace.h b/arch/x86/um/shared/sysdep/ptrace_32.h
index c398a5076111..befd1df32ed0 100644
--- a/arch/um/sys-i386/shared/sysdep/ptrace.h
+++ b/arch/x86/um/shared/sysdep/ptrace_32.h
@@ -6,7 +6,7 @@
#ifndef __SYSDEP_I386_PTRACE_H
#define __SYSDEP_I386_PTRACE_H
-#include "user_constants.h"
+#include <generated/user_constants.h>
#include "sysdep/faultinfo.h"
#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
@@ -24,18 +24,16 @@ void set_using_sysemu(int value);
int get_using_sysemu(void);
extern int sysemu_supported;
-#include "skas_ptregs.h"
-
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-#define REGS_EAX(r) ((r)[HOST_EAX])
-#define REGS_EBX(r) ((r)[HOST_EBX])
-#define REGS_ECX(r) ((r)[HOST_ECX])
-#define REGS_EDX(r) ((r)[HOST_EDX])
-#define REGS_ESI(r) ((r)[HOST_ESI])
-#define REGS_EDI(r) ((r)[HOST_EDI])
-#define REGS_EBP(r) ((r)[HOST_EBP])
+#define REGS_EAX(r) ((r)[HOST_AX])
+#define REGS_EBX(r) ((r)[HOST_BX])
+#define REGS_ECX(r) ((r)[HOST_CX])
+#define REGS_EDX(r) ((r)[HOST_DX])
+#define REGS_ESI(r) ((r)[HOST_SI])
+#define REGS_EDI(r) ((r)[HOST_DI])
+#define REGS_EBP(r) ((r)[HOST_BP])
#define REGS_CS(r) ((r)[HOST_CS])
#define REGS_SS(r) ((r)[HOST_SS])
#define REGS_DS(r) ((r)[HOST_DS])
@@ -45,6 +43,7 @@ extern int sysemu_supported;
#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
#ifndef PTRACE_SYSEMU_SINGLESTEP
@@ -102,62 +101,6 @@ struct syscall_args {
UPT_SYSCALL_ARG5(r), \
UPT_SYSCALL_ARG6(r) } } )
-#define UPT_REG(regs, reg) \
- ({ unsigned long val; \
- switch(reg){ \
- case EIP: val = UPT_IP(regs); break; \
- case UESP: val = UPT_SP(regs); break; \
- case EAX: val = UPT_EAX(regs); break; \
- case EBX: val = UPT_EBX(regs); break; \
- case ECX: val = UPT_ECX(regs); break; \
- case EDX: val = UPT_EDX(regs); break; \
- case ESI: val = UPT_ESI(regs); break; \
- case EDI: val = UPT_EDI(regs); break; \
- case EBP: val = UPT_EBP(regs); break; \
- case ORIG_EAX: val = UPT_ORIG_EAX(regs); break; \
- case CS: val = UPT_CS(regs); break; \
- case SS: val = UPT_SS(regs); break; \
- case DS: val = UPT_DS(regs); break; \
- case ES: val = UPT_ES(regs); break; \
- case FS: val = UPT_FS(regs); break; \
- case GS: val = UPT_GS(regs); break; \
- case EFL: val = UPT_EFLAGS(regs); break; \
- default : \
- panic("Bad register in UPT_REG : %d\n", reg); \
- val = -1; \
- } \
- val; \
- })
-
-#define UPT_SET(regs, reg, val) \
- do { \
- switch(reg){ \
- case EIP: UPT_IP(regs) = val; break; \
- case UESP: UPT_SP(regs) = val; break; \
- case EAX: UPT_EAX(regs) = val; break; \
- case EBX: UPT_EBX(regs) = val; break; \
- case ECX: UPT_ECX(regs) = val; break; \
- case EDX: UPT_EDX(regs) = val; break; \
- case ESI: UPT_ESI(regs) = val; break; \
- case EDI: UPT_EDI(regs) = val; break; \
- case EBP: UPT_EBP(regs) = val; break; \
- case ORIG_EAX: UPT_ORIG_EAX(regs) = val; break; \
- case CS: UPT_CS(regs) = val; break; \
- case SS: UPT_SS(regs) = val; break; \
- case DS: UPT_DS(regs) = val; break; \
- case ES: UPT_ES(regs) = val; break; \
- case FS: UPT_FS(regs) = val; break; \
- case GS: UPT_GS(regs) = val; break; \
- case EFL: UPT_EFLAGS(regs) = val; break; \
- default : \
- panic("Bad register in UPT_SET : %d\n", reg); \
- break; \
- } \
- } while (0)
-
-#define UPT_SET_SYSCALL_RETURN(r, res) \
- REGS_SET_SYSCALL_RETURN((r)->regs, (res))
-
#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
diff --git a/arch/um/sys-x86_64/shared/sysdep/ptrace.h b/arch/x86/um/shared/sysdep/ptrace_64.h
index 8ee8f8e12af1..031edc53ac57 100644
--- a/arch/um/sys-x86_64/shared/sysdep/ptrace.h
+++ b/arch/x86/um/shared/sysdep/ptrace_64.h
@@ -8,24 +8,22 @@
#ifndef __SYSDEP_X86_64_PTRACE_H
#define __SYSDEP_X86_64_PTRACE_H
-#include "user_constants.h"
+#include <generated/user_constants.h>
#include "sysdep/faultinfo.h"
#define MAX_REG_OFFSET (UM_FRAME_SIZE)
#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
-#include "skas_ptregs.h"
-
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
-#define REGS_RBX(r) ((r)[HOST_RBX])
-#define REGS_RCX(r) ((r)[HOST_RCX])
-#define REGS_RDX(r) ((r)[HOST_RDX])
-#define REGS_RSI(r) ((r)[HOST_RSI])
-#define REGS_RDI(r) ((r)[HOST_RDI])
-#define REGS_RBP(r) ((r)[HOST_RBP])
-#define REGS_RAX(r) ((r)[HOST_RAX])
+#define REGS_RBX(r) ((r)[HOST_BX])
+#define REGS_RCX(r) ((r)[HOST_CX])
+#define REGS_RDX(r) ((r)[HOST_DX])
+#define REGS_RSI(r) ((r)[HOST_SI])
+#define REGS_RDI(r) ((r)[HOST_DI])
+#define REGS_RBP(r) ((r)[HOST_BP])
+#define REGS_RAX(r) ((r)[HOST_AX])
#define REGS_R8(r) ((r)[HOST_R8])
#define REGS_R9(r) ((r)[HOST_R9])
#define REGS_R10(r) ((r)[HOST_R10])
@@ -67,14 +65,13 @@
#define REGS_FS(r) ((r)[HOST_FS])
#define REGS_GS(r) ((r)[HOST_GS])
-#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_RAX])
+#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_AX])
#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res)
+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
-
#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
@@ -149,88 +146,8 @@ struct syscall_args {
UPT_SYSCALL_ARG5(r), \
UPT_SYSCALL_ARG6(r) } } )
-#define UPT_REG(regs, reg) \
- ({ unsigned long val; \
- switch(reg){ \
- case R8: val = UPT_R8(regs); break; \
- case R9: val = UPT_R9(regs); break; \
- case R10: val = UPT_R10(regs); break; \
- case R11: val = UPT_R11(regs); break; \
- case R12: val = UPT_R12(regs); break; \
- case R13: val = UPT_R13(regs); break; \
- case R14: val = UPT_R14(regs); break; \
- case R15: val = UPT_R15(regs); break; \
- case RIP: val = UPT_IP(regs); break; \
- case RSP: val = UPT_SP(regs); break; \
- case RAX: val = UPT_RAX(regs); break; \
- case RBX: val = UPT_RBX(regs); break; \
- case RCX: val = UPT_RCX(regs); break; \
- case RDX: val = UPT_RDX(regs); break; \
- case RSI: val = UPT_RSI(regs); break; \
- case RDI: val = UPT_RDI(regs); break; \
- case RBP: val = UPT_RBP(regs); break; \
- case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \
- case CS: val = UPT_CS(regs); break; \
- case SS: val = UPT_SS(regs); break; \
- case FS_BASE: val = UPT_FS_BASE(regs); break; \
- case GS_BASE: val = UPT_GS_BASE(regs); break; \
- case DS: val = UPT_DS(regs); break; \
- case ES: val = UPT_ES(regs); break; \
- case FS : val = UPT_FS (regs); break; \
- case GS: val = UPT_GS(regs); break; \
- case EFLAGS: val = UPT_EFLAGS(regs); break; \
- default : \
- panic("Bad register in UPT_REG : %d\n", reg); \
- val = -1; \
- } \
- val; \
- })
-
-
-#define UPT_SET(regs, reg, val) \
- ({ unsigned long __upt_val = val; \
- switch(reg){ \
- case R8: UPT_R8(regs) = __upt_val; break; \
- case R9: UPT_R9(regs) = __upt_val; break; \
- case R10: UPT_R10(regs) = __upt_val; break; \
- case R11: UPT_R11(regs) = __upt_val; break; \
- case R12: UPT_R12(regs) = __upt_val; break; \
- case R13: UPT_R13(regs) = __upt_val; break; \
- case R14: UPT_R14(regs) = __upt_val; break; \
- case R15: UPT_R15(regs) = __upt_val; break; \
- case RIP: UPT_IP(regs) = __upt_val; break; \
- case RSP: UPT_SP(regs) = __upt_val; break; \
- case RAX: UPT_RAX(regs) = __upt_val; break; \
- case RBX: UPT_RBX(regs) = __upt_val; break; \
- case RCX: UPT_RCX(regs) = __upt_val; break; \
- case RDX: UPT_RDX(regs) = __upt_val; break; \
- case RSI: UPT_RSI(regs) = __upt_val; break; \
- case RDI: UPT_RDI(regs) = __upt_val; break; \
- case RBP: UPT_RBP(regs) = __upt_val; break; \
- case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
- case CS: UPT_CS(regs) = __upt_val; break; \
- case SS: UPT_SS(regs) = __upt_val; break; \
- case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \
- case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \
- case DS: UPT_DS(regs) = __upt_val; break; \
- case ES: UPT_ES(regs) = __upt_val; break; \
- case FS: UPT_FS(regs) = __upt_val; break; \
- case GS: UPT_GS(regs) = __upt_val; break; \
- case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
- default : \
- panic("Bad register in UPT_SET : %d\n", reg); \
- break; \
- } \
- __upt_val; \
- })
-
-#define UPT_SET_SYSCALL_RETURN(r, res) \
- REGS_SET_SYSCALL_RETURN((r)->regs, (res))
-
#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
-#define UPT_SEGV_IS_FIXABLE(r) REGS_SEGV_IS_FIXABLE(&r->skas)
-
#define UPT_FAULTINFO(r) (&(r)->faultinfo)
static inline void arch_init_registers(int pid)
diff --git a/arch/x86/um/shared/sysdep/ptrace_user.h b/arch/x86/um/shared/sysdep/ptrace_user.h
new file mode 100644
index 000000000000..16cd6b5e71f7
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/ptrace_user.h
@@ -0,0 +1,27 @@
+#include <generated/user_constants.h>
+
+#define PT_OFFSET(r) ((r) * sizeof(long))
+
+#define PT_SYSCALL_NR(regs) ((regs)[HOST_ORIG_AX])
+#define PT_SYSCALL_NR_OFFSET PT_OFFSET(HOST_ORIG_AX)
+
+#define PT_SYSCALL_RET_OFFSET PT_OFFSET(HOST_AX)
+
+#define REGS_IP_INDEX HOST_IP
+#define REGS_SP_INDEX HOST_SP
+
+#ifdef __i386__
+#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
+#else
+#define FP_SIZE HOST_FP_SIZE
+
+/*
+ * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
+ * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
+ * 2.4 name and value for 2.4 host compatibility.
+ */
+#ifndef PTRACE_OLDSETOPTIONS
+#define PTRACE_OLDSETOPTIONS 21
+#endif
+
+#endif
diff --git a/arch/um/sys-i386/shared/sysdep/skas_ptrace.h b/arch/x86/um/shared/sysdep/skas_ptrace.h
index e27b8a791773..453febe98993 100644
--- a/arch/um/sys-i386/shared/sysdep/skas_ptrace.h
+++ b/arch/x86/um/shared/sysdep/skas_ptrace.h
@@ -3,8 +3,8 @@
* Licensed under the GPL
*/
-#ifndef __SYSDEP_I386_SKAS_PTRACE_H
-#define __SYSDEP_I386_SKAS_PTRACE_H
+#ifndef __SYSDEP_X86_SKAS_PTRACE_H
+#define __SYSDEP_X86_SKAS_PTRACE_H
struct ptrace_faultinfo {
int is_write;
diff --git a/arch/x86/um/shared/sysdep/stub.h b/arch/x86/um/shared/sysdep/stub.h
new file mode 100644
index 000000000000..bd161e300102
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/stub.h
@@ -0,0 +1,14 @@
+#include <asm/unistd.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include "as-layout.h"
+#include "stub-data.h"
+
+#ifdef __i386__
+#include "stub_32.h"
+#else
+#include "stub_64.h"
+#endif
+
+extern void stub_segv_handler(int, siginfo_t *, void *);
+extern void stub_clone_handler(void);
diff --git a/arch/um/sys-i386/shared/sysdep/stub.h b/arch/x86/um/shared/sysdep/stub_32.h
index 977dedd9221b..51fd256c75f0 100644
--- a/arch/um/sys-i386/shared/sysdep/stub.h
+++ b/arch/x86/um/shared/sysdep/stub_32.h
@@ -6,15 +6,7 @@
#ifndef __SYSDEP_STUB_H
#define __SYSDEP_STUB_H
-#include <sys/mman.h>
#include <asm/ptrace.h>
-#include <asm/unistd.h>
-#include "as-layout.h"
-#include "stub-data.h"
-#include "kern_constants.h"
-
-extern void stub_segv_handler(int sig);
-extern void stub_clone_handler(void);
#define STUB_SYSCALL_RET EAX
#define STUB_MMAP_NR __NR_mmap2
diff --git a/arch/um/sys-x86_64/shared/sysdep/stub.h b/arch/x86/um/shared/sysdep/stub_64.h
index 3432aa249970..994df93c5ed3 100644
--- a/arch/um/sys-x86_64/shared/sysdep/stub.h
+++ b/arch/x86/um/shared/sysdep/stub_64.h
@@ -6,15 +6,7 @@
#ifndef __SYSDEP_STUB_H
#define __SYSDEP_STUB_H
-#include <sys/mman.h>
-#include <asm/unistd.h>
#include <sysdep/ptrace_user.h>
-#include "as-layout.h"
-#include "stub-data.h"
-#include "kern_constants.h"
-
-extern void stub_segv_handler(int sig);
-extern void stub_clone_handler(void);
#define STUB_SYSCALL_RET PT_INDEX(RAX)
#define STUB_MMAP_NR __NR_mmap
diff --git a/arch/x86/um/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls.h
new file mode 100644
index 000000000000..bd9a89b67e41
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/syscalls.h
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "syscalls_32.h"
+#else
+#include "syscalls_64.h"
+#endif
diff --git a/arch/um/sys-i386/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls_32.h
index 05cb796aecb5..05cb796aecb5 100644
--- a/arch/um/sys-i386/shared/sysdep/syscalls.h
+++ b/arch/x86/um/shared/sysdep/syscalls_32.h
diff --git a/arch/um/sys-x86_64/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls_64.h
index 7cfb0b085655..8a7d5e1da98e 100644
--- a/arch/um/sys-x86_64/shared/sysdep/syscalls.h
+++ b/arch/x86/um/shared/sysdep/syscalls_64.h
@@ -9,7 +9,6 @@
#include <linux/msg.h>
#include <linux/shm.h>
-#include <kern_constants.h>
typedef long syscall_handler_t(void);
diff --git a/arch/um/sys-i386/shared/sysdep/tls.h b/arch/x86/um/shared/sysdep/tls.h
index 34550755b2a1..27cce00c6b30 100644
--- a/arch/um/sys-i386/shared/sysdep/tls.h
+++ b/arch/x86/um/shared/sysdep/tls.h
@@ -17,16 +17,23 @@ typedef struct um_dup_user_desc {
unsigned int limit_in_pages:1;
unsigned int seg_not_present:1;
unsigned int useable:1;
+#ifdef __x86_64__
+ unsigned int lm:1;
+#endif
} user_desc_t;
# else /* __KERNEL__ */
-# include <ldt.h>
typedef struct user_desc user_desc_t;
# endif /* __KERNEL__ */
+extern int os_set_thread_area(user_desc_t *info, int pid);
+extern int os_get_thread_area(user_desc_t *info, int pid);
+
+#ifdef __i386__
#define GDT_ENTRY_TLS_MIN_I386 6
#define GDT_ENTRY_TLS_MIN_X86_64 12
+#endif
#endif /* _SYSDEP_TLS_H */
diff --git a/arch/um/sys-i386/signal.c b/arch/x86/um/signal.c
index 89a46626bfd8..4883b9546016 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/x86/um/signal.c
@@ -1,36 +1,20 @@
/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright (C) 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
+
+#include <linux/personality.h>
#include <linux/ptrace.h>
+#include <linux/kernel.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
#include <asm/ucontext.h>
#include "frame_kern.h"
#include "skas.h"
-void copy_sc(struct uml_pt_regs *regs, void *from)
-{
- struct sigcontext *sc = from;
-
- REGS_GS(regs->gp) = sc->gs;
- REGS_FS(regs->gp) = sc->fs;
- REGS_ES(regs->gp) = sc->es;
- REGS_DS(regs->gp) = sc->ds;
- REGS_EDI(regs->gp) = sc->di;
- REGS_ESI(regs->gp) = sc->si;
- REGS_EBP(regs->gp) = sc->bp;
- REGS_SP(regs->gp) = sc->sp;
- REGS_EBX(regs->gp) = sc->bx;
- REGS_EDX(regs->gp) = sc->dx;
- REGS_ECX(regs->gp) = sc->cx;
- REGS_EAX(regs->gp) = sc->ax;
- REGS_IP(regs->gp) = sc->ip;
- REGS_CS(regs->gp) = sc->cs;
- REGS_EFLAGS(regs->gp) = sc->flags;
- REGS_SS(regs->gp) = sc->ss;
-}
+#ifdef CONFIG_X86_32
/*
* FPU tag word conversions.
@@ -164,6 +148,8 @@ static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
extern int have_fpx_regs;
+#endif
+
static int copy_sc_from_user(struct pt_regs *regs,
struct sigcontext __user *from)
{
@@ -174,8 +160,45 @@ static int copy_sc_from_user(struct pt_regs *regs,
if (err)
return err;
+#define GETREG(regno, regname) regs->regs.gp[HOST_##regno] = sc.regname
+
+#ifdef CONFIG_X86_32
+ GETREG(GS, gs);
+ GETREG(FS, fs);
+ GETREG(ES, es);
+ GETREG(DS, ds);
+#endif
+ GETREG(DI, di);
+ GETREG(SI, si);
+ GETREG(BP, bp);
+ GETREG(SP, sp);
+ GETREG(BX, bx);
+ GETREG(DX, dx);
+ GETREG(CX, cx);
+ GETREG(AX, ax);
+ GETREG(IP, ip);
+
+#ifdef CONFIG_X86_64
+ GETREG(R8, r8);
+ GETREG(R9, r9);
+ GETREG(R10, r10);
+ GETREG(R11, r11);
+ GETREG(R12, r12);
+ GETREG(R13, r13);
+ GETREG(R14, r14);
+ GETREG(R15, r15);
+#endif
+
+ GETREG(CS, cs);
+ GETREG(EFLAGS, flags);
+#ifdef CONFIG_X86_32
+ GETREG(SS, ss);
+#endif
+
+#undef GETREG
+
pid = userspace_pid[current_thread_info()->cpu];
- copy_sc(&regs->regs, &sc);
+#ifdef CONFIG_X86_32
if (have_fpx_regs) {
struct user_fxsr_struct fpx;
@@ -196,8 +219,9 @@ static int copy_sc_from_user(struct pt_regs *regs,
-err);
return 1;
}
- }
- else {
+ } else
+#endif
+ {
struct user_i387_struct fp;
err = copy_from_user(&fp, sc.fpstate,
@@ -213,43 +237,66 @@ static int copy_sc_from_user(struct pt_regs *regs,
return 1;
}
}
-
return 0;
}
static int copy_sc_to_user(struct sigcontext __user *to,
struct _fpstate __user *to_fp, struct pt_regs *regs,
- unsigned long sp)
+ unsigned long mask)
{
struct sigcontext sc;
struct faultinfo * fi = &current->thread.arch.faultinfo;
int err, pid;
+ memset(&sc, 0, sizeof(struct sigcontext));
+
+#define PUTREG(regno, regname) sc.regname = regs->regs.gp[HOST_##regno]
+
+#ifdef CONFIG_X86_32
+ PUTREG(GS, gs);
+ PUTREG(FS, fs);
+ PUTREG(ES, es);
+ PUTREG(DS, ds);
+#endif
+ PUTREG(DI, di);
+ PUTREG(SI, si);
+ PUTREG(BP, bp);
+ PUTREG(SP, sp);
+ PUTREG(BX, bx);
+ PUTREG(DX, dx);
+ PUTREG(CX, cx);
+ PUTREG(AX, ax);
+#ifdef CONFIG_X86_64
+ PUTREG(R8, r8);
+ PUTREG(R9, r9);
+ PUTREG(R10, r10);
+ PUTREG(R11, r11);
+ PUTREG(R12, r12);
+ PUTREG(R13, r13);
+ PUTREG(R14, r14);
+ PUTREG(R15, r15);
+#endif
- sc.gs = REGS_GS(regs->regs.gp);
- sc.fs = REGS_FS(regs->regs.gp);
- sc.es = REGS_ES(regs->regs.gp);
- sc.ds = REGS_DS(regs->regs.gp);
- sc.di = REGS_EDI(regs->regs.gp);
- sc.si = REGS_ESI(regs->regs.gp);
- sc.bp = REGS_EBP(regs->regs.gp);
- sc.sp = sp;
- sc.bx = REGS_EBX(regs->regs.gp);
- sc.dx = REGS_EDX(regs->regs.gp);
- sc.cx = REGS_ECX(regs->regs.gp);
- sc.ax = REGS_EAX(regs->regs.gp);
- sc.ip = REGS_IP(regs->regs.gp);
- sc.cs = REGS_CS(regs->regs.gp);
- sc.flags = REGS_EFLAGS(regs->regs.gp);
- sc.sp_at_signal = regs->regs.gp[UESP];
- sc.ss = regs->regs.gp[SS];
sc.cr2 = fi->cr2;
sc.err = fi->error_code;
sc.trapno = fi->trap_no;
-
- to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
+ PUTREG(IP, ip);
+ PUTREG(CS, cs);
+ PUTREG(EFLAGS, flags);
+#ifdef CONFIG_X86_32
+ PUTREG(SP, sp_at_signal);
+ PUTREG(SS, ss);
+#endif
+#undef PUTREG
+ sc.oldmask = mask;
sc.fpstate = to_fp;
+ err = copy_to_user(to, &sc, sizeof(struct sigcontext));
+ if (err)
+ return 1;
+
pid = userspace_pid[current_thread_info()->cpu];
+
+#ifdef CONFIG_X86_32
if (have_fpx_regs) {
struct user_fxsr_struct fpx;
@@ -272,8 +319,9 @@ static int copy_sc_to_user(struct sigcontext __user *to,
if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
sizeof(struct user_fxsr_struct)))
return 1;
- }
- else {
+ } else
+#endif
+ {
struct user_i387_struct fp;
err = save_fp_registers(pid, (unsigned long *) &fp);
@@ -281,9 +329,10 @@ static int copy_sc_to_user(struct sigcontext __user *to,
return 1;
}
- return copy_to_user(to, &sc, sizeof(sc));
+ return 0;
}
+#ifdef CONFIG_X86_32
static int copy_ucontext_to_user(struct ucontext __user *uc,
struct _fpstate __user *fp, sigset_t *set,
unsigned long sp)
@@ -293,7 +342,7 @@ static int copy_ucontext_to_user(struct ucontext __user *uc,
err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
- err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp);
+ err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, 0);
err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
return err;
}
@@ -326,7 +375,6 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
{
struct sigframe __user *frame;
void __user *restorer;
- unsigned long save_sp = PT_REGS_SP(regs);
int err = 0;
/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
@@ -339,20 +387,9 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
if (ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
- /* Update SP now because the page fault handler refuses to extend
- * the stack if the faulting address is too far below the current
- * SP, which frame now certainly is. If there's an error, the original
- * value is restored on the way out.
- * When writing the sigcontext to the stack, we have to write the
- * original value, so that's passed to copy_sc_to_user, which does
- * the right thing with it.
- */
- PT_REGS_SP(regs) = (unsigned long) frame;
-
err |= __put_user(restorer, &frame->pretcode);
err |= __put_user(sig, &frame->sig);
- err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp);
- err |= __put_user(mask->sig[0], &frame->sc.oldmask);
+ err |= copy_sc_to_user(&frame->sc, &frame->fpstate, regs, mask->sig[0]);
if (_NSIG_WORDS > 1)
err |= __copy_to_user(&frame->extramask, &mask->sig[1],
sizeof(frame->extramask));
@@ -369,7 +406,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
if (err)
- goto err;
+ return err;
PT_REGS_SP(regs) = (unsigned long) frame;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
@@ -380,10 +417,6 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
ptrace_notify(SIGTRAP);
return 0;
-
-err:
- PT_REGS_SP(regs) = save_sp;
- return err;
}
int setup_signal_stack_si(unsigned long stack_top, int sig,
@@ -392,7 +425,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
{
struct rt_sigframe __user *frame;
void __user *restorer;
- unsigned long save_sp = PT_REGS_SP(regs);
int err = 0;
stack_top &= -8UL;
@@ -404,16 +436,13 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
if (ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
- /* See comment above about why this is here */
- PT_REGS_SP(regs) = (unsigned long) frame;
-
err |= __put_user(restorer, &frame->pretcode);
err |= __put_user(sig, &frame->sig);
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info);
err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
- save_sp);
+ PT_REGS_SP(regs));
/*
* This is movl $,%eax ; int $0x80
@@ -427,8 +456,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
if (err)
- goto err;
+ return err;
+ PT_REGS_SP(regs) = (unsigned long) frame;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
PT_REGS_EAX(regs) = (unsigned long) sig;
PT_REGS_EDX(regs) = (unsigned long) &frame->info;
@@ -437,13 +467,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
ptrace_notify(SIGTRAP);
return 0;
-
-err:
- PT_REGS_SP(regs) = save_sp;
- return err;
}
-long sys_sigreturn(struct pt_regs regs)
+long sys_sigreturn(struct pt_regs *regs)
{
unsigned long sp = PT_REGS_SP(&current->thread.regs);
struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
@@ -458,11 +484,7 @@ long sys_sigreturn(struct pt_regs regs)
goto segfault;
sigdelsetmask(&set, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);
if (copy_sc_from_user(&current->thread.regs, sc))
goto segfault;
@@ -476,24 +498,107 @@ long sys_sigreturn(struct pt_regs regs)
return 0;
}
-long sys_rt_sigreturn(struct pt_regs regs)
+#else
+
+struct rt_sigframe
+{
+ char __user *pretcode;
+ struct ucontext uc;
+ struct siginfo info;
+ struct _fpstate fpstate;
+};
+
+int setup_signal_stack_si(unsigned long stack_top, int sig,
+ struct k_sigaction *ka, struct pt_regs * regs,
+ siginfo_t *info, sigset_t *set)
+{
+ struct rt_sigframe __user *frame;
+ int err = 0;
+ struct task_struct *me = current;
+
+ frame = (struct rt_sigframe __user *)
+ round_down(stack_top - sizeof(struct rt_sigframe), 16);
+ /* Subtract 128 for a red zone and 8 for proper alignment */
+ frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto out;
+
+ if (ka->sa.sa_flags & SA_SIGINFO) {
+ err |= copy_siginfo_to_user(&frame->info, info);
+ if (err)
+ goto out;
+ }
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
+ set->sig[0]);
+ err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
+ if (sizeof(*set) == 16) {
+ __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
+ __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
+ }
+ else
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set,
+ sizeof(*set));
+
+ /*
+ * Set up to return from userspace. If provided, use a stub
+ * already in userspace.
+ */
+ /* x86-64 should always use SA_RESTORER. */
+ if (ka->sa.sa_flags & SA_RESTORER)
+ err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
+ else
+ /* could use a vstub here */
+ return err;
+
+ if (err)
+ return err;
+
+ /* Set up registers for signal handler */
+ {
+ struct exec_domain *ed = current_thread_info()->exec_domain;
+ if (unlikely(ed && ed->signal_invmap && sig < 32))
+ sig = ed->signal_invmap[sig];
+ }
+
+ PT_REGS_SP(regs) = (unsigned long) frame;
+ PT_REGS_RDI(regs) = sig;
+ /* In case the signal handler was declared without prototypes */
+ PT_REGS_RAX(regs) = 0;
+
+ /*
+ * This also works for non SA_SIGINFO handlers because they expect the
+ * next argument after the signal number on the stack.
+ */
+ PT_REGS_RSI(regs) = (unsigned long) &frame->info;
+ PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
+ PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
+ out:
+ return err;
+}
+#endif
+
+long sys_rt_sigreturn(struct pt_regs *regs)
{
unsigned long sp = PT_REGS_SP(&current->thread.regs);
struct rt_sigframe __user *frame =
- (struct rt_sigframe __user *) (sp - 4);
- sigset_t set;
+ (struct rt_sigframe __user *)(sp - sizeof(long));
struct ucontext __user *uc = &frame->uc;
- int sig_size = _NSIG_WORDS * sizeof(unsigned long);
+ sigset_t set;
- if (copy_from_user(&set, &uc->uc_sigmask, sig_size))
+ if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
goto segfault;
sigdelsetmask(&set, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);
if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
goto segfault;
@@ -506,3 +611,14 @@ long sys_rt_sigreturn(struct pt_regs regs)
force_sig(SIGSEGV, current);
return 0;
}
+
+#ifdef CONFIG_X86_32
+long ptregs_sigreturn(void)
+{
+ return sys_sigreturn(NULL);
+}
+long ptregs_rt_sigreturn(void)
+{
+ return sys_rt_sigreturn(NULL);
+}
+#endif
diff --git a/arch/um/sys-i386/stub.S b/arch/x86/um/stub_32.S
index 54a36ec20cb7..54a36ec20cb7 100644
--- a/arch/um/sys-i386/stub.S
+++ b/arch/x86/um/stub_32.S
diff --git a/arch/um/sys-x86_64/stub.S b/arch/x86/um/stub_64.S
index 20e4a96a6dcb..20e4a96a6dcb 100644
--- a/arch/um/sys-x86_64/stub.S
+++ b/arch/x86/um/stub_64.S
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/x86/um/stub_segv.c
index ced051afc705..b7450bd22e7d 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/x86/um/stub_segv.c
@@ -3,19 +3,16 @@
* Licensed under the GPL
*/
-#include <signal.h>
-#include "as-layout.h"
#include "sysdep/stub.h"
#include "sysdep/faultinfo.h"
-#include "sysdep/sigcontext.h"
+#include "sysdep/mcontext.h"
void __attribute__ ((__section__ (".__syscall_stub")))
-stub_segv_handler(int sig)
+stub_segv_handler(int sig, siginfo_t *info, void *p)
{
- struct ucontext *uc;
+ struct ucontext *uc = p;
- __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
- GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA),
+ GET_FAULTINFO_FROM_MC(*((struct faultinfo *) STUB_DATA),
&uc->uc_mcontext);
trap_myself();
}
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/x86/um/sys_call_table_32.S
index de274071455d..a7ca80d2dceb 100644
--- a/arch/um/sys-i386/sys_call_table.S
+++ b/arch/x86/um/sys_call_table_32.S
@@ -13,16 +13,14 @@
#define ptregs_execve sys_execve
#define ptregs_iopl sys_iopl
#define ptregs_vm86old sys_vm86old
-#define ptregs_sigreturn sys_sigreturn
#define ptregs_clone sys_clone
#define ptregs_vm86 sys_vm86
-#define ptregs_rt_sigreturn sys_rt_sigreturn
#define ptregs_sigaltstack sys_sigaltstack
#define ptregs_vfork sys_vfork
.section .rodata,"a"
-#include "../../x86/kernel/syscall_table_32.S"
+#include "../kernel/syscall_table_32.S"
ENTRY(syscall_table_size)
.long .-sys_call_table
diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/x86/um/sys_call_table_64.c
index 47d469e7e7ce..99522f78b162 100644
--- a/arch/um/sys-x86_64/syscall_table.c
+++ b/arch/x86/um/sys_call_table_64.c
@@ -6,7 +6,6 @@
#include <linux/linkage.h>
#include <linux/sys.h>
#include <linux/cache.h>
-#include <kern_constants.h>
#define __NO_STUBS
@@ -59,7 +58,7 @@ extern void sys_ni_syscall(void);
*/
sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
-#include "../../x86/include/asm/unistd_64.h"
+#include <asm/unistd_64.h>
};
int syscall_table_size = sizeof(sys_call_table);
diff --git a/arch/um/sys-i386/syscalls.c b/arch/x86/um/syscalls_32.c
index 70ca357393b8..70ca357393b8 100644
--- a/arch/um/sys-i386/syscalls.c
+++ b/arch/x86/um/syscalls_32.c
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/x86/um/syscalls_64.c
index f3d82bb6e15a..f3d82bb6e15a 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/x86/um/syscalls_64.c
diff --git a/arch/um/sys-i386/sysrq.c b/arch/x86/um/sysrq_32.c
index 171b3e9dc867..171b3e9dc867 100644
--- a/arch/um/sys-i386/sysrq.c
+++ b/arch/x86/um/sysrq_32.c
diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/x86/um/sysrq_64.c
index f4f82beb3508..e8913436d7dc 100644
--- a/arch/um/sys-x86_64/sysrq.c
+++ b/arch/x86/um/sysrq_64.c
@@ -20,7 +20,7 @@ void __show_regs(struct pt_regs *regs)
current->comm, print_tainted(), init_utsname()->release);
printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
PT_REGS_RIP(regs));
- printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs),
+ printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_SP(regs),
PT_REGS_EFLAGS(regs));
printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
diff --git a/arch/um/sys-i386/tls.c b/arch/x86/um/tls_32.c
index c6c7131e563b..c6c7131e563b 100644
--- a/arch/um/sys-i386/tls.c
+++ b/arch/x86/um/tls_32.c
diff --git a/arch/um/sys-x86_64/tls.c b/arch/x86/um/tls_64.c
index f7ba46200ecd..f7ba46200ecd 100644
--- a/arch/um/sys-x86_64/tls.c
+++ b/arch/x86/um/tls_64.c
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/x86/um/user-offsets.c
index 973585414a66..ca49be8ddd0c 100644
--- a/arch/um/sys-x86_64/user-offsets.c
+++ b/arch/x86/um/user-offsets.c
@@ -9,28 +9,43 @@
#include <asm/types.h>
#define DEFINE(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define DEFINE_LONGS(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
-
-#define OFFSET(sym, str, mem) \
- DEFINE(sym, offsetof(struct str, mem));
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
void foo(void)
{
- OFFSET(HOST_SC_CR2, sigcontext, cr2);
- OFFSET(HOST_SC_ERR, sigcontext, err);
- OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
+#ifdef __i386__
+ DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
+ DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
+ DEFINE(HOST_IP, EIP);
+ DEFINE(HOST_SP, UESP);
+ DEFINE(HOST_EFLAGS, EFL);
+ DEFINE(HOST_AX, EAX);
+ DEFINE(HOST_BX, EBX);
+ DEFINE(HOST_CX, ECX);
+ DEFINE(HOST_DX, EDX);
+ DEFINE(HOST_SI, ESI);
+ DEFINE(HOST_DI, EDI);
+ DEFINE(HOST_BP, EBP);
+ DEFINE(HOST_CS, CS);
+ DEFINE(HOST_SS, SS);
+ DEFINE(HOST_DS, DS);
+ DEFINE(HOST_FS, FS);
+ DEFINE(HOST_ES, ES);
+ DEFINE(HOST_GS, GS);
+ DEFINE(HOST_ORIG_AX, ORIG_EAX);
+#else
DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
- DEFINE_LONGS(HOST_RBX, RBX);
- DEFINE_LONGS(HOST_RCX, RCX);
- DEFINE_LONGS(HOST_RDI, RDI);
- DEFINE_LONGS(HOST_RSI, RSI);
- DEFINE_LONGS(HOST_RDX, RDX);
- DEFINE_LONGS(HOST_RBP, RBP);
- DEFINE_LONGS(HOST_RAX, RAX);
+ DEFINE_LONGS(HOST_BX, RBX);
+ DEFINE_LONGS(HOST_CX, RCX);
+ DEFINE_LONGS(HOST_DI, RDI);
+ DEFINE_LONGS(HOST_SI, RSI);
+ DEFINE_LONGS(HOST_DX, RDX);
+ DEFINE_LONGS(HOST_BP, RBP);
+ DEFINE_LONGS(HOST_AX, RAX);
DEFINE_LONGS(HOST_R8, R8);
DEFINE_LONGS(HOST_R9, R9);
DEFINE_LONGS(HOST_R10, R10);
@@ -39,7 +54,7 @@ void foo(void)
DEFINE_LONGS(HOST_R13, R13);
DEFINE_LONGS(HOST_R14, R14);
DEFINE_LONGS(HOST_R15, R15);
- DEFINE_LONGS(HOST_ORIG_RAX, ORIG_RAX);
+ DEFINE_LONGS(HOST_ORIG_AX, ORIG_RAX);
DEFINE_LONGS(HOST_CS, CS);
DEFINE_LONGS(HOST_SS, SS);
DEFINE_LONGS(HOST_EFLAGS, EFLAGS);
@@ -52,9 +67,9 @@ void foo(void)
DEFINE_LONGS(HOST_IP, RIP);
DEFINE_LONGS(HOST_SP, RSP);
- DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+#endif
- /* XXX Duplicated between i386 and x86_64 */
+ DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
DEFINE(UM_POLLIN, POLLIN);
DEFINE(UM_POLLPRI, POLLPRI);
DEFINE(UM_POLLOUT, POLLOUT);
diff --git a/arch/um/sys-x86_64/vdso/Makefile b/arch/x86/um/vdso/Makefile
index 5dffe6d46686..6c803ca49b5d 100644
--- a/arch/um/sys-x86_64/vdso/Makefile
+++ b/arch/x86/um/vdso/Makefile
@@ -46,8 +46,8 @@ $(vobjs): KBUILD_CFLAGS += $(CFL)
#
# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
#
-CFLAGS_REMOVE_vdso-note.o = -pg
-CFLAGS_REMOVE_um_vdso.o = -pg
+CFLAGS_REMOVE_vdso-note.o = -pg -fprofile-arcs -ftest-coverage
+CFLAGS_REMOVE_um_vdso.o = -pg -fprofile-arcs -ftest-coverage
targets += vdso-syms.lds
obj-$(VDSO64-y) += vdso-syms.lds
diff --git a/arch/um/sys-x86_64/vdso/checkundef.sh b/arch/x86/um/vdso/checkundef.sh
index 7ee90a9b549d..7ee90a9b549d 100644
--- a/arch/um/sys-x86_64/vdso/checkundef.sh
+++ b/arch/x86/um/vdso/checkundef.sh
diff --git a/arch/um/sys-x86_64/vdso/um_vdso.c b/arch/x86/um/vdso/um_vdso.c
index 7c441b59d375..7c441b59d375 100644
--- a/arch/um/sys-x86_64/vdso/um_vdso.c
+++ b/arch/x86/um/vdso/um_vdso.c
diff --git a/arch/um/sys-x86_64/vdso/vdso-layout.lds.S b/arch/x86/um/vdso/vdso-layout.lds.S
index 634a2cf62046..634a2cf62046 100644
--- a/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
+++ b/arch/x86/um/vdso/vdso-layout.lds.S
diff --git a/arch/um/sys-x86_64/vdso/vdso-note.S b/arch/x86/um/vdso/vdso-note.S
index 79a071e4357e..79a071e4357e 100644
--- a/arch/um/sys-x86_64/vdso/vdso-note.S
+++ b/arch/x86/um/vdso/vdso-note.S
diff --git a/arch/um/sys-x86_64/vdso/vdso.S b/arch/x86/um/vdso/vdso.S
index ec82c1686bd6..1cb468adacbb 100644
--- a/arch/um/sys-x86_64/vdso/vdso.S
+++ b/arch/x86/um/vdso/vdso.S
@@ -4,7 +4,7 @@ __INITDATA
.globl vdso_start, vdso_end
vdso_start:
- .incbin "arch/um/sys-x86_64/vdso/vdso.so"
+ .incbin "arch/x86/um/vdso/vdso.so"
vdso_end:
__FINIT
diff --git a/arch/um/sys-x86_64/vdso/vdso.lds.S b/arch/x86/um/vdso/vdso.lds.S
index b96b2677cad8..b96b2677cad8 100644
--- a/arch/um/sys-x86_64/vdso/vdso.lds.S
+++ b/arch/x86/um/vdso/vdso.lds.S
diff --git a/arch/um/sys-x86_64/vdso/vma.c b/arch/x86/um/vdso/vma.c
index 9495c8d0ce37..91f4ec9a0a56 100644
--- a/arch/um/sys-x86_64/vdso/vma.c
+++ b/arch/x86/um/vdso/vma.c
@@ -28,7 +28,7 @@ static int __init init_vdso(void)
um_vdso_addr = task_size - PAGE_SIZE;
- vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *));
+ vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL);
if (!vdsop)
goto oom;
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
index 316fbca3490e..153407c35b75 100644
--- a/arch/x86/vdso/vma.c
+++ b/arch/x86/vdso/vma.c
@@ -89,6 +89,15 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
addr = start + (offset << PAGE_SHIFT);
if (addr >= end)
addr = end;
+
+ /*
+ * page-align it here so that get_unmapped_area doesn't
+ * align it wrongfully again to the next page. addr can come in 4K
+ * unaligned here as a result of stack start randomization.
+ */
+ addr = PAGE_ALIGN(addr);
+ addr = align_addr(addr, NULL, ALIGN_VDSO);
+
return addr;
}
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index 5cc821cb2e09..26c731a106af 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -25,8 +25,7 @@ config XEN_PRIVILEGED_GUEST
config XEN_PVHVM
def_bool y
- depends on XEN
- depends on X86_LOCAL_APIC
+ depends on XEN && PCI && X86_LOCAL_APIC
config XEN_MAX_DOMAIN_MEMORY
int
@@ -49,11 +48,3 @@ config XEN_DEBUG_FS
help
Enable statistics output and various tuning options in debugfs.
Enabling this option may incur a significant performance overhead.
-
-config XEN_DEBUG
- bool "Enable Xen debug checks"
- depends on XEN
- default n
- help
- Enable various WARN_ON checks in the Xen MMU code.
- Enabling this option WILL incur a significant performance overhead.
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 2d69617950f7..da8afd576a6b 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -251,6 +251,7 @@ static void __init xen_init_cpuid_mask(void)
~((1 << X86_FEATURE_APIC) | /* disable local APIC */
(1 << X86_FEATURE_ACPI)); /* disable ACPI */
ax = 1;
+ cx = 0;
xen_cpuid(&ax, &bx, &cx, &dx);
xsave_mask =
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 3dd53f997b11..87f6673b1207 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -495,41 +495,6 @@ static pte_t xen_make_pte(pteval_t pte)
}
PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte);
-#ifdef CONFIG_XEN_DEBUG
-pte_t xen_make_pte_debug(pteval_t pte)
-{
- phys_addr_t addr = (pte & PTE_PFN_MASK);
- phys_addr_t other_addr;
- bool io_page = false;
- pte_t _pte;
-
- if (pte & _PAGE_IOMAP)
- io_page = true;
-
- _pte = xen_make_pte(pte);
-
- if (!addr)
- return _pte;
-
- if (io_page &&
- (xen_initial_domain() || addr >= ISA_END_ADDRESS)) {
- other_addr = pfn_to_mfn(addr >> PAGE_SHIFT) << PAGE_SHIFT;
- WARN_ONCE(addr != other_addr,
- "0x%lx is using VM_IO, but it is 0x%lx!\n",
- (unsigned long)addr, (unsigned long)other_addr);
- } else {
- pteval_t iomap_set = (_pte.pte & PTE_FLAGS_MASK) & _PAGE_IOMAP;
- other_addr = (_pte.pte & PTE_PFN_MASK);
- WARN_ONCE((addr == other_addr) && (!io_page) && (!iomap_set),
- "0x%lx is missing VM_IO (and wasn't fixed)!\n",
- (unsigned long)addr);
- }
-
- return _pte;
-}
-PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_debug);
-#endif
-
static pgd_t xen_make_pgd(pgdval_t pgd)
{
pgd = pte_pfn_to_mfn(pgd);
@@ -1992,9 +1957,6 @@ void __init xen_ident_map_ISA(void)
static void __init xen_post_allocator_init(void)
{
-#ifdef CONFIG_XEN_DEBUG
- pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug);
-#endif
pv_mmu_ops.set_pte = xen_set_pte;
pv_mmu_ops.set_pmd = xen_set_pmd;
pv_mmu_ops.set_pud = xen_set_pud;
@@ -2404,17 +2366,3 @@ out:
return err;
}
EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
-
-#ifdef CONFIG_XEN_DEBUG_FS
-static int p2m_dump_open(struct inode *inode, struct file *filp)
-{
- return single_open(filp, p2m_dump_show, NULL);
-}
-
-static const struct file_operations p2m_dump_fops = {
- .open = p2m_dump_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-#endif /* CONFIG_XEN_DEBUG_FS */
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 58efeb9d5440..1b267e75158d 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -161,7 +161,9 @@
#include <asm/xen/page.h>
#include <asm/xen/hypercall.h>
#include <asm/xen/hypervisor.h>
+#include <xen/grant_table.h>
+#include "multicalls.h"
#include "xen-ops.h"
static void __init m2p_override_init(void);
@@ -676,7 +678,8 @@ static unsigned long mfn_hash(unsigned long mfn)
}
/* Add an MFN override for a particular page */
-int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte)
+int m2p_add_override(unsigned long mfn, struct page *page,
+ struct gnttab_map_grant_ref *kmap_op)
{
unsigned long flags;
unsigned long pfn;
@@ -692,16 +695,28 @@ int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte)
"m2p_add_override: pfn %lx not mapped", pfn))
return -EINVAL;
}
-
- page->private = mfn;
+ WARN_ON(PagePrivate(page));
+ SetPagePrivate(page);
+ set_page_private(page, mfn);
page->index = pfn_to_mfn(pfn);
if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
return -ENOMEM;
- if (clear_pte && !PageHighMem(page))
- /* Just zap old mapping for now */
- pte_clear(&init_mm, address, ptep);
+ if (kmap_op != NULL) {
+ if (!PageHighMem(page)) {
+ struct multicall_space mcs =
+ xen_mc_entry(sizeof(*kmap_op));
+
+ MULTI_grant_table_op(mcs.mc,
+ GNTTABOP_map_grant_ref, kmap_op, 1);
+
+ xen_mc_issue(PARAVIRT_LAZY_MMU);
+ }
+ /* let's use dev_bus_addr to record the old mfn instead */
+ kmap_op->dev_bus_addr = page->index;
+ page->index = (unsigned long) kmap_op;
+ }
spin_lock_irqsave(&m2p_override_lock, flags);
list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
spin_unlock_irqrestore(&m2p_override_lock, flags);
@@ -735,13 +750,56 @@ int m2p_remove_override(struct page *page, bool clear_pte)
spin_lock_irqsave(&m2p_override_lock, flags);
list_del(&page->lru);
spin_unlock_irqrestore(&m2p_override_lock, flags);
- set_phys_to_machine(pfn, page->index);
+ WARN_ON(!PagePrivate(page));
+ ClearPagePrivate(page);
- if (clear_pte && !PageHighMem(page))
- set_pte_at(&init_mm, address, ptep,
- pfn_pte(pfn, PAGE_KERNEL));
- /* No tlb flush necessary because the caller already
- * left the pte unmapped. */
+ if (clear_pte) {
+ struct gnttab_map_grant_ref *map_op =
+ (struct gnttab_map_grant_ref *) page->index;
+ set_phys_to_machine(pfn, map_op->dev_bus_addr);
+ if (!PageHighMem(page)) {
+ struct multicall_space mcs;
+ struct gnttab_unmap_grant_ref *unmap_op;
+
+ /*
+ * It might be that we queued all the m2p grant table
+ * hypercalls in a multicall, then m2p_remove_override
+ * get called before the multicall has actually been
+ * issued. In this case handle is going to -1 because
+ * it hasn't been modified yet.
+ */
+ if (map_op->handle == -1)
+ xen_mc_flush();
+ /*
+ * Now if map_op->handle is negative it means that the
+ * hypercall actually returned an error.
+ */
+ if (map_op->handle == GNTST_general_error) {
+ printk(KERN_WARNING "m2p_remove_override: "
+ "pfn %lx mfn %lx, failed to modify kernel mappings",
+ pfn, mfn);
+ return -1;
+ }
+
+ mcs = xen_mc_entry(
+ sizeof(struct gnttab_unmap_grant_ref));
+ unmap_op = mcs.args;
+ unmap_op->host_addr = map_op->host_addr;
+ unmap_op->handle = map_op->handle;
+ unmap_op->dev_bus_addr = 0;
+
+ MULTI_grant_table_op(mcs.mc,
+ GNTTABOP_unmap_grant_ref, unmap_op, 1);
+
+ xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+ set_pte_at(&init_mm, address, ptep,
+ pfn_pte(pfn, PAGE_KERNEL));
+ __flush_tlb_single(address);
+ map_op->host_addr = 0;
+ }
+ } else
+ set_phys_to_machine(pfn, page->index);
return 0;
}
@@ -758,7 +816,7 @@ struct page *m2p_find_override(unsigned long mfn)
spin_lock_irqsave(&m2p_override_lock, flags);
list_for_each_entry(p, bucket, lru) {
- if (p->private == mfn) {
+ if (page_private(p) == mfn) {
ret = p;
break;
}
@@ -782,17 +840,21 @@ unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn)
EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
#ifdef CONFIG_XEN_DEBUG_FS
-
-int p2m_dump_show(struct seq_file *m, void *v)
+#include <linux/debugfs.h>
+#include "debugfs.h"
+static int p2m_dump_show(struct seq_file *m, void *v)
{
static const char * const level_name[] = { "top", "middle",
- "entry", "abnormal" };
- static const char * const type_name[] = { "identity", "missing",
- "pfn", "abnormal"};
+ "entry", "abnormal", "error"};
#define TYPE_IDENTITY 0
#define TYPE_MISSING 1
#define TYPE_PFN 2
#define TYPE_UNKNOWN 3
+ static const char * const type_name[] = {
+ [TYPE_IDENTITY] = "identity",
+ [TYPE_MISSING] = "missing",
+ [TYPE_PFN] = "pfn",
+ [TYPE_UNKNOWN] = "abnormal"};
unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0;
unsigned int uninitialized_var(prev_level);
unsigned int uninitialized_var(prev_type);
@@ -856,4 +918,32 @@ int p2m_dump_show(struct seq_file *m, void *v)
#undef TYPE_PFN
#undef TYPE_UNKNOWN
}
-#endif
+
+static int p2m_dump_open(struct inode *inode, struct file *filp)
+{
+ return single_open(filp, p2m_dump_show, NULL);
+}
+
+static const struct file_operations p2m_dump_fops = {
+ .open = p2m_dump_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct dentry *d_mmu_debug;
+
+static int __init xen_p2m_debugfs(void)
+{
+ struct dentry *d_xen = xen_init_debugfs();
+
+ if (d_xen == NULL)
+ return -ENOMEM;
+
+ d_mmu_debug = debugfs_create_dir("mmu", d_xen);
+
+ debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
+ return 0;
+}
+fs_initcall(xen_p2m_debugfs);
+#endif /* CONFIG_XEN_DEBUG_FS */
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 46d6d21dbdbe..38d0af4fefec 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -37,7 +37,10 @@ extern void xen_syscall_target(void);
extern void xen_syscall32_target(void);
/* Amount of extra memory space we add to the e820 ranges */
-phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
+struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
+
+/* Number of pages released from the initial allocation. */
+unsigned long xen_released_pages;
/*
* The maximum amount of extra memory compared to the base size. The
@@ -51,48 +54,47 @@ phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
*/
#define EXTRA_MEM_RATIO (10)
-static void __init xen_add_extra_mem(unsigned long pages)
+static void __init xen_add_extra_mem(u64 start, u64 size)
{
unsigned long pfn;
+ int i;
- u64 size = (u64)pages * PAGE_SIZE;
- u64 extra_start = xen_extra_mem_start + xen_extra_mem_size;
-
- if (!pages)
- return;
-
- e820_add_region(extra_start, size, E820_RAM);
- sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
-
- memblock_x86_reserve_range(extra_start, extra_start + size, "XEN EXTRA");
+ for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
+ /* Add new region. */
+ if (xen_extra_mem[i].size == 0) {
+ xen_extra_mem[i].start = start;
+ xen_extra_mem[i].size = size;
+ break;
+ }
+ /* Append to existing region. */
+ if (xen_extra_mem[i].start + xen_extra_mem[i].size == start) {
+ xen_extra_mem[i].size += size;
+ break;
+ }
+ }
+ if (i == XEN_EXTRA_MEM_MAX_REGIONS)
+ printk(KERN_WARNING "Warning: not enough extra memory regions\n");
- xen_extra_mem_size += size;
+ memblock_x86_reserve_range(start, start + size, "XEN EXTRA");
- xen_max_p2m_pfn = PFN_DOWN(extra_start + size);
+ xen_max_p2m_pfn = PFN_DOWN(start + size);
- for (pfn = PFN_DOWN(extra_start); pfn <= xen_max_p2m_pfn; pfn++)
+ for (pfn = PFN_DOWN(start); pfn <= xen_max_p2m_pfn; pfn++)
__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
}
-static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
- phys_addr_t end_addr)
+static unsigned long __init xen_release_chunk(unsigned long start,
+ unsigned long end)
{
struct xen_memory_reservation reservation = {
.address_bits = 0,
.extent_order = 0,
.domid = DOMID_SELF
};
- unsigned long start, end;
unsigned long len = 0;
unsigned long pfn;
int ret;
- start = PFN_UP(start_addr);
- end = PFN_DOWN(end_addr);
-
- if (end <= start)
- return 0;
-
for(pfn = start; pfn < end; pfn++) {
unsigned long mfn = pfn_to_mfn(pfn);
@@ -117,72 +119,52 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
return len;
}
-static unsigned long __init xen_return_unused_memory(unsigned long max_pfn,
- const struct e820map *e820)
+static unsigned long __init xen_set_identity_and_release(
+ const struct e820entry *list, size_t map_size, unsigned long nr_pages)
{
- phys_addr_t max_addr = PFN_PHYS(max_pfn);
- phys_addr_t last_end = ISA_END_ADDRESS;
+ phys_addr_t start = 0;
unsigned long released = 0;
- int i;
-
- /* Free any unused memory above the low 1Mbyte. */
- for (i = 0; i < e820->nr_map && last_end < max_addr; i++) {
- phys_addr_t end = e820->map[i].addr;
- end = min(max_addr, end);
-
- if (last_end < end)
- released += xen_release_chunk(last_end, end);
- last_end = max(last_end, e820->map[i].addr + e820->map[i].size);
- }
-
- if (last_end < max_addr)
- released += xen_release_chunk(last_end, max_addr);
-
- printk(KERN_INFO "released %lu pages of unused memory\n", released);
- return released;
-}
-
-static unsigned long __init xen_set_identity(const struct e820entry *list,
- ssize_t map_size)
-{
- phys_addr_t last = xen_initial_domain() ? 0 : ISA_END_ADDRESS;
- phys_addr_t start_pci = last;
- const struct e820entry *entry;
unsigned long identity = 0;
+ const struct e820entry *entry;
int i;
+ /*
+ * Combine non-RAM regions and gaps until a RAM region (or the
+ * end of the map) is reached, then set the 1:1 map and
+ * release the pages (if available) in those non-RAM regions.
+ *
+ * The combined non-RAM regions are rounded to a whole number
+ * of pages so any partial pages are accessible via the 1:1
+ * mapping. This is needed for some BIOSes that put (for
+ * example) the DMI tables in a reserved region that begins on
+ * a non-page boundary.
+ */
for (i = 0, entry = list; i < map_size; i++, entry++) {
- phys_addr_t start = entry->addr;
- phys_addr_t end = start + entry->size;
+ phys_addr_t end = entry->addr + entry->size;
- if (start < last)
- start = last;
+ if (entry->type == E820_RAM || i == map_size - 1) {
+ unsigned long start_pfn = PFN_DOWN(start);
+ unsigned long end_pfn = PFN_UP(end);
- if (end <= start)
- continue;
+ if (entry->type == E820_RAM)
+ end_pfn = PFN_UP(entry->addr);
- /* Skip over the 1MB region. */
- if (last > end)
- continue;
+ if (start_pfn < end_pfn) {
+ if (start_pfn < nr_pages)
+ released += xen_release_chunk(
+ start_pfn, min(end_pfn, nr_pages));
- if ((entry->type == E820_RAM) || (entry->type == E820_UNUSABLE)) {
- if (start > start_pci)
identity += set_phys_range_identity(
- PFN_UP(start_pci), PFN_DOWN(start));
-
- /* Without saving 'last' we would gooble RAM too
- * at the end of the loop. */
- last = end;
- start_pci = end;
- continue;
+ start_pfn, end_pfn);
+ }
+ start = end;
}
- start_pci = min(start, start_pci);
- last = end;
}
- if (last > start_pci)
- identity += set_phys_range_identity(
- PFN_UP(start_pci), PFN_DOWN(last));
- return identity;
+
+ printk(KERN_INFO "Released %lu pages of unused memory\n", released);
+ printk(KERN_INFO "Set %ld page(s) to 1-1 mapping\n", identity);
+
+ return released;
}
static unsigned long __init xen_get_max_pages(void)
@@ -197,21 +179,32 @@ static unsigned long __init xen_get_max_pages(void)
return min(max_pages, MAX_DOMAIN_PAGES);
}
+static void xen_align_and_add_e820_region(u64 start, u64 size, int type)
+{
+ u64 end = start + size;
+
+ /* Align RAM regions to page boundaries. */
+ if (type == E820_RAM) {
+ start = PAGE_ALIGN(start);
+ end &= ~((u64)PAGE_SIZE - 1);
+ }
+
+ e820_add_region(start, end - start, type);
+}
+
/**
* machine_specific_memory_setup - Hook for machine specific memory setup.
**/
char * __init xen_memory_setup(void)
{
static struct e820entry map[E820MAX] __initdata;
- static struct e820entry map_raw[E820MAX] __initdata;
unsigned long max_pfn = xen_start_info->nr_pages;
unsigned long long mem_end;
int rc;
struct xen_memory_map memmap;
+ unsigned long max_pages;
unsigned long extra_pages = 0;
- unsigned long extra_limit;
- unsigned long identity_pages = 0;
int i;
int op;
@@ -237,58 +230,65 @@ char * __init xen_memory_setup(void)
}
BUG_ON(rc);
- memcpy(map_raw, map, sizeof(map));
- e820.nr_map = 0;
- xen_extra_mem_start = mem_end;
- for (i = 0; i < memmap.nr_entries; i++) {
- unsigned long long end;
-
- /* Guard against non-page aligned E820 entries. */
- if (map[i].type == E820_RAM)
- map[i].size -= (map[i].size + map[i].addr) % PAGE_SIZE;
-
- end = map[i].addr + map[i].size;
- if (map[i].type == E820_RAM && end > mem_end) {
- /* RAM off the end - may be partially included */
- u64 delta = min(map[i].size, end - mem_end);
-
- map[i].size -= delta;
- end -= delta;
-
- extra_pages += PFN_DOWN(delta);
- /*
- * Set RAM below 4GB that is not for us to be unusable.
- * This prevents "System RAM" address space from being
- * used as potential resource for I/O address (happens
- * when 'allocate_resource' is called).
- */
- if (delta &&
- (xen_initial_domain() && end < 0x100000000ULL))
- e820_add_region(end, delta, E820_UNUSABLE);
+ /* Make sure the Xen-supplied memory map is well-ordered. */
+ sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
+
+ max_pages = xen_get_max_pages();
+ if (max_pages > max_pfn)
+ extra_pages += max_pages - max_pfn;
+
+ /*
+ * Set P2M for all non-RAM pages and E820 gaps to be identity
+ * type PFNs. Any RAM pages that would be made inaccesible by
+ * this are first released.
+ */
+ xen_released_pages = xen_set_identity_and_release(
+ map, memmap.nr_entries, max_pfn);
+ extra_pages += xen_released_pages;
+
+ /*
+ * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
+ * factor the base size. On non-highmem systems, the base
+ * size is the full initial memory allocation; on highmem it
+ * is limited to the max size of lowmem, so that it doesn't
+ * get completely filled.
+ *
+ * In principle there could be a problem in lowmem systems if
+ * the initial memory is also very large with respect to
+ * lowmem, but we won't try to deal with that here.
+ */
+ extra_pages = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)),
+ extra_pages);
+
+ i = 0;
+ while (i < memmap.nr_entries) {
+ u64 addr = map[i].addr;
+ u64 size = map[i].size;
+ u32 type = map[i].type;
+
+ if (type == E820_RAM) {
+ if (addr < mem_end) {
+ size = min(size, mem_end - addr);
+ } else if (extra_pages) {
+ size = min(size, (u64)extra_pages * PAGE_SIZE);
+ extra_pages -= size / PAGE_SIZE;
+ xen_add_extra_mem(addr, size);
+ } else
+ type = E820_UNUSABLE;
}
- if (map[i].size > 0 && end > xen_extra_mem_start)
- xen_extra_mem_start = end;
+ xen_align_and_add_e820_region(addr, size, type);
- /* Add region if any remains */
- if (map[i].size > 0)
- e820_add_region(map[i].addr, map[i].size, map[i].type);
+ map[i].addr += size;
+ map[i].size -= size;
+ if (map[i].size == 0)
+ i++;
}
- /* Align the balloon area so that max_low_pfn does not get set
- * to be at the _end_ of the PCI gap at the far end (fee01000).
- * Note that xen_extra_mem_start gets set in the loop above to be
- * past the last E820 region. */
- if (xen_initial_domain() && (xen_extra_mem_start < (1ULL<<32)))
- xen_extra_mem_start = (1ULL<<32);
/*
* In domU, the ISA region is normal, usable memory, but we
* reserve ISA memory anyway because too many things poke
* about in there.
- *
- * In Dom0, the host E820 information can leave gaps in the
- * ISA range, which would cause us to release those pages. To
- * avoid this, we unconditionally reserve them here.
*/
e820_add_region(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS,
E820_RESERVED);
@@ -305,44 +305,6 @@ char * __init xen_memory_setup(void)
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
- extra_limit = xen_get_max_pages();
- if (max_pfn + extra_pages > extra_limit) {
- if (extra_limit > max_pfn)
- extra_pages = extra_limit - max_pfn;
- else
- extra_pages = 0;
- }
-
- extra_pages += xen_return_unused_memory(xen_start_info->nr_pages, &e820);
-
- /*
- * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
- * factor the base size. On non-highmem systems, the base
- * size is the full initial memory allocation; on highmem it
- * is limited to the max size of lowmem, so that it doesn't
- * get completely filled.
- *
- * In principle there could be a problem in lowmem systems if
- * the initial memory is also very large with respect to
- * lowmem, but we won't try to deal with that here.
- */
- extra_limit = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)),
- max_pfn + extra_pages);
-
- if (extra_limit >= max_pfn)
- extra_pages = extra_limit - max_pfn;
- else
- extra_pages = 0;
-
- xen_add_extra_mem(extra_pages);
-
- /*
- * Set P2M for all non-RAM pages and E820 gaps to be identity
- * type PFNs. We supply it with the non-sanitized version
- * of the E820.
- */
- identity_pages = xen_set_identity(map_raw, memmap.nr_entries);
- printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages);
return "Xen";
}
diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig
index 0234cd198c54..f932b30b47fb 100644
--- a/arch/xtensa/configs/iss_defconfig
+++ b/arch/xtensa/configs/iss_defconfig
@@ -15,7 +15,6 @@ CONFIG_GENERIC_GPIO=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_NO_IOPORT=y
CONFIG_HZ=100
-CONFIG_GENERIC_TIME=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_CONSTRUCTORS=y
diff --git a/arch/xtensa/configs/s6105_defconfig b/arch/xtensa/configs/s6105_defconfig
index 4891abbf16bc..550e8ed5b5c6 100644
--- a/arch/xtensa/configs/s6105_defconfig
+++ b/arch/xtensa/configs/s6105_defconfig
@@ -15,7 +15,6 @@ CONFIG_GENERIC_GPIO=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_NO_IOPORT=y
CONFIG_HZ=100
-CONFIG_GENERIC_TIME=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c
index f717e20d961b..7dde24456427 100644
--- a/arch/xtensa/platforms/iss/network.c
+++ b/arch/xtensa/platforms/iss/network.c
@@ -633,7 +633,7 @@ static const struct net_device_ops iss_netdev_ops = {
.ndo_set_mac_address = iss_net_set_mac,
//.ndo_do_ioctl = iss_net_ioctl,
.ndo_tx_timeout = iss_net_tx_timeout,
- .ndo_set_multicast_list = iss_net_set_multicast_list,
+ .ndo_set_rx_mode = iss_net_set_multicast_list,
};
static int iss_net_configure(int index, char *init)
diff --git a/block/genhd.c b/block/genhd.c
index e2f67902dd02..94855a9717de 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -19,6 +19,7 @@
#include <linux/mutex.h>
#include <linux/idr.h>
#include <linux/log2.h>
+#include <linux/ctype.h>
#include "blk.h"
@@ -909,6 +910,74 @@ static int __init genhd_device_init(void)
subsys_initcall(genhd_device_init);
+static ssize_t alias_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gendisk *disk = dev_to_disk(dev);
+ ssize_t ret = 0;
+
+ if (disk->alias)
+ ret = snprintf(buf, ALIAS_LEN, "%s\n", disk->alias);
+ return ret;
+}
+
+static ssize_t alias_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct gendisk *disk = dev_to_disk(dev);
+ char *alias;
+ char *envp[] = { NULL, NULL };
+ unsigned char c;
+ int i;
+ ssize_t ret = count;
+
+ if (!count)
+ return -EINVAL;
+
+ if (count >= ALIAS_LEN) {
+ printk(KERN_ERR "alias: alias is too long\n");
+ return -EINVAL;
+ }
+
+ /* Validation check */
+ for (i = 0; i < count; i++) {
+ c = buf[i];
+ if (i == count - 1 && c == '\n')
+ break;
+ if (!isalnum(c) && c != '_' && c != '-') {
+ printk(KERN_ERR "alias: invalid alias\n");
+ return -EINVAL;
+ }
+ }
+
+ if (disk->alias) {
+ printk(KERN_INFO "alias: %s is already assigned (%s)\n",
+ disk->disk_name, disk->alias);
+ return -EINVAL;
+ }
+
+ alias = kasprintf(GFP_KERNEL, "%s", buf);
+ if (!alias)
+ return -ENOMEM;
+
+ if (alias[count - 1] == '\n')
+ alias[count - 1] = '\0';
+
+ envp[0] = kasprintf(GFP_KERNEL, "ALIAS=%s", alias);
+ if (!envp[0]) {
+ kfree(alias);
+ return -ENOMEM;
+ }
+
+ disk->alias = alias;
+ printk(KERN_INFO "alias: assigned %s to %s\n", alias, disk->disk_name);
+
+ kobject_uevent_env(&dev->kobj, KOBJ_ADD, envp);
+
+ kfree(envp[0]);
+ return ret;
+}
+
static ssize_t disk_range_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -968,6 +1037,7 @@ static ssize_t disk_discard_alignment_show(struct device *dev,
return sprintf(buf, "%d\n", queue_discard_alignment(disk->queue));
}
+static DEVICE_ATTR(alias, S_IRUGO|S_IWUSR, alias_show, alias_store);
static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL);
static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL);
static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL);
@@ -990,6 +1060,7 @@ static struct device_attribute dev_attr_fail_timeout =
#endif
static struct attribute *disk_attrs[] = {
+ &dev_attr_alias.attr,
&dev_attr_range.attr,
&dev_attr_ext_range.attr,
&dev_attr_removable.attr,
diff --git a/crypto/Kconfig b/crypto/Kconfig
index ae27b7534ea7..527a857d10b6 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -100,6 +100,14 @@ config CRYPTO_MANAGER2
select CRYPTO_BLKCIPHER2
select CRYPTO_PCOMP2
+config CRYPTO_USER
+ tristate "Userspace cryptographic algorithm configuration"
+ depends on NET
+ select CRYPTO_MANAGER
+ help
+ Userapace configuration for cryptographic instantiations such as
+ cbc(aes).
+
config CRYPTO_MANAGER_DISABLE_TESTS
bool "Disable run-time self tests"
default y
@@ -407,6 +415,16 @@ config CRYPTO_SHA1
help
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+config CRYPTO_SHA1_SSSE3
+ tristate "SHA1 digest algorithm (SSSE3/AVX)"
+ depends on X86 && 64BIT
+ select CRYPTO_SHA1
+ select CRYPTO_HASH
+ help
+ SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+ using Supplemental SSE3 (SSSE3) instructions or Advanced Vector
+ Extensions (AVX), when available.
+
config CRYPTO_SHA256
tristate "SHA224 and SHA256 digest algorithm"
select CRYPTO_HASH
@@ -590,6 +608,7 @@ config CRYPTO_ARC4
config CRYPTO_BLOWFISH
tristate "Blowfish cipher algorithm"
select CRYPTO_ALGAPI
+ select CRYPTO_BLOWFISH_COMMON
help
Blowfish cipher algorithm, by Bruce Schneier.
@@ -600,6 +619,30 @@ config CRYPTO_BLOWFISH
See also:
<http://www.schneier.com/blowfish.html>
+config CRYPTO_BLOWFISH_COMMON
+ tristate
+ help
+ Common parts of the Blowfish cipher algorithm shared by the
+ generic c and the assembler implementations.
+
+ See also:
+ <http://www.schneier.com/blowfish.html>
+
+config CRYPTO_BLOWFISH_X86_64
+ tristate "Blowfish cipher algorithm (x86_64)"
+ depends on (X86 || UML_X86) && 64BIT
+ select CRYPTO_ALGAPI
+ select CRYPTO_BLOWFISH_COMMON
+ help
+ Blowfish cipher algorithm (x86_64), by Bruce Schneier.
+
+ This is a variable key length cipher which can use keys from 32
+ bits to 448 bits in length. It's fast, simple and specifically
+ designed for use on "large microprocessors".
+
+ See also:
+ <http://www.schneier.com/blowfish.html>
+
config CRYPTO_CAMELLIA
tristate "Camellia cipher algorithms"
depends on CRYPTO
@@ -793,6 +836,26 @@ config CRYPTO_TWOFISH_X86_64
See also:
<http://www.schneier.com/twofish.html>
+config CRYPTO_TWOFISH_X86_64_3WAY
+ tristate "Twofish cipher algorithm (x86_64, 3-way parallel)"
+ depends on (X86 || UML_X86) && 64BIT
+ select CRYPTO_ALGAPI
+ select CRYPTO_TWOFISH_COMMON
+ select CRYPTO_TWOFISH_X86_64
+ help
+ Twofish cipher algorithm (x86_64, 3-way parallel).
+
+ Twofish was submitted as an AES (Advanced Encryption Standard)
+ candidate cipher by researchers at CounterPane Systems. It is a
+ 16 round block cipher supporting key sizes of 128, 192, and 256
+ bits.
+
+ This module provides Twofish cipher algorithm that processes three
+ blocks parallel, utilizing resources of out-of-order CPUs better.
+
+ See also:
+ <http://www.schneier.com/twofish.html>
+
comment "Compression"
config CRYPTO_DEFLATE
diff --git a/crypto/Makefile b/crypto/Makefile
index ce5a813d3639..9e6eee2c05db 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o
cryptomgr-y := algboss.o testmgr.o
obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
+obj-$(CONFIG_CRYPTO_USER) += crypto_user.o
obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
obj-$(CONFIG_CRYPTO_VMAC) += vmac.o
obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
@@ -60,7 +61,8 @@ obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o
obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
obj-$(CONFIG_CRYPTO_DES) += des_generic.o
obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
-obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
+obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish_generic.o
+obj-$(CONFIG_CRYPTO_BLOWFISH_COMMON) += blowfish_common.o
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish_generic.o
obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index fdc67d38660b..a816f24f2d52 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -23,6 +23,8 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
#include <crypto/scatterwalk.h>
@@ -381,6 +383,28 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
return 0;
}
+static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_blkcipher rblkcipher;
+
+ snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher");
+ snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+ alg->cra_ablkcipher.geniv ?: "<default>");
+
+ rblkcipher.blocksize = alg->cra_blocksize;
+ rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
+ rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
+ rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+ sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
__attribute__ ((unused));
static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -403,6 +427,7 @@ const struct crypto_type crypto_ablkcipher_type = {
#ifdef CONFIG_PROC_FS
.show = crypto_ablkcipher_show,
#endif
+ .report = crypto_ablkcipher_report,
};
EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
@@ -432,6 +457,28 @@ static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
return 0;
}
+static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_blkcipher rblkcipher;
+
+ snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher");
+ snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+ alg->cra_ablkcipher.geniv ?: "<built-in>");
+
+ rblkcipher.blocksize = alg->cra_blocksize;
+ rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
+ rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
+ rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+ sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
__attribute__ ((unused));
static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -454,6 +501,7 @@ const struct crypto_type crypto_givcipher_type = {
#ifdef CONFIG_PROC_FS
.show = crypto_givcipher_show,
#endif
+ .report = crypto_givcipher_report,
};
EXPORT_SYMBOL_GPL(crypto_givcipher_type);
diff --git a/crypto/aead.c b/crypto/aead.c
index 6729e8ff68e7..701556ffaaef 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -21,6 +21,8 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
#include "internal.h"
@@ -109,6 +111,28 @@ static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
return 0;
}
+static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_aead raead;
+ struct aead_alg *aead = &alg->cra_aead;
+
+ snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead");
+ snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+ aead->geniv ?: "<built-in>");
+
+ raead.blocksize = alg->cra_blocksize;
+ raead.maxauthsize = aead->maxauthsize;
+ raead.ivsize = aead->ivsize;
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
+ sizeof(struct crypto_report_aead), &raead);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
__attribute__ ((unused));
static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
@@ -130,6 +154,7 @@ const struct crypto_type crypto_aead_type = {
#ifdef CONFIG_PROC_FS
.show = crypto_aead_show,
#endif
+ .report = crypto_aead_report,
};
EXPORT_SYMBOL_GPL(crypto_aead_type);
@@ -165,6 +190,28 @@ static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
return 0;
}
+static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_aead raead;
+ struct aead_alg *aead = &alg->cra_aead;
+
+ snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead");
+ snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv);
+
+ raead.blocksize = alg->cra_blocksize;
+ raead.maxauthsize = aead->maxauthsize;
+ raead.ivsize = aead->ivsize;
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
+ sizeof(struct crypto_report_aead), &raead);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+
static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
__attribute__ ((unused));
static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
@@ -186,6 +233,7 @@ const struct crypto_type crypto_nivaead_type = {
#ifdef CONFIG_PROC_FS
.show = crypto_nivaead_show,
#endif
+ .report = crypto_nivaead_report,
};
EXPORT_SYMBOL_GPL(crypto_nivaead_type);
diff --git a/crypto/ahash.c b/crypto/ahash.c
index f669822a7a44..a3e6ef99394a 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -21,6 +21,8 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
#include "internal.h"
@@ -397,6 +399,24 @@ static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
return sizeof(struct crypto_shash *);
}
+static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_hash rhash;
+
+ snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash");
+
+ rhash.blocksize = alg->cra_blocksize;
+ rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
+ sizeof(struct crypto_report_hash), &rhash);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
__attribute__ ((unused));
static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
@@ -415,6 +435,7 @@ const struct crypto_type crypto_ahash_type = {
#ifdef CONFIG_PROC_FS
.show = crypto_ahash_show,
#endif
+ .report = crypto_ahash_report,
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
.type = CRYPTO_ALG_TYPE_AHASH,
diff --git a/crypto/algapi.c b/crypto/algapi.c
index c3cf1a69a47a..54dd4e33b5d6 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -22,8 +22,6 @@
#include "internal.h"
-static void crypto_remove_final(struct list_head *list);
-
static LIST_HEAD(crypto_template_list);
void crypto_larval_error(const char *name, u32 type, u32 mask)
@@ -129,9 +127,8 @@ static void crypto_remove_spawn(struct crypto_spawn *spawn,
BUG_ON(!list_empty(&inst->alg.cra_users));
}
-static void crypto_remove_spawns(struct crypto_alg *alg,
- struct list_head *list,
- struct crypto_alg *nalg)
+void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
+ struct crypto_alg *nalg)
{
u32 new_type = (nalg ?: alg)->cra_flags;
struct crypto_spawn *spawn, *n;
@@ -177,6 +174,7 @@ static void crypto_remove_spawns(struct crypto_alg *alg,
crypto_remove_spawn(spawn, list);
}
}
+EXPORT_SYMBOL_GPL(crypto_remove_spawns);
static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
{
@@ -321,7 +319,7 @@ unlock:
}
EXPORT_SYMBOL_GPL(crypto_alg_tested);
-static void crypto_remove_final(struct list_head *list)
+void crypto_remove_final(struct list_head *list)
{
struct crypto_alg *alg;
struct crypto_alg *n;
@@ -331,6 +329,7 @@ static void crypto_remove_final(struct list_head *list)
crypto_alg_put(alg);
}
}
+EXPORT_SYMBOL_GPL(crypto_remove_final);
static void crypto_wait_for_test(struct crypto_larval *larval)
{
@@ -493,6 +492,7 @@ int crypto_register_instance(struct crypto_template *tmpl,
goto err;
inst->alg.cra_module = tmpl->module;
+ inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
down_write(&crypto_alg_sem);
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 7a7219266e3c..2572d2600136 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -24,6 +24,8 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
#include "internal.h"
@@ -492,6 +494,28 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
return crypto_init_blkcipher_ops_async(tfm);
}
+static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_blkcipher rblkcipher;
+
+ snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher");
+ snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+ alg->cra_blkcipher.geniv ?: "<default>");
+
+ rblkcipher.blocksize = alg->cra_blocksize;
+ rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+ rblkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+ rblkcipher.ivsize = alg->cra_blkcipher.ivsize;
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+ sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
__attribute__ ((unused));
static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -511,6 +535,7 @@ const struct crypto_type crypto_blkcipher_type = {
#ifdef CONFIG_PROC_FS
.show = crypto_blkcipher_show,
#endif
+ .report = crypto_blkcipher_report,
};
EXPORT_SYMBOL_GPL(crypto_blkcipher_type);
diff --git a/crypto/blowfish.c b/crypto/blowfish_common.c
index a67d52ee0580..f636aab0209f 100644
--- a/crypto/blowfish.c
+++ b/crypto/blowfish_common.c
@@ -1,6 +1,9 @@
/*
* Cryptographic API.
*
+ * Common Blowfish algorithm parts shared between the c and assembler
+ * implementations.
+ *
* Blowfish Cipher Algorithm, by Bruce Schneier.
* http://www.counterpane.com/blowfish.html
*
@@ -22,15 +25,7 @@
#include <asm/byteorder.h>
#include <linux/crypto.h>
#include <linux/types.h>
-
-#define BF_BLOCK_SIZE 8
-#define BF_MIN_KEY_SIZE 4
-#define BF_MAX_KEY_SIZE 56
-
-struct bf_ctx {
- u32 p[18];
- u32 s[1024];
-};
+#include <crypto/blowfish.h>
static const u32 bf_pbox[16 + 2] = {
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
@@ -309,9 +304,9 @@ static const u32 bf_sbox[256 * 4] = {
#define GET32_0(x) (((x) >> (24)) & (0xff))
#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
- S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
+ S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
-#define ROUND(a, b, n) b ^= P[n]; a ^= bf_F (b)
+#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
/*
* The blowfish encipher, processes 64-bit blocks.
@@ -348,57 +343,10 @@ static void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src)
dst[1] = yl;
}
-static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
- const __be32 *in_blk = (const __be32 *)src;
- __be32 *const out_blk = (__be32 *)dst;
- u32 in32[2], out32[2];
-
- in32[0] = be32_to_cpu(in_blk[0]);
- in32[1] = be32_to_cpu(in_blk[1]);
- encrypt_block(crypto_tfm_ctx(tfm), out32, in32);
- out_blk[0] = cpu_to_be32(out32[0]);
- out_blk[1] = cpu_to_be32(out32[1]);
-}
-
-static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
- struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
- const __be32 *in_blk = (const __be32 *)src;
- __be32 *const out_blk = (__be32 *)dst;
- const u32 *P = ctx->p;
- const u32 *S = ctx->s;
- u32 yl = be32_to_cpu(in_blk[0]);
- u32 yr = be32_to_cpu(in_blk[1]);
-
- ROUND(yr, yl, 17);
- ROUND(yl, yr, 16);
- ROUND(yr, yl, 15);
- ROUND(yl, yr, 14);
- ROUND(yr, yl, 13);
- ROUND(yl, yr, 12);
- ROUND(yr, yl, 11);
- ROUND(yl, yr, 10);
- ROUND(yr, yl, 9);
- ROUND(yl, yr, 8);
- ROUND(yr, yl, 7);
- ROUND(yl, yr, 6);
- ROUND(yr, yl, 5);
- ROUND(yl, yr, 4);
- ROUND(yr, yl, 3);
- ROUND(yl, yr, 2);
-
- yl ^= P[1];
- yr ^= P[0];
-
- out_blk[0] = cpu_to_be32(yr);
- out_blk[1] = cpu_to_be32(yl);
-}
-
/*
* Calculates the blowfish S and P boxes for encryption and decryption.
*/
-static int bf_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+int blowfish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
{
struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
u32 *P = ctx->p;
@@ -448,35 +396,7 @@ static int bf_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
/* Bruce says not to bother with the weak key check. */
return 0;
}
-
-static struct crypto_alg alg = {
- .cra_name = "blowfish",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
- .cra_blocksize = BF_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct bf_ctx),
- .cra_alignmask = 3,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(alg.cra_list),
- .cra_u = { .cipher = {
- .cia_min_keysize = BF_MIN_KEY_SIZE,
- .cia_max_keysize = BF_MAX_KEY_SIZE,
- .cia_setkey = bf_setkey,
- .cia_encrypt = bf_encrypt,
- .cia_decrypt = bf_decrypt } }
-};
-
-static int __init blowfish_mod_init(void)
-{
- return crypto_register_alg(&alg);
-}
-
-static void __exit blowfish_mod_fini(void)
-{
- crypto_unregister_alg(&alg);
-}
-
-module_init(blowfish_mod_init);
-module_exit(blowfish_mod_fini);
+EXPORT_SYMBOL_GPL(blowfish_setkey);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
+MODULE_DESCRIPTION("Blowfish Cipher common functions");
diff --git a/crypto/blowfish_generic.c b/crypto/blowfish_generic.c
new file mode 100644
index 000000000000..6f269b5cfa3b
--- /dev/null
+++ b/crypto/blowfish_generic.c
@@ -0,0 +1,142 @@
+/*
+ * Cryptographic API.
+ *
+ * Blowfish Cipher Algorithm, by Bruce Schneier.
+ * http://www.counterpane.com/blowfish.html
+ *
+ * Adapted from Kerneli implementation.
+ *
+ * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
+ * Copyright (c) Kyle McMartin <kyle@debian.org>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/byteorder.h>
+#include <linux/crypto.h>
+#include <linux/types.h>
+#include <crypto/blowfish.h>
+
+/*
+ * Round loop unrolling macros, S is a pointer to a S-Box array
+ * organized in 4 unsigned longs at a row.
+ */
+#define GET32_3(x) (((x) & 0xff))
+#define GET32_2(x) (((x) >> (8)) & (0xff))
+#define GET32_1(x) (((x) >> (16)) & (0xff))
+#define GET32_0(x) (((x) >> (24)) & (0xff))
+
+#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
+ S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
+
+#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
+
+static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+ const __be32 *in_blk = (const __be32 *)src;
+ __be32 *const out_blk = (__be32 *)dst;
+ const u32 *P = ctx->p;
+ const u32 *S = ctx->s;
+ u32 yl = be32_to_cpu(in_blk[0]);
+ u32 yr = be32_to_cpu(in_blk[1]);
+
+ ROUND(yr, yl, 0);
+ ROUND(yl, yr, 1);
+ ROUND(yr, yl, 2);
+ ROUND(yl, yr, 3);
+ ROUND(yr, yl, 4);
+ ROUND(yl, yr, 5);
+ ROUND(yr, yl, 6);
+ ROUND(yl, yr, 7);
+ ROUND(yr, yl, 8);
+ ROUND(yl, yr, 9);
+ ROUND(yr, yl, 10);
+ ROUND(yl, yr, 11);
+ ROUND(yr, yl, 12);
+ ROUND(yl, yr, 13);
+ ROUND(yr, yl, 14);
+ ROUND(yl, yr, 15);
+
+ yl ^= P[16];
+ yr ^= P[17];
+
+ out_blk[0] = cpu_to_be32(yr);
+ out_blk[1] = cpu_to_be32(yl);
+}
+
+static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+ const __be32 *in_blk = (const __be32 *)src;
+ __be32 *const out_blk = (__be32 *)dst;
+ const u32 *P = ctx->p;
+ const u32 *S = ctx->s;
+ u32 yl = be32_to_cpu(in_blk[0]);
+ u32 yr = be32_to_cpu(in_blk[1]);
+
+ ROUND(yr, yl, 17);
+ ROUND(yl, yr, 16);
+ ROUND(yr, yl, 15);
+ ROUND(yl, yr, 14);
+ ROUND(yr, yl, 13);
+ ROUND(yl, yr, 12);
+ ROUND(yr, yl, 11);
+ ROUND(yl, yr, 10);
+ ROUND(yr, yl, 9);
+ ROUND(yl, yr, 8);
+ ROUND(yr, yl, 7);
+ ROUND(yl, yr, 6);
+ ROUND(yr, yl, 5);
+ ROUND(yl, yr, 4);
+ ROUND(yr, yl, 3);
+ ROUND(yl, yr, 2);
+
+ yl ^= P[1];
+ yr ^= P[0];
+
+ out_blk[0] = cpu_to_be32(yr);
+ out_blk[1] = cpu_to_be32(yl);
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "blowfish",
+ .cra_driver_name = "blowfish-generic",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = BF_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct bf_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = { .cipher = {
+ .cia_min_keysize = BF_MIN_KEY_SIZE,
+ .cia_max_keysize = BF_MAX_KEY_SIZE,
+ .cia_setkey = blowfish_setkey,
+ .cia_encrypt = bf_encrypt,
+ .cia_decrypt = bf_decrypt } }
+};
+
+static int __init blowfish_mod_init(void)
+{
+ return crypto_register_alg(&alg);
+}
+
+static void __exit blowfish_mod_fini(void)
+{
+ crypto_unregister_alg(&alg);
+}
+
+module_init(blowfish_mod_init);
+module_exit(blowfish_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
+MODULE_ALIAS("blowfish");
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index e46d21ae26bc..671d4d6d14df 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -945,7 +945,7 @@ static void __exit cryptd_exit(void)
crypto_unregister_template(&cryptd_tmpl);
}
-module_init(cryptd_init);
+subsys_initcall(cryptd_init);
module_exit(cryptd_exit);
MODULE_LICENSE("GPL");
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
new file mode 100644
index 000000000000..2abca780312d
--- /dev/null
+++ b/crypto/crypto_user.c
@@ -0,0 +1,438 @@
+/*
+ * Crypto user configuration API.
+ *
+ * Copyright (C) 2011 secunet Security Networks AG
+ * Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.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.
+ */
+
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
+#include <linux/security.h>
+#include <net/net_namespace.h>
+#include "internal.h"
+
+DEFINE_MUTEX(crypto_cfg_mutex);
+
+/* The crypto netlink socket */
+static struct sock *crypto_nlsk;
+
+struct crypto_dump_info {
+ struct sk_buff *in_skb;
+ struct sk_buff *out_skb;
+ u32 nlmsg_seq;
+ u16 nlmsg_flags;
+};
+
+static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
+{
+ struct crypto_alg *q, *alg = NULL;
+
+ down_read(&crypto_alg_sem);
+
+ if (list_empty(&crypto_alg_list))
+ return NULL;
+
+ list_for_each_entry(q, &crypto_alg_list, cra_list) {
+ int match = 0;
+
+ if ((q->cra_flags ^ p->cru_type) & p->cru_mask)
+ continue;
+
+ if (strlen(p->cru_driver_name))
+ match = !strcmp(q->cra_driver_name,
+ p->cru_driver_name);
+ else if (!exact)
+ match = !strcmp(q->cra_name, p->cru_name);
+
+ if (match) {
+ alg = q;
+ break;
+ }
+ }
+
+ up_read(&crypto_alg_sem);
+
+ return alg;
+}
+
+static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_cipher rcipher;
+
+ snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher");
+
+ rcipher.blocksize = alg->cra_blocksize;
+ rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
+ rcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_CIPHER,
+ sizeof(struct crypto_report_cipher), &rcipher);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_comp rcomp;
+
+ snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression");
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
+ sizeof(struct crypto_report_comp), &rcomp);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+static int crypto_report_one(struct crypto_alg *alg,
+ struct crypto_user_alg *ualg, struct sk_buff *skb)
+{
+ memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name));
+ memcpy(&ualg->cru_driver_name, &alg->cra_driver_name,
+ sizeof(ualg->cru_driver_name));
+ memcpy(&ualg->cru_module_name, module_name(alg->cra_module),
+ CRYPTO_MAX_ALG_NAME);
+
+ ualg->cru_flags = alg->cra_flags;
+ ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
+
+ NLA_PUT_U32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority);
+
+ if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
+ struct crypto_report_larval rl;
+
+ snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval");
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_LARVAL,
+ sizeof(struct crypto_report_larval), &rl);
+
+ goto out;
+ }
+
+ if (alg->cra_type && alg->cra_type->report) {
+ if (alg->cra_type->report(skb, alg))
+ goto nla_put_failure;
+
+ goto out;
+ }
+
+ switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
+ case CRYPTO_ALG_TYPE_CIPHER:
+ if (crypto_report_cipher(skb, alg))
+ goto nla_put_failure;
+
+ break;
+ case CRYPTO_ALG_TYPE_COMPRESS:
+ if (crypto_report_comp(skb, alg))
+ goto nla_put_failure;
+
+ break;
+ }
+
+out:
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+static int crypto_report_alg(struct crypto_alg *alg,
+ struct crypto_dump_info *info)
+{
+ struct sk_buff *in_skb = info->in_skb;
+ struct sk_buff *skb = info->out_skb;
+ struct nlmsghdr *nlh;
+ struct crypto_user_alg *ualg;
+ int err = 0;
+
+ nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, info->nlmsg_seq,
+ CRYPTO_MSG_GETALG, sizeof(*ualg), info->nlmsg_flags);
+ if (!nlh) {
+ err = -EMSGSIZE;
+ goto out;
+ }
+
+ ualg = nlmsg_data(nlh);
+
+ err = crypto_report_one(alg, ualg, skb);
+ if (err) {
+ nlmsg_cancel(skb, nlh);
+ goto out;
+ }
+
+ nlmsg_end(skb, nlh);
+
+out:
+ return err;
+}
+
+static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+ struct nlattr **attrs)
+{
+ struct crypto_user_alg *p = nlmsg_data(in_nlh);
+ struct crypto_alg *alg;
+ struct sk_buff *skb;
+ struct crypto_dump_info info;
+ int err;
+
+ if (!p->cru_driver_name)
+ return -EINVAL;
+
+ alg = crypto_alg_match(p, 1);
+ if (!alg)
+ return -ENOENT;
+
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ info.in_skb = in_skb;
+ info.out_skb = skb;
+ info.nlmsg_seq = in_nlh->nlmsg_seq;
+ info.nlmsg_flags = 0;
+
+ err = crypto_report_alg(alg, &info);
+ if (err)
+ return err;
+
+ return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).pid);
+}
+
+static int crypto_dump_report(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct crypto_alg *alg;
+ struct crypto_dump_info info;
+ int err;
+
+ if (cb->args[0])
+ goto out;
+
+ cb->args[0] = 1;
+
+ info.in_skb = cb->skb;
+ info.out_skb = skb;
+ info.nlmsg_seq = cb->nlh->nlmsg_seq;
+ info.nlmsg_flags = NLM_F_MULTI;
+
+ list_for_each_entry(alg, &crypto_alg_list, cra_list) {
+ err = crypto_report_alg(alg, &info);
+ if (err)
+ goto out_err;
+ }
+
+out:
+ return skb->len;
+out_err:
+ return err;
+}
+
+static int crypto_dump_report_done(struct netlink_callback *cb)
+{
+ return 0;
+}
+
+static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct nlattr **attrs)
+{
+ struct crypto_alg *alg;
+ struct crypto_user_alg *p = nlmsg_data(nlh);
+ struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
+ LIST_HEAD(list);
+
+ if (priority && !strlen(p->cru_driver_name))
+ return -EINVAL;
+
+ alg = crypto_alg_match(p, 1);
+ if (!alg)
+ return -ENOENT;
+
+ down_write(&crypto_alg_sem);
+
+ crypto_remove_spawns(alg, &list, NULL);
+
+ if (priority)
+ alg->cra_priority = nla_get_u32(priority);
+
+ up_write(&crypto_alg_sem);
+
+ crypto_remove_final(&list);
+
+ return 0;
+}
+
+static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct nlattr **attrs)
+{
+ struct crypto_alg *alg;
+ struct crypto_user_alg *p = nlmsg_data(nlh);
+
+ alg = crypto_alg_match(p, 1);
+ if (!alg)
+ return -ENOENT;
+
+ /* We can not unregister core algorithms such as aes-generic.
+ * We would loose the reference in the crypto_alg_list to this algorithm
+ * if we try to unregister. Unregistering such an algorithm without
+ * removing the module is not possible, so we restrict to crypto
+ * instances that are build from templates. */
+ if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
+ return -EINVAL;
+
+ if (atomic_read(&alg->cra_refcnt) != 1)
+ return -EBUSY;
+
+ return crypto_unregister_alg(alg);
+}
+
+static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct nlattr **attrs)
+{
+ int exact;
+ const char *name;
+ struct crypto_alg *alg;
+ struct crypto_user_alg *p = nlmsg_data(nlh);
+ struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
+
+ if (strlen(p->cru_driver_name))
+ exact = 1;
+
+ if (priority && !exact)
+ return -EINVAL;
+
+ alg = crypto_alg_match(p, exact);
+ if (alg)
+ return -EEXIST;
+
+ if (strlen(p->cru_driver_name))
+ name = p->cru_driver_name;
+ else
+ name = p->cru_name;
+
+ alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
+ if (IS_ERR(alg))
+ return PTR_ERR(alg);
+
+ down_write(&crypto_alg_sem);
+
+ if (priority)
+ alg->cra_priority = nla_get_u32(priority);
+
+ up_write(&crypto_alg_sem);
+
+ crypto_mod_put(alg);
+
+ return 0;
+}
+
+#define MSGSIZE(type) sizeof(struct type)
+
+static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
+ [CRYPTO_MSG_NEWALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+ [CRYPTO_MSG_DELALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+ [CRYPTO_MSG_UPDATEALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+ [CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+};
+
+static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
+ [CRYPTOCFGA_PRIORITY_VAL] = { .type = NLA_U32},
+};
+
+#undef MSGSIZE
+
+static struct crypto_link {
+ int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
+ int (*dump)(struct sk_buff *, struct netlink_callback *);
+ int (*done)(struct netlink_callback *);
+} crypto_dispatch[CRYPTO_NR_MSGTYPES] = {
+ [CRYPTO_MSG_NEWALG - CRYPTO_MSG_BASE] = { .doit = crypto_add_alg},
+ [CRYPTO_MSG_DELALG - CRYPTO_MSG_BASE] = { .doit = crypto_del_alg},
+ [CRYPTO_MSG_UPDATEALG - CRYPTO_MSG_BASE] = { .doit = crypto_update_alg},
+ [CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE] = { .doit = crypto_report,
+ .dump = crypto_dump_report,
+ .done = crypto_dump_report_done},
+};
+
+static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+ struct nlattr *attrs[CRYPTOCFGA_MAX+1];
+ struct crypto_link *link;
+ int type, err;
+
+ type = nlh->nlmsg_type;
+ if (type > CRYPTO_MSG_MAX)
+ return -EINVAL;
+
+ type -= CRYPTO_MSG_BASE;
+ link = &crypto_dispatch[type];
+
+ if (security_netlink_recv(skb, CAP_NET_ADMIN))
+ return -EPERM;
+
+ if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
+ (nlh->nlmsg_flags & NLM_F_DUMP))) {
+ if (link->dump == NULL)
+ return -EINVAL;
+
+ return netlink_dump_start(crypto_nlsk, skb, nlh,
+ link->dump, link->done, 0);
+ }
+
+ err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
+ crypto_policy);
+ if (err < 0)
+ return err;
+
+ if (link->doit == NULL)
+ return -EINVAL;
+
+ return link->doit(skb, nlh, attrs);
+}
+
+static void crypto_netlink_rcv(struct sk_buff *skb)
+{
+ mutex_lock(&crypto_cfg_mutex);
+ netlink_rcv_skb(skb, &crypto_user_rcv_msg);
+ mutex_unlock(&crypto_cfg_mutex);
+}
+
+static int __init crypto_user_init(void)
+{
+ crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO,
+ 0, crypto_netlink_rcv,
+ NULL, THIS_MODULE);
+ if (!crypto_nlsk)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void __exit crypto_user_exit(void)
+{
+ netlink_kernel_release(crypto_nlsk);
+}
+
+module_init(crypto_user_init);
+module_exit(crypto_user_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
+MODULE_DESCRIPTION("Crypto userspace configuration API");
diff --git a/crypto/internal.h b/crypto/internal.h
index d4384b08ab29..b865ca1a8613 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -86,6 +86,9 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask);
void crypto_larval_error(const char *name, u32 type, u32 mask);
void crypto_alg_tested(const char *name, int err);
+void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
+ struct crypto_alg *nalg);
+void crypto_remove_final(struct list_head *list);
void crypto_shoot_alg(struct crypto_alg *alg);
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
u32 mask);
diff --git a/crypto/pcompress.c b/crypto/pcompress.c
index f7c4a7d7412e..fefda78a6a2a 100644
--- a/crypto/pcompress.c
+++ b/crypto/pcompress.c
@@ -24,6 +24,8 @@
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
#include <crypto/compress.h>
#include <crypto/internal/compress.h>
@@ -46,6 +48,21 @@ static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm)
return 0;
}
+static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_comp rpcomp;
+
+ snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp");
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
+ sizeof(struct crypto_report_comp), &rpcomp);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
__attribute__ ((unused));
static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
@@ -60,6 +77,7 @@ static const struct crypto_type crypto_pcomp_type = {
#ifdef CONFIG_PROC_FS
.show = crypto_pcomp_show,
#endif
+ .report = crypto_pcomp_report,
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
.maskset = CRYPTO_ALG_TYPE_MASK,
.type = CRYPTO_ALG_TYPE_PCOMPRESS,
diff --git a/crypto/rng.c b/crypto/rng.c
index 45229ae782be..feb7de00f437 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -21,6 +21,8 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
static DEFINE_MUTEX(crypto_default_rng_lock);
struct crypto_rng *crypto_default_rng;
@@ -58,6 +60,23 @@ static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
return 0;
}
+static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_rng rrng;
+
+ snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng");
+
+ rrng.seedsize = alg->cra_rng.seedsize;
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_RNG,
+ sizeof(struct crypto_report_rng), &rrng);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
__attribute__ ((unused));
static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
@@ -78,6 +97,7 @@ const struct crypto_type crypto_rng_type = {
#ifdef CONFIG_PROC_FS
.show = crypto_rng_show,
#endif
+ .report = crypto_rng_report,
};
EXPORT_SYMBOL_GPL(crypto_rng_type);
diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
index 00ae60eb9254..42794803c480 100644
--- a/crypto/sha1_generic.c
+++ b/crypto/sha1_generic.c
@@ -36,7 +36,7 @@ static int sha1_init(struct shash_desc *desc)
return 0;
}
-static int sha1_update(struct shash_desc *desc, const u8 *data,
+int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha1_state *sctx = shash_desc_ctx(desc);
@@ -71,6 +71,7 @@ static int sha1_update(struct shash_desc *desc, const u8 *data,
return 0;
}
+EXPORT_SYMBOL(crypto_sha1_update);
/* Add padding and return the message digest. */
@@ -87,10 +88,10 @@ static int sha1_final(struct shash_desc *desc, u8 *out)
/* Pad out to 56 mod 64 */
index = sctx->count & 0x3f;
padlen = (index < 56) ? (56 - index) : ((64+56) - index);
- sha1_update(desc, padding, padlen);
+ crypto_sha1_update(desc, padding, padlen);
/* Append length */
- sha1_update(desc, (const u8 *)&bits, sizeof(bits));
+ crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits));
/* Store state in digest */
for (i = 0; i < 5; i++)
@@ -121,7 +122,7 @@ static int sha1_import(struct shash_desc *desc, const void *in)
static struct shash_alg alg = {
.digestsize = SHA1_DIGEST_SIZE,
.init = sha1_init,
- .update = sha1_update,
+ .update = crypto_sha1_update,
.final = sha1_final,
.export = sha1_export,
.import = sha1_import,
diff --git a/crypto/shash.c b/crypto/shash.c
index 76f74b963151..ea8a9c6e21e3 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -17,6 +17,8 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
#include "internal.h"
@@ -522,6 +524,24 @@ static unsigned int crypto_shash_extsize(struct crypto_alg *alg)
return alg->cra_ctxsize;
}
+static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_hash rhash;
+ struct shash_alg *salg = __crypto_shash_alg(alg);
+
+ snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash");
+ rhash.blocksize = alg->cra_blocksize;
+ rhash.digestsize = salg->digestsize;
+
+ NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
+ sizeof(struct crypto_report_hash), &rhash);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
__attribute__ ((unused));
static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
@@ -541,6 +561,7 @@ static const struct crypto_type crypto_shash_type = {
#ifdef CONFIG_PROC_FS
.show = crypto_shash_show,
#endif
+ .report = crypto_shash_report,
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
.maskset = CRYPTO_ALG_TYPE_MASK,
.type = CRYPTO_ALG_TYPE_SHASH,
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 2222617b3bed..0c4e80f34651 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -782,11 +782,13 @@ static int do_test(int m)
case 7:
ret += tcrypt_test("ecb(blowfish)");
ret += tcrypt_test("cbc(blowfish)");
+ ret += tcrypt_test("ctr(blowfish)");
break;
case 8:
ret += tcrypt_test("ecb(twofish)");
ret += tcrypt_test("cbc(twofish)");
+ ret += tcrypt_test("ctr(twofish)");
break;
case 9:
@@ -1039,6 +1041,10 @@ static int do_test(int m)
speed_template_16_24_32);
test_cipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0,
speed_template_16_24_32);
+ test_cipher_speed("ctr(twofish)", ENCRYPT, sec, NULL, 0,
+ speed_template_16_24_32);
+ test_cipher_speed("ctr(twofish)", DECRYPT, sec, NULL, 0,
+ speed_template_16_24_32);
break;
case 203:
@@ -1050,6 +1056,10 @@ static int do_test(int m)
speed_template_8_32);
test_cipher_speed("cbc(blowfish)", DECRYPT, sec, NULL, 0,
speed_template_8_32);
+ test_cipher_speed("ctr(blowfish)", ENCRYPT, sec, NULL, 0,
+ speed_template_8_32);
+ test_cipher_speed("ctr(blowfish)", DECRYPT, sec, NULL, 0,
+ speed_template_8_32);
break;
case 204:
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index b6b93d416351..e91c1eb1722a 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1756,6 +1756,36 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}, {
+ .alg = "ctr(blowfish)",
+ .test = alg_test_skcipher,
+ .suite = {
+ .cipher = {
+ .enc = {
+ .vecs = bf_ctr_enc_tv_template,
+ .count = BF_CTR_ENC_TEST_VECTORS
+ },
+ .dec = {
+ .vecs = bf_ctr_dec_tv_template,
+ .count = BF_CTR_DEC_TEST_VECTORS
+ }
+ }
+ }
+ }, {
+ .alg = "ctr(twofish)",
+ .test = alg_test_skcipher,
+ .suite = {
+ .cipher = {
+ .enc = {
+ .vecs = tf_ctr_enc_tv_template,
+ .count = TF_CTR_ENC_TEST_VECTORS
+ },
+ .dec = {
+ .vecs = tf_ctr_dec_tv_template,
+ .count = TF_CTR_DEC_TEST_VECTORS
+ }
+ }
+ }
+ }, {
.alg = "cts(cbc(aes))",
.test = alg_test_skcipher,
.suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 27adc92842ba..37b4d8f45447 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -2391,10 +2391,12 @@ static struct cipher_testvec des3_ede_cbc_dec_tv_template[] = {
/*
* Blowfish test vectors.
*/
-#define BF_ENC_TEST_VECTORS 6
-#define BF_DEC_TEST_VECTORS 6
-#define BF_CBC_ENC_TEST_VECTORS 1
-#define BF_CBC_DEC_TEST_VECTORS 1
+#define BF_ENC_TEST_VECTORS 7
+#define BF_DEC_TEST_VECTORS 7
+#define BF_CBC_ENC_TEST_VECTORS 2
+#define BF_CBC_DEC_TEST_VECTORS 2
+#define BF_CTR_ENC_TEST_VECTORS 2
+#define BF_CTR_DEC_TEST_VECTORS 2
static struct cipher_testvec bf_enc_tv_template[] = {
{ /* DES test vectors from OpenSSL */
@@ -2448,6 +2450,24 @@ static struct cipher_testvec bf_enc_tv_template[] = {
.ilen = 8,
.result = "\xc0\x45\x04\x01\x2e\x4e\x1f\x53",
.rlen = 8,
+ }, { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+ .ilen = 40,
+ .result = "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
+ "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
+ "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
+ "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
+ "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
+ .rlen = 40,
},
};
@@ -2503,6 +2523,24 @@ static struct cipher_testvec bf_dec_tv_template[] = {
.ilen = 8,
.result = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
.rlen = 8,
+ }, { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .input = "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
+ "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
+ "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
+ "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
+ "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
+ .ilen = 40,
+ .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+ .rlen = 40,
},
};
@@ -2522,6 +2560,25 @@ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
"\x58\xde\xb9\xe7\x15\x46\x16\xd9"
"\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
.rlen = 32,
+ }, { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+ .input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+ .ilen = 40,
+ .result = "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+ "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+ "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+ "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+ "\x01\x9C\x93\x63\x51\x60\x82\xD2",
+ .rlen = 40,
},
};
@@ -2541,16 +2598,125 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
"\x68\x65\x20\x74\x69\x6d\x65\x20"
"\x66\x6f\x72\x20\x00\x00\x00\x00",
.rlen = 32,
+ }, { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+ .input = "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+ "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+ "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+ "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+ "\x01\x9C\x93\x63\x51\x60\x82\xD2",
+ .ilen = 40,
+ .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+ .rlen = 40,
+ },
+};
+
+static struct cipher_testvec bf_ctr_enc_tv_template[] = {
+ { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+ .input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+ .ilen = 40,
+ .result = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+ "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+ "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+ "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+ "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
+ .rlen = 40,
+ }, { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+ .input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+ "\x6D\x04\x9B",
+ .ilen = 43,
+ .result = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+ "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+ "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+ "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+ "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+ "\x3D\xA7\xE9",
+ .rlen = 43,
+ },
+};
+
+static struct cipher_testvec bf_ctr_dec_tv_template[] = {
+ { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+ .input = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+ "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+ "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+ "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+ "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
+ .ilen = 40,
+ .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+ .rlen = 40,
+ }, { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+ .input = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+ "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+ "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+ "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+ "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+ "\x3D\xA7\xE9",
+ .ilen = 43,
+ .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+ "\x6D\x04\x9B",
+ .rlen = 43,
},
};
/*
* Twofish test vectors.
*/
-#define TF_ENC_TEST_VECTORS 3
-#define TF_DEC_TEST_VECTORS 3
-#define TF_CBC_ENC_TEST_VECTORS 4
-#define TF_CBC_DEC_TEST_VECTORS 4
+#define TF_ENC_TEST_VECTORS 4
+#define TF_DEC_TEST_VECTORS 4
+#define TF_CBC_ENC_TEST_VECTORS 5
+#define TF_CBC_DEC_TEST_VECTORS 5
+#define TF_CTR_ENC_TEST_VECTORS 2
+#define TF_CTR_DEC_TEST_VECTORS 2
static struct cipher_testvec tf_enc_tv_template[] = {
{
@@ -2582,6 +2748,30 @@ static struct cipher_testvec tf_enc_tv_template[] = {
.result = "\x37\x52\x7b\xe0\x05\x23\x34\xb8"
"\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20",
.rlen = 16,
+ }, { /* Generated with Crypto++ */
+ .key = "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
+ "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
+ "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
+ "\x9B\x78\xBE\x9B\x78\x55\x32\x0F",
+ .klen = 32,
+ .input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+ "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+ "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+ "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+ .ilen = 64,
+ .result = "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF"
+ "\xF6\x90\x46\x9C\x4A\x0F\x08\xDC"
+ "\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D"
+ "\xE0\xE4\x8B\x3F\xD5\xA3\xF7\x14"
+ "\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5"
+ "\xDF\xFA\xC7\xE8\x09\x50\x76\x08"
+ "\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05"
+ "\x89\xF6\x82\xF0\xD3\xDB\x06\x02",
+ .rlen = 64,
},
};
@@ -2615,6 +2805,30 @@ static struct cipher_testvec tf_dec_tv_template[] = {
.ilen = 16,
.result = zeroed_string,
.rlen = 16,
+ }, { /* Generated with Crypto++ */
+ .key = "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
+ "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
+ "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
+ "\x9B\x78\xBE\x9B\x78\x55\x32\x0F",
+ .klen = 32,
+ .input = "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF"
+ "\xF6\x90\x46\x9C\x4A\x0F\x08\xDC"
+ "\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D"
+ "\xE0\xE4\x8B\x3F\xD5\xA3\xF7\x14"
+ "\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5"
+ "\xDF\xFA\xC7\xE8\x09\x50\x76\x08"
+ "\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05"
+ "\x89\xF6\x82\xF0\xD3\xDB\x06\x02",
+ .ilen = 64,
+ .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+ "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+ "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+ "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+ .rlen = 64,
},
};
@@ -2661,6 +2875,32 @@ static struct cipher_testvec tf_cbc_enc_tv_template[] = {
"\x05\xef\x8c\x61\xa8\x11\x58\x26"
"\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
.rlen = 48,
+ }, { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+ "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+ .input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+ "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+ "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+ "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+ .ilen = 64,
+ .result = "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1"
+ "\x33\x38\xC2\xC0\x0C\x14\x7E\xB5"
+ "\x26\x1B\x05\x0C\x05\x12\x3F\xC0"
+ "\xF9\x1C\x02\x28\x40\x96\x6F\xD0"
+ "\x3D\x32\xDF\xDA\x56\x00\x6E\xEE"
+ "\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC"
+ "\x8C\x53\xFA\x87\x6F\xDD\x81\xA3"
+ "\xB1\xD3\x44\x65\xDF\xE7\x63\x38",
+ .rlen = 64,
},
};
@@ -2707,6 +2947,148 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
.ilen = 48,
.result = zeroed_string,
.rlen = 48,
+ }, { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+ "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+ .input = "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1"
+ "\x33\x38\xC2\xC0\x0C\x14\x7E\xB5"
+ "\x26\x1B\x05\x0C\x05\x12\x3F\xC0"
+ "\xF9\x1C\x02\x28\x40\x96\x6F\xD0"
+ "\x3D\x32\xDF\xDA\x56\x00\x6E\xEE"
+ "\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC"
+ "\x8C\x53\xFA\x87\x6F\xDD\x81\xA3"
+ "\xB1\xD3\x44\x65\xDF\xE7\x63\x38",
+ .ilen = 64,
+ .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+ "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+ "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+ "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+ .rlen = 64,
+ },
+};
+
+static struct cipher_testvec tf_ctr_enc_tv_template[] = {
+ { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+ "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+ .input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+ "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+ "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+ "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+ .ilen = 64,
+ .result = "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+ "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+ "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+ "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+ "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+ "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+ "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+ "\x01\x41\x21\x12\x38\xAB\x52\x4F",
+ .rlen = 64,
+ }, { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+ "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+ .input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+ "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+ "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+ "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+ "\xC3\x37\xCE",
+ .ilen = 67,
+ .result = "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+ "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+ "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+ "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+ "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+ "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+ "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+ "\x01\x41\x21\x12\x38\xAB\x52\x4F"
+ "\xA8\x57\x20",
+ .rlen = 67,
+ },
+};
+
+static struct cipher_testvec tf_ctr_dec_tv_template[] = {
+ { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+ "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+ .input = "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+ "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+ "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+ "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+ "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+ "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+ "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+ "\x01\x41\x21\x12\x38\xAB\x52\x4F",
+ .ilen = 64,
+ .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+ "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+ "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+ "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+ .rlen = 64,
+ }, { /* Generated with Crypto++ */
+ .key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+ "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+ "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+ "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+ .klen = 32,
+ .iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+ "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+ .input = "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+ "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+ "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+ "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+ "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+ "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+ "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+ "\x01\x41\x21\x12\x38\xAB\x52\x4F"
+ "\xA8\x57\x20",
+ .ilen = 67,
+ .result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+ "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+ "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+ "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+ "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+ "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+ "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+ "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+ "\xC3\x37\xCE",
+ .rlen = 67,
},
};
diff --git a/crypto/wp512.c b/crypto/wp512.c
index 723427273687..71719a2be25a 100644
--- a/crypto/wp512.c
+++ b/crypto/wp512.c
@@ -762,11 +762,17 @@ static const u64 C7[256] = {
0x86228644a411c286ULL,
};
-static const u64 rc[WHIRLPOOL_ROUNDS + 1] = {
- 0x0000000000000000ULL, 0x1823c6e887b8014fULL, 0x36a6d2f5796f9152ULL,
- 0x60bc9b8ea30c7b35ULL, 0x1de0d7c22e4bfe57ULL, 0x157737e59ff04adaULL,
- 0x58c9290ab1a06b85ULL, 0xbd5d10f4cb3e0567ULL, 0xe427418ba77d95d8ULL,
- 0xfbee7c66dd17479eULL, 0xca2dbf07ad5a8333ULL,
+static const u64 rc[WHIRLPOOL_ROUNDS] = {
+ 0x1823c6e887b8014fULL,
+ 0x36a6d2f5796f9152ULL,
+ 0x60bc9b8ea30c7b35ULL,
+ 0x1de0d7c22e4bfe57ULL,
+ 0x157737e59ff04adaULL,
+ 0x58c9290ab1a06b85ULL,
+ 0xbd5d10f4cb3e0567ULL,
+ 0xe427418ba77d95d8ULL,
+ 0xfbee7c66dd17479eULL,
+ 0xca2dbf07ad5a8333ULL,
};
/**
@@ -793,7 +799,7 @@ static void wp512_process_buffer(struct wp512_ctx *wctx) {
state[6] = block[6] ^ (K[6] = wctx->hash[6]);
state[7] = block[7] ^ (K[7] = wctx->hash[7]);
- for (r = 1; r <= WHIRLPOOL_ROUNDS; r++) {
+ for (r = 0; r < WHIRLPOOL_ROUNDS; r++) {
L[0] = C0[(int)(K[0] >> 56) ] ^
C1[(int)(K[7] >> 48) & 0xff] ^
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 95b9e7eefadc..b5e6f243f749 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/pps/Kconfig"
source "drivers/ptp/Kconfig"
+source "drivers/pinctrl/Kconfig"
+
source "drivers/gpio/Kconfig"
source "drivers/w1/Kconfig"
@@ -130,4 +132,8 @@ source "drivers/iommu/Kconfig"
source "drivers/virt/Kconfig"
+source "drivers/hv/Kconfig"
+
+source "drivers/devfreq/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 7fa433a7030c..1b3142127bf5 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -5,6 +5,8 @@
# Rewritten to use lists instead of if-statements.
#
+# GPIO must come after pinctrl as gpios may need to mux pins etc
+obj-y += pinctrl/
obj-y += gpio/
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_PARISC) += parisc/
@@ -127,3 +129,6 @@ obj-$(CONFIG_IOMMU_SUPPORT) += iommu/
# Virtualization drivers
obj-$(CONFIG_VIRT_DRIVERS) += virt/
+obj-$(CONFIG_HYPERV) += hv/
+
+obj-$(CONFIG_PM_DEVFREQ) += devfreq/
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index e3f47872ec22..f0c1ce95a0ec 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -14,7 +14,6 @@ config ACPI_APEI_GHES
depends on ACPI_APEI && X86
select ACPI_HED
select IRQ_WORK
- select LLIST
select GENERIC_ALLOCATOR
help
Generic Hardware Error Source provides a way to report
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 2ca59dc69f7f..127408069ca7 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -933,7 +933,7 @@ static int erst_open_pstore(struct pstore_info *psi);
static int erst_close_pstore(struct pstore_info *psi);
static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
struct timespec *time, struct pstore_info *psi);
-static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
size_t size, struct pstore_info *psi);
static int erst_clearer(enum pstore_type_id type, u64 id,
struct pstore_info *psi);
@@ -1040,11 +1040,12 @@ out:
return (rc < 0) ? rc : (len - sizeof(*rcd));
}
-static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
size_t size, struct pstore_info *psi)
{
struct cper_pstore_record *rcd = (struct cper_pstore_record *)
(erst_info.buf - sizeof(*rcd));
+ int ret;
memset(rcd, 0, sizeof(*rcd));
memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
@@ -1079,9 +1080,10 @@ static u64 erst_writer(enum pstore_type_id type, unsigned int part,
}
rcd->sec_hdr.section_severity = CPER_SEV_FATAL;
- erst_write(&rcd->hdr);
+ ret = erst_write(&rcd->hdr);
+ *id = rcd->hdr.record_id;
- return rcd->hdr.record_id;
+ return ret;
}
static int erst_clearer(enum pstore_type_id type, u64 id,
@@ -1165,7 +1167,7 @@ static int __init erst_init(void)
goto err_release_erange;
buf = kmalloc(erst_erange.size, GFP_KERNEL);
- mutex_init(&erst_info.buf_mutex);
+ spin_lock_init(&erst_info.buf_lock);
if (buf) {
erst_info.buf = buf + sizeof(struct cper_pstore_record);
erst_info.bufsize = erst_erange.size -
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 0784f99a4665..b8e08cb67a18 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -50,6 +50,7 @@
#include <acpi/hed.h>
#include <asm/mce.h>
#include <asm/tlbflush.h>
+#include <asm/nmi.h>
#include "apei-internal.h"
@@ -749,15 +750,11 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
}
}
-static int ghes_notify_nmi(struct notifier_block *this,
- unsigned long cmd, void *data)
+static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
{
struct ghes *ghes, *ghes_global = NULL;
int sev, sev_global = -1;
- int ret = NOTIFY_DONE;
-
- if (cmd != DIE_NMI)
- return ret;
+ int ret = NMI_DONE;
raw_spin_lock(&ghes_nmi_lock);
list_for_each_entry_rcu(ghes, &ghes_nmi, list) {
@@ -770,10 +767,10 @@ static int ghes_notify_nmi(struct notifier_block *this,
sev_global = sev;
ghes_global = ghes;
}
- ret = NOTIFY_STOP;
+ ret = NMI_HANDLED;
}
- if (ret == NOTIFY_DONE)
+ if (ret == NMI_DONE)
goto out;
if (sev_global >= GHES_SEV_PANIC) {
@@ -825,10 +822,6 @@ static struct notifier_block ghes_notifier_sci = {
.notifier_call = ghes_notify_sci,
};
-static struct notifier_block ghes_notifier_nmi = {
- .notifier_call = ghes_notify_nmi,
-};
-
static unsigned long ghes_esource_prealloc_size(
const struct acpi_hest_generic *generic)
{
@@ -918,7 +911,8 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev)
ghes_estatus_pool_expand(len);
mutex_lock(&ghes_list_mutex);
if (list_empty(&ghes_nmi))
- register_die_notifier(&ghes_notifier_nmi);
+ register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0,
+ "ghes");
list_add_rcu(&ghes->list, &ghes_nmi);
mutex_unlock(&ghes_list_mutex);
break;
@@ -964,7 +958,7 @@ static int __devexit ghes_remove(struct platform_device *ghes_dev)
mutex_lock(&ghes_list_mutex);
list_del_rcu(&ghes->list);
if (list_empty(&ghes_nmi))
- unregister_die_notifier(&ghes_notifier_nmi);
+ unregister_nmi_handler(NMI_LOCAL, "ghes");
mutex_unlock(&ghes_list_mutex);
/*
* To synchronize with NMI handler, ghes can only be
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index fa32f584229f..f31c5c5f1b7e 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -80,7 +80,8 @@ static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
static struct workqueue_struct *kacpi_notify_wq;
-static struct workqueue_struct *kacpi_hotplug_wq;
+struct workqueue_struct *kacpi_hotplug_wq;
+EXPORT_SYMBOL(kacpi_hotplug_wq);
struct acpi_res_list {
resource_size_t start;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 431ab11c8c1b..9b88f9828d8c 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -37,7 +37,7 @@
#include <linux/dmi.h>
#include <linux/moduleparam.h>
#include <linux/sched.h> /* need_resched() */
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
#include <linux/clockchips.h>
#include <linux/cpuidle.h>
#include <linux/irqflags.h>
@@ -852,7 +852,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
}
static int c3_cpu_count;
-static DEFINE_SPINLOCK(c3_lock);
+static DEFINE_RAW_SPINLOCK(c3_lock);
/**
* acpi_idle_enter_bm - enters C3 with proper BM handling
@@ -930,12 +930,12 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
* without doing anything.
*/
if (pr->flags.bm_check && pr->flags.bm_control) {
- spin_lock(&c3_lock);
+ raw_spin_lock(&c3_lock);
c3_cpu_count++;
/* Disable bus master arbitration when all CPUs are in C3 */
if (c3_cpu_count == num_online_cpus())
acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
- spin_unlock(&c3_lock);
+ raw_spin_unlock(&c3_lock);
} else if (!pr->flags.bm_check) {
ACPI_FLUSH_CPU_CACHE();
}
@@ -944,10 +944,10 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
/* Re-enable bus master arbitration */
if (pr->flags.bm_check && pr->flags.bm_control) {
- spin_lock(&c3_lock);
+ raw_spin_lock(&c3_lock);
acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
c3_cpu_count--;
- spin_unlock(&c3_lock);
+ raw_spin_unlock(&c3_lock);
}
kt2 = ktime_get_real();
idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 3ed80b2ca907..0e46faef1d30 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -390,6 +390,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
},
{
.callback = init_nvs_nosave,
+ .ident = "Sony Vaio VGN-FW21E",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
.ident = "Sony Vaio VGN-SR11M",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
@@ -444,6 +452,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
},
},
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VGN-SR26GN_P",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VGN-FW520F",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
+ },
+ },
{},
};
#endif /* CONFIG_SUSPEND */
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index d74926e0939e..bd230e801131 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -365,6 +365,40 @@ static int amba_pm_restore_noirq(struct device *dev)
#endif /* !CONFIG_HIBERNATE_CALLBACKS */
+#ifdef CONFIG_PM_RUNTIME
+/*
+ * Hooks to provide runtime PM of the pclk (bus clock). It is safe to
+ * enable/disable the bus clock at runtime PM suspend/resume as this
+ * does not result in loss of context. However, disabling vcore power
+ * would do, so we leave that to the driver.
+ */
+static int amba_pm_runtime_suspend(struct device *dev)
+{
+ struct amba_device *pcdev = to_amba_device(dev);
+ int ret = pm_generic_runtime_suspend(dev);
+
+ if (ret == 0 && dev->driver)
+ clk_disable(pcdev->pclk);
+
+ return ret;
+}
+
+static int amba_pm_runtime_resume(struct device *dev)
+{
+ struct amba_device *pcdev = to_amba_device(dev);
+ int ret;
+
+ if (dev->driver) {
+ ret = clk_enable(pcdev->pclk);
+ /* Failure is probably fatal to the system, but... */
+ if (ret)
+ return ret;
+ }
+
+ return pm_generic_runtime_resume(dev);
+}
+#endif
+
#ifdef CONFIG_PM
static const struct dev_pm_ops amba_pm = {
@@ -383,8 +417,8 @@ static const struct dev_pm_ops amba_pm = {
.poweroff_noirq = amba_pm_poweroff_noirq,
.restore_noirq = amba_pm_restore_noirq,
SET_RUNTIME_PM_OPS(
- pm_generic_runtime_suspend,
- pm_generic_runtime_resume,
+ amba_pm_runtime_suspend,
+ amba_pm_runtime_resume,
pm_generic_runtime_idle
)
};
@@ -426,9 +460,17 @@ static int amba_get_enable_pclk(struct amba_device *pcdev)
if (IS_ERR(pclk))
return PTR_ERR(pclk);
+ ret = clk_prepare(pclk);
+ if (ret) {
+ clk_put(pclk);
+ return ret;
+ }
+
ret = clk_enable(pclk);
- if (ret)
+ if (ret) {
+ clk_unprepare(pclk);
clk_put(pclk);
+ }
return ret;
}
@@ -438,6 +480,7 @@ static void amba_put_disable_pclk(struct amba_device *pcdev)
struct clk *pclk = pcdev->pclk;
clk_disable(pclk);
+ clk_unprepare(pclk);
clk_put(pclk);
}
@@ -494,10 +537,18 @@ static int amba_probe(struct device *dev)
if (ret)
break;
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
ret = pcdrv->probe(pcdev, id);
if (ret == 0)
break;
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+ pm_runtime_put_noidle(dev);
+
amba_put_disable_pclk(pcdev);
amba_put_disable_vcore(pcdev);
} while (0);
@@ -509,7 +560,16 @@ static int amba_remove(struct device *dev)
{
struct amba_device *pcdev = to_amba_device(dev);
struct amba_driver *drv = to_amba_driver(dev->driver);
- int ret = drv->remove(pcdev);
+ int ret;
+
+ pm_runtime_get_sync(dev);
+ ret = drv->remove(pcdev);
+ pm_runtime_put_noidle(dev);
+
+ /* Undo the runtime PM settings in amba_probe() */
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+ pm_runtime_put_noidle(dev);
amba_put_disable_pclk(pcdev);
amba_put_disable_vcore(pcdev);
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 5987e0ba8c2d..6bdedd7cca2c 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -820,7 +820,7 @@ config PATA_PLATFORM
config PATA_OF_PLATFORM
tristate "OpenFirmware platform device PATA support"
- depends on PATA_PLATFORM && PPC_OF
+ depends on PATA_PLATFORM && OF
help
This option enables support for generic directly connected ATA
devices commonly found on embedded systems with OpenFirmware
@@ -831,6 +831,7 @@ config PATA_OF_PLATFORM
config PATA_QDI
tristate "QDI VLB PATA support"
depends on ISA
+ select PATA_LEGACY
help
Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 9550d691fd19..6ece5b7231a3 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -88,7 +88,6 @@ obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o
obj-$(CONFIG_PATA_PALMLD) += pata_palmld.o
obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
-obj-$(CONFIG_PATA_QDI) += pata_qdi.o
obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
obj-$(CONFIG_PATA_SAMSUNG_CF) += pata_samsung_cf.o
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 6fef1fa75c54..c03277d37748 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -23,6 +23,41 @@
#include <linux/ahci_platform.h>
#include "ahci.h"
+enum ahci_type {
+ AHCI, /* standard platform ahci */
+ IMX53_AHCI, /* ahci on i.mx53 */
+};
+
+static struct platform_device_id ahci_devtype[] = {
+ {
+ .name = "ahci",
+ .driver_data = AHCI,
+ }, {
+ .name = "imx53-ahci",
+ .driver_data = IMX53_AHCI,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, ahci_devtype);
+
+
+static const struct ata_port_info ahci_port_info[] = {
+ /* by features */
+ [AHCI] = {
+ .flags = AHCI_FLAG_COMMON,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+ },
+ [IMX53_AHCI] = {
+ .flags = AHCI_FLAG_COMMON,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_pmp_retry_srst_ops,
+ },
+};
+
static struct scsi_host_template ahci_platform_sht = {
AHCI_SHT("ahci_platform"),
};
@@ -31,12 +66,8 @@ static int __init ahci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ahci_platform_data *pdata = dev->platform_data;
- struct ata_port_info pi = {
- .flags = AHCI_FLAG_COMMON,
- .pio_mask = ATA_PIO4,
- .udma_mask = ATA_UDMA6,
- .port_ops = &ahci_ops,
- };
+ const struct platform_device_id *id = platform_get_device_id(pdev);
+ struct ata_port_info pi = ahci_port_info[id->driver_data];
const struct ata_port_info *ppi[] = { &pi, NULL };
struct ahci_host_priv *hpriv;
struct ata_host *host;
@@ -177,6 +208,7 @@ static struct platform_driver ahci_driver = {
.name = "ahci",
.owner = THIS_MODULE,
},
+ .id_table = ahci_devtype,
};
static int __init ahci_init(void)
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 43107e9415da..69ac373c72ab 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -113,6 +113,8 @@ enum {
PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS,
PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
+ PIIX_FLAG_PIO16 = (1 << 30), /*support 16bit PIO only*/
+
PIIX_80C_PRI = (1 << 5) | (1 << 4),
PIIX_80C_SEC = (1 << 7) | (1 << 6),
@@ -147,6 +149,7 @@ enum piix_controller_ids {
ich8m_apple_sata, /* locks up on second port enable */
tolapai_sata,
piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */
+ ich8_sata_snb,
};
struct piix_map_db {
@@ -177,6 +180,7 @@ static int piix_sidpr_scr_write(struct ata_link *link,
static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
unsigned hints);
static bool piix_irq_check(struct ata_port *ap);
+static int piix_port_start(struct ata_port *ap);
#ifdef CONFIG_PM
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int piix_pci_device_resume(struct pci_dev *pdev);
@@ -298,21 +302,21 @@ static const struct pci_device_id piix_pci_tbl[] = {
/* SATA Controller IDE (PCH) */
{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
/* SATA Controller IDE (CPT) */
- { 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ { 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
/* SATA Controller IDE (CPT) */
- { 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ { 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
/* SATA Controller IDE (CPT) */
{ 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (CPT) */
{ 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (PBG) */
- { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
/* SATA Controller IDE (PBG) */
{ 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (Panther Point) */
- { 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ { 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
/* SATA Controller IDE (Panther Point) */
- { 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ { 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
/* SATA Controller IDE (Panther Point) */
{ 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (Panther Point) */
@@ -338,6 +342,7 @@ static struct scsi_host_template piix_sht = {
static struct ata_port_operations piix_sata_ops = {
.inherits = &ata_bmdma32_port_ops,
.sff_irq_check = piix_irq_check,
+ .port_start = piix_port_start,
};
static struct ata_port_operations piix_pata_ops = {
@@ -478,6 +483,7 @@ static const struct piix_map_db *piix_map_db_table[] = {
[ich8_2port_sata] = &ich8_2port_map_db,
[ich8m_apple_sata] = &ich8m_apple_map_db,
[tolapai_sata] = &tolapai_map_db,
+ [ich8_sata_snb] = &ich8_map_db,
};
static struct ata_port_info piix_port_info[] = {
@@ -606,6 +612,19 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_vmw_ops,
},
+ /*
+ * some Sandybridge chipsets have broken 32 mode up to now,
+ * see https://bugzilla.kernel.org/show_bug.cgi?id=40592
+ */
+ [ich8_sata_snb] =
+ {
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &piix_sata_ops,
+ },
+
};
static struct pci_bits piix_enable_bits[] = {
@@ -649,6 +668,14 @@ static const struct ich_laptop ich_laptop[] = {
{ 0, }
};
+static int piix_port_start(struct ata_port *ap)
+{
+ if (!(ap->flags & PIIX_FLAG_PIO16))
+ ap->pflags |= ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE;
+
+ return ata_bmdma_port_start(ap);
+}
+
/**
* ich_pata_cable_detect - Probe host controller cable detect info
* @ap: Port for which cable detect info is desired
@@ -704,22 +731,11 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
static DEFINE_SPINLOCK(piix_lock);
-/**
- * piix_set_piomode - Initialize host controller PATA PIO timings
- * @ap: Port whose timings we are configuring
- * @adev: um
- *
- * Set PIO mode for device, in host controller PCI config space.
- *
- * LOCKING:
- * None (inherited from caller).
- */
-
-static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+static void piix_set_timings(struct ata_port *ap, struct ata_device *adev,
+ u8 pio)
{
struct pci_dev *dev = to_pci_dev(ap->host->dev);
unsigned long flags;
- unsigned int pio = adev->pio_mode - XFER_PIO_0;
unsigned int is_slave = (adev->devno != 0);
unsigned int master_port= ap->port_no ? 0x42 : 0x40;
unsigned int slave_port = 0x44;
@@ -744,10 +760,16 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
control |= 1; /* TIME1 enable */
if (ata_pio_need_iordy(adev))
control |= 2; /* IE enable */
-
/* Intel specifies that the PPE functionality is for disk only */
if (adev->class == ATA_DEV_ATA)
control |= 4; /* PPE enable */
+ /*
+ * If the drive MWDMA is faster than it can do PIO then
+ * we must force PIO into PIO0
+ */
+ if (adev->pio_mode < XFER_PIO_0 + pio)
+ /* Enable DMA timing only */
+ control |= 8; /* PIO cycles in PIO0 */
spin_lock_irqsave(&piix_lock, flags);
@@ -759,8 +781,6 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
if (is_slave) {
/* clear TIME1|IE1|PPE1|DTE1 */
master_data &= 0xff0f;
- /* Enable SITRE (separate slave timing register) */
- master_data |= 0x4000;
/* enable PPE1, IE1 and TIME1 as needed */
master_data |= (control << 4);
pci_read_config_byte(dev, slave_port, &slave_data);
@@ -778,6 +798,9 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
(timings[pio][0] << 12) |
(timings[pio][1] << 8);
}
+
+ /* Enable SITRE (separate slave timing register) */
+ master_data |= 0x4000;
pci_write_config_word(dev, master_port, master_data);
if (is_slave)
pci_write_config_byte(dev, slave_port, slave_data);
@@ -795,6 +818,22 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
}
/**
+ * piix_set_piomode - Initialize host controller PATA PIO timings
+ * @ap: Port whose timings we are configuring
+ * @adev: Drive in question
+ *
+ * Set PIO mode for device, in host controller PCI config space.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+
+static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ piix_set_timings(ap, adev, adev->pio_mode - XFER_PIO_0);
+}
+
+/**
* do_pata_set_dmamode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
* @adev: Drive in question
@@ -810,31 +849,20 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in
{
struct pci_dev *dev = to_pci_dev(ap->host->dev);
unsigned long flags;
- u8 master_port = ap->port_no ? 0x42 : 0x40;
- u16 master_data;
u8 speed = adev->dma_mode;
int devid = adev->devno + 2 * ap->port_no;
u8 udma_enable = 0;
- static const /* ISP RTC */
- u8 timings[][2] = { { 0, 0 },
- { 0, 0 },
- { 1, 0 },
- { 2, 1 },
- { 2, 3 }, };
-
- spin_lock_irqsave(&piix_lock, flags);
-
- pci_read_config_word(dev, master_port, &master_data);
- if (ap->udma_mask)
- pci_read_config_byte(dev, 0x48, &udma_enable);
-
if (speed >= XFER_UDMA_0) {
- unsigned int udma = adev->dma_mode - XFER_UDMA_0;
+ unsigned int udma = speed - XFER_UDMA_0;
u16 udma_timing;
u16 ideconf;
int u_clock, u_speed;
+ spin_lock_irqsave(&piix_lock, flags);
+
+ pci_read_config_byte(dev, 0x48, &udma_enable);
+
/*
* UDMA is handled by a combination of clock switching and
* selection of dividers
@@ -867,56 +895,21 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in
performance (WR_PingPong_En) */
pci_write_config_word(dev, 0x54, ideconf);
}
+
+ pci_write_config_byte(dev, 0x48, udma_enable);
+
+ spin_unlock_irqrestore(&piix_lock, flags);
} else {
- /*
- * MWDMA is driven by the PIO timings. We must also enable
- * IORDY unconditionally along with TIME1. PPE has already
- * been set when the PIO timing was set.
- */
- unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0;
- unsigned int control;
- u8 slave_data;
+ /* MWDMA is driven by the PIO timings. */
+ unsigned int mwdma = speed - XFER_MW_DMA_0;
const unsigned int needed_pio[3] = {
XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
};
int pio = needed_pio[mwdma] - XFER_PIO_0;
- control = 3; /* IORDY|TIME1 */
-
- /* If the drive MWDMA is faster than it can do PIO then
- we must force PIO into PIO0 */
-
- if (adev->pio_mode < needed_pio[mwdma])
- /* Enable DMA timing only */
- control |= 8; /* PIO cycles in PIO0 */
-
- if (adev->devno) { /* Slave */
- master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */
- master_data |= control << 4;
- pci_read_config_byte(dev, 0x44, &slave_data);
- slave_data &= (ap->port_no ? 0x0f : 0xf0);
- /* Load the matching timing */
- slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
- pci_write_config_byte(dev, 0x44, slave_data);
- } else { /* Master */
- master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY
- and master timing bits */
- master_data |= control;
- master_data |=
- (timings[pio][0] << 12) |
- (timings[pio][1] << 8);
- }
-
- if (ap->udma_mask)
- udma_enable &= ~(1 << devid);
-
- pci_write_config_word(dev, master_port, master_data);
+ /* XFER_PIO_0 is never used currently */
+ piix_set_timings(ap, adev, pio);
}
- /* Don't scribble on 0x48 if the controller does not support UDMA */
- if (ap->udma_mask)
- pci_write_config_byte(dev, 0x48, udma_enable);
-
- spin_unlock_irqrestore(&piix_lock, flags);
}
/**
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 4a3a5ae7bb45..c04ad68cb602 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2938,7 +2938,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
if (id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
memset(&p, 0, sizeof(p));
- if (speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
+ if (speed >= XFER_PIO_0 && speed < XFER_SW_DMA_0) {
if (speed <= XFER_PIO_2)
p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
else if ((speed <= XFER_PIO_4) ||
@@ -6713,6 +6713,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
+EXPORT_SYMBOL_GPL(__ata_change_queue_depth);
EXPORT_SYMBOL_GPL(sata_scr_valid);
EXPORT_SYMBOL_GPL(sata_scr_read);
EXPORT_SYMBOL_GPL(sata_scr_write);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index ed16fbedaabd..c021186736e9 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2532,8 +2532,7 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
return reset(link, classes, deadline);
}
-static int ata_eh_followup_srst_needed(struct ata_link *link,
- int rc, const unsigned int *classes)
+static int ata_eh_followup_srst_needed(struct ata_link *link, int rc)
{
if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link))
return 0;
@@ -2726,7 +2725,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
/* perform follow-up SRST if necessary */
if (reset == hardreset &&
- ata_eh_followup_srst_needed(link, rc, classes)) {
+ ata_eh_followup_srst_needed(link, rc)) {
reset = softreset;
if (!reset) {
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 46d087f08607..19ba77032ac2 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1215,25 +1215,15 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
}
/**
- * ata_scsi_change_queue_depth - SCSI callback for queue depth config
- * @sdev: SCSI device to configure queue depth for
- * @queue_depth: new queue depth
- * @reason: calling context
- *
- * This is libata standard hostt->change_queue_depth callback.
- * SCSI will call into this callback when user tries to set queue
- * depth via sysfs.
+ * __ata_change_queue_depth - helper for ata_scsi_change_queue_depth
*
- * LOCKING:
- * SCSI layer (we don't care)
+ * libsas and libata have different approaches for associating a sdev to
+ * its ata_port.
*
- * RETURNS:
- * Newly configured queue depth.
*/
-int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
- int reason)
+int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
+ int queue_depth, int reason)
{
- struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev;
unsigned long flags;
@@ -1269,6 +1259,30 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
}
/**
+ * ata_scsi_change_queue_depth - SCSI callback for queue depth config
+ * @sdev: SCSI device to configure queue depth for
+ * @queue_depth: new queue depth
+ * @reason: calling context
+ *
+ * This is libata standard hostt->change_queue_depth callback.
+ * SCSI will call into this callback when user tries to set queue
+ * depth via sysfs.
+ *
+ * LOCKING:
+ * SCSI layer (we don't care)
+ *
+ * RETURNS:
+ * Newly configured queue depth.
+ */
+int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+ int reason)
+{
+ struct ata_port *ap = ata_shost_to_port(sdev->host);
+
+ return __ata_change_queue_depth(ap, sdev, queue_depth, reason);
+}
+
+/**
* ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
* @qc: Storage for translated ATA taskfile
*
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index c24127dd6ef2..239bfa67d032 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -569,7 +569,7 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,
/* Transfer trailing byte, if any. */
if (unlikely(buflen & 0x01)) {
- unsigned char pad[2];
+ unsigned char pad[2] = { };
/* Point buf to the tail of buffer */
buf += buflen - 1;
@@ -628,7 +628,7 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
/* Transfer trailing bytes, if any */
if (unlikely(slop)) {
- unsigned char pad[4];
+ unsigned char pad[4] = { };
/* Point buf to the tail of buffer */
buf += buflen - slop;
@@ -678,7 +678,7 @@ unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
unsigned int consumed;
local_irq_save(flags);
- consumed = ata_sff_data_xfer(dev, buf, buflen, rw);
+ consumed = ata_sff_data_xfer32(dev, buf, buflen, rw);
local_irq_restore(flags);
return consumed;
@@ -2507,31 +2507,10 @@ static const struct ata_port_info *ata_sff_find_valid_pi(
return NULL;
}
-/**
- * ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller
- * @pdev: Controller to be initialized
- * @ppi: array of port_info, must be enough for two ports
- * @sht: scsi_host_template to use when registering the host
- * @host_priv: host private_data
- * @hflag: host flags
- *
- * This is a helper function which can be called from a driver's
- * xxx_init_one() probe function if the hardware uses traditional
- * IDE taskfile registers and is PIO only.
- *
- * ASSUMPTION:
- * Nobody makes a single channel controller that appears solely as
- * the secondary legacy port on PCI.
- *
- * LOCKING:
- * Inherited from PCI layer (may sleep).
- *
- * RETURNS:
- * Zero on success, negative on errno-based value on error.
- */
-int ata_pci_sff_init_one(struct pci_dev *pdev,
- const struct ata_port_info * const *ppi,
- struct scsi_host_template *sht, void *host_priv, int hflag)
+static int ata_pci_init_one(struct pci_dev *pdev,
+ const struct ata_port_info * const *ppi,
+ struct scsi_host_template *sht, void *host_priv,
+ int hflags, bool bmdma)
{
struct device *dev = &pdev->dev;
const struct ata_port_info *pi;
@@ -2553,14 +2532,22 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
if (rc)
goto out;
- /* prepare and activate SFF host */
- rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ if (bmdma)
+ /* prepare and activate BMDMA host */
+ rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
+ else
+ /* prepare and activate SFF host */
+ rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
if (rc)
goto out;
host->private_data = host_priv;
- host->flags |= hflag;
+ host->flags |= hflags;
- rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
+ if (bmdma) {
+ pci_set_master(pdev);
+ rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
+ } else
+ rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
out:
if (rc == 0)
devres_remove_group(&pdev->dev, NULL);
@@ -2569,6 +2556,35 @@ out:
return rc;
}
+
+/**
+ * ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller
+ * @pdev: Controller to be initialized
+ * @ppi: array of port_info, must be enough for two ports
+ * @sht: scsi_host_template to use when registering the host
+ * @host_priv: host private_data
+ * @hflag: host flags
+ *
+ * This is a helper function which can be called from a driver's
+ * xxx_init_one() probe function if the hardware uses traditional
+ * IDE taskfile registers and is PIO only.
+ *
+ * ASSUMPTION:
+ * Nobody makes a single channel controller that appears solely as
+ * the secondary legacy port on PCI.
+ *
+ * LOCKING:
+ * Inherited from PCI layer (may sleep).
+ *
+ * RETURNS:
+ * Zero on success, negative on errno-based value on error.
+ */
+int ata_pci_sff_init_one(struct pci_dev *pdev,
+ const struct ata_port_info * const *ppi,
+ struct scsi_host_template *sht, void *host_priv, int hflag)
+{
+ return ata_pci_init_one(pdev, ppi, sht, host_priv, hflag, 0);
+}
EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
#endif /* CONFIG_PCI */
@@ -3286,42 +3302,7 @@ int ata_pci_bmdma_init_one(struct pci_dev *pdev,
struct scsi_host_template *sht, void *host_priv,
int hflags)
{
- struct device *dev = &pdev->dev;
- const struct ata_port_info *pi;
- struct ata_host *host = NULL;
- int rc;
-
- DPRINTK("ENTER\n");
-
- pi = ata_sff_find_valid_pi(ppi);
- if (!pi) {
- dev_err(&pdev->dev, "no valid port_info specified\n");
- return -EINVAL;
- }
-
- if (!devres_open_group(dev, NULL, GFP_KERNEL))
- return -ENOMEM;
-
- rc = pcim_enable_device(pdev);
- if (rc)
- goto out;
-
- /* prepare and activate BMDMA host */
- rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
- if (rc)
- goto out;
- host->private_data = host_priv;
- host->flags |= hflags;
-
- pci_set_master(pdev);
- rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
- out:
- if (rc == 0)
- devres_remove_group(&pdev->dev, NULL);
- else
- devres_release_group(&pdev->dev, NULL);
-
- return rc;
+ return ata_pci_init_one(pdev, ppi, sht, host_priv, hflags, 1);
}
EXPORT_SYMBOL_GPL(ata_pci_bmdma_init_one);
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index cadd67998bac..61da0694aecd 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -56,7 +56,7 @@ static const struct dmi_system_id cable_dmi_table[] = {
},
},
{
- .ident = "Toshiba Satelite S1800-814",
+ .ident = "Toshiba Satellite S1800-814",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"),
diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
index 719bb73a73e0..e8574bba3ee4 100644
--- a/drivers/ata/pata_arasan_cf.c
+++ b/drivers/ata/pata_arasan_cf.c
@@ -922,8 +922,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int arasan_cf_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct ata_host *host = dev_get_drvdata(dev);
struct arasan_cf_dev *acdev = host->ports[0]->private_data;
if (acdev->dma_chan) {
@@ -937,8 +936,7 @@ static int arasan_cf_suspend(struct device *dev)
static int arasan_cf_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct ata_host *host = dev_get_drvdata(dev);
struct arasan_cf_dev *acdev = host->ports[0]->private_data;
cf_init(acdev);
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 78a93b690959..4b8b22efc00b 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -2,7 +2,7 @@
* pata_artop.c - ARTOP ATA controller driver
*
* (C) 2006 Red Hat
- * (C) 2007 Bartlomiej Zolnierkiewicz
+ * (C) 2007,2011 Bartlomiej Zolnierkiewicz
*
* Based in part on drivers/ide/pci/aec62xx.c
* Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
@@ -28,7 +28,7 @@
#include <linux/ata.h>
#define DRV_NAME "pata_artop"
-#define DRV_VERSION "0.4.5"
+#define DRV_VERSION "0.4.6"
/*
* The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
@@ -39,31 +39,15 @@
static int clock = 0;
-static int artop6210_pre_reset(struct ata_link *link, unsigned long deadline)
-{
- struct ata_port *ap = link->ap;
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- const struct pci_bits artop_enable_bits[] = {
- { 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */
- { 0x4AU, 1U, 0x04UL, 0x04UL }, /* port 1 */
- };
-
- if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
- return -ENOENT;
-
- return ata_sff_prereset(link, deadline);
-}
-
/**
- * artop6260_pre_reset - check for 40/80 pin
+ * artop62x0_pre_reset - probe begin
* @link: link
* @deadline: deadline jiffies for the operation
*
- * The ARTOP hardware reports the cable detect bits in register 0x49.
* Nothing complicated needed here.
*/
-static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline)
+static int artop62x0_pre_reset(struct ata_link *link, unsigned long deadline)
{
static const struct pci_bits artop_enable_bits[] = {
{ 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */
@@ -73,7 +57,7 @@ static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline)
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- /* Odd numbered device ids are the units with enable bits (the -R cards) */
+ /* Odd numbered device ids are the units with enable bits. */
if ((pdev->device & 1) &&
!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
return -ENOENT;
@@ -317,7 +301,7 @@ static struct ata_port_operations artop6210_ops = {
.cable_detect = ata_cable_40wire,
.set_piomode = artop6210_set_piomode,
.set_dmamode = artop6210_set_dmamode,
- .prereset = artop6210_pre_reset,
+ .prereset = artop62x0_pre_reset,
.qc_defer = artop6210_qc_defer,
};
@@ -326,9 +310,36 @@ static struct ata_port_operations artop6260_ops = {
.cable_detect = artop6260_cable_detect,
.set_piomode = artop6260_set_piomode,
.set_dmamode = artop6260_set_dmamode,
- .prereset = artop6260_pre_reset,
+ .prereset = artop62x0_pre_reset,
};
+static void atp8xx_fixup(struct pci_dev *pdev)
+{
+ if (pdev->device == 0x0005)
+ /* BIOS may have left us in UDMA, clear it before libata probe */
+ pci_write_config_byte(pdev, 0x54, 0);
+ else if (pdev->device == 0x0008 || pdev->device == 0x0009) {
+ u8 reg;
+
+ /* Mac systems come up with some registers not set as we
+ will need them */
+
+ /* Clear reset & test bits */
+ pci_read_config_byte(pdev, 0x49, &reg);
+ pci_write_config_byte(pdev, 0x49, reg & ~0x30);
+
+ /* PCI latency must be > 0x80 for burst mode, tweak it
+ * if required.
+ */
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &reg);
+ if (reg <= 0x80)
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90);
+
+ /* Enable IRQ output and burst mode */
+ pci_read_config_byte(pdev, 0x4a, &reg);
+ pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80);
+ }
+}
/**
* artop_init_one - Register ARTOP ATA PCI device with kernel services
@@ -383,42 +394,22 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
- if (id->driver_data == 0) { /* 6210 variant */
+ if (id->driver_data == 0) /* 6210 variant */
ppi[0] = &info_6210;
- /* BIOS may have left us in UDMA, clear it before libata probe */
- pci_write_config_byte(pdev, 0x54, 0);
- }
else if (id->driver_data == 1) /* 6260 */
ppi[0] = &info_626x;
else if (id->driver_data == 2) { /* 6280 or 6280 + fast */
unsigned long io = pci_resource_start(pdev, 4);
- u8 reg;
ppi[0] = &info_628x;
if (inb(io) & 0x10)
ppi[0] = &info_628x_fast;
- /* Mac systems come up with some registers not set as we
- will need them */
-
- /* Clear reset & test bits */
- pci_read_config_byte(pdev, 0x49, &reg);
- pci_write_config_byte(pdev, 0x49, reg & ~ 0x30);
-
- /* PCI latency must be > 0x80 for burst mode, tweak it
- * if required.
- */
- pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &reg);
- if (reg <= 0x80)
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90);
-
- /* Enable IRQ output and burst mode */
- pci_read_config_byte(pdev, 0x4a, &reg);
- pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80);
-
}
BUG_ON(ppi[0] == NULL);
+ atp8xx_fixup(pdev);
+
return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0);
}
@@ -432,11 +423,32 @@ static const struct pci_device_id artop_pci_tbl[] = {
{ } /* terminate list */
};
+#ifdef CONFIG_PM
+static int atp8xx_reinit_one(struct pci_dev *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ int rc;
+
+ rc = ata_pci_device_do_resume(pdev);
+ if (rc)
+ return rc;
+
+ atp8xx_fixup(pdev);
+
+ ata_host_resume(host);
+ return 0;
+}
+#endif
+
static struct pci_driver artop_pci_driver = {
.name = DRV_NAME,
.id_table = artop_pci_tbl,
.probe = artop_init_one,
.remove = ata_pci_remove_one,
+#ifdef CONFIG_PM
+ .suspend = ata_pci_device_suspend,
+ .resume = atp8xx_reinit_one,
+#endif
};
static int __init artop_init(void)
@@ -452,9 +464,8 @@ static void __exit artop_exit(void)
module_init(artop_init);
module_exit(artop_exit);
-MODULE_AUTHOR("Alan Cox");
+MODULE_AUTHOR("Alan Cox, Bartlomiej Zolnierkiewicz");
MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, artop_pci_tbl);
MODULE_VERSION(DRV_VERSION);
-
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c
index 960c72571395..a76f24a8e5db 100644
--- a/drivers/ata/pata_at91.c
+++ b/drivers/ata/pata_at91.c
@@ -30,7 +30,7 @@
#include <mach/at91sam9_smc.h>
#include <mach/board.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#define DRV_NAME "pata_at91"
#define DRV_VERSION "0.3"
@@ -414,10 +414,13 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
host->private_data = info;
- return ata_host_activate(host, irq ? gpio_to_irq(irq) : 0,
+ ret = ata_host_activate(host, irq ? gpio_to_irq(irq) : 0,
irq ? ata_sff_interrupt : NULL,
irq_flags, &pata_at91_sht);
+ if (!ret)
+ return 0;
+
err_put:
clk_put(info->mck);
return ret;
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 43755616dc5a..be1aa1486d39 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -49,6 +49,31 @@ static int atiixp_cable_detect(struct ata_port *ap)
static DEFINE_SPINLOCK(atiixp_lock);
/**
+ * atiixp_prereset - perform reset handling
+ * @link: ATA link
+ * @deadline: deadline jiffies for the operation
+ *
+ * Reset sequence checking enable bits to see which ports are
+ * active.
+ */
+
+static int atiixp_prereset(struct ata_link *link, unsigned long deadline)
+{
+ static const struct pci_bits atiixp_enable_bits[] = {
+ { 0x48, 1, 0x01, 0x00 },
+ { 0x48, 1, 0x08, 0x00 }
+ };
+
+ struct ata_port *ap = link->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+ if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+ return ata_sff_prereset(link, deadline);
+}
+
+/**
* atiixp_set_pio_timing - set initial PIO mode data
* @ap: ATA interface
* @adev: ATA device
@@ -221,6 +246,7 @@ static struct ata_port_operations atiixp_port_ops = {
.bmdma_start = atiixp_bmdma_start,
.bmdma_stop = atiixp_bmdma_stop,
+ .prereset = atiixp_prereset,
.cable_detect = atiixp_cable_detect,
.set_piomode = atiixp_set_piomode,
.set_dmamode = atiixp_set_dmamode,
@@ -235,16 +261,7 @@ static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
.udma_mask = ATA_UDMA5,
.port_ops = &atiixp_port_ops
};
- static const struct pci_bits atiixp_enable_bits[] = {
- { 0x48, 1, 0x01, 0x00 },
- { 0x48, 1, 0x08, 0x00 }
- };
const struct ata_port_info *ppi[] = { &info, &info };
- int i;
-
- for (i = 0; i < 2; i++)
- if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i]))
- ppi[i] = &ata_dummy_port_info;
return ata_pci_bmdma_init_one(pdev, ppi, &atiixp_sht, NULL,
ATA_HOST_PARALLEL_SCAN);
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 7bafc16cf5e0..e1fb39a74ce1 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -82,7 +82,7 @@ static int cmd648_cable_detect(struct ata_port *ap)
}
/**
- * cmd64x_set_piomode - set PIO and MWDMA timing
+ * cmd64x_set_timing - set PIO and MWDMA timing
* @ap: ATA interface
* @adev: ATA device
* @mode: mode
@@ -288,6 +288,22 @@ static struct ata_port_operations cmd648_port_ops = {
.cable_detect = cmd648_cable_detect,
};
+static void cmd64x_fixup(struct pci_dev *pdev)
+{
+ u8 mrdmode;
+
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+ pci_read_config_byte(pdev, MRDMODE, &mrdmode);
+ mrdmode &= ~0x30; /* IRQ set up */
+ mrdmode |= 0x02; /* Memory read line enable */
+ pci_write_config_byte(pdev, MRDMODE, mrdmode);
+
+ /* PPC specific fixup copied from old driver */
+#ifdef CONFIG_PPC
+ pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
+#endif
+}
+
static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info cmd_info[6] = {
@@ -336,7 +352,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
&cmd_info[id->driver_data],
NULL
};
- u8 mrdmode, reg;
+ u8 reg;
int rc;
struct pci_dev *bridge = pdev->bus->self;
/* mobility split bridges don't report enabled ports correctly */
@@ -368,11 +384,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
cntrl_ch0_ok = 0;
}
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
- pci_read_config_byte(pdev, MRDMODE, &mrdmode);
- mrdmode &= ~ 0x30; /* IRQ set up */
- mrdmode |= 0x02; /* Memory read line enable */
- pci_write_config_byte(pdev, MRDMODE, mrdmode);
+ cmd64x_fixup(pdev);
/* check for enabled ports */
pci_read_config_byte(pdev, CNTRL, &reg);
@@ -388,13 +400,6 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
ppi[1] = &ata_dummy_port_info;
}
- /* Force PIO 0 here.. */
-
- /* PPC specific fixup copied from old driver */
-#ifdef CONFIG_PPC
- pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
-#endif
-
return ata_pci_bmdma_init_one(pdev, ppi, &cmd64x_sht, NULL, 0);
}
@@ -402,21 +407,14 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static int cmd64x_reinit_one(struct pci_dev *pdev)
{
struct ata_host *host = dev_get_drvdata(&pdev->dev);
- u8 mrdmode;
int rc;
rc = ata_pci_device_do_resume(pdev);
if (rc)
return rc;
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
- pci_read_config_byte(pdev, MRDMODE, &mrdmode);
- mrdmode &= ~ 0x30; /* IRQ set up */
- mrdmode |= 0x02; /* Memory read line enable */
- pci_write_config_byte(pdev, MRDMODE, mrdmode);
-#ifdef CONFIG_PPC
- pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
-#endif
+ cmd64x_fixup(pdev);
+
ata_host_resume(host);
return 0;
}
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index 03a93186aa19..a0b4640125ae 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -38,7 +38,7 @@
#include <linux/libata.h>
#include <asm/msr.h>
-#define DRV_NAME "cs5535"
+#define DRV_NAME "pata_cs5535"
#define DRV_VERSION "0.2.12"
/*
@@ -67,8 +67,6 @@
#define CS5535_CABLE_DETECT 0x48
-#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000UL)==0x00009172 )
-
/**
* cs5535_cable_detect - detect cable type
* @ap: Port to detect on
@@ -188,16 +186,6 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
};
const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
- u32 timings, dummy;
-
- /* Check the BIOS set the initial timing clock. If not set the
- timings for PIO0 */
- rdmsr(ATAC_CH0D0_PIO, timings, dummy);
- if (CS5535_BAD_PIO(timings))
- wrmsr(ATAC_CH0D0_PIO, 0xF7F4F7F4UL, 0);
- rdmsr(ATAC_CH0D1_PIO, timings, dummy);
- if (CS5535_BAD_PIO(timings))
- wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0);
return ata_pci_bmdma_init_one(dev, ppi, &cs5535_sht, NULL, 0);
}
@@ -230,7 +218,7 @@ static void __exit cs5535_exit(void)
}
MODULE_AUTHOR("Alan Cox, Jens Altmann, Wolfgan Zuleger, Alexander Kiausch");
-MODULE_DESCRIPTION("low-level driver for the NS/AMD 5530");
+MODULE_DESCRIPTION("low-level driver for the NS/AMD 5535");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, cs5535);
MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index aca47e4e29ea..f0243ed206f7 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -73,7 +73,7 @@ static DEFINE_SPINLOCK(efar_lock);
/**
* efar_set_piomode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
- * @adev: um
+ * @adev: Device to program
*
* Set PIO mode for device, in host controller PCI config space.
*
@@ -85,9 +85,9 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev)
{
unsigned int pio = adev->pio_mode - XFER_PIO_0;
struct pci_dev *dev = to_pci_dev(ap->host->dev);
- unsigned int idetm_port= ap->port_no ? 0x42 : 0x40;
+ unsigned int master_port = ap->port_no ? 0x42 : 0x40;
unsigned long flags;
- u16 idetm_data;
+ u16 master_data;
u8 udma_enable;
int control = 0;
@@ -113,20 +113,20 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev)
spin_lock_irqsave(&efar_lock, flags);
- pci_read_config_word(dev, idetm_port, &idetm_data);
+ pci_read_config_word(dev, master_port, &master_data);
/* Set PPE, IE, and TIME as appropriate */
if (adev->devno == 0) {
- idetm_data &= 0xCCF0;
- idetm_data |= control;
- idetm_data |= (timings[pio][0] << 12) |
+ master_data &= 0xCCF0;
+ master_data |= control;
+ master_data |= (timings[pio][0] << 12) |
(timings[pio][1] << 8);
} else {
int shift = 4 * ap->port_no;
u8 slave_data;
- idetm_data &= 0xFF0F;
- idetm_data |= (control << 4);
+ master_data &= 0xFF0F;
+ master_data |= (control << 4);
/* Slave timing in separate register */
pci_read_config_byte(dev, 0x44, &slave_data);
@@ -135,8 +135,8 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev)
pci_write_config_byte(dev, 0x44, slave_data);
}
- idetm_data |= 0x4000; /* Ensure SITRE is set */
- pci_write_config_word(dev, idetm_port, idetm_data);
+ master_data |= 0x4000; /* Ensure SITRE is set */
+ pci_write_config_word(dev, master_port, master_data);
pci_read_config_byte(dev, 0x48, &udma_enable);
udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 6c77d68dbd05..42cffd38910d 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -111,6 +111,28 @@ static const struct hpt_clock hpt366_25[] = {
{ 0, 0x01208585 }
};
+/**
+ * hpt36x_find_mode - find the hpt36x timing
+ * @ap: ATA port
+ * @speed: transfer mode
+ *
+ * Return the 32bit register programming information for this channel
+ * that matches the speed provided.
+ */
+
+static u32 hpt36x_find_mode(struct ata_port *ap, int speed)
+{
+ struct hpt_clock *clocks = ap->host->private_data;
+
+ while (clocks->xfer_mode) {
+ if (clocks->xfer_mode == speed)
+ return clocks->timing;
+ clocks++;
+ }
+ BUG();
+ return 0xffffffffU; /* silence compiler warning */
+}
+
static const char * const bad_ata33[] = {
"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3",
"Maxtor 90845U3", "Maxtor 90650U2",
@@ -210,10 +232,9 @@ static int hpt36x_cable_detect(struct ata_port *ap)
static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
u8 mode)
{
- struct hpt_clock *clocks = ap->host->private_data;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 addr = 0x40 + 4 * adev->devno;
- u32 mask, reg;
+ u32 mask, reg, t;
/* determine timing mask and find matching clock entry */
if (mode < XFER_MW_DMA_0)
@@ -223,13 +244,7 @@ static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
else
mask = 0x30070000;
- while (clocks->xfer_mode) {
- if (clocks->xfer_mode == mode)
- break;
- clocks++;
- }
- if (!clocks->xfer_mode)
- BUG();
+ t = hpt36x_find_mode(ap, mode);
/*
* Combine new mode bits with old config bits and disable
@@ -237,7 +252,7 @@ static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
* problems handling I/O errors later.
*/
pci_read_config_dword(pdev, addr, &reg);
- reg = ((reg & ~mask) | (clocks->timing & mask)) & ~0xc0000000;
+ reg = ((reg & ~mask) | (t & mask)) & ~0xc0000000;
pci_write_config_dword(pdev, addr, reg);
}
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index 998af0e629b1..cf9164d79f11 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -76,8 +76,8 @@ static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)
{
unsigned int pio = adev->pio_mode - XFER_PIO_0;
struct pci_dev *dev = to_pci_dev(ap->host->dev);
- unsigned int idetm_port= ap->port_no ? 0x42 : 0x40;
- u16 idetm_data;
+ unsigned int master_port = ap->port_no ? 0x42 : 0x40;
+ u16 master_data;
int control = 0;
/*
@@ -100,19 +100,19 @@ static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)
if (adev->class != ATA_DEV_ATA)
control |= 4; /* PPE */
- pci_read_config_word(dev, idetm_port, &idetm_data);
+ pci_read_config_word(dev, master_port, &master_data);
/* Set PPE, IE, and TIME as appropriate */
if (adev->devno == 0) {
- idetm_data &= 0xCCF0;
- idetm_data |= control;
- idetm_data |= (timings[pio][0] << 12) |
+ master_data &= 0xCCF0;
+ master_data |= control;
+ master_data |= (timings[pio][0] << 12) |
(timings[pio][1] << 8);
} else {
u8 slave_data;
- idetm_data &= 0xFF0F;
- idetm_data |= (control << 4);
+ master_data &= 0xFF0F;
+ master_data |= (control << 4);
/* Slave timing in separate register */
pci_read_config_byte(dev, 0x44, &slave_data);
@@ -121,8 +121,8 @@ static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)
pci_write_config_byte(dev, 0x44, slave_data);
}
- idetm_data |= 0x4000; /* Ensure SITRE is set */
- pci_write_config_word(dev, idetm_port, idetm_data);
+ master_data |= 0x4000; /* Ensure SITRE is set */
+ pci_write_config_word(dev, master_port, master_data);
}
/**
@@ -163,7 +163,7 @@ static void it8213_set_dmamode (struct ata_port *ap, struct ata_device *adev)
/* Clocks follow the PIIX style */
u_speed = min(2 - (udma & 1), udma);
- if (udma == 5)
+ if (udma > 4)
u_clock = 0x1000; /* 100Mhz */
else if (udma > 2)
u_clock = 1; /* 66Mhz */
@@ -262,7 +262,7 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA12_ONLY,
- .udma_mask = ATA_UDMA4, /* FIXME: want UDMA 100? */
+ .udma_mask = ATA_UDMA6,
.port_ops = &it8213_ops,
};
/* Current IT8213 stuff is single port */
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index d960f8e9e8b1..35aca7d1a3eb 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -79,15 +79,6 @@ static int all;
module_param(all, int, 0444);
MODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)");
-struct legacy_data {
- unsigned long timing;
- u8 clock[2];
- u8 last;
- int fast;
- struct platform_device *platform_dev;
-
-};
-
enum controller {
BIOS = 0,
SNOOP = 1,
@@ -104,6 +95,14 @@ enum controller {
UNKNOWN = -1
};
+struct legacy_data {
+ unsigned long timing;
+ u8 clock[2];
+ u8 last;
+ int fast;
+ enum controller type;
+ struct platform_device *platform_dev;
+};
struct legacy_probe {
unsigned char *name;
@@ -137,11 +136,17 @@ static int ht6560a; /* HT 6560A on primary 1, second 2, both 3 */
static int ht6560b; /* HT 6560A on primary 1, second 2, both 3 */
static int opti82c611a; /* Opti82c611A on primary 1, sec 2, both 3 */
static int opti82c46x; /* Opti 82c465MV present(pri/sec autodetect) */
-static int qdi; /* Set to probe QDI controllers */
static int autospeed; /* Chip present which snoops speed changes */
static int pio_mask = ATA_PIO4; /* PIO range for autospeed devices */
static int iordy_mask = 0xFFFFFFFF; /* Use iordy if available */
+/* Set to probe QDI controllers */
+#ifdef CONFIG_PATA_QDI_MODULE
+static int qdi = 1;
+#else
+static int qdi;
+#endif
+
#ifdef CONFIG_PATA_WINBOND_VLB_MODULE
static int winbond = 1; /* Set to probe Winbond controllers,
give I/O port if non standard */
@@ -631,40 +636,20 @@ static struct ata_port_operations opti82c46x_port_ops = {
.qc_issue = opti82c46x_qc_issue,
};
-static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
- struct ata_timing t;
- struct legacy_data *ld_qdi = ap->host->private_data;
- int active, recovery;
- u8 timing;
-
- /* Get the timing data in cycles */
- ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
- if (ld_qdi->fast) {
- active = 8 - clamp_val(t.active, 1, 8);
- recovery = 18 - clamp_val(t.recover, 3, 18);
- } else {
- active = 9 - clamp_val(t.active, 2, 9);
- recovery = 15 - clamp_val(t.recover, 0, 15);
- }
- timing = (recovery << 4) | active | 0x08;
-
- ld_qdi->clock[adev->devno] = timing;
-
- outb(timing, ld_qdi->timing);
-}
-
/**
- * qdi6580dp_set_piomode - PIO setup for dual channel
+ * qdi65x0_set_piomode - PIO setup for QDI65x0
* @ap: Port
* @adev: Device
*
+ * In single channel mode the 6580 has one clock per device and we can
+ * avoid the requirement to clock switch. We also have to load the timing
+ * into the right clock according to whether we are master or slave.
+ *
* In dual channel mode the 6580 has one clock per channel and we have
* to software clockswitch in qc_issue.
*/
-static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
+static void qdi65x0_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
struct ata_timing t;
struct legacy_data *ld_qdi = ap->host->private_data;
@@ -682,47 +667,15 @@ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
recovery = 15 - clamp_val(t.recover, 0, 15);
}
timing = (recovery << 4) | active | 0x08;
-
ld_qdi->clock[adev->devno] = timing;
- outb(timing, ld_qdi->timing + 2 * ap->port_no);
- /* Clear the FIFO */
- if (adev->class != ATA_DEV_ATA)
- outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3);
-}
-
-/**
- * qdi6580_set_piomode - PIO setup for single channel
- * @ap: Port
- * @adev: Device
- *
- * In single channel mode the 6580 has one clock per device and we can
- * avoid the requirement to clock switch. We also have to load the timing
- * into the right clock according to whether we are master or slave.
- */
-
-static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
- struct ata_timing t;
- struct legacy_data *ld_qdi = ap->host->private_data;
- int active, recovery;
- u8 timing;
-
- /* Get the timing data in cycles */
- ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
+ if (ld_qdi->type == QDI6580)
+ outb(timing, ld_qdi->timing + 2 * adev->devno);
+ else
+ outb(timing, ld_qdi->timing + 2 * ap->port_no);
- if (ld_qdi->fast) {
- active = 8 - clamp_val(t.active, 1, 8);
- recovery = 18 - clamp_val(t.recover, 3, 18);
- } else {
- active = 9 - clamp_val(t.active, 2, 9);
- recovery = 15 - clamp_val(t.recover, 0, 15);
- }
- timing = (recovery << 4) | active | 0x08;
- ld_qdi->clock[adev->devno] = timing;
- outb(timing, ld_qdi->timing + 2 * adev->devno);
/* Clear the FIFO */
- if (adev->class != ATA_DEV_ATA)
+ if (ld_qdi->type != QDI6500 && adev->class != ATA_DEV_ATA)
outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3);
}
@@ -789,20 +742,20 @@ static int qdi_port(struct platform_device *dev,
static struct ata_port_operations qdi6500_port_ops = {
.inherits = &legacy_base_port_ops,
- .set_piomode = qdi6500_set_piomode,
+ .set_piomode = qdi65x0_set_piomode,
.qc_issue = qdi_qc_issue,
.sff_data_xfer = vlb32_data_xfer,
};
static struct ata_port_operations qdi6580_port_ops = {
.inherits = &legacy_base_port_ops,
- .set_piomode = qdi6580_set_piomode,
+ .set_piomode = qdi65x0_set_piomode,
.sff_data_xfer = vlb32_data_xfer,
};
static struct ata_port_operations qdi6580dp_port_ops = {
.inherits = &legacy_base_port_ops,
- .set_piomode = qdi6580dp_set_piomode,
+ .set_piomode = qdi65x0_set_piomode,
.qc_issue = qdi_qc_issue,
.sff_data_xfer = vlb32_data_xfer,
};
@@ -879,29 +832,29 @@ static struct ata_port_operations winbond_port_ops = {
};
static struct legacy_controller controllers[] = {
- {"BIOS", &legacy_port_ops, 0x1F,
+ {"BIOS", &legacy_port_ops, ATA_PIO4,
ATA_FLAG_NO_IORDY, 0, NULL },
- {"Snooping", &simple_port_ops, 0x1F,
+ {"Snooping", &simple_port_ops, ATA_PIO4,
0, 0, NULL },
- {"PDC20230", &pdc20230_port_ops, 0x7,
+ {"PDC20230", &pdc20230_port_ops, ATA_PIO2,
ATA_FLAG_NO_IORDY,
ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, NULL },
- {"HT6560A", &ht6560a_port_ops, 0x07,
+ {"HT6560A", &ht6560a_port_ops, ATA_PIO2,
ATA_FLAG_NO_IORDY, 0, NULL },
- {"HT6560B", &ht6560b_port_ops, 0x1F,
+ {"HT6560B", &ht6560b_port_ops, ATA_PIO4,
ATA_FLAG_NO_IORDY, 0, NULL },
- {"OPTI82C611A", &opti82c611a_port_ops, 0x0F,
+ {"OPTI82C611A", &opti82c611a_port_ops, ATA_PIO3,
0, 0, NULL },
- {"OPTI82C46X", &opti82c46x_port_ops, 0x0F,
+ {"OPTI82C46X", &opti82c46x_port_ops, ATA_PIO3,
0, 0, NULL },
- {"QDI6500", &qdi6500_port_ops, 0x07,
+ {"QDI6500", &qdi6500_port_ops, ATA_PIO2,
ATA_FLAG_NO_IORDY,
ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
- {"QDI6580", &qdi6580_port_ops, 0x1F,
+ {"QDI6580", &qdi6580_port_ops, ATA_PIO4,
0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
- {"QDI6580DP", &qdi6580dp_port_ops, 0x1F,
+ {"QDI6580DP", &qdi6580dp_port_ops, ATA_PIO4,
0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
- {"W83759A", &winbond_port_ops, 0x1F,
+ {"W83759A", &winbond_port_ops, ATA_PIO4,
0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,
winbond_port }
};
@@ -1022,6 +975,7 @@ static __init int legacy_init_one(struct legacy_probe *probe)
ctrl_addr = devm_ioport_map(&pdev->dev, io + 0x0206, 1);
if (!io_addr || !ctrl_addr)
goto fail;
+ ld->type = probe->type;
if (controller->setup)
if (controller->setup(pdev, probe, ld) < 0)
goto fail;
@@ -1306,6 +1260,7 @@ MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("low-level driver for legacy ATA");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("pata_qdi");
MODULE_ALIAS("pata_winbond");
module_param(probe_all, int, 0);
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 2fcac511d39c..3e1746314f22 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -780,7 +780,7 @@ mpc52xx_ata_probe(struct platform_device *op)
}
task_irq = bcom_get_task_irq(dmatsk);
- ret = request_irq(task_irq, &mpc52xx_ata_task_irq, IRQF_DISABLED,
+ ret = request_irq(task_irq, &mpc52xx_ata_task_irq, 0,
"ATA task", priv);
if (ret) {
dev_err(&op->dev, "error requesting DMA IRQ\n");
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
index f3054009bd25..a72ab0dde4e5 100644
--- a/drivers/ata/pata_of_platform.c
+++ b/drivers/ata/pata_of_platform.c
@@ -11,6 +11,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/ata_platform.h>
@@ -57,11 +59,11 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
prop = of_get_property(dn, "reg-shift", NULL);
if (prop)
- reg_shift = *prop;
+ reg_shift = be32_to_cpup(prop);
prop = of_get_property(dn, "pio-mode", NULL);
if (prop) {
- pio_mode = *prop;
+ pio_mode = be32_to_cpup(prop);
if (pio_mode > 6) {
dev_err(&ofdev->dev, "invalid pio-mode\n");
return -EINVAL;
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index b1511f38b0e8..7d63f24179c7 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -63,6 +63,7 @@ enum {
};
static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int pdc2027x_reinit_one(struct pci_dev *pdev);
static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline);
static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
@@ -126,6 +127,10 @@ static struct pci_driver pdc2027x_pci_driver = {
.id_table = pdc2027x_pci_tbl,
.probe = pdc2027x_init_one,
.remove = ata_pci_remove_one,
+#ifdef CONFIG_PM
+ .suspend = ata_pci_device_suspend,
+ .resume = pdc2027x_reinit_one,
+#endif
};
static struct scsi_host_template pdc2027x_sht = {
@@ -754,6 +759,31 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
IRQF_SHARED, &pdc2027x_sht);
}
+#ifdef CONFIG_PM
+static int pdc2027x_reinit_one(struct pci_dev *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ unsigned int board_idx;
+ int rc;
+
+ rc = ata_pci_device_do_resume(pdev);
+ if (rc)
+ return rc;
+
+ if (pdev->device == PCI_DEVICE_ID_PROMISE_20268 ||
+ pdev->device == PCI_DEVICE_ID_PROMISE_20270)
+ board_idx = PDC_UDMA_100;
+ else
+ board_idx = PDC_UDMA_133;
+
+ if (pdc_hardware_init(host, board_idx))
+ return -EIO;
+
+ ata_host_resume(host);
+ return 0;
+}
+#endif
+
/**
* pdc2027x_init - Called after this module is loaded into the kernel.
*/
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
deleted file mode 100644
index 45879dc6fa41..000000000000
--- a/drivers/ata/pata_qdi.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * pata_qdi.c - QDI VLB ATA controllers
- * (C) 2006 Red Hat
- *
- * This driver mostly exists as a proof of concept for non PCI devices under
- * libata. While the QDI6580 was 'neat' in 1993 it is no longer terribly
- * useful.
- *
- * Tuning code written from the documentation at
- * http://www.ryston.cz/petr/vlb/qd6500.html
- * http://www.ryston.cz/petr/vlb/qd6580.html
- *
- * Probe code based on drivers/ide/legacy/qd65xx.c
- * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
- * Samuel Thibault <samuel.thibault@ens-lyon.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-#include <linux/platform_device.h>
-
-#define DRV_NAME "pata_qdi"
-#define DRV_VERSION "0.3.1"
-
-#define NR_HOST 4 /* Two 6580s */
-
-struct qdi_data {
- unsigned long timing;
- u8 clock[2];
- u8 last;
- int fast;
- struct platform_device *platform_dev;
-
-};
-
-static struct ata_host *qdi_host[NR_HOST];
-static struct qdi_data qdi_data[NR_HOST];
-static int nr_qdi_host;
-
-#ifdef MODULE
-static int probe_qdi = 1;
-#else
-static int probe_qdi;
-#endif
-
-static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
- struct ata_timing t;
- struct qdi_data *qdi = ap->host->private_data;
- int active, recovery;
- u8 timing;
-
- /* Get the timing data in cycles */
- ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
- if (qdi->fast) {
- active = 8 - clamp_val(t.active, 1, 8);
- recovery = 18 - clamp_val(t.recover, 3, 18);
- } else {
- active = 9 - clamp_val(t.active, 2, 9);
- recovery = 15 - clamp_val(t.recover, 0, 15);
- }
- timing = (recovery << 4) | active | 0x08;
-
- qdi->clock[adev->devno] = timing;
-
- outb(timing, qdi->timing);
-}
-
-static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
- struct ata_timing t;
- struct qdi_data *qdi = ap->host->private_data;
- int active, recovery;
- u8 timing;
-
- /* Get the timing data in cycles */
- ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
- if (qdi->fast) {
- active = 8 - clamp_val(t.active, 1, 8);
- recovery = 18 - clamp_val(t.recover, 3, 18);
- } else {
- active = 9 - clamp_val(t.active, 2, 9);
- recovery = 15 - clamp_val(t.recover, 0, 15);
- }
- timing = (recovery << 4) | active | 0x08;
-
- qdi->clock[adev->devno] = timing;
-
- outb(timing, qdi->timing);
-
- /* Clear the FIFO */
- if (adev->class != ATA_DEV_ATA)
- outb(0x5F, (qdi->timing & 0xFFF0) + 3);
-}
-
-/**
- * qdi_qc_issue - command issue
- * @qc: command pending
- *
- * Called when the libata layer is about to issue a command. We wrap
- * this interface so that we can load the correct ATA timings.
- */
-
-static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- struct ata_device *adev = qc->dev;
- struct qdi_data *qdi = ap->host->private_data;
-
- if (qdi->clock[adev->devno] != qdi->last) {
- if (adev->pio_mode) {
- qdi->last = qdi->clock[adev->devno];
- outb(qdi->clock[adev->devno], qdi->timing);
- }
- }
- return ata_sff_qc_issue(qc);
-}
-
-static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
- unsigned int buflen, int rw)
-{
- if (ata_id_has_dword_io(dev->id)) {
- struct ata_port *ap = dev->link->ap;
- int slop = buflen & 3;
-
- if (rw == READ)
- ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
- else
- iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-
- if (unlikely(slop)) {
- __le32 pad;
- if (rw == READ) {
- pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
- memcpy(buf + buflen - slop, &pad, slop);
- } else {
- memcpy(&pad, buf + buflen - slop, slop);
- iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
- }
- buflen += 4 - slop;
- }
- } else
- buflen = ata_sff_data_xfer(dev, buf, buflen, rw);
-
- return buflen;
-}
-
-static struct scsi_host_template qdi_sht = {
- ATA_PIO_SHT(DRV_NAME),
-};
-
-static struct ata_port_operations qdi6500_port_ops = {
- .inherits = &ata_sff_port_ops,
- .qc_issue = qdi_qc_issue,
- .sff_data_xfer = qdi_data_xfer,
- .cable_detect = ata_cable_40wire,
- .set_piomode = qdi6500_set_piomode,
-};
-
-static struct ata_port_operations qdi6580_port_ops = {
- .inherits = &qdi6500_port_ops,
- .set_piomode = qdi6580_set_piomode,
-};
-
-/**
- * qdi_init_one - attach a qdi interface
- * @type: Type to display
- * @io: I/O port start
- * @irq: interrupt line
- * @fast: True if on a > 33Mhz VLB
- *
- * Register an ISA bus IDE interface. Such interfaces are PIO and we
- * assume do not support IRQ sharing.
- */
-
-static __init int qdi_init_one(unsigned long port, int type, unsigned long io, int irq, int fast)
-{
- unsigned long ctl = io + 0x206;
- struct platform_device *pdev;
- struct ata_host *host;
- struct ata_port *ap;
- void __iomem *io_addr, *ctl_addr;
- int ret;
-
- /*
- * Fill in a probe structure first of all
- */
-
- pdev = platform_device_register_simple(DRV_NAME, nr_qdi_host, NULL, 0);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- ret = -ENOMEM;
- io_addr = devm_ioport_map(&pdev->dev, io, 8);
- ctl_addr = devm_ioport_map(&pdev->dev, ctl, 1);
- if (!io_addr || !ctl_addr)
- goto fail;
-
- ret = -ENOMEM;
- host = ata_host_alloc(&pdev->dev, 1);
- if (!host)
- goto fail;
- ap = host->ports[0];
-
- if (type == 6580) {
- ap->ops = &qdi6580_port_ops;
- ap->pio_mask = ATA_PIO4;
- ap->flags |= ATA_FLAG_SLAVE_POSS;
- } else {
- ap->ops = &qdi6500_port_ops;
- ap->pio_mask = ATA_PIO2; /* Actually PIO3 !IORDY is possible */
- ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY;
- }
-
- ap->ioaddr.cmd_addr = io_addr;
- ap->ioaddr.altstatus_addr = ctl_addr;
- ap->ioaddr.ctl_addr = ctl_addr;
- ata_sff_std_ports(&ap->ioaddr);
-
- ata_port_desc(ap, "cmd %lx ctl %lx", io, ctl);
-
- /*
- * Hook in a private data structure per channel
- */
- ap->private_data = &qdi_data[nr_qdi_host];
-
- qdi_data[nr_qdi_host].timing = port;
- qdi_data[nr_qdi_host].fast = fast;
- qdi_data[nr_qdi_host].platform_dev = pdev;
-
- printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io);
-
- /* activate */
- ret = ata_host_activate(host, irq, ata_sff_interrupt, 0, &qdi_sht);
- if (ret)
- goto fail;
-
- qdi_host[nr_qdi_host++] = dev_get_drvdata(&pdev->dev);
- return 0;
-
- fail:
- platform_device_unregister(pdev);
- return ret;
-}
-
-/**
- * qdi_init - attach qdi interfaces
- *
- * Attach qdi IDE interfaces by scanning the ports it may occupy.
- */
-
-static __init int qdi_init(void)
-{
- unsigned long flags;
- static const unsigned long qd_port[2] = { 0x30, 0xB0 };
- static const unsigned long ide_port[2] = { 0x170, 0x1F0 };
- static const int ide_irq[2] = { 14, 15 };
-
- int ct = 0;
- int i;
-
- if (probe_qdi == 0)
- return -ENODEV;
-
- /*
- * Check each possible QD65xx base address
- */
-
- for (i = 0; i < 2; i++) {
- unsigned long port = qd_port[i];
- u8 r, res;
-
-
- if (request_region(port, 2, "pata_qdi")) {
- /* Check for a card */
- local_irq_save(flags);
- r = inb_p(port);
- outb_p(0x19, port);
- res = inb_p(port);
- outb_p(r, port);
- local_irq_restore(flags);
-
- /* Fail */
- if (res == 0x19)
- {
- release_region(port, 2);
- continue;
- }
-
- /* Passes the presence test */
- r = inb_p(port + 1); /* Check port agrees with port set */
- if ((r & 2) >> 1 != i) {
- release_region(port, 2);
- continue;
- }
-
- /* Check card type */
- if ((r & 0xF0) == 0xC0) {
- /* QD6500: single channel */
- if (r & 8) {
- /* Disabled ? */
- release_region(port, 2);
- continue;
- }
- if (qdi_init_one(port, 6500, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0)
- ct++;
- }
- if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) {
- /* QD6580: dual channel */
- if (!request_region(port + 2 , 2, "pata_qdi"))
- {
- release_region(port, 2);
- continue;
- }
- res = inb(port + 3);
- if (res & 1) {
- /* Single channel mode */
- if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0)
- ct++;
- } else {
- /* Dual channel mode */
- if (qdi_init_one(port, 6580, 0x1F0, 14, r & 0x04) == 0)
- ct++;
- if (qdi_init_one(port + 2, 6580, 0x170, 15, r & 0x04) == 0)
- ct++;
- }
- }
- }
- }
- if (ct != 0)
- return 0;
- return -ENODEV;
-}
-
-static __exit void qdi_exit(void)
-{
- int i;
-
- for (i = 0; i < nr_qdi_host; i++) {
- ata_host_detach(qdi_host[i]);
- /* Free the control resource. The 6580 dual channel has the resources
- * claimed as a pair of 2 byte resources so we need no special cases...
- */
- release_region(qdi_data[i].timing, 2);
- platform_device_unregister(qdi_data[i].platform_dev);
- }
-}
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("low-level driver for qdi ATA");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-module_init(qdi_init);
-module_exit(qdi_exit);
-
-module_param(probe_qdi, int, 0);
-
diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c
index 4d318f86ae86..e6a2dd7809c1 100644
--- a/drivers/ata/pata_rdc.c
+++ b/drivers/ata/pata_rdc.c
@@ -86,6 +86,8 @@ static int rdc_pata_prereset(struct ata_link *link, unsigned long deadline)
return ata_sff_prereset(link, deadline);
}
+static DEFINE_SPINLOCK(rdc_lock);
+
/**
* rdc_set_piomode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
@@ -101,6 +103,7 @@ static void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
unsigned int pio = adev->pio_mode - XFER_PIO_0;
struct pci_dev *dev = to_pci_dev(ap->host->dev);
+ unsigned long flags;
unsigned int is_slave = (adev->devno != 0);
unsigned int master_port= ap->port_no ? 0x42 : 0x40;
unsigned int slave_port = 0x44;
@@ -124,6 +127,8 @@ static void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev)
if (adev->class == ATA_DEV_ATA)
control |= 4; /* PPE enable */
+ spin_lock_irqsave(&rdc_lock, flags);
+
/* PIO configuration clears DTE unconditionally. It will be
* programmed in set_dmamode which is guaranteed to be called
* after set_piomode if any DMA mode is available.
@@ -161,6 +166,8 @@ static void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev)
pci_read_config_byte(dev, 0x48, &udma_enable);
udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
pci_write_config_byte(dev, 0x48, udma_enable);
+
+ spin_unlock_irqrestore(&rdc_lock, flags);
}
/**
@@ -177,6 +184,7 @@ static void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev)
static void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
struct pci_dev *dev = to_pci_dev(ap->host->dev);
+ unsigned long flags;
u8 master_port = ap->port_no ? 0x42 : 0x40;
u16 master_data;
u8 speed = adev->dma_mode;
@@ -190,6 +198,8 @@ static void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{ 2, 1 },
{ 2, 3 }, };
+ spin_lock_irqsave(&rdc_lock, flags);
+
pci_read_config_word(dev, master_port, &master_data);
pci_read_config_byte(dev, 0x48, &udma_enable);
@@ -271,6 +281,8 @@ static void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)
pci_write_config_word(dev, master_port, master_data);
}
pci_write_config_byte(dev, 0x48, udma_enable);
+
+ spin_unlock_irqrestore(&rdc_lock, flags);
}
static struct ata_port_operations rdc_pata_ops = {
@@ -375,6 +387,10 @@ static struct pci_driver rdc_pci_driver = {
.id_table = rdc_pci_tbl,
.probe = rdc_init_one,
.remove = rdc_remove_one,
+#ifdef CONFIG_PM
+ .suspend = ata_pci_device_suspend,
+ .resume = ata_pci_device_resume,
+#endif
};
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index e2c18257adff..c0e603a84f7f 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -38,7 +38,7 @@
#include <scsi/scsi_host.h>
#include <linux/libata.h>
-#define DRV_NAME "sc1200"
+#define DRV_NAME "pata_sc1200"
#define DRV_VERSION "0.2.6"
#define SC1200_REV_A 0x00
@@ -86,10 +86,14 @@ static int sc1200_clock(void)
static void sc1200_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
static const u32 pio_timings[4][5] = {
- {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, // format0 33Mhz
- {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}, // format1, 33Mhz
- {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021}, // format1, 48Mhz
- {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131} // format1, 66Mhz
+ /* format0, 33Mhz */
+ { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 },
+ /* format1, 33Mhz */
+ { 0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010 },
+ /* format1, 48Mhz */
+ { 0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021 },
+ /* format1, 66Mhz */
+ { 0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131 }
};
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index eb748e327143..e265f835c95d 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -826,18 +826,6 @@ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
}
/**
- * scc_pata_prereset - prepare for reset
- * @ap: ATA port to be reset
- * @deadline: deadline jiffies for the operation
- */
-
-static int scc_pata_prereset(struct ata_link *link, unsigned long deadline)
-{
- link->ap->cbl = ATA_CBL_PATA80;
- return ata_sff_prereset(link, deadline);
-}
-
-/**
* scc_postreset - standard postreset callback
* @ap: the target ata_port
* @classes: classes of attached devices
@@ -946,7 +934,7 @@ static struct ata_port_operations scc_pata_ops = {
.bmdma_status = scc_bmdma_status,
.sff_data_xfer = scc_data_xfer,
- .prereset = scc_pata_prereset,
+ .cable_detect = ata_cable_80wire,
.softreset = scc_softreset,
.postreset = scc_postreset,
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 86dd714e3e1d..71eaf385e970 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -58,31 +58,15 @@ static const char *csb_bad_ata100[] = {
};
/**
- * dell_cable - Dell serverworks cable detection
+ * oem_cable - Dell/Sun serverworks cable detection
* @ap: ATA port to do cable detect
*
- * Dell hide the 40/80 pin select for their interfaces in the top two
- * bits of the subsystem ID.
+ * Dell PowerEdge and Sun Cobalt 'Alpine' hide the 40/80 pin select
+ * for their interfaces in the top two bits of the subsystem ID.
*/
-static int dell_cable(struct ata_port *ap) {
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-
- if (pdev->subsystem_device & (1 << (ap->port_no + 14)))
- return ATA_CBL_PATA80;
- return ATA_CBL_PATA40;
-}
-
-/**
- * sun_cable - Sun Cobalt 'Alpine' cable detection
- * @ap: ATA port to do cable select
- *
- * Cobalt CSB5 IDE hides the 40/80pin in the top two bits of the
- * subsystem ID the same as dell. We could use one function but we may
- * need to extend the Dell one in future
- */
-
-static int sun_cable(struct ata_port *ap) {
+static int oem_cable(struct ata_port *ap)
+{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (pdev->subsystem_device & (1 << (ap->port_no + 14)))
@@ -90,49 +74,21 @@ static int sun_cable(struct ata_port *ap) {
return ATA_CBL_PATA40;
}
-/**
- * osb4_cable - OSB4 cable detect
- * @ap: ATA port to check
- *
- * The OSB4 isn't UDMA66 capable so this is easy
- */
-
-static int osb4_cable(struct ata_port *ap) {
- return ATA_CBL_PATA40;
-}
-
-/**
- * csb_cable - CSB5/6 cable detect
- * @ap: ATA port to check
- *
- * Serverworks default arrangement is to use the drive side detection
- * only.
- */
-
-static int csb_cable(struct ata_port *ap) {
- return ATA_CBL_PATA_UNK;
-}
-
struct sv_cable_table {
int device;
int subvendor;
int (*cable_detect)(struct ata_port *ap);
};
-/*
- * Note that we don't copy the old serverworks code because the old
- * code contains obvious mistakes
- */
-
static struct sv_cable_table cable_detect[] = {
- { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, dell_cable },
- { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, dell_cable },
- { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN, sun_cable },
- { PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, osb4_cable },
- { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, csb_cable },
- { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, csb_cable },
- { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, csb_cable },
- { PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, csb_cable },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, oem_cable },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, oem_cable },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN, oem_cable },
+ { PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, ata_cable_40wire },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, ata_cable_unknown },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, ata_cable_unknown },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, ata_cable_unknown },
+ { PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, ata_cable_unknown },
{ }
};
@@ -393,6 +349,31 @@ static void serverworks_fixup_ht1000(struct pci_dev *pdev)
pci_write_config_byte(pdev, 0x5A, btr);
}
+static int serverworks_fixup(struct pci_dev *pdev)
+{
+ int rc = 0;
+
+ /* Force master latency timer to 64 PCI clocks */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
+ rc = serverworks_fixup_osb4(pdev);
+ break;
+ case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+ ata_pci_bmdma_clear_simplex(pdev);
+ /* fall through */
+ case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
+ case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
+ rc = serverworks_fixup_csb(pdev);
+ break;
+ case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
+ serverworks_fixup_ht1000(pdev);
+ break;
+ }
+
+ return rc;
+}
static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
@@ -430,13 +411,12 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
if (rc)
return rc;
- /* Force master latency timer to 64 PCI clocks */
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+ rc = serverworks_fixup(pdev);
/* OSB4 : South Bridge and IDE */
if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
/* Select non UDMA capable OSB4 if we can't do fixups */
- if ( serverworks_fixup_osb4(pdev) < 0)
+ if (rc < 0)
ppi[0] = &info[1];
}
/* setup CSB5/CSB6 : South Bridge and IDE option RAID */
@@ -446,19 +426,13 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
/* If the returned btr is the newer revision then
select the right info block */
- if (serverworks_fixup_csb(pdev) == 3)
+ if (rc == 3)
ppi[0] = &info[3];
/* Is this the 3rd channel CSB6 IDE ? */
if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)
ppi[1] = &ata_dummy_port_info;
}
- /* setup HT1000E */
- else if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
- serverworks_fixup_ht1000(pdev);
-
- if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
- ata_pci_bmdma_clear_simplex(pdev);
return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0);
}
@@ -473,24 +447,7 @@ static int serverworks_reinit_one(struct pci_dev *pdev)
if (rc)
return rc;
- /* Force master latency timer to 64 PCI clocks */
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
-
- switch (pdev->device) {
- case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
- serverworks_fixup_osb4(pdev);
- break;
- case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
- ata_pci_bmdma_clear_simplex(pdev);
- /* fall through */
- case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
- case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
- serverworks_fixup_csb(pdev);
- break;
- case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
- serverworks_fixup_ht1000(pdev);
- break;
- }
+ (void)serverworks_fixup(pdev);
ata_host_resume(host);
return 0;
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 31f759b0ab71..b92eacf8dd3c 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -38,11 +38,12 @@
/**
* sil680_selreg - return register base
- * @hwif: interface
+ * @ap: ATA interface
* @r: config offset
*
- * Turn a config register offset into the right address in either
- * PCI space or MMIO space to access the control register in question
+ * Turn a config register offset into the right address in PCI space
+ * to access the control register in question.
+ *
* Thankfully this is a configuration operation so isn't performance
* criticial.
*/
@@ -56,12 +57,12 @@ static unsigned long sil680_selreg(struct ata_port *ap, int r)
/**
* sil680_seldev - return register base
- * @hwif: interface
+ * @ap: ATA interface
* @r: config offset
*
- * Turn a config register offset into the right address in either
- * PCI space or MMIO space to access the control register in question
- * including accounting for the unit shift.
+ * Turn a config register offset into the right address in PCI space
+ * to access the control register in question including accounting for
+ * the unit shift.
*/
static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r)
@@ -81,7 +82,8 @@ static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev,
* space for us.
*/
-static int sil680_cable_detect(struct ata_port *ap) {
+static int sil680_cable_detect(struct ata_port *ap)
+{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned long addr = sil680_selreg(ap, 0);
u8 ata66;
@@ -93,7 +95,7 @@ static int sil680_cable_detect(struct ata_port *ap) {
}
/**
- * sil680_set_piomode - set initial PIO mode data
+ * sil680_set_piomode - set PIO mode data
* @ap: ATA interface
* @adev: ATA device
*
@@ -104,8 +106,12 @@ static int sil680_cable_detect(struct ata_port *ap) {
static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
- static u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 };
- static u16 speed_t[5] = { 0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1 };
+ static const u16 speed_p[5] = {
+ 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1
+ };
+ static const u16 speed_t[5] = {
+ 0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1
+ };
unsigned long tfaddr = sil680_selreg(ap, 0x02);
unsigned long addr = sil680_seldev(ap, adev, 0x04);
@@ -140,22 +146,23 @@ static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)
}
/**
- * sil680_set_dmamode - set initial DMA mode data
+ * sil680_set_dmamode - set DMA mode data
* @ap: ATA interface
* @adev: ATA device
*
- * Program the MWDMA/UDMA modes for the sil680 k
- * chipset. The MWDMA mode values are pulled from a lookup table
+ * Program the MWDMA/UDMA modes for the sil680 chipset.
+ *
+ * The MWDMA mode values are pulled from a lookup table
* while the chipset uses mode number for UDMA.
*/
static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
- static u8 ultra_table[2][7] = {
+ static const u8 ultra_table[2][7] = {
{ 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01, 0xFF }, /* 100MHz */
{ 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }, /* 133Mhz */
};
- static u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 };
+ static const u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 };
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned long ma = sil680_seldev(ap, adev, 0x08);
@@ -175,7 +182,7 @@ static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)
mode &= ~(0x03 << port_shift);
/* Extract scsc */
- scsc = (scsc & 0x30) ? 1: 0;
+ scsc = (scsc & 0x30) ? 1 : 0;
if (adev->dma_mode >= XFER_UDMA_0) {
multi = 0x10C1;
@@ -248,7 +255,7 @@ static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)
{
u8 tmpbyte = 0;
- /* FIXME: double check */
+ /* FIXME: double check */
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE,
pdev->revision ? 1 : 255);
@@ -266,22 +273,22 @@ static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)
*try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5);
#endif
- switch(tmpbyte & 0x30) {
- case 0x00:
- /* 133 clock attempt to force it on */
- pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10);
- break;
- case 0x30:
- /* if clocking is disabled */
- /* 133 clock attempt to force it on */
- pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20);
- break;
- case 0x10:
- /* 133 already */
- break;
- case 0x20:
- /* BIOS set PCI x2 clocking */
- break;
+ switch (tmpbyte & 0x30) {
+ case 0x00:
+ /* 133 clock attempt to force it on */
+ pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10);
+ break;
+ case 0x30:
+ /* if clocking is disabled */
+ /* 133 clock attempt to force it on */
+ pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20);
+ break;
+ case 0x10:
+ /* 133 already */
+ break;
+ case 0x20:
+ /* BIOS set PCI x2 clocking */
+ break;
}
pci_read_config_byte(pdev, 0x8A, &tmpbyte);
@@ -299,12 +306,19 @@ static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)
pci_write_config_dword(pdev, 0xB8, 0x43924392);
pci_write_config_dword(pdev, 0xBC, 0x40094009);
- switch(tmpbyte & 0x30) {
- case 0x00: printk(KERN_INFO "sil680: 100MHz clock.\n");break;
- case 0x10: printk(KERN_INFO "sil680: 133MHz clock.\n");break;
- case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break;
- /* This last case is _NOT_ ok */
- case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n");
+ switch (tmpbyte & 0x30) {
+ case 0x00:
+ printk(KERN_INFO "sil680: 100MHz clock.\n");
+ break;
+ case 0x10:
+ printk(KERN_INFO "sil680: 133MHz clock.\n");
+ break;
+ case 0x20:
+ printk(KERN_INFO "sil680: Using PCI clock.\n");
+ break;
+ /* This last case is _NOT_ ok */
+ case 0x30:
+ printk(KERN_ERR "sil680: Clock disabled ?\n");
}
return tmpbyte & 0x30;
}
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 533f2aefab87..b0edc7de7b2d 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -55,7 +55,7 @@ static const struct sis_laptop sis_laptop[] = {
/* devid, subvendor, subdev */
{ 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */
{ 0x5513, 0x1734, 0x105F }, /* FSC Amilo A1630 */
- { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */
+ { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */
/* end marker */
{ 0, }
};
@@ -76,7 +76,7 @@ static int sis_short_ata40(struct pci_dev *dev)
}
/**
- * sis_old_port_base - return PCI configuration base for dev
+ * sis_old_port_base - return PCI configuration base for dev
* @adev: device
*
* Returns the base of the PCI configuration registers for this port
@@ -85,11 +85,34 @@ static int sis_short_ata40(struct pci_dev *dev)
static int sis_old_port_base(struct ata_device *adev)
{
- return 0x40 + (4 * adev->link->ap->port_no) + (2 * adev->devno);
+ return 0x40 + (4 * adev->link->ap->port_no) + (2 * adev->devno);
}
/**
- * sis_133_cable_detect - check for 40/80 pin
+ * sis_port_base - return PCI configuration base for dev
+ * @adev: device
+ *
+ * Returns the base of the PCI configuration registers for this port
+ * number.
+ */
+
+static int sis_port_base(struct ata_device *adev)
+{
+ struct ata_port *ap = adev->link->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int port = 0x40;
+ u32 reg54;
+
+ /* If bit 30 is set then the registers are mapped at 0x70 not 0x40 */
+ pci_read_config_dword(pdev, 0x54, &reg54);
+ if (reg54 & 0x40000000)
+ port = 0x70;
+
+ return port + (8 * ap->port_no) + (4 * adev->devno);
+}
+
+/**
+ * sis_133_cable_detect - check for 40/80 pin
* @ap: Port
* @deadline: deadline jiffies for the operation
*
@@ -110,7 +133,7 @@ static int sis_133_cable_detect(struct ata_port *ap)
}
/**
- * sis_66_cable_detect - check for 40/80 pin
+ * sis_66_cable_detect - check for 40/80 pin
* @ap: Port
*
* Perform cable detection on the UDMA66, UDMA100 and early UDMA133
@@ -132,7 +155,7 @@ static int sis_66_cable_detect(struct ata_port *ap)
/**
- * sis_pre_reset - probe begin
+ * sis_pre_reset - probe begin
* @link: ATA link
* @deadline: deadline jiffies for the operation
*
@@ -160,7 +183,7 @@ static int sis_pre_reset(struct ata_link *link, unsigned long deadline)
/**
- * sis_set_fifo - Set RWP fifo bits for this device
+ * sis_set_fifo - Set RWP fifo bits for this device
* @ap: Port
* @adev: Device
*
@@ -203,13 +226,13 @@ static void sis_set_fifo(struct ata_port *ap, struct ata_device *adev)
static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int port = sis_old_port_base(adev);
u8 t1, t2;
int speed = adev->pio_mode - XFER_PIO_0;
- const u8 active[] = { 0x00, 0x07, 0x04, 0x03, 0x01 };
- const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 };
+ static const u8 active[] = { 0x00, 0x07, 0x04, 0x03, 0x01 };
+ static const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 };
sis_set_fifo(ap, adev);
@@ -240,11 +263,11 @@ static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev)
static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int port = sis_old_port_base(adev);
int speed = adev->pio_mode - XFER_PIO_0;
- const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
+ static const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
sis_set_fifo(ap, adev);
@@ -265,20 +288,19 @@ static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)
static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- int port = 0x40;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int port;
u32 t1;
- u32 reg54;
int speed = adev->pio_mode - XFER_PIO_0;
- const u32 timing133[] = {
+ static const u32 timing133[] = {
0x28269000, /* Recovery << 24 | Act << 16 | Ini << 12 */
0x0C266000,
0x04263000,
0x0C0A3000,
0x05093000
};
- const u32 timing100[] = {
+ static const u32 timing100[] = {
0x1E1C6000, /* Recovery << 24 | Act << 16 | Ini << 12 */
0x091C4000,
0x031C2000,
@@ -288,12 +310,7 @@ static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
sis_set_fifo(ap, adev);
- /* If bit 14 is set then the registers are mapped at 0x70 not 0x40 */
- pci_read_config_dword(pdev, 0x54, &reg54);
- if (reg54 & 0x40000000)
- port = 0x70;
- port += 8 * ap->port_no + 4 * adev->devno;
-
+ port = sis_port_base(adev);
pci_read_config_dword(pdev, port, &t1);
t1 &= 0xC0C00FFF; /* Mask out timing */
@@ -319,13 +336,13 @@ static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int speed = adev->dma_mode - XFER_MW_DMA_0;
int drive_pci = sis_old_port_base(adev);
u16 timing;
- const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
- const u16 udma_bits[] = { 0xE000, 0xC000, 0xA000 };
+ static const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
+ static const u16 udma_bits[] = { 0xE000, 0xC000, 0xA000 };
pci_read_config_word(pdev, drive_pci, &timing);
@@ -358,14 +375,14 @@ static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev)
static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int speed = adev->dma_mode - XFER_MW_DMA_0;
int drive_pci = sis_old_port_base(adev);
u16 timing;
/* MWDMA 0-2 and UDMA 0-5 */
- const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
- const u16 udma_bits[] = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 };
+ static const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
+ static const u16 udma_bits[] = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 };
pci_read_config_word(pdev, drive_pci, &timing);
@@ -397,12 +414,12 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int speed = adev->dma_mode - XFER_MW_DMA_0;
int drive_pci = sis_old_port_base(adev);
u8 timing;
- const u8 udma_bits[] = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
+ static const u8 udma_bits[] = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
pci_read_config_byte(pdev, drive_pci + 1, &timing);
@@ -431,7 +448,7 @@ static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev)
static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *adev)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int speed = adev->dma_mode - XFER_MW_DMA_0;
int drive_pci = sis_old_port_base(adev);
u8 timing;
@@ -464,32 +481,34 @@ static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *a
static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- int speed = adev->dma_mode - XFER_MW_DMA_0;
- int port = 0x40;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int port;
u32 t1;
- u32 reg54;
-
- /* bits 4- cycle time 8 - cvs time */
- static const u32 timing_u100[] = { 0x6B0, 0x470, 0x350, 0x140, 0x120, 0x110, 0x000 };
- static const u32 timing_u133[] = { 0x9F0, 0x6A0, 0x470, 0x250, 0x230, 0x220, 0x210 };
-
- /* If bit 14 is set then the registers are mapped at 0x70 not 0x40 */
- pci_read_config_dword(pdev, 0x54, &reg54);
- if (reg54 & 0x40000000)
- port = 0x70;
- port += (8 * ap->port_no) + (4 * adev->devno);
+ port = sis_port_base(adev);
pci_read_config_dword(pdev, port, &t1);
if (adev->dma_mode < XFER_UDMA_0) {
+ /* Recovery << 24 | Act << 16 | Ini << 12, like PIO modes */
+ static const u32 timing_u100[] = { 0x19154000, 0x06072000, 0x04062000 };
+ static const u32 timing_u133[] = { 0x221C6000, 0x0C0A3000, 0x05093000 };
+ int speed = adev->dma_mode - XFER_MW_DMA_0;
+
+ t1 &= 0xC0C00FFF;
+ /* disable UDMA */
t1 &= ~0x00000004;
- /* FIXME: need data sheet to add MWDMA here. Also lacking on
- ide/pci driver */
+ if (t1 & 0x08)
+ t1 |= timing_u133[speed];
+ else
+ t1 |= timing_u100[speed];
} else {
- speed = adev->dma_mode - XFER_UDMA_0;
- /* if & 8 no UDMA133 - need info for ... */
+ /* bits 4- cycle time 8 - cvs time */
+ static const u32 timing_u100[] = { 0x6B0, 0x470, 0x350, 0x140, 0x120, 0x110, 0x000 };
+ static const u32 timing_u133[] = { 0x9F0, 0x6A0, 0x470, 0x250, 0x230, 0x220, 0x210 };
+ int speed = adev->dma_mode - XFER_UDMA_0;
+
t1 &= ~0x00000FF0;
+ /* enable UDMA */
t1 |= 0x00000004;
if (t1 & 0x08)
t1 |= timing_u133[speed];
@@ -499,6 +518,27 @@ static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev)
pci_write_config_dword(pdev, port, t1);
}
+/**
+ * sis_133_mode_filter - mode selection filter
+ * @adev: ATA device
+ *
+ * Block UDMA6 on devices that do not support it.
+ */
+
+static unsigned long sis_133_mode_filter(struct ata_device *adev, unsigned long mask)
+{
+ struct ata_port *ap = adev->link->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int port = sis_port_base(adev);
+ u32 t1;
+
+ pci_read_config_dword(pdev, port, &t1);
+ /* if ATA133 is disabled, mask it out */
+ if (!(t1 & 0x08))
+ mask &= ~(0xC0 << ATA_SHIFT_UDMA);
+ return mask;
+}
+
static struct scsi_host_template sis_sht = {
ATA_BMDMA_SHT(DRV_NAME),
};
@@ -520,6 +560,7 @@ static struct ata_port_operations sis_133_ops = {
.set_piomode = sis_133_set_piomode,
.set_dmamode = sis_133_set_dmamode,
.cable_detect = sis_133_cable_detect,
+ .mode_filter = sis_133_mode_filter,
};
static struct ata_port_operations sis_133_early_ops = {
@@ -588,7 +629,7 @@ static const struct ata_port_info sis_info100_early = {
static const struct ata_port_info sis_info133 = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
- /* No MWDMA */
+ .mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &sis_133_ops,
};
@@ -669,7 +710,7 @@ static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)
* @pdev: PCI device to register
* @ent: Entry in sis_pci_tbl matching with @pdev
*
- * Called from kernel PCI layer. We probe for combined mode (sigh),
+ * Called from kernel PCI layer. We probe for combined mode (sigh),
* and then hand over control to libata, for it to do the rest.
*
* LOCKING:
@@ -769,17 +810,20 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
switch(trueid) {
case 0x5518: /* SIS 962/963 */
+ dev_info(&pdev->dev,
+ "SiS 962/963 MuTIOL IDE UDMA133 controller\n");
chipset = &sis133;
if ((idemisc & 0x40000000) == 0) {
pci_write_config_dword(pdev, 0x54, idemisc | 0x40000000);
- printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");
+ dev_info(&pdev->dev,
+ "Switching to 5513 register mapping\n");
}
break;
case 0x0180: /* SIS 965/965L */
- chipset = &sis133;
+ chipset = &sis133;
break;
case 0x1180: /* SIS 966/966L */
- chipset = &sis133;
+ chipset = &sis133;
break;
}
}
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index c06ce8ced566..24cf200dd1c9 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -1,6 +1,7 @@
/*
* pata_sl82c105.c - SL82C105 PATA for new ATA layer
* (C) 2005 Red Hat Inc
+ * (C) 2011 Bartlomiej Zolnierkiewicz
*
* Based in part on linux/drivers/ide/pci/sl82c105.c
* SL82C105/Winbond 553 IDE driver
@@ -289,6 +290,14 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
return bridge->revision;
}
+static void sl82c105_fixup(struct pci_dev *pdev)
+{
+ u32 val;
+
+ pci_read_config_dword(pdev, 0x40, &val);
+ val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
+ pci_write_config_dword(pdev, 0x40, val);
+}
static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
@@ -306,7 +315,6 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
/* for now use only the first port */
const struct ata_port_info *ppi[] = { &info_early,
NULL };
- u32 val;
int rev;
int rc;
@@ -325,13 +333,28 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
else
ppi[0] = &info_dma;
- pci_read_config_dword(dev, 0x40, &val);
- val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
- pci_write_config_dword(dev, 0x40, val);
+ sl82c105_fixup(dev);
return ata_pci_bmdma_init_one(dev, ppi, &sl82c105_sht, NULL, 0);
}
+#ifdef CONFIG_PM
+static int sl82c105_reinit_one(struct pci_dev *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ int rc;
+
+ rc = ata_pci_device_do_resume(pdev);
+ if (rc)
+ return rc;
+
+ sl82c105_fixup(pdev);
+
+ ata_host_resume(host);
+ return 0;
+}
+#endif
+
static const struct pci_device_id sl82c105[] = {
{ PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), },
@@ -342,7 +365,11 @@ static struct pci_driver sl82c105_pci_driver = {
.name = DRV_NAME,
.id_table = sl82c105,
.probe = sl82c105_init_one,
- .remove = ata_pci_remove_one
+ .remove = ata_pci_remove_one,
+#ifdef CONFIG_PM
+ .suspend = ata_pci_device_suspend,
+ .resume = sl82c105_reinit_one,
+#endif
};
static int __init sl82c105_init(void)
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 8e9f5048a10a..255f336cd7ea 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -509,6 +509,27 @@ static void via_config_fifo(struct pci_dev *pdev, unsigned int flags)
}
}
+static void via_fixup(struct pci_dev *pdev, const struct via_isa_bridge *config)
+{
+ u32 timing;
+
+ /* Initialise the FIFO for the enabled channels. */
+ via_config_fifo(pdev, config->flags);
+
+ if (config->udma_mask == ATA_UDMA4) {
+ /* The 66 MHz devices require we enable the clock */
+ pci_read_config_dword(pdev, 0x50, &timing);
+ timing |= 0x80008;
+ pci_write_config_dword(pdev, 0x50, timing);
+ }
+ if (config->flags & VIA_BAD_CLK66) {
+ /* Disable the 66MHz clock on problem devices */
+ pci_read_config_dword(pdev, 0x50, &timing);
+ timing &= ~0x80008;
+ pci_write_config_dword(pdev, 0x50, timing);
+ }
+}
+
/**
* via_init_one - discovery callback
* @pdev: PCI device
@@ -570,7 +591,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
struct pci_dev *isa;
const struct via_isa_bridge *config;
u8 enable;
- u32 timing;
unsigned long flags = id->driver_data;
int rc;
@@ -609,9 +629,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENODEV;
}
- /* Initialise the FIFO for the enabled channels. */
- via_config_fifo(pdev, config->flags);
-
/* Clock set up */
switch (config->udma_mask) {
case 0x00:
@@ -637,12 +654,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENODEV;
}
- if (config->flags & VIA_BAD_CLK66) {
- /* Disable the 66MHz clock on problem devices */
- pci_read_config_dword(pdev, 0x50, &timing);
- timing &= ~0x80008;
- pci_write_config_dword(pdev, 0x50, timing);
- }
+ via_fixup(pdev, config);
/* We have established the device type, now fire it up */
return ata_pci_bmdma_init_one(pdev, ppi, &via_sht, (void *)config, 0);
@@ -661,29 +673,14 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static int via_reinit_one(struct pci_dev *pdev)
{
- u32 timing;
struct ata_host *host = dev_get_drvdata(&pdev->dev);
- const struct via_isa_bridge *config = host->private_data;
int rc;
rc = ata_pci_device_do_resume(pdev);
if (rc)
return rc;
- via_config_fifo(pdev, config->flags);
-
- if (config->udma_mask == ATA_UDMA4) {
- /* The 66 MHz devices require we enable the clock */
- pci_read_config_dword(pdev, 0x50, &timing);
- timing |= 0x80008;
- pci_write_config_dword(pdev, 0x50, timing);
- }
- if (config->flags & VIA_BAD_CLK66) {
- /* Disable the 66MHz clock on problem devices */
- pci_read_config_dword(pdev, 0x50, &timing);
- timing &= ~0x80008;
- pci_write_config_dword(pdev, 0x50, timing);
- }
+ via_fixup(pdev, host->private_data);
ata_host_resume(host);
return 0;
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 4b6b2090784b..0b8b8b488ee8 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4087,8 +4087,11 @@ static int mv_platform_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "slots %u ports %d\n",
(unsigned)MV_MAX_Q_DEPTH, host->n_ports);
- return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt,
- IRQF_SHARED, &mv6_sht);
+ rc = ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt,
+ IRQF_SHARED, &mv6_sht);
+ if (!rc)
+ return 0;
+
err:
#if defined(CONFIG_HAVE_CLK)
if (!IS_ERR(hpriv->clk)) {
@@ -4110,8 +4113,7 @@ err:
*/
static int __devexit mv_platform_remove(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct ata_host *host = dev_get_drvdata(dev);
+ struct ata_host *host = platform_get_drvdata(pdev);
#if defined(CONFIG_HAVE_CLK)
struct mv_host_priv *hpriv = host->private_data;
#endif
@@ -4129,7 +4131,7 @@ static int __devexit mv_platform_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int mv_platform_suspend(struct platform_device *pdev, pm_message_t state)
{
- struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct ata_host *host = platform_get_drvdata(pdev);
if (host)
return ata_host_suspend(host, state);
else
@@ -4138,7 +4140,7 @@ static int mv_platform_suspend(struct platform_device *pdev, pm_message_t state)
static int mv_platform_resume(struct platform_device *pdev)
{
- struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct ata_host *host = platform_get_drvdata(pdev);
int ret;
if (host) {
@@ -4353,7 +4355,7 @@ static int mv_pci_init_one(struct pci_dev *pdev,
#ifdef CONFIG_PM
static int mv_pci_device_resume(struct pci_dev *pdev)
{
- struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct ata_host *host = pci_get_drvdata(pdev);
int rc;
rc = ata_pci_device_do_resume(pdev);
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 55470f337e51..1e9140626a83 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -268,7 +268,7 @@ union sil24_cmd_block {
struct sil24_atapi_block atapi;
};
-static struct sil24_cerr_info {
+static const struct sil24_cerr_info {
unsigned int err_mask, action;
const char *desc;
} sil24_cerr_db[] = {
@@ -1019,7 +1019,7 @@ static void sil24_error_intr(struct ata_port *ap)
/* deal with command error */
if (irq_stat & PORT_IRQ_ERROR) {
- struct sil24_cerr_info *ci = NULL;
+ const struct sil24_cerr_info *ci = NULL;
unsigned int err_mask = 0, action = 0;
u32 context, cerr;
int pmp;
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 93071417315f..956e9accb051 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -1134,8 +1134,9 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
skb_headlen(skb));
else
put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
- skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset,
- skb_shinfo(skb)->frags[i].size);
+ skb_frag_page(&skb_shinfo(skb)->frags[i]) +
+ skb_shinfo(skb)->frags[i].page_offset,
+ skb_frag_size(&skb_shinfo(skb)->frags[i]));
}
if (skb->len & 3)
put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3));
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index db06f34419cf..1c052127548c 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -3416,27 +3416,28 @@ init_card(struct atm_dev *dev)
size = sizeof(struct vc_map *) * card->tct_size;
IPRINTK("%s: allocate %d byte for VC map.\n", card->name, size);
- if (NULL == (card->vcs = vmalloc(size))) {
+ card->vcs = vzalloc(size);
+ if (!card->vcs) {
printk("%s: memory allocation failure.\n", card->name);
deinit_card(card);
return -1;
}
- memset(card->vcs, 0, size);
size = sizeof(struct vc_map *) * card->scd_size;
IPRINTK("%s: allocate %d byte for SCD to VC mapping.\n",
card->name, size);
- if (NULL == (card->scd2vc = vmalloc(size))) {
+ card->scd2vc = vzalloc(size);
+ if (!card->scd2vc) {
printk("%s: memory allocation failure.\n", card->name);
deinit_card(card);
return -1;
}
- memset(card->scd2vc, 0, size);
size = sizeof(struct tst_info) * (card->tst_size - 2);
IPRINTK("%s: allocate %d byte for TST to VC mapping.\n",
card->name, size);
- if (NULL == (card->soft_tst = vmalloc(size))) {
+ card->soft_tst = vmalloc(size);
+ if (!card->soft_tst) {
printk("%s: memory allocation failure.\n", card->name);
deinit_card(card);
return -1;
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index cb90f7a3e074..3d0c2b0fed9c 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -818,127 +818,152 @@ static void ia_hw_type(IADEV *iadev) {
}
-static void IaFrontEndIntr(IADEV *iadev) {
- volatile IA_SUNI *suni;
- volatile ia_mb25_t *mb25;
- volatile suni_pm7345_t *suni_pm7345;
-
- if(iadev->phy_type & FE_25MBIT_PHY) {
- mb25 = (ia_mb25_t*)iadev->phy;
- iadev->carrier_detect = Boolean(mb25->mb25_intr_status & MB25_IS_GSB);
- } else if (iadev->phy_type & FE_DS3_PHY) {
- suni_pm7345 = (suni_pm7345_t *)iadev->phy;
- /* clear FRMR interrupts */
- (void) suni_pm7345->suni_ds3_frm_intr_stat;
- iadev->carrier_detect =
- Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV));
- } else if (iadev->phy_type & FE_E3_PHY ) {
- suni_pm7345 = (suni_pm7345_t *)iadev->phy;
- (void) suni_pm7345->suni_e3_frm_maint_intr_ind;
- iadev->carrier_detect =
- Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat&SUNI_E3_LOS));
- }
- else {
- suni = (IA_SUNI *)iadev->phy;
- (void) suni->suni_rsop_status;
- iadev->carrier_detect = Boolean(!(suni->suni_rsop_status & SUNI_LOSV));
- }
- if (iadev->carrier_detect)
- printk("IA: SUNI carrier detected\n");
- else
- printk("IA: SUNI carrier lost signal\n");
- return;
+static u32 ia_phy_read32(struct iadev_priv *ia, unsigned int reg)
+{
+ return readl(ia->phy + (reg >> 2));
+}
+
+static void ia_phy_write32(struct iadev_priv *ia, unsigned int reg, u32 val)
+{
+ writel(val, ia->phy + (reg >> 2));
+}
+
+static void ia_frontend_intr(struct iadev_priv *iadev)
+{
+ u32 status;
+
+ if (iadev->phy_type & FE_25MBIT_PHY) {
+ status = ia_phy_read32(iadev, MB25_INTR_STATUS);
+ iadev->carrier_detect = (status & MB25_IS_GSB) ? 1 : 0;
+ } else if (iadev->phy_type & FE_DS3_PHY) {
+ ia_phy_read32(iadev, SUNI_DS3_FRM_INTR_STAT);
+ status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT);
+ iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1;
+ } else if (iadev->phy_type & FE_E3_PHY) {
+ ia_phy_read32(iadev, SUNI_E3_FRM_MAINT_INTR_IND);
+ status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT);
+ iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1;
+ } else {
+ status = ia_phy_read32(iadev, SUNI_RSOP_STATUS);
+ iadev->carrier_detect = (status & SUNI_LOSV) ? 0 : 1;
+ }
+
+ printk(KERN_INFO "IA: SUNI carrier %s\n",
+ iadev->carrier_detect ? "detected" : "lost signal");
}
-static void ia_mb25_init (IADEV *iadev)
+static void ia_mb25_init(struct iadev_priv *iadev)
{
- volatile ia_mb25_t *mb25 = (ia_mb25_t*)iadev->phy;
#if 0
mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC | MB25_MC_ENABLED;
#endif
- mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC;
- mb25->mb25_diag_control = 0;
- /*
- * Initialize carrier detect state
- */
- iadev->carrier_detect = Boolean(mb25->mb25_intr_status & MB25_IS_GSB);
- return;
-}
+ ia_phy_write32(iadev, MB25_MASTER_CTRL, MB25_MC_DRIC | MB25_MC_DREC);
+ ia_phy_write32(iadev, MB25_DIAG_CONTROL, 0);
+
+ iadev->carrier_detect =
+ (ia_phy_read32(iadev, MB25_INTR_STATUS) & MB25_IS_GSB) ? 1 : 0;
+}
-static void ia_suni_pm7345_init (IADEV *iadev)
+struct ia_reg {
+ u16 reg;
+ u16 val;
+};
+
+static void ia_phy_write(struct iadev_priv *iadev,
+ const struct ia_reg *regs, int len)
{
- volatile suni_pm7345_t *suni_pm7345 = (suni_pm7345_t *)iadev->phy;
- if (iadev->phy_type & FE_DS3_PHY)
- {
- iadev->carrier_detect =
- Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV));
- suni_pm7345->suni_ds3_frm_intr_enbl = 0x17;
- suni_pm7345->suni_ds3_frm_cfg = 1;
- suni_pm7345->suni_ds3_tran_cfg = 1;
- suni_pm7345->suni_config = 0;
- suni_pm7345->suni_splr_cfg = 0;
- suni_pm7345->suni_splt_cfg = 0;
- }
- else
- {
- iadev->carrier_detect =
- Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat & SUNI_E3_LOS));
- suni_pm7345->suni_e3_frm_fram_options = 0x4;
- suni_pm7345->suni_e3_frm_maint_options = 0x20;
- suni_pm7345->suni_e3_frm_fram_intr_enbl = 0x1d;
- suni_pm7345->suni_e3_frm_maint_intr_enbl = 0x30;
- suni_pm7345->suni_e3_tran_stat_diag_options = 0x0;
- suni_pm7345->suni_e3_tran_fram_options = 0x1;
- suni_pm7345->suni_config = SUNI_PM7345_E3ENBL;
- suni_pm7345->suni_splr_cfg = 0x41;
- suni_pm7345->suni_splt_cfg = 0x41;
- }
- /*
- * Enable RSOP loss of signal interrupt.
- */
- suni_pm7345->suni_intr_enbl = 0x28;
-
- /*
- * Clear error counters
- */
- suni_pm7345->suni_id_reset = 0;
-
- /*
- * Clear "PMCTST" in master test register.
- */
- suni_pm7345->suni_master_test = 0;
-
- suni_pm7345->suni_rxcp_ctrl = 0x2c;
- suni_pm7345->suni_rxcp_fctrl = 0x81;
-
- suni_pm7345->suni_rxcp_idle_pat_h1 =
- suni_pm7345->suni_rxcp_idle_pat_h2 =
- suni_pm7345->suni_rxcp_idle_pat_h3 = 0;
- suni_pm7345->suni_rxcp_idle_pat_h4 = 1;
-
- suni_pm7345->suni_rxcp_idle_mask_h1 = 0xff;
- suni_pm7345->suni_rxcp_idle_mask_h2 = 0xff;
- suni_pm7345->suni_rxcp_idle_mask_h3 = 0xff;
- suni_pm7345->suni_rxcp_idle_mask_h4 = 0xfe;
-
- suni_pm7345->suni_rxcp_cell_pat_h1 =
- suni_pm7345->suni_rxcp_cell_pat_h2 =
- suni_pm7345->suni_rxcp_cell_pat_h3 = 0;
- suni_pm7345->suni_rxcp_cell_pat_h4 = 1;
-
- suni_pm7345->suni_rxcp_cell_mask_h1 =
- suni_pm7345->suni_rxcp_cell_mask_h2 =
- suni_pm7345->suni_rxcp_cell_mask_h3 =
- suni_pm7345->suni_rxcp_cell_mask_h4 = 0xff;
-
- suni_pm7345->suni_txcp_ctrl = 0xa4;
- suni_pm7345->suni_txcp_intr_en_sts = 0x10;
- suni_pm7345->suni_txcp_idle_pat_h5 = 0x55;
-
- suni_pm7345->suni_config &= ~(SUNI_PM7345_LLB |
- SUNI_PM7345_CLB |
- SUNI_PM7345_DLB |
- SUNI_PM7345_PLB);
+ while (len--) {
+ ia_phy_write32(iadev, regs->reg, regs->val);
+ regs++;
+ }
+}
+
+static void ia_suni_pm7345_init_ds3(struct iadev_priv *iadev)
+{
+ static const struct ia_reg suni_ds3_init [] = {
+ { SUNI_DS3_FRM_INTR_ENBL, 0x17 },
+ { SUNI_DS3_FRM_CFG, 0x01 },
+ { SUNI_DS3_TRAN_CFG, 0x01 },
+ { SUNI_CONFIG, 0 },
+ { SUNI_SPLR_CFG, 0 },
+ { SUNI_SPLT_CFG, 0 }
+ };
+ u32 status;
+
+ status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT);
+ iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1;
+
+ ia_phy_write(iadev, suni_ds3_init, ARRAY_SIZE(suni_ds3_init));
+}
+
+static void ia_suni_pm7345_init_e3(struct iadev_priv *iadev)
+{
+ static const struct ia_reg suni_e3_init [] = {
+ { SUNI_E3_FRM_FRAM_OPTIONS, 0x04 },
+ { SUNI_E3_FRM_MAINT_OPTIONS, 0x20 },
+ { SUNI_E3_FRM_FRAM_INTR_ENBL, 0x1d },
+ { SUNI_E3_FRM_MAINT_INTR_ENBL, 0x30 },
+ { SUNI_E3_TRAN_STAT_DIAG_OPTIONS, 0 },
+ { SUNI_E3_TRAN_FRAM_OPTIONS, 0x01 },
+ { SUNI_CONFIG, SUNI_PM7345_E3ENBL },
+ { SUNI_SPLR_CFG, 0x41 },
+ { SUNI_SPLT_CFG, 0x41 }
+ };
+ u32 status;
+
+ status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT);
+ iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1;
+ ia_phy_write(iadev, suni_e3_init, ARRAY_SIZE(suni_e3_init));
+}
+
+static void ia_suni_pm7345_init(struct iadev_priv *iadev)
+{
+ static const struct ia_reg suni_init [] = {
+ /* Enable RSOP loss of signal interrupt. */
+ { SUNI_INTR_ENBL, 0x28 },
+ /* Clear error counters. */
+ { SUNI_ID_RESET, 0 },
+ /* Clear "PMCTST" in master test register. */
+ { SUNI_MASTER_TEST, 0 },
+
+ { SUNI_RXCP_CTRL, 0x2c },
+ { SUNI_RXCP_FCTRL, 0x81 },
+
+ { SUNI_RXCP_IDLE_PAT_H1, 0 },
+ { SUNI_RXCP_IDLE_PAT_H2, 0 },
+ { SUNI_RXCP_IDLE_PAT_H3, 0 },
+ { SUNI_RXCP_IDLE_PAT_H4, 0x01 },
+
+ { SUNI_RXCP_IDLE_MASK_H1, 0xff },
+ { SUNI_RXCP_IDLE_MASK_H2, 0xff },
+ { SUNI_RXCP_IDLE_MASK_H3, 0xff },
+ { SUNI_RXCP_IDLE_MASK_H4, 0xfe },
+
+ { SUNI_RXCP_CELL_PAT_H1, 0 },
+ { SUNI_RXCP_CELL_PAT_H2, 0 },
+ { SUNI_RXCP_CELL_PAT_H3, 0 },
+ { SUNI_RXCP_CELL_PAT_H4, 0x01 },
+
+ { SUNI_RXCP_CELL_MASK_H1, 0xff },
+ { SUNI_RXCP_CELL_MASK_H2, 0xff },
+ { SUNI_RXCP_CELL_MASK_H3, 0xff },
+ { SUNI_RXCP_CELL_MASK_H4, 0xff },
+
+ { SUNI_TXCP_CTRL, 0xa4 },
+ { SUNI_TXCP_INTR_EN_STS, 0x10 },
+ { SUNI_TXCP_IDLE_PAT_H5, 0x55 }
+ };
+
+ if (iadev->phy_type & FE_DS3_PHY)
+ ia_suni_pm7345_init_ds3(iadev);
+ else
+ ia_suni_pm7345_init_e3(iadev);
+
+ ia_phy_write(iadev, suni_init, ARRAY_SIZE(suni_init));
+
+ ia_phy_write32(iadev, SUNI_CONFIG, ia_phy_read32(iadev, SUNI_CONFIG) &
+ ~(SUNI_PM7345_LLB | SUNI_PM7345_CLB |
+ SUNI_PM7345_DLB | SUNI_PM7345_PLB));
#ifdef __SNMP__
suni_pm7345->suni_rxcp_intr_en_sts |= SUNI_OOCDE;
#endif /* __SNMP__ */
@@ -1425,10 +1450,10 @@ static int rx_init(struct atm_dev *dev)
iadev->dma + IPHASE5575_RX_LIST_ADDR);
IF_INIT(printk("Tx Dle list addr: 0x%p value: 0x%0x\n",
iadev->dma+IPHASE5575_TX_LIST_ADDR,
- *(u32*)(iadev->dma+IPHASE5575_TX_LIST_ADDR));
+ readl(iadev->dma + IPHASE5575_TX_LIST_ADDR));
printk("Rx Dle list addr: 0x%p value: 0x%0x\n",
iadev->dma+IPHASE5575_RX_LIST_ADDR,
- *(u32*)(iadev->dma+IPHASE5575_RX_LIST_ADDR));)
+ readl(iadev->dma + IPHASE5575_RX_LIST_ADDR));)
writew(0xffff, iadev->reass_reg+REASS_MASK_REG);
writew(0, iadev->reass_reg+MODE_REG);
@@ -2208,7 +2233,7 @@ static irqreturn_t ia_int(int irq, void *dev_id)
if (status & STAT_DLERINT)
{
/* Clear this bit by writing a 1 to it. */
- *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLERINT;
+ writel(STAT_DLERINT, iadev->reg + IPHASE5575_BUS_STATUS_REG);
rx_dle_intr(dev);
}
if (status & STAT_SEGINT)
@@ -2219,13 +2244,13 @@ static irqreturn_t ia_int(int irq, void *dev_id)
}
if (status & STAT_DLETINT)
{
- *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLETINT;
+ writel(STAT_DLETINT, iadev->reg + IPHASE5575_BUS_STATUS_REG);
tx_dle_intr(dev);
}
if (status & (STAT_FEINT | STAT_ERRINT | STAT_MARKINT))
{
if (status & STAT_FEINT)
- IaFrontEndIntr(iadev);
+ ia_frontend_intr(iadev);
}
}
return IRQ_RETVAL(handled);
@@ -2556,7 +2581,7 @@ static int __devinit ia_start(struct atm_dev *dev)
goto err_free_rx;
}
/* Get iadev->carrier_detect status */
- IaFrontEndIntr(iadev);
+ ia_frontend_intr(iadev);
}
return 0;
@@ -2827,7 +2852,7 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
case 0xb:
if (!capable(CAP_NET_ADMIN)) return -EPERM;
- IaFrontEndIntr(iadev);
+ ia_frontend_intr(iadev);
break;
case 0xa:
if (!capable(CAP_NET_ADMIN)) return -EPERM;
diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h
index 077735e0e04b..6a0955e6d4fc 100644
--- a/drivers/atm/iphase.h
+++ b/drivers/atm/iphase.h
@@ -889,79 +889,71 @@ typedef struct ia_rtn_q {
} IARTN_Q;
#define SUNI_LOSV 0x04
-typedef struct {
- u32 suni_master_reset; /* SUNI Master Reset and Identity */
- u32 suni_master_config; /* SUNI Master Configuration */
- u32 suni_master_intr_stat; /* SUNI Master Interrupt Status */
- u32 suni_reserved1; /* Reserved */
- u32 suni_master_clk_monitor;/* SUNI Master Clock Monitor */
- u32 suni_master_control; /* SUNI Master Clock Monitor */
- u32 suni_reserved2[10]; /* Reserved */
-
- u32 suni_rsop_control; /* RSOP Control/Interrupt Enable */
- u32 suni_rsop_status; /* RSOP Status/Interrupt States */
- u32 suni_rsop_section_bip8l;/* RSOP Section BIP-8 LSB */
- u32 suni_rsop_section_bip8m;/* RSOP Section BIP-8 MSB */
-
- u32 suni_tsop_control; /* TSOP Control */
- u32 suni_tsop_diag; /* TSOP Disgnostics */
- u32 suni_tsop_reserved[2]; /* TSOP Reserved */
-
- u32 suni_rlop_cs; /* RLOP Control/Status */
- u32 suni_rlop_intr; /* RLOP Interrupt Enable/Status */
- u32 suni_rlop_line_bip24l; /* RLOP Line BIP-24 LSB */
- u32 suni_rlop_line_bip24; /* RLOP Line BIP-24 */
- u32 suni_rlop_line_bip24m; /* RLOP Line BIP-24 MSB */
- u32 suni_rlop_line_febel; /* RLOP Line FEBE LSB */
- u32 suni_rlop_line_febe; /* RLOP Line FEBE */
- u32 suni_rlop_line_febem; /* RLOP Line FEBE MSB */
-
- u32 suni_tlop_control; /* TLOP Control */
- u32 suni_tlop_disg; /* TLOP Disgnostics */
- u32 suni_tlop_reserved[14]; /* TLOP Reserved */
-
- u32 suni_rpop_cs; /* RPOP Status/Control */
- u32 suni_rpop_intr; /* RPOP Interrupt/Status */
- u32 suni_rpop_reserved; /* RPOP Reserved */
- u32 suni_rpop_intr_ena; /* RPOP Interrupt Enable */
- u32 suni_rpop_reserved1[3]; /* RPOP Reserved */
- u32 suni_rpop_path_sig; /* RPOP Path Signal Label */
- u32 suni_rpop_bip8l; /* RPOP Path BIP-8 LSB */
- u32 suni_rpop_bip8m; /* RPOP Path BIP-8 MSB */
- u32 suni_rpop_febel; /* RPOP Path FEBE LSB */
- u32 suni_rpop_febem; /* RPOP Path FEBE MSB */
- u32 suni_rpop_reserved2[4]; /* RPOP Reserved */
-
- u32 suni_tpop_cntrl_daig; /* TPOP Control/Disgnostics */
- u32 suni_tpop_pointer_ctrl; /* TPOP Pointer Control */
- u32 suni_tpop_sourcer_ctrl; /* TPOP Source Control */
- u32 suni_tpop_reserved1[2]; /* TPOP Reserved */
- u32 suni_tpop_arb_prtl; /* TPOP Arbitrary Pointer LSB */
- u32 suni_tpop_arb_prtm; /* TPOP Arbitrary Pointer MSB */
- u32 suni_tpop_reserved2; /* TPOP Reserved */
- u32 suni_tpop_path_sig; /* TPOP Path Signal Lable */
- u32 suni_tpop_path_status; /* TPOP Path Status */
- u32 suni_tpop_reserved3[6]; /* TPOP Reserved */
-
- u32 suni_racp_cs; /* RACP Control/Status */
- u32 suni_racp_intr; /* RACP Interrupt Enable/Status */
- u32 suni_racp_hdr_pattern; /* RACP Match Header Pattern */
- u32 suni_racp_hdr_mask; /* RACP Match Header Mask */
- u32 suni_racp_corr_hcs; /* RACP Correctable HCS Error Count */
- u32 suni_racp_uncorr_hcs; /* RACP Uncorrectable HCS Error Count */
- u32 suni_racp_reserved[10]; /* RACP Reserved */
-
- u32 suni_tacp_control; /* TACP Control */
- u32 suni_tacp_idle_hdr_pat; /* TACP Idle Cell Header Pattern */
- u32 suni_tacp_idle_pay_pay; /* TACP Idle Cell Payld Octet Pattern */
- u32 suni_tacp_reserved[5]; /* TACP Reserved */
-
- u32 suni_reserved3[24]; /* Reserved */
-
- u32 suni_master_test; /* SUNI Master Test */
- u32 suni_reserved_test; /* SUNI Reserved for Test */
-} IA_SUNI;
-
+enum ia_suni {
+ SUNI_MASTER_RESET = 0x000, /* SUNI Master Reset and Identity */
+ SUNI_MASTER_CONFIG = 0x004, /* SUNI Master Configuration */
+ SUNI_MASTER_INTR_STAT = 0x008, /* SUNI Master Interrupt Status */
+ SUNI_RESERVED1 = 0x00c, /* Reserved */
+ SUNI_MASTER_CLK_MONITOR = 0x010, /* SUNI Master Clock Monitor */
+ SUNI_MASTER_CONTROL = 0x014, /* SUNI Master Clock Monitor */
+ /* Reserved (10) */
+ SUNI_RSOP_CONTROL = 0x040, /* RSOP Control/Interrupt Enable */
+ SUNI_RSOP_STATUS = 0x044, /* RSOP Status/Interrupt States */
+ SUNI_RSOP_SECTION_BIP8L = 0x048, /* RSOP Section BIP-8 LSB */
+ SUNI_RSOP_SECTION_BIP8M = 0x04c, /* RSOP Section BIP-8 MSB */
+
+ SUNI_TSOP_CONTROL = 0x050, /* TSOP Control */
+ SUNI_TSOP_DIAG = 0x054, /* TSOP Disgnostics */
+ /* Reserved (2) */
+ SUNI_RLOP_CS = 0x060, /* RLOP Control/Status */
+ SUNI_RLOP_INTR = 0x064, /* RLOP Interrupt Enable/Status */
+ SUNI_RLOP_LINE_BIP24L = 0x068, /* RLOP Line BIP-24 LSB */
+ SUNI_RLOP_LINE_BIP24 = 0x06c, /* RLOP Line BIP-24 */
+ SUNI_RLOP_LINE_BIP24M = 0x070, /* RLOP Line BIP-24 MSB */
+ SUNI_RLOP_LINE_FEBEL = 0x074, /* RLOP Line FEBE LSB */
+ SUNI_RLOP_LINE_FEBE = 0x078, /* RLOP Line FEBE */
+ SUNI_RLOP_LINE_FEBEM = 0x07c, /* RLOP Line FEBE MSB */
+
+ SUNI_TLOP_CONTROL = 0x080, /* TLOP Control */
+ SUNI_TLOP_DISG = 0x084, /* TLOP Disgnostics */
+ /* Reserved (14) */
+ SUNI_RPOP_CS = 0x0c0, /* RPOP Status/Control */
+ SUNI_RPOP_INTR = 0x0c4, /* RPOP Interrupt/Status */
+ SUNI_RPOP_RESERVED = 0x0c8, /* RPOP Reserved */
+ SUNI_RPOP_INTR_ENA = 0x0cc, /* RPOP Interrupt Enable */
+ /* Reserved (3) */
+ SUNI_RPOP_PATH_SIG = 0x0dc, /* RPOP Path Signal Label */
+ SUNI_RPOP_BIP8L = 0x0e0, /* RPOP Path BIP-8 LSB */
+ SUNI_RPOP_BIP8M = 0x0e4, /* RPOP Path BIP-8 MSB */
+ SUNI_RPOP_FEBEL = 0x0e8, /* RPOP Path FEBE LSB */
+ SUNI_RPOP_FEBEM = 0x0ec, /* RPOP Path FEBE MSB */
+ /* Reserved (4) */
+ SUNI_TPOP_CNTRL_DAIG = 0x100, /* TPOP Control/Disgnostics */
+ SUNI_TPOP_POINTER_CTRL = 0x104, /* TPOP Pointer Control */
+ SUNI_TPOP_SOURCER_CTRL = 0x108, /* TPOP Source Control */
+ /* Reserved (2) */
+ SUNI_TPOP_ARB_PRTL = 0x114, /* TPOP Arbitrary Pointer LSB */
+ SUNI_TPOP_ARB_PRTM = 0x118, /* TPOP Arbitrary Pointer MSB */
+ SUNI_TPOP_RESERVED2 = 0x11c, /* TPOP Reserved */
+ SUNI_TPOP_PATH_SIG = 0x120, /* TPOP Path Signal Lable */
+ SUNI_TPOP_PATH_STATUS = 0x124, /* TPOP Path Status */
+ /* Reserved (6) */
+ SUNI_RACP_CS = 0x140, /* RACP Control/Status */
+ SUNI_RACP_INTR = 0x144, /* RACP Interrupt Enable/Status */
+ SUNI_RACP_HDR_PATTERN = 0x148, /* RACP Match Header Pattern */
+ SUNI_RACP_HDR_MASK = 0x14c, /* RACP Match Header Mask */
+ SUNI_RACP_CORR_HCS = 0x150, /* RACP Correctable HCS Error Count */
+ SUNI_RACP_UNCORR_HCS = 0x154, /* RACP Uncorrectable HCS Err Count */
+ /* Reserved (10) */
+ SUNI_TACP_CONTROL = 0x180, /* TACP Control */
+ SUNI_TACP_IDLE_HDR_PAT = 0x184, /* TACP Idle Cell Header Pattern */
+ SUNI_TACP_IDLE_PAY_PAY = 0x188, /* TACP Idle Cell Payld Octet Patrn */
+ /* Reserved (5) */
+ /* Reserved (24) */
+ /* FIXME: unused but name conflicts.
+ * SUNI_MASTER_TEST = 0x200, SUNI Master Test */
+ SUNI_RESERVED_TEST = 0x204 /* SUNI Reserved for Test */
+};
typedef struct _SUNI_STATS_
{
@@ -993,13 +985,11 @@ typedef struct _SUNI_STATS_
u32 racp_uchcs_count; // uncorrectable HCS error count
} IA_SUNI_STATS;
-typedef struct iadev_t {
+typedef struct iadev_priv {
/*-----base pointers into (i)chipSAR+ address space */
- u32 __iomem *phy; /* base pointer into phy(SUNI) */
- u32 __iomem *dma; /* base pointer into DMA control
- registers */
- u32 __iomem *reg; /* base pointer to SAR registers
- - Bus Interface Control Regs */
+ u32 __iomem *phy; /* Base pointer into phy (SUNI). */
+ u32 __iomem *dma; /* Base pointer into DMA control registers. */
+ u32 __iomem *reg; /* Base pointer to SAR registers. */
u32 __iomem *seg_reg; /* base pointer to segmentation engine
internal registers */
u32 __iomem *reass_reg; /* base pointer to reassemble engine
@@ -1071,14 +1061,14 @@ typedef struct iadev_t {
#define INPH_IA_VCC(v) ((struct ia_vcc *) (v)->dev_data)
/******************* IDT77105 25MB/s PHY DEFINE *****************************/
-typedef struct {
- u_int mb25_master_ctrl; /* Master control */
- u_int mb25_intr_status; /* Interrupt status */
- u_int mb25_diag_control; /* Diagnostic control */
- u_int mb25_led_hec; /* LED driver and HEC status/control */
- u_int mb25_low_byte_counter; /* Low byte counter */
- u_int mb25_high_byte_counter; /* High byte counter */
-} ia_mb25_t;
+enum ia_mb25 {
+ MB25_MASTER_CTRL = 0x00, /* Master control */
+ MB25_INTR_STATUS = 0x04, /* Interrupt status */
+ MB25_DIAG_CONTROL = 0x08, /* Diagnostic control */
+ MB25_LED_HEC = 0x0c, /* LED driver and HEC status/control */
+ MB25_LOW_BYTE_COUNTER = 0x10,
+ MB25_HIGH_BYTE_COUNTER = 0x14
+};
/*
* Master Control
@@ -1127,122 +1117,121 @@ typedef struct {
#define FE_E3_PHY 0x0090 /* E3 */
/*********************** SUNI_PM7345 PHY DEFINE HERE *********************/
-typedef struct _suni_pm7345_t
-{
- u_int suni_config; /* SUNI Configuration */
- u_int suni_intr_enbl; /* SUNI Interrupt Enable */
- u_int suni_intr_stat; /* SUNI Interrupt Status */
- u_int suni_control; /* SUNI Control */
- u_int suni_id_reset; /* SUNI Reset and Identity */
- u_int suni_data_link_ctrl;
- u_int suni_rboc_conf_intr_enbl;
- u_int suni_rboc_stat;
- u_int suni_ds3_frm_cfg;
- u_int suni_ds3_frm_intr_enbl;
- u_int suni_ds3_frm_intr_stat;
- u_int suni_ds3_frm_stat;
- u_int suni_rfdl_cfg;
- u_int suni_rfdl_enbl_stat;
- u_int suni_rfdl_stat;
- u_int suni_rfdl_data;
- u_int suni_pmon_chng;
- u_int suni_pmon_intr_enbl_stat;
- u_int suni_reserved1[0x13-0x11];
- u_int suni_pmon_lcv_evt_cnt_lsb;
- u_int suni_pmon_lcv_evt_cnt_msb;
- u_int suni_pmon_fbe_evt_cnt_lsb;
- u_int suni_pmon_fbe_evt_cnt_msb;
- u_int suni_pmon_sez_det_cnt_lsb;
- u_int suni_pmon_sez_det_cnt_msb;
- u_int suni_pmon_pe_evt_cnt_lsb;
- u_int suni_pmon_pe_evt_cnt_msb;
- u_int suni_pmon_ppe_evt_cnt_lsb;
- u_int suni_pmon_ppe_evt_cnt_msb;
- u_int suni_pmon_febe_evt_cnt_lsb;
- u_int suni_pmon_febe_evt_cnt_msb;
- u_int suni_ds3_tran_cfg;
- u_int suni_ds3_tran_diag;
- u_int suni_reserved2[0x23-0x21];
- u_int suni_xfdl_cfg;
- u_int suni_xfdl_intr_st;
- u_int suni_xfdl_xmit_data;
- u_int suni_xboc_code;
- u_int suni_splr_cfg;
- u_int suni_splr_intr_en;
- u_int suni_splr_intr_st;
- u_int suni_splr_status;
- u_int suni_splt_cfg;
- u_int suni_splt_cntl;
- u_int suni_splt_diag_g1;
- u_int suni_splt_f1;
- u_int suni_cppm_loc_meters;
- u_int suni_cppm_chng_of_cppm_perf_meter;
- u_int suni_cppm_b1_err_cnt_lsb;
- u_int suni_cppm_b1_err_cnt_msb;
- u_int suni_cppm_framing_err_cnt_lsb;
- u_int suni_cppm_framing_err_cnt_msb;
- u_int suni_cppm_febe_cnt_lsb;
- u_int suni_cppm_febe_cnt_msb;
- u_int suni_cppm_hcs_err_cnt_lsb;
- u_int suni_cppm_hcs_err_cnt_msb;
- u_int suni_cppm_idle_un_cell_cnt_lsb;
- u_int suni_cppm_idle_un_cell_cnt_msb;
- u_int suni_cppm_rcv_cell_cnt_lsb;
- u_int suni_cppm_rcv_cell_cnt_msb;
- u_int suni_cppm_xmit_cell_cnt_lsb;
- u_int suni_cppm_xmit_cell_cnt_msb;
- u_int suni_rxcp_ctrl;
- u_int suni_rxcp_fctrl;
- u_int suni_rxcp_intr_en_sts;
- u_int suni_rxcp_idle_pat_h1;
- u_int suni_rxcp_idle_pat_h2;
- u_int suni_rxcp_idle_pat_h3;
- u_int suni_rxcp_idle_pat_h4;
- u_int suni_rxcp_idle_mask_h1;
- u_int suni_rxcp_idle_mask_h2;
- u_int suni_rxcp_idle_mask_h3;
- u_int suni_rxcp_idle_mask_h4;
- u_int suni_rxcp_cell_pat_h1;
- u_int suni_rxcp_cell_pat_h2;
- u_int suni_rxcp_cell_pat_h3;
- u_int suni_rxcp_cell_pat_h4;
- u_int suni_rxcp_cell_mask_h1;
- u_int suni_rxcp_cell_mask_h2;
- u_int suni_rxcp_cell_mask_h3;
- u_int suni_rxcp_cell_mask_h4;
- u_int suni_rxcp_hcs_cs;
- u_int suni_rxcp_lcd_cnt_threshold;
- u_int suni_reserved3[0x57-0x54];
- u_int suni_txcp_ctrl;
- u_int suni_txcp_intr_en_sts;
- u_int suni_txcp_idle_pat_h1;
- u_int suni_txcp_idle_pat_h2;
- u_int suni_txcp_idle_pat_h3;
- u_int suni_txcp_idle_pat_h4;
- u_int suni_txcp_idle_pat_h5;
- u_int suni_txcp_idle_payload;
- u_int suni_e3_frm_fram_options;
- u_int suni_e3_frm_maint_options;
- u_int suni_e3_frm_fram_intr_enbl;
- u_int suni_e3_frm_fram_intr_ind_stat;
- u_int suni_e3_frm_maint_intr_enbl;
- u_int suni_e3_frm_maint_intr_ind;
- u_int suni_e3_frm_maint_stat;
- u_int suni_reserved4;
- u_int suni_e3_tran_fram_options;
- u_int suni_e3_tran_stat_diag_options;
- u_int suni_e3_tran_bip_8_err_mask;
- u_int suni_e3_tran_maint_adapt_options;
- u_int suni_ttb_ctrl;
- u_int suni_ttb_trail_trace_id_stat;
- u_int suni_ttb_ind_addr;
- u_int suni_ttb_ind_data;
- u_int suni_ttb_exp_payload_type;
- u_int suni_ttb_payload_type_ctrl_stat;
- u_int suni_pad5[0x7f-0x71];
- u_int suni_master_test;
- u_int suni_pad6[0xff-0x80];
-}suni_pm7345_t;
+enum suni_pm7345 {
+ SUNI_CONFIG = 0x000, /* SUNI Configuration */
+ SUNI_INTR_ENBL = 0x004, /* SUNI Interrupt Enable */
+ SUNI_INTR_STAT = 0x008, /* SUNI Interrupt Status */
+ SUNI_CONTROL = 0x00c, /* SUNI Control */
+ SUNI_ID_RESET = 0x010, /* SUNI Reset and Identity */
+ SUNI_DATA_LINK_CTRL = 0x014,
+ SUNI_RBOC_CONF_INTR_ENBL = 0x018,
+ SUNI_RBOC_STAT = 0x01c,
+ SUNI_DS3_FRM_CFG = 0x020,
+ SUNI_DS3_FRM_INTR_ENBL = 0x024,
+ SUNI_DS3_FRM_INTR_STAT = 0x028,
+ SUNI_DS3_FRM_STAT = 0x02c,
+ SUNI_RFDL_CFG = 0x030,
+ SUNI_RFDL_ENBL_STAT = 0x034,
+ SUNI_RFDL_STAT = 0x038,
+ SUNI_RFDL_DATA = 0x03c,
+ SUNI_PMON_CHNG = 0x040,
+ SUNI_PMON_INTR_ENBL_STAT = 0x044,
+ /* SUNI_RESERVED1 (0x13 - 0x11) */
+ SUNI_PMON_LCV_EVT_CNT_LSB = 0x050,
+ SUNI_PMON_LCV_EVT_CNT_MSB = 0x054,
+ SUNI_PMON_FBE_EVT_CNT_LSB = 0x058,
+ SUNI_PMON_FBE_EVT_CNT_MSB = 0x05c,
+ SUNI_PMON_SEZ_DET_CNT_LSB = 0x060,
+ SUNI_PMON_SEZ_DET_CNT_MSB = 0x064,
+ SUNI_PMON_PE_EVT_CNT_LSB = 0x068,
+ SUNI_PMON_PE_EVT_CNT_MSB = 0x06c,
+ SUNI_PMON_PPE_EVT_CNT_LSB = 0x070,
+ SUNI_PMON_PPE_EVT_CNT_MSB = 0x074,
+ SUNI_PMON_FEBE_EVT_CNT_LSB = 0x078,
+ SUNI_PMON_FEBE_EVT_CNT_MSB = 0x07c,
+ SUNI_DS3_TRAN_CFG = 0x080,
+ SUNI_DS3_TRAN_DIAG = 0x084,
+ /* SUNI_RESERVED2 (0x23 - 0x21) */
+ SUNI_XFDL_CFG = 0x090,
+ SUNI_XFDL_INTR_ST = 0x094,
+ SUNI_XFDL_XMIT_DATA = 0x098,
+ SUNI_XBOC_CODE = 0x09c,
+ SUNI_SPLR_CFG = 0x0a0,
+ SUNI_SPLR_INTR_EN = 0x0a4,
+ SUNI_SPLR_INTR_ST = 0x0a8,
+ SUNI_SPLR_STATUS = 0x0ac,
+ SUNI_SPLT_CFG = 0x0b0,
+ SUNI_SPLT_CNTL = 0x0b4,
+ SUNI_SPLT_DIAG_G1 = 0x0b8,
+ SUNI_SPLT_F1 = 0x0bc,
+ SUNI_CPPM_LOC_METERS = 0x0c0,
+ SUNI_CPPM_CHG_OF_CPPM_PERF_METR = 0x0c4,
+ SUNI_CPPM_B1_ERR_CNT_LSB = 0x0c8,
+ SUNI_CPPM_B1_ERR_CNT_MSB = 0x0cc,
+ SUNI_CPPM_FRAMING_ERR_CNT_LSB = 0x0d0,
+ SUNI_CPPM_FRAMING_ERR_CNT_MSB = 0x0d4,
+ SUNI_CPPM_FEBE_CNT_LSB = 0x0d8,
+ SUNI_CPPM_FEBE_CNT_MSB = 0x0dc,
+ SUNI_CPPM_HCS_ERR_CNT_LSB = 0x0e0,
+ SUNI_CPPM_HCS_ERR_CNT_MSB = 0x0e4,
+ SUNI_CPPM_IDLE_UN_CELL_CNT_LSB = 0x0e8,
+ SUNI_CPPM_IDLE_UN_CELL_CNT_MSB = 0x0ec,
+ SUNI_CPPM_RCV_CELL_CNT_LSB = 0x0f0,
+ SUNI_CPPM_RCV_CELL_CNT_MSB = 0x0f4,
+ SUNI_CPPM_XMIT_CELL_CNT_LSB = 0x0f8,
+ SUNI_CPPM_XMIT_CELL_CNT_MSB = 0x0fc,
+ SUNI_RXCP_CTRL = 0x100,
+ SUNI_RXCP_FCTRL = 0x104,
+ SUNI_RXCP_INTR_EN_STS = 0x108,
+ SUNI_RXCP_IDLE_PAT_H1 = 0x10c,
+ SUNI_RXCP_IDLE_PAT_H2 = 0x110,
+ SUNI_RXCP_IDLE_PAT_H3 = 0x114,
+ SUNI_RXCP_IDLE_PAT_H4 = 0x118,
+ SUNI_RXCP_IDLE_MASK_H1 = 0x11c,
+ SUNI_RXCP_IDLE_MASK_H2 = 0x120,
+ SUNI_RXCP_IDLE_MASK_H3 = 0x124,
+ SUNI_RXCP_IDLE_MASK_H4 = 0x128,
+ SUNI_RXCP_CELL_PAT_H1 = 0x12c,
+ SUNI_RXCP_CELL_PAT_H2 = 0x130,
+ SUNI_RXCP_CELL_PAT_H3 = 0x134,
+ SUNI_RXCP_CELL_PAT_H4 = 0x138,
+ SUNI_RXCP_CELL_MASK_H1 = 0x13c,
+ SUNI_RXCP_CELL_MASK_H2 = 0x140,
+ SUNI_RXCP_CELL_MASK_H3 = 0x144,
+ SUNI_RXCP_CELL_MASK_H4 = 0x148,
+ SUNI_RXCP_HCS_CS = 0x14c,
+ SUNI_RXCP_LCD_CNT_THRESHOLD = 0x150,
+ /* SUNI_RESERVED3 (0x57 - 0x54) */
+ SUNI_TXCP_CTRL = 0x160,
+ SUNI_TXCP_INTR_EN_STS = 0x164,
+ SUNI_TXCP_IDLE_PAT_H1 = 0x168,
+ SUNI_TXCP_IDLE_PAT_H2 = 0x16c,
+ SUNI_TXCP_IDLE_PAT_H3 = 0x170,
+ SUNI_TXCP_IDLE_PAT_H4 = 0x174,
+ SUNI_TXCP_IDLE_PAT_H5 = 0x178,
+ SUNI_TXCP_IDLE_PAYLOAD = 0x17c,
+ SUNI_E3_FRM_FRAM_OPTIONS = 0x180,
+ SUNI_E3_FRM_MAINT_OPTIONS = 0x184,
+ SUNI_E3_FRM_FRAM_INTR_ENBL = 0x188,
+ SUNI_E3_FRM_FRAM_INTR_IND_STAT = 0x18c,
+ SUNI_E3_FRM_MAINT_INTR_ENBL = 0x190,
+ SUNI_E3_FRM_MAINT_INTR_IND = 0x194,
+ SUNI_E3_FRM_MAINT_STAT = 0x198,
+ SUNI_RESERVED4 = 0x19c,
+ SUNI_E3_TRAN_FRAM_OPTIONS = 0x1a0,
+ SUNI_E3_TRAN_STAT_DIAG_OPTIONS = 0x1a4,
+ SUNI_E3_TRAN_BIP_8_ERR_MASK = 0x1a8,
+ SUNI_E3_TRAN_MAINT_ADAPT_OPTS = 0x1ac,
+ SUNI_TTB_CTRL = 0x1b0,
+ SUNI_TTB_TRAIL_TRACE_ID_STAT = 0x1b4,
+ SUNI_TTB_IND_ADDR = 0x1b8,
+ SUNI_TTB_IND_DATA = 0x1bc,
+ SUNI_TTB_EXP_PAYLOAD_TYPE = 0x1c0,
+ SUNI_TTB_PAYLOAD_TYPE_CTRL_STAT = 0x1c4,
+ /* SUNI_PAD5 (0x7f - 0x71) */
+ SUNI_MASTER_TEST = 0x200,
+ /* SUNI_PAD6 (0xff - 0x80) */
+};
#define SUNI_PM7345_T suni_pm7345_t
#define SUNI_PM7345 0x20 /* Suni chip type */
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index e828c5487493..f5569699f31c 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -1457,10 +1457,9 @@ static int __devinit vcc_table_allocate(struct lanai_dev *lanai)
return (lanai->vccs == NULL) ? -ENOMEM : 0;
#else
int bytes = (lanai->num_vci) * sizeof(struct lanai_vcc *);
- lanai->vccs = (struct lanai_vcc **) vmalloc(bytes);
+ lanai->vccs = vzalloc(bytes);
if (unlikely(lanai->vccs == NULL))
return -ENOMEM;
- memset(lanai->vccs, 0, bytes);
return 0;
#endif
}
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 4f1df2e8fd74..b80d91cc8c3a 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -47,6 +47,18 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
return ret;
}
+static const void *class_attr_namespace(struct kobject *kobj,
+ const struct attribute *attr)
+{
+ struct class_attribute *class_attr = to_class_attr(attr);
+ struct subsys_private *cp = to_subsys_private(kobj);
+ const void *ns = NULL;
+
+ if (class_attr->namespace)
+ ns = class_attr->namespace(cp->class, class_attr);
+ return ns;
+}
+
static void class_release(struct kobject *kobj)
{
struct subsys_private *cp = to_subsys_private(kobj);
@@ -72,8 +84,9 @@ static const struct kobj_ns_type_operations *class_child_ns_type(struct kobject
}
static const struct sysfs_ops class_sysfs_ops = {
- .show = class_attr_show,
- .store = class_attr_store,
+ .show = class_attr_show,
+ .store = class_attr_store,
+ .namespace = class_attr_namespace,
};
static struct kobj_type class_ktype = {
diff --git a/drivers/base/core.c b/drivers/base/core.c
index bc8729d603a7..82c865452c70 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1764,8 +1764,8 @@ void device_shutdown(void)
#ifdef CONFIG_PRINTK
-static int __dev_printk(const char *level, const struct device *dev,
- struct va_format *vaf)
+int __dev_printk(const char *level, const struct device *dev,
+ struct va_format *vaf)
{
if (!dev)
return printk("%s(NULL device *): %pV", level, vaf);
@@ -1773,6 +1773,7 @@ static int __dev_printk(const char *level, const struct device *dev,
return printk("%s%s %s: %pV",
level, dev_driver_string(dev), dev_name(dev), vaf);
}
+EXPORT_SYMBOL(__dev_printk);
int dev_printk(const char *level, const struct device *dev,
const char *fmt, ...)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 6658da743c3a..142e3d600f14 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -147,6 +147,9 @@ probe_failed:
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev_name(dev), ret);
+ } else {
+ pr_debug("%s: probe of %s rejects match %d\n",
+ drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 2840ed4668c1..8272d92d22c0 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -224,13 +224,48 @@ int memory_isolate_notify(unsigned long val, void *v)
}
/*
+ * The probe routines leave the pages reserved, just as the bootmem code does.
+ * Make sure they're still that way.
+ */
+static bool pages_correctly_reserved(unsigned long start_pfn,
+ unsigned long nr_pages)
+{
+ int i, j;
+ struct page *page;
+ unsigned long pfn = start_pfn;
+
+ /*
+ * memmap between sections is not contiguous except with
+ * SPARSEMEM_VMEMMAP. We lookup the page once per section
+ * and assume memmap is contiguous within each section
+ */
+ for (i = 0; i < sections_per_block; i++, pfn += PAGES_PER_SECTION) {
+ if (WARN_ON_ONCE(!pfn_valid(pfn)))
+ return false;
+ page = pfn_to_page(pfn);
+
+ for (j = 0; j < PAGES_PER_SECTION; j++) {
+ if (PageReserved(page + j))
+ continue;
+
+ printk(KERN_WARNING "section number %ld page number %d "
+ "not reserved, was it already online?\n",
+ pfn_to_section_nr(pfn), j);
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
* MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
* OK to have direct references to sparsemem variables in here.
*/
static int
memory_block_action(unsigned long phys_index, unsigned long action)
{
- int i;
unsigned long start_pfn, start_paddr;
unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
struct page *first_page;
@@ -238,26 +273,13 @@ memory_block_action(unsigned long phys_index, unsigned long action)
first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
- /*
- * The probe routines leave the pages reserved, just
- * as the bootmem code does. Make sure they're still
- * that way.
- */
- if (action == MEM_ONLINE) {
- for (i = 0; i < nr_pages; i++) {
- if (PageReserved(first_page+i))
- continue;
-
- printk(KERN_WARNING "section number %ld page number %d "
- "not reserved, was it already online?\n",
- phys_index, i);
- return -EBUSY;
- }
- }
-
switch (action) {
case MEM_ONLINE:
start_pfn = page_to_pfn(first_page);
+
+ if (!pages_correctly_reserved(start_pfn, nr_pages))
+ return -EBUSY;
+
ret = online_pages(start_pfn, nr_pages);
break;
case MEM_OFFLINE:
@@ -380,9 +402,13 @@ memory_probe_store(struct class *class, struct class_attribute *attr,
u64 phys_addr;
int nid;
int i, ret;
+ unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;
phys_addr = simple_strtoull(buf, NULL, 0);
+ if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
+ return -EINVAL;
+
for (i = 0; i < sections_per_block; i++) {
nid = memory_add_physaddr_to_nid(phys_addr);
ret = add_memory(nid, phys_addr,
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 99a5272d7c2f..7a24895543e7 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -375,52 +375,64 @@ void platform_device_unregister(struct platform_device *pdev)
EXPORT_SYMBOL_GPL(platform_device_unregister);
/**
- * platform_device_register_resndata - add a platform-level device with
+ * platform_device_register_full - add a platform-level device with
* resources and platform-specific data
*
- * @parent: parent device for the device we're adding
- * @name: base name of the device we're adding
- * @id: instance id
- * @res: set of resources that needs to be allocated for the device
- * @num: number of resources
- * @data: platform specific data for this platform device
- * @size: size of platform specific data
+ * @pdevinfo: data used to create device
*
* Returns &struct platform_device pointer on success, or ERR_PTR() on error.
*/
-struct platform_device *platform_device_register_resndata(
- struct device *parent,
- const char *name, int id,
- const struct resource *res, unsigned int num,
- const void *data, size_t size)
+struct platform_device *platform_device_register_full(
+ struct platform_device_info *pdevinfo)
{
int ret = -ENOMEM;
struct platform_device *pdev;
- pdev = platform_device_alloc(name, id);
+ pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
if (!pdev)
- goto err;
-
- pdev->dev.parent = parent;
+ goto err_alloc;
+
+ pdev->dev.parent = pdevinfo->parent;
+
+ if (pdevinfo->dma_mask) {
+ /*
+ * This memory isn't freed when the device is put,
+ * I don't have a nice idea for that though. Conceptually
+ * dma_mask in struct device should not be a pointer.
+ * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
+ */
+ pdev->dev.dma_mask =
+ kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+ if (!pdev->dev.dma_mask)
+ goto err;
+
+ *pdev->dev.dma_mask = pdevinfo->dma_mask;
+ pdev->dev.coherent_dma_mask = pdevinfo->dma_mask;
+ }
- ret = platform_device_add_resources(pdev, res, num);
+ ret = platform_device_add_resources(pdev,
+ pdevinfo->res, pdevinfo->num_res);
if (ret)
goto err;
- ret = platform_device_add_data(pdev, data, size);
+ ret = platform_device_add_data(pdev,
+ pdevinfo->data, pdevinfo->size_data);
if (ret)
goto err;
ret = platform_device_add(pdev);
if (ret) {
err:
+ kfree(pdev->dev.dma_mask);
+
+err_alloc:
platform_device_put(pdev);
return ERR_PTR(ret);
}
return pdev;
}
-EXPORT_SYMBOL_GPL(platform_device_register_resndata);
+EXPORT_SYMBOL_GPL(platform_device_register_full);
static int platform_drv_probe(struct device *_dev)
{
@@ -614,7 +626,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
return rc;
add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
- (pdev->id_entry) ? pdev->id_entry->name : pdev->name);
+ pdev->name);
return 0;
}
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index 2639ae79a372..81676dd17900 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_PM) += sysfs.o generic_ops.o
+obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o
obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o
obj-$(CONFIG_PM_RUNTIME) += runtime.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o
@@ -6,4 +6,4 @@ obj-$(CONFIG_PM_OPP) += opp.o
obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o
obj-$(CONFIG_HAVE_CLK) += clock_ops.o
-ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG \ No newline at end of file
+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index b97294e2d95b..5f0f85d5c576 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -10,18 +10,13 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/pm.h>
-#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/err.h>
#ifdef CONFIG_PM
-struct pm_clk_data {
- struct list_head clock_list;
- spinlock_t lock;
-};
-
enum pce_status {
PCE_STATUS_NONE = 0,
PCE_STATUS_ACQUIRED,
@@ -36,11 +31,6 @@ struct pm_clock_entry {
enum pce_status status;
};
-static struct pm_clk_data *__to_pcd(struct device *dev)
-{
- return dev ? dev->power.subsys_data : NULL;
-}
-
/**
* pm_clk_acquire - Acquire a device clock.
* @dev: Device whose clock is to be acquired.
@@ -67,10 +57,10 @@ static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
*/
int pm_clk_add(struct device *dev, const char *con_id)
{
- struct pm_clk_data *pcd = __to_pcd(dev);
+ struct pm_subsys_data *psd = dev_to_psd(dev);
struct pm_clock_entry *ce;
- if (!pcd)
+ if (!psd)
return -EINVAL;
ce = kzalloc(sizeof(*ce), GFP_KERNEL);
@@ -91,9 +81,9 @@ int pm_clk_add(struct device *dev, const char *con_id)
pm_clk_acquire(dev, ce);
- spin_lock_irq(&pcd->lock);
- list_add_tail(&ce->node, &pcd->clock_list);
- spin_unlock_irq(&pcd->lock);
+ spin_lock_irq(&psd->lock);
+ list_add_tail(&ce->node, &psd->clock_list);
+ spin_unlock_irq(&psd->lock);
return 0;
}
@@ -114,9 +104,7 @@ static void __pm_clk_remove(struct pm_clock_entry *ce)
clk_put(ce->clk);
}
- if (ce->con_id)
- kfree(ce->con_id);
-
+ kfree(ce->con_id);
kfree(ce);
}
@@ -130,15 +118,15 @@ static void __pm_clk_remove(struct pm_clock_entry *ce)
*/
void pm_clk_remove(struct device *dev, const char *con_id)
{
- struct pm_clk_data *pcd = __to_pcd(dev);
+ struct pm_subsys_data *psd = dev_to_psd(dev);
struct pm_clock_entry *ce;
- if (!pcd)
+ if (!psd)
return;
- spin_lock_irq(&pcd->lock);
+ spin_lock_irq(&psd->lock);
- list_for_each_entry(ce, &pcd->clock_list, node) {
+ list_for_each_entry(ce, &psd->clock_list, node) {
if (!con_id && !ce->con_id)
goto remove;
else if (!con_id || !ce->con_id)
@@ -147,12 +135,12 @@ void pm_clk_remove(struct device *dev, const char *con_id)
goto remove;
}
- spin_unlock_irq(&pcd->lock);
+ spin_unlock_irq(&psd->lock);
return;
remove:
list_del(&ce->node);
- spin_unlock_irq(&pcd->lock);
+ spin_unlock_irq(&psd->lock);
__pm_clk_remove(ce);
}
@@ -161,23 +149,27 @@ void pm_clk_remove(struct device *dev, const char *con_id)
* pm_clk_init - Initialize a device's list of power management clocks.
* @dev: Device to initialize the list of PM clocks for.
*
- * Allocate a struct pm_clk_data object, initialize its lock member and
- * make the @dev's power.subsys_data field point to it.
+ * Initialize the lock and clock_list members of the device's pm_subsys_data
+ * object.
*/
-int pm_clk_init(struct device *dev)
+void pm_clk_init(struct device *dev)
{
- struct pm_clk_data *pcd;
-
- pcd = kzalloc(sizeof(*pcd), GFP_KERNEL);
- if (!pcd) {
- dev_err(dev, "Not enough memory for PM clock data.\n");
- return -ENOMEM;
- }
+ struct pm_subsys_data *psd = dev_to_psd(dev);
+ if (psd)
+ INIT_LIST_HEAD(&psd->clock_list);
+}
- INIT_LIST_HEAD(&pcd->clock_list);
- spin_lock_init(&pcd->lock);
- dev->power.subsys_data = pcd;
- return 0;
+/**
+ * pm_clk_create - Create and initialize a device's list of PM clocks.
+ * @dev: Device to create and initialize the list of PM clocks for.
+ *
+ * Allocate a struct pm_subsys_data object, initialize its lock and clock_list
+ * members and make the @dev's power.subsys_data field point to it.
+ */
+int pm_clk_create(struct device *dev)
+{
+ int ret = dev_pm_get_subsys_data(dev);
+ return ret < 0 ? ret : 0;
}
/**
@@ -185,29 +177,28 @@ int pm_clk_init(struct device *dev)
* @dev: Device to destroy the list of PM clocks for.
*
* Clear the @dev's power.subsys_data field, remove the list of clock entries
- * from the struct pm_clk_data object pointed to by it before and free
+ * from the struct pm_subsys_data object pointed to by it before and free
* that object.
*/
void pm_clk_destroy(struct device *dev)
{
- struct pm_clk_data *pcd = __to_pcd(dev);
+ struct pm_subsys_data *psd = dev_to_psd(dev);
struct pm_clock_entry *ce, *c;
struct list_head list;
- if (!pcd)
+ if (!psd)
return;
- dev->power.subsys_data = NULL;
INIT_LIST_HEAD(&list);
- spin_lock_irq(&pcd->lock);
+ spin_lock_irq(&psd->lock);
- list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node)
+ list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node)
list_move(&ce->node, &list);
- spin_unlock_irq(&pcd->lock);
+ spin_unlock_irq(&psd->lock);
- kfree(pcd);
+ dev_pm_put_subsys_data(dev);
list_for_each_entry_safe_reverse(ce, c, &list, node) {
list_del(&ce->node);
@@ -225,25 +216,25 @@ void pm_clk_destroy(struct device *dev)
*/
int pm_clk_suspend(struct device *dev)
{
- struct pm_clk_data *pcd = __to_pcd(dev);
+ struct pm_subsys_data *psd = dev_to_psd(dev);
struct pm_clock_entry *ce;
unsigned long flags;
dev_dbg(dev, "%s()\n", __func__);
- if (!pcd)
+ if (!psd)
return 0;
- spin_lock_irqsave(&pcd->lock, flags);
+ spin_lock_irqsave(&psd->lock, flags);
- list_for_each_entry_reverse(ce, &pcd->clock_list, node) {
+ list_for_each_entry_reverse(ce, &psd->clock_list, node) {
if (ce->status < PCE_STATUS_ERROR) {
clk_disable(ce->clk);
ce->status = PCE_STATUS_ACQUIRED;
}
}
- spin_unlock_irqrestore(&pcd->lock, flags);
+ spin_unlock_irqrestore(&psd->lock, flags);
return 0;
}
@@ -254,25 +245,25 @@ int pm_clk_suspend(struct device *dev)
*/
int pm_clk_resume(struct device *dev)
{
- struct pm_clk_data *pcd = __to_pcd(dev);
+ struct pm_subsys_data *psd = dev_to_psd(dev);
struct pm_clock_entry *ce;
unsigned long flags;
dev_dbg(dev, "%s()\n", __func__);
- if (!pcd)
+ if (!psd)
return 0;
- spin_lock_irqsave(&pcd->lock, flags);
+ spin_lock_irqsave(&psd->lock, flags);
- list_for_each_entry(ce, &pcd->clock_list, node) {
+ list_for_each_entry(ce, &psd->clock_list, node) {
if (ce->status < PCE_STATUS_ERROR) {
clk_enable(ce->clk);
ce->status = PCE_STATUS_ENABLED;
}
}
- spin_unlock_irqrestore(&pcd->lock, flags);
+ spin_unlock_irqrestore(&psd->lock, flags);
return 0;
}
@@ -310,7 +301,7 @@ static int pm_clk_notify(struct notifier_block *nb,
if (dev->pm_domain)
break;
- error = pm_clk_init(dev);
+ error = pm_clk_create(dev);
if (error)
break;
@@ -345,22 +336,22 @@ static int pm_clk_notify(struct notifier_block *nb,
*/
int pm_clk_suspend(struct device *dev)
{
- struct pm_clk_data *pcd = __to_pcd(dev);
+ struct pm_subsys_data *psd = dev_to_psd(dev);
struct pm_clock_entry *ce;
unsigned long flags;
dev_dbg(dev, "%s()\n", __func__);
/* If there is no driver, the clocks are already disabled. */
- if (!pcd || !dev->driver)
+ if (!psd || !dev->driver)
return 0;
- spin_lock_irqsave(&pcd->lock, flags);
+ spin_lock_irqsave(&psd->lock, flags);
- list_for_each_entry_reverse(ce, &pcd->clock_list, node)
+ list_for_each_entry_reverse(ce, &psd->clock_list, node)
clk_disable(ce->clk);
- spin_unlock_irqrestore(&pcd->lock, flags);
+ spin_unlock_irqrestore(&psd->lock, flags);
return 0;
}
@@ -371,22 +362,22 @@ int pm_clk_suspend(struct device *dev)
*/
int pm_clk_resume(struct device *dev)
{
- struct pm_clk_data *pcd = __to_pcd(dev);
+ struct pm_subsys_data *psd = dev_to_psd(dev);
struct pm_clock_entry *ce;
unsigned long flags;
dev_dbg(dev, "%s()\n", __func__);
/* If there is no driver, the clocks should remain disabled. */
- if (!pcd || !dev->driver)
+ if (!psd || !dev->driver)
return 0;
- spin_lock_irqsave(&pcd->lock, flags);
+ spin_lock_irqsave(&psd->lock, flags);
- list_for_each_entry(ce, &pcd->clock_list, node)
+ list_for_each_entry(ce, &psd->clock_list, node)
clk_enable(ce->clk);
- spin_unlock_irqrestore(&pcd->lock, flags);
+ spin_unlock_irqrestore(&psd->lock, flags);
return 0;
}
diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
new file mode 100644
index 000000000000..29820c396182
--- /dev/null
+++ b/drivers/base/power/common.c
@@ -0,0 +1,86 @@
+/*
+ * drivers/base/power/common.c - Common device power management code.
+ *
+ * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pm_clock.h>
+
+/**
+ * dev_pm_get_subsys_data - Create or refcount power.subsys_data for device.
+ * @dev: Device to handle.
+ *
+ * If power.subsys_data is NULL, point it to a new object, otherwise increment
+ * its reference counter. Return 1 if a new object has been created, otherwise
+ * return 0 or error code.
+ */
+int dev_pm_get_subsys_data(struct device *dev)
+{
+ struct pm_subsys_data *psd;
+ int ret = 0;
+
+ psd = kzalloc(sizeof(*psd), GFP_KERNEL);
+ if (!psd)
+ return -ENOMEM;
+
+ spin_lock_irq(&dev->power.lock);
+
+ if (dev->power.subsys_data) {
+ dev->power.subsys_data->refcount++;
+ } else {
+ spin_lock_init(&psd->lock);
+ psd->refcount = 1;
+ dev->power.subsys_data = psd;
+ pm_clk_init(dev);
+ psd = NULL;
+ ret = 1;
+ }
+
+ spin_unlock_irq(&dev->power.lock);
+
+ /* kfree() verifies that its argument is nonzero. */
+ kfree(psd);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_get_subsys_data);
+
+/**
+ * dev_pm_put_subsys_data - Drop reference to power.subsys_data.
+ * @dev: Device to handle.
+ *
+ * If the reference counter of power.subsys_data is zero after dropping the
+ * reference, power.subsys_data is removed. Return 1 if that happens or 0
+ * otherwise.
+ */
+int dev_pm_put_subsys_data(struct device *dev)
+{
+ struct pm_subsys_data *psd;
+ int ret = 0;
+
+ spin_lock_irq(&dev->power.lock);
+
+ psd = dev_to_psd(dev);
+ if (!psd) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (--psd->refcount == 0) {
+ dev->power.subsys_data = NULL;
+ kfree(psd);
+ ret = 1;
+ }
+
+ out:
+ spin_unlock_irq(&dev->power.lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_put_subsys_data);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 1c374579407c..6790cf7eba5a 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -29,10 +29,20 @@ static struct generic_pm_domain *dev_to_genpd(struct device *dev)
return pd_to_genpd(dev->pm_domain);
}
-static void genpd_sd_counter_dec(struct generic_pm_domain *genpd)
+static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
{
- if (!WARN_ON(genpd->sd_count == 0))
- genpd->sd_count--;
+ bool ret = false;
+
+ if (!WARN_ON(atomic_read(&genpd->sd_count) == 0))
+ ret = !!atomic_dec_and_test(&genpd->sd_count);
+
+ return ret;
+}
+
+static void genpd_sd_counter_inc(struct generic_pm_domain *genpd)
+{
+ atomic_inc(&genpd->sd_count);
+ smp_mb__after_atomic_inc();
}
static void genpd_acquire_lock(struct generic_pm_domain *genpd)
@@ -71,81 +81,119 @@ static void genpd_set_active(struct generic_pm_domain *genpd)
}
/**
- * pm_genpd_poweron - Restore power to a given PM domain and its parents.
+ * __pm_genpd_poweron - Restore power to a given PM domain and its masters.
* @genpd: PM domain to power up.
*
- * Restore power to @genpd and all of its parents so that it is possible to
+ * Restore power to @genpd and all of its masters so that it is possible to
* resume a device belonging to it.
*/
-int pm_genpd_poweron(struct generic_pm_domain *genpd)
+int __pm_genpd_poweron(struct generic_pm_domain *genpd)
+ __releases(&genpd->lock) __acquires(&genpd->lock)
{
- struct generic_pm_domain *parent = genpd->parent;
+ struct gpd_link *link;
+ DEFINE_WAIT(wait);
int ret = 0;
- start:
- if (parent) {
- genpd_acquire_lock(parent);
- mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
- } else {
+ /* If the domain's master is being waited for, we have to wait too. */
+ for (;;) {
+ prepare_to_wait(&genpd->status_wait_queue, &wait,
+ TASK_UNINTERRUPTIBLE);
+ if (genpd->status != GPD_STATE_WAIT_MASTER)
+ break;
+ mutex_unlock(&genpd->lock);
+
+ schedule();
+
mutex_lock(&genpd->lock);
}
+ finish_wait(&genpd->status_wait_queue, &wait);
if (genpd->status == GPD_STATE_ACTIVE
|| (genpd->prepared_count > 0 && genpd->suspend_power_off))
- goto out;
+ return 0;
if (genpd->status != GPD_STATE_POWER_OFF) {
genpd_set_active(genpd);
- goto out;
+ return 0;
}
- if (parent && parent->status != GPD_STATE_ACTIVE) {
+ /*
+ * The list is guaranteed not to change while the loop below is being
+ * executed, unless one of the masters' .power_on() callbacks fiddles
+ * with it.
+ */
+ list_for_each_entry(link, &genpd->slave_links, slave_node) {
+ genpd_sd_counter_inc(link->master);
+ genpd->status = GPD_STATE_WAIT_MASTER;
+
mutex_unlock(&genpd->lock);
- genpd_release_lock(parent);
- ret = pm_genpd_poweron(parent);
- if (ret)
- return ret;
+ ret = pm_genpd_poweron(link->master);
- goto start;
+ mutex_lock(&genpd->lock);
+
+ /*
+ * The "wait for parent" status is guaranteed not to change
+ * while the master is powering on.
+ */
+ genpd->status = GPD_STATE_POWER_OFF;
+ wake_up_all(&genpd->status_wait_queue);
+ if (ret) {
+ genpd_sd_counter_dec(link->master);
+ goto err;
+ }
}
if (genpd->power_on) {
ret = genpd->power_on(genpd);
if (ret)
- goto out;
+ goto err;
}
genpd_set_active(genpd);
- if (parent)
- parent->sd_count++;
- out:
- mutex_unlock(&genpd->lock);
- if (parent)
- genpd_release_lock(parent);
+ return 0;
+
+ err:
+ list_for_each_entry_continue_reverse(link, &genpd->slave_links, slave_node)
+ genpd_sd_counter_dec(link->master);
return ret;
}
+/**
+ * pm_genpd_poweron - Restore power to a given PM domain and its masters.
+ * @genpd: PM domain to power up.
+ */
+int pm_genpd_poweron(struct generic_pm_domain *genpd)
+{
+ int ret;
+
+ mutex_lock(&genpd->lock);
+ ret = __pm_genpd_poweron(genpd);
+ mutex_unlock(&genpd->lock);
+ return ret;
+}
+
#endif /* CONFIG_PM */
#ifdef CONFIG_PM_RUNTIME
/**
* __pm_genpd_save_device - Save the pre-suspend state of a device.
- * @dle: Device list entry of the device to save the state of.
+ * @pdd: Domain data of the device to save the state of.
* @genpd: PM domain the device belongs to.
*/
-static int __pm_genpd_save_device(struct dev_list_entry *dle,
+static int __pm_genpd_save_device(struct pm_domain_data *pdd,
struct generic_pm_domain *genpd)
__releases(&genpd->lock) __acquires(&genpd->lock)
{
- struct device *dev = dle->dev;
+ struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
+ struct device *dev = pdd->dev;
struct device_driver *drv = dev->driver;
int ret = 0;
- if (dle->need_restore)
+ if (gpd_data->need_restore)
return 0;
mutex_unlock(&genpd->lock);
@@ -163,24 +211,25 @@ static int __pm_genpd_save_device(struct dev_list_entry *dle,
mutex_lock(&genpd->lock);
if (!ret)
- dle->need_restore = true;
+ gpd_data->need_restore = true;
return ret;
}
/**
* __pm_genpd_restore_device - Restore the pre-suspend state of a device.
- * @dle: Device list entry of the device to restore the state of.
+ * @pdd: Domain data of the device to restore the state of.
* @genpd: PM domain the device belongs to.
*/
-static void __pm_genpd_restore_device(struct dev_list_entry *dle,
+static void __pm_genpd_restore_device(struct pm_domain_data *pdd,
struct generic_pm_domain *genpd)
__releases(&genpd->lock) __acquires(&genpd->lock)
{
- struct device *dev = dle->dev;
+ struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
+ struct device *dev = pdd->dev;
struct device_driver *drv = dev->driver;
- if (!dle->need_restore)
+ if (!gpd_data->need_restore)
return;
mutex_unlock(&genpd->lock);
@@ -197,7 +246,7 @@ static void __pm_genpd_restore_device(struct dev_list_entry *dle,
mutex_lock(&genpd->lock);
- dle->need_restore = false;
+ gpd_data->need_restore = false;
}
/**
@@ -211,7 +260,8 @@ static void __pm_genpd_restore_device(struct dev_list_entry *dle,
*/
static bool genpd_abort_poweroff(struct generic_pm_domain *genpd)
{
- return genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
+ return genpd->status == GPD_STATE_WAIT_MASTER
+ || genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
}
/**
@@ -238,8 +288,8 @@ void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
__releases(&genpd->lock) __acquires(&genpd->lock)
{
- struct generic_pm_domain *parent;
- struct dev_list_entry *dle;
+ struct pm_domain_data *pdd;
+ struct gpd_link *link;
unsigned int not_suspended;
int ret = 0;
@@ -247,19 +297,22 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
/*
* Do not try to power off the domain in the following situations:
* (1) The domain is already in the "power off" state.
- * (2) System suspend is in progress.
+ * (2) The domain is waiting for its master to power up.
* (3) One of the domain's devices is being resumed right now.
+ * (4) System suspend is in progress.
*/
- if (genpd->status == GPD_STATE_POWER_OFF || genpd->prepared_count > 0
- || genpd->resume_count > 0)
+ if (genpd->status == GPD_STATE_POWER_OFF
+ || genpd->status == GPD_STATE_WAIT_MASTER
+ || genpd->resume_count > 0 || genpd->prepared_count > 0)
return 0;
- if (genpd->sd_count > 0)
+ if (atomic_read(&genpd->sd_count) > 0)
return -EBUSY;
not_suspended = 0;
- list_for_each_entry(dle, &genpd->dev_list, node)
- if (dle->dev->driver && !pm_runtime_suspended(dle->dev))
+ list_for_each_entry(pdd, &genpd->dev_list, list_node)
+ if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
+ || pdd->dev->power.irq_safe))
not_suspended++;
if (not_suspended > genpd->in_progress)
@@ -282,54 +335,50 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
genpd->status = GPD_STATE_BUSY;
genpd->poweroff_task = current;
- list_for_each_entry_reverse(dle, &genpd->dev_list, node) {
- ret = __pm_genpd_save_device(dle, genpd);
+ list_for_each_entry_reverse(pdd, &genpd->dev_list, list_node) {
+ ret = atomic_read(&genpd->sd_count) == 0 ?
+ __pm_genpd_save_device(pdd, genpd) : -EBUSY;
+
+ if (genpd_abort_poweroff(genpd))
+ goto out;
+
if (ret) {
genpd_set_active(genpd);
goto out;
}
- if (genpd_abort_poweroff(genpd))
- goto out;
-
if (genpd->status == GPD_STATE_REPEAT) {
genpd->poweroff_task = NULL;
goto start;
}
}
- parent = genpd->parent;
- if (parent) {
- mutex_unlock(&genpd->lock);
-
- genpd_acquire_lock(parent);
- mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
-
- if (genpd_abort_poweroff(genpd)) {
- genpd_release_lock(parent);
+ if (genpd->power_off) {
+ if (atomic_read(&genpd->sd_count) > 0) {
+ ret = -EBUSY;
goto out;
}
- }
- if (genpd->power_off) {
+ /*
+ * If sd_count > 0 at this point, one of the subdomains hasn't
+ * managed to call pm_genpd_poweron() for the master yet after
+ * incrementing it. In that case pm_genpd_poweron() will wait
+ * for us to drop the lock, so we can call .power_off() and let
+ * the pm_genpd_poweron() restore power for us (this shouldn't
+ * happen very often).
+ */
ret = genpd->power_off(genpd);
if (ret == -EBUSY) {
genpd_set_active(genpd);
- if (parent)
- genpd_release_lock(parent);
-
goto out;
}
}
genpd->status = GPD_STATE_POWER_OFF;
- if (parent) {
- genpd_sd_counter_dec(parent);
- if (parent->sd_count == 0)
- genpd_queue_power_off_work(parent);
-
- genpd_release_lock(parent);
+ list_for_each_entry(link, &genpd->slave_links, slave_node) {
+ genpd_sd_counter_dec(link->master);
+ genpd_queue_power_off_work(link->master);
}
out:
@@ -371,12 +420,21 @@ static int pm_genpd_runtime_suspend(struct device *dev)
if (IS_ERR(genpd))
return -EINVAL;
+ might_sleep_if(!genpd->dev_irq_safe);
+
if (genpd->stop_device) {
int ret = genpd->stop_device(dev);
if (ret)
return ret;
}
+ /*
+ * If power.irq_safe is set, this routine will be run with interrupts
+ * off, so it can't use mutexes.
+ */
+ if (dev->power.irq_safe)
+ return 0;
+
mutex_lock(&genpd->lock);
genpd->in_progress++;
pm_genpd_poweroff(genpd);
@@ -387,24 +445,6 @@ static int pm_genpd_runtime_suspend(struct device *dev)
}
/**
- * __pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
- * @dev: Device to resume.
- * @genpd: PM domain the device belongs to.
- */
-static void __pm_genpd_runtime_resume(struct device *dev,
- struct generic_pm_domain *genpd)
-{
- struct dev_list_entry *dle;
-
- list_for_each_entry(dle, &genpd->dev_list, node) {
- if (dle->dev == dev) {
- __pm_genpd_restore_device(dle, genpd);
- break;
- }
- }
-}
-
-/**
* pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
* @dev: Device to resume.
*
@@ -424,11 +464,18 @@ static int pm_genpd_runtime_resume(struct device *dev)
if (IS_ERR(genpd))
return -EINVAL;
- ret = pm_genpd_poweron(genpd);
- if (ret)
- return ret;
+ might_sleep_if(!genpd->dev_irq_safe);
+
+ /* If power.irq_safe, the PM domain is never powered off. */
+ if (dev->power.irq_safe)
+ goto out;
mutex_lock(&genpd->lock);
+ ret = __pm_genpd_poweron(genpd);
+ if (ret) {
+ mutex_unlock(&genpd->lock);
+ return ret;
+ }
genpd->status = GPD_STATE_BUSY;
genpd->resume_count++;
for (;;) {
@@ -448,12 +495,13 @@ static int pm_genpd_runtime_resume(struct device *dev)
mutex_lock(&genpd->lock);
}
finish_wait(&genpd->status_wait_queue, &wait);
- __pm_genpd_runtime_resume(dev, genpd);
+ __pm_genpd_restore_device(dev->power.subsys_data->domain_data, genpd);
genpd->resume_count--;
genpd_set_active(genpd);
wake_up_all(&genpd->status_wait_queue);
mutex_unlock(&genpd->lock);
+ out:
if (genpd->start_device)
genpd->start_device(dev);
@@ -478,8 +526,6 @@ void pm_genpd_poweroff_unused(void)
#else
static inline void genpd_power_off_work_fn(struct work_struct *work) {}
-static inline void __pm_genpd_runtime_resume(struct device *dev,
- struct generic_pm_domain *genpd) {}
#define pm_genpd_runtime_suspend NULL
#define pm_genpd_runtime_resume NULL
@@ -489,11 +535,11 @@ static inline void __pm_genpd_runtime_resume(struct device *dev,
#ifdef CONFIG_PM_SLEEP
/**
- * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its parents.
+ * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its masters.
* @genpd: PM domain to power off, if possible.
*
* Check if the given PM domain can be powered off (during system suspend or
- * hibernation) and do that if so. Also, in that case propagate to its parent.
+ * hibernation) and do that if so. Also, in that case propagate to its masters.
*
* This function is only called in "noirq" stages of system power transitions,
* so it need not acquire locks (all of the "noirq" callbacks are executed
@@ -501,21 +547,23 @@ static inline void __pm_genpd_runtime_resume(struct device *dev,
*/
static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
{
- struct generic_pm_domain *parent = genpd->parent;
+ struct gpd_link *link;
if (genpd->status == GPD_STATE_POWER_OFF)
return;
- if (genpd->suspended_count != genpd->device_count || genpd->sd_count > 0)
+ if (genpd->suspended_count != genpd->device_count
+ || atomic_read(&genpd->sd_count) > 0)
return;
if (genpd->power_off)
genpd->power_off(genpd);
genpd->status = GPD_STATE_POWER_OFF;
- if (parent) {
- genpd_sd_counter_dec(parent);
- pm_genpd_sync_poweroff(parent);
+
+ list_for_each_entry(link, &genpd->slave_links, slave_node) {
+ genpd_sd_counter_dec(link->master);
+ pm_genpd_sync_poweroff(link->master);
}
}
@@ -666,7 +714,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
if (ret)
return ret;
- if (device_may_wakeup(dev)
+ if (dev->power.wakeup_path
&& genpd->active_wakeup && genpd->active_wakeup(dev))
return 0;
@@ -890,7 +938,7 @@ static int pm_genpd_dev_poweroff_noirq(struct device *dev)
if (ret)
return ret;
- if (device_may_wakeup(dev)
+ if (dev->power.wakeup_path
&& genpd->active_wakeup && genpd->active_wakeup(dev))
return 0;
@@ -1034,7 +1082,8 @@ static void pm_genpd_complete(struct device *dev)
*/
int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
{
- struct dev_list_entry *dle;
+ struct generic_pm_domain_data *gpd_data;
+ struct pm_domain_data *pdd;
int ret = 0;
dev_dbg(dev, "%s()\n", __func__);
@@ -1054,26 +1103,26 @@ int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
goto out;
}
- list_for_each_entry(dle, &genpd->dev_list, node)
- if (dle->dev == dev) {
+ list_for_each_entry(pdd, &genpd->dev_list, list_node)
+ if (pdd->dev == dev) {
ret = -EINVAL;
goto out;
}
- dle = kzalloc(sizeof(*dle), GFP_KERNEL);
- if (!dle) {
+ gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
+ if (!gpd_data) {
ret = -ENOMEM;
goto out;
}
- dle->dev = dev;
- dle->need_restore = false;
- list_add_tail(&dle->node, &genpd->dev_list);
genpd->device_count++;
- spin_lock_irq(&dev->power.lock);
dev->pm_domain = &genpd->domain;
- spin_unlock_irq(&dev->power.lock);
+ dev_pm_get_subsys_data(dev);
+ dev->power.subsys_data->domain_data = &gpd_data->base;
+ gpd_data->base.dev = dev;
+ gpd_data->need_restore = false;
+ list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
out:
genpd_release_lock(genpd);
@@ -1089,7 +1138,7 @@ int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
int pm_genpd_remove_device(struct generic_pm_domain *genpd,
struct device *dev)
{
- struct dev_list_entry *dle;
+ struct pm_domain_data *pdd;
int ret = -EINVAL;
dev_dbg(dev, "%s()\n", __func__);
@@ -1104,17 +1153,17 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
goto out;
}
- list_for_each_entry(dle, &genpd->dev_list, node) {
- if (dle->dev != dev)
+ list_for_each_entry(pdd, &genpd->dev_list, list_node) {
+ if (pdd->dev != dev)
continue;
- spin_lock_irq(&dev->power.lock);
+ list_del_init(&pdd->list_node);
+ pdd->dev = NULL;
+ dev_pm_put_subsys_data(dev);
dev->pm_domain = NULL;
- spin_unlock_irq(&dev->power.lock);
+ kfree(to_gpd_data(pdd));
genpd->device_count--;
- list_del(&dle->node);
- kfree(dle);
ret = 0;
break;
@@ -1129,48 +1178,55 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
/**
* pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
* @genpd: Master PM domain to add the subdomain to.
- * @new_subdomain: Subdomain to be added.
+ * @subdomain: Subdomain to be added.
*/
int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
- struct generic_pm_domain *new_subdomain)
+ struct generic_pm_domain *subdomain)
{
- struct generic_pm_domain *subdomain;
+ struct gpd_link *link;
int ret = 0;
- if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(new_subdomain))
+ if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
return -EINVAL;
start:
genpd_acquire_lock(genpd);
- mutex_lock_nested(&new_subdomain->lock, SINGLE_DEPTH_NESTING);
+ mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
- if (new_subdomain->status != GPD_STATE_POWER_OFF
- && new_subdomain->status != GPD_STATE_ACTIVE) {
- mutex_unlock(&new_subdomain->lock);
+ if (subdomain->status != GPD_STATE_POWER_OFF
+ && subdomain->status != GPD_STATE_ACTIVE) {
+ mutex_unlock(&subdomain->lock);
genpd_release_lock(genpd);
goto start;
}
if (genpd->status == GPD_STATE_POWER_OFF
- && new_subdomain->status != GPD_STATE_POWER_OFF) {
+ && subdomain->status != GPD_STATE_POWER_OFF) {
ret = -EINVAL;
goto out;
}
- list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
- if (subdomain == new_subdomain) {
+ list_for_each_entry(link, &genpd->slave_links, slave_node) {
+ if (link->slave == subdomain && link->master == genpd) {
ret = -EINVAL;
goto out;
}
}
- list_add_tail(&new_subdomain->sd_node, &genpd->sd_list);
- new_subdomain->parent = genpd;
+ link = kzalloc(sizeof(*link), GFP_KERNEL);
+ if (!link) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ link->master = genpd;
+ list_add_tail(&link->master_node, &genpd->master_links);
+ link->slave = subdomain;
+ list_add_tail(&link->slave_node, &subdomain->slave_links);
if (subdomain->status != GPD_STATE_POWER_OFF)
- genpd->sd_count++;
+ genpd_sd_counter_inc(genpd);
out:
- mutex_unlock(&new_subdomain->lock);
+ mutex_unlock(&subdomain->lock);
genpd_release_lock(genpd);
return ret;
@@ -1179,22 +1235,22 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
/**
* pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
* @genpd: Master PM domain to remove the subdomain from.
- * @target: Subdomain to be removed.
+ * @subdomain: Subdomain to be removed.
*/
int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
- struct generic_pm_domain *target)
+ struct generic_pm_domain *subdomain)
{
- struct generic_pm_domain *subdomain;
+ struct gpd_link *link;
int ret = -EINVAL;
- if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(target))
+ if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
return -EINVAL;
start:
genpd_acquire_lock(genpd);
- list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
- if (subdomain != target)
+ list_for_each_entry(link, &genpd->master_links, master_node) {
+ if (link->slave != subdomain)
continue;
mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
@@ -1206,8 +1262,9 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
goto start;
}
- list_del(&subdomain->sd_node);
- subdomain->parent = NULL;
+ list_del(&link->master_node);
+ list_del(&link->slave_node);
+ kfree(link);
if (subdomain->status != GPD_STATE_POWER_OFF)
genpd_sd_counter_dec(genpd);
@@ -1234,15 +1291,14 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
if (IS_ERR_OR_NULL(genpd))
return;
- INIT_LIST_HEAD(&genpd->sd_node);
- genpd->parent = NULL;
+ INIT_LIST_HEAD(&genpd->master_links);
+ INIT_LIST_HEAD(&genpd->slave_links);
INIT_LIST_HEAD(&genpd->dev_list);
- INIT_LIST_HEAD(&genpd->sd_list);
mutex_init(&genpd->lock);
genpd->gov = gov;
INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
genpd->in_progress = 0;
- genpd->sd_count = 0;
+ atomic_set(&genpd->sd_count, 0);
genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
init_waitqueue_head(&genpd->status_wait_queue);
genpd->poweroff_task = NULL;
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index a85459126bc6..59f8ab235486 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -46,6 +46,7 @@ LIST_HEAD(dpm_prepared_list);
LIST_HEAD(dpm_suspended_list);
LIST_HEAD(dpm_noirq_list);
+struct suspend_stats suspend_stats;
static DEFINE_MUTEX(dpm_list_mtx);
static pm_message_t pm_transition;
@@ -65,6 +66,7 @@ void device_pm_init(struct device *dev)
spin_lock_init(&dev->power.lock);
pm_runtime_init(dev);
INIT_LIST_HEAD(&dev->power.entry);
+ dev->power.power_state = PMSG_INVALID;
}
/**
@@ -96,6 +98,7 @@ void device_pm_add(struct device *dev)
dev_warn(dev, "parent %s should not be sleeping\n",
dev_name(dev->parent));
list_add_tail(&dev->power.entry, &dpm_list);
+ dev_pm_qos_constraints_init(dev);
mutex_unlock(&dpm_list_mtx);
}
@@ -109,6 +112,7 @@ void device_pm_remove(struct device *dev)
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
complete_all(&dev->power.completion);
mutex_lock(&dpm_list_mtx);
+ dev_pm_qos_constraints_destroy(dev);
list_del_init(&dev->power.entry);
mutex_unlock(&dpm_list_mtx);
device_wakeup_disable(dev);
@@ -464,8 +468,12 @@ void dpm_resume_noirq(pm_message_t state)
mutex_unlock(&dpm_list_mtx);
error = device_resume_noirq(dev, state);
- if (error)
+ if (error) {
+ suspend_stats.failed_resume_noirq++;
+ dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
+ dpm_save_failed_dev(dev_name(dev));
pm_dev_err(dev, state, " early", error);
+ }
mutex_lock(&dpm_list_mtx);
put_device(dev);
@@ -626,8 +634,12 @@ void dpm_resume(pm_message_t state)
mutex_unlock(&dpm_list_mtx);
error = device_resume(dev, state, false);
- if (error)
+ if (error) {
+ suspend_stats.failed_resume++;
+ dpm_save_failed_step(SUSPEND_RESUME);
+ dpm_save_failed_dev(dev_name(dev));
pm_dev_err(dev, state, "", error);
+ }
mutex_lock(&dpm_list_mtx);
}
@@ -802,6 +814,9 @@ int dpm_suspend_noirq(pm_message_t state)
mutex_lock(&dpm_list_mtx);
if (error) {
pm_dev_err(dev, state, " late", error);
+ suspend_stats.failed_suspend_noirq++;
+ dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
+ dpm_save_failed_dev(dev_name(dev));
put_device(dev);
break;
}
@@ -902,7 +917,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
}
End:
- dev->power.is_suspended = !error;
+ if (!error) {
+ dev->power.is_suspended = true;
+ if (dev->power.wakeup_path && dev->parent)
+ dev->parent->power.wakeup_path = true;
+ }
device_unlock(dev);
complete_all(&dev->power.completion);
@@ -923,8 +942,10 @@ static void async_suspend(void *data, async_cookie_t cookie)
int error;
error = __device_suspend(dev, pm_transition, true);
- if (error)
+ if (error) {
+ dpm_save_failed_dev(dev_name(dev));
pm_dev_err(dev, pm_transition, " async", error);
+ }
put_device(dev);
}
@@ -967,6 +988,7 @@ int dpm_suspend(pm_message_t state)
mutex_lock(&dpm_list_mtx);
if (error) {
pm_dev_err(dev, state, "", error);
+ dpm_save_failed_dev(dev_name(dev));
put_device(dev);
break;
}
@@ -980,7 +1002,10 @@ int dpm_suspend(pm_message_t state)
async_synchronize_full();
if (!error)
error = async_error;
- if (!error)
+ if (error) {
+ suspend_stats.failed_suspend++;
+ dpm_save_failed_step(SUSPEND_SUSPEND);
+ } else
dpm_show_time(starttime, state, NULL);
return error;
}
@@ -999,6 +1024,8 @@ static int device_prepare(struct device *dev, pm_message_t state)
device_lock(dev);
+ dev->power.wakeup_path = device_may_wakeup(dev);
+
if (dev->pm_domain) {
pm_dev_dbg(dev, state, "preparing power domain ");
if (dev->pm_domain->ops.prepare)
@@ -1088,7 +1115,10 @@ int dpm_suspend_start(pm_message_t state)
int error;
error = dpm_prepare(state);
- if (!error)
+ if (error) {
+ suspend_stats.failed_prepare++;
+ dpm_save_failed_step(SUSPEND_PREPARE);
+ } else
error = dpm_suspend(state);
return error;
}
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index b23de185cb04..434a6c011675 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -73,6 +73,7 @@ struct opp {
* RCU usage: nodes are not modified in the list of device_opp,
* however addition is possible and is secured by dev_opp_list_lock
* @dev: device pointer
+ * @head: notifier head to notify the OPP availability changes.
* @opp_list: list of opps
*
* This is an internal data structure maintaining the link to opps attached to
@@ -83,6 +84,7 @@ struct device_opp {
struct list_head node;
struct device *dev;
+ struct srcu_notifier_head head;
struct list_head opp_list;
};
@@ -404,6 +406,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
}
dev_opp->dev = dev;
+ srcu_init_notifier_head(&dev_opp->head);
INIT_LIST_HEAD(&dev_opp->opp_list);
/* Secure the device list modification */
@@ -428,6 +431,11 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
list_add_rcu(&new_opp->node, head);
mutex_unlock(&dev_opp_list_lock);
+ /*
+ * Notify the changes in the availability of the operable
+ * frequency/voltage list.
+ */
+ srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp);
return 0;
}
@@ -504,6 +512,14 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
mutex_unlock(&dev_opp_list_lock);
synchronize_rcu();
+ /* Notify the change of the OPP availability */
+ if (availability_req)
+ srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ENABLE,
+ new_opp);
+ else
+ srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE,
+ new_opp);
+
/* clean up old opp */
new_opp = opp;
goto out;
@@ -643,3 +659,17 @@ void opp_free_cpufreq_table(struct device *dev,
*table = NULL;
}
#endif /* CONFIG_CPU_FREQ */
+
+/**
+ * opp_get_notifier() - find notifier_head of the device with opp
+ * @dev: device pointer used to lookup device OPPs.
+ */
+struct srcu_notifier_head *opp_get_notifier(struct device *dev)
+{
+ struct device_opp *dev_opp = find_device_opp(dev);
+
+ if (IS_ERR(dev_opp))
+ return ERR_PTR(PTR_ERR(dev_opp)); /* matching type */
+
+ return &dev_opp->head;
+}
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index f2a25f18fde7..9bf62323aaf3 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -1,3 +1,5 @@
+#include <linux/pm_qos.h>
+
#ifdef CONFIG_PM_RUNTIME
extern void pm_runtime_init(struct device *dev);
@@ -35,15 +37,21 @@ extern void device_pm_move_last(struct device *);
static inline void device_pm_init(struct device *dev)
{
spin_lock_init(&dev->power.lock);
+ dev->power.power_state = PMSG_INVALID;
pm_runtime_init(dev);
}
+static inline void device_pm_add(struct device *dev)
+{
+ dev_pm_qos_constraints_init(dev);
+}
+
static inline void device_pm_remove(struct device *dev)
{
+ dev_pm_qos_constraints_destroy(dev);
pm_runtime_remove(dev);
}
-static inline void device_pm_add(struct device *dev) {}
static inline void device_pm_move_before(struct device *deva,
struct device *devb) {}
static inline void device_pm_move_after(struct device *deva,
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
new file mode 100644
index 000000000000..91e061417382
--- /dev/null
+++ b/drivers/base/power/qos.c
@@ -0,0 +1,419 @@
+/*
+ * Devices PM QoS constraints management
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * This module exposes the interface to kernel space for specifying
+ * per-device PM QoS dependencies. It provides infrastructure for registration
+ * of:
+ *
+ * Dependents on a QoS value : register requests
+ * Watchers of QoS value : get notified when target QoS value changes
+ *
+ * This QoS design is best effort based. Dependents register their QoS needs.
+ * Watchers register to keep track of the current QoS needs of the system.
+ * Watchers can register different types of notification callbacks:
+ * . a per-device notification callback using the dev_pm_qos_*_notifier API.
+ * The notification chain data is stored in the per-device constraint
+ * data struct.
+ * . a system-wide notification callback using the dev_pm_qos_*_global_notifier
+ * API. The notification chain data is stored in a static variable.
+ *
+ * Note about the per-device constraint data struct allocation:
+ * . The per-device constraints data struct ptr is tored into the device
+ * dev_pm_info.
+ * . To minimize the data usage by the per-device constraints, the data struct
+ * is only allocated at the first call to dev_pm_qos_add_request.
+ * . The data is later free'd when the device is removed from the system.
+ * . A global mutex protects the constraints users from the data being
+ * allocated and free'd.
+ */
+
+#include <linux/pm_qos.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+
+static DEFINE_MUTEX(dev_pm_qos_mtx);
+
+static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
+
+/**
+ * dev_pm_qos_read_value - Get PM QoS constraint for a given device.
+ * @dev: Device to get the PM QoS constraint value for.
+ */
+s32 dev_pm_qos_read_value(struct device *dev)
+{
+ struct pm_qos_constraints *c;
+ unsigned long flags;
+ s32 ret = 0;
+
+ spin_lock_irqsave(&dev->power.lock, flags);
+
+ c = dev->power.constraints;
+ if (c)
+ ret = pm_qos_read_value(c);
+
+ spin_unlock_irqrestore(&dev->power.lock, flags);
+
+ return ret;
+}
+
+/*
+ * apply_constraint
+ * @req: constraint request to apply
+ * @action: action to perform add/update/remove, of type enum pm_qos_req_action
+ * @value: defines the qos request
+ *
+ * Internal function to update the constraints list using the PM QoS core
+ * code and if needed call the per-device and the global notification
+ * callbacks
+ */
+static int apply_constraint(struct dev_pm_qos_request *req,
+ enum pm_qos_req_action action, int value)
+{
+ int ret, curr_value;
+
+ ret = pm_qos_update_target(req->dev->power.constraints,
+ &req->node, action, value);
+
+ if (ret) {
+ /* Call the global callbacks if needed */
+ curr_value = pm_qos_read_value(req->dev->power.constraints);
+ blocking_notifier_call_chain(&dev_pm_notifiers,
+ (unsigned long)curr_value,
+ req);
+ }
+
+ return ret;
+}
+
+/*
+ * dev_pm_qos_constraints_allocate
+ * @dev: device to allocate data for
+ *
+ * Called at the first call to add_request, for constraint data allocation
+ * Must be called with the dev_pm_qos_mtx mutex held
+ */
+static int dev_pm_qos_constraints_allocate(struct device *dev)
+{
+ struct pm_qos_constraints *c;
+ struct blocking_notifier_head *n;
+
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return -ENOMEM;
+
+ n = kzalloc(sizeof(*n), GFP_KERNEL);
+ if (!n) {
+ kfree(c);
+ return -ENOMEM;
+ }
+ BLOCKING_INIT_NOTIFIER_HEAD(n);
+
+ plist_head_init(&c->list);
+ c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+ c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+ c->type = PM_QOS_MIN;
+ c->notifiers = n;
+
+ spin_lock_irq(&dev->power.lock);
+ dev->power.constraints = c;
+ spin_unlock_irq(&dev->power.lock);
+
+ return 0;
+}
+
+/**
+ * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer.
+ * @dev: target device
+ *
+ * Called from the device PM subsystem during device insertion under
+ * device_pm_lock().
+ */
+void dev_pm_qos_constraints_init(struct device *dev)
+{
+ mutex_lock(&dev_pm_qos_mtx);
+ dev->power.constraints = NULL;
+ dev->power.power_state = PMSG_ON;
+ mutex_unlock(&dev_pm_qos_mtx);
+}
+
+/**
+ * dev_pm_qos_constraints_destroy
+ * @dev: target device
+ *
+ * Called from the device PM subsystem on device removal under device_pm_lock().
+ */
+void dev_pm_qos_constraints_destroy(struct device *dev)
+{
+ struct dev_pm_qos_request *req, *tmp;
+ struct pm_qos_constraints *c;
+
+ mutex_lock(&dev_pm_qos_mtx);
+
+ dev->power.power_state = PMSG_INVALID;
+ c = dev->power.constraints;
+ if (!c)
+ goto out;
+
+ /* Flush the constraints list for the device */
+ plist_for_each_entry_safe(req, tmp, &c->list, node) {
+ /*
+ * Update constraints list and call the notification
+ * callbacks if needed
+ */
+ apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+ memset(req, 0, sizeof(*req));
+ }
+
+ spin_lock_irq(&dev->power.lock);
+ dev->power.constraints = NULL;
+ spin_unlock_irq(&dev->power.lock);
+
+ kfree(c->notifiers);
+ kfree(c);
+
+ out:
+ mutex_unlock(&dev_pm_qos_mtx);
+}
+
+/**
+ * dev_pm_qos_add_request - inserts new qos request into the list
+ * @dev: target device for the constraint
+ * @req: pointer to a preallocated handle
+ * @value: defines the qos request
+ *
+ * This function inserts a new entry in the device constraints list of
+ * requested qos performance characteristics. It recomputes the aggregate
+ * QoS expectations of parameters and initializes the dev_pm_qos_request
+ * handle. Caller needs to save this handle for later use in updates and
+ * removal.
+ *
+ * Returns 1 if the aggregated constraint value has changed,
+ * 0 if the aggregated constraint value has not changed,
+ * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
+ * to allocate for data structures, -ENODEV if the device has just been removed
+ * from the system.
+ */
+int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
+ s32 value)
+{
+ int ret = 0;
+
+ if (!dev || !req) /*guard against callers passing in null */
+ return -EINVAL;
+
+ if (dev_pm_qos_request_active(req)) {
+ WARN(1, KERN_ERR "dev_pm_qos_add_request() called for already "
+ "added request\n");
+ return -EINVAL;
+ }
+
+ req->dev = dev;
+
+ mutex_lock(&dev_pm_qos_mtx);
+
+ if (!dev->power.constraints) {
+ if (dev->power.power_state.event == PM_EVENT_INVALID) {
+ /* The device has been removed from the system. */
+ req->dev = NULL;
+ ret = -ENODEV;
+ goto out;
+ } else {
+ /*
+ * Allocate the constraints data on the first call to
+ * add_request, i.e. only if the data is not already
+ * allocated and if the device has not been removed.
+ */
+ ret = dev_pm_qos_constraints_allocate(dev);
+ }
+ }
+
+ if (!ret)
+ ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
+
+ out:
+ mutex_unlock(&dev_pm_qos_mtx);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
+
+/**
+ * dev_pm_qos_update_request - modifies an existing qos request
+ * @req : handle to list element holding a dev_pm_qos request to use
+ * @new_value: defines the qos request
+ *
+ * Updates an existing dev PM qos request along with updating the
+ * target value.
+ *
+ * Attempts are made to make this code callable on hot code paths.
+ *
+ * Returns 1 if the aggregated constraint value has changed,
+ * 0 if the aggregated constraint value has not changed,
+ * -EINVAL in case of wrong parameters, -ENODEV if the device has been
+ * removed from the system
+ */
+int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
+ s32 new_value)
+{
+ int ret = 0;
+
+ if (!req) /*guard against callers passing in null */
+ return -EINVAL;
+
+ if (!dev_pm_qos_request_active(req)) {
+ WARN(1, KERN_ERR "dev_pm_qos_update_request() called for "
+ "unknown object\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev_pm_qos_mtx);
+
+ if (req->dev->power.constraints) {
+ if (new_value != req->node.prio)
+ ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
+ new_value);
+ } else {
+ /* Return if the device has been removed */
+ ret = -ENODEV;
+ }
+
+ mutex_unlock(&dev_pm_qos_mtx);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
+
+/**
+ * dev_pm_qos_remove_request - modifies an existing qos request
+ * @req: handle to request list element
+ *
+ * Will remove pm qos request from the list of constraints and
+ * recompute the current target value. Call this on slow code paths.
+ *
+ * Returns 1 if the aggregated constraint value has changed,
+ * 0 if the aggregated constraint value has not changed,
+ * -EINVAL in case of wrong parameters, -ENODEV if the device has been
+ * removed from the system
+ */
+int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
+{
+ int ret = 0;
+
+ if (!req) /*guard against callers passing in null */
+ return -EINVAL;
+
+ if (!dev_pm_qos_request_active(req)) {
+ WARN(1, KERN_ERR "dev_pm_qos_remove_request() called for "
+ "unknown object\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev_pm_qos_mtx);
+
+ if (req->dev->power.constraints) {
+ ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
+ PM_QOS_DEFAULT_VALUE);
+ memset(req, 0, sizeof(*req));
+ } else {
+ /* Return if the device has been removed */
+ ret = -ENODEV;
+ }
+
+ mutex_unlock(&dev_pm_qos_mtx);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
+
+/**
+ * dev_pm_qos_add_notifier - sets notification entry for changes to target value
+ * of per-device PM QoS constraints
+ *
+ * @dev: target device for the constraint
+ * @notifier: notifier block managed by caller.
+ *
+ * Will register the notifier into a notification chain that gets called
+ * upon changes to the target value for the device.
+ */
+int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
+{
+ int retval = 0;
+
+ mutex_lock(&dev_pm_qos_mtx);
+
+ /* Silently return if the constraints object is not present. */
+ if (dev->power.constraints)
+ retval = blocking_notifier_chain_register(
+ dev->power.constraints->notifiers,
+ notifier);
+
+ mutex_unlock(&dev_pm_qos_mtx);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);
+
+/**
+ * dev_pm_qos_remove_notifier - deletes notification for changes to target value
+ * of per-device PM QoS constraints
+ *
+ * @dev: target device for the constraint
+ * @notifier: notifier block to be removed.
+ *
+ * Will remove the notifier from the notification chain that gets called
+ * upon changes to the target value.
+ */
+int dev_pm_qos_remove_notifier(struct device *dev,
+ struct notifier_block *notifier)
+{
+ int retval = 0;
+
+ mutex_lock(&dev_pm_qos_mtx);
+
+ /* Silently return if the constraints object is not present. */
+ if (dev->power.constraints)
+ retval = blocking_notifier_chain_unregister(
+ dev->power.constraints->notifiers,
+ notifier);
+
+ mutex_unlock(&dev_pm_qos_mtx);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
+
+/**
+ * dev_pm_qos_add_global_notifier - sets notification entry for changes to
+ * target value of the PM QoS constraints for any device
+ *
+ * @notifier: notifier block managed by caller.
+ *
+ * Will register the notifier into a notification chain that gets called
+ * upon changes to the target value for any device.
+ */
+int dev_pm_qos_add_global_notifier(struct notifier_block *notifier)
+{
+ return blocking_notifier_chain_register(&dev_pm_notifiers, notifier);
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier);
+
+/**
+ * dev_pm_qos_remove_global_notifier - deletes notification for changes to
+ * target value of PM QoS constraints for any device
+ *
+ * @notifier: notifier block to be removed.
+ *
+ * Will remove the notifier from the notification chain that gets called
+ * upon changes to the target value for any device.
+ */
+int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier)
+{
+ return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier);
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index acb3f83b8079..6bb3aafa85ed 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -9,6 +9,7 @@
#include <linux/sched.h>
#include <linux/pm_runtime.h>
+#include <trace/events/rpm.h>
#include "power.h"
static int rpm_resume(struct device *dev, int rpmflags);
@@ -155,6 +156,31 @@ static int rpm_check_suspend_allowed(struct device *dev)
}
/**
+ * __rpm_callback - Run a given runtime PM callback for a given device.
+ * @cb: Runtime PM callback to run.
+ * @dev: Device to run the callback for.
+ */
+static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
+ __releases(&dev->power.lock) __acquires(&dev->power.lock)
+{
+ int retval;
+
+ if (dev->power.irq_safe)
+ spin_unlock(&dev->power.lock);
+ else
+ spin_unlock_irq(&dev->power.lock);
+
+ retval = cb(dev);
+
+ if (dev->power.irq_safe)
+ spin_lock(&dev->power.lock);
+ else
+ spin_lock_irq(&dev->power.lock);
+
+ return retval;
+}
+
+/**
* rpm_idle - Notify device bus type if the device can be suspended.
* @dev: Device to notify the bus type about.
* @rpmflags: Flag bits.
@@ -171,6 +197,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
int (*callback)(struct device *);
int retval;
+ trace_rpm_idle(dev, rpmflags);
retval = rpm_check_suspend_allowed(dev);
if (retval < 0)
; /* Conditions are wrong. */
@@ -225,24 +252,14 @@ static int rpm_idle(struct device *dev, int rpmflags)
else
callback = NULL;
- if (callback) {
- if (dev->power.irq_safe)
- spin_unlock(&dev->power.lock);
- else
- spin_unlock_irq(&dev->power.lock);
-
- callback(dev);
-
- if (dev->power.irq_safe)
- spin_lock(&dev->power.lock);
- else
- spin_lock_irq(&dev->power.lock);
- }
+ if (callback)
+ __rpm_callback(callback, dev);
dev->power.idle_notification = false;
wake_up_all(&dev->power.wait_queue);
out:
+ trace_rpm_return_int(dev, _THIS_IP_, retval);
return retval;
}
@@ -252,22 +269,14 @@ static int rpm_idle(struct device *dev, int rpmflags)
* @dev: Device to run the callback for.
*/
static int rpm_callback(int (*cb)(struct device *), struct device *dev)
- __releases(&dev->power.lock) __acquires(&dev->power.lock)
{
int retval;
if (!cb)
return -ENOSYS;
- if (dev->power.irq_safe) {
- retval = cb(dev);
- } else {
- spin_unlock_irq(&dev->power.lock);
-
- retval = cb(dev);
+ retval = __rpm_callback(cb, dev);
- spin_lock_irq(&dev->power.lock);
- }
dev->power.runtime_error = retval;
return retval != -EACCES ? retval : -EIO;
}
@@ -277,14 +286,16 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev)
* @dev: Device to suspend.
* @rpmflags: Flag bits.
*
- * Check if the device's runtime PM status allows it to be suspended. If
- * another suspend has been started earlier, either return immediately or wait
- * for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC flags. Cancel a
- * pending idle notification. If the RPM_ASYNC flag is set then queue a
- * suspend request; otherwise run the ->runtime_suspend() callback directly.
- * If a deferred resume was requested while the callback was running then carry
- * it out; otherwise send an idle notification for the device (if the suspend
- * failed) or for its parent (if the suspend succeeded).
+ * Check if the device's runtime PM status allows it to be suspended.
+ * Cancel a pending idle notification, autosuspend or suspend. If
+ * another suspend has been started earlier, either return immediately
+ * or wait for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC
+ * flags. If the RPM_ASYNC flag is set then queue a suspend request;
+ * otherwise run the ->runtime_suspend() callback directly. When
+ * ->runtime_suspend succeeded, if a deferred resume was requested while
+ * the callback was running then carry it out, otherwise send an idle
+ * notification for its parent (if the suspend succeeded and both
+ * ignore_children of parent->power and irq_safe of dev->power are not set).
*
* This function must be called under dev->power.lock with interrupts disabled.
*/
@@ -295,7 +306,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
struct device *parent = NULL;
int retval;
- dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+ trace_rpm_suspend(dev, rpmflags);
repeat:
retval = rpm_check_suspend_allowed(dev);
@@ -347,6 +358,15 @@ static int rpm_suspend(struct device *dev, int rpmflags)
goto out;
}
+ if (dev->power.irq_safe) {
+ spin_unlock(&dev->power.lock);
+
+ cpu_relax();
+
+ spin_lock(&dev->power.lock);
+ goto repeat;
+ }
+
/* Wait for the other suspend running in parallel with us. */
for (;;) {
prepare_to_wait(&dev->power.wait_queue, &wait,
@@ -400,15 +420,16 @@ static int rpm_suspend(struct device *dev, int rpmflags)
dev->power.runtime_error = 0;
else
pm_runtime_cancel_pending(dev);
- } else {
+ wake_up_all(&dev->power.wait_queue);
+ goto out;
+ }
no_callback:
- __update_runtime_status(dev, RPM_SUSPENDED);
- pm_runtime_deactivate_timer(dev);
+ __update_runtime_status(dev, RPM_SUSPENDED);
+ pm_runtime_deactivate_timer(dev);
- if (dev->parent) {
- parent = dev->parent;
- atomic_add_unless(&parent->power.child_count, -1, 0);
- }
+ if (dev->parent) {
+ parent = dev->parent;
+ atomic_add_unless(&parent->power.child_count, -1, 0);
}
wake_up_all(&dev->power.wait_queue);
@@ -430,7 +451,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
}
out:
- dev_dbg(dev, "%s returns %d\n", __func__, retval);
+ trace_rpm_return_int(dev, _THIS_IP_, retval);
return retval;
}
@@ -459,7 +480,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
struct device *parent = NULL;
int retval = 0;
- dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+ trace_rpm_resume(dev, rpmflags);
repeat:
if (dev->power.runtime_error)
@@ -496,6 +517,15 @@ static int rpm_resume(struct device *dev, int rpmflags)
goto out;
}
+ if (dev->power.irq_safe) {
+ spin_unlock(&dev->power.lock);
+
+ cpu_relax();
+
+ spin_lock(&dev->power.lock);
+ goto repeat;
+ }
+
/* Wait for the operation carried out in parallel with us. */
for (;;) {
prepare_to_wait(&dev->power.wait_queue, &wait,
@@ -615,7 +645,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
spin_lock_irq(&dev->power.lock);
}
- dev_dbg(dev, "%s returns %d\n", __func__, retval);
+ trace_rpm_return_int(dev, _THIS_IP_, retval);
return retval;
}
@@ -732,13 +762,16 @@ EXPORT_SYMBOL_GPL(pm_schedule_suspend);
* return immediately if it is larger than zero. Then carry out an idle
* notification, either synchronous or asynchronous.
*
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
*/
int __pm_runtime_idle(struct device *dev, int rpmflags)
{
unsigned long flags;
int retval;
+ might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
if (rpmflags & RPM_GET_PUT) {
if (!atomic_dec_and_test(&dev->power.usage_count))
return 0;
@@ -761,13 +794,16 @@ EXPORT_SYMBOL_GPL(__pm_runtime_idle);
* return immediately if it is larger than zero. Then carry out a suspend,
* either synchronous or asynchronous.
*
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
*/
int __pm_runtime_suspend(struct device *dev, int rpmflags)
{
unsigned long flags;
int retval;
+ might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
if (rpmflags & RPM_GET_PUT) {
if (!atomic_dec_and_test(&dev->power.usage_count))
return 0;
@@ -789,13 +825,16 @@ EXPORT_SYMBOL_GPL(__pm_runtime_suspend);
* If the RPM_GET_PUT flag is set, increment the device's usage count. Then
* carry out a resume, either synchronous or asynchronous.
*
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
*/
int __pm_runtime_resume(struct device *dev, int rpmflags)
{
unsigned long flags;
int retval;
+ might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
if (rpmflags & RPM_GET_PUT)
atomic_inc(&dev->power.usage_count);
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 84f7c7d5a098..14ee07e9cc43 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -276,7 +276,9 @@ EXPORT_SYMBOL_GPL(device_set_wakeup_capable);
*
* By default, most devices should leave wakeup disabled. The exceptions are
* devices that everyone expects to be wakeup sources: keyboards, power buttons,
- * possibly network interfaces, etc.
+ * possibly network interfaces, etc. Also, devices that don't generate their
+ * own wakeup requests but merely forward requests from one bus to another
+ * (like PCI bridges) should have wakeup enabled by default.
*/
int device_init_wakeup(struct device *dev, bool enable)
{
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index fabbf6cc5367..2fc6a66f39a4 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -4,6 +4,8 @@
config REGMAP
default y if (REGMAP_I2C || REGMAP_SPI)
+ select LZO_COMPRESS
+ select LZO_DECOMPRESS
bool
config REGMAP_I2C
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index f476f4571295..0573c8a9dacb 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -1,3 +1,4 @@
-obj-$(CONFIG_REGMAP) += regmap.o
+obj-$(CONFIG_REGMAP) += regmap.o regcache.o regcache-indexed.o regcache-rbtree.o regcache-lzo.o
+obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
new file mode 100644
index 000000000000..348ff02eb93e
--- /dev/null
+++ b/drivers/base/regmap/internal.h
@@ -0,0 +1,128 @@
+/*
+ * Register map access API internal header
+ *
+ * Copyright 2011 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 _REGMAP_INTERNAL_H
+#define _REGMAP_INTERNAL_H
+
+#include <linux/regmap.h>
+#include <linux/fs.h>
+
+struct regmap;
+struct regcache_ops;
+
+struct regmap_format {
+ size_t buf_size;
+ size_t reg_bytes;
+ size_t val_bytes;
+ void (*format_write)(struct regmap *map,
+ unsigned int reg, unsigned int val);
+ void (*format_reg)(void *buf, unsigned int reg);
+ void (*format_val)(void *buf, unsigned int val);
+ unsigned int (*parse_val)(void *buf);
+};
+
+struct regmap {
+ struct mutex lock;
+
+ struct device *dev; /* Device we do I/O on */
+ void *work_buf; /* Scratch buffer used to format I/O */
+ struct regmap_format format; /* Buffer format */
+ const struct regmap_bus *bus;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs;
+#endif
+
+ unsigned int max_register;
+ bool (*writeable_reg)(struct device *dev, unsigned int reg);
+ bool (*readable_reg)(struct device *dev, unsigned int reg);
+ bool (*volatile_reg)(struct device *dev, unsigned int reg);
+ bool (*precious_reg)(struct device *dev, unsigned int reg);
+
+ u8 read_flag_mask;
+ u8 write_flag_mask;
+
+ /* regcache specific members */
+ const struct regcache_ops *cache_ops;
+ enum regcache_type cache_type;
+
+ /* number of bytes in reg_defaults_raw */
+ unsigned int cache_size_raw;
+ /* number of bytes per word in reg_defaults_raw */
+ unsigned int cache_word_size;
+ /* number of entries in reg_defaults */
+ unsigned int num_reg_defaults;
+ /* number of entries in reg_defaults_raw */
+ unsigned int num_reg_defaults_raw;
+
+ /* if set, only the cache is modified not the HW */
+ unsigned int cache_only:1;
+ /* if set, only the HW is modified not the cache */
+ unsigned int cache_bypass:1;
+ /* if set, remember to free reg_defaults_raw */
+ unsigned int cache_free:1;
+
+ struct reg_default *reg_defaults;
+ const void *reg_defaults_raw;
+ void *cache;
+};
+
+struct regcache_ops {
+ const char *name;
+ enum regcache_type type;
+ int (*init)(struct regmap *map);
+ int (*exit)(struct regmap *map);
+ int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
+ int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
+ int (*sync)(struct regmap *map);
+};
+
+bool regmap_writeable(struct regmap *map, unsigned int reg);
+bool regmap_readable(struct regmap *map, unsigned int reg);
+bool regmap_volatile(struct regmap *map, unsigned int reg);
+bool regmap_precious(struct regmap *map, unsigned int reg);
+
+int _regmap_write(struct regmap *map, unsigned int reg,
+ unsigned int val);
+
+#ifdef CONFIG_DEBUG_FS
+extern void regmap_debugfs_initcall(void);
+extern void regmap_debugfs_init(struct regmap *map);
+extern void regmap_debugfs_exit(struct regmap *map);
+#else
+static inline void regmap_debugfs_initcall(void) { }
+static inline void regmap_debugfs_init(struct regmap *map) { }
+static inline void regmap_debugfs_exit(struct regmap *map) { }
+#endif
+
+/* regcache core declarations */
+int regcache_init(struct regmap *map);
+void regcache_exit(struct regmap *map);
+int regcache_read(struct regmap *map,
+ unsigned int reg, unsigned int *value);
+int regcache_write(struct regmap *map,
+ unsigned int reg, unsigned int value);
+int regcache_sync(struct regmap *map);
+
+unsigned int regcache_get_val(const void *base, unsigned int idx,
+ unsigned int word_size);
+bool regcache_set_val(void *base, unsigned int idx,
+ unsigned int val, unsigned int word_size);
+int regcache_lookup_reg(struct regmap *map, unsigned int reg);
+int regcache_insert_reg(struct regmap *map, unsigned int reg,
+ unsigned int val);
+
+extern struct regcache_ops regcache_indexed_ops;
+extern struct regcache_ops regcache_rbtree_ops;
+extern struct regcache_ops regcache_lzo_ops;
+
+#endif
diff --git a/drivers/base/regmap/regcache-indexed.c b/drivers/base/regmap/regcache-indexed.c
new file mode 100644
index 000000000000..507731ad8ec1
--- /dev/null
+++ b/drivers/base/regmap/regcache-indexed.c
@@ -0,0 +1,64 @@
+/*
+ * Register cache access API - indexed caching support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@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/slab.h>
+
+#include "internal.h"
+
+static int regcache_indexed_read(struct regmap *map, unsigned int reg,
+ unsigned int *value)
+{
+ int ret;
+
+ ret = regcache_lookup_reg(map, reg);
+ if (ret >= 0)
+ *value = map->reg_defaults[ret].def;
+
+ return ret;
+}
+
+static int regcache_indexed_write(struct regmap *map, unsigned int reg,
+ unsigned int value)
+{
+ int ret;
+
+ ret = regcache_lookup_reg(map, reg);
+ if (ret < 0)
+ return regcache_insert_reg(map, reg, value);
+ map->reg_defaults[ret].def = value;
+ return 0;
+}
+
+static int regcache_indexed_sync(struct regmap *map)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < map->num_reg_defaults; i++) {
+ ret = _regmap_write(map, map->reg_defaults[i].reg,
+ map->reg_defaults[i].def);
+ if (ret < 0)
+ return ret;
+ dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+ map->reg_defaults[i].reg,
+ map->reg_defaults[i].def);
+ }
+ return 0;
+}
+
+struct regcache_ops regcache_indexed_ops = {
+ .type = REGCACHE_INDEXED,
+ .name = "indexed",
+ .read = regcache_indexed_read,
+ .write = regcache_indexed_write,
+ .sync = regcache_indexed_sync
+};
diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c
new file mode 100644
index 000000000000..066aeece3626
--- /dev/null
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -0,0 +1,361 @@
+/*
+ * Register cache access API - LZO caching support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@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/slab.h>
+#include <linux/lzo.h>
+
+#include "internal.h"
+
+struct regcache_lzo_ctx {
+ void *wmem;
+ void *dst;
+ const void *src;
+ size_t src_len;
+ size_t dst_len;
+ size_t decompressed_size;
+ unsigned long *sync_bmp;
+ int sync_bmp_nbits;
+};
+
+#define LZO_BLOCK_NUM 8
+static int regcache_lzo_block_count(void)
+{
+ return LZO_BLOCK_NUM;
+}
+
+static int regcache_lzo_prepare(struct regcache_lzo_ctx *lzo_ctx)
+{
+ lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+ if (!lzo_ctx->wmem)
+ return -ENOMEM;
+ return 0;
+}
+
+static int regcache_lzo_compress(struct regcache_lzo_ctx *lzo_ctx)
+{
+ size_t compress_size;
+ int ret;
+
+ ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
+ lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
+ if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
+ return -EINVAL;
+ lzo_ctx->dst_len = compress_size;
+ return 0;
+}
+
+static int regcache_lzo_decompress(struct regcache_lzo_ctx *lzo_ctx)
+{
+ size_t dst_len;
+ int ret;
+
+ dst_len = lzo_ctx->dst_len;
+ ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
+ lzo_ctx->dst, &dst_len);
+ if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
+ return -EINVAL;
+ return 0;
+}
+
+static int regcache_lzo_compress_cache_block(struct regmap *map,
+ struct regcache_lzo_ctx *lzo_ctx)
+{
+ int ret;
+
+ lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
+ lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
+ if (!lzo_ctx->dst) {
+ lzo_ctx->dst_len = 0;
+ return -ENOMEM;
+ }
+
+ ret = regcache_lzo_compress(lzo_ctx);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static int regcache_lzo_decompress_cache_block(struct regmap *map,
+ struct regcache_lzo_ctx *lzo_ctx)
+{
+ int ret;
+
+ lzo_ctx->dst_len = lzo_ctx->decompressed_size;
+ lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
+ if (!lzo_ctx->dst) {
+ lzo_ctx->dst_len = 0;
+ return -ENOMEM;
+ }
+
+ ret = regcache_lzo_decompress(lzo_ctx);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static inline int regcache_lzo_get_blkindex(struct regmap *map,
+ unsigned int reg)
+{
+ return (reg * map->cache_word_size) /
+ DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count());
+}
+
+static inline int regcache_lzo_get_blkpos(struct regmap *map,
+ unsigned int reg)
+{
+ return reg % (DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count()) /
+ map->cache_word_size);
+}
+
+static inline int regcache_lzo_get_blksize(struct regmap *map)
+{
+ return DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count());
+}
+
+static int regcache_lzo_init(struct regmap *map)
+{
+ struct regcache_lzo_ctx **lzo_blocks;
+ size_t bmp_size;
+ int ret, i, blksize, blkcount;
+ const char *p, *end;
+ unsigned long *sync_bmp;
+
+ ret = 0;
+
+ blkcount = regcache_lzo_block_count();
+ map->cache = kzalloc(blkcount * sizeof *lzo_blocks,
+ GFP_KERNEL);
+ if (!map->cache)
+ return -ENOMEM;
+ lzo_blocks = map->cache;
+
+ /*
+ * allocate a bitmap to be used when syncing the cache with
+ * the hardware. Each time a register is modified, the corresponding
+ * bit is set in the bitmap, so we know that we have to sync
+ * that register.
+ */
+ bmp_size = map->num_reg_defaults_raw;
+ sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
+ GFP_KERNEL);
+ if (!sync_bmp) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ bitmap_zero(sync_bmp, bmp_size);
+
+ /* allocate the lzo blocks and initialize them */
+ for (i = 0; i < blkcount; i++) {
+ lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
+ GFP_KERNEL);
+ if (!lzo_blocks[i]) {
+ kfree(sync_bmp);
+ ret = -ENOMEM;
+ goto err;
+ }
+ lzo_blocks[i]->sync_bmp = sync_bmp;
+ lzo_blocks[i]->sync_bmp_nbits = bmp_size;
+ /* alloc the working space for the compressed block */
+ ret = regcache_lzo_prepare(lzo_blocks[i]);
+ if (ret < 0)
+ goto err;
+ }
+
+ blksize = regcache_lzo_get_blksize(map);
+ p = map->reg_defaults_raw;
+ end = map->reg_defaults_raw + map->cache_size_raw;
+ /* compress the register map and fill the lzo blocks */
+ for (i = 0; i < blkcount; i++, p += blksize) {
+ lzo_blocks[i]->src = p;
+ if (p + blksize > end)
+ lzo_blocks[i]->src_len = end - p;
+ else
+ lzo_blocks[i]->src_len = blksize;
+ ret = regcache_lzo_compress_cache_block(map,
+ lzo_blocks[i]);
+ if (ret < 0)
+ goto err;
+ lzo_blocks[i]->decompressed_size =
+ lzo_blocks[i]->src_len;
+ }
+
+ return 0;
+err:
+ regcache_exit(map);
+ return ret;
+}
+
+static int regcache_lzo_exit(struct regmap *map)
+{
+ struct regcache_lzo_ctx **lzo_blocks;
+ int i, blkcount;
+
+ lzo_blocks = map->cache;
+ if (!lzo_blocks)
+ return 0;
+
+ blkcount = regcache_lzo_block_count();
+ /*
+ * the pointer to the bitmap used for syncing the cache
+ * is shared amongst all lzo_blocks. Ensure it is freed
+ * only once.
+ */
+ if (lzo_blocks[0])
+ kfree(lzo_blocks[0]->sync_bmp);
+ for (i = 0; i < blkcount; i++) {
+ if (lzo_blocks[i]) {
+ kfree(lzo_blocks[i]->wmem);
+ kfree(lzo_blocks[i]->dst);
+ }
+ /* each lzo_block is a pointer returned by kmalloc or NULL */
+ kfree(lzo_blocks[i]);
+ }
+ kfree(lzo_blocks);
+ map->cache = NULL;
+ return 0;
+}
+
+static int regcache_lzo_read(struct regmap *map,
+ unsigned int reg, unsigned int *value)
+{
+ struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
+ int ret, blkindex, blkpos;
+ size_t blksize, tmp_dst_len;
+ void *tmp_dst;
+
+ /* index of the compressed lzo block */
+ blkindex = regcache_lzo_get_blkindex(map, reg);
+ /* register index within the decompressed block */
+ blkpos = regcache_lzo_get_blkpos(map, reg);
+ /* size of the compressed block */
+ blksize = regcache_lzo_get_blksize(map);
+ lzo_blocks = map->cache;
+ lzo_block = lzo_blocks[blkindex];
+
+ /* save the pointer and length of the compressed block */
+ tmp_dst = lzo_block->dst;
+ tmp_dst_len = lzo_block->dst_len;
+
+ /* prepare the source to be the compressed block */
+ lzo_block->src = lzo_block->dst;
+ lzo_block->src_len = lzo_block->dst_len;
+
+ /* decompress the block */
+ ret = regcache_lzo_decompress_cache_block(map, lzo_block);
+ if (ret >= 0)
+ /* fetch the value from the cache */
+ *value = regcache_get_val(lzo_block->dst, blkpos,
+ map->cache_word_size);
+
+ kfree(lzo_block->dst);
+ /* restore the pointer and length of the compressed block */
+ lzo_block->dst = tmp_dst;
+ lzo_block->dst_len = tmp_dst_len;
+
+ return ret;
+}
+
+static int regcache_lzo_write(struct regmap *map,
+ unsigned int reg, unsigned int value)
+{
+ struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
+ int ret, blkindex, blkpos;
+ size_t blksize, tmp_dst_len;
+ void *tmp_dst;
+
+ /* index of the compressed lzo block */
+ blkindex = regcache_lzo_get_blkindex(map, reg);
+ /* register index within the decompressed block */
+ blkpos = regcache_lzo_get_blkpos(map, reg);
+ /* size of the compressed block */
+ blksize = regcache_lzo_get_blksize(map);
+ lzo_blocks = map->cache;
+ lzo_block = lzo_blocks[blkindex];
+
+ /* save the pointer and length of the compressed block */
+ tmp_dst = lzo_block->dst;
+ tmp_dst_len = lzo_block->dst_len;
+
+ /* prepare the source to be the compressed block */
+ lzo_block->src = lzo_block->dst;
+ lzo_block->src_len = lzo_block->dst_len;
+
+ /* decompress the block */
+ ret = regcache_lzo_decompress_cache_block(map, lzo_block);
+ if (ret < 0) {
+ kfree(lzo_block->dst);
+ goto out;
+ }
+
+ /* write the new value to the cache */
+ if (regcache_set_val(lzo_block->dst, blkpos, value,
+ map->cache_word_size)) {
+ kfree(lzo_block->dst);
+ goto out;
+ }
+
+ /* prepare the source to be the decompressed block */
+ lzo_block->src = lzo_block->dst;
+ lzo_block->src_len = lzo_block->dst_len;
+
+ /* compress the block */
+ ret = regcache_lzo_compress_cache_block(map, lzo_block);
+ if (ret < 0) {
+ kfree(lzo_block->dst);
+ kfree(lzo_block->src);
+ goto out;
+ }
+
+ /* set the bit so we know we have to sync this register */
+ set_bit(reg, lzo_block->sync_bmp);
+ kfree(tmp_dst);
+ kfree(lzo_block->src);
+ return 0;
+out:
+ lzo_block->dst = tmp_dst;
+ lzo_block->dst_len = tmp_dst_len;
+ return ret;
+}
+
+static int regcache_lzo_sync(struct regmap *map)
+{
+ struct regcache_lzo_ctx **lzo_blocks;
+ unsigned int val;
+ int i;
+ int ret;
+
+ lzo_blocks = map->cache;
+ for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
+ ret = regcache_read(map, i, &val);
+ if (ret)
+ return ret;
+ map->cache_bypass = 1;
+ ret = _regmap_write(map, i, val);
+ map->cache_bypass = 0;
+ if (ret)
+ return ret;
+ dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+ i, val);
+ }
+
+ return 0;
+}
+
+struct regcache_ops regcache_lzo_ops = {
+ .type = REGCACHE_LZO,
+ .name = "lzo",
+ .init = regcache_lzo_init,
+ .exit = regcache_lzo_exit,
+ .read = regcache_lzo_read,
+ .write = regcache_lzo_write,
+ .sync = regcache_lzo_sync
+};
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
new file mode 100644
index 000000000000..e31498499b0f
--- /dev/null
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -0,0 +1,345 @@
+/*
+ * Register cache access API - rbtree caching support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@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/slab.h>
+#include <linux/rbtree.h>
+
+#include "internal.h"
+
+static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
+ unsigned int value);
+
+struct regcache_rbtree_node {
+ /* the actual rbtree node holding this block */
+ struct rb_node node;
+ /* base register handled by this block */
+ unsigned int base_reg;
+ /* block of adjacent registers */
+ void *block;
+ /* number of registers available in the block */
+ unsigned int blklen;
+} __attribute__ ((packed));
+
+struct regcache_rbtree_ctx {
+ struct rb_root root;
+ struct regcache_rbtree_node *cached_rbnode;
+};
+
+static inline void regcache_rbtree_get_base_top_reg(
+ struct regcache_rbtree_node *rbnode,
+ unsigned int *base, unsigned int *top)
+{
+ *base = rbnode->base_reg;
+ *top = rbnode->base_reg + rbnode->blklen - 1;
+}
+
+static unsigned int regcache_rbtree_get_register(
+ struct regcache_rbtree_node *rbnode, unsigned int idx,
+ unsigned int word_size)
+{
+ return regcache_get_val(rbnode->block, idx, word_size);
+}
+
+static void regcache_rbtree_set_register(struct regcache_rbtree_node *rbnode,
+ unsigned int idx, unsigned int val,
+ unsigned int word_size)
+{
+ regcache_set_val(rbnode->block, idx, val, word_size);
+}
+
+static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
+ unsigned int reg)
+{
+ struct regcache_rbtree_ctx *rbtree_ctx = map->cache;
+ struct rb_node *node;
+ struct regcache_rbtree_node *rbnode;
+ unsigned int base_reg, top_reg;
+
+ rbnode = rbtree_ctx->cached_rbnode;
+ if (rbnode) {
+ regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+ if (reg >= base_reg && reg <= top_reg)
+ return rbnode;
+ }
+
+ node = rbtree_ctx->root.rb_node;
+ while (node) {
+ rbnode = container_of(node, struct regcache_rbtree_node, node);
+ regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+ if (reg >= base_reg && reg <= top_reg) {
+ rbtree_ctx->cached_rbnode = rbnode;
+ return rbnode;
+ } else if (reg > top_reg) {
+ node = node->rb_right;
+ } else if (reg < base_reg) {
+ node = node->rb_left;
+ }
+ }
+
+ return NULL;
+}
+
+static int regcache_rbtree_insert(struct rb_root *root,
+ struct regcache_rbtree_node *rbnode)
+{
+ struct rb_node **new, *parent;
+ struct regcache_rbtree_node *rbnode_tmp;
+ unsigned int base_reg_tmp, top_reg_tmp;
+ unsigned int base_reg;
+
+ parent = NULL;
+ new = &root->rb_node;
+ while (*new) {
+ rbnode_tmp = container_of(*new, struct regcache_rbtree_node,
+ node);
+ /* base and top registers of the current rbnode */
+ regcache_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp,
+ &top_reg_tmp);
+ /* base register of the rbnode to be added */
+ base_reg = rbnode->base_reg;
+ parent = *new;
+ /* if this register has already been inserted, just return */
+ if (base_reg >= base_reg_tmp &&
+ base_reg <= top_reg_tmp)
+ return 0;
+ else if (base_reg > top_reg_tmp)
+ new = &((*new)->rb_right);
+ else if (base_reg < base_reg_tmp)
+ new = &((*new)->rb_left);
+ }
+
+ /* insert the node into the rbtree */
+ rb_link_node(&rbnode->node, parent, new);
+ rb_insert_color(&rbnode->node, root);
+
+ return 1;
+}
+
+static int regcache_rbtree_init(struct regmap *map)
+{
+ struct regcache_rbtree_ctx *rbtree_ctx;
+ int i;
+ int ret;
+
+ map->cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
+ if (!map->cache)
+ return -ENOMEM;
+
+ rbtree_ctx = map->cache;
+ rbtree_ctx->root = RB_ROOT;
+ rbtree_ctx->cached_rbnode = NULL;
+
+ for (i = 0; i < map->num_reg_defaults; i++) {
+ ret = regcache_rbtree_write(map,
+ map->reg_defaults[i].reg,
+ map->reg_defaults[i].def);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ regcache_exit(map);
+ return ret;
+}
+
+static int regcache_rbtree_exit(struct regmap *map)
+{
+ struct rb_node *next;
+ struct regcache_rbtree_ctx *rbtree_ctx;
+ struct regcache_rbtree_node *rbtree_node;
+
+ /* if we've already been called then just return */
+ rbtree_ctx = map->cache;
+ if (!rbtree_ctx)
+ return 0;
+
+ /* free up the rbtree */
+ next = rb_first(&rbtree_ctx->root);
+ while (next) {
+ rbtree_node = rb_entry(next, struct regcache_rbtree_node, node);
+ next = rb_next(&rbtree_node->node);
+ rb_erase(&rbtree_node->node, &rbtree_ctx->root);
+ kfree(rbtree_node->block);
+ kfree(rbtree_node);
+ }
+
+ /* release the resources */
+ kfree(map->cache);
+ map->cache = NULL;
+
+ return 0;
+}
+
+static int regcache_rbtree_read(struct regmap *map,
+ unsigned int reg, unsigned int *value)
+{
+ struct regcache_rbtree_node *rbnode;
+ unsigned int reg_tmp;
+
+ rbnode = regcache_rbtree_lookup(map, reg);
+ if (rbnode) {
+ reg_tmp = reg - rbnode->base_reg;
+ *value = regcache_rbtree_get_register(rbnode, reg_tmp,
+ map->cache_word_size);
+ } else {
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+
+static int regcache_rbtree_insert_to_block(struct regcache_rbtree_node *rbnode,
+ unsigned int pos, unsigned int reg,
+ unsigned int value, unsigned int word_size)
+{
+ u8 *blk;
+
+ blk = krealloc(rbnode->block,
+ (rbnode->blklen + 1) * word_size, GFP_KERNEL);
+ if (!blk)
+ return -ENOMEM;
+
+ /* insert the register value in the correct place in the rbnode block */
+ memmove(blk + (pos + 1) * word_size,
+ blk + pos * word_size,
+ (rbnode->blklen - pos) * word_size);
+
+ /* update the rbnode block, its size and the base register */
+ rbnode->block = blk;
+ rbnode->blklen++;
+ if (!pos)
+ rbnode->base_reg = reg;
+
+ regcache_rbtree_set_register(rbnode, pos, value, word_size);
+ return 0;
+}
+
+static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
+ unsigned int value)
+{
+ struct regcache_rbtree_ctx *rbtree_ctx;
+ struct regcache_rbtree_node *rbnode, *rbnode_tmp;
+ struct rb_node *node;
+ unsigned int val;
+ unsigned int reg_tmp;
+ unsigned int pos;
+ int i;
+ int ret;
+
+ rbtree_ctx = map->cache;
+ /* if we can't locate it in the cached rbnode we'll have
+ * to traverse the rbtree looking for it.
+ */
+ rbnode = regcache_rbtree_lookup(map, reg);
+ if (rbnode) {
+ reg_tmp = reg - rbnode->base_reg;
+ val = regcache_rbtree_get_register(rbnode, reg_tmp,
+ map->cache_word_size);
+ if (val == value)
+ return 0;
+ regcache_rbtree_set_register(rbnode, reg_tmp, value,
+ map->cache_word_size);
+ } else {
+ /* look for an adjacent register to the one we are about to add */
+ for (node = rb_first(&rbtree_ctx->root); node;
+ node = rb_next(node)) {
+ rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, node);
+ for (i = 0; i < rbnode_tmp->blklen; i++) {
+ reg_tmp = rbnode_tmp->base_reg + i;
+ if (abs(reg_tmp - reg) != 1)
+ continue;
+ /* decide where in the block to place our register */
+ if (reg_tmp + 1 == reg)
+ pos = i + 1;
+ else
+ pos = i;
+ ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos,
+ reg, value,
+ map->cache_word_size);
+ if (ret)
+ return ret;
+ rbtree_ctx->cached_rbnode = rbnode_tmp;
+ return 0;
+ }
+ }
+ /* we did not manage to find a place to insert it in an existing
+ * block so create a new rbnode with a single register in its block.
+ * This block will get populated further if any other adjacent
+ * registers get modified in the future.
+ */
+ rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
+ if (!rbnode)
+ return -ENOMEM;
+ rbnode->blklen = 1;
+ rbnode->base_reg = reg;
+ rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
+ GFP_KERNEL);
+ if (!rbnode->block) {
+ kfree(rbnode);
+ return -ENOMEM;
+ }
+ regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
+ regcache_rbtree_insert(&rbtree_ctx->root, rbnode);
+ rbtree_ctx->cached_rbnode = rbnode;
+ }
+
+ return 0;
+}
+
+static int regcache_rbtree_sync(struct regmap *map)
+{
+ struct regcache_rbtree_ctx *rbtree_ctx;
+ struct rb_node *node;
+ struct regcache_rbtree_node *rbnode;
+ unsigned int regtmp;
+ unsigned int val;
+ int ret;
+ int i;
+
+ rbtree_ctx = map->cache;
+ for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
+ rbnode = rb_entry(node, struct regcache_rbtree_node, node);
+ for (i = 0; i < rbnode->blklen; i++) {
+ regtmp = rbnode->base_reg + i;
+ val = regcache_rbtree_get_register(rbnode, i,
+ map->cache_word_size);
+
+ /* Is this the hardware default? If so skip. */
+ ret = regcache_lookup_reg(map, i);
+ if (ret > 0 && val == map->reg_defaults[ret].def)
+ continue;
+
+ map->cache_bypass = 1;
+ ret = _regmap_write(map, regtmp, val);
+ map->cache_bypass = 0;
+ if (ret)
+ return ret;
+ dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+ regtmp, val);
+ }
+ }
+
+ return 0;
+}
+
+struct regcache_ops regcache_rbtree_ops = {
+ .type = REGCACHE_RBTREE,
+ .name = "rbtree",
+ .init = regcache_rbtree_init,
+ .exit = regcache_rbtree_exit,
+ .read = regcache_rbtree_read,
+ .write = regcache_rbtree_write,
+ .sync = regcache_rbtree_sync
+};
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
new file mode 100644
index 000000000000..afcfef838263
--- /dev/null
+++ b/drivers/base/regmap/regcache.c
@@ -0,0 +1,401 @@
+/*
+ * Register cache access API
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@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/slab.h>
+#include <trace/events/regmap.h>
+#include <linux/bsearch.h>
+#include <linux/sort.h>
+
+#include "internal.h"
+
+static const struct regcache_ops *cache_types[] = {
+ &regcache_indexed_ops,
+ &regcache_rbtree_ops,
+ &regcache_lzo_ops,
+};
+
+static int regcache_hw_init(struct regmap *map)
+{
+ int i, j;
+ int ret;
+ int count;
+ unsigned int val;
+ void *tmp_buf;
+
+ if (!map->num_reg_defaults_raw)
+ return -EINVAL;
+
+ if (!map->reg_defaults_raw) {
+ dev_warn(map->dev, "No cache defaults, reading back from HW\n");
+ tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
+ if (!tmp_buf)
+ return -EINVAL;
+ ret = regmap_bulk_read(map, 0, tmp_buf,
+ map->num_reg_defaults_raw);
+ if (ret < 0) {
+ kfree(tmp_buf);
+ return ret;
+ }
+ map->reg_defaults_raw = tmp_buf;
+ map->cache_free = 1;
+ }
+
+ /* calculate the size of reg_defaults */
+ for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
+ val = regcache_get_val(map->reg_defaults_raw,
+ i, map->cache_word_size);
+ if (!val)
+ continue;
+ count++;
+ }
+
+ map->reg_defaults = kmalloc(count * sizeof(struct reg_default),
+ GFP_KERNEL);
+ if (!map->reg_defaults)
+ return -ENOMEM;
+
+ /* fill the reg_defaults */
+ map->num_reg_defaults = count;
+ for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
+ val = regcache_get_val(map->reg_defaults_raw,
+ i, map->cache_word_size);
+ if (!val)
+ continue;
+ map->reg_defaults[j].reg = i;
+ map->reg_defaults[j].def = val;
+ j++;
+ }
+
+ return 0;
+}
+
+int regcache_init(struct regmap *map)
+{
+ int ret;
+ int i;
+ void *tmp_buf;
+
+ if (map->cache_type == REGCACHE_NONE) {
+ map->cache_bypass = true;
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cache_types); i++)
+ if (cache_types[i]->type == map->cache_type)
+ break;
+
+ if (i == ARRAY_SIZE(cache_types)) {
+ dev_err(map->dev, "Could not match compress type: %d\n",
+ map->cache_type);
+ return -EINVAL;
+ }
+
+ map->cache = NULL;
+ map->cache_ops = cache_types[i];
+
+ if (!map->cache_ops->read ||
+ !map->cache_ops->write ||
+ !map->cache_ops->name)
+ return -EINVAL;
+
+ /* We still need to ensure that the reg_defaults
+ * won't vanish from under us. We'll need to make
+ * a copy of it.
+ */
+ if (map->reg_defaults) {
+ if (!map->num_reg_defaults)
+ return -EINVAL;
+ tmp_buf = kmemdup(map->reg_defaults, map->num_reg_defaults *
+ sizeof(struct reg_default), GFP_KERNEL);
+ if (!tmp_buf)
+ return -ENOMEM;
+ map->reg_defaults = tmp_buf;
+ } else if (map->num_reg_defaults_raw) {
+ /* Some devices such as PMICs don't have cache defaults,
+ * we cope with this by reading back the HW registers and
+ * crafting the cache defaults by hand.
+ */
+ ret = regcache_hw_init(map);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (!map->max_register)
+ map->max_register = map->num_reg_defaults_raw;
+
+ if (map->cache_ops->init) {
+ dev_dbg(map->dev, "Initializing %s cache\n",
+ map->cache_ops->name);
+ return map->cache_ops->init(map);
+ }
+ return 0;
+}
+
+void regcache_exit(struct regmap *map)
+{
+ if (map->cache_type == REGCACHE_NONE)
+ return;
+
+ BUG_ON(!map->cache_ops);
+
+ kfree(map->reg_defaults);
+ if (map->cache_free)
+ kfree(map->reg_defaults_raw);
+
+ if (map->cache_ops->exit) {
+ dev_dbg(map->dev, "Destroying %s cache\n",
+ map->cache_ops->name);
+ map->cache_ops->exit(map);
+ }
+}
+
+/**
+ * regcache_read: Fetch the value of a given register from the cache.
+ *
+ * @map: map to configure.
+ * @reg: The register index.
+ * @value: The value to be returned.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_read(struct regmap *map,
+ unsigned int reg, unsigned int *value)
+{
+ if (map->cache_type == REGCACHE_NONE)
+ return -ENOSYS;
+
+ BUG_ON(!map->cache_ops);
+
+ if (!regmap_readable(map, reg))
+ return -EIO;
+
+ if (!regmap_volatile(map, reg))
+ return map->cache_ops->read(map, reg, value);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regcache_read);
+
+/**
+ * regcache_write: Set the value of a given register in the cache.
+ *
+ * @map: map to configure.
+ * @reg: The register index.
+ * @value: The new register value.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_write(struct regmap *map,
+ unsigned int reg, unsigned int value)
+{
+ if (map->cache_type == REGCACHE_NONE)
+ return 0;
+
+ BUG_ON(!map->cache_ops);
+
+ if (!regmap_writeable(map, reg))
+ return -EIO;
+
+ if (!regmap_volatile(map, reg))
+ return map->cache_ops->write(map, reg, value);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(regcache_write);
+
+/**
+ * regcache_sync: Sync the register cache with the hardware.
+ *
+ * @map: map to configure.
+ *
+ * Any registers that should not be synced should be marked as
+ * volatile. In general drivers can choose not to use the provided
+ * syncing functionality if they so require.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_sync(struct regmap *map)
+{
+ int ret = 0;
+ unsigned int val;
+ unsigned int i;
+ const char *name;
+ unsigned int bypass;
+
+ BUG_ON(!map->cache_ops);
+
+ mutex_lock(&map->lock);
+ /* Remember the initial bypass state */
+ bypass = map->cache_bypass;
+ dev_dbg(map->dev, "Syncing %s cache\n",
+ map->cache_ops->name);
+ name = map->cache_ops->name;
+ trace_regcache_sync(map->dev, name, "start");
+ if (map->cache_ops->sync) {
+ ret = map->cache_ops->sync(map);
+ } else {
+ for (i = 0; i < map->num_reg_defaults; i++) {
+ ret = regcache_read(map, i, &val);
+ if (ret < 0)
+ goto out;
+ map->cache_bypass = 1;
+ ret = _regmap_write(map, i, val);
+ map->cache_bypass = 0;
+ if (ret < 0)
+ goto out;
+ dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+ map->reg_defaults[i].reg,
+ map->reg_defaults[i].def);
+ }
+
+ }
+out:
+ trace_regcache_sync(map->dev, name, "stop");
+ /* Restore the bypass state */
+ map->cache_bypass = bypass;
+ mutex_unlock(&map->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regcache_sync);
+
+/**
+ * regcache_cache_only: Put a register map into cache only mode
+ *
+ * @map: map to configure
+ * @cache_only: flag if changes should be written to the hardware
+ *
+ * When a register map is marked as cache only writes to the register
+ * map API will only update the register cache, they will not cause
+ * any hardware changes. This is useful for allowing portions of
+ * drivers to act as though the device were functioning as normal when
+ * it is disabled for power saving reasons.
+ */
+void regcache_cache_only(struct regmap *map, bool enable)
+{
+ mutex_lock(&map->lock);
+ WARN_ON(map->cache_bypass && enable);
+ map->cache_only = enable;
+ mutex_unlock(&map->lock);
+}
+EXPORT_SYMBOL_GPL(regcache_cache_only);
+
+/**
+ * regcache_cache_bypass: Put a register map into cache bypass mode
+ *
+ * @map: map to configure
+ * @cache_bypass: flag if changes should not be written to the hardware
+ *
+ * When a register map is marked with the cache bypass option, writes
+ * to the register map API will only update the hardware and not the
+ * the cache directly. This is useful when syncing the cache back to
+ * the hardware.
+ */
+void regcache_cache_bypass(struct regmap *map, bool enable)
+{
+ mutex_lock(&map->lock);
+ WARN_ON(map->cache_only && enable);
+ map->cache_bypass = enable;
+ mutex_unlock(&map->lock);
+}
+EXPORT_SYMBOL_GPL(regcache_cache_bypass);
+
+bool regcache_set_val(void *base, unsigned int idx,
+ unsigned int val, unsigned int word_size)
+{
+ switch (word_size) {
+ case 1: {
+ u8 *cache = base;
+ if (cache[idx] == val)
+ return true;
+ cache[idx] = val;
+ break;
+ }
+ case 2: {
+ u16 *cache = base;
+ if (cache[idx] == val)
+ return true;
+ cache[idx] = val;
+ break;
+ }
+ default:
+ BUG();
+ }
+ /* unreachable */
+ return false;
+}
+
+unsigned int regcache_get_val(const void *base, unsigned int idx,
+ unsigned int word_size)
+{
+ if (!base)
+ return -EINVAL;
+
+ switch (word_size) {
+ case 1: {
+ const u8 *cache = base;
+ return cache[idx];
+ }
+ case 2: {
+ const u16 *cache = base;
+ return cache[idx];
+ }
+ default:
+ BUG();
+ }
+ /* unreachable */
+ return -1;
+}
+
+static int regcache_default_cmp(const void *a, const void *b)
+{
+ const struct reg_default *_a = a;
+ const struct reg_default *_b = b;
+
+ return _a->reg - _b->reg;
+}
+
+int regcache_lookup_reg(struct regmap *map, unsigned int reg)
+{
+ struct reg_default key;
+ struct reg_default *r;
+
+ key.reg = reg;
+ key.def = 0;
+
+ r = bsearch(&key, map->reg_defaults, map->num_reg_defaults,
+ sizeof(struct reg_default), regcache_default_cmp);
+
+ if (r)
+ return r - map->reg_defaults;
+ else
+ return -ENOENT;
+}
+
+int regcache_insert_reg(struct regmap *map, unsigned int reg,
+ unsigned int val)
+{
+ void *tmp;
+
+ tmp = krealloc(map->reg_defaults,
+ (map->num_reg_defaults + 1) * sizeof(struct reg_default),
+ GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+ map->reg_defaults = tmp;
+ map->num_reg_defaults++;
+ map->reg_defaults[map->num_reg_defaults - 1].reg = reg;
+ map->reg_defaults[map->num_reg_defaults - 1].def = val;
+ sort(map->reg_defaults, map->num_reg_defaults,
+ sizeof(struct reg_default), regcache_default_cmp, NULL);
+ return 0;
+}
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
new file mode 100644
index 000000000000..6f397476e27c
--- /dev/null
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -0,0 +1,209 @@
+/*
+ * Register map access API - debugfs
+ *
+ * Copyright 2011 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/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include "internal.h"
+
+static struct dentry *regmap_debugfs_root;
+
+/* Calculate the length of a fixed format */
+static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
+{
+ snprintf(buf, buf_size, "%x", max_val);
+ return strlen(buf);
+}
+
+static int regmap_open_file(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ int reg_len, val_len, tot_len;
+ size_t buf_pos = 0;
+ loff_t p = 0;
+ ssize_t ret;
+ int i;
+ struct regmap *map = file->private_data;
+ char *buf;
+ unsigned int val;
+
+ if (*ppos < 0 || !count)
+ return -EINVAL;
+
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Calculate the length of a fixed format */
+ reg_len = regmap_calc_reg_len(map->max_register, buf, count);
+ val_len = 2 * map->format.val_bytes;
+ tot_len = reg_len + val_len + 3; /* : \n */
+
+ for (i = 0; i < map->max_register + 1; i++) {
+ if (!regmap_readable(map, i))
+ continue;
+
+ if (regmap_precious(map, i))
+ continue;
+
+ /* If we're in the region the user is trying to read */
+ if (p >= *ppos) {
+ /* ...but not beyond it */
+ if (buf_pos >= count - 1 - tot_len)
+ break;
+
+ /* Format the register */
+ snprintf(buf + buf_pos, count - buf_pos, "%.*x: ",
+ reg_len, i);
+ buf_pos += reg_len + 2;
+
+ /* Format the value, write all X if we can't read */
+ ret = regmap_read(map, i, &val);
+ if (ret == 0)
+ snprintf(buf + buf_pos, count - buf_pos,
+ "%.*x", val_len, val);
+ else
+ memset(buf + buf_pos, 'X', val_len);
+ buf_pos += 2 * map->format.val_bytes;
+
+ buf[buf_pos++] = '\n';
+ }
+ p += tot_len;
+ }
+
+ ret = buf_pos;
+
+ if (copy_to_user(user_buf, buf, buf_pos)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ *ppos += buf_pos;
+
+out:
+ kfree(buf);
+ return ret;
+}
+
+static const struct file_operations regmap_map_fops = {
+ .open = regmap_open_file,
+ .read = regmap_map_read_file,
+ .llseek = default_llseek,
+};
+
+static ssize_t regmap_access_read_file(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ int reg_len, tot_len;
+ size_t buf_pos = 0;
+ loff_t p = 0;
+ ssize_t ret;
+ int i;
+ struct regmap *map = file->private_data;
+ char *buf;
+
+ if (*ppos < 0 || !count)
+ return -EINVAL;
+
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Calculate the length of a fixed format */
+ reg_len = regmap_calc_reg_len(map->max_register, buf, count);
+ tot_len = reg_len + 10; /* ': R W V P\n' */
+
+ for (i = 0; i < map->max_register + 1; i++) {
+ /* Ignore registers which are neither readable nor writable */
+ if (!regmap_readable(map, i) && !regmap_writeable(map, i))
+ continue;
+
+ /* If we're in the region the user is trying to read */
+ if (p >= *ppos) {
+ /* ...but not beyond it */
+ if (buf_pos >= count - 1 - tot_len)
+ break;
+
+ /* Format the register */
+ snprintf(buf + buf_pos, count - buf_pos,
+ "%.*x: %c %c %c %c\n",
+ reg_len, i,
+ regmap_readable(map, i) ? 'y' : 'n',
+ regmap_writeable(map, i) ? 'y' : 'n',
+ regmap_volatile(map, i) ? 'y' : 'n',
+ regmap_precious(map, i) ? 'y' : 'n');
+
+ buf_pos += tot_len;
+ }
+ p += tot_len;
+ }
+
+ ret = buf_pos;
+
+ if (copy_to_user(user_buf, buf, buf_pos)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ *ppos += buf_pos;
+
+out:
+ kfree(buf);
+ return ret;
+}
+
+static const struct file_operations regmap_access_fops = {
+ .open = regmap_open_file,
+ .read = regmap_access_read_file,
+ .llseek = default_llseek,
+};
+
+void regmap_debugfs_init(struct regmap *map)
+{
+ map->debugfs = debugfs_create_dir(dev_name(map->dev),
+ regmap_debugfs_root);
+ if (!map->debugfs) {
+ dev_warn(map->dev, "Failed to create debugfs directory\n");
+ return;
+ }
+
+ if (map->max_register) {
+ debugfs_create_file("registers", 0400, map->debugfs,
+ map, &regmap_map_fops);
+ debugfs_create_file("access", 0400, map->debugfs,
+ map, &regmap_access_fops);
+ }
+}
+
+void regmap_debugfs_exit(struct regmap *map)
+{
+ debugfs_remove_recursive(map->debugfs);
+}
+
+void regmap_debugfs_initcall(void)
+{
+ regmap_debugfs_root = debugfs_create_dir("regmap", NULL);
+ if (!regmap_debugfs_root) {
+ pr_warn("regmap: Failed to create debugfs root\n");
+ return;
+ }
+}
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index c4f7a45cd2c3..38621ec87c05 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -90,11 +90,9 @@ static int regmap_i2c_read(struct device *dev,
}
static struct regmap_bus regmap_i2c = {
- .type = &i2c_bus_type,
.write = regmap_i2c_write,
.gather_write = regmap_i2c_gather_write,
.read = regmap_i2c_read,
- .owner = THIS_MODULE,
};
/**
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index f8396945d6ed..2560658de344 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -48,11 +48,9 @@ static int regmap_spi_read(struct device *dev,
}
static struct regmap_bus regmap_spi = {
- .type = &spi_bus_type,
.write = regmap_spi_write,
.gather_write = regmap_spi_gather_write,
.read = regmap_spi_read,
- .owner = THIS_MODULE,
.read_flag_mask = 0x80,
};
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 20663f8dae45..bf441db1ee90 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -15,29 +15,54 @@
#include <linux/mutex.h>
#include <linux/err.h>
-#include <linux/regmap.h>
-
-struct regmap;
-
-struct regmap_format {
- size_t buf_size;
- size_t reg_bytes;
- size_t val_bytes;
- void (*format_write)(struct regmap *map,
- unsigned int reg, unsigned int val);
- void (*format_reg)(void *buf, unsigned int reg);
- void (*format_val)(void *buf, unsigned int val);
- unsigned int (*parse_val)(void *buf);
-};
-
-struct regmap {
- struct mutex lock;
-
- struct device *dev; /* Device we do I/O on */
- void *work_buf; /* Scratch buffer used to format I/O */
- struct regmap_format format; /* Buffer format */
- const struct regmap_bus *bus;
-};
+#define CREATE_TRACE_POINTS
+#include <trace/events/regmap.h>
+
+#include "internal.h"
+
+bool regmap_writeable(struct regmap *map, unsigned int reg)
+{
+ if (map->max_register && reg > map->max_register)
+ return false;
+
+ if (map->writeable_reg)
+ return map->writeable_reg(map->dev, reg);
+
+ return true;
+}
+
+bool regmap_readable(struct regmap *map, unsigned int reg)
+{
+ if (map->max_register && reg > map->max_register)
+ return false;
+
+ if (map->readable_reg)
+ return map->readable_reg(map->dev, reg);
+
+ return true;
+}
+
+bool regmap_volatile(struct regmap *map, unsigned int reg)
+{
+ if (map->max_register && reg > map->max_register)
+ return false;
+
+ if (map->volatile_reg)
+ return map->volatile_reg(map->dev, reg);
+
+ return true;
+}
+
+bool regmap_precious(struct regmap *map, unsigned int reg)
+{
+ if (map->max_register && reg > map->max_register)
+ return false;
+
+ if (map->precious_reg)
+ return map->precious_reg(map->dev, reg);
+
+ return false;
+}
static void regmap_format_4_12_write(struct regmap *map,
unsigned int reg, unsigned int val)
@@ -116,6 +141,25 @@ struct regmap *regmap_init(struct device *dev,
map->format.val_bytes = config->val_bits / 8;
map->dev = dev;
map->bus = bus;
+ map->max_register = config->max_register;
+ map->writeable_reg = config->writeable_reg;
+ map->readable_reg = config->readable_reg;
+ map->volatile_reg = config->volatile_reg;
+ map->precious_reg = config->precious_reg;
+ map->cache_type = config->cache_type;
+ map->reg_defaults = config->reg_defaults;
+ map->num_reg_defaults = config->num_reg_defaults;
+ map->num_reg_defaults_raw = config->num_reg_defaults_raw;
+ map->reg_defaults_raw = config->reg_defaults_raw;
+ map->cache_size_raw = (config->val_bits / 8) * config->num_reg_defaults_raw;
+ map->cache_word_size = config->val_bits / 8;
+
+ if (config->read_flag_mask || config->write_flag_mask) {
+ map->read_flag_mask = config->read_flag_mask;
+ map->write_flag_mask = config->write_flag_mask;
+ } else {
+ map->read_flag_mask = bus->read_flag_mask;
+ }
switch (config->reg_bits) {
case 4:
@@ -171,6 +215,12 @@ struct regmap *regmap_init(struct device *dev,
goto err_map;
}
+ ret = regcache_init(map);
+ if (ret < 0)
+ goto err_map;
+
+ regmap_debugfs_init(map);
+
return map;
err_map:
@@ -185,6 +235,8 @@ EXPORT_SYMBOL_GPL(regmap_init);
*/
void regmap_exit(struct regmap *map)
{
+ regcache_exit(map);
+ regmap_debugfs_exit(map);
kfree(map->work_buf);
kfree(map);
}
@@ -193,19 +245,38 @@ EXPORT_SYMBOL_GPL(regmap_exit);
static int _regmap_raw_write(struct regmap *map, unsigned int reg,
const void *val, size_t val_len)
{
+ u8 *u8 = map->work_buf;
void *buf;
int ret = -ENOTSUPP;
size_t len;
+ int i;
+
+ /* Check for unwritable registers before we start */
+ if (map->writeable_reg)
+ for (i = 0; i < val_len / map->format.val_bytes; i++)
+ if (!map->writeable_reg(map->dev, reg + i))
+ return -EINVAL;
map->format.format_reg(map->work_buf, reg);
- /* Try to do a gather write if we can */
- if (map->bus->gather_write)
+ u8[0] |= map->write_flag_mask;
+
+ trace_regmap_hw_write_start(map->dev, reg,
+ val_len / map->format.val_bytes);
+
+ /* If we're doing a single register write we can probably just
+ * send the work_buf directly, otherwise try to do a gather
+ * write.
+ */
+ if (val == map->work_buf + map->format.reg_bytes)
+ ret = map->bus->write(map->dev, map->work_buf,
+ map->format.reg_bytes + val_len);
+ else if (map->bus->gather_write)
ret = map->bus->gather_write(map->dev, map->work_buf,
map->format.reg_bytes,
val, val_len);
- /* Otherwise fall back on linearising by hand. */
+ /* If that didn't work fall back on linearising by hand. */
if (ret == -ENOTSUPP) {
len = map->format.reg_bytes + val_len;
buf = kmalloc(len, GFP_KERNEL);
@@ -219,19 +290,39 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
kfree(buf);
}
+ trace_regmap_hw_write_done(map->dev, reg,
+ val_len / map->format.val_bytes);
+
return ret;
}
-static int _regmap_write(struct regmap *map, unsigned int reg,
- unsigned int val)
+int _regmap_write(struct regmap *map, unsigned int reg,
+ unsigned int val)
{
+ int ret;
BUG_ON(!map->format.format_write && !map->format.format_val);
+ if (!map->cache_bypass) {
+ ret = regcache_write(map, reg, val);
+ if (ret != 0)
+ return ret;
+ if (map->cache_only)
+ return 0;
+ }
+
+ trace_regmap_reg_write(map->dev, reg, val);
+
if (map->format.format_write) {
map->format.format_write(map, reg, val);
- return map->bus->write(map->dev, map->work_buf,
- map->format.buf_size);
+ trace_regmap_hw_write_start(map->dev, reg, 1);
+
+ ret = map->bus->write(map->dev, map->work_buf,
+ map->format.buf_size);
+
+ trace_regmap_hw_write_done(map->dev, reg, 1);
+
+ return ret;
} else {
map->format.format_val(map->work_buf + map->format.reg_bytes,
val);
@@ -286,6 +377,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
{
int ret;
+ WARN_ON(map->cache_type != REGCACHE_NONE);
+
mutex_lock(&map->lock);
ret = _regmap_raw_write(map, reg, val, val_len);
@@ -305,20 +398,23 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
map->format.format_reg(map->work_buf, reg);
/*
- * Some buses flag reads by setting the high bits in the
+ * Some buses or devices flag reads by setting the high bits in the
* register addresss; since it's always the high bits for all
* current formats we can do this here rather than in
* formatting. This may break if we get interesting formats.
*/
- if (map->bus->read_flag_mask)
- u8[0] |= map->bus->read_flag_mask;
+ u8[0] |= map->read_flag_mask;
+
+ trace_regmap_hw_read_start(map->dev, reg,
+ val_len / map->format.val_bytes);
ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes,
val, val_len);
- if (ret != 0)
- return ret;
- return 0;
+ trace_regmap_hw_read_done(map->dev, reg,
+ val_len / map->format.val_bytes);
+
+ return ret;
}
static int _regmap_read(struct regmap *map, unsigned int reg,
@@ -329,9 +425,20 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
if (!map->format.parse_val)
return -EINVAL;
+ if (!map->cache_bypass) {
+ ret = regcache_read(map, reg, val);
+ if (ret == 0)
+ return 0;
+ }
+
+ if (map->cache_only)
+ return -EBUSY;
+
ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
- if (ret == 0)
+ if (ret == 0) {
*val = map->format.parse_val(map->work_buf);
+ trace_regmap_reg_read(map->dev, reg, *val);
+ }
return ret;
}
@@ -375,6 +482,14 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
size_t val_len)
{
int ret;
+ int i;
+ bool vol = true;
+
+ for (i = 0; i < val_len / map->format.val_bytes; i++)
+ if (!regmap_volatile(map, reg + i))
+ vol = false;
+
+ WARN_ON(!vol && map->cache_type != REGCACHE_NONE);
mutex_lock(&map->lock);
@@ -402,16 +517,30 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
{
int ret, i;
size_t val_bytes = map->format.val_bytes;
+ bool vol = true;
if (!map->format.parse_val)
return -EINVAL;
- ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
- if (ret != 0)
- return ret;
+ /* Is this a block of volatile registers? */
+ for (i = 0; i < val_count; i++)
+ if (!regmap_volatile(map, reg + i))
+ vol = false;
+
+ if (vol || map->cache_type == REGCACHE_NONE) {
+ ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
+ if (ret != 0)
+ return ret;
- for (i = 0; i < val_count * val_bytes; i += val_bytes)
- map->format.parse_val(val + i);
+ for (i = 0; i < val_count * val_bytes; i += val_bytes)
+ map->format.parse_val(val + i);
+ } else {
+ for (i = 0; i < val_count; i++) {
+ ret = regmap_read(map, reg + i, val + (i * val_bytes));
+ if (ret != 0)
+ return ret;
+ }
+ }
return 0;
}
@@ -450,3 +579,11 @@ out:
return ret;
}
EXPORT_SYMBOL_GPL(regmap_update_bits);
+
+static int __init regmap_initcall(void)
+{
+ regmap_debugfs_initcall();
+
+ return 0;
+}
+postcore_initcall(regmap_initcall);
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index ae0a02e1b808..c1172dafdffa 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -33,6 +33,19 @@ config BCMA_DRIVER_PCI_HOSTMODE
help
PCI core hostmode operation (external PCI bus).
+config BCMA_HOST_SOC
+ bool
+ depends on BCMA_DRIVER_MIPS
+
+config BCMA_DRIVER_MIPS
+ bool "BCMA Broadcom MIPS core driver"
+ depends on BCMA && MIPS
+ help
+ Driver for the Broadcom MIPS core attached to Broadcom specific
+ Advanced Microcontroller Bus.
+
+ If unsure, say N
+
config BCMA_DEBUG
bool "BCMA debugging"
depends on BCMA
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index a2161cceafb9..82de24e5340c 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -2,7 +2,9 @@ bcma-y += main.o scan.o core.o sprom.o
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
bcma-y += driver_pci.o
bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
+bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
+bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
obj-$(CONFIG_BCMA) += bcma.o
ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index e02ff21835c9..30a3085d3354 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -15,13 +15,29 @@ struct bcma_bus;
/* main.c */
int bcma_bus_register(struct bcma_bus *bus);
void bcma_bus_unregister(struct bcma_bus *bus);
+int __init bcma_bus_early_register(struct bcma_bus *bus,
+ struct bcma_device *core_cc,
+ struct bcma_device *core_mips);
/* scan.c */
int bcma_bus_scan(struct bcma_bus *bus);
+int __init bcma_bus_scan_early(struct bcma_bus *bus,
+ struct bcma_device_id *match,
+ struct bcma_device *core);
+void bcma_init_bus(struct bcma_bus *bus);
/* sprom.c */
int bcma_sprom_get(struct bcma_bus *bus);
+/* driver_chipcommon.c */
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+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);
+
#ifdef CONFIG_BCMA_HOST_PCI
/* host_pci.c */
extern int __init bcma_host_pci_init(void);
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index 4a04a49cc06d..189a97b51be9 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -110,6 +110,8 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
u32 bcma_core_dma_translation(struct bcma_device *core)
{
switch (core->bus->hosttype) {
+ case BCMA_HOSTTYPE_SOC:
+ return 0;
case BCMA_HOSTTYPE_PCI:
if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
return BCMA_DMA_TRANSLATION_DMA64_CMT;
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index 851e05bc948a..47cce9d69630 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -26,6 +26,9 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
u32 leddc_on = 10;
u32 leddc_off = 90;
+ if (cc->setup_done)
+ return;
+
if (cc->core->id.rev >= 11)
cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -52,6 +55,8 @@ 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->setup_done = true;
}
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
@@ -101,3 +106,51 @@ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
{
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
}
+
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
+{
+ unsigned int irq;
+ u32 baud_base;
+ u32 i;
+ unsigned int ccrev = cc->core->id.rev;
+ struct bcma_serial_port *ports = cc->serial_ports;
+
+ if (ccrev >= 11 && ccrev != 15) {
+ /* Fixed ALP clock */
+ baud_base = bcma_pmu_alp_clock(cc);
+ if (ccrev >= 21) {
+ /* Turn off UART clock before switching clocksource. */
+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
+ bcma_cc_read32(cc, BCMA_CC_CORECTL)
+ & ~BCMA_CC_CORECTL_UARTCLKEN);
+ }
+ /* Set the override bit so we don't divide it */
+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
+ bcma_cc_read32(cc, BCMA_CC_CORECTL)
+ | BCMA_CC_CORECTL_UARTCLK0);
+ if (ccrev >= 21) {
+ /* Re-enable the UART clock. */
+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
+ bcma_cc_read32(cc, BCMA_CC_CORECTL)
+ | BCMA_CC_CORECTL_UARTCLKEN);
+ }
+ } else {
+ pr_err("serial not supported on this device ccrev: 0x%x\n",
+ ccrev);
+ return;
+ }
+
+ irq = bcma_core_mips_irq(cc->core);
+
+ /* Determine the registers of the UARTs */
+ cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
+ for (i = 0; i < cc->nr_serial_ports; i++) {
+ ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
+ (i * 256);
+ ports[i].irq = irq;
+ ports[i].baud_base = baud_base;
+ ports[i].reg_shift = 0;
+ }
+}
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index fcc63db0ce75..2968d809d49f 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -11,20 +11,47 @@
#include "bcma_private.h"
#include <linux/bcma/bcma.h>
-static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
- u32 offset, u32 mask, u32 set)
+static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
{
- u32 value;
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+ bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+ return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
+}
- bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
+void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
+{
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+ bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_pll_write);
+
+void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
+ u32 set)
+{
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+ bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+ bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset);
+
+void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
+ u32 offset, u32 mask, u32 set)
+{
bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset);
bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
- value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
- value &= mask;
- value |= set;
- bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value);
- bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
+ bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset);
+
+void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
+ u32 set)
+{
+ bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset);
+ bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR);
+ bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set);
}
+EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
{
@@ -83,6 +110,24 @@ void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
}
}
+/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
+void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
+{
+ struct bcma_bus *bus = cc->core->bus;
+ u32 val;
+
+ val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL);
+ if (enable) {
+ val |= BCMA_CHIPCTL_4331_EXTPA_EN;
+ if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
+ val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
+ } else {
+ val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
+ val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
+ }
+ bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
+}
+
void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
{
struct bcma_bus *bus = cc->core->bus;
@@ -92,7 +137,7 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
break;
case 0x4331:
- pr_err("Enabling Ext PA lines not implemented\n");
+ /* BCM4331 workaround is SPROM-related, we put it in sprom.c */
break;
case 43224:
if (bus->chipinfo.rev == 0) {
@@ -136,3 +181,129 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
bcma_pmu_swreg_init(cc);
bcma_pmu_workarounds(cc);
}
+
+u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
+{
+ struct bcma_bus *bus = cc->core->bus;
+
+ switch (bus->chipinfo.id) {
+ case 0x4716:
+ case 0x4748:
+ case 47162:
+ case 0x4313:
+ case 0x5357:
+ case 0x4749:
+ case 53572:
+ /* always 20Mhz */
+ return 20000 * 1000;
+ case 0x5356:
+ case 0x5300:
+ /* always 25Mhz */
+ return 25000 * 1000;
+ default:
+ pr_warn("No ALP clock specified for %04X device, "
+ "pmu rev. %d, using default %d Hz\n",
+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
+ }
+ return BCMA_CC_PMU_ALP_CLOCK;
+}
+
+/* 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)
+{
+ u32 tmp, div, ndiv, p1, p2, fc;
+ struct bcma_bus *bus = cc->core->bus;
+
+ BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
+
+ BUG_ON(!m || m > 4);
+
+ if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) {
+ /* Detect failure in clock setting */
+ tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
+ if (tmp & 0x40000)
+ return 133 * 1000000;
+ }
+
+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF);
+ p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT;
+ p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT;
+
+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF);
+ div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) &
+ BCMA_CC_PPL_MDIV_MASK;
+
+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF);
+ ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
+
+ /* Do calculation in Mhz */
+ fc = bcma_pmu_alp_clock(cc) / 1000000;
+ fc = (p1 * ndiv * fc) / p2;
+
+ /* Return clock in Hertz */
+ return (fc / div) * 1000000;
+}
+
+/* query bus clock frequency for PMU-enabled chipcommon */
+u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
+{
+ struct bcma_bus *bus = cc->core->bus;
+
+ switch (bus->chipinfo.id) {
+ case 0x4716:
+ case 0x4748:
+ case 47162:
+ return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_SSB);
+ case 0x5356:
+ return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_SSB);
+ case 0x5357:
+ case 0x4749:
+ return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_SSB);
+ case 0x5300:
+ return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
+ BCMA_CC_PMU5_MAINPLL_SSB);
+ case 53572:
+ return 75000000;
+ default:
+ pr_warn("No backplane 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)
+{
+ struct bcma_bus *bus = cc->core->bus;
+
+ if (bus->chipinfo.id == 53572)
+ return 300000000;
+
+ if (cc->pmu.rev >= 5) {
+ u32 pll;
+ switch (bus->chipinfo.id) {
+ case 0x5356:
+ pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
+ break;
+ case 0x5357:
+ case 0x4749:
+ pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
+ break;
+ default:
+ pll = BCMA_CC_PMU4716_MAINPLL_PLL0;
+ break;
+ }
+
+ /* TODO: if (bus->chipinfo.id == 0x5300)
+ return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
+ return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
+ }
+
+ return bcma_pmu_get_clockcontrol(cc);
+}
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
new file mode 100644
index 000000000000..c3e9dff4224e
--- /dev/null
+++ b/drivers/bcma/driver_mips.c
@@ -0,0 +1,256 @@
+/*
+ * Broadcom specific AMBA
+ * Broadcom MIPS32 74K core driver
+ *
+ * Copyright 2009, Broadcom Corporation
+ * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
+ * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+
+#include <linux/bcma/bcma.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/time.h>
+
+/* The 47162a0 hangs when reading MIPS DMP registers registers */
+static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
+{
+ return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
+ dev->id.id == BCMA_CORE_MIPS_74K;
+}
+
+/* The 5357b0 hangs when reading USB20H DMP registers */
+static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
+{
+ return (dev->bus->chipinfo.id == 0x5357 ||
+ dev->bus->chipinfo.id == 0x4749) &&
+ dev->bus->chipinfo.pkg == 11 &&
+ dev->id.id == BCMA_CORE_USB20_HOST;
+}
+
+static inline u32 mips_read32(struct bcma_drv_mips *mcore,
+ u16 offset)
+{
+ return bcma_read32(mcore->core, offset);
+}
+
+static inline void mips_write32(struct bcma_drv_mips *mcore,
+ u16 offset,
+ u32 value)
+{
+ bcma_write32(mcore->core, offset, value);
+}
+
+static const u32 ipsflag_irq_mask[] = {
+ 0,
+ BCMA_MIPS_IPSFLAG_IRQ1,
+ BCMA_MIPS_IPSFLAG_IRQ2,
+ BCMA_MIPS_IPSFLAG_IRQ3,
+ BCMA_MIPS_IPSFLAG_IRQ4,
+};
+
+static const u32 ipsflag_irq_shift[] = {
+ 0,
+ BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
+ BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
+ BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
+ BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
+};
+
+static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
+{
+ u32 flag;
+
+ if (bcma_core_mips_bcm47162a0_quirk(dev))
+ return dev->core_index;
+ if (bcma_core_mips_bcm5357b0_quirk(dev))
+ return dev->core_index;
+ flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
+
+ return flag & 0x1F;
+}
+
+/* Get the MIPS IRQ assignment for a specified device.
+ * If unassigned, 0 is returned.
+ */
+unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+{
+ struct bcma_device *mdev = dev->bus->drv_mips.core;
+ u32 irqflag;
+ unsigned int irq;
+
+ irqflag = bcma_core_mips_irqflag(dev);
+
+ for (irq = 1; irq <= 4; irq++)
+ if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
+ (1 << irqflag))
+ return irq;
+
+ return 0;
+}
+EXPORT_SYMBOL(bcma_core_mips_irq);
+
+static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
+{
+ unsigned int oldirq = bcma_core_mips_irq(dev);
+ struct bcma_bus *bus = dev->bus;
+ struct bcma_device *mdev = bus->drv_mips.core;
+ u32 irqflag;
+
+ irqflag = bcma_core_mips_irqflag(dev);
+ BUG_ON(oldirq == 6);
+
+ dev->irq = irq + 2;
+
+ /* clear the old irq */
+ if (oldirq == 0)
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
+ ~(1 << irqflag));
+ else
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
+
+ /* assign the new one */
+ if (irq == 0) {
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
+ (1 << irqflag));
+ } else {
+ u32 oldirqflag = bcma_read32(mdev,
+ BCMA_MIPS_MIPS74K_INTMASK(irq));
+ if (oldirqflag) {
+ struct bcma_device *core;
+
+ /* backplane irq line is in use, find out who uses
+ * it and set user to irq 0
+ */
+ list_for_each_entry_reverse(core, &bus->cores, list) {
+ if ((1 << bcma_core_mips_irqflag(core)) ==
+ oldirqflag) {
+ bcma_core_mips_set_irq(core, 0);
+ break;
+ }
+ }
+ }
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
+ 1 << irqflag);
+ }
+
+ pr_info("set_irq: core 0x%04x, irq %d => %d\n",
+ dev->id.id, oldirq + 2, irq + 2);
+}
+
+static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
+{
+ int i;
+ static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
+ printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
+ for (i = 0; i <= 6; i++)
+ printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
+ printk("\n");
+}
+
+static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
+{
+ struct bcma_device *core;
+
+ list_for_each_entry_reverse(core, &bus->cores, list) {
+ bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
+ }
+}
+
+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);
+
+ pr_err("No PMU available, need this to get the cpu clock\n");
+ return 0;
+}
+EXPORT_SYMBOL(bcma_cpu_clock);
+
+static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
+{
+ struct bcma_bus *bus = mcore->core->bus;
+
+ switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
+ case BCMA_CC_FLASHT_STSER:
+ case BCMA_CC_FLASHT_ATSER:
+ pr_err("Serial flash not supported.\n");
+ break;
+ case BCMA_CC_FLASHT_PARA:
+ pr_info("found parallel flash.\n");
+ bus->drv_cc.pflash.window = 0x1c000000;
+ bus->drv_cc.pflash.window_size = 0x02000000;
+
+ if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
+ BCMA_CC_FLASH_CFG_DS) == 0)
+ bus->drv_cc.pflash.buswidth = 1;
+ else
+ bus->drv_cc.pflash.buswidth = 2;
+ break;
+ default:
+ pr_err("flash not supported.\n");
+ }
+}
+
+void bcma_core_mips_init(struct bcma_drv_mips *mcore)
+{
+ struct bcma_bus *bus;
+ struct bcma_device *core;
+ bus = mcore->core->bus;
+
+ pr_info("Initializing MIPS core...\n");
+
+ if (!mcore->setup_done)
+ mcore->assigned_irqs = 1;
+
+ /* Assign IRQs to all cores on the bus */
+ list_for_each_entry_reverse(core, &bus->cores, list) {
+ int mips_irq;
+ if (core->irq)
+ continue;
+
+ mips_irq = bcma_core_mips_irq(core);
+ if (mips_irq > 4)
+ core->irq = 0;
+ else
+ core->irq = mips_irq + 2;
+ if (core->irq > 5)
+ continue;
+ switch (core->id.id) {
+ case BCMA_CORE_PCI:
+ case BCMA_CORE_PCIE:
+ case BCMA_CORE_ETHERNET:
+ case BCMA_CORE_ETHERNET_GBIT:
+ case BCMA_CORE_MAC_GBIT:
+ case BCMA_CORE_80211:
+ case BCMA_CORE_USB20_HOST:
+ /* These devices get their own IRQ line if available,
+ * the rest goes on IRQ0
+ */
+ if (mcore->assigned_irqs <= 4)
+ bcma_core_mips_set_irq(core,
+ mcore->assigned_irqs++);
+ break;
+ }
+ }
+ pr_info("IRQ reconfiguration done\n");
+ bcma_core_mips_dump_irq(bus);
+
+ if (mcore->setup_done)
+ return;
+
+ bcma_chipco_serial_init(&bus->drv_cc);
+ bcma_core_mips_flash_detect(mcore);
+ mcore->setup_done = true;
+}
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c
index 25f3ddf33823..81f3d0a4b856 100644
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -173,7 +173,7 @@ static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
return false;
#ifdef CONFIG_SSB_DRIVER_PCICORE
- if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
+ if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI)
return false;
#endif /* CONFIG_SSB_DRIVER_PCICORE */
@@ -189,6 +189,9 @@ static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
void bcma_core_pci_init(struct bcma_drv_pci *pc)
{
+ if (pc->setup_done)
+ return;
+
if (bcma_core_pci_is_in_hostmode(pc)) {
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
bcma_core_pci_hostmode_init(pc);
@@ -198,6 +201,8 @@ void bcma_core_pci_init(struct bcma_drv_pci *pc)
} else {
bcma_core_pci_clientmode_init(pc);
}
+
+ pc->setup_done = true;
}
int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
@@ -205,7 +210,14 @@ int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
{
struct pci_dev *pdev = pc->core->bus->host_pci;
u32 coremask, tmp;
- int err;
+ int err = 0;
+
+ if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
+ /* This bcma device is not on a PCI host-bus. So the IRQs are
+ * not routed through the PCI core.
+ * So we must not enable routing through the PCI core. */
+ goto out;
+ }
err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
if (err)
diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c
new file mode 100644
index 000000000000..3c381fb8f9c4
--- /dev/null
+++ b/drivers/bcma/host_soc.c
@@ -0,0 +1,183 @@
+/*
+ * Broadcom specific AMBA
+ * System on Chip (SoC) Host
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include "scan.h"
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_soc.h>
+
+static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
+{
+ return readb(core->io_addr + offset);
+}
+
+static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
+{
+ return readw(core->io_addr + offset);
+}
+
+static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
+{
+ return readl(core->io_addr + offset);
+}
+
+static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
+ u8 value)
+{
+ writeb(value, core->io_addr + offset);
+}
+
+static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
+ u16 value)
+{
+ writew(value, core->io_addr + offset);
+}
+
+static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
+ u32 value)
+{
+ writel(value, core->io_addr + offset);
+}
+
+#ifdef CONFIG_BCMA_BLOCKIO
+static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ void __iomem *addr = core->io_addr + offset;
+
+ switch (reg_width) {
+ case sizeof(u8): {
+ u8 *buf = buffer;
+
+ while (count) {
+ *buf = __raw_readb(addr);
+ buf++;
+ count--;
+ }
+ break;
+ }
+ case sizeof(u16): {
+ __le16 *buf = buffer;
+
+ WARN_ON(count & 1);
+ while (count) {
+ *buf = (__force __le16)__raw_readw(addr);
+ buf++;
+ count -= 2;
+ }
+ break;
+ }
+ case sizeof(u32): {
+ __le32 *buf = buffer;
+
+ WARN_ON(count & 3);
+ while (count) {
+ *buf = (__force __le32)__raw_readl(addr);
+ buf++;
+ count -= 4;
+ }
+ break;
+ }
+ default:
+ WARN_ON(1);
+ }
+}
+
+static void bcma_host_soc_block_write(struct bcma_device *core,
+ const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ void __iomem *addr = core->io_addr + offset;
+
+ switch (reg_width) {
+ case sizeof(u8): {
+ const u8 *buf = buffer;
+
+ while (count) {
+ __raw_writeb(*buf, addr);
+ buf++;
+ count--;
+ }
+ break;
+ }
+ case sizeof(u16): {
+ const __le16 *buf = buffer;
+
+ WARN_ON(count & 1);
+ while (count) {
+ __raw_writew((__force u16)(*buf), addr);
+ buf++;
+ count -= 2;
+ }
+ break;
+ }
+ case sizeof(u32): {
+ const __le32 *buf = buffer;
+
+ WARN_ON(count & 3);
+ while (count) {
+ __raw_writel((__force u32)(*buf), addr);
+ buf++;
+ count -= 4;
+ }
+ break;
+ }
+ default:
+ WARN_ON(1);
+ }
+}
+#endif /* CONFIG_BCMA_BLOCKIO */
+
+static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
+{
+ return readl(core->io_wrap + offset);
+}
+
+static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
+ u32 value)
+{
+ writel(value, core->io_wrap + offset);
+}
+
+const struct bcma_host_ops bcma_host_soc_ops = {
+ .read8 = bcma_host_soc_read8,
+ .read16 = bcma_host_soc_read16,
+ .read32 = bcma_host_soc_read32,
+ .write8 = bcma_host_soc_write8,
+ .write16 = bcma_host_soc_write16,
+ .write32 = bcma_host_soc_write32,
+#ifdef CONFIG_BCMA_BLOCKIO
+ .block_read = bcma_host_soc_block_read,
+ .block_write = bcma_host_soc_block_write,
+#endif
+ .aread32 = bcma_host_soc_aread32,
+ .awrite32 = bcma_host_soc_awrite32,
+};
+
+int __init bcma_host_soc_register(struct bcma_soc *soc)
+{
+ struct bcma_bus *bus = &soc->bus;
+ int err;
+
+ /* iomap only first core. We have to read some register on this core
+ * to scan the bus.
+ */
+ bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
+ if (!bus->mmio)
+ return -ENOMEM;
+
+ /* Host specific */
+ bus->hosttype = BCMA_HOSTTYPE_SOC;
+ bus->ops = &bcma_host_soc_ops;
+
+ /* Register */
+ err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
+ if (err)
+ iounmap(bus->mmio);
+
+ return err;
+}
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 73b7b1a18fab..8c09c3e547cd 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -68,6 +68,10 @@ static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
static void bcma_release_core_dev(struct device *dev)
{
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+ if (core->io_addr)
+ iounmap(core->io_addr);
+ if (core->io_wrap)
+ iounmap(core->io_wrap);
kfree(core);
}
@@ -82,6 +86,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
case BCMA_CORE_CHIPCOMMON:
case BCMA_CORE_PCI:
case BCMA_CORE_PCIE:
+ case BCMA_CORE_MIPS_74K:
continue;
}
@@ -95,7 +100,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
core->dma_dev = &bus->host_pci->dev;
core->irq = bus->host_pci->irq;
break;
- case BCMA_HOSTTYPE_NONE:
+ case BCMA_HOSTTYPE_SOC:
+ core->dev.dma_mask = &core->dev.coherent_dma_mask;
+ core->dma_dev = &core->dev;
+ break;
case BCMA_HOSTTYPE_SDIO:
break;
}
@@ -142,6 +150,13 @@ int bcma_bus_register(struct bcma_bus *bus)
bcma_core_chipcommon_init(&bus->drv_cc);
}
+ /* 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);
+ }
+
/* Init PCIE core */
core = bcma_find_core(bus, BCMA_CORE_PCIE);
if (core) {
@@ -171,6 +186,59 @@ void bcma_bus_unregister(struct bcma_bus *bus)
bcma_unregister_cores(bus);
}
+int __init bcma_bus_early_register(struct bcma_bus *bus,
+ struct bcma_device *core_cc,
+ struct bcma_device *core_mips)
+{
+ int err;
+ struct bcma_device *core;
+ struct bcma_device_id match;
+
+ bcma_init_bus(bus);
+
+ match.manuf = BCMA_MANUF_BCM;
+ match.id = BCMA_CORE_CHIPCOMMON;
+ match.class = BCMA_CL_SIM;
+ match.rev = BCMA_ANY_REV;
+
+ /* Scan for chip common core */
+ err = bcma_bus_scan_early(bus, &match, core_cc);
+ if (err) {
+ pr_err("Failed to scan for common core: %d\n", err);
+ return -1;
+ }
+
+ match.manuf = BCMA_MANUF_MIPS;
+ match.id = BCMA_CORE_MIPS_74K;
+ match.class = BCMA_CL_SIM;
+ match.rev = BCMA_ANY_REV;
+
+ /* Scan for mips core */
+ err = bcma_bus_scan_early(bus, &match, core_mips);
+ if (err) {
+ pr_err("Failed to scan for mips core: %d\n", err);
+ return -1;
+ }
+
+ /* Init CC core */
+ core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
+ if (core) {
+ bus->drv_cc.core = core;
+ bcma_core_chipcommon_init(&bus->drv_cc);
+ }
+
+ /* 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);
+ }
+
+ pr_info("Early bus registered\n");
+
+ return 0;
+}
+
int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
{
drv->drv.name = drv->name;
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 40d7dcce8933..cad994857683 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -200,18 +200,162 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
return addrl;
}
-int bcma_bus_scan(struct bcma_bus *bus)
+static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
+ u16 index)
{
- u32 erombase;
- u32 __iomem *eromptr, *eromend;
+ struct bcma_device *core;
+ list_for_each_entry(core, &bus->cores, list) {
+ if (core->core_index == index)
+ return core;
+ }
+ return NULL;
+}
+
+static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
+ struct bcma_device_id *match, int core_num,
+ struct bcma_device *core)
+{
+ s32 tmp;
+ u8 i, j;
s32 cia, cib;
u8 ports[2], wrappers[2];
+ /* get CIs */
+ cia = bcma_erom_get_ci(bus, eromptr);
+ if (cia < 0) {
+ bcma_erom_push_ent(eromptr);
+ if (bcma_erom_is_end(bus, eromptr))
+ return -ESPIPE;
+ return -EILSEQ;
+ }
+ cib = bcma_erom_get_ci(bus, eromptr);
+ if (cib < 0)
+ return -EILSEQ;
+
+ /* parse CIs */
+ core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
+ core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
+ core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
+ ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
+ ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
+ wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
+ wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
+ core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
+
+ if (((core->id.manuf == BCMA_MANUF_ARM) &&
+ (core->id.id == 0xFFF)) ||
+ (ports[1] == 0)) {
+ bcma_erom_skip_component(bus, eromptr);
+ return -ENXIO;
+ }
+
+ /* check if component is a core at all */
+ if (wrappers[0] + wrappers[1] == 0) {
+ /* we could save addrl of the router
+ if (cid == BCMA_CORE_OOB_ROUTER)
+ */
+ bcma_erom_skip_component(bus, eromptr);
+ return -ENXIO;
+ }
+
+ if (bcma_erom_is_bridge(bus, eromptr)) {
+ bcma_erom_skip_component(bus, eromptr);
+ return -ENXIO;
+ }
+
+ if (bcma_find_core_by_index(bus, core_num)) {
+ bcma_erom_skip_component(bus, eromptr);
+ return -ENODEV;
+ }
+
+ if (match && ((match->manuf != BCMA_ANY_MANUF &&
+ match->manuf != core->id.manuf) ||
+ (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
+ (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
+ (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
+ )) {
+ bcma_erom_skip_component(bus, eromptr);
+ return -ENODEV;
+ }
+
+ /* get & parse master ports */
+ for (i = 0; i < ports[0]; i++) {
+ s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
+ if (mst_port_d < 0)
+ return -EILSEQ;
+ }
+
+ /* get & parse slave ports */
+ for (i = 0; i < ports[1]; i++) {
+ for (j = 0; ; j++) {
+ tmp = bcma_erom_get_addr_desc(bus, eromptr,
+ SCAN_ADDR_TYPE_SLAVE, i);
+ if (tmp < 0) {
+ /* no more entries for port _i_ */
+ /* pr_debug("erom: slave port %d "
+ * "has %d descriptors\n", i, j); */
+ break;
+ } else {
+ if (i == 0 && j == 0)
+ core->addr = tmp;
+ }
+ }
+ }
+
+ /* get & parse master wrappers */
+ for (i = 0; i < wrappers[0]; i++) {
+ for (j = 0; ; j++) {
+ tmp = bcma_erom_get_addr_desc(bus, eromptr,
+ SCAN_ADDR_TYPE_MWRAP, i);
+ if (tmp < 0) {
+ /* no more entries for port _i_ */
+ /* pr_debug("erom: master wrapper %d "
+ * "has %d descriptors\n", i, j); */
+ break;
+ } else {
+ if (i == 0 && j == 0)
+ core->wrap = tmp;
+ }
+ }
+ }
+
+ /* get & parse slave wrappers */
+ for (i = 0; i < wrappers[1]; i++) {
+ u8 hack = (ports[1] == 1) ? 0 : 1;
+ for (j = 0; ; j++) {
+ tmp = bcma_erom_get_addr_desc(bus, eromptr,
+ SCAN_ADDR_TYPE_SWRAP, i + hack);
+ if (tmp < 0) {
+ /* no more entries for port _i_ */
+ /* pr_debug("erom: master wrapper %d "
+ * has %d descriptors\n", i, j); */
+ break;
+ } else {
+ if (wrappers[0] == 0 && !i && !j)
+ core->wrap = tmp;
+ }
+ }
+ }
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+ core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE);
+ if (!core->io_addr)
+ return -ENOMEM;
+ core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE);
+ if (!core->io_wrap) {
+ iounmap(core->io_addr);
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+void bcma_init_bus(struct bcma_bus *bus)
+{
s32 tmp;
- u8 i, j;
- int err;
+ if (bus->init_done)
+ return;
INIT_LIST_HEAD(&bus->cores);
bus->nr_cores = 0;
@@ -222,9 +366,27 @@ int bcma_bus_scan(struct bcma_bus *bus)
bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+ bus->init_done = true;
+}
+
+int bcma_bus_scan(struct bcma_bus *bus)
+{
+ u32 erombase;
+ u32 __iomem *eromptr, *eromend;
+
+ int err, core_num = 0;
+
+ bcma_init_bus(bus);
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
- eromptr = bus->mmio;
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+ eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
+ if (!eromptr)
+ return -ENOMEM;
+ } else {
+ eromptr = bus->mmio;
+ }
+
eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
bcma_scan_switch_core(bus, erombase);
@@ -236,125 +398,89 @@ int bcma_bus_scan(struct bcma_bus *bus)
INIT_LIST_HEAD(&core->list);
core->bus = bus;
- /* get CIs */
- cia = bcma_erom_get_ci(bus, &eromptr);
- if (cia < 0) {
- bcma_erom_push_ent(&eromptr);
- if (bcma_erom_is_end(bus, &eromptr))
- break;
- err= -EILSEQ;
- goto out;
- }
- cib = bcma_erom_get_ci(bus, &eromptr);
- if (cib < 0) {
- err= -EILSEQ;
- goto out;
- }
-
- /* parse CIs */
- core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
- core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
- core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
- ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
- ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
- wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
- wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
- core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
-
- if (((core->id.manuf == BCMA_MANUF_ARM) &&
- (core->id.id == 0xFFF)) ||
- (ports[1] == 0)) {
- bcma_erom_skip_component(bus, &eromptr);
+ err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
+ if (err == -ENODEV) {
+ core_num++;
continue;
- }
-
- /* check if component is a core at all */
- if (wrappers[0] + wrappers[1] == 0) {
- /* we could save addrl of the router
- if (cid == BCMA_CORE_OOB_ROUTER)
- */
- bcma_erom_skip_component(bus, &eromptr);
+ } else if (err == -ENXIO)
continue;
- }
+ else if (err == -ESPIPE)
+ break;
+ else if (err < 0)
+ return err;
- if (bcma_erom_is_bridge(bus, &eromptr)) {
- bcma_erom_skip_component(bus, &eromptr);
- continue;
- }
+ core->core_index = core_num++;
+ bus->nr_cores++;
- /* get & parse master ports */
- for (i = 0; i < ports[0]; i++) {
- u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr);
- if (mst_port_d < 0) {
- err= -EILSEQ;
- goto out;
- }
- }
+ pr_info("Core %d found: %s "
+ "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
+ core->core_index, bcma_device_name(&core->id),
+ core->id.manuf, core->id.id, core->id.rev,
+ core->id.class);
- /* get & parse slave ports */
- for (i = 0; i < ports[1]; i++) {
- for (j = 0; ; j++) {
- tmp = bcma_erom_get_addr_desc(bus, &eromptr,
- SCAN_ADDR_TYPE_SLAVE, i);
- if (tmp < 0) {
- /* no more entries for port _i_ */
- /* pr_debug("erom: slave port %d "
- * "has %d descriptors\n", i, j); */
- break;
- } else {
- if (i == 0 && j == 0)
- core->addr = tmp;
- }
- }
- }
+ list_add(&core->list, &bus->cores);
+ }
- /* get & parse master wrappers */
- for (i = 0; i < wrappers[0]; i++) {
- for (j = 0; ; j++) {
- tmp = bcma_erom_get_addr_desc(bus, &eromptr,
- SCAN_ADDR_TYPE_MWRAP, i);
- if (tmp < 0) {
- /* no more entries for port _i_ */
- /* pr_debug("erom: master wrapper %d "
- * "has %d descriptors\n", i, j); */
- break;
- } else {
- if (i == 0 && j == 0)
- core->wrap = tmp;
- }
- }
- }
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC)
+ iounmap(eromptr);
- /* get & parse slave wrappers */
- for (i = 0; i < wrappers[1]; i++) {
- u8 hack = (ports[1] == 1) ? 0 : 1;
- for (j = 0; ; j++) {
- tmp = bcma_erom_get_addr_desc(bus, &eromptr,
- SCAN_ADDR_TYPE_SWRAP, i + hack);
- if (tmp < 0) {
- /* no more entries for port _i_ */
- /* pr_debug("erom: master wrapper %d "
- * has %d descriptors\n", i, j); */
- break;
- } else {
- if (wrappers[0] == 0 && !i && !j)
- core->wrap = tmp;
- }
- }
- }
+ return 0;
+}
+
+int __init bcma_bus_scan_early(struct bcma_bus *bus,
+ struct bcma_device_id *match,
+ struct bcma_device *core)
+{
+ u32 erombase;
+ u32 __iomem *eromptr, *eromend;
+
+ int err = -ENODEV;
+ int core_num = 0;
+
+ erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+ eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
+ if (!eromptr)
+ return -ENOMEM;
+ } else {
+ eromptr = bus->mmio;
+ }
+
+ eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
+
+ bcma_scan_switch_core(bus, erombase);
+
+ while (eromptr < eromend) {
+ memset(core, 0, sizeof(*core));
+ INIT_LIST_HEAD(&core->list);
+ core->bus = bus;
+ err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
+ if (err == -ENODEV) {
+ core_num++;
+ continue;
+ } else if (err == -ENXIO)
+ continue;
+ else if (err == -ESPIPE)
+ break;
+ else if (err < 0)
+ return err;
+
+ core->core_index = core_num++;
+ bus->nr_cores++;
pr_info("Core %d found: %s "
"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
- bus->nr_cores, bcma_device_name(&core->id),
+ core->core_index, bcma_device_name(&core->id),
core->id.manuf, core->id.id, core->id.rev,
core->id.class);
- core->core_index = bus->nr_cores++;
list_add(&core->list, &bus->cores);
- continue;
-out:
- return err;
+ err = 0;
+ break;
}
- return 0;
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC)
+ iounmap(eromptr);
+
+ return err;
}
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index 8b5b7856abe3..d7292390d236 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -133,6 +133,15 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
}
+
+ bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
+
+ bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
+ bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
+ bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
+ bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
+
+ bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
}
int bcma_sprom_get(struct bcma_bus *bus)
@@ -152,6 +161,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
if (!sprom)
return -ENOMEM;
+ if (bus->chipinfo.id == 0x4331)
+ bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
+
/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
* According to brcm80211 this applies to cards with PCIe rev >= 6
* TODO: understand this condition and use it */
@@ -159,6 +171,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
BCMA_CC_SPROM_PCIE6;
bcma_sprom_read(bus, offset, sprom);
+ if (bus->chipinfo.id == 0x4331)
+ bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
+
err = bcma_sprom_valid(sprom);
if (err)
goto out;
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 7b976296b564..912f585a760f 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -378,15 +378,14 @@ static struct page **bm_realloc_pages(struct drbd_bitmap *b, unsigned long want)
* thread. As we have no disk yet, we are not in the IO path,
* not even the IO path of the peer. */
bytes = sizeof(struct page *)*want;
- new_pages = kmalloc(bytes, GFP_KERNEL);
+ new_pages = kzalloc(bytes, GFP_KERNEL);
if (!new_pages) {
- new_pages = vmalloc(bytes);
+ new_pages = vzalloc(bytes);
if (!new_pages)
return NULL;
vmalloced = 1;
}
- memset(new_pages, 0, bytes);
if (want >= have) {
for (i = 0; i < have; i++)
new_pages[i] = old_pages[i];
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index ef2ceed3be4b..1706d60b8c99 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -28,7 +28,6 @@
#include <linux/compiler.h>
#include <linux/types.h>
-#include <linux/version.h>
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/bitops.h>
@@ -928,7 +927,7 @@ struct drbd_md {
#define NL_INT64(pn,pr,member) __u64 member;
#define NL_BIT(pn,pr,member) unsigned member:1;
#define NL_STRING(pn,pr,member,len) unsigned char member[len]; int member ## _len;
-#include "linux/drbd_nl.h"
+#include <linux/drbd_nl.h>
struct drbd_backing_dev {
struct block_device *backing_bdev;
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 0feab261e295..af2a25049bce 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -94,7 +94,7 @@ static int name ## _from_tags(struct drbd_conf *mdev, \
arg->member ## _len = dlen; \
memcpy(arg->member, tags, min_t(size_t, dlen, len)); \
break;
-#include "linux/drbd_nl.h"
+#include <linux/drbd_nl.h>
/* Generate the struct to tag_list functions */
#define NL_PACKET(name, number, fields) \
@@ -129,7 +129,7 @@ name ## _to_tags(struct drbd_conf *mdev, \
put_unaligned(arg->member ## _len, tags++); \
memcpy(tags, arg->member, arg->member ## _len); \
tags = (unsigned short *)((char *)tags + arg->member ## _len);
-#include "linux/drbd_nl.h"
+#include <linux/drbd_nl.h>
void drbd_bcast_ev_helper(struct drbd_conf *mdev, char *helper_name);
void drbd_nl_send_reply(struct cn_msg *, int);
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 15f65b5f3fc7..65cc424359b0 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -192,7 +192,7 @@ static ssize_t rbd_snap_add(struct device *dev,
const char *buf,
size_t count);
static void __rbd_remove_snap_dev(struct rbd_device *rbd_dev,
- struct rbd_snap *snap);;
+ struct rbd_snap *snap);
static struct rbd_device *dev_to_rbd(struct device *dev)
@@ -260,7 +260,7 @@ static struct rbd_client *rbd_client_create(struct ceph_options *opt,
kref_init(&rbdc->kref);
INIT_LIST_HEAD(&rbdc->node);
- rbdc->client = ceph_create_client(opt, rbdc);
+ rbdc->client = ceph_create_client(opt, rbdc, 0, 0);
if (IS_ERR(rbdc->client))
goto out_rbdc;
opt = NULL; /* Now rbdc->client is responsible for opt */
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 079c08808d8a..e7a5750a93d9 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -8,10 +8,13 @@
#include <linux/scatterlist.h>
#include <linux/string_helpers.h>
#include <scsi/scsi_cmnd.h>
+#include <linux/idr.h>
#define PART_BITS 4
-static int major, index;
+static int major;
+static DEFINE_IDA(vd_index_ida);
+
struct workqueue_struct *virtblk_wq;
struct virtio_blk
@@ -35,6 +38,9 @@ struct virtio_blk
/* What host tells us, plus 2 for header & tailer. */
unsigned int sg_elems;
+ /* Ida index - used to track minor number allocations. */
+ int index;
+
/* Scatterlist: can be too big for stack. */
struct scatterlist sg[/*sg_elems*/];
};
@@ -276,6 +282,11 @@ static int index_to_minor(int index)
return index << PART_BITS;
}
+static int minor_to_index(int minor)
+{
+ return minor >> PART_BITS;
+}
+
static ssize_t virtblk_serial_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -341,14 +352,17 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
{
struct virtio_blk *vblk;
struct request_queue *q;
- int err;
+ int err, index;
u64 cap;
u32 v, blk_size, sg_elems, opt_io_size;
u16 min_io_size;
u8 physical_block_exp, alignment_offset;
- if (index_to_minor(index) >= 1 << MINORBITS)
- return -ENOSPC;
+ err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
+ GFP_KERNEL);
+ if (err < 0)
+ goto out;
+ index = err;
/* We need to know how many segments before we allocate. */
err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
@@ -365,7 +379,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
sizeof(vblk->sg[0]) * sg_elems, GFP_KERNEL);
if (!vblk) {
err = -ENOMEM;
- goto out;
+ goto out_free_index;
}
INIT_LIST_HEAD(&vblk->reqs);
@@ -421,7 +435,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
vblk->disk->private_data = vblk;
vblk->disk->fops = &virtblk_fops;
vblk->disk->driverfs_dev = &vdev->dev;
- index++;
+ vblk->index = index;
/* configure queue flush support */
if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH))
@@ -516,6 +530,8 @@ out_free_vq:
vdev->config->del_vqs(vdev);
out_free_vblk:
kfree(vblk);
+out_free_index:
+ ida_simple_remove(&vd_index_ida, index);
out:
return err;
}
@@ -523,6 +539,7 @@ out:
static void __devexit virtblk_remove(struct virtio_device *vdev)
{
struct virtio_blk *vblk = vdev->priv;
+ int index = vblk->index;
flush_work(&vblk->config_work);
@@ -538,6 +555,7 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
mempool_destroy(vblk->pool);
vdev->config->del_vqs(vdev);
kfree(vblk);
+ ida_simple_remove(&vd_index_ida, index);
}
static const struct virtio_device_id id_table[] = {
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 2330a9ad5e95..1540792b1e54 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -396,7 +396,7 @@ static int xen_blkbk_map(struct blkif_request *req,
continue;
ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr),
- blkbk->pending_page(pending_req, i), false);
+ blkbk->pending_page(pending_req, i), NULL);
if (ret) {
pr_alert(DRV_PFX "Failed to install M2P override for %lx (ret: %d)\n",
(unsigned long)map[i].dev_bus_addr, ret);
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index 00c57c90e2d6..c4bd34063ecc 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -27,7 +27,6 @@
#ifndef __XEN_BLKIF__BACKEND__COMMON_H__
#define __XEN_BLKIF__BACKEND__COMMON_H__
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 7f521d4ac657..c827d737ccee 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -81,7 +81,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = {
.io_port_2 = 0x7a,
};
-static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
+static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "sd8688_helper.bin",
.firmware = "sd8688.bin",
.reg = &btmrvl_reg_8688,
@@ -98,7 +98,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8688 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
- .driver_data = (unsigned long) &btmrvl_sdio_sd6888 },
+ .driver_data = (unsigned long) &btmrvl_sdio_sd8688 },
/* Marvell SD8787 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 9cbac6b445e1..f9b726091ad0 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -60,6 +60,9 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
+ /* Broadcom SoftSailing reporting vendor specific */
+ { USB_DEVICE(0x05ac, 0x21e1) },
+
/* Apple MacBookPro 7,1 */
{ USB_DEVICE(0x05ac, 0x8213) },
@@ -708,8 +711,7 @@ static int btusb_send_frame(struct sk_buff *skb)
break;
case HCI_ACLDATA_PKT:
- if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 &&
- hdev->conn_hash.le_num < 1))
+ if (!data->bulk_tx_ep)
return -ENODEV;
urb = usb_alloc_urb(0, GFP_ATOMIC);
@@ -1116,7 +1118,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
return 0;
spin_lock_irq(&data->txlock);
- if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) {
+ if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) {
set_bit(BTUSB_SUSPENDING, &data->flags);
spin_unlock_irq(&data->txlock);
} else {
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 423fd56bf612..43643033a3ae 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -298,7 +298,7 @@ if RTC_LIB=n
config RTC
tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \
- && !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN
+ && !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN && !UML
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -346,7 +346,7 @@ config JS_RTC
config GEN_RTC
tristate "Generic /dev/rtc emulation"
- depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN
+ depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN && !UML
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -490,7 +490,7 @@ config SCx200_GPIO
config PC8736x_GPIO
tristate "NatSemi PC8736x GPIO Support"
- depends on X86_32
+ depends on X86_32 && !UML
default SCx200_GPIO # mostly N
select NSC_GPIO # needed for support routines
help
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index f27d0d0816d3..4b71647782d0 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -171,7 +171,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
}
got_gatt = 1;
- bridge->key_list = vmalloc(PAGE_SIZE * 4);
+ bridge->key_list = vzalloc(PAGE_SIZE * 4);
if (bridge->key_list == NULL) {
dev_err(&bridge->dev->dev,
"can't allocate memory for key lists\n");
@@ -181,7 +181,6 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
got_keylist = 1;
/* FIXME vmalloc'd memory not guaranteed contiguous */
- memset(bridge->key_list, 0, PAGE_SIZE * 4);
if (bridge->driver->configure()) {
dev_err(&bridge->dev->dev, "error configuring host chipset\n");
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 056b289a1e89..3695773ce7c3 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -336,7 +336,8 @@ hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type)
off_t j, io_pg_start;
int io_pg_count;
- if (type != 0 || mem->type != 0) {
+ if (type != mem->type ||
+ agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
return -EINVAL;
}
@@ -380,7 +381,8 @@ hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type)
struct _hp_private *hp = &hp_private;
int i, io_pg_start, io_pg_count;
- if (type != 0 || mem->type != 0) {
+ if (type != mem->type ||
+ agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
return -EINVAL;
}
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 85151019dde1..66cd0b8096ca 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -30,10 +30,10 @@
/*
* If we have Intel graphics, we're not going to have anything other than
* an Intel IOMMU. So make the correct use of the PCI DMA API contingent
- * on the Intel IOMMU support (CONFIG_DMAR).
+ * on the Intel IOMMU support (CONFIG_INTEL_IOMMU).
* Only newer chipsets need to bother with this, of course.
*/
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
#define USE_PCI_DMA_API 1
#else
#define USE_PCI_DMA_API 0
@@ -923,6 +923,9 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem,
{
int ret = -EINVAL;
+ if (intel_private.base.do_idle_maps)
+ return -ENODEV;
+
if (intel_private.clear_fake_agp) {
int start = intel_private.base.stolen_size / PAGE_SIZE;
int end = intel_private.base.gtt_mappable_entries;
@@ -985,6 +988,9 @@ static int intel_fake_agp_remove_entries(struct agp_memory *mem,
if (mem->page_count == 0)
return 0;
+ if (intel_private.base.do_idle_maps)
+ return -ENODEV;
+
intel_gtt_clear_range(pg_start, mem->page_count);
if (intel_private.base.needs_dmar) {
@@ -1177,6 +1183,25 @@ static void gen6_cleanup(void)
{
}
+/* Certain Gen5 chipsets require require idling the GPU before
+ * unmapping anything from the GTT when VT-d is enabled.
+ */
+extern int intel_iommu_gfx_mapped;
+static inline int needs_idle_maps(void)
+{
+ const unsigned short gpu_devid = intel_private.pcidev->device;
+
+ /* Query intel_iommu to see if we need the workaround. Presumably that
+ * was loaded first.
+ */
+ if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB ||
+ gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
+ intel_iommu_gfx_mapped)
+ return 1;
+
+ return 0;
+}
+
static int i9xx_setup(void)
{
u32 reg_addr;
@@ -1211,6 +1236,9 @@ static int i9xx_setup(void)
intel_private.gtt_bus_addr = reg_addr + gtt_offset;
}
+ if (needs_idle_maps());
+ intel_private.base.do_idle_maps = 1;
+
intel_i9xx_setup_flush();
return 0;
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index a7346ab97a3c..f4837a893dfa 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -40,10 +40,7 @@
#define APM_MINOR_DEV 134
/*
- * See Documentation/Config.help for the configuration options.
- *
- * Various options can be changed at boot time as follows:
- * (We allow underscores for compatibility with the modules code)
+ * One option can be changed at boot time as follows:
* apm=on/off enable/disable APM
*/
@@ -300,17 +297,13 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)
/*
* Wait for the suspend/resume to complete. If there
* are pending acknowledges, we wait here for them.
+ * wait_event_freezable() is interruptible and pending
+ * signal can cause busy looping. We aren't doing
+ * anything critical, chill a bit on each iteration.
*/
- freezer_do_not_count();
-
- wait_event(apm_suspend_waitqueue,
- as->suspend_state == SUSPEND_DONE);
-
- /*
- * Since we are waiting until the suspend is done, the
- * try_to_freeze() in freezer_count() will not trigger
- */
- freezer_count();
+ while (wait_event_freezable(apm_suspend_waitqueue,
+ as->suspend_state == SUSPEND_DONE))
+ msleep(10);
break;
case SUSPEND_ACKTO:
as->suspend_result = -ETIMEDOUT;
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 1d2ebc7a4947..0689bf6b0183 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -60,6 +60,19 @@ config HW_RANDOM_AMD
If unsure, say Y.
+config HW_RANDOM_ATMEL
+ tristate "Atmel Random Number Generator support"
+ depends on HW_RANDOM && ARCH_AT91SAM9G45
+ default HW_RANDOM
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on Atmel AT91 devices.
+
+ To compile this driver as a module, choose M here: the
+ module will be called atmel-rng.
+
+ If unsure, say Y.
+
config HW_RANDOM_GEODE
tristate "AMD Geode HW Random Number Generator support"
depends on HW_RANDOM && X86_32 && PCI
@@ -222,3 +235,18 @@ config HW_RANDOM_PPC4XX
module will be called ppc4xx-rng.
If unsure, say N.
+
+config UML_RANDOM
+ depends on UML
+ tristate "Hardware random number generator"
+ help
+ This option enables UML's "hardware" random number generator. It
+ attaches itself to the host's /dev/random, supplying as much entropy
+ as the host has, rather than the small amount the UML gets from its
+ own drivers. It registers itself as a standard hardware random number
+ generator, major 10, minor 183, and the canonical device name is
+ /dev/hwrng.
+ The way to make use of this is to install the rng-tools package
+ (check your distro, or download from
+ http://sourceforge.net/projects/gkernel/). rngd periodically reads
+ /dev/hwrng and injects the entropy into /dev/random.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index c88f244c8a71..b2ff5265a996 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -7,6 +7,7 @@ rng-core-y := core.o
obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
+obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
n2-rng-y := n2-drv.o n2-asm.o
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
new file mode 100644
index 000000000000..241df2e76aba
--- /dev/null
+++ b/drivers/char/hw_random/atmel-rng.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2011 Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/hw_random.h>
+#include <linux/platform_device.h>
+
+#define TRNG_CR 0x00
+#define TRNG_ISR 0x1c
+#define TRNG_ODATA 0x50
+
+#define TRNG_KEY 0x524e4700 /* RNG */
+
+struct atmel_trng {
+ struct clk *clk;
+ void __iomem *base;
+ struct hwrng rng;
+};
+
+static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max,
+ bool wait)
+{
+ struct atmel_trng *trng = container_of(rng, struct atmel_trng, rng);
+ u32 *data = buf;
+
+ /* data ready? */
+ if (readl(trng->base + TRNG_ODATA) & 1) {
+ *data = readl(trng->base + TRNG_ODATA);
+ return 4;
+ } else
+ return 0;
+}
+
+static int atmel_trng_probe(struct platform_device *pdev)
+{
+ struct atmel_trng *trng;
+ struct resource *res;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
+ if (!trng)
+ return -ENOMEM;
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), pdev->name))
+ return -EBUSY;
+
+ trng->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!trng->base)
+ return -EBUSY;
+
+ trng->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(trng->clk))
+ return PTR_ERR(trng->clk);
+
+ ret = clk_enable(trng->clk);
+ if (ret)
+ goto err_enable;
+
+ writel(TRNG_KEY | 1, trng->base + TRNG_CR);
+ trng->rng.name = pdev->name;
+ trng->rng.read = atmel_trng_read;
+
+ ret = hwrng_register(&trng->rng);
+ if (ret)
+ goto err_register;
+
+ platform_set_drvdata(pdev, trng);
+
+ return 0;
+
+err_register:
+ clk_disable(trng->clk);
+err_enable:
+ clk_put(trng->clk);
+
+ return ret;
+}
+
+static int __devexit atmel_trng_remove(struct platform_device *pdev)
+{
+ struct atmel_trng *trng = platform_get_drvdata(pdev);
+
+ hwrng_unregister(&trng->rng);
+
+ writel(TRNG_KEY, trng->base + TRNG_CR);
+ clk_disable(trng->clk);
+ clk_put(trng->clk);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int atmel_trng_suspend(struct device *dev)
+{
+ struct atmel_trng *trng = dev_get_drvdata(dev);
+
+ clk_disable(trng->clk);
+
+ return 0;
+}
+
+static int atmel_trng_resume(struct device *dev)
+{
+ struct atmel_trng *trng = dev_get_drvdata(dev);
+
+ return clk_enable(trng->clk);
+}
+
+static const struct dev_pm_ops atmel_trng_pm_ops = {
+ .suspend = atmel_trng_suspend,
+ .resume = atmel_trng_resume,
+};
+#endif /* CONFIG_PM */
+
+static struct platform_driver atmel_trng_driver = {
+ .probe = atmel_trng_probe,
+ .remove = __devexit_p(atmel_trng_remove),
+ .driver = {
+ .name = "atmel-trng",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &atmel_trng_pm_ops,
+#endif /* CONFIG_PM */
+ },
+};
+
+static int __init atmel_trng_init(void)
+{
+ return platform_driver_register(&atmel_trng_driver);
+}
+module_init(atmel_trng_init);
+
+static void __exit atmel_trng_exit(void)
+{
+ platform_driver_unregister(&atmel_trng_driver);
+}
+module_exit(atmel_trng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("Atmel true random number generator driver");
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 3302586655c4..c2917ffad2c2 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -65,6 +65,7 @@
* mechanism for it at that time.
*/
#include <asm/kdebug.h>
+#include <asm/nmi.h>
#define HAVE_DIE_NMI
#endif
@@ -1077,17 +1078,8 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
#ifdef HAVE_DIE_NMI
static int
-ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
+ipmi_nmi(unsigned int val, struct pt_regs *regs)
{
- struct die_args *args = data;
-
- if (val != DIE_NMIUNKNOWN)
- return NOTIFY_OK;
-
- /* Hack, if it's a memory or I/O error, ignore it. */
- if (args->err & 0xc0)
- return NOTIFY_OK;
-
/*
* If we get here, it's an NMI that's not a memory or I/O
* error. We can't truly tell if it's from IPMI or not
@@ -1097,15 +1089,15 @@ ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
if (testing_nmi) {
testing_nmi = 2;
- return NOTIFY_STOP;
+ return NMI_HANDLED;
}
/* If we are not expecting a timeout, ignore it. */
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
- return NOTIFY_OK;
+ return NMI_DONE;
if (preaction_val != WDOG_PRETIMEOUT_NMI)
- return NOTIFY_OK;
+ return NMI_DONE;
/*
* If no one else handled the NMI, we assume it was the IPMI
@@ -1120,12 +1112,8 @@ ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
panic(PFX "pre-timeout");
}
- return NOTIFY_STOP;
+ return NMI_HANDLED;
}
-
-static struct notifier_block ipmi_nmi_handler = {
- .notifier_call = ipmi_nmi
-};
#endif
static int wdog_reboot_handler(struct notifier_block *this,
@@ -1290,7 +1278,8 @@ static void check_parms(void)
}
}
if (do_nmi && !nmi_handler_registered) {
- rv = register_die_notifier(&ipmi_nmi_handler);
+ rv = register_nmi_handler(NMI_UNKNOWN, ipmi_nmi, 0,
+ "ipmi");
if (rv) {
printk(KERN_WARNING PFX
"Can't register nmi handler\n");
@@ -1298,7 +1287,7 @@ static void check_parms(void)
} else
nmi_handler_registered = 1;
} else if (!do_nmi && nmi_handler_registered) {
- unregister_die_notifier(&ipmi_nmi_handler);
+ unregister_nmi_handler(NMI_UNKNOWN, "ipmi");
nmi_handler_registered = 0;
}
#endif
@@ -1336,7 +1325,7 @@ static int __init ipmi_wdog_init(void)
if (rv) {
#ifdef HAVE_DIE_NMI
if (nmi_handler_registered)
- unregister_die_notifier(&ipmi_nmi_handler);
+ unregister_nmi_handler(NMI_UNKNOWN, "ipmi");
#endif
atomic_notifier_chain_unregister(&panic_notifier_list,
&wdog_panic_notifier);
@@ -1357,7 +1346,7 @@ static void __exit ipmi_wdog_exit(void)
#ifdef HAVE_DIE_NMI
if (nmi_handler_registered)
- unregister_die_notifier(&ipmi_nmi_handler);
+ unregister_nmi_handler(NMI_UNKNOWN, "ipmi");
#endif
atomic_notifier_chain_unregister(&panic_notifier_list,
diff --git a/drivers/char/random.c b/drivers/char/random.c
index c35a785005b0..63e19ba56bbe 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -932,7 +932,21 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
*/
void get_random_bytes(void *buf, int nbytes)
{
- extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
+ char *p = buf;
+
+ while (nbytes) {
+ unsigned long v;
+ int chunk = min(nbytes, (int)sizeof(unsigned long));
+
+ if (!arch_get_random_long(&v))
+ break;
+
+ memcpy(buf, &v, chunk);
+ p += chunk;
+ nbytes -= chunk;
+ }
+
+ extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
}
EXPORT_SYMBOL(get_random_bytes);
@@ -1318,9 +1332,14 @@ late_initcall(random_int_secret_init);
DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
unsigned int get_random_int(void)
{
- __u32 *hash = get_cpu_var(get_random_int_hash);
+ __u32 *hash;
unsigned int ret;
+ if (arch_get_random_int(&ret))
+ return ret;
+
+ hash = get_cpu_var(get_random_int_hash);
+
hash[0] += current->pid + jiffies + get_cycles();
md5_transform(hash, random_int_secret);
ret = hash[0];
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index b33e8ea314ed..b6de2c047145 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -324,13 +324,12 @@ static int __init raw_init(void)
max_raw_minors = MAX_RAW_MINORS;
}
- raw_devices = vmalloc(sizeof(struct raw_device_data) * max_raw_minors);
+ raw_devices = vzalloc(sizeof(struct raw_device_data) * max_raw_minors);
if (!raw_devices) {
printk(KERN_ERR "Not enough memory for raw device structures\n");
ret = -ENOMEM;
goto error;
}
- memset(raw_devices, 0, sizeof(struct raw_device_data) * max_raw_minors);
ret = register_chrdev_region(dev, max_raw_minors, "raw");
if (ret)
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index dfa8b3062fda..ccd124ab7ca7 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -80,6 +80,7 @@
#include <linux/bcd.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
+#include <linux/ratelimit.h>
#include <asm/current.h>
#include <asm/system.h>
@@ -1195,10 +1196,8 @@ static void rtc_dropped_irq(unsigned long data)
spin_unlock_irq(&rtc_lock);
- if (printk_ratelimit()) {
- printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
- freq);
- }
+ printk_ratelimited(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
+ freq);
/* Now we have new data */
wake_up_interruptible(&rtc_wait);
diff --git a/drivers/char/scc.h b/drivers/char/scc.h
deleted file mode 100644
index 341b1142bea8..000000000000
--- a/drivers/char/scc.h
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * atari_SCC.h: Definitions for the Am8530 Serial Communications Controller
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * 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 _SCC_H
-#define _SCC_H
-
-#include <linux/delay.h>
-
-/* Special configuration ioctls for the Atari SCC5380 Serial
- * Communications Controller
- */
-
-/* ioctl command codes */
-
-#define TIOCGATSCC 0x54c0 /* get SCC configuration */
-#define TIOCSATSCC 0x54c1 /* set SCC configuration */
-#define TIOCDATSCC 0x54c2 /* reset configuration to defaults */
-
-/* Clock sources */
-
-#define CLK_RTxC 0
-#define CLK_TRxC 1
-#define CLK_PCLK 2
-
-/* baud_bases for the common clocks in the Atari. These are the real
- * frequencies divided by 16.
- */
-
-#define SCC_BAUD_BASE_TIMC 19200 /* 0.3072 MHz from TT-MFP, Timer C */
-#define SCC_BAUD_BASE_BCLK 153600 /* 2.4576 MHz */
-#define SCC_BAUD_BASE_PCLK4 229500 /* 3.6720 MHz */
-#define SCC_BAUD_BASE_PCLK 503374 /* 8.0539763 MHz */
-#define SCC_BAUD_BASE_NONE 0 /* for not connected or unused
- * clock sources */
-
-/* The SCC clock configuration structure */
-
-struct scc_clock_config {
- unsigned RTxC_base; /* base_baud of RTxC */
- unsigned TRxC_base; /* base_baud of TRxC */
- unsigned PCLK_base; /* base_baud of PCLK, both channels! */
- struct {
- unsigned clksrc; /* CLK_RTxC, CLK_TRxC or CLK_PCLK */
- unsigned divisor; /* divisor for base baud, valid values:
- * see below */
- } baud_table[17]; /* For 50, 75, 110, 135, 150, 200, 300,
- * 600, 1200, 1800, 2400, 4800, 9600,
- * 19200, 38400, 57600 and 115200 bps.
- * The last two could be replaced by
- * other rates > 38400 if they're not
- * possible.
- */
-};
-
-/* The following divisors are valid:
- *
- * - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
- * the BRG)
- *
- * - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
- *
- * - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
- *
- */
-
-struct scc_port {
- struct gs_port gs;
- volatile unsigned char *ctrlp;
- volatile unsigned char *datap;
- int x_char; /* xon/xoff character */
- int c_dcd;
- int channel;
- struct scc_port *port_a; /* Reference to port A and B */
- struct scc_port *port_b; /* structs for reg access */
-};
-
-#define SCC_MAGIC 0x52696368
-
-/***********************************************************************/
-/* */
-/* Register Names */
-/* */
-/***********************************************************************/
-
-/* The SCC documentation gives no explicit names to the registers,
- * they're just called WR0..15 and RR0..15. To make the source code
- * better readable and make the transparent write reg read access (see
- * below) possible, I christen them here with self-invented names.
- * Note that (real) read registers are assigned numbers 16..31. WR7'
- * has number 33.
- */
-
-#define COMMAND_REG 0 /* wo */
-#define INT_AND_DMA_REG 1 /* wo */
-#define INT_VECTOR_REG 2 /* rw, common to both channels */
-#define RX_CTRL_REG 3 /* rw */
-#define AUX1_CTRL_REG 4 /* rw */
-#define TX_CTRL_REG 5 /* rw */
-#define SYNC_ADR_REG 6 /* wo */
-#define SYNC_CHAR_REG 7 /* wo */
-#define SDLC_OPTION_REG 33 /* wo */
-#define TX_DATA_REG 8 /* wo */
-#define MASTER_INT_CTRL 9 /* wo, common to both channels */
-#define AUX2_CTRL_REG 10 /* rw */
-#define CLK_CTRL_REG 11 /* wo */
-#define TIMER_LOW_REG 12 /* rw */
-#define TIMER_HIGH_REG 13 /* rw */
-#define DPLL_CTRL_REG 14 /* wo */
-#define INT_CTRL_REG 15 /* rw */
-
-#define STATUS_REG 16 /* ro */
-#define SPCOND_STATUS_REG 17 /* wo */
-/* RR2 is WR2 for Channel A, Channel B gives vector + current status: */
-#define CURR_VECTOR_REG 18 /* Ch. B only, Ch. A for rw */
-#define INT_PENDING_REG 19 /* Channel A only! */
-/* RR4 is WR4, if b6(MR7') == 1 */
-/* RR5 is WR5, if b6(MR7') == 1 */
-#define FS_FIFO_LOW_REG 22 /* ro */
-#define FS_FIFO_HIGH_REG 23 /* ro */
-#define RX_DATA_REG 24 /* ro */
-/* RR9 is WR3, if b6(MR7') == 1 */
-#define DPLL_STATUS_REG 26 /* ro */
-/* RR11 is WR10, if b6(MR7') == 1 */
-/* RR12 is WR12 */
-/* RR13 is WR13 */
-/* RR14 not present */
-/* RR15 is WR15 */
-
-
-/***********************************************************************/
-/* */
-/* Register Values */
-/* */
-/***********************************************************************/
-
-
-/* WR0: COMMAND_REG "CR" */
-
-#define CR_RX_CRC_RESET 0x40
-#define CR_TX_CRC_RESET 0x80
-#define CR_TX_UNDERRUN_RESET 0xc0
-
-#define CR_EXTSTAT_RESET 0x10
-#define CR_SEND_ABORT 0x18
-#define CR_ENAB_INT_NEXT_RX 0x20
-#define CR_TX_PENDING_RESET 0x28
-#define CR_ERROR_RESET 0x30
-#define CR_HIGHEST_IUS_RESET 0x38
-
-
-/* WR1: INT_AND_DMA_REG "IDR" */
-
-#define IDR_EXTSTAT_INT_ENAB 0x01
-#define IDR_TX_INT_ENAB 0x02
-#define IDR_PARERR_AS_SPCOND 0x04
-
-#define IDR_RX_INT_DISAB 0x00
-#define IDR_RX_INT_FIRST 0x08
-#define IDR_RX_INT_ALL 0x10
-#define IDR_RX_INT_SPCOND 0x18
-#define IDR_RX_INT_MASK 0x18
-
-#define IDR_WAITREQ_RX 0x20
-#define IDR_WAITREQ_IS_REQ 0x40
-#define IDR_WAITREQ_ENAB 0x80
-
-
-/* WR3: RX_CTRL_REG "RCR" */
-
-#define RCR_RX_ENAB 0x01
-#define RCR_DISCARD_SYNC_CHARS 0x02
-#define RCR_ADDR_SEARCH 0x04
-#define RCR_CRC_ENAB 0x08
-#define RCR_SEARCH_MODE 0x10
-#define RCR_AUTO_ENAB_MODE 0x20
-
-#define RCR_CHSIZE_MASK 0xc0
-#define RCR_CHSIZE_5 0x00
-#define RCR_CHSIZE_6 0x40
-#define RCR_CHSIZE_7 0x80
-#define RCR_CHSIZE_8 0xc0
-
-
-/* WR4: AUX1_CTRL_REG "A1CR" */
-
-#define A1CR_PARITY_MASK 0x03
-#define A1CR_PARITY_NONE 0x00
-#define A1CR_PARITY_ODD 0x01
-#define A1CR_PARITY_EVEN 0x03
-
-#define A1CR_MODE_MASK 0x0c
-#define A1CR_MODE_SYNCR 0x00
-#define A1CR_MODE_ASYNC_1 0x04
-#define A1CR_MODE_ASYNC_15 0x08
-#define A1CR_MODE_ASYNC_2 0x0c
-
-#define A1CR_SYNCR_MODE_MASK 0x30
-#define A1CR_SYNCR_MONOSYNC 0x00
-#define A1CR_SYNCR_BISYNC 0x10
-#define A1CR_SYNCR_SDLC 0x20
-#define A1CR_SYNCR_EXTCSYNC 0x30
-
-#define A1CR_CLKMODE_MASK 0xc0
-#define A1CR_CLKMODE_x1 0x00
-#define A1CR_CLKMODE_x16 0x40
-#define A1CR_CLKMODE_x32 0x80
-#define A1CR_CLKMODE_x64 0xc0
-
-
-/* WR5: TX_CTRL_REG "TCR" */
-
-#define TCR_TX_CRC_ENAB 0x01
-#define TCR_RTS 0x02
-#define TCR_USE_CRC_CCITT 0x00
-#define TCR_USE_CRC_16 0x04
-#define TCR_TX_ENAB 0x08
-#define TCR_SEND_BREAK 0x10
-
-#define TCR_CHSIZE_MASK 0x60
-#define TCR_CHSIZE_5 0x00
-#define TCR_CHSIZE_6 0x20
-#define TCR_CHSIZE_7 0x40
-#define TCR_CHSIZE_8 0x60
-
-#define TCR_DTR 0x80
-
-
-/* WR7': SLDC_OPTION_REG "SOR" */
-
-#define SOR_AUTO_TX_ENAB 0x01
-#define SOR_AUTO_EOM_RESET 0x02
-#define SOR_AUTO_RTS_MODE 0x04
-#define SOR_NRZI_DISAB_HIGH 0x08
-#define SOR_ALT_DTRREQ_TIMING 0x10
-#define SOR_READ_CRC_CHARS 0x20
-#define SOR_EXTENDED_REG_ACCESS 0x40
-
-
-/* WR9: MASTER_INT_CTRL "MIC" */
-
-#define MIC_VEC_INCL_STAT 0x01
-#define MIC_NO_VECTOR 0x02
-#define MIC_DISAB_LOWER_CHAIN 0x04
-#define MIC_MASTER_INT_ENAB 0x08
-#define MIC_STATUS_HIGH 0x10
-#define MIC_IGN_INTACK 0x20
-
-#define MIC_NO_RESET 0x00
-#define MIC_CH_A_RESET 0x40
-#define MIC_CH_B_RESET 0x80
-#define MIC_HARD_RESET 0xc0
-
-
-/* WR10: AUX2_CTRL_REG "A2CR" */
-
-#define A2CR_SYNC_6 0x01
-#define A2CR_LOOP_MODE 0x02
-#define A2CR_ABORT_ON_UNDERRUN 0x04
-#define A2CR_MARK_IDLE 0x08
-#define A2CR_GO_ACTIVE_ON_POLL 0x10
-
-#define A2CR_CODING_MASK 0x60
-#define A2CR_CODING_NRZ 0x00
-#define A2CR_CODING_NRZI 0x20
-#define A2CR_CODING_FM1 0x40
-#define A2CR_CODING_FM0 0x60
-
-#define A2CR_PRESET_CRC_1 0x80
-
-
-/* WR11: CLK_CTRL_REG "CCR" */
-
-#define CCR_TRxCOUT_MASK 0x03
-#define CCR_TRxCOUT_XTAL 0x00
-#define CCR_TRxCOUT_TXCLK 0x01
-#define CCR_TRxCOUT_BRG 0x02
-#define CCR_TRxCOUT_DPLL 0x03
-
-#define CCR_TRxC_OUTPUT 0x04
-
-#define CCR_TXCLK_MASK 0x18
-#define CCR_TXCLK_RTxC 0x00
-#define CCR_TXCLK_TRxC 0x08
-#define CCR_TXCLK_BRG 0x10
-#define CCR_TXCLK_DPLL 0x18
-
-#define CCR_RXCLK_MASK 0x60
-#define CCR_RXCLK_RTxC 0x00
-#define CCR_RXCLK_TRxC 0x20
-#define CCR_RXCLK_BRG 0x40
-#define CCR_RXCLK_DPLL 0x60
-
-#define CCR_RTxC_XTAL 0x80
-
-
-/* WR14: DPLL_CTRL_REG "DCR" */
-
-#define DCR_BRG_ENAB 0x01
-#define DCR_BRG_USE_PCLK 0x02
-#define DCR_DTRREQ_IS_REQ 0x04
-#define DCR_AUTO_ECHO 0x08
-#define DCR_LOCAL_LOOPBACK 0x10
-
-#define DCR_DPLL_EDGE_SEARCH 0x20
-#define DCR_DPLL_ERR_RESET 0x40
-#define DCR_DPLL_DISAB 0x60
-#define DCR_DPLL_CLK_BRG 0x80
-#define DCR_DPLL_CLK_RTxC 0xa0
-#define DCR_DPLL_FM 0xc0
-#define DCR_DPLL_NRZI 0xe0
-
-
-/* WR15: INT_CTRL_REG "ICR" */
-
-#define ICR_OPTIONREG_SELECT 0x01
-#define ICR_ENAB_BRG_ZERO_INT 0x02
-#define ICR_USE_FS_FIFO 0x04
-#define ICR_ENAB_DCD_INT 0x08
-#define ICR_ENAB_SYNC_INT 0x10
-#define ICR_ENAB_CTS_INT 0x20
-#define ICR_ENAB_UNDERRUN_INT 0x40
-#define ICR_ENAB_BREAK_INT 0x80
-
-
-/* RR0: STATUS_REG "SR" */
-
-#define SR_CHAR_AVAIL 0x01
-#define SR_BRG_ZERO 0x02
-#define SR_TX_BUF_EMPTY 0x04
-#define SR_DCD 0x08
-#define SR_SYNC_ABORT 0x10
-#define SR_CTS 0x20
-#define SR_TX_UNDERRUN 0x40
-#define SR_BREAK 0x80
-
-
-/* RR1: SPCOND_STATUS_REG "SCSR" */
-
-#define SCSR_ALL_SENT 0x01
-#define SCSR_RESIDUAL_MASK 0x0e
-#define SCSR_PARITY_ERR 0x10
-#define SCSR_RX_OVERRUN 0x20
-#define SCSR_CRC_FRAME_ERR 0x40
-#define SCSR_END_OF_FRAME 0x80
-
-
-/* RR3: INT_PENDING_REG "IPR" */
-
-#define IPR_B_EXTSTAT 0x01
-#define IPR_B_TX 0x02
-#define IPR_B_RX 0x04
-#define IPR_A_EXTSTAT 0x08
-#define IPR_A_TX 0x10
-#define IPR_A_RX 0x20
-
-
-/* RR7: FS_FIFO_HIGH_REG "FFHR" */
-
-#define FFHR_CNT_MASK 0x3f
-#define FFHR_IS_FROM_FIFO 0x40
-#define FFHR_FIFO_OVERRUN 0x80
-
-
-/* RR10: DPLL_STATUS_REG "DSR" */
-
-#define DSR_ON_LOOP 0x02
-#define DSR_ON_LOOP_SENDING 0x10
-#define DSR_TWO_CLK_MISSING 0x40
-#define DSR_ONE_CLK_MISSING 0x80
-
-/***********************************************************************/
-/* */
-/* Register Access */
-/* */
-/***********************************************************************/
-
-
-/* The SCC needs 3.5 PCLK cycles recovery time between to register
- * accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 *
- * 125 ns = 437.5 ns. This is too short for udelay().
- * 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be
- * quite right
- */
-
-#define scc_reg_delay() \
- do { \
- if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147) \
- __asm__ __volatile__ ( " nop; nop"); \
- else if (MACH_IS_ATARI) \
- __asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\
- } while (0)
-
-static unsigned char scc_shadow[2][16];
-
-/* The following functions should relax the somehow complicated
- * register access of the SCC. _SCCwrite() stores all written values
- * (except for WR0 and WR8) in shadow registers for later recall. This
- * removes the burden of remembering written values as needed. The
- * extra work of storing the value doesn't count, since a delay is
- * needed after a SCC access anyway. Additionally, _SCCwrite() manages
- * writes to WR0 and WR8 differently, because these can be accessed
- * directly with less overhead. Another special case are WR7 and WR7'.
- * _SCCwrite automatically checks what of this registers is selected
- * and changes b0 of WR15 if needed.
- *
- * _SCCread() for standard read registers is straightforward, except
- * for RR2 (split into two "virtual" registers: one for the value
- * written to WR2 (from the shadow) and one for the vector including
- * status from RR2, Ch. B) and RR3. The latter must be read from
- * Channel A, because it reads as all zeros on Ch. B. RR0 and RR8 can
- * be accessed directly as before.
- *
- * The two inline function contain complicated switch statements. But
- * I rely on regno and final_delay being constants, so gcc can reduce
- * the whole stuff to just some assembler statements.
- *
- * _SCCwrite and _SCCread aren't intended to be used directly under
- * normal circumstances. The macros SCCread[_ND] and SCCwrite[_ND] are
- * for that purpose. They assume that a local variable 'port' is
- * declared and pointing to the port's scc_struct entry. The
- * variants with "_NB" appended should be used if no other SCC
- * accesses follow immediately (within 0.5 usecs). They just skip the
- * final delay nops.
- *
- * Please note that accesses to SCC registers should only take place
- * when interrupts are turned off (at least if SCC interrupts are
- * enabled). Otherwise, an interrupt could interfere with the
- * two-stage accessing process.
- *
- */
-
-
-static __inline__ void _SCCwrite(
- struct scc_port *port,
- unsigned char *shadow,
- volatile unsigned char *_scc_del,
- int regno,
- unsigned char val, int final_delay )
-{
- switch( regno ) {
-
- case COMMAND_REG:
- /* WR0 can be written directly without pointing */
- *port->ctrlp = val;
- break;
-
- case SYNC_CHAR_REG:
- /* For WR7, first set b0 of WR15 to 0, if needed */
- if (shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT) {
- *port->ctrlp = 15;
- shadow[INT_CTRL_REG] &= ~ICR_OPTIONREG_SELECT;
- scc_reg_delay();
- *port->ctrlp = shadow[INT_CTRL_REG];
- scc_reg_delay();
- }
- goto normal_case;
-
- case SDLC_OPTION_REG:
- /* For WR7', first set b0 of WR15 to 1, if needed */
- if (!(shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT)) {
- *port->ctrlp = 15;
- shadow[INT_CTRL_REG] |= ICR_OPTIONREG_SELECT;
- scc_reg_delay();
- *port->ctrlp = shadow[INT_CTRL_REG];
- scc_reg_delay();
- }
- *port->ctrlp = 7;
- shadow[8] = val; /* WR7' shadowed at WR8 */
- scc_reg_delay();
- *port->ctrlp = val;
- break;
-
- case TX_DATA_REG: /* WR8 */
- /* TX_DATA_REG can be accessed directly on some h/w */
- if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
- {
- *port->ctrlp = regno;
- scc_reg_delay();
- *port->ctrlp = val;
- }
- else
- *port->datap = val;
- break;
-
- case MASTER_INT_CTRL:
- *port->ctrlp = regno;
- val &= 0x3f; /* bits 6..7 are the reset commands */
- scc_shadow[0][regno] = val;
- scc_reg_delay();
- *port->ctrlp = val;
- break;
-
- case DPLL_CTRL_REG:
- *port->ctrlp = regno;
- val &= 0x1f; /* bits 5..7 are the DPLL commands */
- shadow[regno] = val;
- scc_reg_delay();
- *port->ctrlp = val;
- break;
-
- case 1 ... 6:
- case 10 ... 13:
- case 15:
- normal_case:
- *port->ctrlp = regno;
- shadow[regno] = val;
- scc_reg_delay();
- *port->ctrlp = val;
- break;
-
- default:
- printk( "Bad SCC write access to WR%d\n", regno );
- break;
-
- }
-
- if (final_delay)
- scc_reg_delay();
-}
-
-
-static __inline__ unsigned char _SCCread(
- struct scc_port *port,
- unsigned char *shadow,
- volatile unsigned char *_scc_del,
- int regno, int final_delay )
-{
- unsigned char rv;
-
- switch( regno ) {
-
- /* --- real read registers --- */
- case STATUS_REG:
- rv = *port->ctrlp;
- break;
-
- case INT_PENDING_REG:
- /* RR3: read only from Channel A! */
- port = port->port_a;
- goto normal_case;
-
- case RX_DATA_REG:
- /* RR8 can be accessed directly on some h/w */
- if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
- {
- *port->ctrlp = 8;
- scc_reg_delay();
- rv = *port->ctrlp;
- }
- else
- rv = *port->datap;
- break;
-
- case CURR_VECTOR_REG:
- /* RR2 (vector including status) from Ch. B */
- port = port->port_b;
- goto normal_case;
-
- /* --- reading write registers: access the shadow --- */
- case 1 ... 7:
- case 10 ... 15:
- return shadow[regno]; /* no final delay! */
-
- /* WR7' is special, because it is shadowed at the place of WR8 */
- case SDLC_OPTION_REG:
- return shadow[8]; /* no final delay! */
-
- /* WR9 is special too, because it is common for both channels */
- case MASTER_INT_CTRL:
- return scc_shadow[0][9]; /* no final delay! */
-
- default:
- printk( "Bad SCC read access to %cR%d\n", (regno & 16) ? 'R' : 'W',
- regno & ~16 );
- break;
-
- case SPCOND_STATUS_REG:
- case FS_FIFO_LOW_REG:
- case FS_FIFO_HIGH_REG:
- case DPLL_STATUS_REG:
- normal_case:
- *port->ctrlp = regno & 0x0f;
- scc_reg_delay();
- rv = *port->ctrlp;
- break;
-
- }
-
- if (final_delay)
- scc_reg_delay();
- return rv;
-}
-
-#define SCC_ACCESS_INIT(port) \
- unsigned char *_scc_shadow = &scc_shadow[port->channel][0]
-
-#define SCCwrite(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),1)
-#define SCCwrite_NB(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),0)
-#define SCCread(reg) _SCCread(port,_scc_shadow,scc_del,(reg),1)
-#define SCCread_NB(reg) _SCCread(port,_scc_shadow,scc_del,(reg),0)
-
-#define SCCmod(reg,and,or) SCCwrite((reg),(SCCread(reg)&(and))|(or))
-
-#endif /* _SCC_H */
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 9ca5c021d0b6..361a1dff8f77 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -966,6 +966,9 @@ ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr,
{
struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip->vendor.duration[TPM_LONG] == 0)
+ return 0;
+
return sprintf(buf, "%d %d %d [%s]\n",
jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index a1f68af4ccf4..f22861511909 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -170,7 +170,7 @@ static const struct tty_operations ttyprintk_ops = {
.ioctl = tpk_ioctl,
};
-struct tty_port_operations null_ops = { };
+static struct tty_port_operations null_ops = { };
static struct tty_driver *ttyprintk_driver;
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index fb68b1295373..4ca181f1378b 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -19,8 +19,10 @@
*/
#include <linux/cdev.h>
#include <linux/debugfs.h>
+#include <linux/completion.h>
#include <linux/device.h>
#include <linux/err.h>
+#include <linux/freezer.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/list.h>
@@ -73,6 +75,7 @@ struct ports_driver_data {
static struct ports_driver_data pdrvdata;
DEFINE_SPINLOCK(pdrvdata_lock);
+DECLARE_COMPLETION(early_console_added);
/* This struct holds information that's relevant only for console ports */
struct console {
@@ -151,6 +154,10 @@ struct ports_device {
int chr_major;
};
+struct port_stats {
+ unsigned long bytes_sent, bytes_received, bytes_discarded;
+};
+
/* This struct holds the per-port data */
struct port {
/* Next port in the list, head is in the ports_device */
@@ -179,6 +186,13 @@ struct port {
struct dentry *debugfs_file;
/*
+ * Keep count of the bytes sent, received and discarded for
+ * this port for accounting and debugging purposes. These
+ * counts are not reset across port open / close events.
+ */
+ struct port_stats stats;
+
+ /*
* The entries in this struct will be valid if this port is
* hooked up to an hvc console
*/
@@ -347,17 +361,19 @@ fail:
}
/* Callers should take appropriate locks */
-static void *get_inbuf(struct port *port)
+static struct port_buffer *get_inbuf(struct port *port)
{
struct port_buffer *buf;
- struct virtqueue *vq;
unsigned int len;
- vq = port->in_vq;
- buf = virtqueue_get_buf(vq, &len);
+ if (port->inbuf)
+ return port->inbuf;
+
+ buf = virtqueue_get_buf(port->in_vq, &len);
if (buf) {
buf->len = len;
buf->offset = 0;
+ port->stats.bytes_received += len;
}
return buf;
}
@@ -384,32 +400,27 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf)
static void discard_port_data(struct port *port)
{
struct port_buffer *buf;
- struct virtqueue *vq;
- unsigned int len;
- int ret;
+ unsigned int err;
if (!port->portdev) {
/* Device has been unplugged. vqs are already gone. */
return;
}
- vq = port->in_vq;
- if (port->inbuf)
- buf = port->inbuf;
- else
- buf = virtqueue_get_buf(vq, &len);
+ buf = get_inbuf(port);
- ret = 0;
+ err = 0;
while (buf) {
- if (add_inbuf(vq, buf) < 0) {
- ret++;
+ port->stats.bytes_discarded += buf->len - buf->offset;
+ if (add_inbuf(port->in_vq, buf) < 0) {
+ err++;
free_buf(buf);
}
- buf = virtqueue_get_buf(vq, &len);
+ port->inbuf = NULL;
+ buf = get_inbuf(port);
}
- port->inbuf = NULL;
- if (ret)
+ if (err)
dev_warn(port->dev, "Errors adding %d buffers back to vq\n",
- ret);
+ err);
}
static bool port_has_data(struct port *port)
@@ -417,18 +428,12 @@ static bool port_has_data(struct port *port)
unsigned long flags;
bool ret;
+ ret = false;
spin_lock_irqsave(&port->inbuf_lock, flags);
- if (port->inbuf) {
- ret = true;
- goto out;
- }
port->inbuf = get_inbuf(port);
- if (port->inbuf) {
+ if (port->inbuf)
ret = true;
- goto out;
- }
- ret = false;
-out:
+
spin_unlock_irqrestore(&port->inbuf_lock, flags);
return ret;
}
@@ -529,6 +534,8 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
cpu_relax();
done:
spin_unlock_irqrestore(&port->outvq_lock, flags);
+
+ port->stats.bytes_sent += in_count;
/*
* We're expected to return the amount of data we wrote -- all
* of it
@@ -633,8 +640,8 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
- ret = wait_event_interruptible(port->waitqueue,
- !will_read_block(port));
+ ret = wait_event_freezable(port->waitqueue,
+ !will_read_block(port));
if (ret < 0)
return ret;
}
@@ -677,8 +684,8 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
if (nonblock)
return -EAGAIN;
- ret = wait_event_interruptible(port->waitqueue,
- !will_write_block(port));
+ ret = wait_event_freezable(port->waitqueue,
+ !will_write_block(port));
if (ret < 0)
return ret;
}
@@ -1059,6 +1066,14 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf,
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"outvq_full: %d\n", port->outvq_full);
out_offset += snprintf(buf + out_offset, out_count - out_offset,
+ "bytes_sent: %lu\n", port->stats.bytes_sent);
+ out_offset += snprintf(buf + out_offset, out_count - out_offset,
+ "bytes_received: %lu\n",
+ port->stats.bytes_received);
+ out_offset += snprintf(buf + out_offset, out_count - out_offset,
+ "bytes_discarded: %lu\n",
+ port->stats.bytes_discarded);
+ out_offset += snprintf(buf + out_offset, out_count - out_offset,
"is_console: %s\n",
is_console_port(port) ? "yes" : "no");
out_offset += snprintf(buf + out_offset, out_count - out_offset,
@@ -1143,6 +1158,7 @@ static int add_port(struct ports_device *portdev, u32 id)
port->cons.ws.ws_row = port->cons.ws.ws_col = 0;
port->host_connected = port->guest_connected = false;
+ port->stats = (struct port_stats) { 0 };
port->outvq_full = false;
@@ -1352,6 +1368,7 @@ static void handle_control_message(struct ports_device *portdev,
break;
init_port_console(port);
+ complete(&early_console_added);
/*
* Could remove the port here in case init fails - but
* have to notify the host first.
@@ -1394,6 +1411,13 @@ static void handle_control_message(struct ports_device *portdev,
break;
case VIRTIO_CONSOLE_PORT_NAME:
/*
+ * If we woke up after hibernation, we can get this
+ * again. Skip it in that case.
+ */
+ if (port->name)
+ break;
+
+ /*
* Skip the size of the header and the cpkt to get the size
* of the name that was sent
*/
@@ -1481,8 +1505,7 @@ static void in_intr(struct virtqueue *vq)
return;
spin_lock_irqsave(&port->inbuf_lock, flags);
- if (!port->inbuf)
- port->inbuf = get_inbuf(port);
+ port->inbuf = get_inbuf(port);
/*
* Don't queue up data when port is closed. This condition
@@ -1563,7 +1586,7 @@ static int init_vqs(struct ports_device *portdev)
portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
GFP_KERNEL);
if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs ||
- !portdev->out_vqs) {
+ !portdev->out_vqs) {
err = -ENOMEM;
goto free;
}
@@ -1648,6 +1671,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
struct ports_device *portdev;
int err;
bool multiport;
+ bool early = early_put_chars != NULL;
+
+ /* Ensure to read early_put_chars now */
+ barrier();
portdev = kmalloc(sizeof(*portdev), GFP_KERNEL);
if (!portdev) {
@@ -1675,13 +1702,11 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
multiport = false;
portdev->config.max_nr_ports = 1;
- if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) {
+ if (virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
+ offsetof(struct virtio_console_config,
+ max_nr_ports),
+ &portdev->config.max_nr_ports) == 0)
multiport = true;
- vdev->config->get(vdev, offsetof(struct virtio_console_config,
- max_nr_ports),
- &portdev->config.max_nr_ports,
- sizeof(portdev->config.max_nr_ports));
- }
err = init_vqs(portdev);
if (err < 0) {
@@ -1719,6 +1744,19 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
VIRTIO_CONSOLE_DEVICE_READY, 1);
+
+ /*
+ * If there was an early virtio console, assume that there are no
+ * other consoles. We need to wait until the hvc_alloc matches the
+ * hvc_instantiate, otherwise tty_open will complain, resulting in
+ * a "Warning: unable to open an initial console" boot failure.
+ * Without multiport this is done in add_port above. With multiport
+ * this might take some host<->guest communication - thus we have to
+ * wait.
+ */
+ if (multiport && early)
+ wait_for_completion(&early_console_added);
+
return 0;
free_vqs:
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 34e9c4f88926..999d6a03e436 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -15,3 +15,18 @@ config CLKSRC_MMIO
config DW_APB_TIMER
bool
+
+config CLKSRC_DBX500_PRCMU
+ bool "Clocksource PRCMU Timer"
+ depends on UX500_SOC_DB5500 || UX500_SOC_DB8500
+ default y
+ help
+ Use the always on PRCMU Timer as clocksource
+
+config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+ bool "Clocksource PRCMU Timer sched_clock"
+ depends on (CLKSRC_DBX500_PRCMU && !NOMADIK_MTU_SCHED_CLOCK)
+ select HAVE_SCHED_CLOCK
+ default y
+ help
+ Use the always on PRCMU Timer as sched_clock
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 85ad1646a7b7..8d81a1d32653 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
obj-$(CONFIG_CLKBLD_I8253) += i8253.o
obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
+obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o \ No newline at end of file
diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c
new file mode 100644
index 000000000000..59feefe0e3e6
--- /dev/null
+++ b/drivers/clocksource/clksrc-dbx500-prcmu.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
+ * Author: Sundar Iyer for ST-Ericsson
+ * sched_clock implementation is based on:
+ * plat-nomadik/timer.c Linus Walleij <linus.walleij@stericsson.com>
+ *
+ * DBx500-PRCMU Timer
+ * The PRCMU has 5 timers which are available in a always-on
+ * power domain. We use the Timer 4 for our always-on clock
+ * source on DB8500 and Timer 3 on DB5500.
+ */
+#include <linux/clockchips.h>
+#include <linux/clksrc-dbx500-prcmu.h>
+
+#include <asm/sched_clock.h>
+
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+#define RATE_32K 32768
+
+#define TIMER_MODE_CONTINOUS 0x1
+#define TIMER_DOWNCOUNT_VAL 0xffffffff
+
+#define PRCMU_TIMER_REF 0
+#define PRCMU_TIMER_DOWNCOUNT 0x4
+#define PRCMU_TIMER_MODE 0x8
+
+#define SCHED_CLOCK_MIN_WRAP 131072 /* 2^32 / 32768 */
+
+static void __iomem *clksrc_dbx500_timer_base;
+
+static cycle_t clksrc_dbx500_prcmu_read(struct clocksource *cs)
+{
+ u32 count, count2;
+
+ do {
+ count = readl(clksrc_dbx500_timer_base +
+ PRCMU_TIMER_DOWNCOUNT);
+ count2 = readl(clksrc_dbx500_timer_base +
+ PRCMU_TIMER_DOWNCOUNT);
+ } while (count2 != count);
+
+ /* Negate because the timer is a decrementing counter */
+ return ~count;
+}
+
+static struct clocksource clocksource_dbx500_prcmu = {
+ .name = "dbx500-prcmu-timer",
+ .rating = 300,
+ .read = clksrc_dbx500_prcmu_read,
+ .shift = 10,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+static DEFINE_CLOCK_DATA(cd);
+
+unsigned long long notrace sched_clock(void)
+{
+ u32 cyc;
+
+ if (unlikely(!clksrc_dbx500_timer_base))
+ return 0;
+
+ cyc = clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu);
+
+ return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace clksrc_dbx500_prcmu_update_sched_clock(void)
+{
+ u32 cyc = clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu);
+ update_sched_clock(&cd, cyc, (u32)~0);
+}
+#endif
+
+void __init clksrc_dbx500_prcmu_init(void __iomem *base)
+{
+ clksrc_dbx500_timer_base = base;
+
+ /*
+ * The A9 sub system expects the timer to be configured as
+ * a continous looping timer.
+ * The PRCMU should configure it but if it for some reason
+ * don't we do it here.
+ */
+ if (readl(clksrc_dbx500_timer_base + PRCMU_TIMER_MODE) !=
+ TIMER_MODE_CONTINOUS) {
+ writel(TIMER_MODE_CONTINOUS,
+ clksrc_dbx500_timer_base + PRCMU_TIMER_MODE);
+ writel(TIMER_DOWNCOUNT_VAL,
+ clksrc_dbx500_timer_base + PRCMU_TIMER_REF);
+ }
+#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+ init_sched_clock(&cd, clksrc_dbx500_prcmu_update_sched_clock,
+ 32, RATE_32K);
+#endif
+ clocksource_calc_mult_shift(&clocksource_dbx500_prcmu,
+ RATE_32K, SCHED_CLOCK_MIN_WRAP);
+ clocksource_register(&clocksource_dbx500_prcmu);
+}
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
index 580f870541a3..8c2a35f26d9b 100644
--- a/drivers/clocksource/dw_apb_timer.c
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -348,7 +348,7 @@ static void apbt_restart_clocksource(struct clocksource *cs)
* dw_apb_clocksource_register() as the next step.
*/
struct dw_apb_clocksource *
-dw_apb_clocksource_init(unsigned rating, char *name, void __iomem *base,
+dw_apb_clocksource_init(unsigned rating, const char *name, void __iomem *base,
unsigned long freq)
{
struct dw_apb_clocksource *dw_cs = kzalloc(sizeof(*dw_cs), GFP_KERNEL);
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index e55814bc0d06..77e1e6cd66ce 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -205,6 +205,32 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}
+void proc_comm_connector(struct task_struct *task)
+{
+ struct cn_msg *msg;
+ struct proc_event *ev;
+ struct timespec ts;
+ __u8 buffer[CN_PROC_MSG_SIZE];
+
+ if (atomic_read(&proc_event_num_listeners) < 1)
+ return;
+
+ msg = (struct cn_msg *)buffer;
+ ev = (struct proc_event *)msg->data;
+ get_seq(&msg->seq, &ev->cpu);
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+ ev->what = PROC_EVENT_COMM;
+ ev->event_data.comm.process_pid = task->pid;
+ ev->event_data.comm.process_tgid = task->tgid;
+ get_task_comm(ev->event_data.comm.comm, task);
+
+ memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
+ msg->ack = 0; /* not used */
+ msg->len = sizeof(*ev);
+ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+}
+
void proc_exit_connector(struct task_struct *task)
{
struct cn_msg *msg;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 33b56e5c5c14..c97b468ee9f7 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -120,10 +120,12 @@ static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu,
static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
{
- u64 idle_time = get_cpu_idle_time_us(cpu, wall);
+ u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
if (idle_time == -1ULL)
return get_cpu_idle_time_jiffy(cpu, wall);
+ else
+ idle_time += get_cpu_iowait_time_us(cpu, wall);
return idle_time;
}
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 891360edecdd..fa8af4ebb1d6 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -144,10 +144,12 @@ static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu,
static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
{
- u64 idle_time = get_cpu_idle_time_us(cpu, wall);
+ u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
if (idle_time == -1ULL)
return get_cpu_idle_time_jiffy(cpu, wall);
+ else
+ idle_time += get_cpu_iowait_time_us(cpu, wall);
return idle_time;
}
@@ -725,7 +727,7 @@ static int __init cpufreq_gov_dbs_init(void)
dbs_tuners_ins.down_differential =
MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
/*
- * In no_hz/micro accounting case we set the minimum frequency
+ * In nohz/micro accounting case we set the minimum frequency
* not depending on HZ, but fixed (very low). The deferred
* timer might skip some samples if idle/sleeping as needed.
*/
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index d4c542372886..0df014110097 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -12,7 +12,7 @@
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/notifier.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
#include <linux/cpu.h>
#include <linux/cpuidle.h>
#include <linux/ktime.h>
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index 12c98900dcf8..f62fde21e962 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -14,7 +14,7 @@
#include <linux/kernel.h>
#include <linux/cpuidle.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
#include <linux/moduleparam.h>
#include <linux/jiffies.h>
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index c47f3d09c1ee..3600f1955e48 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -12,7 +12,7 @@
#include <linux/kernel.h>
#include <linux/cpuidle.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
#include <linux/time.h>
#include <linux/ktime.h>
#include <linux/hrtimer.h>
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index e0b25de1e339..6d16b4b0d7a0 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -200,6 +200,7 @@ config CRYPTO_DEV_HIFN_795X
select CRYPTO_BLKCIPHER
select HW_RANDOM if CRYPTO_DEV_HIFN_795X_RNG
depends on PCI
+ depends on !ARCH_DMA_ADDR_T_64BIT
help
This option allows you to have support for HIFN 795x crypto adapters.
@@ -266,7 +267,7 @@ config CRYPTO_DEV_OMAP_AES
config CRYPTO_DEV_PICOXCELL
tristate "Support for picoXcell IPSEC and Layer2 crypto engines"
- depends on ARCH_PICOXCELL
+ depends on ARCH_PICOXCELL && HAVE_CLK
select CRYPTO_AES
select CRYPTO_AUTHENC
select CRYPTO_ALGAPI
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index a84250a5dd51..fe765f49de58 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -2744,10 +2744,8 @@ static int __init hifn_init(void)
unsigned int freq;
int err;
- if (sizeof(dma_addr_t) > 4) {
- printk(KERN_INFO "HIFN supports only 32-bit addresses.\n");
- return -EINVAL;
- }
+ /* HIFN supports only 32-bit addresses */
+ BUILD_BUG_ON(sizeof(dma_addr_t) != 4);
if (strncmp(hifn_pll_ref, "ext", 3) &&
strncmp(hifn_pll_ref, "pci", 3)) {
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index d0183ddb3076..8944dabc0e3c 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -1006,9 +1006,9 @@ static int n2_do_ecb(struct ablkcipher_request *req, bool encrypt)
spin_unlock_irqrestore(&qp->lock, flags);
+out:
put_cpu();
-out:
n2_chunk_complete(req, NULL);
return err;
}
@@ -1096,9 +1096,9 @@ static int n2_do_chaining(struct ablkcipher_request *req, bool encrypt)
spin_unlock_irqrestore(&qp->lock, flags);
+out:
put_cpu();
-out:
n2_chunk_complete(req, err ? NULL : final_iv_addr);
return err;
}
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index db33d300aa23..29b9469f8378 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -508,10 +508,8 @@ static int __init padlock_init(void)
int ret;
struct cpuinfo_x86 *c = &cpu_data(0);
- if (!cpu_has_xcrypt) {
- printk(KERN_NOTICE PFX "VIA PadLock not detected.\n");
+ if (!cpu_has_xcrypt)
return -ENODEV;
- }
if (!cpu_has_xcrypt_enabled) {
printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index 230b5b8cda1f..a2b553eabbdb 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -34,6 +34,7 @@
#include <linux/io.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/rtnetlink.h>
@@ -1241,8 +1242,8 @@ static void spacc_spacc_complete(unsigned long data)
spin_unlock_irqrestore(&engine->hw_lock, flags);
list_for_each_entry_safe(req, tmp, &completed, list) {
- req->complete(req);
list_del(&req->list);
+ req->complete(req);
}
}
@@ -1657,10 +1658,33 @@ static struct spacc_alg l2_engine_algs[] = {
},
};
-static int __devinit spacc_probe(struct platform_device *pdev,
- unsigned max_ctxs, size_t cipher_pg_sz,
- size_t hash_pg_sz, size_t fifo_sz,
- struct spacc_alg *algs, size_t num_algs)
+#ifdef CONFIG_OF
+static const struct of_device_id spacc_of_id_table[] = {
+ { .compatible = "picochip,spacc-ipsec" },
+ { .compatible = "picochip,spacc-l2" },
+ {}
+};
+#else /* CONFIG_OF */
+#define spacc_of_id_table NULL
+#endif /* CONFIG_OF */
+
+static bool spacc_is_compatible(struct platform_device *pdev,
+ const char *spacc_type)
+{
+ const struct platform_device_id *platid = platform_get_device_id(pdev);
+
+ if (platid && !strcmp(platid->name, spacc_type))
+ return true;
+
+#ifdef CONFIG_OF
+ if (of_device_is_compatible(pdev->dev.of_node, spacc_type))
+ return true;
+#endif /* CONFIG_OF */
+
+ return false;
+}
+
+static int __devinit spacc_probe(struct platform_device *pdev)
{
int i, err, ret = -EINVAL;
struct resource *mem, *irq;
@@ -1669,13 +1693,25 @@ static int __devinit spacc_probe(struct platform_device *pdev,
if (!engine)
return -ENOMEM;
- engine->max_ctxs = max_ctxs;
- engine->cipher_pg_sz = cipher_pg_sz;
- engine->hash_pg_sz = hash_pg_sz;
- engine->fifo_sz = fifo_sz;
- engine->algs = algs;
- engine->num_algs = num_algs;
- engine->name = dev_name(&pdev->dev);
+ if (spacc_is_compatible(pdev, "picochip,spacc-ipsec")) {
+ engine->max_ctxs = SPACC_CRYPTO_IPSEC_MAX_CTXS;
+ engine->cipher_pg_sz = SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ;
+ engine->hash_pg_sz = SPACC_CRYPTO_IPSEC_HASH_PG_SZ;
+ engine->fifo_sz = SPACC_CRYPTO_IPSEC_FIFO_SZ;
+ engine->algs = ipsec_engine_algs;
+ engine->num_algs = ARRAY_SIZE(ipsec_engine_algs);
+ } else if (spacc_is_compatible(pdev, "picochip,spacc-l2")) {
+ engine->max_ctxs = SPACC_CRYPTO_L2_MAX_CTXS;
+ engine->cipher_pg_sz = SPACC_CRYPTO_L2_CIPHER_PG_SZ;
+ engine->hash_pg_sz = SPACC_CRYPTO_L2_HASH_PG_SZ;
+ engine->fifo_sz = SPACC_CRYPTO_L2_FIFO_SZ;
+ engine->algs = l2_engine_algs;
+ engine->num_algs = ARRAY_SIZE(l2_engine_algs);
+ } else {
+ return -EINVAL;
+ }
+
+ engine->name = dev_name(&pdev->dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -1711,7 +1747,7 @@ static int __devinit spacc_probe(struct platform_device *pdev,
spin_lock_init(&engine->hw_lock);
- engine->clk = clk_get(&pdev->dev, NULL);
+ engine->clk = clk_get(&pdev->dev, "ref");
if (IS_ERR(engine->clk)) {
dev_info(&pdev->dev, "clk unavailable\n");
device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
@@ -1800,72 +1836,33 @@ static int __devexit spacc_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit ipsec_probe(struct platform_device *pdev)
-{
- return spacc_probe(pdev, SPACC_CRYPTO_IPSEC_MAX_CTXS,
- SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ,
- SPACC_CRYPTO_IPSEC_HASH_PG_SZ,
- SPACC_CRYPTO_IPSEC_FIFO_SZ, ipsec_engine_algs,
- ARRAY_SIZE(ipsec_engine_algs));
-}
-
-static struct platform_driver ipsec_driver = {
- .probe = ipsec_probe,
- .remove = __devexit_p(spacc_remove),
- .driver = {
- .name = "picoxcell-ipsec",
-#ifdef CONFIG_PM
- .pm = &spacc_pm_ops,
-#endif /* CONFIG_PM */
- },
+static const struct platform_device_id spacc_id_table[] = {
+ { "picochip,spacc-ipsec", },
+ { "picochip,spacc-l2", },
};
-static int __devinit l2_probe(struct platform_device *pdev)
-{
- return spacc_probe(pdev, SPACC_CRYPTO_L2_MAX_CTXS,
- SPACC_CRYPTO_L2_CIPHER_PG_SZ,
- SPACC_CRYPTO_L2_HASH_PG_SZ, SPACC_CRYPTO_L2_FIFO_SZ,
- l2_engine_algs, ARRAY_SIZE(l2_engine_algs));
-}
-
-static struct platform_driver l2_driver = {
- .probe = l2_probe,
+static struct platform_driver spacc_driver = {
+ .probe = spacc_probe,
.remove = __devexit_p(spacc_remove),
.driver = {
- .name = "picoxcell-l2",
+ .name = "picochip,spacc",
#ifdef CONFIG_PM
.pm = &spacc_pm_ops,
#endif /* CONFIG_PM */
+ .of_match_table = spacc_of_id_table,
},
+ .id_table = spacc_id_table,
};
static int __init spacc_init(void)
{
- int ret = platform_driver_register(&ipsec_driver);
- if (ret) {
- pr_err("failed to register ipsec spacc driver");
- goto out;
- }
-
- ret = platform_driver_register(&l2_driver);
- if (ret) {
- pr_err("failed to register l2 spacc driver");
- goto l2_failed;
- }
-
- return 0;
-
-l2_failed:
- platform_driver_unregister(&ipsec_driver);
-out:
- return ret;
+ return platform_driver_register(&spacc_driver);
}
module_init(spacc_init);
static void __exit spacc_exit(void)
{
- platform_driver_unregister(&ipsec_driver);
- platform_driver_unregister(&l2_driver);
+ platform_driver_unregister(&spacc_driver);
}
module_exit(spacc_exit);
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 8a0bb417aa11..dbe76b5df9cf 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -416,7 +416,7 @@ static void talitos_done(unsigned long data)
/*
* locate current (offending) descriptor
*/
-static struct talitos_desc *current_desc(struct device *dev, int ch)
+static u32 current_desc_hdr(struct device *dev, int ch)
{
struct talitos_private *priv = dev_get_drvdata(dev);
int tail = priv->chan[ch].tail;
@@ -428,23 +428,25 @@ static struct talitos_desc *current_desc(struct device *dev, int ch)
tail = (tail + 1) & (priv->fifo_len - 1);
if (tail == priv->chan[ch].tail) {
dev_err(dev, "couldn't locate current descriptor\n");
- return NULL;
+ return 0;
}
}
- return priv->chan[ch].fifo[tail].desc;
+ return priv->chan[ch].fifo[tail].desc->hdr;
}
/*
* user diagnostics; report root cause of error based on execution unit status
*/
-static void report_eu_error(struct device *dev, int ch,
- struct talitos_desc *desc)
+static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
{
struct talitos_private *priv = dev_get_drvdata(dev);
int i;
- switch (desc->hdr & DESC_HDR_SEL0_MASK) {
+ if (!desc_hdr)
+ desc_hdr = in_be32(priv->reg + TALITOS_DESCBUF(ch));
+
+ switch (desc_hdr & DESC_HDR_SEL0_MASK) {
case DESC_HDR_SEL0_AFEU:
dev_err(dev, "AFEUISR 0x%08x_%08x\n",
in_be32(priv->reg + TALITOS_AFEUISR),
@@ -488,7 +490,7 @@ static void report_eu_error(struct device *dev, int ch,
break;
}
- switch (desc->hdr & DESC_HDR_SEL1_MASK) {
+ switch (desc_hdr & DESC_HDR_SEL1_MASK) {
case DESC_HDR_SEL1_MDEUA:
case DESC_HDR_SEL1_MDEUB:
dev_err(dev, "MDEUISR 0x%08x_%08x\n",
@@ -550,7 +552,7 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
if (v_lo & TALITOS_CCPSR_LO_IEU)
dev_err(dev, "invalid execution unit error\n");
if (v_lo & TALITOS_CCPSR_LO_EU)
- report_eu_error(dev, ch, current_desc(dev, ch));
+ report_eu_error(dev, ch, current_desc_hdr(dev, ch));
if (v_lo & TALITOS_CCPSR_LO_GB)
dev_err(dev, "gather boundary error\n");
if (v_lo & TALITOS_CCPSR_LO_GRL)
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c
index 4abd089a094f..25ec0bb05198 100644
--- a/drivers/dca/dca-core.c
+++ b/drivers/dca/dca-core.c
@@ -35,7 +35,7 @@ MODULE_VERSION(DCA_VERSION);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Intel Corporation");
-static DEFINE_SPINLOCK(dca_lock);
+static DEFINE_RAW_SPINLOCK(dca_lock);
static LIST_HEAD(dca_domains);
@@ -101,10 +101,10 @@ static void unregister_dca_providers(void)
INIT_LIST_HEAD(&unregistered_providers);
- spin_lock_irqsave(&dca_lock, flags);
+ raw_spin_lock_irqsave(&dca_lock, flags);
if (list_empty(&dca_domains)) {
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
return;
}
@@ -116,7 +116,7 @@ static void unregister_dca_providers(void)
dca_free_domain(domain);
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
list_for_each_entry_safe(dca, _dca, &unregistered_providers, node) {
dca_sysfs_remove_provider(dca);
@@ -144,13 +144,8 @@ static struct dca_domain *dca_get_domain(struct device *dev)
domain = dca_find_domain(rc);
if (!domain) {
- if (dca_provider_ioat_ver_3_0(dev) && !list_empty(&dca_domains)) {
+ if (dca_provider_ioat_ver_3_0(dev) && !list_empty(&dca_domains))
dca_providers_blocked = 1;
- } else {
- domain = dca_allocate_domain(rc);
- if (domain)
- list_add(&domain->node, &dca_domains);
- }
}
return domain;
@@ -198,19 +193,19 @@ int dca_add_requester(struct device *dev)
if (!dev)
return -EFAULT;
- spin_lock_irqsave(&dca_lock, flags);
+ raw_spin_lock_irqsave(&dca_lock, flags);
/* check if the requester has not been added already */
dca = dca_find_provider_by_dev(dev);
if (dca) {
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
return -EEXIST;
}
pci_rc = dca_pci_rc_from_dev(dev);
domain = dca_find_domain(pci_rc);
if (!domain) {
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
return -ENODEV;
}
@@ -220,17 +215,17 @@ int dca_add_requester(struct device *dev)
break;
}
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
if (slot < 0)
return slot;
err = dca_sysfs_add_req(dca, dev, slot);
if (err) {
- spin_lock_irqsave(&dca_lock, flags);
+ raw_spin_lock_irqsave(&dca_lock, flags);
if (dca == dca_find_provider_by_dev(dev))
dca->ops->remove_requester(dca, dev);
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
return err;
}
@@ -251,14 +246,14 @@ int dca_remove_requester(struct device *dev)
if (!dev)
return -EFAULT;
- spin_lock_irqsave(&dca_lock, flags);
+ raw_spin_lock_irqsave(&dca_lock, flags);
dca = dca_find_provider_by_dev(dev);
if (!dca) {
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
return -ENODEV;
}
slot = dca->ops->remove_requester(dca, dev);
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
if (slot < 0)
return slot;
@@ -280,16 +275,16 @@ u8 dca_common_get_tag(struct device *dev, int cpu)
u8 tag;
unsigned long flags;
- spin_lock_irqsave(&dca_lock, flags);
+ raw_spin_lock_irqsave(&dca_lock, flags);
dca = dca_find_provider_by_dev(dev);
if (!dca) {
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
return -ENODEV;
}
tag = dca->ops->get_tag(dca, dev, cpu);
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
return tag;
}
@@ -360,36 +355,51 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev)
{
int err;
unsigned long flags;
- struct dca_domain *domain;
+ struct dca_domain *domain, *newdomain = NULL;
- spin_lock_irqsave(&dca_lock, flags);
+ raw_spin_lock_irqsave(&dca_lock, flags);
if (dca_providers_blocked) {
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
return -ENODEV;
}
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
err = dca_sysfs_add_provider(dca, dev);
if (err)
return err;
- spin_lock_irqsave(&dca_lock, flags);
+ raw_spin_lock_irqsave(&dca_lock, flags);
domain = dca_get_domain(dev);
if (!domain) {
+ struct pci_bus *rc;
+
if (dca_providers_blocked) {
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
dca_sysfs_remove_provider(dca);
unregister_dca_providers();
- } else {
- spin_unlock_irqrestore(&dca_lock, flags);
+ return -ENODEV;
+ }
+
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
+ rc = dca_pci_rc_from_dev(dev);
+ newdomain = dca_allocate_domain(rc);
+ if (!newdomain)
+ return -ENODEV;
+ raw_spin_lock_irqsave(&dca_lock, flags);
+ /* Recheck, we might have raced after dropping the lock */
+ domain = dca_get_domain(dev);
+ if (!domain) {
+ domain = newdomain;
+ newdomain = NULL;
+ list_add(&domain->node, &dca_domains);
}
- return -ENODEV;
}
list_add(&dca->node, &domain->dca_providers);
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_ADD, NULL);
+ kfree(newdomain);
return 0;
}
EXPORT_SYMBOL_GPL(register_dca_provider);
@@ -407,7 +417,7 @@ void unregister_dca_provider(struct dca_provider *dca, struct device *dev)
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_REMOVE, NULL);
- spin_lock_irqsave(&dca_lock, flags);
+ raw_spin_lock_irqsave(&dca_lock, flags);
list_del(&dca->node);
@@ -416,7 +426,7 @@ void unregister_dca_provider(struct dca_provider *dca, struct device *dev)
if (list_empty(&domain->dca_providers))
dca_free_domain(domain);
- spin_unlock_irqrestore(&dca_lock, flags);
+ raw_spin_unlock_irqrestore(&dca_lock, flags);
dca_sysfs_remove_provider(dca);
}
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
new file mode 100644
index 000000000000..643b055ed3cd
--- /dev/null
+++ b/drivers/devfreq/Kconfig
@@ -0,0 +1,75 @@
+config ARCH_HAS_DEVFREQ
+ bool
+ depends on ARCH_HAS_OPP
+ help
+ Denotes that the architecture supports DEVFREQ. If the architecture
+ supports multiple OPP entries per device and the frequency of the
+ devices with OPPs may be altered dynamically, the architecture
+ supports DEVFREQ.
+
+menuconfig PM_DEVFREQ
+ bool "Generic Dynamic Voltage and Frequency Scaling (DVFS) support"
+ depends on PM_OPP && ARCH_HAS_DEVFREQ
+ help
+ With OPP support, a device may have a list of frequencies and
+ voltages available. DEVFREQ, a generic DVFS framework can be
+ registered for a device with OPP support in order to let the
+ governor provided to DEVFREQ choose an operating frequency
+ based on the OPP's list and the policy given with DEVFREQ.
+
+ Each device may have its own governor and policy. DEVFREQ can
+ reevaluate the device state periodically and/or based on the
+ OPP list changes (each frequency/voltage pair in OPP may be
+ disabled or enabled).
+
+ Like some CPUs with CPUFREQ, a device may have multiple clocks.
+ However, because the clock frequencies of a single device are
+ determined by the single device's state, an instance of DEVFREQ
+ is attached to a single device and returns a "representative"
+ clock frequency from the OPP of the device, which is also attached
+ to a device by 1-to-1. The device registering DEVFREQ takes the
+ responsiblity to "interpret" the frequency listed in OPP and
+ to set its every clock accordingly with the "target" callback
+ given to DEVFREQ.
+
+if PM_DEVFREQ
+
+comment "DEVFREQ Governors"
+
+config DEVFREQ_GOV_SIMPLE_ONDEMAND
+ bool "Simple Ondemand"
+ help
+ Chooses frequency based on the recent load on the device. Works
+ similar as ONDEMAND governor of CPUFREQ does. A device with
+ Simple-Ondemand should be able to provide busy/total counter
+ values that imply the usage rate. A device may provide tuned
+ values to the governor with data field at devfreq_add_device().
+
+config DEVFREQ_GOV_PERFORMANCE
+ bool "Performance"
+ help
+ Sets the frequency at the maximum available frequency.
+ This governor always returns UINT_MAX as frequency so that
+ the DEVFREQ framework returns the highest frequency available
+ at any time.
+
+config DEVFREQ_GOV_POWERSAVE
+ bool "Powersave"
+ help
+ Sets the frequency at the minimum available frequency.
+ This governor always returns 0 as frequency so that
+ the DEVFREQ framework returns the lowest frequency available
+ at any time.
+
+config DEVFREQ_GOV_USERSPACE
+ bool "Userspace"
+ help
+ Sets the frequency at the user specified one.
+ This governor returns the user configured frequency if there
+ has been an input to /sys/devices/.../power/devfreq_set_freq.
+ Otherwise, the governor does not change the frequnecy
+ given at the initialization.
+
+comment "DEVFREQ Drivers"
+
+endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
new file mode 100644
index 000000000000..4564a89e970a
--- /dev/null
+++ b/drivers/devfreq/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_PM_DEVFREQ) += devfreq.o
+obj-$(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) += governor_simpleondemand.o
+obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE) += governor_performance.o
+obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o
+obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
new file mode 100644
index 000000000000..5d15b812377b
--- /dev/null
+++ b/drivers/devfreq/devfreq.c
@@ -0,0 +1,601 @@
+/*
+ * devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework
+ * for Non-CPU Devices.
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * MyungJoo Ham <myungjoo.ham@samsung.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/sched.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/opp.h>
+#include <linux/devfreq.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/printk.h>
+#include <linux/hrtimer.h>
+#include "governor.h"
+
+struct class *devfreq_class;
+
+/*
+ * devfreq_work periodically monitors every registered device.
+ * The minimum polling interval is one jiffy. The polling interval is
+ * determined by the minimum polling period among all polling devfreq
+ * devices. The resolution of polling interval is one jiffy.
+ */
+static bool polling;
+static struct workqueue_struct *devfreq_wq;
+static struct delayed_work devfreq_work;
+
+/* wait removing if this is to be removed */
+static struct devfreq *wait_remove_device;
+
+/* The list of all device-devfreq */
+static LIST_HEAD(devfreq_list);
+static DEFINE_MUTEX(devfreq_list_lock);
+
+/**
+ * find_device_devfreq() - find devfreq struct using device pointer
+ * @dev: device pointer used to lookup device devfreq.
+ *
+ * Search the list of device devfreqs and return the matched device's
+ * devfreq info. devfreq_list_lock should be held by the caller.
+ */
+static struct devfreq *find_device_devfreq(struct device *dev)
+{
+ struct devfreq *tmp_devfreq;
+
+ if (unlikely(IS_ERR_OR_NULL(dev))) {
+ pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+ WARN(!mutex_is_locked(&devfreq_list_lock),
+ "devfreq_list_lock must be locked.");
+
+ list_for_each_entry(tmp_devfreq, &devfreq_list, node) {
+ if (tmp_devfreq->dev.parent == dev)
+ return tmp_devfreq;
+ }
+
+ return ERR_PTR(-ENODEV);
+}
+
+/**
+ * update_devfreq() - Reevaluate the device and configure frequency.
+ * @devfreq: the devfreq instance.
+ *
+ * Note: Lock devfreq->lock before calling update_devfreq
+ * This function is exported for governors.
+ */
+int update_devfreq(struct devfreq *devfreq)
+{
+ unsigned long freq;
+ int err = 0;
+
+ if (!mutex_is_locked(&devfreq->lock)) {
+ WARN(true, "devfreq->lock must be locked by the caller.\n");
+ return -EINVAL;
+ }
+
+ /* Reevaluate the proper frequency */
+ err = devfreq->governor->get_target_freq(devfreq, &freq);
+ if (err)
+ return err;
+
+ err = devfreq->profile->target(devfreq->dev.parent, &freq);
+ if (err)
+ return err;
+
+ devfreq->previous_freq = freq;
+ return err;
+}
+
+/**
+ * devfreq_notifier_call() - Notify that the device frequency requirements
+ * has been changed out of devfreq framework.
+ * @nb the notifier_block (supposed to be devfreq->nb)
+ * @type not used
+ * @devp not used
+ *
+ * Called by a notifier that uses devfreq->nb.
+ */
+static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
+ void *devp)
+{
+ struct devfreq *devfreq = container_of(nb, struct devfreq, nb);
+ int ret;
+
+ mutex_lock(&devfreq->lock);
+ ret = update_devfreq(devfreq);
+ mutex_unlock(&devfreq->lock);
+
+ return ret;
+}
+
+/**
+ * _remove_devfreq() - Remove devfreq from the device.
+ * @devfreq: the devfreq struct
+ * @skip: skip calling device_unregister().
+ *
+ * Note that the caller should lock devfreq->lock before calling
+ * this. _remove_devfreq() will unlock it and free devfreq
+ * internally. devfreq_list_lock should be locked by the caller
+ * as well (not relased at return)
+ *
+ * Lock usage:
+ * devfreq->lock: locked before call.
+ * unlocked at return (and freed)
+ * devfreq_list_lock: locked before call.
+ * kept locked at return.
+ * if devfreq is centrally polled.
+ *
+ * Freed memory:
+ * devfreq
+ */
+static void _remove_devfreq(struct devfreq *devfreq, bool skip)
+{
+ if (!mutex_is_locked(&devfreq->lock)) {
+ WARN(true, "devfreq->lock must be locked by the caller.\n");
+ return;
+ }
+ if (!devfreq->governor->no_central_polling &&
+ !mutex_is_locked(&devfreq_list_lock)) {
+ WARN(true, "devfreq_list_lock must be locked by the caller.\n");
+ return;
+ }
+
+ if (devfreq->being_removed)
+ return;
+
+ devfreq->being_removed = true;
+
+ if (devfreq->profile->exit)
+ devfreq->profile->exit(devfreq->dev.parent);
+
+ if (devfreq->governor->exit)
+ devfreq->governor->exit(devfreq);
+
+ if (!skip && get_device(&devfreq->dev)) {
+ device_unregister(&devfreq->dev);
+ put_device(&devfreq->dev);
+ }
+
+ if (!devfreq->governor->no_central_polling)
+ list_del(&devfreq->node);
+
+ mutex_unlock(&devfreq->lock);
+ mutex_destroy(&devfreq->lock);
+
+ kfree(devfreq);
+}
+
+/**
+ * devfreq_dev_release() - Callback for struct device to release the device.
+ * @dev: the devfreq device
+ *
+ * This calls _remove_devfreq() if _remove_devfreq() is not called.
+ * Note that devfreq_dev_release() could be called by _remove_devfreq() as
+ * well as by others unregistering the device.
+ */
+static void devfreq_dev_release(struct device *dev)
+{
+ struct devfreq *devfreq = to_devfreq(dev);
+ bool central_polling = !devfreq->governor->no_central_polling;
+
+ /*
+ * If devfreq_dev_release() was called by device_unregister() of
+ * _remove_devfreq(), we cannot mutex_lock(&devfreq->lock) and
+ * being_removed is already set. This also partially checks the case
+ * where devfreq_dev_release() is called from a thread other than
+ * the one called _remove_devfreq(); however, this case is
+ * dealt completely with another following being_removed check.
+ *
+ * Because being_removed is never being
+ * unset, we do not need to worry about race conditions on
+ * being_removed.
+ */
+ if (devfreq->being_removed)
+ return;
+
+ if (central_polling)
+ mutex_lock(&devfreq_list_lock);
+
+ mutex_lock(&devfreq->lock);
+
+ /*
+ * Check being_removed flag again for the case where
+ * devfreq_dev_release() was called in a thread other than the one
+ * possibly called _remove_devfreq().
+ */
+ if (devfreq->being_removed) {
+ mutex_unlock(&devfreq->lock);
+ goto out;
+ }
+
+ /* devfreq->lock is unlocked and removed in _removed_devfreq() */
+ _remove_devfreq(devfreq, true);
+
+out:
+ if (central_polling)
+ mutex_unlock(&devfreq_list_lock);
+}
+
+/**
+ * devfreq_monitor() - Periodically poll devfreq objects.
+ * @work: the work struct used to run devfreq_monitor periodically.
+ *
+ */
+static void devfreq_monitor(struct work_struct *work)
+{
+ static unsigned long last_polled_at;
+ struct devfreq *devfreq, *tmp;
+ int error;
+ unsigned long jiffies_passed;
+ unsigned long next_jiffies = ULONG_MAX, now = jiffies;
+ struct device *dev;
+
+ /* Initially last_polled_at = 0, polling every device at bootup */
+ jiffies_passed = now - last_polled_at;
+ last_polled_at = now;
+ if (jiffies_passed == 0)
+ jiffies_passed = 1;
+
+ mutex_lock(&devfreq_list_lock);
+ list_for_each_entry_safe(devfreq, tmp, &devfreq_list, node) {
+ mutex_lock(&devfreq->lock);
+ dev = devfreq->dev.parent;
+
+ /* Do not remove tmp for a while */
+ wait_remove_device = tmp;
+
+ if (devfreq->governor->no_central_polling ||
+ devfreq->next_polling == 0) {
+ mutex_unlock(&devfreq->lock);
+ continue;
+ }
+ mutex_unlock(&devfreq_list_lock);
+
+ /*
+ * Reduce more next_polling if devfreq_wq took an extra
+ * delay. (i.e., CPU has been idled.)
+ */
+ if (devfreq->next_polling <= jiffies_passed) {
+ error = update_devfreq(devfreq);
+
+ /* Remove a devfreq with an error. */
+ if (error && error != -EAGAIN) {
+
+ dev_err(dev, "Due to update_devfreq error(%d), devfreq(%s) is removed from the device\n",
+ error, devfreq->governor->name);
+
+ /*
+ * Unlock devfreq before locking the list
+ * in order to avoid deadlock with
+ * find_device_devfreq or others
+ */
+ mutex_unlock(&devfreq->lock);
+ mutex_lock(&devfreq_list_lock);
+ /* Check if devfreq is already removed */
+ if (IS_ERR(find_device_devfreq(dev)))
+ continue;
+ mutex_lock(&devfreq->lock);
+ /* This unlocks devfreq->lock and free it */
+ _remove_devfreq(devfreq, false);
+ continue;
+ }
+ devfreq->next_polling = devfreq->polling_jiffies;
+ } else {
+ devfreq->next_polling -= jiffies_passed;
+ }
+
+ if (devfreq->next_polling)
+ next_jiffies = (next_jiffies > devfreq->next_polling) ?
+ devfreq->next_polling : next_jiffies;
+
+ mutex_unlock(&devfreq->lock);
+ mutex_lock(&devfreq_list_lock);
+ }
+ wait_remove_device = NULL;
+ mutex_unlock(&devfreq_list_lock);
+
+ if (next_jiffies > 0 && next_jiffies < ULONG_MAX) {
+ polling = true;
+ queue_delayed_work(devfreq_wq, &devfreq_work, next_jiffies);
+ } else {
+ polling = false;
+ }
+}
+
+/**
+ * devfreq_add_device() - Add devfreq feature to the device
+ * @dev: the device to add devfreq feature.
+ * @profile: device-specific profile to run devfreq.
+ * @governor: the policy to choose frequency.
+ * @data: private data for the governor. The devfreq framework does not
+ * touch this value.
+ */
+struct devfreq *devfreq_add_device(struct device *dev,
+ struct devfreq_dev_profile *profile,
+ const struct devfreq_governor *governor,
+ void *data)
+{
+ struct devfreq *devfreq;
+ int err = 0;
+
+ if (!dev || !profile || !governor) {
+ dev_err(dev, "%s: Invalid parameters.\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+
+ if (!governor->no_central_polling) {
+ mutex_lock(&devfreq_list_lock);
+ devfreq = find_device_devfreq(dev);
+ mutex_unlock(&devfreq_list_lock);
+ if (!IS_ERR(devfreq)) {
+ dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__);
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL);
+ if (!devfreq) {
+ dev_err(dev, "%s: Unable to create devfreq for the device\n",
+ __func__);
+ err = -ENOMEM;
+ goto out;
+ }
+
+ mutex_init(&devfreq->lock);
+ mutex_lock(&devfreq->lock);
+ devfreq->dev.parent = dev;
+ devfreq->dev.class = devfreq_class;
+ devfreq->dev.release = devfreq_dev_release;
+ devfreq->profile = profile;
+ devfreq->governor = governor;
+ devfreq->previous_freq = profile->initial_freq;
+ devfreq->data = data;
+ devfreq->next_polling = devfreq->polling_jiffies
+ = msecs_to_jiffies(devfreq->profile->polling_ms);
+ devfreq->nb.notifier_call = devfreq_notifier_call;
+
+ dev_set_name(&devfreq->dev, dev_name(dev));
+ err = device_register(&devfreq->dev);
+ if (err) {
+ put_device(&devfreq->dev);
+ goto err_dev;
+ }
+
+ if (governor->init)
+ err = governor->init(devfreq);
+ if (err)
+ goto err_init;
+
+ mutex_unlock(&devfreq->lock);
+
+ if (governor->no_central_polling)
+ goto out;
+
+ mutex_lock(&devfreq_list_lock);
+
+ list_add(&devfreq->node, &devfreq_list);
+
+ if (devfreq_wq && devfreq->next_polling && !polling) {
+ polling = true;
+ queue_delayed_work(devfreq_wq, &devfreq_work,
+ devfreq->next_polling);
+ }
+ mutex_unlock(&devfreq_list_lock);
+ goto out;
+err_init:
+ device_unregister(&devfreq->dev);
+err_dev:
+ mutex_unlock(&devfreq->lock);
+ kfree(devfreq);
+out:
+ if (err)
+ return ERR_PTR(err);
+ else
+ return devfreq;
+}
+
+/**
+ * devfreq_remove_device() - Remove devfreq feature from a device.
+ * @devfreq the devfreq instance to be removed
+ */
+int devfreq_remove_device(struct devfreq *devfreq)
+{
+ if (!devfreq)
+ return -EINVAL;
+
+ if (!devfreq->governor->no_central_polling) {
+ mutex_lock(&devfreq_list_lock);
+ while (wait_remove_device == devfreq) {
+ mutex_unlock(&devfreq_list_lock);
+ schedule();
+ mutex_lock(&devfreq_list_lock);
+ }
+ }
+
+ mutex_lock(&devfreq->lock);
+ _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */
+
+ if (!devfreq->governor->no_central_polling)
+ mutex_unlock(&devfreq_list_lock);
+
+ return 0;
+}
+
+static ssize_t show_governor(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
+}
+
+static ssize_t show_freq(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq);
+}
+
+static ssize_t show_polling_interval(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", to_devfreq(dev)->profile->polling_ms);
+}
+
+static ssize_t store_polling_interval(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct devfreq *df = to_devfreq(dev);
+ unsigned int value;
+ int ret;
+
+ ret = sscanf(buf, "%u", &value);
+ if (ret != 1)
+ goto out;
+
+ mutex_lock(&df->lock);
+ df->profile->polling_ms = value;
+ df->next_polling = df->polling_jiffies
+ = msecs_to_jiffies(value);
+ mutex_unlock(&df->lock);
+
+ ret = count;
+
+ if (df->governor->no_central_polling)
+ goto out;
+
+ mutex_lock(&devfreq_list_lock);
+ if (df->next_polling > 0 && !polling) {
+ polling = true;
+ queue_delayed_work(devfreq_wq, &devfreq_work,
+ df->next_polling);
+ }
+ mutex_unlock(&devfreq_list_lock);
+out:
+ return ret;
+}
+
+static ssize_t show_central_polling(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n",
+ !to_devfreq(dev)->governor->no_central_polling);
+}
+
+static struct device_attribute devfreq_attrs[] = {
+ __ATTR(governor, S_IRUGO, show_governor, NULL),
+ __ATTR(cur_freq, S_IRUGO, show_freq, NULL),
+ __ATTR(central_polling, S_IRUGO, show_central_polling, NULL),
+ __ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
+ store_polling_interval),
+ { },
+};
+
+/**
+ * devfreq_start_polling() - Initialize data structure for devfreq framework and
+ * start polling registered devfreq devices.
+ */
+static int __init devfreq_start_polling(void)
+{
+ mutex_lock(&devfreq_list_lock);
+ polling = false;
+ devfreq_wq = create_freezable_workqueue("devfreq_wq");
+ INIT_DELAYED_WORK_DEFERRABLE(&devfreq_work, devfreq_monitor);
+ mutex_unlock(&devfreq_list_lock);
+
+ devfreq_monitor(&devfreq_work.work);
+ return 0;
+}
+late_initcall(devfreq_start_polling);
+
+static int __init devfreq_init(void)
+{
+ devfreq_class = class_create(THIS_MODULE, "devfreq");
+ if (IS_ERR(devfreq_class)) {
+ pr_err("%s: couldn't create class\n", __FILE__);
+ return PTR_ERR(devfreq_class);
+ }
+ devfreq_class->dev_attrs = devfreq_attrs;
+ return 0;
+}
+subsys_initcall(devfreq_init);
+
+static void __exit devfreq_exit(void)
+{
+ class_destroy(devfreq_class);
+}
+module_exit(devfreq_exit);
+
+/*
+ * The followings are helper functions for devfreq user device drivers with
+ * OPP framework.
+ */
+
+/**
+ * devfreq_recommended_opp() - Helper function to get proper OPP for the
+ * freq value given to target callback.
+ * @dev The devfreq user device. (parent of devfreq)
+ * @freq The frequency given to target function
+ *
+ */
+struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq)
+{
+ struct opp *opp = opp_find_freq_ceil(dev, freq);
+
+ if (opp == ERR_PTR(-ENODEV))
+ opp = opp_find_freq_floor(dev, freq);
+ return opp;
+}
+
+/**
+ * devfreq_register_opp_notifier() - Helper function to get devfreq notified
+ * for any changes in the OPP availability
+ * changes
+ * @dev The devfreq user device. (parent of devfreq)
+ * @devfreq The devfreq object.
+ */
+int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
+{
+ struct srcu_notifier_head *nh = opp_get_notifier(dev);
+
+ if (IS_ERR(nh))
+ return PTR_ERR(nh);
+ return srcu_notifier_chain_register(nh, &devfreq->nb);
+}
+
+/**
+ * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq
+ * notified for any changes in the OPP
+ * availability changes anymore.
+ * @dev The devfreq user device. (parent of devfreq)
+ * @devfreq The devfreq object.
+ *
+ * At exit() callback of devfreq_dev_profile, this must be included if
+ * devfreq_recommended_opp is used.
+ */
+int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
+{
+ struct srcu_notifier_head *nh = opp_get_notifier(dev);
+
+ if (IS_ERR(nh))
+ return PTR_ERR(nh);
+ return srcu_notifier_chain_unregister(nh, &devfreq->nb);
+}
+
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("devfreq class support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
new file mode 100644
index 000000000000..ea7f13c58ded
--- /dev/null
+++ b/drivers/devfreq/governor.h
@@ -0,0 +1,24 @@
+/*
+ * governor.h - internal header for devfreq governors.
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * MyungJoo Ham <myungjoo.ham@samsung.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 header is for devfreq governors in drivers/devfreq/
+ */
+
+#ifndef _GOVERNOR_H
+#define _GOVERNOR_H
+
+#include <linux/devfreq.h>
+
+#define to_devfreq(DEV) container_of((DEV), struct devfreq, dev)
+
+/* Caution: devfreq->lock must be locked before calling update_devfreq */
+extern int update_devfreq(struct devfreq *devfreq);
+
+#endif /* _GOVERNOR_H */
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
new file mode 100644
index 000000000000..c0596b291761
--- /dev/null
+++ b/drivers/devfreq/governor_performance.c
@@ -0,0 +1,29 @@
+/*
+ * linux/drivers/devfreq/governor_performance.c
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * MyungJoo Ham <myungjoo.ham@samsung.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/devfreq.h>
+
+static int devfreq_performance_func(struct devfreq *df,
+ unsigned long *freq)
+{
+ /*
+ * target callback should be able to get floor value as
+ * said in devfreq.h
+ */
+ *freq = UINT_MAX;
+ return 0;
+}
+
+const struct devfreq_governor devfreq_performance = {
+ .name = "performance",
+ .get_target_freq = devfreq_performance_func,
+ .no_central_polling = true,
+};
diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c
new file mode 100644
index 000000000000..2483a85a266f
--- /dev/null
+++ b/drivers/devfreq/governor_powersave.c
@@ -0,0 +1,29 @@
+/*
+ * linux/drivers/devfreq/governor_powersave.c
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * MyungJoo Ham <myungjoo.ham@samsung.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/devfreq.h>
+
+static int devfreq_powersave_func(struct devfreq *df,
+ unsigned long *freq)
+{
+ /*
+ * target callback should be able to get ceiling value as
+ * said in devfreq.h
+ */
+ *freq = 0;
+ return 0;
+}
+
+const struct devfreq_governor devfreq_powersave = {
+ .name = "powersave",
+ .get_target_freq = devfreq_powersave_func,
+ .no_central_polling = true,
+};
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
new file mode 100644
index 000000000000..efad8dcf9028
--- /dev/null
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -0,0 +1,88 @@
+/*
+ * linux/drivers/devfreq/governor_simpleondemand.c
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * MyungJoo Ham <myungjoo.ham@samsung.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/errno.h>
+#include <linux/devfreq.h>
+#include <linux/math64.h>
+
+/* Default constants for DevFreq-Simple-Ondemand (DFSO) */
+#define DFSO_UPTHRESHOLD (90)
+#define DFSO_DOWNDIFFERENCTIAL (5)
+static int devfreq_simple_ondemand_func(struct devfreq *df,
+ unsigned long *freq)
+{
+ struct devfreq_dev_status stat;
+ int err = df->profile->get_dev_status(df->dev.parent, &stat);
+ unsigned long long a, b;
+ unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
+ unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
+ struct devfreq_simple_ondemand_data *data = df->data;
+
+ if (err)
+ return err;
+
+ if (data) {
+ if (data->upthreshold)
+ dfso_upthreshold = data->upthreshold;
+ if (data->downdifferential)
+ dfso_downdifferential = data->downdifferential;
+ }
+ if (dfso_upthreshold > 100 ||
+ dfso_upthreshold < dfso_downdifferential)
+ return -EINVAL;
+
+ /* Assume MAX if it is going to be divided by zero */
+ if (stat.total_time == 0) {
+ *freq = UINT_MAX;
+ return 0;
+ }
+
+ /* Prevent overflow */
+ if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) {
+ stat.busy_time >>= 7;
+ stat.total_time >>= 7;
+ }
+
+ /* Set MAX if it's busy enough */
+ if (stat.busy_time * 100 >
+ stat.total_time * dfso_upthreshold) {
+ *freq = UINT_MAX;
+ return 0;
+ }
+
+ /* Set MAX if we do not know the initial frequency */
+ if (stat.current_frequency == 0) {
+ *freq = UINT_MAX;
+ return 0;
+ }
+
+ /* Keep the current frequency */
+ if (stat.busy_time * 100 >
+ stat.total_time * (dfso_upthreshold - dfso_downdifferential)) {
+ *freq = stat.current_frequency;
+ return 0;
+ }
+
+ /* Set the desired frequency based on the load */
+ a = stat.busy_time;
+ a *= stat.current_frequency;
+ b = div_u64(a, stat.total_time);
+ b *= 100;
+ b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
+ *freq = (unsigned long) b;
+
+ return 0;
+}
+
+const struct devfreq_governor devfreq_simple_ondemand = {
+ .name = "simple_ondemand",
+ .get_target_freq = devfreq_simple_ondemand_func,
+};
diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c
new file mode 100644
index 000000000000..4f8b563da782
--- /dev/null
+++ b/drivers/devfreq/governor_userspace.c
@@ -0,0 +1,116 @@
+/*
+ * linux/drivers/devfreq/governor_simpleondemand.c
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * MyungJoo Ham <myungjoo.ham@samsung.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/slab.h>
+#include <linux/device.h>
+#include <linux/devfreq.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include "governor.h"
+
+struct userspace_data {
+ unsigned long user_frequency;
+ bool valid;
+};
+
+static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq)
+{
+ struct userspace_data *data = df->data;
+
+ if (!data->valid)
+ *freq = df->previous_freq; /* No user freq specified yet */
+ else
+ *freq = data->user_frequency;
+ return 0;
+}
+
+static ssize_t store_freq(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct devfreq *devfreq = to_devfreq(dev);
+ struct userspace_data *data;
+ unsigned long wanted;
+ int err = 0;
+
+
+ mutex_lock(&devfreq->lock);
+ data = devfreq->data;
+
+ sscanf(buf, "%lu", &wanted);
+ data->user_frequency = wanted;
+ data->valid = true;
+ err = update_devfreq(devfreq);
+ if (err == 0)
+ err = count;
+ mutex_unlock(&devfreq->lock);
+ return err;
+}
+
+static ssize_t show_freq(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct devfreq *devfreq = to_devfreq(dev);
+ struct userspace_data *data;
+ int err = 0;
+
+ mutex_lock(&devfreq->lock);
+ data = devfreq->data;
+
+ if (data->valid)
+ err = sprintf(buf, "%lu\n", data->user_frequency);
+ else
+ err = sprintf(buf, "undefined\n");
+ mutex_unlock(&devfreq->lock);
+ return err;
+}
+
+static DEVICE_ATTR(set_freq, 0644, show_freq, store_freq);
+static struct attribute *dev_entries[] = {
+ &dev_attr_set_freq.attr,
+ NULL,
+};
+static struct attribute_group dev_attr_group = {
+ .name = "userspace",
+ .attrs = dev_entries,
+};
+
+static int userspace_init(struct devfreq *devfreq)
+{
+ int err = 0;
+ struct userspace_data *data = kzalloc(sizeof(struct userspace_data),
+ GFP_KERNEL);
+
+ if (!data) {
+ err = -ENOMEM;
+ goto out;
+ }
+ data->valid = false;
+ devfreq->data = data;
+
+ err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group);
+out:
+ return err;
+}
+
+static void userspace_exit(struct devfreq *devfreq)
+{
+ sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group);
+ kfree(devfreq->data);
+ devfreq->data = NULL;
+}
+
+const struct devfreq_governor devfreq_userspace = {
+ .name = "userspace",
+ .get_target_freq = devfreq_userspace_func,
+ .init = userspace_init,
+ .exit = userspace_exit,
+ .no_central_polling = true,
+};
diff --git a/drivers/dma/ipu/ipu_irq.c b/drivers/dma/ipu/ipu_irq.c
index ab8a4eff072a..a71f55e72be9 100644
--- a/drivers/dma/ipu/ipu_irq.c
+++ b/drivers/dma/ipu/ipu_irq.c
@@ -81,7 +81,7 @@ static struct ipu_irq_map irq_map[CONFIG_MX3_IPU_IRQS];
/* Protects allocations from the above array of maps */
static DEFINE_MUTEX(map_lock);
/* Protects register accesses and individual mappings */
-static DEFINE_SPINLOCK(bank_lock);
+static DEFINE_RAW_SPINLOCK(bank_lock);
static struct ipu_irq_map *src2map(unsigned int src)
{
@@ -101,11 +101,11 @@ static void ipu_irq_unmask(struct irq_data *d)
uint32_t reg;
unsigned long lock_flags;
- spin_lock_irqsave(&bank_lock, lock_flags);
+ raw_spin_lock_irqsave(&bank_lock, lock_flags);
bank = map->bank;
if (!bank) {
- spin_unlock_irqrestore(&bank_lock, lock_flags);
+ raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
return;
}
@@ -114,7 +114,7 @@ static void ipu_irq_unmask(struct irq_data *d)
reg |= (1UL << (map->source & 31));
ipu_write_reg(bank->ipu, reg, bank->control);
- spin_unlock_irqrestore(&bank_lock, lock_flags);
+ raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
}
static void ipu_irq_mask(struct irq_data *d)
@@ -124,11 +124,11 @@ static void ipu_irq_mask(struct irq_data *d)
uint32_t reg;
unsigned long lock_flags;
- spin_lock_irqsave(&bank_lock, lock_flags);
+ raw_spin_lock_irqsave(&bank_lock, lock_flags);
bank = map->bank;
if (!bank) {
- spin_unlock_irqrestore(&bank_lock, lock_flags);
+ raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
return;
}
@@ -137,7 +137,7 @@ static void ipu_irq_mask(struct irq_data *d)
reg &= ~(1UL << (map->source & 31));
ipu_write_reg(bank->ipu, reg, bank->control);
- spin_unlock_irqrestore(&bank_lock, lock_flags);
+ raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
}
static void ipu_irq_ack(struct irq_data *d)
@@ -146,17 +146,17 @@ static void ipu_irq_ack(struct irq_data *d)
struct ipu_irq_bank *bank;
unsigned long lock_flags;
- spin_lock_irqsave(&bank_lock, lock_flags);
+ raw_spin_lock_irqsave(&bank_lock, lock_flags);
bank = map->bank;
if (!bank) {
- spin_unlock_irqrestore(&bank_lock, lock_flags);
+ raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
return;
}
ipu_write_reg(bank->ipu, 1UL << (map->source & 31), bank->status);
- spin_unlock_irqrestore(&bank_lock, lock_flags);
+ raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
}
/**
@@ -172,11 +172,11 @@ bool ipu_irq_status(unsigned int irq)
unsigned long lock_flags;
bool ret;
- spin_lock_irqsave(&bank_lock, lock_flags);
+ raw_spin_lock_irqsave(&bank_lock, lock_flags);
bank = map->bank;
ret = bank && ipu_read_reg(bank->ipu, bank->status) &
(1UL << (map->source & 31));
- spin_unlock_irqrestore(&bank_lock, lock_flags);
+ raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
return ret;
}
@@ -213,10 +213,10 @@ int ipu_irq_map(unsigned int source)
if (irq_map[i].source < 0) {
unsigned long lock_flags;
- spin_lock_irqsave(&bank_lock, lock_flags);
+ raw_spin_lock_irqsave(&bank_lock, lock_flags);
irq_map[i].source = source;
irq_map[i].bank = irq_bank + source / 32;
- spin_unlock_irqrestore(&bank_lock, lock_flags);
+ raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
ret = irq_map[i].irq;
pr_debug("IPU: mapped source %u to IRQ %u\n",
@@ -252,10 +252,10 @@ int ipu_irq_unmap(unsigned int source)
pr_debug("IPU: unmapped source %u from IRQ %u\n",
source, irq_map[i].irq);
- spin_lock_irqsave(&bank_lock, lock_flags);
+ raw_spin_lock_irqsave(&bank_lock, lock_flags);
irq_map[i].source = -EINVAL;
irq_map[i].bank = NULL;
- spin_unlock_irqrestore(&bank_lock, lock_flags);
+ raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
ret = 0;
break;
@@ -276,7 +276,7 @@ static void ipu_irq_err(unsigned int irq, struct irq_desc *desc)
for (i = IPU_IRQ_NR_FN_BANKS; i < IPU_IRQ_NR_BANKS; i++) {
struct ipu_irq_bank *bank = irq_bank + i;
- spin_lock(&bank_lock);
+ raw_spin_lock(&bank_lock);
status = ipu_read_reg(ipu, bank->status);
/*
* Don't think we have to clear all interrupts here, they will
@@ -284,18 +284,18 @@ static void ipu_irq_err(unsigned int irq, struct irq_desc *desc)
* might want to clear unhandled interrupts after the loop...
*/
status &= ipu_read_reg(ipu, bank->control);
- spin_unlock(&bank_lock);
+ raw_spin_unlock(&bank_lock);
while ((line = ffs(status))) {
struct ipu_irq_map *map;
line--;
status &= ~(1UL << line);
- spin_lock(&bank_lock);
+ raw_spin_lock(&bank_lock);
map = src2map(32 * i + line);
if (map)
irq = map->irq;
- spin_unlock(&bank_lock);
+ raw_spin_unlock(&bank_lock);
if (!map) {
pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
@@ -317,22 +317,22 @@ static void ipu_irq_fn(unsigned int irq, struct irq_desc *desc)
for (i = 0; i < IPU_IRQ_NR_FN_BANKS; i++) {
struct ipu_irq_bank *bank = irq_bank + i;
- spin_lock(&bank_lock);
+ raw_spin_lock(&bank_lock);
status = ipu_read_reg(ipu, bank->status);
/* Not clearing all interrupts, see above */
status &= ipu_read_reg(ipu, bank->control);
- spin_unlock(&bank_lock);
+ raw_spin_unlock(&bank_lock);
while ((line = ffs(status))) {
struct ipu_irq_map *map;
line--;
status &= ~(1UL << line);
- spin_lock(&bank_lock);
+ raw_spin_lock(&bank_lock);
map = src2map(32 * i + line);
if (map)
irq = map->irq;
- spin_unlock(&bank_lock);
+ raw_spin_unlock(&bank_lock);
if (!map) {
pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index af1a17d42bd7..203361e4ef94 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -41,7 +41,7 @@ config EDAC_DEBUG
config EDAC_DECODE_MCE
tristate "Decode MCEs in human-readable form (only on AMD for now)"
- depends on CPU_SUP_AMD && X86_MCE
+ depends on CPU_SUP_AMD && X86_MCE_AMD
default y
---help---
Enable this option if you want to decode Machine Check Exceptions
@@ -71,9 +71,6 @@ config EDAC_MM_EDAC
occurred so that a particular failing memory module can be
replaced. If unsure, select 'Y'.
-config EDAC_MCE
- bool
-
config EDAC_AMD64
tristate "AMD64 (Opteron, Athlon64) K8, F10h"
depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE
@@ -173,8 +170,7 @@ config EDAC_I5400
config EDAC_I7CORE
tristate "Intel i7 Core (Nehalem) processors"
- depends on EDAC_MM_EDAC && PCI && X86
- select EDAC_MCE
+ depends on EDAC_MM_EDAC && PCI && X86 && X86_MCE_INTEL
help
Support for error detection and correction the Intel
i7 Core (Nehalem) Integrated Memory Controller that exists on
@@ -216,6 +212,14 @@ config EDAC_I7300
Support for error detection and correction the Intel
Clarksboro MCH (Intel 7300 chipset).
+config EDAC_SBRIDGE
+ tristate "Intel Sandy-Bridge Integrated MC"
+ depends on EDAC_MM_EDAC && PCI && X86 && X86_MCE_INTEL
+ depends on EXPERIMENTAL
+ help
+ Support for error detection and correction the Intel
+ Sandy Bridge Integrated Memory Controller.
+
config EDAC_MPC85XX
tristate "Freescale MPC83xx / MPC85xx"
depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx)
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 3e239133e29e..196a63dd37c5 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -8,7 +8,6 @@
obj-$(CONFIG_EDAC) := edac_stub.o
obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
-obj-$(CONFIG_EDAC_MCE) += edac_mce.o
edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
edac_core-y += edac_module.o edac_device_sysfs.o
@@ -29,6 +28,7 @@ obj-$(CONFIG_EDAC_I5100) += i5100_edac.o
obj-$(CONFIG_EDAC_I5400) += i5400_edac.o
obj-$(CONFIG_EDAC_I7300) += i7300_edac.o
obj-$(CONFIG_EDAC_I7CORE) += i7core_edac.o
+obj-$(CONFIG_EDAC_SBRIDGE) += sb_edac.o
obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 9a8bebcf6b17..c9eee6d33e9a 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -114,10 +114,22 @@ static int f10_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
}
+/*
+ * Select DCT to which PCI cfg accesses are routed
+ */
+static void f15h_select_dct(struct amd64_pvt *pvt, u8 dct)
+{
+ u32 reg = 0;
+
+ amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, &reg);
+ reg &= 0xfffffffe;
+ reg |= dct;
+ amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg);
+}
+
static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
const char *func)
{
- u32 reg = 0;
u8 dct = 0;
if (addr >= 0x140 && addr <= 0x1a0) {
@@ -125,10 +137,7 @@ static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
addr -= 0x100;
}
- amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, &reg);
- reg &= 0xfffffffe;
- reg |= dct;
- amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg);
+ f15h_select_dct(pvt, dct);
return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
}
@@ -198,6 +207,10 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
if (boot_cpu_data.x86 == 0xf)
min_scrubrate = 0x0;
+ /* F15h Erratum #505 */
+ if (boot_cpu_data.x86 == 0x15)
+ f15h_select_dct(pvt, 0);
+
return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate);
}
@@ -207,6 +220,10 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
u32 scrubval = 0;
int i, retval = -EINVAL;
+ /* F15h Erratum #505 */
+ if (boot_cpu_data.x86 == 0x15)
+ f15h_select_dct(pvt, 0);
+
amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
scrubval = scrubval & 0x001F;
@@ -751,10 +768,10 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16);
* Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs
* are ECC capable.
*/
-static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt)
+static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt)
{
u8 bit;
- enum dev_type edac_cap = EDAC_FLAG_NONE;
+ unsigned long edac_cap = EDAC_FLAG_NONE;
bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= K8_REV_F)
? 19
@@ -1953,11 +1970,9 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
amd64_handle_ue(mci, m);
}
-void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg)
+void amd64_decode_bus_error(int node_id, struct mce *m)
{
- struct mem_ctl_info *mci = mcis[node_id];
-
- __amd64_decode_bus_error(mci, m);
+ __amd64_decode_bus_error(mcis[node_id], m);
}
/*
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index 55b8278bb172..fe90cd4a7ebc 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -34,11 +34,10 @@
#include <linux/platform_device.h>
#include <linux/sysdev.h>
#include <linux/workqueue.h>
+#include <linux/edac.h>
-#define EDAC_MC_LABEL_LEN 31
#define EDAC_DEVICE_NAME_LEN 31
#define EDAC_ATTRIB_VALUE_LEN 15
-#define MC_PROC_NAME_MAX_LEN 7
#if PAGE_SHIFT < 20
#define PAGES_TO_MiB(pages) ((pages) >> (20 - PAGE_SHIFT))
@@ -101,353 +100,6 @@ extern int edac_debug_level;
#define edac_dev_name(dev) (dev)->dev_name
-/* memory devices */
-enum dev_type {
- DEV_UNKNOWN = 0,
- DEV_X1,
- DEV_X2,
- DEV_X4,
- DEV_X8,
- DEV_X16,
- DEV_X32, /* Do these parts exist? */
- DEV_X64 /* Do these parts exist? */
-};
-
-#define DEV_FLAG_UNKNOWN BIT(DEV_UNKNOWN)
-#define DEV_FLAG_X1 BIT(DEV_X1)
-#define DEV_FLAG_X2 BIT(DEV_X2)
-#define DEV_FLAG_X4 BIT(DEV_X4)
-#define DEV_FLAG_X8 BIT(DEV_X8)
-#define DEV_FLAG_X16 BIT(DEV_X16)
-#define DEV_FLAG_X32 BIT(DEV_X32)
-#define DEV_FLAG_X64 BIT(DEV_X64)
-
-/* memory types */
-enum mem_type {
- MEM_EMPTY = 0, /* Empty csrow */
- MEM_RESERVED, /* Reserved csrow type */
- MEM_UNKNOWN, /* Unknown csrow type */
- MEM_FPM, /* Fast page mode */
- MEM_EDO, /* Extended data out */
- MEM_BEDO, /* Burst Extended data out */
- MEM_SDR, /* Single data rate SDRAM */
- MEM_RDR, /* Registered single data rate SDRAM */
- MEM_DDR, /* Double data rate SDRAM */
- MEM_RDDR, /* Registered Double data rate SDRAM */
- MEM_RMBS, /* Rambus DRAM */
- MEM_DDR2, /* DDR2 RAM */
- MEM_FB_DDR2, /* fully buffered DDR2 */
- MEM_RDDR2, /* Registered DDR2 RAM */
- MEM_XDR, /* Rambus XDR */
- MEM_DDR3, /* DDR3 RAM */
- MEM_RDDR3, /* Registered DDR3 RAM */
-};
-
-#define MEM_FLAG_EMPTY BIT(MEM_EMPTY)
-#define MEM_FLAG_RESERVED BIT(MEM_RESERVED)
-#define MEM_FLAG_UNKNOWN BIT(MEM_UNKNOWN)
-#define MEM_FLAG_FPM BIT(MEM_FPM)
-#define MEM_FLAG_EDO BIT(MEM_EDO)
-#define MEM_FLAG_BEDO BIT(MEM_BEDO)
-#define MEM_FLAG_SDR BIT(MEM_SDR)
-#define MEM_FLAG_RDR BIT(MEM_RDR)
-#define MEM_FLAG_DDR BIT(MEM_DDR)
-#define MEM_FLAG_RDDR BIT(MEM_RDDR)
-#define MEM_FLAG_RMBS BIT(MEM_RMBS)
-#define MEM_FLAG_DDR2 BIT(MEM_DDR2)
-#define MEM_FLAG_FB_DDR2 BIT(MEM_FB_DDR2)
-#define MEM_FLAG_RDDR2 BIT(MEM_RDDR2)
-#define MEM_FLAG_XDR BIT(MEM_XDR)
-#define MEM_FLAG_DDR3 BIT(MEM_DDR3)
-#define MEM_FLAG_RDDR3 BIT(MEM_RDDR3)
-
-/* chipset Error Detection and Correction capabilities and mode */
-enum edac_type {
- EDAC_UNKNOWN = 0, /* Unknown if ECC is available */
- EDAC_NONE, /* Doesn't support ECC */
- EDAC_RESERVED, /* Reserved ECC type */
- EDAC_PARITY, /* Detects parity errors */
- EDAC_EC, /* Error Checking - no correction */
- EDAC_SECDED, /* Single bit error correction, Double detection */
- EDAC_S2ECD2ED, /* Chipkill x2 devices - do these exist? */
- EDAC_S4ECD4ED, /* Chipkill x4 devices */
- EDAC_S8ECD8ED, /* Chipkill x8 devices */
- EDAC_S16ECD16ED, /* Chipkill x16 devices */
-};
-
-#define EDAC_FLAG_UNKNOWN BIT(EDAC_UNKNOWN)
-#define EDAC_FLAG_NONE BIT(EDAC_NONE)
-#define EDAC_FLAG_PARITY BIT(EDAC_PARITY)
-#define EDAC_FLAG_EC BIT(EDAC_EC)
-#define EDAC_FLAG_SECDED BIT(EDAC_SECDED)
-#define EDAC_FLAG_S2ECD2ED BIT(EDAC_S2ECD2ED)
-#define EDAC_FLAG_S4ECD4ED BIT(EDAC_S4ECD4ED)
-#define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED)
-#define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED)
-
-/* scrubbing capabilities */
-enum scrub_type {
- SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */
- SCRUB_NONE, /* No scrubber */
- SCRUB_SW_PROG, /* SW progressive (sequential) scrubbing */
- SCRUB_SW_SRC, /* Software scrub only errors */
- SCRUB_SW_PROG_SRC, /* Progressive software scrub from an error */
- SCRUB_SW_TUNABLE, /* Software scrub frequency is tunable */
- SCRUB_HW_PROG, /* HW progressive (sequential) scrubbing */
- SCRUB_HW_SRC, /* Hardware scrub only errors */
- SCRUB_HW_PROG_SRC, /* Progressive hardware scrub from an error */
- SCRUB_HW_TUNABLE /* Hardware scrub frequency is tunable */
-};
-
-#define SCRUB_FLAG_SW_PROG BIT(SCRUB_SW_PROG)
-#define SCRUB_FLAG_SW_SRC BIT(SCRUB_SW_SRC)
-#define SCRUB_FLAG_SW_PROG_SRC BIT(SCRUB_SW_PROG_SRC)
-#define SCRUB_FLAG_SW_TUN BIT(SCRUB_SW_SCRUB_TUNABLE)
-#define SCRUB_FLAG_HW_PROG BIT(SCRUB_HW_PROG)
-#define SCRUB_FLAG_HW_SRC BIT(SCRUB_HW_SRC)
-#define SCRUB_FLAG_HW_PROG_SRC BIT(SCRUB_HW_PROG_SRC)
-#define SCRUB_FLAG_HW_TUN BIT(SCRUB_HW_TUNABLE)
-
-/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
-
-/* EDAC internal operation states */
-#define OP_ALLOC 0x100
-#define OP_RUNNING_POLL 0x201
-#define OP_RUNNING_INTERRUPT 0x202
-#define OP_RUNNING_POLL_INTR 0x203
-#define OP_OFFLINE 0x300
-
-/*
- * There are several things to be aware of that aren't at all obvious:
- *
- *
- * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
- *
- * These are some of the many terms that are thrown about that don't always
- * mean what people think they mean (Inconceivable!). In the interest of
- * creating a common ground for discussion, terms and their definitions
- * will be established.
- *
- * Memory devices: The individual chip on a memory stick. These devices
- * commonly output 4 and 8 bits each. Grouping several
- * of these in parallel provides 64 bits which is common
- * for a memory stick.
- *
- * Memory Stick: A printed circuit board that aggregates multiple
- * memory devices in parallel. This is the atomic
- * memory component that is purchaseable by Joe consumer
- * and loaded into a memory socket.
- *
- * Socket: A physical connector on the motherboard that accepts
- * a single memory stick.
- *
- * Channel: Set of memory devices on a memory stick that must be
- * grouped in parallel with one or more additional
- * channels from other memory sticks. This parallel
- * grouping of the output from multiple channels are
- * necessary for the smallest granularity of memory access.
- * Some memory controllers are capable of single channel -
- * which means that memory sticks can be loaded
- * individually. Other memory controllers are only
- * capable of dual channel - which means that memory
- * sticks must be loaded as pairs (see "socket set").
- *
- * Chip-select row: All of the memory devices that are selected together.
- * for a single, minimum grain of memory access.
- * This selects all of the parallel memory devices across
- * all of the parallel channels. Common chip-select rows
- * for single channel are 64 bits, for dual channel 128
- * bits.
- *
- * Single-Ranked stick: A Single-ranked stick has 1 chip-select row of memory.
- * Motherboards commonly drive two chip-select pins to
- * a memory stick. A single-ranked stick, will occupy
- * only one of those rows. The other will be unused.
- *
- * Double-Ranked stick: A double-ranked stick has two chip-select rows which
- * access different sets of memory devices. The two
- * rows cannot be accessed concurrently.
- *
- * Double-sided stick: DEPRECATED TERM, see Double-Ranked stick.
- * A double-sided stick has two chip-select rows which
- * access different sets of memory devices. The two
- * rows cannot be accessed concurrently. "Double-sided"
- * is irrespective of the memory devices being mounted
- * on both sides of the memory stick.
- *
- * Socket set: All of the memory sticks that are required for
- * a single memory access or all of the memory sticks
- * spanned by a chip-select row. A single socket set
- * has two chip-select rows and if double-sided sticks
- * are used these will occupy those chip-select rows.
- *
- * Bank: This term is avoided because it is unclear when
- * needing to distinguish between chip-select rows and
- * socket sets.
- *
- * Controller pages:
- *
- * Physical pages:
- *
- * Virtual pages:
- *
- *
- * STRUCTURE ORGANIZATION AND CHOICES
- *
- *
- *
- * PS - I enjoyed writing all that about as much as you enjoyed reading it.
- */
-
-struct channel_info {
- int chan_idx; /* channel index */
- u32 ce_count; /* Correctable Errors for this CHANNEL */
- char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
- struct csrow_info *csrow; /* the parent */
-};
-
-struct csrow_info {
- unsigned long first_page; /* first page number in dimm */
- unsigned long last_page; /* last page number in dimm */
- unsigned long page_mask; /* used for interleaving -
- * 0UL for non intlv
- */
- u32 nr_pages; /* number of pages in csrow */
- u32 grain; /* granularity of reported error in bytes */
- int csrow_idx; /* the chip-select row */
- enum dev_type dtype; /* memory device type */
- u32 ue_count; /* Uncorrectable Errors for this csrow */
- u32 ce_count; /* Correctable Errors for this csrow */
- enum mem_type mtype; /* memory csrow type */
- enum edac_type edac_mode; /* EDAC mode for this csrow */
- struct mem_ctl_info *mci; /* the parent */
-
- struct kobject kobj; /* sysfs kobject for this csrow */
-
- /* channel information for this csrow */
- u32 nr_channels;
- struct channel_info *channels;
-};
-
-struct mcidev_sysfs_group {
- const char *name; /* group name */
- const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
-};
-
-struct mcidev_sysfs_group_kobj {
- struct list_head list; /* list for all instances within a mc */
-
- struct kobject kobj; /* kobj for the group */
-
- const struct mcidev_sysfs_group *grp; /* group description table */
- struct mem_ctl_info *mci; /* the parent */
-};
-
-/* mcidev_sysfs_attribute structure
- * used for driver sysfs attributes and in mem_ctl_info
- * sysfs top level entries
- */
-struct mcidev_sysfs_attribute {
- /* It should use either attr or grp */
- struct attribute attr;
- const struct mcidev_sysfs_group *grp; /* Points to a group of attributes */
-
- /* Ops for show/store values at the attribute - not used on group */
- ssize_t (*show)(struct mem_ctl_info *,char *);
- ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
-};
-
-/* MEMORY controller information structure
- */
-struct mem_ctl_info {
- struct list_head link; /* for global list of mem_ctl_info structs */
-
- struct module *owner; /* Module owner of this control struct */
-
- unsigned long mtype_cap; /* memory types supported by mc */
- unsigned long edac_ctl_cap; /* Mem controller EDAC capabilities */
- unsigned long edac_cap; /* configuration capabilities - this is
- * closely related to edac_ctl_cap. The
- * difference is that the controller may be
- * capable of s4ecd4ed which would be listed
- * in edac_ctl_cap, but if channels aren't
- * capable of s4ecd4ed then the edac_cap would
- * not have that capability.
- */
- unsigned long scrub_cap; /* chipset scrub capabilities */
- enum scrub_type scrub_mode; /* current scrub mode */
-
- /* Translates sdram memory scrub rate given in bytes/sec to the
- internal representation and configures whatever else needs
- to be configured.
- */
- int (*set_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 bw);
-
- /* Get the current sdram memory scrub rate from the internal
- representation and converts it to the closest matching
- bandwidth in bytes/sec.
- */
- int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci);
-
-
- /* pointer to edac checking routine */
- void (*edac_check) (struct mem_ctl_info * mci);
-
- /*
- * Remaps memory pages: controller pages to physical pages.
- * For most MC's, this will be NULL.
- */
- /* FIXME - why not send the phys page to begin with? */
- unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
- unsigned long page);
- int mc_idx;
- int nr_csrows;
- struct csrow_info *csrows;
- /*
- * FIXME - what about controllers on other busses? - IDs must be
- * unique. dev pointer should be sufficiently unique, but
- * BUS:SLOT.FUNC numbers may not be unique.
- */
- struct device *dev;
- const char *mod_name;
- const char *mod_ver;
- const char *ctl_name;
- const char *dev_name;
- char proc_name[MC_PROC_NAME_MAX_LEN + 1];
- void *pvt_info;
- u32 ue_noinfo_count; /* Uncorrectable Errors w/o info */
- u32 ce_noinfo_count; /* Correctable Errors w/o info */
- u32 ue_count; /* Total Uncorrectable Errors for this MC */
- u32 ce_count; /* Total Correctable Errors for this MC */
- unsigned long start_time; /* mci load start time (in jiffies) */
-
- struct completion complete;
-
- /* edac sysfs device control */
- struct kobject edac_mci_kobj;
-
- /* list for all grp instances within a mc */
- struct list_head grp_kobj_list;
-
- /* Additional top controller level attributes, but specified
- * by the low level driver.
- *
- * Set by the low level driver to provide attributes at the
- * controller level, same level as 'ue_count' and 'ce_count' above.
- * An array of structures, NULL terminated
- *
- * If attributes are desired, then set to array of attributes
- * If no attributes are desired, leave NULL
- */
- const struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
-
- /* work struct for this MC */
- struct delayed_work work;
-
- /* the internal state of this controller instance */
- int op_state;
-};
-
/*
* The following are the structures to provide for a generic
* or abstract 'edac_device'. This set of structures and the
diff --git a/drivers/edac/edac_mce.c b/drivers/edac/edac_mce.c
deleted file mode 100644
index 9ccdc5b140e7..000000000000
--- a/drivers/edac/edac_mce.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Provides edac interface to mcelog events
- *
- * This file may be distributed under the terms of the
- * GNU General Public License version 2.
- *
- * Copyright (c) 2009 by:
- * Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * Red Hat Inc. http://www.redhat.com
- */
-
-#include <linux/module.h>
-#include <linux/edac_mce.h>
-#include <asm/mce.h>
-
-int edac_mce_enabled;
-EXPORT_SYMBOL_GPL(edac_mce_enabled);
-
-
-/*
- * Extension interface
- */
-
-static LIST_HEAD(edac_mce_list);
-static DEFINE_MUTEX(edac_mce_lock);
-
-int edac_mce_register(struct edac_mce *edac_mce)
-{
- mutex_lock(&edac_mce_lock);
- list_add_tail(&edac_mce->list, &edac_mce_list);
- mutex_unlock(&edac_mce_lock);
- return 0;
-}
-EXPORT_SYMBOL(edac_mce_register);
-
-void edac_mce_unregister(struct edac_mce *edac_mce)
-{
- mutex_lock(&edac_mce_lock);
- list_del(&edac_mce->list);
- mutex_unlock(&edac_mce_lock);
-}
-EXPORT_SYMBOL(edac_mce_unregister);
-
-int edac_mce_parse(struct mce *mce)
-{
- struct edac_mce *edac_mce;
-
- list_for_each_entry(edac_mce, &edac_mce_list, list) {
- if (edac_mce->check_error(edac_mce->priv, mce))
- return 1;
- }
-
- /* Nobody queued the error */
- return 0;
-}
-EXPORT_SYMBOL_GPL(edac_mce_parse);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("EDAC Driver for mcelog captured errors");
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c
index a76fe8366b68..6104dba380b6 100644
--- a/drivers/edac/i7300_edac.c
+++ b/drivers/edac/i7300_edac.c
@@ -372,7 +372,7 @@ static const char *get_err_from_table(const char *table[], int size, int pos)
static void i7300_process_error_global(struct mem_ctl_info *mci)
{
struct i7300_pvt *pvt;
- u32 errnum, value;
+ u32 errnum, error_reg;
unsigned long errors;
const char *specific;
bool is_fatal;
@@ -381,9 +381,9 @@ static void i7300_process_error_global(struct mem_ctl_info *mci)
/* read in the 1st FATAL error register */
pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
- FERR_GLOBAL_HI, &value);
- if (unlikely(value)) {
- errors = value;
+ FERR_GLOBAL_HI, &error_reg);
+ if (unlikely(error_reg)) {
+ errors = error_reg;
errnum = find_first_bit(&errors,
ARRAY_SIZE(ferr_global_hi_name));
specific = GET_ERR_FROM_TABLE(ferr_global_hi_name, errnum);
@@ -391,15 +391,15 @@ static void i7300_process_error_global(struct mem_ctl_info *mci)
/* Clear the error bit */
pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
- FERR_GLOBAL_HI, value);
+ FERR_GLOBAL_HI, error_reg);
goto error_global;
}
pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
- FERR_GLOBAL_LO, &value);
- if (unlikely(value)) {
- errors = value;
+ FERR_GLOBAL_LO, &error_reg);
+ if (unlikely(error_reg)) {
+ errors = error_reg;
errnum = find_first_bit(&errors,
ARRAY_SIZE(ferr_global_lo_name));
specific = GET_ERR_FROM_TABLE(ferr_global_lo_name, errnum);
@@ -407,7 +407,7 @@ static void i7300_process_error_global(struct mem_ctl_info *mci)
/* Clear the error bit */
pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
- FERR_GLOBAL_LO, value);
+ FERR_GLOBAL_LO, error_reg);
goto error_global;
}
@@ -427,7 +427,7 @@ error_global:
static void i7300_process_fbd_error(struct mem_ctl_info *mci)
{
struct i7300_pvt *pvt;
- u32 errnum, value;
+ u32 errnum, value, error_reg;
u16 val16;
unsigned branch, channel, bank, rank, cas, ras;
u32 syndrome;
@@ -440,14 +440,14 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
/* read in the 1st FATAL error register */
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
- FERR_FAT_FBD, &value);
- if (unlikely(value & FERR_FAT_FBD_ERR_MASK)) {
- errors = value & FERR_FAT_FBD_ERR_MASK ;
+ FERR_FAT_FBD, &error_reg);
+ if (unlikely(error_reg & FERR_FAT_FBD_ERR_MASK)) {
+ errors = error_reg & FERR_FAT_FBD_ERR_MASK ;
errnum = find_first_bit(&errors,
ARRAY_SIZE(ferr_fat_fbd_name));
specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum);
+ branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
- branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
NRECMEMA, &val16);
bank = NRECMEMA_BANK(val16);
@@ -455,11 +455,14 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
NRECMEMB, &value);
-
is_wr = NRECMEMB_IS_WR(value);
cas = NRECMEMB_CAS(value);
ras = NRECMEMB_RAS(value);
+ /* Clean the error register */
+ pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
+ FERR_FAT_FBD, error_reg);
+
snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
"FATAL (Branch=%d DRAM-Bank=%d %s "
"RAS=%d CAS=%d Err=0x%lx (%s))",
@@ -476,21 +479,17 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
/* read in the 1st NON-FATAL error register */
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
- FERR_NF_FBD, &value);
- if (unlikely(value & FERR_NF_FBD_ERR_MASK)) {
- errors = value & FERR_NF_FBD_ERR_MASK;
+ FERR_NF_FBD, &error_reg);
+ if (unlikely(error_reg & FERR_NF_FBD_ERR_MASK)) {
+ errors = error_reg & FERR_NF_FBD_ERR_MASK;
errnum = find_first_bit(&errors,
ARRAY_SIZE(ferr_nf_fbd_name));
specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum);
-
- /* Clear the error bit */
- pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
- FERR_GLOBAL_LO, value);
+ branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
REDMEMA, &syndrome);
- branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
RECMEMA, &val16);
bank = RECMEMA_BANK(val16);
@@ -498,18 +497,20 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
RECMEMB, &value);
-
is_wr = RECMEMB_IS_WR(value);
cas = RECMEMB_CAS(value);
ras = RECMEMB_RAS(value);
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
REDMEMB, &value);
-
channel = (branch << 1);
if (IS_SECOND_CH(value))
channel++;
+ /* Clear the error bit */
+ pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
+ FERR_NF_FBD, error_reg);
+
/* Form out message */
snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
"Corrected error (Branch=%d, Channel %d), "
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index f6cf448d69b4..70ad8923f1d7 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -31,11 +31,13 @@
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/dmi.h>
#include <linux/edac.h>
#include <linux/mmzone.h>
-#include <linux/edac_mce.h>
#include <linux/smp.h>
+#include <asm/mce.h>
#include <asm/processor.h>
+#include <asm/div64.h>
#include "edac_core.h"
@@ -78,6 +80,8 @@ MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices");
/* OFFSETS for Device 0 Function 0 */
#define MC_CFG_CONTROL 0x90
+ #define MC_CFG_UNLOCK 0x02
+ #define MC_CFG_LOCK 0x00
/* OFFSETS for Device 3 Function 0 */
@@ -98,6 +102,15 @@ MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices");
#define DIMM0_COR_ERR(r) ((r) & 0x7fff)
/* OFFSETS for Device 3 Function 2, as inicated on Xeon 5500 datasheet */
+#define MC_SSRCONTROL 0x48
+ #define SSR_MODE_DISABLE 0x00
+ #define SSR_MODE_ENABLE 0x01
+ #define SSR_MODE_MASK 0x03
+
+#define MC_SCRUB_CONTROL 0x4c
+ #define STARTSCRUB (1 << 24)
+ #define SCRUBINTERVAL_MASK 0xffffff
+
#define MC_COR_ECC_CNT_0 0x80
#define MC_COR_ECC_CNT_1 0x84
#define MC_COR_ECC_CNT_2 0x88
@@ -253,10 +266,7 @@ struct i7core_pvt {
unsigned long rdimm_ce_count[NUM_CHANS][MAX_DIMMS];
int rdimm_last_ce_count[NUM_CHANS][MAX_DIMMS];
- unsigned int is_registered;
-
- /* mcelog glue */
- struct edac_mce edac_mce;
+ bool is_registered, enable_scrub;
/* Fifo double buffers */
struct mce mce_entry[MCE_LOG_LEN];
@@ -268,6 +278,9 @@ struct i7core_pvt {
/* Count indicator to show errors not got */
unsigned mce_overrun;
+ /* DCLK Frequency used for computing scrub rate */
+ int dclk_freq;
+
/* Struct to control EDAC polling */
struct edac_pci_ctl_info *i7core_pci;
};
@@ -281,8 +294,7 @@ static const struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
/* Memory controller */
{ PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) },
{ PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) },
-
- /* Exists only for RDIMM */
+ /* Exists only for RDIMM */
{ PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS), .optional = 1 },
{ PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
@@ -303,6 +315,16 @@ static const struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
{ PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
{ PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
{ PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC) },
+
+ /* Generic Non-core registers */
+ /*
+ * This is the PCI device on i7core and on Xeon 35xx (8086:2c41)
+ * On Xeon 55xx, however, it has a different id (8086:2c40). So,
+ * the probing code needs to test for the other address in case of
+ * failure of this one
+ */
+ { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE) },
+
};
static const struct pci_id_descr pci_dev_descr_lynnfield[] = {
@@ -319,6 +341,12 @@ static const struct pci_id_descr pci_dev_descr_lynnfield[] = {
{ PCI_DESCR( 5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR) },
{ PCI_DESCR( 5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK) },
{ PCI_DESCR( 5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC) },
+
+ /*
+ * This is the PCI device has an alternate address on some
+ * processors like Core i7 860
+ */
+ { PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE) },
};
static const struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
@@ -346,6 +374,10 @@ static const struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
{ PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2) },
{ PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2) },
{ PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2) },
+
+ /* Generic Non-core registers */
+ { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2) },
+
};
#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
@@ -714,6 +746,10 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
csr->edac_mode = mode;
csr->mtype = mtype;
+ snprintf(csr->channels[0].label,
+ sizeof(csr->channels[0].label),
+ "CPU#%uChannel#%u_DIMM#%u",
+ pvt->i7core_dev->socket, i, j);
csrow++;
}
@@ -731,7 +767,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
debugf1("\t\t%#x\t%#x\t%#x\n",
(value[j] >> 27) & 0x1,
(value[j] >> 24) & 0x7,
- (value[j] && ((1 << 24) - 1)));
+ (value[j] & ((1 << 24) - 1)));
}
return 0;
@@ -1324,6 +1360,20 @@ static int i7core_get_onedevice(struct pci_dev **prev,
pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
dev_descr->dev_id, *prev);
+ /*
+ * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
+ * is at addr 8086:2c40, instead of 8086:2c41. So, we need
+ * to probe for the alternate address in case of failure
+ */
+ if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
+
+ if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
+ *prev);
+
if (!pdev) {
if (*prev) {
*prev = pdev;
@@ -1444,8 +1494,10 @@ static int mci_bind_devs(struct mem_ctl_info *mci,
struct i7core_pvt *pvt = mci->pvt_info;
struct pci_dev *pdev;
int i, func, slot;
+ char *family;
- pvt->is_registered = 0;
+ pvt->is_registered = false;
+ pvt->enable_scrub = false;
for (i = 0; i < i7core_dev->n_devs; i++) {
pdev = i7core_dev->pdev[i];
if (!pdev)
@@ -1461,9 +1513,37 @@ static int mci_bind_devs(struct mem_ctl_info *mci,
if (unlikely(func > MAX_CHAN_FUNC))
goto error;
pvt->pci_ch[slot - 4][func] = pdev;
- } else if (!slot && !func)
+ } else if (!slot && !func) {
pvt->pci_noncore = pdev;
- else
+
+ /* Detect the processor family */
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_I7_NONCORE:
+ family = "Xeon 35xx/ i7core";
+ pvt->enable_scrub = false;
+ break;
+ case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT:
+ family = "i7-800/i5-700";
+ pvt->enable_scrub = false;
+ break;
+ case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE:
+ family = "Xeon 34xx";
+ pvt->enable_scrub = false;
+ break;
+ case PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT:
+ family = "Xeon 55xx";
+ pvt->enable_scrub = true;
+ break;
+ case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2:
+ family = "Xeon 56xx / i7-900";
+ pvt->enable_scrub = true;
+ break;
+ default:
+ family = "unknown";
+ pvt->enable_scrub = false;
+ }
+ debugf0("Detected a processor type %s\n", family);
+ } else
goto error;
debugf0("Associated fn %d.%d, dev = %p, socket %d\n",
@@ -1472,7 +1552,7 @@ static int mci_bind_devs(struct mem_ctl_info *mci,
if (PCI_SLOT(pdev->devfn) == 3 &&
PCI_FUNC(pdev->devfn) == 2)
- pvt->is_registered = 1;
+ pvt->is_registered = true;
}
return 0;
@@ -1826,33 +1906,43 @@ check_ce_error:
* WARNING: As this routine should be called at NMI time, extra care should
* be taken to avoid deadlocks, and to be as fast as possible.
*/
-static int i7core_mce_check_error(void *priv, struct mce *mce)
+static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val,
+ void *data)
{
- struct mem_ctl_info *mci = priv;
- struct i7core_pvt *pvt = mci->pvt_info;
+ struct mce *mce = (struct mce *)data;
+ struct i7core_dev *i7_dev;
+ struct mem_ctl_info *mci;
+ struct i7core_pvt *pvt;
+
+ i7_dev = get_i7core_dev(mce->socketid);
+ if (!i7_dev)
+ return NOTIFY_BAD;
+
+ mci = i7_dev->mci;
+ pvt = mci->pvt_info;
/*
* Just let mcelog handle it if the error is
* outside the memory controller
*/
if (((mce->status & 0xffff) >> 7) != 1)
- return 0;
+ return NOTIFY_DONE;
/* Bank 8 registers are the only ones that we know how to handle */
if (mce->bank != 8)
- return 0;
+ return NOTIFY_DONE;
#ifdef CONFIG_SMP
/* Only handle if it is the right mc controller */
- if (cpu_data(mce->cpu).phys_proc_id != pvt->i7core_dev->socket)
- return 0;
+ if (mce->socketid != pvt->i7core_dev->socket)
+ return NOTIFY_DONE;
#endif
smp_rmb();
if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
smp_wmb();
pvt->mce_overrun++;
- return 0;
+ return NOTIFY_DONE;
}
/* Copy memory error at the ringbuffer */
@@ -1865,7 +1955,240 @@ static int i7core_mce_check_error(void *priv, struct mce *mce)
i7core_check_error(mci);
/* Advise mcelog that the errors were handled */
- return 1;
+ return NOTIFY_STOP;
+}
+
+static struct notifier_block i7_mce_dec = {
+ .notifier_call = i7core_mce_check_error,
+};
+
+struct memdev_dmi_entry {
+ u8 type;
+ u8 length;
+ u16 handle;
+ u16 phys_mem_array_handle;
+ u16 mem_err_info_handle;
+ u16 total_width;
+ u16 data_width;
+ u16 size;
+ u8 form;
+ u8 device_set;
+ u8 device_locator;
+ u8 bank_locator;
+ u8 memory_type;
+ u16 type_detail;
+ u16 speed;
+ u8 manufacturer;
+ u8 serial_number;
+ u8 asset_tag;
+ u8 part_number;
+ u8 attributes;
+ u32 extended_size;
+ u16 conf_mem_clk_speed;
+} __attribute__((__packed__));
+
+
+/*
+ * Decode the DRAM Clock Frequency, be paranoid, make sure that all
+ * memory devices show the same speed, and if they don't then consider
+ * all speeds to be invalid.
+ */
+static void decode_dclk(const struct dmi_header *dh, void *_dclk_freq)
+{
+ int *dclk_freq = _dclk_freq;
+ u16 dmi_mem_clk_speed;
+
+ if (*dclk_freq == -1)
+ return;
+
+ if (dh->type == DMI_ENTRY_MEM_DEVICE) {
+ struct memdev_dmi_entry *memdev_dmi_entry =
+ (struct memdev_dmi_entry *)dh;
+ unsigned long conf_mem_clk_speed_offset =
+ (unsigned long)&memdev_dmi_entry->conf_mem_clk_speed -
+ (unsigned long)&memdev_dmi_entry->type;
+ unsigned long speed_offset =
+ (unsigned long)&memdev_dmi_entry->speed -
+ (unsigned long)&memdev_dmi_entry->type;
+
+ /* Check that a DIMM is present */
+ if (memdev_dmi_entry->size == 0)
+ return;
+
+ /*
+ * Pick the configured speed if it's available, otherwise
+ * pick the DIMM speed, or we don't have a speed.
+ */
+ if (memdev_dmi_entry->length > conf_mem_clk_speed_offset) {
+ dmi_mem_clk_speed =
+ memdev_dmi_entry->conf_mem_clk_speed;
+ } else if (memdev_dmi_entry->length > speed_offset) {
+ dmi_mem_clk_speed = memdev_dmi_entry->speed;
+ } else {
+ *dclk_freq = -1;
+ return;
+ }
+
+ if (*dclk_freq == 0) {
+ /* First pass, speed was 0 */
+ if (dmi_mem_clk_speed > 0) {
+ /* Set speed if a valid speed is read */
+ *dclk_freq = dmi_mem_clk_speed;
+ } else {
+ /* Otherwise we don't have a valid speed */
+ *dclk_freq = -1;
+ }
+ } else if (*dclk_freq > 0 &&
+ *dclk_freq != dmi_mem_clk_speed) {
+ /*
+ * If we have a speed, check that all DIMMS are the same
+ * speed, otherwise set the speed as invalid.
+ */
+ *dclk_freq = -1;
+ }
+ }
+}
+
+/*
+ * The default DCLK frequency is used as a fallback if we
+ * fail to find anything reliable in the DMI. The value
+ * is taken straight from the datasheet.
+ */
+#define DEFAULT_DCLK_FREQ 800
+
+static int get_dclk_freq(void)
+{
+ int dclk_freq = 0;
+
+ dmi_walk(decode_dclk, (void *)&dclk_freq);
+
+ if (dclk_freq < 1)
+ return DEFAULT_DCLK_FREQ;
+
+ return dclk_freq;
+}
+
+/*
+ * set_sdram_scrub_rate This routine sets byte/sec bandwidth scrub rate
+ * to hardware according to SCRUBINTERVAL formula
+ * found in datasheet.
+ */
+static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ struct pci_dev *pdev;
+ u32 dw_scrub;
+ u32 dw_ssr;
+
+ /* Get data from the MC register, function 2 */
+ pdev = pvt->pci_mcr[2];
+ if (!pdev)
+ return -ENODEV;
+
+ pci_read_config_dword(pdev, MC_SCRUB_CONTROL, &dw_scrub);
+
+ if (new_bw == 0) {
+ /* Prepare to disable petrol scrub */
+ dw_scrub &= ~STARTSCRUB;
+ /* Stop the patrol scrub engine */
+ write_and_test(pdev, MC_SCRUB_CONTROL,
+ dw_scrub & ~SCRUBINTERVAL_MASK);
+
+ /* Get current status of scrub rate and set bit to disable */
+ pci_read_config_dword(pdev, MC_SSRCONTROL, &dw_ssr);
+ dw_ssr &= ~SSR_MODE_MASK;
+ dw_ssr |= SSR_MODE_DISABLE;
+ } else {
+ const int cache_line_size = 64;
+ const u32 freq_dclk_mhz = pvt->dclk_freq;
+ unsigned long long scrub_interval;
+ /*
+ * Translate the desired scrub rate to a register value and
+ * program the corresponding register value.
+ */
+ scrub_interval = (unsigned long long)freq_dclk_mhz *
+ cache_line_size * 1000000;
+ do_div(scrub_interval, new_bw);
+
+ if (!scrub_interval || scrub_interval > SCRUBINTERVAL_MASK)
+ return -EINVAL;
+
+ dw_scrub = SCRUBINTERVAL_MASK & scrub_interval;
+
+ /* Start the patrol scrub engine */
+ pci_write_config_dword(pdev, MC_SCRUB_CONTROL,
+ STARTSCRUB | dw_scrub);
+
+ /* Get current status of scrub rate and set bit to enable */
+ pci_read_config_dword(pdev, MC_SSRCONTROL, &dw_ssr);
+ dw_ssr &= ~SSR_MODE_MASK;
+ dw_ssr |= SSR_MODE_ENABLE;
+ }
+ /* Disable or enable scrubbing */
+ pci_write_config_dword(pdev, MC_SSRCONTROL, dw_ssr);
+
+ return new_bw;
+}
+
+/*
+ * get_sdram_scrub_rate This routine convert current scrub rate value
+ * into byte/sec bandwidth accourding to
+ * SCRUBINTERVAL formula found in datasheet.
+ */
+static int get_sdram_scrub_rate(struct mem_ctl_info *mci)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ struct pci_dev *pdev;
+ const u32 cache_line_size = 64;
+ const u32 freq_dclk_mhz = pvt->dclk_freq;
+ unsigned long long scrub_rate;
+ u32 scrubval;
+
+ /* Get data from the MC register, function 2 */
+ pdev = pvt->pci_mcr[2];
+ if (!pdev)
+ return -ENODEV;
+
+ /* Get current scrub control data */
+ pci_read_config_dword(pdev, MC_SCRUB_CONTROL, &scrubval);
+
+ /* Mask highest 8-bits to 0 */
+ scrubval &= SCRUBINTERVAL_MASK;
+ if (!scrubval)
+ return 0;
+
+ /* Calculate scrub rate value into byte/sec bandwidth */
+ scrub_rate = (unsigned long long)freq_dclk_mhz *
+ 1000000 * cache_line_size;
+ do_div(scrub_rate, scrubval);
+ return (int)scrub_rate;
+}
+
+static void enable_sdram_scrub_setting(struct mem_ctl_info *mci)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ u32 pci_lock;
+
+ /* Unlock writes to pci registers */
+ pci_read_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, &pci_lock);
+ pci_lock &= ~0x3;
+ pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL,
+ pci_lock | MC_CFG_UNLOCK);
+
+ mci->set_sdram_scrub_rate = set_sdram_scrub_rate;
+ mci->get_sdram_scrub_rate = get_sdram_scrub_rate;
+}
+
+static void disable_sdram_scrub_setting(struct mem_ctl_info *mci)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ u32 pci_lock;
+
+ /* Lock writes to pci registers */
+ pci_read_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, &pci_lock);
+ pci_lock &= ~0x3;
+ pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL,
+ pci_lock | MC_CFG_LOCK);
}
static void i7core_pci_ctl_create(struct i7core_pvt *pvt)
@@ -1874,7 +2197,8 @@ static void i7core_pci_ctl_create(struct i7core_pvt *pvt)
&pvt->i7core_dev->pdev[0]->dev,
EDAC_MOD_STR);
if (unlikely(!pvt->i7core_pci))
- pr_warn("Unable to setup PCI error report via EDAC\n");
+ i7core_printk(KERN_WARNING,
+ "Unable to setup PCI error report via EDAC\n");
}
static void i7core_pci_ctl_release(struct i7core_pvt *pvt)
@@ -1906,8 +2230,11 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev)
debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
__func__, mci, &i7core_dev->pdev[0]->dev);
- /* Disable MCE NMI handler */
- edac_mce_unregister(&pvt->edac_mce);
+ /* Disable scrubrate setting */
+ if (pvt->enable_scrub)
+ disable_sdram_scrub_setting(mci);
+
+ atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &i7_mce_dec);
/* Disable EDAC polling */
i7core_pci_ctl_release(pvt);
@@ -1979,6 +2306,10 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
/* Set the function pointer to an actual operation function */
mci->edac_check = i7core_check_error;
+ /* Enable scrubrate setting */
+ if (pvt->enable_scrub)
+ enable_sdram_scrub_setting(mci);
+
/* add this new MC control structure to EDAC's list of MCs */
if (unlikely(edac_mc_add_mc(mci))) {
debugf0("MC: " __FILE__
@@ -2002,21 +2333,13 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
/* allocating generic PCI control info */
i7core_pci_ctl_create(pvt);
- /* Registers on edac_mce in order to receive memory errors */
- pvt->edac_mce.priv = mci;
- pvt->edac_mce.check_error = i7core_mce_check_error;
- rc = edac_mce_register(&pvt->edac_mce);
- if (unlikely(rc < 0)) {
- debugf0("MC: " __FILE__
- ": %s(): failed edac_mce_register()\n", __func__);
- goto fail1;
- }
+ /* DCLK for scrub rate setting */
+ pvt->dclk_freq = get_dclk_freq();
+
+ atomic_notifier_chain_register(&x86_mce_decoder_chain, &i7_mce_dec);
return 0;
-fail1:
- i7core_pci_ctl_release(pvt);
- edac_mc_del_mc(mci->dev);
fail0:
kfree(mci->ctl_name);
edac_mc_free(mci);
@@ -2035,7 +2358,7 @@ fail0:
static int __devinit i7core_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
- int rc;
+ int rc, count = 0;
struct i7core_dev *i7core_dev;
/* get the pci devices we want to reserve for our use */
@@ -2055,12 +2378,28 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
goto fail0;
list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
+ count++;
rc = i7core_register_mci(i7core_dev);
if (unlikely(rc < 0))
goto fail1;
}
- i7core_printk(KERN_INFO, "Driver loaded.\n");
+ /*
+ * Nehalem-EX uses a different memory controller. However, as the
+ * memory controller is not visible on some Nehalem/Nehalem-EP, we
+ * need to indirectly probe via a X58 PCI device. The same devices
+ * are found on (some) Nehalem-EX. So, on those machines, the
+ * probe routine needs to return -ENODEV, as the actual Memory
+ * Controller registers won't be detected.
+ */
+ if (!count) {
+ rc = -ENODEV;
+ goto fail1;
+ }
+
+ i7core_printk(KERN_INFO,
+ "Driver loaded, %d memory controller(s) found.\n",
+ count);
mutex_unlock(&i7core_edac_lock);
return 0;
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 795cfbc0bf50..d0864d9c38ad 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -9,7 +9,7 @@ static u8 xec_mask = 0xf;
static u8 nb_err_cpumask = 0xf;
static bool report_gart_errors;
-static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
+static void (*nb_bus_decoder)(int node_id, struct mce *m);
void amd_report_gart_errors(bool v)
{
@@ -17,13 +17,13 @@ void amd_report_gart_errors(bool v)
}
EXPORT_SYMBOL_GPL(amd_report_gart_errors);
-void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
+void amd_register_ecc_decoder(void (*f)(int, struct mce *))
{
nb_bus_decoder = f;
}
EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
-void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *))
{
if (nb_bus_decoder) {
WARN_ON(nb_bus_decoder != f);
@@ -592,31 +592,14 @@ static bool nb_noop_mce(u16 ec, u8 xec)
return false;
}
-void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
+void amd_decode_nb_mce(struct mce *m)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
- u16 ec = EC(m->status);
- u8 xec = XEC(m->status, 0x1f);
- u32 nbsh = (u32)(m->status >> 32);
- int core = -1;
-
- pr_emerg(HW_ERR "Northbridge Error (node %d", node_id);
-
- /* F10h, revD can disable ErrCpu[3:0] through ErrCpuVal */
- if (c->x86 == 0x10 && c->x86_model > 7) {
- if (nbsh & NBSH_ERR_CPU_VAL)
- core = nbsh & nb_err_cpumask;
- } else {
- u8 assoc_cpus = nbsh & nb_err_cpumask;
-
- if (assoc_cpus > 0)
- core = fls(assoc_cpus) - 1;
- }
+ int node_id = amd_get_nb_id(m->extcpu);
+ u16 ec = EC(m->status);
+ u8 xec = XEC(m->status, 0x1f);
- if (core >= 0)
- pr_cont(", core %d): ", core);
- else
- pr_cont("): ");
+ pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id);
switch (xec) {
case 0x2:
@@ -648,7 +631,7 @@ void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x15)
if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
- nb_bus_decoder(node_id, m, nbcfg);
+ nb_bus_decoder(node_id, m);
return;
@@ -764,13 +747,13 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
{
struct mce *m = (struct mce *)data;
struct cpuinfo_x86 *c = &boot_cpu_data;
- int node, ecc;
+ int ecc;
if (amd_filter_mce(m))
return NOTIFY_STOP;
- pr_emerg(HW_ERR "MC%d_STATUS[%s|%s|%s|%s|%s",
- m->bank,
+ pr_emerg(HW_ERR "CPU:%d\tMC%d_STATUS[%s|%s|%s|%s|%s",
+ m->extcpu, m->bank,
((m->status & MCI_STATUS_OVER) ? "Over" : "-"),
((m->status & MCI_STATUS_UC) ? "UE" : "CE"),
((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"),
@@ -789,6 +772,8 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
pr_cont("]: 0x%016llx\n", m->status);
+ if (m->status & MCI_STATUS_ADDRV)
+ pr_emerg(HW_ERR "\tMC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
switch (m->bank) {
case 0:
@@ -811,8 +796,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
break;
case 4:
- node = amd_get_nb_id(m->extcpu);
- amd_decode_nb_mce(node, m, 0);
+ amd_decode_nb_mce(m);
break;
case 5:
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h
index 795a3206acf5..0106747e240c 100644
--- a/drivers/edac/mce_amd.h
+++ b/drivers/edac/mce_amd.h
@@ -86,9 +86,9 @@ struct amd_decoder_ops {
};
void amd_report_gart_errors(bool);
-void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32));
-void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32));
-void amd_decode_nb_mce(int, struct mce *, u32);
+void amd_register_ecc_decoder(void (*f)(int, struct mce *));
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *));
+void amd_decode_nb_mce(struct mce *);
int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
#endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
new file mode 100644
index 000000000000..7a402bfbee7d
--- /dev/null
+++ b/drivers/edac/sb_edac.c
@@ -0,0 +1,1893 @@
+/* Intel Sandy Bridge -EN/-EP/-EX Memory Controller kernel module
+ *
+ * This driver supports the memory controllers found on the Intel
+ * processor family Sandy Bridge.
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License version 2 only.
+ *
+ * Copyright (c) 2011 by:
+ * Mauro Carvalho Chehab <mchehab@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/edac.h>
+#include <linux/mmzone.h>
+#include <linux/smp.h>
+#include <linux/bitmap.h>
+#include <asm/processor.h>
+#include <asm/mce.h>
+
+#include "edac_core.h"
+
+/* Static vars */
+static LIST_HEAD(sbridge_edac_list);
+static DEFINE_MUTEX(sbridge_edac_lock);
+static int probed;
+
+/*
+ * Alter this version for the module when modifications are made
+ */
+#define SBRIDGE_REVISION " Ver: 1.0.0 "
+#define EDAC_MOD_STR "sbridge_edac"
+
+/*
+ * Debug macros
+ */
+#define sbridge_printk(level, fmt, arg...) \
+ edac_printk(level, "sbridge", fmt, ##arg)
+
+#define sbridge_mc_printk(mci, level, fmt, arg...) \
+ edac_mc_chipset_printk(mci, level, "sbridge", fmt, ##arg)
+
+/*
+ * Get a bit field at register value <v>, from bit <lo> to bit <hi>
+ */
+#define GET_BITFIELD(v, lo, hi) \
+ (((v) & ((1ULL << ((hi) - (lo) + 1)) - 1) << (lo)) >> (lo))
+
+/*
+ * sbridge Memory Controller Registers
+ */
+
+/*
+ * FIXME: For now, let's order by device function, as it makes
+ * easier for driver's development proccess. This table should be
+ * moved to pci_id.h when submitted upstream
+ */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0 0x3cf4 /* 12.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1 0x3cf6 /* 12.7 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_BR 0x3cf5 /* 13.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0 0x3ca0 /* 14.0 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA 0x3ca8 /* 15.0 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS 0x3c71 /* 15.1 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0 0x3caa /* 15.2 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1 0x3cab /* 15.3 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2 0x3cac /* 15.4 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3 0x3cad /* 15.5 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO 0x3cb8 /* 17.0 */
+
+ /*
+ * Currently, unused, but will be needed in the future
+ * implementations, as they hold the error counters
+ */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR0 0x3c72 /* 16.2 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR1 0x3c73 /* 16.3 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR2 0x3c76 /* 16.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR3 0x3c77 /* 16.7 */
+
+/* Devices 12 Function 6, Offsets 0x80 to 0xcc */
+static const u32 dram_rule[] = {
+ 0x80, 0x88, 0x90, 0x98, 0xa0,
+ 0xa8, 0xb0, 0xb8, 0xc0, 0xc8,
+};
+#define MAX_SAD ARRAY_SIZE(dram_rule)
+
+#define SAD_LIMIT(reg) ((GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff)
+#define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3)
+#define INTERLEAVE_MODE(reg) GET_BITFIELD(reg, 1, 1)
+#define DRAM_RULE_ENABLE(reg) GET_BITFIELD(reg, 0, 0)
+
+static char *get_dram_attr(u32 reg)
+{
+ switch(DRAM_ATTR(reg)) {
+ case 0:
+ return "DRAM";
+ case 1:
+ return "MMCFG";
+ case 2:
+ return "NXM";
+ default:
+ return "unknown";
+ }
+}
+
+static const u32 interleave_list[] = {
+ 0x84, 0x8c, 0x94, 0x9c, 0xa4,
+ 0xac, 0xb4, 0xbc, 0xc4, 0xcc,
+};
+#define MAX_INTERLEAVE ARRAY_SIZE(interleave_list)
+
+#define SAD_PKG0(reg) GET_BITFIELD(reg, 0, 2)
+#define SAD_PKG1(reg) GET_BITFIELD(reg, 3, 5)
+#define SAD_PKG2(reg) GET_BITFIELD(reg, 8, 10)
+#define SAD_PKG3(reg) GET_BITFIELD(reg, 11, 13)
+#define SAD_PKG4(reg) GET_BITFIELD(reg, 16, 18)
+#define SAD_PKG5(reg) GET_BITFIELD(reg, 19, 21)
+#define SAD_PKG6(reg) GET_BITFIELD(reg, 24, 26)
+#define SAD_PKG7(reg) GET_BITFIELD(reg, 27, 29)
+
+static inline int sad_pkg(u32 reg, int interleave)
+{
+ switch (interleave) {
+ case 0:
+ return SAD_PKG0(reg);
+ case 1:
+ return SAD_PKG1(reg);
+ case 2:
+ return SAD_PKG2(reg);
+ case 3:
+ return SAD_PKG3(reg);
+ case 4:
+ return SAD_PKG4(reg);
+ case 5:
+ return SAD_PKG5(reg);
+ case 6:
+ return SAD_PKG6(reg);
+ case 7:
+ return SAD_PKG7(reg);
+ default:
+ return -EINVAL;
+ }
+}
+
+/* Devices 12 Function 7 */
+
+#define TOLM 0x80
+#define TOHM 0x84
+
+#define GET_TOLM(reg) ((GET_BITFIELD(reg, 0, 3) << 28) | 0x3ffffff)
+#define GET_TOHM(reg) ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff)
+
+/* Device 13 Function 6 */
+
+#define SAD_TARGET 0xf0
+
+#define SOURCE_ID(reg) GET_BITFIELD(reg, 9, 11)
+
+#define SAD_CONTROL 0xf4
+
+#define NODE_ID(reg) GET_BITFIELD(reg, 0, 2)
+
+/* Device 14 function 0 */
+
+static const u32 tad_dram_rule[] = {
+ 0x40, 0x44, 0x48, 0x4c,
+ 0x50, 0x54, 0x58, 0x5c,
+ 0x60, 0x64, 0x68, 0x6c,
+};
+#define MAX_TAD ARRAY_SIZE(tad_dram_rule)
+
+#define TAD_LIMIT(reg) ((GET_BITFIELD(reg, 12, 31) << 26) | 0x3ffffff)
+#define TAD_SOCK(reg) GET_BITFIELD(reg, 10, 11)
+#define TAD_CH(reg) GET_BITFIELD(reg, 8, 9)
+#define TAD_TGT3(reg) GET_BITFIELD(reg, 6, 7)
+#define TAD_TGT2(reg) GET_BITFIELD(reg, 4, 5)
+#define TAD_TGT1(reg) GET_BITFIELD(reg, 2, 3)
+#define TAD_TGT0(reg) GET_BITFIELD(reg, 0, 1)
+
+/* Device 15, function 0 */
+
+#define MCMTR 0x7c
+
+#define IS_ECC_ENABLED(mcmtr) GET_BITFIELD(mcmtr, 2, 2)
+#define IS_LOCKSTEP_ENABLED(mcmtr) GET_BITFIELD(mcmtr, 1, 1)
+#define IS_CLOSE_PG(mcmtr) GET_BITFIELD(mcmtr, 0, 0)
+
+/* Device 15, function 1 */
+
+#define RASENABLES 0xac
+#define IS_MIRROR_ENABLED(reg) GET_BITFIELD(reg, 0, 0)
+
+/* Device 15, functions 2-5 */
+
+static const int mtr_regs[] = {
+ 0x80, 0x84, 0x88,
+};
+
+#define RANK_DISABLE(mtr) GET_BITFIELD(mtr, 16, 19)
+#define IS_DIMM_PRESENT(mtr) GET_BITFIELD(mtr, 14, 14)
+#define RANK_CNT_BITS(mtr) GET_BITFIELD(mtr, 12, 13)
+#define RANK_WIDTH_BITS(mtr) GET_BITFIELD(mtr, 2, 4)
+#define COL_WIDTH_BITS(mtr) GET_BITFIELD(mtr, 0, 1)
+
+static const u32 tad_ch_nilv_offset[] = {
+ 0x90, 0x94, 0x98, 0x9c,
+ 0xa0, 0xa4, 0xa8, 0xac,
+ 0xb0, 0xb4, 0xb8, 0xbc,
+};
+#define CHN_IDX_OFFSET(reg) GET_BITFIELD(reg, 28, 29)
+#define TAD_OFFSET(reg) (GET_BITFIELD(reg, 6, 25) << 26)
+
+static const u32 rir_way_limit[] = {
+ 0x108, 0x10c, 0x110, 0x114, 0x118,
+};
+#define MAX_RIR_RANGES ARRAY_SIZE(rir_way_limit)
+
+#define IS_RIR_VALID(reg) GET_BITFIELD(reg, 31, 31)
+#define RIR_WAY(reg) GET_BITFIELD(reg, 28, 29)
+#define RIR_LIMIT(reg) ((GET_BITFIELD(reg, 1, 10) << 29)| 0x1fffffff)
+
+#define MAX_RIR_WAY 8
+
+static const u32 rir_offset[MAX_RIR_RANGES][MAX_RIR_WAY] = {
+ { 0x120, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c },
+ { 0x140, 0x144, 0x148, 0x14c, 0x150, 0x154, 0x158, 0x15c },
+ { 0x160, 0x164, 0x168, 0x16c, 0x170, 0x174, 0x178, 0x17c },
+ { 0x180, 0x184, 0x188, 0x18c, 0x190, 0x194, 0x198, 0x19c },
+ { 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc },
+};
+
+#define RIR_RNK_TGT(reg) GET_BITFIELD(reg, 16, 19)
+#define RIR_OFFSET(reg) GET_BITFIELD(reg, 2, 14)
+
+/* Device 16, functions 2-7 */
+
+/*
+ * FIXME: Implement the error count reads directly
+ */
+
+static const u32 correrrcnt[] = {
+ 0x104, 0x108, 0x10c, 0x110,
+};
+
+#define RANK_ODD_OV(reg) GET_BITFIELD(reg, 31, 31)
+#define RANK_ODD_ERR_CNT(reg) GET_BITFIELD(reg, 16, 30)
+#define RANK_EVEN_OV(reg) GET_BITFIELD(reg, 15, 15)
+#define RANK_EVEN_ERR_CNT(reg) GET_BITFIELD(reg, 0, 14)
+
+static const u32 correrrthrsld[] = {
+ 0x11c, 0x120, 0x124, 0x128,
+};
+
+#define RANK_ODD_ERR_THRSLD(reg) GET_BITFIELD(reg, 16, 30)
+#define RANK_EVEN_ERR_THRSLD(reg) GET_BITFIELD(reg, 0, 14)
+
+
+/* Device 17, function 0 */
+
+#define RANK_CFG_A 0x0328
+
+#define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11)
+
+/*
+ * sbridge structs
+ */
+
+#define NUM_CHANNELS 4
+#define MAX_DIMMS 3 /* Max DIMMS per channel */
+
+struct sbridge_info {
+ u32 mcmtr;
+};
+
+struct sbridge_channel {
+ u32 ranks;
+ u32 dimms;
+};
+
+struct pci_id_descr {
+ int dev;
+ int func;
+ int dev_id;
+ int optional;
+};
+
+struct pci_id_table {
+ const struct pci_id_descr *descr;
+ int n_devs;
+};
+
+struct sbridge_dev {
+ struct list_head list;
+ u8 bus, mc;
+ u8 node_id, source_id;
+ struct pci_dev **pdev;
+ int n_devs;
+ struct mem_ctl_info *mci;
+};
+
+struct sbridge_pvt {
+ struct pci_dev *pci_ta, *pci_ddrio, *pci_ras;
+ struct pci_dev *pci_sad0, *pci_sad1, *pci_ha0;
+ struct pci_dev *pci_br;
+ struct pci_dev *pci_tad[NUM_CHANNELS];
+
+ struct sbridge_dev *sbridge_dev;
+
+ struct sbridge_info info;
+ struct sbridge_channel channel[NUM_CHANNELS];
+
+ int csrow_map[NUM_CHANNELS][MAX_DIMMS];
+
+ /* Memory type detection */
+ bool is_mirrored, is_lockstep, is_close_pg;
+
+ /* Fifo double buffers */
+ struct mce mce_entry[MCE_LOG_LEN];
+ struct mce mce_outentry[MCE_LOG_LEN];
+
+ /* Fifo in/out counters */
+ unsigned mce_in, mce_out;
+
+ /* Count indicator to show errors not got */
+ unsigned mce_overrun;
+
+ /* Memory description */
+ u64 tolm, tohm;
+};
+
+#define PCI_DESCR(device, function, device_id) \
+ .dev = (device), \
+ .func = (function), \
+ .dev_id = (device_id)
+
+static const struct pci_id_descr pci_dev_descr_sbridge[] = {
+ /* Processor Home Agent */
+ { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0) },
+
+ /* Memory controller */
+ { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA) },
+ { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS) },
+ { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0) },
+ { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1) },
+ { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2) },
+ { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3) },
+ { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO) },
+
+ /* System Address Decoder */
+ { PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0) },
+ { PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1) },
+
+ /* Broadcast Registers */
+ { PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR) },
+};
+
+#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
+static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge),
+ {0,} /* 0 terminated list. */
+};
+
+/*
+ * pci_device_id table for which devices we are looking for
+ */
+static const struct pci_device_id sbridge_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)},
+ {0,} /* 0 terminated list. */
+};
+
+
+/****************************************************************************
+ Anciliary status routines
+ ****************************************************************************/
+
+static inline int numrank(u32 mtr)
+{
+ int ranks = (1 << RANK_CNT_BITS(mtr));
+
+ if (ranks > 4) {
+ debugf0("Invalid number of ranks: %d (max = 4) raw value = %x (%04x)",
+ ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr);
+ return -EINVAL;
+ }
+
+ return ranks;
+}
+
+static inline int numrow(u32 mtr)
+{
+ int rows = (RANK_WIDTH_BITS(mtr) + 12);
+
+ if (rows < 13 || rows > 18) {
+ debugf0("Invalid number of rows: %d (should be between 14 and 17) raw value = %x (%04x)",
+ rows, (unsigned int)RANK_WIDTH_BITS(mtr), mtr);
+ return -EINVAL;
+ }
+
+ return 1 << rows;
+}
+
+static inline int numcol(u32 mtr)
+{
+ int cols = (COL_WIDTH_BITS(mtr) + 10);
+
+ if (cols > 12) {
+ debugf0("Invalid number of cols: %d (max = 4) raw value = %x (%04x)",
+ cols, (unsigned int)COL_WIDTH_BITS(mtr), mtr);
+ return -EINVAL;
+ }
+
+ return 1 << cols;
+}
+
+static struct sbridge_dev *get_sbridge_dev(u8 bus)
+{
+ struct sbridge_dev *sbridge_dev;
+
+ list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+ if (sbridge_dev->bus == bus)
+ return sbridge_dev;
+ }
+
+ return NULL;
+}
+
+static struct sbridge_dev *alloc_sbridge_dev(u8 bus,
+ const struct pci_id_table *table)
+{
+ struct sbridge_dev *sbridge_dev;
+
+ sbridge_dev = kzalloc(sizeof(*sbridge_dev), GFP_KERNEL);
+ if (!sbridge_dev)
+ return NULL;
+
+ sbridge_dev->pdev = kzalloc(sizeof(*sbridge_dev->pdev) * table->n_devs,
+ GFP_KERNEL);
+ if (!sbridge_dev->pdev) {
+ kfree(sbridge_dev);
+ return NULL;
+ }
+
+ sbridge_dev->bus = bus;
+ sbridge_dev->n_devs = table->n_devs;
+ list_add_tail(&sbridge_dev->list, &sbridge_edac_list);
+
+ return sbridge_dev;
+}
+
+static void free_sbridge_dev(struct sbridge_dev *sbridge_dev)
+{
+ list_del(&sbridge_dev->list);
+ kfree(sbridge_dev->pdev);
+ kfree(sbridge_dev);
+}
+
+/****************************************************************************
+ Memory check routines
+ ****************************************************************************/
+static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot,
+ unsigned func)
+{
+ struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus);
+ int i;
+
+ if (!sbridge_dev)
+ return NULL;
+
+ for (i = 0; i < sbridge_dev->n_devs; i++) {
+ if (!sbridge_dev->pdev[i])
+ continue;
+
+ if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot &&
+ PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) {
+ debugf1("Associated %02x.%02x.%d with %p\n",
+ bus, slot, func, sbridge_dev->pdev[i]);
+ return sbridge_dev->pdev[i];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * sbridge_get_active_channels() - gets the number of channels and csrows
+ * bus: Device bus
+ * @channels: Number of channels that will be returned
+ * @csrows: Number of csrows found
+ *
+ * Since EDAC core needs to know in advance the number of available channels
+ * and csrows, in order to allocate memory for csrows/channels, it is needed
+ * to run two similar steps. At the first step, implemented on this function,
+ * it checks the number of csrows/channels present at one socket, identified
+ * by the associated PCI bus.
+ * this is used in order to properly allocate the size of mci components.
+ * Note: one csrow is one dimm.
+ */
+static int sbridge_get_active_channels(const u8 bus, unsigned *channels,
+ unsigned *csrows)
+{
+ struct pci_dev *pdev = NULL;
+ int i, j;
+ u32 mcmtr;
+
+ *channels = 0;
+ *csrows = 0;
+
+ pdev = get_pdev_slot_func(bus, 15, 0);
+ if (!pdev) {
+ sbridge_printk(KERN_ERR, "Couldn't find PCI device "
+ "%2x.%02d.%d!!!\n",
+ bus, 15, 0);
+ return -ENODEV;
+ }
+
+ pci_read_config_dword(pdev, MCMTR, &mcmtr);
+ if (!IS_ECC_ENABLED(mcmtr)) {
+ sbridge_printk(KERN_ERR, "ECC is disabled. Aborting\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ u32 mtr;
+
+ /* Device 15 functions 2 - 5 */
+ pdev = get_pdev_slot_func(bus, 15, 2 + i);
+ if (!pdev) {
+ sbridge_printk(KERN_ERR, "Couldn't find PCI device "
+ "%2x.%02d.%d!!!\n",
+ bus, 15, 2 + i);
+ return -ENODEV;
+ }
+ (*channels)++;
+
+ for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) {
+ pci_read_config_dword(pdev, mtr_regs[j], &mtr);
+ debugf1("Bus#%02x channel #%d MTR%d = %x\n", bus, i, j, mtr);
+ if (IS_DIMM_PRESENT(mtr))
+ (*csrows)++;
+ }
+ }
+
+ debugf0("Number of active channels: %d, number of active dimms: %d\n",
+ *channels, *csrows);
+
+ return 0;
+}
+
+static int get_dimm_config(const struct mem_ctl_info *mci)
+{
+ struct sbridge_pvt *pvt = mci->pvt_info;
+ struct csrow_info *csr;
+ int i, j, banks, ranks, rows, cols, size, npages;
+ int csrow = 0;
+ unsigned long last_page = 0;
+ u32 reg;
+ enum edac_type mode;
+ enum mem_type mtype;
+
+ pci_read_config_dword(pvt->pci_br, SAD_TARGET, &reg);
+ pvt->sbridge_dev->source_id = SOURCE_ID(reg);
+
+ pci_read_config_dword(pvt->pci_br, SAD_CONTROL, &reg);
+ pvt->sbridge_dev->node_id = NODE_ID(reg);
+ debugf0("mc#%d: Node ID: %d, source ID: %d\n",
+ pvt->sbridge_dev->mc,
+ pvt->sbridge_dev->node_id,
+ pvt->sbridge_dev->source_id);
+
+ pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
+ if (IS_MIRROR_ENABLED(reg)) {
+ debugf0("Memory mirror is enabled\n");
+ pvt->is_mirrored = true;
+ } else {
+ debugf0("Memory mirror is disabled\n");
+ pvt->is_mirrored = false;
+ }
+
+ pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
+ if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
+ debugf0("Lockstep is enabled\n");
+ mode = EDAC_S8ECD8ED;
+ pvt->is_lockstep = true;
+ } else {
+ debugf0("Lockstep is disabled\n");
+ mode = EDAC_S4ECD4ED;
+ pvt->is_lockstep = false;
+ }
+ if (IS_CLOSE_PG(pvt->info.mcmtr)) {
+ debugf0("address map is on closed page mode\n");
+ pvt->is_close_pg = true;
+ } else {
+ debugf0("address map is on open page mode\n");
+ pvt->is_close_pg = false;
+ }
+
+ pci_read_config_dword(pvt->pci_ta, RANK_CFG_A, &reg);
+ if (IS_RDIMM_ENABLED(reg)) {
+ /* FIXME: Can also be LRDIMM */
+ debugf0("Memory is registered\n");
+ mtype = MEM_RDDR3;
+ } else {
+ debugf0("Memory is unregistered\n");
+ mtype = MEM_DDR3;
+ }
+
+ /* On all supported DDR3 DIMM types, there are 8 banks available */
+ banks = 8;
+
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ u32 mtr;
+
+ for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) {
+ pci_read_config_dword(pvt->pci_tad[i],
+ mtr_regs[j], &mtr);
+ debugf4("Channel #%d MTR%d = %x\n", i, j, mtr);
+ if (IS_DIMM_PRESENT(mtr)) {
+ pvt->channel[i].dimms++;
+
+ ranks = numrank(mtr);
+ rows = numrow(mtr);
+ cols = numcol(mtr);
+
+ /* DDR3 has 8 I/O banks */
+ size = (rows * cols * banks * ranks) >> (20 - 3);
+ npages = MiB_TO_PAGES(size);
+
+ debugf0("mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
+ pvt->sbridge_dev->mc, i, j,
+ size, npages,
+ banks, ranks, rows, cols);
+ csr = &mci->csrows[csrow];
+
+ csr->first_page = last_page;
+ csr->last_page = last_page + npages - 1;
+ csr->page_mask = 0UL; /* Unused */
+ csr->nr_pages = npages;
+ csr->grain = 32;
+ csr->csrow_idx = csrow;
+ csr->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
+ csr->ce_count = 0;
+ csr->ue_count = 0;
+ csr->mtype = mtype;
+ csr->edac_mode = mode;
+ csr->nr_channels = 1;
+ csr->channels[0].chan_idx = i;
+ csr->channels[0].ce_count = 0;
+ pvt->csrow_map[i][j] = csrow;
+ snprintf(csr->channels[0].label,
+ sizeof(csr->channels[0].label),
+ "CPU_SrcID#%u_Channel#%u_DIMM#%u",
+ pvt->sbridge_dev->source_id, i, j);
+ last_page += npages;
+ csrow++;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void get_memory_layout(const struct mem_ctl_info *mci)
+{
+ struct sbridge_pvt *pvt = mci->pvt_info;
+ int i, j, k, n_sads, n_tads, sad_interl;
+ u32 reg;
+ u64 limit, prv = 0;
+ u64 tmp_mb;
+ u32 rir_way;
+
+ /*
+ * Step 1) Get TOLM/TOHM ranges
+ */
+
+ /* Address range is 32:28 */
+ pci_read_config_dword(pvt->pci_sad1, TOLM,
+ &reg);
+ pvt->tolm = GET_TOLM(reg);
+ tmp_mb = (1 + pvt->tolm) >> 20;
+
+ debugf0("TOLM: %Lu.%03Lu GB (0x%016Lx)\n",
+ tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tolm);
+
+ /* Address range is already 45:25 */
+ pci_read_config_dword(pvt->pci_sad1, TOHM,
+ &reg);
+ pvt->tohm = GET_TOHM(reg);
+ tmp_mb = (1 + pvt->tohm) >> 20;
+
+ debugf0("TOHM: %Lu.%03Lu GB (0x%016Lx)",
+ tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tohm);
+
+ /*
+ * Step 2) Get SAD range and SAD Interleave list
+ * TAD registers contain the interleave wayness. However, it
+ * seems simpler to just discover it indirectly, with the
+ * algorithm bellow.
+ */
+ prv = 0;
+ for (n_sads = 0; n_sads < MAX_SAD; n_sads++) {
+ /* SAD_LIMIT Address range is 45:26 */
+ pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads],
+ &reg);
+ limit = SAD_LIMIT(reg);
+
+ if (!DRAM_RULE_ENABLE(reg))
+ continue;
+
+ if (limit <= prv)
+ break;
+
+ tmp_mb = (limit + 1) >> 20;
+ debugf0("SAD#%d %s up to %Lu.%03Lu GB (0x%016Lx) %s reg=0x%08x\n",
+ n_sads,
+ get_dram_attr(reg),
+ tmp_mb / 1000, tmp_mb % 1000,
+ ((u64)tmp_mb) << 20L,
+ INTERLEAVE_MODE(reg) ? "Interleave: 8:6" : "Interleave: [8:6]XOR[18:16]",
+ reg);
+ prv = limit;
+
+ pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads],
+ &reg);
+ sad_interl = sad_pkg(reg, 0);
+ for (j = 0; j < 8; j++) {
+ if (j > 0 && sad_interl == sad_pkg(reg, j))
+ break;
+
+ debugf0("SAD#%d, interleave #%d: %d\n",
+ n_sads, j, sad_pkg(reg, j));
+ }
+ }
+
+ /*
+ * Step 3) Get TAD range
+ */
+ prv = 0;
+ for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
+ pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
+ &reg);
+ limit = TAD_LIMIT(reg);
+ if (limit <= prv)
+ break;
+ tmp_mb = (limit + 1) >> 20;
+
+ debugf0("TAD#%d: up to %Lu.%03Lu GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
+ n_tads, tmp_mb / 1000, tmp_mb % 1000,
+ ((u64)tmp_mb) << 20L,
+ (u32)TAD_SOCK(reg),
+ (u32)TAD_CH(reg),
+ (u32)TAD_TGT0(reg),
+ (u32)TAD_TGT1(reg),
+ (u32)TAD_TGT2(reg),
+ (u32)TAD_TGT3(reg),
+ reg);
+ prv = tmp_mb;
+ }
+
+ /*
+ * Step 4) Get TAD offsets, per each channel
+ */
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ if (!pvt->channel[i].dimms)
+ continue;
+ for (j = 0; j < n_tads; j++) {
+ pci_read_config_dword(pvt->pci_tad[i],
+ tad_ch_nilv_offset[j],
+ &reg);
+ tmp_mb = TAD_OFFSET(reg) >> 20;
+ debugf0("TAD CH#%d, offset #%d: %Lu.%03Lu GB (0x%016Lx), reg=0x%08x\n",
+ i, j,
+ tmp_mb / 1000, tmp_mb % 1000,
+ ((u64)tmp_mb) << 20L,
+ reg);
+ }
+ }
+
+ /*
+ * Step 6) Get RIR Wayness/Limit, per each channel
+ */
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ if (!pvt->channel[i].dimms)
+ continue;
+ for (j = 0; j < MAX_RIR_RANGES; j++) {
+ pci_read_config_dword(pvt->pci_tad[i],
+ rir_way_limit[j],
+ &reg);
+
+ if (!IS_RIR_VALID(reg))
+ continue;
+
+ tmp_mb = RIR_LIMIT(reg) >> 20;
+ rir_way = 1 << RIR_WAY(reg);
+ debugf0("CH#%d RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d, reg=0x%08x\n",
+ i, j,
+ tmp_mb / 1000, tmp_mb % 1000,
+ ((u64)tmp_mb) << 20L,
+ rir_way,
+ reg);
+
+ for (k = 0; k < rir_way; k++) {
+ pci_read_config_dword(pvt->pci_tad[i],
+ rir_offset[j][k],
+ &reg);
+ tmp_mb = RIR_OFFSET(reg) << 6;
+
+ debugf0("CH#%d RIR#%d INTL#%d, offset %Lu.%03Lu GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
+ i, j, k,
+ tmp_mb / 1000, tmp_mb % 1000,
+ ((u64)tmp_mb) << 20L,
+ (u32)RIR_RNK_TGT(reg),
+ reg);
+ }
+ }
+ }
+}
+
+struct mem_ctl_info *get_mci_for_node_id(u8 node_id)
+{
+ struct sbridge_dev *sbridge_dev;
+
+ list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+ if (sbridge_dev->node_id == node_id)
+ return sbridge_dev->mci;
+ }
+ return NULL;
+}
+
+static int get_memory_error_data(struct mem_ctl_info *mci,
+ u64 addr,
+ u8 *socket,
+ long *channel_mask,
+ u8 *rank,
+ char *area_type)
+{
+ struct mem_ctl_info *new_mci;
+ struct sbridge_pvt *pvt = mci->pvt_info;
+ char msg[256];
+ int n_rir, n_sads, n_tads, sad_way, sck_xch;
+ int sad_interl, idx, base_ch;
+ int interleave_mode;
+ unsigned sad_interleave[MAX_INTERLEAVE];
+ u32 reg;
+ u8 ch_way,sck_way;
+ u32 tad_offset;
+ u32 rir_way;
+ u64 ch_addr, offset, limit, prv = 0;
+
+
+ /*
+ * Step 0) Check if the address is at special memory ranges
+ * The check bellow is probably enough to fill all cases where
+ * the error is not inside a memory, except for the legacy
+ * range (e. g. VGA addresses). It is unlikely, however, that the
+ * memory controller would generate an error on that range.
+ */
+ if ((addr > (u64) pvt->tolm) && (addr < (1L << 32))) {
+ sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr);
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+ if (addr >= (u64)pvt->tohm) {
+ sprintf(msg, "Error at MMIOH area, on addr 0x%016Lx", addr);
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+
+ /*
+ * Step 1) Get socket
+ */
+ for (n_sads = 0; n_sads < MAX_SAD; n_sads++) {
+ pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads],
+ &reg);
+
+ if (!DRAM_RULE_ENABLE(reg))
+ continue;
+
+ limit = SAD_LIMIT(reg);
+ if (limit <= prv) {
+ sprintf(msg, "Can't discover the memory socket");
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+ if (addr <= limit)
+ break;
+ prv = limit;
+ }
+ if (n_sads == MAX_SAD) {
+ sprintf(msg, "Can't discover the memory socket");
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+ area_type = get_dram_attr(reg);
+ interleave_mode = INTERLEAVE_MODE(reg);
+
+ pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads],
+ &reg);
+ sad_interl = sad_pkg(reg, 0);
+ for (sad_way = 0; sad_way < 8; sad_way++) {
+ if (sad_way > 0 && sad_interl == sad_pkg(reg, sad_way))
+ break;
+ sad_interleave[sad_way] = sad_pkg(reg, sad_way);
+ debugf0("SAD interleave #%d: %d\n",
+ sad_way, sad_interleave[sad_way]);
+ }
+ debugf0("mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n",
+ pvt->sbridge_dev->mc,
+ n_sads,
+ addr,
+ limit,
+ sad_way + 7,
+ INTERLEAVE_MODE(reg) ? "" : "XOR[18:16]");
+ if (interleave_mode)
+ idx = ((addr >> 6) ^ (addr >> 16)) & 7;
+ else
+ idx = (addr >> 6) & 7;
+ switch (sad_way) {
+ case 1:
+ idx = 0;
+ break;
+ case 2:
+ idx = idx & 1;
+ break;
+ case 4:
+ idx = idx & 3;
+ break;
+ case 8:
+ break;
+ default:
+ sprintf(msg, "Can't discover socket interleave");
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+ *socket = sad_interleave[idx];
+ debugf0("SAD interleave index: %d (wayness %d) = CPU socket %d\n",
+ idx, sad_way, *socket);
+
+ /*
+ * Move to the proper node structure, in order to access the
+ * right PCI registers
+ */
+ new_mci = get_mci_for_node_id(*socket);
+ if (!new_mci) {
+ sprintf(msg, "Struct for socket #%u wasn't initialized",
+ *socket);
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+ mci = new_mci;
+ pvt = mci->pvt_info;
+
+ /*
+ * Step 2) Get memory channel
+ */
+ prv = 0;
+ for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
+ pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
+ &reg);
+ limit = TAD_LIMIT(reg);
+ if (limit <= prv) {
+ sprintf(msg, "Can't discover the memory channel");
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+ if (addr <= limit)
+ break;
+ prv = limit;
+ }
+ ch_way = TAD_CH(reg) + 1;
+ sck_way = TAD_SOCK(reg) + 1;
+ /*
+ * FIXME: Is it right to always use channel 0 for offsets?
+ */
+ pci_read_config_dword(pvt->pci_tad[0],
+ tad_ch_nilv_offset[n_tads],
+ &tad_offset);
+
+ if (ch_way == 3)
+ idx = addr >> 6;
+ else
+ idx = addr >> (6 + sck_way);
+ idx = idx % ch_way;
+
+ /*
+ * FIXME: Shouldn't we use CHN_IDX_OFFSET() here, when ch_way == 3 ???
+ */
+ switch (idx) {
+ case 0:
+ base_ch = TAD_TGT0(reg);
+ break;
+ case 1:
+ base_ch = TAD_TGT1(reg);
+ break;
+ case 2:
+ base_ch = TAD_TGT2(reg);
+ break;
+ case 3:
+ base_ch = TAD_TGT3(reg);
+ break;
+ default:
+ sprintf(msg, "Can't discover the TAD target");
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+ *channel_mask = 1 << base_ch;
+
+ if (pvt->is_mirrored) {
+ *channel_mask |= 1 << ((base_ch + 2) % 4);
+ switch(ch_way) {
+ case 2:
+ case 4:
+ sck_xch = 1 << sck_way * (ch_way >> 1);
+ break;
+ default:
+ sprintf(msg, "Invalid mirror set. Can't decode addr");
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+ } else
+ sck_xch = (1 << sck_way) * ch_way;
+
+ if (pvt->is_lockstep)
+ *channel_mask |= 1 << ((base_ch + 1) % 4);
+
+ offset = TAD_OFFSET(tad_offset);
+
+ debugf0("TAD#%d: address 0x%016Lx < 0x%016Lx, socket interleave %d, channel interleave %d (offset 0x%08Lx), index %d, base ch: %d, ch mask: 0x%02lx\n",
+ n_tads,
+ addr,
+ limit,
+ (u32)TAD_SOCK(reg),
+ ch_way,
+ offset,
+ idx,
+ base_ch,
+ *channel_mask);
+
+ /* Calculate channel address */
+ /* Remove the TAD offset */
+
+ if (offset > addr) {
+ sprintf(msg, "Can't calculate ch addr: TAD offset 0x%08Lx is too high for addr 0x%08Lx!",
+ offset, addr);
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+ addr -= offset;
+ /* Store the low bits [0:6] of the addr */
+ ch_addr = addr & 0x7f;
+ /* Remove socket wayness and remove 6 bits */
+ addr >>= 6;
+ addr /= sck_xch;
+#if 0
+ /* Divide by channel way */
+ addr = addr / ch_way;
+#endif
+ /* Recover the last 6 bits */
+ ch_addr |= addr << 6;
+
+ /*
+ * Step 3) Decode rank
+ */
+ for (n_rir = 0; n_rir < MAX_RIR_RANGES; n_rir++) {
+ pci_read_config_dword(pvt->pci_tad[base_ch],
+ rir_way_limit[n_rir],
+ &reg);
+
+ if (!IS_RIR_VALID(reg))
+ continue;
+
+ limit = RIR_LIMIT(reg);
+
+ debugf0("RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d\n",
+ n_rir,
+ (limit >> 20) / 1000, (limit >> 20) % 1000,
+ limit,
+ 1 << RIR_WAY(reg));
+ if (ch_addr <= limit)
+ break;
+ }
+ if (n_rir == MAX_RIR_RANGES) {
+ sprintf(msg, "Can't discover the memory rank for ch addr 0x%08Lx",
+ ch_addr);
+ edac_mc_handle_ce_no_info(mci, msg);
+ return -EINVAL;
+ }
+ rir_way = RIR_WAY(reg);
+ if (pvt->is_close_pg)
+ idx = (ch_addr >> 6);
+ else
+ idx = (ch_addr >> 13); /* FIXME: Datasheet says to shift by 15 */
+ idx %= 1 << rir_way;
+
+ pci_read_config_dword(pvt->pci_tad[base_ch],
+ rir_offset[n_rir][idx],
+ &reg);
+ *rank = RIR_RNK_TGT(reg);
+
+ debugf0("RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
+ n_rir,
+ ch_addr,
+ limit,
+ rir_way,
+ idx);
+
+ return 0;
+}
+
+/****************************************************************************
+ Device initialization routines: put/get, init/exit
+ ****************************************************************************/
+
+/*
+ * sbridge_put_all_devices 'put' all the devices that we have
+ * reserved via 'get'
+ */
+static void sbridge_put_devices(struct sbridge_dev *sbridge_dev)
+{
+ int i;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+ for (i = 0; i < sbridge_dev->n_devs; i++) {
+ struct pci_dev *pdev = sbridge_dev->pdev[i];
+ if (!pdev)
+ continue;
+ debugf0("Removing dev %02x:%02x.%d\n",
+ pdev->bus->number,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+ pci_dev_put(pdev);
+ }
+}
+
+static void sbridge_put_all_devices(void)
+{
+ struct sbridge_dev *sbridge_dev, *tmp;
+
+ list_for_each_entry_safe(sbridge_dev, tmp, &sbridge_edac_list, list) {
+ sbridge_put_devices(sbridge_dev);
+ free_sbridge_dev(sbridge_dev);
+ }
+}
+
+/*
+ * sbridge_get_all_devices Find and perform 'get' operation on the MCH's
+ * device/functions we want to reference for this driver
+ *
+ * Need to 'get' device 16 func 1 and func 2
+ */
+static int sbridge_get_onedevice(struct pci_dev **prev,
+ u8 *num_mc,
+ const struct pci_id_table *table,
+ const unsigned devno)
+{
+ struct sbridge_dev *sbridge_dev;
+ const struct pci_id_descr *dev_descr = &table->descr[devno];
+
+ struct pci_dev *pdev = NULL;
+ u8 bus = 0;
+
+ sbridge_printk(KERN_INFO,
+ "Seeking for: dev %02x.%d PCI ID %04x:%04x\n",
+ dev_descr->dev, dev_descr->func,
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ dev_descr->dev_id, *prev);
+
+ if (!pdev) {
+ if (*prev) {
+ *prev = pdev;
+ return 0;
+ }
+
+ if (dev_descr->optional)
+ return 0;
+
+ if (devno == 0)
+ return -ENODEV;
+
+ sbridge_printk(KERN_INFO,
+ "Device not found: dev %02x.%d PCI ID %04x:%04x\n",
+ dev_descr->dev, dev_descr->func,
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+ /* End of list, leave */
+ return -ENODEV;
+ }
+ bus = pdev->bus->number;
+
+ sbridge_dev = get_sbridge_dev(bus);
+ if (!sbridge_dev) {
+ sbridge_dev = alloc_sbridge_dev(bus, table);
+ if (!sbridge_dev) {
+ pci_dev_put(pdev);
+ return -ENOMEM;
+ }
+ (*num_mc)++;
+ }
+
+ if (sbridge_dev->pdev[devno]) {
+ sbridge_printk(KERN_ERR,
+ "Duplicated device for "
+ "dev %02x:%d.%d PCI ID %04x:%04x\n",
+ bus, dev_descr->dev, dev_descr->func,
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+ pci_dev_put(pdev);
+ return -ENODEV;
+ }
+
+ sbridge_dev->pdev[devno] = pdev;
+
+ /* Sanity check */
+ if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
+ PCI_FUNC(pdev->devfn) != dev_descr->func)) {
+ sbridge_printk(KERN_ERR,
+ "Device PCI ID %04x:%04x "
+ "has dev %02x:%d.%d instead of dev %02x:%02x.%d\n",
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
+ bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+ bus, dev_descr->dev, dev_descr->func);
+ return -ENODEV;
+ }
+
+ /* Be sure that the device is enabled */
+ if (unlikely(pci_enable_device(pdev) < 0)) {
+ sbridge_printk(KERN_ERR,
+ "Couldn't enable "
+ "dev %02x:%d.%d PCI ID %04x:%04x\n",
+ bus, dev_descr->dev, dev_descr->func,
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+ return -ENODEV;
+ }
+
+ debugf0("Detected dev %02x:%d.%d PCI ID %04x:%04x\n",
+ bus, dev_descr->dev,
+ dev_descr->func,
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+ /*
+ * As stated on drivers/pci/search.c, the reference count for
+ * @from is always decremented if it is not %NULL. So, as we need
+ * to get all devices up to null, we need to do a get for the device
+ */
+ pci_dev_get(pdev);
+
+ *prev = pdev;
+
+ return 0;
+}
+
+static int sbridge_get_all_devices(u8 *num_mc)
+{
+ int i, rc;
+ struct pci_dev *pdev = NULL;
+ const struct pci_id_table *table = pci_dev_descr_sbridge_table;
+
+ while (table && table->descr) {
+ for (i = 0; i < table->n_devs; i++) {
+ pdev = NULL;
+ do {
+ rc = sbridge_get_onedevice(&pdev, num_mc,
+ table, i);
+ if (rc < 0) {
+ if (i == 0) {
+ i = table->n_devs;
+ break;
+ }
+ sbridge_put_all_devices();
+ return -ENODEV;
+ }
+ } while (pdev);
+ }
+ table++;
+ }
+
+ return 0;
+}
+
+static int mci_bind_devs(struct mem_ctl_info *mci,
+ struct sbridge_dev *sbridge_dev)
+{
+ struct sbridge_pvt *pvt = mci->pvt_info;
+ struct pci_dev *pdev;
+ int i, func, slot;
+
+ for (i = 0; i < sbridge_dev->n_devs; i++) {
+ pdev = sbridge_dev->pdev[i];
+ if (!pdev)
+ continue;
+ slot = PCI_SLOT(pdev->devfn);
+ func = PCI_FUNC(pdev->devfn);
+ switch (slot) {
+ case 12:
+ switch (func) {
+ case 6:
+ pvt->pci_sad0 = pdev;
+ break;
+ case 7:
+ pvt->pci_sad1 = pdev;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case 13:
+ switch (func) {
+ case 6:
+ pvt->pci_br = pdev;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case 14:
+ switch (func) {
+ case 0:
+ pvt->pci_ha0 = pdev;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case 15:
+ switch (func) {
+ case 0:
+ pvt->pci_ta = pdev;
+ break;
+ case 1:
+ pvt->pci_ras = pdev;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ pvt->pci_tad[func - 2] = pdev;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case 17:
+ switch (func) {
+ case 0:
+ pvt->pci_ddrio = pdev;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ default:
+ goto error;
+ }
+
+ debugf0("Associated PCI %02x.%02d.%d with dev = %p\n",
+ sbridge_dev->bus,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+ pdev);
+ }
+
+ /* Check if everything were registered */
+ if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha0 ||
+ !pvt-> pci_tad || !pvt->pci_ras || !pvt->pci_ta ||
+ !pvt->pci_ddrio)
+ goto enodev;
+
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ if (!pvt->pci_tad[i])
+ goto enodev;
+ }
+ return 0;
+
+enodev:
+ sbridge_printk(KERN_ERR, "Some needed devices are missing\n");
+ return -ENODEV;
+
+error:
+ sbridge_printk(KERN_ERR, "Device %d, function %d "
+ "is out of the expected range\n",
+ slot, func);
+ return -EINVAL;
+}
+
+/****************************************************************************
+ Error check routines
+ ****************************************************************************/
+
+/*
+ * While Sandy Bridge has error count registers, SMI BIOS read values from
+ * and resets the counters. So, they are not reliable for the OS to read
+ * from them. So, we have no option but to just trust on whatever MCE is
+ * telling us about the errors.
+ */
+static void sbridge_mce_output_error(struct mem_ctl_info *mci,
+ const struct mce *m)
+{
+ struct mem_ctl_info *new_mci;
+ struct sbridge_pvt *pvt = mci->pvt_info;
+ char *type, *optype, *msg, *recoverable_msg;
+ bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0);
+ bool overflow = GET_BITFIELD(m->status, 62, 62);
+ bool uncorrected_error = GET_BITFIELD(m->status, 61, 61);
+ bool recoverable = GET_BITFIELD(m->status, 56, 56);
+ u32 core_err_cnt = GET_BITFIELD(m->status, 38, 52);
+ u32 mscod = GET_BITFIELD(m->status, 16, 31);
+ u32 errcode = GET_BITFIELD(m->status, 0, 15);
+ u32 channel = GET_BITFIELD(m->status, 0, 3);
+ u32 optypenum = GET_BITFIELD(m->status, 4, 6);
+ long channel_mask, first_channel;
+ u8 rank, socket;
+ int csrow, rc, dimm;
+ char *area_type = "Unknown";
+
+ if (ripv)
+ type = "NON_FATAL";
+ else
+ type = "FATAL";
+
+ /*
+ * According with Table 15-9 of the Intel Archictecture spec vol 3A,
+ * memory errors should fit in this mask:
+ * 000f 0000 1mmm cccc (binary)
+ * where:
+ * f = Correction Report Filtering Bit. If 1, subsequent errors
+ * won't be shown
+ * mmm = error type
+ * cccc = channel
+ * If the mask doesn't match, report an error to the parsing logic
+ */
+ if (! ((errcode & 0xef80) == 0x80)) {
+ optype = "Can't parse: it is not a mem";
+ } else {
+ switch (optypenum) {
+ case 0:
+ optype = "generic undef request";
+ break;
+ case 1:
+ optype = "memory read";
+ break;
+ case 2:
+ optype = "memory write";
+ break;
+ case 3:
+ optype = "addr/cmd";
+ break;
+ case 4:
+ optype = "memory scrubbing";
+ break;
+ default:
+ optype = "reserved";
+ break;
+ }
+ }
+
+ rc = get_memory_error_data(mci, m->addr, &socket,
+ &channel_mask, &rank, area_type);
+ if (rc < 0)
+ return;
+ new_mci = get_mci_for_node_id(socket);
+ if (!new_mci) {
+ edac_mc_handle_ce_no_info(mci, "Error: socket got corrupted!");
+ return;
+ }
+ mci = new_mci;
+ pvt = mci->pvt_info;
+
+ first_channel = find_first_bit(&channel_mask, NUM_CHANNELS);
+
+ if (rank < 4)
+ dimm = 0;
+ else if (rank < 8)
+ dimm = 1;
+ else
+ dimm = 2;
+
+ csrow = pvt->csrow_map[first_channel][dimm];
+
+ if (uncorrected_error && recoverable)
+ recoverable_msg = " recoverable";
+ else
+ recoverable_msg = "";
+
+ /*
+ * FIXME: What should we do with "channel" information on mcelog?
+ * Probably, we can just discard it, as the channel information
+ * comes from the get_memory_error_data() address decoding
+ */
+ msg = kasprintf(GFP_ATOMIC,
+ "%d %s error(s): %s on %s area %s%s: cpu=%d Err=%04x:%04x (ch=%d), "
+ "addr = 0x%08llx => socket=%d, Channel=%ld(mask=%ld), rank=%d\n",
+ core_err_cnt,
+ area_type,
+ optype,
+ type,
+ recoverable_msg,
+ overflow ? "OVERFLOW" : "",
+ m->cpu,
+ mscod, errcode,
+ channel, /* 1111b means not specified */
+ (long long) m->addr,
+ socket,
+ first_channel, /* This is the real channel on SB */
+ channel_mask,
+ rank);
+
+ debugf0("%s", msg);
+
+ /* Call the helper to output message */
+ if (uncorrected_error)
+ edac_mc_handle_fbd_ue(mci, csrow, 0, 0, msg);
+ else
+ edac_mc_handle_fbd_ce(mci, csrow, 0, msg);
+
+ kfree(msg);
+}
+
+/*
+ * sbridge_check_error Retrieve and process errors reported by the
+ * hardware. Called by the Core module.
+ */
+static void sbridge_check_error(struct mem_ctl_info *mci)
+{
+ struct sbridge_pvt *pvt = mci->pvt_info;
+ int i;
+ unsigned count = 0;
+ struct mce *m;
+
+ /*
+ * MCE first step: Copy all mce errors into a temporary buffer
+ * We use a double buffering here, to reduce the risk of
+ * loosing an error.
+ */
+ smp_rmb();
+ count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in)
+ % MCE_LOG_LEN;
+ if (!count)
+ return;
+
+ m = pvt->mce_outentry;
+ if (pvt->mce_in + count > MCE_LOG_LEN) {
+ unsigned l = MCE_LOG_LEN - pvt->mce_in;
+
+ memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l);
+ smp_wmb();
+ pvt->mce_in = 0;
+ count -= l;
+ m += l;
+ }
+ memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count);
+ smp_wmb();
+ pvt->mce_in += count;
+
+ smp_rmb();
+ if (pvt->mce_overrun) {
+ sbridge_printk(KERN_ERR, "Lost %d memory errors\n",
+ pvt->mce_overrun);
+ smp_wmb();
+ pvt->mce_overrun = 0;
+ }
+
+ /*
+ * MCE second step: parse errors and display
+ */
+ for (i = 0; i < count; i++)
+ sbridge_mce_output_error(mci, &pvt->mce_outentry[i]);
+}
+
+/*
+ * sbridge_mce_check_error Replicates mcelog routine to get errors
+ * This routine simply queues mcelog errors, and
+ * return. The error itself should be handled later
+ * by sbridge_check_error.
+ * WARNING: As this routine should be called at NMI time, extra care should
+ * be taken to avoid deadlocks, and to be as fast as possible.
+ */
+static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ struct mce *mce = (struct mce *)data;
+ struct mem_ctl_info *mci;
+ struct sbridge_pvt *pvt;
+
+ mci = get_mci_for_node_id(mce->socketid);
+ if (!mci)
+ return NOTIFY_BAD;
+ pvt = mci->pvt_info;
+
+ /*
+ * Just let mcelog handle it if the error is
+ * outside the memory controller. A memory error
+ * is indicated by bit 7 = 1 and bits = 8-11,13-15 = 0.
+ * bit 12 has an special meaning.
+ */
+ if ((mce->status & 0xefff) >> 7 != 1)
+ return NOTIFY_DONE;
+
+ printk("sbridge: HANDLING MCE MEMORY ERROR\n");
+
+ printk("CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n",
+ mce->extcpu, mce->mcgstatus, mce->bank, mce->status);
+ printk("TSC %llx ", mce->tsc);
+ printk("ADDR %llx ", mce->addr);
+ printk("MISC %llx ", mce->misc);
+
+ printk("PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
+ mce->cpuvendor, mce->cpuid, mce->time,
+ mce->socketid, mce->apicid);
+
+#ifdef CONFIG_SMP
+ /* Only handle if it is the right mc controller */
+ if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc)
+ return NOTIFY_DONE;
+#endif
+
+ smp_rmb();
+ if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
+ smp_wmb();
+ pvt->mce_overrun++;
+ return NOTIFY_DONE;
+ }
+
+ /* Copy memory error at the ringbuffer */
+ memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce));
+ smp_wmb();
+ pvt->mce_out = (pvt->mce_out + 1) % MCE_LOG_LEN;
+
+ /* Handle fatal errors immediately */
+ if (mce->mcgstatus & 1)
+ sbridge_check_error(mci);
+
+ /* Advice mcelog that the error were handled */
+ return NOTIFY_STOP;
+}
+
+static struct notifier_block sbridge_mce_dec = {
+ .notifier_call = sbridge_mce_check_error,
+};
+
+/****************************************************************************
+ EDAC register/unregister logic
+ ****************************************************************************/
+
+static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev)
+{
+ struct mem_ctl_info *mci = sbridge_dev->mci;
+ struct sbridge_pvt *pvt;
+
+ if (unlikely(!mci || !mci->pvt_info)) {
+ debugf0("MC: " __FILE__ ": %s(): dev = %p\n",
+ __func__, &sbridge_dev->pdev[0]->dev);
+
+ sbridge_printk(KERN_ERR, "Couldn't find mci handler\n");
+ return;
+ }
+
+ pvt = mci->pvt_info;
+
+ debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+ __func__, mci, &sbridge_dev->pdev[0]->dev);
+
+ atomic_notifier_chain_unregister(&x86_mce_decoder_chain,
+ &sbridge_mce_dec);
+
+ /* Remove MC sysfs nodes */
+ edac_mc_del_mc(mci->dev);
+
+ debugf1("%s: free mci struct\n", mci->ctl_name);
+ kfree(mci->ctl_name);
+ edac_mc_free(mci);
+ sbridge_dev->mci = NULL;
+}
+
+static int sbridge_register_mci(struct sbridge_dev *sbridge_dev)
+{
+ struct mem_ctl_info *mci;
+ struct sbridge_pvt *pvt;
+ int rc, channels, csrows;
+
+ /* Check the number of active and not disabled channels */
+ rc = sbridge_get_active_channels(sbridge_dev->bus, &channels, &csrows);
+ if (unlikely(rc < 0))
+ return rc;
+
+ /* allocate a new MC control structure */
+ mci = edac_mc_alloc(sizeof(*pvt), csrows, channels, sbridge_dev->mc);
+ if (unlikely(!mci))
+ return -ENOMEM;
+
+ debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+ __func__, mci, &sbridge_dev->pdev[0]->dev);
+
+ pvt = mci->pvt_info;
+ memset(pvt, 0, sizeof(*pvt));
+
+ /* Associate sbridge_dev and mci for future usage */
+ pvt->sbridge_dev = sbridge_dev;
+ sbridge_dev->mci = mci;
+
+ mci->mtype_cap = MEM_FLAG_DDR3;
+ mci->edac_ctl_cap = EDAC_FLAG_NONE;
+ mci->edac_cap = EDAC_FLAG_NONE;
+ mci->mod_name = "sbridge_edac.c";
+ mci->mod_ver = SBRIDGE_REVISION;
+ mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
+ mci->dev_name = pci_name(sbridge_dev->pdev[0]);
+ mci->ctl_page_to_phys = NULL;
+
+ /* Set the function pointer to an actual operation function */
+ mci->edac_check = sbridge_check_error;
+
+ /* Store pci devices at mci for faster access */
+ rc = mci_bind_devs(mci, sbridge_dev);
+ if (unlikely(rc < 0))
+ goto fail0;
+
+ /* Get dimm basic config and the memory layout */
+ get_dimm_config(mci);
+ get_memory_layout(mci);
+
+ /* record ptr to the generic device */
+ mci->dev = &sbridge_dev->pdev[0]->dev;
+
+ /* add this new MC control structure to EDAC's list of MCs */
+ if (unlikely(edac_mc_add_mc(mci))) {
+ debugf0("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ rc = -EINVAL;
+ goto fail0;
+ }
+
+ atomic_notifier_chain_register(&x86_mce_decoder_chain,
+ &sbridge_mce_dec);
+ return 0;
+
+fail0:
+ kfree(mci->ctl_name);
+ edac_mc_free(mci);
+ sbridge_dev->mci = NULL;
+ return rc;
+}
+
+/*
+ * sbridge_probe Probe for ONE instance of device to see if it is
+ * present.
+ * return:
+ * 0 for FOUND a device
+ * < 0 for error code
+ */
+
+static int __devinit sbridge_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int rc;
+ u8 mc, num_mc = 0;
+ struct sbridge_dev *sbridge_dev;
+
+ /* get the pci devices we want to reserve for our use */
+ mutex_lock(&sbridge_edac_lock);
+
+ /*
+ * All memory controllers are allocated at the first pass.
+ */
+ if (unlikely(probed >= 1)) {
+ mutex_unlock(&sbridge_edac_lock);
+ return -ENODEV;
+ }
+ probed++;
+
+ rc = sbridge_get_all_devices(&num_mc);
+ if (unlikely(rc < 0))
+ goto fail0;
+ mc = 0;
+
+ list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+ debugf0("Registering MC#%d (%d of %d)\n", mc, mc + 1, num_mc);
+ sbridge_dev->mc = mc++;
+ rc = sbridge_register_mci(sbridge_dev);
+ if (unlikely(rc < 0))
+ goto fail1;
+ }
+
+ sbridge_printk(KERN_INFO, "Driver loaded.\n");
+
+ mutex_unlock(&sbridge_edac_lock);
+ return 0;
+
+fail1:
+ list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
+ sbridge_unregister_mci(sbridge_dev);
+
+ sbridge_put_all_devices();
+fail0:
+ mutex_unlock(&sbridge_edac_lock);
+ return rc;
+}
+
+/*
+ * sbridge_remove destructor for one instance of device
+ *
+ */
+static void __devexit sbridge_remove(struct pci_dev *pdev)
+{
+ struct sbridge_dev *sbridge_dev;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ /*
+ * we have a trouble here: pdev value for removal will be wrong, since
+ * it will point to the X58 register used to detect that the machine
+ * is a Nehalem or upper design. However, due to the way several PCI
+ * devices are grouped together to provide MC functionality, we need
+ * to use a different method for releasing the devices
+ */
+
+ mutex_lock(&sbridge_edac_lock);
+
+ if (unlikely(!probed)) {
+ mutex_unlock(&sbridge_edac_lock);
+ return;
+ }
+
+ list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
+ sbridge_unregister_mci(sbridge_dev);
+
+ /* Release PCI resources */
+ sbridge_put_all_devices();
+
+ probed--;
+
+ mutex_unlock(&sbridge_edac_lock);
+}
+
+MODULE_DEVICE_TABLE(pci, sbridge_pci_tbl);
+
+/*
+ * sbridge_driver pci_driver structure for this module
+ *
+ */
+static struct pci_driver sbridge_driver = {
+ .name = "sbridge_edac",
+ .probe = sbridge_probe,
+ .remove = __devexit_p(sbridge_remove),
+ .id_table = sbridge_pci_tbl,
+};
+
+/*
+ * sbridge_init Module entry function
+ * Try to initialize this module for its devices
+ */
+static int __init sbridge_init(void)
+{
+ int pci_rc;
+
+ debugf2("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+ opstate_init();
+
+ pci_rc = pci_register_driver(&sbridge_driver);
+
+ if (pci_rc >= 0)
+ return 0;
+
+ sbridge_printk(KERN_ERR, "Failed to register device with error %d.\n",
+ pci_rc);
+
+ return pci_rc;
+}
+
+/*
+ * sbridge_exit() Module exit function
+ * Unregister the driver
+ */
+static void __exit sbridge_exit(void)
+{
+ debugf2("MC: " __FILE__ ": %s()\n", __func__);
+ pci_unregister_driver(&sbridge_driver);
+}
+
+module_init(sbridge_init);
+module_exit(sbridge_exit);
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge memory controllers - "
+ SBRIDGE_REVISION);
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 334b82a3542c..855ab3f5936f 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -1046,8 +1046,8 @@ static void update_split_timeout(struct fw_card *card)
cycles = card->split_timeout_hi * 8000 + (card->split_timeout_lo >> 19);
- cycles = max(cycles, 800u); /* minimum as per the spec */
- cycles = min(cycles, 3u * 8000u); /* maximum OHCI timeout */
+ /* minimum per IEEE 1394, maximum which doesn't overflow OHCI */
+ cycles = clamp(cycles, 800u, 3u * 8000u);
card->split_timeout_cycles = cycles;
card->split_timeout_jiffies = DIV_ROUND_UP(cycles * HZ, 8000);
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 03a7a85d0424..a20f45b1e7e5 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -502,11 +502,7 @@ static struct fwnet_peer *fwnet_peer_find_by_node_id(struct fwnet_device *dev,
static unsigned fwnet_max_payload(unsigned max_rec, unsigned speed)
{
max_rec = min(max_rec, speed + 8);
- max_rec = min(max_rec, 0xbU); /* <= 4096 */
- if (max_rec < 8) {
- fw_notify("max_rec %x out of range\n", max_rec);
- max_rec = 8;
- }
+ max_rec = clamp(max_rec, 8U, 11U); /* 512...4096 */
return (1 << (max_rec + 1)) - RFC2374_FRAG_HDR_SIZE;
}
@@ -1125,17 +1121,12 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
unsigned u;
if (dev->local_fifo == FWNET_NO_FIFO_ADDR) {
- /* outside OHCI posted write area? */
- static const struct fw_address_region region = {
- .start = 0xffff00000000ULL,
- .end = CSR_REGISTER_BASE,
- };
-
dev->handler.length = 4096;
dev->handler.address_callback = fwnet_receive_packet;
dev->handler.callback_data = dev;
- retval = fw_core_add_address_handler(&dev->handler, &region);
+ retval = fw_core_add_address_handler(&dev->handler,
+ &fw_high_memory_region);
if (retval < 0)
goto failed_initial;
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index fd7170a9ad2c..6628feaa7622 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -42,6 +42,7 @@
#include <linux/string.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
#include <asm/byteorder.h>
#include <asm/page.h>
@@ -125,6 +126,7 @@ struct context {
struct fw_ohci *ohci;
u32 regs;
int total_allocation;
+ u32 current_bus;
bool running;
bool flushing;
@@ -226,7 +228,7 @@ struct fw_ohci {
__le32 *self_id_cpu;
dma_addr_t self_id_bus;
- struct tasklet_struct bus_reset_tasklet;
+ struct work_struct bus_reset_work;
u32 self_id_buffer[512];
};
@@ -263,6 +265,8 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
#define PCI_DEVICE_ID_AGERE_FW643 0x5901
#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380
#define PCI_DEVICE_ID_TI_TSB12LV22 0x8009
+#define PCI_DEVICE_ID_TI_TSB12LV26 0x8020
+#define PCI_DEVICE_ID_TI_TSB82AA2 0x8025
#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd
#define QUIRK_CYCLE_TIMER 1
@@ -270,6 +274,7 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
#define QUIRK_BE_HEADERS 4
#define QUIRK_NO_1394A 8
#define QUIRK_NO_MSI 16
+#define QUIRK_TI_SLLZ059 32
/* In case of multiple matches in ohci_quirks[], only the first one is used. */
static const struct {
@@ -299,6 +304,12 @@ static const struct {
{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
+ {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV26, PCI_ANY_ID,
+ QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
+ {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB82AA2, PCI_ANY_ID,
+ QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
{PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
QUIRK_RESET_PACKET},
@@ -315,6 +326,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS)
", no 1394a enhancements = " __stringify(QUIRK_NO_1394A)
", disable MSI = " __stringify(QUIRK_NO_MSI)
+ ", TI SLLZ059 erratum = " __stringify(QUIRK_TI_SLLZ059)
")");
#define OHCI_PARAM_DEBUG_AT_AR 1
@@ -859,7 +871,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
*
* Alas some chips sometimes emit bus reset packets with a
* wrong generation. We set the correct generation for these
- * at a slightly incorrect time (in bus_reset_tasklet).
+ * at a slightly incorrect time (in bus_reset_work).
*/
if (evt == OHCI1394_evt_bus_reset) {
if (!(ohci->quirks & QUIRK_RESET_PACKET))
@@ -1046,6 +1058,7 @@ static void context_tasklet(unsigned long data)
address = le32_to_cpu(last->branch_address);
z = address & 0xf;
address &= ~0xf;
+ ctx->current_bus = address;
/* If the branch address points to a buffer outside of the
* current buffer, advance to the next buffer. */
@@ -1713,9 +1726,94 @@ static u32 update_bus_time(struct fw_ohci *ohci)
return ohci->bus_time | cycle_time_seconds;
}
-static void bus_reset_tasklet(unsigned long data)
+static int get_status_for_port(struct fw_ohci *ohci, int port_index)
+{
+ int reg;
+
+ mutex_lock(&ohci->phy_reg_mutex);
+ reg = write_phy_reg(ohci, 7, port_index);
+ if (reg >= 0)
+ reg = read_phy_reg(ohci, 8);
+ mutex_unlock(&ohci->phy_reg_mutex);
+ if (reg < 0)
+ return reg;
+
+ switch (reg & 0x0f) {
+ case 0x06:
+ return 2; /* is child node (connected to parent node) */
+ case 0x0e:
+ return 3; /* is parent node (connected to child node) */
+ }
+ return 1; /* not connected */
+}
+
+static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id,
+ int self_id_count)
+{
+ int i;
+ u32 entry;
+
+ for (i = 0; i < self_id_count; i++) {
+ entry = ohci->self_id_buffer[i];
+ if ((self_id & 0xff000000) == (entry & 0xff000000))
+ return -1;
+ if ((self_id & 0xff000000) < (entry & 0xff000000))
+ return i;
+ }
+ return i;
+}
+
+/*
+ * TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally
+ * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059.
+ * Construct the selfID from phy register contents.
+ * FIXME: How to determine the selfID.i flag?
+ */
+static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
+{
+ int reg, i, pos, status;
+ /* link active 1, speed 3, bridge 0, contender 1, more packets 0 */
+ u32 self_id = 0x8040c800;
+
+ reg = reg_read(ohci, OHCI1394_NodeID);
+ if (!(reg & OHCI1394_NodeID_idValid)) {
+ fw_notify("node ID not valid, new bus reset in progress\n");
+ return -EBUSY;
+ }
+ self_id |= ((reg & 0x3f) << 24); /* phy ID */
+
+ reg = ohci_read_phy_reg(&ohci->card, 4);
+ if (reg < 0)
+ return reg;
+ self_id |= ((reg & 0x07) << 8); /* power class */
+
+ reg = ohci_read_phy_reg(&ohci->card, 1);
+ if (reg < 0)
+ return reg;
+ self_id |= ((reg & 0x3f) << 16); /* gap count */
+
+ for (i = 0; i < 3; i++) {
+ status = get_status_for_port(ohci, i);
+ if (status < 0)
+ return status;
+ self_id |= ((status & 0x3) << (6 - (i * 2)));
+ }
+
+ pos = get_self_id_pos(ohci, self_id, self_id_count);
+ if (pos >= 0) {
+ memmove(&(ohci->self_id_buffer[pos+1]),
+ &(ohci->self_id_buffer[pos]),
+ (self_id_count - pos) * sizeof(*ohci->self_id_buffer));
+ ohci->self_id_buffer[pos] = self_id;
+ self_id_count++;
+ }
+ return self_id_count;
+}
+
+static void bus_reset_work(struct work_struct *work)
{
- struct fw_ohci *ohci = (struct fw_ohci *)data;
+ struct fw_ohci *ohci =
+ container_of(work, struct fw_ohci, bus_reset_work);
int self_id_count, i, j, reg;
int generation, new_generation;
unsigned long flags;
@@ -1753,21 +1851,50 @@ static void bus_reset_tasklet(unsigned long data)
* bit extra to get the actual number of self IDs.
*/
self_id_count = (reg >> 3) & 0xff;
- if (self_id_count == 0 || self_id_count > 252) {
+
+ if (self_id_count > 252) {
fw_notify("inconsistent self IDs\n");
return;
}
+
generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
rmb();
for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) {
- fw_notify("inconsistent self IDs\n");
- return;
+ /*
+ * If the invalid data looks like a cycle start packet,
+ * it's likely to be the result of the cycle master
+ * having a wrong gap count. In this case, the self IDs
+ * so far are valid and should be processed so that the
+ * bus manager can then correct the gap count.
+ */
+ if (cond_le32_to_cpu(ohci->self_id_cpu[i])
+ == 0xffff008f) {
+ fw_notify("ignoring spurious self IDs\n");
+ self_id_count = j;
+ break;
+ } else {
+ fw_notify("inconsistent self IDs\n");
+ return;
+ }
}
ohci->self_id_buffer[j] =
cond_le32_to_cpu(ohci->self_id_cpu[i]);
}
+
+ if (ohci->quirks & QUIRK_TI_SLLZ059) {
+ self_id_count = find_and_insert_self_id(ohci, self_id_count);
+ if (self_id_count < 0) {
+ fw_notify("could not construct local self ID\n");
+ return;
+ }
+ }
+
+ if (self_id_count == 0) {
+ fw_notify("inconsistent self IDs\n");
+ return;
+ }
rmb();
/*
@@ -1887,7 +2014,7 @@ static irqreturn_t irq_handler(int irq, void *data)
log_irqs(event);
if (event & OHCI1394_selfIDComplete)
- tasklet_schedule(&ohci->bus_reset_tasklet);
+ queue_work(fw_workqueue, &ohci->bus_reset_work);
if (event & OHCI1394_RQPkt)
tasklet_schedule(&ohci->ar_request_ctx.tasklet);
@@ -1934,7 +2061,8 @@ static irqreturn_t irq_handler(int irq, void *data)
reg_read(ohci, OHCI1394_PostedWriteAddressLo);
reg_write(ohci, OHCI1394_IntEventClear,
OHCI1394_postedWriteErr);
- fw_error("PCI posted write error\n");
+ if (printk_ratelimit())
+ fw_error("PCI posted write error\n");
}
if (unlikely(event & OHCI1394_cycleTooLong)) {
@@ -2048,6 +2176,28 @@ static int configure_1394a_enhancements(struct fw_ohci *ohci)
return 0;
}
+static int probe_tsb41ba3d(struct fw_ohci *ohci)
+{
+ /* TI vendor ID = 0x080028, TSB41BA3D product ID = 0x833005 (sic) */
+ static const u8 id[] = { 0x08, 0x00, 0x28, 0x83, 0x30, 0x05, };
+ int reg, i;
+
+ reg = read_phy_reg(ohci, 2);
+ if (reg < 0)
+ return reg;
+ if ((reg & PHY_EXTENDED_REGISTERS) != PHY_EXTENDED_REGISTERS)
+ return 0;
+
+ for (i = ARRAY_SIZE(id) - 1; i >= 0; i--) {
+ reg = read_paged_phy_reg(ohci, 1, i + 10);
+ if (reg < 0)
+ return reg;
+ if (reg != id[i])
+ return 0;
+ }
+ return 1;
+}
+
static int ohci_enable(struct fw_card *card,
const __be32 *config_rom, size_t length)
{
@@ -2085,6 +2235,16 @@ static int ohci_enable(struct fw_card *card,
return -EIO;
}
+ if (ohci->quirks & QUIRK_TI_SLLZ059) {
+ ret = probe_tsb41ba3d(ohci);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ fw_notify("local TSB41BA3D phy\n");
+ else
+ ohci->quirks &= ~QUIRK_TI_SLLZ059;
+ }
+
reg_write(ohci, OHCI1394_HCControlClear,
OHCI1394_HCControl_noByteSwapData);
@@ -2260,7 +2420,7 @@ static int ohci_set_config_rom(struct fw_card *card,
* then set up the real values for the two registers.
*
* We use ohci->lock to avoid racing with the code that sets
- * ohci->next_config_rom to NULL (see bus_reset_tasklet).
+ * ohci->next_config_rom to NULL (see bus_reset_work).
*/
next_config_rom =
@@ -2539,6 +2699,7 @@ static int handle_ir_packet_per_buffer(struct context *context,
struct iso_context *ctx =
container_of(context, struct iso_context, context);
struct descriptor *pd;
+ u32 buffer_dma;
__le32 *ir_header;
void *p;
@@ -2549,6 +2710,16 @@ static int handle_ir_packet_per_buffer(struct context *context,
/* Descriptor(s) not done yet, stop iteration */
return 0;
+ while (!(d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))) {
+ d++;
+ buffer_dma = le32_to_cpu(d->data_address);
+ dma_sync_single_range_for_cpu(context->ohci->card.device,
+ buffer_dma & PAGE_MASK,
+ buffer_dma & ~PAGE_MASK,
+ le16_to_cpu(d->req_count),
+ DMA_FROM_DEVICE);
+ }
+
p = last + 1;
copy_iso_headers(ctx, p);
@@ -2571,11 +2742,19 @@ static int handle_ir_buffer_fill(struct context *context,
{
struct iso_context *ctx =
container_of(context, struct iso_context, context);
+ u32 buffer_dma;
if (!last->transfer_status)
/* Descriptor(s) not done yet, stop iteration */
return 0;
+ buffer_dma = le32_to_cpu(last->data_address);
+ dma_sync_single_range_for_cpu(context->ohci->card.device,
+ buffer_dma & PAGE_MASK,
+ buffer_dma & ~PAGE_MASK,
+ le16_to_cpu(last->req_count),
+ DMA_FROM_DEVICE);
+
if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
ctx->base.callback.mc(&ctx->base,
le32_to_cpu(last->data_address) +
@@ -2586,6 +2765,43 @@ static int handle_ir_buffer_fill(struct context *context,
return 1;
}
+static inline void sync_it_packet_for_cpu(struct context *context,
+ struct descriptor *pd)
+{
+ __le16 control;
+ u32 buffer_dma;
+
+ /* only packets beginning with OUTPUT_MORE* have data buffers */
+ if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+ return;
+
+ /* skip over the OUTPUT_MORE_IMMEDIATE descriptor */
+ pd += 2;
+
+ /*
+ * If the packet has a header, the first OUTPUT_MORE/LAST descriptor's
+ * data buffer is in the context program's coherent page and must not
+ * be synced.
+ */
+ if ((le32_to_cpu(pd->data_address) & PAGE_MASK) ==
+ (context->current_bus & PAGE_MASK)) {
+ if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+ return;
+ pd++;
+ }
+
+ do {
+ buffer_dma = le32_to_cpu(pd->data_address);
+ dma_sync_single_range_for_cpu(context->ohci->card.device,
+ buffer_dma & PAGE_MASK,
+ buffer_dma & ~PAGE_MASK,
+ le16_to_cpu(pd->req_count),
+ DMA_TO_DEVICE);
+ control = pd->control;
+ pd++;
+ } while (!(control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)));
+}
+
static int handle_it_packet(struct context *context,
struct descriptor *d,
struct descriptor *last)
@@ -2602,6 +2818,8 @@ static int handle_it_packet(struct context *context,
/* Descriptor(s) not done yet, stop iteration */
return 0;
+ sync_it_packet_for_cpu(context, d);
+
i = ctx->header_length;
if (i + 4 < PAGE_SIZE) {
/* Present this value as big-endian to match the receive code */
@@ -2971,6 +3189,10 @@ static int queue_iso_transmit(struct iso_context *ctx,
page_bus = page_private(buffer->pages[page]);
pd[i].data_address = cpu_to_le32(page_bus + offset);
+ dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+ page_bus, offset, length,
+ DMA_TO_DEVICE);
+
payload_index += length;
}
@@ -2995,6 +3217,7 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx,
struct fw_iso_buffer *buffer,
unsigned long payload)
{
+ struct device *device = ctx->context.ohci->card.device;
struct descriptor *d, *pd;
dma_addr_t d_bus, page_bus;
u32 z, header_z, rest;
@@ -3049,6 +3272,10 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx,
page_bus = page_private(buffer->pages[page]);
pd->data_address = cpu_to_le32(page_bus + offset);
+ dma_sync_single_range_for_device(device, page_bus,
+ offset, length,
+ DMA_FROM_DEVICE);
+
offset = (offset + length) & ~PAGE_MASK;
rest -= length;
if (offset == 0)
@@ -3108,6 +3335,10 @@ static int queue_iso_buffer_fill(struct iso_context *ctx,
page_bus = page_private(buffer->pages[page]);
d->data_address = cpu_to_le32(page_bus + offset);
+ dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+ page_bus, offset, length,
+ DMA_FROM_DEVICE);
+
rest -= length;
offset = 0;
page++;
@@ -3239,8 +3470,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
spin_lock_init(&ohci->lock);
mutex_init(&ohci->phy_reg_mutex);
- tasklet_init(&ohci->bus_reset_tasklet,
- bus_reset_tasklet, (unsigned long)ohci);
+ INIT_WORK(&ohci->bus_reset_work, bus_reset_work);
err = pci_request_region(dev, 0, ohci_driver_name);
if (err) {
@@ -3382,6 +3612,7 @@ static void pci_remove(struct pci_dev *dev)
ohci = pci_get_drvdata(dev);
reg_write(ohci, OHCI1394_IntMaskClear, ~0);
flush_writes(ohci);
+ cancel_work_sync(&ohci->bus_reset_work);
fw_core_remove_card(&ohci->card);
/*
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index 17cef864506a..68375bc3aef6 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -154,12 +154,16 @@ struct sbp2_logical_unit {
bool blocked;
};
+static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
+{
+ queue_delayed_work(fw_workqueue, &lu->work, delay);
+}
+
/*
* We create one struct sbp2_target per IEEE 1212 Unit Directory
* and one struct Scsi_Host per sbp2_target.
*/
struct sbp2_target {
- struct kref kref;
struct fw_unit *unit;
const char *bus_id;
struct list_head lu_list;
@@ -772,71 +776,6 @@ static int sbp2_lun2int(u16 lun)
return scsilun_to_int(&eight_bytes_lun);
}
-static void sbp2_release_target(struct kref *kref)
-{
- struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref);
- struct sbp2_logical_unit *lu, *next;
- struct Scsi_Host *shost =
- container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
- struct scsi_device *sdev;
- struct fw_device *device = target_device(tgt);
-
- /* prevent deadlocks */
- sbp2_unblock(tgt);
-
- list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
- sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
- if (sdev) {
- scsi_remove_device(sdev);
- scsi_device_put(sdev);
- }
- if (lu->login_id != INVALID_LOGIN_ID) {
- int generation, node_id;
- /*
- * tgt->node_id may be obsolete here if we failed
- * during initial login or after a bus reset where
- * the topology changed.
- */
- generation = device->generation;
- smp_rmb(); /* node_id vs. generation */
- node_id = device->node_id;
- sbp2_send_management_orb(lu, node_id, generation,
- SBP2_LOGOUT_REQUEST,
- lu->login_id, NULL);
- }
- fw_core_remove_address_handler(&lu->address_handler);
- list_del(&lu->link);
- kfree(lu);
- }
- scsi_remove_host(shost);
- fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
-
- fw_unit_put(tgt->unit);
- scsi_host_put(shost);
- fw_device_put(device);
-}
-
-static void sbp2_target_get(struct sbp2_target *tgt)
-{
- kref_get(&tgt->kref);
-}
-
-static void sbp2_target_put(struct sbp2_target *tgt)
-{
- kref_put(&tgt->kref, sbp2_release_target);
-}
-
-/*
- * Always get the target's kref when scheduling work on one its units.
- * Each workqueue job is responsible to call sbp2_target_put() upon return.
- */
-static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
-{
- sbp2_target_get(lu->tgt);
- if (!queue_delayed_work(fw_workqueue, &lu->work, delay))
- sbp2_target_put(lu->tgt);
-}
-
/*
* Write retransmit retry values into the BUSY_TIMEOUT register.
* - The single-phase retry protocol is supported by all SBP-2 devices, but the
@@ -877,7 +816,7 @@ static void sbp2_login(struct work_struct *work)
int generation, node_id, local_node_id;
if (fw_device_is_shutdown(device))
- goto out;
+ return;
generation = device->generation;
smp_rmb(); /* node IDs must not be older than generation */
@@ -899,7 +838,7 @@ static void sbp2_login(struct work_struct *work)
/* Let any waiting I/O fail from now on. */
sbp2_unblock(lu->tgt);
}
- goto out;
+ return;
}
tgt->node_id = node_id;
@@ -925,7 +864,8 @@ static void sbp2_login(struct work_struct *work)
if (lu->has_sdev) {
sbp2_cancel_orbs(lu);
sbp2_conditionally_unblock(lu);
- goto out;
+
+ return;
}
if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
@@ -957,7 +897,8 @@ static void sbp2_login(struct work_struct *work)
lu->has_sdev = true;
scsi_device_put(sdev);
sbp2_allow_block(lu);
- goto out;
+
+ return;
out_logout_login:
smp_rmb(); /* generation may have changed */
@@ -971,8 +912,57 @@ static void sbp2_login(struct work_struct *work)
* lu->work already. Reset the work from reconnect to login.
*/
PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
- out:
- sbp2_target_put(tgt);
+}
+
+static void sbp2_reconnect(struct work_struct *work)
+{
+ struct sbp2_logical_unit *lu =
+ container_of(work, struct sbp2_logical_unit, work.work);
+ struct sbp2_target *tgt = lu->tgt;
+ struct fw_device *device = target_device(tgt);
+ int generation, node_id, local_node_id;
+
+ if (fw_device_is_shutdown(device))
+ return;
+
+ generation = device->generation;
+ smp_rmb(); /* node IDs must not be older than generation */
+ node_id = device->node_id;
+ local_node_id = device->card->node_id;
+
+ if (sbp2_send_management_orb(lu, node_id, generation,
+ SBP2_RECONNECT_REQUEST,
+ lu->login_id, NULL) < 0) {
+ /*
+ * If reconnect was impossible even though we are in the
+ * current generation, fall back and try to log in again.
+ *
+ * We could check for "Function rejected" status, but
+ * looking at the bus generation as simpler and more general.
+ */
+ smp_rmb(); /* get current card generation */
+ if (generation == device->card->generation ||
+ lu->retries++ >= 5) {
+ fw_error("%s: failed to reconnect\n", tgt->bus_id);
+ lu->retries = 0;
+ PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+ }
+ sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+
+ return;
+ }
+
+ tgt->node_id = node_id;
+ tgt->address_high = local_node_id << 16;
+ smp_wmb(); /* node IDs must not be older than generation */
+ lu->generation = generation;
+
+ fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
+ tgt->bus_id, lu->lun, lu->retries);
+
+ sbp2_agent_reset(lu);
+ sbp2_cancel_orbs(lu);
+ sbp2_conditionally_unblock(lu);
}
static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
@@ -1120,6 +1110,7 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
}
static struct scsi_host_template scsi_driver_template;
+static int sbp2_remove(struct device *dev);
static int sbp2_probe(struct device *dev)
{
@@ -1141,7 +1132,6 @@ static int sbp2_probe(struct device *dev)
tgt = (struct sbp2_target *)shost->hostdata;
dev_set_drvdata(&unit->device, tgt);
tgt->unit = unit;
- kref_init(&tgt->kref);
INIT_LIST_HEAD(&tgt->lu_list);
tgt->bus_id = dev_name(&unit->device);
tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
@@ -1154,9 +1144,6 @@ static int sbp2_probe(struct device *dev)
if (scsi_add_host(shost, &unit->device) < 0)
goto fail_shost_put;
- fw_device_get(device);
- fw_unit_get(unit);
-
/* implicit directory ID */
tgt->directory_id = ((unit->directory - device->config_rom) * 4
+ CSR_CONFIG_ROM) & 0xffffff;
@@ -1166,7 +1153,7 @@ static int sbp2_probe(struct device *dev)
if (sbp2_scan_unit_dir(tgt, unit->directory, &model,
&firmware_revision) < 0)
- goto fail_tgt_put;
+ goto fail_remove;
sbp2_clamp_management_orb_timeout(tgt);
sbp2_init_workarounds(tgt, model, firmware_revision);
@@ -1177,16 +1164,17 @@ static int sbp2_probe(struct device *dev)
* specifies the max payload size as 2 ^ (max_payload + 2), so
* if we set this to max_speed + 7, we get the right value.
*/
- tgt->max_payload = min(device->max_speed + 7, 10U);
- tgt->max_payload = min(tgt->max_payload, device->card->max_receive - 1);
+ tgt->max_payload = min3(device->max_speed + 7, 10U,
+ device->card->max_receive - 1);
/* Do the login in a workqueue so we can easily reschedule retries. */
list_for_each_entry(lu, &tgt->lu_list, link)
sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+
return 0;
- fail_tgt_put:
- sbp2_target_put(tgt);
+ fail_remove:
+ sbp2_remove(dev);
return -ENOMEM;
fail_shost_put:
@@ -1194,71 +1182,6 @@ static int sbp2_probe(struct device *dev)
return -ENOMEM;
}
-static int sbp2_remove(struct device *dev)
-{
- struct fw_unit *unit = fw_unit(dev);
- struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
- struct sbp2_logical_unit *lu;
-
- list_for_each_entry(lu, &tgt->lu_list, link)
- cancel_delayed_work_sync(&lu->work);
-
- sbp2_target_put(tgt);
- return 0;
-}
-
-static void sbp2_reconnect(struct work_struct *work)
-{
- struct sbp2_logical_unit *lu =
- container_of(work, struct sbp2_logical_unit, work.work);
- struct sbp2_target *tgt = lu->tgt;
- struct fw_device *device = target_device(tgt);
- int generation, node_id, local_node_id;
-
- if (fw_device_is_shutdown(device))
- goto out;
-
- generation = device->generation;
- smp_rmb(); /* node IDs must not be older than generation */
- node_id = device->node_id;
- local_node_id = device->card->node_id;
-
- if (sbp2_send_management_orb(lu, node_id, generation,
- SBP2_RECONNECT_REQUEST,
- lu->login_id, NULL) < 0) {
- /*
- * If reconnect was impossible even though we are in the
- * current generation, fall back and try to log in again.
- *
- * We could check for "Function rejected" status, but
- * looking at the bus generation as simpler and more general.
- */
- smp_rmb(); /* get current card generation */
- if (generation == device->card->generation ||
- lu->retries++ >= 5) {
- fw_error("%s: failed to reconnect\n", tgt->bus_id);
- lu->retries = 0;
- PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
- }
- sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
- goto out;
- }
-
- tgt->node_id = node_id;
- tgt->address_high = local_node_id << 16;
- smp_wmb(); /* node IDs must not be older than generation */
- lu->generation = generation;
-
- fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
- tgt->bus_id, lu->lun, lu->retries);
-
- sbp2_agent_reset(lu);
- sbp2_cancel_orbs(lu);
- sbp2_conditionally_unblock(lu);
- out:
- sbp2_target_put(tgt);
-}
-
static void sbp2_update(struct fw_unit *unit)
{
struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
@@ -1277,6 +1200,51 @@ static void sbp2_update(struct fw_unit *unit)
}
}
+static int sbp2_remove(struct device *dev)
+{
+ struct fw_unit *unit = fw_unit(dev);
+ struct fw_device *device = fw_parent_device(unit);
+ struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
+ struct sbp2_logical_unit *lu, *next;
+ struct Scsi_Host *shost =
+ container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
+ struct scsi_device *sdev;
+
+ /* prevent deadlocks */
+ sbp2_unblock(tgt);
+
+ list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
+ cancel_delayed_work_sync(&lu->work);
+ sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
+ if (sdev) {
+ scsi_remove_device(sdev);
+ scsi_device_put(sdev);
+ }
+ if (lu->login_id != INVALID_LOGIN_ID) {
+ int generation, node_id;
+ /*
+ * tgt->node_id may be obsolete here if we failed
+ * during initial login or after a bus reset where
+ * the topology changed.
+ */
+ generation = device->generation;
+ smp_rmb(); /* node_id vs. generation */
+ node_id = device->node_id;
+ sbp2_send_management_orb(lu, node_id, generation,
+ SBP2_LOGOUT_REQUEST,
+ lu->login_id, NULL);
+ }
+ fw_core_remove_address_handler(&lu->address_handler);
+ list_del(&lu->link);
+ kfree(lu);
+ }
+ scsi_remove_host(shost);
+ fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
+
+ scsi_host_put(shost);
+ return 0;
+}
+
#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
#define SBP2_SW_VERSION_ENTRY 0x00010483
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index eb80b549ed8d..8370f72d87ff 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -490,8 +490,8 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
return 0;
}
-static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
- size_t size, struct pstore_info *psi)
+static int efi_pstore_write(enum pstore_type_id type, u64 *id,
+ unsigned int part, size_t size, struct pstore_info *psi)
{
char name[DUMP_NAME_LEN];
char stub_name[DUMP_NAME_LEN];
@@ -499,7 +499,7 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
struct efivars *efivars = psi->data;
struct efivar_entry *entry, *found = NULL;
- int i;
+ int i, ret = 0;
sprintf(stub_name, "dump-type%u-%u-", type, part);
sprintf(name, "%s%lu", stub_name, get_seconds());
@@ -548,18 +548,19 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
efivar_unregister(found);
if (size)
- efivar_create_sysfs_entry(efivars,
+ ret = efivar_create_sysfs_entry(efivars,
utf16_strsize(efi_name,
DUMP_NAME_LEN * 2),
efi_name, &vendor);
- return part;
+ *id = part;
+ return ret;
};
static int efi_pstore_erase(enum pstore_type_id type, u64 id,
struct pstore_info *psi)
{
- efi_pstore_write(type, id, 0, psi);
+ efi_pstore_write(type, &id, (unsigned int)id, 0, psi);
return 0;
}
@@ -580,8 +581,8 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
return -1;
}
-static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
- size_t size, struct pstore_info *psi)
+static int efi_pstore_write(enum pstore_type_id type, u64 *id,
+ unsigned int part, size_t size, struct pstore_info *psi)
{
return 0;
}
@@ -978,7 +979,7 @@ int register_efivars(struct efivars *efivars,
if (efivars->efi_pstore_info.buf) {
efivars->efi_pstore_info.bufsize = 1024;
efivars->efi_pstore_info.data = efivars;
- mutex_init(&efivars->efi_pstore_info.buf_mutex);
+ spin_lock_init(&efivars->efi_pstore_info.buf_lock);
pstore_register(&efivars->efi_pstore_info);
}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index fbc5fd449a04..8b3c745b1b05 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -178,6 +178,15 @@ config GPIO_SCH
The Intel Tunnel Creek processor has 5 GPIOs powered by the
core power rail and 9 from suspend power supply.
+config GPIO_U300
+ bool "ST-Ericsson U300 COH 901 335/571 GPIO"
+ depends on GPIOLIB && ARCH_U300
+ help
+ Say yes here to support GPIO interface on ST-Ericsson U300.
+ The names of the two IP block variants supported are
+ COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
+ ports of 8 GPIO pins each.
+
config GPIO_VX855
tristate "VIA VX855/VX875 GPIO"
depends on PCI
@@ -388,6 +397,7 @@ config GPIO_LANGWELL
config GPIO_PCH
tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
depends on PCI && X86
+ select GENERIC_IRQ_CHIP
help
This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
which is an IOH(Input/Output Hub) for x86 embedded processor.
@@ -402,6 +412,7 @@ config GPIO_PCH
config GPIO_ML_IOH
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
depends on PCI
+ select GENERIC_IRQ_CHIP
help
ML7213 is companion chip for Intel Atom E6xx series.
This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9588948c96f0..19c5d27b6d2e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -14,11 +14,14 @@ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
+obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o
obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
+obj-$(CONFIG_MACH_KS8695) += gpio-ks8695.o
obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o
+obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o
@@ -37,18 +40,20 @@ obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
+obj-$(CONFIG_PLAT_PXA) += gpio-pxa.o
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o
obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o
obj-$(CONFIG_GPIO_S5PV210) += gpio-s5pv210.o
-
+obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o
obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o
+obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
diff --git a/arch/arm/mach-davinci/gpio.c b/drivers/gpio/gpio-davinci.c
index cafbe13a82a5..df0d59570a84 100644
--- a/arch/arm/mach-davinci/gpio.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -9,15 +9,13 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
-
+#include <linux/gpio.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <mach/gpio.h>
-
#include <asm/mach/irq.h>
struct davinci_gpio_regs {
@@ -232,9 +230,6 @@ static void gpio_irq_enable(struct irq_data *d)
static int gpio_irq_type(struct irq_data *d, unsigned trigger)
{
- struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
- u32 mask = (u32) irq_data_get_irq_handler_data(d);
-
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
return -EINVAL;
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index 72fb9c665320..7aafbb437339 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -23,6 +23,9 @@
#include <linux/basic_mmio_gpio.h>
#include <mach/hardware.h>
+#include <mach/gpio-ep93xx.h>
+
+#define irq_to_gpio(irq) ((irq) - gpio_to_irq(0))
struct ep93xx_gpio {
void __iomem *mmio_base;
@@ -307,6 +310,21 @@ static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
return 0;
}
+/*
+ * Map GPIO A0..A7 (0..7) to irq 64..71,
+ * B0..B7 (7..15) to irq 72..79, and
+ * F0..F7 (16..24) to irq 80..87.
+ */
+static int ep93xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ int gpio = chip->base + offset;
+
+ if (gpio > EP93XX_GPIO_LINE_MAX_IRQ)
+ return -EINVAL;
+
+ return 64 + gpio;
+}
+
static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
void __iomem *mmio_base, struct ep93xx_gpio_bank *bank)
{
@@ -321,8 +339,10 @@ static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
bgc->gc.label = bank->label;
bgc->gc.base = bank->base;
- if (bank->has_debounce)
+ if (bank->has_debounce) {
bgc->gc.set_debounce = ep93xx_gpio_set_debounce;
+ bgc->gc.to_irq = ep93xx_gpio_to_irq;
+ }
return gpiochip_add(&bgc->gc);
}
diff --git a/arch/arm/mach-ks8695/gpio.c b/drivers/gpio/gpio-ks8695.c
index 31e456508a6f..a3ac66ea364b 100644
--- a/arch/arm/mach-ks8695/gpio.c
+++ b/drivers/gpio/gpio-ks8695.c
@@ -18,7 +18,7 @@
* 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/gpio.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/init.h>
@@ -31,7 +31,7 @@
#include <asm/mach/irq.h>
#include <mach/regs-gpio.h>
-#include <mach/gpio.h>
+#include <mach/gpio-ks8695.h>
/*
* Configure a GPIO line for either GPIO function, or its internal
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
index d2eb57c60e0e..00692e89ef87 100644
--- a/drivers/gpio/gpio-langwell.c
+++ b/drivers/gpio/gpio-langwell.c
@@ -59,6 +59,7 @@ enum GPIO_REG {
GRER, /* rising edge detect */
GFER, /* falling edge detect */
GEDR, /* edge detect result */
+ GAFR, /* alt function */
};
struct lnw_gpio {
@@ -81,6 +82,31 @@ static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
return ptr;
}
+static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
+ enum GPIO_REG reg_type)
+{
+ struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+ unsigned nreg = chip->ngpio / 32;
+ u8 reg = offset / 16;
+ void __iomem *ptr;
+
+ ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
+ return ptr;
+}
+
+static int lnw_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
+ u32 value = readl(gafr);
+ int shift = (offset % 16) << 1, af = (value >> shift) & 3;
+
+ if (af) {
+ value &= ~(3 << shift);
+ writel(value, gafr);
+ }
+ return 0;
+}
+
static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
{
void __iomem *gplr = gpio_reg(chip, offset, GPLR);
@@ -321,6 +347,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
lnw->reg_base = base;
lnw->irq_base = irq_base;
lnw->chip.label = dev_name(&pdev->dev);
+ lnw->chip.request = lnw_gpio_request;
lnw->chip.direction_input = lnw_gpio_direction_input;
lnw->chip.direction_output = lnw_gpio_direction_output;
lnw->chip.get = lnw_gpio_get;
diff --git a/arch/arm/mach-lpc32xx/gpiolib.c b/drivers/gpio/gpio-lpc32xx.c
index 69061ea8997a..5b6948081f8f 100644
--- a/arch/arm/mach-lpc32xx/gpiolib.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -24,7 +24,7 @@
#include <mach/hardware.h>
#include <mach/platform.h>
-#include "common.h"
+#include <mach/gpio-lpc32xx.h>
#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000)
#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004)
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index a9016f56ed7e..3aa6beec8c1e 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -18,6 +18,17 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#define IOH_EDGE_FALLING 0
+#define IOH_EDGE_RISING BIT(0)
+#define IOH_LEVEL_L BIT(1)
+#define IOH_LEVEL_H (BIT(0) | BIT(1))
+#define IOH_EDGE_BOTH BIT(2)
+#define IOH_IM_MASK (BIT(0) | BIT(1) | BIT(2))
+
+#define IOH_IRQ_BASE 0
#define PCI_VENDOR_ID_ROHM 0x10DB
@@ -46,12 +57,22 @@ struct ioh_regs {
/**
* struct ioh_gpio_reg_data - The register store data.
+ * @ien_reg To store contents of interrupt enable register.
+ * @imask_reg: To store contents of interrupt mask regist
* @po_reg: To store contents of PO register.
* @pm_reg: To store contents of PM register.
+ * @im0_reg: To store contents of interrupt mode regist0
+ * @im1_reg: To store contents of interrupt mode regist1
+ * @use_sel_reg: To store contents of GPIO_USE_SEL0~3
*/
struct ioh_gpio_reg_data {
+ u32 ien_reg;
+ u32 imask_reg;
u32 po_reg;
u32 pm_reg;
+ u32 im0_reg;
+ u32 im1_reg;
+ u32 use_sel_reg;
};
/**
@@ -62,7 +83,11 @@ struct ioh_gpio_reg_data {
* @gpio: Data for GPIO infrastructure.
* @ioh_gpio_reg: Memory mapped Register data is saved here
* when suspend.
+ * @gpio_use_sel: Save GPIO_USE_SEL1~4 register for PM
* @ch: Indicate GPIO channel
+ * @irq_base: Save base of IRQ number for interrupt
+ * @spinlock: Used for register access protection in
+ * interrupt context ioh_irq_type and PM;
*/
struct ioh_gpio {
void __iomem *base;
@@ -70,8 +95,11 @@ struct ioh_gpio {
struct device *dev;
struct gpio_chip gpio;
struct ioh_gpio_reg_data ioh_gpio_reg;
+ u32 gpio_use_sel;
struct mutex lock;
int ch;
+ int irq_base;
+ spinlock_t spinlock;
};
static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
@@ -145,8 +173,25 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
*/
static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
{
- chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po);
- chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
+ int i;
+
+ for (i = 0; i < 8; i ++, chip++) {
+ chip->ioh_gpio_reg.po_reg =
+ ioread32(&chip->reg->regs[chip->ch].po);
+ chip->ioh_gpio_reg.pm_reg =
+ ioread32(&chip->reg->regs[chip->ch].pm);
+ chip->ioh_gpio_reg.ien_reg =
+ ioread32(&chip->reg->regs[chip->ch].ien);
+ chip->ioh_gpio_reg.imask_reg =
+ ioread32(&chip->reg->regs[chip->ch].imask);
+ chip->ioh_gpio_reg.im0_reg =
+ ioread32(&chip->reg->regs[chip->ch].im_0);
+ chip->ioh_gpio_reg.im1_reg =
+ ioread32(&chip->reg->regs[chip->ch].im_1);
+ if (i < 4)
+ chip->ioh_gpio_reg.use_sel_reg =
+ ioread32(&chip->reg->ioh_sel_reg[i]);
+ }
}
/*
@@ -154,13 +199,34 @@ static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
*/
static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
{
- /* to store contents of PO register */
- iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
- /* to store contents of PM register */
- iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm);
+ int i;
+
+ for (i = 0; i < 8; i ++, chip++) {
+ iowrite32(chip->ioh_gpio_reg.po_reg,
+ &chip->reg->regs[chip->ch].po);
+ iowrite32(chip->ioh_gpio_reg.pm_reg,
+ &chip->reg->regs[chip->ch].pm);
+ iowrite32(chip->ioh_gpio_reg.ien_reg,
+ &chip->reg->regs[chip->ch].ien);
+ iowrite32(chip->ioh_gpio_reg.imask_reg,
+ &chip->reg->regs[chip->ch].imask);
+ iowrite32(chip->ioh_gpio_reg.im0_reg,
+ &chip->reg->regs[chip->ch].im_0);
+ iowrite32(chip->ioh_gpio_reg.im1_reg,
+ &chip->reg->regs[chip->ch].im_1);
+ if (i < 4)
+ iowrite32(chip->ioh_gpio_reg.use_sel_reg,
+ &chip->reg->ioh_sel_reg[i]);
+ }
}
#endif
+static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+ struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
+ return chip->irq_base + offset;
+}
+
static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
{
struct gpio_chip *gpio = &chip->gpio;
@@ -175,16 +241,148 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
gpio->base = -1;
gpio->ngpio = num_port;
gpio->can_sleep = 0;
+ gpio->to_irq = ioh_gpio_to_irq;
+}
+
+static int ioh_irq_type(struct irq_data *d, unsigned int type)
+{
+ u32 im;
+ u32 *im_reg;
+ u32 ien;
+ u32 im_pos;
+ int ch;
+ unsigned long flags;
+ u32 val;
+ int irq = d->irq;
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct ioh_gpio *chip = gc->private;
+
+ ch = irq - chip->irq_base;
+ if (irq <= chip->irq_base + 7) {
+ im_reg = &chip->reg->regs[chip->ch].im_0;
+ im_pos = ch;
+ } else {
+ im_reg = &chip->reg->regs[chip->ch].im_1;
+ im_pos = ch - 8;
+ }
+ dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n",
+ __func__, irq, type, ch, im_pos, type);
+
+ spin_lock_irqsave(&chip->spinlock, flags);
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ val = IOH_EDGE_RISING;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ val = IOH_EDGE_FALLING;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ val = IOH_EDGE_BOTH;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ val = IOH_LEVEL_H;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ val = IOH_LEVEL_L;
+ break;
+ case IRQ_TYPE_PROBE:
+ goto end;
+ default:
+ dev_warn(chip->dev, "%s: unknown type(%dd)",
+ __func__, type);
+ goto end;
+ }
+
+ /* Set interrupt mode */
+ im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4));
+ iowrite32(im | (val << (im_pos * 4)), im_reg);
+
+ /* iclr */
+ iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr);
+
+ /* IMASKCLR */
+ iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr);
+
+ /* Enable interrupt */
+ ien = ioread32(&chip->reg->regs[chip->ch].ien);
+ iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien);
+end:
+ spin_unlock_irqrestore(&chip->spinlock, flags);
+
+ return 0;
+}
+
+static void ioh_irq_unmask(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct ioh_gpio *chip = gc->private;
+
+ iowrite32(1 << (d->irq - chip->irq_base),
+ &chip->reg->regs[chip->ch].imaskclr);
+}
+
+static void ioh_irq_mask(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct ioh_gpio *chip = gc->private;
+
+ iowrite32(1 << (d->irq - chip->irq_base),
+ &chip->reg->regs[chip->ch].imask);
+}
+
+static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
+{
+ struct ioh_gpio *chip = dev_id;
+ u32 reg_val;
+ int i, j;
+ int ret = IRQ_NONE;
+
+ for (i = 0; i < 8; i++) {
+ reg_val = ioread32(&chip->reg->regs[i].istatus);
+ for (j = 0; j < num_ports[i]; j++) {
+ if (reg_val & BIT(j)) {
+ dev_dbg(chip->dev,
+ "%s:[%d]:irq=%d status=0x%x\n",
+ __func__, j, irq, reg_val);
+ iowrite32(BIT(j),
+ &chip->reg->regs[chip->ch].iclr);
+ generic_handle_irq(chip->irq_base + j);
+ ret = IRQ_HANDLED;
+ }
+ }
+ }
+ return ret;
+}
+
+static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
+ unsigned int irq_start, unsigned int num)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base,
+ handle_simple_irq);
+ gc->private = chip;
+ ct = gc->chip_types;
+
+ ct->chip.irq_mask = ioh_irq_mask;
+ ct->chip.irq_unmask = ioh_irq_unmask;
+ ct->chip.irq_set_type = ioh_irq_type;
+
+ irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+ IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}
static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int ret;
- int i;
+ int i, j;
struct ioh_gpio *chip;
void __iomem *base;
void __iomem *chip_save;
+ int irq_base;
ret = pci_enable_device(pdev);
if (ret) {
@@ -228,10 +426,41 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
}
chip = chip_save;
+ for (j = 0; j < 8; j++, chip++) {
+ irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j],
+ NUMA_NO_NODE);
+ if (irq_base < 0) {
+ dev_warn(&pdev->dev,
+ "ml_ioh_gpio: Failed to get IRQ base num\n");
+ chip->irq_base = -1;
+ goto err_irq_alloc_descs;
+ }
+ chip->irq_base = irq_base;
+ ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
+ }
+
+ chip = chip_save;
+ ret = request_irq(pdev->irq, ioh_gpio_handler,
+ IRQF_SHARED, KBUILD_MODNAME, chip);
+ if (ret != 0) {
+ dev_err(&pdev->dev,
+ "%s request_irq failed\n", __func__);
+ goto err_request_irq;
+ }
+
pci_set_drvdata(pdev, chip);
return 0;
+err_request_irq:
+ chip = chip_save;
+err_irq_alloc_descs:
+ while (--j >= 0) {
+ chip--;
+ irq_free_descs(chip->irq_base, num_ports[j]);
+ }
+
+ chip = chip_save;
err_gpiochip_add:
while (--i >= 0) {
chip--;
@@ -264,7 +493,11 @@ static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
void __iomem *chip_save;
chip_save = chip;
+
+ free_irq(pdev->irq, chip);
+
for (i = 0; i < 8; i++, chip++) {
+ irq_free_descs(chip->irq_base, num_ports[i]);
err = gpiochip_remove(&chip->gpio);
if (err)
dev_err(&pdev->dev, "Failed gpiochip_remove\n");
@@ -282,9 +515,11 @@ static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
{
s32 ret;
struct ioh_gpio *chip = pci_get_drvdata(pdev);
+ unsigned long flags;
+ spin_lock_irqsave(&chip->spinlock, flags);
ioh_gpio_save_reg_conf(chip);
- ioh_gpio_restore_reg_conf(chip);
+ spin_unlock_irqrestore(&chip->spinlock, flags);
ret = pci_save_state(pdev);
if (ret) {
@@ -304,6 +539,7 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
{
s32 ret;
struct ioh_gpio *chip = pci_get_drvdata(pdev);
+ unsigned long flags;
ret = pci_enable_wake(pdev, PCI_D0, 0);
@@ -315,9 +551,11 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
}
pci_restore_state(pdev);
+ spin_lock_irqsave(&chip->spinlock, flags);
iowrite32(0x01, &chip->reg->srst);
iowrite32(0x00, &chip->reg->srst);
ioh_gpio_restore_reg_conf(chip);
+ spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 4340acae3bd3..b81c98992114 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -30,6 +30,9 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <asm-generic/bug.h>
+#include <asm/mach/irq.h>
+
+#define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START)
enum mxc_gpio_hwtype {
IMX1_GPIO, /* runs on i.mx1 */
@@ -232,10 +235,15 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
u32 irq_stat;
struct mxc_gpio_port *port = irq_get_handler_data(irq);
+ struct irq_chip *chip = irq_get_chip(irq);
+
+ chained_irq_enter(chip, desc);
irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
mxc_gpio_irq_handler(port, irq_stat);
+
+ chained_irq_exit(chip, desc);
}
/* MX2 has one interrupt *for all* gpio ports */
@@ -337,6 +345,15 @@ static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
mxc_gpio_hwtype = hwtype;
}
+static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+ struct bgpio_chip *bgc = to_bgpio_chip(gc);
+ struct mxc_gpio_port *port =
+ container_of(bgc, struct mxc_gpio_port, bgc);
+
+ return port->virtual_irq_start + offset;
+}
+
static int __devinit mxc_gpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -403,6 +420,7 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev)
if (err)
goto out_iounmap;
+ port->bgc.gc.to_irq = mxc_gpio_to_irq;
port->bgc.gc.base = pdev->id * 32;
port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir);
port->bgc.data = port->bgc.read_reg(port->bgc.reg_set);
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index af55a8577c2e..292b50481db9 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -49,6 +49,8 @@
#define GPIO_INT_LEV_MASK (1 << 0)
#define GPIO_INT_POL_MASK (1 << 1)
+#define irq_to_gpio(irq) ((irq) - MXS_GPIO_IRQ_START)
+
struct mxs_gpio_port {
void __iomem *base;
int id;
diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c
index 2c212c732d76..1ebedfb6d46d 100644
--- a/drivers/gpio/gpio-nomadik.c
+++ b/drivers/gpio/gpio-nomadik.c
@@ -27,8 +27,9 @@
#include <asm/mach/irq.h>
#include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
/*
* The GPIO module in the Nomadik family of Systems-on-Chip is an
@@ -58,7 +59,6 @@ struct nmk_gpio_chip {
u32 rwimsc;
u32 fwimsc;
u32 slpm;
- u32 enabled;
u32 pull_up;
};
@@ -276,6 +276,8 @@ static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
if (!chip)
break;
+ clk_enable(chip->clk);
+
slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
writel(temp, chip->addr + NMK_GPIO_SLPC);
}
@@ -292,6 +294,8 @@ static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
break;
writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
+
+ clk_disable(chip->clk);
}
}
@@ -336,10 +340,12 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
break;
}
+ clk_enable(nmk_chip->clk);
spin_lock(&nmk_chip->lock);
__nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
cfgs[i], sleep, glitch ? slpm : NULL);
spin_unlock(&nmk_chip->lock);
+ clk_disable(nmk_chip->clk);
}
if (glitch)
@@ -424,6 +430,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
if (!nmk_chip)
return -EINVAL;
+ clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock);
@@ -431,6 +438,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
spin_unlock(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+ clk_disable(nmk_chip->clk);
return 0;
}
@@ -457,9 +465,11 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
if (!nmk_chip)
return -EINVAL;
+ clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags);
__nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
+ clk_disable(nmk_chip->clk);
return 0;
}
@@ -483,9 +493,11 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode)
if (!nmk_chip)
return -EINVAL;
+ clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags);
__nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
+ clk_disable(nmk_chip->clk);
return 0;
}
@@ -502,9 +514,13 @@ int nmk_gpio_get_mode(int gpio)
bit = 1 << (gpio - nmk_chip->chip.base);
+ clk_enable(nmk_chip->clk);
+
afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
+ clk_disable(nmk_chip->clk);
+
return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
}
EXPORT_SYMBOL(nmk_gpio_get_mode);
@@ -525,7 +541,10 @@ static void nmk_gpio_irq_ack(struct irq_data *d)
nmk_chip = irq_data_get_irq_chip_data(d);
if (!nmk_chip)
return;
+
+ clk_enable(nmk_chip->clk);
writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
+ clk_disable(nmk_chip->clk);
}
enum nmk_gpio_irq_type {
@@ -586,11 +605,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
if (!nmk_chip)
return -EINVAL;
- if (enable)
- nmk_chip->enabled |= bitmask;
- else
- nmk_chip->enabled &= ~bitmask;
-
+ clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock);
@@ -601,6 +616,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
spin_unlock(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+ clk_disable(nmk_chip->clk);
return 0;
}
@@ -628,10 +644,11 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
return -EINVAL;
bitmask = nmk_gpio_get_bitmask(gpio);
+ clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
spin_lock(&nmk_chip->lock);
- if (!(nmk_chip->enabled & bitmask))
+ if (irqd_irq_disabled(d))
__nmk_gpio_set_wake(nmk_chip, gpio, on);
if (on)
@@ -641,13 +658,15 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
spin_unlock(&nmk_chip->lock);
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+ clk_disable(nmk_chip->clk);
return 0;
}
static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
- bool enabled, wake = irqd_is_wakeup_set(d);
+ bool enabled = !irqd_irq_disabled(d);
+ bool wake = irqd_is_wakeup_set(d);
int gpio;
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
@@ -664,8 +683,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
if (type & IRQ_TYPE_LEVEL_LOW)
return -EINVAL;
- enabled = nmk_chip->enabled & bitmask;
-
+ clk_enable(nmk_chip->clk);
spin_lock_irqsave(&nmk_chip->lock, flags);
if (enabled)
@@ -689,10 +707,28 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
+ clk_disable(nmk_chip->clk);
return 0;
}
+static unsigned int nmk_gpio_irq_startup(struct irq_data *d)
+{
+ struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
+
+ clk_enable(nmk_chip->clk);
+ nmk_gpio_irq_unmask(d);
+ return 0;
+}
+
+static void nmk_gpio_irq_shutdown(struct irq_data *d)
+{
+ struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
+
+ nmk_gpio_irq_mask(d);
+ clk_disable(nmk_chip->clk);
+}
+
static struct irq_chip nmk_gpio_irq_chip = {
.name = "Nomadik-GPIO",
.irq_ack = nmk_gpio_irq_ack,
@@ -700,6 +736,8 @@ static struct irq_chip nmk_gpio_irq_chip = {
.irq_unmask = nmk_gpio_irq_unmask,
.irq_set_type = nmk_gpio_irq_set_type,
.irq_set_wake = nmk_gpio_irq_set_wake,
+ .irq_startup = nmk_gpio_irq_startup,
+ .irq_shutdown = nmk_gpio_irq_shutdown,
};
static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
@@ -726,7 +764,11 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
- u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
+ u32 status;
+
+ clk_enable(nmk_chip->clk);
+ status = readl(nmk_chip->addr + NMK_GPIO_IS);
+ clk_disable(nmk_chip->clk);
__nmk_gpio_irq_handler(irq, desc, status);
}
@@ -772,7 +814,12 @@ static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
+ clk_enable(nmk_chip->clk);
+
writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+
+ clk_disable(nmk_chip->clk);
+
return 0;
}
@@ -781,8 +828,15 @@ static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
u32 bit = 1 << offset;
+ int value;
+
+ clk_enable(nmk_chip->clk);
- return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+ value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+
+ clk_disable(nmk_chip->clk);
+
+ return value;
}
static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
@@ -791,7 +845,11 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
+ clk_enable(nmk_chip->clk);
+
__nmk_gpio_set_output(nmk_chip, offset, val);
+
+ clk_disable(nmk_chip->clk);
}
static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
@@ -800,8 +858,12 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
+ clk_enable(nmk_chip->clk);
+
__nmk_gpio_make_output(nmk_chip, offset, val);
+ clk_disable(nmk_chip->clk);
+
return 0;
}
@@ -832,6 +894,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
[NMK_GPIO_ALT_C] = "altC",
};
+ clk_enable(nmk_chip->clk);
+
for (i = 0; i < chip->ngpio; i++, gpio++) {
const char *label = gpiochip_is_requested(chip, i);
bool pull;
@@ -876,6 +940,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
seq_printf(s, "\n");
}
+
+ clk_disable(nmk_chip->clk);
}
#else
@@ -893,6 +959,34 @@ static struct gpio_chip nmk_gpio_template = {
.can_sleep = 0,
};
+void nmk_gpio_clocks_enable(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_BANKS; i++) {
+ struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+ if (!chip)
+ continue;
+
+ clk_enable(chip->clk);
+ }
+}
+
+void nmk_gpio_clocks_disable(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_BANKS; i++) {
+ struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+ if (!chip)
+ continue;
+
+ clk_disable(chip->clk);
+ }
+}
+
/*
* Called from the suspend/resume path to only keep the real wakeup interrupts
* (those that have had set_irq_wake() called on them) as wakeup interrupts,
@@ -912,6 +1006,8 @@ void nmk_gpio_wakeups_suspend(void)
if (!chip)
break;
+ clk_enable(chip->clk);
+
chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
@@ -926,6 +1022,8 @@ void nmk_gpio_wakeups_suspend(void)
/* 0 -> wakeup enable */
writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
}
+
+ clk_disable(chip->clk);
}
}
@@ -939,11 +1037,15 @@ void nmk_gpio_wakeups_resume(void)
if (!chip)
break;
+ clk_enable(chip->clk);
+
writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
if (chip->sleepmode)
writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
+
+ clk_disable(chip->clk);
}
}
@@ -1010,8 +1112,6 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
goto out_release;
}
- clk_enable(clk);
-
nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
if (!nmk_chip) {
ret = -ENOMEM;
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 118ec12d2d5f..0e49d87f6c60 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -25,7 +25,7 @@
#include <mach/hardware.h>
#include <asm/irq.h>
#include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <asm/mach/irq.h>
struct gpio_bank {
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 36919e77c495..1e8a4a538810 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -17,9 +17,17 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
-#define PCH_GPIO_ALL_PINS 0xfff /* Mask for GPIO pins 0 to 11 */
-#define GPIO_NUM_PINS 12 /* Specifies number of GPIO PINS GPIO0-GPIO11 */
+#define PCH_EDGE_FALLING 0
+#define PCH_EDGE_RISING BIT(0)
+#define PCH_LEVEL_L BIT(1)
+#define PCH_LEVEL_H (BIT(0) | BIT(1))
+#define PCH_EDGE_BOTH BIT(2)
+#define PCH_IM_MASK (BIT(0) | BIT(1) | BIT(2))
+
+#define PCH_IRQ_BASE 24
struct pch_regs {
u32 ien;
@@ -33,18 +41,43 @@ struct pch_regs {
u32 pm;
u32 im0;
u32 im1;
- u32 reserved[4];
+ u32 reserved[3];
+ u32 gpio_use_sel;
u32 reset;
};
+enum pch_type_t {
+ INTEL_EG20T_PCH,
+ OKISEMI_ML7223m_IOH, /* OKISEMI ML7223 IOH PCIe Bus-m */
+ OKISEMI_ML7223n_IOH /* OKISEMI ML7223 IOH PCIe Bus-n */
+};
+
+/* Specifies number of GPIO PINS */
+static int gpio_pins[] = {
+ [INTEL_EG20T_PCH] = 12,
+ [OKISEMI_ML7223m_IOH] = 8,
+ [OKISEMI_ML7223n_IOH] = 8,
+};
+
/**
* struct pch_gpio_reg_data - The register store data.
+ * @ien_reg: To store contents of IEN register.
+ * @imask_reg: To store contents of IMASK register.
* @po_reg: To store contents of PO register.
* @pm_reg: To store contents of PM register.
+ * @im0_reg: To store contents of IM0 register.
+ * @im1_reg: To store contents of IM1 register.
+ * @gpio_use_sel_reg : To store contents of GPIO_USE_SEL register.
+ * (Only ML7223 Bus-n)
*/
struct pch_gpio_reg_data {
+ u32 ien_reg;
+ u32 imask_reg;
u32 po_reg;
u32 pm_reg;
+ u32 im0_reg;
+ u32 im1_reg;
+ u32 gpio_use_sel_reg;
};
/**
@@ -55,6 +88,12 @@ struct pch_gpio_reg_data {
* @gpio: Data for GPIO infrastructure.
* @pch_gpio_reg: Memory mapped Register data is saved here
* when suspend.
+ * @lock: Used for register access protection
+ * @irq_base: Save base of IRQ number for interrupt
+ * @ioh: IOH ID
+ * @spinlock: Used for register access protection in
+ * interrupt context pch_irq_mask,
+ * pch_irq_unmask and pch_irq_type;
*/
struct pch_gpio {
void __iomem *base;
@@ -63,6 +102,9 @@ struct pch_gpio {
struct gpio_chip gpio;
struct pch_gpio_reg_data pch_gpio_reg;
struct mutex lock;
+ int irq_base;
+ enum pch_type_t ioh;
+ spinlock_t spinlock;
};
static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
@@ -96,7 +138,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
u32 reg_val;
mutex_lock(&chip->lock);
- pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
+ pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
pm |= (1 << nr);
iowrite32(pm, &chip->reg->pm);
@@ -118,7 +160,7 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
u32 pm;
mutex_lock(&chip->lock);
- pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
+ pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
pm &= ~(1 << nr);
iowrite32(pm, &chip->reg->pm);
mutex_unlock(&chip->lock);
@@ -131,8 +173,16 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
*/
static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
{
+ chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien);
+ chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask);
chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
+ chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0);
+ if (chip->ioh == INTEL_EG20T_PCH)
+ chip->pch_gpio_reg.im1_reg = ioread32(&chip->reg->im1);
+ if (chip->ioh == OKISEMI_ML7223n_IOH)
+ chip->pch_gpio_reg.gpio_use_sel_reg =\
+ ioread32(&chip->reg->gpio_use_sel);
}
/*
@@ -140,10 +190,24 @@ static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
*/
static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
{
+ iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien);
+ iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask);
/* to store contents of PO register */
iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
/* to store contents of PM register */
iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
+ iowrite32(chip->pch_gpio_reg.im0_reg, &chip->reg->im0);
+ if (chip->ioh == INTEL_EG20T_PCH)
+ iowrite32(chip->pch_gpio_reg.im1_reg, &chip->reg->im1);
+ if (chip->ioh == OKISEMI_ML7223n_IOH)
+ iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg,
+ &chip->reg->gpio_use_sel);
+}
+
+static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+ struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
+ return chip->irq_base + offset;
}
static void pch_gpio_setup(struct pch_gpio *chip)
@@ -158,8 +222,132 @@ static void pch_gpio_setup(struct pch_gpio *chip)
gpio->set = pch_gpio_set;
gpio->dbg_show = NULL;
gpio->base = -1;
- gpio->ngpio = GPIO_NUM_PINS;
+ gpio->ngpio = gpio_pins[chip->ioh];
gpio->can_sleep = 0;
+ gpio->to_irq = pch_gpio_to_irq;
+}
+
+static int pch_irq_type(struct irq_data *d, unsigned int type)
+{
+ u32 im;
+ u32 *im_reg;
+ u32 ien;
+ u32 im_pos;
+ int ch;
+ unsigned long flags;
+ u32 val;
+ int irq = d->irq;
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct pch_gpio *chip = gc->private;
+
+ ch = irq - chip->irq_base;
+ if (irq <= chip->irq_base + 7) {
+ im_reg = &chip->reg->im0;
+ im_pos = ch;
+ } else {
+ im_reg = &chip->reg->im1;
+ im_pos = ch - 8;
+ }
+ dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d\n",
+ __func__, irq, type, ch, im_pos);
+
+ spin_lock_irqsave(&chip->spinlock, flags);
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ val = PCH_EDGE_RISING;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ val = PCH_EDGE_FALLING;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ val = PCH_EDGE_BOTH;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ val = PCH_LEVEL_H;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ val = PCH_LEVEL_L;
+ break;
+ case IRQ_TYPE_PROBE:
+ goto end;
+ default:
+ dev_warn(chip->dev, "%s: unknown type(%dd)",
+ __func__, type);
+ goto end;
+ }
+
+ /* Set interrupt mode */
+ im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
+ iowrite32(im | (val << (im_pos * 4)), im_reg);
+
+ /* iclr */
+ iowrite32(BIT(ch), &chip->reg->iclr);
+
+ /* IMASKCLR */
+ iowrite32(BIT(ch), &chip->reg->imaskclr);
+
+ /* Enable interrupt */
+ ien = ioread32(&chip->reg->ien);
+ iowrite32(ien | BIT(ch), &chip->reg->ien);
+end:
+ spin_unlock_irqrestore(&chip->spinlock, flags);
+
+ return 0;
+}
+
+static void pch_irq_unmask(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct pch_gpio *chip = gc->private;
+
+ iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imaskclr);
+}
+
+static void pch_irq_mask(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct pch_gpio *chip = gc->private;
+
+ iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask);
+}
+
+static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
+{
+ struct pch_gpio *chip = dev_id;
+ u32 reg_val = ioread32(&chip->reg->istatus);
+ int i;
+ int ret = IRQ_NONE;
+
+ for (i = 0; i < gpio_pins[chip->ioh]; i++) {
+ if (reg_val & BIT(i)) {
+ dev_dbg(chip->dev, "%s:[%d]:irq=%d status=0x%x\n",
+ __func__, i, irq, reg_val);
+ iowrite32(BIT(i), &chip->reg->iclr);
+ generic_handle_irq(chip->irq_base + i);
+ ret = IRQ_HANDLED;
+ }
+ }
+ return ret;
+}
+
+static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
+ unsigned int irq_start, unsigned int num)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+
+ gc = irq_alloc_generic_chip("pch_gpio", 1, irq_start, chip->base,
+ handle_simple_irq);
+ gc->private = chip;
+ ct = gc->chip_types;
+
+ ct->chip.irq_mask = pch_irq_mask;
+ ct->chip.irq_unmask = pch_irq_unmask;
+ ct->chip.irq_set_type = pch_irq_type;
+
+ irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+ IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}
static int __devinit pch_gpio_probe(struct pci_dev *pdev,
@@ -167,6 +355,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
{
s32 ret;
struct pch_gpio *chip;
+ int irq_base;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
@@ -192,6 +381,13 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
goto err_iomap;
}
+ if (pdev->device == 0x8803)
+ chip->ioh = INTEL_EG20T_PCH;
+ else if (pdev->device == 0x8014)
+ chip->ioh = OKISEMI_ML7223m_IOH;
+ else if (pdev->device == 0x8043)
+ chip->ioh = OKISEMI_ML7223n_IOH;
+
chip->reg = chip->base;
pci_set_drvdata(pdev, chip);
mutex_init(&chip->lock);
@@ -202,8 +398,36 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
goto err_gpiochip_add;
}
+ irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE);
+ if (irq_base < 0) {
+ dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
+ chip->irq_base = -1;
+ goto end;
+ }
+ chip->irq_base = irq_base;
+
+ ret = request_irq(pdev->irq, pch_gpio_handler,
+ IRQF_SHARED, KBUILD_MODNAME, chip);
+ if (ret != 0) {
+ dev_err(&pdev->dev,
+ "%s request_irq failed\n", __func__);
+ goto err_request_irq;
+ }
+
+ pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]);
+
+ /* Initialize interrupt ien register */
+ iowrite32(0, &chip->reg->ien);
+end:
return 0;
+err_request_irq:
+ irq_free_descs(irq_base, gpio_pins[chip->ioh]);
+
+ ret = gpiochip_remove(&chip->gpio);
+ if (ret)
+ dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
+
err_gpiochip_add:
pci_iounmap(pdev, chip->base);
@@ -224,6 +448,12 @@ static void __devexit pch_gpio_remove(struct pci_dev *pdev)
int err;
struct pch_gpio *chip = pci_get_drvdata(pdev);
+ if (chip->irq_base != -1) {
+ free_irq(pdev->irq, chip);
+
+ irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
+ }
+
err = gpiochip_remove(&chip->gpio);
if (err)
dev_err(&pdev->dev, "Failed gpiochip_remove\n");
@@ -239,9 +469,11 @@ static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
{
s32 ret;
struct pch_gpio *chip = pci_get_drvdata(pdev);
+ unsigned long flags;
+ spin_lock_irqsave(&chip->spinlock, flags);
pch_gpio_save_reg_conf(chip);
- pch_gpio_restore_reg_conf(chip);
+ spin_unlock_irqrestore(&chip->spinlock, flags);
ret = pci_save_state(pdev);
if (ret) {
@@ -261,6 +493,7 @@ static int pch_gpio_resume(struct pci_dev *pdev)
{
s32 ret;
struct pch_gpio *chip = pci_get_drvdata(pdev);
+ unsigned long flags;
ret = pci_enable_wake(pdev, PCI_D0, 0);
@@ -272,9 +505,11 @@ static int pch_gpio_resume(struct pci_dev *pdev)
}
pci_restore_state(pdev);
+ spin_lock_irqsave(&chip->spinlock, flags);
iowrite32(0x01, &chip->reg->reset);
iowrite32(0x00, &chip->reg->reset);
pch_gpio_restore_reg_conf(chip);
+ spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}
@@ -287,6 +522,7 @@ static int pch_gpio_resume(struct pci_dev *pdev)
static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 2c5a18f32bf3..093c90bd3c1d 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -118,7 +118,7 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
- if (chip->irq_base == (unsigned) -1)
+ if (chip->irq_base == NO_IRQ)
return -EINVAL;
return chip->irq_base + offset;
@@ -246,6 +246,18 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
if (chip == NULL)
return -ENOMEM;
+ pdata = dev->dev.platform_data;
+ if (pdata) {
+ chip->gc.base = pdata->gpio_base;
+ chip->irq_base = pdata->irq_base;
+ } else if (dev->dev.of_node) {
+ chip->gc.base = -1;
+ chip->irq_base = NO_IRQ;
+ } else {
+ ret = -ENODEV;
+ goto free_mem;
+ }
+
if (!request_mem_region(dev->res.start,
resource_size(&dev->res), "pl061")) {
ret = -EBUSY;
@@ -267,14 +279,11 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
chip->gc.get = pl061_get_value;
chip->gc.set = pl061_set_value;
chip->gc.to_irq = pl061_to_irq;
- chip->gc.base = pdata->gpio_base;
chip->gc.ngpio = PL061_GPIO_NR;
chip->gc.label = dev_name(&dev->dev);
chip->gc.dev = &dev->dev;
chip->gc.owner = THIS_MODULE;
- chip->irq_base = pdata->irq_base;
-
ret = gpiochip_add(&chip->gc);
if (ret)
goto iounmap;
@@ -283,7 +292,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
* irq_chip support
*/
- if (chip->irq_base == (unsigned) -1)
+ if (chip->irq_base == NO_IRQ)
return 0;
writeb(0, chip->base + GPIOIE); /* disable irqs */
@@ -307,11 +316,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
list_add(&chip->list, chip_list);
for (i = 0; i < PL061_GPIO_NR; i++) {
- if (pdata->directions & (1 << i))
- pl061_direction_output(&chip->gc, i,
- pdata->values & (1 << i));
- else
- pl061_direction_input(&chip->gc, i);
+ if (pdata) {
+ if (pdata->directions & (1 << i))
+ pl061_direction_output(&chip->gc, i,
+ pdata->values & (1 << i));
+ else
+ pl061_direction_input(&chip->gc, i);
+ }
irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
handle_simple_irq);
diff --git a/arch/arm/plat-pxa/gpio.c b/drivers/gpio/gpio-pxa.c
index a11dc3670505..ee137712f9db 100644
--- a/arch/arm/plat-pxa/gpio.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -11,14 +11,14 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/syscore_ops.h>
#include <linux/slab.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
int pxa_last_gpio;
@@ -122,7 +122,7 @@ static int __init pxa_init_gpio_chip(int gpio_end)
struct gpio_chip *c = &chips[i].chip;
sprintf(chips[i].label, "gpio-%d", i);
- chips[i].regbase = (void __iomem *)GPIO_BANK(i);
+ chips[i].regbase = GPIO_BANK(i);
c->base = gpio;
c->label = chips[i].label;
diff --git a/arch/arm/mach-sa1100/gpio.c b/drivers/gpio/gpio-sa1100.c
index 0d3829a8c2c1..b6c1f6d80649 100644
--- a/arch/arm/mach-sa1100/gpio.c
+++ b/drivers/gpio/gpio-sa1100.c
@@ -7,13 +7,11 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <asm/gpio.h>
#include <mach/hardware.h>
-#include "generic.h"
static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
{
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 747eb40e8afe..61044c889f7f 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -20,13 +20,15 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
-
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
#include <asm/mach/irq.h>
+#include <mach/gpio-tegra.h>
#include <mach/iomap.h>
#include <mach/suspend.h>
@@ -34,9 +36,7 @@
#define GPIO_PORT(x) (((x) >> 3) & 0x3)
#define GPIO_BIT(x) ((x) & 0x7)
-#define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \
- GPIO_BANK(x) * 0x80 + \
- GPIO_PORT(x) * 4)
+#define GPIO_REG(x) (GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4)
#define GPIO_CNF(x) (GPIO_REG(x) + 0x00)
#define GPIO_OE(x) (GPIO_REG(x) + 0x10)
@@ -75,15 +75,18 @@ struct tegra_gpio_bank {
};
-static struct tegra_gpio_bank tegra_gpio_banks[] = {
- {.bank = 0, .irq = INT_GPIO1},
- {.bank = 1, .irq = INT_GPIO2},
- {.bank = 2, .irq = INT_GPIO3},
- {.bank = 3, .irq = INT_GPIO4},
- {.bank = 4, .irq = INT_GPIO5},
- {.bank = 5, .irq = INT_GPIO6},
- {.bank = 6, .irq = INT_GPIO7},
-};
+static void __iomem *regs;
+static struct tegra_gpio_bank tegra_gpio_banks[7];
+
+static inline void tegra_gpio_writel(u32 val, u32 reg)
+{
+ __raw_writel(val, regs + reg);
+}
+
+static inline u32 tegra_gpio_readl(u32 reg)
+{
+ return __raw_readl(regs + reg);
+}
static int tegra_gpio_compose(int bank, int port, int bit)
{
@@ -97,7 +100,7 @@ static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
val = 0x100 << GPIO_BIT(gpio);
if (value)
val |= 1 << GPIO_BIT(gpio);
- __raw_writel(val, reg);
+ tegra_gpio_writel(val, reg);
}
void tegra_gpio_enable(int gpio)
@@ -117,7 +120,7 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+ return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
}
static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -134,7 +137,10 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
return 0;
}
-
+static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ return TEGRA_GPIO_TO_IRQ(offset);
+}
static struct gpio_chip tegra_gpio_chip = {
.label = "tegra-gpio",
@@ -142,6 +148,7 @@ static struct gpio_chip tegra_gpio_chip = {
.get = tegra_gpio_get,
.direction_output = tegra_gpio_direction_output,
.set = tegra_gpio_set,
+ .to_irq = tegra_gpio_to_irq,
.base = 0,
.ngpio = TEGRA_NR_GPIOS,
};
@@ -150,7 +157,7 @@ static void tegra_gpio_irq_ack(struct irq_data *d)
{
int gpio = d->irq - INT_GPIO_BASE;
- __raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+ tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
}
static void tegra_gpio_irq_mask(struct irq_data *d)
@@ -203,10 +210,10 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
spin_lock_irqsave(&bank->lvl_lock[port], flags);
- val = __raw_readl(GPIO_INT_LVL(gpio));
+ val = tegra_gpio_readl(GPIO_INT_LVL(gpio));
val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
val |= lvl_type << GPIO_BIT(gpio);
- __raw_writel(val, GPIO_INT_LVL(gpio));
+ tegra_gpio_writel(val, GPIO_INT_LVL(gpio));
spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
@@ -232,12 +239,12 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
for (port = 0; port < 4; port++) {
int gpio = tegra_gpio_compose(bank->bank, port, 0);
- unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
- __raw_readl(GPIO_INT_ENB(gpio));
- u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
+ unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) &
+ tegra_gpio_readl(GPIO_INT_ENB(gpio));
+ u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio));
for_each_set_bit(pin, &sta, 8) {
- __raw_writel(1 << pin, GPIO_INT_CLR(gpio));
+ tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio));
/* if gpio is edge triggered, clear condition
* before executing the hander so that we don't
@@ -271,11 +278,11 @@ void tegra_gpio_resume(void)
for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
unsigned int gpio = (b<<5) | (p<<3);
- __raw_writel(bank->cnf[p], GPIO_CNF(gpio));
- __raw_writel(bank->out[p], GPIO_OUT(gpio));
- __raw_writel(bank->oe[p], GPIO_OE(gpio));
- __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
- __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
+ tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio));
+ tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio));
+ tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio));
+ tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
+ tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
}
}
@@ -294,11 +301,11 @@ void tegra_gpio_suspend(void)
for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
unsigned int gpio = (b<<5) | (p<<3);
- bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
- bank->out[p] = __raw_readl(GPIO_OUT(gpio));
- bank->oe[p] = __raw_readl(GPIO_OE(gpio));
- bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
- bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
+ bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio));
+ bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio));
+ bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
+ bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
+ bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
}
}
local_irq_restore(flags);
@@ -328,38 +335,69 @@ static struct irq_chip tegra_gpio_irq_chip = {
*/
static struct lock_class_key gpio_lock_class;
-static int __init tegra_gpio_init(void)
+static int __devinit tegra_gpio_probe(struct platform_device *pdev)
{
+ struct resource *res;
struct tegra_gpio_bank *bank;
+ int gpio;
int i;
int j;
+ for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!res) {
+ dev_err(&pdev->dev, "Missing IRQ resource\n");
+ return -ENODEV;
+ }
+
+ bank = &tegra_gpio_banks[i];
+ bank->bank = i;
+ bank->irq = res->start;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Missing MEM resource\n");
+ return -ENODEV;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res),
+ dev_name(&pdev->dev))) {
+ dev_err(&pdev->dev, "Couldn't request MEM resource\n");
+ return -ENODEV;
+ }
+
+ regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!regs) {
+ dev_err(&pdev->dev, "Couldn't ioremap regs\n");
+ return -ENODEV;
+ }
+
for (i = 0; i < 7; i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
- __raw_writel(0x00, GPIO_INT_ENB(gpio));
+ tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio));
}
}
#ifdef CONFIG_OF_GPIO
- /*
- * This isn't ideal, but it gets things hooked up until this
- * driver is converted into a platform_device
- */
- tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL,
- "nvidia,tegra20-gpio");
-#endif /* CONFIG_OF_GPIO */
+ tegra_gpio_chip.of_node = pdev->dev.of_node;
+#endif
gpiochip_add(&tegra_gpio_chip);
- for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
- bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
+ for (gpio = 0; gpio < TEGRA_NR_GPIOS; gpio++) {
+ int irq = TEGRA_GPIO_TO_IRQ(gpio);
+ /* No validity check; all Tegra GPIOs are valid IRQs */
- irq_set_lockdep_class(i, &gpio_lock_class);
- irq_set_chip_data(i, bank);
- irq_set_chip_and_handler(i, &tegra_gpio_irq_chip,
+ bank = &tegra_gpio_banks[GPIO_BANK(gpio)];
+
+ irq_set_lockdep_class(irq, &gpio_lock_class);
+ irq_set_chip_data(irq, bank);
+ irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip,
handle_simple_irq);
- set_irq_flags(i, IRQF_VALID);
+ set_irq_flags(irq, IRQF_VALID);
}
for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
@@ -375,6 +413,24 @@ static int __init tegra_gpio_init(void)
return 0;
}
+static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra20-gpio", },
+ { },
+};
+
+static struct platform_driver tegra_gpio_driver = {
+ .driver = {
+ .name = "tegra-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = tegra_gpio_of_match,
+ },
+ .probe = tegra_gpio_probe,
+};
+
+static int __init tegra_gpio_init(void)
+{
+ return platform_driver_register(&tegra_gpio_driver);
+}
postcore_initcall(tegra_gpio_init);
void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
@@ -407,13 +463,13 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
seq_printf(s,
"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
i, j,
- __raw_readl(GPIO_CNF(gpio)),
- __raw_readl(GPIO_OE(gpio)),
- __raw_readl(GPIO_OUT(gpio)),
- __raw_readl(GPIO_IN(gpio)),
- __raw_readl(GPIO_INT_STA(gpio)),
- __raw_readl(GPIO_INT_ENB(gpio)),
- __raw_readl(GPIO_INT_LVL(gpio)));
+ tegra_gpio_readl(GPIO_CNF(gpio)),
+ tegra_gpio_readl(GPIO_OE(gpio)),
+ tegra_gpio_readl(GPIO_OUT(gpio)),
+ tegra_gpio_readl(GPIO_IN(gpio)),
+ tegra_gpio_readl(GPIO_INT_STA(gpio)),
+ tegra_gpio_readl(GPIO_INT_ENB(gpio)),
+ tegra_gpio_readl(GPIO_INT_LVL(gpio)));
}
}
return 0;
diff --git a/arch/arm/mach-davinci/gpio-tnetv107x.c b/drivers/gpio/gpio-tnetv107x.c
index 3fa3e2867e19..3fa3e2867e19 100644
--- a/arch/arm/mach-davinci/gpio-tnetv107x.c
+++ b/drivers/gpio/gpio-tnetv107x.c
diff --git a/drivers/gpio/gpio-u300.c b/drivers/gpio/gpio-u300.c
index 53e8255cb0ba..4035778852b0 100644
--- a/drivers/gpio/gpio-u300.c
+++ b/drivers/gpio/gpio-u300.c
@@ -1,18 +1,17 @@
/*
* U300 GPIO module.
*
- * Copyright (C) 2007-2009 ST-Ericsson AB
+ * Copyright (C) 2007-2011 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
* This can driver either of the two basic GPIO cores
* available in the U300 platforms:
* COH 901 335 - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
* COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0)
- * Notice that you also have inline macros in <asm-arch/gpio.h>
- * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Linus Walleij <linus.walleij@linaro.org>
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
- *
*/
#include <linux/module.h>
+#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -21,677 +20,898 @@
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <mach/gpio-u300.h>
-/* Reference to GPIO block clock */
-static struct clk *clk;
+/*
+ * Bias modes for U300 GPIOs
+ *
+ * GPIO_U300_CONFIG_BIAS_UNKNOWN: this bias mode is not known to us
+ * GPIO_U300_CONFIG_BIAS_FLOAT: no specific bias, the GPIO will float or state
+ * is not controlled by software
+ * GPIO_U300_CONFIG_BIAS_PULL_UP: the GPIO will be pulled up (usually with high
+ * impedance to VDD)
+ */
+#define GPIO_U300_CONFIG_BIAS_UNKNOWN 0x1000
+#define GPIO_U300_CONFIG_BIAS_FLOAT 0x1001
+#define GPIO_U300_CONFIG_BIAS_PULL_UP 0x1002
-/* Memory resource */
-static struct resource *memres;
-static void __iomem *virtbase;
-static struct device *gpiodev;
+/*
+ * Drive modes for U300 GPIOs (output)
+ *
+ * GPIO_U300_CONFIG_DRIVE_PUSH_PULL: the GPIO will be driven actively high and
+ * low, this is the most typical case and is typically achieved with two
+ * active transistors on the output
+ * GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: the GPIO will be driven with open drain
+ * (open collector) which means it is usually wired with other output
+ * ports which are then pulled up with an external resistor
+ * GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: the GPIO will be driven with open drain
+ * (open emitter) which is the same as open drain mutatis mutandis but
+ * pulled to ground
+ */
+#define GPIO_U300_CONFIG_DRIVE_PUSH_PULL 0x2000
+#define GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN 0x2001
+#define GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE 0x2002
+
+/*
+ * Register definitions for COH 901 335 variant
+ */
+#define U300_335_PORT_STRIDE (0x1C)
+/* Port X Pin Data Register 32bit, this is both input and output (R/W) */
+#define U300_335_PXPDIR (0x00)
+#define U300_335_PXPDOR (0x00)
+/* Port X Pin Config Register 32bit (R/W) */
+#define U300_335_PXPCR (0x04)
+/* This register layout is the same in both blocks */
+#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL)
+#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL)
+#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL)
+/* Port X Interrupt Event Register 32bit (R/W) */
+#define U300_335_PXIEV (0x08)
+/* Port X Interrupt Enable Register 32bit (R/W) */
+#define U300_335_PXIEN (0x0C)
+/* Port X Interrupt Force Register 32bit (R/W) */
+#define U300_335_PXIFR (0x10)
+/* Port X Interrupt Config Register 32bit (R/W) */
+#define U300_335_PXICR (0x14)
+/* This register layout is the same in both blocks */
+#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL)
+/* Port X Pull-up Enable Register 32bit (R/W) */
+#define U300_335_PXPER (0x18)
+/* This register layout is the same in both blocks */
+#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL)
+#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL)
+/* Control Register 32bit (R/W) */
+#define U300_335_CR (0x54)
+#define U300_335_CR_BLOCK_CLOCK_ENABLE (0x00000001UL)
+
+/*
+ * Register definitions for COH 901 571 / 3 variant
+ */
+#define U300_571_PORT_STRIDE (0x30)
+/*
+ * Control Register 32bit (R/W)
+ * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
+ * gives the number of GPIO pins.
+ * bit 8-2 (mask 0x000001FC) contains the core version ID.
+ */
+#define U300_571_CR (0x00)
+#define U300_571_CR_SYNC_SEL_ENABLE (0x00000002UL)
+#define U300_571_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL)
+/*
+ * These registers have the same layout and function as the corresponding
+ * COH 901 335 registers, just at different offset.
+ */
+#define U300_571_PXPDIR (0x04)
+#define U300_571_PXPDOR (0x08)
+#define U300_571_PXPCR (0x0C)
+#define U300_571_PXPER (0x10)
+#define U300_571_PXIEV (0x14)
+#define U300_571_PXIEN (0x18)
+#define U300_571_PXIFR (0x1C)
+#define U300_571_PXICR (0x20)
+
+/* 8 bits per port, no version has more than 7 ports */
+#define U300_GPIO_PINS_PER_PORT 8
+#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * 7)
+
+struct u300_gpio {
+ struct gpio_chip chip;
+ struct list_head port_list;
+ struct clk *clk;
+ struct resource *memres;
+ void __iomem *base;
+ struct device *dev;
+ int irq_base;
+ u32 stride;
+ /* Register offsets */
+ u32 pcr;
+ u32 dor;
+ u32 dir;
+ u32 per;
+ u32 icr;
+ u32 ien;
+ u32 iev;
+};
struct u300_gpio_port {
- const char *name;
+ struct list_head node;
+ struct u300_gpio *gpio;
+ char name[8];
int irq;
int number;
+ u8 toggle_edge_mode;
};
+/*
+ * Macro to expand to read a specific register found in the "gpio"
+ * struct. It requires the struct u300_gpio *gpio variable to exist in
+ * its context. It calculates the port offset from the given pin
+ * offset, muliplies by the port stride and adds the register offset
+ * so it provides a pointer to the desired register.
+ */
+#define U300_PIN_REG(pin, reg) \
+ (gpio->base + (pin >> 3) * gpio->stride + gpio->reg)
-static struct u300_gpio_port gpio_ports[] = {
- {
- .name = "gpio0",
- .number = 0,
- },
- {
- .name = "gpio1",
- .number = 1,
- },
- {
- .name = "gpio2",
- .number = 2,
- },
-#ifdef U300_COH901571_3
- {
- .name = "gpio3",
- .number = 3,
- },
- {
- .name = "gpio4",
- .number = 4,
- },
-#ifdef CONFIG_MACH_U300_BS335
- {
- .name = "gpio5",
- .number = 5,
- },
- {
- .name = "gpio6",
- .number = 6,
- },
-#endif
-#endif
+/*
+ * Provides a bitmask for a specific gpio pin inside an 8-bit GPIO
+ * register.
+ */
+#define U300_PIN_BIT(pin) \
+ (1 << (pin & 0x07))
+struct u300_gpio_confdata {
+ u16 bias_mode;
+ bool output;
+ int outval;
};
+/* BS335 has seven ports of 8 bits each = GPIO pins 0..55 */
+#define BS335_GPIO_NUM_PORTS 7
+/* BS365 has five ports of 8 bits each = GPIO pins 0..39 */
+#define BS365_GPIO_NUM_PORTS 5
-#ifdef U300_COH901571_3
+#define U300_FLOATING_INPUT { \
+ .bias_mode = GPIO_U300_CONFIG_BIAS_FLOAT, \
+ .output = false, \
+}
-/* Default input value */
-#define DEFAULT_OUTPUT_LOW 0
-#define DEFAULT_OUTPUT_HIGH 1
+#define U300_PULL_UP_INPUT { \
+ .bias_mode = GPIO_U300_CONFIG_BIAS_PULL_UP, \
+ .output = false, \
+}
-/* GPIO Pull-Up status */
-#define DISABLE_PULL_UP 0
-#define ENABLE_PULL_UP 1
+#define U300_OUTPUT_LOW { \
+ .output = true, \
+ .outval = 0, \
+}
-#define GPIO_NOT_USED 0
-#define GPIO_IN 1
-#define GPIO_OUT 2
+#define U300_OUTPUT_HIGH { \
+ .output = true, \
+ .outval = 1, \
+}
-struct u300_gpio_configuration_data {
- unsigned char pin_usage;
- unsigned char default_output_value;
- unsigned char pull_up;
-};
/* Initial configuration */
-const struct u300_gpio_configuration_data
-u300_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
-#ifdef CONFIG_MACH_U300_BS335
+static const struct __initdata u300_gpio_confdata
+bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
/* Port 0, pins 0-7 */
{
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ U300_FLOATING_INPUT,
+ U300_OUTPUT_HIGH,
+ U300_FLOATING_INPUT,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
},
/* Port 1, pins 0-7 */
{
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
+ U300_PULL_UP_INPUT,
+ U300_FLOATING_INPUT,
+ U300_OUTPUT_HIGH,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
},
/* Port 2, pins 0-7 */
{
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_OUTPUT_LOW,
+ U300_PULL_UP_INPUT,
+ U300_OUTPUT_LOW,
+ U300_PULL_UP_INPUT,
},
/* Port 3, pins 0-7 */
{
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ U300_PULL_UP_INPUT,
+ U300_OUTPUT_LOW,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
},
/* Port 4, pins 0-7 */
{
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
},
/* Port 5, pins 0-7 */
{
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
},
/* Port 6, pind 0-7 */
{
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
}
-#endif
+};
-#ifdef CONFIG_MACH_U300_BS365
+static const struct __initdata u300_gpio_confdata
+bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
/* Port 0, pins 0-7 */
{
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ U300_FLOATING_INPUT,
+ U300_OUTPUT_LOW,
+ U300_FLOATING_INPUT,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
+ U300_PULL_UP_INPUT,
+ U300_FLOATING_INPUT,
},
/* Port 1, pins 0-7 */
{
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
+ U300_OUTPUT_LOW,
+ U300_FLOATING_INPUT,
+ U300_OUTPUT_LOW,
+ U300_FLOATING_INPUT,
+ U300_FLOATING_INPUT,
+ U300_OUTPUT_HIGH,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
},
/* Port 2, pins 0-7 */
{
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
+ U300_FLOATING_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
},
/* Port 3, pins 0-7 */
{
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
},
/* Port 4, pins 0-7 */
{
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
+ U300_PULL_UP_INPUT,
/* These 4 pins doesn't exist on DB3210 */
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
+ U300_OUTPUT_LOW,
}
-#endif
};
-#endif
-
-/* No users == we can power down GPIO */
-static int gpio_users;
-
-struct gpio_struct {
- int (*callback)(void *);
- void *data;
- int users;
-};
-
-static struct gpio_struct gpio_pin[U300_GPIO_MAX];
-
-/*
- * Let drivers register callback in order to get notified when there is
- * an interrupt on the gpio pin
+/**
+ * to_u300_gpio() - get the pointer to u300_gpio
+ * @chip: the gpio chip member of the structure u300_gpio
*/
-int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data)
+static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip)
{
- if (gpio_pin[gpio].callback)
- dev_warn(gpiodev, "%s: WARNING: callback already "
- "registered for gpio pin#%d\n", __func__, gpio);
- gpio_pin[gpio].callback = func;
- gpio_pin[gpio].data = data;
-
- return 0;
+ return container_of(chip, struct u300_gpio, chip);
}
-EXPORT_SYMBOL(gpio_register_callback);
-int gpio_unregister_callback(unsigned gpio)
+static int u300_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- if (!gpio_pin[gpio].callback)
- dev_warn(gpiodev, "%s: WARNING: callback already "
- "unregistered for gpio pin#%d\n", __func__, gpio);
- gpio_pin[gpio].callback = NULL;
- gpio_pin[gpio].data = NULL;
+ struct u300_gpio *gpio = to_u300_gpio(chip);
- return 0;
+ return readl(U300_PIN_REG(offset, dir)) & U300_PIN_BIT(offset);
}
-EXPORT_SYMBOL(gpio_unregister_callback);
-/* Non-zero means valid */
-int gpio_is_valid(int number)
+static void u300_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
- if (number >= 0 &&
- number < (U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT))
- return 1;
- return 0;
-}
-EXPORT_SYMBOL(gpio_is_valid);
+ struct u300_gpio *gpio = to_u300_gpio(chip);
+ unsigned long flags;
+ u32 val;
-int gpio_request(unsigned gpio, const char *label)
-{
- if (gpio_pin[gpio].users)
- return -EINVAL;
- else
- gpio_pin[gpio].users++;
+ local_irq_save(flags);
- gpio_users++;
+ val = readl(U300_PIN_REG(offset, dor));
+ if (value)
+ writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, dor));
+ else
+ writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, dor));
- return 0;
+ local_irq_restore(flags);
}
-EXPORT_SYMBOL(gpio_request);
-void gpio_free(unsigned gpio)
+static int u300_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
- gpio_users--;
- gpio_pin[gpio].users--;
- if (unlikely(gpio_pin[gpio].users < 0)) {
- dev_warn(gpiodev, "warning: gpio#%d release mismatch\n",
- gpio);
- gpio_pin[gpio].users = 0;
- }
-
- return;
-}
-EXPORT_SYMBOL(gpio_free);
+ struct u300_gpio *gpio = to_u300_gpio(chip);
+ unsigned long flags;
+ u32 val;
-/* This returns zero or nonzero */
-int gpio_get_value(unsigned gpio)
-{
- return readl(virtbase + U300_GPIO_PXPDIR +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) & (1 << (gpio & 0x07));
+ local_irq_save(flags);
+ val = readl(U300_PIN_REG(offset, pcr));
+ /* Mask out this pin, note 2 bits per setting */
+ val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1));
+ writel(val, U300_PIN_REG(offset, pcr));
+ local_irq_restore(flags);
+ return 0;
}
-EXPORT_SYMBOL(gpio_get_value);
-/*
- * We hope that the compiler will optimize away the unused branch
- * in case "value" is a constant
- */
-void gpio_set_value(unsigned gpio, int value)
+static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
{
- u32 val;
+ struct u300_gpio *gpio = to_u300_gpio(chip);
unsigned long flags;
+ u32 oldmode;
+ u32 val;
local_irq_save(flags);
- if (value) {
- /* set */
- val = readl(virtbase + U300_GPIO_PXPDOR +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
- & (1 << (gpio & 0x07));
- writel(val | (1 << (gpio & 0x07)), virtbase +
- U300_GPIO_PXPDOR +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
- } else {
- /* clear */
- val = readl(virtbase + U300_GPIO_PXPDOR +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
- & (1 << (gpio & 0x07));
- writel(val & ~(1 << (gpio & 0x07)), virtbase +
- U300_GPIO_PXPDOR +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+ val = readl(U300_PIN_REG(offset, pcr));
+ /*
+ * Drive mode must be set by the special mode set function, set
+ * push/pull mode by default if no mode has been selected.
+ */
+ oldmode = val & (U300_GPIO_PXPCR_PIN_MODE_MASK <<
+ ((offset & 0x07) << 1));
+ /* mode = 0 means input, else some mode is already set */
+ if (oldmode == 0) {
+ val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK <<
+ ((offset & 0x07) << 1));
+ val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
+ << ((offset & 0x07) << 1));
+ writel(val, U300_PIN_REG(offset, pcr));
}
+ u300_gpio_set(chip, offset, value);
local_irq_restore(flags);
+ return 0;
}
-EXPORT_SYMBOL(gpio_set_value);
-int gpio_direction_input(unsigned gpio)
+static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
+ struct u300_gpio *gpio = to_u300_gpio(chip);
+ int retirq = gpio->irq_base + offset;
+
+ dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset,
+ retirq);
+ return retirq;
+}
+
+static int u300_gpio_config(struct gpio_chip *chip, unsigned offset,
+ u16 param, unsigned long *data)
+{
+ struct u300_gpio *gpio = to_u300_gpio(chip);
unsigned long flags;
u32 val;
- if (gpio > U300_GPIO_MAX)
- return -EINVAL;
-
local_irq_save(flags);
- val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- /* Mask out this pin*/
- val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
- /* This is not needed since it sets the bits to zero.*/
- /* val |= (U300_GPIO_PXPCR_PIN_MODE_INPUT << (gpio*2)); */
- writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
+ switch (param) {
+ case GPIO_U300_CONFIG_BIAS_UNKNOWN:
+ case GPIO_U300_CONFIG_BIAS_FLOAT:
+ val = readl(U300_PIN_REG(offset, per));
+ writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, per));
+ break;
+ case GPIO_U300_CONFIG_BIAS_PULL_UP:
+ val = readl(U300_PIN_REG(offset, per));
+ writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, per));
+ break;
+ case GPIO_U300_CONFIG_DRIVE_PUSH_PULL:
+ val = readl(U300_PIN_REG(offset, pcr));
+ val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
+ << ((offset & 0x07) << 1));
+ val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
+ << ((offset & 0x07) << 1));
+ writel(val, U300_PIN_REG(offset, pcr));
+ break;
+ case GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN:
+ val = readl(U300_PIN_REG(offset, pcr));
+ val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
+ << ((offset & 0x07) << 1));
+ val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN
+ << ((offset & 0x07) << 1));
+ writel(val, U300_PIN_REG(offset, pcr));
+ break;
+ case GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE:
+ val = readl(U300_PIN_REG(offset, pcr));
+ val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
+ << ((offset & 0x07) << 1));
+ val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE
+ << ((offset & 0x07) << 1));
+ writel(val, U300_PIN_REG(offset, pcr));
+ break;
+ default:
+ local_irq_restore(flags);
+ dev_err(gpio->dev, "illegal configuration requested\n");
+ return -EINVAL;
+ }
local_irq_restore(flags);
return 0;
}
-EXPORT_SYMBOL(gpio_direction_input);
-int gpio_direction_output(unsigned gpio, int value)
+static struct gpio_chip u300_gpio_chip = {
+ .label = "u300-gpio-chip",
+ .owner = THIS_MODULE,
+ .get = u300_gpio_get,
+ .set = u300_gpio_set,
+ .direction_input = u300_gpio_direction_input,
+ .direction_output = u300_gpio_direction_output,
+ .to_irq = u300_gpio_to_irq,
+};
+
+static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset)
{
- unsigned long flags;
u32 val;
- if (gpio > U300_GPIO_MAX)
- return -EINVAL;
-
- local_irq_save(flags);
- val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- /* Mask out this pin */
- val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
- /*
- * FIXME: configure for push/pull, open drain or open source per pin
- * in setup. The current driver will only support push/pull.
- */
- val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
- << ((gpio & 0x07) << 1));
- writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- gpio_set_value(gpio, value);
- local_irq_restore(flags);
- return 0;
+ val = readl(U300_PIN_REG(offset, icr));
+ /* Set mode depending on state */
+ if (u300_gpio_get(&gpio->chip, offset)) {
+ /* High now, let's trigger on falling edge next then */
+ writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+ dev_dbg(gpio->dev, "next IRQ on falling edge on pin %d\n",
+ offset);
+ } else {
+ /* Low now, let's trigger on rising edge next then */
+ writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+ dev_dbg(gpio->dev, "next IRQ on rising edge on pin %d\n",
+ offset);
+ }
}
-EXPORT_SYMBOL(gpio_direction_output);
-/*
- * Enable an IRQ, edge is rising edge (!= 0) or falling edge (==0).
- */
-void enable_irq_on_gpio_pin(unsigned gpio, int edge)
+static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
{
+ struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct u300_gpio *gpio = port->gpio;
+ int offset = d->irq - gpio->irq_base;
u32 val;
- unsigned long flags;
- local_irq_save(flags);
- val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- val |= (1 << (gpio & 0x07));
- writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- val = readl(virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- if (edge)
- val |= (1 << (gpio & 0x07));
- else
- val &= ~(1 << (gpio & 0x07));
- writel(val, virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- local_irq_restore(flags);
+ if ((trigger & IRQF_TRIGGER_RISING) &&
+ (trigger & IRQF_TRIGGER_FALLING)) {
+ /*
+ * The GPIO block can only trigger on falling OR rising edges,
+ * not both. So we need to toggle the mode whenever the pin
+ * goes from one state to the other with a special state flag
+ */
+ dev_dbg(gpio->dev,
+ "trigger on both rising and falling edge on pin %d\n",
+ offset);
+ port->toggle_edge_mode |= U300_PIN_BIT(offset);
+ u300_toggle_trigger(gpio, offset);
+ } else if (trigger & IRQF_TRIGGER_RISING) {
+ dev_dbg(gpio->dev, "trigger on rising edge on pin %d\n",
+ offset);
+ val = readl(U300_PIN_REG(offset, icr));
+ writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+ port->toggle_edge_mode &= ~U300_PIN_BIT(offset);
+ } else if (trigger & IRQF_TRIGGER_FALLING) {
+ dev_dbg(gpio->dev, "trigger on falling edge on pin %d\n",
+ offset);
+ val = readl(U300_PIN_REG(offset, icr));
+ writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+ port->toggle_edge_mode &= ~U300_PIN_BIT(offset);
+ }
+
+ return 0;
}
-EXPORT_SYMBOL(enable_irq_on_gpio_pin);
-void disable_irq_on_gpio_pin(unsigned gpio)
+static void u300_gpio_irq_enable(struct irq_data *d)
{
+ struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct u300_gpio *gpio = port->gpio;
+ int offset = d->irq - gpio->irq_base;
u32 val;
unsigned long flags;
local_irq_save(flags);
- val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- val &= ~(1 << (gpio & 0x07));
- writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
+ val = readl(U300_PIN_REG(offset, ien));
+ writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
local_irq_restore(flags);
}
-EXPORT_SYMBOL(disable_irq_on_gpio_pin);
-/* Enable (value == 0) or disable (value == 1) internal pullup */
-void gpio_pullup(unsigned gpio, int value)
+static void u300_gpio_irq_disable(struct irq_data *d)
{
+ struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct u300_gpio *gpio = port->gpio;
+ int offset = d->irq - gpio->irq_base;
u32 val;
unsigned long flags;
local_irq_save(flags);
- if (value) {
- val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- writel(val | (1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
- } else {
- val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- writel(val & ~(1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
- }
+ val = readl(U300_PIN_REG(offset, ien));
+ writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
local_irq_restore(flags);
}
-EXPORT_SYMBOL(gpio_pullup);
-static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+static struct irq_chip u300_gpio_irqchip = {
+ .name = "u300-gpio-irqchip",
+ .irq_enable = u300_gpio_irq_enable,
+ .irq_disable = u300_gpio_irq_disable,
+ .irq_set_type = u300_gpio_irq_type,
+
+};
+
+static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{
- struct u300_gpio_port *port = dev_id;
- u32 val;
- int pin;
+ struct u300_gpio_port *port = irq_get_handler_data(irq);
+ struct u300_gpio *gpio = port->gpio;
+ int pinoffset = port->number << 3; /* get the right stride */
+ unsigned long val;
+ desc->irq_data.chip->irq_ack(&desc->irq_data);
/* Read event register */
- val = readl(virtbase + U300_GPIO_PXIEV + port->number *
- U300_GPIO_PORTX_SPACING);
- /* Mask with enable register */
- val &= readl(virtbase + U300_GPIO_PXIEV + port->number *
- U300_GPIO_PORTX_SPACING);
+ val = readl(U300_PIN_REG(pinoffset, iev));
/* Mask relevant bits */
- val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK;
+ val &= 0xFFU; /* 8 bits per port */
/* ACK IRQ (clear event) */
- writel(val, virtbase + U300_GPIO_PXIEV + port->number *
- U300_GPIO_PORTX_SPACING);
- /* Print message */
- while (val != 0) {
- unsigned gpio;
-
- pin = __ffs(val);
- /* mask off this pin */
- val &= ~(1 << pin);
- gpio = (port->number << 3) + pin;
-
- if (gpio_pin[gpio].callback)
- (void)gpio_pin[gpio].callback(gpio_pin[gpio].data);
- else
- dev_dbg(gpiodev, "stray GPIO IRQ on line %d\n",
- gpio);
+ writel(val, U300_PIN_REG(pinoffset, iev));
+
+ /* Call IRQ handler */
+ if (val != 0) {
+ int irqoffset;
+
+ for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
+ int pin_irq = gpio->irq_base + (port->number << 3)
+ + irqoffset;
+ int offset = pinoffset + irqoffset;
+
+ dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
+ pin_irq, offset);
+ generic_handle_irq(pin_irq);
+ /*
+ * Triggering IRQ on both rising and falling edge
+ * needs mockery
+ */
+ if (port->toggle_edge_mode & U300_PIN_BIT(offset))
+ u300_toggle_trigger(gpio, offset);
+ }
}
- return IRQ_HANDLED;
+
+ desc->irq_data.chip->irq_unmask(&desc->irq_data);
}
-static void gpio_set_initial_values(void)
+static void __init u300_gpio_init_pin(struct u300_gpio *gpio,
+ int offset,
+ const struct u300_gpio_confdata *conf)
{
-#ifdef U300_COH901571_3
- int i, j;
- unsigned long flags;
- u32 val;
+ /* Set mode: input or output */
+ if (conf->output) {
+ u300_gpio_direction_output(&gpio->chip, offset, conf->outval);
- /* Write default values to all pins */
- for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
- val = 0;
- for (j = 0; j < 8; j++)
- val |= (u32) (u300_gpio_config[i][j].default_output_value != DEFAULT_OUTPUT_LOW) << j;
- local_irq_save(flags);
- writel(val, virtbase + U300_GPIO_PXPDOR + i * U300_GPIO_PORTX_SPACING);
- local_irq_restore(flags);
+ /* Deactivate bias mode for output */
+ u300_gpio_config(&gpio->chip, offset,
+ GPIO_U300_CONFIG_BIAS_FLOAT,
+ NULL);
+
+ /* Set drive mode for output */
+ u300_gpio_config(&gpio->chip, offset,
+ GPIO_U300_CONFIG_DRIVE_PUSH_PULL, NULL);
+
+ dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n",
+ offset, conf->outval);
+ } else {
+ u300_gpio_direction_input(&gpio->chip, offset);
+
+ /* Always set output low on input pins */
+ u300_gpio_set(&gpio->chip, offset, 0);
+
+ /* Set bias mode for input */
+ u300_gpio_config(&gpio->chip, offset, conf->bias_mode, NULL);
+
+ dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x\n",
+ offset, conf->bias_mode);
}
+}
- /*
- * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED'
- * to output and 'GPIO_IN' to input for each port. And initialize
- * default value on outputs.
- */
- for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
- for (j = 0; j < U300_GPIO_PINS_PER_PORT; j++) {
- local_irq_save(flags);
- val = readl(virtbase + U300_GPIO_PXPCR +
- i * U300_GPIO_PORTX_SPACING);
- /* Mask out this pin */
- val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << (j << 1));
-
- if (u300_gpio_config[i][j].pin_usage != GPIO_IN)
- val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL << (j << 1));
- writel(val, virtbase + U300_GPIO_PXPCR +
- i * U300_GPIO_PORTX_SPACING);
- local_irq_restore(flags);
+static void __init u300_gpio_init_coh901571(struct u300_gpio *gpio,
+ struct u300_gpio_platform *plat)
+{
+ int i, j;
+
+ /* Write default config and values to all pins */
+ for (i = 0; i < plat->ports; i++) {
+ for (j = 0; j < 8; j++) {
+ const struct u300_gpio_confdata *conf;
+ int offset = (i*8) + j;
+
+ if (plat->variant == U300_GPIO_COH901571_3_BS335)
+ conf = &bs335_gpio_config[i][j];
+ else if (plat->variant == U300_GPIO_COH901571_3_BS365)
+ conf = &bs365_gpio_config[i][j];
+ else
+ break;
+
+ u300_gpio_init_pin(gpio, offset, conf);
}
}
+}
- /* Enable or disable the internal pull-ups in the GPIO ASIC block */
- for (i = 0; i < U300_GPIO_MAX; i++) {
- val = 0;
- for (j = 0; j < 8; j++)
- val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP) << j);
- local_irq_save(flags);
- writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING);
- local_irq_restore(flags);
+static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
+{
+ struct u300_gpio_port *port;
+ struct list_head *p, *n;
+
+ list_for_each_safe(p, n, &gpio->port_list) {
+ port = list_entry(p, struct u300_gpio_port, node);
+ list_del(&port->node);
+ free_irq(port->irq, port);
+ kfree(port);
}
-#endif
}
-static int __init gpio_probe(struct platform_device *pdev)
+static int __init u300_gpio_probe(struct platform_device *pdev)
{
- u32 val;
+ struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
+ struct u300_gpio *gpio;
int err = 0;
+ int portno;
+ u32 val;
+ u32 ifr;
int i;
- int num_irqs;
- gpiodev = &pdev->dev;
- memset(gpio_pin, 0, sizeof(gpio_pin));
+ gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL);
+ if (gpio == NULL) {
+ dev_err(&pdev->dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ gpio->chip = u300_gpio_chip;
+ gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT;
+ gpio->irq_base = plat->gpio_irq_base;
+ gpio->chip.dev = &pdev->dev;
+ gpio->chip.base = plat->gpio_base;
+ gpio->dev = &pdev->dev;
/* Get GPIO clock */
- clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- err = PTR_ERR(clk);
- dev_err(gpiodev, "could not get GPIO clock\n");
+ gpio->clk = clk_get(gpio->dev, NULL);
+ if (IS_ERR(gpio->clk)) {
+ err = PTR_ERR(gpio->clk);
+ dev_err(gpio->dev, "could not get GPIO clock\n");
goto err_no_clk;
}
- err = clk_enable(clk);
+ err = clk_enable(gpio->clk);
if (err) {
- dev_err(gpiodev, "could not enable GPIO clock\n");
+ dev_err(gpio->dev, "could not enable GPIO clock\n");
goto err_no_clk_enable;
}
- memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!memres)
+ gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!gpio->memres) {
+ dev_err(gpio->dev, "could not get GPIO memory resource\n");
+ err = -ENODEV;
goto err_no_resource;
+ }
- if (!request_mem_region(memres->start, resource_size(memres),
+ if (!request_mem_region(gpio->memres->start,
+ resource_size(gpio->memres),
"GPIO Controller")) {
err = -ENODEV;
goto err_no_ioregion;
}
- virtbase = ioremap(memres->start, resource_size(memres));
- if (!virtbase) {
+ gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres));
+ if (!gpio->base) {
err = -ENOMEM;
goto err_no_ioremap;
}
- dev_info(gpiodev, "remapped 0x%08x to %p\n",
- memres->start, virtbase);
-
-#ifdef U300_COH901335
- dev_info(gpiodev, "initializing GPIO Controller COH 901 335\n");
- /* Turn on the GPIO block */
- writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR);
-#endif
-
-#ifdef U300_COH901571_3
- dev_info(gpiodev, "initializing GPIO Controller COH 901 571/3\n");
- val = readl(virtbase + U300_GPIO_CR);
- dev_info(gpiodev, "COH901571/3 block version: %d, " \
- "number of cores: %d\n",
- ((val & 0x0000FE00) >> 9),
- ((val & 0x000001FC) >> 2));
- writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE, virtbase + U300_GPIO_CR);
-#endif
-
- gpio_set_initial_values();
-
- for (num_irqs = 0 ; num_irqs < U300_GPIO_NUM_PORTS; num_irqs++) {
-
- gpio_ports[num_irqs].irq =
- platform_get_irq_byname(pdev,
- gpio_ports[num_irqs].name);
-
- err = request_irq(gpio_ports[num_irqs].irq,
- gpio_irq_handler, IRQF_DISABLED,
- gpio_ports[num_irqs].name,
- &gpio_ports[num_irqs]);
- if (err) {
- dev_err(gpiodev, "cannot allocate IRQ for %s!\n",
- gpio_ports[num_irqs].name);
- goto err_no_irq;
+
+ if (plat->variant == U300_GPIO_COH901335) {
+ dev_info(gpio->dev,
+ "initializing GPIO Controller COH 901 335\n");
+ gpio->stride = U300_335_PORT_STRIDE;
+ gpio->pcr = U300_335_PXPCR;
+ gpio->dor = U300_335_PXPDOR;
+ gpio->dir = U300_335_PXPDIR;
+ gpio->per = U300_335_PXPER;
+ gpio->icr = U300_335_PXICR;
+ gpio->ien = U300_335_PXIEN;
+ gpio->iev = U300_335_PXIEV;
+ ifr = U300_335_PXIFR;
+
+ /* Turn on the GPIO block */
+ writel(U300_335_CR_BLOCK_CLOCK_ENABLE,
+ gpio->base + U300_335_CR);
+ } else if (plat->variant == U300_GPIO_COH901571_3_BS335 ||
+ plat->variant == U300_GPIO_COH901571_3_BS365) {
+ dev_info(gpio->dev,
+ "initializing GPIO Controller COH 901 571/3\n");
+ gpio->stride = U300_571_PORT_STRIDE;
+ gpio->pcr = U300_571_PXPCR;
+ gpio->dor = U300_571_PXPDOR;
+ gpio->dir = U300_571_PXPDIR;
+ gpio->per = U300_571_PXPER;
+ gpio->icr = U300_571_PXICR;
+ gpio->ien = U300_571_PXIEN;
+ gpio->iev = U300_571_PXIEV;
+ ifr = U300_571_PXIFR;
+
+ val = readl(gpio->base + U300_571_CR);
+ dev_info(gpio->dev, "COH901571/3 block version: %d, " \
+ "number of cores: %d totalling %d pins\n",
+ ((val & 0x000001FC) >> 2),
+ ((val & 0x0000FE00) >> 9),
+ ((val & 0x0000FE00) >> 9) * 8);
+ writel(U300_571_CR_BLOCK_CLKRQ_ENABLE,
+ gpio->base + U300_571_CR);
+ u300_gpio_init_coh901571(gpio, plat);
+ } else {
+ dev_err(gpio->dev, "unknown block variant\n");
+ err = -ENODEV;
+ goto err_unknown_variant;
+ }
+
+ /* Add each port with its IRQ separately */
+ INIT_LIST_HEAD(&gpio->port_list);
+ for (portno = 0 ; portno < plat->ports; portno++) {
+ struct u300_gpio_port *port =
+ kmalloc(sizeof(struct u300_gpio_port), GFP_KERNEL);
+
+ if (!port) {
+ dev_err(gpio->dev, "out of memory\n");
+ err = -ENOMEM;
+ goto err_no_port;
}
- /* Turns off PortX_irq_force */
- writel(0x0, virtbase + U300_GPIO_PXIFR +
- num_irqs * U300_GPIO_PORTX_SPACING);
+
+ snprintf(port->name, 8, "gpio%d", portno);
+ port->number = portno;
+ port->gpio = gpio;
+
+ port->irq = platform_get_irq_byname(pdev,
+ port->name);
+
+ dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq,
+ port->name);
+
+ irq_set_chained_handler(port->irq, u300_gpio_irq_handler);
+ irq_set_handler_data(port->irq, port);
+
+ /* For each GPIO pin set the unique IRQ handler */
+ for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) {
+ int irqno = gpio->irq_base + (portno << 3) + i;
+
+ dev_dbg(gpio->dev, "handler for IRQ %d on %s\n",
+ irqno, port->name);
+ irq_set_chip_and_handler(irqno, &u300_gpio_irqchip,
+ handle_simple_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ irq_set_chip_data(irqno, port);
+ }
+
+ /* Turns off irq force (test register) for this port */
+ writel(0x0, gpio->base + portno * gpio->stride + ifr);
+
+ list_add_tail(&port->node, &gpio->port_list);
}
+ dev_dbg(gpio->dev, "initialized %d GPIO ports\n", portno);
+
+ err = gpiochip_add(&gpio->chip);
+ if (err) {
+ dev_err(gpio->dev, "unable to add gpiochip: %d\n", err);
+ goto err_no_chip;
+ }
+
+ platform_set_drvdata(pdev, gpio);
return 0;
- err_no_irq:
- for (i = 0; i < num_irqs; i++)
- free_irq(gpio_ports[i].irq, &gpio_ports[i]);
- iounmap(virtbase);
- err_no_ioremap:
- release_mem_region(memres->start, resource_size(memres));
- err_no_ioregion:
- err_no_resource:
- clk_disable(clk);
- err_no_clk_enable:
- clk_put(clk);
- err_no_clk:
- dev_info(gpiodev, "module ERROR:%d\n", err);
+err_no_chip:
+err_no_port:
+ u300_gpio_free_ports(gpio);
+err_unknown_variant:
+ iounmap(gpio->base);
+err_no_ioremap:
+ release_mem_region(gpio->memres->start, resource_size(gpio->memres));
+err_no_ioregion:
+err_no_resource:
+ clk_disable(gpio->clk);
+err_no_clk_enable:
+ clk_put(gpio->clk);
+err_no_clk:
+ kfree(gpio);
+ dev_info(&pdev->dev, "module ERROR:%d\n", err);
return err;
}
-static int __exit gpio_remove(struct platform_device *pdev)
+static int __exit u300_gpio_remove(struct platform_device *pdev)
{
- int i;
+ struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
+ struct u300_gpio *gpio = platform_get_drvdata(pdev);
+ int err;
/* Turn off the GPIO block */
- writel(0x00000000U, virtbase + U300_GPIO_CR);
- for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++)
- free_irq(gpio_ports[i].irq, &gpio_ports[i]);
- iounmap(virtbase);
- release_mem_region(memres->start, resource_size(memres));
- clk_disable(clk);
- clk_put(clk);
+ if (plat->variant == U300_GPIO_COH901335)
+ writel(0x00000000U, gpio->base + U300_335_CR);
+ if (plat->variant == U300_GPIO_COH901571_3_BS335 ||
+ plat->variant == U300_GPIO_COH901571_3_BS365)
+ writel(0x00000000U, gpio->base + U300_571_CR);
+
+ err = gpiochip_remove(&gpio->chip);
+ if (err < 0) {
+ dev_err(gpio->dev, "unable to remove gpiochip: %d\n", err);
+ return err;
+ }
+ u300_gpio_free_ports(gpio);
+ iounmap(gpio->base);
+ release_mem_region(gpio->memres->start,
+ resource_size(gpio->memres));
+ clk_disable(gpio->clk);
+ clk_put(gpio->clk);
+ platform_set_drvdata(pdev, NULL);
+ kfree(gpio);
return 0;
}
-static struct platform_driver gpio_driver = {
+static struct platform_driver u300_gpio_driver = {
.driver = {
.name = "u300-gpio",
},
- .remove = __exit_p(gpio_remove),
+ .remove = __exit_p(u300_gpio_remove),
};
static int __init u300_gpio_init(void)
{
- return platform_driver_probe(&gpio_driver, gpio_probe);
+ return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe);
}
static void __exit u300_gpio_exit(void)
{
- platform_driver_unregister(&gpio_driver);
+ platform_driver_unregister(&u300_gpio_driver);
}
arch_initcall(u300_gpio_init);
module_exit(u300_gpio_exit);
MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
-
-#ifdef U300_COH901571_3
-MODULE_DESCRIPTION("ST-Ericsson AB COH 901 571/3 GPIO driver");
-#endif
-
-#ifdef U300_COH901335
-MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335 GPIO driver");
-#endif
-
+MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335/COH 901 571/3 GPIO driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index b493663c7ba7..785127cb281b 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -158,3 +158,7 @@ config DRM_SAVAGE
help
Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
chipset. If M is selected the module will be called savage.
+
+source "drivers/gpu/drm/exynos/Kconfig"
+
+source "drivers/gpu/drm/vmwgfx/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 89cf05a72d1c..c0496f660707 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -35,4 +35,5 @@ obj-$(CONFIG_DRM_SAVAGE)+= savage/
obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
obj-$(CONFIG_DRM_VIA) +=via/
obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
+obj-$(CONFIG_DRM_EXYNOS) +=exynos/
obj-y += i2c/
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index f88a9b2c977b..f2366440b738 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -372,11 +372,13 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
encoder_funcs = encoder->helper_private;
if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
adjusted_mode))) {
+ DRM_DEBUG_KMS("Encoder fixup failed\n");
goto done;
}
}
if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
+ DRM_DEBUG_KMS("CRTC fixup failed\n");
goto done;
}
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 9d2668a50872..b9dc2629ea9a 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -107,11 +107,8 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count,
ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
root, tmp, &drm_debugfs_fops);
if (!ent) {
- char name[64];
- strncpy(name, root->d_name.name,
- min(root->d_name.len, 64U));
DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/%s\n",
- name, files[i].name);
+ root->d_name.name, files[i].name);
kfree(tmp);
ret = -1;
goto fail;
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 93a112d45c1a..7a87e0878f30 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -438,6 +438,8 @@ long drm_ioctl(struct file *filp,
goto err_i1;
}
}
+ if (asize > usize)
+ memset(kdata + usize, 0, asize - usize);
}
if (cmd & IOC_IN) {
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 7425e5c9bd75..fe39c3570538 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1319,6 +1319,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
#define HDMI_IDENTIFIER 0x000C03
#define AUDIO_BLOCK 0x01
#define VENDOR_BLOCK 0x03
+#define SPEAKER_BLOCK 0x04
#define EDID_BASIC_AUDIO (1 << 6)
/**
@@ -1347,6 +1348,176 @@ u8 *drm_find_cea_extension(struct edid *edid)
}
EXPORT_SYMBOL(drm_find_cea_extension);
+static void
+parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db)
+{
+ connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */
+
+ connector->dvi_dual = db[6] & 1;
+ connector->max_tmds_clock = db[7] * 5;
+
+ connector->latency_present[0] = db[8] >> 7;
+ connector->latency_present[1] = (db[8] >> 6) & 1;
+ connector->video_latency[0] = db[9];
+ connector->audio_latency[0] = db[10];
+ connector->video_latency[1] = db[11];
+ connector->audio_latency[1] = db[12];
+
+ DRM_LOG_KMS("HDMI: DVI dual %d, "
+ "max TMDS clock %d, "
+ "latency present %d %d, "
+ "video latency %d %d, "
+ "audio latency %d %d\n",
+ connector->dvi_dual,
+ connector->max_tmds_clock,
+ (int) connector->latency_present[0],
+ (int) connector->latency_present[1],
+ connector->video_latency[0],
+ connector->video_latency[1],
+ connector->audio_latency[0],
+ connector->audio_latency[1]);
+}
+
+static void
+monitor_name(struct detailed_timing *t, void *data)
+{
+ if (t->data.other_data.type == EDID_DETAIL_MONITOR_NAME)
+ *(u8 **)data = t->data.other_data.data.str.str;
+}
+
+/**
+ * drm_edid_to_eld - build ELD from EDID
+ * @connector: connector corresponding to the HDMI/DP sink
+ * @edid: EDID to parse
+ *
+ * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver.
+ * Some ELD fields are left to the graphics driver caller:
+ * - Conn_Type
+ * - HDCP
+ * - Port_ID
+ */
+void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
+{
+ uint8_t *eld = connector->eld;
+ u8 *cea;
+ u8 *name;
+ u8 *db;
+ int sad_count = 0;
+ int mnl;
+ int dbl;
+
+ memset(eld, 0, sizeof(connector->eld));
+
+ cea = drm_find_cea_extension(edid);
+ if (!cea) {
+ DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
+ return;
+ }
+
+ name = NULL;
+ drm_for_each_detailed_block((u8 *)edid, monitor_name, &name);
+ for (mnl = 0; name && mnl < 13; mnl++) {
+ if (name[mnl] == 0x0a)
+ break;
+ eld[20 + mnl] = name[mnl];
+ }
+ eld[4] = (cea[1] << 5) | mnl;
+ DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20);
+
+ eld[0] = 2 << 3; /* ELD version: 2 */
+
+ eld[16] = edid->mfg_id[0];
+ eld[17] = edid->mfg_id[1];
+ eld[18] = edid->prod_code[0];
+ eld[19] = edid->prod_code[1];
+
+ for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
+ dbl = db[0] & 0x1f;
+
+ switch ((db[0] & 0xe0) >> 5) {
+ case AUDIO_BLOCK: /* Audio Data Block, contains SADs */
+ sad_count = dbl / 3;
+ memcpy(eld + 20 + mnl, &db[1], dbl);
+ break;
+ case SPEAKER_BLOCK: /* Speaker Allocation Data Block */
+ eld[7] = db[1];
+ break;
+ case VENDOR_BLOCK:
+ /* HDMI Vendor-Specific Data Block */
+ if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0)
+ parse_hdmi_vsdb(connector, db);
+ break;
+ default:
+ break;
+ }
+ }
+ eld[5] |= sad_count << 4;
+ eld[2] = (20 + mnl + sad_count * 3 + 3) / 4;
+
+ DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", (int)eld[2], sad_count);
+}
+EXPORT_SYMBOL(drm_edid_to_eld);
+
+/**
+ * drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond
+ * @connector: connector associated with the HDMI/DP sink
+ * @mode: the display mode
+ */
+int drm_av_sync_delay(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+ int a, v;
+
+ if (!connector->latency_present[0])
+ return 0;
+ if (!connector->latency_present[1])
+ i = 0;
+
+ a = connector->audio_latency[i];
+ v = connector->video_latency[i];
+
+ /*
+ * HDMI/DP sink doesn't support audio or video?
+ */
+ if (a == 255 || v == 255)
+ return 0;
+
+ /*
+ * Convert raw EDID values to millisecond.
+ * Treat unknown latency as 0ms.
+ */
+ if (a)
+ a = min(2 * (a - 1), 500);
+ if (v)
+ v = min(2 * (v - 1), 500);
+
+ return max(v - a, 0);
+}
+EXPORT_SYMBOL(drm_av_sync_delay);
+
+/**
+ * drm_select_eld - select one ELD from multiple HDMI/DP sinks
+ * @encoder: the encoder just changed display mode
+ * @mode: the adjusted display mode
+ *
+ * It's possible for one encoder to be associated with multiple HDMI/DP sinks.
+ * The policy is now hard coded to simply use the first HDMI/DP sink's ELD.
+ */
+struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
+ struct drm_display_mode *mode)
+{
+ struct drm_connector *connector;
+ struct drm_device *dev = encoder->dev;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+ if (connector->encoder == encoder && connector->eld[0])
+ return connector;
+
+ return NULL;
+}
+EXPORT_SYMBOL(drm_select_eld);
+
/**
* drm_detect_hdmi_monitor - detect whether monitor is hdmi.
* @edid: monitor EDID information
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 186d62eb063b..396e60ce8114 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -285,6 +285,94 @@ again:
}
EXPORT_SYMBOL(drm_gem_handle_create);
+
+/**
+ * drm_gem_free_mmap_offset - release a fake mmap offset for an object
+ * @obj: obj in question
+ *
+ * This routine frees fake offsets allocated by drm_gem_create_mmap_offset().
+ */
+void
+drm_gem_free_mmap_offset(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_gem_mm *mm = dev->mm_private;
+ struct drm_map_list *list = &obj->map_list;
+
+ drm_ht_remove_item(&mm->offset_hash, &list->hash);
+ drm_mm_put_block(list->file_offset_node);
+ kfree(list->map);
+ list->map = NULL;
+}
+EXPORT_SYMBOL(drm_gem_free_mmap_offset);
+
+/**
+ * drm_gem_create_mmap_offset - create a fake mmap offset for an object
+ * @obj: obj in question
+ *
+ * GEM memory mapping works by handing back to userspace a fake mmap offset
+ * it can use in a subsequent mmap(2) call. The DRM core code then looks
+ * up the object based on the offset and sets up the various memory mapping
+ * structures.
+ *
+ * This routine allocates and attaches a fake offset for @obj.
+ */
+int
+drm_gem_create_mmap_offset(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_gem_mm *mm = dev->mm_private;
+ struct drm_map_list *list;
+ struct drm_local_map *map;
+ int ret = 0;
+
+ /* Set the object up for mmap'ing */
+ list = &obj->map_list;
+ list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
+ if (!list->map)
+ return -ENOMEM;
+
+ map = list->map;
+ map->type = _DRM_GEM;
+ map->size = obj->size;
+ map->handle = obj;
+
+ /* Get a DRM GEM mmap offset allocated... */
+ list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
+ obj->size / PAGE_SIZE, 0, 0);
+
+ if (!list->file_offset_node) {
+ DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
+ ret = -ENOSPC;
+ goto out_free_list;
+ }
+
+ list->file_offset_node = drm_mm_get_block(list->file_offset_node,
+ obj->size / PAGE_SIZE, 0);
+ if (!list->file_offset_node) {
+ ret = -ENOMEM;
+ goto out_free_list;
+ }
+
+ list->hash.key = list->file_offset_node->start;
+ ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
+ if (ret) {
+ DRM_ERROR("failed to add to map hash\n");
+ goto out_free_mm;
+ }
+
+ return 0;
+
+out_free_mm:
+ drm_mm_put_block(list->file_offset_node);
+out_free_list:
+ kfree(list->map);
+ list->map = NULL;
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_create_mmap_offset);
+
/** Returns a reference to the object named by the handle. */
struct drm_gem_object *
drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
index 9e5b07efebb7..0f3c4e3cafc3 100644
--- a/drivers/gpu/drm/drm_proc.c
+++ b/drivers/gpu/drm/drm_proc.c
@@ -95,7 +95,6 @@ int drm_proc_create_files(struct drm_info_list *files, int count,
struct drm_device *dev = minor->dev;
struct proc_dir_entry *ent;
struct drm_info_node *tmp;
- char name[64];
int i, ret;
for (i = 0; i < count; i++) {
@@ -118,7 +117,7 @@ int drm_proc_create_files(struct drm_info_list *files, int count,
&drm_proc_fops, tmp);
if (!ent) {
DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
- name, files[i].name);
+ root->name, files[i].name);
list_del(&tmp->list);
kfree(tmp);
ret = -1;
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
new file mode 100644
index 000000000000..847466aab435
--- /dev/null
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -0,0 +1,20 @@
+config DRM_EXYNOS
+ tristate "DRM Support for Samsung SoC EXYNOS Series"
+ depends on DRM && PLAT_SAMSUNG
+ default n
+ select DRM_KMS_HELPER
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
+ help
+ Choose this option if you have a Samsung SoC EXYNOS chipset.
+ If M is selected the module will be called exynosdrm.
+
+config DRM_EXYNOS_FIMD
+ tristate "Exynos DRM FIMD"
+ depends on DRM_EXYNOS
+ default n
+ help
+ Choose this option if you want to use Exynos FIMD for DRM.
+ If M is selected, the module will be called exynos_drm_fimd
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
new file mode 100644
index 000000000000..0496d3ff2683
--- /dev/null
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the drm device driver. This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos
+exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
+ exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \
+ exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o
+
+obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o
+obj-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c
new file mode 100644
index 000000000000..6f8afea94fc9
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c
@@ -0,0 +1,110 @@
+/* exynos_drm_buf.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author: Inki Dae <inki.dae@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_buf.h"
+
+static DEFINE_MUTEX(exynos_drm_buf_lock);
+
+static int lowlevel_buffer_allocate(struct drm_device *dev,
+ struct exynos_drm_buf_entry *entry)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ entry->vaddr = dma_alloc_writecombine(dev->dev, entry->size,
+ (dma_addr_t *)&entry->paddr, GFP_KERNEL);
+ if (!entry->paddr) {
+ DRM_ERROR("failed to allocate buffer.\n");
+ return -ENOMEM;
+ }
+
+ DRM_DEBUG_KMS("allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n",
+ (unsigned int)entry->vaddr, entry->paddr, entry->size);
+
+ return 0;
+}
+
+static void lowlevel_buffer_deallocate(struct drm_device *dev,
+ struct exynos_drm_buf_entry *entry)
+{
+ DRM_DEBUG_KMS("%s.\n", __FILE__);
+
+ if (entry->paddr && entry->vaddr && entry->size)
+ dma_free_writecombine(dev->dev, entry->size, entry->vaddr,
+ entry->paddr);
+ else
+ DRM_DEBUG_KMS("entry data is null.\n");
+}
+
+struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
+ unsigned int size)
+{
+ struct exynos_drm_buf_entry *entry;
+
+ DRM_DEBUG_KMS("%s.\n", __FILE__);
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+ DRM_ERROR("failed to allocate exynos_drm_buf_entry.\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ entry->size = size;
+
+ /*
+ * allocate memory region with size and set the memory information
+ * to vaddr and paddr of a entry object.
+ */
+ if (lowlevel_buffer_allocate(dev, entry) < 0) {
+ kfree(entry);
+ entry = NULL;
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return entry;
+}
+
+void exynos_drm_buf_destroy(struct drm_device *dev,
+ struct exynos_drm_buf_entry *entry)
+{
+ DRM_DEBUG_KMS("%s.\n", __FILE__);
+
+ if (!entry) {
+ DRM_DEBUG_KMS("entry is null.\n");
+ return;
+ }
+
+ lowlevel_buffer_deallocate(dev, entry);
+
+ kfree(entry);
+ entry = NULL;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Buffer Management Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.h b/drivers/gpu/drm/exynos/exynos_drm_buf.h
new file mode 100644
index 000000000000..045d59eab01a
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.h
@@ -0,0 +1,53 @@
+/* exynos_drm_buf.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author: Inki Dae <inki.dae@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_BUF_H_
+#define _EXYNOS_DRM_BUF_H_
+
+/*
+ * exynos drm buffer entry structure.
+ *
+ * @paddr: physical address of allocated memory.
+ * @vaddr: kernel virtual address of allocated memory.
+ * @size: size of allocated memory.
+ */
+struct exynos_drm_buf_entry {
+ dma_addr_t paddr;
+ void __iomem *vaddr;
+ unsigned int size;
+};
+
+/* allocate physical memory. */
+struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
+ unsigned int size);
+
+/* get physical memory information of a drm framebuffer. */
+struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);
+
+/* remove allocated physical memory. */
+void exynos_drm_buf_destroy(struct drm_device *dev,
+ struct exynos_drm_buf_entry *entry);
+
+#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
new file mode 100644
index 000000000000..985d9e768728
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_encoder.h"
+
+#define MAX_EDID 256
+#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
+ drm_connector)
+
+struct exynos_drm_connector {
+ struct drm_connector drm_connector;
+};
+
+/* convert exynos_video_timings to drm_display_mode */
+static inline void
+convert_to_display_mode(struct drm_display_mode *mode,
+ struct fb_videomode *timing)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ mode->clock = timing->pixclock / 1000;
+
+ mode->hdisplay = timing->xres;
+ mode->hsync_start = mode->hdisplay + timing->left_margin;
+ mode->hsync_end = mode->hsync_start + timing->hsync_len;
+ mode->htotal = mode->hsync_end + timing->right_margin;
+
+ mode->vdisplay = timing->yres;
+ mode->vsync_start = mode->vdisplay + timing->upper_margin;
+ mode->vsync_end = mode->vsync_start + timing->vsync_len;
+ mode->vtotal = mode->vsync_end + timing->lower_margin;
+}
+
+/* convert drm_display_mode to exynos_video_timings */
+static inline void
+convert_to_video_timing(struct fb_videomode *timing,
+ struct drm_display_mode *mode)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ memset(timing, 0, sizeof(*timing));
+
+ timing->pixclock = mode->clock * 1000;
+ timing->refresh = mode->vrefresh;
+
+ timing->xres = mode->hdisplay;
+ timing->left_margin = mode->hsync_start - mode->hdisplay;
+ timing->hsync_len = mode->hsync_end - mode->hsync_start;
+ timing->right_margin = mode->htotal - mode->hsync_end;
+
+ timing->yres = mode->vdisplay;
+ timing->upper_margin = mode->vsync_start - mode->vdisplay;
+ timing->vsync_len = mode->vsync_end - mode->vsync_start;
+ timing->lower_margin = mode->vtotal - mode->vsync_end;
+
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ timing->vmode = FB_VMODE_INTERLACED;
+ else
+ timing->vmode = FB_VMODE_NONINTERLACED;
+
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ timing->vmode |= FB_VMODE_DOUBLE;
+}
+
+static int exynos_drm_connector_get_modes(struct drm_connector *connector)
+{
+ struct exynos_drm_manager *manager =
+ exynos_drm_get_manager(connector->encoder);
+ struct exynos_drm_display *display = manager->display;
+ unsigned int count;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (!display) {
+ DRM_DEBUG_KMS("display is null.\n");
+ return 0;
+ }
+
+ /*
+ * if get_edid() exists then get_edid() callback of hdmi side
+ * is called to get edid data through i2c interface else
+ * get timing from the FIMD driver(display controller).
+ *
+ * P.S. in case of lcd panel, count is always 1 if success
+ * because lcd panel has only one mode.
+ */
+ if (display->get_edid) {
+ int ret;
+ void *edid;
+
+ edid = kzalloc(MAX_EDID, GFP_KERNEL);
+ if (!edid) {
+ DRM_ERROR("failed to allocate edid\n");
+ return 0;
+ }
+
+ ret = display->get_edid(manager->dev, connector,
+ edid, MAX_EDID);
+ if (ret < 0) {
+ DRM_ERROR("failed to get edid data.\n");
+ kfree(edid);
+ edid = NULL;
+ return 0;
+ }
+
+ drm_mode_connector_update_edid_property(connector, edid);
+ count = drm_add_edid_modes(connector, edid);
+
+ kfree(connector->display_info.raw_edid);
+ connector->display_info.raw_edid = edid;
+ } else {
+ struct drm_display_mode *mode = drm_mode_create(connector->dev);
+ struct fb_videomode *timing;
+
+ if (display->get_timing)
+ timing = display->get_timing(manager->dev);
+ else {
+ drm_mode_destroy(connector->dev, mode);
+ return 0;
+ }
+
+ convert_to_display_mode(mode, timing);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+
+ count = 1;
+ }
+
+ return count;
+}
+
+static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ struct exynos_drm_manager *manager =
+ exynos_drm_get_manager(connector->encoder);
+ struct exynos_drm_display *display = manager->display;
+ struct fb_videomode timing;
+ int ret = MODE_BAD;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ convert_to_video_timing(&timing, mode);
+
+ if (display && display->check_timing)
+ if (!display->check_timing(manager->dev, (void *)&timing))
+ ret = MODE_OK;
+
+ return ret;
+}
+
+struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ return connector->encoder;
+}
+
+static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
+ .get_modes = exynos_drm_connector_get_modes,
+ .mode_valid = exynos_drm_connector_mode_valid,
+ .best_encoder = exynos_drm_best_encoder,
+};
+
+/* get detection status of display device. */
+static enum drm_connector_status
+exynos_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct exynos_drm_manager *manager =
+ exynos_drm_get_manager(connector->encoder);
+ struct exynos_drm_display *display = manager->display;
+ enum drm_connector_status status = connector_status_disconnected;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (display && display->is_connected) {
+ if (display->is_connected(manager->dev))
+ status = connector_status_connected;
+ else
+ status = connector_status_disconnected;
+ }
+
+ return status;
+}
+
+static void exynos_drm_connector_destroy(struct drm_connector *connector)
+{
+ struct exynos_drm_connector *exynos_connector =
+ to_exynos_connector(connector);
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ drm_sysfs_connector_remove(connector);
+ drm_connector_cleanup(connector);
+ kfree(exynos_connector);
+}
+
+static struct drm_connector_funcs exynos_connector_funcs = {
+ .dpms = drm_helper_connector_dpms,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .detect = exynos_drm_connector_detect,
+ .destroy = exynos_drm_connector_destroy,
+};
+
+struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
+ struct drm_encoder *encoder)
+{
+ struct exynos_drm_connector *exynos_connector;
+ struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+ struct drm_connector *connector;
+ int type;
+ int err;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
+ if (!exynos_connector) {
+ DRM_ERROR("failed to allocate connector\n");
+ return NULL;
+ }
+
+ connector = &exynos_connector->drm_connector;
+
+ switch (manager->display->type) {
+ case EXYNOS_DISPLAY_TYPE_HDMI:
+ type = DRM_MODE_CONNECTOR_HDMIA;
+ break;
+ default:
+ type = DRM_MODE_CONNECTOR_Unknown;
+ break;
+ }
+
+ drm_connector_init(dev, connector, &exynos_connector_funcs, type);
+ drm_connector_helper_add(connector, &exynos_connector_helper_funcs);
+
+ err = drm_sysfs_connector_add(connector);
+ if (err)
+ goto err_connector;
+
+ connector->encoder = encoder;
+ err = drm_mode_connector_attach_encoder(connector, encoder);
+ if (err) {
+ DRM_ERROR("failed to attach a connector to a encoder\n");
+ goto err_sysfs;
+ }
+
+ DRM_DEBUG_KMS("connector has been created\n");
+
+ return connector;
+
+err_sysfs:
+ drm_sysfs_connector_remove(connector);
+err_connector:
+ drm_connector_cleanup(connector);
+ kfree(exynos_connector);
+ return NULL;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Connector Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.h b/drivers/gpu/drm/exynos/exynos_drm_connector.h
new file mode 100644
index 000000000000..1c7b2b5b579c
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_CONNECTOR_H_
+#define _EXYNOS_DRM_CONNECTOR_H_
+
+struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
+ struct drm_encoder *encoder);
+
+#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
new file mode 100644
index 000000000000..661a03571d0c
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -0,0 +1,272 @@
+/* exynos_drm_core.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "exynos_drm_drv.h"
+#include "exynos_drm_encoder.h"
+#include "exynos_drm_connector.h"
+#include "exynos_drm_fbdev.h"
+
+static DEFINE_MUTEX(exynos_drm_mutex);
+static LIST_HEAD(exynos_drm_subdrv_list);
+static struct drm_device *drm_dev;
+
+static int exynos_drm_subdrv_probe(struct drm_device *dev,
+ struct exynos_drm_subdrv *subdrv)
+{
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ if (subdrv->probe) {
+ int ret;
+
+ /*
+ * this probe callback would be called by sub driver
+ * after setting of all resources to this sub driver,
+ * such as clock, irq and register map are done or by load()
+ * of exynos drm driver.
+ *
+ * P.S. note that this driver is considered for modularization.
+ */
+ ret = subdrv->probe(dev, subdrv->manager.dev);
+ if (ret)
+ return ret;
+ }
+
+ /* create and initialize a encoder for this sub driver. */
+ encoder = exynos_drm_encoder_create(dev, &subdrv->manager,
+ (1 << MAX_CRTC) - 1);
+ if (!encoder) {
+ DRM_ERROR("failed to create encoder\n");
+ return -EFAULT;
+ }
+
+ /*
+ * create and initialize a connector for this sub driver and
+ * attach the encoder created above to the connector.
+ */
+ connector = exynos_drm_connector_create(dev, encoder);
+ if (!connector) {
+ DRM_ERROR("failed to create connector\n");
+ encoder->funcs->destroy(encoder);
+ return -EFAULT;
+ }
+
+ subdrv->encoder = encoder;
+ subdrv->connector = connector;
+
+ return 0;
+}
+
+static void exynos_drm_subdrv_remove(struct drm_device *dev,
+ struct exynos_drm_subdrv *subdrv)
+{
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ if (subdrv->remove)
+ subdrv->remove(dev);
+
+ if (subdrv->encoder) {
+ struct drm_encoder *encoder = subdrv->encoder;
+ encoder->funcs->destroy(encoder);
+ subdrv->encoder = NULL;
+ }
+
+ if (subdrv->connector) {
+ struct drm_connector *connector = subdrv->connector;
+ connector->funcs->destroy(connector);
+ subdrv->connector = NULL;
+ }
+}
+
+int exynos_drm_device_register(struct drm_device *dev)
+{
+ struct exynos_drm_subdrv *subdrv, *n;
+ int err;
+
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ if (!dev)
+ return -EINVAL;
+
+ if (drm_dev) {
+ DRM_ERROR("Already drm device were registered\n");
+ return -EBUSY;
+ }
+
+ mutex_lock(&exynos_drm_mutex);
+ list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
+ err = exynos_drm_subdrv_probe(dev, subdrv);
+ if (err) {
+ DRM_DEBUG("exynos drm subdrv probe failed.\n");
+ list_del(&subdrv->list);
+ }
+ }
+
+ drm_dev = dev;
+ mutex_unlock(&exynos_drm_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_device_register);
+
+int exynos_drm_device_unregister(struct drm_device *dev)
+{
+ struct exynos_drm_subdrv *subdrv;
+
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ if (!dev || dev != drm_dev) {
+ WARN(1, "Unexpected drm device unregister!\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&exynos_drm_mutex);
+ list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list)
+ exynos_drm_subdrv_remove(dev, subdrv);
+
+ drm_dev = NULL;
+ mutex_unlock(&exynos_drm_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
+
+static int exynos_drm_mode_group_reinit(struct drm_device *dev)
+{
+ struct drm_mode_group *group = &dev->primary->mode_group;
+ uint32_t *id_list = group->id_list;
+ int ret;
+
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ ret = drm_mode_group_init_legacy_group(dev, group);
+ if (ret < 0)
+ return ret;
+
+ kfree(id_list);
+ return 0;
+}
+
+int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
+{
+ int err;
+
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ if (!subdrv)
+ return -EINVAL;
+
+ mutex_lock(&exynos_drm_mutex);
+ if (drm_dev) {
+ err = exynos_drm_subdrv_probe(drm_dev, subdrv);
+ if (err) {
+ DRM_ERROR("failed to probe exynos drm subdrv\n");
+ mutex_unlock(&exynos_drm_mutex);
+ return err;
+ }
+
+ /*
+ * if any specific driver such as fimd or hdmi driver called
+ * exynos_drm_subdrv_register() later than drm_load(),
+ * the fb helper should be re-initialized and re-configured.
+ */
+ err = exynos_drm_fbdev_reinit(drm_dev);
+ if (err) {
+ DRM_ERROR("failed to reinitialize exynos drm fbdev\n");
+ exynos_drm_subdrv_remove(drm_dev, subdrv);
+ mutex_unlock(&exynos_drm_mutex);
+ return err;
+ }
+
+ err = exynos_drm_mode_group_reinit(drm_dev);
+ if (err) {
+ DRM_ERROR("failed to reinitialize mode group\n");
+ exynos_drm_fbdev_fini(drm_dev);
+ exynos_drm_subdrv_remove(drm_dev, subdrv);
+ mutex_unlock(&exynos_drm_mutex);
+ return err;
+ }
+ }
+
+ subdrv->drm_dev = drm_dev;
+
+ list_add_tail(&subdrv->list, &exynos_drm_subdrv_list);
+ mutex_unlock(&exynos_drm_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
+
+int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
+{
+ int ret = -EFAULT;
+
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ if (!subdrv) {
+ DRM_DEBUG("Unexpected exynos drm subdrv unregister!\n");
+ return ret;
+ }
+
+ mutex_lock(&exynos_drm_mutex);
+ if (drm_dev) {
+ exynos_drm_subdrv_remove(drm_dev, subdrv);
+ list_del(&subdrv->list);
+
+ /*
+ * fb helper should be updated once a sub driver is released
+ * to re-configure crtc and connector and also to re-setup
+ * drm framebuffer.
+ */
+ ret = exynos_drm_fbdev_reinit(drm_dev);
+ if (ret < 0) {
+ DRM_ERROR("failed fb helper reinit.\n");
+ goto fail;
+ }
+
+ ret = exynos_drm_mode_group_reinit(drm_dev);
+ if (ret < 0) {
+ DRM_ERROR("failed drm mode group reinit.\n");
+ goto fail;
+ }
+ }
+
+fail:
+ mutex_unlock(&exynos_drm_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister);
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Core Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
new file mode 100644
index 000000000000..9337e5e2dbb6
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -0,0 +1,381 @@
+/* exynos_drm_crtc.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_encoder.h"
+#include "exynos_drm_buf.h"
+
+#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\
+ drm_crtc)
+
+/*
+ * Exynos specific crtc postion structure.
+ *
+ * @fb_x: offset x on a framebuffer to be displyed
+ * - the unit is screen coordinates.
+ * @fb_y: offset y on a framebuffer to be displayed
+ * - the unit is screen coordinates.
+ * @crtc_x: offset x on hardware screen.
+ * @crtc_y: offset y on hardware screen.
+ * @crtc_w: width of hardware screen.
+ * @crtc_h: height of hardware screen.
+ */
+struct exynos_drm_crtc_pos {
+ unsigned int fb_x;
+ unsigned int fb_y;
+ unsigned int crtc_x;
+ unsigned int crtc_y;
+ unsigned int crtc_w;
+ unsigned int crtc_h;
+};
+
+/*
+ * Exynos specific crtc structure.
+ *
+ * @drm_crtc: crtc object.
+ * @overlay: contain information common to display controller and hdmi and
+ * contents of this overlay object would be copied to sub driver size.
+ * @pipe: a crtc index created at load() with a new crtc object creation
+ * and the crtc object would be set to private->crtc array
+ * to get a crtc object corresponding to this pipe from private->crtc
+ * array when irq interrupt occured. the reason of using this pipe is that
+ * drm framework doesn't support multiple irq yet.
+ * we can refer to the crtc to current hardware interrupt occured through
+ * this pipe value.
+ */
+struct exynos_drm_crtc {
+ struct drm_crtc drm_crtc;
+ struct exynos_drm_overlay overlay;
+ unsigned int pipe;
+};
+
+static void exynos_drm_crtc_apply(struct drm_crtc *crtc)
+{
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+ struct exynos_drm_overlay *overlay = &exynos_crtc->overlay;
+
+ exynos_drm_fn_encoder(crtc, overlay,
+ exynos_drm_encoder_crtc_mode_set);
+ exynos_drm_fn_encoder(crtc, NULL, exynos_drm_encoder_crtc_commit);
+}
+
+static int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
+ struct drm_framebuffer *fb,
+ struct drm_display_mode *mode,
+ struct exynos_drm_crtc_pos *pos)
+{
+ struct exynos_drm_buf_entry *entry;
+ unsigned int actual_w;
+ unsigned int actual_h;
+
+ entry = exynos_drm_fb_get_buf(fb);
+ if (!entry) {
+ DRM_LOG_KMS("entry is null.\n");
+ return -EFAULT;
+ }
+
+ overlay->paddr = entry->paddr;
+ overlay->vaddr = entry->vaddr;
+
+ DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
+ (unsigned long)overlay->vaddr,
+ (unsigned long)overlay->paddr);
+
+ actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
+ actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
+
+ /* set drm framebuffer data. */
+ overlay->fb_x = pos->fb_x;
+ overlay->fb_y = pos->fb_y;
+ overlay->fb_width = fb->width;
+ overlay->fb_height = fb->height;
+ overlay->bpp = fb->bits_per_pixel;
+ overlay->pitch = fb->pitch;
+
+ /* set overlay range to be displayed. */
+ overlay->crtc_x = pos->crtc_x;
+ overlay->crtc_y = pos->crtc_y;
+ overlay->crtc_width = actual_w;
+ overlay->crtc_height = actual_h;
+
+ /* set drm mode data. */
+ overlay->mode_width = mode->hdisplay;
+ overlay->mode_height = mode->vdisplay;
+ overlay->refresh = mode->vrefresh;
+ overlay->scan_flag = mode->flags;
+
+ DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
+ overlay->crtc_x, overlay->crtc_y,
+ overlay->crtc_width, overlay->crtc_height);
+
+ return 0;
+}
+
+static int exynos_drm_crtc_update(struct drm_crtc *crtc)
+{
+ struct exynos_drm_crtc *exynos_crtc;
+ struct exynos_drm_overlay *overlay;
+ struct exynos_drm_crtc_pos pos;
+ struct drm_display_mode *mode = &crtc->mode;
+ struct drm_framebuffer *fb = crtc->fb;
+
+ if (!mode || !fb)
+ return -EINVAL;
+
+ exynos_crtc = to_exynos_crtc(crtc);
+ overlay = &exynos_crtc->overlay;
+
+ memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos));
+
+ /* it means the offset of framebuffer to be displayed. */
+ pos.fb_x = crtc->x;
+ pos.fb_y = crtc->y;
+
+ /* OSD position to be displayed. */
+ pos.crtc_x = 0;
+ pos.crtc_y = 0;
+ pos.crtc_w = fb->width - crtc->x;
+ pos.crtc_h = fb->height - crtc->y;
+
+ return exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos);
+}
+
+static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* TODO */
+}
+
+static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* drm framework doesn't check NULL. */
+}
+
+static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* drm framework doesn't check NULL. */
+}
+
+static bool
+exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* drm framework doesn't check NULL */
+ return true;
+}
+
+static int
+exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ mode = adjusted_mode;
+
+ return exynos_drm_crtc_update(crtc);
+}
+
+static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ int ret;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ ret = exynos_drm_crtc_update(crtc);
+ if (ret)
+ return ret;
+
+ exynos_drm_crtc_apply(crtc);
+
+ return ret;
+}
+
+static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+ /* drm framework doesn't check NULL */
+}
+
+static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
+ .dpms = exynos_drm_crtc_dpms,
+ .prepare = exynos_drm_crtc_prepare,
+ .commit = exynos_drm_crtc_commit,
+ .mode_fixup = exynos_drm_crtc_mode_fixup,
+ .mode_set = exynos_drm_crtc_mode_set,
+ .mode_set_base = exynos_drm_crtc_mode_set_base,
+ .load_lut = exynos_drm_crtc_load_lut,
+};
+
+static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event)
+{
+ struct drm_device *dev = crtc->dev;
+ struct exynos_drm_private *dev_priv = dev->dev_private;
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+ struct drm_framebuffer *old_fb = crtc->fb;
+ int ret = -EINVAL;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ mutex_lock(&dev->struct_mutex);
+
+ if (event) {
+ /*
+ * the pipe from user always is 0 so we can set pipe number
+ * of current owner to event.
+ */
+ event->pipe = exynos_crtc->pipe;
+
+ list_add_tail(&event->base.link,
+ &dev_priv->pageflip_event_list);
+
+ ret = drm_vblank_get(dev, exynos_crtc->pipe);
+ if (ret) {
+ DRM_DEBUG("failed to acquire vblank counter\n");
+ list_del(&event->base.link);
+
+ goto out;
+ }
+
+ crtc->fb = fb;
+ ret = exynos_drm_crtc_update(crtc);
+ if (ret) {
+ crtc->fb = old_fb;
+ drm_vblank_put(dev, exynos_crtc->pipe);
+ list_del(&event->base.link);
+
+ goto out;
+ }
+
+ /*
+ * the values related to a buffer of the drm framebuffer
+ * to be applied should be set at here. because these values
+ * first, are set to shadow registers and then to
+ * real registers at vsync front porch period.
+ */
+ exynos_drm_crtc_apply(crtc);
+ }
+out:
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+}
+
+static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
+{
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+ struct exynos_drm_private *private = crtc->dev->dev_private;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ private->crtc[exynos_crtc->pipe] = NULL;
+
+ drm_crtc_cleanup(crtc);
+ kfree(exynos_crtc);
+}
+
+static struct drm_crtc_funcs exynos_crtc_funcs = {
+ .set_config = drm_crtc_helper_set_config,
+ .page_flip = exynos_drm_crtc_page_flip,
+ .destroy = exynos_drm_crtc_destroy,
+};
+
+struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev,
+ struct drm_crtc *crtc)
+{
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+ return &exynos_crtc->overlay;
+}
+
+int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
+{
+ struct exynos_drm_crtc *exynos_crtc;
+ struct exynos_drm_private *private = dev->dev_private;
+ struct drm_crtc *crtc;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
+ if (!exynos_crtc) {
+ DRM_ERROR("failed to allocate exynos crtc\n");
+ return -ENOMEM;
+ }
+
+ exynos_crtc->pipe = nr;
+ crtc = &exynos_crtc->drm_crtc;
+
+ private->crtc[nr] = crtc;
+
+ drm_crtc_init(dev, crtc, &exynos_crtc_funcs);
+ drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
+
+ return 0;
+}
+
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
+{
+ struct exynos_drm_private *private = dev->dev_private;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
+ exynos_drm_enable_vblank);
+
+ return 0;
+}
+
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
+{
+ struct exynos_drm_private *private = dev->dev_private;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
+ exynos_drm_disable_vblank);
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM CRTC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
new file mode 100644
index 000000000000..c584042d6d2c
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -0,0 +1,38 @@
+/* exynos_drm_crtc.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_CRTC_H_
+#define _EXYNOS_DRM_CRTC_H_
+
+struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev,
+ struct drm_crtc *crtc);
+int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
+
+#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
new file mode 100644
index 000000000000..83810cbe3c17
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+
+#include <drm/exynos_drm.h>
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
+#include "exynos_drm_fbdev.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_gem.h"
+
+#define DRIVER_NAME "exynos-drm"
+#define DRIVER_DESC "Samsung SoC DRM"
+#define DRIVER_DATE "20110530"
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+
+static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
+{
+ struct exynos_drm_private *private;
+ int ret;
+ int nr;
+
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
+ if (!private) {
+ DRM_ERROR("failed to allocate private\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&private->pageflip_event_list);
+ dev->dev_private = (void *)private;
+
+ drm_mode_config_init(dev);
+
+ exynos_drm_mode_config_init(dev);
+
+ /*
+ * EXYNOS4 is enough to have two CRTCs and each crtc would be used
+ * without dependency of hardware.
+ */
+ for (nr = 0; nr < MAX_CRTC; nr++) {
+ ret = exynos_drm_crtc_create(dev, nr);
+ if (ret)
+ goto err_crtc;
+ }
+
+ ret = drm_vblank_init(dev, MAX_CRTC);
+ if (ret)
+ goto err_crtc;
+
+ /*
+ * probe sub drivers such as display controller and hdmi driver,
+ * that were registered at probe() of platform driver
+ * to the sub driver and create encoder and connector for them.
+ */
+ ret = exynos_drm_device_register(dev);
+ if (ret)
+ goto err_vblank;
+
+ /*
+ * create and configure fb helper and also exynos specific
+ * fbdev object.
+ */
+ ret = exynos_drm_fbdev_init(dev);
+ if (ret) {
+ DRM_ERROR("failed to initialize drm fbdev\n");
+ goto err_drm_device;
+ }
+
+ return 0;
+
+err_drm_device:
+ exynos_drm_device_unregister(dev);
+err_vblank:
+ drm_vblank_cleanup(dev);
+err_crtc:
+ drm_mode_config_cleanup(dev);
+ kfree(private);
+
+ return ret;
+}
+
+static int exynos_drm_unload(struct drm_device *dev)
+{
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ exynos_drm_fbdev_fini(dev);
+ exynos_drm_device_unregister(dev);
+ drm_vblank_cleanup(dev);
+ drm_mode_config_cleanup(dev);
+ kfree(dev->dev_private);
+
+ dev->dev_private = NULL;
+
+ return 0;
+}
+
+static void exynos_drm_preclose(struct drm_device *dev,
+ struct drm_file *file_priv)
+{
+ struct exynos_drm_private *dev_priv = dev->dev_private;
+
+ /*
+ * drm framework frees all events at release time,
+ * so private event list should be cleared.
+ */
+ if (!list_empty(&dev_priv->pageflip_event_list))
+ INIT_LIST_HEAD(&dev_priv->pageflip_event_list);
+}
+
+static void exynos_drm_lastclose(struct drm_device *dev)
+{
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ exynos_drm_fbdev_restore_mode(dev);
+}
+
+static struct vm_operations_struct exynos_drm_gem_vm_ops = {
+ .fault = exynos_drm_gem_fault,
+ .open = drm_gem_vm_open,
+ .close = drm_gem_vm_close,
+};
+
+static struct drm_ioctl_desc exynos_ioctls[] = {
+ DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
+ DRM_UNLOCKED | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET,
+ exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED |
+ DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP,
+ exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH),
+};
+
+static struct drm_driver exynos_drm_driver = {
+ .driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM |
+ DRIVER_MODESET | DRIVER_GEM,
+ .load = exynos_drm_load,
+ .unload = exynos_drm_unload,
+ .preclose = exynos_drm_preclose,
+ .lastclose = exynos_drm_lastclose,
+ .get_vblank_counter = drm_vblank_count,
+ .enable_vblank = exynos_drm_crtc_enable_vblank,
+ .disable_vblank = exynos_drm_crtc_disable_vblank,
+ .gem_init_object = exynos_drm_gem_init_object,
+ .gem_free_object = exynos_drm_gem_free_object,
+ .gem_vm_ops = &exynos_drm_gem_vm_ops,
+ .dumb_create = exynos_drm_gem_dumb_create,
+ .dumb_map_offset = exynos_drm_gem_dumb_map_offset,
+ .dumb_destroy = exynos_drm_gem_dumb_destroy,
+ .ioctls = exynos_ioctls,
+ .fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .mmap = exynos_drm_gem_mmap,
+ .poll = drm_poll,
+ .read = drm_read,
+ .unlocked_ioctl = drm_ioctl,
+ .release = drm_release,
+ },
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+};
+
+static int exynos_drm_platform_probe(struct platform_device *pdev)
+{
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
+
+ return drm_platform_init(&exynos_drm_driver, pdev);
+}
+
+static int exynos_drm_platform_remove(struct platform_device *pdev)
+{
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ drm_platform_exit(&exynos_drm_driver, pdev);
+
+ return 0;
+}
+
+static struct platform_driver exynos_drm_platform_driver = {
+ .probe = exynos_drm_platform_probe,
+ .remove = __devexit_p(exynos_drm_platform_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ },
+};
+
+static int __init exynos_drm_init(void)
+{
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ return platform_driver_register(&exynos_drm_platform_driver);
+}
+
+static void __exit exynos_drm_exit(void)
+{
+ DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+ platform_driver_unregister(&exynos_drm_platform_driver);
+}
+
+module_init(exynos_drm_init);
+module_exit(exynos_drm_exit);
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
new file mode 100644
index 000000000000..c03683f2ae72
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -0,0 +1,254 @@
+/* exynos_drm_drv.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_DRV_H_
+#define _EXYNOS_DRM_DRV_H_
+
+#include "drm.h"
+
+#define MAX_CRTC 2
+
+struct drm_device;
+struct exynos_drm_overlay;
+struct drm_connector;
+
+/* this enumerates display type. */
+enum exynos_drm_output_type {
+ EXYNOS_DISPLAY_TYPE_NONE,
+ /* RGB or CPU Interface. */
+ EXYNOS_DISPLAY_TYPE_LCD,
+ /* HDMI Interface. */
+ EXYNOS_DISPLAY_TYPE_HDMI,
+};
+
+/*
+ * Exynos drm overlay ops structure.
+ *
+ * @mode_set: copy drm overlay info to hw specific overlay info.
+ * @commit: apply hardware specific overlay data to registers.
+ * @disable: disable hardware specific overlay.
+ */
+struct exynos_drm_overlay_ops {
+ void (*mode_set)(struct device *subdrv_dev,
+ struct exynos_drm_overlay *overlay);
+ void (*commit)(struct device *subdrv_dev);
+ void (*disable)(struct device *subdrv_dev);
+};
+
+/*
+ * Exynos drm common overlay structure.
+ *
+ * @fb_x: offset x on a framebuffer to be displayed.
+ * - the unit is screen coordinates.
+ * @fb_y: offset y on a framebuffer to be displayed.
+ * - the unit is screen coordinates.
+ * @fb_width: width of a framebuffer.
+ * @fb_height: height of a framebuffer.
+ * @crtc_x: offset x on hardware screen.
+ * @crtc_y: offset y on hardware screen.
+ * @crtc_width: window width to be displayed (hardware screen).
+ * @crtc_height: window height to be displayed (hardware screen).
+ * @mode_width: width of screen mode.
+ * @mode_height: height of screen mode.
+ * @refresh: refresh rate.
+ * @scan_flag: interlace or progressive way.
+ * (it could be DRM_MODE_FLAG_*)
+ * @bpp: pixel size.(in bit)
+ * @paddr: bus(accessed by dma) physical memory address to this overlay
+ * and this is physically continuous.
+ * @vaddr: virtual memory addresss to this overlay.
+ * @default_win: a window to be enabled.
+ * @color_key: color key on or off.
+ * @index_color: if using color key feature then this value would be used
+ * as index color.
+ * @local_path: in case of lcd type, local path mode on or off.
+ * @transparency: transparency on or off.
+ * @activated: activated or not.
+ *
+ * this structure is common to exynos SoC and its contents would be copied
+ * to hardware specific overlay info.
+ */
+struct exynos_drm_overlay {
+ unsigned int fb_x;
+ unsigned int fb_y;
+ unsigned int fb_width;
+ unsigned int fb_height;
+ unsigned int crtc_x;
+ unsigned int crtc_y;
+ unsigned int crtc_width;
+ unsigned int crtc_height;
+ unsigned int mode_width;
+ unsigned int mode_height;
+ unsigned int refresh;
+ unsigned int scan_flag;
+ unsigned int bpp;
+ unsigned int pitch;
+ dma_addr_t paddr;
+ void __iomem *vaddr;
+
+ bool default_win;
+ bool color_key;
+ unsigned int index_color;
+ bool local_path;
+ bool transparency;
+ bool activated;
+};
+
+/*
+ * Exynos DRM Display Structure.
+ * - this structure is common to analog tv, digital tv and lcd panel.
+ *
+ * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
+ * @is_connected: check for that display is connected or not.
+ * @get_edid: get edid modes from display driver.
+ * @get_timing: get timing object from display driver.
+ * @check_timing: check if timing is valid or not.
+ * @power_on: display device on or off.
+ */
+struct exynos_drm_display {
+ enum exynos_drm_output_type type;
+ bool (*is_connected)(struct device *dev);
+ int (*get_edid)(struct device *dev, struct drm_connector *connector,
+ u8 *edid, int len);
+ void *(*get_timing)(struct device *dev);
+ int (*check_timing)(struct device *dev, void *timing);
+ int (*power_on)(struct device *dev, int mode);
+};
+
+/*
+ * Exynos drm manager ops
+ *
+ * @mode_set: convert drm_display_mode to hw specific display mode and
+ * would be called by encoder->mode_set().
+ * @commit: set current hw specific display mode to hw.
+ * @enable_vblank: specific driver callback for enabling vblank interrupt.
+ * @disable_vblank: specific driver callback for disabling vblank interrupt.
+ */
+struct exynos_drm_manager_ops {
+ void (*mode_set)(struct device *subdrv_dev, void *mode);
+ void (*commit)(struct device *subdrv_dev);
+ int (*enable_vblank)(struct device *subdrv_dev);
+ void (*disable_vblank)(struct device *subdrv_dev);
+};
+
+/*
+ * Exynos drm common manager structure.
+ *
+ * @dev: pointer to device object for subdrv device driver.
+ * sub drivers such as display controller or hdmi driver,
+ * have their own device object.
+ * @ops: pointer to callbacks for exynos drm specific framebuffer.
+ * these callbacks should be set by specific drivers such fimd
+ * or hdmi driver and are used to control hardware global registers.
+ * @overlay_ops: pointer to callbacks for exynos drm specific framebuffer.
+ * these callbacks should be set by specific drivers such fimd
+ * or hdmi driver and are used to control hardware overlay reigsters.
+ * @display: pointer to callbacks for exynos drm specific framebuffer.
+ * these callbacks should be set by specific drivers such fimd
+ * or hdmi driver and are used to control display devices such as
+ * analog tv, digital tv and lcd panel and also get timing data for them.
+ */
+struct exynos_drm_manager {
+ struct device *dev;
+ int pipe;
+ struct exynos_drm_manager_ops *ops;
+ struct exynos_drm_overlay_ops *overlay_ops;
+ struct exynos_drm_display *display;
+};
+
+/*
+ * Exynos drm private structure.
+ */
+struct exynos_drm_private {
+ struct drm_fb_helper *fb_helper;
+
+ /* list head for new event to be added. */
+ struct list_head pageflip_event_list;
+
+ /*
+ * created crtc object would be contained at this array and
+ * this array is used to be aware of which crtc did it request vblank.
+ */
+ struct drm_crtc *crtc[MAX_CRTC];
+};
+
+/*
+ * Exynos drm sub driver structure.
+ *
+ * @list: sub driver has its own list object to register to exynos drm driver.
+ * @drm_dev: pointer to drm_device and this pointer would be set
+ * when sub driver calls exynos_drm_subdrv_register().
+ * @probe: this callback would be called by exynos drm driver after
+ * subdrv is registered to it.
+ * @remove: this callback is used to release resources created
+ * by probe callback.
+ * @manager: subdrv has its own manager to control a hardware appropriately
+ * and we can access a hardware drawing on this manager.
+ * @encoder: encoder object owned by this sub driver.
+ * @connector: connector object owned by this sub driver.
+ */
+struct exynos_drm_subdrv {
+ struct list_head list;
+ struct drm_device *drm_dev;
+
+ int (*probe)(struct drm_device *drm_dev, struct device *dev);
+ void (*remove)(struct drm_device *dev);
+
+ struct exynos_drm_manager manager;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+};
+
+/*
+ * this function calls a probe callback registered to sub driver list and
+ * create its own encoder and connector and then set drm_device object
+ * to global one.
+ */
+int exynos_drm_device_register(struct drm_device *dev);
+/*
+ * this function calls a remove callback registered to sub driver list and
+ * destroy its own encoder and connetor.
+ */
+int exynos_drm_device_unregister(struct drm_device *dev);
+
+/*
+ * this function would be called by sub drivers such as display controller
+ * or hdmi driver to register this sub driver object to exynos drm driver
+ * and when a sub driver is registered to exynos drm driver a probe callback
+ * of the sub driver is called and creates its own encoder and connector
+ * and then fb helper and drm mode group would be re-initialized.
+ */
+int exynos_drm_subdrv_register(struct exynos_drm_subdrv *drm_subdrv);
+
+/*
+ * this function removes subdrv list from exynos drm driver and fb helper
+ * and drm mode group would be re-initialized.
+ */
+int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *drm_subdrv);
+
+#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
new file mode 100644
index 000000000000..7cf6fa86a67e
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -0,0 +1,271 @@
+/* exynos_drm_encoder.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
+#include "exynos_drm_encoder.h"
+
+#define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder,\
+ drm_encoder)
+
+/*
+ * exynos specific encoder structure.
+ *
+ * @drm_encoder: encoder object.
+ * @manager: specific encoder has its own manager to control a hardware
+ * appropriately and we can access a hardware drawing on this manager.
+ */
+struct exynos_drm_encoder {
+ struct drm_encoder drm_encoder;
+ struct exynos_drm_manager *manager;
+};
+
+static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct drm_device *dev = encoder->dev;
+ struct drm_connector *connector;
+ struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+
+ DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ if (connector->encoder == encoder) {
+ struct exynos_drm_display *display = manager->display;
+
+ if (display && display->power_on)
+ display->power_on(manager->dev, mode);
+ }
+ }
+}
+
+static bool
+exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* drm framework doesn't check NULL. */
+
+ return true;
+}
+
+static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct drm_device *dev = encoder->dev;
+ struct drm_connector *connector;
+ struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+ struct exynos_drm_manager_ops *manager_ops = manager->ops;
+ struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+ struct exynos_drm_overlay *overlay = get_exynos_drm_overlay(dev,
+ encoder->crtc);
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ mode = adjusted_mode;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ if (connector->encoder == encoder) {
+ if (manager_ops && manager_ops->mode_set)
+ manager_ops->mode_set(manager->dev, mode);
+
+ if (overlay_ops && overlay_ops->mode_set)
+ overlay_ops->mode_set(manager->dev, overlay);
+ }
+ }
+}
+
+static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* drm framework doesn't check NULL. */
+}
+
+static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
+{
+ struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+ struct exynos_drm_manager_ops *manager_ops = manager->ops;
+ struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (manager_ops && manager_ops->commit)
+ manager_ops->commit(manager->dev);
+
+ if (overlay_ops && overlay_ops->commit)
+ overlay_ops->commit(manager->dev);
+}
+
+static struct drm_crtc *
+exynos_drm_encoder_get_crtc(struct drm_encoder *encoder)
+{
+ return encoder->crtc;
+}
+
+static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
+ .dpms = exynos_drm_encoder_dpms,
+ .mode_fixup = exynos_drm_encoder_mode_fixup,
+ .mode_set = exynos_drm_encoder_mode_set,
+ .prepare = exynos_drm_encoder_prepare,
+ .commit = exynos_drm_encoder_commit,
+ .get_crtc = exynos_drm_encoder_get_crtc,
+};
+
+static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
+{
+ struct exynos_drm_encoder *exynos_encoder =
+ to_exynos_encoder(encoder);
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ exynos_encoder->manager->pipe = -1;
+
+ drm_encoder_cleanup(encoder);
+ encoder->dev->mode_config.num_encoder--;
+ kfree(exynos_encoder);
+}
+
+static struct drm_encoder_funcs exynos_encoder_funcs = {
+ .destroy = exynos_drm_encoder_destroy,
+};
+
+struct drm_encoder *
+exynos_drm_encoder_create(struct drm_device *dev,
+ struct exynos_drm_manager *manager,
+ unsigned int possible_crtcs)
+{
+ struct drm_encoder *encoder;
+ struct exynos_drm_encoder *exynos_encoder;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (!manager || !possible_crtcs)
+ return NULL;
+
+ if (!manager->dev)
+ return NULL;
+
+ exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
+ if (!exynos_encoder) {
+ DRM_ERROR("failed to allocate encoder\n");
+ return NULL;
+ }
+
+ exynos_encoder->manager = manager;
+ encoder = &exynos_encoder->drm_encoder;
+ encoder->possible_crtcs = possible_crtcs;
+
+ DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
+
+ drm_encoder_init(dev, encoder, &exynos_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS);
+
+ drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
+
+ DRM_DEBUG_KMS("encoder has been created\n");
+
+ return encoder;
+}
+
+struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder)
+{
+ return to_exynos_encoder(encoder)->manager;
+}
+
+void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
+ void (*fn)(struct drm_encoder *, void *))
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_encoder *encoder;
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (encoder->crtc != crtc)
+ continue;
+
+ fn(encoder, data);
+ }
+}
+
+void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
+{
+ struct exynos_drm_manager *manager =
+ to_exynos_encoder(encoder)->manager;
+ struct exynos_drm_manager_ops *manager_ops = manager->ops;
+ int crtc = *(int *)data;
+
+ if (manager->pipe == -1)
+ manager->pipe = crtc;
+
+ if (manager_ops->enable_vblank)
+ manager_ops->enable_vblank(manager->dev);
+}
+
+void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
+{
+ struct exynos_drm_manager *manager =
+ to_exynos_encoder(encoder)->manager;
+ struct exynos_drm_manager_ops *manager_ops = manager->ops;
+ int crtc = *(int *)data;
+
+ if (manager->pipe == -1)
+ manager->pipe = crtc;
+
+ if (manager_ops->disable_vblank)
+ manager_ops->disable_vblank(manager->dev);
+}
+
+void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data)
+{
+ struct exynos_drm_manager *manager =
+ to_exynos_encoder(encoder)->manager;
+ struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+
+ overlay_ops->commit(manager->dev);
+}
+
+void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
+{
+ struct exynos_drm_manager *manager =
+ to_exynos_encoder(encoder)->manager;
+ struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+ struct exynos_drm_overlay *overlay = data;
+
+ overlay_ops->mode_set(manager->dev, overlay);
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Encoder Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h
new file mode 100644
index 000000000000..5ecd645d06a9
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_ENCODER_H_
+#define _EXYNOS_DRM_ENCODER_H_
+
+struct exynos_drm_manager;
+
+struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev,
+ struct exynos_drm_manager *mgr,
+ unsigned int possible_crtcs);
+struct exynos_drm_manager *
+exynos_drm_get_manager(struct drm_encoder *encoder);
+void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
+ void (*fn)(struct drm_encoder *, void *));
+void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data);
+void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data);
+
+#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
new file mode 100644
index 000000000000..48d29cfd5240
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -0,0 +1,265 @@
+/* exynos_drm_fb.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_fb.h"
+#include "exynos_drm_buf.h"
+#include "exynos_drm_gem.h"
+
+#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb)
+
+/*
+ * exynos specific framebuffer structure.
+ *
+ * @fb: drm framebuffer obejct.
+ * @exynos_gem_obj: exynos specific gem object containing a gem object.
+ * @entry: pointer to exynos drm buffer entry object.
+ * - containing only the information to physically continuous memory
+ * region allocated at default framebuffer creation.
+ */
+struct exynos_drm_fb {
+ struct drm_framebuffer fb;
+ struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_buf_entry *entry;
+};
+
+static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
+{
+ struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ drm_framebuffer_cleanup(fb);
+
+ /*
+ * default framebuffer has no gem object so
+ * a buffer of the default framebuffer should be released at here.
+ */
+ if (!exynos_fb->exynos_gem_obj && exynos_fb->entry)
+ exynos_drm_buf_destroy(fb->dev, exynos_fb->entry);
+
+ kfree(exynos_fb);
+ exynos_fb = NULL;
+}
+
+static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
+ struct drm_file *file_priv,
+ unsigned int *handle)
+{
+ struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ return drm_gem_handle_create(file_priv,
+ &exynos_fb->exynos_gem_obj->base, handle);
+}
+
+static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
+ struct drm_file *file_priv, unsigned flags,
+ unsigned color, struct drm_clip_rect *clips,
+ unsigned num_clips)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* TODO */
+
+ return 0;
+}
+
+static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
+ .destroy = exynos_drm_fb_destroy,
+ .create_handle = exynos_drm_fb_create_handle,
+ .dirty = exynos_drm_fb_dirty,
+};
+
+static struct drm_framebuffer *
+exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev,
+ struct drm_mode_fb_cmd *mode_cmd)
+{
+ struct exynos_drm_fb *exynos_fb;
+ struct drm_framebuffer *fb;
+ struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
+ struct drm_gem_object *obj;
+ unsigned int size;
+ int ret;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ mode_cmd->pitch = max(mode_cmd->pitch,
+ mode_cmd->width * (mode_cmd->bpp >> 3));
+
+ DRM_LOG_KMS("drm fb create(%dx%d)\n",
+ mode_cmd->width, mode_cmd->height);
+
+ exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
+ if (!exynos_fb) {
+ DRM_ERROR("failed to allocate exynos drm framebuffer.\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ fb = &exynos_fb->fb;
+ ret = drm_framebuffer_init(dev, fb, &exynos_drm_fb_funcs);
+ if (ret) {
+ DRM_ERROR("failed to initialize framebuffer.\n");
+ goto err_init;
+ }
+
+ DRM_LOG_KMS("create: fb id: %d\n", fb->base.id);
+
+ size = mode_cmd->pitch * mode_cmd->height;
+
+ /*
+ * mode_cmd->handle could be NULL at booting time or
+ * with user request. if NULL, a new buffer or a gem object
+ * would be allocated.
+ */
+ if (!mode_cmd->handle) {
+ if (!file_priv) {
+ struct exynos_drm_buf_entry *entry;
+
+ /*
+ * in case that file_priv is NULL, it allocates
+ * only buffer and this buffer would be used
+ * for default framebuffer.
+ */
+ entry = exynos_drm_buf_create(dev, size);
+ if (IS_ERR(entry)) {
+ ret = PTR_ERR(entry);
+ goto err_buffer;
+ }
+
+ exynos_fb->entry = entry;
+
+ DRM_LOG_KMS("default fb: paddr = 0x%lx, size = 0x%x\n",
+ (unsigned long)entry->paddr, size);
+
+ goto out;
+ } else {
+ exynos_gem_obj = exynos_drm_gem_create(file_priv, dev,
+ size,
+ &mode_cmd->handle);
+ if (IS_ERR(exynos_gem_obj)) {
+ ret = PTR_ERR(exynos_gem_obj);
+ goto err_buffer;
+ }
+ }
+ } else {
+ obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
+ if (!obj) {
+ DRM_ERROR("failed to lookup gem object.\n");
+ goto err_buffer;
+ }
+
+ exynos_gem_obj = to_exynos_gem_obj(obj);
+
+ drm_gem_object_unreference_unlocked(obj);
+ }
+
+ /*
+ * if got a exynos_gem_obj from either a handle or
+ * a new creation then exynos_fb->exynos_gem_obj is NULL
+ * so that default framebuffer has no its own gem object,
+ * only its own buffer object.
+ */
+ exynos_fb->entry = exynos_gem_obj->entry;
+
+ DRM_LOG_KMS("paddr = 0x%lx, size = 0x%x, gem object = 0x%x\n",
+ (unsigned long)exynos_fb->entry->paddr, size,
+ (unsigned int)&exynos_gem_obj->base);
+
+out:
+ exynos_fb->exynos_gem_obj = exynos_gem_obj;
+
+ drm_helper_mode_fill_fb_struct(fb, mode_cmd);
+
+ return fb;
+
+err_buffer:
+ drm_framebuffer_cleanup(fb);
+
+err_init:
+ kfree(exynos_fb);
+
+ return ERR_PTR(ret);
+}
+
+struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
+ struct drm_file *file_priv,
+ struct drm_mode_fb_cmd *mode_cmd)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ return exynos_drm_fb_init(file_priv, dev, mode_cmd);
+}
+
+struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
+{
+ struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+ struct exynos_drm_buf_entry *entry;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ entry = exynos_fb->entry;
+ if (!entry)
+ return NULL;
+
+ DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
+ (unsigned long)entry->vaddr,
+ (unsigned long)entry->paddr);
+
+ return entry;
+}
+
+static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
+ .fb_create = exynos_drm_fb_create,
+};
+
+void exynos_drm_mode_config_init(struct drm_device *dev)
+{
+ dev->mode_config.min_width = 0;
+ dev->mode_config.min_height = 0;
+
+ /*
+ * set max width and height as default value(4096x4096).
+ * this value would be used to check framebuffer size limitation
+ * at drm_mode_addfb().
+ */
+ dev->mode_config.max_width = 4096;
+ dev->mode_config.max_height = 4096;
+
+ dev->mode_config.funcs = &exynos_drm_mode_config_funcs;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM FB Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h
new file mode 100644
index 000000000000..eb35931d302c
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_FB_H_
+#define _EXYNOS_DRM_FB_H
+
+struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
+ struct drm_file *filp,
+ struct drm_mode_fb_cmd *mode_cmd);
+
+void exynos_drm_mode_config_init(struct drm_device *dev);
+
+#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
new file mode 100644
index 000000000000..1f4b3d1a7713
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -0,0 +1,456 @@
+/* exynos_drm_fbdev.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_crtc.h"
+#include "drm_fb_helper.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_buf.h"
+
+#define MAX_CONNECTOR 4
+#define PREFERRED_BPP 32
+
+#define to_exynos_fbdev(x) container_of(x, struct exynos_drm_fbdev,\
+ drm_fb_helper)
+
+struct exynos_drm_fbdev {
+ struct drm_fb_helper drm_fb_helper;
+ struct drm_framebuffer *fb;
+};
+
+static int exynos_drm_fbdev_set_par(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+
+ switch (var->bits_per_pixel) {
+ case 32:
+ case 24:
+ case 18:
+ case 16:
+ case 12:
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ break;
+ case 1:
+ info->fix.visual = FB_VISUAL_MONO01;
+ break;
+ default:
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+ }
+
+ info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
+
+ return drm_fb_helper_set_par(info);
+}
+
+
+static struct fb_ops exynos_drm_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_check_var = drm_fb_helper_check_var,
+ .fb_set_par = exynos_drm_fbdev_set_par,
+ .fb_blank = drm_fb_helper_blank,
+ .fb_pan_display = drm_fb_helper_pan_display,
+ .fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
+ struct drm_framebuffer *fb,
+ unsigned int fb_width,
+ unsigned int fb_height)
+{
+ struct fb_info *fbi = helper->fbdev;
+ struct drm_device *dev = helper->dev;
+ struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper);
+ struct exynos_drm_buf_entry *entry;
+ unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3);
+ unsigned long offset;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ exynos_fb->fb = fb;
+
+ drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
+ drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height);
+
+ entry = exynos_drm_fb_get_buf(fb);
+ if (!entry) {
+ DRM_LOG_KMS("entry is null.\n");
+ return -EFAULT;
+ }
+
+ offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
+ offset += fbi->var.yoffset * fb->pitch;
+
+ dev->mode_config.fb_base = entry->paddr;
+ fbi->screen_base = entry->vaddr + offset;
+ fbi->fix.smem_start = entry->paddr + offset;
+ fbi->screen_size = size;
+ fbi->fix.smem_len = size;
+
+ return 0;
+}
+
+static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
+ struct drm_device *dev = helper->dev;
+ struct fb_info *fbi;
+ struct drm_mode_fb_cmd mode_cmd = { 0 };
+ struct platform_device *pdev = dev->platformdev;
+ int ret;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
+ sizes->surface_width, sizes->surface_height,
+ sizes->surface_bpp);
+
+ mode_cmd.width = sizes->surface_width;
+ mode_cmd.height = sizes->surface_height;
+ mode_cmd.bpp = sizes->surface_bpp;
+ mode_cmd.depth = sizes->surface_depth;
+
+ mutex_lock(&dev->struct_mutex);
+
+ fbi = framebuffer_alloc(0, &pdev->dev);
+ if (!fbi) {
+ DRM_ERROR("failed to allocate fb info.\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd);
+ if (IS_ERR_OR_NULL(exynos_fbdev->fb)) {
+ DRM_ERROR("failed to create drm framebuffer.\n");
+ ret = PTR_ERR(exynos_fbdev->fb);
+ goto out;
+ }
+
+ helper->fb = exynos_fbdev->fb;
+ helper->fbdev = fbi;
+
+ fbi->par = helper;
+ fbi->flags = FBINFO_FLAG_DEFAULT;
+ fbi->fbops = &exynos_drm_fb_ops;
+
+ ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+ if (ret) {
+ DRM_ERROR("failed to allocate cmap.\n");
+ goto out;
+ }
+
+ ret = exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
+ sizes->fb_height);
+ if (ret < 0)
+ fb_dealloc_cmap(&fbi->cmap);
+
+/*
+ * if failed, all resources allocated above would be released by
+ * drm_mode_config_cleanup() when drm_load() had been called prior
+ * to any specific driver such as fimd or hdmi driver.
+ */
+out:
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+}
+
+static bool
+exynos_drm_fbdev_is_samefb(struct drm_framebuffer *fb,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ if (fb->width != sizes->surface_width)
+ return false;
+ if (fb->height != sizes->surface_height)
+ return false;
+ if (fb->bits_per_pixel != sizes->surface_bpp)
+ return false;
+ if (fb->depth != sizes->surface_depth)
+ return false;
+
+ return true;
+}
+
+static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct drm_device *dev = helper->dev;
+ struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
+ struct drm_framebuffer *fb = exynos_fbdev->fb;
+ struct drm_mode_fb_cmd mode_cmd = { 0 };
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (helper->fb != fb) {
+ DRM_ERROR("drm framebuffer is different\n");
+ return -EINVAL;
+ }
+
+ if (exynos_drm_fbdev_is_samefb(fb, sizes))
+ return 0;
+
+ mode_cmd.width = sizes->surface_width;
+ mode_cmd.height = sizes->surface_height;
+ mode_cmd.bpp = sizes->surface_bpp;
+ mode_cmd.depth = sizes->surface_depth;
+
+ if (fb->funcs->destroy)
+ fb->funcs->destroy(fb);
+
+ exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd);
+ if (IS_ERR(exynos_fbdev->fb)) {
+ DRM_ERROR("failed to allocate fb.\n");
+ return PTR_ERR(exynos_fbdev->fb);
+ }
+
+ helper->fb = exynos_fbdev->fb;
+ return exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
+ sizes->fb_height);
+}
+
+static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ int ret = 0;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (!helper->fb) {
+ ret = exynos_drm_fbdev_create(helper, sizes);
+ if (ret < 0) {
+ DRM_ERROR("failed to create fbdev.\n");
+ return ret;
+ }
+
+ /*
+ * fb_helper expects a value more than 1 if succeed
+ * because register_framebuffer() should be called.
+ */
+ ret = 1;
+ } else {
+ ret = exynos_drm_fbdev_recreate(helper, sizes);
+ if (ret < 0) {
+ DRM_ERROR("failed to reconfigure fbdev\n");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
+ .fb_probe = exynos_drm_fbdev_probe,
+};
+
+int exynos_drm_fbdev_init(struct drm_device *dev)
+{
+ struct exynos_drm_fbdev *fbdev;
+ struct exynos_drm_private *private = dev->dev_private;
+ struct drm_fb_helper *helper;
+ unsigned int num_crtc;
+ int ret;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
+ return 0;
+
+ fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+ if (!fbdev) {
+ DRM_ERROR("failed to allocate drm fbdev.\n");
+ return -ENOMEM;
+ }
+
+ private->fb_helper = helper = &fbdev->drm_fb_helper;
+ helper->funcs = &exynos_drm_fb_helper_funcs;
+
+ num_crtc = dev->mode_config.num_crtc;
+
+ ret = drm_fb_helper_init(dev, helper, num_crtc, MAX_CONNECTOR);
+ if (ret < 0) {
+ DRM_ERROR("failed to initialize drm fb helper.\n");
+ goto err_init;
+ }
+
+ ret = drm_fb_helper_single_add_all_connectors(helper);
+ if (ret < 0) {
+ DRM_ERROR("failed to register drm_fb_helper_connector.\n");
+ goto err_setup;
+
+ }
+
+ ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
+ if (ret < 0) {
+ DRM_ERROR("failed to set up hw configuration.\n");
+ goto err_setup;
+ }
+
+ return 0;
+
+err_setup:
+ drm_fb_helper_fini(helper);
+
+err_init:
+ private->fb_helper = NULL;
+ kfree(fbdev);
+
+ return ret;
+}
+
+static void exynos_drm_fbdev_destroy(struct drm_device *dev,
+ struct drm_fb_helper *fb_helper)
+{
+ struct drm_framebuffer *fb;
+
+ /* release drm framebuffer and real buffer */
+ if (fb_helper->fb && fb_helper->fb->funcs) {
+ fb = fb_helper->fb;
+ if (fb && fb->funcs->destroy)
+ fb->funcs->destroy(fb);
+ }
+
+ /* release linux framebuffer */
+ if (fb_helper->fbdev) {
+ struct fb_info *info;
+ int ret;
+
+ info = fb_helper->fbdev;
+ ret = unregister_framebuffer(info);
+ if (ret < 0)
+ DRM_DEBUG_KMS("failed unregister_framebuffer()\n");
+
+ if (info->cmap.len)
+ fb_dealloc_cmap(&info->cmap);
+
+ framebuffer_release(info);
+ }
+
+ drm_fb_helper_fini(fb_helper);
+}
+
+void exynos_drm_fbdev_fini(struct drm_device *dev)
+{
+ struct exynos_drm_private *private = dev->dev_private;
+ struct exynos_drm_fbdev *fbdev;
+
+ if (!private || !private->fb_helper)
+ return;
+
+ fbdev = to_exynos_fbdev(private->fb_helper);
+
+ exynos_drm_fbdev_destroy(dev, private->fb_helper);
+ kfree(fbdev);
+ private->fb_helper = NULL;
+}
+
+void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
+{
+ struct exynos_drm_private *private = dev->dev_private;
+
+ if (!private || !private->fb_helper)
+ return;
+
+ drm_fb_helper_restore_fbdev_mode(private->fb_helper);
+}
+
+int exynos_drm_fbdev_reinit(struct drm_device *dev)
+{
+ struct exynos_drm_private *private = dev->dev_private;
+ struct drm_fb_helper *fb_helper;
+ int ret;
+
+ if (!private)
+ return -EINVAL;
+
+ /*
+ * if all sub drivers were unloaded then num_connector is 0
+ * so at this time, the framebuffers also should be destroyed.
+ */
+ if (!dev->mode_config.num_connector) {
+ exynos_drm_fbdev_fini(dev);
+ return 0;
+ }
+
+ fb_helper = private->fb_helper;
+
+ if (fb_helper) {
+ drm_fb_helper_fini(fb_helper);
+
+ ret = drm_fb_helper_init(dev, fb_helper,
+ dev->mode_config.num_crtc, MAX_CONNECTOR);
+ if (ret < 0) {
+ DRM_ERROR("failed to initialize drm fb helper\n");
+ return ret;
+ }
+
+ ret = drm_fb_helper_single_add_all_connectors(fb_helper);
+ if (ret < 0) {
+ DRM_ERROR("failed to add fb helper to connectors\n");
+ goto err;
+ }
+
+ ret = drm_fb_helper_initial_config(fb_helper, PREFERRED_BPP);
+ if (ret < 0) {
+ DRM_ERROR("failed to set up hw configuration.\n");
+ goto err;
+ }
+ } else {
+ /*
+ * if drm_load() failed whem drm load() was called prior
+ * to specific drivers, fb_helper must be NULL and so
+ * this fuction should be called again to re-initialize and
+ * re-configure the fb helper. it means that this function
+ * has been called by the specific drivers.
+ */
+ ret = exynos_drm_fbdev_init(dev);
+ }
+
+ return ret;
+
+err:
+ /*
+ * if drm_load() failed when drm load() was called prior
+ * to specific drivers, the fb_helper must be NULL and so check it.
+ */
+ if (fb_helper)
+ drm_fb_helper_fini(fb_helper);
+
+ return ret;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM FBDEV Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h
new file mode 100644
index 000000000000..ccfce8a1a451
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_FBDEV_H_
+#define _EXYNOS_DRM_FBDEV_H_
+
+int exynos_drm_fbdev_init(struct drm_device *dev);
+int exynos_drm_fbdev_reinit(struct drm_device *dev);
+void exynos_drm_fbdev_fini(struct drm_device *dev);
+void exynos_drm_fbdev_restore_mode(struct drm_device *dev);
+
+#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
new file mode 100644
index 000000000000..4659c88cdd9b
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -0,0 +1,811 @@
+/* exynos_drm_fimd.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Authors:
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Inki Dae <inki.dae@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include "drmP.h"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <drm/exynos_drm.h>
+#include <plat/regs-fb-v4.h>
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fbdev.h"
+#include "exynos_drm_crtc.h"
+
+/*
+ * FIMD is stand for Fully Interactive Mobile Display and
+ * as a display controller, it transfers contents drawn on memory
+ * to a LCD Panel through Display Interfaces such as RGB or
+ * CPU Interface.
+ */
+
+/* position control register for hardware window 0, 2 ~ 4.*/
+#define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16)
+#define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16)
+/* size control register for hardware window 0. */
+#define VIDOSD_C_SIZE_W0 (VIDOSD_BASE + 0x08)
+/* alpha control register for hardware window 1 ~ 4. */
+#define VIDOSD_C(win) (VIDOSD_BASE + 0x18 + (win) * 16)
+/* size control register for hardware window 1 ~ 4. */
+#define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16)
+
+#define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8)
+#define VIDWx_BUF_END(win, buf) (VIDW_BUF_END(buf) + (win) * 8)
+#define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4)
+
+/* color key control register for hardware window 1 ~ 4. */
+#define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + (x * 8))
+/* color key value register for hardware window 1 ~ 4. */
+#define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + (x * 8))
+
+/* FIMD has totally five hardware windows. */
+#define WINDOWS_NR 5
+
+#define get_fimd_context(dev) platform_get_drvdata(to_platform_device(dev))
+
+struct fimd_win_data {
+ unsigned int offset_x;
+ unsigned int offset_y;
+ unsigned int ovl_width;
+ unsigned int ovl_height;
+ unsigned int fb_width;
+ unsigned int fb_height;
+ unsigned int bpp;
+ dma_addr_t paddr;
+ void __iomem *vaddr;
+ unsigned int buf_offsize;
+ unsigned int line_size; /* bytes */
+};
+
+struct fimd_context {
+ struct exynos_drm_subdrv subdrv;
+ int irq;
+ struct drm_crtc *crtc;
+ struct clk *bus_clk;
+ struct clk *lcd_clk;
+ struct resource *regs_res;
+ void __iomem *regs;
+ struct fimd_win_data win_data[WINDOWS_NR];
+ unsigned int clkdiv;
+ unsigned int default_win;
+ unsigned long irq_flags;
+ u32 vidcon0;
+ u32 vidcon1;
+
+ struct fb_videomode *timing;
+};
+
+static bool fimd_display_is_connected(struct device *dev)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* TODO. */
+
+ return true;
+}
+
+static void *fimd_get_timing(struct device *dev)
+{
+ struct fimd_context *ctx = get_fimd_context(dev);
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ return ctx->timing;
+}
+
+static int fimd_check_timing(struct device *dev, void *timing)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* TODO. */
+
+ return 0;
+}
+
+static int fimd_display_power_on(struct device *dev, int mode)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* TODO. */
+
+ return 0;
+}
+
+static struct exynos_drm_display fimd_display = {
+ .type = EXYNOS_DISPLAY_TYPE_LCD,
+ .is_connected = fimd_display_is_connected,
+ .get_timing = fimd_get_timing,
+ .check_timing = fimd_check_timing,
+ .power_on = fimd_display_power_on,
+};
+
+static void fimd_commit(struct device *dev)
+{
+ struct fimd_context *ctx = get_fimd_context(dev);
+ struct fb_videomode *timing = ctx->timing;
+ u32 val;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* setup polarity values from machine code. */
+ writel(ctx->vidcon1, ctx->regs + VIDCON1);
+
+ /* setup vertical timing values. */
+ val = VIDTCON0_VBPD(timing->upper_margin - 1) |
+ VIDTCON0_VFPD(timing->lower_margin - 1) |
+ VIDTCON0_VSPW(timing->vsync_len - 1);
+ writel(val, ctx->regs + VIDTCON0);
+
+ /* setup horizontal timing values. */
+ val = VIDTCON1_HBPD(timing->left_margin - 1) |
+ VIDTCON1_HFPD(timing->right_margin - 1) |
+ VIDTCON1_HSPW(timing->hsync_len - 1);
+ writel(val, ctx->regs + VIDTCON1);
+
+ /* setup horizontal and vertical display size. */
+ val = VIDTCON2_LINEVAL(timing->yres - 1) |
+ VIDTCON2_HOZVAL(timing->xres - 1);
+ writel(val, ctx->regs + VIDTCON2);
+
+ /* setup clock source, clock divider, enable dma. */
+ val = ctx->vidcon0;
+ val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
+
+ if (ctx->clkdiv > 1)
+ val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
+ else
+ val &= ~VIDCON0_CLKDIR; /* 1:1 clock */
+
+ /*
+ * fields of register with prefix '_F' would be updated
+ * at vsync(same as dma start)
+ */
+ val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
+ writel(val, ctx->regs + VIDCON0);
+}
+
+static int fimd_enable_vblank(struct device *dev)
+{
+ struct fimd_context *ctx = get_fimd_context(dev);
+ u32 val;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (!test_and_set_bit(0, &ctx->irq_flags)) {
+ val = readl(ctx->regs + VIDINTCON0);
+
+ val |= VIDINTCON0_INT_ENABLE;
+ val |= VIDINTCON0_INT_FRAME;
+
+ val &= ~VIDINTCON0_FRAMESEL0_MASK;
+ val |= VIDINTCON0_FRAMESEL0_VSYNC;
+ val &= ~VIDINTCON0_FRAMESEL1_MASK;
+ val |= VIDINTCON0_FRAMESEL1_NONE;
+
+ writel(val, ctx->regs + VIDINTCON0);
+ }
+
+ return 0;
+}
+
+static void fimd_disable_vblank(struct device *dev)
+{
+ struct fimd_context *ctx = get_fimd_context(dev);
+ u32 val;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (test_and_clear_bit(0, &ctx->irq_flags)) {
+ val = readl(ctx->regs + VIDINTCON0);
+
+ val &= ~VIDINTCON0_INT_FRAME;
+ val &= ~VIDINTCON0_INT_ENABLE;
+
+ writel(val, ctx->regs + VIDINTCON0);
+ }
+}
+
+static struct exynos_drm_manager_ops fimd_manager_ops = {
+ .commit = fimd_commit,
+ .enable_vblank = fimd_enable_vblank,
+ .disable_vblank = fimd_disable_vblank,
+};
+
+static void fimd_win_mode_set(struct device *dev,
+ struct exynos_drm_overlay *overlay)
+{
+ struct fimd_context *ctx = get_fimd_context(dev);
+ struct fimd_win_data *win_data;
+ unsigned long offset;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (!overlay) {
+ dev_err(dev, "overlay is NULL\n");
+ return;
+ }
+
+ offset = overlay->fb_x * (overlay->bpp >> 3);
+ offset += overlay->fb_y * overlay->pitch;
+
+ DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
+
+ win_data = &ctx->win_data[ctx->default_win];
+
+ win_data->offset_x = overlay->crtc_x;
+ win_data->offset_y = overlay->crtc_y;
+ win_data->ovl_width = overlay->crtc_width;
+ win_data->ovl_height = overlay->crtc_height;
+ win_data->fb_width = overlay->fb_width;
+ win_data->fb_height = overlay->fb_height;
+ win_data->paddr = overlay->paddr + offset;
+ win_data->vaddr = overlay->vaddr + offset;
+ win_data->bpp = overlay->bpp;
+ win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
+ (overlay->bpp >> 3);
+ win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
+
+ DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
+ win_data->offset_x, win_data->offset_y);
+ DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
+ win_data->ovl_width, win_data->ovl_height);
+ DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
+ (unsigned long)win_data->paddr,
+ (unsigned long)win_data->vaddr);
+ DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
+ overlay->fb_width, overlay->crtc_width);
+}
+
+static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
+{
+ struct fimd_context *ctx = get_fimd_context(dev);
+ struct fimd_win_data *win_data = &ctx->win_data[win];
+ unsigned long val;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ val = WINCONx_ENWIN;
+
+ switch (win_data->bpp) {
+ case 1:
+ val |= WINCON0_BPPMODE_1BPP;
+ val |= WINCONx_BITSWP;
+ val |= WINCONx_BURSTLEN_4WORD;
+ break;
+ case 2:
+ val |= WINCON0_BPPMODE_2BPP;
+ val |= WINCONx_BITSWP;
+ val |= WINCONx_BURSTLEN_8WORD;
+ break;
+ case 4:
+ val |= WINCON0_BPPMODE_4BPP;
+ val |= WINCONx_BITSWP;
+ val |= WINCONx_BURSTLEN_8WORD;
+ break;
+ case 8:
+ val |= WINCON0_BPPMODE_8BPP_PALETTE;
+ val |= WINCONx_BURSTLEN_8WORD;
+ val |= WINCONx_BYTSWP;
+ break;
+ case 16:
+ val |= WINCON0_BPPMODE_16BPP_565;
+ val |= WINCONx_HAWSWP;
+ val |= WINCONx_BURSTLEN_16WORD;
+ break;
+ case 24:
+ val |= WINCON0_BPPMODE_24BPP_888;
+ val |= WINCONx_WSWP;
+ val |= WINCONx_BURSTLEN_16WORD;
+ break;
+ case 32:
+ val |= WINCON1_BPPMODE_28BPP_A4888
+ | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
+ val |= WINCONx_WSWP;
+ val |= WINCONx_BURSTLEN_16WORD;
+ break;
+ default:
+ DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
+
+ val |= WINCON0_BPPMODE_24BPP_888;
+ val |= WINCONx_WSWP;
+ val |= WINCONx_BURSTLEN_16WORD;
+ break;
+ }
+
+ DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
+
+ writel(val, ctx->regs + WINCON(win));
+}
+
+static void fimd_win_set_colkey(struct device *dev, unsigned int win)
+{
+ struct fimd_context *ctx = get_fimd_context(dev);
+ unsigned int keycon0 = 0, keycon1 = 0;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
+ WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
+
+ keycon1 = WxKEYCON1_COLVAL(0xffffffff);
+
+ writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
+ writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
+}
+
+static void fimd_win_commit(struct device *dev)
+{
+ struct fimd_context *ctx = get_fimd_context(dev);
+ struct fimd_win_data *win_data;
+ int win = ctx->default_win;
+ unsigned long val, alpha, size;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (win < 0 || win > WINDOWS_NR)
+ return;
+
+ win_data = &ctx->win_data[win];
+
+ /*
+ * SHADOWCON register is used for enabling timing.
+ *
+ * for example, once only width value of a register is set,
+ * if the dma is started then fimd hardware could malfunction so
+ * with protect window setting, the register fields with prefix '_F'
+ * wouldn't be updated at vsync also but updated once unprotect window
+ * is set.
+ */
+
+ /* protect windows */
+ val = readl(ctx->regs + SHADOWCON);
+ val |= SHADOWCON_WINx_PROTECT(win);
+ writel(val, ctx->regs + SHADOWCON);
+
+ /* buffer start address */
+ val = win_data->paddr;
+ writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
+
+ /* buffer end address */
+ size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
+ val = win_data->paddr + size;
+ writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
+
+ DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
+ (unsigned long)win_data->paddr, val, size);
+ DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
+ win_data->ovl_width, win_data->ovl_height);
+
+ /* buffer size */
+ val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
+ VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size);
+ writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
+
+ /* OSD position */
+ val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
+ VIDOSDxA_TOPLEFT_Y(win_data->offset_y);
+ writel(val, ctx->regs + VIDOSD_A(win));
+
+ val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x +
+ win_data->ovl_width - 1) |
+ VIDOSDxB_BOTRIGHT_Y(win_data->offset_y +
+ win_data->ovl_height - 1);
+ writel(val, ctx->regs + VIDOSD_B(win));
+
+ DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
+ win_data->offset_x, win_data->offset_y,
+ win_data->offset_x + win_data->ovl_width - 1,
+ win_data->offset_y + win_data->ovl_height - 1);
+
+ /* hardware window 0 doesn't support alpha channel. */
+ if (win != 0) {
+ /* OSD alpha */
+ alpha = VIDISD14C_ALPHA1_R(0xf) |
+ VIDISD14C_ALPHA1_G(0xf) |
+ VIDISD14C_ALPHA1_B(0xf);
+
+ writel(alpha, ctx->regs + VIDOSD_C(win));
+ }
+
+ /* OSD size */
+ if (win != 3 && win != 4) {
+ u32 offset = VIDOSD_D(win);
+ if (win == 0)
+ offset = VIDOSD_C_SIZE_W0;
+ val = win_data->ovl_width * win_data->ovl_height;
+ writel(val, ctx->regs + offset);
+
+ DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
+ }
+
+ fimd_win_set_pixfmt(dev, win);
+
+ /* hardware window 0 doesn't support color key. */
+ if (win != 0)
+ fimd_win_set_colkey(dev, win);
+
+ /* Enable DMA channel and unprotect windows */
+ val = readl(ctx->regs + SHADOWCON);
+ val |= SHADOWCON_CHx_ENABLE(win);
+ val &= ~SHADOWCON_WINx_PROTECT(win);
+ writel(val, ctx->regs + SHADOWCON);
+}
+
+static void fimd_win_disable(struct device *dev)
+{
+ struct fimd_context *ctx = get_fimd_context(dev);
+ struct fimd_win_data *win_data;
+ int win = ctx->default_win;
+ u32 val;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (win < 0 || win > WINDOWS_NR)
+ return;
+
+ win_data = &ctx->win_data[win];
+
+ /* protect windows */
+ val = readl(ctx->regs + SHADOWCON);
+ val |= SHADOWCON_WINx_PROTECT(win);
+ writel(val, ctx->regs + SHADOWCON);
+
+ /* wincon */
+ val = readl(ctx->regs + WINCON(win));
+ val &= ~WINCONx_ENWIN;
+ writel(val, ctx->regs + WINCON(win));
+
+ /* unprotect windows */
+ val = readl(ctx->regs + SHADOWCON);
+ val &= ~SHADOWCON_CHx_ENABLE(win);
+ val &= ~SHADOWCON_WINx_PROTECT(win);
+ writel(val, ctx->regs + SHADOWCON);
+}
+
+static struct exynos_drm_overlay_ops fimd_overlay_ops = {
+ .mode_set = fimd_win_mode_set,
+ .commit = fimd_win_commit,
+ .disable = fimd_win_disable,
+};
+
+static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
+{
+ struct exynos_drm_private *dev_priv = drm_dev->dev_private;
+ struct drm_pending_vblank_event *e, *t;
+ struct timeval now;
+ unsigned long flags;
+ bool is_checked = false;
+
+ spin_lock_irqsave(&drm_dev->event_lock, flags);
+
+ list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
+ base.link) {
+ /* if event's pipe isn't same as crtc then ignore it. */
+ if (crtc != e->pipe)
+ continue;
+
+ is_checked = true;
+
+ do_gettimeofday(&now);
+ e->event.sequence = 0;
+ e->event.tv_sec = now.tv_sec;
+ e->event.tv_usec = now.tv_usec;
+
+ list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+ wake_up_interruptible(&e->base.file_priv->event_wait);
+ }
+
+ if (is_checked)
+ drm_vblank_put(drm_dev, crtc);
+
+ spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+}
+
+static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
+{
+ struct fimd_context *ctx = (struct fimd_context *)dev_id;
+ struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+ struct drm_device *drm_dev = subdrv->drm_dev;
+ struct exynos_drm_manager *manager = &subdrv->manager;
+ u32 val;
+
+ val = readl(ctx->regs + VIDINTCON1);
+
+ if (val & VIDINTCON1_INT_FRAME)
+ /* VSYNC interrupt */
+ writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
+
+ drm_handle_vblank(drm_dev, manager->pipe);
+ fimd_finish_pageflip(drm_dev, manager->pipe);
+
+ return IRQ_HANDLED;
+}
+
+static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /*
+ * enable drm irq mode.
+ * - with irq_enabled = 1, we can use the vblank feature.
+ *
+ * P.S. note that we wouldn't use drm irq handler but
+ * just specific driver own one instead because
+ * drm framework supports only one irq handler.
+ */
+ drm_dev->irq_enabled = 1;
+
+ /*
+ * with vblank_disable_allowed = 1, vblank interrupt will be disabled
+ * by drm timer once a current process gives up ownership of
+ * vblank event.(drm_vblank_put function was called)
+ */
+ drm_dev->vblank_disable_allowed = 1;
+
+ return 0;
+}
+
+static void fimd_subdrv_remove(struct drm_device *drm_dev)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* TODO. */
+}
+
+static int fimd_calc_clkdiv(struct fimd_context *ctx,
+ struct fb_videomode *timing)
+{
+ unsigned long clk = clk_get_rate(ctx->lcd_clk);
+ u32 retrace;
+ u32 clkdiv;
+ u32 best_framerate = 0;
+ u32 framerate;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ retrace = timing->left_margin + timing->hsync_len +
+ timing->right_margin + timing->xres;
+ retrace *= timing->upper_margin + timing->vsync_len +
+ timing->lower_margin + timing->yres;
+
+ /* default framerate is 60Hz */
+ if (!timing->refresh)
+ timing->refresh = 60;
+
+ clk /= retrace;
+
+ for (clkdiv = 1; clkdiv < 0x100; clkdiv++) {
+ int tmp;
+
+ /* get best framerate */
+ framerate = clk / clkdiv;
+ tmp = timing->refresh - framerate;
+ if (tmp < 0) {
+ best_framerate = framerate;
+ continue;
+ } else {
+ if (!best_framerate)
+ best_framerate = framerate;
+ else if (tmp < (best_framerate - framerate))
+ best_framerate = framerate;
+ break;
+ }
+ }
+
+ return clkdiv;
+}
+
+static void fimd_clear_win(struct fimd_context *ctx, int win)
+{
+ u32 val;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ writel(0, ctx->regs + WINCON(win));
+ writel(0, ctx->regs + VIDOSD_A(win));
+ writel(0, ctx->regs + VIDOSD_B(win));
+ writel(0, ctx->regs + VIDOSD_C(win));
+
+ if (win == 1 || win == 2)
+ writel(0, ctx->regs + VIDOSD_D(win));
+
+ val = readl(ctx->regs + SHADOWCON);
+ val &= ~SHADOWCON_WINx_PROTECT(win);
+ writel(val, ctx->regs + SHADOWCON);
+}
+
+static int __devinit fimd_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct fimd_context *ctx;
+ struct exynos_drm_subdrv *subdrv;
+ struct exynos_drm_fimd_pdata *pdata;
+ struct fb_videomode *timing;
+ struct resource *res;
+ int win;
+ int ret = -EINVAL;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(dev, "no platform data specified\n");
+ return -EINVAL;
+ }
+
+ timing = &pdata->timing;
+ if (!timing) {
+ dev_err(dev, "timing is null.\n");
+ return -EINVAL;
+ }
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->bus_clk = clk_get(dev, "fimd");
+ if (IS_ERR(ctx->bus_clk)) {
+ dev_err(dev, "failed to get bus clock\n");
+ ret = PTR_ERR(ctx->bus_clk);
+ goto err_clk_get;
+ }
+
+ clk_enable(ctx->bus_clk);
+
+ ctx->lcd_clk = clk_get(dev, "sclk_fimd");
+ if (IS_ERR(ctx->lcd_clk)) {
+ dev_err(dev, "failed to get lcd clock\n");
+ ret = PTR_ERR(ctx->lcd_clk);
+ goto err_bus_clk;
+ }
+
+ clk_enable(ctx->lcd_clk);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "failed to find registers\n");
+ ret = -ENOENT;
+ goto err_clk;
+ }
+
+ ctx->regs_res = request_mem_region(res->start, resource_size(res),
+ dev_name(dev));
+ if (!ctx->regs_res) {
+ dev_err(dev, "failed to claim register region\n");
+ ret = -ENOENT;
+ goto err_clk;
+ }
+
+ ctx->regs = ioremap(res->start, resource_size(res));
+ if (!ctx->regs) {
+ dev_err(dev, "failed to map registers\n");
+ ret = -ENXIO;
+ goto err_req_region_io;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(dev, "irq request failed.\n");
+ goto err_req_region_irq;
+ }
+
+ ctx->irq = res->start;
+
+ for (win = 0; win < WINDOWS_NR; win++)
+ fimd_clear_win(ctx, win);
+
+ ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx);
+ if (ret < 0) {
+ dev_err(dev, "irq request failed.\n");
+ goto err_req_irq;
+ }
+
+ ctx->clkdiv = fimd_calc_clkdiv(ctx, timing);
+ ctx->vidcon0 = pdata->vidcon0;
+ ctx->vidcon1 = pdata->vidcon1;
+ ctx->default_win = pdata->default_win;
+ ctx->timing = timing;
+
+ timing->pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv;
+
+ DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n",
+ timing->pixclock, ctx->clkdiv);
+
+ subdrv = &ctx->subdrv;
+
+ subdrv->probe = fimd_subdrv_probe;
+ subdrv->remove = fimd_subdrv_remove;
+ subdrv->manager.pipe = -1;
+ subdrv->manager.ops = &fimd_manager_ops;
+ subdrv->manager.overlay_ops = &fimd_overlay_ops;
+ subdrv->manager.display = &fimd_display;
+ subdrv->manager.dev = dev;
+
+ platform_set_drvdata(pdev, ctx);
+ exynos_drm_subdrv_register(subdrv);
+
+ return 0;
+
+err_req_irq:
+err_req_region_irq:
+ iounmap(ctx->regs);
+
+err_req_region_io:
+ release_resource(ctx->regs_res);
+ kfree(ctx->regs_res);
+
+err_clk:
+ clk_disable(ctx->lcd_clk);
+ clk_put(ctx->lcd_clk);
+
+err_bus_clk:
+ clk_disable(ctx->bus_clk);
+ clk_put(ctx->bus_clk);
+
+err_clk_get:
+ kfree(ctx);
+ return ret;
+}
+
+static int __devexit fimd_remove(struct platform_device *pdev)
+{
+ struct fimd_context *ctx = platform_get_drvdata(pdev);
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ exynos_drm_subdrv_unregister(&ctx->subdrv);
+
+ clk_disable(ctx->lcd_clk);
+ clk_disable(ctx->bus_clk);
+ clk_put(ctx->lcd_clk);
+ clk_put(ctx->bus_clk);
+
+ iounmap(ctx->regs);
+ release_resource(ctx->regs_res);
+ kfree(ctx->regs_res);
+ free_irq(ctx->irq, ctx);
+
+ kfree(ctx);
+
+ return 0;
+}
+
+static struct platform_driver fimd_driver = {
+ .probe = fimd_probe,
+ .remove = __devexit_p(fimd_remove),
+ .driver = {
+ .name = "exynos4-fb",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init fimd_init(void)
+{
+ return platform_driver_register(&fimd_driver);
+}
+
+static void __exit fimd_exit(void)
+{
+ platform_driver_unregister(&fimd_driver);
+}
+
+module_init(fimd_init);
+module_exit(fimd_exit);
+
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samsung DRM FIMD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
new file mode 100644
index 000000000000..a8e7a88906ed
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -0,0 +1,415 @@
+/* exynos_drm_gem.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author: Inki Dae <inki.dae@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+
+#include <drm/exynos_drm.h>
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_buf.h"
+
+static unsigned int convert_to_vm_err_msg(int msg)
+{
+ unsigned int out_msg;
+
+ switch (msg) {
+ case 0:
+ case -ERESTARTSYS:
+ case -EINTR:
+ out_msg = VM_FAULT_NOPAGE;
+ break;
+
+ case -ENOMEM:
+ out_msg = VM_FAULT_OOM;
+ break;
+
+ default:
+ out_msg = VM_FAULT_SIGBUS;
+ break;
+ }
+
+ return out_msg;
+}
+
+static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
+}
+
+struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_file *file_priv,
+ struct drm_device *dev, unsigned int size,
+ unsigned int *handle)
+{
+ struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct exynos_drm_buf_entry *entry;
+ struct drm_gem_object *obj;
+ int ret;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ size = roundup(size, PAGE_SIZE);
+
+ exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
+ if (!exynos_gem_obj) {
+ DRM_ERROR("failed to allocate exynos gem object.\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* allocate the new buffer object and memory region. */
+ entry = exynos_drm_buf_create(dev, size);
+ if (!entry) {
+ kfree(exynos_gem_obj);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ exynos_gem_obj->entry = entry;
+
+ obj = &exynos_gem_obj->base;
+
+ ret = drm_gem_object_init(dev, obj, size);
+ if (ret < 0) {
+ DRM_ERROR("failed to initailize gem object.\n");
+ goto err_obj_init;
+ }
+
+ DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
+
+ ret = drm_gem_create_mmap_offset(obj);
+ if (ret < 0) {
+ DRM_ERROR("failed to allocate mmap offset.\n");
+ goto err_create_mmap_offset;
+ }
+
+ /*
+ * allocate a id of idr table where the obj is registered
+ * and handle has the id what user can see.
+ */
+ ret = drm_gem_handle_create(file_priv, obj, handle);
+ if (ret)
+ goto err_handle_create;
+
+ DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
+
+ /* drop reference from allocate - handle holds it now. */
+ drm_gem_object_unreference_unlocked(obj);
+
+ return exynos_gem_obj;
+
+err_handle_create:
+ drm_gem_free_mmap_offset(obj);
+
+err_create_mmap_offset:
+ drm_gem_object_release(obj);
+
+err_obj_init:
+ exynos_drm_buf_destroy(dev, exynos_gem_obj->entry);
+
+ kfree(exynos_gem_obj);
+
+ return ERR_PTR(ret);
+}
+
+int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_exynos_gem_create *args = data;
+ struct exynos_drm_gem_obj *exynos_gem_obj;
+
+ DRM_DEBUG_KMS("%s : size = 0x%x\n", __FILE__, args->size);
+
+ exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, args->size,
+ &args->handle);
+ if (IS_ERR(exynos_gem_obj))
+ return PTR_ERR(exynos_gem_obj);
+
+ return 0;
+}
+
+int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_exynos_gem_map_off *args = data;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n",
+ args->handle, (unsigned long)args->offset);
+
+ if (!(dev->driver->driver_features & DRIVER_GEM)) {
+ DRM_ERROR("does not support GEM.\n");
+ return -ENODEV;
+ }
+
+ return exynos_drm_gem_dumb_map_offset(file_priv, dev, args->handle,
+ &args->offset);
+}
+
+static int exynos_drm_gem_mmap_buffer(struct file *filp,
+ struct vm_area_struct *vma)
+{
+ struct drm_gem_object *obj = filp->private_data;
+ struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
+ struct exynos_drm_buf_entry *entry;
+ unsigned long pfn, vm_size;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ vma->vm_flags |= (VM_IO | VM_RESERVED);
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_file = filp;
+
+ vm_size = vma->vm_end - vma->vm_start;
+ /*
+ * a entry contains information to physically continuous memory
+ * allocated by user request or at framebuffer creation.
+ */
+ entry = exynos_gem_obj->entry;
+
+ /* check if user-requested size is valid. */
+ if (vm_size > entry->size)
+ return -EINVAL;
+
+ /*
+ * get page frame number to physical memory to be mapped
+ * to user space.
+ */
+ pfn = exynos_gem_obj->entry->paddr >> PAGE_SHIFT;
+
+ DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn);
+
+ if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size,
+ vma->vm_page_prot)) {
+ DRM_ERROR("failed to remap pfn range.\n");
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+static const struct file_operations exynos_drm_gem_fops = {
+ .mmap = exynos_drm_gem_mmap_buffer,
+};
+
+int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_exynos_gem_mmap *args = data;
+ struct drm_gem_object *obj;
+ unsigned int addr;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (!(dev->driver->driver_features & DRIVER_GEM)) {
+ DRM_ERROR("does not support GEM.\n");
+ return -ENODEV;
+ }
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (!obj) {
+ DRM_ERROR("failed to lookup gem object.\n");
+ return -EINVAL;
+ }
+
+ obj->filp->f_op = &exynos_drm_gem_fops;
+ obj->filp->private_data = obj;
+
+ down_write(&current->mm->mmap_sem);
+ addr = do_mmap(obj->filp, 0, args->size,
+ PROT_READ | PROT_WRITE, MAP_SHARED, 0);
+ up_write(&current->mm->mmap_sem);
+
+ drm_gem_object_unreference_unlocked(obj);
+
+ if (IS_ERR((void *)addr))
+ return PTR_ERR((void *)addr);
+
+ args->mapped = addr;
+
+ DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped);
+
+ return 0;
+}
+
+int exynos_drm_gem_init_object(struct drm_gem_object *obj)
+{
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ return 0;
+}
+
+void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj)
+{
+ struct exynos_drm_gem_obj *exynos_gem_obj;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ DRM_DEBUG_KMS("handle count = %d\n",
+ atomic_read(&gem_obj->handle_count));
+
+ if (gem_obj->map_list.map)
+ drm_gem_free_mmap_offset(gem_obj);
+
+ /* release file pointer to gem object. */
+ drm_gem_object_release(gem_obj);
+
+ exynos_gem_obj = to_exynos_gem_obj(gem_obj);
+
+ exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->entry);
+
+ kfree(exynos_gem_obj);
+}
+
+int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
+ struct drm_device *dev, struct drm_mode_create_dumb *args)
+{
+ struct exynos_drm_gem_obj *exynos_gem_obj;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /*
+ * alocate memory to be used for framebuffer.
+ * - this callback would be called by user application
+ * with DRM_IOCTL_MODE_CREATE_DUMB command.
+ */
+
+ args->pitch = args->width * args->bpp >> 3;
+ args->size = args->pitch * args->height;
+
+ exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, args->size,
+ &args->handle);
+ if (IS_ERR(exynos_gem_obj))
+ return PTR_ERR(exynos_gem_obj);
+
+ return 0;
+}
+
+int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
+ struct drm_device *dev, uint32_t handle, uint64_t *offset)
+{
+ struct exynos_drm_gem_obj *exynos_gem_obj;
+ struct drm_gem_object *obj;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ mutex_lock(&dev->struct_mutex);
+
+ /*
+ * get offset of memory allocated for drm framebuffer.
+ * - this callback would be called by user application
+ * with DRM_IOCTL_MODE_MAP_DUMB command.
+ */
+
+ obj = drm_gem_object_lookup(dev, file_priv, handle);
+ if (!obj) {
+ DRM_ERROR("failed to lookup gem object.\n");
+ mutex_unlock(&dev->struct_mutex);
+ return -EINVAL;
+ }
+
+ exynos_gem_obj = to_exynos_gem_obj(obj);
+
+ *offset = get_gem_mmap_offset(&exynos_gem_obj->base);
+
+ drm_gem_object_unreference(obj);
+
+ DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
+
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+}
+
+int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct drm_gem_object *obj = vma->vm_private_data;
+ struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
+ struct drm_device *dev = obj->dev;
+ unsigned long pfn;
+ pgoff_t page_offset;
+ int ret;
+
+ page_offset = ((unsigned long)vmf->virtual_address -
+ vma->vm_start) >> PAGE_SHIFT;
+
+ mutex_lock(&dev->struct_mutex);
+
+ pfn = (exynos_gem_obj->entry->paddr >> PAGE_SHIFT) + page_offset;
+
+ ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
+
+ mutex_unlock(&dev->struct_mutex);
+
+ return convert_to_vm_err_msg(ret);
+}
+
+int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ int ret;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /* set vm_area_struct. */
+ ret = drm_gem_mmap(filp, vma);
+ if (ret < 0) {
+ DRM_ERROR("failed to mmap.\n");
+ return ret;
+ }
+
+ vma->vm_flags &= ~VM_PFNMAP;
+ vma->vm_flags |= VM_MIXEDMAP;
+
+ return ret;
+}
+
+
+int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
+ struct drm_device *dev, unsigned int handle)
+{
+ int ret;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ /*
+ * obj->refcount and obj->handle_count are decreased and
+ * if both them are 0 then exynos_drm_gem_free_object()
+ * would be called by callback to release resources.
+ */
+ ret = drm_gem_handle_delete(file_priv, handle);
+ if (ret < 0) {
+ DRM_ERROR("failed to delete drm_gem_handle.\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM GEM Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
new file mode 100644
index 000000000000..e5fc0148277b
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -0,0 +1,107 @@
+/* exynos_drm_gem.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authoer: Inki Dae <inki.dae@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_GEM_H_
+#define _EXYNOS_DRM_GEM_H_
+
+#define to_exynos_gem_obj(x) container_of(x,\
+ struct exynos_drm_gem_obj, base)
+
+/*
+ * exynos drm buffer structure.
+ *
+ * @base: a gem object.
+ * - a new handle to this gem object would be created
+ * by drm_gem_handle_create().
+ * @entry: pointer to exynos drm buffer entry object.
+ * - containing the information to physically
+ * continuous memory region allocated by user request
+ * or at framebuffer creation.
+ *
+ * P.S. this object would be transfered to user as kms_bo.handle so
+ * user can access the buffer through kms_bo.handle.
+ */
+struct exynos_drm_gem_obj {
+ struct drm_gem_object base;
+ struct exynos_drm_buf_entry *entry;
+};
+
+/* create a new buffer and get a new gem handle. */
+struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_file *file_priv,
+ struct drm_device *dev, unsigned int size,
+ unsigned int *handle);
+
+/*
+ * request gem object creation and buffer allocation as the size
+ * that it is calculated with framebuffer information such as width,
+ * height and bpp.
+ */
+int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+/* get buffer offset to map to user space. */
+int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+/* unmap a buffer from user space. */
+int exynos_drm_gem_munmap_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+/* initialize gem object. */
+int exynos_drm_gem_init_object(struct drm_gem_object *obj);
+
+/* free gem object. */
+void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj);
+
+/* create memory region for drm framebuffer. */
+int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
+ struct drm_device *dev, struct drm_mode_create_dumb *args);
+
+/* map memory region for drm framebuffer to user space. */
+int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
+ struct drm_device *dev, uint32_t handle, uint64_t *offset);
+
+/* page fault handler and mmap fault address(virtual) to physical memory. */
+int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+
+/*
+ * mmap the physically continuous memory that a gem object contains
+ * to user space.
+ */
+int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+/* set vm_flags and we can change the vm attribute to other one at here. */
+int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+
+/*
+ * destroy memory region allocated.
+ * - a gem handle and physical memory region pointed by a gem object
+ * would be released by drm_gem_handle_delete().
+ */
+int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
+ struct drm_device *dev, unsigned int handle);
+
+#endif
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
index d3e8c540f778..1ca799a1e1fc 100644
--- a/drivers/gpu/drm/i915/dvo_ch7017.c
+++ b/drivers/gpu/drm/i915/dvo_ch7017.c
@@ -227,7 +227,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo,
default:
DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
"slave %d.\n",
- val, adapter->name,dvo->slave_addr);
+ val, adapter->name, dvo->slave_addr);
goto fail;
}
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
index 7eaa94e4ff06..4a036600e806 100644
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -111,7 +111,7 @@ static char *ch7xxx_get_id(uint8_t vid)
/** Reads an 8 bit register */
static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
{
- struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
+ struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus;
u8 out_buf[2];
u8 in_buf[2];
@@ -303,7 +303,7 @@ static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
for (i = 0; i < CH7xxx_NUM_REGS; i++) {
uint8_t val;
- if ((i % 8) == 0 )
+ if ((i % 8) == 0)
DRM_LOG_KMS("\n %02X: ", i);
ch7xxx_readb(dvo, i, &val);
DRM_LOG_KMS("%02X ", val);
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
index a12ed9414cc7..04f2893d5e3c 100644
--- a/drivers/gpu/drm/i915/dvo_ivch.c
+++ b/drivers/gpu/drm/i915/dvo_ivch.c
@@ -344,8 +344,8 @@ static void ivch_mode_set(struct intel_dvo_device *dvo,
(adjusted_mode->hdisplay - 1)) >> 2;
y_ratio = (((mode->vdisplay - 1) << 16) /
(adjusted_mode->vdisplay - 1)) >> 2;
- ivch_write (dvo, VR42, x_ratio);
- ivch_write (dvo, VR41, y_ratio);
+ ivch_write(dvo, VR42, x_ratio);
+ ivch_write(dvo, VR41, y_ratio);
} else {
vr01 &= ~VR01_PANEL_FIT_ENABLE;
vr40 &= ~VR40_CLOCK_GATING_ENABLE;
@@ -410,7 +410,7 @@ static void ivch_destroy(struct intel_dvo_device *dvo)
}
}
-struct intel_dvo_dev_ops ivch_ops= {
+struct intel_dvo_dev_ops ivch_ops = {
.init = ivch_init,
.dpms = ivch_dpms,
.mode_valid = ivch_mode_valid,
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
index e4b4091df942..a0b13a6f619d 100644
--- a/drivers/gpu/drm/i915/dvo_sil164.c
+++ b/drivers/gpu/drm/i915/dvo_sil164.c
@@ -104,7 +104,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
{
- struct sil164_priv *sil= dvo->dev_priv;
+ struct sil164_priv *sil = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus;
uint8_t out_buf[2];
struct i2c_msg msg = {
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
index 8ab2855bb544..aa2cd3ec54aa 100644
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -56,7 +56,7 @@
#define TFP410_CTL_2_MDI (1<<0)
#define TFP410_CTL_3 0x0A
-#define TFP410_CTL_3_DK_MASK (0x7<<5)
+#define TFP410_CTL_3_DK_MASK (0x7<<5)
#define TFP410_CTL_3_DK (1<<5)
#define TFP410_CTL_3_DKEN (1<<4)
#define TFP410_CTL_3_CTL_MASK (0x7<<1)
@@ -225,12 +225,12 @@ static void tfp410_mode_set(struct intel_dvo_device *dvo,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
- /* As long as the basics are set up, since we don't have clock dependencies
- * in the mode setup, we can just leave the registers alone and everything
- * will work fine.
- */
- /* don't do much */
- return;
+ /* As long as the basics are set up, since we don't have clock dependencies
+ * in the mode setup, we can just leave the registers alone and everything
+ * will work fine.
+ */
+ /* don't do much */
+ return;
}
/* set the tfp410 power state */
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 3c395a59da35..8e95d66800b0 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -98,12 +98,12 @@ static const char *get_pin_flag(struct drm_i915_gem_object *obj)
static const char *get_tiling_flag(struct drm_i915_gem_object *obj)
{
- switch (obj->tiling_mode) {
- default:
- case I915_TILING_NONE: return " ";
- case I915_TILING_X: return "X";
- case I915_TILING_Y: return "Y";
- }
+ switch (obj->tiling_mode) {
+ default:
+ case I915_TILING_NONE: return " ";
+ case I915_TILING_X: return "X";
+ case I915_TILING_Y: return "Y";
+ }
}
static const char *cache_level_str(int type)
@@ -217,7 +217,7 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
++mappable_count; \
} \
} \
-} while(0)
+} while (0)
static int i915_gem_object_info(struct seq_file *m, void* data)
{
@@ -1293,12 +1293,12 @@ i915_wedged_read(struct file *filp,
char buf[80];
int len;
- len = snprintf(buf, sizeof (buf),
+ len = snprintf(buf, sizeof(buf),
"wedged : %d\n",
atomic_read(&dev_priv->mm.wedged));
- if (len > sizeof (buf))
- len = sizeof (buf);
+ if (len > sizeof(buf))
+ len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
}
@@ -1314,7 +1314,7 @@ i915_wedged_write(struct file *filp,
int val = 1;
if (cnt > 0) {
- if (cnt > sizeof (buf) - 1)
+ if (cnt > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, ubuf, cnt))
@@ -1357,11 +1357,11 @@ i915_max_freq_read(struct file *filp,
char buf[80];
int len;
- len = snprintf(buf, sizeof (buf),
+ len = snprintf(buf, sizeof(buf),
"max freq: %d\n", dev_priv->max_delay * 50);
- if (len > sizeof (buf))
- len = sizeof (buf);
+ if (len > sizeof(buf))
+ len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
}
@@ -1378,7 +1378,7 @@ i915_max_freq_write(struct file *filp,
int val = 1;
if (cnt > 0) {
- if (cnt > sizeof (buf) - 1)
+ if (cnt > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, ubuf, cnt))
@@ -1432,12 +1432,12 @@ i915_cache_sharing_read(struct file *filp,
snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
mutex_unlock(&dev_priv->dev->struct_mutex);
- len = snprintf(buf, sizeof (buf),
+ len = snprintf(buf, sizeof(buf),
"%d\n", (snpcr & GEN6_MBC_SNPCR_MASK) >>
GEN6_MBC_SNPCR_SHIFT);
- if (len > sizeof (buf))
- len = sizeof (buf);
+ if (len > sizeof(buf))
+ len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
}
@@ -1455,7 +1455,7 @@ i915_cache_sharing_write(struct file *filp,
int val = 1;
if (cnt > 0) {
- if (cnt > sizeof (buf) - 1)
+ if (cnt > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, ubuf, cnt))
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 8a3942c4f099..2eac955dee18 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -884,7 +884,7 @@ static int i915_get_bridge_dev(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+ dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
if (!dev_priv->bridge_dev) {
DRM_ERROR("bridge device not found\n");
return -1;
@@ -1730,10 +1730,10 @@ static DEFINE_SPINLOCK(mchdev_lock);
*/
unsigned long i915_read_mch_val(void)
{
- struct drm_i915_private *dev_priv;
+ struct drm_i915_private *dev_priv;
unsigned long chipset_val, graphics_val, ret = 0;
- spin_lock(&mchdev_lock);
+ spin_lock(&mchdev_lock);
if (!i915_mch_dev)
goto out_unlock;
dev_priv = i915_mch_dev;
@@ -1744,9 +1744,9 @@ unsigned long i915_read_mch_val(void)
ret = chipset_val + graphics_val;
out_unlock:
- spin_unlock(&mchdev_lock);
+ spin_unlock(&mchdev_lock);
- return ret;
+ return ret;
}
EXPORT_SYMBOL_GPL(i915_read_mch_val);
@@ -1757,10 +1757,10 @@ EXPORT_SYMBOL_GPL(i915_read_mch_val);
*/
bool i915_gpu_raise(void)
{
- struct drm_i915_private *dev_priv;
+ struct drm_i915_private *dev_priv;
bool ret = true;
- spin_lock(&mchdev_lock);
+ spin_lock(&mchdev_lock);
if (!i915_mch_dev) {
ret = false;
goto out_unlock;
@@ -1771,9 +1771,9 @@ bool i915_gpu_raise(void)
dev_priv->max_delay--;
out_unlock:
- spin_unlock(&mchdev_lock);
+ spin_unlock(&mchdev_lock);
- return ret;
+ return ret;
}
EXPORT_SYMBOL_GPL(i915_gpu_raise);
@@ -1785,10 +1785,10 @@ EXPORT_SYMBOL_GPL(i915_gpu_raise);
*/
bool i915_gpu_lower(void)
{
- struct drm_i915_private *dev_priv;
+ struct drm_i915_private *dev_priv;
bool ret = true;
- spin_lock(&mchdev_lock);
+ spin_lock(&mchdev_lock);
if (!i915_mch_dev) {
ret = false;
goto out_unlock;
@@ -1799,9 +1799,9 @@ bool i915_gpu_lower(void)
dev_priv->max_delay++;
out_unlock:
- spin_unlock(&mchdev_lock);
+ spin_unlock(&mchdev_lock);
- return ret;
+ return ret;
}
EXPORT_SYMBOL_GPL(i915_gpu_lower);
@@ -1812,10 +1812,10 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower);
*/
bool i915_gpu_busy(void)
{
- struct drm_i915_private *dev_priv;
+ struct drm_i915_private *dev_priv;
bool ret = false;
- spin_lock(&mchdev_lock);
+ spin_lock(&mchdev_lock);
if (!i915_mch_dev)
goto out_unlock;
dev_priv = i915_mch_dev;
@@ -1823,9 +1823,9 @@ bool i915_gpu_busy(void)
ret = dev_priv->busy;
out_unlock:
- spin_unlock(&mchdev_lock);
+ spin_unlock(&mchdev_lock);
- return ret;
+ return ret;
}
EXPORT_SYMBOL_GPL(i915_gpu_busy);
@@ -1837,10 +1837,10 @@ EXPORT_SYMBOL_GPL(i915_gpu_busy);
*/
bool i915_gpu_turbo_disable(void)
{
- struct drm_i915_private *dev_priv;
+ struct drm_i915_private *dev_priv;
bool ret = true;
- spin_lock(&mchdev_lock);
+ spin_lock(&mchdev_lock);
if (!i915_mch_dev) {
ret = false;
goto out_unlock;
@@ -1853,9 +1853,9 @@ bool i915_gpu_turbo_disable(void)
ret = false;
out_unlock:
- spin_unlock(&mchdev_lock);
+ spin_unlock(&mchdev_lock);
- return ret;
+ return ret;
}
EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
@@ -1948,7 +1948,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
- dev_priv->mm.gtt_mapping =
+ dev_priv->mm.gtt_mapping =
io_mapping_create_wc(dev->agp->base, agp_size);
if (dev_priv->mm.gtt_mapping == NULL) {
ret = -EIO;
@@ -2035,7 +2035,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
spin_lock_init(&dev_priv->error_lock);
spin_lock_init(&dev_priv->rps_lock);
- if (IS_MOBILE(dev) || !IS_GEN2(dev))
+ if (IS_IVYBRIDGE(dev))
+ dev_priv->num_pipe = 3;
+ else if (IS_MOBILE(dev) || !IS_GEN2(dev))
dev_priv->num_pipe = 2;
else
dev_priv->num_pipe = 1;
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index f07e4252b708..4c8d681c2151 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -79,11 +79,11 @@ MODULE_PARM_DESC(lvds_downclock,
"Use panel (LVDS/eDP) downclocking for power savings "
"(default: false)");
-unsigned int i915_panel_use_ssc __read_mostly = 1;
+unsigned int i915_panel_use_ssc __read_mostly = -1;
module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
MODULE_PARM_DESC(lvds_use_ssc,
"Use Spread Spectrum Clock with panels [LVDS/eDP] "
- "(default: true)");
+ "(default: auto from VBT)");
int i915_vbt_sdvo_panel_type __read_mostly = -1;
module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
@@ -294,7 +294,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
#define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00
#define INTEL_PCH_PPT_DEVICE_ID_TYPE 0x1e00
-void intel_detect_pch (struct drm_device *dev)
+void intel_detect_pch(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct pci_dev *pch;
@@ -377,7 +377,7 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
{
- if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES ) {
+ if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
int loop = 500;
u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
@@ -471,6 +471,9 @@ static int i915_drm_thaw(struct drm_device *dev)
error = i915_gem_init_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex);
+ if (HAS_PCH_SPLIT(dev))
+ ironlake_init_pch_refclk(dev);
+
drm_mode_config_reset(dev);
drm_irq_install(dev);
@@ -770,12 +773,12 @@ static int i915_pm_poweroff(struct device *dev)
}
static const struct dev_pm_ops i915_pm_ops = {
- .suspend = i915_pm_suspend,
- .resume = i915_pm_resume,
- .freeze = i915_pm_freeze,
- .thaw = i915_pm_thaw,
- .poweroff = i915_pm_poweroff,
- .restore = i915_pm_resume,
+ .suspend = i915_pm_suspend,
+ .resume = i915_pm_resume,
+ .freeze = i915_pm_freeze,
+ .thaw = i915_pm_thaw,
+ .poweroff = i915_pm_poweroff,
+ .restore = i915_pm_resume,
};
static struct vm_operations_struct i915_gem_vm_ops = {
@@ -895,3 +898,43 @@ module_exit(i915_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
+
+/* We give fast paths for the really cool registers */
+#define NEEDS_FORCE_WAKE(dev_priv, reg) \
+ (((dev_priv)->info->gen >= 6) && \
+ ((reg) < 0x40000) && \
+ ((reg) != FORCEWAKE))
+
+#define __i915_read(x, y) \
+u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
+ u##x val = 0; \
+ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+ gen6_gt_force_wake_get(dev_priv); \
+ val = read##y(dev_priv->regs + reg); \
+ gen6_gt_force_wake_put(dev_priv); \
+ } else { \
+ val = read##y(dev_priv->regs + reg); \
+ } \
+ trace_i915_reg_rw(false, reg, val, sizeof(val)); \
+ return val; \
+}
+
+__i915_read(8, b)
+__i915_read(16, w)
+__i915_read(32, l)
+__i915_read(64, q)
+#undef __i915_read
+
+#define __i915_write(x, y) \
+void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
+ trace_i915_reg_rw(true, reg, val, sizeof(val)); \
+ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+ __gen6_gt_wait_for_fifo(dev_priv); \
+ } \
+ write##y(val, dev_priv->regs + reg); \
+}
+__i915_write(8, b)
+__i915_write(16, w)
+__i915_write(32, l)
+__i915_write(64, q)
+#undef __i915_write
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7916bd97d5c1..06a37f4fd74b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -139,7 +139,6 @@ struct sdvo_device_mapping {
u8 slave_addr;
u8 dvo_wiring;
u8 i2c_pin;
- u8 i2c_speed;
u8 ddc_pin;
};
@@ -209,6 +208,8 @@ struct drm_i915_display_funcs {
struct drm_display_mode *adjusted_mode,
int x, int y,
struct drm_framebuffer *old_fb);
+ void (*write_eld)(struct drm_connector *connector,
+ struct drm_crtc *crtc);
void (*fdi_link_train)(struct drm_crtc *crtc);
void (*init_clock_gating)(struct drm_device *dev);
void (*init_pch_clock_gating)(struct drm_device *dev);
@@ -226,26 +227,26 @@ struct drm_i915_display_funcs {
struct intel_device_info {
u8 gen;
- u8 is_mobile : 1;
- u8 is_i85x : 1;
- u8 is_i915g : 1;
- u8 is_i945gm : 1;
- u8 is_g33 : 1;
- u8 need_gfx_hws : 1;
- u8 is_g4x : 1;
- u8 is_pineview : 1;
- u8 is_broadwater : 1;
- u8 is_crestline : 1;
- u8 is_ivybridge : 1;
- u8 has_fbc : 1;
- u8 has_pipe_cxsr : 1;
- u8 has_hotplug : 1;
- u8 cursor_needs_physical : 1;
- u8 has_overlay : 1;
- u8 overlay_needs_physical : 1;
- u8 supports_tv : 1;
- u8 has_bsd_ring : 1;
- u8 has_blt_ring : 1;
+ u8 is_mobile:1;
+ u8 is_i85x:1;
+ u8 is_i915g:1;
+ u8 is_i945gm:1;
+ u8 is_g33:1;
+ u8 need_gfx_hws:1;
+ u8 is_g4x:1;
+ u8 is_pineview:1;
+ u8 is_broadwater:1;
+ u8 is_crestline:1;
+ u8 is_ivybridge:1;
+ u8 has_fbc:1;
+ u8 has_pipe_cxsr:1;
+ u8 has_hotplug:1;
+ u8 cursor_needs_physical:1;
+ u8 has_overlay:1;
+ u8 overlay_needs_physical:1;
+ u8 supports_tv:1;
+ u8 has_bsd_ring:1;
+ u8 has_blt_ring:1;
};
enum no_fbc_reason {
@@ -347,7 +348,6 @@ typedef struct drm_i915_private {
/* LVDS info */
int backlight_level; /* restore backlight to this value */
bool backlight_enabled;
- struct drm_display_mode *panel_fixed_mode;
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
@@ -357,6 +357,7 @@ typedef struct drm_i915_private {
unsigned int lvds_vbt:1;
unsigned int int_crt_support:1;
unsigned int lvds_use_ssc:1;
+ unsigned int display_clock_mode:1;
int lvds_ssc_freq;
struct {
int rate;
@@ -672,10 +673,9 @@ typedef struct drm_i915_private {
unsigned int lvds_border_bits;
/* Panel fitter placement and size for Ironlake+ */
u32 pch_pf_pos, pch_pf_size;
- int panel_t3, panel_t12;
- struct drm_crtc *plane_to_crtc_mapping[2];
- struct drm_crtc *pipe_to_crtc_mapping[2];
+ struct drm_crtc *plane_to_crtc_mapping[3];
+ struct drm_crtc *pipe_to_crtc_mapping[3];
wait_queue_head_t pending_flip_queue;
bool flip_pending_is_done;
@@ -759,19 +759,19 @@ struct drm_i915_gem_object {
* (has pending rendering), and is not set if it's on inactive (ready
* to be unbound).
*/
- unsigned int active : 1;
+ unsigned int active:1;
/**
* This is set if the object has been written to since last bound
* to the GTT
*/
- unsigned int dirty : 1;
+ unsigned int dirty:1;
/**
* This is set if the object has been written to since the last
* GPU flush.
*/
- unsigned int pending_gpu_write : 1;
+ unsigned int pending_gpu_write:1;
/**
* Fence register bits (if any) for this object. Will be set
@@ -780,18 +780,18 @@ struct drm_i915_gem_object {
*
* Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
*/
- signed int fence_reg : 5;
+ signed int fence_reg:5;
/**
* Advice: are the backing pages purgeable?
*/
- unsigned int madv : 2;
+ unsigned int madv:2;
/**
* Current tiling mode for the object.
*/
- unsigned int tiling_mode : 2;
- unsigned int tiling_changed : 1;
+ unsigned int tiling_mode:2;
+ unsigned int tiling_changed:1;
/** How many users have pinned this object in GTT space. The following
* users can each hold at most one reference: pwrite/pread, pin_ioctl
@@ -802,22 +802,22 @@ struct drm_i915_gem_object {
*
* In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
* bits with absolutely no headroom. So use 4 bits. */
- unsigned int pin_count : 4;
+ unsigned int pin_count:4;
#define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
/**
* Is the object at the current location in the gtt mappable and
* fenceable? Used to avoid costly recalculations.
*/
- unsigned int map_and_fenceable : 1;
+ unsigned int map_and_fenceable:1;
/**
* Whether the current gtt mapping needs to be mappable (and isn't just
* mappable by accident). Track pin and fault separate for a more
* accurate mappable working set.
*/
- unsigned int fault_mappable : 1;
- unsigned int pin_mappable : 1;
+ unsigned int fault_mappable:1;
+ unsigned int pin_mappable:1;
/*
* Is the GPU currently using a fence to access this buffer,
@@ -1056,7 +1056,7 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
void
i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
-void intel_enable_asle (struct drm_device *dev);
+void intel_enable_asle(struct drm_device *dev);
#ifdef CONFIG_DEBUG_FS
extern void i915_destroy_error_state(struct drm_device *dev);
@@ -1146,7 +1146,7 @@ int i915_gem_dumb_create(struct drm_file *file_priv,
int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
uint32_t handle, uint64_t *offset);
int i915_gem_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
- uint32_t handle);
+ uint32_t handle);
/**
* Returns true if seq1 is later than seq2.
*/
@@ -1301,10 +1301,11 @@ extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
extern bool intel_fbc_enabled(struct drm_device *dev);
extern void intel_disable_fbc(struct drm_device *dev);
extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
+extern void ironlake_init_pch_refclk(struct drm_device *dev);
extern void ironlake_enable_rc6(struct drm_device *dev);
extern void gen6_set_rps(struct drm_device *dev, u8 val);
-extern void intel_detect_pch (struct drm_device *dev);
-extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
+extern void intel_detect_pch(struct drm_device *dev);
+extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
/* overlay */
#ifdef CONFIG_DEBUG_FS
@@ -1354,18 +1355,7 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
((reg) != FORCEWAKE))
#define __i915_read(x, y) \
-static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
- u##x val = 0; \
- if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
- gen6_gt_force_wake_get(dev_priv); \
- val = read##y(dev_priv->regs + reg); \
- gen6_gt_force_wake_put(dev_priv); \
- } else { \
- val = read##y(dev_priv->regs + reg); \
- } \
- trace_i915_reg_rw(false, reg, val, sizeof(val)); \
- return val; \
-}
+ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
__i915_read(8, b)
__i915_read(16, w)
@@ -1374,13 +1364,8 @@ __i915_read(64, q)
#undef __i915_read
#define __i915_write(x, y) \
-static inline void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
- trace_i915_reg_rw(true, reg, val, sizeof(val)); \
- if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
- __gen6_gt_wait_for_fifo(dev_priv); \
- } \
- write##y(val, dev_priv->regs + reg); \
-}
+ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val);
+
__i915_write(8, b)
__i915_write(16, w)
__i915_write(32, l)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a546a71fb060..6651c36b6e8a 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -179,7 +179,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
mutex_unlock(&dev->struct_mutex);
args->aper_size = dev_priv->mm.gtt_total;
- args->aper_available_size = args->aper_size -pinned;
+ args->aper_available_size = args->aper_size - pinned;
return 0;
}
@@ -195,6 +195,8 @@ i915_gem_create(struct drm_file *file,
u32 handle;
size = roundup(size, PAGE_SIZE);
+ if (size == 0)
+ return -EINVAL;
/* Allocate the new object */
obj = i915_gem_alloc_object(dev, size);
@@ -800,11 +802,11 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev,
if (IS_ERR(page))
return PTR_ERR(page);
- vaddr = kmap_atomic(page, KM_USER0);
+ vaddr = kmap_atomic(page);
ret = __copy_from_user_inatomic(vaddr + page_offset,
user_data,
page_length);
- kunmap_atomic(vaddr, KM_USER0);
+ kunmap_atomic(vaddr);
set_page_dirty(page);
mark_page_accessed(page);
@@ -1265,74 +1267,6 @@ out:
}
/**
- * i915_gem_create_mmap_offset - create a fake mmap offset for an object
- * @obj: obj in question
- *
- * GEM memory mapping works by handing back to userspace a fake mmap offset
- * it can use in a subsequent mmap(2) call. The DRM core code then looks
- * up the object based on the offset and sets up the various memory mapping
- * structures.
- *
- * This routine allocates and attaches a fake offset for @obj.
- */
-static int
-i915_gem_create_mmap_offset(struct drm_i915_gem_object *obj)
-{
- struct drm_device *dev = obj->base.dev;
- struct drm_gem_mm *mm = dev->mm_private;
- struct drm_map_list *list;
- struct drm_local_map *map;
- int ret = 0;
-
- /* Set the object up for mmap'ing */
- list = &obj->base.map_list;
- list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
- if (!list->map)
- return -ENOMEM;
-
- map = list->map;
- map->type = _DRM_GEM;
- map->size = obj->base.size;
- map->handle = obj;
-
- /* Get a DRM GEM mmap offset allocated... */
- list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
- obj->base.size / PAGE_SIZE,
- 0, 0);
- if (!list->file_offset_node) {
- DRM_ERROR("failed to allocate offset for bo %d\n",
- obj->base.name);
- ret = -ENOSPC;
- goto out_free_list;
- }
-
- list->file_offset_node = drm_mm_get_block(list->file_offset_node,
- obj->base.size / PAGE_SIZE,
- 0);
- if (!list->file_offset_node) {
- ret = -ENOMEM;
- goto out_free_list;
- }
-
- list->hash.key = list->file_offset_node->start;
- ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
- if (ret) {
- DRM_ERROR("failed to add to map hash\n");
- goto out_free_mm;
- }
-
- return 0;
-
-out_free_mm:
- drm_mm_put_block(list->file_offset_node);
-out_free_list:
- kfree(list->map);
- list->map = NULL;
-
- return ret;
-}
-
-/**
* i915_gem_release_mmap - remove physical page mappings
* @obj: obj in question
*
@@ -1360,19 +1294,6 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
obj->fault_mappable = false;
}
-static void
-i915_gem_free_mmap_offset(struct drm_i915_gem_object *obj)
-{
- struct drm_device *dev = obj->base.dev;
- struct drm_gem_mm *mm = dev->mm_private;
- struct drm_map_list *list = &obj->base.map_list;
-
- drm_ht_remove_item(&mm->offset_hash, &list->hash);
- drm_mm_put_block(list->file_offset_node);
- kfree(list->map);
- list->map = NULL;
-}
-
static uint32_t
i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode)
{
@@ -1485,7 +1406,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
}
if (!obj->base.map_list.map) {
- ret = i915_gem_create_mmap_offset(obj);
+ ret = drm_gem_create_mmap_offset(&obj->base);
if (ret)
goto out;
}
@@ -1557,7 +1478,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
obj->pages[i] = page;
}
- if (obj->tiling_mode != I915_TILING_NONE)
+ if (i915_gem_object_needs_bit17_swizzle(obj))
i915_gem_object_do_bit_17_swizzle(obj);
return 0;
@@ -1579,7 +1500,7 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
BUG_ON(obj->madv == __I915_MADV_PURGED);
- if (obj->tiling_mode != I915_TILING_NONE)
+ if (i915_gem_object_needs_bit17_swizzle(obj))
i915_gem_object_save_bit_17_swizzle(obj);
if (obj->madv == I915_MADV_DONTNEED)
@@ -1856,7 +1777,7 @@ void i915_gem_reset(struct drm_device *dev)
* lost bo to the inactive list.
*/
while (!list_empty(&dev_priv->mm.flushing_list)) {
- obj= list_first_entry(&dev_priv->mm.flushing_list,
+ obj = list_first_entry(&dev_priv->mm.flushing_list,
struct drm_i915_gem_object,
mm_list);
@@ -1922,7 +1843,7 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
while (!list_empty(&ring->active_list)) {
struct drm_i915_gem_object *obj;
- obj= list_first_entry(&ring->active_list,
+ obj = list_first_entry(&ring->active_list,
struct drm_i915_gem_object,
ring_list);
@@ -2272,14 +2193,8 @@ int
i915_gpu_idle(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- bool lists_empty;
int ret, i;
- lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
- list_empty(&dev_priv->mm.active_list));
- if (lists_empty)
- return 0;
-
/* Flush everything onto the inactive list. */
for (i = 0; i < I915_NUM_RINGS; i++) {
ret = i915_ring_idle(&dev_priv->ring[i]);
@@ -2882,7 +2797,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
fenceable =
obj->gtt_space->size == fence_size &&
- (obj->gtt_space->start & (fence_alignment -1)) == 0;
+ (obj->gtt_space->start & (fence_alignment - 1)) == 0;
mappable =
obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;
@@ -3598,7 +3513,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
*/
request = kzalloc(sizeof(*request), GFP_KERNEL);
if (request)
- ret = i915_add_request(obj->ring, NULL,request);
+ ret = i915_add_request(obj->ring, NULL, request);
else
ret = -ENOMEM;
}
@@ -3623,7 +3538,7 @@ int
i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- return i915_gem_ring_throttle(dev, file_priv);
+ return i915_gem_ring_throttle(dev, file_priv);
}
int
@@ -3752,7 +3667,7 @@ static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj)
trace_i915_gem_object_destroy(obj);
if (obj->base.map_list.map)
- i915_gem_free_mmap_offset(obj);
+ drm_gem_free_mmap_offset(&obj->base);
drm_gem_object_release(&obj->base);
i915_gem_info_remove_obj(dev_priv, obj->base.size);
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c
index 8da1899bd24f..cc93cac242d6 100644
--- a/drivers/gpu/drm/i915/i915_gem_debug.c
+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
@@ -72,7 +72,7 @@ i915_verify_lists(struct drm_device *dev)
break;
} else if (!obj->active ||
(obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0 ||
- list_empty(&obj->gpu_write_list)){
+ list_empty(&obj->gpu_write_list)) {
DRM_ERROR("invalid flushing %p (a %d w %x gwl %d)\n",
obj,
obj->active,
@@ -157,7 +157,7 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle)
for (page = 0; page < obj->size / PAGE_SIZE; page++) {
int i;
- backing_map = kmap_atomic(obj->pages[page], KM_USER0);
+ backing_map = kmap_atomic(obj->pages[page]);
if (backing_map == NULL) {
DRM_ERROR("failed to map backing page\n");
@@ -181,13 +181,13 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle)
}
}
}
- kunmap_atomic(backing_map, KM_USER0);
+ kunmap_atomic(backing_map);
backing_map = NULL;
}
out:
if (backing_map != NULL)
- kunmap_atomic(backing_map, KM_USER0);
+ kunmap_atomic(backing_map);
iounmap(gtt_mapping);
/* give syslog time to catch up */
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index da05a2692a75..ead5d00f91b0 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -122,7 +122,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
goto found;
}
list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
- if (! obj->base.write_domain || obj->pin_count)
+ if (!obj->base.write_domain || obj->pin_count)
continue;
if (mark_free(obj, &unwind_list))
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 4934cf84c320..3693e83a97f3 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -784,7 +784,8 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
}
from->sync_seqno[idx] = seqno;
- return intel_ring_sync(to, from, seqno - 1);
+
+ return to->sync_to(to, from, seqno - 1);
}
static int
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 7a709cd8d543..6042c5e6d278 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -49,6 +49,28 @@ static unsigned int cache_level_to_agp_type(struct drm_device *dev,
}
}
+static bool do_idling(struct drm_i915_private *dev_priv)
+{
+ bool ret = dev_priv->mm.interruptible;
+
+ if (unlikely(dev_priv->mm.gtt->do_idle_maps)) {
+ dev_priv->mm.interruptible = false;
+ if (i915_gpu_idle(dev_priv->dev)) {
+ DRM_ERROR("Couldn't idle GPU\n");
+ /* Wait a bit, in hopes it avoids the hang */
+ udelay(10);
+ }
+ }
+
+ return ret;
+}
+
+static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
+{
+ if (unlikely(dev_priv->mm.gtt->do_idle_maps))
+ dev_priv->mm.interruptible = interruptible;
+}
+
void i915_gem_restore_gtt_mappings(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -117,6 +139,12 @@ void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
{
+ struct drm_device *dev = obj->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ bool interruptible;
+
+ interruptible = do_idling(dev_priv);
+
intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
obj->base.size >> PAGE_SHIFT);
@@ -124,4 +152,6 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
intel_gtt_unmap_memory(obj->sg_list, obj->num_sg);
obj->sg_list = NULL;
}
+
+ undo_idling(dev_priv, interruptible);
}
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 99c4faa59d8f..31d334d9d9da 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -92,7 +92,10 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
- if (INTEL_INFO(dev)->gen >= 5) {
+ if (INTEL_INFO(dev)->gen >= 6) {
+ swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+ swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+ } else if (IS_GEN5(dev)) {
/* On Ironlake whatever DRAM config, GPU always do
* same swizzling setup.
*/
@@ -440,14 +443,9 @@ i915_gem_swizzle_page(struct page *page)
void
i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
{
- struct drm_device *dev = obj->base.dev;
- drm_i915_private_t *dev_priv = dev->dev_private;
int page_count = obj->base.size >> PAGE_SHIFT;
int i;
- if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
- return;
-
if (obj->bit_17 == NULL)
return;
@@ -464,14 +462,9 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
void
i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
{
- struct drm_device *dev = obj->base.dev;
- drm_i915_private_t *dev_priv = dev->dev_private;
int page_count = obj->base.size >> PAGE_SHIFT;
int i;
- if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
- return;
-
if (obj->bit_17 == NULL) {
obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
sizeof(long), GFP_KERNEL);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 9cbb0cd8f46a..9ee2729fe5c6 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -383,6 +383,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
pm_iir = dev_priv->pm_iir;
dev_priv->pm_iir = 0;
pm_imr = I915_READ(GEN6_PMIMR);
+ I915_WRITE(GEN6_PMIMR, 0);
spin_unlock_irq(&dev_priv->rps_lock);
if (!pm_iir)
@@ -420,7 +421,6 @@ static void gen6_pm_rps_work(struct work_struct *work)
* an *extremely* unlikely race with gen6_rps_enable() that is prevented
* by holding struct_mutex for the duration of the write.
*/
- I915_WRITE(GEN6_PMIMR, pm_imr & ~pm_iir);
mutex_unlock(&dev_priv->dev->struct_mutex);
}
@@ -536,8 +536,9 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
unsigned long flags;
spin_lock_irqsave(&dev_priv->rps_lock, flags);
WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
- I915_WRITE(GEN6_PMIMR, pm_iir);
dev_priv->pm_iir |= pm_iir;
+ I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
+ POSTING_READ(GEN6_PMIMR);
spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
queue_work(dev_priv->wq, &dev_priv->rps_work);
}
@@ -649,8 +650,9 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
unsigned long flags;
spin_lock_irqsave(&dev_priv->rps_lock, flags);
WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
- I915_WRITE(GEN6_PMIMR, pm_iir);
dev_priv->pm_iir |= pm_iir;
+ I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
+ POSTING_READ(GEN6_PMIMR);
spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
queue_work(dev_priv->wq, &dev_priv->rps_work);
}
@@ -711,7 +713,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
page_count = src->base.size / PAGE_SIZE;
- dst = kmalloc(sizeof(*dst) + page_count * sizeof (u32 *), GFP_ATOMIC);
+ dst = kmalloc(sizeof(*dst) + page_count * sizeof(u32 *), GFP_ATOMIC);
if (dst == NULL)
return NULL;
@@ -1493,7 +1495,7 @@ static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
- DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
+ DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
return 0;
@@ -1541,7 +1543,7 @@ static void ironlake_disable_vblank(struct drm_device *dev, int pipe)
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
- DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
+ DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
@@ -1777,6 +1779,26 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
POSTING_READ(SDEIER);
}
+/*
+ * Enable digital hotplug on the PCH, and configure the DP short pulse
+ * duration to 2ms (which is the minimum in the Display Port spec)
+ *
+ * This register is the same on all known PCH chips.
+ */
+
+static void ironlake_enable_pch_hotplug(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ u32 hotplug;
+
+ hotplug = I915_READ(PCH_PORT_HOTPLUG);
+ hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK);
+ hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
+ hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
+ hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms;
+ I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
+}
+
static int ironlake_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1839,6 +1861,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
I915_WRITE(SDEIER, hotplug_mask);
POSTING_READ(SDEIER);
+ ironlake_enable_pch_hotplug(dev);
+
if (IS_IRONLAKE_M(dev)) {
/* Clear & enable PCU event interrupts */
I915_WRITE(DEIIR, DE_PCU_EVENT);
@@ -1896,6 +1920,8 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
I915_WRITE(SDEIER, hotplug_mask);
POSTING_READ(SDEIER);
+ ironlake_enable_pch_hotplug(dev);
+
return 0;
}
@@ -2020,6 +2046,10 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
I915_WRITE(GTIMR, 0xffffffff);
I915_WRITE(GTIER, 0x0);
I915_WRITE(GTIIR, I915_READ(GTIIR));
+
+ I915_WRITE(SDEIMR, 0xffffffff);
+ I915_WRITE(SDEIER, 0x0);
+ I915_WRITE(SDEIIR, I915_READ(SDEIIR));
}
static void i915_driver_irq_uninstall(struct drm_device * dev)
diff --git a/drivers/gpu/drm/i915/i915_mem.c b/drivers/gpu/drm/i915/i915_mem.c
index 83b7b81bb2b8..cc8f6d49cf20 100644
--- a/drivers/gpu/drm/i915/i915_mem.c
+++ b/drivers/gpu/drm/i915/i915_mem.c
@@ -202,7 +202,7 @@ static int init_heap(struct mem_block **heap, int start, int size)
blocks->next = blocks->prev = *heap;
memset(*heap, 0, sizeof(**heap));
- (*heap)->file_priv = (struct drm_file *) - 1;
+ (*heap)->file_priv = (struct drm_file *) -1;
(*heap)->next = (*heap)->prev = blocks;
return 0;
}
@@ -359,19 +359,19 @@ int i915_mem_init_heap(struct drm_device *dev, void *data,
return init_heap(heap, initheap->start, initheap->size);
}
-int i915_mem_destroy_heap( struct drm_device *dev, void *data,
- struct drm_file *file_priv )
+int i915_mem_destroy_heap(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_mem_destroy_heap_t *destroyheap = data;
struct mem_block **heap;
- if ( !dev_priv ) {
- DRM_ERROR( "called with no initialization\n" );
+ if (!dev_priv) {
+ DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
- heap = get_heap( dev_priv, destroyheap->region );
+ heap = get_heap(dev_priv, destroyheap->region);
if (!heap) {
DRM_ERROR("get_heap failed");
return -EFAULT;
@@ -382,6 +382,6 @@ int i915_mem_destroy_heap( struct drm_device *dev, void *data,
return -EFAULT;
}
- i915_mem_takedown( heap );
+ i915_mem_takedown(heap);
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 542453f7498c..5a09416e611f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -156,7 +156,7 @@
#define MI_SUSPEND_FLUSH MI_INSTR(0x0b, 0)
#define MI_SUSPEND_FLUSH_EN (1<<0)
#define MI_REPORT_HEAD MI_INSTR(0x07, 0)
-#define MI_OVERLAY_FLIP MI_INSTR(0x11,0)
+#define MI_OVERLAY_FLIP MI_INSTR(0x11, 0)
#define MI_OVERLAY_CONTINUE (0x0<<21)
#define MI_OVERLAY_ON (0x1<<21)
#define MI_OVERLAY_OFF (0x2<<21)
@@ -194,6 +194,13 @@
#define MI_SEMAPHORE_UPDATE (1<<21)
#define MI_SEMAPHORE_COMPARE (1<<20)
#define MI_SEMAPHORE_REGISTER (1<<18)
+#define MI_SEMAPHORE_SYNC_RV (2<<16)
+#define MI_SEMAPHORE_SYNC_RB (0<<16)
+#define MI_SEMAPHORE_SYNC_VR (0<<16)
+#define MI_SEMAPHORE_SYNC_VB (2<<16)
+#define MI_SEMAPHORE_SYNC_BR (2<<16)
+#define MI_SEMAPHORE_SYNC_BV (0<<16)
+#define MI_SEMAPHORE_SYNC_INVALID (1<<0)
/*
* 3D instructions used by the kernel
*/
@@ -235,16 +242,22 @@
#define ASYNC_FLIP (1<<22)
#define DISPLAY_PLANE_A (0<<20)
#define DISPLAY_PLANE_B (1<<20)
-#define GFX_OP_PIPE_CONTROL ((0x3<<29)|(0x3<<27)|(0x2<<24)|2)
-#define PIPE_CONTROL_QW_WRITE (1<<14)
-#define PIPE_CONTROL_DEPTH_STALL (1<<13)
-#define PIPE_CONTROL_WC_FLUSH (1<<12)
-#define PIPE_CONTROL_IS_FLUSH (1<<11) /* MBZ on Ironlake */
-#define PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */
-#define PIPE_CONTROL_ISP_DIS (1<<9)
-#define PIPE_CONTROL_NOTIFY (1<<8)
+#define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
+#define PIPE_CONTROL_CS_STALL (1<<20)
+#define PIPE_CONTROL_QW_WRITE (1<<14)
+#define PIPE_CONTROL_DEPTH_STALL (1<<13)
+#define PIPE_CONTROL_WRITE_FLUSH (1<<12)
+#define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */
+#define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on Ironlake */
+#define PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE (1<<10) /* GM45+ only */
+#define PIPE_CONTROL_INDIRECT_STATE_DISABLE (1<<9)
+#define PIPE_CONTROL_NOTIFY (1<<8)
+#define PIPE_CONTROL_VF_CACHE_INVALIDATE (1<<4)
+#define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1<<3)
+#define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1<<2)
+#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1<<1)
+#define PIPE_CONTROL_DEPTH_CACHE_FLUSH (1<<0)
#define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
-#define PIPE_CONTROL_STALL_EN (1<<1) /* in addr word, Ironlake+ only */
/*
@@ -296,6 +309,12 @@
#define RING_CTL(base) ((base)+0x3c)
#define RING_SYNC_0(base) ((base)+0x40)
#define RING_SYNC_1(base) ((base)+0x44)
+#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE))
+#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE))
+#define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE))
+#define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE))
+#define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE))
+#define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE))
#define RING_MAX_IDLE(base) ((base)+0x54)
#define RING_HWS_PGA(base) ((base)+0x80)
#define RING_HWS_PGA_GEN6(base) ((base)+0x2080)
@@ -470,7 +489,7 @@
/* Enables non-sequential data reads through arbiter
*/
-#define MI_ARB_DUAL_DATA_PHASE_DISABLE (1 << 9)
+#define MI_ARB_DUAL_DATA_PHASE_DISABLE (1 << 9)
/* Disable FSB snooping of cacheable write cycles from binner/render
* command stream
@@ -626,7 +645,7 @@
#define ILK_DISPLAY_CHICKEN1 0x42000
#define ILK_FBCQ_DIS (1<<22)
-#define ILK_PABSTRETCH_DIS (1<<21)
+#define ILK_PABSTRETCH_DIS (1<<21)
/*
@@ -2358,7 +2377,7 @@
#define DSPFW1 0x70034
#define DSPFW_SR_SHIFT 23
-#define DSPFW_SR_MASK (0x1ff<<23)
+#define DSPFW_SR_MASK (0x1ff<<23)
#define DSPFW_CURSORB_SHIFT 16
#define DSPFW_CURSORB_MASK (0x3f<<16)
#define DSPFW_PLANEB_SHIFT 8
@@ -2416,6 +2435,7 @@
#define WM0_PIPE_CURSOR_MASK (0x1f)
#define WM0_PIPEB_ILK 0x45104
+#define WM0_PIPEC_IVB 0x45200
#define WM1_LP_ILK 0x45108
#define WM1_LP_SR_EN (1<<31)
#define WM1_LP_LATENCY_SHIFT 24
@@ -2554,10 +2574,18 @@
#define _CURBBASE 0x700c4
#define _CURBPOS 0x700c8
+#define _CURBCNTR_IVB 0x71080
+#define _CURBBASE_IVB 0x71084
+#define _CURBPOS_IVB 0x71088
+
#define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR)
#define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE)
#define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS)
+#define CURCNTR_IVB(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR_IVB)
+#define CURBASE_IVB(pipe) _PIPE(pipe, _CURABASE, _CURBBASE_IVB)
+#define CURPOS_IVB(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS_IVB)
+
/* Display A control */
#define _DSPACNTR 0x70180
#define DISPLAY_PLANE_ENABLE (1<<31)
@@ -2903,12 +2931,13 @@
#define SDEIER 0xc400c
/* digital port hotplug */
-#define PCH_PORT_HOTPLUG 0xc4030
+#define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */
#define PORTD_HOTPLUG_ENABLE (1 << 20)
#define PORTD_PULSE_DURATION_2ms (0)
#define PORTD_PULSE_DURATION_4_5ms (1 << 18)
#define PORTD_PULSE_DURATION_6ms (2 << 18)
#define PORTD_PULSE_DURATION_100ms (3 << 18)
+#define PORTD_PULSE_DURATION_MASK (3 << 18)
#define PORTD_HOTPLUG_NO_DETECT (0)
#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
#define PORTD_HOTPLUG_LONG_DETECT (1 << 17)
@@ -2917,6 +2946,7 @@
#define PORTC_PULSE_DURATION_4_5ms (1 << 10)
#define PORTC_PULSE_DURATION_6ms (2 << 10)
#define PORTC_PULSE_DURATION_100ms (3 << 10)
+#define PORTC_PULSE_DURATION_MASK (3 << 10)
#define PORTC_HOTPLUG_NO_DETECT (0)
#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
#define PORTC_HOTPLUG_LONG_DETECT (1 << 9)
@@ -2925,6 +2955,7 @@
#define PORTB_PULSE_DURATION_4_5ms (1 << 2)
#define PORTB_PULSE_DURATION_6ms (2 << 2)
#define PORTB_PULSE_DURATION_100ms (3 << 2)
+#define PORTB_PULSE_DURATION_MASK (3 << 2)
#define PORTB_HOTPLUG_NO_DETECT (0)
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTB_HOTPLUG_LONG_DETECT (1 << 1)
@@ -2945,15 +2976,15 @@
#define _PCH_DPLL_A 0xc6014
#define _PCH_DPLL_B 0xc6018
-#define PCH_DPLL(pipe) _PIPE(pipe, _PCH_DPLL_A, _PCH_DPLL_B)
+#define PCH_DPLL(pipe) (pipe == 0 ? _PCH_DPLL_A : _PCH_DPLL_B)
#define _PCH_FPA0 0xc6040
#define FP_CB_TUNE (0x3<<22)
#define _PCH_FPA1 0xc6044
#define _PCH_FPB0 0xc6048
#define _PCH_FPB1 0xc604c
-#define PCH_FP0(pipe) _PIPE(pipe, _PCH_FPA0, _PCH_FPB0)
-#define PCH_FP1(pipe) _PIPE(pipe, _PCH_FPA1, _PCH_FPB1)
+#define PCH_FP0(pipe) (pipe == 0 ? _PCH_FPA0 : _PCH_FPB0)
+#define PCH_FP1(pipe) (pipe == 0 ? _PCH_FPA1 : _PCH_FPB1)
#define PCH_DPLL_TEST 0xc606c
@@ -3167,6 +3198,7 @@
#define FDI_LINK_TRAIN_NONE_IVB (3<<8)
/* both Tx and Rx */
+#define FDI_COMPOSITE_SYNC (1<<11)
#define FDI_LINK_TRAIN_AUTO (1<<10)
#define FDI_SCRAMBLING_ENABLE (0<<7)
#define FDI_SCRAMBLING_DISABLE (1<<7)
@@ -3308,15 +3340,35 @@
#define PCH_PP_STATUS 0xc7200
#define PCH_PP_CONTROL 0xc7204
#define PANEL_UNLOCK_REGS (0xabcd << 16)
+#define PANEL_UNLOCK_MASK (0xffff << 16)
#define EDP_FORCE_VDD (1 << 3)
#define EDP_BLC_ENABLE (1 << 2)
#define PANEL_POWER_RESET (1 << 1)
#define PANEL_POWER_OFF (0 << 0)
#define PANEL_POWER_ON (1 << 0)
#define PCH_PP_ON_DELAYS 0xc7208
+#define PANEL_PORT_SELECT_MASK (3 << 30)
+#define PANEL_PORT_SELECT_LVDS (0 << 30)
+#define PANEL_PORT_SELECT_DPA (1 << 30)
#define EDP_PANEL (1 << 30)
+#define PANEL_PORT_SELECT_DPC (2 << 30)
+#define PANEL_PORT_SELECT_DPD (3 << 30)
+#define PANEL_POWER_UP_DELAY_MASK (0x1fff0000)
+#define PANEL_POWER_UP_DELAY_SHIFT 16
+#define PANEL_LIGHT_ON_DELAY_MASK (0x1fff)
+#define PANEL_LIGHT_ON_DELAY_SHIFT 0
+
#define PCH_PP_OFF_DELAYS 0xc720c
+#define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000)
+#define PANEL_POWER_DOWN_DELAY_SHIFT 16
+#define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff)
+#define PANEL_LIGHT_OFF_DELAY_SHIFT 0
+
#define PCH_PP_DIVISOR 0xc7210
+#define PP_REFERENCE_DIVIDER_MASK (0xffffff00)
+#define PP_REFERENCE_DIVIDER_SHIFT 8
+#define PANEL_POWER_CYCLE_DELAY_MASK (0x1f)
+#define PANEL_POWER_CYCLE_DELAY_SHIFT 0
#define PCH_DP_B 0xe4100
#define PCH_DPB_AUX_CH_CTL 0xe4110
@@ -3470,4 +3522,29 @@
#define GEN6_PCODE_DATA 0x138128
#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8
+#define G4X_AUD_VID_DID 0x62020
+#define INTEL_AUDIO_DEVCL 0x808629FB
+#define INTEL_AUDIO_DEVBLC 0x80862801
+#define INTEL_AUDIO_DEVCTG 0x80862802
+
+#define G4X_AUD_CNTL_ST 0x620B4
+#define G4X_ELDV_DEVCL_DEVBLC (1 << 13)
+#define G4X_ELDV_DEVCTG (1 << 14)
+#define G4X_ELD_ADDR (0xf << 5)
+#define G4X_ELD_ACK (1 << 4)
+#define G4X_HDMIW_HDMIEDID 0x6210C
+
+#define GEN5_HDMIW_HDMIEDID_A 0xE2050
+#define GEN5_AUD_CNTL_ST_A 0xE20B4
+#define GEN5_ELD_BUFFER_SIZE (0x1f << 10)
+#define GEN5_ELD_ADDRESS (0x1f << 5)
+#define GEN5_ELD_ACK (1 << 4)
+#define GEN5_AUD_CNTL_ST2 0xE20C0
+#define GEN5_ELD_VALIDB (1 << 0)
+#define GEN5_CP_READYB (1 << 1)
+
+#define GEN7_HDMIW_HDMIEDID_A 0xE5050
+#define GEN7_AUD_CNTRL_ST_A 0xE50B4
+#define GEN7_AUD_CNTRL_ST2 0xE50C0
+
#endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index f10742359ec9..f8f602d76650 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -60,7 +60,7 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
else
array = dev_priv->save_palette_b;
- for(i = 0; i < 256; i++)
+ for (i = 0; i < 256; i++)
array[i] = I915_READ(reg + (i << 2));
}
@@ -82,7 +82,7 @@ static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
else
array = dev_priv->save_palette_b;
- for(i = 0; i < 256; i++)
+ for (i = 0; i < 256; i++)
I915_WRITE(reg + (i << 2), array[i]);
}
@@ -887,10 +887,10 @@ int i915_restore_state(struct drm_device *dev)
mutex_lock(&dev->struct_mutex);
/* Cache mode state */
- I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
+ I915_WRITE(CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
/* Memory arbitration state */
- I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
+ I915_WRITE(MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
for (i = 0; i < 16; i++) {
I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index d623fefbfaca..dac7bba4d9da 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -385,29 +385,29 @@ TRACE_EVENT(i915_flip_complete,
);
TRACE_EVENT(i915_reg_rw,
- TP_PROTO(bool write, u32 reg, u64 val, int len),
-
- TP_ARGS(write, reg, val, len),
-
- TP_STRUCT__entry(
- __field(u64, val)
- __field(u32, reg)
- __field(u16, write)
- __field(u16, len)
- ),
-
- TP_fast_assign(
- __entry->val = (u64)val;
- __entry->reg = reg;
- __entry->write = write;
- __entry->len = len;
- ),
-
- TP_printk("%s reg=0x%x, len=%d, val=(0x%x, 0x%x)",
- __entry->write ? "write" : "read",
- __entry->reg, __entry->len,
- (u32)(__entry->val & 0xffffffff),
- (u32)(__entry->val >> 32))
+ TP_PROTO(bool write, u32 reg, u64 val, int len),
+
+ TP_ARGS(write, reg, val, len),
+
+ TP_STRUCT__entry(
+ __field(u64, val)
+ __field(u32, reg)
+ __field(u16, write)
+ __field(u16, len)
+ ),
+
+ TP_fast_assign(
+ __entry->val = (u64)val;
+ __entry->reg = reg;
+ __entry->write = write;
+ __entry->len = len;
+ ),
+
+ TP_printk("%s reg=0x%x, len=%d, val=(0x%x, 0x%x)",
+ __entry->write ? "write" : "read",
+ __entry->reg, __entry->len,
+ (u32)(__entry->val & 0xffffffff),
+ (u32)(__entry->val >> 32))
);
#endif /* _I915_TRACE_H_ */
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
index 2cb8e0b9f1ee..cb912106d1a2 100644
--- a/drivers/gpu/drm/i915/intel_acpi.c
+++ b/drivers/gpu/drm/i915/intel_acpi.c
@@ -64,7 +64,7 @@ static int intel_dsm(acpi_handle handle, int func, int arg)
case ACPI_TYPE_BUFFER:
if (obj->buffer.length == 4) {
- result =(obj->buffer.pointer[0] |
+ result = (obj->buffer.pointer[0] |
(obj->buffer.pointer[1] << 8) |
(obj->buffer.pointer[2] << 16) |
(obj->buffer.pointer[3] << 24));
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 61abef8a8119..63880e2e5cfd 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2006 Intel Corporation
+ * Copyright © 2006 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -309,6 +309,13 @@ parse_general_features(struct drm_i915_private *dev_priv,
dev_priv->lvds_use_ssc = general->enable_ssc;
dev_priv->lvds_ssc_freq =
intel_bios_ssc_frequency(dev, general->ssc_freq);
+ dev_priv->display_clock_mode = general->display_clock_mode;
+ DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d\n",
+ dev_priv->int_tv_support,
+ dev_priv->int_crt_support,
+ dev_priv->lvds_use_ssc,
+ dev_priv->lvds_ssc_freq,
+ dev_priv->display_clock_mode);
}
}
@@ -381,7 +388,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
if (p_child->dvo_port != DEVICE_PORT_DVOB &&
p_child->dvo_port != DEVICE_PORT_DVOC) {
/* skip the incorrect SDVO port */
- DRM_DEBUG_KMS("Incorrect SDVO port. Skip it \n");
+ DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
continue;
}
DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
@@ -396,15 +403,13 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
p_mapping->dvo_wiring = p_child->dvo_wiring;
p_mapping->ddc_pin = p_child->ddc_pin;
p_mapping->i2c_pin = p_child->i2c_pin;
- p_mapping->i2c_speed = p_child->i2c_speed;
p_mapping->initialized = 1;
- DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n",
+ DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
p_mapping->dvo_port,
p_mapping->slave_addr,
p_mapping->dvo_wiring,
p_mapping->ddc_pin,
- p_mapping->i2c_pin,
- p_mapping->i2c_speed);
+ p_mapping->i2c_pin);
} else {
DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
"two SDVO device.\n");
@@ -564,7 +569,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
count++;
}
if (!count) {
- DRM_DEBUG_KMS("no child dev is parsed from VBT \n");
+ DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
return;
}
dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL);
@@ -610,7 +615,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
/* Default to using SSC */
dev_priv->lvds_use_ssc = 1;
dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
- DRM_DEBUG("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
+ DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
/* eDP data */
dev_priv->edp.bpp = 18;
@@ -639,7 +644,7 @@ intel_parse_bios(struct drm_device *dev)
if (dev_priv->opregion.vbt) {
struct vbt_header *vbt = dev_priv->opregion.vbt;
if (memcmp(vbt->signature, "$VBT", 4) == 0) {
- DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n",
+ DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
vbt->signature);
bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
} else
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index 5f8e4edcbbb9..8af3735e27c6 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 2006 Intel Corporation
+ * Copyright © 2006 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -120,7 +120,9 @@ struct bdb_general_features {
u8 ssc_freq:1;
u8 enable_lfp_on_override:1;
u8 disable_ssc_ddt:1;
- u8 rsvd8:3; /* finish byte */
+ u8 rsvd7:1;
+ u8 display_clock_mode:1;
+ u8 rsvd8:1; /* finish byte */
/* bits 3 */
u8 disable_smooth_vision:1;
@@ -133,7 +135,10 @@ struct bdb_general_features {
/* bits 5 */
u8 int_crt_support:1;
u8 int_tv_support:1;
- u8 rsvd11:6; /* finish byte */
+ u8 int_efp_support:1;
+ u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */
+ u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */
+ u8 rsvd11:3; /* finish byte */
} __attribute__((packed));
/* pre-915 */
@@ -197,8 +202,7 @@ struct bdb_general_features {
struct child_device_config {
u16 handle;
u16 device_type;
- u8 i2c_speed;
- u8 rsvd[9];
+ u8 device_id[10]; /* ascii string */
u16 addin_offset;
u8 dvo_port; /* See Device_PORT_* above */
u8 i2c_pin;
@@ -240,7 +244,7 @@ struct bdb_general_definitions {
* And the device num is related with the size of general definition
* block. It is obtained by using the following formula:
* number = (block_size - sizeof(bdb_general_definitions))/
- * sizeof(child_device_config);
+ * sizeof(child_device_config);
*/
struct child_device_config devices[0];
} __attribute__((packed));
@@ -446,11 +450,11 @@ struct bdb_driver_features {
#define EDP_VSWING_1_2V 3
struct edp_power_seq {
- u16 t3;
- u16 t7;
+ u16 t1_t3;
+ u16 t8;
u16 t9;
u16 t10;
- u16 t12;
+ u16 t11_t12;
} __attribute__ ((packed));
struct edp_link_params {
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 0979d8877880..fee0ad02c6d0 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -69,7 +69,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
temp &= ~ADPA_DAC_ENABLE;
- switch(mode) {
+ switch (mode) {
case DRM_MODE_DPMS_ON:
temp |= ADPA_DAC_ENABLE;
break;
@@ -152,17 +152,13 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
- if (intel_crtc->pipe == 0) {
- if (HAS_PCH_CPT(dev))
- adpa |= PORT_TRANS_A_SEL_CPT;
- else
- adpa |= ADPA_PIPE_A_SELECT;
- } else {
- if (HAS_PCH_CPT(dev))
- adpa |= PORT_TRANS_B_SEL_CPT;
- else
- adpa |= ADPA_PIPE_B_SELECT;
- }
+ /* For CPT allow 3 pipe config, for others just use A or B */
+ if (HAS_PCH_CPT(dev))
+ adpa |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
+ else if (intel_crtc->pipe == 0)
+ adpa |= ADPA_PIPE_A_SELECT;
+ else
+ adpa |= ADPA_PIPE_B_SELECT;
if (!HAS_PCH_SPLIT(dev))
I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 04411ad2e779..981b1f1c04d8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -31,6 +31,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/vgaarb.h>
+#include <drm/drm_edid.h>
#include "drmP.h"
#include "intel_drv.h"
#include "i915_drm.h"
@@ -42,39 +43,39 @@
#define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
-bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
+bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
static void intel_update_watermarks(struct drm_device *dev);
static void intel_increase_pllclock(struct drm_crtc *crtc);
static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
typedef struct {
- /* given values */
- int n;
- int m1, m2;
- int p1, p2;
- /* derived values */
- int dot;
- int vco;
- int m;
- int p;
+ /* given values */
+ int n;
+ int m1, m2;
+ int p1, p2;
+ /* derived values */
+ int dot;
+ int vco;
+ int m;
+ int p;
} intel_clock_t;
typedef struct {
- int min, max;
+ int min, max;
} intel_range_t;
typedef struct {
- int dot_limit;
- int p2_slow, p2_fast;
+ int dot_limit;
+ int p2_slow, p2_fast;
} intel_p2_t;
#define INTEL_P2_NUM 2
typedef struct intel_limit intel_limit_t;
struct intel_limit {
- intel_range_t dot, vco, n, m, m1, m2, p, p1;
- intel_p2_t p2;
- bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
- int, int, intel_clock_t *);
+ intel_range_t dot, vco, n, m, m1, m2, p, p1;
+ intel_p2_t p2;
+ bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
+ int, int, intel_clock_t *);
};
/* FDI */
@@ -105,56 +106,56 @@ intel_fdi_link_freq(struct drm_device *dev)
}
static const intel_limit_t intel_limits_i8xx_dvo = {
- .dot = { .min = 25000, .max = 350000 },
- .vco = { .min = 930000, .max = 1400000 },
- .n = { .min = 3, .max = 16 },
- .m = { .min = 96, .max = 140 },
- .m1 = { .min = 18, .max = 26 },
- .m2 = { .min = 6, .max = 16 },
- .p = { .min = 4, .max = 128 },
- .p1 = { .min = 2, .max = 33 },
+ .dot = { .min = 25000, .max = 350000 },
+ .vco = { .min = 930000, .max = 1400000 },
+ .n = { .min = 3, .max = 16 },
+ .m = { .min = 96, .max = 140 },
+ .m1 = { .min = 18, .max = 26 },
+ .m2 = { .min = 6, .max = 16 },
+ .p = { .min = 4, .max = 128 },
+ .p1 = { .min = 2, .max = 33 },
.p2 = { .dot_limit = 165000,
.p2_slow = 4, .p2_fast = 2 },
.find_pll = intel_find_best_PLL,
};
static const intel_limit_t intel_limits_i8xx_lvds = {
- .dot = { .min = 25000, .max = 350000 },
- .vco = { .min = 930000, .max = 1400000 },
- .n = { .min = 3, .max = 16 },
- .m = { .min = 96, .max = 140 },
- .m1 = { .min = 18, .max = 26 },
- .m2 = { .min = 6, .max = 16 },
- .p = { .min = 4, .max = 128 },
- .p1 = { .min = 1, .max = 6 },
+ .dot = { .min = 25000, .max = 350000 },
+ .vco = { .min = 930000, .max = 1400000 },
+ .n = { .min = 3, .max = 16 },
+ .m = { .min = 96, .max = 140 },
+ .m1 = { .min = 18, .max = 26 },
+ .m2 = { .min = 6, .max = 16 },
+ .p = { .min = 4, .max = 128 },
+ .p1 = { .min = 1, .max = 6 },
.p2 = { .dot_limit = 165000,
.p2_slow = 14, .p2_fast = 7 },
.find_pll = intel_find_best_PLL,
};
static const intel_limit_t intel_limits_i9xx_sdvo = {
- .dot = { .min = 20000, .max = 400000 },
- .vco = { .min = 1400000, .max = 2800000 },
- .n = { .min = 1, .max = 6 },
- .m = { .min = 70, .max = 120 },
- .m1 = { .min = 10, .max = 22 },
- .m2 = { .min = 5, .max = 9 },
- .p = { .min = 5, .max = 80 },
- .p1 = { .min = 1, .max = 8 },
+ .dot = { .min = 20000, .max = 400000 },
+ .vco = { .min = 1400000, .max = 2800000 },
+ .n = { .min = 1, .max = 6 },
+ .m = { .min = 70, .max = 120 },
+ .m1 = { .min = 10, .max = 22 },
+ .m2 = { .min = 5, .max = 9 },
+ .p = { .min = 5, .max = 80 },
+ .p1 = { .min = 1, .max = 8 },
.p2 = { .dot_limit = 200000,
.p2_slow = 10, .p2_fast = 5 },
.find_pll = intel_find_best_PLL,
};
static const intel_limit_t intel_limits_i9xx_lvds = {
- .dot = { .min = 20000, .max = 400000 },
- .vco = { .min = 1400000, .max = 2800000 },
- .n = { .min = 1, .max = 6 },
- .m = { .min = 70, .max = 120 },
- .m1 = { .min = 10, .max = 22 },
- .m2 = { .min = 5, .max = 9 },
- .p = { .min = 7, .max = 98 },
- .p1 = { .min = 1, .max = 8 },
+ .dot = { .min = 20000, .max = 400000 },
+ .vco = { .min = 1400000, .max = 2800000 },
+ .n = { .min = 1, .max = 6 },
+ .m = { .min = 70, .max = 120 },
+ .m1 = { .min = 10, .max = 22 },
+ .m2 = { .min = 5, .max = 9 },
+ .p = { .min = 7, .max = 98 },
+ .p1 = { .min = 1, .max = 8 },
.p2 = { .dot_limit = 112000,
.p2_slow = 14, .p2_fast = 7 },
.find_pll = intel_find_best_PLL,
@@ -222,44 +223,44 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
};
static const intel_limit_t intel_limits_g4x_display_port = {
- .dot = { .min = 161670, .max = 227000 },
- .vco = { .min = 1750000, .max = 3500000},
- .n = { .min = 1, .max = 2 },
- .m = { .min = 97, .max = 108 },
- .m1 = { .min = 0x10, .max = 0x12 },
- .m2 = { .min = 0x05, .max = 0x06 },
- .p = { .min = 10, .max = 20 },
- .p1 = { .min = 1, .max = 2},
- .p2 = { .dot_limit = 0,
+ .dot = { .min = 161670, .max = 227000 },
+ .vco = { .min = 1750000, .max = 3500000},
+ .n = { .min = 1, .max = 2 },
+ .m = { .min = 97, .max = 108 },
+ .m1 = { .min = 0x10, .max = 0x12 },
+ .m2 = { .min = 0x05, .max = 0x06 },
+ .p = { .min = 10, .max = 20 },
+ .p1 = { .min = 1, .max = 2},
+ .p2 = { .dot_limit = 0,
.p2_slow = 10, .p2_fast = 10 },
- .find_pll = intel_find_pll_g4x_dp,
+ .find_pll = intel_find_pll_g4x_dp,
};
static const intel_limit_t intel_limits_pineview_sdvo = {
- .dot = { .min = 20000, .max = 400000},
- .vco = { .min = 1700000, .max = 3500000 },
+ .dot = { .min = 20000, .max = 400000},
+ .vco = { .min = 1700000, .max = 3500000 },
/* Pineview's Ncounter is a ring counter */
- .n = { .min = 3, .max = 6 },
- .m = { .min = 2, .max = 256 },
+ .n = { .min = 3, .max = 6 },
+ .m = { .min = 2, .max = 256 },
/* Pineview only has one combined m divider, which we treat as m2. */
- .m1 = { .min = 0, .max = 0 },
- .m2 = { .min = 0, .max = 254 },
- .p = { .min = 5, .max = 80 },
- .p1 = { .min = 1, .max = 8 },
+ .m1 = { .min = 0, .max = 0 },
+ .m2 = { .min = 0, .max = 254 },
+ .p = { .min = 5, .max = 80 },
+ .p1 = { .min = 1, .max = 8 },
.p2 = { .dot_limit = 200000,
.p2_slow = 10, .p2_fast = 5 },
.find_pll = intel_find_best_PLL,
};
static const intel_limit_t intel_limits_pineview_lvds = {
- .dot = { .min = 20000, .max = 400000 },
- .vco = { .min = 1700000, .max = 3500000 },
- .n = { .min = 3, .max = 6 },
- .m = { .min = 2, .max = 256 },
- .m1 = { .min = 0, .max = 0 },
- .m2 = { .min = 0, .max = 254 },
- .p = { .min = 7, .max = 112 },
- .p1 = { .min = 1, .max = 8 },
+ .dot = { .min = 20000, .max = 400000 },
+ .vco = { .min = 1700000, .max = 3500000 },
+ .n = { .min = 3, .max = 6 },
+ .m = { .min = 2, .max = 256 },
+ .m1 = { .min = 0, .max = 0 },
+ .m2 = { .min = 0, .max = 254 },
+ .p = { .min = 7, .max = 112 },
+ .p1 = { .min = 1, .max = 8 },
.p2 = { .dot_limit = 112000,
.p2_slow = 14, .p2_fast = 14 },
.find_pll = intel_find_best_PLL,
@@ -321,7 +322,7 @@ static const intel_limit_t intel_limits_ironlake_single_lvds_100m = {
.m1 = { .min = 12, .max = 22 },
.m2 = { .min = 5, .max = 9 },
.p = { .min = 28, .max = 112 },
- .p1 = { .min = 2,.max = 8 },
+ .p1 = { .min = 2, .max = 8 },
.p2 = { .dot_limit = 225000,
.p2_slow = 14, .p2_fast = 14 },
.find_pll = intel_g4x_find_best_PLL,
@@ -335,24 +336,24 @@ static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
.m1 = { .min = 12, .max = 22 },
.m2 = { .min = 5, .max = 9 },
.p = { .min = 14, .max = 42 },
- .p1 = { .min = 2,.max = 6 },
+ .p1 = { .min = 2, .max = 6 },
.p2 = { .dot_limit = 225000,
.p2_slow = 7, .p2_fast = 7 },
.find_pll = intel_g4x_find_best_PLL,
};
static const intel_limit_t intel_limits_ironlake_display_port = {
- .dot = { .min = 25000, .max = 350000 },
- .vco = { .min = 1760000, .max = 3510000},
- .n = { .min = 1, .max = 2 },
- .m = { .min = 81, .max = 90 },
- .m1 = { .min = 12, .max = 22 },
- .m2 = { .min = 5, .max = 9 },
- .p = { .min = 10, .max = 20 },
- .p1 = { .min = 1, .max = 2},
- .p2 = { .dot_limit = 0,
+ .dot = { .min = 25000, .max = 350000 },
+ .vco = { .min = 1760000, .max = 3510000},
+ .n = { .min = 1, .max = 2 },
+ .m = { .min = 81, .max = 90 },
+ .m1 = { .min = 12, .max = 22 },
+ .m2 = { .min = 5, .max = 9 },
+ .p = { .min = 10, .max = 20 },
+ .p1 = { .min = 1, .max = 2},
+ .p2 = { .dot_limit = 0,
.p2_slow = 10, .p2_fast = 10 },
- .find_pll = intel_find_pll_ironlake_dp,
+ .find_pll = intel_find_pll_ironlake_dp,
};
static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
@@ -404,7 +405,7 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
limit = &intel_limits_g4x_hdmi;
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
limit = &intel_limits_g4x_sdvo;
- } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+ } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
limit = &intel_limits_g4x_display_port;
} else /* The option is for other outputs */
limit = &intel_limits_i9xx_sdvo;
@@ -488,26 +489,26 @@ static bool intel_PLL_is_valid(struct drm_device *dev,
const intel_clock_t *clock)
{
if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
- INTELPllInvalid ("p1 out of range\n");
+ INTELPllInvalid("p1 out of range\n");
if (clock->p < limit->p.min || limit->p.max < clock->p)
- INTELPllInvalid ("p out of range\n");
+ INTELPllInvalid("p out of range\n");
if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
- INTELPllInvalid ("m2 out of range\n");
+ INTELPllInvalid("m2 out of range\n");
if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
- INTELPllInvalid ("m1 out of range\n");
+ INTELPllInvalid("m1 out of range\n");
if (clock->m1 <= clock->m2 && !IS_PINEVIEW(dev))
- INTELPllInvalid ("m1 <= m2\n");
+ INTELPllInvalid("m1 <= m2\n");
if (clock->m < limit->m.min || limit->m.max < clock->m)
- INTELPllInvalid ("m out of range\n");
+ INTELPllInvalid("m out of range\n");
if (clock->n < limit->n.min || limit->n.max < clock->n)
- INTELPllInvalid ("n out of range\n");
+ INTELPllInvalid("n out of range\n");
if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
- INTELPllInvalid ("vco out of range\n");
+ INTELPllInvalid("vco out of range\n");
/* XXX: We may need to be checking "Dot clock" depending on the multiplier,
* connector, etc., rather than just a single range.
*/
if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
- INTELPllInvalid ("dot out of range\n");
+ INTELPllInvalid("dot out of range\n");
return true;
}
@@ -542,7 +543,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
clock.p2 = limit->p2.p2_fast;
}
- memset (best_clock, 0, sizeof (*best_clock));
+ memset(best_clock, 0, sizeof(*best_clock));
for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
clock.m1++) {
@@ -802,6 +803,19 @@ static void assert_pch_pll(struct drm_i915_private *dev_priv,
u32 val;
bool cur_state;
+ if (HAS_PCH_CPT(dev_priv->dev)) {
+ u32 pch_dpll;
+
+ pch_dpll = I915_READ(PCH_DPLL_SEL);
+
+ /* Make sure the selected PLL is enabled to the transcoder */
+ WARN(!((pch_dpll >> (4 * pipe)) & 8),
+ "transcoder %d PLL not enabled\n", pipe);
+
+ /* Convert the transcoder pipe number to a pll pipe number */
+ pipe = (pch_dpll >> (4 * pipe)) & 1;
+ }
+
reg = PCH_DPLL(pipe);
val = I915_READ(reg);
cur_state = !!(val & DPLL_VCO_ENABLE);
@@ -1171,6 +1185,9 @@ static void intel_enable_pch_pll(struct drm_i915_private *dev_priv,
int reg;
u32 val;
+ if (pipe > 1)
+ return;
+
/* PCH only available on ILK+ */
BUG_ON(dev_priv->info->gen < 5);
@@ -1191,6 +1208,9 @@ static void intel_disable_pch_pll(struct drm_i915_private *dev_priv,
int reg;
u32 val;
+ if (pipe > 1)
+ return;
+
/* PCH only available on ILK+ */
BUG_ON(dev_priv->info->gen < 5);
@@ -1256,7 +1276,7 @@ static void intel_disable_transcoder(struct drm_i915_private *dev_priv,
I915_WRITE(reg, val);
/* wait for PCH transcoder off, transcoder state */
if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
- DRM_ERROR("failed to disable transcoder\n");
+ DRM_ERROR("failed to disable transcoder %d\n", pipe);
}
/**
@@ -2085,6 +2105,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
switch (plane) {
case 0:
case 1:
+ case 2:
break;
default:
DRM_ERROR("Can't update plane %d in SAREA\n", plane);
@@ -2184,6 +2205,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
case 0:
case 1:
break;
+ case 2:
+ if (IS_IVYBRIDGE(dev))
+ break;
+ /* fall through otherwise */
default:
DRM_ERROR("no plane for crtc\n");
return -EINVAL;
@@ -2440,7 +2465,7 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
}
-static const int snb_b_fdi_train_param [] = {
+static const int snb_b_fdi_train_param[] = {
FDI_LINK_TRAIN_400MV_0DB_SNB_B,
FDI_LINK_TRAIN_400MV_6DB_SNB_B,
FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,
@@ -2496,7 +2521,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
if (HAS_PCH_CPT(dev))
cpt_phase_pointer_enable(dev, pipe);
- for (i = 0; i < 4; i++ ) {
+ for (i = 0; i < 4; i++) {
reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2545,7 +2570,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
POSTING_READ(reg);
udelay(150);
- for (i = 0; i < 4; i++ ) {
+ for (i = 0; i < 4; i++) {
reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2600,6 +2625,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
+ temp |= FDI_COMPOSITE_SYNC;
I915_WRITE(reg, temp | FDI_TX_ENABLE);
reg = FDI_RX_CTL(pipe);
@@ -2607,6 +2633,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
temp &= ~FDI_LINK_TRAIN_AUTO;
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+ temp |= FDI_COMPOSITE_SYNC;
I915_WRITE(reg, temp | FDI_RX_ENABLE);
POSTING_READ(reg);
@@ -2615,7 +2642,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
if (HAS_PCH_CPT(dev))
cpt_phase_pointer_enable(dev, pipe);
- for (i = 0; i < 4; i++ ) {
+ for (i = 0; i < 4; i++) {
reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2657,7 +2684,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
POSTING_READ(reg);
udelay(150);
- for (i = 0; i < 4; i++ ) {
+ for (i = 0; i < 4; i++) {
reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2866,7 +2893,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+ u32 reg, temp, transc_sel;
/* For PCH output, training FDI link */
dev_priv->display.fdi_link_train(crtc);
@@ -2874,12 +2901,21 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
intel_enable_pch_pll(dev_priv, pipe);
if (HAS_PCH_CPT(dev)) {
+ transc_sel = intel_crtc->use_pll_a ? TRANSC_DPLLA_SEL :
+ TRANSC_DPLLB_SEL;
+
/* Be sure PCH DPLL SEL is set */
temp = I915_READ(PCH_DPLL_SEL);
- if (pipe == 0 && (temp & TRANSA_DPLL_ENABLE) == 0)
+ if (pipe == 0) {
+ temp &= ~(TRANSA_DPLLB_SEL);
temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
- else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0)
+ } else if (pipe == 1) {
+ temp &= ~(TRANSB_DPLLB_SEL);
temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
+ } else if (pipe == 2) {
+ temp &= ~(TRANSC_DPLLB_SEL);
+ temp |= (TRANSC_DPLL_ENABLE | transc_sel);
+ }
I915_WRITE(PCH_DPLL_SEL, temp);
}
@@ -2935,6 +2971,24 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
intel_enable_transcoder(dev_priv, pipe);
}
+void intel_cpt_verify_modeset(struct drm_device *dev, int pipe)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int dslreg = PIPEDSL(pipe), tc2reg = TRANS_CHICKEN2(pipe);
+ u32 temp;
+
+ temp = I915_READ(dslreg);
+ udelay(500);
+ if (wait_for(I915_READ(dslreg) != temp, 5)) {
+ /* Without this, mode sets may fail silently on FDI */
+ I915_WRITE(tc2reg, TRANS_AUTOTRAIN_GEN_STALL_DIS);
+ udelay(250);
+ I915_WRITE(tc2reg, 0);
+ if (wait_for(I915_READ(dslreg) != temp, 5))
+ DRM_ERROR("mode set failed: pipe %d stuck\n", pipe);
+ }
+}
+
static void ironlake_crtc_enable(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -3045,13 +3099,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
temp = I915_READ(PCH_DPLL_SEL);
switch (pipe) {
case 0:
- temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
+ temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL);
break;
case 1:
temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
break;
case 2:
- /* FIXME: manage transcoder PLLs? */
+ /* C shares PLL A or B */
temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL);
break;
default:
@@ -3061,7 +3115,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
}
/* disable PCH DPLL */
- intel_disable_pch_pll(dev_priv, pipe);
+ if (!intel_crtc->no_pll)
+ intel_disable_pch_pll(dev_priv, pipe);
/* Switch from PCDclk to Rawclk */
reg = FDI_RX_CTL(pipe);
@@ -3293,18 +3348,25 @@ static void ironlake_crtc_commit(struct drm_crtc *crtc)
ironlake_crtc_enable(crtc);
}
-void intel_encoder_prepare (struct drm_encoder *encoder)
+void intel_encoder_prepare(struct drm_encoder *encoder)
{
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
/* lvds has its own version of prepare see intel_lvds_prepare */
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
}
-void intel_encoder_commit (struct drm_encoder *encoder)
+void intel_encoder_commit(struct drm_encoder *encoder)
{
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
+ struct drm_device *dev = encoder->dev;
+ struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+ struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
+
/* lvds has its own version of commit see intel_lvds_commit */
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+
+ if (HAS_PCH_CPT(dev))
+ intel_cpt_verify_modeset(dev, intel_crtc->pipe);
}
void intel_encoder_destroy(struct drm_encoder *encoder)
@@ -4478,6 +4540,20 @@ static void sandybridge_update_wm(struct drm_device *dev)
enabled |= 2;
}
+ /* IVB has 3 pipes */
+ if (IS_IVYBRIDGE(dev) &&
+ g4x_compute_wm0(dev, 2,
+ &sandybridge_display_wm_info, latency,
+ &sandybridge_cursor_wm_info, latency,
+ &plane_wm, &cursor_wm)) {
+ I915_WRITE(WM0_PIPEC_IVB,
+ (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+ DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
+ " plane %d, cursor: %d\n",
+ plane_wm, cursor_wm);
+ enabled |= 3;
+ }
+
/*
* Calculate and update the self-refresh watermark only when one
* display plane is used.
@@ -4584,7 +4660,9 @@ static void intel_update_watermarks(struct drm_device *dev)
static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
{
- return dev_priv->lvds_use_ssc && i915_panel_use_ssc
+ if (i915_panel_use_ssc >= 0)
+ return i915_panel_use_ssc != 0;
+ return dev_priv->lvds_use_ssc
&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
}
@@ -5107,36 +5185,52 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
return ret;
}
-static void ironlake_update_pch_refclk(struct drm_device *dev)
+/*
+ * Initialize reference clocks when the driver loads
+ */
+void ironlake_init_pch_refclk(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_mode_config *mode_config = &dev->mode_config;
- struct drm_crtc *crtc;
struct intel_encoder *encoder;
- struct intel_encoder *has_edp_encoder = NULL;
u32 temp;
bool has_lvds = false;
+ bool has_cpu_edp = false;
+ bool has_pch_edp = false;
+ bool has_panel = false;
+ bool has_ck505 = false;
+ bool can_ssc = false;
/* We need to take the global config into account */
- list_for_each_entry(crtc, &mode_config->crtc_list, head) {
- if (!crtc->enabled)
- continue;
-
- list_for_each_entry(encoder, &mode_config->encoder_list,
- base.head) {
- if (encoder->base.crtc != crtc)
- continue;
-
- switch (encoder->type) {
- case INTEL_OUTPUT_LVDS:
- has_lvds = true;
- case INTEL_OUTPUT_EDP:
- has_edp_encoder = encoder;
- break;
- }
+ list_for_each_entry(encoder, &mode_config->encoder_list,
+ base.head) {
+ switch (encoder->type) {
+ case INTEL_OUTPUT_LVDS:
+ has_panel = true;
+ has_lvds = true;
+ break;
+ case INTEL_OUTPUT_EDP:
+ has_panel = true;
+ if (intel_encoder_is_pch_edp(&encoder->base))
+ has_pch_edp = true;
+ else
+ has_cpu_edp = true;
+ break;
}
}
+ if (HAS_PCH_IBX(dev)) {
+ has_ck505 = dev_priv->display_clock_mode;
+ can_ssc = has_ck505;
+ } else {
+ has_ck505 = false;
+ can_ssc = true;
+ }
+
+ DRM_DEBUG_KMS("has_panel %d has_lvds %d has_pch_edp %d has_cpu_edp %d has_ck505 %d\n",
+ has_panel, has_lvds, has_pch_edp, has_cpu_edp,
+ has_ck505);
+
/* Ironlake: try to setup display ref clock before DPLL
* enabling. This is only under driver's control after
* PCH B stepping, previous chipset stepping should be
@@ -5145,43 +5239,102 @@ static void ironlake_update_pch_refclk(struct drm_device *dev)
temp = I915_READ(PCH_DREF_CONTROL);
/* Always enable nonspread source */
temp &= ~DREF_NONSPREAD_SOURCE_MASK;
- temp |= DREF_NONSPREAD_SOURCE_ENABLE;
- temp &= ~DREF_SSC_SOURCE_MASK;
- temp |= DREF_SSC_SOURCE_ENABLE;
- I915_WRITE(PCH_DREF_CONTROL, temp);
- POSTING_READ(PCH_DREF_CONTROL);
- udelay(200);
+ if (has_ck505)
+ temp |= DREF_NONSPREAD_CK505_ENABLE;
+ else
+ temp |= DREF_NONSPREAD_SOURCE_ENABLE;
- if (has_edp_encoder) {
- if (intel_panel_use_ssc(dev_priv)) {
- temp |= DREF_SSC1_ENABLE;
- I915_WRITE(PCH_DREF_CONTROL, temp);
+ if (has_panel) {
+ temp &= ~DREF_SSC_SOURCE_MASK;
+ temp |= DREF_SSC_SOURCE_ENABLE;
- POSTING_READ(PCH_DREF_CONTROL);
- udelay(200);
+ /* SSC must be turned on before enabling the CPU output */
+ if (intel_panel_use_ssc(dev_priv) && can_ssc) {
+ DRM_DEBUG_KMS("Using SSC on panel\n");
+ temp |= DREF_SSC1_ENABLE;
}
+
+ /* Get SSC going before enabling the outputs */
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+ udelay(200);
+
temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
/* Enable CPU source on CPU attached eDP */
- if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
- if (intel_panel_use_ssc(dev_priv))
+ if (has_cpu_edp) {
+ if (intel_panel_use_ssc(dev_priv) && can_ssc) {
+ DRM_DEBUG_KMS("Using SSC on eDP\n");
temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+ }
else
temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
- } else {
- /* Enable SSC on PCH eDP if needed */
- if (intel_panel_use_ssc(dev_priv)) {
- DRM_ERROR("enabling SSC on PCH\n");
- temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
- }
- }
+ } else
+ temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+ udelay(200);
+ } else {
+ DRM_DEBUG_KMS("Disabling SSC entirely\n");
+
+ temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+
+ /* Turn off CPU output */
+ temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+ udelay(200);
+
+ /* Turn off the SSC source */
+ temp &= ~DREF_SSC_SOURCE_MASK;
+ temp |= DREF_SSC_SOURCE_DISABLE;
+
+ /* Turn off SSC1 */
+ temp &= ~ DREF_SSC1_ENABLE;
+
I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL);
udelay(200);
}
}
+static int ironlake_get_refclk(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_encoder *encoder;
+ struct drm_mode_config *mode_config = &dev->mode_config;
+ struct intel_encoder *edp_encoder = NULL;
+ int num_connectors = 0;
+ bool is_lvds = false;
+
+ list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
+ if (encoder->base.crtc != crtc)
+ continue;
+
+ switch (encoder->type) {
+ case INTEL_OUTPUT_LVDS:
+ is_lvds = true;
+ break;
+ case INTEL_OUTPUT_EDP:
+ edp_encoder = encoder;
+ break;
+ }
+ num_connectors++;
+ }
+
+ if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
+ DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
+ dev_priv->lvds_ssc_freq);
+ return dev_priv->lvds_ssc_freq * 1000;
+ }
+
+ return 120000;
+}
+
static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
@@ -5241,16 +5394,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
num_connectors++;
}
- if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
- refclk = dev_priv->lvds_ssc_freq * 1000;
- DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
- refclk / 1000);
- } else {
- refclk = 96000;
- if (!has_edp_encoder ||
- intel_encoder_is_pch_edp(&has_edp_encoder->base))
- refclk = 120000; /* 120Mhz refclk */
- }
+ refclk = ironlake_get_refclk(crtc);
/*
* Returns a set of divisors for the desired target clock with the given
@@ -5377,8 +5521,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
&m_n);
- ironlake_update_pch_refclk(dev);
-
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
if (has_reduced_clock)
fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
@@ -5450,39 +5592,32 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
/* Set up the display plane register */
dspcntr = DISPPLANE_GAMMA_ENABLE;
- DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+ DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
drm_mode_debug_printmodeline(mode);
/* PCH eDP needs FDI, but CPU eDP does not */
- if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
- I915_WRITE(PCH_FP0(pipe), fp);
- I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
-
- POSTING_READ(PCH_DPLL(pipe));
- udelay(150);
- }
+ if (!intel_crtc->no_pll) {
+ if (!has_edp_encoder ||
+ intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+ I915_WRITE(PCH_FP0(pipe), fp);
+ I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
- /* enable transcoder DPLL */
- if (HAS_PCH_CPT(dev)) {
- temp = I915_READ(PCH_DPLL_SEL);
- switch (pipe) {
- case 0:
- temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL;
- break;
- case 1:
- temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL;
- break;
- case 2:
- /* FIXME: manage transcoder PLLs? */
- temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL;
- break;
- default:
- BUG();
+ POSTING_READ(PCH_DPLL(pipe));
+ udelay(150);
+ }
+ } else {
+ if (dpll == (I915_READ(PCH_DPLL(0)) & 0x7fffffff) &&
+ fp == I915_READ(PCH_FP0(0))) {
+ intel_crtc->use_pll_a = true;
+ DRM_DEBUG_KMS("using pipe a dpll\n");
+ } else if (dpll == (I915_READ(PCH_DPLL(1)) & 0x7fffffff) &&
+ fp == I915_READ(PCH_FP0(1))) {
+ intel_crtc->use_pll_a = false;
+ DRM_DEBUG_KMS("using pipe b dpll\n");
+ } else {
+ DRM_DEBUG_KMS("no matching PLL configuration for pipe 2\n");
+ return -EINVAL;
}
- I915_WRITE(PCH_DPLL_SEL, temp);
-
- POSTING_READ(PCH_DPLL_SEL);
- udelay(150);
}
/* The LVDS pin pair needs to be on before the DPLLs are enabled.
@@ -5492,17 +5627,13 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
if (is_lvds) {
temp = I915_READ(PCH_LVDS);
temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
- if (pipe == 1) {
- if (HAS_PCH_CPT(dev))
- temp |= PORT_TRANS_B_SEL_CPT;
- else
- temp |= LVDS_PIPEB_SELECT;
- } else {
- if (HAS_PCH_CPT(dev))
- temp &= ~PORT_TRANS_SEL_MASK;
- else
- temp &= ~LVDS_PIPEB_SELECT;
- }
+ if (HAS_PCH_CPT(dev))
+ temp |= PORT_TRANS_SEL_CPT(pipe);
+ else if (pipe == 1)
+ temp |= LVDS_PIPEB_SELECT;
+ else
+ temp &= ~LVDS_PIPEB_SELECT;
+
/* set the corresponsding LVDS_BORDER bit */
temp |= dev_priv->lvds_border_bits;
/* Set the B0-B3 data pairs corresponding to whether we're going to
@@ -5552,8 +5683,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(TRANSDPLINK_N1(pipe), 0);
}
- if (!has_edp_encoder ||
- intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+ if (!intel_crtc->no_pll &&
+ (!has_edp_encoder ||
+ intel_encoder_is_pch_edp(&has_edp_encoder->base))) {
I915_WRITE(PCH_DPLL(pipe), dpll);
/* Wait for the clocks to stabilize. */
@@ -5569,18 +5701,20 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
}
intel_crtc->lowfreq_avail = false;
- if (is_lvds && has_reduced_clock && i915_powersave) {
- I915_WRITE(PCH_FP1(pipe), fp2);
- intel_crtc->lowfreq_avail = true;
- if (HAS_PIPE_CXSR(dev)) {
- DRM_DEBUG_KMS("enabling CxSR downclocking\n");
- pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
- }
- } else {
- I915_WRITE(PCH_FP1(pipe), fp);
- if (HAS_PIPE_CXSR(dev)) {
- DRM_DEBUG_KMS("disabling CxSR downclocking\n");
- pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+ if (!intel_crtc->no_pll) {
+ if (is_lvds && has_reduced_clock && i915_powersave) {
+ I915_WRITE(PCH_FP1(pipe), fp2);
+ intel_crtc->lowfreq_avail = true;
+ if (HAS_PIPE_CXSR(dev)) {
+ DRM_DEBUG_KMS("enabling CxSR downclocking\n");
+ pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
+ }
+ } else {
+ I915_WRITE(PCH_FP1(pipe), fp);
+ if (HAS_PIPE_CXSR(dev)) {
+ DRM_DEBUG_KMS("disabling CxSR downclocking\n");
+ pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+ }
}
}
@@ -5677,6 +5811,131 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
return ret;
}
+static void g4x_write_eld(struct drm_connector *connector,
+ struct drm_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = connector->dev->dev_private;
+ uint8_t *eld = connector->eld;
+ uint32_t eldv;
+ uint32_t len;
+ uint32_t i;
+
+ i = I915_READ(G4X_AUD_VID_DID);
+
+ if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL)
+ eldv = G4X_ELDV_DEVCL_DEVBLC;
+ else
+ eldv = G4X_ELDV_DEVCTG;
+
+ i = I915_READ(G4X_AUD_CNTL_ST);
+ i &= ~(eldv | G4X_ELD_ADDR);
+ len = (i >> 9) & 0x1f; /* ELD buffer size */
+ I915_WRITE(G4X_AUD_CNTL_ST, i);
+
+ if (!eld[0])
+ return;
+
+ len = min_t(uint8_t, eld[2], len);
+ DRM_DEBUG_DRIVER("ELD size %d\n", len);
+ for (i = 0; i < len; i++)
+ I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i));
+
+ i = I915_READ(G4X_AUD_CNTL_ST);
+ i |= eldv;
+ I915_WRITE(G4X_AUD_CNTL_ST, i);
+}
+
+static void ironlake_write_eld(struct drm_connector *connector,
+ struct drm_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = connector->dev->dev_private;
+ uint8_t *eld = connector->eld;
+ uint32_t eldv;
+ uint32_t i;
+ int len;
+ int hdmiw_hdmiedid;
+ int aud_cntl_st;
+ int aud_cntrl_st2;
+
+ if (IS_IVYBRIDGE(connector->dev)) {
+ hdmiw_hdmiedid = GEN7_HDMIW_HDMIEDID_A;
+ aud_cntl_st = GEN7_AUD_CNTRL_ST_A;
+ aud_cntrl_st2 = GEN7_AUD_CNTRL_ST2;
+ } else {
+ hdmiw_hdmiedid = GEN5_HDMIW_HDMIEDID_A;
+ aud_cntl_st = GEN5_AUD_CNTL_ST_A;
+ aud_cntrl_st2 = GEN5_AUD_CNTL_ST2;
+ }
+
+ i = to_intel_crtc(crtc)->pipe;
+ hdmiw_hdmiedid += i * 0x100;
+ aud_cntl_st += i * 0x100;
+
+ DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
+
+ i = I915_READ(aud_cntl_st);
+ i = (i >> 29) & 0x3; /* DIP_Port_Select, 0x1 = PortB */
+ if (!i) {
+ DRM_DEBUG_DRIVER("Audio directed to unknown port\n");
+ /* operate blindly on all ports */
+ eldv = GEN5_ELD_VALIDB;
+ eldv |= GEN5_ELD_VALIDB << 4;
+ eldv |= GEN5_ELD_VALIDB << 8;
+ } else {
+ DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i);
+ eldv = GEN5_ELD_VALIDB << ((i - 1) * 4);
+ }
+
+ i = I915_READ(aud_cntrl_st2);
+ i &= ~eldv;
+ I915_WRITE(aud_cntrl_st2, i);
+
+ if (!eld[0])
+ return;
+
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+ DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
+ eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */
+ }
+
+ i = I915_READ(aud_cntl_st);
+ i &= ~GEN5_ELD_ADDRESS;
+ I915_WRITE(aud_cntl_st, i);
+
+ len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */
+ DRM_DEBUG_DRIVER("ELD size %d\n", len);
+ for (i = 0; i < len; i++)
+ I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i));
+
+ i = I915_READ(aud_cntrl_st2);
+ i |= eldv;
+ I915_WRITE(aud_cntrl_st2, i);
+}
+
+void intel_write_eld(struct drm_encoder *encoder,
+ struct drm_display_mode *mode)
+{
+ struct drm_crtc *crtc = encoder->crtc;
+ struct drm_connector *connector;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ connector = drm_select_eld(encoder, mode);
+ if (!connector)
+ return;
+
+ DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
+ connector->base.id,
+ drm_get_connector_name(connector),
+ connector->encoder->base.id,
+ drm_get_encoder_name(connector->encoder));
+
+ connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
+
+ if (dev_priv->display.write_eld)
+ dev_priv->display.write_eld(connector, crtc);
+}
+
/** Loads the palette/gamma unit for the CRTC with the prepared values */
void intel_crtc_load_lut(struct drm_crtc *crtc)
{
@@ -5758,6 +6017,31 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
I915_WRITE(CURBASE(pipe), base);
}
+static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int pipe = intel_crtc->pipe;
+ bool visible = base != 0;
+
+ if (intel_crtc->cursor_visible != visible) {
+ uint32_t cntl = I915_READ(CURCNTR_IVB(pipe));
+ if (base) {
+ cntl &= ~CURSOR_MODE;
+ cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+ } else {
+ cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
+ cntl |= CURSOR_MODE_DISABLE;
+ }
+ I915_WRITE(CURCNTR_IVB(pipe), cntl);
+
+ intel_crtc->cursor_visible = visible;
+ }
+ /* and commit changes on next vblank */
+ I915_WRITE(CURBASE_IVB(pipe), base);
+}
+
/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
static void intel_crtc_update_cursor(struct drm_crtc *crtc,
bool on)
@@ -5805,11 +6089,16 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
if (!visible && !intel_crtc->cursor_visible)
return;
- I915_WRITE(CURPOS(pipe), pos);
- if (IS_845G(dev) || IS_I865G(dev))
- i845_update_cursor(crtc, base);
- else
- i9xx_update_cursor(crtc, base);
+ if (IS_IVYBRIDGE(dev)) {
+ I915_WRITE(CURPOS_IVB(pipe), pos);
+ ivb_update_cursor(crtc, base);
+ } else {
+ I915_WRITE(CURPOS(pipe), pos);
+ if (IS_845G(dev) || IS_I865G(dev))
+ i845_update_cursor(crtc, base);
+ else
+ i9xx_update_cursor(crtc, base);
+ }
if (visible)
intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
@@ -7071,6 +7360,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
intel_crtc->bpp = 24; /* default for pre-Ironlake */
if (HAS_PCH_SPLIT(dev)) {
+ if (pipe == 2 && IS_IVYBRIDGE(dev))
+ intel_crtc->no_pll = true;
intel_helper_funcs.prepare = ironlake_crtc_prepare;
intel_helper_funcs.commit = ironlake_crtc_commit;
} else {
@@ -7250,6 +7541,9 @@ static void intel_setup_outputs(struct drm_device *dev)
/* disable all the possible outputs/crtcs before entering KMS mode */
drm_helper_disable_unused_functions(dev);
+
+ if (HAS_PCH_SPLIT(dev))
+ ironlake_init_pch_refclk(dev);
}
static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -7494,6 +7788,10 @@ void gen6_disable_rps(struct drm_device *dev)
I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
I915_WRITE(GEN6_PMIER, 0);
+ /* Complete PM interrupt masking here doesn't race with the rps work
+ * item again unmasking PM interrupts because that is using a different
+ * register (PMIMR) to mask PM interrupts. The only risk is in leaving
+ * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
spin_lock_irq(&dev_priv->rps_lock);
dev_priv->pm_iir = 0;
@@ -8154,7 +8452,7 @@ static void intel_init_display(struct drm_device *dev)
}
/* Returns the core display clock speed */
- if (IS_I945G(dev) || (IS_G33(dev) && ! IS_PINEVIEW_M(dev)))
+ if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev)))
dev_priv->display.get_display_clock_speed =
i945_get_display_clock_speed;
else if (IS_I915G(dev))
@@ -8193,6 +8491,7 @@ static void intel_init_display(struct drm_device *dev)
}
dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
+ dev_priv->display.write_eld = ironlake_write_eld;
} else if (IS_GEN6(dev)) {
if (SNB_READ_WM0_LATENCY()) {
dev_priv->display.update_wm = sandybridge_update_wm;
@@ -8203,6 +8502,7 @@ static void intel_init_display(struct drm_device *dev)
}
dev_priv->display.fdi_link_train = gen6_fdi_link_train;
dev_priv->display.init_clock_gating = gen6_init_clock_gating;
+ dev_priv->display.write_eld = ironlake_write_eld;
} else if (IS_IVYBRIDGE(dev)) {
/* FIXME: detect B0+ stepping and use auto training */
dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
@@ -8214,7 +8514,7 @@ static void intel_init_display(struct drm_device *dev)
dev_priv->display.update_wm = NULL;
}
dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
-
+ dev_priv->display.write_eld = ironlake_write_eld;
} else
dev_priv->display.update_wm = NULL;
} else if (IS_PINEVIEW(dev)) {
@@ -8225,7 +8525,7 @@ static void intel_init_display(struct drm_device *dev)
DRM_INFO("failed to find known CxSR latency "
"(found ddr%s fsb freq %d, mem freq %d), "
"disabling CxSR\n",
- (dev_priv->is_ddr3 == 1) ? "3": "2",
+ (dev_priv->is_ddr3 == 1) ? "3" : "2",
dev_priv->fsb_freq, dev_priv->mem_freq);
/* Disable CxSR and never update its watermark again */
pineview_disable_cxsr(dev);
@@ -8234,6 +8534,7 @@ static void intel_init_display(struct drm_device *dev)
dev_priv->display.update_wm = pineview_update_wm;
dev_priv->display.init_clock_gating = gen3_init_clock_gating;
} else if (IS_G4X(dev)) {
+ dev_priv->display.write_eld = g4x_write_eld;
dev_priv->display.update_wm = g4x_update_wm;
dev_priv->display.init_clock_gating = g4x_init_clock_gating;
} else if (IS_GEN4(dev)) {
@@ -8294,7 +8595,7 @@ static void intel_init_display(struct drm_device *dev)
* resume, or other times. This quirk makes sure that's the case for
* affected systems.
*/
-static void quirk_pipea_force (struct drm_device *dev)
+static void quirk_pipea_force(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -8322,7 +8623,7 @@ struct intel_quirk intel_quirks[] = {
/* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */
{ 0x2a42, 0x103c, 0x30eb, quirk_pipea_force },
/* HP Mini needs pipe A force quirk (LP: #322104) */
- { 0x27ae,0x103c, 0x361a, quirk_pipea_force },
+ { 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
/* Thinkpad R31 needs pipe A force quirk */
{ 0x3577, 0x1014, 0x0505, quirk_pipea_force },
@@ -8488,6 +8789,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
* enqueue unpin/hotplug work. */
drm_irq_uninstall(dev);
cancel_work_sync(&dev_priv->hotplug_work);
+ cancel_work_sync(&dev_priv->rps_work);
/* flush any delayed tasks or pending work */
flush_scheduled_work();
@@ -8573,7 +8875,7 @@ struct intel_display_error_state {
struct intel_display_error_state *
intel_display_capture_error_state(struct drm_device *dev)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_display_error_state *error;
int i;
@@ -8589,7 +8891,7 @@ intel_display_capture_error_state(struct drm_device *dev)
error->plane[i].control = I915_READ(DSPCNTR(i));
error->plane[i].stride = I915_READ(DSPSTRIDE(i));
error->plane[i].size = I915_READ(DSPSIZE(i));
- error->plane[i].pos= I915_READ(DSPPOS(i));
+ error->plane[i].pos = I915_READ(DSPPOS(i));
error->plane[i].addr = I915_READ(DSPADDR(i));
if (INTEL_INFO(dev)->gen >= 4) {
error->plane[i].surface = I915_READ(DSPSURF(i));
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 44fef5e1c490..fc1a0832af4f 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -36,7 +36,7 @@
#include "i915_drv.h"
#include "drm_dp_helper.h"
-
+#define DP_RECEIVER_CAP_SIZE 0xf
#define DP_LINK_STATUS_SIZE 6
#define DP_LINK_CHECK_TIMEOUT (10 * 1000)
@@ -53,12 +53,21 @@ struct intel_dp {
int dpms_mode;
uint8_t link_bw;
uint8_t lane_count;
- uint8_t dpcd[8];
+ uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
struct i2c_adapter adapter;
struct i2c_algo_dp_aux_data algo;
bool is_pch_edp;
uint8_t train_set[4];
uint8_t link_status[DP_LINK_STATUS_SIZE];
+ int panel_power_up_delay;
+ int panel_power_down_delay;
+ int panel_power_cycle_delay;
+ int backlight_on_delay;
+ int backlight_off_delay;
+ struct drm_display_mode *panel_fixed_mode; /* for eDP */
+ struct delayed_work panel_vdd_work;
+ bool want_panel_vdd;
+ unsigned long panel_off_jiffies;
};
/**
@@ -86,6 +95,17 @@ static bool is_pch_edp(struct intel_dp *intel_dp)
return intel_dp->is_pch_edp;
}
+/**
+ * is_cpu_edp - is the port on the CPU and attached to an eDP panel?
+ * @intel_dp: DP struct
+ *
+ * Returns true if the given DP struct corresponds to a CPU eDP port.
+ */
+static bool is_cpu_edp(struct intel_dp *intel_dp)
+{
+ return is_edp(intel_dp) && !is_pch_edp(intel_dp);
+}
+
static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
{
return container_of(encoder, struct intel_dp, base.base);
@@ -121,7 +141,7 @@ static void intel_dp_complete_link_train(struct intel_dp *intel_dp);
static void intel_dp_link_down(struct intel_dp *intel_dp);
void
-intel_edp_link_config (struct intel_encoder *intel_encoder,
+intel_edp_link_config(struct intel_encoder *intel_encoder,
int *lane_num, int *link_bw)
{
struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
@@ -175,9 +195,25 @@ intel_dp_link_clock(uint8_t link_bw)
return 162000;
}
-/* I think this is a fiction */
+/*
+ * The units on the numbers in the next two are... bizarre. Examples will
+ * make it clearer; this one parallels an example in the eDP spec.
+ *
+ * intel_dp_max_data_rate for one lane of 2.7GHz evaluates as:
+ *
+ * 270000 * 1 * 8 / 10 == 216000
+ *
+ * The actual data capacity of that configuration is 2.16Gbit/s, so the
+ * units are decakilobits. ->clock in a drm_display_mode is in kilohertz -
+ * or equivalently, kilopixels per second - so for 1680x1050R it'd be
+ * 119000. At 18bpp that's 2142000 kilobits per second.
+ *
+ * Thus the strange-looking division by 10 in intel_dp_link_required, to
+ * get the result in decakilobits instead of kilobits.
+ */
+
static int
-intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pixel_clock)
+intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock)
{
struct drm_crtc *crtc = intel_dp->base.base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -186,7 +222,7 @@ intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pi
if (intel_crtc)
bpp = intel_crtc->bpp;
- return (pixel_clock * bpp + 7) / 8;
+ return (pixel_clock * bpp + 9) / 10;
}
static int
@@ -200,24 +236,19 @@ intel_dp_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
- struct drm_device *dev = connector->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
int max_lanes = intel_dp_max_lane_count(intel_dp);
- if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) {
- if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay)
+ if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
+ if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
return MODE_PANEL;
- if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay)
+ if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay)
return MODE_PANEL;
}
- /* only refuse the mode on non eDP since we have seen some weird eDP panels
- which are outside spec tolerances but somehow work by magic */
- if (!is_edp(intel_dp) &&
- (intel_dp_link_required(connector->dev, intel_dp, mode->clock)
- > intel_dp_max_data_rate(max_link_clock, max_lanes)))
+ if (intel_dp_link_required(intel_dp, mode->clock)
+ > intel_dp_max_data_rate(max_link_clock, max_lanes))
return MODE_CLOCK_HIGH;
if (mode->clock < 10000)
@@ -279,6 +310,38 @@ intel_hrawclk(struct drm_device *dev)
}
}
+static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
+}
+
+static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ return (I915_READ(PCH_PP_CONTROL) & EDP_FORCE_VDD) != 0;
+}
+
+static void
+intel_dp_check_edp(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (!is_edp(intel_dp))
+ return;
+ if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) {
+ WARN(1, "eDP powered off while attempting aux channel communication.\n");
+ DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
+ I915_READ(PCH_PP_STATUS),
+ I915_READ(PCH_PP_CONTROL));
+ }
+}
+
static int
intel_dp_aux_ch(struct intel_dp *intel_dp,
uint8_t *send, int send_bytes,
@@ -295,6 +358,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
uint32_t aux_clock_divider;
int try, precharge;
+ intel_dp_check_edp(intel_dp);
/* The clock divider is based off the hrawclk,
* and would like to run at 2MHz. So, take the
* hrawclk value and divide by 2 and use that
@@ -302,7 +366,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
* Note that PCH attached eDP panels should use a 125MHz input
* clock divider.
*/
- if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) {
+ if (is_cpu_edp(intel_dp)) {
if (IS_GEN6(dev))
aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
else
@@ -337,7 +401,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
for (i = 0; i < send_bytes; i += 4)
I915_WRITE(ch_data + i,
pack_aux(send + i, send_bytes - i));
-
+
/* Send the command and wait for it to complete */
I915_WRITE(ch_ctl,
DP_AUX_CH_CTL_SEND_BUSY |
@@ -354,7 +418,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
break;
udelay(100);
}
-
+
/* Clear done status and any errors */
I915_WRITE(ch_ctl,
status |
@@ -390,7 +454,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
if (recv_bytes > recv_size)
recv_bytes = recv_size;
-
+
for (i = 0; i < recv_bytes; i += 4)
unpack_aux(I915_READ(ch_data + i),
recv + i, recv_bytes - i);
@@ -408,6 +472,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
int msg_bytes;
uint8_t ack;
+ intel_dp_check_edp(intel_dp);
if (send_bytes > 16)
return -1;
msg[0] = AUX_NATIVE_WRITE << 4;
@@ -450,6 +515,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
uint8_t ack;
int ret;
+ intel_dp_check_edp(intel_dp);
msg[0] = AUX_NATIVE_READ << 4;
msg[1] = address >> 8;
msg[2] = address & 0xff;
@@ -493,6 +559,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
int reply_bytes;
int ret;
+ intel_dp_check_edp(intel_dp);
/* Set up the command byte */
if (mode & MODE_I2C_READ)
msg[0] = AUX_I2C_READ << 4;
@@ -573,24 +640,32 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
return -EREMOTEIO;
}
+static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
+static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
+
static int
intel_dp_i2c_init(struct intel_dp *intel_dp,
struct intel_connector *intel_connector, const char *name)
{
+ int ret;
+
DRM_DEBUG_KMS("i2c_init %s\n", name);
intel_dp->algo.running = false;
intel_dp->algo.address = 0;
intel_dp->algo.aux_ch = intel_dp_i2c_aux_ch;
- memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter));
+ memset(&intel_dp->adapter, '\0', sizeof(intel_dp->adapter));
intel_dp->adapter.owner = THIS_MODULE;
intel_dp->adapter.class = I2C_CLASS_DDC;
- strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
+ strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
intel_dp->adapter.algo_data = &intel_dp->algo;
intel_dp->adapter.dev.parent = &intel_connector->base.kdev;
- return i2c_dp_aux_add_bus(&intel_dp->adapter);
+ ironlake_edp_panel_vdd_on(intel_dp);
+ ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
+ ironlake_edp_panel_vdd_off(intel_dp, false);
+ return ret;
}
static bool
@@ -598,29 +673,28 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
int lane_count, clock;
int max_lane_count = intel_dp_max_lane_count(intel_dp);
int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
- if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) {
- intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode);
+ if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
+ intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode);
intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN,
mode, adjusted_mode);
/*
* the mode->clock is used to calculate the Data&Link M/N
* of the pipe. For the eDP the fixed clock should be used.
*/
- mode->clock = dev_priv->panel_fixed_mode->clock;
+ mode->clock = intel_dp->panel_fixed_mode->clock;
}
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
for (clock = 0; clock <= max_clock; clock++) {
int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
- if (intel_dp_link_required(encoder->dev, intel_dp, mode->clock)
+ if (intel_dp_link_required(intel_dp, mode->clock)
<= link_avail) {
intel_dp->link_bw = bws[clock];
intel_dp->lane_count = lane_count;
@@ -634,19 +708,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
}
}
- if (is_edp(intel_dp)) {
- /* okay we failed just pick the highest */
- intel_dp->lane_count = max_lane_count;
- intel_dp->link_bw = bws[max_clock];
- adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
- DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
- "count %d clock %d\n",
- intel_dp->link_bw, intel_dp->lane_count,
- adjusted_mode->clock);
-
- return true;
- }
-
return false;
}
@@ -740,6 +801,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
}
}
+static void ironlake_edp_pll_on(struct drm_encoder *encoder);
+static void ironlake_edp_pll_off(struct drm_encoder *encoder);
+
static void
intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -749,6 +813,14 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_crtc *crtc = intel_dp->base.base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ /* Turn on the eDP PLL if needed */
+ if (is_edp(intel_dp)) {
+ if (!is_pch_edp(intel_dp))
+ ironlake_edp_pll_on(encoder);
+ else
+ ironlake_edp_pll_off(encoder);
+ }
+
intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
intel_dp->DP |= intel_dp->color_range;
@@ -757,7 +829,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
intel_dp->DP |= DP_SYNC_VS_HIGH;
- if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+ if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
else
intel_dp->DP |= DP_LINK_TRAIN_OFF;
@@ -773,8 +845,12 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
intel_dp->DP |= DP_PORT_WIDTH_4;
break;
}
- if (intel_dp->has_audio)
+ if (intel_dp->has_audio) {
+ DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
+ pipe_name(intel_crtc->pipe));
intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
+ intel_write_eld(encoder, adjusted_mode);
+ }
memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
intel_dp->link_configuration[0] = intel_dp->link_bw;
@@ -794,7 +870,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev))
intel_dp->DP |= DP_PIPEB_SELECT;
- if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) {
+ if (is_cpu_edp(intel_dp)) {
/* don't miss out required setting for eDP */
intel_dp->DP |= DP_PLL_ENABLE;
if (adjusted_mode->clock < 200000)
@@ -804,58 +880,150 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
}
}
+static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
+{
+ unsigned long off_time;
+ unsigned long delay;
+
+ DRM_DEBUG_KMS("Wait for panel power off time\n");
+
+ if (ironlake_edp_have_panel_power(intel_dp) ||
+ ironlake_edp_have_panel_vdd(intel_dp))
+ {
+ DRM_DEBUG_KMS("Panel still on, no delay needed\n");
+ return;
+ }
+
+ off_time = intel_dp->panel_off_jiffies + msecs_to_jiffies(intel_dp->panel_power_down_delay);
+ if (time_after(jiffies, off_time)) {
+ DRM_DEBUG_KMS("Time already passed");
+ return;
+ }
+ delay = jiffies_to_msecs(off_time - jiffies);
+ if (delay > intel_dp->panel_power_down_delay)
+ delay = intel_dp->panel_power_down_delay;
+ DRM_DEBUG_KMS("Waiting an additional %ld ms\n", delay);
+ msleep(delay);
+}
+
static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp;
- /*
- * If the panel wasn't on, make sure there's not a currently
- * active PP sequence before enabling AUX VDD.
- */
- if (!(I915_READ(PCH_PP_STATUS) & PP_ON))
- msleep(dev_priv->panel_t3);
+ if (!is_edp(intel_dp))
+ return;
+ DRM_DEBUG_KMS("Turn eDP VDD on\n");
+
+ WARN(intel_dp->want_panel_vdd,
+ "eDP VDD already requested on\n");
+
+ intel_dp->want_panel_vdd = true;
+ if (ironlake_edp_have_panel_vdd(intel_dp)) {
+ DRM_DEBUG_KMS("eDP VDD already on\n");
+ return;
+ }
+ ironlake_wait_panel_off(intel_dp);
pp = I915_READ(PCH_PP_CONTROL);
+ pp &= ~PANEL_UNLOCK_MASK;
+ pp |= PANEL_UNLOCK_REGS;
pp |= EDP_FORCE_VDD;
I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
+ DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
+ I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
+
+ /*
+ * If the panel wasn't on, delay before accessing aux channel
+ */
+ if (!ironlake_edp_have_panel_power(intel_dp)) {
+ DRM_DEBUG_KMS("eDP was not running\n");
+ msleep(intel_dp->panel_power_up_delay);
+ }
}
-static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp)
+static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp;
- pp = I915_READ(PCH_PP_CONTROL);
- pp &= ~EDP_FORCE_VDD;
- I915_WRITE(PCH_PP_CONTROL, pp);
- POSTING_READ(PCH_PP_CONTROL);
+ if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) {
+ pp = I915_READ(PCH_PP_CONTROL);
+ pp &= ~PANEL_UNLOCK_MASK;
+ pp |= PANEL_UNLOCK_REGS;
+ pp &= ~EDP_FORCE_VDD;
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+
+ /* Make sure sequencer is idle before allowing subsequent activity */
+ DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
+ I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
+ intel_dp->panel_off_jiffies = jiffies;
+ }
+}
+
+static void ironlake_panel_vdd_work(struct work_struct *__work)
+{
+ struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
+ struct intel_dp, panel_vdd_work);
+ struct drm_device *dev = intel_dp->base.base.dev;
- /* Make sure sequencer is idle before allowing subsequent activity */
- msleep(dev_priv->panel_t12);
+ mutex_lock(&dev->struct_mutex);
+ ironlake_panel_vdd_off_sync(intel_dp);
+ mutex_unlock(&dev->struct_mutex);
+}
+
+static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+{
+ if (!is_edp(intel_dp))
+ return;
+
+ DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd);
+ WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on");
+
+ intel_dp->want_panel_vdd = false;
+
+ if (sync) {
+ ironlake_panel_vdd_off_sync(intel_dp);
+ } else {
+ /*
+ * Queue the timer to fire a long
+ * time from now (relative to the power down delay)
+ * to keep the panel power up across a sequence of operations
+ */
+ schedule_delayed_work(&intel_dp->panel_vdd_work,
+ msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
+ }
}
/* Returns true if the panel was already on when called */
-static bool ironlake_edp_panel_on (struct intel_dp *intel_dp)
+static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE;
- if (I915_READ(PCH_PP_STATUS) & PP_ON)
- return true;
+ if (!is_edp(intel_dp))
+ return;
+ if (ironlake_edp_have_panel_power(intel_dp))
+ return;
+ ironlake_wait_panel_off(intel_dp);
pp = I915_READ(PCH_PP_CONTROL);
+ pp &= ~PANEL_UNLOCK_MASK;
+ pp |= PANEL_UNLOCK_REGS;
+
+ if (IS_GEN5(dev)) {
+ /* ILK workaround: disable reset around power sequence */
+ pp &= ~PANEL_POWER_RESET;
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+ }
- /* ILK workaround: disable reset around power sequence */
- pp &= ~PANEL_POWER_RESET;
- I915_WRITE(PCH_PP_CONTROL, pp);
- POSTING_READ(PCH_PP_CONTROL);
-
- pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
+ pp |= POWER_TARGET_ON;
I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
@@ -864,44 +1032,64 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp)
DRM_ERROR("panel on wait timed out: 0x%08x\n",
I915_READ(PCH_PP_STATUS));
- pp |= PANEL_POWER_RESET; /* restore panel reset bit */
- I915_WRITE(PCH_PP_CONTROL, pp);
- POSTING_READ(PCH_PP_CONTROL);
-
- return false;
+ if (IS_GEN5(dev)) {
+ pp |= PANEL_POWER_RESET; /* restore panel reset bit */
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+ }
}
-static void ironlake_edp_panel_off (struct drm_device *dev)
+static void ironlake_edp_panel_off(struct drm_encoder *encoder)
{
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK |
PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK;
+ if (!is_edp(intel_dp))
+ return;
pp = I915_READ(PCH_PP_CONTROL);
+ pp &= ~PANEL_UNLOCK_MASK;
+ pp |= PANEL_UNLOCK_REGS;
+
+ if (IS_GEN5(dev)) {
+ /* ILK workaround: disable reset around power sequence */
+ pp &= ~PANEL_POWER_RESET;
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+ }
- /* ILK workaround: disable reset around power sequence */
- pp &= ~PANEL_POWER_RESET;
- I915_WRITE(PCH_PP_CONTROL, pp);
- POSTING_READ(PCH_PP_CONTROL);
+ intel_dp->panel_off_jiffies = jiffies;
- pp &= ~POWER_TARGET_ON;
- I915_WRITE(PCH_PP_CONTROL, pp);
- POSTING_READ(PCH_PP_CONTROL);
+ if (IS_GEN5(dev)) {
+ pp &= ~POWER_TARGET_ON;
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+ pp &= ~POWER_TARGET_ON;
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+ msleep(intel_dp->panel_power_cycle_delay);
- if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000))
- DRM_ERROR("panel off wait timed out: 0x%08x\n",
- I915_READ(PCH_PP_STATUS));
+ if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000))
+ DRM_ERROR("panel off wait timed out: 0x%08x\n",
+ I915_READ(PCH_PP_STATUS));
- pp |= PANEL_POWER_RESET; /* restore panel reset bit */
- I915_WRITE(PCH_PP_CONTROL, pp);
- POSTING_READ(PCH_PP_CONTROL);
+ pp |= PANEL_POWER_RESET; /* restore panel reset bit */
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+ }
}
-static void ironlake_edp_backlight_on (struct drm_device *dev)
+static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
{
+ struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp;
+ if (!is_edp(intel_dp))
+ return;
+
DRM_DEBUG_KMS("\n");
/*
* If we enable the backlight right away following a panel power
@@ -909,21 +1097,32 @@ static void ironlake_edp_backlight_on (struct drm_device *dev)
* link. So delay a bit to make sure the image is solid before
* allowing it to appear.
*/
- msleep(300);
+ msleep(intel_dp->backlight_on_delay);
pp = I915_READ(PCH_PP_CONTROL);
+ pp &= ~PANEL_UNLOCK_MASK;
+ pp |= PANEL_UNLOCK_REGS;
pp |= EDP_BLC_ENABLE;
I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
}
-static void ironlake_edp_backlight_off (struct drm_device *dev)
+static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
{
+ struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp;
+ if (!is_edp(intel_dp))
+ return;
+
DRM_DEBUG_KMS("\n");
pp = I915_READ(PCH_PP_CONTROL);
+ pp &= ~PANEL_UNLOCK_MASK;
+ pp |= PANEL_UNLOCK_REGS;
pp &= ~EDP_BLC_ENABLE;
I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+ msleep(intel_dp->backlight_off_delay);
}
static void ironlake_edp_pll_on(struct drm_encoder *encoder)
@@ -986,43 +1185,39 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
static void intel_dp_prepare(struct drm_encoder *encoder)
{
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- struct drm_device *dev = encoder->dev;
/* Wake up the sink first */
+ ironlake_edp_panel_vdd_on(intel_dp);
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+ ironlake_edp_panel_vdd_off(intel_dp, false);
- if (is_edp(intel_dp)) {
- ironlake_edp_backlight_off(dev);
- ironlake_edp_panel_off(dev);
- if (!is_pch_edp(intel_dp))
- ironlake_edp_pll_on(encoder);
- else
- ironlake_edp_pll_off(encoder);
- }
+ /* Make sure the panel is off before trying to
+ * change the mode
+ */
+ ironlake_edp_backlight_off(intel_dp);
intel_dp_link_down(intel_dp);
+ ironlake_edp_panel_off(encoder);
}
static void intel_dp_commit(struct drm_encoder *encoder)
{
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev;
+ struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
- if (is_edp(intel_dp))
- ironlake_edp_panel_vdd_on(intel_dp);
-
+ ironlake_edp_panel_vdd_on(intel_dp);
+ intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
intel_dp_start_link_train(intel_dp);
-
- if (is_edp(intel_dp)) {
- ironlake_edp_panel_on(intel_dp);
- ironlake_edp_panel_vdd_off(intel_dp);
- }
+ ironlake_edp_panel_on(intel_dp);
+ ironlake_edp_panel_vdd_off(intel_dp, true);
intel_dp_complete_link_train(intel_dp);
-
- if (is_edp(intel_dp))
- ironlake_edp_backlight_on(dev);
+ ironlake_edp_backlight_on(intel_dp);
intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
+
+ if (HAS_PCH_CPT(dev))
+ intel_cpt_verify_modeset(dev, intel_crtc->pipe);
}
static void
@@ -1034,28 +1229,27 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
uint32_t dp_reg = I915_READ(intel_dp->output_reg);
if (mode != DRM_MODE_DPMS_ON) {
+ ironlake_edp_panel_vdd_on(intel_dp);
if (is_edp(intel_dp))
- ironlake_edp_backlight_off(dev);
+ ironlake_edp_backlight_off(intel_dp);
intel_dp_sink_dpms(intel_dp, mode);
intel_dp_link_down(intel_dp);
- if (is_edp(intel_dp))
- ironlake_edp_panel_off(dev);
+ ironlake_edp_panel_off(encoder);
if (is_edp(intel_dp) && !is_pch_edp(intel_dp))
ironlake_edp_pll_off(encoder);
+ ironlake_edp_panel_vdd_off(intel_dp, false);
} else {
- if (is_edp(intel_dp))
- ironlake_edp_panel_vdd_on(intel_dp);
+ ironlake_edp_panel_vdd_on(intel_dp);
intel_dp_sink_dpms(intel_dp, mode);
if (!(dp_reg & DP_PORT_EN)) {
intel_dp_start_link_train(intel_dp);
- if (is_edp(intel_dp)) {
- ironlake_edp_panel_on(intel_dp);
- ironlake_edp_panel_vdd_off(intel_dp);
- }
+ ironlake_edp_panel_on(intel_dp);
+ ironlake_edp_panel_vdd_off(intel_dp, true);
intel_dp_complete_link_train(intel_dp);
- }
- if (is_edp(intel_dp))
- ironlake_edp_backlight_on(dev);
+ ironlake_edp_backlight_on(intel_dp);
+ } else
+ ironlake_edp_panel_vdd_off(intel_dp, false);
+ ironlake_edp_backlight_on(intel_dp);
}
intel_dp->dpms_mode = mode;
}
@@ -1364,7 +1558,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
DP_LINK_CONFIGURATION_SIZE);
DP |= DP_PORT_EN;
- if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+ if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
DP &= ~DP_LINK_TRAIN_MASK_CPT;
else
DP &= ~DP_LINK_TRAIN_MASK;
@@ -1383,7 +1577,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
}
- if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+ if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
else
reg = DP | DP_LINK_TRAIN_PAT_1;
@@ -1458,7 +1652,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
}
- if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+ if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
reg = DP | DP_LINK_TRAIN_PAT_2_CPT;
else
reg = DP | DP_LINK_TRAIN_PAT_2;
@@ -1499,7 +1693,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
++tries;
}
- if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+ if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
reg = DP | DP_LINK_TRAIN_OFF_CPT;
else
reg = DP | DP_LINK_TRAIN_OFF;
@@ -1529,7 +1723,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
udelay(100);
}
- if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) {
+ if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) {
DP &= ~DP_LINK_TRAIN_MASK_CPT;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
} else {
@@ -1578,13 +1772,14 @@ intel_dp_link_down(struct intel_dp *intel_dp)
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
POSTING_READ(intel_dp->output_reg);
+ msleep(intel_dp->panel_power_down_delay);
}
static bool
intel_dp_get_dpcd(struct intel_dp *intel_dp)
{
if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
- sizeof (intel_dp->dpcd)) &&
+ sizeof(intel_dp->dpcd)) &&
(intel_dp->dpcd[DP_DPCD_REV] != 0)) {
return true;
}
@@ -1592,6 +1787,27 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
return false;
}
+static bool
+intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
+{
+ int ret;
+
+ ret = intel_dp_aux_native_read_retry(intel_dp,
+ DP_DEVICE_SERVICE_IRQ_VECTOR,
+ sink_irq_vector, 1);
+ if (!ret)
+ return false;
+
+ return true;
+}
+
+static void
+intel_dp_handle_test_request(struct intel_dp *intel_dp)
+{
+ /* NAK by default */
+ intel_dp_aux_native_write_1(intel_dp, DP_TEST_RESPONSE, DP_TEST_ACK);
+}
+
/*
* According to DP spec
* 5.1.2:
@@ -1604,6 +1820,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
static void
intel_dp_check_link_status(struct intel_dp *intel_dp)
{
+ u8 sink_irq_vector;
+
if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
return;
@@ -1622,6 +1840,20 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
return;
}
+ /* Try to read the source of the interrupt */
+ if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
+ intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) {
+ /* Clear interrupt source */
+ intel_dp_aux_native_write_1(intel_dp,
+ DP_DEVICE_SERVICE_IRQ_VECTOR,
+ sink_irq_vector);
+
+ if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST)
+ intel_dp_handle_test_request(intel_dp);
+ if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
+ DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
+ }
+
if (!intel_channel_eq_ok(intel_dp)) {
DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
drm_get_encoder_name(&intel_dp->base.base));
@@ -1683,6 +1915,31 @@ g4x_dp_detect(struct intel_dp *intel_dp)
return intel_dp_detect_dpcd(intel_dp);
}
+static struct edid *
+intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
+{
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
+ struct edid *edid;
+
+ ironlake_edp_panel_vdd_on(intel_dp);
+ edid = drm_get_edid(connector, adapter);
+ ironlake_edp_panel_vdd_off(intel_dp, false);
+ return edid;
+}
+
+static int
+intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *adapter)
+{
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
+ int ret;
+
+ ironlake_edp_panel_vdd_on(intel_dp);
+ ret = intel_ddc_get_modes(connector, adapter);
+ ironlake_edp_panel_vdd_off(intel_dp, false);
+ return ret;
+}
+
+
/**
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
*
@@ -1715,7 +1972,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
if (intel_dp->force_audio) {
intel_dp->has_audio = intel_dp->force_audio > 0;
} else {
- edid = drm_get_edid(connector, &intel_dp->adapter);
+ edid = intel_dp_get_edid(connector, &intel_dp->adapter);
if (edid) {
intel_dp->has_audio = drm_detect_monitor_audio(edid);
connector->display_info.raw_edid = NULL;
@@ -1736,28 +1993,36 @@ static int intel_dp_get_modes(struct drm_connector *connector)
/* We should parse the EDID data and find out if it has an audio sink
*/
- ret = intel_ddc_get_modes(connector, &intel_dp->adapter);
+ ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
if (ret) {
- if (is_edp(intel_dp) && !dev_priv->panel_fixed_mode) {
+ if (is_edp(intel_dp) && !intel_dp->panel_fixed_mode) {
struct drm_display_mode *newmode;
list_for_each_entry(newmode, &connector->probed_modes,
head) {
- if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
- dev_priv->panel_fixed_mode =
+ if ((newmode->type & DRM_MODE_TYPE_PREFERRED)) {
+ intel_dp->panel_fixed_mode =
drm_mode_duplicate(dev, newmode);
break;
}
}
}
-
return ret;
}
/* if eDP has no EDID, try to use fixed panel mode from VBT */
if (is_edp(intel_dp)) {
- if (dev_priv->panel_fixed_mode != NULL) {
+ /* initialize panel mode from VBT if available for eDP */
+ if (intel_dp->panel_fixed_mode == NULL && dev_priv->lfp_lvds_vbt_mode != NULL) {
+ intel_dp->panel_fixed_mode =
+ drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
+ if (intel_dp->panel_fixed_mode) {
+ intel_dp->panel_fixed_mode->type |=
+ DRM_MODE_TYPE_PREFERRED;
+ }
+ }
+ if (intel_dp->panel_fixed_mode) {
struct drm_display_mode *mode;
- mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
+ mode = drm_mode_duplicate(dev, intel_dp->panel_fixed_mode);
drm_mode_probed_add(connector, mode);
return 1;
}
@@ -1772,7 +2037,7 @@ intel_dp_detect_audio(struct drm_connector *connector)
struct edid *edid;
bool has_audio = false;
- edid = drm_get_edid(connector, &intel_dp->adapter);
+ edid = intel_dp_get_edid(connector, &intel_dp->adapter);
if (edid) {
has_audio = drm_detect_monitor_audio(edid);
@@ -1839,7 +2104,7 @@ done:
}
static void
-intel_dp_destroy (struct drm_connector *connector)
+intel_dp_destroy(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
@@ -1857,6 +2122,10 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
i2c_del_adapter(&intel_dp->adapter);
drm_encoder_cleanup(encoder);
+ if (is_edp(intel_dp)) {
+ cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+ ironlake_panel_vdd_off_sync(intel_dp);
+ }
kfree(intel_dp);
}
@@ -1896,7 +2165,7 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder)
/* Return which DP Port should be selected for Transcoder DP control */
int
-intel_trans_dp_port_sel (struct drm_crtc *crtc)
+intel_trans_dp_port_sel(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_mode_config *mode_config = &dev->mode_config;
@@ -1993,10 +2262,13 @@ intel_dp_init(struct drm_device *dev, int output_reg)
else if (output_reg == DP_D || output_reg == PCH_DP_D)
intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
- if (is_edp(intel_dp))
+ if (is_edp(intel_dp)) {
intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
+ INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
+ ironlake_panel_vdd_work);
+ }
- intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
+ intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
connector->interlace_allowed = true;
connector->doublescan_allowed = 0;
@@ -2032,25 +2304,60 @@ intel_dp_init(struct drm_device *dev, int output_reg)
break;
}
- intel_dp_i2c_init(intel_dp, intel_connector, name);
-
/* Cache some DPCD data in the eDP case */
if (is_edp(intel_dp)) {
bool ret;
- u32 pp_on, pp_div;
+ struct edp_power_seq cur, vbt;
+ u32 pp_on, pp_off, pp_div;
pp_on = I915_READ(PCH_PP_ON_DELAYS);
+ pp_off = I915_READ(PCH_PP_OFF_DELAYS);
pp_div = I915_READ(PCH_PP_DIVISOR);
- /* Get T3 & T12 values (note: VESA not bspec terminology) */
- dev_priv->panel_t3 = (pp_on & 0x1fff0000) >> 16;
- dev_priv->panel_t3 /= 10; /* t3 in 100us units */
- dev_priv->panel_t12 = pp_div & 0xf;
- dev_priv->panel_t12 *= 100; /* t12 in 100ms units */
+ /* Pull timing values out of registers */
+ cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
+ PANEL_POWER_UP_DELAY_SHIFT;
+
+ cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
+ PANEL_LIGHT_ON_DELAY_SHIFT;
+
+ cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
+ PANEL_LIGHT_OFF_DELAY_SHIFT;
+
+ cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
+ PANEL_POWER_DOWN_DELAY_SHIFT;
+
+ cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
+ PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
+
+ DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+ cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
+
+ vbt = dev_priv->edp.pps;
+
+ DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+ vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12);
+
+#define get_delay(field) ((max(cur.field, vbt.field) + 9) / 10)
+
+ intel_dp->panel_power_up_delay = get_delay(t1_t3);
+ intel_dp->backlight_on_delay = get_delay(t8);
+ intel_dp->backlight_off_delay = get_delay(t9);
+ intel_dp->panel_power_down_delay = get_delay(t10);
+ intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
+
+ DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
+ intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
+ intel_dp->panel_power_cycle_delay);
+
+ DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
+ intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
+
+ intel_dp->panel_off_jiffies = jiffies - intel_dp->panel_power_down_delay;
ironlake_edp_panel_vdd_on(intel_dp);
ret = intel_dp_get_dpcd(intel_dp);
- ironlake_edp_panel_vdd_off(intel_dp);
+ ironlake_edp_panel_vdd_off(intel_dp, false);
if (ret) {
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
dev_priv->no_aux_handshake =
@@ -2065,18 +2372,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
}
}
+ intel_dp_i2c_init(intel_dp, intel_connector, name);
+
intel_encoder->hot_plug = intel_dp_hot_plug;
if (is_edp(intel_dp)) {
- /* initialize panel mode from VBT if available for eDP */
- if (dev_priv->lfp_lvds_vbt_mode) {
- dev_priv->panel_fixed_mode =
- drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
- if (dev_priv->panel_fixed_mode) {
- dev_priv->panel_fixed_mode->type |=
- DRM_MODE_TYPE_PREFERRED;
- }
- }
dev_priv->int_edp_connector = connector;
intel_panel_setup_backlight(dev);
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fe1099d8817e..bd9a604b73da 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -34,7 +34,7 @@
#define _wait_for(COND, MS, W) ({ \
unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
int ret__ = 0; \
- while (! (COND)) { \
+ while (!(COND)) { \
if (time_after(jiffies, timeout__)) { \
ret__ = -ETIMEDOUT; \
break; \
@@ -49,10 +49,10 @@
#define MSLEEP(x) do { \
if (in_dbg_master()) \
- mdelay(x); \
+ mdelay(x); \
else \
msleep(x); \
-} while(0)
+} while (0)
#define KHz(x) (1000*x)
#define MHz(x) KHz(1000*x)
@@ -171,6 +171,9 @@ struct intel_crtc {
int16_t cursor_width, cursor_height;
bool cursor_visible;
unsigned int bpp;
+
+ bool no_pll; /* tertiary pipe for IVB */
+ bool use_pll_a;
};
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
@@ -184,7 +187,7 @@ struct intel_crtc {
#define DIP_VERSION_AVI 0x2
#define DIP_LEN_AVI 13
-#define DIP_TYPE_SPD 0x3
+#define DIP_TYPE_SPD 0x83
#define DIP_VERSION_SPD 0x1
#define DIP_LEN_SPD 25
#define DIP_SPD_UNKNOWN 0
@@ -284,7 +287,7 @@ void
intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
extern bool intel_dpd_is_edp(struct drm_device *dev);
-extern void intel_edp_link_config (struct intel_encoder *, int *, int *);
+extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
/* intel_panel.c */
@@ -304,8 +307,8 @@ extern void intel_panel_destroy_backlight(struct drm_device *dev);
extern enum drm_connector_status intel_panel_detect(struct drm_device *dev);
extern void intel_crtc_load_lut(struct drm_crtc *crtc);
-extern void intel_encoder_prepare (struct drm_encoder *encoder);
-extern void intel_encoder_commit (struct drm_encoder *encoder);
+extern void intel_encoder_prepare(struct drm_encoder *encoder);
+extern void intel_encoder_commit(struct drm_encoder *encoder);
extern void intel_encoder_destroy(struct drm_encoder *encoder);
static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector)
@@ -377,4 +380,8 @@ extern void intel_fb_output_poll_changed(struct drm_device *dev);
extern void intel_fb_restore_mode(struct drm_device *dev);
extern void intel_init_clock_gating(struct drm_device *dev);
+extern void intel_write_eld(struct drm_encoder *encoder,
+ struct drm_display_mode *mode);
+extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
+
#endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 226ba830f383..d4f5a0b2120d 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -69,8 +69,7 @@ void intel_dip_infoframe_csum(struct dip_infoframe *frame)
frame->checksum = 0;
frame->ecc = 0;
- /* Header isn't part of the checksum */
- for (i = 5; i < frame->len; i++)
+ for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++)
sum += data[i];
frame->checksum = 0x100 - sum;
@@ -104,7 +103,7 @@ static u32 intel_infoframe_flags(struct dip_infoframe *frame)
flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC;
break;
case DIP_TYPE_SPD:
- flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_2VSYNC;
+ flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_VSYNC;
break;
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
@@ -165,9 +164,9 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder,
flags = intel_infoframe_index(frame);
- val &= ~VIDEO_DIP_SELECT_MASK;
+ val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
- I915_WRITE(reg, val | flags);
+ I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
for (i = 0; i < len; i += 4) {
I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
@@ -245,16 +244,17 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
sdvox |= HDMI_MODE_SELECT;
if (intel_hdmi->has_audio) {
+ DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
+ pipe_name(intel_crtc->pipe));
sdvox |= SDVO_AUDIO_ENABLE;
sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
+ intel_write_eld(encoder, adjusted_mode);
}
- if (intel_crtc->pipe == 1) {
- if (HAS_PCH_CPT(dev))
- sdvox |= PORT_TRANS_B_SEL_CPT;
- else
- sdvox |= SDVO_PIPE_B_SELECT;
- }
+ if (HAS_PCH_CPT(dev))
+ sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
+ else if (intel_crtc->pipe == 1)
+ sdvox |= SDVO_PIPE_B_SELECT;
I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
POSTING_READ(intel_hdmi->sdvox_reg);
@@ -486,6 +486,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
struct intel_hdmi *intel_hdmi;
+ int i;
intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
if (!intel_hdmi)
@@ -511,7 +512,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
- intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
+ intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
/* Set up the DDC bus. */
if (sdvox_reg == SDVOB) {
@@ -538,10 +539,14 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
intel_hdmi->sdvox_reg = sdvox_reg;
- if (!HAS_PCH_SPLIT(dev))
+ if (!HAS_PCH_SPLIT(dev)) {
intel_hdmi->write_infoframe = i9xx_write_infoframe;
- else
+ I915_WRITE(VIDEO_DIP_CTL, 0);
+ } else {
intel_hdmi->write_infoframe = ironlake_write_infoframe;
+ for_each_pipe(i)
+ I915_WRITE(TVIDEO_DIP_CTL(i), 0);
+ }
drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index d98cee60b602..9ed5380e5a53 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -422,13 +422,7 @@ void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
- /* speed:
- * 0x0 = 100 KHz
- * 0x1 = 50 KHz
- * 0x2 = 400 KHz
- * 0x3 = 1000 Khz
- */
- bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8);
+ bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | speed;
}
void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 31da77f5c051..42f165a520de 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -888,9 +888,11 @@ bool intel_lvds_init(struct drm_device *dev)
intel_encoder->type = INTEL_OUTPUT_LVDS;
intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
- intel_encoder->crtc_mask = (1 << 1);
- if (INTEL_INFO(dev)->gen >= 5)
- intel_encoder->crtc_mask |= (1 << 0);
+ if (HAS_PCH_SPLIT(dev))
+ intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
+ else
+ intel_encoder->crtc_mask = (1 << 1);
+
drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index 3b26a3ba02dd..be2c6fe07d12 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/fb.h>
+#include <drm/drm_edid.h>
#include "drmP.h"
#include "intel_drv.h"
#include "i915_drv.h"
@@ -74,6 +75,7 @@ int intel_ddc_get_modes(struct drm_connector *connector,
if (edid) {
drm_mode_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
+ drm_edid_to_eld(connector, edid);
connector->display_info.raw_edid = NULL;
kfree(edid);
}
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index b8e8158bb16e..289140bc83cb 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -51,61 +51,61 @@
#define MBOX_ASLE (1<<2)
struct opregion_header {
- u8 signature[16];
- u32 size;
- u32 opregion_ver;
- u8 bios_ver[32];
- u8 vbios_ver[16];
- u8 driver_ver[16];
- u32 mboxes;
- u8 reserved[164];
+ u8 signature[16];
+ u32 size;
+ u32 opregion_ver;
+ u8 bios_ver[32];
+ u8 vbios_ver[16];
+ u8 driver_ver[16];
+ u32 mboxes;
+ u8 reserved[164];
} __attribute__((packed));
/* OpRegion mailbox #1: public ACPI methods */
struct opregion_acpi {
- u32 drdy; /* driver readiness */
- u32 csts; /* notification status */
- u32 cevt; /* current event */
- u8 rsvd1[20];
- u32 didl[8]; /* supported display devices ID list */
- u32 cpdl[8]; /* currently presented display list */
- u32 cadl[8]; /* currently active display list */
- u32 nadl[8]; /* next active devices list */
- u32 aslp; /* ASL sleep time-out */
- u32 tidx; /* toggle table index */
- u32 chpd; /* current hotplug enable indicator */
- u32 clid; /* current lid state*/
- u32 cdck; /* current docking state */
- u32 sxsw; /* Sx state resume */
- u32 evts; /* ASL supported events */
- u32 cnot; /* current OS notification */
- u32 nrdy; /* driver status */
- u8 rsvd2[60];
+ u32 drdy; /* driver readiness */
+ u32 csts; /* notification status */
+ u32 cevt; /* current event */
+ u8 rsvd1[20];
+ u32 didl[8]; /* supported display devices ID list */
+ u32 cpdl[8]; /* currently presented display list */
+ u32 cadl[8]; /* currently active display list */
+ u32 nadl[8]; /* next active devices list */
+ u32 aslp; /* ASL sleep time-out */
+ u32 tidx; /* toggle table index */
+ u32 chpd; /* current hotplug enable indicator */
+ u32 clid; /* current lid state*/
+ u32 cdck; /* current docking state */
+ u32 sxsw; /* Sx state resume */
+ u32 evts; /* ASL supported events */
+ u32 cnot; /* current OS notification */
+ u32 nrdy; /* driver status */
+ u8 rsvd2[60];
} __attribute__((packed));
/* OpRegion mailbox #2: SWSCI */
struct opregion_swsci {
- u32 scic; /* SWSCI command|status|data */
- u32 parm; /* command parameters */
- u32 dslp; /* driver sleep time-out */
- u8 rsvd[244];
+ u32 scic; /* SWSCI command|status|data */
+ u32 parm; /* command parameters */
+ u32 dslp; /* driver sleep time-out */
+ u8 rsvd[244];
} __attribute__((packed));
/* OpRegion mailbox #3: ASLE */
struct opregion_asle {
- u32 ardy; /* driver readiness */
- u32 aslc; /* ASLE interrupt command */
- u32 tche; /* technology enabled indicator */
- u32 alsi; /* current ALS illuminance reading */
- u32 bclp; /* backlight brightness to set */
- u32 pfit; /* panel fitting state */
- u32 cblv; /* current brightness level */
- u16 bclm[20]; /* backlight level duty cycle mapping table */
- u32 cpfm; /* current panel fitting mode */
- u32 epfm; /* enabled panel fitting modes */
- u8 plut[74]; /* panel LUT and identifier */
- u32 pfmb; /* PWM freq and min brightness */
- u8 rsvd[102];
+ u32 ardy; /* driver readiness */
+ u32 aslc; /* ASLE interrupt command */
+ u32 tche; /* technology enabled indicator */
+ u32 alsi; /* current ALS illuminance reading */
+ u32 bclp; /* backlight brightness to set */
+ u32 pfit; /* panel fitting state */
+ u32 cblv; /* current brightness level */
+ u16 bclm[20]; /* backlight level duty cycle mapping table */
+ u32 cpfm; /* current panel fitting mode */
+ u32 epfm; /* enabled panel fitting modes */
+ u8 plut[74]; /* panel LUT and identifier */
+ u32 pfmb; /* PWM freq and min brightness */
+ u8 rsvd[102];
} __attribute__((packed));
/* ASLE irq request bits */
@@ -361,7 +361,7 @@ static void intel_didl_outputs(struct drm_device *dev)
list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
if (i >= 8) {
- dev_printk (KERN_ERR, &dev->pdev->dev,
+ dev_printk(KERN_ERR, &dev->pdev->dev,
"More than 8 outputs detected\n");
return;
}
@@ -387,7 +387,7 @@ blind_set:
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
int output_type = ACPI_OTHER_OUTPUT;
if (i >= 8) {
- dev_printk (KERN_ERR, &dev->pdev->dev,
+ dev_printk(KERN_ERR, &dev->pdev->dev,
"More than 8 outputs detected\n");
return;
}
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index d36038086826..cdf17d4cc1f7 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -117,57 +117,57 @@
/* memory bufferd overlay registers */
struct overlay_registers {
- u32 OBUF_0Y;
- u32 OBUF_1Y;
- u32 OBUF_0U;
- u32 OBUF_0V;
- u32 OBUF_1U;
- u32 OBUF_1V;
- u32 OSTRIDE;
- u32 YRGB_VPH;
- u32 UV_VPH;
- u32 HORZ_PH;
- u32 INIT_PHS;
- u32 DWINPOS;
- u32 DWINSZ;
- u32 SWIDTH;
- u32 SWIDTHSW;
- u32 SHEIGHT;
- u32 YRGBSCALE;
- u32 UVSCALE;
- u32 OCLRC0;
- u32 OCLRC1;
- u32 DCLRKV;
- u32 DCLRKM;
- u32 SCLRKVH;
- u32 SCLRKVL;
- u32 SCLRKEN;
- u32 OCONFIG;
- u32 OCMD;
- u32 RESERVED1; /* 0x6C */
- u32 OSTART_0Y;
- u32 OSTART_1Y;
- u32 OSTART_0U;
- u32 OSTART_0V;
- u32 OSTART_1U;
- u32 OSTART_1V;
- u32 OTILEOFF_0Y;
- u32 OTILEOFF_1Y;
- u32 OTILEOFF_0U;
- u32 OTILEOFF_0V;
- u32 OTILEOFF_1U;
- u32 OTILEOFF_1V;
- u32 FASTHSCALE; /* 0xA0 */
- u32 UVSCALEV; /* 0xA4 */
- u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
- u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
- u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
- u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
- u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
- u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
- u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
- u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
- u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
+ u32 OBUF_0Y;
+ u32 OBUF_1Y;
+ u32 OBUF_0U;
+ u32 OBUF_0V;
+ u32 OBUF_1U;
+ u32 OBUF_1V;
+ u32 OSTRIDE;
+ u32 YRGB_VPH;
+ u32 UV_VPH;
+ u32 HORZ_PH;
+ u32 INIT_PHS;
+ u32 DWINPOS;
+ u32 DWINSZ;
+ u32 SWIDTH;
+ u32 SWIDTHSW;
+ u32 SHEIGHT;
+ u32 YRGBSCALE;
+ u32 UVSCALE;
+ u32 OCLRC0;
+ u32 OCLRC1;
+ u32 DCLRKV;
+ u32 DCLRKM;
+ u32 SCLRKVH;
+ u32 SCLRKVL;
+ u32 SCLRKEN;
+ u32 OCONFIG;
+ u32 OCMD;
+ u32 RESERVED1; /* 0x6C */
+ u32 OSTART_0Y;
+ u32 OSTART_1Y;
+ u32 OSTART_0U;
+ u32 OSTART_0V;
+ u32 OSTART_1U;
+ u32 OSTART_1V;
+ u32 OTILEOFF_0Y;
+ u32 OTILEOFF_1Y;
+ u32 OTILEOFF_0U;
+ u32 OTILEOFF_0V;
+ u32 OTILEOFF_1U;
+ u32 OTILEOFF_1V;
+ u32 FASTHSCALE; /* 0xA0 */
+ u32 UVSCALEV; /* 0xA4 */
+ u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
+ u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
+ u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
+ u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
+ u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
+ u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
+ u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
+ u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
+ u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
};
struct intel_overlay {
@@ -192,7 +192,7 @@ struct intel_overlay {
static struct overlay_registers *
intel_overlay_map_regs(struct intel_overlay *overlay)
{
- drm_i915_private_t *dev_priv = overlay->dev->dev_private;
+ drm_i915_private_t *dev_priv = overlay->dev->dev_private;
struct overlay_registers *regs;
if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
@@ -264,7 +264,7 @@ i830_activate_pipe_a(struct drm_device *dev)
mode = drm_mode_duplicate(dev, &vesa_640x480);
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
- if(!drm_crtc_helper_set_mode(&crtc->base, mode,
+ if (!drm_crtc_helper_set_mode(&crtc->base, mode,
crtc->base.x, crtc->base.y,
crtc->base.fb))
return 0;
@@ -332,7 +332,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
bool load_polyphase_filter)
{
struct drm_device *dev = overlay->dev;
- drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_request *request;
u32 flip_addr = overlay->flip_addr;
u32 tmp;
@@ -359,7 +359,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
}
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
OUT_RING(flip_addr);
- ADVANCE_LP_RING();
+ ADVANCE_LP_RING();
ret = i915_add_request(LP_RING(dev_priv), NULL, request);
if (ret) {
@@ -583,7 +583,7 @@ static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
ret = ((offset + width + mask) >> shift) - (offset >> shift);
if (!IS_GEN2(dev))
ret <<= 1;
- ret -=1;
+ ret -= 1;
return ret << 2;
}
@@ -817,7 +817,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
regs->SWIDTHSW = calc_swidthsw(overlay->dev,
params->offset_Y, tmp_width);
regs->SHEIGHT = params->src_h;
- regs->OBUF_0Y = new_bo->gtt_offset + params-> offset_Y;
+ regs->OBUF_0Y = new_bo->gtt_offset + params->offset_Y;
regs->OSTRIDE = params->stride_Y;
if (params->format & I915_OVERLAY_YUV_PLANAR) {
@@ -917,7 +917,7 @@ static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
* line with the intel documentation for the i965
*/
if (INTEL_INFO(dev)->gen >= 4) {
- /* on i965 use the PGM reg to read out the autoscaler values */
+ /* on i965 use the PGM reg to read out the autoscaler values */
ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
} else {
if (pfit_control & VERT_AUTO_SCALE)
@@ -1098,7 +1098,7 @@ static int intel_panel_fitter_pipe(struct drm_device *dev)
}
int intel_overlay_put_image(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+ struct drm_file *file_priv)
{
struct drm_intel_overlay_put_image *put_image_rec = data;
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -1301,10 +1301,10 @@ static int check_gamma(struct drm_intel_overlay_attrs *attrs)
}
int intel_overlay_attrs(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+ struct drm_file *file_priv)
{
struct drm_intel_overlay_attrs *attrs = data;
- drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_overlay *overlay;
struct overlay_registers *regs;
int ret;
@@ -1393,7 +1393,7 @@ out_unlock:
void intel_setup_overlay(struct drm_device *dev)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_overlay *overlay;
struct drm_i915_gem_object *reg_bo;
struct overlay_registers *regs;
@@ -1421,24 +1421,24 @@ void intel_setup_overlay(struct drm_device *dev)
ret = i915_gem_attach_phys_object(dev, reg_bo,
I915_GEM_PHYS_OVERLAY_REGS,
PAGE_SIZE);
- if (ret) {
- DRM_ERROR("failed to attach phys overlay regs\n");
- goto out_free_bo;
- }
+ if (ret) {
+ DRM_ERROR("failed to attach phys overlay regs\n");
+ goto out_free_bo;
+ }
overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
} else {
ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
if (ret) {
- DRM_ERROR("failed to pin overlay register bo\n");
- goto out_free_bo;
- }
+ DRM_ERROR("failed to pin overlay register bo\n");
+ goto out_free_bo;
+ }
overlay->flip_addr = reg_bo->gtt_offset;
ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
if (ret) {
- DRM_ERROR("failed to move overlay register bo into the GTT\n");
- goto out_unpin_bo;
- }
+ DRM_ERROR("failed to move overlay register bo into the GTT\n");
+ goto out_unpin_bo;
+ }
}
/* init all values */
@@ -1525,7 +1525,7 @@ static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
struct intel_overlay_error_state *
intel_overlay_capture_error_state(struct drm_device *dev)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_overlay *overlay = dev_priv->overlay;
struct intel_overlay_error_state *error;
struct overlay_registers __iomem *regs;
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index a9e0c7bcd317..499d4c0dbeeb 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -84,7 +84,7 @@ intel_pch_panel_fitting(struct drm_device *dev,
if (scaled_width > scaled_height) { /* pillar */
width = scaled_height / mode->vdisplay;
if (width & 1)
- width++;
+ width++;
x = (adjusted_mode->hdisplay - width + 1) / 2;
y = 0;
height = adjusted_mode->vdisplay;
@@ -206,7 +206,7 @@ u32 intel_panel_get_backlight(struct drm_device *dev)
if (IS_PINEVIEW(dev))
val >>= 1;
- if (is_backlight_combination_mode(dev)){
+ if (is_backlight_combination_mode(dev)) {
u8 lbpc;
val &= ~1;
@@ -226,7 +226,7 @@ static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
I915_WRITE(BLC_PWM_CPU_CTL, val | level);
}
-void intel_panel_set_backlight(struct drm_device *dev, u32 level)
+static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 tmp;
@@ -236,7 +236,7 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level)
if (HAS_PCH_SPLIT(dev))
return intel_pch_panel_set_backlight(dev, level);
- if (is_backlight_combination_mode(dev)){
+ if (is_backlight_combination_mode(dev)) {
u32 max = intel_panel_get_max_backlight(dev);
u8 lbpc;
@@ -254,16 +254,21 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level)
I915_WRITE(BLC_PWM_CTL, tmp | level);
}
-void intel_panel_disable_backlight(struct drm_device *dev)
+void intel_panel_set_backlight(struct drm_device *dev, u32 level)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- if (dev_priv->backlight_enabled) {
- dev_priv->backlight_level = intel_panel_get_backlight(dev);
- dev_priv->backlight_enabled = false;
- }
+ dev_priv->backlight_level = level;
+ if (dev_priv->backlight_enabled)
+ intel_panel_actually_set_backlight(dev, level);
+}
+
+void intel_panel_disable_backlight(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
- intel_panel_set_backlight(dev, 0);
+ dev_priv->backlight_enabled = false;
+ intel_panel_actually_set_backlight(dev, 0);
}
void intel_panel_enable_backlight(struct drm_device *dev)
@@ -273,8 +278,8 @@ void intel_panel_enable_backlight(struct drm_device *dev)
if (dev_priv->backlight_level == 0)
dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
- intel_panel_set_backlight(dev, dev_priv->backlight_level);
dev_priv->backlight_enabled = true;
+ intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
}
static void intel_panel_init_backlight(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index c30626ea9f93..ca70e2f10445 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -34,6 +34,16 @@
#include "i915_trace.h"
#include "intel_drv.h"
+/*
+ * 965+ support PIPE_CONTROL commands, which provide finer grained control
+ * over cache flushing.
+ */
+struct pipe_control {
+ struct drm_i915_gem_object *obj;
+ volatile u32 *cpu_page;
+ u32 gtt_offset;
+};
+
static inline int ring_space(struct intel_ring_buffer *ring)
{
int space = (ring->head & HEAD_ADDR) - (ring->tail + 8);
@@ -123,6 +133,118 @@ render_ring_flush(struct intel_ring_buffer *ring,
return 0;
}
+/**
+ * Emits a PIPE_CONTROL with a non-zero post-sync operation, for
+ * implementing two workarounds on gen6. From section 1.4.7.1
+ * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
+ *
+ * [DevSNB-C+{W/A}] Before any depth stall flush (including those
+ * produced by non-pipelined state commands), software needs to first
+ * send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
+ * 0.
+ *
+ * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
+ * =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
+ *
+ * And the workaround for these two requires this workaround first:
+ *
+ * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
+ * BEFORE the pipe-control with a post-sync op and no write-cache
+ * flushes.
+ *
+ * And this last workaround is tricky because of the requirements on
+ * that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
+ * volume 2 part 1:
+ *
+ * "1 of the following must also be set:
+ * - Render Target Cache Flush Enable ([12] of DW1)
+ * - Depth Cache Flush Enable ([0] of DW1)
+ * - Stall at Pixel Scoreboard ([1] of DW1)
+ * - Depth Stall ([13] of DW1)
+ * - Post-Sync Operation ([13] of DW1)
+ * - Notify Enable ([8] of DW1)"
+ *
+ * The cache flushes require the workaround flush that triggered this
+ * one, so we can't use it. Depth stall would trigger the same.
+ * Post-sync nonzero is what triggered this second workaround, so we
+ * can't use that one either. Notify enable is IRQs, which aren't
+ * really our business. That leaves only stall at scoreboard.
+ */
+static int
+intel_emit_post_sync_nonzero_flush(struct intel_ring_buffer *ring)
+{
+ struct pipe_control *pc = ring->private;
+ u32 scratch_addr = pc->gtt_offset + 128;
+ int ret;
+
+
+ ret = intel_ring_begin(ring, 6);
+ if (ret)
+ return ret;
+
+ intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
+ intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
+ PIPE_CONTROL_STALL_AT_SCOREBOARD);
+ intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
+ intel_ring_emit(ring, 0); /* low dword */
+ intel_ring_emit(ring, 0); /* high dword */
+ intel_ring_emit(ring, MI_NOOP);
+ intel_ring_advance(ring);
+
+ ret = intel_ring_begin(ring, 6);
+ if (ret)
+ return ret;
+
+ intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
+ intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
+ intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, MI_NOOP);
+ intel_ring_advance(ring);
+
+ return 0;
+}
+
+static int
+gen6_render_ring_flush(struct intel_ring_buffer *ring,
+ u32 invalidate_domains, u32 flush_domains)
+{
+ u32 flags = 0;
+ struct pipe_control *pc = ring->private;
+ u32 scratch_addr = pc->gtt_offset + 128;
+ int ret;
+
+ /* Force SNB workarounds for PIPE_CONTROL flushes */
+ intel_emit_post_sync_nonzero_flush(ring);
+
+ /* Just flush everything. Experiments have shown that reducing the
+ * number of bits based on the write domains has little performance
+ * impact.
+ */
+ flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
+ flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
+ flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
+ flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
+ flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
+
+ ret = intel_ring_begin(ring, 6);
+ if (ret)
+ return ret;
+
+ intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
+ intel_ring_emit(ring, flags);
+ intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
+ intel_ring_emit(ring, 0); /* lower dword */
+ intel_ring_emit(ring, 0); /* uppwer dword */
+ intel_ring_emit(ring, MI_NOOP);
+ intel_ring_advance(ring);
+
+ return 0;
+}
+
static void ring_write_tail(struct intel_ring_buffer *ring,
u32 value)
{
@@ -206,16 +328,6 @@ static int init_ring_common(struct intel_ring_buffer *ring)
return 0;
}
-/*
- * 965+ support PIPE_CONTROL commands, which provide finer grained control
- * over cache flushing.
- */
-struct pipe_control {
- struct drm_i915_gem_object *obj;
- volatile u32 *cpu_page;
- u32 gtt_offset;
-};
-
static int
init_pipe_control(struct intel_ring_buffer *ring)
{
@@ -296,8 +408,7 @@ static int init_render_ring(struct intel_ring_buffer *ring)
GFX_MODE_ENABLE(GFX_REPLAY_MODE));
}
- if (INTEL_INFO(dev)->gen >= 6) {
- } else if (IS_GEN5(dev)) {
+ if (INTEL_INFO(dev)->gen >= 5) {
ret = init_pipe_control(ring);
if (ret)
return ret;
@@ -315,83 +426,131 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring)
}
static void
-update_semaphore(struct intel_ring_buffer *ring, int i, u32 seqno)
+update_mboxes(struct intel_ring_buffer *ring,
+ u32 seqno,
+ u32 mmio_offset)
{
- struct drm_device *dev = ring->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- int id;
-
- /*
- * cs -> 1 = vcs, 0 = bcs
- * vcs -> 1 = bcs, 0 = cs,
- * bcs -> 1 = cs, 0 = vcs.
- */
- id = ring - dev_priv->ring;
- id += 2 - i;
- id %= 3;
-
- intel_ring_emit(ring,
- MI_SEMAPHORE_MBOX |
- MI_SEMAPHORE_REGISTER |
- MI_SEMAPHORE_UPDATE);
+ intel_ring_emit(ring, MI_SEMAPHORE_MBOX |
+ MI_SEMAPHORE_GLOBAL_GTT |
+ MI_SEMAPHORE_REGISTER |
+ MI_SEMAPHORE_UPDATE);
intel_ring_emit(ring, seqno);
- intel_ring_emit(ring,
- RING_SYNC_0(dev_priv->ring[id].mmio_base) + 4*i);
+ intel_ring_emit(ring, mmio_offset);
}
+/**
+ * gen6_add_request - Update the semaphore mailbox registers
+ *
+ * @ring - ring that is adding a request
+ * @seqno - return seqno stuck into the ring
+ *
+ * Update the mailbox registers in the *other* rings with the current seqno.
+ * This acts like a signal in the canonical semaphore.
+ */
static int
gen6_add_request(struct intel_ring_buffer *ring,
- u32 *result)
+ u32 *seqno)
{
- u32 seqno;
+ u32 mbox1_reg;
+ u32 mbox2_reg;
int ret;
ret = intel_ring_begin(ring, 10);
if (ret)
return ret;
- seqno = i915_gem_get_seqno(ring->dev);
- update_semaphore(ring, 0, seqno);
- update_semaphore(ring, 1, seqno);
+ mbox1_reg = ring->signal_mbox[0];
+ mbox2_reg = ring->signal_mbox[1];
+ *seqno = i915_gem_get_seqno(ring->dev);
+
+ update_mboxes(ring, *seqno, mbox1_reg);
+ update_mboxes(ring, *seqno, mbox2_reg);
intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
- intel_ring_emit(ring, seqno);
+ intel_ring_emit(ring, *seqno);
intel_ring_emit(ring, MI_USER_INTERRUPT);
intel_ring_advance(ring);
- *result = seqno;
return 0;
}
-int
-intel_ring_sync(struct intel_ring_buffer *ring,
- struct intel_ring_buffer *to,
+/**
+ * intel_ring_sync - sync the waiter to the signaller on seqno
+ *
+ * @waiter - ring that is waiting
+ * @signaller - ring which has, or will signal
+ * @seqno - seqno which the waiter will block on
+ */
+static int
+intel_ring_sync(struct intel_ring_buffer *waiter,
+ struct intel_ring_buffer *signaller,
+ int ring,
u32 seqno)
{
int ret;
+ u32 dw1 = MI_SEMAPHORE_MBOX |
+ MI_SEMAPHORE_COMPARE |
+ MI_SEMAPHORE_REGISTER;
- ret = intel_ring_begin(ring, 4);
+ ret = intel_ring_begin(waiter, 4);
if (ret)
return ret;
- intel_ring_emit(ring,
- MI_SEMAPHORE_MBOX |
- MI_SEMAPHORE_REGISTER |
- intel_ring_sync_index(ring, to) << 17 |
- MI_SEMAPHORE_COMPARE);
- intel_ring_emit(ring, seqno);
- intel_ring_emit(ring, 0);
- intel_ring_emit(ring, MI_NOOP);
- intel_ring_advance(ring);
+ intel_ring_emit(waiter, dw1 | signaller->semaphore_register[ring]);
+ intel_ring_emit(waiter, seqno);
+ intel_ring_emit(waiter, 0);
+ intel_ring_emit(waiter, MI_NOOP);
+ intel_ring_advance(waiter);
return 0;
}
+/* VCS->RCS (RVSYNC) or BCS->RCS (RBSYNC) */
+int
+render_ring_sync_to(struct intel_ring_buffer *waiter,
+ struct intel_ring_buffer *signaller,
+ u32 seqno)
+{
+ WARN_ON(signaller->semaphore_register[RCS] == MI_SEMAPHORE_SYNC_INVALID);
+ return intel_ring_sync(waiter,
+ signaller,
+ RCS,
+ seqno);
+}
+
+/* RCS->VCS (VRSYNC) or BCS->VCS (VBSYNC) */
+int
+gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter,
+ struct intel_ring_buffer *signaller,
+ u32 seqno)
+{
+ WARN_ON(signaller->semaphore_register[VCS] == MI_SEMAPHORE_SYNC_INVALID);
+ return intel_ring_sync(waiter,
+ signaller,
+ VCS,
+ seqno);
+}
+
+/* RCS->BCS (BRSYNC) or VCS->BCS (BVSYNC) */
+int
+gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter,
+ struct intel_ring_buffer *signaller,
+ u32 seqno)
+{
+ WARN_ON(signaller->semaphore_register[BCS] == MI_SEMAPHORE_SYNC_INVALID);
+ return intel_ring_sync(waiter,
+ signaller,
+ BCS,
+ seqno);
+}
+
+
+
#define PIPE_CONTROL_FLUSH(ring__, addr__) \
do { \
- intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \
- PIPE_CONTROL_DEPTH_STALL | 2); \
+ intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \
+ PIPE_CONTROL_DEPTH_STALL); \
intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \
intel_ring_emit(ring__, 0); \
intel_ring_emit(ring__, 0); \
@@ -419,8 +578,9 @@ pc_render_add_request(struct intel_ring_buffer *ring,
if (ret)
return ret;
- intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
- PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
+ intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
+ PIPE_CONTROL_WRITE_FLUSH |
+ PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, seqno);
intel_ring_emit(ring, 0);
@@ -435,8 +595,9 @@ pc_render_add_request(struct intel_ring_buffer *ring,
PIPE_CONTROL_FLUSH(ring, scratch_addr);
scratch_addr += 128;
PIPE_CONTROL_FLUSH(ring, scratch_addr);
- intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
- PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
+ intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
+ PIPE_CONTROL_WRITE_FLUSH |
+ PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
PIPE_CONTROL_NOTIFY);
intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, seqno);
@@ -1026,7 +1187,12 @@ static const struct intel_ring_buffer render_ring = {
.irq_get = render_ring_get_irq,
.irq_put = render_ring_put_irq,
.dispatch_execbuffer = render_ring_dispatch_execbuffer,
- .cleanup = render_ring_cleanup,
+ .cleanup = render_ring_cleanup,
+ .sync_to = render_ring_sync_to,
+ .semaphore_register = {MI_SEMAPHORE_SYNC_INVALID,
+ MI_SEMAPHORE_SYNC_RV,
+ MI_SEMAPHORE_SYNC_RB},
+ .signal_mbox = {GEN6_VRSYNC, GEN6_BRSYNC},
};
/* ring buffer for bit-stream decoder */
@@ -1050,23 +1216,23 @@ static const struct intel_ring_buffer bsd_ring = {
static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring,
u32 value)
{
- drm_i915_private_t *dev_priv = ring->dev->dev_private;
+ drm_i915_private_t *dev_priv = ring->dev->dev_private;
/* Every tail move must follow the sequence below */
- I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
- GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
- GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);
- I915_WRITE(GEN6_BSD_RNCID, 0x0);
-
- if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
- GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0,
- 50))
- DRM_ERROR("timed out waiting for IDLE Indicator\n");
-
- I915_WRITE_TAIL(ring, value);
- I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
- GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
- GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
+ I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
+ GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
+ GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);
+ I915_WRITE(GEN6_BSD_RNCID, 0x0);
+
+ if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
+ GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0,
+ 50))
+ DRM_ERROR("timed out waiting for IDLE Indicator\n");
+
+ I915_WRITE_TAIL(ring, value);
+ I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
+ GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
+ GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
}
static int gen6_ring_flush(struct intel_ring_buffer *ring,
@@ -1094,18 +1260,18 @@ static int
gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
u32 offset, u32 len)
{
- int ret;
+ int ret;
- ret = intel_ring_begin(ring, 2);
- if (ret)
- return ret;
+ ret = intel_ring_begin(ring, 2);
+ if (ret)
+ return ret;
- intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
- /* bit0-7 is the length on GEN6+ */
- intel_ring_emit(ring, offset);
- intel_ring_advance(ring);
+ intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
+ /* bit0-7 is the length on GEN6+ */
+ intel_ring_emit(ring, offset);
+ intel_ring_advance(ring);
- return 0;
+ return 0;
}
static bool
@@ -1154,6 +1320,11 @@ static const struct intel_ring_buffer gen6_bsd_ring = {
.irq_get = gen6_bsd_ring_get_irq,
.irq_put = gen6_bsd_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
+ .sync_to = gen6_bsd_ring_sync_to,
+ .semaphore_register = {MI_SEMAPHORE_SYNC_VR,
+ MI_SEMAPHORE_SYNC_INVALID,
+ MI_SEMAPHORE_SYNC_VB},
+ .signal_mbox = {GEN6_RVSYNC, GEN6_BVSYNC},
};
/* Blitter support (SandyBridge+) */
@@ -1272,19 +1443,24 @@ static void blt_ring_cleanup(struct intel_ring_buffer *ring)
}
static const struct intel_ring_buffer gen6_blt_ring = {
- .name = "blt ring",
- .id = RING_BLT,
- .mmio_base = BLT_RING_BASE,
- .size = 32 * PAGE_SIZE,
- .init = blt_ring_init,
- .write_tail = ring_write_tail,
- .flush = blt_ring_flush,
- .add_request = gen6_add_request,
- .get_seqno = ring_get_seqno,
- .irq_get = blt_ring_get_irq,
- .irq_put = blt_ring_put_irq,
- .dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
- .cleanup = blt_ring_cleanup,
+ .name = "blt ring",
+ .id = RING_BLT,
+ .mmio_base = BLT_RING_BASE,
+ .size = 32 * PAGE_SIZE,
+ .init = blt_ring_init,
+ .write_tail = ring_write_tail,
+ .flush = blt_ring_flush,
+ .add_request = gen6_add_request,
+ .get_seqno = ring_get_seqno,
+ .irq_get = blt_ring_get_irq,
+ .irq_put = blt_ring_put_irq,
+ .dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
+ .cleanup = blt_ring_cleanup,
+ .sync_to = gen6_blt_ring_sync_to,
+ .semaphore_register = {MI_SEMAPHORE_SYNC_BR,
+ MI_SEMAPHORE_SYNC_BV,
+ MI_SEMAPHORE_SYNC_INVALID},
+ .signal_mbox = {GEN6_RBSYNC, GEN6_VBSYNC},
};
int intel_init_render_ring_buffer(struct drm_device *dev)
@@ -1295,6 +1471,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
*ring = render_ring;
if (INTEL_INFO(dev)->gen >= 6) {
ring->add_request = gen6_add_request;
+ ring->flush = gen6_render_ring_flush;
ring->irq_get = gen6_render_ring_get_irq;
ring->irq_put = gen6_render_ring_put_irq;
} else if (IS_GEN5(dev)) {
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 39ac2b634ae5..68281c96c558 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -2,10 +2,10 @@
#define _INTEL_RINGBUFFER_H_
enum {
- RCS = 0x0,
- VCS,
- BCS,
- I915_NUM_RINGS,
+ RCS = 0x0,
+ VCS,
+ BCS,
+ I915_NUM_RINGS,
};
struct intel_hw_status_page {
@@ -75,7 +75,12 @@ struct intel_ring_buffer {
int (*dispatch_execbuffer)(struct intel_ring_buffer *ring,
u32 offset, u32 length);
void (*cleanup)(struct intel_ring_buffer *ring);
+ int (*sync_to)(struct intel_ring_buffer *ring,
+ struct intel_ring_buffer *to,
+ u32 seqno);
+ u32 semaphore_register[3]; /*our mbox written by others */
+ u32 signal_mbox[2]; /* mboxes this ring signals to */
/**
* List of objects currently involved in rendering from the
* ringbuffer.
@@ -180,9 +185,6 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring,
void intel_ring_advance(struct intel_ring_buffer *ring);
u32 intel_ring_get_seqno(struct intel_ring_buffer *ring);
-int intel_ring_sync(struct intel_ring_buffer *ring,
- struct intel_ring_buffer *to,
- u32 seqno);
int intel_init_render_ring_buffer(struct drm_device *dev);
int intel_init_bsd_ring_buffer(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 6348c499616f..6db3b1ccb6eb 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -43,7 +43,7 @@
#define SDVO_TV_MASK (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0)
#define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\
- SDVO_TV_MASK)
+ SDVO_TV_MASK)
#define IS_TV(c) (c->output_flag & SDVO_TV_MASK)
#define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK)
@@ -288,117 +288,117 @@ static const struct _sdvo_cmd_name {
u8 cmd;
const char *name;
} sdvo_cmd_names[] = {
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS),
-
- /* Add the op code for SDVO enhancements */
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HPOS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HPOS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HPOS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_VPOS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_VPOS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_VPOS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_2D),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_2D),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_2D),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SHARPNESS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SHARPNESS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SHARPNESS),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DOT_CRAWL),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DOT_CRAWL),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_CHROMA_FILTER),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_CHROMA_FILTER),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_CHROMA_FILTER),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_LUMA_FILTER),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_LUMA_FILTER),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_LUMA_FILTER),
-
- /* HDMI op code */
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS),
+
+ /* Add the op code for SDVO enhancements */
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HPOS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HPOS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HPOS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_VPOS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_VPOS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_VPOS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_2D),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_2D),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_2D),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SHARPNESS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SHARPNESS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SHARPNESS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DOT_CRAWL),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DOT_CRAWL),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_CHROMA_FILTER),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_CHROMA_FILTER),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_CHROMA_FILTER),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_LUMA_FILTER),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_LUMA_FILTER),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_LUMA_FILTER),
+
+ /* HDMI op code */
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA),
};
#define IS_SDVOB(reg) (reg == SDVOB || reg == PCH_SDVOB)
@@ -1232,8 +1232,7 @@ static bool
intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
{
/* Is there more than one type of output? */
- int caps = intel_sdvo->caps.output_flags & 0xf;
- return caps & -caps;
+ return hweight16(intel_sdvo->caps.output_flags) > 1;
}
static struct edid *
@@ -1254,7 +1253,7 @@ intel_sdvo_get_analog_edid(struct drm_connector *connector)
}
enum drm_connector_status
-intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
+intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
{
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
enum drm_connector_status status;
@@ -1349,7 +1348,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
if ((intel_sdvo_connector->output_flag & response) == 0)
ret = connector_status_disconnected;
else if (IS_TMDS(intel_sdvo_connector))
- ret = intel_sdvo_hdmi_sink_detect(connector);
+ ret = intel_sdvo_tmds_sink_detect(connector);
else {
struct edid *edid;
@@ -1896,7 +1895,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
struct intel_sdvo *sdvo, u32 reg)
{
struct sdvo_device_mapping *mapping;
- u8 pin, speed;
+ u8 pin;
if (IS_SDVOB(reg))
mapping = &dev_priv->sdvo_mappings[0];
@@ -1904,18 +1903,16 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
mapping = &dev_priv->sdvo_mappings[1];
pin = GMBUS_PORT_DPB;
- speed = GMBUS_RATE_1MHZ >> 8;
- if (mapping->initialized) {
+ if (mapping->initialized)
pin = mapping->i2c_pin;
- speed = mapping->i2c_speed;
- }
if (pin < GMBUS_NUM_PORTS) {
sdvo->i2c = &dev_priv->gmbus[pin].adapter;
- intel_gmbus_set_speed(sdvo->i2c, speed);
+ intel_gmbus_set_speed(sdvo->i2c, GMBUS_RATE_1MHZ);
intel_gmbus_force_bit(sdvo->i2c, true);
- } else
+ } else {
sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
+ }
}
static bool
@@ -2206,7 +2203,7 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
bytes[0], bytes[1]);
return false;
}
- intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1);
+ intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
return true;
}
@@ -2275,7 +2272,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
DRM_DEBUG_KMS(#name ": max %d, default %d, current %d\n", \
data_value[0], data_value[1], response); \
} \
-} while(0)
+} while (0)
static bool
intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo,
@@ -2442,7 +2439,7 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo,
if (IS_TV(intel_sdvo_connector))
return intel_sdvo_create_enhance_property_tv(intel_sdvo, intel_sdvo_connector, enhancements.reply);
- else if(IS_LVDS(intel_sdvo_connector))
+ else if (IS_LVDS(intel_sdvo_connector))
return intel_sdvo_create_enhance_property_lvds(intel_sdvo, intel_sdvo_connector, enhancements.reply);
else
return true;
diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h
index 4f4e23bc2d16..4aa6f343e49a 100644
--- a/drivers/gpu/drm/i915/intel_sdvo_regs.h
+++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h
@@ -46,63 +46,63 @@
#define SDVO_OUTPUT_LAST (14)
struct intel_sdvo_caps {
- u8 vendor_id;
- u8 device_id;
- u8 device_rev_id;
- u8 sdvo_version_major;
- u8 sdvo_version_minor;
- unsigned int sdvo_inputs_mask:2;
- unsigned int smooth_scaling:1;
- unsigned int sharp_scaling:1;
- unsigned int up_scaling:1;
- unsigned int down_scaling:1;
- unsigned int stall_support:1;
- unsigned int pad:1;
- u16 output_flags;
+ u8 vendor_id;
+ u8 device_id;
+ u8 device_rev_id;
+ u8 sdvo_version_major;
+ u8 sdvo_version_minor;
+ unsigned int sdvo_inputs_mask:2;
+ unsigned int smooth_scaling:1;
+ unsigned int sharp_scaling:1;
+ unsigned int up_scaling:1;
+ unsigned int down_scaling:1;
+ unsigned int stall_support:1;
+ unsigned int pad:1;
+ u16 output_flags;
} __attribute__((packed));
/** This matches the EDID DTD structure, more or less */
struct intel_sdvo_dtd {
- struct {
- u16 clock; /**< pixel clock, in 10kHz units */
- u8 h_active; /**< lower 8 bits (pixels) */
- u8 h_blank; /**< lower 8 bits (pixels) */
- u8 h_high; /**< upper 4 bits each h_active, h_blank */
- u8 v_active; /**< lower 8 bits (lines) */
- u8 v_blank; /**< lower 8 bits (lines) */
- u8 v_high; /**< upper 4 bits each v_active, v_blank */
- } part1;
-
- struct {
- u8 h_sync_off; /**< lower 8 bits, from hblank start */
- u8 h_sync_width; /**< lower 8 bits (pixels) */
- /** lower 4 bits each vsync offset, vsync width */
- u8 v_sync_off_width;
- /**
- * 2 high bits of hsync offset, 2 high bits of hsync width,
- * bits 4-5 of vsync offset, and 2 high bits of vsync width.
- */
- u8 sync_off_width_high;
- u8 dtd_flags;
- u8 sdvo_flags;
- /** bits 6-7 of vsync offset at bits 6-7 */
- u8 v_sync_off_high;
- u8 reserved;
- } part2;
+ struct {
+ u16 clock; /**< pixel clock, in 10kHz units */
+ u8 h_active; /**< lower 8 bits (pixels) */
+ u8 h_blank; /**< lower 8 bits (pixels) */
+ u8 h_high; /**< upper 4 bits each h_active, h_blank */
+ u8 v_active; /**< lower 8 bits (lines) */
+ u8 v_blank; /**< lower 8 bits (lines) */
+ u8 v_high; /**< upper 4 bits each v_active, v_blank */
+ } part1;
+
+ struct {
+ u8 h_sync_off; /**< lower 8 bits, from hblank start */
+ u8 h_sync_width; /**< lower 8 bits (pixels) */
+ /** lower 4 bits each vsync offset, vsync width */
+ u8 v_sync_off_width;
+ /**
+ * 2 high bits of hsync offset, 2 high bits of hsync width,
+ * bits 4-5 of vsync offset, and 2 high bits of vsync width.
+ */
+ u8 sync_off_width_high;
+ u8 dtd_flags;
+ u8 sdvo_flags;
+ /** bits 6-7 of vsync offset at bits 6-7 */
+ u8 v_sync_off_high;
+ u8 reserved;
+ } part2;
} __attribute__((packed));
struct intel_sdvo_pixel_clock_range {
- u16 min; /**< pixel clock, in 10kHz units */
- u16 max; /**< pixel clock, in 10kHz units */
+ u16 min; /**< pixel clock, in 10kHz units */
+ u16 max; /**< pixel clock, in 10kHz units */
} __attribute__((packed));
struct intel_sdvo_preferred_input_timing_args {
- u16 clock;
- u16 width;
- u16 height;
- u8 interlace:1;
- u8 scaled:1;
- u8 pad:6;
+ u16 clock;
+ u16 width;
+ u16 height;
+ u8 interlace:1;
+ u8 scaled:1;
+ u8 pad:6;
} __attribute__((packed));
/* I2C registers for SDVO */
@@ -154,9 +154,9 @@ struct intel_sdvo_preferred_input_timing_args {
*/
#define SDVO_CMD_GET_TRAINED_INPUTS 0x03
struct intel_sdvo_get_trained_inputs_response {
- unsigned int input0_trained:1;
- unsigned int input1_trained:1;
- unsigned int pad:6;
+ unsigned int input0_trained:1;
+ unsigned int input1_trained:1;
+ unsigned int pad:6;
} __attribute__((packed));
/** Returns a struct intel_sdvo_output_flags of active outputs. */
@@ -177,7 +177,7 @@ struct intel_sdvo_get_trained_inputs_response {
*/
#define SDVO_CMD_GET_IN_OUT_MAP 0x06
struct intel_sdvo_in_out_map {
- u16 in0, in1;
+ u16 in0, in1;
};
/**
@@ -210,10 +210,10 @@ struct intel_sdvo_in_out_map {
#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f
struct intel_sdvo_get_interrupt_event_source_response {
- u16 interrupt_status;
- unsigned int ambient_light_interrupt:1;
- unsigned int hdmi_audio_encrypt_change:1;
- unsigned int pad:6;
+ u16 interrupt_status;
+ unsigned int ambient_light_interrupt:1;
+ unsigned int hdmi_audio_encrypt_change:1;
+ unsigned int pad:6;
} __attribute__((packed));
/**
@@ -225,8 +225,8 @@ struct intel_sdvo_get_interrupt_event_source_response {
*/
#define SDVO_CMD_SET_TARGET_INPUT 0x10
struct intel_sdvo_set_target_input_args {
- unsigned int target_1:1;
- unsigned int pad:7;
+ unsigned int target_1:1;
+ unsigned int pad:7;
} __attribute__((packed));
/**
@@ -314,57 +314,57 @@ struct intel_sdvo_set_target_input_args {
#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27
/** 6 bytes of bit flags for TV formats shared by all TV format functions */
struct intel_sdvo_tv_format {
- unsigned int ntsc_m:1;
- unsigned int ntsc_j:1;
- unsigned int ntsc_443:1;
- unsigned int pal_b:1;
- unsigned int pal_d:1;
- unsigned int pal_g:1;
- unsigned int pal_h:1;
- unsigned int pal_i:1;
-
- unsigned int pal_m:1;
- unsigned int pal_n:1;
- unsigned int pal_nc:1;
- unsigned int pal_60:1;
- unsigned int secam_b:1;
- unsigned int secam_d:1;
- unsigned int secam_g:1;
- unsigned int secam_k:1;
-
- unsigned int secam_k1:1;
- unsigned int secam_l:1;
- unsigned int secam_60:1;
- unsigned int hdtv_std_smpte_240m_1080i_59:1;
- unsigned int hdtv_std_smpte_240m_1080i_60:1;
- unsigned int hdtv_std_smpte_260m_1080i_59:1;
- unsigned int hdtv_std_smpte_260m_1080i_60:1;
- unsigned int hdtv_std_smpte_274m_1080i_50:1;
-
- unsigned int hdtv_std_smpte_274m_1080i_59:1;
- unsigned int hdtv_std_smpte_274m_1080i_60:1;
- unsigned int hdtv_std_smpte_274m_1080p_23:1;
- unsigned int hdtv_std_smpte_274m_1080p_24:1;
- unsigned int hdtv_std_smpte_274m_1080p_25:1;
- unsigned int hdtv_std_smpte_274m_1080p_29:1;
- unsigned int hdtv_std_smpte_274m_1080p_30:1;
- unsigned int hdtv_std_smpte_274m_1080p_50:1;
-
- unsigned int hdtv_std_smpte_274m_1080p_59:1;
- unsigned int hdtv_std_smpte_274m_1080p_60:1;
- unsigned int hdtv_std_smpte_295m_1080i_50:1;
- unsigned int hdtv_std_smpte_295m_1080p_50:1;
- unsigned int hdtv_std_smpte_296m_720p_59:1;
- unsigned int hdtv_std_smpte_296m_720p_60:1;
- unsigned int hdtv_std_smpte_296m_720p_50:1;
- unsigned int hdtv_std_smpte_293m_480p_59:1;
-
- unsigned int hdtv_std_smpte_170m_480i_59:1;
- unsigned int hdtv_std_iturbt601_576i_50:1;
- unsigned int hdtv_std_iturbt601_576p_50:1;
- unsigned int hdtv_std_eia_7702a_480i_60:1;
- unsigned int hdtv_std_eia_7702a_480p_60:1;
- unsigned int pad:3;
+ unsigned int ntsc_m:1;
+ unsigned int ntsc_j:1;
+ unsigned int ntsc_443:1;
+ unsigned int pal_b:1;
+ unsigned int pal_d:1;
+ unsigned int pal_g:1;
+ unsigned int pal_h:1;
+ unsigned int pal_i:1;
+
+ unsigned int pal_m:1;
+ unsigned int pal_n:1;
+ unsigned int pal_nc:1;
+ unsigned int pal_60:1;
+ unsigned int secam_b:1;
+ unsigned int secam_d:1;
+ unsigned int secam_g:1;
+ unsigned int secam_k:1;
+
+ unsigned int secam_k1:1;
+ unsigned int secam_l:1;
+ unsigned int secam_60:1;
+ unsigned int hdtv_std_smpte_240m_1080i_59:1;
+ unsigned int hdtv_std_smpte_240m_1080i_60:1;
+ unsigned int hdtv_std_smpte_260m_1080i_59:1;
+ unsigned int hdtv_std_smpte_260m_1080i_60:1;
+ unsigned int hdtv_std_smpte_274m_1080i_50:1;
+
+ unsigned int hdtv_std_smpte_274m_1080i_59:1;
+ unsigned int hdtv_std_smpte_274m_1080i_60:1;
+ unsigned int hdtv_std_smpte_274m_1080p_23:1;
+ unsigned int hdtv_std_smpte_274m_1080p_24:1;
+ unsigned int hdtv_std_smpte_274m_1080p_25:1;
+ unsigned int hdtv_std_smpte_274m_1080p_29:1;
+ unsigned int hdtv_std_smpte_274m_1080p_30:1;
+ unsigned int hdtv_std_smpte_274m_1080p_50:1;
+
+ unsigned int hdtv_std_smpte_274m_1080p_59:1;
+ unsigned int hdtv_std_smpte_274m_1080p_60:1;
+ unsigned int hdtv_std_smpte_295m_1080i_50:1;
+ unsigned int hdtv_std_smpte_295m_1080p_50:1;
+ unsigned int hdtv_std_smpte_296m_720p_59:1;
+ unsigned int hdtv_std_smpte_296m_720p_60:1;
+ unsigned int hdtv_std_smpte_296m_720p_50:1;
+ unsigned int hdtv_std_smpte_293m_480p_59:1;
+
+ unsigned int hdtv_std_smpte_170m_480i_59:1;
+ unsigned int hdtv_std_iturbt601_576i_50:1;
+ unsigned int hdtv_std_iturbt601_576p_50:1;
+ unsigned int hdtv_std_eia_7702a_480i_60:1;
+ unsigned int hdtv_std_eia_7702a_480p_60:1;
+ unsigned int pad:3;
} __attribute__((packed));
#define SDVO_CMD_GET_TV_FORMAT 0x28
@@ -374,53 +374,53 @@ struct intel_sdvo_tv_format {
/** Returns the resolutiosn that can be used with the given TV format */
#define SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT 0x83
struct intel_sdvo_sdtv_resolution_request {
- unsigned int ntsc_m:1;
- unsigned int ntsc_j:1;
- unsigned int ntsc_443:1;
- unsigned int pal_b:1;
- unsigned int pal_d:1;
- unsigned int pal_g:1;
- unsigned int pal_h:1;
- unsigned int pal_i:1;
-
- unsigned int pal_m:1;
- unsigned int pal_n:1;
- unsigned int pal_nc:1;
- unsigned int pal_60:1;
- unsigned int secam_b:1;
- unsigned int secam_d:1;
- unsigned int secam_g:1;
- unsigned int secam_k:1;
-
- unsigned int secam_k1:1;
- unsigned int secam_l:1;
- unsigned int secam_60:1;
- unsigned int pad:5;
+ unsigned int ntsc_m:1;
+ unsigned int ntsc_j:1;
+ unsigned int ntsc_443:1;
+ unsigned int pal_b:1;
+ unsigned int pal_d:1;
+ unsigned int pal_g:1;
+ unsigned int pal_h:1;
+ unsigned int pal_i:1;
+
+ unsigned int pal_m:1;
+ unsigned int pal_n:1;
+ unsigned int pal_nc:1;
+ unsigned int pal_60:1;
+ unsigned int secam_b:1;
+ unsigned int secam_d:1;
+ unsigned int secam_g:1;
+ unsigned int secam_k:1;
+
+ unsigned int secam_k1:1;
+ unsigned int secam_l:1;
+ unsigned int secam_60:1;
+ unsigned int pad:5;
} __attribute__((packed));
struct intel_sdvo_sdtv_resolution_reply {
- unsigned int res_320x200:1;
- unsigned int res_320x240:1;
- unsigned int res_400x300:1;
- unsigned int res_640x350:1;
- unsigned int res_640x400:1;
- unsigned int res_640x480:1;
- unsigned int res_704x480:1;
- unsigned int res_704x576:1;
-
- unsigned int res_720x350:1;
- unsigned int res_720x400:1;
- unsigned int res_720x480:1;
- unsigned int res_720x540:1;
- unsigned int res_720x576:1;
- unsigned int res_768x576:1;
- unsigned int res_800x600:1;
- unsigned int res_832x624:1;
-
- unsigned int res_920x766:1;
- unsigned int res_1024x768:1;
- unsigned int res_1280x1024:1;
- unsigned int pad:5;
+ unsigned int res_320x200:1;
+ unsigned int res_320x240:1;
+ unsigned int res_400x300:1;
+ unsigned int res_640x350:1;
+ unsigned int res_640x400:1;
+ unsigned int res_640x480:1;
+ unsigned int res_704x480:1;
+ unsigned int res_704x576:1;
+
+ unsigned int res_720x350:1;
+ unsigned int res_720x400:1;
+ unsigned int res_720x480:1;
+ unsigned int res_720x540:1;
+ unsigned int res_720x576:1;
+ unsigned int res_768x576:1;
+ unsigned int res_800x600:1;
+ unsigned int res_832x624:1;
+
+ unsigned int res_920x766:1;
+ unsigned int res_1024x768:1;
+ unsigned int res_1280x1024:1;
+ unsigned int pad:5;
} __attribute__((packed));
/* Get supported resolution with squire pixel aspect ratio that can be
@@ -428,90 +428,90 @@ struct intel_sdvo_sdtv_resolution_reply {
#define SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT 0x85
struct intel_sdvo_hdtv_resolution_request {
- unsigned int hdtv_std_smpte_240m_1080i_59:1;
- unsigned int hdtv_std_smpte_240m_1080i_60:1;
- unsigned int hdtv_std_smpte_260m_1080i_59:1;
- unsigned int hdtv_std_smpte_260m_1080i_60:1;
- unsigned int hdtv_std_smpte_274m_1080i_50:1;
- unsigned int hdtv_std_smpte_274m_1080i_59:1;
- unsigned int hdtv_std_smpte_274m_1080i_60:1;
- unsigned int hdtv_std_smpte_274m_1080p_23:1;
-
- unsigned int hdtv_std_smpte_274m_1080p_24:1;
- unsigned int hdtv_std_smpte_274m_1080p_25:1;
- unsigned int hdtv_std_smpte_274m_1080p_29:1;
- unsigned int hdtv_std_smpte_274m_1080p_30:1;
- unsigned int hdtv_std_smpte_274m_1080p_50:1;
- unsigned int hdtv_std_smpte_274m_1080p_59:1;
- unsigned int hdtv_std_smpte_274m_1080p_60:1;
- unsigned int hdtv_std_smpte_295m_1080i_50:1;
-
- unsigned int hdtv_std_smpte_295m_1080p_50:1;
- unsigned int hdtv_std_smpte_296m_720p_59:1;
- unsigned int hdtv_std_smpte_296m_720p_60:1;
- unsigned int hdtv_std_smpte_296m_720p_50:1;
- unsigned int hdtv_std_smpte_293m_480p_59:1;
- unsigned int hdtv_std_smpte_170m_480i_59:1;
- unsigned int hdtv_std_iturbt601_576i_50:1;
- unsigned int hdtv_std_iturbt601_576p_50:1;
-
- unsigned int hdtv_std_eia_7702a_480i_60:1;
- unsigned int hdtv_std_eia_7702a_480p_60:1;
- unsigned int pad:6;
+ unsigned int hdtv_std_smpte_240m_1080i_59:1;
+ unsigned int hdtv_std_smpte_240m_1080i_60:1;
+ unsigned int hdtv_std_smpte_260m_1080i_59:1;
+ unsigned int hdtv_std_smpte_260m_1080i_60:1;
+ unsigned int hdtv_std_smpte_274m_1080i_50:1;
+ unsigned int hdtv_std_smpte_274m_1080i_59:1;
+ unsigned int hdtv_std_smpte_274m_1080i_60:1;
+ unsigned int hdtv_std_smpte_274m_1080p_23:1;
+
+ unsigned int hdtv_std_smpte_274m_1080p_24:1;
+ unsigned int hdtv_std_smpte_274m_1080p_25:1;
+ unsigned int hdtv_std_smpte_274m_1080p_29:1;
+ unsigned int hdtv_std_smpte_274m_1080p_30:1;
+ unsigned int hdtv_std_smpte_274m_1080p_50:1;
+ unsigned int hdtv_std_smpte_274m_1080p_59:1;
+ unsigned int hdtv_std_smpte_274m_1080p_60:1;
+ unsigned int hdtv_std_smpte_295m_1080i_50:1;
+
+ unsigned int hdtv_std_smpte_295m_1080p_50:1;
+ unsigned int hdtv_std_smpte_296m_720p_59:1;
+ unsigned int hdtv_std_smpte_296m_720p_60:1;
+ unsigned int hdtv_std_smpte_296m_720p_50:1;
+ unsigned int hdtv_std_smpte_293m_480p_59:1;
+ unsigned int hdtv_std_smpte_170m_480i_59:1;
+ unsigned int hdtv_std_iturbt601_576i_50:1;
+ unsigned int hdtv_std_iturbt601_576p_50:1;
+
+ unsigned int hdtv_std_eia_7702a_480i_60:1;
+ unsigned int hdtv_std_eia_7702a_480p_60:1;
+ unsigned int pad:6;
} __attribute__((packed));
struct intel_sdvo_hdtv_resolution_reply {
- unsigned int res_640x480:1;
- unsigned int res_800x600:1;
- unsigned int res_1024x768:1;
- unsigned int res_1280x960:1;
- unsigned int res_1400x1050:1;
- unsigned int res_1600x1200:1;
- unsigned int res_1920x1440:1;
- unsigned int res_2048x1536:1;
-
- unsigned int res_2560x1920:1;
- unsigned int res_3200x2400:1;
- unsigned int res_3840x2880:1;
- unsigned int pad1:5;
-
- unsigned int res_848x480:1;
- unsigned int res_1064x600:1;
- unsigned int res_1280x720:1;
- unsigned int res_1360x768:1;
- unsigned int res_1704x960:1;
- unsigned int res_1864x1050:1;
- unsigned int res_1920x1080:1;
- unsigned int res_2128x1200:1;
-
- unsigned int res_2560x1400:1;
- unsigned int res_2728x1536:1;
- unsigned int res_3408x1920:1;
- unsigned int res_4264x2400:1;
- unsigned int res_5120x2880:1;
- unsigned int pad2:3;
-
- unsigned int res_768x480:1;
- unsigned int res_960x600:1;
- unsigned int res_1152x720:1;
- unsigned int res_1124x768:1;
- unsigned int res_1536x960:1;
- unsigned int res_1680x1050:1;
- unsigned int res_1728x1080:1;
- unsigned int res_1920x1200:1;
-
- unsigned int res_2304x1440:1;
- unsigned int res_2456x1536:1;
- unsigned int res_3072x1920:1;
- unsigned int res_3840x2400:1;
- unsigned int res_4608x2880:1;
- unsigned int pad3:3;
-
- unsigned int res_1280x1024:1;
- unsigned int pad4:7;
-
- unsigned int res_1280x768:1;
- unsigned int pad5:7;
+ unsigned int res_640x480:1;
+ unsigned int res_800x600:1;
+ unsigned int res_1024x768:1;
+ unsigned int res_1280x960:1;
+ unsigned int res_1400x1050:1;
+ unsigned int res_1600x1200:1;
+ unsigned int res_1920x1440:1;
+ unsigned int res_2048x1536:1;
+
+ unsigned int res_2560x1920:1;
+ unsigned int res_3200x2400:1;
+ unsigned int res_3840x2880:1;
+ unsigned int pad1:5;
+
+ unsigned int res_848x480:1;
+ unsigned int res_1064x600:1;
+ unsigned int res_1280x720:1;
+ unsigned int res_1360x768:1;
+ unsigned int res_1704x960:1;
+ unsigned int res_1864x1050:1;
+ unsigned int res_1920x1080:1;
+ unsigned int res_2128x1200:1;
+
+ unsigned int res_2560x1400:1;
+ unsigned int res_2728x1536:1;
+ unsigned int res_3408x1920:1;
+ unsigned int res_4264x2400:1;
+ unsigned int res_5120x2880:1;
+ unsigned int pad2:3;
+
+ unsigned int res_768x480:1;
+ unsigned int res_960x600:1;
+ unsigned int res_1152x720:1;
+ unsigned int res_1124x768:1;
+ unsigned int res_1536x960:1;
+ unsigned int res_1680x1050:1;
+ unsigned int res_1728x1080:1;
+ unsigned int res_1920x1200:1;
+
+ unsigned int res_2304x1440:1;
+ unsigned int res_2456x1536:1;
+ unsigned int res_3072x1920:1;
+ unsigned int res_3840x2400:1;
+ unsigned int res_4608x2880:1;
+ unsigned int pad3:3;
+
+ unsigned int res_1280x1024:1;
+ unsigned int pad4:7;
+
+ unsigned int res_1280x768:1;
+ unsigned int pad5:7;
} __attribute__((packed));
/* Get supported power state returns info for encoder and monitor, rely on
@@ -539,25 +539,25 @@ struct intel_sdvo_hdtv_resolution_reply {
* The high fields are bits 8:9 of the 10-bit values.
*/
struct sdvo_panel_power_sequencing {
- u8 t0;
- u8 t1;
- u8 t2;
- u8 t3;
- u8 t4;
-
- unsigned int t0_high:2;
- unsigned int t1_high:2;
- unsigned int t2_high:2;
- unsigned int t3_high:2;
-
- unsigned int t4_high:2;
- unsigned int pad:6;
+ u8 t0;
+ u8 t1;
+ u8 t2;
+ u8 t3;
+ u8 t4;
+
+ unsigned int t0_high:2;
+ unsigned int t1_high:2;
+ unsigned int t2_high:2;
+ unsigned int t3_high:2;
+
+ unsigned int t4_high:2;
+ unsigned int pad:6;
} __attribute__((packed));
#define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30
struct sdvo_max_backlight_reply {
- u8 max_value;
- u8 default_value;
+ u8 max_value;
+ u8 default_value;
} __attribute__((packed));
#define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31
@@ -565,16 +565,16 @@ struct sdvo_max_backlight_reply {
#define SDVO_CMD_GET_AMBIENT_LIGHT 0x33
struct sdvo_get_ambient_light_reply {
- u16 trip_low;
- u16 trip_high;
- u16 value;
+ u16 trip_low;
+ u16 trip_high;
+ u16 value;
} __attribute__((packed));
#define SDVO_CMD_SET_AMBIENT_LIGHT 0x34
struct sdvo_set_ambient_light_reply {
- u16 trip_low;
- u16 trip_high;
- unsigned int enable:1;
- unsigned int pad:7;
+ u16 trip_low;
+ u16 trip_high;
+ unsigned int enable:1;
+ unsigned int pad:7;
} __attribute__((packed));
/* Set display power state */
@@ -586,23 +586,23 @@ struct sdvo_set_ambient_light_reply {
#define SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS 0x84
struct intel_sdvo_enhancements_reply {
- unsigned int flicker_filter:1;
- unsigned int flicker_filter_adaptive:1;
- unsigned int flicker_filter_2d:1;
- unsigned int saturation:1;
- unsigned int hue:1;
- unsigned int brightness:1;
- unsigned int contrast:1;
- unsigned int overscan_h:1;
-
- unsigned int overscan_v:1;
- unsigned int hpos:1;
- unsigned int vpos:1;
- unsigned int sharpness:1;
- unsigned int dot_crawl:1;
- unsigned int dither:1;
- unsigned int tv_chroma_filter:1;
- unsigned int tv_luma_filter:1;
+ unsigned int flicker_filter:1;
+ unsigned int flicker_filter_adaptive:1;
+ unsigned int flicker_filter_2d:1;
+ unsigned int saturation:1;
+ unsigned int hue:1;
+ unsigned int brightness:1;
+ unsigned int contrast:1;
+ unsigned int overscan_h:1;
+
+ unsigned int overscan_v:1;
+ unsigned int hpos:1;
+ unsigned int vpos:1;
+ unsigned int sharpness:1;
+ unsigned int dot_crawl:1;
+ unsigned int dither:1;
+ unsigned int tv_chroma_filter:1;
+ unsigned int tv_luma_filter:1;
} __attribute__((packed));
/* Picture enhancement limits below are dependent on the current TV format,
@@ -623,8 +623,8 @@ struct intel_sdvo_enhancements_reply {
#define SDVO_CMD_GET_MAX_TV_CHROMA_FILTER 0x74
#define SDVO_CMD_GET_MAX_TV_LUMA_FILTER 0x77
struct intel_sdvo_enhancement_limits_reply {
- u16 max_value;
- u16 default_value;
+ u16 max_value;
+ u16 default_value;
} __attribute__((packed));
#define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f
@@ -665,8 +665,8 @@ struct intel_sdvo_enhancement_limits_reply {
#define SDVO_CMD_GET_TV_LUMA_FILTER 0x78
#define SDVO_CMD_SET_TV_LUMA_FILTER 0x79
struct intel_sdvo_enhancements_arg {
- u16 value;
-}__attribute__((packed));
+ u16 value;
+} __attribute__((packed));
#define SDVO_CMD_GET_DOT_CRAWL 0x70
#define SDVO_CMD_SET_DOT_CRAWL 0x71
@@ -717,7 +717,7 @@ struct intel_sdvo_enhancements_arg {
#define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c
#define SDVO_NEED_TO_STALL (1 << 7)
-struct intel_sdvo_encode{
- u8 dvi_rev;
- u8 hdmi_rev;
+struct intel_sdvo_encode {
+ u8 dvi_rev;
+ u8 hdmi_rev;
} __attribute__ ((packed));
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 210d570fd516..f3c6a9a8b081 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -194,10 +194,10 @@ static const u32 filter_table[] = {
*
* if (f >= 1) {
* exp = 0x7;
- * mant = 1 << 8;
+ * mant = 1 << 8;
* } else {
* for (exp = 0; exp < 3 && f < 0.5; exp++)
- * f *= 2.0;
+ * f *= 2.0;
* mant = (f * (1 << 9) + 0.5);
* if (mant >= (1 << 9))
* mant = (1 << 9) - 1;
@@ -430,7 +430,7 @@ static const struct tv_mode tv_modes[] = {
.vsync_start_f1 = 6, .vsync_start_f2 = 7,
.vsync_len = 6,
- .veq_ena = true, .veq_start_f1 = 0,
+ .veq_ena = true, .veq_start_f1 = 0,
.veq_start_f2 = 1, .veq_len = 18,
.vi_end_f1 = 20, .vi_end_f2 = 21,
@@ -472,7 +472,7 @@ static const struct tv_mode tv_modes[] = {
.vsync_start_f1 = 6, .vsync_start_f2 = 7,
.vsync_len = 6,
- .veq_ena = true, .veq_start_f1 = 0,
+ .veq_ena = true, .veq_start_f1 = 0,
.veq_start_f2 = 1, .veq_len = 18,
.vi_end_f1 = 20, .vi_end_f2 = 21,
@@ -515,7 +515,7 @@ static const struct tv_mode tv_modes[] = {
.vsync_start_f1 = 6, .vsync_start_f2 = 7,
.vsync_len = 6,
- .veq_ena = true, .veq_start_f1 = 0,
+ .veq_ena = true, .veq_start_f1 = 0,
.veq_start_f2 = 1, .veq_len = 18,
.vi_end_f1 = 20, .vi_end_f2 = 21,
@@ -558,7 +558,7 @@ static const struct tv_mode tv_modes[] = {
.vsync_start_f1 = 6, .vsync_start_f2 = 7,
.vsync_len = 6,
- .veq_ena = true, .veq_start_f1 = 0,
+ .veq_ena = true, .veq_start_f1 = 0,
.veq_start_f2 = 1, .veq_len = 18,
.vi_end_f1 = 20, .vi_end_f2 = 21,
@@ -602,14 +602,14 @@ static const struct tv_mode tv_modes[] = {
.vsync_start_f1 = 6, .vsync_start_f2 = 7,
.vsync_len = 6,
- .veq_ena = true, .veq_start_f1 = 0,
+ .veq_ena = true, .veq_start_f1 = 0,
.veq_start_f2 = 1, .veq_len = 18,
.vi_end_f1 = 24, .vi_end_f2 = 25,
.nbr_end = 286,
.burst_ena = true,
- .hburst_start = 73, .hburst_len = 34,
+ .hburst_start = 73, .hburst_len = 34,
.vburst_start_f1 = 8, .vburst_end_f1 = 285,
.vburst_start_f2 = 8, .vburst_end_f2 = 286,
.vburst_start_f3 = 9, .vburst_end_f3 = 286,
@@ -646,7 +646,7 @@ static const struct tv_mode tv_modes[] = {
.vsync_start_f1 = 5, .vsync_start_f2 = 6,
.vsync_len = 5,
- .veq_ena = true, .veq_start_f1 = 0,
+ .veq_ena = true, .veq_start_f1 = 0,
.veq_start_f2 = 1, .veq_len = 15,
.vi_end_f1 = 24, .vi_end_f2 = 25,
@@ -675,7 +675,7 @@ static const struct tv_mode tv_modes[] = {
},
{
.name = "480p@59.94Hz",
- .clock = 107520,
+ .clock = 107520,
.refresh = 59940,
.oversample = TV_OVERSAMPLE_4X,
.component_only = 1,
@@ -683,7 +683,7 @@ static const struct tv_mode tv_modes[] = {
.hsync_end = 64, .hblank_end = 122,
.hblank_start = 842, .htotal = 857,
- .progressive = true,.trilevel_sync = false,
+ .progressive = true, .trilevel_sync = false,
.vsync_start_f1 = 12, .vsync_start_f2 = 12,
.vsync_len = 12,
@@ -699,7 +699,7 @@ static const struct tv_mode tv_modes[] = {
},
{
.name = "480p@60Hz",
- .clock = 107520,
+ .clock = 107520,
.refresh = 60000,
.oversample = TV_OVERSAMPLE_4X,
.component_only = 1,
@@ -707,7 +707,7 @@ static const struct tv_mode tv_modes[] = {
.hsync_end = 64, .hblank_end = 122,
.hblank_start = 842, .htotal = 856,
- .progressive = true,.trilevel_sync = false,
+ .progressive = true, .trilevel_sync = false,
.vsync_start_f1 = 12, .vsync_start_f2 = 12,
.vsync_len = 12,
@@ -723,7 +723,7 @@ static const struct tv_mode tv_modes[] = {
},
{
.name = "576p",
- .clock = 107520,
+ .clock = 107520,
.refresh = 50000,
.oversample = TV_OVERSAMPLE_4X,
.component_only = 1,
@@ -755,7 +755,7 @@ static const struct tv_mode tv_modes[] = {
.hsync_end = 80, .hblank_end = 300,
.hblank_start = 1580, .htotal = 1649,
- .progressive = true, .trilevel_sync = true,
+ .progressive = true, .trilevel_sync = true,
.vsync_start_f1 = 10, .vsync_start_f2 = 10,
.vsync_len = 10,
@@ -779,7 +779,7 @@ static const struct tv_mode tv_modes[] = {
.hsync_end = 80, .hblank_end = 300,
.hblank_start = 1580, .htotal = 1651,
- .progressive = true, .trilevel_sync = true,
+ .progressive = true, .trilevel_sync = true,
.vsync_start_f1 = 10, .vsync_start_f2 = 10,
.vsync_len = 10,
@@ -803,7 +803,7 @@ static const struct tv_mode tv_modes[] = {
.hsync_end = 80, .hblank_end = 300,
.hblank_start = 1580, .htotal = 1979,
- .progressive = true, .trilevel_sync = true,
+ .progressive = true, .trilevel_sync = true,
.vsync_start_f1 = 10, .vsync_start_f2 = 10,
.vsync_len = 10,
@@ -828,12 +828,12 @@ static const struct tv_mode tv_modes[] = {
.hsync_end = 88, .hblank_end = 235,
.hblank_start = 2155, .htotal = 2639,
- .progressive = false, .trilevel_sync = true,
+ .progressive = false, .trilevel_sync = true,
.vsync_start_f1 = 4, .vsync_start_f2 = 5,
.vsync_len = 10,
- .veq_ena = true, .veq_start_f1 = 4,
+ .veq_ena = true, .veq_start_f1 = 4,
.veq_start_f2 = 4, .veq_len = 10,
@@ -854,12 +854,12 @@ static const struct tv_mode tv_modes[] = {
.hsync_end = 88, .hblank_end = 235,
.hblank_start = 2155, .htotal = 2199,
- .progressive = false, .trilevel_sync = true,
+ .progressive = false, .trilevel_sync = true,
.vsync_start_f1 = 4, .vsync_start_f2 = 5,
.vsync_len = 10,
- .veq_ena = true, .veq_start_f1 = 4,
+ .veq_ena = true, .veq_start_f1 = 4,
.veq_start_f2 = 4, .veq_len = 10,
@@ -880,16 +880,16 @@ static const struct tv_mode tv_modes[] = {
.hsync_end = 88, .hblank_end = 235,
.hblank_start = 2155, .htotal = 2201,
- .progressive = false, .trilevel_sync = true,
+ .progressive = false, .trilevel_sync = true,
.vsync_start_f1 = 4, .vsync_start_f2 = 5,
.vsync_len = 10,
.veq_ena = true, .veq_start_f1 = 4,
- .veq_start_f2 = 4, .veq_len = 10,
+ .veq_start_f2 = 4, .veq_len = 10,
- .vi_end_f1 = 21, .vi_end_f2 = 22,
+ .vi_end_f1 = 21, .vi_end_f2 = 22,
.nbr_end = 539,
.burst_ena = false,
@@ -916,7 +916,7 @@ intel_tv_dpms(struct drm_encoder *encoder, int mode)
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- switch(mode) {
+ switch (mode) {
case DRM_MODE_DPMS_ON:
I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
break;
@@ -933,7 +933,7 @@ intel_tv_mode_lookup(const char *tv_format)
{
int i;
- for (i = 0; i < sizeof(tv_modes) / sizeof (tv_modes[0]); i++) {
+ for (i = 0; i < sizeof(tv_modes) / sizeof(tv_modes[0]); i++) {
const struct tv_mode *tv_mode = &tv_modes[i];
if (!strcmp(tv_format, tv_mode->name))
@@ -1128,7 +1128,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
if (color_conversion) {
I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) |
color_conversion->gy);
- I915_WRITE(TV_CSC_Y2,(color_conversion->by << 16) |
+ I915_WRITE(TV_CSC_Y2, (color_conversion->by << 16) |
color_conversion->ay);
I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) |
color_conversion->gu);
@@ -1232,7 +1232,7 @@ static const struct drm_display_mode reported_modes[] = {
* \return false if TV is disconnected.
*/
static int
-intel_tv_detect_type (struct intel_tv *intel_tv,
+intel_tv_detect_type(struct intel_tv *intel_tv,
struct drm_connector *connector)
{
struct drm_encoder *encoder = &intel_tv->base.base;
@@ -1486,7 +1486,7 @@ intel_tv_get_modes(struct drm_connector *connector)
}
static void
-intel_tv_destroy (struct drm_connector *connector)
+intel_tv_destroy(struct drm_connector *connector)
{
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index 0583677e4581..35ef5b1e3566 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -21,16 +21,17 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nv40_grctx.o nv50_grctx.o nvc0_grctx.o \
nv84_crypt.o \
nva3_copy.o nvc0_copy.o \
- nv40_mpeg.o nv50_mpeg.o \
+ nv31_mpeg.o nv50_mpeg.o \
nv04_instmem.o nv50_instmem.o nvc0_instmem.o \
- nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
- nv50_cursor.o nv50_display.o \
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
nv04_crtc.o nv04_display.o nv04_cursor.o \
+ nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
+ nv50_cursor.o nv50_display.o \
+ nvd0_display.o \
nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \
nv10_gpio.o nv50_gpio.o \
nv50_calc.o \
- nv04_pm.o nv50_pm.o nva3_pm.o \
+ nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \
nv50_vram.o nvc0_vram.o \
nv50_vm.o nvc0_vm.o
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 00a55dfdba82..fa22b28e8777 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -37,8 +37,10 @@
#include "nouveau_drv.h"
#include "nouveau_drm.h"
#include "nouveau_reg.h"
+#include "nouveau_encoder.h"
-static int nv40_get_intensity(struct backlight_device *bd)
+static int
+nv40_get_intensity(struct backlight_device *bd)
{
struct drm_device *dev = bl_get_data(bd);
int val = (nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK)
@@ -47,7 +49,8 @@ static int nv40_get_intensity(struct backlight_device *bd)
return val;
}
-static int nv40_set_intensity(struct backlight_device *bd)
+static int
+nv40_set_intensity(struct backlight_device *bd)
{
struct drm_device *dev = bl_get_data(bd);
int val = bd->props.brightness;
@@ -65,30 +68,8 @@ static const struct backlight_ops nv40_bl_ops = {
.update_status = nv40_set_intensity,
};
-static int nv50_get_intensity(struct backlight_device *bd)
-{
- struct drm_device *dev = bl_get_data(bd);
-
- return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT);
-}
-
-static int nv50_set_intensity(struct backlight_device *bd)
-{
- struct drm_device *dev = bl_get_data(bd);
- int val = bd->props.brightness;
-
- nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT,
- val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE);
- return 0;
-}
-
-static const struct backlight_ops nv50_bl_ops = {
- .options = BL_CORE_SUSPENDRESUME,
- .get_brightness = nv50_get_intensity,
- .update_status = nv50_set_intensity,
-};
-
-static int nouveau_nv40_backlight_init(struct drm_connector *connector)
+static int
+nv40_backlight_init(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -113,34 +94,129 @@ static int nouveau_nv40_backlight_init(struct drm_connector *connector)
return 0;
}
-static int nouveau_nv50_backlight_init(struct drm_connector *connector)
+static int
+nv50_get_intensity(struct backlight_device *bd)
+{
+ struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+ struct drm_device *dev = nv_encoder->base.base.dev;
+ int or = nv_encoder->or;
+ u32 div = 1025;
+ u32 val;
+
+ val = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or));
+ val &= NV50_PDISP_SOR_PWM_CTL_VAL;
+ return ((val * 100) + (div / 2)) / div;
+}
+
+static int
+nv50_set_intensity(struct backlight_device *bd)
+{
+ struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+ struct drm_device *dev = nv_encoder->base.base.dev;
+ int or = nv_encoder->or;
+ u32 div = 1025;
+ u32 val = (bd->props.brightness * div) / 100;
+
+ nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or),
+ NV50_PDISP_SOR_PWM_CTL_NEW | val);
+ return 0;
+}
+
+static const struct backlight_ops nv50_bl_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .get_brightness = nv50_get_intensity,
+ .update_status = nv50_set_intensity,
+};
+
+static int
+nva3_get_intensity(struct backlight_device *bd)
+{
+ struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+ struct drm_device *dev = nv_encoder->base.base.dev;
+ int or = nv_encoder->or;
+ u32 div, val;
+
+ div = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or));
+ val = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or));
+ val &= NVA3_PDISP_SOR_PWM_CTL_VAL;
+ if (div && div >= val)
+ return ((val * 100) + (div / 2)) / div;
+
+ return 100;
+}
+
+static int
+nva3_set_intensity(struct backlight_device *bd)
+{
+ struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+ struct drm_device *dev = nv_encoder->base.base.dev;
+ int or = nv_encoder->or;
+ u32 div, val;
+
+ div = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or));
+ val = (bd->props.brightness * div) / 100;
+ if (div) {
+ nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or), val |
+ NV50_PDISP_SOR_PWM_CTL_NEW |
+ NVA3_PDISP_SOR_PWM_CTL_UNK);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static const struct backlight_ops nva3_bl_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .get_brightness = nva3_get_intensity,
+ .update_status = nva3_set_intensity,
+};
+
+static int
+nv50_backlight_init(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_encoder *nv_encoder;
struct backlight_properties props;
struct backlight_device *bd;
+ const struct backlight_ops *ops;
+
+ nv_encoder = find_encoder(connector, OUTPUT_LVDS);
+ if (!nv_encoder) {
+ nv_encoder = find_encoder(connector, OUTPUT_DP);
+ if (!nv_encoder)
+ return -ENODEV;
+ }
- if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))
+ if (!nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or)))
return 0;
+ if (dev_priv->chipset <= 0xa0 ||
+ dev_priv->chipset == 0xaa ||
+ dev_priv->chipset == 0xac)
+ ops = &nv50_bl_ops;
+ else
+ ops = &nva3_bl_ops;
+
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW;
- props.max_brightness = 1025;
- bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
- &nv50_bl_ops, &props);
+ props.max_brightness = 100;
+ bd = backlight_device_register("nv_backlight", &connector->kdev,
+ nv_encoder, ops, &props);
if (IS_ERR(bd))
return PTR_ERR(bd);
dev_priv->backlight = bd;
- bd->props.brightness = nv50_get_intensity(bd);
+ bd->props.brightness = bd->ops->get_brightness(bd);
backlight_update_status(bd);
return 0;
}
-int nouveau_backlight_init(struct drm_connector *connector)
+int
+nouveau_backlight_init(struct drm_device *dev)
{
- struct drm_device *dev = connector->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct drm_connector *connector;
#ifdef CONFIG_ACPI
if (acpi_video_backlight_support()) {
@@ -150,21 +226,28 @@ int nouveau_backlight_init(struct drm_connector *connector)
}
#endif
- switch (dev_priv->card_type) {
- case NV_40:
- return nouveau_nv40_backlight_init(connector);
- case NV_50:
- return nouveau_nv50_backlight_init(connector);
- default:
- break;
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
+ connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+ continue;
+
+ switch (dev_priv->card_type) {
+ case NV_40:
+ return nv40_backlight_init(connector);
+ case NV_50:
+ return nv50_backlight_init(connector);
+ default:
+ break;
+ }
}
+
return 0;
}
-void nouveau_backlight_exit(struct drm_connector *connector)
+void
+nouveau_backlight_exit(struct drm_device *dev)
{
- struct drm_device *dev = connector->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
if (dev_priv->backlight) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index b311faba34f8..032a82098136 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -296,6 +296,11 @@ munge_reg(struct nvbios *bios, uint32_t reg)
if (dev_priv->card_type < NV_50)
return reg;
+ if (reg & 0x80000000) {
+ BUG_ON(bios->display.crtc < 0);
+ reg += bios->display.crtc * 0x800;
+ }
+
if (reg & 0x40000000) {
BUG_ON(!dcbent);
@@ -304,7 +309,7 @@ munge_reg(struct nvbios *bios, uint32_t reg)
reg += 0x00000080;
}
- reg &= ~0x60000000;
+ reg &= ~0xe0000000;
return reg;
}
@@ -1174,22 +1179,19 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
*
*/
- struct bit_displayport_encoder_table *dpe = NULL;
struct dcb_entry *dcb = bios->display.output;
struct drm_device *dev = bios->dev;
uint8_t cond = bios->data[offset + 1];
- int dummy;
+ uint8_t *table, *entry;
BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond);
if (!iexec->execute)
return 3;
- dpe = nouveau_bios_dp_table(dev, dcb, &dummy);
- if (!dpe) {
- NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset);
+ table = nouveau_dp_bios_data(dev, dcb, &entry);
+ if (!table)
return 3;
- }
switch (cond) {
case 0:
@@ -1203,7 +1205,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
break;
case 1:
case 2:
- if (!(dpe->unknown & cond))
+ if (!(entry[5] & cond))
iexec->execute = false;
break;
case 5:
@@ -3221,6 +3223,49 @@ init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
return 1;
}
+static void
+init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio)
+{
+ const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
+ u32 r, s, v;
+
+ /* Not a clue, needs de-magicing */
+ r = nv50_gpio_ctl[gpio->line >> 4];
+ s = (gpio->line & 0x0f);
+ v = bios_rd32(bios, r) & ~(0x00010001 << s);
+ switch ((gpio->entry & 0x06000000) >> 25) {
+ case 1:
+ v |= (0x00000001 << s);
+ break;
+ case 2:
+ v |= (0x00010000 << s);
+ break;
+ default:
+ break;
+ }
+
+ bios_wr32(bios, r, v);
+}
+
+static void
+init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio)
+{
+ u32 v, i;
+
+ v = bios_rd32(bios, 0x00d610 + (gpio->line * 4));
+ v &= 0xffffff00;
+ v |= (gpio->entry & 0x00ff0000) >> 16;
+ bios_wr32(bios, 0x00d610 + (gpio->line * 4), v);
+
+ i = (gpio->entry & 0x1f000000) >> 24;
+ if (i) {
+ v = bios_rd32(bios, 0x00d640 + ((i - 1) * 4));
+ v &= 0xffffff00;
+ v |= gpio->line;
+ bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v);
+ }
+}
+
static int
init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
{
@@ -3235,7 +3280,6 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
- const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
int i;
if (dev_priv->card_type < NV_50) {
@@ -3248,33 +3292,20 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
for (i = 0; i < bios->dcb.gpio.entries; i++) {
struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i];
- uint32_t r, s, v;
BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
offset, gpio->tag, gpio->state_default);
- if (bios->execute)
- pgpio->set(bios->dev, gpio->tag, gpio->state_default);
- /* The NVIDIA binary driver doesn't appear to actually do
- * any of this, my VBIOS does however.
- */
- /* Not a clue, needs de-magicing */
- r = nv50_gpio_ctl[gpio->line >> 4];
- s = (gpio->line & 0x0f);
- v = bios_rd32(bios, r) & ~(0x00010001 << s);
- switch ((gpio->entry & 0x06000000) >> 25) {
- case 1:
- v |= (0x00000001 << s);
- break;
- case 2:
- v |= (0x00010000 << s);
- break;
- default:
- break;
- }
- bios_wr32(bios, r, v);
+ if (!bios->execute)
+ continue;
+
+ pgpio->set(bios->dev, gpio->tag, gpio->state_default);
+ if (dev_priv->card_type < NV_D0)
+ init_gpio_unknv50(bios, gpio);
+ else
+ init_gpio_unknvd0(bios, gpio);
}
return 1;
@@ -3737,6 +3768,10 @@ parse_init_table(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
int count = 0, i, ret;
uint8_t id;
+ /* catch NULL script pointers */
+ if (offset == 0)
+ return 0;
+
/*
* Loop until INIT_DONE causes us to break out of the loop
* (or until offset > bios length just in case... )
@@ -4389,86 +4424,37 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
return 0;
}
-static uint8_t *
-bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
- uint16_t record, int record_len, int record_nr,
- bool match_link)
+/* BIT 'U'/'d' table encoder subtables have hashes matching them to
+ * a particular set of encoders.
+ *
+ * This function returns true if a particular DCB entry matches.
+ */
+bool
+bios_encoder_match(struct dcb_entry *dcb, u32 hash)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nvbios *bios = &dev_priv->vbios;
- uint32_t entry;
- uint16_t table;
- int i, v;
+ if ((hash & 0x000000f0) != (dcb->location << 4))
+ return false;
+ if ((hash & 0x0000000f) != dcb->type)
+ return false;
+ if (!(hash & (dcb->or << 16)))
+ return false;
- switch (dcbent->type) {
+ switch (dcb->type) {
case OUTPUT_TMDS:
case OUTPUT_LVDS:
case OUTPUT_DP:
- break;
- default:
- match_link = false;
- break;
- }
-
- for (i = 0; i < record_nr; i++, record += record_len) {
- table = ROM16(bios->data[record]);
- if (!table)
- continue;
- entry = ROM32(bios->data[table]);
-
- if (match_link) {
- v = (entry & 0x00c00000) >> 22;
- if (!(v & dcbent->sorconf.link))
- continue;
+ if (hash & 0x00c00000) {
+ if (!(hash & (dcb->sorconf.link << 22)))
+ return false;
}
-
- v = (entry & 0x000f0000) >> 16;
- if (!(v & dcbent->or))
- continue;
-
- v = (entry & 0x000000f0) >> 4;
- if (v != dcbent->location)
- continue;
-
- v = (entry & 0x0000000f);
- if (v != dcbent->type)
- continue;
-
- return &bios->data[table];
- }
-
- return NULL;
-}
-
-void *
-nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
- int *length)
-{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nvbios *bios = &dev_priv->vbios;
- uint8_t *table;
-
- if (!bios->display.dp_table_ptr) {
- NV_ERROR(dev, "No pointer to DisplayPort table\n");
- return NULL;
- }
- table = &bios->data[bios->display.dp_table_ptr];
-
- if (table[0] != 0x20 && table[0] != 0x21) {
- NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n",
- table[0]);
- return NULL;
+ default:
+ return true;
}
-
- *length = table[4];
- return bios_output_config_match(dev, dcbent,
- bios->display.dp_table_ptr + table[1],
- table[2], table[3], table[0] >= 0x21);
}
int
-nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
- uint32_t sub, int pxclk)
+nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk,
+ struct dcb_entry *dcbent, int crtc)
{
/*
* The display script table is located by the BIT 'U' table.
@@ -4498,7 +4484,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
uint8_t *table = &bios->data[bios->display.script_table_ptr];
uint8_t *otable = NULL;
uint16_t script;
- int i = 0;
+ int i;
if (!bios->display.script_table_ptr) {
NV_ERROR(dev, "No pointer to output script table\n");
@@ -4550,30 +4536,33 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n",
dcbent->type, dcbent->location, dcbent->or);
- otable = bios_output_config_match(dev, dcbent, table[1] +
- bios->display.script_table_ptr,
- table[2], table[3], table[0] >= 0x21);
+ for (i = 0; i < table[3]; i++) {
+ otable = ROMPTR(bios, table[table[1] + (i * table[2])]);
+ if (otable && bios_encoder_match(dcbent, ROM32(otable[0])))
+ break;
+ }
+
if (!otable) {
NV_DEBUG_KMS(dev, "failed to match any output table\n");
return 1;
}
- if (pxclk < -2 || pxclk > 0) {
+ if (pclk < -2 || pclk > 0) {
/* Try to find matching script table entry */
for (i = 0; i < otable[5]; i++) {
- if (ROM16(otable[table[4] + i*6]) == sub)
+ if (ROM16(otable[table[4] + i*6]) == type)
break;
}
if (i == otable[5]) {
NV_ERROR(dev, "Table 0x%04x not found for %d/%d, "
"using first\n",
- sub, dcbent->type, dcbent->or);
+ type, dcbent->type, dcbent->or);
i = 0;
}
}
- if (pxclk == 0) {
+ if (pclk == 0) {
script = ROM16(otable[6]);
if (!script) {
NV_DEBUG_KMS(dev, "output script 0 not found\n");
@@ -4581,9 +4570,9 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
}
NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script);
- nouveau_bios_run_init_table(dev, script, dcbent);
+ nouveau_bios_run_init_table(dev, script, dcbent, crtc);
} else
- if (pxclk == -1) {
+ if (pclk == -1) {
script = ROM16(otable[8]);
if (!script) {
NV_DEBUG_KMS(dev, "output script 1 not found\n");
@@ -4591,9 +4580,9 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
}
NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script);
- nouveau_bios_run_init_table(dev, script, dcbent);
+ nouveau_bios_run_init_table(dev, script, dcbent, crtc);
} else
- if (pxclk == -2) {
+ if (pclk == -2) {
if (table[4] >= 12)
script = ROM16(otable[10]);
else
@@ -4604,31 +4593,31 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
}
NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script);
- nouveau_bios_run_init_table(dev, script, dcbent);
+ nouveau_bios_run_init_table(dev, script, dcbent, crtc);
} else
- if (pxclk > 0) {
+ if (pclk > 0) {
script = ROM16(otable[table[4] + i*6 + 2]);
if (script)
- script = clkcmptable(bios, script, pxclk);
+ script = clkcmptable(bios, script, pclk);
if (!script) {
NV_DEBUG_KMS(dev, "clock script 0 not found\n");
return 1;
}
NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script);
- nouveau_bios_run_init_table(dev, script, dcbent);
+ nouveau_bios_run_init_table(dev, script, dcbent, crtc);
} else
- if (pxclk < 0) {
+ if (pclk < 0) {
script = ROM16(otable[table[4] + i*6 + 4]);
if (script)
- script = clkcmptable(bios, script, -pxclk);
+ script = clkcmptable(bios, script, -pclk);
if (!script) {
NV_DEBUG_KMS(dev, "clock script 1 not found\n");
return 1;
}
NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script);
- nouveau_bios_run_init_table(dev, script, dcbent);
+ nouveau_bios_run_init_table(dev, script, dcbent, crtc);
}
return 0;
@@ -5478,14 +5467,6 @@ parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios,
return 0;
}
-static int
-parse_bit_displayport_tbl_entry(struct drm_device *dev, struct nvbios *bios,
- struct bit_entry *bitentry)
-{
- bios->display.dp_table_ptr = ROM16(bios->data[bitentry->offset]);
- return 0;
-}
-
struct bit_table {
const char id;
int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *);
@@ -5559,7 +5540,6 @@ parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset)
parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds));
parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds));
parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U));
- parse_bit_table(bios, bitoffset, &BIT_TABLE('d', displayport));
return 0;
}
@@ -5884,9 +5864,15 @@ parse_dcb_gpio_table(struct nvbios *bios)
}
e->line = (e->entry & 0x0000001f) >> 0;
- e->state_default = (e->entry & 0x01000000) >> 24;
- e->state[0] = (e->entry & 0x18000000) >> 27;
- e->state[1] = (e->entry & 0x60000000) >> 29;
+ if (gpio[0] == 0x40) {
+ e->state_default = (e->entry & 0x01000000) >> 24;
+ e->state[0] = (e->entry & 0x18000000) >> 27;
+ e->state[1] = (e->entry & 0x60000000) >> 29;
+ } else {
+ e->state_default = (e->entry & 0x00000080) >> 7;
+ e->state[0] = (entry[4] >> 4) & 3;
+ e->state[1] = (entry[4] >> 6) & 3;
+ }
}
}
@@ -6156,7 +6142,14 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
}
case OUTPUT_DP:
entry->dpconf.sor.link = (conf & 0x00000030) >> 4;
- entry->dpconf.link_bw = (conf & 0x00e00000) >> 21;
+ switch ((conf & 0x00e00000) >> 21) {
+ case 0:
+ entry->dpconf.link_bw = 162000;
+ break;
+ default:
+ entry->dpconf.link_bw = 270000;
+ break;
+ }
switch ((conf & 0x0f000000) >> 24) {
case 0xf:
entry->dpconf.link_nr = 4;
@@ -6769,7 +6762,7 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev)
void
nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
- struct dcb_entry *dcbent)
+ struct dcb_entry *dcbent, int crtc)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvbios *bios = &dev_priv->vbios;
@@ -6777,11 +6770,22 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
spin_lock_bh(&bios->lock);
bios->display.output = dcbent;
+ bios->display.crtc = crtc;
parse_init_table(bios, table, &iexec);
bios->display.output = NULL;
spin_unlock_bh(&bios->lock);
}
+void
+nouveau_bios_init_exec(struct drm_device *dev, uint16_t table)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nvbios *bios = &dev_priv->vbios;
+ struct init_exec iexec = { true, false };
+
+ parse_init_table(bios, table, &iexec);
+}
+
static bool NVInitVBIOS(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -6863,9 +6867,8 @@ nouveau_run_vbios_init(struct drm_device *dev)
if (dev_priv->card_type >= NV_50) {
for (i = 0; i < bios->dcb.entries; i++) {
- nouveau_bios_run_display_table(dev,
- &bios->dcb.entry[i],
- 0, 0);
+ nouveau_bios_run_display_table(dev, 0, 0,
+ &bios->dcb.entry[i], -1);
}
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index 050c314119df..8adb69e4a6b1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -289,8 +289,8 @@ struct nvbios {
struct {
struct dcb_entry *output;
+ int crtc;
uint16_t script_table_ptr;
- uint16_t dp_table_ptr;
} display;
struct {
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 890d50e4d682..7226f419e178 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -956,7 +956,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
break;
}
- if (dev_priv->card_type == NV_C0)
+ if (dev_priv->card_type >= NV_C0)
page_shift = node->page_shift;
else
page_shift = 12;
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
index b0d753f45bbd..a319d5646ea9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -411,13 +411,17 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
return ret;
init->channel = chan->id;
- if (chan->dma.ib_max)
- init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
- NOUVEAU_GEM_DOMAIN_GART;
- else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM)
+ if (nouveau_vram_pushbuf == 0) {
+ if (chan->dma.ib_max)
+ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
+ NOUVEAU_GEM_DOMAIN_GART;
+ else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM)
+ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
+ else
+ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
+ } else {
init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
- else
- init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
+ }
if (dev_priv->card_type < NV_C0) {
init->subchan[0].handle = NvM2MF;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 939d4df07777..e0d275e1c96c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -39,7 +39,7 @@
static void nouveau_connector_hotplug(void *, int);
-static struct nouveau_encoder *
+struct nouveau_encoder *
find_encoder(struct drm_connector *connector, int type)
{
struct drm_device *dev = connector->dev;
@@ -116,10 +116,6 @@ nouveau_connector_destroy(struct drm_connector *connector)
nouveau_connector_hotplug, connector);
}
- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
- connector->connector_type == DRM_MODE_CONNECTOR_eDP)
- nouveau_backlight_exit(connector);
-
kfree(nv_connector->edid);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
@@ -712,11 +708,8 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
case OUTPUT_TV:
return get_slave_funcs(encoder)->mode_valid(encoder, mode);
case OUTPUT_DP:
- if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7)
- max_clock = nv_encoder->dp.link_nr * 270000;
- else
- max_clock = nv_encoder->dp.link_nr * 162000;
-
+ max_clock = nv_encoder->dp.link_nr;
+ max_clock *= nv_encoder->dp.link_bw;
clock = clock * nouveau_connector_bpp(connector) / 8;
break;
default:
@@ -871,7 +864,6 @@ nouveau_connector_create(struct drm_device *dev, int index)
dev->mode_config.scaling_mode_property,
nv_connector->scaling_mode);
}
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
/* fall-through */
case DCB_CONNECTOR_TV_0:
case DCB_CONNECTOR_TV_1:
@@ -888,27 +880,20 @@ nouveau_connector_create(struct drm_device *dev, int index)
dev->mode_config.dithering_mode_property,
nv_connector->use_dithering ?
DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF);
-
- if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) {
- if (dev_priv->card_type >= NV_50)
- connector->polled = DRM_CONNECTOR_POLL_HPD;
- else
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
- }
break;
}
- if (pgpio->irq_register) {
+ if (nv_connector->dcb->gpio_tag != 0xff && pgpio->irq_register) {
pgpio->irq_register(dev, nv_connector->dcb->gpio_tag,
nouveau_connector_hotplug, connector);
+
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+ } else {
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT;
}
drm_sysfs_connector_add(connector);
- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
- connector->connector_type == DRM_MODE_CONNECTOR_eDP)
- nouveau_backlight_init(connector);
-
dcb->drm = connector;
return dcb->drm;
@@ -925,22 +910,13 @@ nouveau_connector_hotplug(void *data, int plugged)
struct drm_connector *connector = data;
struct drm_device *dev = connector->dev;
- NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un",
- drm_get_connector_name(connector));
-
- if (connector->encoder && connector->encoder->crtc &&
- connector->encoder->crtc->enabled) {
- struct nouveau_encoder *nv_encoder = nouveau_encoder(connector->encoder);
- struct drm_encoder_helper_funcs *helper =
- connector->encoder->helper_private;
+ NV_DEBUG(dev, "%splugged %s\n", plugged ? "" : "un",
+ drm_get_connector_name(connector));
- if (nv_encoder->dcb->type == OUTPUT_DP) {
- if (plugged)
- helper->dpms(connector->encoder, DRM_MODE_DPMS_ON);
- else
- helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF);
- }
- }
+ if (plugged)
+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+ else
+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
drm_helper_hpd_irq_event(dev);
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index cb1ce2a09162..bf8e1289953d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -82,14 +82,13 @@ static inline struct drm_crtc *to_drm_crtc(struct nouveau_crtc *crtc)
}
int nv50_crtc_create(struct drm_device *dev, int index);
-int nv50_cursor_init(struct nouveau_crtc *);
-void nv50_cursor_fini(struct nouveau_crtc *);
int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv,
uint32_t buffer_handle, uint32_t width,
uint32_t height);
int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y);
int nv04_cursor_init(struct nouveau_crtc *);
+int nv50_cursor_init(struct nouveau_crtc *);
struct nouveau_connector *
nouveau_crtc_connector_get(struct nouveau_crtc *crtc);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index eb514ea29377..ddbabefb4273 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -105,9 +105,12 @@ nouveau_framebuffer_init(struct drm_device *dev,
if (dev_priv->chipset == 0x50)
nv_fb->r_format |= (tile_flags << 8);
- if (!tile_flags)
- nv_fb->r_pitch = 0x00100000 | fb->pitch;
- else {
+ if (!tile_flags) {
+ if (dev_priv->card_type < NV_D0)
+ nv_fb->r_pitch = 0x00100000 | fb->pitch;
+ else
+ nv_fb->r_pitch = 0x01000000 | fb->pitch;
+ } else {
u32 mode = nvbo->tile_mode;
if (dev_priv->card_type >= NV_C0)
mode >>= 4;
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 7beb82a0315d..de5efe71fefd 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -28,418 +28,619 @@
#include "nouveau_i2c.h"
#include "nouveau_connector.h"
#include "nouveau_encoder.h"
+#include "nouveau_crtc.h"
+
+/******************************************************************************
+ * aux channel util functions
+ *****************************************************************************/
+#define AUX_DBG(fmt, args...) do { \
+ if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_AUXCH) { \
+ NV_PRINTK(KERN_DEBUG, dev, "AUXCH(%d): " fmt, ch, ##args); \
+ } \
+} while (0)
+#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args)
+
+static void
+auxch_fini(struct drm_device *dev, int ch)
+{
+ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000);
+}
static int
-auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
+auxch_init(struct drm_device *dev, int ch)
{
- struct drm_device *dev = encoder->dev;
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nouveau_i2c_chan *auxch;
- int ret;
-
- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
- if (!auxch)
- return -ENODEV;
-
- ret = nouveau_dp_auxch(auxch, 9, address, buf, size);
- if (ret)
- return ret;
+ const u32 unksel = 1; /* nfi which to use, or if it matters.. */
+ const u32 ureq = unksel ? 0x00100000 : 0x00200000;
+ const u32 urep = unksel ? 0x01000000 : 0x02000000;
+ u32 ctrl, timeout;
+
+ /* wait up to 1ms for any previous transaction to be done... */
+ timeout = 1000;
+ do {
+ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+ udelay(1);
+ if (!timeout--) {
+ AUX_ERR("begin idle timeout 0x%08x", ctrl);
+ return -EBUSY;
+ }
+ } while (ctrl & 0x03010000);
+
+ /* set some magic, and wait up to 1ms for it to appear */
+ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq);
+ timeout = 1000;
+ do {
+ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+ udelay(1);
+ if (!timeout--) {
+ AUX_ERR("magic wait 0x%08x\n", ctrl);
+ auxch_fini(dev, ch);
+ return -EBUSY;
+ }
+ } while ((ctrl & 0x03000000) != urep);
return 0;
}
static int
-auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
+auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size)
{
- struct drm_device *dev = encoder->dev;
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nouveau_i2c_chan *auxch;
- int ret;
+ u32 ctrl, stat, timeout, retries;
+ u32 xbuf[4] = {};
+ int ret, i;
- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
- if (!auxch)
- return -ENODEV;
+ AUX_DBG("%d: 0x%08x %d\n", type, addr, size);
- ret = nouveau_dp_auxch(auxch, 8, address, buf, size);
- return ret;
-}
+ ret = auxch_init(dev, ch);
+ if (ret)
+ goto out;
-static int
-nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd)
-{
- struct drm_device *dev = encoder->dev;
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- uint32_t tmp;
- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
-
- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
- tmp &= ~(NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED |
- NV50_SOR_DP_CTRL_LANE_MASK);
- tmp |= ((1 << (cmd & DP_LANE_COUNT_MASK)) - 1) << 16;
- if (cmd & DP_LANE_COUNT_ENHANCED_FRAME_EN)
- tmp |= NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED;
- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp);
-
- return auxch_wr(encoder, DP_LANE_COUNT_SET, &cmd, 1);
-}
+ stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50));
+ if (!(stat & 0x10000000)) {
+ AUX_DBG("sink not detected\n");
+ ret = -ENXIO;
+ goto out;
+ }
-static int
-nouveau_dp_link_bw_set(struct drm_encoder *encoder, uint8_t cmd)
-{
- struct drm_device *dev = encoder->dev;
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- uint32_t tmp;
- int reg = 0x614300 + (nv_encoder->or * 0x800);
+ if (!(type & 1)) {
+ memcpy(xbuf, data, size);
+ for (i = 0; i < 16; i += 4) {
+ AUX_DBG("wr 0x%08x\n", xbuf[i / 4]);
+ nv_wr32(dev, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]);
+ }
+ }
- tmp = nv_rd32(dev, reg);
- tmp &= 0xfff3ffff;
- if (cmd == DP_LINK_BW_2_7)
- tmp |= 0x00040000;
- nv_wr32(dev, reg, tmp);
+ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+ ctrl &= ~0x0001f0ff;
+ ctrl |= type << 12;
+ ctrl |= size - 1;
+ nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr);
+
+ /* retry transaction a number of times on failure... */
+ ret = -EREMOTEIO;
+ for (retries = 0; retries < 32; retries++) {
+ /* reset, and delay a while if this is a retry */
+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl);
+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl);
+ if (retries)
+ udelay(400);
+
+ /* transaction request, wait up to 1ms for it to complete */
+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl);
+
+ timeout = 1000;
+ do {
+ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+ udelay(1);
+ if (!timeout--) {
+ AUX_ERR("tx req timeout 0x%08x\n", ctrl);
+ goto out;
+ }
+ } while (ctrl & 0x00010000);
- return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1);
-}
+ /* read status, and check if transaction completed ok */
+ stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0);
+ if (!(stat & 0x000f0f00)) {
+ ret = 0;
+ break;
+ }
-static int
-nouveau_dp_link_train_set(struct drm_encoder *encoder, int pattern)
-{
- struct drm_device *dev = encoder->dev;
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- uint32_t tmp;
- uint8_t cmd;
- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
- int ret;
+ AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat);
+ }
- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
- tmp &= ~NV50_SOR_DP_CTRL_TRAINING_PATTERN;
- tmp |= (pattern << 24);
- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp);
+ if (type & 1) {
+ for (i = 0; i < 16; i += 4) {
+ xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i);
+ AUX_DBG("rd 0x%08x\n", xbuf[i / 4]);
+ }
+ memcpy(data, xbuf, size);
+ }
- ret = auxch_rd(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1);
- if (ret)
- return ret;
- cmd &= ~DP_TRAINING_PATTERN_MASK;
- cmd |= (pattern & DP_TRAINING_PATTERN_MASK);
- return auxch_wr(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1);
+out:
+ auxch_fini(dev, ch);
+ return ret;
}
-static int
-nouveau_dp_max_voltage_swing(struct drm_encoder *encoder)
+static u32
+dp_link_bw_get(struct drm_device *dev, int or, int link)
{
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct drm_device *dev = encoder->dev;
- struct bit_displayport_encoder_table_entry *dpse;
- struct bit_displayport_encoder_table *dpe;
- int i, dpe_headerlen, max_vs = 0;
-
- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
- if (!dpe)
- return false;
- dpse = (void *)((char *)dpe + dpe_headerlen);
+ u32 ctrl = nv_rd32(dev, 0x614300 + (or * 0x800));
+ if (!(ctrl & 0x000c0000))
+ return 162000;
+ return 270000;
+}
- for (i = 0; i < dpe_headerlen; i++, dpse++) {
- if (dpse->vs_level > max_vs)
- max_vs = dpse->vs_level;
+static int
+dp_lane_count_get(struct drm_device *dev, int or, int link)
+{
+ u32 ctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
+ switch (ctrl & 0x000f0000) {
+ case 0x00010000: return 1;
+ case 0x00030000: return 2;
+ default:
+ return 4;
}
-
- return max_vs;
}
-static int
-nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs)
+void
+nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp)
{
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct drm_device *dev = encoder->dev;
- struct bit_displayport_encoder_table_entry *dpse;
- struct bit_displayport_encoder_table *dpe;
- int i, dpe_headerlen, max_pre = 0;
+ const u32 symbol = 100000;
+ int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0;
+ int TU, VTUi, VTUf, VTUa;
+ u64 link_data_rate, link_ratio, unk;
+ u32 best_diff = 64 * symbol;
+ u32 link_nr, link_bw, r;
+
+ /* calculate packed data rate for each lane */
+ link_nr = dp_lane_count_get(dev, or, link);
+ link_data_rate = (clk * bpp / 8) / link_nr;
+
+ /* calculate ratio of packed data rate to link symbol rate */
+ link_bw = dp_link_bw_get(dev, or, link);
+ link_ratio = link_data_rate * symbol;
+ r = do_div(link_ratio, link_bw);
+
+ for (TU = 64; TU >= 32; TU--) {
+ /* calculate average number of valid symbols in each TU */
+ u32 tu_valid = link_ratio * TU;
+ u32 calc, diff;
+
+ /* find a hw representation for the fraction.. */
+ VTUi = tu_valid / symbol;
+ calc = VTUi * symbol;
+ diff = tu_valid - calc;
+ if (diff) {
+ if (diff >= (symbol / 2)) {
+ VTUf = symbol / (symbol - diff);
+ if (symbol - (VTUf * diff))
+ VTUf++;
+
+ if (VTUf <= 15) {
+ VTUa = 1;
+ calc += symbol - (symbol / VTUf);
+ } else {
+ VTUa = 0;
+ VTUf = 1;
+ calc += symbol;
+ }
+ } else {
+ VTUa = 0;
+ VTUf = min((int)(symbol / diff), 15);
+ calc += symbol / VTUf;
+ }
- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
- if (!dpe)
- return false;
- dpse = (void *)((char *)dpe + dpe_headerlen);
+ diff = calc - tu_valid;
+ } else {
+ /* no remainder, but the hw doesn't like the fractional
+ * part to be zero. decrement the integer part and
+ * have the fraction add a whole symbol back
+ */
+ VTUa = 0;
+ VTUf = 1;
+ VTUi--;
+ }
- for (i = 0; i < dpe_headerlen; i++, dpse++) {
- if (dpse->vs_level != vs)
- continue;
+ if (diff < best_diff) {
+ best_diff = diff;
+ bestTU = TU;
+ bestVTUa = VTUa;
+ bestVTUf = VTUf;
+ bestVTUi = VTUi;
+ if (diff == 0)
+ break;
+ }
+ }
- if (dpse->pre_level > max_pre)
- max_pre = dpse->pre_level;
+ if (!bestTU) {
+ NV_ERROR(dev, "DP: unable to find suitable config\n");
+ return;
}
- return max_pre;
+ /* XXX close to vbios numbers, but not right */
+ unk = (symbol - link_ratio) * bestTU;
+ unk *= link_ratio;
+ r = do_div(unk, symbol);
+ r = do_div(unk, symbol);
+ unk += 6;
+
+ nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2);
+ nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 |
+ bestVTUf << 16 |
+ bestVTUi << 8 |
+ unk);
}
-static bool
-nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config)
+u8 *
+nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
{
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct drm_device *dev = encoder->dev;
- struct bit_displayport_encoder_table *dpe;
- int ret, i, dpe_headerlen, vs = 0, pre = 0;
- uint8_t request[2];
-
- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
- if (!dpe)
- return false;
-
- ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2);
- if (ret)
- return false;
-
- NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]);
-
- /* Keep all lanes at the same level.. */
- for (i = 0; i < nv_encoder->dp.link_nr; i++) {
- int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf;
- int lane_vs = lane_req & 3;
- int lane_pre = (lane_req >> 2) & 3;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nvbios *bios = &dev_priv->vbios;
+ struct bit_entry d;
+ u8 *table;
+ int i;
+
+ if (bit_table(dev, 'd', &d)) {
+ NV_ERROR(dev, "BIT 'd' table not found\n");
+ return NULL;
+ }
- if (lane_vs > vs)
- vs = lane_vs;
- if (lane_pre > pre)
- pre = lane_pre;
+ if (d.version != 1) {
+ NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version);
+ return NULL;
}
- if (vs >= nouveau_dp_max_voltage_swing(encoder)) {
- vs = nouveau_dp_max_voltage_swing(encoder);
- vs |= 4;
+ table = ROMPTR(bios, d.data[0]);
+ if (!table) {
+ NV_ERROR(dev, "displayport table pointer invalid\n");
+ return NULL;
}
- if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) {
- pre = nouveau_dp_max_pre_emphasis(encoder, vs & 3);
- pre |= 4;
+ switch (table[0]) {
+ case 0x20:
+ case 0x21:
+ case 0x30:
+ break;
+ default:
+ NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]);
+ return NULL;
}
- /* Update the configuration for all lanes.. */
- for (i = 0; i < nv_encoder->dp.link_nr; i++)
- config[i] = (pre << 3) | vs;
+ for (i = 0; i < table[3]; i++) {
+ *entry = ROMPTR(bios, table[table[1] + (i * table[2])]);
+ if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0])))
+ return table;
+ }
- return true;
+ NV_ERROR(dev, "displayport encoder table not found\n");
+ return NULL;
}
-static bool
-nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config)
-{
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct drm_device *dev = encoder->dev;
- struct bit_displayport_encoder_table_entry *dpse;
- struct bit_displayport_encoder_table *dpe;
- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
- int dpe_headerlen, ret, i;
+/******************************************************************************
+ * link training
+ *****************************************************************************/
+struct dp_state {
+ struct dcb_entry *dcb;
+ u8 *table;
+ u8 *entry;
+ int auxch;
+ int crtc;
+ int or;
+ int link;
+ u8 *dpcd;
+ int link_nr;
+ u32 link_bw;
+ u8 stat[6];
+ u8 conf[4];
+};
- NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n",
- config[0], config[1], config[2], config[3]);
+static void
+dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ int or = dp->or, link = dp->link;
+ u8 *entry, sink[2];
+ u32 dp_ctrl;
+ u16 script;
+
+ NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
+
+ /* set selected link rate on source */
+ switch (dp->link_bw) {
+ case 270000:
+ nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00040000);
+ sink[0] = DP_LINK_BW_2_7;
+ break;
+ default:
+ nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00000000);
+ sink[0] = DP_LINK_BW_1_62;
+ break;
+ }
- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
- if (!dpe)
- return false;
- dpse = (void *)((char *)dpe + dpe_headerlen);
+ /* offset +0x0a of each dp encoder table entry is a pointer to another
+ * table, that has (among other things) pointers to more scripts that
+ * need to be executed, this time depending on link speed.
+ */
+ entry = ROMPTR(&dev_priv->vbios, dp->entry[10]);
+ if (entry) {
+ if (dp->table[0] < 0x30) {
+ while (dp->link_bw < (ROM16(entry[0]) * 10))
+ entry += 4;
+ script = ROM16(entry[2]);
+ } else {
+ while (dp->link_bw < (entry[0] * 27000))
+ entry += 3;
+ script = ROM16(entry[1]);
+ }
- for (i = 0; i < dpe->record_nr; i++, dpse++) {
- if (dpse->vs_level == (config[0] & 3) &&
- dpse->pre_level == ((config[0] >> 3) & 3))
- break;
+ nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
}
- BUG_ON(i == dpe->record_nr);
-
- for (i = 0; i < nv_encoder->dp.link_nr; i++) {
- const int shift[4] = { 16, 8, 0, 24 };
- uint32_t mask = 0xff << shift[i];
- uint32_t reg0, reg1, reg2;
-
- reg0 = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask;
- reg0 |= (dpse->reg0 << shift[i]);
- reg1 = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask;
- reg1 |= (dpse->reg1 << shift[i]);
- reg2 = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff;
- reg2 |= (dpse->reg2 << 8);
- nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0);
- nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1);
- nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2);
+
+ /* configure lane count on the source */
+ dp_ctrl = ((1 << dp->link_nr) - 1) << 16;
+ sink[1] = dp->link_nr;
+ if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) {
+ dp_ctrl |= 0x00004000;
+ sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
}
- ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4);
- if (ret)
- return false;
+ nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x001f4000, dp_ctrl);
- return true;
+ /* inform the sink of the new configuration */
+ auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2);
}
-bool
-nouveau_dp_link_train(struct drm_encoder *encoder)
+static void
+dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 tp)
{
- struct drm_device *dev = encoder->dev;
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nouveau_connector *nv_connector;
- struct bit_displayport_encoder_table *dpe;
- int dpe_headerlen;
- uint8_t config[4], status[3];
- bool cr_done, cr_max_vs, eq_done, hpd_state;
- int ret = 0, i, tries, voltage;
+ u8 sink_tp;
- NV_DEBUG_KMS(dev, "link training!!\n");
+ NV_DEBUG_KMS(dev, "training pattern %d\n", tp);
- nv_connector = nouveau_encoder_connector_get(nv_encoder);
- if (!nv_connector)
- return false;
+ nv_mask(dev, NV50_SOR_DP_CTRL(dp->or, dp->link), 0x0f000000, tp << 24);
- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
- if (!dpe) {
- NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or);
- return false;
- }
+ auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
+ sink_tp &= ~DP_TRAINING_PATTERN_MASK;
+ sink_tp |= tp;
+ auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
+}
- /* disable hotplug detect, this flips around on some panels during
- * link training.
- */
- hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
+static const u8 nv50_lane_map[] = { 16, 8, 0, 24 };
+static const u8 nvaf_lane_map[] = { 24, 16, 8, 0 };
+
+static int
+dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ u32 mask = 0, drv = 0, pre = 0, unk = 0;
+ const u8 *shifts;
+ int link = dp->link;
+ int or = dp->or;
+ int i;
+
+ if (dev_priv->chipset != 0xaf)
+ shifts = nv50_lane_map;
+ else
+ shifts = nvaf_lane_map;
+
+ for (i = 0; i < dp->link_nr; i++) {
+ u8 *conf = dp->entry + dp->table[4];
+ u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf;
+ u8 lpre = (lane & 0x0c) >> 2;
+ u8 lvsw = (lane & 0x03) >> 0;
+
+ mask |= 0xff << shifts[i];
+ unk |= 1 << (shifts[i] >> 3);
+
+ dp->conf[i] = (lpre << 3) | lvsw;
+ if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200)
+ dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED;
+ if (lpre == DP_TRAIN_PRE_EMPHASIS_9_5)
+ dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+ NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]);
+
+ if (dp->table[0] < 0x30) {
+ u8 *last = conf + (dp->entry[4] * dp->table[5]);
+ while (lvsw != conf[0] || lpre != conf[1]) {
+ conf += dp->table[5];
+ if (conf >= last)
+ return -EINVAL;
+ }
+
+ conf += 2;
+ } else {
+ /* no lookup table anymore, set entries for each
+ * combination of voltage swing and pre-emphasis
+ * level allowed by the DP spec.
+ */
+ switch (lvsw) {
+ case 0: lpre += 0; break;
+ case 1: lpre += 4; break;
+ case 2: lpre += 7; break;
+ case 3: lpre += 9; break;
+ }
+
+ conf = conf + (lpre * dp->table[5]);
+ conf++;
+ }
- if (dpe->script0) {
- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0),
- nv_encoder->dcb);
+ drv |= conf[0] << shifts[i];
+ pre |= conf[1] << shifts[i];
+ unk = (unk & ~0x0000ff00) | (conf[2] << 8);
}
-train:
- cr_done = eq_done = false;
+ nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv);
+ nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, pre);
+ nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff0f, unk);
- /* set link configuration */
- NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n",
- nv_encoder->dp.link_bw, nv_encoder->dp.link_nr);
+ return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4);
+}
- ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw);
- if (ret)
- return false;
+static int
+dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay)
+{
+ int ret;
- config[0] = nv_encoder->dp.link_nr;
- if (nv_encoder->dp.dpcd_version >= 0x11 &&
- nv_encoder->dp.enhanced_frame)
- config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+ udelay(delay);
- ret = nouveau_dp_lane_count_set(encoder, config[0]);
+ ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6);
if (ret)
- return false;
+ return ret;
- /* clock recovery */
- NV_DEBUG_KMS(dev, "\tbegin cr\n");
- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1);
- if (ret)
- goto stop;
+ NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n",
+ dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3],
+ dp->stat[4], dp->stat[5]);
+ return 0;
+}
- tries = 0;
- voltage = -1;
- memset(config, 0x00, sizeof(config));
- for (;;) {
- if (!nouveau_dp_link_train_commit(encoder, config))
- break;
+static int
+dp_link_train_cr(struct drm_device *dev, struct dp_state *dp)
+{
+ bool cr_done = false, abort = false;
+ int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+ int tries = 0, i;
- udelay(100);
+ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1);
- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2);
- if (ret)
+ do {
+ if (dp_link_train_commit(dev, dp) ||
+ dp_link_train_update(dev, dp, 100))
break;
- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n",
- status[0], status[1]);
cr_done = true;
- cr_max_vs = false;
- for (i = 0; i < nv_encoder->dp.link_nr; i++) {
- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf;
-
+ for (i = 0; i < dp->link_nr; i++) {
+ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
if (!(lane & DP_LANE_CR_DONE)) {
cr_done = false;
- if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED)
- cr_max_vs = true;
+ if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED)
+ abort = true;
break;
}
}
- if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
- voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+ if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
+ voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
tries = 0;
}
+ } while (!cr_done && !abort && ++tries < 5);
- if (cr_done || cr_max_vs || (++tries == 5))
- break;
-
- if (!nouveau_dp_link_train_adjust(encoder, config))
- break;
- }
-
- if (!cr_done)
- goto stop;
+ return cr_done ? 0 : -1;
+}
- /* channel equalisation */
- NV_DEBUG_KMS(dev, "\tbegin eq\n");
- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2);
- if (ret)
- goto stop;
+static int
+dp_link_train_eq(struct drm_device *dev, struct dp_state *dp)
+{
+ bool eq_done, cr_done = true;
+ int tries = 0, i;
- for (tries = 0; tries <= 5; tries++) {
- udelay(400);
+ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2);
- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3);
- if (ret)
+ do {
+ if (dp_link_train_update(dev, dp, 400))
break;
- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n",
- status[0], status[1]);
- eq_done = true;
- if (!(status[2] & DP_INTERLANE_ALIGN_DONE))
- eq_done = false;
-
- for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) {
- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf;
-
- if (!(lane & DP_LANE_CR_DONE)) {
+ eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE);
+ for (i = 0; i < dp->link_nr && eq_done; i++) {
+ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
+ if (!(lane & DP_LANE_CR_DONE))
cr_done = false;
- break;
- }
-
if (!(lane & DP_LANE_CHANNEL_EQ_DONE) ||
- !(lane & DP_LANE_SYMBOL_LOCKED)) {
+ !(lane & DP_LANE_SYMBOL_LOCKED))
eq_done = false;
- break;
- }
}
- if (eq_done || !cr_done)
+ if (dp_link_train_commit(dev, dp))
break;
+ } while (!eq_done && cr_done && ++tries <= 5);
- if (!nouveau_dp_link_train_adjust(encoder, config) ||
- !nouveau_dp_link_train_commit(encoder, config))
- break;
- }
+ return eq_done ? 0 : -1;
+}
-stop:
- /* end link training */
- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_DISABLE);
- if (ret)
+bool
+nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
+{
+ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+ struct nouveau_connector *nv_connector =
+ nouveau_encoder_connector_get(nv_encoder);
+ struct drm_device *dev = encoder->dev;
+ struct nouveau_i2c_chan *auxch;
+ const u32 bw_list[] = { 270000, 162000, 0 };
+ const u32 *link_bw = bw_list;
+ struct dp_state dp;
+
+ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+ if (!auxch)
return false;
- /* retry at a lower setting, if possible */
- if (!ret && !(eq_done && cr_done)) {
- NV_DEBUG_KMS(dev, "\twe failed\n");
- if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62) {
- NV_DEBUG_KMS(dev, "retry link training at low rate\n");
- nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
- goto train;
- }
+ dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry);
+ if (!dp.table)
+ return -EINVAL;
+
+ dp.dcb = nv_encoder->dcb;
+ dp.crtc = nv_crtc->index;
+ dp.auxch = auxch->rd;
+ dp.or = nv_encoder->or;
+ dp.link = !(nv_encoder->dcb->sorconf.link & 1);
+ dp.dpcd = nv_encoder->dp.dpcd;
+
+ /* some sinks toggle hotplug in response to some of the actions
+ * we take during link training (DP_SET_POWER is one), we need
+ * to ignore them for the moment to avoid races.
+ */
+ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
+
+ /* enable down-spreading, if possible */
+ if (dp.table[1] >= 16) {
+ u16 script = ROM16(dp.entry[14]);
+ if (nv_encoder->dp.dpcd[3] & 1)
+ script = ROM16(dp.entry[12]);
+
+ nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc);
}
- if (dpe->script1) {
- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1),
- nv_encoder->dcb);
+ /* execute pre-train script from vbios */
+ nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc);
+
+ /* start off at highest link rate supported by encoder and display */
+ while (*link_bw > nv_encoder->dp.link_bw)
+ link_bw++;
+
+ while (link_bw[0]) {
+ /* find minimum required lane count at this link rate */
+ dp.link_nr = nv_encoder->dp.link_nr;
+ while ((dp.link_nr >> 1) * link_bw[0] > datarate)
+ dp.link_nr >>= 1;
+
+ /* drop link rate to minimum with this lane count */
+ while ((link_bw[1] * dp.link_nr) > datarate)
+ link_bw++;
+ dp.link_bw = link_bw[0];
+
+ /* program selected link configuration */
+ dp_set_link_config(dev, &dp);
+
+ /* attempt to train the link at this configuration */
+ memset(dp.stat, 0x00, sizeof(dp.stat));
+ if (!dp_link_train_cr(dev, &dp) &&
+ !dp_link_train_eq(dev, &dp))
+ break;
+
+ /* retry at lower rate */
+ link_bw++;
}
- /* re-enable hotplug detect */
- pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state);
+ /* finish link training */
+ dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE);
- return eq_done;
+ /* execute post-train script from vbios */
+ nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc);
+
+ /* re-enable hotplug detect */
+ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true);
+ return true;
}
bool
@@ -447,31 +648,34 @@ nouveau_dp_detect(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct drm_device *dev = encoder->dev;
- uint8_t dpcd[4];
+ struct nouveau_i2c_chan *auxch;
+ u8 *dpcd = nv_encoder->dp.dpcd;
int ret;
- ret = auxch_rd(encoder, 0x0000, dpcd, 4);
- if (ret)
+ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+ if (!auxch)
return false;
- NV_DEBUG_KMS(dev, "encoder: link_bw %d, link_nr %d\n"
- "display: link_bw %d, link_nr %d version 0x%02x\n",
- nv_encoder->dcb->dpconf.link_bw,
- nv_encoder->dcb->dpconf.link_nr,
- dpcd[1], dpcd[2] & 0x0f, dpcd[0]);
+ ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8);
+ if (ret)
+ return false;
- nv_encoder->dp.dpcd_version = dpcd[0];
+ nv_encoder->dp.link_bw = 27000 * dpcd[1];
+ nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
- nv_encoder->dp.link_bw = dpcd[1];
- if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62 &&
- !nv_encoder->dcb->dpconf.link_bw)
- nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
+ NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n",
+ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
+ NV_DEBUG_KMS(dev, "encoder: %dx%d\n",
+ nv_encoder->dcb->dpconf.link_nr,
+ nv_encoder->dcb->dpconf.link_bw);
- nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
- if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr)
+ if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr)
nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr;
+ if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw)
+ nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw;
- nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP);
+ NV_DEBUG_KMS(dev, "maximum: %dx%d\n",
+ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
return true;
}
@@ -480,105 +684,13 @@ int
nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
uint8_t *data, int data_nr)
{
- struct drm_device *dev = auxch->dev;
- uint32_t tmp, ctrl, stat = 0, data32[4] = {};
- int ret = 0, i, index = auxch->rd;
-
- NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr);
-
- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
- nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000);
- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
- if (!(tmp & 0x01000000)) {
- NV_ERROR(dev, "expected bit 24 == 1, got 0x%08x\n", tmp);
- ret = -EIO;
- goto out;
- }
-
- for (i = 0; i < 3; i++) {
- tmp = nv_rd32(dev, NV50_AUXCH_STAT(auxch->rd));
- if (tmp & NV50_AUXCH_STAT_STATE_READY)
- break;
- udelay(100);
- }
-
- if (i == 3) {
- ret = -EBUSY;
- goto out;
- }
-
- if (!(cmd & 1)) {
- memcpy(data32, data, data_nr);
- for (i = 0; i < 4; i++) {
- NV_DEBUG_KMS(dev, "wr %d: 0x%08x\n", i, data32[i]);
- nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]);
- }
- }
-
- nv_wr32(dev, NV50_AUXCH_ADDR(index), addr);
- ctrl = nv_rd32(dev, NV50_AUXCH_CTRL(index));
- ctrl &= ~(NV50_AUXCH_CTRL_CMD | NV50_AUXCH_CTRL_LEN);
- ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT);
- ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT);
-
- for (i = 0; i < 16; i++) {
- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000);
- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl);
- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000);
- if (!nv_wait(dev, NV50_AUXCH_CTRL(index),
- 0x00010000, 0x00000000)) {
- NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n",
- nv_rd32(dev, NV50_AUXCH_CTRL(index)));
- ret = -EBUSY;
- goto out;
- }
-
- udelay(400);
-
- stat = nv_rd32(dev, NV50_AUXCH_STAT(index));
- if ((stat & NV50_AUXCH_STAT_REPLY_AUX) !=
- NV50_AUXCH_STAT_REPLY_AUX_DEFER)
- break;
- }
-
- if (i == 16) {
- NV_ERROR(dev, "auxch DEFER too many times, bailing\n");
- ret = -EREMOTEIO;
- goto out;
- }
-
- if (cmd & 1) {
- if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
- ret = -EREMOTEIO;
- goto out;
- }
-
- for (i = 0; i < 4; i++) {
- data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i));
- NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]);
- }
- memcpy(data, data32, data_nr);
- }
-
-out:
- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
- nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp & ~0x00100000);
- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
- if (tmp & 0x01000000) {
- NV_ERROR(dev, "expected bit 24 == 0, got 0x%08x\n", tmp);
- ret = -EIO;
- }
-
- udelay(400);
-
- return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY);
+ return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr);
}
static int
nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap;
- struct drm_device *dev = auxch->dev;
struct i2c_msg *msg = msgs;
int ret, mcnt = num;
@@ -602,19 +714,6 @@ nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (ret < 0)
return ret;
- switch (ret & NV50_AUXCH_STAT_REPLY_I2C) {
- case NV50_AUXCH_STAT_REPLY_I2C_ACK:
- break;
- case NV50_AUXCH_STAT_REPLY_I2C_NACK:
- return -EREMOTEIO;
- case NV50_AUXCH_STAT_REPLY_I2C_DEFER:
- udelay(100);
- continue;
- default:
- NV_ERROR(dev, "bad auxch reply: 0x%08x\n", ret);
- return -EREMOTEIO;
- }
-
ptr += cnt;
remaining -= cnt;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index b30ddd8d2e2a..c1e01f37b9d1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -41,7 +41,7 @@ int nouveau_agpmode = -1;
module_param_named(agpmode, nouveau_agpmode, int, 0400);
MODULE_PARM_DESC(modeset, "Enable kernel modesetting");
-static int nouveau_modeset = -1; /* kms */
+int nouveau_modeset = -1;
module_param_named(modeset, nouveau_modeset, int, 0400);
MODULE_PARM_DESC(vbios, "Override default VBIOS location");
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index d7d51deb34b6..29837da1098b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -414,12 +414,13 @@ struct nouveau_gpio_engine {
};
struct nouveau_pm_voltage_level {
- u8 voltage;
- u8 vid;
+ u32 voltage; /* microvolts */
+ u8 vid;
};
struct nouveau_pm_voltage {
bool supported;
+ u8 version;
u8 vid_mask;
struct nouveau_pm_voltage_level *level;
@@ -428,17 +429,48 @@ struct nouveau_pm_voltage {
struct nouveau_pm_memtiming {
int id;
- u32 reg_100220;
- u32 reg_100224;
- u32 reg_100228;
- u32 reg_10022c;
- u32 reg_100230;
- u32 reg_100234;
- u32 reg_100238;
- u32 reg_10023c;
- u32 reg_100240;
+ u32 reg_0; /* 0x10f290 on Fermi, 0x100220 for older */
+ u32 reg_1;
+ u32 reg_2;
+ u32 reg_3;
+ u32 reg_4;
+ u32 reg_5;
+ u32 reg_6;
+ u32 reg_7;
+ u32 reg_8;
+ /* To be written to 0x1002c0 */
+ u8 CL;
+ u8 WR;
};
+struct nouveau_pm_tbl_header{
+ u8 version;
+ u8 header_len;
+ u8 entry_cnt;
+ u8 entry_len;
+};
+
+struct nouveau_pm_tbl_entry{
+ u8 tWR;
+ u8 tUNK_1;
+ u8 tCL;
+ u8 tRP; /* Byte 3 */
+ u8 empty_4;
+ u8 tRAS; /* Byte 5 */
+ u8 empty_6;
+ u8 tRFC; /* Byte 7 */
+ u8 empty_8;
+ u8 tRC; /* Byte 9 */
+ u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14;
+ u8 empty_15,empty_16,empty_17;
+ u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21;
+};
+
+/* nouveau_mem.c */
+void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number,
+ struct nouveau_pm_memtiming *timing);
+
#define NOUVEAU_PM_MAX_LEVEL 8
struct nouveau_pm_level {
struct device_attribute dev_attr;
@@ -448,11 +480,19 @@ struct nouveau_pm_level {
u32 core;
u32 memory;
u32 shader;
- u32 unk05;
- u32 unk0a;
-
- u8 voltage;
- u8 fanspeed;
+ u32 rop;
+ u32 copy;
+ u32 daemon;
+ u32 vdec;
+ u32 unk05; /* nv50:nva3, roughly.. */
+ u32 unka0; /* nva3:nvc0 */
+ u32 hub01; /* nvc0- */
+ u32 hub06; /* nvc0- */
+ u32 hub07; /* nvc0- */
+
+ u32 volt_min; /* microvolts */
+ u32 volt_max;
+ u8 fanspeed;
u16 memscript;
struct nouveau_pm_memtiming *timing;
@@ -496,6 +536,11 @@ struct nouveau_pm_engine {
void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *,
u32 id, int khz);
void (*clock_set)(struct drm_device *, void *);
+
+ int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *);
+ void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *);
+ void (*clocks_set)(struct drm_device *, void *);
+
int (*voltage_get)(struct drm_device *);
int (*voltage_set)(struct drm_device *, int voltage);
int (*fanspeed_get)(struct drm_device *);
@@ -504,7 +549,7 @@ struct nouveau_pm_engine {
};
struct nouveau_vram_engine {
- struct nouveau_mm *mm;
+ struct nouveau_mm mm;
int (*init)(struct drm_device *);
void (*takedown)(struct drm_device *dev);
@@ -623,6 +668,7 @@ enum nouveau_card_type {
NV_40 = 0x40,
NV_50 = 0x50,
NV_C0 = 0xc0,
+ NV_D0 = 0xd0
};
struct drm_nouveau_private {
@@ -633,8 +679,8 @@ struct drm_nouveau_private {
enum nouveau_card_type card_type;
/* exact chipset, derived from NV_PMC_BOOT_0 */
int chipset;
- int stepping;
int flags;
+ u32 crystal;
void __iomem *mmio;
@@ -721,7 +767,6 @@ struct drm_nouveau_private {
uint64_t vram_size;
uint64_t vram_sys_base;
- uint64_t fb_phys;
uint64_t fb_available_size;
uint64_t fb_mappable_pages;
uint64_t fb_aper_free;
@@ -784,6 +829,7 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo)
}
/* nouveau_drv.c */
+extern int nouveau_modeset;
extern int nouveau_agpmode;
extern int nouveau_duallink;
extern int nouveau_uscript_lvds;
@@ -824,6 +870,8 @@ extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val);
extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val);
+extern bool nouveau_wait_cb(struct drm_device *, u64 timeout,
+ bool (*cond)(void *), void *);
extern bool nouveau_wait_for_idle(struct drm_device *);
extern int nouveau_card_init(struct drm_device *);
@@ -1006,15 +1054,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector
/* nouveau_backlight.c */
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-extern int nouveau_backlight_init(struct drm_connector *);
-extern void nouveau_backlight_exit(struct drm_connector *);
+extern int nouveau_backlight_init(struct drm_device *);
+extern void nouveau_backlight_exit(struct drm_device *);
#else
-static inline int nouveau_backlight_init(struct drm_connector *dev)
+static inline int nouveau_backlight_init(struct drm_device *dev)
{
return 0;
}
-static inline void nouveau_backlight_exit(struct drm_connector *dev) { }
+static inline void nouveau_backlight_exit(struct drm_device *dev) { }
#endif
/* nouveau_bios.c */
@@ -1022,7 +1070,8 @@ extern int nouveau_bios_init(struct drm_device *);
extern void nouveau_bios_takedown(struct drm_device *dev);
extern int nouveau_run_vbios_init(struct drm_device *);
extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table,
- struct dcb_entry *);
+ struct dcb_entry *, int crtc);
+extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table);
extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *,
enum dcb_gpio_tag);
extern struct dcb_connector_table_entry *
@@ -1030,11 +1079,8 @@ nouveau_bios_connector_entry(struct drm_device *, int index);
extern u32 get_pll_register(struct drm_device *, enum pll_types);
extern int get_pll_limits(struct drm_device *, uint32_t limit_match,
struct pll_lims *);
-extern int nouveau_bios_run_display_table(struct drm_device *,
- struct dcb_entry *,
- uint32_t script, int pxclk);
-extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *,
- int *length);
+extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk,
+ struct dcb_entry *, int crtc);
extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *);
extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *);
extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk,
@@ -1043,6 +1089,7 @@ extern int run_tmds_table(struct drm_device *, struct dcb_entry *,
int head, int pxclk);
extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head,
enum LVDS_script, int pxclk);
+bool bios_encoder_match(struct dcb_entry *, u32 hash);
/* nouveau_ttm.c */
int nouveau_ttm_global_init(struct drm_nouveau_private *);
@@ -1053,7 +1100,9 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *);
int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
uint8_t *data, int data_nr);
bool nouveau_dp_detect(struct drm_encoder *);
-bool nouveau_dp_link_train(struct drm_encoder *);
+bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate);
+void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32);
+u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **);
/* nv04_fb.c */
extern int nv04_fb_init(struct drm_device *);
@@ -1179,8 +1228,8 @@ extern int nva3_copy_create(struct drm_device *dev);
/* nvc0_copy.c */
extern int nvc0_copy_create(struct drm_device *dev, int engine);
-/* nv40_mpeg.c */
-extern int nv40_mpeg_create(struct drm_device *dev);
+/* nv31_mpeg.c */
+extern int nv31_mpeg_create(struct drm_device *dev);
/* nv50_mpeg.c */
extern int nv50_mpeg_create(struct drm_device *dev);
@@ -1265,6 +1314,11 @@ extern int nv04_display_create(struct drm_device *);
extern int nv04_display_init(struct drm_device *);
extern void nv04_display_destroy(struct drm_device *);
+/* nvd0_display.c */
+extern int nvd0_display_create(struct drm_device *);
+extern int nvd0_display_init(struct drm_device *);
+extern void nvd0_display_destroy(struct drm_device *);
+
/* nv04_crtc.c */
extern int nv04_crtc_create(struct drm_device *, int index);
@@ -1374,6 +1428,8 @@ int nv50_gpio_init(struct drm_device *dev);
void nv50_gpio_fini(struct drm_device *dev);
int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
+int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
+int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag,
void (*)(void *, int), void *);
void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag,
@@ -1448,6 +1504,8 @@ static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val)
nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val))
#define nv_wait_ne(dev, reg, mask, val) \
nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val))
+#define nv_wait_cb(dev, func, data) \
+ nouveau_wait_cb(dev, 2000000000ULL, (func), (data))
/* PRAMIN access */
static inline u32 nv_ri32(struct drm_device *dev, unsigned offset)
@@ -1514,6 +1572,7 @@ enum {
NOUVEAU_REG_DEBUG_RMVIO = 0x80,
NOUVEAU_REG_DEBUG_VGAATTR = 0x100,
NOUVEAU_REG_DEBUG_EVO = 0x200,
+ NOUVEAU_REG_DEBUG_AUXCH = 0x400
};
#define NV_REG_DEBUG(type, dev, fmt, arg...) do { \
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index ae69b61d93db..e5d6e3faff3d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -49,17 +49,17 @@ struct nouveau_encoder {
union {
struct {
- int mc_unknown;
- uint32_t unk0;
- uint32_t unk1;
- int dpcd_version;
+ u8 dpcd[8];
int link_nr;
int link_bw;
- bool enhanced_frame;
+ u32 datarate;
} dp;
};
};
+struct nouveau_encoder *
+find_encoder(struct drm_connector *connector, int type);
+
static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc)
{
struct drm_encoder_slave *slave = to_encoder_slave(enc);
@@ -83,21 +83,4 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
int nv50_sor_create(struct drm_connector *, struct dcb_entry *);
int nv50_dac_create(struct drm_connector *, struct dcb_entry *);
-struct bit_displayport_encoder_table {
- uint32_t match;
- uint8_t record_nr;
- uint8_t unknown;
- uint16_t script0;
- uint16_t script1;
- uint16_t unknown_table;
-} __attribute__ ((packed));
-
-struct bit_displayport_encoder_table_entry {
- uint8_t vs_level;
- uint8_t pre_level;
- uint8_t reg0;
- uint8_t reg1;
- uint8_t reg2;
-} __attribute__ ((packed));
-
#endif /* __NOUVEAU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index c919cfc8f2fd..81116cfea275 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -519,7 +519,7 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
if (USE_SEMA(dev) && dev_priv->chipset < 0x84) {
struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem;
- ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY,
mem->start << PAGE_SHIFT,
mem->size, NV_MEM_ACCESS_RW,
NV_MEM_TARGET_VRAM, &obj);
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c
index cb389d014326..f6a27fabcfe0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_i2c.c
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c
@@ -107,6 +107,13 @@ nv4e_i2c_getsda(void *data)
return !!((nv_rd32(dev, i2c->rd) >> 16) & 8);
}
+static const uint32_t nv50_i2c_port[] = {
+ 0x00e138, 0x00e150, 0x00e168, 0x00e180,
+ 0x00e254, 0x00e274, 0x00e764, 0x00e780,
+ 0x00e79c, 0x00e7b8
+};
+#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)
+
static int
nv50_i2c_getscl(void *data)
{
@@ -130,28 +137,32 @@ static void
nv50_i2c_setscl(void *data, int state)
{
struct nouveau_i2c_chan *i2c = data;
- struct drm_device *dev = i2c->dev;
- nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
+ nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
}
static void
nv50_i2c_setsda(void *data, int state)
{
struct nouveau_i2c_chan *i2c = data;
- struct drm_device *dev = i2c->dev;
- nv_wr32(dev, i2c->wr,
- (nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0));
+ nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0));
i2c->data = state;
}
-static const uint32_t nv50_i2c_port[] = {
- 0x00e138, 0x00e150, 0x00e168, 0x00e180,
- 0x00e254, 0x00e274, 0x00e764, 0x00e780,
- 0x00e79c, 0x00e7b8
-};
-#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)
+static int
+nvd0_i2c_getscl(void *data)
+{
+ struct nouveau_i2c_chan *i2c = data;
+ return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10);
+}
+
+static int
+nvd0_i2c_getsda(void *data)
+{
+ struct nouveau_i2c_chan *i2c = data;
+ return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20);
+}
int
nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
@@ -163,7 +174,8 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
if (entry->chan)
return -EEXIST;
- if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) {
+ if (dev_priv->card_type >= NV_50 &&
+ dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) {
NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
return -EINVAL;
}
@@ -192,10 +204,17 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
case 5:
i2c->bit.setsda = nv50_i2c_setsda;
i2c->bit.setscl = nv50_i2c_setscl;
- i2c->bit.getsda = nv50_i2c_getsda;
- i2c->bit.getscl = nv50_i2c_getscl;
- i2c->rd = nv50_i2c_port[entry->read];
- i2c->wr = i2c->rd;
+ if (dev_priv->card_type < NV_D0) {
+ i2c->bit.getsda = nv50_i2c_getsda;
+ i2c->bit.getscl = nv50_i2c_getscl;
+ i2c->rd = nv50_i2c_port[entry->read];
+ i2c->wr = i2c->rd;
+ } else {
+ i2c->bit.getsda = nvd0_i2c_getsda;
+ i2c->bit.getscl = nvd0_i2c_getscl;
+ i2c->rd = 0x00d014 + (entry->read * 0x20);
+ i2c->wr = i2c->rd;
+ }
break;
case 6:
i2c->rd = entry->read;
@@ -267,7 +286,10 @@ nouveau_i2c_find(struct drm_device *dev, int index)
val = 0xe001;
}
- nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val);
+ /* nfi, but neither auxch or i2c work if it's 1 */
+ nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000);
+ /* nfi, but switches auxch vs normal i2c */
+ nv_mask(dev, reg + 0x00, 0x0000f003, val);
}
if (!i2c->chan && nouveau_i2c_init(dev, i2c, index))
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index f9ae2fc3d6f1..36bec4807701 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -408,8 +408,6 @@ nouveau_mem_vram_init(struct drm_device *dev)
if (ret)
return ret;
- dev_priv->fb_phys = pci_resource_start(dev->pdev, 1);
-
ret = nouveau_ttm_global_init(dev_priv);
if (ret)
return ret;
@@ -504,35 +502,146 @@ nouveau_mem_gart_init(struct drm_device *dev)
return 0;
}
+/* XXX: For now a dummy. More samples required, possibly even a card
+ * Called from nouveau_perf.c */
+void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number,
+ struct nouveau_pm_memtiming *timing) {
+
+ NV_DEBUG(dev,"Timing entry format unknown, please contact nouveau developers");
+}
+
+void nv40_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number,
+ struct nouveau_pm_memtiming *timing) {
+
+ timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP);
+
+ /* XXX: I don't trust the -1's and +1's... they must come
+ * from somewhere! */
+ timing->reg_1 = (e->tWR + 2 + magic_number) << 24 |
+ 1 << 16 |
+ (e->tUNK_1 + 2 + magic_number) << 8 |
+ (e->tCL + 2 - magic_number);
+ timing->reg_2 = (magic_number << 24 | e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10);
+ timing->reg_2 |= 0x20200000;
+
+ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id,
+ timing->reg_0, timing->reg_1,timing->reg_2);
+}
+
+void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P, struct nouveau_pm_tbl_header *hdr,
+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number,struct nouveau_pm_memtiming *timing) {
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+ uint8_t unk18 = 1,
+ unk19 = 1,
+ unk20 = 0,
+ unk21 = 0;
+
+ switch (min(hdr->entry_len, (u8) 22)) {
+ case 22:
+ unk21 = e->tUNK_21;
+ case 21:
+ unk20 = e->tUNK_20;
+ case 20:
+ unk19 = e->tUNK_19;
+ case 19:
+ unk18 = e->tUNK_18;
+ break;
+ }
+
+ timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP);
+
+ /* XXX: I don't trust the -1's and +1's... they must come
+ * from somewhere! */
+ timing->reg_1 = (e->tWR + unk19 + 1 + magic_number) << 24 |
+ max(unk18, (u8) 1) << 16 |
+ (e->tUNK_1 + unk19 + 1 + magic_number) << 8;
+ if (dev_priv->chipset == 0xa8) {
+ timing->reg_1 |= (e->tCL - 1);
+ } else {
+ timing->reg_1 |= (e->tCL + 2 - magic_number);
+ }
+ timing->reg_2 = (e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10);
+
+ timing->reg_5 = (e->tRAS << 24 | e->tRC);
+ timing->reg_5 += max(e->tUNK_10, e->tUNK_11) << 16;
+
+ if (P->version == 1) {
+ timing->reg_2 |= magic_number << 24;
+ timing->reg_3 = (0x14 + e->tCL) << 24 |
+ 0x16 << 16 |
+ (e->tCL - 1) << 8 |
+ (e->tCL - 1);
+ timing->reg_4 = (nv_rd32(dev,0x10022c) & 0xffff0000) | e->tUNK_13 << 8 | e->tUNK_13;
+ timing->reg_5 |= (e->tCL + 2) << 8;
+ timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16;
+ } else {
+ timing->reg_2 |= (unk19 - 1) << 24;
+ /* XXX: reg_10022c for recentish cards pretty much unknown*/
+ timing->reg_3 = e->tCL - 1;
+ timing->reg_4 = (unk20 << 24 | unk21 << 16 |
+ e->tUNK_13 << 8 | e->tUNK_13);
+ /* XXX: +6? */
+ timing->reg_5 |= (unk19 + 6) << 8;
+
+ /* XXX: reg_10023c currently unknown
+ * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */
+ timing->reg_7 = 0x202;
+ }
+
+ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id,
+ timing->reg_0, timing->reg_1,
+ timing->reg_2, timing->reg_3);
+ NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n",
+ timing->reg_4, timing->reg_5,
+ timing->reg_6, timing->reg_7);
+ NV_DEBUG(dev, " 240: %08x\n", timing->reg_8);
+}
+
+void nvc0_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+ struct nouveau_pm_tbl_entry *e, struct nouveau_pm_memtiming *timing) {
+ timing->reg_0 = (e->tRC << 24 | (e->tRFC & 0x7f) << 17 | e->tRAS << 8 | e->tRP);
+ timing->reg_1 = (nv_rd32(dev,0x10f294) & 0xff000000) | (e->tUNK_11&0x0f) << 20 | (e->tUNK_19 << 7) | (e->tCL & 0x0f);
+ timing->reg_2 = (nv_rd32(dev,0x10f298) & 0xff0000ff) | e->tWR << 16 | e->tUNK_1 << 8;
+ timing->reg_3 = e->tUNK_20 << 9 | e->tUNK_13;
+ timing->reg_4 = (nv_rd32(dev,0x10f2a0) & 0xfff000ff) | e->tUNK_12 << 15;
+ NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id,
+ timing->reg_0, timing->reg_1,
+ timing->reg_2, timing->reg_3);
+ NV_DEBUG(dev, " 2a0: %08x %08x %08x %08x\n",
+ timing->reg_4, timing->reg_5,
+ timing->reg_6, timing->reg_7);
+}
+
+/**
+ * Processes the Memory Timing BIOS table, stores generated
+ * register values
+ * @pre init scripts were run, memtiming regs are initialized
+ */
void
nouveau_mem_timing_init(struct drm_device *dev)
{
- /* cards < NVC0 only */
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
struct nouveau_pm_memtimings *memtimings = &pm->memtimings;
struct nvbios *bios = &dev_priv->vbios;
struct bit_entry P;
- u8 tUNK_0, tUNK_1, tUNK_2;
- u8 tRP; /* Byte 3 */
- u8 tRAS; /* Byte 5 */
- u8 tRFC; /* Byte 7 */
- u8 tRC; /* Byte 9 */
- u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14;
- u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21;
- u8 magic_number = 0; /* Yeah... sorry*/
- u8 *mem = NULL, *entry;
- int i, recordlen, entries;
+ struct nouveau_pm_tbl_header *hdr = NULL;
+ uint8_t magic_number;
+ u8 *entry;
+ int i;
if (bios->type == NVBIOS_BIT) {
if (bit_table(dev, 'P', &P))
return;
if (P.version == 1)
- mem = ROMPTR(bios, P.data[4]);
+ hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[4]);
else
if (P.version == 2)
- mem = ROMPTR(bios, P.data[8]);
+ hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[8]);
else {
NV_WARN(dev, "unknown mem for BIT P %d\n", P.version);
}
@@ -541,150 +650,56 @@ nouveau_mem_timing_init(struct drm_device *dev)
return;
}
- if (!mem) {
+ if (!hdr) {
NV_DEBUG(dev, "memory timing table pointer invalid\n");
return;
}
- if (mem[0] != 0x10) {
- NV_WARN(dev, "memory timing table 0x%02x unknown\n", mem[0]);
+ if (hdr->version != 0x10) {
+ NV_WARN(dev, "memory timing table 0x%02x unknown\n", hdr->version);
return;
}
/* validate record length */
- entries = mem[2];
- recordlen = mem[3];
- if (recordlen < 15) {
- NV_ERROR(dev, "mem timing table length unknown: %d\n", mem[3]);
+ if (hdr->entry_len < 15) {
+ NV_ERROR(dev, "mem timing table length unknown: %d\n", hdr->entry_len);
return;
}
/* parse vbios entries into common format */
memtimings->timing =
- kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL);
+ kcalloc(hdr->entry_cnt, sizeof(*memtimings->timing), GFP_KERNEL);
if (!memtimings->timing)
return;
/* Get "some number" from the timing reg for NV_40 and NV_50
- * Used in calculations later */
- if (dev_priv->card_type >= NV_40 && dev_priv->chipset < 0x98) {
+ * Used in calculations later... source unknown */
+ magic_number = 0;
+ if (P.version == 1) {
magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24;
}
- entry = mem + mem[1];
- for (i = 0; i < entries; i++, entry += recordlen) {
+ entry = (u8*) hdr + hdr->header_len;
+ for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) {
struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i];
if (entry[0] == 0)
continue;
- tUNK_18 = 1;
- tUNK_19 = 1;
- tUNK_20 = 0;
- tUNK_21 = 0;
- switch (min(recordlen, 22)) {
- case 22:
- tUNK_21 = entry[21];
- case 21:
- tUNK_20 = entry[20];
- case 20:
- tUNK_19 = entry[19];
- case 19:
- tUNK_18 = entry[18];
- default:
- tUNK_0 = entry[0];
- tUNK_1 = entry[1];
- tUNK_2 = entry[2];
- tRP = entry[3];
- tRAS = entry[5];
- tRFC = entry[7];
- tRC = entry[9];
- tUNK_10 = entry[10];
- tUNK_11 = entry[11];
- tUNK_12 = entry[12];
- tUNK_13 = entry[13];
- tUNK_14 = entry[14];
- break;
- }
-
- timing->reg_100220 = (tRC << 24 | tRFC << 16 | tRAS << 8 | tRP);
-
- /* XXX: I don't trust the -1's and +1's... they must come
- * from somewhere! */
- timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 |
- max(tUNK_18, (u8) 1) << 16 |
- (tUNK_1 + tUNK_19 + 1 + magic_number) << 8;
- if (dev_priv->chipset == 0xa8) {
- timing->reg_100224 |= (tUNK_2 - 1);
- } else {
- timing->reg_100224 |= (tUNK_2 + 2 - magic_number);
- }
-
- timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10);
- if (dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa)
- timing->reg_100228 |= (tUNK_19 - 1) << 24;
- else
- timing->reg_100228 |= magic_number << 24;
-
- if (dev_priv->card_type == NV_40) {
- /* NV40: don't know what the rest of the regs are..
- * And don't need to know either */
- timing->reg_100228 |= 0x20200000;
- } else if (dev_priv->card_type >= NV_50) {
- if (dev_priv->chipset < 0x98 ||
- (dev_priv->chipset == 0x98 &&
- dev_priv->stepping <= 0xa1)) {
- timing->reg_10022c = (0x14 + tUNK_2) << 24 |
- 0x16 << 16 |
- (tUNK_2 - 1) << 8 |
- (tUNK_2 - 1);
- } else {
- /* XXX: reg_10022c for recentish cards */
- timing->reg_10022c = tUNK_2 - 1;
- }
-
- timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
- tUNK_13 << 8 | tUNK_13);
-
- timing->reg_100234 = (tRAS << 24 | tRC);
- timing->reg_100234 += max(tUNK_10, tUNK_11) << 16;
-
- if (dev_priv->chipset < 0x98 ||
- (dev_priv->chipset == 0x98 &&
- dev_priv->stepping <= 0xa1)) {
- timing->reg_100234 |= (tUNK_2 + 2) << 8;
- } else {
- /* XXX: +6? */
- timing->reg_100234 |= (tUNK_19 + 6) << 8;
- }
-
- /* XXX; reg_100238
- * reg_100238: 0x00?????? */
- timing->reg_10023c = 0x202;
- if (dev_priv->chipset < 0x98 ||
- (dev_priv->chipset == 0x98 &&
- dev_priv->stepping <= 0xa1)) {
- timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16;
- } else {
- /* XXX: reg_10023c
- * currently unknown
- * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */
- }
-
- /* XXX: reg_100240? */
- }
timing->id = i;
-
- NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,
- timing->reg_100220, timing->reg_100224,
- timing->reg_100228, timing->reg_10022c);
- NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n",
- timing->reg_100230, timing->reg_100234,
- timing->reg_100238, timing->reg_10023c);
- NV_DEBUG(dev, " 240: %08x\n", timing->reg_100240);
+ timing->WR = entry[0];
+ timing->CL = entry[2];
+
+ if(dev_priv->card_type <= NV_40) {
+ nv40_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]);
+ } else if(dev_priv->card_type == NV_50){
+ nv50_mem_timing_entry(dev,&P,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]);
+ } else if(dev_priv->card_type == NV_C0) {
+ nvc0_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,&pm->memtimings.timing[i]);
+ }
}
- memtimings->nr_timing = entries;
- memtimings->supported = (dev_priv->chipset <= 0x98);
+ memtimings->nr_timing = hdr->entry_cnt;
+ memtimings->supported = P.version == 1;
}
void
@@ -693,7 +708,10 @@ nouveau_mem_timing_fini(struct drm_device *dev)
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings;
- kfree(mem->timing);
+ if(mem->timing) {
+ kfree(mem->timing);
+ mem->timing = NULL;
+ }
}
static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.c b/drivers/gpu/drm/nouveau/nouveau_mm.c
index 1640dec3b823..b29ffb3d1408 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.c
@@ -27,7 +27,7 @@
#include "nouveau_mm.h"
static inline void
-region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a)
+region_put(struct nouveau_mm *mm, struct nouveau_mm_node *a)
{
list_del(&a->nl_entry);
list_del(&a->fl_entry);
@@ -35,7 +35,7 @@ region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a)
}
static struct nouveau_mm_node *
-region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size)
+region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
{
struct nouveau_mm_node *b;
@@ -57,33 +57,33 @@ region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size)
return b;
}
-#define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \
+#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \
list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry)
void
-nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this)
+nouveau_mm_put(struct nouveau_mm *mm, struct nouveau_mm_node *this)
{
struct nouveau_mm_node *prev = node(this, prev);
struct nouveau_mm_node *next = node(this, next);
- list_add(&this->fl_entry, &rmm->free);
+ list_add(&this->fl_entry, &mm->free);
this->type = 0;
if (prev && prev->type == 0) {
prev->length += this->length;
- region_put(rmm, this);
+ region_put(mm, this);
this = prev;
}
if (next && next->type == 0) {
next->offset = this->offset;
next->length += this->length;
- region_put(rmm, this);
+ region_put(mm, this);
}
}
int
-nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
+nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc,
u32 align, struct nouveau_mm_node **pnode)
{
struct nouveau_mm_node *prev, *this, *next;
@@ -92,17 +92,17 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
u32 splitoff;
u32 s, e;
- list_for_each_entry(this, &rmm->free, fl_entry) {
+ list_for_each_entry(this, &mm->free, fl_entry) {
e = this->offset + this->length;
s = this->offset;
prev = node(this, prev);
if (prev && prev->type != type)
- s = roundup(s, rmm->block_size);
+ s = roundup(s, mm->block_size);
next = node(this, next);
if (next && next->type != type)
- e = rounddown(e, rmm->block_size);
+ e = rounddown(e, mm->block_size);
s = (s + align_mask) & ~align_mask;
e &= ~align_mask;
@@ -110,10 +110,10 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
continue;
splitoff = s - this->offset;
- if (splitoff && !region_split(rmm, this, splitoff))
+ if (splitoff && !region_split(mm, this, splitoff))
return -ENOMEM;
- this = region_split(rmm, this, min(size, e - s));
+ this = region_split(mm, this, min(size, e - s));
if (!this)
return -ENOMEM;
@@ -127,52 +127,49 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
}
int
-nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block)
+nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
{
- struct nouveau_mm *rmm;
- struct nouveau_mm_node *heap;
+ struct nouveau_mm_node *node;
+
+ if (block) {
+ mutex_init(&mm->mutex);
+ INIT_LIST_HEAD(&mm->nodes);
+ INIT_LIST_HEAD(&mm->free);
+ mm->block_size = block;
+ mm->heap_nodes = 0;
+ }
- heap = kzalloc(sizeof(*heap), GFP_KERNEL);
- if (!heap)
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node)
return -ENOMEM;
- heap->offset = roundup(offset, block);
- heap->length = rounddown(offset + length, block) - heap->offset;
+ node->offset = roundup(offset, mm->block_size);
+ node->length = rounddown(offset + length, mm->block_size) - node->offset;
- rmm = kzalloc(sizeof(*rmm), GFP_KERNEL);
- if (!rmm) {
- kfree(heap);
- return -ENOMEM;
- }
- rmm->block_size = block;
- mutex_init(&rmm->mutex);
- INIT_LIST_HEAD(&rmm->nodes);
- INIT_LIST_HEAD(&rmm->free);
- list_add(&heap->nl_entry, &rmm->nodes);
- list_add(&heap->fl_entry, &rmm->free);
-
- *prmm = rmm;
+ list_add_tail(&node->nl_entry, &mm->nodes);
+ list_add_tail(&node->fl_entry, &mm->free);
+ mm->heap_nodes++;
return 0;
}
int
-nouveau_mm_fini(struct nouveau_mm **prmm)
+nouveau_mm_fini(struct nouveau_mm *mm)
{
- struct nouveau_mm *rmm = *prmm;
struct nouveau_mm_node *node, *heap =
- list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry);
-
- if (!list_is_singular(&rmm->nodes)) {
- printk(KERN_ERR "nouveau_mm not empty at destroy time!\n");
- list_for_each_entry(node, &rmm->nodes, nl_entry) {
- printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
- node->type, node->offset, node->length);
+ list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry);
+ int nodes = 0;
+
+ list_for_each_entry(node, &mm->nodes, nl_entry) {
+ if (nodes++ == mm->heap_nodes) {
+ printk(KERN_ERR "nouveau_mm in use at destroy time!\n");
+ list_for_each_entry(node, &mm->nodes, nl_entry) {
+ printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
+ node->type, node->offset, node->length);
+ }
+ WARN_ON(1);
+ return -EBUSY;
}
- WARN_ON(1);
- return -EBUSY;
}
kfree(heap);
- kfree(rmm);
- *prmm = NULL;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h
index b9c016d21553..57a600c35c95 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.h
@@ -42,10 +42,11 @@ struct nouveau_mm {
struct mutex mutex;
u32 block_size;
+ int heap_nodes;
};
-int nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block);
-int nouveau_mm_fini(struct nouveau_mm **);
+int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
+int nouveau_mm_fini(struct nouveau_mm *);
int nouveau_mm_pre(struct nouveau_mm *);
int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc,
u32 align, struct nouveau_mm_node **);
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index 159b7c437d3f..02222c540aee 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -693,6 +693,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
static int
nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm)
{
+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
struct drm_device *dev = chan->dev;
struct nouveau_gpuobj *pgd = NULL;
struct nouveau_vm_pgd *vpgd;
@@ -722,6 +723,9 @@ nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm)
nv_wo32(chan->ramin, 0x020c, 0x000000ff);
/* map display semaphore buffers into channel's vm */
+ if (dev_priv->card_type >= NV_D0)
+ return 0;
+
for (i = 0; i < 2; i++) {
struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i];
@@ -746,7 +750,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
int ret, i;
NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
- if (dev_priv->card_type == NV_C0)
+ if (dev_priv->card_type >= NV_C0)
return nvc0_gpuobj_channel_init(chan, vm);
/* Allocate a chunk of memory for per-channel object storage */
@@ -793,7 +797,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
return ret;
/* dma objects for display sync channel semaphore blocks */
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < dev->mode_config.num_crtc; i++) {
struct nouveau_gpuobj *sem = NULL;
struct nv50_display_crtc *dispc =
&nv50_display(dev)->crtc[i];
@@ -875,18 +879,18 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
NV_DEBUG(dev, "ch%d\n", chan->id);
- if (dev_priv->card_type >= NV_50) {
+ if (dev_priv->card_type >= NV_50 && dev_priv->card_type <= NV_C0) {
struct nv50_display *disp = nv50_display(dev);
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < dev->mode_config.num_crtc; i++) {
struct nv50_display_crtc *dispc = &disp->crtc[i];
nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]);
}
-
- nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
- nouveau_gpuobj_ref(NULL, &chan->vm_pd);
}
+ nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
+ nouveau_gpuobj_ref(NULL, &chan->vm_pd);
+
if (drm_mm_initialized(&chan->ramin_heap))
drm_mm_takedown(&chan->ramin_heap);
nouveau_gpuobj_ref(NULL, &chan->ramin);
diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c
index ef9dec0e6f8b..9f178aa94162 100644
--- a/drivers/gpu/drm/nouveau/nouveau_perf.c
+++ b/drivers/gpu/drm/nouveau/nouveau_perf.c
@@ -127,13 +127,57 @@ nouveau_perf_timing(struct drm_device *dev, struct bit_entry *P,
entry += ramcfg * recordlen;
if (entry[1] >= pm->memtimings.nr_timing) {
- NV_WARN(dev, "timingset %d does not exist\n", entry[1]);
+ if (entry[1] != 0xff)
+ NV_WARN(dev, "timingset %d does not exist\n", entry[1]);
return NULL;
}
return &pm->memtimings.timing[entry[1]];
}
+static void
+nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P,
+ struct nouveau_pm_level *perflvl)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nvbios *bios = &dev_priv->vbios;
+ u8 *vmap;
+ int id;
+
+ id = perflvl->volt_min;
+ perflvl->volt_min = 0;
+
+ /* boards using voltage table version <0x40 store the voltage
+ * level directly in the perflvl entry as a multiple of 10mV
+ */
+ if (dev_priv->engine.pm.voltage.version < 0x40) {
+ perflvl->volt_min = id * 10000;
+ perflvl->volt_max = perflvl->volt_min;
+ return;
+ }
+
+ /* on newer ones, the perflvl stores an index into yet another
+ * vbios table containing a min/max voltage value for the perflvl
+ */
+ if (P->version != 2 || P->length < 34) {
+ NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n",
+ P->version, P->length);
+ return;
+ }
+
+ vmap = ROMPTR(bios, P->data[32]);
+ if (!vmap) {
+ NV_DEBUG(dev, "volt map table pointer invalid\n");
+ return;
+ }
+
+ if (id < vmap[3]) {
+ vmap += vmap[1] + (vmap[2] * id);
+ perflvl->volt_min = ROM32(vmap[0]);
+ perflvl->volt_max = ROM32(vmap[4]);
+ }
+}
+
void
nouveau_perf_init(struct drm_device *dev)
{
@@ -141,6 +185,8 @@ nouveau_perf_init(struct drm_device *dev)
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
struct nvbios *bios = &dev_priv->vbios;
struct bit_entry P;
+ struct nouveau_pm_memtimings *memtimings = &pm->memtimings;
+ struct nouveau_pm_tbl_header mt_hdr;
u8 version, headerlen, recordlen, entries;
u8 *perf, *entry;
int vid, i;
@@ -188,6 +234,22 @@ nouveau_perf_init(struct drm_device *dev)
}
entry = perf + headerlen;
+
+ /* For version 0x15, initialize memtiming table */
+ if(version == 0x15) {
+ memtimings->timing =
+ kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL);
+ if(!memtimings) {
+ NV_WARN(dev,"Could not allocate memtiming table\n");
+ return;
+ }
+
+ mt_hdr.entry_cnt = entries;
+ mt_hdr.entry_len = 14;
+ mt_hdr.version = version;
+ mt_hdr.header_len = 4;
+ }
+
for (i = 0; i < entries; i++) {
struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl];
@@ -203,7 +265,8 @@ nouveau_perf_init(struct drm_device *dev)
case 0x13:
case 0x15:
perflvl->fanspeed = entry[55];
- perflvl->voltage = (recordlen > 56) ? entry[56] : 0;
+ if (recordlen > 56)
+ perflvl->volt_min = entry[56];
perflvl->core = ROM32(entry[1]) * 10;
perflvl->memory = ROM32(entry[5]) * 20;
break;
@@ -211,9 +274,10 @@ nouveau_perf_init(struct drm_device *dev)
case 0x23:
case 0x24:
perflvl->fanspeed = entry[4];
- perflvl->voltage = entry[5];
- perflvl->core = ROM16(entry[6]) * 1000;
-
+ perflvl->volt_min = entry[5];
+ perflvl->shader = ROM16(entry[6]) * 1000;
+ perflvl->core = perflvl->shader;
+ perflvl->core += (signed char)entry[8] * 1000;
if (dev_priv->chipset == 0x49 ||
dev_priv->chipset == 0x4b)
perflvl->memory = ROM16(entry[11]) * 1000;
@@ -223,7 +287,7 @@ nouveau_perf_init(struct drm_device *dev)
break;
case 0x25:
perflvl->fanspeed = entry[4];
- perflvl->voltage = entry[5];
+ perflvl->volt_min = entry[5];
perflvl->core = ROM16(entry[6]) * 1000;
perflvl->shader = ROM16(entry[10]) * 1000;
perflvl->memory = ROM16(entry[12]) * 1000;
@@ -232,7 +296,7 @@ nouveau_perf_init(struct drm_device *dev)
perflvl->memscript = ROM16(entry[2]);
case 0x35:
perflvl->fanspeed = entry[6];
- perflvl->voltage = entry[7];
+ perflvl->volt_min = entry[7];
perflvl->core = ROM16(entry[8]) * 1000;
perflvl->shader = ROM16(entry[10]) * 1000;
perflvl->memory = ROM16(entry[12]) * 1000;
@@ -240,30 +304,34 @@ nouveau_perf_init(struct drm_device *dev)
perflvl->unk05 = ROM16(entry[16]) * 1000;
break;
case 0x40:
-#define subent(n) entry[perf[2] + ((n) * perf[3])]
+#define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000
perflvl->fanspeed = 0; /*XXX*/
- perflvl->voltage = entry[2];
+ perflvl->volt_min = entry[2];
if (dev_priv->card_type == NV_50) {
- perflvl->core = ROM16(subent(0)) & 0xfff;
- perflvl->shader = ROM16(subent(1)) & 0xfff;
- perflvl->memory = ROM16(subent(2)) & 0xfff;
+ perflvl->core = subent(0);
+ perflvl->shader = subent(1);
+ perflvl->memory = subent(2);
+ perflvl->vdec = subent(3);
+ perflvl->unka0 = subent(4);
} else {
- perflvl->shader = ROM16(subent(3)) & 0xfff;
+ perflvl->hub06 = subent(0);
+ perflvl->hub01 = subent(1);
+ perflvl->copy = subent(2);
+ perflvl->shader = subent(3);
+ perflvl->rop = subent(4);
+ perflvl->memory = subent(5);
+ perflvl->vdec = subent(6);
+ perflvl->daemon = subent(10);
+ perflvl->hub07 = subent(11);
perflvl->core = perflvl->shader / 2;
- perflvl->unk0a = ROM16(subent(4)) & 0xfff;
- perflvl->memory = ROM16(subent(5)) & 0xfff;
}
-
- perflvl->core *= 1000;
- perflvl->shader *= 1000;
- perflvl->memory *= 1000;
- perflvl->unk0a *= 1000;
break;
}
/* make sure vid is valid */
- if (pm->voltage.supported && perflvl->voltage) {
- vid = nouveau_volt_vid_lookup(dev, perflvl->voltage);
+ nouveau_perf_voltage(dev, &P, perflvl);
+ if (pm->voltage.supported && perflvl->volt_min) {
+ vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min);
if (vid < 0) {
NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i);
entry += recordlen;
@@ -272,7 +340,11 @@ nouveau_perf_init(struct drm_device *dev)
}
/* get the corresponding memory timings */
- if (version > 0x15) {
+ if (version == 0x15) {
+ memtimings->timing[i].id = i;
+ nv30_mem_timing_entry(dev,&mt_hdr,(struct nouveau_pm_tbl_entry*) &entry[41],0,&memtimings->timing[i]);
+ perflvl->timing = &memtimings->timing[i];
+ } else if (version > 0x15) {
/* last 3 args are for < 0x40, ignored for >= 0x40 */
perflvl->timing =
nouveau_perf_timing(dev, &P,
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c
index da8d994d5e8a..a539fd257921 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -64,18 +64,26 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl)
if (perflvl == pm->cur)
return 0;
- if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) {
- ret = pm->voltage_set(dev, perflvl->voltage);
+ if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) {
+ ret = pm->voltage_set(dev, perflvl->volt_min);
if (ret) {
NV_ERROR(dev, "voltage_set %d failed: %d\n",
- perflvl->voltage, ret);
+ perflvl->volt_min, ret);
}
}
- nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core);
- nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader);
- nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory);
- nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05);
+ if (pm->clocks_pre) {
+ void *state = pm->clocks_pre(dev, perflvl);
+ if (IS_ERR(state))
+ return PTR_ERR(state);
+ pm->clocks_set(dev, state);
+ } else
+ if (pm->clock_set) {
+ nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core);
+ nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader);
+ nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory);
+ nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05);
+ }
pm->cur = perflvl;
return 0;
@@ -92,9 +100,6 @@ nouveau_pm_profile_set(struct drm_device *dev, const char *profile)
if (nouveau_perflvl_wr != 7777)
return -EPERM;
- if (!pm->clock_set)
- return -EINVAL;
-
if (!strncmp(profile, "boot", 4))
perflvl = &pm->boot;
else {
@@ -123,31 +128,37 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
int ret;
- if (!pm->clock_get)
- return -EINVAL;
-
memset(perflvl, 0, sizeof(*perflvl));
- ret = pm->clock_get(dev, PLL_CORE);
- if (ret > 0)
- perflvl->core = ret;
+ if (pm->clocks_get) {
+ ret = pm->clocks_get(dev, perflvl);
+ if (ret)
+ return ret;
+ } else
+ if (pm->clock_get) {
+ ret = pm->clock_get(dev, PLL_CORE);
+ if (ret > 0)
+ perflvl->core = ret;
- ret = pm->clock_get(dev, PLL_MEMORY);
- if (ret > 0)
- perflvl->memory = ret;
+ ret = pm->clock_get(dev, PLL_MEMORY);
+ if (ret > 0)
+ perflvl->memory = ret;
- ret = pm->clock_get(dev, PLL_SHADER);
- if (ret > 0)
- perflvl->shader = ret;
+ ret = pm->clock_get(dev, PLL_SHADER);
+ if (ret > 0)
+ perflvl->shader = ret;
- ret = pm->clock_get(dev, PLL_UNK05);
- if (ret > 0)
- perflvl->unk05 = ret;
+ ret = pm->clock_get(dev, PLL_UNK05);
+ if (ret > 0)
+ perflvl->unk05 = ret;
+ }
if (pm->voltage.supported && pm->voltage_get) {
ret = pm->voltage_get(dev);
- if (ret > 0)
- perflvl->voltage = ret;
+ if (ret > 0) {
+ perflvl->volt_min = ret;
+ perflvl->volt_max = ret;
+ }
}
return 0;
@@ -156,7 +167,7 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
static void
nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
{
- char c[16], s[16], v[16], f[16], t[16];
+ char c[16], s[16], v[32], f[16], t[16], m[16];
c[0] = '\0';
if (perflvl->core)
@@ -166,9 +177,19 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
if (perflvl->shader)
snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000);
+ m[0] = '\0';
+ if (perflvl->memory)
+ snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000);
+
v[0] = '\0';
- if (perflvl->voltage)
- snprintf(v, sizeof(v), " voltage %dmV", perflvl->voltage * 10);
+ if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) {
+ snprintf(v, sizeof(v), " voltage %dmV-%dmV",
+ perflvl->volt_min / 1000, perflvl->volt_max / 1000);
+ } else
+ if (perflvl->volt_min) {
+ snprintf(v, sizeof(v), " voltage %dmV",
+ perflvl->volt_min / 1000);
+ }
f[0] = '\0';
if (perflvl->fanspeed)
@@ -178,8 +199,7 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
if (perflvl->timing)
snprintf(t, sizeof(t), " timing %d", perflvl->timing->id);
- snprintf(ptr, len, "memory %dMHz%s%s%s%s%s\n", perflvl->memory / 1000,
- c, s, v, f, t);
+ snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f);
}
static ssize_t
@@ -190,7 +210,7 @@ nouveau_pm_get_perflvl_info(struct device *d,
char *ptr = buf;
int len = PAGE_SIZE;
- snprintf(ptr, len, "%d: ", perflvl->id);
+ snprintf(ptr, len, "%d:", perflvl->id);
ptr += strlen(buf);
len -= strlen(buf);
@@ -211,9 +231,9 @@ nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf)
if (!pm->cur)
snprintf(ptr, len, "setting: boot\n");
else if (pm->cur == &pm->boot)
- snprintf(ptr, len, "setting: boot\nc: ");
+ snprintf(ptr, len, "setting: boot\nc:");
else
- snprintf(ptr, len, "setting: static %d\nc: ", pm->cur->id);
+ snprintf(ptr, len, "setting: static %d\nc:", pm->cur->id);
ptr += strlen(buf);
len -= strlen(buf);
@@ -292,7 +312,7 @@ nouveau_sysfs_fini(struct drm_device *dev)
}
}
-#ifdef CONFIG_HWMON
+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
static ssize_t
nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
{
@@ -409,7 +429,7 @@ static const struct attribute_group hwmon_attrgroup = {
static int
nouveau_hwmon_init(struct drm_device *dev)
{
-#ifdef CONFIG_HWMON
+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
struct device *hwmon_dev;
@@ -442,7 +462,7 @@ nouveau_hwmon_init(struct drm_device *dev)
static void
nouveau_hwmon_fini(struct drm_device *dev)
{
-#ifdef CONFIG_HWMON
+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
@@ -488,7 +508,7 @@ nouveau_pm_init(struct drm_device *dev)
NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl);
for (i = 0; i < pm->nr_perflvl; i++) {
nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info));
- NV_INFO(dev, "%d: %s", pm->perflvl[i].id, info);
+ NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info);
}
/* determine current ("boot") performance level */
@@ -498,7 +518,7 @@ nouveau_pm_init(struct drm_device *dev)
pm->cur = &pm->boot;
nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info));
- NV_INFO(dev, "c: %s", info);
+ NV_INFO(dev, "c:%s", info);
}
/* switch performance levels now if requested */
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h
index 4a9838ddacec..8ac02cdd03a1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.h
@@ -52,6 +52,11 @@ void *nv04_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
u32 id, int khz);
void nv04_pm_clock_set(struct drm_device *, void *);
+/* nv40_pm.c */
+int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
+void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *);
+void nv40_pm_clocks_set(struct drm_device *, void *);
+
/* nv50_pm.c */
int nv50_pm_clock_get(struct drm_device *, u32 id);
void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
@@ -59,10 +64,12 @@ void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
void nv50_pm_clock_set(struct drm_device *, void *);
/* nva3_pm.c */
-int nva3_pm_clock_get(struct drm_device *, u32 id);
-void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
- u32 id, int khz);
-void nva3_pm_clock_set(struct drm_device *, void *);
+int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
+void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *);
+void nva3_pm_clocks_set(struct drm_device *, void *);
+
+/* nvc0_pm.c */
+int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
/* nouveau_temp.c */
void nouveau_temp_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h
index f18cdfc3400f..43a96b99e180 100644
--- a/drivers/gpu/drm/nouveau/nouveau_reg.h
+++ b/drivers/gpu/drm/nouveau/nouveau_reg.h
@@ -826,9 +826,12 @@
#define NV50_PDISPLAY_SOR_DPMS_STATE_ACTIVE 0x00030000
#define NV50_PDISPLAY_SOR_DPMS_STATE_BLANKED 0x00080000
#define NV50_PDISPLAY_SOR_DPMS_STATE_WAIT 0x10000000
-#define NV50_PDISPLAY_SOR_BACKLIGHT 0x0061c084
-#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000
-#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff
+#define NV50_PDISP_SOR_PWM_DIV(i) (0x0061c080 + (i) * 0x800)
+#define NV50_PDISP_SOR_PWM_CTL(i) (0x0061c084 + (i) * 0x800)
+#define NV50_PDISP_SOR_PWM_CTL_NEW 0x80000000
+#define NVA3_PDISP_SOR_PWM_CTL_UNK 0x40000000
+#define NV50_PDISP_SOR_PWM_CTL_VAL 0x000007ff
+#define NVA3_PDISP_SOR_PWM_CTL_VAL 0x00ffffff
#define NV50_SOR_DP_CTRL(i, l) (0x0061c10c + (i) * 0x800 + (l) * 0x80)
#define NV50_SOR_DP_CTRL_ENABLED 0x00000001
#define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000
@@ -843,7 +846,7 @@
#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2 0x02000000
#define NV50_SOR_DP_UNK118(i, l) (0x0061c118 + (i) * 0x800 + (l) * 0x80)
#define NV50_SOR_DP_UNK120(i, l) (0x0061c120 + (i) * 0x800 + (l) * 0x80)
-#define NV50_SOR_DP_UNK128(i, l) (0x0061c128 + (i) * 0x800 + (l) * 0x80)
+#define NV50_SOR_DP_SCFG(i, l) (0x0061c128 + (i) * 0x800 + (l) * 0x80)
#define NV50_SOR_DP_UNK130(i, l) (0x0061c130 + (i) * 0x800 + (l) * 0x80)
#define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000)
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
index 2706cb3d871a..b75258a9fe44 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -12,8 +12,8 @@ struct nouveau_sgdma_be {
struct drm_device *dev;
dma_addr_t *pages;
- bool *ttm_alloced;
unsigned nr_pages;
+ bool unmap_pages;
u64 offset;
bool bound;
@@ -26,43 +26,28 @@ nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
{
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
struct drm_device *dev = nvbe->dev;
+ int i;
NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages);
- if (nvbe->pages)
- return -EINVAL;
-
- nvbe->pages = kmalloc(sizeof(dma_addr_t) * num_pages, GFP_KERNEL);
- if (!nvbe->pages)
- return -ENOMEM;
+ nvbe->pages = dma_addrs;
+ nvbe->nr_pages = num_pages;
+ nvbe->unmap_pages = true;
- nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL);
- if (!nvbe->ttm_alloced) {
- kfree(nvbe->pages);
- nvbe->pages = NULL;
- return -ENOMEM;
+ /* this code path isn't called and is incorrect anyways */
+ if (0) { /* dma_addrs[0] != DMA_ERROR_CODE) { */
+ nvbe->unmap_pages = false;
+ return 0;
}
- nvbe->nr_pages = 0;
- while (num_pages--) {
- /* this code path isn't called and is incorrect anyways */
- if (0) { /*dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE)*/
- nvbe->pages[nvbe->nr_pages] =
- dma_addrs[nvbe->nr_pages];
- nvbe->ttm_alloced[nvbe->nr_pages] = true;
- } else {
- nvbe->pages[nvbe->nr_pages] =
- pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0,
- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
- if (pci_dma_mapping_error(dev->pdev,
- nvbe->pages[nvbe->nr_pages])) {
- be->func->clear(be);
- return -EFAULT;
- }
- nvbe->ttm_alloced[nvbe->nr_pages] = false;
+ for (i = 0; i < num_pages; i++) {
+ nvbe->pages[i] = pci_map_page(dev->pdev, pages[i], 0,
+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(dev->pdev, nvbe->pages[i])) {
+ nvbe->nr_pages = --i;
+ be->func->clear(be);
+ return -EFAULT;
}
-
- nvbe->nr_pages++;
}
return 0;
@@ -72,25 +57,16 @@ static void
nouveau_sgdma_clear(struct ttm_backend *be)
{
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
- struct drm_device *dev;
-
- if (nvbe && nvbe->pages) {
- dev = nvbe->dev;
- NV_DEBUG(dev, "\n");
+ struct drm_device *dev = nvbe->dev;
- if (nvbe->bound)
- be->func->unbind(be);
+ if (nvbe->bound)
+ be->func->unbind(be);
+ if (nvbe->unmap_pages) {
while (nvbe->nr_pages--) {
- if (!nvbe->ttm_alloced[nvbe->nr_pages])
- pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
+ pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
}
- kfree(nvbe->pages);
- kfree(nvbe->ttm_alloced);
- nvbe->pages = NULL;
- nvbe->ttm_alloced = NULL;
- nvbe->nr_pages = 0;
}
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 10656e430b44..82478e0998e5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -286,9 +286,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->gpio.get = nv10_gpio_get;
engine->gpio.set = nv10_gpio_set;
engine->gpio.irq_enable = NULL;
- engine->pm.clock_get = nv04_pm_clock_get;
- engine->pm.clock_pre = nv04_pm_clock_pre;
- engine->pm.clock_set = nv04_pm_clock_set;
+ engine->pm.clocks_get = nv40_pm_clocks_get;
+ engine->pm.clocks_pre = nv40_pm_clocks_pre;
+ engine->pm.clocks_set = nv40_pm_clocks_set;
engine->pm.voltage_get = nouveau_voltage_gpio_get;
engine->pm.voltage_set = nouveau_voltage_gpio_set;
engine->pm.temp_get = nv40_temp_get;
@@ -299,7 +299,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
case 0x50:
case 0x80: /* gotta love NVIDIA's consistency.. */
case 0x90:
- case 0xA0:
+ case 0xa0:
engine->instmem.init = nv50_instmem_init;
engine->instmem.takedown = nv50_instmem_takedown;
engine->instmem.suspend = nv50_instmem_suspend;
@@ -359,9 +359,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clock_set = nv50_pm_clock_set;
break;
default:
- engine->pm.clock_get = nva3_pm_clock_get;
- engine->pm.clock_pre = nva3_pm_clock_pre;
- engine->pm.clock_set = nva3_pm_clock_set;
+ engine->pm.clocks_get = nva3_pm_clocks_get;
+ engine->pm.clocks_pre = nva3_pm_clocks_pre;
+ engine->pm.clocks_set = nva3_pm_clocks_set;
break;
}
engine->pm.voltage_get = nouveau_voltage_gpio_get;
@@ -376,7 +376,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->vram.put = nv50_vram_del;
engine->vram.flags_valid = nv50_vram_flags_valid;
break;
- case 0xC0:
+ case 0xc0:
engine->instmem.init = nvc0_instmem_init;
engine->instmem.takedown = nvc0_instmem_takedown;
engine->instmem.suspend = nvc0_instmem_suspend;
@@ -422,12 +422,73 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->vram.put = nv50_vram_del;
engine->vram.flags_valid = nvc0_vram_flags_valid;
engine->pm.temp_get = nv84_temp_get;
+ engine->pm.clocks_get = nvc0_pm_clocks_get;
+ engine->pm.voltage_get = nouveau_voltage_gpio_get;
+ engine->pm.voltage_set = nouveau_voltage_gpio_set;
+ break;
+ case 0xd0:
+ engine->instmem.init = nvc0_instmem_init;
+ engine->instmem.takedown = nvc0_instmem_takedown;
+ engine->instmem.suspend = nvc0_instmem_suspend;
+ engine->instmem.resume = nvc0_instmem_resume;
+ engine->instmem.get = nv50_instmem_get;
+ engine->instmem.put = nv50_instmem_put;
+ engine->instmem.map = nv50_instmem_map;
+ engine->instmem.unmap = nv50_instmem_unmap;
+ engine->instmem.flush = nv84_instmem_flush;
+ engine->mc.init = nv50_mc_init;
+ engine->mc.takedown = nv50_mc_takedown;
+ engine->timer.init = nv04_timer_init;
+ engine->timer.read = nv04_timer_read;
+ engine->timer.takedown = nv04_timer_takedown;
+ engine->fb.init = nvc0_fb_init;
+ engine->fb.takedown = nvc0_fb_takedown;
+ engine->fifo.channels = 128;
+ engine->fifo.init = nvc0_fifo_init;
+ engine->fifo.takedown = nvc0_fifo_takedown;
+ engine->fifo.disable = nvc0_fifo_disable;
+ engine->fifo.enable = nvc0_fifo_enable;
+ engine->fifo.reassign = nvc0_fifo_reassign;
+ engine->fifo.channel_id = nvc0_fifo_channel_id;
+ engine->fifo.create_context = nvc0_fifo_create_context;
+ engine->fifo.destroy_context = nvc0_fifo_destroy_context;
+ engine->fifo.load_context = nvc0_fifo_load_context;
+ engine->fifo.unload_context = nvc0_fifo_unload_context;
+ engine->display.early_init = nouveau_stub_init;
+ engine->display.late_takedown = nouveau_stub_takedown;
+ engine->display.create = nvd0_display_create;
+ engine->display.init = nvd0_display_init;
+ engine->display.destroy = nvd0_display_destroy;
+ engine->gpio.init = nv50_gpio_init;
+ engine->gpio.takedown = nouveau_stub_takedown;
+ engine->gpio.get = nvd0_gpio_get;
+ engine->gpio.set = nvd0_gpio_set;
+ engine->gpio.irq_register = nv50_gpio_irq_register;
+ engine->gpio.irq_unregister = nv50_gpio_irq_unregister;
+ engine->gpio.irq_enable = nv50_gpio_irq_enable;
+ engine->vram.init = nvc0_vram_init;
+ engine->vram.takedown = nv50_vram_fini;
+ engine->vram.get = nvc0_vram_new;
+ engine->vram.put = nv50_vram_del;
+ engine->vram.flags_valid = nvc0_vram_flags_valid;
+ engine->pm.clocks_get = nvc0_pm_clocks_get;
+ engine->pm.voltage_get = nouveau_voltage_gpio_get;
+ engine->pm.voltage_set = nouveau_voltage_gpio_set;
break;
default:
NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
return 1;
}
+ /* headless mode */
+ if (nouveau_modeset == 2) {
+ engine->display.early_init = nouveau_stub_init;
+ engine->display.late_takedown = nouveau_stub_takedown;
+ engine->display.create = nouveau_stub_init;
+ engine->display.init = nouveau_stub_init;
+ engine->display.destroy = nouveau_stub_takedown;
+ }
+
return 0;
}
@@ -449,21 +510,6 @@ nouveau_vga_set_decode(void *priv, bool state)
return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
}
-static int
-nouveau_card_init_channel(struct drm_device *dev)
-{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- int ret;
-
- ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
- NvDmaFB, NvDmaTT);
- if (ret)
- return ret;
-
- mutex_unlock(&dev_priv->channel->mutex);
- return 0;
-}
-
static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
enum vga_switcheroo_state state)
{
@@ -630,8 +676,11 @@ nouveau_card_init(struct drm_device *dev)
break;
}
- if (dev_priv->card_type == NV_40)
- nv40_mpeg_create(dev);
+ if (dev_priv->card_type == NV_40 ||
+ dev_priv->chipset == 0x31 ||
+ dev_priv->chipset == 0x34 ||
+ dev_priv->chipset == 0x36)
+ nv31_mpeg_create(dev);
else
if (dev_priv->card_type == NV_50 &&
(dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0))
@@ -651,41 +700,69 @@ nouveau_card_init(struct drm_device *dev)
goto out_engine;
}
- ret = engine->display.create(dev);
+ ret = nouveau_irq_init(dev);
if (ret)
goto out_fifo;
- ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1);
- if (ret)
- goto out_vblank;
+ /* initialise general modesetting */
+ drm_mode_config_init(dev);
+ drm_mode_create_scaling_mode_property(dev);
+ drm_mode_create_dithering_property(dev);
+ dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
+ dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1);
+ dev->mode_config.min_width = 0;
+ dev->mode_config.min_height = 0;
+ if (dev_priv->card_type < NV_10) {
+ dev->mode_config.max_width = 2048;
+ dev->mode_config.max_height = 2048;
+ } else
+ if (dev_priv->card_type < NV_50) {
+ dev->mode_config.max_width = 4096;
+ dev->mode_config.max_height = 4096;
+ } else {
+ dev->mode_config.max_width = 8192;
+ dev->mode_config.max_height = 8192;
+ }
- ret = nouveau_irq_init(dev);
+ ret = engine->display.create(dev);
if (ret)
- goto out_vblank;
+ goto out_irq;
- /* what about PVIDEO/PCRTC/PRAMDAC etc? */
+ nouveau_backlight_init(dev);
if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
ret = nouveau_fence_init(dev);
if (ret)
- goto out_irq;
+ goto out_disp;
- ret = nouveau_card_init_channel(dev);
+ ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
+ NvDmaFB, NvDmaTT);
if (ret)
goto out_fence;
+
+ mutex_unlock(&dev_priv->channel->mutex);
+ }
+
+ if (dev->mode_config.num_crtc) {
+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+ if (ret)
+ goto out_chan;
+
+ nouveau_fbcon_init(dev);
+ drm_kms_helper_poll_init(dev);
}
- nouveau_fbcon_init(dev);
- drm_kms_helper_poll_init(dev);
return 0;
+out_chan:
+ nouveau_channel_put_unlocked(&dev_priv->channel);
out_fence:
nouveau_fence_fini(dev);
+out_disp:
+ nouveau_backlight_exit(dev);
+ engine->display.destroy(dev);
out_irq:
nouveau_irq_fini(dev);
-out_vblank:
- drm_vblank_cleanup(dev);
- engine->display.destroy(dev);
out_fifo:
if (!dev_priv->noaccel)
engine->fifo.takedown(dev);
@@ -732,15 +809,20 @@ static void nouveau_card_takedown(struct drm_device *dev)
struct nouveau_engine *engine = &dev_priv->engine;
int e;
- drm_kms_helper_poll_fini(dev);
- nouveau_fbcon_fini(dev);
+ if (dev->mode_config.num_crtc) {
+ drm_kms_helper_poll_fini(dev);
+ nouveau_fbcon_fini(dev);
+ drm_vblank_cleanup(dev);
+ }
if (dev_priv->channel) {
nouveau_channel_put_unlocked(&dev_priv->channel);
nouveau_fence_fini(dev);
}
+ nouveau_backlight_exit(dev);
engine->display.destroy(dev);
+ drm_mode_config_cleanup(dev);
if (!dev_priv->noaccel) {
engine->fifo.takedown(dev);
@@ -774,7 +856,6 @@ static void nouveau_card_takedown(struct drm_device *dev)
engine->vram.takedown(dev);
nouveau_irq_fini(dev);
- drm_vblank_cleanup(dev);
nouveau_pm_fini(dev);
nouveau_bios_takedown(dev);
@@ -907,7 +988,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev)
int nouveau_load(struct drm_device *dev, unsigned long flags)
{
struct drm_nouveau_private *dev_priv;
- uint32_t reg0;
+ uint32_t reg0, strap;
resource_size_t mmio_start_offs;
int ret;
@@ -951,13 +1032,11 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
/* Time to determine the card architecture */
reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);
- dev_priv->stepping = 0; /* XXX: add stepping for pre-NV10? */
/* We're dealing with >=NV10 */
if ((reg0 & 0x0f000000) > 0) {
/* Bit 27-20 contain the architecture in hex */
dev_priv->chipset = (reg0 & 0xff00000) >> 20;
- dev_priv->stepping = (reg0 & 0xff);
/* NV04 or NV05 */
} else if ((reg0 & 0xff00fff0) == 0x20004000) {
if (reg0 & 0x00f00000)
@@ -987,6 +1066,9 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
case 0xc0:
dev_priv->card_type = NV_C0;
break;
+ case 0xd0:
+ dev_priv->card_type = NV_D0;
+ break;
default:
NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0);
ret = -EINVAL;
@@ -996,6 +1078,23 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
dev_priv->card_type, reg0);
+ /* determine frequency of timing crystal */
+ strap = nv_rd32(dev, 0x101000);
+ if ( dev_priv->chipset < 0x17 ||
+ (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25))
+ strap &= 0x00000040;
+ else
+ strap &= 0x00400040;
+
+ switch (strap) {
+ case 0x00000000: dev_priv->crystal = 13500; break;
+ case 0x00000040: dev_priv->crystal = 14318; break;
+ case 0x00400000: dev_priv->crystal = 27000; break;
+ case 0x00400040: dev_priv->crystal = 25000; break;
+ }
+
+ NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal);
+
/* Determine whether we'll attempt acceleration or not, some
* cards are disabled by default here due to them being known
* non-functional, or never been tested due to lack of hw.
@@ -1030,7 +1129,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
ioremap(pci_resource_start(dev->pdev, ramin_bar),
dev_priv->ramin_size);
if (!dev_priv->ramin) {
- NV_ERROR(dev, "Failed to PRAMIN BAR");
+ NV_ERROR(dev, "Failed to map PRAMIN BAR\n");
ret = -ENOMEM;
goto err_mmio;
}
@@ -1130,7 +1229,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
getparam->value = 1;
break;
case NOUVEAU_GETPARAM_HAS_PAGEFLIP:
- getparam->value = 1;
+ getparam->value = dev_priv->card_type < NV_D0;
break;
case NOUVEAU_GETPARAM_GRAPH_UNITS:
/* NV40 and NV50 versions are quite different, but register
@@ -1198,6 +1297,23 @@ nouveau_wait_ne(struct drm_device *dev, uint64_t timeout,
return false;
}
+/* Wait until cond(data) == true, up until timeout has hit */
+bool
+nouveau_wait_cb(struct drm_device *dev, u64 timeout,
+ bool (*cond)(void *), void *data)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+ u64 start = ptimer->read(dev);
+
+ do {
+ if (cond(data) == true)
+ return true;
+ } while (ptimer->read(dev) - start < timeout);
+
+ return false;
+}
+
/* Waits for PGRAPH to go completely idle */
bool nouveau_wait_for_idle(struct drm_device *dev)
{
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c
index 244fd38fdb84..ef0832b29ad2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.c
@@ -172,9 +172,9 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde)
vm->map_pgt(vpgd->obj, pde, vpgt->obj);
}
- mutex_unlock(&vm->mm->mutex);
+ mutex_unlock(&vm->mm.mutex);
nouveau_gpuobj_ref(NULL, &pgt);
- mutex_lock(&vm->mm->mutex);
+ mutex_lock(&vm->mm.mutex);
}
}
@@ -191,18 +191,18 @@ nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type)
pgt_size = (1 << (vm->pgt_bits + 12)) >> type;
pgt_size *= 8;
- mutex_unlock(&vm->mm->mutex);
+ mutex_unlock(&vm->mm.mutex);
ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000,
NVOBJ_FLAG_ZERO_ALLOC, &pgt);
- mutex_lock(&vm->mm->mutex);
+ mutex_lock(&vm->mm.mutex);
if (unlikely(ret))
return ret;
/* someone beat us to filling the PDE while we didn't have the lock */
if (unlikely(vpgt->refcount[big]++)) {
- mutex_unlock(&vm->mm->mutex);
+ mutex_unlock(&vm->mm.mutex);
nouveau_gpuobj_ref(NULL, &pgt);
- mutex_lock(&vm->mm->mutex);
+ mutex_lock(&vm->mm.mutex);
return 0;
}
@@ -223,10 +223,10 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift,
u32 fpde, lpde, pde;
int ret;
- mutex_lock(&vm->mm->mutex);
- ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node);
+ mutex_lock(&vm->mm.mutex);
+ ret = nouveau_mm_get(&vm->mm, page_shift, msize, 0, align, &vma->node);
if (unlikely(ret != 0)) {
- mutex_unlock(&vm->mm->mutex);
+ mutex_unlock(&vm->mm.mutex);
return ret;
}
@@ -245,13 +245,13 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift,
if (ret) {
if (pde != fpde)
nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1);
- nouveau_mm_put(vm->mm, vma->node);
- mutex_unlock(&vm->mm->mutex);
+ nouveau_mm_put(&vm->mm, vma->node);
+ mutex_unlock(&vm->mm.mutex);
vma->node = NULL;
return ret;
}
}
- mutex_unlock(&vm->mm->mutex);
+ mutex_unlock(&vm->mm.mutex);
vma->vm = vm;
vma->offset = (u64)vma->node->offset << 12;
@@ -270,11 +270,11 @@ nouveau_vm_put(struct nouveau_vma *vma)
fpde = (vma->node->offset >> vm->pgt_bits);
lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits;
- mutex_lock(&vm->mm->mutex);
+ mutex_lock(&vm->mm.mutex);
nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde);
- nouveau_mm_put(vm->mm, vma->node);
+ nouveau_mm_put(&vm->mm, vma->node);
vma->node = NULL;
- mutex_unlock(&vm->mm->mutex);
+ mutex_unlock(&vm->mm.mutex);
}
int
@@ -306,7 +306,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset,
block = length;
} else
- if (dev_priv->card_type == NV_C0) {
+ if (dev_priv->card_type >= NV_C0) {
vm->map_pgt = nvc0_vm_map_pgt;
vm->map = nvc0_vm_map;
vm->map_sg = nvc0_vm_map_sg;
@@ -360,11 +360,11 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
nouveau_gpuobj_ref(pgd, &vpgd->obj);
- mutex_lock(&vm->mm->mutex);
+ mutex_lock(&vm->mm.mutex);
for (i = vm->fpde; i <= vm->lpde; i++)
vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj);
list_add(&vpgd->head, &vm->pgd_list);
- mutex_unlock(&vm->mm->mutex);
+ mutex_unlock(&vm->mm.mutex);
return 0;
}
@@ -377,7 +377,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
if (!mpgd)
return;
- mutex_lock(&vm->mm->mutex);
+ mutex_lock(&vm->mm.mutex);
list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
if (vpgd->obj == mpgd) {
pgd = vpgd->obj;
@@ -386,7 +386,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
break;
}
}
- mutex_unlock(&vm->mm->mutex);
+ mutex_unlock(&vm->mm.mutex);
nouveau_gpuobj_ref(NULL, &pgd);
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h
index 579ca8cc223c..6ce995f7797e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h
@@ -51,7 +51,7 @@ struct nouveau_vma {
struct nouveau_vm {
struct drm_device *dev;
- struct nouveau_mm *mm;
+ struct nouveau_mm mm;
int refcount;
struct list_head pgd_list;
diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c
index 75e872741d92..86d03e15735d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_volt.c
+++ b/drivers/gpu/drm/nouveau/nouveau_volt.c
@@ -27,7 +27,7 @@
#include "nouveau_drv.h"
#include "nouveau_pm.h"
-static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a };
+static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 };
static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]);
int
@@ -170,6 +170,13 @@ nouveau_volt_init(struct drm_device *dev)
*/
vidshift = 2;
break;
+ case 0x40:
+ headerlen = volt[1];
+ recordlen = volt[2];
+ entries = volt[3]; /* not a clue what the entries are for.. */
+ vidmask = volt[11]; /* guess.. */
+ vidshift = 0;
+ break;
default:
NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]);
return;
@@ -197,16 +204,37 @@ nouveau_volt_init(struct drm_device *dev)
}
/* parse vbios entries into common format */
- voltage->level = kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL);
- if (!voltage->level)
- return;
+ voltage->version = volt[0];
+ if (voltage->version < 0x40) {
+ voltage->nr_level = entries;
+ voltage->level =
+ kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL);
+ if (!voltage->level)
+ return;
- entry = volt + headerlen;
- for (i = 0; i < entries; i++, entry += recordlen) {
- voltage->level[i].voltage = entry[0];
- voltage->level[i].vid = entry[1] >> vidshift;
+ entry = volt + headerlen;
+ for (i = 0; i < entries; i++, entry += recordlen) {
+ voltage->level[i].voltage = entry[0] * 10000;
+ voltage->level[i].vid = entry[1] >> vidshift;
+ }
+ } else {
+ u32 volt_uv = ROM32(volt[4]);
+ s16 step_uv = ROM16(volt[8]);
+ u8 vid;
+
+ voltage->nr_level = voltage->vid_mask + 1;
+ voltage->level = kcalloc(voltage->nr_level,
+ sizeof(*voltage->level), GFP_KERNEL);
+ if (!voltage->level)
+ return;
+
+ for (vid = 0; vid <= voltage->vid_mask; vid++) {
+ voltage->level[vid].voltage = volt_uv;
+ voltage->level[vid].vid = vid;
+ volt_uv += step_uv;
+ }
}
- voltage->nr_level = entries;
+
voltage->supported = true;
}
diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c
index 1715e1464b7d..6bd8518d7b2e 100644
--- a/drivers/gpu/drm/nouveau/nv04_display.c
+++ b/drivers/gpu/drm/nouveau/nv04_display.c
@@ -126,27 +126,6 @@ nv04_display_create(struct drm_device *dev)
nouveau_hw_save_vga_fonts(dev, 1);
- drm_mode_config_init(dev);
- drm_mode_create_scaling_mode_property(dev);
- drm_mode_create_dithering_property(dev);
-
- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
-
- dev->mode_config.min_width = 0;
- dev->mode_config.min_height = 0;
- switch (dev_priv->card_type) {
- case NV_04:
- dev->mode_config.max_width = 2048;
- dev->mode_config.max_height = 2048;
- break;
- default:
- dev->mode_config.max_width = 4096;
- dev->mode_config.max_height = 4096;
- break;
- }
-
- dev->mode_config.fb_base = dev_priv->fb_phys;
-
nv04_crtc_create(dev, 0);
if (nv_two_heads(dev))
nv04_crtc_create(dev, 1);
@@ -235,8 +214,6 @@ nv04_display_destroy(struct drm_device *dev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
crtc->funcs->restore(crtc);
- drm_mode_config_cleanup(dev);
-
nouveau_hw_save_vga_fonts(dev, 0);
}
diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c
index eb1c70dd82ed..9ae92a87b8cc 100644
--- a/drivers/gpu/drm/nouveau/nv04_pm.c
+++ b/drivers/gpu/drm/nouveau/nv04_pm.c
@@ -68,6 +68,7 @@ void
nv04_pm_clock_set(struct drm_device *dev, void *pre_state)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
struct nv04_pm_state *state = pre_state;
u32 reg = state->pll.reg;
@@ -85,6 +86,9 @@ nv04_pm_clock_set(struct drm_device *dev, void *pre_state)
nv_mask(dev, 0x1002c0, 0, 1 << 8);
}
+ if (reg == NV_PRAMDAC_NVPLL_COEFF)
+ ptimer->init(dev);
+
kfree(state);
}
diff --git a/drivers/gpu/drm/nouveau/nv04_timer.c b/drivers/gpu/drm/nouveau/nv04_timer.c
index 1d09ddd57399..263301b809dd 100644
--- a/drivers/gpu/drm/nouveau/nv04_timer.c
+++ b/drivers/gpu/drm/nouveau/nv04_timer.c
@@ -6,43 +6,75 @@
int
nv04_timer_init(struct drm_device *dev)
{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ u32 m, n, d;
+
nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000);
nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF);
- /* Just use the pre-existing values when possible for now; these regs
- * are not written in nv (driver writer missed a /4 on the address), and
- * writing 8 and 3 to the correct regs breaks the timings on the LVDS
- * hardware sequencing microcode.
- * A correct solution (involving calculations with the GPU PLL) can
- * be done when kernel modesetting lands
- */
- if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) ||
- !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) {
- nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008);
- nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003);
+ /* aim for 31.25MHz, which gives us nanosecond timestamps */
+ d = 1000000 / 32;
+
+ /* determine base clock for timer source */
+ if (dev_priv->chipset < 0x40) {
+ n = dev_priv->engine.pm.clock_get(dev, PLL_CORE);
+ } else
+ if (dev_priv->chipset == 0x40) {
+ /*XXX: figure this out */
+ n = 0;
+ } else {
+ n = dev_priv->crystal;
+ m = 1;
+ while (n < (d * 2)) {
+ n += (n / m);
+ m++;
+ }
+
+ nv_wr32(dev, 0x009220, m - 1);
+ }
+
+ if (!n) {
+ NV_WARN(dev, "PTIMER: unknown input clock freq\n");
+ if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) ||
+ !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) {
+ nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1);
+ nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1);
+ }
+ return 0;
+ }
+
+ /* reduce ratio to acceptable values */
+ while (((n % 5) == 0) && ((d % 5) == 0)) {
+ n /= 5;
+ d /= 5;
}
+ while (((n % 2) == 0) && ((d % 2) == 0)) {
+ n /= 2;
+ d /= 2;
+ }
+
+ while (n > 0xffff || d > 0xffff) {
+ n >>= 1;
+ d >>= 1;
+ }
+
+ nv_wr32(dev, NV04_PTIMER_NUMERATOR, n);
+ nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d);
return 0;
}
-uint64_t
+u64
nv04_timer_read(struct drm_device *dev)
{
- uint32_t low;
- /* From kmmio dumps on nv28 this looks like how the blob does this.
- * It reads the high dword twice, before and after.
- * The only explanation seems to be that the 64-bit timer counter
- * advances between high and low dword reads and may corrupt the
- * result. Not confirmed.
- */
- uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1);
- uint32_t high1;
+ u32 hi, lo;
+
do {
- high1 = high2;
- low = nv_rd32(dev, NV04_PTIMER_TIME_0);
- high2 = nv_rd32(dev, NV04_PTIMER_TIME_1);
- } while (high1 != high2);
- return (((uint64_t)high2) << 32) | (uint64_t)low;
+ hi = nv_rd32(dev, NV04_PTIMER_TIME_1);
+ lo = nv_rd32(dev, NV04_PTIMER_TIME_0);
+ } while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1));
+
+ return ((u64)hi << 32 | lo);
}
void
diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv31_mpeg.c
index ad03a0e1fc7d..6f06a0713f00 100644
--- a/drivers/gpu/drm/nouveau/nv40_mpeg.c
+++ b/drivers/gpu/drm/nouveau/nv31_mpeg.c
@@ -26,10 +26,32 @@
#include "nouveau_drv.h"
#include "nouveau_ramht.h"
-struct nv40_mpeg_engine {
+struct nv31_mpeg_engine {
struct nouveau_exec_engine base;
+ atomic_t refcount;
};
+
+static int
+nv31_mpeg_context_new(struct nouveau_channel *chan, int engine)
+{
+ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine);
+
+ if (!atomic_add_unless(&pmpeg->refcount, 1, 1))
+ return -EBUSY;
+
+ chan->engctx[engine] = (void *)0xdeadcafe;
+ return 0;
+}
+
+static void
+nv31_mpeg_context_del(struct nouveau_channel *chan, int engine)
+{
+ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine);
+ atomic_dec(&pmpeg->refcount);
+ chan->engctx[engine] = NULL;
+}
+
static int
nv40_mpeg_context_new(struct nouveau_channel *chan, int engine)
{
@@ -81,7 +103,7 @@ nv40_mpeg_context_del(struct nouveau_channel *chan, int engine)
}
static int
-nv40_mpeg_object_new(struct nouveau_channel *chan, int engine,
+nv31_mpeg_object_new(struct nouveau_channel *chan, int engine,
u32 handle, u16 class)
{
struct drm_device *dev = chan->dev;
@@ -103,10 +125,10 @@ nv40_mpeg_object_new(struct nouveau_channel *chan, int engine,
}
static int
-nv40_mpeg_init(struct drm_device *dev, int engine)
+nv31_mpeg_init(struct drm_device *dev, int engine)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
+ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine);
int i;
/* VPE init */
@@ -121,7 +143,7 @@ nv40_mpeg_init(struct drm_device *dev, int engine)
/* PMPEG init */
nv_wr32(dev, 0x00b32c, 0x00000000);
nv_wr32(dev, 0x00b314, 0x00000100);
- nv_wr32(dev, 0x00b220, 0x00000044);
+ nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031);
nv_wr32(dev, 0x00b300, 0x02001ec1);
nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
@@ -137,7 +159,7 @@ nv40_mpeg_init(struct drm_device *dev, int engine)
}
static int
-nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
+nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
{
/*XXX: context save? */
nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
@@ -146,7 +168,7 @@ nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
}
static int
-nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
+nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
{
struct drm_device *dev = chan->dev;
u32 inst = data << 4;
@@ -184,13 +206,17 @@ nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
}
static int
-nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst)
+nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *ctx;
unsigned long flags;
int i;
+ /* hardcode drm channel id on nv3x, so swmthd lookup works */
+ if (dev_priv->card_type < NV_40)
+ return 0;
+
spin_lock_irqsave(&dev_priv->channels.lock, flags);
for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
if (!dev_priv->channels.ptr[i])
@@ -205,7 +231,7 @@ nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst)
}
static void
-nv40_vpe_set_tile_region(struct drm_device *dev, int i)
+nv31_vpe_set_tile_region(struct drm_device *dev, int i)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
@@ -216,10 +242,10 @@ nv40_vpe_set_tile_region(struct drm_device *dev, int i)
}
static void
-nv40_mpeg_isr(struct drm_device *dev)
+nv31_mpeg_isr(struct drm_device *dev)
{
u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4;
- u32 chid = nv40_mpeg_isr_chid(dev, inst);
+ u32 chid = nv31_mpeg_isr_chid(dev, inst);
u32 stat = nv_rd32(dev, 0x00b100);
u32 type = nv_rd32(dev, 0x00b230);
u32 mthd = nv_rd32(dev, 0x00b234);
@@ -249,10 +275,10 @@ nv40_mpeg_isr(struct drm_device *dev)
}
static void
-nv40_vpe_isr(struct drm_device *dev)
+nv31_vpe_isr(struct drm_device *dev)
{
if (nv_rd32(dev, 0x00b100))
- nv40_mpeg_isr(dev);
+ nv31_mpeg_isr(dev);
if (nv_rd32(dev, 0x00b800)) {
u32 stat = nv_rd32(dev, 0x00b800);
@@ -262,9 +288,9 @@ nv40_vpe_isr(struct drm_device *dev)
}
static void
-nv40_mpeg_destroy(struct drm_device *dev, int engine)
+nv31_mpeg_destroy(struct drm_device *dev, int engine)
{
- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
+ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine);
nouveau_irq_unregister(dev, 0);
@@ -273,34 +299,41 @@ nv40_mpeg_destroy(struct drm_device *dev, int engine)
}
int
-nv40_mpeg_create(struct drm_device *dev)
+nv31_mpeg_create(struct drm_device *dev)
{
- struct nv40_mpeg_engine *pmpeg;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nv31_mpeg_engine *pmpeg;
pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
if (!pmpeg)
return -ENOMEM;
-
- pmpeg->base.destroy = nv40_mpeg_destroy;
- pmpeg->base.init = nv40_mpeg_init;
- pmpeg->base.fini = nv40_mpeg_fini;
- pmpeg->base.context_new = nv40_mpeg_context_new;
- pmpeg->base.context_del = nv40_mpeg_context_del;
- pmpeg->base.object_new = nv40_mpeg_object_new;
+ atomic_set(&pmpeg->refcount, 0);
+
+ pmpeg->base.destroy = nv31_mpeg_destroy;
+ pmpeg->base.init = nv31_mpeg_init;
+ pmpeg->base.fini = nv31_mpeg_fini;
+ if (dev_priv->card_type < NV_40) {
+ pmpeg->base.context_new = nv31_mpeg_context_new;
+ pmpeg->base.context_del = nv31_mpeg_context_del;
+ } else {
+ pmpeg->base.context_new = nv40_mpeg_context_new;
+ pmpeg->base.context_del = nv40_mpeg_context_del;
+ }
+ pmpeg->base.object_new = nv31_mpeg_object_new;
/* ISR vector, PMC_ENABLE bit, and TILE regs are shared between
* all VPE engines, for this driver's purposes the PMPEG engine
* will be treated as the "master" and handle the global VPE
* bits too
*/
- pmpeg->base.set_tile_region = nv40_vpe_set_tile_region;
- nouveau_irq_register(dev, 0, nv40_vpe_isr);
+ pmpeg->base.set_tile_region = nv31_vpe_set_tile_region;
+ nouveau_irq_register(dev, 0, nv31_vpe_isr);
NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
NVOBJ_CLASS(dev, 0x3174, MPEG);
- NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma);
- NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma);
- NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma);
+ NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma);
+ NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma);
+ NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma);
#if 0
NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c
new file mode 100644
index 000000000000..bbc0b9c7e1f7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv40_pm.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_bios.h"
+#include "nouveau_pm.h"
+#include "nouveau_hw.h"
+
+#define min2(a,b) ((a) < (b) ? (a) : (b))
+
+static u32
+read_pll_1(struct drm_device *dev, u32 reg)
+{
+ u32 ctrl = nv_rd32(dev, reg + 0x00);
+ int P = (ctrl & 0x00070000) >> 16;
+ int N = (ctrl & 0x0000ff00) >> 8;
+ int M = (ctrl & 0x000000ff) >> 0;
+ u32 ref = 27000, clk = 0;
+
+ if (ctrl & 0x80000000)
+ clk = ref * N / M;
+
+ return clk >> P;
+}
+
+static u32
+read_pll_2(struct drm_device *dev, u32 reg)
+{
+ u32 ctrl = nv_rd32(dev, reg + 0x00);
+ u32 coef = nv_rd32(dev, reg + 0x04);
+ int N2 = (coef & 0xff000000) >> 24;
+ int M2 = (coef & 0x00ff0000) >> 16;
+ int N1 = (coef & 0x0000ff00) >> 8;
+ int M1 = (coef & 0x000000ff) >> 0;
+ int P = (ctrl & 0x00070000) >> 16;
+ u32 ref = 27000, clk = 0;
+
+ if (ctrl & 0x80000000)
+ clk = ref * N1 / M1;
+
+ if (!(ctrl & 0x00000100)) {
+ if (ctrl & 0x40000000)
+ clk = clk * N2 / M2;
+ }
+
+ return clk >> P;
+}
+
+static u32
+read_clk(struct drm_device *dev, u32 src)
+{
+ switch (src) {
+ case 3:
+ return read_pll_2(dev, 0x004000);
+ case 2:
+ return read_pll_1(dev, 0x004008);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int
+nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+ u32 ctrl = nv_rd32(dev, 0x00c040);
+
+ perflvl->core = read_clk(dev, (ctrl & 0x00000003) >> 0);
+ perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4);
+ perflvl->memory = read_pll_2(dev, 0x4020);
+ return 0;
+}
+
+struct nv40_pm_state {
+ u32 ctrl;
+ u32 npll_ctrl;
+ u32 npll_coef;
+ u32 spll;
+ u32 mpll_ctrl;
+ u32 mpll_coef;
+};
+
+static int
+nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll,
+ u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P)
+{
+ struct nouveau_pll_vals coef;
+ int ret;
+
+ ret = get_pll_limits(dev, reg, pll);
+ if (ret)
+ return ret;
+
+ if (clk < pll->vco1.maxfreq)
+ pll->vco2.maxfreq = 0;
+
+ ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef);
+ if (ret == 0)
+ return -ERANGE;
+
+ *N1 = coef.N1;
+ *M1 = coef.M1;
+ if (N2 && M2) {
+ if (pll->vco2.maxfreq) {
+ *N2 = coef.N2;
+ *M2 = coef.M2;
+ } else {
+ *N2 = 1;
+ *M2 = 1;
+ }
+ }
+ *log2P = coef.log2P;
+ return 0;
+}
+
+void *
+nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+ struct nv40_pm_state *info;
+ struct pll_lims pll;
+ int N1, N2, M1, M2, log2P;
+ int ret;
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+
+ /* core/geometric clock */
+ ret = nv40_calc_pll(dev, 0x004000, &pll, perflvl->core,
+ &N1, &M1, &N2, &M2, &log2P);
+ if (ret < 0)
+ goto out;
+
+ if (N2 == M2) {
+ info->npll_ctrl = 0x80000100 | (log2P << 16);
+ info->npll_coef = (N1 << 8) | M1;
+ } else {
+ info->npll_ctrl = 0xc0000000 | (log2P << 16);
+ info->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
+ }
+
+ /* use the second PLL for shader/rop clock, if it differs from core */
+ if (perflvl->shader && perflvl->shader != perflvl->core) {
+ ret = nv40_calc_pll(dev, 0x004008, &pll, perflvl->shader,
+ &N1, &M1, NULL, NULL, &log2P);
+ if (ret < 0)
+ goto out;
+
+ info->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1;
+ info->ctrl = 0x00000223;
+ } else {
+ info->spll = 0x00000000;
+ info->ctrl = 0x00000333;
+ }
+
+ /* memory clock */
+ ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory,
+ &N1, &M1, &N2, &M2, &log2P);
+ if (ret < 0)
+ goto out;
+
+ info->mpll_ctrl = 0x80000000 | (log2P << 16);
+ info->mpll_ctrl |= min2(pll.log2p_bias + log2P, pll.max_log2p) << 20;
+ if (N2 == M2) {
+ info->mpll_ctrl |= 0x00000100;
+ info->mpll_coef = (N1 << 8) | M1;
+ } else {
+ info->mpll_ctrl |= 0x40000000;
+ info->mpll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
+ }
+
+out:
+ if (ret < 0) {
+ kfree(info);
+ info = ERR_PTR(ret);
+ }
+ return info;
+}
+
+static bool
+nv40_pm_gr_idle(void *data)
+{
+ struct drm_device *dev = data;
+
+ if ((nv_rd32(dev, 0x400760) & 0x000000f0) >> 4 !=
+ (nv_rd32(dev, 0x400760) & 0x0000000f))
+ return false;
+
+ if (nv_rd32(dev, 0x400700))
+ return false;
+
+ return true;
+}
+
+void
+nv40_pm_clocks_set(struct drm_device *dev, void *pre_state)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nv40_pm_state *info = pre_state;
+ unsigned long flags;
+ struct bit_entry M;
+ u32 crtc_mask = 0;
+ u8 sr1[2];
+ int i;
+
+ /* determine which CRTCs are active, fetch VGA_SR1 for each */
+ for (i = 0; i < 2; i++) {
+ u32 vbl = nv_rd32(dev, 0x600808 + (i * 0x2000));
+ u32 cnt = 0;
+ do {
+ if (vbl != nv_rd32(dev, 0x600808 + (i * 0x2000))) {
+ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
+ sr1[i] = nv_rd08(dev, 0x0c03c5 + (i * 0x2000));
+ if (!(sr1[i] & 0x20))
+ crtc_mask |= (1 << i);
+ break;
+ }
+ udelay(1);
+ } while (cnt++ < 32);
+ }
+
+ /* halt and idle engines */
+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+ nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
+ if (!nv_wait(dev, 0x002500, 0x00000010, 0x00000000))
+ goto resume;
+ nv_mask(dev, 0x003220, 0x00000001, 0x00000000);
+ if (!nv_wait(dev, 0x003220, 0x00000010, 0x00000000))
+ goto resume;
+ nv_mask(dev, 0x003200, 0x00000001, 0x00000000);
+ nv04_fifo_cache_pull(dev, false);
+
+ if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev))
+ goto resume;
+
+ /* set engine clocks */
+ nv_mask(dev, 0x00c040, 0x00000333, 0x00000000);
+ nv_wr32(dev, 0x004004, info->npll_coef);
+ nv_mask(dev, 0x004000, 0xc0070100, info->npll_ctrl);
+ nv_mask(dev, 0x004008, 0xc007ffff, info->spll);
+ mdelay(5);
+ nv_mask(dev, 0x00c040, 0x00000333, info->ctrl);
+
+ /* wait for vblank start on active crtcs, disable memory access */
+ for (i = 0; i < 2; i++) {
+ if (!(crtc_mask & (1 << i)))
+ continue;
+ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000);
+ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000);
+ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
+ nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20);
+ }
+
+ /* prepare ram for reclocking */
+ nv_wr32(dev, 0x1002d4, 0x00000001); /* precharge */
+ nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */
+ nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */
+ nv_mask(dev, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */
+ nv_wr32(dev, 0x1002dc, 0x00000001); /* enable self-refresh */
+
+ /* change the PLL of each memory partition */
+ nv_mask(dev, 0x00c040, 0x0000c000, 0x00000000);
+ switch (dev_priv->chipset) {
+ case 0x40:
+ case 0x45:
+ case 0x41:
+ case 0x42:
+ case 0x47:
+ nv_mask(dev, 0x004044, 0xc0771100, info->mpll_ctrl);
+ nv_mask(dev, 0x00402c, 0xc0771100, info->mpll_ctrl);
+ nv_wr32(dev, 0x004048, info->mpll_coef);
+ nv_wr32(dev, 0x004030, info->mpll_coef);
+ case 0x43:
+ case 0x49:
+ case 0x4b:
+ nv_mask(dev, 0x004038, 0xc0771100, info->mpll_ctrl);
+ nv_wr32(dev, 0x00403c, info->mpll_coef);
+ default:
+ nv_mask(dev, 0x004020, 0xc0771100, info->mpll_ctrl);
+ nv_wr32(dev, 0x004024, info->mpll_coef);
+ break;
+ }
+ udelay(100);
+ nv_mask(dev, 0x00c040, 0x0000c000, 0x0000c000);
+
+ /* re-enable normal operation of memory controller */
+ nv_wr32(dev, 0x1002dc, 0x00000000);
+ nv_mask(dev, 0x100210, 0x80000000, 0x80000000);
+ udelay(100);
+
+ /* execute memory reset script from vbios */
+ if (!bit_table(dev, 'M', &M))
+ nouveau_bios_init_exec(dev, ROM16(M.data[0]));
+
+ /* make sure we're in vblank (hopefully the same one as before), and
+ * then re-enable crtc memory access
+ */
+ for (i = 0; i < 2; i++) {
+ if (!(crtc_mask & (1 << i)))
+ continue;
+ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000);
+ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
+ nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i]);
+ }
+
+ /* resume engines */
+resume:
+ nv_wr32(dev, 0x003250, 0x00000001);
+ nv_mask(dev, 0x003220, 0x00000001, 0x00000001);
+ nv_wr32(dev, 0x003200, 0x00000001);
+ nv_wr32(dev, 0x002500, 0x00000001);
+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+ kfree(info);
+}
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index 5d989073ba6e..882080e0b4f5 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -329,8 +329,6 @@ nv50_crtc_destroy(struct drm_crtc *crtc)
drm_crtc_cleanup(&nv_crtc->base);
- nv50_cursor_fini(nv_crtc);
-
nouveau_bo_unmap(nv_crtc->lut.nvbo);
nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c
index 9752c35bb84b..adfc9b607a50 100644
--- a/drivers/gpu/drm/nouveau/nv50_cursor.c
+++ b/drivers/gpu/drm/nouveau/nv50_cursor.c
@@ -137,21 +137,3 @@ nv50_cursor_init(struct nouveau_crtc *nv_crtc)
nv_crtc->cursor.show = nv50_cursor_show;
return 0;
}
-
-void
-nv50_cursor_fini(struct nouveau_crtc *nv_crtc)
-{
- struct drm_device *dev = nv_crtc->base.dev;
- int idx = nv_crtc->index;
-
- NV_DEBUG_KMS(dev, "\n");
-
- nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0);
- if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx),
- NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) {
- NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n");
- NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n",
- nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx)));
- }
-}
-
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index db1a5f4b711d..d23ca00e7d62 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -247,6 +247,16 @@ static int nv50_display_disable(struct drm_device *dev)
}
}
+ for (i = 0; i < 2; i++) {
+ nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0);
+ if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i),
+ NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) {
+ NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n");
+ NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n",
+ nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i)));
+ }
+ }
+
nv50_evo_fini(dev);
for (i = 0; i < 3; i++) {
@@ -286,23 +296,6 @@ int nv50_display_create(struct drm_device *dev)
return -ENOMEM;
dev_priv->engine.display.priv = priv;
- /* init basic kernel modesetting */
- drm_mode_config_init(dev);
-
- /* Initialise some optional connector properties. */
- drm_mode_create_scaling_mode_property(dev);
- drm_mode_create_dithering_property(dev);
-
- dev->mode_config.min_width = 0;
- dev->mode_config.min_height = 0;
-
- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
-
- dev->mode_config.max_width = 8192;
- dev->mode_config.max_height = 8192;
-
- dev->mode_config.fb_base = dev_priv->fb_phys;
-
/* Create CRTC objects */
for (i = 0; i < 2; i++)
nv50_crtc_create(dev, i);
@@ -364,8 +357,6 @@ nv50_display_destroy(struct drm_device *dev)
NV_DEBUG_KMS(dev, "\n");
- drm_mode_config_cleanup(dev);
-
nv50_display_disable(dev);
nouveau_irq_unregister(dev, 26);
kfree(disp);
@@ -698,7 +689,7 @@ nv50_display_unk10_handler(struct drm_device *dev)
struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i];
if (dcb->type == type && (dcb->or & (1 << or))) {
- nouveau_bios_run_display_table(dev, dcb, 0, -1);
+ nouveau_bios_run_display_table(dev, 0, -1, dcb, -1);
disp->irq.dcb = dcb;
goto ack;
}
@@ -711,37 +702,6 @@ ack:
}
static void
-nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb)
-{
- int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1);
- struct drm_encoder *encoder;
- uint32_t tmp, unk0 = 0, unk1 = 0;
-
- if (dcb->type != OUTPUT_DP)
- return;
-
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-
- if (nv_encoder->dcb == dcb) {
- unk0 = nv_encoder->dp.unk0;
- unk1 = nv_encoder->dp.unk1;
- break;
- }
- }
-
- if (unk0 || unk1) {
- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
- tmp &= 0xfffffe03;
- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp | unk0);
-
- tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link));
- tmp &= 0xfef080c0;
- nv_wr32(dev, NV50_SOR_DP_UNK128(or, link), tmp | unk1);
- }
-}
-
-static void
nv50_display_unk20_handler(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -753,7 +713,7 @@ nv50_display_unk20_handler(struct drm_device *dev)
NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
dcb = disp->irq.dcb;
if (dcb) {
- nouveau_bios_run_display_table(dev, dcb, 0, -2);
+ nouveau_bios_run_display_table(dev, 0, -2, dcb, -1);
disp->irq.dcb = NULL;
}
@@ -837,9 +797,15 @@ nv50_display_unk20_handler(struct drm_device *dev)
}
script = nv50_display_script_select(dev, dcb, mc, pclk);
- nouveau_bios_run_display_table(dev, dcb, script, pclk);
+ nouveau_bios_run_display_table(dev, script, pclk, dcb, -1);
- nv50_display_unk20_dp_hack(dev, dcb);
+ if (type == OUTPUT_DP) {
+ int link = !(dcb->dpconf.sor.link & 1);
+ if ((mc & 0x000f0000) == 0x00020000)
+ nouveau_dp_tu_update(dev, or, link, pclk, 18);
+ else
+ nouveau_dp_tu_update(dev, or, link, pclk, 24);
+ }
if (dcb->type != OUTPUT_ANALOG) {
tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or));
@@ -904,7 +870,7 @@ nv50_display_unk40_handler(struct drm_device *dev)
if (!dcb)
goto ack;
- nouveau_bios_run_display_table(dev, dcb, script, -pclk);
+ nouveau_bios_run_display_table(dev, script, -pclk, dcb, -1);
nv50_display_unk40_dp_set_tmds(dev, dcb);
ack:
diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c
index d4f4206dad7e..793a5ccca121 100644
--- a/drivers/gpu/drm/nouveau/nv50_gpio.c
+++ b/drivers/gpu/drm/nouveau/nv50_gpio.c
@@ -98,6 +98,37 @@ nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
}
int
+nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
+{
+ struct dcb_gpio_entry *gpio;
+ u32 v;
+
+ gpio = nouveau_bios_gpio_entry(dev, tag);
+ if (!gpio)
+ return -ENOENT;
+
+ v = nv_rd32(dev, 0x00d610 + (gpio->line * 4));
+ v &= 0x00004000;
+ return (!!v == (gpio->state[1] & 1));
+}
+
+int
+nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
+{
+ struct dcb_gpio_entry *gpio;
+ u32 v;
+
+ gpio = nouveau_bios_gpio_entry(dev, tag);
+ if (!gpio)
+ return -ENOENT;
+
+ v = gpio->state[state] ^ 2;
+
+ nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12);
+ return 0;
+}
+
+int
nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag,
void (*handler)(void *, int), void *data)
{
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
index d43c46caa76e..8c979b31ff61 100644
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -120,70 +120,62 @@ nv50_graph_unload_context(struct drm_device *dev)
return 0;
}
-static void
-nv50_graph_init_reset(struct drm_device *dev)
-{
- uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
- NV_DEBUG(dev, "\n");
-
- nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e);
- nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | pmc_e);
-}
-
-static void
-nv50_graph_init_intr(struct drm_device *dev)
-{
- NV_DEBUG(dev, "\n");
-
- nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff);
- nv_wr32(dev, 0x400138, 0xffffffff);
- nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff);
-}
-
-static void
-nv50_graph_init_regs__nv(struct drm_device *dev)
+static int
+nv50_graph_init(struct drm_device *dev, int engine)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- uint32_t units = nv_rd32(dev, 0x1540);
+ struct nv50_graph_engine *pgraph = nv_engine(dev, engine);
+ u32 units = nv_rd32(dev, 0x001540);
int i;
NV_DEBUG(dev, "\n");
+ /* master reset */
+ nv_mask(dev, 0x000200, 0x00200100, 0x00000000);
+ nv_mask(dev, 0x000200, 0x00200100, 0x00200100);
+ nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
+
+ /* reset/enable traps and interrupts */
nv_wr32(dev, 0x400804, 0xc0000000);
nv_wr32(dev, 0x406800, 0xc0000000);
nv_wr32(dev, 0x400c04, 0xc0000000);
nv_wr32(dev, 0x401800, 0xc0000000);
nv_wr32(dev, 0x405018, 0xc0000000);
nv_wr32(dev, 0x402000, 0xc0000000);
-
for (i = 0; i < 16; i++) {
- if (units & 1 << i) {
- if (dev_priv->chipset < 0xa0) {
- nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000);
- nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000);
- nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000);
- } else {
- nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000);
- nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000);
- nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000);
- }
+ if (!(units & (1 << i)))
+ continue;
+
+ if (dev_priv->chipset < 0xa0) {
+ nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000);
+ nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000);
+ nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000);
+ } else {
+ nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000);
+ nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000);
+ nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000);
}
}
nv_wr32(dev, 0x400108, 0xffffffff);
-
- nv_wr32(dev, 0x400824, 0x00004000);
+ nv_wr32(dev, 0x400138, 0xffffffff);
+ nv_wr32(dev, 0x400100, 0xffffffff);
+ nv_wr32(dev, 0x40013c, 0xffffffff);
nv_wr32(dev, 0x400500, 0x00010001);
-}
-
-static void
-nv50_graph_init_zcull(struct drm_device *dev)
-{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- int i;
-
- NV_DEBUG(dev, "\n");
+ /* upload context program, initialise ctxctl defaults */
+ nv_wr32(dev, 0x400324, 0x00000000);
+ for (i = 0; i < pgraph->ctxprog_size; i++)
+ nv_wr32(dev, 0x400328, pgraph->ctxprog[i]);
+ nv_wr32(dev, 0x400824, 0x00000000);
+ nv_wr32(dev, 0x400828, 0x00000000);
+ nv_wr32(dev, 0x40082c, 0x00000000);
+ nv_wr32(dev, 0x400830, 0x00000000);
+ nv_wr32(dev, 0x400724, 0x00000000);
+ nv_wr32(dev, 0x40032c, 0x00000000);
+ nv_wr32(dev, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */
+
+ /* some unknown zcull magic */
switch (dev_priv->chipset & 0xf0) {
case 0x50:
case 0x80:
@@ -212,43 +204,7 @@ nv50_graph_init_zcull(struct drm_device *dev)
nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000);
nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000);
}
-}
-
-static int
-nv50_graph_init_ctxctl(struct drm_device *dev)
-{
- struct nv50_graph_engine *pgraph = nv_engine(dev, NVOBJ_ENGINE_GR);
- int i;
-
- NV_DEBUG(dev, "\n");
-
- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
- for (i = 0; i < pgraph->ctxprog_size; i++)
- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, pgraph->ctxprog[i]);
-
- nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
- nv_wr32(dev, 0x400320, 4);
- nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
- nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
- return 0;
-}
-
-static int
-nv50_graph_init(struct drm_device *dev, int engine)
-{
- int ret;
-
- NV_DEBUG(dev, "\n");
-
- nv50_graph_init_reset(dev);
- nv50_graph_init_regs__nv(dev);
- nv50_graph_init_zcull(dev);
-
- ret = nv50_graph_init_ctxctl(dev);
- if (ret)
- return ret;
- nv50_graph_init_intr(dev);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c
index de9abff12b90..d05c2c3b2444 100644
--- a/drivers/gpu/drm/nouveau/nv50_grctx.c
+++ b/drivers/gpu/drm/nouveau/nv50_grctx.c
@@ -40,6 +40,12 @@
#define CP_FLAG_UNK0B ((0 * 32) + 0xb)
#define CP_FLAG_UNK0B_CLEAR 0
#define CP_FLAG_UNK0B_SET 1
+#define CP_FLAG_XFER_SWITCH ((0 * 32) + 0xe)
+#define CP_FLAG_XFER_SWITCH_DISABLE 0
+#define CP_FLAG_XFER_SWITCH_ENABLE 1
+#define CP_FLAG_STATE ((0 * 32) + 0x1c)
+#define CP_FLAG_STATE_STOPPED 0
+#define CP_FLAG_STATE_RUNNING 1
#define CP_FLAG_UNK1D ((0 * 32) + 0x1d)
#define CP_FLAG_UNK1D_CLEAR 0
#define CP_FLAG_UNK1D_SET 1
@@ -194,6 +200,9 @@ nv50_grctx_init(struct nouveau_grctx *ctx)
"the devs.\n");
return -ENOSYS;
}
+
+ cp_set (ctx, STATE, RUNNING);
+ cp_set (ctx, XFER_SWITCH, ENABLE);
/* decide whether we're loading/unloading the context */
cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save);
cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save);
@@ -260,6 +269,8 @@ nv50_grctx_init(struct nouveau_grctx *ctx)
cp_name(ctx, cp_exit);
cp_set (ctx, USER_SAVE, NOT_PENDING);
cp_set (ctx, USER_LOAD, NOT_PENDING);
+ cp_set (ctx, XFER_SWITCH, DISABLE);
+ cp_set (ctx, STATE, STOPPED);
cp_out (ctx, CP_END);
ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index 8a2810011bda..3d5a86b98282 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -115,15 +115,15 @@ nv50_pm_clock_set(struct drm_device *dev, void *pre_state)
BIT_M.version == 1 && BIT_M.length >= 0x0b) {
script = ROM16(BIT_M.data[0x05]);
if (script)
- nouveau_bios_run_init_table(dev, script, NULL);
+ nouveau_bios_run_init_table(dev, script, NULL, -1);
script = ROM16(BIT_M.data[0x07]);
if (script)
- nouveau_bios_run_init_table(dev, script, NULL);
+ nouveau_bios_run_init_table(dev, script, NULL, -1);
script = ROM16(BIT_M.data[0x09]);
if (script)
- nouveau_bios_run_init_table(dev, script, NULL);
+ nouveau_bios_run_init_table(dev, script, NULL, -1);
- nouveau_bios_run_init_table(dev, perflvl->memscript, NULL);
+ nouveau_bios_run_init_table(dev, perflvl->memscript, NULL, -1);
}
if (state->type == PLL_MEMORY) {
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index ffe8b483b7b0..2633aa8554eb 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -124,7 +124,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
if (mode == DRM_MODE_DPMS_ON) {
u8 status = DP_SET_POWER_D0;
nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1);
- nouveau_dp_link_train(encoder);
+ nouveau_dp_link_train(encoder, nv_encoder->dp.datarate);
} else {
u8 status = DP_SET_POWER_D3;
nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1);
@@ -187,14 +187,13 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct drm_device *dev = encoder->dev;
struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
+ struct nouveau_connector *nv_connector;
uint32_t mode_ctl = 0;
int ret;
NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n",
nv_encoder->or, nv_encoder->dcb->type, crtc->index);
- nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
-
switch (nv_encoder->dcb->type) {
case OUTPUT_TMDS:
if (nv_encoder->dcb->sorconf.link & 1) {
@@ -206,7 +205,15 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
mode_ctl = 0x0200;
break;
case OUTPUT_DP:
- mode_ctl |= (nv_encoder->dp.mc_unknown << 16);
+ nv_connector = nouveau_encoder_connector_get(nv_encoder);
+ if (nv_connector && nv_connector->base.display_info.bpc == 6) {
+ nv_encoder->dp.datarate = crtc->mode->clock * 18 / 8;
+ mode_ctl |= 0x00020000;
+ } else {
+ nv_encoder->dp.datarate = crtc->mode->clock * 24 / 8;
+ mode_ctl |= 0x00050000;
+ }
+
if (nv_encoder->dcb->sorconf.link & 1)
mode_ctl |= 0x00000800;
else
@@ -227,6 +234,8 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC;
+ nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
+
ret = RING_SPACE(evo, 2);
if (ret) {
NV_ERROR(dev, "no space while connecting SOR\n");
@@ -313,31 +322,6 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry)
encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0;
- if (nv_encoder->dcb->type == OUTPUT_DP) {
- int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
- uint32_t tmp;
-
- tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
- if (!tmp)
- tmp = nv_rd32(dev, 0x610798 + (or * 8));
-
- switch ((tmp & 0x00000f00) >> 8) {
- case 8:
- case 9:
- nv_encoder->dp.mc_unknown = (tmp & 0x000f0000) >> 16;
- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
- nv_encoder->dp.unk0 = tmp & 0x000001fc;
- tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link));
- nv_encoder->dp.unk1 = tmp & 0x010f7f3f;
- break;
- default:
- break;
- }
-
- if (!nv_encoder->dp.mc_unknown)
- nv_encoder->dp.mc_unknown = 5;
- }
-
drm_mode_connector_attach_encoder(connector, encoder);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c
index af32daecd1ed..9da23838e63e 100644
--- a/drivers/gpu/drm/nouveau/nv50_vram.c
+++ b/drivers/gpu/drm/nouveau/nv50_vram.c
@@ -51,7 +51,7 @@ void
nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_mm *mm = dev_priv->engine.vram.mm;
+ struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
struct nouveau_mm_node *this;
struct nouveau_mem *mem;
@@ -82,7 +82,7 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
u32 memtype, struct nouveau_mem **pmem)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_mm *mm = dev_priv->engine.vram.mm;
+ struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
struct nouveau_mm_node *r;
struct nouveau_mem *mem;
int comp = (memtype & 0x300) >> 8;
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c
index e4b2b9e934b2..618c144b7a30 100644
--- a/drivers/gpu/drm/nouveau/nva3_pm.c
+++ b/drivers/gpu/drm/nouveau/nva3_pm.c
@@ -27,178 +27,316 @@
#include "nouveau_bios.h"
#include "nouveau_pm.h"
-/* This is actually a lot more complex than it appears here, but hopefully
- * this should be able to deal with what the VBIOS leaves for us..
- *
- * If not, well, I'll jump off that bridge when I come to it.
- */
+static u32 read_clk(struct drm_device *, int, bool);
+static u32 read_pll(struct drm_device *, int, u32);
-struct nva3_pm_state {
- enum pll_types type;
- u32 src0;
- u32 src1;
- u32 ctrl;
- u32 coef;
- u32 old_pnm;
- u32 new_pnm;
- u32 new_div;
-};
+static u32
+read_vco(struct drm_device *dev, int clk)
+{
+ u32 sctl = nv_rd32(dev, 0x4120 + (clk * 4));
+ if ((sctl & 0x00000030) != 0x00000030)
+ return read_pll(dev, 0x41, 0x00e820);
+ return read_pll(dev, 0x42, 0x00e8a0);
+}
-static int
-nva3_pm_pll_offset(u32 id)
+static u32
+read_clk(struct drm_device *dev, int clk, bool ignore_en)
{
- static const u32 pll_map[] = {
- 0x00, PLL_CORE,
- 0x01, PLL_SHADER,
- 0x02, PLL_MEMORY,
- 0x00, 0x00
- };
- const u32 *map = pll_map;
-
- while (map[1]) {
- if (id == map[1])
- return map[0];
- map += 2;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ u32 sctl, sdiv, sclk;
+
+ /* refclk for the 0xe8xx plls is a fixed frequency */
+ if (clk >= 0x40) {
+ if (dev_priv->chipset == 0xaf) {
+ /* no joke.. seriously.. sigh.. */
+ return nv_rd32(dev, 0x00471c) * 1000;
+ }
+
+ return dev_priv->crystal;
}
- return -ENOENT;
+ sctl = nv_rd32(dev, 0x4120 + (clk * 4));
+ if (!ignore_en && !(sctl & 0x00000100))
+ return 0;
+
+ switch (sctl & 0x00003000) {
+ case 0x00000000:
+ return dev_priv->crystal;
+ case 0x00002000:
+ if (sctl & 0x00000040)
+ return 108000;
+ return 100000;
+ case 0x00003000:
+ sclk = read_vco(dev, clk);
+ sdiv = ((sctl & 0x003f0000) >> 16) + 2;
+ return (sclk * 2) / sdiv;
+ default:
+ return 0;
+ }
}
-int
-nva3_pm_clock_get(struct drm_device *dev, u32 id)
+static u32
+read_pll(struct drm_device *dev, int clk, u32 pll)
+{
+ u32 ctrl = nv_rd32(dev, pll + 0);
+ u32 sclk = 0, P = 1, N = 1, M = 1;
+
+ if (!(ctrl & 0x00000008)) {
+ if (ctrl & 0x00000001) {
+ u32 coef = nv_rd32(dev, pll + 4);
+ M = (coef & 0x000000ff) >> 0;
+ N = (coef & 0x0000ff00) >> 8;
+ P = (coef & 0x003f0000) >> 16;
+
+ /* no post-divider on these.. */
+ if ((pll & 0x00ff00) == 0x00e800)
+ P = 1;
+
+ sclk = read_clk(dev, 0x00 + clk, false);
+ }
+ } else {
+ sclk = read_clk(dev, 0x10 + clk, false);
+ }
+
+ return sclk * N / (M * P);
+}
+
+struct creg {
+ u32 clk;
+ u32 pll;
+};
+
+static int
+calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg)
{
- u32 src0, src1, ctrl, coef;
- struct pll_lims pll;
- int ret, off;
- int P, N, M;
+ struct pll_lims limits;
+ u32 oclk, sclk, sdiv;
+ int P, N, M, diff;
+ int ret;
+
+ reg->pll = 0;
+ reg->clk = 0;
+ if (!khz) {
+ NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk);
+ return 0;
+ }
- ret = get_pll_limits(dev, id, &pll);
+ switch (khz) {
+ case 27000:
+ reg->clk = 0x00000100;
+ return khz;
+ case 100000:
+ reg->clk = 0x00002100;
+ return khz;
+ case 108000:
+ reg->clk = 0x00002140;
+ return khz;
+ default:
+ sclk = read_vco(dev, clk);
+ sdiv = min((sclk * 2) / (khz - 2999), (u32)65);
+ /* if the clock has a PLL attached, and we can get a within
+ * [-2, 3) MHz of a divider, we'll disable the PLL and use
+ * the divider instead.
+ *
+ * divider can go as low as 2, limited here because NVIDIA
+ * and the VBIOS on my NVA8 seem to prefer using the PLL
+ * for 810MHz - is there a good reason?
+ */
+ if (sdiv > 4) {
+ oclk = (sclk * 2) / sdiv;
+ diff = khz - oclk;
+ if (!pll || (diff >= -2000 && diff < 3000)) {
+ reg->clk = (((sdiv - 2) << 16) | 0x00003100);
+ return oclk;
+ }
+ }
+
+ if (!pll) {
+ NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk);
+ return -ERANGE;
+ }
+
+ break;
+ }
+
+ ret = get_pll_limits(dev, pll, &limits);
if (ret)
return ret;
- off = nva3_pm_pll_offset(id);
- if (off < 0)
- return off;
+ limits.refclk = read_clk(dev, clk - 0x10, true);
+ if (!limits.refclk)
+ return -EINVAL;
+
+ ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P);
+ if (ret >= 0) {
+ reg->clk = nv_rd32(dev, 0x4120 + (clk * 4));
+ reg->pll = (P << 16) | (N << 8) | M;
+ }
+ return ret;
+}
+
+static void
+prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg)
+{
+ const u32 src0 = 0x004120 + (clk * 4);
+ const u32 src1 = 0x004160 + (clk * 4);
+ const u32 ctrl = pll + 0;
+ const u32 coef = pll + 4;
+ u32 cntl;
+
+ if (!reg->clk && !reg->pll) {
+ NV_DEBUG(dev, "no clock for %02x\n", clk);
+ return;
+ }
- src0 = nv_rd32(dev, 0x4120 + (off * 4));
- src1 = nv_rd32(dev, 0x4160 + (off * 4));
- ctrl = nv_rd32(dev, pll.reg + 0);
- coef = nv_rd32(dev, pll.reg + 4);
- NV_DEBUG(dev, "PLL %02x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
- id, src0, src1, ctrl, coef);
+ cntl = nv_rd32(dev, ctrl) & 0xfffffff2;
+ if (reg->pll) {
+ nv_mask(dev, src0, 0x00000101, 0x00000101);
+ nv_wr32(dev, coef, reg->pll);
+ nv_wr32(dev, ctrl, cntl | 0x00000015);
+ nv_mask(dev, src1, 0x00000100, 0x00000000);
+ nv_mask(dev, src1, 0x00000001, 0x00000000);
+ } else {
+ nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk);
+ nv_wr32(dev, ctrl, cntl | 0x0000001d);
+ nv_mask(dev, ctrl, 0x00000001, 0x00000000);
+ nv_mask(dev, src0, 0x00000100, 0x00000000);
+ nv_mask(dev, src0, 0x00000001, 0x00000000);
+ }
+}
- if (ctrl & 0x00000008) {
- u32 div = ((src1 & 0x003c0000) >> 18) + 1;
- return (pll.refclk * 2) / div;
+static void
+prog_clk(struct drm_device *dev, int clk, struct creg *reg)
+{
+ if (!reg->clk) {
+ NV_DEBUG(dev, "no clock for %02x\n", clk);
+ return;
}
- P = (coef & 0x003f0000) >> 16;
- N = (coef & 0x0000ff00) >> 8;
- M = (coef & 0x000000ff);
- return pll.refclk * N / M / P;
+ nv_mask(dev, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk);
+}
+
+int
+nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+ perflvl->core = read_pll(dev, 0x00, 0x4200);
+ perflvl->shader = read_pll(dev, 0x01, 0x4220);
+ perflvl->memory = read_pll(dev, 0x02, 0x4000);
+ perflvl->unka0 = read_clk(dev, 0x20, false);
+ perflvl->vdec = read_clk(dev, 0x21, false);
+ perflvl->daemon = read_clk(dev, 0x25, false);
+ perflvl->copy = perflvl->core;
+ return 0;
}
+struct nva3_pm_state {
+ struct creg nclk;
+ struct creg sclk;
+ struct creg mclk;
+ struct creg vdec;
+ struct creg unka0;
+};
+
void *
-nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl,
- u32 id, int khz)
+nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
{
- struct nva3_pm_state *pll;
- struct pll_lims limits;
- int N, M, P, diff;
- int ret, off;
+ struct nva3_pm_state *info;
+ int ret;
- ret = get_pll_limits(dev, id, &limits);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+
+ ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk);
if (ret < 0)
- return (ret == -ENOENT) ? NULL : ERR_PTR(ret);
+ goto out;
- off = nva3_pm_pll_offset(id);
- if (id < 0)
- return ERR_PTR(-EINVAL);
+ ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk);
+ if (ret < 0)
+ goto out;
+ ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk);
+ if (ret < 0)
+ goto out;
- pll = kzalloc(sizeof(*pll), GFP_KERNEL);
- if (!pll)
- return ERR_PTR(-ENOMEM);
- pll->type = id;
- pll->src0 = 0x004120 + (off * 4);
- pll->src1 = 0x004160 + (off * 4);
- pll->ctrl = limits.reg + 0;
- pll->coef = limits.reg + 4;
-
- /* If target clock is within [-2, 3) MHz of a divisor, we'll
- * use that instead of calculating MNP values
- */
- pll->new_div = min((limits.refclk * 2) / (khz - 2999), 16);
- if (pll->new_div) {
- diff = khz - ((limits.refclk * 2) / pll->new_div);
- if (diff < -2000 || diff >= 3000)
- pll->new_div = 0;
- }
+ ret = calc_clk(dev, 0x20, 0x0000, perflvl->unka0, &info->unka0);
+ if (ret < 0)
+ goto out;
- if (!pll->new_div) {
- ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P);
- if (ret < 0)
- return ERR_PTR(ret);
+ ret = calc_clk(dev, 0x21, 0x0000, perflvl->vdec, &info->vdec);
+ if (ret < 0)
+ goto out;
- pll->new_pnm = (P << 16) | (N << 8) | M;
- pll->new_div = 2 - 1;
- } else {
- pll->new_pnm = 0;
- pll->new_div--;
+out:
+ if (ret < 0) {
+ kfree(info);
+ info = ERR_PTR(ret);
}
+ return info;
+}
+
+static bool
+nva3_pm_grcp_idle(void *data)
+{
+ struct drm_device *dev = data;
- if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101)
- pll->old_pnm = nv_rd32(dev, pll->coef);
- return pll;
+ if (!(nv_rd32(dev, 0x400304) & 0x00000001))
+ return true;
+ if (nv_rd32(dev, 0x400308) == 0x0050001c)
+ return true;
+ return false;
}
void
-nva3_pm_clock_set(struct drm_device *dev, void *pre_state)
+nva3_pm_clocks_set(struct drm_device *dev, void *pre_state)
{
- struct nva3_pm_state *pll = pre_state;
- u32 ctrl = 0;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nva3_pm_state *info = pre_state;
+ unsigned long flags;
- /* For the memory clock, NVIDIA will build a "script" describing
- * the reclocking process and ask PDAEMON to execute it.
- */
- if (pll->type == PLL_MEMORY) {
- nv_wr32(dev, 0x100210, 0);
- nv_wr32(dev, 0x1002dc, 1);
- nv_wr32(dev, 0x004018, 0x00001000);
- ctrl = 0x18000100;
+ /* prevent any new grctx switches from starting */
+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+ nv_wr32(dev, 0x400324, 0x00000000);
+ nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */
+ /* wait for any pending grctx switches to complete */
+ if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) {
+ NV_ERROR(dev, "pm: ctxprog didn't go idle\n");
+ goto cleanup;
}
-
- if (pll->old_pnm || !pll->new_pnm) {
- nv_mask(dev, pll->src1, 0x003c0101, 0x00000101 |
- (pll->new_div << 18));
- nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl);
- nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000);
+ /* freeze PFIFO */
+ nv_mask(dev, 0x002504, 0x00000001, 0x00000001);
+ if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) {
+ NV_ERROR(dev, "pm: fifo didn't go idle\n");
+ goto cleanup;
}
- if (pll->new_pnm) {
- nv_mask(dev, pll->src0, 0x00000101, 0x00000101);
- nv_wr32(dev, pll->coef, pll->new_pnm);
- nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl);
- nv_mask(dev, pll->ctrl, 0x00000010, 0x00000000);
- nv_mask(dev, pll->ctrl, 0x00020010, 0x00020010);
- nv_wr32(dev, pll->ctrl, 0x00010015 | ctrl);
- nv_mask(dev, pll->src1, 0x00000100, 0x00000000);
- nv_mask(dev, pll->src1, 0x00000001, 0x00000000);
- if (pll->type == PLL_MEMORY)
- nv_wr32(dev, 0x4018, 0x10005000);
- } else {
- nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000);
- nv_mask(dev, pll->src0, 0x00000100, 0x00000000);
- nv_mask(dev, pll->src0, 0x00000001, 0x00000000);
- if (pll->type == PLL_MEMORY)
- nv_wr32(dev, 0x4018, 0x1000d000);
- }
+ prog_pll(dev, 0x00, 0x004200, &info->nclk);
+ prog_pll(dev, 0x01, 0x004220, &info->sclk);
+ prog_clk(dev, 0x20, &info->unka0);
+ prog_clk(dev, 0x21, &info->vdec);
- if (pll->type == PLL_MEMORY) {
+ if (info->mclk.clk || info->mclk.pll) {
+ nv_wr32(dev, 0x100210, 0);
+ nv_wr32(dev, 0x1002dc, 1);
+ nv_wr32(dev, 0x004018, 0x00001000);
+ prog_pll(dev, 0x02, 0x004000, &info->mclk);
+ if (nv_rd32(dev, 0x4000) & 0x00000008)
+ nv_wr32(dev, 0x004018, 0x1000d000);
+ else
+ nv_wr32(dev, 0x004018, 0x10005000);
nv_wr32(dev, 0x1002dc, 0);
nv_wr32(dev, 0x100210, 0x80000000);
}
- kfree(pll);
+cleanup:
+ /* unfreeze PFIFO */
+ nv_mask(dev, 0x002504, 0x00000001, 0x00000000);
+ /* restore ctxprog to normal */
+ nv_wr32(dev, 0x400324, 0x00000000);
+ nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */
+ /* unblock it if necessary */
+ if (nv_rd32(dev, 0x400308) == 0x0050001c)
+ nv_mask(dev, 0x400824, 0x10000000, 0x10000000);
+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+ kfree(info);
}
-
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c
index 08e6b118f021..5bf55038fd92 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fb.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fb.c
@@ -32,6 +32,30 @@ struct nvc0_fb_priv {
dma_addr_t r100c10;
};
+static inline void
+nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp)
+{
+ u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400);
+ u32 stat = nv_rd32(dev, subp_base + 0x020);
+
+ if (stat) {
+ NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat);
+ nv_wr32(dev, subp_base + 0x020, stat);
+ }
+}
+
+static void
+nvc0_mfb_isr(struct drm_device *dev)
+{
+ u32 units = nv_rd32(dev, 0x00017c);
+ while (units) {
+ u32 subp, unit = ffs(units) - 1;
+ for (subp = 0; subp < 2; subp++)
+ nvc0_mfb_subp_isr(dev, unit, subp);
+ units &= ~(1 << unit);
+ }
+}
+
static void
nvc0_fb_destroy(struct drm_device *dev)
{
@@ -39,6 +63,8 @@ nvc0_fb_destroy(struct drm_device *dev)
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
struct nvc0_fb_priv *priv = pfb->priv;
+ nouveau_irq_unregister(dev, 25);
+
if (priv->r100c10_page) {
pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
@@ -74,6 +100,7 @@ nvc0_fb_create(struct drm_device *dev)
return -EFAULT;
}
+ nouveau_irq_register(dev, 25, nvc0_mfb_isr);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c
index 6f9f341c3e86..dcbe0d5d0241 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c
@@ -322,7 +322,7 @@ nvc0_fifo_init(struct drm_device *dev)
}
/* PSUBFIFO[n] */
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < priv->spoon_nr; i++) {
nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c
index 5b2f6f420468..4b8d0b3f7d2b 100644
--- a/drivers/gpu/drm/nouveau/nvc0_graph.c
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.c
@@ -390,7 +390,7 @@ nvc0_graph_init_gpc_0(struct drm_device *dev)
}
nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918);
- nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr);
+ nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800));
}
static void
@@ -700,22 +700,6 @@ nvc0_graph_isr(struct drm_device *dev)
nv_wr32(dev, 0x400500, 0x00010001);
}
-static void
-nvc0_runk140_isr(struct drm_device *dev)
-{
- u32 units = nv_rd32(dev, 0x00017c) & 0x1f;
-
- while (units) {
- u32 unit = ffs(units) - 1;
- u32 reg = 0x140000 + unit * 0x2000;
- u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0);
- u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0);
-
- NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
- units &= ~(1 << unit);
- }
-}
-
static int
nvc0_graph_create_fw(struct drm_device *dev, const char *fwname,
struct nvc0_graph_fuc *fuc)
@@ -764,7 +748,6 @@ nvc0_graph_destroy(struct drm_device *dev, int engine)
}
nouveau_irq_unregister(dev, 12);
- nouveau_irq_unregister(dev, 25);
nouveau_gpuobj_ref(NULL, &priv->unk4188b8);
nouveau_gpuobj_ref(NULL, &priv->unk4188b4);
@@ -803,7 +786,6 @@ nvc0_graph_create(struct drm_device *dev)
NVOBJ_ENGINE_ADD(dev, GR, &priv->base);
nouveau_irq_register(dev, 12, nvc0_graph_isr);
- nouveau_irq_register(dev, 25, nvc0_runk140_isr);
if (nouveau_ctxfw) {
NV_INFO(dev, "PGRAPH: using external firmware\n");
@@ -864,6 +846,9 @@ nvc0_graph_create(struct drm_device *dev)
case 0xce: /* 4/4/0/0, 4 */
priv->magic_not_rop_nr = 0x03;
break;
+ case 0xcf: /* 4/0/0/0, 3 */
+ priv->magic_not_rop_nr = 0x03;
+ break;
}
if (!priv->magic_not_rop_nr) {
@@ -889,20 +874,3 @@ error:
nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR);
return ret;
}
-
-MODULE_FIRMWARE("nouveau/nvc0_fuc409c");
-MODULE_FIRMWARE("nouveau/nvc0_fuc409d");
-MODULE_FIRMWARE("nouveau/nvc0_fuc41ac");
-MODULE_FIRMWARE("nouveau/nvc0_fuc41ad");
-MODULE_FIRMWARE("nouveau/nvc3_fuc409c");
-MODULE_FIRMWARE("nouveau/nvc3_fuc409d");
-MODULE_FIRMWARE("nouveau/nvc3_fuc41ac");
-MODULE_FIRMWARE("nouveau/nvc3_fuc41ad");
-MODULE_FIRMWARE("nouveau/nvc4_fuc409c");
-MODULE_FIRMWARE("nouveau/nvc4_fuc409d");
-MODULE_FIRMWARE("nouveau/nvc4_fuc41ac");
-MODULE_FIRMWARE("nouveau/nvc4_fuc41ad");
-MODULE_FIRMWARE("nouveau/fuc409c");
-MODULE_FIRMWARE("nouveau/fuc409d");
-MODULE_FIRMWARE("nouveau/fuc41ac");
-MODULE_FIRMWARE("nouveau/fuc41ad");
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h
index 55689e997286..636fe9812f79 100644
--- a/drivers/gpu/drm/nouveau/nvc0_graph.h
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.h
@@ -82,6 +82,7 @@ nvc0_graph_class(struct drm_device *dev)
case 0xc3:
case 0xc4:
case 0xce: /* guess, mmio trace shows only 0x9097 state */
+ case 0xcf: /* guess, mmio trace shows only 0x9097 state */
return 0x9097;
case 0xc1:
return 0x9197;
diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c
index 31018eaf5279..dd0e6a736b3b 100644
--- a/drivers/gpu/drm/nouveau/nvc0_grctx.c
+++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c
@@ -1678,7 +1678,10 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
nv_wr32(dev, 0x419c04, 0x00000006);
nv_wr32(dev, 0x419c08, 0x00000002);
nv_wr32(dev, 0x419c20, 0x00000000);
- nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048
+ if (chipset == 0xce || chipset == 0xcf)
+ nv_wr32(dev, 0x419cb0, 0x00020048);
+ else
+ nv_wr32(dev, 0x419cb0, 0x00060048);
nv_wr32(dev, 0x419ce8, 0x00000000);
nv_wr32(dev, 0x419cf4, 0x00000183);
nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000);
@@ -1783,11 +1786,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
nv_wr32(dev, 0x40587c, 0x00000000);
if (1) {
- const u8 chipset_tp_max[] = { 16, 4, 0, 4, 8, 0, 0, 0,
- 16, 0, 0, 0, 0, 0, 8, 0 };
- u8 max = chipset_tp_max[dev_priv->chipset & 0x0f];
- u8 tpnr[GPC_MAX];
- u8 data[TP_MAX];
+ u8 tpnr[GPC_MAX], data[TP_MAX];
memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
memset(data, 0x1f, sizeof(data));
@@ -1801,7 +1800,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
data[tp] = gpc;
}
- for (i = 0; i < max / 4; i++)
+ for (i = 0; i < 4; i++)
nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]);
}
diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
index 0ec2add72a76..06f5e26d1e0f 100644
--- a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
+++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
@@ -77,6 +77,11 @@ chipsets:
.b16 nvc0_gpc_mmio_tail
.b16 nvc0_tpc_mmio_head
.b16 nvc3_tpc_mmio_tail
+.b8 0xcf 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvcf_tpc_mmio_tail
.b8 0 0 0 0
// GPC mmio lists
@@ -134,8 +139,9 @@ mmctx_data(0x000750, 2)
nvc0_tpc_mmio_tail:
mmctx_data(0x000758, 1)
mmctx_data(0x0002c4, 1)
-mmctx_data(0x0004bc, 1)
mmctx_data(0x0006e0, 1)
+nvcf_tpc_mmio_tail:
+mmctx_data(0x0004bc, 1)
nvc3_tpc_mmio_tail:
mmctx_data(0x000544, 1)
nvc1_tpc_mmio_tail:
diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
index 1896c898f5ba..6f820324480e 100644
--- a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
+++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
@@ -25,23 +25,26 @@ uint32_t nvc0_grgpc_data[] = {
0x00000000,
0x00000000,
0x000000c0,
- 0x011000b0,
- 0x01640114,
+ 0x011c00bc,
+ 0x01700120,
0x000000c1,
- 0x011400b0,
- 0x01780114,
+ 0x012000bc,
+ 0x01840120,
0x000000c3,
- 0x011000b0,
- 0x01740114,
+ 0x011c00bc,
+ 0x01800120,
0x000000c4,
- 0x011000b0,
- 0x01740114,
+ 0x011c00bc,
+ 0x01800120,
0x000000c8,
- 0x011000b0,
- 0x01640114,
+ 0x011c00bc,
+ 0x01700120,
0x000000ce,
- 0x011000b0,
- 0x01740114,
+ 0x011c00bc,
+ 0x01800120,
+ 0x000000cf,
+ 0x011c00bc,
+ 0x017c0120,
0x00000000,
0x00000380,
0x14000400,
@@ -90,8 +93,8 @@ uint32_t nvc0_grgpc_data[] = {
0x04000750,
0x00000758,
0x000002c4,
- 0x000004bc,
0x000006e0,
+ 0x000004bc,
0x00000544,
};
diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
index a1a599124cf4..e4f8c7e89ddd 100644
--- a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
+++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
@@ -56,6 +56,9 @@ chipsets:
.b8 0xce 0 0 0
.b16 nvc0_hub_mmio_head
.b16 nvc0_hub_mmio_tail
+.b8 0xcf 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
.b8 0 0 0 0
nvc0_hub_mmio_head:
diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
index b3b541b6d044..241d3263f1e5 100644
--- a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
+++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
@@ -23,17 +23,19 @@ uint32_t nvc0_grhub_data[] = {
0x00000000,
0x00000000,
0x000000c0,
- 0x012c0090,
+ 0x01340098,
0x000000c1,
- 0x01300090,
+ 0x01380098,
0x000000c3,
- 0x012c0090,
+ 0x01340098,
0x000000c4,
- 0x012c0090,
+ 0x01340098,
0x000000c8,
- 0x012c0090,
+ 0x01340098,
0x000000ce,
- 0x012c0090,
+ 0x01340098,
+ 0x000000cf,
+ 0x01340098,
0x00000000,
0x0417e91c,
0x04400204,
@@ -190,8 +192,6 @@ uint32_t nvc0_grhub_data[] = {
0x00000000,
0x00000000,
0x00000000,
- 0x00000000,
- 0x00000000,
};
uint32_t nvc0_grhub_code[] = {
diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c
new file mode 100644
index 000000000000..929aded35cb5
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_pm.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_bios.h"
+#include "nouveau_pm.h"
+
+static u32 read_div(struct drm_device *, int, u32, u32);
+static u32 read_pll(struct drm_device *, u32);
+
+static u32
+read_vco(struct drm_device *dev, u32 dsrc)
+{
+ u32 ssrc = nv_rd32(dev, dsrc);
+ if (!(ssrc & 0x00000100))
+ return read_pll(dev, 0x00e800);
+ return read_pll(dev, 0x00e820);
+}
+
+static u32
+read_pll(struct drm_device *dev, u32 pll)
+{
+ u32 ctrl = nv_rd32(dev, pll + 0);
+ u32 coef = nv_rd32(dev, pll + 4);
+ u32 P = (coef & 0x003f0000) >> 16;
+ u32 N = (coef & 0x0000ff00) >> 8;
+ u32 M = (coef & 0x000000ff) >> 0;
+ u32 sclk, doff;
+
+ if (!(ctrl & 0x00000001))
+ return 0;
+
+ switch (pll & 0xfff000) {
+ case 0x00e000:
+ sclk = 27000;
+ P = 1;
+ break;
+ case 0x137000:
+ doff = (pll - 0x137000) / 0x20;
+ sclk = read_div(dev, doff, 0x137120, 0x137140);
+ break;
+ case 0x132000:
+ switch (pll) {
+ case 0x132000:
+ sclk = read_pll(dev, 0x132020);
+ break;
+ case 0x132020:
+ sclk = read_div(dev, 0, 0x137320, 0x137330);
+ break;
+ default:
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return sclk * N / M / P;
+}
+
+static u32
+read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl)
+{
+ u32 ssrc = nv_rd32(dev, dsrc + (doff * 4));
+ u32 sctl = nv_rd32(dev, dctl + (doff * 4));
+
+ switch (ssrc & 0x00000003) {
+ case 0:
+ if ((ssrc & 0x00030000) != 0x00030000)
+ return 27000;
+ return 108000;
+ case 2:
+ return 100000;
+ case 3:
+ if (sctl & 0x80000000) {
+ u32 sclk = read_vco(dev, dsrc + (doff * 4));
+ u32 sdiv = (sctl & 0x0000003f) + 2;
+ return (sclk * 2) / sdiv;
+ }
+
+ return read_vco(dev, dsrc + (doff * 4));
+ default:
+ return 0;
+ }
+}
+
+static u32
+read_mem(struct drm_device *dev)
+{
+ u32 ssel = nv_rd32(dev, 0x1373f0);
+ if (ssel & 0x00000001)
+ return read_div(dev, 0, 0x137300, 0x137310);
+ return read_pll(dev, 0x132000);
+}
+
+static u32
+read_clk(struct drm_device *dev, int clk)
+{
+ u32 sctl = nv_rd32(dev, 0x137250 + (clk * 4));
+ u32 ssel = nv_rd32(dev, 0x137100);
+ u32 sclk, sdiv;
+
+ if (ssel & (1 << clk)) {
+ if (clk < 7)
+ sclk = read_pll(dev, 0x137000 + (clk * 0x20));
+ else
+ sclk = read_pll(dev, 0x1370e0);
+ sdiv = ((sctl & 0x00003f00) >> 8) + 2;
+ } else {
+ sclk = read_div(dev, clk, 0x137160, 0x1371d0);
+ sdiv = ((sctl & 0x0000003f) >> 0) + 2;
+ }
+
+ if (sctl & 0x80000000)
+ return (sclk * 2) / sdiv;
+ return sclk;
+}
+
+int
+nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+ perflvl->shader = read_clk(dev, 0x00);
+ perflvl->core = perflvl->shader / 2;
+ perflvl->memory = read_mem(dev);
+ perflvl->rop = read_clk(dev, 0x01);
+ perflvl->hub07 = read_clk(dev, 0x02);
+ perflvl->hub06 = read_clk(dev, 0x07);
+ perflvl->hub01 = read_clk(dev, 0x08);
+ perflvl->copy = read_clk(dev, 0x09);
+ perflvl->daemon = read_clk(dev, 0x0c);
+ perflvl->vdec = read_clk(dev, 0x0e);
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c
index e45a24d84e98..edbfe9360ae2 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vram.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vram.c
@@ -61,7 +61,7 @@ nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
u32 type, struct nouveau_mem **pmem)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_mm *mm = dev_priv->engine.vram.mm;
+ struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
struct nouveau_mm_node *r;
struct nouveau_mem *mem;
int ret;
@@ -106,12 +106,50 @@ nvc0_vram_init(struct drm_device *dev)
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
- u32 length;
+ u32 parts = nv_rd32(dev, 0x121c74);
+ u32 bsize = nv_rd32(dev, 0x10f20c);
+ u32 offset, length;
+ bool uniform = true;
+ int ret, i;
- dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20;
- dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
+ NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
+ NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize);
- length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+ /* read amount of vram attached to each memory controller */
+ for (i = 0; i < parts; i++) {
+ u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000));
+ if (psize != bsize) {
+ if (psize < bsize)
+ bsize = psize;
+ uniform = false;
+ }
+
+ NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize);
+
+ dev_priv->vram_size += (u64)psize << 20;
+ }
+
+ /* if all controllers have the same amount attached, there's no holes */
+ if (uniform) {
+ offset = rsvd_head;
+ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+ return nouveau_mm_init(&vram->mm, offset, length, 1);
+ }
- return nouveau_mm_init(&vram->mm, rsvd_head, length, 1);
+ /* otherwise, address lowest common amount from 0GiB */
+ ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1);
+ if (ret)
+ return ret;
+
+ /* and the rest starting from (8GiB + common_size) */
+ offset = (0x0200000000ULL >> 12) + (bsize << 8);
+ length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail;
+
+ ret = nouveau_mm_init(&vram->mm, offset, length, 0);
+ if (ret) {
+ nouveau_mm_fini(&vram->mm);
+ return ret;
+ }
+
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c
new file mode 100644
index 000000000000..23d63b4b3d77
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvd0_display.c
@@ -0,0 +1,1473 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <linux/dma-mapping.h>
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "nouveau_drv.h"
+#include "nouveau_connector.h"
+#include "nouveau_encoder.h"
+#include "nouveau_crtc.h"
+#include "nouveau_dma.h"
+#include "nouveau_fb.h"
+#include "nv50_display.h"
+
+struct nvd0_display {
+ struct nouveau_gpuobj *mem;
+ struct {
+ dma_addr_t handle;
+ u32 *ptr;
+ } evo[1];
+
+ struct tasklet_struct tasklet;
+ u32 modeset;
+};
+
+static struct nvd0_display *
+nvd0_display(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ return dev_priv->engine.display.priv;
+}
+
+static inline int
+evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data)
+{
+ int ret = 0;
+ nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001);
+ nv_wr32(dev, 0x610704 + (id * 0x10), data);
+ nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd);
+ if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000))
+ ret = -EBUSY;
+ nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000);
+ return ret;
+}
+
+static u32 *
+evo_wait(struct drm_device *dev, int id, int nr)
+{
+ struct nvd0_display *disp = nvd0_display(dev);
+ u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4;
+
+ if (put + nr >= (PAGE_SIZE / 4)) {
+ disp->evo[id].ptr[put] = 0x20000000;
+
+ nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000);
+ if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) {
+ NV_ERROR(dev, "evo %d dma stalled\n", id);
+ return NULL;
+ }
+
+ put = 0;
+ }
+
+ return disp->evo[id].ptr + put;
+}
+
+static void
+evo_kick(u32 *push, struct drm_device *dev, int id)
+{
+ struct nvd0_display *disp = nvd0_display(dev);
+ nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2);
+}
+
+#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m))
+#define evo_data(p,d) *((p)++) = (d)
+
+static struct drm_crtc *
+nvd0_display_crtc_get(struct drm_encoder *encoder)
+{
+ return nouveau_encoder(encoder)->crtc;
+}
+
+/******************************************************************************
+ * CRTC
+ *****************************************************************************/
+static int
+nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update)
+{
+ struct drm_device *dev = nv_crtc->base.dev;
+ u32 *push, mode;
+
+ mode = 0x00000000;
+ if (on) {
+ /* 0x11: 6bpc dynamic 2x2
+ * 0x13: 8bpc dynamic 2x2
+ * 0x19: 6bpc static 2x2
+ * 0x1b: 8bpc static 2x2
+ * 0x21: 6bpc temporal
+ * 0x23: 8bpc temporal
+ */
+ mode = 0x00000011;
+ }
+
+ push = evo_wait(dev, 0, 4);
+ if (push) {
+ evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, mode);
+ if (update) {
+ evo_mthd(push, 0x0080, 1);
+ evo_data(push, 0x00000000);
+ }
+ evo_kick(push, dev, 0);
+ }
+
+ return 0;
+}
+
+static int
+nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, int type, bool update)
+{
+ struct drm_display_mode *mode = &nv_crtc->base.mode;
+ struct drm_device *dev = nv_crtc->base.dev;
+ struct nouveau_connector *nv_connector;
+ u32 *push, outX, outY;
+
+ outX = mode->hdisplay;
+ outY = mode->vdisplay;
+
+ nv_connector = nouveau_crtc_connector_get(nv_crtc);
+ if (nv_connector && nv_connector->native_mode) {
+ struct drm_display_mode *native = nv_connector->native_mode;
+ u32 xratio = (native->hdisplay << 19) / mode->hdisplay;
+ u32 yratio = (native->vdisplay << 19) / mode->vdisplay;
+
+ switch (type) {
+ case DRM_MODE_SCALE_ASPECT:
+ if (xratio > yratio) {
+ outX = (mode->hdisplay * yratio) >> 19;
+ outY = (mode->vdisplay * yratio) >> 19;
+ } else {
+ outX = (mode->hdisplay * xratio) >> 19;
+ outY = (mode->vdisplay * xratio) >> 19;
+ }
+ break;
+ case DRM_MODE_SCALE_FULLSCREEN:
+ outX = native->hdisplay;
+ outY = native->vdisplay;
+ break;
+ default:
+ break;
+ }
+ }
+
+ push = evo_wait(dev, 0, 16);
+ if (push) {
+ evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3);
+ evo_data(push, (outY << 16) | outX);
+ evo_data(push, (outY << 16) | outX);
+ evo_data(push, (outY << 16) | outX);
+ evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, 0x00000000);
+ evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, (mode->vdisplay << 16) | mode->hdisplay);
+ if (update) {
+ evo_mthd(push, 0x0080, 1);
+ evo_data(push, 0x00000000);
+ }
+ evo_kick(push, dev, 0);
+ }
+
+ return 0;
+}
+
+static int
+nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
+ int x, int y, bool update)
+{
+ struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb);
+ u32 *push;
+
+ push = evo_wait(fb->dev, 0, 16);
+ if (push) {
+ evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, nvfb->nvbo->bo.offset >> 8);
+ evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4);
+ evo_data(push, (fb->height << 16) | fb->width);
+ evo_data(push, nvfb->r_pitch);
+ evo_data(push, nvfb->r_format);
+ evo_data(push, nvfb->r_dma);
+ evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, (y << 16) | x);
+ if (update) {
+ evo_mthd(push, 0x0080, 1);
+ evo_data(push, 0x00000000);
+ }
+ evo_kick(push, fb->dev, 0);
+ }
+
+ nv_crtc->fb.tile_flags = nvfb->r_dma;
+ return 0;
+}
+
+static void
+nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update)
+{
+ struct drm_device *dev = nv_crtc->base.dev;
+ u32 *push = evo_wait(dev, 0, 16);
+ if (push) {
+ if (show) {
+ evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
+ evo_data(push, 0x85000000);
+ evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
+ evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
+ evo_data(push, NvEvoVRAM);
+ } else {
+ evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, 0x05000000);
+ evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
+ evo_data(push, 0x00000000);
+ }
+
+ if (update) {
+ evo_mthd(push, 0x0080, 1);
+ evo_data(push, 0x00000000);
+ }
+
+ evo_kick(push, dev, 0);
+ }
+}
+
+static void
+nvd0_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+}
+
+static void
+nvd0_crtc_prepare(struct drm_crtc *crtc)
+{
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ u32 *push;
+
+ push = evo_wait(crtc->dev, 0, 2);
+ if (push) {
+ evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, 0x00000000);
+ evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, 0x03000000);
+ evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, crtc->dev, 0);
+ }
+
+ nvd0_crtc_cursor_show(nv_crtc, false, false);
+}
+
+static void
+nvd0_crtc_commit(struct drm_crtc *crtc)
+{
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ u32 *push;
+
+ push = evo_wait(crtc->dev, 0, 32);
+ if (push) {
+ evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, nv_crtc->fb.tile_flags);
+ evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
+ evo_data(push, 0x83000000);
+ evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
+ evo_data(push, 0x00000000);
+ evo_data(push, 0x00000000);
+ evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
+ evo_data(push, NvEvoVRAM);
+ evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, 0xffffff00);
+ evo_kick(push, crtc->dev, 0);
+ }
+
+ nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true);
+}
+
+static bool
+nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ return true;
+}
+
+static int
+nvd0_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
+{
+ struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+ int ret;
+
+ ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
+ if (ret)
+ return ret;
+
+ if (old_fb) {
+ nvfb = nouveau_framebuffer(old_fb);
+ nouveau_bo_unpin(nvfb->nvbo);
+ }
+
+ return 0;
+}
+
+static int
+nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
+ struct drm_display_mode *mode, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ struct nouveau_connector *nv_connector;
+ u32 htotal = mode->htotal;
+ u32 vtotal = mode->vtotal;
+ u32 hsyncw = mode->hsync_end - mode->hsync_start - 1;
+ u32 vsyncw = mode->vsync_end - mode->vsync_start - 1;
+ u32 hfrntp = mode->hsync_start - mode->hdisplay;
+ u32 vfrntp = mode->vsync_start - mode->vdisplay;
+ u32 hbackp = mode->htotal - mode->hsync_end;
+ u32 vbackp = mode->vtotal - mode->vsync_end;
+ u32 hss2be = hsyncw + hbackp;
+ u32 vss2be = vsyncw + vbackp;
+ u32 hss2de = htotal - hfrntp;
+ u32 vss2de = vtotal - vfrntp;
+ u32 syncs, *push;
+ int ret;
+
+ syncs = 0x00000001;
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ syncs |= 0x00000008;
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ syncs |= 0x00000010;
+
+ ret = nvd0_crtc_swap_fbs(crtc, old_fb);
+ if (ret)
+ return ret;
+
+ push = evo_wait(crtc->dev, 0, 64);
+ if (push) {
+ evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5);
+ evo_data(push, 0x00000000);
+ evo_data(push, (vtotal << 16) | htotal);
+ evo_data(push, (vsyncw << 16) | hsyncw);
+ evo_data(push, (vss2be << 16) | hss2be);
+ evo_data(push, (vss2de << 16) | hss2de);
+ evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1);
+ evo_data(push, 0x00000000); /* ??? */
+ evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3);
+ evo_data(push, mode->clock * 1000);
+ evo_data(push, 0x00200000); /* ??? */
+ evo_data(push, mode->clock * 1000);
+ evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1);
+ evo_data(push, syncs);
+ evo_kick(push, crtc->dev, 0);
+ }
+
+ nv_connector = nouveau_crtc_connector_get(nv_crtc);
+ nvd0_crtc_set_dither(nv_crtc, nv_connector->use_dithering, false);
+ nvd0_crtc_set_scale(nv_crtc, nv_connector->scaling_mode, false);
+ nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
+ return 0;
+}
+
+static int
+nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ int ret;
+
+ if (!crtc->fb) {
+ NV_DEBUG_KMS(crtc->dev, "No FB bound\n");
+ return 0;
+ }
+
+ ret = nvd0_crtc_swap_fbs(crtc, old_fb);
+ if (ret)
+ return ret;
+
+ nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
+ return 0;
+}
+
+static int
+nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb, int x, int y,
+ enum mode_set_atomic state)
+{
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ nvd0_crtc_set_image(nv_crtc, fb, x, y, true);
+ return 0;
+}
+
+static void
+nvd0_crtc_lut_load(struct drm_crtc *crtc)
+{
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo);
+ int i;
+
+ for (i = 0; i < 256; i++) {
+ writew(0x6000 + (nv_crtc->lut.r[i] >> 2), lut + (i * 0x20) + 0);
+ writew(0x6000 + (nv_crtc->lut.g[i] >> 2), lut + (i * 0x20) + 2);
+ writew(0x6000 + (nv_crtc->lut.b[i] >> 2), lut + (i * 0x20) + 4);
+ }
+}
+
+static int
+nvd0_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
+ uint32_t handle, uint32_t width, uint32_t height)
+{
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct drm_gem_object *gem;
+ struct nouveau_bo *nvbo;
+ bool visible = (handle != 0);
+ int i, ret = 0;
+
+ if (visible) {
+ if (width != 64 || height != 64)
+ return -EINVAL;
+
+ gem = drm_gem_object_lookup(dev, file_priv, handle);
+ if (unlikely(!gem))
+ return -ENOENT;
+ nvbo = nouveau_gem_object(gem);
+
+ ret = nouveau_bo_map(nvbo);
+ if (ret == 0) {
+ for (i = 0; i < 64 * 64; i++) {
+ u32 v = nouveau_bo_rd32(nvbo, i);
+ nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, v);
+ }
+ nouveau_bo_unmap(nvbo);
+ }
+
+ drm_gem_object_unreference_unlocked(gem);
+ }
+
+ if (visible != nv_crtc->cursor.visible) {
+ nvd0_crtc_cursor_show(nv_crtc, visible, true);
+ nv_crtc->cursor.visible = visible;
+ }
+
+ return ret;
+}
+
+static int
+nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ const u32 data = (y << 16) | x;
+
+ nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data);
+ nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000);
+ return 0;
+}
+
+static void
+nvd0_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
+ uint32_t start, uint32_t size)
+{
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ u32 end = max(start + size, (u32)256);
+ u32 i;
+
+ for (i = start; i < end; i++) {
+ nv_crtc->lut.r[i] = r[i];
+ nv_crtc->lut.g[i] = g[i];
+ nv_crtc->lut.b[i] = b[i];
+ }
+
+ nvd0_crtc_lut_load(crtc);
+}
+
+static void
+nvd0_crtc_destroy(struct drm_crtc *crtc)
+{
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ nouveau_bo_unmap(nv_crtc->cursor.nvbo);
+ nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
+ nouveau_bo_unmap(nv_crtc->lut.nvbo);
+ nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
+ drm_crtc_cleanup(crtc);
+ kfree(crtc);
+}
+
+static const struct drm_crtc_helper_funcs nvd0_crtc_hfunc = {
+ .dpms = nvd0_crtc_dpms,
+ .prepare = nvd0_crtc_prepare,
+ .commit = nvd0_crtc_commit,
+ .mode_fixup = nvd0_crtc_mode_fixup,
+ .mode_set = nvd0_crtc_mode_set,
+ .mode_set_base = nvd0_crtc_mode_set_base,
+ .mode_set_base_atomic = nvd0_crtc_mode_set_base_atomic,
+ .load_lut = nvd0_crtc_lut_load,
+};
+
+static const struct drm_crtc_funcs nvd0_crtc_func = {
+ .cursor_set = nvd0_crtc_cursor_set,
+ .cursor_move = nvd0_crtc_cursor_move,
+ .gamma_set = nvd0_crtc_gamma_set,
+ .set_config = drm_crtc_helper_set_config,
+ .destroy = nvd0_crtc_destroy,
+};
+
+static void
+nvd0_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
+{
+}
+
+static void
+nvd0_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
+{
+}
+
+static int
+nvd0_crtc_create(struct drm_device *dev, int index)
+{
+ struct nouveau_crtc *nv_crtc;
+ struct drm_crtc *crtc;
+ int ret, i;
+
+ nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
+ if (!nv_crtc)
+ return -ENOMEM;
+
+ nv_crtc->index = index;
+ nv_crtc->set_dither = nvd0_crtc_set_dither;
+ nv_crtc->set_scale = nvd0_crtc_set_scale;
+ nv_crtc->cursor.set_offset = nvd0_cursor_set_offset;
+ nv_crtc->cursor.set_pos = nvd0_cursor_set_pos;
+ for (i = 0; i < 256; i++) {
+ nv_crtc->lut.r[i] = i << 8;
+ nv_crtc->lut.g[i] = i << 8;
+ nv_crtc->lut.b[i] = i << 8;
+ }
+
+ crtc = &nv_crtc->base;
+ drm_crtc_init(dev, crtc, &nvd0_crtc_func);
+ drm_crtc_helper_add(crtc, &nvd0_crtc_hfunc);
+ drm_mode_crtc_set_gamma_size(crtc, 256);
+
+ ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM,
+ 0, 0x0000, &nv_crtc->cursor.nvbo);
+ if (!ret) {
+ ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
+ if (!ret)
+ ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
+ if (ret)
+ nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
+ }
+
+ if (ret)
+ goto out;
+
+ ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM,
+ 0, 0x0000, &nv_crtc->lut.nvbo);
+ if (!ret) {
+ ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
+ if (!ret)
+ ret = nouveau_bo_map(nv_crtc->lut.nvbo);
+ if (ret)
+ nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
+ }
+
+ if (ret)
+ goto out;
+
+ nvd0_crtc_lut_load(crtc);
+
+out:
+ if (ret)
+ nvd0_crtc_destroy(crtc);
+ return ret;
+}
+
+/******************************************************************************
+ * DAC
+ *****************************************************************************/
+static void
+nvd0_dac_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct drm_device *dev = encoder->dev;
+ int or = nv_encoder->or;
+ u32 dpms_ctrl;
+
+ dpms_ctrl = 0x80000000;
+ if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF)
+ dpms_ctrl |= 0x00000001;
+ if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF)
+ dpms_ctrl |= 0x00000004;
+
+ nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000);
+ nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl);
+ nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000);
+}
+
+static bool
+nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nouveau_connector *nv_connector;
+
+ nv_connector = nouveau_encoder_connector_get(nv_encoder);
+ if (nv_connector && nv_connector->native_mode) {
+ if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
+ int id = adjusted_mode->base.id;
+ *adjusted_mode = *nv_connector->native_mode;
+ adjusted_mode->base.id = id;
+ }
+ }
+
+ return true;
+}
+
+static void
+nvd0_dac_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_dac_commit(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+ u32 *push;
+
+ nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON);
+
+ push = evo_wait(encoder->dev, 0, 4);
+ if (push) {
+ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2);
+ evo_data(push, 1 << nv_crtc->index);
+ evo_data(push, 0x00ff);
+ evo_kick(push, encoder->dev, 0);
+ }
+
+ nv_encoder->crtc = encoder->crtc;
+}
+
+static void
+nvd0_dac_disconnect(struct drm_encoder *encoder)
+{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct drm_device *dev = encoder->dev;
+ u32 *push;
+
+ if (nv_encoder->crtc) {
+ nvd0_crtc_prepare(nv_encoder->crtc);
+
+ push = evo_wait(dev, 0, 4);
+ if (push) {
+ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1);
+ evo_data(push, 0x00000000);
+ evo_mthd(push, 0x0080, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, dev, 0);
+ }
+
+ nv_encoder->crtc = NULL;
+ }
+}
+
+static enum drm_connector_status
+nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+ enum drm_connector_status status = connector_status_disconnected;
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct drm_device *dev = encoder->dev;
+ int or = nv_encoder->or;
+ u32 load;
+
+ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000);
+ udelay(9500);
+ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000);
+
+ load = nv_rd32(dev, 0x61a00c + (or * 0x800));
+ if ((load & 0x38000000) == 0x38000000)
+ status = connector_status_connected;
+
+ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000);
+ return status;
+}
+
+static void
+nvd0_dac_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+ kfree(encoder);
+}
+
+static const struct drm_encoder_helper_funcs nvd0_dac_hfunc = {
+ .dpms = nvd0_dac_dpms,
+ .mode_fixup = nvd0_dac_mode_fixup,
+ .prepare = nvd0_dac_prepare,
+ .commit = nvd0_dac_commit,
+ .mode_set = nvd0_dac_mode_set,
+ .disable = nvd0_dac_disconnect,
+ .get_crtc = nvd0_display_crtc_get,
+ .detect = nvd0_dac_detect
+};
+
+static const struct drm_encoder_funcs nvd0_dac_func = {
+ .destroy = nvd0_dac_destroy,
+};
+
+static int
+nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe)
+{
+ struct drm_device *dev = connector->dev;
+ struct nouveau_encoder *nv_encoder;
+ struct drm_encoder *encoder;
+
+ nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+ if (!nv_encoder)
+ return -ENOMEM;
+ nv_encoder->dcb = dcbe;
+ nv_encoder->or = ffs(dcbe->or) - 1;
+
+ encoder = to_drm_encoder(nv_encoder);
+ encoder->possible_crtcs = dcbe->heads;
+ encoder->possible_clones = 0;
+ drm_encoder_init(dev, encoder, &nvd0_dac_func, DRM_MODE_ENCODER_DAC);
+ drm_encoder_helper_add(encoder, &nvd0_dac_hfunc);
+
+ drm_mode_connector_attach_encoder(connector, encoder);
+ return 0;
+}
+
+/******************************************************************************
+ * SOR
+ *****************************************************************************/
+static void
+nvd0_sor_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct drm_device *dev = encoder->dev;
+ struct drm_encoder *partner;
+ int or = nv_encoder->or;
+ u32 dpms_ctrl;
+
+ nv_encoder->last_dpms = mode;
+
+ list_for_each_entry(partner, &dev->mode_config.encoder_list, head) {
+ struct nouveau_encoder *nv_partner = nouveau_encoder(partner);
+
+ if (partner->encoder_type != DRM_MODE_ENCODER_TMDS)
+ continue;
+
+ if (nv_partner != nv_encoder &&
+ nv_partner->dcb->or == nv_encoder->or) {
+ if (nv_partner->last_dpms == DRM_MODE_DPMS_ON)
+ return;
+ break;
+ }
+ }
+
+ dpms_ctrl = (mode == DRM_MODE_DPMS_ON);
+ dpms_ctrl |= 0x80000000;
+
+ nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
+ nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl);
+ nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
+ nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000);
+}
+
+static bool
+nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nouveau_connector *nv_connector;
+
+ nv_connector = nouveau_encoder_connector_get(nv_encoder);
+ if (nv_connector && nv_connector->native_mode) {
+ if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
+ int id = adjusted_mode->base.id;
+ *adjusted_mode = *nv_connector->native_mode;
+ adjusted_mode->base.id = id;
+ }
+ }
+
+ return true;
+}
+
+static void
+nvd0_sor_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_sor_commit(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
+ struct drm_display_mode *mode)
+{
+ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+ struct nouveau_connector *nv_connector;
+ struct nvbios *bios = &dev_priv->vbios;
+ u32 mode_ctrl = (1 << nv_crtc->index);
+ u32 *push, or_config;
+
+ nv_connector = nouveau_encoder_connector_get(nv_encoder);
+ switch (nv_encoder->dcb->type) {
+ case OUTPUT_TMDS:
+ if (nv_encoder->dcb->sorconf.link & 1) {
+ if (mode->clock < 165000)
+ mode_ctrl |= 0x00000100;
+ else
+ mode_ctrl |= 0x00000500;
+ } else {
+ mode_ctrl |= 0x00000200;
+ }
+
+ or_config = (mode_ctrl & 0x00000f00) >> 8;
+ if (mode->clock >= 165000)
+ or_config |= 0x0100;
+ break;
+ case OUTPUT_LVDS:
+ or_config = (mode_ctrl & 0x00000f00) >> 8;
+ if (bios->fp_no_ddc) {
+ if (bios->fp.dual_link)
+ or_config |= 0x0100;
+ if (bios->fp.if_is_24bit)
+ or_config |= 0x0200;
+ } else {
+ if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) {
+ if (((u8 *)nv_connector->edid)[121] == 2)
+ or_config |= 0x0100;
+ } else
+ if (mode->clock >= bios->fp.duallink_transition_clk) {
+ or_config |= 0x0100;
+ }
+
+ if (or_config & 0x0100) {
+ if (bios->fp.strapless_is_24bit & 2)
+ or_config |= 0x0200;
+ } else {
+ if (bios->fp.strapless_is_24bit & 1)
+ or_config |= 0x0200;
+ }
+
+ if (nv_connector->base.display_info.bpc == 8)
+ or_config |= 0x0200;
+
+ }
+ break;
+ default:
+ BUG_ON(1);
+ break;
+ }
+
+ nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON);
+
+ push = evo_wait(encoder->dev, 0, 4);
+ if (push) {
+ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2);
+ evo_data(push, mode_ctrl);
+ evo_data(push, or_config);
+ evo_kick(push, encoder->dev, 0);
+ }
+
+ nv_encoder->crtc = encoder->crtc;
+}
+
+static void
+nvd0_sor_disconnect(struct drm_encoder *encoder)
+{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct drm_device *dev = encoder->dev;
+ u32 *push;
+
+ if (nv_encoder->crtc) {
+ nvd0_crtc_prepare(nv_encoder->crtc);
+
+ push = evo_wait(dev, 0, 4);
+ if (push) {
+ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1);
+ evo_data(push, 0x00000000);
+ evo_mthd(push, 0x0080, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, dev, 0);
+ }
+
+ nv_encoder->crtc = NULL;
+ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
+ }
+}
+
+static void
+nvd0_sor_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+ kfree(encoder);
+}
+
+static const struct drm_encoder_helper_funcs nvd0_sor_hfunc = {
+ .dpms = nvd0_sor_dpms,
+ .mode_fixup = nvd0_sor_mode_fixup,
+ .prepare = nvd0_sor_prepare,
+ .commit = nvd0_sor_commit,
+ .mode_set = nvd0_sor_mode_set,
+ .disable = nvd0_sor_disconnect,
+ .get_crtc = nvd0_display_crtc_get,
+};
+
+static const struct drm_encoder_funcs nvd0_sor_func = {
+ .destroy = nvd0_sor_destroy,
+};
+
+static int
+nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe)
+{
+ struct drm_device *dev = connector->dev;
+ struct nouveau_encoder *nv_encoder;
+ struct drm_encoder *encoder;
+
+ nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+ if (!nv_encoder)
+ return -ENOMEM;
+ nv_encoder->dcb = dcbe;
+ nv_encoder->or = ffs(dcbe->or) - 1;
+ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
+
+ encoder = to_drm_encoder(nv_encoder);
+ encoder->possible_crtcs = dcbe->heads;
+ encoder->possible_clones = 0;
+ drm_encoder_init(dev, encoder, &nvd0_sor_func, DRM_MODE_ENCODER_TMDS);
+ drm_encoder_helper_add(encoder, &nvd0_sor_hfunc);
+
+ drm_mode_connector_attach_encoder(connector, encoder);
+ return 0;
+}
+
+/******************************************************************************
+ * IRQ
+ *****************************************************************************/
+static struct dcb_entry *
+lookup_dcb(struct drm_device *dev, int id, u32 mc)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ int type, or, i;
+
+ if (id < 4) {
+ type = OUTPUT_ANALOG;
+ or = id;
+ } else {
+ switch (mc & 0x00000f00) {
+ case 0x00000000: type = OUTPUT_LVDS; break;
+ case 0x00000100: type = OUTPUT_TMDS; break;
+ case 0x00000200: type = OUTPUT_TMDS; break;
+ case 0x00000500: type = OUTPUT_TMDS; break;
+ default:
+ NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc);
+ return NULL;
+ }
+
+ or = id - 4;
+ }
+
+ for (i = 0; i < dev_priv->vbios.dcb.entries; i++) {
+ struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i];
+ if (dcb->type == type && (dcb->or & (1 << or)))
+ return dcb;
+ }
+
+ NV_ERROR(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc);
+ return NULL;
+}
+
+static void
+nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask)
+{
+ struct dcb_entry *dcb;
+ int i;
+
+ for (i = 0; mask && i < 8; i++) {
+ u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20));
+ if (!(mcc & (1 << crtc)))
+ continue;
+
+ dcb = lookup_dcb(dev, i, mcc);
+ if (!dcb)
+ continue;
+
+ nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc);
+ }
+
+ nv_wr32(dev, 0x6101d4, 0x00000000);
+ nv_wr32(dev, 0x6109d4, 0x00000000);
+ nv_wr32(dev, 0x6101d0, 0x80000000);
+}
+
+static void
+nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask)
+{
+ struct dcb_entry *dcb;
+ u32 or, tmp, pclk;
+ int i;
+
+ for (i = 0; mask && i < 8; i++) {
+ u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20));
+ if (!(mcc & (1 << crtc)))
+ continue;
+
+ dcb = lookup_dcb(dev, i, mcc);
+ if (!dcb)
+ continue;
+
+ nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc);
+ }
+
+ pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000;
+ if (mask & 0x00010000) {
+ nv50_crtc_set_clock(dev, crtc, pclk);
+ }
+
+ for (i = 0; mask && i < 8; i++) {
+ u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20));
+ u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20));
+ if (!(mcp & (1 << crtc)))
+ continue;
+
+ dcb = lookup_dcb(dev, i, mcp);
+ if (!dcb)
+ continue;
+ or = ffs(dcb->or) - 1;
+
+ nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc);
+
+ nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000);
+ switch (dcb->type) {
+ case OUTPUT_ANALOG:
+ nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000);
+ break;
+ case OUTPUT_TMDS:
+ case OUTPUT_LVDS:
+ if (cfg & 0x00000100)
+ tmp = 0x00000101;
+ else
+ tmp = 0x00000000;
+
+ nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ nv_wr32(dev, 0x6101d4, 0x00000000);
+ nv_wr32(dev, 0x6109d4, 0x00000000);
+ nv_wr32(dev, 0x6101d0, 0x80000000);
+}
+
+static void
+nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask)
+{
+ struct dcb_entry *dcb;
+ int pclk, i;
+
+ pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000;
+
+ for (i = 0; mask && i < 8; i++) {
+ u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20));
+ u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20));
+ if (!(mcp & (1 << crtc)))
+ continue;
+
+ dcb = lookup_dcb(dev, i, mcp);
+ if (!dcb)
+ continue;
+
+ nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc);
+ }
+
+ nv_wr32(dev, 0x6101d4, 0x00000000);
+ nv_wr32(dev, 0x6109d4, 0x00000000);
+ nv_wr32(dev, 0x6101d0, 0x80000000);
+}
+
+static void
+nvd0_display_bh(unsigned long data)
+{
+ struct drm_device *dev = (struct drm_device *)data;
+ struct nvd0_display *disp = nvd0_display(dev);
+ u32 mask, crtc;
+ int i;
+
+ if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) {
+ NV_INFO(dev, "PDISP: modeset req %d\n", disp->modeset);
+ NV_INFO(dev, " STAT: 0x%08x 0x%08x 0x%08x\n",
+ nv_rd32(dev, 0x6101d0),
+ nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4));
+ for (i = 0; i < 8; i++) {
+ NV_INFO(dev, " %s%d: 0x%08x 0x%08x\n",
+ i < 4 ? "DAC" : "SOR", i,
+ nv_rd32(dev, 0x640180 + (i * 0x20)),
+ nv_rd32(dev, 0x660180 + (i * 0x20)));
+ }
+ }
+
+ mask = nv_rd32(dev, 0x6101d4);
+ crtc = 0;
+ if (!mask) {
+ mask = nv_rd32(dev, 0x6109d4);
+ crtc = 1;
+ }
+
+ if (disp->modeset & 0x00000001)
+ nvd0_display_unk1_handler(dev, crtc, mask);
+ if (disp->modeset & 0x00000002)
+ nvd0_display_unk2_handler(dev, crtc, mask);
+ if (disp->modeset & 0x00000004)
+ nvd0_display_unk4_handler(dev, crtc, mask);
+}
+
+static void
+nvd0_display_intr(struct drm_device *dev)
+{
+ struct nvd0_display *disp = nvd0_display(dev);
+ u32 intr = nv_rd32(dev, 0x610088);
+
+ if (intr & 0x00000002) {
+ u32 stat = nv_rd32(dev, 0x61009c);
+ int chid = ffs(stat) - 1;
+ if (chid >= 0) {
+ u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12));
+ u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12));
+ u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12));
+
+ NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x "
+ "0x%08x 0x%08x\n",
+ chid, (mthd & 0x0000ffc), data, mthd, unkn);
+ nv_wr32(dev, 0x61009c, (1 << chid));
+ nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000);
+ }
+
+ intr &= ~0x00000002;
+ }
+
+ if (intr & 0x00100000) {
+ u32 stat = nv_rd32(dev, 0x6100ac);
+
+ if (stat & 0x00000007) {
+ disp->modeset = stat;
+ tasklet_schedule(&disp->tasklet);
+
+ nv_wr32(dev, 0x6100ac, (stat & 0x00000007));
+ stat &= ~0x00000007;
+ }
+
+ if (stat) {
+ NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat);
+ nv_wr32(dev, 0x6100ac, stat);
+ }
+
+ intr &= ~0x00100000;
+ }
+
+ if (intr & 0x01000000) {
+ u32 stat = nv_rd32(dev, 0x6100bc);
+ nv_wr32(dev, 0x6100bc, stat);
+ intr &= ~0x01000000;
+ }
+
+ if (intr & 0x02000000) {
+ u32 stat = nv_rd32(dev, 0x6108bc);
+ nv_wr32(dev, 0x6108bc, stat);
+ intr &= ~0x02000000;
+ }
+
+ if (intr)
+ NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr);
+}
+
+/******************************************************************************
+ * Init
+ *****************************************************************************/
+static void
+nvd0_display_fini(struct drm_device *dev)
+{
+ int i;
+
+ /* fini cursors */
+ for (i = 14; i >= 13; i--) {
+ if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001))
+ continue;
+
+ nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000);
+ nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000);
+ nv_mask(dev, 0x610090, 1 << i, 0x00000000);
+ nv_mask(dev, 0x6100a0, 1 << i, 0x00000000);
+ }
+
+ /* fini master */
+ if (nv_rd32(dev, 0x610490) & 0x00000010) {
+ nv_mask(dev, 0x610490, 0x00000010, 0x00000000);
+ nv_mask(dev, 0x610490, 0x00000003, 0x00000000);
+ nv_wait(dev, 0x610490, 0x80000000, 0x00000000);
+ nv_mask(dev, 0x610090, 0x00000001, 0x00000000);
+ nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000);
+ }
+}
+
+int
+nvd0_display_init(struct drm_device *dev)
+{
+ struct nvd0_display *disp = nvd0_display(dev);
+ u32 *push;
+ int i;
+
+ if (nv_rd32(dev, 0x6100ac) & 0x00000100) {
+ nv_wr32(dev, 0x6100ac, 0x00000100);
+ nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000);
+ if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) {
+ NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n",
+ nv_rd32(dev, 0x6194e8));
+ return -EBUSY;
+ }
+ }
+
+ /* nfi what these are exactly, i do know that SOR_MODE_CTRL won't
+ * work at all unless you do the SOR part below.
+ */
+ for (i = 0; i < 3; i++) {
+ u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800));
+ nv_wr32(dev, 0x6101c0 + (i * 0x800), dac);
+ }
+
+ for (i = 0; i < 4; i++) {
+ u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800));
+ nv_wr32(dev, 0x6301c4 + (i * 0x800), sor);
+ }
+
+ for (i = 0; i < 2; i++) {
+ u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800));
+ u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800));
+ u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800));
+ nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0);
+ nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1);
+ nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2);
+ }
+
+ /* point at our hash table / objects, enable interrupts */
+ nv_wr32(dev, 0x610010, (disp->mem->vinst >> 8) | 9);
+ nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307);
+
+ /* init master */
+ nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3);
+ nv_wr32(dev, 0x610498, 0x00010000);
+ nv_wr32(dev, 0x61049c, 0x00000001);
+ nv_mask(dev, 0x610490, 0x00000010, 0x00000010);
+ nv_wr32(dev, 0x640000, 0x00000000);
+ nv_wr32(dev, 0x610490, 0x01000013);
+ if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) {
+ NV_ERROR(dev, "PDISP: master 0x%08x\n",
+ nv_rd32(dev, 0x610490));
+ return -EBUSY;
+ }
+ nv_mask(dev, 0x610090, 0x00000001, 0x00000001);
+ nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001);
+
+ /* init cursors */
+ for (i = 13; i <= 14; i++) {
+ nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001);
+ if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) {
+ NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i,
+ nv_rd32(dev, 0x610490 + (i * 0x10)));
+ return -EBUSY;
+ }
+
+ nv_mask(dev, 0x610090, 1 << i, 1 << i);
+ nv_mask(dev, 0x6100a0, 1 << i, 1 << i);
+ }
+
+ push = evo_wait(dev, 0, 32);
+ if (!push)
+ return -EBUSY;
+ evo_mthd(push, 0x0088, 1);
+ evo_data(push, NvEvoSync);
+ evo_mthd(push, 0x0084, 1);
+ evo_data(push, 0x00000000);
+ evo_mthd(push, 0x0084, 1);
+ evo_data(push, 0x80000000);
+ evo_mthd(push, 0x008c, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, dev, 0);
+
+ return 0;
+}
+
+void
+nvd0_display_destroy(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nvd0_display *disp = nvd0_display(dev);
+ struct pci_dev *pdev = dev->pdev;
+
+ nvd0_display_fini(dev);
+
+ pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle);
+ nouveau_gpuobj_ref(NULL, &disp->mem);
+ nouveau_irq_unregister(dev, 26);
+
+ dev_priv->engine.display.priv = NULL;
+ kfree(disp);
+}
+
+int
+nvd0_display_create(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+ struct dcb_table *dcb = &dev_priv->vbios.dcb;
+ struct drm_connector *connector, *tmp;
+ struct pci_dev *pdev = dev->pdev;
+ struct nvd0_display *disp;
+ struct dcb_entry *dcbe;
+ int ret, i;
+
+ disp = kzalloc(sizeof(*disp), GFP_KERNEL);
+ if (!disp)
+ return -ENOMEM;
+ dev_priv->engine.display.priv = disp;
+
+ /* create crtc objects to represent the hw heads */
+ for (i = 0; i < 2; i++) {
+ ret = nvd0_crtc_create(dev, i);
+ if (ret)
+ goto out;
+ }
+
+ /* create encoder/connector objects based on VBIOS DCB table */
+ for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) {
+ connector = nouveau_connector_create(dev, dcbe->connector);
+ if (IS_ERR(connector))
+ continue;
+
+ if (dcbe->location != DCB_LOC_ON_CHIP) {
+ NV_WARN(dev, "skipping off-chip encoder %d/%d\n",
+ dcbe->type, ffs(dcbe->or) - 1);
+ continue;
+ }
+
+ switch (dcbe->type) {
+ case OUTPUT_TMDS:
+ case OUTPUT_LVDS:
+ nvd0_sor_create(connector, dcbe);
+ break;
+ case OUTPUT_ANALOG:
+ nvd0_dac_create(connector, dcbe);
+ break;
+ default:
+ NV_WARN(dev, "skipping unsupported encoder %d/%d\n",
+ dcbe->type, ffs(dcbe->or) - 1);
+ continue;
+ }
+ }
+
+ /* cull any connectors we created that don't have an encoder */
+ list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) {
+ if (connector->encoder_ids[0])
+ continue;
+
+ NV_WARN(dev, "%s has no encoders, removing\n",
+ drm_get_connector_name(connector));
+ connector->funcs->destroy(connector);
+ }
+
+ /* setup interrupt handling */
+ tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev);
+ nouveau_irq_register(dev, 26, nvd0_display_intr);
+
+ /* hash table and dma objects for the memory areas we care about */
+ ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000,
+ NVOBJ_FLAG_ZERO_ALLOC, &disp->mem);
+ if (ret)
+ goto out;
+
+ nv_wo32(disp->mem, 0x1000, 0x00000049);
+ nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8);
+ nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8);
+ nv_wo32(disp->mem, 0x100c, 0x00000000);
+ nv_wo32(disp->mem, 0x1010, 0x00000000);
+ nv_wo32(disp->mem, 0x1014, 0x00000000);
+ nv_wo32(disp->mem, 0x0000, NvEvoSync);
+ nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001);
+
+ nv_wo32(disp->mem, 0x1020, 0x00000049);
+ nv_wo32(disp->mem, 0x1024, 0x00000000);
+ nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8);
+ nv_wo32(disp->mem, 0x102c, 0x00000000);
+ nv_wo32(disp->mem, 0x1030, 0x00000000);
+ nv_wo32(disp->mem, 0x1034, 0x00000000);
+ nv_wo32(disp->mem, 0x0008, NvEvoVRAM);
+ nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001);
+
+ nv_wo32(disp->mem, 0x1040, 0x00000009);
+ nv_wo32(disp->mem, 0x1044, 0x00000000);
+ nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8);
+ nv_wo32(disp->mem, 0x104c, 0x00000000);
+ nv_wo32(disp->mem, 0x1050, 0x00000000);
+ nv_wo32(disp->mem, 0x1054, 0x00000000);
+ nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP);
+ nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001);
+
+ nv_wo32(disp->mem, 0x1060, 0x0fe00009);
+ nv_wo32(disp->mem, 0x1064, 0x00000000);
+ nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8);
+ nv_wo32(disp->mem, 0x106c, 0x00000000);
+ nv_wo32(disp->mem, 0x1070, 0x00000000);
+ nv_wo32(disp->mem, 0x1074, 0x00000000);
+ nv_wo32(disp->mem, 0x0018, NvEvoFB32);
+ nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001);
+
+ pinstmem->flush(dev);
+
+ /* push buffers for evo channels */
+ disp->evo[0].ptr =
+ pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle);
+ if (!disp->evo[0].ptr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = nvd0_display_init(dev);
+ if (ret)
+ goto out;
+
+out:
+ if (ret)
+ nvd0_display_destroy(dev);
+ return ret;
+}
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index c4ffa14fb2f4..ed406e8404a3 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -39,7 +39,7 @@
static void evergreen_gpu_init(struct radeon_device *rdev);
void evergreen_fini(struct radeon_device *rdev);
-static void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
+void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
{
@@ -935,6 +935,9 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev)
WREG32(VM_CONTEXT1_CNTL, 0);
evergreen_pcie_gart_tlb_flush(rdev);
+ DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+ (unsigned)(rdev->mc.gtt_size >> 20),
+ (unsigned long long)rdev->gart.table_addr);
rdev->gart.ready = true;
return 0;
}
@@ -2586,7 +2589,7 @@ int evergreen_irq_set(struct radeon_device *rdev)
return 0;
}
-static inline void evergreen_irq_ack(struct radeon_device *rdev)
+static void evergreen_irq_ack(struct radeon_device *rdev)
{
u32 tmp;
@@ -2697,7 +2700,7 @@ void evergreen_irq_suspend(struct radeon_device *rdev)
r600_rlc_stop(rdev);
}
-static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
+static u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
{
u32 wptr, tmp;
@@ -3003,8 +3006,7 @@ static int evergreen_startup(struct radeon_device *rdev)
int r;
/* enable pcie gen2 link */
- if (!ASIC_IS_DCE5(rdev))
- evergreen_pcie_gen2_enable(rdev);
+ evergreen_pcie_gen2_enable(rdev);
if (ASIC_IS_DCE5(rdev)) {
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
@@ -3041,7 +3043,7 @@ static int evergreen_startup(struct radeon_device *rdev)
r = evergreen_blit_init(rdev);
if (r) {
- evergreen_blit_fini(rdev);
+ r600_blit_fini(rdev);
rdev->asic->copy = NULL;
dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
}
@@ -3107,45 +3109,14 @@ int evergreen_resume(struct radeon_device *rdev)
int evergreen_suspend(struct radeon_device *rdev)
{
- int r;
-
/* FIXME: we should wait for ring to be empty */
r700_cp_stop(rdev);
rdev->cp.ready = false;
evergreen_irq_suspend(rdev);
radeon_wb_disable(rdev);
evergreen_pcie_gart_disable(rdev);
+ r600_blit_suspend(rdev);
- /* unpin shaders bo */
- r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
- if (likely(r == 0)) {
- radeon_bo_unpin(rdev->r600_blit.shader_obj);
- radeon_bo_unreserve(rdev->r600_blit.shader_obj);
- }
-
- return 0;
-}
-
-int evergreen_copy_blit(struct radeon_device *rdev,
- uint64_t src_offset,
- uint64_t dst_offset,
- unsigned num_gpu_pages,
- struct radeon_fence *fence)
-{
- int r;
-
- mutex_lock(&rdev->r600_blit.mutex);
- rdev->r600_blit.vb_ib = NULL;
- r = evergreen_blit_prepare_copy(rdev, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
- if (r) {
- if (rdev->r600_blit.vb_ib)
- radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
- mutex_unlock(&rdev->r600_blit.mutex);
- return r;
- }
- evergreen_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
- evergreen_blit_done_copy(rdev, fence);
- mutex_unlock(&rdev->r600_blit.mutex);
return 0;
}
@@ -3257,7 +3228,7 @@ int evergreen_init(struct radeon_device *rdev)
void evergreen_fini(struct radeon_device *rdev)
{
- evergreen_blit_fini(rdev);
+ r600_blit_fini(rdev);
r700_cp_fini(rdev);
r600_irq_fini(rdev);
radeon_wb_fini(rdev);
@@ -3273,7 +3244,7 @@ void evergreen_fini(struct radeon_device *rdev)
rdev->bios = NULL;
}
-static void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
+void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
{
u32 link_width_cntl, speed_cntl;
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c
index 2eb251858e72..dcf11bbc06d9 100644
--- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c
+++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c
@@ -56,7 +56,9 @@ set_render_target(struct radeon_device *rdev, int format,
if (h < 8)
h = 8;
- cb_color_info = ((format << 2) | (1 << 24) | (1 << 8));
+ cb_color_info = CB_FORMAT(format) |
+ CB_SOURCE_FORMAT(CB_SF_EXPORT_NORM) |
+ CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
pitch = (w / 8) - 1;
slice = ((w * h) / 64) - 1;
@@ -67,7 +69,7 @@ set_render_target(struct radeon_device *rdev, int format,
radeon_ring_write(rdev, slice);
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, cb_color_info);
- radeon_ring_write(rdev, (1 << 4));
+ radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, (w - 1) | ((h - 1) << 16));
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, 0);
@@ -133,12 +135,16 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr)
u32 sq_vtx_constant_word2, sq_vtx_constant_word3;
/* high addr, stride */
- sq_vtx_constant_word2 = ((upper_32_bits(gpu_addr) & 0xff) | (16 << 8));
+ sq_vtx_constant_word2 = SQ_VTXC_BASE_ADDR_HI(upper_32_bits(gpu_addr) & 0xff) |
+ SQ_VTXC_STRIDE(16);
#ifdef __BIG_ENDIAN
- sq_vtx_constant_word2 |= (2 << 30);
+ sq_vtx_constant_word2 |= SQ_VTXC_ENDIAN_SWAP(SQ_ENDIAN_8IN32);
#endif
/* xyzw swizzles */
- sq_vtx_constant_word3 = (0 << 3) | (1 << 6) | (2 << 9) | (3 << 12);
+ sq_vtx_constant_word3 = SQ_VTCX_SEL_X(SQ_SEL_X) |
+ SQ_VTCX_SEL_Y(SQ_SEL_Y) |
+ SQ_VTCX_SEL_Z(SQ_SEL_Z) |
+ SQ_VTCX_SEL_W(SQ_SEL_W);
radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8));
radeon_ring_write(rdev, 0x580);
@@ -149,7 +155,7 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr)
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, 0);
- radeon_ring_write(rdev, SQ_TEX_VTX_VALID_BUFFER << 30);
+ radeon_ring_write(rdev, S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_BUFFER));
if ((rdev->family == CHIP_CEDAR) ||
(rdev->family == CHIP_PALM) ||
@@ -176,14 +182,19 @@ set_tex_resource(struct radeon_device *rdev,
if (h < 1)
h = 1;
- sq_tex_resource_word0 = (1 << 0); /* 2D */
+ sq_tex_resource_word0 = TEX_DIM(SQ_TEX_DIM_2D);
sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 6) |
((w - 1) << 18));
- sq_tex_resource_word1 = ((h - 1) << 0) | (1 << 28);
+ sq_tex_resource_word1 = ((h - 1) << 0) |
+ TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
/* xyzw swizzles */
- sq_tex_resource_word4 = (0 << 16) | (1 << 19) | (2 << 22) | (3 << 25);
+ sq_tex_resource_word4 = TEX_DST_SEL_X(SQ_SEL_X) |
+ TEX_DST_SEL_Y(SQ_SEL_Y) |
+ TEX_DST_SEL_Z(SQ_SEL_Z) |
+ TEX_DST_SEL_W(SQ_SEL_W);
- sq_tex_resource_word7 = format | (SQ_TEX_VTX_VALID_TEXTURE << 30);
+ sq_tex_resource_word7 = format |
+ S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_TEXTURE);
radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8));
radeon_ring_write(rdev, 0);
@@ -584,31 +595,6 @@ set_default_state(struct radeon_device *rdev)
}
-static inline uint32_t i2f(uint32_t input)
-{
- u32 result, i, exponent, fraction;
-
- if ((input & 0x3fff) == 0)
- result = 0; /* 0 is a special case */
- else {
- exponent = 140; /* exponent biased by 127; */
- fraction = (input & 0x3fff) << 10; /* cheat and only
- handle numbers below 2^^15 */
- for (i = 0; i < 14; i++) {
- if (fraction & 0x800000)
- break;
- else {
- fraction = fraction << 1; /* keep
- shifting left until top bit = 1 */
- exponent = exponent - 1;
- }
- }
- result = exponent << 23 | (fraction & 0x7fffff); /* mask
- off top bit; assumed 1 */
- }
- return result;
-}
-
int evergreen_blit_init(struct radeon_device *rdev)
{
u32 obj_size;
@@ -617,6 +603,24 @@ int evergreen_blit_init(struct radeon_device *rdev)
u32 packet2s[16];
int num_packet2s = 0;
+ rdev->r600_blit.primitives.set_render_target = set_render_target;
+ rdev->r600_blit.primitives.cp_set_surface_sync = cp_set_surface_sync;
+ rdev->r600_blit.primitives.set_shaders = set_shaders;
+ rdev->r600_blit.primitives.set_vtx_resource = set_vtx_resource;
+ rdev->r600_blit.primitives.set_tex_resource = set_tex_resource;
+ rdev->r600_blit.primitives.set_scissors = set_scissors;
+ rdev->r600_blit.primitives.draw_auto = draw_auto;
+ rdev->r600_blit.primitives.set_default_state = set_default_state;
+
+ rdev->r600_blit.ring_size_common = 55; /* shaders + def state */
+ rdev->r600_blit.ring_size_common += 10; /* fence emit for VB IB */
+ rdev->r600_blit.ring_size_common += 5; /* done copy */
+ rdev->r600_blit.ring_size_common += 10; /* fence emit for done copy */
+
+ rdev->r600_blit.ring_size_per_loop = 74;
+
+ rdev->r600_blit.max_dim = 16384;
+
/* pin copy shader into vram if already initialized */
if (rdev->r600_blit.shader_obj)
goto done;
@@ -712,277 +716,3 @@ done:
radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
return 0;
}
-
-void evergreen_blit_fini(struct radeon_device *rdev)
-{
- int r;
-
- radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
- if (rdev->r600_blit.shader_obj == NULL)
- return;
- /* If we can't reserve the bo, unref should be enough to destroy
- * it when it becomes idle.
- */
- r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
- if (!r) {
- radeon_bo_unpin(rdev->r600_blit.shader_obj);
- radeon_bo_unreserve(rdev->r600_blit.shader_obj);
- }
- radeon_bo_unref(&rdev->r600_blit.shader_obj);
-}
-
-static int evergreen_vb_ib_get(struct radeon_device *rdev)
-{
- int r;
- r = radeon_ib_get(rdev, &rdev->r600_blit.vb_ib);
- if (r) {
- DRM_ERROR("failed to get IB for vertex buffer\n");
- return r;
- }
-
- rdev->r600_blit.vb_total = 64*1024;
- rdev->r600_blit.vb_used = 0;
- return 0;
-}
-
-static void evergreen_vb_ib_put(struct radeon_device *rdev)
-{
- radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence);
- radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
-}
-
-int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
-{
- int r;
- int ring_size, line_size;
- int max_size;
- /* loops of emits + fence emit possible */
- int dwords_per_loop = 74, num_loops;
-
- r = evergreen_vb_ib_get(rdev);
- if (r)
- return r;
-
- /* 8 bpp vs 32 bpp for xfer unit */
- if (size_bytes & 3)
- line_size = 8192;
- else
- line_size = 8192 * 4;
-
- max_size = 8192 * line_size;
-
- /* major loops cover the max size transfer */
- num_loops = ((size_bytes + max_size) / max_size);
- /* minor loops cover the extra non aligned bits */
- num_loops += ((size_bytes % line_size) ? 1 : 0);
- /* calculate number of loops correctly */
- ring_size = num_loops * dwords_per_loop;
- /* set default + shaders */
- ring_size += 55; /* shaders + def state */
- ring_size += 10; /* fence emit for VB IB */
- ring_size += 5; /* done copy */
- ring_size += 10; /* fence emit for done copy */
- r = radeon_ring_lock(rdev, ring_size);
- if (r)
- return r;
-
- set_default_state(rdev); /* 36 */
- set_shaders(rdev); /* 16 */
- return 0;
-}
-
-void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence)
-{
- int r;
-
- if (rdev->r600_blit.vb_ib)
- evergreen_vb_ib_put(rdev);
-
- if (fence)
- r = radeon_fence_emit(rdev, fence);
-
- radeon_ring_unlock_commit(rdev);
-}
-
-void evergreen_kms_blit_copy(struct radeon_device *rdev,
- u64 src_gpu_addr, u64 dst_gpu_addr,
- int size_bytes)
-{
- int max_bytes;
- u64 vb_gpu_addr;
- u32 *vb;
-
- DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr,
- size_bytes, rdev->r600_blit.vb_used);
- vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
- if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
- max_bytes = 8192;
-
- while (size_bytes) {
- int cur_size = size_bytes;
- int src_x = src_gpu_addr & 255;
- int dst_x = dst_gpu_addr & 255;
- int h = 1;
- src_gpu_addr = src_gpu_addr & ~255ULL;
- dst_gpu_addr = dst_gpu_addr & ~255ULL;
-
- if (!src_x && !dst_x) {
- h = (cur_size / max_bytes);
- if (h > 8192)
- h = 8192;
- if (h == 0)
- h = 1;
- else
- cur_size = max_bytes;
- } else {
- if (cur_size > max_bytes)
- cur_size = max_bytes;
- if (cur_size > (max_bytes - dst_x))
- cur_size = (max_bytes - dst_x);
- if (cur_size > (max_bytes - src_x))
- cur_size = (max_bytes - src_x);
- }
-
- if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
- WARN_ON(1);
- }
-
- vb[0] = i2f(dst_x);
- vb[1] = 0;
- vb[2] = i2f(src_x);
- vb[3] = 0;
-
- vb[4] = i2f(dst_x);
- vb[5] = i2f(h);
- vb[6] = i2f(src_x);
- vb[7] = i2f(h);
-
- vb[8] = i2f(dst_x + cur_size);
- vb[9] = i2f(h);
- vb[10] = i2f(src_x + cur_size);
- vb[11] = i2f(h);
-
- /* src 10 */
- set_tex_resource(rdev, FMT_8,
- src_x + cur_size, h, src_x + cur_size,
- src_gpu_addr);
-
- /* 5 */
- cp_set_surface_sync(rdev,
- PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
-
- /* dst 17 */
- set_render_target(rdev, COLOR_8,
- dst_x + cur_size, h,
- dst_gpu_addr);
-
- /* scissors 12 */
- set_scissors(rdev, dst_x, 0, dst_x + cur_size, h);
-
- /* 15 */
- vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
- set_vtx_resource(rdev, vb_gpu_addr);
-
- /* draw 10 */
- draw_auto(rdev);
-
- /* 5 */
- cp_set_surface_sync(rdev,
- PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
- cur_size * h, dst_gpu_addr);
-
- vb += 12;
- rdev->r600_blit.vb_used += 12 * 4;
-
- src_gpu_addr += cur_size * h;
- dst_gpu_addr += cur_size * h;
- size_bytes -= cur_size * h;
- }
- } else {
- max_bytes = 8192 * 4;
-
- while (size_bytes) {
- int cur_size = size_bytes;
- int src_x = (src_gpu_addr & 255);
- int dst_x = (dst_gpu_addr & 255);
- int h = 1;
- src_gpu_addr = src_gpu_addr & ~255ULL;
- dst_gpu_addr = dst_gpu_addr & ~255ULL;
-
- if (!src_x && !dst_x) {
- h = (cur_size / max_bytes);
- if (h > 8192)
- h = 8192;
- if (h == 0)
- h = 1;
- else
- cur_size = max_bytes;
- } else {
- if (cur_size > max_bytes)
- cur_size = max_bytes;
- if (cur_size > (max_bytes - dst_x))
- cur_size = (max_bytes - dst_x);
- if (cur_size > (max_bytes - src_x))
- cur_size = (max_bytes - src_x);
- }
-
- if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
- WARN_ON(1);
- }
-
- vb[0] = i2f(dst_x / 4);
- vb[1] = 0;
- vb[2] = i2f(src_x / 4);
- vb[3] = 0;
-
- vb[4] = i2f(dst_x / 4);
- vb[5] = i2f(h);
- vb[6] = i2f(src_x / 4);
- vb[7] = i2f(h);
-
- vb[8] = i2f((dst_x + cur_size) / 4);
- vb[9] = i2f(h);
- vb[10] = i2f((src_x + cur_size) / 4);
- vb[11] = i2f(h);
-
- /* src 10 */
- set_tex_resource(rdev, FMT_8_8_8_8,
- (src_x + cur_size) / 4,
- h, (src_x + cur_size) / 4,
- src_gpu_addr);
- /* 5 */
- cp_set_surface_sync(rdev,
- PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
- /* dst 17 */
- set_render_target(rdev, COLOR_8_8_8_8,
- (dst_x + cur_size) / 4, h,
- dst_gpu_addr);
-
- /* scissors 12 */
- set_scissors(rdev, (dst_x / 4), 0, (dst_x + cur_size / 4), h);
-
- /* Vertex buffer setup 15 */
- vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
- set_vtx_resource(rdev, vb_gpu_addr);
-
- /* draw 10 */
- draw_auto(rdev);
-
- /* 5 */
- cp_set_surface_sync(rdev,
- PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
- cur_size * h, dst_gpu_addr);
-
- /* 74 ring dwords per loop */
- vb += 12;
- rdev->r600_blit.vb_used += 12 * 4;
-
- src_gpu_addr += cur_size * h;
- dst_gpu_addr += cur_size * h;
- size_bytes -= cur_size * h;
- }
- }
-}
-
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index a134790903d3..7fdfa8ea7570 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -122,12 +122,6 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track)
track->db_s_write_bo = NULL;
}
-static inline int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
-{
- /* XXX fill in */
- return 0;
-}
-
static int evergreen_cs_track_check(struct radeon_cs_parser *p)
{
struct evergreen_cs_track *track = p->track;
@@ -236,28 +230,6 @@ static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
}
/**
- * evergreen_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
- * @parser: parser structure holding parsing context.
- *
- * Check next packet is relocation packet3, do bo validation and compute
- * GPU offset using the provided start.
- **/
-static inline int evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
-{
- struct radeon_cs_packet p3reloc;
- int r;
-
- r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
- if (r) {
- return 0;
- }
- if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
- return 0;
- }
- return 1;
-}
-
-/**
* evergreen_cs_packet_next_vline() - parse userspace VLINE packet
* @parser: parser structure holding parsing context.
*
@@ -414,7 +386,7 @@ static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
* if register is safe. If register is not flag as safe this function
* will test it against a list of register needind special handling.
*/
-static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
{
struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
struct radeon_cs_reloc *reloc;
@@ -990,7 +962,7 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
* This function will check that the resource has valid field and that
* the texture and mipmap bo object are big enough to cover this resource.
*/
-static inline int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
+static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
struct radeon_bo *texture,
struct radeon_bo *mipmap)
{
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index 7363d9dec909..b937c49054d9 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -941,11 +941,15 @@
#define CB_COLOR0_SLICE 0x28c68
#define CB_COLOR0_VIEW 0x28c6c
#define CB_COLOR0_INFO 0x28c70
+# define CB_FORMAT(x) ((x) << 2)
# define CB_ARRAY_MODE(x) ((x) << 8)
# define ARRAY_LINEAR_GENERAL 0
# define ARRAY_LINEAR_ALIGNED 1
# define ARRAY_1D_TILED_THIN1 2
# define ARRAY_2D_TILED_THIN1 4
+# define CB_SOURCE_FORMAT(x) ((x) << 24)
+# define CB_SF_EXPORT_FULL 0
+# define CB_SF_EXPORT_NORM 1
#define CB_COLOR0_ATTRIB 0x28c74
#define CB_COLOR0_DIM 0x28c78
/* only CB0-7 blocks have these regs */
@@ -1107,15 +1111,53 @@
#define CB_COLOR7_CLEAR_WORD3 0x28e3c
#define SQ_TEX_RESOURCE_WORD0_0 0x30000
+# define TEX_DIM(x) ((x) << 0)
+# define SQ_TEX_DIM_1D 0
+# define SQ_TEX_DIM_2D 1
+# define SQ_TEX_DIM_3D 2
+# define SQ_TEX_DIM_CUBEMAP 3
+# define SQ_TEX_DIM_1D_ARRAY 4
+# define SQ_TEX_DIM_2D_ARRAY 5
+# define SQ_TEX_DIM_2D_MSAA 6
+# define SQ_TEX_DIM_2D_ARRAY_MSAA 7
#define SQ_TEX_RESOURCE_WORD1_0 0x30004
# define TEX_ARRAY_MODE(x) ((x) << 28)
#define SQ_TEX_RESOURCE_WORD2_0 0x30008
#define SQ_TEX_RESOURCE_WORD3_0 0x3000C
#define SQ_TEX_RESOURCE_WORD4_0 0x30010
+# define TEX_DST_SEL_X(x) ((x) << 16)
+# define TEX_DST_SEL_Y(x) ((x) << 19)
+# define TEX_DST_SEL_Z(x) ((x) << 22)
+# define TEX_DST_SEL_W(x) ((x) << 25)
+# define SQ_SEL_X 0
+# define SQ_SEL_Y 1
+# define SQ_SEL_Z 2
+# define SQ_SEL_W 3
+# define SQ_SEL_0 4
+# define SQ_SEL_1 5
#define SQ_TEX_RESOURCE_WORD5_0 0x30014
#define SQ_TEX_RESOURCE_WORD6_0 0x30018
#define SQ_TEX_RESOURCE_WORD7_0 0x3001c
+#define SQ_VTX_CONSTANT_WORD0_0 0x30000
+#define SQ_VTX_CONSTANT_WORD1_0 0x30004
+#define SQ_VTX_CONSTANT_WORD2_0 0x30008
+# define SQ_VTXC_BASE_ADDR_HI(x) ((x) << 0)
+# define SQ_VTXC_STRIDE(x) ((x) << 8)
+# define SQ_VTXC_ENDIAN_SWAP(x) ((x) << 30)
+# define SQ_ENDIAN_NONE 0
+# define SQ_ENDIAN_8IN16 1
+# define SQ_ENDIAN_8IN32 2
+#define SQ_VTX_CONSTANT_WORD3_0 0x3000C
+# define SQ_VTCX_SEL_X(x) ((x) << 3)
+# define SQ_VTCX_SEL_Y(x) ((x) << 6)
+# define SQ_VTCX_SEL_Z(x) ((x) << 9)
+# define SQ_VTCX_SEL_W(x) ((x) << 12)
+#define SQ_VTX_CONSTANT_WORD4_0 0x30010
+#define SQ_VTX_CONSTANT_WORD5_0 0x30014
+#define SQ_VTX_CONSTANT_WORD6_0 0x30018
+#define SQ_VTX_CONSTANT_WORD7_0 0x3001c
+
/* cayman 3D regs */
#define CAYMAN_VGT_OFFCHIP_LDS_BASE 0x89B0
#define CAYMAN_DB_EQAA 0x28804
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 8c79ca97753d..556b7bc3418b 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -40,6 +40,7 @@ extern void evergreen_mc_program(struct radeon_device *rdev);
extern void evergreen_irq_suspend(struct radeon_device *rdev);
extern int evergreen_mc_init(struct radeon_device *rdev);
extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
+extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
#define EVERGREEN_PFP_UCODE_SIZE 1120
#define EVERGREEN_PM4_UCODE_SIZE 1376
@@ -967,6 +968,9 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev)
WREG32(VM_CONTEXT1_CNTL, 0);
cayman_pcie_gart_tlb_flush(rdev);
+ DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+ (unsigned)(rdev->mc.gtt_size >> 20),
+ (unsigned long long)rdev->gart.table_addr);
rdev->gart.ready = true;
return 0;
}
@@ -1341,6 +1345,9 @@ static int cayman_startup(struct radeon_device *rdev)
{
int r;
+ /* enable pcie gen2 link */
+ evergreen_pcie_gen2_enable(rdev);
+
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
r = ni_init_microcode(rdev);
if (r) {
@@ -1362,7 +1369,7 @@ static int cayman_startup(struct radeon_device *rdev)
r = evergreen_blit_init(rdev);
if (r) {
- evergreen_blit_fini(rdev);
+ r600_blit_fini(rdev);
rdev->asic->copy = NULL;
dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
}
@@ -1423,21 +1430,13 @@ int cayman_resume(struct radeon_device *rdev)
int cayman_suspend(struct radeon_device *rdev)
{
- int r;
-
/* FIXME: we should wait for ring to be empty */
cayman_cp_enable(rdev, false);
rdev->cp.ready = false;
evergreen_irq_suspend(rdev);
radeon_wb_disable(rdev);
cayman_pcie_gart_disable(rdev);
-
- /* unpin shaders bo */
- r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
- if (likely(r == 0)) {
- radeon_bo_unpin(rdev->r600_blit.shader_obj);
- radeon_bo_unreserve(rdev->r600_blit.shader_obj);
- }
+ r600_blit_suspend(rdev);
return 0;
}
@@ -1550,7 +1549,7 @@ int cayman_init(struct radeon_device *rdev)
void cayman_fini(struct radeon_device *rdev)
{
- evergreen_blit_fini(rdev);
+ r600_blit_fini(rdev);
cayman_cp_fini(rdev);
r600_irq_fini(rdev);
radeon_wb_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 7fcdbbbf2979..8f8b8fa14357 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -68,6 +68,108 @@ MODULE_FIRMWARE(FIRMWARE_R520);
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
*/
+int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt,
+ unsigned idx,
+ unsigned reg)
+{
+ int r;
+ u32 tile_flags = 0;
+ u32 tmp;
+ struct radeon_cs_reloc *reloc;
+ u32 value;
+
+ r = r100_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+ idx, reg);
+ r100_cs_dump_packet(p, pkt);
+ return r;
+ }
+ value = radeon_get_ib_value(p, idx);
+ tmp = value & 0x003fffff;
+ tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
+
+ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+ tile_flags |= RADEON_DST_TILE_MACRO;
+ if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+ if (reg == RADEON_SRC_PITCH_OFFSET) {
+ DRM_ERROR("Cannot src blit from microtiled surface\n");
+ r100_cs_dump_packet(p, pkt);
+ return -EINVAL;
+ }
+ tile_flags |= RADEON_DST_TILE_MICRO;
+ }
+
+ tmp |= tile_flags;
+ p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
+ return 0;
+}
+
+int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt,
+ int idx)
+{
+ unsigned c, i;
+ struct radeon_cs_reloc *reloc;
+ struct r100_cs_track *track;
+ int r = 0;
+ volatile uint32_t *ib;
+ u32 idx_value;
+
+ ib = p->ib->ptr;
+ track = (struct r100_cs_track *)p->track;
+ c = radeon_get_ib_value(p, idx++) & 0x1F;
+ if (c > 16) {
+ DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
+ pkt->opcode);
+ r100_cs_dump_packet(p, pkt);
+ return -EINVAL;
+ }
+ track->num_arrays = c;
+ for (i = 0; i < (c - 1); i+=2, idx+=3) {
+ r = r100_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("No reloc for packet3 %d\n",
+ pkt->opcode);
+ r100_cs_dump_packet(p, pkt);
+ return r;
+ }
+ idx_value = radeon_get_ib_value(p, idx);
+ ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
+
+ track->arrays[i + 0].esize = idx_value >> 8;
+ track->arrays[i + 0].robj = reloc->robj;
+ track->arrays[i + 0].esize &= 0x7F;
+ r = r100_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("No reloc for packet3 %d\n",
+ pkt->opcode);
+ r100_cs_dump_packet(p, pkt);
+ return r;
+ }
+ ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset);
+ track->arrays[i + 1].robj = reloc->robj;
+ track->arrays[i + 1].esize = idx_value >> 24;
+ track->arrays[i + 1].esize &= 0x7F;
+ }
+ if (c & 1) {
+ r = r100_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("No reloc for packet3 %d\n",
+ pkt->opcode);
+ r100_cs_dump_packet(p, pkt);
+ return r;
+ }
+ idx_value = radeon_get_ib_value(p, idx);
+ ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
+ track->arrays[i + 0].robj = reloc->robj;
+ track->arrays[i + 0].esize = idx_value >> 8;
+ track->arrays[i + 0].esize &= 0x7F;
+ }
+ return r;
+}
+
void r100_pre_page_flip(struct radeon_device *rdev, int crtc)
{
/* enable the pflip int */
@@ -513,6 +615,9 @@ int r100_pci_gart_enable(struct radeon_device *rdev)
tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
WREG32(RADEON_AIC_CNTL, tmp);
r100_pci_gart_tlb_flush(rdev);
+ DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+ (unsigned)(rdev->mc.gtt_size >> 20),
+ (unsigned long long)rdev->gart.table_addr);
rdev->gart.ready = true;
return 0;
}
@@ -588,7 +693,7 @@ void r100_irq_disable(struct radeon_device *rdev)
WREG32(R_000044_GEN_INT_STATUS, tmp);
}
-static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
+static uint32_t r100_irq_ack(struct radeon_device *rdev)
{
uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
uint32_t irq_mask = RADEON_SW_INT_TEST |
@@ -3147,7 +3252,7 @@ void r100_bandwidth_update(struct radeon_device *rdev)
}
}
-static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
+static void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
{
DRM_ERROR("pitch %d\n", t->pitch);
DRM_ERROR("use_pitch %d\n", t->use_pitch);
@@ -3965,3 +4070,43 @@ int r100_init(struct radeon_device *rdev)
}
return 0;
}
+
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+ if (reg < rdev->rmmio_size)
+ return readl(((void __iomem *)rdev->rmmio) + reg);
+ else {
+ writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+ return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+ }
+}
+
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+ if (reg < rdev->rmmio_size)
+ writel(v, ((void __iomem *)rdev->rmmio) + reg);
+ else {
+ writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+ writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+ }
+}
+
+u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
+{
+ if (reg < rdev->rio_mem_size)
+ return ioread32(rdev->rio_mem + reg);
+ else {
+ iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
+ return ioread32(rdev->rio_mem + RADEON_MM_DATA);
+ }
+}
+
+void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
+{
+ if (reg < rdev->rio_mem_size)
+ iowrite32(v, rdev->rio_mem + reg);
+ else {
+ iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
+ iowrite32(v, rdev->rio_mem + RADEON_MM_DATA);
+ }
+}
diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h
index 686f9dc5d4bd..6a603b378adb 100644
--- a/drivers/gpu/drm/radeon/r100_track.h
+++ b/drivers/gpu/drm/radeon/r100_track.h
@@ -92,106 +92,10 @@ int r200_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg);
-
-
-static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
- struct radeon_cs_packet *pkt,
- unsigned idx,
- unsigned reg)
-{
- int r;
- u32 tile_flags = 0;
- u32 tmp;
- struct radeon_cs_reloc *reloc;
- u32 value;
-
- r = r100_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
- idx, reg);
- r100_cs_dump_packet(p, pkt);
- return r;
- }
- value = radeon_get_ib_value(p, idx);
- tmp = value & 0x003fffff;
- tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
-
- if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
- tile_flags |= RADEON_DST_TILE_MACRO;
- if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
- if (reg == RADEON_SRC_PITCH_OFFSET) {
- DRM_ERROR("Cannot src blit from microtiled surface\n");
- r100_cs_dump_packet(p, pkt);
- return -EINVAL;
- }
- tile_flags |= RADEON_DST_TILE_MICRO;
- }
-
- tmp |= tile_flags;
- p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
- return 0;
-}
-
-static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
- struct radeon_cs_packet *pkt,
- int idx)
-{
- unsigned c, i;
- struct radeon_cs_reloc *reloc;
- struct r100_cs_track *track;
- int r = 0;
- volatile uint32_t *ib;
- u32 idx_value;
-
- ib = p->ib->ptr;
- track = (struct r100_cs_track *)p->track;
- c = radeon_get_ib_value(p, idx++) & 0x1F;
- if (c > 16) {
- DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
- pkt->opcode);
- r100_cs_dump_packet(p, pkt);
- return -EINVAL;
- }
- track->num_arrays = c;
- for (i = 0; i < (c - 1); i+=2, idx+=3) {
- r = r100_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("No reloc for packet3 %d\n",
- pkt->opcode);
- r100_cs_dump_packet(p, pkt);
- return r;
- }
- idx_value = radeon_get_ib_value(p, idx);
- ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
-
- track->arrays[i + 0].esize = idx_value >> 8;
- track->arrays[i + 0].robj = reloc->robj;
- track->arrays[i + 0].esize &= 0x7F;
- r = r100_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("No reloc for packet3 %d\n",
- pkt->opcode);
- r100_cs_dump_packet(p, pkt);
- return r;
- }
- ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset);
- track->arrays[i + 1].robj = reloc->robj;
- track->arrays[i + 1].esize = idx_value >> 24;
- track->arrays[i + 1].esize &= 0x7F;
- }
- if (c & 1) {
- r = r100_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("No reloc for packet3 %d\n",
- pkt->opcode);
- r100_cs_dump_packet(p, pkt);
- return r;
- }
- idx_value = radeon_get_ib_value(p, idx);
- ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
- track->arrays[i + 0].robj = reloc->robj;
- track->arrays[i + 0].esize = idx_value >> 8;
- track->arrays[i + 0].esize &= 0x7F;
- }
- return r;
-}
+int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt,
+ unsigned idx,
+ unsigned reg);
+int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt,
+ int idx);
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 55a7f190027e..33f2b68c680b 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -144,8 +144,9 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
rv370_pcie_gart_tlb_flush(rdev);
- DRM_INFO("PCIE GART of %uM enabled (table at 0x%08X).\n",
- (unsigned)(rdev->mc.gtt_size >> 20), table_addr);
+ DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+ (unsigned)(rdev->mc.gtt_size >> 20),
+ (unsigned long long)table_addr);
rdev->gart.ready = true;
return 0;
}
diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c
index c5c2742e4140..1fe98b421c9b 100644
--- a/drivers/gpu/drm/radeon/r300_cmdbuf.c
+++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c
@@ -791,7 +791,7 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
/**
* Emit the sequence to pacify R300.
*/
-static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
+static void r300_pacify(drm_radeon_private_t *dev_priv)
{
uint32_t cache_z, cache_3d, cache_2d;
RING_LOCALS;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 720dd99163f8..12470b090ddf 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -993,6 +993,9 @@ int r600_pcie_gart_enable(struct radeon_device *rdev)
WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
r600_pcie_gart_tlb_flush(rdev);
+ DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+ (unsigned)(rdev->mc.gtt_size >> 20),
+ (unsigned long long)rdev->gart.table_addr);
rdev->gart.ready = true;
return 0;
}
@@ -2362,19 +2365,33 @@ int r600_copy_blit(struct radeon_device *rdev,
mutex_lock(&rdev->r600_blit.mutex);
rdev->r600_blit.vb_ib = NULL;
- r = r600_blit_prepare_copy(rdev, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
+ r = r600_blit_prepare_copy(rdev, num_gpu_pages);
if (r) {
if (rdev->r600_blit.vb_ib)
radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
mutex_unlock(&rdev->r600_blit.mutex);
return r;
}
- r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
+ r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages);
r600_blit_done_copy(rdev, fence);
mutex_unlock(&rdev->r600_blit.mutex);
return 0;
}
+void r600_blit_suspend(struct radeon_device *rdev)
+{
+ int r;
+
+ /* unpin shaders bo */
+ if (rdev->r600_blit.shader_obj) {
+ r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+ if (!r) {
+ radeon_bo_unpin(rdev->r600_blit.shader_obj);
+ radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+ }
+ }
+}
+
int r600_set_surface_reg(struct radeon_device *rdev, int reg,
uint32_t tiling_flags, uint32_t pitch,
uint32_t offset, uint32_t obj_size)
@@ -2494,8 +2511,6 @@ int r600_resume(struct radeon_device *rdev)
int r600_suspend(struct radeon_device *rdev)
{
- int r;
-
r600_audio_fini(rdev);
/* FIXME: we should wait for ring to be empty */
r600_cp_stop(rdev);
@@ -2503,14 +2518,8 @@ int r600_suspend(struct radeon_device *rdev)
r600_irq_suspend(rdev);
radeon_wb_disable(rdev);
r600_pcie_gart_disable(rdev);
- /* unpin shaders bo */
- if (rdev->r600_blit.shader_obj) {
- r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
- if (!r) {
- radeon_bo_unpin(rdev->r600_blit.shader_obj);
- radeon_bo_unreserve(rdev->r600_blit.shader_obj);
- }
- }
+ r600_blit_suspend(rdev);
+
return 0;
}
@@ -3137,7 +3146,7 @@ int r600_irq_set(struct radeon_device *rdev)
return 0;
}
-static inline void r600_irq_ack(struct radeon_device *rdev)
+static void r600_irq_ack(struct radeon_device *rdev)
{
u32 tmp;
@@ -3238,7 +3247,7 @@ void r600_irq_disable(struct radeon_device *rdev)
r600_disable_interrupt_state(rdev);
}
-static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
+static u32 r600_get_ih_wptr(struct radeon_device *rdev)
{
u32 wptr, tmp;
diff --git a/drivers/gpu/drm/radeon/r600_blit.c b/drivers/gpu/drm/radeon/r600_blit.c
index 7f1043448d25..3c031a48205d 100644
--- a/drivers/gpu/drm/radeon/r600_blit.c
+++ b/drivers/gpu/drm/radeon/r600_blit.c
@@ -41,7 +41,7 @@
#define COLOR_5_6_5 0x8
#define COLOR_8_8_8_8 0x1a
-static inline void
+static void
set_render_target(drm_radeon_private_t *dev_priv, int format, int w, int h, u64 gpu_addr)
{
u32 cb_color_info;
@@ -99,7 +99,7 @@ set_render_target(drm_radeon_private_t *dev_priv, int format, int w, int h, u64
ADVANCE_RING();
}
-static inline void
+static void
cp_set_surface_sync(drm_radeon_private_t *dev_priv,
u32 sync_type, u32 size, u64 mc_addr)
{
@@ -121,7 +121,7 @@ cp_set_surface_sync(drm_radeon_private_t *dev_priv,
ADVANCE_RING();
}
-static inline void
+static void
set_shaders(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -184,7 +184,7 @@ set_shaders(struct drm_device *dev)
R600_SH_ACTION_ENA, 512, gpu_addr);
}
-static inline void
+static void
set_vtx_resource(drm_radeon_private_t *dev_priv, u64 gpu_addr)
{
uint32_t sq_vtx_constant_word2;
@@ -220,7 +220,7 @@ set_vtx_resource(drm_radeon_private_t *dev_priv, u64 gpu_addr)
R600_VC_ACTION_ENA, 48, gpu_addr);
}
-static inline void
+static void
set_tex_resource(drm_radeon_private_t *dev_priv,
int format, int w, int h, int pitch, u64 gpu_addr)
{
@@ -258,7 +258,7 @@ set_tex_resource(drm_radeon_private_t *dev_priv,
}
-static inline void
+static void
set_scissors(drm_radeon_private_t *dev_priv, int x1, int y1, int x2, int y2)
{
RING_LOCALS;
@@ -282,7 +282,7 @@ set_scissors(drm_radeon_private_t *dev_priv, int x1, int y1, int x2, int y2)
ADVANCE_RING();
}
-static inline void
+static void
draw_auto(drm_radeon_private_t *dev_priv)
{
RING_LOCALS;
@@ -311,7 +311,7 @@ draw_auto(drm_radeon_private_t *dev_priv)
COMMIT_RING();
}
-static inline void
+static void
set_default_state(drm_radeon_private_t *dev_priv)
{
int i;
@@ -489,7 +489,7 @@ set_default_state(drm_radeon_private_t *dev_priv)
ADVANCE_RING();
}
-static inline uint32_t i2f(uint32_t input)
+static uint32_t i2f(uint32_t input)
{
u32 result, i, exponent, fraction;
@@ -515,7 +515,7 @@ static inline uint32_t i2f(uint32_t input)
}
-static inline int r600_nomm_get_vb(struct drm_device *dev)
+static int r600_nomm_get_vb(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
dev_priv->blit_vb = radeon_freelist_get(dev);
@@ -526,7 +526,7 @@ static inline int r600_nomm_get_vb(struct drm_device *dev)
return 0;
}
-static inline void r600_nomm_put_vb(struct drm_device *dev)
+static void r600_nomm_put_vb(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -534,7 +534,7 @@ static inline void r600_nomm_put_vb(struct drm_device *dev)
radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->master, dev_priv->blit_vb);
}
-static inline void *r600_nomm_get_vb_ptr(struct drm_device *dev)
+static void *r600_nomm_get_vb_ptr(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
return (((char *)dev->agp_buffer_map->handle +
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c
index 9aa74c3f8cb6..c4cf1308d4a1 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -42,6 +42,9 @@
#define COLOR_5_6_5 0x8
#define COLOR_8_8_8_8 0x1a
+#define RECT_UNIT_H 32
+#define RECT_UNIT_W (RADEON_GPU_PAGE_SIZE / 4 / RECT_UNIT_H)
+
/* emits 21 on rv770+, 23 on r600 */
static void
set_render_target(struct radeon_device *rdev, int format,
@@ -54,7 +57,9 @@ set_render_target(struct radeon_device *rdev, int format,
if (h < 8)
h = 8;
- cb_color_info = ((format << 2) | (1 << 27) | (1 << 8));
+ cb_color_info = CB_FORMAT(format) |
+ CB_SOURCE_FORMAT(CB_SF_EXPORT_NORM) |
+ CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
pitch = (w / 8) - 1;
slice = ((w * h) / 64) - 1;
@@ -164,9 +169,10 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr)
{
u32 sq_vtx_constant_word2;
- sq_vtx_constant_word2 = ((upper_32_bits(gpu_addr) & 0xff) | (16 << 8));
+ sq_vtx_constant_word2 = SQ_VTXC_BASE_ADDR_HI(upper_32_bits(gpu_addr) & 0xff) |
+ SQ_VTXC_STRIDE(16);
#ifdef __BIG_ENDIAN
- sq_vtx_constant_word2 |= (2 << 30);
+ sq_vtx_constant_word2 |= SQ_VTXC_ENDIAN_SWAP(SQ_ENDIAN_8IN32);
#endif
radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
@@ -202,18 +208,19 @@ set_tex_resource(struct radeon_device *rdev,
if (h < 1)
h = 1;
- sq_tex_resource_word0 = (1 << 0) | (1 << 3);
- sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 8) |
- ((w - 1) << 19));
+ sq_tex_resource_word0 = S_038000_DIM(V_038000_SQ_TEX_DIM_2D) |
+ S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+ sq_tex_resource_word0 |= S_038000_PITCH((pitch >> 3) - 1) |
+ S_038000_TEX_WIDTH(w - 1);
- sq_tex_resource_word1 = (format << 26);
- sq_tex_resource_word1 |= ((h - 1) << 0);
+ sq_tex_resource_word1 = S_038004_DATA_FORMAT(format);
+ sq_tex_resource_word1 |= S_038004_TEX_HEIGHT(h - 1);
- sq_tex_resource_word4 = ((1 << 14) |
- (0 << 16) |
- (1 << 19) |
- (2 << 22) |
- (3 << 25));
+ sq_tex_resource_word4 = S_038010_REQUEST_SIZE(1) |
+ S_038010_DST_SEL_X(SQ_SEL_X) |
+ S_038010_DST_SEL_Y(SQ_SEL_Y) |
+ S_038010_DST_SEL_Z(SQ_SEL_Z) |
+ S_038010_DST_SEL_W(SQ_SEL_W);
radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
radeon_ring_write(rdev, 0);
@@ -450,7 +457,7 @@ set_default_state(struct radeon_device *rdev)
radeon_ring_write(rdev, sq_stack_resource_mgmt_2);
}
-static inline uint32_t i2f(uint32_t input)
+static uint32_t i2f(uint32_t input)
{
u32 result, i, exponent, fraction;
@@ -483,6 +490,27 @@ int r600_blit_init(struct radeon_device *rdev)
u32 packet2s[16];
int num_packet2s = 0;
+ rdev->r600_blit.primitives.set_render_target = set_render_target;
+ rdev->r600_blit.primitives.cp_set_surface_sync = cp_set_surface_sync;
+ rdev->r600_blit.primitives.set_shaders = set_shaders;
+ rdev->r600_blit.primitives.set_vtx_resource = set_vtx_resource;
+ rdev->r600_blit.primitives.set_tex_resource = set_tex_resource;
+ rdev->r600_blit.primitives.set_scissors = set_scissors;
+ rdev->r600_blit.primitives.draw_auto = draw_auto;
+ rdev->r600_blit.primitives.set_default_state = set_default_state;
+
+ rdev->r600_blit.ring_size_common = 40; /* shaders + def state */
+ rdev->r600_blit.ring_size_common += 10; /* fence emit for VB IB */
+ rdev->r600_blit.ring_size_common += 5; /* done copy */
+ rdev->r600_blit.ring_size_common += 10; /* fence emit for done copy */
+
+ rdev->r600_blit.ring_size_per_loop = 76;
+ /* set_render_target emits 2 extra dwords on rv6xx */
+ if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770)
+ rdev->r600_blit.ring_size_per_loop += 2;
+
+ rdev->r600_blit.max_dim = 8192;
+
/* pin copy shader into vram if already initialized */
if (rdev->r600_blit.shader_obj)
goto done;
@@ -600,47 +628,80 @@ static void r600_vb_ib_put(struct radeon_device *rdev)
radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
}
-int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
+static unsigned r600_blit_create_rect(unsigned num_gpu_pages,
+ int *width, int *height, int max_dim)
+{
+ unsigned max_pages;
+ unsigned pages = num_gpu_pages;
+ int w, h;
+
+ if (num_gpu_pages == 0) {
+ /* not supposed to be called with no pages, but just in case */
+ h = 0;
+ w = 0;
+ pages = 0;
+ WARN_ON(1);
+ } else {
+ int rect_order = 2;
+ h = RECT_UNIT_H;
+ while (num_gpu_pages / rect_order) {
+ h *= 2;
+ rect_order *= 4;
+ if (h >= max_dim) {
+ h = max_dim;
+ break;
+ }
+ }
+ max_pages = (max_dim * h) / (RECT_UNIT_W * RECT_UNIT_H);
+ if (pages > max_pages)
+ pages = max_pages;
+ w = (pages * RECT_UNIT_W * RECT_UNIT_H) / h;
+ w = (w / RECT_UNIT_W) * RECT_UNIT_W;
+ pages = (w * h) / (RECT_UNIT_W * RECT_UNIT_H);
+ BUG_ON(pages == 0);
+ }
+
+
+ DRM_DEBUG("blit_rectangle: h=%d, w=%d, pages=%d\n", h, w, pages);
+
+ /* return width and height only of the caller wants it */
+ if (height)
+ *height = h;
+ if (width)
+ *width = w;
+
+ return pages;
+}
+
+
+int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages)
{
int r;
- int ring_size, line_size;
- int max_size;
- /* loops of emits 64 + fence emit possible */
- int dwords_per_loop = 76, num_loops;
+ int ring_size;
+ int num_loops = 0;
+ int dwords_per_loop = rdev->r600_blit.ring_size_per_loop;
r = r600_vb_ib_get(rdev);
if (r)
return r;
- /* set_render_target emits 2 extra dwords on rv6xx */
- if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770)
- dwords_per_loop += 2;
-
- /* 8 bpp vs 32 bpp for xfer unit */
- if (size_bytes & 3)
- line_size = 8192;
- else
- line_size = 8192*4;
-
- max_size = 8192 * line_size;
+ /* num loops */
+ while (num_gpu_pages) {
+ num_gpu_pages -=
+ r600_blit_create_rect(num_gpu_pages, NULL, NULL,
+ rdev->r600_blit.max_dim);
+ num_loops++;
+ }
- /* major loops cover the max size transfer */
- num_loops = ((size_bytes + max_size) / max_size);
- /* minor loops cover the extra non aligned bits */
- num_loops += ((size_bytes % line_size) ? 1 : 0);
/* calculate number of loops correctly */
ring_size = num_loops * dwords_per_loop;
- /* set default + shaders */
- ring_size += 40; /* shaders + def state */
- ring_size += 10; /* fence emit for VB IB */
- ring_size += 5; /* done copy */
- ring_size += 10; /* fence emit for done copy */
+ ring_size += rdev->r600_blit.ring_size_common;
r = radeon_ring_lock(rdev, ring_size);
if (r)
return r;
- set_default_state(rdev); /* 14 */
- set_shaders(rdev); /* 26 */
+ rdev->r600_blit.primitives.set_default_state(rdev);
+ rdev->r600_blit.primitives.set_shaders(rdev);
return 0;
}
@@ -659,182 +720,64 @@ void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence)
void r600_kms_blit_copy(struct radeon_device *rdev,
u64 src_gpu_addr, u64 dst_gpu_addr,
- int size_bytes)
+ unsigned num_gpu_pages)
{
- int max_bytes;
u64 vb_gpu_addr;
u32 *vb;
- DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr,
- size_bytes, rdev->r600_blit.vb_used);
+ DRM_DEBUG("emitting copy %16llx %16llx %d %d\n",
+ src_gpu_addr, dst_gpu_addr,
+ num_gpu_pages, rdev->r600_blit.vb_used);
vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
- if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
- max_bytes = 8192;
-
- while (size_bytes) {
- int cur_size = size_bytes;
- int src_x = src_gpu_addr & 255;
- int dst_x = dst_gpu_addr & 255;
- int h = 1;
- src_gpu_addr = src_gpu_addr & ~255ULL;
- dst_gpu_addr = dst_gpu_addr & ~255ULL;
-
- if (!src_x && !dst_x) {
- h = (cur_size / max_bytes);
- if (h > 8192)
- h = 8192;
- if (h == 0)
- h = 1;
- else
- cur_size = max_bytes;
- } else {
- if (cur_size > max_bytes)
- cur_size = max_bytes;
- if (cur_size > (max_bytes - dst_x))
- cur_size = (max_bytes - dst_x);
- if (cur_size > (max_bytes - src_x))
- cur_size = (max_bytes - src_x);
- }
-
- if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
- WARN_ON(1);
- }
-
- vb[0] = i2f(dst_x);
- vb[1] = 0;
- vb[2] = i2f(src_x);
- vb[3] = 0;
-
- vb[4] = i2f(dst_x);
- vb[5] = i2f(h);
- vb[6] = i2f(src_x);
- vb[7] = i2f(h);
-
- vb[8] = i2f(dst_x + cur_size);
- vb[9] = i2f(h);
- vb[10] = i2f(src_x + cur_size);
- vb[11] = i2f(h);
-
- /* src 9 */
- set_tex_resource(rdev, FMT_8,
- src_x + cur_size, h, src_x + cur_size,
- src_gpu_addr);
-
- /* 5 */
- cp_set_surface_sync(rdev,
- PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
- /* dst 23 */
- set_render_target(rdev, COLOR_8,
- dst_x + cur_size, h,
- dst_gpu_addr);
+ while (num_gpu_pages) {
+ int w, h;
+ unsigned size_in_bytes;
+ unsigned pages_per_loop =
+ r600_blit_create_rect(num_gpu_pages, &w, &h,
+ rdev->r600_blit.max_dim);
- /* scissors 12 */
- set_scissors(rdev, dst_x, 0, dst_x + cur_size, h);
+ size_in_bytes = pages_per_loop * RADEON_GPU_PAGE_SIZE;
+ DRM_DEBUG("rectangle w=%d h=%d\n", w, h);
- /* 14 */
- vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
- set_vtx_resource(rdev, vb_gpu_addr);
-
- /* draw 10 */
- draw_auto(rdev);
-
- /* 5 */
- cp_set_surface_sync(rdev,
- PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
- cur_size * h, dst_gpu_addr);
-
- vb += 12;
- rdev->r600_blit.vb_used += 12 * 4;
-
- src_gpu_addr += cur_size * h;
- dst_gpu_addr += cur_size * h;
- size_bytes -= cur_size * h;
+ if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
+ WARN_ON(1);
}
- } else {
- max_bytes = 8192 * 4;
-
- while (size_bytes) {
- int cur_size = size_bytes;
- int src_x = (src_gpu_addr & 255);
- int dst_x = (dst_gpu_addr & 255);
- int h = 1;
- src_gpu_addr = src_gpu_addr & ~255ULL;
- dst_gpu_addr = dst_gpu_addr & ~255ULL;
-
- if (!src_x && !dst_x) {
- h = (cur_size / max_bytes);
- if (h > 8192)
- h = 8192;
- if (h == 0)
- h = 1;
- else
- cur_size = max_bytes;
- } else {
- if (cur_size > max_bytes)
- cur_size = max_bytes;
- if (cur_size > (max_bytes - dst_x))
- cur_size = (max_bytes - dst_x);
- if (cur_size > (max_bytes - src_x))
- cur_size = (max_bytes - src_x);
- }
-
- if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
- WARN_ON(1);
- }
- vb[0] = i2f(dst_x / 4);
- vb[1] = 0;
- vb[2] = i2f(src_x / 4);
- vb[3] = 0;
-
- vb[4] = i2f(dst_x / 4);
- vb[5] = i2f(h);
- vb[6] = i2f(src_x / 4);
- vb[7] = i2f(h);
-
- vb[8] = i2f((dst_x + cur_size) / 4);
- vb[9] = i2f(h);
- vb[10] = i2f((src_x + cur_size) / 4);
- vb[11] = i2f(h);
-
- /* src 9 */
- set_tex_resource(rdev, FMT_8_8_8_8,
- (src_x + cur_size) / 4,
- h, (src_x + cur_size) / 4,
- src_gpu_addr);
- /* 5 */
- cp_set_surface_sync(rdev,
- PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
- /* dst 23 */
- set_render_target(rdev, COLOR_8_8_8_8,
- (dst_x + cur_size) / 4, h,
- dst_gpu_addr);
-
- /* scissors 12 */
- set_scissors(rdev, (dst_x / 4), 0, (dst_x + cur_size / 4), h);
-
- /* Vertex buffer setup 14 */
- vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
- set_vtx_resource(rdev, vb_gpu_addr);
-
- /* draw 10 */
- draw_auto(rdev);
-
- /* 5 */
- cp_set_surface_sync(rdev,
- PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
- cur_size * h, dst_gpu_addr);
-
- /* 78 ring dwords per loop */
- vb += 12;
- rdev->r600_blit.vb_used += 12 * 4;
-
- src_gpu_addr += cur_size * h;
- dst_gpu_addr += cur_size * h;
- size_bytes -= cur_size * h;
- }
+ vb[0] = 0;
+ vb[1] = 0;
+ vb[2] = 0;
+ vb[3] = 0;
+
+ vb[4] = 0;
+ vb[5] = i2f(h);
+ vb[6] = 0;
+ vb[7] = i2f(h);
+
+ vb[8] = i2f(w);
+ vb[9] = i2f(h);
+ vb[10] = i2f(w);
+ vb[11] = i2f(h);
+
+ rdev->r600_blit.primitives.set_tex_resource(rdev, FMT_8_8_8_8,
+ w, h, w, src_gpu_addr);
+ rdev->r600_blit.primitives.cp_set_surface_sync(rdev,
+ PACKET3_TC_ACTION_ENA,
+ size_in_bytes, src_gpu_addr);
+ rdev->r600_blit.primitives.set_render_target(rdev, COLOR_8_8_8_8,
+ w, h, dst_gpu_addr);
+ rdev->r600_blit.primitives.set_scissors(rdev, 0, 0, w, h);
+ vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
+ rdev->r600_blit.primitives.set_vtx_resource(rdev, vb_gpu_addr);
+ rdev->r600_blit.primitives.draw_auto(rdev);
+ rdev->r600_blit.primitives.cp_set_surface_sync(rdev,
+ PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
+ size_in_bytes, dst_gpu_addr);
+
+ vb += 12;
+ rdev->r600_blit.vb_used += 4*12;
+ src_gpu_addr += size_in_bytes;
+ dst_gpu_addr += size_in_bytes;
+ num_gpu_pages -= pages_per_loop;
}
}
-
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index cf83aa05a684..0a2e023c1557 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -162,7 +162,7 @@ static const struct gpu_formats color_formats_table[] = {
[V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR},
};
-static inline bool fmt_is_valid_color(u32 format)
+static bool fmt_is_valid_color(u32 format)
{
if (format >= ARRAY_SIZE(color_formats_table))
return false;
@@ -173,7 +173,7 @@ static inline bool fmt_is_valid_color(u32 format)
return false;
}
-static inline bool fmt_is_valid_texture(u32 format, enum radeon_family family)
+static bool fmt_is_valid_texture(u32 format, enum radeon_family family)
{
if (format >= ARRAY_SIZE(color_formats_table))
return false;
@@ -187,7 +187,7 @@ static inline bool fmt_is_valid_texture(u32 format, enum radeon_family family)
return false;
}
-static inline int fmt_get_blocksize(u32 format)
+static int fmt_get_blocksize(u32 format)
{
if (format >= ARRAY_SIZE(color_formats_table))
return 0;
@@ -195,7 +195,7 @@ static inline int fmt_get_blocksize(u32 format)
return color_formats_table[format].blocksize;
}
-static inline int fmt_get_nblocksx(u32 format, u32 w)
+static int fmt_get_nblocksx(u32 format, u32 w)
{
unsigned bw;
@@ -209,7 +209,7 @@ static inline int fmt_get_nblocksx(u32 format, u32 w)
return (w + bw - 1) / bw;
}
-static inline int fmt_get_nblocksy(u32 format, u32 h)
+static int fmt_get_nblocksy(u32 format, u32 h)
{
unsigned bh;
@@ -223,25 +223,6 @@ static inline int fmt_get_nblocksy(u32 format, u32 h)
return (h + bh - 1) / bh;
}
-static inline int r600_bpe_from_format(u32 *bpe, u32 format)
-{
- unsigned res;
-
- if (format >= ARRAY_SIZE(color_formats_table))
- goto fail;
-
- res = color_formats_table[format].blocksize;
- if (res == 0)
- goto fail;
-
- *bpe = res;
- return 0;
-
-fail:
- *bpe = 16;
- return -EINVAL;
-}
-
struct array_mode_checker {
int array_mode;
u32 group_size;
@@ -252,7 +233,7 @@ struct array_mode_checker {
};
/* returns alignment in pixels for pitch/height/depth and bytes for base */
-static inline int r600_get_array_mode_alignment(struct array_mode_checker *values,
+static int r600_get_array_mode_alignment(struct array_mode_checker *values,
u32 *pitch_align,
u32 *height_align,
u32 *depth_align,
@@ -331,7 +312,7 @@ static void r600_cs_track_init(struct r600_cs_track *track)
track->db_depth_control = 0xFFFFFFFF;
}
-static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
+static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
{
struct r600_cs_track *track = p->track;
u32 slice_tile_max, size, tmp;
@@ -737,7 +718,7 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
* Check next packet is relocation packet3, do bo validation and compute
* GPU offset using the provided start.
**/
-static inline int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+static int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
{
struct radeon_cs_packet p3reloc;
int r;
@@ -911,7 +892,7 @@ static int r600_cs_parse_packet0(struct radeon_cs_parser *p,
* if register is safe. If register is not flag as safe this function
* will test it against a list of register needind special handling.
*/
-static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
{
struct r600_cs_track *track = (struct r600_cs_track *)p->track;
struct radeon_cs_reloc *reloc;
@@ -1215,7 +1196,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
return 0;
}
-static inline unsigned mip_minify(unsigned size, unsigned level)
+static unsigned mip_minify(unsigned size, unsigned level)
{
unsigned val;
@@ -1285,7 +1266,7 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,
* This function will check that the resource has valid field and that
* the texture and mipmap bo object are big enough to cover this resource.
*/
-static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
+static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
struct radeon_bo *texture,
struct radeon_bo *mipmap,
u64 base_offset,
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 0245ae6c204e..bfe1b5d92afe 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -79,6 +79,11 @@
#define CB_COLOR0_SIZE 0x28060
#define CB_COLOR0_VIEW 0x28080
#define CB_COLOR0_INFO 0x280a0
+# define CB_FORMAT(x) ((x) << 2)
+# define CB_ARRAY_MODE(x) ((x) << 8)
+# define CB_SOURCE_FORMAT(x) ((x) << 27)
+# define CB_SF_EXPORT_FULL 0
+# define CB_SF_EXPORT_NORM 1
#define CB_COLOR0_TILE 0x280c0
#define CB_COLOR0_FRAG 0x280e0
#define CB_COLOR0_MASK 0x28100
@@ -417,6 +422,17 @@
#define SQ_PGM_START_VS 0x28858
#define SQ_PGM_RESOURCES_VS 0x28868
#define SQ_PGM_CF_OFFSET_VS 0x288d0
+
+#define SQ_VTX_CONSTANT_WORD0_0 0x30000
+#define SQ_VTX_CONSTANT_WORD1_0 0x30004
+#define SQ_VTX_CONSTANT_WORD2_0 0x30008
+# define SQ_VTXC_BASE_ADDR_HI(x) ((x) << 0)
+# define SQ_VTXC_STRIDE(x) ((x) << 8)
+# define SQ_VTXC_ENDIAN_SWAP(x) ((x) << 30)
+# define SQ_ENDIAN_NONE 0
+# define SQ_ENDIAN_8IN16 1
+# define SQ_ENDIAN_8IN32 2
+#define SQ_VTX_CONSTANT_WORD3_0 0x3000c
#define SQ_VTX_CONSTANT_WORD6_0 0x38018
#define S__SQ_VTX_CONSTANT_TYPE(x) (((x) & 3) << 30)
#define G__SQ_VTX_CONSTANT_TYPE(x) (((x) >> 30) & 3)
@@ -1352,6 +1368,12 @@
#define S_038010_DST_SEL_W(x) (((x) & 0x7) << 25)
#define G_038010_DST_SEL_W(x) (((x) >> 25) & 0x7)
#define C_038010_DST_SEL_W 0xF1FFFFFF
+# define SQ_SEL_X 0
+# define SQ_SEL_Y 1
+# define SQ_SEL_Z 2
+# define SQ_SEL_W 3
+# define SQ_SEL_0 4
+# define SQ_SEL_1 5
#define S_038010_BASE_LEVEL(x) (((x) & 0xF) << 28)
#define G_038010_BASE_LEVEL(x) (((x) >> 28) & 0xF)
#define C_038010_BASE_LEVEL 0x0FFFFFFF
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c1e056b35b29..e3170c794c1d 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -102,7 +102,7 @@ extern int radeon_pcie_gen2;
#define RADEON_FENCE_JIFFIES_TIMEOUT (HZ / 2)
/* RADEON_IB_POOL_SIZE must be a power of 2 */
#define RADEON_IB_POOL_SIZE 16
-#define RADEON_DEBUGFS_MAX_NUM_FILES 32
+#define RADEON_DEBUGFS_MAX_COMPONENTS 32
#define RADEONFB_CONN_LIMIT 4
#define RADEON_BIOS_NUM_SCRATCH 8
@@ -523,9 +523,30 @@ struct r600_ih {
bool enabled;
};
+struct r600_blit_cp_primitives {
+ void (*set_render_target)(struct radeon_device *rdev, int format,
+ int w, int h, u64 gpu_addr);
+ void (*cp_set_surface_sync)(struct radeon_device *rdev,
+ u32 sync_type, u32 size,
+ u64 mc_addr);
+ void (*set_shaders)(struct radeon_device *rdev);
+ void (*set_vtx_resource)(struct radeon_device *rdev, u64 gpu_addr);
+ void (*set_tex_resource)(struct radeon_device *rdev,
+ int format, int w, int h, int pitch,
+ u64 gpu_addr);
+ void (*set_scissors)(struct radeon_device *rdev, int x1, int y1,
+ int x2, int y2);
+ void (*draw_auto)(struct radeon_device *rdev);
+ void (*set_default_state)(struct radeon_device *rdev);
+};
+
struct r600_blit {
struct mutex mutex;
struct radeon_bo *shader_obj;
+ struct r600_blit_cp_primitives primitives;
+ int max_dim;
+ int ring_size_common;
+ int ring_size_per_loop;
u64 shader_gpu_addr;
u32 vs_offset, ps_offset;
u32 state_offset;
@@ -534,6 +555,8 @@ struct r600_blit {
struct radeon_ib *vb_ib;
};
+void r600_blit_suspend(struct radeon_device *rdev);
+
int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib);
void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
@@ -601,32 +624,7 @@ struct radeon_cs_parser {
extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx);
extern int radeon_cs_finish_pages(struct radeon_cs_parser *p);
-
-
-static inline u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
-{
- struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
- u32 pg_idx, pg_offset;
- u32 idx_value = 0;
- int new_page;
-
- pg_idx = (idx * 4) / PAGE_SIZE;
- pg_offset = (idx * 4) % PAGE_SIZE;
-
- if (ibc->kpage_idx[0] == pg_idx)
- return ibc->kpage[0][pg_offset/4];
- if (ibc->kpage_idx[1] == pg_idx)
- return ibc->kpage[1][pg_offset/4];
-
- new_page = radeon_cs_update_pages(p, pg_idx);
- if (new_page < 0) {
- p->parser_error = new_page;
- return 0;
- }
-
- idx_value = ibc->kpage[new_page][pg_offset/4];
- return idx_value;
-}
+extern u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx);
struct radeon_cs_packet {
unsigned idx;
@@ -869,7 +867,7 @@ struct radeon_pm {
/*
* Benchmarking
*/
-void radeon_benchmark(struct radeon_device *rdev);
+void radeon_benchmark(struct radeon_device *rdev, int test_number);
/*
@@ -1252,45 +1250,10 @@ int radeon_device_init(struct radeon_device *rdev,
void radeon_device_fini(struct radeon_device *rdev);
int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
-static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
-{
- if (reg < rdev->rmmio_size)
- return readl((rdev->rmmio) + reg);
- else {
- writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
- return readl((rdev->rmmio) + RADEON_MM_DATA);
- }
-}
-
-static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
-{
- if (reg < rdev->rmmio_size)
- writel(v, (rdev->rmmio) + reg);
- else {
- writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
- writel(v, (rdev->rmmio) + RADEON_MM_DATA);
- }
-}
-
-static inline u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
-{
- if (reg < rdev->rio_mem_size)
- return ioread32(rdev->rio_mem + reg);
- else {
- iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
- return ioread32(rdev->rio_mem + RADEON_MM_DATA);
- }
-}
-
-static inline void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
-{
- if (reg < rdev->rio_mem_size)
- iowrite32(v, rdev->rio_mem + reg);
- else {
- iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
- iowrite32(v, rdev->rio_mem + RADEON_MM_DATA);
- }
-}
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+u32 r100_io_rreg(struct radeon_device *rdev, u32 reg);
+void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
/*
* Cast helper
@@ -1413,19 +1376,19 @@ void radeon_atombios_fini(struct radeon_device *rdev);
/*
* RING helpers.
*/
+
+#if DRM_DEBUG_CODE == 0
static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
{
-#if DRM_DEBUG_CODE
- if (rdev->cp.count_dw <= 0) {
- DRM_ERROR("radeon: writting more dword to ring than expected !\n");
- }
-#endif
rdev->cp.ring[rdev->cp.wptr++] = v;
rdev->cp.wptr &= rdev->cp.ptr_mask;
rdev->cp.count_dw--;
rdev->cp.ring_free_dw--;
}
-
+#else
+/* With debugging this is just too big to inline */
+void radeon_ring_write(struct radeon_device *rdev, uint32_t v);
+#endif
/*
* ASICs macro.
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index df8218bb83a6..e2944566ffea 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -765,9 +765,9 @@ static struct radeon_asic evergreen_asic = {
.get_vblank_counter = &evergreen_get_vblank_counter,
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &evergreen_cs_parse,
- .copy_blit = &evergreen_copy_blit,
+ .copy_blit = &r600_copy_blit,
.copy_dma = NULL,
- .copy = &evergreen_copy_blit,
+ .copy = &r600_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
.get_memory_clock = &radeon_atom_get_memory_clock,
@@ -812,9 +812,9 @@ static struct radeon_asic sumo_asic = {
.get_vblank_counter = &evergreen_get_vblank_counter,
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &evergreen_cs_parse,
- .copy_blit = &evergreen_copy_blit,
+ .copy_blit = &r600_copy_blit,
.copy_dma = NULL,
- .copy = &evergreen_copy_blit,
+ .copy = &r600_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
.get_memory_clock = NULL,
@@ -859,9 +859,9 @@ static struct radeon_asic btc_asic = {
.get_vblank_counter = &evergreen_get_vblank_counter,
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &evergreen_cs_parse,
- .copy_blit = &evergreen_copy_blit,
+ .copy_blit = &r600_copy_blit,
.copy_dma = NULL,
- .copy = &evergreen_copy_blit,
+ .copy = &r600_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
.get_memory_clock = &radeon_atom_get_memory_clock,
@@ -906,9 +906,9 @@ static struct radeon_asic cayman_asic = {
.get_vblank_counter = &evergreen_get_vblank_counter,
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &evergreen_cs_parse,
- .copy_blit = &evergreen_copy_blit,
+ .copy_blit = &r600_copy_blit,
.copy_dma = NULL,
- .copy = &evergreen_copy_blit,
+ .copy = &r600_copy_blit,
.get_engine_clock = &radeon_atom_get_engine_clock,
.set_engine_clock = &radeon_atom_set_engine_clock,
.get_memory_clock = &radeon_atom_get_memory_clock,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 3dedaa07aac1..85f14f0337e4 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -364,11 +364,11 @@ void r600_hdmi_init(struct drm_encoder *encoder);
int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
/* r600 blit */
-int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
+int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages);
void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
void r600_kms_blit_copy(struct radeon_device *rdev,
u64 src_gpu_addr, u64 dst_gpu_addr,
- int size_bytes);
+ unsigned num_gpu_pages);
/*
* rv770,rv730,rv710,rv740
@@ -401,9 +401,6 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev);
int evergreen_asic_reset(struct radeon_device *rdev);
void evergreen_bandwidth_update(struct radeon_device *rdev);
void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
-int evergreen_copy_blit(struct radeon_device *rdev,
- uint64_t src_offset, uint64_t dst_offset,
- unsigned num_gpu_pages, struct radeon_fence *fence);
void evergreen_hpd_init(struct radeon_device *rdev);
void evergreen_hpd_fini(struct radeon_device *rdev);
bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
@@ -421,13 +418,6 @@ extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_ba
extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc);
void evergreen_disable_interrupt_state(struct radeon_device *rdev);
int evergreen_blit_init(struct radeon_device *rdev);
-void evergreen_blit_fini(struct radeon_device *rdev);
-/* evergreen blit */
-int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
-void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
-void evergreen_kms_blit_copy(struct radeon_device *rdev,
- u64 src_gpu_addr, u64 dst_gpu_addr,
- int size_bytes);
/*
* cayman
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index bf2b61584cdb..08d0b94332e6 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -62,7 +62,7 @@ union atom_supported_devices {
struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
};
-static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
+static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
uint8_t id)
{
struct atom_context *ctx = rdev->mode_info.atom_context;
@@ -228,7 +228,7 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)
}
}
-static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
+static struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
u8 id)
{
struct atom_context *ctx = rdev->mode_info.atom_context;
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c
index 10191d9372d8..5cafc90de7f8 100644
--- a/drivers/gpu/drm/radeon/radeon_benchmark.c
+++ b/drivers/gpu/drm/radeon/radeon_benchmark.c
@@ -26,21 +26,81 @@
#include "radeon_reg.h"
#include "radeon.h"
-void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
- unsigned sdomain, unsigned ddomain)
+#define RADEON_BENCHMARK_COPY_BLIT 1
+#define RADEON_BENCHMARK_COPY_DMA 0
+
+#define RADEON_BENCHMARK_ITERATIONS 1024
+#define RADEON_BENCHMARK_COMMON_MODES_N 17
+
+static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size,
+ uint64_t saddr, uint64_t daddr,
+ int flag, int n)
+{
+ unsigned long start_jiffies;
+ unsigned long end_jiffies;
+ struct radeon_fence *fence = NULL;
+ int i, r;
+
+ start_jiffies = jiffies;
+ for (i = 0; i < n; i++) {
+ r = radeon_fence_create(rdev, &fence);
+ if (r)
+ return r;
+
+ switch (flag) {
+ case RADEON_BENCHMARK_COPY_DMA:
+ r = radeon_copy_dma(rdev, saddr, daddr,
+ size / RADEON_GPU_PAGE_SIZE,
+ fence);
+ break;
+ case RADEON_BENCHMARK_COPY_BLIT:
+ r = radeon_copy_blit(rdev, saddr, daddr,
+ size / RADEON_GPU_PAGE_SIZE,
+ fence);
+ break;
+ default:
+ DRM_ERROR("Unknown copy method\n");
+ r = -EINVAL;
+ }
+ if (r)
+ goto exit_do_move;
+ r = radeon_fence_wait(fence, false);
+ if (r)
+ goto exit_do_move;
+ radeon_fence_unref(&fence);
+ }
+ end_jiffies = jiffies;
+ r = jiffies_to_msecs(end_jiffies - start_jiffies);
+
+exit_do_move:
+ if (fence)
+ radeon_fence_unref(&fence);
+ return r;
+}
+
+
+static void radeon_benchmark_log_results(int n, unsigned size,
+ unsigned int time,
+ unsigned sdomain, unsigned ddomain,
+ char *kind)
+{
+ unsigned int throughput = (n * (size >> 10)) / time;
+ DRM_INFO("radeon: %s %u bo moves of %u kB from"
+ " %d to %d in %u ms, throughput: %u Mb/s or %u MB/s\n",
+ kind, n, size >> 10, sdomain, ddomain, time,
+ throughput * 8, throughput);
+}
+
+static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
+ unsigned sdomain, unsigned ddomain)
{
struct radeon_bo *dobj = NULL;
struct radeon_bo *sobj = NULL;
- struct radeon_fence *fence = NULL;
uint64_t saddr, daddr;
- unsigned long start_jiffies;
- unsigned long end_jiffies;
- unsigned long time;
- unsigned i, n, size;
- int r;
+ int r, n;
+ unsigned int time;
- size = bsize;
- n = 1024;
+ n = RADEON_BENCHMARK_ITERATIONS;
r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, &sobj);
if (r) {
goto out_cleanup;
@@ -67,65 +127,26 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
}
/* r100 doesn't have dma engine so skip the test */
- if (rdev->asic->copy_dma) {
-
- start_jiffies = jiffies;
- for (i = 0; i < n; i++) {
- r = radeon_fence_create(rdev, &fence);
- if (r) {
- goto out_cleanup;
- }
-
- r = radeon_copy_dma(rdev, saddr, daddr,
- size / RADEON_GPU_PAGE_SIZE, fence);
-
- if (r) {
- goto out_cleanup;
- }
- r = radeon_fence_wait(fence, false);
- if (r) {
- goto out_cleanup;
- }
- radeon_fence_unref(&fence);
- }
- end_jiffies = jiffies;
- time = end_jiffies - start_jiffies;
- time = jiffies_to_msecs(time);
- if (time > 0) {
- i = ((n * size) >> 10) / time;
- printk(KERN_INFO "radeon: dma %u bo moves of %ukb from"
- " %d to %d in %lums (%ukb/ms %ukb/s %uM/s)\n",
- n, size >> 10,
- sdomain, ddomain, time,
- i, i * 1000, (i * 1000) / 1024);
- }
- }
-
- start_jiffies = jiffies;
- for (i = 0; i < n; i++) {
- r = radeon_fence_create(rdev, &fence);
- if (r) {
- goto out_cleanup;
- }
- r = radeon_copy_blit(rdev, saddr, daddr, size / RADEON_GPU_PAGE_SIZE, fence);
- if (r) {
- goto out_cleanup;
- }
- r = radeon_fence_wait(fence, false);
- if (r) {
+ /* also, VRAM-to-VRAM test doesn't make much sense for DMA */
+ /* skip it as well if domains are the same */
+ if ((rdev->asic->copy_dma) && (sdomain != ddomain)) {
+ time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
+ RADEON_BENCHMARK_COPY_DMA, n);
+ if (time < 0)
goto out_cleanup;
- }
- radeon_fence_unref(&fence);
- }
- end_jiffies = jiffies;
- time = end_jiffies - start_jiffies;
- time = jiffies_to_msecs(time);
- if (time > 0) {
- i = ((n * size) >> 10) / time;
- printk(KERN_INFO "radeon: blit %u bo moves of %ukb from %d to %d"
- " in %lums (%ukb/ms %ukb/s %uM/s)\n", n, size >> 10,
- sdomain, ddomain, time, i, i * 1000, (i * 1000) / 1024);
+ if (time > 0)
+ radeon_benchmark_log_results(n, size, time,
+ sdomain, ddomain, "dma");
}
+
+ time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
+ RADEON_BENCHMARK_COPY_BLIT, n);
+ if (time < 0)
+ goto out_cleanup;
+ if (time > 0)
+ radeon_benchmark_log_results(n, size, time,
+ sdomain, ddomain, "blit");
+
out_cleanup:
if (sobj) {
r = radeon_bo_reserve(sobj, false);
@@ -143,18 +164,92 @@ out_cleanup:
}
radeon_bo_unref(&dobj);
}
- if (fence) {
- radeon_fence_unref(&fence);
- }
+
if (r) {
- printk(KERN_WARNING "Error while benchmarking BO move.\n");
+ DRM_ERROR("Error while benchmarking BO move.\n");
}
}
-void radeon_benchmark(struct radeon_device *rdev)
+void radeon_benchmark(struct radeon_device *rdev, int test_number)
{
- radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT,
- RADEON_GEM_DOMAIN_VRAM);
- radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
- RADEON_GEM_DOMAIN_GTT);
+ int i;
+ int common_modes[RADEON_BENCHMARK_COMMON_MODES_N] = {
+ 640 * 480 * 4,
+ 720 * 480 * 4,
+ 800 * 600 * 4,
+ 848 * 480 * 4,
+ 1024 * 768 * 4,
+ 1152 * 768 * 4,
+ 1280 * 720 * 4,
+ 1280 * 800 * 4,
+ 1280 * 854 * 4,
+ 1280 * 960 * 4,
+ 1280 * 1024 * 4,
+ 1440 * 900 * 4,
+ 1400 * 1050 * 4,
+ 1680 * 1050 * 4,
+ 1600 * 1200 * 4,
+ 1920 * 1080 * 4,
+ 1920 * 1200 * 4
+ };
+
+ switch (test_number) {
+ case 1:
+ /* simple test, VRAM to GTT and GTT to VRAM */
+ radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT,
+ RADEON_GEM_DOMAIN_VRAM);
+ radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
+ RADEON_GEM_DOMAIN_GTT);
+ break;
+ case 2:
+ /* simple test, VRAM to VRAM */
+ radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
+ RADEON_GEM_DOMAIN_VRAM);
+ break;
+ case 3:
+ /* GTT to VRAM, buffer size sweep, powers of 2 */
+ for (i = 1; i <= 65536; i <<= 1)
+ radeon_benchmark_move(rdev, i*1024,
+ RADEON_GEM_DOMAIN_GTT,
+ RADEON_GEM_DOMAIN_VRAM);
+ break;
+ case 4:
+ /* VRAM to GTT, buffer size sweep, powers of 2 */
+ for (i = 1; i <= 65536; i <<= 1)
+ radeon_benchmark_move(rdev, i*1024,
+ RADEON_GEM_DOMAIN_VRAM,
+ RADEON_GEM_DOMAIN_GTT);
+ break;
+ case 5:
+ /* VRAM to VRAM, buffer size sweep, powers of 2 */
+ for (i = 1; i <= 65536; i <<= 1)
+ radeon_benchmark_move(rdev, i*1024,
+ RADEON_GEM_DOMAIN_VRAM,
+ RADEON_GEM_DOMAIN_VRAM);
+ break;
+ case 6:
+ /* GTT to VRAM, buffer size sweep, common modes */
+ for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
+ radeon_benchmark_move(rdev, common_modes[i],
+ RADEON_GEM_DOMAIN_GTT,
+ RADEON_GEM_DOMAIN_VRAM);
+ break;
+ case 7:
+ /* VRAM to GTT, buffer size sweep, common modes */
+ for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
+ radeon_benchmark_move(rdev, common_modes[i],
+ RADEON_GEM_DOMAIN_VRAM,
+ RADEON_GEM_DOMAIN_GTT);
+ break;
+ case 8:
+ /* VRAM to VRAM, buffer size sweep, common modes */
+ for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
+ radeon_benchmark_move(rdev, common_modes[i],
+ RADEON_GEM_DOMAIN_VRAM,
+ RADEON_GEM_DOMAIN_VRAM);
+ break;
+
+ default:
+ DRM_ERROR("Unknown benchmark\n");
+ }
}
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 63675241c7ff..8bf83c4b4147 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -620,8 +620,8 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
i2c.y_data_mask = 0x80;
} else {
/* default masks for ddc pads */
- i2c.mask_clk_mask = RADEON_GPIO_EN_1;
- i2c.mask_data_mask = RADEON_GPIO_EN_0;
+ i2c.mask_clk_mask = RADEON_GPIO_MASK_1;
+ i2c.mask_data_mask = RADEON_GPIO_MASK_0;
i2c.a_clk_mask = RADEON_GPIO_A_1;
i2c.a_data_mask = RADEON_GPIO_A_0;
i2c.en_clk_mask = RADEON_GPIO_EN_1;
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 449c3d8c6836..dec6cbe6a0a6 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -724,6 +724,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
dret = radeon_ddc_probe(radeon_connector,
radeon_connector->requires_extended_probe);
if (dret) {
+ radeon_connector->detected_by_load = false;
if (radeon_connector->edid) {
kfree(radeon_connector->edid);
radeon_connector->edid = NULL;
@@ -750,12 +751,21 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
} else {
/* if we aren't forcing don't do destructive polling */
- if (!force)
- return connector->status;
+ if (!force) {
+ /* only return the previous status if we last
+ * detected a monitor via load.
+ */
+ if (radeon_connector->detected_by_load)
+ return connector->status;
+ else
+ return ret;
+ }
if (radeon_connector->dac_load_detect && encoder) {
encoder_funcs = encoder->helper_private;
ret = encoder_funcs->detect(encoder, connector);
+ if (ret == connector_status_connected)
+ radeon_connector->detected_by_load = true;
}
}
@@ -897,6 +907,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
dret = radeon_ddc_probe(radeon_connector,
radeon_connector->requires_extended_probe);
if (dret) {
+ radeon_connector->detected_by_load = false;
if (radeon_connector->edid) {
kfree(radeon_connector->edid);
radeon_connector->edid = NULL;
@@ -959,8 +970,18 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
goto out;
+ /* DVI-D and HDMI-A are digital only */
+ if ((connector->connector_type == DRM_MODE_CONNECTOR_DVID) ||
+ (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))
+ goto out;
+
+ /* if we aren't forcing don't do destructive polling */
if (!force) {
- ret = connector->status;
+ /* only return the previous status if we last
+ * detected a monitor via load.
+ */
+ if (radeon_connector->detected_by_load)
+ ret = connector->status;
goto out;
}
@@ -984,6 +1005,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
ret = encoder_funcs->detect(encoder, connector);
if (ret == connector_status_connected) {
radeon_connector->use_digital = false;
+ radeon_connector->detected_by_load = true;
}
}
break;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index b51e15725c6e..c33bc914d93d 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -750,14 +750,15 @@ int radeon_device_init(struct radeon_device *rdev,
/* set DMA mask + need_dma32 flags.
* PCIE - can handle 40-bits.
- * IGP - can handle 40-bits (in theory)
+ * IGP - can handle 40-bits
* AGP - generally dma32 is safest
- * PCI - only dma32
+ * PCI - dma32 for legacy pci gart, 40 bits on newer asics
*/
rdev->need_dma32 = false;
if (rdev->flags & RADEON_IS_AGP)
rdev->need_dma32 = true;
- if (rdev->flags & RADEON_IS_PCI)
+ if ((rdev->flags & RADEON_IS_PCI) &&
+ (rdev->family < CHIP_RS400))
rdev->need_dma32 = true;
dma_bits = rdev->need_dma32 ? 32 : 40;
@@ -817,7 +818,7 @@ int radeon_device_init(struct radeon_device *rdev,
radeon_test_moves(rdev);
}
if (radeon_benchmarking) {
- radeon_benchmark(rdev);
+ radeon_benchmark(rdev, radeon_benchmarking);
}
return 0;
}
@@ -981,7 +982,7 @@ struct radeon_debugfs {
struct drm_info_list *files;
unsigned num_files;
};
-static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_NUM_FILES];
+static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_COMPONENTS];
static unsigned _radeon_debugfs_count = 0;
int radeon_debugfs_add_files(struct radeon_device *rdev,
@@ -996,14 +997,17 @@ int radeon_debugfs_add_files(struct radeon_device *rdev,
return 0;
}
}
- if ((_radeon_debugfs_count + nfiles) > RADEON_DEBUGFS_MAX_NUM_FILES) {
- DRM_ERROR("Reached maximum number of debugfs files.\n");
- DRM_ERROR("Report so we increase RADEON_DEBUGFS_MAX_NUM_FILES.\n");
+
+ i = _radeon_debugfs_count + 1;
+ if (i > RADEON_DEBUGFS_MAX_COMPONENTS) {
+ DRM_ERROR("Reached maximum number of debugfs components.\n");
+ DRM_ERROR("Report so we increase "
+ "RADEON_DEBUGFS_MAX_COMPONENTS.\n");
return -EINVAL;
}
_radeon_debugfs[_radeon_debugfs_count].files = files;
_radeon_debugfs[_radeon_debugfs_count].num_files = nfiles;
- _radeon_debugfs_count++;
+ _radeon_debugfs_count = i;
#if defined(CONFIG_DEBUG_FS)
drm_debugfs_create_files(files, nfiles,
rdev->ddev->control->debugfs_root,
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 7fd4e3e5ad5f..76ec0e9ed8ae 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -48,7 +48,7 @@ static void radeon_fence_write(struct radeon_device *rdev, u32 seq)
scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
else
scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
- rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);;
+ rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);
} else
WREG32(rdev->fence_drv.scratch_reg, seq);
}
@@ -263,7 +263,7 @@ retry:
*/
if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) {
/* good news we believe it's a lockup */
- WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n",
+ printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n",
fence->seq, seq);
/* FIXME: what should we do ? marking everyone
* as signaled for now
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
index a533f52fd163..fdc3a9a54bf8 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -142,7 +142,7 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
u64 page_base;
if (!rdev->gart.ready) {
- WARN(1, "trying to unbind memory to unitialized GART !\n");
+ WARN(1, "trying to unbind memory from uninitialized GART !\n");
return;
}
t = offset / RADEON_GPU_PAGE_SIZE;
@@ -174,7 +174,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
int i, j;
if (!rdev->gart.ready) {
- WARN(1, "trying to bind memory to unitialized GART !\n");
+ WARN(1, "trying to bind memory to uninitialized GART !\n");
return -EINVAL;
}
t = offset / RADEON_GPU_PAGE_SIZE;
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 6c111c1fa3f9..02cb7da4124d 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -81,8 +81,9 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e
/* bit banging i2c */
-static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
+static int pre_xfer(struct i2c_adapter *i2c_adap)
{
+ struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
struct radeon_device *rdev = i2c->dev->dev_private;
struct radeon_i2c_bus_rec *rec = &i2c->rec;
uint32_t temp;
@@ -137,19 +138,30 @@ static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
WREG32(rec->en_data_reg, temp);
/* mask the gpio pins for software use */
- temp = RREG32(rec->mask_clk_reg);
- if (lock_state)
- temp |= rec->mask_clk_mask;
- else
- temp &= ~rec->mask_clk_mask;
+ temp = RREG32(rec->mask_clk_reg) | rec->mask_clk_mask;
WREG32(rec->mask_clk_reg, temp);
temp = RREG32(rec->mask_clk_reg);
+ temp = RREG32(rec->mask_data_reg) | rec->mask_data_mask;
+ WREG32(rec->mask_data_reg, temp);
temp = RREG32(rec->mask_data_reg);
- if (lock_state)
- temp |= rec->mask_data_mask;
- else
- temp &= ~rec->mask_data_mask;
+
+ return 0;
+}
+
+static void post_xfer(struct i2c_adapter *i2c_adap)
+{
+ struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+ struct radeon_device *rdev = i2c->dev->dev_private;
+ struct radeon_i2c_bus_rec *rec = &i2c->rec;
+ uint32_t temp;
+
+ /* unmask the gpio pins for software use */
+ temp = RREG32(rec->mask_clk_reg) & ~rec->mask_clk_mask;
+ WREG32(rec->mask_clk_reg, temp);
+ temp = RREG32(rec->mask_clk_reg);
+
+ temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask;
WREG32(rec->mask_data_reg, temp);
temp = RREG32(rec->mask_data_reg);
}
@@ -209,22 +221,6 @@ static void set_data(void *i2c_priv, int data)
WREG32(rec->en_data_reg, val);
}
-static int pre_xfer(struct i2c_adapter *i2c_adap)
-{
- struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
-
- radeon_i2c_do_lock(i2c, 1);
-
- return 0;
-}
-
-static void post_xfer(struct i2c_adapter *i2c_adap)
-{
- struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
-
- radeon_i2c_do_lock(i2c, 0);
-}
-
/* hw i2c */
static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c
index 465746bd51b7..00da38424dfc 100644
--- a/drivers/gpu/drm/radeon/radeon_irq.c
+++ b/drivers/gpu/drm/radeon/radeon_irq.c
@@ -129,7 +129,7 @@ void radeon_disable_vblank(struct drm_device *dev, int crtc)
}
}
-static inline u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
+static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
{
u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS);
u32 irq_mask = RADEON_SW_INT_TEST;
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_tv.c b/drivers/gpu/drm/radeon/radeon_legacy_tv.c
index c7b6cb428d09..b37ec0f1413a 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_tv.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_tv.c
@@ -864,7 +864,7 @@ void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder,
*v_sync_strt_wid = tmp;
}
-static inline int get_post_div(int value)
+static int get_post_div(int value)
{
int post_div;
switch (value) {
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 68820f5f6303..ed0178f03235 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -447,6 +447,7 @@ struct radeon_connector {
struct edid *edid;
void *con_priv;
bool dac_load_detect;
+ bool detected_by_load; /* if the connection status was determined by load */
uint16_t connector_object_id;
struct radeon_hpd hpd;
struct radeon_router router;
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 976c3b1b1b6e..1c851521f458 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -515,3 +515,44 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
}
return 0;
}
+
+int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait)
+{
+ int r;
+
+ r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+ if (unlikely(r != 0))
+ return r;
+ spin_lock(&bo->tbo.bdev->fence_lock);
+ if (mem_type)
+ *mem_type = bo->tbo.mem.mem_type;
+ if (bo->tbo.sync_obj)
+ r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
+ spin_unlock(&bo->tbo.bdev->fence_lock);
+ ttm_bo_unreserve(&bo->tbo);
+ return r;
+}
+
+
+/**
+ * radeon_bo_reserve - reserve bo
+ * @bo: bo structure
+ * @no_wait: don't sleep while trying to reserve (return -EBUSY)
+ *
+ * Returns:
+ * -EBUSY: buffer is busy and @no_wait is true
+ * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
+ * a signal. Release all buffer reservations and return to user-space.
+ */
+int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
+{
+ int r;
+
+ r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+ if (unlikely(r != 0)) {
+ if (r != -ERESTARTSYS)
+ dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
+ return r;
+ }
+ return 0;
+}
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index ede6c13628f2..b07f0f9b8627 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -52,28 +52,7 @@ static inline unsigned radeon_mem_type_to_domain(u32 mem_type)
return 0;
}
-/**
- * radeon_bo_reserve - reserve bo
- * @bo: bo structure
- * @no_wait: don't sleep while trying to reserve (return -EBUSY)
- *
- * Returns:
- * -EBUSY: buffer is busy and @no_wait is true
- * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
- * a signal. Release all buffer reservations and return to user-space.
- */
-static inline int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
-{
- int r;
-
- r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
- if (unlikely(r != 0)) {
- if (r != -ERESTARTSYS)
- dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
- return r;
- }
- return 0;
-}
+int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait);
static inline void radeon_bo_unreserve(struct radeon_bo *bo)
{
@@ -118,23 +97,8 @@ static inline u64 radeon_bo_mmap_offset(struct radeon_bo *bo)
return bo->tbo.addr_space_offset;
}
-static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
- bool no_wait)
-{
- int r;
-
- r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
- if (unlikely(r != 0))
- return r;
- spin_lock(&bo->tbo.bdev->fence_lock);
- if (mem_type)
- *mem_type = bo->tbo.mem.mem_type;
- if (bo->tbo.sync_obj)
- r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
- spin_unlock(&bo->tbo.bdev->fence_lock);
- ttm_bo_unreserve(&bo->tbo);
- return r;
-}
+extern int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
+ bool no_wait);
extern int radeon_bo_create(struct radeon_device *rdev,
unsigned long size, int byte_align,
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 08c0233db1b8..49d58202202c 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -35,6 +35,44 @@
int radeon_debugfs_ib_init(struct radeon_device *rdev);
+u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
+{
+ struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
+ u32 pg_idx, pg_offset;
+ u32 idx_value = 0;
+ int new_page;
+
+ pg_idx = (idx * 4) / PAGE_SIZE;
+ pg_offset = (idx * 4) % PAGE_SIZE;
+
+ if (ibc->kpage_idx[0] == pg_idx)
+ return ibc->kpage[0][pg_offset/4];
+ if (ibc->kpage_idx[1] == pg_idx)
+ return ibc->kpage[1][pg_offset/4];
+
+ new_page = radeon_cs_update_pages(p, pg_idx);
+ if (new_page < 0) {
+ p->parser_error = new_page;
+ return 0;
+ }
+
+ idx_value = ibc->kpage[new_page][pg_offset/4];
+ return idx_value;
+}
+
+void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
+{
+#if DRM_DEBUG_CODE
+ if (rdev->cp.count_dw <= 0) {
+ DRM_ERROR("radeon: writting more dword to ring than expected !\n");
+ }
+#endif
+ rdev->cp.ring[rdev->cp.wptr++] = v;
+ rdev->cp.wptr &= rdev->cp.ptr_mask;
+ rdev->cp.count_dw--;
+ rdev->cp.ring_free_dw--;
+}
+
void radeon_ib_bogus_cleanup(struct radeon_device *rdev)
{
struct radeon_ib *ib, *n;
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index 92e7ea73b7c5..e8422ae7fe74 100644
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ b/drivers/gpu/drm/radeon/radeon_state.c
@@ -272,12 +272,12 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
return 0;
}
-static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
- dev_priv,
- struct drm_file *file_priv,
- drm_radeon_kcmd_buffer_t *
- cmdbuf,
- unsigned int *cmdsz)
+static int radeon_check_and_fixup_packet3(drm_radeon_private_t *
+ dev_priv,
+ struct drm_file *file_priv,
+ drm_radeon_kcmd_buffer_t *
+ cmdbuf,
+ unsigned int *cmdsz)
{
u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
u32 offset, narrays;
@@ -446,8 +446,8 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
* CP hardware state programming functions
*/
-static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
- struct drm_clip_rect * box)
+static void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
+ struct drm_clip_rect * box)
{
RING_LOCALS;
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c
index aa6a66eeb4ec..89a6e1ecea8d 100644
--- a/drivers/gpu/drm/radeon/rs400.c
+++ b/drivers/gpu/drm/radeon/rs400.c
@@ -182,6 +182,9 @@ int rs400_gart_enable(struct radeon_device *rdev)
/* Enable gart */
WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | size_reg));
rs400_gart_tlb_flush(rdev);
+ DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+ (unsigned)(rdev->mc.gtt_size >> 20),
+ (unsigned long long)rdev->gart.table_addr);
rdev->gart.ready = true;
return 0;
}
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 4b5d0e6974a8..9320dd6404f6 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -484,6 +484,9 @@ static int rs600_gart_enable(struct radeon_device *rdev)
tmp = RREG32_MC(R_000009_MC_CNTL1);
WREG32_MC(R_000009_MC_CNTL1, (tmp | S_000009_ENABLE_PAGE_TABLES(1)));
rs600_gart_tlb_flush(rdev);
+ DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+ (unsigned)(rdev->mc.gtt_size >> 20),
+ (unsigned long long)rdev->gart.table_addr);
rdev->gart.ready = true;
return 0;
}
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index b13c2eedc321..87cc1feee3ac 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -161,6 +161,9 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
r600_pcie_gart_tlb_flush(rdev);
+ DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+ (unsigned)(rdev->mc.gtt_size >> 20),
+ (unsigned long long)rdev->gart.table_addr);
rdev->gart.ready = true;
return 0;
}
@@ -1184,8 +1187,6 @@ int rv770_resume(struct radeon_device *rdev)
int rv770_suspend(struct radeon_device *rdev)
{
- int r;
-
r600_audio_fini(rdev);
/* FIXME: we should wait for ring to be empty */
r700_cp_stop(rdev);
@@ -1193,14 +1194,8 @@ int rv770_suspend(struct radeon_device *rdev)
r600_irq_suspend(rdev);
radeon_wb_disable(rdev);
rv770_pcie_gart_disable(rdev);
- /* unpin shaders bo */
- if (rdev->r600_blit.shader_obj) {
- r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
- if (likely(r == 0)) {
- radeon_bo_unpin(rdev->r600_blit.shader_obj);
- radeon_bo_unreserve(rdev->r600_blit.shader_obj);
- }
- }
+ r600_blit_suspend(rdev);
+
return 0;
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index ef06194c5aa6..617b64678fc6 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1293,6 +1293,7 @@ int ttm_bo_create(struct ttm_bo_device *bdev,
return ret;
}
+EXPORT_SYMBOL(ttm_bo_create);
static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
unsigned mem_type, bool allow_errors)
diff --git a/drivers/gpu/drm/vmwgfx/Kconfig b/drivers/gpu/drm/vmwgfx/Kconfig
index 30ad13344f7b..794ff67c5701 100644
--- a/drivers/gpu/drm/vmwgfx/Kconfig
+++ b/drivers/gpu/drm/vmwgfx/Kconfig
@@ -7,7 +7,8 @@ config DRM_VMWGFX
select FB_CFB_IMAGEBLIT
select DRM_TTM
help
- KMS enabled DRM driver for SVGA2 virtual hardware.
-
- If unsure say n. The compiled module will be
- called vmwgfx.ko
+ Choose this option if you would like to run 3D acceleration
+ in a VMware virtual machine.
+ This is a KMS enabled DRM driver for the VMware SVGA2
+ virtual hardware.
+ The compiled module will be called "vmwgfx.ko".
diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile
index c9281a1b1d3b..586869c8c11f 100644
--- a/drivers/gpu/drm/vmwgfx/Makefile
+++ b/drivers/gpu/drm/vmwgfx/Makefile
@@ -4,6 +4,7 @@ ccflags-y := -Iinclude/drm
vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
- vmwgfx_overlay.o vmwgfx_fence.o vmwgfx_gmrid_manager.o
+ vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \
+ vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o
obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff --git a/drivers/gpu/drm/vmwgfx/svga3d_reg.h b/drivers/gpu/drm/vmwgfx/svga3d_reg.h
index 77cb45331000..d0e085ee8249 100644
--- a/drivers/gpu/drm/vmwgfx/svga3d_reg.h
+++ b/drivers/gpu/drm/vmwgfx/svga3d_reg.h
@@ -57,7 +57,8 @@ typedef enum {
SVGA3D_HWVERSION_WS6_B1 = SVGA3D_MAKE_HWVERSION(1, 1),
SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4),
SVGA3D_HWVERSION_WS65_B1 = SVGA3D_MAKE_HWVERSION(2, 0),
- SVGA3D_HWVERSION_CURRENT = SVGA3D_HWVERSION_WS65_B1,
+ SVGA3D_HWVERSION_WS8_B1 = SVGA3D_MAKE_HWVERSION(2, 1),
+ SVGA3D_HWVERSION_CURRENT = SVGA3D_HWVERSION_WS8_B1,
} SVGA3dHardwareVersion;
/*
@@ -67,7 +68,8 @@ typedef enum {
typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
#define SVGA3D_NUM_CLIPPLANES 6
#define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS 8
-
+#define SVGA3D_MAX_CONTEXT_IDS 256
+#define SVGA3D_MAX_SURFACE_IDS (32 * 1024)
/*
* Surface formats.
@@ -79,76 +81,91 @@ typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
*/
typedef enum SVGA3dSurfaceFormat {
- SVGA3D_FORMAT_INVALID = 0,
+ SVGA3D_FORMAT_INVALID = 0,
- SVGA3D_X8R8G8B8 = 1,
- SVGA3D_A8R8G8B8 = 2,
+ SVGA3D_X8R8G8B8 = 1,
+ SVGA3D_A8R8G8B8 = 2,
- SVGA3D_R5G6B5 = 3,
- SVGA3D_X1R5G5B5 = 4,
- SVGA3D_A1R5G5B5 = 5,
- SVGA3D_A4R4G4B4 = 6,
+ SVGA3D_R5G6B5 = 3,
+ SVGA3D_X1R5G5B5 = 4,
+ SVGA3D_A1R5G5B5 = 5,
+ SVGA3D_A4R4G4B4 = 6,
- SVGA3D_Z_D32 = 7,
- SVGA3D_Z_D16 = 8,
- SVGA3D_Z_D24S8 = 9,
- SVGA3D_Z_D15S1 = 10,
+ SVGA3D_Z_D32 = 7,
+ SVGA3D_Z_D16 = 8,
+ SVGA3D_Z_D24S8 = 9,
+ SVGA3D_Z_D15S1 = 10,
- SVGA3D_LUMINANCE8 = 11,
- SVGA3D_LUMINANCE4_ALPHA4 = 12,
- SVGA3D_LUMINANCE16 = 13,
- SVGA3D_LUMINANCE8_ALPHA8 = 14,
+ SVGA3D_LUMINANCE8 = 11,
+ SVGA3D_LUMINANCE4_ALPHA4 = 12,
+ SVGA3D_LUMINANCE16 = 13,
+ SVGA3D_LUMINANCE8_ALPHA8 = 14,
- SVGA3D_DXT1 = 15,
- SVGA3D_DXT2 = 16,
- SVGA3D_DXT3 = 17,
- SVGA3D_DXT4 = 18,
- SVGA3D_DXT5 = 19,
+ SVGA3D_DXT1 = 15,
+ SVGA3D_DXT2 = 16,
+ SVGA3D_DXT3 = 17,
+ SVGA3D_DXT4 = 18,
+ SVGA3D_DXT5 = 19,
- SVGA3D_BUMPU8V8 = 20,
- SVGA3D_BUMPL6V5U5 = 21,
- SVGA3D_BUMPX8L8V8U8 = 22,
- SVGA3D_BUMPL8V8U8 = 23,
+ SVGA3D_BUMPU8V8 = 20,
+ SVGA3D_BUMPL6V5U5 = 21,
+ SVGA3D_BUMPX8L8V8U8 = 22,
+ SVGA3D_BUMPL8V8U8 = 23,
- SVGA3D_ARGB_S10E5 = 24, /* 16-bit floating-point ARGB */
- SVGA3D_ARGB_S23E8 = 25, /* 32-bit floating-point ARGB */
+ SVGA3D_ARGB_S10E5 = 24, /* 16-bit floating-point ARGB */
+ SVGA3D_ARGB_S23E8 = 25, /* 32-bit floating-point ARGB */
- SVGA3D_A2R10G10B10 = 26,
+ SVGA3D_A2R10G10B10 = 26,
/* signed formats */
- SVGA3D_V8U8 = 27,
- SVGA3D_Q8W8V8U8 = 28,
- SVGA3D_CxV8U8 = 29,
+ SVGA3D_V8U8 = 27,
+ SVGA3D_Q8W8V8U8 = 28,
+ SVGA3D_CxV8U8 = 29,
/* mixed formats */
- SVGA3D_X8L8V8U8 = 30,
- SVGA3D_A2W10V10U10 = 31,
+ SVGA3D_X8L8V8U8 = 30,
+ SVGA3D_A2W10V10U10 = 31,
- SVGA3D_ALPHA8 = 32,
+ SVGA3D_ALPHA8 = 32,
/* Single- and dual-component floating point formats */
- SVGA3D_R_S10E5 = 33,
- SVGA3D_R_S23E8 = 34,
- SVGA3D_RG_S10E5 = 35,
- SVGA3D_RG_S23E8 = 36,
+ SVGA3D_R_S10E5 = 33,
+ SVGA3D_R_S23E8 = 34,
+ SVGA3D_RG_S10E5 = 35,
+ SVGA3D_RG_S23E8 = 36,
/*
* Any surface can be used as a buffer object, but SVGA3D_BUFFER is
* the most efficient format to use when creating new surfaces
* expressly for index or vertex data.
*/
- SVGA3D_BUFFER = 37,
- SVGA3D_Z_D24X8 = 38,
+ SVGA3D_BUFFER = 37,
+
+ SVGA3D_Z_D24X8 = 38,
- SVGA3D_V16U16 = 39,
+ SVGA3D_V16U16 = 39,
- SVGA3D_G16R16 = 40,
- SVGA3D_A16B16G16R16 = 41,
+ SVGA3D_G16R16 = 40,
+ SVGA3D_A16B16G16R16 = 41,
/* Packed Video formats */
- SVGA3D_UYVY = 42,
- SVGA3D_YUY2 = 43,
+ SVGA3D_UYVY = 42,
+ SVGA3D_YUY2 = 43,
+
+ /* Planar video formats */
+ SVGA3D_NV12 = 44,
+
+ /* Video format with alpha */
+ SVGA3D_AYUV = 45,
+
+ SVGA3D_BC4_UNORM = 108,
+ SVGA3D_BC5_UNORM = 111,
+
+ /* Advanced D3D9 depth formats. */
+ SVGA3D_Z_DF16 = 118,
+ SVGA3D_Z_DF24 = 119,
+ SVGA3D_Z_D24S8_INT = 120,
SVGA3D_FORMAT_MAX
} SVGA3dSurfaceFormat;
@@ -414,10 +431,20 @@ typedef enum {
SVGA3D_RS_SRCBLENDALPHA = 94, /* SVGA3dBlendOp */
SVGA3D_RS_DSTBLENDALPHA = 95, /* SVGA3dBlendOp */
SVGA3D_RS_BLENDEQUATIONALPHA = 96, /* SVGA3dBlendEquation */
+ SVGA3D_RS_TRANSPARENCYANTIALIAS = 97, /* SVGA3dTransparencyAntialiasType */
+ SVGA3D_RS_LINEAA = 98, /* SVGA3dBool */
+ SVGA3D_RS_LINEWIDTH = 99, /* float */
SVGA3D_RS_MAX
} SVGA3dRenderStateName;
typedef enum {
+ SVGA3D_TRANSPARENCYANTIALIAS_NORMAL = 0,
+ SVGA3D_TRANSPARENCYANTIALIAS_ALPHATOCOVERAGE = 1,
+ SVGA3D_TRANSPARENCYANTIALIAS_SUPERSAMPLE = 2,
+ SVGA3D_TRANSPARENCYANTIALIAS_MAX
+} SVGA3dTransparencyAntialiasType;
+
+typedef enum {
SVGA3D_VERTEXMATERIAL_NONE = 0, /* Use the value in the current material */
SVGA3D_VERTEXMATERIAL_DIFFUSE = 1, /* Use the value in the diffuse component */
SVGA3D_VERTEXMATERIAL_SPECULAR = 2, /* Use the value in the specular component */
@@ -728,10 +755,10 @@ typedef enum {
SVGA3D_TEX_FILTER_NEAREST = 1,
SVGA3D_TEX_FILTER_LINEAR = 2,
SVGA3D_TEX_FILTER_ANISOTROPIC = 3,
- SVGA3D_TEX_FILTER_FLATCUBIC = 4, // Deprecated, not implemented
- SVGA3D_TEX_FILTER_GAUSSIANCUBIC = 5, // Deprecated, not implemented
- SVGA3D_TEX_FILTER_PYRAMIDALQUAD = 6, // Not currently implemented
- SVGA3D_TEX_FILTER_GAUSSIANQUAD = 7, // Not currently implemented
+ SVGA3D_TEX_FILTER_FLATCUBIC = 4, /* Deprecated, not implemented */
+ SVGA3D_TEX_FILTER_GAUSSIANCUBIC = 5, /* Deprecated, not implemented */
+ SVGA3D_TEX_FILTER_PYRAMIDALQUAD = 6, /* Not currently implemented */
+ SVGA3D_TEX_FILTER_GAUSSIANQUAD = 7, /* Not currently implemented */
SVGA3D_TEX_FILTER_MAX
} SVGA3dTextureFilter;
@@ -799,19 +826,19 @@ typedef enum {
typedef enum {
SVGA3D_DECLUSAGE_POSITION = 0,
- SVGA3D_DECLUSAGE_BLENDWEIGHT, // 1
- SVGA3D_DECLUSAGE_BLENDINDICES, // 2
- SVGA3D_DECLUSAGE_NORMAL, // 3
- SVGA3D_DECLUSAGE_PSIZE, // 4
- SVGA3D_DECLUSAGE_TEXCOORD, // 5
- SVGA3D_DECLUSAGE_TANGENT, // 6
- SVGA3D_DECLUSAGE_BINORMAL, // 7
- SVGA3D_DECLUSAGE_TESSFACTOR, // 8
- SVGA3D_DECLUSAGE_POSITIONT, // 9
- SVGA3D_DECLUSAGE_COLOR, // 10
- SVGA3D_DECLUSAGE_FOG, // 11
- SVGA3D_DECLUSAGE_DEPTH, // 12
- SVGA3D_DECLUSAGE_SAMPLE, // 13
+ SVGA3D_DECLUSAGE_BLENDWEIGHT, /* 1 */
+ SVGA3D_DECLUSAGE_BLENDINDICES, /* 2 */
+ SVGA3D_DECLUSAGE_NORMAL, /* 3 */
+ SVGA3D_DECLUSAGE_PSIZE, /* 4 */
+ SVGA3D_DECLUSAGE_TEXCOORD, /* 5 */
+ SVGA3D_DECLUSAGE_TANGENT, /* 6 */
+ SVGA3D_DECLUSAGE_BINORMAL, /* 7 */
+ SVGA3D_DECLUSAGE_TESSFACTOR, /* 8 */
+ SVGA3D_DECLUSAGE_POSITIONT, /* 9 */
+ SVGA3D_DECLUSAGE_COLOR, /* 10 */
+ SVGA3D_DECLUSAGE_FOG, /* 11 */
+ SVGA3D_DECLUSAGE_DEPTH, /* 12 */
+ SVGA3D_DECLUSAGE_SAMPLE, /* 13 */
SVGA3D_DECLUSAGE_MAX
} SVGA3dDeclUsage;
@@ -819,10 +846,10 @@ typedef enum {
SVGA3D_DECLMETHOD_DEFAULT = 0,
SVGA3D_DECLMETHOD_PARTIALU,
SVGA3D_DECLMETHOD_PARTIALV,
- SVGA3D_DECLMETHOD_CROSSUV, // Normal
+ SVGA3D_DECLMETHOD_CROSSUV, /* Normal */
SVGA3D_DECLMETHOD_UV,
- SVGA3D_DECLMETHOD_LOOKUP, // Lookup a displacement map
- SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map
+ SVGA3D_DECLMETHOD_LOOKUP, /* Lookup a displacement map */
+ SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, /* Lookup a pre-sampled displacement map */
} SVGA3dDeclMethod;
typedef enum {
@@ -930,7 +957,6 @@ typedef enum {
} SVGA3dCubeFace;
typedef enum {
- SVGA3D_SHADERTYPE_COMPILED_DX8 = 0,
SVGA3D_SHADERTYPE_VS = 1,
SVGA3D_SHADERTYPE_PS = 2,
SVGA3D_SHADERTYPE_MAX
@@ -968,12 +994,18 @@ typedef enum {
} SVGA3dTransferType;
/*
- * The maximum number vertex arrays we're guaranteed to support in
+ * The maximum number of vertex arrays we're guaranteed to support in
* SVGA_3D_CMD_DRAWPRIMITIVES.
*/
#define SVGA3D_MAX_VERTEX_ARRAYS 32
/*
+ * The maximum number of primitive ranges we're guaranteed to support
+ * in SVGA_3D_CMD_DRAWPRIMITIVES.
+ */
+#define SVGA3D_MAX_DRAW_PRIMITIVE_RANGES 32
+
+/*
* Identifiers for commands in the command FIFO.
*
* IDs between 1000 and 1039 (inclusive) were used by obsolete versions of
@@ -990,7 +1022,7 @@ typedef enum {
#define SVGA_3D_CMD_LEGACY_BASE 1000
#define SVGA_3D_CMD_BASE 1040
-#define SVGA_3D_CMD_SURFACE_DEFINE SVGA_3D_CMD_BASE + 0
+#define SVGA_3D_CMD_SURFACE_DEFINE SVGA_3D_CMD_BASE + 0 /* Deprecated */
#define SVGA_3D_CMD_SURFACE_DESTROY SVGA_3D_CMD_BASE + 1
#define SVGA_3D_CMD_SURFACE_COPY SVGA_3D_CMD_BASE + 2
#define SVGA_3D_CMD_SURFACE_STRETCHBLT SVGA_3D_CMD_BASE + 3
@@ -1008,7 +1040,7 @@ typedef enum {
#define SVGA_3D_CMD_SETVIEWPORT SVGA_3D_CMD_BASE + 15
#define SVGA_3D_CMD_SETCLIPPLANE SVGA_3D_CMD_BASE + 16
#define SVGA_3D_CMD_CLEAR SVGA_3D_CMD_BASE + 17
-#define SVGA_3D_CMD_PRESENT SVGA_3D_CMD_BASE + 18 // Deprecated
+#define SVGA_3D_CMD_PRESENT SVGA_3D_CMD_BASE + 18 /* Deprecated */
#define SVGA_3D_CMD_SHADER_DEFINE SVGA_3D_CMD_BASE + 19
#define SVGA_3D_CMD_SHADER_DESTROY SVGA_3D_CMD_BASE + 20
#define SVGA_3D_CMD_SET_SHADER SVGA_3D_CMD_BASE + 21
@@ -1018,9 +1050,13 @@ typedef enum {
#define SVGA_3D_CMD_BEGIN_QUERY SVGA_3D_CMD_BASE + 25
#define SVGA_3D_CMD_END_QUERY SVGA_3D_CMD_BASE + 26
#define SVGA_3D_CMD_WAIT_FOR_QUERY SVGA_3D_CMD_BASE + 27
-#define SVGA_3D_CMD_PRESENT_READBACK SVGA_3D_CMD_BASE + 28 // Deprecated
+#define SVGA_3D_CMD_PRESENT_READBACK SVGA_3D_CMD_BASE + 28 /* Deprecated */
#define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29
-#define SVGA_3D_CMD_MAX SVGA_3D_CMD_BASE + 30
+#define SVGA_3D_CMD_SURFACE_DEFINE_V2 SVGA_3D_CMD_BASE + 30
+#define SVGA_3D_CMD_GENERATE_MIPMAPS SVGA_3D_CMD_BASE + 31
+#define SVGA_3D_CMD_ACTIVATE_SURFACE SVGA_3D_CMD_BASE + 40
+#define SVGA_3D_CMD_DEACTIVATE_SURFACE SVGA_3D_CMD_BASE + 41
+#define SVGA_3D_CMD_MAX SVGA_3D_CMD_BASE + 42
#define SVGA_3D_CMD_FUTURE_MAX 2000
@@ -1031,9 +1067,9 @@ typedef enum {
typedef struct {
union {
struct {
- uint16 function; // SVGA3dFogFunction
- uint8 type; // SVGA3dFogType
- uint8 base; // SVGA3dFogBase
+ uint16 function; /* SVGA3dFogFunction */
+ uint8 type; /* SVGA3dFogType */
+ uint8 base; /* SVGA3dFogBase */
};
uint32 uintValue;
};
@@ -1109,6 +1145,8 @@ typedef enum {
SVGA3D_SURFACE_HINT_RENDERTARGET = (1 << 6),
SVGA3D_SURFACE_HINT_DEPTHSTENCIL = (1 << 7),
SVGA3D_SURFACE_HINT_WRITEONLY = (1 << 8),
+ SVGA3D_SURFACE_MASKABLE_ANTIALIAS = (1 << 9),
+ SVGA3D_SURFACE_AUTOGENMIPMAPS = (1 << 10),
} SVGA3dSurfaceFlags;
typedef
@@ -1121,6 +1159,12 @@ struct {
uint32 sid;
SVGA3dSurfaceFlags surfaceFlags;
SVGA3dSurfaceFormat format;
+ /*
+ * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace
+ * structures must have the same value of numMipLevels field.
+ * Otherwise, all but the first SVGA3dSurfaceFace structures must have the
+ * numMipLevels set to 0.
+ */
SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES];
/*
* Followed by an SVGA3dSize structure for each mip level in each face.
@@ -1135,6 +1179,31 @@ struct {
typedef
struct {
+ uint32 sid;
+ SVGA3dSurfaceFlags surfaceFlags;
+ SVGA3dSurfaceFormat format;
+ /*
+ * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace
+ * structures must have the same value of numMipLevels field.
+ * Otherwise, all but the first SVGA3dSurfaceFace structures must have the
+ * numMipLevels set to 0.
+ */
+ SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES];
+ uint32 multisampleCount;
+ SVGA3dTextureFilter autogenFilter;
+ /*
+ * Followed by an SVGA3dSize structure for each mip level in each face.
+ *
+ * A note on surface sizes: Sizes are always specified in pixels,
+ * even if the true surface size is not a multiple of the minimum
+ * block size of the surface's format. For example, a 3x3x1 DXT1
+ * compressed texture would actually be stored as a 4x4x1 image in
+ * memory.
+ */
+} SVGA3dCmdDefineSurface_v2; /* SVGA_3D_CMD_SURFACE_DEFINE_V2 */
+
+typedef
+struct {
uint32 sid;
} SVGA3dCmdDestroySurface; /* SVGA_3D_CMD_SURFACE_DESTROY */
@@ -1474,10 +1543,12 @@ struct {
* SVGA3dCmdDrawPrimitives structure. In order,
* they are:
*
- * 1. SVGA3dVertexDecl, quantity 'numVertexDecls'
- * 2. SVGA3dPrimitiveRange, quantity 'numRanges'
+ * 1. SVGA3dVertexDecl, quantity 'numVertexDecls', but no more than
+ * SVGA3D_MAX_VERTEX_ARRAYS;
+ * 2. SVGA3dPrimitiveRange, quantity 'numRanges', but no more than
+ * SVGA3D_MAX_DRAW_PRIMITIVE_RANGES;
* 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains
- * the frequency divisor for this the corresponding vertex decl)
+ * the frequency divisor for the corresponding vertex decl).
*/
} SVGA3dCmdDrawPrimitives; /* SVGA_3D_CMD_DRAWPRIMITIVES */
@@ -1671,6 +1742,12 @@ struct {
/* Clipping: zero or more SVGASignedRects follow */
} SVGA3dCmdBlitSurfaceToScreen; /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */
+typedef
+struct {
+ uint32 sid;
+ SVGA3dTextureFilter filter;
+} SVGA3dCmdGenerateMipmaps; /* SVGA_3D_CMD_GENERATE_MIPMAPS */
+
/*
* Capability query index.
@@ -1774,6 +1851,32 @@ typedef enum {
SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = 67,
SVGA3D_DEVCAP_SURFACEFMT_UYVY = 68,
SVGA3D_DEVCAP_SURFACEFMT_YUY2 = 69,
+ SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = 70,
+ SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = 71,
+ SVGA3D_DEVCAP_ALPHATOCOVERAGE = 72,
+ SVGA3D_DEVCAP_SUPERSAMPLE = 73,
+ SVGA3D_DEVCAP_AUTOGENMIPMAPS = 74,
+ SVGA3D_DEVCAP_SURFACEFMT_NV12 = 75,
+ SVGA3D_DEVCAP_SURFACEFMT_AYUV = 76,
+
+ /*
+ * This is the maximum number of SVGA context IDs that the guest
+ * can define using SVGA_3D_CMD_CONTEXT_DEFINE.
+ */
+ SVGA3D_DEVCAP_MAX_CONTEXT_IDS = 77,
+
+ /*
+ * This is the maximum number of SVGA surface IDs that the guest
+ * can define using SVGA_3D_CMD_SURFACE_DEFINE*.
+ */
+ SVGA3D_DEVCAP_MAX_SURFACE_IDS = 78,
+
+ SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = 79,
+ SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = 80,
+ SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = 81,
+
+ SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM = 82,
+ SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM = 83,
/*
* Don't add new caps into the previous section; the values in this
diff --git a/drivers/gpu/drm/vmwgfx/svga_escape.h b/drivers/gpu/drm/vmwgfx/svga_escape.h
index 7b85e9b8c854..8e8d9682e018 100644
--- a/drivers/gpu/drm/vmwgfx/svga_escape.h
+++ b/drivers/gpu/drm/vmwgfx/svga_escape.h
@@ -75,7 +75,7 @@
*/
#define SVGA_ESCAPE_VMWARE_HINT 0x00030000
-#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN 0x00030001 // Deprecated
+#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN 0x00030001 /* Deprecated */
typedef
struct {
diff --git a/drivers/gpu/drm/vmwgfx/svga_overlay.h b/drivers/gpu/drm/vmwgfx/svga_overlay.h
index f753d73c14b4..f38416fcb046 100644
--- a/drivers/gpu/drm/vmwgfx/svga_overlay.h
+++ b/drivers/gpu/drm/vmwgfx/svga_overlay.h
@@ -38,9 +38,9 @@
* Video formats we support
*/
-#define VMWARE_FOURCC_YV12 0x32315659 // 'Y' 'V' '1' '2'
-#define VMWARE_FOURCC_YUY2 0x32595559 // 'Y' 'U' 'Y' '2'
-#define VMWARE_FOURCC_UYVY 0x59565955 // 'U' 'Y' 'V' 'Y'
+#define VMWARE_FOURCC_YV12 0x32315659 /* 'Y' 'V' '1' '2' */
+#define VMWARE_FOURCC_YUY2 0x32595559 /* 'Y' 'U' 'Y' '2' */
+#define VMWARE_FOURCC_UYVY 0x59565955 /* 'U' 'Y' 'V' 'Y' */
typedef enum {
SVGA_OVERLAY_FORMAT_INVALID = 0,
@@ -68,7 +68,7 @@ struct SVGAEscapeVideoSetRegs {
uint32 streamId;
} header;
- // May include zero or more items.
+ /* May include zero or more items. */
struct {
uint32 registerId;
uint32 value;
@@ -134,12 +134,12 @@ struct {
*/
static inline bool
-VMwareVideoGetAttributes(const SVGAOverlayFormat format, // IN
- uint32 *width, // IN / OUT
- uint32 *height, // IN / OUT
- uint32 *size, // OUT
- uint32 *pitches, // OUT (optional)
- uint32 *offsets) // OUT (optional)
+VMwareVideoGetAttributes(const SVGAOverlayFormat format, /* IN */
+ uint32 *width, /* IN / OUT */
+ uint32 *height, /* IN / OUT */
+ uint32 *size, /* OUT */
+ uint32 *pitches, /* OUT (optional) */
+ uint32 *offsets) /* OUT (optional) */
{
int tmp;
@@ -198,4 +198,4 @@ VMwareVideoGetAttributes(const SVGAOverlayFormat format, // IN
return true;
}
-#endif // _SVGA_OVERLAY_H_
+#endif /* _SVGA_OVERLAY_H_ */
diff --git a/drivers/gpu/drm/vmwgfx/svga_reg.h b/drivers/gpu/drm/vmwgfx/svga_reg.h
index 1b96c2ec07dd..01f63cb49678 100644
--- a/drivers/gpu/drm/vmwgfx/svga_reg.h
+++ b/drivers/gpu/drm/vmwgfx/svga_reg.h
@@ -39,6 +39,15 @@
#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405
/*
+ * SVGA_REG_ENABLE bit definitions.
+ */
+#define SVGA_REG_ENABLE_DISABLE 0
+#define SVGA_REG_ENABLE_ENABLE 1
+#define SVGA_REG_ENABLE_HIDE 2
+#define SVGA_REG_ENABLE_ENABLE_HIDE (SVGA_REG_ENABLE_ENABLE |\
+ SVGA_REG_ENABLE_HIDE)
+
+/*
* Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned
* cursor bypass mode. This is still supported, but no new guest
* drivers should use it.
@@ -158,7 +167,9 @@ enum {
SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44,
SVGA_REG_TRACES = 45, /* Enable trace-based updates even when FIFO is on */
- SVGA_REG_TOP = 46, /* Must be 1 more than the last register */
+ SVGA_REG_GMRS_MAX_PAGES = 46, /* Maximum number of 4KB pages for all GMRs */
+ SVGA_REG_MEMORY_SIZE = 47, /* Total dedicated device memory excluding FIFO */
+ SVGA_REG_TOP = 48, /* Must be 1 more than the last register */
SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */
/* Next 768 (== 256*3) registers exist for colormap */
@@ -265,7 +276,7 @@ enum {
* possible.
*/
#define SVGA_GMR_NULL ((uint32) -1)
-#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) // Guest Framebuffer (GFB)
+#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) /* Guest Framebuffer (GFB) */
typedef
struct SVGAGuestMemDescriptor {
@@ -306,13 +317,35 @@ struct SVGAGMRImageFormat {
struct {
uint32 bitsPerPixel : 8;
uint32 colorDepth : 8;
- uint32 reserved : 16; // Must be zero
+ uint32 reserved : 16; /* Must be zero */
};
uint32 value;
};
} SVGAGMRImageFormat;
+typedef
+struct SVGAGuestImage {
+ SVGAGuestPtr ptr;
+
+ /*
+ * A note on interpretation of pitch: This value of pitch is the
+ * number of bytes between vertically adjacent image
+ * blocks. Normally this is the number of bytes between the first
+ * pixel of two adjacent scanlines. With compressed textures,
+ * however, this may represent the number of bytes between
+ * compression blocks rather than between rows of pixels.
+ *
+ * XXX: Compressed textures currently must be tightly packed in guest memory.
+ *
+ * If the image is 1-dimensional, pitch is ignored.
+ *
+ * If 'pitch' is zero, the SVGA3D device calculates a pitch value
+ * assuming each row of blocks is tightly packed.
+ */
+ uint32 pitch;
+} SVGAGuestImage;
+
/*
* SVGAColorBGRX --
*
@@ -328,7 +361,7 @@ struct SVGAColorBGRX {
uint32 b : 8;
uint32 g : 8;
uint32 r : 8;
- uint32 x : 8; // Unused
+ uint32 x : 8; /* Unused */
};
uint32 value;
@@ -370,23 +403,34 @@ struct SVGASignedPoint {
* Note the holes in the bitfield. Missing bits have been deprecated,
* and must not be reused. Those capabilities will never be reported
* by new versions of the SVGA device.
+ *
+ * SVGA_CAP_GMR2 --
+ * Provides asynchronous commands to define and remap guest memory
+ * regions. Adds device registers SVGA_REG_GMRS_MAX_PAGES and
+ * SVGA_REG_MEMORY_SIZE.
+ *
+ * SVGA_CAP_SCREEN_OBJECT_2 --
+ * Allow screen object support, and require backing stores from the
+ * guest for each screen object.
*/
#define SVGA_CAP_NONE 0x00000000
#define SVGA_CAP_RECT_COPY 0x00000002
#define SVGA_CAP_CURSOR 0x00000020
-#define SVGA_CAP_CURSOR_BYPASS 0x00000040 // Legacy (Use Cursor Bypass 3 instead)
-#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 // Legacy (Use Cursor Bypass 3 instead)
+#define SVGA_CAP_CURSOR_BYPASS 0x00000040 /* Legacy (Use Cursor Bypass 3 instead) */
+#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 /* Legacy (Use Cursor Bypass 3 instead) */
#define SVGA_CAP_8BIT_EMULATION 0x00000100
#define SVGA_CAP_ALPHA_CURSOR 0x00000200
#define SVGA_CAP_3D 0x00004000
#define SVGA_CAP_EXTENDED_FIFO 0x00008000
-#define SVGA_CAP_MULTIMON 0x00010000 // Legacy multi-monitor support
+#define SVGA_CAP_MULTIMON 0x00010000 /* Legacy multi-monitor support */
#define SVGA_CAP_PITCHLOCK 0x00020000
#define SVGA_CAP_IRQMASK 0x00040000
-#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 // Legacy multi-monitor support
+#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 /* Legacy multi-monitor support */
#define SVGA_CAP_GMR 0x00100000
#define SVGA_CAP_TRACES 0x00200000
+#define SVGA_CAP_GMR2 0x00400000
+#define SVGA_CAP_SCREEN_OBJECT_2 0x00800000
/*
@@ -431,7 +475,7 @@ enum {
SVGA_FIFO_CAPABILITIES = 4,
SVGA_FIFO_FLAGS,
- // Valid with SVGA_FIFO_CAP_FENCE:
+ /* Valid with SVGA_FIFO_CAP_FENCE: */
SVGA_FIFO_FENCE,
/*
@@ -444,33 +488,47 @@ enum {
* extended FIFO.
*/
- // Valid if exists (i.e. if extended FIFO enabled):
+ /* Valid if exists (i.e. if extended FIFO enabled): */
SVGA_FIFO_3D_HWVERSION, /* See SVGA3dHardwareVersion in svga3d_reg.h */
- // Valid with SVGA_FIFO_CAP_PITCHLOCK:
+ /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */
SVGA_FIFO_PITCHLOCK,
- // Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3:
+ /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */
SVGA_FIFO_CURSOR_ON, /* Cursor bypass 3 show/hide register */
SVGA_FIFO_CURSOR_X, /* Cursor bypass 3 x register */
SVGA_FIFO_CURSOR_Y, /* Cursor bypass 3 y register */
SVGA_FIFO_CURSOR_COUNT, /* Incremented when any of the other 3 change */
SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */
- // Valid with SVGA_FIFO_CAP_RESERVE:
+ /* Valid with SVGA_FIFO_CAP_RESERVE: */
SVGA_FIFO_RESERVED, /* Bytes past NEXT_CMD with real contents */
/*
- * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT:
+ * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2:
*
* By default this is SVGA_ID_INVALID, to indicate that the cursor
* coordinates are specified relative to the virtual root. If this
* is set to a specific screen ID, cursor position is reinterpreted
- * as a signed offset relative to that screen's origin. This is the
- * only way to place the cursor on a non-rooted screen.
+ * as a signed offset relative to that screen's origin.
*/
SVGA_FIFO_CURSOR_SCREEN_ID,
/*
+ * Valid with SVGA_FIFO_CAP_DEAD
+ *
+ * An arbitrary value written by the host, drivers should not use it.
+ */
+ SVGA_FIFO_DEAD,
+
+ /*
+ * Valid with SVGA_FIFO_CAP_3D_HWVERSION_REVISED:
+ *
+ * Contains 3D HWVERSION (see SVGA3dHardwareVersion in svga3d_reg.h)
+ * on platforms that can enforce graphics resource limits.
+ */
+ SVGA_FIFO_3D_HWVERSION_REVISED,
+
+ /*
* XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new
* registers, but this must be done carefully and with judicious use of
* capability bits, since comparisons based on SVGA_FIFO_MIN aren't
@@ -508,7 +566,7 @@ enum {
* sets SVGA_FIFO_MIN high enough to leave room for them.
*/
- // Valid if register exists:
+ /* Valid if register exists: */
SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */
SVGA_FIFO_FENCE_GOAL, /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */
SVGA_FIFO_BUSY, /* See "FIFO Synchronization Registers" */
@@ -709,6 +767,37 @@ enum {
*
* - When a screen is resized, either using Screen Object commands or
* legacy multimon registers, its contents are preserved.
+ *
+ * SVGA_FIFO_CAP_GMR2 --
+ *
+ * Provides new commands to define and remap guest memory regions (GMR).
+ *
+ * New 2D commands:
+ * DEFINE_GMR2, REMAP_GMR2.
+ *
+ * SVGA_FIFO_CAP_3D_HWVERSION_REVISED --
+ *
+ * Indicates new register SVGA_FIFO_3D_HWVERSION_REVISED exists.
+ * This register may replace SVGA_FIFO_3D_HWVERSION on platforms
+ * that enforce graphics resource limits. This allows the platform
+ * to clear SVGA_FIFO_3D_HWVERSION and disable 3D in legacy guest
+ * drivers that do not limit their resources.
+ *
+ * Note this is an alias to SVGA_FIFO_CAP_GMR2 because these indicators
+ * are codependent (and thus we use a single capability bit).
+ *
+ * SVGA_FIFO_CAP_SCREEN_OBJECT_2 --
+ *
+ * Modifies the DEFINE_SCREEN command to include a guest provided
+ * backing store in GMR memory and the bytesPerLine for the backing
+ * store. This capability requires the use of a backing store when
+ * creating screen objects. However if SVGA_FIFO_CAP_SCREEN_OBJECT
+ * is present then backing stores are optional.
+ *
+ * SVGA_FIFO_CAP_DEAD --
+ *
+ * Drivers should not use this cap bit. This cap bit can not be
+ * reused since some hosts already expose it.
*/
#define SVGA_FIFO_CAP_NONE 0
@@ -720,6 +809,10 @@ enum {
#define SVGA_FIFO_CAP_ESCAPE (1<<5)
#define SVGA_FIFO_CAP_RESERVE (1<<6)
#define SVGA_FIFO_CAP_SCREEN_OBJECT (1<<7)
+#define SVGA_FIFO_CAP_GMR2 (1<<8)
+#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED SVGA_FIFO_CAP_GMR2
+#define SVGA_FIFO_CAP_SCREEN_OBJECT_2 (1<<9)
+#define SVGA_FIFO_CAP_DEAD (1<<10)
/*
@@ -730,7 +823,7 @@ enum {
#define SVGA_FIFO_FLAG_NONE 0
#define SVGA_FIFO_FLAG_ACCELFRONT (1<<0)
-#define SVGA_FIFO_FLAG_RESERVED (1<<31) // Internal use only
+#define SVGA_FIFO_FLAG_RESERVED (1<<31) /* Internal use only */
/*
* FIFO reservation sentinel value
@@ -763,22 +856,22 @@ enum {
SVGA_VIDEO_DATA_OFFSET,
SVGA_VIDEO_FORMAT,
SVGA_VIDEO_COLORKEY,
- SVGA_VIDEO_SIZE, // Deprecated
+ SVGA_VIDEO_SIZE, /* Deprecated */
SVGA_VIDEO_WIDTH,
SVGA_VIDEO_HEIGHT,
SVGA_VIDEO_SRC_X,
SVGA_VIDEO_SRC_Y,
SVGA_VIDEO_SRC_WIDTH,
SVGA_VIDEO_SRC_HEIGHT,
- SVGA_VIDEO_DST_X, // Signed int32
- SVGA_VIDEO_DST_Y, // Signed int32
+ SVGA_VIDEO_DST_X, /* Signed int32 */
+ SVGA_VIDEO_DST_Y, /* Signed int32 */
SVGA_VIDEO_DST_WIDTH,
SVGA_VIDEO_DST_HEIGHT,
SVGA_VIDEO_PITCH_1,
SVGA_VIDEO_PITCH_2,
SVGA_VIDEO_PITCH_3,
- SVGA_VIDEO_DATA_GMRID, // Optional, defaults to SVGA_GMR_FRAMEBUFFER
- SVGA_VIDEO_DST_SCREEN_ID, // Optional, defaults to virtual coords (SVGA_ID_INVALID)
+ SVGA_VIDEO_DATA_GMRID, /* Optional, defaults to SVGA_GMR_FRAMEBUFFER */
+ SVGA_VIDEO_DST_SCREEN_ID, /* Optional, defaults to virtual coords (SVGA_ID_INVALID) */
SVGA_VIDEO_NUM_REGS
};
@@ -829,15 +922,51 @@ typedef struct SVGAOverlayUnit {
* compatibility. New flags can be added, and the struct may grow,
* but existing fields must retain their meaning.
*
+ * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2 are required fields of
+ * a SVGAGuestPtr that is used to back the screen contents. This
+ * memory must come from the GFB. The guest is not allowed to
+ * access the memory and doing so will have undefined results. The
+ * backing store is required to be page aligned and the size is
+ * padded to the next page boundry. The number of pages is:
+ * (bytesPerLine * size.width * 4 + PAGE_SIZE - 1) / PAGE_SIZE
+ *
+ * The pitch in the backingStore is required to be at least large
+ * enough to hold a 32bbp scanline. It is recommended that the
+ * driver pad bytesPerLine for a potential performance win.
+ *
+ * The cloneCount field is treated as a hint from the guest that
+ * the user wants this display to be cloned, countCount times. A
+ * value of zero means no cloning should happen.
+ */
+
+#define SVGA_SCREEN_MUST_BE_SET (1 << 0) /* Must be set or results undefined */
+#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET /* Deprecated */
+#define SVGA_SCREEN_IS_PRIMARY (1 << 1) /* Guest considers this screen to be 'primary' */
+#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) /* Guest is running a fullscreen app here */
+
+/*
+ * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When the screen is
+ * deactivated the base layer is defined to lose all contents and
+ * become black. When a screen is deactivated the backing store is
+ * optional. When set backingPtr and bytesPerLine will be ignored.
*/
+#define SVGA_SCREEN_DEACTIVATE (1 << 3)
-#define SVGA_SCREEN_HAS_ROOT (1 << 0) // Screen is present in the virtual coord space
-#define SVGA_SCREEN_IS_PRIMARY (1 << 1) // Guest considers this screen to be 'primary'
-#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) // Guest is running a fullscreen app here
+/*
+ * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When this flag is set
+ * the screen contents will be outputted as all black to the user
+ * though the base layer contents is preserved. The screen base layer
+ * can still be read and written to like normal though the no visible
+ * effect will be seen by the user. When the flag is changed the
+ * screen will be blanked or redrawn to the current contents as needed
+ * without any extra commands from the driver. This flag only has an
+ * effect when the screen is not deactivated.
+ */
+#define SVGA_SCREEN_BLANKING (1 << 4)
typedef
struct SVGAScreenObject {
- uint32 structSize; // sizeof(SVGAScreenObject)
+ uint32 structSize; /* sizeof(SVGAScreenObject) */
uint32 id;
uint32 flags;
struct {
@@ -847,7 +976,14 @@ struct SVGAScreenObject {
struct {
int32 x;
int32 y;
- } root; // Only used if SVGA_SCREEN_HAS_ROOT is set.
+ } root;
+
+ /*
+ * Added and required by SVGA_FIFO_CAP_SCREEN_OBJECT_2, optional
+ * with SVGA_FIFO_CAP_SCREEN_OBJECT.
+ */
+ SVGAGuestImage backingStore;
+ uint32 cloneCount;
} SVGAScreenObject;
@@ -885,6 +1021,8 @@ typedef enum {
SVGA_CMD_BLIT_SCREEN_TO_GMRFB = 38,
SVGA_CMD_ANNOTATION_FILL = 39,
SVGA_CMD_ANNOTATION_COPY = 40,
+ SVGA_CMD_DEFINE_GMR2 = 41,
+ SVGA_CMD_REMAP_GMR2 = 42,
SVGA_CMD_MAX
} SVGAFifoCmdId;
@@ -920,7 +1058,7 @@ typedef enum {
*/
typedef
-struct {
+struct SVGAFifoCmdUpdate {
uint32 x;
uint32 y;
uint32 width;
@@ -939,7 +1077,7 @@ struct {
*/
typedef
-struct {
+struct SVGAFifoCmdRectCopy {
uint32 srcX;
uint32 srcY;
uint32 destX;
@@ -963,14 +1101,14 @@ struct {
*/
typedef
-struct {
- uint32 id; // Reserved, must be zero.
+struct SVGAFifoCmdDefineCursor {
+ uint32 id; /* Reserved, must be zero. */
uint32 hotspotX;
uint32 hotspotY;
uint32 width;
uint32 height;
- uint32 andMaskDepth; // Value must be 1 or equal to BITS_PER_PIXEL
- uint32 xorMaskDepth; // Value must be 1 or equal to BITS_PER_PIXEL
+ uint32 andMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */
+ uint32 xorMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */
/*
* Followed by scanline data for AND mask, then XOR mask.
* Each scanline is padded to a 32-bit boundary.
@@ -992,8 +1130,8 @@ struct {
*/
typedef
-struct {
- uint32 id; // Reserved, must be zero.
+struct SVGAFifoCmdDefineAlphaCursor {
+ uint32 id; /* Reserved, must be zero. */
uint32 hotspotX;
uint32 hotspotY;
uint32 width;
@@ -1015,7 +1153,7 @@ struct {
*/
typedef
-struct {
+struct SVGAFifoCmdUpdateVerbose {
uint32 x;
uint32 y;
uint32 width;
@@ -1040,13 +1178,13 @@ struct {
#define SVGA_ROP_COPY 0x03
typedef
-struct {
- uint32 color; // In the same format as the GFB
+struct SVGAFifoCmdFrontRopFill {
+ uint32 color; /* In the same format as the GFB */
uint32 x;
uint32 y;
uint32 width;
uint32 height;
- uint32 rop; // Must be SVGA_ROP_COPY
+ uint32 rop; /* Must be SVGA_ROP_COPY */
} SVGAFifoCmdFrontRopFill;
@@ -1083,7 +1221,7 @@ struct {
*/
typedef
-struct {
+struct SVGAFifoCmdEscape {
uint32 nsid;
uint32 size;
/* followed by 'size' bytes of data */
@@ -1113,12 +1251,12 @@ struct {
* registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*).
*
* Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT
+ * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
*/
typedef
struct {
- SVGAScreenObject screen; // Variable-length according to version
+ SVGAScreenObject screen; /* Variable-length according to version */
} SVGAFifoCmdDefineScreen;
@@ -1129,7 +1267,7 @@ struct {
* re-use.
*
* Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT
+ * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
*/
typedef
@@ -1182,7 +1320,7 @@ struct {
* GMRFB.
*
* Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT
+ * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
*/
typedef
@@ -1219,7 +1357,7 @@ struct {
* SVGA_CMD_ANNOTATION_* commands for details.
*
* Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT
+ * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
*/
typedef
@@ -1267,7 +1405,7 @@ struct {
* the time any subsequent FENCE commands are reached.
*
* Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT
+ * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
*/
typedef
@@ -1302,7 +1440,7 @@ struct {
* user's display is being remoted over a network connection.
*
* Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT
+ * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
*/
typedef
@@ -1334,7 +1472,7 @@ struct {
* undefined.
*
* Availability:
- * SVGA_FIFO_CAP_SCREEN_OBJECT
+ * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
*/
typedef
@@ -1343,4 +1481,72 @@ struct {
uint32 srcScreenId;
} SVGAFifoCmdAnnotationCopy;
+
+/*
+ * SVGA_CMD_DEFINE_GMR2 --
+ *
+ * Define guest memory region v2. See the description of GMRs above.
+ *
+ * Availability:
+ * SVGA_CAP_GMR2
+ */
+
+typedef
+struct {
+ uint32 gmrId;
+ uint32 numPages;
+} SVGAFifoCmdDefineGMR2;
+
+
+/*
+ * SVGA_CMD_REMAP_GMR2 --
+ *
+ * Remap guest memory region v2. See the description of GMRs above.
+ *
+ * This command allows guest to modify a portion of an existing GMR by
+ * invalidating it or reassigning it to different guest physical pages.
+ * The pages are identified by physical page number (PPN). The pages
+ * are assumed to be pinned and valid for DMA operations.
+ *
+ * Description of command flags:
+ *
+ * SVGA_REMAP_GMR2_VIA_GMR: If enabled, references a PPN list in a GMR.
+ * The PPN list must not overlap with the remap region (this can be
+ * handled trivially by referencing a separate GMR). If flag is
+ * disabled, PPN list is appended to SVGARemapGMR command.
+ *
+ * SVGA_REMAP_GMR2_PPN64: If set, PPN list is in PPN64 format, otherwise
+ * it is in PPN32 format.
+ *
+ * SVGA_REMAP_GMR2_SINGLE_PPN: If set, PPN list contains a single entry.
+ * A single PPN can be used to invalidate a portion of a GMR or
+ * map it to to a single guest scratch page.
+ *
+ * Availability:
+ * SVGA_CAP_GMR2
+ */
+
+typedef enum {
+ SVGA_REMAP_GMR2_PPN32 = 0,
+ SVGA_REMAP_GMR2_VIA_GMR = (1 << 0),
+ SVGA_REMAP_GMR2_PPN64 = (1 << 1),
+ SVGA_REMAP_GMR2_SINGLE_PPN = (1 << 2),
+} SVGARemapGMR2Flags;
+
+typedef
+struct {
+ uint32 gmrId;
+ SVGARemapGMR2Flags flags;
+ uint32 offsetPages; /* offset in pages to begin remap */
+ uint32 numPages; /* number of pages to remap */
+ /*
+ * Followed by additional data depending on SVGARemapGMR2Flags.
+ *
+ * If flag SVGA_REMAP_GMR2_VIA_GMR is set, single SVGAGuestPtr follows.
+ * Otherwise an array of page descriptors in PPN32 or PPN64 format
+ * (according to flag SVGA_REMAP_GMR2_PPN64) follows. If flag
+ * SVGA_REMAP_GMR2_SINGLE_PPN is set, array contains a single entry.
+ */
+} SVGAFifoCmdRemapGMR2;
+
#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
index 87e43e0733bf..5a72ed908232 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
@@ -42,6 +42,10 @@ static uint32_t sys_placement_flags = TTM_PL_FLAG_SYSTEM |
static uint32_t gmr_placement_flags = VMW_PL_FLAG_GMR |
TTM_PL_FLAG_CACHED;
+static uint32_t gmr_ne_placement_flags = VMW_PL_FLAG_GMR |
+ TTM_PL_FLAG_CACHED |
+ TTM_PL_FLAG_NO_EVICT;
+
struct ttm_placement vmw_vram_placement = {
.fpfn = 0,
.lpfn = 0,
@@ -56,6 +60,11 @@ static uint32_t vram_gmr_placement_flags[] = {
VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
};
+static uint32_t gmr_vram_placement_flags[] = {
+ VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED,
+ TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED
+};
+
struct ttm_placement vmw_vram_gmr_placement = {
.fpfn = 0,
.lpfn = 0,
@@ -65,6 +74,20 @@ struct ttm_placement vmw_vram_gmr_placement = {
.busy_placement = &gmr_placement_flags
};
+static uint32_t vram_gmr_ne_placement_flags[] = {
+ TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT,
+ VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT
+};
+
+struct ttm_placement vmw_vram_gmr_ne_placement = {
+ .fpfn = 0,
+ .lpfn = 0,
+ .num_placement = 2,
+ .placement = vram_gmr_ne_placement_flags,
+ .num_busy_placement = 1,
+ .busy_placement = &gmr_ne_placement_flags
+};
+
struct ttm_placement vmw_vram_sys_placement = {
.fpfn = 0,
.lpfn = 0,
@@ -92,6 +115,30 @@ struct ttm_placement vmw_sys_placement = {
.busy_placement = &sys_placement_flags
};
+static uint32_t evictable_placement_flags[] = {
+ TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED,
+ TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED,
+ VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
+};
+
+struct ttm_placement vmw_evictable_placement = {
+ .fpfn = 0,
+ .lpfn = 0,
+ .num_placement = 3,
+ .placement = evictable_placement_flags,
+ .num_busy_placement = 1,
+ .busy_placement = &sys_placement_flags
+};
+
+struct ttm_placement vmw_srf_placement = {
+ .fpfn = 0,
+ .lpfn = 0,
+ .num_placement = 1,
+ .num_busy_placement = 2,
+ .placement = &gmr_placement_flags,
+ .busy_placement = gmr_vram_placement_flags
+};
+
struct vmw_ttm_backend {
struct ttm_backend backend;
struct page **pages;
@@ -274,39 +321,39 @@ static int vmw_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
static void *vmw_sync_obj_ref(void *sync_obj)
{
- return sync_obj;
+
+ return (void *)
+ vmw_fence_obj_reference((struct vmw_fence_obj *) sync_obj);
}
static void vmw_sync_obj_unref(void **sync_obj)
{
- *sync_obj = NULL;
+ vmw_fence_obj_unreference((struct vmw_fence_obj **) sync_obj);
}
static int vmw_sync_obj_flush(void *sync_obj, void *sync_arg)
{
- struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
-
- mutex_lock(&dev_priv->hw_mutex);
- vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
- mutex_unlock(&dev_priv->hw_mutex);
+ vmw_fence_obj_flush((struct vmw_fence_obj *) sync_obj);
return 0;
}
static bool vmw_sync_obj_signaled(void *sync_obj, void *sync_arg)
{
- struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
- uint32_t sequence = (unsigned long) sync_obj;
+ unsigned long flags = (unsigned long) sync_arg;
+ return vmw_fence_obj_signaled((struct vmw_fence_obj *) sync_obj,
+ (uint32_t) flags);
- return vmw_fence_signaled(dev_priv, sequence);
}
static int vmw_sync_obj_wait(void *sync_obj, void *sync_arg,
bool lazy, bool interruptible)
{
- struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
- uint32_t sequence = (unsigned long) sync_obj;
+ unsigned long flags = (unsigned long) sync_arg;
- return vmw_wait_fence(dev_priv, false, sequence, false, 3*HZ);
+ return vmw_fence_obj_wait((struct vmw_fence_obj *) sync_obj,
+ (uint32_t) flags,
+ lazy, interruptible,
+ VMW_FENCE_WAIT_TIMEOUT);
}
struct ttm_bo_driver vmw_bo_driver = {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
new file mode 100644
index 000000000000..3fa884db08ab
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
@@ -0,0 +1,322 @@
+/**************************************************************************
+ *
+ * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "ttm/ttm_placement.h"
+
+#include "drmP.h"
+#include "vmwgfx_drv.h"
+
+
+/**
+ * vmw_dmabuf_to_placement - Validate a buffer to placement.
+ *
+ * @dev_priv: Driver private.
+ * @buf: DMA buffer to move.
+ * @pin: Pin buffer if true.
+ * @interruptible: Use interruptible wait.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ * Flushes and unpins the query bo to avoid failures.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buf,
+ struct ttm_placement *placement,
+ bool interruptible)
+{
+ struct vmw_master *vmaster = dev_priv->active_master;
+ struct ttm_buffer_object *bo = &buf->base;
+ int ret;
+
+ ret = ttm_write_lock(&vmaster->lock, interruptible);
+ if (unlikely(ret != 0))
+ return ret;
+
+ vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+
+ ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+ if (unlikely(ret != 0))
+ goto err;
+
+ ret = ttm_bo_validate(bo, placement, interruptible, false, false);
+
+ ttm_bo_unreserve(bo);
+
+err:
+ ttm_write_unlock(&vmaster->lock);
+ return ret;
+}
+
+/**
+ * vmw_dmabuf_to_vram_or_gmr - Move a buffer to vram or gmr.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ * Flushes and unpins the query bo if @pin == true to avoid failures.
+ *
+ * @dev_priv: Driver private.
+ * @buf: DMA buffer to move.
+ * @pin: Pin buffer if true.
+ * @interruptible: Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buf,
+ bool pin, bool interruptible)
+{
+ struct vmw_master *vmaster = dev_priv->active_master;
+ struct ttm_buffer_object *bo = &buf->base;
+ struct ttm_placement *placement;
+ int ret;
+
+ ret = ttm_write_lock(&vmaster->lock, interruptible);
+ if (unlikely(ret != 0))
+ return ret;
+
+ if (pin)
+ vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+
+ ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+ if (unlikely(ret != 0))
+ goto err;
+
+ /**
+ * Put BO in VRAM if there is space, otherwise as a GMR.
+ * If there is no space in VRAM and GMR ids are all used up,
+ * start evicting GMRs to make room. If the DMA buffer can't be
+ * used as a GMR, this will return -ENOMEM.
+ */
+
+ if (pin)
+ placement = &vmw_vram_gmr_ne_placement;
+ else
+ placement = &vmw_vram_gmr_placement;
+
+ ret = ttm_bo_validate(bo, placement, interruptible, false, false);
+ if (likely(ret == 0) || ret == -ERESTARTSYS)
+ goto err_unreserve;
+
+
+ /**
+ * If that failed, try VRAM again, this time evicting
+ * previous contents.
+ */
+
+ if (pin)
+ placement = &vmw_vram_ne_placement;
+ else
+ placement = &vmw_vram_placement;
+
+ ret = ttm_bo_validate(bo, placement, interruptible, false, false);
+
+err_unreserve:
+ ttm_bo_unreserve(bo);
+err:
+ ttm_write_unlock(&vmaster->lock);
+ return ret;
+}
+
+/**
+ * vmw_dmabuf_to_vram - Move a buffer to vram.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ *
+ * @dev_priv: Driver private.
+ * @buf: DMA buffer to move.
+ * @pin: Pin buffer in vram if true.
+ * @interruptible: Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_vram(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buf,
+ bool pin, bool interruptible)
+{
+ struct ttm_placement *placement;
+
+ if (pin)
+ placement = &vmw_vram_ne_placement;
+ else
+ placement = &vmw_vram_placement;
+
+ return vmw_dmabuf_to_placement(dev_priv, buf,
+ placement,
+ interruptible);
+}
+
+/**
+ * vmw_dmabuf_to_start_of_vram - Move a buffer to start of vram.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ * Flushes and unpins the query bo if @pin == true to avoid failures.
+ *
+ * @dev_priv: Driver private.
+ * @buf: DMA buffer to move.
+ * @pin: Pin buffer in vram if true.
+ * @interruptible: Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buf,
+ bool pin, bool interruptible)
+{
+ struct vmw_master *vmaster = dev_priv->active_master;
+ struct ttm_buffer_object *bo = &buf->base;
+ struct ttm_placement placement;
+ int ret = 0;
+
+ if (pin)
+ placement = vmw_vram_ne_placement;
+ else
+ placement = vmw_vram_placement;
+ placement.lpfn = bo->num_pages;
+
+ ret = ttm_write_lock(&vmaster->lock, interruptible);
+ if (unlikely(ret != 0))
+ return ret;
+
+ if (pin)
+ vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+
+ ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+ if (unlikely(ret != 0))
+ goto err_unlock;
+
+ /* Is this buffer already in vram but not at the start of it? */
+ if (bo->mem.mem_type == TTM_PL_VRAM &&
+ bo->mem.start < bo->num_pages &&
+ bo->mem.start > 0)
+ (void) ttm_bo_validate(bo, &vmw_sys_placement, false,
+ false, false);
+
+ ret = ttm_bo_validate(bo, &placement, interruptible, false, false);
+
+ /* For some reason we didn't up at the start of vram */
+ WARN_ON(ret == 0 && bo->offset != 0);
+
+ ttm_bo_unreserve(bo);
+err_unlock:
+ ttm_write_unlock(&vmaster->lock);
+
+ return ret;
+}
+
+
+/**
+ * vmw_dmabuf_upin - Unpin the buffer given buffer, does not move the buffer.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ *
+ * @dev_priv: Driver private.
+ * @buf: DMA buffer to unpin.
+ * @interruptible: Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_unpin(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buf,
+ bool interruptible)
+{
+ /*
+ * We could in theory early out if the buffer is
+ * unpinned but we need to lock and reserve the buffer
+ * anyways so we don't gain much by that.
+ */
+ return vmw_dmabuf_to_placement(dev_priv, buf,
+ &vmw_evictable_placement,
+ interruptible);
+}
+
+
+/**
+ * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement
+ * of a buffer.
+ *
+ * @bo: Pointer to a struct ttm_buffer_object. Must be pinned or reserved.
+ * @ptr: SVGAGuestPtr returning the result.
+ */
+void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo,
+ SVGAGuestPtr *ptr)
+{
+ if (bo->mem.mem_type == TTM_PL_VRAM) {
+ ptr->gmrId = SVGA_GMR_FRAMEBUFFER;
+ ptr->offset = bo->offset;
+ } else {
+ ptr->gmrId = bo->mem.start;
+ ptr->offset = 0;
+ }
+}
+
+
+/**
+ * vmw_bo_pin - Pin or unpin a buffer object without moving it.
+ *
+ * @bo: The buffer object. Must be reserved, and present either in VRAM
+ * or GMR memory.
+ * @pin: Whether to pin or unpin.
+ *
+ */
+void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
+{
+ uint32_t pl_flags;
+ struct ttm_placement placement;
+ uint32_t old_mem_type = bo->mem.mem_type;
+ int ret;
+
+ BUG_ON(!atomic_read(&bo->reserved));
+ BUG_ON(old_mem_type != TTM_PL_VRAM &&
+ old_mem_type != VMW_PL_FLAG_GMR);
+
+ pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
+ if (pin)
+ pl_flags |= TTM_PL_FLAG_NO_EVICT;
+
+ memset(&placement, 0, sizeof(placement));
+ placement.num_placement = 1;
+ placement.placement = &pl_flags;
+
+ ret = ttm_bo_validate(bo, &placement, false, true, true);
+
+ BUG_ON(ret != 0 || bo->mem.mem_type != old_mem_type);
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 96949b93d920..13afddc1f034 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -82,16 +82,27 @@
#define DRM_IOCTL_VMW_EXECBUF \
DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_EXECBUF, \
struct drm_vmw_execbuf_arg)
-#define DRM_IOCTL_VMW_FIFO_DEBUG \
- DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FIFO_DEBUG, \
- struct drm_vmw_fifo_debug_arg)
+#define DRM_IOCTL_VMW_GET_3D_CAP \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_GET_3D_CAP, \
+ struct drm_vmw_get_3d_cap_arg)
#define DRM_IOCTL_VMW_FENCE_WAIT \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT, \
struct drm_vmw_fence_wait_arg)
-#define DRM_IOCTL_VMW_UPDATE_LAYOUT \
- DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT, \
- struct drm_vmw_update_layout_arg)
-
+#define DRM_IOCTL_VMW_FENCE_SIGNALED \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_SIGNALED, \
+ struct drm_vmw_fence_signaled_arg)
+#define DRM_IOCTL_VMW_FENCE_UNREF \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_FENCE_UNREF, \
+ struct drm_vmw_fence_arg)
+#define DRM_IOCTL_VMW_FENCE_EVENT \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_FENCE_EVENT, \
+ struct drm_vmw_fence_event_arg)
+#define DRM_IOCTL_VMW_PRESENT \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT, \
+ struct drm_vmw_present_arg)
+#define DRM_IOCTL_VMW_PRESENT_READBACK \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK, \
+ struct drm_vmw_present_readback_arg)
/**
* The core DRM version of this macro doesn't account for
@@ -135,12 +146,25 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
DRM_AUTH | DRM_UNLOCKED),
VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
DRM_AUTH | DRM_UNLOCKED),
- VMW_IOCTL_DEF(VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
- DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
- VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
+ VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
+ DRM_AUTH | DRM_UNLOCKED),
+ VMW_IOCTL_DEF(VMW_FENCE_SIGNALED,
+ vmw_fence_obj_signaled_ioctl,
+ DRM_AUTH | DRM_UNLOCKED),
+ VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
+ DRM_AUTH | DRM_UNLOCKED),
+ VMW_IOCTL_DEF(VMW_FENCE_EVENT,
+ vmw_fence_event_ioctl,
+ DRM_AUTH | DRM_UNLOCKED),
+ VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
DRM_AUTH | DRM_UNLOCKED),
- VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
- DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
+
+ /* these allow direct access to the framebuffers mark as master only */
+ VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl,
+ DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
+ VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
+ vmw_present_readback_ioctl,
+ DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
};
static struct pci_device_id vmw_pci_id_list[] = {
@@ -189,8 +213,78 @@ static void vmw_print_capabilities(uint32_t capabilities)
DRM_INFO(" GMR.\n");
if (capabilities & SVGA_CAP_TRACES)
DRM_INFO(" Traces.\n");
+ if (capabilities & SVGA_CAP_GMR2)
+ DRM_INFO(" GMR2.\n");
+ if (capabilities & SVGA_CAP_SCREEN_OBJECT_2)
+ DRM_INFO(" Screen Object 2.\n");
+}
+
+
+/**
+ * vmw_execbuf_prepare_dummy_query - Initialize a query result structure at
+ * the start of a buffer object.
+ *
+ * @dev_priv: The device private structure.
+ *
+ * This function will idle the buffer using an uninterruptible wait, then
+ * map the first page and initialize a pending occlusion query result structure,
+ * Finally it will unmap the buffer.
+ *
+ * TODO: Since we're only mapping a single page, we should optimize the map
+ * to use kmap_atomic / iomap_atomic.
+ */
+static void vmw_dummy_query_bo_prepare(struct vmw_private *dev_priv)
+{
+ struct ttm_bo_kmap_obj map;
+ volatile SVGA3dQueryResult *result;
+ bool dummy;
+ int ret;
+ struct ttm_bo_device *bdev = &dev_priv->bdev;
+ struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
+
+ ttm_bo_reserve(bo, false, false, false, 0);
+ spin_lock(&bdev->fence_lock);
+ ret = ttm_bo_wait(bo, false, false, false);
+ spin_unlock(&bdev->fence_lock);
+ if (unlikely(ret != 0))
+ (void) vmw_fallback_wait(dev_priv, false, true, 0, false,
+ 10*HZ);
+
+ ret = ttm_bo_kmap(bo, 0, 1, &map);
+ if (likely(ret == 0)) {
+ result = ttm_kmap_obj_virtual(&map, &dummy);
+ result->totalSize = sizeof(*result);
+ result->state = SVGA3D_QUERYSTATE_PENDING;
+ result->result32 = 0xff;
+ ttm_bo_kunmap(&map);
+ } else
+ DRM_ERROR("Dummy query buffer map failed.\n");
+ ttm_bo_unreserve(bo);
+}
+
+
+/**
+ * vmw_dummy_query_bo_create - create a bo to hold a dummy query result
+ *
+ * @dev_priv: A device private structure.
+ *
+ * This function creates a small buffer object that holds the query
+ * result for dummy queries emitted as query barriers.
+ * No interruptible waits are done within this function.
+ *
+ * Returns an error if bo creation fails.
+ */
+static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
+{
+ return ttm_bo_create(&dev_priv->bdev,
+ PAGE_SIZE,
+ ttm_bo_type_device,
+ &vmw_vram_sys_placement,
+ 0, 0, false, NULL,
+ &dev_priv->dummy_query_bo);
}
+
static int vmw_request_device(struct vmw_private *dev_priv)
{
int ret;
@@ -200,16 +294,42 @@ static int vmw_request_device(struct vmw_private *dev_priv)
DRM_ERROR("Unable to initialize FIFO.\n");
return ret;
}
+ vmw_fence_fifo_up(dev_priv->fman);
+ ret = vmw_dummy_query_bo_create(dev_priv);
+ if (unlikely(ret != 0))
+ goto out_no_query_bo;
+ vmw_dummy_query_bo_prepare(dev_priv);
return 0;
+
+out_no_query_bo:
+ vmw_fence_fifo_down(dev_priv->fman);
+ vmw_fifo_release(dev_priv, &dev_priv->fifo);
+ return ret;
}
static void vmw_release_device(struct vmw_private *dev_priv)
{
+ /*
+ * Previous destructions should've released
+ * the pinned bo.
+ */
+
+ BUG_ON(dev_priv->pinned_bo != NULL);
+
+ ttm_bo_unref(&dev_priv->dummy_query_bo);
+ vmw_fence_fifo_down(dev_priv->fman);
vmw_fifo_release(dev_priv, &dev_priv->fifo);
}
-int vmw_3d_resource_inc(struct vmw_private *dev_priv)
+/**
+ * Increase the 3d resource refcount.
+ * If the count was prevously zero, initialize the fifo, switching to svga
+ * mode. Note that the master holds a ref as well, and may request an
+ * explicit switch to svga mode if fb is not running, using @unhide_svga.
+ */
+int vmw_3d_resource_inc(struct vmw_private *dev_priv,
+ bool unhide_svga)
{
int ret = 0;
@@ -218,19 +338,42 @@ int vmw_3d_resource_inc(struct vmw_private *dev_priv)
ret = vmw_request_device(dev_priv);
if (unlikely(ret != 0))
--dev_priv->num_3d_resources;
+ } else if (unhide_svga) {
+ mutex_lock(&dev_priv->hw_mutex);
+ vmw_write(dev_priv, SVGA_REG_ENABLE,
+ vmw_read(dev_priv, SVGA_REG_ENABLE) &
+ ~SVGA_REG_ENABLE_HIDE);
+ mutex_unlock(&dev_priv->hw_mutex);
}
+
mutex_unlock(&dev_priv->release_mutex);
return ret;
}
-
-void vmw_3d_resource_dec(struct vmw_private *dev_priv)
+/**
+ * Decrease the 3d resource refcount.
+ * If the count reaches zero, disable the fifo, switching to vga mode.
+ * Note that the master holds a refcount as well, and may request an
+ * explicit switch to vga mode when it releases its refcount to account
+ * for the situation of an X server vt switch to VGA with 3d resources
+ * active.
+ */
+void vmw_3d_resource_dec(struct vmw_private *dev_priv,
+ bool hide_svga)
{
int32_t n3d;
mutex_lock(&dev_priv->release_mutex);
if (unlikely(--dev_priv->num_3d_resources == 0))
vmw_release_device(dev_priv);
+ else if (hide_svga) {
+ mutex_lock(&dev_priv->hw_mutex);
+ vmw_write(dev_priv, SVGA_REG_ENABLE,
+ vmw_read(dev_priv, SVGA_REG_ENABLE) |
+ SVGA_REG_ENABLE_HIDE);
+ mutex_unlock(&dev_priv->hw_mutex);
+ }
+
n3d = (int32_t) dev_priv->num_3d_resources;
mutex_unlock(&dev_priv->release_mutex);
@@ -252,7 +395,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->dev = dev;
dev_priv->vmw_chipset = chipset;
- dev_priv->last_read_sequence = (uint32_t) -100;
+ dev_priv->last_read_seqno = (uint32_t) -100;
mutex_init(&dev_priv->hw_mutex);
mutex_init(&dev_priv->cmdbuf_mutex);
mutex_init(&dev_priv->release_mutex);
@@ -263,8 +406,10 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
mutex_init(&dev_priv->init_mutex);
init_waitqueue_head(&dev_priv->fence_queue);
init_waitqueue_head(&dev_priv->fifo_queue);
- atomic_set(&dev_priv->fence_queue_waiters, 0);
+ dev_priv->fence_queue_waiters = 0;
atomic_set(&dev_priv->fifo_queue_waiters, 0);
+ INIT_LIST_HEAD(&dev_priv->surface_lru);
+ dev_priv->used_memory_size = 0;
dev_priv->io_start = pci_resource_start(dev->pdev, 0);
dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
@@ -285,6 +430,10 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES);
+ dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
+ dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE);
+ dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH);
+ dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT);
if (dev_priv->capabilities & SVGA_CAP_GMR) {
dev_priv->max_gmr_descriptors =
vmw_read(dev_priv,
@@ -292,11 +441,19 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->max_gmr_ids =
vmw_read(dev_priv, SVGA_REG_GMR_MAX_IDS);
}
-
- dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
- dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE);
- dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH);
- dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT);
+ if (dev_priv->capabilities & SVGA_CAP_GMR2) {
+ dev_priv->max_gmr_pages =
+ vmw_read(dev_priv, SVGA_REG_GMRS_MAX_PAGES);
+ dev_priv->memory_size =
+ vmw_read(dev_priv, SVGA_REG_MEMORY_SIZE);
+ dev_priv->memory_size -= dev_priv->vram_size;
+ } else {
+ /*
+ * An arbitrary limit of 512MiB on surface
+ * memory. But all HWV8 hardware supports GMR2.
+ */
+ dev_priv->memory_size = 512*1024*1024;
+ }
mutex_unlock(&dev_priv->hw_mutex);
@@ -308,6 +465,12 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
DRM_INFO("Max GMR descriptors is %u\n",
(unsigned)dev_priv->max_gmr_descriptors);
}
+ if (dev_priv->capabilities & SVGA_CAP_GMR2) {
+ DRM_INFO("Max number of GMR pages is %u\n",
+ (unsigned)dev_priv->max_gmr_pages);
+ DRM_INFO("Max dedicated hypervisor surface memory is %u kiB\n",
+ (unsigned)dev_priv->memory_size / 1024);
+ }
DRM_INFO("VRAM at 0x%08x size is %u kiB\n",
dev_priv->vram_start, dev_priv->vram_size / 1024);
DRM_INFO("MMIO at 0x%08x size is %u kiB\n",
@@ -394,22 +557,34 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
goto out_no_device;
}
}
+
+ dev_priv->fman = vmw_fence_manager_init(dev_priv);
+ if (unlikely(dev_priv->fman == NULL))
+ goto out_no_fman;
+
+ /* Need to start the fifo to check if we can do screen objects */
+ ret = vmw_3d_resource_inc(dev_priv, true);
+ if (unlikely(ret != 0))
+ goto out_no_fifo;
+ vmw_kms_save_vga(dev_priv);
+
+ /* Start kms and overlay systems, needs fifo. */
ret = vmw_kms_init(dev_priv);
if (unlikely(ret != 0))
goto out_no_kms;
vmw_overlay_init(dev_priv);
+
+ /* 3D Depends on Screen Objects being used. */
+ DRM_INFO("Detected %sdevice 3D availability.\n",
+ vmw_fifo_have_3d(dev_priv) ?
+ "" : "no ");
+
+ /* We might be done with the fifo now */
if (dev_priv->enable_fb) {
- ret = vmw_3d_resource_inc(dev_priv);
- if (unlikely(ret != 0))
- goto out_no_fifo;
- vmw_kms_save_vga(dev_priv);
vmw_fb_init(dev_priv);
- DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
- "Detected device 3D availability.\n" :
- "Detected no device 3D availability.\n");
} else {
- DRM_INFO("Delayed 3D detection since we're not "
- "running the device in SVGA mode yet.\n");
+ vmw_kms_restore_vga(dev_priv);
+ vmw_3d_resource_dec(dev_priv, true);
}
if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
@@ -426,15 +601,19 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
return 0;
out_no_irq:
- if (dev_priv->enable_fb) {
+ if (dev_priv->enable_fb)
vmw_fb_close(dev_priv);
- vmw_kms_restore_vga(dev_priv);
- vmw_3d_resource_dec(dev_priv);
- }
-out_no_fifo:
vmw_overlay_close(dev_priv);
vmw_kms_close(dev_priv);
out_no_kms:
+ /* We still have a 3D resource reference held */
+ if (dev_priv->enable_fb) {
+ vmw_kms_restore_vga(dev_priv);
+ vmw_3d_resource_dec(dev_priv, false);
+ }
+out_no_fifo:
+ vmw_fence_manager_takedown(dev_priv->fman);
+out_no_fman:
if (dev_priv->stealth)
pci_release_region(dev->pdev, 2);
else
@@ -467,15 +646,18 @@ static int vmw_driver_unload(struct drm_device *dev)
unregister_pm_notifier(&dev_priv->pm_nb);
+ if (dev_priv->ctx.cmd_bounce)
+ vfree(dev_priv->ctx.cmd_bounce);
if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
drm_irq_uninstall(dev_priv->dev);
if (dev_priv->enable_fb) {
vmw_fb_close(dev_priv);
vmw_kms_restore_vga(dev_priv);
- vmw_3d_resource_dec(dev_priv);
+ vmw_3d_resource_dec(dev_priv, false);
}
vmw_kms_close(dev_priv);
vmw_overlay_close(dev_priv);
+ vmw_fence_manager_takedown(dev_priv->fman);
if (dev_priv->stealth)
pci_release_region(dev->pdev, 2);
else
@@ -646,7 +828,7 @@ static int vmw_master_set(struct drm_device *dev,
int ret = 0;
if (!dev_priv->enable_fb) {
- ret = vmw_3d_resource_inc(dev_priv);
+ ret = vmw_3d_resource_inc(dev_priv, true);
if (unlikely(ret != 0))
return ret;
vmw_kms_save_vga(dev_priv);
@@ -688,7 +870,7 @@ out_no_active_lock:
vmw_write(dev_priv, SVGA_REG_TRACES, 1);
mutex_unlock(&dev_priv->hw_mutex);
vmw_kms_restore_vga(dev_priv);
- vmw_3d_resource_dec(dev_priv);
+ vmw_3d_resource_dec(dev_priv, true);
}
return ret;
}
@@ -709,7 +891,7 @@ static void vmw_master_drop(struct drm_device *dev,
vmw_fp->locked_master = drm_master_get(file_priv->master);
ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
- vmw_kms_idle_workqueues(vmaster);
+ vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
if (unlikely((ret != 0))) {
DRM_ERROR("Unable to lock TTM at VT switch.\n");
@@ -726,7 +908,7 @@ static void vmw_master_drop(struct drm_device *dev,
vmw_write(dev_priv, SVGA_REG_TRACES, 1);
mutex_unlock(&dev_priv->hw_mutex);
vmw_kms_restore_vga(dev_priv);
- vmw_3d_resource_dec(dev_priv);
+ vmw_3d_resource_dec(dev_priv, true);
}
dev_priv->active_master = &dev_priv->fbdev_master;
@@ -761,6 +943,7 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
* This empties VRAM and unbinds all GMR bindings.
* Buffer contents is moved to swappable memory.
*/
+ vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
ttm_bo_swapout_all(&dev_priv->bdev);
break;
@@ -835,7 +1018,7 @@ static int vmw_pm_prepare(struct device *kdev)
*/
dev_priv->suspended = true;
if (dev_priv->enable_fb)
- vmw_3d_resource_dec(dev_priv);
+ vmw_3d_resource_dec(dev_priv, true);
if (dev_priv->num_3d_resources != 0) {
@@ -843,7 +1026,7 @@ static int vmw_pm_prepare(struct device *kdev)
"while 3D resources are active.\n");
if (dev_priv->enable_fb)
- vmw_3d_resource_inc(dev_priv);
+ vmw_3d_resource_inc(dev_priv, true);
dev_priv->suspended = false;
return -EBUSY;
}
@@ -862,7 +1045,7 @@ static void vmw_pm_complete(struct device *kdev)
* start fifo.
*/
if (dev_priv->enable_fb)
- vmw_3d_resource_inc(dev_priv);
+ vmw_3d_resource_inc(dev_priv, false);
dev_priv->suspended = false;
}
@@ -886,6 +1069,8 @@ static struct drm_driver driver = {
.irq_uninstall = vmw_irq_uninstall,
.irq_handler = vmw_irq_handler,
.get_vblank_counter = vmw_get_vblank_counter,
+ .enable_vblank = vmw_enable_vblank,
+ .disable_vblank = vmw_disable_vblank,
.reclaim_buffers_locked = NULL,
.ioctls = vmw_ioctls,
.num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls),
@@ -902,7 +1087,8 @@ static struct drm_driver driver = {
.release = drm_release,
.unlocked_ioctl = vmw_unlocked_ioctl,
.mmap = vmw_mmap,
- .poll = drm_poll,
+ .poll = vmw_fops_poll,
+ .read = vmw_fops_read,
.fasync = drm_fasync,
#if defined(CONFIG_COMPAT)
.compat_ioctl = drm_compat_ioctl,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 10fc01f69c40..30589d0aecd9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -38,20 +38,27 @@
#include "ttm/ttm_lock.h"
#include "ttm/ttm_execbuf_util.h"
#include "ttm/ttm_module.h"
+#include "vmwgfx_fence.h"
-#define VMWGFX_DRIVER_DATE "20100927"
-#define VMWGFX_DRIVER_MAJOR 1
-#define VMWGFX_DRIVER_MINOR 4
+#define VMWGFX_DRIVER_DATE "20111008"
+#define VMWGFX_DRIVER_MAJOR 2
+#define VMWGFX_DRIVER_MINOR 2
#define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
#define VMWGFX_MAX_RELOCATIONS 2048
-#define VMWGFX_MAX_GMRS 2048
+#define VMWGFX_MAX_VALIDATIONS 2048
#define VMWGFX_MAX_DISPLAYS 16
+#define VMWGFX_CMD_BOUNCE_INIT_SIZE 32768
#define VMW_PL_GMR TTM_PL_PRIV0
#define VMW_PL_FLAG_GMR TTM_PL_FLAG_PRIV0
+#define VMW_RES_CONTEXT ttm_driver_type0
+#define VMW_RES_SURFACE ttm_driver_type1
+#define VMW_RES_STREAM ttm_driver_type2
+#define VMW_RES_FENCE ttm_driver_type3
+
struct vmw_fpriv {
struct drm_master *locked_master;
struct ttm_object_file *tfile;
@@ -72,9 +79,11 @@ struct vmw_resource {
int id;
enum ttm_object_type res_type;
bool avail;
+ void (*remove_from_lists) (struct vmw_resource *res);
void (*hw_destroy) (struct vmw_resource *res);
void (*res_free) (struct vmw_resource *res);
-
+ struct list_head validate_head;
+ struct list_head query_head; /* Protected by the cmdbuf mutex */
/* TODO is a generic snooper needed? */
#if 0
void (*snoop)(struct vmw_resource *res,
@@ -90,8 +99,12 @@ struct vmw_cursor_snooper {
uint32_t *image;
};
+struct vmw_framebuffer;
+struct vmw_surface_offset;
+
struct vmw_surface {
struct vmw_resource res;
+ struct list_head lru_head; /* Protected by the resource lock */
uint32_t flags;
uint32_t format;
uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
@@ -102,9 +115,12 @@ struct vmw_surface {
/* TODO so far just a extra pointer */
struct vmw_cursor_snooper snooper;
+ struct ttm_buffer_object *backup;
+ struct vmw_surface_offset *offsets;
+ uint32_t backup_size;
};
-struct vmw_fence_queue {
+struct vmw_marker_queue {
struct list_head head;
struct timespec lag;
struct timespec lag_time;
@@ -115,16 +131,12 @@ struct vmw_fifo_state {
unsigned long reserved_size;
__le32 *dynamic_buffer;
__le32 *static_buffer;
- __le32 *last_buffer;
- uint32_t last_data_size;
- uint32_t last_buffer_size;
- bool last_buffer_add;
unsigned long static_buffer_size;
bool using_bounce_buffer;
uint32_t capabilities;
struct mutex fifo_mutex;
struct rw_semaphore rwsem;
- struct vmw_fence_queue fence_queue;
+ struct vmw_marker_queue marker_queue;
};
struct vmw_relocation {
@@ -136,6 +148,8 @@ struct vmw_sw_context{
struct ida bo_list;
uint32_t last_cid;
bool cid_valid;
+ bool kernel; /**< is the called made from the kernel */
+ struct vmw_resource *cur_ctx;
uint32_t last_sid;
uint32_t sid_translation;
bool sid_valid;
@@ -143,8 +157,16 @@ struct vmw_sw_context{
struct list_head validate_nodes;
struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS];
uint32_t cur_reloc;
- struct ttm_validate_buffer val_bufs[VMWGFX_MAX_GMRS];
+ struct ttm_validate_buffer val_bufs[VMWGFX_MAX_VALIDATIONS];
uint32_t cur_val_buf;
+ uint32_t *cmd_bounce;
+ uint32_t cmd_bounce_size;
+ struct list_head resource_list;
+ uint32_t fence_flags;
+ struct list_head query_list;
+ struct ttm_buffer_object *cur_query_bo;
+ uint32_t cur_query_cid;
+ bool query_cid_valid;
};
struct vmw_legacy_display;
@@ -185,6 +207,8 @@ struct vmw_private {
uint32_t capabilities;
uint32_t max_gmr_descriptors;
uint32_t max_gmr_ids;
+ uint32_t max_gmr_pages;
+ uint32_t memory_size;
bool has_gmr;
struct mutex hw_mutex;
@@ -195,12 +219,7 @@ struct vmw_private {
struct vmw_vga_topology_state vga_save[VMWGFX_MAX_DISPLAYS];
uint32_t vga_width;
uint32_t vga_height;
- uint32_t vga_depth;
uint32_t vga_bpp;
- uint32_t vga_pseudo;
- uint32_t vga_red_mask;
- uint32_t vga_green_mask;
- uint32_t vga_blue_mask;
uint32_t vga_bpl;
uint32_t vga_pitchlock;
@@ -212,6 +231,7 @@ struct vmw_private {
void *fb_info;
struct vmw_legacy_display *ldu_priv;
+ struct vmw_screen_object_display *sou_priv;
struct vmw_overlay *overlay_priv;
/*
@@ -240,13 +260,16 @@ struct vmw_private {
* Fencing and IRQs.
*/
- atomic_t fence_seq;
+ atomic_t marker_seq;
wait_queue_head_t fence_queue;
wait_queue_head_t fifo_queue;
- atomic_t fence_queue_waiters;
+ int fence_queue_waiters; /* Protected by hw_mutex */
+ int goal_queue_waiters; /* Protected by hw_mutex */
atomic_t fifo_queue_waiters;
- uint32_t last_read_sequence;
+ uint32_t last_read_seqno;
spinlock_t irq_lock;
+ struct vmw_fence_manager *fman;
+ uint32_t irq_mask;
/*
* Device state
@@ -285,6 +308,26 @@ struct vmw_private {
struct mutex release_mutex;
uint32_t num_3d_resources;
+
+ /*
+ * Query processing. These members
+ * are protected by the cmdbuf mutex.
+ */
+
+ struct ttm_buffer_object *dummy_query_bo;
+ struct ttm_buffer_object *pinned_bo;
+ uint32_t query_cid;
+ bool dummy_query_bo_pinned;
+
+ /*
+ * Surface swapping. The "surface_lru" list is protected by the
+ * resource lock in order to be able to destroy a surface and take
+ * it off the lru atomically. "used_memory_size" is currently
+ * protected by the cmdbuf mutex for simplicity.
+ */
+
+ struct list_head surface_lru;
+ uint32_t used_memory_size;
};
static inline struct vmw_private *vmw_priv(struct drm_device *dev)
@@ -319,8 +362,8 @@ static inline uint32_t vmw_read(struct vmw_private *dev_priv,
return val;
}
-int vmw_3d_resource_inc(struct vmw_private *dev_priv);
-void vmw_3d_resource_dec(struct vmw_private *dev_priv);
+int vmw_3d_resource_inc(struct vmw_private *dev_priv, bool unhide_svga);
+void vmw_3d_resource_dec(struct vmw_private *dev_priv, bool hide_svga);
/**
* GMR utilities - vmwgfx_gmr.c
@@ -345,7 +388,8 @@ extern int vmw_context_define_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int vmw_context_check(struct vmw_private *dev_priv,
struct ttm_object_file *tfile,
- int id);
+ int id,
+ struct vmw_resource **p_res);
extern void vmw_surface_res_free(struct vmw_resource *res);
extern int vmw_surface_init(struct vmw_private *dev_priv,
struct vmw_surface *srf,
@@ -363,6 +407,8 @@ extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
extern int vmw_surface_check(struct vmw_private *dev_priv,
struct ttm_object_file *tfile,
uint32_t handle, int *id);
+extern int vmw_surface_validate(struct vmw_private *dev_priv,
+ struct vmw_surface *srf);
extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo);
extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
struct vmw_dma_buffer *vmw_bo,
@@ -378,10 +424,6 @@ extern uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo);
extern int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
uint32_t id, struct vmw_dma_buffer **out);
-extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
- struct vmw_dma_buffer *bo);
-extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
- struct vmw_dma_buffer *bo);
extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
@@ -390,7 +432,30 @@ extern int vmw_user_stream_lookup(struct vmw_private *dev_priv,
struct ttm_object_file *tfile,
uint32_t *inout_id,
struct vmw_resource **out);
+extern void vmw_resource_unreserve(struct list_head *list);
+/**
+ * DMA buffer helper routines - vmwgfx_dmabuf.c
+ */
+extern int vmw_dmabuf_to_placement(struct vmw_private *vmw_priv,
+ struct vmw_dma_buffer *bo,
+ struct ttm_placement *placement,
+ bool interruptible);
+extern int vmw_dmabuf_to_vram(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buf,
+ bool pin, bool interruptible);
+extern int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buf,
+ bool pin, bool interruptible);
+extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
+ struct vmw_dma_buffer *bo,
+ bool pin, bool interruptible);
+extern int vmw_dmabuf_unpin(struct vmw_private *vmw_priv,
+ struct vmw_dma_buffer *bo,
+ bool interruptible);
+extern void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *buf,
+ SVGAGuestPtr *ptr);
+extern void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin);
/**
* Misc Ioctl functionality - vmwgfx_ioctl.c
@@ -398,8 +463,16 @@ extern int vmw_user_stream_lookup(struct vmw_private *dev_priv,
extern int vmw_getparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-extern int vmw_fifo_debug_ioctl(struct drm_device *dev, void *data,
+extern int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+extern int vmw_present_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern unsigned int vmw_fops_poll(struct file *filp,
+ struct poll_table_struct *wait);
+extern ssize_t vmw_fops_read(struct file *filp, char __user *buffer,
+ size_t count, loff_t *offset);
/**
* Fifo utilities - vmwgfx_fifo.c
@@ -412,11 +485,12 @@ extern void vmw_fifo_release(struct vmw_private *dev_priv,
extern void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes);
extern void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes);
extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
- uint32_t *sequence);
+ uint32_t *seqno);
extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
-extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
+extern int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
+ uint32_t cid);
/**
* TTM glue - vmwgfx_ttm_glue.c
@@ -434,7 +508,10 @@ extern struct ttm_placement vmw_vram_placement;
extern struct ttm_placement vmw_vram_ne_placement;
extern struct ttm_placement vmw_vram_sys_placement;
extern struct ttm_placement vmw_vram_gmr_placement;
+extern struct ttm_placement vmw_vram_gmr_ne_placement;
extern struct ttm_placement vmw_sys_placement;
+extern struct ttm_placement vmw_evictable_placement;
+extern struct ttm_placement vmw_srf_placement;
extern struct ttm_bo_driver vmw_bo_driver;
extern int vmw_dma_quiescent(struct drm_device *dev);
@@ -444,45 +521,70 @@ extern int vmw_dma_quiescent(struct drm_device *dev);
extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+extern int vmw_execbuf_process(struct drm_file *file_priv,
+ struct vmw_private *dev_priv,
+ void __user *user_commands,
+ void *kernel_commands,
+ uint32_t command_size,
+ uint64_t throttle_us,
+ struct drm_vmw_fence_rep __user
+ *user_fence_rep);
+
+extern void
+vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
+ bool only_on_cid_match, uint32_t cid);
+
+extern int vmw_execbuf_fence_commands(struct drm_file *file_priv,
+ struct vmw_private *dev_priv,
+ struct vmw_fence_obj **p_fence,
+ uint32_t *p_handle);
+extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
+ struct vmw_fpriv *vmw_fp,
+ int ret,
+ struct drm_vmw_fence_rep __user
+ *user_fence_rep,
+ struct vmw_fence_obj *fence,
+ uint32_t fence_handle);
/**
* IRQs and wating - vmwgfx_irq.c
*/
extern irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS);
-extern int vmw_wait_fence(struct vmw_private *dev_priv, bool lazy,
- uint32_t sequence, bool interruptible,
- unsigned long timeout);
+extern int vmw_wait_seqno(struct vmw_private *dev_priv, bool lazy,
+ uint32_t seqno, bool interruptible,
+ unsigned long timeout);
extern void vmw_irq_preinstall(struct drm_device *dev);
extern int vmw_irq_postinstall(struct drm_device *dev);
extern void vmw_irq_uninstall(struct drm_device *dev);
-extern bool vmw_fence_signaled(struct vmw_private *dev_priv,
- uint32_t sequence);
-extern int vmw_fence_wait_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+extern bool vmw_seqno_passed(struct vmw_private *dev_priv,
+ uint32_t seqno);
extern int vmw_fallback_wait(struct vmw_private *dev_priv,
bool lazy,
bool fifo_idle,
- uint32_t sequence,
+ uint32_t seqno,
bool interruptible,
unsigned long timeout);
-extern void vmw_update_sequence(struct vmw_private *dev_priv,
+extern void vmw_update_seqno(struct vmw_private *dev_priv,
struct vmw_fifo_state *fifo_state);
-
+extern void vmw_seqno_waiter_add(struct vmw_private *dev_priv);
+extern void vmw_seqno_waiter_remove(struct vmw_private *dev_priv);
+extern void vmw_goal_waiter_add(struct vmw_private *dev_priv);
+extern void vmw_goal_waiter_remove(struct vmw_private *dev_priv);
/**
- * Rudimentary fence objects currently used only for throttling -
- * vmwgfx_fence.c
+ * Rudimentary fence-like objects currently used only for throttling -
+ * vmwgfx_marker.c
*/
-extern void vmw_fence_queue_init(struct vmw_fence_queue *queue);
-extern void vmw_fence_queue_takedown(struct vmw_fence_queue *queue);
-extern int vmw_fence_push(struct vmw_fence_queue *queue,
- uint32_t sequence);
-extern int vmw_fence_pull(struct vmw_fence_queue *queue,
- uint32_t signaled_sequence);
+extern void vmw_marker_queue_init(struct vmw_marker_queue *queue);
+extern void vmw_marker_queue_takedown(struct vmw_marker_queue *queue);
+extern int vmw_marker_push(struct vmw_marker_queue *queue,
+ uint32_t seqno);
+extern int vmw_marker_pull(struct vmw_marker_queue *queue,
+ uint32_t signaled_seqno);
extern int vmw_wait_lag(struct vmw_private *dev_priv,
- struct vmw_fence_queue *queue, uint32_t us);
+ struct vmw_marker_queue *queue, uint32_t us);
/**
* Kernel framebuffer - vmwgfx_fb.c
@@ -508,16 +610,29 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
struct ttm_object_file *tfile,
struct ttm_buffer_object *bo,
SVGA3dCmdHeader *header);
-void vmw_kms_write_svga(struct vmw_private *vmw_priv,
- unsigned width, unsigned height, unsigned pitch,
- unsigned bbp, unsigned depth);
-int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+int vmw_kms_write_svga(struct vmw_private *vmw_priv,
+ unsigned width, unsigned height, unsigned pitch,
+ unsigned bpp, unsigned depth);
void vmw_kms_idle_workqueues(struct vmw_master *vmaster);
bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
uint32_t pitch,
uint32_t height);
u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc);
+int vmw_enable_vblank(struct drm_device *dev, int crtc);
+void vmw_disable_vblank(struct drm_device *dev, int crtc);
+int vmw_kms_present(struct vmw_private *dev_priv,
+ struct drm_file *file_priv,
+ struct vmw_framebuffer *vfb,
+ struct vmw_surface *surface,
+ uint32_t sid, int32_t destX, int32_t destY,
+ struct drm_vmw_rect *clips,
+ uint32_t num_clips);
+int vmw_kms_readback(struct vmw_private *dev_priv,
+ struct drm_file *file_priv,
+ struct vmw_framebuffer *vfb,
+ struct drm_vmw_fence_rep __user *user_fence_rep,
+ struct drm_vmw_rect *clips,
+ uint32_t num_clips);
/**
* Overlay control - vmwgfx_overlay.c
@@ -576,4 +691,8 @@ static inline struct vmw_dma_buffer *vmw_dmabuf_reference(struct vmw_dma_buffer
return NULL;
}
+static inline struct ttm_mem_global *vmw_mem_glob(struct vmw_private *dev_priv)
+{
+ return (struct ttm_mem_global *) dev_priv->mem_global_ref.object;
+}
#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 41b95ed6dbcd..40932fbdac0f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -44,10 +44,71 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv,
return 0;
}
+static void vmw_resource_to_validate_list(struct vmw_sw_context *sw_context,
+ struct vmw_resource **p_res)
+{
+ struct vmw_resource *res = *p_res;
+
+ if (list_empty(&res->validate_head)) {
+ list_add_tail(&res->validate_head, &sw_context->resource_list);
+ *p_res = NULL;
+ } else
+ vmw_resource_unreference(p_res);
+}
+
+/**
+ * vmw_bo_to_validate_list - add a bo to a validate list
+ *
+ * @sw_context: The software context used for this command submission batch.
+ * @bo: The buffer object to add.
+ * @fence_flags: Fence flags to be or'ed with any other fence flags for
+ * this buffer on this submission batch.
+ * @p_val_node: If non-NULL Will be updated with the validate node number
+ * on return.
+ *
+ * Returns -EINVAL if the limit of number of buffer objects per command
+ * submission is reached.
+ */
+static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
+ struct ttm_buffer_object *bo,
+ uint32_t fence_flags,
+ uint32_t *p_val_node)
+{
+ uint32_t val_node;
+ struct ttm_validate_buffer *val_buf;
+
+ val_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
+
+ if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) {
+ DRM_ERROR("Max number of DMA buffers per submission"
+ " exceeded.\n");
+ return -EINVAL;
+ }
+
+ val_buf = &sw_context->val_bufs[val_node];
+ if (unlikely(val_node == sw_context->cur_val_buf)) {
+ val_buf->new_sync_obj_arg = NULL;
+ val_buf->bo = ttm_bo_reference(bo);
+ list_add_tail(&val_buf->head, &sw_context->validate_nodes);
+ ++sw_context->cur_val_buf;
+ }
+
+ val_buf->new_sync_obj_arg = (void *)
+ ((unsigned long) val_buf->new_sync_obj_arg | fence_flags);
+ sw_context->fence_flags |= fence_flags;
+
+ if (p_val_node)
+ *p_val_node = val_node;
+
+ return 0;
+}
+
static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
+ struct vmw_resource *ctx;
+
struct vmw_cid_cmd {
SVGA3dCmdHeader header;
__le32 cid;
@@ -58,7 +119,8 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
if (likely(sw_context->cid_valid && cmd->cid == sw_context->last_cid))
return 0;
- ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid);
+ ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid,
+ &ctx);
if (unlikely(ret != 0)) {
DRM_ERROR("Could not find or use context %u\n",
(unsigned) cmd->cid);
@@ -67,6 +129,8 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
sw_context->last_cid = cmd->cid;
sw_context->cid_valid = true;
+ sw_context->cur_ctx = ctx;
+ vmw_resource_to_validate_list(sw_context, &ctx);
return 0;
}
@@ -75,29 +139,45 @@ static int vmw_cmd_sid_check(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
uint32_t *sid)
{
+ struct vmw_surface *srf;
+ int ret;
+ struct vmw_resource *res;
+
if (*sid == SVGA3D_INVALID_ID)
return 0;
- if (unlikely((!sw_context->sid_valid ||
- *sid != sw_context->last_sid))) {
- int real_id;
- int ret = vmw_surface_check(dev_priv, sw_context->tfile,
- *sid, &real_id);
+ if (likely((sw_context->sid_valid &&
+ *sid == sw_context->last_sid))) {
+ *sid = sw_context->sid_translation;
+ return 0;
+ }
- if (unlikely(ret != 0)) {
- DRM_ERROR("Could ot find or use surface 0x%08x "
- "address 0x%08lx\n",
- (unsigned int) *sid,
- (unsigned long) sid);
- return ret;
- }
+ ret = vmw_user_surface_lookup_handle(dev_priv,
+ sw_context->tfile,
+ *sid, &srf);
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("Could ot find or use surface 0x%08x "
+ "address 0x%08lx\n",
+ (unsigned int) *sid,
+ (unsigned long) sid);
+ return ret;
+ }
- sw_context->last_sid = *sid;
- sw_context->sid_valid = true;
- *sid = real_id;
- sw_context->sid_translation = real_id;
- } else
- *sid = sw_context->sid_translation;
+ ret = vmw_surface_validate(dev_priv, srf);
+ if (unlikely(ret != 0)) {
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("Could not validate surface.\n");
+ vmw_surface_unreference(&srf);
+ return ret;
+ }
+
+ sw_context->last_sid = *sid;
+ sw_context->sid_valid = true;
+ sw_context->sid_translation = srf->res.id;
+ *sid = sw_context->sid_translation;
+
+ res = &srf->res;
+ vmw_resource_to_validate_list(sw_context, &res);
return 0;
}
@@ -166,6 +246,12 @@ static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
} *cmd;
cmd = container_of(header, struct vmw_sid_cmd, header);
+
+ if (unlikely(!sw_context->kernel)) {
+ DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
+ return -EPERM;
+ }
+
return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid);
}
@@ -178,10 +264,179 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv,
SVGA3dCmdPresent body;
} *cmd;
+
cmd = container_of(header, struct vmw_sid_cmd, header);
+
+ if (unlikely(!sw_context->kernel)) {
+ DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
+ return -EPERM;
+ }
+
return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid);
}
+/**
+ * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries.
+ *
+ * @dev_priv: The device private structure.
+ * @cid: The hardware context for the next query.
+ * @new_query_bo: The new buffer holding query results.
+ * @sw_context: The software context used for this command submission.
+ *
+ * This function checks whether @new_query_bo is suitable for holding
+ * query results, and if another buffer currently is pinned for query
+ * results. If so, the function prepares the state of @sw_context for
+ * switching pinned buffers after successful submission of the current
+ * command batch. It also checks whether we're using a new query context.
+ * In that case, it makes sure we emit a query barrier for the old
+ * context before the current query buffer is fenced.
+ */
+static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
+ uint32_t cid,
+ struct ttm_buffer_object *new_query_bo,
+ struct vmw_sw_context *sw_context)
+{
+ int ret;
+ bool add_cid = false;
+ uint32_t cid_to_add;
+
+ if (unlikely(new_query_bo != sw_context->cur_query_bo)) {
+
+ if (unlikely(new_query_bo->num_pages > 4)) {
+ DRM_ERROR("Query buffer too large.\n");
+ return -EINVAL;
+ }
+
+ if (unlikely(sw_context->cur_query_bo != NULL)) {
+ BUG_ON(!sw_context->query_cid_valid);
+ add_cid = true;
+ cid_to_add = sw_context->cur_query_cid;
+ ret = vmw_bo_to_validate_list(sw_context,
+ sw_context->cur_query_bo,
+ DRM_VMW_FENCE_FLAG_EXEC,
+ NULL);
+ if (unlikely(ret != 0))
+ return ret;
+ }
+ sw_context->cur_query_bo = new_query_bo;
+
+ ret = vmw_bo_to_validate_list(sw_context,
+ dev_priv->dummy_query_bo,
+ DRM_VMW_FENCE_FLAG_EXEC,
+ NULL);
+ if (unlikely(ret != 0))
+ return ret;
+
+ }
+
+ if (unlikely(cid != sw_context->cur_query_cid &&
+ sw_context->query_cid_valid)) {
+ add_cid = true;
+ cid_to_add = sw_context->cur_query_cid;
+ }
+
+ sw_context->cur_query_cid = cid;
+ sw_context->query_cid_valid = true;
+
+ if (add_cid) {
+ struct vmw_resource *ctx = sw_context->cur_ctx;
+
+ if (list_empty(&ctx->query_head))
+ list_add_tail(&ctx->query_head,
+ &sw_context->query_list);
+ ret = vmw_bo_to_validate_list(sw_context,
+ dev_priv->dummy_query_bo,
+ DRM_VMW_FENCE_FLAG_EXEC,
+ NULL);
+ if (unlikely(ret != 0))
+ return ret;
+ }
+ return 0;
+}
+
+
+/**
+ * vmw_query_bo_switch_commit - Finalize switching pinned query buffer
+ *
+ * @dev_priv: The device private structure.
+ * @sw_context: The software context used for this command submission batch.
+ *
+ * This function will check if we're switching query buffers, and will then,
+ * if no other query waits are issued this command submission batch,
+ * issue a dummy occlusion query wait used as a query barrier. When the fence
+ * object following that query wait has signaled, we are sure that all
+ * preseding queries have finished, and the old query buffer can be unpinned.
+ * However, since both the new query buffer and the old one are fenced with
+ * that fence, we can do an asynchronus unpin now, and be sure that the
+ * old query buffer won't be moved until the fence has signaled.
+ *
+ * As mentioned above, both the new - and old query buffers need to be fenced
+ * using a sequence emitted *after* calling this function.
+ */
+static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
+ struct vmw_sw_context *sw_context)
+{
+
+ struct vmw_resource *ctx, *next_ctx;
+ int ret;
+
+ /*
+ * The validate list should still hold references to all
+ * contexts here.
+ */
+
+ list_for_each_entry_safe(ctx, next_ctx, &sw_context->query_list,
+ query_head) {
+ list_del_init(&ctx->query_head);
+
+ BUG_ON(list_empty(&ctx->validate_head));
+
+ ret = vmw_fifo_emit_dummy_query(dev_priv, ctx->id);
+
+ if (unlikely(ret != 0))
+ DRM_ERROR("Out of fifo space for dummy query.\n");
+ }
+
+ if (dev_priv->pinned_bo != sw_context->cur_query_bo) {
+ if (dev_priv->pinned_bo) {
+ vmw_bo_pin(dev_priv->pinned_bo, false);
+ ttm_bo_unref(&dev_priv->pinned_bo);
+ }
+
+ vmw_bo_pin(sw_context->cur_query_bo, true);
+
+ /*
+ * We pin also the dummy_query_bo buffer so that we
+ * don't need to validate it when emitting
+ * dummy queries in context destroy paths.
+ */
+
+ vmw_bo_pin(dev_priv->dummy_query_bo, true);
+ dev_priv->dummy_query_bo_pinned = true;
+
+ dev_priv->query_cid = sw_context->cur_query_cid;
+ dev_priv->pinned_bo =
+ ttm_bo_reference(sw_context->cur_query_bo);
+ }
+}
+
+/**
+ * vmw_query_switch_backoff - clear query barrier list
+ * @sw_context: The sw context used for this submission batch.
+ *
+ * This function is used as part of an error path, where a previously
+ * set up list of query barriers needs to be cleared.
+ *
+ */
+static void vmw_query_switch_backoff(struct vmw_sw_context *sw_context)
+{
+ struct list_head *list, *next;
+
+ list_for_each_safe(list, next, &sw_context->query_list) {
+ list_del_init(list);
+ }
+}
+
static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGAGuestPtr *ptr,
@@ -191,8 +446,6 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
struct ttm_buffer_object *bo;
uint32_t handle = ptr->gmrId;
struct vmw_relocation *reloc;
- uint32_t cur_validate_node;
- struct ttm_validate_buffer *val_buf;
int ret;
ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
@@ -212,22 +465,11 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
reloc = &sw_context->relocs[sw_context->cur_reloc++];
reloc->location = ptr;
- cur_validate_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
- if (unlikely(cur_validate_node >= VMWGFX_MAX_GMRS)) {
- DRM_ERROR("Max number of DMA buffers per submission"
- " exceeded.\n");
- ret = -EINVAL;
+ ret = vmw_bo_to_validate_list(sw_context, bo, DRM_VMW_FENCE_FLAG_EXEC,
+ &reloc->index);
+ if (unlikely(ret != 0))
goto out_no_reloc;
- }
- reloc->index = cur_validate_node;
- if (unlikely(cur_validate_node == sw_context->cur_val_buf)) {
- val_buf = &sw_context->val_bufs[cur_validate_node];
- val_buf->bo = ttm_bo_reference(bo);
- val_buf->new_sync_obj_arg = (void *) dev_priv;
- list_add_tail(&val_buf->head, &sw_context->validate_nodes);
- ++sw_context->cur_val_buf;
- }
*vmw_bo_p = vmw_bo;
return 0;
@@ -259,8 +501,11 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv,
if (unlikely(ret != 0))
return ret;
+ ret = vmw_query_bo_switch_prepare(dev_priv, cmd->q.cid,
+ &vmw_bo->base, sw_context);
+
vmw_dmabuf_unreference(&vmw_bo);
- return 0;
+ return ret;
}
static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
@@ -273,6 +518,7 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
SVGA3dCmdWaitForQuery q;
} *cmd;
int ret;
+ struct vmw_resource *ctx;
cmd = container_of(header, struct vmw_query_cmd, header);
ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
@@ -286,10 +532,19 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
return ret;
vmw_dmabuf_unreference(&vmw_bo);
+
+ /*
+ * This wait will act as a barrier for previous waits for this
+ * context.
+ */
+
+ ctx = sw_context->cur_ctx;
+ if (!list_empty(&ctx->query_head))
+ list_del_init(&ctx->query_head);
+
return 0;
}
-
static int vmw_cmd_dma(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
@@ -302,6 +557,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
SVGA3dCmdSurfaceDMA dma;
} *cmd;
int ret;
+ struct vmw_resource *res;
cmd = container_of(header, struct vmw_dma_cmd, header);
ret = vmw_translate_guest_ptr(dev_priv, sw_context,
@@ -318,18 +574,28 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
goto out_no_reloc;
}
- /**
+ ret = vmw_surface_validate(dev_priv, srf);
+ if (unlikely(ret != 0)) {
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("Culd not validate surface.\n");
+ goto out_no_validate;
+ }
+
+ /*
* Patch command stream with device SID.
*/
-
cmd->dma.host.sid = srf->res.id;
vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
- /**
- * FIXME: May deadlock here when called from the
- * command parsing code.
- */
- vmw_surface_unreference(&srf);
+ vmw_dmabuf_unreference(&vmw_bo);
+
+ res = &srf->res;
+ vmw_resource_to_validate_list(sw_context, &res);
+
+ return 0;
+
+out_no_validate:
+ vmw_surface_unreference(&srf);
out_no_reloc:
vmw_dmabuf_unreference(&vmw_bo);
return ret;
@@ -419,6 +685,71 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
return 0;
}
+static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
+ struct vmw_sw_context *sw_context,
+ void *buf)
+{
+ struct vmw_dma_buffer *vmw_bo;
+ int ret;
+
+ struct {
+ uint32_t header;
+ SVGAFifoCmdDefineGMRFB body;
+ } *cmd = buf;
+
+ ret = vmw_translate_guest_ptr(dev_priv, sw_context,
+ &cmd->body.ptr,
+ &vmw_bo);
+ if (unlikely(ret != 0))
+ return ret;
+
+ vmw_dmabuf_unreference(&vmw_bo);
+
+ return ret;
+}
+
+static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
+ struct vmw_sw_context *sw_context,
+ void *buf, uint32_t *size)
+{
+ uint32_t size_remaining = *size;
+ uint32_t cmd_id;
+
+ cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
+ switch (cmd_id) {
+ case SVGA_CMD_UPDATE:
+ *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdUpdate);
+ break;
+ case SVGA_CMD_DEFINE_GMRFB:
+ *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMRFB);
+ break;
+ case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
+ *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen);
+ break;
+ case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
+ *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen);
+ break;
+ default:
+ DRM_ERROR("Unsupported SVGA command: %u.\n", cmd_id);
+ return -EINVAL;
+ }
+
+ if (*size > size_remaining) {
+ DRM_ERROR("Invalid SVGA command (size mismatch):"
+ " %u.\n", cmd_id);
+ return -EINVAL;
+ }
+
+ if (unlikely(!sw_context->kernel)) {
+ DRM_ERROR("Kernel only SVGA command: %u.\n", cmd_id);
+ return -EPERM;
+ }
+
+ if (cmd_id == SVGA_CMD_DEFINE_GMRFB)
+ return vmw_cmd_check_define_gmrfb(dev_priv, sw_context, buf);
+
+ return 0;
+}
typedef int (*vmw_cmd_func) (struct vmw_private *,
struct vmw_sw_context *,
@@ -471,11 +802,11 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
int ret;
- cmd_id = ((uint32_t *)buf)[0];
- if (cmd_id == SVGA_CMD_UPDATE) {
- *size = 5 << 2;
- return 0;
- }
+ cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
+ /* Handle any none 3D commands */
+ if (unlikely(cmd_id < SVGA_CMD_MAX))
+ return vmw_cmd_check_not_3d(dev_priv, sw_context, buf, size);
+
cmd_id = le32_to_cpu(header->id);
*size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader);
@@ -500,7 +831,8 @@ out_err:
static int vmw_cmd_check_all(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
- void *buf, uint32_t size)
+ void *buf,
+ uint32_t size)
{
int32_t cur_size = size;
int ret;
@@ -550,7 +882,11 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
static void vmw_clear_validations(struct vmw_sw_context *sw_context)
{
struct ttm_validate_buffer *entry, *next;
+ struct vmw_resource *res, *res_next;
+ /*
+ * Drop references to DMA buffers held during command submission.
+ */
list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
head) {
list_del(&entry->head);
@@ -559,6 +895,16 @@ static void vmw_clear_validations(struct vmw_sw_context *sw_context)
sw_context->cur_val_buf--;
}
BUG_ON(sw_context->cur_val_buf != 0);
+
+ /*
+ * Drop references to resources held during command submission.
+ */
+ vmw_resource_unreserve(&sw_context->resource_list);
+ list_for_each_entry_safe(res, res_next, &sw_context->resource_list,
+ validate_head) {
+ list_del_init(&res->validate_head);
+ vmw_resource_unreference(&res);
+ }
}
static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
@@ -566,6 +912,16 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
{
int ret;
+
+ /*
+ * Don't validate pinned buffers.
+ */
+
+ if (bo == dev_priv->pinned_bo ||
+ (bo == dev_priv->dummy_query_bo &&
+ dev_priv->dummy_query_bo_pinned))
+ return 0;
+
/**
* Put BO in VRAM if there is space, otherwise as a GMR.
* If there is no space in VRAM and GMR ids are all used up,
@@ -602,57 +958,208 @@ static int vmw_validate_buffers(struct vmw_private *dev_priv,
return 0;
}
-int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+static int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context,
+ uint32_t size)
+{
+ if (likely(sw_context->cmd_bounce_size >= size))
+ return 0;
+
+ if (sw_context->cmd_bounce_size == 0)
+ sw_context->cmd_bounce_size = VMWGFX_CMD_BOUNCE_INIT_SIZE;
+
+ while (sw_context->cmd_bounce_size < size) {
+ sw_context->cmd_bounce_size =
+ PAGE_ALIGN(sw_context->cmd_bounce_size +
+ (sw_context->cmd_bounce_size >> 1));
+ }
+
+ if (sw_context->cmd_bounce != NULL)
+ vfree(sw_context->cmd_bounce);
+
+ sw_context->cmd_bounce = vmalloc(sw_context->cmd_bounce_size);
+
+ if (sw_context->cmd_bounce == NULL) {
+ DRM_ERROR("Failed to allocate command bounce buffer.\n");
+ sw_context->cmd_bounce_size = 0;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/**
+ * vmw_execbuf_fence_commands - create and submit a command stream fence
+ *
+ * Creates a fence object and submits a command stream marker.
+ * If this fails for some reason, We sync the fifo and return NULL.
+ * It is then safe to fence buffers with a NULL pointer.
+ *
+ * If @p_handle is not NULL @file_priv must also not be NULL. Creates
+ * a userspace handle if @p_handle is not NULL, otherwise not.
+ */
+
+int vmw_execbuf_fence_commands(struct drm_file *file_priv,
+ struct vmw_private *dev_priv,
+ struct vmw_fence_obj **p_fence,
+ uint32_t *p_handle)
{
- struct vmw_private *dev_priv = vmw_priv(dev);
- struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
- struct drm_vmw_fence_rep fence_rep;
- struct drm_vmw_fence_rep __user *user_fence_rep;
- int ret;
- void *user_cmd;
- void *cmd;
uint32_t sequence;
- struct vmw_sw_context *sw_context = &dev_priv->ctx;
- struct vmw_master *vmaster = vmw_master(file_priv->master);
+ int ret;
+ bool synced = false;
- ret = ttm_read_lock(&vmaster->lock, true);
- if (unlikely(ret != 0))
- return ret;
+ /* p_handle implies file_priv. */
+ BUG_ON(p_handle != NULL && file_priv == NULL);
- ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+ ret = vmw_fifo_send_fence(dev_priv, &sequence);
if (unlikely(ret != 0)) {
- ret = -ERESTARTSYS;
- goto out_no_cmd_mutex;
+ DRM_ERROR("Fence submission error. Syncing.\n");
+ synced = true;
}
- cmd = vmw_fifo_reserve(dev_priv, arg->command_size);
- if (unlikely(cmd == NULL)) {
- DRM_ERROR("Failed reserving fifo space for commands.\n");
- ret = -ENOMEM;
- goto out_unlock;
+ if (p_handle != NULL)
+ ret = vmw_user_fence_create(file_priv, dev_priv->fman,
+ sequence,
+ DRM_VMW_FENCE_FLAG_EXEC,
+ p_fence, p_handle);
+ else
+ ret = vmw_fence_create(dev_priv->fman, sequence,
+ DRM_VMW_FENCE_FLAG_EXEC,
+ p_fence);
+
+ if (unlikely(ret != 0 && !synced)) {
+ (void) vmw_fallback_wait(dev_priv, false, false,
+ sequence, false,
+ VMW_FENCE_WAIT_TIMEOUT);
+ *p_fence = NULL;
}
- user_cmd = (void __user *)(unsigned long)arg->commands;
- ret = copy_from_user(cmd, user_cmd, arg->command_size);
+ return 0;
+}
- if (unlikely(ret != 0)) {
- ret = -EFAULT;
- DRM_ERROR("Failed copying commands.\n");
- goto out_commit;
+/**
+ * vmw_execbuf_copy_fence_user - copy fence object information to
+ * user-space.
+ *
+ * @dev_priv: Pointer to a vmw_private struct.
+ * @vmw_fp: Pointer to the struct vmw_fpriv representing the calling file.
+ * @ret: Return value from fence object creation.
+ * @user_fence_rep: User space address of a struct drm_vmw_fence_rep to
+ * which the information should be copied.
+ * @fence: Pointer to the fenc object.
+ * @fence_handle: User-space fence handle.
+ *
+ * This function copies fence information to user-space. If copying fails,
+ * The user-space struct drm_vmw_fence_rep::error member is hopefully
+ * left untouched, and if it's preloaded with an -EFAULT by user-space,
+ * the error will hopefully be detected.
+ * Also if copying fails, user-space will be unable to signal the fence
+ * object so we wait for it immediately, and then unreference the
+ * user-space reference.
+ */
+void
+vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
+ struct vmw_fpriv *vmw_fp,
+ int ret,
+ struct drm_vmw_fence_rep __user *user_fence_rep,
+ struct vmw_fence_obj *fence,
+ uint32_t fence_handle)
+{
+ struct drm_vmw_fence_rep fence_rep;
+
+ if (user_fence_rep == NULL)
+ return;
+
+ memset(&fence_rep, 0, sizeof(fence_rep));
+
+ fence_rep.error = ret;
+ if (ret == 0) {
+ BUG_ON(fence == NULL);
+
+ fence_rep.handle = fence_handle;
+ fence_rep.seqno = fence->seqno;
+ vmw_update_seqno(dev_priv, &dev_priv->fifo);
+ fence_rep.passed_seqno = dev_priv->last_read_seqno;
}
+ /*
+ * copy_to_user errors will be detected by user space not
+ * seeing fence_rep::error filled in. Typically
+ * user-space would have pre-set that member to -EFAULT.
+ */
+ ret = copy_to_user(user_fence_rep, &fence_rep,
+ sizeof(fence_rep));
+
+ /*
+ * User-space lost the fence object. We need to sync
+ * and unreference the handle.
+ */
+ if (unlikely(ret != 0) && (fence_rep.error == 0)) {
+ ttm_ref_object_base_unref(vmw_fp->tfile,
+ fence_handle, TTM_REF_USAGE);
+ DRM_ERROR("Fence copy error. Syncing.\n");
+ (void) vmw_fence_obj_wait(fence, fence->signal_mask,
+ false, false,
+ VMW_FENCE_WAIT_TIMEOUT);
+ }
+}
+
+int vmw_execbuf_process(struct drm_file *file_priv,
+ struct vmw_private *dev_priv,
+ void __user *user_commands,
+ void *kernel_commands,
+ uint32_t command_size,
+ uint64_t throttle_us,
+ struct drm_vmw_fence_rep __user *user_fence_rep)
+{
+ struct vmw_sw_context *sw_context = &dev_priv->ctx;
+ struct vmw_fence_obj *fence;
+ uint32_t handle;
+ void *cmd;
+ int ret;
+
+ ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+ if (unlikely(ret != 0))
+ return -ERESTARTSYS;
+
+ if (kernel_commands == NULL) {
+ sw_context->kernel = false;
+
+ ret = vmw_resize_cmd_bounce(sw_context, command_size);
+ if (unlikely(ret != 0))
+ goto out_unlock;
+
+
+ ret = copy_from_user(sw_context->cmd_bounce,
+ user_commands, command_size);
+
+ if (unlikely(ret != 0)) {
+ ret = -EFAULT;
+ DRM_ERROR("Failed copying commands.\n");
+ goto out_unlock;
+ }
+ kernel_commands = sw_context->cmd_bounce;
+ } else
+ sw_context->kernel = true;
+
sw_context->tfile = vmw_fpriv(file_priv)->tfile;
sw_context->cid_valid = false;
sw_context->sid_valid = false;
sw_context->cur_reloc = 0;
sw_context->cur_val_buf = 0;
+ sw_context->fence_flags = 0;
+ INIT_LIST_HEAD(&sw_context->query_list);
+ INIT_LIST_HEAD(&sw_context->resource_list);
+ sw_context->cur_query_bo = dev_priv->pinned_bo;
+ sw_context->cur_query_cid = dev_priv->query_cid;
+ sw_context->query_cid_valid = (dev_priv->pinned_bo != NULL);
INIT_LIST_HEAD(&sw_context->validate_nodes);
- ret = vmw_cmd_check_all(dev_priv, sw_context, cmd, arg->command_size);
+ ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
+ command_size);
if (unlikely(ret != 0))
goto out_err;
+
ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes);
if (unlikely(ret != 0))
goto out_err;
@@ -663,57 +1170,206 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
vmw_apply_relocations(sw_context);
- if (arg->throttle_us) {
- ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.fence_queue,
- arg->throttle_us);
+ if (throttle_us) {
+ ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue,
+ throttle_us);
if (unlikely(ret != 0))
- goto out_err;
+ goto out_throttle;
}
- vmw_fifo_commit(dev_priv, arg->command_size);
-
- ret = vmw_fifo_send_fence(dev_priv, &sequence);
+ cmd = vmw_fifo_reserve(dev_priv, command_size);
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("Failed reserving fifo space for commands.\n");
+ ret = -ENOMEM;
+ goto out_throttle;
+ }
- ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
- (void *)(unsigned long) sequence);
- vmw_clear_validations(sw_context);
- mutex_unlock(&dev_priv->cmdbuf_mutex);
+ memcpy(cmd, kernel_commands, command_size);
+ vmw_fifo_commit(dev_priv, command_size);
+ vmw_query_bo_switch_commit(dev_priv, sw_context);
+ ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
+ &fence,
+ (user_fence_rep) ? &handle : NULL);
/*
* This error is harmless, because if fence submission fails,
- * vmw_fifo_send_fence will sync.
+ * vmw_fifo_send_fence will sync. The error will be propagated to
+ * user-space in @fence_rep
*/
if (ret != 0)
DRM_ERROR("Fence submission error. Syncing.\n");
- fence_rep.error = ret;
- fence_rep.fence_seq = (uint64_t) sequence;
- fence_rep.pad64 = 0;
-
- user_fence_rep = (struct drm_vmw_fence_rep __user *)
- (unsigned long)arg->fence_rep;
+ ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
+ (void *) fence);
- /*
- * copy_to_user errors will be detected by user space not
- * seeing fence_rep::error filled in.
- */
+ vmw_clear_validations(sw_context);
+ vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
+ user_fence_rep, fence, handle);
- ret = copy_to_user(user_fence_rep, &fence_rep, sizeof(fence_rep));
+ if (likely(fence != NULL))
+ vmw_fence_obj_unreference(&fence);
- vmw_kms_cursor_post_execbuf(dev_priv);
- ttm_read_unlock(&vmaster->lock);
+ mutex_unlock(&dev_priv->cmdbuf_mutex);
return 0;
+
out_err:
vmw_free_relocations(sw_context);
+out_throttle:
+ vmw_query_switch_backoff(sw_context);
ttm_eu_backoff_reservation(&sw_context->validate_nodes);
vmw_clear_validations(sw_context);
-out_commit:
- vmw_fifo_commit(dev_priv, 0);
out_unlock:
mutex_unlock(&dev_priv->cmdbuf_mutex);
-out_no_cmd_mutex:
+ return ret;
+}
+
+/**
+ * vmw_execbuf_unpin_panic - Idle the fifo and unpin the query buffer.
+ *
+ * @dev_priv: The device private structure.
+ *
+ * This function is called to idle the fifo and unpin the query buffer
+ * if the normal way to do this hits an error, which should typically be
+ * extremely rare.
+ */
+static void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv)
+{
+ DRM_ERROR("Can't unpin query buffer. Trying to recover.\n");
+
+ (void) vmw_fallback_wait(dev_priv, false, true, 0, false, 10*HZ);
+ vmw_bo_pin(dev_priv->pinned_bo, false);
+ vmw_bo_pin(dev_priv->dummy_query_bo, false);
+ dev_priv->dummy_query_bo_pinned = false;
+}
+
+
+/**
+ * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
+ * query bo.
+ *
+ * @dev_priv: The device private structure.
+ * @only_on_cid_match: Only flush and unpin if the current active query cid
+ * matches @cid.
+ * @cid: Optional context id to match.
+ *
+ * This function should be used to unpin the pinned query bo, or
+ * as a query barrier when we need to make sure that all queries have
+ * finished before the next fifo command. (For example on hardware
+ * context destructions where the hardware may otherwise leak unfinished
+ * queries).
+ *
+ * This function does not return any failure codes, but make attempts
+ * to do safe unpinning in case of errors.
+ *
+ * The function will synchronize on the previous query barrier, and will
+ * thus not finish until that barrier has executed.
+ */
+void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
+ bool only_on_cid_match, uint32_t cid)
+{
+ int ret = 0;
+ struct list_head validate_list;
+ struct ttm_validate_buffer pinned_val, query_val;
+ struct vmw_fence_obj *fence;
+
+ mutex_lock(&dev_priv->cmdbuf_mutex);
+
+ if (dev_priv->pinned_bo == NULL)
+ goto out_unlock;
+
+ if (only_on_cid_match && cid != dev_priv->query_cid)
+ goto out_unlock;
+
+ INIT_LIST_HEAD(&validate_list);
+
+ pinned_val.new_sync_obj_arg = (void *)(unsigned long)
+ DRM_VMW_FENCE_FLAG_EXEC;
+ pinned_val.bo = ttm_bo_reference(dev_priv->pinned_bo);
+ list_add_tail(&pinned_val.head, &validate_list);
+
+ query_val.new_sync_obj_arg = pinned_val.new_sync_obj_arg;
+ query_val.bo = ttm_bo_reference(dev_priv->dummy_query_bo);
+ list_add_tail(&query_val.head, &validate_list);
+
+ do {
+ ret = ttm_eu_reserve_buffers(&validate_list);
+ } while (ret == -ERESTARTSYS);
+
+ if (unlikely(ret != 0)) {
+ vmw_execbuf_unpin_panic(dev_priv);
+ goto out_no_reserve;
+ }
+
+ ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid);
+ if (unlikely(ret != 0)) {
+ vmw_execbuf_unpin_panic(dev_priv);
+ goto out_no_emit;
+ }
+
+ vmw_bo_pin(dev_priv->pinned_bo, false);
+ vmw_bo_pin(dev_priv->dummy_query_bo, false);
+ dev_priv->dummy_query_bo_pinned = false;
+
+ (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
+ ttm_eu_fence_buffer_objects(&validate_list, (void *) fence);
+
+ ttm_bo_unref(&query_val.bo);
+ ttm_bo_unref(&pinned_val.bo);
+ ttm_bo_unref(&dev_priv->pinned_bo);
+
+out_unlock:
+ mutex_unlock(&dev_priv->cmdbuf_mutex);
+ return;
+
+out_no_emit:
+ ttm_eu_backoff_reservation(&validate_list);
+out_no_reserve:
+ ttm_bo_unref(&query_val.bo);
+ ttm_bo_unref(&pinned_val.bo);
+ ttm_bo_unref(&dev_priv->pinned_bo);
+ mutex_unlock(&dev_priv->cmdbuf_mutex);
+}
+
+
+int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct vmw_private *dev_priv = vmw_priv(dev);
+ struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
+ struct vmw_master *vmaster = vmw_master(file_priv->master);
+ int ret;
+
+ /*
+ * This will allow us to extend the ioctl argument while
+ * maintaining backwards compatibility:
+ * We take different code paths depending on the value of
+ * arg->version.
+ */
+
+ if (unlikely(arg->version != DRM_VMW_EXECBUF_VERSION)) {
+ DRM_ERROR("Incorrect execbuf version.\n");
+ DRM_ERROR("You're running outdated experimental "
+ "vmwgfx user-space drivers.");
+ return -EINVAL;
+ }
+
+ ret = ttm_read_lock(&vmaster->lock, true);
+ if (unlikely(ret != 0))
+ return ret;
+
+ ret = vmw_execbuf_process(file_priv, dev_priv,
+ (void __user *)(unsigned long)arg->commands,
+ NULL, arg->command_size, arg->throttle_us,
+ (void __user *)(unsigned long)arg->fence_rep);
+
+ if (unlikely(ret != 0))
+ goto out_unlock;
+
+ vmw_kms_cursor_post_execbuf(dev_priv);
+
+out_unlock:
ttm_read_unlock(&vmaster->lock);
return ret;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index bfab60c938ac..070797b7b03a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -158,10 +158,14 @@ static int vmw_fb_set_par(struct fb_info *info)
{
struct vmw_fb_par *par = info->par;
struct vmw_private *vmw_priv = par->vmw_priv;
+ int ret;
+
+ ret = vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
+ info->fix.line_length,
+ par->bpp, par->depth);
+ if (ret)
+ return ret;
- vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
- info->fix.line_length,
- par->bpp, par->depth);
if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
/* TODO check if pitch and offset changes */
vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
@@ -405,14 +409,14 @@ int vmw_fb_init(struct vmw_private *vmw_priv)
struct fb_info *info;
unsigned initial_width, initial_height;
unsigned fb_width, fb_height;
- unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
+ unsigned fb_bpp, fb_depth, fb_offset, fb_pitch, fb_size;
int ret;
/* XXX These shouldn't be hardcoded. */
initial_width = 800;
initial_height = 600;
- fb_bbp = 32;
+ fb_bpp = 32;
fb_depth = 24;
/* XXX As shouldn't these be as well. */
@@ -422,7 +426,7 @@ int vmw_fb_init(struct vmw_private *vmw_priv)
initial_width = min(fb_width, initial_width);
initial_height = min(fb_height, initial_height);
- fb_pitch = fb_width * fb_bbp / 8;
+ fb_pitch = fb_width * fb_bpp / 8;
fb_size = fb_pitch * fb_height;
fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
@@ -437,7 +441,7 @@ int vmw_fb_init(struct vmw_private *vmw_priv)
par = info->par;
par->vmw_priv = vmw_priv;
par->depth = fb_depth;
- par->bpp = fb_bbp;
+ par->bpp = fb_bpp;
par->vmalloc = NULL;
par->max_width = fb_width;
par->max_height = fb_height;
@@ -588,58 +592,6 @@ int vmw_fb_close(struct vmw_private *vmw_priv)
return 0;
}
-int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
- struct vmw_dma_buffer *vmw_bo)
-{
- struct ttm_buffer_object *bo = &vmw_bo->base;
- int ret = 0;
-
- ret = ttm_bo_reserve(bo, false, false, false, 0);
- if (unlikely(ret != 0))
- return ret;
-
- ret = ttm_bo_validate(bo, &vmw_sys_placement, false, false, false);
- ttm_bo_unreserve(bo);
-
- return ret;
-}
-
-int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
- struct vmw_dma_buffer *vmw_bo)
-{
- struct ttm_buffer_object *bo = &vmw_bo->base;
- struct ttm_placement ne_placement = vmw_vram_ne_placement;
- int ret = 0;
-
- ne_placement.lpfn = bo->num_pages;
-
- /* interuptable? */
- ret = ttm_write_lock(&vmw_priv->active_master->lock, false);
- if (unlikely(ret != 0))
- return ret;
-
- ret = ttm_bo_reserve(bo, false, false, false, 0);
- if (unlikely(ret != 0))
- goto err_unlock;
-
- if (bo->mem.mem_type == TTM_PL_VRAM &&
- bo->mem.start < bo->num_pages &&
- bo->mem.start > 0)
- (void) ttm_bo_validate(bo, &vmw_sys_placement, false,
- false, false);
-
- ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
-
- /* Could probably bug on */
- WARN_ON(bo->offset != 0);
-
- ttm_bo_unreserve(bo);
-err_unlock:
- ttm_write_unlock(&vmw_priv->active_master->lock);
-
- return ret;
-}
-
int vmw_fb_off(struct vmw_private *vmw_priv)
{
struct fb_info *info;
@@ -661,7 +613,7 @@ int vmw_fb_off(struct vmw_private *vmw_priv)
par->bo_ptr = NULL;
ttm_bo_kunmap(&par->map);
- vmw_dmabuf_from_vram(vmw_priv, par->vmw_bo);
+ vmw_dmabuf_unpin(vmw_priv, par->vmw_bo, false);
return 0;
}
@@ -687,7 +639,7 @@ int vmw_fb_on(struct vmw_private *vmw_priv)
/* Make sure that all overlays are stoped when we take over */
vmw_overlay_stop_all(vmw_priv);
- ret = vmw_dmabuf_to_start_of_vram(vmw_priv, par->vmw_bo);
+ ret = vmw_dmabuf_to_start_of_vram(vmw_priv, par->vmw_bo, true, false);
if (unlikely(ret != 0)) {
DRM_ERROR("could not move buffer to start of VRAM\n");
goto err_no_buffer;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index 61eacc1b5ca3..15fb26088d68 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
+ * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,149 +25,1100 @@
*
**************************************************************************/
-
+#include "drmP.h"
#include "vmwgfx_drv.h"
-struct vmw_fence {
- struct list_head head;
- uint32_t sequence;
- struct timespec submitted;
+#define VMW_FENCE_WRAP (1 << 31)
+
+struct vmw_fence_manager {
+ int num_fence_objects;
+ struct vmw_private *dev_priv;
+ spinlock_t lock;
+ struct list_head fence_list;
+ struct work_struct work;
+ u32 user_fence_size;
+ u32 fence_size;
+ u32 event_fence_action_size;
+ bool fifo_down;
+ struct list_head cleanup_list;
+ uint32_t pending_actions[VMW_ACTION_MAX];
+ struct mutex goal_irq_mutex;
+ bool goal_irq_on; /* Protected by @goal_irq_mutex */
+ bool seqno_valid; /* Protected by @lock, and may not be set to true
+ without the @goal_irq_mutex held. */
};
-void vmw_fence_queue_init(struct vmw_fence_queue *queue)
+struct vmw_user_fence {
+ struct ttm_base_object base;
+ struct vmw_fence_obj fence;
+};
+
+/**
+ * struct vmw_event_fence_action - fence action that delivers a drm event.
+ *
+ * @e: A struct drm_pending_event that controls the event delivery.
+ * @action: A struct vmw_fence_action to hook up to a fence.
+ * @fence: A referenced pointer to the fence to keep it alive while @action
+ * hangs on it.
+ * @dev: Pointer to a struct drm_device so we can access the event stuff.
+ * @kref: Both @e and @action has destructors, so we need to refcount.
+ * @size: Size accounted for this object.
+ * @tv_sec: If non-null, the variable pointed to will be assigned
+ * current time tv_sec val when the fence signals.
+ * @tv_usec: Must be set if @tv_sec is set, and the variable pointed to will
+ * be assigned the current time tv_usec val when the fence signals.
+ */
+struct vmw_event_fence_action {
+ struct drm_pending_event e;
+ struct vmw_fence_action action;
+ struct vmw_fence_obj *fence;
+ struct drm_device *dev;
+ struct kref kref;
+ uint32_t size;
+ uint32_t *tv_sec;
+ uint32_t *tv_usec;
+};
+
+/**
+ * Note on fencing subsystem usage of irqs:
+ * Typically the vmw_fences_update function is called
+ *
+ * a) When a new fence seqno has been submitted by the fifo code.
+ * b) On-demand when we have waiters. Sleeping waiters will switch on the
+ * ANY_FENCE irq and call vmw_fences_update function each time an ANY_FENCE
+ * irq is received. When the last fence waiter is gone, that IRQ is masked
+ * away.
+ *
+ * In situations where there are no waiters and we don't submit any new fences,
+ * fence objects may not be signaled. This is perfectly OK, since there are
+ * no consumers of the signaled data, but that is NOT ok when there are fence
+ * actions attached to a fence. The fencing subsystem then makes use of the
+ * FENCE_GOAL irq and sets the fence goal seqno to that of the next fence
+ * which has an action attached, and each time vmw_fences_update is called,
+ * the subsystem makes sure the fence goal seqno is updated.
+ *
+ * The fence goal seqno irq is on as long as there are unsignaled fence
+ * objects with actions attached to them.
+ */
+
+static void vmw_fence_obj_destroy_locked(struct kref *kref)
+{
+ struct vmw_fence_obj *fence =
+ container_of(kref, struct vmw_fence_obj, kref);
+
+ struct vmw_fence_manager *fman = fence->fman;
+ unsigned int num_fences;
+
+ list_del_init(&fence->head);
+ num_fences = --fman->num_fence_objects;
+ spin_unlock_irq(&fman->lock);
+ if (fence->destroy)
+ fence->destroy(fence);
+ else
+ kfree(fence);
+
+ spin_lock_irq(&fman->lock);
+}
+
+
+/**
+ * Execute signal actions on fences recently signaled.
+ * This is done from a workqueue so we don't have to execute
+ * signal actions from atomic context.
+ */
+
+static void vmw_fence_work_func(struct work_struct *work)
{
- INIT_LIST_HEAD(&queue->head);
- queue->lag = ns_to_timespec(0);
- getrawmonotonic(&queue->lag_time);
- spin_lock_init(&queue->lock);
+ struct vmw_fence_manager *fman =
+ container_of(work, struct vmw_fence_manager, work);
+ struct list_head list;
+ struct vmw_fence_action *action, *next_action;
+ bool seqno_valid;
+
+ do {
+ INIT_LIST_HEAD(&list);
+ mutex_lock(&fman->goal_irq_mutex);
+
+ spin_lock_irq(&fman->lock);
+ list_splice_init(&fman->cleanup_list, &list);
+ seqno_valid = fman->seqno_valid;
+ spin_unlock_irq(&fman->lock);
+
+ if (!seqno_valid && fman->goal_irq_on) {
+ fman->goal_irq_on = false;
+ vmw_goal_waiter_remove(fman->dev_priv);
+ }
+ mutex_unlock(&fman->goal_irq_mutex);
+
+ if (list_empty(&list))
+ return;
+
+ /*
+ * At this point, only we should be able to manipulate the
+ * list heads of the actions we have on the private list.
+ * hence fman::lock not held.
+ */
+
+ list_for_each_entry_safe(action, next_action, &list, head) {
+ list_del_init(&action->head);
+ if (action->cleanup)
+ action->cleanup(action);
+ }
+ } while (1);
}
-void vmw_fence_queue_takedown(struct vmw_fence_queue *queue)
+struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv)
{
- struct vmw_fence *fence, *next;
+ struct vmw_fence_manager *fman = kzalloc(sizeof(*fman), GFP_KERNEL);
- spin_lock(&queue->lock);
- list_for_each_entry_safe(fence, next, &queue->head, head) {
- kfree(fence);
- }
- spin_unlock(&queue->lock);
+ if (unlikely(fman == NULL))
+ return NULL;
+
+ fman->dev_priv = dev_priv;
+ spin_lock_init(&fman->lock);
+ INIT_LIST_HEAD(&fman->fence_list);
+ INIT_LIST_HEAD(&fman->cleanup_list);
+ INIT_WORK(&fman->work, &vmw_fence_work_func);
+ fman->fifo_down = true;
+ fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence));
+ fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj));
+ fman->event_fence_action_size =
+ ttm_round_pot(sizeof(struct vmw_event_fence_action));
+ mutex_init(&fman->goal_irq_mutex);
+
+ return fman;
}
-int vmw_fence_push(struct vmw_fence_queue *queue,
- uint32_t sequence)
+void vmw_fence_manager_takedown(struct vmw_fence_manager *fman)
{
- struct vmw_fence *fence = kmalloc(sizeof(*fence), GFP_KERNEL);
+ unsigned long irq_flags;
+ bool lists_empty;
- if (unlikely(!fence))
- return -ENOMEM;
+ (void) cancel_work_sync(&fman->work);
- fence->sequence = sequence;
- getrawmonotonic(&fence->submitted);
- spin_lock(&queue->lock);
- list_add_tail(&fence->head, &queue->head);
- spin_unlock(&queue->lock);
+ spin_lock_irqsave(&fman->lock, irq_flags);
+ lists_empty = list_empty(&fman->fence_list) &&
+ list_empty(&fman->cleanup_list);
+ spin_unlock_irqrestore(&fman->lock, irq_flags);
- return 0;
+ BUG_ON(!lists_empty);
+ kfree(fman);
}
-int vmw_fence_pull(struct vmw_fence_queue *queue,
- uint32_t signaled_sequence)
+static int vmw_fence_obj_init(struct vmw_fence_manager *fman,
+ struct vmw_fence_obj *fence,
+ u32 seqno,
+ uint32_t mask,
+ void (*destroy) (struct vmw_fence_obj *fence))
{
- struct vmw_fence *fence, *next;
- struct timespec now;
- bool updated = false;
+ unsigned long irq_flags;
+ unsigned int num_fences;
+ int ret = 0;
- spin_lock(&queue->lock);
- getrawmonotonic(&now);
+ fence->seqno = seqno;
+ INIT_LIST_HEAD(&fence->seq_passed_actions);
+ fence->fman = fman;
+ fence->signaled = 0;
+ fence->signal_mask = mask;
+ kref_init(&fence->kref);
+ fence->destroy = destroy;
+ init_waitqueue_head(&fence->queue);
- if (list_empty(&queue->head)) {
- queue->lag = ns_to_timespec(0);
- queue->lag_time = now;
- updated = true;
+ spin_lock_irqsave(&fman->lock, irq_flags);
+ if (unlikely(fman->fifo_down)) {
+ ret = -EBUSY;
goto out_unlock;
}
+ list_add_tail(&fence->head, &fman->fence_list);
+ num_fences = ++fman->num_fence_objects;
- list_for_each_entry_safe(fence, next, &queue->head, head) {
- if (signaled_sequence - fence->sequence > (1 << 30))
- continue;
+out_unlock:
+ spin_unlock_irqrestore(&fman->lock, irq_flags);
+ return ret;
- queue->lag = timespec_sub(now, fence->submitted);
- queue->lag_time = now;
- updated = true;
- list_del(&fence->head);
- kfree(fence);
+}
+
+struct vmw_fence_obj *vmw_fence_obj_reference(struct vmw_fence_obj *fence)
+{
+ if (unlikely(fence == NULL))
+ return NULL;
+
+ kref_get(&fence->kref);
+ return fence;
+}
+
+/**
+ * vmw_fence_obj_unreference
+ *
+ * Note that this function may not be entered with disabled irqs since
+ * it may re-enable them in the destroy function.
+ *
+ */
+void vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p)
+{
+ struct vmw_fence_obj *fence = *fence_p;
+ struct vmw_fence_manager *fman;
+
+ if (unlikely(fence == NULL))
+ return;
+
+ fman = fence->fman;
+ *fence_p = NULL;
+ spin_lock_irq(&fman->lock);
+ BUG_ON(atomic_read(&fence->kref.refcount) == 0);
+ kref_put(&fence->kref, vmw_fence_obj_destroy_locked);
+ spin_unlock_irq(&fman->lock);
+}
+
+void vmw_fences_perform_actions(struct vmw_fence_manager *fman,
+ struct list_head *list)
+{
+ struct vmw_fence_action *action, *next_action;
+
+ list_for_each_entry_safe(action, next_action, list, head) {
+ list_del_init(&action->head);
+ fman->pending_actions[action->type]--;
+ if (action->seq_passed != NULL)
+ action->seq_passed(action);
+
+ /*
+ * Add the cleanup action to the cleanup list so that
+ * it will be performed by a worker task.
+ */
+
+ list_add_tail(&action->head, &fman->cleanup_list);
}
+}
+
+/**
+ * vmw_fence_goal_new_locked - Figure out a new device fence goal
+ * seqno if needed.
+ *
+ * @fman: Pointer to a fence manager.
+ * @passed_seqno: The seqno the device currently signals as passed.
+ *
+ * This function should be called with the fence manager lock held.
+ * It is typically called when we have a new passed_seqno, and
+ * we might need to update the fence goal. It checks to see whether
+ * the current fence goal has already passed, and, in that case,
+ * scans through all unsignaled fences to get the next fence object with an
+ * action attached, and sets the seqno of that fence as a new fence goal.
+ *
+ * returns true if the device goal seqno was updated. False otherwise.
+ */
+static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
+ u32 passed_seqno)
+{
+ u32 goal_seqno;
+ __le32 __iomem *fifo_mem;
+ struct vmw_fence_obj *fence;
+
+ if (likely(!fman->seqno_valid))
+ return false;
+
+ fifo_mem = fman->dev_priv->mmio_virt;
+ goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL);
+ if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP))
+ return false;
+
+ fman->seqno_valid = false;
+ list_for_each_entry(fence, &fman->fence_list, head) {
+ if (!list_empty(&fence->seq_passed_actions)) {
+ fman->seqno_valid = true;
+ iowrite32(fence->seqno,
+ fifo_mem + SVGA_FIFO_FENCE_GOAL);
+ break;
+ }
+ }
+
+ return true;
+}
-out_unlock:
- spin_unlock(&queue->lock);
- return (updated) ? 0 : -EBUSY;
+/**
+ * vmw_fence_goal_check_locked - Replace the device fence goal seqno if
+ * needed.
+ *
+ * @fence: Pointer to a struct vmw_fence_obj the seqno of which should be
+ * considered as a device fence goal.
+ *
+ * This function should be called with the fence manager lock held.
+ * It is typically called when an action has been attached to a fence to
+ * check whether the seqno of that fence should be used for a fence
+ * goal interrupt. This is typically needed if the current fence goal is
+ * invalid, or has a higher seqno than that of the current fence object.
+ *
+ * returns true if the device goal seqno was updated. False otherwise.
+ */
+static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence)
+{
+ u32 goal_seqno;
+ __le32 __iomem *fifo_mem;
+
+ if (fence->signaled & DRM_VMW_FENCE_FLAG_EXEC)
+ return false;
+
+ fifo_mem = fence->fman->dev_priv->mmio_virt;
+ goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL);
+ if (likely(fence->fman->seqno_valid &&
+ goal_seqno - fence->seqno < VMW_FENCE_WRAP))
+ return false;
+
+ iowrite32(fence->seqno, fifo_mem + SVGA_FIFO_FENCE_GOAL);
+ fence->fman->seqno_valid = true;
+
+ return true;
}
-static struct timespec vmw_timespec_add(struct timespec t1,
- struct timespec t2)
+void vmw_fences_update(struct vmw_fence_manager *fman)
{
- t1.tv_sec += t2.tv_sec;
- t1.tv_nsec += t2.tv_nsec;
- if (t1.tv_nsec >= 1000000000L) {
- t1.tv_sec += 1;
- t1.tv_nsec -= 1000000000L;
+ unsigned long flags;
+ struct vmw_fence_obj *fence, *next_fence;
+ struct list_head action_list;
+ bool needs_rerun;
+ uint32_t seqno, new_seqno;
+ __le32 __iomem *fifo_mem = fman->dev_priv->mmio_virt;
+
+ seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+rerun:
+ spin_lock_irqsave(&fman->lock, flags);
+ list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) {
+ if (seqno - fence->seqno < VMW_FENCE_WRAP) {
+ list_del_init(&fence->head);
+ fence->signaled |= DRM_VMW_FENCE_FLAG_EXEC;
+ INIT_LIST_HEAD(&action_list);
+ list_splice_init(&fence->seq_passed_actions,
+ &action_list);
+ vmw_fences_perform_actions(fman, &action_list);
+ wake_up_all(&fence->queue);
+ } else
+ break;
}
- return t1;
+ needs_rerun = vmw_fence_goal_new_locked(fman, seqno);
+
+ if (!list_empty(&fman->cleanup_list))
+ (void) schedule_work(&fman->work);
+ spin_unlock_irqrestore(&fman->lock, flags);
+
+ /*
+ * Rerun if the fence goal seqno was updated, and the
+ * hardware might have raced with that update, so that
+ * we missed a fence_goal irq.
+ */
+
+ if (unlikely(needs_rerun)) {
+ new_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+ if (new_seqno != seqno) {
+ seqno = new_seqno;
+ goto rerun;
+ }
+ }
+}
+
+bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence,
+ uint32_t flags)
+{
+ struct vmw_fence_manager *fman = fence->fman;
+ unsigned long irq_flags;
+ uint32_t signaled;
+
+ spin_lock_irqsave(&fman->lock, irq_flags);
+ signaled = fence->signaled;
+ spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+ flags &= fence->signal_mask;
+ if ((signaled & flags) == flags)
+ return 1;
+
+ if ((signaled & DRM_VMW_FENCE_FLAG_EXEC) == 0)
+ vmw_fences_update(fman);
+
+ spin_lock_irqsave(&fman->lock, irq_flags);
+ signaled = fence->signaled;
+ spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+ return ((signaled & flags) == flags);
}
-static struct timespec vmw_fifo_lag(struct vmw_fence_queue *queue)
+int vmw_fence_obj_wait(struct vmw_fence_obj *fence,
+ uint32_t flags, bool lazy,
+ bool interruptible, unsigned long timeout)
{
- struct timespec now;
+ struct vmw_private *dev_priv = fence->fman->dev_priv;
+ long ret;
+
+ if (likely(vmw_fence_obj_signaled(fence, flags)))
+ return 0;
+
+ vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+ vmw_seqno_waiter_add(dev_priv);
+
+ if (interruptible)
+ ret = wait_event_interruptible_timeout
+ (fence->queue,
+ vmw_fence_obj_signaled(fence, flags),
+ timeout);
+ else
+ ret = wait_event_timeout
+ (fence->queue,
+ vmw_fence_obj_signaled(fence, flags),
+ timeout);
+
+ vmw_seqno_waiter_remove(dev_priv);
+
+ if (unlikely(ret == 0))
+ ret = -EBUSY;
+ else if (likely(ret > 0))
+ ret = 0;
+
+ return ret;
+}
+
+void vmw_fence_obj_flush(struct vmw_fence_obj *fence)
+{
+ struct vmw_private *dev_priv = fence->fman->dev_priv;
+
+ vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+}
+
+static void vmw_fence_destroy(struct vmw_fence_obj *fence)
+{
+ struct vmw_fence_manager *fman = fence->fman;
+
+ kfree(fence);
+ /*
+ * Free kernel space accounting.
+ */
+ ttm_mem_global_free(vmw_mem_glob(fman->dev_priv),
+ fman->fence_size);
+}
+
+int vmw_fence_create(struct vmw_fence_manager *fman,
+ uint32_t seqno,
+ uint32_t mask,
+ struct vmw_fence_obj **p_fence)
+{
+ struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv);
+ struct vmw_fence_obj *fence;
+ int ret;
+
+ ret = ttm_mem_global_alloc(mem_glob, fman->fence_size,
+ false, false);
+ if (unlikely(ret != 0))
+ return ret;
+
+ fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+ if (unlikely(fence == NULL)) {
+ ret = -ENOMEM;
+ goto out_no_object;
+ }
+
+ ret = vmw_fence_obj_init(fman, fence, seqno, mask,
+ vmw_fence_destroy);
+ if (unlikely(ret != 0))
+ goto out_err_init;
+
+ *p_fence = fence;
+ return 0;
+
+out_err_init:
+ kfree(fence);
+out_no_object:
+ ttm_mem_global_free(mem_glob, fman->fence_size);
+ return ret;
+}
+
+
+static void vmw_user_fence_destroy(struct vmw_fence_obj *fence)
+{
+ struct vmw_user_fence *ufence =
+ container_of(fence, struct vmw_user_fence, fence);
+ struct vmw_fence_manager *fman = fence->fman;
+
+ kfree(ufence);
+ /*
+ * Free kernel space accounting.
+ */
+ ttm_mem_global_free(vmw_mem_glob(fman->dev_priv),
+ fman->user_fence_size);
+}
+
+static void vmw_user_fence_base_release(struct ttm_base_object **p_base)
+{
+ struct ttm_base_object *base = *p_base;
+ struct vmw_user_fence *ufence =
+ container_of(base, struct vmw_user_fence, base);
+ struct vmw_fence_obj *fence = &ufence->fence;
+
+ *p_base = NULL;
+ vmw_fence_obj_unreference(&fence);
+}
+
+int vmw_user_fence_create(struct drm_file *file_priv,
+ struct vmw_fence_manager *fman,
+ uint32_t seqno,
+ uint32_t mask,
+ struct vmw_fence_obj **p_fence,
+ uint32_t *p_handle)
+{
+ struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+ struct vmw_user_fence *ufence;
+ struct vmw_fence_obj *tmp;
+ struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv);
+ int ret;
+
+ /*
+ * Kernel memory space accounting, since this object may
+ * be created by a user-space request.
+ */
+
+ ret = ttm_mem_global_alloc(mem_glob, fman->user_fence_size,
+ false, false);
+ if (unlikely(ret != 0))
+ return ret;
+
+ ufence = kzalloc(sizeof(*ufence), GFP_KERNEL);
+ if (unlikely(ufence == NULL)) {
+ ret = -ENOMEM;
+ goto out_no_object;
+ }
+
+ ret = vmw_fence_obj_init(fman, &ufence->fence, seqno,
+ mask, vmw_user_fence_destroy);
+ if (unlikely(ret != 0)) {
+ kfree(ufence);
+ goto out_no_object;
+ }
+
+ /*
+ * The base object holds a reference which is freed in
+ * vmw_user_fence_base_release.
+ */
+ tmp = vmw_fence_obj_reference(&ufence->fence);
+ ret = ttm_base_object_init(tfile, &ufence->base, false,
+ VMW_RES_FENCE,
+ &vmw_user_fence_base_release, NULL);
- spin_lock(&queue->lock);
- getrawmonotonic(&now);
- queue->lag = vmw_timespec_add(queue->lag,
- timespec_sub(now, queue->lag_time));
- queue->lag_time = now;
- spin_unlock(&queue->lock);
- return queue->lag;
+
+ if (unlikely(ret != 0)) {
+ /*
+ * Free the base object's reference
+ */
+ vmw_fence_obj_unreference(&tmp);
+ goto out_err;
+ }
+
+ *p_fence = &ufence->fence;
+ *p_handle = ufence->base.hash.key;
+
+ return 0;
+out_err:
+ tmp = &ufence->fence;
+ vmw_fence_obj_unreference(&tmp);
+out_no_object:
+ ttm_mem_global_free(mem_glob, fman->user_fence_size);
+ return ret;
}
-static bool vmw_lag_lt(struct vmw_fence_queue *queue,
- uint32_t us)
+/**
+ * vmw_fence_fifo_down - signal all unsignaled fence objects.
+ */
+
+void vmw_fence_fifo_down(struct vmw_fence_manager *fman)
+{
+ unsigned long irq_flags;
+ struct list_head action_list;
+ int ret;
+
+ /*
+ * The list may be altered while we traverse it, so always
+ * restart when we've released the fman->lock.
+ */
+
+ spin_lock_irqsave(&fman->lock, irq_flags);
+ fman->fifo_down = true;
+ while (!list_empty(&fman->fence_list)) {
+ struct vmw_fence_obj *fence =
+ list_entry(fman->fence_list.prev, struct vmw_fence_obj,
+ head);
+ kref_get(&fence->kref);
+ spin_unlock_irq(&fman->lock);
+
+ ret = vmw_fence_obj_wait(fence, fence->signal_mask,
+ false, false,
+ VMW_FENCE_WAIT_TIMEOUT);
+
+ if (unlikely(ret != 0)) {
+ list_del_init(&fence->head);
+ fence->signaled |= DRM_VMW_FENCE_FLAG_EXEC;
+ INIT_LIST_HEAD(&action_list);
+ list_splice_init(&fence->seq_passed_actions,
+ &action_list);
+ vmw_fences_perform_actions(fman, &action_list);
+ wake_up_all(&fence->queue);
+ }
+
+ spin_lock_irq(&fman->lock);
+
+ BUG_ON(!list_empty(&fence->head));
+ kref_put(&fence->kref, vmw_fence_obj_destroy_locked);
+ }
+ spin_unlock_irqrestore(&fman->lock, irq_flags);
+}
+
+void vmw_fence_fifo_up(struct vmw_fence_manager *fman)
{
- struct timespec lag, cond;
+ unsigned long irq_flags;
- cond = ns_to_timespec((s64) us * 1000);
- lag = vmw_fifo_lag(queue);
- return (timespec_compare(&lag, &cond) < 1);
+ spin_lock_irqsave(&fman->lock, irq_flags);
+ fman->fifo_down = false;
+ spin_unlock_irqrestore(&fman->lock, irq_flags);
}
-int vmw_wait_lag(struct vmw_private *dev_priv,
- struct vmw_fence_queue *queue, uint32_t us)
+
+int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
- struct vmw_fence *fence;
- uint32_t sequence;
+ struct drm_vmw_fence_wait_arg *arg =
+ (struct drm_vmw_fence_wait_arg *)data;
+ unsigned long timeout;
+ struct ttm_base_object *base;
+ struct vmw_fence_obj *fence;
+ struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
int ret;
+ uint64_t wait_timeout = ((uint64_t)arg->timeout_us * HZ);
+
+ /*
+ * 64-bit division not present on 32-bit systems, so do an
+ * approximation. (Divide by 1000000).
+ */
+
+ wait_timeout = (wait_timeout >> 20) + (wait_timeout >> 24) -
+ (wait_timeout >> 26);
+
+ if (!arg->cookie_valid) {
+ arg->cookie_valid = 1;
+ arg->kernel_cookie = jiffies + wait_timeout;
+ }
+
+ base = ttm_base_object_lookup(tfile, arg->handle);
+ if (unlikely(base == NULL)) {
+ printk(KERN_ERR "Wait invalid fence object handle "
+ "0x%08lx.\n",
+ (unsigned long)arg->handle);
+ return -EINVAL;
+ }
+
+ fence = &(container_of(base, struct vmw_user_fence, base)->fence);
+
+ timeout = jiffies;
+ if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie)) {
+ ret = ((vmw_fence_obj_signaled(fence, arg->flags)) ?
+ 0 : -EBUSY);
+ goto out;
+ }
+
+ timeout = (unsigned long)arg->kernel_cookie - timeout;
+
+ ret = vmw_fence_obj_wait(fence, arg->flags, arg->lazy, true, timeout);
+
+out:
+ ttm_base_object_unref(&base);
+
+ /*
+ * Optionally unref the fence object.
+ */
+
+ if (ret == 0 && (arg->wait_options & DRM_VMW_WAIT_OPTION_UNREF))
+ return ttm_ref_object_base_unref(tfile, arg->handle,
+ TTM_REF_USAGE);
+ return ret;
+}
+
+int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_vmw_fence_signaled_arg *arg =
+ (struct drm_vmw_fence_signaled_arg *) data;
+ struct ttm_base_object *base;
+ struct vmw_fence_obj *fence;
+ struct vmw_fence_manager *fman;
+ struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+ struct vmw_private *dev_priv = vmw_priv(dev);
+
+ base = ttm_base_object_lookup(tfile, arg->handle);
+ if (unlikely(base == NULL)) {
+ printk(KERN_ERR "Fence signaled invalid fence object handle "
+ "0x%08lx.\n",
+ (unsigned long)arg->handle);
+ return -EINVAL;
+ }
+
+ fence = &(container_of(base, struct vmw_user_fence, base)->fence);
+ fman = fence->fman;
+
+ arg->signaled = vmw_fence_obj_signaled(fence, arg->flags);
+ spin_lock_irq(&fman->lock);
+
+ arg->signaled_flags = fence->signaled;
+ arg->passed_seqno = dev_priv->last_read_seqno;
+ spin_unlock_irq(&fman->lock);
+
+ ttm_base_object_unref(&base);
+
+ return 0;
+}
+
+
+int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_vmw_fence_arg *arg =
+ (struct drm_vmw_fence_arg *) data;
+
+ return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+ arg->handle,
+ TTM_REF_USAGE);
+}
+
+/**
+ * vmw_event_fence_action_destroy
+ *
+ * @kref: The struct kref embedded in a struct vmw_event_fence_action.
+ *
+ * The vmw_event_fence_action destructor that may be called either after
+ * the fence action cleanup, or when the event is delivered.
+ * It frees both the vmw_event_fence_action struct and the actual
+ * event structure copied to user-space.
+ */
+static void vmw_event_fence_action_destroy(struct kref *kref)
+{
+ struct vmw_event_fence_action *eaction =
+ container_of(kref, struct vmw_event_fence_action, kref);
+ struct ttm_mem_global *mem_glob =
+ vmw_mem_glob(vmw_priv(eaction->dev));
+ uint32_t size = eaction->size;
+
+ kfree(eaction->e.event);
+ kfree(eaction);
+ ttm_mem_global_free(mem_glob, size);
+}
+
+
+/**
+ * vmw_event_fence_action_delivered
+ *
+ * @e: The struct drm_pending_event embedded in a struct
+ * vmw_event_fence_action.
+ *
+ * The struct drm_pending_event destructor that is called by drm
+ * once the event is delivered. Since we don't know whether this function
+ * will be called before or after the fence action destructor, we
+ * free a refcount and destroy if it becomes zero.
+ */
+static void vmw_event_fence_action_delivered(struct drm_pending_event *e)
+{
+ struct vmw_event_fence_action *eaction =
+ container_of(e, struct vmw_event_fence_action, e);
+
+ kref_put(&eaction->kref, vmw_event_fence_action_destroy);
+}
+
+
+/**
+ * vmw_event_fence_action_seq_passed
+ *
+ * @action: The struct vmw_fence_action embedded in a struct
+ * vmw_event_fence_action.
+ *
+ * This function is called when the seqno of the fence where @action is
+ * attached has passed. It queues the event on the submitter's event list.
+ * This function is always called from atomic context, and may be called
+ * from irq context. It ups a refcount reflecting that we now have two
+ * destructors.
+ */
+static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action)
+{
+ struct vmw_event_fence_action *eaction =
+ container_of(action, struct vmw_event_fence_action, action);
+ struct drm_device *dev = eaction->dev;
+ struct drm_file *file_priv = eaction->e.file_priv;
+ unsigned long irq_flags;
+
+ kref_get(&eaction->kref);
+ spin_lock_irqsave(&dev->event_lock, irq_flags);
+
+ if (likely(eaction->tv_sec != NULL)) {
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+ *eaction->tv_sec = tv.tv_sec;
+ *eaction->tv_usec = tv.tv_usec;
+ }
+
+ list_add_tail(&eaction->e.link, &file_priv->event_list);
+ wake_up_all(&file_priv->event_wait);
+ spin_unlock_irqrestore(&dev->event_lock, irq_flags);
+}
+
+/**
+ * vmw_event_fence_action_cleanup
+ *
+ * @action: The struct vmw_fence_action embedded in a struct
+ * vmw_event_fence_action.
+ *
+ * This function is the struct vmw_fence_action destructor. It's typically
+ * called from a workqueue.
+ */
+static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action)
+{
+ struct vmw_event_fence_action *eaction =
+ container_of(action, struct vmw_event_fence_action, action);
+
+ vmw_fence_obj_unreference(&eaction->fence);
+ kref_put(&eaction->kref, vmw_event_fence_action_destroy);
+}
+
+
+/**
+ * vmw_fence_obj_add_action - Add an action to a fence object.
+ *
+ * @fence - The fence object.
+ * @action - The action to add.
+ *
+ * Note that the action callbacks may be executed before this function
+ * returns.
+ */
+void vmw_fence_obj_add_action(struct vmw_fence_obj *fence,
+ struct vmw_fence_action *action)
+{
+ struct vmw_fence_manager *fman = fence->fman;
+ unsigned long irq_flags;
+ bool run_update = false;
+
+ mutex_lock(&fman->goal_irq_mutex);
+ spin_lock_irqsave(&fman->lock, irq_flags);
+
+ fman->pending_actions[action->type]++;
+ if (fence->signaled & DRM_VMW_FENCE_FLAG_EXEC) {
+ struct list_head action_list;
- while (!vmw_lag_lt(queue, us)) {
- spin_lock(&queue->lock);
- if (list_empty(&queue->head))
- sequence = atomic_read(&dev_priv->fence_seq);
- else {
- fence = list_first_entry(&queue->head,
- struct vmw_fence, head);
- sequence = fence->sequence;
+ INIT_LIST_HEAD(&action_list);
+ list_add_tail(&action->head, &action_list);
+ vmw_fences_perform_actions(fman, &action_list);
+ } else {
+ list_add_tail(&action->head, &fence->seq_passed_actions);
+
+ /*
+ * This function may set fman::seqno_valid, so it must
+ * be run with the goal_irq_mutex held.
+ */
+ run_update = vmw_fence_goal_check_locked(fence);
+ }
+
+ spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+ if (run_update) {
+ if (!fman->goal_irq_on) {
+ fman->goal_irq_on = true;
+ vmw_goal_waiter_add(fman->dev_priv);
}
- spin_unlock(&queue->lock);
+ vmw_fences_update(fman);
+ }
+ mutex_unlock(&fman->goal_irq_mutex);
- ret = vmw_wait_fence(dev_priv, false, sequence, true,
- 3*HZ);
+}
- if (unlikely(ret != 0))
- return ret;
+/**
+ * vmw_event_fence_action_create - Post an event for sending when a fence
+ * object seqno has passed.
+ *
+ * @file_priv: The file connection on which the event should be posted.
+ * @fence: The fence object on which to post the event.
+ * @event: Event to be posted. This event should've been alloced
+ * using k[mz]alloc, and should've been completely initialized.
+ * @interruptible: Interruptible waits if possible.
+ *
+ * As a side effect, the object pointed to by @event may have been
+ * freed when this function returns. If this function returns with
+ * an error code, the caller needs to free that object.
+ */
+
+int vmw_event_fence_action_create(struct drm_file *file_priv,
+ struct vmw_fence_obj *fence,
+ struct drm_event *event,
+ uint32_t *tv_sec,
+ uint32_t *tv_usec,
+ bool interruptible)
+{
+ struct vmw_event_fence_action *eaction;
+ struct ttm_mem_global *mem_glob =
+ vmw_mem_glob(fence->fman->dev_priv);
+ struct vmw_fence_manager *fman = fence->fman;
+ uint32_t size = fman->event_fence_action_size +
+ ttm_round_pot(event->length);
+ int ret;
+
+ /*
+ * Account for internal structure size as well as the
+ * event size itself.
+ */
+
+ ret = ttm_mem_global_alloc(mem_glob, size, false, interruptible);
+ if (unlikely(ret != 0))
+ return ret;
- (void) vmw_fence_pull(queue, sequence);
+ eaction = kzalloc(sizeof(*eaction), GFP_KERNEL);
+ if (unlikely(eaction == NULL)) {
+ ttm_mem_global_free(mem_glob, size);
+ return -ENOMEM;
}
+
+ eaction->e.event = event;
+ eaction->e.file_priv = file_priv;
+ eaction->e.destroy = vmw_event_fence_action_delivered;
+
+ eaction->action.seq_passed = vmw_event_fence_action_seq_passed;
+ eaction->action.cleanup = vmw_event_fence_action_cleanup;
+ eaction->action.type = VMW_ACTION_EVENT;
+
+ eaction->fence = vmw_fence_obj_reference(fence);
+ eaction->dev = fman->dev_priv->dev;
+ eaction->size = size;
+ eaction->tv_sec = tv_sec;
+ eaction->tv_usec = tv_usec;
+
+ kref_init(&eaction->kref);
+ vmw_fence_obj_add_action(fence, &eaction->action);
+
return 0;
}
+int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct vmw_private *dev_priv = vmw_priv(dev);
+ struct drm_vmw_fence_event_arg *arg =
+ (struct drm_vmw_fence_event_arg *) data;
+ struct vmw_fence_obj *fence = NULL;
+ struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
+ struct drm_vmw_fence_rep __user *user_fence_rep =
+ (struct drm_vmw_fence_rep __user *)(unsigned long)
+ arg->fence_rep;
+ uint32_t handle;
+ unsigned long irq_flags;
+ struct drm_vmw_event_fence *event;
+ int ret;
+
+ /*
+ * Look up an existing fence object,
+ * and if user-space wants a new reference,
+ * add one.
+ */
+ if (arg->handle) {
+ struct ttm_base_object *base =
+ ttm_base_object_lookup(vmw_fp->tfile, arg->handle);
+ if (unlikely(base == NULL)) {
+ DRM_ERROR("Fence event invalid fence object handle "
+ "0x%08lx.\n",
+ (unsigned long)arg->handle);
+ return -EINVAL;
+ }
+ fence = &(container_of(base, struct vmw_user_fence,
+ base)->fence);
+ (void) vmw_fence_obj_reference(fence);
+
+ if (user_fence_rep != NULL) {
+ bool existed;
+
+ ret = ttm_ref_object_add(vmw_fp->tfile, base,
+ TTM_REF_USAGE, &existed);
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("Failed to reference a fence "
+ "object.\n");
+ goto out_no_ref_obj;
+ }
+ handle = base->hash.key;
+ }
+ ttm_base_object_unref(&base);
+ }
+
+ /*
+ * Create a new fence object.
+ */
+ if (!fence) {
+ ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
+ &fence,
+ (user_fence_rep) ?
+ &handle : NULL);
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("Fence event failed to create fence.\n");
+ return ret;
+ }
+ }
+
+ BUG_ON(fence == NULL);
+
+ spin_lock_irqsave(&dev->event_lock, irq_flags);
+
+ ret = (file_priv->event_space < sizeof(*event)) ? -EBUSY : 0;
+ if (likely(ret == 0))
+ file_priv->event_space -= sizeof(*event);
+
+ spin_unlock_irqrestore(&dev->event_lock, irq_flags);
+
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("Failed to allocate event space for this file.\n");
+ goto out_no_event_space;
+ }
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (unlikely(event == NULL)) {
+ DRM_ERROR("Failed to allocate an event.\n");
+ goto out_no_event;
+ }
+
+ event->base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
+ event->base.length = sizeof(*event);
+ event->user_data = arg->user_data;
+
+ if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME)
+ ret = vmw_event_fence_action_create(file_priv, fence,
+ &event->base,
+ &event->tv_sec,
+ &event->tv_usec,
+ true);
+ else
+ ret = vmw_event_fence_action_create(file_priv, fence,
+ &event->base,
+ NULL,
+ NULL,
+ true);
+
+ if (unlikely(ret != 0)) {
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("Failed to attach event to fence.\n");
+ goto out_no_attach;
+ }
+
+ vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence,
+ handle);
+ vmw_fence_obj_unreference(&fence);
+ return 0;
+out_no_attach:
+ kfree(event);
+out_no_event:
+ spin_lock_irqsave(&dev->event_lock, irq_flags);
+ file_priv->event_space += sizeof(*event);
+ spin_unlock_irqrestore(&dev->event_lock, irq_flags);
+out_no_event_space:
+ if (user_fence_rep != NULL)
+ ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+ handle, TTM_REF_USAGE);
+out_no_ref_obj:
+ vmw_fence_obj_unreference(&fence);
+ return ret;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
new file mode 100644
index 000000000000..0854a2096b55
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
@@ -0,0 +1,113 @@
+/**************************************************************************
+ *
+ * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _VMWGFX_FENCE_H_
+
+#define VMW_FENCE_WAIT_TIMEOUT (5*HZ)
+
+struct vmw_private;
+
+struct vmw_fence_manager;
+
+/**
+ *
+ *
+ */
+enum vmw_action_type {
+ VMW_ACTION_EVENT = 0,
+ VMW_ACTION_MAX
+};
+
+struct vmw_fence_action {
+ struct list_head head;
+ enum vmw_action_type type;
+ void (*seq_passed) (struct vmw_fence_action *action);
+ void (*cleanup) (struct vmw_fence_action *action);
+};
+
+struct vmw_fence_obj {
+ struct kref kref;
+ u32 seqno;
+
+ struct vmw_fence_manager *fman;
+ struct list_head head;
+ uint32_t signaled;
+ uint32_t signal_mask;
+ struct list_head seq_passed_actions;
+ void (*destroy)(struct vmw_fence_obj *fence);
+ wait_queue_head_t queue;
+};
+
+extern struct vmw_fence_manager *
+vmw_fence_manager_init(struct vmw_private *dev_priv);
+
+extern void vmw_fence_manager_takedown(struct vmw_fence_manager *fman);
+
+extern void vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p);
+
+extern struct vmw_fence_obj *
+vmw_fence_obj_reference(struct vmw_fence_obj *fence);
+
+extern void vmw_fences_update(struct vmw_fence_manager *fman);
+
+extern bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence,
+ uint32_t flags);
+
+extern int vmw_fence_obj_wait(struct vmw_fence_obj *fence, uint32_t flags,
+ bool lazy,
+ bool interruptible, unsigned long timeout);
+
+extern void vmw_fence_obj_flush(struct vmw_fence_obj *fence);
+
+extern int vmw_fence_create(struct vmw_fence_manager *fman,
+ uint32_t seqno,
+ uint32_t mask,
+ struct vmw_fence_obj **p_fence);
+
+extern int vmw_user_fence_create(struct drm_file *file_priv,
+ struct vmw_fence_manager *fman,
+ uint32_t sequence,
+ uint32_t mask,
+ struct vmw_fence_obj **p_fence,
+ uint32_t *p_handle);
+
+extern void vmw_fence_fifo_up(struct vmw_fence_manager *fman);
+
+extern void vmw_fence_fifo_down(struct vmw_fence_manager *fman);
+
+extern int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+extern int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+extern int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+#endif /* _VMWGFX_FENCE_H_ */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index 635c0ffee7fe..03bbc2a6f9a7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -45,7 +45,11 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
if (hwversion == 0)
return false;
- if (hwversion < SVGA3D_HWVERSION_WS65_B1)
+ if (hwversion < SVGA3D_HWVERSION_WS8_B1)
+ return false;
+
+ /* Non-Screen Object path does not support surfaces */
+ if (!dev_priv->sou_priv)
return false;
return true;
@@ -72,22 +76,12 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
uint32_t max;
uint32_t min;
uint32_t dummy;
- int ret;
fifo->static_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
fifo->static_buffer = vmalloc(fifo->static_buffer_size);
if (unlikely(fifo->static_buffer == NULL))
return -ENOMEM;
- fifo->last_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
- fifo->last_data_size = 0;
- fifo->last_buffer_add = false;
- fifo->last_buffer = vmalloc(fifo->last_buffer_size);
- if (unlikely(fifo->last_buffer == NULL)) {
- ret = -ENOMEM;
- goto out_err;
- }
-
fifo->dynamic_buffer = NULL;
fifo->reserved_size = 0;
fifo->using_bounce_buffer = false;
@@ -137,14 +131,10 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
(unsigned int) min,
(unsigned int) fifo->capabilities);
- atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
- iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
- vmw_fence_queue_init(&fifo->fence_queue);
+ atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno);
+ iowrite32(dev_priv->last_read_seqno, fifo_mem + SVGA_FIFO_FENCE);
+ vmw_marker_queue_init(&fifo->marker_queue);
return vmw_fifo_send_fence(dev_priv, &dummy);
-out_err:
- vfree(fifo->static_buffer);
- fifo->static_buffer = NULL;
- return ret;
}
void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
@@ -170,7 +160,7 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
- dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+ dev_priv->last_read_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
vmw_write(dev_priv, SVGA_REG_CONFIG_DONE,
dev_priv->config_done_state);
@@ -180,12 +170,7 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
dev_priv->traces_state);
mutex_unlock(&dev_priv->hw_mutex);
- vmw_fence_queue_takedown(&fifo->fence_queue);
-
- if (likely(fifo->last_buffer != NULL)) {
- vfree(fifo->last_buffer);
- fifo->last_buffer = NULL;
- }
+ vmw_marker_queue_takedown(&fifo->marker_queue);
if (likely(fifo->static_buffer != NULL)) {
vfree(fifo->static_buffer);
@@ -262,9 +247,8 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv,
spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
outl(SVGA_IRQFLAG_FIFO_PROGRESS,
dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- vmw_write(dev_priv, SVGA_REG_IRQMASK,
- vmw_read(dev_priv, SVGA_REG_IRQMASK) |
- SVGA_IRQFLAG_FIFO_PROGRESS);
+ dev_priv->irq_mask |= SVGA_IRQFLAG_FIFO_PROGRESS;
+ vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
}
mutex_unlock(&dev_priv->hw_mutex);
@@ -286,9 +270,8 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv,
mutex_lock(&dev_priv->hw_mutex);
if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) {
spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- vmw_write(dev_priv, SVGA_REG_IRQMASK,
- vmw_read(dev_priv, SVGA_REG_IRQMASK) &
- ~SVGA_IRQFLAG_FIFO_PROGRESS);
+ dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS;
+ vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
}
mutex_unlock(&dev_priv->hw_mutex);
@@ -296,6 +279,16 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv,
return ret;
}
+/**
+ * Reserve @bytes number of bytes in the fifo.
+ *
+ * This function will return NULL (error) on two conditions:
+ * If it timeouts waiting for fifo space, or if @bytes is larger than the
+ * available fifo space.
+ *
+ * Returns:
+ * Pointer to the fifo, or null on error (possible hardware hang).
+ */
void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes)
{
struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
@@ -466,7 +459,7 @@ void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes)
mutex_unlock(&fifo_state->fifo_mutex);
}
-int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
+int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
{
struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
struct svga_fifo_cmd_fence *cmd_fence;
@@ -476,16 +469,16 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
fm = vmw_fifo_reserve(dev_priv, bytes);
if (unlikely(fm == NULL)) {
- *sequence = atomic_read(&dev_priv->fence_seq);
+ *seqno = atomic_read(&dev_priv->marker_seq);
ret = -ENOMEM;
- (void)vmw_fallback_wait(dev_priv, false, true, *sequence,
+ (void)vmw_fallback_wait(dev_priv, false, true, *seqno,
false, 3*HZ);
goto out_err;
}
do {
- *sequence = atomic_add_return(1, &dev_priv->fence_seq);
- } while (*sequence == 0);
+ *seqno = atomic_add_return(1, &dev_priv->marker_seq);
+ } while (*seqno == 0);
if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) {
@@ -502,61 +495,68 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
cmd_fence = (struct svga_fifo_cmd_fence *)
((unsigned long)fm + sizeof(__le32));
- iowrite32(*sequence, &cmd_fence->fence);
- fifo_state->last_buffer_add = true;
+ iowrite32(*seqno, &cmd_fence->fence);
vmw_fifo_commit(dev_priv, bytes);
- fifo_state->last_buffer_add = false;
- (void) vmw_fence_push(&fifo_state->fence_queue, *sequence);
- vmw_update_sequence(dev_priv, fifo_state);
+ (void) vmw_marker_push(&fifo_state->marker_queue, *seqno);
+ vmw_update_seqno(dev_priv, fifo_state);
out_err:
return ret;
}
/**
- * Map the first page of the FIFO read-only to user-space.
+ * vmw_fifo_emit_dummy_query - emits a dummy query to the fifo.
+ *
+ * @dev_priv: The device private structure.
+ * @cid: The hardware context id used for the query.
+ *
+ * This function is used to emit a dummy occlusion query with
+ * no primitives rendered between query begin and query end.
+ * It's used to provide a query barrier, in order to know that when
+ * this query is finished, all preceding queries are also finished.
+ *
+ * A Query results structure should have been initialized at the start
+ * of the dev_priv->dummy_query_bo buffer object. And that buffer object
+ * must also be either reserved or pinned when this function is called.
+ *
+ * Returns -ENOMEM on failure to reserve fifo space.
*/
-
-static int vmw_fifo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
+ uint32_t cid)
{
- int ret;
- unsigned long address = (unsigned long)vmf->virtual_address;
+ /*
+ * A query wait without a preceding query end will
+ * actually finish all queries for this cid
+ * without writing to the query result structure.
+ */
- if (address != vma->vm_start)
- return VM_FAULT_SIGBUS;
+ struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
+ struct {
+ SVGA3dCmdHeader header;
+ SVGA3dCmdWaitForQuery body;
+ } *cmd;
- ret = vm_insert_pfn(vma, address, vma->vm_pgoff);
- if (likely(ret == -EBUSY || ret == 0))
- return VM_FAULT_NOPAGE;
- else if (ret == -ENOMEM)
- return VM_FAULT_OOM;
+ cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
- return VM_FAULT_SIGBUS;
-}
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("Out of fifo space for dummy query.\n");
+ return -ENOMEM;
+ }
-static struct vm_operations_struct vmw_fifo_vm_ops = {
- .fault = vmw_fifo_vm_fault,
- .open = NULL,
- .close = NULL
-};
+ cmd->header.id = SVGA_3D_CMD_WAIT_FOR_QUERY;
+ cmd->header.size = sizeof(cmd->body);
+ cmd->body.cid = cid;
+ cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION;
+
+ if (bo->mem.mem_type == TTM_PL_VRAM) {
+ cmd->body.guestResult.gmrId = SVGA_GMR_FRAMEBUFFER;
+ cmd->body.guestResult.offset = bo->offset;
+ } else {
+ cmd->body.guestResult.gmrId = bo->mem.start;
+ cmd->body.guestResult.offset = 0;
+ }
+
+ vmw_fifo_commit(dev_priv, sizeof(*cmd));
-int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct drm_file *file_priv;
- struct vmw_private *dev_priv;
-
- file_priv = filp->private_data;
- dev_priv = vmw_priv(file_priv->minor->dev);
-
- if (vma->vm_pgoff != (dev_priv->mmio_start >> PAGE_SHIFT) ||
- (vma->vm_end - vma->vm_start) != PAGE_SIZE)
- return -EINVAL;
-
- vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
- vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_SHARED;
- vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
- vma->vm_page_prot = ttm_io_prot(TTM_PL_FLAG_UNCACHED,
- vma->vm_page_prot);
- vma->vm_ops = &vmw_fifo_vm_ops;
return 0;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
index de0c5948521d..f4e7763a7694 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * Copyright © 2009-2011 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -29,6 +29,77 @@
#include "drmP.h"
#include "ttm/ttm_bo_driver.h"
+#define VMW_PPN_SIZE sizeof(unsigned long)
+
+static int vmw_gmr2_bind(struct vmw_private *dev_priv,
+ struct page *pages[],
+ unsigned long num_pages,
+ int gmr_id)
+{
+ SVGAFifoCmdDefineGMR2 define_cmd;
+ SVGAFifoCmdRemapGMR2 remap_cmd;
+ uint32_t define_size = sizeof(define_cmd) + 4;
+ uint32_t remap_size = VMW_PPN_SIZE * num_pages + sizeof(remap_cmd) + 4;
+ uint32_t *cmd;
+ uint32_t *cmd_orig;
+ uint32_t i;
+
+ cmd_orig = cmd = vmw_fifo_reserve(dev_priv, define_size + remap_size);
+ if (unlikely(cmd == NULL))
+ return -ENOMEM;
+
+ define_cmd.gmrId = gmr_id;
+ define_cmd.numPages = num_pages;
+
+ remap_cmd.gmrId = gmr_id;
+ remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
+ SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
+ remap_cmd.offsetPages = 0;
+ remap_cmd.numPages = num_pages;
+
+ *cmd++ = SVGA_CMD_DEFINE_GMR2;
+ memcpy(cmd, &define_cmd, sizeof(define_cmd));
+ cmd += sizeof(define_cmd) / sizeof(uint32);
+
+ *cmd++ = SVGA_CMD_REMAP_GMR2;
+ memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
+ cmd += sizeof(remap_cmd) / sizeof(uint32);
+
+ for (i = 0; i < num_pages; ++i) {
+ if (VMW_PPN_SIZE > 4)
+ *cmd = page_to_pfn(*pages++);
+ else
+ *((uint64_t *)cmd) = page_to_pfn(*pages++);
+
+ cmd += VMW_PPN_SIZE / sizeof(*cmd);
+ }
+
+ vmw_fifo_commit(dev_priv, define_size + remap_size);
+
+ return 0;
+}
+
+static void vmw_gmr2_unbind(struct vmw_private *dev_priv,
+ int gmr_id)
+{
+ SVGAFifoCmdDefineGMR2 define_cmd;
+ uint32_t define_size = sizeof(define_cmd) + 4;
+ uint32_t *cmd;
+
+ cmd = vmw_fifo_reserve(dev_priv, define_size);
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("GMR2 unbind failed.\n");
+ return;
+ }
+ define_cmd.gmrId = gmr_id;
+ define_cmd.numPages = 0;
+
+ *cmd++ = SVGA_CMD_DEFINE_GMR2;
+ memcpy(cmd, &define_cmd, sizeof(define_cmd));
+
+ vmw_fifo_commit(dev_priv, define_size);
+}
+
/**
* FIXME: Adjust to the ttm lowmem / highmem storage to minimize
* the number of used descriptors.
@@ -170,6 +241,9 @@ int vmw_gmr_bind(struct vmw_private *dev_priv,
struct list_head desc_pages;
int ret;
+ if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
+ return vmw_gmr2_bind(dev_priv, pages, num_pages, gmr_id);
+
if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR)))
return -EINVAL;
@@ -192,6 +266,11 @@ int vmw_gmr_bind(struct vmw_private *dev_priv,
void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
{
+ if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) {
+ vmw_gmr2_unbind(dev_priv, gmr_id);
+ return;
+ }
+
mutex_lock(&dev_priv->hw_mutex);
vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
wmb();
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
index ac6e0d1bd629..5f717152cff5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
@@ -40,6 +40,8 @@ struct vmwgfx_gmrid_man {
spinlock_t lock;
struct ida gmr_ida;
uint32_t max_gmr_ids;
+ uint32_t max_gmr_pages;
+ uint32_t used_gmr_pages;
};
static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man,
@@ -49,33 +51,50 @@ static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man,
{
struct vmwgfx_gmrid_man *gman =
(struct vmwgfx_gmrid_man *)man->priv;
- int ret;
+ int ret = 0;
int id;
mem->mm_node = NULL;
- do {
- if (unlikely(ida_pre_get(&gman->gmr_ida, GFP_KERNEL) == 0))
- return -ENOMEM;
+ spin_lock(&gman->lock);
+
+ if (gman->max_gmr_pages > 0) {
+ gman->used_gmr_pages += bo->num_pages;
+ if (unlikely(gman->used_gmr_pages > gman->max_gmr_pages))
+ goto out_err_locked;
+ }
+ do {
+ spin_unlock(&gman->lock);
+ if (unlikely(ida_pre_get(&gman->gmr_ida, GFP_KERNEL) == 0)) {
+ ret = -ENOMEM;
+ goto out_err;
+ }
spin_lock(&gman->lock);
- ret = ida_get_new(&gman->gmr_ida, &id);
+ ret = ida_get_new(&gman->gmr_ida, &id);
if (unlikely(ret == 0 && id >= gman->max_gmr_ids)) {
ida_remove(&gman->gmr_ida, id);
- spin_unlock(&gman->lock);
- return 0;
+ ret = 0;
+ goto out_err_locked;
}
-
- spin_unlock(&gman->lock);
-
} while (ret == -EAGAIN);
if (likely(ret == 0)) {
mem->mm_node = gman;
mem->start = id;
- }
+ mem->num_pages = bo->num_pages;
+ } else
+ goto out_err_locked;
+
+ spin_unlock(&gman->lock);
+ return 0;
+out_err:
+ spin_lock(&gman->lock);
+out_err_locked:
+ gman->used_gmr_pages -= bo->num_pages;
+ spin_unlock(&gman->lock);
return ret;
}
@@ -88,6 +107,7 @@ static void vmw_gmrid_man_put_node(struct ttm_mem_type_manager *man,
if (mem->mm_node) {
spin_lock(&gman->lock);
ida_remove(&gman->gmr_ida, mem->start);
+ gman->used_gmr_pages -= mem->num_pages;
spin_unlock(&gman->lock);
mem->mm_node = NULL;
}
@@ -96,6 +116,8 @@ static void vmw_gmrid_man_put_node(struct ttm_mem_type_manager *man,
static int vmw_gmrid_man_init(struct ttm_mem_type_manager *man,
unsigned long p_size)
{
+ struct vmw_private *dev_priv =
+ container_of(man->bdev, struct vmw_private, bdev);
struct vmwgfx_gmrid_man *gman =
kzalloc(sizeof(*gman), GFP_KERNEL);
@@ -103,6 +125,8 @@ static int vmw_gmrid_man_init(struct ttm_mem_type_manager *man,
return -ENOMEM;
spin_lock_init(&gman->lock);
+ gman->max_gmr_pages = dev_priv->max_gmr_pages;
+ gman->used_gmr_pages = 0;
ida_init(&gman->gmr_ida);
gman->max_gmr_ids = p_size;
man->priv = (void *) gman;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 570d57775a58..3f6343502d1f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -27,6 +27,7 @@
#include "vmwgfx_drv.h"
#include "vmwgfx_drm.h"
+#include "vmwgfx_kms.h"
int vmw_getparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
@@ -45,9 +46,6 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
case DRM_VMW_PARAM_3D:
param->value = vmw_fifo_have_3d(dev_priv) ? 1 : 0;
break;
- case DRM_VMW_PARAM_FIFO_OFFSET:
- param->value = dev_priv->mmio_start;
- break;
case DRM_VMW_PARAM_HW_CAPS:
param->value = dev_priv->capabilities;
break;
@@ -57,6 +55,13 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
case DRM_VMW_PARAM_MAX_FB_SIZE:
param->value = dev_priv->vram_size;
break;
+ case DRM_VMW_PARAM_FIFO_HW_VERSION:
+ {
+ __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+
+ param->value = ioread32(fifo_mem + SVGA_FIFO_3D_HWVERSION);
+ break;
+ }
default:
DRM_ERROR("Illegal vmwgfx get param request: %d\n",
param->param);
@@ -66,25 +71,259 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
return 0;
}
-int vmw_fifo_debug_ioctl(struct drm_device *dev, void *data,
+
+int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ struct drm_vmw_get_3d_cap_arg *arg =
+ (struct drm_vmw_get_3d_cap_arg *) data;
struct vmw_private *dev_priv = vmw_priv(dev);
- struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
- struct drm_vmw_fifo_debug_arg *arg =
- (struct drm_vmw_fifo_debug_arg *)data;
- __le32 __user *buffer = (__le32 __user *)
- (unsigned long)arg->debug_buffer;
+ uint32_t size;
+ __le32 __iomem *fifo_mem;
+ void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
+ void *bounce;
+ int ret;
- if (unlikely(fifo_state->last_buffer == NULL))
+ if (unlikely(arg->pad64 != 0)) {
+ DRM_ERROR("Illegal GET_3D_CAP argument.\n");
return -EINVAL;
+ }
+
+ size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) << 2;
+
+ if (arg->max_size < size)
+ size = arg->max_size;
+
+ bounce = vmalloc(size);
+ if (unlikely(bounce == NULL)) {
+ DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n");
+ return -ENOMEM;
+ }
+
+ fifo_mem = dev_priv->mmio_virt;
+ memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
+
+ ret = copy_to_user(buffer, bounce, size);
+ vfree(bounce);
+
+ if (unlikely(ret != 0))
+ DRM_ERROR("Failed to report 3D caps info.\n");
+
+ return ret;
+}
+
+int vmw_present_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+ struct vmw_private *dev_priv = vmw_priv(dev);
+ struct drm_vmw_present_arg *arg =
+ (struct drm_vmw_present_arg *)data;
+ struct vmw_surface *surface;
+ struct vmw_master *vmaster = vmw_master(file_priv->master);
+ struct drm_vmw_rect __user *clips_ptr;
+ struct drm_vmw_rect *clips = NULL;
+ struct drm_mode_object *obj;
+ struct vmw_framebuffer *vfb;
+ uint32_t num_clips;
+ int ret;
+
+ num_clips = arg->num_clips;
+ clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr;
+
+ if (unlikely(num_clips == 0))
+ return 0;
+
+ if (clips_ptr == NULL) {
+ DRM_ERROR("Variable clips_ptr must be specified.\n");
+ ret = -EINVAL;
+ goto out_clips;
+ }
+
+ clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
+ if (clips == NULL) {
+ DRM_ERROR("Failed to allocate clip rect list.\n");
+ ret = -ENOMEM;
+ goto out_clips;
+ }
+
+ ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
+ if (ret) {
+ DRM_ERROR("Failed to copy clip rects from userspace.\n");
+ ret = -EFAULT;
+ goto out_no_copy;
+ }
+
+ ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+ if (unlikely(ret != 0)) {
+ ret = -ERESTARTSYS;
+ goto out_no_mode_mutex;
+ }
+
+ obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB);
+ if (!obj) {
+ DRM_ERROR("Invalid framebuffer id.\n");
+ ret = -EINVAL;
+ goto out_no_fb;
+ }
+
+ vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj));
+ if (!vfb->dmabuf) {
+ DRM_ERROR("Framebuffer not dmabuf backed.\n");
+ ret = -EINVAL;
+ goto out_no_fb;
+ }
+
+ ret = ttm_read_lock(&vmaster->lock, true);
+ if (unlikely(ret != 0))
+ goto out_no_ttm_lock;
+
+ ret = vmw_user_surface_lookup_handle(dev_priv, tfile, arg->sid,
+ &surface);
+ if (ret)
+ goto out_no_surface;
+
+ ret = vmw_kms_present(dev_priv, file_priv,
+ vfb, surface, arg->sid,
+ arg->dest_x, arg->dest_y,
+ clips, num_clips);
- if (arg->debug_buffer_size < fifo_state->last_data_size) {
- arg->used_size = arg->debug_buffer_size;
- arg->did_not_fit = 1;
- } else {
- arg->used_size = fifo_state->last_data_size;
- arg->did_not_fit = 0;
+ /* vmw_user_surface_lookup takes one ref so does new_fb */
+ vmw_surface_unreference(&surface);
+
+out_no_surface:
+ ttm_read_unlock(&vmaster->lock);
+out_no_ttm_lock:
+out_no_fb:
+ mutex_unlock(&dev->mode_config.mutex);
+out_no_mode_mutex:
+out_no_copy:
+ kfree(clips);
+out_clips:
+ return ret;
+}
+
+int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct vmw_private *dev_priv = vmw_priv(dev);
+ struct drm_vmw_present_readback_arg *arg =
+ (struct drm_vmw_present_readback_arg *)data;
+ struct drm_vmw_fence_rep __user *user_fence_rep =
+ (struct drm_vmw_fence_rep __user *)
+ (unsigned long)arg->fence_rep;
+ struct vmw_master *vmaster = vmw_master(file_priv->master);
+ struct drm_vmw_rect __user *clips_ptr;
+ struct drm_vmw_rect *clips = NULL;
+ struct drm_mode_object *obj;
+ struct vmw_framebuffer *vfb;
+ uint32_t num_clips;
+ int ret;
+
+ num_clips = arg->num_clips;
+ clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr;
+
+ if (unlikely(num_clips == 0))
+ return 0;
+
+ if (clips_ptr == NULL) {
+ DRM_ERROR("Argument clips_ptr must be specified.\n");
+ ret = -EINVAL;
+ goto out_clips;
+ }
+
+ clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
+ if (clips == NULL) {
+ DRM_ERROR("Failed to allocate clip rect list.\n");
+ ret = -ENOMEM;
+ goto out_clips;
+ }
+
+ ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
+ if (ret) {
+ DRM_ERROR("Failed to copy clip rects from userspace.\n");
+ ret = -EFAULT;
+ goto out_no_copy;
+ }
+
+ ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+ if (unlikely(ret != 0)) {
+ ret = -ERESTARTSYS;
+ goto out_no_mode_mutex;
+ }
+
+ obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB);
+ if (!obj) {
+ DRM_ERROR("Invalid framebuffer id.\n");
+ ret = -EINVAL;
+ goto out_no_fb;
+ }
+
+ vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj));
+ if (!vfb->dmabuf) {
+ DRM_ERROR("Framebuffer not dmabuf backed.\n");
+ ret = -EINVAL;
+ goto out_no_fb;
}
- return copy_to_user(buffer, fifo_state->last_buffer, arg->used_size);
+
+ ret = ttm_read_lock(&vmaster->lock, true);
+ if (unlikely(ret != 0))
+ goto out_no_ttm_lock;
+
+ ret = vmw_kms_readback(dev_priv, file_priv,
+ vfb, user_fence_rep,
+ clips, num_clips);
+
+ ttm_read_unlock(&vmaster->lock);
+out_no_ttm_lock:
+out_no_fb:
+ mutex_unlock(&dev->mode_config.mutex);
+out_no_mode_mutex:
+out_no_copy:
+ kfree(clips);
+out_clips:
+ return ret;
+}
+
+
+/**
+ * vmw_fops_poll - wrapper around the drm_poll function
+ *
+ * @filp: See the linux fops poll documentation.
+ * @wait: See the linux fops poll documentation.
+ *
+ * Wrapper around the drm_poll function that makes sure the device is
+ * processing the fifo if drm_poll decides to wait.
+ */
+unsigned int vmw_fops_poll(struct file *filp, struct poll_table_struct *wait)
+{
+ struct drm_file *file_priv = filp->private_data;
+ struct vmw_private *dev_priv =
+ vmw_priv(file_priv->minor->dev);
+
+ vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+ return drm_poll(filp, wait);
+}
+
+
+/**
+ * vmw_fops_read - wrapper around the drm_read function
+ *
+ * @filp: See the linux fops read documentation.
+ * @buffer: See the linux fops read documentation.
+ * @count: See the linux fops read documentation.
+ * offset: See the linux fops read documentation.
+ *
+ * Wrapper around the drm_read function that makes sure the device is
+ * processing the fifo if drm_read decides to wait.
+ */
+ssize_t vmw_fops_read(struct file *filp, char __user *buffer,
+ size_t count, loff_t *offset)
+{
+ struct drm_file *file_priv = filp->private_data;
+ struct vmw_private *dev_priv =
+ vmw_priv(file_priv->minor->dev);
+
+ vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+ return drm_read(filp, buffer, count, offset);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
index e92298a6a383..cabc95f7517e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
@@ -34,26 +34,33 @@ irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *)arg;
struct vmw_private *dev_priv = vmw_priv(dev);
- uint32_t status;
+ uint32_t status, masked_status;
spin_lock(&dev_priv->irq_lock);
status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+ masked_status = status & dev_priv->irq_mask;
spin_unlock(&dev_priv->irq_lock);
- if (status & SVGA_IRQFLAG_ANY_FENCE)
+ if (likely(status))
+ outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+
+ if (!masked_status)
+ return IRQ_NONE;
+
+ if (masked_status & (SVGA_IRQFLAG_ANY_FENCE |
+ SVGA_IRQFLAG_FENCE_GOAL)) {
+ vmw_fences_update(dev_priv->fman);
wake_up_all(&dev_priv->fence_queue);
- if (status & SVGA_IRQFLAG_FIFO_PROGRESS)
+ }
+
+ if (masked_status & SVGA_IRQFLAG_FIFO_PROGRESS)
wake_up_all(&dev_priv->fifo_queue);
- if (likely(status)) {
- outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- return IRQ_HANDLED;
- }
- return IRQ_NONE;
+ return IRQ_HANDLED;
}
-static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence)
+static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno)
{
uint32_t busy;
@@ -64,43 +71,43 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence)
return (busy == 0);
}
-void vmw_update_sequence(struct vmw_private *dev_priv,
+void vmw_update_seqno(struct vmw_private *dev_priv,
struct vmw_fifo_state *fifo_state)
{
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+ uint32_t seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
- uint32_t sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
-
- if (dev_priv->last_read_sequence != sequence) {
- dev_priv->last_read_sequence = sequence;
- vmw_fence_pull(&fifo_state->fence_queue, sequence);
+ if (dev_priv->last_read_seqno != seqno) {
+ dev_priv->last_read_seqno = seqno;
+ vmw_marker_pull(&fifo_state->marker_queue, seqno);
+ vmw_fences_update(dev_priv->fman);
}
}
-bool vmw_fence_signaled(struct vmw_private *dev_priv,
- uint32_t sequence)
+bool vmw_seqno_passed(struct vmw_private *dev_priv,
+ uint32_t seqno)
{
struct vmw_fifo_state *fifo_state;
bool ret;
- if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+ if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
return true;
fifo_state = &dev_priv->fifo;
- vmw_update_sequence(dev_priv, fifo_state);
- if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+ vmw_update_seqno(dev_priv, fifo_state);
+ if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
return true;
if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
- vmw_fifo_idle(dev_priv, sequence))
+ vmw_fifo_idle(dev_priv, seqno))
return true;
/**
- * Then check if the sequence is higher than what we've actually
+ * Then check if the seqno is higher than what we've actually
* emitted. Then the fence is stale and signaled.
*/
- ret = ((atomic_read(&dev_priv->fence_seq) - sequence)
+ ret = ((atomic_read(&dev_priv->marker_seq) - seqno)
> VMW_FENCE_WRAP);
return ret;
@@ -109,7 +116,7 @@ bool vmw_fence_signaled(struct vmw_private *dev_priv,
int vmw_fallback_wait(struct vmw_private *dev_priv,
bool lazy,
bool fifo_idle,
- uint32_t sequence,
+ uint32_t seqno,
bool interruptible,
unsigned long timeout)
{
@@ -123,7 +130,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
DEFINE_WAIT(__wait);
wait_condition = (fifo_idle) ? &vmw_fifo_idle :
- &vmw_fence_signaled;
+ &vmw_seqno_passed;
/**
* Block command submission while waiting for idle.
@@ -131,14 +138,14 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
if (fifo_idle)
down_read(&fifo_state->rwsem);
- signal_seq = atomic_read(&dev_priv->fence_seq);
+ signal_seq = atomic_read(&dev_priv->marker_seq);
ret = 0;
for (;;) {
prepare_to_wait(&dev_priv->fence_queue, &__wait,
(interruptible) ?
TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
- if (wait_condition(dev_priv, sequence))
+ if (wait_condition(dev_priv, seqno))
break;
if (time_after_eq(jiffies, end_jiffies)) {
DRM_ERROR("SVGA device lockup.\n");
@@ -175,68 +182,110 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
return ret;
}
-int vmw_wait_fence(struct vmw_private *dev_priv,
- bool lazy, uint32_t sequence,
- bool interruptible, unsigned long timeout)
+void vmw_seqno_waiter_add(struct vmw_private *dev_priv)
+{
+ mutex_lock(&dev_priv->hw_mutex);
+ if (dev_priv->fence_queue_waiters++ == 0) {
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+ outl(SVGA_IRQFLAG_ANY_FENCE,
+ dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+ dev_priv->irq_mask |= SVGA_IRQFLAG_ANY_FENCE;
+ vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+ }
+ mutex_unlock(&dev_priv->hw_mutex);
+}
+
+void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
+{
+ mutex_lock(&dev_priv->hw_mutex);
+ if (--dev_priv->fence_queue_waiters == 0) {
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+ dev_priv->irq_mask &= ~SVGA_IRQFLAG_ANY_FENCE;
+ vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+ }
+ mutex_unlock(&dev_priv->hw_mutex);
+}
+
+
+void vmw_goal_waiter_add(struct vmw_private *dev_priv)
+{
+ mutex_lock(&dev_priv->hw_mutex);
+ if (dev_priv->goal_queue_waiters++ == 0) {
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+ outl(SVGA_IRQFLAG_FENCE_GOAL,
+ dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+ dev_priv->irq_mask |= SVGA_IRQFLAG_FENCE_GOAL;
+ vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+ }
+ mutex_unlock(&dev_priv->hw_mutex);
+}
+
+void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
+{
+ mutex_lock(&dev_priv->hw_mutex);
+ if (--dev_priv->goal_queue_waiters == 0) {
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+ dev_priv->irq_mask &= ~SVGA_IRQFLAG_FENCE_GOAL;
+ vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+ }
+ mutex_unlock(&dev_priv->hw_mutex);
+}
+
+int vmw_wait_seqno(struct vmw_private *dev_priv,
+ bool lazy, uint32_t seqno,
+ bool interruptible, unsigned long timeout)
{
long ret;
- unsigned long irq_flags;
struct vmw_fifo_state *fifo = &dev_priv->fifo;
- if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+ if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
return 0;
- if (likely(vmw_fence_signaled(dev_priv, sequence)))
+ if (likely(vmw_seqno_passed(dev_priv, seqno)))
return 0;
vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE))
- return vmw_fallback_wait(dev_priv, lazy, true, sequence,
+ return vmw_fallback_wait(dev_priv, lazy, true, seqno,
interruptible, timeout);
if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
- return vmw_fallback_wait(dev_priv, lazy, false, sequence,
+ return vmw_fallback_wait(dev_priv, lazy, false, seqno,
interruptible, timeout);
- mutex_lock(&dev_priv->hw_mutex);
- if (atomic_add_return(1, &dev_priv->fence_queue_waiters) > 0) {
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- outl(SVGA_IRQFLAG_ANY_FENCE,
- dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- vmw_write(dev_priv, SVGA_REG_IRQMASK,
- vmw_read(dev_priv, SVGA_REG_IRQMASK) |
- SVGA_IRQFLAG_ANY_FENCE);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
- }
- mutex_unlock(&dev_priv->hw_mutex);
+ vmw_seqno_waiter_add(dev_priv);
if (interruptible)
ret = wait_event_interruptible_timeout
(dev_priv->fence_queue,
- vmw_fence_signaled(dev_priv, sequence),
+ vmw_seqno_passed(dev_priv, seqno),
timeout);
else
ret = wait_event_timeout
(dev_priv->fence_queue,
- vmw_fence_signaled(dev_priv, sequence),
+ vmw_seqno_passed(dev_priv, seqno),
timeout);
+ vmw_seqno_waiter_remove(dev_priv);
+
if (unlikely(ret == 0))
ret = -EBUSY;
else if (likely(ret > 0))
ret = 0;
- mutex_lock(&dev_priv->hw_mutex);
- if (atomic_dec_and_test(&dev_priv->fence_queue_waiters)) {
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- vmw_write(dev_priv, SVGA_REG_IRQMASK,
- vmw_read(dev_priv, SVGA_REG_IRQMASK) &
- ~SVGA_IRQFLAG_ANY_FENCE);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
- }
- mutex_unlock(&dev_priv->hw_mutex);
-
return ret;
}
@@ -273,25 +322,3 @@ void vmw_irq_uninstall(struct drm_device *dev)
status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
}
-
-#define VMW_FENCE_WAIT_TIMEOUT 3*HZ;
-
-int vmw_fence_wait_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_vmw_fence_wait_arg *arg =
- (struct drm_vmw_fence_wait_arg *)data;
- unsigned long timeout;
-
- if (!arg->cookie_valid) {
- arg->cookie_valid = 1;
- arg->kernel_cookie = jiffies + VMW_FENCE_WAIT_TIMEOUT;
- }
-
- timeout = jiffies;
- if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie))
- return -EBUSY;
-
- timeout = (unsigned long)arg->kernel_cookie - timeout;
- return vmw_wait_fence(vmw_priv(dev), true, arg->sequence, true, timeout);
-}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index dfe32e62bd90..8b14dfd513a1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -27,12 +27,10 @@
#include "vmwgfx_kms.h"
+
/* Might need a hrtimer here? */
#define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
-static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb);
-static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb);
-
void vmw_display_unit_cleanup(struct vmw_display_unit *du)
{
if (du->cursor_surface)
@@ -329,41 +327,10 @@ struct vmw_framebuffer_surface {
struct vmw_framebuffer base;
struct vmw_surface *surface;
struct vmw_dma_buffer *buffer;
- struct delayed_work d_work;
- struct mutex work_lock;
- bool present_fs;
struct list_head head;
struct drm_master *master;
};
-/**
- * vmw_kms_idle_workqueues - Flush workqueues on this master
- *
- * @vmaster - Pointer identifying the master, for the surfaces of which
- * we idle the dirty work queues.
- *
- * This function should be called with the ttm lock held in exclusive mode
- * to idle all dirty work queues before the fifo is taken down.
- *
- * The work task may actually requeue itself, but after the flush returns we're
- * sure that there's nothing to present, since the ttm lock is held in
- * exclusive mode, so the fifo will never get used.
- */
-
-void vmw_kms_idle_workqueues(struct vmw_master *vmaster)
-{
- struct vmw_framebuffer_surface *entry;
-
- mutex_lock(&vmaster->fb_surf_mutex);
- list_for_each_entry(entry, &vmaster->fb_surf, head) {
- if (cancel_delayed_work_sync(&entry->d_work))
- (void) entry->d_work.work.func(&entry->d_work.work);
-
- (void) cancel_delayed_work_sync(&entry->d_work);
- }
- mutex_unlock(&vmaster->fb_surf_mutex);
-}
-
void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
{
struct vmw_framebuffer_surface *vfbs =
@@ -375,64 +342,127 @@ void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
list_del(&vfbs->head);
mutex_unlock(&vmaster->fb_surf_mutex);
- cancel_delayed_work_sync(&vfbs->d_work);
drm_master_put(&vfbs->master);
drm_framebuffer_cleanup(framebuffer);
vmw_surface_unreference(&vfbs->surface);
+ ttm_base_object_unref(&vfbs->base.user_obj);
kfree(vfbs);
}
-static void vmw_framebuffer_present_fs_callback(struct work_struct *work)
+static int do_surface_dirty_sou(struct vmw_private *dev_priv,
+ struct drm_file *file_priv,
+ struct vmw_framebuffer *framebuffer,
+ unsigned flags, unsigned color,
+ struct drm_clip_rect *clips,
+ unsigned num_clips, int inc)
{
- struct delayed_work *d_work =
- container_of(work, struct delayed_work, work);
- struct vmw_framebuffer_surface *vfbs =
- container_of(d_work, struct vmw_framebuffer_surface, d_work);
- struct vmw_surface *surf = vfbs->surface;
- struct drm_framebuffer *framebuffer = &vfbs->base.base;
- struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+ struct drm_clip_rect *clips_ptr;
+ struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+ struct drm_crtc *crtc;
+ size_t fifo_size;
+ int i, num_units;
+ int ret = 0; /* silence warning */
+ int left, right, top, bottom;
struct {
SVGA3dCmdHeader header;
- SVGA3dCmdPresent body;
- SVGA3dCopyRect cr;
+ SVGA3dCmdBlitSurfaceToScreen body;
} *cmd;
+ SVGASignedRect *blits;
- /**
- * Strictly we should take the ttm_lock in read mode before accessing
- * the fifo, to make sure the fifo is present and up. However,
- * instead we flush all workqueues under the ttm lock in exclusive mode
- * before taking down the fifo.
- */
- mutex_lock(&vfbs->work_lock);
- if (!vfbs->present_fs)
- goto out_unlock;
-
- cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
- if (unlikely(cmd == NULL))
- goto out_resched;
-
- cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT);
- cmd->header.size = cpu_to_le32(sizeof(cmd->body) + sizeof(cmd->cr));
- cmd->body.sid = cpu_to_le32(surf->res.id);
- cmd->cr.x = cpu_to_le32(0);
- cmd->cr.y = cpu_to_le32(0);
- cmd->cr.srcx = cmd->cr.x;
- cmd->cr.srcy = cmd->cr.y;
- cmd->cr.w = cpu_to_le32(framebuffer->width);
- cmd->cr.h = cpu_to_le32(framebuffer->height);
- vfbs->present_fs = false;
- vmw_fifo_commit(dev_priv, sizeof(*cmd));
-out_resched:
- /**
- * Will not re-add if already pending.
- */
- schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE);
-out_unlock:
- mutex_unlock(&vfbs->work_lock);
-}
+ num_units = 0;
+ list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
+ head) {
+ if (crtc->fb != &framebuffer->base)
+ continue;
+ units[num_units++] = vmw_crtc_to_du(crtc);
+ }
+
+ BUG_ON(!clips || !num_clips);
+
+ fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips;
+ cmd = kzalloc(fifo_size, GFP_KERNEL);
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("Temporary fifo memory alloc failed.\n");
+ return -ENOMEM;
+ }
+
+ left = clips->x1;
+ right = clips->x2;
+ top = clips->y1;
+ bottom = clips->y2;
+
+ clips_ptr = clips;
+ for (i = 1; i < num_clips; i++, clips_ptr += inc) {
+ left = min_t(int, left, (int)clips_ptr->x1);
+ right = max_t(int, right, (int)clips_ptr->x2);
+ top = min_t(int, top, (int)clips_ptr->y1);
+ bottom = max_t(int, bottom, (int)clips_ptr->y2);
+ }
+
+ /* only need to do this once */
+ memset(cmd, 0, fifo_size);
+ cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
+ cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
+
+ cmd->body.srcRect.left = left;
+ cmd->body.srcRect.right = right;
+ cmd->body.srcRect.top = top;
+ cmd->body.srcRect.bottom = bottom;
+
+ clips_ptr = clips;
+ blits = (SVGASignedRect *)&cmd[1];
+ for (i = 0; i < num_clips; i++, clips_ptr += inc) {
+ blits[i].left = clips_ptr->x1 - left;
+ blits[i].right = clips_ptr->x2 - left;
+ blits[i].top = clips_ptr->y1 - top;
+ blits[i].bottom = clips_ptr->y2 - top;
+ }
+
+ /* do per unit writing, reuse fifo for each */
+ for (i = 0; i < num_units; i++) {
+ struct vmw_display_unit *unit = units[i];
+ int clip_x1 = left - unit->crtc.x;
+ int clip_y1 = top - unit->crtc.y;
+ int clip_x2 = right - unit->crtc.x;
+ int clip_y2 = bottom - unit->crtc.y;
+
+ /* skip any crtcs that misses the clip region */
+ if (clip_x1 >= unit->crtc.mode.hdisplay ||
+ clip_y1 >= unit->crtc.mode.vdisplay ||
+ clip_x2 <= 0 || clip_y2 <= 0)
+ continue;
+
+ /* need to reset sid as it is changed by execbuf */
+ cmd->body.srcImage.sid = cpu_to_le32(framebuffer->user_handle);
+
+ cmd->body.destScreenId = unit->unit;
+
+ /*
+ * The blit command is a lot more resilient then the
+ * readback command when it comes to clip rects. So its
+ * okay to go out of bounds.
+ */
+
+ cmd->body.destRect.left = clip_x1;
+ cmd->body.destRect.right = clip_x2;
+ cmd->body.destRect.top = clip_y1;
+ cmd->body.destRect.bottom = clip_y2;
+
+
+ ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
+ fifo_size, 0, NULL);
+
+ if (unlikely(ret != 0))
+ break;
+ }
+
+ kfree(cmd);
+
+ return ret;
+}
int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
struct drm_file *file_priv,
@@ -444,44 +474,20 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
struct vmw_master *vmaster = vmw_master(file_priv->master);
struct vmw_framebuffer_surface *vfbs =
vmw_framebuffer_to_vfbs(framebuffer);
- struct vmw_surface *surf = vfbs->surface;
struct drm_clip_rect norect;
- SVGA3dCopyRect *cr;
- int i, inc = 1;
- int ret;
-
- struct {
- SVGA3dCmdHeader header;
- SVGA3dCmdPresent body;
- SVGA3dCopyRect cr;
- } *cmd;
+ int ret, inc = 1;
if (unlikely(vfbs->master != file_priv->master))
return -EINVAL;
+ /* Require ScreenObject support for 3D */
+ if (!dev_priv->sou_priv)
+ return -EINVAL;
+
ret = ttm_read_lock(&vmaster->lock, true);
if (unlikely(ret != 0))
return ret;
- if (!num_clips ||
- !(dev_priv->fifo.capabilities &
- SVGA_FIFO_CAP_SCREEN_OBJECT)) {
- int ret;
-
- mutex_lock(&vfbs->work_lock);
- vfbs->present_fs = true;
- ret = schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE);
- mutex_unlock(&vfbs->work_lock);
- if (ret) {
- /**
- * No work pending, Force immediate present.
- */
- vmw_framebuffer_present_fs_callback(&vfbs->d_work.work);
- }
- ttm_read_unlock(&vmaster->lock);
- return 0;
- }
-
if (!num_clips) {
num_clips = 1;
clips = &norect;
@@ -493,29 +499,10 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
inc = 2; /* skip source rects */
}
- cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
- if (unlikely(cmd == NULL)) {
- DRM_ERROR("Fifo reserve failed.\n");
- ttm_read_unlock(&vmaster->lock);
- return -ENOMEM;
- }
-
- memset(cmd, 0, sizeof(*cmd));
-
- cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT);
- cmd->header.size = cpu_to_le32(sizeof(cmd->body) + num_clips * sizeof(cmd->cr));
- cmd->body.sid = cpu_to_le32(surf->res.id);
-
- for (i = 0, cr = &cmd->cr; i < num_clips; i++, cr++, clips += inc) {
- cr->x = cpu_to_le16(clips->x1);
- cr->y = cpu_to_le16(clips->y1);
- cr->srcx = cr->x;
- cr->srcy = cr->y;
- cr->w = cpu_to_le16(clips->x2 - clips->x1);
- cr->h = cpu_to_le16(clips->y2 - clips->y1);
- }
+ ret = do_surface_dirty_sou(dev_priv, file_priv, &vfbs->base,
+ flags, color,
+ clips, num_clips, inc);
- vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
ttm_read_unlock(&vmaster->lock);
return 0;
}
@@ -540,6 +527,10 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
struct vmw_master *vmaster = vmw_master(file_priv->master);
int ret;
+ /* 3D is only supported on HWv8 hosts which supports screen objects */
+ if (!dev_priv->sou_priv)
+ return -ENOSYS;
+
/*
* Sanity checks.
*/
@@ -567,6 +558,9 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
case 15:
format = SVGA3D_A1R5G5B5;
break;
+ case 8:
+ format = SVGA3D_LUMINANCE8;
+ break;
default:
DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
return -EINVAL;
@@ -599,14 +593,11 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
vfbs->base.base.depth = mode_cmd->depth;
vfbs->base.base.width = mode_cmd->width;
vfbs->base.base.height = mode_cmd->height;
- vfbs->base.pin = &vmw_surface_dmabuf_pin;
- vfbs->base.unpin = &vmw_surface_dmabuf_unpin;
vfbs->surface = surface;
+ vfbs->base.user_handle = mode_cmd->handle;
vfbs->master = drm_master_get(file_priv->master);
- mutex_init(&vfbs->work_lock);
mutex_lock(&vmaster->fb_surf_mutex);
- INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback);
list_add_tail(&vfbs->head, &vmaster->fb_surf);
mutex_unlock(&vmaster->fb_surf_mutex);
@@ -641,48 +632,33 @@ void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer)
drm_framebuffer_cleanup(framebuffer);
vmw_dmabuf_unreference(&vfbd->buffer);
+ ttm_base_object_unref(&vfbd->base.user_obj);
kfree(vfbd);
}
-int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
- struct drm_file *file_priv,
- unsigned flags, unsigned color,
- struct drm_clip_rect *clips,
- unsigned num_clips)
+static int do_dmabuf_dirty_ldu(struct vmw_private *dev_priv,
+ struct vmw_framebuffer *framebuffer,
+ unsigned flags, unsigned color,
+ struct drm_clip_rect *clips,
+ unsigned num_clips, int increment)
{
- struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
- struct vmw_master *vmaster = vmw_master(file_priv->master);
- struct drm_clip_rect norect;
- int ret;
+ size_t fifo_size;
+ int i;
+
struct {
uint32_t header;
SVGAFifoCmdUpdate body;
} *cmd;
- int i, increment = 1;
-
- ret = ttm_read_lock(&vmaster->lock, true);
- if (unlikely(ret != 0))
- return ret;
-
- if (!num_clips) {
- num_clips = 1;
- clips = &norect;
- norect.x1 = norect.y1 = 0;
- norect.x2 = framebuffer->width;
- norect.y2 = framebuffer->height;
- } else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
- num_clips /= 2;
- increment = 2;
- }
- cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) * num_clips);
+ fifo_size = sizeof(*cmd) * num_clips;
+ cmd = vmw_fifo_reserve(dev_priv, fifo_size);
if (unlikely(cmd == NULL)) {
DRM_ERROR("Fifo reserve failed.\n");
- ttm_read_unlock(&vmaster->lock);
return -ENOMEM;
}
+ memset(cmd, 0, fifo_size);
for (i = 0; i < num_clips; i++, clips += increment) {
cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE);
cmd[i].body.x = cpu_to_le32(clips->x1);
@@ -691,57 +667,186 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
cmd[i].body.height = cpu_to_le32(clips->y2 - clips->y1);
}
- vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips);
- ttm_read_unlock(&vmaster->lock);
-
+ vmw_fifo_commit(dev_priv, fifo_size);
return 0;
}
-static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
- .destroy = vmw_framebuffer_dmabuf_destroy,
- .dirty = vmw_framebuffer_dmabuf_dirty,
- .create_handle = vmw_framebuffer_create_handle,
-};
-
-static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb)
+static int do_dmabuf_define_gmrfb(struct drm_file *file_priv,
+ struct vmw_private *dev_priv,
+ struct vmw_framebuffer *framebuffer)
{
- struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
- struct vmw_framebuffer_surface *vfbs =
- vmw_framebuffer_to_vfbs(&vfb->base);
- unsigned long size = vfbs->base.base.pitch * vfbs->base.base.height;
+ int depth = framebuffer->base.depth;
+ size_t fifo_size;
int ret;
- vfbs->buffer = kzalloc(sizeof(*vfbs->buffer), GFP_KERNEL);
- if (unlikely(vfbs->buffer == NULL))
+ struct {
+ uint32_t header;
+ SVGAFifoCmdDefineGMRFB body;
+ } *cmd;
+
+ /* Emulate RGBA support, contrary to svga_reg.h this is not
+ * supported by hosts. This is only a problem if we are reading
+ * this value later and expecting what we uploaded back.
+ */
+ if (depth == 32)
+ depth = 24;
+
+ fifo_size = sizeof(*cmd);
+ cmd = kmalloc(fifo_size, GFP_KERNEL);
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("Failed to allocate temporary cmd buffer.\n");
return -ENOMEM;
+ }
- vmw_overlay_pause_all(dev_priv);
- ret = vmw_dmabuf_init(dev_priv, vfbs->buffer, size,
- &vmw_vram_ne_placement,
- false, &vmw_dmabuf_bo_free);
- vmw_overlay_resume_all(dev_priv);
+ memset(cmd, 0, fifo_size);
+ cmd->header = SVGA_CMD_DEFINE_GMRFB;
+ cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel;
+ cmd->body.format.colorDepth = depth;
+ cmd->body.format.reserved = 0;
+ cmd->body.bytesPerLine = framebuffer->base.pitch;
+ cmd->body.ptr.gmrId = framebuffer->user_handle;
+ cmd->body.ptr.offset = 0;
+
+ ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
+ fifo_size, 0, NULL);
+
+ kfree(cmd);
+
+ return ret;
+}
+
+static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
+ struct vmw_private *dev_priv,
+ struct vmw_framebuffer *framebuffer,
+ unsigned flags, unsigned color,
+ struct drm_clip_rect *clips,
+ unsigned num_clips, int increment)
+{
+ struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+ struct drm_clip_rect *clips_ptr;
+ int i, k, num_units, ret;
+ struct drm_crtc *crtc;
+ size_t fifo_size;
+
+ struct {
+ uint32_t header;
+ SVGAFifoCmdBlitGMRFBToScreen body;
+ } *blits;
+
+ ret = do_dmabuf_define_gmrfb(file_priv, dev_priv, framebuffer);
if (unlikely(ret != 0))
- vfbs->buffer = NULL;
+ return ret; /* define_gmrfb prints warnings */
+
+ fifo_size = sizeof(*blits) * num_clips;
+ blits = kmalloc(fifo_size, GFP_KERNEL);
+ if (unlikely(blits == NULL)) {
+ DRM_ERROR("Failed to allocate temporary cmd buffer.\n");
+ return -ENOMEM;
+ }
+
+ num_units = 0;
+ list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
+ if (crtc->fb != &framebuffer->base)
+ continue;
+ units[num_units++] = vmw_crtc_to_du(crtc);
+ }
+
+ for (k = 0; k < num_units; k++) {
+ struct vmw_display_unit *unit = units[k];
+ int hit_num = 0;
+
+ clips_ptr = clips;
+ for (i = 0; i < num_clips; i++, clips_ptr += increment) {
+ int clip_x1 = clips_ptr->x1 - unit->crtc.x;
+ int clip_y1 = clips_ptr->y1 - unit->crtc.y;
+ int clip_x2 = clips_ptr->x2 - unit->crtc.x;
+ int clip_y2 = clips_ptr->y2 - unit->crtc.y;
+
+ /* skip any crtcs that misses the clip region */
+ if (clip_x1 >= unit->crtc.mode.hdisplay ||
+ clip_y1 >= unit->crtc.mode.vdisplay ||
+ clip_x2 <= 0 || clip_y2 <= 0)
+ continue;
+
+ blits[hit_num].header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN;
+ blits[hit_num].body.destScreenId = unit->unit;
+ blits[hit_num].body.srcOrigin.x = clips_ptr->x1;
+ blits[hit_num].body.srcOrigin.y = clips_ptr->y1;
+ blits[hit_num].body.destRect.left = clip_x1;
+ blits[hit_num].body.destRect.top = clip_y1;
+ blits[hit_num].body.destRect.right = clip_x2;
+ blits[hit_num].body.destRect.bottom = clip_y2;
+ hit_num++;
+ }
+
+ /* no clips hit the crtc */
+ if (hit_num == 0)
+ continue;
+
+ fifo_size = sizeof(*blits) * hit_num;
+ ret = vmw_execbuf_process(file_priv, dev_priv, NULL, blits,
+ fifo_size, 0, NULL);
+
+ if (unlikely(ret != 0))
+ break;
+ }
+
+ kfree(blits);
return ret;
}
-static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb)
+int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
+ struct drm_file *file_priv,
+ unsigned flags, unsigned color,
+ struct drm_clip_rect *clips,
+ unsigned num_clips)
{
- struct ttm_buffer_object *bo;
- struct vmw_framebuffer_surface *vfbs =
- vmw_framebuffer_to_vfbs(&vfb->base);
+ struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+ struct vmw_master *vmaster = vmw_master(file_priv->master);
+ struct vmw_framebuffer_dmabuf *vfbd =
+ vmw_framebuffer_to_vfbd(framebuffer);
+ struct drm_clip_rect norect;
+ int ret, increment = 1;
- if (unlikely(vfbs->buffer == NULL))
- return 0;
+ ret = ttm_read_lock(&vmaster->lock, true);
+ if (unlikely(ret != 0))
+ return ret;
+
+ if (!num_clips) {
+ num_clips = 1;
+ clips = &norect;
+ norect.x1 = norect.y1 = 0;
+ norect.x2 = framebuffer->width;
+ norect.y2 = framebuffer->height;
+ } else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
+ num_clips /= 2;
+ increment = 2;
+ }
- bo = &vfbs->buffer->base;
- ttm_bo_unref(&bo);
- vfbs->buffer = NULL;
+ if (dev_priv->ldu_priv) {
+ ret = do_dmabuf_dirty_ldu(dev_priv, &vfbd->base,
+ flags, color,
+ clips, num_clips, increment);
+ } else {
+ ret = do_dmabuf_dirty_sou(file_priv, dev_priv, &vfbd->base,
+ flags, color,
+ clips, num_clips, increment);
+ }
- return 0;
+ ttm_read_unlock(&vmaster->lock);
+ return ret;
}
+static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
+ .destroy = vmw_framebuffer_dmabuf_destroy,
+ .dirty = vmw_framebuffer_dmabuf_dirty,
+ .create_handle = vmw_framebuffer_create_handle,
+};
+
+/**
+ * Pin the dmabuffer to the start of vram.
+ */
static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
{
struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
@@ -749,10 +854,12 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
vmw_framebuffer_to_vfbd(&vfb->base);
int ret;
+ /* This code should not be used with screen objects */
+ BUG_ON(dev_priv->sou_priv);
vmw_overlay_pause_all(dev_priv);
- ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
+ ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer, true, false);
vmw_overlay_resume_all(dev_priv);
@@ -772,7 +879,7 @@ static int vmw_framebuffer_dmabuf_unpin(struct vmw_framebuffer *vfb)
return 0;
}
- return vmw_dmabuf_from_vram(dev_priv, vfbd->buffer);
+ return vmw_dmabuf_unpin(dev_priv, vfbd->buffer, false);
}
static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
@@ -794,6 +901,33 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
return -EINVAL;
}
+ /* Limited framebuffer color depth support for screen objects */
+ if (dev_priv->sou_priv) {
+ switch (mode_cmd->depth) {
+ case 32:
+ case 24:
+ /* Only support 32 bpp for 32 and 24 depth fbs */
+ if (mode_cmd->bpp == 32)
+ break;
+
+ DRM_ERROR("Invalid color depth/bbp: %d %d\n",
+ mode_cmd->depth, mode_cmd->bpp);
+ return -EINVAL;
+ case 16:
+ case 15:
+ /* Only support 16 bpp for 16 and 15 depth fbs */
+ if (mode_cmd->bpp == 16)
+ break;
+
+ DRM_ERROR("Invalid color depth/bbp: %d %d\n",
+ mode_cmd->depth, mode_cmd->bpp);
+ return -EINVAL;
+ default:
+ DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
+ return -EINVAL;
+ }
+ }
+
vfbd = kzalloc(sizeof(*vfbd), GFP_KERNEL);
if (!vfbd) {
ret = -ENOMEM;
@@ -815,9 +949,13 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
vfbd->base.base.depth = mode_cmd->depth;
vfbd->base.base.width = mode_cmd->width;
vfbd->base.base.height = mode_cmd->height;
- vfbd->base.pin = vmw_framebuffer_dmabuf_pin;
- vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin;
+ if (!dev_priv->sou_priv) {
+ vfbd->base.pin = vmw_framebuffer_dmabuf_pin;
+ vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin;
+ }
+ vfbd->base.dmabuf = true;
vfbd->buffer = dmabuf;
+ vfbd->base.user_handle = mode_cmd->handle;
*out = &vfbd->base;
return 0;
@@ -843,6 +981,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
struct vmw_framebuffer *vfb = NULL;
struct vmw_surface *surface = NULL;
struct vmw_dma_buffer *bo = NULL;
+ struct ttm_base_object *user_obj;
u64 required_size;
int ret;
@@ -858,6 +997,21 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
return NULL;
}
+ /*
+ * Take a reference on the user object of the resource
+ * backing the kms fb. This ensures that user-space handle
+ * lookups on that resource will always work as long as
+ * it's registered with a kms framebuffer. This is important,
+ * since vmw_execbuf_process identifies resources in the
+ * command stream using user-space handles.
+ */
+
+ user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle);
+ if (unlikely(user_obj == NULL)) {
+ DRM_ERROR("Could not locate requested kms frame buffer.\n");
+ return ERR_PTR(-ENOENT);
+ }
+
/**
* End conditioned code.
*/
@@ -878,8 +1032,10 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
if (ret) {
DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret);
+ ttm_base_object_unref(&user_obj);
return ERR_PTR(ret);
- }
+ } else
+ vfb->user_obj = user_obj;
return &vfb->base;
try_dmabuf:
@@ -899,8 +1055,10 @@ try_dmabuf:
if (ret) {
DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret);
+ ttm_base_object_unref(&user_obj);
return ERR_PTR(ret);
- }
+ } else
+ vfb->user_obj = user_obj;
return &vfb->base;
@@ -908,6 +1066,7 @@ err_not_scanout:
DRM_ERROR("surface not marked as scanout\n");
/* vmw_user_surface_lookup takes one ref */
vmw_surface_unreference(&surface);
+ ttm_base_object_unref(&user_obj);
return ERR_PTR(-EINVAL);
}
@@ -916,6 +1075,210 @@ static struct drm_mode_config_funcs vmw_kms_funcs = {
.fb_create = vmw_kms_fb_create,
};
+int vmw_kms_present(struct vmw_private *dev_priv,
+ struct drm_file *file_priv,
+ struct vmw_framebuffer *vfb,
+ struct vmw_surface *surface,
+ uint32_t sid,
+ int32_t destX, int32_t destY,
+ struct drm_vmw_rect *clips,
+ uint32_t num_clips)
+{
+ struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+ struct drm_crtc *crtc;
+ size_t fifo_size;
+ int i, k, num_units;
+ int ret = 0; /* silence warning */
+
+ struct {
+ SVGA3dCmdHeader header;
+ SVGA3dCmdBlitSurfaceToScreen body;
+ } *cmd;
+ SVGASignedRect *blits;
+
+ num_units = 0;
+ list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
+ if (crtc->fb != &vfb->base)
+ continue;
+ units[num_units++] = vmw_crtc_to_du(crtc);
+ }
+
+ BUG_ON(surface == NULL);
+ BUG_ON(!clips || !num_clips);
+
+ fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips;
+ cmd = kmalloc(fifo_size, GFP_KERNEL);
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("Failed to allocate temporary fifo memory.\n");
+ return -ENOMEM;
+ }
+
+ /* only need to do this once */
+ memset(cmd, 0, fifo_size);
+ cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
+ cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
+
+ cmd->body.srcRect.left = 0;
+ cmd->body.srcRect.right = surface->sizes[0].width;
+ cmd->body.srcRect.top = 0;
+ cmd->body.srcRect.bottom = surface->sizes[0].height;
+
+ blits = (SVGASignedRect *)&cmd[1];
+ for (i = 0; i < num_clips; i++) {
+ blits[i].left = clips[i].x;
+ blits[i].right = clips[i].x + clips[i].w;
+ blits[i].top = clips[i].y;
+ blits[i].bottom = clips[i].y + clips[i].h;
+ }
+
+ for (k = 0; k < num_units; k++) {
+ struct vmw_display_unit *unit = units[k];
+ int clip_x1 = destX - unit->crtc.x;
+ int clip_y1 = destY - unit->crtc.y;
+ int clip_x2 = clip_x1 + surface->sizes[0].width;
+ int clip_y2 = clip_y1 + surface->sizes[0].height;
+
+ /* skip any crtcs that misses the clip region */
+ if (clip_x1 >= unit->crtc.mode.hdisplay ||
+ clip_y1 >= unit->crtc.mode.vdisplay ||
+ clip_x2 <= 0 || clip_y2 <= 0)
+ continue;
+
+ /* need to reset sid as it is changed by execbuf */
+ cmd->body.srcImage.sid = sid;
+
+ cmd->body.destScreenId = unit->unit;
+
+ /*
+ * The blit command is a lot more resilient then the
+ * readback command when it comes to clip rects. So its
+ * okay to go out of bounds.
+ */
+
+ cmd->body.destRect.left = clip_x1;
+ cmd->body.destRect.right = clip_x2;
+ cmd->body.destRect.top = clip_y1;
+ cmd->body.destRect.bottom = clip_y2;
+
+ ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
+ fifo_size, 0, NULL);
+
+ if (unlikely(ret != 0))
+ break;
+ }
+
+ kfree(cmd);
+
+ return ret;
+}
+
+int vmw_kms_readback(struct vmw_private *dev_priv,
+ struct drm_file *file_priv,
+ struct vmw_framebuffer *vfb,
+ struct drm_vmw_fence_rep __user *user_fence_rep,
+ struct drm_vmw_rect *clips,
+ uint32_t num_clips)
+{
+ struct vmw_framebuffer_dmabuf *vfbd =
+ vmw_framebuffer_to_vfbd(&vfb->base);
+ struct vmw_dma_buffer *dmabuf = vfbd->buffer;
+ struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+ struct drm_crtc *crtc;
+ size_t fifo_size;
+ int i, k, ret, num_units, blits_pos;
+
+ struct {
+ uint32_t header;
+ SVGAFifoCmdDefineGMRFB body;
+ } *cmd;
+ struct {
+ uint32_t header;
+ SVGAFifoCmdBlitScreenToGMRFB body;
+ } *blits;
+
+ num_units = 0;
+ list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
+ if (crtc->fb != &vfb->base)
+ continue;
+ units[num_units++] = vmw_crtc_to_du(crtc);
+ }
+
+ BUG_ON(dmabuf == NULL);
+ BUG_ON(!clips || !num_clips);
+
+ /* take a safe guess at fifo size */
+ fifo_size = sizeof(*cmd) + sizeof(*blits) * num_clips * num_units;
+ cmd = kmalloc(fifo_size, GFP_KERNEL);
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("Failed to allocate temporary fifo memory.\n");
+ return -ENOMEM;
+ }
+
+ memset(cmd, 0, fifo_size);
+ cmd->header = SVGA_CMD_DEFINE_GMRFB;
+ cmd->body.format.bitsPerPixel = vfb->base.bits_per_pixel;
+ cmd->body.format.colorDepth = vfb->base.depth;
+ cmd->body.format.reserved = 0;
+ cmd->body.bytesPerLine = vfb->base.pitch;
+ cmd->body.ptr.gmrId = vfb->user_handle;
+ cmd->body.ptr.offset = 0;
+
+ blits = (void *)&cmd[1];
+ blits_pos = 0;
+ for (i = 0; i < num_units; i++) {
+ struct drm_vmw_rect *c = clips;
+ for (k = 0; k < num_clips; k++, c++) {
+ /* transform clip coords to crtc origin based coords */
+ int clip_x1 = c->x - units[i]->crtc.x;
+ int clip_x2 = c->x - units[i]->crtc.x + c->w;
+ int clip_y1 = c->y - units[i]->crtc.y;
+ int clip_y2 = c->y - units[i]->crtc.y + c->h;
+ int dest_x = c->x;
+ int dest_y = c->y;
+
+ /* compensate for clipping, we negate
+ * a negative number and add that.
+ */
+ if (clip_x1 < 0)
+ dest_x += -clip_x1;
+ if (clip_y1 < 0)
+ dest_y += -clip_y1;
+
+ /* clip */
+ clip_x1 = max(clip_x1, 0);
+ clip_y1 = max(clip_y1, 0);
+ clip_x2 = min(clip_x2, units[i]->crtc.mode.hdisplay);
+ clip_y2 = min(clip_y2, units[i]->crtc.mode.vdisplay);
+
+ /* and cull any rects that misses the crtc */
+ if (clip_x1 >= units[i]->crtc.mode.hdisplay ||
+ clip_y1 >= units[i]->crtc.mode.vdisplay ||
+ clip_x2 <= 0 || clip_y2 <= 0)
+ continue;
+
+ blits[blits_pos].header = SVGA_CMD_BLIT_SCREEN_TO_GMRFB;
+ blits[blits_pos].body.srcScreenId = units[i]->unit;
+ blits[blits_pos].body.destOrigin.x = dest_x;
+ blits[blits_pos].body.destOrigin.y = dest_y;
+
+ blits[blits_pos].body.srcRect.left = clip_x1;
+ blits[blits_pos].body.srcRect.top = clip_y1;
+ blits[blits_pos].body.srcRect.right = clip_x2;
+ blits[blits_pos].body.srcRect.bottom = clip_y2;
+ blits_pos++;
+ }
+ }
+ /* reset size here and use calculated exact size from loops */
+ fifo_size = sizeof(*cmd) + sizeof(*blits) * blits_pos;
+
+ ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size,
+ 0, user_fence_rep);
+
+ kfree(cmd);
+
+ return ret;
+}
+
int vmw_kms_init(struct vmw_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
@@ -929,7 +1292,9 @@ int vmw_kms_init(struct vmw_private *dev_priv)
dev->mode_config.max_width = 8192;
dev->mode_config.max_height = 8192;
- ret = vmw_kms_init_legacy_display_system(dev_priv);
+ ret = vmw_kms_init_screen_object_display(dev_priv);
+ if (ret) /* Fallback */
+ (void)vmw_kms_init_legacy_display_system(dev_priv);
return 0;
}
@@ -987,9 +1352,9 @@ out:
return ret;
}
-void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+int vmw_kms_write_svga(struct vmw_private *vmw_priv,
unsigned width, unsigned height, unsigned pitch,
- unsigned bbp, unsigned depth)
+ unsigned bpp, unsigned depth)
{
if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
@@ -997,11 +1362,15 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv,
iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
- vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp);
- vmw_write(vmw_priv, SVGA_REG_DEPTH, depth);
- vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
- vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
- vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+ vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bpp);
+
+ if (vmw_read(vmw_priv, SVGA_REG_DEPTH) != depth) {
+ DRM_ERROR("Invalid depth %u for %u bpp, host expects %u\n",
+ depth, bpp, vmw_read(vmw_priv, SVGA_REG_DEPTH));
+ return -EINVAL;
+ }
+
+ return 0;
}
int vmw_kms_save_vga(struct vmw_private *vmw_priv)
@@ -1011,12 +1380,7 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
- vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH);
vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
- vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR);
- vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
- vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
- vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
vmw_priv->vga_pitchlock =
vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
@@ -1065,12 +1429,7 @@ int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width);
vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height);
- vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth);
vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
- vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo);
- vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
- vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
- vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
vmw_write(vmw_priv, SVGA_REG_PITCHLOCK,
vmw_priv->vga_pitchlock);
@@ -1095,60 +1454,272 @@ int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
return 0;
}
-int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
+ uint32_t pitch,
+ uint32_t height)
{
- struct vmw_private *dev_priv = vmw_priv(dev);
- struct drm_vmw_update_layout_arg *arg =
- (struct drm_vmw_update_layout_arg *)data;
- struct vmw_master *vmaster = vmw_master(file_priv->master);
- void __user *user_rects;
- struct drm_vmw_rect *rects;
- unsigned rects_size;
- int ret;
+ return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size;
+}
- ret = ttm_read_lock(&vmaster->lock, true);
- if (unlikely(ret != 0))
- return ret;
- if (!arg->num_outputs) {
- struct drm_vmw_rect def_rect = {0, 0, 800, 600};
- vmw_kms_ldu_update_layout(dev_priv, 1, &def_rect);
- goto out_unlock;
- }
+/**
+ * Function called by DRM code called with vbl_lock held.
+ */
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+ return 0;
+}
- rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
- rects = kzalloc(rects_size, GFP_KERNEL);
- if (unlikely(!rects)) {
- ret = -ENOMEM;
- goto out_unlock;
+/**
+ * Function called by DRM code called with vbl_lock held.
+ */
+int vmw_enable_vblank(struct drm_device *dev, int crtc)
+{
+ return -ENOSYS;
+}
+
+/**
+ * Function called by DRM code called with vbl_lock held.
+ */
+void vmw_disable_vblank(struct drm_device *dev, int crtc)
+{
+}
+
+
+/*
+ * Small shared kms functions.
+ */
+
+int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
+ struct drm_vmw_rect *rects)
+{
+ struct drm_device *dev = dev_priv->dev;
+ struct vmw_display_unit *du;
+ struct drm_connector *con;
+
+ mutex_lock(&dev->mode_config.mutex);
+
+#if 0
+ {
+ unsigned int i;
+
+ DRM_INFO("%s: new layout ", __func__);
+ for (i = 0; i < num; i++)
+ DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
+ rects[i].w, rects[i].h);
+ DRM_INFO("\n");
+ }
+#endif
+
+ list_for_each_entry(con, &dev->mode_config.connector_list, head) {
+ du = vmw_connector_to_du(con);
+ if (num > du->unit) {
+ du->pref_width = rects[du->unit].w;
+ du->pref_height = rects[du->unit].h;
+ du->pref_active = true;
+ } else {
+ du->pref_width = 800;
+ du->pref_height = 600;
+ du->pref_active = false;
+ }
+ con->status = vmw_du_connector_detect(con, true);
}
- user_rects = (void __user *)(unsigned long)arg->rects;
- ret = copy_from_user(rects, user_rects, rects_size);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Failed to get rects.\n");
- ret = -EFAULT;
- goto out_free;
+ mutex_unlock(&dev->mode_config.mutex);
+
+ return 0;
+}
+
+void vmw_du_crtc_save(struct drm_crtc *crtc)
+{
+}
+
+void vmw_du_crtc_restore(struct drm_crtc *crtc)
+{
+}
+
+void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
+ u16 *r, u16 *g, u16 *b,
+ uint32_t start, uint32_t size)
+{
+ struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+ int i;
+
+ for (i = 0; i < size; i++) {
+ DRM_DEBUG("%d r/g/b = 0x%04x / 0x%04x / 0x%04x\n", i,
+ r[i], g[i], b[i]);
+ vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 0, r[i] >> 8);
+ vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 1, g[i] >> 8);
+ vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 2, b[i] >> 8);
}
+}
- vmw_kms_ldu_update_layout(dev_priv, arg->num_outputs, rects);
+void vmw_du_connector_dpms(struct drm_connector *connector, int mode)
+{
+}
-out_free:
- kfree(rects);
-out_unlock:
- ttm_read_unlock(&vmaster->lock);
- return ret;
+void vmw_du_connector_save(struct drm_connector *connector)
+{
}
-bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
- uint32_t pitch,
- uint32_t height)
+void vmw_du_connector_restore(struct drm_connector *connector)
{
- return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size;
}
-u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
+enum drm_connector_status
+vmw_du_connector_detect(struct drm_connector *connector, bool force)
+{
+ uint32_t num_displays;
+ struct drm_device *dev = connector->dev;
+ struct vmw_private *dev_priv = vmw_priv(dev);
+
+ mutex_lock(&dev_priv->hw_mutex);
+ num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS);
+ mutex_unlock(&dev_priv->hw_mutex);
+
+ return ((vmw_connector_to_du(connector)->unit < num_displays) ?
+ connector_status_connected : connector_status_disconnected);
+}
+
+static struct drm_display_mode vmw_kms_connector_builtin[] = {
+ /* 640x480@60Hz */
+ { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
+ 752, 800, 0, 480, 489, 492, 525, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+ /* 800x600@60Hz */
+ { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
+ 968, 1056, 0, 600, 601, 605, 628, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1024x768@60Hz */
+ { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
+ 1184, 1344, 0, 768, 771, 777, 806, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+ /* 1152x864@75Hz */
+ { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
+ 1344, 1600, 0, 864, 865, 868, 900, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1280x768@60Hz */
+ { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
+ 1472, 1664, 0, 768, 771, 778, 798, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1280x800@60Hz */
+ { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
+ 1480, 1680, 0, 800, 803, 809, 831, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+ /* 1280x960@60Hz */
+ { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
+ 1488, 1800, 0, 960, 961, 964, 1000, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1280x1024@60Hz */
+ { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
+ 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1360x768@60Hz */
+ { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
+ 1536, 1792, 0, 768, 771, 777, 795, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1440x1050@60Hz */
+ { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
+ 1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1440x900@60Hz */
+ { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
+ 1672, 1904, 0, 900, 903, 909, 934, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1600x1200@60Hz */
+ { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
+ 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1680x1050@60Hz */
+ { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
+ 1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1792x1344@60Hz */
+ { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
+ 2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1853x1392@60Hz */
+ { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
+ 2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1920x1200@60Hz */
+ { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
+ 2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 1920x1440@60Hz */
+ { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
+ 2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 2560x1600@60Hz */
+ { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
+ 3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* Terminate */
+ { DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
+};
+
+int vmw_du_connector_fill_modes(struct drm_connector *connector,
+ uint32_t max_width, uint32_t max_height)
+{
+ struct vmw_display_unit *du = vmw_connector_to_du(connector);
+ struct drm_device *dev = connector->dev;
+ struct vmw_private *dev_priv = vmw_priv(dev);
+ struct drm_display_mode *mode = NULL;
+ struct drm_display_mode *bmode;
+ struct drm_display_mode prefmode = { DRM_MODE("preferred",
+ DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
+ };
+ int i;
+
+ /* Add preferred mode */
+ {
+ mode = drm_mode_duplicate(dev, &prefmode);
+ if (!mode)
+ return 0;
+ mode->hdisplay = du->pref_width;
+ mode->vdisplay = du->pref_height;
+ mode->vrefresh = drm_mode_vrefresh(mode);
+ if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
+ mode->vdisplay)) {
+ drm_mode_probed_add(connector, mode);
+
+ if (du->pref_mode) {
+ list_del_init(&du->pref_mode->head);
+ drm_mode_destroy(dev, du->pref_mode);
+ }
+
+ du->pref_mode = mode;
+ }
+ }
+
+ for (i = 0; vmw_kms_connector_builtin[i].type != 0; i++) {
+ bmode = &vmw_kms_connector_builtin[i];
+ if (bmode->hdisplay > max_width ||
+ bmode->vdisplay > max_height)
+ continue;
+
+ if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2,
+ bmode->vdisplay))
+ continue;
+
+ mode = drm_mode_duplicate(dev, bmode);
+ if (!mode)
+ return 0;
+ mode->vrefresh = drm_mode_vrefresh(mode);
+
+ drm_mode_probed_add(connector, mode);
+ }
+
+ drm_mode_connector_list_update(connector);
+
+ return 1;
+}
+
+int vmw_du_connector_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t val)
{
return 0;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 8a398a0339b6..db0b901f8c3f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -31,6 +31,8 @@
#include "drmP.h"
#include "vmwgfx_drv.h"
+#define VMWGFX_NUM_DISPLAY_UNITS 8
+
#define vmw_framebuffer_to_vfb(x) \
container_of(x, struct vmw_framebuffer, base)
@@ -45,6 +47,9 @@ struct vmw_framebuffer {
struct drm_framebuffer base;
int (*pin)(struct vmw_framebuffer *fb);
int (*unpin)(struct vmw_framebuffer *fb);
+ bool dmabuf;
+ struct ttm_base_object *user_obj;
+ uint32_t user_handle;
};
@@ -83,22 +88,59 @@ struct vmw_display_unit {
int hotspot_y;
unsigned unit;
+
+ /*
+ * Prefered mode tracking.
+ */
+ unsigned pref_width;
+ unsigned pref_height;
+ bool pref_active;
+ struct drm_display_mode *pref_mode;
};
+#define vmw_crtc_to_du(x) \
+ container_of(x, struct vmw_display_unit, crtc)
+#define vmw_connector_to_du(x) \
+ container_of(x, struct vmw_display_unit, connector)
+
+
/*
* Shared display unit functions - vmwgfx_kms.c
*/
void vmw_display_unit_cleanup(struct vmw_display_unit *du);
+void vmw_du_crtc_save(struct drm_crtc *crtc);
+void vmw_du_crtc_restore(struct drm_crtc *crtc);
+void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
+ u16 *r, u16 *g, u16 *b,
+ uint32_t start, uint32_t size);
int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
uint32_t handle, uint32_t width, uint32_t height);
int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
+void vmw_du_connector_dpms(struct drm_connector *connector, int mode);
+void vmw_du_connector_save(struct drm_connector *connector);
+void vmw_du_connector_restore(struct drm_connector *connector);
+enum drm_connector_status
+vmw_du_connector_detect(struct drm_connector *connector, bool force);
+int vmw_du_connector_fill_modes(struct drm_connector *connector,
+ uint32_t max_width, uint32_t max_height);
+int vmw_du_connector_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t val);
+int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
+ struct drm_vmw_rect *rects);
/*
* Legacy display unit functions - vmwgfx_ldu.c
*/
int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
-int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
+
+/*
+ * Screen Objects display functions - vmwgfx_scrn.c
+ */
+int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv);
+int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv);
+int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num,
struct drm_vmw_rect *rects);
#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index b3a2cd5118d7..92f56bc594eb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -27,7 +27,6 @@
#include "vmwgfx_kms.h"
-#define VMWGFX_LDU_NUM_DU 8
#define vmw_crtc_to_ldu(x) \
container_of(x, struct vmw_legacy_display_unit, base.crtc)
@@ -51,11 +50,6 @@ struct vmw_legacy_display {
struct vmw_legacy_display_unit {
struct vmw_display_unit base;
- unsigned pref_width;
- unsigned pref_height;
- bool pref_active;
- struct drm_display_mode *pref_mode;
-
struct list_head active;
};
@@ -71,20 +65,6 @@ static void vmw_ldu_destroy(struct vmw_legacy_display_unit *ldu)
* Legacy Display Unit CRTC functions
*/
-static void vmw_ldu_crtc_save(struct drm_crtc *crtc)
-{
-}
-
-static void vmw_ldu_crtc_restore(struct drm_crtc *crtc)
-{
-}
-
-static void vmw_ldu_crtc_gamma_set(struct drm_crtc *crtc,
- u16 *r, u16 *g, u16 *b,
- uint32_t start, uint32_t size)
-{
-}
-
static void vmw_ldu_crtc_destroy(struct drm_crtc *crtc)
{
vmw_ldu_destroy(vmw_crtc_to_ldu(crtc));
@@ -114,10 +94,8 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
return 0;
fb = entry->base.crtc.fb;
- vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
- fb->bits_per_pixel, fb->depth);
-
- return 0;
+ return vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
+ fb->bits_per_pixel, fb->depth);
}
if (!list_empty(&lds->active)) {
@@ -265,9 +243,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
vmw_ldu_del_active(dev_priv, ldu);
- vmw_ldu_commit_list(dev_priv);
-
- return 0;
+ return vmw_ldu_commit_list(dev_priv);
}
@@ -292,21 +268,20 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
vmw_ldu_add_active(dev_priv, ldu, vfb);
- vmw_ldu_commit_list(dev_priv);
-
- return 0;
+ return vmw_ldu_commit_list(dev_priv);
}
static struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
- .save = vmw_ldu_crtc_save,
- .restore = vmw_ldu_crtc_restore,
+ .save = vmw_du_crtc_save,
+ .restore = vmw_du_crtc_restore,
.cursor_set = vmw_du_crtc_cursor_set,
.cursor_move = vmw_du_crtc_cursor_move,
- .gamma_set = vmw_ldu_crtc_gamma_set,
+ .gamma_set = vmw_du_crtc_gamma_set,
.destroy = vmw_ldu_crtc_destroy,
.set_config = vmw_ldu_crtc_set_config,
};
+
/*
* Legacy Display Unit encoder functions
*/
@@ -324,183 +299,18 @@ static struct drm_encoder_funcs vmw_legacy_encoder_funcs = {
* Legacy Display Unit connector functions
*/
-static void vmw_ldu_connector_dpms(struct drm_connector *connector, int mode)
-{
-}
-
-static void vmw_ldu_connector_save(struct drm_connector *connector)
-{
-}
-
-static void vmw_ldu_connector_restore(struct drm_connector *connector)
-{
-}
-
-static enum drm_connector_status
- vmw_ldu_connector_detect(struct drm_connector *connector,
- bool force)
-{
- if (vmw_connector_to_ldu(connector)->pref_active)
- return connector_status_connected;
- return connector_status_disconnected;
-}
-
-static const struct drm_display_mode vmw_ldu_connector_builtin[] = {
- /* 640x480@60Hz */
- { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
- 752, 800, 0, 480, 489, 492, 525, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 800x600@60Hz */
- { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
- 968, 1056, 0, 600, 601, 605, 628, 0,
- DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1024x768@60Hz */
- { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
- 1184, 1344, 0, 768, 771, 777, 806, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1152x864@75Hz */
- { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
- 1344, 1600, 0, 864, 865, 868, 900, 0,
- DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x768@60Hz */
- { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
- 1472, 1664, 0, 768, 771, 778, 798, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x800@60Hz */
- { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
- 1480, 1680, 0, 800, 803, 809, 831, 0,
- DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1280x960@60Hz */
- { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
- 1488, 1800, 0, 960, 961, 964, 1000, 0,
- DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x1024@60Hz */
- { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
- 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
- DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1360x768@60Hz */
- { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
- 1536, 1792, 0, 768, 771, 777, 795, 0,
- DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1440x1050@60Hz */
- { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
- 1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1440x900@60Hz */
- { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
- 1672, 1904, 0, 900, 903, 909, 934, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1600x1200@60Hz */
- { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
- 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
- DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1680x1050@60Hz */
- { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
- 1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1792x1344@60Hz */
- { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
- 2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1853x1392@60Hz */
- { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
- 2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1920x1200@60Hz */
- { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
- 2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1920x1440@60Hz */
- { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
- 2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 2560x1600@60Hz */
- { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
- 3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* Terminate */
- { DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
-};
-
-static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
- uint32_t max_width, uint32_t max_height)
-{
- struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
- struct drm_device *dev = connector->dev;
- struct vmw_private *dev_priv = vmw_priv(dev);
- struct drm_display_mode *mode = NULL;
- struct drm_display_mode prefmode = { DRM_MODE("preferred",
- DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
- };
- int i;
-
- /* Add preferred mode */
- {
- mode = drm_mode_duplicate(dev, &prefmode);
- if (!mode)
- return 0;
- mode->hdisplay = ldu->pref_width;
- mode->vdisplay = ldu->pref_height;
- mode->vrefresh = drm_mode_vrefresh(mode);
- if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
- mode->vdisplay)) {
- drm_mode_probed_add(connector, mode);
-
- if (ldu->pref_mode) {
- list_del_init(&ldu->pref_mode->head);
- drm_mode_destroy(dev, ldu->pref_mode);
- }
-
- ldu->pref_mode = mode;
- }
- }
-
- for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
- const struct drm_display_mode *bmode;
-
- bmode = &vmw_ldu_connector_builtin[i];
- if (bmode->hdisplay > max_width ||
- bmode->vdisplay > max_height)
- continue;
-
- if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2,
- bmode->vdisplay))
- continue;
-
- mode = drm_mode_duplicate(dev, bmode);
- if (!mode)
- return 0;
- mode->vrefresh = drm_mode_vrefresh(mode);
-
- drm_mode_probed_add(connector, mode);
- }
-
- drm_mode_connector_list_update(connector);
-
- return 1;
-}
-
-static int vmw_ldu_connector_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t val)
-{
- return 0;
-}
-
static void vmw_ldu_connector_destroy(struct drm_connector *connector)
{
vmw_ldu_destroy(vmw_connector_to_ldu(connector));
}
static struct drm_connector_funcs vmw_legacy_connector_funcs = {
- .dpms = vmw_ldu_connector_dpms,
- .save = vmw_ldu_connector_save,
- .restore = vmw_ldu_connector_restore,
- .detect = vmw_ldu_connector_detect,
- .fill_modes = vmw_ldu_connector_fill_modes,
- .set_property = vmw_ldu_connector_set_property,
+ .dpms = vmw_du_connector_dpms,
+ .save = vmw_du_connector_save,
+ .restore = vmw_du_connector_restore,
+ .detect = vmw_du_connector_detect,
+ .fill_modes = vmw_du_connector_fill_modes,
+ .set_property = vmw_du_connector_set_property,
.destroy = vmw_ldu_connector_destroy,
};
@@ -523,14 +333,14 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
INIT_LIST_HEAD(&ldu->active);
- ldu->pref_active = (unit == 0);
- ldu->pref_width = 800;
- ldu->pref_height = 600;
- ldu->pref_mode = NULL;
+ ldu->base.pref_active = (unit == 0);
+ ldu->base.pref_width = 800;
+ ldu->base.pref_height = 600;
+ ldu->base.pref_mode = NULL;
drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
- connector->status = vmw_ldu_connector_detect(connector, true);
+ connector->status = vmw_du_connector_detect(connector, true);
drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
DRM_MODE_ENCODER_LVDS);
@@ -540,6 +350,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
+ drm_mode_crtc_set_gamma_size(crtc, 256);
+
drm_connector_attach_property(connector,
dev->mode_config.dirty_info_property,
1);
@@ -550,8 +362,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
- int i;
- int ret;
+ int i, ret;
if (dev_priv->ldu_priv) {
DRM_INFO("ldu system already on\n");
@@ -559,7 +370,6 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
}
dev_priv->ldu_priv = kmalloc(sizeof(*dev_priv->ldu_priv), GFP_KERNEL);
-
if (!dev_priv->ldu_priv)
return -ENOMEM;
@@ -568,18 +378,31 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
dev_priv->ldu_priv->last_num_active = 0;
dev_priv->ldu_priv->fb = NULL;
- drm_mode_create_dirty_info_property(dev_priv->dev);
+ /* for old hardware without multimon only enable one display */
+ if (dev_priv->capabilities & SVGA_CAP_MULTIMON)
+ ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
+ else
+ ret = drm_vblank_init(dev, 1);
+ if (ret != 0)
+ goto err_free;
+
+ ret = drm_mode_create_dirty_info_property(dev);
+ if (ret != 0)
+ goto err_vblank_cleanup;
- if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
- for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i)
+ if (dev_priv->capabilities & SVGA_CAP_MULTIMON)
+ for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
vmw_ldu_init(dev_priv, i);
- ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU);
- } else {
- /* for old hardware without multimon only enable one display */
+ else
vmw_ldu_init(dev_priv, 0);
- ret = drm_vblank_init(dev, 1);
- }
+ return 0;
+
+err_vblank_cleanup:
+ drm_vblank_cleanup(dev);
+err_free:
+ kfree(dev_priv->ldu_priv);
+ dev_priv->ldu_priv = NULL;
return ret;
}
@@ -587,52 +410,14 @@ int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
- drm_vblank_cleanup(dev);
if (!dev_priv->ldu_priv)
return -ENOSYS;
+ drm_vblank_cleanup(dev);
+
BUG_ON(!list_empty(&dev_priv->ldu_priv->active));
kfree(dev_priv->ldu_priv);
return 0;
}
-
-int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
- struct drm_vmw_rect *rects)
-{
- struct drm_device *dev = dev_priv->dev;
- struct vmw_legacy_display_unit *ldu;
- struct drm_connector *con;
- int i;
-
- mutex_lock(&dev->mode_config.mutex);
-
-#if 0
- DRM_INFO("%s: new layout ", __func__);
- for (i = 0; i < (int)num; i++)
- DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
- rects[i].w, rects[i].h);
- DRM_INFO("\n");
-#else
- (void)i;
-#endif
-
- list_for_each_entry(con, &dev->mode_config.connector_list, head) {
- ldu = vmw_connector_to_ldu(con);
- if (num > ldu->base.unit) {
- ldu->pref_width = rects[ldu->base.unit].w;
- ldu->pref_height = rects[ldu->base.unit].h;
- ldu->pref_active = true;
- } else {
- ldu->pref_width = 800;
- ldu->pref_height = 600;
- ldu->pref_active = false;
- }
- con->status = vmw_ldu_connector_detect(con, true);
- }
-
- mutex_unlock(&dev->mode_config.mutex);
-
- return 0;
-}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c b/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c
new file mode 100644
index 000000000000..8a8725c2716c
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c
@@ -0,0 +1,171 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "vmwgfx_drv.h"
+
+struct vmw_marker {
+ struct list_head head;
+ uint32_t seqno;
+ struct timespec submitted;
+};
+
+void vmw_marker_queue_init(struct vmw_marker_queue *queue)
+{
+ INIT_LIST_HEAD(&queue->head);
+ queue->lag = ns_to_timespec(0);
+ getrawmonotonic(&queue->lag_time);
+ spin_lock_init(&queue->lock);
+}
+
+void vmw_marker_queue_takedown(struct vmw_marker_queue *queue)
+{
+ struct vmw_marker *marker, *next;
+
+ spin_lock(&queue->lock);
+ list_for_each_entry_safe(marker, next, &queue->head, head) {
+ kfree(marker);
+ }
+ spin_unlock(&queue->lock);
+}
+
+int vmw_marker_push(struct vmw_marker_queue *queue,
+ uint32_t seqno)
+{
+ struct vmw_marker *marker = kmalloc(sizeof(*marker), GFP_KERNEL);
+
+ if (unlikely(!marker))
+ return -ENOMEM;
+
+ marker->seqno = seqno;
+ getrawmonotonic(&marker->submitted);
+ spin_lock(&queue->lock);
+ list_add_tail(&marker->head, &queue->head);
+ spin_unlock(&queue->lock);
+
+ return 0;
+}
+
+int vmw_marker_pull(struct vmw_marker_queue *queue,
+ uint32_t signaled_seqno)
+{
+ struct vmw_marker *marker, *next;
+ struct timespec now;
+ bool updated = false;
+
+ spin_lock(&queue->lock);
+ getrawmonotonic(&now);
+
+ if (list_empty(&queue->head)) {
+ queue->lag = ns_to_timespec(0);
+ queue->lag_time = now;
+ updated = true;
+ goto out_unlock;
+ }
+
+ list_for_each_entry_safe(marker, next, &queue->head, head) {
+ if (signaled_seqno - marker->seqno > (1 << 30))
+ continue;
+
+ queue->lag = timespec_sub(now, marker->submitted);
+ queue->lag_time = now;
+ updated = true;
+ list_del(&marker->head);
+ kfree(marker);
+ }
+
+out_unlock:
+ spin_unlock(&queue->lock);
+
+ return (updated) ? 0 : -EBUSY;
+}
+
+static struct timespec vmw_timespec_add(struct timespec t1,
+ struct timespec t2)
+{
+ t1.tv_sec += t2.tv_sec;
+ t1.tv_nsec += t2.tv_nsec;
+ if (t1.tv_nsec >= 1000000000L) {
+ t1.tv_sec += 1;
+ t1.tv_nsec -= 1000000000L;
+ }
+
+ return t1;
+}
+
+static struct timespec vmw_fifo_lag(struct vmw_marker_queue *queue)
+{
+ struct timespec now;
+
+ spin_lock(&queue->lock);
+ getrawmonotonic(&now);
+ queue->lag = vmw_timespec_add(queue->lag,
+ timespec_sub(now, queue->lag_time));
+ queue->lag_time = now;
+ spin_unlock(&queue->lock);
+ return queue->lag;
+}
+
+
+static bool vmw_lag_lt(struct vmw_marker_queue *queue,
+ uint32_t us)
+{
+ struct timespec lag, cond;
+
+ cond = ns_to_timespec((s64) us * 1000);
+ lag = vmw_fifo_lag(queue);
+ return (timespec_compare(&lag, &cond) < 1);
+}
+
+int vmw_wait_lag(struct vmw_private *dev_priv,
+ struct vmw_marker_queue *queue, uint32_t us)
+{
+ struct vmw_marker *marker;
+ uint32_t seqno;
+ int ret;
+
+ while (!vmw_lag_lt(queue, us)) {
+ spin_lock(&queue->lock);
+ if (list_empty(&queue->head))
+ seqno = atomic_read(&dev_priv->marker_seq);
+ else {
+ marker = list_first_entry(&queue->head,
+ struct vmw_marker, head);
+ seqno = marker->seqno;
+ }
+ spin_unlock(&queue->lock);
+
+ ret = vmw_wait_seqno(dev_priv, false, seqno, true,
+ 3*HZ);
+
+ if (unlikely(ret != 0))
+ return ret;
+
+ (void) vmw_marker_pull(queue, seqno);
+ }
+ return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
index 07ce02da78a4..14399eec9c3c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -87,48 +87,6 @@ static inline void fill_flush(struct vmw_escape_video_flush *cmd,
}
/**
- * Pin or unpin a buffer in vram.
- *
- * @dev_priv: Driver private.
- * @buf: DMA buffer to pin or unpin.
- * @pin: Pin buffer in vram if true.
- * @interruptible: Use interruptible wait.
- *
- * Takes the current masters ttm lock in read.
- *
- * Returns
- * -ERESTARTSYS if interrupted by a signal.
- */
-static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
- struct vmw_dma_buffer *buf,
- bool pin, bool interruptible)
-{
- struct ttm_buffer_object *bo = &buf->base;
- struct ttm_placement *overlay_placement = &vmw_vram_placement;
- int ret;
-
- ret = ttm_read_lock(&dev_priv->active_master->lock, interruptible);
- if (unlikely(ret != 0))
- return ret;
-
- ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
- if (unlikely(ret != 0))
- goto err;
-
- if (pin)
- overlay_placement = &vmw_vram_ne_placement;
-
- ret = ttm_bo_validate(bo, overlay_placement, interruptible, false, false);
-
- ttm_bo_unreserve(bo);
-
-err:
- ttm_read_unlock(&dev_priv->active_master->lock);
-
- return ret;
-}
-
-/**
* Send put command to hw.
*
* Returns
@@ -139,68 +97,80 @@ static int vmw_overlay_send_put(struct vmw_private *dev_priv,
struct drm_vmw_control_stream_arg *arg,
bool interruptible)
{
+ struct vmw_escape_video_flush *flush;
+ size_t fifo_size;
+ bool have_so = dev_priv->sou_priv ? true : false;
+ int i, num_items;
+ SVGAGuestPtr ptr;
+
struct {
struct vmw_escape_header escape;
struct {
- struct {
- uint32_t cmdType;
- uint32_t streamId;
- } header;
- struct {
- uint32_t registerId;
- uint32_t value;
- } items[SVGA_VIDEO_PITCH_3 + 1];
- } body;
- struct vmw_escape_video_flush flush;
+ uint32_t cmdType;
+ uint32_t streamId;
+ } header;
} *cmds;
- uint32_t offset;
- int i, ret;
+ struct {
+ uint32_t registerId;
+ uint32_t value;
+ } *items;
- for (;;) {
- cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds));
- if (cmds)
- break;
+ /* defines are a index needs + 1 */
+ if (have_so)
+ num_items = SVGA_VIDEO_DST_SCREEN_ID + 1;
+ else
+ num_items = SVGA_VIDEO_PITCH_3 + 1;
- ret = vmw_fallback_wait(dev_priv, false, true, 0,
- interruptible, 3*HZ);
- if (interruptible && ret == -ERESTARTSYS)
- return ret;
- else
- BUG_ON(ret != 0);
+ fifo_size = sizeof(*cmds) + sizeof(*flush) + sizeof(*items) * num_items;
+
+ cmds = vmw_fifo_reserve(dev_priv, fifo_size);
+ /* hardware has hung, can't do anything here */
+ if (!cmds)
+ return -ENOMEM;
+
+ items = (typeof(items))&cmds[1];
+ flush = (struct vmw_escape_video_flush *)&items[num_items];
+
+ /* the size is header + number of items */
+ fill_escape(&cmds->escape, sizeof(*items) * (num_items + 1));
+
+ cmds->header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
+ cmds->header.streamId = arg->stream_id;
+
+ /* the IDs are neatly numbered */
+ for (i = 0; i < num_items; i++)
+ items[i].registerId = i;
+
+ vmw_bo_get_guest_ptr(&buf->base, &ptr);
+ ptr.offset += arg->offset;
+
+ items[SVGA_VIDEO_ENABLED].value = true;
+ items[SVGA_VIDEO_FLAGS].value = arg->flags;
+ items[SVGA_VIDEO_DATA_OFFSET].value = ptr.offset;
+ items[SVGA_VIDEO_FORMAT].value = arg->format;
+ items[SVGA_VIDEO_COLORKEY].value = arg->color_key;
+ items[SVGA_VIDEO_SIZE].value = arg->size;
+ items[SVGA_VIDEO_WIDTH].value = arg->width;
+ items[SVGA_VIDEO_HEIGHT].value = arg->height;
+ items[SVGA_VIDEO_SRC_X].value = arg->src.x;
+ items[SVGA_VIDEO_SRC_Y].value = arg->src.y;
+ items[SVGA_VIDEO_SRC_WIDTH].value = arg->src.w;
+ items[SVGA_VIDEO_SRC_HEIGHT].value = arg->src.h;
+ items[SVGA_VIDEO_DST_X].value = arg->dst.x;
+ items[SVGA_VIDEO_DST_Y].value = arg->dst.y;
+ items[SVGA_VIDEO_DST_WIDTH].value = arg->dst.w;
+ items[SVGA_VIDEO_DST_HEIGHT].value = arg->dst.h;
+ items[SVGA_VIDEO_PITCH_1].value = arg->pitch[0];
+ items[SVGA_VIDEO_PITCH_2].value = arg->pitch[1];
+ items[SVGA_VIDEO_PITCH_3].value = arg->pitch[2];
+ if (have_so) {
+ items[SVGA_VIDEO_DATA_GMRID].value = ptr.gmrId;
+ items[SVGA_VIDEO_DST_SCREEN_ID].value = SVGA_ID_INVALID;
}
- fill_escape(&cmds->escape, sizeof(cmds->body));
- cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
- cmds->body.header.streamId = arg->stream_id;
-
- for (i = 0; i <= SVGA_VIDEO_PITCH_3; i++)
- cmds->body.items[i].registerId = i;
-
- offset = buf->base.offset + arg->offset;
-
- cmds->body.items[SVGA_VIDEO_ENABLED].value = true;
- cmds->body.items[SVGA_VIDEO_FLAGS].value = arg->flags;
- cmds->body.items[SVGA_VIDEO_DATA_OFFSET].value = offset;
- cmds->body.items[SVGA_VIDEO_FORMAT].value = arg->format;
- cmds->body.items[SVGA_VIDEO_COLORKEY].value = arg->color_key;
- cmds->body.items[SVGA_VIDEO_SIZE].value = arg->size;
- cmds->body.items[SVGA_VIDEO_WIDTH].value = arg->width;
- cmds->body.items[SVGA_VIDEO_HEIGHT].value = arg->height;
- cmds->body.items[SVGA_VIDEO_SRC_X].value = arg->src.x;
- cmds->body.items[SVGA_VIDEO_SRC_Y].value = arg->src.y;
- cmds->body.items[SVGA_VIDEO_SRC_WIDTH].value = arg->src.w;
- cmds->body.items[SVGA_VIDEO_SRC_HEIGHT].value = arg->src.h;
- cmds->body.items[SVGA_VIDEO_DST_X].value = arg->dst.x;
- cmds->body.items[SVGA_VIDEO_DST_Y].value = arg->dst.y;
- cmds->body.items[SVGA_VIDEO_DST_WIDTH].value = arg->dst.w;
- cmds->body.items[SVGA_VIDEO_DST_HEIGHT].value = arg->dst.h;
- cmds->body.items[SVGA_VIDEO_PITCH_1].value = arg->pitch[0];
- cmds->body.items[SVGA_VIDEO_PITCH_2].value = arg->pitch[1];
- cmds->body.items[SVGA_VIDEO_PITCH_3].value = arg->pitch[2];
-
- fill_flush(&cmds->flush, arg->stream_id);
+ fill_flush(flush, arg->stream_id);
- vmw_fifo_commit(dev_priv, sizeof(*cmds));
+ vmw_fifo_commit(dev_priv, fifo_size);
return 0;
}
@@ -248,6 +218,25 @@ static int vmw_overlay_send_stop(struct vmw_private *dev_priv,
}
/**
+ * Move a buffer to vram or gmr if @pin is set, else unpin the buffer.
+ *
+ * With the introduction of screen objects buffers could now be
+ * used with GMRs instead of being locked to vram.
+ */
+static int vmw_overlay_move_buffer(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buf,
+ bool pin, bool inter)
+{
+ if (!pin)
+ return vmw_dmabuf_unpin(dev_priv, buf, inter);
+
+ if (!dev_priv->sou_priv)
+ return vmw_dmabuf_to_vram(dev_priv, buf, true, inter);
+
+ return vmw_dmabuf_to_vram_or_gmr(dev_priv, buf, true, inter);
+}
+
+/**
* Stop or pause a stream.
*
* If the stream is paused the no evict flag is removed from the buffer
@@ -279,8 +268,8 @@ static int vmw_overlay_stop(struct vmw_private *dev_priv,
return ret;
/* We just remove the NO_EVICT flag so no -ENOMEM */
- ret = vmw_dmabuf_pin_in_vram(dev_priv, stream->buf, false,
- interruptible);
+ ret = vmw_overlay_move_buffer(dev_priv, stream->buf, false,
+ interruptible);
if (interruptible && ret == -ERESTARTSYS)
return ret;
else
@@ -342,7 +331,7 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
/* We don't start the old stream if we are interrupted.
* Might return -ENOMEM if it can't fit the buffer in vram.
*/
- ret = vmw_dmabuf_pin_in_vram(dev_priv, buf, true, interruptible);
+ ret = vmw_overlay_move_buffer(dev_priv, buf, true, interruptible);
if (ret)
return ret;
@@ -351,7 +340,8 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
/* This one needs to happen no matter what. We only remove
* the NO_EVICT flag so this is safe from -ENOMEM.
*/
- BUG_ON(vmw_dmabuf_pin_in_vram(dev_priv, buf, false, false) != 0);
+ BUG_ON(vmw_overlay_move_buffer(dev_priv, buf, false, false)
+ != 0);
return ret;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index bfe1bcce7f8a..86c5e4cceb31 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -31,10 +31,6 @@
#include "ttm/ttm_placement.h"
#include "drmP.h"
-#define VMW_RES_CONTEXT ttm_driver_type0
-#define VMW_RES_SURFACE ttm_driver_type1
-#define VMW_RES_STREAM ttm_driver_type2
-
struct vmw_user_context {
struct ttm_base_object base;
struct vmw_resource res;
@@ -43,6 +39,7 @@ struct vmw_user_context {
struct vmw_user_surface {
struct ttm_base_object base;
struct vmw_surface srf;
+ uint32_t size;
};
struct vmw_user_dma_buffer {
@@ -65,6 +62,17 @@ struct vmw_user_stream {
struct vmw_stream stream;
};
+struct vmw_surface_offset {
+ uint32_t face;
+ uint32_t mip;
+ uint32_t bo_offset;
+};
+
+
+static uint64_t vmw_user_context_size;
+static uint64_t vmw_user_surface_size;
+static uint64_t vmw_user_stream_size;
+
static inline struct vmw_dma_buffer *
vmw_dma_buffer(struct ttm_buffer_object *bo)
{
@@ -84,13 +92,36 @@ struct vmw_resource *vmw_resource_reference(struct vmw_resource *res)
return res;
}
+
+/**
+ * vmw_resource_release_id - release a resource id to the id manager.
+ *
+ * @res: Pointer to the resource.
+ *
+ * Release the resource id to the resource id manager and set it to -1
+ */
+static void vmw_resource_release_id(struct vmw_resource *res)
+{
+ struct vmw_private *dev_priv = res->dev_priv;
+
+ write_lock(&dev_priv->resource_lock);
+ if (res->id != -1)
+ idr_remove(res->idr, res->id);
+ res->id = -1;
+ write_unlock(&dev_priv->resource_lock);
+}
+
static void vmw_resource_release(struct kref *kref)
{
struct vmw_resource *res =
container_of(kref, struct vmw_resource, kref);
struct vmw_private *dev_priv = res->dev_priv;
+ int id = res->id;
+ struct idr *idr = res->idr;
- idr_remove(res->idr, res->id);
+ res->avail = false;
+ if (res->remove_from_lists != NULL)
+ res->remove_from_lists(res);
write_unlock(&dev_priv->resource_lock);
if (likely(res->hw_destroy != NULL))
@@ -102,6 +133,9 @@ static void vmw_resource_release(struct kref *kref)
kfree(res);
write_lock(&dev_priv->resource_lock);
+
+ if (id != -1)
+ idr_remove(idr, id);
}
void vmw_resource_unreference(struct vmw_resource **p_res)
@@ -115,28 +149,29 @@ void vmw_resource_unreference(struct vmw_resource **p_res)
write_unlock(&dev_priv->resource_lock);
}
-static int vmw_resource_init(struct vmw_private *dev_priv,
- struct vmw_resource *res,
- struct idr *idr,
- enum ttm_object_type obj_type,
- void (*res_free) (struct vmw_resource *res))
+
+/**
+ * vmw_resource_alloc_id - release a resource id to the id manager.
+ *
+ * @dev_priv: Pointer to the device private structure.
+ * @res: Pointer to the resource.
+ *
+ * Allocate the lowest free resource from the resource manager, and set
+ * @res->id to that id. Returns 0 on success and -ENOMEM on failure.
+ */
+static int vmw_resource_alloc_id(struct vmw_private *dev_priv,
+ struct vmw_resource *res)
{
int ret;
- kref_init(&res->kref);
- res->hw_destroy = NULL;
- res->res_free = res_free;
- res->res_type = obj_type;
- res->idr = idr;
- res->avail = false;
- res->dev_priv = dev_priv;
+ BUG_ON(res->id != -1);
do {
- if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
+ if (unlikely(idr_pre_get(res->idr, GFP_KERNEL) == 0))
return -ENOMEM;
write_lock(&dev_priv->resource_lock);
- ret = idr_get_new_above(idr, res, 1, &res->id);
+ ret = idr_get_new_above(res->idr, res, 1, &res->id);
write_unlock(&dev_priv->resource_lock);
} while (ret == -EAGAIN);
@@ -144,6 +179,33 @@ static int vmw_resource_init(struct vmw_private *dev_priv,
return ret;
}
+
+static int vmw_resource_init(struct vmw_private *dev_priv,
+ struct vmw_resource *res,
+ struct idr *idr,
+ enum ttm_object_type obj_type,
+ bool delay_id,
+ void (*res_free) (struct vmw_resource *res),
+ void (*remove_from_lists)
+ (struct vmw_resource *res))
+{
+ kref_init(&res->kref);
+ res->hw_destroy = NULL;
+ res->res_free = res_free;
+ res->remove_from_lists = remove_from_lists;
+ res->res_type = obj_type;
+ res->idr = idr;
+ res->avail = false;
+ res->dev_priv = dev_priv;
+ INIT_LIST_HEAD(&res->query_head);
+ INIT_LIST_HEAD(&res->validate_head);
+ res->id = -1;
+ if (delay_id)
+ return 0;
+ else
+ return vmw_resource_alloc_id(dev_priv, res);
+}
+
/**
* vmw_resource_activate
*
@@ -198,8 +260,12 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDestroyContext body;
- } *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+ } *cmd;
+
+ vmw_execbuf_release_pinned_bo(dev_priv, true, res->id);
+
+ cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
if (unlikely(cmd == NULL)) {
DRM_ERROR("Failed reserving FIFO space for surface "
"destruction.\n");
@@ -211,7 +277,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
cmd->body.cid = cpu_to_le32(res->id);
vmw_fifo_commit(dev_priv, sizeof(*cmd));
- vmw_3d_resource_dec(dev_priv);
+ vmw_3d_resource_dec(dev_priv, false);
}
static int vmw_context_init(struct vmw_private *dev_priv,
@@ -226,14 +292,17 @@ static int vmw_context_init(struct vmw_private *dev_priv,
} *cmd;
ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr,
- VMW_RES_CONTEXT, res_free);
+ VMW_RES_CONTEXT, false, res_free, NULL);
if (unlikely(ret != 0)) {
- if (res_free == NULL)
- kfree(res);
- else
- res_free(res);
- return ret;
+ DRM_ERROR("Failed to allocate a resource id.\n");
+ goto out_early;
+ }
+
+ if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) {
+ DRM_ERROR("Out of hw context ids.\n");
+ vmw_resource_unreference(&res);
+ return -ENOMEM;
}
cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
@@ -248,9 +317,16 @@ static int vmw_context_init(struct vmw_private *dev_priv,
cmd->body.cid = cpu_to_le32(res->id);
vmw_fifo_commit(dev_priv, sizeof(*cmd));
- (void) vmw_3d_resource_inc(dev_priv);
+ (void) vmw_3d_resource_inc(dev_priv, false);
vmw_resource_activate(res, vmw_hw_context_destroy);
return 0;
+
+out_early:
+ if (res_free == NULL)
+ kfree(res);
+ else
+ res_free(res);
+ return ret;
}
struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
@@ -273,8 +349,11 @@ static void vmw_user_context_free(struct vmw_resource *res)
{
struct vmw_user_context *ctx =
container_of(res, struct vmw_user_context, res);
+ struct vmw_private *dev_priv = res->dev_priv;
kfree(ctx);
+ ttm_mem_global_free(vmw_mem_glob(dev_priv),
+ vmw_user_context_size);
}
/**
@@ -328,23 +407,56 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct vmw_private *dev_priv = vmw_priv(dev);
- struct vmw_user_context *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+ struct vmw_user_context *ctx;
struct vmw_resource *res;
struct vmw_resource *tmp;
struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+ struct vmw_master *vmaster = vmw_master(file_priv->master);
int ret;
- if (unlikely(ctx == NULL))
- return -ENOMEM;
+
+ /*
+ * Approximate idr memory usage with 128 bytes. It will be limited
+ * by maximum number_of contexts anyway.
+ */
+
+ if (unlikely(vmw_user_context_size == 0))
+ vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
+
+ ret = ttm_read_lock(&vmaster->lock, true);
+ if (unlikely(ret != 0))
+ return ret;
+
+ ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+ vmw_user_context_size,
+ false, true);
+ if (unlikely(ret != 0)) {
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("Out of graphics memory for context"
+ " creation.\n");
+ goto out_unlock;
+ }
+
+ ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+ if (unlikely(ctx == NULL)) {
+ ttm_mem_global_free(vmw_mem_glob(dev_priv),
+ vmw_user_context_size);
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
res = &ctx->res;
ctx->base.shareable = false;
ctx->base.tfile = NULL;
+ /*
+ * From here on, the destructor takes over resource freeing.
+ */
+
ret = vmw_context_init(dev_priv, res, vmw_user_context_free);
if (unlikely(ret != 0))
- return ret;
+ goto out_unlock;
tmp = vmw_resource_reference(&ctx->res);
ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
@@ -358,13 +470,16 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
arg->cid = res->id;
out_err:
vmw_resource_unreference(&res);
+out_unlock:
+ ttm_read_unlock(&vmaster->lock);
return ret;
}
int vmw_context_check(struct vmw_private *dev_priv,
struct ttm_object_file *tfile,
- int id)
+ int id,
+ struct vmw_resource **p_res)
{
struct vmw_resource *res;
int ret = 0;
@@ -376,6 +491,8 @@ int vmw_context_check(struct vmw_private *dev_priv,
container_of(res, struct vmw_user_context, res);
if (ctx->base.tfile != tfile && !ctx->base.shareable)
ret = -EPERM;
+ if (p_res)
+ *p_res = vmw_resource_reference(res);
} else
ret = -EINVAL;
read_unlock(&dev_priv->resource_lock);
@@ -383,102 +500,638 @@ int vmw_context_check(struct vmw_private *dev_priv,
return ret;
}
+struct vmw_bpp {
+ uint8_t bpp;
+ uint8_t s_bpp;
+};
+
+/*
+ * Size table for the supported SVGA3D surface formats. It consists of
+ * two values. The bpp value and the s_bpp value which is short for
+ * "stride bits per pixel" The values are given in such a way that the
+ * minimum stride for the image is calculated using
+ *
+ * min_stride = w*s_bpp
+ *
+ * and the total memory requirement for the image is
+ *
+ * h*min_stride*bpp/s_bpp
+ *
+ */
+static const struct vmw_bpp vmw_sf_bpp[] = {
+ [SVGA3D_FORMAT_INVALID] = {0, 0},
+ [SVGA3D_X8R8G8B8] = {32, 32},
+ [SVGA3D_A8R8G8B8] = {32, 32},
+ [SVGA3D_R5G6B5] = {16, 16},
+ [SVGA3D_X1R5G5B5] = {16, 16},
+ [SVGA3D_A1R5G5B5] = {16, 16},
+ [SVGA3D_A4R4G4B4] = {16, 16},
+ [SVGA3D_Z_D32] = {32, 32},
+ [SVGA3D_Z_D16] = {16, 16},
+ [SVGA3D_Z_D24S8] = {32, 32},
+ [SVGA3D_Z_D15S1] = {16, 16},
+ [SVGA3D_LUMINANCE8] = {8, 8},
+ [SVGA3D_LUMINANCE4_ALPHA4] = {8, 8},
+ [SVGA3D_LUMINANCE16] = {16, 16},
+ [SVGA3D_LUMINANCE8_ALPHA8] = {16, 16},
+ [SVGA3D_DXT1] = {4, 16},
+ [SVGA3D_DXT2] = {8, 32},
+ [SVGA3D_DXT3] = {8, 32},
+ [SVGA3D_DXT4] = {8, 32},
+ [SVGA3D_DXT5] = {8, 32},
+ [SVGA3D_BUMPU8V8] = {16, 16},
+ [SVGA3D_BUMPL6V5U5] = {16, 16},
+ [SVGA3D_BUMPX8L8V8U8] = {32, 32},
+ [SVGA3D_ARGB_S10E5] = {16, 16},
+ [SVGA3D_ARGB_S23E8] = {32, 32},
+ [SVGA3D_A2R10G10B10] = {32, 32},
+ [SVGA3D_V8U8] = {16, 16},
+ [SVGA3D_Q8W8V8U8] = {32, 32},
+ [SVGA3D_CxV8U8] = {16, 16},
+ [SVGA3D_X8L8V8U8] = {32, 32},
+ [SVGA3D_A2W10V10U10] = {32, 32},
+ [SVGA3D_ALPHA8] = {8, 8},
+ [SVGA3D_R_S10E5] = {16, 16},
+ [SVGA3D_R_S23E8] = {32, 32},
+ [SVGA3D_RG_S10E5] = {16, 16},
+ [SVGA3D_RG_S23E8] = {32, 32},
+ [SVGA3D_BUFFER] = {8, 8},
+ [SVGA3D_Z_D24X8] = {32, 32},
+ [SVGA3D_V16U16] = {32, 32},
+ [SVGA3D_G16R16] = {32, 32},
+ [SVGA3D_A16B16G16R16] = {64, 64},
+ [SVGA3D_UYVY] = {12, 12},
+ [SVGA3D_YUY2] = {12, 12},
+ [SVGA3D_NV12] = {12, 8},
+ [SVGA3D_AYUV] = {32, 32},
+ [SVGA3D_BC4_UNORM] = {4, 16},
+ [SVGA3D_BC5_UNORM] = {8, 32},
+ [SVGA3D_Z_DF16] = {16, 16},
+ [SVGA3D_Z_DF24] = {24, 24},
+ [SVGA3D_Z_D24S8_INT] = {32, 32}
+};
+
/**
* Surface management.
*/
+struct vmw_surface_dma {
+ SVGA3dCmdHeader header;
+ SVGA3dCmdSurfaceDMA body;
+ SVGA3dCopyBox cb;
+ SVGA3dCmdSurfaceDMASuffix suffix;
+};
+
+struct vmw_surface_define {
+ SVGA3dCmdHeader header;
+ SVGA3dCmdDefineSurface body;
+};
+
+struct vmw_surface_destroy {
+ SVGA3dCmdHeader header;
+ SVGA3dCmdDestroySurface body;
+};
+
+
+/**
+ * vmw_surface_dma_size - Compute fifo size for a dma command.
+ *
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * Computes the required size for a surface dma command for backup or
+ * restoration of the surface represented by @srf.
+ */
+static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
+{
+ return srf->num_sizes * sizeof(struct vmw_surface_dma);
+}
+
+
+/**
+ * vmw_surface_define_size - Compute fifo size for a surface define command.
+ *
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * Computes the required size for a surface define command for the definition
+ * of the surface represented by @srf.
+ */
+static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
+{
+ return sizeof(struct vmw_surface_define) + srf->num_sizes *
+ sizeof(SVGA3dSize);
+}
+
+
+/**
+ * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
+ *
+ * Computes the required size for a surface destroy command for the destruction
+ * of a hw surface.
+ */
+static inline uint32_t vmw_surface_destroy_size(void)
+{
+ return sizeof(struct vmw_surface_destroy);
+}
+
+/**
+ * vmw_surface_destroy_encode - Encode a surface_destroy command.
+ *
+ * @id: The surface id
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ */
+static void vmw_surface_destroy_encode(uint32_t id,
+ void *cmd_space)
+{
+ struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
+ cmd_space;
+
+ cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
+ cmd->header.size = sizeof(cmd->body);
+ cmd->body.sid = id;
+}
+
+/**
+ * vmw_surface_define_encode - Encode a surface_define command.
+ *
+ * @srf: Pointer to a struct vmw_surface object.
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ */
+static void vmw_surface_define_encode(const struct vmw_surface *srf,
+ void *cmd_space)
+{
+ struct vmw_surface_define *cmd = (struct vmw_surface_define *)
+ cmd_space;
+ struct drm_vmw_size *src_size;
+ SVGA3dSize *cmd_size;
+ uint32_t cmd_len;
+ int i;
+
+ cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
+
+ cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE;
+ cmd->header.size = cmd_len;
+ cmd->body.sid = srf->res.id;
+ cmd->body.surfaceFlags = srf->flags;
+ cmd->body.format = cpu_to_le32(srf->format);
+ for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+ cmd->body.face[i].numMipLevels = srf->mip_levels[i];
+
+ cmd += 1;
+ cmd_size = (SVGA3dSize *) cmd;
+ src_size = srf->sizes;
+
+ for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
+ cmd_size->width = src_size->width;
+ cmd_size->height = src_size->height;
+ cmd_size->depth = src_size->depth;
+ }
+}
+
+
+/**
+ * vmw_surface_dma_encode - Encode a surface_dma command.
+ *
+ * @srf: Pointer to a struct vmw_surface object.
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
+ * should be placed or read from.
+ * @to_surface: Boolean whether to DMA to the surface or from the surface.
+ */
+static void vmw_surface_dma_encode(struct vmw_surface *srf,
+ void *cmd_space,
+ const SVGAGuestPtr *ptr,
+ bool to_surface)
+{
+ uint32_t i;
+ uint32_t bpp = vmw_sf_bpp[srf->format].bpp;
+ uint32_t stride_bpp = vmw_sf_bpp[srf->format].s_bpp;
+ struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
+
+ for (i = 0; i < srf->num_sizes; ++i) {
+ SVGA3dCmdHeader *header = &cmd->header;
+ SVGA3dCmdSurfaceDMA *body = &cmd->body;
+ SVGA3dCopyBox *cb = &cmd->cb;
+ SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
+ const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
+ const struct drm_vmw_size *cur_size = &srf->sizes[i];
+
+ header->id = SVGA_3D_CMD_SURFACE_DMA;
+ header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
+
+ body->guest.ptr = *ptr;
+ body->guest.ptr.offset += cur_offset->bo_offset;
+ body->guest.pitch = (cur_size->width * stride_bpp + 7) >> 3;
+ body->host.sid = srf->res.id;
+ body->host.face = cur_offset->face;
+ body->host.mipmap = cur_offset->mip;
+ body->transfer = ((to_surface) ? SVGA3D_WRITE_HOST_VRAM :
+ SVGA3D_READ_HOST_VRAM);
+ cb->x = 0;
+ cb->y = 0;
+ cb->z = 0;
+ cb->srcx = 0;
+ cb->srcy = 0;
+ cb->srcz = 0;
+ cb->w = cur_size->width;
+ cb->h = cur_size->height;
+ cb->d = cur_size->depth;
+
+ suffix->suffixSize = sizeof(*suffix);
+ suffix->maximumOffset = body->guest.pitch*cur_size->height*
+ cur_size->depth*bpp / stride_bpp;
+ suffix->flags.discard = 0;
+ suffix->flags.unsynchronized = 0;
+ suffix->flags.reserved = 0;
+ ++cmd;
+ }
+};
+
+
static void vmw_hw_surface_destroy(struct vmw_resource *res)
{
struct vmw_private *dev_priv = res->dev_priv;
- struct {
- SVGA3dCmdHeader header;
- SVGA3dCmdDestroySurface body;
- } *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+ struct vmw_surface *srf;
+ void *cmd;
- if (unlikely(cmd == NULL)) {
- DRM_ERROR("Failed reserving FIFO space for surface "
- "destruction.\n");
- return;
- }
+ if (res->id != -1) {
- cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DESTROY);
- cmd->header.size = cpu_to_le32(sizeof(cmd->body));
- cmd->body.sid = cpu_to_le32(res->id);
+ cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("Failed reserving FIFO space for surface "
+ "destruction.\n");
+ return;
+ }
- vmw_fifo_commit(dev_priv, sizeof(*cmd));
- vmw_3d_resource_dec(dev_priv);
+ vmw_surface_destroy_encode(res->id, cmd);
+ vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
+
+ /*
+ * used_memory_size_atomic, or separate lock
+ * to avoid taking dev_priv::cmdbuf_mutex in
+ * the destroy path.
+ */
+
+ mutex_lock(&dev_priv->cmdbuf_mutex);
+ srf = container_of(res, struct vmw_surface, res);
+ dev_priv->used_memory_size -= srf->backup_size;
+ mutex_unlock(&dev_priv->cmdbuf_mutex);
+
+ }
+ vmw_3d_resource_dec(dev_priv, false);
}
void vmw_surface_res_free(struct vmw_resource *res)
{
struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
+ if (srf->backup)
+ ttm_bo_unref(&srf->backup);
+ kfree(srf->offsets);
kfree(srf->sizes);
kfree(srf->snooper.image);
kfree(srf);
}
-int vmw_surface_init(struct vmw_private *dev_priv,
- struct vmw_surface *srf,
- void (*res_free) (struct vmw_resource *res))
+
+/**
+ * vmw_surface_do_validate - make a surface available to the device.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @srf: Pointer to a struct vmw_surface.
+ *
+ * If the surface doesn't have a hw id, allocate one, and optionally
+ * DMA the backed up surface contents to the device.
+ *
+ * Returns -EBUSY if there wasn't sufficient device resources to
+ * complete the validation. Retry after freeing up resources.
+ *
+ * May return other errors if the kernel is out of guest resources.
+ */
+int vmw_surface_do_validate(struct vmw_private *dev_priv,
+ struct vmw_surface *srf)
{
- int ret;
- struct {
- SVGA3dCmdHeader header;
- SVGA3dCmdDefineSurface body;
- } *cmd;
- SVGA3dSize *cmd_size;
struct vmw_resource *res = &srf->res;
- struct drm_vmw_size *src_size;
- size_t submit_size;
- uint32_t cmd_len;
- int i;
+ struct list_head val_list;
+ struct ttm_validate_buffer val_buf;
+ uint32_t submit_size;
+ uint8_t *cmd;
+ int ret;
- BUG_ON(res_free == NULL);
- ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr,
- VMW_RES_SURFACE, res_free);
+ if (likely(res->id != -1))
+ return 0;
+
+ if (unlikely(dev_priv->used_memory_size + srf->backup_size >=
+ dev_priv->memory_size))
+ return -EBUSY;
+
+ /*
+ * Reserve- and validate the backup DMA bo.
+ */
+
+ if (srf->backup) {
+ INIT_LIST_HEAD(&val_list);
+ val_buf.bo = ttm_bo_reference(srf->backup);
+ val_buf.new_sync_obj_arg = (void *)((unsigned long)
+ DRM_VMW_FENCE_FLAG_EXEC);
+ list_add_tail(&val_buf.head, &val_list);
+ ret = ttm_eu_reserve_buffers(&val_list);
+ if (unlikely(ret != 0))
+ goto out_no_reserve;
+
+ ret = ttm_bo_validate(srf->backup, &vmw_srf_placement,
+ true, false, false);
+ if (unlikely(ret != 0))
+ goto out_no_validate;
+ }
+
+ /*
+ * Alloc id for the resource.
+ */
+ ret = vmw_resource_alloc_id(dev_priv, res);
if (unlikely(ret != 0)) {
- res_free(res);
- return ret;
+ DRM_ERROR("Failed to allocate a surface id.\n");
+ goto out_no_id;
+ }
+ if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
+ ret = -EBUSY;
+ goto out_no_fifo;
}
- submit_size = sizeof(*cmd) + srf->num_sizes * sizeof(SVGA3dSize);
- cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
+
+ /*
+ * Encode surface define- and dma commands.
+ */
+
+ submit_size = vmw_surface_define_size(srf);
+ if (srf->backup)
+ submit_size += vmw_surface_dma_size(srf);
cmd = vmw_fifo_reserve(dev_priv, submit_size);
if (unlikely(cmd == NULL)) {
- DRM_ERROR("Fifo reserve failed for create surface.\n");
- vmw_resource_unreference(&res);
- return -ENOMEM;
+ DRM_ERROR("Failed reserving FIFO space for surface "
+ "validation.\n");
+ ret = -ENOMEM;
+ goto out_no_fifo;
}
- cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DEFINE);
- cmd->header.size = cpu_to_le32(cmd_len);
- cmd->body.sid = cpu_to_le32(res->id);
- cmd->body.surfaceFlags = cpu_to_le32(srf->flags);
- cmd->body.format = cpu_to_le32(srf->format);
- for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
- cmd->body.face[i].numMipLevels =
- cpu_to_le32(srf->mip_levels[i]);
+ vmw_surface_define_encode(srf, cmd);
+ if (srf->backup) {
+ SVGAGuestPtr ptr;
+
+ cmd += vmw_surface_define_size(srf);
+ vmw_bo_get_guest_ptr(srf->backup, &ptr);
+ vmw_surface_dma_encode(srf, cmd, &ptr, true);
}
- cmd += 1;
- cmd_size = (SVGA3dSize *) cmd;
- src_size = srf->sizes;
+ vmw_fifo_commit(dev_priv, submit_size);
- for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
- cmd_size->width = cpu_to_le32(src_size->width);
- cmd_size->height = cpu_to_le32(src_size->height);
- cmd_size->depth = cpu_to_le32(src_size->depth);
+ /*
+ * Create a fence object and fence the backup buffer.
+ */
+
+ if (srf->backup) {
+ struct vmw_fence_obj *fence;
+
+ (void) vmw_execbuf_fence_commands(NULL, dev_priv,
+ &fence, NULL);
+ ttm_eu_fence_buffer_objects(&val_list, fence);
+ if (likely(fence != NULL))
+ vmw_fence_obj_unreference(&fence);
+ ttm_bo_unref(&val_buf.bo);
+ ttm_bo_unref(&srf->backup);
+ }
+
+ /*
+ * Surface memory usage accounting.
+ */
+
+ dev_priv->used_memory_size += srf->backup_size;
+
+ return 0;
+
+out_no_fifo:
+ vmw_resource_release_id(res);
+out_no_id:
+out_no_validate:
+ if (srf->backup)
+ ttm_eu_backoff_reservation(&val_list);
+out_no_reserve:
+ if (srf->backup)
+ ttm_bo_unref(&val_buf.bo);
+ return ret;
+}
+
+/**
+ * vmw_surface_evict - Evict a hw surface.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * DMA the contents of a hw surface to a backup guest buffer object,
+ * and destroy the hw surface, releasing its id.
+ */
+int vmw_surface_evict(struct vmw_private *dev_priv,
+ struct vmw_surface *srf)
+{
+ struct vmw_resource *res = &srf->res;
+ struct list_head val_list;
+ struct ttm_validate_buffer val_buf;
+ uint32_t submit_size;
+ uint8_t *cmd;
+ int ret;
+ struct vmw_fence_obj *fence;
+ SVGAGuestPtr ptr;
+
+ BUG_ON(res->id == -1);
+
+ /*
+ * Create a surface backup buffer object.
+ */
+
+ if (!srf->backup) {
+ ret = ttm_bo_create(&dev_priv->bdev, srf->backup_size,
+ ttm_bo_type_device,
+ &vmw_srf_placement, 0, 0, true,
+ NULL, &srf->backup);
+ if (unlikely(ret != 0))
+ return ret;
+ }
+
+ /*
+ * Reserve- and validate the backup DMA bo.
+ */
+
+ INIT_LIST_HEAD(&val_list);
+ val_buf.bo = ttm_bo_reference(srf->backup);
+ val_buf.new_sync_obj_arg = (void *)(unsigned long)
+ DRM_VMW_FENCE_FLAG_EXEC;
+ list_add_tail(&val_buf.head, &val_list);
+ ret = ttm_eu_reserve_buffers(&val_list);
+ if (unlikely(ret != 0))
+ goto out_no_reserve;
+
+ ret = ttm_bo_validate(srf->backup, &vmw_srf_placement,
+ true, false, false);
+ if (unlikely(ret != 0))
+ goto out_no_validate;
+
+
+ /*
+ * Encode the dma- and surface destroy commands.
+ */
+
+ submit_size = vmw_surface_dma_size(srf) + vmw_surface_destroy_size();
+ cmd = vmw_fifo_reserve(dev_priv, submit_size);
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("Failed reserving FIFO space for surface "
+ "eviction.\n");
+ ret = -ENOMEM;
+ goto out_no_fifo;
}
+ vmw_bo_get_guest_ptr(srf->backup, &ptr);
+ vmw_surface_dma_encode(srf, cmd, &ptr, false);
+ cmd += vmw_surface_dma_size(srf);
+ vmw_surface_destroy_encode(res->id, cmd);
vmw_fifo_commit(dev_priv, submit_size);
- (void) vmw_3d_resource_inc(dev_priv);
- vmw_resource_activate(res, vmw_hw_surface_destroy);
+
+ /*
+ * Surface memory usage accounting.
+ */
+
+ dev_priv->used_memory_size -= srf->backup_size;
+
+ /*
+ * Create a fence object and fence the DMA buffer.
+ */
+
+ (void) vmw_execbuf_fence_commands(NULL, dev_priv,
+ &fence, NULL);
+ ttm_eu_fence_buffer_objects(&val_list, fence);
+ if (likely(fence != NULL))
+ vmw_fence_obj_unreference(&fence);
+ ttm_bo_unref(&val_buf.bo);
+
+ /*
+ * Release the surface ID.
+ */
+
+ vmw_resource_release_id(res);
+
return 0;
+
+out_no_fifo:
+out_no_validate:
+ if (srf->backup)
+ ttm_eu_backoff_reservation(&val_list);
+out_no_reserve:
+ ttm_bo_unref(&val_buf.bo);
+ ttm_bo_unref(&srf->backup);
+ return ret;
+}
+
+
+/**
+ * vmw_surface_validate - make a surface available to the device, evicting
+ * other surfaces if needed.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @srf: Pointer to a struct vmw_surface.
+ *
+ * Try to validate a surface and if it fails due to limited device resources,
+ * repeatedly try to evict other surfaces until the request can be
+ * acommodated.
+ *
+ * May return errors if out of resources.
+ */
+int vmw_surface_validate(struct vmw_private *dev_priv,
+ struct vmw_surface *srf)
+{
+ int ret;
+ struct vmw_surface *evict_srf;
+
+ do {
+ write_lock(&dev_priv->resource_lock);
+ list_del_init(&srf->lru_head);
+ write_unlock(&dev_priv->resource_lock);
+
+ ret = vmw_surface_do_validate(dev_priv, srf);
+ if (likely(ret != -EBUSY))
+ break;
+
+ write_lock(&dev_priv->resource_lock);
+ if (list_empty(&dev_priv->surface_lru)) {
+ DRM_ERROR("Out of device memory for surfaces.\n");
+ ret = -EBUSY;
+ write_unlock(&dev_priv->resource_lock);
+ break;
+ }
+
+ evict_srf = vmw_surface_reference
+ (list_first_entry(&dev_priv->surface_lru,
+ struct vmw_surface,
+ lru_head));
+ list_del_init(&evict_srf->lru_head);
+
+ write_unlock(&dev_priv->resource_lock);
+ (void) vmw_surface_evict(dev_priv, evict_srf);
+
+ vmw_surface_unreference(&evict_srf);
+
+ } while (1);
+
+ if (unlikely(ret != 0 && srf->res.id != -1)) {
+ write_lock(&dev_priv->resource_lock);
+ list_add_tail(&srf->lru_head, &dev_priv->surface_lru);
+ write_unlock(&dev_priv->resource_lock);
+ }
+
+ return ret;
+}
+
+
+/**
+ * vmw_surface_remove_from_lists - Remove surface resources from lookup lists
+ *
+ * @res: Pointer to a struct vmw_resource embedded in a struct vmw_surface
+ *
+ * As part of the resource destruction, remove the surface from any
+ * lookup lists.
+ */
+static void vmw_surface_remove_from_lists(struct vmw_resource *res)
+{
+ struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
+
+ list_del_init(&srf->lru_head);
+}
+
+int vmw_surface_init(struct vmw_private *dev_priv,
+ struct vmw_surface *srf,
+ void (*res_free) (struct vmw_resource *res))
+{
+ int ret;
+ struct vmw_resource *res = &srf->res;
+
+ BUG_ON(res_free == NULL);
+ INIT_LIST_HEAD(&srf->lru_head);
+ ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr,
+ VMW_RES_SURFACE, true, res_free,
+ vmw_surface_remove_from_lists);
+
+ if (unlikely(ret != 0))
+ res_free(res);
+
+ /*
+ * The surface won't be visible to hardware until a
+ * surface validate.
+ */
+
+ (void) vmw_3d_resource_inc(dev_priv, false);
+ vmw_resource_activate(res, vmw_hw_surface_destroy);
+ return ret;
}
static void vmw_user_surface_free(struct vmw_resource *res)
@@ -486,12 +1139,58 @@ static void vmw_user_surface_free(struct vmw_resource *res)
struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
struct vmw_user_surface *user_srf =
container_of(srf, struct vmw_user_surface, srf);
+ struct vmw_private *dev_priv = srf->res.dev_priv;
+ uint32_t size = user_srf->size;
+ if (srf->backup)
+ ttm_bo_unref(&srf->backup);
+ kfree(srf->offsets);
kfree(srf->sizes);
kfree(srf->snooper.image);
kfree(user_srf);
+ ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+}
+
+/**
+ * vmw_resource_unreserve - unreserve resources previously reserved for
+ * command submission.
+ *
+ * @list_head: list of resources to unreserve.
+ *
+ * Currently only surfaces are considered, and unreserving a surface
+ * means putting it back on the device's surface lru list,
+ * so that it can be evicted if necessary.
+ * This function traverses the resource list and
+ * checks whether resources are surfaces, and in that case puts them back
+ * on the device's surface LRU list.
+ */
+void vmw_resource_unreserve(struct list_head *list)
+{
+ struct vmw_resource *res;
+ struct vmw_surface *srf;
+ rwlock_t *lock = NULL;
+
+ list_for_each_entry(res, list, validate_head) {
+
+ if (res->res_free != &vmw_surface_res_free &&
+ res->res_free != &vmw_user_surface_free)
+ continue;
+
+ if (unlikely(lock == NULL)) {
+ lock = &res->dev_priv->resource_lock;
+ write_lock(lock);
+ }
+
+ srf = container_of(res, struct vmw_surface, res);
+ list_del_init(&srf->lru_head);
+ list_add_tail(&srf->lru_head, &res->dev_priv->surface_lru);
+ }
+
+ if (lock != NULL)
+ write_unlock(lock);
}
+
int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
struct ttm_object_file *tfile,
uint32_t handle, struct vmw_surface **out)
@@ -556,8 +1255,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct vmw_private *dev_priv = vmw_priv(dev);
- struct vmw_user_surface *user_srf =
- kmalloc(sizeof(*user_srf), GFP_KERNEL);
+ struct vmw_user_surface *user_srf;
struct vmw_surface *srf;
struct vmw_resource *res;
struct vmw_resource *tmp;
@@ -568,10 +1266,51 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
struct drm_vmw_size __user *user_sizes;
int ret;
- int i;
+ int i, j;
+ uint32_t cur_bo_offset;
+ struct drm_vmw_size *cur_size;
+ struct vmw_surface_offset *cur_offset;
+ uint32_t stride_bpp;
+ uint32_t bpp;
+ uint32_t num_sizes;
+ uint32_t size;
+ struct vmw_master *vmaster = vmw_master(file_priv->master);
- if (unlikely(user_srf == NULL))
- return -ENOMEM;
+ if (unlikely(vmw_user_surface_size == 0))
+ vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
+ 128;
+
+ num_sizes = 0;
+ for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+ num_sizes += req->mip_levels[i];
+
+ if (num_sizes > DRM_VMW_MAX_SURFACE_FACES *
+ DRM_VMW_MAX_MIP_LEVELS)
+ return -EINVAL;
+
+ size = vmw_user_surface_size + 128 +
+ ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
+ ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
+
+
+ ret = ttm_read_lock(&vmaster->lock, true);
+ if (unlikely(ret != 0))
+ return ret;
+
+ ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+ size, false, true);
+ if (unlikely(ret != 0)) {
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("Out of graphics memory for surface"
+ " creation.\n");
+ goto out_unlock;
+ }
+
+ user_srf = kmalloc(sizeof(*user_srf), GFP_KERNEL);
+ if (unlikely(user_srf == NULL)) {
+ ret = -ENOMEM;
+ goto out_no_user_srf;
+ }
srf = &user_srf->srf;
res = &srf->res;
@@ -579,21 +1318,22 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
srf->flags = req->flags;
srf->format = req->format;
srf->scanout = req->scanout;
- memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
- srf->num_sizes = 0;
- for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
- srf->num_sizes += srf->mip_levels[i];
+ srf->backup = NULL;
- if (srf->num_sizes > DRM_VMW_MAX_SURFACE_FACES *
- DRM_VMW_MAX_MIP_LEVELS) {
- ret = -EINVAL;
- goto out_err0;
- }
+ memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
+ srf->num_sizes = num_sizes;
+ user_srf->size = size;
srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
if (unlikely(srf->sizes == NULL)) {
ret = -ENOMEM;
- goto out_err0;
+ goto out_no_sizes;
+ }
+ srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets),
+ GFP_KERNEL);
+ if (unlikely(srf->sizes == NULL)) {
+ ret = -ENOMEM;
+ goto out_no_offsets;
}
user_sizes = (struct drm_vmw_size __user *)(unsigned long)
@@ -603,9 +1343,32 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
srf->num_sizes * sizeof(*srf->sizes));
if (unlikely(ret != 0)) {
ret = -EFAULT;
- goto out_err1;
+ goto out_no_copy;
}
+ cur_bo_offset = 0;
+ cur_offset = srf->offsets;
+ cur_size = srf->sizes;
+
+ bpp = vmw_sf_bpp[srf->format].bpp;
+ stride_bpp = vmw_sf_bpp[srf->format].s_bpp;
+
+ for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
+ for (j = 0; j < srf->mip_levels[i]; ++j) {
+ uint32_t stride =
+ (cur_size->width * stride_bpp + 7) >> 3;
+
+ cur_offset->face = i;
+ cur_offset->mip = j;
+ cur_offset->bo_offset = cur_bo_offset;
+ cur_bo_offset += stride * cur_size->height *
+ cur_size->depth * bpp / stride_bpp;
+ ++cur_offset;
+ ++cur_size;
+ }
+ }
+ srf->backup_size = cur_bo_offset;
+
if (srf->scanout &&
srf->num_sizes == 1 &&
srf->sizes[0].width == 64 &&
@@ -617,7 +1380,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
if (!srf->snooper.image) {
DRM_ERROR("Failed to allocate cursor_image\n");
ret = -ENOMEM;
- goto out_err1;
+ goto out_no_copy;
}
} else {
srf->snooper.image = NULL;
@@ -634,7 +1397,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
if (unlikely(ret != 0))
- return ret;
+ goto out_unlock;
tmp = vmw_resource_reference(&srf->res);
ret = ttm_base_object_init(tfile, &user_srf->base,
@@ -644,7 +1407,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
if (unlikely(ret != 0)) {
vmw_resource_unreference(&tmp);
vmw_resource_unreference(&res);
- return ret;
+ goto out_unlock;
}
rep->sid = user_srf->base.hash.key;
@@ -652,11 +1415,19 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
DRM_ERROR("Created bad Surface ID.\n");
vmw_resource_unreference(&res);
+
+ ttm_read_unlock(&vmaster->lock);
return 0;
-out_err1:
+out_no_copy:
+ kfree(srf->offsets);
+out_no_offsets:
kfree(srf->sizes);
-out_err0:
+out_no_sizes:
kfree(user_srf);
+out_no_user_srf:
+ ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+out_unlock:
+ ttm_read_unlock(&vmaster->lock);
return ret;
}
@@ -970,7 +1741,7 @@ static int vmw_stream_init(struct vmw_private *dev_priv,
int ret;
ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr,
- VMW_RES_STREAM, res_free);
+ VMW_RES_STREAM, false, res_free, NULL);
if (unlikely(ret != 0)) {
if (res_free == NULL)
@@ -1000,8 +1771,11 @@ static void vmw_user_stream_free(struct vmw_resource *res)
{
struct vmw_user_stream *stream =
container_of(res, struct vmw_user_stream, stream.res);
+ struct vmw_private *dev_priv = res->dev_priv;
kfree(stream);
+ ttm_mem_global_free(vmw_mem_glob(dev_priv),
+ vmw_user_stream_size);
}
/**
@@ -1055,23 +1829,56 @@ int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct vmw_private *dev_priv = vmw_priv(dev);
- struct vmw_user_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL);
+ struct vmw_user_stream *stream;
struct vmw_resource *res;
struct vmw_resource *tmp;
struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+ struct vmw_master *vmaster = vmw_master(file_priv->master);
int ret;
- if (unlikely(stream == NULL))
- return -ENOMEM;
+ /*
+ * Approximate idr memory usage with 128 bytes. It will be limited
+ * by maximum number_of streams anyway?
+ */
+
+ if (unlikely(vmw_user_stream_size == 0))
+ vmw_user_stream_size = ttm_round_pot(sizeof(*stream)) + 128;
+
+ ret = ttm_read_lock(&vmaster->lock, true);
+ if (unlikely(ret != 0))
+ return ret;
+
+ ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+ vmw_user_stream_size,
+ false, true);
+ if (unlikely(ret != 0)) {
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("Out of graphics memory for stream"
+ " creation.\n");
+ goto out_unlock;
+ }
+
+
+ stream = kmalloc(sizeof(*stream), GFP_KERNEL);
+ if (unlikely(stream == NULL)) {
+ ttm_mem_global_free(vmw_mem_glob(dev_priv),
+ vmw_user_stream_size);
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
res = &stream->stream.res;
stream->base.shareable = false;
stream->base.tfile = NULL;
+ /*
+ * From here on, the destructor takes over resource freeing.
+ */
+
ret = vmw_stream_init(dev_priv, &stream->stream, vmw_user_stream_free);
if (unlikely(ret != 0))
- return ret;
+ goto out_unlock;
tmp = vmw_resource_reference(res);
ret = ttm_base_object_init(tfile, &stream->base, false, VMW_RES_STREAM,
@@ -1085,6 +1892,8 @@ int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
arg->stream_id = res->id;
out_err:
vmw_resource_unreference(&res);
+out_unlock:
+ ttm_read_unlock(&vmaster->lock);
return ret;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
new file mode 100644
index 000000000000..477b2a9eb3c2
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -0,0 +1,567 @@
+/**************************************************************************
+ *
+ * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_kms.h"
+
+
+#define vmw_crtc_to_sou(x) \
+ container_of(x, struct vmw_screen_object_unit, base.crtc)
+#define vmw_encoder_to_sou(x) \
+ container_of(x, struct vmw_screen_object_unit, base.encoder)
+#define vmw_connector_to_sou(x) \
+ container_of(x, struct vmw_screen_object_unit, base.connector)
+
+struct vmw_screen_object_display {
+ struct list_head active;
+
+ unsigned num_active;
+ unsigned last_num_active;
+
+ struct vmw_framebuffer *fb;
+};
+
+/**
+ * Display unit using screen objects.
+ */
+struct vmw_screen_object_unit {
+ struct vmw_display_unit base;
+
+ unsigned long buffer_size; /**< Size of allocated buffer */
+ struct vmw_dma_buffer *buffer; /**< Backing store buffer */
+
+ bool defined;
+
+ struct list_head active;
+};
+
+static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
+{
+ list_del_init(&sou->active);
+ vmw_display_unit_cleanup(&sou->base);
+ kfree(sou);
+}
+
+
+/*
+ * Screen Object Display Unit CRTC functions
+ */
+
+static void vmw_sou_crtc_destroy(struct drm_crtc *crtc)
+{
+ vmw_sou_destroy(vmw_crtc_to_sou(crtc));
+}
+
+static int vmw_sou_del_active(struct vmw_private *vmw_priv,
+ struct vmw_screen_object_unit *sou)
+{
+ struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
+ if (list_empty(&sou->active))
+ return 0;
+
+ /* Must init otherwise list_empty(&sou->active) will not work. */
+ list_del_init(&sou->active);
+ if (--(ld->num_active) == 0) {
+ BUG_ON(!ld->fb);
+ if (ld->fb->unpin)
+ ld->fb->unpin(ld->fb);
+ ld->fb = NULL;
+ }
+
+ return 0;
+}
+
+static int vmw_sou_add_active(struct vmw_private *vmw_priv,
+ struct vmw_screen_object_unit *sou,
+ struct vmw_framebuffer *vfb)
+{
+ struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
+ struct vmw_screen_object_unit *entry;
+ struct list_head *at;
+
+ BUG_ON(!ld->num_active && ld->fb);
+ if (vfb != ld->fb) {
+ if (ld->fb && ld->fb->unpin)
+ ld->fb->unpin(ld->fb);
+ if (vfb->pin)
+ vfb->pin(vfb);
+ ld->fb = vfb;
+ }
+
+ if (!list_empty(&sou->active))
+ return 0;
+
+ at = &ld->active;
+ list_for_each_entry(entry, &ld->active, active) {
+ if (entry->base.unit > sou->base.unit)
+ break;
+
+ at = &entry->active;
+ }
+
+ list_add(&sou->active, at);
+
+ ld->num_active++;
+
+ return 0;
+}
+
+/**
+ * Send the fifo command to create a screen.
+ */
+static int vmw_sou_fifo_create(struct vmw_private *dev_priv,
+ struct vmw_screen_object_unit *sou,
+ uint32_t x, uint32_t y,
+ struct drm_display_mode *mode)
+{
+ size_t fifo_size;
+
+ struct {
+ struct {
+ uint32_t cmdType;
+ } header;
+ SVGAScreenObject obj;
+ } *cmd;
+
+ BUG_ON(!sou->buffer);
+
+ fifo_size = sizeof(*cmd);
+ cmd = vmw_fifo_reserve(dev_priv, fifo_size);
+ /* The hardware has hung, nothing we can do about it here. */
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("Fifo reserve failed.\n");
+ return -ENOMEM;
+ }
+
+ memset(cmd, 0, fifo_size);
+ cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN;
+ cmd->obj.structSize = sizeof(SVGAScreenObject);
+ cmd->obj.id = sou->base.unit;
+ cmd->obj.flags = SVGA_SCREEN_HAS_ROOT |
+ (sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0);
+ cmd->obj.size.width = mode->hdisplay;
+ cmd->obj.size.height = mode->vdisplay;
+ cmd->obj.root.x = x;
+ cmd->obj.root.y = y;
+
+ /* Ok to assume that buffer is pinned in vram */
+ vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
+ cmd->obj.backingStore.pitch = mode->hdisplay * 4;
+
+ vmw_fifo_commit(dev_priv, fifo_size);
+
+ sou->defined = true;
+
+ return 0;
+}
+
+/**
+ * Send the fifo command to destroy a screen.
+ */
+static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
+ struct vmw_screen_object_unit *sou)
+{
+ size_t fifo_size;
+ int ret;
+
+ struct {
+ struct {
+ uint32_t cmdType;
+ } header;
+ SVGAFifoCmdDestroyScreen body;
+ } *cmd;
+
+ /* no need to do anything */
+ if (unlikely(!sou->defined))
+ return 0;
+
+ fifo_size = sizeof(*cmd);
+ cmd = vmw_fifo_reserve(dev_priv, fifo_size);
+ /* the hardware has hung, nothing we can do about it here */
+ if (unlikely(cmd == NULL)) {
+ DRM_ERROR("Fifo reserve failed.\n");
+ return -ENOMEM;
+ }
+
+ memset(cmd, 0, fifo_size);
+ cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN;
+ cmd->body.screenId = sou->base.unit;
+
+ vmw_fifo_commit(dev_priv, fifo_size);
+
+ /* Force sync */
+ ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
+ if (unlikely(ret != 0))
+ DRM_ERROR("Failed to sync with HW");
+ else
+ sou->defined = false;
+
+ return ret;
+}
+
+/**
+ * Free the backing store.
+ */
+static void vmw_sou_backing_free(struct vmw_private *dev_priv,
+ struct vmw_screen_object_unit *sou)
+{
+ struct ttm_buffer_object *bo;
+
+ if (unlikely(sou->buffer == NULL))
+ return;
+
+ bo = &sou->buffer->base;
+ ttm_bo_unref(&bo);
+ sou->buffer = NULL;
+ sou->buffer_size = 0;
+}
+
+/**
+ * Allocate the backing store for the buffer.
+ */
+static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
+ struct vmw_screen_object_unit *sou,
+ unsigned long size)
+{
+ int ret;
+
+ if (sou->buffer_size == size)
+ return 0;
+
+ if (sou->buffer)
+ vmw_sou_backing_free(dev_priv, sou);
+
+ sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL);
+ if (unlikely(sou->buffer == NULL))
+ return -ENOMEM;
+
+ /* After we have alloced the backing store might not be able to
+ * resume the overlays, this is preferred to failing to alloc.
+ */
+ vmw_overlay_pause_all(dev_priv);
+ ret = vmw_dmabuf_init(dev_priv, sou->buffer, size,
+ &vmw_vram_ne_placement,
+ false, &vmw_dmabuf_bo_free);
+ vmw_overlay_resume_all(dev_priv);
+
+ if (unlikely(ret != 0))
+ sou->buffer = NULL; /* vmw_dmabuf_init frees on error */
+ else
+ sou->buffer_size = size;
+
+ return ret;
+}
+
+static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
+{
+ struct vmw_private *dev_priv;
+ struct vmw_screen_object_unit *sou;
+ struct drm_connector *connector;
+ struct drm_display_mode *mode;
+ struct drm_encoder *encoder;
+ struct vmw_framebuffer *vfb;
+ struct drm_framebuffer *fb;
+ struct drm_crtc *crtc;
+ int ret = 0;
+
+ if (!set)
+ return -EINVAL;
+
+ if (!set->crtc)
+ return -EINVAL;
+
+ /* get the sou */
+ crtc = set->crtc;
+ sou = vmw_crtc_to_sou(crtc);
+ vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
+ dev_priv = vmw_priv(crtc->dev);
+
+ if (set->num_connectors > 1) {
+ DRM_ERROR("to many connectors\n");
+ return -EINVAL;
+ }
+
+ if (set->num_connectors == 1 &&
+ set->connectors[0] != &sou->base.connector) {
+ DRM_ERROR("connector doesn't match %p %p\n",
+ set->connectors[0], &sou->base.connector);
+ return -EINVAL;
+ }
+
+ /* sou only supports one fb active at the time */
+ if (dev_priv->sou_priv->fb && vfb &&
+ !(dev_priv->sou_priv->num_active == 1 &&
+ !list_empty(&sou->active)) &&
+ dev_priv->sou_priv->fb != vfb) {
+ DRM_ERROR("Multiple framebuffers not supported\n");
+ return -EINVAL;
+ }
+
+ /* since they always map one to one these are safe */
+ connector = &sou->base.connector;
+ encoder = &sou->base.encoder;
+
+ /* should we turn the crtc off */
+ if (set->num_connectors == 0 || !set->mode || !set->fb) {
+ ret = vmw_sou_fifo_destroy(dev_priv, sou);
+ /* the hardware has hung don't do anything more */
+ if (unlikely(ret != 0))
+ return ret;
+
+ connector->encoder = NULL;
+ encoder->crtc = NULL;
+ crtc->fb = NULL;
+ crtc->x = 0;
+ crtc->y = 0;
+
+ vmw_sou_del_active(dev_priv, sou);
+
+ vmw_sou_backing_free(dev_priv, sou);
+
+ return 0;
+ }
+
+
+ /* we now know we want to set a mode */
+ mode = set->mode;
+ fb = set->fb;
+
+ if (set->x + mode->hdisplay > fb->width ||
+ set->y + mode->vdisplay > fb->height) {
+ DRM_ERROR("set outside of framebuffer\n");
+ return -EINVAL;
+ }
+
+ vmw_fb_off(dev_priv);
+
+ if (mode->hdisplay != crtc->mode.hdisplay ||
+ mode->vdisplay != crtc->mode.vdisplay) {
+ /* no need to check if depth is different, because backing
+ * store depth is forced to 4 by the device.
+ */
+
+ ret = vmw_sou_fifo_destroy(dev_priv, sou);
+ /* the hardware has hung don't do anything more */
+ if (unlikely(ret != 0))
+ return ret;
+
+ vmw_sou_backing_free(dev_priv, sou);
+ }
+
+ if (!sou->buffer) {
+ /* forced to depth 4 by the device */
+ size_t size = mode->hdisplay * mode->vdisplay * 4;
+ ret = vmw_sou_backing_alloc(dev_priv, sou, size);
+ if (unlikely(ret != 0))
+ return ret;
+ }
+
+ ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode);
+ if (unlikely(ret != 0)) {
+ /*
+ * We are in a bit of a situation here, the hardware has
+ * hung and we may or may not have a buffer hanging of
+ * the screen object, best thing to do is not do anything
+ * if we where defined, if not just turn the crtc of.
+ * Not what userspace wants but it needs to htfu.
+ */
+ if (sou->defined)
+ return ret;
+
+ connector->encoder = NULL;
+ encoder->crtc = NULL;
+ crtc->fb = NULL;
+ crtc->x = 0;
+ crtc->y = 0;
+
+ return ret;
+ }
+
+ vmw_sou_add_active(dev_priv, sou, vfb);
+
+ connector->encoder = encoder;
+ encoder->crtc = crtc;
+ crtc->mode = *mode;
+ crtc->fb = fb;
+ crtc->x = set->x;
+ crtc->y = set->y;
+
+ return 0;
+}
+
+static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
+ .save = vmw_du_crtc_save,
+ .restore = vmw_du_crtc_restore,
+ .cursor_set = vmw_du_crtc_cursor_set,
+ .cursor_move = vmw_du_crtc_cursor_move,
+ .gamma_set = vmw_du_crtc_gamma_set,
+ .destroy = vmw_sou_crtc_destroy,
+ .set_config = vmw_sou_crtc_set_config,
+};
+
+/*
+ * Screen Object Display Unit encoder functions
+ */
+
+static void vmw_sou_encoder_destroy(struct drm_encoder *encoder)
+{
+ vmw_sou_destroy(vmw_encoder_to_sou(encoder));
+}
+
+static struct drm_encoder_funcs vmw_screen_object_encoder_funcs = {
+ .destroy = vmw_sou_encoder_destroy,
+};
+
+/*
+ * Screen Object Display Unit connector functions
+ */
+
+static void vmw_sou_connector_destroy(struct drm_connector *connector)
+{
+ vmw_sou_destroy(vmw_connector_to_sou(connector));
+}
+
+static struct drm_connector_funcs vmw_legacy_connector_funcs = {
+ .dpms = vmw_du_connector_dpms,
+ .save = vmw_du_connector_save,
+ .restore = vmw_du_connector_restore,
+ .detect = vmw_du_connector_detect,
+ .fill_modes = vmw_du_connector_fill_modes,
+ .set_property = vmw_du_connector_set_property,
+ .destroy = vmw_sou_connector_destroy,
+};
+
+static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
+{
+ struct vmw_screen_object_unit *sou;
+ struct drm_device *dev = dev_priv->dev;
+ struct drm_connector *connector;
+ struct drm_encoder *encoder;
+ struct drm_crtc *crtc;
+
+ sou = kzalloc(sizeof(*sou), GFP_KERNEL);
+ if (!sou)
+ return -ENOMEM;
+
+ sou->base.unit = unit;
+ crtc = &sou->base.crtc;
+ encoder = &sou->base.encoder;
+ connector = &sou->base.connector;
+
+ INIT_LIST_HEAD(&sou->active);
+
+ sou->base.pref_active = (unit == 0);
+ sou->base.pref_width = 800;
+ sou->base.pref_height = 600;
+ sou->base.pref_mode = NULL;
+
+ drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
+ DRM_MODE_CONNECTOR_LVDS);
+ connector->status = vmw_du_connector_detect(connector, true);
+
+ drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
+ DRM_MODE_ENCODER_LVDS);
+ drm_mode_connector_attach_encoder(connector, encoder);
+ encoder->possible_crtcs = (1 << unit);
+ encoder->possible_clones = 0;
+
+ drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
+
+ drm_mode_crtc_set_gamma_size(crtc, 256);
+
+ drm_connector_attach_property(connector,
+ dev->mode_config.dirty_info_property,
+ 1);
+
+ return 0;
+}
+
+int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv)
+{
+ struct drm_device *dev = dev_priv->dev;
+ int i, ret;
+
+ if (dev_priv->sou_priv) {
+ DRM_INFO("sou system already on\n");
+ return -EINVAL;
+ }
+
+ if (!(dev_priv->fifo.capabilities & SVGA_FIFO_CAP_SCREEN_OBJECT_2)) {
+ DRM_INFO("Not using screen objects,"
+ " missing cap SCREEN_OBJECT_2\n");
+ return -ENOSYS;
+ }
+
+ ret = -ENOMEM;
+ dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL);
+ if (unlikely(!dev_priv->sou_priv))
+ goto err_no_mem;
+
+ INIT_LIST_HEAD(&dev_priv->sou_priv->active);
+ dev_priv->sou_priv->num_active = 0;
+ dev_priv->sou_priv->last_num_active = 0;
+ dev_priv->sou_priv->fb = NULL;
+
+ ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
+ if (unlikely(ret != 0))
+ goto err_free;
+
+ ret = drm_mode_create_dirty_info_property(dev);
+ if (unlikely(ret != 0))
+ goto err_vblank_cleanup;
+
+ for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
+ vmw_sou_init(dev_priv, i);
+
+ DRM_INFO("Screen objects system initialized\n");
+
+ return 0;
+
+err_vblank_cleanup:
+ drm_vblank_cleanup(dev);
+err_free:
+ kfree(dev_priv->sou_priv);
+ dev_priv->sou_priv = NULL;
+err_no_mem:
+ return ret;
+}
+
+int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv)
+{
+ struct drm_device *dev = dev_priv->dev;
+
+ if (!dev_priv->sou_priv)
+ return -ENOSYS;
+
+ drm_vblank_cleanup(dev);
+
+ if (!list_empty(&dev_priv->sou_priv->active))
+ DRM_ERROR("Still have active outputs when unloading driver");
+
+ kfree(dev_priv->sou_priv);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
index 1e8eedd901e0..d3c11f5184f3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
@@ -34,9 +34,8 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma)
struct vmw_private *dev_priv;
if (unlikely(vma->vm_pgoff < VMWGFX_FILE_PAGE_OFFSET)) {
- if (vmw_fifo_mmap(filp, vma) == 0)
- return 0;
- return drm_mmap(filp, vma);
+ DRM_ERROR("Illegal attempt to mmap old fifo space.\n");
+ return -EINVAL;
}
file_priv = filp->private_data;
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 1130a8987125..22a4a051f221 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -69,7 +69,7 @@ config HID_ACRUX
Say Y here if you want to enable support for ACRUX game controllers.
config HID_ACRUX_FF
- tristate "ACRUX force feedback support"
+ bool "ACRUX force feedback support"
depends on HID_ACRUX
select INPUT_FF_MEMLESS
---help---
@@ -245,6 +245,15 @@ config HID_LOGITECH
---help---
Support for Logitech devices that are not fully compliant with HID standard.
+config HID_LOGITECH_DJ
+ tristate "Logitech Unifying receivers full support"
+ depends on HID_LOGITECH
+ default m
+ ---help---
+ Say Y if you want support for Logitech Unifying receivers and devices.
+ Unifying receivers are capable of pairing up to 6 Logitech compliant
+ devices to the same receiver.
+
config LOGITECH_FF
bool "Logitech force feedback support"
depends on HID_LOGITECH
@@ -278,13 +287,21 @@ config LOGIG940_FF
Say Y here if you want to enable force feedback support for Logitech
Flight System G940 devices.
-config LOGIWII_FF
- bool "Logitech Speed Force Wireless force feedback support"
+config LOGIWHEELS_FF
+ bool "Logitech wheels configuration and force feedback support"
depends on HID_LOGITECH
select INPUT_FF_MEMLESS
+ default LOGITECH_FF
help
- Say Y here if you want to enable force feedback support for Logitech
- Speed Force Wireless (Wii) devices.
+ Say Y here if you want to enable force feedback and range setting
+ support for following Logitech wheels:
+ - Logitech Driving Force
+ - Logitech Driving Force Pro
+ - Logitech Driving Force GT
+ - Logitech G25
+ - Logitech G27
+ - Logitech MOMO/MOMO 2
+ - Logitech Formula Force EX
config HID_MAGICMOUSE
tristate "Apple MagicMouse multi-touch support"
@@ -328,6 +345,7 @@ config HID_MULTITOUCH
- Hanvon dual touch panels
- Ilitek dual touch panels
- IrTouch Infrared USB panels
+ - LG Display panels (Dell ST2220Tc)
- Lumio CrystalTouch panels
- MosArt dual-touch panels
- PenMount dual touch panels
@@ -441,6 +459,13 @@ config HID_PICOLCD_LEDS
---help---
Provide access to PicoLCD's GPO pins via leds class.
+config HID_PRIMAX
+ tristate "Primax non-fully HID-compliant devices"
+ depends on USB_HID
+ ---help---
+ Support for Primax devices that are not fully compliant with the
+ HID standard.
+
config HID_QUANTA
tristate "Quanta Optical Touch panels"
depends on USB_HID
@@ -539,7 +564,11 @@ config HID_SMARTJOYPLUS
tristate "SmartJoy PLUS PS2/USB adapter support"
depends on USB_HID
---help---
- Support for SmartJoy PLUS PS2/USB adapter.
+ Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box,
+ Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro.
+
+ Note that DDR (Dance Dance Revolution) mode is not supported, nor
+ is pressure sensitive buttons on the pro models.
config SMARTJOYPLUS_FF
bool "SmartJoy PLUS PS2/USB adapter force feedback support"
@@ -590,6 +619,7 @@ config HID_WIIMOTE
tristate "Nintendo Wii Remote support"
depends on BT_HIDP
depends on LEDS_CLASS
+ select POWER_SUPPLY
---help---
Support for the Nintendo Wii Remote bluetooth device.
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 0a0a38e9fd28..1e0d2a638b28 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -21,7 +21,7 @@ endif
ifdef CONFIG_LOGIG940_FF
hid-logitech-y += hid-lg3ff.o
endif
-ifdef CONFIG_LOGIWII_FF
+ifdef CONFIG_LOGIWHEELS_FF
hid-logitech-y += hid-lg4ff.o
endif
@@ -43,6 +43,7 @@ obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
obj-$(CONFIG_HID_KYE) += hid-kye.o
obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
+obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o
obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
@@ -54,6 +55,7 @@ obj-$(CONFIG_HID_QUANTA) += hid-quanta.o
obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o
+obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o
obj-$(CONFIG_HID_ROCCAT_COMMON) += hid-roccat-common.o
obj-$(CONFIG_HID_ROCCAT_ARVO) += hid-roccat-arvo.o
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 18b3bc646bf3..8cdb4b45b30a 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -183,6 +183,9 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
table = macbookair_fn_keys;
+ else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI &&
+ hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING6_JIS)
+ table = macbookair_fn_keys;
else if (hid->product < 0x21d || hid->product >= 0x300)
table = powerbook_fn_keys;
else
@@ -455,6 +458,9 @@ static const struct hid_device_id apple_devices[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
APPLE_ISO_KEYBOARD },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),
+ .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+ APPLE_ISO_KEYBOARD },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
@@ -493,6 +499,24 @@ static const struct hid_device_id apple_devices[] = {
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI),
+ .driver_data = APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS),
+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI),
+ .driver_data = APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS),
+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
+ .driver_data = APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c
index 121514149e0b..3bdb4500f95e 100644
--- a/drivers/hid/hid-axff.c
+++ b/drivers/hid/hid-axff.c
@@ -6,7 +6,7 @@
* Xbox 360 controller.
*
* 1a34:0802 "ACRUX USB GAMEPAD 8116"
- * - tested with a EXEQ EQ-PCU-02090 game controller.
+ * - tested with an EXEQ EQ-PCU-02090 game controller.
*
* Copyright (c) 2010 Sergei Kolzun <x0r@dv-life.ru>
*/
@@ -45,7 +45,10 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect
{
struct hid_device *hid = input_get_drvdata(dev);
struct axff_device *axff = data;
+ struct hid_report *report = axff->report;
+ int field_count = 0;
int left, right;
+ int i, j;
left = effect->u.rumble.strong_magnitude;
right = effect->u.rumble.weak_magnitude;
@@ -55,10 +58,14 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect
left = left * 0xff / 0xffff;
right = right * 0xff / 0xffff;
- axff->report->field[0]->value[0] = left;
- axff->report->field[1]->value[0] = right;
- axff->report->field[2]->value[0] = left;
- axff->report->field[3]->value[0] = right;
+ for (i = 0; i < report->maxfield; i++) {
+ for (j = 0; j < report->field[i]->report_count; j++) {
+ report->field[i]->value[j] =
+ field_count % 2 ? right : left;
+ field_count++;
+ }
+ }
+
dbg_hid("running with 0x%02x 0x%02x", left, right);
usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
@@ -72,6 +79,8 @@ static int axff_init(struct hid_device *hid)
struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct input_dev *dev = hidinput->input;
+ int field_count = 0;
+ int i, j;
int error;
if (list_empty(report_list)) {
@@ -80,9 +89,16 @@ static int axff_init(struct hid_device *hid)
}
report = list_first_entry(report_list, struct hid_report, list);
+ for (i = 0; i < report->maxfield; i++) {
+ for (j = 0; j < report->field[i]->report_count; j++) {
+ report->field[i]->value[j] = 0x00;
+ field_count++;
+ }
+ }
- if (report->maxfield < 4) {
- hid_err(hid, "no fields in the report: %d\n", report->maxfield);
+ if (field_count < 4) {
+ hid_err(hid, "not enough fields in the report: %d\n",
+ field_count);
return -ENODEV;
}
@@ -97,13 +113,9 @@ static int axff_init(struct hid_device *hid)
goto err_free_mem;
axff->report = report;
- axff->report->field[0]->value[0] = 0x00;
- axff->report->field[1]->value[0] = 0x00;
- axff->report->field[2]->value[0] = 0x00;
- axff->report->field[3]->value[0] = 0x00;
usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
- hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun<x0r@dv-life.ru>\n");
+ hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n");
return 0;
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 242353df3dc4..848a56c0279c 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -29,6 +29,7 @@
#include <linux/wait.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
+#include <linux/semaphore.h>
#include <linux/hid.h>
#include <linux/hiddev.h>
@@ -1085,16 +1086,25 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
struct hid_report *report;
char *buf;
unsigned int i;
- int ret;
+ int ret = 0;
- if (!hid || !hid->driver)
+ if (!hid)
return -ENODEV;
+
+ if (down_trylock(&hid->driver_lock))
+ return -EBUSY;
+
+ if (!hid->driver) {
+ ret = -ENODEV;
+ goto unlock;
+ }
report_enum = hid->report_enum + type;
hdrv = hid->driver;
if (!size) {
dbg_hid("empty report\n");
- return -1;
+ ret = -1;
+ goto unlock;
}
buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
@@ -1118,18 +1128,24 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
nomem:
report = hid_get_report(report_enum, data);
- if (!report)
- return -1;
+ if (!report) {
+ ret = -1;
+ goto unlock;
+ }
if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
ret = hdrv->raw_event(hid, report, data, size);
- if (ret != 0)
- return ret < 0 ? ret : 0;
+ if (ret != 0) {
+ ret = ret < 0 ? ret : 0;
+ goto unlock;
+ }
}
hid_report_raw_event(hid, type, data, size, interrupt);
- return 0;
+unlock:
+ up(&hid->driver_lock);
+ return ret;
}
EXPORT_SYMBOL_GPL(hid_input_report);
@@ -1212,6 +1228,12 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,
connect_mask & HID_CONNECT_HIDINPUT_FORCE))
hdev->claimed |= HID_CLAIMED_INPUT;
+ if (hdev->quirks & HID_QUIRK_MULTITOUCH) {
+ /* this device should be handled by hid-multitouch, skip it */
+ hdev->quirks &= ~HID_QUIRK_MULTITOUCH;
+ return -ENODEV;
+ }
+
if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect &&
!hdev->hiddev_connect(hdev,
connect_mask & HID_CONNECT_HIDDEV_FORCE))
@@ -1340,12 +1362,22 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
{ 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_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) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
@@ -1391,6 +1423,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
@@ -1399,6 +1432,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MULTITOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
@@ -1420,8 +1454,11 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
@@ -1461,6 +1498,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
@@ -1501,6 +1539,10 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
@@ -1620,10 +1662,15 @@ static int hid_device_probe(struct device *dev)
const struct hid_device_id *id;
int ret = 0;
+ if (down_interruptible(&hdev->driver_lock))
+ return -EINTR;
+
if (!hdev->driver) {
id = hid_match_device(hdev, hdrv);
- if (id == NULL)
- return -ENODEV;
+ if (id == NULL) {
+ ret = -ENODEV;
+ goto unlock;
+ }
hdev->driver = hdrv;
if (hdrv->probe) {
@@ -1636,14 +1683,20 @@ static int hid_device_probe(struct device *dev)
if (ret)
hdev->driver = NULL;
}
+unlock:
+ up(&hdev->driver_lock);
return ret;
}
static int hid_device_remove(struct device *dev)
{
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct hid_driver *hdrv = hdev->driver;
+ struct hid_driver *hdrv;
+
+ if (down_interruptible(&hdev->driver_lock))
+ return -EINTR;
+ hdrv = hdev->driver;
if (hdrv) {
if (hdrv->remove)
hdrv->remove(hdev);
@@ -1652,6 +1705,7 @@ static int hid_device_remove(struct device *dev)
hdev->driver = NULL;
}
+ up(&hdev->driver_lock);
return 0;
}
@@ -1892,6 +1946,15 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
{ 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) },
{ }
@@ -1999,6 +2062,7 @@ struct hid_device *hid_allocate_device(void)
init_waitqueue_head(&hdev->debug_wait);
INIT_LIST_HEAD(&hdev->debug_list);
+ sema_init(&hdev->driver_lock, 1);
return hdev;
err:
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index bae48745bb42..9a243ca96e6d 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -450,6 +450,11 @@ void hid_dump_field(struct hid_field *field, int n, struct seq_file *f) {
seq_printf(f, "Logical(");
hid_resolv_usage(field->logical, f); seq_printf(f, ")\n");
}
+ if (field->application) {
+ tab(n, f);
+ seq_printf(f, "Application(");
+ hid_resolv_usage(field->application, f); seq_printf(f, ")\n");
+ }
tab(n, f); seq_printf(f, "Usage(%d)\n", field->maxusage);
for (j = 0; j < field->maxusage; j++) {
tab(n+2, f); hid_resolv_usage(field->usage[j].hid, f); seq_printf(f, "\n");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 7484e1b67249..06ce996b8b65 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -112,9 +112,19 @@
#define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI 0x024f
#define USB_DEVICE_ID_APPLE_ALU_REVB_ISO 0x0250
#define USB_DEVICE_ID_APPLE_ALU_REVB_JIS 0x0251
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS 0x024e
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241
@@ -351,6 +361,9 @@
#define USB_DEVICE_ID_UGCI_FLYING 0x0020
#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030
+#define USB_VENDOR_ID_IDEACOM 0x1cb6
+#define USB_DEVICE_ID_IDEACOM_IDC6650 0x6650
+
#define USB_VENDOR_ID_ILITEK 0x222a
#define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001
@@ -423,6 +436,9 @@
#define USB_DEVICE_ID_LD_HYBRID 0x2090
#define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0
+#define USB_VENDOR_ID_LG 0x1fd2
+#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
+
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110
@@ -440,6 +456,7 @@
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
#define USB_DEVICE_ID_LOGITECH_DFP_WHEEL 0xc298
#define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299
+#define USB_DEVICE_ID_LOGITECH_DFGT_WHEEL 0xc29a
#define USB_DEVICE_ID_LOGITECH_G27_WHEEL 0xc29b
#define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c
#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
@@ -447,6 +464,8 @@
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
+#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER 0xc52b
+#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 0xc532
#define USB_DEVICE_ID_SPACETRAVELLER 0xc623
#define USB_DEVICE_ID_SPACENAVIGATOR 0xc626
#define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704
@@ -678,6 +697,9 @@
#define USB_VENDOR_ID_WISEGROUP_LTD 0x6666
#define USB_VENDOR_ID_WISEGROUP_LTD2 0x6677
#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
+#define USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO 0x8801
+#define USB_DEVICE_ID_SUPER_DUAL_BOX_PRO 0x8802
+#define USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO 0x8804
#define USB_VENDOR_ID_X_TENSIONS 0x1ae7
#define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE 0x9001
@@ -693,4 +715,7 @@
#define USB_VENDOR_ID_ZYDACRON 0x13EC
#define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL 0x0006
+#define USB_VENDOR_ID_PRIMAX 0x0461
+#define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05
+
#endif
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 6559e2e3364e..f333139d1a48 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -474,6 +474,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
map_key_clear(BTN_STYLUS2);
break;
+ case 0x51: /* ContactID */
+ device->quirks |= HID_QUIRK_MULTITOUCH;
+ goto unknown;
+
default: goto unknown;
}
break;
@@ -978,6 +982,13 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
}
}
+ if (hid->quirks & HID_QUIRK_MULTITOUCH) {
+ /* generic hid does not know how to handle multitouch devices */
+ if (hidinput)
+ goto out_cleanup;
+ goto out_unwind;
+ }
+
if (hidinput && input_register_device(hidinput->input))
goto out_cleanup;
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index a7f916e8fc32..e7a7bd1eb34a 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -363,7 +363,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err_free;
}
- if (quirks & (LG_FF | LG_FF2 | LG_FF3))
+ if (quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
connect_mask &= ~HID_CONNECT_FF;
ret = hid_hw_start(hdev, connect_mask);
@@ -372,7 +372,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err_free;
}
- if (quirks & LG_FF4) {
+ /* Setup wireless link with Logitech Wii wheel */
+ if(hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
@@ -405,6 +406,15 @@ err_free:
return ret;
}
+static void lg_remove(struct hid_device *hdev)
+{
+ unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+ if(quirks & LG_FF4)
+ lg4ff_deinit(hdev);
+
+ hid_hw_stop(hdev);
+}
+
static const struct hid_device_id lg_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
.driver_data = LG_RDESC | LG_WIRELESS },
@@ -431,7 +441,7 @@ static const struct hid_device_id lg_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
.driver_data = LG_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
- .driver_data = LG_NOGET | LG_FF },
+ .driver_data = LG_NOGET | LG_FF4 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
.driver_data = LG_FF2 },
@@ -444,15 +454,17 @@ static const struct hid_device_id lg_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
.driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
- .driver_data = LG_FF },
+ .driver_data = LG_FF4 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
- .driver_data = LG_FF },
+ .driver_data = LG_FF4 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
- .driver_data = LG_FF },
+ .driver_data = LG_FF4 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL),
+ .driver_data = LG_FF4 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
- .driver_data = LG_FF },
+ .driver_data = LG_FF4 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
- .driver_data = LG_NOGET | LG_FF },
+ .driver_data = LG_NOGET | LG_FF4 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
.driver_data = LG_FF4 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
@@ -478,6 +490,7 @@ static struct hid_driver lg_driver = {
.input_mapped = lg_input_mapped,
.event = lg_event,
.probe = lg_probe,
+ .remove = lg_remove,
};
static int __init lg_init(void)
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h
index b0100ba2ae0b..4b097286dc78 100644
--- a/drivers/hid/hid-lg.h
+++ b/drivers/hid/hid-lg.h
@@ -19,10 +19,12 @@ int lg3ff_init(struct hid_device *hdev);
static inline int lg3ff_init(struct hid_device *hdev) { return -1; }
#endif
-#ifdef CONFIG_LOGIWII_FF
+#ifdef CONFIG_LOGIWHEELS_FF
int lg4ff_init(struct hid_device *hdev);
+int lg4ff_deinit(struct hid_device *hdev);
#else
static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
+static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; }
#endif
#endif
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index fa550c8e1d1b..103f30d93f76 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -29,19 +29,108 @@
#include "usbhid/usbhid.h"
#include "hid-lg.h"
+#include "hid-ids.h"
-struct lg4ff_device {
- struct hid_report *report;
+#define DFGT_REV_MAJ 0x13
+#define DFGT_REV_MIN 0x22
+#define DFP_REV_MAJ 0x11
+#define DFP_REV_MIN 0x06
+#define FFEX_REV_MAJ 0x21
+#define FFEX_REV_MIN 0x00
+#define G25_REV_MAJ 0x12
+#define G25_REV_MIN 0x22
+#define G27_REV_MAJ 0x12
+#define G27_REV_MIN 0x38
+
+#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
+
+static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range);
+static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range);
+static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+
+static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store);
+
+static bool list_inited;
+
+struct lg4ff_device_entry {
+ char *device_id; /* Use name in respective kobject structure's address as the ID */
+ __u16 range;
+ __u16 min_range;
+ __u16 max_range;
+ __u8 leds;
+ struct list_head list;
+ void (*set_range)(struct hid_device *hid, u16 range);
};
-static const signed short ff4_wheel_ac[] = {
+static struct lg4ff_device_entry device_list;
+
+static const signed short lg4ff_wheel_effects[] = {
FF_CONSTANT,
FF_AUTOCENTER,
-1
};
-static int hid_lg4ff_play(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+struct lg4ff_wheel {
+ const __u32 product_id;
+ const signed short *ff_effects;
+ const __u16 min_range;
+ const __u16 max_range;
+ void (*set_range)(struct hid_device *hid, u16 range);
+};
+
+static const struct lg4ff_wheel lg4ff_devices[] = {
+ {USB_DEVICE_ID_LOGITECH_WHEEL, lg4ff_wheel_effects, 40, 270, NULL},
+ {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL, lg4ff_wheel_effects, 40, 270, NULL},
+ {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_dfp},
+ {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
+ {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
+ {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
+ {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL},
+ {USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}
+};
+
+struct lg4ff_native_cmd {
+ const __u8 cmd_num; /* Number of commands to send */
+ const __u8 cmd[];
+};
+
+struct lg4ff_usb_revision {
+ const __u16 rev_maj;
+ const __u16 rev_min;
+ const struct lg4ff_native_cmd *command;
+};
+
+static const struct lg4ff_native_cmd native_dfp = {
+ 1,
+ {0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct lg4ff_native_cmd native_dfgt = {
+ 2,
+ {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1st command */
+ 0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00} /* 2nd command */
+};
+
+static const struct lg4ff_native_cmd native_g25 = {
+ 1,
+ {0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct lg4ff_native_cmd native_g27 = {
+ 2,
+ {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1st command */
+ 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00} /* 2nd command */
+};
+
+static const struct lg4ff_usb_revision lg4ff_revs[] = {
+ {DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt}, /* Driving Force GT */
+ {DFP_REV_MAJ, DFP_REV_MIN, &native_dfp}, /* Driving Force Pro */
+ {G25_REV_MAJ, G25_REV_MIN, &native_g25}, /* G25 */
+ {G27_REV_MAJ, G27_REV_MIN, &native_g27}, /* G27 */
+};
+
+static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
{
struct hid_device *hid = input_get_drvdata(dev);
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
@@ -55,13 +144,12 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data,
x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */
CLAMP(x);
report->field[0]->value[0] = 0x11; /* Slot 1 */
- report->field[0]->value[1] = 0x10;
+ report->field[0]->value[1] = 0x08;
report->field[0]->value[2] = x;
- report->field[0]->value[3] = 0x00;
+ report->field[0]->value[3] = 0x80;
report->field[0]->value[4] = 0x00;
- report->field[0]->value[5] = 0x08;
+ report->field[0]->value[5] = 0x00;
report->field[0]->value[6] = 0x00;
- dbg_hid("Autocenter, x=0x%02X\n", x);
usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
@@ -69,24 +157,184 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data,
return 0;
}
-static void hid_lg4ff_set_autocenter(struct input_dev *dev, u16 magnitude)
+/* Sends default autocentering command compatible with
+ * all wheels except Formula Force EX */
+static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude)
{
struct hid_device *hid = input_get_drvdata(dev);
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
- __s32 *value = report->field[0]->value;
- *value++ = 0xfe;
- *value++ = 0x0d;
- *value++ = 0x07;
- *value++ = 0x07;
- *value++ = (magnitude >> 8) & 0xff;
- *value++ = 0x00;
- *value = 0x00;
+ report->field[0]->value[0] = 0xfe;
+ report->field[0]->value[1] = 0x0d;
+ report->field[0]->value[2] = magnitude >> 13;
+ report->field[0]->value[3] = magnitude >> 13;
+ report->field[0]->value[4] = magnitude >> 8;
+ report->field[0]->value[5] = 0x00;
+ report->field[0]->value[6] = 0x00;
+
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+/* Sends autocentering command compatible with Formula Force EX */
+static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude)
+{
+ struct hid_device *hid = input_get_drvdata(dev);
+ struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+ magnitude = magnitude * 90 / 65535;
+
+
+ report->field[0]->value[0] = 0xfe;
+ report->field[0]->value[1] = 0x03;
+ report->field[0]->value[2] = magnitude >> 14;
+ report->field[0]->value[3] = magnitude >> 14;
+ report->field[0]->value[4] = magnitude;
+ report->field[0]->value[5] = 0x00;
+ report->field[0]->value[6] = 0x00;
+
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+/* Sends command to set range compatible with G25/G27/Driving Force GT */
+static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range)
+{
+ struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+ dbg_hid("G25/G27/DFGT: setting range to %u\n", range);
+
+ report->field[0]->value[0] = 0xf8;
+ report->field[0]->value[1] = 0x81;
+ report->field[0]->value[2] = range & 0x00ff;
+ report->field[0]->value[3] = (range & 0xff00) >> 8;
+ report->field[0]->value[4] = 0x00;
+ report->field[0]->value[5] = 0x00;
+ report->field[0]->value[6] = 0x00;
+
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+/* Sends commands to set range compatible with Driving Force Pro wheel */
+static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
+{
+ struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+ int start_left, start_right, full_range;
+ dbg_hid("Driving Force Pro: setting range to %u\n", range);
+
+ /* Prepare "coarse" limit command */
+ report->field[0]->value[0] = 0xf8;
+ report->field[0]->value[1] = 0x00; /* Set later */
+ report->field[0]->value[2] = 0x00;
+ report->field[0]->value[3] = 0x00;
+ report->field[0]->value[4] = 0x00;
+ report->field[0]->value[5] = 0x00;
+ report->field[0]->value[6] = 0x00;
+
+ if (range > 200) {
+ report->field[0]->value[1] = 0x03;
+ full_range = 900;
+ } else {
+ report->field[0]->value[1] = 0x02;
+ full_range = 200;
+ }
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+
+ /* Prepare "fine" limit command */
+ report->field[0]->value[0] = 0x81;
+ report->field[0]->value[1] = 0x0b;
+ report->field[0]->value[2] = 0x00;
+ report->field[0]->value[3] = 0x00;
+ report->field[0]->value[4] = 0x00;
+ report->field[0]->value[5] = 0x00;
+ report->field[0]->value[6] = 0x00;
+
+ if (range == 200 || range == 900) { /* Do not apply any fine limit */
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+ return;
+ }
+
+ /* Construct fine limit command */
+ start_left = (((full_range - range + 1) * 2047) / full_range);
+ start_right = 0xfff - start_left;
+
+ report->field[0]->value[2] = start_left >> 4;
+ report->field[0]->value[3] = start_right >> 4;
+ report->field[0]->value[4] = 0xff;
+ report->field[0]->value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
+ report->field[0]->value[6] = 0xff;
usbhid_submit_report(hid, report, USB_DIR_OUT);
}
+static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd)
+{
+ struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+ __u8 i, j;
+
+ j = 0;
+ while (j < 7*cmd->cmd_num) {
+ for (i = 0; i < 7; i++)
+ report->field[0]->value[i] = cmd->cmd[j++];
+
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+ }
+}
+
+/* Read current range and display it in terminal */
+static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct lg4ff_device_entry *uninitialized_var(entry);
+ struct list_head *h;
+ struct hid_device *hid = to_hid_device(dev);
+ size_t count;
+
+ list_for_each(h, &device_list.list) {
+ entry = list_entry(h, struct lg4ff_device_entry, list);
+ if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0)
+ break;
+ }
+ if (h == &device_list.list) {
+ dbg_hid("Device not found!");
+ return 0;
+ }
+
+ count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->range);
+ return count;
+}
+
+/* Set range to user specified value, call appropriate function
+ * according to the type of the wheel */
+static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct lg4ff_device_entry *uninitialized_var(entry);
+ struct list_head *h;
+ struct hid_device *hid = to_hid_device(dev);
+ __u16 range = simple_strtoul(buf, NULL, 10);
+
+ list_for_each(h, &device_list.list) {
+ entry = list_entry(h, struct lg4ff_device_entry, list);
+ if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0)
+ break;
+ }
+ if (h == &device_list.list) {
+ dbg_hid("Device not found!");
+ return count;
+ }
+
+ if (range == 0)
+ range = entry->max_range;
+
+ /* Check if the wheel supports range setting
+ * and that the range is within limits for the wheel */
+ if (entry->set_range != NULL && range >= entry->min_range && range <= entry->max_range) {
+ entry->set_range(hid, range);
+ entry->range = range;
+ }
+
+ return count;
+}
int lg4ff_init(struct hid_device *hid)
{
@@ -95,9 +343,10 @@ int lg4ff_init(struct hid_device *hid)
struct input_dev *dev = hidinput->input;
struct hid_report *report;
struct hid_field *field;
- const signed short *ff_bits = ff4_wheel_ac;
- int error;
- int i;
+ struct lg4ff_device_entry *entry;
+ struct usb_device_descriptor *udesc;
+ int error, i, j;
+ __u16 bcdDevice, rev_maj, rev_min;
/* Find the report to use */
if (list_empty(report_list)) {
@@ -118,18 +367,122 @@ int lg4ff_init(struct hid_device *hid)
return -1;
}
- for (i = 0; ff_bits[i] >= 0; i++)
- set_bit(ff_bits[i], dev->ffbit);
+ /* Check what wheel has been connected */
+ for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) {
+ if (hid->product == lg4ff_devices[i].product_id) {
+ dbg_hid("Found compatible device, product ID %04X\n", lg4ff_devices[i].product_id);
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(lg4ff_devices)) {
+ hid_err(hid, "Device is not supported by lg4ff driver. If you think it should be, consider reporting a bug to"
+ "LKML, Simon Wood <simon@mungewell.org> or Michal Maly <madcatxster@gmail.com>\n");
+ return -1;
+ }
+
+ /* Attempt to switch wheel to native mode when applicable */
+ udesc = &(hid_to_usb_dev(hid)->descriptor);
+ if (!udesc) {
+ hid_err(hid, "NULL USB device descriptor\n");
+ return -1;
+ }
+ bcdDevice = le16_to_cpu(udesc->bcdDevice);
+ rev_maj = bcdDevice >> 8;
+ rev_min = bcdDevice & 0xff;
+
+ if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_WHEEL) {
+ dbg_hid("Generic wheel detected, can it do native?\n");
+ dbg_hid("USB revision: %2x.%02x\n", rev_maj, rev_min);
+
+ for (j = 0; j < ARRAY_SIZE(lg4ff_revs); j++) {
+ if (lg4ff_revs[j].rev_maj == rev_maj && lg4ff_revs[j].rev_min == rev_min) {
+ hid_lg4ff_switch_native(hid, lg4ff_revs[j].command);
+ hid_info(hid, "Switched to native mode\n");
+ }
+ }
+ }
+
+ /* Set supported force feedback capabilities */
+ for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++)
+ set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit);
error = input_ff_create_memless(dev, NULL, hid_lg4ff_play);
if (error)
return error;
- if (test_bit(FF_AUTOCENTER, dev->ffbit))
- dev->ff->set_autocenter = hid_lg4ff_set_autocenter;
+ /* Check if autocentering is available and
+ * set the centering force to zero by default */
+ if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
+ if(rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */
+ dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
+ else
+ dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
+
+ dev->ff->set_autocenter(dev, 0);
+ }
+
+ /* Initialize device_list if this is the first device to handle by lg4ff */
+ if (!list_inited) {
+ INIT_LIST_HEAD(&device_list.list);
+ list_inited = 1;
+ }
+
+ /* Add the device to device_list */
+ entry = (struct lg4ff_device_entry *)kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL);
+ if (!entry) {
+ hid_err(hid, "Cannot add device, insufficient memory.\n");
+ return -ENOMEM;
+ }
+ entry->device_id = kstrdup((&hid->dev)->kobj.name, GFP_KERNEL);
+ if (!entry->device_id) {
+ hid_err(hid, "Cannot set device_id, insufficient memory.\n");
+ kfree(entry);
+ return -ENOMEM;
+ }
+ entry->min_range = lg4ff_devices[i].min_range;
+ entry->max_range = lg4ff_devices[i].max_range;
+ entry->set_range = lg4ff_devices[i].set_range;
+ list_add(&entry->list, &device_list.list);
+
+ /* Create sysfs interface */
+ error = device_create_file(&hid->dev, &dev_attr_range);
+ if (error)
+ return error;
+ dbg_hid("sysfs interface created\n");
+
+ /* Set the maximum range to start with */
+ entry->range = entry->max_range;
+ if (entry->set_range != NULL)
+ entry->set_range(hid, entry->range);
hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
return 0;
}
+int lg4ff_deinit(struct hid_device *hid)
+{
+ bool found = 0;
+ struct lg4ff_device_entry *entry;
+ struct list_head *h, *g;
+ list_for_each_safe(h, g, &device_list.list) {
+ entry = list_entry(h, struct lg4ff_device_entry, list);
+ if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) {
+ list_del(h);
+ kfree(entry->device_id);
+ kfree(entry);
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ dbg_hid("Device entry not found!\n");
+ return -1;
+ }
+
+ device_remove_file(&hid->dev, &dev_attr_range);
+ dbg_hid("Device successfully unregistered\n");
+ return 0;
+}
diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c
index 088f85049290..27bc54f92f44 100644
--- a/drivers/hid/hid-lgff.c
+++ b/drivers/hid/hid-lgff.c
@@ -58,12 +58,6 @@ static const signed short ff_joystick_ac[] = {
-1
};
-static const signed short ff_wheel[] = {
- FF_CONSTANT,
- FF_AUTOCENTER,
- -1
-};
-
static const struct dev_type devices[] = {
{ 0x046d, 0xc211, ff_rumble },
{ 0x046d, 0xc219, ff_rumble },
@@ -71,14 +65,7 @@ static const struct dev_type devices[] = {
{ 0x046d, 0xc286, ff_joystick_ac },
{ 0x046d, 0xc287, ff_joystick_ac },
{ 0x046d, 0xc293, ff_joystick },
- { 0x046d, 0xc294, ff_wheel },
- { 0x046d, 0xc298, ff_wheel },
- { 0x046d, 0xc299, ff_wheel },
- { 0x046d, 0xc29b, ff_wheel },
{ 0x046d, 0xc295, ff_joystick },
- { 0x046d, 0xc298, ff_wheel },
- { 0x046d, 0xc299, ff_wheel },
- { 0x046d, 0xca03, ff_wheel },
};
static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
new file mode 100644
index 000000000000..38b12e45780c
--- /dev/null
+++ b/drivers/hid/hid-logitech-dj.c
@@ -0,0 +1,922 @@
+/*
+ * HID driver for Logitech Unifying receivers
+ *
+ * Copyright (c) 2011 Logitech
+ */
+
+/*
+ * 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
+ *
+ */
+
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usbhid/usbhid.h"
+#include "hid-ids.h"
+#include "hid-logitech-dj.h"
+
+/* Keyboard descriptor (1) */
+static const char kbd_descriptor[] = {
+ 0x05, 0x01, /* USAGE_PAGE (generic Desktop) */
+ 0x09, 0x06, /* USAGE (Keyboard) */
+ 0xA1, 0x01, /* COLLECTION (Application) */
+ 0x85, 0x01, /* REPORT_ID (1) */
+ 0x95, 0x08, /* REPORT_COUNT (8) */
+ 0x75, 0x01, /* REPORT_SIZE (1) */
+ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
+ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
+ 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
+ 0x19, 0xE0, /* USAGE_MINIMUM (Left Control) */
+ 0x29, 0xE7, /* USAGE_MAXIMUM (Right GUI) */
+ 0x81, 0x02, /* INPUT (Data,Var,Abs) */
+ 0x95, 0x05, /* REPORT COUNT (5) */
+ 0x05, 0x08, /* USAGE PAGE (LED page) */
+ 0x19, 0x01, /* USAGE MINIMUM (1) */
+ 0x29, 0x05, /* USAGE MAXIMUM (5) */
+ 0x91, 0x02, /* OUTPUT (Data, Variable, Absolute) */
+ 0x95, 0x01, /* REPORT COUNT (1) */
+ 0x75, 0x03, /* REPORT SIZE (3) */
+ 0x91, 0x01, /* OUTPUT (Constant) */
+ 0x95, 0x06, /* REPORT_COUNT (6) */
+ 0x75, 0x08, /* REPORT_SIZE (8) */
+ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
+ 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */
+ 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
+ 0x19, 0x00, /* USAGE_MINIMUM (no event) */
+ 0x2A, 0xFF, 0x00, /* USAGE_MAXIMUM (reserved) */
+ 0x81, 0x00, /* INPUT (Data,Ary,Abs) */
+ 0xC0
+};
+
+/* Mouse descriptor (2) */
+static const char mse_descriptor[] = {
+ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
+ 0x09, 0x02, /* USAGE (Mouse) */
+ 0xA1, 0x01, /* COLLECTION (Application) */
+ 0x85, 0x02, /* REPORT_ID = 2 */
+ 0x09, 0x01, /* USAGE (pointer) */
+ 0xA1, 0x00, /* COLLECTION (physical) */
+ 0x05, 0x09, /* USAGE_PAGE (buttons) */
+ 0x19, 0x01, /* USAGE_MIN (1) */
+ 0x29, 0x10, /* USAGE_MAX (16) */
+ 0x15, 0x00, /* LOGICAL_MIN (0) */
+ 0x25, 0x01, /* LOGICAL_MAX (1) */
+ 0x95, 0x10, /* REPORT_COUNT (16) */
+ 0x75, 0x01, /* REPORT_SIZE (1) */
+ 0x81, 0x02, /* INPUT (data var abs) */
+ 0x05, 0x01, /* USAGE_PAGE (generic desktop) */
+ 0x16, 0x01, 0xF8, /* LOGICAL_MIN (-2047) */
+ 0x26, 0xFF, 0x07, /* LOGICAL_MAX (2047) */
+ 0x75, 0x0C, /* REPORT_SIZE (12) */
+ 0x95, 0x02, /* REPORT_COUNT (2) */
+ 0x09, 0x30, /* USAGE (X) */
+ 0x09, 0x31, /* USAGE (Y) */
+ 0x81, 0x06, /* INPUT */
+ 0x15, 0x81, /* LOGICAL_MIN (-127) */
+ 0x25, 0x7F, /* LOGICAL_MAX (127) */
+ 0x75, 0x08, /* REPORT_SIZE (8) */
+ 0x95, 0x01, /* REPORT_COUNT (1) */
+ 0x09, 0x38, /* USAGE (wheel) */
+ 0x81, 0x06, /* INPUT */
+ 0x05, 0x0C, /* USAGE_PAGE(consumer) */
+ 0x0A, 0x38, 0x02, /* USAGE(AC Pan) */
+ 0x95, 0x01, /* REPORT_COUNT (1) */
+ 0x81, 0x06, /* INPUT */
+ 0xC0, /* END_COLLECTION */
+ 0xC0, /* END_COLLECTION */
+};
+
+/* Consumer Control descriptor (3) */
+static const char consumer_descriptor[] = {
+ 0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */
+ 0x09, 0x01, /* USAGE (Consumer Control) */
+ 0xA1, 0x01, /* COLLECTION (Application) */
+ 0x85, 0x03, /* REPORT_ID = 3 */
+ 0x75, 0x10, /* REPORT_SIZE (16) */
+ 0x95, 0x02, /* REPORT_COUNT (2) */
+ 0x15, 0x01, /* LOGICAL_MIN (1) */
+ 0x26, 0x8C, 0x02, /* LOGICAL_MAX (652) */
+ 0x19, 0x01, /* USAGE_MIN (1) */
+ 0x2A, 0x8C, 0x02, /* USAGE_MAX (652) */
+ 0x81, 0x00, /* INPUT (Data Ary Abs) */
+ 0xC0, /* END_COLLECTION */
+}; /* */
+
+/* System control descriptor (4) */
+static const char syscontrol_descriptor[] = {
+ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
+ 0x09, 0x80, /* USAGE (System Control) */
+ 0xA1, 0x01, /* COLLECTION (Application) */
+ 0x85, 0x04, /* REPORT_ID = 4 */
+ 0x75, 0x02, /* REPORT_SIZE (2) */
+ 0x95, 0x01, /* REPORT_COUNT (1) */
+ 0x15, 0x01, /* LOGICAL_MIN (1) */
+ 0x25, 0x03, /* LOGICAL_MAX (3) */
+ 0x09, 0x82, /* USAGE (System Sleep) */
+ 0x09, 0x81, /* USAGE (System Power Down) */
+ 0x09, 0x83, /* USAGE (System Wake Up) */
+ 0x81, 0x60, /* INPUT (Data Ary Abs NPrf Null) */
+ 0x75, 0x06, /* REPORT_SIZE (6) */
+ 0x81, 0x03, /* INPUT (Cnst Var Abs) */
+ 0xC0, /* END_COLLECTION */
+};
+
+/* Media descriptor (8) */
+static const char media_descriptor[] = {
+ 0x06, 0xbc, 0xff, /* Usage Page 0xffbc */
+ 0x09, 0x88, /* Usage 0x0088 */
+ 0xa1, 0x01, /* BeginCollection */
+ 0x85, 0x08, /* Report ID 8 */
+ 0x19, 0x01, /* Usage Min 0x0001 */
+ 0x29, 0xff, /* Usage Max 0x00ff */
+ 0x15, 0x01, /* Logical Min 1 */
+ 0x26, 0xff, 0x00, /* Logical Max 255 */
+ 0x75, 0x08, /* Report Size 8 */
+ 0x95, 0x01, /* Report Count 1 */
+ 0x81, 0x00, /* Input */
+ 0xc0, /* EndCollection */
+}; /* */
+
+/* Maximum size of all defined hid reports in bytes (including report id) */
+#define MAX_REPORT_SIZE 8
+
+/* Number of possible hid report types that can be created by this driver.
+ *
+ * Right now, RF report types have the same report types (or report id's)
+ * than the hid report created from those RF reports. In the future
+ * this doesnt have to be true.
+ *
+ * For instance, RF report type 0x01 which has a size of 8 bytes, corresponds
+ * to hid report id 0x01, this is standard keyboard. Same thing applies to mice
+ * reports and consumer control, etc. If a new RF report is created, it doesn't
+ * has to have the same report id as its corresponding hid report, so an
+ * translation may have to take place for future report types.
+ */
+#define NUMBER_OF_HID_REPORTS 32
+static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = {
+ [1] = 8, /* Standard keyboard */
+ [2] = 8, /* Standard mouse */
+ [3] = 5, /* Consumer control */
+ [4] = 2, /* System control */
+ [8] = 2, /* Media Center */
+};
+
+
+#define LOGITECH_DJ_INTERFACE_NUMBER 0x02
+
+static struct hid_ll_driver logi_dj_ll_driver;
+
+static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
+ size_t count,
+ unsigned char report_type);
+
+static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
+ struct dj_report *dj_report)
+{
+ /* Called in delayed work context */
+ struct dj_device *dj_dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&djrcv_dev->lock, flags);
+ dj_dev = djrcv_dev->paired_dj_devices[dj_report->device_index];
+ djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
+ spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+
+ if (dj_dev != NULL) {
+ hid_destroy_device(dj_dev->hdev);
+ kfree(dj_dev);
+ } else {
+ dev_err(&djrcv_dev->hdev->dev, "%s: can't destroy a NULL device\n",
+ __func__);
+ }
+}
+
+static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
+ struct dj_report *dj_report)
+{
+ /* Called in delayed work context */
+ struct hid_device *djrcv_hdev = djrcv_dev->hdev;
+ struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent);
+ struct usb_device *usbdev = interface_to_usbdev(intf);
+ struct hid_device *dj_hiddev;
+ struct dj_device *dj_dev;
+
+ /* Device index goes from 1 to 6, we need 3 bytes to store the
+ * semicolon, the index, and a null terminator
+ */
+ unsigned char tmpstr[3];
+
+ if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
+ SPFUNCTION_DEVICE_LIST_EMPTY) {
+ dbg_hid("%s: device list is empty\n", __func__);
+ return;
+ }
+
+ if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
+ (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
+ dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n",
+ __func__, dj_report->device_index);
+ return;
+ }
+
+ dj_hiddev = hid_allocate_device();
+ if (IS_ERR(dj_hiddev)) {
+ dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
+ __func__);
+ return;
+ }
+
+ dj_hiddev->ll_driver = &logi_dj_ll_driver;
+ dj_hiddev->hid_output_raw_report = logi_dj_output_hidraw_report;
+
+ dj_hiddev->dev.parent = &djrcv_hdev->dev;
+ dj_hiddev->bus = BUS_USB;
+ dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor);
+ dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct);
+ snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
+ "Logitech Unifying Device. Wireless PID:%02x%02x",
+ dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB],
+ dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]);
+
+ usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys));
+ snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index);
+ strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys));
+
+ dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL);
+
+ if (!dj_dev) {
+ dev_err(&djrcv_hdev->dev, "%s: failed allocating dj_device\n",
+ __func__);
+ goto dj_device_allocate_fail;
+ }
+
+ dj_dev->reports_supported = le32_to_cpu(
+ dj_report->report_params[DEVICE_PAIRED_RF_REPORT_TYPE]);
+ dj_dev->hdev = dj_hiddev;
+ dj_dev->dj_receiver_dev = djrcv_dev;
+ dj_dev->device_index = dj_report->device_index;
+ dj_hiddev->driver_data = dj_dev;
+
+ djrcv_dev->paired_dj_devices[dj_report->device_index] = dj_dev;
+
+ if (hid_add_device(dj_hiddev)) {
+ dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n",
+ __func__);
+ goto hid_add_device_fail;
+ }
+
+ return;
+
+hid_add_device_fail:
+ djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
+ kfree(dj_dev);
+dj_device_allocate_fail:
+ hid_destroy_device(dj_hiddev);
+}
+
+static void delayedwork_callback(struct work_struct *work)
+{
+ struct dj_receiver_dev *djrcv_dev =
+ container_of(work, struct dj_receiver_dev, work);
+
+ struct dj_report dj_report;
+ unsigned long flags;
+ int count;
+
+ dbg_hid("%s\n", __func__);
+
+ spin_lock_irqsave(&djrcv_dev->lock, flags);
+
+ count = kfifo_out(&djrcv_dev->notif_fifo, &dj_report,
+ sizeof(struct dj_report));
+
+ if (count != sizeof(struct dj_report)) {
+ dev_err(&djrcv_dev->hdev->dev, "%s: workitem triggered without "
+ "notifications available\n", __func__);
+ spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+ return;
+ }
+
+ if (!kfifo_is_empty(&djrcv_dev->notif_fifo)) {
+ if (schedule_work(&djrcv_dev->work) == 0) {
+ dbg_hid("%s: did not schedule the work item, was "
+ "already queued\n", __func__);
+ }
+ }
+
+ spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+
+ switch (dj_report.report_type) {
+ case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
+ logi_dj_recv_add_djhid_device(djrcv_dev, &dj_report);
+ break;
+ case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
+ logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
+ break;
+ default:
+ dbg_hid("%s: unexpected report type\n", __func__);
+ }
+}
+
+static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
+ struct dj_report *dj_report)
+{
+ /* We are called from atomic context (tasklet && djrcv->lock held) */
+
+ kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
+
+ if (schedule_work(&djrcv_dev->work) == 0) {
+ dbg_hid("%s: did not schedule the work item, was already "
+ "queued\n", __func__);
+ }
+}
+
+static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
+ struct dj_report *dj_report)
+{
+ /* We are called from atomic context (tasklet && djrcv->lock held) */
+ unsigned int i;
+ u8 reportbuffer[MAX_REPORT_SIZE];
+ struct dj_device *djdev;
+
+ djdev = djrcv_dev->paired_dj_devices[dj_report->device_index];
+
+ if (!djdev) {
+ dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
+ " is NULL, index %d\n", dj_report->device_index);
+ return;
+ }
+
+ memset(reportbuffer, 0, sizeof(reportbuffer));
+
+ for (i = 0; i < NUMBER_OF_HID_REPORTS; i++) {
+ if (djdev->reports_supported & (1 << i)) {
+ reportbuffer[0] = i;
+ if (hid_input_report(djdev->hdev,
+ HID_INPUT_REPORT,
+ reportbuffer,
+ hid_reportid_size_map[i], 1)) {
+ dbg_hid("hid_input_report error sending null "
+ "report\n");
+ }
+ }
+ }
+}
+
+static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
+ struct dj_report *dj_report)
+{
+ /* We are called from atomic context (tasklet && djrcv->lock held) */
+ struct dj_device *dj_device;
+
+ dj_device = djrcv_dev->paired_dj_devices[dj_report->device_index];
+
+ if (dj_device == NULL) {
+ dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
+ " is NULL, index %d\n", dj_report->device_index);
+ return;
+ }
+
+ if ((dj_report->report_type > ARRAY_SIZE(hid_reportid_size_map) - 1) ||
+ (hid_reportid_size_map[dj_report->report_type] == 0)) {
+ dbg_hid("invalid report type:%x\n", dj_report->report_type);
+ return;
+ }
+
+ if (hid_input_report(dj_device->hdev,
+ HID_INPUT_REPORT, &dj_report->report_type,
+ hid_reportid_size_map[dj_report->report_type], 1)) {
+ dbg_hid("hid_input_report error\n");
+ }
+}
+
+
+static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
+ struct dj_report *dj_report)
+{
+ struct hid_device *hdev = djrcv_dev->hdev;
+ int sent_bytes;
+
+ if (!hdev->hid_output_raw_report) {
+ dev_err(&hdev->dev, "%s:"
+ "hid_output_raw_report is null\n", __func__);
+ return -ENODEV;
+ }
+
+ sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report,
+ sizeof(struct dj_report),
+ HID_OUTPUT_REPORT);
+
+ return (sent_bytes < 0) ? sent_bytes : 0;
+}
+
+static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
+{
+ struct dj_report dj_report;
+
+ memset(&dj_report, 0, sizeof(dj_report));
+ dj_report.report_id = REPORT_ID_DJ_SHORT;
+ dj_report.device_index = 0xFF;
+ dj_report.report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
+ return logi_dj_recv_send_report(djrcv_dev, &dj_report);
+}
+
+static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
+ unsigned timeout)
+{
+ struct dj_report dj_report;
+
+ memset(&dj_report, 0, sizeof(dj_report));
+ dj_report.report_id = REPORT_ID_DJ_SHORT;
+ dj_report.device_index = 0xFF;
+ dj_report.report_type = REPORT_TYPE_CMD_SWITCH;
+ dj_report.report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x1F;
+ dj_report.report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout;
+ return logi_dj_recv_send_report(djrcv_dev, &dj_report);
+}
+
+
+static int logi_dj_ll_open(struct hid_device *hid)
+{
+ dbg_hid("%s:%s\n", __func__, hid->phys);
+ return 0;
+
+}
+
+static void logi_dj_ll_close(struct hid_device *hid)
+{
+ dbg_hid("%s:%s\n", __func__, hid->phys);
+}
+
+static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
+ size_t count,
+ unsigned char report_type)
+{
+ /* Called by hid raw to send data */
+ dbg_hid("%s\n", __func__);
+
+ return 0;
+}
+
+static int logi_dj_ll_parse(struct hid_device *hid)
+{
+ struct dj_device *djdev = hid->driver_data;
+ int retval;
+
+ dbg_hid("%s\n", __func__);
+
+ djdev->hdev->version = 0x0111;
+ djdev->hdev->country = 0x00;
+
+ if (djdev->reports_supported & STD_KEYBOARD) {
+ dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n",
+ __func__, djdev->reports_supported);
+ retval = hid_parse_report(hid,
+ (u8 *) kbd_descriptor,
+ sizeof(kbd_descriptor));
+ if (retval) {
+ dbg_hid("%s: sending a kbd descriptor, hid_parse failed"
+ " error: %d\n", __func__, retval);
+ return retval;
+ }
+ }
+
+ if (djdev->reports_supported & STD_MOUSE) {
+ dbg_hid("%s: sending a mouse descriptor, reports_supported: "
+ "%x\n", __func__, djdev->reports_supported);
+ retval = hid_parse_report(hid,
+ (u8 *) mse_descriptor,
+ sizeof(mse_descriptor));
+ if (retval) {
+ dbg_hid("%s: sending a mouse descriptor, hid_parse "
+ "failed error: %d\n", __func__, retval);
+ return retval;
+ }
+ }
+
+ if (djdev->reports_supported & MULTIMEDIA) {
+ dbg_hid("%s: sending a multimedia report descriptor: %x\n",
+ __func__, djdev->reports_supported);
+ retval = hid_parse_report(hid,
+ (u8 *) consumer_descriptor,
+ sizeof(consumer_descriptor));
+ if (retval) {
+ dbg_hid("%s: sending a consumer_descriptor, hid_parse "
+ "failed error: %d\n", __func__, retval);
+ return retval;
+ }
+ }
+
+ if (djdev->reports_supported & POWER_KEYS) {
+ dbg_hid("%s: sending a power keys report descriptor: %x\n",
+ __func__, djdev->reports_supported);
+ retval = hid_parse_report(hid,
+ (u8 *) syscontrol_descriptor,
+ sizeof(syscontrol_descriptor));
+ if (retval) {
+ dbg_hid("%s: sending a syscontrol_descriptor, "
+ "hid_parse failed error: %d\n",
+ __func__, retval);
+ return retval;
+ }
+ }
+
+ if (djdev->reports_supported & MEDIA_CENTER) {
+ dbg_hid("%s: sending a media center report descriptor: %x\n",
+ __func__, djdev->reports_supported);
+ retval = hid_parse_report(hid,
+ (u8 *) media_descriptor,
+ sizeof(media_descriptor));
+ if (retval) {
+ dbg_hid("%s: sending a media_descriptor, hid_parse "
+ "failed error: %d\n", __func__, retval);
+ return retval;
+ }
+ }
+
+ if (djdev->reports_supported & KBD_LEDS) {
+ dbg_hid("%s: need to send kbd leds report descriptor: %x\n",
+ __func__, djdev->reports_supported);
+ }
+
+ return 0;
+}
+
+static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
+ unsigned int code, int value)
+{
+ /* Sent by the input layer to handle leds and Force Feedback */
+ struct hid_device *dj_hiddev = input_get_drvdata(dev);
+ struct dj_device *dj_dev = dj_hiddev->driver_data;
+
+ struct dj_receiver_dev *djrcv_dev =
+ dev_get_drvdata(dj_hiddev->dev.parent);
+ struct hid_device *dj_rcv_hiddev = djrcv_dev->hdev;
+ struct hid_report_enum *output_report_enum;
+
+ struct hid_field *field;
+ struct hid_report *report;
+ unsigned char data[8];
+ int offset;
+
+ dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
+ __func__, dev->phys, type, code, value);
+
+ if (type != EV_LED)
+ return -1;
+
+ offset = hidinput_find_field(dj_hiddev, type, code, &field);
+
+ if (offset == -1) {
+ dev_warn(&dev->dev, "event field not found\n");
+ return -1;
+ }
+ hid_set_field(field, offset, value);
+ hid_output_report(field->report, &data[0]);
+
+ output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
+ report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
+ hid_set_field(report->field[0], 0, dj_dev->device_index);
+ hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
+ hid_set_field(report->field[0], 2, data[1]);
+
+ usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT);
+
+ return 0;
+
+}
+
+static int logi_dj_ll_start(struct hid_device *hid)
+{
+ dbg_hid("%s\n", __func__);
+ return 0;
+}
+
+static void logi_dj_ll_stop(struct hid_device *hid)
+{
+ dbg_hid("%s\n", __func__);
+}
+
+
+static struct hid_ll_driver logi_dj_ll_driver = {
+ .parse = logi_dj_ll_parse,
+ .start = logi_dj_ll_start,
+ .stop = logi_dj_ll_stop,
+ .open = logi_dj_ll_open,
+ .close = logi_dj_ll_close,
+ .hidinput_input_event = logi_dj_ll_input_event,
+};
+
+
+static int logi_dj_raw_event(struct hid_device *hdev,
+ struct hid_report *report, u8 *data,
+ int size)
+{
+ struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+ struct dj_report *dj_report = (struct dj_report *) data;
+ unsigned long flags;
+ bool report_processed = false;
+
+ dbg_hid("%s, size:%d\n", __func__, size);
+
+ /* Here we receive all data coming from iface 2, there are 4 cases:
+ *
+ * 1) Data should continue its normal processing i.e. data does not
+ * come from the DJ collection, in which case we do nothing and
+ * return 0, so hid-core can continue normal processing (will forward
+ * to associated hidraw device)
+ *
+ * 2) Data is from DJ collection, and is intended for this driver i. e.
+ * data contains arrival, departure, etc notifications, in which case
+ * we queue them for delayed processing by the work queue. We return 1
+ * to hid-core as no further processing is required from it.
+ *
+ * 3) Data is from DJ collection, and informs a connection change,
+ * if the change means rf link loss, then we must send a null report
+ * to the upper layer to discard potentially pressed keys that may be
+ * repeated forever by the input layer. Return 1 to hid-core as no
+ * further processing is required.
+ *
+ * 4) Data is from DJ collection and is an actual input event from
+ * a paired DJ device in which case we forward it to the correct hid
+ * device (via hid_input_report() ) and return 1 so hid-core does not do
+ * anything else with it.
+ */
+
+ spin_lock_irqsave(&djrcv_dev->lock, flags);
+ if (dj_report->report_id == REPORT_ID_DJ_SHORT) {
+ switch (dj_report->report_type) {
+ case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
+ case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
+ logi_dj_recv_queue_notification(djrcv_dev, dj_report);
+ break;
+ case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
+ if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
+ STATUS_LINKLOSS) {
+ logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
+ }
+ break;
+ default:
+ logi_dj_recv_forward_report(djrcv_dev, dj_report);
+ }
+ report_processed = true;
+ }
+ spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+
+ return report_processed;
+}
+
+static int logi_dj_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+ struct dj_receiver_dev *djrcv_dev;
+ int retval;
+
+ if (is_dj_device((struct dj_device *)hdev->driver_data))
+ return -ENODEV;
+
+ dbg_hid("%s called for ifnum %d\n", __func__,
+ intf->cur_altsetting->desc.bInterfaceNumber);
+
+ /* Ignore interfaces 0 and 1, they will not carry any data, dont create
+ * any hid_device for them */
+ if (intf->cur_altsetting->desc.bInterfaceNumber !=
+ LOGITECH_DJ_INTERFACE_NUMBER) {
+ dbg_hid("%s: ignoring ifnum %d\n", __func__,
+ intf->cur_altsetting->desc.bInterfaceNumber);
+ return -ENODEV;
+ }
+
+ /* Treat interface 2 */
+
+ djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL);
+ if (!djrcv_dev) {
+ dev_err(&hdev->dev,
+ "%s:failed allocating dj_receiver_dev\n", __func__);
+ return -ENOMEM;
+ }
+ djrcv_dev->hdev = hdev;
+ INIT_WORK(&djrcv_dev->work, delayedwork_callback);
+ spin_lock_init(&djrcv_dev->lock);
+ if (kfifo_alloc(&djrcv_dev->notif_fifo,
+ DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
+ GFP_KERNEL)) {
+ dev_err(&hdev->dev,
+ "%s:failed allocating notif_fifo\n", __func__);
+ kfree(djrcv_dev);
+ return -ENOMEM;
+ }
+ hid_set_drvdata(hdev, djrcv_dev);
+
+ /* Call to usbhid to fetch the HID descriptors of interface 2 and
+ * subsequently call to the hid/hid-core to parse the fetched
+ * descriptors, this will in turn create the hidraw and hiddev nodes
+ * for interface 2 of the receiver */
+ retval = hid_parse(hdev);
+ if (retval) {
+ dev_err(&hdev->dev,
+ "%s:parse of interface 2 failed\n", __func__);
+ goto hid_parse_fail;
+ }
+
+ /* Starts the usb device and connects to upper interfaces hiddev and
+ * hidraw */
+ retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (retval) {
+ dev_err(&hdev->dev,
+ "%s:hid_hw_start returned error\n", __func__);
+ goto hid_hw_start_fail;
+ }
+
+ retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
+ if (retval < 0) {
+ dev_err(&hdev->dev,
+ "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
+ __func__, retval);
+ goto switch_to_dj_mode_fail;
+ }
+
+ /* This is enabling the polling urb on the IN endpoint */
+ retval = hdev->ll_driver->open(hdev);
+ if (retval < 0) {
+ dev_err(&hdev->dev, "%s:hdev->ll_driver->open returned "
+ "error:%d\n", __func__, retval);
+ goto llopen_failed;
+ }
+
+ retval = logi_dj_recv_query_paired_devices(djrcv_dev);
+ if (retval < 0) {
+ dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
+ "error:%d\n", __func__, retval);
+ goto logi_dj_recv_query_paired_devices_failed;
+ }
+
+ return retval;
+
+logi_dj_recv_query_paired_devices_failed:
+ hdev->ll_driver->close(hdev);
+
+llopen_failed:
+switch_to_dj_mode_fail:
+ hid_hw_stop(hdev);
+
+hid_hw_start_fail:
+hid_parse_fail:
+ kfifo_free(&djrcv_dev->notif_fifo);
+ kfree(djrcv_dev);
+ hid_set_drvdata(hdev, NULL);
+ return retval;
+
+}
+
+#ifdef CONFIG_PM
+static int logi_dj_reset_resume(struct hid_device *hdev)
+{
+ int retval;
+ struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+
+ retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
+ if (retval < 0) {
+ dev_err(&hdev->dev,
+ "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
+ __func__, retval);
+ }
+
+ return 0;
+}
+#endif
+
+static void logi_dj_remove(struct hid_device *hdev)
+{
+ struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+ struct dj_device *dj_dev;
+ int i;
+
+ dbg_hid("%s\n", __func__);
+
+ cancel_work_sync(&djrcv_dev->work);
+
+ hdev->ll_driver->close(hdev);
+ hid_hw_stop(hdev);
+
+ /* I suppose that at this point the only context that can access
+ * the djrecv_data is this thread as the work item is guaranteed to
+ * have finished and no more raw_event callbacks should arrive after
+ * the remove callback was triggered so no locks are put around the
+ * code below */
+ for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
+ dj_dev = djrcv_dev->paired_dj_devices[i];
+ if (dj_dev != NULL) {
+ hid_destroy_device(dj_dev->hdev);
+ kfree(dj_dev);
+ djrcv_dev->paired_dj_devices[i] = NULL;
+ }
+ }
+
+ kfifo_free(&djrcv_dev->notif_fifo);
+ kfree(djrcv_dev);
+ hid_set_drvdata(hdev, NULL);
+}
+
+static int logi_djdevice_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ int ret;
+ struct dj_device *dj_dev = hdev->driver_data;
+
+ if (!is_dj_device(dj_dev))
+ return -ENODEV;
+
+ ret = hid_parse(hdev);
+ if (!ret)
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+ return ret;
+}
+
+static const struct hid_device_id logi_dj_receivers[] = {
+ {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+ USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
+ {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+ USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(hid, logi_dj_receivers);
+
+static struct hid_driver logi_djreceiver_driver = {
+ .name = "logitech-djreceiver",
+ .id_table = logi_dj_receivers,
+ .probe = logi_dj_probe,
+ .remove = logi_dj_remove,
+ .raw_event = logi_dj_raw_event,
+#ifdef CONFIG_PM
+ .reset_resume = logi_dj_reset_resume,
+#endif
+};
+
+
+static const struct hid_device_id logi_dj_devices[] = {
+ {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+ USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
+ {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+ USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
+ {}
+};
+
+static struct hid_driver logi_djdevice_driver = {
+ .name = "logitech-djdevice",
+ .id_table = logi_dj_devices,
+ .probe = logi_djdevice_probe,
+};
+
+
+static int __init logi_dj_init(void)
+{
+ int retval;
+
+ dbg_hid("Logitech-DJ:%s\n", __func__);
+
+ retval = hid_register_driver(&logi_djreceiver_driver);
+ if (retval)
+ return retval;
+
+ retval = hid_register_driver(&logi_djdevice_driver);
+ if (retval)
+ hid_unregister_driver(&logi_djreceiver_driver);
+
+ return retval;
+
+}
+
+static void __exit logi_dj_exit(void)
+{
+ dbg_hid("Logitech-DJ:%s\n", __func__);
+
+ hid_unregister_driver(&logi_djdevice_driver);
+ hid_unregister_driver(&logi_djreceiver_driver);
+
+}
+
+module_init(logi_dj_init);
+module_exit(logi_dj_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Logitech");
+MODULE_AUTHOR("Nestor Lopez Casado");
+MODULE_AUTHOR("nlopezcasad@logitech.com");
diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h
new file mode 100644
index 000000000000..fd28a5e0ca3b
--- /dev/null
+++ b/drivers/hid/hid-logitech-dj.h
@@ -0,0 +1,123 @@
+#ifndef __HID_LOGITECH_DJ_H
+#define __HID_LOGITECH_DJ_H
+
+/*
+ * HID driver for Logitech Unifying receivers
+ *
+ * Copyright (c) 2011 Logitech
+ */
+
+/*
+ * 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
+ *
+ */
+
+#include <linux/kfifo.h>
+
+#define DJ_MAX_PAIRED_DEVICES 6
+#define DJ_MAX_NUMBER_NOTIFICATIONS 8
+#define DJ_DEVICE_INDEX_MIN 1
+#define DJ_DEVICE_INDEX_MAX 6
+
+#define DJREPORT_SHORT_LENGTH 15
+#define DJREPORT_LONG_LENGTH 32
+
+#define REPORT_ID_DJ_SHORT 0x20
+#define REPORT_ID_DJ_LONG 0x21
+
+#define REPORT_TYPE_RFREPORT_FIRST 0x01
+#define REPORT_TYPE_RFREPORT_LAST 0x1F
+
+/* Command Switch to DJ mode */
+#define REPORT_TYPE_CMD_SWITCH 0x80
+#define CMD_SWITCH_PARAM_DEVBITFIELD 0x00
+#define CMD_SWITCH_PARAM_TIMEOUT_SECONDS 0x01
+#define TIMEOUT_NO_KEEPALIVE 0x00
+
+/* Command to Get the list of Paired devices */
+#define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x81
+
+/* Device Paired Notification */
+#define REPORT_TYPE_NOTIF_DEVICE_PAIRED 0x41
+#define SPFUNCTION_MORE_NOTIF_EXPECTED 0x01
+#define SPFUNCTION_DEVICE_LIST_EMPTY 0x02
+#define DEVICE_PAIRED_PARAM_SPFUNCTION 0x00
+#define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB 0x01
+#define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB 0x02
+#define DEVICE_PAIRED_RF_REPORT_TYPE 0x03
+
+/* Device Un-Paired Notification */
+#define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x40
+
+
+/* Connection Status Notification */
+#define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x42
+#define CONNECTION_STATUS_PARAM_STATUS 0x00
+#define STATUS_LINKLOSS 0x01
+
+/* Error Notification */
+#define REPORT_TYPE_NOTIF_ERROR 0x7F
+#define NOTIF_ERROR_PARAM_ETYPE 0x00
+#define ETYPE_KEEPALIVE_TIMEOUT 0x01
+
+/* supported DJ HID && RF report types */
+#define REPORT_TYPE_KEYBOARD 0x01
+#define REPORT_TYPE_MOUSE 0x02
+#define REPORT_TYPE_CONSUMER_CONTROL 0x03
+#define REPORT_TYPE_SYSTEM_CONTROL 0x04
+#define REPORT_TYPE_MEDIA_CENTER 0x08
+#define REPORT_TYPE_LEDS 0x0E
+
+/* RF Report types bitfield */
+#define STD_KEYBOARD 0x00000002
+#define STD_MOUSE 0x00000004
+#define MULTIMEDIA 0x00000008
+#define POWER_KEYS 0x00000010
+#define MEDIA_CENTER 0x00000100
+#define KBD_LEDS 0x00004000
+
+struct dj_report {
+ u8 report_id;
+ u8 device_index;
+ u8 report_type;
+ u8 report_params[DJREPORT_SHORT_LENGTH - 3];
+};
+
+struct dj_receiver_dev {
+ struct hid_device *hdev;
+ struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES +
+ DJ_DEVICE_INDEX_MIN];
+ struct work_struct work;
+ struct kfifo notif_fifo;
+ spinlock_t lock;
+};
+
+struct dj_device {
+ struct hid_device *hdev;
+ struct dj_receiver_dev *dj_receiver_dev;
+ u32 reports_supported;
+ u8 device_index;
+};
+
+/**
+ * is_dj_device - know if the given dj_device is not the receiver.
+ * @dj_dev: the dj device to test
+ *
+ * This macro tests if a struct dj_device pointer is a device created
+ * by the bus enumarator.
+ */
+#define is_dj_device(dj_dev) \
+ (&(dj_dev)->dj_receiver_dev->hdev->dev == (dj_dev)->hdev->dev.parent)
+
+#endif
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index f0fbd7bd239e..2ab71758e2e2 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -405,6 +405,13 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h
__set_bit(REL_HWHEEL, input->relbit);
}
} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
+ /* input->keybit is initialized with incorrect button info
+ * for Magic Trackpad. There really is only one physical
+ * button (BTN_LEFT == BTN_MOUSE). Make sure we don't
+ * advertise buttons that don't exist...
+ */
+ __clear_bit(BTN_RIGHT, input->keybit);
+ __clear_bit(BTN_MIDDLE, input->keybit);
__set_bit(BTN_MOUSE, input->keybit);
__set_bit(BTN_TOOL_FINGER, input->keybit);
__set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 58d0e7aaf088..f1c909f1b239 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -47,10 +47,11 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1)
#define MT_QUIRK_CYPRESS (1 << 2)
#define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3)
-#define MT_QUIRK_VALID_IS_INRANGE (1 << 4)
-#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5)
-#define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 6)
-#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 7)
+#define MT_QUIRK_ALWAYS_VALID (1 << 4)
+#define MT_QUIRK_VALID_IS_INRANGE (1 << 5)
+#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6)
+#define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 7)
+#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8)
struct mt_slot {
__s32 x, y, p, w, h;
@@ -86,11 +87,12 @@ struct mt_class {
/* classes of device behavior */
#define MT_CLS_DEFAULT 0x0001
-#define MT_CLS_CONFIDENCE 0x0002
-#define MT_CLS_CONFIDENCE_MINUS_ONE 0x0003
-#define MT_CLS_DUAL_INRANGE_CONTACTID 0x0004
-#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0005
-#define MT_CLS_DUAL_NSMU_CONTACTID 0x0006
+#define MT_CLS_SERIAL 0x0002
+#define MT_CLS_CONFIDENCE 0x0003
+#define MT_CLS_CONFIDENCE_MINUS_ONE 0x0004
+#define MT_CLS_DUAL_INRANGE_CONTACTID 0x0005
+#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0006
+#define MT_CLS_DUAL_NSMU_CONTACTID 0x0007
/* vendor specific classes */
#define MT_CLS_3M 0x0101
@@ -134,6 +136,8 @@ static int find_slot_from_contactid(struct mt_device *td)
struct mt_class mt_classes[] = {
{ .name = MT_CLS_DEFAULT,
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
+ { .name = MT_CLS_SERIAL,
+ .quirks = MT_QUIRK_ALWAYS_VALID},
{ .name = MT_CLS_CONFIDENCE,
.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
{ .name = MT_CLS_CONFIDENCE_MINUS_ONE,
@@ -213,6 +217,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct mt_class *cls = td->mtclass;
__s32 quirks = cls->quirks;
+ /* Only map fields from TouchScreen or TouchPad collections.
+ * We need to ignore fields that belong to other collections
+ * such as Mouse that might have the same GenericDesktop usages. */
+ if (field->application == HID_DG_TOUCHSCREEN)
+ set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
+ else if (field->application == HID_DG_TOUCHPAD)
+ set_bit(INPUT_PROP_POINTER, hi->input->propbit);
+ else
+ return 0;
+
switch (usage->hid & HID_USAGE_PAGE) {
case HID_UP_GENDESK:
@@ -435,7 +449,9 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
switch (usage->hid) {
case HID_DG_INRANGE:
- if (quirks & MT_QUIRK_VALID_IS_INRANGE)
+ if (quirks & MT_QUIRK_ALWAYS_VALID)
+ td->curvalid = true;
+ else if (quirks & MT_QUIRK_VALID_IS_INRANGE)
td->curvalid = value;
break;
case HID_DG_TIPSWITCH:
@@ -662,6 +678,11 @@ static const struct hid_device_id mt_devices[] = {
HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
USB_DEVICE_ID_GOODTOUCH_000f) },
+ /* Ideacom panel */
+ { .driver_data = MT_CLS_SERIAL,
+ HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
+ USB_DEVICE_ID_IDEACOM_IDC6650) },
+
/* Ilitek dual touch panel */
{ .driver_data = MT_CLS_DEFAULT,
HID_USB_DEVICE(USB_VENDOR_ID_ILITEK,
@@ -672,6 +693,11 @@ static const struct hid_device_id mt_devices[] = {
HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
+ /* LG Display panels */
+ { .driver_data = MT_CLS_DEFAULT,
+ HID_USB_DEVICE(USB_VENDOR_ID_LG,
+ USB_DEVICE_ID_LG_MULTITOUCH) },
+
/* Lumio panels */
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
index 9d8710f8bc79..1782693819f3 100644
--- a/drivers/hid/hid-picolcd.c
+++ b/drivers/hid/hid-picolcd.c
@@ -2409,7 +2409,7 @@ static int picolcd_raw_event(struct hid_device *hdev,
#ifdef CONFIG_PM
static int picolcd_suspend(struct hid_device *hdev, pm_message_t message)
{
- if (message.event & PM_EVENT_AUTO)
+ if (PMSG_IS_AUTO(message))
return 0;
picolcd_suspend_backlight(hid_get_drvdata(hdev));
diff --git a/drivers/hid/hid-primax.c b/drivers/hid/hid-primax.c
new file mode 100644
index 000000000000..4d3c60d88318
--- /dev/null
+++ b/drivers/hid/hid-primax.c
@@ -0,0 +1,117 @@
+/*
+ * HID driver for primax and similar keyboards with in-band modifiers
+ *
+ * Copyright 2011 Google Inc. All Rights Reserved
+ *
+ * Author:
+ * Terry Lambert <tlambert@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.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static int px_raw_event(struct hid_device *hid, struct hid_report *report,
+ u8 *data, int size)
+{
+ int idx = size;
+
+ switch (report->id) {
+ case 0: /* keyboard input */
+ /*
+ * Convert in-band modifier key values into out of band
+ * modifier bits and pull the key strokes from the report.
+ * Thus a report data set which looked like:
+ *
+ * [00][00][E0][30][00][00][00][00]
+ * (no modifier bits + "Left Shift" key + "1" key)
+ *
+ * Would be converted to:
+ *
+ * [01][00][00][30][00][00][00][00]
+ * (Left Shift modifier bit + "1" key)
+ *
+ * As long as it's in the size range, the upper level
+ * drivers don't particularly care if there are in-band
+ * 0-valued keys, so they don't stop parsing.
+ */
+ while (--idx > 1) {
+ if (data[idx] < 0xE0 || data[idx] > 0xE7)
+ continue;
+ data[0] |= (1 << (data[idx] - 0xE0));
+ data[idx] = 0;
+ }
+ hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0);
+ return 1;
+
+ default: /* unknown report */
+ /* Unknown report type; pass upstream */
+ hid_info(hid, "unknown report type %d\n", report->id);
+ break;
+ }
+
+ return 0;
+}
+
+static int px_probe(struct hid_device *hid, const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hid);
+ if (ret) {
+ hid_err(hid, "parse failed\n");
+ goto fail;
+ }
+
+ ret = hid_hw_start(hid, HID_CONNECT_DEFAULT);
+ if (ret)
+ hid_err(hid, "hw start failed\n");
+
+fail:
+ return ret;
+}
+
+static void px_remove(struct hid_device *hid)
+{
+ hid_hw_stop(hid);
+}
+
+static const struct hid_device_id px_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, px_devices);
+
+static struct hid_driver px_driver = {
+ .name = "primax",
+ .id_table = px_devices,
+ .raw_event = px_raw_event,
+ .probe = px_probe,
+ .remove = px_remove,
+};
+
+static int __init px_init(void)
+{
+ return hid_register_driver(&px_driver);
+}
+
+static void __exit px_exit(void)
+{
+ hid_unregister_driver(&px_driver);
+}
+
+module_init(px_init);
+module_exit(px_exit);
+MODULE_AUTHOR("Terry Lambert <tlambert@google.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index 158b389d0fb7..f779009104eb 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -816,7 +816,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (pm == NULL) {
hid_err(hdev, "can't alloc descriptor\n");
ret = -ENOMEM;
- goto err_free;
+ goto err_free_pk;
}
pm->pk = pk;
@@ -849,10 +849,10 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
err_stop:
hid_hw_stop(hdev);
err_free:
- if (pm != NULL)
- kfree(pm);
-
+ kfree(pm);
+err_free_pk:
kfree(pk);
+
return ret;
}
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index 2b8f3a31ffb3..e2072afb34bb 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -37,6 +37,21 @@
static uint profile_numbers[5] = {0, 1, 2, 3, 4};
+static void kone_profile_activated(struct kone_device *kone, uint new_profile)
+{
+ kone->actual_profile = new_profile;
+ kone->actual_dpi = kone->profiles[new_profile - 1].startup_dpi;
+}
+
+static void kone_profile_report(struct kone_device *kone, uint new_profile)
+{
+ struct kone_roccat_report roccat_report;
+ roccat_report.event = kone_mouse_event_switch_profile;
+ roccat_report.value = new_profile;
+ roccat_report.key = 0;
+ roccat_report_event(kone->chrdev_minor, (uint8_t *)&roccat_report);
+}
+
static int kone_receive(struct usb_device *usb_dev, uint usb_command,
void *data, uint size)
{
@@ -283,7 +298,7 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
container_of(kobj, struct device, kobj)->parent->parent;
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval = 0, difference;
+ int retval = 0, difference, old_profile;
/* I need to get my data in one piece */
if (off != 0 || count != sizeof(struct kone_settings))
@@ -294,21 +309,20 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
if (difference) {
retval = kone_set_settings(usb_dev,
(struct kone_settings const *)buf);
- if (!retval)
- memcpy(&kone->settings, buf,
- sizeof(struct kone_settings));
- }
- mutex_unlock(&kone->kone_lock);
+ if (retval) {
+ mutex_unlock(&kone->kone_lock);
+ return retval;
+ }
- if (retval)
- return retval;
+ old_profile = kone->settings.startup_profile;
+ memcpy(&kone->settings, buf, sizeof(struct kone_settings));
- /*
- * If we get here, treat settings as okay and update actual values
- * according to startup_profile
- */
- kone->actual_profile = kone->settings.startup_profile;
- kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
+ kone_profile_activated(kone, kone->settings.startup_profile);
+
+ if (kone->settings.startup_profile != old_profile)
+ kone_profile_report(kone, kone->settings.startup_profile);
+ }
+ mutex_unlock(&kone->kone_lock);
return sizeof(struct kone_settings);
}
@@ -501,6 +515,8 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
goto exit_no_settings;
goto exit_unlock;
}
+ /* calibration resets profile */
+ kone_profile_activated(kone, kone->settings.startup_profile);
}
retval = size;
@@ -544,16 +560,16 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
kone_set_settings_checksum(&kone->settings);
retval = kone_set_settings(usb_dev, &kone->settings);
-
- mutex_unlock(&kone->kone_lock);
-
- if (retval)
+ if (retval) {
+ mutex_unlock(&kone->kone_lock);
return retval;
+ }
/* changing the startup profile immediately activates this profile */
- kone->actual_profile = new_startup_profile;
- kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
+ kone_profile_activated(kone, new_startup_profile);
+ kone_profile_report(kone, new_startup_profile);
+ mutex_unlock(&kone->kone_lock);
return size;
}
@@ -665,8 +681,7 @@ static int kone_init_kone_device_struct(struct usb_device *usb_dev,
if (retval)
return retval;
- kone->actual_profile = kone->settings.startup_profile;
- kone->actual_dpi = kone->profiles[kone->actual_profile].startup_dpi;
+ kone_profile_activated(kone, kone->settings.startup_profile);
return 0;
}
@@ -776,10 +791,10 @@ static void kone_keep_values_up_to_date(struct kone_device *kone,
{
switch (event->event) {
case kone_mouse_event_switch_profile:
+ kone->actual_dpi = kone->profiles[event->value - 1].
+ startup_dpi;
case kone_mouse_event_osd_profile:
kone->actual_profile = event->value;
- kone->actual_dpi = kone->profiles[kone->actual_profile - 1].
- startup_dpi;
break;
case kone_mouse_event_switch_dpi:
case kone_mouse_event_osd_dpi:
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index 1f8336e3f584..112d934132c8 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -323,6 +323,7 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
struct usb_device *usb_dev;
unsigned long profile;
int retval;
+ struct kovaplus_roccat_report roccat_report;
dev = dev->parent->parent;
kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
@@ -337,10 +338,22 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
mutex_lock(&kovaplus->kovaplus_lock);
retval = kovaplus_set_actual_profile(usb_dev, profile);
+ if (retval) {
+ mutex_unlock(&kovaplus->kovaplus_lock);
+ return retval;
+ }
+
kovaplus_profile_activated(kovaplus, profile);
+
+ roccat_report.type = KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1;
+ roccat_report.profile = profile + 1;
+ roccat_report.button = 0;
+ roccat_report.data1 = profile + 1;
+ roccat_report.data2 = 0;
+ roccat_report_event(kovaplus->chrdev_minor,
+ (uint8_t const *)&roccat_report);
+
mutex_unlock(&kovaplus->kovaplus_lock);
- if (retval)
- return retval;
return size;
}
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
index 8140776bd8c5..df05c1b1064f 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -298,6 +298,7 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval = 0;
int difference;
+ struct pyra_roccat_report roccat_report;
if (off != 0 || count != sizeof(struct pyra_settings))
return -EINVAL;
@@ -307,17 +308,23 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
if (difference) {
retval = pyra_set_settings(usb_dev,
(struct pyra_settings const *)buf);
- if (!retval)
- memcpy(&pyra->settings, buf,
- sizeof(struct pyra_settings));
- }
- mutex_unlock(&pyra->pyra_lock);
+ if (retval) {
+ mutex_unlock(&pyra->pyra_lock);
+ return retval;
+ }
- if (retval)
- return retval;
+ memcpy(&pyra->settings, buf,
+ sizeof(struct pyra_settings));
- profile_activated(pyra, pyra->settings.startup_profile);
+ profile_activated(pyra, pyra->settings.startup_profile);
+ 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);
+ }
+ mutex_unlock(&pyra->pyra_lock);
return sizeof(struct pyra_settings);
}
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index 5666e7587b18..56ce12c23b02 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -162,27 +162,27 @@ static int roccat_open(struct inode *inode, struct file *file)
device = devices[minor];
- mutex_lock(&device->readers_lock);
-
if (!device) {
pr_emerg("roccat device with minor %d doesn't exist\n", minor);
error = -ENODEV;
- goto exit_err;
+ goto exit_err_devices;
}
+ mutex_lock(&device->readers_lock);
+
if (!device->open++) {
/* power on device on adding first reader */
error = hid_hw_power(device->hid, PM_HINT_FULLON);
if (error < 0) {
--device->open;
- goto exit_err;
+ goto exit_err_readers;
}
error = hid_hw_open(device->hid);
if (error < 0) {
hid_hw_power(device->hid, PM_HINT_NORMAL);
--device->open;
- goto exit_err;
+ goto exit_err_readers;
}
}
@@ -193,13 +193,13 @@ static int roccat_open(struct inode *inode, struct file *file)
list_add_tail(&reader->node, &device->readers);
file->private_data = reader;
-exit_unlock:
+exit_err_readers:
mutex_unlock(&device->readers_lock);
+exit_err_devices:
mutex_unlock(&devices_lock);
+ if (error)
+ kfree(reader);
return error;
-exit_err:
- kfree(reader);
- goto exit_unlock;
}
static int roccat_release(struct inode *inode, struct file *file)
diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c
index 16f7cafc9695..670da9109f86 100644
--- a/drivers/hid/hid-sjoy.c
+++ b/drivers/hid/hid-sjoy.c
@@ -65,8 +65,7 @@ static int sjoyff_init(struct hid_device *hid)
{
struct sjoyff_device *sjoyff;
struct hid_report *report;
- struct hid_input *hidinput = list_entry(hid->inputs.next,
- struct hid_input, list);
+ struct hid_input *hidinput;
struct list_head *report_list =
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct list_head *report_ptr = report_list;
@@ -78,43 +77,45 @@ static int sjoyff_init(struct hid_device *hid)
return -ENODEV;
}
- report_ptr = report_ptr->next;
+ list_for_each_entry(hidinput, &hid->inputs, list) {
+ report_ptr = report_ptr->next;
- if (report_ptr == report_list) {
- hid_err(hid, "required output report is missing\n");
- return -ENODEV;
- }
+ if (report_ptr == report_list) {
+ hid_err(hid, "required output report is missing\n");
+ return -ENODEV;
+ }
- report = list_entry(report_ptr, struct hid_report, list);
- if (report->maxfield < 1) {
- hid_err(hid, "no fields in the report\n");
- return -ENODEV;
- }
+ report = list_entry(report_ptr, struct hid_report, list);
+ if (report->maxfield < 1) {
+ hid_err(hid, "no fields in the report\n");
+ return -ENODEV;
+ }
- if (report->field[0]->report_count < 3) {
- hid_err(hid, "not enough values in the field\n");
- return -ENODEV;
- }
+ if (report->field[0]->report_count < 3) {
+ hid_err(hid, "not enough values in the field\n");
+ return -ENODEV;
+ }
- sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL);
- if (!sjoyff)
- return -ENOMEM;
+ sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL);
+ if (!sjoyff)
+ return -ENOMEM;
- dev = hidinput->input;
+ dev = hidinput->input;
- set_bit(FF_RUMBLE, dev->ffbit);
+ set_bit(FF_RUMBLE, dev->ffbit);
- error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
- if (error) {
- kfree(sjoyff);
- return error;
- }
+ error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
+ if (error) {
+ kfree(sjoyff);
+ return error;
+ }
- sjoyff->report = report;
- sjoyff->report->field[0]->value[0] = 0x01;
- sjoyff->report->field[0]->value[1] = 0x00;
- sjoyff->report->field[0]->value[2] = 0x00;
- usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+ sjoyff->report = report;
+ sjoyff->report->field[0]->value[0] = 0x01;
+ sjoyff->report->field[0]->value[1] = 0x00;
+ sjoyff->report->field[0]->value[2] = 0x00;
+ usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+ }
hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n");
@@ -131,6 +132,8 @@ static int sjoy_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
+ hdev->quirks |= id->driver_data;
+
ret = hid_parse(hdev);
if (ret) {
hid_err(hdev, "parse failed\n");
@@ -151,7 +154,17 @@ err:
}
static const struct hid_device_id sjoy_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO),
+ .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
+ HID_QUIRK_SKIP_OUTPUT_REPORTS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO),
+ .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
+ HID_QUIRK_SKIP_OUTPUT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD),
+ .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
+ HID_QUIRK_SKIP_OUTPUT_REPORTS },
{ }
};
MODULE_DEVICE_TABLE(hid, sjoy_devices);
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index 72ca689b6474..17bb88f782b6 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -304,11 +304,51 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
return 1;
}
+static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage, unsigned long **bit,
+ int *max)
+{
+ struct input_dev *input = hi->input;
+
+ __set_bit(INPUT_PROP_POINTER, input->propbit);
+
+ /* Basics */
+ input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
+
+ __set_bit(REL_WHEEL, input->relbit);
+
+ __set_bit(BTN_TOOL_PEN, input->keybit);
+ __set_bit(BTN_TOUCH, input->keybit);
+ __set_bit(BTN_STYLUS, input->keybit);
+ __set_bit(BTN_STYLUS2, input->keybit);
+ __set_bit(BTN_LEFT, input->keybit);
+ __set_bit(BTN_RIGHT, input->keybit);
+ __set_bit(BTN_MIDDLE, input->keybit);
+
+ /* Pad */
+ input->evbit[0] |= BIT(EV_MSC);
+
+ __set_bit(MSC_SERIAL, input->mscbit);
+
+ __set_bit(BTN_0, input->keybit);
+ __set_bit(BTN_1, input->keybit);
+ __set_bit(BTN_TOOL_FINGER, input->keybit);
+
+ /* Distance, rubber and mouse */
+ __set_bit(BTN_TOOL_RUBBER, input->keybit);
+ __set_bit(BTN_TOOL_MOUSE, input->keybit);
+
+ input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
+ input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
+ input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
+ input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
+
+ return 0;
+}
+
static int wacom_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
- struct hid_input *hidinput;
- struct input_dev *input;
struct wacom_data *wdata;
int ret;
@@ -370,42 +410,6 @@ static int wacom_probe(struct hid_device *hdev,
goto err_ac;
}
#endif
- hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
- input = hidinput->input;
-
- __set_bit(INPUT_PROP_POINTER, input->propbit);
-
- /* Basics */
- input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
-
- __set_bit(REL_WHEEL, input->relbit);
-
- __set_bit(BTN_TOOL_PEN, input->keybit);
- __set_bit(BTN_TOUCH, input->keybit);
- __set_bit(BTN_STYLUS, input->keybit);
- __set_bit(BTN_STYLUS2, input->keybit);
- __set_bit(BTN_LEFT, input->keybit);
- __set_bit(BTN_RIGHT, input->keybit);
- __set_bit(BTN_MIDDLE, input->keybit);
-
- /* Pad */
- input->evbit[0] |= BIT(EV_MSC);
-
- __set_bit(MSC_SERIAL, input->mscbit);
-
- __set_bit(BTN_0, input->keybit);
- __set_bit(BTN_1, input->keybit);
- __set_bit(BTN_TOOL_FINGER, input->keybit);
-
- /* Distance, rubber and mouse */
- __set_bit(BTN_TOOL_RUBBER, input->keybit);
- __set_bit(BTN_TOOL_MOUSE, input->keybit);
-
- input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
- input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
- input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
- input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
-
return 0;
#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
@@ -448,6 +452,7 @@ static struct hid_driver wacom_driver = {
.probe = wacom_probe,
.remove = wacom_remove,
.raw_event = wacom_raw_event,
+ .input_mapped = wacom_input_mapped,
};
static int __init wacom_init(void)
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c
index 85a02e5f9fe8..76739c07fa3c 100644
--- a/drivers/hid/hid-wiimote.c
+++ b/drivers/hid/hid-wiimote.c
@@ -10,15 +10,18 @@
* any later version.
*/
+#include <linux/completion.h>
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/leds.h>
#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/power_supply.h>
#include <linux/spinlock.h>
#include "hid-ids.h"
-#define WIIMOTE_VERSION "0.1"
+#define WIIMOTE_VERSION "0.2"
#define WIIMOTE_NAME "Nintendo Wii Remote"
#define WIIMOTE_BUFSIZE 32
@@ -30,12 +33,26 @@ struct wiimote_buf {
struct wiimote_state {
spinlock_t lock;
__u8 flags;
+ __u8 accel_split[2];
+
+ /* synchronous cmd requests */
+ struct mutex sync;
+ struct completion ready;
+ int cmd;
+ __u32 opt;
+
+ /* results of synchronous requests */
+ __u8 cmd_battery;
+ __u8 cmd_err;
};
struct wiimote_data {
struct hid_device *hdev;
struct input_dev *input;
struct led_classdev *leds[4];
+ struct input_dev *accel;
+ struct input_dev *ir;
+ struct power_supply battery;
spinlock_t qlock;
__u8 head;
@@ -46,23 +63,47 @@ struct wiimote_data {
struct wiimote_state state;
};
-#define WIIPROTO_FLAG_LED1 0x01
-#define WIIPROTO_FLAG_LED2 0x02
-#define WIIPROTO_FLAG_LED3 0x04
-#define WIIPROTO_FLAG_LED4 0x08
+#define WIIPROTO_FLAG_LED1 0x01
+#define WIIPROTO_FLAG_LED2 0x02
+#define WIIPROTO_FLAG_LED3 0x04
+#define WIIPROTO_FLAG_LED4 0x08
+#define WIIPROTO_FLAG_RUMBLE 0x10
+#define WIIPROTO_FLAG_ACCEL 0x20
+#define WIIPROTO_FLAG_IR_BASIC 0x40
+#define WIIPROTO_FLAG_IR_EXT 0x80
+#define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */
#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
+#define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \
+ WIIPROTO_FLAG_IR_FULL)
/* return flag for led \num */
#define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1))
enum wiiproto_reqs {
WIIPROTO_REQ_NULL = 0x0,
+ WIIPROTO_REQ_RUMBLE = 0x10,
WIIPROTO_REQ_LED = 0x11,
WIIPROTO_REQ_DRM = 0x12,
+ WIIPROTO_REQ_IR1 = 0x13,
+ WIIPROTO_REQ_SREQ = 0x15,
+ WIIPROTO_REQ_WMEM = 0x16,
+ WIIPROTO_REQ_RMEM = 0x17,
+ WIIPROTO_REQ_IR2 = 0x1a,
WIIPROTO_REQ_STATUS = 0x20,
+ WIIPROTO_REQ_DATA = 0x21,
WIIPROTO_REQ_RETURN = 0x22,
WIIPROTO_REQ_DRM_K = 0x30,
+ WIIPROTO_REQ_DRM_KA = 0x31,
+ WIIPROTO_REQ_DRM_KE = 0x32,
+ WIIPROTO_REQ_DRM_KAI = 0x33,
+ WIIPROTO_REQ_DRM_KEE = 0x34,
+ WIIPROTO_REQ_DRM_KAE = 0x35,
+ WIIPROTO_REQ_DRM_KIE = 0x36,
+ WIIPROTO_REQ_DRM_KAIE = 0x37,
+ WIIPROTO_REQ_DRM_E = 0x3d,
+ WIIPROTO_REQ_DRM_SKAI1 = 0x3e,
+ WIIPROTO_REQ_DRM_SKAI2 = 0x3f,
};
enum wiiproto_keys {
@@ -94,6 +135,56 @@ static __u16 wiiproto_keymap[] = {
BTN_MODE, /* WIIPROTO_KEY_HOME */
};
+static enum power_supply_property wiimote_battery_props[] = {
+ POWER_SUPPLY_PROP_CAPACITY
+};
+
+/* requires the state.lock spinlock to be held */
+static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd,
+ __u32 opt)
+{
+ return wdata->state.cmd == cmd && wdata->state.opt == opt;
+}
+
+/* requires the state.lock spinlock to be held */
+static inline void wiimote_cmd_complete(struct wiimote_data *wdata)
+{
+ wdata->state.cmd = WIIPROTO_REQ_NULL;
+ complete(&wdata->state.ready);
+}
+
+static inline int wiimote_cmd_acquire(struct wiimote_data *wdata)
+{
+ return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0;
+}
+
+/* requires the state.lock spinlock to be held */
+static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd,
+ __u32 opt)
+{
+ INIT_COMPLETION(wdata->state.ready);
+ wdata->state.cmd = cmd;
+ wdata->state.opt = opt;
+}
+
+static inline void wiimote_cmd_release(struct wiimote_data *wdata)
+{
+ mutex_unlock(&wdata->state.sync);
+}
+
+static inline int wiimote_cmd_wait(struct wiimote_data *wdata)
+{
+ int ret;
+
+ ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ);
+ if (ret < 0)
+ return -ERESTARTSYS;
+ else if (ret == 0)
+ return -EIO;
+ else
+ return 0;
+}
+
static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
size_t count)
{
@@ -172,6 +263,39 @@ static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer,
spin_unlock_irqrestore(&wdata->qlock, flags);
}
+/*
+ * This sets the rumble bit on the given output report if rumble is
+ * currently enabled.
+ * \cmd1 must point to the second byte in the output report => &cmd[1]
+ * This must be called on nearly every output report before passing it
+ * into the output queue!
+ */
+static inline void wiiproto_keep_rumble(struct wiimote_data *wdata, __u8 *cmd1)
+{
+ if (wdata->state.flags & WIIPROTO_FLAG_RUMBLE)
+ *cmd1 |= 0x01;
+}
+
+static void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble)
+{
+ __u8 cmd[2];
+
+ rumble = !!rumble;
+ if (rumble == !!(wdata->state.flags & WIIPROTO_FLAG_RUMBLE))
+ return;
+
+ if (rumble)
+ wdata->state.flags |= WIIPROTO_FLAG_RUMBLE;
+ else
+ wdata->state.flags &= ~WIIPROTO_FLAG_RUMBLE;
+
+ cmd[0] = WIIPROTO_REQ_RUMBLE;
+ cmd[1] = 0;
+
+ wiiproto_keep_rumble(wdata, &cmd[1]);
+ wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
{
__u8 cmd[2];
@@ -193,6 +317,7 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
if (leds & WIIPROTO_FLAG_LED4)
cmd[1] |= 0x80;
+ wiiproto_keep_rumble(wdata, &cmd[1]);
wiimote_queue(wdata, cmd, sizeof(cmd));
}
@@ -203,7 +328,23 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
*/
static __u8 select_drm(struct wiimote_data *wdata)
{
- return WIIPROTO_REQ_DRM_K;
+ __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR;
+
+ if (ir == WIIPROTO_FLAG_IR_BASIC) {
+ if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
+ return WIIPROTO_REQ_DRM_KAIE;
+ else
+ return WIIPROTO_REQ_DRM_KIE;
+ } else if (ir == WIIPROTO_FLAG_IR_EXT) {
+ return WIIPROTO_REQ_DRM_KAI;
+ } else if (ir == WIIPROTO_FLAG_IR_FULL) {
+ return WIIPROTO_REQ_DRM_SKAI1;
+ } else {
+ if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
+ return WIIPROTO_REQ_DRM_KA;
+ else
+ return WIIPROTO_REQ_DRM_K;
+ }
}
static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
@@ -217,9 +358,256 @@ static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
cmd[1] = 0;
cmd[2] = drm;
+ wiiproto_keep_rumble(wdata, &cmd[1]);
+ wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+static void wiiproto_req_status(struct wiimote_data *wdata)
+{
+ __u8 cmd[2];
+
+ cmd[0] = WIIPROTO_REQ_SREQ;
+ cmd[1] = 0;
+
+ wiiproto_keep_rumble(wdata, &cmd[1]);
+ wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel)
+{
+ accel = !!accel;
+ if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL))
+ return;
+
+ if (accel)
+ wdata->state.flags |= WIIPROTO_FLAG_ACCEL;
+ else
+ wdata->state.flags &= ~WIIPROTO_FLAG_ACCEL;
+
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+}
+
+static void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags)
+{
+ __u8 cmd[2];
+
+ cmd[0] = WIIPROTO_REQ_IR1;
+ cmd[1] = flags;
+
+ wiiproto_keep_rumble(wdata, &cmd[1]);
+ wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+static void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags)
+{
+ __u8 cmd[2];
+
+ cmd[0] = WIIPROTO_REQ_IR2;
+ cmd[1] = flags;
+
+ wiiproto_keep_rumble(wdata, &cmd[1]);
+ wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+#define wiiproto_req_wreg(wdata, os, buf, sz) \
+ wiiproto_req_wmem((wdata), false, (os), (buf), (sz))
+
+#define wiiproto_req_weeprom(wdata, os, buf, sz) \
+ wiiproto_req_wmem((wdata), true, (os), (buf), (sz))
+
+static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom,
+ __u32 offset, const __u8 *buf, __u8 size)
+{
+ __u8 cmd[22];
+
+ if (size > 16 || size == 0) {
+ hid_warn(wdata->hdev, "Invalid length %d wmem request\n", size);
+ return;
+ }
+
+ memset(cmd, 0, sizeof(cmd));
+ cmd[0] = WIIPROTO_REQ_WMEM;
+ cmd[2] = (offset >> 16) & 0xff;
+ cmd[3] = (offset >> 8) & 0xff;
+ cmd[4] = offset & 0xff;
+ cmd[5] = size;
+ memcpy(&cmd[6], buf, size);
+
+ if (!eeprom)
+ cmd[1] |= 0x04;
+
+ wiiproto_keep_rumble(wdata, &cmd[1]);
wiimote_queue(wdata, cmd, sizeof(cmd));
}
+/* requries the cmd-mutex to be held */
+static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
+ const __u8 *wmem, __u8 size)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wiimote_cmd_set(wdata, WIIPROTO_REQ_WMEM, 0);
+ wiiproto_req_wreg(wdata, offset, wmem, size);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ ret = wiimote_cmd_wait(wdata);
+ if (!ret && wdata->state.cmd_err)
+ ret = -EIO;
+
+ return ret;
+}
+
+static int wiimote_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct wiimote_data *wdata = container_of(psy,
+ struct wiimote_data, battery);
+ int ret = 0, state;
+ unsigned long flags;
+
+ ret = wiimote_cmd_acquire(wdata);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0);
+ wiiproto_req_status(wdata);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ ret = wiimote_cmd_wait(wdata);
+ state = wdata->state.cmd_battery;
+ wiimote_cmd_release(wdata);
+
+ if (ret)
+ return ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = state * 100 / 255;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode)
+{
+ int ret;
+ unsigned long flags;
+ __u8 format = 0;
+ static const __u8 data_enable[] = { 0x01 };
+ static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01,
+ 0x00, 0xaa, 0x00, 0x64 };
+ static const __u8 data_sens2[] = { 0x63, 0x03 };
+ static const __u8 data_fin[] = { 0x08 };
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+
+ if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) {
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+ return 0;
+ }
+
+ if (mode == 0) {
+ wdata->state.flags &= ~WIIPROTO_FLAGS_IR;
+ wiiproto_req_ir1(wdata, 0);
+ wiiproto_req_ir2(wdata, 0);
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+ return 0;
+ }
+
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ ret = wiimote_cmd_acquire(wdata);
+ if (ret)
+ return ret;
+
+ /* send PIXEL CLOCK ENABLE cmd first */
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0);
+ wiiproto_req_ir1(wdata, 0x06);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ ret = wiimote_cmd_wait(wdata);
+ if (ret)
+ goto unlock;
+ if (wdata->state.cmd_err) {
+ ret = -EIO;
+ goto unlock;
+ }
+
+ /* enable IR LOGIC */
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0);
+ wiiproto_req_ir2(wdata, 0x06);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ ret = wiimote_cmd_wait(wdata);
+ if (ret)
+ goto unlock;
+ if (wdata->state.cmd_err) {
+ ret = -EIO;
+ goto unlock;
+ }
+
+ /* enable IR cam but do not make it send data, yet */
+ ret = wiimote_cmd_write(wdata, 0xb00030, data_enable,
+ sizeof(data_enable));
+ if (ret)
+ goto unlock;
+
+ /* write first sensitivity block */
+ ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1,
+ sizeof(data_sens1));
+ if (ret)
+ goto unlock;
+
+ /* write second sensitivity block */
+ ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2,
+ sizeof(data_sens2));
+ if (ret)
+ goto unlock;
+
+ /* put IR cam into desired state */
+ switch (mode) {
+ case WIIPROTO_FLAG_IR_FULL:
+ format = 5;
+ break;
+ case WIIPROTO_FLAG_IR_EXT:
+ format = 3;
+ break;
+ case WIIPROTO_FLAG_IR_BASIC:
+ format = 1;
+ break;
+ }
+ ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format));
+ if (ret)
+ goto unlock;
+
+ /* make IR cam send data */
+ ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin));
+ if (ret)
+ goto unlock;
+
+ /* request new DRM mode compatible to IR mode */
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags &= ~WIIPROTO_FLAGS_IR;
+ wdata->state.flags |= mode & WIIPROTO_FLAGS_IR;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+unlock:
+ wiimote_cmd_release(wdata);
+ return ret;
+}
+
static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev)
{
struct wiimote_data *wdata;
@@ -268,9 +656,28 @@ static void wiimote_leds_set(struct led_classdev *led_dev,
}
}
-static int wiimote_input_event(struct input_dev *dev, unsigned int type,
- unsigned int code, int value)
+static int wiimote_ff_play(struct input_dev *dev, void *data,
+ struct ff_effect *eff)
{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ __u8 value;
+ unsigned long flags;
+
+ /*
+ * The wiimote supports only a single rumble motor so if any magnitude
+ * is set to non-zero then we start the rumble motor. If both are set to
+ * zero, we stop the rumble motor.
+ */
+
+ if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude)
+ value = 1;
+ else
+ value = 0;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wiiproto_req_rumble(wdata, value);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
return 0;
}
@@ -288,6 +695,61 @@ static void wiimote_input_close(struct input_dev *dev)
hid_hw_close(wdata->hdev);
}
+static int wiimote_accel_open(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ int ret;
+ unsigned long flags;
+
+ ret = hid_hw_open(wdata->hdev);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wiiproto_req_accel(wdata, true);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+static void wiimote_accel_close(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wiiproto_req_accel(wdata, false);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ hid_hw_close(wdata->hdev);
+}
+
+static int wiimote_ir_open(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ int ret;
+
+ ret = hid_hw_open(wdata->hdev);
+ if (ret)
+ return ret;
+
+ ret = wiimote_init_ir(wdata, WIIPROTO_FLAG_IR_BASIC);
+ if (ret) {
+ hid_hw_close(wdata->hdev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void wiimote_ir_close(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+
+ wiimote_init_ir(wdata, 0);
+ hid_hw_close(wdata->hdev);
+}
+
static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
{
input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT],
@@ -315,12 +777,100 @@ static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
input_sync(wdata->input);
}
+static void handler_accel(struct wiimote_data *wdata, const __u8 *payload)
+{
+ __u16 x, y, z;
+
+ if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL))
+ return;
+
+ /*
+ * payload is: BB BB XX YY ZZ
+ * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ
+ * contain the upper 8 bits of each value. The lower 2 bits are
+ * contained in the buttons data BB BB.
+ * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the
+ * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y
+ * accel value and bit 6 is the second bit of the Z value.
+ * The first bit of Y and Z values is not available and always set to 0.
+ * 0x200 is returned on no movement.
+ */
+
+ x = payload[2] << 2;
+ y = payload[3] << 2;
+ z = payload[4] << 2;
+
+ x |= (payload[0] >> 5) & 0x3;
+ y |= (payload[1] >> 4) & 0x2;
+ z |= (payload[1] >> 5) & 0x2;
+
+ input_report_abs(wdata->accel, ABS_RX, x - 0x200);
+ input_report_abs(wdata->accel, ABS_RY, y - 0x200);
+ input_report_abs(wdata->accel, ABS_RZ, z - 0x200);
+ input_sync(wdata->accel);
+}
+
+#define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+ ABS_HAT0X, ABS_HAT0Y)
+#define ir_to_input1(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+ ABS_HAT1X, ABS_HAT1Y)
+#define ir_to_input2(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+ ABS_HAT2X, ABS_HAT2Y)
+#define ir_to_input3(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+ ABS_HAT3X, ABS_HAT3Y)
+
+static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir,
+ bool packed, __u8 xid, __u8 yid)
+{
+ __u16 x, y;
+
+ if (!(wdata->state.flags & WIIPROTO_FLAGS_IR))
+ return;
+
+ /*
+ * Basic IR data is encoded into 3 bytes. The first two bytes are the
+ * upper 8 bit of the X/Y data, the 3rd byte contains the lower 2 bits
+ * of both.
+ * If data is packed, then the 3rd byte is put first and slightly
+ * reordered. This allows to interleave packed and non-packed data to
+ * have two IR sets in 5 bytes instead of 6.
+ * The resulting 10bit X/Y values are passed to the ABS_HATXY input dev.
+ */
+
+ if (packed) {
+ x = ir[1] << 2;
+ y = ir[2] << 2;
+
+ x |= ir[0] & 0x3;
+ y |= (ir[0] >> 2) & 0x3;
+ } else {
+ x = ir[0] << 2;
+ y = ir[1] << 2;
+
+ x |= (ir[2] >> 4) & 0x3;
+ y |= (ir[2] >> 6) & 0x3;
+ }
+
+ input_report_abs(wdata->ir, xid, x);
+ input_report_abs(wdata->ir, yid, y);
+}
+
static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
{
handler_keys(wdata, payload);
/* on status reports the drm is reset so we need to resend the drm */
wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+
+ if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) {
+ wdata->state.cmd_battery = payload[5];
+ wiimote_cmd_complete(wdata);
+ }
+}
+
+static void handler_data(struct wiimote_data *wdata, const __u8 *payload)
+{
+ handler_keys(wdata, payload);
}
static void handler_return(struct wiimote_data *wdata, const __u8 *payload)
@@ -330,9 +880,105 @@ static void handler_return(struct wiimote_data *wdata, const __u8 *payload)
handler_keys(wdata, payload);
- if (err)
+ if (wiimote_cmd_pending(wdata, cmd, 0)) {
+ wdata->state.cmd_err = err;
+ wiimote_cmd_complete(wdata);
+ } else if (err) {
hid_warn(wdata->hdev, "Remote error %hhu on req %hhu\n", err,
cmd);
+ }
+}
+
+static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload)
+{
+ handler_keys(wdata, payload);
+ handler_accel(wdata, payload);
+}
+
+static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload)
+{
+ handler_keys(wdata, payload);
+}
+
+static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload)
+{
+ handler_keys(wdata, payload);
+ handler_accel(wdata, payload);
+ ir_to_input0(wdata, &payload[5], false);
+ ir_to_input1(wdata, &payload[8], false);
+ ir_to_input2(wdata, &payload[11], false);
+ ir_to_input3(wdata, &payload[14], false);
+ input_sync(wdata->ir);
+}
+
+static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload)
+{
+ handler_keys(wdata, payload);
+}
+
+static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload)
+{
+ handler_keys(wdata, payload);
+ ir_to_input0(wdata, &payload[2], false);
+ ir_to_input1(wdata, &payload[4], true);
+ ir_to_input2(wdata, &payload[7], false);
+ ir_to_input3(wdata, &payload[9], true);
+ input_sync(wdata->ir);
+}
+
+static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload)
+{
+ handler_keys(wdata, payload);
+ handler_accel(wdata, payload);
+}
+
+static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload)
+{
+ handler_keys(wdata, payload);
+ handler_accel(wdata, payload);
+ ir_to_input0(wdata, &payload[5], false);
+ ir_to_input1(wdata, &payload[7], true);
+ ir_to_input2(wdata, &payload[10], false);
+ ir_to_input3(wdata, &payload[12], true);
+ input_sync(wdata->ir);
+}
+
+static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload)
+{
+}
+
+static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload)
+{
+ handler_keys(wdata, payload);
+
+ wdata->state.accel_split[0] = payload[2];
+ wdata->state.accel_split[1] = (payload[0] >> 1) & (0x10 | 0x20);
+ wdata->state.accel_split[1] |= (payload[1] << 1) & (0x40 | 0x80);
+
+ ir_to_input0(wdata, &payload[3], false);
+ ir_to_input1(wdata, &payload[12], false);
+ input_sync(wdata->ir);
+}
+
+static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload)
+{
+ __u8 buf[5];
+
+ handler_keys(wdata, payload);
+
+ wdata->state.accel_split[1] |= (payload[0] >> 5) & (0x01 | 0x02);
+ wdata->state.accel_split[1] |= (payload[1] >> 3) & (0x04 | 0x08);
+
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = wdata->state.accel_split[0];
+ buf[3] = payload[2];
+ buf[4] = wdata->state.accel_split[1];
+ handler_accel(wdata, buf);
+
+ ir_to_input2(wdata, &payload[3], false);
+ ir_to_input3(wdata, &payload[12], false);
+ input_sync(wdata->ir);
}
struct wiiproto_handler {
@@ -343,8 +989,19 @@ struct wiiproto_handler {
static struct wiiproto_handler handlers[] = {
{ .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status },
+ { .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data },
{ .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return },
{ .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys },
+ { .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA },
+ { .id = WIIPROTO_REQ_DRM_KE, .size = 10, .func = handler_drm_KE },
+ { .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI },
+ { .id = WIIPROTO_REQ_DRM_KEE, .size = 21, .func = handler_drm_KEE },
+ { .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE },
+ { .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE },
+ { .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE },
+ { .id = WIIPROTO_REQ_DRM_E, .size = 21, .func = handler_drm_E },
+ { .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 },
+ { .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 },
{ .id = 0 }
};
@@ -355,6 +1012,7 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
struct wiiproto_handler *h;
int i;
unsigned long flags;
+ bool handled = false;
if (size < 1)
return -EINVAL;
@@ -363,10 +1021,16 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
for (i = 0; handlers[i].id; ++i) {
h = &handlers[i];
- if (h->id == raw_data[0] && h->size < size)
+ if (h->id == raw_data[0] && h->size < size) {
h->func(wdata, &raw_data[1]);
+ handled = true;
+ }
}
+ if (!handled)
+ hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0],
+ size);
+
spin_unlock_irqrestore(&wdata->state.lock, flags);
return 0;
@@ -434,16 +1098,13 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
return NULL;
wdata->input = input_allocate_device();
- if (!wdata->input) {
- kfree(wdata);
- return NULL;
- }
+ if (!wdata->input)
+ goto err;
wdata->hdev = hdev;
hid_set_drvdata(hdev, wdata);
input_set_drvdata(wdata->input, wdata);
- wdata->input->event = wiimote_input_event;
wdata->input->open = wiimote_input_open;
wdata->input->close = wiimote_input_close;
wdata->input->dev.parent = &wdata->hdev->dev;
@@ -457,18 +1118,89 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
for (i = 0; i < WIIPROTO_KEY_COUNT; ++i)
set_bit(wiiproto_keymap[i], wdata->input->keybit);
+ set_bit(FF_RUMBLE, wdata->input->ffbit);
+ if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play))
+ goto err_input;
+
+ wdata->accel = input_allocate_device();
+ if (!wdata->accel)
+ goto err_input;
+
+ input_set_drvdata(wdata->accel, wdata);
+ wdata->accel->open = wiimote_accel_open;
+ wdata->accel->close = wiimote_accel_close;
+ wdata->accel->dev.parent = &wdata->hdev->dev;
+ wdata->accel->id.bustype = wdata->hdev->bus;
+ wdata->accel->id.vendor = wdata->hdev->vendor;
+ wdata->accel->id.product = wdata->hdev->product;
+ wdata->accel->id.version = wdata->hdev->version;
+ wdata->accel->name = WIIMOTE_NAME " Accelerometer";
+
+ set_bit(EV_ABS, wdata->accel->evbit);
+ set_bit(ABS_RX, wdata->accel->absbit);
+ set_bit(ABS_RY, wdata->accel->absbit);
+ set_bit(ABS_RZ, wdata->accel->absbit);
+ input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4);
+ input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4);
+ input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4);
+
+ wdata->ir = input_allocate_device();
+ if (!wdata->ir)
+ goto err_ir;
+
+ input_set_drvdata(wdata->ir, wdata);
+ wdata->ir->open = wiimote_ir_open;
+ wdata->ir->close = wiimote_ir_close;
+ wdata->ir->dev.parent = &wdata->hdev->dev;
+ wdata->ir->id.bustype = wdata->hdev->bus;
+ wdata->ir->id.vendor = wdata->hdev->vendor;
+ wdata->ir->id.product = wdata->hdev->product;
+ wdata->ir->id.version = wdata->hdev->version;
+ wdata->ir->name = WIIMOTE_NAME " IR";
+
+ set_bit(EV_ABS, wdata->ir->evbit);
+ set_bit(ABS_HAT0X, wdata->ir->absbit);
+ set_bit(ABS_HAT0Y, wdata->ir->absbit);
+ set_bit(ABS_HAT1X, wdata->ir->absbit);
+ set_bit(ABS_HAT1Y, wdata->ir->absbit);
+ set_bit(ABS_HAT2X, wdata->ir->absbit);
+ set_bit(ABS_HAT2Y, wdata->ir->absbit);
+ set_bit(ABS_HAT3X, wdata->ir->absbit);
+ set_bit(ABS_HAT3Y, wdata->ir->absbit);
+ input_set_abs_params(wdata->ir, ABS_HAT0X, 0, 1023, 2, 4);
+ input_set_abs_params(wdata->ir, ABS_HAT0Y, 0, 767, 2, 4);
+ input_set_abs_params(wdata->ir, ABS_HAT1X, 0, 1023, 2, 4);
+ input_set_abs_params(wdata->ir, ABS_HAT1Y, 0, 767, 2, 4);
+ input_set_abs_params(wdata->ir, ABS_HAT2X, 0, 1023, 2, 4);
+ input_set_abs_params(wdata->ir, ABS_HAT2Y, 0, 767, 2, 4);
+ input_set_abs_params(wdata->ir, ABS_HAT3X, 0, 1023, 2, 4);
+ input_set_abs_params(wdata->ir, ABS_HAT3Y, 0, 767, 2, 4);
+
spin_lock_init(&wdata->qlock);
INIT_WORK(&wdata->worker, wiimote_worker);
spin_lock_init(&wdata->state.lock);
+ init_completion(&wdata->state.ready);
+ mutex_init(&wdata->state.sync);
return wdata;
+
+err_ir:
+ input_free_device(wdata->accel);
+err_input:
+ input_free_device(wdata->input);
+err:
+ kfree(wdata);
+ return NULL;
}
static void wiimote_destroy(struct wiimote_data *wdata)
{
wiimote_leds_destroy(wdata);
+ power_supply_unregister(&wdata->battery);
+ input_unregister_device(wdata->accel);
+ input_unregister_device(wdata->ir);
input_unregister_device(wdata->input);
cancel_work_sync(&wdata->worker);
hid_hw_stop(wdata->hdev);
@@ -500,12 +1232,37 @@ static int wiimote_hid_probe(struct hid_device *hdev,
goto err;
}
- ret = input_register_device(wdata->input);
+ ret = input_register_device(wdata->accel);
if (ret) {
hid_err(hdev, "Cannot register input device\n");
goto err_stop;
}
+ ret = input_register_device(wdata->ir);
+ if (ret) {
+ hid_err(hdev, "Cannot register input device\n");
+ goto err_ir;
+ }
+
+ ret = input_register_device(wdata->input);
+ if (ret) {
+ hid_err(hdev, "Cannot register input device\n");
+ goto err_input;
+ }
+
+ wdata->battery.properties = wiimote_battery_props;
+ wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props);
+ wdata->battery.get_property = wiimote_battery_get_property;
+ wdata->battery.name = "wiimote_battery";
+ wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+ wdata->battery.use_for_apm = 0;
+
+ ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
+ if (ret) {
+ hid_err(hdev, "Cannot register battery device\n");
+ goto err_battery;
+ }
+
ret = wiimote_leds_create(wdata);
if (ret)
goto err_free;
@@ -523,9 +1280,20 @@ err_free:
wiimote_destroy(wdata);
return ret;
+err_battery:
+ input_unregister_device(wdata->input);
+ wdata->input = NULL;
+err_input:
+ input_unregister_device(wdata->ir);
+ wdata->ir = NULL;
+err_ir:
+ input_unregister_device(wdata->accel);
+ wdata->accel = NULL;
err_stop:
hid_hw_stop(hdev);
err:
+ input_free_device(wdata->ir);
+ input_free_device(wdata->accel);
input_free_device(wdata->input);
kfree(wdata);
return ret;
diff --git a/drivers/hid/hid-zydacron.c b/drivers/hid/hid-zydacron.c
index e90371508fd2..1ad85f2257b4 100644
--- a/drivers/hid/hid-zydacron.c
+++ b/drivers/hid/hid-zydacron.c
@@ -201,9 +201,7 @@ static void zc_remove(struct hid_device *hdev)
struct zc_device *zc = hid_get_drvdata(hdev);
hid_hw_stop(hdev);
-
- if (NULL != zc)
- kfree(zc);
+ kfree(zc);
}
static const struct hid_device_id zc_devices[] = {
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index c79578b5a788..cf7d6d58e79f 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -259,7 +259,6 @@ static int hidraw_open(struct inode *inode, struct file *file)
mutex_lock(&minors_lock);
if (!hidraw_table[minor]) {
- kfree(list);
err = -ENODEV;
goto out_unlock;
}
@@ -272,8 +271,10 @@ static int hidraw_open(struct inode *inode, struct file *file)
dev = hidraw_table[minor];
if (!dev->open++) {
err = hid_hw_power(dev->hid, PM_HINT_FULLON);
- if (err < 0)
+ if (err < 0) {
+ dev->open--;
goto out_unlock;
+ }
err = hid_hw_open(dev->hid);
if (err < 0) {
@@ -285,6 +286,8 @@ static int hidraw_open(struct inode *inode, struct file *file)
out_unlock:
mutex_unlock(&minors_lock);
out:
+ if (err < 0)
+ kfree(list);
return err;
}
@@ -510,13 +513,12 @@ void hidraw_disconnect(struct hid_device *hid)
{
struct hidraw *hidraw = hid->hidraw;
+ mutex_lock(&minors_lock);
hidraw->exist = 0;
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
- mutex_lock(&minors_lock);
hidraw_table[hidraw->minor] = NULL;
- mutex_unlock(&minors_lock);
if (hidraw->open) {
hid_hw_close(hid);
@@ -524,6 +526,7 @@ void hidraw_disconnect(struct hid_device *hid)
} else {
kfree(hidraw);
}
+ mutex_unlock(&minors_lock);
}
EXPORT_SYMBOL_GPL(hidraw_disconnect);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index ad978f5748d3..b403fcef0b86 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1270,7 +1270,7 @@ static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid)
static void hid_cease_io(struct usbhid_device *usbhid)
{
- del_timer(&usbhid->io_retry);
+ del_timer_sync(&usbhid->io_retry);
usb_kill_urb(usbhid->urbin);
usb_kill_urb(usbhid->urbctrl);
usb_kill_urb(usbhid->urbout);
@@ -1332,7 +1332,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
struct usbhid_device *usbhid = hid->driver_data;
int status;
- if (message.event & PM_EVENT_AUTO) {
+ if (PMSG_IS_AUTO(message)) {
spin_lock_irq(&usbhid->lock); /* Sync with error handler */
if (!test_bit(HID_RESET_PENDING, &usbhid->iofl)
&& !test_bit(HID_CLEAR_HALT, &usbhid->iofl)
@@ -1367,7 +1367,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
return -EIO;
}
- if (!ignoreled && (message.event & PM_EVENT_AUTO)) {
+ if (!ignoreled && PMSG_IS_AUTO(message)) {
spin_lock_irq(&usbhid->lock);
if (test_bit(HID_LED_ON, &usbhid->iofl)) {
spin_unlock_irq(&usbhid->lock);
@@ -1380,8 +1380,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
hid_cancel_delayed_stuff(usbhid);
hid_cease_io(usbhid);
- if ((message.event & PM_EVENT_AUTO) &&
- test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
+ if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
/* lost race against keypresses */
status = hid_start_in(hid);
if (status < 0)
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 3146fdcda272..4ea464151c3b 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -80,10 +80,8 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT },
- { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
- { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE },
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 7c1188b53c3e..4ef02b269a71 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -641,6 +641,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct usb_device *dev = hid_to_usb_dev(hid);
struct usbhid_device *usbhid = hid->driver_data;
+ memset(&dinfo, 0, sizeof(dinfo));
+
dinfo.bustype = BUS_USB;
dinfo.busnum = dev->bus->busnum;
dinfo.devnum = dev->devnum;
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
new file mode 100644
index 000000000000..9fa09ac000ad
--- /dev/null
+++ b/drivers/hv/Kconfig
@@ -0,0 +1,14 @@
+config HYPERV
+ tristate "Microsoft Hyper-V client drivers"
+ depends on X86 && ACPI && PCI
+ help
+ Select this option to run Linux as a Hyper-V client operating
+ system.
+
+config HYPERV_UTILS
+ tristate "Microsoft Hyper-V Utilities driver"
+ depends on HYPERV && CONNECTOR && NLS
+ help
+ Select this option to enable the Hyper-V Utilities.
+
+
diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile
new file mode 100644
index 000000000000..a23938b991c9
--- /dev/null
+++ b/drivers/hv/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_HYPERV) += hv_vmbus.o
+obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o
+
+hv_vmbus-y := vmbus_drv.o \
+ hv.o connection.o channel.o \
+ channel_mgmt.o ring_buffer.o
+hv_utils-y := hv_util.o hv_kvp.o
diff --git a/drivers/staging/hv/channel.c b/drivers/hv/channel.c
index 455f47a891f1..406537420fff 100644
--- a/drivers/staging/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -26,8 +26,8 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/hyperv.h>
-#include "hyperv.h"
#include "hyperv_vmbus.h"
#define NUM_PAGES_SPANNED(addr, len) \
@@ -76,15 +76,14 @@ void vmbus_get_debug_info(struct vmbus_channel *channel,
struct hv_monitor_page *monitorpage;
u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
- /* u32 monitorBit = 1 << monitorOffset; */
debuginfo->relid = channel->offermsg.child_relid;
debuginfo->state = channel->state;
memcpy(&debuginfo->interfacetype,
- &channel->offermsg.offer.if_type, sizeof(struct hv_guid));
+ &channel->offermsg.offer.if_type, sizeof(uuid_le));
memcpy(&debuginfo->interface_instance,
&channel->offermsg.offer.if_instance,
- sizeof(struct hv_guid));
+ sizeof(uuid_le));
monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
@@ -119,8 +118,8 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
void (*onchannelcallback)(void *context), void *context)
{
- struct vmbus_channel_open_channel *openMsg;
- struct vmbus_channel_msginfo *openInfo = NULL;
+ struct vmbus_channel_open_channel *open_msg;
+ struct vmbus_channel_msginfo *open_info = NULL;
void *in, *out;
unsigned long flags;
int ret, t, err = 0;
@@ -173,24 +172,24 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
}
/* Create and init the channel open message */
- openInfo = kmalloc(sizeof(*openInfo) +
+ open_info = kmalloc(sizeof(*open_info) +
sizeof(struct vmbus_channel_open_channel),
GFP_KERNEL);
- if (!openInfo) {
+ if (!open_info) {
err = -ENOMEM;
goto errorout;
}
- init_completion(&openInfo->waitevent);
+ init_completion(&open_info->waitevent);
- openMsg = (struct vmbus_channel_open_channel *)openInfo->msg;
- openMsg->header.msgtype = CHANNELMSG_OPENCHANNEL;
- openMsg->openid = newchannel->offermsg.child_relid;
- openMsg->child_relid = newchannel->offermsg.child_relid;
- openMsg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
- openMsg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
+ open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
+ open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
+ open_msg->openid = newchannel->offermsg.child_relid;
+ open_msg->child_relid = newchannel->offermsg.child_relid;
+ open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
+ open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
PAGE_SHIFT;
- openMsg->server_contextarea_gpadlhandle = 0;
+ open_msg->server_contextarea_gpadlhandle = 0;
if (userdatalen > MAX_USER_DEFINED_BYTES) {
err = -EINVAL;
@@ -198,35 +197,35 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
}
if (userdatalen)
- memcpy(openMsg->userdata, userdata, userdatalen);
+ memcpy(open_msg->userdata, userdata, userdatalen);
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
- list_add_tail(&openInfo->msglistentry,
+ list_add_tail(&open_info->msglistentry,
&vmbus_connection.chn_msg_list);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
- ret = vmbus_post_msg(openMsg,
+ ret = vmbus_post_msg(open_msg,
sizeof(struct vmbus_channel_open_channel));
if (ret != 0)
goto cleanup;
- t = wait_for_completion_timeout(&openInfo->waitevent, 5*HZ);
+ t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
if (t == 0) {
err = -ETIMEDOUT;
goto errorout;
}
- if (openInfo->response.open_result.status)
- err = openInfo->response.open_result.status;
+ if (open_info->response.open_result.status)
+ err = open_info->response.open_result.status;
cleanup:
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
- list_del(&openInfo->msglistentry);
+ list_del(&open_info->msglistentry);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
- kfree(openInfo);
+ kfree(open_info);
return err;
errorout:
@@ -234,57 +233,12 @@ errorout:
hv_ringbuffer_cleanup(&newchannel->inbound);
free_pages((unsigned long)out,
get_order(send_ringbuffer_size + recv_ringbuffer_size));
- kfree(openInfo);
+ kfree(open_info);
return err;
}
EXPORT_SYMBOL_GPL(vmbus_open);
/*
- * dump_gpadl_body - Dump the gpadl body message to the console for
- * debugging purposes.
- */
-static void dump_gpadl_body(struct vmbus_channel_gpadl_body *gpadl, u32 len)
-{
- int i;
- int pfncount;
-
- pfncount = (len - sizeof(struct vmbus_channel_gpadl_body)) /
- sizeof(u64);
-
- DPRINT_DBG(VMBUS, "gpadl body - len %d pfn count %d", len, pfncount);
-
- for (i = 0; i < pfncount; i++)
- DPRINT_DBG(VMBUS, "gpadl body - %d) pfn %llu",
- i, gpadl->pfn[i]);
-}
-
-/*
- * dump_gpadl_header - Dump the gpadl header message to the console for
- * debugging purposes.
- */
-static void dump_gpadl_header(struct vmbus_channel_gpadl_header *gpadl)
-{
- int i, j;
- int pagecount;
-
- DPRINT_DBG(VMBUS,
- "gpadl header - relid %d, range count %d, range buflen %d",
- gpadl->child_relid, gpadl->rangecount, gpadl->range_buflen);
- for (i = 0; i < gpadl->rangecount; i++) {
- pagecount = gpadl->range[i].byte_count >> PAGE_SHIFT;
- pagecount = (pagecount > 26) ? 26 : pagecount;
-
- DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d "
- "page count %d", i, gpadl->range[i].byte_count,
- gpadl->range[i].byte_offset, pagecount);
-
- for (j = 0; j < pagecount; j++)
- DPRINT_DBG(VMBUS, "%d) pfn %llu", j,
- gpadl->range[i].pfn_array[j]);
- }
-}
-
-/*
* create_gpadl_header - Creates a gpadl for the specified buffer
*/
static int create_gpadl_header(void *kbuffer, u32 size,
@@ -437,7 +391,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
{
struct vmbus_channel_gpadl_header *gpadlmsg;
struct vmbus_channel_gpadl_body *gpadl_body;
- /* struct vmbus_channel_gpadl_created *gpadlCreated; */
struct vmbus_channel_msginfo *msginfo = NULL;
struct vmbus_channel_msginfo *submsginfo;
u32 msgcount;
@@ -461,7 +414,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
gpadlmsg->child_relid = channel->offermsg.child_relid;
gpadlmsg->gpadl = next_gpadl_handle;
- dump_gpadl_header(gpadlmsg);
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
list_add_tail(&msginfo->msglistentry,
@@ -485,8 +437,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
CHANNELMSG_GPADL_BODY;
gpadl_body->gpadl = next_gpadl_handle;
- dump_gpadl_body(gpadl_body, submsginfo->msgsize -
- sizeof(*submsginfo));
ret = vmbus_post_msg(gpadl_body,
submsginfo->msgsize -
sizeof(*submsginfo));
@@ -522,8 +472,6 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
unsigned long flags;
int ret, t;
- /* ASSERT(gpadl_handle != 0); */
-
info = kmalloc(sizeof(*info) +
sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
if (!info)
@@ -565,9 +513,12 @@ void vmbus_close(struct vmbus_channel *channel)
{
struct vmbus_channel_close_channel *msg;
int ret;
+ unsigned long flags;
/* Stop callback and cancel the timer asap */
+ spin_lock_irqsave(&channel->inbound_lock, flags);
channel->onchannel_callback = NULL;
+ spin_unlock_irqrestore(&channel->inbound_lock, flags);
/* Send a closing message */
@@ -787,19 +738,15 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
u32 packetlen;
u32 userlen;
int ret;
- unsigned long flags;
*buffer_actual_len = 0;
*requestid = 0;
- spin_lock_irqsave(&channel->inbound_lock, flags);
ret = hv_ringbuffer_peek(&channel->inbound, &desc,
sizeof(struct vmpacket_descriptor));
- if (ret != 0) {
- spin_unlock_irqrestore(&channel->inbound_lock, flags);
+ if (ret != 0)
return 0;
- }
packetlen = desc.len8 << 3;
userlen = packetlen - (desc.offset8 << 3);
@@ -807,7 +754,6 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
*buffer_actual_len = userlen;
if (userlen > bufferlen) {
- spin_unlock_irqrestore(&channel->inbound_lock, flags);
pr_err("Buffer too small - got %d needs %d\n",
bufferlen, userlen);
@@ -820,7 +766,6 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
(desc.offset8 << 3));
- spin_unlock_irqrestore(&channel->inbound_lock, flags);
return 0;
}
@@ -837,19 +782,15 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
u32 packetlen;
u32 userlen;
int ret;
- unsigned long flags;
*buffer_actual_len = 0;
*requestid = 0;
- spin_lock_irqsave(&channel->inbound_lock, flags);
ret = hv_ringbuffer_peek(&channel->inbound, &desc,
sizeof(struct vmpacket_descriptor));
- if (ret != 0) {
- spin_unlock_irqrestore(&channel->inbound_lock, flags);
+ if (ret != 0)
return 0;
- }
packetlen = desc.len8 << 3;
@@ -858,12 +799,10 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
*buffer_actual_len = packetlen;
if (packetlen > bufferlen) {
- spin_unlock_irqrestore(&channel->inbound_lock, flags);
-
pr_err("Buffer too small - needed %d bytes but "
"got space for only %d bytes\n",
packetlen, bufferlen);
- return -2;
+ return -ENOBUFS;
}
*requestid = desc.trans_id;
@@ -871,7 +810,6 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
/* Copy over the entire packet to the user buffer */
ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0);
- spin_unlock_irqrestore(&channel->inbound_lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index bf011f3fb851..12b85ff957fd 100644
--- a/drivers/staging/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -28,8 +28,8 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/completion.h>
+#include <linux/hyperv.h>
-#include "hyperv.h"
#include "hyperv_vmbus.h"
struct vmbus_channel_message_table_entry {
@@ -40,12 +40,12 @@ struct vmbus_channel_message_table_entry {
#define MAX_MSG_TYPES 4
#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8
-static const struct hv_guid
+static const uuid_le
supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
/* Storage - SCSI */
{
- .data = {
+ .b = {
0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
}
@@ -54,7 +54,7 @@ static const struct hv_guid
/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
/* Network */
{
- .data = {
+ .b = {
0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
}
@@ -63,7 +63,7 @@ static const struct hv_guid
/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
/* Input */
{
- .data = {
+ .b = {
0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A
}
@@ -72,7 +72,7 @@ static const struct hv_guid
/* {32412632-86cb-44a2-9b5c-50d1417354f5} */
/* IDE */
{
- .data = {
+ .b = {
0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
}
@@ -80,7 +80,7 @@ static const struct hv_guid
/* 0E0B6031-5213-4934-818B-38D90CED39DB */
/* Shutdown */
{
- .data = {
+ .b = {
0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
}
@@ -88,7 +88,7 @@ static const struct hv_guid
/* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
/* TimeSync */
{
- .data = {
+ .b = {
0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
}
@@ -96,7 +96,7 @@ static const struct hv_guid
/* {57164f39-9115-4e78-ab55-382f3bd5422d} */
/* Heartbeat */
{
- .data = {
+ .b = {
0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
}
@@ -104,7 +104,7 @@ static const struct hv_guid
/* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
/* KVP */
{
- .data = {
+ .b = {
0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6
}
@@ -114,7 +114,7 @@ static const struct hv_guid
/**
- * prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
+ * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
* @icmsghdrp: Pointer to msg header structure
* @icmsg_negotiate: Pointer to negotiate message structure
* @buf: Raw buffer channel data
@@ -128,9 +128,8 @@ static const struct hv_guid
*
* Mainly used by Hyper-V drivers.
*/
-void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
- struct icmsg_negotiate *negop,
- u8 *buf)
+void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
+ struct icmsg_negotiate *negop, u8 *buf)
{
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
icmsghdrp->icmsgsize = 0x10;
@@ -156,119 +155,7 @@ void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
negop->icmsg_vercnt = 1;
}
}
-EXPORT_SYMBOL(prep_negotiate_resp);
-
-/**
- * chn_cb_negotiate() - Default handler for non IDE/SCSI/NETWORK
- * Hyper-V requests
- * @context: Pointer to argument structure.
- *
- * Set up the default handler for non device driver specific requests
- * from Hyper-V. This stub responds to the default negotiate messages
- * that come in for every non IDE/SCSI/Network request.
- * This behavior is normally overwritten in the hv_utils driver. That
- * driver handles requests like graceful shutdown, heartbeats etc.
- *
- * Mainly used by Hyper-V drivers.
- */
-void chn_cb_negotiate(void *context)
-{
- struct vmbus_channel *channel = context;
- u8 *buf;
- u32 buflen, recvlen;
- u64 requestid;
-
- struct icmsg_hdr *icmsghdrp;
- struct icmsg_negotiate *negop = NULL;
-
- if (channel->util_index >= 0) {
- /*
- * This is a properly initialized util channel.
- * Route this callback appropriately and setup state
- * so that we don't need to reroute again.
- */
- if (hv_cb_utils[channel->util_index].callback != NULL) {
- /*
- * The util driver has established a handler for
- * this service; do the magic.
- */
- channel->onchannel_callback =
- hv_cb_utils[channel->util_index].callback;
- (hv_cb_utils[channel->util_index].callback)(channel);
- return;
- }
- }
-
- buflen = PAGE_SIZE;
- buf = kmalloc(buflen, GFP_ATOMIC);
-
- vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
-
- if (recvlen > 0) {
- icmsghdrp = (struct icmsg_hdr *)&buf[
- sizeof(struct vmbuspipe_hdr)];
-
- prep_negotiate_resp(icmsghdrp, negop, buf);
-
- icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
- | ICMSGHDRFLAG_RESPONSE;
-
- vmbus_sendpacket(channel, buf,
- recvlen, requestid,
- VM_PKT_DATA_INBAND, 0);
- }
-
- kfree(buf);
-}
-EXPORT_SYMBOL(chn_cb_negotiate);
-
-/*
- * Function table used for message responses for non IDE/SCSI/Network type
- * messages. (Such as KVP/Shutdown etc)
- */
-struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = {
- /* 0E0B6031-5213-4934-818B-38D90CED39DB */
- /* Shutdown */
- {
- .msg_type = HV_SHUTDOWN_MSG,
- .data = {
- 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
- 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
- },
- .log_msg = "Shutdown channel functionality initialized"
- },
-
- /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
- /* TimeSync */
- {
- .msg_type = HV_TIMESYNC_MSG,
- .data = {
- 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
- 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
- },
- .log_msg = "Timesync channel functionality initialized"
- },
- /* {57164f39-9115-4e78-ab55-382f3bd5422d} */
- /* Heartbeat */
- {
- .msg_type = HV_HEARTBEAT_MSG,
- .data = {
- 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
- 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
- },
- .log_msg = "Heartbeat channel functionality initialized"
- },
- /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
- /* KVP */
- {
- .data = {
- 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
- 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6
- },
- .log_msg = "KVP channel functionality initialized"
- },
-};
-EXPORT_SYMBOL(hv_cb_utils);
+EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
/*
* alloc_channel - Allocate and initialize a vmbus channel object
@@ -309,7 +196,7 @@ static void release_channel(struct work_struct *work)
/*
* free_channel - Release the resources used by the vmbus channel object
*/
-void free_channel(struct vmbus_channel *channel)
+static void free_channel(struct vmbus_channel *channel)
{
/*
@@ -333,7 +220,7 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
struct vmbus_channel,
work);
- vmbus_child_device_unregister(channel->device_obj);
+ vmbus_device_unregister(channel->device_obj);
}
/*
@@ -348,7 +235,6 @@ static void vmbus_process_offer(struct work_struct *work)
struct vmbus_channel *channel;
bool fnew = true;
int ret;
- int cnt;
unsigned long flags;
/* The next possible work is rescind handling */
@@ -358,12 +244,10 @@ static void vmbus_process_offer(struct work_struct *work)
spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
- if (!memcmp(&channel->offermsg.offer.if_type,
- &newchannel->offermsg.offer.if_type,
- sizeof(struct hv_guid)) &&
- !memcmp(&channel->offermsg.offer.if_instance,
- &newchannel->offermsg.offer.if_instance,
- sizeof(struct hv_guid))) {
+ if (!uuid_le_cmp(channel->offermsg.offer.if_type,
+ newchannel->offermsg.offer.if_type) &&
+ !uuid_le_cmp(channel->offermsg.offer.if_instance,
+ newchannel->offermsg.offer.if_instance)) {
fnew = false;
break;
}
@@ -385,7 +269,7 @@ static void vmbus_process_offer(struct work_struct *work)
* We need to set the DeviceObject field before calling
* vmbus_child_dev_add()
*/
- newchannel->device_obj = vmbus_child_device_create(
+ newchannel->device_obj = vmbus_device_create(
&newchannel->offermsg.offer.if_type,
&newchannel->offermsg.offer.if_instance,
newchannel);
@@ -395,7 +279,7 @@ static void vmbus_process_offer(struct work_struct *work)
* binding which eventually invokes the device driver's AddDevice()
* method.
*/
- ret = vmbus_child_device_register(newchannel->device_obj);
+ ret = vmbus_device_register(newchannel->device_obj);
if (ret != 0) {
pr_err("unable to add child device object (relid %d)\n",
newchannel->offermsg.child_relid);
@@ -412,48 +296,26 @@ static void vmbus_process_offer(struct work_struct *work)
* can cleanup properly
*/
newchannel->state = CHANNEL_OPEN_STATE;
- newchannel->util_index = -1; /* Invalid index */
-
- /* Open IC channels */
- for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
- if (memcmp(&newchannel->offermsg.offer.if_type,
- &hv_cb_utils[cnt].data,
- sizeof(struct hv_guid)) == 0 &&
- vmbus_open(newchannel, 2 * PAGE_SIZE,
- 2 * PAGE_SIZE, NULL, 0,
- chn_cb_negotiate,
- newchannel) == 0) {
- hv_cb_utils[cnt].channel = newchannel;
- newchannel->util_index = cnt;
-
- pr_info("%s\n", hv_cb_utils[cnt].log_msg);
-
- }
- }
}
}
/*
* vmbus_onoffer - Handler for channel offers from vmbus in parent partition.
*
- * We ignore all offers except network and storage offers. For each network and
- * storage offers, we create a channel object and queue a work item to the
- * channel object to process the offer synchronously
*/
static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
{
struct vmbus_channel_offer_channel *offer;
struct vmbus_channel *newchannel;
- struct hv_guid *guidtype;
- struct hv_guid *guidinstance;
+ uuid_le *guidtype;
+ uuid_le *guidinstance;
int i;
int fsupported = 0;
offer = (struct vmbus_channel_offer_channel *)hdr;
for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) {
- if (memcmp(&offer->offer.if_type,
- &supported_device_classes[i],
- sizeof(struct hv_guid)) == 0) {
+ if (!uuid_le_cmp(offer->offer.if_type,
+ supported_device_classes[i])) {
fsupported = 1;
break;
}
diff --git a/drivers/staging/hv/connection.c b/drivers/hv/connection.c
index e6b40392e08d..650c9f0b6642 100644
--- a/drivers/staging/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -25,11 +25,12 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/wait.h>
+#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-
-#include "hyperv.h"
+#include <linux/hyperv.h>
+#include <asm/hyperv.h>
#include "hyperv_vmbus.h"
@@ -49,10 +50,6 @@ int vmbus_connect(void)
struct vmbus_channel_initiate_contact *msg;
unsigned long flags;
- /* Make sure we are not connecting or connected */
- if (vmbus_connection.conn_state != DISCONNECTED)
- return -EISCONN;
-
/* Initialize the vmbus connection */
vmbus_connection.conn_state = CONNECTING;
vmbus_connection.work_queue = create_workqueue("hv_vmbus_con");
@@ -214,8 +211,7 @@ struct vmbus_channel *relid2channel(u32 relid)
static void process_chn_event(u32 relid)
{
struct vmbus_channel *channel;
-
- /* ASSERT(relId > 0); */
+ unsigned long flags;
/*
* Find the channel based on this relid and invokes the
@@ -223,11 +219,27 @@ static void process_chn_event(u32 relid)
*/
channel = relid2channel(relid);
- if (channel) {
- channel->onchannel_callback(channel->channel_callback_context);
- } else {
+ if (!channel) {
pr_err("channel not found for relid - %u\n", relid);
+ return;
}
+
+ /*
+ * A channel once created is persistent even when there
+ * is no driver handling the device. An unloading driver
+ * sets the onchannel_callback to NULL under the
+ * protection of the channel inbound_lock. Thus, checking
+ * and invoking the driver specific callback takes care of
+ * orderly unloading of the driver.
+ */
+
+ spin_lock_irqsave(&channel->inbound_lock, flags);
+ if (channel->onchannel_callback != NULL)
+ channel->onchannel_callback(channel->channel_callback_context);
+ else
+ pr_err("no channel callback for relid - %u\n", relid);
+
+ spin_unlock_irqrestore(&channel->inbound_lock, flags);
}
/*
@@ -248,16 +260,17 @@ void vmbus_on_event(unsigned long data)
if (!recv_int_page[dword])
continue;
for (bit = 0; bit < 32; bit++) {
- if (sync_test_and_clear_bit(bit, (unsigned long *)&recv_int_page[dword])) {
+ if (sync_test_and_clear_bit(bit,
+ (unsigned long *)&recv_int_page[dword])) {
relid = (dword << 5) + bit;
- if (relid == 0) {
+ if (relid == 0)
/*
* Special case - vmbus
* channel protocol msg
*/
continue;
- }
+
process_chn_event(relid);
}
}
@@ -270,10 +283,25 @@ void vmbus_on_event(unsigned long data)
int vmbus_post_msg(void *buffer, size_t buflen)
{
union hv_connection_id conn_id;
+ int ret = 0;
+ int retries = 0;
conn_id.asu32 = 0;
conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
- return hv_post_message(conn_id, 1, buffer, buflen);
+
+ /*
+ * hv_post_message() can have transient failures because of
+ * insufficient resources. Retry the operation a couple of
+ * times before giving up.
+ */
+ while (retries < 3) {
+ ret = hv_post_message(conn_id, 1, buffer, buflen);
+ if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
+ return ret;
+ retries++;
+ msleep(100);
+ }
+ return ret;
}
/*
diff --git a/drivers/staging/hv/hv.c b/drivers/hv/hv.c
index 824f81679ae8..0fb100ed91a3 100644
--- a/drivers/staging/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -25,8 +25,8 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-
-#include "hyperv.h"
+#include <linux/hyperv.h>
+#include <asm/hyperv.h>
#include "hyperv_vmbus.h"
/* The one and only */
@@ -111,7 +111,7 @@ static u64 do_hypercall(u64 control, void *input, void *output)
u64 hv_status = 0;
u64 input_address = (input) ? virt_to_phys(input) : 0;
u64 output_address = (output) ? virt_to_phys(output) : 0;
- volatile void *hypercall_page = hv_context.hypercall_page;
+ void *hypercall_page = hv_context.hypercall_page;
__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
__asm__ __volatile__("call *%3" : "=a" (hv_status) :
@@ -132,7 +132,7 @@ static u64 do_hypercall(u64 control, void *input, void *output)
u64 output_address = (output) ? virt_to_phys(output) : 0;
u32 output_address_hi = output_address >> 32;
u32 output_address_lo = output_address & 0xFFFFFFFF;
- volatile void *hypercall_page = hv_context.hypercall_page;
+ void *hypercall_page = hv_context.hypercall_page;
__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
"=a"(hv_status_lo) : "d" (control_hi),
@@ -151,7 +151,6 @@ static u64 do_hypercall(u64 control, void *input, void *output)
*/
int hv_init(void)
{
- int ret = 0;
int max_leaf;
union hv_x64_msr_hypercall_contents hypercall_msr;
void *virtaddr = NULL;
@@ -164,11 +163,7 @@ int hv_init(void)
goto cleanup;
max_leaf = query_hypervisor_info();
- /* HvQueryHypervisorFeatures(maxLeaf); */
- /*
- * We only support running on top of Hyper-V
- */
rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
if (hv_context.guestid != 0)
@@ -181,10 +176,6 @@ int hv_init(void)
/* See if the hypercall page is already set */
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
- /*
- * Allocate the hypercall page memory
- * virtaddr = osd_page_alloc(1);
- */
virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
if (!virtaddr)
@@ -222,7 +213,7 @@ int hv_init(void)
hv_context.signal_event_param->flag_number = 0;
hv_context.signal_event_param->rsvdz = 0;
- return ret;
+ return 0;
cleanup:
if (virtaddr) {
@@ -233,8 +224,8 @@ cleanup:
vfree(virtaddr);
}
- ret = -1;
- return ret;
+
+ return -ENOTSUPP;
}
/*
@@ -378,7 +369,7 @@ void hv_synic_init(void *irqarg)
shared_sint.as_uint64 = 0;
shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
shared_sint.masked = false;
- shared_sint.auto_eoi = true;
+ shared_sint.auto_eoi = false;
wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 13b0ecf7d5d6..89f52440fcf4 100644
--- a/drivers/staging/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -26,8 +26,8 @@
#include <linux/nls.h>
#include <linux/connector.h>
#include <linux/workqueue.h>
+#include <linux/hyperv.h>
-#include "hyperv.h"
#include "hv_kvp.h"
@@ -44,21 +44,24 @@
static struct {
bool active; /* transaction status - active or not */
int recv_len; /* number of bytes received. */
+ int index; /* current index */
struct vmbus_channel *recv_channel; /* chn we got the request */
u64 recv_req_id; /* request ID. */
} kvp_transaction;
-static int kvp_send_key(int index);
+static void kvp_send_key(struct work_struct *dummy);
+
+#define TIMEOUT_FIRED 1
static void kvp_respond_to_host(char *key, char *value, int error);
static void kvp_work_func(struct work_struct *dummy);
static void kvp_register(void);
static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
+static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL };
static const char kvp_name[] = "kvp_kernel_module";
-static int timeout_fired;
static u8 *recv_buffer;
/*
* Register the kernel component with the user-level daemon.
@@ -90,8 +93,7 @@ kvp_work_func(struct work_struct *dummy)
* If the timer fires, the user-mode component has not responded;
* process the pending transaction.
*/
- kvp_respond_to_host("Unknown key", "Guest timed out", timeout_fired);
- timeout_fired = 1;
+ kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED);
}
/*
@@ -121,10 +123,11 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
}
}
-static int
-kvp_send_key(int index)
+static void
+kvp_send_key(struct work_struct *dummy)
{
struct cn_msg *msg;
+ int index = kvp_transaction.index;
msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
@@ -136,9 +139,8 @@ kvp_send_key(int index)
msg->len = sizeof(struct hv_ku_msg);
cn_netlink_send(msg, 0, GFP_ATOMIC);
kfree(msg);
- return 0;
}
- return 1;
+ return;
}
/*
@@ -177,6 +179,15 @@ kvp_respond_to_host(char *key, char *value, int error)
channel = kvp_transaction.recv_channel;
req_id = kvp_transaction.recv_req_id;
+ kvp_transaction.active = false;
+
+ if (channel->onchannel_callback == NULL)
+ /*
+ * We have raced with util driver being unloaded;
+ * silently return.
+ */
+ return;
+
icmsghdrp = (struct icmsg_hdr *)
&recv_buffer[sizeof(struct vmbuspipe_hdr)];
kvp_msg = (struct hv_kvp_msg *)
@@ -217,7 +228,6 @@ response_done:
vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
VM_PKT_DATA_INBAND, 0);
- kvp_transaction.active = false;
}
/*
@@ -243,10 +253,6 @@ void hv_kvp_onchannelcallback(void *context)
struct icmsg_negotiate *negop = NULL;
- if (kvp_transaction.active)
- return;
-
-
vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
if (recvlen > 0) {
@@ -254,7 +260,7 @@ void hv_kvp_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- prep_negotiate_resp(icmsghdrp, negop, recv_buffer);
+ vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer);
} else {
kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
sizeof(struct vmbuspipe_hdr) +
@@ -282,6 +288,7 @@ void hv_kvp_onchannelcallback(void *context)
kvp_transaction.recv_channel = channel;
kvp_transaction.recv_req_id = requestid;
kvp_transaction.active = true;
+ kvp_transaction.index = kvp_data->index;
/*
* Get the information from the
@@ -292,8 +299,8 @@ void hv_kvp_onchannelcallback(void *context)
* Set a timeout to deal with
* user-mode not responding.
*/
- kvp_send_key(kvp_data->index);
- schedule_delayed_work(&kvp_work, 100);
+ schedule_work(&kvp_sendkey_work);
+ schedule_delayed_work(&kvp_work, 5*HZ);
return;
@@ -312,16 +319,14 @@ callback_done:
}
int
-hv_kvp_init(void)
+hv_kvp_init(struct hv_util_service *srv)
{
int err;
err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback);
if (err)
return err;
- recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!recv_buffer)
- return -ENOMEM;
+ recv_buffer = srv->recv_buffer;
return 0;
}
@@ -330,5 +335,5 @@ void hv_kvp_deinit(void)
{
cn_del_callback(&kvp_id);
cancel_delayed_work_sync(&kvp_work);
- kfree(recv_buffer);
+ cancel_work_sync(&kvp_sendkey_work);
}
diff --git a/drivers/staging/hv/hv_kvp.h b/drivers/hv/hv_kvp.h
index 8c402f357d37..9b765d7df838 100644
--- a/drivers/staging/hv/hv_kvp.h
+++ b/drivers/hv/hv_kvp.h
@@ -175,7 +175,7 @@ struct hv_kvp_msg {
struct hv_kvp_msg_enumerate kvp_data;
};
-int hv_kvp_init(void);
+int hv_kvp_init(struct hv_util_service *);
void hv_kvp_deinit(void);
void hv_kvp_onchannelcallback(void *);
diff --git a/drivers/staging/hv/hv_util.c b/drivers/hv/hv_util.c
index c164b54b4cd7..55d58f21e6d4 100644
--- a/drivers/staging/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -26,15 +26,31 @@
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/reboot.h>
-#include <linux/dmi.h>
-#include <linux/pci.h>
+#include <linux/hyperv.h>
-#include "hyperv.h"
#include "hv_kvp.h"
-static u8 *shut_txf_buf;
-static u8 *time_txf_buf;
-static u8 *hbeat_txf_buf;
+
+static void shutdown_onchannelcallback(void *context);
+static struct hv_util_service util_shutdown = {
+ .util_cb = shutdown_onchannelcallback,
+};
+
+static void timesync_onchannelcallback(void *context);
+static struct hv_util_service util_timesynch = {
+ .util_cb = timesync_onchannelcallback,
+};
+
+static void heartbeat_onchannelcallback(void *context);
+static struct hv_util_service util_heartbeat = {
+ .util_cb = heartbeat_onchannelcallback,
+};
+
+static struct hv_util_service util_kvp = {
+ .util_cb = hv_kvp_onchannelcallback,
+ .util_init = hv_kvp_init,
+ .util_deinit = hv_kvp_deinit,
+};
static void shutdown_onchannelcallback(void *context)
{
@@ -42,6 +58,7 @@ static void shutdown_onchannelcallback(void *context)
u32 recvlen;
u64 requestid;
u8 execute_shutdown = false;
+ u8 *shut_txf_buf = util_shutdown.recv_buffer;
struct shutdown_msg_data *shutdown_msg;
@@ -56,7 +73,7 @@ static void shutdown_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
+ vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
} else {
shutdown_msg =
(struct shutdown_msg_data *)&shut_txf_buf[
@@ -91,7 +108,7 @@ static void shutdown_onchannelcallback(void *context)
}
if (execute_shutdown == true)
- orderly_poweroff(false);
+ orderly_poweroff(true);
}
/*
@@ -109,6 +126,24 @@ static inline void do_adj_guesttime(u64 hosttime)
}
/*
+ * Set the host time in a process context.
+ */
+
+struct adj_time_work {
+ struct work_struct work;
+ u64 host_time;
+};
+
+static void hv_set_host_time(struct work_struct *work)
+{
+ struct adj_time_work *wrk;
+
+ wrk = container_of(work, struct adj_time_work, work);
+ do_adj_guesttime(wrk->host_time);
+ kfree(wrk);
+}
+
+/*
* Synchronize time with host after reboot, restore, etc.
*
* ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
@@ -121,17 +156,26 @@ static inline void do_adj_guesttime(u64 hosttime)
*/
static inline void adj_guesttime(u64 hosttime, u8 flags)
{
+ struct adj_time_work *wrk;
static s32 scnt = 50;
+ wrk = kmalloc(sizeof(struct adj_time_work), GFP_ATOMIC);
+ if (wrk == NULL)
+ return;
+
+ wrk->host_time = hosttime;
if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
- do_adj_guesttime(hosttime);
+ INIT_WORK(&wrk->work, hv_set_host_time);
+ schedule_work(&wrk->work);
return;
}
if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) {
scnt--;
- do_adj_guesttime(hosttime);
- }
+ INIT_WORK(&wrk->work, hv_set_host_time);
+ schedule_work(&wrk->work);
+ } else
+ kfree(wrk);
}
/*
@@ -144,6 +188,7 @@ static void timesync_onchannelcallback(void *context)
u64 requestid;
struct icmsg_hdr *icmsghdrp;
struct ictimesync_data *timedatap;
+ u8 *time_txf_buf = util_timesynch.recv_buffer;
vmbus_recvpacket(channel, time_txf_buf,
PAGE_SIZE, &recvlen, &requestid);
@@ -153,7 +198,7 @@ static void timesync_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
+ vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
} else {
timedatap = (struct ictimesync_data *)&time_txf_buf[
sizeof(struct vmbuspipe_hdr) +
@@ -182,6 +227,7 @@ static void heartbeat_onchannelcallback(void *context)
u64 requestid;
struct icmsg_hdr *icmsghdrp;
struct heartbeat_msg_data *heartbeat_msg;
+ u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
vmbus_recvpacket(channel, hbeat_txf_buf,
PAGE_SIZE, &recvlen, &requestid);
@@ -191,7 +237,7 @@ static void heartbeat_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
+ vmbus_prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
} else {
heartbeat_msg =
(struct heartbeat_msg_data *)&hbeat_txf_buf[
@@ -210,92 +256,94 @@ static void heartbeat_onchannelcallback(void *context)
}
}
-static const struct pci_device_id __initconst
-hv_utils_pci_table[] __maybe_unused = {
- { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
-
-
-static const struct dmi_system_id __initconst
-hv_utils_dmi_table[] __maybe_unused = {
- {
- .ident = "Hyper-V",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
- DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
- },
- },
- { },
-};
-MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
-
-
-static int __init init_hyperv_utils(void)
+static int util_probe(struct hv_device *dev,
+ const struct hv_vmbus_device_id *dev_id)
{
- pr_info("Registering HyperV Utility Driver\n");
-
- if (hv_kvp_init())
- return -ENODEV;
-
-
- if (!dmi_check_system(hv_utils_dmi_table))
- return -ENODEV;
-
- shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ struct hv_util_service *srv =
+ (struct hv_util_service *)dev_id->driver_data;
+ int ret;
- if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) {
- pr_info("Unable to allocate memory for receive buffer\n");
- kfree(shut_txf_buf);
- kfree(time_txf_buf);
- kfree(hbeat_txf_buf);
+ srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!srv->recv_buffer)
return -ENOMEM;
+ if (srv->util_init) {
+ ret = srv->util_init(srv);
+ if (ret) {
+ ret = -ENODEV;
+ goto error1;
+ }
}
- hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
+ ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0,
+ srv->util_cb, dev->channel);
+ if (ret)
+ goto error;
+
+ hv_set_drvdata(dev, srv);
+ return 0;
- hv_cb_utils[HV_TIMESYNC_MSG].callback = &timesync_onchannelcallback;
+error:
+ if (srv->util_deinit)
+ srv->util_deinit();
+error1:
+ kfree(srv->recv_buffer);
+ return ret;
+}
- hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback;
+static int util_remove(struct hv_device *dev)
+{
+ struct hv_util_service *srv = hv_get_drvdata(dev);
- hv_cb_utils[HV_KVP_MSG].callback = &hv_kvp_onchannelcallback;
+ vmbus_close(dev->channel);
+ if (srv->util_deinit)
+ srv->util_deinit();
+ kfree(srv->recv_buffer);
return 0;
}
-static void exit_hyperv_utils(void)
-{
- pr_info("De-Registered HyperV Utility Driver\n");
+static const struct hv_vmbus_device_id id_table[] = {
+ /* Shutdown guid */
+ { VMBUS_DEVICE(0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
+ 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB)
+ .driver_data = (unsigned long)&util_shutdown },
+ /* Time synch guid */
+ { VMBUS_DEVICE(0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+ 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf)
+ .driver_data = (unsigned long)&util_timesynch },
+ /* Heartbeat guid */
+ { VMBUS_DEVICE(0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
+ 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d)
+ .driver_data = (unsigned long)&util_heartbeat },
+ /* KVP guid */
+ { VMBUS_DEVICE(0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+ 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6)
+ .driver_data = (unsigned long)&util_kvp },
+ { },
+};
- if (hv_cb_utils[HV_SHUTDOWN_MSG].channel != NULL)
- hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
- &chn_cb_negotiate;
- hv_cb_utils[HV_SHUTDOWN_MSG].callback = NULL;
+MODULE_DEVICE_TABLE(vmbus, id_table);
- if (hv_cb_utils[HV_TIMESYNC_MSG].channel != NULL)
- hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
- &chn_cb_negotiate;
- hv_cb_utils[HV_TIMESYNC_MSG].callback = NULL;
+/* The one and only one */
+static struct hv_driver util_drv = {
+ .name = "hv_util",
+ .id_table = id_table,
+ .probe = util_probe,
+ .remove = util_remove,
+};
- if (hv_cb_utils[HV_HEARTBEAT_MSG].channel != NULL)
- hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
- &chn_cb_negotiate;
- hv_cb_utils[HV_HEARTBEAT_MSG].callback = NULL;
+static int __init init_hyperv_utils(void)
+{
+ pr_info("Registering HyperV Utility Driver\n");
- if (hv_cb_utils[HV_KVP_MSG].channel != NULL)
- hv_cb_utils[HV_KVP_MSG].channel->onchannel_callback =
- &chn_cb_negotiate;
- hv_cb_utils[HV_KVP_MSG].callback = NULL;
+ return vmbus_driver_register(&util_drv);
+}
- hv_kvp_deinit();
+static void exit_hyperv_utils(void)
+{
+ pr_info("De-Registered HyperV Utility Driver\n");
- kfree(shut_txf_buf);
- kfree(time_txf_buf);
- kfree(hbeat_txf_buf);
+ vmbus_driver_unregister(&util_drv);
}
module_init(init_hyperv_utils);
diff --git a/drivers/staging/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 349ad80ce328..0aee1122734c 100644
--- a/drivers/staging/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -28,8 +28,7 @@
#include <linux/list.h>
#include <asm/sync_bitops.h>
#include <linux/atomic.h>
-
-#include "hyperv.h"
+#include <linux/hyperv.h>
/*
* The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
@@ -451,8 +450,8 @@ enum {
/* #define VMBUS_PORT_ID 11 */
/* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */
-static const struct hv_guid VMBUS_SERVICE_ID = {
- .data = {
+static const uuid_le VMBUS_SERVICE_ID = {
+ .b = {
0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c,
0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4
},
@@ -530,8 +529,6 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info,
u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *ring_info);
-void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix);
-
void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
struct hv_ring_buffer_debug_info *debug_info);
@@ -601,12 +598,12 @@ extern struct vmbus_connection vmbus_connection;
/* General vmbus interface */
-struct hv_device *vmbus_child_device_create(struct hv_guid *type,
- struct hv_guid *instance,
+struct hv_device *vmbus_device_create(uuid_le *type,
+ uuid_le *instance,
struct vmbus_channel *channel);
-int vmbus_child_device_register(struct hv_device *child_device_obj);
-void vmbus_child_device_unregister(struct hv_device *device_obj);
+int vmbus_device_register(struct hv_device *child_device_obj);
+void vmbus_device_unregister(struct hv_device *device_obj);
/* static void */
/* VmbusChildDeviceDestroy( */
diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 42f76728429a..8af25a097d75 100644
--- a/drivers/staging/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -25,8 +25,8 @@
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/hyperv.h>
-#include "hyperv.h"
#include "hyperv_vmbus.h"
@@ -34,7 +34,8 @@
/* Amount of space to write to */
-#define BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
+#define BYTES_AVAIL_TO_WRITE(r, w, z) \
+ ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
/*
@@ -171,37 +172,6 @@ hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info)
return (u64)ring_info->ring_buffer->write_index << 32;
}
-
-/*
- *
- * hv_dump_ring_info()
- *
- * Dump out to console the ring buffer info
- *
- */
-void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix)
-{
- u32 bytes_avail_towrite;
- u32 bytes_avail_toread;
-
- hv_get_ringbuffer_availbytes(ring_info,
- &bytes_avail_toread,
- &bytes_avail_towrite);
-
- DPRINT(VMBUS,
- DEBUG_RING_LVL,
- "%s <<ringinfo %p buffer %p avail write %u "
- "avail read %u read idx %u write idx %u>>",
- prefix,
- ring_info,
- ring_info->ring_buffer->buffer,
- bytes_avail_towrite,
- bytes_avail_toread,
- ring_info->ring_buffer->read_index,
- ring_info->ring_buffer->write_index);
-}
-
-
/*
*
* hv_copyfrom_ringbuffer()
@@ -390,7 +360,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
/* is empty since the read index == write index */
if (bytes_avail_towrite <= totalbytes_towrite) {
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
- return -1;
+ return -EAGAIN;
}
/* Write to the ring buffer */
@@ -450,7 +420,7 @@ int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info,
spin_unlock_irqrestore(&Inring_info->ring_lock, flags);
- return -1;
+ return -EAGAIN;
}
/* Convert to byte offset */
@@ -496,7 +466,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
if (bytes_avail_toread < buflen) {
spin_unlock_irqrestore(&inring_info->ring_lock, flags);
- return -1;
+ return -EAGAIN;
}
next_read_location =
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 1c949f5fb716..0c048dd8013f 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -28,14 +28,12 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/sysctl.h>
-#include <linux/pci.h>
-#include <linux/dmi.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <linux/completion.h>
-
-#include "hyperv.h"
+#include <linux/hyperv.h>
+#include <asm/hyperv.h>
#include "hyperv_vmbus.h"
@@ -43,15 +41,28 @@ static struct acpi_device *hv_acpi_dev;
static struct tasklet_struct msg_dpc;
static struct tasklet_struct event_dpc;
-
-unsigned int vmbus_loglevel = (ALL_MODULES << 16 | INFO_LVL);
-EXPORT_SYMBOL(vmbus_loglevel);
- /* (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT); */
- /* (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT); */
-
static struct completion probe_event;
static int irq;
+struct hv_device_info {
+ u32 chn_id;
+ u32 chn_state;
+ uuid_le chn_type;
+ uuid_le chn_instance;
+
+ u32 monitor_id;
+ u32 server_monitor_pending;
+ u32 server_monitor_latency;
+ u32 server_monitor_conn_id;
+ u32 client_monitor_pending;
+ u32 client_monitor_latency;
+ u32 client_monitor_conn_id;
+
+ struct hv_dev_port_info inbound;
+ struct hv_dev_port_info outbound;
+};
+
+
static void get_channel_info(struct hv_device *device,
struct hv_device_info *info)
{
@@ -65,9 +76,9 @@ static void get_channel_info(struct hv_device *device,
info->chn_id = debug_info.relid;
info->chn_state = debug_info.state;
memcpy(&info->chn_type, &debug_info.interfacetype,
- sizeof(struct hv_guid));
+ sizeof(uuid_le));
memcpy(&info->chn_instance, &debug_info.interface_instance,
- sizeof(struct hv_guid));
+ sizeof(uuid_le));
info->monitor_id = debug_info.monitorid;
@@ -97,6 +108,14 @@ static void get_channel_info(struct hv_device *device,
debug_info.outbound.bytes_avail_towrite;
}
+#define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2)
+static void print_alias_name(struct hv_device *hv_dev, char *alias_name)
+{
+ int i;
+ for (i = 0; i < VMBUS_ALIAS_LEN; i += 2)
+ sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]);
+}
+
/*
* vmbus_show_device_attr - Show the device attribute in sysfs.
*
@@ -108,97 +127,105 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
char *buf)
{
struct hv_device *hv_dev = device_to_hv_device(dev);
- struct hv_device_info device_info;
+ struct hv_device_info *device_info;
+ char alias_name[VMBUS_ALIAS_LEN + 1];
+ int ret = 0;
- memset(&device_info, 0, sizeof(struct hv_device_info));
+ device_info = kzalloc(sizeof(struct hv_device_info), GFP_KERNEL);
+ if (!device_info)
+ return ret;
- get_channel_info(hv_dev, &device_info);
+ get_channel_info(hv_dev, device_info);
if (!strcmp(dev_attr->attr.name, "class_id")) {
- return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+ ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x%02x%02x%02x%02x%02x%02x}\n",
- device_info.chn_type.data[3],
- device_info.chn_type.data[2],
- device_info.chn_type.data[1],
- device_info.chn_type.data[0],
- device_info.chn_type.data[5],
- device_info.chn_type.data[4],
- device_info.chn_type.data[7],
- device_info.chn_type.data[6],
- device_info.chn_type.data[8],
- device_info.chn_type.data[9],
- device_info.chn_type.data[10],
- device_info.chn_type.data[11],
- device_info.chn_type.data[12],
- device_info.chn_type.data[13],
- device_info.chn_type.data[14],
- device_info.chn_type.data[15]);
+ device_info->chn_type.b[3],
+ device_info->chn_type.b[2],
+ device_info->chn_type.b[1],
+ device_info->chn_type.b[0],
+ device_info->chn_type.b[5],
+ device_info->chn_type.b[4],
+ device_info->chn_type.b[7],
+ device_info->chn_type.b[6],
+ device_info->chn_type.b[8],
+ device_info->chn_type.b[9],
+ device_info->chn_type.b[10],
+ device_info->chn_type.b[11],
+ device_info->chn_type.b[12],
+ device_info->chn_type.b[13],
+ device_info->chn_type.b[14],
+ device_info->chn_type.b[15]);
} else if (!strcmp(dev_attr->attr.name, "device_id")) {
- return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+ ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x%02x%02x%02x%02x%02x%02x}\n",
- device_info.chn_instance.data[3],
- device_info.chn_instance.data[2],
- device_info.chn_instance.data[1],
- device_info.chn_instance.data[0],
- device_info.chn_instance.data[5],
- device_info.chn_instance.data[4],
- device_info.chn_instance.data[7],
- device_info.chn_instance.data[6],
- device_info.chn_instance.data[8],
- device_info.chn_instance.data[9],
- device_info.chn_instance.data[10],
- device_info.chn_instance.data[11],
- device_info.chn_instance.data[12],
- device_info.chn_instance.data[13],
- device_info.chn_instance.data[14],
- device_info.chn_instance.data[15]);
+ device_info->chn_instance.b[3],
+ device_info->chn_instance.b[2],
+ device_info->chn_instance.b[1],
+ device_info->chn_instance.b[0],
+ device_info->chn_instance.b[5],
+ device_info->chn_instance.b[4],
+ device_info->chn_instance.b[7],
+ device_info->chn_instance.b[6],
+ device_info->chn_instance.b[8],
+ device_info->chn_instance.b[9],
+ device_info->chn_instance.b[10],
+ device_info->chn_instance.b[11],
+ device_info->chn_instance.b[12],
+ device_info->chn_instance.b[13],
+ device_info->chn_instance.b[14],
+ device_info->chn_instance.b[15]);
+ } else if (!strcmp(dev_attr->attr.name, "modalias")) {
+ print_alias_name(hv_dev, alias_name);
+ ret = sprintf(buf, "vmbus:%s\n", alias_name);
} else if (!strcmp(dev_attr->attr.name, "state")) {
- return sprintf(buf, "%d\n", device_info.chn_state);
+ ret = sprintf(buf, "%d\n", device_info->chn_state);
} else if (!strcmp(dev_attr->attr.name, "id")) {
- return sprintf(buf, "%d\n", device_info.chn_id);
+ ret = sprintf(buf, "%d\n", device_info->chn_id);
} else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) {
- return sprintf(buf, "%d\n", device_info.outbound.int_mask);
+ ret = sprintf(buf, "%d\n", device_info->outbound.int_mask);
} else if (!strcmp(dev_attr->attr.name, "out_read_index")) {
- return sprintf(buf, "%d\n", device_info.outbound.read_idx);
+ ret = sprintf(buf, "%d\n", device_info->outbound.read_idx);
} else if (!strcmp(dev_attr->attr.name, "out_write_index")) {
- return sprintf(buf, "%d\n", device_info.outbound.write_idx);
+ ret = sprintf(buf, "%d\n", device_info->outbound.write_idx);
} else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) {
- return sprintf(buf, "%d\n",
- device_info.outbound.bytes_avail_toread);
+ ret = sprintf(buf, "%d\n",
+ device_info->outbound.bytes_avail_toread);
} else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) {
- return sprintf(buf, "%d\n",
- device_info.outbound.bytes_avail_towrite);
+ ret = sprintf(buf, "%d\n",
+ device_info->outbound.bytes_avail_towrite);
} else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) {
- return sprintf(buf, "%d\n", device_info.inbound.int_mask);
+ ret = sprintf(buf, "%d\n", device_info->inbound.int_mask);
} else if (!strcmp(dev_attr->attr.name, "in_read_index")) {
- return sprintf(buf, "%d\n", device_info.inbound.read_idx);
+ ret = sprintf(buf, "%d\n", device_info->inbound.read_idx);
} else if (!strcmp(dev_attr->attr.name, "in_write_index")) {
- return sprintf(buf, "%d\n", device_info.inbound.write_idx);
+ ret = sprintf(buf, "%d\n", device_info->inbound.write_idx);
} else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) {
- return sprintf(buf, "%d\n",
- device_info.inbound.bytes_avail_toread);
+ ret = sprintf(buf, "%d\n",
+ device_info->inbound.bytes_avail_toread);
} else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) {
- return sprintf(buf, "%d\n",
- device_info.inbound.bytes_avail_towrite);
+ ret = sprintf(buf, "%d\n",
+ device_info->inbound.bytes_avail_towrite);
} else if (!strcmp(dev_attr->attr.name, "monitor_id")) {
- return sprintf(buf, "%d\n", device_info.monitor_id);
+ ret = sprintf(buf, "%d\n", device_info->monitor_id);
} else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) {
- return sprintf(buf, "%d\n", device_info.server_monitor_pending);
+ ret = sprintf(buf, "%d\n", device_info->server_monitor_pending);
} else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) {
- return sprintf(buf, "%d\n", device_info.server_monitor_latency);
+ ret = sprintf(buf, "%d\n", device_info->server_monitor_latency);
} else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) {
- return sprintf(buf, "%d\n",
- device_info.server_monitor_conn_id);
+ ret = sprintf(buf, "%d\n",
+ device_info->server_monitor_conn_id);
} else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) {
- return sprintf(buf, "%d\n", device_info.client_monitor_pending);
+ ret = sprintf(buf, "%d\n", device_info->client_monitor_pending);
} else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) {
- return sprintf(buf, "%d\n", device_info.client_monitor_latency);
+ ret = sprintf(buf, "%d\n", device_info->client_monitor_latency);
} else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) {
- return sprintf(buf, "%d\n",
- device_info.client_monitor_conn_id);
- } else {
- return 0;
+ ret = sprintf(buf, "%d\n",
+ device_info->client_monitor_conn_id);
}
+
+ kfree(device_info);
+ return ret;
}
/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
@@ -208,6 +235,7 @@ static struct device_attribute vmbus_device_attrs[] = {
__ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL),
__ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL),
__ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL),
+ __ATTR(modalias, S_IRUGO, vmbus_show_device_attr, NULL),
__ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
__ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
@@ -238,76 +266,60 @@ static struct device_attribute vmbus_device_attrs[] = {
* This routine is invoked when a device is added or removed on the vmbus to
* generate a uevent to udev in the userspace. The udev will then look at its
* rule and the uevent generated here to load the appropriate driver
+ *
+ * The alias string will be of the form vmbus:guid where guid is the string
+ * representation of the device guid (each byte of the guid will be
+ * represented with two hex characters.
*/
static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
{
struct hv_device *dev = device_to_hv_device(device);
int ret;
+ char alias_name[VMBUS_ALIAS_LEN + 1];
- ret = add_uevent_var(env, "VMBUS_DEVICE_CLASS_GUID={"
- "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
- "%02x%02x%02x%02x%02x%02x%02x%02x}",
- dev->dev_type.data[3],
- dev->dev_type.data[2],
- dev->dev_type.data[1],
- dev->dev_type.data[0],
- dev->dev_type.data[5],
- dev->dev_type.data[4],
- dev->dev_type.data[7],
- dev->dev_type.data[6],
- dev->dev_type.data[8],
- dev->dev_type.data[9],
- dev->dev_type.data[10],
- dev->dev_type.data[11],
- dev->dev_type.data[12],
- dev->dev_type.data[13],
- dev->dev_type.data[14],
- dev->dev_type.data[15]);
+ print_alias_name(dev, alias_name);
+ ret = add_uevent_var(env, "MODALIAS=vmbus:%s", alias_name);
+ return ret;
+}
- if (ret)
- return ret;
+static uuid_le null_guid;
- ret = add_uevent_var(env, "VMBUS_DEVICE_DEVICE_GUID={"
- "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
- "%02x%02x%02x%02x%02x%02x%02x%02x}",
- dev->dev_instance.data[3],
- dev->dev_instance.data[2],
- dev->dev_instance.data[1],
- dev->dev_instance.data[0],
- dev->dev_instance.data[5],
- dev->dev_instance.data[4],
- dev->dev_instance.data[7],
- dev->dev_instance.data[6],
- dev->dev_instance.data[8],
- dev->dev_instance.data[9],
- dev->dev_instance.data[10],
- dev->dev_instance.data[11],
- dev->dev_instance.data[12],
- dev->dev_instance.data[13],
- dev->dev_instance.data[14],
- dev->dev_instance.data[15]);
- if (ret)
- return ret;
+static inline bool is_null_guid(const __u8 *guid)
+{
+ if (memcmp(guid, &null_guid, sizeof(uuid_le)))
+ return false;
+ return true;
+}
- return 0;
+/*
+ * Return a matching hv_vmbus_device_id pointer.
+ * If there is no match, return NULL.
+ */
+static const struct hv_vmbus_device_id *hv_vmbus_get_id(
+ const struct hv_vmbus_device_id *id,
+ __u8 *guid)
+{
+ for (; !is_null_guid(id->guid); id++)
+ if (!memcmp(&id->guid, guid, sizeof(uuid_le)))
+ return id;
+
+ return NULL;
}
+
/*
* vmbus_match - Attempt to match the specified device to the specified driver
*/
static int vmbus_match(struct device *device, struct device_driver *driver)
{
- int match = 0;
struct hv_driver *drv = drv_to_hv_drv(driver);
struct hv_device *hv_dev = device_to_hv_device(device);
- /* We found our driver ? */
- if (memcmp(&hv_dev->dev_type, &drv->dev_type,
- sizeof(struct hv_guid)) == 0)
- match = 1;
+ if (hv_vmbus_get_id(drv->id_table, hv_dev->dev_type.b))
+ return 1;
- return match;
+ return 0;
}
/*
@@ -319,9 +331,11 @@ static int vmbus_probe(struct device *child_device)
struct hv_driver *drv =
drv_to_hv_drv(child_device->driver);
struct hv_device *dev = device_to_hv_device(child_device);
+ const struct hv_vmbus_device_id *dev_id;
+ dev_id = hv_vmbus_get_id(drv->id_table, dev->dev_type.b);
if (drv->probe) {
- ret = drv->probe(dev);
+ ret = drv->probe(dev, dev_id);
if (ret != 0)
pr_err("probe failed for device %s (%d)\n",
dev_name(child_device), ret);
@@ -339,22 +353,14 @@ static int vmbus_probe(struct device *child_device)
*/
static int vmbus_remove(struct device *child_device)
{
- int ret;
- struct hv_driver *drv;
-
+ struct hv_driver *drv = drv_to_hv_drv(child_device->driver);
struct hv_device *dev = device_to_hv_device(child_device);
- if (child_device->driver) {
- drv = drv_to_hv_drv(child_device->driver);
-
- if (drv->remove) {
- ret = drv->remove(dev);
- } else {
- pr_err("remove not set for driver %s\n",
- dev_name(child_device));
- ret = -ENODEV;
- }
- }
+ if (drv->remove)
+ drv->remove(dev);
+ else
+ pr_err("remove not set for driver %s\n",
+ dev_name(child_device));
return 0;
}
@@ -422,9 +428,6 @@ static void vmbus_onmessage_work(struct work_struct *work)
kfree(ctx);
}
-/*
- * vmbus_on_msg_dpc - DPC routine to handle messages from the hypervisior
- */
static void vmbus_on_msg_dpc(unsigned long data)
{
int cpu = smp_processor_id();
@@ -468,53 +471,42 @@ static void vmbus_on_msg_dpc(unsigned long data)
}
}
-/*
- * vmbus_on_isr - ISR routine
- */
-static int vmbus_on_isr(void)
+static irqreturn_t vmbus_isr(int irq, void *dev_id)
{
- int ret = 0;
int cpu = smp_processor_id();
void *page_addr;
struct hv_message *msg;
union hv_synic_event_flags *event;
+ bool handled = false;
- page_addr = hv_context.synic_message_page[cpu];
- msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
-
- /* Check if there are actual msgs to be process */
- if (msg->header.message_type != HVMSG_NONE)
- ret |= 0x1;
+ /*
+ * Check for events before checking for messages. This is the order
+ * in which events and messages are checked in Windows guests on
+ * Hyper-V, and the Windows team suggested we do the same.
+ */
page_addr = hv_context.synic_event_page[cpu];
event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
/* Since we are a child, we only need to check bit 0 */
- if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0]))
- ret |= 0x2;
-
- return ret;
-}
-
-
-static irqreturn_t vmbus_isr(int irq, void *dev_id)
-{
- int ret;
-
- ret = vmbus_on_isr();
+ if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
+ handled = true;
+ tasklet_schedule(&event_dpc);
+ }
- /* Schedules a dpc if necessary */
- if (ret > 0) {
- if (test_bit(0, (unsigned long *)&ret))
- tasklet_schedule(&msg_dpc);
+ page_addr = hv_context.synic_message_page[cpu];
+ msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
- if (test_bit(1, (unsigned long *)&ret))
- tasklet_schedule(&event_dpc);
+ /* Check if there are actual msgs to be processed */
+ if (msg->header.message_type != HVMSG_NONE) {
+ handled = true;
+ tasklet_schedule(&msg_dpc);
+ }
+ if (handled)
return IRQ_HANDLED;
- } else {
+ else
return IRQ_NONE;
- }
}
/*
@@ -538,26 +530,20 @@ static int vmbus_bus_init(int irq)
return ret;
}
- /* Initialize the bus context */
tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0);
tasklet_init(&event_dpc, vmbus_on_event, 0);
- /* Now, register the bus with LDM */
ret = bus_register(&hv_bus);
if (ret)
- return ret;
+ goto err_cleanup;
- /* Get the interrupt resource */
ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
driver_name, hv_acpi_dev);
if (ret != 0) {
pr_err("Unable to request IRQ %d\n",
irq);
-
- bus_unregister(&hv_bus);
-
- return ret;
+ goto err_unregister;
}
vector = IRQ0_VECTOR + irq;
@@ -568,76 +554,81 @@ static int vmbus_bus_init(int irq)
*/
on_each_cpu(hv_synic_init, (void *)&vector, 1);
ret = vmbus_connect();
- if (ret) {
- free_irq(irq, hv_acpi_dev);
- bus_unregister(&hv_bus);
- return ret;
- }
-
+ if (ret)
+ goto err_irq;
vmbus_request_offers();
return 0;
+
+err_irq:
+ free_irq(irq, hv_acpi_dev);
+
+err_unregister:
+ bus_unregister(&hv_bus);
+
+err_cleanup:
+ hv_cleanup();
+
+ return ret;
}
/**
- * vmbus_child_driver_register() - Register a vmbus's child driver
- * @drv: Pointer to driver structure you want to register
- *
+ * __vmbus_child_driver_register - Register a vmbus's driver
+ * @drv: Pointer to driver structure you want to register
+ * @owner: owner module of the drv
+ * @mod_name: module name string
*
* Registers the given driver with Linux through the 'driver_register()' call
- * And sets up the hyper-v vmbus handling for this driver.
+ * and sets up the hyper-v vmbus handling for this driver.
* It will return the state of the 'driver_register()' call.
*
- * Mainly used by Hyper-V drivers.
*/
-int vmbus_child_driver_register(struct device_driver *drv)
+int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, const char *mod_name)
{
int ret;
- pr_info("child driver registering - name %s\n", drv->name);
+ pr_info("registering driver %s\n", hv_driver->name);
- /* The child driver on this vmbus */
- drv->bus = &hv_bus;
+ hv_driver->driver.name = hv_driver->name;
+ hv_driver->driver.owner = owner;
+ hv_driver->driver.mod_name = mod_name;
+ hv_driver->driver.bus = &hv_bus;
- ret = driver_register(drv);
+ ret = driver_register(&hv_driver->driver);
vmbus_request_offers();
return ret;
}
-EXPORT_SYMBOL(vmbus_child_driver_register);
+EXPORT_SYMBOL_GPL(__vmbus_driver_register);
/**
- * vmbus_child_driver_unregister() - Unregister a vmbus's child driver
- * @drv: Pointer to driver structure you want to un-register
- *
- *
- * Un-register the given driver with Linux through the 'driver_unregister()'
- * call. And ungegisters the driver from the Hyper-V vmbus handler.
+ * vmbus_driver_unregister() - Unregister a vmbus's driver
+ * @drv: Pointer to driver structure you want to un-register
*
- * Mainly used by Hyper-V drivers.
+ * Un-register the given driver that was previous registered with a call to
+ * vmbus_driver_register()
*/
-void vmbus_child_driver_unregister(struct device_driver *drv)
+void vmbus_driver_unregister(struct hv_driver *hv_driver)
{
- pr_info("child driver unregistering - name %s\n", drv->name);
+ pr_info("unregistering driver %s\n", hv_driver->name);
- driver_unregister(drv);
+ driver_unregister(&hv_driver->driver);
}
-EXPORT_SYMBOL(vmbus_child_driver_unregister);
+EXPORT_SYMBOL_GPL(vmbus_driver_unregister);
/*
- * vmbus_child_device_create - Creates and registers a new child device
+ * vmbus_device_create - Creates and registers a new child device
* on the vmbus.
*/
-struct hv_device *vmbus_child_device_create(struct hv_guid *type,
- struct hv_guid *instance,
+struct hv_device *vmbus_device_create(uuid_le *type,
+ uuid_le *instance,
struct vmbus_channel *channel)
{
struct hv_device *child_device_obj;
- /* Allocate the new child device */
child_device_obj = kzalloc(sizeof(struct hv_device), GFP_KERNEL);
if (!child_device_obj) {
pr_err("Unable to allocate device object for child device\n");
@@ -645,29 +636,27 @@ struct hv_device *vmbus_child_device_create(struct hv_guid *type,
}
child_device_obj->channel = channel;
- memcpy(&child_device_obj->dev_type, type, sizeof(struct hv_guid));
+ memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le));
memcpy(&child_device_obj->dev_instance, instance,
- sizeof(struct hv_guid));
+ sizeof(uuid_le));
return child_device_obj;
}
/*
- * vmbus_child_device_register - Register the child device
+ * vmbus_device_register - Register the child device
*/
-int vmbus_child_device_register(struct hv_device *child_device_obj)
+int vmbus_device_register(struct hv_device *child_device_obj)
{
int ret = 0;
static atomic_t device_num = ATOMIC_INIT(0);
- /* Set the device name. Otherwise, device_register() will fail. */
dev_set_name(&child_device_obj->device, "vmbus_0_%d",
atomic_inc_return(&device_num));
- /* The new device belongs to this bus */
- child_device_obj->device.bus = &hv_bus; /* device->dev.bus; */
+ child_device_obj->device.bus = &hv_bus;
child_device_obj->device.parent = &hv_acpi_dev->dev;
child_device_obj->device.release = vmbus_device_release;
@@ -687,10 +676,10 @@ int vmbus_child_device_register(struct hv_device *child_device_obj)
}
/*
- * vmbus_child_device_unregister - Remove the specified child device
+ * vmbus_device_unregister - Remove the specified child device
* from the vmbus.
*/
-void vmbus_child_device_unregister(struct hv_device *device_obj)
+void vmbus_device_unregister(struct hv_device *device_obj)
{
/*
* Kick off the process of unregistering the device.
@@ -727,9 +716,8 @@ static int vmbus_acpi_add(struct acpi_device *device)
hv_acpi_dev = device;
- result =
- acpi_walk_resources(device->handle, METHOD_NAME__CRS,
- vmbus_walk_resources, &irq);
+ result = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+ vmbus_walk_resources, &irq);
if (ACPI_FAILURE(result)) {
complete(&probe_event);
@@ -754,21 +742,9 @@ static struct acpi_driver vmbus_acpi_driver = {
},
};
-/*
- * We use a PCI table to determine if we should autoload this driver This is
- * needed by distro tools to determine if the hyperv drivers should be
- * installed and/or configured. We don't do anything else with the table, but
- * it needs to be present.
- */
-static const struct pci_device_id microsoft_hv_pci_table[] = {
- { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
-
static int __init hv_acpi_init(void)
{
- int ret;
+ int ret, t;
init_completion(&probe_event);
@@ -781,22 +757,30 @@ static int __init hv_acpi_init(void)
if (ret)
return ret;
- wait_for_completion(&probe_event);
+ t = wait_for_completion_timeout(&probe_event, 5*HZ);
+ if (t == 0) {
+ ret = -ETIMEDOUT;
+ goto cleanup;
+ }
if (irq <= 0) {
- acpi_bus_unregister_driver(&vmbus_acpi_driver);
- return -ENODEV;
+ ret = -ENODEV;
+ goto cleanup;
}
ret = vmbus_bus_init(irq);
if (ret)
- acpi_bus_unregister_driver(&vmbus_acpi_driver);
+ goto cleanup;
+
+ return 0;
+
+cleanup:
+ acpi_bus_unregister_driver(&vmbus_acpi_driver);
return ret;
}
MODULE_LICENSE("GPL");
MODULE_VERSION(HV_DRV_VERSION);
-module_param(vmbus_loglevel, int, S_IRUGO|S_IWUSR);
module_init(hv_acpi_init);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 0b62c3c6b7ce..9b347acf1559 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -68,6 +68,16 @@ config SENSORS_ABITUGURU3
This driver can also be built as a module. If so, the module
will be called abituguru3.
+config SENSORS_AD7314
+ tristate "Analog Devices AD7314 and compatibles"
+ depends on SPI && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Analog Devices
+ AD7314, ADT7301 and ADT7302 temperature sensors.
+
+ This driver can also be built as a module. If so, the module
+ will be called ad7314.
+
config SENSORS_AD7414
tristate "Analog Devices AD7414"
depends on I2C && EXPERIMENTAL
@@ -303,6 +313,16 @@ config SENSORS_DS1621
This driver can also be built as a module. If so, the module
will be called ds1621.
+config SENSORS_EXYNOS4_TMU
+ tristate "Temperature sensor on Samsung EXYNOS4"
+ depends on EXYNOS4_DEV_TMU
+ help
+ If you say yes here you get support for TMU (Thermal Managment
+ Unit) on SAMSUNG EXYNOS4 series of SoC.
+
+ This driver can also be built as a module. If so, the module
+ will be called exynos4-tmu.
+
config SENSORS_I5K_AMB
tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
depends on PCI && EXPERIMENTAL
@@ -531,6 +551,7 @@ config SENSORS_LM75
If you say yes here you get support for one common type of
temperature sensor chip, with models including:
+ - Analog Devices ADT75
- Dallas Semiconductor DS75 and DS1775
- Maxim MAX6625 and MAX6626
- Microchip MCP980x
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 3c9ccefea791..8251ce8cd035 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_SENSORS_W83791D) += w83791d.o
obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o
obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o
+obj-$(CONFIG_SENSORS_AD7314) += ad7314.o
obj-$(CONFIG_SENSORS_AD7414) += ad7414.o
obj-$(CONFIG_SENSORS_AD7418) += ad7418.o
obj-$(CONFIG_SENSORS_ADCXX) += adcxx.o
@@ -47,6 +48,7 @@ obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o
obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o
obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o
+obj-$(CONFIG_SENSORS_EXYNOS4_TMU) += exynos4_tmu.o
obj-$(CONFIG_SENSORS_F71805F) += f71805f.o
obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o
obj-$(CONFIG_SENSORS_F75375S) += f75375s.o
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
new file mode 100644
index 000000000000..318e38e85376
--- /dev/null
+++ b/drivers/hwmon/ad7314.c
@@ -0,0 +1,186 @@
+/*
+ * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ * Conversion to hwmon from IIO done by Jonathan Cameron <jic23@cam.ac.uk>
+ */
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/*
+ * AD7314 power mode
+ */
+#define AD7314_PD 0x2000
+
+/*
+ * AD7314 temperature masks
+ */
+#define AD7314_TEMP_SIGN 0x200
+#define AD7314_TEMP_MASK 0x7FE0
+#define AD7314_TEMP_OFFSET 5
+
+/*
+ * ADT7301 and ADT7302 temperature masks
+ */
+#define ADT7301_TEMP_SIGN 0x2000
+#define ADT7301_TEMP_MASK 0x3FFF
+
+enum ad7314_variant {
+ adt7301,
+ adt7302,
+ ad7314,
+};
+
+struct ad7314_data {
+ struct spi_device *spi_dev;
+ struct device *hwmon_dev;
+ u16 rx ____cacheline_aligned;
+};
+
+static int ad7314_spi_read(struct ad7314_data *chip, s16 *data)
+{
+ int ret;
+
+ ret = spi_read(chip->spi_dev, (u8 *)&chip->rx, sizeof(chip->rx));
+ if (ret < 0) {
+ dev_err(&chip->spi_dev->dev, "SPI read error\n");
+ return ret;
+ }
+
+ *data = be16_to_cpu(chip->rx);
+
+ return ret;
+}
+
+static ssize_t ad7314_show_temperature(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ad7314_data *chip = dev_get_drvdata(dev);
+ s16 data;
+ int ret;
+
+ ret = ad7314_spi_read(chip, &data);
+ if (ret < 0)
+ return ret;
+ switch (spi_get_device_id(chip->spi_dev)->driver_data) {
+ case ad7314:
+ data = (data & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET;
+ data = (data << 6) >> 6;
+
+ return sprintf(buf, "%d\n", 250 * data);
+ case adt7301:
+ case adt7302:
+ /*
+ * Documented as a 13 bit twos complement register
+ * with a sign bit - which is a 14 bit 2's complement
+ * register. 1lsb - 31.25 milli degrees centigrade
+ */
+ data &= ADT7301_TEMP_MASK;
+ data = (data << 2) >> 2;
+
+ return sprintf(buf, "%d\n",
+ DIV_ROUND_CLOSEST(data * 3125, 100));
+ default:
+ return -EINVAL;
+ }
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
+ ad7314_show_temperature, NULL, 0);
+
+static struct attribute *ad7314_attributes[] = {
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group ad7314_group = {
+ .attrs = ad7314_attributes,
+};
+
+static int __devinit ad7314_probe(struct spi_device *spi_dev)
+{
+ int ret;
+ struct ad7314_data *chip;
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ dev_set_drvdata(&spi_dev->dev, chip);
+
+ ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group);
+ if (ret < 0)
+ goto error_free_chip;
+ chip->hwmon_dev = hwmon_device_register(&spi_dev->dev);
+ if (IS_ERR(chip->hwmon_dev)) {
+ ret = PTR_ERR(chip->hwmon_dev);
+ goto error_remove_group;
+ }
+
+ return 0;
+error_remove_group:
+ sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
+error_free_chip:
+ kfree(chip);
+error_ret:
+ return ret;
+}
+
+static int __devexit ad7314_remove(struct spi_device *spi_dev)
+{
+ struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev);
+
+ hwmon_device_unregister(chip->hwmon_dev);
+ sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
+ kfree(chip);
+
+ return 0;
+}
+
+static const struct spi_device_id ad7314_id[] = {
+ { "adt7301", adt7301 },
+ { "adt7302", adt7302 },
+ { "ad7314", ad7314 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad7314_id);
+
+static struct spi_driver ad7314_driver = {
+ .driver = {
+ .name = "ad7314",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = ad7314_probe,
+ .remove = __devexit_p(ad7314_remove),
+ .id_table = ad7314_id,
+};
+
+static __init int ad7314_init(void)
+{
+ return spi_register_driver(&ad7314_driver);
+}
+module_init(ad7314_init);
+
+static __exit void ad7314_exit(void)
+{
+ spi_unregister_driver(&ad7314_driver);
+}
+module_exit(ad7314_exit);
+
+MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"
+ " temperature sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 932383786642..ce18c046f728 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -325,15 +325,6 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
return adjust_tjmax(c, id, dev);
}
-static void __devinit get_ucode_rev_on_cpu(void *edx)
-{
- u32 eax;
-
- wrmsr(MSR_IA32_UCODE_REV, 0, 0);
- sync_core();
- rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
-}
-
static int create_name_attr(struct platform_data *pdata, struct device *dev)
{
sysfs_attr_init(&pdata->name_attr.attr);
@@ -380,27 +371,16 @@ exit_free:
static int __cpuinit chk_ucode_version(unsigned int cpu)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
- int err;
- u32 edx;
/*
* Check if we have problem with errata AE18 of Core processors:
* Readings might stop update when processor visited too deep sleep,
* fixed for stepping D0 (6EC).
*/
- if (c->x86_model == 0xe && c->x86_mask < 0xc) {
- /* check for microcode update */
- err = smp_call_function_single(cpu, get_ucode_rev_on_cpu,
- &edx, 1);
- if (err) {
- pr_err("Cannot determine microcode revision of "
- "CPU#%u (%d)!\n", cpu, err);
- return -ENODEV;
- } else if (edx < 0x39) {
- pr_err("Errata AE18 not fixed, update BIOS or "
- "microcode of the CPU!\n");
- return -ENODEV;
- }
+ if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) {
+ pr_err("Errata AE18 not fixed, update BIOS or "
+ "microcode of the CPU!\n");
+ return -ENODEV;
}
return 0;
}
diff --git a/drivers/hwmon/exynos4_tmu.c b/drivers/hwmon/exynos4_tmu.c
new file mode 100644
index 000000000000..faa0884f61f6
--- /dev/null
+++ b/drivers/hwmon/exynos4_tmu.c
@@ -0,0 +1,524 @@
+/*
+ * exynos4_tmu.c - Samsung EXYNOS4 TMU (Thermal Management Unit)
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * Donggeun Kim <dg77.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/err.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#include <linux/platform_data/exynos4_tmu.h>
+
+#define EXYNOS4_TMU_REG_TRIMINFO 0x0
+#define EXYNOS4_TMU_REG_CONTROL 0x20
+#define EXYNOS4_TMU_REG_STATUS 0x28
+#define EXYNOS4_TMU_REG_CURRENT_TEMP 0x40
+#define EXYNOS4_TMU_REG_THRESHOLD_TEMP 0x44
+#define EXYNOS4_TMU_REG_TRIG_LEVEL0 0x50
+#define EXYNOS4_TMU_REG_TRIG_LEVEL1 0x54
+#define EXYNOS4_TMU_REG_TRIG_LEVEL2 0x58
+#define EXYNOS4_TMU_REG_TRIG_LEVEL3 0x5C
+#define EXYNOS4_TMU_REG_PAST_TEMP0 0x60
+#define EXYNOS4_TMU_REG_PAST_TEMP1 0x64
+#define EXYNOS4_TMU_REG_PAST_TEMP2 0x68
+#define EXYNOS4_TMU_REG_PAST_TEMP3 0x6C
+#define EXYNOS4_TMU_REG_INTEN 0x70
+#define EXYNOS4_TMU_REG_INTSTAT 0x74
+#define EXYNOS4_TMU_REG_INTCLEAR 0x78
+
+#define EXYNOS4_TMU_GAIN_SHIFT 8
+#define EXYNOS4_TMU_REF_VOLTAGE_SHIFT 24
+
+#define EXYNOS4_TMU_TRIM_TEMP_MASK 0xff
+#define EXYNOS4_TMU_CORE_ON 3
+#define EXYNOS4_TMU_CORE_OFF 2
+#define EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET 50
+#define EXYNOS4_TMU_TRIG_LEVEL0_MASK 0x1
+#define EXYNOS4_TMU_TRIG_LEVEL1_MASK 0x10
+#define EXYNOS4_TMU_TRIG_LEVEL2_MASK 0x100
+#define EXYNOS4_TMU_TRIG_LEVEL3_MASK 0x1000
+#define EXYNOS4_TMU_INTCLEAR_VAL 0x1111
+
+struct exynos4_tmu_data {
+ struct exynos4_tmu_platform_data *pdata;
+ struct device *hwmon_dev;
+ struct resource *mem;
+ void __iomem *base;
+ int irq;
+ struct work_struct irq_work;
+ struct mutex lock;
+ struct clk *clk;
+ u8 temp_error1, temp_error2;
+};
+
+/*
+ * TMU treats temperature as a mapped temperature code.
+ * The temperature is converted differently depending on the calibration type.
+ */
+static int temp_to_code(struct exynos4_tmu_data *data, u8 temp)
+{
+ struct exynos4_tmu_platform_data *pdata = data->pdata;
+ int temp_code;
+
+ /* temp should range between 25 and 125 */
+ if (temp < 25 || temp > 125) {
+ temp_code = -EINVAL;
+ goto out;
+ }
+
+ switch (pdata->cal_type) {
+ case TYPE_TWO_POINT_TRIMMING:
+ temp_code = (temp - 25) *
+ (data->temp_error2 - data->temp_error1) /
+ (85 - 25) + data->temp_error1;
+ break;
+ case TYPE_ONE_POINT_TRIMMING:
+ temp_code = temp + data->temp_error1 - 25;
+ break;
+ default:
+ temp_code = temp + EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET;
+ break;
+ }
+out:
+ return temp_code;
+}
+
+/*
+ * Calculate a temperature value from a temperature code.
+ * The unit of the temperature is degree Celsius.
+ */
+static int code_to_temp(struct exynos4_tmu_data *data, u8 temp_code)
+{
+ struct exynos4_tmu_platform_data *pdata = data->pdata;
+ int temp;
+
+ /* temp_code should range between 75 and 175 */
+ if (temp_code < 75 || temp_code > 175) {
+ temp = -ENODATA;
+ goto out;
+ }
+
+ switch (pdata->cal_type) {
+ case TYPE_TWO_POINT_TRIMMING:
+ temp = (temp_code - data->temp_error1) * (85 - 25) /
+ (data->temp_error2 - data->temp_error1) + 25;
+ break;
+ case TYPE_ONE_POINT_TRIMMING:
+ temp = temp_code - data->temp_error1 + 25;
+ break;
+ default:
+ temp = temp_code - EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET;
+ break;
+ }
+out:
+ return temp;
+}
+
+static int exynos4_tmu_initialize(struct platform_device *pdev)
+{
+ struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
+ struct exynos4_tmu_platform_data *pdata = data->pdata;
+ unsigned int status, trim_info;
+ int ret = 0, threshold_code;
+
+ mutex_lock(&data->lock);
+ clk_enable(data->clk);
+
+ status = readb(data->base + EXYNOS4_TMU_REG_STATUS);
+ if (!status) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Save trimming info in order to perform calibration */
+ trim_info = readl(data->base + EXYNOS4_TMU_REG_TRIMINFO);
+ data->temp_error1 = trim_info & EXYNOS4_TMU_TRIM_TEMP_MASK;
+ data->temp_error2 = ((trim_info >> 8) & EXYNOS4_TMU_TRIM_TEMP_MASK);
+
+ /* Write temperature code for threshold */
+ threshold_code = temp_to_code(data, pdata->threshold);
+ if (threshold_code < 0) {
+ ret = threshold_code;
+ goto out;
+ }
+ writeb(threshold_code,
+ data->base + EXYNOS4_TMU_REG_THRESHOLD_TEMP);
+
+ writeb(pdata->trigger_levels[0],
+ data->base + EXYNOS4_TMU_REG_TRIG_LEVEL0);
+ writeb(pdata->trigger_levels[1],
+ data->base + EXYNOS4_TMU_REG_TRIG_LEVEL1);
+ writeb(pdata->trigger_levels[2],
+ data->base + EXYNOS4_TMU_REG_TRIG_LEVEL2);
+ writeb(pdata->trigger_levels[3],
+ data->base + EXYNOS4_TMU_REG_TRIG_LEVEL3);
+
+ writel(EXYNOS4_TMU_INTCLEAR_VAL,
+ data->base + EXYNOS4_TMU_REG_INTCLEAR);
+out:
+ clk_disable(data->clk);
+ mutex_unlock(&data->lock);
+
+ return ret;
+}
+
+static void exynos4_tmu_control(struct platform_device *pdev, bool on)
+{
+ struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
+ struct exynos4_tmu_platform_data *pdata = data->pdata;
+ unsigned int con, interrupt_en;
+
+ mutex_lock(&data->lock);
+ clk_enable(data->clk);
+
+ con = pdata->reference_voltage << EXYNOS4_TMU_REF_VOLTAGE_SHIFT |
+ pdata->gain << EXYNOS4_TMU_GAIN_SHIFT;
+ if (on) {
+ con |= EXYNOS4_TMU_CORE_ON;
+ interrupt_en = pdata->trigger_level3_en << 12 |
+ pdata->trigger_level2_en << 8 |
+ pdata->trigger_level1_en << 4 |
+ pdata->trigger_level0_en;
+ } else {
+ con |= EXYNOS4_TMU_CORE_OFF;
+ interrupt_en = 0; /* Disable all interrupts */
+ }
+ writel(interrupt_en, data->base + EXYNOS4_TMU_REG_INTEN);
+ writel(con, data->base + EXYNOS4_TMU_REG_CONTROL);
+
+ clk_disable(data->clk);
+ mutex_unlock(&data->lock);
+}
+
+static int exynos4_tmu_read(struct exynos4_tmu_data *data)
+{
+ u8 temp_code;
+ int temp;
+
+ mutex_lock(&data->lock);
+ clk_enable(data->clk);
+
+ temp_code = readb(data->base + EXYNOS4_TMU_REG_CURRENT_TEMP);
+ temp = code_to_temp(data, temp_code);
+
+ clk_disable(data->clk);
+ mutex_unlock(&data->lock);
+
+ return temp;
+}
+
+static void exynos4_tmu_work(struct work_struct *work)
+{
+ struct exynos4_tmu_data *data = container_of(work,
+ struct exynos4_tmu_data, irq_work);
+
+ mutex_lock(&data->lock);
+ clk_enable(data->clk);
+
+ writel(EXYNOS4_TMU_INTCLEAR_VAL, data->base + EXYNOS4_TMU_REG_INTCLEAR);
+
+ kobject_uevent(&data->hwmon_dev->kobj, KOBJ_CHANGE);
+
+ enable_irq(data->irq);
+
+ clk_disable(data->clk);
+ mutex_unlock(&data->lock);
+}
+
+static irqreturn_t exynos4_tmu_irq(int irq, void *id)
+{
+ struct exynos4_tmu_data *data = id;
+
+ disable_irq_nosync(irq);
+ schedule_work(&data->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t exynos4_tmu_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "exynos4-tmu\n");
+}
+
+static ssize_t exynos4_tmu_show_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct exynos4_tmu_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ ret = exynos4_tmu_read(data);
+ if (ret < 0)
+ return ret;
+
+ /* convert from degree Celsius to millidegree Celsius */
+ return sprintf(buf, "%d\n", ret * 1000);
+}
+
+static ssize_t exynos4_tmu_show_alarm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct exynos4_tmu_data *data = dev_get_drvdata(dev);
+ struct exynos4_tmu_platform_data *pdata = data->pdata;
+ int temp;
+ unsigned int trigger_level;
+
+ temp = exynos4_tmu_read(data);
+ if (temp < 0)
+ return temp;
+
+ trigger_level = pdata->threshold + pdata->trigger_levels[attr->index];
+
+ return sprintf(buf, "%d\n", !!(temp > trigger_level));
+}
+
+static ssize_t exynos4_tmu_show_level(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct exynos4_tmu_data *data = dev_get_drvdata(dev);
+ struct exynos4_tmu_platform_data *pdata = data->pdata;
+ unsigned int temp = pdata->threshold +
+ pdata->trigger_levels[attr->index];
+
+ return sprintf(buf, "%u\n", temp * 1000);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, exynos4_tmu_show_name, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, exynos4_tmu_show_temp, NULL, 0);
+
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
+ exynos4_tmu_show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO,
+ exynos4_tmu_show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO,
+ exynos4_tmu_show_alarm, NULL, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, exynos4_tmu_show_level, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, exynos4_tmu_show_level, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO,
+ exynos4_tmu_show_level, NULL, 3);
+
+static struct attribute *exynos4_tmu_attributes[] = {
+ &dev_attr_name.attr,
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp1_max.dev_attr.attr,
+ &sensor_dev_attr_temp1_crit.dev_attr.attr,
+ &sensor_dev_attr_temp1_emergency.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group exynos4_tmu_attr_group = {
+ .attrs = exynos4_tmu_attributes,
+};
+
+static int __devinit exynos4_tmu_probe(struct platform_device *pdev)
+{
+ struct exynos4_tmu_data *data;
+ struct exynos4_tmu_platform_data *pdata = pdev->dev.platform_data;
+ int ret;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "No platform init data supplied.\n");
+ return -ENODEV;
+ }
+
+ data = kzalloc(sizeof(struct exynos4_tmu_data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&pdev->dev, "Failed to allocate driver structure\n");
+ return -ENOMEM;
+ }
+
+ data->irq = platform_get_irq(pdev, 0);
+ if (data->irq < 0) {
+ ret = data->irq;
+ dev_err(&pdev->dev, "Failed to get platform irq\n");
+ goto err_free;
+ }
+
+ INIT_WORK(&data->irq_work, exynos4_tmu_work);
+
+ data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!data->mem) {
+ ret = -ENOENT;
+ dev_err(&pdev->dev, "Failed to get platform resource\n");
+ goto err_free;
+ }
+
+ data->mem = request_mem_region(data->mem->start,
+ resource_size(data->mem), pdev->name);
+ if (!data->mem) {
+ ret = -ENODEV;
+ dev_err(&pdev->dev, "Failed to request memory region\n");
+ goto err_free;
+ }
+
+ data->base = ioremap(data->mem->start, resource_size(data->mem));
+ if (!data->base) {
+ ret = -ENODEV;
+ dev_err(&pdev->dev, "Failed to ioremap memory\n");
+ goto err_mem_region;
+ }
+
+ ret = request_irq(data->irq, exynos4_tmu_irq,
+ IRQF_TRIGGER_RISING,
+ "exynos4-tmu", data);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
+ goto err_io_remap;
+ }
+
+ data->clk = clk_get(NULL, "tmu_apbif");
+ if (IS_ERR(data->clk)) {
+ ret = PTR_ERR(data->clk);
+ dev_err(&pdev->dev, "Failed to get clock\n");
+ goto err_irq;
+ }
+
+ data->pdata = pdata;
+ platform_set_drvdata(pdev, data);
+ mutex_init(&data->lock);
+
+ ret = exynos4_tmu_initialize(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to initialize TMU\n");
+ goto err_clk;
+ }
+
+ ret = sysfs_create_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to create sysfs group\n");
+ goto err_clk;
+ }
+
+ data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ ret = PTR_ERR(data->hwmon_dev);
+ dev_err(&pdev->dev, "Failed to register hwmon device\n");
+ goto err_create_group;
+ }
+
+ exynos4_tmu_control(pdev, true);
+
+ return 0;
+
+err_create_group:
+ sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
+err_clk:
+ platform_set_drvdata(pdev, NULL);
+ clk_put(data->clk);
+err_irq:
+ free_irq(data->irq, data);
+err_io_remap:
+ iounmap(data->base);
+err_mem_region:
+ release_mem_region(data->mem->start, resource_size(data->mem));
+err_free:
+ kfree(data);
+
+ return ret;
+}
+
+static int __devexit exynos4_tmu_remove(struct platform_device *pdev)
+{
+ struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
+
+ exynos4_tmu_control(pdev, false);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
+
+ clk_put(data->clk);
+
+ free_irq(data->irq, data);
+
+ iounmap(data->base);
+ release_mem_region(data->mem->start, resource_size(data->mem));
+
+ platform_set_drvdata(pdev, NULL);
+
+ kfree(data);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int exynos4_tmu_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ exynos4_tmu_control(pdev, false);
+
+ return 0;
+}
+
+static int exynos4_tmu_resume(struct platform_device *pdev)
+{
+ exynos4_tmu_initialize(pdev);
+ exynos4_tmu_control(pdev, true);
+
+ return 0;
+}
+#else
+#define exynos4_tmu_suspend NULL
+#define exynos4_tmu_resume NULL
+#endif
+
+static struct platform_driver exynos4_tmu_driver = {
+ .driver = {
+ .name = "exynos4-tmu",
+ .owner = THIS_MODULE,
+ },
+ .probe = exynos4_tmu_probe,
+ .remove = __devexit_p(exynos4_tmu_remove),
+ .suspend = exynos4_tmu_suspend,
+ .resume = exynos4_tmu_resume,
+};
+
+static int __init exynos4_tmu_driver_init(void)
+{
+ return platform_driver_register(&exynos4_tmu_driver);
+}
+module_init(exynos4_tmu_driver_init);
+
+static void __exit exynos4_tmu_driver_exit(void)
+{
+ platform_driver_unregister(&exynos4_tmu_driver);
+}
+module_exit(exynos4_tmu_driver_exit);
+
+MODULE_DESCRIPTION("EXYNOS4 TMU Driver");
+MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:exynos4-tmu");
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 2d96ed2bf8ed..59dd881c71d8 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -605,7 +605,7 @@ static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {
/* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
standard models */
-static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
+static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[3][7] = { {
SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
show_pwm_auto_point_channel,
store_pwm_auto_point_channel, 0, 0),
@@ -627,7 +627,7 @@ static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
0, 0),
SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
show_pwm_auto_point_temp_hyst, NULL, 3, 0),
-
+}, {
SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
show_pwm_auto_point_channel,
store_pwm_auto_point_channel, 0, 1),
@@ -649,7 +649,7 @@ static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
0, 1),
SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
show_pwm_auto_point_temp_hyst, NULL, 3, 1),
-
+}, {
SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
show_pwm_auto_point_channel,
store_pwm_auto_point_channel, 0, 2),
@@ -671,12 +671,12 @@ static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
0, 2),
SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
show_pwm_auto_point_temp_hyst, NULL, 3, 2),
-};
+} };
/* PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the
pwm setting when the temperature is above the pwmX_auto_point1_temp can be
programmed instead of being hardcoded to 0xff */
-static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
+static struct sensor_device_attribute_2 f71869_auto_pwm_attr[3][8] = { {
SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
show_pwm_auto_point_channel,
store_pwm_auto_point_channel, 0, 0),
@@ -701,7 +701,7 @@ static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
0, 0),
SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
show_pwm_auto_point_temp_hyst, NULL, 3, 0),
-
+}, {
SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
show_pwm_auto_point_channel,
store_pwm_auto_point_channel, 0, 1),
@@ -726,7 +726,7 @@ static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
0, 1),
SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
show_pwm_auto_point_temp_hyst, NULL, 3, 1),
-
+}, {
SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
show_pwm_auto_point_channel,
store_pwm_auto_point_channel, 0, 2),
@@ -751,7 +751,7 @@ static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
0, 2),
SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
show_pwm_auto_point_temp_hyst, NULL, 3, 2),
-};
+} };
/* PWM attr for the standard models */
static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
@@ -928,7 +928,7 @@ static struct sensor_device_attribute_2 f8000_fan_attr[] = {
/* PWM attr for the f8000, zones mapped to temp instead of to pwm!
Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
-static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
+static struct sensor_device_attribute_2 f8000_auto_pwm_attr[3][14] = { {
SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
show_pwm_auto_point_channel,
store_pwm_auto_point_channel, 0, 0),
@@ -969,7 +969,7 @@ static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
show_pwm_auto_point_temp_hyst, NULL, 2, 2),
SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
show_pwm_auto_point_temp_hyst, NULL, 3, 2),
-
+}, {
SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
show_pwm_auto_point_channel,
store_pwm_auto_point_channel, 0, 1),
@@ -1010,7 +1010,7 @@ static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
show_pwm_auto_point_temp_hyst, NULL, 2, 0),
SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
show_pwm_auto_point_temp_hyst, NULL, 3, 0),
-
+}, {
SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
show_pwm_auto_point_channel,
store_pwm_auto_point_channel, 0, 2),
@@ -1051,7 +1051,7 @@ static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
show_pwm_auto_point_temp_hyst, NULL, 2, 1),
SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
show_pwm_auto_point_temp_hyst, NULL, 3, 1),
-};
+} };
/* Super I/O functions */
static inline int superio_inb(int base, int reg)
@@ -2154,6 +2154,104 @@ static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
device_remove_file(&pdev->dev, &attr[i].dev_attr);
}
+static int __devinit f71882fg_create_fan_sysfs_files(
+ struct platform_device *pdev, int idx)
+{
+ struct f71882fg_data *data = platform_get_drvdata(pdev);
+ int err;
+
+ /* Sanity check the pwm setting */
+ err = 0;
+ switch (data->type) {
+ case f71858fg:
+ if (((data->pwm_enable >> (idx * 2)) & 3) == 3)
+ err = 1;
+ break;
+ case f71862fg:
+ if (((data->pwm_enable >> (idx * 2)) & 1) != 1)
+ err = 1;
+ break;
+ case f8000:
+ if (idx == 2)
+ err = data->pwm_enable & 0x20;
+ break;
+ default:
+ break;
+ }
+ if (err) {
+ dev_err(&pdev->dev,
+ "Invalid (reserved) pwm settings: 0x%02x, "
+ "skipping fan %d\n",
+ (data->pwm_enable >> (idx * 2)) & 3, idx + 1);
+ return 0; /* This is a non fatal condition */
+ }
+
+ err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[idx][0],
+ ARRAY_SIZE(fxxxx_fan_attr[0]));
+ if (err)
+ return err;
+
+ if (f71882fg_fan_has_beep[data->type]) {
+ err = f71882fg_create_sysfs_files(pdev,
+ &fxxxx_fan_beep_attr[idx],
+ 1);
+ if (err)
+ return err;
+ }
+
+ dev_info(&pdev->dev, "Fan: %d is in %s mode\n", idx + 1,
+ (data->pwm_enable & (1 << (2 * idx))) ? "duty-cycle" : "RPM");
+
+ /* Check for unsupported auto pwm settings */
+ switch (data->type) {
+ case f71808e:
+ case f71808a:
+ case f71869:
+ case f71869a:
+ case f71889fg:
+ case f71889ed:
+ case f71889a:
+ data->pwm_auto_point_mapping[idx] =
+ f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(idx));
+ if ((data->pwm_auto_point_mapping[idx] & 0x80) ||
+ (data->pwm_auto_point_mapping[idx] & 3) == 0) {
+ dev_warn(&pdev->dev,
+ "Auto pwm controlled by raw digital "
+ "data, disabling pwm auto_point "
+ "sysfs attributes for fan %d\n", idx + 1);
+ return 0; /* This is a non fatal condition */
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (data->type) {
+ case f71862fg:
+ err = f71882fg_create_sysfs_files(pdev,
+ &f71862fg_auto_pwm_attr[idx][0],
+ ARRAY_SIZE(f71862fg_auto_pwm_attr[0]));
+ break;
+ case f71808e:
+ case f71869:
+ err = f71882fg_create_sysfs_files(pdev,
+ &f71869_auto_pwm_attr[idx][0],
+ ARRAY_SIZE(f71869_auto_pwm_attr[0]));
+ break;
+ case f8000:
+ err = f71882fg_create_sysfs_files(pdev,
+ &f8000_auto_pwm_attr[idx][0],
+ ARRAY_SIZE(f8000_auto_pwm_attr[0]));
+ break;
+ default:
+ err = f71882fg_create_sysfs_files(pdev,
+ &fxxxx_auto_pwm_attr[idx][0],
+ ARRAY_SIZE(fxxxx_auto_pwm_attr[0]));
+ }
+
+ return err;
+}
+
static int __devinit f71882fg_probe(struct platform_device *pdev)
{
struct f71882fg_data *data;
@@ -2272,117 +2370,29 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
data->pwm_enable =
f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
- /* Sanity check the pwm settings */
- switch (data->type) {
- case f71858fg:
- err = 0;
- for (i = 0; i < nr_fans; i++)
- if (((data->pwm_enable >> (i * 2)) & 3) == 3)
- err = 1;
- break;
- case f71862fg:
- err = (data->pwm_enable & 0x15) != 0x15;
- break;
- case f8000:
- err = data->pwm_enable & 0x20;
- break;
- default:
- err = 0;
- break;
- }
- if (err) {
- dev_err(&pdev->dev,
- "Invalid (reserved) pwm settings: 0x%02x\n",
- (unsigned int)data->pwm_enable);
- err = -ENODEV;
- goto exit_unregister_sysfs;
- }
-
- err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
- ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
- if (err)
- goto exit_unregister_sysfs;
-
- if (f71882fg_fan_has_beep[data->type]) {
- err = f71882fg_create_sysfs_files(pdev,
- fxxxx_fan_beep_attr, nr_fans);
+ for (i = 0; i < nr_fans; i++) {
+ err = f71882fg_create_fan_sysfs_files(pdev, i);
if (err)
goto exit_unregister_sysfs;
}
- switch (data->type) {
- case f71808e:
- case f71808a:
- case f71869:
- case f71869a:
- case f71889fg:
- case f71889ed:
- case f71889a:
- for (i = 0; i < nr_fans; i++) {
- data->pwm_auto_point_mapping[i] =
- f71882fg_read8(data,
- F71882FG_REG_POINT_MAPPING(i));
- if ((data->pwm_auto_point_mapping[i] & 0x80) ||
- (data->pwm_auto_point_mapping[i] & 3) == 0)
- break;
- }
- if (i != nr_fans) {
- dev_warn(&pdev->dev,
- "Auto pwm controlled by raw digital "
- "data, disabling pwm auto_point "
- "sysfs attributes\n");
- goto no_pwm_auto_point;
- }
- break;
- default:
- break;
- }
-
+ /* Some types have 1 extra fan with limited functionality */
switch (data->type) {
case f71808a:
err = f71882fg_create_sysfs_files(pdev,
- &fxxxx_auto_pwm_attr[0][0],
- ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
- if (err)
- goto exit_unregister_sysfs;
- err = f71882fg_create_sysfs_files(pdev,
f71808a_fan3_attr,
ARRAY_SIZE(f71808a_fan3_attr));
break;
- case f71862fg:
- err = f71882fg_create_sysfs_files(pdev,
- f71862fg_auto_pwm_attr,
- ARRAY_SIZE(f71862fg_auto_pwm_attr));
- break;
- case f71808e:
- case f71869:
- err = f71882fg_create_sysfs_files(pdev,
- f71869_auto_pwm_attr,
- ARRAY_SIZE(f71869_auto_pwm_attr));
- break;
case f8000:
err = f71882fg_create_sysfs_files(pdev,
f8000_fan_attr,
ARRAY_SIZE(f8000_fan_attr));
- if (err)
- goto exit_unregister_sysfs;
- err = f71882fg_create_sysfs_files(pdev,
- f8000_auto_pwm_attr,
- ARRAY_SIZE(f8000_auto_pwm_attr));
break;
default:
- err = f71882fg_create_sysfs_files(pdev,
- &fxxxx_auto_pwm_attr[0][0],
- ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
+ break;
}
if (err)
goto exit_unregister_sysfs;
-
-no_pwm_auto_point:
- for (i = 0; i < nr_fans; i++)
- dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1,
- (data->pwm_enable & (1 << 2 * i)) ?
- "duty-cycle" : "RPM");
}
data->hwmon_dev = hwmon_device_register(&pdev->dev);
@@ -2476,22 +2486,23 @@ static int f71882fg_remove(struct platform_device *pdev)
break;
case f71862fg:
f71882fg_remove_sysfs_files(pdev,
- f71862fg_auto_pwm_attr,
- ARRAY_SIZE(f71862fg_auto_pwm_attr));
+ &f71862fg_auto_pwm_attr[0][0],
+ ARRAY_SIZE(f71862fg_auto_pwm_attr[0]) *
+ nr_fans);
break;
case f71808e:
case f71869:
f71882fg_remove_sysfs_files(pdev,
- f71869_auto_pwm_attr,
- ARRAY_SIZE(f71869_auto_pwm_attr));
+ &f71869_auto_pwm_attr[0][0],
+ ARRAY_SIZE(f71869_auto_pwm_attr[0]) * nr_fans);
break;
case f8000:
f71882fg_remove_sysfs_files(pdev,
f8000_fan_attr,
ARRAY_SIZE(f8000_fan_attr));
f71882fg_remove_sysfs_files(pdev,
- f8000_auto_pwm_attr,
- ARRAY_SIZE(f8000_auto_pwm_attr));
+ &f8000_auto_pwm_attr[0][0],
+ ARRAY_SIZE(f8000_auto_pwm_attr[0]) * nr_fans);
break;
default:
f71882fg_remove_sysfs_files(pdev,
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index a61e7815a2a9..6460487e41b5 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -27,8 +27,7 @@
static struct class *hwmon_class;
-static DEFINE_IDR(hwmon_idr);
-static DEFINE_SPINLOCK(idr_lock);
+static DEFINE_IDA(hwmon_ida);
/**
* hwmon_device_register - register w/ hwmon
@@ -42,30 +41,17 @@ static DEFINE_SPINLOCK(idr_lock);
struct device *hwmon_device_register(struct device *dev)
{
struct device *hwdev;
- int id, err;
-
-again:
- if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0))
- return ERR_PTR(-ENOMEM);
-
- spin_lock(&idr_lock);
- err = idr_get_new(&hwmon_idr, NULL, &id);
- spin_unlock(&idr_lock);
+ int id;
- if (unlikely(err == -EAGAIN))
- goto again;
- else if (unlikely(err))
- return ERR_PTR(err);
+ id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
+ if (id < 0)
+ return ERR_PTR(id);
- id = id & MAX_ID_MASK;
hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
HWMON_ID_FORMAT, id);
- if (IS_ERR(hwdev)) {
- spin_lock(&idr_lock);
- idr_remove(&hwmon_idr, id);
- spin_unlock(&idr_lock);
- }
+ if (IS_ERR(hwdev))
+ ida_simple_remove(&hwmon_ida, id);
return hwdev;
}
@@ -81,9 +67,7 @@ void hwmon_device_unregister(struct device *dev)
if (likely(sscanf(dev_name(dev), HWMON_ID_FORMAT, &id) == 1)) {
device_unregister(dev);
- spin_lock(&idr_lock);
- idr_remove(&hwmon_idr, id);
- spin_unlock(&idr_lock);
+ ida_simple_remove(&hwmon_ida, id);
} else
dev_dbg(dev->parent,
"hwmon_device_unregister() failed: bad class ID!\n");
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index c316294c48b4..783d0c17b762 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -88,8 +88,7 @@
#define AEM_MIN_POWER_INTERVAL 200
#define UJ_PER_MJ 1000L
-static DEFINE_IDR(aem_idr);
-static DEFINE_SPINLOCK(aem_idr_lock);
+static DEFINE_IDA(aem_ida);
static struct platform_driver aem_driver = {
.driver = {
@@ -356,38 +355,6 @@ static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
complete(&data->read_complete);
}
-/* ID functions */
-
-/* Obtain an id */
-static int aem_idr_get(int *id)
-{
- int i, err;
-
-again:
- if (unlikely(!idr_pre_get(&aem_idr, GFP_KERNEL)))
- return -ENOMEM;
-
- spin_lock(&aem_idr_lock);
- err = idr_get_new(&aem_idr, NULL, &i);
- spin_unlock(&aem_idr_lock);
-
- if (unlikely(err == -EAGAIN))
- goto again;
- else if (unlikely(err))
- return err;
-
- *id = i & MAX_ID_MASK;
- return 0;
-}
-
-/* Release an object ID */
-static void aem_idr_put(int id)
-{
- spin_lock(&aem_idr_lock);
- idr_remove(&aem_idr, id);
- spin_unlock(&aem_idr_lock);
-}
-
/* Sensor support functions */
/* Read a sensor value */
@@ -530,7 +497,7 @@ static void aem_delete(struct aem_data *data)
ipmi_destroy_user(data->ipmi.user);
platform_set_drvdata(data->pdev, NULL);
platform_device_unregister(data->pdev);
- aem_idr_put(data->id);
+ ida_simple_remove(&aem_ida, data->id);
kfree(data);
}
@@ -587,7 +554,8 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL;
/* Create sub-device for this fw instance */
- if (aem_idr_get(&data->id))
+ data->id = ida_simple_get(&aem_ida, 0, 0, GFP_KERNEL);
+ if (data->id < 0)
goto id_err;
data->pdev = platform_device_alloc(DRVNAME, data->id);
@@ -638,7 +606,7 @@ ipmi_err:
platform_set_drvdata(data->pdev, NULL);
platform_device_unregister(data->pdev);
dev_err:
- aem_idr_put(data->id);
+ ida_simple_remove(&aem_ida, data->id);
id_err:
kfree(data);
@@ -720,7 +688,8 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL;
/* Create sub-device for this fw instance */
- if (aem_idr_get(&data->id))
+ data->id = ida_simple_get(&aem_ida, 0, 0, GFP_KERNEL);
+ if (data->id < 0)
goto id_err;
data->pdev = platform_device_alloc(DRVNAME, data->id);
@@ -771,7 +740,7 @@ ipmi_err:
platform_set_drvdata(data->pdev, NULL);
platform_device_unregister(data->pdev);
dev_err:
- aem_idr_put(data->id);
+ ida_simple_remove(&aem_ida, data->id);
id_err:
kfree(data);
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index ef902d5d06ab..90126a2a1e44 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -35,6 +35,7 @@
*/
enum lm75_type { /* keep sorted in alphabetical order */
+ adt75,
ds1775,
ds75,
lm75,
@@ -213,6 +214,7 @@ static int lm75_remove(struct i2c_client *client)
}
static const struct i2c_device_id lm75_ids[] = {
+ { "adt75", adt75, },
{ "ds1775", ds1775, },
{ "ds75", ds75, },
{ "lm75", lm75, },
@@ -247,19 +249,30 @@ static int lm75_detect(struct i2c_client *new_client,
I2C_FUNC_SMBUS_WORD_DATA))
return -ENODEV;
- /* Now, we do the remaining detection. There is no identification-
- dedicated register so we have to rely on several tricks:
- unused bits, registers cycling over 8-address boundaries,
- addresses 0x04-0x07 returning the last read value.
- The cycling+unused addresses combination is not tested,
- since it would significantly slow the detection down and would
- hardly add any value.
-
- The National Semiconductor LM75A is different than earlier
- LM75s. It has an ID byte of 0xaX (where X is the chip
- revision, with 1 being the only revision in existence) in
- register 7, and unused registers return 0xff rather than the
- last read value. */
+ /*
+ * Now, we do the remaining detection. There is no identification-
+ * dedicated register so we have to rely on several tricks:
+ * unused bits, registers cycling over 8-address boundaries,
+ * addresses 0x04-0x07 returning the last read value.
+ * The cycling+unused addresses combination is not tested,
+ * since it would significantly slow the detection down and would
+ * hardly add any value.
+ *
+ * The National Semiconductor LM75A is different than earlier
+ * LM75s. It has an ID byte of 0xaX (where X is the chip
+ * revision, with 1 being the only revision in existence) in
+ * register 7, and unused registers return 0xff rather than the
+ * last read value.
+ *
+ * Note that this function only detects the original National
+ * Semiconductor LM75 and the LM75A. Clones from other vendors
+ * aren't detected, on purpose, because they are typically never
+ * found on PC hardware. They are found on embedded designs where
+ * they can be instantiated explicitly so detection is not needed.
+ * The absence of identification registers on all these clones
+ * would make their exhaustive detection very difficult and weak,
+ * and odds are that the driver would bind to unsupported devices.
+ */
/* Unused bits */
conf = i2c_smbus_read_byte_data(new_client, 1);
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index c9237b9dcff2..4b26f51920ba 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -20,17 +20,18 @@ config SENSORS_PMBUS
help
If you say yes here you get hardware monitoring support for generic
PMBus devices, including but not limited to ADP4000, BMR450, BMR451,
- BMR453, BMR454, LTC2978, NCP4200, and NCP4208.
+ BMR453, BMR454, NCP4200, and NCP4208.
This driver can also be built as a module. If so, the module will
be called pmbus.
config SENSORS_ADM1275
- tristate "Analog Devices ADM1275"
+ tristate "Analog Devices ADM1275 and compatibles"
default n
help
If you say yes here you get hardware monitoring support for Analog
- Devices ADM1275 Hot-Swap Controller and Digital Power Monitor.
+ Devices ADM1275 and ADM1276 Hot-Swap Controller and Digital Power
+ Monitor.
This driver can also be built as a module. If so, the module will
be called adm1275.
@@ -45,6 +46,16 @@ config SENSORS_LM25066
This driver can also be built as a module. If so, the module will
be called lm25066.
+config SENSORS_LTC2978
+ tristate "Linear Technologies LTC2978 and LTC3880"
+ default n
+ help
+ If you say yes here you get hardware monitoring support for Linear
+ Technology LTC2978 and LTC3880.
+
+ This driver can also be built as a module. If so, the module will
+ be called ltc2978.
+
config SENSORS_MAX16064
tristate "Maxim MAX16064"
default n
@@ -97,4 +108,15 @@ config SENSORS_UCD9200
This driver can also be built as a module. If so, the module will
be called ucd9200.
+config SENSORS_ZL6100
+ tristate "Intersil ZL6100 and compatibles"
+ default n
+ help
+ If you say yes here you get hardware monitoring support for Intersil
+ ZL2004, ZL2006, ZL2008, ZL2105, ZL2106, ZL6100, and ZL6105 Digital
+ DC/DC Controllers.
+
+ This driver can also be built as a module. If so, the module will
+ be called zl6100.
+
endif # PMBUS
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index 623eedb1ed9a..789376c85dbb 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -6,8 +6,10 @@ obj-$(CONFIG_PMBUS) += pmbus_core.o
obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o
obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o
obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
+obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o
+obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o
diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
index c936e2782309..980a4d9d5028 100644
--- a/drivers/hwmon/pmbus/adm1275.c
+++ b/drivers/hwmon/pmbus/adm1275.c
@@ -23,6 +23,8 @@
#include <linux/i2c.h>
#include "pmbus.h"
+enum chips { adm1275, adm1276 };
+
#define ADM1275_PEAK_IOUT 0xd0
#define ADM1275_PEAK_VIN 0xd1
#define ADM1275_PEAK_VOUT 0xd2
@@ -31,14 +33,47 @@
#define ADM1275_VIN_VOUT_SELECT (1 << 6)
#define ADM1275_VRANGE (1 << 5)
+#define ADM1275_IOUT_WARN2_LIMIT 0xd7
+#define ADM1275_DEVICE_CONFIG 0xd8
+
+#define ADM1275_IOUT_WARN2_SELECT (1 << 4)
+
+#define ADM1276_PEAK_PIN 0xda
+
+#define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0)
+
+struct adm1275_data {
+ int id;
+ bool have_oc_fault;
+ struct pmbus_driver_info info;
+};
+
+#define to_adm1275_data(x) container_of(x, struct adm1275_data, info)
+
static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
{
- int ret;
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ const struct adm1275_data *data = to_adm1275_data(info);
+ int ret = 0;
if (page)
- return -EINVAL;
+ return -ENXIO;
switch (reg) {
+ case PMBUS_IOUT_UC_FAULT_LIMIT:
+ if (data->have_oc_fault) {
+ ret = -ENXIO;
+ break;
+ }
+ ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
+ break;
+ case PMBUS_IOUT_OC_FAULT_LIMIT:
+ if (!data->have_oc_fault) {
+ ret = -ENXIO;
+ break;
+ }
+ ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
+ break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
break;
@@ -48,10 +83,20 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
case PMBUS_VIRT_READ_VIN_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
break;
+ case PMBUS_VIRT_READ_PIN_MAX:
+ if (data->id != adm1276) {
+ ret = -ENXIO;
+ break;
+ }
+ ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
+ break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
case PMBUS_VIRT_RESET_VOUT_HISTORY:
case PMBUS_VIRT_RESET_VIN_HISTORY:
- ret = 0;
+ break;
+ case PMBUS_VIRT_RESET_PIN_HISTORY:
+ if (data->id != adm1276)
+ ret = -ENXIO;
break;
default:
ret = -ENODATA;
@@ -66,9 +111,14 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
int ret;
if (page)
- return -EINVAL;
+ return -ENXIO;
switch (reg) {
+ case PMBUS_IOUT_UC_FAULT_LIMIT:
+ case PMBUS_IOUT_OC_FAULT_LIMIT:
+ ret = pmbus_write_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT,
+ word);
+ break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0);
break;
@@ -78,6 +128,41 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
case PMBUS_VIRT_RESET_VIN_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0);
break;
+ case PMBUS_VIRT_RESET_PIN_HISTORY:
+ ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0);
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+ return ret;
+}
+
+static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ const struct adm1275_data *data = to_adm1275_data(info);
+ int mfr_status, ret;
+
+ if (page > 0)
+ return -ENXIO;
+
+ switch (reg) {
+ case PMBUS_STATUS_IOUT:
+ ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT);
+ if (ret < 0)
+ break;
+ mfr_status = pmbus_read_byte_data(client, page,
+ PMBUS_STATUS_MFR_SPECIFIC);
+ if (mfr_status < 0) {
+ ret = mfr_status;
+ break;
+ }
+ if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) {
+ ret |= data->have_oc_fault ?
+ PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT;
+ }
+ break;
default:
ret = -ENODATA;
break;
@@ -88,16 +173,17 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
static int adm1275_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int config;
+ int config, device_config;
int ret;
struct pmbus_driver_info *info;
+ struct adm1275_data *data;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BYTE_DATA))
return -ENODEV;
- info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL);
- if (!info)
+ data = kzalloc(sizeof(struct adm1275_data), GFP_KERNEL);
+ if (!data)
return -ENOMEM;
config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
@@ -106,6 +192,15 @@ static int adm1275_probe(struct i2c_client *client,
goto err_mem;
}
+ device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG);
+ if (device_config < 0) {
+ ret = device_config;
+ goto err_mem;
+ }
+
+ data->id = id->driver_data;
+ info = &data->info;
+
info->pages = 1;
info->format[PSC_VOLTAGE_IN] = direct;
info->format[PSC_VOLTAGE_OUT] = direct;
@@ -116,6 +211,7 @@ static int adm1275_probe(struct i2c_client *client,
info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
info->read_word_data = adm1275_read_word_data;
+ info->read_byte_data = adm1275_read_byte_data;
info->write_word_data = adm1275_write_word_data;
if (config & ADM1275_VRANGE) {
@@ -134,10 +230,36 @@ static int adm1275_probe(struct i2c_client *client,
info->R[PSC_VOLTAGE_OUT] = -1;
}
- if (config & ADM1275_VIN_VOUT_SELECT)
- info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
- else
- info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
+ if (device_config & ADM1275_IOUT_WARN2_SELECT)
+ data->have_oc_fault = true;
+
+ switch (id->driver_data) {
+ case adm1275:
+ if (config & ADM1275_VIN_VOUT_SELECT)
+ info->func[0] |=
+ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+ else
+ info->func[0] |=
+ PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
+ break;
+ case adm1276:
+ info->format[PSC_POWER] = direct;
+ info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
+ | PMBUS_HAVE_STATUS_INPUT;
+ if (config & ADM1275_VIN_VOUT_SELECT)
+ info->func[0] |=
+ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+ if (config & ADM1275_VRANGE) {
+ info->m[PSC_POWER] = 6043;
+ info->b[PSC_POWER] = 0;
+ info->R[PSC_POWER] = -2;
+ } else {
+ info->m[PSC_POWER] = 2115;
+ info->b[PSC_POWER] = 0;
+ info->R[PSC_POWER] = -1;
+ }
+ break;
+ }
ret = pmbus_do_probe(client, id, info);
if (ret)
@@ -145,22 +267,23 @@ static int adm1275_probe(struct i2c_client *client,
return 0;
err_mem:
- kfree(info);
+ kfree(data);
return ret;
}
static int adm1275_remove(struct i2c_client *client)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
- int ret;
+ const struct adm1275_data *data = to_adm1275_data(info);
- ret = pmbus_do_remove(client);
- kfree(info);
- return ret;
+ pmbus_do_remove(client);
+ kfree(data);
+ return 0;
}
static const struct i2c_device_id adm1275_id[] = {
- {"adm1275", 0},
+ { "adm1275", adm1275 },
+ { "adm1276", adm1276 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adm1275_id);
@@ -185,7 +308,7 @@ static void __exit adm1275_exit(void)
}
MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275");
+MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles");
MODULE_LICENSE("GPL");
module_init(adm1275_init);
module_exit(adm1275_exit);
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
index ac254fba551b..84a37f0c8db6 100644
--- a/drivers/hwmon/pmbus/lm25066.c
+++ b/drivers/hwmon/pmbus/lm25066.c
@@ -57,7 +57,7 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
int ret;
if (page > 1)
- return -EINVAL;
+ return -ENXIO;
/* Map READ_VAUX into READ_VOUT register on page 1 */
if (page == 1) {
@@ -85,7 +85,7 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
break;
default:
/* No other valid registers on page 1 */
- ret = -EINVAL;
+ ret = -ENXIO;
break;
}
goto done;
@@ -138,7 +138,7 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
int ret;
if (page > 1)
- return -EINVAL;
+ return -ENXIO;
switch (reg) {
case PMBUS_IIN_OC_WARN_LIMIT:
@@ -164,10 +164,10 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
static int lm25066_write_byte(struct i2c_client *client, int page, u8 value)
{
if (page > 1)
- return -EINVAL;
+ return -ENXIO;
- if (page == 0)
- return pmbus_write_byte(client, 0, value);
+ if (page <= 0)
+ return pmbus_write_byte(client, page, value);
return 0;
}
@@ -309,11 +309,10 @@ static int lm25066_remove(struct i2c_client *client)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct lm25066_data *data = to_lm25066_data(info);
- int ret;
- ret = pmbus_do_remove(client);
+ pmbus_do_remove(client);
kfree(data);
- return ret;
+ return 0;
}
static const struct i2c_device_id lm25066_id[] = {
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
new file mode 100644
index 000000000000..820fff48910b
--- /dev/null
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -0,0 +1,408 @@
+/*
+ * Hardware monitoring driver for LTC2978 and LTC3880
+ *
+ * Copyright (c) 2011 Ericsson AB.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+enum chips { ltc2978, ltc3880 };
+
+/* LTC2978 and LTC3880 */
+#define LTC2978_MFR_VOUT_PEAK 0xdd
+#define LTC2978_MFR_VIN_PEAK 0xde
+#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf
+#define LTC2978_MFR_SPECIAL_ID 0xe7
+
+/* LTC2978 only */
+#define LTC2978_MFR_VOUT_MIN 0xfb
+#define LTC2978_MFR_VIN_MIN 0xfc
+#define LTC2978_MFR_TEMPERATURE_MIN 0xfd
+
+/* LTC3880 only */
+#define LTC3880_MFR_IOUT_PEAK 0xd7
+#define LTC3880_MFR_CLEAR_PEAKS 0xe3
+#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
+
+#define LTC2978_ID_REV1 0x0121
+#define LTC2978_ID_REV2 0x0122
+#define LTC3880_ID 0x4000
+#define LTC3880_ID_MASK 0xff00
+
+/*
+ * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
+ * happens pretty much each time chip data is updated. Raw peak data therefore
+ * does not provide much value. To be able to provide useful peak data, keep an
+ * internal cache of measured peak data, which is only cleared if an explicit
+ * "clear peak" command is executed for the sensor in question.
+ */
+struct ltc2978_data {
+ enum chips id;
+ int vin_min, vin_max;
+ int temp_min, temp_max;
+ int vout_min[8], vout_max[8];
+ int iout_max[2];
+ int temp2_max[2];
+ struct pmbus_driver_info info;
+};
+
+#define to_ltc2978_data(x) container_of(x, struct ltc2978_data, info)
+
+static inline int lin11_to_val(int data)
+{
+ s16 e = ((s16)data) >> 11;
+ s32 m = (((s16)(data << 5)) >> 5);
+
+ /*
+ * mantissa is 10 bit + sign, exponent adds up to 15 bit.
+ * Add 6 bit to exponent for maximum accuracy (10 + 15 + 6 = 31).
+ */
+ e += 6;
+ return (e < 0 ? m >> -e : m << e);
+}
+
+static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
+ int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct ltc2978_data *data = to_ltc2978_data(info);
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VIRT_READ_VIN_MAX:
+ ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK);
+ if (ret >= 0) {
+ if (lin11_to_val(ret) > lin11_to_val(data->vin_max))
+ data->vin_max = ret;
+ ret = data->vin_max;
+ }
+ break;
+ case PMBUS_VIRT_READ_VOUT_MAX:
+ ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
+ if (ret >= 0) {
+ /*
+ * VOUT is 16 bit unsigned with fixed exponent,
+ * so we can compare it directly
+ */
+ if (ret > data->vout_max[page])
+ data->vout_max[page] = ret;
+ ret = data->vout_max[page];
+ }
+ break;
+ case PMBUS_VIRT_READ_TEMP_MAX:
+ ret = pmbus_read_word_data(client, page,
+ LTC2978_MFR_TEMPERATURE_PEAK);
+ if (ret >= 0) {
+ if (lin11_to_val(ret) > lin11_to_val(data->temp_max))
+ data->temp_max = ret;
+ ret = data->temp_max;
+ }
+ break;
+ case PMBUS_VIRT_RESET_VOUT_HISTORY:
+ case PMBUS_VIRT_RESET_VIN_HISTORY:
+ case PMBUS_VIRT_RESET_TEMP_HISTORY:
+ ret = 0;
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+ return ret;
+}
+
+static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct ltc2978_data *data = to_ltc2978_data(info);
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VIRT_READ_VIN_MIN:
+ ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN);
+ if (ret >= 0) {
+ if (lin11_to_val(ret) < lin11_to_val(data->vin_min))
+ data->vin_min = ret;
+ ret = data->vin_min;
+ }
+ break;
+ case PMBUS_VIRT_READ_VOUT_MIN:
+ ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
+ if (ret >= 0) {
+ /*
+ * VOUT_MIN is known to not be supported on some lots
+ * of LTC2978 revision 1, and will return the maximum
+ * possible voltage if read. If VOUT_MAX is valid and
+ * lower than the reading of VOUT_MIN, use it instead.
+ */
+ if (data->vout_max[page] && ret > data->vout_max[page])
+ ret = data->vout_max[page];
+ if (ret < data->vout_min[page])
+ data->vout_min[page] = ret;
+ ret = data->vout_min[page];
+ }
+ break;
+ case PMBUS_VIRT_READ_TEMP_MIN:
+ ret = pmbus_read_word_data(client, page,
+ LTC2978_MFR_TEMPERATURE_MIN);
+ if (ret >= 0) {
+ if (lin11_to_val(ret)
+ < lin11_to_val(data->temp_min))
+ data->temp_min = ret;
+ ret = data->temp_min;
+ }
+ break;
+ case PMBUS_VIRT_READ_IOUT_MAX:
+ case PMBUS_VIRT_RESET_IOUT_HISTORY:
+ case PMBUS_VIRT_READ_TEMP2_MAX:
+ case PMBUS_VIRT_RESET_TEMP2_HISTORY:
+ ret = -ENXIO;
+ break;
+ default:
+ ret = ltc2978_read_word_data_common(client, page, reg);
+ break;
+ }
+ return ret;
+}
+
+static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct ltc2978_data *data = to_ltc2978_data(info);
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VIRT_READ_IOUT_MAX:
+ ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK);
+ if (ret >= 0) {
+ if (lin11_to_val(ret)
+ > lin11_to_val(data->iout_max[page]))
+ data->iout_max[page] = ret;
+ ret = data->iout_max[page];
+ }
+ break;
+ case PMBUS_VIRT_READ_TEMP2_MAX:
+ ret = pmbus_read_word_data(client, page,
+ LTC3880_MFR_TEMPERATURE2_PEAK);
+ if (ret >= 0) {
+ if (lin11_to_val(ret)
+ > lin11_to_val(data->temp2_max[page]))
+ data->temp2_max[page] = ret;
+ ret = data->temp2_max[page];
+ }
+ break;
+ case PMBUS_VIRT_READ_VIN_MIN:
+ case PMBUS_VIRT_READ_VOUT_MIN:
+ case PMBUS_VIRT_READ_TEMP_MIN:
+ ret = -ENXIO;
+ break;
+ case PMBUS_VIRT_RESET_IOUT_HISTORY:
+ case PMBUS_VIRT_RESET_TEMP2_HISTORY:
+ ret = 0;
+ break;
+ default:
+ ret = ltc2978_read_word_data_common(client, page, reg);
+ break;
+ }
+ return ret;
+}
+
+static int ltc2978_clear_peaks(struct i2c_client *client, int page,
+ enum chips id)
+{
+ int ret;
+
+ if (id == ltc2978)
+ ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
+ else
+ ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
+
+ return ret;
+}
+
+static int ltc2978_write_word_data(struct i2c_client *client, int page,
+ int reg, u16 word)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct ltc2978_data *data = to_ltc2978_data(info);
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VIRT_RESET_IOUT_HISTORY:
+ data->iout_max[page] = 0x7fff;
+ ret = ltc2978_clear_peaks(client, page, data->id);
+ break;
+ case PMBUS_VIRT_RESET_TEMP2_HISTORY:
+ data->temp2_max[page] = 0x7fff;
+ ret = ltc2978_clear_peaks(client, page, data->id);
+ break;
+ case PMBUS_VIRT_RESET_VOUT_HISTORY:
+ data->vout_min[page] = 0xffff;
+ data->vout_max[page] = 0;
+ ret = ltc2978_clear_peaks(client, page, data->id);
+ break;
+ case PMBUS_VIRT_RESET_VIN_HISTORY:
+ data->vin_min = 0x7bff;
+ data->vin_max = 0;
+ ret = ltc2978_clear_peaks(client, page, data->id);
+ break;
+ case PMBUS_VIRT_RESET_TEMP_HISTORY:
+ data->temp_min = 0x7bff;
+ data->temp_max = 0x7fff;
+ ret = ltc2978_clear_peaks(client, page, data->id);
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+ return ret;
+}
+
+static const struct i2c_device_id ltc2978_id[] = {
+ {"ltc2978", ltc2978},
+ {"ltc3880", ltc3880},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, ltc2978_id);
+
+static int ltc2978_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int chip_id, ret, i;
+ struct ltc2978_data *data;
+ struct pmbus_driver_info *info;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_WORD_DATA))
+ return -ENODEV;
+
+ data = kzalloc(sizeof(struct ltc2978_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
+ if (chip_id < 0) {
+ ret = chip_id;
+ goto err_mem;
+ }
+
+ if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
+ data->id = ltc2978;
+ } else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
+ data->id = ltc3880;
+ } else {
+ dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
+ ret = -ENODEV;
+ goto err_mem;
+ }
+ if (data->id != id->driver_data)
+ dev_warn(&client->dev,
+ "Device mismatch: Configured %s, detected %s\n",
+ id->name,
+ ltc2978_id[data->id].name);
+
+ info = &data->info;
+ info->write_word_data = ltc2978_write_word_data;
+
+ data->vout_min[0] = 0xffff;
+ data->vin_min = 0x7bff;
+ data->temp_min = 0x7bff;
+ data->temp_max = 0x7fff;
+
+ switch (id->driver_data) {
+ case ltc2978:
+ info->read_word_data = ltc2978_read_word_data;
+ info->pages = 8;
+ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ for (i = 1; i < 8; i++) {
+ info->func[i] = PMBUS_HAVE_VOUT
+ | PMBUS_HAVE_STATUS_VOUT;
+ data->vout_min[i] = 0xffff;
+ }
+ break;
+ case ltc3880:
+ info->read_word_data = ltc3880_read_word_data;
+ info->pages = 2;
+ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
+ | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
+ | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
+ info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_POUT
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ data->vout_min[1] = 0xffff;
+ break;
+ default:
+ ret = -ENODEV;
+ goto err_mem;
+ }
+
+ ret = pmbus_do_probe(client, id, info);
+ if (ret)
+ goto err_mem;
+ return 0;
+
+err_mem:
+ kfree(data);
+ return ret;
+}
+
+static int ltc2978_remove(struct i2c_client *client)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ const struct ltc2978_data *data = to_ltc2978_data(info);
+
+ pmbus_do_remove(client);
+ kfree(data);
+ return 0;
+}
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ltc2978_driver = {
+ .driver = {
+ .name = "ltc2978",
+ },
+ .probe = ltc2978_probe,
+ .remove = ltc2978_remove,
+ .id_table = ltc2978_id,
+};
+
+static int __init ltc2978_init(void)
+{
+ return i2c_add_driver(&ltc2978_driver);
+}
+
+static void __exit ltc2978_exit(void)
+{
+ i2c_del_driver(&ltc2978_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for LTC2978 and LTC3880");
+MODULE_LICENSE("GPL");
+module_init(ltc2978_init);
+module_exit(ltc2978_exit);
diff --git a/drivers/hwmon/pmbus/max16064.c b/drivers/hwmon/pmbus/max16064.c
index e50b296e8db4..1d77cf4d2d44 100644
--- a/drivers/hwmon/pmbus/max16064.c
+++ b/drivers/hwmon/pmbus/max16064.c
@@ -105,7 +105,8 @@ static int max16064_probe(struct i2c_client *client,
static int max16064_remove(struct i2c_client *client)
{
- return pmbus_do_remove(client);
+ pmbus_do_remove(client);
+ return 0;
}
static const struct i2c_device_id max16064_id[] = {
diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c
index fda621d2e458..beaf5a8d9c45 100644
--- a/drivers/hwmon/pmbus/max34440.c
+++ b/drivers/hwmon/pmbus/max34440.c
@@ -93,12 +93,14 @@ static int max34440_write_word_data(struct i2c_client *client, int page,
static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
{
- int ret;
+ int ret = 0;
int mfg_status;
- ret = pmbus_set_page(client, page);
- if (ret < 0)
- return ret;
+ if (page >= 0) {
+ ret = pmbus_set_page(client, page);
+ if (ret < 0)
+ return ret;
+ }
switch (reg) {
case PMBUS_STATUS_IOUT:
@@ -224,7 +226,8 @@ static int max34440_probe(struct i2c_client *client,
static int max34440_remove(struct i2c_client *client)
{
- return pmbus_do_remove(client);
+ pmbus_do_remove(client);
+ return 0;
}
static const struct i2c_device_id max34440_id[] = {
diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c
index c3e72f1a3cfb..e2b74bb399ba 100644
--- a/drivers/hwmon/pmbus/max8688.c
+++ b/drivers/hwmon/pmbus/max8688.c
@@ -45,7 +45,7 @@ static int max8688_read_word_data(struct i2c_client *client, int page, int reg)
int ret;
if (page)
- return -EINVAL;
+ return -ENXIO;
switch (reg) {
case PMBUS_VIRT_READ_VOUT_MAX:
@@ -101,8 +101,8 @@ static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
int ret = 0;
int mfg_status;
- if (page)
- return -EINVAL;
+ if (page > 0)
+ return -ENXIO;
switch (reg) {
case PMBUS_STATUS_VOUT:
@@ -182,7 +182,8 @@ static int max8688_probe(struct i2c_client *client,
static int max8688_remove(struct i2c_client *client)
{
- return pmbus_do_remove(client);
+ pmbus_do_remove(client);
+ return 0;
}
static const struct i2c_device_id max8688_id[] = {
diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c
index 73de9f1f3194..995e873197e3 100644
--- a/drivers/hwmon/pmbus/pmbus.c
+++ b/drivers/hwmon/pmbus/pmbus.c
@@ -187,13 +187,12 @@ out:
static int pmbus_remove(struct i2c_client *client)
{
- int ret;
const struct pmbus_driver_info *info;
info = pmbus_get_driver_info(client);
- ret = pmbus_do_remove(client);
+ pmbus_do_remove(client);
kfree(info);
- return ret;
+ return 0;
}
/*
@@ -205,10 +204,13 @@ static const struct i2c_device_id pmbus_id[] = {
{"bmr451", 1},
{"bmr453", 1},
{"bmr454", 1},
- {"ltc2978", 8},
{"ncp4200", 1},
{"ncp4208", 1},
+ {"pdt003", 1},
+ {"pdt006", 1},
+ {"pdt012", 1},
{"pmbus", 0},
+ {"udt020", 1},
{}
};
diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index a6ae20ffef6b..5d31d1c2c0f5 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -134,8 +134,16 @@
* Semantics:
* Virtual registers are all word size.
* READ registers are read-only; writes are either ignored or return an error.
- * RESET registers are read/write. Reading returns zero (used for detection),
- * writing any value causes the associated history to be reset.
+ * RESET registers are read/write. Reading reset registers returns zero
+ * (used for detection), writing any value causes the associated history to be
+ * reset.
+ * Virtual registers have to be handled in device specific driver code. Chip
+ * driver code returns non-negative register values if a virtual register is
+ * supported, or a negative error code if not. The chip driver may return
+ * -ENODATA or any other error code in this case, though an error code other
+ * than -ENODATA is handled more efficiently and thus preferred. Either case,
+ * the calling PMBus core code will abort if the chip driver returns an error
+ * code when reading or writing virtual registers.
*/
#define PMBUS_VIRT_BASE 0x100
#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 0)
@@ -160,6 +168,9 @@
#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 19)
#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 20)
#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 21)
+#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 22)
+#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 23)
+#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 24)
/*
* CAPABILITY
@@ -320,6 +331,12 @@ struct pmbus_driver_info {
* The following functions map manufacturing specific register values
* to PMBus standard register values. Specify only if mapping is
* necessary.
+ * Functions return the register value (read) or zero (write) if
+ * successful. A return value of -ENODATA indicates that there is no
+ * manufacturer specific register, but that a standard PMBus register
+ * may exist. Any other negative return value indicates that the
+ * register does not exist, and that no attempt should be made to read
+ * the standard register.
*/
int (*read_byte_data)(struct i2c_client *client, int page, int reg);
int (*read_word_data)(struct i2c_client *client, int page, int reg);
@@ -347,7 +364,7 @@ bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
struct pmbus_driver_info *info);
-int pmbus_do_remove(struct i2c_client *client);
+void pmbus_do_remove(struct i2c_client *client);
const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
*client);
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 397fc59b5682..00460d8d8423 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -160,7 +160,7 @@ int pmbus_set_page(struct i2c_client *client, u8 page)
rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE);
if (newpage != page)
- rv = -EINVAL;
+ rv = -EIO;
else
data->currpage = page;
}
@@ -229,7 +229,7 @@ static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg,
return status;
}
if (reg >= PMBUS_VIRT_BASE)
- return -EINVAL;
+ return -ENXIO;
return pmbus_write_word_data(client, page, reg, word);
}
@@ -261,7 +261,7 @@ static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg)
return status;
}
if (reg >= PMBUS_VIRT_BASE)
- return -EINVAL;
+ return -ENXIO;
return pmbus_read_word_data(client, page, reg);
}
@@ -316,11 +316,11 @@ static int pmbus_check_status_cml(struct i2c_client *client)
{
int status, status2;
- status = pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
+ status = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
if (status < 0 || (status & PB_STATUS_CML)) {
- status2 = pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
+ status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
- return -EINVAL;
+ return -EIO;
}
return 0;
}
@@ -371,8 +371,8 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
for (i = 0; i < info->pages; i++)
data->status[PB_STATUS_BASE + i]
- = pmbus_read_byte_data(client, i,
- PMBUS_STATUS_BYTE);
+ = _pmbus_read_byte_data(client, i,
+ PMBUS_STATUS_BYTE);
for (i = 0; i < info->pages; i++) {
if (!(info->func[i] & PMBUS_HAVE_STATUS_VOUT))
continue;
@@ -445,13 +445,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
exponent = data->exponent;
mantissa = (u16) sensor->data;
} else { /* LINEAR11 */
- exponent = (sensor->data >> 11) & 0x001f;
- mantissa = sensor->data & 0x07ff;
-
- if (exponent > 0x0f)
- exponent |= 0xffe0; /* sign extend exponent */
- if (mantissa > 0x03ff)
- mantissa |= 0xfffff800; /* sign extend mantissa */
+ exponent = ((s16)sensor->data) >> 11;
+ mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5;
}
val = mantissa;
@@ -1401,7 +1396,42 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = {
}
};
-static const struct pmbus_limit_attr temp_limit_attrs23[] = {
+static const struct pmbus_limit_attr temp_limit_attrs2[] = {
+ {
+ .reg = PMBUS_UT_WARN_LIMIT,
+ .low = true,
+ .attr = "min",
+ .alarm = "min_alarm",
+ .sbit = PB_TEMP_UT_WARNING,
+ }, {
+ .reg = PMBUS_UT_FAULT_LIMIT,
+ .low = true,
+ .attr = "lcrit",
+ .alarm = "lcrit_alarm",
+ .sbit = PB_TEMP_UT_FAULT,
+ }, {
+ .reg = PMBUS_OT_WARN_LIMIT,
+ .attr = "max",
+ .alarm = "max_alarm",
+ .sbit = PB_TEMP_OT_WARNING,
+ }, {
+ .reg = PMBUS_OT_FAULT_LIMIT,
+ .attr = "crit",
+ .alarm = "crit_alarm",
+ .sbit = PB_TEMP_OT_FAULT,
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_MIN,
+ .attr = "lowest",
+ }, {
+ .reg = PMBUS_VIRT_READ_TEMP2_MAX,
+ .attr = "highest",
+ }, {
+ .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY,
+ .attr = "reset_history",
+ }
+};
+
+static const struct pmbus_limit_attr temp_limit_attrs3[] = {
{
.reg = PMBUS_UT_WARN_LIMIT,
.low = true,
@@ -1450,8 +1480,8 @@ static const struct pmbus_sensor_attr temp_attributes[] = {
.sfunc = PMBUS_HAVE_STATUS_TEMP,
.sbase = PB_STATUS_TEMP_BASE,
.gbit = PB_STATUS_TEMPERATURE,
- .limit = temp_limit_attrs23,
- .nlimit = ARRAY_SIZE(temp_limit_attrs23),
+ .limit = temp_limit_attrs2,
+ .nlimit = ARRAY_SIZE(temp_limit_attrs2),
}, {
.reg = PMBUS_READ_TEMPERATURE_3,
.class = PSC_TEMPERATURE,
@@ -1462,8 +1492,8 @@ static const struct pmbus_sensor_attr temp_attributes[] = {
.sfunc = PMBUS_HAVE_STATUS_TEMP,
.sbase = PB_STATUS_TEMP_BASE,
.gbit = PB_STATUS_TEMPERATURE,
- .limit = temp_limit_attrs23,
- .nlimit = ARRAY_SIZE(temp_limit_attrs23),
+ .limit = temp_limit_attrs3,
+ .nlimit = ARRAY_SIZE(temp_limit_attrs3),
}
};
@@ -1593,10 +1623,10 @@ static void pmbus_find_attributes(struct i2c_client *client,
static int pmbus_identify_common(struct i2c_client *client,
struct pmbus_data *data)
{
- int vout_mode = -1, exponent;
+ int vout_mode = -1;
if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE))
- vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
+ vout_mode = _pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
if (vout_mode >= 0 && vout_mode != 0xff) {
/*
* Not all chips support the VOUT_MODE command,
@@ -1607,11 +1637,7 @@ static int pmbus_identify_common(struct i2c_client *client,
if (data->info->format[PSC_VOLTAGE_OUT] != linear)
return -ENODEV;
- exponent = vout_mode & 0x1f;
- /* and sign-extend it */
- if (exponent & 0x10)
- exponent |= ~0x1f;
- data->exponent = exponent;
+ data->exponent = ((s8)(vout_mode << 3)) >> 3;
break;
case 1: /* VID mode */
if (data->info->format[PSC_VOLTAGE_OUT] != vid)
@@ -1682,7 +1708,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
if (info->pages <= 0 || info->pages > PMBUS_PAGES) {
dev_err(&client->dev, "Bad number of PMBus pages: %d\n",
info->pages);
- ret = -EINVAL;
+ ret = -ENODEV;
goto out_data;
}
@@ -1764,7 +1790,7 @@ out_data:
}
EXPORT_SYMBOL_GPL(pmbus_do_probe);
-int pmbus_do_remove(struct i2c_client *client)
+void pmbus_do_remove(struct i2c_client *client)
{
struct pmbus_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
@@ -1774,7 +1800,6 @@ int pmbus_do_remove(struct i2c_client *client)
kfree(data->booleans);
kfree(data->sensors);
kfree(data);
- return 0;
}
EXPORT_SYMBOL_GPL(pmbus_do_remove);
diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c
index d0ddb60155c9..4ff6cf289f85 100644
--- a/drivers/hwmon/pmbus/ucd9000.c
+++ b/drivers/hwmon/pmbus/ucd9000.c
@@ -74,8 +74,8 @@ static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_FAN_CONFIG_12:
- if (page)
- return -EINVAL;
+ if (page > 0)
+ return -ENXIO;
ret = ucd9000_get_fan_config(client, 0);
if (ret < 0)
@@ -88,8 +88,8 @@ static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg)
ret = fan_config;
break;
case PMBUS_FAN_CONFIG_34:
- if (page)
- return -EINVAL;
+ if (page > 0)
+ return -ENXIO;
ret = ucd9000_get_fan_config(client, 2);
if (ret < 0)
@@ -239,13 +239,12 @@ out:
static int ucd9000_remove(struct i2c_client *client)
{
- int ret;
struct ucd9000_data *data;
data = to_ucd9000_data(pmbus_get_driver_info(client));
- ret = pmbus_do_remove(client);
+ pmbus_do_remove(client);
kfree(data);
- return ret;
+ return 0;
}
diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c
index c65e9da707cc..6e1c1a80ab85 100644
--- a/drivers/hwmon/pmbus/ucd9200.c
+++ b/drivers/hwmon/pmbus/ucd9200.c
@@ -171,13 +171,12 @@ out:
static int ucd9200_remove(struct i2c_client *client)
{
- int ret;
const struct pmbus_driver_info *info;
info = pmbus_get_driver_info(client);
- ret = pmbus_do_remove(client);
+ pmbus_do_remove(client);
kfree(info);
- return ret;
+ return 0;
}
diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c
new file mode 100644
index 000000000000..2bc980006f83
--- /dev/null
+++ b/drivers/hwmon/pmbus/zl6100.c
@@ -0,0 +1,256 @@
+/*
+ * Hardware monitoring driver for ZL6100 and compatibles
+ *
+ * Copyright (c) 2011 Ericsson AB.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/ktime.h>
+#include <linux/delay.h>
+#include "pmbus.h"
+
+enum chips { zl2004, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105 };
+
+struct zl6100_data {
+ int id;
+ ktime_t access; /* chip access time */
+ struct pmbus_driver_info info;
+};
+
+#define to_zl6100_data(x) container_of(x, struct zl6100_data, info)
+
+#define ZL6100_DEVICE_ID 0xe4
+
+#define ZL6100_WAIT_TIME 1000 /* uS */
+
+static ushort delay = ZL6100_WAIT_TIME;
+module_param(delay, ushort, 0644);
+MODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
+
+/* Some chips need a delay between accesses */
+static inline void zl6100_wait(const struct zl6100_data *data)
+{
+ if (delay) {
+ s64 delta = ktime_us_delta(ktime_get(), data->access);
+ if (delta < delay)
+ udelay(delay - delta);
+ }
+}
+
+static int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct zl6100_data *data = to_zl6100_data(info);
+ int ret;
+
+ if (page || reg >= PMBUS_VIRT_BASE)
+ return -ENXIO;
+
+ zl6100_wait(data);
+ ret = pmbus_read_word_data(client, page, reg);
+ data->access = ktime_get();
+
+ return ret;
+}
+
+static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct zl6100_data *data = to_zl6100_data(info);
+ int ret;
+
+ if (page > 0)
+ return -ENXIO;
+
+ zl6100_wait(data);
+ ret = pmbus_read_byte_data(client, page, reg);
+ data->access = ktime_get();
+
+ return ret;
+}
+
+static int zl6100_write_word_data(struct i2c_client *client, int page, int reg,
+ u16 word)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct zl6100_data *data = to_zl6100_data(info);
+ int ret;
+
+ if (page || reg >= PMBUS_VIRT_BASE)
+ return -ENXIO;
+
+ zl6100_wait(data);
+ ret = pmbus_write_word_data(client, page, reg, word);
+ data->access = ktime_get();
+
+ return ret;
+}
+
+static int zl6100_write_byte(struct i2c_client *client, int page, u8 value)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct zl6100_data *data = to_zl6100_data(info);
+ int ret;
+
+ if (page > 0)
+ return -ENXIO;
+
+ zl6100_wait(data);
+ ret = pmbus_write_byte(client, page, value);
+ data->access = ktime_get();
+
+ return ret;
+}
+
+static const struct i2c_device_id zl6100_id[] = {
+ {"zl2004", zl2004},
+ {"zl2006", zl2006},
+ {"zl2008", zl2008},
+ {"zl2105", zl2105},
+ {"zl2106", zl2106},
+ {"zl6100", zl6100},
+ {"zl6105", zl6105},
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, zl6100_id);
+
+static int zl6100_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret;
+ struct zl6100_data *data;
+ struct pmbus_driver_info *info;
+ u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
+ const struct i2c_device_id *mid;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_BYTE_DATA
+ | I2C_FUNC_SMBUS_READ_BLOCK_DATA))
+ return -ENODEV;
+
+ ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID,
+ device_id);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to read device ID\n");
+ return ret;
+ }
+ device_id[ret] = '\0';
+ dev_info(&client->dev, "Device ID %s\n", device_id);
+
+ mid = NULL;
+ for (mid = zl6100_id; mid->name[0]; mid++) {
+ if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
+ break;
+ }
+ if (!mid->name[0]) {
+ dev_err(&client->dev, "Unsupported device\n");
+ return -ENODEV;
+ }
+ if (id->driver_data != mid->driver_data)
+ dev_notice(&client->dev,
+ "Device mismatch: Configured %s, detected %s\n",
+ id->name, mid->name);
+
+ data = kzalloc(sizeof(struct zl6100_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->id = mid->driver_data;
+
+ /*
+ * ZL2008, ZL2105, and ZL6100 are known to require a wait time
+ * between I2C accesses. ZL2004 and ZL6105 are known to be safe.
+ *
+ * Only clear the wait time for chips known to be safe. The wait time
+ * can be cleared later for additional chips if tests show that it
+ * is not needed (in other words, better be safe than sorry).
+ */
+ if (data->id == zl2004 || data->id == zl6105)
+ delay = 0;
+
+ /*
+ * Since there was a direct I2C device access above, wait before
+ * accessing the chip again.
+ * Set the timestamp, wait, then set it again. This should provide
+ * enough buffer time to be safe.
+ */
+ data->access = ktime_get();
+ zl6100_wait(data);
+ data->access = ktime_get();
+
+ info = &data->info;
+
+ info->pages = 1;
+ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
+
+ info->read_word_data = zl6100_read_word_data;
+ info->read_byte_data = zl6100_read_byte_data;
+ info->write_word_data = zl6100_write_word_data;
+ info->write_byte = zl6100_write_byte;
+
+ ret = pmbus_do_probe(client, mid, info);
+ if (ret)
+ goto err_mem;
+ return 0;
+
+err_mem:
+ kfree(data);
+ return ret;
+}
+
+static int zl6100_remove(struct i2c_client *client)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ const struct zl6100_data *data = to_zl6100_data(info);
+
+ pmbus_do_remove(client);
+ kfree(data);
+ return 0;
+}
+
+static struct i2c_driver zl6100_driver = {
+ .driver = {
+ .name = "zl6100",
+ },
+ .probe = zl6100_probe,
+ .remove = zl6100_remove,
+ .id_table = zl6100_id,
+};
+
+static int __init zl6100_init(void)
+{
+ return i2c_add_driver(&zl6100_driver);
+}
+
+static void __exit zl6100_exit(void)
+{
+ i2c_del_driver(&zl6100_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
+MODULE_LICENSE("GPL");
+module_init(zl6100_init);
+module_exit(zl6100_exit);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 36d7f270b14d..98aab4bea342 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -197,6 +197,9 @@ static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0, 0x152, 0x252, 0 };
#define W83627EHF_REG_ALARM2 0x45A
#define W83627EHF_REG_ALARM3 0x45B
+#define W83627EHF_REG_CASEOPEN_DET 0x42 /* SMI STATUS #2 */
+#define W83627EHF_REG_CASEOPEN_CLR 0x46 /* SMI MASK #3 */
+
/* SmartFan registers */
#define W83627EHF_REG_FAN_STEPUP_TIME 0x0f
#define W83627EHF_REG_FAN_STEPDOWN_TIME 0x0e
@@ -316,7 +319,7 @@ static const char *const nct6776_temp_label[] = {
#define NUM_REG_TEMP ARRAY_SIZE(NCT6775_REG_TEMP)
-static inline int is_word_sized(u16 reg)
+static int is_word_sized(u16 reg)
{
return ((((reg & 0xff00) == 0x100
|| (reg & 0xff00) == 0x200)
@@ -385,23 +388,6 @@ div_from_reg(u8 reg)
return 1 << reg;
}
-static inline int
-temp_from_reg(u16 reg, s16 regval)
-{
- if (is_word_sized(reg))
- return LM75_TEMP_FROM_REG(regval);
- return ((s8)regval) * 1000;
-}
-
-static inline u16
-temp_to_reg(u16 reg, long temp)
-{
- if (is_word_sized(reg))
- return LM75_TEMP_TO_REG(temp);
- return (s8)DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, -127000, 128000),
- 1000);
-}
-
/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 };
@@ -469,6 +455,7 @@ struct w83627ehf_data {
s16 temp_max[9];
s16 temp_max_hyst[9];
u32 alarms;
+ u8 caseopen;
u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
u8 pwm_enable[4]; /* 1->manual
@@ -557,6 +544,26 @@ static int w83627ehf_write_value(struct w83627ehf_data *data, u16 reg,
return 0;
}
+/* We left-align 8-bit temperature values to make the code simpler */
+static u16 w83627ehf_read_temp(struct w83627ehf_data *data, u16 reg)
+{
+ u16 res;
+
+ res = w83627ehf_read_value(data, reg);
+ if (!is_word_sized(reg))
+ res <<= 8;
+
+ return res;
+}
+
+static int w83627ehf_write_temp(struct w83627ehf_data *data, u16 reg,
+ u16 value)
+{
+ if (!is_word_sized(reg))
+ value >>= 8;
+ return w83627ehf_write_value(data, reg, value);
+}
+
/* This function assumes that the caller holds data->update_lock */
static void nct6775_write_fan_div(struct w83627ehf_data *data, int nr)
{
@@ -771,6 +778,9 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
/* Measured voltages and limits */
for (i = 0; i < data->in_num; i++) {
+ if ((i == 6) && data->in6_skip)
+ continue;
+
data->in[i] = w83627ehf_read_value(data,
W83627EHF_REG_IN(i));
data->in_min[i] = w83627ehf_read_value(data,
@@ -855,15 +865,15 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
for (i = 0; i < NUM_REG_TEMP; i++) {
if (!(data->have_temp & (1 << i)))
continue;
- data->temp[i] = w83627ehf_read_value(data,
+ data->temp[i] = w83627ehf_read_temp(data,
data->reg_temp[i]);
if (data->reg_temp_over[i])
data->temp_max[i]
- = w83627ehf_read_value(data,
+ = w83627ehf_read_temp(data,
data->reg_temp_over[i]);
if (data->reg_temp_hyst[i])
data->temp_max_hyst[i]
- = w83627ehf_read_value(data,
+ = w83627ehf_read_temp(data,
data->reg_temp_hyst[i]);
}
@@ -874,6 +884,9 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
(w83627ehf_read_value(data,
W83627EHF_REG_ALARM3) << 16);
+ data->caseopen = w83627ehf_read_value(data,
+ W83627EHF_REG_CASEOPEN_DET);
+
data->last_updated = jiffies;
data->valid = 1;
}
@@ -1156,8 +1169,7 @@ show_##reg(struct device *dev, struct device_attribute *attr, \
struct sensor_device_attribute *sensor_attr = \
to_sensor_dev_attr(attr); \
int nr = sensor_attr->index; \
- return sprintf(buf, "%d\n", \
- temp_from_reg(data->addr[nr], data->reg[nr])); \
+ return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->reg[nr])); \
}
show_temp_reg(reg_temp, temp);
show_temp_reg(reg_temp_over, temp_max);
@@ -1178,9 +1190,8 @@ store_##reg(struct device *dev, struct device_attribute *attr, \
if (err < 0) \
return err; \
mutex_lock(&data->update_lock); \
- data->reg[nr] = temp_to_reg(data->addr[nr], val); \
- w83627ehf_write_value(data, data->addr[nr], \
- data->reg[nr]); \
+ data->reg[nr] = LM75_TEMP_TO_REG(val); \
+ w83627ehf_write_temp(data, data->addr[nr], data->reg[nr]); \
mutex_unlock(&data->update_lock); \
return count; \
}
@@ -1655,6 +1666,48 @@ show_vid(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+/* Case open detection */
+
+static ssize_t
+show_caseopen(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83627ehf_data *data = w83627ehf_update_device(dev);
+
+ return sprintf(buf, "%d\n",
+ !!(data->caseopen & to_sensor_dev_attr_2(attr)->index));
+}
+
+static ssize_t
+clear_caseopen(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct w83627ehf_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ u16 reg, mask;
+
+ if (strict_strtoul(buf, 10, &val) || val != 0)
+ return -EINVAL;
+
+ mask = to_sensor_dev_attr_2(attr)->nr;
+
+ mutex_lock(&data->update_lock);
+ reg = w83627ehf_read_value(data, W83627EHF_REG_CASEOPEN_CLR);
+ w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg | mask);
+ w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg & ~mask);
+ data->valid = 0; /* Force cache refresh */
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static struct sensor_device_attribute_2 sda_caseopen[] = {
+ SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_caseopen,
+ clear_caseopen, 0x80, 0x10),
+ SENSOR_ATTR_2(intrusion1_alarm, S_IWUSR | S_IRUGO, show_caseopen,
+ clear_caseopen, 0x40, 0x40),
+};
+
/*
* Driver and device management
*/
@@ -1711,6 +1764,9 @@ static void w83627ehf_device_remove_files(struct device *dev)
device_remove_file(dev, &sda_temp_type[i].dev_attr);
}
+ device_remove_file(dev, &sda_caseopen[0].dev_attr);
+ device_remove_file(dev, &sda_caseopen[1].dev_attr);
+
device_remove_file(dev, &dev_attr_name);
device_remove_file(dev, &dev_attr_cpu0_vid);
}
@@ -1789,13 +1845,78 @@ static void w82627ehf_swap_tempreg(struct w83627ehf_data *data,
data->reg_temp_config[r2] = tmp;
}
+static void __devinit
+w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
+ struct w83627ehf_data *data)
+{
+ int fan3pin, fan4pin, fan4min, fan5pin, regval;
+
+ superio_enter(sio_data->sioreg);
+
+ /* fan4 and fan5 share some pins with the GPIO and serial flash */
+ if (sio_data->kind == nct6775) {
+ /* On NCT6775, fan4 shares pins with the fdc interface */
+ fan3pin = 1;
+ fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
+ fan4min = 0;
+ fan5pin = 0;
+ } else if (sio_data->kind == nct6776) {
+ fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+ fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
+ fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+ fan4min = fan4pin;
+ } else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
+ fan3pin = 1;
+ fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40;
+ fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
+ fan4min = fan4pin;
+ } else {
+ fan3pin = 1;
+ fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06);
+ fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
+ fan4min = fan4pin;
+ }
+
+ superio_exit(sio_data->sioreg);
+
+ data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
+ data->has_fan |= (fan3pin << 2);
+ data->has_fan_min |= (fan3pin << 2);
+
+ if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+ /*
+ * NCT6775F and NCT6776F don't have the W83627EHF_REG_FANDIV1
+ * register
+ */
+ data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
+ data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
+ } else {
+ /*
+ * It looks like fan4 and fan5 pins can be alternatively used
+ * as fan on/off switches, but fan5 control is write only :/
+ * We assume that if the serial interface is disabled, designers
+ * connected fan5 as input unless they are emitting log 1, which
+ * is not the default.
+ */
+ regval = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
+ if ((regval & (1 << 2)) && fan4pin) {
+ data->has_fan |= (1 << 3);
+ data->has_fan_min |= (1 << 3);
+ }
+ if (!(regval & (1 << 1)) && fan5pin) {
+ data->has_fan |= (1 << 4);
+ data->has_fan_min |= (1 << 4);
+ }
+ }
+}
+
static int __devinit w83627ehf_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct w83627ehf_sio_data *sio_data = dev->platform_data;
struct w83627ehf_data *data;
struct resource *res;
- u8 fan3pin, fan4pin, fan4min, fan5pin, en_vrm10;
+ u8 en_vrm10;
int i, err = 0;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -2080,30 +2201,6 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
}
}
- /* fan4 and fan5 share some pins with the GPIO and serial flash */
- if (sio_data->kind == nct6775) {
- /* On NCT6775, fan4 shares pins with the fdc interface */
- fan3pin = 1;
- fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
- fan4min = 0;
- fan5pin = 0;
- } else if (sio_data->kind == nct6776) {
- fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
- fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
- fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
- fan4min = fan4pin;
- } else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
- fan3pin = 1;
- fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40;
- fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
- fan4min = fan4pin;
- } else {
- fan3pin = 1;
- fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06);
- fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
- fan4min = fan4pin;
- }
-
if (fan_debounce &&
(sio_data->kind == nct6775 || sio_data->kind == nct6776)) {
u8 tmp;
@@ -2121,34 +2218,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
superio_exit(sio_data->sioreg);
- /* It looks like fan4 and fan5 pins can be alternatively used
- as fan on/off switches, but fan5 control is write only :/
- We assume that if the serial interface is disabled, designers
- connected fan5 as input unless they are emitting log 1, which
- is not the default. */
-
- data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
-
- data->has_fan |= (fan3pin << 2);
- data->has_fan_min |= (fan3pin << 2);
-
- /*
- * NCT6775F and NCT6776F don't have the W83627EHF_REG_FANDIV1 register
- */
- if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
- data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
- data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
- } else {
- i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
- if ((i & (1 << 2)) && fan4pin) {
- data->has_fan |= (1 << 3);
- data->has_fan_min |= (1 << 3);
- }
- if (!(i & (1 << 1)) && fan5pin) {
- data->has_fan |= (1 << 4);
- data->has_fan_min |= (1 << 4);
- }
- }
+ w83627ehf_check_fan_inputs(sio_data, data);
/* Read fan clock dividers immediately */
w83627ehf_update_fan_div_common(dev, data);
@@ -2269,6 +2339,16 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
goto exit_remove;
}
+ err = device_create_file(dev, &sda_caseopen[0].dev_attr);
+ if (err)
+ goto exit_remove;
+
+ if (sio_data->kind == nct6776) {
+ err = device_create_file(dev, &sda_caseopen[1].dev_attr);
+ if (err)
+ goto exit_remove;
+ }
+
err = device_create_file(dev, &dev_attr_name);
if (err)
goto exit_remove;
diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
index 1f29bab6b3e5..c7c3128393d1 100644
--- a/drivers/hwspinlock/Kconfig
+++ b/drivers/hwspinlock/Kconfig
@@ -2,22 +2,31 @@
# Generic HWSPINLOCK framework
#
+# HWSPINLOCK always gets selected by whoever wants it.
config HWSPINLOCK
- tristate "Generic Hardware Spinlock framework"
- depends on ARCH_OMAP4
- help
- Say y here to support the generic hardware spinlock framework.
- You only need to enable this if you have hardware spinlock module
- on your system (usually only relevant if your system has remote slave
- coprocessors).
+ tristate
- If unsure, say N.
+menu "Hardware Spinlock drivers"
config HWSPINLOCK_OMAP
tristate "OMAP Hardware Spinlock device"
- depends on HWSPINLOCK && ARCH_OMAP4
+ depends on ARCH_OMAP4
+ select HWSPINLOCK
help
Say y here to support the OMAP Hardware Spinlock device (firstly
introduced in OMAP4).
If unsure, say N.
+
+config HSEM_U8500
+ tristate "STE Hardware Semaphore functionality"
+ depends on ARCH_U8500
+ select HWSPINLOCK
+ help
+ Say y here to support the STE Hardware Semaphore functionality, which
+ provides a synchronisation mechanism for the various processor on the
+ SoC.
+
+ If unsure, say N.
+
+endmenu
diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile
index 5729a3f7ed3d..93eb64b66486 100644
--- a/drivers/hwspinlock/Makefile
+++ b/drivers/hwspinlock/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_HWSPINLOCK) += hwspinlock_core.o
obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o
+obj-$(CONFIG_HSEM_U8500) += u8500_hsem.o
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
index 43a62714b4fb..61c9cf15fa52 100644
--- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -26,6 +26,7 @@
#include <linux/radix-tree.h>
#include <linux/hwspinlock.h>
#include <linux/pm_runtime.h>
+#include <linux/mutex.h>
#include "hwspinlock_internal.h"
@@ -52,10 +53,12 @@
static RADIX_TREE(hwspinlock_tree, GFP_KERNEL);
/*
- * Synchronization of access to the tree is achieved using this spinlock,
+ * Synchronization of access to the tree is achieved using this mutex,
* as the radix-tree API requires that users provide all synchronisation.
+ * A mutex is needed because we're using non-atomic radix tree allocations.
*/
-static DEFINE_SPINLOCK(hwspinlock_tree_lock);
+static DEFINE_MUTEX(hwspinlock_tree_lock);
+
/**
* __hwspin_trylock() - attempt to lock a specific hwspinlock
@@ -114,7 +117,7 @@ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
return -EBUSY;
/* try to take the hwspinlock device */
- ret = hwlock->ops->trylock(hwlock);
+ ret = hwlock->bank->ops->trylock(hwlock);
/* if hwlock is already taken, undo spin_trylock_* and exit */
if (!ret) {
@@ -196,8 +199,8 @@ int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to,
* Allow platform-specific relax handlers to prevent
* hogging the interconnect (no sleeping, though)
*/
- if (hwlock->ops->relax)
- hwlock->ops->relax(hwlock);
+ if (hwlock->bank->ops->relax)
+ hwlock->bank->ops->relax(hwlock);
}
return ret;
@@ -242,7 +245,7 @@ void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
*/
mb();
- hwlock->ops->unlock(hwlock);
+ hwlock->bank->ops->unlock(hwlock);
/* Undo the spin_trylock{_irq, _irqsave} called while locking */
if (mode == HWLOCK_IRQSTATE)
@@ -254,68 +257,37 @@ void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
}
EXPORT_SYMBOL_GPL(__hwspin_unlock);
-/**
- * hwspin_lock_register() - register a new hw spinlock
- * @hwlock: hwspinlock to register.
- *
- * This function should be called from the underlying platform-specific
- * implementation, to register a new hwspinlock instance.
- *
- * Can be called from an atomic context (will not sleep) but not from
- * within interrupt context.
- *
- * Returns 0 on success, or an appropriate error code on failure
- */
-int hwspin_lock_register(struct hwspinlock *hwlock)
+static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id)
{
struct hwspinlock *tmp;
int ret;
- if (!hwlock || !hwlock->ops ||
- !hwlock->ops->trylock || !hwlock->ops->unlock) {
- pr_err("invalid parameters\n");
- return -EINVAL;
- }
-
- spin_lock_init(&hwlock->lock);
-
- spin_lock(&hwspinlock_tree_lock);
+ mutex_lock(&hwspinlock_tree_lock);
- ret = radix_tree_insert(&hwspinlock_tree, hwlock->id, hwlock);
- if (ret)
+ ret = radix_tree_insert(&hwspinlock_tree, id, hwlock);
+ if (ret) {
+ if (ret == -EEXIST)
+ pr_err("hwspinlock id %d already exists!\n", id);
goto out;
+ }
/* mark this hwspinlock as available */
- tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock->id,
- HWSPINLOCK_UNUSED);
+ tmp = radix_tree_tag_set(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
/* self-sanity check which should never fail */
WARN_ON(tmp != hwlock);
out:
- spin_unlock(&hwspinlock_tree_lock);
- return ret;
+ mutex_unlock(&hwspinlock_tree_lock);
+ return 0;
}
-EXPORT_SYMBOL_GPL(hwspin_lock_register);
-/**
- * hwspin_lock_unregister() - unregister an hw spinlock
- * @id: index of the specific hwspinlock to unregister
- *
- * This function should be called from the underlying platform-specific
- * implementation, to unregister an existing (and unused) hwspinlock.
- *
- * Can be called from an atomic context (will not sleep) but not from
- * within interrupt context.
- *
- * Returns the address of hwspinlock @id on success, or NULL on failure
- */
-struct hwspinlock *hwspin_lock_unregister(unsigned int id)
+static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id)
{
struct hwspinlock *hwlock = NULL;
int ret;
- spin_lock(&hwspinlock_tree_lock);
+ mutex_lock(&hwspinlock_tree_lock);
/* make sure the hwspinlock is not in use (tag is set) */
ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
@@ -331,9 +303,91 @@ struct hwspinlock *hwspin_lock_unregister(unsigned int id)
}
out:
- spin_unlock(&hwspinlock_tree_lock);
+ mutex_unlock(&hwspinlock_tree_lock);
return hwlock;
}
+
+/**
+ * hwspin_lock_register() - register a new hw spinlock device
+ * @bank: the hwspinlock device, which usually provides numerous hw locks
+ * @dev: the backing device
+ * @ops: hwspinlock handlers for this device
+ * @base_id: id of the first hardware spinlock in this bank
+ * @num_locks: number of hwspinlocks provided by this device
+ *
+ * This function should be called from the underlying platform-specific
+ * implementation, to register a new hwspinlock device instance.
+ *
+ * Should be called from a process context (might sleep)
+ *
+ * Returns 0 on success, or an appropriate error code on failure
+ */
+int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
+ const struct hwspinlock_ops *ops, int base_id, int num_locks)
+{
+ struct hwspinlock *hwlock;
+ int ret = 0, i;
+
+ if (!bank || !ops || !dev || !num_locks || !ops->trylock ||
+ !ops->unlock) {
+ pr_err("invalid parameters\n");
+ return -EINVAL;
+ }
+
+ bank->dev = dev;
+ bank->ops = ops;
+ bank->base_id = base_id;
+ bank->num_locks = num_locks;
+
+ for (i = 0; i < num_locks; i++) {
+ hwlock = &bank->lock[i];
+
+ spin_lock_init(&hwlock->lock);
+ hwlock->bank = bank;
+
+ ret = hwspin_lock_register_single(hwlock, i);
+ if (ret)
+ goto reg_failed;
+ }
+
+ return 0;
+
+reg_failed:
+ while (--i >= 0)
+ hwspin_lock_unregister_single(i);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_register);
+
+/**
+ * hwspin_lock_unregister() - unregister an hw spinlock device
+ * @bank: the hwspinlock device, which usually provides numerous hw locks
+ *
+ * This function should be called from the underlying platform-specific
+ * implementation, to unregister an existing (and unused) hwspinlock.
+ *
+ * Should be called from a process context (might sleep)
+ *
+ * Returns 0 on success, or an appropriate error code on failure
+ */
+int hwspin_lock_unregister(struct hwspinlock_device *bank)
+{
+ struct hwspinlock *hwlock, *tmp;
+ int i;
+
+ for (i = 0; i < bank->num_locks; i++) {
+ hwlock = &bank->lock[i];
+
+ tmp = hwspin_lock_unregister_single(bank->base_id + i);
+ if (!tmp)
+ return -EBUSY;
+
+ /* self-sanity check that should never fail */
+ WARN_ON(tmp != hwlock);
+ }
+
+ return 0;
+}
EXPORT_SYMBOL_GPL(hwspin_lock_unregister);
/**
@@ -348,24 +402,25 @@ EXPORT_SYMBOL_GPL(hwspin_lock_unregister);
*/
static int __hwspin_lock_request(struct hwspinlock *hwlock)
{
+ struct device *dev = hwlock->bank->dev;
struct hwspinlock *tmp;
int ret;
/* prevent underlying implementation from being removed */
- if (!try_module_get(hwlock->owner)) {
- dev_err(hwlock->dev, "%s: can't get owner\n", __func__);
+ if (!try_module_get(dev->driver->owner)) {
+ dev_err(dev, "%s: can't get owner\n", __func__);
return -EINVAL;
}
/* notify PM core that power is now needed */
- ret = pm_runtime_get_sync(hwlock->dev);
+ ret = pm_runtime_get_sync(dev);
if (ret < 0) {
- dev_err(hwlock->dev, "%s: can't power on device\n", __func__);
+ dev_err(dev, "%s: can't power on device\n", __func__);
return ret;
}
/* mark hwspinlock as used, should not fail */
- tmp = radix_tree_tag_clear(&hwspinlock_tree, hwlock->id,
+ tmp = radix_tree_tag_clear(&hwspinlock_tree, hwlock_to_id(hwlock),
HWSPINLOCK_UNUSED);
/* self-sanity check that should never fail */
@@ -387,7 +442,7 @@ int hwspin_lock_get_id(struct hwspinlock *hwlock)
return -EINVAL;
}
- return hwlock->id;
+ return hwlock_to_id(hwlock);
}
EXPORT_SYMBOL_GPL(hwspin_lock_get_id);
@@ -400,9 +455,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_get_id);
* to the remote core before it can be used for synchronization (to get the
* id of a given hwlock, use hwspin_lock_get_id()).
*
- * Can be called from an atomic context (will not sleep) but not from
- * within interrupt context (simply because there is no use case for
- * that yet).
+ * Should be called from a process context (might sleep)
*
* Returns the address of the assigned hwspinlock, or NULL on error
*/
@@ -411,7 +464,7 @@ struct hwspinlock *hwspin_lock_request(void)
struct hwspinlock *hwlock;
int ret;
- spin_lock(&hwspinlock_tree_lock);
+ mutex_lock(&hwspinlock_tree_lock);
/* look for an unused lock */
ret = radix_tree_gang_lookup_tag(&hwspinlock_tree, (void **)&hwlock,
@@ -431,7 +484,7 @@ struct hwspinlock *hwspin_lock_request(void)
hwlock = NULL;
out:
- spin_unlock(&hwspinlock_tree_lock);
+ mutex_unlock(&hwspinlock_tree_lock);
return hwlock;
}
EXPORT_SYMBOL_GPL(hwspin_lock_request);
@@ -445,9 +498,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request);
* Usually early board code will be calling this function in order to
* reserve specific hwspinlock ids for predefined purposes.
*
- * Can be called from an atomic context (will not sleep) but not from
- * within interrupt context (simply because there is no use case for
- * that yet).
+ * Should be called from a process context (might sleep)
*
* Returns the address of the assigned hwspinlock, or NULL on error
*/
@@ -456,7 +507,7 @@ struct hwspinlock *hwspin_lock_request_specific(unsigned int id)
struct hwspinlock *hwlock;
int ret;
- spin_lock(&hwspinlock_tree_lock);
+ mutex_lock(&hwspinlock_tree_lock);
/* make sure this hwspinlock exists */
hwlock = radix_tree_lookup(&hwspinlock_tree, id);
@@ -466,7 +517,7 @@ struct hwspinlock *hwspin_lock_request_specific(unsigned int id)
}
/* sanity check (this shouldn't happen) */
- WARN_ON(hwlock->id != id);
+ WARN_ON(hwlock_to_id(hwlock) != id);
/* make sure this hwspinlock is unused */
ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
@@ -482,7 +533,7 @@ struct hwspinlock *hwspin_lock_request_specific(unsigned int id)
hwlock = NULL;
out:
- spin_unlock(&hwspinlock_tree_lock);
+ mutex_unlock(&hwspinlock_tree_lock);
return hwlock;
}
EXPORT_SYMBOL_GPL(hwspin_lock_request_specific);
@@ -495,14 +546,13 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request_specific);
* Should only be called with an @hwlock that was retrieved from
* an earlier call to omap_hwspin_lock_request{_specific}.
*
- * Can be called from an atomic context (will not sleep) but not from
- * within interrupt context (simply because there is no use case for
- * that yet).
+ * Should be called from a process context (might sleep)
*
* Returns 0 on success, or an appropriate error code on failure
*/
int hwspin_lock_free(struct hwspinlock *hwlock)
{
+ struct device *dev = hwlock->bank->dev;
struct hwspinlock *tmp;
int ret;
@@ -511,34 +561,34 @@ int hwspin_lock_free(struct hwspinlock *hwlock)
return -EINVAL;
}
- spin_lock(&hwspinlock_tree_lock);
+ mutex_lock(&hwspinlock_tree_lock);
/* make sure the hwspinlock is used */
- ret = radix_tree_tag_get(&hwspinlock_tree, hwlock->id,
+ ret = radix_tree_tag_get(&hwspinlock_tree, hwlock_to_id(hwlock),
HWSPINLOCK_UNUSED);
if (ret == 1) {
- dev_err(hwlock->dev, "%s: hwlock is already free\n", __func__);
+ dev_err(dev, "%s: hwlock is already free\n", __func__);
dump_stack();
ret = -EINVAL;
goto out;
}
/* notify the underlying device that power is not needed */
- ret = pm_runtime_put(hwlock->dev);
+ ret = pm_runtime_put(dev);
if (ret < 0)
goto out;
/* mark this hwspinlock as available */
- tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock->id,
+ tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock_to_id(hwlock),
HWSPINLOCK_UNUSED);
/* sanity check (this shouldn't happen) */
WARN_ON(tmp != hwlock);
- module_put(hwlock->owner);
+ module_put(dev->driver->owner);
out:
- spin_unlock(&hwspinlock_tree_lock);
+ mutex_unlock(&hwspinlock_tree_lock);
return ret;
}
EXPORT_SYMBOL_GPL(hwspin_lock_free);
diff --git a/drivers/hwspinlock/hwspinlock_internal.h b/drivers/hwspinlock/hwspinlock_internal.h
index 69935e6b93e5..d26f78b8f214 100644
--- a/drivers/hwspinlock/hwspinlock_internal.h
+++ b/drivers/hwspinlock/hwspinlock_internal.h
@@ -21,6 +21,8 @@
#include <linux/spinlock.h>
#include <linux/device.h>
+struct hwspinlock_device;
+
/**
* struct hwspinlock_ops - platform-specific hwspinlock handlers
*
@@ -39,23 +41,37 @@ struct hwspinlock_ops {
/**
* struct hwspinlock - this struct represents a single hwspinlock instance
- *
- * @dev: underlying device, will be used to invoke runtime PM api
- * @ops: platform-specific hwspinlock handlers
- * @id: a global, unique, system-wide, index of the lock.
+ * @bank: the hwspinlock_device structure which owns this lock
* @lock: initialized and used by hwspinlock core
- * @owner: underlying implementation module, used to maintain module ref count
- *
- * Note: currently simplicity was opted for, but later we can squeeze some
- * memory bytes by grouping the dev, ops and owner members in a single
- * per-platform struct, and have all hwspinlocks point at it.
+ * @priv: private data, owned by the underlying platform-specific hwspinlock drv
*/
struct hwspinlock {
+ struct hwspinlock_device *bank;
+ spinlock_t lock;
+ void *priv;
+};
+
+/**
+ * struct hwspinlock_device - a device which usually spans numerous hwspinlocks
+ * @dev: underlying device, will be used to invoke runtime PM api
+ * @ops: platform-specific hwspinlock handlers
+ * @base_id: id index of the first lock in this device
+ * @num_locks: number of locks in this device
+ * @lock: dynamically allocated array of 'struct hwspinlock'
+ */
+struct hwspinlock_device {
struct device *dev;
const struct hwspinlock_ops *ops;
- int id;
- spinlock_t lock;
- struct module *owner;
+ int base_id;
+ int num_locks;
+ struct hwspinlock lock[0];
};
+static inline int hwlock_to_id(struct hwspinlock *hwlock)
+{
+ int local_id = hwlock - &hwlock->bank->lock[0];
+
+ return hwlock->bank->base_id + local_id;
+}
+
#endif /* __HWSPINLOCK_HWSPINLOCK_H */
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index a8f02734c026..887d34effb3a 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -41,33 +41,20 @@
#define SPINLOCK_NOTTAKEN (0) /* free */
#define SPINLOCK_TAKEN (1) /* locked */
-#define to_omap_hwspinlock(lock) \
- container_of(lock, struct omap_hwspinlock, lock)
-
-struct omap_hwspinlock {
- struct hwspinlock lock;
- void __iomem *addr;
-};
-
-struct omap_hwspinlock_state {
- int num_locks; /* Total number of locks in system */
- void __iomem *io_base; /* Mapped base address */
-};
-
static int omap_hwspinlock_trylock(struct hwspinlock *lock)
{
- struct omap_hwspinlock *omap_lock = to_omap_hwspinlock(lock);
+ void __iomem *lock_addr = lock->priv;
/* attempt to acquire the lock by reading its value */
- return (SPINLOCK_NOTTAKEN == readl(omap_lock->addr));
+ return (SPINLOCK_NOTTAKEN == readl(lock_addr));
}
static void omap_hwspinlock_unlock(struct hwspinlock *lock)
{
- struct omap_hwspinlock *omap_lock = to_omap_hwspinlock(lock);
+ void __iomem *lock_addr = lock->priv;
/* release the lock by writing 0 to it */
- writel(SPINLOCK_NOTTAKEN, omap_lock->addr);
+ writel(SPINLOCK_NOTTAKEN, lock_addr);
}
/*
@@ -93,26 +80,23 @@ static const struct hwspinlock_ops omap_hwspinlock_ops = {
static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
{
- struct omap_hwspinlock *omap_lock;
- struct omap_hwspinlock_state *state;
- struct hwspinlock *lock;
+ struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
+ struct hwspinlock_device *bank;
+ struct hwspinlock *hwlock;
struct resource *res;
void __iomem *io_base;
- int i, ret;
+ int num_locks, i, ret;
+
+ if (!pdata)
+ return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
- state = kzalloc(sizeof(*state), GFP_KERNEL);
- if (!state)
- return -ENOMEM;
-
io_base = ioremap(res->start, resource_size(res));
- if (!io_base) {
- ret = -ENOMEM;
- goto free_state;
- }
+ if (!io_base)
+ return -ENOMEM;
/* Determine number of locks */
i = readl(io_base + SYSSTATUS_OFFSET);
@@ -124,10 +108,18 @@ static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
goto iounmap_base;
}
- state->num_locks = i * 32;
- state->io_base = io_base;
+ num_locks = i * 32; /* actual number of locks in this device */
+
+ bank = kzalloc(sizeof(*bank) + num_locks * sizeof(*hwlock), GFP_KERNEL);
+ if (!bank) {
+ ret = -ENOMEM;
+ goto iounmap_base;
+ }
+
+ platform_set_drvdata(pdev, bank);
- platform_set_drvdata(pdev, state);
+ for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
+ hwlock->priv = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
/*
* runtime PM will make sure the clock of this module is
@@ -135,79 +127,46 @@ static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
*/
pm_runtime_enable(&pdev->dev);
- for (i = 0; i < state->num_locks; i++) {
- omap_lock = kzalloc(sizeof(*omap_lock), GFP_KERNEL);
- if (!omap_lock) {
- ret = -ENOMEM;
- goto free_locks;
- }
-
- omap_lock->lock.dev = &pdev->dev;
- omap_lock->lock.owner = THIS_MODULE;
- omap_lock->lock.id = i;
- omap_lock->lock.ops = &omap_hwspinlock_ops;
- omap_lock->addr = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
-
- ret = hwspin_lock_register(&omap_lock->lock);
- if (ret) {
- kfree(omap_lock);
- goto free_locks;
- }
- }
+ ret = hwspin_lock_register(bank, &pdev->dev, &omap_hwspinlock_ops,
+ pdata->base_id, num_locks);
+ if (ret)
+ goto reg_fail;
return 0;
-free_locks:
- while (--i >= 0) {
- lock = hwspin_lock_unregister(i);
- /* this should't happen, but let's give our best effort */
- if (!lock) {
- dev_err(&pdev->dev, "%s: cleanups failed\n", __func__);
- continue;
- }
- omap_lock = to_omap_hwspinlock(lock);
- kfree(omap_lock);
- }
+reg_fail:
pm_runtime_disable(&pdev->dev);
+ kfree(bank);
iounmap_base:
iounmap(io_base);
-free_state:
- kfree(state);
return ret;
}
-static int omap_hwspinlock_remove(struct platform_device *pdev)
+static int __devexit omap_hwspinlock_remove(struct platform_device *pdev)
{
- struct omap_hwspinlock_state *state = platform_get_drvdata(pdev);
- struct hwspinlock *lock;
- struct omap_hwspinlock *omap_lock;
- int i;
-
- for (i = 0; i < state->num_locks; i++) {
- lock = hwspin_lock_unregister(i);
- /* this shouldn't happen at this point. if it does, at least
- * don't continue with the remove */
- if (!lock) {
- dev_err(&pdev->dev, "%s: failed on %d\n", __func__, i);
- return -EBUSY;
- }
-
- omap_lock = to_omap_hwspinlock(lock);
- kfree(omap_lock);
+ struct hwspinlock_device *bank = platform_get_drvdata(pdev);
+ void __iomem *io_base = bank->lock[0].priv - LOCK_BASE_OFFSET;
+ int ret;
+
+ ret = hwspin_lock_unregister(bank);
+ if (ret) {
+ dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
+ return ret;
}
pm_runtime_disable(&pdev->dev);
- iounmap(state->io_base);
- kfree(state);
+ iounmap(io_base);
+ kfree(bank);
return 0;
}
static struct platform_driver omap_hwspinlock_driver = {
.probe = omap_hwspinlock_probe,
- .remove = omap_hwspinlock_remove,
+ .remove = __devexit_p(omap_hwspinlock_remove),
.driver = {
.name = "omap_hwspinlock",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c
new file mode 100644
index 000000000000..143461a95ae4
--- /dev/null
+++ b/drivers/hwspinlock/u8500_hsem.c
@@ -0,0 +1,198 @@
+/*
+ * u8500 HWSEM driver
+ *
+ * Copyright (C) 2010-2011 ST-Ericsson
+ *
+ * Implements u8500 semaphore handling for protocol 1, no interrupts.
+ *
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ * Heavily borrowed from the work of :
+ * Simon Que <sque@ti.com>
+ * Hari Kanigeri <h-kanigeri2@ti.com>
+ * Ohad Ben-Cohen <ohad@wizery.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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/hwspinlock.h>
+#include <linux/platform_device.h>
+
+#include "hwspinlock_internal.h"
+
+/*
+ * Implementation of STE's HSem protocol 1 without interrutps.
+ * The only masterID we allow is '0x01' to force people to use
+ * HSems for synchronisation between processors rather than processes
+ * on the ARM core.
+ */
+
+#define U8500_MAX_SEMAPHORE 32 /* a total of 32 semaphore */
+#define RESET_SEMAPHORE (0) /* free */
+
+/*
+ * CPU ID for master running u8500 kernel.
+ * Hswpinlocks should only be used to synchonise operations
+ * between the Cortex A9 core and the other CPUs. Hence
+ * forcing the masterID to a preset value.
+ */
+#define HSEM_MASTER_ID 0x01
+
+#define HSEM_REGISTER_OFFSET 0x08
+
+#define HSEM_CTRL_REG 0x00
+#define HSEM_ICRALL 0x90
+#define HSEM_PROTOCOL_1 0x01
+
+static int u8500_hsem_trylock(struct hwspinlock *lock)
+{
+ void __iomem *lock_addr = lock->priv;
+
+ writel(HSEM_MASTER_ID, lock_addr);
+
+ /* get only first 4 bit and compare to masterID.
+ * if equal, we have the semaphore, otherwise
+ * someone else has it.
+ */
+ return (HSEM_MASTER_ID == (0x0F & readl(lock_addr)));
+}
+
+static void u8500_hsem_unlock(struct hwspinlock *lock)
+{
+ void __iomem *lock_addr = lock->priv;
+
+ /* release the lock by writing 0 to it */
+ writel(RESET_SEMAPHORE, lock_addr);
+}
+
+/*
+ * u8500: what value is recommended here ?
+ */
+static void u8500_hsem_relax(struct hwspinlock *lock)
+{
+ ndelay(50);
+}
+
+static const struct hwspinlock_ops u8500_hwspinlock_ops = {
+ .trylock = u8500_hsem_trylock,
+ .unlock = u8500_hsem_unlock,
+ .relax = u8500_hsem_relax,
+};
+
+static int __devinit u8500_hsem_probe(struct platform_device *pdev)
+{
+ struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
+ struct hwspinlock_device *bank;
+ struct hwspinlock *hwlock;
+ struct resource *res;
+ void __iomem *io_base;
+ int i, ret, num_locks = U8500_MAX_SEMAPHORE;
+ ulong val;
+
+ if (!pdata)
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ io_base = ioremap(res->start, resource_size(res));
+ if (!io_base) {
+ ret = -ENOMEM;
+ goto free_state;
+ }
+
+ /* make sure protocol 1 is selected */
+ val = readl(io_base + HSEM_CTRL_REG);
+ writel((val & ~HSEM_PROTOCOL_1), io_base + HSEM_CTRL_REG);
+
+ /* clear all interrupts */
+ writel(0xFFFF, io_base + HSEM_ICRALL);
+
+ bank = kzalloc(sizeof(*bank) + num_locks * sizeof(*hwlock), GFP_KERNEL);
+ if (!bank) {
+ ret = -ENOMEM;
+ goto iounmap_base;
+ }
+
+ platform_set_drvdata(pdev, bank);
+
+ for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
+ hwlock->priv = io_base + HSEM_REGISTER_OFFSET + sizeof(u32) * i;
+
+ /* no pm needed for HSem but required to comply with hwspilock core */
+ pm_runtime_enable(&pdev->dev);
+
+ ret = hwspin_lock_register(bank, &pdev->dev, &u8500_hwspinlock_ops,
+ pdata->base_id, num_locks);
+ if (ret)
+ goto reg_fail;
+
+ return 0;
+
+reg_fail:
+ pm_runtime_disable(&pdev->dev);
+ kfree(bank);
+iounmap_base:
+ iounmap(io_base);
+ return ret;
+}
+
+static int __devexit u8500_hsem_remove(struct platform_device *pdev)
+{
+ struct hwspinlock_device *bank = platform_get_drvdata(pdev);
+ void __iomem *io_base = bank->lock[0].priv - HSEM_REGISTER_OFFSET;
+ int ret;
+
+ /* clear all interrupts */
+ writel(0xFFFF, io_base + HSEM_ICRALL);
+
+ ret = hwspin_lock_unregister(bank);
+ if (ret) {
+ dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
+ return ret;
+ }
+
+ pm_runtime_disable(&pdev->dev);
+ iounmap(io_base);
+ kfree(bank);
+
+ return 0;
+}
+
+static struct platform_driver u8500_hsem_driver = {
+ .probe = u8500_hsem_probe,
+ .remove = __devexit_p(u8500_hsem_remove),
+ .driver = {
+ .name = "u8500_hsem",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init u8500_hsem_init(void)
+{
+ return platform_driver_register(&u8500_hsem_driver);
+}
+/* board init code might need to reserve hwspinlocks for predefined purposes */
+postcore_initcall(u8500_hsem_init);
+
+static void __exit u8500_hsem_exit(void)
+{
+ platform_driver_unregister(&u8500_hsem_driver);
+}
+module_exit(u8500_hsem_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Hardware Spinlock driver for u8500");
+MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index d6d58684712b..85584a547c25 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -47,8 +47,8 @@
/* ----- global variables --------------------------------------------- */
static int bit_test; /* see if the line-setting functions work */
-module_param(bit_test, bool, 0);
-MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
+module_param(bit_test, int, S_IRUGO);
+MODULE_PARM_DESC(bit_test, "lines testing - 0 off; 1 report; 2 fail if stuck");
#ifdef DEBUG
static int i2c_debug = 1;
@@ -250,7 +250,9 @@ static int test_bus(struct i2c_adapter *i2c_adap)
sda = getsda(adap);
scl = (adap->getscl == NULL) ? 1 : getscl(adap);
if (!scl || !sda) {
- printk(KERN_WARNING "%s: bus seems to be busy\n", name);
+ printk(KERN_WARNING
+ "%s: bus seems to be busy (scl=%d, sda=%d)\n",
+ name, scl, sda);
goto bailout;
}
@@ -441,7 +443,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
acknak(i2c_adap, 0);
dev_err(&i2c_adap->dev, "readbytes: invalid "
"block length (%d)\n", inval);
- return -EREMOTEIO;
+ return -EPROTO;
}
/* The original count value accounts for the extra
bytes, that is, either 1 for a regular transaction,
@@ -470,7 +472,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
* reads, writes as well as 10bit-addresses.
* returns:
* 0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set
- * -x an error occurred (like: -EREMOTEIO if the device did not answer, or
+ * -x an error occurred (like: -ENXIO if the device did not answer, or
* -ETIMEDOUT, for example if the lines are stuck...)
*/
static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
@@ -493,14 +495,14 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
if ((ret != 1) && !nak_ok) {
dev_err(&i2c_adap->dev,
"died at extended address code\n");
- return -EREMOTEIO;
+ return -ENXIO;
}
/* the remaining 8 bit address */
ret = i2c_outb(i2c_adap, msg->addr & 0x7f);
if ((ret != 1) && !nak_ok) {
/* the chip did not ack / xmission error occurred */
dev_err(&i2c_adap->dev, "died at 2nd address code\n");
- return -EREMOTEIO;
+ return -ENXIO;
}
if (flags & I2C_M_RD) {
bit_dbg(3, &i2c_adap->dev, "emitting repeated "
@@ -512,7 +514,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
if ((ret != 1) && !nak_ok) {
dev_err(&i2c_adap->dev,
"died at repeated address code\n");
- return -EREMOTEIO;
+ return -EIO;
}
}
} else { /* normal 7bit address */
@@ -570,7 +572,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
ret, ret == 1 ? "" : "s");
if (ret < pmsg->len) {
if (ret >= 0)
- ret = -EREMOTEIO;
+ ret = -EIO;
goto bailout;
}
} else {
@@ -581,7 +583,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
ret, ret == 1 ? "" : "s");
if (ret < pmsg->len) {
if (ret >= 0)
- ret = -EREMOTEIO;
+ ret = -EIO;
goto bailout;
}
}
@@ -624,7 +626,7 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap,
if (bit_test) {
ret = test_bus(adap);
- if (ret < 0)
+ if (bit_test >= 2 && ret < 0)
return -ENODEV;
}
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index 4ca9cf9cde73..beb9ffe2564b 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -196,7 +196,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
} else {
dev_dbg(&i2c_adap->dev, "bus is not idle. status is "
"%#04x\n", state);
- return -EAGAIN;
+ return -EBUSY;
}
}
@@ -224,7 +224,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
}
curmsg = 0;
- ret = -EREMOTEIO;
+ ret = -EIO;
while (curmsg < num) {
state = pca_status(adap);
@@ -259,6 +259,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */
DEB2("NOT ACK received after SLA+W\n");
pca_stop(adap);
+ ret = -ENXIO;
goto out;
case 0x40: /* SLA+R has been transmitted; ACK has been received */
@@ -283,6 +284,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */
DEB2("NOT ACK received after SLA+R\n");
pca_stop(adap);
+ ret = -ENXIO;
goto out;
case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d625a484fa85..76f65314a385 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -349,15 +349,25 @@ config I2C_DAVINCI
devices such as DaVinci NIC.
For details please see http://www.ti.com/davinci
-config I2C_DESIGNWARE
- tristate "Synopsys DesignWare"
+config I2C_DESIGNWARE_PLATFORM
+ tristate "Synopsys DesignWare Platfrom"
depends on HAVE_CLK
help
If you say yes to this option, support will be included for the
Synopsys DesignWare I2C adapter. Only master mode is supported.
This driver can also be built as a module. If so, the module
- will be called i2c-designware.
+ will be called i2c-designware-platform.
+
+config I2C_DESIGNWARE_PCI
+ tristate "Synopsys DesignWare PCI"
+ depends on PCI
+ help
+ If you say yes to this option, support will be included for the
+ Synopsys DesignWare I2C adapter. Only master mode is supported.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-designware-pci.
config I2C_GPIO
tristate "GPIO-based bitbanging I2C"
@@ -788,7 +798,7 @@ config I2C_ACORN
config I2C_ELEKTOR
tristate "Elektor ISA card"
- depends on ISA && BROKEN_ON_SMP
+ depends on ISA && HAS_IOPORT && BROKEN_ON_SMP
select I2C_ALGOPCF
help
This supports the PCF8584 ISA bus I2C adapter. Say Y if you own
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index e6cf294d3729..fba6da60aa0e 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -33,7 +33,10 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
-obj-$(CONFIG_I2C_DESIGNWARE) += i2c-designware.o
+obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o
+i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
+obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o
+i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index 532828bc50e6..4f757a2da8cc 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -39,29 +39,41 @@
#include <asm/mach-au1x00/au1xxx.h>
#include <asm/mach-au1x00/au1xxx_psc.h>
+#define PSC_SEL 0x00
+#define PSC_CTRL 0x04
+#define PSC_SMBCFG 0x08
+#define PSC_SMBMSK 0x0C
+#define PSC_SMBPCR 0x10
+#define PSC_SMBSTAT 0x14
+#define PSC_SMBEVNT 0x18
+#define PSC_SMBTXRX 0x1C
+#define PSC_SMBTMR 0x20
+
struct i2c_au1550_data {
- u32 psc_base;
+ void __iomem *psc_base;
int xfer_timeout;
- int ack_timeout;
struct i2c_adapter adap;
struct resource *ioarea;
};
-static int
-wait_xfer_done(struct i2c_au1550_data *adap)
+static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
{
- u32 stat;
- int i;
- volatile psc_smb_t *sp;
+ __raw_writel(v, a->psc_base + r);
+ wmb();
+}
- sp = (volatile psc_smb_t *)(adap->psc_base);
+static inline unsigned long RD(struct i2c_au1550_data *a, int r)
+{
+ return __raw_readl(a->psc_base + r);
+}
- /* Wait for Tx Buffer Empty
- */
+static int wait_xfer_done(struct i2c_au1550_data *adap)
+{
+ int i;
+
+ /* Wait for Tx Buffer Empty */
for (i = 0; i < adap->xfer_timeout; i++) {
- stat = sp->psc_smbstat;
- au_sync();
- if ((stat & PSC_SMBSTAT_TE) != 0)
+ if (RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_TE)
return 0;
udelay(1);
@@ -70,41 +82,27 @@ wait_xfer_done(struct i2c_au1550_data *adap)
return -ETIMEDOUT;
}
-static int
-wait_ack(struct i2c_au1550_data *adap)
+static int wait_ack(struct i2c_au1550_data *adap)
{
- u32 stat;
- volatile psc_smb_t *sp;
+ unsigned long stat;
if (wait_xfer_done(adap))
return -ETIMEDOUT;
- sp = (volatile psc_smb_t *)(adap->psc_base);
-
- stat = sp->psc_smbevnt;
- au_sync();
-
+ stat = RD(adap, PSC_SMBEVNT);
if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0)
return -ETIMEDOUT;
return 0;
}
-static int
-wait_master_done(struct i2c_au1550_data *adap)
+static int wait_master_done(struct i2c_au1550_data *adap)
{
- u32 stat;
- int i;
- volatile psc_smb_t *sp;
+ int i;
- sp = (volatile psc_smb_t *)(adap->psc_base);
-
- /* Wait for Master Done.
- */
- for (i = 0; i < adap->xfer_timeout; i++) {
- stat = sp->psc_smbevnt;
- au_sync();
- if ((stat & PSC_SMBEVNT_MD) != 0)
+ /* Wait for Master Done. */
+ for (i = 0; i < 2 * adap->xfer_timeout; i++) {
+ if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0)
return 0;
udelay(1);
}
@@ -115,29 +113,20 @@ wait_master_done(struct i2c_au1550_data *adap)
static int
do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
{
- volatile psc_smb_t *sp;
- u32 stat;
+ unsigned long stat;
- sp = (volatile psc_smb_t *)(adap->psc_base);
-
- /* Reset the FIFOs, clear events.
- */
- stat = sp->psc_smbstat;
- sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR;
- au_sync();
+ /* Reset the FIFOs, clear events. */
+ stat = RD(adap, PSC_SMBSTAT);
+ WR(adap, PSC_SMBEVNT, PSC_SMBEVNT_ALLCLR);
if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
- sp->psc_smbpcr = PSC_SMBPCR_DC;
- au_sync();
- do {
- stat = sp->psc_smbpcr;
- au_sync();
- } while ((stat & PSC_SMBPCR_DC) != 0);
+ WR(adap, PSC_SMBPCR, PSC_SMBPCR_DC);
+ while ((RD(adap, PSC_SMBPCR) & PSC_SMBPCR_DC) != 0)
+ cpu_relax();
udelay(50);
}
- /* Write out the i2c chip address and specify operation
- */
+ /* Write out the i2c chip address and specify operation */
addr <<= 1;
if (rd)
addr |= 1;
@@ -146,56 +135,42 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
if (q)
addr |= PSC_SMBTXRX_STP;
- /* Put byte into fifo, start up master.
- */
- sp->psc_smbtxrx = addr;
- au_sync();
- sp->psc_smbpcr = PSC_SMBPCR_MS;
- au_sync();
+ /* Put byte into fifo, start up master. */
+ WR(adap, PSC_SMBTXRX, addr);
+ WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS);
if (wait_ack(adap))
return -EIO;
return (q) ? wait_master_done(adap) : 0;
}
-static u32
-wait_for_rx_byte(struct i2c_au1550_data *adap, u32 *ret_data)
+static int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out)
{
- int j;
- u32 data, stat;
- volatile psc_smb_t *sp;
+ int j;
if (wait_xfer_done(adap))
return -EIO;
- sp = (volatile psc_smb_t *)(adap->psc_base);
-
j = adap->xfer_timeout * 100;
do {
j--;
if (j <= 0)
return -EIO;
- stat = sp->psc_smbstat;
- au_sync();
- if ((stat & PSC_SMBSTAT_RE) == 0)
+ if ((RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_RE) == 0)
j = 0;
else
udelay(1);
} while (j > 0);
- data = sp->psc_smbtxrx;
- au_sync();
- *ret_data = data;
+
+ *out = RD(adap, PSC_SMBTXRX);
return 0;
}
-static int
-i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
+static int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
unsigned int len)
{
- int i;
- u32 data;
- volatile psc_smb_t *sp;
+ int i;
if (len == 0)
return 0;
@@ -204,62 +179,46 @@ i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
* zero bytes for timing, waiting for bytes to appear in the
* receive fifo, then reading the bytes.
*/
-
- sp = (volatile psc_smb_t *)(adap->psc_base);
-
i = 0;
- while (i < (len-1)) {
- sp->psc_smbtxrx = 0;
- au_sync();
- if (wait_for_rx_byte(adap, &data))
+ while (i < (len - 1)) {
+ WR(adap, PSC_SMBTXRX, 0);
+ if (wait_for_rx_byte(adap, &buf[i]))
return -EIO;
- buf[i] = data;
i++;
}
- /* The last byte has to indicate transfer done.
- */
- sp->psc_smbtxrx = PSC_SMBTXRX_STP;
- au_sync();
+ /* The last byte has to indicate transfer done. */
+ WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP);
if (wait_master_done(adap))
return -EIO;
- data = sp->psc_smbtxrx;
- au_sync();
- buf[i] = data;
+ buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff);
return 0;
}
-static int
-i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
+static int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
unsigned int len)
{
- int i;
- u32 data;
- volatile psc_smb_t *sp;
+ int i;
+ unsigned long data;
if (len == 0)
return 0;
- sp = (volatile psc_smb_t *)(adap->psc_base);
-
i = 0;
while (i < (len-1)) {
data = buf[i];
- sp->psc_smbtxrx = data;
- au_sync();
+ WR(adap, PSC_SMBTXRX, data);
if (wait_ack(adap))
return -EIO;
i++;
}
- /* The last byte has to indicate transfer done.
- */
+ /* The last byte has to indicate transfer done. */
data = buf[i];
data |= PSC_SMBTXRX_STP;
- sp->psc_smbtxrx = data;
- au_sync();
+ WR(adap, PSC_SMBTXRX, data);
if (wait_master_done(adap))
return -EIO;
return 0;
@@ -269,12 +228,10 @@ static int
au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{
struct i2c_au1550_data *adap = i2c_adap->algo_data;
- volatile psc_smb_t *sp = (volatile psc_smb_t *)adap->psc_base;
struct i2c_msg *p;
int i, err = 0;
- sp->psc_ctrl = PSC_CTRL_ENABLE;
- au_sync();
+ WR(adap, PSC_CTRL, PSC_CTRL_ENABLE);
for (i = 0; !err && i < num; i++) {
p = &msgs[i];
@@ -293,14 +250,12 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
if (err == 0)
err = num;
- sp->psc_ctrl = PSC_CTRL_SUSPEND;
- au_sync();
+ WR(adap, PSC_CTRL, PSC_CTRL_SUSPEND);
return err;
}
-static u32
-au1550_func(struct i2c_adapter *adap)
+static u32 au1550_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
@@ -312,57 +267,45 @@ static const struct i2c_algorithm au1550_algo = {
static void i2c_au1550_setup(struct i2c_au1550_data *priv)
{
- volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
- u32 stat;
-
- sp->psc_ctrl = PSC_CTRL_DISABLE;
- au_sync();
- sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
- sp->psc_smbcfg = 0;
- au_sync();
- sp->psc_ctrl = PSC_CTRL_ENABLE;
- au_sync();
- do {
- stat = sp->psc_smbstat;
- au_sync();
- } while ((stat & PSC_SMBSTAT_SR) == 0);
+ unsigned long cfg;
- sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 |
- PSC_SMBCFG_DD_DISABLE);
+ WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
+ WR(priv, PSC_SEL, PSC_SEL_PS_SMBUSMODE);
+ WR(priv, PSC_SMBCFG, 0);
+ WR(priv, PSC_CTRL, PSC_CTRL_ENABLE);
+ while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
+ cpu_relax();
+
+ cfg = PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | PSC_SMBCFG_DD_DISABLE;
+ WR(priv, PSC_SMBCFG, cfg);
/* Divide by 8 to get a 6.25 MHz clock. The later protocol
* timings are based on this clock.
*/
- sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
- sp->psc_smbmsk = PSC_SMBMSK_ALLMASK;
- au_sync();
+ cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
+ WR(priv, PSC_SMBCFG, cfg);
+ WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK);
/* Set the protocol timer values. See Table 71 in the
* Au1550 Data Book for standard timing values.
*/
- sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
+ WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
- PSC_SMBTMR_SET_CH(15);
- au_sync();
+ PSC_SMBTMR_SET_CH(15));
- sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE;
- do {
- stat = sp->psc_smbstat;
- au_sync();
- } while ((stat & PSC_SMBSTAT_SR) == 0);
+ cfg |= PSC_SMBCFG_DE_ENABLE;
+ WR(priv, PSC_SMBCFG, cfg);
+ while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
+ cpu_relax();
- sp->psc_ctrl = PSC_CTRL_SUSPEND;
- au_sync();
+ WR(priv, PSC_CTRL, PSC_CTRL_SUSPEND);
}
static void i2c_au1550_disable(struct i2c_au1550_data *priv)
{
- volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
-
- sp->psc_smbcfg = 0;
- sp->psc_ctrl = PSC_CTRL_DISABLE;
- au_sync();
+ WR(priv, PSC_SMBCFG, 0);
+ WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
}
/*
@@ -396,9 +339,12 @@ i2c_au1550_probe(struct platform_device *pdev)
goto out_mem;
}
- priv->psc_base = CKSEG1ADDR(r->start);
+ priv->psc_base = ioremap(r->start, resource_size(r));
+ if (!priv->psc_base) {
+ ret = -EIO;
+ goto out_map;
+ }
priv->xfer_timeout = 200;
- priv->ack_timeout = 200;
priv->adap.nr = pdev->id;
priv->adap.algo = &au1550_algo;
@@ -406,8 +352,7 @@ i2c_au1550_probe(struct platform_device *pdev)
priv->adap.dev.parent = &pdev->dev;
strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
- /* Now, set up the PSC for SMBus PIO mode.
- */
+ /* Now, set up the PSC for SMBus PIO mode. */
i2c_au1550_setup(priv);
ret = i2c_add_numbered_adapter(&priv->adap);
@@ -417,7 +362,8 @@ i2c_au1550_probe(struct platform_device *pdev)
}
i2c_au1550_disable(priv);
-
+ iounmap(priv->psc_base);
+out_map:
release_resource(priv->ioarea);
kfree(priv->ioarea);
out_mem:
@@ -426,14 +372,14 @@ out:
return ret;
}
-static int __devexit
-i2c_au1550_remove(struct platform_device *pdev)
+static int __devexit i2c_au1550_remove(struct platform_device *pdev)
{
struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
i2c_del_adapter(&priv->adap);
i2c_au1550_disable(priv);
+ iounmap(priv->psc_base);
release_resource(priv->ioarea);
kfree(priv->ioarea);
kfree(priv);
@@ -441,49 +387,51 @@ i2c_au1550_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
-static int
-i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
+static int i2c_au1550_suspend(struct device *dev)
{
- struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+ struct i2c_au1550_data *priv = dev_get_drvdata(dev);
i2c_au1550_disable(priv);
return 0;
}
-static int
-i2c_au1550_resume(struct platform_device *pdev)
+static int i2c_au1550_resume(struct device *dev)
{
- struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+ struct i2c_au1550_data *priv = dev_get_drvdata(dev);
i2c_au1550_setup(priv);
return 0;
}
+
+static const struct dev_pm_ops i2c_au1550_pmops = {
+ .suspend = i2c_au1550_suspend,
+ .resume = i2c_au1550_resume,
+};
+
+#define AU1XPSC_SMBUS_PMOPS (&i2c_au1550_pmops)
+
#else
-#define i2c_au1550_suspend NULL
-#define i2c_au1550_resume NULL
+#define AU1XPSC_SMBUS_PMOPS NULL
#endif
static struct platform_driver au1xpsc_smbus_driver = {
.driver = {
.name = "au1xpsc_smbus",
.owner = THIS_MODULE,
+ .pm = AU1XPSC_SMBUS_PMOPS,
},
.probe = i2c_au1550_probe,
.remove = __devexit_p(i2c_au1550_remove),
- .suspend = i2c_au1550_suspend,
- .resume = i2c_au1550_resume,
};
-static int __init
-i2c_au1550_init(void)
+static int __init i2c_au1550_init(void)
{
return platform_driver_register(&au1xpsc_smbus_driver);
}
-static void __exit
-i2c_au1550_exit(void)
+static void __exit i2c_au1550_exit(void)
{
platform_driver_unregister(&au1xpsc_smbus_driver);
}
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index cbc98aea5b09..cdb59e5b23f7 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -631,7 +631,7 @@ static int i2c_bfin_twi_resume(struct platform_device *pdev)
struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
int rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
- IRQF_DISABLED, pdev->name, iface);
+ 0, pdev->name, iface);
if (rc) {
dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
return -ENODEV;
@@ -702,7 +702,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
}
rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
- IRQF_DISABLED, pdev->name, iface);
+ 0, pdev->name, iface);
if (rc) {
dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
rc = -ENODEV;
diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware-core.c
index b7a51c43b185..df8799241009 100644
--- a/drivers/i2c/busses/i2c-designware.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -25,18 +25,15 @@
* ----------------------------------------------------------------------------
*
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
#include <linux/clk.h>
#include <linux/errno.h>
-#include <linux/sched.h>
#include <linux/err.h>
+#include <linux/i2c.h>
#include <linux/interrupt.h>
-#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include "i2c-designware-core.h"
/*
* Registers offset
@@ -68,15 +65,10 @@
#define DW_IC_STATUS 0x70
#define DW_IC_TXFLR 0x74
#define DW_IC_RXFLR 0x78
-#define DW_IC_COMP_PARAM_1 0xf4
#define DW_IC_TX_ABRT_SOURCE 0x80
-
-#define DW_IC_CON_MASTER 0x1
-#define DW_IC_CON_SPEED_STD 0x2
-#define DW_IC_CON_SPEED_FAST 0x4
-#define DW_IC_CON_10BITADDR_MASTER 0x10
-#define DW_IC_CON_RESTART_EN 0x20
-#define DW_IC_CON_SLAVE_DISABLE 0x40
+#define DW_IC_COMP_PARAM_1 0xf4
+#define DW_IC_COMP_TYPE 0xfc
+#define DW_IC_COMP_TYPE_VALUE 0x44570140
#define DW_IC_INTR_RX_UNDER 0x001
#define DW_IC_INTR_RX_OVER 0x002
@@ -170,55 +162,23 @@ static char *abort_sources[] = {
"lost arbitration",
};
-/**
- * struct dw_i2c_dev - private i2c-designware data
- * @dev: driver model device node
- * @base: IO registers pointer
- * @cmd_complete: tx completion indicator
- * @lock: protect this struct and IO registers
- * @clk: input reference clock
- * @cmd_err: run time hadware error code
- * @msgs: points to an array of messages currently being transferred
- * @msgs_num: the number of elements in msgs
- * @msg_write_idx: the element index of the current tx message in the msgs
- * array
- * @tx_buf_len: the length of the current tx buffer
- * @tx_buf: the current tx buffer
- * @msg_read_idx: the element index of the current rx message in the msgs
- * array
- * @rx_buf_len: the length of the current rx buffer
- * @rx_buf: the current rx buffer
- * @msg_err: error status of the current transfer
- * @status: i2c master status, one of STATUS_*
- * @abort_source: copy of the TX_ABRT_SOURCE register
- * @irq: interrupt number for the i2c master
- * @adapter: i2c subsystem adapter node
- * @tx_fifo_depth: depth of the hardware tx fifo
- * @rx_fifo_depth: depth of the hardware rx fifo
- */
-struct dw_i2c_dev {
- struct device *dev;
- void __iomem *base;
- struct completion cmd_complete;
- struct mutex lock;
- struct clk *clk;
- int cmd_err;
- struct i2c_msg *msgs;
- int msgs_num;
- int msg_write_idx;
- u32 tx_buf_len;
- u8 *tx_buf;
- int msg_read_idx;
- u32 rx_buf_len;
- u8 *rx_buf;
- int msg_err;
- unsigned int status;
- u32 abort_source;
- int irq;
- struct i2c_adapter adapter;
- unsigned int tx_fifo_depth;
- unsigned int rx_fifo_depth;
-};
+u32 dw_readl(struct dw_i2c_dev *dev, int offset)
+{
+ u32 value = readl(dev->base + offset);
+
+ if (dev->swab)
+ return swab32(value);
+ else
+ return value;
+}
+
+void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
+{
+ if (dev->swab)
+ b = swab32(b);
+
+ writel(b, dev->base + offset);
+}
static u32
i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
@@ -283,13 +243,29 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
* This function is called during I2C init function, and in case of timeout at
* run time.
*/
-static void i2c_dw_init(struct dw_i2c_dev *dev)
+int i2c_dw_init(struct dw_i2c_dev *dev)
{
- u32 input_clock_khz = clk_get_rate(dev->clk) / 1000;
- u32 ic_con, hcnt, lcnt;
+ u32 input_clock_khz;
+ u32 hcnt, lcnt;
+ u32 reg;
+
+ input_clock_khz = dev->get_clk_rate_khz(dev);
+
+ /* Configure register endianess access */
+ reg = dw_readl(dev, DW_IC_COMP_TYPE);
+ if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
+ dev->swab = 1;
+ reg = DW_IC_COMP_TYPE_VALUE;
+ }
+
+ if (reg != DW_IC_COMP_TYPE_VALUE) {
+ dev_err(dev->dev, "Unknown Synopsys component type: "
+ "0x%08x\n", reg);
+ return -ENODEV;
+ }
/* Disable the adapter */
- writel(0, dev->base + DW_IC_ENABLE);
+ dw_writel(dev, 0, DW_IC_ENABLE);
/* set standard and fast speed deviders for high/low periods */
@@ -303,8 +279,8 @@ static void i2c_dw_init(struct dw_i2c_dev *dev)
47, /* tLOW = 4.7 us */
3, /* tf = 0.3 us */
0); /* No offset */
- writel(hcnt, dev->base + DW_IC_SS_SCL_HCNT);
- writel(lcnt, dev->base + DW_IC_SS_SCL_LCNT);
+ dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
+ dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
/* Fast-mode */
@@ -317,18 +293,17 @@ static void i2c_dw_init(struct dw_i2c_dev *dev)
13, /* tLOW = 1.3 us */
3, /* tf = 0.3 us */
0); /* No offset */
- writel(hcnt, dev->base + DW_IC_FS_SCL_HCNT);
- writel(lcnt, dev->base + DW_IC_FS_SCL_LCNT);
+ dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
+ dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
/* Configure Tx/Rx FIFO threshold levels */
- writel(dev->tx_fifo_depth - 1, dev->base + DW_IC_TX_TL);
- writel(0, dev->base + DW_IC_RX_TL);
+ dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
+ dw_writel(dev, 0, DW_IC_RX_TL);
/* configure the i2c master */
- ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
- DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
- writel(ic_con, dev->base + DW_IC_CON);
+ dw_writel(dev, dev->master_cfg , DW_IC_CON);
+ return 0;
}
/*
@@ -338,7 +313,7 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
{
int timeout = TIMEOUT;
- while (readl(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
+ while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
if (timeout <= 0) {
dev_warn(dev->dev, "timeout waiting for bus ready\n");
return -ETIMEDOUT;
@@ -356,24 +331,24 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
u32 ic_con;
/* Disable the adapter */
- writel(0, dev->base + DW_IC_ENABLE);
+ dw_writel(dev, 0, DW_IC_ENABLE);
/* set the slave (target) address */
- writel(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR);
+ dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR);
/* if the slave address is ten bit address, enable 10BITADDR */
- ic_con = readl(dev->base + DW_IC_CON);
+ ic_con = dw_readl(dev, DW_IC_CON);
if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
ic_con |= DW_IC_CON_10BITADDR_MASTER;
else
ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
- writel(ic_con, dev->base + DW_IC_CON);
+ dw_writel(dev, ic_con, DW_IC_CON);
/* Enable the adapter */
- writel(1, dev->base + DW_IC_ENABLE);
+ dw_writel(dev, 1, DW_IC_ENABLE);
/* Enable interrupts */
- writel(DW_IC_INTR_DEFAULT_MASK, dev->base + DW_IC_INTR_MASK);
+ dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
}
/*
@@ -382,7 +357,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
* messages into the tx buffer. Even if the size of i2c_msg data is
* longer than the size of the tx buffer, it handles everything.
*/
-static void
+void
i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
{
struct i2c_msg *msgs = dev->msgs;
@@ -390,7 +365,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
int tx_limit, rx_limit;
u32 addr = msgs[dev->msg_write_idx].addr;
u32 buf_len = dev->tx_buf_len;
- u8 *buf = dev->tx_buf;;
+ u8 *buf = dev->tx_buf;
intr_mask = DW_IC_INTR_DEFAULT_MASK;
@@ -420,15 +395,15 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
buf_len = msgs[dev->msg_write_idx].len;
}
- tx_limit = dev->tx_fifo_depth - readl(dev->base + DW_IC_TXFLR);
- rx_limit = dev->rx_fifo_depth - readl(dev->base + DW_IC_RXFLR);
+ tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
+ rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
- writel(0x100, dev->base + DW_IC_DATA_CMD);
+ dw_writel(dev, 0x100, DW_IC_DATA_CMD);
rx_limit--;
} else
- writel(*buf++, dev->base + DW_IC_DATA_CMD);
+ dw_writel(dev, *buf++, DW_IC_DATA_CMD);
tx_limit--; buf_len--;
}
@@ -453,7 +428,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
if (dev->msg_err)
intr_mask = 0;
- writel(intr_mask, dev->base + DW_IC_INTR_MASK);
+ dw_writel(dev, intr_mask, DW_IC_INTR_MASK);
}
static void
@@ -477,10 +452,10 @@ i2c_dw_read(struct dw_i2c_dev *dev)
buf = dev->rx_buf;
}
- rx_valid = readl(dev->base + DW_IC_RXFLR);
+ rx_valid = dw_readl(dev, DW_IC_RXFLR);
for (; len > 0 && rx_valid > 0; len--, rx_valid--)
- *buf++ = readl(dev->base + DW_IC_DATA_CMD);
+ *buf++ = dw_readl(dev, DW_IC_DATA_CMD);
if (len > 0) {
dev->status |= STATUS_READ_IN_PROGRESS;
@@ -518,7 +493,7 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
/*
* Prepare controller for a transaction and call i2c_dw_xfer_msg
*/
-static int
+int
i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
@@ -527,6 +502,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
mutex_lock(&dev->lock);
+ pm_runtime_get_sync(dev->dev);
INIT_COMPLETION(dev->cmd_complete);
dev->msgs = msgs;
@@ -563,7 +539,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
/* no error */
if (likely(!dev->cmd_err)) {
/* Disable the adapter */
- writel(0, dev->base + DW_IC_ENABLE);
+ dw_writel(dev, 0, DW_IC_ENABLE);
ret = num;
goto done;
}
@@ -576,19 +552,16 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
ret = -EIO;
done:
+ pm_runtime_put(dev->dev);
mutex_unlock(&dev->lock);
return ret;
}
-static u32 i2c_dw_func(struct i2c_adapter *adap)
+u32 i2c_dw_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C |
- I2C_FUNC_10BIT_ADDR |
- I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA |
- I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_I2C_BLOCK;
+ struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+ return dev->functionality;
}
static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
@@ -601,47 +574,47 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
* in the IC_RAW_INTR_STAT register.
*
* That is,
- * stat = readl(IC_INTR_STAT);
+ * stat = dw_readl(IC_INTR_STAT);
* equals to,
- * stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
+ * stat = dw_readl(IC_RAW_INTR_STAT) & dw_readl(IC_INTR_MASK);
*
* The raw version might be useful for debugging purposes.
*/
- stat = readl(dev->base + DW_IC_INTR_STAT);
+ stat = dw_readl(dev, DW_IC_INTR_STAT);
/*
* Do not use the IC_CLR_INTR register to clear interrupts, or
* you'll miss some interrupts, triggered during the period from
- * readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
+ * dw_readl(IC_INTR_STAT) to dw_readl(IC_CLR_INTR).
*
* Instead, use the separately-prepared IC_CLR_* registers.
*/
if (stat & DW_IC_INTR_RX_UNDER)
- readl(dev->base + DW_IC_CLR_RX_UNDER);
+ dw_readl(dev, DW_IC_CLR_RX_UNDER);
if (stat & DW_IC_INTR_RX_OVER)
- readl(dev->base + DW_IC_CLR_RX_OVER);
+ dw_readl(dev, DW_IC_CLR_RX_OVER);
if (stat & DW_IC_INTR_TX_OVER)
- readl(dev->base + DW_IC_CLR_TX_OVER);
+ dw_readl(dev, DW_IC_CLR_TX_OVER);
if (stat & DW_IC_INTR_RD_REQ)
- readl(dev->base + DW_IC_CLR_RD_REQ);
+ dw_readl(dev, DW_IC_CLR_RD_REQ);
if (stat & DW_IC_INTR_TX_ABRT) {
/*
* The IC_TX_ABRT_SOURCE register is cleared whenever
* the IC_CLR_TX_ABRT is read. Preserve it beforehand.
*/
- dev->abort_source = readl(dev->base + DW_IC_TX_ABRT_SOURCE);
- readl(dev->base + DW_IC_CLR_TX_ABRT);
+ dev->abort_source = dw_readl(dev, DW_IC_TX_ABRT_SOURCE);
+ dw_readl(dev, DW_IC_CLR_TX_ABRT);
}
if (stat & DW_IC_INTR_RX_DONE)
- readl(dev->base + DW_IC_CLR_RX_DONE);
+ dw_readl(dev, DW_IC_CLR_RX_DONE);
if (stat & DW_IC_INTR_ACTIVITY)
- readl(dev->base + DW_IC_CLR_ACTIVITY);
+ dw_readl(dev, DW_IC_CLR_ACTIVITY);
if (stat & DW_IC_INTR_STOP_DET)
- readl(dev->base + DW_IC_CLR_STOP_DET);
+ dw_readl(dev, DW_IC_CLR_STOP_DET);
if (stat & DW_IC_INTR_START_DET)
- readl(dev->base + DW_IC_CLR_START_DET);
+ dw_readl(dev, DW_IC_CLR_START_DET);
if (stat & DW_IC_INTR_GEN_CALL)
- readl(dev->base + DW_IC_CLR_GEN_CALL);
+ dw_readl(dev, DW_IC_CLR_GEN_CALL);
return stat;
}
@@ -650,13 +623,19 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
* Interrupt service routine. This gets called whenever an I2C interrupt
* occurs.
*/
-static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
{
struct dw_i2c_dev *dev = dev_id;
- u32 stat;
+ u32 stat, enabled;
+
+ enabled = dw_readl(dev, DW_IC_ENABLE);
+ stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
+ dev_dbg(dev->dev, "%s: %s enabled= 0x%x stat=0x%x\n", __func__,
+ dev->adapter.name, enabled, stat);
+ if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
+ return IRQ_NONE;
stat = i2c_dw_read_clear_intrbits(dev);
- dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
if (stat & DW_IC_INTR_TX_ABRT) {
dev->cmd_err |= DW_IC_ERR_TX_ABRT;
@@ -666,7 +645,7 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
* Anytime TX_ABRT is set, the contents of the tx/rx
* buffers are flushed. Make sure to skip them.
*/
- writel(0, dev->base + DW_IC_INTR_MASK);
+ dw_writel(dev, 0, DW_IC_INTR_MASK);
goto tx_aborted;
}
@@ -689,159 +668,38 @@ tx_aborted:
return IRQ_HANDLED;
}
-static struct i2c_algorithm i2c_dw_algo = {
- .master_xfer = i2c_dw_xfer,
- .functionality = i2c_dw_func,
-};
-
-static int __devinit dw_i2c_probe(struct platform_device *pdev)
+void i2c_dw_enable(struct dw_i2c_dev *dev)
{
- struct dw_i2c_dev *dev;
- struct i2c_adapter *adap;
- struct resource *mem, *ioarea;
- int irq, r;
-
- /* NOTE: driver uses the static register mapping */
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "no mem resource?\n");
- return -EINVAL;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "no irq resource?\n");
- return irq; /* -ENXIO */
- }
-
- ioarea = request_mem_region(mem->start, resource_size(mem),
- pdev->name);
- if (!ioarea) {
- dev_err(&pdev->dev, "I2C region already claimed\n");
- return -EBUSY;
- }
-
- dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
- if (!dev) {
- r = -ENOMEM;
- goto err_release_region;
- }
-
- init_completion(&dev->cmd_complete);
- mutex_init(&dev->lock);
- dev->dev = get_device(&pdev->dev);
- dev->irq = irq;
- platform_set_drvdata(pdev, dev);
-
- dev->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(dev->clk)) {
- r = -ENODEV;
- goto err_free_mem;
- }
- clk_enable(dev->clk);
-
- dev->base = ioremap(mem->start, resource_size(mem));
- if (dev->base == NULL) {
- dev_err(&pdev->dev, "failure mapping io resources\n");
- r = -EBUSY;
- goto err_unuse_clocks;
- }
- {
- u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1);
-
- dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
- dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1;
- }
- i2c_dw_init(dev);
-
- writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
- r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
- if (r) {
- dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
- goto err_iounmap;
- }
-
- adap = &dev->adapter;
- i2c_set_adapdata(adap, dev);
- adap->owner = THIS_MODULE;
- adap->class = I2C_CLASS_HWMON;
- strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
- sizeof(adap->name));
- adap->algo = &i2c_dw_algo;
- adap->dev.parent = &pdev->dev;
-
- adap->nr = pdev->id;
- r = i2c_add_numbered_adapter(adap);
- if (r) {
- dev_err(&pdev->dev, "failure adding adapter\n");
- goto err_free_irq;
- }
-
- return 0;
-
-err_free_irq:
- free_irq(dev->irq, dev);
-err_iounmap:
- iounmap(dev->base);
-err_unuse_clocks:
- clk_disable(dev->clk);
- clk_put(dev->clk);
- dev->clk = NULL;
-err_free_mem:
- platform_set_drvdata(pdev, NULL);
- put_device(&pdev->dev);
- kfree(dev);
-err_release_region:
- release_mem_region(mem->start, resource_size(mem));
-
- return r;
+ /* Enable the adapter */
+ dw_writel(dev, 1, DW_IC_ENABLE);
}
-static int __devexit dw_i2c_remove(struct platform_device *pdev)
+u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
{
- struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
- struct resource *mem;
-
- platform_set_drvdata(pdev, NULL);
- i2c_del_adapter(&dev->adapter);
- put_device(&pdev->dev);
-
- clk_disable(dev->clk);
- clk_put(dev->clk);
- dev->clk = NULL;
-
- writel(0, dev->base + DW_IC_ENABLE);
- free_irq(dev->irq, dev);
- kfree(dev);
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
- return 0;
+ return dw_readl(dev, DW_IC_ENABLE);
}
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:i2c_designware");
+void i2c_dw_disable(struct dw_i2c_dev *dev)
+{
+ /* Disable controller */
+ dw_writel(dev, 0, DW_IC_ENABLE);
-static struct platform_driver dw_i2c_driver = {
- .remove = __devexit_p(dw_i2c_remove),
- .driver = {
- .name = "i2c_designware",
- .owner = THIS_MODULE,
- },
-};
+ /* Disable all interupts */
+ dw_writel(dev, 0, DW_IC_INTR_MASK);
+ dw_readl(dev, DW_IC_CLR_INTR);
+}
-static int __init dw_i2c_init_driver(void)
+void i2c_dw_clear_int(struct dw_i2c_dev *dev)
{
- return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+ dw_readl(dev, DW_IC_CLR_INTR);
}
-module_init(dw_i2c_init_driver);
-static void __exit dw_i2c_exit_driver(void)
+void i2c_dw_disable_int(struct dw_i2c_dev *dev)
{
- platform_driver_unregister(&dw_i2c_driver);
+ dw_writel(dev, 0, DW_IC_INTR_MASK);
}
-module_exit(dw_i2c_exit_driver);
-MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
-MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
-MODULE_LICENSE("GPL");
+u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
+{
+ return dw_readl(dev, DW_IC_COMP_PARAM_1);
+}
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
new file mode 100644
index 000000000000..02d1a2ddd853
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -0,0 +1,105 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+
+#define DW_IC_CON_MASTER 0x1
+#define DW_IC_CON_SPEED_STD 0x2
+#define DW_IC_CON_SPEED_FAST 0x4
+#define DW_IC_CON_10BITADDR_MASTER 0x10
+#define DW_IC_CON_RESTART_EN 0x20
+#define DW_IC_CON_SLAVE_DISABLE 0x40
+
+
+/**
+ * struct dw_i2c_dev - private i2c-designware data
+ * @dev: driver model device node
+ * @base: IO registers pointer
+ * @cmd_complete: tx completion indicator
+ * @lock: protect this struct and IO registers
+ * @clk: input reference clock
+ * @cmd_err: run time hadware error code
+ * @msgs: points to an array of messages currently being transfered
+ * @msgs_num: the number of elements in msgs
+ * @msg_write_idx: the element index of the current tx message in the msgs
+ * array
+ * @tx_buf_len: the length of the current tx buffer
+ * @tx_buf: the current tx buffer
+ * @msg_read_idx: the element index of the current rx message in the msgs
+ * array
+ * @rx_buf_len: the length of the current rx buffer
+ * @rx_buf: the current rx buffer
+ * @msg_err: error status of the current transfer
+ * @status: i2c master status, one of STATUS_*
+ * @abort_source: copy of the TX_ABRT_SOURCE register
+ * @irq: interrupt number for the i2c master
+ * @adapter: i2c subsystem adapter node
+ * @tx_fifo_depth: depth of the hardware tx fifo
+ * @rx_fifo_depth: depth of the hardware rx fifo
+ */
+struct dw_i2c_dev {
+ struct device *dev;
+ void __iomem *base;
+ struct completion cmd_complete;
+ struct mutex lock;
+ struct clk *clk;
+ u32 (*get_clk_rate_khz) (struct dw_i2c_dev *dev);
+ struct dw_pci_controller *controller;
+ int cmd_err;
+ struct i2c_msg *msgs;
+ int msgs_num;
+ int msg_write_idx;
+ u32 tx_buf_len;
+ u8 *tx_buf;
+ int msg_read_idx;
+ u32 rx_buf_len;
+ u8 *rx_buf;
+ int msg_err;
+ unsigned int status;
+ u32 abort_source;
+ int irq;
+ int swab;
+ struct i2c_adapter adapter;
+ u32 functionality;
+ u32 master_cfg;
+ unsigned int tx_fifo_depth;
+ unsigned int rx_fifo_depth;
+};
+
+extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
+extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
+extern int i2c_dw_init(struct dw_i2c_dev *dev);
+extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+ int num);
+extern u32 i2c_dw_func(struct i2c_adapter *adap);
+extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
+extern void i2c_dw_enable(struct dw_i2c_dev *dev);
+extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable(struct dw_i2c_dev *dev);
+extern void i2c_dw_clear_int(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
+extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
new file mode 100644
index 000000000000..9e89e7313d62
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -0,0 +1,392 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ * Copyright (C) 2011 Intel corporation.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include "i2c-designware-core.h"
+
+#define DRIVER_NAME "i2c-designware-pci"
+
+enum dw_pci_ctl_id_t {
+ moorestown_0,
+ moorestown_1,
+ moorestown_2,
+
+ medfield_0,
+ medfield_1,
+ medfield_2,
+ medfield_3,
+ medfield_4,
+ medfield_5,
+};
+
+struct dw_pci_controller {
+ u32 bus_num;
+ u32 bus_cfg;
+ u32 tx_fifo_depth;
+ u32 rx_fifo_depth;
+ u32 clk_khz;
+};
+
+#define INTEL_MID_STD_CFG (DW_IC_CON_MASTER | \
+ DW_IC_CON_SLAVE_DISABLE | \
+ DW_IC_CON_RESTART_EN)
+
+static struct dw_pci_controller dw_pci_controllers[] = {
+ [moorestown_0] = {
+ .bus_num = 0,
+ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+ .tx_fifo_depth = 32,
+ .rx_fifo_depth = 32,
+ .clk_khz = 25000,
+ },
+ [moorestown_1] = {
+ .bus_num = 1,
+ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+ .tx_fifo_depth = 32,
+ .rx_fifo_depth = 32,
+ .clk_khz = 25000,
+ },
+ [moorestown_2] = {
+ .bus_num = 2,
+ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+ .tx_fifo_depth = 32,
+ .rx_fifo_depth = 32,
+ .clk_khz = 25000,
+ },
+ [medfield_0] = {
+ .bus_num = 0,
+ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+ .tx_fifo_depth = 32,
+ .rx_fifo_depth = 32,
+ .clk_khz = 25000,
+ },
+ [medfield_1] = {
+ .bus_num = 1,
+ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+ .tx_fifo_depth = 32,
+ .rx_fifo_depth = 32,
+ .clk_khz = 25000,
+ },
+ [medfield_2] = {
+ .bus_num = 2,
+ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+ .tx_fifo_depth = 32,
+ .rx_fifo_depth = 32,
+ .clk_khz = 25000,
+ },
+ [medfield_3] = {
+ .bus_num = 3,
+ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD,
+ .tx_fifo_depth = 32,
+ .rx_fifo_depth = 32,
+ .clk_khz = 25000,
+ },
+ [medfield_4] = {
+ .bus_num = 4,
+ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+ .tx_fifo_depth = 32,
+ .rx_fifo_depth = 32,
+ .clk_khz = 25000,
+ },
+ [medfield_5] = {
+ .bus_num = 5,
+ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+ .tx_fifo_depth = 32,
+ .rx_fifo_depth = 32,
+ .clk_khz = 25000,
+ },
+};
+static struct i2c_algorithm i2c_dw_algo = {
+ .master_xfer = i2c_dw_xfer,
+ .functionality = i2c_dw_func,
+};
+
+static int i2c_dw_pci_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+ int err;
+
+
+ i2c_dw_disable(i2c);
+
+ err = pci_save_state(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "pci_save_state failed\n");
+ return err;
+ }
+
+ err = pci_set_power_state(pdev, PCI_D3hot);
+ if (err) {
+ dev_err(&pdev->dev, "pci_set_power_state failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int i2c_dw_pci_resume(struct device *dev)
+{
+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+ int err;
+ u32 enabled;
+
+ enabled = i2c_dw_is_enabled(i2c);
+ if (enabled)
+ return 0;
+
+ err = pci_set_power_state(pdev, PCI_D0);
+ if (err) {
+ dev_err(&pdev->dev, "pci_set_power_state() failed\n");
+ return err;
+ }
+
+ pci_restore_state(pdev);
+
+ i2c_dw_init(i2c);
+ i2c_dw_enable(i2c);
+ return 0;
+}
+
+static int i2c_dw_pci_runtime_idle(struct device *dev)
+{
+ int err = pm_schedule_suspend(dev, 500);
+ dev_dbg(dev, "runtime_idle called\n");
+
+ if (err != 0)
+ return 0;
+ return -EBUSY;
+}
+
+static const struct dev_pm_ops i2c_dw_pm_ops = {
+ .resume = i2c_dw_pci_resume,
+ .suspend = i2c_dw_pci_suspend,
+ SET_RUNTIME_PM_OPS(i2c_dw_pci_suspend, i2c_dw_pci_resume,
+ i2c_dw_pci_runtime_idle)
+};
+
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+ return dev->controller->clk_khz;
+}
+
+static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev,
+const struct pci_device_id *id)
+{
+ struct dw_i2c_dev *dev;
+ struct i2c_adapter *adap;
+ unsigned long start, len;
+ void __iomem *base;
+ int r;
+ struct dw_pci_controller *controller;
+
+ if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) {
+ printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n",
+ id->driver_data);
+ return -EINVAL;
+ }
+
+ controller = &dw_pci_controllers[id->driver_data];
+
+ r = pci_enable_device(pdev);
+ if (r) {
+ dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n",
+ r);
+ goto exit;
+ }
+
+ /* Determine the address of the I2C area */
+ start = pci_resource_start(pdev, 0);
+ len = pci_resource_len(pdev, 0);
+ if (!start || len == 0) {
+ dev_err(&pdev->dev, "base address not set\n");
+ r = -ENODEV;
+ goto exit;
+ }
+
+ r = pci_request_region(pdev, 0, DRIVER_NAME);
+ if (r) {
+ dev_err(&pdev->dev, "failed to request I2C region "
+ "0x%lx-0x%lx\n", start,
+ (unsigned long)pci_resource_end(pdev, 0));
+ goto exit;
+ }
+
+ base = ioremap_nocache(start, len);
+ if (!base) {
+ dev_err(&pdev->dev, "I/O memory remapping failed\n");
+ r = -ENOMEM;
+ goto err_release_region;
+ }
+
+
+ dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+ if (!dev) {
+ r = -ENOMEM;
+ goto err_release_region;
+ }
+
+ init_completion(&dev->cmd_complete);
+ mutex_init(&dev->lock);
+ dev->clk = NULL;
+ dev->controller = controller;
+ dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+ dev->base = base;
+ dev->dev = get_device(&pdev->dev);
+ dev->functionality =
+ I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK;
+ dev->master_cfg = controller->bus_cfg;
+
+ pci_set_drvdata(pdev, dev);
+
+ dev->tx_fifo_depth = controller->tx_fifo_depth;
+ dev->rx_fifo_depth = controller->rx_fifo_depth;
+ r = i2c_dw_init(dev);
+ if (r)
+ goto err_iounmap;
+
+ adap = &dev->adapter;
+ i2c_set_adapdata(adap, dev);
+ adap->owner = THIS_MODULE;
+ adap->class = 0;
+ adap->algo = &i2c_dw_algo;
+ adap->dev.parent = &pdev->dev;
+ adap->nr = controller->bus_num;
+ snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d",
+ adap->nr);
+
+ r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev);
+ if (r) {
+ dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+ goto err_iounmap;
+ }
+
+ i2c_dw_disable_int(dev);
+ i2c_dw_clear_int(dev);
+ r = i2c_add_numbered_adapter(adap);
+ if (r) {
+ dev_err(&pdev->dev, "failure adding adapter\n");
+ goto err_free_irq;
+ }
+
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_allow(&pdev->dev);
+
+ return 0;
+
+err_free_irq:
+ free_irq(pdev->irq, dev);
+err_iounmap:
+ iounmap(dev->base);
+ pci_set_drvdata(pdev, NULL);
+ put_device(&pdev->dev);
+ kfree(dev);
+err_release_region:
+ pci_release_region(pdev, 0);
+exit:
+ return r;
+}
+
+static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev)
+{
+ struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
+
+ i2c_dw_disable(dev);
+ pm_runtime_forbid(&pdev->dev);
+ pm_runtime_get_noresume(&pdev->dev);
+
+ pci_set_drvdata(pdev, NULL);
+ i2c_del_adapter(&dev->adapter);
+ put_device(&pdev->dev);
+
+ free_irq(dev->irq, dev);
+ kfree(dev);
+ pci_release_region(pdev, 0);
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("i2c_designware-pci");
+
+DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = {
+ /* Moorestown */
+ { PCI_VDEVICE(INTEL, 0x0802), moorestown_0 },
+ { PCI_VDEVICE(INTEL, 0x0803), moorestown_1 },
+ { PCI_VDEVICE(INTEL, 0x0804), moorestown_2 },
+ /* Medfield */
+ { PCI_VDEVICE(INTEL, 0x0817), medfield_3,},
+ { PCI_VDEVICE(INTEL, 0x0818), medfield_4 },
+ { PCI_VDEVICE(INTEL, 0x0819), medfield_5 },
+ { PCI_VDEVICE(INTEL, 0x082C), medfield_0 },
+ { PCI_VDEVICE(INTEL, 0x082D), medfield_1 },
+ { PCI_VDEVICE(INTEL, 0x082E), medfield_2 },
+ { 0,}
+};
+MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
+
+static struct pci_driver dw_i2c_driver = {
+ .name = DRIVER_NAME,
+ .id_table = i2_designware_pci_ids,
+ .probe = i2c_dw_pci_probe,
+ .remove = __devexit_p(i2c_dw_pci_remove),
+ .driver = {
+ .pm = &i2c_dw_pm_ops,
+ },
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+ return pci_register_driver(&dw_i2c_driver);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+ pci_unregister_driver(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
new file mode 100644
index 000000000000..2d3657ab1258
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -0,0 +1,215 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include "i2c-designware-core.h"
+
+static struct i2c_algorithm i2c_dw_algo = {
+ .master_xfer = i2c_dw_xfer,
+ .functionality = i2c_dw_func,
+};
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+ return clk_get_rate(dev->clk)/1000;
+}
+
+static int __devinit dw_i2c_probe(struct platform_device *pdev)
+{
+ struct dw_i2c_dev *dev;
+ struct i2c_adapter *adap;
+ struct resource *mem, *ioarea;
+ int irq, r;
+
+ /* NOTE: driver uses the static register mapping */
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "no mem resource?\n");
+ return -EINVAL;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq resource?\n");
+ return irq; /* -ENXIO */
+ }
+
+ ioarea = request_mem_region(mem->start, resource_size(mem),
+ pdev->name);
+ if (!ioarea) {
+ dev_err(&pdev->dev, "I2C region already claimed\n");
+ return -EBUSY;
+ }
+
+ dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+ if (!dev) {
+ r = -ENOMEM;
+ goto err_release_region;
+ }
+
+ init_completion(&dev->cmd_complete);
+ mutex_init(&dev->lock);
+ dev->dev = get_device(&pdev->dev);
+ dev->irq = irq;
+ platform_set_drvdata(pdev, dev);
+
+ dev->clk = clk_get(&pdev->dev, NULL);
+ dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+
+ if (IS_ERR(dev->clk)) {
+ r = -ENODEV;
+ goto err_free_mem;
+ }
+ clk_enable(dev->clk);
+
+ dev->functionality =
+ I2C_FUNC_I2C |
+ I2C_FUNC_10BIT_ADDR |
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK;
+ dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+ DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+
+ dev->base = ioremap(mem->start, resource_size(mem));
+ if (dev->base == NULL) {
+ dev_err(&pdev->dev, "failure mapping io resources\n");
+ r = -EBUSY;
+ goto err_unuse_clocks;
+ }
+ {
+ u32 param1 = i2c_dw_read_comp_param(dev);
+
+ dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
+ dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1;
+ }
+ r = i2c_dw_init(dev);
+ if (r)
+ goto err_iounmap;
+
+ i2c_dw_disable_int(dev);
+ r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
+ if (r) {
+ dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+ goto err_iounmap;
+ }
+
+ adap = &dev->adapter;
+ i2c_set_adapdata(adap, dev);
+ adap->owner = THIS_MODULE;
+ adap->class = I2C_CLASS_HWMON;
+ strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
+ sizeof(adap->name));
+ adap->algo = &i2c_dw_algo;
+ adap->dev.parent = &pdev->dev;
+
+ adap->nr = pdev->id;
+ r = i2c_add_numbered_adapter(adap);
+ if (r) {
+ dev_err(&pdev->dev, "failure adding adapter\n");
+ goto err_free_irq;
+ }
+
+ return 0;
+
+err_free_irq:
+ free_irq(dev->irq, dev);
+err_iounmap:
+ iounmap(dev->base);
+err_unuse_clocks:
+ clk_disable(dev->clk);
+ clk_put(dev->clk);
+ dev->clk = NULL;
+err_free_mem:
+ platform_set_drvdata(pdev, NULL);
+ put_device(&pdev->dev);
+ kfree(dev);
+err_release_region:
+ release_mem_region(mem->start, resource_size(mem));
+
+ return r;
+}
+
+static int __devexit dw_i2c_remove(struct platform_device *pdev)
+{
+ struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+ struct resource *mem;
+
+ platform_set_drvdata(pdev, NULL);
+ i2c_del_adapter(&dev->adapter);
+ put_device(&pdev->dev);
+
+ clk_disable(dev->clk);
+ clk_put(dev->clk);
+ dev->clk = NULL;
+
+ i2c_dw_disable(dev);
+ free_irq(dev->irq, dev);
+ kfree(dev);
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mem->start, resource_size(mem));
+ return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:i2c_designware");
+
+static struct platform_driver dw_i2c_driver = {
+ .remove = __devexit_p(dw_i2c_remove),
+ .driver = {
+ .name = "i2c_designware",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+ return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+ platform_driver_unregister(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index ce1a32b71e47..8cebef49aeac 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -64,6 +64,7 @@
#define TEN_BIT_ADDR_DEFAULT 0xF000
#define TEN_BIT_ADDR_MASK 0xF0
#define PCH_START 0x0020
+#define PCH_RESTART 0x0004
#define PCH_ESR_START 0x0001
#define PCH_BUFF_START 0x1
#define PCH_REPSTART 0x0004
@@ -273,23 +274,24 @@ static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
s32 timeout)
{
void __iomem *p = adap->pch_base_address;
+ ktime_t ns_val;
+
+ if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+ return 0;
/* MAX timeout value is timeout*1000*1000nsec */
- ktime_t ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
+ ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
do {
- if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
- break;
msleep(20);
+ if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+ return 0;
} while (ktime_lt(ktime_get(), ns_val));
pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
+ pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
+ pch_i2c_init(adap);
- if (timeout == 0) {
- pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
- return -ETIME;
- }
-
- return 0;
+ return -ETIME;
}
/**
@@ -311,21 +313,19 @@ static void pch_i2c_start(struct i2c_algo_pch_data *adap)
*/
static s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap)
{
- s32 ret;
+ long ret;
ret = wait_event_timeout(pch_event,
(adap->pch_event_flag != 0), msecs_to_jiffies(50));
- if (ret < 0) {
- pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
- return ret;
- }
if (ret == 0) {
pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
+ adap->pch_event_flag = 0;
return -ETIMEDOUT;
}
if (adap->pch_event_flag & I2C_ERROR_MASK) {
pch_err(adap, "error bits set: %x\n", adap->pch_event_flag);
+ adap->pch_event_flag = 0;
return -EIO;
}
@@ -394,6 +394,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
u32 addr_2_msb;
u32 addr_8_lsb;
s32 wrcount;
+ s32 rtn;
void __iomem *p = adap->pch_base_address;
length = msgs->len;
@@ -412,15 +413,29 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
}
if (msgs->flags & I2C_M_TEN) {
- addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
+ addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06;
iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
if (first)
pch_i2c_start(adap);
- if (pch_i2c_wait_for_xfer_complete(adap) == 0 &&
- pch_i2c_getack(adap) == 0) {
+
+ rtn = pch_i2c_wait_for_xfer_complete(adap);
+ if (rtn == 0) {
+ if (pch_i2c_getack(adap)) {
+ pch_dbg(adap, "Receive NACK for slave address"
+ "setting\n");
+ return -EIO;
+ }
addr_8_lsb = (addr & I2C_ADDR_MSK);
iowrite32(addr_8_lsb, p + PCH_I2CDR);
- } else {
+ } else if (rtn == -EIO) { /* Arbitration Lost */
+ pch_err(adap, "Lost Arbitration\n");
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+ I2CMAL_BIT);
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+ I2CMIF_BIT);
+ pch_i2c_init(adap);
+ return -EAGAIN;
+ } else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
@@ -431,30 +446,51 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
pch_i2c_start(adap);
}
- if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
- (pch_i2c_getack(adap) == 0)) {
- for (wrcount = 0; wrcount < length; ++wrcount) {
- /* write buffer value to I2C data register */
- iowrite32(buf[wrcount], p + PCH_I2CDR);
- pch_dbg(adap, "writing %x to Data register\n",
- buf[wrcount]);
+ rtn = pch_i2c_wait_for_xfer_complete(adap);
+ if (rtn == 0) {
+ if (pch_i2c_getack(adap)) {
+ pch_dbg(adap, "Receive NACK for slave address"
+ "setting\n");
+ return -EIO;
+ }
+ } else if (rtn == -EIO) { /* Arbitration Lost */
+ pch_err(adap, "Lost Arbitration\n");
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
+ pch_i2c_init(adap);
+ return -EAGAIN;
+ } else { /* wait-event timeout */
+ pch_i2c_stop(adap);
+ return -ETIME;
+ }
- if (pch_i2c_wait_for_xfer_complete(adap) != 0)
- return -ETIME;
+ for (wrcount = 0; wrcount < length; ++wrcount) {
+ /* write buffer value to I2C data register */
+ iowrite32(buf[wrcount], p + PCH_I2CDR);
+ pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]);
- if (pch_i2c_getack(adap))
+ rtn = pch_i2c_wait_for_xfer_complete(adap);
+ if (rtn == 0) {
+ if (pch_i2c_getack(adap)) {
+ pch_dbg(adap, "Receive NACK for slave address"
+ "setting\n");
return -EIO;
+ }
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+ I2CMCF_BIT);
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+ I2CMIF_BIT);
+ } else { /* wait-event timeout */
+ pch_i2c_stop(adap);
+ return -ETIME;
}
+ }
- /* check if this is the last message */
- if (last)
- pch_i2c_stop(adap);
- else
- pch_i2c_repstart(adap);
- } else {
+ /* check if this is the last message */
+ if (last)
pch_i2c_stop(adap);
- return -EIO;
- }
+ else
+ pch_i2c_repstart(adap);
pch_dbg(adap, "return=%d\n", wrcount);
@@ -484,6 +520,19 @@ static void pch_i2c_sendnack(struct i2c_algo_pch_data *adap)
}
/**
+ * pch_i2c_restart() - Generate I2C restart condition in normal mode.
+ * @adap: Pointer to struct i2c_algo_pch_data.
+ *
+ * Generate I2C restart condition in normal mode by setting I2CCTL.I2CRSTA.
+ */
+static void pch_i2c_restart(struct i2c_algo_pch_data *adap)
+{
+ void __iomem *p = adap->pch_base_address;
+ pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
+ pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_RESTART);
+}
+
+/**
* pch_i2c_readbytes() - read data from I2C bus in normal mode.
* @i2c_adap: Pointer to the struct i2c_adapter.
* @msgs: Pointer to i2c_msg structure.
@@ -500,7 +549,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
u32 length;
u32 addr;
u32 addr_2_msb;
+ u32 addr_8_lsb;
void __iomem *p = adap->pch_base_address;
+ s32 rtn;
length = msgs->len;
buf = msgs->buf;
@@ -515,9 +566,55 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
}
if (msgs->flags & I2C_M_TEN) {
- addr_2_msb = (((addr & I2C_MSB_2B_MSK) >> 7) | (I2C_RD));
+ addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
+ if (first)
+ pch_i2c_start(adap);
+ rtn = pch_i2c_wait_for_xfer_complete(adap);
+ if (rtn == 0) {
+ if (pch_i2c_getack(adap)) {
+ pch_dbg(adap, "Receive NACK for slave address"
+ "setting\n");
+ return -EIO;
+ }
+ addr_8_lsb = (addr & I2C_ADDR_MSK);
+ iowrite32(addr_8_lsb, p + PCH_I2CDR);
+ } else if (rtn == -EIO) { /* Arbitration Lost */
+ pch_err(adap, "Lost Arbitration\n");
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+ I2CMAL_BIT);
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+ I2CMIF_BIT);
+ pch_i2c_init(adap);
+ return -EAGAIN;
+ } else { /* wait-event timeout */
+ pch_i2c_stop(adap);
+ return -ETIME;
+ }
+ pch_i2c_restart(adap);
+ rtn = pch_i2c_wait_for_xfer_complete(adap);
+ if (rtn == 0) {
+ if (pch_i2c_getack(adap)) {
+ pch_dbg(adap, "Receive NACK for slave address"
+ "setting\n");
+ return -EIO;
+ }
+ addr_2_msb |= I2C_RD;
+ iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK,
+ p + PCH_I2CDR);
+ } else if (rtn == -EIO) { /* Arbitration Lost */
+ pch_err(adap, "Lost Arbitration\n");
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+ I2CMAL_BIT);
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+ I2CMIF_BIT);
+ pch_i2c_init(adap);
+ return -EAGAIN;
+ } else { /* wait-event timeout */
+ pch_i2c_stop(adap);
+ return -ETIME;
+ }
} else {
/* 7 address bits + R/W bit */
addr = (((addr) << 1) | (I2C_RD));
@@ -528,56 +625,81 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
if (first)
pch_i2c_start(adap);
- if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
- (pch_i2c_getack(adap) == 0)) {
- pch_dbg(adap, "return %d\n", 0);
+ rtn = pch_i2c_wait_for_xfer_complete(adap);
+ if (rtn == 0) {
+ if (pch_i2c_getack(adap)) {
+ pch_dbg(adap, "Receive NACK for slave address"
+ "setting\n");
+ return -EIO;
+ }
+ } else if (rtn == -EIO) { /* Arbitration Lost */
+ pch_err(adap, "Lost Arbitration\n");
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
+ pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
+ pch_i2c_init(adap);
+ return -EAGAIN;
+ } else { /* wait-event timeout */
+ pch_i2c_stop(adap);
+ return -ETIME;
+ }
- if (length == 0) {
- pch_i2c_stop(adap);
- ioread32(p + PCH_I2CDR); /* Dummy read needs */
+ if (length == 0) {
+ pch_i2c_stop(adap);
+ ioread32(p + PCH_I2CDR); /* Dummy read needs */
- count = length;
- } else {
- int read_index;
- int loop;
- pch_i2c_sendack(adap);
+ count = length;
+ } else {
+ int read_index;
+ int loop;
+ pch_i2c_sendack(adap);
- /* Dummy read */
- for (loop = 1, read_index = 0; loop < length; loop++) {
- buf[read_index] = ioread32(p + PCH_I2CDR);
+ /* Dummy read */
+ for (loop = 1, read_index = 0; loop < length; loop++) {
+ buf[read_index] = ioread32(p + PCH_I2CDR);
- if (loop != 1)
- read_index++;
+ if (loop != 1)
+ read_index++;
- if (pch_i2c_wait_for_xfer_complete(adap) != 0) {
- pch_i2c_stop(adap);
- return -ETIME;
+ rtn = pch_i2c_wait_for_xfer_complete(adap);
+ if (rtn == 0) {
+ if (pch_i2c_getack(adap)) {
+ pch_dbg(adap, "Receive NACK for slave"
+ "address setting\n");
+ return -EIO;
}
- } /* end for */
+ } else { /* wait-event timeout */
+ pch_i2c_stop(adap);
+ return -ETIME;
+ }
- pch_i2c_sendnack(adap);
+ } /* end for */
- buf[read_index] = ioread32(p + PCH_I2CDR);
+ pch_i2c_sendnack(adap);
- if (length != 1)
- read_index++;
+ buf[read_index] = ioread32(p + PCH_I2CDR); /* Read final - 1 */
- if (pch_i2c_wait_for_xfer_complete(adap) == 0) {
- if (last)
- pch_i2c_stop(adap);
- else
- pch_i2c_repstart(adap);
+ if (length != 1)
+ read_index++;
- buf[read_index++] = ioread32(p + PCH_I2CDR);
- count = read_index;
- } else {
- count = -ETIME;
+ rtn = pch_i2c_wait_for_xfer_complete(adap);
+ if (rtn == 0) {
+ if (pch_i2c_getack(adap)) {
+ pch_dbg(adap, "Receive NACK for slave"
+ "address setting\n");
+ return -EIO;
}
-
+ } else { /* wait-event timeout */
+ pch_i2c_stop(adap);
+ return -ETIME;
}
- } else {
- count = -ETIME;
- pch_i2c_stop(adap);
+
+ if (last)
+ pch_i2c_stop(adap);
+ else
+ pch_i2c_repstart(adap);
+
+ buf[read_index++] = ioread32(p + PCH_I2CDR); /* Read Final */
+ count = read_index;
}
return count;
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
index 3876a2478bd7..63bb1cc2a042 100644
--- a/drivers/i2c/busses/i2c-highlander.c
+++ b/drivers/i2c/busses/i2c-highlander.c
@@ -387,7 +387,7 @@ static int __devinit highlander_i2c_probe(struct platform_device *pdev)
dev->irq = 0;
if (dev->irq) {
- ret = request_irq(dev->irq, highlander_i2c_irq, IRQF_DISABLED,
+ ret = request_irq(dev->irq, highlander_i2c_irq, 0,
pdev->name, dev);
if (unlikely(ret))
goto err_unmap;
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 4c2a62b75b5c..58832e578fff 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -48,6 +48,9 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_i2c.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
@@ -125,6 +128,11 @@ struct imx_i2c_struct {
unsigned int ifdr; /* IMX_I2C_IFDR */
};
+static const struct of_device_id i2c_imx_dt_ids[] = {
+ { .compatible = "fsl,imx1-i2c", },
+ { /* sentinel */ }
+};
+
/** Functions for IMX I2C adapter driver ***************************************
*******************************************************************************/
@@ -466,10 +474,10 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
{
struct imx_i2c_struct *i2c_imx;
struct resource *res;
- struct imxi2c_platform_data *pdata;
+ struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
void __iomem *base;
resource_size_t res_size;
- int irq;
+ int irq, bitrate;
int ret;
dev_dbg(&pdev->dev, "<%s>\n", __func__);
@@ -485,19 +493,11 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
return -ENOENT;
}
- pdata = pdev->dev.platform_data;
-
- if (pdata && pdata->init) {
- ret = pdata->init(&pdev->dev);
- if (ret)
- return ret;
- }
-
res_size = resource_size(res);
if (!request_mem_region(res->start, res_size, DRIVER_NAME)) {
- ret = -EBUSY;
- goto fail0;
+ dev_err(&pdev->dev, "request_mem_region failed\n");
+ return -EBUSY;
}
base = ioremap(res->start, res_size);
@@ -520,6 +520,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
i2c_imx->adapter.algo = &i2c_imx_algo;
i2c_imx->adapter.dev.parent = &pdev->dev;
i2c_imx->adapter.nr = pdev->id;
+ i2c_imx->adapter.dev.of_node = pdev->dev.of_node;
i2c_imx->irq = irq;
i2c_imx->base = base;
i2c_imx->res = res;
@@ -546,10 +547,12 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
/* Set up clock divider */
- if (pdata && pdata->bitrate)
- i2c_imx_set_clk(i2c_imx, pdata->bitrate);
- else
- i2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE);
+ bitrate = IMX_I2C_BIT_RATE;
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "clock-frequency", &bitrate);
+ if (ret < 0 && pdata && pdata->bitrate)
+ bitrate = pdata->bitrate;
+ i2c_imx_set_clk(i2c_imx, bitrate);
/* Set up chip registers to defaults */
writeb(0, i2c_imx->base + IMX_I2C_I2CR);
@@ -562,6 +565,8 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
goto fail5;
}
+ of_i2c_register_devices(&i2c_imx->adapter);
+
/* Set up platform driver data */
platform_set_drvdata(pdev, i2c_imx);
@@ -586,16 +591,12 @@ fail2:
iounmap(base);
fail1:
release_mem_region(res->start, resource_size(res));
-fail0:
- if (pdata && pdata->exit)
- pdata->exit(&pdev->dev);
return ret; /* Return error number */
}
static int __exit i2c_imx_remove(struct platform_device *pdev)
{
struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
- struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
/* remove adapter */
dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
@@ -611,10 +612,6 @@ static int __exit i2c_imx_remove(struct platform_device *pdev)
writeb(0, i2c_imx->base + IMX_I2C_I2CR);
writeb(0, i2c_imx->base + IMX_I2C_I2SR);
- /* Shut down hardware */
- if (pdata && pdata->exit)
- pdata->exit(&pdev->dev);
-
clk_put(i2c_imx->clk);
iounmap(i2c_imx->base);
@@ -628,6 +625,7 @@ static struct platform_driver i2c_imx_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
+ .of_match_table = i2c_imx_dt_ids,
}
};
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index 5d8aed5ec21b..c01e9519f6c1 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -35,7 +35,7 @@
#include <linux/slab.h>
#include <mach/hardware.h> /* Pick up IXP2000-specific bits */
-#include <mach/gpio.h>
+#include <mach/gpio-ixp2000.h>
static inline int ixp2000_scl_pin(void *data)
{
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index b228e09c5d05..5267ab93d550 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -63,11 +63,11 @@
/* Master controller (MCR) register */
#define I2C_MCR_OP (0x1 << 0) /* Operation */
#define I2C_MCR_A7 (0x7f << 1) /* 7-bit address */
-#define I2C_MCR_EA10 (0x7 << 8) /* 10-bit Extended address */
+#define I2C_MCR_EA10 (0x7 << 8) /* 10-bit Extended address */
#define I2C_MCR_SB (0x1 << 11) /* Extended address */
#define I2C_MCR_AM (0x3 << 12) /* Address type */
-#define I2C_MCR_STOP (0x1 << 14) /* Stop condition */
-#define I2C_MCR_LENGTH (0x7ff << 15) /* Transaction length */
+#define I2C_MCR_STOP (0x1 << 14) /* Stop condition */
+#define I2C_MCR_LENGTH (0x7ff << 15) /* Transaction length */
/* Status register (SR) */
#define I2C_SR_OP (0x3 << 0) /* Operation */
@@ -77,7 +77,7 @@
#define I2C_SR_LENGTH (0x7ff << 9) /* Transfer length */
/* Interrupt mask set/clear (IMSCR) bits */
-#define I2C_IT_TXFE (0x1 << 0)
+#define I2C_IT_TXFE (0x1 << 0)
#define I2C_IT_TXFNE (0x1 << 1)
#define I2C_IT_TXFF (0x1 << 2)
#define I2C_IT_TXFOVR (0x1 << 3)
@@ -135,31 +135,31 @@ struct i2c_nmk_client {
};
/**
- * struct nmk_i2c_dev - private data structure of the controller
- * @pdev: parent platform device
- * @adap: corresponding I2C adapter
- * @irq: interrupt line for the controller
- * @virtbase: virtual io memory area
- * @clk: hardware i2c block clock
- * @cfg: machine provided controller configuration
- * @cli: holder of client specific data
- * @stop: stop condition
- * @xfer_complete: acknowledge completion for a I2C message
- * @result: controller propogated result
- * @regulator: pointer to i2c regulator
- * @busy: Busy doing transfer
+ * struct nmk_i2c_dev - private data structure of the controller.
+ * @pdev: parent platform device.
+ * @adap: corresponding I2C adapter.
+ * @irq: interrupt line for the controller.
+ * @virtbase: virtual io memory area.
+ * @clk: hardware i2c block clock.
+ * @cfg: machine provided controller configuration.
+ * @cli: holder of client specific data.
+ * @stop: stop condition.
+ * @xfer_complete: acknowledge completion for a I2C message.
+ * @result: controller propogated result.
+ * @regulator: pointer to i2c regulator.
+ * @busy: Busy doing transfer.
*/
struct nmk_i2c_dev {
struct platform_device *pdev;
- struct i2c_adapter adap;
- int irq;
+ struct i2c_adapter adap;
+ int irq;
void __iomem *virtbase;
struct clk *clk;
struct nmk_i2c_controller cfg;
struct i2c_nmk_client cli;
- int stop;
+ int stop;
struct completion xfer_complete;
- int result;
+ int result;
struct regulator *regulator;
bool busy;
};
@@ -217,8 +217,9 @@ static int flush_i2c_fifo(struct nmk_i2c_dev *dev)
}
}
- dev_err(&dev->pdev->dev, "flushing operation timed out "
- "giving up after %d attempts", LOOP_ATTEMPTS);
+ dev_err(&dev->pdev->dev,
+ "flushing operation timed out giving up after %d attempts",
+ LOOP_ATTEMPTS);
return -ETIMEDOUT;
}
@@ -270,7 +271,7 @@ exit:
}
/* enable peripheral, master mode operation */
-#define DEFAULT_I2C_REG_CR ((1 << 1) | I2C_CR_PE)
+#define DEFAULT_I2C_REG_CR ((1 << 1) | I2C_CR_PE)
/**
* load_i2c_mcr_reg() - load the MCR register
@@ -363,8 +364,8 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)
* and high speed (up to 3.4 Mb/s)
*/
if (dev->cfg.sm > I2C_FREQ_MODE_FAST) {
- dev_err(&dev->pdev->dev, "do not support this mode "
- "defaulting to std. mode\n");
+ dev_err(&dev->pdev->dev,
+ "do not support this mode defaulting to std. mode\n");
brcr2 = i2c_clk/(100000 * 2) & 0xffff;
writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
writel(I2C_FREQ_MODE_STANDARD << 4,
@@ -423,7 +424,7 @@ static int read_i2c(struct nmk_i2c_dev *dev)
if (timeout < 0) {
dev_err(&dev->pdev->dev,
- "wait_for_completion_timeout"
+ "wait_for_completion_timeout "
"returned %d waiting for event\n", timeout);
status = timeout;
}
@@ -556,8 +557,8 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags)
if (((i2c_sr >> 2) & 0x3) == 0x3) {
/* get the abort cause */
cause = (i2c_sr >> 4) & 0x7;
- dev_err(&dev->pdev->dev, "%s\n", cause
- >= ARRAY_SIZE(abort_causes) ?
+ dev_err(&dev->pdev->dev, "%s\n",
+ cause >= ARRAY_SIZE(abort_causes) ?
"unknown reason" :
abort_causes[cause]);
}
@@ -582,13 +583,13 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags)
*
* NOTE:
* READ TRANSFER : We impose a restriction of the first message to be the
- * index message for any read transaction.
- * - a no index is coded as '0',
- * - 2byte big endian index is coded as '3'
- * !!! msg[0].buf holds the actual index.
- * This is compatible with generic messages of smbus emulator
- * that send a one byte index.
- * eg. a I2C transation to read 2 bytes from index 0
+ * index message for any read transaction.
+ * - a no index is coded as '0',
+ * - 2byte big endian index is coded as '3'
+ * !!! msg[0].buf holds the actual index.
+ * This is compatible with generic messages of smbus emulator
+ * that send a one byte index.
+ * eg. a I2C transation to read 2 bytes from index 0
* idx = 0;
* msg[0].addr = client->addr;
* msg[0].flags = 0x0;
@@ -644,8 +645,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
for (i = 0; i < num_msgs; i++) {
if (unlikely(msgs[i].flags & I2C_M_TEN)) {
- dev_err(&dev->pdev->dev, "10 bit addressing"
- "not supported\n");
+ dev_err(&dev->pdev->dev,
+ "10 bit addressing not supported\n");
status = -EINVAL;
goto out;
@@ -789,8 +790,9 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
if (dev->cli.count) {
dev->result = -EIO;
- dev_err(&dev->pdev->dev, "%lu bytes still remain to be"
- "xfered\n", dev->cli.count);
+ dev_err(&dev->pdev->dev,
+ "%lu bytes still remain to be xfered\n",
+ dev->cli.count);
(void) init_hw(dev);
}
complete(&dev->xfer_complete);
@@ -923,7 +925,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
}
if (request_mem_region(res->start, resource_size(res),
- DRIVER_NAME "I/O region") == NULL) {
+ DRIVER_NAME "I/O region") == NULL) {
ret = -EBUSY;
goto err_no_region;
}
@@ -935,7 +937,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
}
dev->irq = platform_get_irq(pdev, 0);
- ret = request_irq(dev->irq, i2c_irq_handler, IRQF_DISABLED,
+ ret = request_irq(dev->irq, i2c_irq_handler, 0,
DRIVER_NAME, dev);
if (ret) {
dev_err(&pdev->dev, "cannot claim the irq %d\n", dev->irq);
@@ -980,8 +982,9 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(adap, dev);
- dev_info(&pdev->dev, "initialize %s on virtual "
- "base %p\n", adap->name, dev->virtbase);
+ dev_info(&pdev->dev,
+ "initialize %s on virtual base %p\n",
+ adap->name, dev->virtbase);
ret = i2c_add_numbered_adapter(adap);
if (ret) {
diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c
index 72434263787b..835e47b39bc2 100644
--- a/drivers/i2c/busses/i2c-nuc900.c
+++ b/drivers/i2c/busses/i2c-nuc900.c
@@ -610,7 +610,7 @@ static int __devinit nuc900_i2c_probe(struct platform_device *pdev)
goto err_iomap;
}
- ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_DISABLED | IRQF_SHARED,
+ ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_SHARED,
dev_name(&pdev->dev), i2c);
if (ret != 0) {
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 2dfb63176856..a43d0023446a 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -42,12 +42,12 @@
#include <linux/pm_runtime.h>
/* I2C controller revisions */
-#define OMAP_I2C_REV_2 0x20
+#define OMAP_I2C_OMAP1_REV_2 0x20
/* I2C controller revisions present on specific hardware */
#define OMAP_I2C_REV_ON_2430 0x36
#define OMAP_I2C_REV_ON_3430 0x3C
-#define OMAP_I2C_REV_ON_4430 0x40
+#define OMAP_I2C_REV_ON_3530_4430 0x40
/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -72,11 +72,12 @@ enum {
OMAP_I2C_SCLH_REG,
OMAP_I2C_SYSTEST_REG,
OMAP_I2C_BUFSTAT_REG,
- OMAP_I2C_REVNB_LO,
- OMAP_I2C_REVNB_HI,
- OMAP_I2C_IRQSTATUS_RAW,
- OMAP_I2C_IRQENABLE_SET,
- OMAP_I2C_IRQENABLE_CLR,
+ /* only on OMAP4430 */
+ OMAP_I2C_IP_V2_REVNB_LO,
+ OMAP_I2C_IP_V2_REVNB_HI,
+ OMAP_I2C_IP_V2_IRQSTATUS_RAW,
+ OMAP_I2C_IP_V2_IRQENABLE_SET,
+ OMAP_I2C_IP_V2_IRQENABLE_CLR,
};
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
@@ -193,7 +194,6 @@ struct omap_i2c_dev {
*/
u8 rev;
unsigned b_hw:1; /* bad h/w fixes */
- unsigned idle:1;
u16 iestate; /* Saved interrupt register */
u16 pscstate;
u16 scllstate;
@@ -204,7 +204,7 @@ struct omap_i2c_dev {
u16 errata;
};
-static const u8 reg_map[] = {
+static const u8 reg_map_ip_v1[] = {
[OMAP_I2C_REV_REG] = 0x00,
[OMAP_I2C_IE_REG] = 0x01,
[OMAP_I2C_STAT_REG] = 0x02,
@@ -225,7 +225,7 @@ static const u8 reg_map[] = {
[OMAP_I2C_BUFSTAT_REG] = 0x10,
};
-static const u8 omap4_reg_map[] = {
+static const u8 reg_map_ip_v2[] = {
[OMAP_I2C_REV_REG] = 0x04,
[OMAP_I2C_IE_REG] = 0x2c,
[OMAP_I2C_STAT_REG] = 0x28,
@@ -244,11 +244,11 @@ static const u8 omap4_reg_map[] = {
[OMAP_I2C_SCLH_REG] = 0xb8,
[OMAP_I2C_SYSTEST_REG] = 0xbC,
[OMAP_I2C_BUFSTAT_REG] = 0xc0,
- [OMAP_I2C_REVNB_LO] = 0x00,
- [OMAP_I2C_REVNB_HI] = 0x04,
- [OMAP_I2C_IRQSTATUS_RAW] = 0x24,
- [OMAP_I2C_IRQENABLE_SET] = 0x2c,
- [OMAP_I2C_IRQENABLE_CLR] = 0x30,
+ [OMAP_I2C_IP_V2_REVNB_LO] = 0x00,
+ [OMAP_I2C_IP_V2_REVNB_HI] = 0x04,
+ [OMAP_I2C_IP_V2_IRQSTATUS_RAW] = 0x24,
+ [OMAP_I2C_IP_V2_IRQENABLE_SET] = 0x2c,
+ [OMAP_I2C_IP_V2_IRQENABLE_CLR] = 0x30,
};
static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
@@ -266,17 +266,11 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
static void omap_i2c_unidle(struct omap_i2c_dev *dev)
{
- struct platform_device *pdev;
struct omap_i2c_bus_platform_data *pdata;
- WARN_ON(!dev->idle);
+ pdata = dev->dev->platform_data;
- pdev = to_platform_device(dev->dev);
- pdata = pdev->dev.platform_data;
-
- pm_runtime_get_sync(&pdev->dev);
-
- if (cpu_is_omap34xx()) {
+ if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
@@ -286,7 +280,6 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
}
- dev->idle = 0;
/*
* Don't write to this register if the IE state is 0 as it can
@@ -298,32 +291,25 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
static void omap_i2c_idle(struct omap_i2c_dev *dev)
{
- struct platform_device *pdev;
struct omap_i2c_bus_platform_data *pdata;
u16 iv;
- WARN_ON(dev->idle);
-
- pdev = to_platform_device(dev->dev);
- pdata = pdev->dev.platform_data;
+ pdata = dev->dev->platform_data;
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
- if (dev->rev >= OMAP_I2C_REV_ON_4430)
- omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1);
+ if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+ omap_i2c_write_reg(dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1);
else
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
- if (dev->rev < OMAP_I2C_REV_2) {
+ if (dev->rev < OMAP_I2C_OMAP1_REV_2) {
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
} else {
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
- /* Flush posted write before the dev->idle store occurs */
+ /* Flush posted write */
omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
}
- dev->idle = 1;
-
- pm_runtime_put_sync(&pdev->dev);
}
static int omap_i2c_init(struct omap_i2c_dev *dev)
@@ -334,8 +320,11 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
unsigned long timeout;
unsigned long internal_clk = 0;
struct clk *fclk;
+ struct omap_i2c_bus_platform_data *pdata;
+
+ pdata = dev->dev->platform_data;
- if (dev->rev >= OMAP_I2C_REV_2) {
+ if (dev->rev >= OMAP_I2C_OMAP1_REV_2) {
/* Disable I2C controller before soft reset */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
@@ -378,12 +367,13 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
* REVISIT: Some wkup sources might not be needed.
*/
dev->westate = OMAP_I2C_WE_ALL;
- omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+ omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
+ dev->westate);
}
}
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
- if (cpu_class_is_omap1()) {
+ if (pdata->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {
/*
* The I2C functional clock is the armxor_ck, so there's
* no need to get "armxor_ck" separately. Now, if OMAP2420
@@ -407,7 +397,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
psc = fclk_rate / 12000000;
}
- if (!(cpu_class_is_omap1() || cpu_is_omap2420())) {
+ if (!(pdata->flags & OMAP_I2C_FLAG_SIMPLE_CLOCK)) {
/*
* HSI2C controller internal clk rate should be 19.2 Mhz for
@@ -415,7 +405,8 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
* to get longer filter period for better noise suppression.
* The filter is iclk (fclk for HS) period.
*/
- if (dev->speed > 400 || cpu_is_omap2430())
+ if (dev->speed > 400 ||
+ pdata->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK)
internal_clk = 19200;
else if (dev->speed > 100)
internal_clk = 9600;
@@ -484,7 +475,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
dev->errata = 0;
- if (cpu_is_omap2430() || cpu_is_omap34xx())
+ if (pdata->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
dev->errata |= I2C_OMAP_ERRATA_I207;
/* Enable interrupts */
@@ -493,7 +484,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
- if (cpu_is_omap34xx()) {
+ if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
dev->pscstate = psc;
dev->scllstate = scll;
dev->sclhstate = sclh;
@@ -642,7 +633,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
int i;
int r;
- omap_i2c_unidle(dev);
+ pm_runtime_get_sync(dev->dev);
r = omap_i2c_wait_for_bb(dev);
if (r < 0)
@@ -665,7 +656,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
omap_i2c_wait_for_bb(dev);
out:
- omap_i2c_idle(dev);
+ pm_runtime_put(dev->dev);
return r;
}
@@ -720,12 +711,12 @@ static inline void i2c_omap_errata_i207(struct omap_i2c_dev *dev, u16 stat)
#ifdef CONFIG_ARCH_OMAP15XX
static irqreturn_t
-omap_i2c_rev1_isr(int this_irq, void *dev_id)
+omap_i2c_omap1_isr(int this_irq, void *dev_id)
{
struct omap_i2c_dev *dev = dev_id;
u16 iv, w;
- if (dev->idle)
+ if (pm_runtime_suspended(dev->dev))
return IRQ_NONE;
iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
@@ -774,7 +765,7 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
return IRQ_HANDLED;
}
#else
-#define omap_i2c_rev1_isr NULL
+#define omap_i2c_omap1_isr NULL
#endif
/*
@@ -813,8 +804,11 @@ omap_i2c_isr(int this_irq, void *dev_id)
u16 bits;
u16 stat, w;
int err, count = 0;
+ struct omap_i2c_bus_platform_data *pdata;
- if (dev->idle)
+ pdata = dev->dev->platform_data;
+
+ if (pm_runtime_suspended(dev->dev))
return IRQ_NONE;
bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
@@ -881,8 +875,8 @@ complete:
* Data reg in 2430, omap3 and
* omap4 is 8 bit wide
*/
- if (cpu_class_is_omap1() ||
- cpu_is_omap2420()) {
+ if (pdata->flags &
+ OMAP_I2C_FLAG_16BIT_DATA_REG) {
if (dev->buf_len) {
*dev->buf++ = w >> 8;
dev->buf_len--;
@@ -924,8 +918,8 @@ complete:
* Data reg in 2430, omap3 and
* omap4 is 8 bit wide
*/
- if (cpu_class_is_omap1() ||
- cpu_is_omap2420()) {
+ if (pdata->flags &
+ OMAP_I2C_FLAG_16BIT_DATA_REG) {
if (dev->buf_len) {
w |= *dev->buf++ << 8;
dev->buf_len--;
@@ -1016,7 +1010,6 @@ omap_i2c_probe(struct platform_device *pdev)
}
dev->speed = speed;
- dev->idle = 1;
dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->base = ioremap(mem->start, resource_size(mem));
@@ -1027,27 +1020,22 @@ omap_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
- if (cpu_is_omap7xx())
- dev->reg_shift = 1;
- else if (cpu_is_omap44xx())
- dev->reg_shift = 0;
- else
- dev->reg_shift = 2;
+ dev->reg_shift = (pdata->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
- if (cpu_is_omap44xx())
- dev->regs = (u8 *) omap4_reg_map;
+ if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+ dev->regs = (u8 *)reg_map_ip_v2;
else
- dev->regs = (u8 *) reg_map;
+ dev->regs = (u8 *)reg_map_ip_v1;
- pm_runtime_enable(&pdev->dev);
- omap_i2c_unidle(dev);
+ pm_runtime_enable(dev->dev);
+ pm_runtime_get_sync(dev->dev);
dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
if (dev->rev <= OMAP_I2C_REV_ON_3430)
dev->errata |= I2C_OMAP3_1P153;
- if (!(cpu_class_is_omap1() || cpu_is_omap2420())) {
+ if (!(pdata->flags & OMAP_I2C_FLAG_NO_FIFO)) {
u16 s;
/* Set up the fifo size - Get total size */
@@ -1059,7 +1047,7 @@ omap_i2c_probe(struct platform_device *pdev)
* size. This is to ensure that we can handle the status on int
* call back latencies.
*/
- if (dev->rev >= OMAP_I2C_REV_ON_4430) {
+ if (dev->rev >= OMAP_I2C_REV_ON_3530_4430) {
dev->fifo_size = 0;
dev->b_hw = 0; /* Disable hardware fixes */
} else {
@@ -1075,7 +1063,8 @@ omap_i2c_probe(struct platform_device *pdev)
/* reset ASAP, clearing any IRQs */
omap_i2c_init(dev);
- isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr;
+ isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
+ omap_i2c_isr;
r = request_irq(dev->irq, isr, 0, pdev->name, dev);
if (r) {
@@ -1083,10 +1072,10 @@ omap_i2c_probe(struct platform_device *pdev)
goto err_unuse_clocks;
}
- dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
- pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+ dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id,
+ pdata->rev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
- omap_i2c_idle(dev);
+ pm_runtime_put(dev->dev);
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
@@ -1110,7 +1099,7 @@ err_free_irq:
free_irq(dev->irq, dev);
err_unuse_clocks:
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
- omap_i2c_idle(dev);
+ pm_runtime_put(dev->dev);
iounmap(dev->base);
err_free_mem:
platform_set_drvdata(pdev, NULL);
@@ -1139,12 +1128,43 @@ omap_i2c_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_RUNTIME
+static int omap_i2c_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
+
+ omap_i2c_idle(_dev);
+
+ return 0;
+}
+
+static int omap_i2c_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
+
+ omap_i2c_unidle(_dev);
+
+ return 0;
+}
+
+static struct dev_pm_ops omap_i2c_pm_ops = {
+ .runtime_suspend = omap_i2c_runtime_suspend,
+ .runtime_resume = omap_i2c_runtime_resume,
+};
+#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
+#else
+#define OMAP_I2C_PM_OPS NULL
+#endif
+
static struct platform_driver omap_i2c_driver = {
.probe = omap_i2c_probe,
.remove = omap_i2c_remove,
.driver = {
.name = "omap_i2c",
.owner = THIS_MODULE,
+ .pm = OMAP_I2C_PM_OPS,
},
};
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index dfa7ae9c1b8e..127051b06921 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -306,7 +306,7 @@ static int __devinit pmcmsptwi_probe(struct platform_device *pldev)
pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
if (pmcmsptwi_data.irq) {
rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
- IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+ IRQF_SHARED | IRQF_SAMPLE_RANDOM,
pldev->name, &pmcmsptwi_data);
if (rc == 0) {
/*
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index f84a63c6dd97..2754cef86a06 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -35,6 +35,8 @@
#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/of_i2c.h>
+#include <linux/of_gpio.h>
#include <asm/irq.h>
@@ -78,6 +80,8 @@ struct s3c24xx_i2c {
struct resource *ioarea;
struct i2c_adapter adap;
+ struct s3c2410_platform_i2c *pdata;
+ int gpios[2];
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
#endif
@@ -95,6 +99,12 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
struct platform_device *pdev = to_platform_device(i2c->dev);
enum s3c24xx_i2c_type type;
+#ifdef CONFIG_OF
+ if (i2c->dev->of_node)
+ return of_device_is_compatible(i2c->dev->of_node,
+ "samsung,s3c2440-i2c");
+#endif
+
type = platform_get_device_id(pdev)->driver_data;
return type == TYPE_S3C2440;
}
@@ -625,7 +635,7 @@ static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted,
static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
{
- struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
+ struct s3c2410_platform_i2c *pdata = i2c->pdata;
unsigned long clkin = clk_get_rate(i2c->clk);
unsigned int divs, div1;
unsigned long target_frequency;
@@ -741,6 +751,49 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
}
#endif
+#ifdef CONFIG_OF
+static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
+{
+ int idx, gpio, ret;
+
+ for (idx = 0; idx < 2; idx++) {
+ gpio = of_get_gpio(i2c->dev->of_node, idx);
+ if (!gpio_is_valid(gpio)) {
+ dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
+ goto free_gpio;
+ }
+
+ ret = gpio_request(gpio, "i2c-bus");
+ if (ret) {
+ dev_err(i2c->dev, "gpio [%d] request failed\n", gpio);
+ goto free_gpio;
+ }
+ }
+ return 0;
+
+free_gpio:
+ while (--idx >= 0)
+ gpio_free(i2c->gpios[idx]);
+ return -EINVAL;
+}
+
+static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
+{
+ unsigned int idx;
+ for (idx = 0; idx < 2; idx++)
+ gpio_free(i2c->gpios[idx]);
+}
+#else
+static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
+{
+ return -EINVAL;
+}
+
+static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
+{
+}
+#endif
+
/* s3c24xx_i2c_init
*
* initialise the controller, set the IO lines and frequency
@@ -754,12 +807,15 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
/* get the plafrom data */
- pdata = i2c->dev->platform_data;
+ pdata = i2c->pdata;
/* inititalise the gpio */
if (pdata->cfg_gpio)
pdata->cfg_gpio(to_platform_device(i2c->dev));
+ else
+ if (s3c24xx_i2c_parse_dt_gpio(i2c))
+ return -EINVAL;
/* write slave address */
@@ -785,6 +841,34 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
return 0;
}
+#ifdef CONFIG_OF
+/* s3c24xx_i2c_parse_dt
+ *
+ * Parse the device tree node and retreive the platform data.
+*/
+
+static void
+s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
+{
+ struct s3c2410_platform_i2c *pdata = i2c->pdata;
+
+ if (!np)
+ return;
+
+ pdata->bus_num = -1; /* i2c bus number is dynamically assigned */
+ of_property_read_u32(np, "samsung,i2c-sda-delay", &pdata->sda_delay);
+ of_property_read_u32(np, "samsung,i2c-slave-addr", &pdata->slave_addr);
+ of_property_read_u32(np, "samsung,i2c-max-bus-freq",
+ (u32 *)&pdata->frequency);
+}
+#else
+static void
+s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
+{
+ return;
+}
+#endif
+
/* s3c24xx_i2c_probe
*
* called by the bus driver when a suitable device is found
@@ -793,14 +877,16 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
static int s3c24xx_i2c_probe(struct platform_device *pdev)
{
struct s3c24xx_i2c *i2c;
- struct s3c2410_platform_i2c *pdata;
+ struct s3c2410_platform_i2c *pdata = NULL;
struct resource *res;
int ret;
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data\n");
- return -EINVAL;
+ if (!pdev->dev.of_node) {
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data\n");
+ return -EINVAL;
+ }
}
i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
@@ -809,6 +895,17 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ i2c->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!i2c->pdata) {
+ ret = -ENOMEM;
+ goto err_noclk;
+ }
+
+ if (pdata)
+ memcpy(i2c->pdata, pdata, sizeof(*pdata));
+ else
+ s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c);
+
strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
i2c->adap.owner = THIS_MODULE;
i2c->adap.algo = &s3c24xx_i2c_algorithm;
@@ -883,7 +980,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_iomap;
}
- ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
+ ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
dev_name(&pdev->dev), i2c);
if (ret != 0) {
@@ -903,7 +1000,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
* being bus 0.
*/
- i2c->adap.nr = pdata->bus_num;
+ i2c->adap.nr = i2c->pdata->bus_num;
+ i2c->adap.dev.of_node = pdev->dev.of_node;
ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
@@ -911,6 +1009,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_cpufreq;
}
+ of_i2c_register_devices(&i2c->adap);
platform_set_drvdata(pdev, i2c);
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
@@ -959,6 +1058,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
iounmap(i2c->regs);
release_resource(i2c->ioarea);
+ s3c24xx_i2c_dt_gpio_free(i2c);
kfree(i2c->ioarea);
kfree(i2c);
@@ -1012,6 +1112,17 @@ static struct platform_device_id s3c24xx_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
+#ifdef CONFIG_OF
+static const struct of_device_id s3c24xx_i2c_match[] = {
+ { .compatible = "samsung,s3c2410-i2c" },
+ { .compatible = "samsung,s3c2440-i2c" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
+#else
+#define s3c24xx_i2c_match NULL
+#endif
+
static struct platform_driver s3c24xx_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
@@ -1020,6 +1131,7 @@ static struct platform_driver s3c24xx_i2c_driver = {
.owner = THIS_MODULE,
.name = "s3c-i2c",
.pm = S3C24XX_DEV_PM_OPS,
+ .of_match_table = s3c24xx_i2c_match,
},
};
diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
index 3cad8fecc3d3..c418c41eff3d 100644
--- a/drivers/i2c/busses/i2c-sh7760.c
+++ b/drivers/i2c/busses/i2c-sh7760.c
@@ -502,7 +502,7 @@ static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
}
OUT32(id, I2CCCR, ret);
- if (request_irq(id->irq, sh7760_i2c_irq, IRQF_DISABLED,
+ if (request_irq(id->irq, sh7760_i2c_irq, 0,
SH7760_I2C_DEVNAME, id)) {
dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
ret = -EBUSY;
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index f633a53b6dbe..675c9692d148 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -543,7 +543,7 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
for (n = res->start; hook && n <= res->end; n++) {
- if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
+ if (request_irq(n, sh_mobile_i2c_isr, 0,
dev_name(&dev->dev), dev)) {
for (n--; n >= res->start; n--)
free_irq(n, dev);
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index 99879617e686..4d44af181f37 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -916,7 +916,7 @@ stu300_probe(struct platform_device *pdev)
}
dev->irq = platform_get_irq(pdev, 0);
- if (request_irq(dev->irq, stu300_irh, IRQF_DISABLED,
+ if (request_irq(dev->irq, stu300_irh, 0,
NAME, dev)) {
ret = -EIO;
goto err_no_irq;
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 3c94c4a81a55..b0505309faa7 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -566,7 +566,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
struct clk *clk;
struct clk *i2c_clk;
const unsigned int *prop;
- void *base;
+ void __iomem *base;
int irq;
int ret = 0;
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 986e5f62debe..91e349c884c5 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -550,7 +550,7 @@ static int __devexit scx200_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver scx200_pci_drv = {
+static struct platform_driver scx200_pci_driver = {
.driver = {
.name = "cs5535-smb",
.owner = THIS_MODULE,
@@ -593,14 +593,14 @@ static int __init scx200_acb_init(void)
return 0;
/* No ISA devices; register the platform driver for PCI-based devices */
- return platform_driver_register(&scx200_pci_drv);
+ return platform_driver_register(&scx200_pci_driver);
}
static void __exit scx200_acb_cleanup(void)
{
struct scx200_acb_iface *iface;
- platform_driver_unregister(&scx200_pci_drv);
+ platform_driver_unregister(&scx200_pci_driver);
mutex_lock(&scx200_acb_list_mutex);
while ((iface = scx200_acb_list) != NULL) {
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 811dbbd9306c..76b6d98bd295 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -681,7 +681,7 @@ config BLK_DEV_IDE_AU1XXX
select IDE_XFER_MODE
choice
prompt "IDE Mode for AMD Alchemy Au1200"
- default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+ default BLK_DEV_IDE_AU1XXX_PIO_DBDMA
depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
config BLK_DEV_IDE_AU1XXX_PIO_DBDMA
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c
index 000a78e5246c..6dede8f366c5 100644
--- a/drivers/ide/at91_ide.c
+++ b/drivers/ide/at91_ide.c
@@ -28,7 +28,7 @@
#include <linux/platform_device.h>
#include <mach/board.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <mach/at91sam9_smc.h>
#define DRV_NAME "at91_ide"
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index fc0f2bd9ca82..4104ea2427c2 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -889,6 +889,8 @@ retest:
break;
case IB_CM_ESTABLISHED:
spin_unlock_irq(&cm_id_priv->lock);
+ if (cm_id_priv->qp_type == IB_QPT_XRC_TGT)
+ break;
ib_send_cm_dreq(cm_id, NULL, 0);
goto retest;
case IB_CM_DREQ_SENT:
@@ -1008,7 +1010,6 @@ static void cm_format_req(struct cm_req_msg *req_msg,
req_msg->service_id = param->service_id;
req_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
cm_req_set_local_qpn(req_msg, cpu_to_be32(param->qp_num));
- cm_req_set_resp_res(req_msg, param->responder_resources);
cm_req_set_init_depth(req_msg, param->initiator_depth);
cm_req_set_remote_resp_timeout(req_msg,
param->remote_cm_response_timeout);
@@ -1017,12 +1018,16 @@ static void cm_format_req(struct cm_req_msg *req_msg,
cm_req_set_starting_psn(req_msg, cpu_to_be32(param->starting_psn));
cm_req_set_local_resp_timeout(req_msg,
param->local_cm_response_timeout);
- cm_req_set_retry_count(req_msg, param->retry_count);
req_msg->pkey = param->primary_path->pkey;
cm_req_set_path_mtu(req_msg, param->primary_path->mtu);
- cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
cm_req_set_max_cm_retries(req_msg, param->max_cm_retries);
- cm_req_set_srq(req_msg, param->srq);
+
+ if (param->qp_type != IB_QPT_XRC_INI) {
+ cm_req_set_resp_res(req_msg, param->responder_resources);
+ cm_req_set_retry_count(req_msg, param->retry_count);
+ cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
+ cm_req_set_srq(req_msg, param->srq);
+ }
if (pri_path->hop_limit <= 1) {
req_msg->primary_local_lid = pri_path->slid;
@@ -1080,7 +1085,8 @@ static int cm_validate_req_param(struct ib_cm_req_param *param)
if (!param->primary_path)
return -EINVAL;
- if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC)
+ if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC &&
+ param->qp_type != IB_QPT_XRC_INI)
return -EINVAL;
if (param->private_data &&
@@ -1601,18 +1607,24 @@ static void cm_format_rep(struct cm_rep_msg *rep_msg,
cm_format_mad_hdr(&rep_msg->hdr, CM_REP_ATTR_ID, cm_id_priv->tid);
rep_msg->local_comm_id = cm_id_priv->id.local_id;
rep_msg->remote_comm_id = cm_id_priv->id.remote_id;
- cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));
rep_msg->resp_resources = param->responder_resources;
- rep_msg->initiator_depth = param->initiator_depth;
cm_rep_set_target_ack_delay(rep_msg,
cm_id_priv->av.port->cm_dev->ack_delay);
cm_rep_set_failover(rep_msg, param->failover_accepted);
- cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
- cm_rep_set_srq(rep_msg, param->srq);
rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
+ if (cm_id_priv->qp_type != IB_QPT_XRC_TGT) {
+ rep_msg->initiator_depth = param->initiator_depth;
+ cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
+ cm_rep_set_srq(rep_msg, param->srq);
+ cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
+ } else {
+ cm_rep_set_srq(rep_msg, 1);
+ cm_rep_set_local_eecn(rep_msg, cpu_to_be32(param->qp_num));
+ }
+
if (param->private_data && param->private_data_len)
memcpy(rep_msg->private_data, param->private_data,
param->private_data_len);
@@ -1660,7 +1672,7 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
cm_id_priv->initiator_depth = param->initiator_depth;
cm_id_priv->responder_resources = param->responder_resources;
cm_id_priv->rq_psn = cm_rep_get_starting_psn(rep_msg);
- cm_id_priv->local_qpn = cm_rep_get_local_qpn(rep_msg);
+ cm_id_priv->local_qpn = cpu_to_be32(param->qp_num & 0xFFFFFF);
out: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
return ret;
@@ -1731,7 +1743,7 @@ error: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
}
EXPORT_SYMBOL(ib_send_cm_rtu);
-static void cm_format_rep_event(struct cm_work *work)
+static void cm_format_rep_event(struct cm_work *work, enum ib_qp_type qp_type)
{
struct cm_rep_msg *rep_msg;
struct ib_cm_rep_event_param *param;
@@ -1740,7 +1752,7 @@ static void cm_format_rep_event(struct cm_work *work)
param = &work->cm_event.param.rep_rcvd;
param->remote_ca_guid = rep_msg->local_ca_guid;
param->remote_qkey = be32_to_cpu(rep_msg->local_qkey);
- param->remote_qpn = be32_to_cpu(cm_rep_get_local_qpn(rep_msg));
+ param->remote_qpn = be32_to_cpu(cm_rep_get_qpn(rep_msg, qp_type));
param->starting_psn = be32_to_cpu(cm_rep_get_starting_psn(rep_msg));
param->responder_resources = rep_msg->initiator_depth;
param->initiator_depth = rep_msg->resp_resources;
@@ -1808,7 +1820,7 @@ static int cm_rep_handler(struct cm_work *work)
return -EINVAL;
}
- cm_format_rep_event(work);
+ cm_format_rep_event(work, cm_id_priv->qp_type);
spin_lock_irq(&cm_id_priv->lock);
switch (cm_id_priv->id.state) {
@@ -1823,7 +1835,7 @@ static int cm_rep_handler(struct cm_work *work)
cm_id_priv->timewait_info->work.remote_id = rep_msg->local_comm_id;
cm_id_priv->timewait_info->remote_ca_guid = rep_msg->local_ca_guid;
- cm_id_priv->timewait_info->remote_qpn = cm_rep_get_local_qpn(rep_msg);
+ cm_id_priv->timewait_info->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
spin_lock(&cm.lock);
/* Check for duplicate REP. */
@@ -1850,7 +1862,7 @@ static int cm_rep_handler(struct cm_work *work)
cm_id_priv->id.state = IB_CM_REP_RCVD;
cm_id_priv->id.remote_id = rep_msg->local_comm_id;
- cm_id_priv->remote_qpn = cm_rep_get_local_qpn(rep_msg);
+ cm_id_priv->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
cm_id_priv->initiator_depth = rep_msg->resp_resources;
cm_id_priv->responder_resources = rep_msg->initiator_depth;
cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);
@@ -3492,7 +3504,8 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
qp_attr->path_mtu = cm_id_priv->path_mtu;
qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
- if (cm_id_priv->qp_type == IB_QPT_RC) {
+ if (cm_id_priv->qp_type == IB_QPT_RC ||
+ cm_id_priv->qp_type == IB_QPT_XRC_TGT) {
*qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER;
qp_attr->max_dest_rd_atomic =
@@ -3537,15 +3550,21 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
*qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
- if (cm_id_priv->qp_type == IB_QPT_RC) {
- *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
- IB_QP_RNR_RETRY |
+ switch (cm_id_priv->qp_type) {
+ case IB_QPT_RC:
+ case IB_QPT_XRC_INI:
+ *qp_attr_mask |= IB_QP_RETRY_CNT | IB_QP_RNR_RETRY |
IB_QP_MAX_QP_RD_ATOMIC;
- qp_attr->timeout = cm_id_priv->av.timeout;
qp_attr->retry_cnt = cm_id_priv->retry_count;
qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
- qp_attr->max_rd_atomic =
- cm_id_priv->initiator_depth;
+ qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+ /* fall through */
+ case IB_QPT_XRC_TGT:
+ *qp_attr_mask |= IB_QP_TIMEOUT;
+ qp_attr->timeout = cm_id_priv->av.timeout;
+ break;
+ default:
+ break;
}
if (cm_id_priv->alt_av.ah_attr.dlid) {
*qp_attr_mask |= IB_QP_PATH_MIG_STATE;
diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h
index 7e63c08f697c..505db2a59e7f 100644
--- a/drivers/infiniband/core/cm_msgs.h
+++ b/drivers/infiniband/core/cm_msgs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Intel Corporation. All rights reserved.
+ * Copyright (c) 2004, 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
* Copyright (c) 2004 Voltaire Corporation. All rights reserved.
*
@@ -86,7 +86,7 @@ struct cm_req_msg {
__be16 pkey;
/* path MTU:4, RDC exists:1, RNR retry count:3. */
u8 offset50;
- /* max CM Retries:4, SRQ:1, rsvd:3 */
+ /* max CM Retries:4, SRQ:1, extended transport type:3 */
u8 offset51;
__be16 primary_local_lid;
@@ -175,6 +175,11 @@ static inline enum ib_qp_type cm_req_get_qp_type(struct cm_req_msg *req_msg)
switch(transport_type) {
case 0: return IB_QPT_RC;
case 1: return IB_QPT_UC;
+ case 3:
+ switch (req_msg->offset51 & 0x7) {
+ case 1: return IB_QPT_XRC_TGT;
+ default: return 0;
+ }
default: return 0;
}
}
@@ -188,6 +193,12 @@ static inline void cm_req_set_qp_type(struct cm_req_msg *req_msg,
req_msg->offset40) &
0xFFFFFFF9) | 0x2);
break;
+ case IB_QPT_XRC_INI:
+ req_msg->offset40 = cpu_to_be32((be32_to_cpu(
+ req_msg->offset40) &
+ 0xFFFFFFF9) | 0x6);
+ req_msg->offset51 = (req_msg->offset51 & 0xF8) | 1;
+ break;
default:
req_msg->offset40 = cpu_to_be32(be32_to_cpu(
req_msg->offset40) &
@@ -527,6 +538,23 @@ static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, __be32 qpn)
(be32_to_cpu(rep_msg->offset12) & 0x000000FF));
}
+static inline __be32 cm_rep_get_local_eecn(struct cm_rep_msg *rep_msg)
+{
+ return cpu_to_be32(be32_to_cpu(rep_msg->offset16) >> 8);
+}
+
+static inline void cm_rep_set_local_eecn(struct cm_rep_msg *rep_msg, __be32 eecn)
+{
+ rep_msg->offset16 = cpu_to_be32((be32_to_cpu(eecn) << 8) |
+ (be32_to_cpu(rep_msg->offset16) & 0x000000FF));
+}
+
+static inline __be32 cm_rep_get_qpn(struct cm_rep_msg *rep_msg, enum ib_qp_type qp_type)
+{
+ return (qp_type == IB_QPT_XRC_INI) ?
+ cm_rep_get_local_eecn(rep_msg) : cm_rep_get_local_qpn(rep_msg);
+}
+
static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
{
return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index ca4c5dcd7133..872b1842598a 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -81,6 +81,7 @@ static DEFINE_IDR(sdp_ps);
static DEFINE_IDR(tcp_ps);
static DEFINE_IDR(udp_ps);
static DEFINE_IDR(ipoib_ps);
+static DEFINE_IDR(ib_ps);
struct cma_device {
struct list_head list;
@@ -1179,6 +1180,15 @@ static void cma_set_req_event_data(struct rdma_cm_event *event,
event->param.conn.qp_num = req_data->remote_qpn;
}
+static int cma_check_req_qp_type(struct rdma_cm_id *id, struct ib_cm_event *ib_event)
+{
+ return (((ib_event->event == IB_CM_REQ_RECEIVED) ||
+ (ib_event->param.req_rcvd.qp_type == id->qp_type)) ||
+ ((ib_event->event == IB_CM_SIDR_REQ_RECEIVED) &&
+ (id->qp_type == IB_QPT_UD)) ||
+ (!id->qp_type));
+}
+
static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
{
struct rdma_id_private *listen_id, *conn_id;
@@ -1186,13 +1196,16 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
int offset, ret;
listen_id = cm_id->context;
+ if (!cma_check_req_qp_type(&listen_id->id, ib_event))
+ return -EINVAL;
+
if (cma_disable_callback(listen_id, RDMA_CM_LISTEN))
return -ECONNABORTED;
memset(&event, 0, sizeof event);
offset = cma_user_data_offset(listen_id->id.ps);
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
- if (listen_id->id.qp_type == IB_QPT_UD) {
+ if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) {
conn_id = cma_new_udp_id(&listen_id->id, ib_event);
event.param.ud.private_data = ib_event->private_data + offset;
event.param.ud.private_data_len =
@@ -1328,6 +1341,8 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
switch (iw_event->status) {
case 0:
event.event = RDMA_CM_EVENT_ESTABLISHED;
+ event.param.conn.initiator_depth = iw_event->ird;
+ event.param.conn.responder_resources = iw_event->ord;
break;
case -ECONNRESET:
case -ECONNREFUSED:
@@ -1343,6 +1358,8 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
break;
case IW_CM_EVENT_ESTABLISHED:
event.event = RDMA_CM_EVENT_ESTABLISHED;
+ event.param.conn.initiator_depth = iw_event->ird;
+ event.param.conn.responder_resources = iw_event->ord;
break;
default:
BUG_ON(1);
@@ -1433,8 +1450,8 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
event.param.conn.private_data = iw_event->private_data;
event.param.conn.private_data_len = iw_event->private_data_len;
- event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
- event.param.conn.responder_resources = attr.max_qp_rd_atom;
+ event.param.conn.initiator_depth = iw_event->ird;
+ event.param.conn.responder_resources = iw_event->ord;
/*
* Protect against the user destroying conn_id from another thread
@@ -2234,6 +2251,9 @@ static int cma_get_port(struct rdma_id_private *id_priv)
case RDMA_PS_IPOIB:
ps = &ipoib_ps;
break;
+ case RDMA_PS_IB:
+ ps = &ib_ps;
+ break;
default:
return -EPROTONOSUPPORT;
}
@@ -2569,7 +2589,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
req.service_id = cma_get_service_id(id_priv->id.ps,
(struct sockaddr *) &route->addr.dst_addr);
req.qp_num = id_priv->qp_num;
- req.qp_type = IB_QPT_RC;
+ req.qp_type = id_priv->id.qp_type;
req.starting_psn = id_priv->seq_num;
req.responder_resources = conn_param->responder_resources;
req.initiator_depth = conn_param->initiator_depth;
@@ -2616,14 +2636,16 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
if (ret)
goto out;
- iw_param.ord = conn_param->initiator_depth;
- iw_param.ird = conn_param->responder_resources;
- iw_param.private_data = conn_param->private_data;
- iw_param.private_data_len = conn_param->private_data_len;
- if (id_priv->id.qp)
+ if (conn_param) {
+ iw_param.ord = conn_param->initiator_depth;
+ iw_param.ird = conn_param->responder_resources;
+ iw_param.private_data = conn_param->private_data;
+ iw_param.private_data_len = conn_param->private_data_len;
+ iw_param.qpn = id_priv->id.qp ? id_priv->qp_num : conn_param->qp_num;
+ } else {
+ memset(&iw_param, 0, sizeof iw_param);
iw_param.qpn = id_priv->qp_num;
- else
- iw_param.qpn = conn_param->qp_num;
+ }
ret = iw_cm_connect(cm_id, &iw_param);
out:
if (ret) {
@@ -2765,14 +2787,20 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
switch (rdma_node_get_transport(id->device->node_type)) {
case RDMA_TRANSPORT_IB:
- if (id->qp_type == IB_QPT_UD)
- ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
- conn_param->private_data,
- conn_param->private_data_len);
- else if (conn_param)
- ret = cma_accept_ib(id_priv, conn_param);
- else
- ret = cma_rep_recv(id_priv);
+ if (id->qp_type == IB_QPT_UD) {
+ if (conn_param)
+ ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+ conn_param->private_data,
+ conn_param->private_data_len);
+ else
+ ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+ NULL, 0);
+ } else {
+ if (conn_param)
+ ret = cma_accept_ib(id_priv, conn_param);
+ else
+ ret = cma_rep_recv(id_priv);
+ }
break;
case RDMA_TRANSPORT_IWARP:
ret = cma_accept_iw(id_priv, conn_param);
@@ -3460,6 +3488,7 @@ static void __exit cma_cleanup(void)
idr_destroy(&tcp_ps);
idr_destroy(&udp_ps);
idr_destroy(&ipoib_ps);
+ idr_destroy(&ib_ps);
}
module_init(cma_init);
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index b4d8672a3e4e..056389229ea7 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -1596,6 +1596,9 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
mad->mad_hdr.class_version].class;
if (!class)
goto out;
+ if (convert_mgmt_class(mad->mad_hdr.mgmt_class) >=
+ IB_MGMT_MAX_METHODS)
+ goto out;
method = class->method_table[convert_mgmt_class(
mad->mad_hdr.mgmt_class)];
if (method)
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 9ab5df72df7b..2b59b72b57f9 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -185,17 +185,35 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,
if (ret)
return ret;
+ rate = (25 * attr.active_speed) / 10;
+
switch (attr.active_speed) {
- case 2: speed = " DDR"; break;
- case 4: speed = " QDR"; break;
+ case 2:
+ speed = " DDR";
+ break;
+ case 4:
+ speed = " QDR";
+ break;
+ case 8:
+ speed = " FDR10";
+ rate = 10;
+ break;
+ case 16:
+ speed = " FDR";
+ rate = 14;
+ break;
+ case 32:
+ speed = " EDR";
+ rate = 25;
+ break;
}
- rate = 25 * ib_width_enum_to_int(attr.active_width) * attr.active_speed;
+ rate *= ib_width_enum_to_int(attr.active_width);
if (rate < 0)
return -EINVAL;
return sprintf(buf, "%d%s Gb/sec (%dX%s)\n",
- rate / 10, rate % 10 ? ".5" : "",
+ rate, (attr.active_speed == 1) ? ".5" : "",
ib_width_enum_to_int(attr.active_width), speed);
}
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 08f948df8fa9..b8a0b4a7811b 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1122,7 +1122,7 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
if (copy_from_user(&hdr, buf, sizeof(hdr)))
return -EFAULT;
- if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
+ if (hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
return -EINVAL;
if (hdr.in + sizeof(hdr) > len)
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 71be5eebd683..b69307f4f6d0 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -276,7 +276,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,
ucma_set_event_context(ctx, event, uevent);
uevent->resp.event = event->event;
uevent->resp.status = event->status;
- if (cm_id->ps == RDMA_PS_UDP || cm_id->ps == RDMA_PS_IPOIB)
+ if (cm_id->qp_type == IB_QPT_UD)
ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
else
ucma_copy_conn_event(&uevent->resp.param.conn,
@@ -377,6 +377,9 @@ static int ucma_get_qp_type(struct rdma_ucm_create_id *cmd, enum ib_qp_type *qp_
case RDMA_PS_IPOIB:
*qp_type = IB_QPT_UD;
return 0;
+ case RDMA_PS_IB:
+ *qp_type = cmd->qp_type;
+ return 0;
default:
return -EINVAL;
}
@@ -1270,7 +1273,7 @@ static ssize_t ucma_write(struct file *filp, const char __user *buf,
if (copy_from_user(&hdr, buf, sizeof(hdr)))
return -EFAULT;
- if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
+ if (hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
return -EINVAL;
if (hdr.in + sizeof(hdr) > len)
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index b645e558876f..9155f91d66bf 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -136,7 +136,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
down_write(&current->mm->mmap_sem);
- locked = npages + current->mm->locked_vm;
+ locked = npages + current->mm->pinned_vm;
lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
@@ -206,7 +206,7 @@ out:
__ib_umem_release(context->device, umem, 0);
kfree(umem);
} else
- current->mm->locked_vm = locked;
+ current->mm->pinned_vm = locked;
up_write(&current->mm->mmap_sem);
if (vma_list)
@@ -222,7 +222,7 @@ static void ib_umem_account(struct work_struct *work)
struct ib_umem *umem = container_of(work, struct ib_umem, work);
down_write(&umem->mm->mmap_sem);
- umem->mm->locked_vm -= umem->diff;
+ umem->mm->pinned_vm -= umem->diff;
up_write(&umem->mm->mmap_sem);
mmput(umem->mm);
kfree(umem);
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 8d261b6ea5fe..07db22997e97 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -458,8 +458,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
goto err;
}
- if (packet->mad.hdr.id < 0 ||
- packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
+ if (packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
ret = -EINVAL;
goto err;
}
@@ -703,7 +702,7 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
mutex_lock(&file->port->file_mutex);
mutex_lock(&file->mutex);
- if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
+ if (id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
ret = -EINVAL;
goto out;
}
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index a078e5624d22..5bcb2afd3dcb 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -76,6 +76,8 @@ struct ib_uverbs_device {
struct ib_device *ib_dev;
int devnum;
struct cdev cdev;
+ struct rb_root xrcd_tree;
+ struct mutex xrcd_tree_mutex;
};
struct ib_uverbs_event_file {
@@ -120,6 +122,16 @@ struct ib_uevent_object {
u32 events_reported;
};
+struct ib_uxrcd_object {
+ struct ib_uobject uobject;
+ atomic_t refcnt;
+};
+
+struct ib_usrq_object {
+ struct ib_uevent_object uevent;
+ struct ib_uxrcd_object *uxrcd;
+};
+
struct ib_uqp_object {
struct ib_uevent_object uevent;
struct list_head mcast_list;
@@ -142,6 +154,7 @@ extern struct idr ib_uverbs_ah_idr;
extern struct idr ib_uverbs_cq_idr;
extern struct idr ib_uverbs_qp_idr;
extern struct idr ib_uverbs_srq_idr;
+extern struct idr ib_uverbs_xrcd_idr;
void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
@@ -161,6 +174,7 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_event_handler(struct ib_event_handler *handler,
struct ib_event *event);
+void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev, struct ib_xrcd *xrcd);
#define IB_UVERBS_DECLARE_CMD(name) \
ssize_t ib_uverbs_##name(struct ib_uverbs_file *file, \
@@ -181,6 +195,7 @@ IB_UVERBS_DECLARE_CMD(poll_cq);
IB_UVERBS_DECLARE_CMD(req_notify_cq);
IB_UVERBS_DECLARE_CMD(destroy_cq);
IB_UVERBS_DECLARE_CMD(create_qp);
+IB_UVERBS_DECLARE_CMD(open_qp);
IB_UVERBS_DECLARE_CMD(query_qp);
IB_UVERBS_DECLARE_CMD(modify_qp);
IB_UVERBS_DECLARE_CMD(destroy_qp);
@@ -195,5 +210,8 @@ IB_UVERBS_DECLARE_CMD(create_srq);
IB_UVERBS_DECLARE_CMD(modify_srq);
IB_UVERBS_DECLARE_CMD(query_srq);
IB_UVERBS_DECLARE_CMD(destroy_srq);
+IB_UVERBS_DECLARE_CMD(create_xsrq);
+IB_UVERBS_DECLARE_CMD(open_xrcd);
+IB_UVERBS_DECLARE_CMD(close_xrcd);
#endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index c42699285f8e..254f1649c734 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -47,6 +47,7 @@ static struct lock_class_key cq_lock_key;
static struct lock_class_key qp_lock_key;
static struct lock_class_key ah_lock_key;
static struct lock_class_key srq_lock_key;
+static struct lock_class_key xrcd_lock_key;
#define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \
do { \
@@ -255,6 +256,18 @@ static void put_srq_read(struct ib_srq *srq)
put_uobj_read(srq->uobject);
}
+static struct ib_xrcd *idr_read_xrcd(int xrcd_handle, struct ib_ucontext *context,
+ struct ib_uobject **uobj)
+{
+ *uobj = idr_read_uobj(&ib_uverbs_xrcd_idr, xrcd_handle, context, 0);
+ return *uobj ? (*uobj)->object : NULL;
+}
+
+static void put_xrcd_read(struct ib_uobject *uobj)
+{
+ put_uobj_read(uobj);
+}
+
ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
const char __user *buf,
int in_len, int out_len)
@@ -298,6 +311,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
INIT_LIST_HEAD(&ucontext->qp_list);
INIT_LIST_HEAD(&ucontext->srq_list);
INIT_LIST_HEAD(&ucontext->ah_list);
+ INIT_LIST_HEAD(&ucontext->xrcd_list);
ucontext->closing = 0;
resp.num_comp_vectors = file->device->num_comp_vectors;
@@ -579,6 +593,310 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
return in_len;
}
+struct xrcd_table_entry {
+ struct rb_node node;
+ struct ib_xrcd *xrcd;
+ struct inode *inode;
+};
+
+static int xrcd_table_insert(struct ib_uverbs_device *dev,
+ struct inode *inode,
+ struct ib_xrcd *xrcd)
+{
+ struct xrcd_table_entry *entry, *scan;
+ struct rb_node **p = &dev->xrcd_tree.rb_node;
+ struct rb_node *parent = NULL;
+
+ entry = kmalloc(sizeof *entry, GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ entry->xrcd = xrcd;
+ entry->inode = inode;
+
+ while (*p) {
+ parent = *p;
+ scan = rb_entry(parent, struct xrcd_table_entry, node);
+
+ if (inode < scan->inode) {
+ p = &(*p)->rb_left;
+ } else if (inode > scan->inode) {
+ p = &(*p)->rb_right;
+ } else {
+ kfree(entry);
+ return -EEXIST;
+ }
+ }
+
+ rb_link_node(&entry->node, parent, p);
+ rb_insert_color(&entry->node, &dev->xrcd_tree);
+ igrab(inode);
+ return 0;
+}
+
+static struct xrcd_table_entry *xrcd_table_search(struct ib_uverbs_device *dev,
+ struct inode *inode)
+{
+ struct xrcd_table_entry *entry;
+ struct rb_node *p = dev->xrcd_tree.rb_node;
+
+ while (p) {
+ entry = rb_entry(p, struct xrcd_table_entry, node);
+
+ if (inode < entry->inode)
+ p = p->rb_left;
+ else if (inode > entry->inode)
+ p = p->rb_right;
+ else
+ return entry;
+ }
+
+ return NULL;
+}
+
+static struct ib_xrcd *find_xrcd(struct ib_uverbs_device *dev, struct inode *inode)
+{
+ struct xrcd_table_entry *entry;
+
+ entry = xrcd_table_search(dev, inode);
+ if (!entry)
+ return NULL;
+
+ return entry->xrcd;
+}
+
+static void xrcd_table_delete(struct ib_uverbs_device *dev,
+ struct inode *inode)
+{
+ struct xrcd_table_entry *entry;
+
+ entry = xrcd_table_search(dev, inode);
+ if (entry) {
+ iput(inode);
+ rb_erase(&entry->node, &dev->xrcd_tree);
+ kfree(entry);
+ }
+}
+
+ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_open_xrcd cmd;
+ struct ib_uverbs_open_xrcd_resp resp;
+ struct ib_udata udata;
+ struct ib_uxrcd_object *obj;
+ struct ib_xrcd *xrcd = NULL;
+ struct file *f = NULL;
+ struct inode *inode = NULL;
+ int ret = 0;
+ int new_xrcd = 0;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ INIT_UDATA(&udata, buf + sizeof cmd,
+ (unsigned long) cmd.response + sizeof resp,
+ in_len - sizeof cmd, out_len - sizeof resp);
+
+ mutex_lock(&file->device->xrcd_tree_mutex);
+
+ if (cmd.fd != -1) {
+ /* search for file descriptor */
+ f = fget(cmd.fd);
+ if (!f) {
+ ret = -EBADF;
+ goto err_tree_mutex_unlock;
+ }
+
+ inode = f->f_dentry->d_inode;
+ if (!inode) {
+ ret = -EBADF;
+ goto err_tree_mutex_unlock;
+ }
+
+ xrcd = find_xrcd(file->device, inode);
+ if (!xrcd && !(cmd.oflags & O_CREAT)) {
+ /* no file descriptor. Need CREATE flag */
+ ret = -EAGAIN;
+ goto err_tree_mutex_unlock;
+ }
+
+ if (xrcd && cmd.oflags & O_EXCL) {
+ ret = -EINVAL;
+ goto err_tree_mutex_unlock;
+ }
+ }
+
+ obj = kmalloc(sizeof *obj, GFP_KERNEL);
+ if (!obj) {
+ ret = -ENOMEM;
+ goto err_tree_mutex_unlock;
+ }
+
+ init_uobj(&obj->uobject, 0, file->ucontext, &xrcd_lock_key);
+
+ down_write(&obj->uobject.mutex);
+
+ if (!xrcd) {
+ xrcd = file->device->ib_dev->alloc_xrcd(file->device->ib_dev,
+ file->ucontext, &udata);
+ if (IS_ERR(xrcd)) {
+ ret = PTR_ERR(xrcd);
+ goto err;
+ }
+
+ xrcd->inode = inode;
+ xrcd->device = file->device->ib_dev;
+ atomic_set(&xrcd->usecnt, 0);
+ mutex_init(&xrcd->tgt_qp_mutex);
+ INIT_LIST_HEAD(&xrcd->tgt_qp_list);
+ new_xrcd = 1;
+ }
+
+ atomic_set(&obj->refcnt, 0);
+ obj->uobject.object = xrcd;
+ ret = idr_add_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
+ if (ret)
+ goto err_idr;
+
+ memset(&resp, 0, sizeof resp);
+ resp.xrcd_handle = obj->uobject.id;
+
+ if (inode) {
+ if (new_xrcd) {
+ /* create new inode/xrcd table entry */
+ ret = xrcd_table_insert(file->device, inode, xrcd);
+ if (ret)
+ goto err_insert_xrcd;
+ }
+ atomic_inc(&xrcd->usecnt);
+ }
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+ goto err_copy;
+ }
+
+ if (f)
+ fput(f);
+
+ mutex_lock(&file->mutex);
+ list_add_tail(&obj->uobject.list, &file->ucontext->xrcd_list);
+ mutex_unlock(&file->mutex);
+
+ obj->uobject.live = 1;
+ up_write(&obj->uobject.mutex);
+
+ mutex_unlock(&file->device->xrcd_tree_mutex);
+ return in_len;
+
+err_copy:
+ if (inode) {
+ if (new_xrcd)
+ xrcd_table_delete(file->device, inode);
+ atomic_dec(&xrcd->usecnt);
+ }
+
+err_insert_xrcd:
+ idr_remove_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
+
+err_idr:
+ ib_dealloc_xrcd(xrcd);
+
+err:
+ put_uobj_write(&obj->uobject);
+
+err_tree_mutex_unlock:
+ if (f)
+ fput(f);
+
+ mutex_unlock(&file->device->xrcd_tree_mutex);
+
+ return ret;
+}
+
+ssize_t ib_uverbs_close_xrcd(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_close_xrcd cmd;
+ struct ib_uobject *uobj;
+ struct ib_xrcd *xrcd = NULL;
+ struct inode *inode = NULL;
+ struct ib_uxrcd_object *obj;
+ int live;
+ int ret = 0;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ mutex_lock(&file->device->xrcd_tree_mutex);
+ uobj = idr_write_uobj(&ib_uverbs_xrcd_idr, cmd.xrcd_handle, file->ucontext);
+ if (!uobj) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ xrcd = uobj->object;
+ inode = xrcd->inode;
+ obj = container_of(uobj, struct ib_uxrcd_object, uobject);
+ if (atomic_read(&obj->refcnt)) {
+ put_uobj_write(uobj);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (!inode || atomic_dec_and_test(&xrcd->usecnt)) {
+ ret = ib_dealloc_xrcd(uobj->object);
+ if (!ret)
+ uobj->live = 0;
+ }
+
+ live = uobj->live;
+ if (inode && ret)
+ atomic_inc(&xrcd->usecnt);
+
+ put_uobj_write(uobj);
+
+ if (ret)
+ goto out;
+
+ if (inode && !live)
+ xrcd_table_delete(file->device, inode);
+
+ idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+ mutex_lock(&file->mutex);
+ list_del(&uobj->list);
+ mutex_unlock(&file->mutex);
+
+ put_uobj(uobj);
+ ret = in_len;
+
+out:
+ mutex_unlock(&file->device->xrcd_tree_mutex);
+ return ret;
+}
+
+void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev,
+ struct ib_xrcd *xrcd)
+{
+ struct inode *inode;
+
+ inode = xrcd->inode;
+ if (inode && !atomic_dec_and_test(&xrcd->usecnt))
+ return;
+
+ ib_dealloc_xrcd(xrcd);
+
+ if (inode)
+ xrcd_table_delete(dev, inode);
+}
+
ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
@@ -1052,9 +1370,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
struct ib_uverbs_create_qp_resp resp;
struct ib_udata udata;
struct ib_uqp_object *obj;
- struct ib_pd *pd;
- struct ib_cq *scq, *rcq;
- struct ib_srq *srq;
+ struct ib_device *device;
+ struct ib_pd *pd = NULL;
+ struct ib_xrcd *xrcd = NULL;
+ struct ib_uobject *uninitialized_var(xrcd_uobj);
+ struct ib_cq *scq = NULL, *rcq = NULL;
+ struct ib_srq *srq = NULL;
struct ib_qp *qp;
struct ib_qp_init_attr attr;
int ret;
@@ -1076,15 +1397,39 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
down_write(&obj->uevent.uobject.mutex);
- srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
- pd = idr_read_pd(cmd.pd_handle, file->ucontext);
- scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
- rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
- scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+ if (cmd.qp_type == IB_QPT_XRC_TGT) {
+ xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+ if (!xrcd) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+ device = xrcd->device;
+ } else {
+ pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+ scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
+ if (!pd || !scq) {
+ ret = -EINVAL;
+ goto err_put;
+ }
- if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
- ret = -EINVAL;
- goto err_put;
+ if (cmd.qp_type == IB_QPT_XRC_INI) {
+ cmd.max_recv_wr = cmd.max_recv_sge = 0;
+ } else {
+ if (cmd.is_srq) {
+ srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+ if (!srq || srq->srq_type != IB_SRQT_BASIC) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+ }
+ rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ?
+ scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+ if (!rcq) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+ }
+ device = pd->device;
}
attr.event_handler = ib_uverbs_qp_event_handler;
@@ -1092,6 +1437,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
attr.send_cq = scq;
attr.recv_cq = rcq;
attr.srq = srq;
+ attr.xrcd = xrcd;
attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
attr.qp_type = cmd.qp_type;
attr.create_flags = 0;
@@ -1106,26 +1452,34 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
INIT_LIST_HEAD(&obj->uevent.event_list);
INIT_LIST_HEAD(&obj->mcast_list);
- qp = pd->device->create_qp(pd, &attr, &udata);
+ if (cmd.qp_type == IB_QPT_XRC_TGT)
+ qp = ib_create_qp(pd, &attr);
+ else
+ qp = device->create_qp(pd, &attr, &udata);
+
if (IS_ERR(qp)) {
ret = PTR_ERR(qp);
goto err_put;
}
- qp->device = pd->device;
- qp->pd = pd;
- qp->send_cq = attr.send_cq;
- qp->recv_cq = attr.recv_cq;
- qp->srq = attr.srq;
- qp->uobject = &obj->uevent.uobject;
- qp->event_handler = attr.event_handler;
- qp->qp_context = attr.qp_context;
- qp->qp_type = attr.qp_type;
- atomic_inc(&pd->usecnt);
- atomic_inc(&attr.send_cq->usecnt);
- atomic_inc(&attr.recv_cq->usecnt);
- if (attr.srq)
- atomic_inc(&attr.srq->usecnt);
+ if (cmd.qp_type != IB_QPT_XRC_TGT) {
+ qp->real_qp = qp;
+ qp->device = device;
+ qp->pd = pd;
+ qp->send_cq = attr.send_cq;
+ qp->recv_cq = attr.recv_cq;
+ qp->srq = attr.srq;
+ qp->event_handler = attr.event_handler;
+ qp->qp_context = attr.qp_context;
+ qp->qp_type = attr.qp_type;
+ atomic_inc(&pd->usecnt);
+ atomic_inc(&attr.send_cq->usecnt);
+ if (attr.recv_cq)
+ atomic_inc(&attr.recv_cq->usecnt);
+ if (attr.srq)
+ atomic_inc(&attr.srq->usecnt);
+ }
+ qp->uobject = &obj->uevent.uobject;
obj->uevent.uobject.object = qp;
ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
@@ -1147,9 +1501,13 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
goto err_copy;
}
- put_pd_read(pd);
- put_cq_read(scq);
- if (rcq != scq)
+ if (xrcd)
+ put_xrcd_read(xrcd_uobj);
+ if (pd)
+ put_pd_read(pd);
+ if (scq)
+ put_cq_read(scq);
+ if (rcq && rcq != scq)
put_cq_read(rcq);
if (srq)
put_srq_read(srq);
@@ -1171,6 +1529,8 @@ err_destroy:
ib_destroy_qp(qp);
err_put:
+ if (xrcd)
+ put_xrcd_read(xrcd_uobj);
if (pd)
put_pd_read(pd);
if (scq)
@@ -1184,6 +1544,98 @@ err_put:
return ret;
}
+ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len, int out_len)
+{
+ struct ib_uverbs_open_qp cmd;
+ struct ib_uverbs_create_qp_resp resp;
+ struct ib_udata udata;
+ struct ib_uqp_object *obj;
+ struct ib_xrcd *xrcd;
+ struct ib_uobject *uninitialized_var(xrcd_uobj);
+ struct ib_qp *qp;
+ struct ib_qp_open_attr attr;
+ int ret;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ INIT_UDATA(&udata, buf + sizeof cmd,
+ (unsigned long) cmd.response + sizeof resp,
+ in_len - sizeof cmd, out_len - sizeof resp);
+
+ obj = kmalloc(sizeof *obj, GFP_KERNEL);
+ if (!obj)
+ return -ENOMEM;
+
+ init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
+ down_write(&obj->uevent.uobject.mutex);
+
+ xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+ if (!xrcd) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+
+ attr.event_handler = ib_uverbs_qp_event_handler;
+ attr.qp_context = file;
+ attr.qp_num = cmd.qpn;
+ attr.qp_type = cmd.qp_type;
+
+ obj->uevent.events_reported = 0;
+ INIT_LIST_HEAD(&obj->uevent.event_list);
+ INIT_LIST_HEAD(&obj->mcast_list);
+
+ qp = ib_open_qp(xrcd, &attr);
+ if (IS_ERR(qp)) {
+ ret = PTR_ERR(qp);
+ goto err_put;
+ }
+
+ qp->uobject = &obj->uevent.uobject;
+
+ obj->uevent.uobject.object = qp;
+ ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+ if (ret)
+ goto err_destroy;
+
+ memset(&resp, 0, sizeof resp);
+ resp.qpn = qp->qp_num;
+ resp.qp_handle = obj->uevent.uobject.id;
+
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+ goto err_remove;
+ }
+
+ put_xrcd_read(xrcd_uobj);
+
+ mutex_lock(&file->mutex);
+ list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
+ mutex_unlock(&file->mutex);
+
+ obj->uevent.uobject.live = 1;
+
+ up_write(&obj->uevent.uobject.mutex);
+
+ return in_len;
+
+err_remove:
+ idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+
+err_destroy:
+ ib_destroy_qp(qp);
+
+err_put:
+ put_xrcd_read(xrcd_uobj);
+ put_uobj_write(&obj->uevent.uobject);
+ return ret;
+}
+
ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
@@ -1284,6 +1736,20 @@ out:
return ret ? ret : in_len;
}
+/* Remove ignored fields set in the attribute mask */
+static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
+{
+ switch (qp_type) {
+ case IB_QPT_XRC_INI:
+ return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER);
+ case IB_QPT_XRC_TGT:
+ return mask & ~(IB_QP_MAX_QP_RD_ATOMIC | IB_QP_RETRY_CNT |
+ IB_QP_RNR_RETRY);
+ default:
+ return mask;
+ }
+}
+
ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
@@ -1356,7 +1822,12 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;
- ret = qp->device->modify_qp(qp, attr, cmd.attr_mask, &udata);
+ if (qp->real_qp == qp) {
+ ret = qp->device->modify_qp(qp, attr,
+ modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+ } else {
+ ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
+ }
put_qp_read(qp);
@@ -1553,7 +2024,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
}
resp.bad_wr = 0;
- ret = qp->device->post_send(qp, wr, &bad_wr);
+ ret = qp->device->post_send(qp->real_qp, wr, &bad_wr);
if (ret)
for (next = wr; next; next = next->next) {
++resp.bad_wr;
@@ -1691,7 +2162,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
goto out;
resp.bad_wr = 0;
- ret = qp->device->post_recv(qp, wr, &bad_wr);
+ ret = qp->device->post_recv(qp->real_qp, wr, &bad_wr);
put_qp_read(qp);
@@ -1975,107 +2446,199 @@ out_put:
return ret ? ret : in_len;
}
-ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
- const char __user *buf, int in_len,
- int out_len)
+int __uverbs_create_xsrq(struct ib_uverbs_file *file,
+ struct ib_uverbs_create_xsrq *cmd,
+ struct ib_udata *udata)
{
- struct ib_uverbs_create_srq cmd;
struct ib_uverbs_create_srq_resp resp;
- struct ib_udata udata;
- struct ib_uevent_object *obj;
+ struct ib_usrq_object *obj;
struct ib_pd *pd;
struct ib_srq *srq;
+ struct ib_uobject *uninitialized_var(xrcd_uobj);
struct ib_srq_init_attr attr;
int ret;
- if (out_len < sizeof resp)
- return -ENOSPC;
-
- if (copy_from_user(&cmd, buf, sizeof cmd))
- return -EFAULT;
-
- INIT_UDATA(&udata, buf + sizeof cmd,
- (unsigned long) cmd.response + sizeof resp,
- in_len - sizeof cmd, out_len - sizeof resp);
-
obj = kmalloc(sizeof *obj, GFP_KERNEL);
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
- down_write(&obj->uobject.mutex);
+ init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_key);
+ down_write(&obj->uevent.uobject.mutex);
- pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+ pd = idr_read_pd(cmd->pd_handle, file->ucontext);
if (!pd) {
ret = -EINVAL;
goto err;
}
+ if (cmd->srq_type == IB_SRQT_XRC) {
+ attr.ext.xrc.cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
+ if (!attr.ext.xrc.cq) {
+ ret = -EINVAL;
+ goto err_put_pd;
+ }
+
+ attr.ext.xrc.xrcd = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj);
+ if (!attr.ext.xrc.xrcd) {
+ ret = -EINVAL;
+ goto err_put_cq;
+ }
+
+ obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
+ atomic_inc(&obj->uxrcd->refcnt);
+ }
+
attr.event_handler = ib_uverbs_srq_event_handler;
attr.srq_context = file;
- attr.attr.max_wr = cmd.max_wr;
- attr.attr.max_sge = cmd.max_sge;
- attr.attr.srq_limit = cmd.srq_limit;
+ attr.srq_type = cmd->srq_type;
+ attr.attr.max_wr = cmd->max_wr;
+ attr.attr.max_sge = cmd->max_sge;
+ attr.attr.srq_limit = cmd->srq_limit;
- obj->events_reported = 0;
- INIT_LIST_HEAD(&obj->event_list);
+ obj->uevent.events_reported = 0;
+ INIT_LIST_HEAD(&obj->uevent.event_list);
- srq = pd->device->create_srq(pd, &attr, &udata);
+ srq = pd->device->create_srq(pd, &attr, udata);
if (IS_ERR(srq)) {
ret = PTR_ERR(srq);
goto err_put;
}
- srq->device = pd->device;
- srq->pd = pd;
- srq->uobject = &obj->uobject;
+ srq->device = pd->device;
+ srq->pd = pd;
+ srq->srq_type = cmd->srq_type;
+ srq->uobject = &obj->uevent.uobject;
srq->event_handler = attr.event_handler;
srq->srq_context = attr.srq_context;
+
+ if (cmd->srq_type == IB_SRQT_XRC) {
+ srq->ext.xrc.cq = attr.ext.xrc.cq;
+ srq->ext.xrc.xrcd = attr.ext.xrc.xrcd;
+ atomic_inc(&attr.ext.xrc.cq->usecnt);
+ atomic_inc(&attr.ext.xrc.xrcd->usecnt);
+ }
+
atomic_inc(&pd->usecnt);
atomic_set(&srq->usecnt, 0);
- obj->uobject.object = srq;
- ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+ obj->uevent.uobject.object = srq;
+ ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
if (ret)
goto err_destroy;
memset(&resp, 0, sizeof resp);
- resp.srq_handle = obj->uobject.id;
+ resp.srq_handle = obj->uevent.uobject.id;
resp.max_wr = attr.attr.max_wr;
resp.max_sge = attr.attr.max_sge;
+ if (cmd->srq_type == IB_SRQT_XRC)
+ resp.srqn = srq->ext.xrc.srq_num;
- if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ if (copy_to_user((void __user *) (unsigned long) cmd->response,
&resp, sizeof resp)) {
ret = -EFAULT;
goto err_copy;
}
+ if (cmd->srq_type == IB_SRQT_XRC) {
+ put_uobj_read(xrcd_uobj);
+ put_cq_read(attr.ext.xrc.cq);
+ }
put_pd_read(pd);
mutex_lock(&file->mutex);
- list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
+ list_add_tail(&obj->uevent.uobject.list, &file->ucontext->srq_list);
mutex_unlock(&file->mutex);
- obj->uobject.live = 1;
+ obj->uevent.uobject.live = 1;
- up_write(&obj->uobject.mutex);
+ up_write(&obj->uevent.uobject.mutex);
- return in_len;
+ return 0;
err_copy:
- idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+ idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
err_destroy:
ib_destroy_srq(srq);
err_put:
+ if (cmd->srq_type == IB_SRQT_XRC) {
+ atomic_dec(&obj->uxrcd->refcnt);
+ put_uobj_read(xrcd_uobj);
+ }
+
+err_put_cq:
+ if (cmd->srq_type == IB_SRQT_XRC)
+ put_cq_read(attr.ext.xrc.cq);
+
+err_put_pd:
put_pd_read(pd);
err:
- put_uobj_write(&obj->uobject);
+ put_uobj_write(&obj->uevent.uobject);
return ret;
}
+ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_create_srq cmd;
+ struct ib_uverbs_create_xsrq xcmd;
+ struct ib_uverbs_create_srq_resp resp;
+ struct ib_udata udata;
+ int ret;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ xcmd.response = cmd.response;
+ xcmd.user_handle = cmd.user_handle;
+ xcmd.srq_type = IB_SRQT_BASIC;
+ xcmd.pd_handle = cmd.pd_handle;
+ xcmd.max_wr = cmd.max_wr;
+ xcmd.max_sge = cmd.max_sge;
+ xcmd.srq_limit = cmd.srq_limit;
+
+ INIT_UDATA(&udata, buf + sizeof cmd,
+ (unsigned long) cmd.response + sizeof resp,
+ in_len - sizeof cmd, out_len - sizeof resp);
+
+ ret = __uverbs_create_xsrq(file, &xcmd, &udata);
+ if (ret)
+ return ret;
+
+ return in_len;
+}
+
+ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len, int out_len)
+{
+ struct ib_uverbs_create_xsrq cmd;
+ struct ib_uverbs_create_srq_resp resp;
+ struct ib_udata udata;
+ int ret;
+
+ if (out_len < sizeof resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof cmd))
+ return -EFAULT;
+
+ INIT_UDATA(&udata, buf + sizeof cmd,
+ (unsigned long) cmd.response + sizeof resp,
+ in_len - sizeof cmd, out_len - sizeof resp);
+
+ ret = __uverbs_create_xsrq(file, &cmd, &udata);
+ if (ret)
+ return ret;
+
+ return in_len;
+}
+
ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 56898b6578a4..879636746373 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -72,6 +72,7 @@ DEFINE_IDR(ib_uverbs_ah_idr);
DEFINE_IDR(ib_uverbs_cq_idr);
DEFINE_IDR(ib_uverbs_qp_idr);
DEFINE_IDR(ib_uverbs_srq_idr);
+DEFINE_IDR(ib_uverbs_xrcd_idr);
static DEFINE_SPINLOCK(map_lock);
static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -107,6 +108,10 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
[IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
[IB_USER_VERBS_CMD_QUERY_SRQ] = ib_uverbs_query_srq,
[IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
+ [IB_USER_VERBS_CMD_OPEN_XRCD] = ib_uverbs_open_xrcd,
+ [IB_USER_VERBS_CMD_CLOSE_XRCD] = ib_uverbs_close_xrcd,
+ [IB_USER_VERBS_CMD_CREATE_XSRQ] = ib_uverbs_create_xsrq,
+ [IB_USER_VERBS_CMD_OPEN_QP] = ib_uverbs_open_qp
};
static void ib_uverbs_add_one(struct ib_device *device);
@@ -202,8 +207,12 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
container_of(uobj, struct ib_uqp_object, uevent.uobject);
idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
- ib_uverbs_detach_umcast(qp, uqp);
- ib_destroy_qp(qp);
+ if (qp != qp->real_qp) {
+ ib_close_qp(qp);
+ } else {
+ ib_uverbs_detach_umcast(qp, uqp);
+ ib_destroy_qp(qp);
+ }
ib_uverbs_release_uevent(file, &uqp->uevent);
kfree(uqp);
}
@@ -241,6 +250,18 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
kfree(uobj);
}
+ mutex_lock(&file->device->xrcd_tree_mutex);
+ list_for_each_entry_safe(uobj, tmp, &context->xrcd_list, list) {
+ struct ib_xrcd *xrcd = uobj->object;
+ struct ib_uxrcd_object *uxrcd =
+ container_of(uobj, struct ib_uxrcd_object, uobject);
+
+ idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+ ib_uverbs_dealloc_xrcd(file->device, xrcd);
+ kfree(uxrcd);
+ }
+ mutex_unlock(&file->device->xrcd_tree_mutex);
+
list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
struct ib_pd *pd = uobj->object;
@@ -557,8 +578,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (hdr.in_words * 4 != count)
return -EINVAL;
- if (hdr.command < 0 ||
- hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
+ if (hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
!uverbs_cmd_table[hdr.command])
return -EINVAL;
@@ -741,6 +761,8 @@ static void ib_uverbs_add_one(struct ib_device *device)
kref_init(&uverbs_dev->ref);
init_completion(&uverbs_dev->comp);
+ uverbs_dev->xrcd_tree = RB_ROOT;
+ mutex_init(&uverbs_dev->xrcd_tree_mutex);
spin_lock(&map_lock);
devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index af7a8b08b2e9..42517500b223 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -39,6 +39,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/string.h>
+#include <linux/slab.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>
@@ -77,6 +78,31 @@ enum ib_rate mult_to_ib_rate(int mult)
}
EXPORT_SYMBOL(mult_to_ib_rate);
+int ib_rate_to_mbps(enum ib_rate rate)
+{
+ switch (rate) {
+ case IB_RATE_2_5_GBPS: return 2500;
+ case IB_RATE_5_GBPS: return 5000;
+ case IB_RATE_10_GBPS: return 10000;
+ case IB_RATE_20_GBPS: return 20000;
+ case IB_RATE_30_GBPS: return 30000;
+ case IB_RATE_40_GBPS: return 40000;
+ case IB_RATE_60_GBPS: return 60000;
+ case IB_RATE_80_GBPS: return 80000;
+ case IB_RATE_120_GBPS: return 120000;
+ case IB_RATE_14_GBPS: return 14062;
+ case IB_RATE_56_GBPS: return 56250;
+ case IB_RATE_112_GBPS: return 112500;
+ case IB_RATE_168_GBPS: return 168750;
+ case IB_RATE_25_GBPS: return 25781;
+ case IB_RATE_100_GBPS: return 103125;
+ case IB_RATE_200_GBPS: return 206250;
+ case IB_RATE_300_GBPS: return 309375;
+ default: return -1;
+ }
+}
+EXPORT_SYMBOL(ib_rate_to_mbps);
+
enum rdma_transport_type
rdma_node_get_transport(enum rdma_node_type node_type)
{
@@ -250,6 +276,13 @@ struct ib_srq *ib_create_srq(struct ib_pd *pd,
srq->uobject = NULL;
srq->event_handler = srq_init_attr->event_handler;
srq->srq_context = srq_init_attr->srq_context;
+ srq->srq_type = srq_init_attr->srq_type;
+ if (srq->srq_type == IB_SRQT_XRC) {
+ srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
+ srq->ext.xrc.cq = srq_init_attr->ext.xrc.cq;
+ atomic_inc(&srq->ext.xrc.xrcd->usecnt);
+ atomic_inc(&srq->ext.xrc.cq->usecnt);
+ }
atomic_inc(&pd->usecnt);
atomic_set(&srq->usecnt, 0);
}
@@ -279,16 +312,29 @@ EXPORT_SYMBOL(ib_query_srq);
int ib_destroy_srq(struct ib_srq *srq)
{
struct ib_pd *pd;
+ enum ib_srq_type srq_type;
+ struct ib_xrcd *uninitialized_var(xrcd);
+ struct ib_cq *uninitialized_var(cq);
int ret;
if (atomic_read(&srq->usecnt))
return -EBUSY;
pd = srq->pd;
+ srq_type = srq->srq_type;
+ if (srq_type == IB_SRQT_XRC) {
+ xrcd = srq->ext.xrc.xrcd;
+ cq = srq->ext.xrc.cq;
+ }
ret = srq->device->destroy_srq(srq);
- if (!ret)
+ if (!ret) {
atomic_dec(&pd->usecnt);
+ if (srq_type == IB_SRQT_XRC) {
+ atomic_dec(&xrcd->usecnt);
+ atomic_dec(&cq->usecnt);
+ }
+ }
return ret;
}
@@ -296,28 +342,123 @@ EXPORT_SYMBOL(ib_destroy_srq);
/* Queue pairs */
+static void __ib_shared_qp_event_handler(struct ib_event *event, void *context)
+{
+ struct ib_qp *qp = context;
+
+ list_for_each_entry(event->element.qp, &qp->open_list, open_list)
+ event->element.qp->event_handler(event, event->element.qp->qp_context);
+}
+
+static void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp)
+{
+ mutex_lock(&xrcd->tgt_qp_mutex);
+ list_add(&qp->xrcd_list, &xrcd->tgt_qp_list);
+ mutex_unlock(&xrcd->tgt_qp_mutex);
+}
+
+static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
+ void (*event_handler)(struct ib_event *, void *),
+ void *qp_context)
+{
+ struct ib_qp *qp;
+ unsigned long flags;
+
+ qp = kzalloc(sizeof *qp, GFP_KERNEL);
+ if (!qp)
+ return ERR_PTR(-ENOMEM);
+
+ qp->real_qp = real_qp;
+ atomic_inc(&real_qp->usecnt);
+ qp->device = real_qp->device;
+ qp->event_handler = event_handler;
+ qp->qp_context = qp_context;
+ qp->qp_num = real_qp->qp_num;
+ qp->qp_type = real_qp->qp_type;
+
+ spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
+ list_add(&qp->open_list, &real_qp->open_list);
+ spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
+
+ return qp;
+}
+
+struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd,
+ struct ib_qp_open_attr *qp_open_attr)
+{
+ struct ib_qp *qp, *real_qp;
+
+ if (qp_open_attr->qp_type != IB_QPT_XRC_TGT)
+ return ERR_PTR(-EINVAL);
+
+ qp = ERR_PTR(-EINVAL);
+ mutex_lock(&xrcd->tgt_qp_mutex);
+ list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) {
+ if (real_qp->qp_num == qp_open_attr->qp_num) {
+ qp = __ib_open_qp(real_qp, qp_open_attr->event_handler,
+ qp_open_attr->qp_context);
+ break;
+ }
+ }
+ mutex_unlock(&xrcd->tgt_qp_mutex);
+ return qp;
+}
+EXPORT_SYMBOL(ib_open_qp);
+
struct ib_qp *ib_create_qp(struct ib_pd *pd,
struct ib_qp_init_attr *qp_init_attr)
{
- struct ib_qp *qp;
+ struct ib_qp *qp, *real_qp;
+ struct ib_device *device;
- qp = pd->device->create_qp(pd, qp_init_attr, NULL);
+ device = pd ? pd->device : qp_init_attr->xrcd->device;
+ qp = device->create_qp(pd, qp_init_attr, NULL);
if (!IS_ERR(qp)) {
- qp->device = pd->device;
- qp->pd = pd;
- qp->send_cq = qp_init_attr->send_cq;
- qp->recv_cq = qp_init_attr->recv_cq;
- qp->srq = qp_init_attr->srq;
- qp->uobject = NULL;
- qp->event_handler = qp_init_attr->event_handler;
- qp->qp_context = qp_init_attr->qp_context;
- qp->qp_type = qp_init_attr->qp_type;
- atomic_inc(&pd->usecnt);
- atomic_inc(&qp_init_attr->send_cq->usecnt);
- atomic_inc(&qp_init_attr->recv_cq->usecnt);
- if (qp_init_attr->srq)
- atomic_inc(&qp_init_attr->srq->usecnt);
+ qp->device = device;
+ qp->real_qp = qp;
+ qp->uobject = NULL;
+ qp->qp_type = qp_init_attr->qp_type;
+
+ if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
+ qp->event_handler = __ib_shared_qp_event_handler;
+ qp->qp_context = qp;
+ qp->pd = NULL;
+ qp->send_cq = qp->recv_cq = NULL;
+ qp->srq = NULL;
+ qp->xrcd = qp_init_attr->xrcd;
+ atomic_inc(&qp_init_attr->xrcd->usecnt);
+ INIT_LIST_HEAD(&qp->open_list);
+ atomic_set(&qp->usecnt, 0);
+
+ real_qp = qp;
+ qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
+ qp_init_attr->qp_context);
+ if (!IS_ERR(qp))
+ __ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp);
+ else
+ real_qp->device->destroy_qp(real_qp);
+ } else {
+ qp->event_handler = qp_init_attr->event_handler;
+ qp->qp_context = qp_init_attr->qp_context;
+ if (qp_init_attr->qp_type == IB_QPT_XRC_INI) {
+ qp->recv_cq = NULL;
+ qp->srq = NULL;
+ } else {
+ qp->recv_cq = qp_init_attr->recv_cq;
+ atomic_inc(&qp_init_attr->recv_cq->usecnt);
+ qp->srq = qp_init_attr->srq;
+ if (qp->srq)
+ atomic_inc(&qp_init_attr->srq->usecnt);
+ }
+
+ qp->pd = pd;
+ qp->send_cq = qp_init_attr->send_cq;
+ qp->xrcd = NULL;
+
+ atomic_inc(&pd->usecnt);
+ atomic_inc(&qp_init_attr->send_cq->usecnt);
+ }
}
return qp;
@@ -326,8 +467,8 @@ EXPORT_SYMBOL(ib_create_qp);
static const struct {
int valid;
- enum ib_qp_attr_mask req_param[IB_QPT_RAW_ETHERTYPE + 1];
- enum ib_qp_attr_mask opt_param[IB_QPT_RAW_ETHERTYPE + 1];
+ enum ib_qp_attr_mask req_param[IB_QPT_MAX];
+ enum ib_qp_attr_mask opt_param[IB_QPT_MAX];
} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
[IB_QPS_RESET] = {
[IB_QPS_RESET] = { .valid = 1 },
@@ -343,6 +484,12 @@ static const struct {
[IB_QPT_RC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
+ [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
+ [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
@@ -365,6 +512,12 @@ static const struct {
[IB_QPT_RC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
+ [IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
+ [IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_ACCESS_FLAGS),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
@@ -384,6 +537,16 @@ static const struct {
IB_QP_RQ_PSN |
IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER),
+ [IB_QPT_XRC_INI] = (IB_QP_AV |
+ IB_QP_PATH_MTU |
+ IB_QP_DEST_QPN |
+ IB_QP_RQ_PSN),
+ [IB_QPT_XRC_TGT] = (IB_QP_AV |
+ IB_QP_PATH_MTU |
+ IB_QP_DEST_QPN |
+ IB_QP_RQ_PSN |
+ IB_QP_MAX_DEST_RD_ATOMIC |
+ IB_QP_MIN_RNR_TIMER),
},
.opt_param = {
[IB_QPT_UD] = (IB_QP_PKEY_INDEX |
@@ -394,6 +557,12 @@ static const struct {
[IB_QPT_RC] = (IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX),
+ [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PKEY_INDEX),
+ [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PKEY_INDEX),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
@@ -414,6 +583,13 @@ static const struct {
IB_QP_RNR_RETRY |
IB_QP_SQ_PSN |
IB_QP_MAX_QP_RD_ATOMIC),
+ [IB_QPT_XRC_INI] = (IB_QP_TIMEOUT |
+ IB_QP_RETRY_CNT |
+ IB_QP_RNR_RETRY |
+ IB_QP_SQ_PSN |
+ IB_QP_MAX_QP_RD_ATOMIC),
+ [IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT |
+ IB_QP_SQ_PSN),
[IB_QPT_SMI] = IB_QP_SQ_PSN,
[IB_QPT_GSI] = IB_QP_SQ_PSN,
},
@@ -429,6 +605,15 @@ static const struct {
IB_QP_ACCESS_FLAGS |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_MIN_RNR_TIMER |
+ IB_QP_PATH_MIG_STATE),
[IB_QPT_SMI] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_CUR_STATE |
@@ -453,6 +638,15 @@ static const struct {
IB_QP_ALT_PATH |
IB_QP_PATH_MIG_STATE |
IB_QP_MIN_RNR_TIMER),
+ [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_ALT_PATH |
+ IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_ALT_PATH |
+ IB_QP_PATH_MIG_STATE |
+ IB_QP_MIN_RNR_TIMER),
[IB_QPT_SMI] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_CUR_STATE |
@@ -465,6 +659,8 @@ static const struct {
[IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
+ [IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
+ [IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */
[IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
}
@@ -487,6 +683,15 @@ static const struct {
IB_QP_ACCESS_FLAGS |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_MIN_RNR_TIMER |
+ IB_QP_PATH_MIG_STATE),
[IB_QPT_SMI] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_CUR_STATE |
@@ -515,6 +720,25 @@ static const struct {
IB_QP_PKEY_INDEX |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_INI] = (IB_QP_PORT |
+ IB_QP_AV |
+ IB_QP_TIMEOUT |
+ IB_QP_RETRY_CNT |
+ IB_QP_RNR_RETRY |
+ IB_QP_MAX_QP_RD_ATOMIC |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PKEY_INDEX |
+ IB_QP_PATH_MIG_STATE),
+ [IB_QPT_XRC_TGT] = (IB_QP_PORT |
+ IB_QP_AV |
+ IB_QP_TIMEOUT |
+ IB_QP_MAX_DEST_RD_ATOMIC |
+ IB_QP_ALT_PATH |
+ IB_QP_ACCESS_FLAGS |
+ IB_QP_PKEY_INDEX |
+ IB_QP_MIN_RNR_TIMER |
+ IB_QP_PATH_MIG_STATE),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
@@ -579,7 +803,7 @@ int ib_modify_qp(struct ib_qp *qp,
struct ib_qp_attr *qp_attr,
int qp_attr_mask)
{
- return qp->device->modify_qp(qp, qp_attr, qp_attr_mask, NULL);
+ return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
}
EXPORT_SYMBOL(ib_modify_qp);
@@ -589,11 +813,59 @@ int ib_query_qp(struct ib_qp *qp,
struct ib_qp_init_attr *qp_init_attr)
{
return qp->device->query_qp ?
- qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) :
+ qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) :
-ENOSYS;
}
EXPORT_SYMBOL(ib_query_qp);
+int ib_close_qp(struct ib_qp *qp)
+{
+ struct ib_qp *real_qp;
+ unsigned long flags;
+
+ real_qp = qp->real_qp;
+ if (real_qp == qp)
+ return -EINVAL;
+
+ spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
+ list_del(&qp->open_list);
+ spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
+
+ atomic_dec(&real_qp->usecnt);
+ kfree(qp);
+
+ return 0;
+}
+EXPORT_SYMBOL(ib_close_qp);
+
+static int __ib_destroy_shared_qp(struct ib_qp *qp)
+{
+ struct ib_xrcd *xrcd;
+ struct ib_qp *real_qp;
+ int ret;
+
+ real_qp = qp->real_qp;
+ xrcd = real_qp->xrcd;
+
+ mutex_lock(&xrcd->tgt_qp_mutex);
+ ib_close_qp(qp);
+ if (atomic_read(&real_qp->usecnt) == 0)
+ list_del(&real_qp->xrcd_list);
+ else
+ real_qp = NULL;
+ mutex_unlock(&xrcd->tgt_qp_mutex);
+
+ if (real_qp) {
+ ret = ib_destroy_qp(real_qp);
+ if (!ret)
+ atomic_dec(&xrcd->usecnt);
+ else
+ __ib_insert_xrcd_qp(xrcd, real_qp);
+ }
+
+ return 0;
+}
+
int ib_destroy_qp(struct ib_qp *qp)
{
struct ib_pd *pd;
@@ -601,16 +873,25 @@ int ib_destroy_qp(struct ib_qp *qp)
struct ib_srq *srq;
int ret;
- pd = qp->pd;
- scq = qp->send_cq;
- rcq = qp->recv_cq;
- srq = qp->srq;
+ if (atomic_read(&qp->usecnt))
+ return -EBUSY;
+
+ if (qp->real_qp != qp)
+ return __ib_destroy_shared_qp(qp);
+
+ pd = qp->pd;
+ scq = qp->send_cq;
+ rcq = qp->recv_cq;
+ srq = qp->srq;
ret = qp->device->destroy_qp(qp);
if (!ret) {
- atomic_dec(&pd->usecnt);
- atomic_dec(&scq->usecnt);
- atomic_dec(&rcq->usecnt);
+ if (pd)
+ atomic_dec(&pd->usecnt);
+ if (scq)
+ atomic_dec(&scq->usecnt);
+ if (rcq)
+ atomic_dec(&rcq->usecnt);
if (srq)
atomic_dec(&srq->usecnt);
}
@@ -920,3 +1201,42 @@ int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
return qp->device->detach_mcast(qp, gid, lid);
}
EXPORT_SYMBOL(ib_detach_mcast);
+
+struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device)
+{
+ struct ib_xrcd *xrcd;
+
+ if (!device->alloc_xrcd)
+ return ERR_PTR(-ENOSYS);
+
+ xrcd = device->alloc_xrcd(device, NULL, NULL);
+ if (!IS_ERR(xrcd)) {
+ xrcd->device = device;
+ xrcd->inode = NULL;
+ atomic_set(&xrcd->usecnt, 0);
+ mutex_init(&xrcd->tgt_qp_mutex);
+ INIT_LIST_HEAD(&xrcd->tgt_qp_list);
+ }
+
+ return xrcd;
+}
+EXPORT_SYMBOL(ib_alloc_xrcd);
+
+int ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+ struct ib_qp *qp;
+ int ret;
+
+ if (atomic_read(&xrcd->usecnt))
+ return -EBUSY;
+
+ while (!list_empty(&xrcd->tgt_qp_list)) {
+ qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list);
+ ret = ib_destroy_qp(qp);
+ if (ret)
+ return ret;
+ }
+
+ return xrcd->device->dealloc_xrcd(xrcd);
+}
+EXPORT_SYMBOL(ib_dealloc_xrcd);
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 444470a28de2..5ce7b9e8bff6 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -800,13 +800,10 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* Loop thru additional data fragments and queue them */
if (skb_shinfo(skb)->nr_frags) {
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- maplen = frag->size;
- mapaddr =
- pci_map_page(c2dev->pcidev, frag->page,
- frag->page_offset, maplen,
- PCI_DMA_TODEVICE);
-
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ maplen = skb_frag_size(frag);
+ mapaddr = skb_frag_dma_map(&c2dev->pcidev->dev, frag,
+ 0, maplen, DMA_TO_DEVICE);
elem = elem->next;
elem->skb = NULL;
elem->mapaddr = mapaddr;
diff --git a/drivers/infiniband/hw/amso1100/c2_ae.c b/drivers/infiniband/hw/amso1100/c2_ae.c
index 24f9e3a90e8e..32d34e88d5cf 100644
--- a/drivers/infiniband/hw/amso1100/c2_ae.c
+++ b/drivers/infiniband/hw/amso1100/c2_ae.c
@@ -288,6 +288,11 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
cm_event.private_data_len =
be32_to_cpu(req->private_data_length);
cm_event.private_data = req->private_data;
+ /*
+ * Until ird/ord negotiation via MPAv2 support is added, send
+ * max supported values
+ */
+ cm_event.ird = cm_event.ord = 128;
if (cm_id->event_handler)
cm_id->event_handler(cm_id, &cm_event);
diff --git a/drivers/infiniband/hw/amso1100/c2_intr.c b/drivers/infiniband/hw/amso1100/c2_intr.c
index 0ebe4e806b86..8951db4ae29d 100644
--- a/drivers/infiniband/hw/amso1100/c2_intr.c
+++ b/drivers/infiniband/hw/amso1100/c2_intr.c
@@ -183,6 +183,11 @@ static void handle_vq(struct c2_dev *c2dev, u32 mq_index)
case IW_CM_EVENT_ESTABLISHED:
c2_set_qp_state(req->qp,
C2_QP_STATE_RTS);
+ /*
+ * Until ird/ord negotiation via MPAv2 support is added, send
+ * max supported values
+ */
+ cm_event.ird = cm_event.ord = 128;
case IW_CM_EVENT_CLOSE:
/*
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c
index f101bb73be63..12f923d64e42 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -753,10 +753,7 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev)
memcpy_fromio(netdev->dev_addr, c2dev->kva + C2_REGS_RDMA_ENADDR, 6);
/* Print out the MAC address */
- pr_debug("%s: MAC %02X:%02X:%02X:%02X:%02X:%02X\n",
- netdev->name,
- netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
- netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+ pr_debug("%s: MAC %pM\n", netdev->name, netdev->dev_addr);
#if 0
/* Disable network packets */
diff --git a/drivers/infiniband/hw/cxgb3/Makefile b/drivers/infiniband/hw/cxgb3/Makefile
index 621619c794e5..2761364185af 100644
--- a/drivers/infiniband/hw/cxgb3/Makefile
+++ b/drivers/infiniband/hw/cxgb3/Makefile
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/cxgb3
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb3
obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 6cd642aaa4de..de6d0774e609 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -753,6 +753,11 @@ static void connect_request_upcall(struct iwch_ep *ep)
event.private_data_len = ep->plen;
event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
event.provider_data = ep;
+ /*
+ * Until ird/ord negotiation via MPAv2 support is added, send max
+ * supported values
+ */
+ event.ird = event.ord = 8;
if (state_read(&ep->parent_ep->com) != DEAD) {
get_ep(&ep->com);
ep->parent_ep->com.cm_id->event_handler(
@@ -770,6 +775,11 @@ static void established_upcall(struct iwch_ep *ep)
PDBG("%s ep %p\n", __func__, ep);
memset(&event, 0, sizeof(event));
event.event = IW_CM_EVENT_ESTABLISHED;
+ /*
+ * Until ird/ord negotiation via MPAv2 support is added, send max
+ * supported values
+ */
+ event.ird = event.ord = 8;
if (ep->com.cm_id) {
PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
ep->com.cm_id->event_handler(ep->com.cm_id, &event);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c
index 71e0d845da3d..abcc9e76962b 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_ev.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c
@@ -46,6 +46,7 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
struct ib_event event;
struct iwch_qp_attributes attrs;
struct iwch_qp *qhp;
+ unsigned long flag;
spin_lock(&rnicp->lock);
qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
@@ -94,7 +95,9 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
if (qhp->ibqp.event_handler)
(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
+ spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+ spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
if (atomic_dec_and_test(&qhp->refcnt))
wake_up(&qhp->wait);
@@ -107,6 +110,7 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
struct iwch_cq *chp;
struct iwch_qp *qhp;
u32 cqid = RSPQ_CQID(rsp_msg);
+ unsigned long flag;
rnicp = (struct iwch_dev *) rdev_p->ulp;
spin_lock(&rnicp->lock);
@@ -170,7 +174,9 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
*/
if (qhp->ep && SQ_TYPE(rsp_msg->cqe))
dst_confirm(qhp->ep->dst);
+ spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+ spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
break;
case TPT_ERR_STAG:
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index c7d9411f2954..37c224fc3ad9 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -190,6 +190,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
chp->rhp = rhp;
chp->ibcq.cqe = 1 << chp->cq.size_log2;
spin_lock_init(&chp->lock);
+ spin_lock_init(&chp->comp_handler_lock);
atomic_set(&chp->refcnt, 1);
init_waitqueue_head(&chp->wait);
if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) {
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
index 9a342c9b220d..87c14b0c5ac0 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
@@ -103,6 +103,7 @@ struct iwch_cq {
struct iwch_dev *rhp;
struct t3_cq cq;
spinlock_t lock;
+ spinlock_t comp_handler_lock;
atomic_t refcnt;
wait_queue_head_t wait;
u32 __user *user_rptr_addr;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index ecd313f359a4..bea5839d89ee 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -822,8 +822,11 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
flushed = cxio_flush_rq(&qhp->wq, &rchp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&rchp->lock, *flag);
- if (flushed)
+ if (flushed) {
+ spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+ spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
+ }
/* locking hierarchy: cq lock first, then qp lock. */
spin_lock_irqsave(&schp->lock, *flag);
@@ -833,8 +836,11 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
flushed = cxio_flush_sq(&qhp->wq, &schp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&schp->lock, *flag);
- if (flushed)
+ if (flushed) {
+ spin_lock_irqsave(&schp->comp_handler_lock, *flag);
(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+ spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
+ }
/* deref */
if (atomic_dec_and_test(&qhp->refcnt))
@@ -853,11 +859,15 @@ static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
if (qhp->ibqp.uobject) {
cxio_set_wq_in_error(&qhp->wq);
cxio_set_cq_in_error(&rchp->cq);
+ spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+ spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
if (schp != rchp) {
cxio_set_cq_in_error(&schp->cq);
+ spin_lock_irqsave(&schp->comp_handler_lock, *flag);
(*schp->ibcq.comp_handler)(&schp->ibcq,
schp->ibcq.cq_context);
+ spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
}
return;
}
diff --git a/drivers/infiniband/hw/cxgb4/Makefile b/drivers/infiniband/hw/cxgb4/Makefile
index cd20b1342aec..46b878ca2c3b 100644
--- a/drivers/infiniband/hw/cxgb4/Makefile
+++ b/drivers/infiniband/hw/cxgb4/Makefile
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/cxgb4
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 77f769d9227d..b36cdac9c558 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -103,7 +103,8 @@ MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout "
static int mpa_rev = 1;
module_param(mpa_rev, int, 0644);
MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, "
- "1 is spec compliant. (default=1)");
+ "1 is RFC0544 spec compliant, 2 is IETF MPA Peer Connect Draft"
+ " compliant (default=1)");
static int markers_enabled;
module_param(markers_enabled, int, 0644);
@@ -497,17 +498,21 @@ static int send_connect(struct c4iw_ep *ep)
return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
}
-static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb)
+static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
+ u8 mpa_rev_to_use)
{
int mpalen, wrlen;
struct fw_ofld_tx_data_wr *req;
struct mpa_message *mpa;
+ struct mpa_v2_conn_params mpa_v2_params;
PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
BUG_ON(skb_cloned(skb));
mpalen = sizeof(*mpa) + ep->plen;
+ if (mpa_rev_to_use == 2)
+ mpalen += sizeof(struct mpa_v2_conn_params);
wrlen = roundup(mpalen + sizeof *req, 16);
skb = get_skb(skb, wrlen, GFP_KERNEL);
if (!skb) {
@@ -533,12 +538,39 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb)
mpa = (struct mpa_message *)(req + 1);
memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key));
mpa->flags = (crc_enabled ? MPA_CRC : 0) |
- (markers_enabled ? MPA_MARKERS : 0);
+ (markers_enabled ? MPA_MARKERS : 0) |
+ (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
mpa->private_data_size = htons(ep->plen);
- mpa->revision = mpa_rev;
+ mpa->revision = mpa_rev_to_use;
+ if (mpa_rev_to_use == 1)
+ ep->tried_with_mpa_v1 = 1;
+
+ if (mpa_rev_to_use == 2) {
+ mpa->private_data_size +=
+ htons(sizeof(struct mpa_v2_conn_params));
+ mpa_v2_params.ird = htons((u16)ep->ird);
+ mpa_v2_params.ord = htons((u16)ep->ord);
+
+ if (peer2peer) {
+ mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
+ if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
+ mpa_v2_params.ord |=
+ htons(MPA_V2_RDMA_WRITE_RTR);
+ else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
+ mpa_v2_params.ord |=
+ htons(MPA_V2_RDMA_READ_RTR);
+ }
+ memcpy(mpa->private_data, &mpa_v2_params,
+ sizeof(struct mpa_v2_conn_params));
- if (ep->plen)
- memcpy(mpa->private_data, ep->mpa_pkt + sizeof(*mpa), ep->plen);
+ if (ep->plen)
+ memcpy(mpa->private_data +
+ sizeof(struct mpa_v2_conn_params),
+ ep->mpa_pkt + sizeof(*mpa), ep->plen);
+ } else
+ if (ep->plen)
+ memcpy(mpa->private_data,
+ ep->mpa_pkt + sizeof(*mpa), ep->plen);
/*
* Reference the mpa skb. This ensures the data area
@@ -562,10 +594,13 @@ static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen)
struct fw_ofld_tx_data_wr *req;
struct mpa_message *mpa;
struct sk_buff *skb;
+ struct mpa_v2_conn_params mpa_v2_params;
PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
mpalen = sizeof(*mpa) + plen;
+ if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
+ mpalen += sizeof(struct mpa_v2_conn_params);
wrlen = roundup(mpalen + sizeof *req, 16);
skb = get_skb(NULL, wrlen, GFP_KERNEL);
@@ -595,8 +630,29 @@ static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen)
mpa->flags = MPA_REJECT;
mpa->revision = mpa_rev;
mpa->private_data_size = htons(plen);
- if (plen)
- memcpy(mpa->private_data, pdata, plen);
+
+ if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+ mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+ mpa->private_data_size +=
+ htons(sizeof(struct mpa_v2_conn_params));
+ mpa_v2_params.ird = htons(((u16)ep->ird) |
+ (peer2peer ? MPA_V2_PEER2PEER_MODEL :
+ 0));
+ mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ?
+ (p2p_type ==
+ FW_RI_INIT_P2PTYPE_RDMA_WRITE ?
+ MPA_V2_RDMA_WRITE_RTR : p2p_type ==
+ FW_RI_INIT_P2PTYPE_READ_REQ ?
+ MPA_V2_RDMA_READ_RTR : 0) : 0));
+ memcpy(mpa->private_data, &mpa_v2_params,
+ sizeof(struct mpa_v2_conn_params));
+
+ if (ep->plen)
+ memcpy(mpa->private_data +
+ sizeof(struct mpa_v2_conn_params), pdata, plen);
+ } else
+ if (plen)
+ memcpy(mpa->private_data, pdata, plen);
/*
* Reference the mpa skb again. This ensures the data area
@@ -617,10 +673,13 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen)
struct fw_ofld_tx_data_wr *req;
struct mpa_message *mpa;
struct sk_buff *skb;
+ struct mpa_v2_conn_params mpa_v2_params;
PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
mpalen = sizeof(*mpa) + plen;
+ if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
+ mpalen += sizeof(struct mpa_v2_conn_params);
wrlen = roundup(mpalen + sizeof *req, 16);
skb = get_skb(NULL, wrlen, GFP_KERNEL);
@@ -649,10 +708,36 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen)
memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) |
(markers_enabled ? MPA_MARKERS : 0);
- mpa->revision = mpa_rev;
+ mpa->revision = ep->mpa_attr.version;
mpa->private_data_size = htons(plen);
- if (plen)
- memcpy(mpa->private_data, pdata, plen);
+
+ if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+ mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+ mpa->private_data_size +=
+ htons(sizeof(struct mpa_v2_conn_params));
+ mpa_v2_params.ird = htons((u16)ep->ird);
+ mpa_v2_params.ord = htons((u16)ep->ord);
+ if (peer2peer && (ep->mpa_attr.p2p_type !=
+ FW_RI_INIT_P2PTYPE_DISABLED)) {
+ mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
+
+ if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
+ mpa_v2_params.ord |=
+ htons(MPA_V2_RDMA_WRITE_RTR);
+ else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
+ mpa_v2_params.ord |=
+ htons(MPA_V2_RDMA_READ_RTR);
+ }
+
+ memcpy(mpa->private_data, &mpa_v2_params,
+ sizeof(struct mpa_v2_conn_params));
+
+ if (ep->plen)
+ memcpy(mpa->private_data +
+ sizeof(struct mpa_v2_conn_params), pdata, plen);
+ } else
+ if (plen)
+ memcpy(mpa->private_data, pdata, plen);
/*
* Reference the mpa skb. This ensures the data area
@@ -695,7 +780,10 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
/* start MPA negotiation */
send_flowc(ep, NULL);
- send_mpa_req(ep, skb);
+ if (ep->retry_with_mpa_v1)
+ send_mpa_req(ep, skb, 1);
+ else
+ send_mpa_req(ep, skb, mpa_rev);
return 0;
}
@@ -769,8 +857,19 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
event.remote_addr = ep->com.remote_addr;
if ((status == 0) || (status == -ECONNREFUSED)) {
- event.private_data_len = ep->plen;
- event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+ if (!ep->tried_with_mpa_v1) {
+ /* this means MPA_v2 is used */
+ event.private_data_len = ep->plen -
+ sizeof(struct mpa_v2_conn_params);
+ event.private_data = ep->mpa_pkt +
+ sizeof(struct mpa_message) +
+ sizeof(struct mpa_v2_conn_params);
+ } else {
+ /* this means MPA_v1 is used */
+ event.private_data_len = ep->plen;
+ event.private_data = ep->mpa_pkt +
+ sizeof(struct mpa_message);
+ }
}
PDBG("%s ep %p tid %u status %d\n", __func__, ep,
@@ -793,9 +892,22 @@ static void connect_request_upcall(struct c4iw_ep *ep)
event.event = IW_CM_EVENT_CONNECT_REQUEST;
event.local_addr = ep->com.local_addr;
event.remote_addr = ep->com.remote_addr;
- event.private_data_len = ep->plen;
- event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
event.provider_data = ep;
+ if (!ep->tried_with_mpa_v1) {
+ /* this means MPA_v2 is used */
+ event.ord = ep->ord;
+ event.ird = ep->ird;
+ event.private_data_len = ep->plen -
+ sizeof(struct mpa_v2_conn_params);
+ event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) +
+ sizeof(struct mpa_v2_conn_params);
+ } else {
+ /* this means MPA_v1 is used. Send max supported */
+ event.ord = c4iw_max_read_depth;
+ event.ird = c4iw_max_read_depth;
+ event.private_data_len = ep->plen;
+ event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+ }
if (state_read(&ep->parent_ep->com) != DEAD) {
c4iw_get_ep(&ep->com);
ep->parent_ep->com.cm_id->event_handler(
@@ -813,6 +925,8 @@ static void established_upcall(struct c4iw_ep *ep)
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
memset(&event, 0, sizeof(event));
event.event = IW_CM_EVENT_ESTABLISHED;
+ event.ird = ep->ird;
+ event.ord = ep->ord;
if (ep->com.cm_id) {
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
ep->com.cm_id->event_handler(ep->com.cm_id, &event);
@@ -848,7 +962,10 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
{
struct mpa_message *mpa;
+ struct mpa_v2_conn_params *mpa_v2_params;
u16 plen;
+ u16 resp_ird, resp_ord;
+ u8 rtr_mismatch = 0, insuff_ird = 0;
struct c4iw_qp_attributes attrs;
enum c4iw_qp_attr_mask mask;
int err;
@@ -888,7 +1005,9 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
mpa = (struct mpa_message *) ep->mpa_pkt;
/* Validate MPA header. */
- if (mpa->revision != mpa_rev) {
+ if (mpa->revision > mpa_rev) {
+ printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
+ " Received = %d\n", __func__, mpa_rev, mpa->revision);
err = -EPROTO;
goto err;
}
@@ -938,13 +1057,66 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
ep->mpa_attr.recv_marker_enabled = markers_enabled;
ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
- ep->mpa_attr.version = mpa_rev;
- ep->mpa_attr.p2p_type = peer2peer ? p2p_type :
- FW_RI_INIT_P2PTYPE_DISABLED;
+ ep->mpa_attr.version = mpa->revision;
+ ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+
+ if (mpa->revision == 2) {
+ ep->mpa_attr.enhanced_rdma_conn =
+ mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
+ if (ep->mpa_attr.enhanced_rdma_conn) {
+ mpa_v2_params = (struct mpa_v2_conn_params *)
+ (ep->mpa_pkt + sizeof(*mpa));
+ resp_ird = ntohs(mpa_v2_params->ird) &
+ MPA_V2_IRD_ORD_MASK;
+ resp_ord = ntohs(mpa_v2_params->ord) &
+ MPA_V2_IRD_ORD_MASK;
+
+ /*
+ * This is a double-check. Ideally, below checks are
+ * not required since ird/ord stuff has been taken
+ * care of in c4iw_accept_cr
+ */
+ if ((ep->ird < resp_ord) || (ep->ord > resp_ird)) {
+ err = -ENOMEM;
+ ep->ird = resp_ord;
+ ep->ord = resp_ird;
+ insuff_ird = 1;
+ }
+
+ if (ntohs(mpa_v2_params->ird) &
+ MPA_V2_PEER2PEER_MODEL) {
+ if (ntohs(mpa_v2_params->ord) &
+ MPA_V2_RDMA_WRITE_RTR)
+ ep->mpa_attr.p2p_type =
+ FW_RI_INIT_P2PTYPE_RDMA_WRITE;
+ else if (ntohs(mpa_v2_params->ord) &
+ MPA_V2_RDMA_READ_RTR)
+ ep->mpa_attr.p2p_type =
+ FW_RI_INIT_P2PTYPE_READ_REQ;
+ }
+ }
+ } else if (mpa->revision == 1)
+ if (peer2peer)
+ ep->mpa_attr.p2p_type = p2p_type;
+
PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
- "xmit_marker_enabled=%d, version=%d\n", __func__,
- ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
- ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+ "xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = "
+ "%d\n", __func__, ep->mpa_attr.crc_enabled,
+ ep->mpa_attr.recv_marker_enabled,
+ ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
+ ep->mpa_attr.p2p_type, p2p_type);
+
+ /*
+ * If responder's RTR does not match with that of initiator, assign
+ * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not
+ * generated when moving QP to RTS state.
+ * A TERM message will be sent after QP has moved to RTS state
+ */
+ if ((ep->mpa_attr.version == 2) &&
+ (ep->mpa_attr.p2p_type != p2p_type)) {
+ ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+ rtr_mismatch = 1;
+ }
attrs.mpa_attr = ep->mpa_attr;
attrs.max_ird = ep->ird;
@@ -961,6 +1133,39 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
ep->com.qp, mask, &attrs, 1);
if (err)
goto err;
+
+ /*
+ * If responder's RTR requirement did not match with what initiator
+ * supports, generate TERM message
+ */
+ if (rtr_mismatch) {
+ printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__);
+ attrs.layer_etype = LAYER_MPA | DDP_LLP;
+ attrs.ecode = MPA_NOMATCH_RTR;
+ attrs.next_state = C4IW_QP_STATE_TERMINATE;
+ err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+ C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * Generate TERM if initiator IRD is not sufficient for responder
+ * provided ORD. Currently, we do the same behaviour even when
+ * responder provided IRD is also not sufficient as regards to
+ * initiator ORD.
+ */
+ if (insuff_ird) {
+ printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n",
+ __func__);
+ attrs.layer_etype = LAYER_MPA | DDP_LLP;
+ attrs.ecode = MPA_INSUFF_IRD;
+ attrs.next_state = C4IW_QP_STATE_TERMINATE;
+ err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+ C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+ err = -ENOMEM;
+ goto out;
+ }
goto out;
err:
state_set(&ep->com, ABORTING);
@@ -973,6 +1178,7 @@ out:
static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
{
struct mpa_message *mpa;
+ struct mpa_v2_conn_params *mpa_v2_params;
u16 plen;
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
@@ -1013,7 +1219,9 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
/*
* Validate MPA Header.
*/
- if (mpa->revision != mpa_rev) {
+ if (mpa->revision > mpa_rev) {
+ printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
+ " Received = %d\n", __func__, mpa_rev, mpa->revision);
abort_connection(ep, skb, GFP_KERNEL);
return;
}
@@ -1056,9 +1264,37 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
ep->mpa_attr.recv_marker_enabled = markers_enabled;
ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
- ep->mpa_attr.version = mpa_rev;
- ep->mpa_attr.p2p_type = peer2peer ? p2p_type :
- FW_RI_INIT_P2PTYPE_DISABLED;
+ ep->mpa_attr.version = mpa->revision;
+ if (mpa->revision == 1)
+ ep->tried_with_mpa_v1 = 1;
+ ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+
+ if (mpa->revision == 2) {
+ ep->mpa_attr.enhanced_rdma_conn =
+ mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
+ if (ep->mpa_attr.enhanced_rdma_conn) {
+ mpa_v2_params = (struct mpa_v2_conn_params *)
+ (ep->mpa_pkt + sizeof(*mpa));
+ ep->ird = ntohs(mpa_v2_params->ird) &
+ MPA_V2_IRD_ORD_MASK;
+ ep->ord = ntohs(mpa_v2_params->ord) &
+ MPA_V2_IRD_ORD_MASK;
+ if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
+ if (peer2peer) {
+ if (ntohs(mpa_v2_params->ord) &
+ MPA_V2_RDMA_WRITE_RTR)
+ ep->mpa_attr.p2p_type =
+ FW_RI_INIT_P2PTYPE_RDMA_WRITE;
+ else if (ntohs(mpa_v2_params->ord) &
+ MPA_V2_RDMA_READ_RTR)
+ ep->mpa_attr.p2p_type =
+ FW_RI_INIT_P2PTYPE_READ_REQ;
+ }
+ }
+ } else if (mpa->revision == 1)
+ if (peer2peer)
+ ep->mpa_attr.p2p_type = p2p_type;
+
PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
"xmit_marker_enabled=%d, version=%d p2p_type=%d\n", __func__,
ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
@@ -1550,6 +1786,112 @@ static int is_neg_adv_abort(unsigned int status)
status == CPL_ERR_PERSIST_NEG_ADVICE;
}
+static int c4iw_reconnect(struct c4iw_ep *ep)
+{
+ int err = 0;
+ struct rtable *rt;
+ struct net_device *pdev;
+ struct neighbour *neigh;
+ int step;
+
+ PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id);
+ init_timer(&ep->timer);
+
+ /*
+ * Allocate an active TID to initiate a TCP connection.
+ */
+ ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep);
+ if (ep->atid == -1) {
+ printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
+ err = -ENOMEM;
+ goto fail2;
+ }
+
+ /* find a route */
+ rt = find_route(ep->com.dev,
+ ep->com.cm_id->local_addr.sin_addr.s_addr,
+ ep->com.cm_id->remote_addr.sin_addr.s_addr,
+ ep->com.cm_id->local_addr.sin_port,
+ ep->com.cm_id->remote_addr.sin_port, 0);
+ if (!rt) {
+ printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
+ err = -EHOSTUNREACH;
+ goto fail3;
+ }
+ ep->dst = &rt->dst;
+
+ neigh = dst_get_neighbour(ep->dst);
+
+ /* get a l2t entry */
+ if (neigh->dev->flags & IFF_LOOPBACK) {
+ PDBG("%s LOOPBACK\n", __func__);
+ pdev = ip_dev_find(&init_net,
+ ep->com.cm_id->remote_addr.sin_addr.s_addr);
+ ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+ neigh, pdev, 0);
+ ep->mtu = pdev->mtu;
+ ep->tx_chan = cxgb4_port_chan(pdev);
+ ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+ step = ep->com.dev->rdev.lldi.ntxq /
+ ep->com.dev->rdev.lldi.nchan;
+ ep->txq_idx = cxgb4_port_idx(pdev) * step;
+ step = ep->com.dev->rdev.lldi.nrxq /
+ ep->com.dev->rdev.lldi.nchan;
+ ep->ctrlq_idx = cxgb4_port_idx(pdev);
+ ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+ cxgb4_port_idx(pdev) * step];
+ dev_put(pdev);
+ } else {
+ ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+ neigh, neigh->dev, 0);
+ ep->mtu = dst_mtu(ep->dst);
+ ep->tx_chan = cxgb4_port_chan(neigh->dev);
+ ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
+ step = ep->com.dev->rdev.lldi.ntxq /
+ ep->com.dev->rdev.lldi.nchan;
+ ep->txq_idx = cxgb4_port_idx(neigh->dev) * step;
+ ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);
+ step = ep->com.dev->rdev.lldi.nrxq /
+ ep->com.dev->rdev.lldi.nchan;
+ ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+ cxgb4_port_idx(neigh->dev) * step];
+ }
+ if (!ep->l2t) {
+ printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
+ err = -ENOMEM;
+ goto fail4;
+ }
+
+ PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
+ __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid,
+ ep->l2t->idx);
+
+ state_set(&ep->com, CONNECTING);
+ ep->tos = 0;
+
+ /* send connect request to rnic */
+ err = send_connect(ep);
+ if (!err)
+ goto out;
+
+ cxgb4_l2t_release(ep->l2t);
+fail4:
+ dst_release(ep->dst);
+fail3:
+ cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
+fail2:
+ /*
+ * remember to send notification to upper layer.
+ * We are in here so the upper layer is not aware that this is
+ * re-connect attempt and so, upper layer is still waiting for
+ * response of 1st connect request.
+ */
+ connect_reply_upcall(ep, -ECONNRESET);
+ c4iw_put_ep(&ep->com);
+out:
+ return err;
+}
+
static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
{
struct cpl_abort_req_rss *req = cplhdr(skb);
@@ -1573,8 +1915,11 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
/*
* Wake up any threads in rdma_init() or rdma_fini().
+ * However, this is not needed if com state is just
+ * MPA_REQ_SENT
*/
- c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+ if (ep->com.state != MPA_REQ_SENT)
+ c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
mutex_lock(&ep->com.mutex);
switch (ep->com.state) {
@@ -1585,7 +1930,21 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
break;
case MPA_REQ_SENT:
stop_ep_timer(ep);
- connect_reply_upcall(ep, -ECONNRESET);
+ if (mpa_rev == 2 && ep->tried_with_mpa_v1)
+ connect_reply_upcall(ep, -ECONNRESET);
+ else {
+ /*
+ * we just don't send notification upwards because we
+ * want to retry with mpa_v1 without upper layers even
+ * knowing it.
+ *
+ * do some housekeeping so as to re-initiate the
+ * connection
+ */
+ PDBG("%s: mpa_rev=%d. Retrying with mpav1\n", __func__,
+ mpa_rev);
+ ep->retry_with_mpa_v1 = 1;
+ }
break;
case MPA_REP_SENT:
break;
@@ -1621,7 +1980,9 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
dst_confirm(ep->dst);
if (ep->com.state != ABORTING) {
__state_set(&ep->com, DEAD);
- release = 1;
+ /* we don't release if we want to retry with mpa_v1 */
+ if (!ep->retry_with_mpa_v1)
+ release = 1;
}
mutex_unlock(&ep->com.mutex);
@@ -1641,6 +2002,15 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
out:
if (release)
release_ep_resources(ep);
+
+ /* retry with mpa-v1 */
+ if (ep && ep->retry_with_mpa_v1) {
+ cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
+ dst_release(ep->dst);
+ cxgb4_l2t_release(ep->l2t);
+ c4iw_reconnect(ep);
+ }
+
return 0;
}
@@ -1792,18 +2162,40 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
goto err;
}
- cm_id->add_ref(cm_id);
- ep->com.cm_id = cm_id;
- ep->com.qp = qp;
+ if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+ if (conn_param->ord > ep->ird) {
+ ep->ird = conn_param->ird;
+ ep->ord = conn_param->ord;
+ send_mpa_reject(ep, conn_param->private_data,
+ conn_param->private_data_len);
+ abort_connection(ep, NULL, GFP_KERNEL);
+ err = -ENOMEM;
+ goto err;
+ }
+ if (conn_param->ird > ep->ord) {
+ if (!ep->ord)
+ conn_param->ird = 1;
+ else {
+ abort_connection(ep, NULL, GFP_KERNEL);
+ err = -ENOMEM;
+ goto err;
+ }
+ }
+ }
ep->ird = conn_param->ird;
ep->ord = conn_param->ord;
- if (peer2peer && ep->ird == 0)
- ep->ird = 1;
+ if (ep->mpa_attr.version != 2)
+ if (peer2peer && ep->ird == 0)
+ ep->ird = 1;
PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
+ cm_id->add_ref(cm_id);
+ ep->com.cm_id = cm_id;
+ ep->com.qp = qp;
+
/* bind QP to EP and move to RTS */
attrs.mpa_attr = ep->mpa_attr;
attrs.max_ird = ep->ird;
@@ -1944,6 +2336,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ep->com.dev->rdev.lldi.nchan;
ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
cxgb4_port_idx(neigh->dev) * step];
+ ep->retry_with_mpa_v1 = 0;
+ ep->tried_with_mpa_v1 = 0;
}
if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
@@ -2323,8 +2717,11 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
/*
* Wake up any threads in rdma_init() or rdma_fini().
+ * However, this is not needed if com state is just
+ * MPA_REQ_SENT
*/
- c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+ if (ep->com.state != MPA_REQ_SENT)
+ c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
sched(dev, skb);
return 0;
}
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index 1720dc790d13..f35a935267e7 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -185,7 +185,7 @@ static void insert_recv_cqe(struct t4_wq *wq, struct t4_cq *cq)
V_CQE_OPCODE(FW_RI_SEND) |
V_CQE_TYPE(0) |
V_CQE_SWCQE(1) |
- V_CQE_QPID(wq->rq.qid));
+ V_CQE_QPID(wq->sq.qid));
cqe.bits_type_ts = cpu_to_be64(V_CQE_GENBIT((u64)cq->gen));
cq->sw_queue[cq->sw_pidx] = cqe;
t4_swcq_produce(cq);
@@ -818,6 +818,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
chp->cq.size--; /* status page */
chp->ibcq.cqe = entries - 2;
spin_lock_init(&chp->lock);
+ spin_lock_init(&chp->comp_handler_lock);
atomic_set(&chp->refcnt, 1);
init_waitqueue_head(&chp->wait);
ret = insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid);
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 40a13cc633a3..6d0df6ec161b 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -376,10 +376,8 @@ struct uld_ctx {
struct c4iw_dev *dev;
};
-static void c4iw_remove(struct uld_ctx *ctx)
+static void c4iw_dealloc(struct uld_ctx *ctx)
{
- PDBG("%s c4iw_dev %p\n", __func__, ctx->dev);
- c4iw_unregister_device(ctx->dev);
c4iw_rdev_close(&ctx->dev->rdev);
idr_destroy(&ctx->dev->cqidr);
idr_destroy(&ctx->dev->qpidr);
@@ -389,11 +387,30 @@ static void c4iw_remove(struct uld_ctx *ctx)
ctx->dev = NULL;
}
+static void c4iw_remove(struct uld_ctx *ctx)
+{
+ PDBG("%s c4iw_dev %p\n", __func__, ctx->dev);
+ c4iw_unregister_device(ctx->dev);
+ c4iw_dealloc(ctx);
+}
+
+static int rdma_supported(const struct cxgb4_lld_info *infop)
+{
+ return infop->vr->stag.size > 0 && infop->vr->pbl.size > 0 &&
+ infop->vr->rq.size > 0 && infop->vr->qp.size > 0 &&
+ infop->vr->cq.size > 0 && infop->vr->ocq.size > 0;
+}
+
static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
{
struct c4iw_dev *devp;
int ret;
+ if (!rdma_supported(infop)) {
+ printk(KERN_INFO MOD "%s: RDMA not supported on this device.\n",
+ pci_name(infop->pdev));
+ return ERR_PTR(-ENOSYS);
+ }
devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp));
if (!devp) {
printk(KERN_ERR MOD "Cannot allocate ib device\n");
@@ -414,7 +431,6 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
ret = c4iw_rdev_open(&devp->rdev);
if (ret) {
- mutex_unlock(&dev_mutex);
printk(KERN_ERR MOD "Unable to open CXIO rdev err %d\n", ret);
ib_dealloc_device(&devp->ibdev);
return ERR_PTR(ret);
@@ -519,15 +535,24 @@ static int c4iw_uld_state_change(void *handle, enum cxgb4_state new_state)
case CXGB4_STATE_UP:
printk(KERN_INFO MOD "%s: Up\n", pci_name(ctx->lldi.pdev));
if (!ctx->dev) {
- int ret = 0;
+ int ret;
ctx->dev = c4iw_alloc(&ctx->lldi);
- if (!IS_ERR(ctx->dev))
- ret = c4iw_register_device(ctx->dev);
- if (IS_ERR(ctx->dev) || ret)
+ if (IS_ERR(ctx->dev)) {
+ printk(KERN_ERR MOD
+ "%s: initialization failed: %ld\n",
+ pci_name(ctx->lldi.pdev),
+ PTR_ERR(ctx->dev));
+ ctx->dev = NULL;
+ break;
+ }
+ ret = c4iw_register_device(ctx->dev);
+ if (ret) {
printk(KERN_ERR MOD
"%s: RDMA registration failed: %d\n",
pci_name(ctx->lldi.pdev), ret);
+ c4iw_dealloc(ctx);
+ }
}
break;
case CXGB4_STATE_DOWN:
diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
index c13041a0aeba..397cb36cf103 100644
--- a/drivers/infiniband/hw/cxgb4/ev.c
+++ b/drivers/infiniband/hw/cxgb4/ev.c
@@ -42,6 +42,7 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
{
struct ib_event event;
struct c4iw_qp_attributes attrs;
+ unsigned long flag;
if ((qhp->attr.state == C4IW_QP_STATE_ERROR) ||
(qhp->attr.state == C4IW_QP_STATE_TERMINATE)) {
@@ -72,7 +73,9 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
if (qhp->ibqp.event_handler)
(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
+ spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+ spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
}
void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
@@ -183,11 +186,14 @@ out:
int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
{
struct c4iw_cq *chp;
+ unsigned long flag;
chp = get_chp(dev, qid);
- if (chp)
+ if (chp) {
+ spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
- else
+ spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
+ } else
PDBG("%s unknown cqid 0x%x\n", __func__, qid);
return 0;
}
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 4f045375c8e2..1357c5bf209b 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -309,6 +309,7 @@ struct c4iw_cq {
struct c4iw_dev *rhp;
struct t4_cq cq;
spinlock_t lock;
+ spinlock_t comp_handler_lock;
atomic_t refcnt;
wait_queue_head_t wait;
};
@@ -323,6 +324,7 @@ struct c4iw_mpa_attributes {
u8 recv_marker_enabled;
u8 xmit_marker_enabled;
u8 crc_enabled;
+ u8 enhanced_rdma_conn;
u8 version;
u8 p2p_type;
};
@@ -349,6 +351,8 @@ struct c4iw_qp_attributes {
u8 is_terminate_local;
struct c4iw_mpa_attributes mpa_attr;
struct c4iw_ep *llp_stream_handle;
+ u8 layer_etype;
+ u8 ecode;
};
struct c4iw_qp {
@@ -501,11 +505,18 @@ enum c4iw_mmid_state {
#define MPA_KEY_REP "MPA ID Rep Frame"
#define MPA_MAX_PRIVATE_DATA 256
+#define MPA_ENHANCED_RDMA_CONN 0x10
#define MPA_REJECT 0x20
#define MPA_CRC 0x40
#define MPA_MARKERS 0x80
#define MPA_FLAGS_MASK 0xE0
+#define MPA_V2_PEER2PEER_MODEL 0x8000
+#define MPA_V2_ZERO_LEN_FPDU_RTR 0x4000
+#define MPA_V2_RDMA_WRITE_RTR 0x8000
+#define MPA_V2_RDMA_READ_RTR 0x4000
+#define MPA_V2_IRD_ORD_MASK 0x3FFF
+
#define c4iw_put_ep(ep) { \
PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__, \
ep, atomic_read(&((ep)->kref.refcount))); \
@@ -528,6 +539,11 @@ struct mpa_message {
u8 private_data[0];
};
+struct mpa_v2_conn_params {
+ __be16 ird;
+ __be16 ord;
+};
+
struct terminate_message {
u8 layer_etype;
u8 ecode;
@@ -580,7 +596,10 @@ enum c4iw_ddp_ecodes {
enum c4iw_mpa_ecodes {
MPA_CRC_ERR = 0x02,
- MPA_MARKER_ERR = 0x03
+ MPA_MARKER_ERR = 0x03,
+ MPA_LOCAL_CATA = 0x05,
+ MPA_INSUFF_IRD = 0x06,
+ MPA_NOMATCH_RTR = 0x07,
};
enum c4iw_ep_state {
@@ -651,6 +670,8 @@ struct c4iw_ep {
u16 txq_idx;
u16 ctrlq_idx;
u8 tos;
+ u8 retry_with_mpa_v1;
+ u8 tried_with_mpa_v1;
};
static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id)
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index a41578e48c7b..d6ccc7e84802 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -917,7 +917,11 @@ static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe,
wqe->u.terminate.type = FW_RI_TYPE_TERMINATE;
wqe->u.terminate.immdlen = cpu_to_be32(sizeof *term);
term = (struct terminate_message *)wqe->u.terminate.termmsg;
- build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
+ if (qhp->attr.layer_etype == (LAYER_MPA|DDP_LLP)) {
+ term->layer_etype = qhp->attr.layer_etype;
+ term->ecode = qhp->attr.ecode;
+ } else
+ build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
c4iw_ofld_send(&qhp->rhp->rdev, skb);
}
@@ -941,8 +945,11 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&rchp->lock, flag);
- if (flushed)
+ if (flushed) {
+ spin_lock_irqsave(&rchp->comp_handler_lock, flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+ spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+ }
/* locking hierarchy: cq lock first, then qp lock. */
spin_lock_irqsave(&schp->lock, flag);
@@ -952,13 +959,17 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&schp->lock, flag);
- if (flushed)
+ if (flushed) {
+ spin_lock_irqsave(&schp->comp_handler_lock, flag);
(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+ spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+ }
}
static void flush_qp(struct c4iw_qp *qhp)
{
struct c4iw_cq *rchp, *schp;
+ unsigned long flag;
rchp = get_chp(qhp->rhp, qhp->attr.rcq);
schp = get_chp(qhp->rhp, qhp->attr.scq);
@@ -966,8 +977,16 @@ static void flush_qp(struct c4iw_qp *qhp)
if (qhp->ibqp.uobject) {
t4_set_wq_in_error(&qhp->wq);
t4_set_cq_in_error(&rchp->cq);
- if (schp != rchp)
+ spin_lock_irqsave(&rchp->comp_handler_lock, flag);
+ (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+ spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+ if (schp != rchp) {
t4_set_cq_in_error(&schp->cq);
+ spin_lock_irqsave(&schp->comp_handler_lock, flag);
+ (*schp->ibcq.comp_handler)(&schp->ibcq,
+ schp->ibcq.cq_context);
+ spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+ }
return;
}
__flush_qp(qhp, rchp, schp);
@@ -1012,6 +1031,7 @@ out:
static void build_rtr_msg(u8 p2p_type, struct fw_ri_init *init)
{
+ PDBG("%s p2p_type = %d\n", __func__, p2p_type);
memset(&init->u, 0, sizeof init->u);
switch (p2p_type) {
case FW_RI_INIT_P2PTYPE_RDMA_WRITE:
@@ -1206,12 +1226,16 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
disconnect = 1;
c4iw_get_ep(&qhp->ep->com);
}
+ if (qhp->ibqp.uobject)
+ t4_set_wq_in_error(&qhp->wq);
ret = rdma_fini(rhp, qhp, ep);
if (ret)
goto err;
break;
case C4IW_QP_STATE_TERMINATE:
set_state(qhp, C4IW_QP_STATE_TERMINATE);
+ qhp->attr.layer_etype = attrs->layer_etype;
+ qhp->attr.ecode = attrs->ecode;
if (qhp->ibqp.uobject)
t4_set_wq_in_error(&qhp->wq);
ep = qhp->ep;
@@ -1222,6 +1246,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
break;
case C4IW_QP_STATE_ERROR:
set_state(qhp, C4IW_QP_STATE_ERROR);
+ if (qhp->ibqp.uobject)
+ t4_set_wq_in_error(&qhp->wq);
if (!internal) {
abort = 1;
disconnect = 1;
@@ -1334,7 +1360,10 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
rhp = qhp->rhp;
attrs.next_state = C4IW_QP_STATE_ERROR;
- c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+ if (qhp->attr.state == C4IW_QP_STATE_TERMINATE)
+ c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
+ else
+ c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
wait_event(qhp->wait, !qhp->ep);
remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index d9b1bb40f480..818d721fc448 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -125,7 +125,7 @@ int ehca_create_eq(struct ehca_shca *shca,
tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
- IRQF_DISABLED, "ehca_eq",
+ 0, "ehca_eq",
(void *)shca);
if (ret < 0)
ehca_err(ib_dev, "Can't map interrupt handler.");
@@ -133,7 +133,7 @@ int ehca_create_eq(struct ehca_shca *shca,
tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);
ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
- IRQF_DISABLED, "ehca_neq",
+ 0, "ehca_neq",
(void *)shca);
if (ret < 0)
ehca_err(ib_dev, "Can't map interrupt handler.");
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 32fb34201aba..964f85520798 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -977,6 +977,9 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
struct hcp_modify_qp_control_block *mqpcb;
u64 hret, update_mask;
+ if (srq_init_attr->srq_type != IB_SRQT_BASIC)
+ return ERR_PTR(-ENOSYS);
+
/* For common attributes, internal_create_qp() takes its info
* out of qp_init_attr, so copy all common attrs there.
*/
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 7c1eebe8c7c9..824a4d508836 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -34,6 +34,7 @@
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
+#include <linux/stat.h>
#include <linux/vmalloc.h>
#include "ipath_kernel.h"
diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
index 386e2c717c53..26271984b717 100644
--- a/drivers/infiniband/hw/ipath/ipath_srq.c
+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
@@ -107,6 +107,11 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
u32 sz;
struct ib_srq *ret;
+ if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
+ ret = ERR_PTR(-ENOSYS);
+ goto done;
+ }
+
if (srq_init_attr->attr.max_wr == 0) {
ret = ERR_PTR(-EINVAL);
goto done;
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c
index cfed5399f074..dc66c4506916 100644
--- a/drivers/infiniband/hw/ipath/ipath_user_pages.c
+++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c
@@ -79,7 +79,7 @@ static int __ipath_get_user_pages(unsigned long start_page, size_t num_pages,
goto bail_release;
}
- current->mm->locked_vm += num_pages;
+ current->mm->pinned_vm += num_pages;
ret = 0;
goto bail;
@@ -178,7 +178,7 @@ void ipath_release_user_pages(struct page **p, size_t num_pages)
__ipath_release_user_pages(p, num_pages, 1);
- current->mm->locked_vm -= num_pages;
+ current->mm->pinned_vm -= num_pages;
up_write(&current->mm->mmap_sem);
}
@@ -195,7 +195,7 @@ static void user_pages_account(struct work_struct *_work)
container_of(_work, struct ipath_user_pages_work, work);
down_write(&work->mm->mmap_sem);
- work->mm->locked_vm -= work->num_pages;
+ work->mm->pinned_vm -= work->num_pages;
up_write(&work->mm->mmap_sem);
mmput(work->mm);
kfree(work);
diff --git a/drivers/infiniband/hw/mlx4/Kconfig b/drivers/infiniband/hw/mlx4/Kconfig
index bd995b2b50d8..24ab11a9ad1e 100644
--- a/drivers/infiniband/hw/mlx4/Kconfig
+++ b/drivers/infiniband/hw/mlx4/Kconfig
@@ -1,6 +1,7 @@
config MLX4_INFINIBAND
tristate "Mellanox ConnectX HCA support"
- depends on NETDEVICES && NETDEV_10000 && PCI
+ depends on NETDEVICES && ETHERNET && PCI
+ select NET_VENDOR_MELLANOX
select MLX4_CORE
---help---
This driver provides low-level InfiniBand support for
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index fa643f4f4e28..77f3dbc0aaa1 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -128,6 +128,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
(dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) &&
(dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR))
props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
+ if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)
+ props->device_cap_flags |= IB_DEVICE_XRC;
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff;
@@ -181,8 +183,12 @@ mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num)
static int ib_link_query_port(struct ib_device *ibdev, u8 port,
struct ib_port_attr *props,
+ struct ib_smp *in_mad,
struct ib_smp *out_mad)
{
+ int ext_active_speed;
+ int err;
+
props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16));
props->lmc = out_mad->data[34] & 0x7;
props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18));
@@ -203,6 +209,39 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port,
props->max_vl_num = out_mad->data[37] >> 4;
props->init_type_reply = out_mad->data[41] >> 4;
+ /* Check if extended speeds (EDR/FDR/...) are supported */
+ if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
+ ext_active_speed = out_mad->data[62] >> 4;
+
+ switch (ext_active_speed) {
+ case 1:
+ props->active_speed = 16; /* FDR */
+ break;
+ case 2:
+ props->active_speed = 32; /* EDR */
+ break;
+ }
+ }
+
+ /* If reported active speed is QDR, check if is FDR-10 */
+ if (props->active_speed == 4) {
+ if (to_mdev(ibdev)->dev->caps.ext_port_cap[port] &
+ MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
+ init_query_mad(in_mad);
+ in_mad->attr_id = MLX4_ATTR_EXTENDED_PORT_INFO;
+ in_mad->attr_mod = cpu_to_be32(port);
+
+ err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port,
+ NULL, NULL, in_mad, out_mad);
+ if (err)
+ return err;
+
+ /* Checking LinkSpeedActive for FDR-10 */
+ if (out_mad->data[15] & 0x1)
+ props->active_speed = 8;
+ }
+ }
+
return 0;
}
@@ -227,7 +266,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port,
props->pkey_tbl_len = 1;
props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46));
props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48));
- props->max_mtu = IB_MTU_2048;
+ props->max_mtu = IB_MTU_4096;
props->subnet_timeout = 0;
props->max_vl_num = out_mad->data[37] >> 4;
props->init_type_reply = 0;
@@ -274,7 +313,7 @@ static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
goto out;
err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ?
- ib_link_query_port(ibdev, port, props, out_mad) :
+ ib_link_query_port(ibdev, port, props, in_mad, out_mad) :
eth_link_query_port(ibdev, port, props, out_mad);
out:
@@ -566,6 +605,57 @@ static int mlx4_ib_dealloc_pd(struct ib_pd *pd)
return 0;
}
+static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ struct mlx4_ib_xrcd *xrcd;
+ int err;
+
+ if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+ return ERR_PTR(-ENOSYS);
+
+ xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL);
+ if (!xrcd)
+ return ERR_PTR(-ENOMEM);
+
+ err = mlx4_xrcd_alloc(to_mdev(ibdev)->dev, &xrcd->xrcdn);
+ if (err)
+ goto err1;
+
+ xrcd->pd = ib_alloc_pd(ibdev);
+ if (IS_ERR(xrcd->pd)) {
+ err = PTR_ERR(xrcd->pd);
+ goto err2;
+ }
+
+ xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, 1, 0);
+ if (IS_ERR(xrcd->cq)) {
+ err = PTR_ERR(xrcd->cq);
+ goto err3;
+ }
+
+ return &xrcd->ibxrcd;
+
+err3:
+ ib_dealloc_pd(xrcd->pd);
+err2:
+ mlx4_xrcd_free(to_mdev(ibdev)->dev, xrcd->xrcdn);
+err1:
+ kfree(xrcd);
+ return ERR_PTR(err);
+}
+
+static int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+ ib_destroy_cq(to_mxrcd(xrcd)->cq);
+ ib_dealloc_pd(to_mxrcd(xrcd)->pd);
+ mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn);
+ kfree(xrcd);
+
+ return 0;
+}
+
static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
{
struct mlx4_ib_qp *mqp = to_mqp(ibqp);
@@ -1044,7 +1134,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
(1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
(1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
- (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+ (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_XSRQ) |
+ (1ull << IB_USER_VERBS_CMD_OPEN_QP);
ibdev->ib_dev.query_device = mlx4_ib_query_device;
ibdev->ib_dev.query_port = mlx4_ib_query_port;
@@ -1093,6 +1185,14 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr;
ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc;
+ if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
+ ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
+ ibdev->ib_dev.dealloc_xrcd = mlx4_ib_dealloc_xrcd;
+ ibdev->ib_dev.uverbs_cmd_mask |=
+ (1ull << IB_USER_VERBS_CMD_OPEN_XRCD) |
+ (1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
+ }
+
spin_lock_init(&iboe->lock);
if (init_node_data(ibdev))
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index e4bf2cff8662..ed80345c99ae 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -56,6 +56,13 @@ struct mlx4_ib_pd {
u32 pdn;
};
+struct mlx4_ib_xrcd {
+ struct ib_xrcd ibxrcd;
+ u32 xrcdn;
+ struct ib_pd *pd;
+ struct ib_cq *cq;
+};
+
struct mlx4_ib_cq_buf {
struct mlx4_buf buf;
struct mlx4_mtt mtt;
@@ -138,6 +145,7 @@ struct mlx4_ib_qp {
struct mlx4_mtt mtt;
int buf_size;
struct mutex mutex;
+ u16 xrcdn;
u32 flags;
u8 port;
u8 alt_port;
@@ -211,6 +219,11 @@ static inline struct mlx4_ib_pd *to_mpd(struct ib_pd *ibpd)
return container_of(ibpd, struct mlx4_ib_pd, ibpd);
}
+static inline struct mlx4_ib_xrcd *to_mxrcd(struct ib_xrcd *ibxrcd)
+{
+ return container_of(ibxrcd, struct mlx4_ib_xrcd, ibxrcd);
+}
+
static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq)
{
return container_of(ibcq, struct mlx4_ib_cq, ibcq);
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 3a91d9d8dc51..a16f0c8e6f3f 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -302,15 +302,14 @@ static int send_wqe_overhead(enum ib_qp_type type, u32 flags)
}
static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
- int is_user, int has_srq, struct mlx4_ib_qp *qp)
+ int is_user, int has_rq, struct mlx4_ib_qp *qp)
{
/* Sanity check RQ size before proceeding */
if (cap->max_recv_wr > dev->dev->caps.max_wqes ||
cap->max_recv_sge > dev->dev->caps.max_rq_sg)
return -EINVAL;
- if (has_srq) {
- /* QPs attached to an SRQ should have no RQ */
+ if (!has_rq) {
if (cap->max_recv_wr)
return -EINVAL;
@@ -463,6 +462,14 @@ static int set_user_sq_size(struct mlx4_ib_dev *dev,
return 0;
}
+static int qp_has_rq(struct ib_qp_init_attr *attr)
+{
+ if (attr->qp_type == IB_QPT_XRC_INI || attr->qp_type == IB_QPT_XRC_TGT)
+ return 0;
+
+ return !attr->srq;
+}
+
static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
@@ -479,7 +486,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
qp->sq_signal_bits = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE);
- err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp);
+ err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, qp_has_rq(init_attr), qp);
if (err)
goto err;
@@ -513,7 +520,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err)
goto err_mtt;
- if (!init_attr->srq) {
+ if (qp_has_rq(init_attr)) {
err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
ucmd.db_addr, &qp->db);
if (err)
@@ -532,7 +539,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err)
goto err;
- if (!init_attr->srq) {
+ if (qp_has_rq(init_attr)) {
err = mlx4_db_alloc(dev->dev, &qp->db, 0);
if (err)
goto err;
@@ -575,6 +582,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err)
goto err_qpn;
+ if (init_attr->qp_type == IB_QPT_XRC_TGT)
+ qp->mqp.qpn |= (1 << 23);
+
/*
* Hardware wants QPN written in big-endian order (after
* shifting) for send doorbell. Precompute this value to save
@@ -592,9 +602,8 @@ err_qpn:
err_wrid:
if (pd->uobject) {
- if (!init_attr->srq)
- mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context),
- &qp->db);
+ if (qp_has_rq(init_attr))
+ mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db);
} else {
kfree(qp->sq.wrid);
kfree(qp->rq.wrid);
@@ -610,7 +619,7 @@ err_buf:
mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
err_db:
- if (!pd->uobject && !init_attr->srq)
+ if (!pd->uobject && qp_has_rq(init_attr))
mlx4_db_free(dev->dev, &qp->db);
err:
@@ -671,6 +680,33 @@ static void del_gid_entries(struct mlx4_ib_qp *qp)
}
}
+static struct mlx4_ib_pd *get_pd(struct mlx4_ib_qp *qp)
+{
+ if (qp->ibqp.qp_type == IB_QPT_XRC_TGT)
+ return to_mpd(to_mxrcd(qp->ibqp.xrcd)->pd);
+ else
+ return to_mpd(qp->ibqp.pd);
+}
+
+static void get_cqs(struct mlx4_ib_qp *qp,
+ struct mlx4_ib_cq **send_cq, struct mlx4_ib_cq **recv_cq)
+{
+ switch (qp->ibqp.qp_type) {
+ case IB_QPT_XRC_TGT:
+ *send_cq = to_mcq(to_mxrcd(qp->ibqp.xrcd)->cq);
+ *recv_cq = *send_cq;
+ break;
+ case IB_QPT_XRC_INI:
+ *send_cq = to_mcq(qp->ibqp.send_cq);
+ *recv_cq = *send_cq;
+ break;
+ default:
+ *send_cq = to_mcq(qp->ibqp.send_cq);
+ *recv_cq = to_mcq(qp->ibqp.recv_cq);
+ break;
+ }
+}
+
static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
int is_user)
{
@@ -682,8 +718,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
printk(KERN_WARNING "mlx4_ib: modify QP %06x to RESET failed.\n",
qp->mqp.qpn);
- send_cq = to_mcq(qp->ibqp.send_cq);
- recv_cq = to_mcq(qp->ibqp.recv_cq);
+ get_cqs(qp, &send_cq, &recv_cq);
mlx4_ib_lock_cqs(send_cq, recv_cq);
@@ -706,7 +741,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
mlx4_mtt_cleanup(dev->dev, &qp->mtt);
if (is_user) {
- if (!qp->ibqp.srq)
+ if (qp->rq.wqe_cnt)
mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context),
&qp->db);
ib_umem_release(qp->umem);
@@ -714,7 +749,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
kfree(qp->sq.wrid);
kfree(qp->rq.wrid);
mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
- if (!qp->ibqp.srq)
+ if (qp->rq.wqe_cnt)
mlx4_db_free(dev->dev, &qp->db);
}
@@ -725,10 +760,10 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata)
{
- struct mlx4_ib_dev *dev = to_mdev(pd->device);
struct mlx4_ib_sqp *sqp;
struct mlx4_ib_qp *qp;
int err;
+ u16 xrcdn = 0;
/*
* We only support LSO and multicast loopback blocking, and
@@ -739,10 +774,20 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
return ERR_PTR(-EINVAL);
if (init_attr->create_flags &&
- (pd->uobject || init_attr->qp_type != IB_QPT_UD))
+ (udata || init_attr->qp_type != IB_QPT_UD))
return ERR_PTR(-EINVAL);
switch (init_attr->qp_type) {
+ case IB_QPT_XRC_TGT:
+ pd = to_mxrcd(init_attr->xrcd)->pd;
+ xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn;
+ init_attr->send_cq = to_mxrcd(init_attr->xrcd)->cq;
+ /* fall through */
+ case IB_QPT_XRC_INI:
+ if (!(to_mdev(pd->device)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+ return ERR_PTR(-ENOSYS);
+ init_attr->recv_cq = init_attr->send_cq;
+ /* fall through */
case IB_QPT_RC:
case IB_QPT_UC:
case IB_QPT_UD:
@@ -751,13 +796,14 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
if (!qp)
return ERR_PTR(-ENOMEM);
- err = create_qp_common(dev, pd, init_attr, udata, 0, qp);
+ err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata, 0, qp);
if (err) {
kfree(qp);
return ERR_PTR(err);
}
qp->ibqp.qp_num = qp->mqp.qpn;
+ qp->xrcdn = xrcdn;
break;
}
@@ -765,7 +811,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
case IB_QPT_GSI:
{
/* Userspace is not allowed to create special QPs: */
- if (pd->uobject)
+ if (udata)
return ERR_PTR(-EINVAL);
sqp = kzalloc(sizeof *sqp, GFP_KERNEL);
@@ -774,8 +820,8 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
qp = &sqp->qp;
- err = create_qp_common(dev, pd, init_attr, udata,
- dev->dev->caps.sqp_start +
+ err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata,
+ to_mdev(pd->device)->dev->caps.sqp_start +
(init_attr->qp_type == IB_QPT_SMI ? 0 : 2) +
init_attr->port_num - 1,
qp);
@@ -801,11 +847,13 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp)
{
struct mlx4_ib_dev *dev = to_mdev(qp->device);
struct mlx4_ib_qp *mqp = to_mqp(qp);
+ struct mlx4_ib_pd *pd;
if (is_qp0(dev, mqp))
mlx4_CLOSE_PORT(dev->dev, mqp->port);
- destroy_qp_common(dev, mqp, !!qp->pd->uobject);
+ pd = get_pd(mqp);
+ destroy_qp_common(dev, mqp, !!pd->ibpd.uobject);
if (is_sqp(dev, mqp))
kfree(to_msqp(mqp));
@@ -821,6 +869,8 @@ static int to_mlx4_st(enum ib_qp_type type)
case IB_QPT_RC: return MLX4_QP_ST_RC;
case IB_QPT_UC: return MLX4_QP_ST_UC;
case IB_QPT_UD: return MLX4_QP_ST_UD;
+ case IB_QPT_XRC_INI:
+ case IB_QPT_XRC_TGT: return MLX4_QP_ST_XRC;
case IB_QPT_SMI:
case IB_QPT_GSI: return MLX4_QP_ST_MLX;
default: return -1;
@@ -959,6 +1009,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
{
struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
struct mlx4_ib_qp *qp = to_mqp(ibqp);
+ struct mlx4_ib_pd *pd;
+ struct mlx4_ib_cq *send_cq, *recv_cq;
struct mlx4_qp_context *context;
enum mlx4_qp_optpar optpar = 0;
int sqd_event;
@@ -1014,8 +1066,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
context->sq_size_stride |= qp->sq.wqe_shift - 4;
- if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+ if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
+ context->xrcd = cpu_to_be32((u32) qp->xrcdn);
+ }
if (qp->ibqp.uobject)
context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
@@ -1079,8 +1133,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH;
}
- context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
- context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
+ pd = get_pd(qp);
+ get_cqs(qp, &send_cq, &recv_cq);
+ context->pd = cpu_to_be32(pd->pdn);
+ context->cqn_send = cpu_to_be32(send_cq->mcq.cqn);
+ context->cqn_recv = cpu_to_be32(recv_cq->mcq.cqn);
+ context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
/* Set "fast registration enabled" for all kernel QPs */
if (!qp->ibqp.uobject)
@@ -1106,8 +1164,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (attr_mask & IB_QP_SQ_PSN)
context->next_send_psn = cpu_to_be32(attr->sq_psn);
- context->cqn_send = cpu_to_be32(to_mcq(ibqp->send_cq)->mcq.cqn);
-
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
if (attr->max_dest_rd_atomic)
context->params2 |=
@@ -1130,8 +1186,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (attr_mask & IB_QP_RQ_PSN)
context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
- context->cqn_recv = cpu_to_be32(to_mcq(ibqp->recv_cq)->mcq.cqn);
-
if (attr_mask & IB_QP_QKEY) {
context->qkey = cpu_to_be32(attr->qkey);
optpar |= MLX4_QP_OPTPAR_Q_KEY;
@@ -1140,7 +1194,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (ibqp->srq)
context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn);
- if (!ibqp->srq && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+ if (qp->rq.wqe_cnt && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
context->db_rec_addr = cpu_to_be64(qp->db.dma);
if (cur_state == IB_QPS_INIT &&
@@ -1225,17 +1279,17 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
* entries and reinitialize the QP.
*/
if (new_state == IB_QPS_RESET && !ibqp->uobject) {
- mlx4_ib_cq_clean(to_mcq(ibqp->recv_cq), qp->mqp.qpn,
+ mlx4_ib_cq_clean(recv_cq, qp->mqp.qpn,
ibqp->srq ? to_msrq(ibqp->srq): NULL);
- if (ibqp->send_cq != ibqp->recv_cq)
- mlx4_ib_cq_clean(to_mcq(ibqp->send_cq), qp->mqp.qpn, NULL);
+ if (send_cq != recv_cq)
+ mlx4_ib_cq_clean(send_cq, qp->mqp.qpn, NULL);
qp->rq.head = 0;
qp->rq.tail = 0;
qp->sq.head = 0;
qp->sq.tail = 0;
qp->sq_next_wqe = 0;
- if (!ibqp->srq)
+ if (qp->rq.wqe_cnt)
*qp->db.db = 0;
}
@@ -1547,14 +1601,13 @@ static void set_masked_atomic_seg(struct mlx4_wqe_masked_atomic_seg *aseg,
}
static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
- struct ib_send_wr *wr, __be16 *vlan)
+ struct ib_send_wr *wr)
{
memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av));
dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan;
memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6);
- *vlan = dseg->vlan;
}
static void set_mlx_icrc_seg(void *dseg)
@@ -1657,7 +1710,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
__be32 uninitialized_var(lso_hdr_sz);
__be32 blh;
int i;
- __be16 vlan = cpu_to_be16(0xffff);
spin_lock_irqsave(&qp->sq.lock, flags);
@@ -1761,7 +1813,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break;
case IB_QPT_UD:
- set_datagram_seg(wqe, wr, &vlan);
+ set_datagram_seg(wqe, wr);
wqe += sizeof (struct mlx4_wqe_datagram_seg);
size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
@@ -1824,11 +1876,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ?
MLX4_WQE_CTRL_FENCE : 0) | size;
- if (be16_to_cpu(vlan) < 0x1000) {
- ctrl->ins_vlan = 1 << 6;
- ctrl->vlan_tag = vlan;
- }
-
/*
* Make sure descriptor is fully written before
* setting ownership bit (because HW can start
diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
index 818b7ecace5e..39542f3703b8 100644
--- a/drivers/infiniband/hw/mlx4/srq.c
+++ b/drivers/infiniband/hw/mlx4/srq.c
@@ -76,6 +76,8 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
struct mlx4_ib_srq *srq;
struct mlx4_wqe_srq_next_seg *next;
struct mlx4_wqe_data_seg *scatter;
+ u32 cqn;
+ u16 xrcdn;
int desc_size;
int buf_size;
int err;
@@ -174,12 +176,18 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
}
}
- err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt,
+ cqn = (init_attr->srq_type == IB_SRQT_XRC) ?
+ to_mcq(init_attr->ext.xrc.cq)->mcq.cqn : 0;
+ xrcdn = (init_attr->srq_type == IB_SRQT_XRC) ?
+ to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn :
+ (u16) dev->dev->caps.reserved_xrcds;
+ err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, cqn, xrcdn, &srq->mtt,
srq->db.dma, &srq->msrq);
if (err)
goto err_wrid;
srq->msrq.event = mlx4_ib_srq_event;
+ srq->ibsrq.ext.xrc.srq_num = srq->msrq.srqn;
if (pd->uobject)
if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) {
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 365fe0e14192..cb9a0b976804 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -438,6 +438,9 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
struct mthca_srq *srq;
int err;
+ if (init_attr->srq_type != IB_SRQT_BASIC)
+ return ERR_PTR(-ENOSYS);
+
srq = kmalloc(sizeof *srq, GFP_KERNEL);
if (!srq)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/infiniband/hw/nes/Makefile b/drivers/infiniband/hw/nes/Makefile
index 35148513c47e..97820c23ecef 100644
--- a/drivers/infiniband/hw/nes/Makefile
+++ b/drivers/infiniband/hw/nes/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_INFINIBAND_NES) += iw_nes.o
-iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o
+iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o nes_mgt.o
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index 2d668c69f6d9..5965b3df8f2f 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -84,7 +84,7 @@ module_param(send_first, int, 0644);
MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection");
-unsigned int nes_drv_opt = 0;
+unsigned int nes_drv_opt = NES_DRV_OPT_DISABLE_INT_MOD | NES_DRV_OPT_ENABLE_PAU;
module_param(nes_drv_opt, int, 0644);
MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters");
@@ -130,9 +130,6 @@ static struct notifier_block nes_net_notifier = {
.notifier_call = nes_net_event
};
-
-
-
/**
* nes_inetaddr_event
*/
@@ -321,6 +318,9 @@ void nes_rem_ref(struct ib_qp *ibqp)
}
if (atomic_dec_and_test(&nesqp->refcount)) {
+ if (nesqp->pau_mode)
+ nes_destroy_pau_qp(nesdev, nesqp);
+
/* Destroy the QP */
cqp_request = nes_get_cqp_request(nesdev);
if (cqp_request == NULL) {
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index 6fe79876009e..568b4f11380a 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -102,6 +102,7 @@
#define NES_DRV_OPT_NO_INLINE_DATA 0x00000080
#define NES_DRV_OPT_DISABLE_INT_MOD 0x00000100
#define NES_DRV_OPT_DISABLE_VIRT_WQ 0x00000200
+#define NES_DRV_OPT_ENABLE_PAU 0x00000400
#define NES_AEQ_EVENT_TIMEOUT 2500
#define NES_DISCONNECT_EVENT_TIMEOUT 2000
@@ -128,6 +129,7 @@
#define NES_DBG_IW_RX 0x00020000
#define NES_DBG_IW_TX 0x00040000
#define NES_DBG_SHUTDOWN 0x00080000
+#define NES_DBG_PAU 0x00100000
#define NES_DBG_RSVD1 0x10000000
#define NES_DBG_RSVD2 0x20000000
#define NES_DBG_RSVD3 0x40000000
@@ -162,6 +164,7 @@ do { \
#include "nes_context.h"
#include "nes_user.h"
#include "nes_cm.h"
+#include "nes_mgt.h"
extern int max_mtu;
#define max_frame_len (max_mtu+ETH_HLEN)
@@ -202,6 +205,8 @@ extern atomic_t cm_nodes_created;
extern atomic_t cm_nodes_destroyed;
extern atomic_t cm_accel_dropped_pkts;
extern atomic_t cm_resets_recvd;
+extern atomic_t pau_qps_created;
+extern atomic_t pau_qps_destroyed;
extern u32 int_mod_timer_init;
extern u32 int_mod_cq_depth_256;
@@ -273,6 +278,14 @@ struct nes_device {
u8 link_recheck;
};
+/* Receive skb private area - must fit in skb->cb area */
+struct nes_rskb_cb {
+ u64 busaddr;
+ u32 maplen;
+ u32 seqnum;
+ u8 *data_start;
+ struct nes_qp *nesqp;
+};
static inline __le32 get_crc_value(struct nes_v4_quad *nes_quad)
{
@@ -305,8 +318,8 @@ set_wqe_32bit_value(__le32 *wqe_words, u32 index, u32 value)
static inline void
nes_fill_init_cqp_wqe(struct nes_hw_cqp_wqe *cqp_wqe, struct nes_device *nesdev)
{
- set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_CTX_LOW_IDX,
- (u64)((unsigned long) &nesdev->cqp));
+ cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX] = 0;
+ cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0;
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0;
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0;
cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0;
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index c118663e4437..dfce9ea98a39 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -77,26 +77,19 @@ atomic_t cm_nodes_destroyed;
atomic_t cm_accel_dropped_pkts;
atomic_t cm_resets_recvd;
-static inline int mini_cm_accelerated(struct nes_cm_core *,
- struct nes_cm_node *);
-static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *,
- struct nes_vnic *, struct nes_cm_info *);
+static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *);
+static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, struct nes_vnic *, struct nes_cm_info *);
static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *);
-static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *,
- struct nes_vnic *, u16, void *, struct nes_cm_info *);
+static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, struct nes_vnic *, u16, void *, struct nes_cm_info *);
static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
-static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *,
- struct nes_cm_node *);
-static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
- struct nes_cm_node *);
-static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
- struct sk_buff *);
+static int mini_cm_accept(struct nes_cm_core *, struct nes_cm_node *);
+static int mini_cm_reject(struct nes_cm_core *, struct nes_cm_node *);
+static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, struct sk_buff *);
static int mini_cm_dealloc_core(struct nes_cm_core *);
static int mini_cm_get(struct nes_cm_core *);
static int mini_cm_set(struct nes_cm_core *, u32, u32);
-static void form_cm_frame(struct sk_buff *, struct nes_cm_node *,
- void *, u32, void *, u32, u8);
+static void form_cm_frame(struct sk_buff *, struct nes_cm_node *, void *, u32, void *, u32, u8);
static int add_ref_cm_node(struct nes_cm_node *);
static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
@@ -111,16 +104,14 @@ static int send_syn(struct nes_cm_node *, u32, struct sk_buff *);
static int send_reset(struct nes_cm_node *, struct sk_buff *);
static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb);
static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb);
-static void process_packet(struct nes_cm_node *, struct sk_buff *,
- struct nes_cm_core *);
+static void process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *);
static void active_open_err(struct nes_cm_node *, struct sk_buff *, int);
static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int);
static void cleanup_retrans_entry(struct nes_cm_node *);
static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *);
static void free_retrans_entry(struct nes_cm_node *cm_node);
-static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
- struct sk_buff *skb, int optionsize, int passive);
+static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, struct sk_buff *skb, int optionsize, int passive);
/* CM event handler functions */
static void cm_event_connected(struct nes_cm_event *);
@@ -130,6 +121,12 @@ static void cm_event_mpa_req(struct nes_cm_event *);
static void cm_event_mpa_reject(struct nes_cm_event *);
static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node);
+/* MPA build functions */
+static int cm_build_mpa_frame(struct nes_cm_node *, u8 **, u16 *, u8 *, u8);
+static void build_mpa_v2(struct nes_cm_node *, void *, u8);
+static void build_mpa_v1(struct nes_cm_node *, void *, u8);
+static void build_rdma0_msg(struct nes_cm_node *, struct nes_qp **);
+
static void print_core(struct nes_cm_core *core);
/* External CM API Interface */
@@ -159,12 +156,21 @@ atomic_t cm_connecteds;
atomic_t cm_connect_reqs;
atomic_t cm_rejects;
+int nes_add_ref_cm_node(struct nes_cm_node *cm_node)
+{
+ return add_ref_cm_node(cm_node);
+}
+
+int nes_rem_ref_cm_node(struct nes_cm_node *cm_node)
+{
+ return rem_ref_cm_node(cm_node->cm_core, cm_node);
+}
/**
* create_event
*/
-static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
- enum nes_cm_event_type type)
+static struct nes_cm_event *create_event(struct nes_cm_node * cm_node,
+ enum nes_cm_event_type type)
{
struct nes_cm_event *event;
@@ -186,10 +192,10 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
event->cm_info.cm_id = cm_node->cm_id;
nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, "
- "dst_addr=%08x[%x], src_addr=%08x[%x]\n",
- cm_node, event, type, event->cm_info.loc_addr,
- event->cm_info.loc_port, event->cm_info.rem_addr,
- event->cm_info.rem_port);
+ "dst_addr=%08x[%x], src_addr=%08x[%x]\n",
+ cm_node, event, type, event->cm_info.loc_addr,
+ event->cm_info.loc_port, event->cm_info.rem_addr,
+ event->cm_info.rem_port);
nes_cm_post_event(event);
return event;
@@ -201,14 +207,19 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
*/
static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
{
+ u8 start_addr = 0;
+ u8 *start_ptr = &start_addr;
+ u8 **start_buff = &start_ptr;
+ u16 buff_len = 0;
+
if (!skb) {
nes_debug(NES_DBG_CM, "skb set to NULL\n");
return -1;
}
/* send an MPA Request frame */
- form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
- cm_node->mpa_frame_size, SET_ACK);
+ cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REQUEST);
+ form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK);
return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
}
@@ -217,7 +228,11 @@ static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
static int send_mpa_reject(struct nes_cm_node *cm_node)
{
- struct sk_buff *skb = NULL;
+ struct sk_buff *skb = NULL;
+ u8 start_addr = 0;
+ u8 *start_ptr = &start_addr;
+ u8 **start_buff = &start_ptr;
+ u16 buff_len = 0;
skb = dev_alloc_skb(MAX_CM_BUFFER);
if (!skb) {
@@ -226,8 +241,8 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
}
/* send an MPA reject frame */
- form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
- cm_node->mpa_frame_size, SET_ACK | SET_FIN);
+ cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY);
+ form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);
cm_node->state = NES_CM_STATE_FIN_WAIT1;
return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
@@ -239,24 +254,31 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
* IETF MPA frame
*/
static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
- u32 len)
+ u32 len)
{
- struct ietf_mpa_frame *mpa_frame;
+ struct ietf_mpa_v1 *mpa_frame;
+ struct ietf_mpa_v2 *mpa_v2_frame;
+ struct ietf_rtr_msg *rtr_msg;
+ int mpa_hdr_len;
+ int priv_data_len;
*type = NES_MPA_REQUEST_ACCEPT;
/* assume req frame is in tcp data payload */
- if (len < sizeof(struct ietf_mpa_frame)) {
+ if (len < sizeof(struct ietf_mpa_v1)) {
nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len);
return -EINVAL;
}
- mpa_frame = (struct ietf_mpa_frame *)buffer;
- cm_node->mpa_frame_size = ntohs(mpa_frame->priv_data_len);
+ /* points to the beginning of the frame, which could be MPA V1 or V2 */
+ mpa_frame = (struct ietf_mpa_v1 *)buffer;
+ mpa_hdr_len = sizeof(struct ietf_mpa_v1);
+ priv_data_len = ntohs(mpa_frame->priv_data_len);
+
/* make sure mpa private data len is less than 512 bytes */
- if (cm_node->mpa_frame_size > IETF_MAX_PRIV_DATA_LEN) {
+ if (priv_data_len > IETF_MAX_PRIV_DATA_LEN) {
nes_debug(NES_DBG_CM, "The received Length of Private"
- " Data field exceeds 512 octets\n");
+ " Data field exceeds 512 octets\n");
return -EINVAL;
}
/*
@@ -264,11 +286,22 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
* received MPA version and MPA key information
*
*/
- if (mpa_frame->rev != mpa_version) {
+ if (mpa_frame->rev != IETF_MPA_V1 && mpa_frame->rev != IETF_MPA_V2) {
+ nes_debug(NES_DBG_CM, "The received mpa version"
+ " is not supported\n");
+ return -EINVAL;
+ }
+ /*
+ * backwards compatibility only
+ */
+ if (mpa_frame->rev > cm_node->mpa_frame_rev) {
nes_debug(NES_DBG_CM, "The received mpa version"
- " can not be interoperated\n");
+ " can not be interoperated\n");
return -EINVAL;
+ } else {
+ cm_node->mpa_frame_rev = mpa_frame->rev;
}
+
if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE)) {
nes_debug(NES_DBG_CM, "Unexpected MPA Key received \n");
@@ -281,25 +314,75 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
}
}
- if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) {
+
+ if (priv_data_len + mpa_hdr_len != len) {
nes_debug(NES_DBG_CM, "The received ietf buffer was not right"
- " complete (%x + %x != %x)\n",
- cm_node->mpa_frame_size,
- (u32)sizeof(struct ietf_mpa_frame), len);
+ " complete (%x + %x != %x)\n",
+ priv_data_len, mpa_hdr_len, len);
return -EINVAL;
}
/* make sure it does not exceed the max size */
if (len > MAX_CM_BUFFER) {
nes_debug(NES_DBG_CM, "The received ietf buffer was too large"
- " (%x + %x != %x)\n",
- cm_node->mpa_frame_size,
- (u32)sizeof(struct ietf_mpa_frame), len);
+ " (%x + %x != %x)\n",
+ priv_data_len, mpa_hdr_len, len);
return -EINVAL;
}
+ cm_node->mpa_frame_size = priv_data_len;
+
+ switch (mpa_frame->rev) {
+ case IETF_MPA_V2: {
+ u16 ird_size;
+ u16 ord_size;
+ mpa_v2_frame = (struct ietf_mpa_v2 *)buffer;
+ mpa_hdr_len += IETF_RTR_MSG_SIZE;
+ cm_node->mpa_frame_size -= IETF_RTR_MSG_SIZE;
+ rtr_msg = &mpa_v2_frame->rtr_msg;
+
+ /* parse rtr message */
+ rtr_msg->ctrl_ird = ntohs(rtr_msg->ctrl_ird);
+ rtr_msg->ctrl_ord = ntohs(rtr_msg->ctrl_ord);
+ ird_size = rtr_msg->ctrl_ird & IETF_NO_IRD_ORD;
+ ord_size = rtr_msg->ctrl_ord & IETF_NO_IRD_ORD;
+
+ if (!(rtr_msg->ctrl_ird & IETF_PEER_TO_PEER)) {
+ /* send reset */
+ return -EINVAL;
+ }
+
+ if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
+ /* responder */
+ if (cm_node->ord_size > ird_size)
+ cm_node->ord_size = ird_size;
+ } else {
+ /* initiator */
+ if (cm_node->ord_size > ird_size)
+ cm_node->ord_size = ird_size;
+
+ if (cm_node->ird_size < ord_size) {
+ /* no resources available */
+ /* send terminate message */
+ return -EINVAL;
+ }
+ }
+
+ if (rtr_msg->ctrl_ord & IETF_RDMA0_READ) {
+ cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO;
+ } else if (rtr_msg->ctrl_ord & IETF_RDMA0_WRITE) {
+ cm_node->send_rdma0_op = SEND_RDMA_WRITE_ZERO;
+ } else { /* Not supported RDMA0 operation */
+ return -EINVAL;
+ }
+ break;
+ }
+ case IETF_MPA_V1:
+ default:
+ break;
+ }
+
/* copy entire MPA frame to our cm_node's frame */
- memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame),
- cm_node->mpa_frame_size);
+ memcpy(cm_node->mpa_frame_buf, buffer + mpa_hdr_len, cm_node->mpa_frame_size);
if (mpa_frame->flags & IETF_MPA_FLAGS_REJECT)
*type = NES_MPA_REQUEST_REJECT;
@@ -312,8 +395,8 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
* node info to build.
*/
static void form_cm_frame(struct sk_buff *skb,
- struct nes_cm_node *cm_node, void *options, u32 optionsize,
- void *data, u32 datasize, u8 flags)
+ struct nes_cm_node *cm_node, void *options, u32 optionsize,
+ void *data, u32 datasize, u8 flags)
{
struct tcphdr *tcph;
struct iphdr *iph;
@@ -322,14 +405,14 @@ static void form_cm_frame(struct sk_buff *skb,
u16 packetsize = sizeof(*iph);
packetsize += sizeof(*tcph);
- packetsize += optionsize + datasize;
+ packetsize += optionsize + datasize;
+ skb_trim(skb, 0);
memset(skb->data, 0x00, ETH_HLEN + sizeof(*iph) + sizeof(*tcph));
- skb->len = 0;
buf = skb_put(skb, packetsize + ETH_HLEN);
- ethh = (struct ethhdr *) buf;
+ ethh = (struct ethhdr *)buf;
buf += ETH_HLEN;
iph = (struct iphdr *)buf;
@@ -337,7 +420,7 @@ static void form_cm_frame(struct sk_buff *skb,
tcph = (struct tcphdr *)buf;
skb_reset_mac_header(skb);
skb_set_network_header(skb, ETH_HLEN);
- skb_set_transport_header(skb, ETH_HLEN+sizeof(*iph));
+ skb_set_transport_header(skb, ETH_HLEN + sizeof(*iph));
buf += sizeof(*tcph);
skb->ip_summed = CHECKSUM_PARTIAL;
@@ -350,14 +433,14 @@ static void form_cm_frame(struct sk_buff *skb,
ethh->h_proto = htons(0x0800);
iph->version = IPVERSION;
- iph->ihl = 5; /* 5 * 4Byte words, IP headr len */
+ iph->ihl = 5; /* 5 * 4Byte words, IP headr len */
iph->tos = 0;
iph->tot_len = htons(packetsize);
iph->id = htons(++cm_node->tcp_cntxt.loc_id);
iph->frag_off = htons(0x4000);
iph->ttl = 0x40;
- iph->protocol = 0x06; /* IPPROTO_TCP */
+ iph->protocol = 0x06; /* IPPROTO_TCP */
iph->saddr = htonl(cm_node->loc_addr);
iph->daddr = htonl(cm_node->rem_addr);
@@ -370,14 +453,16 @@ static void form_cm_frame(struct sk_buff *skb,
cm_node->tcp_cntxt.loc_ack_num = cm_node->tcp_cntxt.rcv_nxt;
tcph->ack_seq = htonl(cm_node->tcp_cntxt.loc_ack_num);
tcph->ack = 1;
- } else
+ } else {
tcph->ack_seq = 0;
+ }
if (flags & SET_SYN) {
cm_node->tcp_cntxt.loc_seq_num++;
tcph->syn = 1;
- } else
+ } else {
cm_node->tcp_cntxt.loc_seq_num += datasize;
+ }
if (flags & SET_FIN) {
cm_node->tcp_cntxt.loc_seq_num++;
@@ -398,10 +483,8 @@ static void form_cm_frame(struct sk_buff *skb,
skb_shinfo(skb)->nr_frags = 0;
cm_packets_created++;
-
}
-
/**
* print_core - dump a cm core
*/
@@ -413,7 +496,7 @@ static void print_core(struct nes_cm_core *core)
return;
nes_debug(NES_DBG_CM, "---------------------------------------------\n");
- nes_debug(NES_DBG_CM, "State : %u \n", core->state);
+ nes_debug(NES_DBG_CM, "State : %u \n", core->state);
nes_debug(NES_DBG_CM, "Listen Nodes : %u \n", atomic_read(&core->listen_node_cnt));
nes_debug(NES_DBG_CM, "Active Nodes : %u \n", atomic_read(&core->node_cnt));
@@ -423,6 +506,147 @@ static void print_core(struct nes_cm_core *core)
nes_debug(NES_DBG_CM, "-------------- end core ---------------\n");
}
+/**
+ * cm_build_mpa_frame - build a MPA V1 frame or MPA V2 frame
+ */
+static int cm_build_mpa_frame(struct nes_cm_node *cm_node, u8 **start_buff,
+ u16 *buff_len, u8 *pci_mem, u8 mpa_key)
+{
+ int ret = 0;
+
+ *start_buff = (pci_mem) ? pci_mem : &cm_node->mpa_frame_buf[0];
+
+ switch (cm_node->mpa_frame_rev) {
+ case IETF_MPA_V1:
+ *start_buff = (u8 *)*start_buff + sizeof(struct ietf_rtr_msg);
+ *buff_len = sizeof(struct ietf_mpa_v1) + cm_node->mpa_frame_size;
+ build_mpa_v1(cm_node, *start_buff, mpa_key);
+ break;
+ case IETF_MPA_V2:
+ *buff_len = sizeof(struct ietf_mpa_v2) + cm_node->mpa_frame_size;
+ build_mpa_v2(cm_node, *start_buff, mpa_key);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+/**
+ * build_mpa_v2 - build a MPA V2 frame
+ */
+static void build_mpa_v2(struct nes_cm_node *cm_node,
+ void *start_addr, u8 mpa_key)
+{
+ struct ietf_mpa_v2 *mpa_frame = (struct ietf_mpa_v2 *)start_addr;
+ struct ietf_rtr_msg *rtr_msg = &mpa_frame->rtr_msg;
+
+ /* initialize the upper 5 bytes of the frame */
+ build_mpa_v1(cm_node, start_addr, mpa_key);
+ mpa_frame->flags |= IETF_MPA_V2_FLAG; /* set a bit to indicate MPA V2 */
+ mpa_frame->priv_data_len += htons(IETF_RTR_MSG_SIZE);
+
+ /* initialize RTR msg */
+ rtr_msg->ctrl_ird = (cm_node->ird_size > IETF_NO_IRD_ORD) ?
+ IETF_NO_IRD_ORD : cm_node->ird_size;
+ rtr_msg->ctrl_ord = (cm_node->ord_size > IETF_NO_IRD_ORD) ?
+ IETF_NO_IRD_ORD : cm_node->ord_size;
+
+ rtr_msg->ctrl_ird |= IETF_PEER_TO_PEER;
+ rtr_msg->ctrl_ird |= IETF_FLPDU_ZERO_LEN;
+
+ switch (mpa_key) {
+ case MPA_KEY_REQUEST:
+ rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE;
+ rtr_msg->ctrl_ord |= IETF_RDMA0_READ;
+ break;
+ case MPA_KEY_REPLY:
+ switch (cm_node->send_rdma0_op) {
+ case SEND_RDMA_WRITE_ZERO:
+ rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE;
+ break;
+ case SEND_RDMA_READ_ZERO:
+ rtr_msg->ctrl_ord |= IETF_RDMA0_READ;
+ break;
+ }
+ }
+ rtr_msg->ctrl_ird = htons(rtr_msg->ctrl_ird);
+ rtr_msg->ctrl_ord = htons(rtr_msg->ctrl_ord);
+}
+
+/**
+ * build_mpa_v1 - build a MPA V1 frame
+ */
+static void build_mpa_v1(struct nes_cm_node *cm_node, void *start_addr, u8 mpa_key)
+{
+ struct ietf_mpa_v1 *mpa_frame = (struct ietf_mpa_v1 *)start_addr;
+
+ switch (mpa_key) {
+ case MPA_KEY_REQUEST:
+ memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
+ break;
+ case MPA_KEY_REPLY:
+ memcpy(mpa_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
+ break;
+ }
+ mpa_frame->flags = IETF_MPA_FLAGS_CRC;
+ mpa_frame->rev = cm_node->mpa_frame_rev;
+ mpa_frame->priv_data_len = htons(cm_node->mpa_frame_size);
+}
+
+static void build_rdma0_msg(struct nes_cm_node *cm_node, struct nes_qp **nesqp_addr)
+{
+ u64 u64temp;
+ struct nes_qp *nesqp = *nesqp_addr;
+ struct nes_hw_qp_wqe *wqe = &nesqp->hwqp.sq_vbase[0];
+
+ u64temp = (unsigned long)nesqp;
+ u64temp |= NES_SW_CONTEXT_ALIGN >> 1;
+ set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
+
+ wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
+
+ switch (cm_node->send_rdma0_op) {
+ case SEND_RDMA_WRITE_ZERO:
+ nes_debug(NES_DBG_CM, "Sending first write.\n");
+ wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+ cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
+ wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+ break;
+
+ case SEND_RDMA_READ_ZERO:
+ default:
+ if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO) {
+ printk(KERN_ERR "%s[%u]: Unsupported RDMA0 len operation=%u\n",
+ __func__, __LINE__, cm_node->send_rdma0_op);
+ WARN_ON(1);
+ }
+ nes_debug(NES_DBG_CM, "Sending first rdma operation.\n");
+ wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+ cpu_to_le32(NES_IWARP_SQ_OP_RDMAR);
+ wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX] = 1;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_HIGH_IDX] = 0;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] = 0;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_STAG_IDX] = 1;
+ wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 1;
+ break;
+ }
+
+ if (nesqp->sq_kmapped) {
+ nesqp->sq_kmapped = 0;
+ kunmap(nesqp->page);
+ }
+
+ /*use the reserved spot on the WQ for the extra first WQE*/
+ nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
+ NES_QPCONTEXT_ORDIRD_WRPDU |
+ NES_QPCONTEXT_ORDIRD_ALSMM));
+ nesqp->skip_lsmm = 1;
+ nesqp->hwqp.sq_tail = 0;
+}
/**
* schedule_nes_timer
@@ -430,10 +654,10 @@ static void print_core(struct nes_cm_core *core)
* rem_ref_cm_node(cm_core, cm_node);add_ref_cm_node(cm_node);
*/
int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
- enum nes_timer_type type, int send_retrans,
- int close_when_complete)
+ enum nes_timer_type type, int send_retrans,
+ int close_when_complete)
{
- unsigned long flags;
+ unsigned long flags;
struct nes_cm_core *cm_core = cm_node->cm_core;
struct nes_timer_entry *new_send;
int ret = 0;
@@ -454,7 +678,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
new_send->close_when_complete = close_when_complete;
if (type == NES_TIMER_TYPE_CLOSE) {
- new_send->timetosend += (HZ/10);
+ new_send->timetosend += (HZ / 10);
if (cm_node->recv_entry) {
kfree(new_send);
WARN_ON(1);
@@ -475,7 +699,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev);
if (ret != NETDEV_TX_OK) {
nes_debug(NES_DBG_CM, "Error sending packet %p "
- "(jiffies = %lu)\n", new_send, jiffies);
+ "(jiffies = %lu)\n", new_send, jiffies);
new_send->timetosend = jiffies;
ret = NETDEV_TX_OK;
} else {
@@ -504,6 +728,7 @@ static void nes_retrans_expired(struct nes_cm_node *cm_node)
struct iw_cm_id *cm_id = cm_node->cm_id;
enum nes_cm_node_state state = cm_node->state;
cm_node->state = NES_CM_STATE_CLOSED;
+
switch (state) {
case NES_CM_STATE_SYN_RCVD:
case NES_CM_STATE_CLOSING:
@@ -536,10 +761,10 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
spin_lock_irqsave(&nesqp->lock, qplockflags);
if (nesqp->cm_id) {
nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
- "refcount = %d: HIT A "
- "NES_TIMER_TYPE_CLOSE with something "
- "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
- atomic_read(&nesqp->refcount));
+ "refcount = %d: HIT A "
+ "NES_TIMER_TYPE_CLOSE with something "
+ "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+ atomic_read(&nesqp->refcount));
nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
nesqp->ibqp_state = IB_QPS_ERR;
@@ -548,10 +773,10 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
} else {
spin_unlock_irqrestore(&nesqp->lock, qplockflags);
nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
- "refcount = %d: HIT A "
- "NES_TIMER_TYPE_CLOSE with nothing "
- "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
- atomic_read(&nesqp->refcount));
+ "refcount = %d: HIT A "
+ "NES_TIMER_TYPE_CLOSE with nothing "
+ "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+ atomic_read(&nesqp->refcount));
}
} else if (rem_node) {
/* TIME_WAIT state */
@@ -580,11 +805,12 @@ static void nes_cm_timer_tick(unsigned long pass)
int ret = NETDEV_TX_OK;
struct list_head timer_list;
+
INIT_LIST_HEAD(&timer_list);
spin_lock_irqsave(&cm_core->ht_lock, flags);
list_for_each_safe(list_node, list_core_temp,
- &cm_core->connected_nodes) {
+ &cm_core->connected_nodes) {
cm_node = container_of(list_node, struct nes_cm_node, list);
if ((cm_node->recv_entry) || (cm_node->send_entry)) {
add_ref_cm_node(cm_node);
@@ -595,18 +821,19 @@ static void nes_cm_timer_tick(unsigned long pass)
list_for_each_safe(list_node, list_core_temp, &timer_list) {
cm_node = container_of(list_node, struct nes_cm_node,
- timer_entry);
+ timer_entry);
recv_entry = cm_node->recv_entry;
if (recv_entry) {
if (time_after(recv_entry->timetosend, jiffies)) {
if (nexttimeout > recv_entry->timetosend ||
- !settimer) {
+ !settimer) {
nexttimeout = recv_entry->timetosend;
settimer = 1;
}
- } else
+ } else {
handle_recv_entry(cm_node, 1);
+ }
}
spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
@@ -617,8 +844,8 @@ static void nes_cm_timer_tick(unsigned long pass)
if (time_after(send_entry->timetosend, jiffies)) {
if (cm_node->state != NES_CM_STATE_TSA) {
if ((nexttimeout >
- send_entry->timetosend) ||
- !settimer) {
+ send_entry->timetosend) ||
+ !settimer) {
nexttimeout =
send_entry->timetosend;
settimer = 1;
@@ -630,13 +857,13 @@ static void nes_cm_timer_tick(unsigned long pass)
}
if ((cm_node->state == NES_CM_STATE_TSA) ||
- (cm_node->state == NES_CM_STATE_CLOSED)) {
+ (cm_node->state == NES_CM_STATE_CLOSED)) {
free_retrans_entry(cm_node);
break;
}
if (!send_entry->retranscount ||
- !send_entry->retrycount) {
+ !send_entry->retrycount) {
cm_packets_dropped++;
free_retrans_entry(cm_node);
@@ -645,28 +872,28 @@ static void nes_cm_timer_tick(unsigned long pass)
nes_retrans_expired(cm_node);
cm_node->state = NES_CM_STATE_CLOSED;
spin_lock_irqsave(&cm_node->retrans_list_lock,
- flags);
+ flags);
break;
}
atomic_inc(&send_entry->skb->users);
cm_packets_retrans++;
nes_debug(NES_DBG_CM, "Retransmitting send_entry %p "
- "for node %p, jiffies = %lu, time to send = "
- "%lu, retranscount = %u, send_entry->seq_num = "
- "0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
- "0x%08X\n", send_entry, cm_node, jiffies,
- send_entry->timetosend,
- send_entry->retranscount,
- send_entry->seq_num,
- cm_node->tcp_cntxt.rem_ack_num);
+ "for node %p, jiffies = %lu, time to send = "
+ "%lu, retranscount = %u, send_entry->seq_num = "
+ "0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
+ "0x%08X\n", send_entry, cm_node, jiffies,
+ send_entry->timetosend,
+ send_entry->retranscount,
+ send_entry->seq_num,
+ cm_node->tcp_cntxt.rem_ack_num);
spin_unlock_irqrestore(&cm_node->retrans_list_lock,
- flags);
+ flags);
ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev);
spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
if (ret != NETDEV_TX_OK) {
nes_debug(NES_DBG_CM, "rexmit failed for "
- "node=%p\n", cm_node);
+ "node=%p\n", cm_node);
cm_packets_bounced++;
send_entry->retrycount--;
nexttimeout = jiffies + NES_SHORT_TIME;
@@ -676,18 +903,18 @@ static void nes_cm_timer_tick(unsigned long pass)
cm_packets_sent++;
}
nes_debug(NES_DBG_CM, "Packet Sent: retrans count = "
- "%u, retry count = %u.\n",
- send_entry->retranscount,
- send_entry->retrycount);
+ "%u, retry count = %u.\n",
+ send_entry->retranscount,
+ send_entry->retrycount);
if (send_entry->send_retrans) {
send_entry->retranscount--;
timetosend = (NES_RETRY_TIMEOUT <<
- (NES_DEFAULT_RETRANS - send_entry->retranscount));
+ (NES_DEFAULT_RETRANS - send_entry->retranscount));
send_entry->timetosend = jiffies +
- min(timetosend, NES_MAX_TIMEOUT);
+ min(timetosend, NES_MAX_TIMEOUT);
if (nexttimeout > send_entry->timetosend ||
- !settimer) {
+ !settimer) {
nexttimeout = send_entry->timetosend;
settimer = 1;
}
@@ -696,11 +923,11 @@ static void nes_cm_timer_tick(unsigned long pass)
close_when_complete =
send_entry->close_when_complete;
nes_debug(NES_DBG_CM, "cm_node=%p state=%d\n",
- cm_node, cm_node->state);
+ cm_node, cm_node->state);
free_retrans_entry(cm_node);
if (close_when_complete)
rem_ref_cm_node(cm_node->cm_core,
- cm_node);
+ cm_node);
}
} while (0);
@@ -710,7 +937,7 @@ static void nes_cm_timer_tick(unsigned long pass)
if (settimer) {
if (!timer_pending(&cm_core->tcp_timer)) {
- cm_core->tcp_timer.expires = nexttimeout;
+ cm_core->tcp_timer.expires = nexttimeout;
add_timer(&cm_core->tcp_timer);
}
}
@@ -721,13 +948,13 @@ static void nes_cm_timer_tick(unsigned long pass)
* send_syn
*/
static int send_syn(struct nes_cm_node *cm_node, u32 sendack,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
int ret;
int flags = SET_SYN;
char optionsbuffer[sizeof(struct option_mss) +
- sizeof(struct option_windowscale) + sizeof(struct option_base) +
- TCP_OPTIONS_PADDING];
+ sizeof(struct option_windowscale) + sizeof(struct option_base) +
+ TCP_OPTIONS_PADDING];
int optionssize = 0;
/* Sending MSS option */
@@ -854,7 +1081,7 @@ static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)
* find_node - find a cm node that matches the reference cm node
*/
static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
- u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
+ u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
{
unsigned long flags;
struct list_head *hte;
@@ -868,12 +1095,12 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
list_for_each_entry(cm_node, hte, list) {
/* compare quad, return node handle if a match */
nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n",
- cm_node->loc_addr, cm_node->loc_port,
- loc_addr, loc_port,
- cm_node->rem_addr, cm_node->rem_port,
- rem_addr, rem_port);
+ cm_node->loc_addr, cm_node->loc_port,
+ loc_addr, loc_port,
+ cm_node->rem_addr, cm_node->rem_port,
+ rem_addr, rem_port);
if ((cm_node->loc_addr == loc_addr) && (cm_node->loc_port == loc_port) &&
- (cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
+ (cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
add_ref_cm_node(cm_node);
spin_unlock_irqrestore(&cm_core->ht_lock, flags);
return cm_node;
@@ -890,7 +1117,7 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
* find_listener - find a cm node listening on this addr-port pair
*/
static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
- nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
+ nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
{
unsigned long flags;
struct nes_cm_listener *listen_node;
@@ -900,9 +1127,9 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
list_for_each_entry(listen_node, &cm_core->listen_list.list, list) {
/* compare node pair, return node handle if a match */
if (((listen_node->loc_addr == dst_addr) ||
- listen_node->loc_addr == 0x00000000) &&
- (listen_node->loc_port == dst_port) &&
- (listener_state & listen_node->listener_state)) {
+ listen_node->loc_addr == 0x00000000) &&
+ (listen_node->loc_port == dst_port) &&
+ (listener_state & listen_node->listener_state)) {
atomic_inc(&listen_node->ref_count);
spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
return listen_node;
@@ -927,7 +1154,7 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node
return -EINVAL;
nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n",
- cm_node);
+ cm_node);
spin_lock_irqsave(&cm_core->ht_lock, flags);
@@ -946,7 +1173,7 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node
* mini_cm_dec_refcnt_listen
*/
static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
- struct nes_cm_listener *listener, int free_hanging_nodes)
+ struct nes_cm_listener *listener, int free_hanging_nodes)
{
int ret = -EINVAL;
int err = 0;
@@ -957,8 +1184,8 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
struct list_head reset_list;
nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, "
- "refcnt=%d\n", listener, free_hanging_nodes,
- atomic_read(&listener->ref_count));
+ "refcnt=%d\n", listener, free_hanging_nodes,
+ atomic_read(&listener->ref_count));
/* free non-accelerated child nodes for this listener */
INIT_LIST_HEAD(&reset_list);
if (free_hanging_nodes) {
@@ -966,7 +1193,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
list_for_each_safe(list_pos, list_temp,
&g_cm_core->connected_nodes) {
cm_node = container_of(list_pos, struct nes_cm_node,
- list);
+ list);
if ((cm_node->listener == listener) &&
(!cm_node->accelerated)) {
add_ref_cm_node(cm_node);
@@ -978,7 +1205,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
list_for_each_safe(list_pos, list_temp, &reset_list) {
cm_node = container_of(list_pos, struct nes_cm_node,
- reset_entry);
+ reset_entry);
{
struct nes_cm_node *loopback = cm_node->loopbackpartner;
enum nes_cm_node_state old_state;
@@ -990,7 +1217,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
err = send_reset(cm_node, NULL);
if (err) {
cm_node->state =
- NES_CM_STATE_CLOSED;
+ NES_CM_STATE_CLOSED;
WARN_ON(1);
} else {
old_state = cm_node->state;
@@ -1035,10 +1262,9 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
- if (listener->nesvnic) {
+ if (listener->nesvnic)
nes_manage_apbvt(listener->nesvnic, listener->loc_port,
- PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
- }
+ PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
nes_debug(NES_DBG_CM, "destroying listener (%p)\n", listener);
@@ -1052,8 +1278,8 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
if (listener) {
if (atomic_read(&listener->pend_accepts_cnt) > 0)
nes_debug(NES_DBG_CM, "destroying listener (%p)"
- " with non-zero pending accepts=%u\n",
- listener, atomic_read(&listener->pend_accepts_cnt));
+ " with non-zero pending accepts=%u\n",
+ listener, atomic_read(&listener->pend_accepts_cnt));
}
return ret;
@@ -1064,7 +1290,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
* mini_cm_del_listen
*/
static int mini_cm_del_listen(struct nes_cm_core *cm_core,
- struct nes_cm_listener *listener)
+ struct nes_cm_listener *listener)
{
listener->listener_state = NES_CM_LISTENER_PASSIVE_STATE;
listener->cm_id = NULL; /* going to be destroyed pretty soon */
@@ -1076,9 +1302,10 @@ static int mini_cm_del_listen(struct nes_cm_core *cm_core,
* mini_cm_accelerated
*/
static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
- struct nes_cm_node *cm_node)
+ struct nes_cm_node *cm_node)
{
u32 was_timer_set;
+
cm_node->accelerated = 1;
if (cm_node->accept_pend) {
@@ -1112,7 +1339,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0);
if (IS_ERR(rt)) {
printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n",
- __func__, dst_ip);
+ __func__, dst_ip);
return rc;
}
@@ -1130,7 +1357,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
if (arpindex >= 0) {
if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
- neigh->ha, ETH_ALEN)){
+ neigh->ha, ETH_ALEN)) {
/* Mac address same as in nes_arp_table */
neigh_release(neigh);
ip_rt_put(rt);
@@ -1138,8 +1365,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
}
nes_manage_arp_cache(nesvnic->netdev,
- nesadapter->arp_table[arpindex].mac_addr,
- dst_ip, NES_ARP_DELETE);
+ nesadapter->arp_table[arpindex].mac_addr,
+ dst_ip, NES_ARP_DELETE);
}
nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
@@ -1161,8 +1388,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
* make_cm_node - create a new instance of a cm node
*/
static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
- struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
- struct nes_cm_listener *listener)
+ struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
+ struct nes_cm_listener *listener)
{
struct nes_cm_node *cm_node;
struct timespec ts;
@@ -1181,7 +1408,12 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
cm_node->rem_addr = cm_info->rem_addr;
cm_node->loc_port = cm_info->loc_port;
cm_node->rem_port = cm_info->rem_port;
- cm_node->send_write0 = send_first;
+
+ cm_node->mpa_frame_rev = mpa_version;
+ cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO;
+ cm_node->ird_size = IETF_NO_IRD_ORD;
+ cm_node->ord_size = IETF_NO_IRD_ORD;
+
nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n",
&cm_node->loc_addr, cm_node->loc_port,
&cm_node->rem_addr, cm_node->rem_port);
@@ -1191,7 +1423,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN);
nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", cm_node->listener,
- cm_node->cm_id);
+ cm_node->cm_id);
spin_lock_init(&cm_node->retrans_list_lock);
@@ -1202,11 +1434,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID;
cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
cm_node->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >>
- NES_CM_DEFAULT_RCV_WND_SCALE;
+ NES_CM_DEFAULT_RCV_WND_SCALE;
ts = current_kernel_time();
cm_node->tcp_cntxt.loc_seq_num = htonl(ts.tv_nsec);
cm_node->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) -
- sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;
+ sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;
cm_node->tcp_cntxt.rcv_nxt = 0;
/* get a unique session ID , add thread_id to an upcounter to handle race */
atomic_inc(&cm_core->node_cnt);
@@ -1222,12 +1454,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
cm_node->loopbackpartner = NULL;
/* get the mac addr for the remote node */
- if (ipv4_is_loopback(htonl(cm_node->rem_addr)))
+ if (ipv4_is_loopback(htonl(cm_node->rem_addr))) {
arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE);
- else {
+ } else {
oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex);
-
}
if (arpindex < 0) {
kfree(cm_node);
@@ -1260,7 +1491,7 @@ static int add_ref_cm_node(struct nes_cm_node *cm_node)
* rem_ref_cm_node - destroy an instance of a cm node
*/
static int rem_ref_cm_node(struct nes_cm_core *cm_core,
- struct nes_cm_node *cm_node)
+ struct nes_cm_node *cm_node)
{
unsigned long flags;
struct nes_qp *nesqp;
@@ -1291,9 +1522,9 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
} else {
if (cm_node->apbvt_set && cm_node->nesvnic) {
nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port,
- PCI_FUNC(
- cm_node->nesvnic->nesdev->pcidev->devfn),
- NES_MANAGE_APBVT_DEL);
+ PCI_FUNC(
+ cm_node->nesvnic->nesdev->pcidev->devfn),
+ NES_MANAGE_APBVT_DEL);
}
}
@@ -1314,7 +1545,7 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
* process_options
*/
static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
- u32 optionsize, u32 syn_packet)
+ u32 optionsize, u32 syn_packet)
{
u32 tmp;
u32 offset = 0;
@@ -1332,15 +1563,15 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
continue;
case OPTION_NUMBER_MSS:
nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d "
- "Size: %d\n", __func__,
- all_options->as_mss.length, offset, optionsize);
+ "Size: %d\n", __func__,
+ all_options->as_mss.length, offset, optionsize);
got_mss_option = 1;
if (all_options->as_mss.length != 4) {
return 1;
} else {
tmp = ntohs(all_options->as_mss.mss);
if (tmp > 0 && tmp <
- cm_node->tcp_cntxt.mss)
+ cm_node->tcp_cntxt.mss)
cm_node->tcp_cntxt.mss = tmp;
}
break;
@@ -1348,12 +1579,9 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
cm_node->tcp_cntxt.snd_wscale =
all_options->as_windowscale.shiftcount;
break;
- case OPTION_NUMBER_WRITE0:
- cm_node->send_write0 = 1;
- break;
default:
nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n",
- all_options->as_base.optionnum);
+ all_options->as_base.optionnum);
break;
}
offset += all_options->as_base.length;
@@ -1372,8 +1600,8 @@ static void drop_packet(struct sk_buff *skb)
static void handle_fin_pkt(struct nes_cm_node *cm_node)
{
nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
- "refcnt=%d\n", cm_node, cm_node->state,
- atomic_read(&cm_node->ref_count));
+ "refcnt=%d\n", cm_node, cm_node->state,
+ atomic_read(&cm_node->ref_count));
switch (cm_node->state) {
case NES_CM_STATE_SYN_RCVD:
case NES_CM_STATE_SYN_SENT:
@@ -1439,7 +1667,20 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
"listener=%p state=%d\n", __func__, __LINE__, cm_node,
cm_node->listener, cm_node->state);
- active_open_err(cm_node, skb, reset);
+ switch (cm_node->mpa_frame_rev) {
+ case IETF_MPA_V2:
+ cm_node->mpa_frame_rev = IETF_MPA_V1;
+ /* send a syn and goto syn sent state */
+ cm_node->state = NES_CM_STATE_SYN_SENT;
+ if (send_syn(cm_node, 0, NULL)) {
+ active_open_err(cm_node, skb, reset);
+ }
+ break;
+ case IETF_MPA_V1:
+ default:
+ active_open_err(cm_node, skb, reset);
+ break;
+ }
break;
case NES_CM_STATE_MPAREQ_RCVD:
atomic_inc(&cm_node->passive_state);
@@ -1475,21 +1716,21 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
{
-
- int ret = 0;
+ int ret = 0;
int datasize = skb->len;
u8 *dataloc = skb->data;
enum nes_cm_event_type type = NES_CM_EVENT_UNKNOWN;
- u32 res_type;
+ u32 res_type;
+
ret = parse_mpa(cm_node, dataloc, &res_type, datasize);
if (ret) {
nes_debug(NES_DBG_CM, "didn't like MPA Request\n");
if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) {
nes_debug(NES_DBG_CM, "%s[%u] create abort for "
- "cm_node=%p listener=%p state=%d\n", __func__,
- __LINE__, cm_node, cm_node->listener,
- cm_node->state);
+ "cm_node=%p listener=%p state=%d\n", __func__,
+ __LINE__, cm_node, cm_node->listener,
+ cm_node->state);
active_open_err(cm_node, skb, 1);
} else {
passive_open_err(cm_node, skb, 1);
@@ -1499,16 +1740,15 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
switch (cm_node->state) {
case NES_CM_STATE_ESTABLISHED:
- if (res_type == NES_MPA_REQUEST_REJECT) {
+ if (res_type == NES_MPA_REQUEST_REJECT)
/*BIG problem as we are receiving the MPA.. So should
- * not be REJECT.. This is Passive Open.. We can
- * only receive it Reject for Active Open...*/
+ * not be REJECT.. This is Passive Open.. We can
+ * only receive it Reject for Active Open...*/
WARN_ON(1);
- }
cm_node->state = NES_CM_STATE_MPAREQ_RCVD;
type = NES_CM_EVENT_MPA_REQ;
atomic_set(&cm_node->passive_state,
- NES_PASSIVE_STATE_INDICATED);
+ NES_PASSIVE_STATE_INDICATED);
break;
case NES_CM_STATE_MPAREQ_SENT:
cleanup_retrans_entry(cm_node);
@@ -1535,8 +1775,8 @@ static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)
case NES_CM_STATE_SYN_SENT:
case NES_CM_STATE_MPAREQ_SENT:
nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
- "listener=%p state=%d\n", __func__, __LINE__, cm_node,
- cm_node->listener, cm_node->state);
+ "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+ cm_node->listener, cm_node->state);
active_open_err(cm_node, skb, 1);
break;
case NES_CM_STATE_ESTABLISHED:
@@ -1550,11 +1790,11 @@ static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)
}
static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
int err;
- err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num))? 0 : 1;
+ err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num)) ? 0 : 1;
if (err)
active_open_err(cm_node, skb, 1);
@@ -1562,7 +1802,7 @@ static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph,
}
static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
int err = 0;
u32 seq;
@@ -1570,21 +1810,22 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
u32 loc_seq_num = cm_node->tcp_cntxt.loc_seq_num;
u32 rcv_nxt = cm_node->tcp_cntxt.rcv_nxt;
u32 rcv_wnd;
+
seq = ntohl(tcph->seq);
ack_seq = ntohl(tcph->ack_seq);
rcv_wnd = cm_node->tcp_cntxt.rcv_wnd;
if (ack_seq != loc_seq_num)
err = 1;
- else if (!between(seq, rcv_nxt, (rcv_nxt+rcv_wnd)))
+ else if (!between(seq, rcv_nxt, (rcv_nxt + rcv_wnd)))
err = 1;
if (err) {
nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
- "listener=%p state=%d\n", __func__, __LINE__, cm_node,
- cm_node->listener, cm_node->state);
+ "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+ cm_node->listener, cm_node->state);
indicate_pkt_err(cm_node, skb);
nes_debug(NES_DBG_CM, "seq ERROR cm_node =%p seq=0x%08X "
- "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
- rcv_wnd);
+ "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
+ rcv_wnd);
}
return err;
}
@@ -1594,9 +1835,8 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
* is created with a listener or it may comein as rexmitted packet which in
* that case will be just dropped.
*/
-
static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
- struct tcphdr *tcph)
+ struct tcphdr *tcph)
{
int ret;
u32 inc_sequence;
@@ -1615,15 +1855,15 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
case NES_CM_STATE_LISTENING:
/* Passive OPEN */
if (atomic_read(&cm_node->listener->pend_accepts_cnt) >
- cm_node->listener->backlog) {
+ cm_node->listener->backlog) {
nes_debug(NES_DBG_CM, "drop syn due to backlog "
- "pressure \n");
+ "pressure \n");
cm_backlog_drops++;
passive_open_err(cm_node, skb, 0);
break;
}
ret = handle_tcp_options(cm_node, tcph, skb, optionsize,
- 1);
+ 1);
if (ret) {
passive_open_err(cm_node, skb, 0);
/* drop pkt */
@@ -1657,9 +1897,8 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
}
static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
- struct tcphdr *tcph)
+ struct tcphdr *tcph)
{
-
int ret;
u32 inc_sequence;
int optionsize;
@@ -1678,7 +1917,7 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 0);
if (ret) {
nes_debug(NES_DBG_CM, "cm_node=%p tcp_options failed\n",
- cm_node);
+ cm_node);
break;
}
cleanup_retrans_entry(cm_node);
@@ -1717,12 +1956,13 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
}
static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
- struct tcphdr *tcph)
+ struct tcphdr *tcph)
{
int datasize = 0;
u32 inc_sequence;
int ret = 0;
int optionsize;
+
optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
if (check_seq(cm_node, tcph, skb))
@@ -1743,8 +1983,9 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
if (datasize) {
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
handle_rcv_mpa(cm_node, skb);
- } else /* rcvd ACK only */
+ } else { /* rcvd ACK only */
dev_kfree_skb_any(skb);
+ }
break;
case NES_CM_STATE_ESTABLISHED:
/* Passive OPEN */
@@ -1752,16 +1993,18 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
if (datasize) {
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
handle_rcv_mpa(cm_node, skb);
- } else
+ } else {
drop_packet(skb);
+ }
break;
case NES_CM_STATE_MPAREQ_SENT:
cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
if (datasize) {
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
handle_rcv_mpa(cm_node, skb);
- } else /* Could be just an ack pkt.. */
+ } else { /* Could be just an ack pkt.. */
dev_kfree_skb_any(skb);
+ }
break;
case NES_CM_STATE_LISTENING:
cleanup_retrans_entry(cm_node);
@@ -1802,14 +2045,15 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
- struct sk_buff *skb, int optionsize, int passive)
+ struct sk_buff *skb, int optionsize, int passive)
{
u8 *optionsloc = (u8 *)&tcph[1];
+
if (optionsize) {
if (process_options(cm_node, optionsloc, optionsize,
- (u32)tcph->syn)) {
+ (u32)tcph->syn)) {
nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n",
- __func__, cm_node);
+ __func__, cm_node);
if (passive)
passive_open_err(cm_node, skb, 1);
else
@@ -1819,7 +2063,7 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
}
cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) <<
- cm_node->tcp_cntxt.snd_wscale;
+ cm_node->tcp_cntxt.snd_wscale;
if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd)
cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd;
@@ -1830,18 +2074,18 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
* active_open_err() will send reset() if flag set..
* It will also send ABORT event.
*/
-
static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
- int reset)
+ int reset)
{
cleanup_retrans_entry(cm_node);
if (reset) {
nes_debug(NES_DBG_CM, "ERROR active err called for cm_node=%p, "
- "state=%d\n", cm_node, cm_node->state);
+ "state=%d\n", cm_node, cm_node->state);
add_ref_cm_node(cm_node);
send_reset(cm_node, skb);
- } else
+ } else {
dev_kfree_skb_any(skb);
+ }
cm_node->state = NES_CM_STATE_CLOSED;
create_event(cm_node, NES_CM_EVENT_ABORTED);
@@ -1851,15 +2095,14 @@ static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
* passive_open_err() will either do a reset() or will free up the skb and
* remove the cm_node.
*/
-
static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
- int reset)
+ int reset)
{
cleanup_retrans_entry(cm_node);
cm_node->state = NES_CM_STATE_CLOSED;
if (reset) {
nes_debug(NES_DBG_CM, "passive_open_err sending RST for "
- "cm_node=%p state =%d\n", cm_node, cm_node->state);
+ "cm_node=%p state =%d\n", cm_node, cm_node->state);
send_reset(cm_node, skb);
} else {
dev_kfree_skb_any(skb);
@@ -1874,6 +2117,7 @@ static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
static void free_retrans_entry(struct nes_cm_node *cm_node)
{
struct nes_timer_entry *send_entry;
+
send_entry = cm_node->send_entry;
if (send_entry) {
cm_node->send_entry = NULL;
@@ -1897,26 +2141,28 @@ static void cleanup_retrans_entry(struct nes_cm_node *cm_node)
* Returns skb if to be freed, else it will return NULL if already used..
*/
static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
- struct nes_cm_core *cm_core)
+ struct nes_cm_core *cm_core)
{
- enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
+ enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
struct tcphdr *tcph = tcp_hdr(skb);
- u32 fin_set = 0;
+ u32 fin_set = 0;
int ret = 0;
+
skb_pull(skb, ip_hdr(skb)->ihl << 2);
nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d "
- "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
- tcph->ack, tcph->rst, tcph->fin);
+ "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
+ tcph->ack, tcph->rst, tcph->fin);
- if (tcph->rst)
+ if (tcph->rst) {
pkt_type = NES_PKT_TYPE_RST;
- else if (tcph->syn) {
+ } else if (tcph->syn) {
pkt_type = NES_PKT_TYPE_SYN;
if (tcph->ack)
pkt_type = NES_PKT_TYPE_SYNACK;
- } else if (tcph->ack)
+ } else if (tcph->ack) {
pkt_type = NES_PKT_TYPE_ACK;
+ }
if (tcph->fin)
fin_set = 1;
@@ -1947,17 +2193,17 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
* mini_cm_listen - create a listen node with params
*/
static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
- struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
+ struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
{
struct nes_cm_listener *listener;
unsigned long flags;
nes_debug(NES_DBG_CM, "Search for 0x%08x : 0x%04x\n",
- cm_info->loc_addr, cm_info->loc_port);
+ cm_info->loc_addr, cm_info->loc_port);
/* cannot have multiple matching listeners */
listener = find_listener(cm_core, htonl(cm_info->loc_addr),
- htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
+ htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) {
/* find automatically incs ref count ??? */
atomic_dec(&listener->ref_count);
@@ -2003,9 +2249,9 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
}
nes_debug(NES_DBG_CM, "Api - listen(): addr=0x%08X, port=0x%04x,"
- " listener = %p, backlog = %d, cm_id = %p.\n",
- cm_info->loc_addr, cm_info->loc_port,
- listener, listener->backlog, listener->cm_id);
+ " listener = %p, backlog = %d, cm_id = %p.\n",
+ cm_info->loc_addr, cm_info->loc_port,
+ listener, listener->backlog, listener->cm_id);
return listener;
}
@@ -2015,26 +2261,20 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
* mini_cm_connect - make a connection node with params
*/
static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
- struct nes_vnic *nesvnic, u16 private_data_len,
- void *private_data, struct nes_cm_info *cm_info)
+ struct nes_vnic *nesvnic, u16 private_data_len,
+ void *private_data, struct nes_cm_info *cm_info)
{
int ret = 0;
struct nes_cm_node *cm_node;
struct nes_cm_listener *loopbackremotelistener;
struct nes_cm_node *loopbackremotenode;
struct nes_cm_info loopback_cm_info;
- u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + private_data_len;
- struct ietf_mpa_frame *mpa_frame = NULL;
+ u8 *start_buff;
/* create a CM connection node */
cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL);
if (!cm_node)
return NULL;
- mpa_frame = &cm_node->mpa_frame;
- memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
- mpa_frame->flags = IETF_MPA_FLAGS_CRC;
- mpa_frame->rev = IETF_MPA_VERSION;
- mpa_frame->priv_data_len = htons(private_data_len);
/* set our node side to client (active) side */
cm_node->tcp_cntxt.client = 1;
@@ -2042,8 +2282,8 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
if (cm_info->loc_addr == cm_info->rem_addr) {
loopbackremotelistener = find_listener(cm_core,
- ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
- NES_CM_LISTENER_ACTIVE_STATE);
+ ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
+ NES_CM_LISTENER_ACTIVE_STATE);
if (loopbackremotelistener == NULL) {
create_event(cm_node, NES_CM_EVENT_ABORTED);
} else {
@@ -2052,7 +2292,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
loopback_cm_info.rem_port = cm_info->loc_port;
loopback_cm_info.cm_id = loopbackremotelistener->cm_id;
loopbackremotenode = make_cm_node(cm_core, nesvnic,
- &loopback_cm_info, loopbackremotelistener);
+ &loopback_cm_info, loopbackremotelistener);
if (!loopbackremotenode) {
rem_ref_cm_node(cm_node->cm_core, cm_node);
return NULL;
@@ -2063,7 +2303,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
NES_CM_DEFAULT_RCV_WND_SCALE;
cm_node->loopbackpartner = loopbackremotenode;
memcpy(loopbackremotenode->mpa_frame_buf, private_data,
- private_data_len);
+ private_data_len);
loopbackremotenode->mpa_frame_size = private_data_len;
/* we are done handling this state. */
@@ -2091,12 +2331,10 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
return cm_node;
}
- /* set our node side to client (active) side */
- cm_node->tcp_cntxt.client = 1;
- /* init our MPA frame ptr */
- memcpy(mpa_frame->priv_data, private_data, private_data_len);
+ start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2);
+ cm_node->mpa_frame_size = private_data_len;
- cm_node->mpa_frame_size = mpa_frame_size;
+ memcpy(start_buff, private_data, private_data_len);
/* send a syn and goto syn sent state */
cm_node->state = NES_CM_STATE_SYN_SENT;
@@ -2105,18 +2343,19 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
if (ret) {
/* error in sending the syn free up the cm_node struct */
nes_debug(NES_DBG_CM, "Api - connect() FAILED: dest "
- "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
- cm_node->rem_addr, cm_node->rem_port, cm_node,
- cm_node->cm_id);
+ "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
+ cm_node->rem_addr, cm_node->rem_port, cm_node,
+ cm_node->cm_id);
rem_ref_cm_node(cm_node->cm_core, cm_node);
cm_node = NULL;
}
- if (cm_node)
+ if (cm_node) {
nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X,"
- "port=0x%04x, cm_node=%p, cm_id = %p.\n",
- cm_node->rem_addr, cm_node->rem_port, cm_node,
- cm_node->cm_id);
+ "port=0x%04x, cm_node=%p, cm_id = %p.\n",
+ cm_node->rem_addr, cm_node->rem_port, cm_node,
+ cm_node->cm_id);
+ }
return cm_node;
}
@@ -2126,8 +2365,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
* mini_cm_accept - accept a connection
* This function is never called
*/
-static int mini_cm_accept(struct nes_cm_core *cm_core,
- struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
+static int mini_cm_accept(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
{
return 0;
}
@@ -2136,8 +2374,7 @@ static int mini_cm_accept(struct nes_cm_core *cm_core,
/**
* mini_cm_reject - reject and teardown a connection
*/
-static int mini_cm_reject(struct nes_cm_core *cm_core,
- struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
+static int mini_cm_reject(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
{
int ret = 0;
int err = 0;
@@ -2147,7 +2384,7 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
struct nes_cm_node *loopback = cm_node->loopbackpartner;
nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n",
- __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
+ __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
if (cm_node->tcp_cntxt.client)
return ret;
@@ -2168,8 +2405,9 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
err = send_reset(cm_node, NULL);
if (err)
WARN_ON(1);
- } else
+ } else {
cm_id->add_ref(cm_id);
+ }
}
}
} else {
@@ -2244,7 +2482,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
case NES_CM_STATE_TSA:
if (cm_node->send_entry)
printk(KERN_ERR "ERROR Close got called from STATE_TSA "
- "send_entry=%p\n", cm_node->send_entry);
+ "send_entry=%p\n", cm_node->send_entry);
ret = rem_ref_cm_node(cm_core, cm_node);
break;
}
@@ -2257,7 +2495,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
* node state machine
*/
static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
- struct nes_vnic *nesvnic, struct sk_buff *skb)
+ struct nes_vnic *nesvnic, struct sk_buff *skb)
{
struct nes_cm_node *cm_node = NULL;
struct nes_cm_listener *listener = NULL;
@@ -2269,9 +2507,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
if (!skb)
return 0;
- if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
+ if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr))
return 0;
- }
iph = (struct iphdr *)skb->data;
tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
@@ -2289,8 +2526,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
do {
cm_node = find_node(cm_core,
- nfo.rem_port, nfo.rem_addr,
- nfo.loc_port, nfo.loc_addr);
+ nfo.rem_port, nfo.rem_addr,
+ nfo.loc_port, nfo.loc_addr);
if (!cm_node) {
/* Only type of packet accepted are for */
@@ -2300,8 +2537,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
break;
}
listener = find_listener(cm_core, nfo.loc_addr,
- nfo.loc_port,
- NES_CM_LISTENER_ACTIVE_STATE);
+ nfo.loc_port,
+ NES_CM_LISTENER_ACTIVE_STATE);
if (!listener) {
nfo.cm_id = NULL;
nfo.conn_type = 0;
@@ -2312,10 +2549,10 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
nfo.cm_id = listener->cm_id;
nfo.conn_type = listener->conn_type;
cm_node = make_cm_node(cm_core, nesvnic, &nfo,
- listener);
+ listener);
if (!cm_node) {
nes_debug(NES_DBG_CM, "Unable to allocate "
- "node\n");
+ "node\n");
cm_packets_dropped++;
atomic_dec(&listener->ref_count);
dev_kfree_skb_any(skb);
@@ -2331,9 +2568,13 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
}
add_ref_cm_node(cm_node);
} else if (cm_node->state == NES_CM_STATE_TSA) {
- rem_ref_cm_node(cm_core, cm_node);
- atomic_inc(&cm_accel_dropped_pkts);
- dev_kfree_skb_any(skb);
+ if (cm_node->nesqp->pau_mode)
+ nes_queue_mgt_skbs(skb, nesvnic, cm_node->nesqp);
+ else {
+ rem_ref_cm_node(cm_core, cm_node);
+ atomic_inc(&cm_accel_dropped_pkts);
+ dev_kfree_skb_any(skb);
+ }
break;
}
skb_reset_network_header(skb);
@@ -2363,7 +2604,7 @@ static struct nes_cm_core *nes_cm_alloc_core(void)
init_timer(&cm_core->tcp_timer);
cm_core->tcp_timer.function = nes_cm_timer_tick;
- cm_core->mtu = NES_CM_DEFAULT_MTU;
+ cm_core->mtu = NES_CM_DEFAULT_MTU;
cm_core->state = NES_CM_STATE_INITED;
cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS;
@@ -2401,9 +2642,8 @@ static int mini_cm_dealloc_core(struct nes_cm_core *cm_core)
barrier();
- if (timer_pending(&cm_core->tcp_timer)) {
+ if (timer_pending(&cm_core->tcp_timer))
del_timer(&cm_core->tcp_timer);
- }
destroy_workqueue(cm_core->event_wq);
destroy_workqueue(cm_core->disconn_wq);
@@ -2458,8 +2698,8 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
return -EINVAL;
nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_IPV4 |
- NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
- NES_QPCONTEXT_MISC_DROS);
+ NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
+ NES_QPCONTEXT_MISC_DROS);
if (cm_node->tcp_cntxt.snd_wscale || cm_node->tcp_cntxt.rcv_wscale)
nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WSCALE);
@@ -2469,15 +2709,15 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16);
nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32(
- (u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
+ (u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
- (cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
- NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
+ (cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
+ NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
- (cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
- NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
+ (cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
+ NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
nesqp->nesqp_context->keepalive = cpu_to_le32(0x80);
nesqp->nesqp_context->ts_recent = 0;
@@ -2486,24 +2726,24 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
nesqp->nesqp_context->snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.snd_wnd);
nesqp->nesqp_context->rcv_nxt = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
nesqp->nesqp_context->rcv_wnd = cpu_to_le32(cm_node->tcp_cntxt.rcv_wnd <<
- cm_node->tcp_cntxt.rcv_wscale);
+ cm_node->tcp_cntxt.rcv_wscale);
nesqp->nesqp_context->snd_max = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
nesqp->nesqp_context->snd_una = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
nesqp->nesqp_context->srtt = 0;
nesqp->nesqp_context->rttvar = cpu_to_le32(0x6);
nesqp->nesqp_context->ssthresh = cpu_to_le32(0x3FFFC000);
- nesqp->nesqp_context->cwnd = cpu_to_le32(2*cm_node->tcp_cntxt.mss);
+ nesqp->nesqp_context->cwnd = cpu_to_le32(2 * cm_node->tcp_cntxt.mss);
nesqp->nesqp_context->snd_wl1 = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
nesqp->nesqp_context->snd_wl2 = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
nesqp->nesqp_context->max_snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.max_snd_wnd);
nes_debug(NES_DBG_CM, "QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X,"
- " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
- nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
- le32_to_cpu(nesqp->nesqp_context->snd_nxt),
- cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
- le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
- le32_to_cpu(nesqp->nesqp_context->misc));
+ " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
+ nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
+ le32_to_cpu(nesqp->nesqp_context->snd_nxt),
+ cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
+ le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
+ le32_to_cpu(nesqp->nesqp_context->misc));
nes_debug(NES_DBG_CM, " snd_wnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->snd_wnd));
nes_debug(NES_DBG_CM, " snd_cwnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->cwnd));
nes_debug(NES_DBG_CM, " max_swnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->max_snd_wnd));
@@ -2524,7 +2764,7 @@ int nes_cm_disconn(struct nes_qp *nesqp)
work = kzalloc(sizeof *work, GFP_ATOMIC);
if (!work)
- return -ENOMEM; /* Timer will clean up */
+ return -ENOMEM; /* Timer will clean up */
nes_add_ref(&nesqp->ibqp);
work->nesqp = nesqp;
@@ -2544,7 +2784,7 @@ static void nes_disconnect_worker(struct work_struct *work)
kfree(dwork);
nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n",
- nesqp->last_aeq, nesqp->hwqp.qp_id);
+ nesqp->last_aeq, nesqp->hwqp.qp_id);
nes_cm_disconn_true(nesqp);
nes_rem_ref(&nesqp->ibqp);
}
@@ -2580,7 +2820,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
/* make sure we havent already closed this connection */
if (!cm_id) {
nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n",
- nesqp->hwqp.qp_id);
+ nesqp->hwqp.qp_id);
spin_unlock_irqrestore(&nesqp->lock, flags);
return -1;
}
@@ -2589,7 +2829,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
nes_debug(NES_DBG_CM, "Disconnecting QP%u\n", nesqp->hwqp.qp_id);
original_hw_tcp_state = nesqp->hw_tcp_state;
- original_ibqp_state = nesqp->ibqp_state;
+ original_ibqp_state = nesqp->ibqp_state;
last_ae = nesqp->last_aeq;
if (nesqp->term_flags) {
@@ -2647,16 +2887,16 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
cm_event.private_data_len = 0;
nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event"
- " for QP%u, SQ Head = %u, SQ Tail = %u. "
- "cm_id = %p, refcount = %u.\n",
- nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
- nesqp->hwqp.sq_tail, cm_id,
- atomic_read(&nesqp->refcount));
+ " for QP%u, SQ Head = %u, SQ Tail = %u. "
+ "cm_id = %p, refcount = %u.\n",
+ nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
+ nesqp->hwqp.sq_tail, cm_id,
+ atomic_read(&nesqp->refcount));
ret = cm_id->event_handler(cm_id, &cm_event);
if (ret)
nes_debug(NES_DBG_CM, "OFA CM event_handler "
- "returned, ret=%d\n", ret);
+ "returned, ret=%d\n", ret);
}
if (issue_close) {
@@ -2674,9 +2914,8 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
cm_event.private_data_len = 0;
ret = cm_id->event_handler(cm_id, &cm_event);
- if (ret) {
+ if (ret)
nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
- }
cm_id->rem_ref(cm_id);
}
@@ -2716,8 +2955,8 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt)
if (nesqp->lsmm_mr)
nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr);
pci_free_consistent(nesdev->pcidev,
- nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
- nesqp->ietf_frame, nesqp->ietf_frame_pbase);
+ nesqp->private_data_len + nesqp->ietf_frame_size,
+ nesqp->ietf_frame, nesqp->ietf_frame_pbase);
}
}
@@ -2756,6 +2995,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct ib_phys_buf ibphysbuf;
struct nes_pd *nespd;
u64 tagged_offset;
+ u8 mpa_frame_offset = 0;
+ struct ietf_mpa_v2 *mpa_v2_frame;
+ u8 start_addr = 0;
+ u8 *start_ptr = &start_addr;
+ u8 **start_buff = &start_ptr;
+ u16 buff_len = 0;
ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
if (!ibqp)
@@ -2796,53 +3041,49 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
netdev_refcnt_read(nesvnic->netdev));
+ nesqp->ietf_frame_size = sizeof(struct ietf_mpa_v2);
/* allocate the ietf frame and space for private data */
nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev,
- sizeof(struct ietf_mpa_frame) + conn_param->private_data_len,
- &nesqp->ietf_frame_pbase);
+ nesqp->ietf_frame_size + conn_param->private_data_len,
+ &nesqp->ietf_frame_pbase);
if (!nesqp->ietf_frame) {
- nes_debug(NES_DBG_CM, "Unable to allocate memory for private "
- "data\n");
+ nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n");
return -ENOMEM;
}
+ mpa_v2_frame = (struct ietf_mpa_v2 *)nesqp->ietf_frame;
+ if (cm_node->mpa_frame_rev == IETF_MPA_V1)
+ mpa_frame_offset = 4;
- /* setup the MPA frame */
- nesqp->private_data_len = conn_param->private_data_len;
- memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
-
- memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data,
- conn_param->private_data_len);
+ memcpy(mpa_v2_frame->priv_data, conn_param->private_data,
+ conn_param->private_data_len);
- nesqp->ietf_frame->priv_data_len =
- cpu_to_be16(conn_param->private_data_len);
- nesqp->ietf_frame->rev = mpa_version;
- nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC;
+ cm_build_mpa_frame(cm_node, start_buff, &buff_len, nesqp->ietf_frame, MPA_KEY_REPLY);
+ nesqp->private_data_len = conn_param->private_data_len;
/* setup our first outgoing iWarp send WQE (the IETF frame response) */
wqe = &nesqp->hwqp.sq_vbase[0];
if (cm_id->remote_addr.sin_addr.s_addr !=
- cm_id->local_addr.sin_addr.s_addr) {
+ cm_id->local_addr.sin_addr.s_addr) {
u64temp = (unsigned long)nesqp;
nesibdev = nesvnic->nesibdev;
nespd = nesqp->nespd;
- ibphysbuf.addr = nesqp->ietf_frame_pbase;
- ibphysbuf.size = conn_param->private_data_len +
- sizeof(struct ietf_mpa_frame);
- tagged_offset = (u64)(unsigned long)nesqp->ietf_frame;
+ ibphysbuf.addr = nesqp->ietf_frame_pbase + mpa_frame_offset;
+ ibphysbuf.size = buff_len;
+ tagged_offset = (u64)(unsigned long)*start_buff;
ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd,
- &ibphysbuf, 1,
- IB_ACCESS_LOCAL_WRITE,
- &tagged_offset);
+ &ibphysbuf, 1,
+ IB_ACCESS_LOCAL_WRITE,
+ &tagged_offset);
if (!ibmr) {
nes_debug(NES_DBG_CM, "Unable to register memory region"
- "for lSMM for cm_node = %p \n",
- cm_node);
+ "for lSMM for cm_node = %p \n",
+ cm_node);
pci_free_consistent(nesdev->pcidev,
- nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
- nesqp->ietf_frame, nesqp->ietf_frame_pbase);
+ nesqp->private_data_len + nesqp->ietf_frame_size,
+ nesqp->ietf_frame, nesqp->ietf_frame_pbase);
return -ENOMEM;
}
@@ -2850,22 +3091,20 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ibmr->device = nespd->ibpd.device;
nesqp->lsmm_mr = ibmr;
- u64temp |= NES_SW_CONTEXT_ALIGN>>1;
+ u64temp |= NES_SW_CONTEXT_ALIGN >> 1;
set_wqe_64bit_value(wqe->wqe_words,
- NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
- u64temp);
+ NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
+ u64temp);
wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING |
- NES_IWARP_SQ_WQE_WRPDU);
+ NES_IWARP_SQ_WQE_WRPDU);
wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] =
- cpu_to_le32(conn_param->private_data_len +
- sizeof(struct ietf_mpa_frame));
+ cpu_to_le32(buff_len);
set_wqe_64bit_value(wqe->wqe_words,
- NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
- (u64)(unsigned long)nesqp->ietf_frame);
+ NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
+ (u64)(unsigned long)(*start_buff));
wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] =
- cpu_to_le32(conn_param->private_data_len +
- sizeof(struct ietf_mpa_frame));
+ cpu_to_le32(buff_len);
wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey;
if (nesqp->sq_kmapped) {
nesqp->sq_kmapped = 0;
@@ -2874,7 +3113,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nesqp->nesqp_context->ird_ord_sizes |=
cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
- NES_QPCONTEXT_ORDIRD_WRPDU);
+ NES_QPCONTEXT_ORDIRD_WRPDU);
} else {
nesqp->nesqp_context->ird_ord_sizes |=
cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU);
@@ -2888,11 +3127,11 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
/* nesqp->cm_node = (void *)cm_id->provider_data; */
cm_id->provider_data = nesqp;
- nesqp->active_conn = 0;
+ nesqp->active_conn = 0;
if (cm_node->state == NES_CM_STATE_TSA)
nes_debug(NES_DBG_CM, "Already state = TSA for cm_node=%p\n",
- cm_node);
+ cm_node);
nes_cm_init_tsa_conn(nesqp, cm_node);
@@ -2909,13 +3148,13 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
nesqp->nesqp_context->misc2 |= cpu_to_le32(
- (u32)PCI_FUNC(nesdev->pcidev->devfn) <<
- NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
+ (u32)PCI_FUNC(nesdev->pcidev->devfn) <<
+ NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
nesqp->nesqp_context->arp_index_vlan |=
cpu_to_le32(nes_arp_table(nesdev,
- le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
- NES_ARP_RESOLVE) << 16);
+ le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
+ NES_ARP_RESOLVE) << 16);
nesqp->nesqp_context->ts_val_delta = cpu_to_le32(
jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW));
@@ -2941,7 +3180,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
crc_value = get_crc_value(&nes_quad);
nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n",
- nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
+ nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
nesqp->hte_index &= adapter->hte_index_mask;
nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
@@ -2949,17 +3188,15 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = "
- "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
- "private data length=%zu.\n", nesqp->hwqp.qp_id,
- ntohl(cm_id->remote_addr.sin_addr.s_addr),
- ntohs(cm_id->remote_addr.sin_port),
- ntohl(cm_id->local_addr.sin_addr.s_addr),
- ntohs(cm_id->local_addr.sin_port),
- le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
- le32_to_cpu(nesqp->nesqp_context->snd_nxt),
- conn_param->private_data_len +
- sizeof(struct ietf_mpa_frame));
-
+ "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
+ "private data length=%u.\n", nesqp->hwqp.qp_id,
+ ntohl(cm_id->remote_addr.sin_addr.s_addr),
+ ntohs(cm_id->remote_addr.sin_port),
+ ntohl(cm_id->local_addr.sin_addr.s_addr),
+ ntohs(cm_id->local_addr.sin_port),
+ le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
+ le32_to_cpu(nesqp->nesqp_context->snd_nxt),
+ buff_len);
/* notify OF layer that accept event was successful */
cm_id->add_ref(cm_id);
@@ -2980,12 +3217,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nesqp->private_data_len;
/* copy entire MPA frame to our cm_node's frame */
memcpy(cm_node->loopbackpartner->mpa_frame_buf,
- nesqp->ietf_frame->priv_data, nesqp->private_data_len);
+ conn_param->private_data, conn_param->private_data_len);
create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED);
}
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
- "ret=%d\n", __func__, __LINE__, ret);
+ "ret=%d\n", __func__, __LINE__, ret);
return 0;
}
@@ -2998,34 +3235,28 @@ int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
{
struct nes_cm_node *cm_node;
struct nes_cm_node *loopback;
-
struct nes_cm_core *cm_core;
+ u8 *start_buff;
atomic_inc(&cm_rejects);
- cm_node = (struct nes_cm_node *) cm_id->provider_data;
+ cm_node = (struct nes_cm_node *)cm_id->provider_data;
loopback = cm_node->loopbackpartner;
cm_core = cm_node->cm_core;
cm_node->cm_id = cm_id;
- cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len;
- if (cm_node->mpa_frame_size > MAX_CM_BUFFER)
+ if (pdata_len + sizeof(struct ietf_mpa_v2) > MAX_CM_BUFFER)
return -EINVAL;
- memcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
if (loopback) {
memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len);
loopback->mpa_frame.priv_data_len = pdata_len;
- loopback->mpa_frame_size = sizeof(struct ietf_mpa_frame) +
- pdata_len;
+ loopback->mpa_frame_size = pdata_len;
} else {
- memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len);
- cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len);
+ start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2);
+ cm_node->mpa_frame_size = pdata_len;
+ memcpy(start_buff, pdata, pdata_len);
}
-
- cm_node->mpa_frame.rev = mpa_version;
- cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT;
-
- return cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node);
+ return cm_core->api->reject(cm_core, cm_node);
}
@@ -3052,7 +3283,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nesvnic = to_nesvnic(nesqp->ibqp.device);
if (!nesvnic)
return -EINVAL;
- nesdev = nesvnic->nesdev;
+ nesdev = nesvnic->nesdev;
if (!nesdev)
return -EINVAL;
@@ -3060,12 +3291,12 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
return -EINVAL;
nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = "
- "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
- ntohl(nesvnic->local_ipaddr),
- ntohl(cm_id->remote_addr.sin_addr.s_addr),
- ntohs(cm_id->remote_addr.sin_port),
- ntohl(cm_id->local_addr.sin_addr.s_addr),
- ntohs(cm_id->local_addr.sin_port));
+ "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
+ ntohl(nesvnic->local_ipaddr),
+ ntohl(cm_id->remote_addr.sin_addr.s_addr),
+ ntohs(cm_id->remote_addr.sin_port),
+ ntohl(cm_id->local_addr.sin_addr.s_addr),
+ ntohs(cm_id->local_addr.sin_port));
atomic_inc(&cm_connects);
nesqp->active_conn = 1;
@@ -3079,12 +3310,12 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord);
nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord);
nes_debug(NES_DBG_CM, "mpa private data len =%u\n",
- conn_param->private_data_len);
+ conn_param->private_data_len);
if (cm_id->local_addr.sin_addr.s_addr !=
- cm_id->remote_addr.sin_addr.s_addr) {
+ cm_id->remote_addr.sin_addr.s_addr) {
nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
- PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
+ PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
apbvt_set = 1;
}
@@ -3100,13 +3331,13 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
/* create a connect CM node connection */
cm_node = g_cm_core->api->connect(g_cm_core, nesvnic,
- conn_param->private_data_len, (void *)conn_param->private_data,
- &cm_info);
+ conn_param->private_data_len, (void *)conn_param->private_data,
+ &cm_info);
if (!cm_node) {
if (apbvt_set)
nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
- PCI_FUNC(nesdev->pcidev->devfn),
- NES_MANAGE_APBVT_DEL);
+ PCI_FUNC(nesdev->pcidev->devfn),
+ NES_MANAGE_APBVT_DEL);
cm_id->rem_ref(cm_id);
return -ENOMEM;
@@ -3156,7 +3387,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info);
if (!cm_node) {
printk(KERN_ERR "%s[%u] Error returned from listen API call\n",
- __func__, __LINE__);
+ __func__, __LINE__);
return -ENOMEM;
}
@@ -3164,12 +3395,12 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
if (!cm_node->reused_node) {
err = nes_manage_apbvt(nesvnic,
- ntohs(cm_id->local_addr.sin_port),
- PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
- NES_MANAGE_APBVT_ADD);
+ ntohs(cm_id->local_addr.sin_port),
+ PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
+ NES_MANAGE_APBVT_ADD);
if (err) {
printk(KERN_ERR "nes_manage_apbvt call returned %d.\n",
- err);
+ err);
g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node);
return err;
}
@@ -3206,13 +3437,13 @@ int nes_destroy_listen(struct iw_cm_id *cm_id)
int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice)
{
int rc = 0;
+
cm_packets_received++;
- if ((g_cm_core) && (g_cm_core->api)) {
+ if ((g_cm_core) && (g_cm_core->api))
rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
- } else {
+ else
nes_debug(NES_DBG_CM, "Unable to process packet for CM,"
- " cm is not setup properly.\n");
- }
+ " cm is not setup properly.\n");
return rc;
}
@@ -3227,11 +3458,10 @@ int nes_cm_start(void)
nes_debug(NES_DBG_CM, "\n");
/* create the primary CM core, pass this handle to subsequent core inits */
g_cm_core = nes_cm_alloc_core();
- if (g_cm_core) {
+ if (g_cm_core)
return 0;
- } else {
+ else
return -ENOMEM;
- }
}
@@ -3252,7 +3482,6 @@ int nes_cm_stop(void)
*/
static void cm_event_connected(struct nes_cm_event *event)
{
- u64 u64temp;
struct nes_qp *nesqp;
struct nes_vnic *nesvnic;
struct nes_device *nesdev;
@@ -3261,7 +3490,6 @@ static void cm_event_connected(struct nes_cm_event *event)
struct ib_qp_attr attr;
struct iw_cm_id *cm_id;
struct iw_cm_event cm_event;
- struct nes_hw_qp_wqe *wqe;
struct nes_v4_quad nes_quad;
u32 crc_value;
int ret;
@@ -3275,17 +3503,16 @@ static void cm_event_connected(struct nes_cm_event *event)
nesdev = nesvnic->nesdev;
nesadapter = nesdev->nesadapter;
- if (nesqp->destroyed) {
+ if (nesqp->destroyed)
return;
- }
atomic_inc(&cm_connecteds);
nes_debug(NES_DBG_CM, "QP%u attempting to connect to 0x%08X:0x%04X on"
- " local port 0x%04X. jiffies = %lu.\n",
- nesqp->hwqp.qp_id,
- ntohl(cm_id->remote_addr.sin_addr.s_addr),
- ntohs(cm_id->remote_addr.sin_port),
- ntohs(cm_id->local_addr.sin_port),
- jiffies);
+ " local port 0x%04X. jiffies = %lu.\n",
+ nesqp->hwqp.qp_id,
+ ntohl(cm_id->remote_addr.sin_addr.s_addr),
+ ntohs(cm_id->remote_addr.sin_port),
+ ntohs(cm_id->local_addr.sin_port),
+ jiffies);
nes_cm_init_tsa_conn(nesqp, cm_node);
@@ -3316,40 +3543,12 @@ static void cm_event_connected(struct nes_cm_event *event)
NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT);
/* Adjust tail for not having a LSMM */
- nesqp->hwqp.sq_tail = 1;
+ /*nesqp->hwqp.sq_tail = 1;*/
-#if defined(NES_SEND_FIRST_WRITE)
- if (cm_node->send_write0) {
- nes_debug(NES_DBG_CM, "Sending first write.\n");
- wqe = &nesqp->hwqp.sq_vbase[0];
- u64temp = (unsigned long)nesqp;
- u64temp |= NES_SW_CONTEXT_ALIGN>>1;
- set_wqe_64bit_value(wqe->wqe_words,
- NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
- wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
- cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
- wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
- wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
- wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
- wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
- wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+ build_rdma0_msg(cm_node, &nesqp);
- if (nesqp->sq_kmapped) {
- nesqp->sq_kmapped = 0;
- kunmap(nesqp->page);
- }
-
- /* use the reserved spot on the WQ for the extra first WQE */
- nesqp->nesqp_context->ird_ord_sizes &=
- cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
- NES_QPCONTEXT_ORDIRD_WRPDU |
- NES_QPCONTEXT_ORDIRD_ALSMM));
- nesqp->skip_lsmm = 1;
- nesqp->hwqp.sq_tail = 0;
- nes_write32(nesdev->regs + NES_WQE_ALLOC,
- (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
- }
-#endif
+ nes_write32(nesdev->regs + NES_WQE_ALLOC,
+ (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
memset(&nes_quad, 0, sizeof(nes_quad));
@@ -3366,13 +3565,13 @@ static void cm_event_connected(struct nes_cm_event *event)
crc_value = get_crc_value(&nes_quad);
nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, After CRC = 0x%08X\n",
- nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
+ nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
nesqp->hte_index &= nesadapter->hte_index_mask;
nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
nesqp->ietf_frame = &cm_node->mpa_frame;
- nesqp->private_data_len = (u8) cm_node->mpa_frame_size;
+ nesqp->private_data_len = (u8)cm_node->mpa_frame_size;
cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
/* notify OF layer we successfully created the requested connection */
@@ -3384,7 +3583,9 @@ static void cm_event_connected(struct nes_cm_event *event)
cm_event.remote_addr = cm_id->remote_addr;
cm_event.private_data = (void *)event->cm_node->mpa_frame_buf;
- cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size;
+ cm_event.private_data_len = (u8)event->cm_node->mpa_frame_size;
+ cm_event.ird = cm_node->ird_size;
+ cm_event.ord = cm_node->ord_size;
cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr;
ret = cm_id->event_handler(cm_id, &cm_event);
@@ -3392,12 +3593,12 @@ static void cm_event_connected(struct nes_cm_event *event)
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
- "ret=%d\n", __func__, __LINE__, ret);
+ "ret=%d\n", __func__, __LINE__, ret);
attr.qp_state = IB_QPS_RTS;
nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = "
- "%lu\n", nesqp->hwqp.qp_id, jiffies);
+ "%lu\n", nesqp->hwqp.qp_id, jiffies);
return;
}
@@ -3418,16 +3619,14 @@ static void cm_event_connect_error(struct nes_cm_event *event)
return;
cm_id = event->cm_node->cm_id;
- if (!cm_id) {
+ if (!cm_id)
return;
- }
nes_debug(NES_DBG_CM, "cm_node=%p, cm_id=%p\n", event->cm_node, cm_id);
nesqp = cm_id->provider_data;
- if (!nesqp) {
+ if (!nesqp)
return;
- }
/* notify OF layer about this connection error event */
/* cm_id->rem_ref(cm_id); */
@@ -3442,14 +3641,14 @@ static void cm_event_connect_error(struct nes_cm_event *event)
cm_event.private_data_len = 0;
nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, "
- "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
- cm_event.remote_addr.sin_addr.s_addr);
+ "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
+ cm_event.remote_addr.sin_addr.s_addr);
ret = cm_id->event_handler(cm_id, &cm_event);
nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
- "ret=%d\n", __func__, __LINE__, ret);
+ "ret=%d\n", __func__, __LINE__, ret);
cm_id->rem_ref(cm_id);
rem_ref_cm_node(event->cm_node->cm_core, event->cm_node);
@@ -3519,7 +3718,7 @@ static void cm_event_reset(struct nes_cm_event *event)
*/
static void cm_event_mpa_req(struct nes_cm_event *event)
{
- struct iw_cm_id *cm_id;
+ struct iw_cm_id *cm_id;
struct iw_cm_event cm_event;
int ret;
struct nes_cm_node *cm_node;
@@ -3531,7 +3730,7 @@ static void cm_event_mpa_req(struct nes_cm_event *event)
atomic_inc(&cm_connect_reqs);
nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
- cm_node, cm_id, jiffies);
+ cm_node, cm_id, jiffies);
cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
cm_event.status = 0;
@@ -3545,19 +3744,21 @@ static void cm_event_mpa_req(struct nes_cm_event *event)
cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port);
cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
cm_event.private_data = cm_node->mpa_frame_buf;
- cm_event.private_data_len = (u8) cm_node->mpa_frame_size;
+ cm_event.private_data_len = (u8)cm_node->mpa_frame_size;
+ cm_event.ird = cm_node->ird_size;
+ cm_event.ord = cm_node->ord_size;
ret = cm_id->event_handler(cm_id, &cm_event);
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
- __func__, __LINE__, ret);
+ __func__, __LINE__, ret);
return;
}
static void cm_event_mpa_reject(struct nes_cm_event *event)
{
- struct iw_cm_id *cm_id;
+ struct iw_cm_id *cm_id;
struct iw_cm_event cm_event;
struct nes_cm_node *cm_node;
int ret;
@@ -3569,7 +3770,7 @@ static void cm_event_mpa_reject(struct nes_cm_event *event)
atomic_inc(&cm_connect_reqs);
nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
- cm_node, cm_id, jiffies);
+ cm_node, cm_id, jiffies);
cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
cm_event.status = -ECONNREFUSED;
@@ -3584,17 +3785,17 @@ static void cm_event_mpa_reject(struct nes_cm_event *event)
cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
cm_event.private_data = cm_node->mpa_frame_buf;
- cm_event.private_data_len = (u8) cm_node->mpa_frame_size;
+ cm_event.private_data_len = (u8)cm_node->mpa_frame_size;
nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, "
- "remove_addr=%08x\n",
- cm_event.local_addr.sin_addr.s_addr,
- cm_event.remote_addr.sin_addr.s_addr);
+ "remove_addr=%08x\n",
+ cm_event.local_addr.sin_addr.s_addr,
+ cm_event.remote_addr.sin_addr.s_addr);
ret = cm_id->event_handler(cm_id, &cm_event);
if (ret)
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
- __func__, __LINE__, ret);
+ __func__, __LINE__, ret);
return;
}
@@ -3613,7 +3814,7 @@ static int nes_cm_post_event(struct nes_cm_event *event)
event->cm_info.cm_id->add_ref(event->cm_info.cm_id);
INIT_WORK(&event->event_work, nes_cm_event_handler);
nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n",
- event->cm_node, event);
+ event->cm_node, event);
queue_work(event->cm_node->cm_core->event_wq, &event->event_work);
@@ -3630,7 +3831,7 @@ static int nes_cm_post_event(struct nes_cm_event *event)
static void nes_cm_event_handler(struct work_struct *work)
{
struct nes_cm_event *event = container_of(work, struct nes_cm_event,
- event_work);
+ event_work);
struct nes_cm_core *cm_core;
if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core))
@@ -3638,29 +3839,29 @@ static void nes_cm_event_handler(struct work_struct *work)
cm_core = event->cm_node->cm_core;
nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n",
- event, event->type, atomic_read(&cm_core->events_posted));
+ event, event->type, atomic_read(&cm_core->events_posted));
switch (event->type) {
case NES_CM_EVENT_MPA_REQ:
cm_event_mpa_req(event);
nes_debug(NES_DBG_CM, "cm_node=%p CM Event: MPA REQUEST\n",
- event->cm_node);
+ event->cm_node);
break;
case NES_CM_EVENT_RESET:
nes_debug(NES_DBG_CM, "cm_node = %p CM Event: RESET\n",
- event->cm_node);
+ event->cm_node);
cm_event_reset(event);
break;
case NES_CM_EVENT_CONNECTED:
if ((!event->cm_node->cm_id) ||
- (event->cm_node->state != NES_CM_STATE_TSA))
+ (event->cm_node->state != NES_CM_STATE_TSA))
break;
cm_event_connected(event);
nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");
break;
case NES_CM_EVENT_MPA_REJECT:
if ((!event->cm_node->cm_id) ||
- (event->cm_node->state == NES_CM_STATE_TSA))
+ (event->cm_node->state == NES_CM_STATE_TSA))
break;
cm_event_mpa_reject(event);
nes_debug(NES_DBG_CM, "CM Event: REJECT\n");
@@ -3668,7 +3869,7 @@ static void nes_cm_event_handler(struct work_struct *work)
case NES_CM_EVENT_ABORTED:
if ((!event->cm_node->cm_id) ||
- (event->cm_node->state == NES_CM_STATE_TSA))
+ (event->cm_node->state == NES_CM_STATE_TSA))
break;
cm_event_connect_error(event);
nes_debug(NES_DBG_CM, "CM Event: ABORTED\n");
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
index d9825fda70a1..bdfa1fbb35fc 100644
--- a/drivers/infiniband/hw/nes/nes_cm.h
+++ b/drivers/infiniband/hw/nes/nes_cm.h
@@ -48,7 +48,16 @@
#define IETF_MPA_KEY_SIZE 16
#define IETF_MPA_VERSION 1
#define IETF_MAX_PRIV_DATA_LEN 512
-#define IETF_MPA_FRAME_SIZE 20
+#define IETF_MPA_FRAME_SIZE 20
+#define IETF_RTR_MSG_SIZE 4
+#define IETF_MPA_V2_FLAG 0x10
+
+/* IETF RTR MSG Fields */
+#define IETF_PEER_TO_PEER 0x8000
+#define IETF_FLPDU_ZERO_LEN 0x4000
+#define IETF_RDMA0_WRITE 0x8000
+#define IETF_RDMA0_READ 0x4000
+#define IETF_NO_IRD_ORD 0x3FFF
enum ietf_mpa_flags {
IETF_MPA_FLAGS_MARKERS = 0x80, /* receive Markers */
@@ -56,7 +65,7 @@ enum ietf_mpa_flags {
IETF_MPA_FLAGS_REJECT = 0x20, /* Reject */
};
-struct ietf_mpa_frame {
+struct ietf_mpa_v1 {
u8 key[IETF_MPA_KEY_SIZE];
u8 flags;
u8 rev;
@@ -66,6 +75,20 @@ struct ietf_mpa_frame {
#define ietf_mpa_req_resp_frame ietf_mpa_frame
+struct ietf_rtr_msg {
+ __be16 ctrl_ird;
+ __be16 ctrl_ord;
+};
+
+struct ietf_mpa_v2 {
+ u8 key[IETF_MPA_KEY_SIZE];
+ u8 flags;
+ u8 rev;
+ __be16 priv_data_len;
+ struct ietf_rtr_msg rtr_msg;
+ u8 priv_data[0];
+};
+
struct nes_v4_quad {
u32 rsvd0;
__le32 DstIpAdrIndex; /* Only most significant 5 bits are valid */
@@ -171,8 +194,7 @@ struct nes_timer_entry {
#define NES_CM_DEF_SEQ2 0x18ed5740
#define NES_CM_DEF_LOCAL_ID2 0xb807
-#define MAX_CM_BUFFER (IETF_MPA_FRAME_SIZE + IETF_MAX_PRIV_DATA_LEN)
-
+#define MAX_CM_BUFFER (IETF_MPA_FRAME_SIZE + IETF_RTR_MSG_SIZE + IETF_MAX_PRIV_DATA_LEN)
typedef u32 nes_addr_t;
@@ -204,6 +226,21 @@ enum nes_cm_node_state {
NES_CM_STATE_CLOSED
};
+enum mpa_frame_version {
+ IETF_MPA_V1 = 1,
+ IETF_MPA_V2 = 2
+};
+
+enum mpa_frame_key {
+ MPA_KEY_REQUEST,
+ MPA_KEY_REPLY
+};
+
+enum send_rdma0 {
+ SEND_RDMA_READ_ZERO = 1,
+ SEND_RDMA_WRITE_ZERO = 2
+};
+
enum nes_tcpip_pkt_type {
NES_PKT_TYPE_UNKNOWN,
NES_PKT_TYPE_SYN,
@@ -245,9 +282,9 @@ struct nes_cm_tcp_context {
enum nes_cm_listener_state {
- NES_CM_LISTENER_PASSIVE_STATE=1,
- NES_CM_LISTENER_ACTIVE_STATE=2,
- NES_CM_LISTENER_EITHER_STATE=3
+ NES_CM_LISTENER_PASSIVE_STATE = 1,
+ NES_CM_LISTENER_ACTIVE_STATE = 2,
+ NES_CM_LISTENER_EITHER_STATE = 3
};
struct nes_cm_listener {
@@ -283,16 +320,20 @@ struct nes_cm_node {
struct nes_cm_node *loopbackpartner;
- struct nes_timer_entry *send_entry;
-
+ struct nes_timer_entry *send_entry;
+ struct nes_timer_entry *recv_entry;
spinlock_t retrans_list_lock;
- struct nes_timer_entry *recv_entry;
+ enum send_rdma0 send_rdma0_op;
- int send_write0;
union {
- struct ietf_mpa_frame mpa_frame;
- u8 mpa_frame_buf[MAX_CM_BUFFER];
+ struct ietf_mpa_v1 mpa_frame;
+ struct ietf_mpa_v2 mpa_v2_frame;
+ u8 mpa_frame_buf[MAX_CM_BUFFER];
};
+ enum mpa_frame_version mpa_frame_rev;
+ u16 ird_size;
+ u16 ord_size;
+
u16 mpa_frame_size;
struct iw_cm_id *cm_id;
struct list_head list;
@@ -399,10 +440,8 @@ struct nes_cm_ops {
struct nes_vnic *, u16, void *,
struct nes_cm_info *);
int (*close)(struct nes_cm_core *, struct nes_cm_node *);
- int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *,
- struct nes_cm_node *);
- int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *,
- struct nes_cm_node *);
+ int (*accept)(struct nes_cm_core *, struct nes_cm_node *);
+ int (*reject)(struct nes_cm_core *, struct nes_cm_node *);
int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
struct sk_buff *);
int (*destroy_cm_core)(struct nes_cm_core *);
@@ -422,5 +461,7 @@ int nes_destroy_listen(struct iw_cm_id *);
int nes_cm_recv(struct sk_buff *, struct net_device *);
int nes_cm_start(void);
int nes_cm_stop(void);
+int nes_add_ref_cm_node(struct nes_cm_node *cm_node);
+int nes_rem_ref_cm_node(struct nes_cm_node *cm_node);
#endif /* NES_CM_H */
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index be36cbeae630..7c0ff19ce382 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -110,6 +110,14 @@ static unsigned char *nes_tcp_state_str[] = {
};
#endif
+static inline void print_ip(struct nes_cm_node *cm_node)
+{
+ unsigned char *rem_addr;
+ if (cm_node) {
+ rem_addr = (unsigned char *)&cm_node->rem_addr;
+ printk(KERN_ERR PFX "Remote IP addr: %pI4\n", rem_addr);
+ }
+}
/**
* nes_nic_init_timer_defaults
@@ -1555,6 +1563,7 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
struct nes_hw_nic_rq_wqe *nic_rqe;
struct nes_hw_nic *nesnic;
struct nes_device *nesdev;
+ struct nes_rskb_cb *cb;
u32 rx_wqes_posted = 0;
nesnic = &nesvnic->nic;
@@ -1580,6 +1589,9 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
bus_address = pci_map_single(nesdev->pcidev,
skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ cb->busaddr = bus_address;
+ cb->maplen = nesvnic->max_frame_size;
nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
@@ -1669,6 +1681,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
u32 cqp_head;
u32 counter;
u32 wqe_count;
+ struct nes_rskb_cb *cb;
u8 jumbomode=0;
/* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
@@ -1845,6 +1858,9 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
pmem = pci_map_single(nesdev->pcidev, skb->data,
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ cb->busaddr = pmem;
+ cb->maplen = nesvnic->max_frame_size;
nic_rqe = &nesvnic->nic.rq_vbase[counter];
nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
@@ -1873,6 +1889,13 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
jumbomode = 1;
nes_nic_init_timer_defaults(nesdev, jumbomode);
}
+ if ((nesdev->nesadapter->allow_unaligned_fpdus) &&
+ (nes_init_mgt_qp(nesdev, netdev, nesvnic))) {
+ nes_debug(NES_DBG_INIT, "%s: Out of memory for pau nic\n", netdev->name);
+ nes_destroy_nic_qp(nesvnic);
+ return -ENOMEM;
+ }
+
nesvnic->lro_mgr.max_aggr = nes_lro_max_aggr;
nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
@@ -1895,28 +1918,29 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
struct nes_device *nesdev = nesvnic->nesdev;
struct nes_hw_cqp_wqe *cqp_wqe;
struct nes_hw_nic_sq_wqe *nic_sqe;
- struct nes_hw_nic_rq_wqe *nic_rqe;
__le16 *wqe_fragment_length;
u16 wqe_fragment_index;
- u64 wqe_frag;
u32 cqp_head;
u32 wqm_cfg0;
unsigned long flags;
+ struct sk_buff *rx_skb;
+ struct nes_rskb_cb *cb;
int ret;
+ if (nesdev->nesadapter->allow_unaligned_fpdus)
+ nes_destroy_mgt(nesvnic);
+
/* clear wqe stall before destroying NIC QP */
wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0);
nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF);
/* Free remaining NIC receive buffers */
while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
- nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
- wqe_frag = (u64)le32_to_cpu(
- nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
- wqe_frag |= ((u64)le32_to_cpu(
- nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
- pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
- nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+ rx_skb = nesvnic->nic.rx_skb[nesvnic->nic.rq_tail];
+ cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+ pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen,
+ PCI_DMA_FROMDEVICE);
+
dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
}
@@ -2775,6 +2799,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
struct nes_hw_nic_sq_wqe *nic_sqe;
struct sk_buff *skb;
struct sk_buff *rx_skb;
+ struct nes_rskb_cb *cb;
__le16 *wqe_fragment_length;
u32 head;
u32 cq_size;
@@ -2859,6 +2884,8 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
pci_unmap_single(nesdev->pcidev, bus_address,
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+ cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+ cb->busaddr = 0;
/* rx_skb->tail = rx_skb->data + rx_pkt_size; */
/* rx_skb->len = rx_pkt_size; */
rx_skb->len = 0; /* TODO: see if this is necessary */
@@ -2983,6 +3010,7 @@ skip_rx_indicate0:
}
+
/**
* nes_cqp_ce_handler
*/
@@ -2997,6 +3025,8 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
u32 cq_size;
u32 cqe_count=0;
u32 error_code;
+ u32 opcode;
+ u32 ctx_index;
/* u32 counter; */
head = cq->cq_head;
@@ -3007,12 +3037,9 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
/* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
- if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
- u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
- cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
- ((u64)(le32_to_cpu(cq->cq_vbase[head].
- cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
- cqp = *((struct nes_hw_cqp **)&u64temp);
+ opcode = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]);
+ if (opcode & NES_CQE_VALID) {
+ cqp = &nesdev->cqp;
error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
if (error_code) {
@@ -3021,15 +3048,14 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
(u16)(error_code >> 16),
(u16)error_code);
- nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
- cqp->qp_id, cqp->sq_head, cqp->sq_tail);
}
- u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
- wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
- ((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
- wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
- cqp_request = *((struct nes_cqp_request **)&u64temp);
+ u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
+ cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
+ ((u64)(le32_to_cpu(cq->cq_vbase[head].
+ cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
+
+ cqp_request = (struct nes_cqp_request *)(unsigned long)u64temp;
if (cqp_request) {
if (cqp_request->waiting) {
/* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
@@ -3075,9 +3101,15 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
cqp_wqe = &nesdev->cqp.sq_vbase[head];
memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
barrier();
- cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
+
+ opcode = cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX];
+ if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
+ ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
+ else
+ ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
+ cqp_wqe->wqe_words[ctx_index] =
cpu_to_le32((u32)((unsigned long)cqp_request));
- cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =
+ cqp_wqe->wqe_words[ctx_index + 1] =
cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
@@ -3093,7 +3125,6 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
nes_read32(nesdev->regs+NES_CQE_ALLOC);
}
-
static u8 *locate_mpa(u8 *pkt, u32 aeq_info)
{
if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) {
@@ -3553,9 +3584,9 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
if (aeq_info & NES_AEQE_QP) {
- if ((!nes_is_resource_allocated(nesadapter, nesadapter->allocated_qps,
- aeqe_cq_id)) ||
- (atomic_read(&nesqp->close_timer_started)))
+ if (!nes_is_resource_allocated(nesadapter,
+ nesadapter->allocated_qps,
+ aeqe_cq_id))
return;
}
@@ -3566,8 +3597,7 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) &&
- (nesqp->ibqp_state == IB_QPS_RTS) &&
- ((nesadapter->eeprom_version >> 16) != NES_A0)) {
+ (nesqp->ibqp_state == IB_QPS_RTS)) {
spin_lock_irqsave(&nesqp->lock, flags);
nesqp->hw_iwarp_state = iwarp_state;
nesqp->hw_tcp_state = tcp_state;
@@ -3594,9 +3624,10 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
return;
}
spin_lock_irqsave(&nesqp->lock, flags);
- nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
+ nesqp->hw_iwarp_state = iwarp_state;
+ nesqp->hw_tcp_state = tcp_state;
+ nesqp->last_aeq = async_event_id;
spin_unlock_irqrestore(&nesqp->lock, flags);
- nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_CLOSING, 0, 0);
nes_cm_disconn(nesqp);
break;
@@ -3694,7 +3725,9 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_FATAL\n",
nesqp->hwqp.qp_id, async_event_id);
- nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
+ print_ip(nesqp->cm_node);
+ if (!atomic_read(&nesqp->close_timer_started))
+ nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
break;
case NES_AEQE_AEID_CQ_OPERATION_ERROR:
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index c3241479ec0e..0b590e152c6a 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -47,6 +47,11 @@
#define NES_MULTICAST_PF_MAX 8
#define NES_A0 3
+#define NES_ENABLE_PAU 0x07000001
+#define NES_DISABLE_PAU 0x07000000
+#define NES_PAU_COUNTER 10
+#define NES_CQP_OPCODE_MASK 0x3f
+
enum pci_regs {
NES_INT_STAT = 0x0000,
NES_INT_MASK = 0x0004,
@@ -73,8 +78,10 @@ enum indexed_regs {
NES_IDX_QP_CONTROL = 0x0040,
NES_IDX_FLM_CONTROL = 0x0080,
NES_IDX_INT_CPU_STATUS = 0x00a0,
+ NES_IDX_GPR_TRIGGER = 0x00bc,
NES_IDX_GPIO_CONTROL = 0x00f0,
NES_IDX_GPIO_DATA = 0x00f4,
+ NES_IDX_GPR2 = 0x010c,
NES_IDX_TCP_CONFIG0 = 0x01e4,
NES_IDX_TCP_TIMER_CONFIG = 0x01ec,
NES_IDX_TCP_NOW = 0x01f0,
@@ -202,6 +209,7 @@ enum nes_cqp_opcodes {
NES_CQP_REGISTER_SHARED_STAG = 0x0c,
NES_CQP_DEALLOCATE_STAG = 0x0d,
NES_CQP_MANAGE_ARP_CACHE = 0x0f,
+ NES_CQP_DOWNLOAD_SEGMENT = 0x10,
NES_CQP_SUSPEND_QPS = 0x11,
NES_CQP_UPLOAD_CONTEXT = 0x13,
NES_CQP_CREATE_CEQ = 0x16,
@@ -210,7 +218,8 @@ enum nes_cqp_opcodes {
NES_CQP_DESTROY_AEQ = 0x1b,
NES_CQP_LMI_ACCESS = 0x20,
NES_CQP_FLUSH_WQES = 0x22,
- NES_CQP_MANAGE_APBVT = 0x23
+ NES_CQP_MANAGE_APBVT = 0x23,
+ NES_CQP_MANAGE_QUAD_HASH = 0x25
};
enum nes_cqp_wqe_word_idx {
@@ -222,6 +231,14 @@ enum nes_cqp_wqe_word_idx {
NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX = 5,
};
+enum nes_cqp_wqe_word_download_idx { /* format differs from other cqp ops */
+ NES_CQP_WQE_DL_OPCODE_IDX = 0,
+ NES_CQP_WQE_DL_COMP_CTX_LOW_IDX = 1,
+ NES_CQP_WQE_DL_COMP_CTX_HIGH_IDX = 2,
+ NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX = 3
+ /* For index values 4-15 use NES_NIC_SQ_WQE_ values */
+};
+
enum nes_cqp_cq_wqeword_idx {
NES_CQP_CQ_WQE_PBL_LOW_IDX = 6,
NES_CQP_CQ_WQE_PBL_HIGH_IDX = 7,
@@ -242,6 +259,7 @@ enum nes_cqp_stag_wqeword_idx {
NES_CQP_STAG_WQE_PBL_LEN_IDX = 14
};
+#define NES_CQP_OP_LOGICAL_PORT_SHIFT 26
#define NES_CQP_OP_IWARP_STATE_SHIFT 28
#define NES_CQP_OP_TERMLEN_SHIFT 28
@@ -599,6 +617,7 @@ enum nes_nic_sq_wqe_bits {
enum nes_nic_cqe_word_idx {
NES_NIC_CQE_ACCQP_ID_IDX = 0,
+ NES_NIC_CQE_HASH_RCVNXT = 1,
NES_NIC_CQE_TAG_PKT_TYPE_IDX = 2,
NES_NIC_CQE_MISC_IDX = 3,
};
@@ -1005,6 +1024,11 @@ struct nes_arp_entry {
#define NES_NIC_CQ_DOWNWARD_TREND 16
#define NES_PFT_SIZE 48
+#define NES_MGT_WQ_COUNT 32
+#define NES_MGT_CTX_SIZE ((NES_NIC_CTX_RQ_SIZE_32) | (NES_NIC_CTX_SQ_SIZE_32))
+#define NES_MGT_QP_OFFSET 36
+#define NES_MGT_QP_COUNT 4
+
struct nes_hw_tune_timer {
/* u16 cq_count; */
u16 threshold_low;
@@ -1118,6 +1142,7 @@ struct nes_adapter {
u32 et_rate_sample_interval;
u32 timer_int_limit;
u32 wqm_quanta;
+ u8 allow_unaligned_fpdus;
/* Adapter base MAC address */
u32 mac_addr_low;
@@ -1251,6 +1276,14 @@ struct nes_vnic {
enum ib_event_type delayed_event;
enum ib_event_type last_dispatched_event;
spinlock_t port_ibevent_lock;
+ u32 mgt_mem_size;
+ void *mgt_vbase;
+ dma_addr_t mgt_pbase;
+ struct nes_vnic_mgt *mgtvnic[NES_MGT_QP_COUNT];
+ struct task_struct *mgt_thread;
+ wait_queue_head_t mgt_wait_queue;
+ struct sk_buff_head mgt_skb_list;
+
};
struct nes_ib_device {
diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
new file mode 100644
index 000000000000..b3b2a240c6e9
--- /dev/null
+++ b/drivers/infiniband/hw/nes/nes_mgt.c
@@ -0,0 +1,1162 @@
+/*
+ * Copyright (c) 2006 - 2009 Intel-NE, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/kthread.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include "nes.h"
+#include "nes_mgt.h"
+
+atomic_t pau_qps_created;
+atomic_t pau_qps_destroyed;
+
+static void nes_replenish_mgt_rq(struct nes_vnic_mgt *mgtvnic)
+{
+ unsigned long flags;
+ dma_addr_t bus_address;
+ struct sk_buff *skb;
+ struct nes_hw_nic_rq_wqe *nic_rqe;
+ struct nes_hw_mgt *nesmgt;
+ struct nes_device *nesdev;
+ struct nes_rskb_cb *cb;
+ u32 rx_wqes_posted = 0;
+
+ nesmgt = &mgtvnic->mgt;
+ nesdev = mgtvnic->nesvnic->nesdev;
+ spin_lock_irqsave(&nesmgt->rq_lock, flags);
+ if (nesmgt->replenishing_rq != 0) {
+ if (((nesmgt->rq_size - 1) == atomic_read(&mgtvnic->rx_skbs_needed)) &&
+ (atomic_read(&mgtvnic->rx_skb_timer_running) == 0)) {
+ atomic_set(&mgtvnic->rx_skb_timer_running, 1);
+ spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+ mgtvnic->rq_wqes_timer.expires = jiffies + (HZ / 2); /* 1/2 second */
+ add_timer(&mgtvnic->rq_wqes_timer);
+ } else {
+ spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+ }
+ return;
+ }
+ nesmgt->replenishing_rq = 1;
+ spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+ do {
+ skb = dev_alloc_skb(mgtvnic->nesvnic->max_frame_size);
+ if (skb) {
+ skb->dev = mgtvnic->nesvnic->netdev;
+
+ bus_address = pci_map_single(nesdev->pcidev,
+ skb->data, mgtvnic->nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ cb->busaddr = bus_address;
+ cb->maplen = mgtvnic->nesvnic->max_frame_size;
+
+ nic_rqe = &nesmgt->rq_vbase[mgtvnic->mgt.rq_head];
+ nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
+ cpu_to_le32(mgtvnic->nesvnic->max_frame_size);
+ nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
+ nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] =
+ cpu_to_le32((u32)bus_address);
+ nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] =
+ cpu_to_le32((u32)((u64)bus_address >> 32));
+ nesmgt->rx_skb[nesmgt->rq_head] = skb;
+ nesmgt->rq_head++;
+ nesmgt->rq_head &= nesmgt->rq_size - 1;
+ atomic_dec(&mgtvnic->rx_skbs_needed);
+ barrier();
+ if (++rx_wqes_posted == 255) {
+ nes_write32(nesdev->regs + NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesmgt->qp_id);
+ rx_wqes_posted = 0;
+ }
+ } else {
+ spin_lock_irqsave(&nesmgt->rq_lock, flags);
+ if (((nesmgt->rq_size - 1) == atomic_read(&mgtvnic->rx_skbs_needed)) &&
+ (atomic_read(&mgtvnic->rx_skb_timer_running) == 0)) {
+ atomic_set(&mgtvnic->rx_skb_timer_running, 1);
+ spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+ mgtvnic->rq_wqes_timer.expires = jiffies + (HZ / 2); /* 1/2 second */
+ add_timer(&mgtvnic->rq_wqes_timer);
+ } else {
+ spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+ }
+ break;
+ }
+ } while (atomic_read(&mgtvnic->rx_skbs_needed));
+ barrier();
+ if (rx_wqes_posted)
+ nes_write32(nesdev->regs + NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesmgt->qp_id);
+ nesmgt->replenishing_rq = 0;
+}
+
+/**
+ * nes_mgt_rq_wqes_timeout
+ */
+static void nes_mgt_rq_wqes_timeout(unsigned long parm)
+{
+ struct nes_vnic_mgt *mgtvnic = (struct nes_vnic_mgt *)parm;
+
+ atomic_set(&mgtvnic->rx_skb_timer_running, 0);
+ if (atomic_read(&mgtvnic->rx_skbs_needed))
+ nes_replenish_mgt_rq(mgtvnic);
+}
+
+/**
+ * nes_mgt_free_skb - unmap and free skb
+ */
+static void nes_mgt_free_skb(struct nes_device *nesdev, struct sk_buff *skb, u32 dir)
+{
+ struct nes_rskb_cb *cb;
+
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen, dir);
+ cb->busaddr = 0;
+ dev_kfree_skb_any(skb);
+}
+
+/**
+ * nes_download_callback - handle download completions
+ */
+static void nes_download_callback(struct nes_device *nesdev, struct nes_cqp_request *cqp_request)
+{
+ struct pau_fpdu_info *fpdu_info = cqp_request->cqp_callback_pointer;
+ struct nes_qp *nesqp = fpdu_info->nesqp;
+ struct sk_buff *skb;
+ int i;
+
+ for (i = 0; i < fpdu_info->frag_cnt; i++) {
+ skb = fpdu_info->frags[i].skb;
+ if (fpdu_info->frags[i].cmplt) {
+ nes_mgt_free_skb(nesdev, skb, PCI_DMA_TODEVICE);
+ nes_rem_ref_cm_node(nesqp->cm_node);
+ }
+ }
+
+ if (fpdu_info->hdr_vbase)
+ pci_free_consistent(nesdev->pcidev, fpdu_info->hdr_len,
+ fpdu_info->hdr_vbase, fpdu_info->hdr_pbase);
+ kfree(fpdu_info);
+}
+
+/**
+ * nes_get_seq - Get the seq, ack_seq and window from the packet
+ */
+static u32 nes_get_seq(struct sk_buff *skb, u32 *ack, u16 *wnd, u32 *fin_rcvd, u32 *rst_rcvd)
+{
+ struct nes_rskb_cb *cb = (struct nes_rskb_cb *)&skb->cb[0];
+ struct iphdr *iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+ struct tcphdr *tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+
+ *ack = be32_to_cpu(tcph->ack_seq);
+ *wnd = be16_to_cpu(tcph->window);
+ *fin_rcvd = tcph->fin;
+ *rst_rcvd = tcph->rst;
+ return be32_to_cpu(tcph->seq);
+}
+
+/**
+ * nes_get_next_skb - Get the next skb based on where current skb is in the queue
+ */
+static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp *nesqp,
+ struct sk_buff *skb, u32 nextseq, u32 *ack,
+ u16 *wnd, u32 *fin_rcvd, u32 *rst_rcvd)
+{
+ u32 seq;
+ bool processacks;
+ struct sk_buff *old_skb;
+
+ if (skb) {
+ /* Continue processing fpdu */
+ if (skb->next == (struct sk_buff *)&nesqp->pau_list)
+ goto out;
+ skb = skb->next;
+ processacks = false;
+ } else {
+ /* Starting a new one */
+ if (skb_queue_empty(&nesqp->pau_list))
+ goto out;
+ skb = skb_peek(&nesqp->pau_list);
+ processacks = true;
+ }
+
+ while (1) {
+ seq = nes_get_seq(skb, ack, wnd, fin_rcvd, rst_rcvd);
+ if (seq == nextseq) {
+ if (skb->len || processacks)
+ break;
+ } else if (after(seq, nextseq)) {
+ goto out;
+ }
+
+ if (skb->next == (struct sk_buff *)&nesqp->pau_list)
+ goto out;
+
+ old_skb = skb;
+ skb = skb->next;
+ skb_unlink(old_skb, &nesqp->pau_list);
+ nes_mgt_free_skb(nesdev, old_skb, PCI_DMA_TODEVICE);
+ nes_rem_ref_cm_node(nesqp->cm_node);
+ }
+ return skb;
+
+out:
+ return NULL;
+}
+
+/**
+ * get_fpdu_info - Find the next complete fpdu and return its fragments.
+ */
+static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
+ struct pau_fpdu_info **pau_fpdu_info)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct tcphdr *tcph;
+ struct nes_rskb_cb *cb;
+ struct pau_fpdu_info *fpdu_info = NULL;
+ struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
+ unsigned long flags;
+ u32 fpdu_len = 0;
+ u32 tmp_len;
+ int frag_cnt = 0;
+ u32 tot_len;
+ u32 frag_tot;
+ u32 ack;
+ u32 fin_rcvd;
+ u32 rst_rcvd;
+ u16 wnd;
+ int i;
+ int rc = 0;
+
+ *pau_fpdu_info = NULL;
+
+ spin_lock_irqsave(&nesqp->pau_lock, flags);
+ skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, &wnd, &fin_rcvd, &rst_rcvd);
+ if (!skb) {
+ spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+ goto out;
+ }
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ if (skb->len) {
+ fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING;
+ fpdu_len = (fpdu_len + 3) & 0xfffffffc;
+ tmp_len = fpdu_len;
+
+ /* See if we have all of the fpdu */
+ frag_tot = 0;
+ memset(&frags, 0, sizeof frags);
+ for (i = 0; i < MAX_FPDU_FRAGS; i++) {
+ frags[i].physaddr = cb->busaddr;
+ frags[i].physaddr += skb->data - cb->data_start;
+ frags[i].frag_len = min(tmp_len, skb->len);
+ frags[i].skb = skb;
+ frags[i].cmplt = (skb->len == frags[i].frag_len);
+ frag_tot += frags[i].frag_len;
+ frag_cnt++;
+
+ tmp_len -= frags[i].frag_len;
+ if (tmp_len == 0)
+ break;
+
+ skb = nes_get_next_skb(nesdev, nesqp, skb,
+ nesqp->pau_rcv_nxt + frag_tot, &ack, &wnd, &fin_rcvd, &rst_rcvd);
+ if (!skb) {
+ spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+ goto out;
+ } else if (rst_rcvd) {
+ /* rst received in the middle of fpdu */
+ for (; i >= 0; i--) {
+ skb_unlink(frags[i].skb, &nesqp->pau_list);
+ nes_mgt_free_skb(nesdev, frags[i].skb, PCI_DMA_TODEVICE);
+ }
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ frags[0].physaddr = cb->busaddr;
+ frags[0].physaddr += skb->data - cb->data_start;
+ frags[0].frag_len = skb->len;
+ frags[0].skb = skb;
+ frags[0].cmplt = true;
+ frag_cnt = 1;
+ break;
+ }
+
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ }
+ } else {
+ /* no data */
+ frags[0].physaddr = cb->busaddr;
+ frags[0].frag_len = 0;
+ frags[0].skb = skb;
+ frags[0].cmplt = true;
+ frag_cnt = 1;
+ }
+
+ spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+
+ /* Found one */
+ fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC);
+ if (fpdu_info == NULL) {
+ nes_debug(NES_DBG_PAU, "Failed to alloc a fpdu_info.\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ fpdu_info->cqp_request = nes_get_cqp_request(nesdev);
+ if (fpdu_info->cqp_request == NULL) {
+ nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ cb = (struct nes_rskb_cb *)&frags[0].skb->cb[0];
+ iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+ tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+ fpdu_info->hdr_len = (((unsigned char *)tcph) + 4 * (tcph->doff)) - cb->data_start;
+ fpdu_info->data_len = fpdu_len;
+ tot_len = fpdu_info->hdr_len + fpdu_len - ETH_HLEN;
+
+ if (frags[0].cmplt) {
+ fpdu_info->hdr_pbase = cb->busaddr;
+ fpdu_info->hdr_vbase = NULL;
+ } else {
+ fpdu_info->hdr_vbase = pci_alloc_consistent(nesdev->pcidev,
+ fpdu_info->hdr_len, &fpdu_info->hdr_pbase);
+ if (!fpdu_info->hdr_vbase) {
+ nes_debug(NES_DBG_PAU, "Unable to allocate memory for pau first frag\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Copy hdrs, adjusting len and seqnum */
+ memcpy(fpdu_info->hdr_vbase, cb->data_start, fpdu_info->hdr_len);
+ iph = (struct iphdr *)(fpdu_info->hdr_vbase + ETH_HLEN);
+ tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+ }
+
+ iph->tot_len = cpu_to_be16(tot_len);
+ iph->saddr = cpu_to_be32(0x7f000001);
+
+ tcph->seq = cpu_to_be32(nesqp->pau_rcv_nxt);
+ tcph->ack_seq = cpu_to_be32(ack);
+ tcph->window = cpu_to_be16(wnd);
+
+ nesqp->pau_rcv_nxt += fpdu_len + fin_rcvd;
+
+ memcpy(fpdu_info->frags, frags, sizeof(fpdu_info->frags));
+ fpdu_info->frag_cnt = frag_cnt;
+ fpdu_info->nesqp = nesqp;
+ *pau_fpdu_info = fpdu_info;
+
+ /* Update skb's for next pass */
+ for (i = 0; i < frag_cnt; i++) {
+ cb = (struct nes_rskb_cb *)&frags[i].skb->cb[0];
+ skb_pull(frags[i].skb, frags[i].frag_len);
+
+ if (frags[i].skb->len == 0) {
+ /* Pull skb off the list - it will be freed in the callback */
+ spin_lock_irqsave(&nesqp->pau_lock, flags);
+ skb_unlink(frags[i].skb, &nesqp->pau_list);
+ spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+ } else {
+ /* Last skb still has data so update the seq */
+ iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+ tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+ tcph->seq = cpu_to_be32(nesqp->pau_rcv_nxt);
+ }
+ }
+
+out:
+ if (rc) {
+ if (fpdu_info) {
+ if (fpdu_info->cqp_request)
+ nes_put_cqp_request(nesdev, fpdu_info->cqp_request);
+ kfree(fpdu_info);
+ }
+ }
+ return rc;
+}
+
+/**
+ * forward_fpdu - send complete fpdus, one at a time
+ */
+static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+ struct nes_device *nesdev = nesvnic->nesdev;
+ struct pau_fpdu_info *fpdu_info;
+ struct nes_hw_cqp_wqe *cqp_wqe;
+ struct nes_cqp_request *cqp_request;
+ u64 u64tmp;
+ u32 u32tmp;
+ int rc;
+
+ while (1) {
+ rc = get_fpdu_info(nesdev, nesqp, &fpdu_info);
+ if (fpdu_info == NULL)
+ return rc;
+
+ cqp_request = fpdu_info->cqp_request;
+ cqp_wqe = &cqp_request->cqp_wqe;
+ nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_DL_OPCODE_IDX,
+ NES_CQP_DOWNLOAD_SEGMENT |
+ (((u32)nesvnic->logical_port) << NES_CQP_OP_LOGICAL_PORT_SHIFT));
+
+ u32tmp = fpdu_info->hdr_len << 16;
+ u32tmp |= fpdu_info->hdr_len + (u32)fpdu_info->data_len;
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX,
+ u32tmp);
+
+ u32tmp = (fpdu_info->frags[1].frag_len << 16) | fpdu_info->frags[0].frag_len;
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_LENGTH_2_1_IDX,
+ u32tmp);
+
+ u32tmp = (fpdu_info->frags[3].frag_len << 16) | fpdu_info->frags[2].frag_len;
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_LENGTH_4_3_IDX,
+ u32tmp);
+
+ u64tmp = (u64)fpdu_info->hdr_pbase;
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX,
+ lower_32_bits(u64tmp));
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_HIGH_IDX,
+ upper_32_bits(u64tmp >> 32));
+
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
+ lower_32_bits(fpdu_info->frags[0].physaddr));
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_HIGH_IDX,
+ upper_32_bits(fpdu_info->frags[0].physaddr));
+
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG2_LOW_IDX,
+ lower_32_bits(fpdu_info->frags[1].physaddr));
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG2_HIGH_IDX,
+ upper_32_bits(fpdu_info->frags[1].physaddr));
+
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG3_LOW_IDX,
+ lower_32_bits(fpdu_info->frags[2].physaddr));
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG3_HIGH_IDX,
+ upper_32_bits(fpdu_info->frags[2].physaddr));
+
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG4_LOW_IDX,
+ lower_32_bits(fpdu_info->frags[3].physaddr));
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG4_HIGH_IDX,
+ upper_32_bits(fpdu_info->frags[3].physaddr));
+
+ cqp_request->cqp_callback_pointer = fpdu_info;
+ cqp_request->callback = 1;
+ cqp_request->cqp_callback = nes_download_callback;
+
+ atomic_set(&cqp_request->refcount, 1);
+ nes_post_cqp_request(nesdev, cqp_request);
+ }
+
+ return 0;
+}
+
+static void process_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+ int again = 1;
+ unsigned long flags;
+
+ do {
+ /* Ignore rc - if it failed, tcp retries will cause it to try again */
+ forward_fpdus(nesvnic, nesqp);
+
+ spin_lock_irqsave(&nesqp->pau_lock, flags);
+ if (nesqp->pau_pending) {
+ nesqp->pau_pending = 0;
+ } else {
+ nesqp->pau_busy = 0;
+ again = 0;
+ }
+
+ spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+ } while (again);
+}
+
+/**
+ * queue_fpdus - Handle fpdu's that hw passed up to sw
+ */
+static void queue_fpdus(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+ struct sk_buff *tmpskb;
+ struct nes_rskb_cb *cb;
+ struct iphdr *iph;
+ struct tcphdr *tcph;
+ unsigned char *tcph_end;
+ u32 rcv_nxt;
+ u32 rcv_wnd;
+ u32 seqnum;
+ u32 len;
+ bool process_it = false;
+ unsigned long flags;
+
+ /* Move data ptr to after tcp header */
+ iph = (struct iphdr *)skb->data;
+ tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+ seqnum = be32_to_cpu(tcph->seq);
+ tcph_end = (((char *)tcph) + (4 * tcph->doff));
+
+ len = be16_to_cpu(iph->tot_len);
+ if (skb->len > len)
+ skb_trim(skb, len);
+ skb_pull(skb, tcph_end - skb->data);
+
+ /* Initialize tracking values */
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ cb->seqnum = seqnum;
+
+ /* Make sure data is in the receive window */
+ rcv_nxt = nesqp->pau_rcv_nxt;
+ rcv_wnd = le32_to_cpu(nesqp->nesqp_context->rcv_wnd);
+ if (!between(seqnum, rcv_nxt, (rcv_nxt + rcv_wnd))) {
+ nes_mgt_free_skb(nesvnic->nesdev, skb, PCI_DMA_TODEVICE);
+ nes_rem_ref_cm_node(nesqp->cm_node);
+ return;
+ }
+
+ spin_lock_irqsave(&nesqp->pau_lock, flags);
+
+ if (nesqp->pau_busy)
+ nesqp->pau_pending = 1;
+ else
+ nesqp->pau_busy = 1;
+
+ /* Queue skb by sequence number */
+ if (skb_queue_len(&nesqp->pau_list) == 0) {
+ skb_queue_head(&nesqp->pau_list, skb);
+ } else {
+ tmpskb = nesqp->pau_list.next;
+ while (tmpskb != (struct sk_buff *)&nesqp->pau_list) {
+ cb = (struct nes_rskb_cb *)&tmpskb->cb[0];
+ if (before(seqnum, cb->seqnum))
+ break;
+ tmpskb = tmpskb->next;
+ }
+ skb_insert(tmpskb, skb, &nesqp->pau_list);
+ }
+ if (nesqp->pau_state == PAU_READY)
+ process_it = true;
+ spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+
+ if (process_it)
+ process_fpdus(nesvnic, nesqp);
+
+ return;
+}
+
+/**
+ * mgt_thread - Handle mgt skbs in a safe context
+ */
+static int mgt_thread(void *context)
+{
+ struct nes_vnic *nesvnic = context;
+ struct sk_buff *skb;
+ struct nes_rskb_cb *cb;
+
+ while (!kthread_should_stop()) {
+ wait_event_interruptible(nesvnic->mgt_wait_queue,
+ skb_queue_len(&nesvnic->mgt_skb_list) || kthread_should_stop());
+ while ((skb_queue_len(&nesvnic->mgt_skb_list)) && !kthread_should_stop()) {
+ skb = skb_dequeue(&nesvnic->mgt_skb_list);
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ cb->data_start = skb->data - ETH_HLEN;
+ cb->busaddr = pci_map_single(nesvnic->nesdev->pcidev, cb->data_start,
+ nesvnic->max_frame_size, PCI_DMA_TODEVICE);
+ queue_fpdus(skb, nesvnic, cb->nesqp);
+ }
+ }
+
+ /* Closing down so delete any entries on the queue */
+ while (skb_queue_len(&nesvnic->mgt_skb_list)) {
+ skb = skb_dequeue(&nesvnic->mgt_skb_list);
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ nes_rem_ref_cm_node(cb->nesqp->cm_node);
+ dev_kfree_skb_any(skb);
+ }
+ return 0;
+}
+
+/**
+ * nes_queue_skbs - Queue skb so it can be handled in a thread context
+ */
+void nes_queue_mgt_skbs(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+ struct nes_rskb_cb *cb;
+
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ cb->nesqp = nesqp;
+ skb_queue_tail(&nesvnic->mgt_skb_list, skb);
+ wake_up_interruptible(&nesvnic->mgt_wait_queue);
+}
+
+void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp)
+{
+ struct sk_buff *skb;
+ unsigned long flags;
+ atomic_inc(&pau_qps_destroyed);
+
+ /* Free packets that have not yet been forwarded */
+ /* Lock is acquired by skb_dequeue when removing the skb */
+ spin_lock_irqsave(&nesqp->pau_lock, flags);
+ while (skb_queue_len(&nesqp->pau_list)) {
+ skb = skb_dequeue(&nesqp->pau_list);
+ nes_mgt_free_skb(nesdev, skb, PCI_DMA_TODEVICE);
+ nes_rem_ref_cm_node(nesqp->cm_node);
+ }
+ spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+}
+
+static void nes_chg_qh_handler(struct nes_device *nesdev, struct nes_cqp_request *cqp_request)
+{
+ struct pau_qh_chg *qh_chg = cqp_request->cqp_callback_pointer;
+ struct nes_cqp_request *new_request;
+ struct nes_hw_cqp_wqe *cqp_wqe;
+ struct nes_adapter *nesadapter;
+ struct nes_qp *nesqp;
+ struct nes_v4_quad nes_quad;
+ u32 crc_value;
+ u64 u64temp;
+
+ nesadapter = nesdev->nesadapter;
+ nesqp = qh_chg->nesqp;
+
+ /* Should we handle the bad completion */
+ if (cqp_request->major_code) {
+ printk(KERN_ERR PFX "Invalid cqp_request major_code=0x%x\n",
+ cqp_request->major_code);
+ WARN_ON(1);
+ }
+
+ switch (nesqp->pau_state) {
+ case PAU_DEL_QH:
+ /* Old hash code deleted, now set the new one */
+ nesqp->pau_state = PAU_ADD_LB_QH;
+ new_request = nes_get_cqp_request(nesdev);
+ if (new_request == NULL) {
+ nes_debug(NES_DBG_PAU, "Failed to get a new_request.\n");
+ WARN_ON(1);
+ return;
+ }
+
+ memset(&nes_quad, 0, sizeof(nes_quad));
+ nes_quad.DstIpAdrIndex =
+ cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
+ nes_quad.SrcIpadr = cpu_to_be32(0x7f000001);
+ nes_quad.TcpPorts[0] = swab16(nesqp->nesqp_context->tcpPorts[1]);
+ nes_quad.TcpPorts[1] = swab16(nesqp->nesqp_context->tcpPorts[0]);
+
+ /* Produce hash key */
+ crc_value = get_crc_value(&nes_quad);
+ nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
+ nes_debug(NES_DBG_PAU, "new HTE Index = 0x%08X, CRC = 0x%08X\n",
+ nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
+
+ nesqp->hte_index &= nesadapter->hte_index_mask;
+ nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
+ nesqp->nesqp_context->ip0 = cpu_to_le32(0x7f000001);
+ nesqp->nesqp_context->rcv_nxt = cpu_to_le32(nesqp->pau_rcv_nxt);
+
+ cqp_wqe = &new_request->cqp_wqe;
+ nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+ set_wqe_32bit_value(cqp_wqe->wqe_words,
+ NES_CQP_WQE_OPCODE_IDX, NES_CQP_MANAGE_QUAD_HASH |
+ NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_CONTEXT_VALID | NES_CQP_QP_IWARP_STATE_RTS);
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
+ u64temp = (u64)nesqp->nesqp_context_pbase;
+ set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+ nes_debug(NES_DBG_PAU, "Waiting for CQP completion for adding the quad hash.\n");
+
+ new_request->cqp_callback_pointer = qh_chg;
+ new_request->callback = 1;
+ new_request->cqp_callback = nes_chg_qh_handler;
+ atomic_set(&new_request->refcount, 1);
+ nes_post_cqp_request(nesdev, new_request);
+ break;
+
+ case PAU_ADD_LB_QH:
+ /* Start processing the queued fpdu's */
+ nesqp->pau_state = PAU_READY;
+ process_fpdus(qh_chg->nesvnic, qh_chg->nesqp);
+ kfree(qh_chg);
+ break;
+ }
+}
+
+/**
+ * nes_change_quad_hash
+ */
+static int nes_change_quad_hash(struct nes_device *nesdev,
+ struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+ struct nes_cqp_request *cqp_request = NULL;
+ struct pau_qh_chg *qh_chg = NULL;
+ u64 u64temp;
+ struct nes_hw_cqp_wqe *cqp_wqe;
+ int ret = 0;
+
+ cqp_request = nes_get_cqp_request(nesdev);
+ if (cqp_request == NULL) {
+ nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+ ret = -ENOMEM;
+ goto chg_qh_err;
+ }
+
+ qh_chg = kmalloc(sizeof *qh_chg, GFP_ATOMIC);
+ if (qh_chg == NULL) {
+ nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+ ret = -ENOMEM;
+ goto chg_qh_err;
+ }
+ qh_chg->nesdev = nesdev;
+ qh_chg->nesvnic = nesvnic;
+ qh_chg->nesqp = nesqp;
+ nesqp->pau_state = PAU_DEL_QH;
+
+ cqp_wqe = &cqp_request->cqp_wqe;
+ nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+ set_wqe_32bit_value(cqp_wqe->wqe_words,
+ NES_CQP_WQE_OPCODE_IDX, NES_CQP_MANAGE_QUAD_HASH | NES_CQP_QP_DEL_HTE |
+ NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_CONTEXT_VALID | NES_CQP_QP_IWARP_STATE_RTS);
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
+ u64temp = (u64)nesqp->nesqp_context_pbase;
+ set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+ nes_debug(NES_DBG_PAU, "Waiting for CQP completion for deleting the quad hash.\n");
+
+ cqp_request->cqp_callback_pointer = qh_chg;
+ cqp_request->callback = 1;
+ cqp_request->cqp_callback = nes_chg_qh_handler;
+ atomic_set(&cqp_request->refcount, 1);
+ nes_post_cqp_request(nesdev, cqp_request);
+
+ return ret;
+
+chg_qh_err:
+ kfree(qh_chg);
+ if (cqp_request)
+ nes_put_cqp_request(nesdev, cqp_request);
+ return ret;
+}
+
+/**
+ * nes_mgt_ce_handler
+ * This management code deals with any packed and unaligned (pau) fpdu's
+ * that the hardware cannot handle.
+ */
+static void nes_mgt_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+{
+ struct nes_vnic_mgt *mgtvnic = container_of(cq, struct nes_vnic_mgt, mgt_cq);
+ struct nes_adapter *nesadapter = nesdev->nesadapter;
+ u32 head;
+ u32 cq_size;
+ u32 cqe_count = 0;
+ u32 cqe_misc;
+ u32 qp_id = 0;
+ u32 skbs_needed;
+ unsigned long context;
+ struct nes_qp *nesqp;
+ struct sk_buff *rx_skb;
+ struct nes_rskb_cb *cb;
+
+ head = cq->cq_head;
+ cq_size = cq->cq_size;
+
+ while (1) {
+ cqe_misc = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]);
+ if (!(cqe_misc & NES_NIC_CQE_VALID))
+ break;
+
+ nesqp = NULL;
+ if (cqe_misc & NES_NIC_CQE_ACCQP_VALID) {
+ qp_id = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_ACCQP_ID_IDX]);
+ qp_id &= 0x001fffff;
+ if (qp_id < nesadapter->max_qp) {
+ context = (unsigned long)nesadapter->qp_table[qp_id - NES_FIRST_QPN];
+ nesqp = (struct nes_qp *)context;
+ }
+ }
+
+ if (nesqp) {
+ if (nesqp->pau_mode == false) {
+ nesqp->pau_mode = true; /* First time for this qp */
+ nesqp->pau_rcv_nxt = le32_to_cpu(
+ cq->cq_vbase[head].cqe_words[NES_NIC_CQE_HASH_RCVNXT]);
+ skb_queue_head_init(&nesqp->pau_list);
+ spin_lock_init(&nesqp->pau_lock);
+ atomic_inc(&pau_qps_created);
+ nes_change_quad_hash(nesdev, mgtvnic->nesvnic, nesqp);
+ }
+
+ rx_skb = mgtvnic->mgt.rx_skb[mgtvnic->mgt.rq_tail];
+ rx_skb->len = 0;
+ skb_put(rx_skb, cqe_misc & 0x0000ffff);
+ rx_skb->protocol = eth_type_trans(rx_skb, mgtvnic->nesvnic->netdev);
+ cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+ pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen, PCI_DMA_FROMDEVICE);
+ cb->busaddr = 0;
+ mgtvnic->mgt.rq_tail++;
+ mgtvnic->mgt.rq_tail &= mgtvnic->mgt.rq_size - 1;
+
+ nes_add_ref_cm_node(nesqp->cm_node);
+ nes_queue_mgt_skbs(rx_skb, mgtvnic->nesvnic, nesqp);
+ } else {
+ printk(KERN_ERR PFX "Invalid QP %d for packed/unaligned handling\n", qp_id);
+ }
+
+ cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX] = 0;
+ cqe_count++;
+ if (++head >= cq_size)
+ head = 0;
+
+ if (cqe_count == 255) {
+ /* Replenish mgt CQ */
+ nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (cqe_count << 16));
+ nesdev->currcq_count += cqe_count;
+ cqe_count = 0;
+ }
+
+ skbs_needed = atomic_inc_return(&mgtvnic->rx_skbs_needed);
+ if (skbs_needed > (mgtvnic->mgt.rq_size >> 1))
+ nes_replenish_mgt_rq(mgtvnic);
+ }
+
+ cq->cq_head = head;
+ nes_write32(nesdev->regs + NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
+ cq->cq_number | (cqe_count << 16));
+ nes_read32(nesdev->regs + NES_CQE_ALLOC);
+ nesdev->currcq_count += cqe_count;
+}
+
+/**
+ * nes_init_mgt_qp
+ */
+int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct nes_vnic *nesvnic)
+{
+ struct nes_vnic_mgt *mgtvnic;
+ u32 counter;
+ void *vmem;
+ dma_addr_t pmem;
+ struct nes_hw_cqp_wqe *cqp_wqe;
+ u32 cqp_head;
+ unsigned long flags;
+ struct nes_hw_nic_qp_context *mgt_context;
+ u64 u64temp;
+ struct nes_hw_nic_rq_wqe *mgt_rqe;
+ struct sk_buff *skb;
+ u32 wqe_count;
+ struct nes_rskb_cb *cb;
+ u32 mgt_mem_size;
+ void *mgt_vbase;
+ dma_addr_t mgt_pbase;
+ int i;
+ int ret;
+
+ /* Allocate space the all mgt QPs once */
+ mgtvnic = kzalloc(NES_MGT_QP_COUNT * sizeof(struct nes_vnic_mgt), GFP_KERNEL);
+ if (mgtvnic == NULL) {
+ nes_debug(NES_DBG_INIT, "Unable to allocate memory for mgt structure\n");
+ return -ENOMEM;
+ }
+
+ /* Allocate fragment, RQ, and CQ; Reuse CEQ based on the PCI function */
+ /* We are not sending from this NIC so sq is not allocated */
+ mgt_mem_size = 256 +
+ (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe)) +
+ (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_cqe)) +
+ sizeof(struct nes_hw_nic_qp_context);
+ mgt_mem_size = (mgt_mem_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+ mgt_vbase = pci_alloc_consistent(nesdev->pcidev, NES_MGT_QP_COUNT * mgt_mem_size, &mgt_pbase);
+ if (!mgt_vbase) {
+ kfree(mgtvnic);
+ nes_debug(NES_DBG_INIT, "Unable to allocate memory for mgt host descriptor rings\n");
+ return -ENOMEM;
+ }
+
+ nesvnic->mgt_mem_size = NES_MGT_QP_COUNT * mgt_mem_size;
+ nesvnic->mgt_vbase = mgt_vbase;
+ nesvnic->mgt_pbase = mgt_pbase;
+
+ skb_queue_head_init(&nesvnic->mgt_skb_list);
+ init_waitqueue_head(&nesvnic->mgt_wait_queue);
+ nesvnic->mgt_thread = kthread_run(mgt_thread, nesvnic, "nes_mgt_thread");
+
+ for (i = 0; i < NES_MGT_QP_COUNT; i++) {
+ mgtvnic->nesvnic = nesvnic;
+ mgtvnic->mgt.qp_id = nesdev->mac_index + NES_MGT_QP_OFFSET + i;
+ memset(mgt_vbase, 0, mgt_mem_size);
+ nes_debug(NES_DBG_INIT, "Allocated mgt QP structures at %p (phys = %016lX), size = %u.\n",
+ mgt_vbase, (unsigned long)mgt_pbase, mgt_mem_size);
+
+ vmem = (void *)(((unsigned long)mgt_vbase + (256 - 1)) &
+ ~(unsigned long)(256 - 1));
+ pmem = (dma_addr_t)(((unsigned long long)mgt_pbase + (256 - 1)) &
+ ~(unsigned long long)(256 - 1));
+
+ spin_lock_init(&mgtvnic->mgt.rq_lock);
+
+ /* setup the RQ */
+ mgtvnic->mgt.rq_vbase = vmem;
+ mgtvnic->mgt.rq_pbase = pmem;
+ mgtvnic->mgt.rq_head = 0;
+ mgtvnic->mgt.rq_tail = 0;
+ mgtvnic->mgt.rq_size = NES_MGT_WQ_COUNT;
+
+ /* setup the CQ */
+ vmem += (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe));
+ pmem += (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe));
+
+ mgtvnic->mgt_cq.cq_number = mgtvnic->mgt.qp_id;
+ mgtvnic->mgt_cq.cq_vbase = vmem;
+ mgtvnic->mgt_cq.cq_pbase = pmem;
+ mgtvnic->mgt_cq.cq_head = 0;
+ mgtvnic->mgt_cq.cq_size = NES_MGT_WQ_COUNT;
+
+ mgtvnic->mgt_cq.ce_handler = nes_mgt_ce_handler;
+
+ /* Send CreateCQ request to CQP */
+ spin_lock_irqsave(&nesdev->cqp.lock, flags);
+ cqp_head = nesdev->cqp.sq_head;
+
+ cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+ nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+ cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
+ NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
+ ((u32)mgtvnic->mgt_cq.cq_size << 16));
+ cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(
+ mgtvnic->mgt_cq.cq_number | ((u32)nesdev->ceq_index << 16));
+ u64temp = (u64)mgtvnic->mgt_cq.cq_pbase;
+ set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
+ cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
+ u64temp = (unsigned long)&mgtvnic->mgt_cq;
+ cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = cpu_to_le32((u32)(u64temp >> 1));
+ cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
+ cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
+ cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
+
+ if (++cqp_head >= nesdev->cqp.sq_size)
+ cqp_head = 0;
+ cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+ nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+ /* Send CreateQP request to CQP */
+ mgt_context = (void *)(&mgtvnic->mgt_cq.cq_vbase[mgtvnic->mgt_cq.cq_size]);
+ mgt_context->context_words[NES_NIC_CTX_MISC_IDX] =
+ cpu_to_le32((u32)NES_MGT_CTX_SIZE |
+ ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 12));
+ nes_debug(NES_DBG_INIT, "RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n",
+ nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE),
+ nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE));
+ if (nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE) != 0)
+ mgt_context->context_words[NES_NIC_CTX_MISC_IDX] |= cpu_to_le32(NES_NIC_BACK_STORE);
+
+ u64temp = (u64)mgtvnic->mgt.rq_pbase;
+ mgt_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+ mgt_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
+ u64temp = (u64)mgtvnic->mgt.rq_pbase;
+ mgt_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+ mgt_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
+
+ cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
+ NES_CQP_QP_TYPE_NIC);
+ cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(mgtvnic->mgt.qp_id);
+ u64temp = (u64)mgtvnic->mgt_cq.cq_pbase +
+ (mgtvnic->mgt_cq.cq_size * sizeof(struct nes_hw_nic_cqe));
+ set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+ if (++cqp_head >= nesdev->cqp.sq_size)
+ cqp_head = 0;
+ nesdev->cqp.sq_head = cqp_head;
+
+ barrier();
+
+ /* Ring doorbell (2 WQEs) */
+ nes_write32(nesdev->regs + NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
+
+ spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
+ nes_debug(NES_DBG_INIT, "Waiting for create MGT QP%u to complete.\n",
+ mgtvnic->mgt.qp_id);
+
+ ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
+ NES_EVENT_TIMEOUT);
+ nes_debug(NES_DBG_INIT, "Create MGT QP%u completed, wait_event_timeout ret = %u.\n",
+ mgtvnic->mgt.qp_id, ret);
+ if (!ret) {
+ nes_debug(NES_DBG_INIT, "MGT QP%u create timeout expired\n", mgtvnic->mgt.qp_id);
+ if (i == 0) {
+ pci_free_consistent(nesdev->pcidev, nesvnic->mgt_mem_size, nesvnic->mgt_vbase,
+ nesvnic->mgt_pbase);
+ kfree(mgtvnic);
+ } else {
+ nes_destroy_mgt(nesvnic);
+ }
+ return -EIO;
+ }
+
+ /* Populate the RQ */
+ for (counter = 0; counter < (NES_MGT_WQ_COUNT - 1); counter++) {
+ skb = dev_alloc_skb(nesvnic->max_frame_size);
+ if (!skb) {
+ nes_debug(NES_DBG_INIT, "%s: out of memory for receive skb\n", netdev->name);
+ return -ENOMEM;
+ }
+
+ skb->dev = netdev;
+
+ pmem = pci_map_single(nesdev->pcidev, skb->data,
+ nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+ cb = (struct nes_rskb_cb *)&skb->cb[0];
+ cb->busaddr = pmem;
+ cb->maplen = nesvnic->max_frame_size;
+
+ mgt_rqe = &mgtvnic->mgt.rq_vbase[counter];
+ mgt_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32((u32)nesvnic->max_frame_size);
+ mgt_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
+ mgt_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
+ mgt_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
+ mgtvnic->mgt.rx_skb[counter] = skb;
+ }
+
+ init_timer(&mgtvnic->rq_wqes_timer);
+ mgtvnic->rq_wqes_timer.function = nes_mgt_rq_wqes_timeout;
+ mgtvnic->rq_wqes_timer.data = (unsigned long)mgtvnic;
+
+ wqe_count = NES_MGT_WQ_COUNT - 1;
+ mgtvnic->mgt.rq_head = wqe_count;
+ barrier();
+ do {
+ counter = min(wqe_count, ((u32)255));
+ wqe_count -= counter;
+ nes_write32(nesdev->regs + NES_WQE_ALLOC, (counter << 24) | mgtvnic->mgt.qp_id);
+ } while (wqe_count);
+
+ nes_write32(nesdev->regs + NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
+ mgtvnic->mgt_cq.cq_number);
+ nes_read32(nesdev->regs + NES_CQE_ALLOC);
+
+ mgt_vbase += mgt_mem_size;
+ mgt_pbase += mgt_mem_size;
+ nesvnic->mgtvnic[i] = mgtvnic++;
+ }
+ return 0;
+}
+
+
+void nes_destroy_mgt(struct nes_vnic *nesvnic)
+{
+ struct nes_device *nesdev = nesvnic->nesdev;
+ struct nes_vnic_mgt *mgtvnic;
+ struct nes_vnic_mgt *first_mgtvnic;
+ unsigned long flags;
+ struct nes_hw_cqp_wqe *cqp_wqe;
+ u32 cqp_head;
+ struct sk_buff *rx_skb;
+ int i;
+ int ret;
+
+ kthread_stop(nesvnic->mgt_thread);
+
+ /* Free remaining NIC receive buffers */
+ first_mgtvnic = nesvnic->mgtvnic[0];
+ for (i = 0; i < NES_MGT_QP_COUNT; i++) {
+ mgtvnic = nesvnic->mgtvnic[i];
+ if (mgtvnic == NULL)
+ continue;
+
+ while (mgtvnic->mgt.rq_head != mgtvnic->mgt.rq_tail) {
+ rx_skb = mgtvnic->mgt.rx_skb[mgtvnic->mgt.rq_tail];
+ nes_mgt_free_skb(nesdev, rx_skb, PCI_DMA_FROMDEVICE);
+ mgtvnic->mgt.rq_tail++;
+ mgtvnic->mgt.rq_tail &= (mgtvnic->mgt.rq_size - 1);
+ }
+
+ spin_lock_irqsave(&nesdev->cqp.lock, flags);
+
+ /* Destroy NIC QP */
+ cqp_head = nesdev->cqp.sq_head;
+ cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+ nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
+ (NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC));
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
+ mgtvnic->mgt.qp_id);
+
+ if (++cqp_head >= nesdev->cqp.sq_size)
+ cqp_head = 0;
+
+ cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+
+ /* Destroy NIC CQ */
+ nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
+ (NES_CQP_DESTROY_CQ | ((u32)mgtvnic->mgt_cq.cq_size << 16)));
+ set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
+ (mgtvnic->mgt_cq.cq_number | ((u32)nesdev->ceq_index << 16)));
+
+ if (++cqp_head >= nesdev->cqp.sq_size)
+ cqp_head = 0;
+
+ nesdev->cqp.sq_head = cqp_head;
+ barrier();
+
+ /* Ring doorbell (2 WQEs) */
+ nes_write32(nesdev->regs + NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
+
+ spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
+ nes_debug(NES_DBG_SHUTDOWN, "Waiting for CQP, cqp_head=%u, cqp.sq_head=%u,"
+ " cqp.sq_tail=%u, cqp.sq_size=%u\n",
+ cqp_head, nesdev->cqp.sq_head,
+ nesdev->cqp.sq_tail, nesdev->cqp.sq_size);
+
+ ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
+ NES_EVENT_TIMEOUT);
+
+ nes_debug(NES_DBG_SHUTDOWN, "Destroy MGT QP returned, wait_event_timeout ret = %u, cqp_head=%u,"
+ " cqp.sq_head=%u, cqp.sq_tail=%u\n",
+ ret, cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
+ if (!ret)
+ nes_debug(NES_DBG_SHUTDOWN, "MGT QP%u destroy timeout expired\n",
+ mgtvnic->mgt.qp_id);
+
+ nesvnic->mgtvnic[i] = NULL;
+ }
+
+ if (nesvnic->mgt_vbase) {
+ pci_free_consistent(nesdev->pcidev, nesvnic->mgt_mem_size, nesvnic->mgt_vbase,
+ nesvnic->mgt_pbase);
+ nesvnic->mgt_vbase = NULL;
+ nesvnic->mgt_pbase = 0;
+ }
+
+ kfree(first_mgtvnic);
+}
diff --git a/drivers/infiniband/hw/nes/nes_mgt.h b/drivers/infiniband/hw/nes/nes_mgt.h
new file mode 100644
index 000000000000..8c8af254555a
--- /dev/null
+++ b/drivers/infiniband/hw/nes/nes_mgt.h
@@ -0,0 +1,97 @@
+/*
+* Copyright (c) 2010 Intel-NE, Inc. All rights reserved.
+*
+* This software is available to you under a choice of one of two
+* licenses. You may choose to be licensed under the terms of the GNU
+* General Public License (GPL) Version 2, available from the file
+* COPYING in the main directory of this source tree, or the
+* OpenIB.org BSD license below:
+*
+* Redistribution and use in source and binary forms, with or
+* without modification, are permitted provided that the following
+* conditions are met:
+*
+* - Redistributions of source code must retain the above
+* copyright notice, this list of conditions and the following
+* disclaimer.
+*
+* - Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials
+* provided with the distribution.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+#ifndef __NES_MGT_H
+#define __NES_MGT_H
+
+#define MPA_FRAMING 6 /* length is 2 bytes, crc is 4 bytes */
+
+int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct nes_vnic *nesvnic);
+void nes_queue_mgt_skbs(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp);
+void nes_destroy_mgt(struct nes_vnic *nesvnic);
+void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp);
+
+struct nes_hw_mgt {
+ struct nes_hw_nic_rq_wqe *rq_vbase; /* virtual address of rq */
+ dma_addr_t rq_pbase; /* PCI memory for host rings */
+ struct sk_buff *rx_skb[NES_NIC_WQ_SIZE];
+ u16 qp_id;
+ u16 sq_head;
+ u16 rq_head;
+ u16 rq_tail;
+ u16 rq_size;
+ u8 replenishing_rq;
+ u8 reserved;
+ spinlock_t rq_lock;
+};
+
+struct nes_vnic_mgt {
+ struct nes_vnic *nesvnic;
+ struct nes_hw_mgt mgt;
+ struct nes_hw_nic_cq mgt_cq;
+ atomic_t rx_skbs_needed;
+ struct timer_list rq_wqes_timer;
+ atomic_t rx_skb_timer_running;
+};
+
+#define MAX_FPDU_FRAGS 4
+struct pau_fpdu_frag {
+ struct sk_buff *skb;
+ u64 physaddr;
+ u32 frag_len;
+ bool cmplt;
+};
+
+struct pau_fpdu_info {
+ struct nes_qp *nesqp;
+ struct nes_cqp_request *cqp_request;
+ void *hdr_vbase;
+ dma_addr_t hdr_pbase;
+ int hdr_len;
+ u16 data_len;
+ u16 frag_cnt;
+ struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
+};
+
+enum pau_qh_state {
+ PAU_DEL_QH,
+ PAU_ADD_LB_QH,
+ PAU_READY
+};
+
+struct pau_qh_chg {
+ struct nes_device *nesdev;
+ struct nes_vnic *nesvnic;
+ struct nes_qp *nesqp;
+};
+
+#endif /* __NES_MGT_H */
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 9d7ffebff213..c00d2f3f8966 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -441,13 +441,13 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev)
nesnic->tx_skb[nesnic->sq_head] = skb;
for (skb_fragment_index = 0; skb_fragment_index < skb_shinfo(skb)->nr_frags;
skb_fragment_index++) {
- bus_address = pci_map_page( nesdev->pcidev,
- skb_shinfo(skb)->frags[skb_fragment_index].page,
- skb_shinfo(skb)->frags[skb_fragment_index].page_offset,
- skb_shinfo(skb)->frags[skb_fragment_index].size,
- PCI_DMA_TODEVICE);
+ skb_frag_t *frag =
+ &skb_shinfo(skb)->frags[skb_fragment_index];
+ bus_address = skb_frag_dma_map(&nesdev->pcidev->dev,
+ frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
wqe_fragment_length[wqe_fragment_index] =
- cpu_to_le16(skb_shinfo(skb)->frags[skb_fragment_index].size);
+ cpu_to_le16(skb_frag_size(&skb_shinfo(skb)->frags[skb_fragment_index]));
set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
bus_address);
wqe_fragment_index++;
@@ -561,11 +561,12 @@ tso_sq_no_longer_full:
/* Map all the buffers */
for (tso_frag_count=0; tso_frag_count < skb_shinfo(skb)->nr_frags;
tso_frag_count++) {
- tso_bus_address[tso_frag_count] = pci_map_page( nesdev->pcidev,
- skb_shinfo(skb)->frags[tso_frag_count].page,
- skb_shinfo(skb)->frags[tso_frag_count].page_offset,
- skb_shinfo(skb)->frags[tso_frag_count].size,
- PCI_DMA_TODEVICE);
+ skb_frag_t *frag =
+ &skb_shinfo(skb)->frags[tso_frag_count];
+ tso_bus_address[tso_frag_count] =
+ skb_frag_dma_map(&nesdev->pcidev->dev,
+ frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
}
tso_frag_index = 0;
@@ -636,11 +637,11 @@ tso_sq_no_longer_full:
}
while (wqe_fragment_index < 5) {
wqe_fragment_length[wqe_fragment_index] =
- cpu_to_le16(skb_shinfo(skb)->frags[tso_frag_index].size);
+ cpu_to_le16(skb_frag_size(&skb_shinfo(skb)->frags[tso_frag_index]));
set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
(u64)tso_bus_address[tso_frag_index]);
wqe_fragment_index++;
- tso_wqe_length += skb_shinfo(skb)->frags[tso_frag_index++].size;
+ tso_wqe_length += skb_frag_size(&skb_shinfo(skb)->frags[tso_frag_index++]);
if (wqe_fragment_index < 5)
wqe_fragment_length[wqe_fragment_index] = 0;
if (tso_frag_index == tso_frag_count)
@@ -1090,6 +1091,8 @@ static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
"LRO aggregated",
"LRO flushed",
"LRO no_desc",
+ "PAU CreateQPs",
+ "PAU DestroyQPs",
};
#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)
@@ -1305,6 +1308,8 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated;
target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed;
target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc;
+ target_stat_values[++index] = atomic_read(&pau_qps_created);
+ target_stat_values[++index] = atomic_read(&pau_qps_destroyed);
}
/**
@@ -1638,7 +1643,7 @@ static const struct net_device_ops nes_netdev_ops = {
.ndo_get_stats = nes_netdev_get_stats,
.ndo_tx_timeout = nes_netdev_tx_timeout,
.ndo_set_mac_address = nes_netdev_set_mac_address,
- .ndo_set_multicast_list = nes_netdev_set_multicast_list,
+ .ndo_set_rx_mode = nes_netdev_set_multicast_list,
.ndo_change_mtu = nes_netdev_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_fix_features = nes_fix_features,
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index f9c417c6b3b3..cd10968bfa22 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -51,13 +51,34 @@
#include "nes.h"
-
-
static u16 nes_read16_eeprom(void __iomem *addr, u16 offset);
u32 mh_detected;
u32 mh_pauses_sent;
+u32 nes_set_pau(struct nes_device *nesdev)
+{
+ u32 ret = 0;
+ u32 counter;
+
+ nes_write_indexed(nesdev, NES_IDX_GPR2, NES_ENABLE_PAU);
+ nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
+
+ for (counter = 0; counter < NES_PAU_COUNTER; counter++) {
+ udelay(30);
+ if (!nes_read_indexed(nesdev, NES_IDX_GPR2)) {
+ printk(KERN_INFO PFX "PAU is supported.\n");
+ break;
+ }
+ nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
+ }
+ if (counter == NES_PAU_COUNTER) {
+ printk(KERN_INFO PFX "PAU is not supported.\n");
+ return -EPERM;
+ }
+ return ret;
+}
+
/**
* nes_read_eeprom_values -
*/
@@ -187,6 +208,11 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada
if (((major_ver == 3) && (minor_ver >= 16)) || (major_ver > 3))
nesadapter->send_term_ok = 1;
+ if (nes_drv_opt & NES_DRV_OPT_ENABLE_PAU) {
+ if (!nes_set_pau(nesdev))
+ nesadapter->allow_unaligned_fpdus = 1;
+ }
+
nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8)) << 16) +
(u32)((u8)eeprom_data);
@@ -594,6 +620,7 @@ void nes_put_cqp_request(struct nes_device *nesdev,
nes_free_cqp_request(nesdev, cqp_request);
}
+
/**
* nes_post_cqp_request
*/
@@ -604,6 +631,8 @@ void nes_post_cqp_request(struct nes_device *nesdev,
unsigned long flags;
u32 cqp_head;
u64 u64temp;
+ u32 opcode;
+ int ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
spin_lock_irqsave(&nesdev->cqp.lock, flags);
@@ -614,17 +643,20 @@ void nes_post_cqp_request(struct nes_device *nesdev,
nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
+ opcode = le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]);
+ if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
+ ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
barrier();
u64temp = (unsigned long)cqp_request;
- set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_SCRATCH_LOW_IDX,
- u64temp);
+ set_wqe_64bit_value(cqp_wqe->wqe_words, ctx_index, u64temp);
nes_debug(NES_DBG_CQP, "CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ,"
- " request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
- " waiting = %d, refcount = %d.\n",
- le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f,
- le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
- nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
- cqp_request->waiting, atomic_read(&cqp_request->refcount));
+ " request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
+ " waiting = %d, refcount = %d.\n",
+ opcode & NES_CQP_OPCODE_MASK,
+ le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
+ nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
+ cqp_request->waiting, atomic_read(&cqp_request->refcount));
+
barrier();
/* Ring doorbell (1 WQEs) */
@@ -645,7 +677,6 @@ void nes_post_cqp_request(struct nes_device *nesdev,
return;
}
-
/**
* nes_arp_table
*/
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 9f2f7d4b1197..5095bc41c6cc 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1458,7 +1458,7 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
struct ib_qp_attr attr;
struct iw_cm_id *cm_id;
struct iw_cm_event cm_event;
- int ret;
+ int ret = 0;
atomic_inc(&sw_qps_destroyed);
nesqp->destroyed = 1;
@@ -1511,7 +1511,6 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))
nes_clean_cq(nesqp, nesqp->nesrcq);
}
-
nes_rem_ref(&nesqp->ibqp);
return 0;
}
@@ -2338,8 +2337,10 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
skip_pages = ((u32)region->offset) >> 12;
- if (ib_copy_from_udata(&req, udata, sizeof(req)))
+ if (ib_copy_from_udata(&req, udata, sizeof(req))) {
+ ib_umem_release(region);
return ERR_PTR(-EFAULT);
+ }
nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type);
switch (req.reg_type) {
@@ -2631,6 +2632,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
return &nesmr->ibmr;
}
+ ib_umem_release(region);
return ERR_PTR(-ENOSYS);
}
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index 2df9993e0cac..fe6b6e92fa90 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -139,7 +139,8 @@ struct nes_qp {
struct nes_cq *nesrcq;
struct nes_pd *nespd;
void *cm_node; /* handle of the node this QP is associated with */
- struct ietf_mpa_frame *ietf_frame;
+ void *ietf_frame;
+ u8 ietf_frame_size;
dma_addr_t ietf_frame_pbase;
struct ib_mr *lsmm_mr;
struct nes_hw_qp hwqp;
@@ -154,6 +155,7 @@ struct nes_qp {
u32 mmap_sq_db_index;
u32 mmap_rq_db_index;
spinlock_t lock;
+ spinlock_t pau_lock;
struct nes_qp_context *nesqp_context;
dma_addr_t nesqp_context_pbase;
void *pbl_vbase;
@@ -161,6 +163,8 @@ struct nes_qp {
struct page *page;
struct timer_list terminate_timer;
enum ib_event_type terminate_eventtype;
+ struct sk_buff_head pau_list;
+ u32 pau_rcv_nxt;
u16 active_conn:1;
u16 skip_lsmm:1;
u16 user_mode:1;
@@ -168,7 +172,8 @@ struct nes_qp {
u16 flush_issued:1;
u16 destroyed:1;
u16 sig_all:1;
- u16 rsvd:9;
+ u16 pau_mode:1;
+ u16 rsvd:8;
u16 private_data_len;
u16 term_sq_flush_code;
u16 term_rq_flush_code;
@@ -176,5 +181,8 @@ struct nes_qp {
u8 hw_tcp_state;
u8 term_flags;
u8 sq_kmapped;
+ u8 pau_busy;
+ u8 pau_pending;
+ u8 pau_state;
};
#endif /* NES_VERBS_H */
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index c9624ea87209..b881bdc401f5 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -171,7 +171,9 @@ struct qib_ctxtdata {
/* how many alloc_pages() chunks in rcvegrbuf_pages */
u32 rcvegrbuf_chunks;
/* how many egrbufs per chunk */
- u32 rcvegrbufs_perchunk;
+ u16 rcvegrbufs_perchunk;
+ /* ilog2 of above */
+ u16 rcvegrbufs_perchunk_shift;
/* order for rcvegrbuf_pages */
size_t rcvegrbuf_size;
/* rcvhdrq size (for freeing) */
@@ -221,6 +223,9 @@ struct qib_ctxtdata {
/* ctxt rcvhdrq head offset */
u32 head;
u32 pkt_count;
+ /* lookaside fields */
+ struct qib_qp *lookaside_qp;
+ u32 lookaside_qpn;
/* QPs waiting for context processing */
struct list_head qp_wait_list;
};
@@ -807,6 +812,10 @@ struct qib_devdata {
* supports, less gives more pio bufs/ctxt, etc.
*/
u32 cfgctxts;
+ /*
+ * number of ctxts available for PSM open
+ */
+ u32 freectxts;
/*
* hint that we should update pioavailshadow before
@@ -936,7 +945,9 @@ struct qib_devdata {
/* chip address space used by 4k pio buffers */
u32 align4k;
/* size of each rcvegrbuffer */
- u32 rcvegrbufsize;
+ u16 rcvegrbufsize;
+ /* log2 of above */
+ u16 rcvegrbufsize_shift;
/* localbus width (1, 2,4,8,16,32) from config space */
u32 lbus_width;
/* localbus speed in MHz */
diff --git a/drivers/infiniband/hw/qib/qib_driver.c b/drivers/infiniband/hw/qib/qib_driver.c
index 23e584f4c36c..9a9047f385ae 100644
--- a/drivers/infiniband/hw/qib/qib_driver.c
+++ b/drivers/infiniband/hw/qib/qib_driver.c
@@ -279,10 +279,10 @@ bail:
*/
static inline void *qib_get_egrbuf(const struct qib_ctxtdata *rcd, u32 etail)
{
- const u32 chunk = etail / rcd->rcvegrbufs_perchunk;
- const u32 idx = etail % rcd->rcvegrbufs_perchunk;
+ const u32 chunk = etail >> rcd->rcvegrbufs_perchunk_shift;
+ const u32 idx = etail & ((u32)rcd->rcvegrbufs_perchunk - 1);
- return rcd->rcvegrbuf[chunk] + idx * rcd->dd->rcvegrbufsize;
+ return rcd->rcvegrbuf[chunk] + (idx << rcd->dd->rcvegrbufsize_shift);
}
/*
@@ -310,7 +310,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
u32 opcode;
u32 psn;
int diff;
- unsigned long flags;
/* Sanity check packet */
if (tlen < 24)
@@ -365,7 +364,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
switch (qp->ibqp.qp_type) {
case IB_QPT_RC:
- spin_lock_irqsave(&qp->s_lock, flags);
ruc_res =
qib_ruc_check_hdr(
ibp, hdr,
@@ -373,11 +371,8 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
qp,
be32_to_cpu(ohdr->bth[0]));
if (ruc_res) {
- spin_unlock_irqrestore(&qp->s_lock,
- flags);
goto unlock;
}
- spin_unlock_irqrestore(&qp->s_lock, flags);
/* Only deal with RDMA Writes for now */
if (opcode <
@@ -547,6 +542,15 @@ move_along:
updegr = 0;
}
}
+ /*
+ * Notify qib_destroy_qp() if it is waiting
+ * for lookaside_qp to finish.
+ */
+ if (rcd->lookaside_qp) {
+ if (atomic_dec_and_test(&rcd->lookaside_qp->refcount))
+ wake_up(&rcd->lookaside_qp->wait);
+ rcd->lookaside_qp = NULL;
+ }
rcd->head = l;
rcd->pkt_count += i;
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index 26253039d2c7..77633666f81c 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -1284,6 +1284,7 @@ static int setup_ctxt(struct qib_pportdata *ppd, int ctxt,
strlcpy(rcd->comm, current->comm, sizeof(rcd->comm));
ctxt_fp(fp) = rcd;
qib_stats.sps_ctxts++;
+ dd->freectxts++;
ret = 0;
goto bail;
@@ -1792,6 +1793,7 @@ static int qib_close(struct inode *in, struct file *fp)
if (dd->pageshadow)
unlock_expected_tids(rcd);
qib_stats.sps_ctxts--;
+ dd->freectxts--;
}
mutex_unlock(&qib_mutex);
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index d8ca0a0b970d..781a802a321f 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -3273,6 +3273,8 @@ static int init_6120_variables(struct qib_devdata *dd)
/* we always allocate at least 2048 bytes for eager buffers */
ret = ib_mtu_enum_to_int(qib_ibmtu);
dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
+ BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+ dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
qib_6120_tidtemplate(dd);
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c
index e1f947446c2a..3f1d562ba898 100644
--- a/drivers/infiniband/hw/qib/qib_iba7220.c
+++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -4085,6 +4085,8 @@ static int qib_init_7220_variables(struct qib_devdata *dd)
/* we always allocate at least 2048 bytes for eager buffers */
ret = ib_mtu_enum_to_int(qib_ibmtu);
dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
+ BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+ dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
qib_7220_tidtemplate(dd);
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 5ea9ece23b33..efd0a110091f 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -2310,12 +2310,15 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
+ ppd->cpspec->ibcctrl_a = val;
/*
* Reset the PCS interface to the serdes (and also ibc, which is still
* in reset from above). Writes new value of ibcctrl_a as last step.
*/
qib_7322_mini_pcs_reset(ppd);
qib_write_kreg(dd, kr_scratch, 0ULL);
+ /* clear the linkinit cmds */
+ ppd->cpspec->ibcctrl_a &= ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
if (!ppd->cpspec->ibcctrl_b) {
unsigned lse = ppd->link_speed_enabled;
@@ -2387,11 +2390,6 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
qib_write_kreg_port(ppd, krp_rcvctrl, ppd->p_rcvctrl);
spin_unlock_irqrestore(&dd->cspec->rcvmod_lock, flags);
- /* Hold the link state machine for mezz boards */
- if (IS_QMH(dd) || IS_QME(dd))
- qib_set_ib_7322_lstate(ppd, 0,
- QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
-
/* Also enable IBSTATUSCHG interrupt. */
val = qib_read_kreg_port(ppd, krp_errmask);
qib_write_kreg_port(ppd, krp_errmask,
@@ -2853,9 +2851,8 @@ static irqreturn_t qib_7322intr(int irq, void *data)
for (i = 0; i < dd->first_user_ctxt; i++) {
if (ctxtrbits & rmask) {
ctxtrbits &= ~rmask;
- if (dd->rcd[i]) {
+ if (dd->rcd[i])
qib_kreceive(dd->rcd[i], NULL, &npkts);
- }
}
rmask <<= 1;
}
@@ -5230,6 +5227,8 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
QIBL_IB_AUTONEG_INPROG)))
set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled);
if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) {
+ struct qib_qsfp_data *qd =
+ &ppd->cpspec->qsfp_data;
/* unlock the Tx settings, speed may change */
qib_write_kreg_port(ppd, krp_tx_deemph_override,
SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
@@ -5237,6 +5236,12 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
qib_cancel_sends(ppd);
/* on link down, ensure sane pcs state */
qib_7322_mini_pcs_reset(ppd);
+ /* schedule the qsfp refresh which should turn the link
+ off */
+ if (ppd->dd->flags & QIB_HAS_QSFP) {
+ qd->t_insert = get_jiffies_64();
+ schedule_work(&qd->work);
+ }
spin_lock_irqsave(&ppd->sdma_lock, flags);
if (__qib_sdma_running(ppd))
__qib_sdma_process_event(ppd,
@@ -5587,43 +5592,79 @@ static void qsfp_7322_event(struct work_struct *work)
struct qib_qsfp_data *qd;
struct qib_pportdata *ppd;
u64 pwrup;
+ unsigned long flags;
int ret;
u32 le2;
qd = container_of(work, struct qib_qsfp_data, work);
ppd = qd->ppd;
- pwrup = qd->t_insert + msecs_to_jiffies(QSFP_PWR_LAG_MSEC);
+ pwrup = qd->t_insert +
+ msecs_to_jiffies(QSFP_PWR_LAG_MSEC - QSFP_MODPRS_LAG_MSEC);
- /*
- * Some QSFP's not only do not respond until the full power-up
- * time, but may behave badly if we try. So hold off responding
- * to insertion.
- */
- while (1) {
- u64 now = get_jiffies_64();
- if (time_after64(now, pwrup))
- break;
- msleep(20);
- }
- ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
- /*
- * Need to change LE2 back to defaults if we couldn't
- * read the cable type (to handle cable swaps), so do this
- * even on failure to read cable information. We don't
- * get here for QME, so IS_QME check not needed here.
- */
- if (!ret && !ppd->dd->cspec->r1) {
- if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
- le2 = LE2_QME;
- else if (qd->cache.atten[1] >= qib_long_atten &&
- QSFP_IS_CU(qd->cache.tech))
- le2 = LE2_5m;
- else
+ /* Delay for 20 msecs to allow ModPrs resistor to setup */
+ mdelay(QSFP_MODPRS_LAG_MSEC);
+
+ if (!qib_qsfp_mod_present(ppd)) {
+ ppd->cpspec->qsfp_data.modpresent = 0;
+ /* Set the physical link to disabled */
+ qib_set_ib_7322_lstate(ppd, 0,
+ QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
+ spin_lock_irqsave(&ppd->lflags_lock, flags);
+ ppd->lflags &= ~QIBL_LINKV;
+ spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+ } else {
+ /*
+ * Some QSFP's not only do not respond until the full power-up
+ * time, but may behave badly if we try. So hold off responding
+ * to insertion.
+ */
+ while (1) {
+ u64 now = get_jiffies_64();
+ if (time_after64(now, pwrup))
+ break;
+ msleep(20);
+ }
+
+ ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
+
+ /*
+ * Need to change LE2 back to defaults if we couldn't
+ * read the cable type (to handle cable swaps), so do this
+ * even on failure to read cable information. We don't
+ * get here for QME, so IS_QME check not needed here.
+ */
+ if (!ret && !ppd->dd->cspec->r1) {
+ if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
+ le2 = LE2_QME;
+ else if (qd->cache.atten[1] >= qib_long_atten &&
+ QSFP_IS_CU(qd->cache.tech))
+ le2 = LE2_5m;
+ else
+ le2 = LE2_DEFAULT;
+ } else
le2 = LE2_DEFAULT;
- } else
- le2 = LE2_DEFAULT;
- ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
- init_txdds_table(ppd, 0);
+ ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
+ /*
+ * We always change parameteters, since we can choose
+ * values for cables without eeproms, and the cable may have
+ * changed from a cable with full or partial eeprom content
+ * to one with partial or no content.
+ */
+ init_txdds_table(ppd, 0);
+ /* The physical link is being re-enabled only when the
+ * previous state was DISABLED and the VALID bit is not
+ * set. This should only happen when the cable has been
+ * physically pulled. */
+ if (!ppd->cpspec->qsfp_data.modpresent &&
+ (ppd->lflags & (QIBL_LINKV | QIBL_IB_LINK_DISABLED))) {
+ ppd->cpspec->qsfp_data.modpresent = 1;
+ qib_set_ib_7322_lstate(ppd, 0,
+ QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
+ spin_lock_irqsave(&ppd->lflags_lock, flags);
+ ppd->lflags |= QIBL_LINKV;
+ spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+ }
+ }
}
/*
@@ -5727,7 +5768,8 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
/* now change the IBC and serdes, overriding generic */
init_txdds_table(ppd, 1);
/* Re-enable the physical state machine on mezz boards
- * now that the correct settings have been set. */
+ * now that the correct settings have been set.
+ * QSFP boards are handles by the QSFP event handler */
if (IS_QMH(dd) || IS_QME(dd))
qib_set_ib_7322_lstate(ppd, 0,
QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
@@ -6205,6 +6247,8 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
/* we always allocate at least 2048 bytes for eager buffers */
dd->rcvegrbufsize = max(mtu, 2048);
+ BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+ dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
qib_7322_tidtemplate(dd);
@@ -7147,7 +7191,8 @@ static void find_best_ent(struct qib_pportdata *ppd,
}
}
- /* Lookup serdes setting by cable type and attenuation */
+ /* Active cables don't have attenuation so we only set SERDES
+ * settings to account for the attenuation of the board traces. */
if (!override && QSFP_IS_ACTIVE(qd->tech)) {
*sdr_dds = txdds_sdr + ppd->dd->board_atten;
*ddr_dds = txdds_ddr + ppd->dd->board_atten;
@@ -7464,12 +7509,6 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd)
u32 le_val, rxcaldone;
int chan, chan_done = (1 << SERDES_CHANS) - 1;
- /*
- * Initialize the Tx DDS tables. Also done every QSFP event,
- * for adapters with QSFP
- */
- init_txdds_table(ppd, 0);
-
/* Clear cmode-override, may be set from older driver */
ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 0 << 14, 1 << 14);
@@ -7655,6 +7694,12 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd)
/* VGA output common mode */
ibsd_wr_allchans(ppd, 12, (3 << 2), BMASK(3, 2));
+ /*
+ * Initialize the Tx DDS tables. Also done every QSFP event,
+ * for adapters with QSFP
+ */
+ init_txdds_table(ppd, 0);
+
return 0;
}
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index a01f3fce8eb3..b093a0b53b2f 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -183,6 +183,9 @@ struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt)
rcd->rcvegrbuf_chunks = (rcd->rcvegrcnt +
rcd->rcvegrbufs_perchunk - 1) /
rcd->rcvegrbufs_perchunk;
+ BUG_ON(!is_power_of_2(rcd->rcvegrbufs_perchunk));
+ rcd->rcvegrbufs_perchunk_shift =
+ ilog2(rcd->rcvegrbufs_perchunk);
}
return rcd;
}
@@ -398,6 +401,7 @@ static void enable_chip(struct qib_devdata *dd)
if (rcd)
dd->f_rcvctrl(rcd->ppd, rcvmask, i);
}
+ dd->freectxts = dd->cfgctxts - dd->first_user_ctxt;
}
static void verify_interrupt(unsigned long opaque)
@@ -581,10 +585,6 @@ int qib_init(struct qib_devdata *dd, int reinit)
continue;
}
- /* let link come up, and enable IBC */
- spin_lock_irqsave(&ppd->lflags_lock, flags);
- ppd->lflags &= ~QIBL_IB_LINK_DISABLED;
- spin_unlock_irqrestore(&ppd->lflags_lock, flags);
portok++;
}
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index e16751f8639e..7e7e16fbee99 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -34,6 +34,7 @@
#include <linux/err.h>
#include <linux/vmalloc.h>
+#include <linux/jhash.h>
#include "qib.h"
@@ -204,6 +205,13 @@ static void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
}
+static inline unsigned qpn_hash(struct qib_ibdev *dev, u32 qpn)
+{
+ return jhash_1word(qpn, dev->qp_rnd) &
+ (dev->qp_table_size - 1);
+}
+
+
/*
* Put the QP into the hash table.
* The hash table holds a reference to the QP.
@@ -211,22 +219,23 @@ static void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
{
struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- unsigned n = qp->ibqp.qp_num % dev->qp_table_size;
unsigned long flags;
+ unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
spin_lock_irqsave(&dev->qpt_lock, flags);
+ atomic_inc(&qp->refcount);
if (qp->ibqp.qp_num == 0)
- ibp->qp0 = qp;
+ rcu_assign_pointer(ibp->qp0, qp);
else if (qp->ibqp.qp_num == 1)
- ibp->qp1 = qp;
+ rcu_assign_pointer(ibp->qp1, qp);
else {
qp->next = dev->qp_table[n];
- dev->qp_table[n] = qp;
+ rcu_assign_pointer(dev->qp_table[n], qp);
}
- atomic_inc(&qp->refcount);
spin_unlock_irqrestore(&dev->qpt_lock, flags);
+ synchronize_rcu();
}
/*
@@ -236,29 +245,32 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
{
struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- struct qib_qp *q, **qpp;
+ unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
unsigned long flags;
- qpp = &dev->qp_table[qp->ibqp.qp_num % dev->qp_table_size];
-
spin_lock_irqsave(&dev->qpt_lock, flags);
if (ibp->qp0 == qp) {
- ibp->qp0 = NULL;
atomic_dec(&qp->refcount);
+ rcu_assign_pointer(ibp->qp0, NULL);
} else if (ibp->qp1 == qp) {
- ibp->qp1 = NULL;
atomic_dec(&qp->refcount);
- } else
+ rcu_assign_pointer(ibp->qp1, NULL);
+ } else {
+ struct qib_qp *q, **qpp;
+
+ qpp = &dev->qp_table[n];
for (; (q = *qpp) != NULL; qpp = &q->next)
if (q == qp) {
- *qpp = qp->next;
- qp->next = NULL;
atomic_dec(&qp->refcount);
+ rcu_assign_pointer(*qpp, qp->next);
+ qp->next = NULL;
break;
}
+ }
spin_unlock_irqrestore(&dev->qpt_lock, flags);
+ synchronize_rcu();
}
/**
@@ -280,21 +292,24 @@ unsigned qib_free_all_qps(struct qib_devdata *dd)
if (!qib_mcast_tree_empty(ibp))
qp_inuse++;
- if (ibp->qp0)
+ rcu_read_lock();
+ if (rcu_dereference(ibp->qp0))
qp_inuse++;
- if (ibp->qp1)
+ if (rcu_dereference(ibp->qp1))
qp_inuse++;
+ rcu_read_unlock();
}
spin_lock_irqsave(&dev->qpt_lock, flags);
for (n = 0; n < dev->qp_table_size; n++) {
qp = dev->qp_table[n];
- dev->qp_table[n] = NULL;
+ rcu_assign_pointer(dev->qp_table[n], NULL);
for (; qp; qp = qp->next)
qp_inuse++;
}
spin_unlock_irqrestore(&dev->qpt_lock, flags);
+ synchronize_rcu();
return qp_inuse;
}
@@ -309,25 +324,28 @@ unsigned qib_free_all_qps(struct qib_devdata *dd)
*/
struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn)
{
- struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
- unsigned long flags;
- struct qib_qp *qp;
+ struct qib_qp *qp = NULL;
- spin_lock_irqsave(&dev->qpt_lock, flags);
+ if (unlikely(qpn <= 1)) {
+ rcu_read_lock();
+ if (qpn == 0)
+ qp = rcu_dereference(ibp->qp0);
+ else
+ qp = rcu_dereference(ibp->qp1);
+ } else {
+ struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
+ unsigned n = qpn_hash(dev, qpn);
- if (qpn == 0)
- qp = ibp->qp0;
- else if (qpn == 1)
- qp = ibp->qp1;
- else
- for (qp = dev->qp_table[qpn % dev->qp_table_size]; qp;
- qp = qp->next)
+ rcu_read_lock();
+ for (qp = dev->qp_table[n]; rcu_dereference(qp); qp = qp->next)
if (qp->ibqp.qp_num == qpn)
break;
+ }
if (qp)
- atomic_inc(&qp->refcount);
+ if (unlikely(!atomic_inc_not_zero(&qp->refcount)))
+ qp = NULL;
- spin_unlock_irqrestore(&dev->qpt_lock, flags);
+ rcu_read_unlock();
return qp;
}
@@ -765,8 +783,10 @@ int qib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
}
}
- if (attr_mask & IB_QP_PATH_MTU)
+ if (attr_mask & IB_QP_PATH_MTU) {
qp->path_mtu = pmtu;
+ qp->pmtu = ib_mtu_enum_to_int(pmtu);
+ }
if (attr_mask & IB_QP_RETRY_CNT) {
qp->s_retry_cnt = attr->retry_cnt;
@@ -781,8 +801,12 @@ int qib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
if (attr_mask & IB_QP_MIN_RNR_TIMER)
qp->r_min_rnr_timer = attr->min_rnr_timer;
- if (attr_mask & IB_QP_TIMEOUT)
+ if (attr_mask & IB_QP_TIMEOUT) {
qp->timeout = attr->timeout;
+ qp->timeout_jiffies =
+ usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
+ 1000UL);
+ }
if (attr_mask & IB_QP_QKEY)
qp->qkey = attr->qkey;
@@ -1013,6 +1037,10 @@ struct ib_qp *qib_create_qp(struct ib_pd *ibpd,
ret = ERR_PTR(-ENOMEM);
goto bail_swq;
}
+ RCU_INIT_POINTER(qp->next, NULL);
+ qp->timeout_jiffies =
+ usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
+ 1000UL);
if (init_attr->srq)
sz = 0;
else {
diff --git a/drivers/infiniband/hw/qib/qib_qsfp.c b/drivers/infiniband/hw/qib/qib_qsfp.c
index 3374a52232c1..e06c4ed383f1 100644
--- a/drivers/infiniband/hw/qib/qib_qsfp.c
+++ b/drivers/infiniband/hw/qib/qib_qsfp.c
@@ -273,18 +273,12 @@ int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, struct qib_qsfp_cache *cp)
int ret;
int idx;
u16 cks;
- u32 mask;
u8 peek[4];
/* ensure sane contents on invalid reads, for cable swaps */
memset(cp, 0, sizeof(*cp));
- mask = QSFP_GPIO_MOD_PRS_N;
- if (ppd->hw_pidx)
- mask <<= QSFP_GPIO_PORT2_SHIFT;
-
- ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
- if (ret & mask) {
+ if (!qib_qsfp_mod_present(ppd)) {
ret = -ENODEV;
goto bail;
}
@@ -444,6 +438,19 @@ const char * const qib_qsfp_devtech[16] = {
static const char *pwr_codes = "1.5W2.0W2.5W3.5W";
+int qib_qsfp_mod_present(struct qib_pportdata *ppd)
+{
+ u32 mask;
+ int ret;
+
+ mask = QSFP_GPIO_MOD_PRS_N <<
+ (ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT);
+ ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
+
+ return !((ret & mask) >>
+ ((ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT) + 3));
+}
+
/*
* Initialize structures that control access to QSFP. Called once per port
* on cards that support QSFP.
@@ -452,7 +459,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
void (*fevent)(struct work_struct *))
{
u32 mask, highs;
- int pins;
struct qib_devdata *dd = qd->ppd->dd;
@@ -480,8 +486,7 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
mask <<= QSFP_GPIO_PORT2_SHIFT;
/* Do not try to wait here. Better to let event handle it */
- pins = dd->f_gpio_mod(dd, 0, 0, 0);
- if (pins & mask)
+ if (!qib_qsfp_mod_present(qd->ppd))
goto bail;
/* We see a module, but it may be unwise to look yet. Just schedule */
qd->t_insert = get_jiffies_64();
diff --git a/drivers/infiniband/hw/qib/qib_qsfp.h b/drivers/infiniband/hw/qib/qib_qsfp.h
index c109bbdc90ac..46002a9417c0 100644
--- a/drivers/infiniband/hw/qib/qib_qsfp.h
+++ b/drivers/infiniband/hw/qib/qib_qsfp.h
@@ -34,6 +34,7 @@
#define QSFP_DEV 0xA0
#define QSFP_PWR_LAG_MSEC 2000
+#define QSFP_MODPRS_LAG_MSEC 20
/*
* Below are masks for various QSFP signals, for Port 1.
@@ -177,10 +178,12 @@ struct qib_qsfp_data {
struct work_struct work;
struct qib_qsfp_cache cache;
u64 t_insert;
+ u8 modpresent;
};
extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd,
struct qib_qsfp_cache *cp);
+extern int qib_qsfp_mod_present(struct qib_pportdata *ppd);
extern void qib_qsfp_init(struct qib_qsfp_data *qd,
void (*fevent)(struct work_struct *));
extern void qib_qsfp_deinit(struct qib_qsfp_data *qd);
diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c
index eca0c41f1226..afaf4ac79f42 100644
--- a/drivers/infiniband/hw/qib/qib_rc.c
+++ b/drivers/infiniband/hw/qib/qib_rc.c
@@ -59,8 +59,7 @@ static void start_timer(struct qib_qp *qp)
qp->s_flags |= QIB_S_TIMER;
qp->s_timer.function = rc_timeout;
/* 4.096 usec. * (1 << qp->timeout) */
- qp->s_timer.expires = jiffies +
- usecs_to_jiffies((4096UL * (1UL << qp->timeout)) / 1000UL);
+ qp->s_timer.expires = jiffies + qp->timeout_jiffies;
add_timer(&qp->s_timer);
}
@@ -239,7 +238,7 @@ int qib_make_rc_req(struct qib_qp *qp)
u32 len;
u32 bth0;
u32 bth2;
- u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ u32 pmtu = qp->pmtu;
char newreq;
unsigned long flags;
int ret = 0;
@@ -1519,9 +1518,7 @@ read_middle:
* 4.096 usec. * (1 << qp->timeout)
*/
qp->s_flags |= QIB_S_TIMER;
- mod_timer(&qp->s_timer, jiffies +
- usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
- 1000UL));
+ mod_timer(&qp->s_timer, jiffies + qp->timeout_jiffies);
if (qp->s_flags & QIB_S_WAIT_ACK) {
qp->s_flags &= ~QIB_S_WAIT_ACK;
qib_schedule_send(qp);
@@ -1732,7 +1729,7 @@ static int qib_rc_rcv_error(struct qib_other_headers *ohdr,
* same request.
*/
offset = ((psn - e->psn) & QIB_PSN_MASK) *
- ib_mtu_enum_to_int(qp->path_mtu);
+ qp->pmtu;
len = be32_to_cpu(reth->length);
if (unlikely(offset + len != e->rdma_sge.sge_length))
goto unlock_done;
@@ -1876,7 +1873,7 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd, struct qib_ib_header *hdr,
u32 psn;
u32 pad;
struct ib_wc wc;
- u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ u32 pmtu = qp->pmtu;
int diff;
struct ib_reth *reth;
unsigned long flags;
@@ -1892,10 +1889,8 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd, struct qib_ib_header *hdr,
}
opcode = be32_to_cpu(ohdr->bth[0]);
- spin_lock_irqsave(&qp->s_lock, flags);
if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
- goto sunlock;
- spin_unlock_irqrestore(&qp->s_lock, flags);
+ return;
psn = be32_to_cpu(ohdr->bth[2]);
opcode >>= 24;
@@ -1955,8 +1950,6 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd, struct qib_ib_header *hdr,
break;
}
- memset(&wc, 0, sizeof wc);
-
if (qp->state == IB_QPS_RTR && !(qp->r_flags & QIB_R_COMM_EST)) {
qp->r_flags |= QIB_R_COMM_EST;
if (qp->ibqp.event_handler) {
@@ -2009,16 +2002,19 @@ send_middle:
goto rnr_nak;
qp->r_rcv_len = 0;
if (opcode == OP(SEND_ONLY))
- goto send_last;
- /* FALLTHROUGH */
+ goto no_immediate_data;
+ /* FALLTHROUGH for SEND_ONLY_WITH_IMMEDIATE */
case OP(SEND_LAST_WITH_IMMEDIATE):
send_last_imm:
wc.ex.imm_data = ohdr->u.imm_data;
hdrsize += 4;
wc.wc_flags = IB_WC_WITH_IMM;
- /* FALLTHROUGH */
+ goto send_last;
case OP(SEND_LAST):
case OP(RDMA_WRITE_LAST):
+no_immediate_data:
+ wc.wc_flags = 0;
+ wc.ex.imm_data = 0;
send_last:
/* Get the number of bytes the message was padded by. */
pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
@@ -2051,6 +2047,12 @@ send_last:
wc.src_qp = qp->remote_qpn;
wc.slid = qp->remote_ah_attr.dlid;
wc.sl = qp->remote_ah_attr.sl;
+ /* zero fields that are N/A */
+ wc.vendor_err = 0;
+ wc.pkey_index = 0;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ wc.csum_ok = 0;
/* Signal completion event if the solicited bit is set. */
qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
(ohdr->bth[0] &
@@ -2089,7 +2091,7 @@ send_last:
if (opcode == OP(RDMA_WRITE_FIRST))
goto send_middle;
else if (opcode == OP(RDMA_WRITE_ONLY))
- goto send_last;
+ goto no_immediate_data;
ret = qib_get_rwqe(qp, 1);
if (ret < 0)
goto nack_op_err;
diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c
index eb78d9367f06..b4b37e47321a 100644
--- a/drivers/infiniband/hw/qib/qib_ruc.c
+++ b/drivers/infiniband/hw/qib/qib_ruc.c
@@ -260,12 +260,15 @@ static int gid_ok(union ib_gid *gid, __be64 gid_prefix, __be64 id)
/*
*
- * This should be called with the QP s_lock held.
+ * This should be called with the QP r_lock held.
+ *
+ * The s_lock will be acquired around the qib_migrate_qp() call.
*/
int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr,
int has_grh, struct qib_qp *qp, u32 bth0)
{
__be64 guid;
+ unsigned long flags;
if (qp->s_mig_state == IB_MIG_ARMED && (bth0 & IB_BTH_MIG_REQ)) {
if (!has_grh) {
@@ -295,7 +298,9 @@ int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr,
if (be16_to_cpu(hdr->lrh[3]) != qp->alt_ah_attr.dlid ||
ppd_from_ibp(ibp)->port != qp->alt_ah_attr.port_num)
goto err;
+ spin_lock_irqsave(&qp->s_lock, flags);
qib_migrate_qp(qp);
+ spin_unlock_irqrestore(&qp->s_lock, flags);
} else {
if (!has_grh) {
if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
diff --git a/drivers/infiniband/hw/qib/qib_srq.c b/drivers/infiniband/hw/qib/qib_srq.c
index c3ec8efc2ed8..d6235931a1ba 100644
--- a/drivers/infiniband/hw/qib/qib_srq.c
+++ b/drivers/infiniband/hw/qib/qib_srq.c
@@ -107,6 +107,11 @@ struct ib_srq *qib_create_srq(struct ib_pd *ibpd,
u32 sz;
struct ib_srq *ret;
+ if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
+ ret = ERR_PTR(-ENOSYS);
+ goto done;
+ }
+
if (srq_init_attr->attr.max_sge == 0 ||
srq_init_attr->attr.max_sge > ib_qib_max_srq_sges ||
srq_init_attr->attr.max_wr == 0 ||
diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c
index 14d129de4320..78fbd56879d4 100644
--- a/drivers/infiniband/hw/qib/qib_sysfs.c
+++ b/drivers/infiniband/hw/qib/qib_sysfs.c
@@ -515,8 +515,7 @@ static ssize_t show_nfreectxts(struct device *device,
struct qib_devdata *dd = dd_from_dev(dev);
/* Return the number of free user ports (contexts) available. */
- return scnprintf(buf, PAGE_SIZE, "%u\n", dd->cfgctxts -
- dd->first_user_ctxt - (u32)qib_stats.sps_ctxts);
+ return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts);
}
static ssize_t show_serial(struct device *device,
diff --git a/drivers/infiniband/hw/qib/qib_uc.c b/drivers/infiniband/hw/qib/qib_uc.c
index 32ccf3c824ca..847e7afdfd94 100644
--- a/drivers/infiniband/hw/qib/qib_uc.c
+++ b/drivers/infiniband/hw/qib/qib_uc.c
@@ -51,7 +51,7 @@ int qib_make_uc_req(struct qib_qp *qp)
u32 hwords;
u32 bth0;
u32 len;
- u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ u32 pmtu = qp->pmtu;
int ret = 0;
spin_lock_irqsave(&qp->s_lock, flags);
@@ -243,13 +243,12 @@ void qib_uc_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr,
int has_grh, void *data, u32 tlen, struct qib_qp *qp)
{
struct qib_other_headers *ohdr;
- unsigned long flags;
u32 opcode;
u32 hdrsize;
u32 psn;
u32 pad;
struct ib_wc wc;
- u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ u32 pmtu = qp->pmtu;
struct ib_reth *reth;
int ret;
@@ -263,14 +262,11 @@ void qib_uc_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr,
}
opcode = be32_to_cpu(ohdr->bth[0]);
- spin_lock_irqsave(&qp->s_lock, flags);
if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
- goto sunlock;
- spin_unlock_irqrestore(&qp->s_lock, flags);
+ return;
psn = be32_to_cpu(ohdr->bth[2]);
opcode >>= 24;
- memset(&wc, 0, sizeof wc);
/* Compare the PSN verses the expected PSN. */
if (unlikely(qib_cmp24(psn, qp->r_psn) != 0)) {
@@ -370,7 +366,7 @@ send_first:
}
qp->r_rcv_len = 0;
if (opcode == OP(SEND_ONLY))
- goto send_last;
+ goto no_immediate_data;
else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE))
goto send_last_imm;
/* FALLTHROUGH */
@@ -389,8 +385,11 @@ send_last_imm:
wc.ex.imm_data = ohdr->u.imm_data;
hdrsize += 4;
wc.wc_flags = IB_WC_WITH_IMM;
- /* FALLTHROUGH */
+ goto send_last;
case OP(SEND_LAST):
+no_immediate_data:
+ wc.ex.imm_data = 0;
+ wc.wc_flags = 0;
send_last:
/* Get the number of bytes the message was padded by. */
pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
@@ -418,6 +417,12 @@ last_imm:
wc.src_qp = qp->remote_qpn;
wc.slid = qp->remote_ah_attr.dlid;
wc.sl = qp->remote_ah_attr.sl;
+ /* zero fields that are N/A */
+ wc.vendor_err = 0;
+ wc.pkey_index = 0;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ wc.csum_ok = 0;
/* Signal completion event if the solicited bit is set. */
qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
(ohdr->bth[0] &
@@ -546,6 +551,4 @@ op_err:
qib_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
return;
-sunlock:
- spin_unlock_irqrestore(&qp->s_lock, flags);
}
diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c
index 7689e49c13c9..2bc1d2b96298 100644
--- a/drivers/infiniband/hw/qib/qib_user_pages.c
+++ b/drivers/infiniband/hw/qib/qib_user_pages.c
@@ -74,7 +74,7 @@ static int __qib_get_user_pages(unsigned long start_page, size_t num_pages,
goto bail_release;
}
- current->mm->locked_vm += num_pages;
+ current->mm->pinned_vm += num_pages;
ret = 0;
goto bail;
@@ -151,7 +151,7 @@ void qib_release_user_pages(struct page **p, size_t num_pages)
__qib_release_user_pages(p, num_pages, 1);
if (current->mm) {
- current->mm->locked_vm -= num_pages;
+ current->mm->pinned_vm -= num_pages;
up_write(&current->mm->mmap_sem);
}
}
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c
index 9fab40488850..9627cb737125 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.c
+++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -38,11 +38,12 @@
#include <linux/utsname.h>
#include <linux/rculist.h>
#include <linux/mm.h>
+#include <linux/random.h>
#include "qib.h"
#include "qib_common.h"
-static unsigned int ib_qib_qp_table_size = 251;
+static unsigned int ib_qib_qp_table_size = 256;
module_param_named(qp_table_size, ib_qib_qp_table_size, uint, S_IRUGO);
MODULE_PARM_DESC(qp_table_size, "QP table size");
@@ -659,17 +660,25 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen)
if (atomic_dec_return(&mcast->refcount) <= 1)
wake_up(&mcast->wait);
} else {
- qp = qib_lookup_qpn(ibp, qp_num);
- if (!qp)
- goto drop;
+ if (rcd->lookaside_qp) {
+ if (rcd->lookaside_qpn != qp_num) {
+ if (atomic_dec_and_test(
+ &rcd->lookaside_qp->refcount))
+ wake_up(
+ &rcd->lookaside_qp->wait);
+ rcd->lookaside_qp = NULL;
+ }
+ }
+ if (!rcd->lookaside_qp) {
+ qp = qib_lookup_qpn(ibp, qp_num);
+ if (!qp)
+ goto drop;
+ rcd->lookaside_qp = qp;
+ rcd->lookaside_qpn = qp_num;
+ } else
+ qp = rcd->lookaside_qp;
ibp->n_unicast_rcv++;
qib_qp_rcv(rcd, hdr, lnh == QIB_LRH_GRH, data, tlen, qp);
- /*
- * Notify qib_destroy_qp() if it is waiting
- * for us to finish.
- */
- if (atomic_dec_and_test(&qp->refcount))
- wake_up(&qp->wait);
}
return;
@@ -1974,6 +1983,8 @@ static void init_ibport(struct qib_pportdata *ppd)
ibp->z_excessive_buffer_overrun_errors =
cntrs.excessive_buffer_overrun_errors;
ibp->z_vl15_dropped = cntrs.vl15_dropped;
+ RCU_INIT_POINTER(ibp->qp0, NULL);
+ RCU_INIT_POINTER(ibp->qp1, NULL);
}
/**
@@ -1990,12 +2001,15 @@ int qib_register_ib_device(struct qib_devdata *dd)
int ret;
dev->qp_table_size = ib_qib_qp_table_size;
- dev->qp_table = kzalloc(dev->qp_table_size * sizeof *dev->qp_table,
+ get_random_bytes(&dev->qp_rnd, sizeof(dev->qp_rnd));
+ dev->qp_table = kmalloc(dev->qp_table_size * sizeof *dev->qp_table,
GFP_KERNEL);
if (!dev->qp_table) {
ret = -ENOMEM;
goto err_qpt;
}
+ for (i = 0; i < dev->qp_table_size; i++)
+ RCU_INIT_POINTER(dev->qp_table[i], NULL);
for (i = 0; i < dd->num_pports; i++)
init_ibport(ppd + i);
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h
index 95e5b47223b3..0c19ef0c4123 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.h
+++ b/drivers/infiniband/hw/qib/qib_verbs.h
@@ -485,6 +485,7 @@ struct qib_qp {
u8 alt_timeout; /* Alternate path timeout for this QP */
u8 port_num;
enum ib_mtu path_mtu;
+ u32 pmtu; /* decoded from path_mtu */
u32 remote_qpn;
u32 qkey; /* QKEY for this QP (for UD or RD) */
u32 s_size; /* send work queue size */
@@ -495,6 +496,7 @@ struct qib_qp {
u32 s_last; /* last completed entry */
u32 s_ssn; /* SSN of tail entry */
u32 s_lsn; /* limit sequence number (credit) */
+ unsigned long timeout_jiffies; /* computed from timeout */
struct qib_swqe *s_wq; /* send work queue */
struct qib_swqe *s_wqe;
struct qib_rq r_rq; /* receive work queue */
@@ -723,7 +725,8 @@ struct qib_ibdev {
dma_addr_t pio_hdrs_phys;
/* list of QPs waiting for RNR timer */
spinlock_t pending_lock; /* protect wait lists, PMA counters, etc. */
- unsigned qp_table_size; /* size of the hash table */
+ u32 qp_table_size; /* size of the hash table */
+ u32 qp_rnd; /* random bytes for hash */
spinlock_t qpt_lock;
u32 n_piowait;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 39913a065f99..231c2f2f52f8 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -84,7 +84,7 @@ static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv, int frags,
ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
for (i = 0; i < frags; ++i)
- ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
+ ib_dma_unmap_page(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
}
static int ipoib_cm_post_receive_srq(struct net_device *dev, int id)
@@ -169,7 +169,7 @@ static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev,
goto partial_error;
skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE);
- mapping[i + 1] = ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[i].page,
+ mapping[i + 1] = ib_dma_map_page(priv->ca, page,
0, PAGE_SIZE, DMA_FROM_DEVICE);
if (unlikely(ib_dma_mapping_error(priv->ca, mapping[i + 1])))
goto partial_error;
@@ -183,7 +183,7 @@ partial_error:
ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
for (; i > 0; --i)
- ib_dma_unmap_single(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
+ ib_dma_unmap_page(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
return NULL;
@@ -537,12 +537,13 @@ static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
if (length == 0) {
/* don't need this page */
- skb_fill_page_desc(toskb, i, frag->page, 0, PAGE_SIZE);
+ skb_fill_page_desc(toskb, i, skb_frag_page(frag),
+ 0, PAGE_SIZE);
--skb_shinfo(skb)->nr_frags;
} else {
size = min(length, (unsigned) PAGE_SIZE);
- frag->size = size;
+ skb_frag_size_set(frag, size);
skb->data_len += size;
skb->truesize += size;
skb->len += size;
@@ -1496,6 +1497,7 @@ static void ipoib_cm_create_srq(struct net_device *dev, int max_sge)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_srq_init_attr srq_init_attr = {
+ .srq_type = IB_SRQT_BASIC,
.attr = {
.max_wr = ipoib_recvq_size,
.max_sge = max_sge
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 86eae229dc49..0e2fe4631ba8 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -212,16 +212,15 @@ static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
gid_buf, path.pathrec.dlid ? "yes" : "no");
if (path.pathrec.dlid) {
- rate = ib_rate_to_mult(path.pathrec.rate) * 25;
+ rate = ib_rate_to_mbps(path.pathrec.rate);
seq_printf(file,
" DLID: 0x%04x\n"
" SL: %12d\n"
- " rate: %*d%s Gb/sec\n",
+ " rate: %8d.%d Gb/sec\n",
be16_to_cpu(path.pathrec.dlid),
path.pathrec.sl,
- 10 - ((rate % 10) ? 2 : 0),
- rate / 10, rate % 10 ? ".5" : "");
+ rate / 1000, rate % 1000);
}
seq_putc(file, '\n');
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 81ae61d68a22..2b060f45bec3 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -117,7 +117,7 @@ static void ipoib_ud_skb_put_frags(struct ipoib_dev_priv *priv,
size = length - IPOIB_UD_HEAD_SIZE;
- frag->size = size;
+ skb_frag_size_set(frag, size);
skb->data_len += size;
skb->truesize += size;
} else
@@ -182,7 +182,7 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
goto partial_error;
skb_fill_page_desc(skb, 0, page, 0, PAGE_SIZE);
mapping[1] =
- ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[0].page,
+ ib_dma_map_page(priv->ca, page,
0, PAGE_SIZE, DMA_FROM_DEVICE);
if (unlikely(ib_dma_mapping_error(priv->ca, mapping[1])))
goto partial_error;
@@ -322,9 +322,10 @@ static int ipoib_dma_map_tx(struct ib_device *ca,
off = 0;
for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- mapping[i + off] = ib_dma_map_page(ca, frag->page,
- frag->page_offset, frag->size,
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ mapping[i + off] = ib_dma_map_page(ca,
+ skb_frag_page(frag),
+ frag->page_offset, skb_frag_size(frag),
DMA_TO_DEVICE);
if (unlikely(ib_dma_mapping_error(ca, mapping[i + off])))
goto partial_error;
@@ -333,8 +334,9 @@ static int ipoib_dma_map_tx(struct ib_device *ca,
partial_error:
for (; i > 0; --i) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
- ib_dma_unmap_page(ca, mapping[i - !off], frag->size, DMA_TO_DEVICE);
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
+
+ ib_dma_unmap_page(ca, mapping[i - !off], skb_frag_size(frag), DMA_TO_DEVICE);
}
if (off)
@@ -358,8 +360,9 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca,
off = 0;
for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- ib_dma_unmap_page(ca, mapping[i + off], frag->size,
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ ib_dma_unmap_page(ca, mapping[i + off], skb_frag_size(frag),
DMA_TO_DEVICE);
}
}
@@ -509,7 +512,7 @@ static inline int post_send(struct ipoib_dev_priv *priv,
for (i = 0; i < nr_frags; ++i) {
priv->tx_sge[i + off].addr = mapping[i + off];
- priv->tx_sge[i + off].length = frags[i].size;
+ priv->tx_sge[i + off].length = skb_frag_size(&frags[i]);
}
priv->tx_wr.num_sge = nr_frags + off;
priv->tx_wr.wr_id = wr_id;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index fe89c4660d55..7567b6000230 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -998,7 +998,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
.ndo_fix_features = ipoib_fix_features,
.ndo_start_xmit = ipoib_start_xmit,
.ndo_tx_timeout = ipoib_timeout,
- .ndo_set_multicast_list = ipoib_set_mcast_list,
+ .ndo_set_rx_mode = ipoib_set_mcast_list,
.ndo_neigh_setup = ipoib_neigh_setup_dev,
};
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 9c61b9c2c597..84e8c293a715 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -632,6 +632,59 @@ iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep)
iser_conn_terminate(ib_conn);
}
+static mode_t iser_attr_is_visible(int param_type, int param)
+{
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_NETDEV_NAME:
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_HDRDGST_EN:
+ case ISCSI_PARAM_DATADGST_EN:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_EXP_STATSN:
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_PING_TMO:
+ case ISCSI_PARAM_RECV_TMO:
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_IMM_DATA_EN:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_USERNAME:
+ case ISCSI_PARAM_PASSWORD:
+ case ISCSI_PARAM_USERNAME_IN:
+ case ISCSI_PARAM_PASSWORD_IN:
+ case ISCSI_PARAM_FAST_ABORT:
+ case ISCSI_PARAM_ABORT_TMO:
+ case ISCSI_PARAM_LU_RESET_TMO:
+ case ISCSI_PARAM_TGT_RESET_TMO:
+ case ISCSI_PARAM_IFACE_NAME:
+ case ISCSI_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
static struct scsi_host_template iscsi_iser_sht = {
.module = THIS_MODULE,
.name = "iSCSI Initiator over iSER, v." DRV_VER,
@@ -653,32 +706,6 @@ static struct iscsi_transport iscsi_iser_transport = {
.owner = THIS_MODULE,
.name = "iser",
.caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T,
- .param_mask = ISCSI_MAX_RECV_DLENGTH |
- ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN |
- ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN |
- ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN |
- ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST |
- ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN |
- ISCSI_CONN_PORT |
- ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN |
- ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS |
- ISCSI_HOST_NETDEV_NAME |
- ISCSI_HOST_INITIATOR_NAME,
/* session management */
.create_session = iscsi_iser_session_create,
.destroy_session = iscsi_iser_session_destroy,
@@ -686,6 +713,7 @@ static struct iscsi_transport iscsi_iser_transport = {
.create_conn = iscsi_iser_conn_create,
.bind_conn = iscsi_iser_conn_bind,
.destroy_conn = iscsi_iser_conn_destroy,
+ .attr_is_visible = iser_attr_is_visible,
.set_param = iscsi_iser_set_param,
.get_conn_param = iscsi_conn_get_param,
.get_ep_param = iscsi_iser_get_ep_param,
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 23e82e46656d..001b147c7f95 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -3,7 +3,7 @@
#
menu "Input device support"
- depends on !S390
+ depends on !S390 && !UML
config INPUT
tristate "Generic input layer (needed for keyboard, mouse, ...)" if EXPERT
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index 3367f760d75a..480eb9d9876a 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -309,9 +309,10 @@ EXPORT_SYMBOL_GPL(input_ff_event);
* Once ff device is created you need to setup its upload, erase,
* playback and other handlers before registering input device
*/
-int input_ff_create(struct input_dev *dev, int max_effects)
+int input_ff_create(struct input_dev *dev, unsigned int max_effects)
{
struct ff_device *ff;
+ size_t ff_dev_size;
int i;
if (!max_effects) {
@@ -319,8 +320,12 @@ int input_ff_create(struct input_dev *dev, int max_effects)
return -EINVAL;
}
- ff = kzalloc(sizeof(struct ff_device) +
- max_effects * sizeof(struct file *), GFP_KERNEL);
+ ff_dev_size = sizeof(struct ff_device) +
+ max_effects * sizeof(struct file *);
+ if (ff_dev_size < max_effects) /* overflow */
+ return -EINVAL;
+
+ ff = kzalloc(ff_dev_size, GFP_KERNEL);
if (!ff)
return -ENOMEM;
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index c48c81f0308d..9150ee78e00a 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -117,6 +117,7 @@ void input_mt_report_finger_count(struct input_dev *dev, int count)
input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4);
+ input_event(dev, EV_KEY, BTN_TOOL_QUINTTAP, count == 5);
}
EXPORT_SYMBOL(input_mt_report_finger_count);
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
index b1aabde87523..b253973881b8 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -49,8 +49,10 @@ static int input_open_polled_device(struct input_dev *input)
dev->open(dev);
/* Only start polling if polling is enabled */
- if (dev->poll_interval > 0)
- queue_delayed_work(system_freezable_wq, &dev->work, 0);
+ if (dev->poll_interval > 0) {
+ dev->poll(dev);
+ input_polldev_queue_work(dev);
+ }
return 0;
}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index b4dee9d5a055..615c21f2a553 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -33,10 +33,10 @@ config KEYBOARD_ADP5588
module will be called adp5588-keys.
config KEYBOARD_ADP5589
- tristate "ADP5589 I2C QWERTY Keypad and IO Expander"
+ tristate "ADP5585/ADP5589 I2C QWERTY Keypad and IO Expander"
depends on I2C
help
- Say Y here if you want to use a ADP5589 attached to your
+ Say Y here if you want to use a ADP5585/ADP5589 attached to your
system I2C bus.
To compile this driver as a module, choose M here: the
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index e34eeb8ae371..4a7f534cf64b 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -550,7 +550,7 @@ static int __devinit adp5588_probe(struct i2c_client *client,
}
error = request_irq(client->irq, adp5588_irq,
- IRQF_TRIGGER_FALLING | IRQF_DISABLED,
+ IRQF_TRIGGER_FALLING,
client->dev.driver->name, kpad);
if (error) {
dev_err(&client->dev, "irq %d busy?\n", client->irq);
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
index c7708263051b..02b5d53031bf 100644
--- a/drivers/input/keyboard/adp5589-keys.c
+++ b/drivers/input/keyboard/adp5589-keys.c
@@ -1,5 +1,5 @@
/*
- * Description: keypad driver for ADP5589
+ * Description: keypad driver for ADP5589, ADP5585
* I2C QWERTY Keypad and IO Expander
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@@ -22,35 +22,165 @@
#include <linux/input/adp5589.h>
+/* ADP5589/ADP5585 Common Registers */
+#define ADP5589_5_ID 0x00
+#define ADP5589_5_INT_STATUS 0x01
+#define ADP5589_5_STATUS 0x02
+#define ADP5589_5_FIFO_1 0x03
+#define ADP5589_5_FIFO_2 0x04
+#define ADP5589_5_FIFO_3 0x05
+#define ADP5589_5_FIFO_4 0x06
+#define ADP5589_5_FIFO_5 0x07
+#define ADP5589_5_FIFO_6 0x08
+#define ADP5589_5_FIFO_7 0x09
+#define ADP5589_5_FIFO_8 0x0A
+#define ADP5589_5_FIFO_9 0x0B
+#define ADP5589_5_FIFO_10 0x0C
+#define ADP5589_5_FIFO_11 0x0D
+#define ADP5589_5_FIFO_12 0x0E
+#define ADP5589_5_FIFO_13 0x0F
+#define ADP5589_5_FIFO_14 0x10
+#define ADP5589_5_FIFO_15 0x11
+#define ADP5589_5_FIFO_16 0x12
+#define ADP5589_5_GPI_INT_STAT_A 0x13
+#define ADP5589_5_GPI_INT_STAT_B 0x14
+
+/* ADP5589 Registers */
+#define ADP5589_GPI_INT_STAT_C 0x15
+#define ADP5589_GPI_STATUS_A 0x16
+#define ADP5589_GPI_STATUS_B 0x17
+#define ADP5589_GPI_STATUS_C 0x18
+#define ADP5589_RPULL_CONFIG_A 0x19
+#define ADP5589_RPULL_CONFIG_B 0x1A
+#define ADP5589_RPULL_CONFIG_C 0x1B
+#define ADP5589_RPULL_CONFIG_D 0x1C
+#define ADP5589_RPULL_CONFIG_E 0x1D
+#define ADP5589_GPI_INT_LEVEL_A 0x1E
+#define ADP5589_GPI_INT_LEVEL_B 0x1F
+#define ADP5589_GPI_INT_LEVEL_C 0x20
+#define ADP5589_GPI_EVENT_EN_A 0x21
+#define ADP5589_GPI_EVENT_EN_B 0x22
+#define ADP5589_GPI_EVENT_EN_C 0x23
+#define ADP5589_GPI_INTERRUPT_EN_A 0x24
+#define ADP5589_GPI_INTERRUPT_EN_B 0x25
+#define ADP5589_GPI_INTERRUPT_EN_C 0x26
+#define ADP5589_DEBOUNCE_DIS_A 0x27
+#define ADP5589_DEBOUNCE_DIS_B 0x28
+#define ADP5589_DEBOUNCE_DIS_C 0x29
+#define ADP5589_GPO_DATA_OUT_A 0x2A
+#define ADP5589_GPO_DATA_OUT_B 0x2B
+#define ADP5589_GPO_DATA_OUT_C 0x2C
+#define ADP5589_GPO_OUT_MODE_A 0x2D
+#define ADP5589_GPO_OUT_MODE_B 0x2E
+#define ADP5589_GPO_OUT_MODE_C 0x2F
+#define ADP5589_GPIO_DIRECTION_A 0x30
+#define ADP5589_GPIO_DIRECTION_B 0x31
+#define ADP5589_GPIO_DIRECTION_C 0x32
+#define ADP5589_UNLOCK1 0x33
+#define ADP5589_UNLOCK2 0x34
+#define ADP5589_EXT_LOCK_EVENT 0x35
+#define ADP5589_UNLOCK_TIMERS 0x36
+#define ADP5589_LOCK_CFG 0x37
+#define ADP5589_RESET1_EVENT_A 0x38
+#define ADP5589_RESET1_EVENT_B 0x39
+#define ADP5589_RESET1_EVENT_C 0x3A
+#define ADP5589_RESET2_EVENT_A 0x3B
+#define ADP5589_RESET2_EVENT_B 0x3C
+#define ADP5589_RESET_CFG 0x3D
+#define ADP5589_PWM_OFFT_LOW 0x3E
+#define ADP5589_PWM_OFFT_HIGH 0x3F
+#define ADP5589_PWM_ONT_LOW 0x40
+#define ADP5589_PWM_ONT_HIGH 0x41
+#define ADP5589_PWM_CFG 0x42
+#define ADP5589_CLOCK_DIV_CFG 0x43
+#define ADP5589_LOGIC_1_CFG 0x44
+#define ADP5589_LOGIC_2_CFG 0x45
+#define ADP5589_LOGIC_FF_CFG 0x46
+#define ADP5589_LOGIC_INT_EVENT_EN 0x47
+#define ADP5589_POLL_PTIME_CFG 0x48
+#define ADP5589_PIN_CONFIG_A 0x49
+#define ADP5589_PIN_CONFIG_B 0x4A
+#define ADP5589_PIN_CONFIG_C 0x4B
+#define ADP5589_PIN_CONFIG_D 0x4C
+#define ADP5589_GENERAL_CFG 0x4D
+#define ADP5589_INT_EN 0x4E
+
+/* ADP5585 Registers */
+#define ADP5585_GPI_STATUS_A 0x15
+#define ADP5585_GPI_STATUS_B 0x16
+#define ADP5585_RPULL_CONFIG_A 0x17
+#define ADP5585_RPULL_CONFIG_B 0x18
+#define ADP5585_RPULL_CONFIG_C 0x19
+#define ADP5585_RPULL_CONFIG_D 0x1A
+#define ADP5585_GPI_INT_LEVEL_A 0x1B
+#define ADP5585_GPI_INT_LEVEL_B 0x1C
+#define ADP5585_GPI_EVENT_EN_A 0x1D
+#define ADP5585_GPI_EVENT_EN_B 0x1E
+#define ADP5585_GPI_INTERRUPT_EN_A 0x1F
+#define ADP5585_GPI_INTERRUPT_EN_B 0x20
+#define ADP5585_DEBOUNCE_DIS_A 0x21
+#define ADP5585_DEBOUNCE_DIS_B 0x22
+#define ADP5585_GPO_DATA_OUT_A 0x23
+#define ADP5585_GPO_DATA_OUT_B 0x24
+#define ADP5585_GPO_OUT_MODE_A 0x25
+#define ADP5585_GPO_OUT_MODE_B 0x26
+#define ADP5585_GPIO_DIRECTION_A 0x27
+#define ADP5585_GPIO_DIRECTION_B 0x28
+#define ADP5585_RESET1_EVENT_A 0x29
+#define ADP5585_RESET1_EVENT_B 0x2A
+#define ADP5585_RESET1_EVENT_C 0x2B
+#define ADP5585_RESET2_EVENT_A 0x2C
+#define ADP5585_RESET2_EVENT_B 0x2D
+#define ADP5585_RESET_CFG 0x2E
+#define ADP5585_PWM_OFFT_LOW 0x2F
+#define ADP5585_PWM_OFFT_HIGH 0x30
+#define ADP5585_PWM_ONT_LOW 0x31
+#define ADP5585_PWM_ONT_HIGH 0x32
+#define ADP5585_PWM_CFG 0x33
+#define ADP5585_LOGIC_CFG 0x34
+#define ADP5585_LOGIC_FF_CFG 0x35
+#define ADP5585_LOGIC_INT_EVENT_EN 0x36
+#define ADP5585_POLL_PTIME_CFG 0x37
+#define ADP5585_PIN_CONFIG_A 0x38
+#define ADP5585_PIN_CONFIG_B 0x39
+#define ADP5585_PIN_CONFIG_D 0x3A
+#define ADP5585_GENERAL_CFG 0x3B
+#define ADP5585_INT_EN 0x3C
+
+/* ID Register */
+#define ADP5589_5_DEVICE_ID_MASK 0xF
+#define ADP5589_5_MAN_ID_MASK 0xF
+#define ADP5589_5_MAN_ID_SHIFT 4
+#define ADP5589_5_MAN_ID 0x02
+
/* GENERAL_CFG Register */
#define OSC_EN (1 << 7)
#define CORE_CLK(x) (((x) & 0x3) << 5)
-#define LCK_TRK_LOGIC (1 << 4)
-#define LCK_TRK_GPI (1 << 3)
+#define LCK_TRK_LOGIC (1 << 4) /* ADP5589 only */
+#define LCK_TRK_GPI (1 << 3) /* ADP5589 only */
#define INT_CFG (1 << 1)
#define RST_CFG (1 << 0)
/* INT_EN Register */
-#define LOGIC2_IEN (1 << 5)
+#define LOGIC2_IEN (1 << 5) /* ADP5589 only */
#define LOGIC1_IEN (1 << 4)
-#define LOCK_IEN (1 << 3)
+#define LOCK_IEN (1 << 3) /* ADP5589 only */
#define OVRFLOW_IEN (1 << 2)
#define GPI_IEN (1 << 1)
#define EVENT_IEN (1 << 0)
/* Interrupt Status Register */
-#define LOGIC2_INT (1 << 5)
+#define LOGIC2_INT (1 << 5) /* ADP5589 only */
#define LOGIC1_INT (1 << 4)
-#define LOCK_INT (1 << 3)
+#define LOCK_INT (1 << 3) /* ADP5589 only */
#define OVRFLOW_INT (1 << 2)
#define GPI_INT (1 << 1)
#define EVENT_INT (1 << 0)
/* STATUS Register */
-
-#define LOGIC2_STAT (1 << 7)
+#define LOGIC2_STAT (1 << 7) /* ADP5589 only */
#define LOGIC1_STAT (1 << 6)
-#define LOCK_STAT (1 << 5)
+#define LOCK_STAT (1 << 5) /* ADP5589 only */
#define KEC 0xF
/* PIN_CONFIG_D Register */
@@ -61,27 +191,54 @@
#define LOCK_EN (1 << 0)
#define PTIME_MASK 0x3
-#define LTIME_MASK 0x3
+#define LTIME_MASK 0x3 /* ADP5589 only */
/* Key Event Register xy */
#define KEY_EV_PRESSED (1 << 7)
#define KEY_EV_MASK (0x7F)
#define KEYP_MAX_EVENT 16
+#define ADP5589_MAXGPIO 19
+#define ADP5585_MAXGPIO 11 /* 10 on the ADP5585-01, 11 on ADP5585-02 */
-#define MAXGPIO 19
-#define ADP_BANK(offs) ((offs) >> 3)
-#define ADP_BIT(offs) (1u << ((offs) & 0x7))
+enum {
+ ADP5589,
+ ADP5585_01,
+ ADP5585_02
+};
+
+struct adp_constants {
+ u8 maxgpio;
+ u8 keymapsize;
+ u8 gpi_pin_row_base;
+ u8 gpi_pin_row_end;
+ u8 gpi_pin_col_base;
+ u8 gpi_pin_base;
+ u8 gpi_pin_end;
+ u8 gpimapsize_max;
+ u8 max_row_num;
+ u8 max_col_num;
+ u8 row_mask;
+ u8 col_mask;
+ u8 col_shift;
+ u8 c4_extend_cfg;
+ u8 (*bank) (u8 offset);
+ u8 (*bit) (u8 offset);
+ u8 (*reg) (u8 reg);
+};
struct adp5589_kpad {
struct i2c_client *client;
struct input_dev *input;
+ const struct adp_constants *var;
unsigned short keycode[ADP5589_KEYMAPSIZE];
const struct adp5589_gpi_map *gpimap;
unsigned short gpimapsize;
unsigned extend_cfg;
+ bool is_adp5585;
+ bool adp5585_support_row5;
#ifdef CONFIG_GPIOLIB
- unsigned char gpiomap[MAXGPIO];
+ unsigned char gpiomap[ADP5589_MAXGPIO];
bool export_gpio;
struct gpio_chip gc;
struct mutex gpio_lock; /* Protect cached dir, dat_out */
@@ -90,6 +247,129 @@ struct adp5589_kpad {
#endif
};
+/*
+ * ADP5589 / ADP5585 derivative / variant handling
+ */
+
+
+/* ADP5589 */
+
+static unsigned char adp5589_bank(unsigned char offset)
+{
+ return offset >> 3;
+}
+
+static unsigned char adp5589_bit(unsigned char offset)
+{
+ return 1u << (offset & 0x7);
+}
+
+static unsigned char adp5589_reg(unsigned char reg)
+{
+ return reg;
+}
+
+static const struct adp_constants const_adp5589 = {
+ .maxgpio = ADP5589_MAXGPIO,
+ .keymapsize = ADP5589_KEYMAPSIZE,
+ .gpi_pin_row_base = ADP5589_GPI_PIN_ROW_BASE,
+ .gpi_pin_row_end = ADP5589_GPI_PIN_ROW_END,
+ .gpi_pin_col_base = ADP5589_GPI_PIN_COL_BASE,
+ .gpi_pin_base = ADP5589_GPI_PIN_BASE,
+ .gpi_pin_end = ADP5589_GPI_PIN_END,
+ .gpimapsize_max = ADP5589_GPIMAPSIZE_MAX,
+ .c4_extend_cfg = 12,
+ .max_row_num = ADP5589_MAX_ROW_NUM,
+ .max_col_num = ADP5589_MAX_COL_NUM,
+ .row_mask = ADP5589_ROW_MASK,
+ .col_mask = ADP5589_COL_MASK,
+ .col_shift = ADP5589_COL_SHIFT,
+ .bank = adp5589_bank,
+ .bit = adp5589_bit,
+ .reg = adp5589_reg,
+};
+
+/* ADP5585 */
+
+static unsigned char adp5585_bank(unsigned char offset)
+{
+ return offset > ADP5585_MAX_ROW_NUM;
+}
+
+static unsigned char adp5585_bit(unsigned char offset)
+{
+ return (offset > ADP5585_MAX_ROW_NUM) ?
+ 1u << (offset - ADP5585_COL_SHIFT) : 1u << offset;
+}
+
+static const unsigned char adp5585_reg_lut[] = {
+ [ADP5589_GPI_STATUS_A] = ADP5585_GPI_STATUS_A,
+ [ADP5589_GPI_STATUS_B] = ADP5585_GPI_STATUS_B,
+ [ADP5589_RPULL_CONFIG_A] = ADP5585_RPULL_CONFIG_A,
+ [ADP5589_RPULL_CONFIG_B] = ADP5585_RPULL_CONFIG_B,
+ [ADP5589_RPULL_CONFIG_C] = ADP5585_RPULL_CONFIG_C,
+ [ADP5589_RPULL_CONFIG_D] = ADP5585_RPULL_CONFIG_D,
+ [ADP5589_GPI_INT_LEVEL_A] = ADP5585_GPI_INT_LEVEL_A,
+ [ADP5589_GPI_INT_LEVEL_B] = ADP5585_GPI_INT_LEVEL_B,
+ [ADP5589_GPI_EVENT_EN_A] = ADP5585_GPI_EVENT_EN_A,
+ [ADP5589_GPI_EVENT_EN_B] = ADP5585_GPI_EVENT_EN_B,
+ [ADP5589_GPI_INTERRUPT_EN_A] = ADP5585_GPI_INTERRUPT_EN_A,
+ [ADP5589_GPI_INTERRUPT_EN_B] = ADP5585_GPI_INTERRUPT_EN_B,
+ [ADP5589_DEBOUNCE_DIS_A] = ADP5585_DEBOUNCE_DIS_A,
+ [ADP5589_DEBOUNCE_DIS_B] = ADP5585_DEBOUNCE_DIS_B,
+ [ADP5589_GPO_DATA_OUT_A] = ADP5585_GPO_DATA_OUT_A,
+ [ADP5589_GPO_DATA_OUT_B] = ADP5585_GPO_DATA_OUT_B,
+ [ADP5589_GPO_OUT_MODE_A] = ADP5585_GPO_OUT_MODE_A,
+ [ADP5589_GPO_OUT_MODE_B] = ADP5585_GPO_OUT_MODE_B,
+ [ADP5589_GPIO_DIRECTION_A] = ADP5585_GPIO_DIRECTION_A,
+ [ADP5589_GPIO_DIRECTION_B] = ADP5585_GPIO_DIRECTION_B,
+ [ADP5589_RESET1_EVENT_A] = ADP5585_RESET1_EVENT_A,
+ [ADP5589_RESET1_EVENT_B] = ADP5585_RESET1_EVENT_B,
+ [ADP5589_RESET1_EVENT_C] = ADP5585_RESET1_EVENT_C,
+ [ADP5589_RESET2_EVENT_A] = ADP5585_RESET2_EVENT_A,
+ [ADP5589_RESET2_EVENT_B] = ADP5585_RESET2_EVENT_B,
+ [ADP5589_RESET_CFG] = ADP5585_RESET_CFG,
+ [ADP5589_PWM_OFFT_LOW] = ADP5585_PWM_OFFT_LOW,
+ [ADP5589_PWM_OFFT_HIGH] = ADP5585_PWM_OFFT_HIGH,
+ [ADP5589_PWM_ONT_LOW] = ADP5585_PWM_ONT_LOW,
+ [ADP5589_PWM_ONT_HIGH] = ADP5585_PWM_ONT_HIGH,
+ [ADP5589_PWM_CFG] = ADP5585_PWM_CFG,
+ [ADP5589_LOGIC_1_CFG] = ADP5585_LOGIC_CFG,
+ [ADP5589_LOGIC_FF_CFG] = ADP5585_LOGIC_FF_CFG,
+ [ADP5589_LOGIC_INT_EVENT_EN] = ADP5585_LOGIC_INT_EVENT_EN,
+ [ADP5589_POLL_PTIME_CFG] = ADP5585_POLL_PTIME_CFG,
+ [ADP5589_PIN_CONFIG_A] = ADP5585_PIN_CONFIG_A,
+ [ADP5589_PIN_CONFIG_B] = ADP5585_PIN_CONFIG_B,
+ [ADP5589_PIN_CONFIG_D] = ADP5585_PIN_CONFIG_D,
+ [ADP5589_GENERAL_CFG] = ADP5585_GENERAL_CFG,
+ [ADP5589_INT_EN] = ADP5585_INT_EN,
+};
+
+static unsigned char adp5585_reg(unsigned char reg)
+{
+ return adp5585_reg_lut[reg];
+}
+
+static const struct adp_constants const_adp5585 = {
+ .maxgpio = ADP5585_MAXGPIO,
+ .keymapsize = ADP5585_KEYMAPSIZE,
+ .gpi_pin_row_base = ADP5585_GPI_PIN_ROW_BASE,
+ .gpi_pin_row_end = ADP5585_GPI_PIN_ROW_END,
+ .gpi_pin_col_base = ADP5585_GPI_PIN_COL_BASE,
+ .gpi_pin_base = ADP5585_GPI_PIN_BASE,
+ .gpi_pin_end = ADP5585_GPI_PIN_END,
+ .gpimapsize_max = ADP5585_GPIMAPSIZE_MAX,
+ .c4_extend_cfg = 10,
+ .max_row_num = ADP5585_MAX_ROW_NUM,
+ .max_col_num = ADP5585_MAX_COL_NUM,
+ .row_mask = ADP5585_ROW_MASK,
+ .col_mask = ADP5585_COL_MASK,
+ .col_shift = ADP5585_COL_SHIFT,
+ .bank = adp5585_bank,
+ .bit = adp5585_bit,
+ .reg = adp5585_reg,
+};
+
static int adp5589_read(struct i2c_client *client, u8 reg)
{
int ret = i2c_smbus_read_byte_data(client, reg);
@@ -109,19 +389,20 @@ static int adp5589_write(struct i2c_client *client, u8 reg, u8 val)
static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off)
{
struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
- unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
- unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+ unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+ unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
- return !!(adp5589_read(kpad->client, ADP5589_GPI_STATUS_A + bank) &
- bit);
+ return !!(adp5589_read(kpad->client,
+ kpad->var->reg(ADP5589_GPI_STATUS_A) + bank) &
+ bit);
}
static void adp5589_gpio_set_value(struct gpio_chip *chip,
unsigned off, int val)
{
struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
- unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
- unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+ unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+ unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
mutex_lock(&kpad->gpio_lock);
@@ -130,8 +411,8 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip,
else
kpad->dat_out[bank] &= ~bit;
- adp5589_write(kpad->client, ADP5589_GPO_DATA_OUT_A + bank,
- kpad->dat_out[bank]);
+ adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A) +
+ bank, kpad->dat_out[bank]);
mutex_unlock(&kpad->gpio_lock);
}
@@ -139,14 +420,15 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip,
static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off)
{
struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
- unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
- unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+ unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+ unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
int ret;
mutex_lock(&kpad->gpio_lock);
kpad->dir[bank] &= ~bit;
- ret = adp5589_write(kpad->client, ADP5589_GPIO_DIRECTION_A + bank,
+ ret = adp5589_write(kpad->client,
+ kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank,
kpad->dir[bank]);
mutex_unlock(&kpad->gpio_lock);
@@ -158,8 +440,8 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip,
unsigned off, int val)
{
struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
- unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
- unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+ unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+ unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
int ret;
mutex_lock(&kpad->gpio_lock);
@@ -171,9 +453,10 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip,
else
kpad->dat_out[bank] &= ~bit;
- ret = adp5589_write(kpad->client, ADP5589_GPO_DATA_OUT_A + bank,
- kpad->dat_out[bank]);
- ret |= adp5589_write(kpad->client, ADP5589_GPIO_DIRECTION_A + bank,
+ ret = adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A)
+ + bank, kpad->dat_out[bank]);
+ ret |= adp5589_write(kpad->client,
+ kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank,
kpad->dir[bank]);
mutex_unlock(&kpad->gpio_lock);
@@ -184,26 +467,29 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip,
static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad,
const struct adp5589_kpad_platform_data *pdata)
{
- bool pin_used[MAXGPIO];
+ bool pin_used[ADP5589_MAXGPIO];
int n_unused = 0;
int i;
memset(pin_used, false, sizeof(pin_used));
- for (i = 0; i < MAXGPIO; i++)
+ for (i = 0; i < kpad->var->maxgpio; i++)
if (pdata->keypad_en_mask & (1 << i))
pin_used[i] = true;
for (i = 0; i < kpad->gpimapsize; i++)
- pin_used[kpad->gpimap[i].pin - ADP5589_GPI_PIN_BASE] = true;
+ pin_used[kpad->gpimap[i].pin - kpad->var->gpi_pin_base] = true;
if (kpad->extend_cfg & R4_EXTEND_CFG)
pin_used[4] = true;
if (kpad->extend_cfg & C4_EXTEND_CFG)
- pin_used[12] = true;
+ pin_used[kpad->var->c4_extend_cfg] = true;
+
+ if (!kpad->adp5585_support_row5)
+ pin_used[5] = true;
- for (i = 0; i < MAXGPIO; i++)
+ for (i = 0; i < kpad->var->maxgpio; i++)
if (!pin_used[i])
kpad->gpiomap[n_unused++] = i;
@@ -246,11 +532,11 @@ static int __devinit adp5589_gpio_add(struct adp5589_kpad *kpad)
return error;
}
- for (i = 0; i <= ADP_BANK(MAXGPIO); i++) {
- kpad->dat_out[i] = adp5589_read(kpad->client,
- ADP5589_GPO_DATA_OUT_A + i);
- kpad->dir[i] = adp5589_read(kpad->client,
- ADP5589_GPIO_DIRECTION_A + i);
+ for (i = 0; i <= kpad->var->bank(kpad->var->maxgpio); i++) {
+ kpad->dat_out[i] = adp5589_read(kpad->client, kpad->var->reg(
+ ADP5589_GPO_DATA_OUT_A) + i);
+ kpad->dir[i] = adp5589_read(kpad->client, kpad->var->reg(
+ ADP5589_GPIO_DIRECTION_A) + i);
}
if (gpio_data->setup) {
@@ -317,11 +603,11 @@ static void adp5589_report_events(struct adp5589_kpad *kpad, int ev_cnt)
int i;
for (i = 0; i < ev_cnt; i++) {
- int key = adp5589_read(kpad->client, ADP5589_FIFO_1 + i);
+ int key = adp5589_read(kpad->client, ADP5589_5_FIFO_1 + i);
int key_val = key & KEY_EV_MASK;
- if (key_val >= ADP5589_GPI_PIN_BASE &&
- key_val <= ADP5589_GPI_PIN_END) {
+ if (key_val >= kpad->var->gpi_pin_base &&
+ key_val <= kpad->var->gpi_pin_end) {
adp5589_report_switches(kpad, key, key_val);
} else {
input_report_key(kpad->input,
@@ -337,29 +623,30 @@ static irqreturn_t adp5589_irq(int irq, void *handle)
struct i2c_client *client = kpad->client;
int status, ev_cnt;
- status = adp5589_read(client, ADP5589_INT_STATUS);
+ status = adp5589_read(client, ADP5589_5_INT_STATUS);
if (status & OVRFLOW_INT) /* Unlikely and should never happen */
dev_err(&client->dev, "Event Overflow Error\n");
if (status & EVENT_INT) {
- ev_cnt = adp5589_read(client, ADP5589_STATUS) & KEC;
+ ev_cnt = adp5589_read(client, ADP5589_5_STATUS) & KEC;
if (ev_cnt) {
adp5589_report_events(kpad, ev_cnt);
input_sync(kpad->input);
}
}
- adp5589_write(client, ADP5589_INT_STATUS, status); /* Status is W1C */
+ adp5589_write(client, ADP5589_5_INT_STATUS, status); /* Status is W1C */
return IRQ_HANDLED;
}
-static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad, unsigned short key)
+static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad,
+ unsigned short key)
{
int i;
- for (i = 0; i < ADP5589_KEYMAPSIZE; i++)
+ for (i = 0; i < kpad->var->keymapsize; i++)
if (key == kpad->keycode[i])
return (i + 1) | KEY_EV_PRESSED;
@@ -372,19 +659,23 @@ static int __devinit adp5589_setup(struct adp5589_kpad *kpad)
{
struct i2c_client *client = kpad->client;
const struct adp5589_kpad_platform_data *pdata =
- client->dev.platform_data;
- int i, ret;
+ client->dev.platform_data;
+ u8 (*reg) (u8) = kpad->var->reg;
unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;
unsigned char pull_mask = 0;
+ int i, ret;
+
+ ret = adp5589_write(client, reg(ADP5589_PIN_CONFIG_A),
+ pdata->keypad_en_mask & kpad->var->row_mask);
+ ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_B),
+ (pdata->keypad_en_mask >> kpad->var->col_shift) &
+ kpad->var->col_mask);
- ret = adp5589_write(client, ADP5589_PIN_CONFIG_A,
- pdata->keypad_en_mask & 0xFF);
- ret |= adp5589_write(client, ADP5589_PIN_CONFIG_B,
- (pdata->keypad_en_mask >> 8) & 0xFF);
- ret |= adp5589_write(client, ADP5589_PIN_CONFIG_C,
- (pdata->keypad_en_mask >> 16) & 0xFF);
+ if (!kpad->is_adp5585)
+ ret |= adp5589_write(client, ADP5589_PIN_CONFIG_C,
+ (pdata->keypad_en_mask >> 16) & 0xFF);
- if (pdata->en_keylock) {
+ if (!kpad->is_adp5585 && pdata->en_keylock) {
ret |= adp5589_write(client, ADP5589_UNLOCK1,
pdata->unlock_key1);
ret |= adp5589_write(client, ADP5589_UNLOCK2,
@@ -395,96 +686,130 @@ static int __devinit adp5589_setup(struct adp5589_kpad *kpad)
}
for (i = 0; i < KEYP_MAX_EVENT; i++)
- ret |= adp5589_read(client, ADP5589_FIFO_1 + i);
+ ret |= adp5589_read(client, ADP5589_5_FIFO_1 + i);
for (i = 0; i < pdata->gpimapsize; i++) {
unsigned short pin = pdata->gpimap[i].pin;
- if (pin <= ADP5589_GPI_PIN_ROW_END) {
- evt_mode1 |= (1 << (pin - ADP5589_GPI_PIN_ROW_BASE));
+ if (pin <= kpad->var->gpi_pin_row_end) {
+ evt_mode1 |= (1 << (pin - kpad->var->gpi_pin_row_base));
} else {
evt_mode2 |=
- ((1 << (pin - ADP5589_GPI_PIN_COL_BASE)) & 0xFF);
- evt_mode3 |=
- ((1 << (pin - ADP5589_GPI_PIN_COL_BASE)) >> 8);
+ ((1 << (pin - kpad->var->gpi_pin_col_base)) & 0xFF);
+ if (!kpad->is_adp5585)
+ evt_mode3 |= ((1 << (pin -
+ kpad->var->gpi_pin_col_base)) >> 8);
}
}
if (pdata->gpimapsize) {
- ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_A, evt_mode1);
- ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_B, evt_mode2);
- ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_C, evt_mode3);
+ ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_A),
+ evt_mode1);
+ ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_B),
+ evt_mode2);
+ if (!kpad->is_adp5585)
+ ret |= adp5589_write(client,
+ reg(ADP5589_GPI_EVENT_EN_C),
+ evt_mode3);
}
if (pdata->pull_dis_mask & pdata->pullup_en_100k &
- pdata->pullup_en_300k & pdata->pulldown_en_300k)
+ pdata->pullup_en_300k & pdata->pulldown_en_300k)
dev_warn(&client->dev, "Conflicting pull resistor config\n");
- for (i = 0; i < MAXGPIO; i++) {
- unsigned val = 0;
+ for (i = 0; i <= kpad->var->max_row_num; i++) {
+ unsigned val = 0, bit = (1 << i);
+ if (pdata->pullup_en_300k & bit)
+ val = 0;
+ else if (pdata->pulldown_en_300k & bit)
+ val = 1;
+ else if (pdata->pullup_en_100k & bit)
+ val = 2;
+ else if (pdata->pull_dis_mask & bit)
+ val = 3;
+
+ pull_mask |= val << (2 * (i & 0x3));
+
+ if (i == 3 || i == kpad->var->max_row_num) {
+ ret |= adp5589_write(client, reg(ADP5585_RPULL_CONFIG_A)
+ + (i >> 2), pull_mask);
+ pull_mask = 0;
+ }
+ }
- if (pdata->pullup_en_300k & (1 << i))
+ for (i = 0; i <= kpad->var->max_col_num; i++) {
+ unsigned val = 0, bit = 1 << (i + kpad->var->col_shift);
+ if (pdata->pullup_en_300k & bit)
val = 0;
- else if (pdata->pulldown_en_300k & (1 << i))
+ else if (pdata->pulldown_en_300k & bit)
val = 1;
- else if (pdata->pullup_en_100k & (1 << i))
+ else if (pdata->pullup_en_100k & bit)
val = 2;
- else if (pdata->pull_dis_mask & (1 << i))
+ else if (pdata->pull_dis_mask & bit)
val = 3;
pull_mask |= val << (2 * (i & 0x3));
- if ((i & 0x3) == 0x3 || i == MAXGPIO - 1) {
+ if (i == 3 || i == kpad->var->max_col_num) {
ret |= adp5589_write(client,
- ADP5589_RPULL_CONFIG_A + (i >> 2),
- pull_mask);
+ reg(ADP5585_RPULL_CONFIG_C) +
+ (i >> 2), pull_mask);
pull_mask = 0;
}
}
if (pdata->reset1_key_1 && pdata->reset1_key_2 && pdata->reset1_key_3) {
- ret |= adp5589_write(client, ADP5589_RESET1_EVENT_A,
+ ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_A),
adp5589_get_evcode(kpad,
pdata->reset1_key_1));
- ret |= adp5589_write(client, ADP5589_RESET1_EVENT_B,
+ ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_B),
adp5589_get_evcode(kpad,
pdata->reset1_key_2));
- ret |= adp5589_write(client, ADP5589_RESET1_EVENT_C,
+ ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_C),
adp5589_get_evcode(kpad,
pdata->reset1_key_3));
kpad->extend_cfg |= R4_EXTEND_CFG;
}
if (pdata->reset2_key_1 && pdata->reset2_key_2) {
- ret |= adp5589_write(client, ADP5589_RESET2_EVENT_A,
+ ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_A),
adp5589_get_evcode(kpad,
pdata->reset2_key_1));
- ret |= adp5589_write(client, ADP5589_RESET2_EVENT_B,
+ ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_B),
adp5589_get_evcode(kpad,
pdata->reset2_key_2));
kpad->extend_cfg |= C4_EXTEND_CFG;
}
if (kpad->extend_cfg) {
- ret |= adp5589_write(client, ADP5589_RESET_CFG,
+ ret |= adp5589_write(client, reg(ADP5589_RESET_CFG),
pdata->reset_cfg);
- ret |= adp5589_write(client, ADP5589_PIN_CONFIG_D,
+ ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_D),
kpad->extend_cfg);
}
- for (i = 0; i <= ADP_BANK(MAXGPIO); i++)
- ret |= adp5589_write(client, ADP5589_DEBOUNCE_DIS_A + i,
- pdata->debounce_dis_mask >> (i * 8));
+ ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_A),
+ pdata->debounce_dis_mask & kpad->var->row_mask);
- ret |= adp5589_write(client, ADP5589_POLL_PTIME_CFG,
+ ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_B),
+ (pdata->debounce_dis_mask >> kpad->var->col_shift)
+ & kpad->var->col_mask);
+
+ if (!kpad->is_adp5585)
+ ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_C),
+ (pdata->debounce_dis_mask >> 16) & 0xFF);
+
+ ret |= adp5589_write(client, reg(ADP5589_POLL_PTIME_CFG),
pdata->scan_cycle_time & PTIME_MASK);
- ret |= adp5589_write(client, ADP5589_INT_STATUS, LOGIC2_INT |
- LOGIC1_INT | OVRFLOW_INT | LOCK_INT |
+ ret |= adp5589_write(client, ADP5589_5_INT_STATUS,
+ (kpad->is_adp5585 ? 0 : LOGIC2_INT) |
+ LOGIC1_INT | OVRFLOW_INT |
+ (kpad->is_adp5585 ? 0 : LOCK_INT) |
GPI_INT | EVENT_INT); /* Status is W1C */
- ret |= adp5589_write(client, ADP5589_GENERAL_CFG,
+ ret |= adp5589_write(client, reg(ADP5589_GENERAL_CFG),
INT_CFG | OSC_EN | CORE_CLK(3));
- ret |= adp5589_write(client, ADP5589_INT_EN,
+ ret |= adp5589_write(client, reg(ADP5589_INT_EN),
OVRFLOW_IEN | GPI_IEN | EVENT_IEN);
if (ret < 0) {
@@ -497,30 +822,33 @@ static int __devinit adp5589_setup(struct adp5589_kpad *kpad)
static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad)
{
- int gpi_stat1 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_A);
- int gpi_stat2 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_B);
- int gpi_stat3 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_C);
int gpi_stat_tmp, pin_loc;
int i;
+ int gpi_stat1 = adp5589_read(kpad->client,
+ kpad->var->reg(ADP5589_GPI_STATUS_A));
+ int gpi_stat2 = adp5589_read(kpad->client,
+ kpad->var->reg(ADP5589_GPI_STATUS_B));
+ int gpi_stat3 = !kpad->is_adp5585 ?
+ adp5589_read(kpad->client, ADP5589_GPI_STATUS_C) : 0;
for (i = 0; i < kpad->gpimapsize; i++) {
unsigned short pin = kpad->gpimap[i].pin;
- if (pin <= ADP5589_GPI_PIN_ROW_END) {
+ if (pin <= kpad->var->gpi_pin_row_end) {
gpi_stat_tmp = gpi_stat1;
- pin_loc = pin - ADP5589_GPI_PIN_ROW_BASE;
- } else if ((pin - ADP5589_GPI_PIN_COL_BASE) < 8) {
+ pin_loc = pin - kpad->var->gpi_pin_row_base;
+ } else if ((pin - kpad->var->gpi_pin_col_base) < 8) {
gpi_stat_tmp = gpi_stat2;
- pin_loc = pin - ADP5589_GPI_PIN_COL_BASE;
+ pin_loc = pin - kpad->var->gpi_pin_col_base;
} else {
gpi_stat_tmp = gpi_stat3;
- pin_loc = pin - ADP5589_GPI_PIN_COL_BASE - 8;
+ pin_loc = pin - kpad->var->gpi_pin_col_base - 8;
}
if (gpi_stat_tmp < 0) {
dev_err(&kpad->client->dev,
- "Can't read GPIO_DAT_STAT switch"
- " %d default to OFF\n", pin);
+ "Can't read GPIO_DAT_STAT switch %d, default to OFF\n",
+ pin);
gpi_stat_tmp = 0;
}
@@ -536,7 +864,8 @@ static int __devinit adp5589_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adp5589_kpad *kpad;
- const struct adp5589_kpad_platform_data *pdata;
+ const struct adp5589_kpad_platform_data *pdata =
+ client->dev.platform_data;
struct input_dev *input;
unsigned int revid;
int ret, i;
@@ -548,56 +877,79 @@ static int __devinit adp5589_probe(struct i2c_client *client,
return -EIO;
}
- pdata = client->dev.platform_data;
if (!pdata) {
dev_err(&client->dev, "no platform data?\n");
return -EINVAL;
}
- if (!((pdata->keypad_en_mask & 0xFF) &&
- (pdata->keypad_en_mask >> 8)) || !pdata->keymap) {
+ kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
+ if (!kpad)
+ return -ENOMEM;
+
+ switch (id->driver_data) {
+ case ADP5585_02:
+ kpad->adp5585_support_row5 = true;
+ case ADP5585_01:
+ kpad->is_adp5585 = true;
+ kpad->var = &const_adp5585;
+ break;
+ case ADP5589:
+ kpad->var = &const_adp5589;
+ break;
+ }
+
+ if (!((pdata->keypad_en_mask & kpad->var->row_mask) &&
+ (pdata->keypad_en_mask >> kpad->var->col_shift)) ||
+ !pdata->keymap) {
dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
- return -EINVAL;
+ error = -EINVAL;
+ goto err_free_mem;
}
- if (pdata->keymapsize != ADP5589_KEYMAPSIZE) {
+ if (pdata->keymapsize != kpad->var->keymapsize) {
dev_err(&client->dev, "invalid keymapsize\n");
- return -EINVAL;
+ error = -EINVAL;
+ goto err_free_mem;
}
if (!pdata->gpimap && pdata->gpimapsize) {
dev_err(&client->dev, "invalid gpimap from pdata\n");
- return -EINVAL;
+ error = -EINVAL;
+ goto err_free_mem;
}
- if (pdata->gpimapsize > ADP5589_GPIMAPSIZE_MAX) {
+ if (pdata->gpimapsize > kpad->var->gpimapsize_max) {
dev_err(&client->dev, "invalid gpimapsize\n");
- return -EINVAL;
+ error = -EINVAL;
+ goto err_free_mem;
}
for (i = 0; i < pdata->gpimapsize; i++) {
unsigned short pin = pdata->gpimap[i].pin;
- if (pin < ADP5589_GPI_PIN_BASE || pin > ADP5589_GPI_PIN_END) {
+ if (pin < kpad->var->gpi_pin_base ||
+ pin > kpad->var->gpi_pin_end) {
dev_err(&client->dev, "invalid gpi pin data\n");
- return -EINVAL;
+ error = -EINVAL;
+ goto err_free_mem;
}
- if ((1 << (pin - ADP5589_GPI_PIN_ROW_BASE)) &
+ if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
pdata->keypad_en_mask) {
dev_err(&client->dev, "invalid gpi row/col data\n");
- return -EINVAL;
+ error = -EINVAL;
+ goto err_free_mem;
}
}
if (!client->irq) {
dev_err(&client->dev, "no IRQ?\n");
- return -EINVAL;
+ error = -EINVAL;
+ goto err_free_mem;
}
- kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
input = input_allocate_device();
- if (!kpad || !input) {
+ if (!input) {
error = -ENOMEM;
goto err_free_mem;
}
@@ -605,13 +957,13 @@ static int __devinit adp5589_probe(struct i2c_client *client,
kpad->client = client;
kpad->input = input;
- ret = adp5589_read(client, ADP5589_ID);
+ ret = adp5589_read(client, ADP5589_5_ID);
if (ret < 0) {
error = ret;
- goto err_free_mem;
+ goto err_free_input;
}
- revid = (u8) ret & ADP5589_DEVICE_ID_MASK;
+ revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
input->name = client->name;
input->phys = "adp5589-keys/input0";
@@ -652,7 +1004,7 @@ static int __devinit adp5589_probe(struct i2c_client *client,
error = input_register_device(input);
if (error) {
dev_err(&client->dev, "unable to register input device\n");
- goto err_free_mem;
+ goto err_free_input;
}
error = request_threaded_irq(client->irq, NULL, adp5589_irq,
@@ -685,8 +1037,9 @@ err_free_irq:
err_unreg_dev:
input_unregister_device(input);
input = NULL;
-err_free_mem:
+err_free_input:
input_free_device(input);
+err_free_mem:
kfree(kpad);
return error;
@@ -696,7 +1049,7 @@ static int __devexit adp5589_remove(struct i2c_client *client)
{
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
- adp5589_write(client, ADP5589_GENERAL_CFG, 0);
+ adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
free_irq(client->irq, kpad);
input_unregister_device(kpad->input);
adp5589_gpio_remove(kpad);
@@ -736,7 +1089,9 @@ static int adp5589_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume);
static const struct i2c_device_id adp5589_id[] = {
- {"adp5589-keys", 0},
+ {"adp5589-keys", ADP5589},
+ {"adp5585-keys", ADP5585_01},
+ {"adp5585-02-keys", ADP5585_02}, /* Adds ROW5 to ADP5585 */
{}
};
@@ -767,4 +1122,4 @@ module_exit(adp5589_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("ADP5589 Keypad driver");
+MODULE_DESCRIPTION("ADP5589/ADP5585 Keypad driver");
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c
index cd89d17162a3..9d82b3aeff5e 100644
--- a/drivers/input/keyboard/davinci_keyscan.c
+++ b/drivers/input/keyboard/davinci_keyscan.c
@@ -271,7 +271,7 @@ static int __init davinci_ks_probe(struct platform_device *pdev)
}
error = request_irq(davinci_ks->irq, davinci_ks_interrupt,
- IRQF_DISABLED, pdev->name, davinci_ks);
+ 0, pdev->name, davinci_ks);
if (error < 0) {
dev_err(dev, "unable to register davinci key scan interrupt\n");
goto fail5;
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index aa17e024d803..4662c5da8018 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -323,7 +323,7 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, keypad);
err = request_irq(keypad->irq, ep93xx_keypad_irq_handler,
- IRQF_DISABLED, pdev->name, keypad);
+ 0, pdev->name, keypad);
if (err)
goto failed_free_dev;
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 67df91af8424..ed1ed469d085 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -461,8 +461,7 @@ static int gpio_keys_get_devtree_pdata(struct device *dev,
struct device_node *node, *pp;
int i;
struct gpio_keys_button *buttons;
- const u32 *reg;
- int len;
+ u32 reg;
node = dev->of_node;
if (node == NULL)
@@ -470,7 +469,7 @@ static int gpio_keys_get_devtree_pdata(struct device *dev,
memset(pdata, 0, sizeof *pdata);
- pdata->rep = !!of_get_property(node, "autorepeat", &len);
+ pdata->rep = !!of_get_property(node, "autorepeat", NULL);
/* First count the subnodes */
pdata->nbuttons = 0;
@@ -498,22 +497,25 @@ static int gpio_keys_get_devtree_pdata(struct device *dev,
buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags);
buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW;
- reg = of_get_property(pp, "linux,code", &len);
- if (!reg) {
+ if (of_property_read_u32(pp, "linux,code", &reg)) {
dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio);
goto out_fail;
}
- buttons[i].code = be32_to_cpup(reg);
+ buttons[i].code = reg;
- buttons[i].desc = of_get_property(pp, "label", &len);
+ buttons[i].desc = of_get_property(pp, "label", NULL);
- reg = of_get_property(pp, "linux,input-type", &len);
- buttons[i].type = reg ? be32_to_cpup(reg) : EV_KEY;
+ if (of_property_read_u32(pp, "linux,input-type", &reg) == 0)
+ buttons[i].type = reg;
+ else
+ buttons[i].type = EV_KEY;
buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
- reg = of_get_property(pp, "debounce-interval", &len);
- buttons[i].debounce_interval = reg ? be32_to_cpup(reg) : 5;
+ if (of_property_read_u32(pp, "debounce-interval", &reg) == 0)
+ buttons[i].debounce_interval = reg;
+ else
+ buttons[i].debounce_interval = 5;
i++;
}
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index d92c15c39e68..ccebd2d09151 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -510,7 +510,7 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev)
/* Ensure that the keypad will stay dormant until opened */
imx_keypad_inhibit(keypad);
- error = request_irq(irq, imx_keypad_irq_handler, IRQF_DISABLED,
+ error = request_irq(irq, imx_keypad_irq_handler, 0,
pdev->name, keypad);
if (error) {
dev_err(&pdev->dev, "failed to request IRQ\n");
@@ -567,10 +567,54 @@ static int __devexit imx_keypad_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int imx_kbd_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct imx_keypad *kbd = platform_get_drvdata(pdev);
+ struct input_dev *input_dev = kbd->input_dev;
+
+ /* imx kbd can wake up system even clock is disabled */
+ mutex_lock(&input_dev->mutex);
+
+ if (input_dev->users)
+ clk_disable(kbd->clk);
+
+ mutex_unlock(&input_dev->mutex);
+
+ if (device_may_wakeup(&pdev->dev))
+ enable_irq_wake(kbd->irq);
+
+ return 0;
+}
+
+static int imx_kbd_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct imx_keypad *kbd = platform_get_drvdata(pdev);
+ struct input_dev *input_dev = kbd->input_dev;
+
+ if (device_may_wakeup(&pdev->dev))
+ disable_irq_wake(kbd->irq);
+
+ mutex_lock(&input_dev->mutex);
+
+ if (input_dev->users)
+ clk_enable(kbd->clk);
+
+ mutex_unlock(&input_dev->mutex);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume);
+
static struct platform_driver imx_keypad_driver = {
.driver = {
.name = "imx-keypad",
.owner = THIS_MODULE,
+ .pm = &imx_kbd_pm_ops,
},
.probe = imx_keypad_probe,
.remove = __devexit_p(imx_keypad_remove),
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
index 2cd3e1d56ea4..0aa6740e60d0 100644
--- a/drivers/input/keyboard/jornada720_kbd.c
+++ b/drivers/input/keyboard/jornada720_kbd.c
@@ -129,7 +129,7 @@ static int __devinit jornada720_kbd_probe(struct platform_device *pdev)
err = request_irq(IRQ_GPIO0,
jornada720_kbd_interrupt,
- IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+ IRQF_TRIGGER_FALLING,
"jornadakbd", pdev);
if (err) {
printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n");
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index 756348a7f93a..82d1dc8badd5 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -788,7 +788,7 @@ static int __devexit lm8323_remove(struct i2c_client *client)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
/*
* We don't need to explicitly suspend the chip, as it already switches off
* when there's no activity.
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index b02e4268e18f..e2ae657717ea 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -343,7 +343,6 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev,
for (i = 0; i < pdata->num_row_gpios; i++) {
err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
matrix_keypad_interrupt,
- IRQF_DISABLED |
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING,
"matrix-keypad", keypad);
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 33d0bdc837c0..323bcdfff248 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -35,7 +35,7 @@
#include <linux/mutex.h>
#include <linux/errno.h>
#include <linux/slab.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <plat/keypad.h>
#include <plat/menelaus.h>
#include <asm/irq.h>
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 4b0ec35259a1..eca6ae63de14 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -535,7 +535,7 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
input_dev->evbit[0] |= BIT_MASK(EV_REL);
}
- error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED,
+ error = request_irq(irq, pxa27x_keypad_irq_handler, 0,
pdev->name, keypad);
if (error) {
dev_err(&pdev->dev, "failed to request IRQ\n");
diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c
index b7123a44b6ec..35451bf780c7 100644
--- a/drivers/input/keyboard/pxa930_rotary.c
+++ b/drivers/input/keyboard/pxa930_rotary.c
@@ -148,7 +148,7 @@ static int __devinit pxa930_rotary_probe(struct platform_device *pdev)
r->input_dev = input_dev;
input_set_drvdata(input_dev, r);
- err = request_irq(irq, rotary_irq, IRQF_DISABLED,
+ err = request_irq(irq, rotary_irq, 0,
"enhanced rotary", r);
if (err) {
dev_err(&pdev->dev, "failed to request IRQ\n");
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c
index 99122f59e988..f60c9e82f204 100644
--- a/drivers/input/keyboard/tc3589x-keypad.c
+++ b/drivers/input/keyboard/tc3589x-keypad.c
@@ -90,7 +90,7 @@ struct tc_keypad {
bool keypad_stopped;
};
-static int __devinit tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
+static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
{
int ret;
struct tc3589x *tc3589x = keypad->tc3589x;
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index a5a77915c650..cf3228b0ab90 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -55,6 +55,7 @@
#define KBC_ROW_CFG0_0 0x8
#define KBC_COL_CFG0_0 0x18
+#define KBC_TO_CNT_0 0x24
#define KBC_INIT_DLY_0 0x28
#define KBC_RPT_DLY_0 0x2c
#define KBC_KP_ENT0_0 0x30
@@ -70,6 +71,7 @@ struct tegra_kbc {
spinlock_t lock;
unsigned int repoll_dly;
unsigned long cp_dly_jiffies;
+ unsigned int cp_to_wkup_dly;
bool use_fn_map;
bool use_ghost_filter;
const struct tegra_kbc_platform_data *pdata;
@@ -258,12 +260,10 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc)
u32 val = 0;
unsigned int i;
unsigned int num_down = 0;
- unsigned long flags;
bool fn_keypress = false;
bool key_in_same_row = false;
bool key_in_same_col = false;
- spin_lock_irqsave(&kbc->lock, flags);
for (i = 0; i < KBC_MAX_KPENT; i++) {
if ((i % 4) == 0)
val = readl(kbc->mmio + KBC_KP_ENT0_0 + i);
@@ -292,7 +292,7 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc)
* any 2 of the 3 keys share a row, and any 2 of them share a column.
* If so ignore the key presses for this iteration.
*/
- if ((kbc->use_ghost_filter) && (num_down >= 3)) {
+ if (kbc->use_ghost_filter && num_down >= 3) {
for (i = 0; i < num_down; i++) {
unsigned int j;
u8 curr_col = scancodes[i] & 0x07;
@@ -325,8 +325,6 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc)
}
}
- spin_unlock_irqrestore(&kbc->lock, flags);
-
/* Ignore the key presses for this iteration? */
if (key_in_same_col && key_in_same_row)
return;
@@ -341,6 +339,18 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc)
kbc->num_pressed_keys = num_down;
}
+static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable)
+{
+ u32 val;
+
+ val = readl(kbc->mmio + KBC_CONTROL_0);
+ if (enable)
+ val |= KBC_CONTROL_FIFO_CNT_INT_EN;
+ else
+ val &= ~KBC_CONTROL_FIFO_CNT_INT_EN;
+ writel(val, kbc->mmio + KBC_CONTROL_0);
+}
+
static void tegra_kbc_keypress_timer(unsigned long data)
{
struct tegra_kbc *kbc = (struct tegra_kbc *)data;
@@ -348,6 +358,8 @@ static void tegra_kbc_keypress_timer(unsigned long data)
u32 val;
unsigned int i;
+ spin_lock_irqsave(&kbc->lock, flags);
+
val = (readl(kbc->mmio + KBC_INT_0) >> 4) & 0xf;
if (val) {
unsigned long dly;
@@ -369,26 +381,19 @@ static void tegra_kbc_keypress_timer(unsigned long data)
kbc->num_pressed_keys = 0;
/* All keys are released so enable the keypress interrupt */
- spin_lock_irqsave(&kbc->lock, flags);
- val = readl(kbc->mmio + KBC_CONTROL_0);
- val |= KBC_CONTROL_FIFO_CNT_INT_EN;
- writel(val, kbc->mmio + KBC_CONTROL_0);
- spin_unlock_irqrestore(&kbc->lock, flags);
+ tegra_kbc_set_fifo_interrupt(kbc, true);
}
+
+ spin_unlock_irqrestore(&kbc->lock, flags);
}
static irqreturn_t tegra_kbc_isr(int irq, void *args)
{
struct tegra_kbc *kbc = args;
- u32 val, ctl;
+ unsigned long flags;
+ u32 val;
- /*
- * Until all keys are released, defer further processing to
- * the polling loop in tegra_kbc_keypress_timer
- */
- ctl = readl(kbc->mmio + KBC_CONTROL_0);
- ctl &= ~KBC_CONTROL_FIFO_CNT_INT_EN;
- writel(ctl, kbc->mmio + KBC_CONTROL_0);
+ spin_lock_irqsave(&kbc->lock, flags);
/*
* Quickly bail out & reenable interrupts if the fifo threshold
@@ -399,15 +404,15 @@ static irqreturn_t tegra_kbc_isr(int irq, void *args)
if (val & KBC_INT_FIFO_CNT_INT_STATUS) {
/*
- * Schedule timer to run when hardware is in continuous
- * polling mode.
+ * Until all keys are released, defer further processing to
+ * the polling loop in tegra_kbc_keypress_timer.
*/
+ tegra_kbc_set_fifo_interrupt(kbc, false);
mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies);
- } else {
- ctl |= KBC_CONTROL_FIFO_CNT_INT_EN;
- writel(ctl, kbc->mmio + KBC_CONTROL_0);
}
+ spin_unlock_irqrestore(&kbc->lock, flags);
+
return IRQ_HANDLED;
}
@@ -455,7 +460,6 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc)
static int tegra_kbc_start(struct tegra_kbc *kbc)
{
const struct tegra_kbc_platform_data *pdata = kbc->pdata;
- unsigned long flags;
unsigned int debounce_cnt;
u32 val = 0;
@@ -493,7 +497,6 @@ static int tegra_kbc_start(struct tegra_kbc *kbc)
* Atomically clear out any remaining entries in the key FIFO
* and enable keyboard interrupts.
*/
- spin_lock_irqsave(&kbc->lock, flags);
while (1) {
val = readl(kbc->mmio + KBC_INT_0);
val >>= 4;
@@ -504,7 +507,6 @@ static int tegra_kbc_start(struct tegra_kbc *kbc)
val = readl(kbc->mmio + KBC_KP_ENT1_0);
}
writel(0x7, kbc->mmio + KBC_INT_0);
- spin_unlock_irqrestore(&kbc->lock, flags);
enable_irq(kbc->irq);
@@ -734,18 +736,30 @@ static int tegra_kbc_suspend(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct tegra_kbc *kbc = platform_get_drvdata(pdev);
+ mutex_lock(&kbc->idev->mutex);
if (device_may_wakeup(&pdev->dev)) {
- tegra_kbc_setup_wakekeys(kbc, true);
- enable_irq_wake(kbc->irq);
+ disable_irq(kbc->irq);
+ del_timer_sync(&kbc->timer);
+ tegra_kbc_set_fifo_interrupt(kbc, false);
+
/* Forcefully clear the interrupt status */
writel(0x7, kbc->mmio + KBC_INT_0);
+ /*
+ * Store the previous resident time of continuous polling mode.
+ * Force the keyboard into interrupt mode.
+ */
+ kbc->cp_to_wkup_dly = readl(kbc->mmio + KBC_TO_CNT_0);
+ writel(0, kbc->mmio + KBC_TO_CNT_0);
+
+ tegra_kbc_setup_wakekeys(kbc, true);
msleep(30);
+
+ enable_irq_wake(kbc->irq);
} else {
- mutex_lock(&kbc->idev->mutex);
if (kbc->idev->users)
tegra_kbc_stop(kbc);
- mutex_unlock(&kbc->idev->mutex);
}
+ mutex_unlock(&kbc->idev->mutex);
return 0;
}
@@ -756,15 +770,22 @@ static int tegra_kbc_resume(struct device *dev)
struct tegra_kbc *kbc = platform_get_drvdata(pdev);
int err = 0;
+ mutex_lock(&kbc->idev->mutex);
if (device_may_wakeup(&pdev->dev)) {
disable_irq_wake(kbc->irq);
tegra_kbc_setup_wakekeys(kbc, false);
+
+ /* Restore the resident time of continuous polling mode. */
+ writel(kbc->cp_to_wkup_dly, kbc->mmio + KBC_TO_CNT_0);
+
+ tegra_kbc_set_fifo_interrupt(kbc, true);
+
+ enable_irq(kbc->irq);
} else {
- mutex_lock(&kbc->idev->mutex);
if (kbc->idev->users)
err = tegra_kbc_start(kbc);
- mutex_unlock(&kbc->idev->mutex);
}
+ mutex_unlock(&kbc->idev->mutex);
return err;
}
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c
index ee2bf6bcf291..318586dadacf 100644
--- a/drivers/input/keyboard/w90p910_keypad.c
+++ b/drivers/input/keyboard/w90p910_keypad.c
@@ -203,7 +203,7 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev)
input_dev->keycode, input_dev->keybit);
error = request_irq(keypad->irq, w90p910_keypad_irq_handler,
- IRQF_DISABLED, pdev->name, keypad);
+ 0, pdev->name, keypad);
if (error) {
dev_err(&pdev->dev, "failed to request IRQ\n");
goto failed_put_clk;
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 7331229e2347..22d875fde53a 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -62,6 +62,17 @@ config INPUT_AD714X_SPI
To compile this driver as a module, choose M here: the
module will be called ad714x-spi.
+config INPUT_BMA150
+ tristate "BMA150/SMB380 acceleration sensor support"
+ depends on I2C
+ select INPUT_POLLDEV
+ help
+ Say Y here if you have Bosch Sensortec's BMA150 or SMB380
+ acceleration sensor hooked to an I2C bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bma150.
+
config INPUT_PCSPKR
tristate "PC Speaker support"
depends on PCSPKR_PLATFORM
@@ -74,6 +85,29 @@ config INPUT_PCSPKR
To compile this driver as a module, choose M here: the
module will be called pcspkr.
+config INPUT_PM8XXX_VIBRATOR
+ tristate "Qualcomm PM8XXX vibrator support"
+ depends on MFD_PM8XXX
+ select INPUT_FF_MEMLESS
+ help
+ This option enables device driver support for the vibrator
+ on Qualcomm PM8xxx chip. This driver supports ff-memless interface
+ from input framework.
+
+ To compile this driver as module, choose M here: the
+ module will be called pm8xxx-vibrator.
+
+config INPUT_PMIC8XXX_PWRKEY
+ tristate "PMIC8XXX power key support"
+ depends on MFD_PM8XXX
+ help
+ Say Y here if you want support for the PMIC8XXX power key.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pmic8xxx-pwrkey.
+
config INPUT_SPARCSPKR
tristate "SPARC Speaker support"
depends on PCI && SPARC64
@@ -193,22 +227,6 @@ config INPUT_ATLAS_BTNS
To compile this driver as a module, choose M here: the module will
be called atlas_btns.
-config INPUT_ATI_REMOTE
- tristate "ATI / X10 USB RF remote control"
- depends on USB_ARCH_HAS_HCD
- select USB
- help
- Say Y here if you want to use an ATI or X10 "Lola" USB remote control.
- These are RF remotes with USB receivers.
- The ATI remote comes with many of ATI's All-In-Wonder video cards.
- The X10 "Lola" remote is available at:
- <http://www.x10.com/products/lola_sg1.htm>
- This driver provides mouse pointer, left and right mouse buttons,
- and maps all the other remote buttons to keypress events.
-
- To compile this driver as a module, choose M here: the module will be
- called ati_remote.
-
config INPUT_ATI_REMOTE2
tristate "ATI / Philips USB RF remote control"
depends on USB_ARCH_HAS_HCD
@@ -389,17 +407,6 @@ config INPUT_PWM_BEEPER
To compile this driver as a module, choose M here: the module will be
called pwm-beeper.
-config INPUT_PMIC8XXX_PWRKEY
- tristate "PMIC8XXX power key support"
- depends on MFD_PM8XXX
- help
- Say Y here if you want support for the PMIC8XXX power key.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called pmic8xxx-pwrkey.
-
config INPUT_GPIO_ROTARY_ENCODER
tristate "Rotary encoders connected to GPIO pins"
depends on GPIOLIB && GENERIC_GPIO
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index f54ccc2d9cb5..a244fc6a781c 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -13,10 +13,10 @@ 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_ATI_REMOTE) += ati_remote.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
+obj-$(CONFIG_INPUT_BMA150) += bma150.o
obj-$(CONFIG_INPUT_CM109) += cm109.o
obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o
@@ -35,9 +35,10 @@ obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o
obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
+obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o
+obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
-obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index 025417d74ca2..56810fb4eadd 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -116,13 +116,13 @@ static struct i2c_driver ad714x_i2c_driver = {
.id_table = ad714x_id,
};
-static __init int ad714x_i2c_init(void)
+static int __init ad714x_i2c_init(void)
{
return i2c_add_driver(&ad714x_i2c_driver);
}
module_init(ad714x_i2c_init);
-static __exit void ad714x_i2c_exit(void)
+static void __exit ad714x_i2c_exit(void)
{
i2c_del_driver(&ad714x_i2c_driver);
}
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
new file mode 100644
index 000000000000..8f55b54352b6
--- /dev/null
+++ b/drivers/input/misc/bma150.c
@@ -0,0 +1,691 @@
+/*
+ * Copyright (c) 2011 Bosch Sensortec GmbH
+ * Copyright (c) 2011 Unixphere
+ *
+ * This driver adds support for Bosch Sensortec's digital acceleration
+ * sensors BMA150 and SMB380.
+ * The SMB380 is fully compatible with BMA150 and only differs in packaging.
+ *
+ * The datasheet for the BMA150 chip can be found here:
+ * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMA150-DS000-07.pdf
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/bma150.h>
+
+#define ABSMAX_ACC_VAL 0x01FF
+#define ABSMIN_ACC_VAL -(ABSMAX_ACC_VAL)
+
+/* Each axis is represented by a 2-byte data word */
+#define BMA150_XYZ_DATA_SIZE 6
+
+/* Input poll interval in milliseconds */
+#define BMA150_POLL_INTERVAL 10
+#define BMA150_POLL_MAX 200
+#define BMA150_POLL_MIN 0
+
+#define BMA150_BW_25HZ 0
+#define BMA150_BW_50HZ 1
+#define BMA150_BW_100HZ 2
+#define BMA150_BW_190HZ 3
+#define BMA150_BW_375HZ 4
+#define BMA150_BW_750HZ 5
+#define BMA150_BW_1500HZ 6
+
+#define BMA150_RANGE_2G 0
+#define BMA150_RANGE_4G 1
+#define BMA150_RANGE_8G 2
+
+#define BMA150_MODE_NORMAL 0
+#define BMA150_MODE_SLEEP 2
+#define BMA150_MODE_WAKE_UP 3
+
+/* Data register addresses */
+#define BMA150_DATA_0_REG 0x00
+#define BMA150_DATA_1_REG 0x01
+#define BMA150_DATA_2_REG 0x02
+
+/* Control register addresses */
+#define BMA150_CTRL_0_REG 0x0A
+#define BMA150_CTRL_1_REG 0x0B
+#define BMA150_CTRL_2_REG 0x14
+#define BMA150_CTRL_3_REG 0x15
+
+/* Configuration/Setting register addresses */
+#define BMA150_CFG_0_REG 0x0C
+#define BMA150_CFG_1_REG 0x0D
+#define BMA150_CFG_2_REG 0x0E
+#define BMA150_CFG_3_REG 0x0F
+#define BMA150_CFG_4_REG 0x10
+#define BMA150_CFG_5_REG 0x11
+
+#define BMA150_CHIP_ID 2
+#define BMA150_CHIP_ID_REG BMA150_DATA_0_REG
+
+#define BMA150_ACC_X_LSB_REG BMA150_DATA_2_REG
+
+#define BMA150_SLEEP_POS 0
+#define BMA150_SLEEP_MSK 0x01
+#define BMA150_SLEEP_REG BMA150_CTRL_0_REG
+
+#define BMA150_BANDWIDTH_POS 0
+#define BMA150_BANDWIDTH_MSK 0x07
+#define BMA150_BANDWIDTH_REG BMA150_CTRL_2_REG
+
+#define BMA150_RANGE_POS 3
+#define BMA150_RANGE_MSK 0x18
+#define BMA150_RANGE_REG BMA150_CTRL_2_REG
+
+#define BMA150_WAKE_UP_POS 0
+#define BMA150_WAKE_UP_MSK 0x01
+#define BMA150_WAKE_UP_REG BMA150_CTRL_3_REG
+
+#define BMA150_SW_RES_POS 1
+#define BMA150_SW_RES_MSK 0x02
+#define BMA150_SW_RES_REG BMA150_CTRL_0_REG
+
+/* Any-motion interrupt register fields */
+#define BMA150_ANY_MOTION_EN_POS 6
+#define BMA150_ANY_MOTION_EN_MSK 0x40
+#define BMA150_ANY_MOTION_EN_REG BMA150_CTRL_1_REG
+
+#define BMA150_ANY_MOTION_DUR_POS 6
+#define BMA150_ANY_MOTION_DUR_MSK 0xC0
+#define BMA150_ANY_MOTION_DUR_REG BMA150_CFG_5_REG
+
+#define BMA150_ANY_MOTION_THRES_REG BMA150_CFG_4_REG
+
+/* Advanced interrupt register fields */
+#define BMA150_ADV_INT_EN_POS 6
+#define BMA150_ADV_INT_EN_MSK 0x40
+#define BMA150_ADV_INT_EN_REG BMA150_CTRL_3_REG
+
+/* High-G interrupt register fields */
+#define BMA150_HIGH_G_EN_POS 1
+#define BMA150_HIGH_G_EN_MSK 0x02
+#define BMA150_HIGH_G_EN_REG BMA150_CTRL_1_REG
+
+#define BMA150_HIGH_G_HYST_POS 3
+#define BMA150_HIGH_G_HYST_MSK 0x38
+#define BMA150_HIGH_G_HYST_REG BMA150_CFG_5_REG
+
+#define BMA150_HIGH_G_DUR_REG BMA150_CFG_3_REG
+#define BMA150_HIGH_G_THRES_REG BMA150_CFG_2_REG
+
+/* Low-G interrupt register fields */
+#define BMA150_LOW_G_EN_POS 0
+#define BMA150_LOW_G_EN_MSK 0x01
+#define BMA150_LOW_G_EN_REG BMA150_CTRL_1_REG
+
+#define BMA150_LOW_G_HYST_POS 0
+#define BMA150_LOW_G_HYST_MSK 0x07
+#define BMA150_LOW_G_HYST_REG BMA150_CFG_5_REG
+
+#define BMA150_LOW_G_DUR_REG BMA150_CFG_1_REG
+#define BMA150_LOW_G_THRES_REG BMA150_CFG_0_REG
+
+struct bma150_data {
+ struct i2c_client *client;
+ struct input_polled_dev *input_polled;
+ struct input_dev *input;
+ u8 mode;
+};
+
+/*
+ * The settings for the given range, bandwidth and interrupt features
+ * are stated and verified by Bosch Sensortec where they are configured
+ * to provide a generic sensitivity performance.
+ */
+static struct bma150_cfg default_cfg __devinitdata = {
+ .any_motion_int = 1,
+ .hg_int = 1,
+ .lg_int = 1,
+ .any_motion_dur = 0,
+ .any_motion_thres = 0,
+ .hg_hyst = 0,
+ .hg_dur = 150,
+ .hg_thres = 160,
+ .lg_hyst = 0,
+ .lg_dur = 150,
+ .lg_thres = 20,
+ .range = BMA150_RANGE_2G,
+ .bandwidth = BMA150_BW_50HZ
+};
+
+static int bma150_write_byte(struct i2c_client *client, u8 reg, u8 val)
+{
+ s32 ret;
+
+ /* As per specification, disable irq in between register writes */
+ if (client->irq)
+ disable_irq_nosync(client->irq);
+
+ ret = i2c_smbus_write_byte_data(client, reg, val);
+
+ if (client->irq)
+ enable_irq(client->irq);
+
+ return ret;
+}
+
+static int bma150_set_reg_bits(struct i2c_client *client,
+ int val, int shift, u8 mask, u8 reg)
+{
+ int data;
+
+ data = i2c_smbus_read_byte_data(client, reg);
+ if (data < 0)
+ return data;
+
+ data = (data & ~mask) | ((val << shift) & mask);
+ return bma150_write_byte(client, reg, data);
+}
+
+static int bma150_set_mode(struct bma150_data *bma150, u8 mode)
+{
+ int error;
+
+ error = bma150_set_reg_bits(bma150->client, mode, BMA150_WAKE_UP_POS,
+ BMA150_WAKE_UP_MSK, BMA150_WAKE_UP_REG);
+ if (error)
+ return error;
+
+ error = bma150_set_reg_bits(bma150->client, mode, BMA150_SLEEP_POS,
+ BMA150_SLEEP_MSK, BMA150_SLEEP_REG);
+ if (error)
+ return error;
+
+ if (mode == BMA150_MODE_NORMAL)
+ msleep(2);
+
+ bma150->mode = mode;
+ return 0;
+}
+
+static int __devinit bma150_soft_reset(struct bma150_data *bma150)
+{
+ int error;
+
+ error = bma150_set_reg_bits(bma150->client, 1, BMA150_SW_RES_POS,
+ BMA150_SW_RES_MSK, BMA150_SW_RES_REG);
+ if (error)
+ return error;
+
+ msleep(2);
+ return 0;
+}
+
+static int __devinit bma150_set_range(struct bma150_data *bma150, u8 range)
+{
+ return bma150_set_reg_bits(bma150->client, range, BMA150_RANGE_POS,
+ BMA150_RANGE_MSK, BMA150_RANGE_REG);
+}
+
+static int __devinit bma150_set_bandwidth(struct bma150_data *bma150, u8 bw)
+{
+ return bma150_set_reg_bits(bma150->client, bw, BMA150_BANDWIDTH_POS,
+ BMA150_BANDWIDTH_MSK, BMA150_BANDWIDTH_REG);
+}
+
+static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150,
+ u8 enable, u8 hyst, u8 dur, u8 thres)
+{
+ int error;
+
+ error = bma150_set_reg_bits(bma150->client, hyst,
+ BMA150_LOW_G_HYST_POS, BMA150_LOW_G_HYST_MSK,
+ BMA150_LOW_G_HYST_REG);
+ if (error)
+ return error;
+
+ error = bma150_write_byte(bma150->client, BMA150_LOW_G_DUR_REG, dur);
+ if (error)
+ return error;
+
+ error = bma150_write_byte(bma150->client, BMA150_LOW_G_THRES_REG, thres);
+ if (error)
+ return error;
+
+ return bma150_set_reg_bits(bma150->client, !!enable,
+ BMA150_LOW_G_EN_POS, BMA150_LOW_G_EN_MSK,
+ BMA150_LOW_G_EN_REG);
+}
+
+static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150,
+ u8 enable, u8 hyst, u8 dur, u8 thres)
+{
+ int error;
+
+ error = bma150_set_reg_bits(bma150->client, hyst,
+ BMA150_HIGH_G_HYST_POS, BMA150_HIGH_G_HYST_MSK,
+ BMA150_HIGH_G_HYST_REG);
+ if (error)
+ return error;
+
+ error = bma150_write_byte(bma150->client,
+ BMA150_HIGH_G_DUR_REG, dur);
+ if (error)
+ return error;
+
+ error = bma150_write_byte(bma150->client,
+ BMA150_HIGH_G_THRES_REG, thres);
+ if (error)
+ return error;
+
+ return bma150_set_reg_bits(bma150->client, !!enable,
+ BMA150_HIGH_G_EN_POS, BMA150_HIGH_G_EN_MSK,
+ BMA150_HIGH_G_EN_REG);
+}
+
+
+static int __devinit bma150_set_any_motion_interrupt(struct bma150_data *bma150,
+ u8 enable, u8 dur, u8 thres)
+{
+ int error;
+
+ error = bma150_set_reg_bits(bma150->client, dur,
+ BMA150_ANY_MOTION_DUR_POS,
+ BMA150_ANY_MOTION_DUR_MSK,
+ BMA150_ANY_MOTION_DUR_REG);
+ if (error)
+ return error;
+
+ error = bma150_write_byte(bma150->client,
+ BMA150_ANY_MOTION_THRES_REG, thres);
+ if (error)
+ return error;
+
+ error = bma150_set_reg_bits(bma150->client, !!enable,
+ BMA150_ADV_INT_EN_POS, BMA150_ADV_INT_EN_MSK,
+ BMA150_ADV_INT_EN_REG);
+ if (error)
+ return error;
+
+ return bma150_set_reg_bits(bma150->client, !!enable,
+ BMA150_ANY_MOTION_EN_POS,
+ BMA150_ANY_MOTION_EN_MSK,
+ BMA150_ANY_MOTION_EN_REG);
+}
+
+static void bma150_report_xyz(struct bma150_data *bma150)
+{
+ u8 data[BMA150_XYZ_DATA_SIZE];
+ s16 x, y, z;
+ s32 ret;
+
+ ret = i2c_smbus_read_i2c_block_data(bma150->client,
+ BMA150_ACC_X_LSB_REG, BMA150_XYZ_DATA_SIZE, data);
+ if (ret != BMA150_XYZ_DATA_SIZE)
+ return;
+
+ x = ((0xc0 & data[0]) >> 6) | (data[1] << 2);
+ y = ((0xc0 & data[2]) >> 6) | (data[3] << 2);
+ z = ((0xc0 & data[4]) >> 6) | (data[5] << 2);
+
+ /* sign extension */
+ x = (s16) (x << 6) >> 6;
+ y = (s16) (y << 6) >> 6;
+ z = (s16) (z << 6) >> 6;
+
+ input_report_abs(bma150->input, ABS_X, x);
+ input_report_abs(bma150->input, ABS_Y, y);
+ input_report_abs(bma150->input, ABS_Z, z);
+ input_sync(bma150->input);
+}
+
+static irqreturn_t bma150_irq_thread(int irq, void *dev)
+{
+ bma150_report_xyz(dev);
+
+ return IRQ_HANDLED;
+}
+
+static void bma150_poll(struct input_polled_dev *dev)
+{
+ bma150_report_xyz(dev->private);
+}
+
+static int bma150_open(struct bma150_data *bma150)
+{
+ int error;
+
+ error = pm_runtime_get_sync(&bma150->client->dev);
+ if (error && error != -ENOSYS)
+ return error;
+
+ /*
+ * See if runtime PM woke up the device. If runtime PM
+ * is disabled we need to do it ourselves.
+ */
+ if (bma150->mode != BMA150_MODE_NORMAL) {
+ error = bma150_set_mode(bma150, BMA150_MODE_NORMAL);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+static void bma150_close(struct bma150_data *bma150)
+{
+ pm_runtime_put_sync(&bma150->client->dev);
+
+ if (bma150->mode != BMA150_MODE_SLEEP)
+ bma150_set_mode(bma150, BMA150_MODE_SLEEP);
+}
+
+static int bma150_irq_open(struct input_dev *input)
+{
+ struct bma150_data *bma150 = input_get_drvdata(input);
+
+ return bma150_open(bma150);
+}
+
+static void bma150_irq_close(struct input_dev *input)
+{
+ struct bma150_data *bma150 = input_get_drvdata(input);
+
+ bma150_close(bma150);
+}
+
+static void bma150_poll_open(struct input_polled_dev *ipoll_dev)
+{
+ struct bma150_data *bma150 = ipoll_dev->private;
+
+ bma150_open(bma150);
+}
+
+static void bma150_poll_close(struct input_polled_dev *ipoll_dev)
+{
+ struct bma150_data *bma150 = ipoll_dev->private;
+
+ bma150_close(bma150);
+}
+
+static int __devinit bma150_initialize(struct bma150_data *bma150,
+ const struct bma150_cfg *cfg)
+{
+ int error;
+
+ error = bma150_soft_reset(bma150);
+ if (error)
+ return error;
+
+ error = bma150_set_bandwidth(bma150, cfg->bandwidth);
+ if (error)
+ return error;
+
+ error = bma150_set_range(bma150, cfg->range);
+ if (error)
+ return error;
+
+ if (bma150->client->irq) {
+ error = bma150_set_any_motion_interrupt(bma150,
+ cfg->any_motion_int,
+ cfg->any_motion_dur,
+ cfg->any_motion_thres);
+ if (error)
+ return error;
+
+ error = bma150_set_high_g_interrupt(bma150,
+ cfg->hg_int, cfg->hg_hyst,
+ cfg->hg_dur, cfg->hg_thres);
+ if (error)
+ return error;
+
+ error = bma150_set_low_g_interrupt(bma150,
+ cfg->lg_int, cfg->lg_hyst,
+ cfg->lg_dur, cfg->lg_thres);
+ if (error)
+ return error;
+ }
+
+ return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
+}
+
+static void __devinit bma150_init_input_device(struct bma150_data *bma150,
+ struct input_dev *idev)
+{
+ idev->name = BMA150_DRIVER;
+ idev->phys = BMA150_DRIVER "/input0";
+ idev->id.bustype = BUS_I2C;
+ idev->dev.parent = &bma150->client->dev;
+
+ idev->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+ input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+ input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+}
+
+static int __devinit bma150_register_input_device(struct bma150_data *bma150)
+{
+ struct input_dev *idev;
+ int error;
+
+ idev = input_allocate_device();
+ if (!idev)
+ return -ENOMEM;
+
+ bma150_init_input_device(bma150, idev);
+
+ idev->open = bma150_irq_open;
+ idev->close = bma150_irq_close;
+ input_set_drvdata(idev, bma150);
+
+ error = input_register_device(idev);
+ if (error) {
+ input_free_device(idev);
+ return error;
+ }
+
+ bma150->input = idev;
+ return 0;
+}
+
+static int __devinit bma150_register_polled_device(struct bma150_data *bma150)
+{
+ struct input_polled_dev *ipoll_dev;
+ int error;
+
+ ipoll_dev = input_allocate_polled_device();
+ if (!ipoll_dev)
+ return -ENOMEM;
+
+ ipoll_dev->private = bma150;
+ ipoll_dev->open = bma150_poll_open;
+ ipoll_dev->close = bma150_poll_close;
+ ipoll_dev->poll = bma150_poll;
+ ipoll_dev->poll_interval = BMA150_POLL_INTERVAL;
+ ipoll_dev->poll_interval_min = BMA150_POLL_MIN;
+ ipoll_dev->poll_interval_max = BMA150_POLL_MAX;
+
+ bma150_init_input_device(bma150, ipoll_dev->input);
+
+ error = input_register_polled_device(ipoll_dev);
+ if (error) {
+ input_free_polled_device(ipoll_dev);
+ return error;
+ }
+
+ bma150->input_polled = ipoll_dev;
+ bma150->input = ipoll_dev->input;
+
+ return 0;
+}
+
+static int __devinit bma150_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ const struct bma150_platform_data *pdata = client->dev.platform_data;
+ const struct bma150_cfg *cfg;
+ struct bma150_data *bma150;
+ int chip_id;
+ int error;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "i2c_check_functionality error\n");
+ return -EIO;
+ }
+
+ chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG);
+ if (chip_id != BMA150_CHIP_ID) {
+ dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id);
+ return -EINVAL;
+ }
+
+ bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL);
+ if (!bma150)
+ return -ENOMEM;
+
+ bma150->client = client;
+
+ if (pdata) {
+ if (pdata->irq_gpio_cfg) {
+ error = pdata->irq_gpio_cfg();
+ if (error) {
+ dev_err(&client->dev,
+ "IRQ GPIO conf. error %d, error %d\n",
+ client->irq, error);
+ goto err_free_mem;
+ }
+ }
+ cfg = &pdata->cfg;
+ } else {
+ cfg = &default_cfg;
+ }
+
+ error = bma150_initialize(bma150, cfg);
+ if (error)
+ goto err_free_mem;
+
+ if (client->irq > 0) {
+ error = bma150_register_input_device(bma150);
+ if (error)
+ goto err_free_mem;
+
+ error = request_threaded_irq(client->irq,
+ NULL, bma150_irq_thread,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ BMA150_DRIVER, bma150);
+ if (error) {
+ dev_err(&client->dev,
+ "irq request failed %d, error %d\n",
+ client->irq, error);
+ input_unregister_device(bma150->input);
+ goto err_free_mem;
+ }
+ } else {
+ error = bma150_register_polled_device(bma150);
+ if (error)
+ goto err_free_mem;
+ }
+
+ i2c_set_clientdata(client, bma150);
+
+ pm_runtime_enable(&client->dev);
+
+ return 0;
+
+err_free_mem:
+ kfree(bma150);
+ return error;
+}
+
+static int __devexit bma150_remove(struct i2c_client *client)
+{
+ struct bma150_data *bma150 = i2c_get_clientdata(client);
+
+ pm_runtime_disable(&client->dev);
+
+ if (client->irq > 0) {
+ free_irq(client->irq, bma150);
+ input_unregister_device(bma150->input);
+ } else {
+ input_unregister_polled_device(bma150->input_polled);
+ input_free_polled_device(bma150->input_polled);
+ }
+
+ kfree(bma150);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int bma150_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma150_data *bma150 = i2c_get_clientdata(client);
+
+ return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
+}
+
+static int bma150_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma150_data *bma150 = i2c_get_clientdata(client);
+
+ return bma150_set_mode(bma150, BMA150_MODE_NORMAL);
+}
+#endif
+
+static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
+
+static const struct i2c_device_id bma150_id[] = {
+ { "bma150", 0 },
+ { "smb380", 0 },
+ { "bma023", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, bma150_id);
+
+static struct i2c_driver bma150_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = BMA150_DRIVER,
+ .pm = &bma150_pm,
+ },
+ .class = I2C_CLASS_HWMON,
+ .id_table = bma150_id,
+ .probe = bma150_probe,
+ .remove = __devexit_p(bma150_remove),
+};
+
+static int __init BMA150_init(void)
+{
+ return i2c_add_driver(&bma150_driver);
+}
+
+static void __exit BMA150_exit(void)
+{
+ i2c_del_driver(&bma150_driver);
+}
+
+MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>");
+MODULE_DESCRIPTION("BMA150 driver");
+MODULE_LICENSE("GPL");
+
+module_init(BMA150_init);
+module_exit(BMA150_exit);
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index 1f38302a5951..302ab46ce752 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -111,7 +111,7 @@ static int __devinit ixp4xx_spkr_probe(struct platform_device *dev)
input_dev->event = ixp4xx_spkr_event;
err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
- IRQF_DISABLED | IRQF_NO_SUSPEND, "ixp4xx-beeper",
+ IRQF_NO_SUSPEND, "ixp4xx-beeper",
(void *) dev->id);
if (err)
goto err_free_device;
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
index 0794778295fc..4d60080bb5d5 100644
--- a/drivers/input/misc/mma8450.c
+++ b/drivers/input/misc/mma8450.c
@@ -88,13 +88,13 @@ static int mma8450_write(struct mma8450 *m, unsigned off, u8 v)
return 0;
}
-static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z)
+static int mma8450_read_block(struct mma8450 *m, unsigned off,
+ u8 *buf, size_t size)
{
struct i2c_client *c = m->client;
- u8 buff[6];
int err;
- err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff);
+ err = i2c_smbus_read_i2c_block_data(c, off, size, buf);
if (err < 0) {
dev_err(&c->dev,
"failed to read block data at 0x%02x, error %d\n",
@@ -102,10 +102,6 @@ static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z)
return err;
}
- *x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf);
- *y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf);
- *z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf);
-
return 0;
}
@@ -114,7 +110,7 @@ static void mma8450_poll(struct input_polled_dev *dev)
struct mma8450 *m = dev->private;
int x, y, z;
int ret;
- int err;
+ u8 buf[6];
ret = mma8450_read(m, MMA8450_STATUS);
if (ret < 0)
@@ -123,10 +119,14 @@ static void mma8450_poll(struct input_polled_dev *dev)
if (!(ret & MMA8450_STATUS_ZXYDR))
return;
- err = mma8450_read_xyz(m, &x, &y, &z);
- if (err)
+ ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf));
+ if (ret < 0)
return;
+ x = ((buf[1] << 4) & 0xff0) | (buf[0] & 0xf);
+ y = ((buf[3] << 4) & 0xff0) | (buf[2] & 0xf);
+ z = ((buf[5] << 4) & 0xff0) | (buf[4] & 0xf);
+
input_report_abs(dev->input, ABS_X, x);
input_report_abs(dev->input, ABS_Y, y);
input_report_abs(dev->input, ABS_Z, z);
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
new file mode 100644
index 000000000000..43192930824b
--- /dev/null
+++ b/drivers/input/misc/pm8xxx-vibrator.c
@@ -0,0 +1,296 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/mfd/pm8xxx/core.h>
+
+#define VIB_DRV 0x4A
+
+#define VIB_DRV_SEL_MASK 0xf8
+#define VIB_DRV_SEL_SHIFT 0x03
+#define VIB_DRV_EN_MANUAL_MASK 0xfc
+
+#define VIB_MAX_LEVEL_mV (3100)
+#define VIB_MIN_LEVEL_mV (1200)
+#define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV)
+
+#define MAX_FF_SPEED 0xff
+
+/**
+ * struct pm8xxx_vib - structure to hold vibrator data
+ * @vib_input_dev: input device supporting force feedback
+ * @work: work structure to set the vibration parameters
+ * @dev: device supporting force feedback
+ * @speed: speed of vibration set from userland
+ * @active: state of vibrator
+ * @level: level of vibration to set in the chip
+ * @reg_vib_drv: VIB_DRV register value
+ */
+struct pm8xxx_vib {
+ struct input_dev *vib_input_dev;
+ struct work_struct work;
+ struct device *dev;
+ int speed;
+ int level;
+ bool active;
+ u8 reg_vib_drv;
+};
+
+/**
+ * pm8xxx_vib_read_u8 - helper to read a byte from pmic chip
+ * @vib: pointer to vibrator structure
+ * @data: placeholder for data to be read
+ * @reg: register address
+ */
+static int pm8xxx_vib_read_u8(struct pm8xxx_vib *vib,
+ u8 *data, u16 reg)
+{
+ int rc;
+
+ rc = pm8xxx_readb(vib->dev->parent, reg, data);
+ if (rc < 0)
+ dev_warn(vib->dev, "Error reading pm8xxx reg 0x%x(0x%x)\n",
+ reg, rc);
+ return rc;
+}
+
+/**
+ * pm8xxx_vib_write_u8 - helper to write a byte to pmic chip
+ * @vib: pointer to vibrator structure
+ * @data: data to write
+ * @reg: register address
+ */
+static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib,
+ u8 data, u16 reg)
+{
+ int rc;
+
+ rc = pm8xxx_writeb(vib->dev->parent, reg, data);
+ if (rc < 0)
+ dev_warn(vib->dev, "Error writing pm8xxx reg 0x%x(0x%x)\n",
+ reg, rc);
+ return rc;
+}
+
+/**
+ * pm8xxx_vib_set - handler to start/stop vibration
+ * @vib: pointer to vibrator structure
+ * @on: state to set
+ */
+static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on)
+{
+ int rc;
+ u8 val = vib->reg_vib_drv;
+
+ if (on)
+ val |= ((vib->level << VIB_DRV_SEL_SHIFT) & VIB_DRV_SEL_MASK);
+ else
+ val &= ~VIB_DRV_SEL_MASK;
+
+ rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
+ if (rc < 0)
+ return rc;
+
+ vib->reg_vib_drv = val;
+ return 0;
+}
+
+/**
+ * pm8xxx_work_handler - worker to set vibration level
+ * @work: pointer to work_struct
+ */
+static void pm8xxx_work_handler(struct work_struct *work)
+{
+ struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work);
+ int rc;
+ u8 val;
+
+ rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
+ if (rc < 0)
+ return;
+
+ /*
+ * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so
+ * scale the level to fit into these ranges.
+ */
+ if (vib->speed) {
+ vib->active = true;
+ vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) +
+ VIB_MIN_LEVEL_mV;
+ vib->level /= 100;
+ } else {
+ vib->active = false;
+ vib->level = VIB_MIN_LEVEL_mV / 100;
+ }
+
+ pm8xxx_vib_set(vib, vib->active);
+}
+
+/**
+ * pm8xxx_vib_close - callback of input close callback
+ * @dev: input device pointer
+ *
+ * Turns off the vibrator.
+ */
+static void pm8xxx_vib_close(struct input_dev *dev)
+{
+ struct pm8xxx_vib *vib = input_get_drvdata(dev);
+
+ cancel_work_sync(&vib->work);
+ if (vib->active)
+ pm8xxx_vib_set(vib, false);
+}
+
+/**
+ * pm8xxx_vib_play_effect - function to handle vib effects.
+ * @dev: input device pointer
+ * @data: data of effect
+ * @effect: effect to play
+ *
+ * Currently this driver supports only rumble effects.
+ */
+static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct pm8xxx_vib *vib = input_get_drvdata(dev);
+
+ vib->speed = effect->u.rumble.strong_magnitude >> 8;
+ if (!vib->speed)
+ vib->speed = effect->u.rumble.weak_magnitude >> 9;
+
+ schedule_work(&vib->work);
+
+ return 0;
+}
+
+static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)
+
+{
+ struct pm8xxx_vib *vib;
+ struct input_dev *input_dev;
+ int error;
+ u8 val;
+
+ vib = kzalloc(sizeof(*vib), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!vib || !input_dev) {
+ dev_err(&pdev->dev, "couldn't allocate memory\n");
+ error = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ INIT_WORK(&vib->work, pm8xxx_work_handler);
+ vib->dev = &pdev->dev;
+ vib->vib_input_dev = input_dev;
+
+ /* operate in manual mode */
+ error = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
+ if (error < 0)
+ goto err_free_mem;
+ val &= ~VIB_DRV_EN_MANUAL_MASK;
+ error = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
+ if (error < 0)
+ goto err_free_mem;
+
+ vib->reg_vib_drv = val;
+
+ input_dev->name = "pm8xxx_vib_ffmemless";
+ input_dev->id.version = 1;
+ input_dev->dev.parent = &pdev->dev;
+ input_dev->close = pm8xxx_vib_close;
+ input_set_drvdata(input_dev, vib);
+ input_set_capability(vib->vib_input_dev, EV_FF, FF_RUMBLE);
+
+ error = input_ff_create_memless(input_dev, NULL,
+ pm8xxx_vib_play_effect);
+ if (error) {
+ dev_err(&pdev->dev,
+ "couldn't register vibrator as FF device\n");
+ goto err_free_mem;
+ }
+
+ error = input_register_device(input_dev);
+ if (error) {
+ dev_err(&pdev->dev, "couldn't register input device\n");
+ goto err_destroy_memless;
+ }
+
+ platform_set_drvdata(pdev, vib);
+ return 0;
+
+err_destroy_memless:
+ input_ff_destroy(input_dev);
+err_free_mem:
+ input_free_device(input_dev);
+ kfree(vib);
+
+ return error;
+}
+
+static int __devexit pm8xxx_vib_remove(struct platform_device *pdev)
+{
+ struct pm8xxx_vib *vib = platform_get_drvdata(pdev);
+
+ input_unregister_device(vib->vib_input_dev);
+ kfree(vib);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pm8xxx_vib_suspend(struct device *dev)
+{
+ struct pm8xxx_vib *vib = dev_get_drvdata(dev);
+
+ /* Turn off the vibrator */
+ pm8xxx_vib_set(vib, false);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL);
+
+static struct platform_driver pm8xxx_vib_driver = {
+ .probe = pm8xxx_vib_probe,
+ .remove = __devexit_p(pm8xxx_vib_remove),
+ .driver = {
+ .name = "pm8xxx-vib",
+ .owner = THIS_MODULE,
+ .pm = &pm8xxx_vib_pm_ops,
+ },
+};
+
+static int __init pm8xxx_vib_init(void)
+{
+ return platform_driver_register(&pm8xxx_vib_driver);
+}
+module_init(pm8xxx_vib_init);
+
+static void __exit pm8xxx_vib_exit(void)
+{
+ platform_driver_unregister(&pm8xxx_vib_driver);
+}
+module_exit(pm8xxx_vib_exit);
+
+MODULE_ALIAS("platform:pm8xxx_vib");
+MODULE_DESCRIPTION("PMIC8xxx vibrator driver based on ff-memless framework");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Amy Maloche <amaloche@codeaurora.org>");
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index 2c8b84dd9dac..2be21694fac1 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -7,7 +7,7 @@
* state machine code inspired by code from Tim Ruetz
*
* A generic driver for rotary encoders connected to GPIO lines.
- * See file:Documentation/input/rotary_encoder.txt for more information
+ * See file:Documentation/input/rotary-encoder.txt for more information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
index c43002e7ec72..ad153a417eed 100644
--- a/drivers/input/misc/twl6040-vibra.c
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -74,12 +74,12 @@ static irqreturn_t twl6040_vib_irq_handler(int irq, void *data)
if (status & TWL6040_VIBLOCDET) {
dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
- TWL6040_VIBENAL);
+ TWL6040_VIBENA);
}
if (status & TWL6040_VIBROCDET) {
dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
- TWL6040_VIBENAR);
+ TWL6040_VIBENA);
}
return IRQ_HANDLED;
@@ -97,23 +97,23 @@ static void twl6040_vibra_enable(struct vibra_info *info)
}
twl6040_power(info->twl6040, 1);
- if (twl6040->rev <= TWL6040_REV_ES1_1) {
+ if (twl6040_get_revid(twl6040) <= TWL6040_REV_ES1_1) {
/*
* ERRATA: Disable overcurrent protection for at least
* 3ms when enabling vibrator drivers to avoid false
* overcurrent detection
*/
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
- TWL6040_VIBENAL | TWL6040_VIBCTRLL);
+ TWL6040_VIBENA | TWL6040_VIBCTRL);
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
- TWL6040_VIBENAR | TWL6040_VIBCTRLR);
+ TWL6040_VIBENA | TWL6040_VIBCTRL);
usleep_range(3000, 3500);
}
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
- TWL6040_VIBENAL);
+ TWL6040_VIBENA);
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
- TWL6040_VIBENAR);
+ TWL6040_VIBENA);
info->enabled = true;
}
@@ -201,6 +201,13 @@ static int vibra_play(struct input_dev *input, void *data,
struct vibra_info *info = input_get_drvdata(input);
int ret;
+ /* Do not allow effect, while the routing is set to use audio */
+ ret = twl6040_get_vibralr_status(info->twl6040);
+ if (ret & TWL6040_VIBSEL) {
+ dev_info(&input->dev, "Vibra is configured for audio\n");
+ return -EBUSY;
+ }
+
info->weak_speed = effect->u.rumble.weak_magnitude;
info->strong_speed = effect->u.rumble.strong_magnitude;
info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
@@ -228,7 +235,7 @@ static void twl6040_vibra_close(struct input_dev *input)
mutex_unlock(&info->mutex);
}
-#if CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
static int twl6040_vibra_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 99d58764ef03..003587c71f43 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -23,13 +23,6 @@
#include "psmouse.h"
#include "alps.h"
-#undef DEBUG
-#ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_INFO "alps.c: " format "\n", ## arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-
#define ALPS_OLDPROTO 0x01 /* old style input */
#define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */
#define ALPS_PASS 0x04 /* device has a pass-through port */
@@ -297,10 +290,10 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
psmouse->packet[4] |
psmouse->packet[5]) & 0x80) ||
(!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) {
- dbg("refusing packet %x %x %x %x "
- "(suspected interleaved ps/2)\n",
- psmouse->packet[3], psmouse->packet[4],
- psmouse->packet[5], psmouse->packet[6]);
+ psmouse_dbg(psmouse,
+ "refusing packet %x %x %x %x (suspected interleaved ps/2)\n",
+ psmouse->packet[3], psmouse->packet[4],
+ psmouse->packet[5], psmouse->packet[6]);
return PSMOUSE_BAD_DATA;
}
@@ -319,13 +312,13 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
* There is also possibility that we got 6-byte ALPS
* packet followed by 3-byte packet from trackpoint. We
* can not distinguish between these 2 scenarios but
- * becase the latter is unlikely to happen in course of
+ * because the latter is unlikely to happen in course of
* normal operation (user would need to press all
* buttons on the pad and start moving trackpoint
* without touching the pad surface) we assume former.
* Even if we are wrong the wost thing that would happen
* the cursor would jump but we should not get protocol
- * desynchronization.
+ * de-synchronization.
*/
alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
@@ -361,10 +354,10 @@ static void alps_flush_packet(unsigned long data)
if ((psmouse->packet[3] |
psmouse->packet[4] |
psmouse->packet[5]) & 0x80) {
- dbg("refusing packet %x %x %x "
- "(suspected interleaved ps/2)\n",
- psmouse->packet[3], psmouse->packet[4],
- psmouse->packet[5]);
+ psmouse_dbg(psmouse,
+ "refusing packet %x %x %x (suspected interleaved ps/2)\n",
+ psmouse->packet[3], psmouse->packet[4],
+ psmouse->packet[5]);
} else {
alps_process_packet(psmouse);
}
@@ -396,16 +389,18 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
}
if (!alps_is_valid_first_byte(model, psmouse->packet[0])) {
- dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
- psmouse->packet[0], model->mask0, model->byte0);
+ psmouse_dbg(psmouse,
+ "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
+ psmouse->packet[0], model->mask0, model->byte0);
return PSMOUSE_BAD_DATA;
}
/* Bytes 2 - 6 should have 0 in the highest bit */
if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
(psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
- dbg("refusing packet[%i] = %x\n",
- psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]);
+ psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
+ psmouse->pktcnt - 1,
+ psmouse->packet[psmouse->pktcnt - 1]);
return PSMOUSE_BAD_DATA;
}
@@ -439,7 +434,8 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int
if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
return NULL;
- dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+ psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x",
+ param[0], param[1], param[2]);
if (param[0] != 0 || param[1] != 0 || (param[2] != 10 && param[2] != 100))
return NULL;
@@ -459,7 +455,8 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int
if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
return NULL;
- dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+ psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x",
+ param[0], param[1], param[2]);
if (version) {
for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++)
@@ -527,7 +524,8 @@ static int alps_get_status(struct psmouse *psmouse, char *param)
ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
return -1;
- dbg("Status: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+ psmouse_dbg(psmouse, "Status: %2.2x %2.2x %2.2x",
+ param[0], param[1], param[2]);
return 0;
}
@@ -605,12 +603,12 @@ static int alps_hw_init(struct psmouse *psmouse)
}
if (alps_tap_mode(psmouse, true)) {
- printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
+ psmouse_warn(psmouse, "Failed to enable hardware tapping\n");
return -1;
}
if (alps_absolute_mode(psmouse)) {
- printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
+ psmouse_err(psmouse, "Failed to enable absolute mode\n");
return -1;
}
@@ -621,7 +619,7 @@ static int alps_hw_init(struct psmouse *psmouse)
/* ALPS needs stream mode, otherwise it won't report any data */
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) {
- printk(KERN_ERR "alps.c: Failed to enable stream mode\n");
+ psmouse_err(psmouse, "Failed to enable stream mode\n");
return -1;
}
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 32503565faf9..09b93b11a274 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -10,8 +10,6 @@
* Trademarks are the property of their respective owners.
*/
-#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
-
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -25,13 +23,10 @@
#define elantech_debug(fmt, ...) \
do { \
if (etd->debug) \
- printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \
+ psmouse_printk(KERN_DEBUG, psmouse, \
+ fmt, ##__VA_ARGS__); \
} while (0)
-static bool force_elantech;
-module_param_named(force_elantech, force_elantech, bool, 0644);
-MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default).");
-
/*
* Send a Synaptics style sliced query command
*/
@@ -40,7 +35,7 @@ static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c,
{
if (psmouse_sliced_command(psmouse, c) ||
ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) {
- pr_err("synaptics_send_cmd query 0x%02x failed.\n", c);
+ psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c);
return -1;
}
@@ -69,7 +64,7 @@ static int elantech_ps2_command(struct psmouse *psmouse,
} while (tries > 0);
if (rc)
- pr_err("ps2 command 0x%02x failed.\n", command);
+ psmouse_err(psmouse, "ps2 command 0x%02x failed.\n", command);
return rc;
}
@@ -84,7 +79,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
unsigned char param[3];
int rc = 0;
- if (reg < 0x10 || reg > 0x26)
+ if (reg < 0x07 || reg > 0x26)
return -1;
if (reg > 0x11 && reg < 0x20)
@@ -108,12 +103,24 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
rc = -1;
}
break;
+
+ case 3 ... 4:
+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, reg) ||
+ elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
+ rc = -1;
+ }
+ break;
}
if (rc)
- pr_err("failed to read register 0x%02x.\n", reg);
- else
+ psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg);
+ else if (etd->hw_version != 4)
*val = param[0];
+ else
+ *val = param[1];
return rc;
}
@@ -127,7 +134,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
struct elantech_data *etd = psmouse->private;
int rc = 0;
- if (reg < 0x10 || reg > 0x26)
+ if (reg < 0x07 || reg > 0x26)
return -1;
if (reg > 0x11 && reg < 0x20)
@@ -154,11 +161,38 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
rc = -1;
}
break;
+
+ case 3:
+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, reg) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, val) ||
+ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+ rc = -1;
+ }
+ break;
+
+ case 4:
+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, reg) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+ elantech_ps2_command(psmouse, NULL, val) ||
+ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+ rc = -1;
+ }
+ break;
}
if (rc)
- pr_err("failed to write register 0x%02x with value 0x%02x.\n",
- reg, val);
+ psmouse_err(psmouse,
+ "failed to write register 0x%02x with value 0x%02x.\n",
+ reg, val);
return rc;
}
@@ -166,13 +200,13 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
/*
* Dump a complete mouse movement packet to the syslog
*/
-static void elantech_packet_dump(unsigned char *packet, int size)
+static void elantech_packet_dump(struct psmouse *psmouse)
{
int i;
- printk(KERN_DEBUG pr_fmt("PS/2 packet ["));
- for (i = 0; i < size; i++)
- printk("%s0x%02x ", (i) ? ", " : " ", packet[i]);
+ psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet [");
+ for (i = 0; i < psmouse->pktsize; i++)
+ printk("%s0x%02x ", i ? ", " : " ", psmouse->packet[i]);
printk("]\n");
}
@@ -223,7 +257,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
input_report_abs(dev, ABS_X,
((packet[1] & 0x0c) << 6) | packet[2]);
input_report_abs(dev, ABS_Y,
- ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3]));
+ etd->y_max - (((packet[1] & 0x03) << 8) | packet[3]));
}
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
@@ -233,7 +267,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
if (etd->fw_version < 0x020000 &&
- (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
+ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
/* rocker up */
input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
/* rocker down */
@@ -273,11 +307,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
struct elantech_data *etd = psmouse->private;
struct input_dev *dev = psmouse->dev;
unsigned char *packet = psmouse->packet;
- unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0;
+ unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+ unsigned int width = 0, pres = 0;
/* byte 0: n1 n0 . . . . R L */
fingers = (packet[0] & 0xc0) >> 6;
- input_report_key(dev, BTN_TOUCH, fingers != 0);
switch (fingers) {
case 3:
@@ -290,18 +324,15 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
/* pass through... */
case 1:
/*
- * byte 1: . . . . . x10 x9 x8
+ * byte 1: . . . . x11 x10 x9 x8
* byte 2: x7 x6 x5 x4 x4 x2 x1 x0
*/
- x1 = ((packet[1] & 0x07) << 8) | packet[2];
+ x1 = ((packet[1] & 0x0f) << 8) | packet[2];
/*
- * byte 4: . . . . . . y9 y8
+ * byte 4: . . . . y11 y10 y9 y8
* byte 5: y7 y6 y5 y4 y3 y2 y1 y0
*/
- y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]);
-
- input_report_abs(dev, ABS_X, x1);
- input_report_abs(dev, ABS_Y, y1);
+ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
@@ -314,22 +345,18 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
* byte 0: . . ay8 ax8 . . . .
* byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0
*/
- x1 = ((packet[0] & 0x10) << 4) | packet[1];
+ x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2;
/* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */
- y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]);
+ y1 = etd->y_max -
+ ((((packet[0] & 0x20) << 3) | packet[2]) << 2);
/*
* byte 3: . . by8 bx8 . . . .
* byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0
*/
- x2 = ((packet[3] & 0x10) << 4) | packet[4];
+ x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2;
/* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */
- y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]);
- /*
- * For compatibility with the X Synaptics driver scale up
- * one coordinate and report as ordinary mouse movent
- */
- input_report_abs(dev, ABS_X, x1 << 2);
- input_report_abs(dev, ABS_Y, y1 << 2);
+ y2 = etd->y_max -
+ ((((packet[3] & 0x20) << 3) | packet[5]) << 2);
/* Unknown so just report sensible values */
pres = 127;
@@ -337,6 +364,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
break;
}
+ input_report_key(dev, BTN_TOUCH, fingers != 0);
+ if (fingers != 0) {
+ input_report_abs(dev, ABS_X, x1);
+ input_report_abs(dev, ABS_Y, y1);
+ }
elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
@@ -352,7 +384,208 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
input_sync(dev);
}
-static int elantech_check_parity_v1(struct psmouse *psmouse)
+/*
+ * Interpret complete data packets and report absolute mode input events for
+ * hardware version 3. (12 byte packets for two fingers)
+ */
+static void elantech_report_absolute_v3(struct psmouse *psmouse,
+ int packet_type)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct elantech_data *etd = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+ unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+ unsigned int width = 0, pres = 0;
+
+ /* byte 0: n1 n0 . . . . R L */
+ fingers = (packet[0] & 0xc0) >> 6;
+
+ switch (fingers) {
+ case 3:
+ case 1:
+ /*
+ * byte 1: . . . . x11 x10 x9 x8
+ * byte 2: x7 x6 x5 x4 x4 x2 x1 x0
+ */
+ x1 = ((packet[1] & 0x0f) << 8) | packet[2];
+ /*
+ * byte 4: . . . . y11 y10 y9 y8
+ * byte 5: y7 y6 y5 y4 y3 y2 y1 y0
+ */
+ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+ break;
+
+ case 2:
+ if (packet_type == PACKET_V3_HEAD) {
+ /*
+ * byte 1: . . . . ax11 ax10 ax9 ax8
+ * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0
+ */
+ etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2];
+ /*
+ * byte 4: . . . . ay11 ay10 ay9 ay8
+ * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0
+ */
+ etd->mt[0].y = etd->y_max -
+ (((packet[4] & 0x0f) << 8) | packet[5]);
+ /*
+ * wait for next packet
+ */
+ return;
+ }
+
+ /* packet_type == PACKET_V3_TAIL */
+ x1 = etd->mt[0].x;
+ y1 = etd->mt[0].y;
+ x2 = ((packet[1] & 0x0f) << 8) | packet[2];
+ y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+ break;
+ }
+
+ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+ width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
+
+ input_report_key(dev, BTN_TOUCH, fingers != 0);
+ if (fingers != 0) {
+ input_report_abs(dev, ABS_X, x1);
+ input_report_abs(dev, ABS_Y, y1);
+ }
+ elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
+ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
+ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
+ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
+ input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
+ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+ input_report_abs(dev, ABS_PRESSURE, pres);
+ input_report_abs(dev, ABS_TOOL_WIDTH, width);
+
+ input_sync(dev);
+}
+
+static void elantech_input_sync_v4(struct psmouse *psmouse)
+{
+ struct input_dev *dev = psmouse->dev;
+ unsigned char *packet = psmouse->packet;
+
+ input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
+ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+ input_mt_report_pointer_emulation(dev, true);
+ input_sync(dev);
+}
+
+static void process_packet_status_v4(struct psmouse *psmouse)
+{
+ struct input_dev *dev = psmouse->dev;
+ unsigned char *packet = psmouse->packet;
+ unsigned fingers;
+ int i;
+
+ /* notify finger state change */
+ fingers = packet[1] & 0x1f;
+ for (i = 0; i < ETP_MAX_FINGERS; i++) {
+ if ((fingers & (1 << i)) == 0) {
+ input_mt_slot(dev, i);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
+ }
+ }
+
+ elantech_input_sync_v4(psmouse);
+}
+
+static void process_packet_head_v4(struct psmouse *psmouse)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct elantech_data *etd = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+ int id = ((packet[3] & 0xe0) >> 5) - 1;
+ int pres, traces;
+
+ if (id < 0)
+ return;
+
+ etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2];
+ etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+ traces = (packet[0] & 0xf0) >> 4;
+
+ input_mt_slot(dev, id);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+
+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
+ input_report_abs(dev, ABS_MT_PRESSURE, pres);
+ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width);
+ /* report this for backwards compatibility */
+ input_report_abs(dev, ABS_TOOL_WIDTH, traces);
+
+ elantech_input_sync_v4(psmouse);
+}
+
+static void process_packet_motion_v4(struct psmouse *psmouse)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct elantech_data *etd = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+ int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0;
+ int id, sid;
+
+ id = ((packet[0] & 0xe0) >> 5) - 1;
+ if (id < 0)
+ return;
+
+ sid = ((packet[3] & 0xe0) >> 5) - 1;
+ weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1;
+ /*
+ * Motion packets give us the delta of x, y values of specific fingers,
+ * but in two's complement. Let the compiler do the conversion for us.
+ * Also _enlarge_ the numbers to int, in case of overflow.
+ */
+ delta_x1 = (signed char)packet[1];
+ delta_y1 = (signed char)packet[2];
+ delta_x2 = (signed char)packet[4];
+ delta_y2 = (signed char)packet[5];
+
+ etd->mt[id].x += delta_x1 * weight;
+ etd->mt[id].y -= delta_y1 * weight;
+ input_mt_slot(dev, id);
+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
+
+ if (sid >= 0) {
+ etd->mt[sid].x += delta_x2 * weight;
+ etd->mt[sid].y -= delta_y2 * weight;
+ input_mt_slot(dev, sid);
+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y);
+ }
+
+ elantech_input_sync_v4(psmouse);
+}
+
+static void elantech_report_absolute_v4(struct psmouse *psmouse,
+ int packet_type)
+{
+ switch (packet_type) {
+ case PACKET_V4_STATUS:
+ process_packet_status_v4(psmouse);
+ break;
+
+ case PACKET_V4_HEAD:
+ process_packet_head_v4(psmouse);
+ break;
+
+ case PACKET_V4_MOTION:
+ process_packet_motion_v4(psmouse);
+ break;
+
+ case PACKET_UNKNOWN:
+ default:
+ /* impossible to get here */
+ break;
+ }
+}
+
+static int elantech_packet_check_v1(struct psmouse *psmouse)
{
struct elantech_data *etd = psmouse->private;
unsigned char *packet = psmouse->packet;
@@ -376,31 +609,142 @@ static int elantech_check_parity_v1(struct psmouse *psmouse)
etd->parity[packet[3]] == p3;
}
+static int elantech_debounce_check_v2(struct psmouse *psmouse)
+{
+ /*
+ * When we encounter packet that matches this exactly, it means the
+ * hardware is in debounce status. Just ignore the whole packet.
+ */
+ const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff };
+ unsigned char *packet = psmouse->packet;
+
+ return !memcmp(packet, debounce_packet, sizeof(debounce_packet));
+}
+
+static int elantech_packet_check_v2(struct psmouse *psmouse)
+{
+ struct elantech_data *etd = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+
+ /*
+ * V2 hardware has two flavors. Older ones that do not report pressure,
+ * and newer ones that reports pressure and width. With newer ones, all
+ * packets (1, 2, 3 finger touch) have the same constant bits. With
+ * older ones, 1/3 finger touch packets and 2 finger touch packets
+ * have different constant bits.
+ * With all three cases, if the constant bits are not exactly what I
+ * expected, I consider them invalid.
+ */
+ if (etd->reports_pressure)
+ return (packet[0] & 0x0c) == 0x04 &&
+ (packet[3] & 0x0f) == 0x02;
+
+ if ((packet[0] & 0xc0) == 0x80)
+ return (packet[0] & 0x0c) == 0x0c &&
+ (packet[3] & 0x0e) == 0x08;
+
+ return (packet[0] & 0x3c) == 0x3c &&
+ (packet[1] & 0xf0) == 0x00 &&
+ (packet[3] & 0x3e) == 0x38 &&
+ (packet[4] & 0xf0) == 0x00;
+}
+
+/*
+ * We check the constant bits to determine what packet type we get,
+ * so packet checking is mandatory for v3 and later hardware.
+ */
+static int elantech_packet_check_v3(struct psmouse *psmouse)
+{
+ const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
+ unsigned char *packet = psmouse->packet;
+
+ /*
+ * check debounce first, it has the same signature in byte 0
+ * and byte 3 as PACKET_V3_HEAD.
+ */
+ if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
+ return PACKET_DEBOUNCE;
+
+ if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
+ return PACKET_V3_HEAD;
+
+ if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
+ return PACKET_V3_TAIL;
+
+ return PACKET_UNKNOWN;
+}
+
+static int elantech_packet_check_v4(struct psmouse *psmouse)
+{
+ unsigned char *packet = psmouse->packet;
+
+ if ((packet[0] & 0x0c) == 0x04 &&
+ (packet[3] & 0x1f) == 0x11)
+ return PACKET_V4_HEAD;
+
+ if ((packet[0] & 0x0c) == 0x04 &&
+ (packet[3] & 0x1f) == 0x12)
+ return PACKET_V4_MOTION;
+
+ if ((packet[0] & 0x0c) == 0x04 &&
+ (packet[3] & 0x1f) == 0x10)
+ return PACKET_V4_STATUS;
+
+ return PACKET_UNKNOWN;
+}
+
/*
* Process byte stream from mouse and handle complete packets
*/
static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
{
struct elantech_data *etd = psmouse->private;
+ int packet_type;
if (psmouse->pktcnt < psmouse->pktsize)
return PSMOUSE_GOOD_DATA;
if (etd->debug > 1)
- elantech_packet_dump(psmouse->packet, psmouse->pktsize);
+ elantech_packet_dump(psmouse);
switch (etd->hw_version) {
case 1:
- if (etd->paritycheck && !elantech_check_parity_v1(psmouse))
+ if (etd->paritycheck && !elantech_packet_check_v1(psmouse))
return PSMOUSE_BAD_DATA;
elantech_report_absolute_v1(psmouse);
break;
case 2:
- /* We don't know how to check parity in protocol v2 */
+ /* ignore debounce */
+ if (elantech_debounce_check_v2(psmouse))
+ return PSMOUSE_FULL_PACKET;
+
+ if (etd->paritycheck && !elantech_packet_check_v2(psmouse))
+ return PSMOUSE_BAD_DATA;
+
elantech_report_absolute_v2(psmouse);
break;
+
+ case 3:
+ packet_type = elantech_packet_check_v3(psmouse);
+ /* ignore debounce */
+ if (packet_type == PACKET_DEBOUNCE)
+ return PSMOUSE_FULL_PACKET;
+
+ if (packet_type == PACKET_UNKNOWN)
+ return PSMOUSE_BAD_DATA;
+
+ elantech_report_absolute_v3(psmouse, packet_type);
+ break;
+
+ case 4:
+ packet_type = elantech_packet_check_v4(psmouse);
+ if (packet_type == PACKET_UNKNOWN)
+ return PSMOUSE_BAD_DATA;
+
+ elantech_report_absolute_v4(psmouse, packet_type);
+ break;
}
return PSMOUSE_FULL_PACKET;
@@ -435,15 +779,29 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
elantech_write_reg(psmouse, 0x11, etd->reg_11) ||
elantech_write_reg(psmouse, 0x21, etd->reg_21)) {
rc = -1;
- break;
}
+ break;
+
+ case 3:
+ etd->reg_10 = 0x0b;
+ if (elantech_write_reg(psmouse, 0x10, etd->reg_10))
+ rc = -1;
+
+ break;
+
+ case 4:
+ etd->reg_07 = 0x01;
+ if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
+ rc = -1;
+
+ goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */
}
if (rc == 0) {
/*
* Read back reg 0x10. For hardware version 1 we must make
* sure the absolute mode bit is set. For hardware version 2
- * the touchpad is probably initalising and not ready until
+ * the touchpad is probably initializing and not ready until
* we read back the value we just wrote.
*/
do {
@@ -456,27 +814,115 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
} while (tries > 0);
if (rc) {
- pr_err("failed to read back register 0x10.\n");
+ psmouse_err(psmouse,
+ "failed to read back register 0x10.\n");
} else if (etd->hw_version == 1 &&
!(val & ETP_R10_ABSOLUTE_MODE)) {
- pr_err("touchpad refuses to switch to absolute mode.\n");
+ psmouse_err(psmouse,
+ "touchpad refuses to switch to absolute mode.\n");
rc = -1;
}
}
+ skip_readback_reg_10:
if (rc)
- pr_err("failed to initialise registers.\n");
+ psmouse_err(psmouse, "failed to initialise registers.\n");
return rc;
}
+static int elantech_set_range(struct psmouse *psmouse,
+ unsigned int *x_min, unsigned int *y_min,
+ unsigned int *x_max, unsigned int *y_max,
+ unsigned int *width)
+{
+ struct elantech_data *etd = psmouse->private;
+ unsigned char param[3];
+ unsigned char traces;
+
+ switch (etd->hw_version) {
+ case 1:
+ *x_min = ETP_XMIN_V1;
+ *y_min = ETP_YMIN_V1;
+ *x_max = ETP_XMAX_V1;
+ *y_max = ETP_YMAX_V1;
+ break;
+
+ case 2:
+ if (etd->fw_version == 0x020800 ||
+ etd->fw_version == 0x020b00 ||
+ etd->fw_version == 0x020030) {
+ *x_min = ETP_XMIN_V2;
+ *y_min = ETP_YMIN_V2;
+ *x_max = ETP_XMAX_V2;
+ *y_max = ETP_YMAX_V2;
+ } else {
+ int i;
+ int fixed_dpi;
+
+ i = (etd->fw_version > 0x020800 &&
+ etd->fw_version < 0x020900) ? 1 : 2;
+
+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+ return -1;
+
+ fixed_dpi = param[1] & 0x10;
+
+ if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) {
+ if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
+ return -1;
+
+ *x_max = (etd->capabilities[1] - i) * param[1] / 2;
+ *y_max = (etd->capabilities[2] - i) * param[2] / 2;
+ } else if (etd->fw_version == 0x040216) {
+ *x_max = 819;
+ *y_max = 405;
+ } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) {
+ *x_max = 900;
+ *y_max = 500;
+ } else {
+ *x_max = (etd->capabilities[1] - i) * 64;
+ *y_max = (etd->capabilities[2] - i) * 64;
+ }
+ }
+ break;
+
+ case 3:
+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+ return -1;
+
+ *x_max = (0x0f & param[0]) << 8 | param[1];
+ *y_max = (0xf0 & param[0]) << 4 | param[2];
+ break;
+
+ case 4:
+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+ return -1;
+
+ *x_max = (0x0f & param[0]) << 8 | param[1];
+ *y_max = (0xf0 & param[0]) << 4 | param[2];
+ traces = etd->capabilities[1];
+ if ((traces < 2) || (traces > *x_max))
+ return -1;
+
+ *width = *x_max / (traces - 1);
+ break;
+ }
+
+ return 0;
+}
+
/*
* Set the appropriate event bits for the input subsystem
*/
-static void elantech_set_input_params(struct psmouse *psmouse)
+static int elantech_set_input_params(struct psmouse *psmouse)
{
struct input_dev *dev = psmouse->dev;
struct elantech_data *etd = psmouse->private;
+ unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
+
+ if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
+ return -1;
__set_bit(EV_KEY, dev->evbit);
__set_bit(EV_ABS, dev->evbit);
@@ -494,30 +940,64 @@ static void elantech_set_input_params(struct psmouse *psmouse)
case 1:
/* Rocker button */
if (etd->fw_version < 0x020000 &&
- (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
+ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
__set_bit(BTN_FORWARD, dev->keybit);
__set_bit(BTN_BACK, dev->keybit);
}
- input_set_abs_params(dev, ABS_X, ETP_XMIN_V1, ETP_XMAX_V1, 0, 0);
- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V1, ETP_YMAX_V1, 0, 0);
+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
break;
case 2:
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
- input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0);
- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0);
+ __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
+ /* fall through */
+ case 3:
+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
if (etd->reports_pressure) {
input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
ETP_PMAX_V2, 0, 0);
input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
ETP_WMAX_V2, 0, 0);
}
- __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
input_mt_init_slots(dev, 2);
- input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0);
- input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+ break;
+
+ case 4:
+ __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+ /* For X to recognize me as touchpad. */
+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
+ /*
+ * range of pressure and width is the same as v2,
+ * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
+ */
+ input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
+ ETP_PMAX_V2, 0, 0);
+ input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
+ ETP_WMAX_V2, 0, 0);
+ /* Multitouch capable pad, up to 5 fingers. */
+ input_mt_init_slots(dev, ETP_MAX_FINGERS);
+ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+ input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
+ ETP_PMAX_V2, 0, 0);
+ /*
+ * The firmware reports how many trace lines the finger spans,
+ * convert to surface unit as Protocol-B requires.
+ */
+ input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0,
+ ETP_WMAX_V2 * width, 0, 0);
break;
}
+
+ etd->y_max = y_max;
+ etd->width = width;
+
+ return 0;
}
struct elantech_attr_data {
@@ -587,6 +1067,7 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse,
elantech_show_int_attr, \
elantech_set_int_attr)
+ELANTECH_INT_ATTR(reg_07, 0x07);
ELANTECH_INT_ATTR(reg_10, 0x10);
ELANTECH_INT_ATTR(reg_11, 0x11);
ELANTECH_INT_ATTR(reg_20, 0x20);
@@ -600,6 +1081,7 @@ ELANTECH_INT_ATTR(debug, 0);
ELANTECH_INT_ATTR(paritycheck, 0);
static struct attribute *elantech_attrs[] = {
+ &psmouse_attr_reg_07.dattr.attr,
&psmouse_attr_reg_10.dattr.attr,
&psmouse_attr_reg_11.dattr.attr,
&psmouse_attr_reg_20.dattr.attr,
@@ -651,7 +1133,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
- pr_debug("sending Elantech magic knock failed.\n");
+ psmouse_dbg(psmouse, "sending Elantech magic knock failed.\n");
return -1;
}
@@ -659,9 +1141,11 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
* Report this in case there are Elantech models that use a different
* set of magic numbers
*/
- if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) {
- pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
- param[0], param[1], param[2]);
+ if (param[0] != 0x3c || param[1] != 0x03 ||
+ (param[2] != 0xc8 && param[2] != 0x00)) {
+ psmouse_dbg(psmouse,
+ "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
+ param[0], param[1], param[2]);
return -1;
}
@@ -671,20 +1155,18 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
* to Elantech magic knock and there might be more.
*/
if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
- pr_debug("failed to query firmware version.\n");
+ psmouse_dbg(psmouse, "failed to query firmware version.\n");
return -1;
}
- pr_debug("Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
- param[0], param[1], param[2]);
+ psmouse_dbg(psmouse,
+ "Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
+ param[0], param[1], param[2]);
if (!elantech_is_signature_valid(param)) {
- if (!force_elantech) {
- pr_debug("Probably not a real Elantech touchpad. Aborting.\n");
- return -1;
- }
-
- pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n");
+ psmouse_dbg(psmouse,
+ "Probably not a real Elantech touchpad. Aborting.\n");
+ return -1;
}
if (set_properties) {
@@ -715,7 +1197,8 @@ static int elantech_reconnect(struct psmouse *psmouse)
return -1;
if (elantech_set_absolute_mode(psmouse)) {
- pr_err("failed to put touchpad back into absolute mode.\n");
+ psmouse_err(psmouse,
+ "failed to put touchpad back into absolute mode.\n");
return -1;
}
@@ -723,6 +1206,48 @@ static int elantech_reconnect(struct psmouse *psmouse)
}
/*
+ * determine hardware version and set some properties according to it.
+ */
+static int elantech_set_properties(struct elantech_data *etd)
+{
+ int ver = (etd->fw_version & 0x0f0000) >> 16;
+
+ if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
+ etd->hw_version = 1;
+ else if (etd->fw_version < 0x150600)
+ etd->hw_version = 2;
+ else if (ver == 5)
+ etd->hw_version = 3;
+ else if (ver == 6)
+ etd->hw_version = 4;
+ else
+ return -1;
+
+ /*
+ * Turn on packet checking by default.
+ */
+ etd->paritycheck = 1;
+
+ /*
+ * This firmware suffers from misreporting coordinates when
+ * a touch action starts causing the mouse cursor or scrolled page
+ * to jump. Enable a workaround.
+ */
+ etd->jumpy_cursor =
+ (etd->fw_version == 0x020022 || etd->fw_version == 0x020600);
+
+ if (etd->hw_version > 1) {
+ /* For now show extra debug information */
+ etd->debug = 1;
+
+ if (etd->fw_version >= 0x020800)
+ etd->reports_pressure = true;
+ }
+
+ return 0;
+}
+
+/*
* Initialize the touchpad and create sysfs entries
*/
int elantech_init(struct psmouse *psmouse)
@@ -743,70 +1268,53 @@ int elantech_init(struct psmouse *psmouse)
* Do the version query again so we can store the result
*/
if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
- pr_err("failed to query firmware version.\n");
+ psmouse_err(psmouse, "failed to query firmware version.\n");
goto init_fail;
}
-
etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
- /*
- * Assume every version greater than this is new EeePC style
- * hardware with 6 byte packets
- */
- if (etd->fw_version >= 0x020030) {
- etd->hw_version = 2;
- /* For now show extra debug information */
- etd->debug = 1;
- /* Don't know how to do parity checking for version 2 */
- etd->paritycheck = 0;
-
- if (etd->fw_version >= 0x020800)
- etd->reports_pressure = true;
-
- } else {
- etd->hw_version = 1;
- etd->paritycheck = 1;
- }
-
- pr_info("assuming hardware version %d, firmware version %d.%d.%d\n",
- etd->hw_version, param[0], param[1], param[2]);
-
- if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) {
- pr_err("failed to query capabilities.\n");
+ if (elantech_set_properties(etd)) {
+ psmouse_err(psmouse, "unknown hardware version, aborting...\n");
goto init_fail;
}
- pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
- param[0], param[1], param[2]);
- etd->capabilities = param[0];
+ psmouse_info(psmouse,
+ "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n",
+ etd->hw_version, param[0], param[1], param[2]);
- /*
- * This firmware suffers from misreporting coordinates when
- * a touch action starts causing the mouse cursor or scrolled page
- * to jump. Enable a workaround.
- */
- if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) {
- pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n");
- etd->jumpy_cursor = true;
+ if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY,
+ etd->capabilities)) {
+ psmouse_err(psmouse, "failed to query capabilities.\n");
+ goto init_fail;
}
+ psmouse_info(psmouse,
+ "Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
+ etd->capabilities[0], etd->capabilities[1],
+ etd->capabilities[2]);
if (elantech_set_absolute_mode(psmouse)) {
- pr_err("failed to put touchpad into absolute mode.\n");
+ psmouse_err(psmouse,
+ "failed to put touchpad into absolute mode.\n");
goto init_fail;
}
- elantech_set_input_params(psmouse);
+ if (elantech_set_input_params(psmouse)) {
+ psmouse_err(psmouse, "failed to query touchpad range.\n");
+ goto init_fail;
+ }
error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
&elantech_attr_group);
if (error) {
- pr_err("failed to create sysfs attributes, error: %d.\n", error);
+ psmouse_err(psmouse,
+ "failed to create sysfs attributes, error: %d.\n",
+ error);
goto init_fail;
}
psmouse->protocol_handler = elantech_process_byte;
psmouse->disconnect = elantech_disconnect;
psmouse->reconnect = elantech_reconnect;
- psmouse->pktsize = etd->hw_version == 2 ? 6 : 4;
+ psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
return 0;
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index fabb2b99615c..9e5f1aabea7e 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -16,14 +16,17 @@
/*
* Command values for Synaptics style queries
*/
+#define ETP_FW_ID_QUERY 0x00
#define ETP_FW_VERSION_QUERY 0x01
#define ETP_CAPABILITIES_QUERY 0x02
+#define ETP_SAMPLE_QUERY 0x03
/*
* Command values for register reading or writing
*/
#define ETP_REGISTER_READ 0x10
#define ETP_REGISTER_WRITE 0x11
+#define ETP_REGISTER_READWRITE 0x00
/*
* Hardware version 2 custom PS/2 command value
@@ -66,16 +69,13 @@
#define ETP_YMAX_V1 (384 - ETP_EDGE_FUZZ_V1)
/*
- * It seems the resolution for hardware version 2 doubled.
- * Hence the X and Y ranges are doubled too.
- * The bezel around the pad also appears to be smaller
+ * The resolution for older v2 hardware doubled.
+ * (newer v2's firmware provides command so we can query)
*/
-#define ETP_EDGE_FUZZ_V2 8
-
-#define ETP_XMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2)
-#define ETP_XMAX_V2 (1152 - ETP_EDGE_FUZZ_V2)
-#define ETP_YMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2)
-#define ETP_YMAX_V2 ( 768 - ETP_EDGE_FUZZ_V2)
+#define ETP_XMIN_V2 0
+#define ETP_XMAX_V2 1152
+#define ETP_YMIN_V2 0
+#define ETP_YMAX_V2 768
#define ETP_PMIN_V2 0
#define ETP_PMAX_V2 255
@@ -83,17 +83,37 @@
#define ETP_WMAX_V2 15
/*
- * For two finger touches the coordinate of each finger gets reported
- * separately but with reduced resolution.
+ * v3 hardware has 2 kinds of packet types,
+ * v4 hardware has 3.
+ */
+#define PACKET_UNKNOWN 0x01
+#define PACKET_DEBOUNCE 0x02
+#define PACKET_V3_HEAD 0x03
+#define PACKET_V3_TAIL 0x04
+#define PACKET_V4_HEAD 0x05
+#define PACKET_V4_MOTION 0x06
+#define PACKET_V4_STATUS 0x07
+
+/*
+ * track up to 5 fingers for v4 hardware
+ */
+#define ETP_MAX_FINGERS 5
+
+/*
+ * weight value for v4 hardware
*/
-#define ETP_2FT_FUZZ 4
+#define ETP_WEIGHT_VALUE 5
-#define ETP_2FT_XMIN ( 0 + ETP_2FT_FUZZ)
-#define ETP_2FT_XMAX (288 - ETP_2FT_FUZZ)
-#define ETP_2FT_YMIN ( 0 + ETP_2FT_FUZZ)
-#define ETP_2FT_YMAX (192 - ETP_2FT_FUZZ)
+/*
+ * The base position for one finger, v4 hardware
+ */
+struct finger_pos {
+ unsigned int x;
+ unsigned int y;
+};
struct elantech_data {
+ unsigned char reg_07;
unsigned char reg_10;
unsigned char reg_11;
unsigned char reg_20;
@@ -104,13 +124,16 @@ struct elantech_data {
unsigned char reg_25;
unsigned char reg_26;
unsigned char debug;
- unsigned char capabilities;
+ unsigned char capabilities[3];
bool paritycheck;
bool jumpy_cursor;
bool reports_pressure;
unsigned char hw_version;
unsigned int fw_version;
unsigned int single_finger_reports;
+ unsigned int y_max;
+ unsigned int width;
+ struct finger_pos mt[ETP_MAX_FINGERS];
unsigned char parity[256];
};
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
index 4d17d9f3320b..0470dd46b566 100644
--- a/drivers/input/mouse/hgpk.c
+++ b/drivers/input/mouse/hgpk.c
@@ -136,10 +136,10 @@ static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
/* discard if too big, or half that but > 4 times the prev delta */
if (avx > recalib_delta ||
(avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) {
- hgpk_err(psmouse, "detected %dpx jump in x\n", x);
+ psmouse_warn(psmouse, "detected %dpx jump in x\n", x);
priv->xbigj = avx;
} else if (approx_half(avx, priv->xbigj)) {
- hgpk_err(psmouse, "detected secondary %dpx jump in x\n", x);
+ psmouse_warn(psmouse, "detected secondary %dpx jump in x\n", x);
priv->xbigj = avx;
priv->xsaw_secondary++;
} else {
@@ -151,10 +151,10 @@ static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
if (avy > recalib_delta ||
(avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
- hgpk_err(psmouse, "detected %dpx jump in y\n", y);
+ psmouse_warn(psmouse, "detected %dpx jump in y\n", y);
priv->ybigj = avy;
} else if (approx_half(avy, priv->ybigj)) {
- hgpk_err(psmouse, "detected secondary %dpx jump in y\n", y);
+ psmouse_warn(psmouse, "detected secondary %dpx jump in y\n", y);
priv->ybigj = avy;
priv->ysaw_secondary++;
} else {
@@ -168,7 +168,7 @@ static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
priv->ylast = avy;
if (do_recal && jumpy_delay) {
- hgpk_err(psmouse, "scheduling recalibration\n");
+ psmouse_warn(psmouse, "scheduling recalibration\n");
psmouse_queue_work(psmouse, &priv->recalib_wq,
msecs_to_jiffies(jumpy_delay));
}
@@ -260,8 +260,8 @@ static void hgpk_spewing_hack(struct psmouse *psmouse,
* movement, it is probably a case of the user moving the
* cursor very slowly across the screen. */
if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
- hgpk_err(psmouse, "packet spew detected (%d,%d)\n",
- priv->x_tally, priv->y_tally);
+ psmouse_warn(psmouse, "packet spew detected (%d,%d)\n",
+ priv->x_tally, priv->y_tally);
priv->spew_flag = RECALIBRATING;
psmouse_queue_work(psmouse, &priv->recalib_wq,
msecs_to_jiffies(spew_delay));
@@ -333,12 +333,12 @@ static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet)
}
if (!valid)
- hgpk_dbg(psmouse,
- "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n",
- priv->mode, pktcnt,
- psmouse->packet[0], psmouse->packet[1],
- psmouse->packet[2], psmouse->packet[3],
- psmouse->packet[4], psmouse->packet[5]);
+ psmouse_dbg(psmouse,
+ "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n",
+ priv->mode, pktcnt,
+ psmouse->packet[0], psmouse->packet[1],
+ psmouse->packet[2], psmouse->packet[3],
+ psmouse->packet[4], psmouse->packet[5]);
return valid;
}
@@ -361,19 +361,20 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse)
input_report_abs(idev, ABS_PRESSURE, z);
if (tpdebug)
- hgpk_dbg(psmouse, "pd=%d fd=%d z=%d",
- pt_down, finger_down, z);
+ psmouse_dbg(psmouse, "pd=%d fd=%d z=%d",
+ pt_down, finger_down, z);
} else {
/*
* PenTablet mode does not report pressure, so we don't
* report it here
*/
if (tpdebug)
- hgpk_dbg(psmouse, "pd=%d ", down);
+ psmouse_dbg(psmouse, "pd=%d ", down);
}
if (tpdebug)
- hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
+ psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
+ left, right, x, y);
input_report_key(idev, BTN_TOUCH, down);
input_report_key(idev, BTN_LEFT, left);
@@ -395,7 +396,7 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse)
if (x == priv->abs_x && y == priv->abs_y) {
if (++priv->dupe_count > SPEW_WATCH_COUNT) {
if (tpdebug)
- hgpk_dbg(psmouse, "hard spew detected\n");
+ psmouse_dbg(psmouse, "hard spew detected\n");
priv->spew_flag = RECALIBRATING;
psmouse_queue_work(psmouse, &priv->recalib_wq,
msecs_to_jiffies(spew_delay));
@@ -412,7 +413,7 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse)
int y_diff = priv->abs_y - y;
if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) {
if (tpdebug)
- hgpk_dbg(psmouse, "discarding\n");
+ psmouse_dbg(psmouse, "discarding\n");
goto done;
}
hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff);
@@ -437,20 +438,21 @@ static void hgpk_process_simple_packet(struct psmouse *psmouse)
int y = ((packet[0] << 3) & 0x100) - packet[2];
if (packet[0] & 0xc0)
- hgpk_dbg(psmouse,
- "overflow -- 0x%02x 0x%02x 0x%02x\n",
- packet[0], packet[1], packet[2]);
+ psmouse_dbg(psmouse,
+ "overflow -- 0x%02x 0x%02x 0x%02x\n",
+ packet[0], packet[1], packet[2]);
if (hgpk_discard_decay_hack(psmouse, x, y)) {
if (tpdebug)
- hgpk_dbg(psmouse, "discarding\n");
+ psmouse_dbg(psmouse, "discarding\n");
return;
}
hgpk_spewing_hack(psmouse, left, right, x, y);
if (tpdebug)
- hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
+ psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
+ left, right, x, y);
input_report_key(dev, BTN_LEFT, left);
input_report_key(dev, BTN_RIGHT, right);
@@ -482,9 +484,8 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse)
* ugh, got a packet inside our recalibration
* window, schedule another recalibration.
*/
- hgpk_dbg(psmouse,
- "packet inside calibration window, "
- "queueing another recalibration\n");
+ psmouse_dbg(psmouse,
+ "packet inside calibration window, queueing another recalibration\n");
psmouse_queue_work(psmouse, &priv->recalib_wq,
msecs_to_jiffies(post_interrupt_delay));
}
@@ -628,7 +629,7 @@ static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate)
err = hgpk_select_mode(psmouse);
if (err) {
- hgpk_err(psmouse, "failed to select mode\n");
+ psmouse_err(psmouse, "failed to select mode\n");
return err;
}
@@ -648,11 +649,11 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse)
return 0;
if (!autorecal) {
- hgpk_dbg(psmouse, "recalibrations disabled, ignoring\n");
+ psmouse_dbg(psmouse, "recalibration disabled, ignoring\n");
return 0;
}
- hgpk_dbg(psmouse, "recalibrating touchpad..\n");
+ psmouse_dbg(psmouse, "recalibrating touchpad..\n");
/* we don't want to race with the irq handler, nor with resyncs */
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
@@ -675,7 +676,7 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse)
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
if (tpdebug)
- hgpk_dbg(psmouse, "touchpad reactivated\n");
+ psmouse_dbg(psmouse, "touchpad reactivated\n");
/*
* If we get packets right away after recalibrating, it's likely
@@ -727,16 +728,16 @@ static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable)
err = hgpk_reset_device(psmouse, false);
if (err) {
- hgpk_err(psmouse, "Failed to reset device!\n");
+ psmouse_err(psmouse, "Failed to reset device!\n");
return err;
}
/* should be all set, enable the touchpad */
ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
- hgpk_dbg(psmouse, "Touchpad powered up.\n");
+ psmouse_dbg(psmouse, "Touchpad powered up.\n");
} else {
- hgpk_dbg(psmouse, "Powering off touchpad.\n");
+ psmouse_dbg(psmouse, "Powering off touchpad.\n");
if (ps2_command(ps2dev, NULL, 0xec) ||
ps2_command(ps2dev, NULL, 0xec) ||
@@ -923,7 +924,7 @@ static void hgpk_recalib_work(struct work_struct *work)
struct psmouse *psmouse = priv->psmouse;
if (hgpk_force_recalibrate(psmouse))
- hgpk_err(psmouse, "recalibration failed!\n");
+ psmouse_err(psmouse, "recalibration failed!\n");
}
static int hgpk_register(struct psmouse *psmouse)
@@ -947,14 +948,15 @@ static int hgpk_register(struct psmouse *psmouse)
err = device_create_file(&psmouse->ps2dev.serio->dev,
&psmouse_attr_powered.dattr);
if (err) {
- hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n");
+ psmouse_err(psmouse, "Failed creating 'powered' sysfs node\n");
return err;
}
err = device_create_file(&psmouse->ps2dev.serio->dev,
&psmouse_attr_hgpk_mode.dattr);
if (err) {
- hgpk_err(psmouse, "Failed creating 'hgpk_mode' sysfs node\n");
+ psmouse_err(psmouse,
+ "Failed creating 'hgpk_mode' sysfs node\n");
goto err_remove_powered;
}
@@ -963,8 +965,8 @@ static int hgpk_register(struct psmouse *psmouse)
err = device_create_file(&psmouse->ps2dev.serio->dev,
&psmouse_attr_recalibrate.dattr);
if (err) {
- hgpk_err(psmouse,
- "Failed creating 'recalibrate' sysfs node\n");
+ psmouse_err(psmouse,
+ "Failed creating 'recalibrate' sysfs node\n");
goto err_remove_mode;
}
}
@@ -1027,13 +1029,13 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse)
return -EIO;
}
- hgpk_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
+ psmouse_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
/* HGPK signature: 0x67, 0x00, 0x<model> */
if (param[0] != 0x67 || param[1] != 0x00)
return -ENODEV;
- hgpk_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
+ psmouse_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
return param[2];
}
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h
index 311c0e87fcbf..dd686771cfe0 100644
--- a/drivers/input/mouse/hgpk.h
+++ b/drivers/input/mouse/hgpk.h
@@ -46,17 +46,6 @@ struct hgpk_data {
int xsaw_secondary, ysaw_secondary; /* jumpiness detection */
};
-#define hgpk_dbg(psmouse, format, arg...) \
- dev_dbg(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_err(psmouse, format, arg...) \
- dev_err(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_info(psmouse, format, arg...) \
- dev_info(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_warn(psmouse, format, arg...) \
- dev_warn(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_notice(psmouse, format, arg...) \
- dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-
#ifdef CONFIG_MOUSE_PS2_OLPC
void hgpk_module_init(void);
int hgpk_detect(struct psmouse *psmouse, bool set_properties);
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 83bcaba96b89..2c4db636de6c 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -169,8 +169,8 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
if (relative_packet) {
if (!dev2)
- printk(KERN_WARNING "lifebook.c: got relative packet "
- "but no relative device set up\n");
+ psmouse_warn(psmouse,
+ "got relative packet but no relative device set up\n");
} else {
if (lifebook_use_6byte_proto) {
input_report_abs(dev1, ABS_X,
@@ -212,7 +212,7 @@ static int lifebook_absolute_mode(struct psmouse *psmouse)
/*
* Enable absolute output -- ps2_command fails always but if
- * you leave this call out the touchsreen will never send
+ * you leave this call out the touchscreen will never send
* absolute coordinates
*/
param = lifebook_use_6byte_proto ? 0x08 : 0x07;
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index c9983aee9082..faac2c3bef74 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -82,11 +82,11 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse)
packet[0] = packet[2] | 0x08;
break;
-#ifdef DEBUG
default:
- printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n",
- (packet[1] >> 4) | (packet[0] & 0x30));
-#endif
+ psmouse_dbg(psmouse,
+ "Received PS2++ packet #%x, but don't know how to handle.\n",
+ (packet[1] >> 4) | (packet[0] & 0x30));
+ break;
}
} else {
/* Standard PS/2 motion data */
@@ -382,7 +382,7 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties)
}
} else {
- printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model);
+ psmouse_warn(psmouse, "Detected unknown Logitech mouse model %d\n", model);
}
if (set_properties) {
@@ -400,9 +400,9 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties)
error = device_create_file(&psmouse->ps2dev.serio->dev,
&psmouse_attr_smartscroll.dattr);
if (error) {
- printk(KERN_ERR
- "logips2pp.c: failed to create smartscroll "
- "sysfs attribute, error: %d\n", error);
+ psmouse_err(psmouse,
+ "failed to create smartscroll sysfs attribute, error: %d\n",
+ error);
return -1;
}
}
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 3f74baee102b..9f352fbd7b4f 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -11,6 +11,9 @@
* the Free Software Foundation.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define psmouse_fmt(fmt) fmt
+
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -251,11 +254,14 @@ static int psmouse_handle_byte(struct psmouse *psmouse)
switch (rc) {
case PSMOUSE_BAD_DATA:
if (psmouse->state == PSMOUSE_ACTIVATED) {
- printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
- psmouse->name, psmouse->phys, psmouse->pktcnt);
+ psmouse_warn(psmouse,
+ "%s at %s lost sync at byte %d\n",
+ psmouse->name, psmouse->phys,
+ psmouse->pktcnt);
if (++psmouse->out_of_sync_cnt == psmouse->resetafter) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
+ psmouse_notice(psmouse,
+ "issuing reconnect request\n");
serio_reconnect(psmouse->ps2dev.serio);
return -1;
}
@@ -267,8 +273,9 @@ static int psmouse_handle_byte(struct psmouse *psmouse)
psmouse->pktcnt = 0;
if (psmouse->out_of_sync_cnt) {
psmouse->out_of_sync_cnt = 0;
- printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
- psmouse->name, psmouse->phys);
+ psmouse_notice(psmouse,
+ "%s at %s - driver resynced.\n",
+ psmouse->name, psmouse->phys);
}
break;
@@ -295,9 +302,10 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
((flags & SERIO_PARITY) && !psmouse->ignore_parity))) {
if (psmouse->state == PSMOUSE_ACTIVATED)
- printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
- flags & SERIO_TIMEOUT ? " timeout" : "",
- flags & SERIO_PARITY ? " bad parity" : "");
+ psmouse_warn(psmouse,
+ "bad data from KBC -%s%s\n",
+ flags & SERIO_TIMEOUT ? " timeout" : "",
+ flags & SERIO_PARITY ? " bad parity" : "");
ps2_cmd_aborted(&psmouse->ps2dev);
goto out;
}
@@ -315,8 +323,8 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if (psmouse->state == PSMOUSE_ACTIVATED &&
psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
- printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
- psmouse->name, psmouse->phys, psmouse->pktcnt);
+ psmouse_info(psmouse, "%s at %s lost synchronization, throwing %d bytes away.\n",
+ psmouse->name, psmouse->phys, psmouse->pktcnt);
psmouse->badbyte = psmouse->packet[0];
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
@@ -943,7 +951,8 @@ static int psmouse_probe(struct psmouse *psmouse)
*/
if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS))
- printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", ps2dev->serio->phys);
+ psmouse_warn(psmouse, "Failed to reset mouse on %s\n",
+ ps2dev->serio->phys);
return 0;
}
@@ -1005,8 +1014,8 @@ static void psmouse_initialize(struct psmouse *psmouse)
static void psmouse_activate(struct psmouse *psmouse)
{
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE))
- printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n",
- psmouse->ps2dev.serio->phys);
+ psmouse_warn(psmouse, "Failed to enable mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
}
@@ -1020,14 +1029,14 @@ static void psmouse_activate(struct psmouse *psmouse)
static void psmouse_deactivate(struct psmouse *psmouse)
{
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
- printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n",
- psmouse->ps2dev.serio->phys);
+ psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
}
/*
- * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it.
+ * psmouse_poll() - default poll handler. Everyone except for ALPS uses it.
*/
static int psmouse_poll(struct psmouse *psmouse)
@@ -1115,14 +1124,15 @@ static void psmouse_resync(struct work_struct *work)
}
if (!enabled) {
- printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n",
- psmouse->ps2dev.serio->phys);
+ psmouse_warn(psmouse, "failed to re-enable mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
failed = true;
}
if (failed) {
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n");
+ psmouse_info(psmouse,
+ "resync failed, issuing reconnect request\n");
serio_reconnect(serio);
} else
psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
@@ -1155,8 +1165,8 @@ static void psmouse_cleanup(struct serio *serio)
* Disable stream mode so cleanup routine can proceed undisturbed.
*/
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
- printk(KERN_WARNING "psmouse.c: Failed to disable mouse on %s\n",
- psmouse->ps2dev.serio->phys);
+ psmouse_warn(psmouse, "Failed to disable mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
if (psmouse->cleanup)
psmouse->cleanup(psmouse);
@@ -1400,7 +1410,8 @@ static int psmouse_reconnect(struct serio *serio)
int rc = -1;
if (!drv || !psmouse) {
- printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
+ psmouse_dbg(psmouse,
+ "reconnect request, but serio is disconnected, ignoring...\n");
return -1;
}
@@ -1427,8 +1438,9 @@ static int psmouse_reconnect(struct serio *serio)
goto out;
}
- /* ok, the device type (and capabilities) match the old one,
- * we can continue using it, complete intialization
+ /*
+ * OK, the device type (and capabilities) match the old one,
+ * we can continue using it, complete initialization
*/
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
@@ -1586,9 +1598,8 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
while (!list_empty(&serio->children)) {
if (++retry > 3) {
- printk(KERN_WARNING
- "psmouse: failed to destroy children ports, "
- "protocol change aborted.\n");
+ psmouse_warn(psmouse,
+ "failed to destroy children ports, protocol change aborted.\n");
input_free_device(new_dev);
return -EIO;
}
@@ -1715,7 +1726,7 @@ static int __init psmouse_init(void)
kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
if (!kpsmoused_wq) {
- printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
+ pr_err("failed to create kpsmoused workqueue\n");
return -ENOMEM;
}
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 593e910bfc7a..9b84b0c4e371 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -150,4 +150,29 @@ static struct psmouse_attribute psmouse_attr_##_name = { \
static ssize_t _set(struct psmouse *, void *, const char *, size_t); \
__PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true)
+#ifndef psmouse_fmt
+#define psmouse_fmt(fmt) KBUILD_BASENAME ": " fmt
+#endif
+
+#define psmouse_dbg(psmouse, format, ...) \
+ dev_dbg(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_info(psmouse, format, ...) \
+ dev_info(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_warn(psmouse, format, ...) \
+ dev_warn(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_err(psmouse, format, ...) \
+ dev_err(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_notice(psmouse, format, ...) \
+ dev_notice(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_printk(level, psmouse, format, ...) \
+ dev_printk(level, \
+ &(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+
+
#endif /* _PSMOUSE_H */
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c
index 6c5d84fcdea1..ee3b0ca9d592 100644
--- a/drivers/input/mouse/pxa930_trkball.c
+++ b/drivers/input/mouse/pxa930_trkball.c
@@ -183,7 +183,7 @@ static int __devinit pxa930_trkball_probe(struct platform_device *pdev)
/* held the module in reset, will be enabled in open() */
pxa930_trkball_disable(trkball);
- error = request_irq(irq, pxa930_trkball_interrupt, IRQF_DISABLED,
+ error = request_irq(irq, pxa930_trkball_interrupt, 0,
pdev->name, trkball);
if (error) {
dev_err(&pdev->dev, "failed to request irq: %d\n", error);
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c
index 2fc887a51066..c5b12d2e955a 100644
--- a/drivers/input/mouse/sentelic.c
+++ b/drivers/input/mouse/sentelic.c
@@ -607,11 +607,12 @@ static void fsp_packet_debug(unsigned char packet[])
ps2_packet_cnt++;
jiffies_msec = jiffies_to_msecs(jiffies);
- printk(KERN_DEBUG "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n",
- jiffies_msec, packet[0], packet[1], packet[2], packet[3]);
+ psmouse_dbg(psmouse,
+ "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n",
+ jiffies_msec, packet[0], packet[1], packet[2], packet[3]);
if (jiffies_msec - ps2_last_second > 1000) {
- printk(KERN_DEBUG "PS/2 packets/sec = %d\n", ps2_packet_cnt);
+ psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt);
ps2_packet_cnt = 0;
ps2_last_second = jiffies_msec;
}
@@ -820,9 +821,9 @@ int fsp_init(struct psmouse *psmouse)
return -ENODEV;
}
- printk(KERN_INFO
- "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n",
- ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7);
+ psmouse_info(psmouse,
+ "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n",
+ ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7);
psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL);
if (!priv)
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 5538fc657af1..c080b828e5dc 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -44,6 +44,16 @@
#define YMIN_NOMINAL 1408
#define YMAX_NOMINAL 4448
+/*
+ * Synaptics touchpads report the y coordinate from bottom to top, which is
+ * opposite from what userspace expects.
+ * This function is used to invert y before reporting.
+ */
+static int synaptics_invert_y(int y)
+{
+ return YMAX_NOMINAL + YMIN_NOMINAL - y;
+}
+
/*****************************************************************************
* Stuff we need even when we do not want native Synaptics support
@@ -157,8 +167,8 @@ static int synaptics_capability(struct psmouse *psmouse)
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
- printk(KERN_ERR "Synaptics claims to have extended capabilities,"
- " but I'm not able to read them.\n");
+ psmouse_warn(psmouse,
+ "device claims to have extended capabilities, but I'm not able to read them.\n");
} else {
priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
@@ -173,8 +183,8 @@ static int synaptics_capability(struct psmouse *psmouse)
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) {
- printk(KERN_ERR "Synaptics claims to have extended capability 0x0c,"
- " but I'm not able to read it.\n");
+ psmouse_warn(psmouse,
+ "device claims to have extended capability 0x0c, but I'm not able to read it.\n");
} else {
priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2];
}
@@ -222,8 +232,8 @@ static int synaptics_resolution(struct psmouse *psmouse)
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
- printk(KERN_ERR "Synaptics claims to have max coordinates"
- " query, but I'm not able to read it.\n");
+ psmouse_warn(psmouse,
+ "device claims to have max coordinates query, but I'm not able to read it.\n");
} else {
priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
@@ -233,8 +243,8 @@ static int synaptics_resolution(struct psmouse *psmouse)
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
- printk(KERN_ERR "Synaptics claims to have min coordinates"
- " query, but I'm not able to read it.\n");
+ psmouse_warn(psmouse,
+ "device claims to have min coordinates query, but I'm not able to read it.\n");
} else {
priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
@@ -294,7 +304,8 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
static unsigned char param = 0xc8;
struct synaptics_data *priv = psmouse->private;
- if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
+ if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
return 0;
if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
@@ -377,7 +388,8 @@ static void synaptics_pt_activate(struct psmouse *psmouse)
priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT;
if (synaptics_mode_cmd(psmouse, priv->mode))
- printk(KERN_INFO "synaptics: failed to switch guest protocol\n");
+ psmouse_warn(psmouse,
+ "failed to switch guest protocol\n");
}
}
@@ -387,7 +399,8 @@ static void synaptics_pt_create(struct psmouse *psmouse)
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio) {
- printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
+ psmouse_err(psmouse,
+ "not enough memory for pass-through port\n");
return;
}
@@ -401,7 +414,8 @@ static void synaptics_pt_create(struct psmouse *psmouse)
psmouse->pt_activate = synaptics_pt_activate;
- printk(KERN_INFO "serio: %s port at %s\n", serio->name, psmouse->phys);
+ psmouse_info(psmouse, "serio: %s port at %s\n",
+ serio->name, psmouse->phys);
serio_register_port(serio);
}
@@ -409,6 +423,44 @@ static void synaptics_pt_create(struct psmouse *psmouse)
* Functions to interpret the absolute mode packets
****************************************************************************/
+static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count,
+ int sgm, int agm)
+{
+ state->count = count;
+ state->sgm = sgm;
+ state->agm = agm;
+}
+
+static void synaptics_parse_agm(const unsigned char buf[],
+ struct synaptics_data *priv,
+ struct synaptics_hw_state *hw)
+{
+ struct synaptics_hw_state *agm = &priv->agm;
+ int agm_packet_type;
+
+ agm_packet_type = (buf[5] & 0x30) >> 4;
+ switch (agm_packet_type) {
+ case 1:
+ /* Gesture packet: (x, y, z) half resolution */
+ agm->w = hw->w;
+ agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
+ agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
+ agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+ break;
+
+ case 2:
+ /* AGM-CONTACT packet: (count, sgm, agm) */
+ synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Record that at least one AGM has been received since last SGM */
+ priv->agm_pending = true;
+}
+
static int synaptics_parse_hw_state(const unsigned char buf[],
struct synaptics_data *priv,
struct synaptics_hw_state *hw)
@@ -442,11 +494,10 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
}
- if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
- /* Gesture packet: (x, y, z) at half resolution */
- priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
- priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
- priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+ if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
+ hw->w == 2) {
+ synaptics_parse_agm(buf, priv, hw);
return 1;
}
@@ -502,8 +553,7 @@ static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot,
input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
if (active) {
input_report_abs(dev, ABS_MT_POSITION_X, x);
- input_report_abs(dev, ABS_MT_POSITION_Y,
- YMAX_NOMINAL + YMIN_NOMINAL - y);
+ input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y));
}
}
@@ -526,6 +576,388 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev,
}
}
+static void synaptics_report_buttons(struct psmouse *psmouse,
+ const struct synaptics_hw_state *hw)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct synaptics_data *priv = psmouse->private;
+ int i;
+
+ input_report_key(dev, BTN_LEFT, hw->left);
+ input_report_key(dev, BTN_RIGHT, hw->right);
+
+ if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
+ input_report_key(dev, BTN_MIDDLE, hw->middle);
+
+ if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
+ input_report_key(dev, BTN_FORWARD, hw->up);
+ input_report_key(dev, BTN_BACK, hw->down);
+ }
+
+ for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
+ input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i));
+}
+
+static void synaptics_report_slot(struct input_dev *dev, int slot,
+ const struct synaptics_hw_state *hw)
+{
+ input_mt_slot(dev, slot);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL));
+ if (!hw)
+ return;
+
+ input_report_abs(dev, ABS_MT_POSITION_X, hw->x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y));
+ input_report_abs(dev, ABS_MT_PRESSURE, hw->z);
+}
+
+static void synaptics_report_mt_data(struct psmouse *psmouse,
+ struct synaptics_mt_state *mt_state,
+ const struct synaptics_hw_state *sgm)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct synaptics_data *priv = psmouse->private;
+ struct synaptics_hw_state *agm = &priv->agm;
+ struct synaptics_mt_state *old = &priv->mt_state;
+
+ switch (mt_state->count) {
+ case 0:
+ synaptics_report_slot(dev, 0, NULL);
+ synaptics_report_slot(dev, 1, NULL);
+ break;
+ case 1:
+ if (mt_state->sgm == -1) {
+ synaptics_report_slot(dev, 0, NULL);
+ synaptics_report_slot(dev, 1, NULL);
+ } else if (mt_state->sgm == 0) {
+ synaptics_report_slot(dev, 0, sgm);
+ synaptics_report_slot(dev, 1, NULL);
+ } else {
+ synaptics_report_slot(dev, 0, NULL);
+ synaptics_report_slot(dev, 1, sgm);
+ }
+ break;
+ default:
+ /*
+ * If the finger slot contained in SGM is valid, and either
+ * hasn't changed, or is new, then report SGM in MTB slot 0.
+ * Otherwise, empty MTB slot 0.
+ */
+ if (mt_state->sgm != -1 &&
+ (mt_state->sgm == old->sgm || old->sgm == -1))
+ synaptics_report_slot(dev, 0, sgm);
+ else
+ synaptics_report_slot(dev, 0, NULL);
+
+ /*
+ * If the finger slot contained in AGM is valid, and either
+ * hasn't changed, or is new, then report AGM in MTB slot 1.
+ * Otherwise, empty MTB slot 1.
+ */
+ if (mt_state->agm != -1 &&
+ (mt_state->agm == old->agm || old->agm == -1))
+ synaptics_report_slot(dev, 1, agm);
+ else
+ synaptics_report_slot(dev, 1, NULL);
+ break;
+ }
+
+ /* Don't use active slot count to generate BTN_TOOL events. */
+ input_mt_report_pointer_emulation(dev, false);
+
+ /* Send the number of fingers reported by touchpad itself. */
+ input_mt_report_finger_count(dev, mt_state->count);
+
+ synaptics_report_buttons(psmouse, sgm);
+
+ input_sync(dev);
+}
+
+/* Handle case where mt_state->count = 0 */
+static void synaptics_image_sensor_0f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ synaptics_mt_state_set(mt_state, 0, -1, -1);
+ priv->mt_state_lost = false;
+}
+
+/* Handle case where mt_state->count = 1 */
+static void synaptics_image_sensor_1f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ struct synaptics_hw_state *agm = &priv->agm;
+ struct synaptics_mt_state *old = &priv->mt_state;
+
+ /*
+ * If the last AGM was (0,0,0), and there is only one finger left,
+ * then we absolutely know that SGM contains slot 0, and all other
+ * fingers have been removed.
+ */
+ if (priv->agm_pending && agm->z == 0) {
+ synaptics_mt_state_set(mt_state, 1, 0, -1);
+ priv->mt_state_lost = false;
+ return;
+ }
+
+ switch (old->count) {
+ case 0:
+ synaptics_mt_state_set(mt_state, 1, 0, -1);
+ break;
+ case 1:
+ /*
+ * If mt_state_lost, then the previous transition was 3->1,
+ * and SGM now contains either slot 0 or 1, but we don't know
+ * which. So, we just assume that the SGM now contains slot 1.
+ *
+ * If pending AGM and either:
+ * (a) the previous SGM slot contains slot 0, or
+ * (b) there was no SGM slot
+ * then, the SGM now contains slot 1
+ *
+ * Case (a) happens with very rapid "drum roll" gestures, where
+ * slot 0 finger is lifted and a new slot 1 finger touches
+ * within one reporting interval.
+ *
+ * Case (b) happens if initially two or more fingers tap
+ * briefly, and all but one lift before the end of the first
+ * reporting interval.
+ *
+ * (In both these cases, slot 0 will becomes empty, so SGM
+ * contains slot 1 with the new finger)
+ *
+ * Else, if there was no previous SGM, it now contains slot 0.
+ *
+ * Otherwise, SGM still contains the same slot.
+ */
+ if (priv->mt_state_lost ||
+ (priv->agm_pending && old->sgm <= 0))
+ synaptics_mt_state_set(mt_state, 1, 1, -1);
+ else if (old->sgm == -1)
+ synaptics_mt_state_set(mt_state, 1, 0, -1);
+ break;
+ case 2:
+ /*
+ * If mt_state_lost, we don't know which finger SGM contains.
+ *
+ * So, report 1 finger, but with both slots empty.
+ * We will use slot 1 on subsequent 1->1
+ */
+ if (priv->mt_state_lost) {
+ synaptics_mt_state_set(mt_state, 1, -1, -1);
+ break;
+ }
+ /*
+ * Since the last AGM was NOT (0,0,0), it was the finger in
+ * slot 0 that has been removed.
+ * So, SGM now contains previous AGM's slot, and AGM is now
+ * empty.
+ */
+ synaptics_mt_state_set(mt_state, 1, old->agm, -1);
+ break;
+ case 3:
+ /*
+ * Since last AGM was not (0,0,0), we don't know which finger
+ * is left.
+ *
+ * So, report 1 finger, but with both slots empty.
+ * We will use slot 1 on subsequent 1->1
+ */
+ synaptics_mt_state_set(mt_state, 1, -1, -1);
+ priv->mt_state_lost = true;
+ break;
+ case 4:
+ case 5:
+ /* mt_state was updated by AGM-CONTACT packet */
+ break;
+ }
+}
+
+/* Handle case where mt_state->count = 2 */
+static void synaptics_image_sensor_2f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ struct synaptics_mt_state *old = &priv->mt_state;
+
+ switch (old->count) {
+ case 0:
+ synaptics_mt_state_set(mt_state, 2, 0, 1);
+ break;
+ case 1:
+ /*
+ * If previous SGM contained slot 1 or higher, SGM now contains
+ * slot 0 (the newly touching finger) and AGM contains SGM's
+ * previous slot.
+ *
+ * Otherwise, SGM still contains slot 0 and AGM now contains
+ * slot 1.
+ */
+ if (old->sgm >= 1)
+ synaptics_mt_state_set(mt_state, 2, 0, old->sgm);
+ else
+ synaptics_mt_state_set(mt_state, 2, 0, 1);
+ break;
+ case 2:
+ /*
+ * If mt_state_lost, SGM now contains either finger 1 or 2, but
+ * we don't know which.
+ * So, we just assume that the SGM contains slot 0 and AGM 1.
+ */
+ if (priv->mt_state_lost)
+ synaptics_mt_state_set(mt_state, 2, 0, 1);
+ /*
+ * Otherwise, use the same mt_state, since it either hasn't
+ * changed, or was updated by a recently received AGM-CONTACT
+ * packet.
+ */
+ break;
+ case 3:
+ /*
+ * 3->2 transitions have two unsolvable problems:
+ * 1) no indication is given which finger was removed
+ * 2) no way to tell if agm packet was for finger 3
+ * before 3->2, or finger 2 after 3->2.
+ *
+ * So, report 2 fingers, but empty all slots.
+ * We will guess slots [0,1] on subsequent 2->2.
+ */
+ synaptics_mt_state_set(mt_state, 2, -1, -1);
+ priv->mt_state_lost = true;
+ break;
+ case 4:
+ case 5:
+ /* mt_state was updated by AGM-CONTACT packet */
+ break;
+ }
+}
+
+/* Handle case where mt_state->count = 3 */
+static void synaptics_image_sensor_3f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ struct synaptics_mt_state *old = &priv->mt_state;
+
+ switch (old->count) {
+ case 0:
+ synaptics_mt_state_set(mt_state, 3, 0, 2);
+ break;
+ case 1:
+ /*
+ * If previous SGM contained slot 2 or higher, SGM now contains
+ * slot 0 (one of the newly touching fingers) and AGM contains
+ * SGM's previous slot.
+ *
+ * Otherwise, SGM now contains slot 0 and AGM contains slot 2.
+ */
+ if (old->sgm >= 2)
+ synaptics_mt_state_set(mt_state, 3, 0, old->sgm);
+ else
+ synaptics_mt_state_set(mt_state, 3, 0, 2);
+ break;
+ case 2:
+ /*
+ * If the AGM previously contained slot 3 or higher, then the
+ * newly touching finger is in the lowest available slot.
+ *
+ * If SGM was previously 1 or higher, then the new SGM is
+ * now slot 0 (with a new finger), otherwise, the new finger
+ * is now in a hidden slot between 0 and AGM's slot.
+ *
+ * In all such cases, the SGM now contains slot 0, and the AGM
+ * continues to contain the same slot as before.
+ */
+ if (old->agm >= 3) {
+ synaptics_mt_state_set(mt_state, 3, 0, old->agm);
+ break;
+ }
+
+ /*
+ * After some 3->1 and all 3->2 transitions, we lose track
+ * of which slot is reported by SGM and AGM.
+ *
+ * For 2->3 in this state, report 3 fingers, but empty all
+ * slots, and we will guess (0,2) on a subsequent 0->3.
+ *
+ * To userspace, the resulting transition will look like:
+ * 2:[0,1] -> 3:[-1,-1] -> 3:[0,2]
+ */
+ if (priv->mt_state_lost) {
+ synaptics_mt_state_set(mt_state, 3, -1, -1);
+ break;
+ }
+
+ /*
+ * If the (SGM,AGM) really previously contained slots (0, 1),
+ * then we cannot know what slot was just reported by the AGM,
+ * because the 2->3 transition can occur either before or after
+ * the AGM packet. Thus, this most recent AGM could contain
+ * either the same old slot 1 or the new slot 2.
+ * Subsequent AGMs will be reporting slot 2.
+ *
+ * To userspace, the resulting transition will look like:
+ * 2:[0,1] -> 3:[0,-1] -> 3:[0,2]
+ */
+ synaptics_mt_state_set(mt_state, 3, 0, -1);
+ break;
+ case 3:
+ /*
+ * If, for whatever reason, the previous agm was invalid,
+ * Assume SGM now contains slot 0, AGM now contains slot 2.
+ */
+ if (old->agm <= 2)
+ synaptics_mt_state_set(mt_state, 3, 0, 2);
+ /*
+ * mt_state either hasn't changed, or was updated by a recently
+ * received AGM-CONTACT packet.
+ */
+ break;
+
+ case 4:
+ case 5:
+ /* mt_state was updated by AGM-CONTACT packet */
+ break;
+ }
+}
+
+/* Handle case where mt_state->count = 4, or = 5 */
+static void synaptics_image_sensor_45f(struct synaptics_data *priv,
+ struct synaptics_mt_state *mt_state)
+{
+ /* mt_state was updated correctly by AGM-CONTACT packet */
+ priv->mt_state_lost = false;
+}
+
+static void synaptics_image_sensor_process(struct psmouse *psmouse,
+ struct synaptics_hw_state *sgm)
+{
+ struct synaptics_data *priv = psmouse->private;
+ struct synaptics_hw_state *agm = &priv->agm;
+ struct synaptics_mt_state mt_state;
+
+ /* Initialize using current mt_state (as updated by last agm) */
+ mt_state = agm->mt_state;
+
+ /*
+ * Update mt_state using the new finger count and current mt_state.
+ */
+ if (sgm->z == 0)
+ synaptics_image_sensor_0f(priv, &mt_state);
+ else if (sgm->w >= 4)
+ synaptics_image_sensor_1f(priv, &mt_state);
+ else if (sgm->w == 0)
+ synaptics_image_sensor_2f(priv, &mt_state);
+ else if (sgm->w == 1 && mt_state.count <= 3)
+ synaptics_image_sensor_3f(priv, &mt_state);
+ else
+ synaptics_image_sensor_45f(priv, &mt_state);
+
+ /* Send resulting input events to user space */
+ synaptics_report_mt_data(psmouse, &mt_state, sgm);
+
+ /* Store updated mt_state */
+ priv->mt_state = agm->mt_state = mt_state;
+ priv->agm_pending = false;
+}
+
/*
* called for each full received packet from the touchpad
*/
@@ -536,11 +968,15 @@ static void synaptics_process_packet(struct psmouse *psmouse)
struct synaptics_hw_state hw;
int num_fingers;
int finger_width;
- int i;
if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
return;
+ if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
+ synaptics_image_sensor_process(psmouse, &hw);
+ return;
+ }
+
if (hw.scroll) {
priv->scroll += hw.scroll;
@@ -586,7 +1022,8 @@ static void synaptics_process_packet(struct psmouse *psmouse)
}
if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
- synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers);
+ synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
+ num_fingers);
/* Post events
* BTN_TOUCH has to be first as mousedev relies on it when doing
@@ -597,7 +1034,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
if (num_fingers > 0) {
input_report_abs(dev, ABS_X, hw.x);
- input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
+ input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y));
}
input_report_abs(dev, ABS_PRESSURE, hw.z);
@@ -605,35 +1042,25 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
- input_report_key(dev, BTN_LEFT, hw.left);
- input_report_key(dev, BTN_RIGHT, hw.right);
-
if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
}
- if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
- input_report_key(dev, BTN_MIDDLE, hw.middle);
-
- if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
- input_report_key(dev, BTN_FORWARD, hw.up);
- input_report_key(dev, BTN_BACK, hw.down);
- }
-
- for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
- input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i));
+ synaptics_report_buttons(psmouse, &hw);
input_sync(dev);
}
-static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type)
+static int synaptics_validate_byte(struct psmouse *psmouse,
+ int idx, unsigned char pkt_type)
{
static const unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
static const unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
static const unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
static const unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
static const unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
+ const char *packet = psmouse->packet;
if (idx < 0 || idx > 4)
return 0;
@@ -651,7 +1078,7 @@ static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned cha
return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
default:
- printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type);
+ psmouse_err(psmouse, "unknown packet type %d\n", pkt_type);
return 0;
}
}
@@ -661,8 +1088,8 @@ static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
int i;
for (i = 0; i < 5; i++)
- if (!synaptics_validate_byte(psmouse->packet, i, SYN_NEWABS_STRICT)) {
- printk(KERN_INFO "synaptics: using relaxed packet validation\n");
+ if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) {
+ psmouse_info(psmouse, "using relaxed packet validation\n");
return SYN_NEWABS_RELAXED;
}
@@ -687,46 +1114,56 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
return PSMOUSE_FULL_PACKET;
}
- return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ?
+ return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ?
PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
}
/*****************************************************************************
* Driver initialization/cleanup functions
****************************************************************************/
-static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
+static void set_abs_position_params(struct input_dev *dev,
+ struct synaptics_data *priv, int x_code,
+ int y_code)
{
- int i;
+ int x_min = priv->x_min ?: XMIN_NOMINAL;
+ int x_max = priv->x_max ?: XMAX_NOMINAL;
+ int y_min = priv->y_min ?: YMIN_NOMINAL;
+ int y_max = priv->y_max ?: YMAX_NOMINAL;
int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
SYN_REDUCED_FILTER_FUZZ : 0;
+ input_set_abs_params(dev, x_code, x_min, x_max, fuzz, 0);
+ input_set_abs_params(dev, y_code, y_min, y_max, fuzz, 0);
+ input_abs_set_res(dev, x_code, priv->x_res);
+ input_abs_set_res(dev, y_code, priv->y_res);
+}
+
+static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
+{
+ int i;
+
__set_bit(INPUT_PROP_POINTER, dev->propbit);
__set_bit(EV_ABS, dev->evbit);
- input_set_abs_params(dev, ABS_X,
- priv->x_min ?: XMIN_NOMINAL,
- priv->x_max ?: XMAX_NOMINAL,
- fuzz, 0);
- input_set_abs_params(dev, ABS_Y,
- priv->y_min ?: YMIN_NOMINAL,
- priv->y_max ?: YMAX_NOMINAL,
- fuzz, 0);
+ set_abs_position_params(dev, priv, ABS_X, ABS_Y);
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
- if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
+ if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
+ input_mt_init_slots(dev, 2);
+ set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
+ ABS_MT_POSITION_Y);
+ /* Image sensors can report per-contact pressure */
+ input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
+ /* Image sensors can signal 4 and 5 finger clicks */
+ __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+ __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
+ } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
+ /* Non-image sensors with AGM use semi-mt */
__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
input_mt_init_slots(dev, 2);
- input_set_abs_params(dev, ABS_MT_POSITION_X,
- priv->x_min ?: XMIN_NOMINAL,
- priv->x_max ?: XMAX_NOMINAL,
- fuzz, 0);
- input_set_abs_params(dev, ABS_MT_POSITION_Y,
- priv->y_min ?: YMIN_NOMINAL,
- priv->y_max ?: YMAX_NOMINAL,
- fuzz, 0);
-
- input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res);
- input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res);
+ set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
+ ABS_MT_POSITION_Y);
}
if (SYN_CAP_PALMDETECT(priv->capabilities))
@@ -759,9 +1196,6 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
__clear_bit(REL_X, dev->relbit);
__clear_bit(REL_Y, dev->relbit);
- input_abs_set_res(dev, ABS_X, priv->x_res);
- input_abs_set_res(dev, ABS_Y, priv->y_res);
-
if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
/* Clickpads report only left button */
@@ -793,21 +1227,21 @@ static int synaptics_reconnect(struct psmouse *psmouse)
return -1;
if (retry > 1)
- printk(KERN_DEBUG "Synaptics reconnected after %d tries\n",
- retry);
+ psmouse_dbg(psmouse, "reconnected after %d tries\n", retry);
if (synaptics_query_hardware(psmouse)) {
- printk(KERN_ERR "Unable to query Synaptics hardware.\n");
+ psmouse_err(psmouse, "Unable to query device.\n");
return -1;
}
if (synaptics_set_absolute_mode(psmouse)) {
- printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+ psmouse_err(psmouse, "Unable to initialize device.\n");
return -1;
}
if (synaptics_set_advanced_gesture_mode(psmouse)) {
- printk(KERN_ERR "Advanced gesture mode reconnect failed.\n");
+ psmouse_err(psmouse,
+ "Advanced gesture mode reconnect failed.\n");
return -1;
}
@@ -815,12 +1249,12 @@ static int synaptics_reconnect(struct psmouse *psmouse)
old_priv.model_id != priv->model_id ||
old_priv.capabilities != priv->capabilities ||
old_priv.ext_cap != priv->ext_cap) {
- printk(KERN_ERR "Synaptics hardware appears to be different: "
- "id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
- old_priv.identity, priv->identity,
- old_priv.model_id, priv->model_id,
- old_priv.capabilities, priv->capabilities,
- old_priv.ext_cap, priv->ext_cap);
+ psmouse_err(psmouse,
+ "hardware appears to be different: id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
+ old_priv.identity, priv->identity,
+ old_priv.model_id, priv->model_id,
+ old_priv.capabilities, priv->capabilities,
+ old_priv.ext_cap, priv->ext_cap);
return -1;
}
@@ -901,7 +1335,8 @@ int synaptics_init(struct psmouse *psmouse)
* just fine.
*/
if (broken_olpc_ec) {
- printk(KERN_INFO "synaptics: OLPC XO detected, not enabling Synaptics protocol.\n");
+ psmouse_info(psmouse,
+ "OLPC XO detected, not enabling Synaptics protocol.\n");
return -ENODEV;
}
@@ -912,26 +1347,28 @@ int synaptics_init(struct psmouse *psmouse)
psmouse_reset(psmouse);
if (synaptics_query_hardware(psmouse)) {
- printk(KERN_ERR "Unable to query Synaptics hardware.\n");
+ psmouse_err(psmouse, "Unable to query device.\n");
goto init_fail;
}
if (synaptics_set_absolute_mode(psmouse)) {
- printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+ psmouse_err(psmouse, "Unable to initialize device.\n");
goto init_fail;
}
if (synaptics_set_advanced_gesture_mode(psmouse)) {
- printk(KERN_ERR "Advanced gesture mode init failed.\n");
+ psmouse_err(psmouse, "Advanced gesture mode init failed.\n");
goto init_fail;
}
priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
- printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
- SYN_ID_MODEL(priv->identity),
- SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
- priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
+ psmouse_info(psmouse,
+ "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
+ SYN_ID_MODEL(priv->identity),
+ SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
+ priv->model_id,
+ priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
set_input_params(psmouse->dev, priv);
@@ -963,8 +1400,9 @@ int synaptics_init(struct psmouse *psmouse)
* the same rate as a standard PS/2 mouse).
*/
if (psmouse->rate >= 80 && impaired_toshiba_kbc) {
- printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n",
- dmi_get_system_info(DMI_PRODUCT_NAME));
+ psmouse_info(psmouse,
+ "Toshiba %s detected, limiting rate to 40pps.\n",
+ dmi_get_system_info(DMI_PRODUCT_NAME));
psmouse->rate = 40;
}
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index ca040aa80fa7..622aea8dd7e0 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -74,6 +74,8 @@
* 2 0x04 reduced filtering firmware does less filtering on
* position data, driver should watch
* for noise.
+ * 2 0x08 image sensor image sensor tracks 5 fingers, but only
+ * reports 2.
* 2 0x20 report min query 0x0f gives min coord reported
*/
#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */
@@ -82,6 +84,7 @@
#define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x002000)
#define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000)
#define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400)
+#define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800)
/* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
@@ -112,9 +115,18 @@
#define SYN_REDUCED_FILTER_FUZZ 8
/*
- * A structure to describe the state of the touchpad hardware (buttons and pad)
+ * A structure to describe which internal touchpad finger slots are being
+ * reported in raw packets.
*/
+struct synaptics_mt_state {
+ int count; /* num fingers being tracked */
+ int sgm; /* which slot is reported by sgm pkt */
+ int agm; /* which slot is reported by agm pkt*/
+};
+/*
+ * A structure to describe the state of the touchpad hardware (buttons and pad)
+ */
struct synaptics_hw_state {
int x;
int y;
@@ -127,6 +139,9 @@ struct synaptics_hw_state {
unsigned int down:1;
unsigned char ext_buttons;
signed char scroll;
+
+ /* As reported in last AGM-CONTACT packets */
+ struct synaptics_mt_state mt_state;
};
struct synaptics_data {
@@ -146,7 +161,15 @@ struct synaptics_data {
struct serio *pt_port; /* Pass-through serio port */
- struct synaptics_hw_state mt; /* current gesture packet */
+ struct synaptics_mt_state mt_state; /* Current mt finger state */
+ bool mt_state_lost; /* mt_state may be incorrect */
+
+ /*
+ * Last received Advanced Gesture Mode (AGM) packet. An AGM packet
+ * contains position data for a second contact, at half resolution.
+ */
+ struct synaptics_hw_state agm;
+ bool agm_pending; /* new AGM packet received */
};
void synaptics_module_init(void);
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index cba3c84d2f21..4b755cb5b38c 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -570,7 +570,7 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client,
"Requesting IRQ: %d\n", touch->client->irq);
ret = request_irq(touch->client->irq, synaptics_i2c_irq,
- IRQF_DISABLED|IRQ_TYPE_EDGE_FALLING,
+ IRQ_TYPE_EDGE_FALLING,
DRIVER_NAME, touch);
if (ret) {
dev_warn(&touch->client->dev,
@@ -619,7 +619,7 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int synaptics_i2c_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index b7ba4597f7f0..4d4cd142bbbb 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -9,6 +9,7 @@
* the Free Software Foundation.
*/
+#include <linux/kref.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/poll.h>
@@ -33,15 +34,16 @@ struct serio_raw {
unsigned int tail, head;
char name[16];
- unsigned int refcnt;
+ struct kref kref;
struct serio *serio;
struct miscdevice dev;
wait_queue_head_t wait;
- struct list_head list;
+ struct list_head client_list;
struct list_head node;
+ bool dead;
};
-struct serio_raw_list {
+struct serio_raw_client {
struct fasync_struct *fasync;
struct serio_raw *serio_raw;
struct list_head node;
@@ -49,7 +51,6 @@ struct serio_raw_list {
static DEFINE_MUTEX(serio_raw_mutex);
static LIST_HEAD(serio_raw_list);
-static unsigned int serio_raw_no;
/*********************************************************************
* Interface with userspace (file operations) *
@@ -57,9 +58,9 @@ static unsigned int serio_raw_no;
static int serio_raw_fasync(int fd, struct file *file, int on)
{
- struct serio_raw_list *list = file->private_data;
+ struct serio_raw_client *client = file->private_data;
- return fasync_helper(fd, file, on, &list->fasync);
+ return fasync_helper(fd, file, on, &client->fasync);
}
static struct serio_raw *serio_raw_locate(int minor)
@@ -77,8 +78,8 @@ static struct serio_raw *serio_raw_locate(int minor)
static int serio_raw_open(struct inode *inode, struct file *file)
{
struct serio_raw *serio_raw;
- struct serio_raw_list *list;
- int retval = 0;
+ struct serio_raw_client *client;
+ int retval;
retval = mutex_lock_interruptible(&serio_raw_mutex);
if (retval)
@@ -90,60 +91,61 @@ static int serio_raw_open(struct inode *inode, struct file *file)
goto out;
}
- if (!serio_raw->serio) {
+ if (serio_raw->dead) {
retval = -ENODEV;
goto out;
}
- list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL);
- if (!list) {
+ client = kzalloc(sizeof(struct serio_raw_client), GFP_KERNEL);
+ if (!client) {
retval = -ENOMEM;
goto out;
}
- list->serio_raw = serio_raw;
- file->private_data = list;
+ client->serio_raw = serio_raw;
+ file->private_data = client;
+
+ kref_get(&serio_raw->kref);
- serio_raw->refcnt++;
- list_add_tail(&list->node, &serio_raw->list);
+ serio_pause_rx(serio_raw->serio);
+ list_add_tail(&client->node, &serio_raw->client_list);
+ serio_continue_rx(serio_raw->serio);
out:
mutex_unlock(&serio_raw_mutex);
return retval;
}
-static int serio_raw_cleanup(struct serio_raw *serio_raw)
+static void serio_raw_free(struct kref *kref)
{
- if (--serio_raw->refcnt == 0) {
- misc_deregister(&serio_raw->dev);
- list_del_init(&serio_raw->node);
- kfree(serio_raw);
+ struct serio_raw *serio_raw =
+ container_of(kref, struct serio_raw, kref);
- return 1;
- }
-
- return 0;
+ put_device(&serio_raw->serio->dev);
+ kfree(serio_raw);
}
static int serio_raw_release(struct inode *inode, struct file *file)
{
- struct serio_raw_list *list = file->private_data;
- struct serio_raw *serio_raw = list->serio_raw;
+ struct serio_raw_client *client = file->private_data;
+ struct serio_raw *serio_raw = client->serio_raw;
- mutex_lock(&serio_raw_mutex);
+ serio_pause_rx(serio_raw->serio);
+ list_del(&client->node);
+ serio_continue_rx(serio_raw->serio);
- serio_raw_cleanup(serio_raw);
+ kfree(client);
+
+ kref_put(&serio_raw->kref, serio_raw_free);
- mutex_unlock(&serio_raw_mutex);
return 0;
}
-static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
+static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
{
- unsigned long flags;
- int empty;
+ bool empty;
- spin_lock_irqsave(&serio_raw->serio->lock, flags);
+ serio_pause_rx(serio_raw->serio);
empty = serio_raw->head == serio_raw->tail;
if (!empty) {
@@ -151,30 +153,31 @@ static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
}
- spin_unlock_irqrestore(&serio_raw->serio->lock, flags);
+ serio_continue_rx(serio_raw->serio);
return !empty;
}
-static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t serio_raw_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ppos)
{
- struct serio_raw_list *list = file->private_data;
- struct serio_raw *serio_raw = list->serio_raw;
+ struct serio_raw_client *client = file->private_data;
+ struct serio_raw *serio_raw = client->serio_raw;
char uninitialized_var(c);
ssize_t retval = 0;
- if (!serio_raw->serio)
+ if (serio_raw->dead)
return -ENODEV;
if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
- retval = wait_event_interruptible(list->serio_raw->wait,
- serio_raw->head != serio_raw->tail || !serio_raw->serio);
+ retval = wait_event_interruptible(serio_raw->wait,
+ serio_raw->head != serio_raw->tail || serio_raw->dead);
if (retval)
return retval;
- if (!serio_raw->serio)
+ if (serio_raw->dead)
return -ENODEV;
while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
@@ -186,9 +189,11 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t cou
return retval;
}
-static ssize_t serio_raw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
{
- struct serio_raw_list *list = file->private_data;
+ struct serio_raw_client *client = file->private_data;
+ struct serio_raw *serio_raw = client->serio_raw;
ssize_t written = 0;
int retval;
unsigned char c;
@@ -197,7 +202,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
if (retval)
return retval;
- if (!list->serio_raw->serio) {
+ if (serio_raw->dead) {
retval = -ENODEV;
goto out;
}
@@ -210,7 +215,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
retval = -EFAULT;
goto out;
}
- if (serio_write(list->serio_raw->serio, c)) {
+ if (serio_write(serio_raw->serio, c)) {
retval = -EIO;
goto out;
}
@@ -224,46 +229,49 @@ out:
static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
{
- struct serio_raw_list *list = file->private_data;
+ struct serio_raw_client *client = file->private_data;
+ struct serio_raw *serio_raw = client->serio_raw;
+ unsigned int mask;
- poll_wait(file, &list->serio_raw->wait, wait);
+ poll_wait(file, &serio_raw->wait, wait);
- if (list->serio_raw->head != list->serio_raw->tail)
+ mask = serio_raw->dead ? POLLHUP | POLLERR : POLLOUT | POLLWRNORM;
+ if (serio_raw->head != serio_raw->tail)
return POLLIN | POLLRDNORM;
return 0;
}
static const struct file_operations serio_raw_fops = {
- .owner = THIS_MODULE,
- .open = serio_raw_open,
- .release = serio_raw_release,
- .read = serio_raw_read,
- .write = serio_raw_write,
- .poll = serio_raw_poll,
- .fasync = serio_raw_fasync,
- .llseek = noop_llseek,
+ .owner = THIS_MODULE,
+ .open = serio_raw_open,
+ .release = serio_raw_release,
+ .read = serio_raw_read,
+ .write = serio_raw_write,
+ .poll = serio_raw_poll,
+ .fasync = serio_raw_fasync,
+ .llseek = noop_llseek,
};
/*********************************************************************
- * Interface with serio port *
+ * Interface with serio port *
*********************************************************************/
static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
unsigned int dfl)
{
struct serio_raw *serio_raw = serio_get_drvdata(serio);
- struct serio_raw_list *list;
+ struct serio_raw_client *client;
unsigned int head = serio_raw->head;
- /* we are holding serio->lock here so we are prootected */
+ /* we are holding serio->lock here so we are protected */
serio_raw->queue[head] = data;
head = (head + 1) % SERIO_RAW_QUEUE_LEN;
if (likely(head != serio_raw->tail)) {
serio_raw->head = head;
- list_for_each_entry(list, &serio_raw->list, node)
- kill_fasync(&list->fasync, SIGIO, POLL_IN);
+ list_for_each_entry(client, &serio_raw->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&serio_raw->wait);
}
@@ -272,29 +280,37 @@ static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
{
+ static atomic_t serio_raw_no = ATOMIC_INIT(0);
struct serio_raw *serio_raw;
int err;
- if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
- printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
+ serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL);
+ if (!serio_raw) {
+ dev_dbg(&serio->dev, "can't allocate memory for a device\n");
return -ENOMEM;
}
- mutex_lock(&serio_raw_mutex);
+ snprintf(serio_raw->name, sizeof(serio_raw->name),
+ "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no) - 1);
+ kref_init(&serio_raw->kref);
+ INIT_LIST_HEAD(&serio_raw->client_list);
+ init_waitqueue_head(&serio_raw->wait);
- snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
- serio_raw->refcnt = 1;
serio_raw->serio = serio;
- INIT_LIST_HEAD(&serio_raw->list);
- init_waitqueue_head(&serio_raw->wait);
+ get_device(&serio->dev);
serio_set_drvdata(serio, serio_raw);
err = serio_open(serio, drv);
if (err)
- goto out_free;
+ goto err_free;
+
+ err = mutex_lock_killable(&serio_raw_mutex);
+ if (err)
+ goto err_close;
list_add_tail(&serio_raw->node, &serio_raw_list);
+ mutex_unlock(&serio_raw_mutex);
serio_raw->dev.minor = PSMOUSE_MINOR;
serio_raw->dev.name = serio_raw->name;
@@ -308,23 +324,23 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
}
if (err) {
- printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n",
+ dev_err(&serio->dev,
+ "failed to register raw access device for %s\n",
serio->phys);
- goto out_close;
+ goto err_unlink;
}
- printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n",
- serio->phys, serio_raw->name, serio_raw->dev.minor);
- goto out;
+ dev_info(&serio->dev, "raw access enabled on %s (%s, minor %d)\n",
+ serio->phys, serio_raw->name, serio_raw->dev.minor);
+ return 0;
-out_close:
- serio_close(serio);
+err_unlink:
list_del_init(&serio_raw->node);
-out_free:
+err_close:
+ serio_close(serio);
+err_free:
serio_set_drvdata(serio, NULL);
- kfree(serio_raw);
-out:
- mutex_unlock(&serio_raw_mutex);
+ kref_put(&serio_raw->kref, serio_raw_free);
return err;
}
@@ -334,7 +350,8 @@ static int serio_raw_reconnect(struct serio *serio)
struct serio_driver *drv = serio->drv;
if (!drv || !serio_raw) {
- printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n");
+ dev_dbg(&serio->dev,
+ "reconnect request, but serio is disconnected, ignoring...\n");
return -1;
}
@@ -345,22 +362,40 @@ static int serio_raw_reconnect(struct serio *serio)
return 0;
}
+/*
+ * Wake up users waiting for IO so they can disconnect from
+ * dead device.
+ */
+static void serio_raw_hangup(struct serio_raw *serio_raw)
+{
+ struct serio_raw_client *client;
+
+ serio_pause_rx(serio_raw->serio);
+ list_for_each_entry(client, &serio_raw->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+ serio_continue_rx(serio_raw->serio);
+
+ wake_up_interruptible(&serio_raw->wait);
+}
+
+
static void serio_raw_disconnect(struct serio *serio)
{
- struct serio_raw *serio_raw;
+ struct serio_raw *serio_raw = serio_get_drvdata(serio);
+
+ misc_deregister(&serio_raw->dev);
mutex_lock(&serio_raw_mutex);
+ serio_raw->dead = true;
+ list_del_init(&serio_raw->node);
+ mutex_unlock(&serio_raw_mutex);
- serio_raw = serio_get_drvdata(serio);
+ serio_raw_hangup(serio_raw);
serio_close(serio);
- serio_set_drvdata(serio, NULL);
-
- serio_raw->serio = NULL;
- if (!serio_raw_cleanup(serio_raw))
- wake_up_interruptible(&serio_raw->wait);
+ kref_put(&serio_raw->kref, serio_raw_free);
- mutex_unlock(&serio_raw_mutex);
+ serio_set_drvdata(serio, NULL);
}
static struct serio_device_id serio_raw_serio_ids[] = {
@@ -391,7 +426,7 @@ static struct serio_driver serio_raw_drv = {
.connect = serio_raw_connect,
.reconnect = serio_raw_reconnect,
.disconnect = serio_raw_disconnect,
- .manual_bind = 1,
+ .manual_bind = true,
};
static int __init serio_raw_init(void)
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 23317bd09c82..0783864a7dc2 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -11,7 +11,7 @@
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
- * Copyright (c) 2002-2009 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2002-2011 Ping Cheng <pingc@wacom.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
@@ -93,7 +93,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.52"
+#define DRIVER_VERSION "v1.53"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom tablet driver"
#define DRIVER_LICENSE "GPL"
@@ -114,6 +114,12 @@ struct wacom {
struct mutex lock;
bool open;
char phys[32];
+ struct wacom_led {
+ u8 select[2]; /* status led selector (0..3) */
+ u8 llv; /* status led brightness no button (1..127) */
+ u8 hlv; /* status led brightness button pressed (1..127) */
+ u8 img_lum; /* OLED matrix display brightness */
+ } led;
};
extern const struct usb_device_id wacom_ids[];
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 958b4eb6369d..1c1b7b43cf92 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -48,27 +48,49 @@ struct hid_descriptor {
/* defines to get/set USB message */
#define USB_REQ_GET_REPORT 0x01
#define USB_REQ_SET_REPORT 0x09
+
#define WAC_HID_FEATURE_REPORT 0x03
#define WAC_MSG_RETRIES 5
-static int usb_get_report(struct usb_interface *intf, unsigned char type,
- unsigned char id, void *buf, int size)
+#define WAC_CMD_LED_CONTROL 0x20
+#define WAC_CMD_ICON_START 0x21
+#define WAC_CMD_ICON_XFER 0x23
+#define WAC_CMD_RETRIES 10
+
+static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id,
+ void *buf, size_t size, unsigned int retries)
{
- return usb_control_msg(interface_to_usbdev(intf),
- usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
- USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
- buf, size, 100);
+ struct usb_device *dev = interface_to_usbdev(intf);
+ int retval;
+
+ do {
+ retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_REPORT,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ (type << 8) + id,
+ intf->altsetting[0].desc.bInterfaceNumber,
+ buf, size, 100);
+ } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
+
+ return retval;
}
-static int usb_set_report(struct usb_interface *intf, unsigned char type,
- unsigned char id, void *buf, int size)
+static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id,
+ void *buf, size_t size, unsigned int retries)
{
- return usb_control_msg(interface_to_usbdev(intf),
- usb_sndctrlpipe(interface_to_usbdev(intf), 0),
- USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
- buf, size, 1000);
+ struct usb_device *dev = interface_to_usbdev(intf);
+ int retval;
+
+ do {
+ retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_SET_REPORT,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ (type << 8) + id,
+ intf->altsetting[0].desc.bInterfaceNumber,
+ buf, size, 1000);
+ } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
+
+ return retval;
}
static void wacom_sys_irq(struct urb *urb)
@@ -319,23 +341,23 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
rep_data[2] = 0;
rep_data[3] = 0;
report_id = 3;
- error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
- report_id, rep_data, 4);
+ error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+ report_id, rep_data, 4, 1);
if (error >= 0)
- error = usb_get_report(intf,
- WAC_HID_FEATURE_REPORT, report_id,
- rep_data, 4);
+ error = wacom_get_report(intf,
+ WAC_HID_FEATURE_REPORT,
+ report_id, rep_data, 4, 1);
} while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
} else if (features->type != TABLETPC) {
do {
rep_data[0] = 2;
rep_data[1] = 2;
- error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
- report_id, rep_data, 2);
+ error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+ report_id, rep_data, 2, 1);
if (error >= 0)
- error = usb_get_report(intf,
- WAC_HID_FEATURE_REPORT, report_id,
- rep_data, 2);
+ error = wacom_get_report(intf,
+ WAC_HID_FEATURE_REPORT,
+ report_id, rep_data, 2, 1);
} while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES);
}
@@ -454,6 +476,275 @@ static void wacom_remove_shared_data(struct wacom_wac *wacom)
}
}
+static int wacom_led_control(struct wacom *wacom)
+{
+ unsigned char *buf;
+ int retval, led = 0;
+
+ buf = kzalloc(9, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (wacom->wacom_wac.features.type == WACOM_21UX2)
+ led = (wacom->led.select[1] << 4) | 0x40;
+
+ led |= wacom->led.select[0] | 0x4;
+
+ buf[0] = WAC_CMD_LED_CONTROL;
+ buf[1] = led;
+ buf[2] = wacom->led.llv;
+ buf[3] = wacom->led.hlv;
+ buf[4] = wacom->led.img_lum;
+
+ retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL,
+ buf, 9, WAC_CMD_RETRIES);
+ kfree(buf);
+
+ return retval;
+}
+
+static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img)
+{
+ unsigned char *buf;
+ int i, retval;
+
+ buf = kzalloc(259, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Send 'start' command */
+ buf[0] = WAC_CMD_ICON_START;
+ buf[1] = 1;
+ retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
+ buf, 2, WAC_CMD_RETRIES);
+ if (retval < 0)
+ goto out;
+
+ buf[0] = WAC_CMD_ICON_XFER;
+ buf[1] = button_id & 0x07;
+ for (i = 0; i < 4; i++) {
+ buf[2] = i;
+ memcpy(buf + 3, img + i * 256, 256);
+
+ retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_XFER,
+ buf, 259, WAC_CMD_RETRIES);
+ if (retval < 0)
+ break;
+ }
+
+ /* Send 'stop' */
+ buf[0] = WAC_CMD_ICON_START;
+ buf[1] = 0;
+ wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
+ buf, 2, WAC_CMD_RETRIES);
+
+out:
+ kfree(buf);
+ return retval;
+}
+
+static ssize_t wacom_led_select_store(struct device *dev, int set_id,
+ const char *buf, size_t count)
+{
+ struct wacom *wacom = dev_get_drvdata(dev);
+ unsigned int id;
+ int err;
+
+ err = kstrtouint(buf, 10, &id);
+ if (err)
+ return err;
+
+ mutex_lock(&wacom->lock);
+
+ wacom->led.select[set_id] = id & 0x3;
+ err = wacom_led_control(wacom);
+
+ mutex_unlock(&wacom->lock);
+
+ return err < 0 ? err : count;
+}
+
+#define DEVICE_LED_SELECT_ATTR(SET_ID) \
+static ssize_t wacom_led##SET_ID##_select_store(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ return wacom_led_select_store(dev, SET_ID, buf, count); \
+} \
+static ssize_t wacom_led##SET_ID##_select_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct wacom *wacom = dev_get_drvdata(dev); \
+ return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]); \
+} \
+static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR, \
+ wacom_led##SET_ID##_select_show, \
+ wacom_led##SET_ID##_select_store)
+
+DEVICE_LED_SELECT_ATTR(0);
+DEVICE_LED_SELECT_ATTR(1);
+
+static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest,
+ const char *buf, size_t count)
+{
+ unsigned int value;
+ int err;
+
+ err = kstrtouint(buf, 10, &value);
+ if (err)
+ return err;
+
+ mutex_lock(&wacom->lock);
+
+ *dest = value & 0x7f;
+ err = wacom_led_control(wacom);
+
+ mutex_unlock(&wacom->lock);
+
+ return err < 0 ? err : count;
+}
+
+#define DEVICE_LUMINANCE_ATTR(name, field) \
+static ssize_t wacom_##name##_luminance_store(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct wacom *wacom = dev_get_drvdata(dev); \
+ \
+ return wacom_luminance_store(wacom, &wacom->led.field, \
+ buf, count); \
+} \
+static DEVICE_ATTR(name##_luminance, S_IWUSR, \
+ NULL, wacom_##name##_luminance_store)
+
+DEVICE_LUMINANCE_ATTR(status0, llv);
+DEVICE_LUMINANCE_ATTR(status1, hlv);
+DEVICE_LUMINANCE_ATTR(buttons, img_lum);
+
+static ssize_t wacom_button_image_store(struct device *dev, int button_id,
+ const char *buf, size_t count)
+{
+ struct wacom *wacom = dev_get_drvdata(dev);
+ int err;
+
+ if (count != 1024)
+ return -EINVAL;
+
+ mutex_lock(&wacom->lock);
+
+ err = wacom_led_putimage(wacom, button_id, buf);
+
+ mutex_unlock(&wacom->lock);
+
+ return err < 0 ? err : count;
+}
+
+#define DEVICE_BTNIMG_ATTR(BUTTON_ID) \
+static ssize_t wacom_btnimg##BUTTON_ID##_store(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ return wacom_button_image_store(dev, BUTTON_ID, buf, count); \
+} \
+static DEVICE_ATTR(button##BUTTON_ID##_rawimg, S_IWUSR, \
+ NULL, wacom_btnimg##BUTTON_ID##_store)
+
+DEVICE_BTNIMG_ATTR(0);
+DEVICE_BTNIMG_ATTR(1);
+DEVICE_BTNIMG_ATTR(2);
+DEVICE_BTNIMG_ATTR(3);
+DEVICE_BTNIMG_ATTR(4);
+DEVICE_BTNIMG_ATTR(5);
+DEVICE_BTNIMG_ATTR(6);
+DEVICE_BTNIMG_ATTR(7);
+
+static struct attribute *cintiq_led_attrs[] = {
+ &dev_attr_status_led0_select.attr,
+ &dev_attr_status_led1_select.attr,
+ NULL
+};
+
+static struct attribute_group cintiq_led_attr_group = {
+ .name = "wacom_led",
+ .attrs = cintiq_led_attrs,
+};
+
+static struct attribute *intuos4_led_attrs[] = {
+ &dev_attr_status0_luminance.attr,
+ &dev_attr_status1_luminance.attr,
+ &dev_attr_status_led0_select.attr,
+ &dev_attr_buttons_luminance.attr,
+ &dev_attr_button0_rawimg.attr,
+ &dev_attr_button1_rawimg.attr,
+ &dev_attr_button2_rawimg.attr,
+ &dev_attr_button3_rawimg.attr,
+ &dev_attr_button4_rawimg.attr,
+ &dev_attr_button5_rawimg.attr,
+ &dev_attr_button6_rawimg.attr,
+ &dev_attr_button7_rawimg.attr,
+ NULL
+};
+
+static struct attribute_group intuos4_led_attr_group = {
+ .name = "wacom_led",
+ .attrs = intuos4_led_attrs,
+};
+
+static int wacom_initialize_leds(struct wacom *wacom)
+{
+ int error;
+
+ /* Initialize default values */
+ switch (wacom->wacom_wac.features.type) {
+ case INTUOS4:
+ case INTUOS4L:
+ wacom->led.select[0] = 0;
+ wacom->led.select[1] = 0;
+ wacom->led.llv = 10;
+ wacom->led.hlv = 20;
+ wacom->led.img_lum = 10;
+ error = sysfs_create_group(&wacom->intf->dev.kobj,
+ &intuos4_led_attr_group);
+ break;
+
+ case WACOM_21UX2:
+ wacom->led.select[0] = 0;
+ wacom->led.select[1] = 0;
+ wacom->led.llv = 0;
+ wacom->led.hlv = 0;
+ wacom->led.img_lum = 0;
+
+ error = sysfs_create_group(&wacom->intf->dev.kobj,
+ &cintiq_led_attr_group);
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (error) {
+ dev_err(&wacom->intf->dev,
+ "cannot create sysfs group err: %d\n", error);
+ return error;
+ }
+ wacom_led_control(wacom);
+
+ return 0;
+}
+
+static void wacom_destroy_leds(struct wacom *wacom)
+{
+ switch (wacom->wacom_wac.features.type) {
+ case INTUOS4:
+ case INTUOS4L:
+ sysfs_remove_group(&wacom->intf->dev.kobj,
+ &intuos4_led_attr_group);
+ break;
+
+ case WACOM_21UX2:
+ sysfs_remove_group(&wacom->intf->dev.kobj,
+ &cintiq_led_attr_group);
+ break;
+ }
+}
+
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
@@ -542,16 +833,21 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom->irq->transfer_dma = wacom->data_dma;
wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- error = input_register_device(input_dev);
+ error = wacom_initialize_leds(wacom);
if (error)
goto fail4;
+ error = input_register_device(input_dev);
+ if (error)
+ goto fail5;
+
/* Note that if query fails it is not a hard failure */
wacom_query_tablet_data(intf, features);
usb_set_intfdata(intf, wacom);
return 0;
+ fail5: wacom_destroy_leds(wacom);
fail4: wacom_remove_shared_data(wacom_wac);
fail3: usb_free_urb(wacom->irq);
fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
@@ -568,6 +864,7 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_kill_urb(wacom->irq);
input_unregister_device(wacom->wacom_wac.input);
+ wacom_destroy_leds(wacom);
usb_free_urb(wacom->irq);
usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
wacom->wacom_wac.data, wacom->data_dma);
@@ -590,17 +887,16 @@ static int wacom_resume(struct usb_interface *intf)
{
struct wacom *wacom = usb_get_intfdata(intf);
struct wacom_features *features = &wacom->wacom_wac.features;
- int rv;
+ int rv = 0;
mutex_lock(&wacom->lock);
/* switch to wacom mode first */
wacom_query_tablet_data(intf, features);
+ wacom_led_control(wacom);
- if (wacom->open)
- rv = usb_submit_urb(wacom->irq, GFP_NOIO);
- else
- rv = 0;
+ if (wacom->open && usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
+ rv = -EIO;
mutex_unlock(&wacom->lock);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 9dea71849f40..da0d8761e778 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -874,7 +874,15 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
x = le16_to_cpup((__le16 *)&data[2]);
y = le16_to_cpup((__le16 *)&data[4]);
p = le16_to_cpup((__le16 *)&data[6]);
- d = data[8];
+ /*
+ * Convert distance from out prox to distance from tablet.
+ * distance will be greater than distance_max once
+ * touching and applying pressure; do not report negative
+ * distance.
+ */
+ if (data[8] <= wacom->features.distance_max)
+ d = wacom->features.distance_max - data[8];
+
pen = data[1] & 0x01;
btn1 = data[1] & 0x02;
btn2 = data[1] & 0x04;
@@ -1030,8 +1038,6 @@ void wacom_setup_device_quirks(struct wacom_features *features)
features->y_max <<= 5;
features->x_fuzz <<= 5;
features->y_fuzz <<= 5;
- features->pressure_max = 256;
- features->pressure_fuzz = 16;
features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
}
}
@@ -1241,14 +1247,14 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
0, features->y_max,
features->y_fuzz, 0);
- input_set_abs_params(input_dev, ABS_MT_PRESSURE,
- 0, features->pressure_max,
- features->pressure_fuzz, 0);
} else if (features->device_type == BTN_TOOL_PEN) {
__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
__set_bit(BTN_TOOL_PEN, input_dev->keybit);
__set_bit(BTN_STYLUS, input_dev->keybit);
__set_bit(BTN_STYLUS2, input_dev->keybit);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+ features->distance_max,
+ 0, 0);
}
break;
}
@@ -1469,37 +1475,37 @@ static const struct wacom_features wacom_features_0x47 =
31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD0 =
{ "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD1 =
{ "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD2 =
{ "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD3 =
- { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD4 =
{ "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD5 =
- { "Wacom Bamboo Pen 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo Pen 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD6 =
{ "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD7 =
{ "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD8 =
- { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xDA =
{ "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static struct wacom_features wacom_features_0xDB =
- { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
- 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
+ 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x6004 =
{ "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index cabd9e54863f..3488ffe1fa0a 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -651,6 +651,18 @@ config TOUCHSCREEN_TOUCHIT213
To compile this driver as a module, choose M here: the
module will be called touchit213.
+config TOUCHSCREEN_TSC_SERIO
+ tristate "TSC-10/25/40 serial touchscreen support"
+ select SERIO
+ help
+ Say Y here if you have a TSC-10, 25 or 40 serial touchscreen connected
+ to your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called tsc40.
+
config TOUCHSCREEN_TSC2005
tristate "TSC2005 based touchscreens"
depends on SPI_MASTER && GENERIC_HARDIRQS
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 282d6f76ae26..f957676035a4 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
+obj-$(CONFIG_TOUCHSCREEN_TSC_SERIO) += tsc40.o
obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o
obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c
index 4e4e58cec6c8..c789b974c795 100644
--- a/drivers/input/touchscreen/ad7879-i2c.c
+++ b/drivers/input/touchscreen/ad7879-i2c.c
@@ -16,7 +16,7 @@
#define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int ad7879_i2c_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -36,9 +36,9 @@ static int ad7879_i2c_resume(struct device *dev)
return 0;
}
+#endif
static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume);
-#endif
/* All registers are word-sized.
* AD7879 uses a high-byte first convention.
@@ -119,9 +119,7 @@ static struct i2c_driver ad7879_i2c_driver = {
.driver = {
.name = "ad7879",
.owner = THIS_MODULE,
-#ifdef CONFIG_PM
.pm = &ad7879_i2c_pm,
-#endif
},
.probe = ad7879_i2c_probe,
.remove = __devexit_p(ad7879_i2c_remove),
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index f5d66859f232..a596c2775d1a 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -910,12 +910,17 @@ static ssize_t mxt_object_show(struct device *dev,
for (i = 0; i < data->info.object_num; i++) {
object = data->object_table + i;
- count += sprintf(buf + count,
- "Object Table Element %d(Type %d)\n",
+ count += snprintf(buf + count, PAGE_SIZE - count,
+ "Object[%d] (Type %d)\n",
i + 1, object->type);
+ if (count >= PAGE_SIZE)
+ return PAGE_SIZE - 1;
if (!mxt_object_readable(object->type)) {
- count += sprintf(buf + count, "\n");
+ count += snprintf(buf + count, PAGE_SIZE - count,
+ "\n");
+ if (count >= PAGE_SIZE)
+ return PAGE_SIZE - 1;
continue;
}
@@ -925,11 +930,15 @@ static ssize_t mxt_object_show(struct device *dev,
if (error)
return error;
- count += sprintf(buf + count,
- " Byte %d: 0x%x (%d)\n", j, val, val);
+ count += snprintf(buf + count, PAGE_SIZE - count,
+ "\t[%2d]: %02x (%d)\n", j, val, val);
+ if (count >= PAGE_SIZE)
+ return PAGE_SIZE - 1;
}
- count += sprintf(buf + count, "\n");
+ count += snprintf(buf + count, PAGE_SIZE - count, "\n");
+ if (count >= PAGE_SIZE)
+ return PAGE_SIZE - 1;
}
return count;
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
index 432c69be6ac6..122a87883659 100644
--- a/drivers/input/touchscreen/atmel_tsadcc.c
+++ b/drivers/input/touchscreen/atmel_tsadcc.c
@@ -229,7 +229,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
goto err_release_mem;
}
- err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, IRQF_DISABLED,
+ err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, 0,
pdev->dev.driver->name, ts_dev);
if (err) {
dev_err(&pdev->dev, "failed to allocate irq.\n");
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index 211811ae5525..6107e563e681 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -396,14 +396,14 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE);
if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
- IRQF_SHARED | IRQF_DISABLED, "h3600_action", ts->dev)) {
+ IRQF_SHARED, "h3600_action", ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
err = -EBUSY;
goto fail1;
}
if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
- IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", ts->dev)) {
+ IRQF_SHARED, "h3600_suspend", ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
err = -EBUSY;
goto fail2;
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index dd4e8f020b99..639a6044183d 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -93,7 +93,7 @@ static int __init hp680_ts_init(void)
hp680_ts_dev->phys = "hp680_ts/input0";
if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
- IRQF_DISABLED, MODNAME, 0) < 0) {
+ 0, MODNAME, 0) < 0) {
printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
HP680_TS_IRQ);
err = -EBUSY;
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
index 4b0a061811ff..50076c2d59e2 100644
--- a/drivers/input/touchscreen/jornada720_ts.c
+++ b/drivers/input/touchscreen/jornada720_ts.c
@@ -127,7 +127,7 @@ static int __devinit jornada720_ts_probe(struct platform_device *pdev)
error = request_irq(IRQ_GPIO9,
jornada720_ts_interrupt,
- IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_RISING,
"HP7XX Touchscreen driver", pdev);
if (error) {
printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n");
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
index dcf803f5a1f7..0a484ed5295c 100644
--- a/drivers/input/touchscreen/lpc32xx_ts.c
+++ b/drivers/input/touchscreen/lpc32xx_ts.c
@@ -276,7 +276,7 @@ static int __devinit lpc32xx_ts_probe(struct platform_device *pdev)
input_set_drvdata(input, tsc);
error = request_irq(tsc->irq, lpc32xx_ts_interrupt,
- IRQF_DISABLED, pdev->name, tsc);
+ 0, pdev->name, tsc);
if (error) {
dev_err(&pdev->dev, "failed requesting interrupt\n");
goto err_put_clock;
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index c7f9cebebbb6..4c012fb2b01e 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -2,6 +2,7 @@
* Penmount serial touchscreen driver
*
* Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
+ * Copyright (c) 2011 John Sung <penmount.touch@gmail.com>
*
* Based on ELO driver (drivers/input/touchscreen/elo.c)
* Copyright (c) 2004 Vojtech Pavlik
@@ -18,12 +19,14 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/serio.h>
#include <linux/init.h>
-#define DRIVER_DESC "Penmount serial touchscreen driver"
+#define DRIVER_DESC "PenMount serial touchscreen driver"
MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
+MODULE_AUTHOR("John Sung <penmount.touch@gmail.com>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
@@ -31,7 +34,19 @@ MODULE_LICENSE("GPL");
* Definitions & global arrays.
*/
-#define PM_MAX_LENGTH 5
+#define PM_MAX_LENGTH 6
+#define PM_MAX_MTSLOT 16
+#define PM_3000_MTSLOT 2
+#define PM_6250_MTSLOT 12
+
+/*
+ * Multi-touch slot
+ */
+
+struct mt_slot {
+ unsigned short x, y;
+ bool active; /* is the touch valid? */
+};
/*
* Per-touchscreen data.
@@ -43,25 +58,119 @@ struct pm {
int idx;
unsigned char data[PM_MAX_LENGTH];
char phys[32];
+ unsigned char packetsize;
+ unsigned char maxcontacts;
+ struct mt_slot slots[PM_MAX_MTSLOT];
+ void (*parse_packet)(struct pm *);
};
-static irqreturn_t pm_interrupt(struct serio *serio,
- unsigned char data, unsigned int flags)
+/*
+ * pm_mtevent() sends mt events and also emulates pointer movement
+ */
+
+static void pm_mtevent(struct pm *pm, struct input_dev *input)
+{
+ int i;
+
+ for (i = 0; i < pm->maxcontacts; ++i) {
+ input_mt_slot(input, i);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER,
+ pm->slots[i].active);
+ if (pm->slots[i].active) {
+ input_event(input, EV_ABS, ABS_MT_POSITION_X, pm->slots[i].x);
+ input_event(input, EV_ABS, ABS_MT_POSITION_Y, pm->slots[i].y);
+ }
+ }
+
+ input_mt_report_pointer_emulation(input, true);
+ input_sync(input);
+}
+
+/*
+ * pm_checkpacket() checks if data packet is valid
+ */
+
+static bool pm_checkpacket(unsigned char *packet)
+{
+ int total = 0;
+ int i;
+
+ for (i = 0; i < 5; i++)
+ total += packet[i];
+
+ return packet[5] == (unsigned char)~(total & 0xff);
+}
+
+static void pm_parse_9000(struct pm *pm)
{
- struct pm *pm = serio_get_drvdata(serio);
struct input_dev *dev = pm->dev;
- pm->data[pm->idx] = data;
+ if ((pm->data[0] & 0x80) && pm->packetsize == ++pm->idx) {
+ input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]);
+ input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]);
+ input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
+ input_sync(dev);
+ pm->idx = 0;
+ }
+}
- if (pm->data[0] & 0x80) {
- if (PM_MAX_LENGTH == ++pm->idx) {
- input_report_abs(dev, ABS_X, pm->data[2] * 128 + pm->data[1]);
- input_report_abs(dev, ABS_Y, pm->data[4] * 128 + pm->data[3]);
- input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
+static void pm_parse_6000(struct pm *pm)
+{
+ struct input_dev *dev = pm->dev;
+
+ if ((pm->data[0] & 0xbf) == 0x30 && pm->packetsize == ++pm->idx) {
+ if (pm_checkpacket(pm->data)) {
+ input_report_abs(dev, ABS_X,
+ pm->data[2] * 256 + pm->data[1]);
+ input_report_abs(dev, ABS_Y,
+ pm->data[4] * 256 + pm->data[3]);
+ input_report_key(dev, BTN_TOUCH, pm->data[0] & 0x40);
input_sync(dev);
- pm->idx = 0;
}
+ pm->idx = 0;
+ }
+}
+
+static void pm_parse_3000(struct pm *pm)
+{
+ struct input_dev *dev = pm->dev;
+
+ if ((pm->data[0] & 0xce) == 0x40 && pm->packetsize == ++pm->idx) {
+ if (pm_checkpacket(pm->data)) {
+ int slotnum = pm->data[0] & 0x0f;
+ pm->slots[slotnum].active = pm->data[0] & 0x30;
+ pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
+ pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
+ pm_mtevent(pm, dev);
+ }
+ pm->idx = 0;
+ }
+}
+
+static void pm_parse_6250(struct pm *pm)
+{
+ struct input_dev *dev = pm->dev;
+
+ if ((pm->data[0] & 0xb0) == 0x30 && pm->packetsize == ++pm->idx) {
+ if (pm_checkpacket(pm->data)) {
+ int slotnum = pm->data[0] & 0x0f;
+ pm->slots[slotnum].active = pm->data[0] & 0x40;
+ pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
+ pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
+ pm_mtevent(pm, dev);
+ }
+ pm->idx = 0;
}
+}
+
+static irqreturn_t pm_interrupt(struct serio *serio,
+ unsigned char data, unsigned int flags)
+{
+ struct pm *pm = serio_get_drvdata(serio);
+
+ pm->data[pm->idx] = data;
+
+ pm->parse_packet(pm);
return IRQ_HANDLED;
}
@@ -74,17 +183,17 @@ static void pm_disconnect(struct serio *serio)
{
struct pm *pm = serio_get_drvdata(serio);
- input_get_device(pm->dev);
- input_unregister_device(pm->dev);
serio_close(serio);
- serio_set_drvdata(serio, NULL);
- input_put_device(pm->dev);
+
+ input_unregister_device(pm->dev);
kfree(pm);
+
+ serio_set_drvdata(serio, NULL);
}
/*
* pm_connect() is the routine that is called when someone adds a
- * new serio device that supports Gunze protocol and registers it as
+ * new serio device that supports PenMount protocol and registers it as
* an input device.
*/
@@ -92,6 +201,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
{
struct pm *pm;
struct input_dev *input_dev;
+ int max_x, max_y;
int err;
pm = kzalloc(sizeof(struct pm), GFP_KERNEL);
@@ -104,8 +214,9 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
pm->serio = serio;
pm->dev = input_dev;
snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
+ pm->maxcontacts = 1;
- input_dev->name = "Penmount Serial TouchScreen";
+ input_dev->name = "PenMount Serial TouchScreen";
input_dev->phys = pm->phys;
input_dev->id.bustype = BUS_RS232;
input_dev->id.vendor = SERIO_PENMOUNT;
@@ -113,10 +224,52 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0);
- input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ switch (serio->id.id) {
+ default:
+ case 0:
+ pm->packetsize = 5;
+ pm->parse_packet = pm_parse_9000;
+ input_dev->id.product = 0x9000;
+ max_x = max_y = 0x3ff;
+ break;
+
+ case 1:
+ pm->packetsize = 6;
+ pm->parse_packet = pm_parse_6000;
+ input_dev->id.product = 0x6000;
+ max_x = max_y = 0x3ff;
+ break;
+
+ case 2:
+ pm->packetsize = 6;
+ pm->parse_packet = pm_parse_3000;
+ input_dev->id.product = 0x3000;
+ max_x = max_y = 0x7ff;
+ pm->maxcontacts = PM_3000_MTSLOT;
+ break;
+
+ case 3:
+ pm->packetsize = 6;
+ pm->parse_packet = pm_parse_6250;
+ input_dev->id.product = 0x6250;
+ max_x = max_y = 0x3ff;
+ pm->maxcontacts = PM_6250_MTSLOT;
+ break;
+ }
+
+ input_set_abs_params(pm->dev, ABS_X, 0, max_x, 0, 0);
+ input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0);
+
+ if (pm->maxcontacts > 1) {
+ input_mt_init_slots(pm->dev, pm->maxcontacts);
+ input_set_abs_params(pm->dev,
+ ABS_MT_POSITION_X, 0, max_x, 0, 0);
+ input_set_abs_params(pm->dev,
+ ABS_MT_POSITION_Y, 0, max_y, 0, 0);
+ }
serio_set_drvdata(serio, pm);
@@ -155,7 +308,7 @@ MODULE_DEVICE_TABLE(serio, pm_serio_ids);
static struct serio_driver pm_drv = {
.driver = {
- .name = "penmountlpc",
+ .name = "serio-penmount",
},
.description = DRIVER_DESC,
.id_table = pm_serio_ids,
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index 8feb7f3c8be1..64ce697a3456 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -328,7 +328,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
ts.shift = info->oversampling_shift;
ts.features = platform_get_device_id(pdev)->driver_data;
- ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED,
+ ret = request_irq(ts.irq_tc, stylus_irq, 0,
"s3c2410_ts_pen", ts.input);
if (ret) {
dev_err(dev, "cannot get TC interrupt\n");
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index fadc11545b1e..1f674cb6c55b 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -66,7 +66,6 @@ struct ts_event {
struct tsc2007 {
struct input_dev *input;
char phys[32];
- struct delayed_work work;
struct i2c_client *client;
@@ -76,9 +75,11 @@ struct tsc2007 {
unsigned long poll_delay;
unsigned long poll_period;
- bool pendown;
int irq;
+ wait_queue_head_t wait;
+ bool stopped;
+
int (*get_pendown_state)(void);
void (*clear_penirq)(void);
};
@@ -141,25 +142,8 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc)
return rt;
}
-static void tsc2007_send_up_event(struct tsc2007 *tsc)
+static bool tsc2007_is_pen_down(struct tsc2007 *ts)
{
- struct input_dev *input = tsc->input;
-
- dev_dbg(&tsc->client->dev, "UP\n");
-
- input_report_key(input, BTN_TOUCH, 0);
- input_report_abs(input, ABS_PRESSURE, 0);
- input_sync(input);
-}
-
-static void tsc2007_work(struct work_struct *work)
-{
- struct tsc2007 *ts =
- container_of(to_delayed_work(work), struct tsc2007, work);
- bool debounced = false;
- struct ts_event tc;
- u32 rt;
-
/*
* NOTE: We can't rely on the pressure to determine the pen down
* state, even though this controller has a pressure sensor.
@@ -170,79 +154,82 @@ static void tsc2007_work(struct work_struct *work)
* The only safe way to check for the pen up condition is in the
* work function by reading the pen signal state (it's a GPIO
* and IRQ). Unfortunately such callback is not always available,
- * in that case we have rely on the pressure anyway.
+ * in that case we assume that the pen is down and expect caller
+ * to fall back on the pressure reading.
*/
- if (ts->get_pendown_state) {
- if (unlikely(!ts->get_pendown_state())) {
- tsc2007_send_up_event(ts);
- ts->pendown = false;
- goto out;
- }
- dev_dbg(&ts->client->dev, "pen is still down\n");
- }
+ if (!ts->get_pendown_state)
+ return true;
+
+ return ts->get_pendown_state();
+}
+
+static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
+{
+ struct tsc2007 *ts = handle;
+ struct input_dev *input = ts->input;
+ struct ts_event tc;
+ u32 rt;
- tsc2007_read_values(ts, &tc);
+ while (!ts->stopped && tsc2007_is_pen_down(ts)) {
- rt = tsc2007_calculate_pressure(ts, &tc);
- if (rt > ts->max_rt) {
- /*
- * Sample found inconsistent by debouncing or pressure is
- * beyond the maximum. Don't report it to user space,
- * repeat at least once more the measurement.
- */
- dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
- debounced = true;
- goto out;
+ /* pen is down, continue with the measurement */
+ tsc2007_read_values(ts, &tc);
- }
+ rt = tsc2007_calculate_pressure(ts, &tc);
- if (rt) {
- struct input_dev *input = ts->input;
+ if (rt == 0 && !ts->get_pendown_state) {
+ /*
+ * If pressure reported is 0 and we don't have
+ * callback to check pendown state, we have to
+ * assume that pen was lifted up.
+ */
+ break;
+ }
- if (!ts->pendown) {
- dev_dbg(&ts->client->dev, "DOWN\n");
+ if (rt <= ts->max_rt) {
+ dev_dbg(&ts->client->dev,
+ "DOWN point(%4d,%4d), pressure (%4u)\n",
+ tc.x, tc.y, rt);
input_report_key(input, BTN_TOUCH, 1);
- ts->pendown = true;
+ input_report_abs(input, ABS_X, tc.x);
+ input_report_abs(input, ABS_Y, tc.y);
+ input_report_abs(input, ABS_PRESSURE, rt);
+
+ input_sync(input);
+
+ } else {
+ /*
+ * Sample found inconsistent by debouncing or pressure is
+ * beyond the maximum. Don't report it to user space,
+ * repeat at least once more the measurement.
+ */
+ dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
}
- input_report_abs(input, ABS_X, tc.x);
- input_report_abs(input, ABS_Y, tc.y);
- input_report_abs(input, ABS_PRESSURE, rt);
+ wait_event_timeout(ts->wait, ts->stopped,
+ msecs_to_jiffies(ts->poll_period));
+ }
- input_sync(input);
+ dev_dbg(&ts->client->dev, "UP\n");
- dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n",
- tc.x, tc.y, rt);
+ input_report_key(input, BTN_TOUCH, 0);
+ input_report_abs(input, ABS_PRESSURE, 0);
+ input_sync(input);
- } else if (!ts->get_pendown_state && ts->pendown) {
- /*
- * We don't have callback to check pendown state, so we
- * have to assume that since pressure reported is 0 the
- * pen was lifted up.
- */
- tsc2007_send_up_event(ts);
- ts->pendown = false;
- }
+ if (ts->clear_penirq)
+ ts->clear_penirq();
- out:
- if (ts->pendown || debounced)
- schedule_delayed_work(&ts->work,
- msecs_to_jiffies(ts->poll_period));
- else
- enable_irq(ts->irq);
+ return IRQ_HANDLED;
}
-static irqreturn_t tsc2007_irq(int irq, void *handle)
+static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
{
struct tsc2007 *ts = handle;
- if (!ts->get_pendown_state || likely(ts->get_pendown_state())) {
- disable_irq_nosync(ts->irq);
- schedule_delayed_work(&ts->work,
- msecs_to_jiffies(ts->poll_delay));
- }
+ if (!ts->get_pendown_state || likely(ts->get_pendown_state()))
+ return IRQ_WAKE_THREAD;
if (ts->clear_penirq)
ts->clear_penirq();
@@ -250,17 +237,40 @@ static irqreturn_t tsc2007_irq(int irq, void *handle)
return IRQ_HANDLED;
}
-static void tsc2007_free_irq(struct tsc2007 *ts)
+static void tsc2007_stop(struct tsc2007 *ts)
{
- free_irq(ts->irq, ts);
- if (cancel_delayed_work_sync(&ts->work)) {
- /*
- * Work was pending, therefore we need to enable
- * IRQ here to balance the disable_irq() done in the
- * interrupt handler.
- */
- enable_irq(ts->irq);
+ ts->stopped = true;
+ mb();
+ wake_up(&ts->wait);
+
+ disable_irq(ts->irq);
+}
+
+static int tsc2007_open(struct input_dev *input_dev)
+{
+ struct tsc2007 *ts = input_get_drvdata(input_dev);
+ int err;
+
+ ts->stopped = false;
+ mb();
+
+ enable_irq(ts->irq);
+
+ /* Prepare for touch readings - power down ADC and enable PENIRQ */
+ err = tsc2007_xfer(ts, PWRDOWN);
+ if (err < 0) {
+ tsc2007_stop(ts);
+ return err;
}
+
+ return 0;
+}
+
+static void tsc2007_close(struct input_dev *input_dev)
+{
+ struct tsc2007 *ts = input_get_drvdata(input_dev);
+
+ tsc2007_stop(ts);
}
static int __devinit tsc2007_probe(struct i2c_client *client,
@@ -290,7 +300,7 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
ts->client = client;
ts->irq = client->irq;
ts->input = input_dev;
- INIT_DELAYED_WORK(&ts->work, tsc2007_work);
+ init_waitqueue_head(&ts->wait);
ts->model = pdata->model;
ts->x_plate_ohms = pdata->x_plate_ohms;
@@ -300,6 +310,12 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
ts->get_pendown_state = pdata->get_pendown_state;
ts->clear_penirq = pdata->clear_penirq;
+ if (pdata->x_plate_ohms == 0) {
+ dev_err(&client->dev, "x_plate_ohms is not set up in platform data");
+ err = -EINVAL;
+ goto err_free_mem;
+ }
+
snprintf(ts->phys, sizeof(ts->phys),
"%s/input0", dev_name(&client->dev));
@@ -307,6 +323,11 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
input_dev->phys = ts->phys;
input_dev->id.bustype = BUS_I2C;
+ input_dev->open = tsc2007_open;
+ input_dev->close = tsc2007_close;
+
+ input_set_drvdata(input_dev, ts);
+
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
@@ -318,17 +339,14 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
if (pdata->init_platform_hw)
pdata->init_platform_hw();
- err = request_irq(ts->irq, tsc2007_irq, 0,
- client->dev.driver->name, ts);
+ err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,
+ IRQF_ONESHOT, client->dev.driver->name, ts);
if (err < 0) {
dev_err(&client->dev, "irq %d busy?\n", ts->irq);
goto err_free_mem;
}
- /* Prepare for touch readings - power down ADC and enable PENIRQ */
- err = tsc2007_xfer(ts, PWRDOWN);
- if (err < 0)
- goto err_free_irq;
+ tsc2007_stop(ts);
err = input_register_device(input_dev);
if (err)
@@ -339,7 +357,7 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
return 0;
err_free_irq:
- tsc2007_free_irq(ts);
+ free_irq(ts->irq, ts);
if (pdata->exit_platform_hw)
pdata->exit_platform_hw();
err_free_mem:
@@ -353,7 +371,7 @@ static int __devexit tsc2007_remove(struct i2c_client *client)
struct tsc2007 *ts = i2c_get_clientdata(client);
struct tsc2007_platform_data *pdata = client->dev.platform_data;
- tsc2007_free_irq(ts);
+ free_irq(ts->irq, ts);
if (pdata->exit_platform_hw)
pdata->exit_platform_hw();
diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c
new file mode 100644
index 000000000000..29d5ed4dd31c
--- /dev/null
+++ b/drivers/input/touchscreen/tsc40.c
@@ -0,0 +1,184 @@
+/*
+ * TSC-40 serial touchscreen driver. It should be compatible with
+ * TSC-10 and 25.
+ *
+ * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ * License: GPLv2 as published by the FSF.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define PACKET_LENGTH 5
+struct tsc_ser {
+ struct input_dev *dev;
+ struct serio *serio;
+ u32 idx;
+ unsigned char data[PACKET_LENGTH];
+ char phys[32];
+};
+
+static void tsc_process_data(struct tsc_ser *ptsc)
+{
+ struct input_dev *dev = ptsc->dev;
+ u8 *data = ptsc->data;
+ u32 x;
+ u32 y;
+
+ x = ((data[1] & 0x03) << 8) | data[2];
+ y = ((data[3] & 0x03) << 8) | data[4];
+
+ input_report_abs(dev, ABS_X, x);
+ input_report_abs(dev, ABS_Y, y);
+ input_report_key(dev, BTN_TOUCH, 1);
+
+ input_sync(dev);
+}
+
+static irqreturn_t tsc_interrupt(struct serio *serio,
+ unsigned char data, unsigned int flags)
+{
+ struct tsc_ser *ptsc = serio_get_drvdata(serio);
+ struct input_dev *dev = ptsc->dev;
+
+ ptsc->data[ptsc->idx] = data;
+ switch (ptsc->idx++) {
+ case 0:
+ if (unlikely((data & 0x3e) != 0x10)) {
+ dev_dbg(&serio->dev,
+ "unsynchronized packet start (0x%02x)\n", data);
+ ptsc->idx = 0;
+ } else if (!(data & 0x01)) {
+ input_report_key(dev, BTN_TOUCH, 0);
+ input_sync(dev);
+ ptsc->idx = 0;
+ }
+ break;
+
+ case 1:
+ case 3:
+ if (unlikely(data & 0xfc)) {
+ dev_dbg(&serio->dev,
+ "unsynchronized data 0x%02x at offset %d\n",
+ data, ptsc->idx - 1);
+ ptsc->idx = 0;
+ }
+ break;
+
+ case 4:
+ tsc_process_data(ptsc);
+ ptsc->idx = 0;
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int tsc_connect(struct serio *serio, struct serio_driver *drv)
+{
+ struct tsc_ser *ptsc;
+ struct input_dev *input_dev;
+ int error;
+
+ ptsc = kzalloc(sizeof(struct tsc_ser), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ptsc || !input_dev) {
+ error = -ENOMEM;
+ goto fail1;
+ }
+
+ ptsc->serio = serio;
+ ptsc->dev = input_dev;
+ snprintf(ptsc->phys, sizeof(ptsc->phys), "%s/input0", serio->phys);
+
+ input_dev->name = "TSC-10/25/40 Serial TouchScreen";
+ input_dev->phys = ptsc->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_TSC40;
+ input_dev->id.product = 40;
+ input_dev->id.version = 0x0001;
+ input_dev->dev.parent = &serio->dev;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+ input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
+ input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
+ input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);
+
+ serio_set_drvdata(serio, ptsc);
+
+ error = serio_open(serio, drv);
+ if (error)
+ goto fail2;
+
+ error = input_register_device(ptsc->dev);
+ if (error)
+ goto fail3;
+
+ return 0;
+
+fail3:
+ serio_close(serio);
+fail2:
+ serio_set_drvdata(serio, NULL);
+fail1:
+ input_free_device(input_dev);
+ kfree(ptsc);
+ return error;
+}
+
+static void tsc_disconnect(struct serio *serio)
+{
+ struct tsc_ser *ptsc = serio_get_drvdata(serio);
+
+ serio_close(serio);
+
+ input_unregister_device(ptsc->dev);
+ kfree(ptsc);
+
+ serio_set_drvdata(serio, NULL);
+}
+
+static struct serio_device_id tsc_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_TSC40,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(serio, tsc_serio_ids);
+
+#define DRIVER_DESC "TSC-10/25/40 serial touchscreen driver"
+
+static struct serio_driver tsc_drv = {
+ .driver = {
+ .name = "tsc40",
+ },
+ .description = DRIVER_DESC,
+ .id_table = tsc_serio_ids,
+ .interrupt = tsc_interrupt,
+ .connect = tsc_connect,
+ .disconnect = tsc_disconnect,
+};
+
+static int __init tsc_ser_init(void)
+{
+ return serio_register_driver(&tsc_drv);
+}
+module_init(tsc_ser_init);
+
+static void __exit tsc_exit(void)
+{
+ serio_unregister_driver(&tsc_drv);
+}
+module_exit(tsc_exit);
+
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c
index 7a45d68c3516..217aa51135c5 100644
--- a/drivers/input/touchscreen/w90p910_ts.c
+++ b/drivers/input/touchscreen/w90p910_ts.c
@@ -279,7 +279,7 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev)
w90p910_ts->irq_num = platform_get_irq(pdev, 0);
if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt,
- IRQF_DISABLED, "w90p910ts", w90p910_ts)) {
+ 0, "w90p910ts", w90p910_ts)) {
err = -EBUSY;
goto fail4;
}
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 9941d39df43d..1569a3934ab2 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -367,6 +367,20 @@ static int w8001_command(struct w8001 *w8001, unsigned char command,
return rc;
}
+static int w8001_open(struct input_dev *dev)
+{
+ struct w8001 *w8001 = input_get_drvdata(dev);
+
+ return w8001_command(w8001, W8001_CMD_START, false);
+}
+
+static void w8001_close(struct input_dev *dev)
+{
+ struct w8001 *w8001 = input_get_drvdata(dev);
+
+ w8001_command(w8001, W8001_CMD_STOP, false);
+}
+
static int w8001_setup(struct w8001 *w8001)
{
struct input_dev *dev = w8001->dev;
@@ -476,7 +490,7 @@ static int w8001_setup(struct w8001 *w8001)
strlcat(w8001->name, " Touchscreen", sizeof(w8001->name));
- return w8001_command(w8001, W8001_CMD_START, false);
+ return 0;
}
/*
@@ -487,12 +501,12 @@ static void w8001_disconnect(struct serio *serio)
{
struct w8001 *w8001 = serio_get_drvdata(serio);
- input_get_device(w8001->dev);
- input_unregister_device(w8001->dev);
serio_close(serio);
- serio_set_drvdata(serio, NULL);
- input_put_device(w8001->dev);
+
+ input_unregister_device(w8001->dev);
kfree(w8001);
+
+ serio_set_drvdata(serio, NULL);
}
/*
@@ -536,6 +550,11 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
+ input_dev->open = w8001_open;
+ input_dev->close = w8001_close;
+
+ input_set_drvdata(input_dev, w8001);
+
err = input_register_device(w8001->dev);
if (err)
goto fail3;
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index b57b3fa492f3..5414253b185a 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -59,10 +59,14 @@ config AMD_IOMMU_STATS
If unsure, say N.
# Intel IOMMU support
-config DMAR
- bool "Support for DMA Remapping Devices"
+config DMAR_TABLE
+ bool
+
+config INTEL_IOMMU
+ bool "Support for Intel IOMMU using DMA Remapping Devices"
depends on PCI_MSI && ACPI && (X86 || IA64_GENERIC)
select IOMMU_API
+ select DMAR_TABLE
help
DMA remapping (DMAR) devices support enables independent address
translations for Direct Memory Access (DMA) from devices.
@@ -70,18 +74,18 @@ config DMAR
and include PCI device scope covered by these DMA
remapping devices.
-config DMAR_DEFAULT_ON
+config INTEL_IOMMU_DEFAULT_ON
def_bool y
- prompt "Enable DMA Remapping Devices by default"
- depends on DMAR
+ prompt "Enable Intel DMA Remapping Devices by default"
+ depends on INTEL_IOMMU
help
Selecting this option will enable a DMAR device at boot time if
one is found. If this option is not selected, DMAR support can
be enabled by passing intel_iommu=on to the kernel.
-config DMAR_BROKEN_GFX_WA
+config INTEL_IOMMU_BROKEN_GFX_WA
bool "Workaround broken graphics drivers (going away soon)"
- depends on DMAR && BROKEN && X86
+ depends on INTEL_IOMMU && BROKEN && X86
---help---
Current Graphics drivers tend to use physical address
for DMA and avoid using DMA APIs. Setting this config
@@ -90,21 +94,41 @@ config DMAR_BROKEN_GFX_WA
to use physical addresses for DMA, at least until this
option is removed in the 2.6.32 kernel.
-config DMAR_FLOPPY_WA
+config INTEL_IOMMU_FLOPPY_WA
def_bool y
- depends on DMAR && X86
+ depends on INTEL_IOMMU && X86
---help---
Floppy disk drivers are known to bypass DMA API calls
thereby failing to work when IOMMU is enabled. This
workaround will setup a 1:1 mapping for the first
16MiB to make floppy (an ISA device) work.
-config INTR_REMAP
+config IRQ_REMAP
bool "Support for Interrupt Remapping (EXPERIMENTAL)"
depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
+ select DMAR_TABLE
---help---
Supports Interrupt remapping for IO-APIC and MSI devices.
To use x2apic mode in the CPU's which support x2APIC enhancements or
to support platforms with CPU's having > 8 bit APIC ID, say Y.
+# OMAP IOMMU support
+config OMAP_IOMMU
+ bool "OMAP IOMMU Support"
+ depends on ARCH_OMAP
+ select IOMMU_API
+
+config OMAP_IOVMM
+ tristate "OMAP IO Virtual Memory Manager Support"
+ depends on OMAP_IOMMU
+
+config OMAP_IOMMU_DEBUG
+ tristate "Export OMAP IOMMU/IOVMM internals in DebugFS"
+ depends on OMAP_IOVMM && DEBUG_FS
+ help
+ Select this to see extensive information about
+ the internal state of OMAP IOMMU/IOVMM in debugfs.
+
+ Say N unless you know you need this.
+
endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 4d4d77df7cac..2f4448794bc7 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -1,5 +1,9 @@
obj-$(CONFIG_IOMMU_API) += iommu.o
obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
-obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
-obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
+obj-$(CONFIG_DMAR_TABLE) += dmar.o
+obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
+obj-$(CONFIG_IRQ_REMAP) += intr_remapping.o
+obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
+obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
+obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 0e4227f457af..4ee277a8521a 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1283,7 +1283,7 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom,
if (!pte || !IOMMU_PTE_PRESENT(*pte))
continue;
- dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1);
+ dma_ops_reserve_addresses(dma_dom, i >> PAGE_SHIFT, 1);
}
update_domain(&dma_dom->domain);
@@ -2495,7 +2495,7 @@ static unsigned device_dma_ops_init(void)
void __init amd_iommu_init_api(void)
{
- register_iommu(&amd_iommu_ops);
+ bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
}
int __init amd_iommu_init_dma_ops(void)
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 6dcc7e2d54de..35c1e17fce1d 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -46,7 +46,7 @@
*/
LIST_HEAD(dmar_drhd_units);
-static struct acpi_table_header * __initdata dmar_tbl;
+struct acpi_table_header * __initdata dmar_tbl;
static acpi_size dmar_tbl_size;
static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
@@ -118,8 +118,8 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
return 0;
}
-static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
- struct pci_dev ***devices, u16 segment)
+int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
+ struct pci_dev ***devices, u16 segment)
{
struct acpi_dmar_device_scope *scope;
void * tmp = start;
@@ -217,133 +217,6 @@ static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru)
return ret;
}
-#ifdef CONFIG_DMAR
-LIST_HEAD(dmar_rmrr_units);
-
-static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
-{
- list_add(&rmrr->list, &dmar_rmrr_units);
-}
-
-
-static int __init
-dmar_parse_one_rmrr(struct acpi_dmar_header *header)
-{
- struct acpi_dmar_reserved_memory *rmrr;
- struct dmar_rmrr_unit *rmrru;
-
- rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
- if (!rmrru)
- return -ENOMEM;
-
- rmrru->hdr = header;
- rmrr = (struct acpi_dmar_reserved_memory *)header;
- rmrru->base_address = rmrr->base_address;
- rmrru->end_address = rmrr->end_address;
-
- dmar_register_rmrr_unit(rmrru);
- return 0;
-}
-
-static int __init
-rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
-{
- struct acpi_dmar_reserved_memory *rmrr;
- int ret;
-
- rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
- ret = dmar_parse_dev_scope((void *)(rmrr + 1),
- ((void *)rmrr) + rmrr->header.length,
- &rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
-
- if (ret || (rmrru->devices_cnt == 0)) {
- list_del(&rmrru->list);
- kfree(rmrru);
- }
- return ret;
-}
-
-static LIST_HEAD(dmar_atsr_units);
-
-static int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
-{
- struct acpi_dmar_atsr *atsr;
- struct dmar_atsr_unit *atsru;
-
- atsr = container_of(hdr, struct acpi_dmar_atsr, header);
- atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
- if (!atsru)
- return -ENOMEM;
-
- atsru->hdr = hdr;
- atsru->include_all = atsr->flags & 0x1;
-
- list_add(&atsru->list, &dmar_atsr_units);
-
- return 0;
-}
-
-static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
-{
- int rc;
- struct acpi_dmar_atsr *atsr;
-
- if (atsru->include_all)
- return 0;
-
- atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
- rc = dmar_parse_dev_scope((void *)(atsr + 1),
- (void *)atsr + atsr->header.length,
- &atsru->devices_cnt, &atsru->devices,
- atsr->segment);
- if (rc || !atsru->devices_cnt) {
- list_del(&atsru->list);
- kfree(atsru);
- }
-
- return rc;
-}
-
-int dmar_find_matched_atsr_unit(struct pci_dev *dev)
-{
- int i;
- struct pci_bus *bus;
- struct acpi_dmar_atsr *atsr;
- struct dmar_atsr_unit *atsru;
-
- dev = pci_physfn(dev);
-
- list_for_each_entry(atsru, &dmar_atsr_units, list) {
- atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
- if (atsr->segment == pci_domain_nr(dev->bus))
- goto found;
- }
-
- return 0;
-
-found:
- for (bus = dev->bus; bus; bus = bus->parent) {
- struct pci_dev *bridge = bus->self;
-
- if (!bridge || !pci_is_pcie(bridge) ||
- bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
- return 0;
-
- if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
- for (i = 0; i < atsru->devices_cnt; i++)
- if (atsru->devices[i] == bridge)
- return 1;
- break;
- }
- }
-
- if (atsru->include_all)
- return 1;
-
- return 0;
-}
-#endif
-
#ifdef CONFIG_ACPI_NUMA
static int __init
dmar_parse_one_rhsa(struct acpi_dmar_header *header)
@@ -484,14 +357,10 @@ parse_dmar_table(void)
ret = dmar_parse_one_drhd(entry_header);
break;
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
-#ifdef CONFIG_DMAR
ret = dmar_parse_one_rmrr(entry_header);
-#endif
break;
case ACPI_DMAR_TYPE_ATSR:
-#ifdef CONFIG_DMAR
ret = dmar_parse_one_atsr(entry_header);
-#endif
break;
case ACPI_DMAR_HARDWARE_AFFINITY:
#ifdef CONFIG_ACPI_NUMA
@@ -557,34 +426,31 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
int __init dmar_dev_scope_init(void)
{
+ static int dmar_dev_scope_initialized;
struct dmar_drhd_unit *drhd, *drhd_n;
int ret = -ENODEV;
+ if (dmar_dev_scope_initialized)
+ return dmar_dev_scope_initialized;
+
+ if (list_empty(&dmar_drhd_units))
+ goto fail;
+
list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) {
ret = dmar_parse_dev(drhd);
if (ret)
- return ret;
+ goto fail;
}
-#ifdef CONFIG_DMAR
- {
- struct dmar_rmrr_unit *rmrr, *rmrr_n;
- struct dmar_atsr_unit *atsr, *atsr_n;
-
- list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
- ret = rmrr_parse_dev(rmrr);
- if (ret)
- return ret;
- }
+ ret = dmar_parse_rmrr_atsr_dev();
+ if (ret)
+ goto fail;
- list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
- ret = atsr_parse_dev(atsr);
- if (ret)
- return ret;
- }
- }
-#endif
+ dmar_dev_scope_initialized = 1;
+ return 0;
+fail:
+ dmar_dev_scope_initialized = ret;
return ret;
}
@@ -611,14 +477,6 @@ int __init dmar_table_init(void)
return -ENODEV;
}
-#ifdef CONFIG_DMAR
- if (list_empty(&dmar_rmrr_units))
- printk(KERN_INFO PREFIX "No RMRR found\n");
-
- if (list_empty(&dmar_atsr_units))
- printk(KERN_INFO PREFIX "No ATSR found\n");
-#endif
-
return 0;
}
@@ -682,9 +540,6 @@ int __init check_zero_address(void)
return 1;
failed:
-#ifdef CONFIG_DMAR
- dmar_disabled = 1;
-#endif
return 0;
}
@@ -696,22 +551,21 @@ int __init detect_intel_iommu(void)
if (ret)
ret = check_zero_address();
{
-#ifdef CONFIG_INTR_REMAP
struct acpi_table_dmar *dmar;
dmar = (struct acpi_table_dmar *) dmar_tbl;
- if (ret && cpu_has_x2apic && dmar->flags & 0x1)
+
+ if (ret && intr_remapping_enabled && cpu_has_x2apic &&
+ dmar->flags & 0x1)
printk(KERN_INFO
- "Queued invalidation will be enabled to support "
- "x2apic and Intr-remapping.\n");
-#endif
-#ifdef CONFIG_DMAR
+ "Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
+
if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
iommu_detected = 1;
/* Make sure ACS will be enabled */
pci_request_acs();
}
-#endif
+
#ifdef CONFIG_X86
if (ret)
x86_init.iommu.iommu_init = intel_iommu_init;
@@ -758,7 +612,6 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
goto err_unmap;
}
-#ifdef CONFIG_DMAR
agaw = iommu_calculate_agaw(iommu);
if (agaw < 0) {
printk(KERN_ERR
@@ -773,7 +626,6 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
iommu->seq_id);
goto err_unmap;
}
-#endif
iommu->agaw = agaw;
iommu->msagaw = msagaw;
@@ -800,7 +652,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
(unsigned long long)iommu->cap,
(unsigned long long)iommu->ecap);
- spin_lock_init(&iommu->register_lock);
+ raw_spin_lock_init(&iommu->register_lock);
drhd->iommu = iommu;
return 0;
@@ -817,9 +669,7 @@ void free_iommu(struct intel_iommu *iommu)
if (!iommu)
return;
-#ifdef CONFIG_DMAR
free_dmar_iommu(iommu);
-#endif
if (iommu->reg)
iounmap(iommu->reg);
@@ -921,11 +771,11 @@ int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
restart:
rc = 0;
- spin_lock_irqsave(&qi->q_lock, flags);
+ raw_spin_lock_irqsave(&qi->q_lock, flags);
while (qi->free_cnt < 3) {
- spin_unlock_irqrestore(&qi->q_lock, flags);
+ raw_spin_unlock_irqrestore(&qi->q_lock, flags);
cpu_relax();
- spin_lock_irqsave(&qi->q_lock, flags);
+ raw_spin_lock_irqsave(&qi->q_lock, flags);
}
index = qi->free_head;
@@ -965,15 +815,15 @@ restart:
if (rc)
break;
- spin_unlock(&qi->q_lock);
+ raw_spin_unlock(&qi->q_lock);
cpu_relax();
- spin_lock(&qi->q_lock);
+ raw_spin_lock(&qi->q_lock);
}
qi->desc_status[index] = QI_DONE;
reclaim_free_desc(qi);
- spin_unlock_irqrestore(&qi->q_lock, flags);
+ raw_spin_unlock_irqrestore(&qi->q_lock, flags);
if (rc == -EAGAIN)
goto restart;
@@ -1062,7 +912,7 @@ void dmar_disable_qi(struct intel_iommu *iommu)
if (!ecap_qis(iommu->ecap))
return;
- spin_lock_irqsave(&iommu->register_lock, flags);
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
if (!(sts & DMA_GSTS_QIES))
@@ -1082,7 +932,7 @@ void dmar_disable_qi(struct intel_iommu *iommu)
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl,
!(sts & DMA_GSTS_QIES), sts);
end:
- spin_unlock_irqrestore(&iommu->register_lock, flags);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
}
/*
@@ -1097,7 +947,7 @@ static void __dmar_enable_qi(struct intel_iommu *iommu)
qi->free_head = qi->free_tail = 0;
qi->free_cnt = QI_LENGTH;
- spin_lock_irqsave(&iommu->register_lock, flags);
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
/* write zero to the tail reg */
writel(0, iommu->reg + DMAR_IQT_REG);
@@ -1110,7 +960,7 @@ static void __dmar_enable_qi(struct intel_iommu *iommu)
/* Make sure hardware complete it */
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
- spin_unlock_irqrestore(&iommu->register_lock, flags);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
}
/*
@@ -1159,7 +1009,7 @@ int dmar_enable_qi(struct intel_iommu *iommu)
qi->free_head = qi->free_tail = 0;
qi->free_cnt = QI_LENGTH;
- spin_lock_init(&qi->q_lock);
+ raw_spin_lock_init(&qi->q_lock);
__dmar_enable_qi(iommu);
@@ -1225,11 +1075,11 @@ void dmar_msi_unmask(struct irq_data *data)
unsigned long flag;
/* unmask it */
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
writel(0, iommu->reg + DMAR_FECTL_REG);
/* Read a reg to force flush the post write */
readl(iommu->reg + DMAR_FECTL_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
void dmar_msi_mask(struct irq_data *data)
@@ -1238,11 +1088,11 @@ void dmar_msi_mask(struct irq_data *data)
struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
/* mask it */
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
/* Read a reg to force flush the post write */
readl(iommu->reg + DMAR_FECTL_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
void dmar_msi_write(int irq, struct msi_msg *msg)
@@ -1250,11 +1100,11 @@ void dmar_msi_write(int irq, struct msi_msg *msg)
struct intel_iommu *iommu = irq_get_handler_data(irq);
unsigned long flag;
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
void dmar_msi_read(int irq, struct msi_msg *msg)
@@ -1262,11 +1112,11 @@ void dmar_msi_read(int irq, struct msi_msg *msg)
struct intel_iommu *iommu = irq_get_handler_data(irq);
unsigned long flag;
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
@@ -1303,7 +1153,7 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
u32 fault_status;
unsigned long flag;
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
fault_status = readl(iommu->reg + DMAR_FSTS_REG);
if (fault_status)
printk(KERN_ERR "DRHD: handling fault status reg %x\n",
@@ -1342,7 +1192,7 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
writel(DMA_FRCD_F, iommu->reg + reg +
fault_index * PRIMARY_FAULT_REG_LEN + 12);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
dmar_fault_do_one(iommu, type, fault_reason,
source_id, guest_addr);
@@ -1350,14 +1200,14 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
fault_index++;
if (fault_index >= cap_num_fault_regs(iommu->cap))
fault_index = 0;
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
}
clear_rest:
/* clear all the other faults */
fault_status = readl(iommu->reg + DMAR_FSTS_REG);
writel(fault_status, iommu->reg + DMAR_FSTS_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
return IRQ_HANDLED;
}
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index a88f3cbb100b..bb161d2fa03c 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -398,11 +398,11 @@ static long list_size;
static void domain_remove_dev_info(struct dmar_domain *domain);
-#ifdef CONFIG_DMAR_DEFAULT_ON
+#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
int dmar_disabled = 0;
#else
int dmar_disabled = 1;
-#endif /*CONFIG_DMAR_DEFAULT_ON*/
+#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
static int dmar_map_gfx = 1;
static int dmar_forcedac;
@@ -939,7 +939,7 @@ static void iommu_set_root_entry(struct intel_iommu *iommu)
addr = iommu->root_entry;
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));
writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
@@ -948,7 +948,7 @@ static void iommu_set_root_entry(struct intel_iommu *iommu)
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
readl, (sts & DMA_GSTS_RTPS), sts);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
static void iommu_flush_write_buffer(struct intel_iommu *iommu)
@@ -959,14 +959,14 @@ static void iommu_flush_write_buffer(struct intel_iommu *iommu)
if (!rwbf_quirk && !cap_rwbf(iommu->cap))
return;
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
/* Make sure hardware complete it */
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
readl, (!(val & DMA_GSTS_WBFS)), val);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
/* return value determine if we need a write buffer flush */
@@ -993,14 +993,14 @@ static void __iommu_flush_context(struct intel_iommu *iommu,
}
val |= DMA_CCMD_ICC;
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
/* Make sure hardware complete it */
IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
dmar_readq, (!(val & DMA_CCMD_ICC)), val);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
/* return value determine if we need a write buffer flush */
@@ -1039,7 +1039,7 @@ static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
if (cap_write_drain(iommu->cap))
val |= DMA_TLB_WRITE_DRAIN;
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
/* Note: Only uses first TLB reg currently */
if (val_iva)
dmar_writeq(iommu->reg + tlb_offset, val_iva);
@@ -1049,7 +1049,7 @@ static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
IOMMU_WAIT_OP(iommu, tlb_offset + 8,
dmar_readq, (!(val & DMA_TLB_IVT)), val);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
/* check IOTLB invalidation granularity */
if (DMA_TLB_IAIG(val) == 0)
@@ -1165,7 +1165,7 @@ static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
u32 pmen;
unsigned long flags;
- spin_lock_irqsave(&iommu->register_lock, flags);
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
pmen = readl(iommu->reg + DMAR_PMEN_REG);
pmen &= ~DMA_PMEN_EPM;
writel(pmen, iommu->reg + DMAR_PMEN_REG);
@@ -1174,7 +1174,7 @@ static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
readl, !(pmen & DMA_PMEN_PRS), pmen);
- spin_unlock_irqrestore(&iommu->register_lock, flags);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
}
static int iommu_enable_translation(struct intel_iommu *iommu)
@@ -1182,7 +1182,7 @@ static int iommu_enable_translation(struct intel_iommu *iommu)
u32 sts;
unsigned long flags;
- spin_lock_irqsave(&iommu->register_lock, flags);
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
iommu->gcmd |= DMA_GCMD_TE;
writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
@@ -1190,7 +1190,7 @@ static int iommu_enable_translation(struct intel_iommu *iommu)
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
readl, (sts & DMA_GSTS_TES), sts);
- spin_unlock_irqrestore(&iommu->register_lock, flags);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
return 0;
}
@@ -1199,7 +1199,7 @@ static int iommu_disable_translation(struct intel_iommu *iommu)
u32 sts;
unsigned long flag;
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
iommu->gcmd &= ~DMA_GCMD_TE;
writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
@@ -1207,7 +1207,7 @@ static int iommu_disable_translation(struct intel_iommu *iommu)
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
readl, (!(sts & DMA_GSTS_TES)), sts);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
return 0;
}
@@ -2157,7 +2157,7 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
rmrr->end_address);
}
-#ifdef CONFIG_DMAR_FLOPPY_WA
+#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
static inline void iommu_prepare_isa(void)
{
struct pci_dev *pdev;
@@ -2180,7 +2180,7 @@ static inline void iommu_prepare_isa(void)
{
return;
}
-#endif /* !CONFIG_DMAR_FLPY_WA */
+#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
static int md_domain_init(struct dmar_domain *domain, int guest_width);
@@ -2491,7 +2491,7 @@ static int __init init_dmars(void)
if (iommu_pass_through)
iommu_identity_mapping |= IDENTMAP_ALL;
-#ifdef CONFIG_DMAR_BROKEN_GFX_WA
+#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
iommu_identity_mapping |= IDENTMAP_GFX;
#endif
@@ -3329,7 +3329,7 @@ static int iommu_suspend(void)
for_each_active_iommu(iommu, drhd) {
iommu_disable_translation(iommu);
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
iommu->iommu_state[SR_DMAR_FECTL_REG] =
readl(iommu->reg + DMAR_FECTL_REG);
@@ -3340,7 +3340,7 @@ static int iommu_suspend(void)
iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
readl(iommu->reg + DMAR_FEUADDR_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
return 0;
@@ -3367,7 +3367,7 @@ static void iommu_resume(void)
for_each_active_iommu(iommu, drhd) {
- spin_lock_irqsave(&iommu->register_lock, flag);
+ raw_spin_lock_irqsave(&iommu->register_lock, flag);
writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
iommu->reg + DMAR_FECTL_REG);
@@ -3378,7 +3378,7 @@ static void iommu_resume(void)
writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
iommu->reg + DMAR_FEUADDR_REG);
- spin_unlock_irqrestore(&iommu->register_lock, flag);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
for_each_active_iommu(iommu, drhd)
@@ -3399,6 +3399,151 @@ static void __init init_iommu_pm_ops(void)
static inline void init_iommu_pm_ops(void) {}
#endif /* CONFIG_PM */
+LIST_HEAD(dmar_rmrr_units);
+
+static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
+{
+ list_add(&rmrr->list, &dmar_rmrr_units);
+}
+
+
+int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header)
+{
+ struct acpi_dmar_reserved_memory *rmrr;
+ struct dmar_rmrr_unit *rmrru;
+
+ rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
+ if (!rmrru)
+ return -ENOMEM;
+
+ rmrru->hdr = header;
+ rmrr = (struct acpi_dmar_reserved_memory *)header;
+ rmrru->base_address = rmrr->base_address;
+ rmrru->end_address = rmrr->end_address;
+
+ dmar_register_rmrr_unit(rmrru);
+ return 0;
+}
+
+static int __init
+rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
+{
+ struct acpi_dmar_reserved_memory *rmrr;
+ int ret;
+
+ rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
+ ret = dmar_parse_dev_scope((void *)(rmrr + 1),
+ ((void *)rmrr) + rmrr->header.length,
+ &rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
+
+ if (ret || (rmrru->devices_cnt == 0)) {
+ list_del(&rmrru->list);
+ kfree(rmrru);
+ }
+ return ret;
+}
+
+static LIST_HEAD(dmar_atsr_units);
+
+int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
+{
+ struct acpi_dmar_atsr *atsr;
+ struct dmar_atsr_unit *atsru;
+
+ atsr = container_of(hdr, struct acpi_dmar_atsr, header);
+ atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
+ if (!atsru)
+ return -ENOMEM;
+
+ atsru->hdr = hdr;
+ atsru->include_all = atsr->flags & 0x1;
+
+ list_add(&atsru->list, &dmar_atsr_units);
+
+ return 0;
+}
+
+static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
+{
+ int rc;
+ struct acpi_dmar_atsr *atsr;
+
+ if (atsru->include_all)
+ return 0;
+
+ atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
+ rc = dmar_parse_dev_scope((void *)(atsr + 1),
+ (void *)atsr + atsr->header.length,
+ &atsru->devices_cnt, &atsru->devices,
+ atsr->segment);
+ if (rc || !atsru->devices_cnt) {
+ list_del(&atsru->list);
+ kfree(atsru);
+ }
+
+ return rc;
+}
+
+int dmar_find_matched_atsr_unit(struct pci_dev *dev)
+{
+ int i;
+ struct pci_bus *bus;
+ struct acpi_dmar_atsr *atsr;
+ struct dmar_atsr_unit *atsru;
+
+ dev = pci_physfn(dev);
+
+ list_for_each_entry(atsru, &dmar_atsr_units, list) {
+ atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
+ if (atsr->segment == pci_domain_nr(dev->bus))
+ goto found;
+ }
+
+ return 0;
+
+found:
+ for (bus = dev->bus; bus; bus = bus->parent) {
+ struct pci_dev *bridge = bus->self;
+
+ if (!bridge || !pci_is_pcie(bridge) ||
+ bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+ return 0;
+
+ if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
+ for (i = 0; i < atsru->devices_cnt; i++)
+ if (atsru->devices[i] == bridge)
+ return 1;
+ break;
+ }
+ }
+
+ if (atsru->include_all)
+ return 1;
+
+ return 0;
+}
+
+int dmar_parse_rmrr_atsr_dev(void)
+{
+ struct dmar_rmrr_unit *rmrr, *rmrr_n;
+ struct dmar_atsr_unit *atsr, *atsr_n;
+ int ret = 0;
+
+ list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
+ ret = rmrr_parse_dev(rmrr);
+ if (ret)
+ return ret;
+ }
+
+ list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
+ ret = atsr_parse_dev(atsr);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
/*
* Here we only respond to action of unbound device from driver.
*
@@ -3448,16 +3593,12 @@ int __init intel_iommu_init(void)
return -ENODEV;
}
- if (dmar_dev_scope_init()) {
+ if (dmar_dev_scope_init() < 0) {
if (force_on)
panic("tboot: Failed to initialize DMAR device scope\n");
return -ENODEV;
}
- /*
- * Check the need for DMA-remapping initialization now.
- * Above initialization will also be used by Interrupt-remapping.
- */
if (no_iommu || dmar_disabled)
return -ENODEV;
@@ -3467,6 +3608,12 @@ int __init intel_iommu_init(void)
return -ENODEV;
}
+ if (list_empty(&dmar_rmrr_units))
+ printk(KERN_INFO "DMAR: No RMRR found\n");
+
+ if (list_empty(&dmar_atsr_units))
+ printk(KERN_INFO "DMAR: No ATSR found\n");
+
if (dmar_init_reserved_ranges()) {
if (force_on)
panic("tboot: Failed to reserve iommu ranges\n");
@@ -3495,7 +3642,7 @@ int __init intel_iommu_init(void)
init_iommu_pm_ops();
- register_iommu(&intel_iommu_ops);
+ bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
bus_register_notifier(&pci_bus_type, &device_nb);
diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c
index 1a89d4a2cadf..07c9f189f314 100644
--- a/drivers/iommu/intr_remapping.c
+++ b/drivers/iommu/intr_remapping.c
@@ -21,6 +21,7 @@ int intr_remapping_enabled;
static int disable_intremap;
static int disable_sourceid_checking;
+static int no_x2apic_optout;
static __init int setup_nointremap(char *str)
{
@@ -34,18 +35,26 @@ static __init int setup_intremap(char *str)
if (!str)
return -EINVAL;
- if (!strncmp(str, "on", 2))
- disable_intremap = 0;
- else if (!strncmp(str, "off", 3))
- disable_intremap = 1;
- else if (!strncmp(str, "nosid", 5))
- disable_sourceid_checking = 1;
+ while (*str) {
+ if (!strncmp(str, "on", 2))
+ disable_intremap = 0;
+ else if (!strncmp(str, "off", 3))
+ disable_intremap = 1;
+ else if (!strncmp(str, "nosid", 5))
+ disable_sourceid_checking = 1;
+ else if (!strncmp(str, "no_x2apic_optout", 16))
+ no_x2apic_optout = 1;
+
+ str += strcspn(str, ",");
+ while (*str == ',')
+ str++;
+ }
return 0;
}
early_param("intremap", setup_intremap);
-static DEFINE_SPINLOCK(irq_2_ir_lock);
+static DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
{
@@ -62,12 +71,12 @@ int get_irte(int irq, struct irte *entry)
if (!entry || !irq_iommu)
return -1;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
+ raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
index = irq_iommu->irte_index + irq_iommu->sub_handle;
*entry = *(irq_iommu->iommu->ir_table->base + index);
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
return 0;
}
@@ -101,7 +110,7 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
return -1;
}
- spin_lock_irqsave(&irq_2_ir_lock, flags);
+ raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
do {
for (i = index; i < index + count; i++)
if (table->base[i].present)
@@ -113,7 +122,7 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
if (index == start_index) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
printk(KERN_ERR "can't allocate an IRTE\n");
return -1;
}
@@ -127,7 +136,7 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
irq_iommu->sub_handle = 0;
irq_iommu->irte_mask = mask;
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
return index;
}
@@ -152,10 +161,10 @@ int map_irq_to_irte_handle(int irq, u16 *sub_handle)
if (!irq_iommu)
return -1;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
+ raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
*sub_handle = irq_iommu->sub_handle;
index = irq_iommu->irte_index;
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
return index;
}
@@ -167,14 +176,14 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
if (!irq_iommu)
return -1;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
+ raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
irq_iommu->iommu = iommu;
irq_iommu->irte_index = index;
irq_iommu->sub_handle = subhandle;
irq_iommu->irte_mask = 0;
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
return 0;
}
@@ -190,7 +199,7 @@ int modify_irte(int irq, struct irte *irte_modified)
if (!irq_iommu)
return -1;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
+ raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
iommu = irq_iommu->iommu;
@@ -202,7 +211,7 @@ int modify_irte(int irq, struct irte *irte_modified)
__iommu_flush_cache(iommu, irte, sizeof(*irte));
rc = qi_flush_iec(iommu, index, 0);
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
return rc;
}
@@ -270,7 +279,7 @@ int free_irte(int irq)
if (!irq_iommu)
return -1;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
+ raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
rc = clear_entries(irq_iommu);
@@ -279,7 +288,7 @@ int free_irte(int irq)
irq_iommu->sub_handle = 0;
irq_iommu->irte_mask = 0;
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
return rc;
}
@@ -409,7 +418,7 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
addr = virt_to_phys((void *)iommu->ir_table->base);
- spin_lock_irqsave(&iommu->register_lock, flags);
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
dmar_writeq(iommu->reg + DMAR_IRTA_REG,
(addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE);
@@ -420,7 +429,7 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
readl, (sts & DMA_GSTS_IRTPS), sts);
- spin_unlock_irqrestore(&iommu->register_lock, flags);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
/*
* global invalidation of interrupt entry cache before enabling
@@ -428,7 +437,7 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
*/
qi_global_iec(iommu);
- spin_lock_irqsave(&iommu->register_lock, flags);
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
/* Enable interrupt-remapping */
iommu->gcmd |= DMA_GCMD_IRE;
@@ -437,7 +446,7 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
readl, (sts & DMA_GSTS_IRES), sts);
- spin_unlock_irqrestore(&iommu->register_lock, flags);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
}
@@ -485,7 +494,7 @@ static void iommu_disable_intr_remapping(struct intel_iommu *iommu)
*/
qi_global_iec(iommu);
- spin_lock_irqsave(&iommu->register_lock, flags);
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
if (!(sts & DMA_GSTS_IRES))
@@ -498,7 +507,16 @@ static void iommu_disable_intr_remapping(struct intel_iommu *iommu)
readl, !(sts & DMA_GSTS_IRES), sts);
end:
- spin_unlock_irqrestore(&iommu->register_lock, flags);
+ raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+static int __init dmar_x2apic_optout(void)
+{
+ struct acpi_table_dmar *dmar;
+ dmar = (struct acpi_table_dmar *)dmar_tbl;
+ if (!dmar || no_x2apic_optout)
+ return 0;
+ return dmar->flags & DMAR_X2APIC_OPT_OUT;
}
int __init intr_remapping_supported(void)
@@ -521,16 +539,25 @@ int __init intr_remapping_supported(void)
return 1;
}
-int __init enable_intr_remapping(int eim)
+int __init enable_intr_remapping(void)
{
struct dmar_drhd_unit *drhd;
int setup = 0;
+ int eim = 0;
if (parse_ioapics_under_ir() != 1) {
printk(KERN_INFO "Not enable interrupt remapping\n");
return -1;
}
+ if (x2apic_supported()) {
+ eim = !dmar_x2apic_optout();
+ WARN(!eim, KERN_WARNING
+ "Your BIOS is broken and requested that x2apic be disabled\n"
+ "This will leave your machine vulnerable to irq-injection attacks\n"
+ "Use 'intremap=no_x2apic_optout' to override BIOS request\n");
+ }
+
for_each_drhd_unit(drhd) {
struct intel_iommu *iommu = drhd->iommu;
@@ -606,8 +633,9 @@ int __init enable_intr_remapping(int eim)
goto error;
intr_remapping_enabled = 1;
+ pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");
- return 0;
+ return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
error:
/*
@@ -745,6 +773,15 @@ int __init parse_ioapics_under_ir(void)
return ir_supported;
}
+int ir_dev_scope_init(void)
+{
+ if (!intr_remapping_enabled)
+ return 0;
+
+ return dmar_dev_scope_init();
+}
+rootfs_initcall(ir_dev_scope_init);
+
void disable_intr_remapping(void)
{
struct dmar_drhd_unit *drhd;
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 6e6b6a11b3ce..2fb2963df553 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/device.h>
+#include <linux/kernel.h>
#include <linux/bug.h>
#include <linux/types.h>
#include <linux/module.h>
@@ -23,32 +25,78 @@
#include <linux/errno.h>
#include <linux/iommu.h>
-static struct iommu_ops *iommu_ops;
+static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops)
+{
+}
-void register_iommu(struct iommu_ops *ops)
+/**
+ * bus_set_iommu - set iommu-callbacks for the bus
+ * @bus: bus.
+ * @ops: the callbacks provided by the iommu-driver
+ *
+ * This function is called by an iommu driver to set the iommu methods
+ * used for a particular bus. Drivers for devices on that bus can use
+ * the iommu-api after these ops are registered.
+ * This special function is needed because IOMMUs are usually devices on
+ * the bus itself, so the iommu drivers are not initialized when the bus
+ * is set up. With this function the iommu-driver can set the iommu-ops
+ * afterwards.
+ */
+int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops)
{
- if (iommu_ops)
- BUG();
+ if (bus->iommu_ops != NULL)
+ return -EBUSY;
+
+ bus->iommu_ops = ops;
+
+ /* Do IOMMU specific setup for this bus-type */
+ iommu_bus_init(bus, ops);
- iommu_ops = ops;
+ return 0;
}
+EXPORT_SYMBOL_GPL(bus_set_iommu);
-bool iommu_found(void)
+bool iommu_present(struct bus_type *bus)
{
- return iommu_ops != NULL;
+ return bus->iommu_ops != NULL;
}
-EXPORT_SYMBOL_GPL(iommu_found);
+EXPORT_SYMBOL_GPL(iommu_present);
-struct iommu_domain *iommu_domain_alloc(void)
+/**
+ * iommu_set_fault_handler() - set a fault handler for an iommu domain
+ * @domain: iommu domain
+ * @handler: fault handler
+ *
+ * This function should be used by IOMMU users which want to be notified
+ * whenever an IOMMU fault happens.
+ *
+ * The fault handler itself should return 0 on success, and an appropriate
+ * error code otherwise.
+ */
+void iommu_set_fault_handler(struct iommu_domain *domain,
+ iommu_fault_handler_t handler)
+{
+ BUG_ON(!domain);
+
+ domain->handler = handler;
+}
+EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
+
+struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
{
struct iommu_domain *domain;
int ret;
+ if (bus == NULL || bus->iommu_ops == NULL)
+ return NULL;
+
domain = kmalloc(sizeof(*domain), GFP_KERNEL);
if (!domain)
return NULL;
- ret = iommu_ops->domain_init(domain);
+ domain->ops = bus->iommu_ops;
+
+ ret = domain->ops->domain_init(domain);
if (ret)
goto out_free;
@@ -63,62 +111,78 @@ EXPORT_SYMBOL_GPL(iommu_domain_alloc);
void iommu_domain_free(struct iommu_domain *domain)
{
- iommu_ops->domain_destroy(domain);
+ if (likely(domain->ops->domain_destroy != NULL))
+ domain->ops->domain_destroy(domain);
+
kfree(domain);
}
EXPORT_SYMBOL_GPL(iommu_domain_free);
int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
{
- return iommu_ops->attach_dev(domain, dev);
+ if (unlikely(domain->ops->attach_dev == NULL))
+ return -ENODEV;
+
+ return domain->ops->attach_dev(domain, dev);
}
EXPORT_SYMBOL_GPL(iommu_attach_device);
void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
{
- iommu_ops->detach_dev(domain, dev);
+ if (unlikely(domain->ops->detach_dev == NULL))
+ return;
+
+ domain->ops->detach_dev(domain, dev);
}
EXPORT_SYMBOL_GPL(iommu_detach_device);
phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long iova)
{
- return iommu_ops->iova_to_phys(domain, iova);
+ if (unlikely(domain->ops->iova_to_phys == NULL))
+ return 0;
+
+ return domain->ops->iova_to_phys(domain, iova);
}
EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
int iommu_domain_has_cap(struct iommu_domain *domain,
unsigned long cap)
{
- return iommu_ops->domain_has_cap(domain, cap);
+ if (unlikely(domain->ops->domain_has_cap == NULL))
+ return 0;
+
+ return domain->ops->domain_has_cap(domain, cap);
}
EXPORT_SYMBOL_GPL(iommu_domain_has_cap);
int iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, int gfp_order, int prot)
{
- unsigned long invalid_mask;
size_t size;
- size = 0x1000UL << gfp_order;
- invalid_mask = size - 1;
+ if (unlikely(domain->ops->map == NULL))
+ return -ENODEV;
- BUG_ON((iova | paddr) & invalid_mask);
+ size = PAGE_SIZE << gfp_order;
- return iommu_ops->map(domain, iova, paddr, gfp_order, prot);
+ BUG_ON(!IS_ALIGNED(iova | paddr, size));
+
+ return domain->ops->map(domain, iova, paddr, gfp_order, prot);
}
EXPORT_SYMBOL_GPL(iommu_map);
int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order)
{
- unsigned long invalid_mask;
size_t size;
- size = 0x1000UL << gfp_order;
- invalid_mask = size - 1;
+ if (unlikely(domain->ops->unmap == NULL))
+ return -ENODEV;
+
+ size = PAGE_SIZE << gfp_order;
- BUG_ON(iova & invalid_mask);
+ BUG_ON(!IS_ALIGNED(iova, size));
- return iommu_ops->unmap(domain, iova, gfp_order);
+ return domain->ops->unmap(domain, iova, gfp_order);
}
EXPORT_SYMBOL_GPL(iommu_unmap);
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 1a584e077c61..5865dd2e28f9 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -543,6 +543,13 @@ static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
}
ret = __flush_iotlb(domain);
+
+ /*
+ * the IOMMU API requires us to return the order of the unmapped
+ * page (on success).
+ */
+ if (!ret)
+ ret = order;
fail:
spin_unlock_irqrestore(&msm_iommu_lock, flags);
return ret;
@@ -721,7 +728,7 @@ static void __init setup_iommu_tex_classes(void)
static int __init msm_iommu_init(void)
{
setup_iommu_tex_classes();
- register_iommu(&msm_iommu_ops);
+ bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
return 0;
}
diff --git a/arch/arm/plat-omap/iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index f07cf2f08e09..9c192e79f806 100644
--- a/arch/arm/plat-omap/iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -21,7 +21,7 @@
#include <plat/iommu.h>
#include <plat/iovmm.h>
-#include "iopgtable.h"
+#include <plat/iopgtable.h>
#define MAXCOLUMN 100 /* for short messages */
@@ -32,7 +32,7 @@ static struct dentry *iommu_debug_root;
static ssize_t debug_read_ver(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- u32 ver = iommu_arch_version();
+ u32 ver = omap_iommu_arch_version();
char buf[MAXCOLUMN], *p = buf;
p += sprintf(p, "H/W version: %d.%d\n", (ver >> 4) & 0xf , ver & 0xf);
@@ -43,7 +43,7 @@ static ssize_t debug_read_ver(struct file *file, char __user *userbuf,
static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct iommu *obj = file->private_data;
+ struct omap_iommu *obj = file->private_data;
char *p, *buf;
ssize_t bytes;
@@ -54,7 +54,7 @@ static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
mutex_lock(&iommu_debug_lock);
- bytes = iommu_dump_ctx(obj, p, count);
+ bytes = omap_iommu_dump_ctx(obj, p, count);
bytes = simple_read_from_buffer(userbuf, count, ppos, buf, bytes);
mutex_unlock(&iommu_debug_lock);
@@ -66,7 +66,7 @@ static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
static ssize_t debug_read_tlb(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct iommu *obj = file->private_data;
+ struct omap_iommu *obj = file->private_data;
char *p, *buf;
ssize_t bytes, rest;
@@ -80,7 +80,7 @@ static ssize_t debug_read_tlb(struct file *file, char __user *userbuf,
p += sprintf(p, "%8s %8s\n", "cam:", "ram:");
p += sprintf(p, "-----------------------------------------\n");
rest = count - (p - buf);
- p += dump_tlb_entries(obj, p, rest);
+ p += omap_dump_tlb_entries(obj, p, rest);
bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
@@ -96,7 +96,7 @@ static ssize_t debug_write_pagetable(struct file *file,
struct iotlb_entry e;
struct cr_regs cr;
int err;
- struct iommu *obj = file->private_data;
+ struct omap_iommu *obj = file->private_data;
char buf[MAXCOLUMN], *p = buf;
count = min(count, sizeof(buf));
@@ -113,8 +113,8 @@ static ssize_t debug_write_pagetable(struct file *file,
return -EINVAL;
}
- iotlb_cr_to_e(&cr, &e);
- err = iopgtable_store_entry(obj, &e);
+ omap_iotlb_cr_to_e(&cr, &e);
+ err = omap_iopgtable_store_entry(obj, &e);
if (err)
dev_err(obj->dev, "%s: fail to store cr\n", __func__);
@@ -136,7 +136,7 @@ static ssize_t debug_write_pagetable(struct file *file,
__err; \
})
-static ssize_t dump_ioptable(struct iommu *obj, char *buf, ssize_t len)
+static ssize_t dump_ioptable(struct omap_iommu *obj, char *buf, ssize_t len)
{
int i;
u32 *iopgd;
@@ -183,7 +183,7 @@ out:
static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct iommu *obj = file->private_data;
+ struct omap_iommu *obj = file->private_data;
char *p, *buf;
size_t bytes;
@@ -211,7 +211,7 @@ static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
static ssize_t debug_read_mmap(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct iommu *obj = file->private_data;
+ struct omap_iommu *obj = file->private_data;
char *p, *buf;
struct iovm_struct *tmp;
int uninitialized_var(i);
@@ -253,7 +253,7 @@ static ssize_t debug_read_mmap(struct file *file, char __user *userbuf,
static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct iommu *obj = file->private_data;
+ struct omap_iommu *obj = file->private_data;
char *p, *buf;
struct iovm_struct *area;
ssize_t bytes;
@@ -267,7 +267,7 @@ static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
mutex_lock(&iommu_debug_lock);
- area = find_iovm_area(obj, (u32)ppos);
+ area = omap_find_iovm_area(obj, (u32)ppos);
if (IS_ERR(area)) {
bytes = -EINVAL;
goto err_out;
@@ -286,7 +286,7 @@ err_out:
static ssize_t debug_write_mem(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
- struct iommu *obj = file->private_data;
+ struct omap_iommu *obj = file->private_data;
struct iovm_struct *area;
char *p, *buf;
@@ -304,7 +304,7 @@ static ssize_t debug_write_mem(struct file *file, const char __user *userbuf,
goto err_out;
}
- area = find_iovm_area(obj, (u32)ppos);
+ area = omap_find_iovm_area(obj, (u32)ppos);
if (IS_ERR(area)) {
count = -EINVAL;
goto err_out;
@@ -360,7 +360,7 @@ DEBUG_FOPS(mem);
static int iommu_debug_register(struct device *dev, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
- struct iommu *obj = platform_get_drvdata(pdev);
+ struct omap_iommu *obj = platform_get_drvdata(pdev);
struct dentry *d, *parent;
if (!obj || !obj->dev)
@@ -396,7 +396,7 @@ static int __init iommu_debug_init(void)
return -ENOMEM;
iommu_debug_root = d;
- err = foreach_iommu_device(d, iommu_debug_register);
+ err = omap_foreach_iommu_device(d, iommu_debug_register);
if (err)
goto err_out;
return 0;
diff --git a/arch/arm/plat-omap/iommu.c b/drivers/iommu/omap-iommu.c
index 34fc31ee9081..8f32b2bf7587 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -18,18 +18,34 @@
#include <linux/ioport.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/iommu.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
#include <asm/cacheflush.h>
#include <plat/iommu.h>
-#include "iopgtable.h"
+#include <plat/iopgtable.h>
#define for_each_iotlb_cr(obj, n, __i, cr) \
for (__i = 0; \
(__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \
__i++)
+/**
+ * struct omap_iommu_domain - omap iommu domain
+ * @pgtable: the page table
+ * @iommu_dev: an omap iommu device attached to this domain. only a single
+ * iommu device can be attached for now.
+ * @lock: domain lock, should be taken when attaching/detaching
+ */
+struct omap_iommu_domain {
+ u32 *pgtable;
+ struct omap_iommu *iommu_dev;
+ spinlock_t lock;
+};
+
/* accommodate the difference between omap1 and omap2/3 */
static const struct iommu_functions *arch_iommu;
@@ -37,13 +53,13 @@ static struct platform_driver omap_iommu_driver;
static struct kmem_cache *iopte_cachep;
/**
- * install_iommu_arch - Install archtecure specific iommu functions
+ * omap_install_iommu_arch - Install archtecure specific iommu functions
* @ops: a pointer to architecture specific iommu functions
*
* There are several kind of iommu algorithm(tlb, pagetable) among
* omap series. This interface installs such an iommu algorighm.
**/
-int install_iommu_arch(const struct iommu_functions *ops)
+int omap_install_iommu_arch(const struct iommu_functions *ops)
{
if (arch_iommu)
return -EBUSY;
@@ -51,53 +67,53 @@ int install_iommu_arch(const struct iommu_functions *ops)
arch_iommu = ops;
return 0;
}
-EXPORT_SYMBOL_GPL(install_iommu_arch);
+EXPORT_SYMBOL_GPL(omap_install_iommu_arch);
/**
- * uninstall_iommu_arch - Uninstall archtecure specific iommu functions
+ * omap_uninstall_iommu_arch - Uninstall archtecure specific iommu functions
* @ops: a pointer to architecture specific iommu functions
*
* This interface uninstalls the iommu algorighm installed previously.
**/
-void uninstall_iommu_arch(const struct iommu_functions *ops)
+void omap_uninstall_iommu_arch(const struct iommu_functions *ops)
{
if (arch_iommu != ops)
pr_err("%s: not your arch\n", __func__);
arch_iommu = NULL;
}
-EXPORT_SYMBOL_GPL(uninstall_iommu_arch);
+EXPORT_SYMBOL_GPL(omap_uninstall_iommu_arch);
/**
- * iommu_save_ctx - Save registers for pm off-mode support
+ * omap_iommu_save_ctx - Save registers for pm off-mode support
* @obj: target iommu
**/
-void iommu_save_ctx(struct iommu *obj)
+void omap_iommu_save_ctx(struct omap_iommu *obj)
{
arch_iommu->save_ctx(obj);
}
-EXPORT_SYMBOL_GPL(iommu_save_ctx);
+EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
/**
- * iommu_restore_ctx - Restore registers for pm off-mode support
+ * omap_iommu_restore_ctx - Restore registers for pm off-mode support
* @obj: target iommu
**/
-void iommu_restore_ctx(struct iommu *obj)
+void omap_iommu_restore_ctx(struct omap_iommu *obj)
{
arch_iommu->restore_ctx(obj);
}
-EXPORT_SYMBOL_GPL(iommu_restore_ctx);
+EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
/**
- * iommu_arch_version - Return running iommu arch version
+ * omap_iommu_arch_version - Return running iommu arch version
**/
-u32 iommu_arch_version(void)
+u32 omap_iommu_arch_version(void)
{
return arch_iommu->version;
}
-EXPORT_SYMBOL_GPL(iommu_arch_version);
+EXPORT_SYMBOL_GPL(omap_iommu_arch_version);
-static int iommu_enable(struct iommu *obj)
+static int iommu_enable(struct omap_iommu *obj)
{
int err;
@@ -115,7 +131,7 @@ static int iommu_enable(struct iommu *obj)
return err;
}
-static void iommu_disable(struct iommu *obj)
+static void iommu_disable(struct omap_iommu *obj)
{
if (!obj)
return;
@@ -130,13 +146,13 @@ static void iommu_disable(struct iommu *obj)
/*
* TLB operations
*/
-void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
+void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
{
BUG_ON(!cr || !e);
arch_iommu->cr_to_e(cr, e);
}
-EXPORT_SYMBOL_GPL(iotlb_cr_to_e);
+EXPORT_SYMBOL_GPL(omap_iotlb_cr_to_e);
static inline int iotlb_cr_valid(struct cr_regs *cr)
{
@@ -146,7 +162,7 @@ static inline int iotlb_cr_valid(struct cr_regs *cr)
return arch_iommu->cr_valid(cr);
}
-static inline struct cr_regs *iotlb_alloc_cr(struct iommu *obj,
+static inline struct cr_regs *iotlb_alloc_cr(struct omap_iommu *obj,
struct iotlb_entry *e)
{
if (!e)
@@ -155,23 +171,22 @@ static inline struct cr_regs *iotlb_alloc_cr(struct iommu *obj,
return arch_iommu->alloc_cr(obj, e);
}
-u32 iotlb_cr_to_virt(struct cr_regs *cr)
+static u32 iotlb_cr_to_virt(struct cr_regs *cr)
{
return arch_iommu->cr_to_virt(cr);
}
-EXPORT_SYMBOL_GPL(iotlb_cr_to_virt);
static u32 get_iopte_attr(struct iotlb_entry *e)
{
return arch_iommu->get_pte_attr(e);
}
-static u32 iommu_report_fault(struct iommu *obj, u32 *da)
+static u32 iommu_report_fault(struct omap_iommu *obj, u32 *da)
{
return arch_iommu->fault_isr(obj, da);
}
-static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
+static void iotlb_lock_get(struct omap_iommu *obj, struct iotlb_lock *l)
{
u32 val;
@@ -182,7 +197,7 @@ static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
}
-static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l)
+static void iotlb_lock_set(struct omap_iommu *obj, struct iotlb_lock *l)
{
u32 val;
@@ -192,12 +207,12 @@ static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l)
iommu_write_reg(obj, val, MMU_LOCK);
}
-static void iotlb_read_cr(struct iommu *obj, struct cr_regs *cr)
+static void iotlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
{
arch_iommu->tlb_read_cr(obj, cr);
}
-static void iotlb_load_cr(struct iommu *obj, struct cr_regs *cr)
+static void iotlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
{
arch_iommu->tlb_load_cr(obj, cr);
@@ -211,7 +226,7 @@ static void iotlb_load_cr(struct iommu *obj, struct cr_regs *cr)
* @cr: contents of cam and ram register
* @buf: output buffer
**/
-static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
+static inline ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr,
char *buf)
{
BUG_ON(!cr || !buf);
@@ -220,7 +235,7 @@ static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
}
/* only used in iotlb iteration for-loop */
-static struct cr_regs __iotlb_read_cr(struct iommu *obj, int n)
+static struct cr_regs __iotlb_read_cr(struct omap_iommu *obj, int n)
{
struct cr_regs cr;
struct iotlb_lock l;
@@ -238,7 +253,8 @@ static struct cr_regs __iotlb_read_cr(struct iommu *obj, int n)
* @obj: target iommu
* @e: an iommu tlb entry info
**/
-int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
+#ifdef PREFETCH_IOTLB
+static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
{
int err = 0;
struct iotlb_lock l;
@@ -294,7 +310,20 @@ out:
clk_disable(obj->clk);
return err;
}
-EXPORT_SYMBOL_GPL(load_iotlb_entry);
+
+#else /* !PREFETCH_IOTLB */
+
+static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+ return 0;
+}
+
+#endif /* !PREFETCH_IOTLB */
+
+static int prefetch_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+ return load_iotlb_entry(obj, e);
+}
/**
* flush_iotlb_page - Clear an iommu tlb entry
@@ -303,7 +332,7 @@ EXPORT_SYMBOL_GPL(load_iotlb_entry);
*
* Clear an iommu tlb entry which includes 'da' address.
**/
-void flush_iotlb_page(struct iommu *obj, u32 da)
+static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
{
int i;
struct cr_regs cr;
@@ -332,33 +361,12 @@ void flush_iotlb_page(struct iommu *obj, u32 da)
if (i == obj->nr_tlb_entries)
dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
}
-EXPORT_SYMBOL_GPL(flush_iotlb_page);
-
-/**
- * flush_iotlb_range - Clear an iommu tlb entries
- * @obj: target iommu
- * @start: iommu device virtual address(start)
- * @end: iommu device virtual address(end)
- *
- * Clear an iommu tlb entry which includes 'da' address.
- **/
-void flush_iotlb_range(struct iommu *obj, u32 start, u32 end)
-{
- u32 da = start;
-
- while (da < end) {
- flush_iotlb_page(obj, da);
- /* FIXME: Optimize for multiple page size */
- da += IOPTE_SIZE;
- }
-}
-EXPORT_SYMBOL_GPL(flush_iotlb_range);
/**
* flush_iotlb_all - Clear all iommu tlb entries
* @obj: target iommu
**/
-void flush_iotlb_all(struct iommu *obj)
+static void flush_iotlb_all(struct omap_iommu *obj)
{
struct iotlb_lock l;
@@ -372,28 +380,10 @@ void flush_iotlb_all(struct iommu *obj)
clk_disable(obj->clk);
}
-EXPORT_SYMBOL_GPL(flush_iotlb_all);
-
-/**
- * iommu_set_twl - enable/disable table walking logic
- * @obj: target iommu
- * @on: enable/disable
- *
- * Function used to enable/disable TWL. If one wants to work
- * exclusively with locked TLB entries and receive notifications
- * for TLB miss then call this function to disable TWL.
- */
-void iommu_set_twl(struct iommu *obj, bool on)
-{
- clk_enable(obj->clk);
- arch_iommu->set_twl(obj, on);
- clk_disable(obj->clk);
-}
-EXPORT_SYMBOL_GPL(iommu_set_twl);
-#if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
+#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
-ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes)
+ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
{
if (!obj || !buf)
return -EINVAL;
@@ -406,9 +396,10 @@ ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes)
return bytes;
}
-EXPORT_SYMBOL_GPL(iommu_dump_ctx);
+EXPORT_SYMBOL_GPL(omap_iommu_dump_ctx);
-static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num)
+static int
+__dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
{
int i;
struct iotlb_lock saved;
@@ -431,11 +422,11 @@ static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num)
}
/**
- * dump_tlb_entries - dump cr arrays to given buffer
+ * omap_dump_tlb_entries - dump cr arrays to given buffer
* @obj: target iommu
* @buf: output buffer
**/
-size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t bytes)
+size_t omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, ssize_t bytes)
{
int i, num;
struct cr_regs *cr;
@@ -455,14 +446,14 @@ size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t bytes)
return p - buf;
}
-EXPORT_SYMBOL_GPL(dump_tlb_entries);
+EXPORT_SYMBOL_GPL(omap_dump_tlb_entries);
-int foreach_iommu_device(void *data, int (*fn)(struct device *, void *))
+int omap_foreach_iommu_device(void *data, int (*fn)(struct device *, void *))
{
return driver_for_each_device(&omap_iommu_driver.driver,
NULL, data, fn);
}
-EXPORT_SYMBOL_GPL(foreach_iommu_device);
+EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
#endif /* CONFIG_OMAP_IOMMU_DEBUG_MODULE */
@@ -495,7 +486,7 @@ static void iopte_free(u32 *iopte)
kmem_cache_free(iopte_cachep, iopte);
}
-static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da)
+static u32 *iopte_alloc(struct omap_iommu *obj, u32 *iopgd, u32 da)
{
u32 *iopte;
@@ -533,7 +524,7 @@ pte_ready:
return iopte;
}
-static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot)
+static int iopgd_alloc_section(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
{
u32 *iopgd = iopgd_offset(obj, da);
@@ -548,7 +539,7 @@ static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot)
return 0;
}
-static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot)
+static int iopgd_alloc_super(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
{
u32 *iopgd = iopgd_offset(obj, da);
int i;
@@ -565,7 +556,7 @@ static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot)
return 0;
}
-static int iopte_alloc_page(struct iommu *obj, u32 da, u32 pa, u32 prot)
+static int iopte_alloc_page(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
{
u32 *iopgd = iopgd_offset(obj, da);
u32 *iopte = iopte_alloc(obj, iopgd, da);
@@ -582,7 +573,7 @@ static int iopte_alloc_page(struct iommu *obj, u32 da, u32 pa, u32 prot)
return 0;
}
-static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot)
+static int iopte_alloc_large(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
{
u32 *iopgd = iopgd_offset(obj, da);
u32 *iopte = iopte_alloc(obj, iopgd, da);
@@ -603,9 +594,10 @@ static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot)
return 0;
}
-static int iopgtable_store_entry_core(struct iommu *obj, struct iotlb_entry *e)
+static int
+iopgtable_store_entry_core(struct omap_iommu *obj, struct iotlb_entry *e)
{
- int (*fn)(struct iommu *, u32, u32, u32);
+ int (*fn)(struct omap_iommu *, u32, u32, u32);
u32 prot;
int err;
@@ -641,23 +633,21 @@ static int iopgtable_store_entry_core(struct iommu *obj, struct iotlb_entry *e)
}
/**
- * iopgtable_store_entry - Make an iommu pte entry
+ * omap_iopgtable_store_entry - Make an iommu pte entry
* @obj: target iommu
* @e: an iommu tlb entry info
**/
-int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e)
+int omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e)
{
int err;
flush_iotlb_page(obj, e->da);
err = iopgtable_store_entry_core(obj, e);
-#ifdef PREFETCH_IOTLB
if (!err)
- load_iotlb_entry(obj, e);
-#endif
+ prefetch_iotlb_entry(obj, e);
return err;
}
-EXPORT_SYMBOL_GPL(iopgtable_store_entry);
+EXPORT_SYMBOL_GPL(omap_iopgtable_store_entry);
/**
* iopgtable_lookup_entry - Lookup an iommu pte entry
@@ -666,7 +656,8 @@ EXPORT_SYMBOL_GPL(iopgtable_store_entry);
* @ppgd: iommu pgd entry pointer to be returned
* @ppte: iommu pte entry pointer to be returned
**/
-void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
+static void
+iopgtable_lookup_entry(struct omap_iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
{
u32 *iopgd, *iopte = NULL;
@@ -680,9 +671,8 @@ out:
*ppgd = iopgd;
*ppte = iopte;
}
-EXPORT_SYMBOL_GPL(iopgtable_lookup_entry);
-static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da)
+static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
{
size_t bytes;
u32 *iopgd = iopgd_offset(obj, da);
@@ -735,7 +725,7 @@ out:
* @obj: target iommu
* @da: iommu device virtual address
**/
-size_t iopgtable_clear_entry(struct iommu *obj, u32 da)
+static size_t iopgtable_clear_entry(struct omap_iommu *obj, u32 da)
{
size_t bytes;
@@ -748,9 +738,8 @@ size_t iopgtable_clear_entry(struct iommu *obj, u32 da)
return bytes;
}
-EXPORT_SYMBOL_GPL(iopgtable_clear_entry);
-static void iopgtable_clear_entry_all(struct iommu *obj)
+static void iopgtable_clear_entry_all(struct omap_iommu *obj)
{
int i;
@@ -785,7 +774,8 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
{
u32 da, errs;
u32 *iopgd, *iopte;
- struct iommu *obj = data;
+ struct omap_iommu *obj = data;
+ struct iommu_domain *domain = obj->domain;
if (!obj->refcount)
return IRQ_NONE;
@@ -797,7 +787,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
return IRQ_HANDLED;
/* Fault callback or TLB/PTE Dynamic loading */
- if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv))
+ if (!report_iommu_fault(domain, obj->dev, da, 0))
return IRQ_HANDLED;
iommu_disable(obj);
@@ -821,7 +811,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
static int device_match_by_alias(struct device *dev, void *data)
{
- struct iommu *obj = to_iommu(dev);
+ struct omap_iommu *obj = to_iommu(dev);
const char *name = data;
pr_debug("%s: %s %s\n", __func__, obj->name, name);
@@ -830,57 +820,55 @@ static int device_match_by_alias(struct device *dev, void *data)
}
/**
- * iommu_set_da_range - Set a valid device address range
- * @obj: target iommu
- * @start Start of valid range
- * @end End of valid range
- **/
-int iommu_set_da_range(struct iommu *obj, u32 start, u32 end)
+ * omap_find_iommu_device() - find an omap iommu device by name
+ * @name: name of the iommu device
+ *
+ * The generic iommu API requires the caller to provide the device
+ * he wishes to attach to a certain iommu domain.
+ *
+ * Drivers generally should not bother with this as it should just
+ * be taken care of by the DMA-API using dev_archdata.
+ *
+ * This function is provided as an interim solution until the latter
+ * materializes, and omap3isp is fully migrated to the DMA-API.
+ */
+struct device *omap_find_iommu_device(const char *name)
{
-
- if (!obj)
- return -EFAULT;
-
- if (end < start || !PAGE_ALIGN(start | end))
- return -EINVAL;
-
- obj->da_start = start;
- obj->da_end = end;
-
- return 0;
+ return driver_find_device(&omap_iommu_driver.driver, NULL,
+ (void *)name,
+ device_match_by_alias);
}
-EXPORT_SYMBOL_GPL(iommu_set_da_range);
+EXPORT_SYMBOL_GPL(omap_find_iommu_device);
/**
- * iommu_get - Get iommu handler
- * @name: target iommu name
+ * omap_iommu_attach() - attach iommu device to an iommu domain
+ * @dev: target omap iommu device
+ * @iopgd: page table
**/
-struct iommu *iommu_get(const char *name)
+static struct omap_iommu *omap_iommu_attach(struct device *dev, u32 *iopgd)
{
int err = -ENOMEM;
- struct device *dev;
- struct iommu *obj;
-
- dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
- device_match_by_alias);
- if (!dev)
- return ERR_PTR(-ENODEV);
-
- obj = to_iommu(dev);
+ struct omap_iommu *obj = to_iommu(dev);
- mutex_lock(&obj->iommu_lock);
+ spin_lock(&obj->iommu_lock);
- if (obj->refcount++ == 0) {
- err = iommu_enable(obj);
- if (err)
- goto err_enable;
- flush_iotlb_all(obj);
+ /* an iommu device can only be attached once */
+ if (++obj->refcount > 1) {
+ dev_err(dev, "%s: already attached!\n", obj->name);
+ err = -EBUSY;
+ goto err_enable;
}
+ obj->iopgd = iopgd;
+ err = iommu_enable(obj);
+ if (err)
+ goto err_enable;
+ flush_iotlb_all(obj);
+
if (!try_module_get(obj->owner))
goto err_module;
- mutex_unlock(&obj->iommu_lock);
+ spin_unlock(&obj->iommu_lock);
dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
return obj;
@@ -890,59 +878,32 @@ err_module:
iommu_disable(obj);
err_enable:
obj->refcount--;
- mutex_unlock(&obj->iommu_lock);
+ spin_unlock(&obj->iommu_lock);
return ERR_PTR(err);
}
-EXPORT_SYMBOL_GPL(iommu_get);
/**
- * iommu_put - Put back iommu handler
+ * omap_iommu_detach - release iommu device
* @obj: target iommu
**/
-void iommu_put(struct iommu *obj)
+static void omap_iommu_detach(struct omap_iommu *obj)
{
if (!obj || IS_ERR(obj))
return;
- mutex_lock(&obj->iommu_lock);
+ spin_lock(&obj->iommu_lock);
if (--obj->refcount == 0)
iommu_disable(obj);
module_put(obj->owner);
- mutex_unlock(&obj->iommu_lock);
-
- dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
-}
-EXPORT_SYMBOL_GPL(iommu_put);
-
-int iommu_set_isr(const char *name,
- int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
- void *priv),
- void *isr_priv)
-{
- struct device *dev;
- struct iommu *obj;
+ obj->iopgd = NULL;
- dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
- device_match_by_alias);
- if (!dev)
- return -ENODEV;
+ spin_unlock(&obj->iommu_lock);
- obj = to_iommu(dev);
- mutex_lock(&obj->iommu_lock);
- if (obj->refcount != 0) {
- mutex_unlock(&obj->iommu_lock);
- return -EBUSY;
- }
- obj->isr = isr;
- obj->isr_priv = isr_priv;
- mutex_unlock(&obj->iommu_lock);
-
- return 0;
+ dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
}
-EXPORT_SYMBOL_GPL(iommu_set_isr);
/*
* OMAP Device MMU(IOMMU) detection
@@ -950,9 +911,8 @@ EXPORT_SYMBOL_GPL(iommu_set_isr);
static int __devinit omap_iommu_probe(struct platform_device *pdev)
{
int err = -ENODEV;
- void *p;
int irq;
- struct iommu *obj;
+ struct omap_iommu *obj;
struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
@@ -974,7 +934,7 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
obj->da_start = pdata->da_start;
obj->da_end = pdata->da_end;
- mutex_init(&obj->iommu_lock);
+ spin_lock_init(&obj->iommu_lock);
mutex_init(&obj->mmap_lock);
spin_lock_init(&obj->page_table_lock);
INIT_LIST_HEAD(&obj->mmap);
@@ -1009,22 +969,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
goto err_irq;
platform_set_drvdata(pdev, obj);
- p = (void *)__get_free_pages(GFP_KERNEL, get_order(IOPGD_TABLE_SIZE));
- if (!p) {
- err = -ENOMEM;
- goto err_pgd;
- }
- memset(p, 0, IOPGD_TABLE_SIZE);
- clean_dcache_area(p, IOPGD_TABLE_SIZE);
- obj->iopgd = p;
-
- BUG_ON(!IS_ALIGNED((unsigned long)obj->iopgd, IOPGD_TABLE_SIZE));
-
dev_info(&pdev->dev, "%s registered\n", obj->name);
return 0;
-err_pgd:
- free_irq(irq, obj);
err_irq:
iounmap(obj->regbase);
err_ioremap:
@@ -1040,12 +987,11 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
{
int irq;
struct resource *res;
- struct iommu *obj = platform_get_drvdata(pdev);
+ struct omap_iommu *obj = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
iopgtable_clear_entry_all(obj);
- free_pages((unsigned long)obj->iopgd, get_order(IOPGD_TABLE_SIZE));
irq = platform_get_irq(pdev, 0);
free_irq(irq, obj);
@@ -1072,6 +1018,201 @@ static void iopte_cachep_ctor(void *iopte)
clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
}
+static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
+ phys_addr_t pa, int order, int prot)
+{
+ struct omap_iommu_domain *omap_domain = domain->priv;
+ struct omap_iommu *oiommu = omap_domain->iommu_dev;
+ struct device *dev = oiommu->dev;
+ size_t bytes = PAGE_SIZE << order;
+ struct iotlb_entry e;
+ int omap_pgsz;
+ u32 ret, flags;
+
+ /* we only support mapping a single iommu page for now */
+ omap_pgsz = bytes_to_iopgsz(bytes);
+ if (omap_pgsz < 0) {
+ dev_err(dev, "invalid size to map: %d\n", bytes);
+ return -EINVAL;
+ }
+
+ dev_dbg(dev, "mapping da 0x%lx to pa 0x%x size 0x%x\n", da, pa, bytes);
+
+ flags = omap_pgsz | prot;
+
+ iotlb_init_entry(&e, da, pa, flags);
+
+ ret = omap_iopgtable_store_entry(oiommu, &e);
+ if (ret)
+ dev_err(dev, "omap_iopgtable_store_entry failed: %d\n", ret);
+
+ return ret;
+}
+
+static int omap_iommu_unmap(struct iommu_domain *domain, unsigned long da,
+ int order)
+{
+ struct omap_iommu_domain *omap_domain = domain->priv;
+ struct omap_iommu *oiommu = omap_domain->iommu_dev;
+ struct device *dev = oiommu->dev;
+ size_t unmap_size;
+
+ dev_dbg(dev, "unmapping da 0x%lx order %d\n", da, order);
+
+ unmap_size = iopgtable_clear_entry(oiommu, da);
+
+ return unmap_size ? get_order(unmap_size) : -EINVAL;
+}
+
+static int
+omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
+{
+ struct omap_iommu_domain *omap_domain = domain->priv;
+ struct omap_iommu *oiommu;
+ int ret = 0;
+
+ spin_lock(&omap_domain->lock);
+
+ /* only a single device is supported per domain for now */
+ if (omap_domain->iommu_dev) {
+ dev_err(dev, "iommu domain is already attached\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* get a handle to and enable the omap iommu */
+ oiommu = omap_iommu_attach(dev, omap_domain->pgtable);
+ if (IS_ERR(oiommu)) {
+ ret = PTR_ERR(oiommu);
+ dev_err(dev, "can't get omap iommu: %d\n", ret);
+ goto out;
+ }
+
+ omap_domain->iommu_dev = oiommu;
+ oiommu->domain = domain;
+
+out:
+ spin_unlock(&omap_domain->lock);
+ return ret;
+}
+
+static void omap_iommu_detach_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ struct omap_iommu_domain *omap_domain = domain->priv;
+ struct omap_iommu *oiommu = to_iommu(dev);
+
+ spin_lock(&omap_domain->lock);
+
+ /* only a single device is supported per domain for now */
+ if (omap_domain->iommu_dev != oiommu) {
+ dev_err(dev, "invalid iommu device\n");
+ goto out;
+ }
+
+ iopgtable_clear_entry_all(oiommu);
+
+ omap_iommu_detach(oiommu);
+
+ omap_domain->iommu_dev = NULL;
+
+out:
+ spin_unlock(&omap_domain->lock);
+}
+
+static int omap_iommu_domain_init(struct iommu_domain *domain)
+{
+ struct omap_iommu_domain *omap_domain;
+
+ omap_domain = kzalloc(sizeof(*omap_domain), GFP_KERNEL);
+ if (!omap_domain) {
+ pr_err("kzalloc failed\n");
+ goto out;
+ }
+
+ omap_domain->pgtable = kzalloc(IOPGD_TABLE_SIZE, GFP_KERNEL);
+ if (!omap_domain->pgtable) {
+ pr_err("kzalloc failed\n");
+ goto fail_nomem;
+ }
+
+ /*
+ * should never fail, but please keep this around to ensure
+ * we keep the hardware happy
+ */
+ BUG_ON(!IS_ALIGNED((long)omap_domain->pgtable, IOPGD_TABLE_SIZE));
+
+ clean_dcache_area(omap_domain->pgtable, IOPGD_TABLE_SIZE);
+ spin_lock_init(&omap_domain->lock);
+
+ domain->priv = omap_domain;
+
+ return 0;
+
+fail_nomem:
+ kfree(omap_domain);
+out:
+ return -ENOMEM;
+}
+
+/* assume device was already detached */
+static void omap_iommu_domain_destroy(struct iommu_domain *domain)
+{
+ struct omap_iommu_domain *omap_domain = domain->priv;
+
+ domain->priv = NULL;
+
+ kfree(omap_domain->pgtable);
+ kfree(omap_domain);
+}
+
+static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
+ unsigned long da)
+{
+ struct omap_iommu_domain *omap_domain = domain->priv;
+ struct omap_iommu *oiommu = omap_domain->iommu_dev;
+ struct device *dev = oiommu->dev;
+ u32 *pgd, *pte;
+ phys_addr_t ret = 0;
+
+ iopgtable_lookup_entry(oiommu, da, &pgd, &pte);
+
+ if (pte) {
+ if (iopte_is_small(*pte))
+ ret = omap_iommu_translate(*pte, da, IOPTE_MASK);
+ else if (iopte_is_large(*pte))
+ ret = omap_iommu_translate(*pte, da, IOLARGE_MASK);
+ else
+ dev_err(dev, "bogus pte 0x%x", *pte);
+ } else {
+ if (iopgd_is_section(*pgd))
+ ret = omap_iommu_translate(*pgd, da, IOSECTION_MASK);
+ else if (iopgd_is_super(*pgd))
+ ret = omap_iommu_translate(*pgd, da, IOSUPER_MASK);
+ else
+ dev_err(dev, "bogus pgd 0x%x", *pgd);
+ }
+
+ return ret;
+}
+
+static int omap_iommu_domain_has_cap(struct iommu_domain *domain,
+ unsigned long cap)
+{
+ return 0;
+}
+
+static struct iommu_ops omap_iommu_ops = {
+ .domain_init = omap_iommu_domain_init,
+ .domain_destroy = omap_iommu_domain_destroy,
+ .attach_dev = omap_iommu_attach_dev,
+ .detach_dev = omap_iommu_detach_dev,
+ .map = omap_iommu_map,
+ .unmap = omap_iommu_unmap,
+ .iova_to_phys = omap_iommu_iova_to_phys,
+ .domain_has_cap = omap_iommu_domain_has_cap,
+};
+
static int __init omap_iommu_init(void)
{
struct kmem_cache *p;
@@ -1084,6 +1225,8 @@ static int __init omap_iommu_init(void)
return -ENOMEM;
iopte_cachep = p;
+ bus_set_iommu(&platform_bus_type, &omap_iommu_ops);
+
return platform_driver_register(&omap_iommu_driver);
}
module_init(omap_iommu_init);
diff --git a/arch/arm/plat-omap/iovmm.c b/drivers/iommu/omap-iovmm.c
index 79e7fedb8602..e8fdb8830f69 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/drivers/iommu/omap-iovmm.c
@@ -15,6 +15,7 @@
#include <linux/vmalloc.h>
#include <linux/device.h>
#include <linux/scatterlist.h>
+#include <linux/iommu.h>
#include <asm/cacheflush.h>
#include <asm/mach/map.h>
@@ -22,44 +23,19 @@
#include <plat/iommu.h>
#include <plat/iovmm.h>
-#include "iopgtable.h"
-
-/*
- * A device driver needs to create address mappings between:
- *
- * - iommu/device address
- * - physical address
- * - mpu virtual address
- *
- * There are 4 possible patterns for them:
- *
- * |iova/ mapping iommu_ page
- * | da pa va (d)-(p)-(v) function type
- * ---------------------------------------------------------------------------
- * 1 | c c c 1 - 1 - 1 _kmap() / _kunmap() s
- * 2 | c c,a c 1 - 1 - 1 _kmalloc()/ _kfree() s
- * 3 | c d c 1 - n - 1 _vmap() / _vunmap() s
- * 4 | c d,a c 1 - n - 1 _vmalloc()/ _vfree() n*
- *
- *
- * 'iova': device iommu virtual address
- * 'da': alias of 'iova'
- * 'pa': physical address
- * 'va': mpu virtual address
- *
- * 'c': contiguous memory area
- * 'd': discontiguous memory area
- * 'a': anonymous memory allocation
- * '()': optional feature
- *
- * 'n': a normal page(4KB) size is used.
- * 's': multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used.
- *
- * '*': not yet, but feasible.
- */
+#include <plat/iopgtable.h>
static struct kmem_cache *iovm_area_cachep;
+/* return the offset of the first scatterlist entry in a sg table */
+static unsigned int sgtable_offset(const struct sg_table *sgt)
+{
+ if (!sgt || !sgt->nents)
+ return 0;
+
+ return sgt->sgl->offset;
+}
+
/* return total bytes of sg buffers */
static size_t sgtable_len(const struct sg_table *sgt)
{
@@ -72,11 +48,17 @@ static size_t sgtable_len(const struct sg_table *sgt)
for_each_sg(sgt->sgl, sg, sgt->nents, i) {
size_t bytes;
- bytes = sg->length;
+ bytes = sg->length + sg->offset;
if (!iopgsz_ok(bytes)) {
- pr_err("%s: sg[%d] not iommu pagesize(%x)\n",
- __func__, i, bytes);
+ pr_err("%s: sg[%d] not iommu pagesize(%u %u)\n",
+ __func__, i, bytes, sg->offset);
+ return 0;
+ }
+
+ if (i && sg->offset) {
+ pr_err("%s: sg[%d] offset not allowed in internal "
+ "entries\n", __func__, i);
return 0;
}
@@ -197,8 +179,8 @@ static void *vmap_sg(const struct sg_table *sgt)
u32 pa;
int err;
- pa = sg_phys(sg);
- bytes = sg->length;
+ pa = sg_phys(sg) - sg->offset;
+ bytes = sg->length + sg->offset;
BUG_ON(bytes != PAGE_SIZE);
@@ -224,7 +206,8 @@ static inline void vunmap_sg(const void *va)
vunmap(va);
}
-static struct iovm_struct *__find_iovm_area(struct iommu *obj, const u32 da)
+static struct iovm_struct *__find_iovm_area(struct omap_iommu *obj,
+ const u32 da)
{
struct iovm_struct *tmp;
@@ -246,12 +229,12 @@ static struct iovm_struct *__find_iovm_area(struct iommu *obj, const u32 da)
}
/**
- * find_iovm_area - find iovma which includes @da
+ * omap_find_iovm_area - find iovma which includes @da
* @da: iommu device virtual address
*
* Find the existing iovma starting at @da
*/
-struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da)
+struct iovm_struct *omap_find_iovm_area(struct omap_iommu *obj, u32 da)
{
struct iovm_struct *area;
@@ -261,13 +244,13 @@ struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da)
return area;
}
-EXPORT_SYMBOL_GPL(find_iovm_area);
+EXPORT_SYMBOL_GPL(omap_find_iovm_area);
/*
* This finds the hole(area) which fits the requested address and len
* in iovmas mmap, and returns the new allocated iovma.
*/
-static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
+static struct iovm_struct *alloc_iovm_area(struct omap_iommu *obj, u32 da,
size_t bytes, u32 flags)
{
struct iovm_struct *new, *tmp;
@@ -342,7 +325,7 @@ found:
return new;
}
-static void free_iovm_area(struct iommu *obj, struct iovm_struct *area)
+static void free_iovm_area(struct omap_iommu *obj, struct iovm_struct *area)
{
size_t bytes;
@@ -358,14 +341,14 @@ static void free_iovm_area(struct iommu *obj, struct iovm_struct *area)
}
/**
- * da_to_va - convert (d) to (v)
+ * omap_da_to_va - convert (d) to (v)
* @obj: objective iommu
* @da: iommu device virtual address
* @va: mpu virtual address
*
* Returns mpu virtual addr which corresponds to a given device virtual addr
*/
-void *da_to_va(struct iommu *obj, u32 da)
+void *omap_da_to_va(struct omap_iommu *obj, u32 da)
{
void *va = NULL;
struct iovm_struct *area;
@@ -383,7 +366,7 @@ out:
return va;
}
-EXPORT_SYMBOL_GPL(da_to_va);
+EXPORT_SYMBOL_GPL(omap_da_to_va);
static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
{
@@ -397,7 +380,7 @@ static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
const size_t bytes = PAGE_SIZE;
/*
- * iommu 'superpage' isn't supported with 'iommu_vmalloc()'
+ * iommu 'superpage' isn't supported with 'omap_iommu_vmalloc()'
*/
pg = vmalloc_to_page(va);
BUG_ON(!pg);
@@ -418,74 +401,39 @@ static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
BUG_ON(!sgt);
}
-static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, u32 da,
- size_t len)
-{
- unsigned int i;
- struct scatterlist *sg;
-
- for_each_sg(sgt->sgl, sg, sgt->nents, i) {
- unsigned bytes;
-
- bytes = max_alignment(da | pa);
- bytes = min_t(unsigned, bytes, iopgsz_max(len));
-
- BUG_ON(!iopgsz_ok(bytes));
-
- sg_set_buf(sg, phys_to_virt(pa), bytes);
- /*
- * 'pa' is cotinuous(linear).
- */
- pa += bytes;
- da += bytes;
- len -= bytes;
- }
- BUG_ON(len);
-}
-
-static inline void sgtable_drain_kmalloc(struct sg_table *sgt)
-{
- /*
- * Actually this is not necessary at all, just exists for
- * consistency of the code readability
- */
- BUG_ON(!sgt);
-}
-
/* create 'da' <-> 'pa' mapping from 'sgt' */
-static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
- const struct sg_table *sgt, u32 flags)
+static int map_iovm_area(struct iommu_domain *domain, struct iovm_struct *new,
+ const struct sg_table *sgt, u32 flags)
{
int err;
unsigned int i, j;
struct scatterlist *sg;
u32 da = new->da_start;
+ int order;
- if (!obj || !sgt)
+ if (!domain || !sgt)
return -EINVAL;
BUG_ON(!sgtable_ok(sgt));
for_each_sg(sgt->sgl, sg, sgt->nents, i) {
u32 pa;
- int pgsz;
size_t bytes;
- struct iotlb_entry e;
- pa = sg_phys(sg);
- bytes = sg->length;
+ pa = sg_phys(sg) - sg->offset;
+ bytes = sg->length + sg->offset;
flags &= ~IOVMF_PGSZ_MASK;
- pgsz = bytes_to_iopgsz(bytes);
- if (pgsz < 0)
+
+ if (bytes_to_iopgsz(bytes) < 0)
goto err_out;
- flags |= pgsz;
+
+ order = get_order(bytes);
pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
i, da, pa, bytes);
- iotlb_init_entry(&e, da, pa, flags);
- err = iopgtable_store_entry(obj, &e);
+ err = iommu_map(domain, da, pa, order, flags);
if (err)
goto err_out;
@@ -499,9 +447,11 @@ err_out:
for_each_sg(sgt->sgl, sg, i, j) {
size_t bytes;
- bytes = iopgtable_clear_entry(obj, da);
+ bytes = sg->length + sg->offset;
+ order = get_order(bytes);
- BUG_ON(!iopgsz_ok(bytes));
+ /* ignore failures.. we're already handling one */
+ iommu_unmap(domain, da, order);
da += bytes;
}
@@ -509,22 +459,31 @@ err_out:
}
/* release 'da' <-> 'pa' mapping */
-static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area)
+static void unmap_iovm_area(struct iommu_domain *domain, struct omap_iommu *obj,
+ struct iovm_struct *area)
{
u32 start;
size_t total = area->da_end - area->da_start;
+ const struct sg_table *sgt = area->sgt;
+ struct scatterlist *sg;
+ int i, err;
+ BUG_ON(!sgtable_ok(sgt));
BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
start = area->da_start;
- while (total > 0) {
+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
size_t bytes;
+ int order;
+
+ bytes = sg->length + sg->offset;
+ order = get_order(bytes);
+
+ err = iommu_unmap(domain, start, order);
+ if (err < 0)
+ break;
- bytes = iopgtable_clear_entry(obj, start);
- if (bytes == 0)
- bytes = PAGE_SIZE;
- else
- dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
+ dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
__func__, start, bytes, area->flags);
BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
@@ -536,7 +495,8 @@ static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area)
}
/* template function for all unmapping */
-static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
+static struct sg_table *unmap_vm_area(struct iommu_domain *domain,
+ struct omap_iommu *obj, const u32 da,
void (*fn)(const void *), u32 flags)
{
struct sg_table *sgt = NULL;
@@ -562,7 +522,7 @@ static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
}
sgt = (struct sg_table *)area->sgt;
- unmap_iovm_area(obj, area);
+ unmap_iovm_area(domain, obj, area);
fn(area->va);
@@ -577,8 +537,9 @@ out:
return sgt;
}
-static u32 map_iommu_region(struct iommu *obj, u32 da,
- const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
+static u32 map_iommu_region(struct iommu_domain *domain, struct omap_iommu *obj,
+ u32 da, const struct sg_table *sgt, void *va,
+ size_t bytes, u32 flags)
{
int err = -ENOMEM;
struct iovm_struct *new;
@@ -593,7 +554,7 @@ static u32 map_iommu_region(struct iommu *obj, u32 da,
new->va = va;
new->sgt = sgt;
- if (map_iovm_area(obj, new, sgt, new->flags))
+ if (map_iovm_area(domain, new, sgt, new->flags))
goto err_map;
mutex_unlock(&obj->mmap_lock);
@@ -610,14 +571,16 @@ err_alloc_iovma:
return err;
}
-static inline u32 __iommu_vmap(struct iommu *obj, u32 da,
- const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
+static inline u32
+__iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj,
+ u32 da, const struct sg_table *sgt,
+ void *va, size_t bytes, u32 flags)
{
- return map_iommu_region(obj, da, sgt, va, bytes, flags);
+ return map_iommu_region(domain, obj, da, sgt, va, bytes, flags);
}
/**
- * iommu_vmap - (d)-(p)-(v) address mapper
+ * omap_iommu_vmap - (d)-(p)-(v) address mapper
* @obj: objective iommu
* @sgt: address of scatter gather table
* @flags: iovma and page property
@@ -625,8 +588,8 @@ static inline u32 __iommu_vmap(struct iommu *obj, u32 da,
* Creates 1-n-1 mapping with given @sgt and returns @da.
* All @sgt element must be io page size aligned.
*/
-u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
- u32 flags)
+u32 omap_iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj, u32 da,
+ const struct sg_table *sgt, u32 flags)
{
size_t bytes;
void *va = NULL;
@@ -648,38 +611,41 @@ u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
flags |= IOVMF_DISCONT;
flags |= IOVMF_MMIO;
- da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
+ da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
if (IS_ERR_VALUE(da))
vunmap_sg(va);
- return da;
+ return da + sgtable_offset(sgt);
}
-EXPORT_SYMBOL_GPL(iommu_vmap);
+EXPORT_SYMBOL_GPL(omap_iommu_vmap);
/**
- * iommu_vunmap - release virtual mapping obtained by 'iommu_vmap()'
+ * omap_iommu_vunmap - release virtual mapping obtained by 'omap_iommu_vmap()'
* @obj: objective iommu
* @da: iommu device virtual address
*
* Free the iommu virtually contiguous memory area starting at
- * @da, which was returned by 'iommu_vmap()'.
+ * @da, which was returned by 'omap_iommu_vmap()'.
*/
-struct sg_table *iommu_vunmap(struct iommu *obj, u32 da)
+struct sg_table *
+omap_iommu_vunmap(struct iommu_domain *domain, struct omap_iommu *obj, u32 da)
{
struct sg_table *sgt;
/*
- * 'sgt' is allocated before 'iommu_vmalloc()' is called.
+ * 'sgt' is allocated before 'omap_iommu_vmalloc()' is called.
* Just returns 'sgt' to the caller to free
*/
- sgt = unmap_vm_area(obj, da, vunmap_sg, IOVMF_DISCONT | IOVMF_MMIO);
+ da &= PAGE_MASK;
+ sgt = unmap_vm_area(domain, obj, da, vunmap_sg,
+ IOVMF_DISCONT | IOVMF_MMIO);
if (!sgt)
dev_dbg(obj->dev, "%s: No sgt\n", __func__);
return sgt;
}
-EXPORT_SYMBOL_GPL(iommu_vunmap);
+EXPORT_SYMBOL_GPL(omap_iommu_vunmap);
/**
- * iommu_vmalloc - (d)-(p)-(v) address allocator and mapper
+ * omap_iommu_vmalloc - (d)-(p)-(v) address allocator and mapper
* @obj: objective iommu
* @da: contiguous iommu virtual memory
* @bytes: allocation size
@@ -688,7 +654,9 @@ EXPORT_SYMBOL_GPL(iommu_vunmap);
* Allocate @bytes linearly and creates 1-n-1 mapping and returns
* @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
*/
-u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
+u32
+omap_iommu_vmalloc(struct iommu_domain *domain, struct omap_iommu *obj, u32 da,
+ size_t bytes, u32 flags)
{
void *va;
struct sg_table *sgt;
@@ -712,7 +680,7 @@ u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
}
sgtable_fill_vmalloc(sgt, va);
- da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
+ da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
if (IS_ERR_VALUE(da))
goto err_iommu_vmap;
@@ -725,158 +693,28 @@ err_sgt_alloc:
vfree(va);
return da;
}
-EXPORT_SYMBOL_GPL(iommu_vmalloc);
+EXPORT_SYMBOL_GPL(omap_iommu_vmalloc);
/**
- * iommu_vfree - release memory allocated by 'iommu_vmalloc()'
+ * omap_iommu_vfree - release memory allocated by 'omap_iommu_vmalloc()'
* @obj: objective iommu
* @da: iommu device virtual address
*
* Frees the iommu virtually continuous memory area starting at
- * @da, as obtained from 'iommu_vmalloc()'.
+ * @da, as obtained from 'omap_iommu_vmalloc()'.
*/
-void iommu_vfree(struct iommu *obj, const u32 da)
+void omap_iommu_vfree(struct iommu_domain *domain, struct omap_iommu *obj,
+ const u32 da)
{
struct sg_table *sgt;
- sgt = unmap_vm_area(obj, da, vfree, IOVMF_DISCONT | IOVMF_ALLOC);
+ sgt = unmap_vm_area(domain, obj, da, vfree,
+ IOVMF_DISCONT | IOVMF_ALLOC);
if (!sgt)
dev_dbg(obj->dev, "%s: No sgt\n", __func__);
sgtable_free(sgt);
}
-EXPORT_SYMBOL_GPL(iommu_vfree);
-
-static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va,
- size_t bytes, u32 flags)
-{
- struct sg_table *sgt;
-
- sgt = sgtable_alloc(bytes, flags, da, pa);
- if (IS_ERR(sgt))
- return PTR_ERR(sgt);
-
- sgtable_fill_kmalloc(sgt, pa, da, bytes);
-
- da = map_iommu_region(obj, da, sgt, va, bytes, flags);
- if (IS_ERR_VALUE(da)) {
- sgtable_drain_kmalloc(sgt);
- sgtable_free(sgt);
- }
-
- return da;
-}
-
-/**
- * iommu_kmap - (d)-(p)-(v) address mapper
- * @obj: objective iommu
- * @da: contiguous iommu virtual memory
- * @pa: contiguous physical memory
- * @flags: iovma and page property
- *
- * Creates 1-1-1 mapping and returns @da again, which can be
- * adjusted if 'IOVMF_DA_FIXED' is not set.
- */
-u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
- u32 flags)
-{
- void *va;
-
- if (!obj || !obj->dev || !bytes)
- return -EINVAL;
-
- bytes = PAGE_ALIGN(bytes);
-
- va = ioremap(pa, bytes);
- if (!va)
- return -ENOMEM;
-
- flags |= IOVMF_LINEAR;
- flags |= IOVMF_MMIO;
-
- da = __iommu_kmap(obj, da, pa, va, bytes, flags);
- if (IS_ERR_VALUE(da))
- iounmap(va);
-
- return da;
-}
-EXPORT_SYMBOL_GPL(iommu_kmap);
-
-/**
- * iommu_kunmap - release virtual mapping obtained by 'iommu_kmap()'
- * @obj: objective iommu
- * @da: iommu device virtual address
- *
- * Frees the iommu virtually contiguous memory area starting at
- * @da, which was passed to and was returned by'iommu_kmap()'.
- */
-void iommu_kunmap(struct iommu *obj, u32 da)
-{
- struct sg_table *sgt;
- typedef void (*func_t)(const void *);
-
- sgt = unmap_vm_area(obj, da, (func_t)iounmap,
- IOVMF_LINEAR | IOVMF_MMIO);
- if (!sgt)
- dev_dbg(obj->dev, "%s: No sgt\n", __func__);
- sgtable_free(sgt);
-}
-EXPORT_SYMBOL_GPL(iommu_kunmap);
-
-/**
- * iommu_kmalloc - (d)-(p)-(v) address allocator and mapper
- * @obj: objective iommu
- * @da: contiguous iommu virtual memory
- * @bytes: bytes for allocation
- * @flags: iovma and page property
- *
- * Allocate @bytes linearly and creates 1-1-1 mapping and returns
- * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
- */
-u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
-{
- void *va;
- u32 pa;
-
- if (!obj || !obj->dev || !bytes)
- return -EINVAL;
-
- bytes = PAGE_ALIGN(bytes);
-
- va = kmalloc(bytes, GFP_KERNEL | GFP_DMA);
- if (!va)
- return -ENOMEM;
- pa = virt_to_phys(va);
-
- flags |= IOVMF_LINEAR;
- flags |= IOVMF_ALLOC;
-
- da = __iommu_kmap(obj, da, pa, va, bytes, flags);
- if (IS_ERR_VALUE(da))
- kfree(va);
-
- return da;
-}
-EXPORT_SYMBOL_GPL(iommu_kmalloc);
-
-/**
- * iommu_kfree - release virtual mapping obtained by 'iommu_kmalloc()'
- * @obj: objective iommu
- * @da: iommu device virtual address
- *
- * Frees the iommu virtually contiguous memory area starting at
- * @da, which was passed to and was returned by'iommu_kmalloc()'.
- */
-void iommu_kfree(struct iommu *obj, u32 da)
-{
- struct sg_table *sgt;
-
- sgt = unmap_vm_area(obj, da, kfree, IOVMF_LINEAR | IOVMF_ALLOC);
- if (!sgt)
- dev_dbg(obj->dev, "%s: No sgt\n", __func__);
- sgtable_free(sgt);
-}
-EXPORT_SYMBOL_GPL(iommu_kfree);
-
+EXPORT_SYMBOL_GPL(omap_iommu_vfree);
static int __init iovmm_init(void)
{
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index 4fb601670de3..a233ed53913a 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -5,7 +5,7 @@
menuconfig ISDN
bool "ISDN support"
depends on NET
- depends on !S390
+ depends on !S390 && !UML
---help---
ISDN ("Integrated Services Digital Network", called RNIS in France)
is a fully digital telephone service that can be used for voice and
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index 37e685eafd24..c4897e1075d8 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -65,7 +65,7 @@ hisax_findcard(int driverid)
return (struct IsdnCardState *) 0;
}
-static __attribute__((format(printf, 3, 4))) void
+static __printf(3, 4) void
link_debug(struct Channel *chanp, int direction, char *fmt, ...)
{
va_list args;
@@ -1068,7 +1068,7 @@ init_d_st(struct Channel *chanp)
return 0;
}
-static __attribute__((format(printf, 2, 3))) void
+static __printf(2, 3) void
callc_debug(struct FsmInst *fi, char *fmt, ...)
{
va_list args;
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 0a5c42a3f125..aff45a11a92d 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1287,9 +1287,9 @@ int jiftime(char *s, long mark);
int HiSax_command(isdn_ctrl * ic);
int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
-__attribute__((format(printf, 3, 4)))
+__printf(3, 4)
void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
-__attribute__((format(printf, 3, 0)))
+__printf(3, 0)
void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
void HiSax_reportcard(int cardnr, int sel);
int QuickHex(char *txt, u_char * p, int cnt);
diff --git a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h
index 425d86116f2b..66ddcab19bba 100644
--- a/drivers/isdn/hisax/isdnl1.h
+++ b/drivers/isdn/hisax/isdnl1.h
@@ -21,7 +21,7 @@
#define B_XMTBUFREADY 1
#define B_ACKPENDING 2
-__attribute__((format(printf, 2, 3)))
+__printf(2, 3)
void debugl1(struct IsdnCardState *cs, char *fmt, ...);
void DChannel_proc_xmt(struct IsdnCardState *cs);
void DChannel_proc_rcv(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index ad291f21b201..1c24e4457b6f 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -66,7 +66,7 @@ static char *strL3Event[] =
"EV_TIMEOUT",
};
-static __attribute__((format(printf, 2, 3))) void
+static __printf(2, 3) void
l3m_debug(struct FsmInst *fi, char *fmt, ...)
{
va_list args;
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 44082637a09f..db247b79e561 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -167,7 +167,7 @@ static struct FsmNode L1FnList[] __initdata =
{ST_L1_F8, EV_IND_RSY, l1_ignore},
};
-static __attribute__((format(printf, 2, 3)))
+static __printf(2, 3)
void l1m_debug(struct FsmInst *fi, char *fmt, ...)
{
va_list args;
@@ -270,7 +270,7 @@ static char *strDoutEvent[] =
"EV_DOUT_UNDERRUN",
};
-static __attribute__((format(printf, 2, 3)))
+static __printf(2, 3)
void dout_debug(struct FsmInst *fi, char *fmt, ...)
{
va_list args;
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 6ed82add6ffa..6ddb795e31c5 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -2308,11 +2308,11 @@ static int __init isdn_init(void)
int i;
char tmprev[50];
- if (!(dev = vmalloc(sizeof(isdn_dev)))) {
+ dev = vzalloc(sizeof(isdn_dev));
+ if (!dev) {
printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
return -EIO;
}
- memset((char *) dev, 0, sizeof(isdn_dev));
init_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
spin_lock_init(&dev->lock);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index d8504279e502..e5546cb3ac69 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1693,7 +1693,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
* line status register.
*/
if (info->flags & ISDN_ASYNC_INITIALIZED) {
- tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
+ tty_wait_until_sent_from_close(tty, 3000); /* 30 seconds timeout */
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
index 2877291a9ed8..0c41553ce684 100644
--- a/drivers/isdn/mISDN/dsp_core.c
+++ b/drivers/isdn/mISDN/dsp_core.c
@@ -1052,12 +1052,11 @@ dspcreate(struct channel_req *crq)
if (crq->protocol != ISDN_P_B_L2DSP
&& crq->protocol != ISDN_P_B_L2DSPHDLC)
return -EPROTONOSUPPORT;
- ndsp = vmalloc(sizeof(struct dsp));
+ ndsp = vzalloc(sizeof(struct dsp));
if (!ndsp) {
printk(KERN_ERR "%s: vmalloc struct dsp failed\n", __func__);
return -ENOMEM;
}
- memset(ndsp, 0, sizeof(struct dsp));
if (dsp_debug & DEBUG_DSP_CTRL)
printk(KERN_DEBUG "%s: creating new dsp instance\n", __func__);
diff --git a/drivers/isdn/mISDN/l1oip_codec.c b/drivers/isdn/mISDN/l1oip_codec.c
index bbfd1b863ed3..5a89972624d8 100644
--- a/drivers/isdn/mISDN/l1oip_codec.c
+++ b/drivers/isdn/mISDN/l1oip_codec.c
@@ -330,14 +330,12 @@ l1oip_4bit_alloc(int ulaw)
return 0;
/* alloc conversion tables */
- table_com = vmalloc(65536);
- table_dec = vmalloc(512);
+ table_com = vzalloc(65536);
+ table_dec = vzalloc(512);
if (!table_com || !table_dec) {
l1oip_4bit_free();
return -ENOMEM;
}
- memset(table_com, 0, 65536);
- memset(table_dec, 0, 512);
/* generate compression table */
i1 = 0;
while (i1 < 256) {
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index b591e726a6fa..ff203a421863 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -113,14 +113,6 @@ config LEDS_WRAP
help
This option enables support for the PCEngines WRAP programmable LEDs.
-config LEDS_ALIX2
- tristate "LED Support for ALIX.2 and ALIX.3 series"
- depends on LEDS_CLASS
- depends on X86 && !GPIO_CS5535 && !CS5535_GPIO
- help
- This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs.
- You have to set leds-alix2.force=1 for boards with Award BIOS.
-
config LEDS_COBALT_QUBE
tristate "LED Support for the Cobalt Qube series front LED"
depends on LEDS_CLASS
@@ -383,6 +375,18 @@ config LEDS_ASIC3
cannot be used. This driver supports hardware blinking with an on+off
period from 62ms to 125s. Say Y to enable LEDs on the HP iPAQ hx4700.
+config LEDS_RENESAS_TPU
+ bool "LED support for Renesas TPU"
+ depends on LEDS_CLASS && HAVE_CLK && GENERIC_GPIO
+ help
+ This option enables build of the LED TPU platform driver,
+ suitable to drive any TPU channel on newer Renesas SoCs.
+ The driver controls the GPIO pin connected to the LED via
+ the GPIO framework and expects the LED to be connected to
+ a pin that can be driven in both GPIO mode and using TPU
+ pin function. The latter to support brightness control.
+ Brightness control is supported but hardware blinking is not.
+
config LEDS_TRIGGERS
bool "LED Trigger support"
depends on LEDS_CLASS
@@ -400,7 +404,7 @@ config LEDS_TRIGGER_TIMER
This allows LEDs to be controlled by a programmable timer
via sysfs. Some LED hardware can be programmed to start
blinking the LED without any further software interaction.
- For more details read Documentation/leds-class.txt.
+ For more details read Documentation/leds/leds-class.txt.
If unsure, say Y.
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index bbfd2e367dc0..e4f6bf568880 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
obj-$(CONFIG_LEDS_NET5501) += leds-net5501.o
obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
-obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o
obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o
@@ -43,6 +42,7 @@ obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
obj-$(CONFIG_LEDS_NS2) += leds-ns2.o
obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o
+obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o
# LED SPI Drivers
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index dc3d3d83191a..661b692573e7 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -267,9 +267,14 @@ void led_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
{
+ del_timer_sync(&led_cdev->blink_timer);
+
if (led_cdev->blink_set &&
- !led_cdev->blink_set(led_cdev, delay_on, delay_off))
+ !led_cdev->blink_set(led_cdev, delay_on, delay_off)) {
+ led_cdev->blink_delay_on = *delay_on;
+ led_cdev->blink_delay_off = *delay_off;
return;
+ }
/* blink with 1 Hz as default if nothing specified */
if (!*delay_on && !*delay_off)
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 4bebae733349..6f1ff93d7cec 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -261,9 +261,12 @@ void led_trigger_register_simple(const char *name, struct led_trigger **tp)
if (trigger) {
trigger->name = name;
err = led_trigger_register(trigger);
- if (err < 0)
+ if (err < 0) {
+ kfree(trigger);
+ trigger = NULL;
printk(KERN_WARNING "LED trigger %s failed to register"
" (%d)\n", name, err);
+ }
} else
printk(KERN_WARNING "LED trigger %s failed to register"
" (no memory)\n", name);
diff --git a/drivers/leds/leds-alix2.c b/drivers/leds/leds-alix2.c
deleted file mode 100644
index f59ffadf5125..000000000000
--- a/drivers/leds/leds-alix2.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * LEDs driver for PCEngines ALIX.2 and ALIX.3
- *
- * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/leds.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-
-static int force = 0;
-module_param(force, bool, 0444);
-MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs");
-
-#define MSR_LBAR_GPIO 0x5140000C
-#define CS5535_GPIO_SIZE 256
-
-static u32 gpio_base;
-
-static struct pci_device_id divil_pci[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
- { } /* NULL entry */
-};
-MODULE_DEVICE_TABLE(pci, divil_pci);
-
-struct alix_led {
- struct led_classdev cdev;
- unsigned short port;
- unsigned int on_value;
- unsigned int off_value;
-};
-
-static void alix_led_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct alix_led *led_dev =
- container_of(led_cdev, struct alix_led, cdev);
-
- if (brightness)
- outl(led_dev->on_value, gpio_base + led_dev->port);
- else
- outl(led_dev->off_value, gpio_base + led_dev->port);
-}
-
-static struct alix_led alix_leds[] = {
- {
- .cdev = {
- .name = "alix:1",
- .brightness_set = alix_led_set,
- },
- .port = 0x00,
- .on_value = 1 << 22,
- .off_value = 1 << 6,
- },
- {
- .cdev = {
- .name = "alix:2",
- .brightness_set = alix_led_set,
- },
- .port = 0x80,
- .on_value = 1 << 25,
- .off_value = 1 << 9,
- },
- {
- .cdev = {
- .name = "alix:3",
- .brightness_set = alix_led_set,
- },
- .port = 0x80,
- .on_value = 1 << 27,
- .off_value = 1 << 11,
- },
-};
-
-static int __init alix_led_probe(struct platform_device *pdev)
-{
- int i;
- int ret;
-
- for (i = 0; i < ARRAY_SIZE(alix_leds); i++) {
- alix_leds[i].cdev.flags |= LED_CORE_SUSPENDRESUME;
- ret = led_classdev_register(&pdev->dev, &alix_leds[i].cdev);
- if (ret < 0)
- goto fail;
- }
- return 0;
-
-fail:
- while (--i >= 0)
- led_classdev_unregister(&alix_leds[i].cdev);
- return ret;
-}
-
-static int alix_led_remove(struct platform_device *pdev)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(alix_leds); i++)
- led_classdev_unregister(&alix_leds[i].cdev);
- return 0;
-}
-
-static struct platform_driver alix_led_driver = {
- .remove = alix_led_remove,
- .driver = {
- .name = KBUILD_MODNAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int __init alix_present(unsigned long bios_phys,
- const char *alix_sig,
- size_t alix_sig_len)
-{
- const size_t bios_len = 0x00010000;
- const char *bios_virt;
- const char *scan_end;
- const char *p;
- char name[64];
-
- if (force) {
- printk(KERN_NOTICE "%s: forced to skip BIOS test, "
- "assume system has ALIX.2 style LEDs\n",
- KBUILD_MODNAME);
- return 1;
- }
-
- bios_virt = phys_to_virt(bios_phys);
- scan_end = bios_virt + bios_len - (alix_sig_len + 2);
- for (p = bios_virt; p < scan_end; p++) {
- const char *tail;
- char *a;
-
- if (memcmp(p, alix_sig, alix_sig_len) != 0)
- continue;
-
- memcpy(name, p, sizeof(name));
-
- /* remove the first \0 character from string */
- a = strchr(name, '\0');
- if (a)
- *a = ' ';
-
- /* cut the string at a newline */
- a = strchr(name, '\r');
- if (a)
- *a = '\0';
-
- tail = p + alix_sig_len;
- if ((tail[0] == '2' || tail[0] == '3')) {
- printk(KERN_INFO
- "%s: system is recognized as \"%s\"\n",
- KBUILD_MODNAME, name);
- return 1;
- }
- }
-
- return 0;
-}
-
-static struct platform_device *pdev;
-
-static int __init alix_pci_led_init(void)
-{
- u32 low, hi;
-
- if (pci_dev_present(divil_pci) == 0) {
- printk(KERN_WARNING KBUILD_MODNAME": DIVIL not found\n");
- return -ENODEV;
- }
-
- /* Grab the GPIO I/O range */
- rdmsr(MSR_LBAR_GPIO, low, hi);
-
- /* Check the mask and whether GPIO is enabled (sanity check) */
- if (hi != 0x0000f001) {
- printk(KERN_WARNING KBUILD_MODNAME": GPIO not enabled\n");
- return -ENODEV;
- }
-
- /* Mask off the IO base address */
- gpio_base = low & 0x0000ff00;
-
- if (!request_region(gpio_base, CS5535_GPIO_SIZE, KBUILD_MODNAME)) {
- printk(KERN_ERR KBUILD_MODNAME": can't allocate I/O for GPIO\n");
- return -ENODEV;
- }
-
- /* Set GPIO function to output */
- outl(1 << 6, gpio_base + 0x04);
- outl(1 << 9, gpio_base + 0x84);
- outl(1 << 11, gpio_base + 0x84);
-
- return 0;
-}
-
-static int __init alix_led_init(void)
-{
- int ret = -ENODEV;
- const char tinybios_sig[] = "PC Engines ALIX.";
- const char coreboot_sig[] = "PC Engines\0ALIX.";
-
- if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
- alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
- ret = alix_pci_led_init();
-
- if (ret < 0)
- return ret;
-
- pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
- if (!IS_ERR(pdev)) {
- ret = platform_driver_probe(&alix_led_driver, alix_led_probe);
- if (ret)
- platform_device_unregister(pdev);
- } else
- ret = PTR_ERR(pdev);
-
- return ret;
-}
-
-static void __exit alix_led_exit(void)
-{
- platform_device_unregister(pdev);
- platform_driver_unregister(&alix_led_driver);
- release_region(gpio_base, CS5535_GPIO_SIZE);
-}
-
-module_init(alix_led_init);
-module_exit(alix_led_exit);
-
-MODULE_AUTHOR("Constantin Baranov <const@mimas.ru>");
-MODULE_DESCRIPTION("PCEngines ALIX.2 and ALIX.3 LED driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 3d8bc327a68d..504cc26c7e4b 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -121,7 +121,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template,
}
led_dat->cdev.brightness_set = gpio_led_set;
if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
- state = !!gpio_get_value(led_dat->gpio) ^ led_dat->active_low;
+ state = !!gpio_get_value_cansleep(led_dat->gpio) ^ led_dat->active_low;
else
state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index 3dd7090a9a9b..4dc510fdfa06 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -421,7 +421,6 @@ err_class_register:
err_reg_init:
regulator_put(drvdata->regulator);
err_regulator_get:
- i2c_set_clientdata(client, NULL);
kfree(drvdata);
err_out:
return err;
@@ -449,7 +448,7 @@ MODULE_DEVICE_TABLE(i2c, lm3530_id);
static struct i2c_driver lm3530_i2c_driver = {
.probe = lm3530_probe,
- .remove = lm3530_remove,
+ .remove = __devexit_p(lm3530_remove),
.id_table = lm3530_id,
.driver = {
.name = LM3530_NAME,
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 9fc122c81f06..cb641f1b3342 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -97,6 +97,9 @@
/* Status */
#define LP5521_EXT_CLK_USED 0x08
+/* default R channel current register value */
+#define LP5521_REG_R_CURR_DEFAULT 0xAF
+
struct lp5521_engine {
int id;
u8 mode;
@@ -175,14 +178,14 @@ static int lp5521_set_engine_mode(struct lp5521_engine *engine, u8 mode)
mode = LP5521_CMD_DIRECT;
ret = lp5521_read(client, LP5521_REG_OP_MODE, &engine_state);
+ if (ret < 0)
+ return ret;
/* set mode only for this engine */
engine_state &= ~(engine->engine_mask);
mode &= engine->engine_mask;
engine_state |= mode;
- ret |= lp5521_write(client, LP5521_REG_OP_MODE, engine_state);
-
- return ret;
+ return lp5521_write(client, LP5521_REG_OP_MODE, engine_state);
}
static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
@@ -643,6 +646,7 @@ static int __devinit lp5521_probe(struct i2c_client *client,
struct lp5521_chip *chip;
struct lp5521_platform_data *pdata;
int ret, i, led;
+ u8 buf;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip)
@@ -681,6 +685,20 @@ static int __devinit lp5521_probe(struct i2c_client *client,
* Exact value is not available. 10 - 20ms
* appears to be enough for reset.
*/
+
+ /*
+ * Make sure that the chip is reset by reading back the r channel
+ * current reg. This is dummy read is required on some platforms -
+ * otherwise further access to the R G B channels in the
+ * LP5521_REG_ENABLE register will not have any effect - strange!
+ */
+ lp5521_read(client, LP5521_REG_R_CURRENT, &buf);
+ if (buf != LP5521_REG_R_CURR_DEFAULT) {
+ dev_err(&client->dev, "error in reseting chip\n");
+ goto fail2;
+ }
+ usleep_range(10000, 20000);
+
ret = lp5521_detect(client);
if (ret) {
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
new file mode 100644
index 000000000000..3ee540eb127e
--- /dev/null
+++ b/drivers/leds/leds-renesas-tpu.c
@@ -0,0 +1,357 @@
+/*
+ * LED control using Renesas TPU
+ *
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 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/spinlock.h>
+#include <linux/printk.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/leds.h>
+#include <linux/platform_data/leds-renesas-tpu.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+
+enum r_tpu_pin { R_TPU_PIN_UNUSED, R_TPU_PIN_GPIO, R_TPU_PIN_GPIO_FN };
+enum r_tpu_timer { R_TPU_TIMER_UNUSED, R_TPU_TIMER_ON };
+
+struct r_tpu_priv {
+ struct led_classdev ldev;
+ void __iomem *mapbase;
+ struct clk *clk;
+ struct platform_device *pdev;
+ enum r_tpu_pin pin_state;
+ enum r_tpu_timer timer_state;
+ unsigned long min_rate;
+ unsigned int refresh_rate;
+ struct work_struct work;
+ enum led_brightness new_brightness;
+};
+
+static DEFINE_SPINLOCK(r_tpu_lock);
+
+#define TSTR -1 /* Timer start register (shared register) */
+#define TCR 0 /* Timer control register (+0x00) */
+#define TMDR 1 /* Timer mode register (+0x04) */
+#define TIOR 2 /* Timer I/O control register (+0x08) */
+#define TIER 3 /* Timer interrupt enable register (+0x0c) */
+#define TSR 4 /* Timer status register (+0x10) */
+#define TCNT 5 /* Timer counter (+0x14) */
+#define TGRA 6 /* Timer general register A (+0x18) */
+#define TGRB 7 /* Timer general register B (+0x1c) */
+#define TGRC 8 /* Timer general register C (+0x20) */
+#define TGRD 9 /* Timer general register D (+0x24) */
+
+static inline unsigned short r_tpu_read(struct r_tpu_priv *p, int reg_nr)
+{
+ struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+ void __iomem *base = p->mapbase;
+ unsigned long offs = reg_nr << 2;
+
+ if (reg_nr == TSTR)
+ return ioread16(base - cfg->channel_offset);
+
+ return ioread16(base + offs);
+}
+
+static inline void r_tpu_write(struct r_tpu_priv *p, int reg_nr,
+ unsigned short value)
+{
+ struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+ void __iomem *base = p->mapbase;
+ unsigned long offs = reg_nr << 2;
+
+ if (reg_nr == TSTR) {
+ iowrite16(value, base - cfg->channel_offset);
+ return;
+ }
+
+ iowrite16(value, base + offs);
+}
+
+static void r_tpu_start_stop_ch(struct r_tpu_priv *p, int start)
+{
+ struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+ unsigned long flags, value;
+
+ /* start stop register shared by multiple timer channels */
+ spin_lock_irqsave(&r_tpu_lock, flags);
+ value = r_tpu_read(p, TSTR);
+
+ if (start)
+ value |= 1 << cfg->timer_bit;
+ else
+ value &= ~(1 << cfg->timer_bit);
+
+ r_tpu_write(p, TSTR, value);
+ spin_unlock_irqrestore(&r_tpu_lock, flags);
+}
+
+static int r_tpu_enable(struct r_tpu_priv *p, enum led_brightness brightness)
+{
+ struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+ int prescaler[] = { 1, 4, 16, 64 };
+ int k, ret;
+ unsigned long rate, tmp;
+
+ if (p->timer_state == R_TPU_TIMER_ON)
+ return 0;
+
+ /* wake up device and enable clock */
+ pm_runtime_get_sync(&p->pdev->dev);
+ ret = clk_enable(p->clk);
+ if (ret) {
+ dev_err(&p->pdev->dev, "cannot enable clock\n");
+ return ret;
+ }
+
+ /* make sure channel is disabled */
+ r_tpu_start_stop_ch(p, 0);
+
+ /* get clock rate after enabling it */
+ rate = clk_get_rate(p->clk);
+
+ /* pick the lowest acceptable rate */
+ for (k = 0; k < ARRAY_SIZE(prescaler); k++)
+ if ((rate / prescaler[k]) < p->min_rate)
+ break;
+
+ if (!k) {
+ dev_err(&p->pdev->dev, "clock rate mismatch\n");
+ goto err0;
+ }
+ dev_dbg(&p->pdev->dev, "rate = %lu, prescaler %u\n",
+ rate, prescaler[k - 1]);
+
+ /* clear TCNT on TGRB match, count on rising edge, set prescaler */
+ r_tpu_write(p, TCR, 0x0040 | (k - 1));
+
+ /* output 0 until TGRA, output 1 until TGRB */
+ r_tpu_write(p, TIOR, 0x0002);
+
+ rate /= prescaler[k - 1] * p->refresh_rate;
+ r_tpu_write(p, TGRB, rate);
+ dev_dbg(&p->pdev->dev, "TRGB = 0x%04lx\n", rate);
+
+ tmp = (cfg->max_brightness - brightness) * rate;
+ r_tpu_write(p, TGRA, tmp / cfg->max_brightness);
+ dev_dbg(&p->pdev->dev, "TRGA = 0x%04lx\n", tmp / cfg->max_brightness);
+
+ /* PWM mode */
+ r_tpu_write(p, TMDR, 0x0002);
+
+ /* enable channel */
+ r_tpu_start_stop_ch(p, 1);
+
+ p->timer_state = R_TPU_TIMER_ON;
+ return 0;
+ err0:
+ clk_disable(p->clk);
+ pm_runtime_put_sync(&p->pdev->dev);
+ return -ENOTSUPP;
+}
+
+static void r_tpu_disable(struct r_tpu_priv *p)
+{
+ if (p->timer_state == R_TPU_TIMER_UNUSED)
+ return;
+
+ /* disable channel */
+ r_tpu_start_stop_ch(p, 0);
+
+ /* stop clock and mark device as idle */
+ clk_disable(p->clk);
+ pm_runtime_put_sync(&p->pdev->dev);
+
+ p->timer_state = R_TPU_TIMER_UNUSED;
+}
+
+static void r_tpu_set_pin(struct r_tpu_priv *p, enum r_tpu_pin new_state,
+ enum led_brightness brightness)
+{
+ struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+
+ if (p->pin_state == new_state) {
+ if (p->pin_state == R_TPU_PIN_GPIO)
+ gpio_set_value(cfg->pin_gpio, brightness);
+ return;
+ }
+
+ if (p->pin_state == R_TPU_PIN_GPIO)
+ gpio_free(cfg->pin_gpio);
+
+ if (p->pin_state == R_TPU_PIN_GPIO_FN)
+ gpio_free(cfg->pin_gpio_fn);
+
+ if (new_state == R_TPU_PIN_GPIO) {
+ gpio_request(cfg->pin_gpio, cfg->name);
+ gpio_direction_output(cfg->pin_gpio, !!brightness);
+ }
+ if (new_state == R_TPU_PIN_GPIO_FN)
+ gpio_request(cfg->pin_gpio_fn, cfg->name);
+
+ p->pin_state = new_state;
+}
+
+static void r_tpu_work(struct work_struct *work)
+{
+ struct r_tpu_priv *p = container_of(work, struct r_tpu_priv, work);
+ enum led_brightness brightness = p->new_brightness;
+
+ r_tpu_disable(p);
+
+ /* off and maximum are handled as GPIO pins, in between PWM */
+ if ((brightness == 0) || (brightness == p->ldev.max_brightness))
+ r_tpu_set_pin(p, R_TPU_PIN_GPIO, brightness);
+ else {
+ r_tpu_set_pin(p, R_TPU_PIN_GPIO_FN, 0);
+ r_tpu_enable(p, brightness);
+ }
+}
+
+static void r_tpu_set_brightness(struct led_classdev *ldev,
+ enum led_brightness brightness)
+{
+ struct r_tpu_priv *p = container_of(ldev, struct r_tpu_priv, ldev);
+ p->new_brightness = brightness;
+ schedule_work(&p->work);
+}
+
+static int __devinit r_tpu_probe(struct platform_device *pdev)
+{
+ struct led_renesas_tpu_config *cfg = pdev->dev.platform_data;
+ struct r_tpu_priv *p;
+ struct resource *res;
+ int ret = -ENXIO;
+
+ if (!cfg) {
+ dev_err(&pdev->dev, "missing platform data\n");
+ goto err0;
+ }
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL) {
+ dev_err(&pdev->dev, "failed to allocate driver data\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get I/O memory\n");
+ goto err1;
+ }
+
+ /* map memory, let mapbase point to our channel */
+ p->mapbase = ioremap_nocache(res->start, resource_size(res));
+ if (p->mapbase == NULL) {
+ dev_err(&pdev->dev, "failed to remap I/O memory\n");
+ goto err1;
+ }
+
+ /* get hold of clock */
+ p->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(p->clk)) {
+ dev_err(&pdev->dev, "cannot get clock\n");
+ ret = PTR_ERR(p->clk);
+ goto err2;
+ }
+
+ p->pdev = pdev;
+ p->pin_state = R_TPU_PIN_UNUSED;
+ p->timer_state = R_TPU_TIMER_UNUSED;
+ p->refresh_rate = cfg->refresh_rate ? cfg->refresh_rate : 100;
+ r_tpu_set_pin(p, R_TPU_PIN_GPIO, LED_OFF);
+ platform_set_drvdata(pdev, p);
+
+ INIT_WORK(&p->work, r_tpu_work);
+
+ p->ldev.name = cfg->name;
+ p->ldev.brightness = LED_OFF;
+ p->ldev.max_brightness = cfg->max_brightness;
+ p->ldev.brightness_set = r_tpu_set_brightness;
+ p->ldev.flags |= LED_CORE_SUSPENDRESUME;
+ ret = led_classdev_register(&pdev->dev, &p->ldev);
+ if (ret < 0)
+ goto err3;
+
+ /* max_brightness may be updated by the LED core code */
+ p->min_rate = p->ldev.max_brightness * p->refresh_rate;
+
+ pm_runtime_enable(&pdev->dev);
+ return 0;
+
+ err3:
+ r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
+ clk_put(p->clk);
+ err2:
+ iounmap(p->mapbase);
+ err1:
+ kfree(p);
+ err0:
+ return ret;
+}
+
+static int __devexit r_tpu_remove(struct platform_device *pdev)
+{
+ struct r_tpu_priv *p = platform_get_drvdata(pdev);
+
+ r_tpu_set_brightness(&p->ldev, LED_OFF);
+ led_classdev_unregister(&p->ldev);
+ cancel_work_sync(&p->work);
+ r_tpu_disable(p);
+ r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
+
+ pm_runtime_disable(&pdev->dev);
+ clk_put(p->clk);
+
+ iounmap(p->mapbase);
+ kfree(p);
+ return 0;
+}
+
+static struct platform_driver r_tpu_device_driver = {
+ .probe = r_tpu_probe,
+ .remove = __devexit_p(r_tpu_remove),
+ .driver = {
+ .name = "leds-renesas-tpu",
+ }
+};
+
+static int __init r_tpu_init(void)
+{
+ return platform_driver_register(&r_tpu_device_driver);
+}
+
+static void __exit r_tpu_exit(void)
+{
+ platform_driver_unregister(&r_tpu_device_driver);
+}
+
+module_init(r_tpu_init);
+module_exit(r_tpu_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas TPU LED Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 2535933c49f8..b5fdcb78a75b 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -232,6 +232,13 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
}
}
+ /*
+ * All long-lived kernel loops need to check with this horrible
+ * thing called the freezer. If the Host is trying to suspend,
+ * it stops us.
+ */
+ try_to_freeze();
+
/* Check for signals */
if (signal_pending(current))
return -ERESTARTSYS;
@@ -246,13 +253,6 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
try_deliver_interrupt(cpu, irq, more);
/*
- * All long-lived kernel loops need to check with this horrible
- * thing called the freezer. If the Host is trying to suspend,
- * it stops us.
- */
- try_to_freeze();
-
- /*
* Just make absolutely sure the Guest is still alive. One of
* those hypercalls could have been fatal, for example.
*/
@@ -313,7 +313,7 @@ static int __init init(void)
int err;
/* Lguest can't run under Xen, VMI or itself. It does Tricky Stuff. */
- if (paravirt_enabled()) {
+ if (get_kernel_rpl() != 0) {
printk("lguest is afraid of being a guest\n");
return -EPERM;
}
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index f75a66e7d312..faa4741df6d3 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -208,6 +208,16 @@ config DM_DEBUG
If unsure, say N.
+config DM_BUFIO
+ tristate
+ depends on BLK_DEV_DM && EXPERIMENTAL
+ ---help---
+ This interface allows you to do buffered I/O on a device and acts
+ as a cache, holding recently-read blocks in memory and performing
+ delayed writes.
+
+source "drivers/md/persistent-data/Kconfig"
+
config DM_CRYPT
tristate "Crypt target support"
depends on BLK_DEV_DM
@@ -233,6 +243,32 @@ config DM_SNAPSHOT
---help---
Allow volume managers to take writable snapshots of a device.
+config DM_THIN_PROVISIONING
+ tristate "Thin provisioning target (EXPERIMENTAL)"
+ depends on BLK_DEV_DM && EXPERIMENTAL
+ select DM_PERSISTENT_DATA
+ ---help---
+ Provides thin provisioning and snapshots that share a data store.
+
+config DM_DEBUG_BLOCK_STACK_TRACING
+ boolean "Keep stack trace of thin provisioning block lock holders"
+ depends on STACKTRACE_SUPPORT && DM_THIN_PROVISIONING
+ select STACKTRACE
+ ---help---
+ Enable this for messages that may help debug problems with the
+ block manager locking used by thin provisioning.
+
+ If unsure, say N.
+
+config DM_DEBUG_SPACE_MAPS
+ boolean "Extra validation for thin provisioning space maps"
+ depends on DM_THIN_PROVISIONING
+ ---help---
+ Enable this for messages that may help debug problems with the
+ space maps used by thin provisioning.
+
+ If unsure, say N.
+
config DM_MIRROR
tristate "Mirror target"
depends on BLK_DEV_DM
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 448838b1f92a..046860c7a166 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -10,6 +10,7 @@ dm-snapshot-y += dm-snap.o dm-exception-store.o dm-snap-transient.o \
dm-mirror-y += dm-raid1.o
dm-log-userspace-y \
+= dm-log-userspace-base.o dm-log-userspace-transfer.o
+dm-thin-pool-y += dm-thin.o dm-thin-metadata.o
md-mod-y += md.o bitmap.o
raid456-y += raid5.o
@@ -27,6 +28,7 @@ obj-$(CONFIG_MD_MULTIPATH) += multipath.o
obj-$(CONFIG_MD_FAULTY) += faulty.o
obj-$(CONFIG_BLK_DEV_MD) += md-mod.o
obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o
+obj-$(CONFIG_DM_BUFIO) += dm-bufio.o
obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
obj-$(CONFIG_DM_DELAY) += dm-delay.o
obj-$(CONFIG_DM_FLAKEY) += dm-flakey.o
@@ -34,10 +36,12 @@ obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o
obj-$(CONFIG_DM_MULTIPATH_QL) += dm-queue-length.o
obj-$(CONFIG_DM_MULTIPATH_ST) += dm-service-time.o
obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
+obj-$(CONFIG_DM_PERSISTENT_DATA) += persistent-data/
obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o
obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o
obj-$(CONFIG_DM_RAID) += dm-raid.o
+obj-$(CONFIG_DM_THIN_PROVISIONING) += dm-thin-pool.o
ifeq ($(CONFIG_DM_UEVENT),y)
dm-mod-objs += dm-uevent.o
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 0dc6546b77a8..7878712721bf 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -29,35 +29,6 @@
#include "md.h"
#include "bitmap.h"
-/* debug macros */
-
-#define DEBUG 0
-
-#if DEBUG
-/* these are for debugging purposes only! */
-
-/* define one and only one of these */
-#define INJECT_FAULTS_1 0 /* cause bitmap_alloc_page to fail always */
-#define INJECT_FAULTS_2 0 /* cause bitmap file to be kicked when first bit set*/
-#define INJECT_FAULTS_3 0 /* treat bitmap file as kicked at init time */
-#define INJECT_FAULTS_4 0 /* undef */
-#define INJECT_FAULTS_5 0 /* undef */
-#define INJECT_FAULTS_6 0
-
-/* if these are defined, the driver will fail! debug only */
-#define INJECT_FATAL_FAULT_1 0 /* fail kmalloc, causing bitmap_create to fail */
-#define INJECT_FATAL_FAULT_2 0 /* undef */
-#define INJECT_FATAL_FAULT_3 0 /* undef */
-#endif
-
-#ifndef PRINTK
-# if DEBUG > 0
-# define PRINTK(x...) printk(KERN_DEBUG x)
-# else
-# define PRINTK(x...)
-# endif
-#endif
-
static inline char *bmname(struct bitmap *bitmap)
{
return bitmap->mddev ? mdname(bitmap->mddev) : "mdX";
@@ -70,16 +41,12 @@ static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
{
unsigned char *page;
-#ifdef INJECT_FAULTS_1
- page = NULL;
-#else
page = kzalloc(PAGE_SIZE, GFP_NOIO);
-#endif
if (!page)
printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
else
- PRINTK("%s: bitmap_alloc_page: allocated page at %p\n",
- bmname(bitmap), page);
+ pr_debug("%s: bitmap_alloc_page: allocated page at %p\n",
+ bmname(bitmap), page);
return page;
}
@@ -88,7 +55,7 @@ static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
*/
static void bitmap_free_page(struct bitmap *bitmap, unsigned char *page)
{
- PRINTK("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
+ pr_debug("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
kfree(page);
}
@@ -133,8 +100,8 @@ __acquires(bitmap->lock)
spin_lock_irq(&bitmap->lock);
if (mappage == NULL) {
- PRINTK("%s: bitmap map page allocation failed, hijacking\n",
- bmname(bitmap));
+ pr_debug("%s: bitmap map page allocation failed, hijacking\n",
+ bmname(bitmap));
/* failed - set the hijacked flag so that we can use the
* pointer as a counter */
if (!bitmap->bp[page].map)
@@ -187,13 +154,13 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
*/
/* IO operations when bitmap is stored near all superblocks */
-static struct page *read_sb_page(mddev_t *mddev, loff_t offset,
+static struct page *read_sb_page(struct mddev *mddev, loff_t offset,
struct page *page,
unsigned long index, int size)
{
/* choose a good rdev and read the page from there */
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t target;
int did_alloc = 0;
@@ -226,7 +193,7 @@ static struct page *read_sb_page(mddev_t *mddev, loff_t offset,
}
-static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev)
{
/* Iterate the disks of an mddev, using rcu to protect access to the
* linked list, and raising the refcount of devices we return to ensure
@@ -247,7 +214,7 @@ static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
pos = &rdev->same_set;
}
list_for_each_continue_rcu(pos, &mddev->disks) {
- rdev = list_entry(pos, mdk_rdev_t, same_set);
+ rdev = list_entry(pos, struct md_rdev, same_set);
if (rdev->raid_disk >= 0 &&
!test_bit(Faulty, &rdev->flags)) {
/* this is a usable devices */
@@ -262,9 +229,9 @@ static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
{
- mdk_rdev_t *rdev = NULL;
+ struct md_rdev *rdev = NULL;
struct block_device *bdev;
- mddev_t *mddev = bitmap->mddev;
+ struct mddev *mddev = bitmap->mddev;
while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
int size = PAGE_SIZE;
@@ -409,8 +376,8 @@ static struct page *read_page(struct file *file, unsigned long index,
struct buffer_head *bh;
sector_t block;
- PRINTK("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
- (unsigned long long)index << PAGE_SHIFT);
+ pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
+ (unsigned long long)index << PAGE_SHIFT);
page = alloc_page(GFP_KERNEL);
if (!page)
@@ -868,7 +835,8 @@ static void bitmap_file_kick(struct bitmap *bitmap)
enum bitmap_page_attr {
BITMAP_PAGE_DIRTY = 0, /* there are set bits that need to be synced */
- BITMAP_PAGE_CLEAN = 1, /* there are bits that might need to be cleared */
+ BITMAP_PAGE_PENDING = 1, /* there are bits that are being cleaned.
+ * i.e. counter is 1 or 2. */
BITMAP_PAGE_NEEDWRITE = 2, /* there are cleared bits that need to be synced */
};
@@ -919,7 +887,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
else
__set_bit_le(bit, kaddr);
kunmap_atomic(kaddr, KM_USER0);
- PRINTK("set file bit %lu page %lu\n", bit, page->index);
+ pr_debug("set file bit %lu page %lu\n", bit, page->index);
/* record page number so it gets flushed to disk when unplug occurs */
set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
}
@@ -997,11 +965,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
BUG_ON(!file && !bitmap->mddev->bitmap_info.offset);
-#ifdef INJECT_FAULTS_3
- outofdate = 1;
-#else
outofdate = bitmap->flags & BITMAP_STALE;
-#endif
if (outofdate)
printk(KERN_INFO "%s: bitmap file is out of date, doing full "
"recovery\n", bmname(bitmap));
@@ -1111,7 +1075,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
(sector_t)i << CHUNK_BLOCK_SHIFT(bitmap),
needed);
bit_cnt++;
- set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
}
@@ -1146,6 +1109,7 @@ void bitmap_write_all(struct bitmap *bitmap)
for (i = 0; i < bitmap->file_pages; i++)
set_page_attr(bitmap, bitmap->filemap[i],
BITMAP_PAGE_NEEDWRITE);
+ bitmap->allclean = 0;
}
static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
@@ -1164,7 +1128,7 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
* out to disk
*/
-void bitmap_daemon_work(mddev_t *mddev)
+void bitmap_daemon_work(struct mddev *mddev)
{
struct bitmap *bitmap;
unsigned long j;
@@ -1204,17 +1168,15 @@ void bitmap_daemon_work(mddev_t *mddev)
if (page != lastpage) {
/* skip this page unless it's marked as needing cleaning */
- if (!test_page_attr(bitmap, page, BITMAP_PAGE_CLEAN)) {
+ if (!test_page_attr(bitmap, page, BITMAP_PAGE_PENDING)) {
int need_write = test_page_attr(bitmap, page,
BITMAP_PAGE_NEEDWRITE);
if (need_write)
clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
- if (need_write) {
+ if (need_write)
write_page(bitmap, page, 0);
- bitmap->allclean = 0;
- }
spin_lock_irqsave(&bitmap->lock, flags);
j |= (PAGE_BITS - 1);
continue;
@@ -1222,12 +1184,16 @@ void bitmap_daemon_work(mddev_t *mddev)
/* grab the new page, sync and release the old */
if (lastpage != NULL) {
- if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
- clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ if (test_page_attr(bitmap, lastpage,
+ BITMAP_PAGE_NEEDWRITE)) {
+ clear_page_attr(bitmap, lastpage,
+ BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
write_page(bitmap, lastpage, 0);
} else {
- set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ set_page_attr(bitmap, lastpage,
+ BITMAP_PAGE_NEEDWRITE);
+ bitmap->allclean = 0;
spin_unlock_irqrestore(&bitmap->lock, flags);
}
} else
@@ -1249,19 +1215,17 @@ void bitmap_daemon_work(mddev_t *mddev)
}
spin_lock_irqsave(&bitmap->lock, flags);
if (!bitmap->need_sync)
- clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+ clear_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+ else
+ bitmap->allclean = 0;
}
bmc = bitmap_get_counter(bitmap,
(sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
&blocks, 0);
- if (bmc) {
- if (*bmc)
- bitmap->allclean = 0;
-
- if (*bmc == 2) {
- *bmc = 1; /* maybe clear the bit next time */
- set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
- } else if (*bmc == 1 && !bitmap->need_sync) {
+ if (!bmc)
+ j |= PAGE_COUNTER_MASK;
+ else if (*bmc) {
+ if (*bmc == 1 && !bitmap->need_sync) {
/* we can clear the bit */
*bmc = 0;
bitmap_count_page(bitmap,
@@ -1275,13 +1239,16 @@ void bitmap_daemon_work(mddev_t *mddev)
paddr);
else
__clear_bit_le(
- file_page_offset(bitmap,
- j),
- paddr);
+ file_page_offset(bitmap,
+ j),
+ paddr);
kunmap_atomic(paddr, KM_USER0);
+ } else if (*bmc <= 2) {
+ *bmc = 1; /* maybe clear the bit next time */
+ set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+ bitmap->allclean = 0;
}
- } else
- j |= PAGE_COUNTER_MASK;
+ }
}
spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1294,6 +1261,7 @@ void bitmap_daemon_work(mddev_t *mddev)
write_page(bitmap, lastpage, 0);
} else {
set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ bitmap->allclean = 0;
spin_unlock_irqrestore(&bitmap->lock, flags);
}
}
@@ -1359,8 +1327,8 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
if (bw > bitmap->behind_writes_used)
bitmap->behind_writes_used = bw;
- PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
- bw, bitmap->max_write_behind);
+ pr_debug("inc write-behind count %d/%lu\n",
+ bw, bitmap->mddev->bitmap_info.max_write_behind);
}
while (sectors) {
@@ -1407,7 +1375,6 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
else
sectors = 0;
}
- bitmap->allclean = 0;
return 0;
}
EXPORT_SYMBOL(bitmap_startwrite);
@@ -1420,8 +1387,9 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
if (behind) {
if (atomic_dec_and_test(&bitmap->behind_writes))
wake_up(&bitmap->behind_wait);
- PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
- atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+ pr_debug("dec write-behind count %d/%lu\n",
+ atomic_read(&bitmap->behind_writes),
+ bitmap->mddev->bitmap_info.max_write_behind);
}
if (bitmap->mddev->degraded)
/* Never clear bits or update events_cleared when degraded */
@@ -1453,13 +1421,14 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
wake_up(&bitmap->overflow_wait);
(*bmc)--;
- if (*bmc <= 2)
+ if (*bmc <= 2) {
set_page_attr(bitmap,
filemap_get_page(
bitmap,
offset >> CHUNK_BLOCK_SHIFT(bitmap)),
- BITMAP_PAGE_CLEAN);
-
+ BITMAP_PAGE_PENDING);
+ bitmap->allclean = 0;
+ }
spin_unlock_irqrestore(&bitmap->lock, flags);
offset += blocks;
if (sectors > blocks)
@@ -1495,7 +1464,6 @@ static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t
}
}
spin_unlock_irq(&bitmap->lock);
- bitmap->allclean = 0;
return rv;
}
@@ -1543,15 +1511,16 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
if (!NEEDED(*bmc) && aborted)
*bmc |= NEEDED_MASK;
else {
- if (*bmc <= 2)
+ if (*bmc <= 2) {
set_page_attr(bitmap,
filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
- BITMAP_PAGE_CLEAN);
+ BITMAP_PAGE_PENDING);
+ bitmap->allclean = 0;
+ }
}
}
unlock:
spin_unlock_irqrestore(&bitmap->lock, flags);
- bitmap->allclean = 0;
}
EXPORT_SYMBOL(bitmap_end_sync);
@@ -1622,10 +1591,10 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
*bmc = 1 | (needed ? NEEDED_MASK : 0);
bitmap_count_page(bitmap, offset, 1);
page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
- set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+ set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+ bitmap->allclean = 0;
}
spin_unlock_irq(&bitmap->lock);
- bitmap->allclean = 0;
}
/* dirty the memory and file bits for bitmap chunks "s" to "e" */
@@ -1649,7 +1618,7 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e)
/*
* flush out any pending updates
*/
-void bitmap_flush(mddev_t *mddev)
+void bitmap_flush(struct mddev *mddev)
{
struct bitmap *bitmap = mddev->bitmap;
long sleep;
@@ -1697,7 +1666,7 @@ static void bitmap_free(struct bitmap *bitmap)
kfree(bitmap);
}
-void bitmap_destroy(mddev_t *mddev)
+void bitmap_destroy(struct mddev *mddev)
{
struct bitmap *bitmap = mddev->bitmap;
@@ -1720,7 +1689,7 @@ void bitmap_destroy(mddev_t *mddev)
* initialize the bitmap structure
* if this returns an error, bitmap_destroy must be called to do clean up
*/
-int bitmap_create(mddev_t *mddev)
+int bitmap_create(struct mddev *mddev)
{
struct bitmap *bitmap;
sector_t blocks = mddev->resync_max_sectors;
@@ -1802,11 +1771,8 @@ int bitmap_create(mddev_t *mddev)
bitmap->pages = pages;
bitmap->missing_pages = pages;
-#ifdef INJECT_FATAL_FAULT_1
- bitmap->bp = NULL;
-#else
bitmap->bp = kzalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
-#endif
+
err = -ENOMEM;
if (!bitmap->bp)
goto error;
@@ -1824,7 +1790,7 @@ int bitmap_create(mddev_t *mddev)
return err;
}
-int bitmap_load(mddev_t *mddev)
+int bitmap_load(struct mddev *mddev)
{
int err = 0;
sector_t start = 0;
@@ -1870,7 +1836,7 @@ out:
EXPORT_SYMBOL_GPL(bitmap_load);
static ssize_t
-location_show(mddev_t *mddev, char *page)
+location_show(struct mddev *mddev, char *page)
{
ssize_t len;
if (mddev->bitmap_info.file)
@@ -1884,7 +1850,7 @@ location_show(mddev_t *mddev, char *page)
}
static ssize_t
-location_store(mddev_t *mddev, const char *buf, size_t len)
+location_store(struct mddev *mddev, const char *buf, size_t len)
{
if (mddev->pers) {
@@ -1961,7 +1927,7 @@ static struct md_sysfs_entry bitmap_location =
__ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store);
static ssize_t
-timeout_show(mddev_t *mddev, char *page)
+timeout_show(struct mddev *mddev, char *page)
{
ssize_t len;
unsigned long secs = mddev->bitmap_info.daemon_sleep / HZ;
@@ -1975,7 +1941,7 @@ timeout_show(mddev_t *mddev, char *page)
}
static ssize_t
-timeout_store(mddev_t *mddev, const char *buf, size_t len)
+timeout_store(struct mddev *mddev, const char *buf, size_t len)
{
/* timeout can be set at any time */
unsigned long timeout;
@@ -2011,13 +1977,13 @@ static struct md_sysfs_entry bitmap_timeout =
__ATTR(time_base, S_IRUGO|S_IWUSR, timeout_show, timeout_store);
static ssize_t
-backlog_show(mddev_t *mddev, char *page)
+backlog_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%lu\n", mddev->bitmap_info.max_write_behind);
}
static ssize_t
-backlog_store(mddev_t *mddev, const char *buf, size_t len)
+backlog_store(struct mddev *mddev, const char *buf, size_t len)
{
unsigned long backlog;
int rv = strict_strtoul(buf, 10, &backlog);
@@ -2033,13 +1999,13 @@ static struct md_sysfs_entry bitmap_backlog =
__ATTR(backlog, S_IRUGO|S_IWUSR, backlog_show, backlog_store);
static ssize_t
-chunksize_show(mddev_t *mddev, char *page)
+chunksize_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%lu\n", mddev->bitmap_info.chunksize);
}
static ssize_t
-chunksize_store(mddev_t *mddev, const char *buf, size_t len)
+chunksize_store(struct mddev *mddev, const char *buf, size_t len)
{
/* Can only be changed when no bitmap is active */
int rv;
@@ -2059,13 +2025,13 @@ chunksize_store(mddev_t *mddev, const char *buf, size_t len)
static struct md_sysfs_entry bitmap_chunksize =
__ATTR(chunksize, S_IRUGO|S_IWUSR, chunksize_show, chunksize_store);
-static ssize_t metadata_show(mddev_t *mddev, char *page)
+static ssize_t metadata_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%s\n", (mddev->bitmap_info.external
? "external" : "internal"));
}
-static ssize_t metadata_store(mddev_t *mddev, const char *buf, size_t len)
+static ssize_t metadata_store(struct mddev *mddev, const char *buf, size_t len)
{
if (mddev->bitmap ||
mddev->bitmap_info.file ||
@@ -2083,7 +2049,7 @@ static ssize_t metadata_store(mddev_t *mddev, const char *buf, size_t len)
static struct md_sysfs_entry bitmap_metadata =
__ATTR(metadata, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
-static ssize_t can_clear_show(mddev_t *mddev, char *page)
+static ssize_t can_clear_show(struct mddev *mddev, char *page)
{
int len;
if (mddev->bitmap)
@@ -2094,7 +2060,7 @@ static ssize_t can_clear_show(mddev_t *mddev, char *page)
return len;
}
-static ssize_t can_clear_store(mddev_t *mddev, const char *buf, size_t len)
+static ssize_t can_clear_store(struct mddev *mddev, const char *buf, size_t len)
{
if (mddev->bitmap == NULL)
return -ENOENT;
@@ -2113,7 +2079,7 @@ static struct md_sysfs_entry bitmap_can_clear =
__ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store);
static ssize_t
-behind_writes_used_show(mddev_t *mddev, char *page)
+behind_writes_used_show(struct mddev *mddev, char *page)
{
if (mddev->bitmap == NULL)
return sprintf(page, "0\n");
@@ -2122,7 +2088,7 @@ behind_writes_used_show(mddev_t *mddev, char *page)
}
static ssize_t
-behind_writes_used_reset(mddev_t *mddev, const char *buf, size_t len)
+behind_writes_used_reset(struct mddev *mddev, const char *buf, size_t len)
{
if (mddev->bitmap)
mddev->bitmap->behind_writes_used = 0;
diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h
index a28f2e5588c6..a15436dd9b3e 100644
--- a/drivers/md/bitmap.h
+++ b/drivers/md/bitmap.h
@@ -193,7 +193,7 @@ struct bitmap {
unsigned long pages; /* total number of pages in the bitmap */
unsigned long missing_pages; /* number of pages not yet allocated */
- mddev_t *mddev; /* the md device that the bitmap is for */
+ struct mddev *mddev; /* the md device that the bitmap is for */
/* bitmap chunksize -- how much data does each bit represent? */
unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
@@ -238,10 +238,10 @@ struct bitmap {
/* the bitmap API */
/* these are used only by md/bitmap */
-int bitmap_create(mddev_t *mddev);
-int bitmap_load(mddev_t *mddev);
-void bitmap_flush(mddev_t *mddev);
-void bitmap_destroy(mddev_t *mddev);
+int bitmap_create(struct mddev *mddev);
+int bitmap_load(struct mddev *mddev);
+void bitmap_flush(struct mddev *mddev);
+void bitmap_destroy(struct mddev *mddev);
void bitmap_print_sb(struct bitmap *bitmap);
void bitmap_update_sb(struct bitmap *bitmap);
@@ -262,7 +262,7 @@ void bitmap_close_sync(struct bitmap *bitmap);
void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector);
void bitmap_unplug(struct bitmap *bitmap);
-void bitmap_daemon_work(mddev_t *mddev);
+void bitmap_daemon_work(struct mddev *mddev);
#endif
#endif
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
new file mode 100644
index 000000000000..cb246667dd52
--- /dev/null
+++ b/drivers/md/dm-bufio.c
@@ -0,0 +1,1699 @@
+/*
+ * Copyright (C) 2009-2011 Red Hat, Inc.
+ *
+ * Author: Mikulas Patocka <mpatocka@redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-bufio.h"
+
+#include <linux/device-mapper.h>
+#include <linux/dm-io.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+#include <linux/shrinker.h>
+
+#define DM_MSG_PREFIX "bufio"
+
+/*
+ * Memory management policy:
+ * Limit the number of buffers to DM_BUFIO_MEMORY_PERCENT of main memory
+ * or DM_BUFIO_VMALLOC_PERCENT of vmalloc memory (whichever is lower).
+ * Always allocate at least DM_BUFIO_MIN_BUFFERS buffers.
+ * Start background writeback when there are DM_BUFIO_WRITEBACK_PERCENT
+ * dirty buffers.
+ */
+#define DM_BUFIO_MIN_BUFFERS 8
+
+#define DM_BUFIO_MEMORY_PERCENT 2
+#define DM_BUFIO_VMALLOC_PERCENT 25
+#define DM_BUFIO_WRITEBACK_PERCENT 75
+
+/*
+ * Check buffer ages in this interval (seconds)
+ */
+#define DM_BUFIO_WORK_TIMER_SECS 10
+
+/*
+ * Free buffers when they are older than this (seconds)
+ */
+#define DM_BUFIO_DEFAULT_AGE_SECS 60
+
+/*
+ * The number of bvec entries that are embedded directly in the buffer.
+ * If the chunk size is larger, dm-io is used to do the io.
+ */
+#define DM_BUFIO_INLINE_VECS 16
+
+/*
+ * Buffer hash
+ */
+#define DM_BUFIO_HASH_BITS 20
+#define DM_BUFIO_HASH(block) \
+ ((((block) >> DM_BUFIO_HASH_BITS) ^ (block)) & \
+ ((1 << DM_BUFIO_HASH_BITS) - 1))
+
+/*
+ * Don't try to use kmem_cache_alloc for blocks larger than this.
+ * For explanation, see alloc_buffer_data below.
+ */
+#define DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT (PAGE_SIZE >> 1)
+#define DM_BUFIO_BLOCK_SIZE_GFP_LIMIT (PAGE_SIZE << (MAX_ORDER - 1))
+
+/*
+ * dm_buffer->list_mode
+ */
+#define LIST_CLEAN 0
+#define LIST_DIRTY 1
+#define LIST_SIZE 2
+
+/*
+ * Linking of buffers:
+ * All buffers are linked to cache_hash with their hash_list field.
+ *
+ * Clean buffers that are not being written (B_WRITING not set)
+ * are linked to lru[LIST_CLEAN] with their lru_list field.
+ *
+ * Dirty and clean buffers that are being written are linked to
+ * lru[LIST_DIRTY] with their lru_list field. When the write
+ * finishes, the buffer cannot be relinked immediately (because we
+ * are in an interrupt context and relinking requires process
+ * context), so some clean-not-writing buffers can be held on
+ * dirty_lru too. They are later added to lru in the process
+ * context.
+ */
+struct dm_bufio_client {
+ struct mutex lock;
+
+ struct list_head lru[LIST_SIZE];
+ unsigned long n_buffers[LIST_SIZE];
+
+ struct block_device *bdev;
+ unsigned block_size;
+ unsigned char sectors_per_block_bits;
+ unsigned char pages_per_block_bits;
+ unsigned char blocks_per_page_bits;
+ unsigned aux_size;
+ void (*alloc_callback)(struct dm_buffer *);
+ void (*write_callback)(struct dm_buffer *);
+
+ struct dm_io_client *dm_io;
+
+ struct list_head reserved_buffers;
+ unsigned need_reserved_buffers;
+
+ struct hlist_head *cache_hash;
+ wait_queue_head_t free_buffer_wait;
+
+ int async_write_error;
+
+ struct list_head client_list;
+ struct shrinker shrinker;
+};
+
+/*
+ * Buffer state bits.
+ */
+#define B_READING 0
+#define B_WRITING 1
+#define B_DIRTY 2
+
+/*
+ * Describes how the block was allocated:
+ * kmem_cache_alloc(), __get_free_pages() or vmalloc().
+ * See the comment at alloc_buffer_data.
+ */
+enum data_mode {
+ DATA_MODE_SLAB = 0,
+ DATA_MODE_GET_FREE_PAGES = 1,
+ DATA_MODE_VMALLOC = 2,
+ DATA_MODE_LIMIT = 3
+};
+
+struct dm_buffer {
+ struct hlist_node hash_list;
+ struct list_head lru_list;
+ sector_t block;
+ void *data;
+ enum data_mode data_mode;
+ unsigned char list_mode; /* LIST_* */
+ unsigned hold_count;
+ int read_error;
+ int write_error;
+ unsigned long state;
+ unsigned long last_accessed;
+ struct dm_bufio_client *c;
+ struct bio bio;
+ struct bio_vec bio_vec[DM_BUFIO_INLINE_VECS];
+};
+
+/*----------------------------------------------------------------*/
+
+static struct kmem_cache *dm_bufio_caches[PAGE_SHIFT - SECTOR_SHIFT];
+static char *dm_bufio_cache_names[PAGE_SHIFT - SECTOR_SHIFT];
+
+static inline int dm_bufio_cache_index(struct dm_bufio_client *c)
+{
+ unsigned ret = c->blocks_per_page_bits - 1;
+
+ BUG_ON(ret >= ARRAY_SIZE(dm_bufio_caches));
+
+ return ret;
+}
+
+#define DM_BUFIO_CACHE(c) (dm_bufio_caches[dm_bufio_cache_index(c)])
+#define DM_BUFIO_CACHE_NAME(c) (dm_bufio_cache_names[dm_bufio_cache_index(c)])
+
+#define dm_bufio_in_request() (!!current->bio_list)
+
+static void dm_bufio_lock(struct dm_bufio_client *c)
+{
+ mutex_lock_nested(&c->lock, dm_bufio_in_request());
+}
+
+static int dm_bufio_trylock(struct dm_bufio_client *c)
+{
+ return mutex_trylock(&c->lock);
+}
+
+static void dm_bufio_unlock(struct dm_bufio_client *c)
+{
+ mutex_unlock(&c->lock);
+}
+
+/*
+ * FIXME Move to sched.h?
+ */
+#ifdef CONFIG_PREEMPT_VOLUNTARY
+# define dm_bufio_cond_resched() \
+do { \
+ if (unlikely(need_resched())) \
+ _cond_resched(); \
+} while (0)
+#else
+# define dm_bufio_cond_resched() do { } while (0)
+#endif
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Default cache size: available memory divided by the ratio.
+ */
+static unsigned long dm_bufio_default_cache_size;
+
+/*
+ * Total cache size set by the user.
+ */
+static unsigned long dm_bufio_cache_size;
+
+/*
+ * A copy of dm_bufio_cache_size because dm_bufio_cache_size can change
+ * at any time. If it disagrees, the user has changed cache size.
+ */
+static unsigned long dm_bufio_cache_size_latch;
+
+static DEFINE_SPINLOCK(param_spinlock);
+
+/*
+ * Buffers are freed after this timeout
+ */
+static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
+
+static unsigned long dm_bufio_peak_allocated;
+static unsigned long dm_bufio_allocated_kmem_cache;
+static unsigned long dm_bufio_allocated_get_free_pages;
+static unsigned long dm_bufio_allocated_vmalloc;
+static unsigned long dm_bufio_current_allocated;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Per-client cache: dm_bufio_cache_size / dm_bufio_client_count
+ */
+static unsigned long dm_bufio_cache_size_per_client;
+
+/*
+ * The current number of clients.
+ */
+static int dm_bufio_client_count;
+
+/*
+ * The list of all clients.
+ */
+static LIST_HEAD(dm_bufio_all_clients);
+
+/*
+ * This mutex protects dm_bufio_cache_size_latch,
+ * dm_bufio_cache_size_per_client and dm_bufio_client_count
+ */
+static DEFINE_MUTEX(dm_bufio_clients_lock);
+
+/*----------------------------------------------------------------*/
+
+static void adjust_total_allocated(enum data_mode data_mode, long diff)
+{
+ static unsigned long * const class_ptr[DATA_MODE_LIMIT] = {
+ &dm_bufio_allocated_kmem_cache,
+ &dm_bufio_allocated_get_free_pages,
+ &dm_bufio_allocated_vmalloc,
+ };
+
+ spin_lock(&param_spinlock);
+
+ *class_ptr[data_mode] += diff;
+
+ dm_bufio_current_allocated += diff;
+
+ if (dm_bufio_current_allocated > dm_bufio_peak_allocated)
+ dm_bufio_peak_allocated = dm_bufio_current_allocated;
+
+ spin_unlock(&param_spinlock);
+}
+
+/*
+ * Change the number of clients and recalculate per-client limit.
+ */
+static void __cache_size_refresh(void)
+{
+ BUG_ON(!mutex_is_locked(&dm_bufio_clients_lock));
+ BUG_ON(dm_bufio_client_count < 0);
+
+ dm_bufio_cache_size_latch = dm_bufio_cache_size;
+
+ barrier();
+
+ /*
+ * Use default if set to 0 and report the actual cache size used.
+ */
+ if (!dm_bufio_cache_size_latch) {
+ (void)cmpxchg(&dm_bufio_cache_size, 0,
+ dm_bufio_default_cache_size);
+ dm_bufio_cache_size_latch = dm_bufio_default_cache_size;
+ }
+
+ dm_bufio_cache_size_per_client = dm_bufio_cache_size_latch /
+ (dm_bufio_client_count ? : 1);
+}
+
+/*
+ * Allocating buffer data.
+ *
+ * Small buffers are allocated with kmem_cache, to use space optimally.
+ *
+ * For large buffers, we choose between get_free_pages and vmalloc.
+ * Each has advantages and disadvantages.
+ *
+ * __get_free_pages can randomly fail if the memory is fragmented.
+ * __vmalloc won't randomly fail, but vmalloc space is limited (it may be
+ * as low as 128M) so using it for caching is not appropriate.
+ *
+ * If the allocation may fail we use __get_free_pages. Memory fragmentation
+ * won't have a fatal effect here, but it just causes flushes of some other
+ * buffers and more I/O will be performed. Don't use __get_free_pages if it
+ * always fails (i.e. order >= MAX_ORDER).
+ *
+ * If the allocation shouldn't fail we use __vmalloc. This is only for the
+ * initial reserve allocation, so there's no risk of wasting all vmalloc
+ * space.
+ */
+static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
+ enum data_mode *data_mode)
+{
+ if (c->block_size <= DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT) {
+ *data_mode = DATA_MODE_SLAB;
+ return kmem_cache_alloc(DM_BUFIO_CACHE(c), gfp_mask);
+ }
+
+ if (c->block_size <= DM_BUFIO_BLOCK_SIZE_GFP_LIMIT &&
+ gfp_mask & __GFP_NORETRY) {
+ *data_mode = DATA_MODE_GET_FREE_PAGES;
+ return (void *)__get_free_pages(gfp_mask,
+ c->pages_per_block_bits);
+ }
+
+ *data_mode = DATA_MODE_VMALLOC;
+ return __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL);
+}
+
+/*
+ * Free buffer's data.
+ */
+static void free_buffer_data(struct dm_bufio_client *c,
+ void *data, enum data_mode data_mode)
+{
+ switch (data_mode) {
+ case DATA_MODE_SLAB:
+ kmem_cache_free(DM_BUFIO_CACHE(c), data);
+ break;
+
+ case DATA_MODE_GET_FREE_PAGES:
+ free_pages((unsigned long)data, c->pages_per_block_bits);
+ break;
+
+ case DATA_MODE_VMALLOC:
+ vfree(data);
+ break;
+
+ default:
+ DMCRIT("dm_bufio_free_buffer_data: bad data mode: %d",
+ data_mode);
+ BUG();
+ }
+}
+
+/*
+ * Allocate buffer and its data.
+ */
+static struct dm_buffer *alloc_buffer(struct dm_bufio_client *c, gfp_t gfp_mask)
+{
+ struct dm_buffer *b = kmalloc(sizeof(struct dm_buffer) + c->aux_size,
+ gfp_mask);
+
+ if (!b)
+ return NULL;
+
+ b->c = c;
+
+ b->data = alloc_buffer_data(c, gfp_mask, &b->data_mode);
+ if (!b->data) {
+ kfree(b);
+ return NULL;
+ }
+
+ adjust_total_allocated(b->data_mode, (long)c->block_size);
+
+ return b;
+}
+
+/*
+ * Free buffer and its data.
+ */
+static void free_buffer(struct dm_buffer *b)
+{
+ struct dm_bufio_client *c = b->c;
+
+ adjust_total_allocated(b->data_mode, -(long)c->block_size);
+
+ free_buffer_data(c, b->data, b->data_mode);
+ kfree(b);
+}
+
+/*
+ * Link buffer to the hash list and clean or dirty queue.
+ */
+static void __link_buffer(struct dm_buffer *b, sector_t block, int dirty)
+{
+ struct dm_bufio_client *c = b->c;
+
+ c->n_buffers[dirty]++;
+ b->block = block;
+ b->list_mode = dirty;
+ list_add(&b->lru_list, &c->lru[dirty]);
+ hlist_add_head(&b->hash_list, &c->cache_hash[DM_BUFIO_HASH(block)]);
+ b->last_accessed = jiffies;
+}
+
+/*
+ * Unlink buffer from the hash list and dirty or clean queue.
+ */
+static void __unlink_buffer(struct dm_buffer *b)
+{
+ struct dm_bufio_client *c = b->c;
+
+ BUG_ON(!c->n_buffers[b->list_mode]);
+
+ c->n_buffers[b->list_mode]--;
+ hlist_del(&b->hash_list);
+ list_del(&b->lru_list);
+}
+
+/*
+ * Place the buffer to the head of dirty or clean LRU queue.
+ */
+static void __relink_lru(struct dm_buffer *b, int dirty)
+{
+ struct dm_bufio_client *c = b->c;
+
+ BUG_ON(!c->n_buffers[b->list_mode]);
+
+ c->n_buffers[b->list_mode]--;
+ c->n_buffers[dirty]++;
+ b->list_mode = dirty;
+ list_del(&b->lru_list);
+ list_add(&b->lru_list, &c->lru[dirty]);
+}
+
+/*----------------------------------------------------------------
+ * Submit I/O on the buffer.
+ *
+ * Bio interface is faster but it has some problems:
+ * the vector list is limited (increasing this limit increases
+ * memory-consumption per buffer, so it is not viable);
+ *
+ * the memory must be direct-mapped, not vmalloced;
+ *
+ * the I/O driver can reject requests spuriously if it thinks that
+ * the requests are too big for the device or if they cross a
+ * controller-defined memory boundary.
+ *
+ * If the buffer is small enough (up to DM_BUFIO_INLINE_VECS pages) and
+ * it is not vmalloced, try using the bio interface.
+ *
+ * If the buffer is big, if it is vmalloced or if the underlying device
+ * rejects the bio because it is too large, use dm-io layer to do the I/O.
+ * The dm-io layer splits the I/O into multiple requests, avoiding the above
+ * shortcomings.
+ *--------------------------------------------------------------*/
+
+/*
+ * dm-io completion routine. It just calls b->bio.bi_end_io, pretending
+ * that the request was handled directly with bio interface.
+ */
+static void dmio_complete(unsigned long error, void *context)
+{
+ struct dm_buffer *b = context;
+
+ b->bio.bi_end_io(&b->bio, error ? -EIO : 0);
+}
+
+static void use_dmio(struct dm_buffer *b, int rw, sector_t block,
+ bio_end_io_t *end_io)
+{
+ int r;
+ struct dm_io_request io_req = {
+ .bi_rw = rw,
+ .notify.fn = dmio_complete,
+ .notify.context = b,
+ .client = b->c->dm_io,
+ };
+ struct dm_io_region region = {
+ .bdev = b->c->bdev,
+ .sector = block << b->c->sectors_per_block_bits,
+ .count = b->c->block_size >> SECTOR_SHIFT,
+ };
+
+ if (b->data_mode != DATA_MODE_VMALLOC) {
+ io_req.mem.type = DM_IO_KMEM;
+ io_req.mem.ptr.addr = b->data;
+ } else {
+ io_req.mem.type = DM_IO_VMA;
+ io_req.mem.ptr.vma = b->data;
+ }
+
+ b->bio.bi_end_io = end_io;
+
+ r = dm_io(&io_req, 1, &region, NULL);
+ if (r)
+ end_io(&b->bio, r);
+}
+
+static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block,
+ bio_end_io_t *end_io)
+{
+ char *ptr;
+ int len;
+
+ bio_init(&b->bio);
+ b->bio.bi_io_vec = b->bio_vec;
+ b->bio.bi_max_vecs = DM_BUFIO_INLINE_VECS;
+ b->bio.bi_sector = block << b->c->sectors_per_block_bits;
+ b->bio.bi_bdev = b->c->bdev;
+ b->bio.bi_end_io = end_io;
+
+ /*
+ * We assume that if len >= PAGE_SIZE ptr is page-aligned.
+ * If len < PAGE_SIZE the buffer doesn't cross page boundary.
+ */
+ ptr = b->data;
+ len = b->c->block_size;
+
+ if (len >= PAGE_SIZE)
+ BUG_ON((unsigned long)ptr & (PAGE_SIZE - 1));
+ else
+ BUG_ON((unsigned long)ptr & (len - 1));
+
+ do {
+ if (!bio_add_page(&b->bio, virt_to_page(ptr),
+ len < PAGE_SIZE ? len : PAGE_SIZE,
+ virt_to_phys(ptr) & (PAGE_SIZE - 1))) {
+ BUG_ON(b->c->block_size <= PAGE_SIZE);
+ use_dmio(b, rw, block, end_io);
+ return;
+ }
+
+ len -= PAGE_SIZE;
+ ptr += PAGE_SIZE;
+ } while (len > 0);
+
+ submit_bio(rw, &b->bio);
+}
+
+static void submit_io(struct dm_buffer *b, int rw, sector_t block,
+ bio_end_io_t *end_io)
+{
+ if (rw == WRITE && b->c->write_callback)
+ b->c->write_callback(b);
+
+ if (b->c->block_size <= DM_BUFIO_INLINE_VECS * PAGE_SIZE &&
+ b->data_mode != DATA_MODE_VMALLOC)
+ use_inline_bio(b, rw, block, end_io);
+ else
+ use_dmio(b, rw, block, end_io);
+}
+
+/*----------------------------------------------------------------
+ * Writing dirty buffers
+ *--------------------------------------------------------------*/
+
+/*
+ * The endio routine for write.
+ *
+ * Set the error, clear B_WRITING bit and wake anyone who was waiting on
+ * it.
+ */
+static void write_endio(struct bio *bio, int error)
+{
+ struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
+
+ b->write_error = error;
+ if (error) {
+ struct dm_bufio_client *c = b->c;
+ (void)cmpxchg(&c->async_write_error, 0, error);
+ }
+
+ BUG_ON(!test_bit(B_WRITING, &b->state));
+
+ smp_mb__before_clear_bit();
+ clear_bit(B_WRITING, &b->state);
+ smp_mb__after_clear_bit();
+
+ wake_up_bit(&b->state, B_WRITING);
+}
+
+/*
+ * This function is called when wait_on_bit is actually waiting.
+ */
+static int do_io_schedule(void *word)
+{
+ io_schedule();
+
+ return 0;
+}
+
+/*
+ * Initiate a write on a dirty buffer, but don't wait for it.
+ *
+ * - If the buffer is not dirty, exit.
+ * - If there some previous write going on, wait for it to finish (we can't
+ * have two writes on the same buffer simultaneously).
+ * - Submit our write and don't wait on it. We set B_WRITING indicating
+ * that there is a write in progress.
+ */
+static void __write_dirty_buffer(struct dm_buffer *b)
+{
+ if (!test_bit(B_DIRTY, &b->state))
+ return;
+
+ clear_bit(B_DIRTY, &b->state);
+ wait_on_bit_lock(&b->state, B_WRITING,
+ do_io_schedule, TASK_UNINTERRUPTIBLE);
+
+ submit_io(b, WRITE, b->block, write_endio);
+}
+
+/*
+ * Wait until any activity on the buffer finishes. Possibly write the
+ * buffer if it is dirty. When this function finishes, there is no I/O
+ * running on the buffer and the buffer is not dirty.
+ */
+static void __make_buffer_clean(struct dm_buffer *b)
+{
+ BUG_ON(b->hold_count);
+
+ if (!b->state) /* fast case */
+ return;
+
+ wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+ __write_dirty_buffer(b);
+ wait_on_bit(&b->state, B_WRITING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+}
+
+/*
+ * Find some buffer that is not held by anybody, clean it, unlink it and
+ * return it.
+ */
+static struct dm_buffer *__get_unclaimed_buffer(struct dm_bufio_client *c)
+{
+ struct dm_buffer *b;
+
+ list_for_each_entry_reverse(b, &c->lru[LIST_CLEAN], lru_list) {
+ BUG_ON(test_bit(B_WRITING, &b->state));
+ BUG_ON(test_bit(B_DIRTY, &b->state));
+
+ if (!b->hold_count) {
+ __make_buffer_clean(b);
+ __unlink_buffer(b);
+ return b;
+ }
+ dm_bufio_cond_resched();
+ }
+
+ list_for_each_entry_reverse(b, &c->lru[LIST_DIRTY], lru_list) {
+ BUG_ON(test_bit(B_READING, &b->state));
+
+ if (!b->hold_count) {
+ __make_buffer_clean(b);
+ __unlink_buffer(b);
+ return b;
+ }
+ dm_bufio_cond_resched();
+ }
+
+ return NULL;
+}
+
+/*
+ * Wait until some other threads free some buffer or release hold count on
+ * some buffer.
+ *
+ * This function is entered with c->lock held, drops it and regains it
+ * before exiting.
+ */
+static void __wait_for_free_buffer(struct dm_bufio_client *c)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(&c->free_buffer_wait, &wait);
+ set_task_state(current, TASK_UNINTERRUPTIBLE);
+ dm_bufio_unlock(c);
+
+ io_schedule();
+
+ set_task_state(current, TASK_RUNNING);
+ remove_wait_queue(&c->free_buffer_wait, &wait);
+
+ dm_bufio_lock(c);
+}
+
+/*
+ * Allocate a new buffer. If the allocation is not possible, wait until
+ * some other thread frees a buffer.
+ *
+ * May drop the lock and regain it.
+ */
+static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c)
+{
+ struct dm_buffer *b;
+
+ /*
+ * dm-bufio is resistant to allocation failures (it just keeps
+ * one buffer reserved in cases all the allocations fail).
+ * So set flags to not try too hard:
+ * GFP_NOIO: don't recurse into the I/O layer
+ * __GFP_NORETRY: don't retry and rather return failure
+ * __GFP_NOMEMALLOC: don't use emergency reserves
+ * __GFP_NOWARN: don't print a warning in case of failure
+ *
+ * For debugging, if we set the cache size to 1, no new buffers will
+ * be allocated.
+ */
+ while (1) {
+ if (dm_bufio_cache_size_latch != 1) {
+ b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+ if (b)
+ return b;
+ }
+
+ if (!list_empty(&c->reserved_buffers)) {
+ b = list_entry(c->reserved_buffers.next,
+ struct dm_buffer, lru_list);
+ list_del(&b->lru_list);
+ c->need_reserved_buffers++;
+
+ return b;
+ }
+
+ b = __get_unclaimed_buffer(c);
+ if (b)
+ return b;
+
+ __wait_for_free_buffer(c);
+ }
+}
+
+static struct dm_buffer *__alloc_buffer_wait(struct dm_bufio_client *c)
+{
+ struct dm_buffer *b = __alloc_buffer_wait_no_callback(c);
+
+ if (c->alloc_callback)
+ c->alloc_callback(b);
+
+ return b;
+}
+
+/*
+ * Free a buffer and wake other threads waiting for free buffers.
+ */
+static void __free_buffer_wake(struct dm_buffer *b)
+{
+ struct dm_bufio_client *c = b->c;
+
+ if (!c->need_reserved_buffers)
+ free_buffer(b);
+ else {
+ list_add(&b->lru_list, &c->reserved_buffers);
+ c->need_reserved_buffers--;
+ }
+
+ wake_up(&c->free_buffer_wait);
+}
+
+static void __write_dirty_buffers_async(struct dm_bufio_client *c, int no_wait)
+{
+ struct dm_buffer *b, *tmp;
+
+ list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_DIRTY], lru_list) {
+ BUG_ON(test_bit(B_READING, &b->state));
+
+ if (!test_bit(B_DIRTY, &b->state) &&
+ !test_bit(B_WRITING, &b->state)) {
+ __relink_lru(b, LIST_CLEAN);
+ continue;
+ }
+
+ if (no_wait && test_bit(B_WRITING, &b->state))
+ return;
+
+ __write_dirty_buffer(b);
+ dm_bufio_cond_resched();
+ }
+}
+
+/*
+ * Get writeback threshold and buffer limit for a given client.
+ */
+static void __get_memory_limit(struct dm_bufio_client *c,
+ unsigned long *threshold_buffers,
+ unsigned long *limit_buffers)
+{
+ unsigned long buffers;
+
+ if (dm_bufio_cache_size != dm_bufio_cache_size_latch) {
+ mutex_lock(&dm_bufio_clients_lock);
+ __cache_size_refresh();
+ mutex_unlock(&dm_bufio_clients_lock);
+ }
+
+ buffers = dm_bufio_cache_size_per_client >>
+ (c->sectors_per_block_bits + SECTOR_SHIFT);
+
+ if (buffers < DM_BUFIO_MIN_BUFFERS)
+ buffers = DM_BUFIO_MIN_BUFFERS;
+
+ *limit_buffers = buffers;
+ *threshold_buffers = buffers * DM_BUFIO_WRITEBACK_PERCENT / 100;
+}
+
+/*
+ * Check if we're over watermark.
+ * If we are over threshold_buffers, start freeing buffers.
+ * If we're over "limit_buffers", block until we get under the limit.
+ */
+static void __check_watermark(struct dm_bufio_client *c)
+{
+ unsigned long threshold_buffers, limit_buffers;
+
+ __get_memory_limit(c, &threshold_buffers, &limit_buffers);
+
+ while (c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY] >
+ limit_buffers) {
+
+ struct dm_buffer *b = __get_unclaimed_buffer(c);
+
+ if (!b)
+ return;
+
+ __free_buffer_wake(b);
+ dm_bufio_cond_resched();
+ }
+
+ if (c->n_buffers[LIST_DIRTY] > threshold_buffers)
+ __write_dirty_buffers_async(c, 1);
+}
+
+/*
+ * Find a buffer in the hash.
+ */
+static struct dm_buffer *__find(struct dm_bufio_client *c, sector_t block)
+{
+ struct dm_buffer *b;
+ struct hlist_node *hn;
+
+ hlist_for_each_entry(b, hn, &c->cache_hash[DM_BUFIO_HASH(block)],
+ hash_list) {
+ dm_bufio_cond_resched();
+ if (b->block == block)
+ return b;
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------
+ * Getting a buffer
+ *--------------------------------------------------------------*/
+
+enum new_flag {
+ NF_FRESH = 0,
+ NF_READ = 1,
+ NF_GET = 2
+};
+
+static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block,
+ enum new_flag nf, struct dm_buffer **bp,
+ int *need_submit)
+{
+ struct dm_buffer *b, *new_b = NULL;
+
+ *need_submit = 0;
+
+ b = __find(c, block);
+ if (b) {
+ b->hold_count++;
+ __relink_lru(b, test_bit(B_DIRTY, &b->state) ||
+ test_bit(B_WRITING, &b->state));
+ return b;
+ }
+
+ if (nf == NF_GET)
+ return NULL;
+
+ new_b = __alloc_buffer_wait(c);
+
+ /*
+ * We've had a period where the mutex was unlocked, so need to
+ * recheck the hash table.
+ */
+ b = __find(c, block);
+ if (b) {
+ __free_buffer_wake(new_b);
+ b->hold_count++;
+ __relink_lru(b, test_bit(B_DIRTY, &b->state) ||
+ test_bit(B_WRITING, &b->state));
+ return b;
+ }
+
+ __check_watermark(c);
+
+ b = new_b;
+ b->hold_count = 1;
+ b->read_error = 0;
+ b->write_error = 0;
+ __link_buffer(b, block, LIST_CLEAN);
+
+ if (nf == NF_FRESH) {
+ b->state = 0;
+ return b;
+ }
+
+ b->state = 1 << B_READING;
+ *need_submit = 1;
+
+ return b;
+}
+
+/*
+ * The endio routine for reading: set the error, clear the bit and wake up
+ * anyone waiting on the buffer.
+ */
+static void read_endio(struct bio *bio, int error)
+{
+ struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
+
+ b->read_error = error;
+
+ BUG_ON(!test_bit(B_READING, &b->state));
+
+ smp_mb__before_clear_bit();
+ clear_bit(B_READING, &b->state);
+ smp_mb__after_clear_bit();
+
+ wake_up_bit(&b->state, B_READING);
+}
+
+/*
+ * A common routine for dm_bufio_new and dm_bufio_read. Operation of these
+ * functions is similar except that dm_bufio_new doesn't read the
+ * buffer from the disk (assuming that the caller overwrites all the data
+ * and uses dm_bufio_mark_buffer_dirty to write new data back).
+ */
+static void *new_read(struct dm_bufio_client *c, sector_t block,
+ enum new_flag nf, struct dm_buffer **bp)
+{
+ int need_submit;
+ struct dm_buffer *b;
+
+ dm_bufio_lock(c);
+ b = __bufio_new(c, block, nf, bp, &need_submit);
+ dm_bufio_unlock(c);
+
+ if (!b || IS_ERR(b))
+ return b;
+
+ if (need_submit)
+ submit_io(b, READ, b->block, read_endio);
+
+ wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+
+ if (b->read_error) {
+ int error = b->read_error;
+
+ dm_bufio_release(b);
+
+ return ERR_PTR(error);
+ }
+
+ *bp = b;
+
+ return b->data;
+}
+
+void *dm_bufio_get(struct dm_bufio_client *c, sector_t block,
+ struct dm_buffer **bp)
+{
+ return new_read(c, block, NF_GET, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get);
+
+void *dm_bufio_read(struct dm_bufio_client *c, sector_t block,
+ struct dm_buffer **bp)
+{
+ BUG_ON(dm_bufio_in_request());
+
+ return new_read(c, block, NF_READ, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_read);
+
+void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
+ struct dm_buffer **bp)
+{
+ BUG_ON(dm_bufio_in_request());
+
+ return new_read(c, block, NF_FRESH, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_new);
+
+void dm_bufio_release(struct dm_buffer *b)
+{
+ struct dm_bufio_client *c = b->c;
+
+ dm_bufio_lock(c);
+
+ BUG_ON(test_bit(B_READING, &b->state));
+ BUG_ON(!b->hold_count);
+
+ b->hold_count--;
+ if (!b->hold_count) {
+ wake_up(&c->free_buffer_wait);
+
+ /*
+ * If there were errors on the buffer, and the buffer is not
+ * to be written, free the buffer. There is no point in caching
+ * invalid buffer.
+ */
+ if ((b->read_error || b->write_error) &&
+ !test_bit(B_WRITING, &b->state) &&
+ !test_bit(B_DIRTY, &b->state)) {
+ __unlink_buffer(b);
+ __free_buffer_wake(b);
+ }
+ }
+
+ dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_release);
+
+void dm_bufio_mark_buffer_dirty(struct dm_buffer *b)
+{
+ struct dm_bufio_client *c = b->c;
+
+ dm_bufio_lock(c);
+
+ if (!test_and_set_bit(B_DIRTY, &b->state))
+ __relink_lru(b, LIST_DIRTY);
+
+ dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_mark_buffer_dirty);
+
+void dm_bufio_write_dirty_buffers_async(struct dm_bufio_client *c)
+{
+ BUG_ON(dm_bufio_in_request());
+
+ dm_bufio_lock(c);
+ __write_dirty_buffers_async(c, 0);
+ dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers_async);
+
+/*
+ * For performance, it is essential that the buffers are written asynchronously
+ * and simultaneously (so that the block layer can merge the writes) and then
+ * waited upon.
+ *
+ * Finally, we flush hardware disk cache.
+ */
+int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c)
+{
+ int a, f;
+ unsigned long buffers_processed = 0;
+ struct dm_buffer *b, *tmp;
+
+ dm_bufio_lock(c);
+ __write_dirty_buffers_async(c, 0);
+
+again:
+ list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_DIRTY], lru_list) {
+ int dropped_lock = 0;
+
+ if (buffers_processed < c->n_buffers[LIST_DIRTY])
+ buffers_processed++;
+
+ BUG_ON(test_bit(B_READING, &b->state));
+
+ if (test_bit(B_WRITING, &b->state)) {
+ if (buffers_processed < c->n_buffers[LIST_DIRTY]) {
+ dropped_lock = 1;
+ b->hold_count++;
+ dm_bufio_unlock(c);
+ wait_on_bit(&b->state, B_WRITING,
+ do_io_schedule,
+ TASK_UNINTERRUPTIBLE);
+ dm_bufio_lock(c);
+ b->hold_count--;
+ } else
+ wait_on_bit(&b->state, B_WRITING,
+ do_io_schedule,
+ TASK_UNINTERRUPTIBLE);
+ }
+
+ if (!test_bit(B_DIRTY, &b->state) &&
+ !test_bit(B_WRITING, &b->state))
+ __relink_lru(b, LIST_CLEAN);
+
+ dm_bufio_cond_resched();
+
+ /*
+ * If we dropped the lock, the list is no longer consistent,
+ * so we must restart the search.
+ *
+ * In the most common case, the buffer just processed is
+ * relinked to the clean list, so we won't loop scanning the
+ * same buffer again and again.
+ *
+ * This may livelock if there is another thread simultaneously
+ * dirtying buffers, so we count the number of buffers walked
+ * and if it exceeds the total number of buffers, it means that
+ * someone is doing some writes simultaneously with us. In
+ * this case, stop, dropping the lock.
+ */
+ if (dropped_lock)
+ goto again;
+ }
+ wake_up(&c->free_buffer_wait);
+ dm_bufio_unlock(c);
+
+ a = xchg(&c->async_write_error, 0);
+ f = dm_bufio_issue_flush(c);
+ if (a)
+ return a;
+
+ return f;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers);
+
+/*
+ * Use dm-io to send and empty barrier flush the device.
+ */
+int dm_bufio_issue_flush(struct dm_bufio_client *c)
+{
+ struct dm_io_request io_req = {
+ .bi_rw = REQ_FLUSH,
+ .mem.type = DM_IO_KMEM,
+ .mem.ptr.addr = NULL,
+ .client = c->dm_io,
+ };
+ struct dm_io_region io_reg = {
+ .bdev = c->bdev,
+ .sector = 0,
+ .count = 0,
+ };
+
+ BUG_ON(dm_bufio_in_request());
+
+ return dm_io(&io_req, 1, &io_reg, NULL);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_issue_flush);
+
+/*
+ * We first delete any other buffer that may be at that new location.
+ *
+ * Then, we write the buffer to the original location if it was dirty.
+ *
+ * Then, if we are the only one who is holding the buffer, relink the buffer
+ * in the hash queue for the new location.
+ *
+ * If there was someone else holding the buffer, we write it to the new
+ * location but not relink it, because that other user needs to have the buffer
+ * at the same place.
+ */
+void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block)
+{
+ struct dm_bufio_client *c = b->c;
+ struct dm_buffer *new;
+
+ BUG_ON(dm_bufio_in_request());
+
+ dm_bufio_lock(c);
+
+retry:
+ new = __find(c, new_block);
+ if (new) {
+ if (new->hold_count) {
+ __wait_for_free_buffer(c);
+ goto retry;
+ }
+
+ /*
+ * FIXME: Is there any point waiting for a write that's going
+ * to be overwritten in a bit?
+ */
+ __make_buffer_clean(new);
+ __unlink_buffer(new);
+ __free_buffer_wake(new);
+ }
+
+ BUG_ON(!b->hold_count);
+ BUG_ON(test_bit(B_READING, &b->state));
+
+ __write_dirty_buffer(b);
+ if (b->hold_count == 1) {
+ wait_on_bit(&b->state, B_WRITING,
+ do_io_schedule, TASK_UNINTERRUPTIBLE);
+ set_bit(B_DIRTY, &b->state);
+ __unlink_buffer(b);
+ __link_buffer(b, new_block, LIST_DIRTY);
+ } else {
+ sector_t old_block;
+ wait_on_bit_lock(&b->state, B_WRITING,
+ do_io_schedule, TASK_UNINTERRUPTIBLE);
+ /*
+ * Relink buffer to "new_block" so that write_callback
+ * sees "new_block" as a block number.
+ * After the write, link the buffer back to old_block.
+ * All this must be done in bufio lock, so that block number
+ * change isn't visible to other threads.
+ */
+ old_block = b->block;
+ __unlink_buffer(b);
+ __link_buffer(b, new_block, b->list_mode);
+ submit_io(b, WRITE, new_block, write_endio);
+ wait_on_bit(&b->state, B_WRITING,
+ do_io_schedule, TASK_UNINTERRUPTIBLE);
+ __unlink_buffer(b);
+ __link_buffer(b, old_block, b->list_mode);
+ }
+
+ dm_bufio_unlock(c);
+ dm_bufio_release(b);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_release_move);
+
+unsigned dm_bufio_get_block_size(struct dm_bufio_client *c)
+{
+ return c->block_size;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_size);
+
+sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
+{
+ return i_size_read(c->bdev->bd_inode) >>
+ (SECTOR_SHIFT + c->sectors_per_block_bits);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_device_size);
+
+sector_t dm_bufio_get_block_number(struct dm_buffer *b)
+{
+ return b->block;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_number);
+
+void *dm_bufio_get_block_data(struct dm_buffer *b)
+{
+ return b->data;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_data);
+
+void *dm_bufio_get_aux_data(struct dm_buffer *b)
+{
+ return b + 1;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_aux_data);
+
+struct dm_bufio_client *dm_bufio_get_client(struct dm_buffer *b)
+{
+ return b->c;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_client);
+
+static void drop_buffers(struct dm_bufio_client *c)
+{
+ struct dm_buffer *b;
+ int i;
+
+ BUG_ON(dm_bufio_in_request());
+
+ /*
+ * An optimization so that the buffers are not written one-by-one.
+ */
+ dm_bufio_write_dirty_buffers_async(c);
+
+ dm_bufio_lock(c);
+
+ while ((b = __get_unclaimed_buffer(c)))
+ __free_buffer_wake(b);
+
+ for (i = 0; i < LIST_SIZE; i++)
+ list_for_each_entry(b, &c->lru[i], lru_list)
+ DMERR("leaked buffer %llx, hold count %u, list %d",
+ (unsigned long long)b->block, b->hold_count, i);
+
+ for (i = 0; i < LIST_SIZE; i++)
+ BUG_ON(!list_empty(&c->lru[i]));
+
+ dm_bufio_unlock(c);
+}
+
+/*
+ * Test if the buffer is unused and too old, and commit it.
+ * At if noio is set, we must not do any I/O because we hold
+ * dm_bufio_clients_lock and we would risk deadlock if the I/O gets rerouted to
+ * different bufio client.
+ */
+static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp,
+ unsigned long max_jiffies)
+{
+ if (jiffies - b->last_accessed < max_jiffies)
+ return 1;
+
+ if (!(gfp & __GFP_IO)) {
+ if (test_bit(B_READING, &b->state) ||
+ test_bit(B_WRITING, &b->state) ||
+ test_bit(B_DIRTY, &b->state))
+ return 1;
+ }
+
+ if (b->hold_count)
+ return 1;
+
+ __make_buffer_clean(b);
+ __unlink_buffer(b);
+ __free_buffer_wake(b);
+
+ return 0;
+}
+
+static void __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
+ struct shrink_control *sc)
+{
+ int l;
+ struct dm_buffer *b, *tmp;
+
+ for (l = 0; l < LIST_SIZE; l++) {
+ list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list)
+ if (!__cleanup_old_buffer(b, sc->gfp_mask, 0) &&
+ !--nr_to_scan)
+ return;
+ dm_bufio_cond_resched();
+ }
+}
+
+static int shrink(struct shrinker *shrinker, struct shrink_control *sc)
+{
+ struct dm_bufio_client *c =
+ container_of(shrinker, struct dm_bufio_client, shrinker);
+ unsigned long r;
+ unsigned long nr_to_scan = sc->nr_to_scan;
+
+ if (sc->gfp_mask & __GFP_IO)
+ dm_bufio_lock(c);
+ else if (!dm_bufio_trylock(c))
+ return !nr_to_scan ? 0 : -1;
+
+ if (nr_to_scan)
+ __scan(c, nr_to_scan, sc);
+
+ r = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
+ if (r > INT_MAX)
+ r = INT_MAX;
+
+ dm_bufio_unlock(c);
+
+ return r;
+}
+
+/*
+ * Create the buffering interface
+ */
+struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
+ unsigned reserved_buffers, unsigned aux_size,
+ void (*alloc_callback)(struct dm_buffer *),
+ void (*write_callback)(struct dm_buffer *))
+{
+ int r;
+ struct dm_bufio_client *c;
+ unsigned i;
+
+ BUG_ON(block_size < 1 << SECTOR_SHIFT ||
+ (block_size & (block_size - 1)));
+
+ c = kmalloc(sizeof(*c), GFP_KERNEL);
+ if (!c) {
+ r = -ENOMEM;
+ goto bad_client;
+ }
+ c->cache_hash = vmalloc(sizeof(struct hlist_head) << DM_BUFIO_HASH_BITS);
+ if (!c->cache_hash) {
+ r = -ENOMEM;
+ goto bad_hash;
+ }
+
+ c->bdev = bdev;
+ c->block_size = block_size;
+ c->sectors_per_block_bits = ffs(block_size) - 1 - SECTOR_SHIFT;
+ c->pages_per_block_bits = (ffs(block_size) - 1 >= PAGE_SHIFT) ?
+ ffs(block_size) - 1 - PAGE_SHIFT : 0;
+ c->blocks_per_page_bits = (ffs(block_size) - 1 < PAGE_SHIFT ?
+ PAGE_SHIFT - (ffs(block_size) - 1) : 0);
+
+ c->aux_size = aux_size;
+ c->alloc_callback = alloc_callback;
+ c->write_callback = write_callback;
+
+ for (i = 0; i < LIST_SIZE; i++) {
+ INIT_LIST_HEAD(&c->lru[i]);
+ c->n_buffers[i] = 0;
+ }
+
+ for (i = 0; i < 1 << DM_BUFIO_HASH_BITS; i++)
+ INIT_HLIST_HEAD(&c->cache_hash[i]);
+
+ mutex_init(&c->lock);
+ INIT_LIST_HEAD(&c->reserved_buffers);
+ c->need_reserved_buffers = reserved_buffers;
+
+ init_waitqueue_head(&c->free_buffer_wait);
+ c->async_write_error = 0;
+
+ c->dm_io = dm_io_client_create();
+ if (IS_ERR(c->dm_io)) {
+ r = PTR_ERR(c->dm_io);
+ goto bad_dm_io;
+ }
+
+ mutex_lock(&dm_bufio_clients_lock);
+ if (c->blocks_per_page_bits) {
+ if (!DM_BUFIO_CACHE_NAME(c)) {
+ DM_BUFIO_CACHE_NAME(c) = kasprintf(GFP_KERNEL, "dm_bufio_cache-%u", c->block_size);
+ if (!DM_BUFIO_CACHE_NAME(c)) {
+ r = -ENOMEM;
+ mutex_unlock(&dm_bufio_clients_lock);
+ goto bad_cache;
+ }
+ }
+
+ if (!DM_BUFIO_CACHE(c)) {
+ DM_BUFIO_CACHE(c) = kmem_cache_create(DM_BUFIO_CACHE_NAME(c),
+ c->block_size,
+ c->block_size, 0, NULL);
+ if (!DM_BUFIO_CACHE(c)) {
+ r = -ENOMEM;
+ mutex_unlock(&dm_bufio_clients_lock);
+ goto bad_cache;
+ }
+ }
+ }
+ mutex_unlock(&dm_bufio_clients_lock);
+
+ while (c->need_reserved_buffers) {
+ struct dm_buffer *b = alloc_buffer(c, GFP_KERNEL);
+
+ if (!b) {
+ r = -ENOMEM;
+ goto bad_buffer;
+ }
+ __free_buffer_wake(b);
+ }
+
+ mutex_lock(&dm_bufio_clients_lock);
+ dm_bufio_client_count++;
+ list_add(&c->client_list, &dm_bufio_all_clients);
+ __cache_size_refresh();
+ mutex_unlock(&dm_bufio_clients_lock);
+
+ c->shrinker.shrink = shrink;
+ c->shrinker.seeks = 1;
+ c->shrinker.batch = 0;
+ register_shrinker(&c->shrinker);
+
+ return c;
+
+bad_buffer:
+bad_cache:
+ while (!list_empty(&c->reserved_buffers)) {
+ struct dm_buffer *b = list_entry(c->reserved_buffers.next,
+ struct dm_buffer, lru_list);
+ list_del(&b->lru_list);
+ free_buffer(b);
+ }
+ dm_io_client_destroy(c->dm_io);
+bad_dm_io:
+ vfree(c->cache_hash);
+bad_hash:
+ kfree(c);
+bad_client:
+ return ERR_PTR(r);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_client_create);
+
+/*
+ * Free the buffering interface.
+ * It is required that there are no references on any buffers.
+ */
+void dm_bufio_client_destroy(struct dm_bufio_client *c)
+{
+ unsigned i;
+
+ drop_buffers(c);
+
+ unregister_shrinker(&c->shrinker);
+
+ mutex_lock(&dm_bufio_clients_lock);
+
+ list_del(&c->client_list);
+ dm_bufio_client_count--;
+ __cache_size_refresh();
+
+ mutex_unlock(&dm_bufio_clients_lock);
+
+ for (i = 0; i < 1 << DM_BUFIO_HASH_BITS; i++)
+ BUG_ON(!hlist_empty(&c->cache_hash[i]));
+
+ BUG_ON(c->need_reserved_buffers);
+
+ while (!list_empty(&c->reserved_buffers)) {
+ struct dm_buffer *b = list_entry(c->reserved_buffers.next,
+ struct dm_buffer, lru_list);
+ list_del(&b->lru_list);
+ free_buffer(b);
+ }
+
+ for (i = 0; i < LIST_SIZE; i++)
+ if (c->n_buffers[i])
+ DMERR("leaked buffer count %d: %ld", i, c->n_buffers[i]);
+
+ for (i = 0; i < LIST_SIZE; i++)
+ BUG_ON(c->n_buffers[i]);
+
+ dm_io_client_destroy(c->dm_io);
+ vfree(c->cache_hash);
+ kfree(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_client_destroy);
+
+static void cleanup_old_buffers(void)
+{
+ unsigned long max_age = dm_bufio_max_age;
+ struct dm_bufio_client *c;
+
+ barrier();
+
+ if (max_age > ULONG_MAX / HZ)
+ max_age = ULONG_MAX / HZ;
+
+ mutex_lock(&dm_bufio_clients_lock);
+ list_for_each_entry(c, &dm_bufio_all_clients, client_list) {
+ if (!dm_bufio_trylock(c))
+ continue;
+
+ while (!list_empty(&c->lru[LIST_CLEAN])) {
+ struct dm_buffer *b;
+ b = list_entry(c->lru[LIST_CLEAN].prev,
+ struct dm_buffer, lru_list);
+ if (__cleanup_old_buffer(b, 0, max_age * HZ))
+ break;
+ dm_bufio_cond_resched();
+ }
+
+ dm_bufio_unlock(c);
+ dm_bufio_cond_resched();
+ }
+ mutex_unlock(&dm_bufio_clients_lock);
+}
+
+static struct workqueue_struct *dm_bufio_wq;
+static struct delayed_work dm_bufio_work;
+
+static void work_fn(struct work_struct *w)
+{
+ cleanup_old_buffers();
+
+ queue_delayed_work(dm_bufio_wq, &dm_bufio_work,
+ DM_BUFIO_WORK_TIMER_SECS * HZ);
+}
+
+/*----------------------------------------------------------------
+ * Module setup
+ *--------------------------------------------------------------*/
+
+/*
+ * This is called only once for the whole dm_bufio module.
+ * It initializes memory limit.
+ */
+static int __init dm_bufio_init(void)
+{
+ __u64 mem;
+
+ memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches);
+ memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names);
+
+ mem = (__u64)((totalram_pages - totalhigh_pages) *
+ DM_BUFIO_MEMORY_PERCENT / 100) << PAGE_SHIFT;
+
+ if (mem > ULONG_MAX)
+ mem = ULONG_MAX;
+
+#ifdef CONFIG_MMU
+ /*
+ * Get the size of vmalloc space the same way as VMALLOC_TOTAL
+ * in fs/proc/internal.h
+ */
+ if (mem > (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100)
+ mem = (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100;
+#endif
+
+ dm_bufio_default_cache_size = mem;
+
+ mutex_lock(&dm_bufio_clients_lock);
+ __cache_size_refresh();
+ mutex_unlock(&dm_bufio_clients_lock);
+
+ dm_bufio_wq = create_singlethread_workqueue("dm_bufio_cache");
+ if (!dm_bufio_wq)
+ return -ENOMEM;
+
+ INIT_DELAYED_WORK(&dm_bufio_work, work_fn);
+ queue_delayed_work(dm_bufio_wq, &dm_bufio_work,
+ DM_BUFIO_WORK_TIMER_SECS * HZ);
+
+ return 0;
+}
+
+/*
+ * This is called once when unloading the dm_bufio module.
+ */
+static void __exit dm_bufio_exit(void)
+{
+ int bug = 0;
+ int i;
+
+ cancel_delayed_work_sync(&dm_bufio_work);
+ destroy_workqueue(dm_bufio_wq);
+
+ for (i = 0; i < ARRAY_SIZE(dm_bufio_caches); i++) {
+ struct kmem_cache *kc = dm_bufio_caches[i];
+
+ if (kc)
+ kmem_cache_destroy(kc);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(dm_bufio_cache_names); i++)
+ kfree(dm_bufio_cache_names[i]);
+
+ if (dm_bufio_client_count) {
+ DMCRIT("%s: dm_bufio_client_count leaked: %d",
+ __func__, dm_bufio_client_count);
+ bug = 1;
+ }
+
+ if (dm_bufio_current_allocated) {
+ DMCRIT("%s: dm_bufio_current_allocated leaked: %lu",
+ __func__, dm_bufio_current_allocated);
+ bug = 1;
+ }
+
+ if (dm_bufio_allocated_get_free_pages) {
+ DMCRIT("%s: dm_bufio_allocated_get_free_pages leaked: %lu",
+ __func__, dm_bufio_allocated_get_free_pages);
+ bug = 1;
+ }
+
+ if (dm_bufio_allocated_vmalloc) {
+ DMCRIT("%s: dm_bufio_vmalloc leaked: %lu",
+ __func__, dm_bufio_allocated_vmalloc);
+ bug = 1;
+ }
+
+ if (bug)
+ BUG();
+}
+
+module_init(dm_bufio_init)
+module_exit(dm_bufio_exit)
+
+module_param_named(max_cache_size_bytes, dm_bufio_cache_size, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache");
+
+module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds");
+
+module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(peak_allocated_bytes, "Tracks the maximum allocated memory");
+
+module_param_named(allocated_kmem_cache_bytes, dm_bufio_allocated_kmem_cache, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_kmem_cache_bytes, "Memory allocated with kmem_cache_alloc");
+
+module_param_named(allocated_get_free_pages_bytes, dm_bufio_allocated_get_free_pages, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_get_free_pages_bytes, "Memory allocated with get_free_pages");
+
+module_param_named(allocated_vmalloc_bytes, dm_bufio_allocated_vmalloc, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_vmalloc_bytes, "Memory allocated with vmalloc");
+
+module_param_named(current_allocated_bytes, dm_bufio_current_allocated, ulong, S_IRUGO);
+MODULE_PARM_DESC(current_allocated_bytes, "Memory currently used by the cache");
+
+MODULE_AUTHOR("Mikulas Patocka <dm-devel@redhat.com>");
+MODULE_DESCRIPTION(DM_NAME " buffered I/O library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm-bufio.h b/drivers/md/dm-bufio.h
new file mode 100644
index 000000000000..5c4c3a04e381
--- /dev/null
+++ b/drivers/md/dm-bufio.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009-2011 Red Hat, Inc.
+ *
+ * Author: Mikulas Patocka <mpatocka@redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BUFIO_H
+#define DM_BUFIO_H
+
+#include <linux/blkdev.h>
+#include <linux/types.h>
+
+/*----------------------------------------------------------------*/
+
+struct dm_bufio_client;
+struct dm_buffer;
+
+/*
+ * Create a buffered IO cache on a given device
+ */
+struct dm_bufio_client *
+dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
+ unsigned reserved_buffers, unsigned aux_size,
+ void (*alloc_callback)(struct dm_buffer *),
+ void (*write_callback)(struct dm_buffer *));
+
+/*
+ * Release a buffered IO cache.
+ */
+void dm_bufio_client_destroy(struct dm_bufio_client *c);
+
+/*
+ * WARNING: to avoid deadlocks, these conditions are observed:
+ *
+ * - At most one thread can hold at most "reserved_buffers" simultaneously.
+ * - Each other threads can hold at most one buffer.
+ * - Threads which call only dm_bufio_get can hold unlimited number of
+ * buffers.
+ */
+
+/*
+ * Read a given block from disk. Returns pointer to data. Returns a
+ * pointer to dm_buffer that can be used to release the buffer or to make
+ * it dirty.
+ */
+void *dm_bufio_read(struct dm_bufio_client *c, sector_t block,
+ struct dm_buffer **bp);
+
+/*
+ * Like dm_bufio_read, but return buffer from cache, don't read
+ * it. If the buffer is not in the cache, return NULL.
+ */
+void *dm_bufio_get(struct dm_bufio_client *c, sector_t block,
+ struct dm_buffer **bp);
+
+/*
+ * Like dm_bufio_read, but don't read anything from the disk. It is
+ * expected that the caller initializes the buffer and marks it dirty.
+ */
+void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
+ struct dm_buffer **bp);
+
+/*
+ * Release a reference obtained with dm_bufio_{read,get,new}. The data
+ * pointer and dm_buffer pointer is no longer valid after this call.
+ */
+void dm_bufio_release(struct dm_buffer *b);
+
+/*
+ * Mark a buffer dirty. It should be called after the buffer is modified.
+ *
+ * In case of memory pressure, the buffer may be written after
+ * dm_bufio_mark_buffer_dirty, but before dm_bufio_write_dirty_buffers. So
+ * dm_bufio_write_dirty_buffers guarantees that the buffer is on-disk but
+ * the actual writing may occur earlier.
+ */
+void dm_bufio_mark_buffer_dirty(struct dm_buffer *b);
+
+/*
+ * Initiate writing of dirty buffers, without waiting for completion.
+ */
+void dm_bufio_write_dirty_buffers_async(struct dm_bufio_client *c);
+
+/*
+ * Write all dirty buffers. Guarantees that all dirty buffers created prior
+ * to this call are on disk when this call exits.
+ */
+int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c);
+
+/*
+ * Send an empty write barrier to the device to flush hardware disk cache.
+ */
+int dm_bufio_issue_flush(struct dm_bufio_client *c);
+
+/*
+ * Like dm_bufio_release but also move the buffer to the new
+ * block. dm_bufio_write_dirty_buffers is needed to commit the new block.
+ */
+void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block);
+
+unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
+sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
+sector_t dm_bufio_get_block_number(struct dm_buffer *b);
+void *dm_bufio_get_block_data(struct dm_buffer *b);
+void *dm_bufio_get_aux_data(struct dm_buffer *b);
+struct dm_bufio_client *dm_bufio_get_client(struct dm_buffer *b);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 2e9a3ca37bdd..31c2dc25886d 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1215,6 +1215,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
struct hash_cell *hc;
struct dm_table *t;
struct mapped_device *md;
+ struct target_type *immutable_target_type;
md = find_device(param);
if (!md)
@@ -1230,6 +1231,16 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
goto out;
}
+ immutable_target_type = dm_get_immutable_target_type(md);
+ if (immutable_target_type &&
+ (immutable_target_type != dm_table_get_immutable_target_type(t))) {
+ DMWARN("can't replace immutable target type %s",
+ immutable_target_type->name);
+ dm_table_destroy(t);
+ r = -EINVAL;
+ goto out;
+ }
+
/* Protect md->type and md->queue against concurrent table loads. */
dm_lock_md_type(md);
if (dm_get_md_type(md) == DM_TYPE_NONE)
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index 32ac70861d66..bed444c93d8d 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -66,6 +66,8 @@ struct dm_kcopyd_client {
struct list_head pages_jobs;
};
+static struct page_list zero_page_list;
+
static void wake(struct dm_kcopyd_client *kc)
{
queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
@@ -254,6 +256,9 @@ int __init dm_kcopyd_init(void)
if (!_job_cache)
return -ENOMEM;
+ zero_page_list.next = &zero_page_list;
+ zero_page_list.page = ZERO_PAGE(0);
+
return 0;
}
@@ -322,7 +327,7 @@ static int run_complete_job(struct kcopyd_job *job)
dm_kcopyd_notify_fn fn = job->fn;
struct dm_kcopyd_client *kc = job->kc;
- if (job->pages)
+ if (job->pages && job->pages != &zero_page_list)
kcopyd_put_pages(kc, job->pages);
/*
* If this is the master job, the sub jobs have already
@@ -484,6 +489,8 @@ static void dispatch_job(struct kcopyd_job *job)
atomic_inc(&kc->nr_jobs);
if (unlikely(!job->source.count))
push(&kc->complete_jobs, job);
+ else if (job->pages == &zero_page_list)
+ push(&kc->io_jobs, job);
else
push(&kc->pages_jobs, job);
wake(kc);
@@ -592,14 +599,20 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
job->flags = flags;
job->read_err = 0;
job->write_err = 0;
- job->rw = READ;
-
- job->source = *from;
job->num_dests = num_dests;
memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
- job->pages = NULL;
+ if (from) {
+ job->source = *from;
+ job->pages = NULL;
+ job->rw = READ;
+ } else {
+ memset(&job->source, 0, sizeof job->source);
+ job->source.count = job->dests[0].count;
+ job->pages = &zero_page_list;
+ job->rw = WRITE;
+ }
job->fn = fn;
job->context = context;
@@ -617,6 +630,14 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
}
EXPORT_SYMBOL(dm_kcopyd_copy);
+int dm_kcopyd_zero(struct dm_kcopyd_client *kc,
+ unsigned num_dests, struct dm_io_region *dests,
+ unsigned flags, dm_kcopyd_notify_fn fn, void *context)
+{
+ return dm_kcopyd_copy(kc, NULL, num_dests, dests, flags, fn, context);
+}
+EXPORT_SYMBOL(dm_kcopyd_zero);
+
void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
dm_kcopyd_notify_fn fn, void *context)
{
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c
index 1021c8986011..8db3862dade5 100644
--- a/drivers/md/dm-log-userspace-base.c
+++ b/drivers/md/dm-log-userspace-base.c
@@ -30,6 +30,7 @@ struct flush_entry {
struct log_c {
struct dm_target *ti;
+ struct dm_dev *log_dev;
uint32_t region_size;
region_t region_count;
uint64_t luid;
@@ -146,7 +147,7 @@ static int build_constructor_string(struct dm_target *ti,
* <UUID> <other args>
* Where 'other args' is the userspace implementation specific log
* arguments. An example might be:
- * <UUID> clustered_disk <arg count> <log dev> <region_size> [[no]sync]
+ * <UUID> clustered-disk <arg count> <log dev> <region_size> [[no]sync]
*
* So, this module will strip off the <UUID> for identification purposes
* when communicating with userspace about a log; but will pass on everything
@@ -161,13 +162,15 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
struct log_c *lc = NULL;
uint64_t rdata;
size_t rdata_size = sizeof(rdata);
+ char *devices_rdata = NULL;
+ size_t devices_rdata_size = DM_NAME_LEN;
if (argc < 3) {
DMWARN("Too few arguments to userspace dirty log");
return -EINVAL;
}
- lc = kmalloc(sizeof(*lc), GFP_KERNEL);
+ lc = kzalloc(sizeof(*lc), GFP_KERNEL);
if (!lc) {
DMWARN("Unable to allocate userspace log context.");
return -ENOMEM;
@@ -195,9 +198,19 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
return str_size;
}
- /* Send table string */
+ devices_rdata = kzalloc(devices_rdata_size, GFP_KERNEL);
+ if (!devices_rdata) {
+ DMERR("Failed to allocate memory for device information");
+ r = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * Send table string and get back any opened device.
+ */
r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
- ctr_str, str_size, NULL, NULL);
+ ctr_str, str_size,
+ devices_rdata, &devices_rdata_size);
if (r < 0) {
if (r == -ESRCH)
@@ -220,7 +233,20 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
lc->region_size = (uint32_t)rdata;
lc->region_count = dm_sector_div_up(ti->len, lc->region_size);
+ if (devices_rdata_size) {
+ if (devices_rdata[devices_rdata_size - 1] != '\0') {
+ DMERR("DM_ULOG_CTR device return string not properly terminated");
+ r = -EINVAL;
+ goto out;
+ }
+ r = dm_get_device(ti, devices_rdata,
+ dm_table_get_mode(ti->table), &lc->log_dev);
+ if (r)
+ DMERR("Failed to register %s with device-mapper",
+ devices_rdata);
+ }
out:
+ kfree(devices_rdata);
if (r) {
kfree(lc);
kfree(ctr_str);
@@ -241,6 +267,9 @@ static void userspace_dtr(struct dm_dirty_log *log)
NULL, 0,
NULL, NULL);
+ if (lc->log_dev)
+ dm_put_device(lc->ti, lc->log_dev);
+
kfree(lc->usr_argv_str);
kfree(lc);
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 86df8b2cf927..11fa96df4b06 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -37,7 +37,7 @@ struct raid_dev {
*/
struct dm_dev *meta_dev;
struct dm_dev *data_dev;
- struct mdk_rdev_s rdev;
+ struct md_rdev rdev;
};
/*
@@ -57,7 +57,7 @@ struct raid_set {
uint64_t print_flags;
- struct mddev_s md;
+ struct mddev md;
struct raid_type *raid_type;
struct dm_target_callbacks callbacks;
@@ -594,7 +594,7 @@ struct dm_raid_superblock {
/* Always set to 0 when writing. */
} __packed;
-static int read_disk_sb(mdk_rdev_t *rdev, int size)
+static int read_disk_sb(struct md_rdev *rdev, int size)
{
BUG_ON(!rdev->sb_page);
@@ -611,9 +611,9 @@ static int read_disk_sb(mdk_rdev_t *rdev, int size)
return 0;
}
-static void super_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
{
- mdk_rdev_t *r, *t;
+ struct md_rdev *r, *t;
uint64_t failed_devices;
struct dm_raid_superblock *sb;
@@ -651,7 +651,7 @@ static void super_sync(mddev_t *mddev, mdk_rdev_t *rdev)
*
* Return: 1 if use rdev, 0 if use refdev, -Exxx otherwise
*/
-static int super_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev)
+static int super_load(struct md_rdev *rdev, struct md_rdev *refdev)
{
int ret;
struct dm_raid_superblock *sb;
@@ -689,7 +689,7 @@ static int super_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev)
return (events_sb > events_refsb) ? 1 : 0;
}
-static int super_init_validation(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_init_validation(struct mddev *mddev, struct md_rdev *rdev)
{
int role;
struct raid_set *rs = container_of(mddev, struct raid_set, md);
@@ -698,7 +698,7 @@ static int super_init_validation(mddev_t *mddev, mdk_rdev_t *rdev)
struct dm_raid_superblock *sb;
uint32_t new_devs = 0;
uint32_t rebuilds = 0;
- mdk_rdev_t *r, *t;
+ struct md_rdev *r, *t;
struct dm_raid_superblock *sb2;
sb = page_address(rdev->sb_page);
@@ -809,7 +809,7 @@ static int super_init_validation(mddev_t *mddev, mdk_rdev_t *rdev)
return 0;
}
-static int super_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_validate(struct mddev *mddev, struct md_rdev *rdev)
{
struct dm_raid_superblock *sb = page_address(rdev->sb_page);
@@ -849,8 +849,8 @@ static int super_validate(mddev_t *mddev, mdk_rdev_t *rdev)
static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
{
int ret;
- mdk_rdev_t *rdev, *freshest, *tmp;
- mddev_t *mddev = &rs->md;
+ struct md_rdev *rdev, *freshest, *tmp;
+ struct mddev *mddev = &rs->md;
freshest = NULL;
rdev_for_each(rdev, tmp, mddev) {
@@ -1004,7 +1004,7 @@ static void raid_dtr(struct dm_target *ti)
static int raid_map(struct dm_target *ti, struct bio *bio, union map_info *map_context)
{
struct raid_set *rs = ti->private;
- mddev_t *mddev = &rs->md;
+ struct mddev *mddev = &rs->md;
mddev->pers->make_request(mddev, bio);
@@ -1017,30 +1017,56 @@ static int raid_status(struct dm_target *ti, status_type_t type,
struct raid_set *rs = ti->private;
unsigned raid_param_cnt = 1; /* at least 1 for chunksize */
unsigned sz = 0;
- int i;
+ int i, array_in_sync = 0;
sector_t sync;
switch (type) {
case STATUSTYPE_INFO:
DMEMIT("%s %d ", rs->raid_type->name, rs->md.raid_disks);
- for (i = 0; i < rs->md.raid_disks; i++) {
- if (test_bit(Faulty, &rs->dev[i].rdev.flags))
- DMEMIT("D");
- else if (test_bit(In_sync, &rs->dev[i].rdev.flags))
- DMEMIT("A");
- else
- DMEMIT("a");
- }
-
if (test_bit(MD_RECOVERY_RUNNING, &rs->md.recovery))
sync = rs->md.curr_resync_completed;
else
sync = rs->md.recovery_cp;
- if (sync > rs->md.resync_max_sectors)
+ if (sync >= rs->md.resync_max_sectors) {
+ array_in_sync = 1;
sync = rs->md.resync_max_sectors;
+ } else {
+ /*
+ * The array may be doing an initial sync, or it may
+ * be rebuilding individual components. If all the
+ * devices are In_sync, then it is the array that is
+ * being initialized.
+ */
+ for (i = 0; i < rs->md.raid_disks; i++)
+ if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
+ array_in_sync = 1;
+ }
+ /*
+ * Status characters:
+ * 'D' = Dead/Failed device
+ * 'a' = Alive but not in-sync
+ * 'A' = Alive and in-sync
+ */
+ for (i = 0; i < rs->md.raid_disks; i++) {
+ if (test_bit(Faulty, &rs->dev[i].rdev.flags))
+ DMEMIT("D");
+ else if (!array_in_sync ||
+ !test_bit(In_sync, &rs->dev[i].rdev.flags))
+ DMEMIT("a");
+ else
+ DMEMIT("A");
+ }
+ /*
+ * In-sync ratio:
+ * The in-sync ratio shows the progress of:
+ * - Initializing the array
+ * - Rebuilding a subset of devices of the array
+ * The user can distinguish between the two by referring
+ * to the status characters.
+ */
DMEMIT(" %llu/%llu",
(unsigned long long) sync,
(unsigned long long) rs->md.resync_max_sectors);
@@ -1097,7 +1123,7 @@ static int raid_status(struct dm_target *ti, status_type_t type,
rs->md.bitmap_info.max_write_behind);
if (rs->print_flags & DMPF_STRIPE_CACHE) {
- raid5_conf_t *conf = rs->md.private;
+ struct r5conf *conf = rs->md.private;
/* convert from kiB to sectors */
DMEMIT(" stripe_cache %d",
@@ -1146,7 +1172,7 @@ static void raid_io_hints(struct dm_target *ti, struct queue_limits *limits)
{
struct raid_set *rs = ti->private;
unsigned chunk_size = rs->md.chunk_sectors << 9;
- raid5_conf_t *conf = rs->md.private;
+ struct r5conf *conf = rs->md.private;
blk_limits_io_min(limits, chunk_size);
blk_limits_io_opt(limits, chunk_size * (conf->raid_disks - conf->max_degraded));
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index bc04518e9d8b..8e9132130142 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -54,7 +54,9 @@ struct dm_table {
sector_t *highs;
struct dm_target *targets;
+ struct target_type *immutable_target_type;
unsigned integrity_supported:1;
+ unsigned singleton:1;
/*
* Indicates the rw permissions for the new logical
@@ -740,6 +742,12 @@ int dm_table_add_target(struct dm_table *t, const char *type,
char **argv;
struct dm_target *tgt;
+ if (t->singleton) {
+ DMERR("%s: target type %s must appear alone in table",
+ dm_device_name(t->md), t->targets->type->name);
+ return -EINVAL;
+ }
+
if ((r = check_space(t)))
return r;
@@ -758,6 +766,36 @@ int dm_table_add_target(struct dm_table *t, const char *type,
return -EINVAL;
}
+ if (dm_target_needs_singleton(tgt->type)) {
+ if (t->num_targets) {
+ DMERR("%s: target type %s must appear alone in table",
+ dm_device_name(t->md), type);
+ return -EINVAL;
+ }
+ t->singleton = 1;
+ }
+
+ if (dm_target_always_writeable(tgt->type) && !(t->mode & FMODE_WRITE)) {
+ DMERR("%s: target type %s may not be included in read-only tables",
+ dm_device_name(t->md), type);
+ return -EINVAL;
+ }
+
+ if (t->immutable_target_type) {
+ if (t->immutable_target_type != tgt->type) {
+ DMERR("%s: immutable target type %s cannot be mixed with other target types",
+ dm_device_name(t->md), t->immutable_target_type->name);
+ return -EINVAL;
+ }
+ } else if (dm_target_is_immutable(tgt->type)) {
+ if (t->num_targets) {
+ DMERR("%s: immutable target type %s cannot be mixed with other target types",
+ dm_device_name(t->md), tgt->type->name);
+ return -EINVAL;
+ }
+ t->immutable_target_type = tgt->type;
+ }
+
tgt->table = t;
tgt->begin = start;
tgt->len = len;
@@ -915,6 +953,11 @@ unsigned dm_table_get_type(struct dm_table *t)
return t->type;
}
+struct target_type *dm_table_get_immutable_target_type(struct dm_table *t)
+{
+ return t->immutable_target_type;
+}
+
bool dm_table_request_based(struct dm_table *t)
{
return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED;
@@ -1299,6 +1342,31 @@ static bool dm_table_discard_zeroes_data(struct dm_table *t)
return 1;
}
+static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ struct request_queue *q = bdev_get_queue(dev->bdev);
+
+ return q && blk_queue_nonrot(q);
+}
+
+static bool dm_table_is_nonrot(struct dm_table *t)
+{
+ struct dm_target *ti;
+ unsigned i = 0;
+
+ /* Ensure that all underlying device are non-rotational. */
+ while (i < dm_table_get_num_targets(t)) {
+ ti = dm_table_get_target(t, i++);
+
+ if (!ti->type->iterate_devices ||
+ !ti->type->iterate_devices(ti, device_is_nonrot, NULL))
+ return 0;
+ }
+
+ return 1;
+}
+
void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
struct queue_limits *limits)
{
@@ -1324,6 +1392,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
if (!dm_table_discard_zeroes_data(t))
q->limits.discard_zeroes_data = 0;
+ if (dm_table_is_nonrot(t))
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
+ else
+ queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
+
dm_table_set_integrity(t);
/*
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
new file mode 100644
index 000000000000..59c4f0446ffa
--- /dev/null
+++ b/drivers/md/dm-thin-metadata.c
@@ -0,0 +1,1391 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-thin-metadata.h"
+#include "persistent-data/dm-btree.h"
+#include "persistent-data/dm-space-map.h"
+#include "persistent-data/dm-space-map-disk.h"
+#include "persistent-data/dm-transaction-manager.h"
+
+#include <linux/list.h>
+#include <linux/device-mapper.h>
+#include <linux/workqueue.h>
+
+/*--------------------------------------------------------------------------
+ * As far as the metadata goes, there is:
+ *
+ * - A superblock in block zero, taking up fewer than 512 bytes for
+ * atomic writes.
+ *
+ * - A space map managing the metadata blocks.
+ *
+ * - A space map managing the data blocks.
+ *
+ * - A btree mapping our internal thin dev ids onto struct disk_device_details.
+ *
+ * - A hierarchical btree, with 2 levels which effectively maps (thin
+ * dev id, virtual block) -> block_time. Block time is a 64-bit
+ * field holding the time in the low 24 bits, and block in the top 48
+ * bits.
+ *
+ * BTrees consist solely of btree_nodes, that fill a block. Some are
+ * internal nodes, as such their values are a __le64 pointing to other
+ * nodes. Leaf nodes can store data of any reasonable size (ie. much
+ * smaller than the block size). The nodes consist of the header,
+ * followed by an array of keys, followed by an array of values. We have
+ * to binary search on the keys so they're all held together to help the
+ * cpu cache.
+ *
+ * Space maps have 2 btrees:
+ *
+ * - One maps a uint64_t onto a struct index_entry. Which points to a
+ * bitmap block, and has some details about how many free entries there
+ * are etc.
+ *
+ * - The bitmap blocks have a header (for the checksum). Then the rest
+ * of the block is pairs of bits. With the meaning being:
+ *
+ * 0 - ref count is 0
+ * 1 - ref count is 1
+ * 2 - ref count is 2
+ * 3 - ref count is higher than 2
+ *
+ * - If the count is higher than 2 then the ref count is entered in a
+ * second btree that directly maps the block_address to a uint32_t ref
+ * count.
+ *
+ * The space map metadata variant doesn't have a bitmaps btree. Instead
+ * it has one single blocks worth of index_entries. This avoids
+ * recursive issues with the bitmap btree needing to allocate space in
+ * order to insert. With a small data block size such as 64k the
+ * metadata support data devices that are hundreds of terrabytes.
+ *
+ * The space maps allocate space linearly from front to back. Space that
+ * is freed in a transaction is never recycled within that transaction.
+ * To try and avoid fragmenting _free_ space the allocator always goes
+ * back and fills in gaps.
+ *
+ * All metadata io is in THIN_METADATA_BLOCK_SIZE sized/aligned chunks
+ * from the block manager.
+ *--------------------------------------------------------------------------*/
+
+#define DM_MSG_PREFIX "thin metadata"
+
+#define THIN_SUPERBLOCK_MAGIC 27022010
+#define THIN_SUPERBLOCK_LOCATION 0
+#define THIN_VERSION 1
+#define THIN_METADATA_CACHE_SIZE 64
+#define SECTOR_TO_BLOCK_SHIFT 3
+
+/* This should be plenty */
+#define SPACE_MAP_ROOT_SIZE 128
+
+/*
+ * Little endian on-disk superblock and device details.
+ */
+struct thin_disk_superblock {
+ __le32 csum; /* Checksum of superblock except for this field. */
+ __le32 flags;
+ __le64 blocknr; /* This block number, dm_block_t. */
+
+ __u8 uuid[16];
+ __le64 magic;
+ __le32 version;
+ __le32 time;
+
+ __le64 trans_id;
+
+ /*
+ * Root held by userspace transactions.
+ */
+ __le64 held_root;
+
+ __u8 data_space_map_root[SPACE_MAP_ROOT_SIZE];
+ __u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
+
+ /*
+ * 2-level btree mapping (dev_id, (dev block, time)) -> data block
+ */
+ __le64 data_mapping_root;
+
+ /*
+ * Device detail root mapping dev_id -> device_details
+ */
+ __le64 device_details_root;
+
+ __le32 data_block_size; /* In 512-byte sectors. */
+
+ __le32 metadata_block_size; /* In 512-byte sectors. */
+ __le64 metadata_nr_blocks;
+
+ __le32 compat_flags;
+ __le32 compat_ro_flags;
+ __le32 incompat_flags;
+} __packed;
+
+struct disk_device_details {
+ __le64 mapped_blocks;
+ __le64 transaction_id; /* When created. */
+ __le32 creation_time;
+ __le32 snapshotted_time;
+} __packed;
+
+struct dm_pool_metadata {
+ struct hlist_node hash;
+
+ struct block_device *bdev;
+ struct dm_block_manager *bm;
+ struct dm_space_map *metadata_sm;
+ struct dm_space_map *data_sm;
+ struct dm_transaction_manager *tm;
+ struct dm_transaction_manager *nb_tm;
+
+ /*
+ * Two-level btree.
+ * First level holds thin_dev_t.
+ * Second level holds mappings.
+ */
+ struct dm_btree_info info;
+
+ /*
+ * Non-blocking version of the above.
+ */
+ struct dm_btree_info nb_info;
+
+ /*
+ * Just the top level for deleting whole devices.
+ */
+ struct dm_btree_info tl_info;
+
+ /*
+ * Just the bottom level for creating new devices.
+ */
+ struct dm_btree_info bl_info;
+
+ /*
+ * Describes the device details btree.
+ */
+ struct dm_btree_info details_info;
+
+ struct rw_semaphore root_lock;
+ uint32_t time;
+ int need_commit;
+ dm_block_t root;
+ dm_block_t details_root;
+ struct list_head thin_devices;
+ uint64_t trans_id;
+ unsigned long flags;
+ sector_t data_block_size;
+};
+
+struct dm_thin_device {
+ struct list_head list;
+ struct dm_pool_metadata *pmd;
+ dm_thin_id id;
+
+ int open_count;
+ int changed;
+ uint64_t mapped_blocks;
+ uint64_t transaction_id;
+ uint32_t creation_time;
+ uint32_t snapshotted_time;
+};
+
+/*----------------------------------------------------------------
+ * superblock validator
+ *--------------------------------------------------------------*/
+
+#define SUPERBLOCK_CSUM_XOR 160774
+
+static void sb_prepare_for_write(struct dm_block_validator *v,
+ struct dm_block *b,
+ size_t block_size)
+{
+ struct thin_disk_superblock *disk_super = dm_block_data(b);
+
+ disk_super->blocknr = cpu_to_le64(dm_block_location(b));
+ disk_super->csum = cpu_to_le32(dm_bm_checksum(&disk_super->flags,
+ block_size - sizeof(__le32),
+ SUPERBLOCK_CSUM_XOR));
+}
+
+static int sb_check(struct dm_block_validator *v,
+ struct dm_block *b,
+ size_t block_size)
+{
+ struct thin_disk_superblock *disk_super = dm_block_data(b);
+ __le32 csum_le;
+
+ if (dm_block_location(b) != le64_to_cpu(disk_super->blocknr)) {
+ DMERR("sb_check failed: blocknr %llu: "
+ "wanted %llu", le64_to_cpu(disk_super->blocknr),
+ (unsigned long long)dm_block_location(b));
+ return -ENOTBLK;
+ }
+
+ if (le64_to_cpu(disk_super->magic) != THIN_SUPERBLOCK_MAGIC) {
+ DMERR("sb_check failed: magic %llu: "
+ "wanted %llu", le64_to_cpu(disk_super->magic),
+ (unsigned long long)THIN_SUPERBLOCK_MAGIC);
+ return -EILSEQ;
+ }
+
+ csum_le = cpu_to_le32(dm_bm_checksum(&disk_super->flags,
+ block_size - sizeof(__le32),
+ SUPERBLOCK_CSUM_XOR));
+ if (csum_le != disk_super->csum) {
+ DMERR("sb_check failed: csum %u: wanted %u",
+ le32_to_cpu(csum_le), le32_to_cpu(disk_super->csum));
+ return -EILSEQ;
+ }
+
+ return 0;
+}
+
+static struct dm_block_validator sb_validator = {
+ .name = "superblock",
+ .prepare_for_write = sb_prepare_for_write,
+ .check = sb_check
+};
+
+/*----------------------------------------------------------------
+ * Methods for the btree value types
+ *--------------------------------------------------------------*/
+
+static uint64_t pack_block_time(dm_block_t b, uint32_t t)
+{
+ return (b << 24) | t;
+}
+
+static void unpack_block_time(uint64_t v, dm_block_t *b, uint32_t *t)
+{
+ *b = v >> 24;
+ *t = v & ((1 << 24) - 1);
+}
+
+static void data_block_inc(void *context, void *value_le)
+{
+ struct dm_space_map *sm = context;
+ __le64 v_le;
+ uint64_t b;
+ uint32_t t;
+
+ memcpy(&v_le, value_le, sizeof(v_le));
+ unpack_block_time(le64_to_cpu(v_le), &b, &t);
+ dm_sm_inc_block(sm, b);
+}
+
+static void data_block_dec(void *context, void *value_le)
+{
+ struct dm_space_map *sm = context;
+ __le64 v_le;
+ uint64_t b;
+ uint32_t t;
+
+ memcpy(&v_le, value_le, sizeof(v_le));
+ unpack_block_time(le64_to_cpu(v_le), &b, &t);
+ dm_sm_dec_block(sm, b);
+}
+
+static int data_block_equal(void *context, void *value1_le, void *value2_le)
+{
+ __le64 v1_le, v2_le;
+ uint64_t b1, b2;
+ uint32_t t;
+
+ memcpy(&v1_le, value1_le, sizeof(v1_le));
+ memcpy(&v2_le, value2_le, sizeof(v2_le));
+ unpack_block_time(le64_to_cpu(v1_le), &b1, &t);
+ unpack_block_time(le64_to_cpu(v2_le), &b2, &t);
+
+ return b1 == b2;
+}
+
+static void subtree_inc(void *context, void *value)
+{
+ struct dm_btree_info *info = context;
+ __le64 root_le;
+ uint64_t root;
+
+ memcpy(&root_le, value, sizeof(root_le));
+ root = le64_to_cpu(root_le);
+ dm_tm_inc(info->tm, root);
+}
+
+static void subtree_dec(void *context, void *value)
+{
+ struct dm_btree_info *info = context;
+ __le64 root_le;
+ uint64_t root;
+
+ memcpy(&root_le, value, sizeof(root_le));
+ root = le64_to_cpu(root_le);
+ if (dm_btree_del(info, root))
+ DMERR("btree delete failed\n");
+}
+
+static int subtree_equal(void *context, void *value1_le, void *value2_le)
+{
+ __le64 v1_le, v2_le;
+ memcpy(&v1_le, value1_le, sizeof(v1_le));
+ memcpy(&v2_le, value2_le, sizeof(v2_le));
+
+ return v1_le == v2_le;
+}
+
+/*----------------------------------------------------------------*/
+
+static int superblock_all_zeroes(struct dm_block_manager *bm, int *result)
+{
+ int r;
+ unsigned i;
+ struct dm_block *b;
+ __le64 *data_le, zero = cpu_to_le64(0);
+ unsigned block_size = dm_bm_block_size(bm) / sizeof(__le64);
+
+ /*
+ * We can't use a validator here - it may be all zeroes.
+ */
+ r = dm_bm_read_lock(bm, THIN_SUPERBLOCK_LOCATION, NULL, &b);
+ if (r)
+ return r;
+
+ data_le = dm_block_data(b);
+ *result = 1;
+ for (i = 0; i < block_size; i++) {
+ if (data_le[i] != zero) {
+ *result = 0;
+ break;
+ }
+ }
+
+ return dm_bm_unlock(b);
+}
+
+static int init_pmd(struct dm_pool_metadata *pmd,
+ struct dm_block_manager *bm,
+ dm_block_t nr_blocks, int create)
+{
+ int r;
+ struct dm_space_map *sm, *data_sm;
+ struct dm_transaction_manager *tm;
+ struct dm_block *sblock;
+
+ if (create) {
+ r = dm_tm_create_with_sm(bm, THIN_SUPERBLOCK_LOCATION,
+ &sb_validator, &tm, &sm, &sblock);
+ if (r < 0) {
+ DMERR("tm_create_with_sm failed");
+ return r;
+ }
+
+ data_sm = dm_sm_disk_create(tm, nr_blocks);
+ if (IS_ERR(data_sm)) {
+ DMERR("sm_disk_create failed");
+ r = PTR_ERR(data_sm);
+ goto bad;
+ }
+ } else {
+ struct thin_disk_superblock *disk_super = NULL;
+ size_t space_map_root_offset =
+ offsetof(struct thin_disk_superblock, metadata_space_map_root);
+
+ r = dm_tm_open_with_sm(bm, THIN_SUPERBLOCK_LOCATION,
+ &sb_validator, space_map_root_offset,
+ SPACE_MAP_ROOT_SIZE, &tm, &sm, &sblock);
+ if (r < 0) {
+ DMERR("tm_open_with_sm failed");
+ return r;
+ }
+
+ disk_super = dm_block_data(sblock);
+ data_sm = dm_sm_disk_open(tm, disk_super->data_space_map_root,
+ sizeof(disk_super->data_space_map_root));
+ if (IS_ERR(data_sm)) {
+ DMERR("sm_disk_open failed");
+ r = PTR_ERR(data_sm);
+ goto bad;
+ }
+ }
+
+
+ r = dm_tm_unlock(tm, sblock);
+ if (r < 0) {
+ DMERR("couldn't unlock superblock");
+ goto bad_data_sm;
+ }
+
+ pmd->bm = bm;
+ pmd->metadata_sm = sm;
+ pmd->data_sm = data_sm;
+ pmd->tm = tm;
+ pmd->nb_tm = dm_tm_create_non_blocking_clone(tm);
+ if (!pmd->nb_tm) {
+ DMERR("could not create clone tm");
+ r = -ENOMEM;
+ goto bad_data_sm;
+ }
+
+ pmd->info.tm = tm;
+ pmd->info.levels = 2;
+ pmd->info.value_type.context = pmd->data_sm;
+ pmd->info.value_type.size = sizeof(__le64);
+ pmd->info.value_type.inc = data_block_inc;
+ pmd->info.value_type.dec = data_block_dec;
+ pmd->info.value_type.equal = data_block_equal;
+
+ memcpy(&pmd->nb_info, &pmd->info, sizeof(pmd->nb_info));
+ pmd->nb_info.tm = pmd->nb_tm;
+
+ pmd->tl_info.tm = tm;
+ pmd->tl_info.levels = 1;
+ pmd->tl_info.value_type.context = &pmd->info;
+ pmd->tl_info.value_type.size = sizeof(__le64);
+ pmd->tl_info.value_type.inc = subtree_inc;
+ pmd->tl_info.value_type.dec = subtree_dec;
+ pmd->tl_info.value_type.equal = subtree_equal;
+
+ pmd->bl_info.tm = tm;
+ pmd->bl_info.levels = 1;
+ pmd->bl_info.value_type.context = pmd->data_sm;
+ pmd->bl_info.value_type.size = sizeof(__le64);
+ pmd->bl_info.value_type.inc = data_block_inc;
+ pmd->bl_info.value_type.dec = data_block_dec;
+ pmd->bl_info.value_type.equal = data_block_equal;
+
+ pmd->details_info.tm = tm;
+ pmd->details_info.levels = 1;
+ pmd->details_info.value_type.context = NULL;
+ pmd->details_info.value_type.size = sizeof(struct disk_device_details);
+ pmd->details_info.value_type.inc = NULL;
+ pmd->details_info.value_type.dec = NULL;
+ pmd->details_info.value_type.equal = NULL;
+
+ pmd->root = 0;
+
+ init_rwsem(&pmd->root_lock);
+ pmd->time = 0;
+ pmd->need_commit = 0;
+ pmd->details_root = 0;
+ pmd->trans_id = 0;
+ pmd->flags = 0;
+ INIT_LIST_HEAD(&pmd->thin_devices);
+
+ return 0;
+
+bad_data_sm:
+ dm_sm_destroy(data_sm);
+bad:
+ dm_tm_destroy(tm);
+ dm_sm_destroy(sm);
+
+ return r;
+}
+
+static int __begin_transaction(struct dm_pool_metadata *pmd)
+{
+ int r;
+ u32 features;
+ struct thin_disk_superblock *disk_super;
+ struct dm_block *sblock;
+
+ /*
+ * __maybe_commit_transaction() resets these
+ */
+ WARN_ON(pmd->need_commit);
+
+ /*
+ * We re-read the superblock every time. Shouldn't need to do this
+ * really.
+ */
+ r = dm_bm_read_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+ &sb_validator, &sblock);
+ if (r)
+ return r;
+
+ disk_super = dm_block_data(sblock);
+ pmd->time = le32_to_cpu(disk_super->time);
+ pmd->root = le64_to_cpu(disk_super->data_mapping_root);
+ pmd->details_root = le64_to_cpu(disk_super->device_details_root);
+ pmd->trans_id = le64_to_cpu(disk_super->trans_id);
+ pmd->flags = le32_to_cpu(disk_super->flags);
+ pmd->data_block_size = le32_to_cpu(disk_super->data_block_size);
+
+ features = le32_to_cpu(disk_super->incompat_flags) & ~THIN_FEATURE_INCOMPAT_SUPP;
+ if (features) {
+ DMERR("could not access metadata due to "
+ "unsupported optional features (%lx).",
+ (unsigned long)features);
+ r = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * Check for read-only metadata to skip the following RDWR checks.
+ */
+ if (get_disk_ro(pmd->bdev->bd_disk))
+ goto out;
+
+ features = le32_to_cpu(disk_super->compat_ro_flags) & ~THIN_FEATURE_COMPAT_RO_SUPP;
+ if (features) {
+ DMERR("could not access metadata RDWR due to "
+ "unsupported optional features (%lx).",
+ (unsigned long)features);
+ r = -EINVAL;
+ }
+
+out:
+ dm_bm_unlock(sblock);
+ return r;
+}
+
+static int __write_changed_details(struct dm_pool_metadata *pmd)
+{
+ int r;
+ struct dm_thin_device *td, *tmp;
+ struct disk_device_details details;
+ uint64_t key;
+
+ list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+ if (!td->changed)
+ continue;
+
+ key = td->id;
+
+ details.mapped_blocks = cpu_to_le64(td->mapped_blocks);
+ details.transaction_id = cpu_to_le64(td->transaction_id);
+ details.creation_time = cpu_to_le32(td->creation_time);
+ details.snapshotted_time = cpu_to_le32(td->snapshotted_time);
+ __dm_bless_for_disk(&details);
+
+ r = dm_btree_insert(&pmd->details_info, pmd->details_root,
+ &key, &details, &pmd->details_root);
+ if (r)
+ return r;
+
+ if (td->open_count)
+ td->changed = 0;
+ else {
+ list_del(&td->list);
+ kfree(td);
+ }
+
+ pmd->need_commit = 1;
+ }
+
+ return 0;
+}
+
+static int __commit_transaction(struct dm_pool_metadata *pmd)
+{
+ /*
+ * FIXME: Associated pool should be made read-only on failure.
+ */
+ int r;
+ size_t metadata_len, data_len;
+ struct thin_disk_superblock *disk_super;
+ struct dm_block *sblock;
+
+ /*
+ * We need to know if the thin_disk_superblock exceeds a 512-byte sector.
+ */
+ BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
+
+ r = __write_changed_details(pmd);
+ if (r < 0)
+ goto out;
+
+ if (!pmd->need_commit)
+ goto out;
+
+ r = dm_sm_commit(pmd->data_sm);
+ if (r < 0)
+ goto out;
+
+ r = dm_tm_pre_commit(pmd->tm);
+ if (r < 0)
+ goto out;
+
+ r = dm_sm_root_size(pmd->metadata_sm, &metadata_len);
+ if (r < 0)
+ goto out;
+
+ r = dm_sm_root_size(pmd->metadata_sm, &data_len);
+ if (r < 0)
+ goto out;
+
+ r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+ &sb_validator, &sblock);
+ if (r)
+ goto out;
+
+ disk_super = dm_block_data(sblock);
+ disk_super->time = cpu_to_le32(pmd->time);
+ disk_super->data_mapping_root = cpu_to_le64(pmd->root);
+ disk_super->device_details_root = cpu_to_le64(pmd->details_root);
+ disk_super->trans_id = cpu_to_le64(pmd->trans_id);
+ disk_super->flags = cpu_to_le32(pmd->flags);
+
+ r = dm_sm_copy_root(pmd->metadata_sm, &disk_super->metadata_space_map_root,
+ metadata_len);
+ if (r < 0)
+ goto out_locked;
+
+ r = dm_sm_copy_root(pmd->data_sm, &disk_super->data_space_map_root,
+ data_len);
+ if (r < 0)
+ goto out_locked;
+
+ r = dm_tm_commit(pmd->tm, sblock);
+ if (!r)
+ pmd->need_commit = 0;
+
+out:
+ return r;
+
+out_locked:
+ dm_bm_unlock(sblock);
+ return r;
+}
+
+struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
+ sector_t data_block_size)
+{
+ int r;
+ struct thin_disk_superblock *disk_super;
+ struct dm_pool_metadata *pmd;
+ sector_t bdev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+ struct dm_block_manager *bm;
+ int create;
+ struct dm_block *sblock;
+
+ pmd = kmalloc(sizeof(*pmd), GFP_KERNEL);
+ if (!pmd) {
+ DMERR("could not allocate metadata struct");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /*
+ * Max hex locks:
+ * 3 for btree insert +
+ * 2 for btree lookup used within space map
+ */
+ bm = dm_block_manager_create(bdev, THIN_METADATA_BLOCK_SIZE,
+ THIN_METADATA_CACHE_SIZE, 5);
+ if (!bm) {
+ DMERR("could not create block manager");
+ kfree(pmd);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ r = superblock_all_zeroes(bm, &create);
+ if (r) {
+ dm_block_manager_destroy(bm);
+ kfree(pmd);
+ return ERR_PTR(r);
+ }
+
+
+ r = init_pmd(pmd, bm, 0, create);
+ if (r) {
+ dm_block_manager_destroy(bm);
+ kfree(pmd);
+ return ERR_PTR(r);
+ }
+ pmd->bdev = bdev;
+
+ if (!create) {
+ r = __begin_transaction(pmd);
+ if (r < 0)
+ goto bad;
+ return pmd;
+ }
+
+ /*
+ * Create.
+ */
+ r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+ &sb_validator, &sblock);
+ if (r)
+ goto bad;
+
+ disk_super = dm_block_data(sblock);
+ disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC);
+ disk_super->version = cpu_to_le32(THIN_VERSION);
+ disk_super->time = 0;
+ disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+ disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT);
+ disk_super->data_block_size = cpu_to_le32(data_block_size);
+
+ r = dm_bm_unlock(sblock);
+ if (r < 0)
+ goto bad;
+
+ r = dm_btree_empty(&pmd->info, &pmd->root);
+ if (r < 0)
+ goto bad;
+
+ r = dm_btree_empty(&pmd->details_info, &pmd->details_root);
+ if (r < 0) {
+ DMERR("couldn't create devices root");
+ goto bad;
+ }
+
+ pmd->flags = 0;
+ pmd->need_commit = 1;
+ r = dm_pool_commit_metadata(pmd);
+ if (r < 0) {
+ DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+ __func__, r);
+ goto bad;
+ }
+
+ return pmd;
+
+bad:
+ if (dm_pool_metadata_close(pmd) < 0)
+ DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+ return ERR_PTR(r);
+}
+
+int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
+{
+ int r;
+ unsigned open_devices = 0;
+ struct dm_thin_device *td, *tmp;
+
+ down_read(&pmd->root_lock);
+ list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+ if (td->open_count)
+ open_devices++;
+ else {
+ list_del(&td->list);
+ kfree(td);
+ }
+ }
+ up_read(&pmd->root_lock);
+
+ if (open_devices) {
+ DMERR("attempt to close pmd when %u device(s) are still open",
+ open_devices);
+ return -EBUSY;
+ }
+
+ r = __commit_transaction(pmd);
+ if (r < 0)
+ DMWARN("%s: __commit_transaction() failed, error = %d",
+ __func__, r);
+
+ dm_tm_destroy(pmd->tm);
+ dm_tm_destroy(pmd->nb_tm);
+ dm_block_manager_destroy(pmd->bm);
+ dm_sm_destroy(pmd->metadata_sm);
+ dm_sm_destroy(pmd->data_sm);
+ kfree(pmd);
+
+ return 0;
+}
+
+static int __open_device(struct dm_pool_metadata *pmd,
+ dm_thin_id dev, int create,
+ struct dm_thin_device **td)
+{
+ int r, changed = 0;
+ struct dm_thin_device *td2;
+ uint64_t key = dev;
+ struct disk_device_details details_le;
+
+ /*
+ * Check the device isn't already open.
+ */
+ list_for_each_entry(td2, &pmd->thin_devices, list)
+ if (td2->id == dev) {
+ td2->open_count++;
+ *td = td2;
+ return 0;
+ }
+
+ /*
+ * Check the device exists.
+ */
+ r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+ &key, &details_le);
+ if (r) {
+ if (r != -ENODATA || !create)
+ return r;
+
+ changed = 1;
+ details_le.mapped_blocks = 0;
+ details_le.transaction_id = cpu_to_le64(pmd->trans_id);
+ details_le.creation_time = cpu_to_le32(pmd->time);
+ details_le.snapshotted_time = cpu_to_le32(pmd->time);
+ }
+
+ *td = kmalloc(sizeof(**td), GFP_NOIO);
+ if (!*td)
+ return -ENOMEM;
+
+ (*td)->pmd = pmd;
+ (*td)->id = dev;
+ (*td)->open_count = 1;
+ (*td)->changed = changed;
+ (*td)->mapped_blocks = le64_to_cpu(details_le.mapped_blocks);
+ (*td)->transaction_id = le64_to_cpu(details_le.transaction_id);
+ (*td)->creation_time = le32_to_cpu(details_le.creation_time);
+ (*td)->snapshotted_time = le32_to_cpu(details_le.snapshotted_time);
+
+ list_add(&(*td)->list, &pmd->thin_devices);
+
+ return 0;
+}
+
+static void __close_device(struct dm_thin_device *td)
+{
+ --td->open_count;
+}
+
+static int __create_thin(struct dm_pool_metadata *pmd,
+ dm_thin_id dev)
+{
+ int r;
+ dm_block_t dev_root;
+ uint64_t key = dev;
+ struct disk_device_details details_le;
+ struct dm_thin_device *td;
+ __le64 value;
+
+ r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+ &key, &details_le);
+ if (!r)
+ return -EEXIST;
+
+ /*
+ * Create an empty btree for the mappings.
+ */
+ r = dm_btree_empty(&pmd->bl_info, &dev_root);
+ if (r)
+ return r;
+
+ /*
+ * Insert it into the main mapping tree.
+ */
+ value = cpu_to_le64(dev_root);
+ __dm_bless_for_disk(&value);
+ r = dm_btree_insert(&pmd->tl_info, pmd->root, &key, &value, &pmd->root);
+ if (r) {
+ dm_btree_del(&pmd->bl_info, dev_root);
+ return r;
+ }
+
+ r = __open_device(pmd, dev, 1, &td);
+ if (r) {
+ __close_device(td);
+ dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+ dm_btree_del(&pmd->bl_info, dev_root);
+ return r;
+ }
+ td->changed = 1;
+ __close_device(td);
+
+ return r;
+}
+
+int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev)
+{
+ int r;
+
+ down_write(&pmd->root_lock);
+ r = __create_thin(pmd, dev);
+ up_write(&pmd->root_lock);
+
+ return r;
+}
+
+static int __set_snapshot_details(struct dm_pool_metadata *pmd,
+ struct dm_thin_device *snap,
+ dm_thin_id origin, uint32_t time)
+{
+ int r;
+ struct dm_thin_device *td;
+
+ r = __open_device(pmd, origin, 0, &td);
+ if (r)
+ return r;
+
+ td->changed = 1;
+ td->snapshotted_time = time;
+
+ snap->mapped_blocks = td->mapped_blocks;
+ snap->snapshotted_time = time;
+ __close_device(td);
+
+ return 0;
+}
+
+static int __create_snap(struct dm_pool_metadata *pmd,
+ dm_thin_id dev, dm_thin_id origin)
+{
+ int r;
+ dm_block_t origin_root;
+ uint64_t key = origin, dev_key = dev;
+ struct dm_thin_device *td;
+ struct disk_device_details details_le;
+ __le64 value;
+
+ /* check this device is unused */
+ r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+ &dev_key, &details_le);
+ if (!r)
+ return -EEXIST;
+
+ /* find the mapping tree for the origin */
+ r = dm_btree_lookup(&pmd->tl_info, pmd->root, &key, &value);
+ if (r)
+ return r;
+ origin_root = le64_to_cpu(value);
+
+ /* clone the origin, an inc will do */
+ dm_tm_inc(pmd->tm, origin_root);
+
+ /* insert into the main mapping tree */
+ value = cpu_to_le64(origin_root);
+ __dm_bless_for_disk(&value);
+ key = dev;
+ r = dm_btree_insert(&pmd->tl_info, pmd->root, &key, &value, &pmd->root);
+ if (r) {
+ dm_tm_dec(pmd->tm, origin_root);
+ return r;
+ }
+
+ pmd->time++;
+
+ r = __open_device(pmd, dev, 1, &td);
+ if (r)
+ goto bad;
+
+ r = __set_snapshot_details(pmd, td, origin, pmd->time);
+ if (r)
+ goto bad;
+
+ __close_device(td);
+ return 0;
+
+bad:
+ __close_device(td);
+ dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+ dm_btree_remove(&pmd->details_info, pmd->details_root,
+ &key, &pmd->details_root);
+ return r;
+}
+
+int dm_pool_create_snap(struct dm_pool_metadata *pmd,
+ dm_thin_id dev,
+ dm_thin_id origin)
+{
+ int r;
+
+ down_write(&pmd->root_lock);
+ r = __create_snap(pmd, dev, origin);
+ up_write(&pmd->root_lock);
+
+ return r;
+}
+
+static int __delete_device(struct dm_pool_metadata *pmd, dm_thin_id dev)
+{
+ int r;
+ uint64_t key = dev;
+ struct dm_thin_device *td;
+
+ /* TODO: failure should mark the transaction invalid */
+ r = __open_device(pmd, dev, 0, &td);
+ if (r)
+ return r;
+
+ if (td->open_count > 1) {
+ __close_device(td);
+ return -EBUSY;
+ }
+
+ list_del(&td->list);
+ kfree(td);
+ r = dm_btree_remove(&pmd->details_info, pmd->details_root,
+ &key, &pmd->details_root);
+ if (r)
+ return r;
+
+ r = dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+ if (r)
+ return r;
+
+ pmd->need_commit = 1;
+
+ return 0;
+}
+
+int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
+ dm_thin_id dev)
+{
+ int r;
+
+ down_write(&pmd->root_lock);
+ r = __delete_device(pmd, dev);
+ up_write(&pmd->root_lock);
+
+ return r;
+}
+
+int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
+ uint64_t current_id,
+ uint64_t new_id)
+{
+ down_write(&pmd->root_lock);
+ if (pmd->trans_id != current_id) {
+ up_write(&pmd->root_lock);
+ DMERR("mismatched transaction id");
+ return -EINVAL;
+ }
+
+ pmd->trans_id = new_id;
+ pmd->need_commit = 1;
+ up_write(&pmd->root_lock);
+
+ return 0;
+}
+
+int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
+ uint64_t *result)
+{
+ down_read(&pmd->root_lock);
+ *result = pmd->trans_id;
+ up_read(&pmd->root_lock);
+
+ return 0;
+}
+
+static int __get_held_metadata_root(struct dm_pool_metadata *pmd,
+ dm_block_t *result)
+{
+ int r;
+ struct thin_disk_superblock *disk_super;
+ struct dm_block *sblock;
+
+ r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+ &sb_validator, &sblock);
+ if (r)
+ return r;
+
+ disk_super = dm_block_data(sblock);
+ *result = le64_to_cpu(disk_super->held_root);
+
+ return dm_bm_unlock(sblock);
+}
+
+int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd,
+ dm_block_t *result)
+{
+ int r;
+
+ down_read(&pmd->root_lock);
+ r = __get_held_metadata_root(pmd, result);
+ up_read(&pmd->root_lock);
+
+ return r;
+}
+
+int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev,
+ struct dm_thin_device **td)
+{
+ int r;
+
+ down_write(&pmd->root_lock);
+ r = __open_device(pmd, dev, 0, td);
+ up_write(&pmd->root_lock);
+
+ return r;
+}
+
+int dm_pool_close_thin_device(struct dm_thin_device *td)
+{
+ down_write(&td->pmd->root_lock);
+ __close_device(td);
+ up_write(&td->pmd->root_lock);
+
+ return 0;
+}
+
+dm_thin_id dm_thin_dev_id(struct dm_thin_device *td)
+{
+ return td->id;
+}
+
+static int __snapshotted_since(struct dm_thin_device *td, uint32_t time)
+{
+ return td->snapshotted_time > time;
+}
+
+int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
+ int can_block, struct dm_thin_lookup_result *result)
+{
+ int r;
+ uint64_t block_time = 0;
+ __le64 value;
+ struct dm_pool_metadata *pmd = td->pmd;
+ dm_block_t keys[2] = { td->id, block };
+
+ if (can_block) {
+ down_read(&pmd->root_lock);
+ r = dm_btree_lookup(&pmd->info, pmd->root, keys, &value);
+ if (!r)
+ block_time = le64_to_cpu(value);
+ up_read(&pmd->root_lock);
+
+ } else if (down_read_trylock(&pmd->root_lock)) {
+ r = dm_btree_lookup(&pmd->nb_info, pmd->root, keys, &value);
+ if (!r)
+ block_time = le64_to_cpu(value);
+ up_read(&pmd->root_lock);
+
+ } else
+ return -EWOULDBLOCK;
+
+ if (!r) {
+ dm_block_t exception_block;
+ uint32_t exception_time;
+ unpack_block_time(block_time, &exception_block,
+ &exception_time);
+ result->block = exception_block;
+ result->shared = __snapshotted_since(td, exception_time);
+ }
+
+ return r;
+}
+
+static int __insert(struct dm_thin_device *td, dm_block_t block,
+ dm_block_t data_block)
+{
+ int r, inserted;
+ __le64 value;
+ struct dm_pool_metadata *pmd = td->pmd;
+ dm_block_t keys[2] = { td->id, block };
+
+ pmd->need_commit = 1;
+ value = cpu_to_le64(pack_block_time(data_block, pmd->time));
+ __dm_bless_for_disk(&value);
+
+ r = dm_btree_insert_notify(&pmd->info, pmd->root, keys, &value,
+ &pmd->root, &inserted);
+ if (r)
+ return r;
+
+ if (inserted) {
+ td->mapped_blocks++;
+ td->changed = 1;
+ }
+
+ return 0;
+}
+
+int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
+ dm_block_t data_block)
+{
+ int r;
+
+ down_write(&td->pmd->root_lock);
+ r = __insert(td, block, data_block);
+ up_write(&td->pmd->root_lock);
+
+ return r;
+}
+
+static int __remove(struct dm_thin_device *td, dm_block_t block)
+{
+ int r;
+ struct dm_pool_metadata *pmd = td->pmd;
+ dm_block_t keys[2] = { td->id, block };
+
+ r = dm_btree_remove(&pmd->info, pmd->root, keys, &pmd->root);
+ if (r)
+ return r;
+
+ pmd->need_commit = 1;
+
+ return 0;
+}
+
+int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block)
+{
+ int r;
+
+ down_write(&td->pmd->root_lock);
+ r = __remove(td, block);
+ up_write(&td->pmd->root_lock);
+
+ return r;
+}
+
+int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+ int r;
+
+ down_write(&pmd->root_lock);
+
+ r = dm_sm_new_block(pmd->data_sm, result);
+ pmd->need_commit = 1;
+
+ up_write(&pmd->root_lock);
+
+ return r;
+}
+
+int dm_pool_commit_metadata(struct dm_pool_metadata *pmd)
+{
+ int r;
+
+ down_write(&pmd->root_lock);
+
+ r = __commit_transaction(pmd);
+ if (r <= 0)
+ goto out;
+
+ /*
+ * Open the next transaction.
+ */
+ r = __begin_transaction(pmd);
+out:
+ up_write(&pmd->root_lock);
+ return r;
+}
+
+int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+ int r;
+
+ down_read(&pmd->root_lock);
+ r = dm_sm_get_nr_free(pmd->data_sm, result);
+ up_read(&pmd->root_lock);
+
+ return r;
+}
+
+int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
+ dm_block_t *result)
+{
+ int r;
+
+ down_read(&pmd->root_lock);
+ r = dm_sm_get_nr_free(pmd->metadata_sm, result);
+ up_read(&pmd->root_lock);
+
+ return r;
+}
+
+int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
+ dm_block_t *result)
+{
+ int r;
+
+ down_read(&pmd->root_lock);
+ r = dm_sm_get_nr_blocks(pmd->metadata_sm, result);
+ up_read(&pmd->root_lock);
+
+ return r;
+}
+
+int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result)
+{
+ down_read(&pmd->root_lock);
+ *result = pmd->data_block_size;
+ up_read(&pmd->root_lock);
+
+ return 0;
+}
+
+int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+ int r;
+
+ down_read(&pmd->root_lock);
+ r = dm_sm_get_nr_blocks(pmd->data_sm, result);
+ up_read(&pmd->root_lock);
+
+ return r;
+}
+
+int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result)
+{
+ struct dm_pool_metadata *pmd = td->pmd;
+
+ down_read(&pmd->root_lock);
+ *result = td->mapped_blocks;
+ up_read(&pmd->root_lock);
+
+ return 0;
+}
+
+static int __highest_block(struct dm_thin_device *td, dm_block_t *result)
+{
+ int r;
+ __le64 value_le;
+ dm_block_t thin_root;
+ struct dm_pool_metadata *pmd = td->pmd;
+
+ r = dm_btree_lookup(&pmd->tl_info, pmd->root, &td->id, &value_le);
+ if (r)
+ return r;
+
+ thin_root = le64_to_cpu(value_le);
+
+ return dm_btree_find_highest_key(&pmd->bl_info, thin_root, result);
+}
+
+int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
+ dm_block_t *result)
+{
+ int r;
+ struct dm_pool_metadata *pmd = td->pmd;
+
+ down_read(&pmd->root_lock);
+ r = __highest_block(td, result);
+ up_read(&pmd->root_lock);
+
+ return r;
+}
+
+static int __resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
+{
+ int r;
+ dm_block_t old_count;
+
+ r = dm_sm_get_nr_blocks(pmd->data_sm, &old_count);
+ if (r)
+ return r;
+
+ if (new_count == old_count)
+ return 0;
+
+ if (new_count < old_count) {
+ DMERR("cannot reduce size of data device");
+ return -EINVAL;
+ }
+
+ r = dm_sm_extend(pmd->data_sm, new_count - old_count);
+ if (!r)
+ pmd->need_commit = 1;
+
+ return r;
+}
+
+int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
+{
+ int r;
+
+ down_write(&pmd->root_lock);
+ r = __resize_data_dev(pmd, new_count);
+ up_write(&pmd->root_lock);
+
+ return r;
+}
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
new file mode 100644
index 000000000000..859c16896877
--- /dev/null
+++ b/drivers/md/dm-thin-metadata.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_THIN_METADATA_H
+#define DM_THIN_METADATA_H
+
+#include "persistent-data/dm-block-manager.h"
+
+#define THIN_METADATA_BLOCK_SIZE 4096
+
+/*----------------------------------------------------------------*/
+
+struct dm_pool_metadata;
+struct dm_thin_device;
+
+/*
+ * Device identifier
+ */
+typedef uint64_t dm_thin_id;
+
+/*
+ * Reopens or creates a new, empty metadata volume.
+ */
+struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
+ sector_t data_block_size);
+
+int dm_pool_metadata_close(struct dm_pool_metadata *pmd);
+
+/*
+ * Compat feature flags. Any incompat flags beyond the ones
+ * specified below will prevent use of the thin metadata.
+ */
+#define THIN_FEATURE_COMPAT_SUPP 0UL
+#define THIN_FEATURE_COMPAT_RO_SUPP 0UL
+#define THIN_FEATURE_INCOMPAT_SUPP 0UL
+
+/*
+ * Device creation/deletion.
+ */
+int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev);
+
+/*
+ * An internal snapshot.
+ *
+ * You can only snapshot a quiesced origin i.e. one that is either
+ * suspended or not instanced at all.
+ */
+int dm_pool_create_snap(struct dm_pool_metadata *pmd, dm_thin_id dev,
+ dm_thin_id origin);
+
+/*
+ * Deletes a virtual device from the metadata. It _is_ safe to call this
+ * when that device is open. Operations on that device will just start
+ * failing. You still need to call close() on the device.
+ */
+int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
+ dm_thin_id dev);
+
+/*
+ * Commits _all_ metadata changes: device creation, deletion, mapping
+ * updates.
+ */
+int dm_pool_commit_metadata(struct dm_pool_metadata *pmd);
+
+/*
+ * Set/get userspace transaction id.
+ */
+int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
+ uint64_t current_id,
+ uint64_t new_id);
+
+int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
+ uint64_t *result);
+
+/*
+ * Hold/get root for userspace transaction.
+ */
+int dm_pool_hold_metadata_root(struct dm_pool_metadata *pmd);
+
+int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd,
+ dm_block_t *result);
+
+/*
+ * Actions on a single virtual device.
+ */
+
+/*
+ * Opening the same device more than once will fail with -EBUSY.
+ */
+int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev,
+ struct dm_thin_device **td);
+
+int dm_pool_close_thin_device(struct dm_thin_device *td);
+
+dm_thin_id dm_thin_dev_id(struct dm_thin_device *td);
+
+struct dm_thin_lookup_result {
+ dm_block_t block;
+ int shared;
+};
+
+/*
+ * Returns:
+ * -EWOULDBLOCK iff @can_block is set and would block.
+ * -ENODATA iff that mapping is not present.
+ * 0 success
+ */
+int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
+ int can_block, struct dm_thin_lookup_result *result);
+
+/*
+ * Obtain an unused block.
+ */
+int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result);
+
+/*
+ * Insert or remove block.
+ */
+int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
+ dm_block_t data_block);
+
+int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block);
+
+/*
+ * Queries.
+ */
+int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
+ dm_block_t *highest_mapped);
+
+int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result);
+
+int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd,
+ dm_block_t *result);
+
+int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
+ dm_block_t *result);
+
+int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
+ dm_block_t *result);
+
+int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result);
+
+int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
+
+/*
+ * Returns -ENOSPC if the new size is too small and already allocated
+ * blocks would be lost.
+ */
+int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
new file mode 100644
index 000000000000..c3087575fef0
--- /dev/null
+++ b/drivers/md/dm-thin.c
@@ -0,0 +1,2428 @@
+/*
+ * Copyright (C) 2011 Red Hat UK.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-thin-metadata.h"
+
+#include <linux/device-mapper.h>
+#include <linux/dm-io.h>
+#include <linux/dm-kcopyd.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define DM_MSG_PREFIX "thin"
+
+/*
+ * Tunable constants
+ */
+#define ENDIO_HOOK_POOL_SIZE 10240
+#define DEFERRED_SET_SIZE 64
+#define MAPPING_POOL_SIZE 1024
+#define PRISON_CELLS 1024
+
+/*
+ * The block size of the device holding pool data must be
+ * between 64KB and 1GB.
+ */
+#define DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT)
+#define DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT)
+
+/*
+ * The metadata device is currently limited in size. The limitation is
+ * checked lower down in dm-space-map-metadata, but we also check it here
+ * so we can fail early.
+ *
+ * We have one block of index, which can hold 255 index entries. Each
+ * index entry contains allocation info about 16k metadata blocks.
+ */
+#define METADATA_DEV_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+
+/*
+ * Device id is restricted to 24 bits.
+ */
+#define MAX_DEV_ID ((1 << 24) - 1)
+
+/*
+ * How do we handle breaking sharing of data blocks?
+ * =================================================
+ *
+ * We use a standard copy-on-write btree to store the mappings for the
+ * devices (note I'm talking about copy-on-write of the metadata here, not
+ * the data). When you take an internal snapshot you clone the root node
+ * of the origin btree. After this there is no concept of an origin or a
+ * snapshot. They are just two device trees that happen to point to the
+ * same data blocks.
+ *
+ * When we get a write in we decide if it's to a shared data block using
+ * some timestamp magic. If it is, we have to break sharing.
+ *
+ * Let's say we write to a shared block in what was the origin. The
+ * steps are:
+ *
+ * i) plug io further to this physical block. (see bio_prison code).
+ *
+ * ii) quiesce any read io to that shared data block. Obviously
+ * including all devices that share this block. (see deferred_set code)
+ *
+ * iii) copy the data block to a newly allocate block. This step can be
+ * missed out if the io covers the block. (schedule_copy).
+ *
+ * iv) insert the new mapping into the origin's btree
+ * (process_prepared_mappings). This act of inserting breaks some
+ * sharing of btree nodes between the two devices. Breaking sharing only
+ * effects the btree of that specific device. Btrees for the other
+ * devices that share the block never change. The btree for the origin
+ * device as it was after the last commit is untouched, ie. we're using
+ * persistent data structures in the functional programming sense.
+ *
+ * v) unplug io to this physical block, including the io that triggered
+ * the breaking of sharing.
+ *
+ * Steps (ii) and (iii) occur in parallel.
+ *
+ * The metadata _doesn't_ need to be committed before the io continues. We
+ * get away with this because the io is always written to a _new_ block.
+ * If there's a crash, then:
+ *
+ * - The origin mapping will point to the old origin block (the shared
+ * one). This will contain the data as it was before the io that triggered
+ * the breaking of sharing came in.
+ *
+ * - The snap mapping still points to the old block. As it would after
+ * the commit.
+ *
+ * The downside of this scheme is the timestamp magic isn't perfect, and
+ * will continue to think that data block in the snapshot device is shared
+ * even after the write to the origin has broken sharing. I suspect data
+ * blocks will typically be shared by many different devices, so we're
+ * breaking sharing n + 1 times, rather than n, where n is the number of
+ * devices that reference this data block. At the moment I think the
+ * benefits far, far outweigh the disadvantages.
+ */
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Sometimes we can't deal with a bio straight away. We put them in prison
+ * where they can't cause any mischief. Bios are put in a cell identified
+ * by a key, multiple bios can be in the same cell. When the cell is
+ * subsequently unlocked the bios become available.
+ */
+struct bio_prison;
+
+struct cell_key {
+ int virtual;
+ dm_thin_id dev;
+ dm_block_t block;
+};
+
+struct cell {
+ struct hlist_node list;
+ struct bio_prison *prison;
+ struct cell_key key;
+ unsigned count;
+ struct bio_list bios;
+};
+
+struct bio_prison {
+ spinlock_t lock;
+ mempool_t *cell_pool;
+
+ unsigned nr_buckets;
+ unsigned hash_mask;
+ struct hlist_head *cells;
+};
+
+static uint32_t calc_nr_buckets(unsigned nr_cells)
+{
+ uint32_t n = 128;
+
+ nr_cells /= 4;
+ nr_cells = min(nr_cells, 8192u);
+
+ while (n < nr_cells)
+ n <<= 1;
+
+ return n;
+}
+
+/*
+ * @nr_cells should be the number of cells you want in use _concurrently_.
+ * Don't confuse it with the number of distinct keys.
+ */
+static struct bio_prison *prison_create(unsigned nr_cells)
+{
+ unsigned i;
+ uint32_t nr_buckets = calc_nr_buckets(nr_cells);
+ size_t len = sizeof(struct bio_prison) +
+ (sizeof(struct hlist_head) * nr_buckets);
+ struct bio_prison *prison = kmalloc(len, GFP_KERNEL);
+
+ if (!prison)
+ return NULL;
+
+ spin_lock_init(&prison->lock);
+ prison->cell_pool = mempool_create_kmalloc_pool(nr_cells,
+ sizeof(struct cell));
+ if (!prison->cell_pool) {
+ kfree(prison);
+ return NULL;
+ }
+
+ prison->nr_buckets = nr_buckets;
+ prison->hash_mask = nr_buckets - 1;
+ prison->cells = (struct hlist_head *) (prison + 1);
+ for (i = 0; i < nr_buckets; i++)
+ INIT_HLIST_HEAD(prison->cells + i);
+
+ return prison;
+}
+
+static void prison_destroy(struct bio_prison *prison)
+{
+ mempool_destroy(prison->cell_pool);
+ kfree(prison);
+}
+
+static uint32_t hash_key(struct bio_prison *prison, struct cell_key *key)
+{
+ const unsigned long BIG_PRIME = 4294967291UL;
+ uint64_t hash = key->block * BIG_PRIME;
+
+ return (uint32_t) (hash & prison->hash_mask);
+}
+
+static int keys_equal(struct cell_key *lhs, struct cell_key *rhs)
+{
+ return (lhs->virtual == rhs->virtual) &&
+ (lhs->dev == rhs->dev) &&
+ (lhs->block == rhs->block);
+}
+
+static struct cell *__search_bucket(struct hlist_head *bucket,
+ struct cell_key *key)
+{
+ struct cell *cell;
+ struct hlist_node *tmp;
+
+ hlist_for_each_entry(cell, tmp, bucket, list)
+ if (keys_equal(&cell->key, key))
+ return cell;
+
+ return NULL;
+}
+
+/*
+ * This may block if a new cell needs allocating. You must ensure that
+ * cells will be unlocked even if the calling thread is blocked.
+ *
+ * Returns the number of entries in the cell prior to the new addition
+ * or < 0 on failure.
+ */
+static int bio_detain(struct bio_prison *prison, struct cell_key *key,
+ struct bio *inmate, struct cell **ref)
+{
+ int r;
+ unsigned long flags;
+ uint32_t hash = hash_key(prison, key);
+ struct cell *uninitialized_var(cell), *cell2 = NULL;
+
+ BUG_ON(hash > prison->nr_buckets);
+
+ spin_lock_irqsave(&prison->lock, flags);
+ cell = __search_bucket(prison->cells + hash, key);
+
+ if (!cell) {
+ /*
+ * Allocate a new cell
+ */
+ spin_unlock_irqrestore(&prison->lock, flags);
+ cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
+ spin_lock_irqsave(&prison->lock, flags);
+
+ /*
+ * We've been unlocked, so we have to double check that
+ * nobody else has inserted this cell in the meantime.
+ */
+ cell = __search_bucket(prison->cells + hash, key);
+
+ if (!cell) {
+ cell = cell2;
+ cell2 = NULL;
+
+ cell->prison = prison;
+ memcpy(&cell->key, key, sizeof(cell->key));
+ cell->count = 0;
+ bio_list_init(&cell->bios);
+ hlist_add_head(&cell->list, prison->cells + hash);
+ }
+ }
+
+ r = cell->count++;
+ bio_list_add(&cell->bios, inmate);
+ spin_unlock_irqrestore(&prison->lock, flags);
+
+ if (cell2)
+ mempool_free(cell2, prison->cell_pool);
+
+ *ref = cell;
+
+ return r;
+}
+
+/*
+ * @inmates must have been initialised prior to this call
+ */
+static void __cell_release(struct cell *cell, struct bio_list *inmates)
+{
+ struct bio_prison *prison = cell->prison;
+
+ hlist_del(&cell->list);
+
+ if (inmates)
+ bio_list_merge(inmates, &cell->bios);
+
+ mempool_free(cell, prison->cell_pool);
+}
+
+static void cell_release(struct cell *cell, struct bio_list *bios)
+{
+ unsigned long flags;
+ struct bio_prison *prison = cell->prison;
+
+ spin_lock_irqsave(&prison->lock, flags);
+ __cell_release(cell, bios);
+ spin_unlock_irqrestore(&prison->lock, flags);
+}
+
+/*
+ * There are a couple of places where we put a bio into a cell briefly
+ * before taking it out again. In these situations we know that no other
+ * bio may be in the cell. This function releases the cell, and also does
+ * a sanity check.
+ */
+static void cell_release_singleton(struct cell *cell, struct bio *bio)
+{
+ struct bio_prison *prison = cell->prison;
+ struct bio_list bios;
+ struct bio *b;
+ unsigned long flags;
+
+ bio_list_init(&bios);
+
+ spin_lock_irqsave(&prison->lock, flags);
+ __cell_release(cell, &bios);
+ spin_unlock_irqrestore(&prison->lock, flags);
+
+ b = bio_list_pop(&bios);
+ BUG_ON(b != bio);
+ BUG_ON(!bio_list_empty(&bios));
+}
+
+static void cell_error(struct cell *cell)
+{
+ struct bio_prison *prison = cell->prison;
+ struct bio_list bios;
+ struct bio *bio;
+ unsigned long flags;
+
+ bio_list_init(&bios);
+
+ spin_lock_irqsave(&prison->lock, flags);
+ __cell_release(cell, &bios);
+ spin_unlock_irqrestore(&prison->lock, flags);
+
+ while ((bio = bio_list_pop(&bios)))
+ bio_io_error(bio);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We use the deferred set to keep track of pending reads to shared blocks.
+ * We do this to ensure the new mapping caused by a write isn't performed
+ * until these prior reads have completed. Otherwise the insertion of the
+ * new mapping could free the old block that the read bios are mapped to.
+ */
+
+struct deferred_set;
+struct deferred_entry {
+ struct deferred_set *ds;
+ unsigned count;
+ struct list_head work_items;
+};
+
+struct deferred_set {
+ spinlock_t lock;
+ unsigned current_entry;
+ unsigned sweeper;
+ struct deferred_entry entries[DEFERRED_SET_SIZE];
+};
+
+static void ds_init(struct deferred_set *ds)
+{
+ int i;
+
+ spin_lock_init(&ds->lock);
+ ds->current_entry = 0;
+ ds->sweeper = 0;
+ for (i = 0; i < DEFERRED_SET_SIZE; i++) {
+ ds->entries[i].ds = ds;
+ ds->entries[i].count = 0;
+ INIT_LIST_HEAD(&ds->entries[i].work_items);
+ }
+}
+
+static struct deferred_entry *ds_inc(struct deferred_set *ds)
+{
+ unsigned long flags;
+ struct deferred_entry *entry;
+
+ spin_lock_irqsave(&ds->lock, flags);
+ entry = ds->entries + ds->current_entry;
+ entry->count++;
+ spin_unlock_irqrestore(&ds->lock, flags);
+
+ return entry;
+}
+
+static unsigned ds_next(unsigned index)
+{
+ return (index + 1) % DEFERRED_SET_SIZE;
+}
+
+static void __sweep(struct deferred_set *ds, struct list_head *head)
+{
+ while ((ds->sweeper != ds->current_entry) &&
+ !ds->entries[ds->sweeper].count) {
+ list_splice_init(&ds->entries[ds->sweeper].work_items, head);
+ ds->sweeper = ds_next(ds->sweeper);
+ }
+
+ if ((ds->sweeper == ds->current_entry) && !ds->entries[ds->sweeper].count)
+ list_splice_init(&ds->entries[ds->sweeper].work_items, head);
+}
+
+static void ds_dec(struct deferred_entry *entry, struct list_head *head)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&entry->ds->lock, flags);
+ BUG_ON(!entry->count);
+ --entry->count;
+ __sweep(entry->ds, head);
+ spin_unlock_irqrestore(&entry->ds->lock, flags);
+}
+
+/*
+ * Returns 1 if deferred or 0 if no pending items to delay job.
+ */
+static int ds_add_work(struct deferred_set *ds, struct list_head *work)
+{
+ int r = 1;
+ unsigned long flags;
+ unsigned next_entry;
+
+ spin_lock_irqsave(&ds->lock, flags);
+ if ((ds->sweeper == ds->current_entry) &&
+ !ds->entries[ds->current_entry].count)
+ r = 0;
+ else {
+ list_add(work, &ds->entries[ds->current_entry].work_items);
+ next_entry = ds_next(ds->current_entry);
+ if (!ds->entries[next_entry].count)
+ ds->current_entry = next_entry;
+ }
+ spin_unlock_irqrestore(&ds->lock, flags);
+
+ return r;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Key building.
+ */
+static void build_data_key(struct dm_thin_device *td,
+ dm_block_t b, struct cell_key *key)
+{
+ key->virtual = 0;
+ key->dev = dm_thin_dev_id(td);
+ key->block = b;
+}
+
+static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
+ struct cell_key *key)
+{
+ key->virtual = 1;
+ key->dev = dm_thin_dev_id(td);
+ key->block = b;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * A pool device ties together a metadata device and a data device. It
+ * also provides the interface for creating and destroying internal
+ * devices.
+ */
+struct new_mapping;
+struct pool {
+ struct list_head list;
+ struct dm_target *ti; /* Only set if a pool target is bound */
+
+ struct mapped_device *pool_md;
+ struct block_device *md_dev;
+ struct dm_pool_metadata *pmd;
+
+ uint32_t sectors_per_block;
+ unsigned block_shift;
+ dm_block_t offset_mask;
+ dm_block_t low_water_blocks;
+
+ unsigned zero_new_blocks:1;
+ unsigned low_water_triggered:1; /* A dm event has been sent */
+ unsigned no_free_space:1; /* A -ENOSPC warning has been issued */
+
+ struct bio_prison *prison;
+ struct dm_kcopyd_client *copier;
+
+ struct workqueue_struct *wq;
+ struct work_struct worker;
+
+ unsigned ref_count;
+
+ spinlock_t lock;
+ struct bio_list deferred_bios;
+ struct bio_list deferred_flush_bios;
+ struct list_head prepared_mappings;
+
+ struct bio_list retry_on_resume_list;
+
+ struct deferred_set ds; /* FIXME: move to thin_c */
+
+ struct new_mapping *next_mapping;
+ mempool_t *mapping_pool;
+ mempool_t *endio_hook_pool;
+};
+
+/*
+ * Target context for a pool.
+ */
+struct pool_c {
+ struct dm_target *ti;
+ struct pool *pool;
+ struct dm_dev *data_dev;
+ struct dm_dev *metadata_dev;
+ struct dm_target_callbacks callbacks;
+
+ dm_block_t low_water_blocks;
+ unsigned zero_new_blocks:1;
+};
+
+/*
+ * Target context for a thin.
+ */
+struct thin_c {
+ struct dm_dev *pool_dev;
+ dm_thin_id dev_id;
+
+ struct pool *pool;
+ struct dm_thin_device *td;
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * A global list of pools that uses a struct mapped_device as a key.
+ */
+static struct dm_thin_pool_table {
+ struct mutex mutex;
+ struct list_head pools;
+} dm_thin_pool_table;
+
+static void pool_table_init(void)
+{
+ mutex_init(&dm_thin_pool_table.mutex);
+ INIT_LIST_HEAD(&dm_thin_pool_table.pools);
+}
+
+static void __pool_table_insert(struct pool *pool)
+{
+ BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+ list_add(&pool->list, &dm_thin_pool_table.pools);
+}
+
+static void __pool_table_remove(struct pool *pool)
+{
+ BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+ list_del(&pool->list);
+}
+
+static struct pool *__pool_table_lookup(struct mapped_device *md)
+{
+ struct pool *pool = NULL, *tmp;
+
+ BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+
+ list_for_each_entry(tmp, &dm_thin_pool_table.pools, list) {
+ if (tmp->pool_md == md) {
+ pool = tmp;
+ break;
+ }
+ }
+
+ return pool;
+}
+
+static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev)
+{
+ struct pool *pool = NULL, *tmp;
+
+ BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+
+ list_for_each_entry(tmp, &dm_thin_pool_table.pools, list) {
+ if (tmp->md_dev == md_dev) {
+ pool = tmp;
+ break;
+ }
+ }
+
+ return pool;
+}
+
+/*----------------------------------------------------------------*/
+
+static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
+{
+ struct bio *bio;
+ struct bio_list bios;
+
+ bio_list_init(&bios);
+ bio_list_merge(&bios, master);
+ bio_list_init(master);
+
+ while ((bio = bio_list_pop(&bios))) {
+ if (dm_get_mapinfo(bio)->ptr == tc)
+ bio_endio(bio, DM_ENDIO_REQUEUE);
+ else
+ bio_list_add(master, bio);
+ }
+}
+
+static void requeue_io(struct thin_c *tc)
+{
+ struct pool *pool = tc->pool;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ __requeue_bio_list(tc, &pool->deferred_bios);
+ __requeue_bio_list(tc, &pool->retry_on_resume_list);
+ spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+/*
+ * This section of code contains the logic for processing a thin device's IO.
+ * Much of the code depends on pool object resources (lists, workqueues, etc)
+ * but most is exclusively called from the thin target rather than the thin-pool
+ * target.
+ */
+
+static dm_block_t get_bio_block(struct thin_c *tc, struct bio *bio)
+{
+ return bio->bi_sector >> tc->pool->block_shift;
+}
+
+static void remap(struct thin_c *tc, struct bio *bio, dm_block_t block)
+{
+ struct pool *pool = tc->pool;
+
+ bio->bi_bdev = tc->pool_dev->bdev;
+ bio->bi_sector = (block << pool->block_shift) +
+ (bio->bi_sector & pool->offset_mask);
+}
+
+static void remap_and_issue(struct thin_c *tc, struct bio *bio,
+ dm_block_t block)
+{
+ struct pool *pool = tc->pool;
+ unsigned long flags;
+
+ remap(tc, bio, block);
+
+ /*
+ * Batch together any FUA/FLUSH bios we find and then issue
+ * a single commit for them in process_deferred_bios().
+ */
+ if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+ spin_lock_irqsave(&pool->lock, flags);
+ bio_list_add(&pool->deferred_flush_bios, bio);
+ spin_unlock_irqrestore(&pool->lock, flags);
+ } else
+ generic_make_request(bio);
+}
+
+/*
+ * wake_worker() is used when new work is queued and when pool_resume is
+ * ready to continue deferred IO processing.
+ */
+static void wake_worker(struct pool *pool)
+{
+ queue_work(pool->wq, &pool->worker);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Bio endio functions.
+ */
+struct endio_hook {
+ struct thin_c *tc;
+ bio_end_io_t *saved_bi_end_io;
+ struct deferred_entry *entry;
+};
+
+struct new_mapping {
+ struct list_head list;
+
+ int prepared;
+
+ struct thin_c *tc;
+ dm_block_t virt_block;
+ dm_block_t data_block;
+ struct cell *cell;
+ int err;
+
+ /*
+ * If the bio covers the whole area of a block then we can avoid
+ * zeroing or copying. Instead this bio is hooked. The bio will
+ * still be in the cell, so care has to be taken to avoid issuing
+ * the bio twice.
+ */
+ struct bio *bio;
+ bio_end_io_t *saved_bi_end_io;
+};
+
+static void __maybe_add_mapping(struct new_mapping *m)
+{
+ struct pool *pool = m->tc->pool;
+
+ if (list_empty(&m->list) && m->prepared) {
+ list_add(&m->list, &pool->prepared_mappings);
+ wake_worker(pool);
+ }
+}
+
+static void copy_complete(int read_err, unsigned long write_err, void *context)
+{
+ unsigned long flags;
+ struct new_mapping *m = context;
+ struct pool *pool = m->tc->pool;
+
+ m->err = read_err || write_err ? -EIO : 0;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ m->prepared = 1;
+ __maybe_add_mapping(m);
+ spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void overwrite_endio(struct bio *bio, int err)
+{
+ unsigned long flags;
+ struct new_mapping *m = dm_get_mapinfo(bio)->ptr;
+ struct pool *pool = m->tc->pool;
+
+ m->err = err;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ m->prepared = 1;
+ __maybe_add_mapping(m);
+ spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void shared_read_endio(struct bio *bio, int err)
+{
+ struct list_head mappings;
+ struct new_mapping *m, *tmp;
+ struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+ unsigned long flags;
+ struct pool *pool = h->tc->pool;
+
+ bio->bi_end_io = h->saved_bi_end_io;
+ bio_endio(bio, err);
+
+ INIT_LIST_HEAD(&mappings);
+ ds_dec(h->entry, &mappings);
+
+ spin_lock_irqsave(&pool->lock, flags);
+ list_for_each_entry_safe(m, tmp, &mappings, list) {
+ list_del(&m->list);
+ INIT_LIST_HEAD(&m->list);
+ __maybe_add_mapping(m);
+ }
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ mempool_free(h, pool->endio_hook_pool);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Workqueue.
+ */
+
+/*
+ * Prepared mapping jobs.
+ */
+
+/*
+ * This sends the bios in the cell back to the deferred_bios list.
+ */
+static void cell_defer(struct thin_c *tc, struct cell *cell,
+ dm_block_t data_block)
+{
+ struct pool *pool = tc->pool;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ cell_release(cell, &pool->deferred_bios);
+ spin_unlock_irqrestore(&tc->pool->lock, flags);
+
+ wake_worker(pool);
+}
+
+/*
+ * Same as cell_defer above, except it omits one particular detainee,
+ * a write bio that covers the block and has already been processed.
+ */
+static void cell_defer_except(struct thin_c *tc, struct cell *cell,
+ struct bio *exception)
+{
+ struct bio_list bios;
+ struct bio *bio;
+ struct pool *pool = tc->pool;
+ unsigned long flags;
+
+ bio_list_init(&bios);
+ cell_release(cell, &bios);
+
+ spin_lock_irqsave(&pool->lock, flags);
+ while ((bio = bio_list_pop(&bios)))
+ if (bio != exception)
+ bio_list_add(&pool->deferred_bios, bio);
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ wake_worker(pool);
+}
+
+static void process_prepared_mapping(struct new_mapping *m)
+{
+ struct thin_c *tc = m->tc;
+ struct bio *bio;
+ int r;
+
+ bio = m->bio;
+ if (bio)
+ bio->bi_end_io = m->saved_bi_end_io;
+
+ if (m->err) {
+ cell_error(m->cell);
+ return;
+ }
+
+ /*
+ * Commit the prepared block into the mapping btree.
+ * Any I/O for this block arriving after this point will get
+ * remapped to it directly.
+ */
+ r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
+ if (r) {
+ DMERR("dm_thin_insert_block() failed");
+ cell_error(m->cell);
+ return;
+ }
+
+ /*
+ * Release any bios held while the block was being provisioned.
+ * If we are processing a write bio that completely covers the block,
+ * we already processed it so can ignore it now when processing
+ * the bios in the cell.
+ */
+ if (bio) {
+ cell_defer_except(tc, m->cell, bio);
+ bio_endio(bio, 0);
+ } else
+ cell_defer(tc, m->cell, m->data_block);
+
+ list_del(&m->list);
+ mempool_free(m, tc->pool->mapping_pool);
+}
+
+static void process_prepared_mappings(struct pool *pool)
+{
+ unsigned long flags;
+ struct list_head maps;
+ struct new_mapping *m, *tmp;
+
+ INIT_LIST_HEAD(&maps);
+ spin_lock_irqsave(&pool->lock, flags);
+ list_splice_init(&pool->prepared_mappings, &maps);
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ list_for_each_entry_safe(m, tmp, &maps, list)
+ process_prepared_mapping(m);
+}
+
+/*
+ * Deferred bio jobs.
+ */
+static int io_overwrites_block(struct pool *pool, struct bio *bio)
+{
+ return ((bio_data_dir(bio) == WRITE) &&
+ !(bio->bi_sector & pool->offset_mask)) &&
+ (bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT));
+}
+
+static void save_and_set_endio(struct bio *bio, bio_end_io_t **save,
+ bio_end_io_t *fn)
+{
+ *save = bio->bi_end_io;
+ bio->bi_end_io = fn;
+}
+
+static int ensure_next_mapping(struct pool *pool)
+{
+ if (pool->next_mapping)
+ return 0;
+
+ pool->next_mapping = mempool_alloc(pool->mapping_pool, GFP_ATOMIC);
+
+ return pool->next_mapping ? 0 : -ENOMEM;
+}
+
+static struct new_mapping *get_next_mapping(struct pool *pool)
+{
+ struct new_mapping *r = pool->next_mapping;
+
+ BUG_ON(!pool->next_mapping);
+
+ pool->next_mapping = NULL;
+
+ return r;
+}
+
+static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
+ dm_block_t data_origin, dm_block_t data_dest,
+ struct cell *cell, struct bio *bio)
+{
+ int r;
+ struct pool *pool = tc->pool;
+ struct new_mapping *m = get_next_mapping(pool);
+
+ INIT_LIST_HEAD(&m->list);
+ m->prepared = 0;
+ m->tc = tc;
+ m->virt_block = virt_block;
+ m->data_block = data_dest;
+ m->cell = cell;
+ m->err = 0;
+ m->bio = NULL;
+
+ ds_add_work(&pool->ds, &m->list);
+
+ /*
+ * IO to pool_dev remaps to the pool target's data_dev.
+ *
+ * If the whole block of data is being overwritten, we can issue the
+ * bio immediately. Otherwise we use kcopyd to clone the data first.
+ */
+ if (io_overwrites_block(pool, bio)) {
+ m->bio = bio;
+ save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+ dm_get_mapinfo(bio)->ptr = m;
+ remap_and_issue(tc, bio, data_dest);
+ } else {
+ struct dm_io_region from, to;
+
+ from.bdev = tc->pool_dev->bdev;
+ from.sector = data_origin * pool->sectors_per_block;
+ from.count = pool->sectors_per_block;
+
+ to.bdev = tc->pool_dev->bdev;
+ to.sector = data_dest * pool->sectors_per_block;
+ to.count = pool->sectors_per_block;
+
+ r = dm_kcopyd_copy(pool->copier, &from, 1, &to,
+ 0, copy_complete, m);
+ if (r < 0) {
+ mempool_free(m, pool->mapping_pool);
+ DMERR("dm_kcopyd_copy() failed");
+ cell_error(cell);
+ }
+ }
+}
+
+static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
+ dm_block_t data_block, struct cell *cell,
+ struct bio *bio)
+{
+ struct pool *pool = tc->pool;
+ struct new_mapping *m = get_next_mapping(pool);
+
+ INIT_LIST_HEAD(&m->list);
+ m->prepared = 0;
+ m->tc = tc;
+ m->virt_block = virt_block;
+ m->data_block = data_block;
+ m->cell = cell;
+ m->err = 0;
+ m->bio = NULL;
+
+ /*
+ * If the whole block of data is being overwritten or we are not
+ * zeroing pre-existing data, we can issue the bio immediately.
+ * Otherwise we use kcopyd to zero the data first.
+ */
+ if (!pool->zero_new_blocks)
+ process_prepared_mapping(m);
+
+ else if (io_overwrites_block(pool, bio)) {
+ m->bio = bio;
+ save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+ dm_get_mapinfo(bio)->ptr = m;
+ remap_and_issue(tc, bio, data_block);
+
+ } else {
+ int r;
+ struct dm_io_region to;
+
+ to.bdev = tc->pool_dev->bdev;
+ to.sector = data_block * pool->sectors_per_block;
+ to.count = pool->sectors_per_block;
+
+ r = dm_kcopyd_zero(pool->copier, 1, &to, 0, copy_complete, m);
+ if (r < 0) {
+ mempool_free(m, pool->mapping_pool);
+ DMERR("dm_kcopyd_zero() failed");
+ cell_error(cell);
+ }
+ }
+}
+
+static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
+{
+ int r;
+ dm_block_t free_blocks;
+ unsigned long flags;
+ struct pool *pool = tc->pool;
+
+ r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
+ if (r)
+ return r;
+
+ if (free_blocks <= pool->low_water_blocks && !pool->low_water_triggered) {
+ DMWARN("%s: reached low water mark, sending event.",
+ dm_device_name(pool->pool_md));
+ spin_lock_irqsave(&pool->lock, flags);
+ pool->low_water_triggered = 1;
+ spin_unlock_irqrestore(&pool->lock, flags);
+ dm_table_event(pool->ti->table);
+ }
+
+ if (!free_blocks) {
+ if (pool->no_free_space)
+ return -ENOSPC;
+ else {
+ /*
+ * Try to commit to see if that will free up some
+ * more space.
+ */
+ r = dm_pool_commit_metadata(pool->pmd);
+ if (r) {
+ DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+ __func__, r);
+ return r;
+ }
+
+ r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
+ if (r)
+ return r;
+
+ /*
+ * If we still have no space we set a flag to avoid
+ * doing all this checking and return -ENOSPC.
+ */
+ if (!free_blocks) {
+ DMWARN("%s: no free space available.",
+ dm_device_name(pool->pool_md));
+ spin_lock_irqsave(&pool->lock, flags);
+ pool->no_free_space = 1;
+ spin_unlock_irqrestore(&pool->lock, flags);
+ return -ENOSPC;
+ }
+ }
+ }
+
+ r = dm_pool_alloc_data_block(pool->pmd, result);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+/*
+ * If we have run out of space, queue bios until the device is
+ * resumed, presumably after having been reloaded with more space.
+ */
+static void retry_on_resume(struct bio *bio)
+{
+ struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+ struct pool *pool = tc->pool;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ bio_list_add(&pool->retry_on_resume_list, bio);
+ spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void no_space(struct cell *cell)
+{
+ struct bio *bio;
+ struct bio_list bios;
+
+ bio_list_init(&bios);
+ cell_release(cell, &bios);
+
+ while ((bio = bio_list_pop(&bios)))
+ retry_on_resume(bio);
+}
+
+static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
+ struct cell_key *key,
+ struct dm_thin_lookup_result *lookup_result,
+ struct cell *cell)
+{
+ int r;
+ dm_block_t data_block;
+
+ r = alloc_data_block(tc, &data_block);
+ switch (r) {
+ case 0:
+ schedule_copy(tc, block, lookup_result->block,
+ data_block, cell, bio);
+ break;
+
+ case -ENOSPC:
+ no_space(cell);
+ break;
+
+ default:
+ DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
+ cell_error(cell);
+ break;
+ }
+}
+
+static void process_shared_bio(struct thin_c *tc, struct bio *bio,
+ dm_block_t block,
+ struct dm_thin_lookup_result *lookup_result)
+{
+ struct cell *cell;
+ struct pool *pool = tc->pool;
+ struct cell_key key;
+
+ /*
+ * If cell is already occupied, then sharing is already in the process
+ * of being broken so we have nothing further to do here.
+ */
+ build_data_key(tc->td, lookup_result->block, &key);
+ if (bio_detain(pool->prison, &key, bio, &cell))
+ return;
+
+ if (bio_data_dir(bio) == WRITE)
+ break_sharing(tc, bio, block, &key, lookup_result, cell);
+ else {
+ struct endio_hook *h;
+ h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO);
+
+ h->tc = tc;
+ h->entry = ds_inc(&pool->ds);
+ save_and_set_endio(bio, &h->saved_bi_end_io, shared_read_endio);
+ dm_get_mapinfo(bio)->ptr = h;
+
+ cell_release_singleton(cell, bio);
+ remap_and_issue(tc, bio, lookup_result->block);
+ }
+}
+
+static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block,
+ struct cell *cell)
+{
+ int r;
+ dm_block_t data_block;
+
+ /*
+ * Remap empty bios (flushes) immediately, without provisioning.
+ */
+ if (!bio->bi_size) {
+ cell_release_singleton(cell, bio);
+ remap_and_issue(tc, bio, 0);
+ return;
+ }
+
+ /*
+ * Fill read bios with zeroes and complete them immediately.
+ */
+ if (bio_data_dir(bio) == READ) {
+ zero_fill_bio(bio);
+ cell_release_singleton(cell, bio);
+ bio_endio(bio, 0);
+ return;
+ }
+
+ r = alloc_data_block(tc, &data_block);
+ switch (r) {
+ case 0:
+ schedule_zero(tc, block, data_block, cell, bio);
+ break;
+
+ case -ENOSPC:
+ no_space(cell);
+ break;
+
+ default:
+ DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
+ cell_error(cell);
+ break;
+ }
+}
+
+static void process_bio(struct thin_c *tc, struct bio *bio)
+{
+ int r;
+ dm_block_t block = get_bio_block(tc, bio);
+ struct cell *cell;
+ struct cell_key key;
+ struct dm_thin_lookup_result lookup_result;
+
+ /*
+ * If cell is already occupied, then the block is already
+ * being provisioned so we have nothing further to do here.
+ */
+ build_virtual_key(tc->td, block, &key);
+ if (bio_detain(tc->pool->prison, &key, bio, &cell))
+ return;
+
+ r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
+ switch (r) {
+ case 0:
+ /*
+ * We can release this cell now. This thread is the only
+ * one that puts bios into a cell, and we know there were
+ * no preceding bios.
+ */
+ /*
+ * TODO: this will probably have to change when discard goes
+ * back in.
+ */
+ cell_release_singleton(cell, bio);
+
+ if (lookup_result.shared)
+ process_shared_bio(tc, bio, block, &lookup_result);
+ else
+ remap_and_issue(tc, bio, lookup_result.block);
+ break;
+
+ case -ENODATA:
+ provision_block(tc, bio, block, cell);
+ break;
+
+ default:
+ DMERR("dm_thin_find_block() failed, error = %d", r);
+ bio_io_error(bio);
+ break;
+ }
+}
+
+static void process_deferred_bios(struct pool *pool)
+{
+ unsigned long flags;
+ struct bio *bio;
+ struct bio_list bios;
+ int r;
+
+ bio_list_init(&bios);
+
+ spin_lock_irqsave(&pool->lock, flags);
+ bio_list_merge(&bios, &pool->deferred_bios);
+ bio_list_init(&pool->deferred_bios);
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ while ((bio = bio_list_pop(&bios))) {
+ struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+ /*
+ * If we've got no free new_mapping structs, and processing
+ * this bio might require one, we pause until there are some
+ * prepared mappings to process.
+ */
+ if (ensure_next_mapping(pool)) {
+ spin_lock_irqsave(&pool->lock, flags);
+ bio_list_merge(&pool->deferred_bios, &bios);
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ break;
+ }
+ process_bio(tc, bio);
+ }
+
+ /*
+ * If there are any deferred flush bios, we must commit
+ * the metadata before issuing them.
+ */
+ bio_list_init(&bios);
+ spin_lock_irqsave(&pool->lock, flags);
+ bio_list_merge(&bios, &pool->deferred_flush_bios);
+ bio_list_init(&pool->deferred_flush_bios);
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ if (bio_list_empty(&bios))
+ return;
+
+ r = dm_pool_commit_metadata(pool->pmd);
+ if (r) {
+ DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+ __func__, r);
+ while ((bio = bio_list_pop(&bios)))
+ bio_io_error(bio);
+ return;
+ }
+
+ while ((bio = bio_list_pop(&bios)))
+ generic_make_request(bio);
+}
+
+static void do_worker(struct work_struct *ws)
+{
+ struct pool *pool = container_of(ws, struct pool, worker);
+
+ process_prepared_mappings(pool);
+ process_deferred_bios(pool);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Mapping functions.
+ */
+
+/*
+ * Called only while mapping a thin bio to hand it over to the workqueue.
+ */
+static void thin_defer_bio(struct thin_c *tc, struct bio *bio)
+{
+ unsigned long flags;
+ struct pool *pool = tc->pool;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ bio_list_add(&pool->deferred_bios, bio);
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ wake_worker(pool);
+}
+
+/*
+ * Non-blocking function called from the thin target's map function.
+ */
+static int thin_bio_map(struct dm_target *ti, struct bio *bio,
+ union map_info *map_context)
+{
+ int r;
+ struct thin_c *tc = ti->private;
+ dm_block_t block = get_bio_block(tc, bio);
+ struct dm_thin_device *td = tc->td;
+ struct dm_thin_lookup_result result;
+
+ /*
+ * Save the thin context for easy access from the deferred bio later.
+ */
+ map_context->ptr = tc;
+
+ if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+ thin_defer_bio(tc, bio);
+ return DM_MAPIO_SUBMITTED;
+ }
+
+ r = dm_thin_find_block(td, block, 0, &result);
+
+ /*
+ * Note that we defer readahead too.
+ */
+ switch (r) {
+ case 0:
+ if (unlikely(result.shared)) {
+ /*
+ * We have a race condition here between the
+ * result.shared value returned by the lookup and
+ * snapshot creation, which may cause new
+ * sharing.
+ *
+ * To avoid this always quiesce the origin before
+ * taking the snap. You want to do this anyway to
+ * ensure a consistent application view
+ * (i.e. lockfs).
+ *
+ * More distant ancestors are irrelevant. The
+ * shared flag will be set in their case.
+ */
+ thin_defer_bio(tc, bio);
+ r = DM_MAPIO_SUBMITTED;
+ } else {
+ remap(tc, bio, result.block);
+ r = DM_MAPIO_REMAPPED;
+ }
+ break;
+
+ case -ENODATA:
+ /*
+ * In future, the failed dm_thin_find_block above could
+ * provide the hint to load the metadata into cache.
+ */
+ case -EWOULDBLOCK:
+ thin_defer_bio(tc, bio);
+ r = DM_MAPIO_SUBMITTED;
+ break;
+ }
+
+ return r;
+}
+
+static int pool_is_congested(struct dm_target_callbacks *cb, int bdi_bits)
+{
+ int r;
+ unsigned long flags;
+ struct pool_c *pt = container_of(cb, struct pool_c, callbacks);
+
+ spin_lock_irqsave(&pt->pool->lock, flags);
+ r = !bio_list_empty(&pt->pool->retry_on_resume_list);
+ spin_unlock_irqrestore(&pt->pool->lock, flags);
+
+ if (!r) {
+ struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+ r = bdi_congested(&q->backing_dev_info, bdi_bits);
+ }
+
+ return r;
+}
+
+static void __requeue_bios(struct pool *pool)
+{
+ bio_list_merge(&pool->deferred_bios, &pool->retry_on_resume_list);
+ bio_list_init(&pool->retry_on_resume_list);
+}
+
+/*----------------------------------------------------------------
+ * Binding of control targets to a pool object
+ *--------------------------------------------------------------*/
+static int bind_control_target(struct pool *pool, struct dm_target *ti)
+{
+ struct pool_c *pt = ti->private;
+
+ pool->ti = ti;
+ pool->low_water_blocks = pt->low_water_blocks;
+ pool->zero_new_blocks = pt->zero_new_blocks;
+
+ return 0;
+}
+
+static void unbind_control_target(struct pool *pool, struct dm_target *ti)
+{
+ if (pool->ti == ti)
+ pool->ti = NULL;
+}
+
+/*----------------------------------------------------------------
+ * Pool creation
+ *--------------------------------------------------------------*/
+static void __pool_destroy(struct pool *pool)
+{
+ __pool_table_remove(pool);
+
+ if (dm_pool_metadata_close(pool->pmd) < 0)
+ DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+
+ prison_destroy(pool->prison);
+ dm_kcopyd_client_destroy(pool->copier);
+
+ if (pool->wq)
+ destroy_workqueue(pool->wq);
+
+ if (pool->next_mapping)
+ mempool_free(pool->next_mapping, pool->mapping_pool);
+ mempool_destroy(pool->mapping_pool);
+ mempool_destroy(pool->endio_hook_pool);
+ kfree(pool);
+}
+
+static struct pool *pool_create(struct mapped_device *pool_md,
+ struct block_device *metadata_dev,
+ unsigned long block_size, char **error)
+{
+ int r;
+ void *err_p;
+ struct pool *pool;
+ struct dm_pool_metadata *pmd;
+
+ pmd = dm_pool_metadata_open(metadata_dev, block_size);
+ if (IS_ERR(pmd)) {
+ *error = "Error creating metadata object";
+ return (struct pool *)pmd;
+ }
+
+ pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+ if (!pool) {
+ *error = "Error allocating memory for pool";
+ err_p = ERR_PTR(-ENOMEM);
+ goto bad_pool;
+ }
+
+ pool->pmd = pmd;
+ pool->sectors_per_block = block_size;
+ pool->block_shift = ffs(block_size) - 1;
+ pool->offset_mask = block_size - 1;
+ pool->low_water_blocks = 0;
+ pool->zero_new_blocks = 1;
+ pool->prison = prison_create(PRISON_CELLS);
+ if (!pool->prison) {
+ *error = "Error creating pool's bio prison";
+ err_p = ERR_PTR(-ENOMEM);
+ goto bad_prison;
+ }
+
+ pool->copier = dm_kcopyd_client_create();
+ if (IS_ERR(pool->copier)) {
+ r = PTR_ERR(pool->copier);
+ *error = "Error creating pool's kcopyd client";
+ err_p = ERR_PTR(r);
+ goto bad_kcopyd_client;
+ }
+
+ /*
+ * Create singlethreaded workqueue that will service all devices
+ * that use this metadata.
+ */
+ pool->wq = alloc_ordered_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM);
+ if (!pool->wq) {
+ *error = "Error creating pool's workqueue";
+ err_p = ERR_PTR(-ENOMEM);
+ goto bad_wq;
+ }
+
+ INIT_WORK(&pool->worker, do_worker);
+ spin_lock_init(&pool->lock);
+ bio_list_init(&pool->deferred_bios);
+ bio_list_init(&pool->deferred_flush_bios);
+ INIT_LIST_HEAD(&pool->prepared_mappings);
+ pool->low_water_triggered = 0;
+ pool->no_free_space = 0;
+ bio_list_init(&pool->retry_on_resume_list);
+ ds_init(&pool->ds);
+
+ pool->next_mapping = NULL;
+ pool->mapping_pool =
+ mempool_create_kmalloc_pool(MAPPING_POOL_SIZE, sizeof(struct new_mapping));
+ if (!pool->mapping_pool) {
+ *error = "Error creating pool's mapping mempool";
+ err_p = ERR_PTR(-ENOMEM);
+ goto bad_mapping_pool;
+ }
+
+ pool->endio_hook_pool =
+ mempool_create_kmalloc_pool(ENDIO_HOOK_POOL_SIZE, sizeof(struct endio_hook));
+ if (!pool->endio_hook_pool) {
+ *error = "Error creating pool's endio_hook mempool";
+ err_p = ERR_PTR(-ENOMEM);
+ goto bad_endio_hook_pool;
+ }
+ pool->ref_count = 1;
+ pool->pool_md = pool_md;
+ pool->md_dev = metadata_dev;
+ __pool_table_insert(pool);
+
+ return pool;
+
+bad_endio_hook_pool:
+ mempool_destroy(pool->mapping_pool);
+bad_mapping_pool:
+ destroy_workqueue(pool->wq);
+bad_wq:
+ dm_kcopyd_client_destroy(pool->copier);
+bad_kcopyd_client:
+ prison_destroy(pool->prison);
+bad_prison:
+ kfree(pool);
+bad_pool:
+ if (dm_pool_metadata_close(pmd))
+ DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+
+ return err_p;
+}
+
+static void __pool_inc(struct pool *pool)
+{
+ BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+ pool->ref_count++;
+}
+
+static void __pool_dec(struct pool *pool)
+{
+ BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+ BUG_ON(!pool->ref_count);
+ if (!--pool->ref_count)
+ __pool_destroy(pool);
+}
+
+static struct pool *__pool_find(struct mapped_device *pool_md,
+ struct block_device *metadata_dev,
+ unsigned long block_size, char **error)
+{
+ struct pool *pool = __pool_table_lookup_metadata_dev(metadata_dev);
+
+ if (pool) {
+ if (pool->pool_md != pool_md)
+ return ERR_PTR(-EBUSY);
+ __pool_inc(pool);
+
+ } else {
+ pool = __pool_table_lookup(pool_md);
+ if (pool) {
+ if (pool->md_dev != metadata_dev)
+ return ERR_PTR(-EINVAL);
+ __pool_inc(pool);
+
+ } else
+ pool = pool_create(pool_md, metadata_dev, block_size, error);
+ }
+
+ return pool;
+}
+
+/*----------------------------------------------------------------
+ * Pool target methods
+ *--------------------------------------------------------------*/
+static void pool_dtr(struct dm_target *ti)
+{
+ struct pool_c *pt = ti->private;
+
+ mutex_lock(&dm_thin_pool_table.mutex);
+
+ unbind_control_target(pt->pool, ti);
+ __pool_dec(pt->pool);
+ dm_put_device(ti, pt->metadata_dev);
+ dm_put_device(ti, pt->data_dev);
+ kfree(pt);
+
+ mutex_unlock(&dm_thin_pool_table.mutex);
+}
+
+struct pool_features {
+ unsigned zero_new_blocks:1;
+};
+
+static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
+ struct dm_target *ti)
+{
+ int r;
+ unsigned argc;
+ const char *arg_name;
+
+ static struct dm_arg _args[] = {
+ {0, 1, "Invalid number of pool feature arguments"},
+ };
+
+ /*
+ * No feature arguments supplied.
+ */
+ if (!as->argc)
+ return 0;
+
+ r = dm_read_arg_group(_args, as, &argc, &ti->error);
+ if (r)
+ return -EINVAL;
+
+ while (argc && !r) {
+ arg_name = dm_shift_arg(as);
+ argc--;
+
+ if (!strcasecmp(arg_name, "skip_block_zeroing")) {
+ pf->zero_new_blocks = 0;
+ continue;
+ }
+
+ ti->error = "Unrecognised pool feature requested";
+ r = -EINVAL;
+ }
+
+ return r;
+}
+
+/*
+ * thin-pool <metadata dev> <data dev>
+ * <data block size (sectors)>
+ * <low water mark (blocks)>
+ * [<#feature args> [<arg>]*]
+ *
+ * Optional feature arguments are:
+ * skip_block_zeroing: skips the zeroing of newly-provisioned blocks.
+ */
+static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+ int r;
+ struct pool_c *pt;
+ struct pool *pool;
+ struct pool_features pf;
+ struct dm_arg_set as;
+ struct dm_dev *data_dev;
+ unsigned long block_size;
+ dm_block_t low_water_blocks;
+ struct dm_dev *metadata_dev;
+ sector_t metadata_dev_size;
+
+ /*
+ * FIXME Remove validation from scope of lock.
+ */
+ mutex_lock(&dm_thin_pool_table.mutex);
+
+ if (argc < 4) {
+ ti->error = "Invalid argument count";
+ r = -EINVAL;
+ goto out_unlock;
+ }
+ as.argc = argc;
+ as.argv = argv;
+
+ r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &metadata_dev);
+ if (r) {
+ ti->error = "Error opening metadata block device";
+ goto out_unlock;
+ }
+
+ metadata_dev_size = i_size_read(metadata_dev->bdev->bd_inode) >> SECTOR_SHIFT;
+ if (metadata_dev_size > METADATA_DEV_MAX_SECTORS) {
+ ti->error = "Metadata device is too large";
+ r = -EINVAL;
+ goto out_metadata;
+ }
+
+ r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
+ if (r) {
+ ti->error = "Error getting data device";
+ goto out_metadata;
+ }
+
+ if (kstrtoul(argv[2], 10, &block_size) || !block_size ||
+ block_size < DATA_DEV_BLOCK_SIZE_MIN_SECTORS ||
+ block_size > DATA_DEV_BLOCK_SIZE_MAX_SECTORS ||
+ !is_power_of_2(block_size)) {
+ ti->error = "Invalid block size";
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (kstrtoull(argv[3], 10, (unsigned long long *)&low_water_blocks)) {
+ ti->error = "Invalid low water mark";
+ r = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * Set default pool features.
+ */
+ memset(&pf, 0, sizeof(pf));
+ pf.zero_new_blocks = 1;
+
+ dm_consume_args(&as, 4);
+ r = parse_pool_features(&as, &pf, ti);
+ if (r)
+ goto out;
+
+ pt = kzalloc(sizeof(*pt), GFP_KERNEL);
+ if (!pt) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev,
+ block_size, &ti->error);
+ if (IS_ERR(pool)) {
+ r = PTR_ERR(pool);
+ goto out_free_pt;
+ }
+
+ pt->pool = pool;
+ pt->ti = ti;
+ pt->metadata_dev = metadata_dev;
+ pt->data_dev = data_dev;
+ pt->low_water_blocks = low_water_blocks;
+ pt->zero_new_blocks = pf.zero_new_blocks;
+ ti->num_flush_requests = 1;
+ ti->num_discard_requests = 0;
+ ti->private = pt;
+
+ pt->callbacks.congested_fn = pool_is_congested;
+ dm_table_add_target_callbacks(ti->table, &pt->callbacks);
+
+ mutex_unlock(&dm_thin_pool_table.mutex);
+
+ return 0;
+
+out_free_pt:
+ kfree(pt);
+out:
+ dm_put_device(ti, data_dev);
+out_metadata:
+ dm_put_device(ti, metadata_dev);
+out_unlock:
+ mutex_unlock(&dm_thin_pool_table.mutex);
+
+ return r;
+}
+
+static int pool_map(struct dm_target *ti, struct bio *bio,
+ union map_info *map_context)
+{
+ int r;
+ struct pool_c *pt = ti->private;
+ struct pool *pool = pt->pool;
+ unsigned long flags;
+
+ /*
+ * As this is a singleton target, ti->begin is always zero.
+ */
+ spin_lock_irqsave(&pool->lock, flags);
+ bio->bi_bdev = pt->data_dev->bdev;
+ r = DM_MAPIO_REMAPPED;
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ return r;
+}
+
+/*
+ * Retrieves the number of blocks of the data device from
+ * the superblock and compares it to the actual device size,
+ * thus resizing the data device in case it has grown.
+ *
+ * This both copes with opening preallocated data devices in the ctr
+ * being followed by a resume
+ * -and-
+ * calling the resume method individually after userspace has
+ * grown the data device in reaction to a table event.
+ */
+static int pool_preresume(struct dm_target *ti)
+{
+ int r;
+ struct pool_c *pt = ti->private;
+ struct pool *pool = pt->pool;
+ dm_block_t data_size, sb_data_size;
+
+ /*
+ * Take control of the pool object.
+ */
+ r = bind_control_target(pool, ti);
+ if (r)
+ return r;
+
+ data_size = ti->len >> pool->block_shift;
+ r = dm_pool_get_data_dev_size(pool->pmd, &sb_data_size);
+ if (r) {
+ DMERR("failed to retrieve data device size");
+ return r;
+ }
+
+ if (data_size < sb_data_size) {
+ DMERR("pool target too small, is %llu blocks (expected %llu)",
+ data_size, sb_data_size);
+ return -EINVAL;
+
+ } else if (data_size > sb_data_size) {
+ r = dm_pool_resize_data_dev(pool->pmd, data_size);
+ if (r) {
+ DMERR("failed to resize data device");
+ return r;
+ }
+
+ r = dm_pool_commit_metadata(pool->pmd);
+ if (r) {
+ DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+ __func__, r);
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+static void pool_resume(struct dm_target *ti)
+{
+ struct pool_c *pt = ti->private;
+ struct pool *pool = pt->pool;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ pool->low_water_triggered = 0;
+ pool->no_free_space = 0;
+ __requeue_bios(pool);
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ wake_worker(pool);
+}
+
+static void pool_postsuspend(struct dm_target *ti)
+{
+ int r;
+ struct pool_c *pt = ti->private;
+ struct pool *pool = pt->pool;
+
+ flush_workqueue(pool->wq);
+
+ r = dm_pool_commit_metadata(pool->pmd);
+ if (r < 0) {
+ DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+ __func__, r);
+ /* FIXME: invalidate device? error the next FUA or FLUSH bio ?*/
+ }
+}
+
+static int check_arg_count(unsigned argc, unsigned args_required)
+{
+ if (argc != args_required) {
+ DMWARN("Message received with %u arguments instead of %u.",
+ argc, args_required);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int read_dev_id(char *arg, dm_thin_id *dev_id, int warning)
+{
+ if (!kstrtoull(arg, 10, (unsigned long long *)dev_id) &&
+ *dev_id <= MAX_DEV_ID)
+ return 0;
+
+ if (warning)
+ DMWARN("Message received with invalid device id: %s", arg);
+
+ return -EINVAL;
+}
+
+static int process_create_thin_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+ dm_thin_id dev_id;
+ int r;
+
+ r = check_arg_count(argc, 2);
+ if (r)
+ return r;
+
+ r = read_dev_id(argv[1], &dev_id, 1);
+ if (r)
+ return r;
+
+ r = dm_pool_create_thin(pool->pmd, dev_id);
+ if (r) {
+ DMWARN("Creation of new thinly-provisioned device with id %s failed.",
+ argv[1]);
+ return r;
+ }
+
+ return 0;
+}
+
+static int process_create_snap_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+ dm_thin_id dev_id;
+ dm_thin_id origin_dev_id;
+ int r;
+
+ r = check_arg_count(argc, 3);
+ if (r)
+ return r;
+
+ r = read_dev_id(argv[1], &dev_id, 1);
+ if (r)
+ return r;
+
+ r = read_dev_id(argv[2], &origin_dev_id, 1);
+ if (r)
+ return r;
+
+ r = dm_pool_create_snap(pool->pmd, dev_id, origin_dev_id);
+ if (r) {
+ DMWARN("Creation of new snapshot %s of device %s failed.",
+ argv[1], argv[2]);
+ return r;
+ }
+
+ return 0;
+}
+
+static int process_delete_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+ dm_thin_id dev_id;
+ int r;
+
+ r = check_arg_count(argc, 2);
+ if (r)
+ return r;
+
+ r = read_dev_id(argv[1], &dev_id, 1);
+ if (r)
+ return r;
+
+ r = dm_pool_delete_thin_device(pool->pmd, dev_id);
+ if (r)
+ DMWARN("Deletion of thin device %s failed.", argv[1]);
+
+ return r;
+}
+
+static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+ dm_thin_id old_id, new_id;
+ int r;
+
+ r = check_arg_count(argc, 3);
+ if (r)
+ return r;
+
+ if (kstrtoull(argv[1], 10, (unsigned long long *)&old_id)) {
+ DMWARN("set_transaction_id message: Unrecognised id %s.", argv[1]);
+ return -EINVAL;
+ }
+
+ if (kstrtoull(argv[2], 10, (unsigned long long *)&new_id)) {
+ DMWARN("set_transaction_id message: Unrecognised new id %s.", argv[2]);
+ return -EINVAL;
+ }
+
+ r = dm_pool_set_metadata_transaction_id(pool->pmd, old_id, new_id);
+ if (r) {
+ DMWARN("Failed to change transaction id from %s to %s.",
+ argv[1], argv[2]);
+ return r;
+ }
+
+ return 0;
+}
+
+/*
+ * Messages supported:
+ * create_thin <dev_id>
+ * create_snap <dev_id> <origin_id>
+ * delete <dev_id>
+ * trim <dev_id> <new_size_in_sectors>
+ * set_transaction_id <current_trans_id> <new_trans_id>
+ */
+static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+ int r = -EINVAL;
+ struct pool_c *pt = ti->private;
+ struct pool *pool = pt->pool;
+
+ if (!strcasecmp(argv[0], "create_thin"))
+ r = process_create_thin_mesg(argc, argv, pool);
+
+ else if (!strcasecmp(argv[0], "create_snap"))
+ r = process_create_snap_mesg(argc, argv, pool);
+
+ else if (!strcasecmp(argv[0], "delete"))
+ r = process_delete_mesg(argc, argv, pool);
+
+ else if (!strcasecmp(argv[0], "set_transaction_id"))
+ r = process_set_transaction_id_mesg(argc, argv, pool);
+
+ else
+ DMWARN("Unrecognised thin pool target message received: %s", argv[0]);
+
+ if (!r) {
+ r = dm_pool_commit_metadata(pool->pmd);
+ if (r)
+ DMERR("%s message: dm_pool_commit_metadata() failed, error = %d",
+ argv[0], r);
+ }
+
+ return r;
+}
+
+/*
+ * Status line is:
+ * <transaction id> <used metadata sectors>/<total metadata sectors>
+ * <used data sectors>/<total data sectors> <held metadata root>
+ */
+static int pool_status(struct dm_target *ti, status_type_t type,
+ char *result, unsigned maxlen)
+{
+ int r;
+ unsigned sz = 0;
+ uint64_t transaction_id;
+ dm_block_t nr_free_blocks_data;
+ dm_block_t nr_free_blocks_metadata;
+ dm_block_t nr_blocks_data;
+ dm_block_t nr_blocks_metadata;
+ dm_block_t held_root;
+ char buf[BDEVNAME_SIZE];
+ char buf2[BDEVNAME_SIZE];
+ struct pool_c *pt = ti->private;
+ struct pool *pool = pt->pool;
+
+ switch (type) {
+ case STATUSTYPE_INFO:
+ r = dm_pool_get_metadata_transaction_id(pool->pmd,
+ &transaction_id);
+ if (r)
+ return r;
+
+ r = dm_pool_get_free_metadata_block_count(pool->pmd,
+ &nr_free_blocks_metadata);
+ if (r)
+ return r;
+
+ r = dm_pool_get_metadata_dev_size(pool->pmd, &nr_blocks_metadata);
+ if (r)
+ return r;
+
+ r = dm_pool_get_free_block_count(pool->pmd,
+ &nr_free_blocks_data);
+ if (r)
+ return r;
+
+ r = dm_pool_get_data_dev_size(pool->pmd, &nr_blocks_data);
+ if (r)
+ return r;
+
+ r = dm_pool_get_held_metadata_root(pool->pmd, &held_root);
+ if (r)
+ return r;
+
+ DMEMIT("%llu %llu/%llu %llu/%llu ",
+ (unsigned long long)transaction_id,
+ (unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata),
+ (unsigned long long)nr_blocks_metadata,
+ (unsigned long long)(nr_blocks_data - nr_free_blocks_data),
+ (unsigned long long)nr_blocks_data);
+
+ if (held_root)
+ DMEMIT("%llu", held_root);
+ else
+ DMEMIT("-");
+
+ break;
+
+ case STATUSTYPE_TABLE:
+ DMEMIT("%s %s %lu %llu ",
+ format_dev_t(buf, pt->metadata_dev->bdev->bd_dev),
+ format_dev_t(buf2, pt->data_dev->bdev->bd_dev),
+ (unsigned long)pool->sectors_per_block,
+ (unsigned long long)pt->low_water_blocks);
+
+ DMEMIT("%u ", !pool->zero_new_blocks);
+
+ if (!pool->zero_new_blocks)
+ DMEMIT("skip_block_zeroing ");
+ break;
+ }
+
+ return 0;
+}
+
+static int pool_iterate_devices(struct dm_target *ti,
+ iterate_devices_callout_fn fn, void *data)
+{
+ struct pool_c *pt = ti->private;
+
+ return fn(ti, pt->data_dev, 0, ti->len, data);
+}
+
+static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+ struct bio_vec *biovec, int max_size)
+{
+ struct pool_c *pt = ti->private;
+ struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+
+ if (!q->merge_bvec_fn)
+ return max_size;
+
+ bvm->bi_bdev = pt->data_dev->bdev;
+
+ return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
+static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+ struct pool_c *pt = ti->private;
+ struct pool *pool = pt->pool;
+
+ blk_limits_io_min(limits, 0);
+ blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
+}
+
+static struct target_type pool_target = {
+ .name = "thin-pool",
+ .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
+ DM_TARGET_IMMUTABLE,
+ .version = {1, 0, 0},
+ .module = THIS_MODULE,
+ .ctr = pool_ctr,
+ .dtr = pool_dtr,
+ .map = pool_map,
+ .postsuspend = pool_postsuspend,
+ .preresume = pool_preresume,
+ .resume = pool_resume,
+ .message = pool_message,
+ .status = pool_status,
+ .merge = pool_merge,
+ .iterate_devices = pool_iterate_devices,
+ .io_hints = pool_io_hints,
+};
+
+/*----------------------------------------------------------------
+ * Thin target methods
+ *--------------------------------------------------------------*/
+static void thin_dtr(struct dm_target *ti)
+{
+ struct thin_c *tc = ti->private;
+
+ mutex_lock(&dm_thin_pool_table.mutex);
+
+ __pool_dec(tc->pool);
+ dm_pool_close_thin_device(tc->td);
+ dm_put_device(ti, tc->pool_dev);
+ kfree(tc);
+
+ mutex_unlock(&dm_thin_pool_table.mutex);
+}
+
+/*
+ * Thin target parameters:
+ *
+ * <pool_dev> <dev_id>
+ *
+ * pool_dev: the path to the pool (eg, /dev/mapper/my_pool)
+ * dev_id: the internal device identifier
+ */
+static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+ int r;
+ struct thin_c *tc;
+ struct dm_dev *pool_dev;
+ struct mapped_device *pool_md;
+
+ mutex_lock(&dm_thin_pool_table.mutex);
+
+ if (argc != 2) {
+ ti->error = "Invalid argument count";
+ r = -EINVAL;
+ goto out_unlock;
+ }
+
+ tc = ti->private = kzalloc(sizeof(*tc), GFP_KERNEL);
+ if (!tc) {
+ ti->error = "Out of memory";
+ r = -ENOMEM;
+ goto out_unlock;
+ }
+
+ r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &pool_dev);
+ if (r) {
+ ti->error = "Error opening pool device";
+ goto bad_pool_dev;
+ }
+ tc->pool_dev = pool_dev;
+
+ if (read_dev_id(argv[1], (unsigned long long *)&tc->dev_id, 0)) {
+ ti->error = "Invalid device id";
+ r = -EINVAL;
+ goto bad_common;
+ }
+
+ pool_md = dm_get_md(tc->pool_dev->bdev->bd_dev);
+ if (!pool_md) {
+ ti->error = "Couldn't get pool mapped device";
+ r = -EINVAL;
+ goto bad_common;
+ }
+
+ tc->pool = __pool_table_lookup(pool_md);
+ if (!tc->pool) {
+ ti->error = "Couldn't find pool object";
+ r = -EINVAL;
+ goto bad_pool_lookup;
+ }
+ __pool_inc(tc->pool);
+
+ r = dm_pool_open_thin_device(tc->pool->pmd, tc->dev_id, &tc->td);
+ if (r) {
+ ti->error = "Couldn't open thin internal device";
+ goto bad_thin_open;
+ }
+
+ ti->split_io = tc->pool->sectors_per_block;
+ ti->num_flush_requests = 1;
+ ti->num_discard_requests = 0;
+ ti->discards_supported = 0;
+
+ dm_put(pool_md);
+
+ mutex_unlock(&dm_thin_pool_table.mutex);
+
+ return 0;
+
+bad_thin_open:
+ __pool_dec(tc->pool);
+bad_pool_lookup:
+ dm_put(pool_md);
+bad_common:
+ dm_put_device(ti, tc->pool_dev);
+bad_pool_dev:
+ kfree(tc);
+out_unlock:
+ mutex_unlock(&dm_thin_pool_table.mutex);
+
+ return r;
+}
+
+static int thin_map(struct dm_target *ti, struct bio *bio,
+ union map_info *map_context)
+{
+ bio->bi_sector -= ti->begin;
+
+ return thin_bio_map(ti, bio, map_context);
+}
+
+static void thin_postsuspend(struct dm_target *ti)
+{
+ if (dm_noflush_suspending(ti))
+ requeue_io((struct thin_c *)ti->private);
+}
+
+/*
+ * <nr mapped sectors> <highest mapped sector>
+ */
+static int thin_status(struct dm_target *ti, status_type_t type,
+ char *result, unsigned maxlen)
+{
+ int r;
+ ssize_t sz = 0;
+ dm_block_t mapped, highest;
+ char buf[BDEVNAME_SIZE];
+ struct thin_c *tc = ti->private;
+
+ if (!tc->td)
+ DMEMIT("-");
+ else {
+ switch (type) {
+ case STATUSTYPE_INFO:
+ r = dm_thin_get_mapped_count(tc->td, &mapped);
+ if (r)
+ return r;
+
+ r = dm_thin_get_highest_mapped_block(tc->td, &highest);
+ if (r < 0)
+ return r;
+
+ DMEMIT("%llu ", mapped * tc->pool->sectors_per_block);
+ if (r)
+ DMEMIT("%llu", ((highest + 1) *
+ tc->pool->sectors_per_block) - 1);
+ else
+ DMEMIT("-");
+ break;
+
+ case STATUSTYPE_TABLE:
+ DMEMIT("%s %lu",
+ format_dev_t(buf, tc->pool_dev->bdev->bd_dev),
+ (unsigned long) tc->dev_id);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int thin_iterate_devices(struct dm_target *ti,
+ iterate_devices_callout_fn fn, void *data)
+{
+ dm_block_t blocks;
+ struct thin_c *tc = ti->private;
+
+ /*
+ * We can't call dm_pool_get_data_dev_size() since that blocks. So
+ * we follow a more convoluted path through to the pool's target.
+ */
+ if (!tc->pool->ti)
+ return 0; /* nothing is bound */
+
+ blocks = tc->pool->ti->len >> tc->pool->block_shift;
+ if (blocks)
+ return fn(ti, tc->pool_dev, 0, tc->pool->sectors_per_block * blocks, data);
+
+ return 0;
+}
+
+static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+ struct thin_c *tc = ti->private;
+
+ blk_limits_io_min(limits, 0);
+ blk_limits_io_opt(limits, tc->pool->sectors_per_block << SECTOR_SHIFT);
+}
+
+static struct target_type thin_target = {
+ .name = "thin",
+ .version = {1, 0, 0},
+ .module = THIS_MODULE,
+ .ctr = thin_ctr,
+ .dtr = thin_dtr,
+ .map = thin_map,
+ .postsuspend = thin_postsuspend,
+ .status = thin_status,
+ .iterate_devices = thin_iterate_devices,
+ .io_hints = thin_io_hints,
+};
+
+/*----------------------------------------------------------------*/
+
+static int __init dm_thin_init(void)
+{
+ int r;
+
+ pool_table_init();
+
+ r = dm_register_target(&thin_target);
+ if (r)
+ return r;
+
+ r = dm_register_target(&pool_target);
+ if (r)
+ dm_unregister_target(&thin_target);
+
+ return r;
+}
+
+static void dm_thin_exit(void)
+{
+ dm_unregister_target(&thin_target);
+ dm_unregister_target(&pool_target);
+}
+
+module_init(dm_thin_init);
+module_exit(dm_thin_exit);
+
+MODULE_DESCRIPTION(DM_NAME "device-mapper thin provisioning target");
+MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 52b39f335bb3..6b6616a41baa 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -25,6 +25,16 @@
#define DM_MSG_PREFIX "core"
+#ifdef CONFIG_PRINTK
+/*
+ * ratelimit state to be used in DMXXX_LIMIT().
+ */
+DEFINE_RATELIMIT_STATE(dm_ratelimit_state,
+ DEFAULT_RATELIMIT_INTERVAL,
+ DEFAULT_RATELIMIT_BURST);
+EXPORT_SYMBOL(dm_ratelimit_state);
+#endif
+
/*
* Cookies are numeric values sent with CHANGE and REMOVE
* uevents while resuming, removing or renaming the device.
@@ -130,6 +140,8 @@ struct mapped_device {
/* Protect queue and type against concurrent access. */
struct mutex type_lock;
+ struct target_type *immutable_target_type;
+
struct gendisk *disk;
char name[16];
@@ -2086,6 +2098,8 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
write_lock_irqsave(&md->map_lock, flags);
old_map = md->map;
md->map = t;
+ md->immutable_target_type = dm_table_get_immutable_target_type(t);
+
dm_table_set_restrictions(t, q, limits);
if (merge_is_optional)
set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
@@ -2156,6 +2170,11 @@ unsigned dm_get_md_type(struct mapped_device *md)
return md->type;
}
+struct target_type *dm_get_immutable_target_type(struct mapped_device *md)
+{
+ return md->immutable_target_type;
+}
+
/*
* Fully initialize a request-based queue (->elevator, ->request_fn, etc).
*/
@@ -2231,6 +2250,7 @@ struct mapped_device *dm_get_md(dev_t dev)
return md;
}
+EXPORT_SYMBOL_GPL(dm_get_md);
void *dm_get_mdptr(struct mapped_device *md)
{
@@ -2316,7 +2336,6 @@ static int dm_wait_for_completion(struct mapped_device *md, int interruptible)
while (1) {
set_current_state(interruptible);
- smp_mb();
if (!md_in_flight(md))
break;
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 6745dbd278a4..b7dacd59d8d7 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -60,6 +60,7 @@ int dm_table_resume_targets(struct dm_table *t);
int dm_table_any_congested(struct dm_table *t, int bdi_bits);
int dm_table_any_busy_target(struct dm_table *t);
unsigned dm_table_get_type(struct dm_table *t);
+struct target_type *dm_table_get_immutable_target_type(struct dm_table *t);
bool dm_table_request_based(struct dm_table *t);
bool dm_table_supports_discards(struct dm_table *t);
int dm_table_alloc_md_mempools(struct dm_table *t);
@@ -72,6 +73,7 @@ void dm_lock_md_type(struct mapped_device *md);
void dm_unlock_md_type(struct mapped_device *md);
void dm_set_md_type(struct mapped_device *md, unsigned type);
unsigned dm_get_md_type(struct mapped_device *md);
+struct target_type *dm_get_immutable_target_type(struct mapped_device *md);
int dm_setup_md_queue(struct mapped_device *md);
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index 23078dabb6df..60816b132c2e 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -81,16 +81,16 @@ static void faulty_fail(struct bio *bio, int error)
bio_io_error(b);
}
-typedef struct faulty_conf {
+struct faulty_conf {
int period[Modes];
atomic_t counters[Modes];
sector_t faults[MaxFault];
int modes[MaxFault];
int nfaults;
- mdk_rdev_t *rdev;
-} conf_t;
+ struct md_rdev *rdev;
+};
-static int check_mode(conf_t *conf, int mode)
+static int check_mode(struct faulty_conf *conf, int mode)
{
if (conf->period[mode] == 0 &&
atomic_read(&conf->counters[mode]) <= 0)
@@ -105,7 +105,7 @@ static int check_mode(conf_t *conf, int mode)
return 0;
}
-static int check_sector(conf_t *conf, sector_t start, sector_t end, int dir)
+static int check_sector(struct faulty_conf *conf, sector_t start, sector_t end, int dir)
{
/* If we find a ReadFixable sector, we fix it ... */
int i;
@@ -129,7 +129,7 @@ static int check_sector(conf_t *conf, sector_t start, sector_t end, int dir)
return 0;
}
-static void add_sector(conf_t *conf, sector_t start, int mode)
+static void add_sector(struct faulty_conf *conf, sector_t start, int mode)
{
int i;
int n = conf->nfaults;
@@ -169,9 +169,9 @@ static void add_sector(conf_t *conf, sector_t start, int mode)
conf->nfaults = n+1;
}
-static int make_request(mddev_t *mddev, struct bio *bio)
+static int make_request(struct mddev *mddev, struct bio *bio)
{
- conf_t *conf = mddev->private;
+ struct faulty_conf *conf = mddev->private;
int failit = 0;
if (bio_data_dir(bio) == WRITE) {
@@ -222,9 +222,9 @@ static int make_request(mddev_t *mddev, struct bio *bio)
}
}
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
{
- conf_t *conf = mddev->private;
+ struct faulty_conf *conf = mddev->private;
int n;
if ((n=atomic_read(&conf->counters[WriteTransient])) != 0)
@@ -255,11 +255,11 @@ static void status(struct seq_file *seq, mddev_t *mddev)
}
-static int reshape(mddev_t *mddev)
+static int reshape(struct mddev *mddev)
{
int mode = mddev->new_layout & ModeMask;
int count = mddev->new_layout >> ModeShift;
- conf_t *conf = mddev->private;
+ struct faulty_conf *conf = mddev->private;
if (mddev->new_layout < 0)
return 0;
@@ -284,7 +284,7 @@ static int reshape(mddev_t *mddev)
return 0;
}
-static sector_t faulty_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t faulty_size(struct mddev *mddev, sector_t sectors, int raid_disks)
{
WARN_ONCE(raid_disks,
"%s does not support generic reshape\n", __func__);
@@ -295,11 +295,11 @@ static sector_t faulty_size(mddev_t *mddev, sector_t sectors, int raid_disks)
return sectors;
}
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int i;
- conf_t *conf;
+ struct faulty_conf *conf;
if (md_check_no_bitmap(mddev))
return -EINVAL;
@@ -325,16 +325,16 @@ static int run(mddev_t *mddev)
return 0;
}
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
{
- conf_t *conf = mddev->private;
+ struct faulty_conf *conf = mddev->private;
kfree(conf);
mddev->private = NULL;
return 0;
}
-static struct mdk_personality faulty_personality =
+static struct md_personality faulty_personality =
{
.name = "faulty",
.level = LEVEL_FAULTY,
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 6cd2c313e800..10c5844460cb 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -26,10 +26,10 @@
/*
* find which device holds a particular offset
*/
-static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
+static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector)
{
int lo, mid, hi;
- linear_conf_t *conf;
+ struct linear_conf *conf;
lo = 0;
hi = mddev->raid_disks - 1;
@@ -63,8 +63,8 @@ static int linear_mergeable_bvec(struct request_queue *q,
struct bvec_merge_data *bvm,
struct bio_vec *biovec)
{
- mddev_t *mddev = q->queuedata;
- dev_info_t *dev0;
+ struct mddev *mddev = q->queuedata;
+ struct dev_info *dev0;
unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
@@ -89,8 +89,8 @@ static int linear_mergeable_bvec(struct request_queue *q,
static int linear_congested(void *data, int bits)
{
- mddev_t *mddev = data;
- linear_conf_t *conf;
+ struct mddev *mddev = data;
+ struct linear_conf *conf;
int i, ret = 0;
if (mddev_congested(mddev, bits))
@@ -108,9 +108,9 @@ static int linear_congested(void *data, int bits)
return ret;
}
-static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t linear_size(struct mddev *mddev, sector_t sectors, int raid_disks)
{
- linear_conf_t *conf;
+ struct linear_conf *conf;
sector_t array_sectors;
rcu_read_lock();
@@ -123,13 +123,13 @@ static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks)
return array_sectors;
}
-static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
+static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
{
- linear_conf_t *conf;
- mdk_rdev_t *rdev;
+ struct linear_conf *conf;
+ struct md_rdev *rdev;
int i, cnt;
- conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
+ conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(struct dev_info),
GFP_KERNEL);
if (!conf)
return NULL;
@@ -139,7 +139,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
list_for_each_entry(rdev, &mddev->disks, same_set) {
int j = rdev->raid_disk;
- dev_info_t *disk = conf->disks + j;
+ struct dev_info *disk = conf->disks + j;
sector_t sectors;
if (j < 0 || j >= raid_disks || disk->rdev) {
@@ -194,9 +194,9 @@ out:
return NULL;
}
-static int linear_run (mddev_t *mddev)
+static int linear_run (struct mddev *mddev)
{
- linear_conf_t *conf;
+ struct linear_conf *conf;
if (md_check_no_bitmap(mddev))
return -EINVAL;
@@ -213,7 +213,7 @@ static int linear_run (mddev_t *mddev)
return md_integrity_register(mddev);
}
-static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
+static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
{
/* Adding a drive to a linear array allows the array to grow.
* It is permitted if the new drive has a matching superblock
@@ -223,7 +223,7 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
* The current one is never freed until the array is stopped.
* This avoids races.
*/
- linear_conf_t *newconf, *oldconf;
+ struct linear_conf *newconf, *oldconf;
if (rdev->saved_raid_disk != mddev->raid_disks)
return -EINVAL;
@@ -245,9 +245,9 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
return 0;
}
-static int linear_stop (mddev_t *mddev)
+static int linear_stop (struct mddev *mddev)
{
- linear_conf_t *conf = mddev->private;
+ struct linear_conf *conf = mddev->private;
/*
* We do not require rcu protection here since
@@ -264,9 +264,9 @@ static int linear_stop (mddev_t *mddev)
return 0;
}
-static int linear_make_request (mddev_t *mddev, struct bio *bio)
+static int linear_make_request (struct mddev *mddev, struct bio *bio)
{
- dev_info_t *tmp_dev;
+ struct dev_info *tmp_dev;
sector_t start_sector;
if (unlikely(bio->bi_rw & REQ_FLUSH)) {
@@ -323,14 +323,14 @@ static int linear_make_request (mddev_t *mddev, struct bio *bio)
return 1;
}
-static void linear_status (struct seq_file *seq, mddev_t *mddev)
+static void linear_status (struct seq_file *seq, struct mddev *mddev)
{
seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2);
}
-static struct mdk_personality linear_personality =
+static struct md_personality linear_personality =
{
.name = "linear",
.level = LEVEL_LINEAR,
diff --git a/drivers/md/linear.h b/drivers/md/linear.h
index 2f2da05b2ce9..b685ddd7d7f7 100644
--- a/drivers/md/linear.h
+++ b/drivers/md/linear.h
@@ -2,20 +2,14 @@
#define _LINEAR_H
struct dev_info {
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t end_sector;
};
-typedef struct dev_info dev_info_t;
-
-struct linear_private_data
+struct linear_conf
{
struct rcu_head rcu;
sector_t array_sectors;
- dev_info_t disks[0];
+ struct dev_info disks[0];
};
-
-
-typedef struct linear_private_data linear_conf_t;
-
#endif
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 5c95ccb59500..266e82ebaf11 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -54,9 +54,6 @@
#include "md.h"
#include "bitmap.h"
-#define DEBUG 0
-#define dprintk(x...) ((void)(DEBUG && printk(x)))
-
#ifndef MODULE
static void autostart_arrays(int part);
#endif
@@ -98,13 +95,13 @@ static struct workqueue_struct *md_misc_wq;
static int sysctl_speed_limit_min = 1000;
static int sysctl_speed_limit_max = 200000;
-static inline int speed_min(mddev_t *mddev)
+static inline int speed_min(struct mddev *mddev)
{
return mddev->sync_speed_min ?
mddev->sync_speed_min : sysctl_speed_limit_min;
}
-static inline int speed_max(mddev_t *mddev)
+static inline int speed_max(struct mddev *mddev)
{
return mddev->sync_speed_max ?
mddev->sync_speed_max : sysctl_speed_limit_max;
@@ -160,7 +157,7 @@ static int start_readonly;
static void mddev_bio_destructor(struct bio *bio)
{
- mddev_t *mddev, **mddevp;
+ struct mddev *mddev, **mddevp;
mddevp = (void*)bio;
mddev = mddevp[-1];
@@ -169,10 +166,10 @@ static void mddev_bio_destructor(struct bio *bio)
}
struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
- mddev_t *mddev)
+ struct mddev *mddev)
{
struct bio *b;
- mddev_t **mddevp;
+ struct mddev **mddevp;
if (!mddev || !mddev->bio_set)
return bio_alloc(gfp_mask, nr_iovecs);
@@ -189,10 +186,10 @@ struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
EXPORT_SYMBOL_GPL(bio_alloc_mddev);
struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
- mddev_t *mddev)
+ struct mddev *mddev)
{
struct bio *b;
- mddev_t **mddevp;
+ struct mddev **mddevp;
if (!mddev || !mddev->bio_set)
return bio_clone(bio, gfp_mask);
@@ -281,7 +278,7 @@ EXPORT_SYMBOL_GPL(md_trim_bio);
*/
static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
static atomic_t md_event_count;
-void md_new_event(mddev_t *mddev)
+void md_new_event(struct mddev *mddev)
{
atomic_inc(&md_event_count);
wake_up(&md_event_waiters);
@@ -291,7 +288,7 @@ EXPORT_SYMBOL_GPL(md_new_event);
/* Alternate version that can be called from interrupts
* when calling sysfs_notify isn't needed.
*/
-static void md_new_event_inintr(mddev_t *mddev)
+static void md_new_event_inintr(struct mddev *mddev)
{
atomic_inc(&md_event_count);
wake_up(&md_event_waiters);
@@ -312,19 +309,19 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
* Any code which breaks out of this loop while own
* a reference to the current mddev and must mddev_put it.
*/
-#define for_each_mddev(mddev,tmp) \
+#define for_each_mddev(_mddev,_tmp) \
\
for (({ spin_lock(&all_mddevs_lock); \
- tmp = all_mddevs.next; \
- mddev = NULL;}); \
- ({ if (tmp != &all_mddevs) \
- mddev_get(list_entry(tmp, mddev_t, all_mddevs));\
+ _tmp = all_mddevs.next; \
+ _mddev = NULL;}); \
+ ({ if (_tmp != &all_mddevs) \
+ mddev_get(list_entry(_tmp, struct mddev, all_mddevs));\
spin_unlock(&all_mddevs_lock); \
- if (mddev) mddev_put(mddev); \
- mddev = list_entry(tmp, mddev_t, all_mddevs); \
- tmp != &all_mddevs;}); \
+ if (_mddev) mddev_put(_mddev); \
+ _mddev = list_entry(_tmp, struct mddev, all_mddevs); \
+ _tmp != &all_mddevs;}); \
({ spin_lock(&all_mddevs_lock); \
- tmp = tmp->next;}) \
+ _tmp = _tmp->next;}) \
)
@@ -338,7 +335,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
static int md_make_request(struct request_queue *q, struct bio *bio)
{
const int rw = bio_data_dir(bio);
- mddev_t *mddev = q->queuedata;
+ struct mddev *mddev = q->queuedata;
int rv;
int cpu;
unsigned int sectors;
@@ -390,7 +387,7 @@ static int md_make_request(struct request_queue *q, struct bio *bio)
* Once ->stop is called and completes, the module will be completely
* unused.
*/
-void mddev_suspend(mddev_t *mddev)
+void mddev_suspend(struct mddev *mddev)
{
BUG_ON(mddev->suspended);
mddev->suspended = 1;
@@ -400,7 +397,7 @@ void mddev_suspend(mddev_t *mddev)
}
EXPORT_SYMBOL_GPL(mddev_suspend);
-void mddev_resume(mddev_t *mddev)
+void mddev_resume(struct mddev *mddev)
{
mddev->suspended = 0;
wake_up(&mddev->sb_wait);
@@ -411,7 +408,7 @@ void mddev_resume(mddev_t *mddev)
}
EXPORT_SYMBOL_GPL(mddev_resume);
-int mddev_congested(mddev_t *mddev, int bits)
+int mddev_congested(struct mddev *mddev, int bits)
{
return mddev->suspended;
}
@@ -423,8 +420,8 @@ EXPORT_SYMBOL(mddev_congested);
static void md_end_flush(struct bio *bio, int err)
{
- mdk_rdev_t *rdev = bio->bi_private;
- mddev_t *mddev = rdev->mddev;
+ struct md_rdev *rdev = bio->bi_private;
+ struct mddev *mddev = rdev->mddev;
rdev_dec_pending(rdev, mddev);
@@ -439,8 +436,8 @@ static void md_submit_flush_data(struct work_struct *ws);
static void submit_flushes(struct work_struct *ws)
{
- mddev_t *mddev = container_of(ws, mddev_t, flush_work);
- mdk_rdev_t *rdev;
+ struct mddev *mddev = container_of(ws, struct mddev, flush_work);
+ struct md_rdev *rdev;
INIT_WORK(&mddev->flush_work, md_submit_flush_data);
atomic_set(&mddev->flush_pending, 1);
@@ -472,7 +469,7 @@ static void submit_flushes(struct work_struct *ws)
static void md_submit_flush_data(struct work_struct *ws)
{
- mddev_t *mddev = container_of(ws, mddev_t, flush_work);
+ struct mddev *mddev = container_of(ws, struct mddev, flush_work);
struct bio *bio = mddev->flush_bio;
if (bio->bi_size == 0)
@@ -488,7 +485,7 @@ static void md_submit_flush_data(struct work_struct *ws)
wake_up(&mddev->sb_wait);
}
-void md_flush_request(mddev_t *mddev, struct bio *bio)
+void md_flush_request(struct mddev *mddev, struct bio *bio)
{
spin_lock_irq(&mddev->write_lock);
wait_event_lock_irq(mddev->sb_wait,
@@ -512,7 +509,7 @@ EXPORT_SYMBOL(md_flush_request);
*/
struct md_plug_cb {
struct blk_plug_cb cb;
- mddev_t *mddev;
+ struct mddev *mddev;
};
static void plugger_unplug(struct blk_plug_cb *cb)
@@ -526,7 +523,7 @@ static void plugger_unplug(struct blk_plug_cb *cb)
/* Check that an unplug wakeup will come shortly.
* If not, wakeup the md thread immediately
*/
-int mddev_check_plugged(mddev_t *mddev)
+int mddev_check_plugged(struct mddev *mddev)
{
struct blk_plug *plug = current->plug;
struct md_plug_cb *mdcb;
@@ -558,7 +555,7 @@ int mddev_check_plugged(mddev_t *mddev)
}
EXPORT_SYMBOL_GPL(mddev_check_plugged);
-static inline mddev_t *mddev_get(mddev_t *mddev)
+static inline struct mddev *mddev_get(struct mddev *mddev)
{
atomic_inc(&mddev->active);
return mddev;
@@ -566,7 +563,7 @@ static inline mddev_t *mddev_get(mddev_t *mddev)
static void mddev_delayed_delete(struct work_struct *ws);
-static void mddev_put(mddev_t *mddev)
+static void mddev_put(struct mddev *mddev)
{
struct bio_set *bs = NULL;
@@ -595,7 +592,7 @@ static void mddev_put(mddev_t *mddev)
bioset_free(bs);
}
-void mddev_init(mddev_t *mddev)
+void mddev_init(struct mddev *mddev)
{
mutex_init(&mddev->open_mutex);
mutex_init(&mddev->reconfig_mutex);
@@ -618,9 +615,9 @@ void mddev_init(mddev_t *mddev)
}
EXPORT_SYMBOL_GPL(mddev_init);
-static mddev_t * mddev_find(dev_t unit)
+static struct mddev * mddev_find(dev_t unit)
{
- mddev_t *mddev, *new = NULL;
+ struct mddev *mddev, *new = NULL;
if (unit && MAJOR(unit) != MD_MAJOR)
unit &= ~((1<<MdpMinorShift)-1);
@@ -692,24 +689,24 @@ static mddev_t * mddev_find(dev_t unit)
goto retry;
}
-static inline int mddev_lock(mddev_t * mddev)
+static inline int mddev_lock(struct mddev * mddev)
{
return mutex_lock_interruptible(&mddev->reconfig_mutex);
}
-static inline int mddev_is_locked(mddev_t *mddev)
+static inline int mddev_is_locked(struct mddev *mddev)
{
return mutex_is_locked(&mddev->reconfig_mutex);
}
-static inline int mddev_trylock(mddev_t * mddev)
+static inline int mddev_trylock(struct mddev * mddev)
{
return mutex_trylock(&mddev->reconfig_mutex);
}
static struct attribute_group md_redundancy_group;
-static void mddev_unlock(mddev_t * mddev)
+static void mddev_unlock(struct mddev * mddev)
{
if (mddev->to_remove) {
/* These cannot be removed under reconfig_mutex as
@@ -744,17 +741,17 @@ static void mddev_unlock(mddev_t * mddev)
} else
mutex_unlock(&mddev->reconfig_mutex);
- /* was we've dropped the mutex we need a spinlock to
- * make sur the thread doesn't disappear
+ /* As we've dropped the mutex we need a spinlock to
+ * make sure the thread doesn't disappear
*/
spin_lock(&pers_lock);
md_wakeup_thread(mddev->thread);
spin_unlock(&pers_lock);
}
-static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
+static struct md_rdev * find_rdev_nr(struct mddev *mddev, int nr)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->desc_nr == nr)
@@ -763,9 +760,9 @@ static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
return NULL;
}
-static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
+static struct md_rdev * find_rdev(struct mddev * mddev, dev_t dev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->bdev->bd_dev == dev)
@@ -774,9 +771,9 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
return NULL;
}
-static struct mdk_personality *find_pers(int level, char *clevel)
+static struct md_personality *find_pers(int level, char *clevel)
{
- struct mdk_personality *pers;
+ struct md_personality *pers;
list_for_each_entry(pers, &pers_list, list) {
if (level != LEVEL_NONE && pers->level == level)
return pers;
@@ -787,13 +784,13 @@ static struct mdk_personality *find_pers(int level, char *clevel)
}
/* return the offset of the super block in 512byte sectors */
-static inline sector_t calc_dev_sboffset(mdk_rdev_t *rdev)
+static inline sector_t calc_dev_sboffset(struct md_rdev *rdev)
{
sector_t num_sectors = i_size_read(rdev->bdev->bd_inode) / 512;
return MD_NEW_SIZE_SECTORS(num_sectors);
}
-static int alloc_disk_sb(mdk_rdev_t * rdev)
+static int alloc_disk_sb(struct md_rdev * rdev)
{
if (rdev->sb_page)
MD_BUG();
@@ -807,7 +804,7 @@ static int alloc_disk_sb(mdk_rdev_t * rdev)
return 0;
}
-static void free_disk_sb(mdk_rdev_t * rdev)
+static void free_disk_sb(struct md_rdev * rdev)
{
if (rdev->sb_page) {
put_page(rdev->sb_page);
@@ -825,8 +822,8 @@ static void free_disk_sb(mdk_rdev_t * rdev)
static void super_written(struct bio *bio, int error)
{
- mdk_rdev_t *rdev = bio->bi_private;
- mddev_t *mddev = rdev->mddev;
+ struct md_rdev *rdev = bio->bi_private;
+ struct mddev *mddev = rdev->mddev;
if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags)) {
printk("md: super_written gets error=%d, uptodate=%d\n",
@@ -840,7 +837,7 @@ static void super_written(struct bio *bio, int error)
bio_put(bio);
}
-void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
sector_t sector, int size, struct page *page)
{
/* write first size bytes of page to sector of rdev
@@ -861,7 +858,7 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
submit_bio(WRITE_FLUSH_FUA, bio);
}
-void md_super_wait(mddev_t *mddev)
+void md_super_wait(struct mddev *mddev)
{
/* wait for all superblock writes that were scheduled to complete */
DEFINE_WAIT(wq);
@@ -879,7 +876,7 @@ static void bi_complete(struct bio *bio, int error)
complete((struct completion*)bio->bi_private);
}
-int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size,
+int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
struct page *page, int rw, bool metadata_op)
{
struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev);
@@ -907,7 +904,7 @@ int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size,
}
EXPORT_SYMBOL_GPL(sync_page_io);
-static int read_disk_sb(mdk_rdev_t * rdev, int size)
+static int read_disk_sb(struct md_rdev * rdev, int size)
{
char b[BDEVNAME_SIZE];
if (!rdev->sb_page) {
@@ -1014,7 +1011,7 @@ static unsigned int calc_sb_csum(mdp_super_t * sb)
* We rely on user-space to write the initial superblock, and support
* reading and updating of superblocks.
* Interface methods are:
- * int load_super(mdk_rdev_t *dev, mdk_rdev_t *refdev, int minor_version)
+ * int load_super(struct md_rdev *dev, struct md_rdev *refdev, int minor_version)
* loads and validates a superblock on dev.
* if refdev != NULL, compare superblocks on both devices
* Return:
@@ -1024,13 +1021,13 @@ static unsigned int calc_sb_csum(mdp_super_t * sb)
* -EINVAL superblock incompatible or invalid
* -othererror e.g. -EIO
*
- * int validate_super(mddev_t *mddev, mdk_rdev_t *dev)
+ * int validate_super(struct mddev *mddev, struct md_rdev *dev)
* Verify that dev is acceptable into mddev.
* The first time, mddev->raid_disks will be 0, and data from
* dev should be merged in. Subsequent calls check that dev
* is new enough. Return 0 or -EINVAL
*
- * void sync_super(mddev_t *mddev, mdk_rdev_t *dev)
+ * void sync_super(struct mddev *mddev, struct md_rdev *dev)
* Update the superblock for rdev with data in mddev
* This does not write to disc.
*
@@ -1039,11 +1036,11 @@ static unsigned int calc_sb_csum(mdp_super_t * sb)
struct super_type {
char *name;
struct module *owner;
- int (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev,
+ int (*load_super)(struct md_rdev *rdev, struct md_rdev *refdev,
int minor_version);
- int (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev);
- void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
- unsigned long long (*rdev_size_change)(mdk_rdev_t *rdev,
+ int (*validate_super)(struct mddev *mddev, struct md_rdev *rdev);
+ void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev);
+ unsigned long long (*rdev_size_change)(struct md_rdev *rdev,
sector_t num_sectors);
};
@@ -1055,7 +1052,7 @@ struct super_type {
* has a bitmap. Otherwise, it returns 0.
*
*/
-int md_check_no_bitmap(mddev_t *mddev)
+int md_check_no_bitmap(struct mddev *mddev)
{
if (!mddev->bitmap_info.file && !mddev->bitmap_info.offset)
return 0;
@@ -1068,7 +1065,7 @@ EXPORT_SYMBOL(md_check_no_bitmap);
/*
* load_super for 0.90.0
*/
-static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
{
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
mdp_super_t *sb;
@@ -1163,7 +1160,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
/*
* validate_super for 0.90.0
*/
-static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
{
mdp_disk_t *desc;
mdp_super_t *sb = page_address(rdev->sb_page);
@@ -1275,10 +1272,10 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
/*
* sync_super for 0.90.0
*/
-static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_90_sync(struct mddev *mddev, struct md_rdev *rdev)
{
mdp_super_t *sb;
- mdk_rdev_t *rdev2;
+ struct md_rdev *rdev2;
int next_spare = mddev->raid_disks;
@@ -1419,7 +1416,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
* rdev_size_change for 0.90.0
*/
static unsigned long long
-super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
{
if (num_sectors && num_sectors < rdev->mddev->dev_sectors)
return 0; /* component must fit device */
@@ -1469,7 +1466,7 @@ static __le32 calc_sb_1_csum(struct mdp_superblock_1 * sb)
static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
int acknowledged);
-static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
{
struct mdp_superblock_1 *sb;
int ret;
@@ -1625,7 +1622,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
return ret;
}
-static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
{
struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
__u64 ev1 = le64_to_cpu(sb->events);
@@ -1726,10 +1723,10 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
return 0;
}
-static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
{
struct mdp_superblock_1 *sb;
- mdk_rdev_t *rdev2;
+ struct md_rdev *rdev2;
int max_dev, i;
/* make rdev->sb match mddev and rdev data. */
@@ -1851,7 +1848,7 @@ retry:
}
static unsigned long long
-super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
{
struct mdp_superblock_1 *sb;
sector_t max_sectors;
@@ -1905,7 +1902,7 @@ static struct super_type super_types[] = {
},
};
-static void sync_super(mddev_t *mddev, mdk_rdev_t *rdev)
+static void sync_super(struct mddev *mddev, struct md_rdev *rdev)
{
if (mddev->sync_super) {
mddev->sync_super(mddev, rdev);
@@ -1917,9 +1914,9 @@ static void sync_super(mddev_t *mddev, mdk_rdev_t *rdev)
super_types[mddev->major_version].sync_super(mddev, rdev);
}
-static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
+static int match_mddev_units(struct mddev *mddev1, struct mddev *mddev2)
{
- mdk_rdev_t *rdev, *rdev2;
+ struct md_rdev *rdev, *rdev2;
rcu_read_lock();
rdev_for_each_rcu(rdev, mddev1)
@@ -1942,9 +1939,9 @@ static LIST_HEAD(pending_raid_disks);
* from the array. It only succeeds if all working and active component devices
* are integrity capable with matching profiles.
*/
-int md_integrity_register(mddev_t *mddev)
+int md_integrity_register(struct mddev *mddev)
{
- mdk_rdev_t *rdev, *reference = NULL;
+ struct md_rdev *rdev, *reference = NULL;
if (list_empty(&mddev->disks))
return 0; /* nothing to do */
@@ -1989,7 +1986,7 @@ int md_integrity_register(mddev_t *mddev)
EXPORT_SYMBOL(md_integrity_register);
/* Disable data integrity if non-capable/non-matching disk is being added */
-void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
{
struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk);
@@ -2006,7 +2003,7 @@ void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
}
EXPORT_SYMBOL(md_integrity_add_rdev);
-static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
+static int bind_rdev_to_array(struct md_rdev * rdev, struct mddev * mddev)
{
char b[BDEVNAME_SIZE];
struct kobject *ko;
@@ -2086,12 +2083,12 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
static void md_delayed_delete(struct work_struct *ws)
{
- mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work);
+ struct md_rdev *rdev = container_of(ws, struct md_rdev, del_work);
kobject_del(&rdev->kobj);
kobject_put(&rdev->kobj);
}
-static void unbind_rdev_from_array(mdk_rdev_t * rdev)
+static void unbind_rdev_from_array(struct md_rdev * rdev)
{
char b[BDEVNAME_SIZE];
if (!rdev->mddev) {
@@ -2123,14 +2120,14 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
* otherwise reused by a RAID array (or any other kernel
* subsystem), by bd_claiming the device.
*/
-static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
+static int lock_rdev(struct md_rdev *rdev, dev_t dev, int shared)
{
int err = 0;
struct block_device *bdev;
char b[BDEVNAME_SIZE];
bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
- shared ? (mdk_rdev_t *)lock_rdev : rdev);
+ shared ? (struct md_rdev *)lock_rdev : rdev);
if (IS_ERR(bdev)) {
printk(KERN_ERR "md: could not open %s.\n",
__bdevname(dev, b));
@@ -2140,7 +2137,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
return err;
}
-static void unlock_rdev(mdk_rdev_t *rdev)
+static void unlock_rdev(struct md_rdev *rdev)
{
struct block_device *bdev = rdev->bdev;
rdev->bdev = NULL;
@@ -2151,7 +2148,7 @@ static void unlock_rdev(mdk_rdev_t *rdev)
void md_autodetect_dev(dev_t dev);
-static void export_rdev(mdk_rdev_t * rdev)
+static void export_rdev(struct md_rdev * rdev)
{
char b[BDEVNAME_SIZE];
printk(KERN_INFO "md: export_rdev(%s)\n",
@@ -2167,15 +2164,15 @@ static void export_rdev(mdk_rdev_t * rdev)
kobject_put(&rdev->kobj);
}
-static void kick_rdev_from_array(mdk_rdev_t * rdev)
+static void kick_rdev_from_array(struct md_rdev * rdev)
{
unbind_rdev_from_array(rdev);
export_rdev(rdev);
}
-static void export_array(mddev_t *mddev)
+static void export_array(struct mddev *mddev)
{
- mdk_rdev_t *rdev, *tmp;
+ struct md_rdev *rdev, *tmp;
rdev_for_each(rdev, tmp, mddev) {
if (!rdev->mddev) {
@@ -2271,7 +2268,7 @@ static void print_sb_1(struct mdp_superblock_1 *sb)
);
}
-static void print_rdev(mdk_rdev_t *rdev, int major_version)
+static void print_rdev(struct md_rdev *rdev, int major_version)
{
char b[BDEVNAME_SIZE];
printk(KERN_INFO "md: rdev %s, Sect:%08llu F:%d S:%d DN:%u\n",
@@ -2295,8 +2292,8 @@ static void print_rdev(mdk_rdev_t *rdev, int major_version)
static void md_print_devices(void)
{
struct list_head *tmp;
- mdk_rdev_t *rdev;
- mddev_t *mddev;
+ struct md_rdev *rdev;
+ struct mddev *mddev;
char b[BDEVNAME_SIZE];
printk("\n");
@@ -2321,7 +2318,7 @@ static void md_print_devices(void)
}
-static void sync_sbs(mddev_t * mddev, int nospares)
+static void sync_sbs(struct mddev * mddev, int nospares)
{
/* Update each superblock (in-memory image), but
* if we are allowed to, skip spares which already
@@ -2329,7 +2326,7 @@ static void sync_sbs(mddev_t * mddev, int nospares)
* (which would mean they aren't being marked as dirty
* with the rest of the array)
*/
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->sb_events == mddev->events ||
(nospares &&
@@ -2344,9 +2341,9 @@ static void sync_sbs(mddev_t * mddev, int nospares)
}
}
-static void md_update_sb(mddev_t * mddev, int force_change)
+static void md_update_sb(struct mddev * mddev, int force_change)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int sync_req;
int nospares = 0;
int any_badblocks_changed = 0;
@@ -2442,27 +2439,24 @@ repeat:
sync_sbs(mddev, nospares);
spin_unlock_irq(&mddev->write_lock);
- dprintk(KERN_INFO
- "md: updating %s RAID superblock on device (in sync %d)\n",
- mdname(mddev),mddev->in_sync);
+ pr_debug("md: updating %s RAID superblock on device (in sync %d)\n",
+ mdname(mddev), mddev->in_sync);
bitmap_update_sb(mddev->bitmap);
list_for_each_entry(rdev, &mddev->disks, same_set) {
char b[BDEVNAME_SIZE];
- dprintk(KERN_INFO "md: ");
+
if (rdev->sb_loaded != 1)
continue; /* no noise on spare devices */
- if (test_bit(Faulty, &rdev->flags))
- dprintk("(skipping faulty ");
- dprintk("%s ", bdevname(rdev->bdev,b));
- if (!test_bit(Faulty, &rdev->flags)) {
+ if (!test_bit(Faulty, &rdev->flags) &&
+ rdev->saved_raid_disk == -1) {
md_super_write(mddev,rdev,
rdev->sb_start, rdev->sb_size,
rdev->sb_page);
- dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
- bdevname(rdev->bdev,b),
- (unsigned long long)rdev->sb_start);
+ pr_debug("md: (write) %s's sb offset: %llu\n",
+ bdevname(rdev->bdev, b),
+ (unsigned long long)rdev->sb_start);
rdev->sb_events = mddev->events;
if (rdev->badblocks.size) {
md_super_write(mddev, rdev,
@@ -2472,8 +2466,12 @@ repeat:
rdev->badblocks.size = 0;
}
- } else
- dprintk(")\n");
+ } else if (test_bit(Faulty, &rdev->flags))
+ pr_debug("md: %s (skipping faulty)\n",
+ bdevname(rdev->bdev, b));
+ else
+ pr_debug("(skipping incremental s/r ");
+
if (mddev->level == LEVEL_MULTIPATH)
/* only need to write one superblock... */
break;
@@ -2527,12 +2525,12 @@ static int cmd_match(const char *cmd, const char *str)
struct rdev_sysfs_entry {
struct attribute attr;
- ssize_t (*show)(mdk_rdev_t *, char *);
- ssize_t (*store)(mdk_rdev_t *, const char *, size_t);
+ ssize_t (*show)(struct md_rdev *, char *);
+ ssize_t (*store)(struct md_rdev *, const char *, size_t);
};
static ssize_t
-state_show(mdk_rdev_t *rdev, char *page)
+state_show(struct md_rdev *rdev, char *page)
{
char *sep = "";
size_t len = 0;
@@ -2568,7 +2566,7 @@ state_show(mdk_rdev_t *rdev, char *page)
}
static ssize_t
-state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+state_store(struct md_rdev *rdev, const char *buf, size_t len)
{
/* can write
* faulty - simulates an error
@@ -2592,7 +2590,7 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
if (rdev->raid_disk >= 0)
err = -EBUSY;
else {
- mddev_t *mddev = rdev->mddev;
+ struct mddev *mddev = rdev->mddev;
kick_rdev_from_array(rdev);
if (mddev->pers)
md_update_sb(mddev, 1);
@@ -2641,13 +2639,13 @@ static struct rdev_sysfs_entry rdev_state =
__ATTR(state, S_IRUGO|S_IWUSR, state_show, state_store);
static ssize_t
-errors_show(mdk_rdev_t *rdev, char *page)
+errors_show(struct md_rdev *rdev, char *page)
{
return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors));
}
static ssize_t
-errors_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+errors_store(struct md_rdev *rdev, const char *buf, size_t len)
{
char *e;
unsigned long n = simple_strtoul(buf, &e, 10);
@@ -2661,7 +2659,7 @@ static struct rdev_sysfs_entry rdev_errors =
__ATTR(errors, S_IRUGO|S_IWUSR, errors_show, errors_store);
static ssize_t
-slot_show(mdk_rdev_t *rdev, char *page)
+slot_show(struct md_rdev *rdev, char *page)
{
if (rdev->raid_disk < 0)
return sprintf(page, "none\n");
@@ -2670,7 +2668,7 @@ slot_show(mdk_rdev_t *rdev, char *page)
}
static ssize_t
-slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+slot_store(struct md_rdev *rdev, const char *buf, size_t len)
{
char *e;
int err;
@@ -2701,7 +2699,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
md_wakeup_thread(rdev->mddev->thread);
} else if (rdev->mddev->pers) {
- mdk_rdev_t *rdev2;
+ struct md_rdev *rdev2;
/* Activating a spare .. or possibly reactivating
* if we ever get bitmaps working here.
*/
@@ -2728,6 +2726,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
rdev->saved_raid_disk = slot;
else
rdev->saved_raid_disk = -1;
+ clear_bit(In_sync, &rdev->flags);
err = rdev->mddev->pers->
hot_add_disk(rdev->mddev, rdev);
if (err) {
@@ -2757,13 +2756,13 @@ static struct rdev_sysfs_entry rdev_slot =
__ATTR(slot, S_IRUGO|S_IWUSR, slot_show, slot_store);
static ssize_t
-offset_show(mdk_rdev_t *rdev, char *page)
+offset_show(struct md_rdev *rdev, char *page)
{
return sprintf(page, "%llu\n", (unsigned long long)rdev->data_offset);
}
static ssize_t
-offset_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+offset_store(struct md_rdev *rdev, const char *buf, size_t len)
{
char *e;
unsigned long long offset = simple_strtoull(buf, &e, 10);
@@ -2783,7 +2782,7 @@ static struct rdev_sysfs_entry rdev_offset =
__ATTR(offset, S_IRUGO|S_IWUSR, offset_show, offset_store);
static ssize_t
-rdev_size_show(mdk_rdev_t *rdev, char *page)
+rdev_size_show(struct md_rdev *rdev, char *page)
{
return sprintf(page, "%llu\n", (unsigned long long)rdev->sectors / 2);
}
@@ -2818,9 +2817,9 @@ static int strict_blocks_to_sectors(const char *buf, sector_t *sectors)
}
static ssize_t
-rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len)
{
- mddev_t *my_mddev = rdev->mddev;
+ struct mddev *my_mddev = rdev->mddev;
sector_t oldsectors = rdev->sectors;
sector_t sectors;
@@ -2846,13 +2845,13 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
* a deadlock. We have already changed rdev->sectors, and if
* we have to change it back, we will have the lock again.
*/
- mddev_t *mddev;
+ struct mddev *mddev;
int overlap = 0;
struct list_head *tmp;
mddev_unlock(my_mddev);
for_each_mddev(mddev, tmp) {
- mdk_rdev_t *rdev2;
+ struct md_rdev *rdev2;
mddev_lock(mddev);
list_for_each_entry(rdev2, &mddev->disks, same_set)
@@ -2889,7 +2888,7 @@ static struct rdev_sysfs_entry rdev_size =
__ATTR(size, S_IRUGO|S_IWUSR, rdev_size_show, rdev_size_store);
-static ssize_t recovery_start_show(mdk_rdev_t *rdev, char *page)
+static ssize_t recovery_start_show(struct md_rdev *rdev, char *page)
{
unsigned long long recovery_start = rdev->recovery_offset;
@@ -2900,7 +2899,7 @@ static ssize_t recovery_start_show(mdk_rdev_t *rdev, char *page)
return sprintf(page, "%llu\n", recovery_start);
}
-static ssize_t recovery_start_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+static ssize_t recovery_start_store(struct md_rdev *rdev, const char *buf, size_t len)
{
unsigned long long recovery_start;
@@ -2930,11 +2929,11 @@ badblocks_show(struct badblocks *bb, char *page, int unack);
static ssize_t
badblocks_store(struct badblocks *bb, const char *page, size_t len, int unack);
-static ssize_t bb_show(mdk_rdev_t *rdev, char *page)
+static ssize_t bb_show(struct md_rdev *rdev, char *page)
{
return badblocks_show(&rdev->badblocks, page, 0);
}
-static ssize_t bb_store(mdk_rdev_t *rdev, const char *page, size_t len)
+static ssize_t bb_store(struct md_rdev *rdev, const char *page, size_t len)
{
int rv = badblocks_store(&rdev->badblocks, page, len, 0);
/* Maybe that ack was all we needed */
@@ -2946,11 +2945,11 @@ static struct rdev_sysfs_entry rdev_bad_blocks =
__ATTR(bad_blocks, S_IRUGO|S_IWUSR, bb_show, bb_store);
-static ssize_t ubb_show(mdk_rdev_t *rdev, char *page)
+static ssize_t ubb_show(struct md_rdev *rdev, char *page)
{
return badblocks_show(&rdev->badblocks, page, 1);
}
-static ssize_t ubb_store(mdk_rdev_t *rdev, const char *page, size_t len)
+static ssize_t ubb_store(struct md_rdev *rdev, const char *page, size_t len)
{
return badblocks_store(&rdev->badblocks, page, len, 1);
}
@@ -2972,8 +2971,8 @@ static ssize_t
rdev_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
{
struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
- mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
- mddev_t *mddev = rdev->mddev;
+ struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj);
+ struct mddev *mddev = rdev->mddev;
ssize_t rv;
if (!entry->show)
@@ -2995,9 +2994,9 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
const char *page, size_t length)
{
struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
- mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
+ struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj);
ssize_t rv;
- mddev_t *mddev = rdev->mddev;
+ struct mddev *mddev = rdev->mddev;
if (!entry->store)
return -EIO;
@@ -3016,7 +3015,7 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
static void rdev_free(struct kobject *ko)
{
- mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj);
+ struct md_rdev *rdev = container_of(ko, struct md_rdev, kobj);
kfree(rdev);
}
static const struct sysfs_ops rdev_sysfs_ops = {
@@ -3029,7 +3028,7 @@ static struct kobj_type rdev_ktype = {
.default_attrs = rdev_default_attrs,
};
-int md_rdev_init(mdk_rdev_t *rdev)
+int md_rdev_init(struct md_rdev *rdev)
{
rdev->desc_nr = -1;
rdev->saved_raid_disk = -1;
@@ -3072,11 +3071,11 @@ EXPORT_SYMBOL_GPL(md_rdev_init);
*
* a faulty rdev _never_ has rdev->sb set.
*/
-static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor)
+static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
{
char b[BDEVNAME_SIZE];
int err;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t size;
rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
@@ -3145,10 +3144,10 @@ abort_free:
*/
-static void analyze_sbs(mddev_t * mddev)
+static void analyze_sbs(struct mddev * mddev)
{
int i;
- mdk_rdev_t *rdev, *freshest, *tmp;
+ struct md_rdev *rdev, *freshest, *tmp;
char b[BDEVNAME_SIZE];
freshest = NULL;
@@ -3248,13 +3247,13 @@ int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale)
static void md_safemode_timeout(unsigned long data);
static ssize_t
-safe_delay_show(mddev_t *mddev, char *page)
+safe_delay_show(struct mddev *mddev, char *page)
{
int msec = (mddev->safemode_delay*1000)/HZ;
return sprintf(page, "%d.%03d\n", msec/1000, msec%1000);
}
static ssize_t
-safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
+safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
{
unsigned long msec;
@@ -3276,9 +3275,9 @@ static struct md_sysfs_entry md_safe_delay =
__ATTR(safe_mode_delay, S_IRUGO|S_IWUSR,safe_delay_show, safe_delay_store);
static ssize_t
-level_show(mddev_t *mddev, char *page)
+level_show(struct mddev *mddev, char *page)
{
- struct mdk_personality *p = mddev->pers;
+ struct md_personality *p = mddev->pers;
if (p)
return sprintf(page, "%s\n", p->name);
else if (mddev->clevel[0])
@@ -3290,14 +3289,14 @@ level_show(mddev_t *mddev, char *page)
}
static ssize_t
-level_store(mddev_t *mddev, const char *buf, size_t len)
+level_store(struct mddev *mddev, const char *buf, size_t len)
{
char clevel[16];
ssize_t rv = len;
- struct mdk_personality *pers;
+ struct md_personality *pers;
long level;
void *priv;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (mddev->pers == NULL) {
if (len == 0)
@@ -3471,7 +3470,7 @@ __ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store);
static ssize_t
-layout_show(mddev_t *mddev, char *page)
+layout_show(struct mddev *mddev, char *page)
{
/* just a number, not meaningful for all levels */
if (mddev->reshape_position != MaxSector &&
@@ -3482,7 +3481,7 @@ layout_show(mddev_t *mddev, char *page)
}
static ssize_t
-layout_store(mddev_t *mddev, const char *buf, size_t len)
+layout_store(struct mddev *mddev, const char *buf, size_t len)
{
char *e;
unsigned long n = simple_strtoul(buf, &e, 10);
@@ -3512,7 +3511,7 @@ __ATTR(layout, S_IRUGO|S_IWUSR, layout_show, layout_store);
static ssize_t
-raid_disks_show(mddev_t *mddev, char *page)
+raid_disks_show(struct mddev *mddev, char *page)
{
if (mddev->raid_disks == 0)
return 0;
@@ -3523,10 +3522,10 @@ raid_disks_show(mddev_t *mddev, char *page)
return sprintf(page, "%d\n", mddev->raid_disks);
}
-static int update_raid_disks(mddev_t *mddev, int raid_disks);
+static int update_raid_disks(struct mddev *mddev, int raid_disks);
static ssize_t
-raid_disks_store(mddev_t *mddev, const char *buf, size_t len)
+raid_disks_store(struct mddev *mddev, const char *buf, size_t len)
{
char *e;
int rv = 0;
@@ -3549,7 +3548,7 @@ static struct md_sysfs_entry md_raid_disks =
__ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store);
static ssize_t
-chunk_size_show(mddev_t *mddev, char *page)
+chunk_size_show(struct mddev *mddev, char *page)
{
if (mddev->reshape_position != MaxSector &&
mddev->chunk_sectors != mddev->new_chunk_sectors)
@@ -3560,7 +3559,7 @@ chunk_size_show(mddev_t *mddev, char *page)
}
static ssize_t
-chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
+chunk_size_store(struct mddev *mddev, const char *buf, size_t len)
{
char *e;
unsigned long n = simple_strtoul(buf, &e, 10);
@@ -3589,7 +3588,7 @@ static struct md_sysfs_entry md_chunk_size =
__ATTR(chunk_size, S_IRUGO|S_IWUSR, chunk_size_show, chunk_size_store);
static ssize_t
-resync_start_show(mddev_t *mddev, char *page)
+resync_start_show(struct mddev *mddev, char *page)
{
if (mddev->recovery_cp == MaxSector)
return sprintf(page, "none\n");
@@ -3597,7 +3596,7 @@ resync_start_show(mddev_t *mddev, char *page)
}
static ssize_t
-resync_start_store(mddev_t *mddev, const char *buf, size_t len)
+resync_start_store(struct mddev *mddev, const char *buf, size_t len)
{
char *e;
unsigned long long n = simple_strtoull(buf, &e, 10);
@@ -3667,7 +3666,7 @@ static int match_word(const char *word, char **list)
}
static ssize_t
-array_state_show(mddev_t *mddev, char *page)
+array_state_show(struct mddev *mddev, char *page)
{
enum array_state st = inactive;
@@ -3700,13 +3699,13 @@ array_state_show(mddev_t *mddev, char *page)
return sprintf(page, "%s\n", array_states[st]);
}
-static int do_md_stop(mddev_t * mddev, int ro, int is_open);
-static int md_set_readonly(mddev_t * mddev, int is_open);
-static int do_md_run(mddev_t * mddev);
-static int restart_array(mddev_t *mddev);
+static int do_md_stop(struct mddev * mddev, int ro, int is_open);
+static int md_set_readonly(struct mddev * mddev, int is_open);
+static int do_md_run(struct mddev * mddev);
+static int restart_array(struct mddev *mddev);
static ssize_t
-array_state_store(mddev_t *mddev, const char *buf, size_t len)
+array_state_store(struct mddev *mddev, const char *buf, size_t len)
{
int err = -EINVAL;
enum array_state st = match_word(buf, array_states);
@@ -3800,13 +3799,13 @@ static struct md_sysfs_entry md_array_state =
__ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);
static ssize_t
-max_corrected_read_errors_show(mddev_t *mddev, char *page) {
+max_corrected_read_errors_show(struct mddev *mddev, char *page) {
return sprintf(page, "%d\n",
atomic_read(&mddev->max_corr_read_errors));
}
static ssize_t
-max_corrected_read_errors_store(mddev_t *mddev, const char *buf, size_t len)
+max_corrected_read_errors_store(struct mddev *mddev, const char *buf, size_t len)
{
char *e;
unsigned long n = simple_strtoul(buf, &e, 10);
@@ -3823,13 +3822,13 @@ __ATTR(max_read_errors, S_IRUGO|S_IWUSR, max_corrected_read_errors_show,
max_corrected_read_errors_store);
static ssize_t
-null_show(mddev_t *mddev, char *page)
+null_show(struct mddev *mddev, char *page)
{
return -EINVAL;
}
static ssize_t
-new_dev_store(mddev_t *mddev, const char *buf, size_t len)
+new_dev_store(struct mddev *mddev, const char *buf, size_t len)
{
/* buf must be %d:%d\n? giving major and minor numbers */
/* The new device is added to the array.
@@ -3842,7 +3841,7 @@ new_dev_store(mddev_t *mddev, const char *buf, size_t len)
int major = simple_strtoul(buf, &e, 10);
int minor;
dev_t dev;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int err;
if (!*buf || *e != ':' || !e[1] || e[1] == '\n')
@@ -3860,8 +3859,9 @@ new_dev_store(mddev_t *mddev, const char *buf, size_t len)
rdev = md_import_device(dev, mddev->major_version,
mddev->minor_version);
if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) {
- mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
- mdk_rdev_t, same_set);
+ struct md_rdev *rdev0
+ = list_entry(mddev->disks.next,
+ struct md_rdev, same_set);
err = super_types[mddev->major_version]
.load_super(rdev, rdev0, mddev->minor_version);
if (err < 0)
@@ -3885,7 +3885,7 @@ static struct md_sysfs_entry md_new_device =
__ATTR(new_dev, S_IWUSR, null_show, new_dev_store);
static ssize_t
-bitmap_store(mddev_t *mddev, const char *buf, size_t len)
+bitmap_store(struct mddev *mddev, const char *buf, size_t len)
{
char *end;
unsigned long chunk, end_chunk;
@@ -3914,16 +3914,16 @@ static struct md_sysfs_entry md_bitmap =
__ATTR(bitmap_set_bits, S_IWUSR, null_show, bitmap_store);
static ssize_t
-size_show(mddev_t *mddev, char *page)
+size_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%llu\n",
(unsigned long long)mddev->dev_sectors / 2);
}
-static int update_size(mddev_t *mddev, sector_t num_sectors);
+static int update_size(struct mddev *mddev, sector_t num_sectors);
static ssize_t
-size_store(mddev_t *mddev, const char *buf, size_t len)
+size_store(struct mddev *mddev, const char *buf, size_t len)
{
/* If array is inactive, we can reduce the component size, but
* not increase it (except from 0).
@@ -3958,7 +3958,7 @@ __ATTR(component_size, S_IRUGO|S_IWUSR, size_show, size_store);
* or N.M for internally known formats
*/
static ssize_t
-metadata_show(mddev_t *mddev, char *page)
+metadata_show(struct mddev *mddev, char *page)
{
if (mddev->persistent)
return sprintf(page, "%d.%d\n",
@@ -3970,7 +3970,7 @@ metadata_show(mddev_t *mddev, char *page)
}
static ssize_t
-metadata_store(mddev_t *mddev, const char *buf, size_t len)
+metadata_store(struct mddev *mddev, const char *buf, size_t len)
{
int major, minor;
char *e;
@@ -4024,7 +4024,7 @@ static struct md_sysfs_entry md_metadata =
__ATTR(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
static ssize_t
-action_show(mddev_t *mddev, char *page)
+action_show(struct mddev *mddev, char *page)
{
char *type = "idle";
if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
@@ -4046,10 +4046,10 @@ action_show(mddev_t *mddev, char *page)
return sprintf(page, "%s\n", type);
}
-static void reap_sync_thread(mddev_t *mddev);
+static void reap_sync_thread(struct mddev *mddev);
static ssize_t
-action_store(mddev_t *mddev, const char *page, size_t len)
+action_store(struct mddev *mddev, const char *page, size_t len)
{
if (!mddev->pers || !mddev->pers->sync_request)
return -EINVAL;
@@ -4095,7 +4095,7 @@ action_store(mddev_t *mddev, const char *page, size_t len)
}
static ssize_t
-mismatch_cnt_show(mddev_t *mddev, char *page)
+mismatch_cnt_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%llu\n",
(unsigned long long) mddev->resync_mismatches);
@@ -4108,14 +4108,14 @@ __ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store);
static struct md_sysfs_entry md_mismatches = __ATTR_RO(mismatch_cnt);
static ssize_t
-sync_min_show(mddev_t *mddev, char *page)
+sync_min_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%d (%s)\n", speed_min(mddev),
mddev->sync_speed_min ? "local": "system");
}
static ssize_t
-sync_min_store(mddev_t *mddev, const char *buf, size_t len)
+sync_min_store(struct mddev *mddev, const char *buf, size_t len)
{
int min;
char *e;
@@ -4134,14 +4134,14 @@ static struct md_sysfs_entry md_sync_min =
__ATTR(sync_speed_min, S_IRUGO|S_IWUSR, sync_min_show, sync_min_store);
static ssize_t
-sync_max_show(mddev_t *mddev, char *page)
+sync_max_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%d (%s)\n", speed_max(mddev),
mddev->sync_speed_max ? "local": "system");
}
static ssize_t
-sync_max_store(mddev_t *mddev, const char *buf, size_t len)
+sync_max_store(struct mddev *mddev, const char *buf, size_t len)
{
int max;
char *e;
@@ -4160,20 +4160,20 @@ static struct md_sysfs_entry md_sync_max =
__ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store);
static ssize_t
-degraded_show(mddev_t *mddev, char *page)
+degraded_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%d\n", mddev->degraded);
}
static struct md_sysfs_entry md_degraded = __ATTR_RO(degraded);
static ssize_t
-sync_force_parallel_show(mddev_t *mddev, char *page)
+sync_force_parallel_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%d\n", mddev->parallel_resync);
}
static ssize_t
-sync_force_parallel_store(mddev_t *mddev, const char *buf, size_t len)
+sync_force_parallel_store(struct mddev *mddev, const char *buf, size_t len)
{
long n;
@@ -4197,7 +4197,7 @@ __ATTR(sync_force_parallel, S_IRUGO|S_IWUSR,
sync_force_parallel_show, sync_force_parallel_store);
static ssize_t
-sync_speed_show(mddev_t *mddev, char *page)
+sync_speed_show(struct mddev *mddev, char *page)
{
unsigned long resync, dt, db;
if (mddev->curr_resync == 0)
@@ -4212,7 +4212,7 @@ sync_speed_show(mddev_t *mddev, char *page)
static struct md_sysfs_entry md_sync_speed = __ATTR_RO(sync_speed);
static ssize_t
-sync_completed_show(mddev_t *mddev, char *page)
+sync_completed_show(struct mddev *mddev, char *page)
{
unsigned long long max_sectors, resync;
@@ -4231,13 +4231,13 @@ sync_completed_show(mddev_t *mddev, char *page)
static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
static ssize_t
-min_sync_show(mddev_t *mddev, char *page)
+min_sync_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%llu\n",
(unsigned long long)mddev->resync_min);
}
static ssize_t
-min_sync_store(mddev_t *mddev, const char *buf, size_t len)
+min_sync_store(struct mddev *mddev, const char *buf, size_t len)
{
unsigned long long min;
if (strict_strtoull(buf, 10, &min))
@@ -4262,7 +4262,7 @@ static struct md_sysfs_entry md_min_sync =
__ATTR(sync_min, S_IRUGO|S_IWUSR, min_sync_show, min_sync_store);
static ssize_t
-max_sync_show(mddev_t *mddev, char *page)
+max_sync_show(struct mddev *mddev, char *page)
{
if (mddev->resync_max == MaxSector)
return sprintf(page, "max\n");
@@ -4271,7 +4271,7 @@ max_sync_show(mddev_t *mddev, char *page)
(unsigned long long)mddev->resync_max);
}
static ssize_t
-max_sync_store(mddev_t *mddev, const char *buf, size_t len)
+max_sync_store(struct mddev *mddev, const char *buf, size_t len)
{
if (strncmp(buf, "max", 3) == 0)
mddev->resync_max = MaxSector;
@@ -4302,13 +4302,13 @@ static struct md_sysfs_entry md_max_sync =
__ATTR(sync_max, S_IRUGO|S_IWUSR, max_sync_show, max_sync_store);
static ssize_t
-suspend_lo_show(mddev_t *mddev, char *page)
+suspend_lo_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo);
}
static ssize_t
-suspend_lo_store(mddev_t *mddev, const char *buf, size_t len)
+suspend_lo_store(struct mddev *mddev, const char *buf, size_t len)
{
char *e;
unsigned long long new = simple_strtoull(buf, &e, 10);
@@ -4336,13 +4336,13 @@ __ATTR(suspend_lo, S_IRUGO|S_IWUSR, suspend_lo_show, suspend_lo_store);
static ssize_t
-suspend_hi_show(mddev_t *mddev, char *page)
+suspend_hi_show(struct mddev *mddev, char *page)
{
return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_hi);
}
static ssize_t
-suspend_hi_store(mddev_t *mddev, const char *buf, size_t len)
+suspend_hi_store(struct mddev *mddev, const char *buf, size_t len)
{
char *e;
unsigned long long new = simple_strtoull(buf, &e, 10);
@@ -4369,7 +4369,7 @@ static struct md_sysfs_entry md_suspend_hi =
__ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store);
static ssize_t
-reshape_position_show(mddev_t *mddev, char *page)
+reshape_position_show(struct mddev *mddev, char *page)
{
if (mddev->reshape_position != MaxSector)
return sprintf(page, "%llu\n",
@@ -4379,7 +4379,7 @@ reshape_position_show(mddev_t *mddev, char *page)
}
static ssize_t
-reshape_position_store(mddev_t *mddev, const char *buf, size_t len)
+reshape_position_store(struct mddev *mddev, const char *buf, size_t len)
{
char *e;
unsigned long long new = simple_strtoull(buf, &e, 10);
@@ -4400,7 +4400,7 @@ __ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show,
reshape_position_store);
static ssize_t
-array_size_show(mddev_t *mddev, char *page)
+array_size_show(struct mddev *mddev, char *page)
{
if (mddev->external_size)
return sprintf(page, "%llu\n",
@@ -4410,7 +4410,7 @@ array_size_show(mddev_t *mddev, char *page)
}
static ssize_t
-array_size_store(mddev_t *mddev, const char *buf, size_t len)
+array_size_store(struct mddev *mddev, const char *buf, size_t len)
{
sector_t sectors;
@@ -4485,7 +4485,7 @@ static ssize_t
md_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
{
struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
- mddev_t *mddev = container_of(kobj, struct mddev_s, kobj);
+ struct mddev *mddev = container_of(kobj, struct mddev, kobj);
ssize_t rv;
if (!entry->show)
@@ -4503,7 +4503,7 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
const char *page, size_t length)
{
struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
- mddev_t *mddev = container_of(kobj, struct mddev_s, kobj);
+ struct mddev *mddev = container_of(kobj, struct mddev, kobj);
ssize_t rv;
if (!entry->store)
@@ -4522,7 +4522,7 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
static void md_free(struct kobject *ko)
{
- mddev_t *mddev = container_of(ko, mddev_t, kobj);
+ struct mddev *mddev = container_of(ko, struct mddev, kobj);
if (mddev->sysfs_state)
sysfs_put(mddev->sysfs_state);
@@ -4551,7 +4551,7 @@ int mdp_major = 0;
static void mddev_delayed_delete(struct work_struct *ws)
{
- mddev_t *mddev = container_of(ws, mddev_t, del_work);
+ struct mddev *mddev = container_of(ws, struct mddev, del_work);
sysfs_remove_group(&mddev->kobj, &md_bitmap_group);
kobject_del(&mddev->kobj);
@@ -4561,7 +4561,7 @@ static void mddev_delayed_delete(struct work_struct *ws)
static int md_alloc(dev_t dev, char *name)
{
static DEFINE_MUTEX(disks_mutex);
- mddev_t *mddev = mddev_find(dev);
+ struct mddev *mddev = mddev_find(dev);
struct gendisk *disk;
int partitioned;
int shift;
@@ -4588,7 +4588,7 @@ static int md_alloc(dev_t dev, char *name)
if (name) {
/* Need to ensure that 'name' is not a duplicate.
*/
- mddev_t *mddev2;
+ struct mddev *mddev2;
spin_lock(&all_mddevs_lock);
list_for_each_entry(mddev2, &all_mddevs, all_mddevs)
@@ -4689,7 +4689,7 @@ static int add_named_array(const char *val, struct kernel_param *kp)
static void md_safemode_timeout(unsigned long data)
{
- mddev_t *mddev = (mddev_t *) data;
+ struct mddev *mddev = (struct mddev *) data;
if (!atomic_read(&mddev->writes_pending)) {
mddev->safemode = 1;
@@ -4701,11 +4701,11 @@ static void md_safemode_timeout(unsigned long data)
static int start_dirty_degraded;
-int md_run(mddev_t *mddev)
+int md_run(struct mddev *mddev)
{
int err;
- mdk_rdev_t *rdev;
- struct mdk_personality *pers;
+ struct md_rdev *rdev;
+ struct md_personality *pers;
if (list_empty(&mddev->disks))
/* cannot run an array with no devices.. */
@@ -4769,7 +4769,7 @@ int md_run(mddev_t *mddev)
if (mddev->bio_set == NULL)
mddev->bio_set = bioset_create(BIO_POOL_SIZE,
- sizeof(mddev_t *));
+ sizeof(struct mddev *));
spin_lock(&pers_lock);
pers = find_pers(mddev->level, mddev->clevel);
@@ -4804,7 +4804,7 @@ int md_run(mddev_t *mddev)
* configuration.
*/
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
- mdk_rdev_t *rdev2;
+ struct md_rdev *rdev2;
int warned = 0;
list_for_each_entry(rdev, &mddev->disks, same_set)
@@ -4903,7 +4903,7 @@ int md_run(mddev_t *mddev)
}
EXPORT_SYMBOL_GPL(md_run);
-static int do_md_run(mddev_t *mddev)
+static int do_md_run(struct mddev *mddev)
{
int err;
@@ -4927,7 +4927,7 @@ out:
return err;
}
-static int restart_array(mddev_t *mddev)
+static int restart_array(struct mddev *mddev)
{
struct gendisk *disk = mddev->gendisk;
@@ -4977,7 +4977,7 @@ void restore_bitmap_write_access(struct file *file)
spin_unlock(&inode->i_lock);
}
-static void md_clean(mddev_t *mddev)
+static void md_clean(struct mddev *mddev)
{
mddev->array_sectors = 0;
mddev->external_size = 0;
@@ -5020,7 +5020,7 @@ static void md_clean(mddev_t *mddev)
mddev->bitmap_info.max_write_behind = 0;
}
-static void __md_stop_writes(mddev_t *mddev)
+static void __md_stop_writes(struct mddev *mddev)
{
if (mddev->sync_thread) {
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -5040,7 +5040,7 @@ static void __md_stop_writes(mddev_t *mddev)
}
}
-void md_stop_writes(mddev_t *mddev)
+void md_stop_writes(struct mddev *mddev)
{
mddev_lock(mddev);
__md_stop_writes(mddev);
@@ -5048,7 +5048,7 @@ void md_stop_writes(mddev_t *mddev)
}
EXPORT_SYMBOL_GPL(md_stop_writes);
-void md_stop(mddev_t *mddev)
+void md_stop(struct mddev *mddev)
{
mddev->ready = 0;
mddev->pers->stop(mddev);
@@ -5060,7 +5060,7 @@ void md_stop(mddev_t *mddev)
}
EXPORT_SYMBOL_GPL(md_stop);
-static int md_set_readonly(mddev_t *mddev, int is_open)
+static int md_set_readonly(struct mddev *mddev, int is_open)
{
int err = 0;
mutex_lock(&mddev->open_mutex);
@@ -5090,10 +5090,10 @@ out:
* 0 - completely stop and dis-assemble array
* 2 - stop but do not disassemble array
*/
-static int do_md_stop(mddev_t * mddev, int mode, int is_open)
+static int do_md_stop(struct mddev * mddev, int mode, int is_open)
{
struct gendisk *disk = mddev->gendisk;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
mutex_lock(&mddev->open_mutex);
if (atomic_read(&mddev->openers) > is_open ||
@@ -5156,9 +5156,9 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
}
#ifndef MODULE
-static void autorun_array(mddev_t *mddev)
+static void autorun_array(struct mddev *mddev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int err;
if (list_empty(&mddev->disks))
@@ -5193,8 +5193,8 @@ static void autorun_array(mddev_t *mddev)
*/
static void autorun_devices(int part)
{
- mdk_rdev_t *rdev0, *rdev, *tmp;
- mddev_t *mddev;
+ struct md_rdev *rdev0, *rdev, *tmp;
+ struct mddev *mddev;
char b[BDEVNAME_SIZE];
printk(KERN_INFO "md: autorun ...\n");
@@ -5203,7 +5203,7 @@ static void autorun_devices(int part)
dev_t dev;
LIST_HEAD(candidates);
rdev0 = list_entry(pending_raid_disks.next,
- mdk_rdev_t, same_set);
+ struct md_rdev, same_set);
printk(KERN_INFO "md: considering %s ...\n",
bdevname(rdev0->bdev,b));
@@ -5289,11 +5289,11 @@ static int get_version(void __user * arg)
return 0;
}
-static int get_array_info(mddev_t * mddev, void __user * arg)
+static int get_array_info(struct mddev * mddev, void __user * arg)
{
mdu_array_info_t info;
int nr,working,insync,failed,spare;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
nr=working=insync=failed=spare=0;
list_for_each_entry(rdev, &mddev->disks, same_set) {
@@ -5342,7 +5342,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
return 0;
}
-static int get_bitmap_file(mddev_t * mddev, void __user * arg)
+static int get_bitmap_file(struct mddev * mddev, void __user * arg)
{
mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
char *ptr, *buf = NULL;
@@ -5382,10 +5382,10 @@ out:
return err;
}
-static int get_disk_info(mddev_t * mddev, void __user * arg)
+static int get_disk_info(struct mddev * mddev, void __user * arg)
{
mdu_disk_info_t info;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -5416,10 +5416,10 @@ static int get_disk_info(mddev_t * mddev, void __user * arg)
return 0;
}
-static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
+static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
{
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
dev_t dev = MKDEV(info->major,info->minor);
if (info->major != MAJOR(dev) || info->minor != MINOR(dev))
@@ -5436,8 +5436,9 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
return PTR_ERR(rdev);
}
if (!list_empty(&mddev->disks)) {
- mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
- mdk_rdev_t, same_set);
+ struct md_rdev *rdev0
+ = list_entry(mddev->disks.next,
+ struct md_rdev, same_set);
err = super_types[mddev->major_version]
.load_super(rdev, rdev0, mddev->minor_version);
if (err < 0) {
@@ -5587,10 +5588,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
return 0;
}
-static int hot_remove_disk(mddev_t * mddev, dev_t dev)
+static int hot_remove_disk(struct mddev * mddev, dev_t dev)
{
char b[BDEVNAME_SIZE];
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
rdev = find_rdev(mddev, dev);
if (!rdev)
@@ -5610,11 +5611,11 @@ busy:
return -EBUSY;
}
-static int hot_add_disk(mddev_t * mddev, dev_t dev)
+static int hot_add_disk(struct mddev * mddev, dev_t dev)
{
char b[BDEVNAME_SIZE];
int err;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (!mddev->pers)
return -ENODEV;
@@ -5684,7 +5685,7 @@ abort_export:
return err;
}
-static int set_bitmap_file(mddev_t *mddev, int fd)
+static int set_bitmap_file(struct mddev *mddev, int fd)
{
int err;
@@ -5757,7 +5758,7 @@ static int set_bitmap_file(mddev_t *mddev, int fd)
* The minor and patch _version numbers are also kept incase the
* super_block handler wishes to interpret them.
*/
-static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
+static int set_array_info(struct mddev * mddev, mdu_array_info_t *info)
{
if (info->raid_disks == 0) {
@@ -5827,7 +5828,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
return 0;
}
-void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors)
+void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors)
{
WARN(!mddev_is_locked(mddev), "%s: unlocked mddev!\n", __func__);
@@ -5838,9 +5839,9 @@ void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors)
}
EXPORT_SYMBOL(md_set_array_sectors);
-static int update_size(mddev_t *mddev, sector_t num_sectors)
+static int update_size(struct mddev *mddev, sector_t num_sectors)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int rv;
int fit = (num_sectors == 0);
@@ -5876,7 +5877,7 @@ static int update_size(mddev_t *mddev, sector_t num_sectors)
return rv;
}
-static int update_raid_disks(mddev_t *mddev, int raid_disks)
+static int update_raid_disks(struct mddev *mddev, int raid_disks)
{
int rv;
/* change the number of raid disks */
@@ -5904,7 +5905,7 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks)
* Any differences that cannot be handled will cause an error.
* Normally, only one change can be managed at a time.
*/
-static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
+static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
{
int rv = 0;
int cnt = 0;
@@ -5997,9 +5998,9 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
return rv;
}
-static int set_disk_faulty(mddev_t *mddev, dev_t dev)
+static int set_disk_faulty(struct mddev *mddev, dev_t dev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (mddev->pers == NULL)
return -ENODEV;
@@ -6022,7 +6023,7 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
*/
static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- mddev_t *mddev = bdev->bd_disk->private_data;
+ struct mddev *mddev = bdev->bd_disk->private_data;
geo->heads = 2;
geo->sectors = 4;
@@ -6035,7 +6036,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
{
int err = 0;
void __user *argp = (void __user *)arg;
- mddev_t *mddev = NULL;
+ struct mddev *mddev = NULL;
int ro;
if (!capable(CAP_SYS_ADMIN))
@@ -6298,7 +6299,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
* Succeed if we can lock the mddev, which confirms that
* it isn't being stopped right now.
*/
- mddev_t *mddev = mddev_find(bdev->bd_dev);
+ struct mddev *mddev = mddev_find(bdev->bd_dev);
int err;
if (mddev->gendisk != bdev->bd_disk) {
@@ -6327,7 +6328,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
static int md_release(struct gendisk *disk, fmode_t mode)
{
- mddev_t *mddev = disk->private_data;
+ struct mddev *mddev = disk->private_data;
BUG_ON(!mddev);
atomic_dec(&mddev->openers);
@@ -6338,14 +6339,14 @@ static int md_release(struct gendisk *disk, fmode_t mode)
static int md_media_changed(struct gendisk *disk)
{
- mddev_t *mddev = disk->private_data;
+ struct mddev *mddev = disk->private_data;
return mddev->changed;
}
static int md_revalidate(struct gendisk *disk)
{
- mddev_t *mddev = disk->private_data;
+ struct mddev *mddev = disk->private_data;
mddev->changed = 0;
return 0;
@@ -6366,7 +6367,7 @@ static const struct block_device_operations md_fops =
static int md_thread(void * arg)
{
- mdk_thread_t *thread = arg;
+ struct md_thread *thread = arg;
/*
* md_thread is a 'system-thread', it's priority should be very
@@ -6405,21 +6406,21 @@ static int md_thread(void * arg)
return 0;
}
-void md_wakeup_thread(mdk_thread_t *thread)
+void md_wakeup_thread(struct md_thread *thread)
{
if (thread) {
- dprintk("md: waking up MD thread %s.\n", thread->tsk->comm);
+ pr_debug("md: waking up MD thread %s.\n", thread->tsk->comm);
set_bit(THREAD_WAKEUP, &thread->flags);
wake_up(&thread->wqueue);
}
}
-mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
+struct md_thread *md_register_thread(void (*run) (struct mddev *), struct mddev *mddev,
const char *name)
{
- mdk_thread_t *thread;
+ struct md_thread *thread;
- thread = kzalloc(sizeof(mdk_thread_t), GFP_KERNEL);
+ thread = kzalloc(sizeof(struct md_thread), GFP_KERNEL);
if (!thread)
return NULL;
@@ -6439,12 +6440,12 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
return thread;
}
-void md_unregister_thread(mdk_thread_t **threadp)
+void md_unregister_thread(struct md_thread **threadp)
{
- mdk_thread_t *thread = *threadp;
+ struct md_thread *thread = *threadp;
if (!thread)
return;
- dprintk("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
+ pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
/* Locking ensures that mddev_unlock does not wake_up a
* non-existent thread
*/
@@ -6456,7 +6457,7 @@ void md_unregister_thread(mdk_thread_t **threadp)
kfree(thread);
}
-void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
+void md_error(struct mddev *mddev, struct md_rdev *rdev)
{
if (!mddev) {
MD_BUG();
@@ -6485,7 +6486,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
static void status_unused(struct seq_file *seq)
{
int i = 0;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
seq_printf(seq, "unused devices: ");
@@ -6502,7 +6503,7 @@ static void status_unused(struct seq_file *seq)
}
-static void status_resync(struct seq_file *seq, mddev_t * mddev)
+static void status_resync(struct seq_file *seq, struct mddev * mddev)
{
sector_t max_sectors, resync, res;
unsigned long dt, db;
@@ -6593,7 +6594,7 @@ static void *md_seq_start(struct seq_file *seq, loff_t *pos)
{
struct list_head *tmp;
loff_t l = *pos;
- mddev_t *mddev;
+ struct mddev *mddev;
if (l >= 0x10000)
return NULL;
@@ -6604,7 +6605,7 @@ static void *md_seq_start(struct seq_file *seq, loff_t *pos)
spin_lock(&all_mddevs_lock);
list_for_each(tmp,&all_mddevs)
if (!l--) {
- mddev = list_entry(tmp, mddev_t, all_mddevs);
+ mddev = list_entry(tmp, struct mddev, all_mddevs);
mddev_get(mddev);
spin_unlock(&all_mddevs_lock);
return mddev;
@@ -6618,7 +6619,7 @@ static void *md_seq_start(struct seq_file *seq, loff_t *pos)
static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct list_head *tmp;
- mddev_t *next_mddev, *mddev = v;
+ struct mddev *next_mddev, *mddev = v;
++*pos;
if (v == (void*)2)
@@ -6630,7 +6631,7 @@ static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
else
tmp = mddev->all_mddevs.next;
if (tmp != &all_mddevs)
- next_mddev = mddev_get(list_entry(tmp,mddev_t,all_mddevs));
+ next_mddev = mddev_get(list_entry(tmp,struct mddev,all_mddevs));
else {
next_mddev = (void*)2;
*pos = 0x10000;
@@ -6645,7 +6646,7 @@ static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
static void md_seq_stop(struct seq_file *seq, void *v)
{
- mddev_t *mddev = v;
+ struct mddev *mddev = v;
if (mddev && v != (void*)1 && v != (void*)2)
mddev_put(mddev);
@@ -6653,13 +6654,13 @@ static void md_seq_stop(struct seq_file *seq, void *v)
static int md_seq_show(struct seq_file *seq, void *v)
{
- mddev_t *mddev = v;
+ struct mddev *mddev = v;
sector_t sectors;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
struct bitmap *bitmap;
if (v == (void*)1) {
- struct mdk_personality *pers;
+ struct md_personality *pers;
seq_printf(seq, "Personalities : ");
spin_lock(&pers_lock);
list_for_each_entry(pers, &pers_list, list)
@@ -6815,7 +6816,7 @@ static const struct file_operations md_seq_fops = {
.poll = mdstat_poll,
};
-int register_md_personality(struct mdk_personality *p)
+int register_md_personality(struct md_personality *p)
{
spin_lock(&pers_lock);
list_add_tail(&p->list, &pers_list);
@@ -6824,7 +6825,7 @@ int register_md_personality(struct mdk_personality *p)
return 0;
}
-int unregister_md_personality(struct mdk_personality *p)
+int unregister_md_personality(struct md_personality *p)
{
printk(KERN_INFO "md: %s personality unregistered\n", p->name);
spin_lock(&pers_lock);
@@ -6833,9 +6834,9 @@ int unregister_md_personality(struct mdk_personality *p)
return 0;
}
-static int is_mddev_idle(mddev_t *mddev, int init)
+static int is_mddev_idle(struct mddev *mddev, int init)
{
- mdk_rdev_t * rdev;
+ struct md_rdev * rdev;
int idle;
int curr_events;
@@ -6877,7 +6878,7 @@ static int is_mddev_idle(mddev_t *mddev, int init)
return idle;
}
-void md_done_sync(mddev_t *mddev, int blocks, int ok)
+void md_done_sync(struct mddev *mddev, int blocks, int ok)
{
/* another "blocks" (512byte) blocks have been synced */
atomic_sub(blocks, &mddev->recovery_active);
@@ -6895,7 +6896,7 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
* in superblock) before writing, schedule a superblock update
* and wait for it to complete.
*/
-void md_write_start(mddev_t *mddev, struct bio *bi)
+void md_write_start(struct mddev *mddev, struct bio *bi)
{
int did_change = 0;
if (bio_data_dir(bi) != WRITE)
@@ -6930,7 +6931,7 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
!test_bit(MD_CHANGE_PENDING, &mddev->flags));
}
-void md_write_end(mddev_t *mddev)
+void md_write_end(struct mddev *mddev)
{
if (atomic_dec_and_test(&mddev->writes_pending)) {
if (mddev->safemode == 2)
@@ -6949,7 +6950,7 @@ void md_write_end(mddev_t *mddev)
* In the ->external case MD_CHANGE_CLEAN can not be cleared until mddev->lock
* is dropped, so return -EAGAIN after notifying userspace.
*/
-int md_allow_write(mddev_t *mddev)
+int md_allow_write(struct mddev *mddev)
{
if (!mddev->pers)
return 0;
@@ -6981,9 +6982,9 @@ EXPORT_SYMBOL_GPL(md_allow_write);
#define SYNC_MARKS 10
#define SYNC_MARK_STEP (3*HZ)
-void md_do_sync(mddev_t *mddev)
+void md_do_sync(struct mddev *mddev)
{
- mddev_t *mddev2;
+ struct mddev *mddev2;
unsigned int currspeed = 0,
window;
sector_t max_sectors,j, io_sectors;
@@ -6993,7 +6994,7 @@ void md_do_sync(mddev_t *mddev)
struct list_head *tmp;
sector_t last_check;
int skipped = 0;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
char *desc;
/* just incase thread restarts... */
@@ -7308,9 +7309,9 @@ void md_do_sync(mddev_t *mddev)
}
EXPORT_SYMBOL_GPL(md_do_sync);
-static int remove_and_add_spares(mddev_t *mddev)
+static int remove_and_add_spares(struct mddev *mddev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int spares = 0;
mddev->curr_resync_completed = 0;
@@ -7352,9 +7353,9 @@ static int remove_and_add_spares(mddev_t *mddev)
return spares;
}
-static void reap_sync_thread(mddev_t *mddev)
+static void reap_sync_thread(struct mddev *mddev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
/* resync has finished, collect result */
md_unregister_thread(&mddev->sync_thread);
@@ -7369,15 +7370,19 @@ static void reap_sync_thread(mddev_t *mddev)
if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
mddev->pers->finish_reshape)
mddev->pers->finish_reshape(mddev);
- md_update_sb(mddev, 1);
- /* if array is no-longer degraded, then any saved_raid_disk
- * information must be scrapped
+ /* If array is no-longer degraded, then any saved_raid_disk
+ * information must be scrapped. Also if any device is now
+ * In_sync we must scrape the saved_raid_disk for that device
+ * do the superblock for an incrementally recovered device
+ * written out.
*/
- if (!mddev->degraded)
- list_for_each_entry(rdev, &mddev->disks, same_set)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ if (!mddev->degraded ||
+ test_bit(In_sync, &rdev->flags))
rdev->saved_raid_disk = -1;
+ md_update_sb(mddev, 1);
clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
@@ -7413,7 +7418,7 @@ static void reap_sync_thread(mddev_t *mddev)
* 5/ If array is degraded, try to add spares devices
* 6/ If array has spares or is not in-sync, start a resync thread.
*/
-void md_check_recovery(mddev_t *mddev)
+void md_check_recovery(struct mddev *mddev)
{
if (mddev->suspended)
return;
@@ -7449,7 +7454,7 @@ void md_check_recovery(mddev_t *mddev)
/* Only thing we do on a ro array is remove
* failed devices.
*/
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0 &&
!test_bit(Blocked, &rdev->flags) &&
@@ -7573,7 +7578,7 @@ void md_check_recovery(mddev_t *mddev)
}
}
-void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev)
{
sysfs_notify_dirent_safe(rdev->sysfs_state);
wait_event_timeout(rdev->blocked_wait,
@@ -7831,7 +7836,7 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
return rv;
}
-int rdev_set_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors,
+int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
int acknowledged)
{
int rv = md_set_badblocks(&rdev->badblocks,
@@ -7940,7 +7945,7 @@ out:
return rv;
}
-int rdev_clear_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors)
+int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors)
{
return md_clear_badblocks(&rdev->badblocks,
s + rdev->data_offset,
@@ -8074,13 +8079,14 @@ static int md_notify_reboot(struct notifier_block *this,
unsigned long code, void *x)
{
struct list_head *tmp;
- mddev_t *mddev;
+ struct mddev *mddev;
+ int need_delay = 0;
if ((code == SYS_DOWN) || (code == SYS_HALT) || (code == SYS_POWER_OFF)) {
printk(KERN_INFO "md: stopping all md devices.\n");
- for_each_mddev(mddev, tmp)
+ for_each_mddev(mddev, tmp) {
if (mddev_trylock(mddev)) {
/* Force a switch to readonly even array
* appears to still be in use. Hence
@@ -8089,13 +8095,16 @@ static int md_notify_reboot(struct notifier_block *this,
md_set_readonly(mddev, 100);
mddev_unlock(mddev);
}
+ need_delay = 1;
+ }
/*
* certain more exotic SCSI devices are known to be
* volatile wrt too early system reboots. While the
* right place to handle this issue is the given
* driver, we do want to have a safe RAID driver ...
*/
- mdelay(1000*1);
+ if (need_delay)
+ mdelay(1000*1);
}
return NOTIFY_DONE;
}
@@ -8108,7 +8117,7 @@ static struct notifier_block md_notifier = {
static void md_geninit(void)
{
- dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
+ pr_debug("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
proc_create("mdstat", S_IRUGO, NULL, &md_seq_fops);
}
@@ -8183,7 +8192,7 @@ void md_autodetect_dev(dev_t dev)
static void autostart_arrays(int part)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
struct detected_devices_node *node_detected_dev;
dev_t dev;
int i_scanned, i_passed;
@@ -8223,7 +8232,7 @@ static void autostart_arrays(int part)
static __exit void md_exit(void)
{
- mddev_t *mddev;
+ struct mddev *mddev;
struct list_head *tmp;
blk_unregister_region(MKDEV(MD_MAJOR,0), 1U << MINORBITS);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 0a309dc29b45..51c1d91557e0 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -1,5 +1,5 @@
/*
- md_k.h : kernel internal structure of the Linux MD driver
+ md.h : kernel internal structure of the Linux MD driver
Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
This program is free software; you can redistribute it and/or modify
@@ -26,9 +26,6 @@
#define MaxSector (~(sector_t)0)
-typedef struct mddev_s mddev_t;
-typedef struct mdk_rdev_s mdk_rdev_t;
-
/* Bad block numbers are stored sorted in a single page.
* 64bits is used for each block or extent.
* 54 bits are sector number, 9 bits are extent size,
@@ -39,12 +36,11 @@ typedef struct mdk_rdev_s mdk_rdev_t;
/*
* MD's 'extended' device
*/
-struct mdk_rdev_s
-{
+struct md_rdev {
struct list_head same_set; /* RAID devices within the same set */
sector_t sectors; /* Device size (in 512bytes sectors) */
- mddev_t *mddev; /* RAID array if running */
+ struct mddev *mddev; /* RAID array if running */
int last_events; /* IO event timestamp */
/*
@@ -168,7 +164,7 @@ struct mdk_rdev_s
extern int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
sector_t *first_bad, int *bad_sectors);
-static inline int is_badblock(mdk_rdev_t *rdev, sector_t s, int sectors,
+static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors,
sector_t *first_bad, int *bad_sectors)
{
if (unlikely(rdev->badblocks.count)) {
@@ -181,15 +177,14 @@ static inline int is_badblock(mdk_rdev_t *rdev, sector_t s, int sectors,
}
return 0;
}
-extern int rdev_set_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors,
+extern int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
int acknowledged);
-extern int rdev_clear_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors);
+extern int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors);
extern void md_ack_all_badblocks(struct badblocks *bb);
-struct mddev_s
-{
+struct mddev {
void *private;
- struct mdk_personality *pers;
+ struct md_personality *pers;
dev_t unit;
int md_minor;
struct list_head disks;
@@ -256,8 +251,8 @@ struct mddev_s
atomic_t plug_cnt; /* If device is expecting
* more bios soon.
*/
- struct mdk_thread_s *thread; /* management thread */
- struct mdk_thread_s *sync_thread; /* doing resync or reconstruct */
+ struct md_thread *thread; /* management thread */
+ struct md_thread *sync_thread; /* doing resync or reconstruct */
sector_t curr_resync; /* last block scheduled */
/* As resync requests can complete out of order, we cannot easily track
* how much resync has been completed. So we occasionally pause until
@@ -402,11 +397,11 @@ struct mddev_s
atomic_t flush_pending;
struct work_struct flush_work;
struct work_struct event_work; /* used by dm to report failure event */
- void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
+ void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev);
};
-static inline void rdev_dec_pending(mdk_rdev_t *rdev, mddev_t *mddev)
+static inline void rdev_dec_pending(struct md_rdev *rdev, struct mddev *mddev)
{
int faulty = test_bit(Faulty, &rdev->flags);
if (atomic_dec_and_test(&rdev->nr_pending) && faulty)
@@ -418,35 +413,35 @@ static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sect
atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
}
-struct mdk_personality
+struct md_personality
{
char *name;
int level;
struct list_head list;
struct module *owner;
- int (*make_request)(mddev_t *mddev, struct bio *bio);
- int (*run)(mddev_t *mddev);
- int (*stop)(mddev_t *mddev);
- void (*status)(struct seq_file *seq, mddev_t *mddev);
+ int (*make_request)(struct mddev *mddev, struct bio *bio);
+ int (*run)(struct mddev *mddev);
+ int (*stop)(struct mddev *mddev);
+ void (*status)(struct seq_file *seq, struct mddev *mddev);
/* error_handler must set ->faulty and clear ->in_sync
* if appropriate, and should abort recovery if needed
*/
- void (*error_handler)(mddev_t *mddev, mdk_rdev_t *rdev);
- int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev);
- int (*hot_remove_disk) (mddev_t *mddev, int number);
- int (*spare_active) (mddev_t *mddev);
- sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
- int (*resize) (mddev_t *mddev, sector_t sectors);
- sector_t (*size) (mddev_t *mddev, sector_t sectors, int raid_disks);
- int (*check_reshape) (mddev_t *mddev);
- int (*start_reshape) (mddev_t *mddev);
- void (*finish_reshape) (mddev_t *mddev);
+ void (*error_handler)(struct mddev *mddev, struct md_rdev *rdev);
+ int (*hot_add_disk) (struct mddev *mddev, struct md_rdev *rdev);
+ int (*hot_remove_disk) (struct mddev *mddev, int number);
+ int (*spare_active) (struct mddev *mddev);
+ sector_t (*sync_request)(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster);
+ int (*resize) (struct mddev *mddev, sector_t sectors);
+ sector_t (*size) (struct mddev *mddev, sector_t sectors, int raid_disks);
+ int (*check_reshape) (struct mddev *mddev);
+ int (*start_reshape) (struct mddev *mddev);
+ void (*finish_reshape) (struct mddev *mddev);
/* quiesce moves between quiescence states
* 0 - fully active
* 1 - no new requests allowed
* others - reserved
*/
- void (*quiesce) (mddev_t *mddev, int state);
+ void (*quiesce) (struct mddev *mddev, int state);
/* takeover is used to transition an array from one
* personality to another. The new personality must be able
* to handle the data in the current layout.
@@ -456,14 +451,14 @@ struct mdk_personality
* This needs to be installed and then ->run used to activate the
* array.
*/
- void *(*takeover) (mddev_t *mddev);
+ void *(*takeover) (struct mddev *mddev);
};
struct md_sysfs_entry {
struct attribute attr;
- ssize_t (*show)(mddev_t *, char *);
- ssize_t (*store)(mddev_t *, const char *, size_t);
+ ssize_t (*show)(struct mddev *, char *);
+ ssize_t (*store)(struct mddev *, const char *, size_t);
};
extern struct attribute_group md_bitmap_group;
@@ -479,19 +474,19 @@ static inline void sysfs_notify_dirent_safe(struct sysfs_dirent *sd)
sysfs_notify_dirent(sd);
}
-static inline char * mdname (mddev_t * mddev)
+static inline char * mdname (struct mddev * mddev)
{
return mddev->gendisk ? mddev->gendisk->disk_name : "mdX";
}
-static inline int sysfs_link_rdev(mddev_t *mddev, mdk_rdev_t *rdev)
+static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev)
{
char nm[20];
sprintf(nm, "rd%d", rdev->raid_disk);
return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
}
-static inline void sysfs_unlink_rdev(mddev_t *mddev, mdk_rdev_t *rdev)
+static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev)
{
char nm[20];
sprintf(nm, "rd%d", rdev->raid_disk);
@@ -514,14 +509,14 @@ static inline void sysfs_unlink_rdev(mddev_t *mddev, mdk_rdev_t *rdev)
#define rdev_for_each_rcu(rdev, mddev) \
list_for_each_entry_rcu(rdev, &((mddev)->disks), same_set)
-typedef struct mdk_thread_s {
- void (*run) (mddev_t *mddev);
- mddev_t *mddev;
+struct md_thread {
+ void (*run) (struct mddev *mddev);
+ struct mddev *mddev;
wait_queue_head_t wqueue;
unsigned long flags;
struct task_struct *tsk;
unsigned long timeout;
-} mdk_thread_t;
+};
#define THREAD_WAKEUP 0
@@ -556,48 +551,50 @@ static inline void safe_put_page(struct page *p)
if (p) put_page(p);
}
-extern int register_md_personality(struct mdk_personality *p);
-extern int unregister_md_personality(struct mdk_personality *p);
-extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev),
- mddev_t *mddev, const char *name);
-extern void md_unregister_thread(mdk_thread_t **threadp);
-extern void md_wakeup_thread(mdk_thread_t *thread);
-extern void md_check_recovery(mddev_t *mddev);
-extern void md_write_start(mddev_t *mddev, struct bio *bi);
-extern void md_write_end(mddev_t *mddev);
-extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
-extern void md_error(mddev_t *mddev, mdk_rdev_t *rdev);
-
-extern int mddev_congested(mddev_t *mddev, int bits);
-extern void md_flush_request(mddev_t *mddev, struct bio *bio);
-extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+extern int register_md_personality(struct md_personality *p);
+extern int unregister_md_personality(struct md_personality *p);
+extern struct md_thread *md_register_thread(
+ void (*run)(struct mddev *mddev),
+ struct mddev *mddev,
+ const char *name);
+extern void md_unregister_thread(struct md_thread **threadp);
+extern void md_wakeup_thread(struct md_thread *thread);
+extern void md_check_recovery(struct mddev *mddev);
+extern void md_write_start(struct mddev *mddev, struct bio *bi);
+extern void md_write_end(struct mddev *mddev);
+extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
+extern void md_error(struct mddev *mddev, struct md_rdev *rdev);
+
+extern int mddev_congested(struct mddev *mddev, int bits);
+extern void md_flush_request(struct mddev *mddev, struct bio *bio);
+extern void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
sector_t sector, int size, struct page *page);
-extern void md_super_wait(mddev_t *mddev);
-extern int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size,
+extern void md_super_wait(struct mddev *mddev);
+extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
struct page *page, int rw, bool metadata_op);
-extern void md_do_sync(mddev_t *mddev);
-extern void md_new_event(mddev_t *mddev);
-extern int md_allow_write(mddev_t *mddev);
-extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
-extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
-extern int md_check_no_bitmap(mddev_t *mddev);
-extern int md_integrity_register(mddev_t *mddev);
-extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
+extern void md_do_sync(struct mddev *mddev);
+extern void md_new_event(struct mddev *mddev);
+extern int md_allow_write(struct mddev *mddev);
+extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
+extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
+extern int md_check_no_bitmap(struct mddev *mddev);
+extern int md_integrity_register(struct mddev *mddev);
+extern void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev);
extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
extern void restore_bitmap_write_access(struct file *file);
-extern void mddev_init(mddev_t *mddev);
-extern int md_run(mddev_t *mddev);
-extern void md_stop(mddev_t *mddev);
-extern void md_stop_writes(mddev_t *mddev);
-extern int md_rdev_init(mdk_rdev_t *rdev);
+extern void mddev_init(struct mddev *mddev);
+extern int md_run(struct mddev *mddev);
+extern void md_stop(struct mddev *mddev);
+extern void md_stop_writes(struct mddev *mddev);
+extern int md_rdev_init(struct md_rdev *rdev);
-extern void mddev_suspend(mddev_t *mddev);
-extern void mddev_resume(mddev_t *mddev);
+extern void mddev_suspend(struct mddev *mddev);
+extern void mddev_resume(struct mddev *mddev);
extern struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
- mddev_t *mddev);
+ struct mddev *mddev);
extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
- mddev_t *mddev);
-extern int mddev_check_plugged(mddev_t *mddev);
+ struct mddev *mddev);
+extern int mddev_check_plugged(struct mddev *mddev);
extern void md_trim_bio(struct bio *bio, int offset, int size);
#endif /* _MD_MD_H */
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index d5b5fb300171..d32c785e17d4 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -31,7 +31,7 @@
#define NR_RESERVED_BUFS 32
-static int multipath_map (multipath_conf_t *conf)
+static int multipath_map (struct mpconf *conf)
{
int i, disks = conf->raid_disks;
@@ -42,7 +42,7 @@ static int multipath_map (multipath_conf_t *conf)
rcu_read_lock();
for (i = 0; i < disks; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
+ struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev);
if (rdev && test_bit(In_sync, &rdev->flags)) {
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
@@ -58,8 +58,8 @@ static int multipath_map (multipath_conf_t *conf)
static void multipath_reschedule_retry (struct multipath_bh *mp_bh)
{
unsigned long flags;
- mddev_t *mddev = mp_bh->mddev;
- multipath_conf_t *conf = mddev->private;
+ struct mddev *mddev = mp_bh->mddev;
+ struct mpconf *conf = mddev->private;
spin_lock_irqsave(&conf->device_lock, flags);
list_add(&mp_bh->retry_list, &conf->retry_list);
@@ -76,7 +76,7 @@ static void multipath_reschedule_retry (struct multipath_bh *mp_bh)
static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err)
{
struct bio *bio = mp_bh->master_bio;
- multipath_conf_t *conf = mp_bh->mddev->private;
+ struct mpconf *conf = mp_bh->mddev->private;
bio_endio(bio, err);
mempool_free(mp_bh, conf->pool);
@@ -86,8 +86,8 @@ static void multipath_end_request(struct bio *bio, int error)
{
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
struct multipath_bh *mp_bh = bio->bi_private;
- multipath_conf_t *conf = mp_bh->mddev->private;
- mdk_rdev_t *rdev = conf->multipaths[mp_bh->path].rdev;
+ struct mpconf *conf = mp_bh->mddev->private;
+ struct md_rdev *rdev = conf->multipaths[mp_bh->path].rdev;
if (uptodate)
multipath_end_bh_io(mp_bh, 0);
@@ -106,9 +106,9 @@ static void multipath_end_request(struct bio *bio, int error)
rdev_dec_pending(rdev, conf->mddev);
}
-static int multipath_make_request(mddev_t *mddev, struct bio * bio)
+static int multipath_make_request(struct mddev *mddev, struct bio * bio)
{
- multipath_conf_t *conf = mddev->private;
+ struct mpconf *conf = mddev->private;
struct multipath_bh * mp_bh;
struct multipath_info *multipath;
@@ -140,9 +140,9 @@ static int multipath_make_request(mddev_t *mddev, struct bio * bio)
return 0;
}
-static void multipath_status (struct seq_file *seq, mddev_t *mddev)
+static void multipath_status (struct seq_file *seq, struct mddev *mddev)
{
- multipath_conf_t *conf = mddev->private;
+ struct mpconf *conf = mddev->private;
int i;
seq_printf (seq, " [%d/%d] [", conf->raid_disks,
@@ -156,8 +156,8 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev)
static int multipath_congested(void *data, int bits)
{
- mddev_t *mddev = data;
- multipath_conf_t *conf = mddev->private;
+ struct mddev *mddev = data;
+ struct mpconf *conf = mddev->private;
int i, ret = 0;
if (mddev_congested(mddev, bits))
@@ -165,7 +165,7 @@ static int multipath_congested(void *data, int bits)
rcu_read_lock();
for (i = 0; i < mddev->raid_disks ; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
+ struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev);
if (rdev && !test_bit(Faulty, &rdev->flags)) {
struct request_queue *q = bdev_get_queue(rdev->bdev);
@@ -183,9 +183,9 @@ static int multipath_congested(void *data, int bits)
/*
* Careful, this can execute in IRQ contexts as well!
*/
-static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev)
+static void multipath_error (struct mddev *mddev, struct md_rdev *rdev)
{
- multipath_conf_t *conf = mddev->private;
+ struct mpconf *conf = mddev->private;
char b[BDEVNAME_SIZE];
if (conf->raid_disks - mddev->degraded <= 1) {
@@ -218,7 +218,7 @@ static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev)
conf->raid_disks - mddev->degraded);
}
-static void print_multipath_conf (multipath_conf_t *conf)
+static void print_multipath_conf (struct mpconf *conf)
{
int i;
struct multipath_info *tmp;
@@ -242,9 +242,9 @@ static void print_multipath_conf (multipath_conf_t *conf)
}
-static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int multipath_add_disk(struct mddev *mddev, struct md_rdev *rdev)
{
- multipath_conf_t *conf = mddev->private;
+ struct mpconf *conf = mddev->private;
struct request_queue *q;
int err = -EEXIST;
int path;
@@ -291,11 +291,11 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
return err;
}
-static int multipath_remove_disk(mddev_t *mddev, int number)
+static int multipath_remove_disk(struct mddev *mddev, int number)
{
- multipath_conf_t *conf = mddev->private;
+ struct mpconf *conf = mddev->private;
int err = 0;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
struct multipath_info *p = conf->multipaths + number;
print_multipath_conf(conf);
@@ -335,12 +335,12 @@ abort:
* 3. Performs writes following reads for array syncronising.
*/
-static void multipathd (mddev_t *mddev)
+static void multipathd (struct mddev *mddev)
{
struct multipath_bh *mp_bh;
struct bio *bio;
unsigned long flags;
- multipath_conf_t *conf = mddev->private;
+ struct mpconf *conf = mddev->private;
struct list_head *head = &conf->retry_list;
md_check_recovery(mddev);
@@ -379,7 +379,7 @@ static void multipathd (mddev_t *mddev)
spin_unlock_irqrestore(&conf->device_lock, flags);
}
-static sector_t multipath_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t multipath_size(struct mddev *mddev, sector_t sectors, int raid_disks)
{
WARN_ONCE(sectors || raid_disks,
"%s does not support generic reshape\n", __func__);
@@ -387,12 +387,12 @@ static sector_t multipath_size(mddev_t *mddev, sector_t sectors, int raid_disks)
return mddev->dev_sectors;
}
-static int multipath_run (mddev_t *mddev)
+static int multipath_run (struct mddev *mddev)
{
- multipath_conf_t *conf;
+ struct mpconf *conf;
int disk_idx;
struct multipath_info *disk;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int working_disks;
if (md_check_no_bitmap(mddev))
@@ -409,7 +409,7 @@ static int multipath_run (mddev_t *mddev)
* should be freed in multipath_stop()]
*/
- conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL);
+ conf = kzalloc(sizeof(struct mpconf), GFP_KERNEL);
mddev->private = conf;
if (!conf) {
printk(KERN_ERR
@@ -510,9 +510,9 @@ out:
}
-static int multipath_stop (mddev_t *mddev)
+static int multipath_stop (struct mddev *mddev)
{
- multipath_conf_t *conf = mddev->private;
+ struct mpconf *conf = mddev->private;
md_unregister_thread(&mddev->thread);
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
@@ -523,7 +523,7 @@ static int multipath_stop (mddev_t *mddev)
return 0;
}
-static struct mdk_personality multipath_personality =
+static struct md_personality multipath_personality =
{
.name = "multipath",
.level = LEVEL_MULTIPATH,
diff --git a/drivers/md/multipath.h b/drivers/md/multipath.h
index 3c5a45eb5f8a..717c60f62898 100644
--- a/drivers/md/multipath.h
+++ b/drivers/md/multipath.h
@@ -2,11 +2,11 @@
#define _MULTIPATH_H
struct multipath_info {
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
};
-struct multipath_private_data {
- mddev_t *mddev;
+struct mpconf {
+ struct mddev *mddev;
struct multipath_info *multipaths;
int raid_disks;
spinlock_t device_lock;
@@ -15,8 +15,6 @@ struct multipath_private_data {
mempool_t *pool;
};
-typedef struct multipath_private_data multipath_conf_t;
-
/*
* this is our 'private' 'collective' MULTIPATH buffer head.
* it contains information about what kind of IO operations were started
@@ -24,7 +22,7 @@ typedef struct multipath_private_data multipath_conf_t;
*/
struct multipath_bh {
- mddev_t *mddev;
+ struct mddev *mddev;
struct bio *master_bio;
struct bio bio;
int path;
diff --git a/drivers/md/persistent-data/Kconfig b/drivers/md/persistent-data/Kconfig
new file mode 100644
index 000000000000..ceb359050a59
--- /dev/null
+++ b/drivers/md/persistent-data/Kconfig
@@ -0,0 +1,8 @@
+config DM_PERSISTENT_DATA
+ tristate
+ depends on BLK_DEV_DM && EXPERIMENTAL
+ select LIBCRC32C
+ select DM_BUFIO
+ ---help---
+ Library providing immutable on-disk data structure support for
+ device-mapper targets such as the thin provisioning target.
diff --git a/drivers/md/persistent-data/Makefile b/drivers/md/persistent-data/Makefile
new file mode 100644
index 000000000000..cfa95f662230
--- /dev/null
+++ b/drivers/md/persistent-data/Makefile
@@ -0,0 +1,11 @@
+obj-$(CONFIG_DM_PERSISTENT_DATA) += dm-persistent-data.o
+dm-persistent-data-objs := \
+ dm-block-manager.o \
+ dm-space-map-checker.o \
+ dm-space-map-common.o \
+ dm-space-map-disk.o \
+ dm-space-map-metadata.o \
+ dm-transaction-manager.o \
+ dm-btree.o \
+ dm-btree-remove.o \
+ dm-btree-spine.o
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
new file mode 100644
index 000000000000..0317ecdc6e53
--- /dev/null
+++ b/drivers/md/persistent-data/dm-block-manager.c
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#include "dm-block-manager.h"
+#include "dm-persistent-data-internal.h"
+#include "../dm-bufio.h"
+
+#include <linux/crc32c.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/rwsem.h>
+#include <linux/device-mapper.h>
+#include <linux/stacktrace.h>
+
+#define DM_MSG_PREFIX "block manager"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This is a read/write semaphore with a couple of differences.
+ *
+ * i) There is a restriction on the number of concurrent read locks that
+ * 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.
+ *
+ * iii) Priority is given to write locks.
+ */
+#define MAX_HOLDERS 4
+#define MAX_STACK 10
+
+typedef unsigned long stack_entries[MAX_STACK];
+
+struct block_lock {
+ spinlock_t lock;
+ __s32 count;
+ struct list_head waiters;
+ struct task_struct *holders[MAX_HOLDERS];
+
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+ struct stack_trace traces[MAX_HOLDERS];
+ stack_entries entries[MAX_HOLDERS];
+#endif
+};
+
+struct waiter {
+ struct list_head list;
+ struct task_struct *task;
+ int wants_write;
+};
+
+static unsigned __find_holder(struct block_lock *lock,
+ struct task_struct *task)
+{
+ unsigned i;
+
+ for (i = 0; i < MAX_HOLDERS; i++)
+ if (lock->holders[i] == task)
+ break;
+
+ BUG_ON(i == MAX_HOLDERS);
+ return i;
+}
+
+/* call this *after* you increment lock->count */
+static void __add_holder(struct block_lock *lock, struct task_struct *task)
+{
+ unsigned h = __find_holder(lock, NULL);
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+ struct stack_trace *t;
+#endif
+
+ get_task_struct(task);
+ lock->holders[h] = task;
+
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+ t = lock->traces + h;
+ t->nr_entries = 0;
+ t->max_entries = MAX_STACK;
+ t->entries = lock->entries[h];
+ t->skip = 2;
+ save_stack_trace(t);
+#endif
+}
+
+/* call this *before* you decrement lock->count */
+static void __del_holder(struct block_lock *lock, struct task_struct *task)
+{
+ unsigned h = __find_holder(lock, task);
+ lock->holders[h] = NULL;
+ put_task_struct(task);
+}
+
+static int __check_holder(struct block_lock *lock)
+{
+ unsigned i;
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+ static struct stack_trace t;
+ static stack_entries entries;
+#endif
+
+ for (i = 0; i < MAX_HOLDERS; i++) {
+ if (lock->holders[i] == current) {
+ DMERR("recursive lock detected in pool metadata");
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+ DMERR("previously held here:");
+ print_stack_trace(lock->traces + i, 4);
+
+ DMERR("subsequent aquisition attempted here:");
+ t.nr_entries = 0;
+ t.max_entries = MAX_STACK;
+ t.entries = entries;
+ t.skip = 3;
+ save_stack_trace(&t);
+ print_stack_trace(&t, 4);
+#endif
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void __wait(struct waiter *w)
+{
+ for (;;) {
+ set_task_state(current, TASK_UNINTERRUPTIBLE);
+
+ if (!w->task)
+ break;
+
+ schedule();
+ }
+
+ set_task_state(current, TASK_RUNNING);
+}
+
+static void __wake_waiter(struct waiter *w)
+{
+ struct task_struct *task;
+
+ list_del(&w->list);
+ task = w->task;
+ smp_mb();
+ w->task = NULL;
+ wake_up_process(task);
+}
+
+/*
+ * We either wake a few readers or a single writer.
+ */
+static void __wake_many(struct block_lock *lock)
+{
+ struct waiter *w, *tmp;
+
+ BUG_ON(lock->count < 0);
+ list_for_each_entry_safe(w, tmp, &lock->waiters, list) {
+ if (lock->count >= MAX_HOLDERS)
+ return;
+
+ if (w->wants_write) {
+ if (lock->count > 0)
+ return; /* still read locked */
+
+ lock->count = -1;
+ __add_holder(lock, w->task);
+ __wake_waiter(w);
+ return;
+ }
+
+ lock->count++;
+ __add_holder(lock, w->task);
+ __wake_waiter(w);
+ }
+}
+
+static void bl_init(struct block_lock *lock)
+{
+ int i;
+
+ spin_lock_init(&lock->lock);
+ lock->count = 0;
+ INIT_LIST_HEAD(&lock->waiters);
+ for (i = 0; i < MAX_HOLDERS; i++)
+ lock->holders[i] = NULL;
+}
+
+static int __available_for_read(struct block_lock *lock)
+{
+ return lock->count >= 0 &&
+ lock->count < MAX_HOLDERS &&
+ list_empty(&lock->waiters);
+}
+
+static int bl_down_read(struct block_lock *lock)
+{
+ int r;
+ struct waiter w;
+
+ spin_lock(&lock->lock);
+ r = __check_holder(lock);
+ if (r) {
+ spin_unlock(&lock->lock);
+ return r;
+ }
+
+ if (__available_for_read(lock)) {
+ lock->count++;
+ __add_holder(lock, current);
+ spin_unlock(&lock->lock);
+ return 0;
+ }
+
+ get_task_struct(current);
+
+ w.task = current;
+ w.wants_write = 0;
+ list_add_tail(&w.list, &lock->waiters);
+ spin_unlock(&lock->lock);
+
+ __wait(&w);
+ put_task_struct(current);
+ return 0;
+}
+
+static int bl_down_read_nonblock(struct block_lock *lock)
+{
+ int r;
+
+ spin_lock(&lock->lock);
+ r = __check_holder(lock);
+ if (r)
+ goto out;
+
+ if (__available_for_read(lock)) {
+ lock->count++;
+ __add_holder(lock, current);
+ r = 0;
+ } else
+ r = -EWOULDBLOCK;
+
+out:
+ spin_unlock(&lock->lock);
+ return r;
+}
+
+static void bl_up_read(struct block_lock *lock)
+{
+ spin_lock(&lock->lock);
+ BUG_ON(lock->count <= 0);
+ __del_holder(lock, current);
+ --lock->count;
+ if (!list_empty(&lock->waiters))
+ __wake_many(lock);
+ spin_unlock(&lock->lock);
+}
+
+static int bl_down_write(struct block_lock *lock)
+{
+ int r;
+ struct waiter w;
+
+ spin_lock(&lock->lock);
+ r = __check_holder(lock);
+ if (r) {
+ spin_unlock(&lock->lock);
+ return r;
+ }
+
+ if (lock->count == 0 && list_empty(&lock->waiters)) {
+ lock->count = -1;
+ __add_holder(lock, current);
+ spin_unlock(&lock->lock);
+ return 0;
+ }
+
+ get_task_struct(current);
+ w.task = current;
+ w.wants_write = 1;
+
+ /*
+ * Writers given priority. We know there's only one mutator in the
+ * system, so ignoring the ordering reversal.
+ */
+ list_add(&w.list, &lock->waiters);
+ spin_unlock(&lock->lock);
+
+ __wait(&w);
+ put_task_struct(current);
+
+ return 0;
+}
+
+static void bl_up_write(struct block_lock *lock)
+{
+ spin_lock(&lock->lock);
+ __del_holder(lock, current);
+ lock->count = 0;
+ if (!list_empty(&lock->waiters))
+ __wake_many(lock);
+ spin_unlock(&lock->lock);
+}
+
+static void report_recursive_bug(dm_block_t b, int r)
+{
+ if (r == -EINVAL)
+ DMERR("recursive acquisition of block %llu requested.",
+ (unsigned long long) b);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Block manager is currently implemented using dm-bufio. struct
+ * dm_block_manager and struct dm_block map directly onto a couple of
+ * structs in the bufio interface. I want to retain the freedom to move
+ * away from bufio in the future. So these structs are just cast within
+ * this .c file, rather than making it through to the public interface.
+ */
+static struct dm_buffer *to_buffer(struct dm_block *b)
+{
+ return (struct dm_buffer *) b;
+}
+
+static struct dm_bufio_client *to_bufio(struct dm_block_manager *bm)
+{
+ return (struct dm_bufio_client *) bm;
+}
+
+dm_block_t dm_block_location(struct dm_block *b)
+{
+ return dm_bufio_get_block_number(to_buffer(b));
+}
+EXPORT_SYMBOL_GPL(dm_block_location);
+
+void *dm_block_data(struct dm_block *b)
+{
+ return dm_bufio_get_block_data(to_buffer(b));
+}
+EXPORT_SYMBOL_GPL(dm_block_data);
+
+struct buffer_aux {
+ struct dm_block_validator *validator;
+ struct block_lock lock;
+ int write_locked;
+};
+
+static void dm_block_manager_alloc_callback(struct dm_buffer *buf)
+{
+ struct buffer_aux *aux = dm_bufio_get_aux_data(buf);
+ aux->validator = NULL;
+ bl_init(&aux->lock);
+}
+
+static void dm_block_manager_write_callback(struct dm_buffer *buf)
+{
+ struct buffer_aux *aux = dm_bufio_get_aux_data(buf);
+ if (aux->validator) {
+ aux->validator->prepare_for_write(aux->validator, (struct dm_block *) buf,
+ dm_bufio_get_block_size(dm_bufio_get_client(buf)));
+ }
+}
+
+/*----------------------------------------------------------------
+ * Public interface
+ *--------------------------------------------------------------*/
+struct dm_block_manager *dm_block_manager_create(struct block_device *bdev,
+ unsigned block_size,
+ unsigned cache_size,
+ unsigned max_held_per_thread)
+{
+ return (struct dm_block_manager *)
+ dm_bufio_client_create(bdev, block_size, max_held_per_thread,
+ sizeof(struct buffer_aux),
+ dm_block_manager_alloc_callback,
+ dm_block_manager_write_callback);
+}
+EXPORT_SYMBOL_GPL(dm_block_manager_create);
+
+void dm_block_manager_destroy(struct dm_block_manager *bm)
+{
+ return dm_bufio_client_destroy(to_bufio(bm));
+}
+EXPORT_SYMBOL_GPL(dm_block_manager_destroy);
+
+unsigned dm_bm_block_size(struct dm_block_manager *bm)
+{
+ return dm_bufio_get_block_size(to_bufio(bm));
+}
+EXPORT_SYMBOL_GPL(dm_bm_block_size);
+
+dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm)
+{
+ return dm_bufio_get_device_size(to_bufio(bm));
+}
+
+static int dm_bm_validate_buffer(struct dm_block_manager *bm,
+ struct dm_buffer *buf,
+ struct buffer_aux *aux,
+ struct dm_block_validator *v)
+{
+ if (unlikely(!aux->validator)) {
+ int r;
+ if (!v)
+ return 0;
+ r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(to_bufio(bm)));
+ if (unlikely(r))
+ return r;
+ aux->validator = v;
+ } else {
+ if (unlikely(aux->validator != v)) {
+ DMERR("validator mismatch (old=%s vs new=%s) for block %llu",
+ aux->validator->name, v ? v->name : "NULL",
+ (unsigned long long)
+ dm_bufio_get_block_number(buf));
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b,
+ struct dm_block_validator *v,
+ struct dm_block **result)
+{
+ struct buffer_aux *aux;
+ void *p;
+ int r;
+
+ p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result);
+ if (unlikely(IS_ERR(p)))
+ return PTR_ERR(p);
+
+ aux = dm_bufio_get_aux_data(to_buffer(*result));
+ r = bl_down_read(&aux->lock);
+ if (unlikely(r)) {
+ dm_bufio_release(to_buffer(*result));
+ report_recursive_bug(b, r);
+ return r;
+ }
+
+ aux->write_locked = 0;
+
+ r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+ if (unlikely(r)) {
+ bl_up_read(&aux->lock);
+ dm_bufio_release(to_buffer(*result));
+ return r;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_read_lock);
+
+int dm_bm_write_lock(struct dm_block_manager *bm,
+ dm_block_t b, struct dm_block_validator *v,
+ struct dm_block **result)
+{
+ struct buffer_aux *aux;
+ void *p;
+ int r;
+
+ p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result);
+ if (unlikely(IS_ERR(p)))
+ return PTR_ERR(p);
+
+ aux = dm_bufio_get_aux_data(to_buffer(*result));
+ r = bl_down_write(&aux->lock);
+ if (r) {
+ dm_bufio_release(to_buffer(*result));
+ report_recursive_bug(b, r);
+ return r;
+ }
+
+ aux->write_locked = 1;
+
+ r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+ if (unlikely(r)) {
+ bl_up_write(&aux->lock);
+ dm_bufio_release(to_buffer(*result));
+ return r;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_write_lock);
+
+int dm_bm_read_try_lock(struct dm_block_manager *bm,
+ dm_block_t b, struct dm_block_validator *v,
+ struct dm_block **result)
+{
+ struct buffer_aux *aux;
+ void *p;
+ int r;
+
+ p = dm_bufio_get(to_bufio(bm), b, (struct dm_buffer **) result);
+ if (unlikely(IS_ERR(p)))
+ return PTR_ERR(p);
+ if (unlikely(!p))
+ return -EWOULDBLOCK;
+
+ aux = dm_bufio_get_aux_data(to_buffer(*result));
+ r = bl_down_read_nonblock(&aux->lock);
+ if (r < 0) {
+ dm_bufio_release(to_buffer(*result));
+ report_recursive_bug(b, r);
+ return r;
+ }
+ aux->write_locked = 0;
+
+ r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+ if (unlikely(r)) {
+ bl_up_read(&aux->lock);
+ dm_bufio_release(to_buffer(*result));
+ return r;
+ }
+
+ return 0;
+}
+
+int dm_bm_write_lock_zero(struct dm_block_manager *bm,
+ dm_block_t b, struct dm_block_validator *v,
+ struct dm_block **result)
+{
+ int r;
+ struct buffer_aux *aux;
+ void *p;
+
+ p = dm_bufio_new(to_bufio(bm), b, (struct dm_buffer **) result);
+ if (unlikely(IS_ERR(p)))
+ return PTR_ERR(p);
+
+ memset(p, 0, dm_bm_block_size(bm));
+
+ aux = dm_bufio_get_aux_data(to_buffer(*result));
+ r = bl_down_write(&aux->lock);
+ if (r) {
+ dm_bufio_release(to_buffer(*result));
+ return r;
+ }
+
+ aux->write_locked = 1;
+ aux->validator = v;
+
+ return 0;
+}
+
+int dm_bm_unlock(struct dm_block *b)
+{
+ struct buffer_aux *aux;
+ aux = dm_bufio_get_aux_data(to_buffer(b));
+
+ if (aux->write_locked) {
+ dm_bufio_mark_buffer_dirty(to_buffer(b));
+ bl_up_write(&aux->lock);
+ } else
+ bl_up_read(&aux->lock);
+
+ dm_bufio_release(to_buffer(b));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_unlock);
+
+int dm_bm_unlock_move(struct dm_block *b, dm_block_t n)
+{
+ struct buffer_aux *aux;
+
+ aux = dm_bufio_get_aux_data(to_buffer(b));
+
+ if (aux->write_locked) {
+ dm_bufio_mark_buffer_dirty(to_buffer(b));
+ bl_up_write(&aux->lock);
+ } else
+ bl_up_read(&aux->lock);
+
+ dm_bufio_release_move(to_buffer(b), n);
+ return 0;
+}
+
+int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
+ struct dm_block *superblock)
+{
+ int r;
+
+ r = dm_bufio_write_dirty_buffers(to_bufio(bm));
+ if (unlikely(r))
+ return r;
+ r = dm_bufio_issue_flush(to_bufio(bm));
+ if (unlikely(r))
+ return r;
+
+ dm_bm_unlock(superblock);
+
+ r = dm_bufio_write_dirty_buffers(to_bufio(bm));
+ if (unlikely(r))
+ return r;
+ r = dm_bufio_issue_flush(to_bufio(bm));
+ if (unlikely(r))
+ return r;
+
+ return 0;
+}
+
+u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor)
+{
+ return crc32c(~(u32) 0, data, len) ^ init_xor;
+}
+EXPORT_SYMBOL_GPL(dm_bm_checksum);
+
+/*----------------------------------------------------------------*/
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+MODULE_DESCRIPTION("Immutable metadata library for dm");
+
+/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h
new file mode 100644
index 000000000000..924833d2dfa6
--- /dev/null
+++ b/drivers/md/persistent-data/dm-block-manager.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_BLOCK_MANAGER_H
+#define _LINUX_DM_BLOCK_MANAGER_H
+
+#include <linux/types.h>
+#include <linux/blkdev.h>
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Block number.
+ */
+typedef uint64_t dm_block_t;
+struct dm_block;
+
+dm_block_t dm_block_location(struct dm_block *b);
+void *dm_block_data(struct dm_block *b);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * @name should be a unique identifier for the block manager, no longer
+ * than 32 chars.
+ *
+ * @max_held_per_thread should be the maximum number of locks, read or
+ * write, that an individual thread holds at any one time.
+ */
+struct dm_block_manager;
+struct dm_block_manager *dm_block_manager_create(
+ struct block_device *bdev, unsigned block_size,
+ unsigned cache_size, unsigned max_held_per_thread);
+void dm_block_manager_destroy(struct dm_block_manager *bm);
+
+unsigned dm_bm_block_size(struct dm_block_manager *bm);
+dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * The validator allows the caller to verify newly-read data and modify
+ * the data just before writing, e.g. to calculate checksums. It's
+ * important to be consistent with your use of validators. The only time
+ * you can change validators is if you call dm_bm_write_lock_zero.
+ */
+struct dm_block_validator {
+ const char *name;
+ void (*prepare_for_write)(struct dm_block_validator *v, struct dm_block *b, size_t block_size);
+
+ /*
+ * Return 0 if the checksum is valid or < 0 on error.
+ */
+ int (*check)(struct dm_block_validator *v, struct dm_block *b, size_t block_size);
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * You can have multiple concurrent readers or a single writer holding a
+ * block lock.
+ */
+
+/*
+ * dm_bm_lock() locks a block and returns through @result a pointer to
+ * memory that holds a copy of that block. If you have write-locked the
+ * block then any changes you make to memory pointed to by @result will be
+ * written back to the disk sometime after dm_bm_unlock is called.
+ */
+int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b,
+ struct dm_block_validator *v,
+ struct dm_block **result);
+
+int dm_bm_write_lock(struct dm_block_manager *bm, dm_block_t b,
+ struct dm_block_validator *v,
+ struct dm_block **result);
+
+/*
+ * The *_try_lock variants return -EWOULDBLOCK if the block isn't
+ * available immediately.
+ */
+int dm_bm_read_try_lock(struct dm_block_manager *bm, dm_block_t b,
+ struct dm_block_validator *v,
+ struct dm_block **result);
+
+/*
+ * Use dm_bm_write_lock_zero() when you know you're going to
+ * overwrite the block completely. It saves a disk read.
+ */
+int dm_bm_write_lock_zero(struct dm_block_manager *bm, dm_block_t b,
+ struct dm_block_validator *v,
+ struct dm_block **result);
+
+int dm_bm_unlock(struct dm_block *b);
+
+/*
+ * An optimisation; we often want to copy a block's contents to a new
+ * block. eg, as part of the shadowing operation. It's far better for
+ * bufio to do this move behind the scenes than hold 2 locks and memcpy the
+ * data.
+ */
+int dm_bm_unlock_move(struct dm_block *b, dm_block_t n);
+
+/*
+ * It's a common idiom to have a superblock that should be committed last.
+ *
+ * @superblock should be write-locked on entry. It will be unlocked during
+ * this function. All dirty blocks are guaranteed to be written and flushed
+ * before the superblock.
+ *
+ * This method always blocks.
+ */
+int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
+ struct dm_block *superblock);
+
+u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor);
+
+/*----------------------------------------------------------------*/
+
+#endif /* _LINUX_DM_BLOCK_MANAGER_H */
diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h
new file mode 100644
index 000000000000..d279c768f8f1
--- /dev/null
+++ b/drivers/md/persistent-data/dm-btree-internal.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BTREE_INTERNAL_H
+#define DM_BTREE_INTERNAL_H
+
+#include "dm-btree.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We'll need 2 accessor functions for n->csum and n->blocknr
+ * to support dm-btree-spine.c in that case.
+ */
+
+enum node_flags {
+ INTERNAL_NODE = 1,
+ LEAF_NODE = 1 << 1
+};
+
+/*
+ * Every btree node begins with this structure. Make sure it's a multiple
+ * of 8-bytes in size, otherwise the 64bit keys will be mis-aligned.
+ */
+struct node_header {
+ __le32 csum;
+ __le32 flags;
+ __le64 blocknr; /* Block this node is supposed to live in. */
+
+ __le32 nr_entries;
+ __le32 max_entries;
+ __le32 value_size;
+ __le32 padding;
+} __packed;
+
+struct node {
+ struct node_header header;
+ __le64 keys[0];
+} __packed;
+
+
+void inc_children(struct dm_transaction_manager *tm, struct node *n,
+ struct dm_btree_value_type *vt);
+
+int new_block(struct dm_btree_info *info, struct dm_block **result);
+int unlock_block(struct dm_btree_info *info, struct dm_block *b);
+
+/*
+ * Spines keep track of the rolling locks. There are 2 variants, read-only
+ * and one that uses shadowing. These are separate structs to allow the
+ * type checker to spot misuse, for example accidentally calling read_lock
+ * on a shadow spine.
+ */
+struct ro_spine {
+ struct dm_btree_info *info;
+
+ int count;
+ struct dm_block *nodes[2];
+};
+
+void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info);
+int exit_ro_spine(struct ro_spine *s);
+int ro_step(struct ro_spine *s, dm_block_t new_child);
+struct node *ro_node(struct ro_spine *s);
+
+struct shadow_spine {
+ struct dm_btree_info *info;
+
+ int count;
+ struct dm_block *nodes[2];
+
+ dm_block_t root;
+};
+
+void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info);
+int exit_shadow_spine(struct shadow_spine *s);
+
+int shadow_step(struct shadow_spine *s, dm_block_t b,
+ struct dm_btree_value_type *vt);
+
+/*
+ * The spine must have at least one entry before calling this.
+ */
+struct dm_block *shadow_current(struct shadow_spine *s);
+
+/*
+ * The spine must have at least two entries before calling this.
+ */
+struct dm_block *shadow_parent(struct shadow_spine *s);
+
+int shadow_has_parent(struct shadow_spine *s);
+
+int shadow_root(struct shadow_spine *s);
+
+/*
+ * Some inlines.
+ */
+static inline __le64 *key_ptr(struct node *n, uint32_t index)
+{
+ return n->keys + index;
+}
+
+static inline void *value_base(struct node *n)
+{
+ return &n->keys[le32_to_cpu(n->header.max_entries)];
+}
+
+/*
+ * FIXME: Now that value size is stored in node we don't need the third parm.
+ */
+static inline void *value_ptr(struct node *n, uint32_t index, size_t value_size)
+{
+ BUG_ON(value_size != le32_to_cpu(n->header.value_size));
+ return value_base(n) + (value_size * index);
+}
+
+/*
+ * Assumes the values are suitably-aligned and converts to core format.
+ */
+static inline uint64_t value64(struct node *n, uint32_t index)
+{
+ __le64 *values_le = value_base(n);
+
+ return le64_to_cpu(values_le[index]);
+}
+
+/*
+ * Searching for a key within a single node.
+ */
+int lower_bound(struct node *n, uint64_t key);
+
+extern struct dm_block_validator btree_node_validator;
+
+#endif /* DM_BTREE_INTERNAL_H */
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c
new file mode 100644
index 000000000000..65fd85ec6514
--- /dev/null
+++ b/drivers/md/persistent-data/dm-btree-remove.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree.h"
+#include "dm-btree-internal.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/module.h>
+
+/*
+ * Removing an entry from a btree
+ * ==============================
+ *
+ * A very important constraint for our btree is that no node, except the
+ * root, may have fewer than a certain number of entries.
+ * (MIN_ENTRIES <= nr_entries <= MAX_ENTRIES).
+ *
+ * Ensuring this is complicated by the way we want to only ever hold the
+ * locks on 2 nodes concurrently, and only change nodes in a top to bottom
+ * fashion.
+ *
+ * Each node may have a left or right sibling. When decending the spine,
+ * if a node contains only MIN_ENTRIES then we try and increase this to at
+ * least MIN_ENTRIES + 1. We do this in the following ways:
+ *
+ * [A] No siblings => this can only happen if the node is the root, in which
+ * case we copy the childs contents over the root.
+ *
+ * [B] No left sibling
+ * ==> rebalance(node, right sibling)
+ *
+ * [C] No right sibling
+ * ==> rebalance(left sibling, node)
+ *
+ * [D] Both siblings, total_entries(left, node, right) <= DEL_THRESHOLD
+ * ==> delete node adding it's contents to left and right
+ *
+ * [E] Both siblings, total_entries(left, node, right) > DEL_THRESHOLD
+ * ==> rebalance(left, node, right)
+ *
+ * After these operations it's possible that the our original node no
+ * longer contains the desired sub tree. For this reason this rebalancing
+ * is performed on the children of the current node. This also avoids
+ * having a special case for the root.
+ *
+ * Once this rebalancing has occurred we can then step into the child node
+ * for internal nodes. Or delete the entry for leaf nodes.
+ */
+
+/*
+ * Some little utilities for moving node data around.
+ */
+static void node_shift(struct node *n, int shift)
+{
+ uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
+ uint32_t value_size = le32_to_cpu(n->header.value_size);
+
+ if (shift < 0) {
+ shift = -shift;
+ BUG_ON(shift > nr_entries);
+ BUG_ON((void *) key_ptr(n, shift) >= value_ptr(n, shift, value_size));
+ memmove(key_ptr(n, 0),
+ key_ptr(n, shift),
+ (nr_entries - shift) * sizeof(__le64));
+ memmove(value_ptr(n, 0, value_size),
+ value_ptr(n, shift, value_size),
+ (nr_entries - shift) * value_size);
+ } else {
+ BUG_ON(nr_entries + shift > le32_to_cpu(n->header.max_entries));
+ memmove(key_ptr(n, shift),
+ key_ptr(n, 0),
+ nr_entries * sizeof(__le64));
+ memmove(value_ptr(n, shift, value_size),
+ value_ptr(n, 0, value_size),
+ nr_entries * value_size);
+ }
+}
+
+static void node_copy(struct node *left, struct node *right, int shift)
+{
+ uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+ uint32_t value_size = le32_to_cpu(left->header.value_size);
+ BUG_ON(value_size != le32_to_cpu(right->header.value_size));
+
+ if (shift < 0) {
+ shift = -shift;
+ BUG_ON(nr_left + shift > le32_to_cpu(left->header.max_entries));
+ memcpy(key_ptr(left, nr_left),
+ key_ptr(right, 0),
+ shift * sizeof(__le64));
+ memcpy(value_ptr(left, nr_left, value_size),
+ value_ptr(right, 0, value_size),
+ shift * value_size);
+ } else {
+ BUG_ON(shift > le32_to_cpu(right->header.max_entries));
+ memcpy(key_ptr(right, 0),
+ key_ptr(left, nr_left - shift),
+ shift * sizeof(__le64));
+ memcpy(value_ptr(right, 0, value_size),
+ value_ptr(left, nr_left - shift, value_size),
+ shift * value_size);
+ }
+}
+
+/*
+ * Delete a specific entry from a leaf node.
+ */
+static void delete_at(struct node *n, unsigned index)
+{
+ unsigned nr_entries = le32_to_cpu(n->header.nr_entries);
+ unsigned nr_to_copy = nr_entries - (index + 1);
+ uint32_t value_size = le32_to_cpu(n->header.value_size);
+ BUG_ON(index >= nr_entries);
+
+ if (nr_to_copy) {
+ memmove(key_ptr(n, index),
+ key_ptr(n, index + 1),
+ nr_to_copy * sizeof(__le64));
+
+ memmove(value_ptr(n, index, value_size),
+ value_ptr(n, index + 1, value_size),
+ nr_to_copy * value_size);
+ }
+
+ n->header.nr_entries = cpu_to_le32(nr_entries - 1);
+}
+
+static unsigned del_threshold(struct node *n)
+{
+ return le32_to_cpu(n->header.max_entries) / 3;
+}
+
+static unsigned merge_threshold(struct node *n)
+{
+ /*
+ * The extra one is because we know we're potentially going to
+ * delete an entry.
+ */
+ return 2 * (le32_to_cpu(n->header.max_entries) / 3) + 1;
+}
+
+struct child {
+ unsigned index;
+ struct dm_block *block;
+ struct node *n;
+};
+
+static struct dm_btree_value_type le64_type = {
+ .context = NULL,
+ .size = sizeof(__le64),
+ .inc = NULL,
+ .dec = NULL,
+ .equal = NULL
+};
+
+static int init_child(struct dm_btree_info *info, struct node *parent,
+ unsigned index, struct child *result)
+{
+ int r, inc;
+ dm_block_t root;
+
+ result->index = index;
+ root = value64(parent, index);
+
+ r = dm_tm_shadow_block(info->tm, root, &btree_node_validator,
+ &result->block, &inc);
+ if (r)
+ return r;
+
+ result->n = dm_block_data(result->block);
+
+ if (inc)
+ inc_children(info->tm, result->n, &le64_type);
+
+ *((__le64 *) value_ptr(parent, index, sizeof(__le64))) =
+ cpu_to_le64(dm_block_location(result->block));
+
+ return 0;
+}
+
+static int exit_child(struct dm_btree_info *info, struct child *c)
+{
+ return dm_tm_unlock(info->tm, c->block);
+}
+
+static void shift(struct node *left, struct node *right, int count)
+{
+ if (!count)
+ return;
+
+ if (count > 0) {
+ node_shift(right, count);
+ node_copy(left, right, count);
+ } else {
+ node_copy(left, right, count);
+ node_shift(right, count);
+ }
+
+ left->header.nr_entries =
+ cpu_to_le32(le32_to_cpu(left->header.nr_entries) - count);
+ BUG_ON(le32_to_cpu(left->header.nr_entries) > le32_to_cpu(left->header.max_entries));
+
+ right->header.nr_entries =
+ cpu_to_le32(le32_to_cpu(right->header.nr_entries) + count);
+ BUG_ON(le32_to_cpu(right->header.nr_entries) > le32_to_cpu(right->header.max_entries));
+}
+
+static void __rebalance2(struct dm_btree_info *info, struct node *parent,
+ struct child *l, struct child *r)
+{
+ struct node *left = l->n;
+ struct node *right = r->n;
+ uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+ uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+
+ if (nr_left + nr_right <= merge_threshold(left)) {
+ /*
+ * Merge
+ */
+ node_copy(left, right, -nr_right);
+ left->header.nr_entries = cpu_to_le32(nr_left + nr_right);
+ delete_at(parent, r->index);
+
+ /*
+ * We need to decrement the right block, but not it's
+ * children, since they're still referenced by left.
+ */
+ dm_tm_dec(info->tm, dm_block_location(r->block));
+ } else {
+ /*
+ * Rebalance.
+ */
+ unsigned target_left = (nr_left + nr_right) / 2;
+ unsigned shift_ = nr_left - target_left;
+ BUG_ON(le32_to_cpu(left->header.max_entries) <= nr_left - shift_);
+ BUG_ON(le32_to_cpu(right->header.max_entries) <= nr_right + shift_);
+ shift(left, right, nr_left - target_left);
+ *key_ptr(parent, r->index) = right->keys[0];
+ }
+}
+
+static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
+ unsigned left_index)
+{
+ int r;
+ struct node *parent;
+ struct child left, right;
+
+ parent = dm_block_data(shadow_current(s));
+
+ r = init_child(info, parent, left_index, &left);
+ if (r)
+ return r;
+
+ r = init_child(info, parent, left_index + 1, &right);
+ if (r) {
+ exit_child(info, &left);
+ return r;
+ }
+
+ __rebalance2(info, parent, &left, &right);
+
+ r = exit_child(info, &left);
+ if (r) {
+ exit_child(info, &right);
+ return r;
+ }
+
+ return exit_child(info, &right);
+}
+
+static void __rebalance3(struct dm_btree_info *info, struct node *parent,
+ struct child *l, struct child *c, struct child *r)
+{
+ struct node *left = l->n;
+ struct node *center = c->n;
+ struct node *right = r->n;
+
+ uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+ uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
+ uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+ uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+
+ unsigned target;
+
+ BUG_ON(left->header.max_entries != center->header.max_entries);
+ BUG_ON(center->header.max_entries != right->header.max_entries);
+
+ if (((nr_left + nr_center + nr_right) / 2) < merge_threshold(center)) {
+ /*
+ * Delete center node:
+ *
+ * We dump as many entries from center as possible into
+ * left, then the rest in right, then rebalance2. This
+ * wastes some cpu, but I want something simple atm.
+ */
+ unsigned shift = min(max_entries - nr_left, nr_center);
+
+ BUG_ON(nr_left + shift > max_entries);
+ node_copy(left, center, -shift);
+ left->header.nr_entries = cpu_to_le32(nr_left + shift);
+
+ if (shift != nr_center) {
+ shift = nr_center - shift;
+ BUG_ON((nr_right + shift) >= max_entries);
+ node_shift(right, shift);
+ node_copy(center, right, shift);
+ right->header.nr_entries = cpu_to_le32(nr_right + shift);
+ }
+ *key_ptr(parent, r->index) = right->keys[0];
+
+ delete_at(parent, c->index);
+ r->index--;
+
+ dm_tm_dec(info->tm, dm_block_location(c->block));
+ __rebalance2(info, parent, l, r);
+
+ return;
+ }
+
+ /*
+ * Rebalance
+ */
+ target = (nr_left + nr_center + nr_right) / 3;
+ BUG_ON(target > max_entries);
+
+ /*
+ * Adjust the left node
+ */
+ shift(left, center, nr_left - target);
+
+ /*
+ * Adjust the right node
+ */
+ shift(center, right, target - nr_right);
+ *key_ptr(parent, c->index) = center->keys[0];
+ *key_ptr(parent, r->index) = right->keys[0];
+}
+
+static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
+ unsigned left_index)
+{
+ int r;
+ struct node *parent = dm_block_data(shadow_current(s));
+ struct child left, center, right;
+
+ /*
+ * FIXME: fill out an array?
+ */
+ r = init_child(info, parent, left_index, &left);
+ if (r)
+ return r;
+
+ r = init_child(info, parent, left_index + 1, &center);
+ if (r) {
+ exit_child(info, &left);
+ return r;
+ }
+
+ r = init_child(info, parent, left_index + 2, &right);
+ if (r) {
+ exit_child(info, &left);
+ exit_child(info, &center);
+ return r;
+ }
+
+ __rebalance3(info, parent, &left, &center, &right);
+
+ r = exit_child(info, &left);
+ if (r) {
+ exit_child(info, &center);
+ exit_child(info, &right);
+ return r;
+ }
+
+ r = exit_child(info, &center);
+ if (r) {
+ exit_child(info, &right);
+ return r;
+ }
+
+ r = exit_child(info, &right);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int get_nr_entries(struct dm_transaction_manager *tm,
+ dm_block_t b, uint32_t *result)
+{
+ int r;
+ struct dm_block *block;
+ struct node *n;
+
+ r = dm_tm_read_lock(tm, b, &btree_node_validator, &block);
+ if (r)
+ return r;
+
+ n = dm_block_data(block);
+ *result = le32_to_cpu(n->header.nr_entries);
+
+ return dm_tm_unlock(tm, block);
+}
+
+static int rebalance_children(struct shadow_spine *s,
+ struct dm_btree_info *info, uint64_t key)
+{
+ int i, r, has_left_sibling, has_right_sibling;
+ uint32_t child_entries;
+ struct node *n;
+
+ n = dm_block_data(shadow_current(s));
+
+ if (le32_to_cpu(n->header.nr_entries) == 1) {
+ struct dm_block *child;
+ dm_block_t b = value64(n, 0);
+
+ r = dm_tm_read_lock(info->tm, b, &btree_node_validator, &child);
+ if (r)
+ return r;
+
+ memcpy(n, dm_block_data(child),
+ dm_bm_block_size(dm_tm_get_bm(info->tm)));
+ r = dm_tm_unlock(info->tm, child);
+ if (r)
+ return r;
+
+ dm_tm_dec(info->tm, dm_block_location(child));
+ return 0;
+ }
+
+ i = lower_bound(n, key);
+ if (i < 0)
+ return -ENODATA;
+
+ r = get_nr_entries(info->tm, value64(n, i), &child_entries);
+ if (r)
+ return r;
+
+ if (child_entries > del_threshold(n))
+ return 0;
+
+ has_left_sibling = i > 0;
+ has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1);
+
+ if (!has_left_sibling)
+ r = rebalance2(s, info, i);
+
+ else if (!has_right_sibling)
+ r = rebalance2(s, info, i - 1);
+
+ else
+ r = rebalance3(s, info, i - 1);
+
+ return r;
+}
+
+static int do_leaf(struct node *n, uint64_t key, unsigned *index)
+{
+ int i = lower_bound(n, key);
+
+ if ((i < 0) ||
+ (i >= le32_to_cpu(n->header.nr_entries)) ||
+ (le64_to_cpu(n->keys[i]) != key))
+ return -ENODATA;
+
+ *index = i;
+
+ return 0;
+}
+
+/*
+ * Prepares for removal from one level of the hierarchy. The caller must
+ * call delete_at() to remove the entry at index.
+ */
+static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
+ struct dm_btree_value_type *vt, dm_block_t root,
+ uint64_t key, unsigned *index)
+{
+ int i = *index, r;
+ struct node *n;
+
+ for (;;) {
+ r = shadow_step(s, root, vt);
+ if (r < 0)
+ break;
+
+ /*
+ * We have to patch up the parent node, ugly, but I don't
+ * see a way to do this automatically as part of the spine
+ * op.
+ */
+ if (shadow_has_parent(s)) {
+ __le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
+ memcpy(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(__le64)),
+ &location, sizeof(__le64));
+ }
+
+ n = dm_block_data(shadow_current(s));
+
+ if (le32_to_cpu(n->header.flags) & LEAF_NODE)
+ return do_leaf(n, key, index);
+
+ r = rebalance_children(s, info, key);
+ if (r)
+ break;
+
+ n = dm_block_data(shadow_current(s));
+ if (le32_to_cpu(n->header.flags) & LEAF_NODE)
+ return do_leaf(n, key, index);
+
+ i = lower_bound(n, key);
+
+ /*
+ * We know the key is present, or else
+ * rebalance_children would have returned
+ * -ENODATA
+ */
+ root = value64(n, i);
+ }
+
+ return r;
+}
+
+int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *keys, dm_block_t *new_root)
+{
+ unsigned level, last_level = info->levels - 1;
+ int index = 0, r = 0;
+ struct shadow_spine spine;
+ struct node *n;
+
+ init_shadow_spine(&spine, info);
+ for (level = 0; level < info->levels; level++) {
+ r = remove_raw(&spine, info,
+ (level == last_level ?
+ &info->value_type : &le64_type),
+ root, keys[level], (unsigned *)&index);
+ if (r < 0)
+ break;
+
+ n = dm_block_data(shadow_current(&spine));
+ if (level != last_level) {
+ root = value64(n, index);
+ continue;
+ }
+
+ BUG_ON(index < 0 || index >= le32_to_cpu(n->header.nr_entries));
+
+ if (info->value_type.dec)
+ info->value_type.dec(info->value_type.context,
+ value_ptr(n, index, info->value_type.size));
+
+ delete_at(n, index);
+ }
+
+ *new_root = shadow_root(&spine);
+ exit_shadow_spine(&spine);
+
+ return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_remove);
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c
new file mode 100644
index 000000000000..d9a7912ee8ee
--- /dev/null
+++ b/drivers/md/persistent-data/dm-btree-spine.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree-internal.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "btree spine"
+
+/*----------------------------------------------------------------*/
+
+#define BTREE_CSUM_XOR 121107
+
+static int node_check(struct dm_block_validator *v,
+ struct dm_block *b,
+ size_t block_size);
+
+static void node_prepare_for_write(struct dm_block_validator *v,
+ struct dm_block *b,
+ size_t block_size)
+{
+ struct node *n = dm_block_data(b);
+ struct node_header *h = &n->header;
+
+ h->blocknr = cpu_to_le64(dm_block_location(b));
+ h->csum = cpu_to_le32(dm_bm_checksum(&h->flags,
+ block_size - sizeof(__le32),
+ BTREE_CSUM_XOR));
+
+ BUG_ON(node_check(v, b, 4096));
+}
+
+static int node_check(struct dm_block_validator *v,
+ struct dm_block *b,
+ size_t block_size)
+{
+ struct node *n = dm_block_data(b);
+ struct node_header *h = &n->header;
+ size_t value_size;
+ __le32 csum_disk;
+ uint32_t flags;
+
+ if (dm_block_location(b) != le64_to_cpu(h->blocknr)) {
+ DMERR("node_check failed blocknr %llu wanted %llu",
+ le64_to_cpu(h->blocknr), dm_block_location(b));
+ return -ENOTBLK;
+ }
+
+ csum_disk = cpu_to_le32(dm_bm_checksum(&h->flags,
+ block_size - sizeof(__le32),
+ BTREE_CSUM_XOR));
+ if (csum_disk != h->csum) {
+ DMERR("node_check failed csum %u wanted %u",
+ le32_to_cpu(csum_disk), le32_to_cpu(h->csum));
+ return -EILSEQ;
+ }
+
+ value_size = le32_to_cpu(h->value_size);
+
+ if (sizeof(struct node_header) +
+ (sizeof(__le64) + value_size) * le32_to_cpu(h->max_entries) > block_size) {
+ DMERR("node_check failed: max_entries too large");
+ return -EILSEQ;
+ }
+
+ if (le32_to_cpu(h->nr_entries) > le32_to_cpu(h->max_entries)) {
+ DMERR("node_check failed, too many entries");
+ return -EILSEQ;
+ }
+
+ /*
+ * The node must be either INTERNAL or LEAF.
+ */
+ flags = le32_to_cpu(h->flags);
+ if (!(flags & INTERNAL_NODE) && !(flags & LEAF_NODE)) {
+ DMERR("node_check failed, node is neither INTERNAL or LEAF");
+ return -EILSEQ;
+ }
+
+ return 0;
+}
+
+struct dm_block_validator btree_node_validator = {
+ .name = "btree_node",
+ .prepare_for_write = node_prepare_for_write,
+ .check = node_check
+};
+
+/*----------------------------------------------------------------*/
+
+static int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
+ struct dm_block **result)
+{
+ return dm_tm_read_lock(info->tm, b, &btree_node_validator, result);
+}
+
+static int bn_shadow(struct dm_btree_info *info, dm_block_t orig,
+ struct dm_btree_value_type *vt,
+ struct dm_block **result)
+{
+ int r, inc;
+
+ r = dm_tm_shadow_block(info->tm, orig, &btree_node_validator,
+ result, &inc);
+ if (!r && inc)
+ inc_children(info->tm, dm_block_data(*result), vt);
+
+ return r;
+}
+
+int new_block(struct dm_btree_info *info, struct dm_block **result)
+{
+ return dm_tm_new_block(info->tm, &btree_node_validator, result);
+}
+
+int unlock_block(struct dm_btree_info *info, struct dm_block *b)
+{
+ return dm_tm_unlock(info->tm, b);
+}
+
+/*----------------------------------------------------------------*/
+
+void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info)
+{
+ s->info = info;
+ s->count = 0;
+ s->nodes[0] = NULL;
+ s->nodes[1] = NULL;
+}
+
+int exit_ro_spine(struct ro_spine *s)
+{
+ int r = 0, i;
+
+ for (i = 0; i < s->count; i++) {
+ int r2 = unlock_block(s->info, s->nodes[i]);
+ if (r2 < 0)
+ r = r2;
+ }
+
+ return r;
+}
+
+int ro_step(struct ro_spine *s, dm_block_t new_child)
+{
+ int r;
+
+ if (s->count == 2) {
+ r = unlock_block(s->info, s->nodes[0]);
+ if (r < 0)
+ return r;
+ s->nodes[0] = s->nodes[1];
+ s->count--;
+ }
+
+ r = bn_read_lock(s->info, new_child, s->nodes + s->count);
+ if (!r)
+ s->count++;
+
+ return r;
+}
+
+struct node *ro_node(struct ro_spine *s)
+{
+ struct dm_block *block;
+
+ BUG_ON(!s->count);
+ block = s->nodes[s->count - 1];
+
+ return dm_block_data(block);
+}
+
+/*----------------------------------------------------------------*/
+
+void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info)
+{
+ s->info = info;
+ s->count = 0;
+}
+
+int exit_shadow_spine(struct shadow_spine *s)
+{
+ int r = 0, i;
+
+ for (i = 0; i < s->count; i++) {
+ int r2 = unlock_block(s->info, s->nodes[i]);
+ if (r2 < 0)
+ r = r2;
+ }
+
+ return r;
+}
+
+int shadow_step(struct shadow_spine *s, dm_block_t b,
+ struct dm_btree_value_type *vt)
+{
+ int r;
+
+ if (s->count == 2) {
+ r = unlock_block(s->info, s->nodes[0]);
+ if (r < 0)
+ return r;
+ s->nodes[0] = s->nodes[1];
+ s->count--;
+ }
+
+ r = bn_shadow(s->info, b, vt, s->nodes + s->count);
+ if (!r) {
+ if (!s->count)
+ s->root = dm_block_location(s->nodes[0]);
+
+ s->count++;
+ }
+
+ return r;
+}
+
+struct dm_block *shadow_current(struct shadow_spine *s)
+{
+ BUG_ON(!s->count);
+
+ return s->nodes[s->count - 1];
+}
+
+struct dm_block *shadow_parent(struct shadow_spine *s)
+{
+ BUG_ON(s->count != 2);
+
+ return s->count == 2 ? s->nodes[0] : NULL;
+}
+
+int shadow_has_parent(struct shadow_spine *s)
+{
+ return s->count >= 2;
+}
+
+int shadow_root(struct shadow_spine *s)
+{
+ return s->root;
+}
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
new file mode 100644
index 000000000000..e0638be53ea4
--- /dev/null
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -0,0 +1,805 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree-internal.h"
+#include "dm-space-map.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/module.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "btree"
+
+/*----------------------------------------------------------------
+ * Array manipulation
+ *--------------------------------------------------------------*/
+static void memcpy_disk(void *dest, const void *src, size_t len)
+ __dm_written_to_disk(src)
+{
+ memcpy(dest, src, len);
+ __dm_unbless_for_disk(src);
+}
+
+static void array_insert(void *base, size_t elt_size, unsigned nr_elts,
+ unsigned index, void *elt)
+ __dm_written_to_disk(elt)
+{
+ if (index < nr_elts)
+ memmove(base + (elt_size * (index + 1)),
+ base + (elt_size * index),
+ (nr_elts - index) * elt_size);
+
+ memcpy_disk(base + (elt_size * index), elt, elt_size);
+}
+
+/*----------------------------------------------------------------*/
+
+/* makes the assumption that no two keys are the same. */
+static int bsearch(struct node *n, uint64_t key, int want_hi)
+{
+ int lo = -1, hi = le32_to_cpu(n->header.nr_entries);
+
+ while (hi - lo > 1) {
+ int mid = lo + ((hi - lo) / 2);
+ uint64_t mid_key = le64_to_cpu(n->keys[mid]);
+
+ if (mid_key == key)
+ return mid;
+
+ if (mid_key < key)
+ lo = mid;
+ else
+ hi = mid;
+ }
+
+ return want_hi ? hi : lo;
+}
+
+int lower_bound(struct node *n, uint64_t key)
+{
+ return bsearch(n, key, 0);
+}
+
+void inc_children(struct dm_transaction_manager *tm, struct node *n,
+ struct dm_btree_value_type *vt)
+{
+ unsigned i;
+ uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
+
+ if (le32_to_cpu(n->header.flags) & INTERNAL_NODE)
+ for (i = 0; i < nr_entries; i++)
+ dm_tm_inc(tm, value64(n, i));
+ else if (vt->inc)
+ for (i = 0; i < nr_entries; i++)
+ vt->inc(vt->context,
+ value_ptr(n, i, vt->size));
+}
+
+static int insert_at(size_t value_size, struct node *node, unsigned index,
+ uint64_t key, void *value)
+ __dm_written_to_disk(value)
+{
+ uint32_t nr_entries = le32_to_cpu(node->header.nr_entries);
+ __le64 key_le = cpu_to_le64(key);
+
+ if (index > nr_entries ||
+ index >= le32_to_cpu(node->header.max_entries)) {
+ DMERR("too many entries in btree node for insert");
+ __dm_unbless_for_disk(value);
+ return -ENOMEM;
+ }
+
+ __dm_bless_for_disk(&key_le);
+
+ array_insert(node->keys, sizeof(*node->keys), nr_entries, index, &key_le);
+ array_insert(value_base(node), value_size, nr_entries, index, value);
+ node->header.nr_entries = cpu_to_le32(nr_entries + 1);
+
+ return 0;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We want 3n entries (for some n). This works more nicely for repeated
+ * insert remove loops than (2n + 1).
+ */
+static uint32_t calc_max_entries(size_t value_size, size_t block_size)
+{
+ uint32_t total, n;
+ size_t elt_size = sizeof(uint64_t) + value_size; /* key + value */
+
+ block_size -= sizeof(struct node_header);
+ total = block_size / elt_size;
+ n = total / 3; /* rounds down */
+
+ return 3 * n;
+}
+
+int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root)
+{
+ int r;
+ struct dm_block *b;
+ struct node *n;
+ size_t block_size;
+ uint32_t max_entries;
+
+ r = new_block(info, &b);
+ if (r < 0)
+ return r;
+
+ block_size = dm_bm_block_size(dm_tm_get_bm(info->tm));
+ max_entries = calc_max_entries(info->value_type.size, block_size);
+
+ n = dm_block_data(b);
+ memset(n, 0, block_size);
+ n->header.flags = cpu_to_le32(LEAF_NODE);
+ n->header.nr_entries = cpu_to_le32(0);
+ n->header.max_entries = cpu_to_le32(max_entries);
+ n->header.value_size = cpu_to_le32(info->value_type.size);
+
+ *root = dm_block_location(b);
+ return unlock_block(info, b);
+}
+EXPORT_SYMBOL_GPL(dm_btree_empty);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Deletion uses a recursive algorithm, since we have limited stack space
+ * we explicitly manage our own stack on the heap.
+ */
+#define MAX_SPINE_DEPTH 64
+struct frame {
+ struct dm_block *b;
+ struct node *n;
+ unsigned level;
+ unsigned nr_children;
+ unsigned current_child;
+};
+
+struct del_stack {
+ struct dm_transaction_manager *tm;
+ int top;
+ struct frame spine[MAX_SPINE_DEPTH];
+};
+
+static int top_frame(struct del_stack *s, struct frame **f)
+{
+ if (s->top < 0) {
+ DMERR("btree deletion stack empty");
+ return -EINVAL;
+ }
+
+ *f = s->spine + s->top;
+
+ return 0;
+}
+
+static int unprocessed_frames(struct del_stack *s)
+{
+ return s->top >= 0;
+}
+
+static int push_frame(struct del_stack *s, dm_block_t b, unsigned level)
+{
+ int r;
+ uint32_t ref_count;
+
+ if (s->top >= MAX_SPINE_DEPTH - 1) {
+ DMERR("btree deletion stack out of memory");
+ return -ENOMEM;
+ }
+
+ r = dm_tm_ref(s->tm, b, &ref_count);
+ if (r)
+ return r;
+
+ if (ref_count > 1)
+ /*
+ * This is a shared node, so we can just decrement it's
+ * reference counter and leave the children.
+ */
+ dm_tm_dec(s->tm, b);
+
+ else {
+ struct frame *f = s->spine + ++s->top;
+
+ r = dm_tm_read_lock(s->tm, b, &btree_node_validator, &f->b);
+ if (r) {
+ s->top--;
+ return r;
+ }
+
+ f->n = dm_block_data(f->b);
+ f->level = level;
+ f->nr_children = le32_to_cpu(f->n->header.nr_entries);
+ f->current_child = 0;
+ }
+
+ return 0;
+}
+
+static void pop_frame(struct del_stack *s)
+{
+ struct frame *f = s->spine + s->top--;
+
+ dm_tm_dec(s->tm, dm_block_location(f->b));
+ dm_tm_unlock(s->tm, f->b);
+}
+
+int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
+{
+ int r;
+ struct del_stack *s;
+
+ s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+ s->tm = info->tm;
+ s->top = -1;
+
+ r = push_frame(s, root, 1);
+ if (r)
+ goto out;
+
+ while (unprocessed_frames(s)) {
+ uint32_t flags;
+ struct frame *f;
+ dm_block_t b;
+
+ r = top_frame(s, &f);
+ if (r)
+ goto out;
+
+ if (f->current_child >= f->nr_children) {
+ pop_frame(s);
+ continue;
+ }
+
+ flags = le32_to_cpu(f->n->header.flags);
+ if (flags & INTERNAL_NODE) {
+ b = value64(f->n, f->current_child);
+ f->current_child++;
+ r = push_frame(s, b, f->level);
+ if (r)
+ goto out;
+
+ } else if (f->level != (info->levels - 1)) {
+ b = value64(f->n, f->current_child);
+ f->current_child++;
+ r = push_frame(s, b, f->level + 1);
+ if (r)
+ goto out;
+
+ } else {
+ if (info->value_type.dec) {
+ unsigned i;
+
+ for (i = 0; i < f->nr_children; i++)
+ info->value_type.dec(info->value_type.context,
+ value_ptr(f->n, i, info->value_type.size));
+ }
+ f->current_child = f->nr_children;
+ }
+ }
+
+out:
+ kfree(s);
+ return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_del);
+
+/*----------------------------------------------------------------*/
+
+static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
+ int (*search_fn)(struct node *, uint64_t),
+ uint64_t *result_key, void *v, size_t value_size)
+{
+ int i, r;
+ uint32_t flags, nr_entries;
+
+ do {
+ r = ro_step(s, block);
+ if (r < 0)
+ return r;
+
+ i = search_fn(ro_node(s), key);
+
+ flags = le32_to_cpu(ro_node(s)->header.flags);
+ nr_entries = le32_to_cpu(ro_node(s)->header.nr_entries);
+ if (i < 0 || i >= nr_entries)
+ return -ENODATA;
+
+ if (flags & INTERNAL_NODE)
+ block = value64(ro_node(s), i);
+
+ } while (!(flags & LEAF_NODE));
+
+ *result_key = le64_to_cpu(ro_node(s)->keys[i]);
+ memcpy(v, value_ptr(ro_node(s), i, value_size), value_size);
+
+ return 0;
+}
+
+int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *keys, void *value_le)
+{
+ unsigned level, last_level = info->levels - 1;
+ int r = -ENODATA;
+ uint64_t rkey;
+ __le64 internal_value_le;
+ struct ro_spine spine;
+
+ init_ro_spine(&spine, info);
+ for (level = 0; level < info->levels; level++) {
+ size_t size;
+ void *value_p;
+
+ if (level == last_level) {
+ value_p = value_le;
+ size = info->value_type.size;
+
+ } else {
+ value_p = &internal_value_le;
+ size = sizeof(uint64_t);
+ }
+
+ r = btree_lookup_raw(&spine, root, keys[level],
+ lower_bound, &rkey,
+ value_p, size);
+
+ if (!r) {
+ if (rkey != keys[level]) {
+ exit_ro_spine(&spine);
+ return -ENODATA;
+ }
+ } else {
+ exit_ro_spine(&spine);
+ return r;
+ }
+
+ root = le64_to_cpu(internal_value_le);
+ }
+ exit_ro_spine(&spine);
+
+ return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_lookup);
+
+/*
+ * Splits a node by creating a sibling node and shifting half the nodes
+ * contents across. Assumes there is a parent node, and it has room for
+ * another child.
+ *
+ * Before:
+ * +--------+
+ * | Parent |
+ * +--------+
+ * |
+ * v
+ * +----------+
+ * | A ++++++ |
+ * +----------+
+ *
+ *
+ * After:
+ * +--------+
+ * | Parent |
+ * +--------+
+ * | |
+ * v +------+
+ * +---------+ |
+ * | A* +++ | v
+ * +---------+ +-------+
+ * | B +++ |
+ * +-------+
+ *
+ * Where A* is a shadow of A.
+ */
+static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
+ unsigned parent_index, uint64_t key)
+{
+ int r;
+ size_t size;
+ unsigned nr_left, nr_right;
+ struct dm_block *left, *right, *parent;
+ struct node *ln, *rn, *pn;
+ __le64 location;
+
+ left = shadow_current(s);
+
+ r = new_block(s->info, &right);
+ if (r < 0)
+ return r;
+
+ ln = dm_block_data(left);
+ rn = dm_block_data(right);
+
+ nr_left = le32_to_cpu(ln->header.nr_entries) / 2;
+ nr_right = le32_to_cpu(ln->header.nr_entries) - nr_left;
+
+ ln->header.nr_entries = cpu_to_le32(nr_left);
+
+ rn->header.flags = ln->header.flags;
+ rn->header.nr_entries = cpu_to_le32(nr_right);
+ rn->header.max_entries = ln->header.max_entries;
+ rn->header.value_size = ln->header.value_size;
+ memcpy(rn->keys, ln->keys + nr_left, nr_right * sizeof(rn->keys[0]));
+
+ size = le32_to_cpu(ln->header.flags) & INTERNAL_NODE ?
+ sizeof(uint64_t) : s->info->value_type.size;
+ memcpy(value_ptr(rn, 0, size), value_ptr(ln, nr_left, size),
+ size * nr_right);
+
+ /*
+ * Patch up the parent
+ */
+ parent = shadow_parent(s);
+
+ pn = dm_block_data(parent);
+ location = cpu_to_le64(dm_block_location(left));
+ __dm_bless_for_disk(&location);
+ memcpy_disk(value_ptr(pn, parent_index, sizeof(__le64)),
+ &location, sizeof(__le64));
+
+ location = cpu_to_le64(dm_block_location(right));
+ __dm_bless_for_disk(&location);
+
+ r = insert_at(sizeof(__le64), pn, parent_index + 1,
+ le64_to_cpu(rn->keys[0]), &location);
+ if (r)
+ return r;
+
+ if (key < le64_to_cpu(rn->keys[0])) {
+ unlock_block(s->info, right);
+ s->nodes[1] = left;
+ } else {
+ unlock_block(s->info, left);
+ s->nodes[1] = right;
+ }
+
+ return 0;
+}
+
+/*
+ * Splits a node by creating two new children beneath the given node.
+ *
+ * Before:
+ * +----------+
+ * | A ++++++ |
+ * +----------+
+ *
+ *
+ * After:
+ * +------------+
+ * | A (shadow) |
+ * +------------+
+ * | |
+ * +------+ +----+
+ * | |
+ * v v
+ * +-------+ +-------+
+ * | B +++ | | C +++ |
+ * +-------+ +-------+
+ */
+static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
+{
+ int r;
+ size_t size;
+ unsigned nr_left, nr_right;
+ struct dm_block *left, *right, *new_parent;
+ struct node *pn, *ln, *rn;
+ __le64 val;
+
+ new_parent = shadow_current(s);
+
+ r = new_block(s->info, &left);
+ if (r < 0)
+ return r;
+
+ r = new_block(s->info, &right);
+ if (r < 0) {
+ /* FIXME: put left */
+ return r;
+ }
+
+ pn = dm_block_data(new_parent);
+ ln = dm_block_data(left);
+ rn = dm_block_data(right);
+
+ nr_left = le32_to_cpu(pn->header.nr_entries) / 2;
+ nr_right = le32_to_cpu(pn->header.nr_entries) - nr_left;
+
+ ln->header.flags = pn->header.flags;
+ ln->header.nr_entries = cpu_to_le32(nr_left);
+ ln->header.max_entries = pn->header.max_entries;
+ ln->header.value_size = pn->header.value_size;
+
+ rn->header.flags = pn->header.flags;
+ rn->header.nr_entries = cpu_to_le32(nr_right);
+ rn->header.max_entries = pn->header.max_entries;
+ rn->header.value_size = pn->header.value_size;
+
+ memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0]));
+ memcpy(rn->keys, pn->keys + nr_left, nr_right * sizeof(pn->keys[0]));
+
+ size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
+ sizeof(__le64) : s->info->value_type.size;
+ memcpy(value_ptr(ln, 0, size), value_ptr(pn, 0, size), nr_left * size);
+ memcpy(value_ptr(rn, 0, size), value_ptr(pn, nr_left, size),
+ nr_right * size);
+
+ /* new_parent should just point to l and r now */
+ pn->header.flags = cpu_to_le32(INTERNAL_NODE);
+ pn->header.nr_entries = cpu_to_le32(2);
+ pn->header.max_entries = cpu_to_le32(
+ calc_max_entries(sizeof(__le64),
+ dm_bm_block_size(
+ dm_tm_get_bm(s->info->tm))));
+ pn->header.value_size = cpu_to_le32(sizeof(__le64));
+
+ val = cpu_to_le64(dm_block_location(left));
+ __dm_bless_for_disk(&val);
+ pn->keys[0] = ln->keys[0];
+ memcpy_disk(value_ptr(pn, 0, sizeof(__le64)), &val, sizeof(__le64));
+
+ val = cpu_to_le64(dm_block_location(right));
+ __dm_bless_for_disk(&val);
+ pn->keys[1] = rn->keys[0];
+ memcpy_disk(value_ptr(pn, 1, sizeof(__le64)), &val, sizeof(__le64));
+
+ /*
+ * rejig the spine. This is ugly, since it knows too
+ * much about the spine
+ */
+ if (s->nodes[0] != new_parent) {
+ unlock_block(s->info, s->nodes[0]);
+ s->nodes[0] = new_parent;
+ }
+ if (key < le64_to_cpu(rn->keys[0])) {
+ unlock_block(s->info, right);
+ s->nodes[1] = left;
+ } else {
+ unlock_block(s->info, left);
+ s->nodes[1] = right;
+ }
+ s->count = 2;
+
+ return 0;
+}
+
+static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
+ struct dm_btree_value_type *vt,
+ uint64_t key, unsigned *index)
+{
+ int r, i = *index, top = 1;
+ struct node *node;
+
+ for (;;) {
+ r = shadow_step(s, root, vt);
+ if (r < 0)
+ return r;
+
+ node = dm_block_data(shadow_current(s));
+
+ /*
+ * We have to patch up the parent node, ugly, but I don't
+ * see a way to do this automatically as part of the spine
+ * op.
+ */
+ if (shadow_has_parent(s) && i >= 0) { /* FIXME: second clause unness. */
+ __le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
+
+ __dm_bless_for_disk(&location);
+ memcpy_disk(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(uint64_t)),
+ &location, sizeof(__le64));
+ }
+
+ node = dm_block_data(shadow_current(s));
+
+ if (node->header.nr_entries == node->header.max_entries) {
+ if (top)
+ r = btree_split_beneath(s, key);
+ else
+ r = btree_split_sibling(s, root, i, key);
+
+ if (r < 0)
+ return r;
+ }
+
+ node = dm_block_data(shadow_current(s));
+
+ i = lower_bound(node, key);
+
+ if (le32_to_cpu(node->header.flags) & LEAF_NODE)
+ break;
+
+ if (i < 0) {
+ /* change the bounds on the lowest key */
+ node->keys[0] = cpu_to_le64(key);
+ i = 0;
+ }
+
+ root = value64(node, i);
+ top = 0;
+ }
+
+ if (i < 0 || le64_to_cpu(node->keys[i]) != key)
+ i++;
+
+ *index = i;
+ return 0;
+}
+
+static int insert(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *keys, void *value, dm_block_t *new_root,
+ int *inserted)
+ __dm_written_to_disk(value)
+{
+ int r, need_insert;
+ unsigned level, index = -1, last_level = info->levels - 1;
+ dm_block_t block = root;
+ struct shadow_spine spine;
+ struct node *n;
+ struct dm_btree_value_type le64_type;
+
+ le64_type.context = NULL;
+ le64_type.size = sizeof(__le64);
+ le64_type.inc = NULL;
+ le64_type.dec = NULL;
+ le64_type.equal = NULL;
+
+ init_shadow_spine(&spine, info);
+
+ for (level = 0; level < (info->levels - 1); level++) {
+ r = btree_insert_raw(&spine, block, &le64_type, keys[level], &index);
+ if (r < 0)
+ goto bad;
+
+ n = dm_block_data(shadow_current(&spine));
+ need_insert = ((index >= le32_to_cpu(n->header.nr_entries)) ||
+ (le64_to_cpu(n->keys[index]) != keys[level]));
+
+ if (need_insert) {
+ dm_block_t new_tree;
+ __le64 new_le;
+
+ r = dm_btree_empty(info, &new_tree);
+ if (r < 0)
+ goto bad;
+
+ new_le = cpu_to_le64(new_tree);
+ __dm_bless_for_disk(&new_le);
+
+ r = insert_at(sizeof(uint64_t), n, index,
+ keys[level], &new_le);
+ if (r)
+ goto bad;
+ }
+
+ if (level < last_level)
+ block = value64(n, index);
+ }
+
+ r = btree_insert_raw(&spine, block, &info->value_type,
+ keys[level], &index);
+ if (r < 0)
+ goto bad;
+
+ n = dm_block_data(shadow_current(&spine));
+ need_insert = ((index >= le32_to_cpu(n->header.nr_entries)) ||
+ (le64_to_cpu(n->keys[index]) != keys[level]));
+
+ if (need_insert) {
+ if (inserted)
+ *inserted = 1;
+
+ r = insert_at(info->value_type.size, n, index,
+ keys[level], value);
+ if (r)
+ goto bad_unblessed;
+ } else {
+ if (inserted)
+ *inserted = 0;
+
+ if (info->value_type.dec &&
+ (!info->value_type.equal ||
+ !info->value_type.equal(
+ info->value_type.context,
+ value_ptr(n, index, info->value_type.size),
+ value))) {
+ info->value_type.dec(info->value_type.context,
+ value_ptr(n, index, info->value_type.size));
+ }
+ memcpy_disk(value_ptr(n, index, info->value_type.size),
+ value, info->value_type.size);
+ }
+
+ *new_root = shadow_root(&spine);
+ exit_shadow_spine(&spine);
+
+ return 0;
+
+bad:
+ __dm_unbless_for_disk(value);
+bad_unblessed:
+ exit_shadow_spine(&spine);
+ return r;
+}
+
+int dm_btree_insert(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *keys, void *value, dm_block_t *new_root)
+ __dm_written_to_disk(value)
+{
+ return insert(info, root, keys, value, new_root, NULL);
+}
+EXPORT_SYMBOL_GPL(dm_btree_insert);
+
+int dm_btree_insert_notify(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *keys, void *value, dm_block_t *new_root,
+ int *inserted)
+ __dm_written_to_disk(value)
+{
+ return insert(info, root, keys, value, new_root, inserted);
+}
+EXPORT_SYMBOL_GPL(dm_btree_insert_notify);
+
+/*----------------------------------------------------------------*/
+
+static int find_highest_key(struct ro_spine *s, dm_block_t block,
+ uint64_t *result_key, dm_block_t *next_block)
+{
+ int i, r;
+ uint32_t flags;
+
+ do {
+ r = ro_step(s, block);
+ if (r < 0)
+ return r;
+
+ flags = le32_to_cpu(ro_node(s)->header.flags);
+ i = le32_to_cpu(ro_node(s)->header.nr_entries);
+ if (!i)
+ return -ENODATA;
+ else
+ i--;
+
+ *result_key = le64_to_cpu(ro_node(s)->keys[i]);
+ if (next_block || flags & INTERNAL_NODE)
+ block = value64(ro_node(s), i);
+
+ } while (flags & INTERNAL_NODE);
+
+ if (next_block)
+ *next_block = block;
+ return 0;
+}
+
+int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *result_keys)
+{
+ int r = 0, count = 0, level;
+ struct ro_spine spine;
+
+ init_ro_spine(&spine, info);
+ for (level = 0; level < info->levels; level++) {
+ r = find_highest_key(&spine, root, result_keys + level,
+ level == info->levels - 1 ? NULL : &root);
+ if (r == -ENODATA) {
+ r = 0;
+ break;
+
+ } else if (r)
+ break;
+
+ count++;
+ }
+ exit_ro_spine(&spine);
+
+ return r ? r : count;
+}
+EXPORT_SYMBOL_GPL(dm_btree_find_highest_key);
diff --git a/drivers/md/persistent-data/dm-btree.h b/drivers/md/persistent-data/dm-btree.h
new file mode 100644
index 000000000000..ae02c84410ff
--- /dev/null
+++ b/drivers/md/persistent-data/dm-btree.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#ifndef _LINUX_DM_BTREE_H
+#define _LINUX_DM_BTREE_H
+
+#include "dm-block-manager.h"
+
+struct dm_transaction_manager;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Annotations used to check on-disk metadata is handled as little-endian.
+ */
+#ifdef __CHECKER__
+# define __dm_written_to_disk(x) __releases(x)
+# define __dm_reads_from_disk(x) __acquires(x)
+# define __dm_bless_for_disk(x) __acquire(x)
+# define __dm_unbless_for_disk(x) __release(x)
+#else
+# define __dm_written_to_disk(x)
+# define __dm_reads_from_disk(x)
+# define __dm_bless_for_disk(x)
+# define __dm_unbless_for_disk(x)
+#endif
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Manipulates hierarchical B+ trees with 64-bit keys and arbitrary-sized
+ * values.
+ */
+
+/*
+ * Infomation about the values stored within the btree.
+ */
+struct dm_btree_value_type {
+ void *context;
+
+ /*
+ * The size in bytes of each value.
+ */
+ uint32_t size;
+
+ /*
+ * Any of these methods can be safely set to NULL if you do not
+ * need the corresponding feature.
+ */
+
+ /*
+ * The btree is making a duplicate of the value, for instance
+ * because previously-shared btree nodes have now diverged.
+ * @value argument is the new copy that the copy function may modify.
+ * (Probably it just wants to increment a reference count
+ * somewhere.) This method is _not_ called for insertion of a new
+ * value: It is assumed the ref count is already 1.
+ */
+ void (*inc)(void *context, void *value);
+
+ /*
+ * This value is being deleted. The btree takes care of freeing
+ * the memory pointed to by @value. Often the del function just
+ * needs to decrement a reference count somewhere.
+ */
+ void (*dec)(void *context, void *value);
+
+ /*
+ * A test for equality between two values. When a value is
+ * overwritten with a new one, the old one has the dec method
+ * called _unless_ the new and old value are deemed equal.
+ */
+ int (*equal)(void *context, void *value1, void *value2);
+};
+
+/*
+ * The shape and contents of a btree.
+ */
+struct dm_btree_info {
+ struct dm_transaction_manager *tm;
+
+ /*
+ * Number of nested btrees. (Not the depth of a single tree.)
+ */
+ unsigned levels;
+ struct dm_btree_value_type value_type;
+};
+
+/*
+ * Set up an empty tree. O(1).
+ */
+int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root);
+
+/*
+ * Delete a tree. O(n) - this is the slow one! It can also block, so
+ * please don't call it on an IO path.
+ */
+int dm_btree_del(struct dm_btree_info *info, dm_block_t root);
+
+/*
+ * All the lookup functions return -ENODATA if the key cannot be found.
+ */
+
+/*
+ * Tries to find a key that matches exactly. O(ln(n))
+ */
+int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *keys, void *value_le);
+
+/*
+ * Insertion (or overwrite an existing value). O(ln(n))
+ */
+int dm_btree_insert(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *keys, void *value, dm_block_t *new_root)
+ __dm_written_to_disk(value);
+
+/*
+ * A variant of insert that indicates whether it actually inserted or just
+ * overwrote. Useful if you're keeping track of the number of entries in a
+ * tree.
+ */
+int dm_btree_insert_notify(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *keys, void *value, dm_block_t *new_root,
+ int *inserted)
+ __dm_written_to_disk(value);
+
+/*
+ * Remove a key if present. This doesn't remove empty sub trees. Normally
+ * subtrees represent a separate entity, like a snapshot map, so this is
+ * correct behaviour. O(ln(n)).
+ */
+int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *keys, dm_block_t *new_root);
+
+/*
+ * Returns < 0 on failure. Otherwise the number of key entries that have
+ * been filled out. Remember trees can have zero entries, and as such have
+ * no highest key.
+ */
+int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
+ uint64_t *result_keys);
+
+#endif /* _LINUX_DM_BTREE_H */
diff --git a/drivers/md/persistent-data/dm-persistent-data-internal.h b/drivers/md/persistent-data/dm-persistent-data-internal.h
new file mode 100644
index 000000000000..c49e26fff36c
--- /dev/null
+++ b/drivers/md/persistent-data/dm-persistent-data-internal.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _DM_PERSISTENT_DATA_INTERNAL_H
+#define _DM_PERSISTENT_DATA_INTERNAL_H
+
+#include "dm-block-manager.h"
+
+static inline unsigned dm_hash_block(dm_block_t b, unsigned hash_mask)
+{
+ const unsigned BIG_PRIME = 4294967291UL;
+
+ return (((unsigned) b) * BIG_PRIME) & hash_mask;
+}
+
+#endif /* _PERSISTENT_DATA_INTERNAL_H */
diff --git a/drivers/md/persistent-data/dm-space-map-checker.c b/drivers/md/persistent-data/dm-space-map-checker.c
new file mode 100644
index 000000000000..bb44a937fe63
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-checker.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-checker.h"
+
+#include <linux/device-mapper.h>
+
+#ifdef CONFIG_DM_DEBUG_SPACE_MAPS
+
+#define DM_MSG_PREFIX "space map checker"
+
+/*----------------------------------------------------------------*/
+
+struct count_array {
+ dm_block_t nr;
+ dm_block_t nr_free;
+
+ uint32_t *counts;
+};
+
+static int ca_get_count(struct count_array *ca, dm_block_t b, uint32_t *count)
+{
+ if (b >= ca->nr)
+ return -EINVAL;
+
+ *count = ca->counts[b];
+ return 0;
+}
+
+static int ca_count_more_than_one(struct count_array *ca, dm_block_t b, int *r)
+{
+ if (b >= ca->nr)
+ return -EINVAL;
+
+ *r = ca->counts[b] > 1;
+ return 0;
+}
+
+static int ca_set_count(struct count_array *ca, dm_block_t b, uint32_t count)
+{
+ uint32_t old_count;
+
+ if (b >= ca->nr)
+ return -EINVAL;
+
+ old_count = ca->counts[b];
+
+ if (!count && old_count)
+ ca->nr_free++;
+
+ else if (count && !old_count)
+ ca->nr_free--;
+
+ ca->counts[b] = count;
+ return 0;
+}
+
+static int ca_inc_block(struct count_array *ca, dm_block_t b)
+{
+ if (b >= ca->nr)
+ return -EINVAL;
+
+ ca_set_count(ca, b, ca->counts[b] + 1);
+ return 0;
+}
+
+static int ca_dec_block(struct count_array *ca, dm_block_t b)
+{
+ if (b >= ca->nr)
+ return -EINVAL;
+
+ BUG_ON(ca->counts[b] == 0);
+ ca_set_count(ca, b, ca->counts[b] - 1);
+ return 0;
+}
+
+static int ca_create(struct count_array *ca, struct dm_space_map *sm)
+{
+ int r;
+ dm_block_t nr_blocks;
+
+ r = dm_sm_get_nr_blocks(sm, &nr_blocks);
+ if (r)
+ return r;
+
+ ca->nr = nr_blocks;
+ ca->nr_free = nr_blocks;
+ ca->counts = kzalloc(sizeof(*ca->counts) * nr_blocks, GFP_KERNEL);
+ if (!ca->counts)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int ca_load(struct count_array *ca, struct dm_space_map *sm)
+{
+ int r;
+ uint32_t count;
+ dm_block_t nr_blocks, i;
+
+ r = dm_sm_get_nr_blocks(sm, &nr_blocks);
+ if (r)
+ return r;
+
+ BUG_ON(ca->nr != nr_blocks);
+
+ DMWARN("Loading debug space map from disk. This may take some time");
+ for (i = 0; i < nr_blocks; i++) {
+ r = dm_sm_get_count(sm, i, &count);
+ if (r) {
+ DMERR("load failed");
+ return r;
+ }
+
+ ca_set_count(ca, i, count);
+ }
+ DMWARN("Load complete");
+
+ return 0;
+}
+
+static int ca_extend(struct count_array *ca, dm_block_t extra_blocks)
+{
+ dm_block_t nr_blocks = ca->nr + extra_blocks;
+ uint32_t *counts = kzalloc(sizeof(*counts) * nr_blocks, GFP_KERNEL);
+ if (!counts)
+ return -ENOMEM;
+
+ memcpy(counts, ca->counts, sizeof(*counts) * ca->nr);
+ kfree(ca->counts);
+ ca->nr = nr_blocks;
+ ca->nr_free += extra_blocks;
+ ca->counts = counts;
+ return 0;
+}
+
+static int ca_commit(struct count_array *old, struct count_array *new)
+{
+ if (old->nr != new->nr) {
+ BUG_ON(old->nr > new->nr);
+ ca_extend(old, new->nr - old->nr);
+ }
+
+ BUG_ON(old->nr != new->nr);
+ old->nr_free = new->nr_free;
+ memcpy(old->counts, new->counts, sizeof(*old->counts) * old->nr);
+ return 0;
+}
+
+static void ca_destroy(struct count_array *ca)
+{
+ kfree(ca->counts);
+}
+
+/*----------------------------------------------------------------*/
+
+struct sm_checker {
+ struct dm_space_map sm;
+
+ struct count_array old_counts;
+ struct count_array counts;
+
+ struct dm_space_map *real_sm;
+};
+
+static void sm_checker_destroy(struct dm_space_map *sm)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+
+ dm_sm_destroy(smc->real_sm);
+ ca_destroy(&smc->old_counts);
+ ca_destroy(&smc->counts);
+ kfree(smc);
+}
+
+static int sm_checker_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ int r = dm_sm_get_nr_blocks(smc->real_sm, count);
+ if (!r)
+ BUG_ON(smc->old_counts.nr != *count);
+ return r;
+}
+
+static int sm_checker_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ int r = dm_sm_get_nr_free(smc->real_sm, count);
+ if (!r) {
+ /*
+ * Slow, but we know it's correct.
+ */
+ dm_block_t b, n = 0;
+ for (b = 0; b < smc->old_counts.nr; b++)
+ if (smc->old_counts.counts[b] == 0 &&
+ smc->counts.counts[b] == 0)
+ n++;
+
+ if (n != *count)
+ DMERR("free block counts differ, checker %u, sm-disk:%u",
+ (unsigned) n, (unsigned) *count);
+ }
+ return r;
+}
+
+static int sm_checker_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ int r = dm_sm_new_block(smc->real_sm, b);
+
+ if (!r) {
+ BUG_ON(*b >= smc->old_counts.nr);
+ BUG_ON(smc->old_counts.counts[*b] != 0);
+ BUG_ON(*b >= smc->counts.nr);
+ BUG_ON(smc->counts.counts[*b] != 0);
+ ca_set_count(&smc->counts, *b, 1);
+ }
+
+ return r;
+}
+
+static int sm_checker_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ int r = dm_sm_inc_block(smc->real_sm, b);
+ int r2 = ca_inc_block(&smc->counts, b);
+ BUG_ON(r != r2);
+ return r;
+}
+
+static int sm_checker_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ int r = dm_sm_dec_block(smc->real_sm, b);
+ int r2 = ca_dec_block(&smc->counts, b);
+ BUG_ON(r != r2);
+ return r;
+}
+
+static int sm_checker_get_count(struct dm_space_map *sm, dm_block_t b, uint32_t *result)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ uint32_t result2 = 0;
+ int r = dm_sm_get_count(smc->real_sm, b, result);
+ int r2 = ca_get_count(&smc->counts, b, &result2);
+
+ BUG_ON(r != r2);
+ if (!r)
+ BUG_ON(*result != result2);
+ return r;
+}
+
+static int sm_checker_count_more_than_one(struct dm_space_map *sm, dm_block_t b, int *result)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ int result2 = 0;
+ int r = dm_sm_count_is_more_than_one(smc->real_sm, b, result);
+ int r2 = ca_count_more_than_one(&smc->counts, b, &result2);
+
+ BUG_ON(r != r2);
+ if (!r)
+ BUG_ON(!(*result) && result2);
+ return r;
+}
+
+static int sm_checker_set_count(struct dm_space_map *sm, dm_block_t b, uint32_t count)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ uint32_t old_rc;
+ int r = dm_sm_set_count(smc->real_sm, b, count);
+ int r2;
+
+ BUG_ON(b >= smc->counts.nr);
+ old_rc = smc->counts.counts[b];
+ r2 = ca_set_count(&smc->counts, b, count);
+ BUG_ON(r != r2);
+
+ return r;
+}
+
+static int sm_checker_commit(struct dm_space_map *sm)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ int r;
+
+ r = dm_sm_commit(smc->real_sm);
+ if (r)
+ return r;
+
+ r = ca_commit(&smc->old_counts, &smc->counts);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int sm_checker_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ int r = dm_sm_extend(smc->real_sm, extra_blocks);
+ if (r)
+ return r;
+
+ return ca_extend(&smc->counts, extra_blocks);
+}
+
+static int sm_checker_root_size(struct dm_space_map *sm, size_t *result)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ return dm_sm_root_size(smc->real_sm, result);
+}
+
+static int sm_checker_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len)
+{
+ struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+ return dm_sm_copy_root(smc->real_sm, copy_to_here_le, len);
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_space_map ops_ = {
+ .destroy = sm_checker_destroy,
+ .get_nr_blocks = sm_checker_get_nr_blocks,
+ .get_nr_free = sm_checker_get_nr_free,
+ .inc_block = sm_checker_inc_block,
+ .dec_block = sm_checker_dec_block,
+ .new_block = sm_checker_new_block,
+ .get_count = sm_checker_get_count,
+ .count_is_more_than_one = sm_checker_count_more_than_one,
+ .set_count = sm_checker_set_count,
+ .commit = sm_checker_commit,
+ .extend = sm_checker_extend,
+ .root_size = sm_checker_root_size,
+ .copy_root = sm_checker_copy_root
+};
+
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
+{
+ int r;
+ struct sm_checker *smc;
+
+ if (!sm)
+ return NULL;
+
+ smc = kmalloc(sizeof(*smc), GFP_KERNEL);
+ if (!smc)
+ return NULL;
+
+ memcpy(&smc->sm, &ops_, sizeof(smc->sm));
+ r = ca_create(&smc->old_counts, sm);
+ if (r) {
+ kfree(smc);
+ return NULL;
+ }
+
+ r = ca_create(&smc->counts, sm);
+ if (r) {
+ ca_destroy(&smc->old_counts);
+ kfree(smc);
+ return NULL;
+ }
+
+ smc->real_sm = sm;
+
+ r = ca_load(&smc->counts, sm);
+ if (r) {
+ ca_destroy(&smc->counts);
+ ca_destroy(&smc->old_counts);
+ kfree(smc);
+ return NULL;
+ }
+
+ r = ca_commit(&smc->old_counts, &smc->counts);
+ if (r) {
+ ca_destroy(&smc->counts);
+ ca_destroy(&smc->old_counts);
+ kfree(smc);
+ return NULL;
+ }
+
+ return &smc->sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create);
+
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm)
+{
+ int r;
+ struct sm_checker *smc;
+
+ if (!sm)
+ return NULL;
+
+ smc = kmalloc(sizeof(*smc), GFP_KERNEL);
+ if (!smc)
+ return NULL;
+
+ memcpy(&smc->sm, &ops_, sizeof(smc->sm));
+ r = ca_create(&smc->old_counts, sm);
+ if (r) {
+ kfree(smc);
+ return NULL;
+ }
+
+ r = ca_create(&smc->counts, sm);
+ if (r) {
+ ca_destroy(&smc->old_counts);
+ kfree(smc);
+ return NULL;
+ }
+
+ smc->real_sm = sm;
+ return &smc->sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh);
+
+/*----------------------------------------------------------------*/
+
+#else
+
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
+{
+ return sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create);
+
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm)
+{
+ return sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff --git a/drivers/md/persistent-data/dm-space-map-checker.h b/drivers/md/persistent-data/dm-space-map-checker.h
new file mode 100644
index 000000000000..444dccf6688c
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-checker.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef SNAPSHOTS_SPACE_MAP_CHECKER_H
+#define SNAPSHOTS_SPACE_MAP_CHECKER_H
+
+#include "dm-space-map.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This space map wraps a real on-disk space map, and verifies all of its
+ * operations. It uses a lot of memory, so only use if you have a specific
+ * problem that you're debugging.
+ *
+ * Ownership of @sm passes.
+ */
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm);
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c
new file mode 100644
index 000000000000..df2494c06cdc
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-common.c
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-common.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/bitops.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map common"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Index validator.
+ */
+#define INDEX_CSUM_XOR 160478
+
+static void index_prepare_for_write(struct dm_block_validator *v,
+ struct dm_block *b,
+ size_t block_size)
+{
+ struct disk_metadata_index *mi_le = dm_block_data(b);
+
+ mi_le->blocknr = cpu_to_le64(dm_block_location(b));
+ mi_le->csum = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
+ block_size - sizeof(__le32),
+ INDEX_CSUM_XOR));
+}
+
+static int index_check(struct dm_block_validator *v,
+ struct dm_block *b,
+ size_t block_size)
+{
+ struct disk_metadata_index *mi_le = dm_block_data(b);
+ __le32 csum_disk;
+
+ if (dm_block_location(b) != le64_to_cpu(mi_le->blocknr)) {
+ DMERR("index_check failed blocknr %llu wanted %llu",
+ le64_to_cpu(mi_le->blocknr), dm_block_location(b));
+ return -ENOTBLK;
+ }
+
+ csum_disk = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
+ block_size - sizeof(__le32),
+ INDEX_CSUM_XOR));
+ if (csum_disk != mi_le->csum) {
+ DMERR("index_check failed csum %u wanted %u",
+ le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum));
+ return -EILSEQ;
+ }
+
+ return 0;
+}
+
+static struct dm_block_validator index_validator = {
+ .name = "index",
+ .prepare_for_write = index_prepare_for_write,
+ .check = index_check
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Bitmap validator
+ */
+#define BITMAP_CSUM_XOR 240779
+
+static void bitmap_prepare_for_write(struct dm_block_validator *v,
+ struct dm_block *b,
+ size_t block_size)
+{
+ struct disk_bitmap_header *disk_header = dm_block_data(b);
+
+ disk_header->blocknr = cpu_to_le64(dm_block_location(b));
+ disk_header->csum = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
+ block_size - sizeof(__le32),
+ BITMAP_CSUM_XOR));
+}
+
+static int bitmap_check(struct dm_block_validator *v,
+ struct dm_block *b,
+ size_t block_size)
+{
+ struct disk_bitmap_header *disk_header = dm_block_data(b);
+ __le32 csum_disk;
+
+ if (dm_block_location(b) != le64_to_cpu(disk_header->blocknr)) {
+ DMERR("bitmap check failed blocknr %llu wanted %llu",
+ le64_to_cpu(disk_header->blocknr), dm_block_location(b));
+ return -ENOTBLK;
+ }
+
+ csum_disk = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
+ block_size - sizeof(__le32),
+ BITMAP_CSUM_XOR));
+ if (csum_disk != disk_header->csum) {
+ DMERR("bitmap check failed csum %u wanted %u",
+ le32_to_cpu(csum_disk), le32_to_cpu(disk_header->csum));
+ return -EILSEQ;
+ }
+
+ return 0;
+}
+
+static struct dm_block_validator dm_sm_bitmap_validator = {
+ .name = "sm_bitmap",
+ .prepare_for_write = bitmap_prepare_for_write,
+ .check = bitmap_check
+};
+
+/*----------------------------------------------------------------*/
+
+#define ENTRIES_PER_WORD 32
+#define ENTRIES_SHIFT 5
+
+static void *dm_bitmap_data(struct dm_block *b)
+{
+ return dm_block_data(b) + sizeof(struct disk_bitmap_header);
+}
+
+#define WORD_MASK_HIGH 0xAAAAAAAAAAAAAAAAULL
+
+static unsigned bitmap_word_used(void *addr, unsigned b)
+{
+ __le64 *words_le = addr;
+ __le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+
+ uint64_t bits = le64_to_cpu(*w_le);
+ uint64_t mask = (bits + WORD_MASK_HIGH + 1) & WORD_MASK_HIGH;
+
+ return !(~bits & mask);
+}
+
+static unsigned sm_lookup_bitmap(void *addr, unsigned b)
+{
+ __le64 *words_le = addr;
+ __le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+ unsigned hi, lo;
+
+ b = (b & (ENTRIES_PER_WORD - 1)) << 1;
+ hi = !!test_bit_le(b, (void *) w_le);
+ lo = !!test_bit_le(b + 1, (void *) w_le);
+ return (hi << 1) | lo;
+}
+
+static void sm_set_bitmap(void *addr, unsigned b, unsigned val)
+{
+ __le64 *words_le = addr;
+ __le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+
+ b = (b & (ENTRIES_PER_WORD - 1)) << 1;
+
+ if (val & 2)
+ __set_bit_le(b, (void *) w_le);
+ else
+ __clear_bit_le(b, (void *) w_le);
+
+ if (val & 1)
+ __set_bit_le(b + 1, (void *) w_le);
+ else
+ __clear_bit_le(b + 1, (void *) w_le);
+}
+
+static int sm_find_free(void *addr, unsigned begin, unsigned end,
+ unsigned *result)
+{
+ while (begin < end) {
+ if (!(begin & (ENTRIES_PER_WORD - 1)) &&
+ bitmap_word_used(addr, begin)) {
+ begin += ENTRIES_PER_WORD;
+ continue;
+ }
+
+ if (!sm_lookup_bitmap(addr, begin)) {
+ *result = begin;
+ return 0;
+ }
+
+ begin++;
+ }
+
+ return -ENOSPC;
+}
+
+/*----------------------------------------------------------------*/
+
+static int sm_ll_init(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+ ll->tm = tm;
+
+ ll->bitmap_info.tm = tm;
+ ll->bitmap_info.levels = 1;
+
+ /*
+ * Because the new bitmap blocks are created via a shadow
+ * operation, the old entry has already had its reference count
+ * decremented and we don't need the btree to do any bookkeeping.
+ */
+ ll->bitmap_info.value_type.size = sizeof(struct disk_index_entry);
+ ll->bitmap_info.value_type.inc = NULL;
+ ll->bitmap_info.value_type.dec = NULL;
+ ll->bitmap_info.value_type.equal = NULL;
+
+ ll->ref_count_info.tm = tm;
+ ll->ref_count_info.levels = 1;
+ ll->ref_count_info.value_type.size = sizeof(uint32_t);
+ ll->ref_count_info.value_type.inc = NULL;
+ ll->ref_count_info.value_type.dec = NULL;
+ ll->ref_count_info.value_type.equal = NULL;
+
+ ll->block_size = dm_bm_block_size(dm_tm_get_bm(tm));
+
+ if (ll->block_size > (1 << 30)) {
+ DMERR("block size too big to hold bitmaps");
+ return -EINVAL;
+ }
+
+ ll->entries_per_block = (ll->block_size - sizeof(struct disk_bitmap_header)) *
+ ENTRIES_PER_BYTE;
+ ll->nr_blocks = 0;
+ ll->bitmap_root = 0;
+ ll->ref_count_root = 0;
+
+ return 0;
+}
+
+int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks)
+{
+ int r;
+ dm_block_t i, nr_blocks, nr_indexes;
+ unsigned old_blocks, blocks;
+
+ nr_blocks = ll->nr_blocks + extra_blocks;
+ old_blocks = dm_sector_div_up(ll->nr_blocks, ll->entries_per_block);
+ blocks = dm_sector_div_up(nr_blocks, ll->entries_per_block);
+
+ nr_indexes = dm_sector_div_up(nr_blocks, ll->entries_per_block);
+ if (nr_indexes > ll->max_entries(ll)) {
+ DMERR("space map too large");
+ return -EINVAL;
+ }
+
+ for (i = old_blocks; i < blocks; i++) {
+ struct dm_block *b;
+ struct disk_index_entry idx;
+
+ r = dm_tm_new_block(ll->tm, &dm_sm_bitmap_validator, &b);
+ if (r < 0)
+ return r;
+ idx.blocknr = cpu_to_le64(dm_block_location(b));
+
+ r = dm_tm_unlock(ll->tm, b);
+ if (r < 0)
+ return r;
+
+ idx.nr_free = cpu_to_le32(ll->entries_per_block);
+ idx.none_free_before = 0;
+
+ r = ll->save_ie(ll, i, &idx);
+ if (r < 0)
+ return r;
+ }
+
+ ll->nr_blocks = nr_blocks;
+ return 0;
+}
+
+int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result)
+{
+ int r;
+ dm_block_t index = b;
+ struct disk_index_entry ie_disk;
+ struct dm_block *blk;
+
+ b = do_div(index, ll->entries_per_block);
+ r = ll->load_ie(ll, index, &ie_disk);
+ if (r < 0)
+ return r;
+
+ r = dm_tm_read_lock(ll->tm, le64_to_cpu(ie_disk.blocknr),
+ &dm_sm_bitmap_validator, &blk);
+ if (r < 0)
+ return r;
+
+ *result = sm_lookup_bitmap(dm_bitmap_data(blk), b);
+
+ return dm_tm_unlock(ll->tm, blk);
+}
+
+int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
+{
+ __le32 le_rc;
+ int r = sm_ll_lookup_bitmap(ll, b, result);
+
+ if (r)
+ return r;
+
+ if (*result != 3)
+ return r;
+
+ r = dm_btree_lookup(&ll->ref_count_info, ll->ref_count_root, &b, &le_rc);
+ if (r < 0)
+ return r;
+
+ *result = le32_to_cpu(le_rc);
+
+ return r;
+}
+
+int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
+ dm_block_t end, dm_block_t *result)
+{
+ int r;
+ struct disk_index_entry ie_disk;
+ dm_block_t i, index_begin = begin;
+ dm_block_t index_end = dm_sector_div_up(end, ll->entries_per_block);
+
+ /*
+ * FIXME: Use shifts
+ */
+ begin = do_div(index_begin, ll->entries_per_block);
+ end = do_div(end, ll->entries_per_block);
+
+ for (i = index_begin; i < index_end; i++, begin = 0) {
+ struct dm_block *blk;
+ unsigned position;
+ uint32_t bit_end;
+
+ r = ll->load_ie(ll, i, &ie_disk);
+ if (r < 0)
+ return r;
+
+ if (le32_to_cpu(ie_disk.nr_free) == 0)
+ continue;
+
+ r = dm_tm_read_lock(ll->tm, le64_to_cpu(ie_disk.blocknr),
+ &dm_sm_bitmap_validator, &blk);
+ if (r < 0)
+ return r;
+
+ bit_end = (i == index_end - 1) ? end : ll->entries_per_block;
+
+ r = sm_find_free(dm_bitmap_data(blk),
+ max_t(unsigned, begin, le32_to_cpu(ie_disk.none_free_before)),
+ bit_end, &position);
+ if (r == -ENOSPC) {
+ /*
+ * This might happen because we started searching
+ * part way through the bitmap.
+ */
+ dm_tm_unlock(ll->tm, blk);
+ continue;
+
+ } else if (r < 0) {
+ dm_tm_unlock(ll->tm, blk);
+ return r;
+ }
+
+ r = dm_tm_unlock(ll->tm, blk);
+ if (r < 0)
+ return r;
+
+ *result = i * ll->entries_per_block + (dm_block_t) position;
+ return 0;
+ }
+
+ return -ENOSPC;
+}
+
+int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
+ uint32_t ref_count, enum allocation_event *ev)
+{
+ int r;
+ uint32_t bit, old;
+ struct dm_block *nb;
+ dm_block_t index = b;
+ struct disk_index_entry ie_disk;
+ void *bm_le;
+ int inc;
+
+ bit = do_div(index, ll->entries_per_block);
+ r = ll->load_ie(ll, index, &ie_disk);
+ if (r < 0)
+ return r;
+
+ r = dm_tm_shadow_block(ll->tm, le64_to_cpu(ie_disk.blocknr),
+ &dm_sm_bitmap_validator, &nb, &inc);
+ if (r < 0) {
+ DMERR("dm_tm_shadow_block() failed");
+ return r;
+ }
+ ie_disk.blocknr = cpu_to_le64(dm_block_location(nb));
+
+ bm_le = dm_bitmap_data(nb);
+ old = sm_lookup_bitmap(bm_le, bit);
+
+ if (ref_count <= 2) {
+ sm_set_bitmap(bm_le, bit, ref_count);
+
+ r = dm_tm_unlock(ll->tm, nb);
+ if (r < 0)
+ return r;
+
+#if 0
+ /* FIXME: dm_btree_remove doesn't handle this yet */
+ if (old > 2) {
+ r = dm_btree_remove(&ll->ref_count_info,
+ ll->ref_count_root,
+ &b, &ll->ref_count_root);
+ if (r)
+ return r;
+ }
+#endif
+
+ } else {
+ __le32 le_rc = cpu_to_le32(ref_count);
+
+ sm_set_bitmap(bm_le, bit, 3);
+ r = dm_tm_unlock(ll->tm, nb);
+ if (r < 0)
+ return r;
+
+ __dm_bless_for_disk(&le_rc);
+ r = dm_btree_insert(&ll->ref_count_info, ll->ref_count_root,
+ &b, &le_rc, &ll->ref_count_root);
+ if (r < 0) {
+ DMERR("ref count insert failed");
+ return r;
+ }
+ }
+
+ if (ref_count && !old) {
+ *ev = SM_ALLOC;
+ ll->nr_allocated++;
+ ie_disk.nr_free = cpu_to_le32(le32_to_cpu(ie_disk.nr_free) - 1);
+ if (le32_to_cpu(ie_disk.none_free_before) == bit)
+ ie_disk.none_free_before = cpu_to_le32(bit + 1);
+
+ } else if (old && !ref_count) {
+ *ev = SM_FREE;
+ ll->nr_allocated--;
+ ie_disk.nr_free = cpu_to_le32(le32_to_cpu(ie_disk.nr_free) + 1);
+ ie_disk.none_free_before = cpu_to_le32(min(le32_to_cpu(ie_disk.none_free_before), bit));
+ }
+
+ return ll->save_ie(ll, index, &ie_disk);
+}
+
+int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+{
+ int r;
+ uint32_t rc;
+
+ r = sm_ll_lookup(ll, b, &rc);
+ if (r)
+ return r;
+
+ return sm_ll_insert(ll, b, rc + 1, ev);
+}
+
+int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+{
+ int r;
+ uint32_t rc;
+
+ r = sm_ll_lookup(ll, b, &rc);
+ if (r)
+ return r;
+
+ if (!rc)
+ return -EINVAL;
+
+ return sm_ll_insert(ll, b, rc - 1, ev);
+}
+
+int sm_ll_commit(struct ll_disk *ll)
+{
+ return ll->commit(ll);
+}
+
+/*----------------------------------------------------------------*/
+
+static int metadata_ll_load_ie(struct ll_disk *ll, dm_block_t index,
+ struct disk_index_entry *ie)
+{
+ memcpy(ie, ll->mi_le.index + index, sizeof(*ie));
+ return 0;
+}
+
+static int metadata_ll_save_ie(struct ll_disk *ll, dm_block_t index,
+ struct disk_index_entry *ie)
+{
+ memcpy(ll->mi_le.index + index, ie, sizeof(*ie));
+ return 0;
+}
+
+static int metadata_ll_init_index(struct ll_disk *ll)
+{
+ int r;
+ struct dm_block *b;
+
+ r = dm_tm_new_block(ll->tm, &index_validator, &b);
+ if (r < 0)
+ return r;
+
+ memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
+ ll->bitmap_root = dm_block_location(b);
+
+ return dm_tm_unlock(ll->tm, b);
+}
+
+static int metadata_ll_open(struct ll_disk *ll)
+{
+ int r;
+ struct dm_block *block;
+
+ r = dm_tm_read_lock(ll->tm, ll->bitmap_root,
+ &index_validator, &block);
+ if (r)
+ return r;
+
+ memcpy(&ll->mi_le, dm_block_data(block), sizeof(ll->mi_le));
+ return dm_tm_unlock(ll->tm, block);
+}
+
+static dm_block_t metadata_ll_max_entries(struct ll_disk *ll)
+{
+ return MAX_METADATA_BITMAPS;
+}
+
+static int metadata_ll_commit(struct ll_disk *ll)
+{
+ int r, inc;
+ struct dm_block *b;
+
+ r = dm_tm_shadow_block(ll->tm, ll->bitmap_root, &index_validator, &b, &inc);
+ if (r)
+ return r;
+
+ memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
+ ll->bitmap_root = dm_block_location(b);
+
+ return dm_tm_unlock(ll->tm, b);
+}
+
+int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+ int r;
+
+ r = sm_ll_init(ll, tm);
+ if (r < 0)
+ return r;
+
+ ll->load_ie = metadata_ll_load_ie;
+ ll->save_ie = metadata_ll_save_ie;
+ ll->init_index = metadata_ll_init_index;
+ ll->open_index = metadata_ll_open;
+ ll->max_entries = metadata_ll_max_entries;
+ ll->commit = metadata_ll_commit;
+
+ ll->nr_blocks = 0;
+ ll->nr_allocated = 0;
+
+ r = ll->init_index(ll);
+ if (r < 0)
+ return r;
+
+ r = dm_btree_empty(&ll->ref_count_info, &ll->ref_count_root);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm,
+ void *root_le, size_t len)
+{
+ int r;
+ struct disk_sm_root *smr = root_le;
+
+ if (len < sizeof(struct disk_sm_root)) {
+ DMERR("sm_metadata root too small");
+ return -ENOMEM;
+ }
+
+ r = sm_ll_init(ll, tm);
+ if (r < 0)
+ return r;
+
+ ll->load_ie = metadata_ll_load_ie;
+ ll->save_ie = metadata_ll_save_ie;
+ ll->init_index = metadata_ll_init_index;
+ ll->open_index = metadata_ll_open;
+ ll->max_entries = metadata_ll_max_entries;
+ ll->commit = metadata_ll_commit;
+
+ ll->nr_blocks = le64_to_cpu(smr->nr_blocks);
+ ll->nr_allocated = le64_to_cpu(smr->nr_allocated);
+ ll->bitmap_root = le64_to_cpu(smr->bitmap_root);
+ ll->ref_count_root = le64_to_cpu(smr->ref_count_root);
+
+ return ll->open_index(ll);
+}
+
+/*----------------------------------------------------------------*/
+
+static int disk_ll_load_ie(struct ll_disk *ll, dm_block_t index,
+ struct disk_index_entry *ie)
+{
+ return dm_btree_lookup(&ll->bitmap_info, ll->bitmap_root, &index, ie);
+}
+
+static int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
+ struct disk_index_entry *ie)
+{
+ __dm_bless_for_disk(ie);
+ return dm_btree_insert(&ll->bitmap_info, ll->bitmap_root,
+ &index, ie, &ll->bitmap_root);
+}
+
+static int disk_ll_init_index(struct ll_disk *ll)
+{
+ return dm_btree_empty(&ll->bitmap_info, &ll->bitmap_root);
+}
+
+static int disk_ll_open(struct ll_disk *ll)
+{
+ /* nothing to do */
+ return 0;
+}
+
+static dm_block_t disk_ll_max_entries(struct ll_disk *ll)
+{
+ return -1ULL;
+}
+
+static int disk_ll_commit(struct ll_disk *ll)
+{
+ return 0;
+}
+
+int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+ int r;
+
+ r = sm_ll_init(ll, tm);
+ if (r < 0)
+ return r;
+
+ ll->load_ie = disk_ll_load_ie;
+ ll->save_ie = disk_ll_save_ie;
+ ll->init_index = disk_ll_init_index;
+ ll->open_index = disk_ll_open;
+ ll->max_entries = disk_ll_max_entries;
+ ll->commit = disk_ll_commit;
+
+ ll->nr_blocks = 0;
+ ll->nr_allocated = 0;
+
+ r = ll->init_index(ll);
+ if (r < 0)
+ return r;
+
+ r = dm_btree_empty(&ll->ref_count_info, &ll->ref_count_root);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int sm_ll_open_disk(struct ll_disk *ll, struct dm_transaction_manager *tm,
+ void *root_le, size_t len)
+{
+ int r;
+ struct disk_sm_root *smr = root_le;
+
+ if (len < sizeof(struct disk_sm_root)) {
+ DMERR("sm_metadata root too small");
+ return -ENOMEM;
+ }
+
+ r = sm_ll_init(ll, tm);
+ if (r < 0)
+ return r;
+
+ ll->load_ie = disk_ll_load_ie;
+ ll->save_ie = disk_ll_save_ie;
+ ll->init_index = disk_ll_init_index;
+ ll->open_index = disk_ll_open;
+ ll->max_entries = disk_ll_max_entries;
+ ll->commit = disk_ll_commit;
+
+ ll->nr_blocks = le64_to_cpu(smr->nr_blocks);
+ ll->nr_allocated = le64_to_cpu(smr->nr_allocated);
+ ll->bitmap_root = le64_to_cpu(smr->bitmap_root);
+ ll->ref_count_root = le64_to_cpu(smr->ref_count_root);
+
+ return ll->open_index(ll);
+}
+
+/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-space-map-common.h b/drivers/md/persistent-data/dm-space-map-common.h
new file mode 100644
index 000000000000..8f220821a9a9
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-common.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_SPACE_MAP_COMMON_H
+#define DM_SPACE_MAP_COMMON_H
+
+#include "dm-btree.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Low level disk format
+ *
+ * Bitmap btree
+ * ------------
+ *
+ * Each value stored in the btree is an index_entry. This points to a
+ * block that is used as a bitmap. Within the bitmap hold 2 bits per
+ * entry, which represent UNUSED = 0, REF_COUNT = 1, REF_COUNT = 2 and
+ * REF_COUNT = many.
+ *
+ * Refcount btree
+ * --------------
+ *
+ * Any entry that has a ref count higher than 2 gets entered in the ref
+ * count tree. The leaf values for this tree is the 32-bit ref count.
+ */
+
+struct disk_index_entry {
+ __le64 blocknr;
+ __le32 nr_free;
+ __le32 none_free_before;
+} __packed;
+
+
+#define MAX_METADATA_BITMAPS 255
+struct disk_metadata_index {
+ __le32 csum;
+ __le32 padding;
+ __le64 blocknr;
+
+ struct disk_index_entry index[MAX_METADATA_BITMAPS];
+} __packed;
+
+struct ll_disk;
+
+typedef int (*load_ie_fn)(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *result);
+typedef int (*save_ie_fn)(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *ie);
+typedef int (*init_index_fn)(struct ll_disk *ll);
+typedef int (*open_index_fn)(struct ll_disk *ll);
+typedef dm_block_t (*max_index_entries_fn)(struct ll_disk *ll);
+typedef int (*commit_fn)(struct ll_disk *ll);
+
+struct ll_disk {
+ struct dm_transaction_manager *tm;
+ struct dm_btree_info bitmap_info;
+ struct dm_btree_info ref_count_info;
+
+ uint32_t block_size;
+ uint32_t entries_per_block;
+ dm_block_t nr_blocks;
+ dm_block_t nr_allocated;
+
+ /*
+ * bitmap_root may be a btree root or a simple index.
+ */
+ dm_block_t bitmap_root;
+
+ dm_block_t ref_count_root;
+
+ struct disk_metadata_index mi_le;
+ load_ie_fn load_ie;
+ save_ie_fn save_ie;
+ init_index_fn init_index;
+ open_index_fn open_index;
+ max_index_entries_fn max_entries;
+ commit_fn commit;
+};
+
+struct disk_sm_root {
+ __le64 nr_blocks;
+ __le64 nr_allocated;
+ __le64 bitmap_root;
+ __le64 ref_count_root;
+} __packed;
+
+#define ENTRIES_PER_BYTE 4
+
+struct disk_bitmap_header {
+ __le32 csum;
+ __le32 not_used;
+ __le64 blocknr;
+} __packed;
+
+enum allocation_event {
+ SM_NONE,
+ SM_ALLOC,
+ SM_FREE,
+};
+
+/*----------------------------------------------------------------*/
+
+int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks);
+int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result);
+int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result);
+int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
+ dm_block_t end, dm_block_t *result);
+int sm_ll_insert(struct ll_disk *ll, dm_block_t b, uint32_t ref_count, enum allocation_event *ev);
+int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
+int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
+int sm_ll_commit(struct ll_disk *ll);
+
+int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm);
+int sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm,
+ void *root_le, size_t len);
+
+int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm);
+int sm_ll_open_disk(struct ll_disk *ll, struct dm_transaction_manager *tm,
+ void *root_le, size_t len);
+
+/*----------------------------------------------------------------*/
+
+#endif /* DM_SPACE_MAP_COMMON_H */
diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c
new file mode 100644
index 000000000000..aeff7852cf79
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-disk.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-checker.h"
+#include "dm-space-map-common.h"
+#include "dm-space-map-disk.h"
+#include "dm-space-map.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map disk"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Space map interface.
+ */
+struct sm_disk {
+ struct dm_space_map sm;
+
+ struct ll_disk ll;
+ struct ll_disk old_ll;
+
+ dm_block_t begin;
+ dm_block_t nr_allocated_this_transaction;
+};
+
+static void sm_disk_destroy(struct dm_space_map *sm)
+{
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+ kfree(smd);
+}
+
+static int sm_disk_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+ return sm_ll_extend(&smd->ll, extra_blocks);
+}
+
+static int sm_disk_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+ *count = smd->old_ll.nr_blocks;
+
+ return 0;
+}
+
+static int sm_disk_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+ *count = (smd->old_ll.nr_blocks - smd->old_ll.nr_allocated) - smd->nr_allocated_this_transaction;
+
+ return 0;
+}
+
+static int sm_disk_get_count(struct dm_space_map *sm, dm_block_t b,
+ uint32_t *result)
+{
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+ return sm_ll_lookup(&smd->ll, b, result);
+}
+
+static int sm_disk_count_is_more_than_one(struct dm_space_map *sm, dm_block_t b,
+ int *result)
+{
+ int r;
+ uint32_t count;
+
+ r = sm_disk_get_count(sm, b, &count);
+ if (r)
+ return r;
+
+ return count > 1;
+}
+
+static int sm_disk_set_count(struct dm_space_map *sm, dm_block_t b,
+ uint32_t count)
+{
+ int r;
+ uint32_t old_count;
+ enum allocation_event ev;
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+ r = sm_ll_insert(&smd->ll, b, count, &ev);
+ if (!r) {
+ switch (ev) {
+ case SM_NONE:
+ break;
+
+ case SM_ALLOC:
+ /*
+ * This _must_ be free in the prior transaction
+ * otherwise we've lost atomicity.
+ */
+ smd->nr_allocated_this_transaction++;
+ break;
+
+ case SM_FREE:
+ /*
+ * It's only free if it's also free in the last
+ * transaction.
+ */
+ r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+ if (r)
+ return r;
+
+ if (!old_count)
+ smd->nr_allocated_this_transaction--;
+ break;
+ }
+ }
+
+ return r;
+}
+
+static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+ int r;
+ enum allocation_event ev;
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+ r = sm_ll_inc(&smd->ll, b, &ev);
+ if (!r && (ev == SM_ALLOC))
+ /*
+ * This _must_ be free in the prior transaction
+ * otherwise we've lost atomicity.
+ */
+ smd->nr_allocated_this_transaction++;
+
+ return r;
+}
+
+static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+ int r;
+ uint32_t old_count;
+ enum allocation_event ev;
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+ r = sm_ll_dec(&smd->ll, b, &ev);
+ if (!r && (ev == SM_FREE)) {
+ /*
+ * It's only free if it's also free in the last
+ * transaction.
+ */
+ r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+ if (r)
+ return r;
+
+ if (!old_count)
+ smd->nr_allocated_this_transaction--;
+ }
+
+ return r;
+}
+
+static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+ int r;
+ enum allocation_event ev;
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+ /* FIXME: we should loop round a couple of times */
+ r = sm_ll_find_free_block(&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b);
+ if (r)
+ return r;
+
+ smd->begin = *b + 1;
+ r = sm_ll_inc(&smd->ll, *b, &ev);
+ if (!r) {
+ BUG_ON(ev != SM_ALLOC);
+ smd->nr_allocated_this_transaction++;
+ }
+
+ return r;
+}
+
+static int sm_disk_commit(struct dm_space_map *sm)
+{
+ int r;
+ dm_block_t nr_free;
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+ r = sm_disk_get_nr_free(sm, &nr_free);
+ if (r)
+ return r;
+
+ r = sm_ll_commit(&smd->ll);
+ if (r)
+ return r;
+
+ memcpy(&smd->old_ll, &smd->ll, sizeof(smd->old_ll));
+ smd->begin = 0;
+ smd->nr_allocated_this_transaction = 0;
+
+ r = sm_disk_get_nr_free(sm, &nr_free);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int sm_disk_root_size(struct dm_space_map *sm, size_t *result)
+{
+ *result = sizeof(struct disk_sm_root);
+
+ return 0;
+}
+
+static int sm_disk_copy_root(struct dm_space_map *sm, void *where_le, size_t max)
+{
+ struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+ struct disk_sm_root root_le;
+
+ root_le.nr_blocks = cpu_to_le64(smd->ll.nr_blocks);
+ root_le.nr_allocated = cpu_to_le64(smd->ll.nr_allocated);
+ root_le.bitmap_root = cpu_to_le64(smd->ll.bitmap_root);
+ root_le.ref_count_root = cpu_to_le64(smd->ll.ref_count_root);
+
+ if (max < sizeof(root_le))
+ return -ENOSPC;
+
+ memcpy(where_le, &root_le, sizeof(root_le));
+
+ return 0;
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_space_map ops = {
+ .destroy = sm_disk_destroy,
+ .extend = sm_disk_extend,
+ .get_nr_blocks = sm_disk_get_nr_blocks,
+ .get_nr_free = sm_disk_get_nr_free,
+ .get_count = sm_disk_get_count,
+ .count_is_more_than_one = sm_disk_count_is_more_than_one,
+ .set_count = sm_disk_set_count,
+ .inc_block = sm_disk_inc_block,
+ .dec_block = sm_disk_dec_block,
+ .new_block = sm_disk_new_block,
+ .commit = sm_disk_commit,
+ .root_size = sm_disk_root_size,
+ .copy_root = sm_disk_copy_root
+};
+
+static struct dm_space_map *dm_sm_disk_create_real(
+ struct dm_transaction_manager *tm,
+ dm_block_t nr_blocks)
+{
+ int r;
+ struct sm_disk *smd;
+
+ smd = kmalloc(sizeof(*smd), GFP_KERNEL);
+ if (!smd)
+ return ERR_PTR(-ENOMEM);
+
+ smd->begin = 0;
+ smd->nr_allocated_this_transaction = 0;
+ memcpy(&smd->sm, &ops, sizeof(smd->sm));
+
+ r = sm_ll_new_disk(&smd->ll, tm);
+ if (r)
+ goto bad;
+
+ r = sm_ll_extend(&smd->ll, nr_blocks);
+ if (r)
+ goto bad;
+
+ r = sm_disk_commit(&smd->sm);
+ if (r)
+ goto bad;
+
+ return &smd->sm;
+
+bad:
+ kfree(smd);
+ return ERR_PTR(r);
+}
+
+struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm,
+ dm_block_t nr_blocks)
+{
+ struct dm_space_map *sm = dm_sm_disk_create_real(tm, nr_blocks);
+ return dm_sm_checker_create_fresh(sm);
+}
+EXPORT_SYMBOL_GPL(dm_sm_disk_create);
+
+static struct dm_space_map *dm_sm_disk_open_real(
+ struct dm_transaction_manager *tm,
+ void *root_le, size_t len)
+{
+ int r;
+ struct sm_disk *smd;
+
+ smd = kmalloc(sizeof(*smd), GFP_KERNEL);
+ if (!smd)
+ return ERR_PTR(-ENOMEM);
+
+ smd->begin = 0;
+ smd->nr_allocated_this_transaction = 0;
+ memcpy(&smd->sm, &ops, sizeof(smd->sm));
+
+ r = sm_ll_open_disk(&smd->ll, tm, root_le, len);
+ if (r)
+ goto bad;
+
+ r = sm_disk_commit(&smd->sm);
+ if (r)
+ goto bad;
+
+ return &smd->sm;
+
+bad:
+ kfree(smd);
+ return ERR_PTR(r);
+}
+
+struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm,
+ void *root_le, size_t len)
+{
+ return dm_sm_checker_create(
+ dm_sm_disk_open_real(tm, root_le, len));
+}
+EXPORT_SYMBOL_GPL(dm_sm_disk_open);
+
+/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-space-map-disk.h b/drivers/md/persistent-data/dm-space-map-disk.h
new file mode 100644
index 000000000000..447a0a9a2d9f
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-disk.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_SPACE_MAP_DISK_H
+#define _LINUX_DM_SPACE_MAP_DISK_H
+
+#include "dm-block-manager.h"
+
+struct dm_space_map;
+struct dm_transaction_manager;
+
+/*
+ * Unfortunately we have to use two-phase construction due to the cycle
+ * between the tm and sm.
+ */
+struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm,
+ dm_block_t nr_blocks);
+
+struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm,
+ void *root, size_t len);
+
+#endif /* _LINUX_DM_SPACE_MAP_DISK_H */
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c
new file mode 100644
index 000000000000..e89ae5e7a519
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -0,0 +1,596 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map.h"
+#include "dm-space-map-common.h"
+#include "dm-space-map-metadata.h"
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map metadata"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Space map interface.
+ *
+ * The low level disk format is written using the standard btree and
+ * transaction manager. This means that performing disk operations may
+ * cause us to recurse into the space map in order to allocate new blocks.
+ * For this reason we have a pool of pre-allocated blocks large enough to
+ * service any metadata_ll_disk operation.
+ */
+
+/*
+ * FIXME: we should calculate this based on the size of the device.
+ * Only the metadata space map needs this functionality.
+ */
+#define MAX_RECURSIVE_ALLOCATIONS 1024
+
+enum block_op_type {
+ BOP_INC,
+ BOP_DEC
+};
+
+struct block_op {
+ enum block_op_type type;
+ dm_block_t block;
+};
+
+struct sm_metadata {
+ struct dm_space_map sm;
+
+ struct ll_disk ll;
+ struct ll_disk old_ll;
+
+ dm_block_t begin;
+
+ unsigned recursion_count;
+ unsigned allocated_this_transaction;
+ unsigned nr_uncommitted;
+ struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS];
+};
+
+static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b)
+{
+ struct block_op *op;
+
+ if (smm->nr_uncommitted == MAX_RECURSIVE_ALLOCATIONS) {
+ DMERR("too many recursive allocations");
+ return -ENOMEM;
+ }
+
+ op = smm->uncommitted + smm->nr_uncommitted++;
+ op->type = type;
+ op->block = b;
+
+ return 0;
+}
+
+static int commit_bop(struct sm_metadata *smm, struct block_op *op)
+{
+ int r = 0;
+ enum allocation_event ev;
+
+ switch (op->type) {
+ case BOP_INC:
+ r = sm_ll_inc(&smm->ll, op->block, &ev);
+ break;
+
+ case BOP_DEC:
+ r = sm_ll_dec(&smm->ll, op->block, &ev);
+ break;
+ }
+
+ return r;
+}
+
+static void in(struct sm_metadata *smm)
+{
+ smm->recursion_count++;
+}
+
+static int out(struct sm_metadata *smm)
+{
+ int r = 0;
+
+ /*
+ * If we're not recursing then very bad things are happening.
+ */
+ if (!smm->recursion_count) {
+ DMERR("lost track of recursion depth");
+ return -ENOMEM;
+ }
+
+ if (smm->recursion_count == 1 && smm->nr_uncommitted) {
+ while (smm->nr_uncommitted && !r) {
+ smm->nr_uncommitted--;
+ r = commit_bop(smm, smm->uncommitted +
+ smm->nr_uncommitted);
+ if (r)
+ break;
+ }
+ }
+
+ smm->recursion_count--;
+
+ return r;
+}
+
+/*
+ * When using the out() function above, we often want to combine an error
+ * code for the operation run in the recursive context with that from
+ * out().
+ */
+static int combine_errors(int r1, int r2)
+{
+ return r1 ? r1 : r2;
+}
+
+static int recursing(struct sm_metadata *smm)
+{
+ return smm->recursion_count;
+}
+
+static void sm_metadata_destroy(struct dm_space_map *sm)
+{
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ kfree(smm);
+}
+
+static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+ DMERR("doesn't support extend");
+ return -EINVAL;
+}
+
+static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ *count = smm->ll.nr_blocks;
+
+ return 0;
+}
+
+static int sm_metadata_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ *count = smm->old_ll.nr_blocks - smm->old_ll.nr_allocated -
+ smm->allocated_this_transaction;
+
+ return 0;
+}
+
+static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b,
+ uint32_t *result)
+{
+ int r, i;
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+ unsigned adjustment = 0;
+
+ /*
+ * We may have some uncommitted adjustments to add. This list
+ * should always be really short.
+ */
+ for (i = 0; i < smm->nr_uncommitted; i++) {
+ struct block_op *op = smm->uncommitted + i;
+
+ if (op->block != b)
+ continue;
+
+ switch (op->type) {
+ case BOP_INC:
+ adjustment++;
+ break;
+
+ case BOP_DEC:
+ adjustment--;
+ break;
+ }
+ }
+
+ r = sm_ll_lookup(&smm->ll, b, result);
+ if (r)
+ return r;
+
+ *result += adjustment;
+
+ return 0;
+}
+
+static int sm_metadata_count_is_more_than_one(struct dm_space_map *sm,
+ dm_block_t b, int *result)
+{
+ int r, i, adjustment = 0;
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+ uint32_t rc;
+
+ /*
+ * We may have some uncommitted adjustments to add. This list
+ * should always be really short.
+ */
+ for (i = 0; i < smm->nr_uncommitted; i++) {
+ struct block_op *op = smm->uncommitted + i;
+
+ if (op->block != b)
+ continue;
+
+ switch (op->type) {
+ case BOP_INC:
+ adjustment++;
+ break;
+
+ case BOP_DEC:
+ adjustment--;
+ break;
+ }
+ }
+
+ if (adjustment > 1) {
+ *result = 1;
+ return 0;
+ }
+
+ r = sm_ll_lookup_bitmap(&smm->ll, b, &rc);
+ if (r)
+ return r;
+
+ if (rc == 3)
+ /*
+ * We err on the side of caution, and always return true.
+ */
+ *result = 1;
+ else
+ *result = rc + adjustment > 1;
+
+ return 0;
+}
+
+static int sm_metadata_set_count(struct dm_space_map *sm, dm_block_t b,
+ uint32_t count)
+{
+ int r, r2;
+ enum allocation_event ev;
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ if (smm->recursion_count) {
+ DMERR("cannot recurse set_count()");
+ return -EINVAL;
+ }
+
+ in(smm);
+ r = sm_ll_insert(&smm->ll, b, count, &ev);
+ r2 = out(smm);
+
+ return combine_errors(r, r2);
+}
+
+static int sm_metadata_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+ int r, r2 = 0;
+ enum allocation_event ev;
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ if (recursing(smm))
+ r = add_bop(smm, BOP_INC, b);
+ else {
+ in(smm);
+ r = sm_ll_inc(&smm->ll, b, &ev);
+ r2 = out(smm);
+ }
+
+ return combine_errors(r, r2);
+}
+
+static int sm_metadata_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+ int r, r2 = 0;
+ enum allocation_event ev;
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ if (recursing(smm))
+ r = add_bop(smm, BOP_DEC, b);
+ else {
+ in(smm);
+ r = sm_ll_dec(&smm->ll, b, &ev);
+ r2 = out(smm);
+ }
+
+ return combine_errors(r, r2);
+}
+
+static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b)
+{
+ int r, r2 = 0;
+ enum allocation_event ev;
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b);
+ if (r)
+ return r;
+
+ smm->begin = *b + 1;
+
+ if (recursing(smm))
+ r = add_bop(smm, BOP_INC, *b);
+ else {
+ in(smm);
+ r = sm_ll_inc(&smm->ll, *b, &ev);
+ r2 = out(smm);
+ }
+
+ if (!r)
+ smm->allocated_this_transaction++;
+
+ return combine_errors(r, r2);
+}
+
+static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+ int r = sm_metadata_new_block_(sm, b);
+ if (r)
+ DMERR("out of metadata space");
+ return r;
+}
+
+static int sm_metadata_commit(struct dm_space_map *sm)
+{
+ int r;
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ r = sm_ll_commit(&smm->ll);
+ if (r)
+ return r;
+
+ memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
+ smm->begin = 0;
+ smm->allocated_this_transaction = 0;
+
+ return 0;
+}
+
+static int sm_metadata_root_size(struct dm_space_map *sm, size_t *result)
+{
+ *result = sizeof(struct disk_sm_root);
+
+ return 0;
+}
+
+static int sm_metadata_copy_root(struct dm_space_map *sm, void *where_le, size_t max)
+{
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+ struct disk_sm_root root_le;
+
+ root_le.nr_blocks = cpu_to_le64(smm->ll.nr_blocks);
+ root_le.nr_allocated = cpu_to_le64(smm->ll.nr_allocated);
+ root_le.bitmap_root = cpu_to_le64(smm->ll.bitmap_root);
+ root_le.ref_count_root = cpu_to_le64(smm->ll.ref_count_root);
+
+ if (max < sizeof(root_le))
+ return -ENOSPC;
+
+ memcpy(where_le, &root_le, sizeof(root_le));
+
+ return 0;
+}
+
+static struct dm_space_map ops = {
+ .destroy = sm_metadata_destroy,
+ .extend = sm_metadata_extend,
+ .get_nr_blocks = sm_metadata_get_nr_blocks,
+ .get_nr_free = sm_metadata_get_nr_free,
+ .get_count = sm_metadata_get_count,
+ .count_is_more_than_one = sm_metadata_count_is_more_than_one,
+ .set_count = sm_metadata_set_count,
+ .inc_block = sm_metadata_inc_block,
+ .dec_block = sm_metadata_dec_block,
+ .new_block = sm_metadata_new_block,
+ .commit = sm_metadata_commit,
+ .root_size = sm_metadata_root_size,
+ .copy_root = sm_metadata_copy_root
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * When a new space map is created that manages its own space. We use
+ * this tiny bootstrap allocator.
+ */
+static void sm_bootstrap_destroy(struct dm_space_map *sm)
+{
+}
+
+static int sm_bootstrap_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+ DMERR("boostrap doesn't support extend");
+
+ return -EINVAL;
+}
+
+static int sm_bootstrap_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ return smm->ll.nr_blocks;
+}
+
+static int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ *count = smm->ll.nr_blocks - smm->begin;
+
+ return 0;
+}
+
+static int sm_bootstrap_get_count(struct dm_space_map *sm, dm_block_t b,
+ uint32_t *result)
+{
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ return b < smm->begin ? 1 : 0;
+}
+
+static int sm_bootstrap_count_is_more_than_one(struct dm_space_map *sm,
+ dm_block_t b, int *result)
+{
+ *result = 0;
+
+ return 0;
+}
+
+static int sm_bootstrap_set_count(struct dm_space_map *sm, dm_block_t b,
+ uint32_t count)
+{
+ DMERR("boostrap doesn't support set_count");
+
+ return -EINVAL;
+}
+
+static int sm_bootstrap_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ /*
+ * We know the entire device is unused.
+ */
+ if (smm->begin == smm->ll.nr_blocks)
+ return -ENOSPC;
+
+ *b = smm->begin++;
+
+ return 0;
+}
+
+static int sm_bootstrap_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ return add_bop(smm, BOP_INC, b);
+}
+
+static int sm_bootstrap_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ return add_bop(smm, BOP_DEC, b);
+}
+
+static int sm_bootstrap_commit(struct dm_space_map *sm)
+{
+ return 0;
+}
+
+static int sm_bootstrap_root_size(struct dm_space_map *sm, size_t *result)
+{
+ DMERR("boostrap doesn't support root_size");
+
+ return -EINVAL;
+}
+
+static int sm_bootstrap_copy_root(struct dm_space_map *sm, void *where,
+ size_t max)
+{
+ DMERR("boostrap doesn't support copy_root");
+
+ return -EINVAL;
+}
+
+static struct dm_space_map bootstrap_ops = {
+ .destroy = sm_bootstrap_destroy,
+ .extend = sm_bootstrap_extend,
+ .get_nr_blocks = sm_bootstrap_get_nr_blocks,
+ .get_nr_free = sm_bootstrap_get_nr_free,
+ .get_count = sm_bootstrap_get_count,
+ .count_is_more_than_one = sm_bootstrap_count_is_more_than_one,
+ .set_count = sm_bootstrap_set_count,
+ .inc_block = sm_bootstrap_inc_block,
+ .dec_block = sm_bootstrap_dec_block,
+ .new_block = sm_bootstrap_new_block,
+ .commit = sm_bootstrap_commit,
+ .root_size = sm_bootstrap_root_size,
+ .copy_root = sm_bootstrap_copy_root
+};
+
+/*----------------------------------------------------------------*/
+
+struct dm_space_map *dm_sm_metadata_init(void)
+{
+ struct sm_metadata *smm;
+
+ smm = kmalloc(sizeof(*smm), GFP_KERNEL);
+ if (!smm)
+ return ERR_PTR(-ENOMEM);
+
+ memcpy(&smm->sm, &ops, sizeof(smm->sm));
+
+ return &smm->sm;
+}
+
+int dm_sm_metadata_create(struct dm_space_map *sm,
+ struct dm_transaction_manager *tm,
+ dm_block_t nr_blocks,
+ dm_block_t superblock)
+{
+ int r;
+ dm_block_t i;
+ enum allocation_event ev;
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ smm->begin = superblock + 1;
+ smm->recursion_count = 0;
+ smm->allocated_this_transaction = 0;
+ smm->nr_uncommitted = 0;
+
+ memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));
+
+ r = sm_ll_new_metadata(&smm->ll, tm);
+ if (r)
+ return r;
+
+ r = sm_ll_extend(&smm->ll, nr_blocks);
+ if (r)
+ return r;
+
+ memcpy(&smm->sm, &ops, sizeof(smm->sm));
+
+ /*
+ * Now we need to update the newly created data structures with the
+ * allocated blocks that they were built from.
+ */
+ for (i = superblock; !r && i < smm->begin; i++)
+ r = sm_ll_inc(&smm->ll, i, &ev);
+
+ if (r)
+ return r;
+
+ return sm_metadata_commit(sm);
+}
+
+int dm_sm_metadata_open(struct dm_space_map *sm,
+ struct dm_transaction_manager *tm,
+ void *root_le, size_t len)
+{
+ int r;
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+ r = sm_ll_open_metadata(&smm->ll, tm, root_le, len);
+ if (r)
+ return r;
+
+ smm->begin = 0;
+ smm->recursion_count = 0;
+ smm->allocated_this_transaction = 0;
+ smm->nr_uncommitted = 0;
+
+ memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
+ return 0;
+}
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.h b/drivers/md/persistent-data/dm-space-map-metadata.h
new file mode 100644
index 000000000000..39bba0801cf2
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-metadata.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_SPACE_MAP_METADATA_H
+#define DM_SPACE_MAP_METADATA_H
+
+#include "dm-transaction-manager.h"
+
+/*
+ * Unfortunately we have to use two-phase construction due to the cycle
+ * between the tm and sm.
+ */
+struct dm_space_map *dm_sm_metadata_init(void);
+
+/*
+ * Create a fresh space map.
+ */
+int dm_sm_metadata_create(struct dm_space_map *sm,
+ struct dm_transaction_manager *tm,
+ dm_block_t nr_blocks,
+ dm_block_t superblock);
+
+/*
+ * Open from a previously-recorded root.
+ */
+int dm_sm_metadata_open(struct dm_space_map *sm,
+ struct dm_transaction_manager *tm,
+ void *root_le, size_t len);
+
+#endif /* DM_SPACE_MAP_METADATA_H */
diff --git a/drivers/md/persistent-data/dm-space-map.h b/drivers/md/persistent-data/dm-space-map.h
new file mode 100644
index 000000000000..1cbfc6b1638a
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_SPACE_MAP_H
+#define _LINUX_DM_SPACE_MAP_H
+
+#include "dm-block-manager.h"
+
+/*
+ * struct dm_space_map keeps a record of how many times each block in a device
+ * is referenced. It needs to be fixed on disk as part of the transaction.
+ */
+struct dm_space_map {
+ void (*destroy)(struct dm_space_map *sm);
+
+ /*
+ * You must commit before allocating the newly added space.
+ */
+ int (*extend)(struct dm_space_map *sm, dm_block_t extra_blocks);
+
+ /*
+ * Extensions do not appear in this count until after commit has
+ * been called.
+ */
+ int (*get_nr_blocks)(struct dm_space_map *sm, dm_block_t *count);
+
+ /*
+ * Space maps must never allocate a block from the previous
+ * transaction, in case we need to rollback. This complicates the
+ * semantics of get_nr_free(), it should return the number of blocks
+ * that are available for allocation _now_. For instance you may
+ * have blocks with a zero reference count that will not be
+ * available for allocation until after the next commit.
+ */
+ int (*get_nr_free)(struct dm_space_map *sm, dm_block_t *count);
+
+ int (*get_count)(struct dm_space_map *sm, dm_block_t b, uint32_t *result);
+ int (*count_is_more_than_one)(struct dm_space_map *sm, dm_block_t b,
+ int *result);
+ int (*set_count)(struct dm_space_map *sm, dm_block_t b, uint32_t count);
+
+ int (*commit)(struct dm_space_map *sm);
+
+ int (*inc_block)(struct dm_space_map *sm, dm_block_t b);
+ int (*dec_block)(struct dm_space_map *sm, dm_block_t b);
+
+ /*
+ * new_block will increment the returned block.
+ */
+ int (*new_block)(struct dm_space_map *sm, dm_block_t *b);
+
+ /*
+ * The root contains all the information needed to fix the space map.
+ * Generally this info is small, so squirrel it away in a disk block
+ * along with other info.
+ */
+ int (*root_size)(struct dm_space_map *sm, size_t *result);
+ int (*copy_root)(struct dm_space_map *sm, void *copy_to_here_le, size_t len);
+};
+
+/*----------------------------------------------------------------*/
+
+static inline void dm_sm_destroy(struct dm_space_map *sm)
+{
+ sm->destroy(sm);
+}
+
+static inline int dm_sm_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+ return sm->extend(sm, extra_blocks);
+}
+
+static inline int dm_sm_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+ return sm->get_nr_blocks(sm, count);
+}
+
+static inline int dm_sm_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+ return sm->get_nr_free(sm, count);
+}
+
+static inline int dm_sm_get_count(struct dm_space_map *sm, dm_block_t b,
+ uint32_t *result)
+{
+ return sm->get_count(sm, b, result);
+}
+
+static inline int dm_sm_count_is_more_than_one(struct dm_space_map *sm,
+ dm_block_t b, int *result)
+{
+ return sm->count_is_more_than_one(sm, b, result);
+}
+
+static inline int dm_sm_set_count(struct dm_space_map *sm, dm_block_t b,
+ uint32_t count)
+{
+ return sm->set_count(sm, b, count);
+}
+
+static inline int dm_sm_commit(struct dm_space_map *sm)
+{
+ return sm->commit(sm);
+}
+
+static inline int dm_sm_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+ return sm->inc_block(sm, b);
+}
+
+static inline int dm_sm_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+ return sm->dec_block(sm, b);
+}
+
+static inline int dm_sm_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+ return sm->new_block(sm, b);
+}
+
+static inline int dm_sm_root_size(struct dm_space_map *sm, size_t *result)
+{
+ return sm->root_size(sm, result);
+}
+
+static inline int dm_sm_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len)
+{
+ return sm->copy_root(sm, copy_to_here_le, len);
+}
+
+#endif /* _LINUX_DM_SPACE_MAP_H */
diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c
new file mode 100644
index 000000000000..728e89a3f978
--- /dev/null
+++ b/drivers/md/persistent-data/dm-transaction-manager.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#include "dm-transaction-manager.h"
+#include "dm-space-map.h"
+#include "dm-space-map-checker.h"
+#include "dm-space-map-disk.h"
+#include "dm-space-map-metadata.h"
+#include "dm-persistent-data-internal.h"
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "transaction manager"
+
+/*----------------------------------------------------------------*/
+
+struct shadow_info {
+ struct hlist_node hlist;
+ dm_block_t where;
+};
+
+/*
+ * It would be nice if we scaled with the size of transaction.
+ */
+#define HASH_SIZE 256
+#define HASH_MASK (HASH_SIZE - 1)
+
+struct dm_transaction_manager {
+ int is_clone;
+ struct dm_transaction_manager *real;
+
+ struct dm_block_manager *bm;
+ struct dm_space_map *sm;
+
+ spinlock_t lock;
+ struct hlist_head buckets[HASH_SIZE];
+};
+
+/*----------------------------------------------------------------*/
+
+static int is_shadow(struct dm_transaction_manager *tm, dm_block_t b)
+{
+ int r = 0;
+ unsigned bucket = dm_hash_block(b, HASH_MASK);
+ struct shadow_info *si;
+ struct hlist_node *n;
+
+ spin_lock(&tm->lock);
+ hlist_for_each_entry(si, n, tm->buckets + bucket, hlist)
+ if (si->where == b) {
+ r = 1;
+ break;
+ }
+ spin_unlock(&tm->lock);
+
+ return r;
+}
+
+/*
+ * This can silently fail if there's no memory. We're ok with this since
+ * creating redundant shadows causes no harm.
+ */
+static void insert_shadow(struct dm_transaction_manager *tm, dm_block_t b)
+{
+ unsigned bucket;
+ struct shadow_info *si;
+
+ si = kmalloc(sizeof(*si), GFP_NOIO);
+ if (si) {
+ si->where = b;
+ bucket = dm_hash_block(b, HASH_MASK);
+ spin_lock(&tm->lock);
+ hlist_add_head(&si->hlist, tm->buckets + bucket);
+ spin_unlock(&tm->lock);
+ }
+}
+
+static void wipe_shadow_table(struct dm_transaction_manager *tm)
+{
+ struct shadow_info *si;
+ struct hlist_node *n, *tmp;
+ struct hlist_head *bucket;
+ int i;
+
+ spin_lock(&tm->lock);
+ for (i = 0; i < HASH_SIZE; i++) {
+ bucket = tm->buckets + i;
+ hlist_for_each_entry_safe(si, n, tmp, bucket, hlist)
+ kfree(si);
+
+ INIT_HLIST_HEAD(bucket);
+ }
+
+ spin_unlock(&tm->lock);
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_transaction_manager *dm_tm_create(struct dm_block_manager *bm,
+ struct dm_space_map *sm)
+{
+ int i;
+ struct dm_transaction_manager *tm;
+
+ tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+ if (!tm)
+ return ERR_PTR(-ENOMEM);
+
+ tm->is_clone = 0;
+ tm->real = NULL;
+ tm->bm = bm;
+ tm->sm = sm;
+
+ spin_lock_init(&tm->lock);
+ for (i = 0; i < HASH_SIZE; i++)
+ INIT_HLIST_HEAD(tm->buckets + i);
+
+ return tm;
+}
+
+struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real)
+{
+ struct dm_transaction_manager *tm;
+
+ tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+ if (tm) {
+ tm->is_clone = 1;
+ tm->real = real;
+ }
+
+ return tm;
+}
+EXPORT_SYMBOL_GPL(dm_tm_create_non_blocking_clone);
+
+void dm_tm_destroy(struct dm_transaction_manager *tm)
+{
+ kfree(tm);
+}
+EXPORT_SYMBOL_GPL(dm_tm_destroy);
+
+int dm_tm_pre_commit(struct dm_transaction_manager *tm)
+{
+ int r;
+
+ if (tm->is_clone)
+ return -EWOULDBLOCK;
+
+ r = dm_sm_commit(tm->sm);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dm_tm_pre_commit);
+
+int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root)
+{
+ if (tm->is_clone)
+ return -EWOULDBLOCK;
+
+ wipe_shadow_table(tm);
+
+ return dm_bm_flush_and_unlock(tm->bm, root);
+}
+EXPORT_SYMBOL_GPL(dm_tm_commit);
+
+int dm_tm_new_block(struct dm_transaction_manager *tm,
+ struct dm_block_validator *v,
+ struct dm_block **result)
+{
+ int r;
+ dm_block_t new_block;
+
+ if (tm->is_clone)
+ return -EWOULDBLOCK;
+
+ r = dm_sm_new_block(tm->sm, &new_block);
+ if (r < 0)
+ return r;
+
+ r = dm_bm_write_lock_zero(tm->bm, new_block, v, result);
+ if (r < 0) {
+ dm_sm_dec_block(tm->sm, new_block);
+ return r;
+ }
+
+ /*
+ * New blocks count as shadows in that they don't need to be
+ * shadowed again.
+ */
+ insert_shadow(tm, new_block);
+
+ return 0;
+}
+
+static int __shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+ struct dm_block_validator *v,
+ struct dm_block **result)
+{
+ int r;
+ dm_block_t new;
+ struct dm_block *orig_block;
+
+ r = dm_sm_new_block(tm->sm, &new);
+ if (r < 0)
+ return r;
+
+ r = dm_sm_dec_block(tm->sm, orig);
+ if (r < 0)
+ return r;
+
+ r = dm_bm_read_lock(tm->bm, orig, v, &orig_block);
+ if (r < 0)
+ return r;
+
+ r = dm_bm_unlock_move(orig_block, new);
+ if (r < 0) {
+ dm_bm_unlock(orig_block);
+ return r;
+ }
+
+ return dm_bm_write_lock(tm->bm, new, v, result);
+}
+
+int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+ struct dm_block_validator *v, struct dm_block **result,
+ int *inc_children)
+{
+ int r;
+
+ if (tm->is_clone)
+ return -EWOULDBLOCK;
+
+ r = dm_sm_count_is_more_than_one(tm->sm, orig, inc_children);
+ if (r < 0)
+ return r;
+
+ if (is_shadow(tm, orig) && !*inc_children)
+ return dm_bm_write_lock(tm->bm, orig, v, result);
+
+ r = __shadow_block(tm, orig, v, result);
+ if (r < 0)
+ return r;
+ insert_shadow(tm, dm_block_location(*result));
+
+ return r;
+}
+
+int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
+ struct dm_block_validator *v,
+ struct dm_block **blk)
+{
+ if (tm->is_clone)
+ return dm_bm_read_try_lock(tm->real->bm, b, v, blk);
+
+ return dm_bm_read_lock(tm->bm, b, v, blk);
+}
+
+int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b)
+{
+ return dm_bm_unlock(b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_unlock);
+
+void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b)
+{
+ /*
+ * The non-blocking clone doesn't support this.
+ */
+ BUG_ON(tm->is_clone);
+
+ dm_sm_inc_block(tm->sm, b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_inc);
+
+void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b)
+{
+ /*
+ * The non-blocking clone doesn't support this.
+ */
+ BUG_ON(tm->is_clone);
+
+ dm_sm_dec_block(tm->sm, b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_dec);
+
+int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b,
+ uint32_t *result)
+{
+ if (tm->is_clone)
+ return -EWOULDBLOCK;
+
+ return dm_sm_get_count(tm->sm, b, result);
+}
+
+struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm)
+{
+ return tm->bm;
+}
+
+/*----------------------------------------------------------------*/
+
+static int dm_tm_create_internal(struct dm_block_manager *bm,
+ dm_block_t sb_location,
+ struct dm_block_validator *sb_validator,
+ size_t root_offset, size_t root_max_len,
+ struct dm_transaction_manager **tm,
+ struct dm_space_map **sm,
+ struct dm_block **sblock,
+ int create)
+{
+ int r;
+ struct dm_space_map *inner;
+
+ inner = dm_sm_metadata_init();
+ if (IS_ERR(inner))
+ return PTR_ERR(inner);
+
+ *tm = dm_tm_create(bm, inner);
+ if (IS_ERR(*tm)) {
+ dm_sm_destroy(inner);
+ return PTR_ERR(*tm);
+ }
+
+ if (create) {
+ r = dm_bm_write_lock_zero(dm_tm_get_bm(*tm), sb_location,
+ sb_validator, sblock);
+ if (r < 0) {
+ DMERR("couldn't lock superblock");
+ goto bad1;
+ }
+
+ r = dm_sm_metadata_create(inner, *tm, dm_bm_nr_blocks(bm),
+ sb_location);
+ if (r) {
+ DMERR("couldn't create metadata space map");
+ goto bad2;
+ }
+
+ *sm = dm_sm_checker_create(inner);
+ if (!*sm)
+ goto bad2;
+
+ } else {
+ r = dm_bm_write_lock(dm_tm_get_bm(*tm), sb_location,
+ sb_validator, sblock);
+ if (r < 0) {
+ DMERR("couldn't lock superblock");
+ goto bad1;
+ }
+
+ r = dm_sm_metadata_open(inner, *tm,
+ dm_block_data(*sblock) + root_offset,
+ root_max_len);
+ if (r) {
+ DMERR("couldn't open metadata space map");
+ goto bad2;
+ }
+
+ *sm = dm_sm_checker_create(inner);
+ if (!*sm)
+ goto bad2;
+ }
+
+ return 0;
+
+bad2:
+ dm_tm_unlock(*tm, *sblock);
+bad1:
+ dm_tm_destroy(*tm);
+ dm_sm_destroy(inner);
+ return r;
+}
+
+int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+ struct dm_block_validator *sb_validator,
+ struct dm_transaction_manager **tm,
+ struct dm_space_map **sm, struct dm_block **sblock)
+{
+ return dm_tm_create_internal(bm, sb_location, sb_validator,
+ 0, 0, tm, sm, sblock, 1);
+}
+EXPORT_SYMBOL_GPL(dm_tm_create_with_sm);
+
+int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+ struct dm_block_validator *sb_validator,
+ size_t root_offset, size_t root_max_len,
+ struct dm_transaction_manager **tm,
+ struct dm_space_map **sm, struct dm_block **sblock)
+{
+ return dm_tm_create_internal(bm, sb_location, sb_validator, root_offset,
+ root_max_len, tm, sm, sblock, 0);
+}
+EXPORT_SYMBOL_GPL(dm_tm_open_with_sm);
+
+/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-transaction-manager.h b/drivers/md/persistent-data/dm-transaction-manager.h
new file mode 100644
index 000000000000..6da784871db4
--- /dev/null
+++ b/drivers/md/persistent-data/dm-transaction-manager.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_TRANSACTION_MANAGER_H
+#define _LINUX_DM_TRANSACTION_MANAGER_H
+
+#include "dm-block-manager.h"
+
+struct dm_transaction_manager;
+struct dm_space_map;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This manages the scope of a transaction. It also enforces immutability
+ * of the on-disk data structures by limiting access to writeable blocks.
+ *
+ * Clients should not fiddle with the block manager directly.
+ */
+
+void dm_tm_destroy(struct dm_transaction_manager *tm);
+
+/*
+ * The non-blocking version of a transaction manager is intended for use in
+ * fast path code that needs to do lookups e.g. a dm mapping function.
+ * You create the non-blocking variant from a normal tm. The interface is
+ * the same, except that most functions will just return -EWOULDBLOCK.
+ * Methods that return void yet may block should not be called on a clone
+ * viz. dm_tm_inc, dm_tm_dec. Call dm_tm_destroy() as you would with a normal
+ * tm when you've finished with it. You may not destroy the original prior
+ * to clones.
+ */
+struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real);
+
+/*
+ * We use a 2-phase commit here.
+ *
+ * i) In the first phase the block manager is told to start flushing, and
+ * the changes to the space map are written to disk. You should interrogate
+ * your particular space map to get detail of its root node etc. to be
+ * included in your superblock.
+ *
+ * ii) @root will be committed last. You shouldn't use more than the
+ * first 512 bytes of @root if you wish the transaction to survive a power
+ * failure. You *must* have a write lock held on @root for both stage (i)
+ * and (ii). The commit will drop the write lock.
+ */
+int dm_tm_pre_commit(struct dm_transaction_manager *tm);
+int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root);
+
+/*
+ * These methods are the only way to get hold of a writeable block.
+ */
+
+/*
+ * dm_tm_new_block() is pretty self-explanatory. Make sure you do actually
+ * write to the whole of @data before you unlock, otherwise you could get
+ * a data leak. (The other option is for tm_new_block() to zero new blocks
+ * before handing them out, which will be redundant in most, if not all,
+ * cases).
+ * Zeroes the new block and returns with write lock held.
+ */
+int dm_tm_new_block(struct dm_transaction_manager *tm,
+ struct dm_block_validator *v,
+ struct dm_block **result);
+
+/*
+ * dm_tm_shadow_block() allocates a new block and copies the data from @orig
+ * to it. It then decrements the reference count on original block. Use
+ * this to update the contents of a block in a data structure, don't
+ * confuse this with a clone - you shouldn't access the orig block after
+ * this operation. Because the tm knows the scope of the transaction it
+ * can optimise requests for a shadow of a shadow to a no-op. Don't forget
+ * to unlock when you've finished with the shadow.
+ *
+ * The @inc_children flag is used to tell the caller whether it needs to
+ * adjust reference counts for children. (Data in the block may refer to
+ * other blocks.)
+ *
+ * Shadowing implicitly drops a reference on @orig so you must not have
+ * it locked when you call this.
+ */
+int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+ struct dm_block_validator *v,
+ struct dm_block **result, int *inc_children);
+
+/*
+ * Read access. You can lock any block you want. If there's a write lock
+ * on it outstanding then it'll block.
+ */
+int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
+ struct dm_block_validator *v,
+ struct dm_block **result);
+
+int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b);
+
+/*
+ * Functions for altering the reference count of a block directly.
+ */
+void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b);
+
+void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b);
+
+int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b,
+ uint32_t *result);
+
+struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm);
+
+/*
+ * A little utility that ties the knot by producing a transaction manager
+ * that has a space map managed by the transaction manager...
+ *
+ * Returns a tm that has an open transaction to write the new disk sm.
+ * Caller should store the new sm root and commit.
+ */
+int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+ struct dm_block_validator *sb_validator,
+ struct dm_transaction_manager **tm,
+ struct dm_space_map **sm, struct dm_block **sblock);
+
+int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+ struct dm_block_validator *sb_validator,
+ size_t root_offset, size_t root_max_len,
+ struct dm_transaction_manager **tm,
+ struct dm_space_map **sm, struct dm_block **sblock);
+
+#endif /* _LINUX_DM_TRANSACTION_MANAGER_H */
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index e86bf3682e1e..0eb08a4df759 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -27,9 +27,9 @@
static int raid0_congested(void *data, int bits)
{
- mddev_t *mddev = data;
- raid0_conf_t *conf = mddev->private;
- mdk_rdev_t **devlist = conf->devlist;
+ struct mddev *mddev = data;
+ struct r0conf *conf = mddev->private;
+ struct md_rdev **devlist = conf->devlist;
int raid_disks = conf->strip_zone[0].nb_dev;
int i, ret = 0;
@@ -47,52 +47,53 @@ static int raid0_congested(void *data, int bits)
/*
* inform the user of the raid configuration
*/
-static void dump_zones(mddev_t *mddev)
+static void dump_zones(struct mddev *mddev)
{
- int j, k, h;
+ int j, k;
sector_t zone_size = 0;
sector_t zone_start = 0;
char b[BDEVNAME_SIZE];
- raid0_conf_t *conf = mddev->private;
+ struct r0conf *conf = mddev->private;
int raid_disks = conf->strip_zone[0].nb_dev;
- printk(KERN_INFO "******* %s configuration *********\n",
- mdname(mddev));
- h = 0;
+ printk(KERN_INFO "md: RAID0 configuration for %s - %d zone%s\n",
+ mdname(mddev),
+ conf->nr_strip_zones, conf->nr_strip_zones==1?"":"s");
for (j = 0; j < conf->nr_strip_zones; j++) {
- printk(KERN_INFO "zone%d=[", j);
+ printk(KERN_INFO "md: zone%d=[", j);
for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
- printk(KERN_CONT "%s/",
+ printk(KERN_CONT "%s%s", k?"/":"",
bdevname(conf->devlist[j*raid_disks
+ k]->bdev, b));
printk(KERN_CONT "]\n");
zone_size = conf->strip_zone[j].zone_end - zone_start;
- printk(KERN_INFO " zone offset=%llukb "
- "device offset=%llukb size=%llukb\n",
+ printk(KERN_INFO " zone-offset=%10lluKB, "
+ "device-offset=%10lluKB, size=%10lluKB\n",
(unsigned long long)zone_start>>1,
(unsigned long long)conf->strip_zone[j].dev_start>>1,
(unsigned long long)zone_size>>1);
zone_start = conf->strip_zone[j].zone_end;
}
- printk(KERN_INFO "**********************************\n\n");
+ printk(KERN_INFO "\n");
}
-static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
+static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
{
int i, c, err;
sector_t curr_zone_end, sectors;
- mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev, **dev;
+ struct md_rdev *smallest, *rdev1, *rdev2, *rdev, **dev;
struct strip_zone *zone;
int cnt;
char b[BDEVNAME_SIZE];
- raid0_conf_t *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+ char b2[BDEVNAME_SIZE];
+ struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
if (!conf)
return -ENOMEM;
list_for_each_entry(rdev1, &mddev->disks, same_set) {
- printk(KERN_INFO "md/raid0:%s: looking at %s\n",
- mdname(mddev),
- bdevname(rdev1->bdev, b));
+ pr_debug("md/raid0:%s: looking at %s\n",
+ mdname(mddev),
+ bdevname(rdev1->bdev, b));
c = 0;
/* round size to chunk_size */
@@ -101,16 +102,16 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
rdev1->sectors = sectors * mddev->chunk_sectors;
list_for_each_entry(rdev2, &mddev->disks, same_set) {
- printk(KERN_INFO "md/raid0:%s: comparing %s(%llu)",
- mdname(mddev),
- bdevname(rdev1->bdev,b),
- (unsigned long long)rdev1->sectors);
- printk(KERN_CONT " with %s(%llu)\n",
- bdevname(rdev2->bdev,b),
- (unsigned long long)rdev2->sectors);
+ pr_debug("md/raid0:%s: comparing %s(%llu)"
+ " with %s(%llu)\n",
+ mdname(mddev),
+ bdevname(rdev1->bdev,b),
+ (unsigned long long)rdev1->sectors,
+ bdevname(rdev2->bdev,b2),
+ (unsigned long long)rdev2->sectors);
if (rdev2 == rdev1) {
- printk(KERN_INFO "md/raid0:%s: END\n",
- mdname(mddev));
+ pr_debug("md/raid0:%s: END\n",
+ mdname(mddev));
break;
}
if (rdev2->sectors == rdev1->sectors) {
@@ -118,30 +119,30 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
* Not unique, don't count it as a new
* group
*/
- printk(KERN_INFO "md/raid0:%s: EQUAL\n",
- mdname(mddev));
+ pr_debug("md/raid0:%s: EQUAL\n",
+ mdname(mddev));
c = 1;
break;
}
- printk(KERN_INFO "md/raid0:%s: NOT EQUAL\n",
- mdname(mddev));
+ pr_debug("md/raid0:%s: NOT EQUAL\n",
+ mdname(mddev));
}
if (!c) {
- printk(KERN_INFO "md/raid0:%s: ==> UNIQUE\n",
- mdname(mddev));
+ pr_debug("md/raid0:%s: ==> UNIQUE\n",
+ mdname(mddev));
conf->nr_strip_zones++;
- printk(KERN_INFO "md/raid0:%s: %d zones\n",
- mdname(mddev), conf->nr_strip_zones);
+ pr_debug("md/raid0:%s: %d zones\n",
+ mdname(mddev), conf->nr_strip_zones);
}
}
- printk(KERN_INFO "md/raid0:%s: FINAL %d zones\n",
- mdname(mddev), conf->nr_strip_zones);
+ pr_debug("md/raid0:%s: FINAL %d zones\n",
+ mdname(mddev), conf->nr_strip_zones);
err = -ENOMEM;
conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
conf->nr_strip_zones, GFP_KERNEL);
if (!conf->strip_zone)
goto abort;
- conf->devlist = kzalloc(sizeof(mdk_rdev_t*)*
+ conf->devlist = kzalloc(sizeof(struct md_rdev*)*
conf->nr_strip_zones*mddev->raid_disks,
GFP_KERNEL);
if (!conf->devlist)
@@ -218,44 +219,45 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
zone = conf->strip_zone + i;
dev = conf->devlist + i * mddev->raid_disks;
- printk(KERN_INFO "md/raid0:%s: zone %d\n",
- mdname(mddev), i);
+ pr_debug("md/raid0:%s: zone %d\n", mdname(mddev), i);
zone->dev_start = smallest->sectors;
smallest = NULL;
c = 0;
for (j=0; j<cnt; j++) {
rdev = conf->devlist[j];
- printk(KERN_INFO "md/raid0:%s: checking %s ...",
- mdname(mddev),
- bdevname(rdev->bdev, b));
if (rdev->sectors <= zone->dev_start) {
- printk(KERN_CONT " nope.\n");
+ pr_debug("md/raid0:%s: checking %s ... nope\n",
+ mdname(mddev),
+ bdevname(rdev->bdev, b));
continue;
}
- printk(KERN_CONT " contained as device %d\n", c);
+ pr_debug("md/raid0:%s: checking %s ..."
+ " contained as device %d\n",
+ mdname(mddev),
+ bdevname(rdev->bdev, b), c);
dev[c] = rdev;
c++;
if (!smallest || rdev->sectors < smallest->sectors) {
smallest = rdev;
- printk(KERN_INFO "md/raid0:%s: (%llu) is smallest!.\n",
- mdname(mddev),
- (unsigned long long)rdev->sectors);
+ pr_debug("md/raid0:%s: (%llu) is smallest!.\n",
+ mdname(mddev),
+ (unsigned long long)rdev->sectors);
}
}
zone->nb_dev = c;
sectors = (smallest->sectors - zone->dev_start) * c;
- printk(KERN_INFO "md/raid0:%s: zone->nb_dev: %d, sectors: %llu\n",
- mdname(mddev),
- zone->nb_dev, (unsigned long long)sectors);
+ pr_debug("md/raid0:%s: zone->nb_dev: %d, sectors: %llu\n",
+ mdname(mddev),
+ zone->nb_dev, (unsigned long long)sectors);
curr_zone_end += sectors;
zone->zone_end = curr_zone_end;
- printk(KERN_INFO "md/raid0:%s: current zone start: %llu\n",
- mdname(mddev),
- (unsigned long long)smallest->sectors);
+ pr_debug("md/raid0:%s: current zone start: %llu\n",
+ mdname(mddev),
+ (unsigned long long)smallest->sectors);
}
mddev->queue->backing_dev_info.congested_fn = raid0_congested;
mddev->queue->backing_dev_info.congested_data = mddev;
@@ -275,7 +277,7 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
blk_queue_io_opt(mddev->queue,
(mddev->chunk_sectors << 9) * mddev->raid_disks);
- printk(KERN_INFO "md/raid0:%s: done.\n", mdname(mddev));
+ pr_debug("md/raid0:%s: done.\n", mdname(mddev));
*private_conf = conf;
return 0;
@@ -299,7 +301,7 @@ static int raid0_mergeable_bvec(struct request_queue *q,
struct bvec_merge_data *bvm,
struct bio_vec *biovec)
{
- mddev_t *mddev = q->queuedata;
+ struct mddev *mddev = q->queuedata;
sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
int max;
unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -318,10 +320,10 @@ static int raid0_mergeable_bvec(struct request_queue *q,
return max;
}
-static sector_t raid0_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks)
{
sector_t array_sectors = 0;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
WARN_ONCE(sectors || raid_disks,
"%s does not support generic reshape\n", __func__);
@@ -332,9 +334,9 @@ static sector_t raid0_size(mddev_t *mddev, sector_t sectors, int raid_disks)
return array_sectors;
}
-static int raid0_run(mddev_t *mddev)
+static int raid0_run(struct mddev *mddev)
{
- raid0_conf_t *conf;
+ struct r0conf *conf;
int ret;
if (mddev->chunk_sectors == 0) {
@@ -382,9 +384,9 @@ static int raid0_run(mddev_t *mddev)
return md_integrity_register(mddev);
}
-static int raid0_stop(mddev_t *mddev)
+static int raid0_stop(struct mddev *mddev)
{
- raid0_conf_t *conf = mddev->private;
+ struct r0conf *conf = mddev->private;
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree(conf->strip_zone);
@@ -397,7 +399,7 @@ static int raid0_stop(mddev_t *mddev)
/* Find the zone which holds a particular offset
* Update *sectorp to be an offset in that zone
*/
-static struct strip_zone *find_zone(struct raid0_private_data *conf,
+static struct strip_zone *find_zone(struct r0conf *conf,
sector_t *sectorp)
{
int i;
@@ -417,12 +419,12 @@ static struct strip_zone *find_zone(struct raid0_private_data *conf,
* remaps the bio to the target device. we separate two flows.
* power 2 flow and a general flow for the sake of perfromance
*/
-static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone,
+static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone,
sector_t sector, sector_t *sector_offset)
{
unsigned int sect_in_chunk;
sector_t chunk;
- raid0_conf_t *conf = mddev->private;
+ struct r0conf *conf = mddev->private;
int raid_disks = conf->strip_zone[0].nb_dev;
unsigned int chunk_sects = mddev->chunk_sectors;
@@ -453,7 +455,7 @@ static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone,
/*
* Is io distribute over 1 or more chunks ?
*/
-static inline int is_io_in_chunk_boundary(mddev_t *mddev,
+static inline int is_io_in_chunk_boundary(struct mddev *mddev,
unsigned int chunk_sects, struct bio *bio)
{
if (likely(is_power_of_2(chunk_sects))) {
@@ -466,12 +468,12 @@ static inline int is_io_in_chunk_boundary(mddev_t *mddev,
}
}
-static int raid0_make_request(mddev_t *mddev, struct bio *bio)
+static int raid0_make_request(struct mddev *mddev, struct bio *bio)
{
unsigned int chunk_sects;
sector_t sector_offset;
struct strip_zone *zone;
- mdk_rdev_t *tmp_dev;
+ struct md_rdev *tmp_dev;
if (unlikely(bio->bi_rw & REQ_FLUSH)) {
md_flush_request(mddev, bio);
@@ -526,43 +528,16 @@ bad_map:
return 0;
}
-static void raid0_status(struct seq_file *seq, mddev_t *mddev)
+static void raid0_status(struct seq_file *seq, struct mddev *mddev)
{
-#undef MD_DEBUG
-#ifdef MD_DEBUG
- int j, k, h;
- char b[BDEVNAME_SIZE];
- raid0_conf_t *conf = mddev->private;
- int raid_disks = conf->strip_zone[0].nb_dev;
-
- sector_t zone_size;
- sector_t zone_start = 0;
- h = 0;
-
- for (j = 0; j < conf->nr_strip_zones; j++) {
- seq_printf(seq, " z%d", j);
- seq_printf(seq, "=[");
- for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
- seq_printf(seq, "%s/", bdevname(
- conf->devlist[j*raid_disks + k]
- ->bdev, b));
-
- zone_size = conf->strip_zone[j].zone_end - zone_start;
- seq_printf(seq, "] ze=%lld ds=%lld s=%lld\n",
- (unsigned long long)zone_start>>1,
- (unsigned long long)conf->strip_zone[j].dev_start>>1,
- (unsigned long long)zone_size>>1);
- zone_start = conf->strip_zone[j].zone_end;
- }
-#endif
seq_printf(seq, " %dk chunks", mddev->chunk_sectors / 2);
return;
}
-static void *raid0_takeover_raid45(mddev_t *mddev)
+static void *raid0_takeover_raid45(struct mddev *mddev)
{
- mdk_rdev_t *rdev;
- raid0_conf_t *priv_conf;
+ struct md_rdev *rdev;
+ struct r0conf *priv_conf;
if (mddev->degraded != 1) {
printk(KERN_ERR "md/raid0:%s: raid5 must be degraded! Degraded disks: %d\n",
@@ -593,9 +568,9 @@ static void *raid0_takeover_raid45(mddev_t *mddev)
return priv_conf;
}
-static void *raid0_takeover_raid10(mddev_t *mddev)
+static void *raid0_takeover_raid10(struct mddev *mddev)
{
- raid0_conf_t *priv_conf;
+ struct r0conf *priv_conf;
/* Check layout:
* - far_copies must be 1
@@ -634,9 +609,9 @@ static void *raid0_takeover_raid10(mddev_t *mddev)
return priv_conf;
}
-static void *raid0_takeover_raid1(mddev_t *mddev)
+static void *raid0_takeover_raid1(struct mddev *mddev)
{
- raid0_conf_t *priv_conf;
+ struct r0conf *priv_conf;
/* Check layout:
* - (N - 1) mirror drives must be already faulty
@@ -660,7 +635,7 @@ static void *raid0_takeover_raid1(mddev_t *mddev)
return priv_conf;
}
-static void *raid0_takeover(mddev_t *mddev)
+static void *raid0_takeover(struct mddev *mddev)
{
/* raid0 can take over:
* raid4 - if all data disks are active.
@@ -691,11 +666,11 @@ static void *raid0_takeover(mddev_t *mddev)
return ERR_PTR(-EINVAL);
}
-static void raid0_quiesce(mddev_t *mddev, int state)
+static void raid0_quiesce(struct mddev *mddev, int state)
{
}
-static struct mdk_personality raid0_personality=
+static struct md_personality raid0_personality=
{
.name = "raid0",
.level = 0,
diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h
index 91f8e876ee64..0884bba8df4c 100644
--- a/drivers/md/raid0.h
+++ b/drivers/md/raid0.h
@@ -1,20 +1,16 @@
#ifndef _RAID0_H
#define _RAID0_H
-struct strip_zone
-{
+struct strip_zone {
sector_t zone_end; /* Start of the next zone (in sectors) */
sector_t dev_start; /* Zone offset in real dev (in sectors) */
int nb_dev; /* # of devices attached to the zone */
};
-struct raid0_private_data
-{
+struct r0conf {
struct strip_zone *strip_zone;
- mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
+ struct md_rdev **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
int nr_strip_zones;
};
-typedef struct raid0_private_data raid0_conf_t;
-
#endif
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d9587dffe533..4602fc57c961 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -40,22 +40,24 @@
#include "raid1.h"
#include "bitmap.h"
-#define DEBUG 0
-#define PRINTK(x...) do { if (DEBUG) printk(x); } while (0)
-
/*
* Number of guaranteed r1bios in case of extreme VM load:
*/
#define NR_RAID1_BIOS 256
+/* When there are this many requests queue to be written by
+ * the raid1 thread, we become 'congested' to provide back-pressure
+ * for writeback.
+ */
+static int max_queued_requests = 1024;
-static void allow_barrier(conf_t *conf);
-static void lower_barrier(conf_t *conf);
+static void allow_barrier(struct r1conf *conf);
+static void lower_barrier(struct r1conf *conf);
static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
{
struct pool_info *pi = data;
- int size = offsetof(r1bio_t, bios[pi->raid_disks]);
+ int size = offsetof(struct r1bio, bios[pi->raid_disks]);
/* allocate a r1bio with room for raid_disks entries in the bios array */
return kzalloc(size, gfp_flags);
@@ -76,7 +78,7 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
{
struct pool_info *pi = data;
struct page *page;
- r1bio_t *r1_bio;
+ struct r1bio *r1_bio;
struct bio *bio;
int i, j;
@@ -142,7 +144,7 @@ static void r1buf_pool_free(void *__r1_bio, void *data)
{
struct pool_info *pi = data;
int i,j;
- r1bio_t *r1bio = __r1_bio;
+ struct r1bio *r1bio = __r1_bio;
for (i = 0; i < RESYNC_PAGES; i++)
for (j = pi->raid_disks; j-- ;) {
@@ -157,7 +159,7 @@ static void r1buf_pool_free(void *__r1_bio, void *data)
r1bio_pool_free(r1bio, data);
}
-static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
+static void put_all_bios(struct r1conf *conf, struct r1bio *r1_bio)
{
int i;
@@ -169,17 +171,17 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
}
}
-static void free_r1bio(r1bio_t *r1_bio)
+static void free_r1bio(struct r1bio *r1_bio)
{
- conf_t *conf = r1_bio->mddev->private;
+ struct r1conf *conf = r1_bio->mddev->private;
put_all_bios(conf, r1_bio);
mempool_free(r1_bio, conf->r1bio_pool);
}
-static void put_buf(r1bio_t *r1_bio)
+static void put_buf(struct r1bio *r1_bio)
{
- conf_t *conf = r1_bio->mddev->private;
+ struct r1conf *conf = r1_bio->mddev->private;
int i;
for (i=0; i<conf->raid_disks; i++) {
@@ -193,11 +195,11 @@ static void put_buf(r1bio_t *r1_bio)
lower_barrier(conf);
}
-static void reschedule_retry(r1bio_t *r1_bio)
+static void reschedule_retry(struct r1bio *r1_bio)
{
unsigned long flags;
- mddev_t *mddev = r1_bio->mddev;
- conf_t *conf = mddev->private;
+ struct mddev *mddev = r1_bio->mddev;
+ struct r1conf *conf = mddev->private;
spin_lock_irqsave(&conf->device_lock, flags);
list_add(&r1_bio->retry_list, &conf->retry_list);
@@ -213,11 +215,11 @@ static void reschedule_retry(r1bio_t *r1_bio)
* operation and are ready to return a success/failure code to the buffer
* cache layer.
*/
-static void call_bio_endio(r1bio_t *r1_bio)
+static void call_bio_endio(struct r1bio *r1_bio)
{
struct bio *bio = r1_bio->master_bio;
int done;
- conf_t *conf = r1_bio->mddev->private;
+ struct r1conf *conf = r1_bio->mddev->private;
if (bio->bi_phys_segments) {
unsigned long flags;
@@ -240,17 +242,17 @@ static void call_bio_endio(r1bio_t *r1_bio)
}
}
-static void raid_end_bio_io(r1bio_t *r1_bio)
+static void raid_end_bio_io(struct r1bio *r1_bio)
{
struct bio *bio = r1_bio->master_bio;
/* if nobody has done the final endio yet, do it now */
if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
- PRINTK(KERN_DEBUG "raid1: sync end %s on sectors %llu-%llu\n",
- (bio_data_dir(bio) == WRITE) ? "write" : "read",
- (unsigned long long) bio->bi_sector,
- (unsigned long long) bio->bi_sector +
- (bio->bi_size >> 9) - 1);
+ pr_debug("raid1: sync end %s on sectors %llu-%llu\n",
+ (bio_data_dir(bio) == WRITE) ? "write" : "read",
+ (unsigned long long) bio->bi_sector,
+ (unsigned long long) bio->bi_sector +
+ (bio->bi_size >> 9) - 1);
call_bio_endio(r1_bio);
}
@@ -260,20 +262,38 @@ static void raid_end_bio_io(r1bio_t *r1_bio)
/*
* Update disk head position estimator based on IRQ completion info.
*/
-static inline void update_head_pos(int disk, r1bio_t *r1_bio)
+static inline void update_head_pos(int disk, struct r1bio *r1_bio)
{
- conf_t *conf = r1_bio->mddev->private;
+ struct r1conf *conf = r1_bio->mddev->private;
conf->mirrors[disk].head_position =
r1_bio->sector + (r1_bio->sectors);
}
+/*
+ * Find the disk number which triggered given bio
+ */
+static int find_bio_disk(struct r1bio *r1_bio, struct bio *bio)
+{
+ int mirror;
+ int raid_disks = r1_bio->mddev->raid_disks;
+
+ for (mirror = 0; mirror < raid_disks; mirror++)
+ if (r1_bio->bios[mirror] == bio)
+ break;
+
+ BUG_ON(mirror == raid_disks);
+ update_head_pos(mirror, r1_bio);
+
+ return mirror;
+}
+
static void raid1_end_read_request(struct bio *bio, int error)
{
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
- r1bio_t *r1_bio = bio->bi_private;
+ struct r1bio *r1_bio = bio->bi_private;
int mirror;
- conf_t *conf = r1_bio->mddev->private;
+ struct r1conf *conf = r1_bio->mddev->private;
mirror = r1_bio->read_disk;
/*
@@ -318,7 +338,7 @@ static void raid1_end_read_request(struct bio *bio, int error)
rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
}
-static void close_write(r1bio_t *r1_bio)
+static void close_write(struct r1bio *r1_bio)
{
/* it really is the end of this request */
if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
@@ -337,7 +357,7 @@ static void close_write(r1bio_t *r1_bio)
md_write_end(r1_bio->mddev);
}
-static void r1_bio_write_done(r1bio_t *r1_bio)
+static void r1_bio_write_done(struct r1bio *r1_bio)
{
if (!atomic_dec_and_test(&r1_bio->remaining))
return;
@@ -356,15 +376,12 @@ static void r1_bio_write_done(r1bio_t *r1_bio)
static void raid1_end_write_request(struct bio *bio, int error)
{
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
- r1bio_t *r1_bio = bio->bi_private;
+ struct r1bio *r1_bio = bio->bi_private;
int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
- conf_t *conf = r1_bio->mddev->private;
+ struct r1conf *conf = r1_bio->mddev->private;
struct bio *to_put = NULL;
-
- for (mirror = 0; mirror < conf->raid_disks; mirror++)
- if (r1_bio->bios[mirror] == bio)
- break;
+ mirror = find_bio_disk(r1_bio, bio);
/*
* 'one mirror IO has finished' event handler:
@@ -400,8 +417,6 @@ static void raid1_end_write_request(struct bio *bio, int error)
}
}
- update_head_pos(mirror, r1_bio);
-
if (behind) {
if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
atomic_dec(&r1_bio->behind_remaining);
@@ -418,10 +433,11 @@ static void raid1_end_write_request(struct bio *bio, int error)
/* Maybe we can return now */
if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
struct bio *mbio = r1_bio->master_bio;
- PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
- (unsigned long long) mbio->bi_sector,
- (unsigned long long) mbio->bi_sector +
- (mbio->bi_size >> 9) - 1);
+ pr_debug("raid1: behind end write sectors"
+ " %llu-%llu\n",
+ (unsigned long long) mbio->bi_sector,
+ (unsigned long long) mbio->bi_sector +
+ (mbio->bi_size >> 9) - 1);
call_bio_endio(r1_bio);
}
}
@@ -455,7 +471,7 @@ static void raid1_end_write_request(struct bio *bio, int error)
*
* The rdev for the device selected will have nr_pending incremented.
*/
-static int read_balance(conf_t *conf, r1bio_t *r1_bio, int *max_sectors)
+static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sectors)
{
const sector_t this_sector = r1_bio->sector;
int sectors;
@@ -464,7 +480,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio, int *max_sectors)
int best_disk;
int i;
sector_t best_dist;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int choose_first;
rcu_read_lock();
@@ -582,14 +598,18 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio, int *max_sectors)
return best_disk;
}
-int md_raid1_congested(mddev_t *mddev, int bits)
+int md_raid1_congested(struct mddev *mddev, int bits)
{
- conf_t *conf = mddev->private;
+ struct r1conf *conf = mddev->private;
int i, ret = 0;
+ if ((bits & (1 << BDI_async_congested)) &&
+ conf->pending_count >= max_queued_requests)
+ return 1;
+
rcu_read_lock();
for (i = 0; i < mddev->raid_disks; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+ struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
if (rdev && !test_bit(Faulty, &rdev->flags)) {
struct request_queue *q = bdev_get_queue(rdev->bdev);
@@ -611,13 +631,13 @@ EXPORT_SYMBOL_GPL(md_raid1_congested);
static int raid1_congested(void *data, int bits)
{
- mddev_t *mddev = data;
+ struct mddev *mddev = data;
return mddev_congested(mddev, bits) ||
md_raid1_congested(mddev, bits);
}
-static void flush_pending_writes(conf_t *conf)
+static void flush_pending_writes(struct r1conf *conf)
{
/* Any writes that have been queued but are awaiting
* bitmap updates get flushed here.
@@ -627,10 +647,12 @@ static void flush_pending_writes(conf_t *conf)
if (conf->pending_bio_list.head) {
struct bio *bio;
bio = bio_list_get(&conf->pending_bio_list);
+ conf->pending_count = 0;
spin_unlock_irq(&conf->device_lock);
/* flush any pending bitmap writes to
* disk before proceeding w/ I/O */
bitmap_unplug(conf->mddev->bitmap);
+ wake_up(&conf->wait_barrier);
while (bio) { /* submit pending writes */
struct bio *next = bio->bi_next;
@@ -665,7 +687,7 @@ static void flush_pending_writes(conf_t *conf)
*/
#define RESYNC_DEPTH 32
-static void raise_barrier(conf_t *conf)
+static void raise_barrier(struct r1conf *conf)
{
spin_lock_irq(&conf->resync_lock);
@@ -684,7 +706,7 @@ static void raise_barrier(conf_t *conf)
spin_unlock_irq(&conf->resync_lock);
}
-static void lower_barrier(conf_t *conf)
+static void lower_barrier(struct r1conf *conf)
{
unsigned long flags;
BUG_ON(conf->barrier <= 0);
@@ -694,7 +716,7 @@ static void lower_barrier(conf_t *conf)
wake_up(&conf->wait_barrier);
}
-static void wait_barrier(conf_t *conf)
+static void wait_barrier(struct r1conf *conf)
{
spin_lock_irq(&conf->resync_lock);
if (conf->barrier) {
@@ -708,7 +730,7 @@ static void wait_barrier(conf_t *conf)
spin_unlock_irq(&conf->resync_lock);
}
-static void allow_barrier(conf_t *conf)
+static void allow_barrier(struct r1conf *conf)
{
unsigned long flags;
spin_lock_irqsave(&conf->resync_lock, flags);
@@ -717,7 +739,7 @@ static void allow_barrier(conf_t *conf)
wake_up(&conf->wait_barrier);
}
-static void freeze_array(conf_t *conf)
+static void freeze_array(struct r1conf *conf)
{
/* stop syncio and normal IO and wait for everything to
* go quite.
@@ -740,7 +762,7 @@ static void freeze_array(conf_t *conf)
flush_pending_writes(conf));
spin_unlock_irq(&conf->resync_lock);
}
-static void unfreeze_array(conf_t *conf)
+static void unfreeze_array(struct r1conf *conf)
{
/* reverse the effect of the freeze */
spin_lock_irq(&conf->resync_lock);
@@ -753,7 +775,7 @@ static void unfreeze_array(conf_t *conf)
/* duplicate the data pages for behind I/O
*/
-static void alloc_behind_pages(struct bio *bio, r1bio_t *r1_bio)
+static void alloc_behind_pages(struct bio *bio, struct r1bio *r1_bio)
{
int i;
struct bio_vec *bvec;
@@ -782,14 +804,14 @@ do_sync_io:
if (bvecs[i].bv_page)
put_page(bvecs[i].bv_page);
kfree(bvecs);
- PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
+ pr_debug("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
}
-static int make_request(mddev_t *mddev, struct bio * bio)
+static int make_request(struct mddev *mddev, struct bio * bio)
{
- conf_t *conf = mddev->private;
- mirror_info_t *mirror;
- r1bio_t *r1_bio;
+ struct r1conf *conf = mddev->private;
+ struct mirror_info *mirror;
+ struct r1bio *r1_bio;
struct bio *read_bio;
int i, disks;
struct bitmap *bitmap;
@@ -797,7 +819,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
const int rw = bio_data_dir(bio);
const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
- mdk_rdev_t *blocked_rdev;
+ struct md_rdev *blocked_rdev;
int plugged;
int first_clone;
int sectors_handled;
@@ -934,6 +956,11 @@ read_again:
/*
* WRITE:
*/
+ if (conf->pending_count >= max_queued_requests) {
+ md_wakeup_thread(mddev->thread);
+ wait_event(conf->wait_barrier,
+ conf->pending_count < max_queued_requests);
+ }
/* first select target devices under rcu_lock and
* inc refcount on their rdev. Record them by setting
* bios[x] to bio
@@ -952,7 +979,7 @@ read_again:
rcu_read_lock();
max_sectors = r1_bio->sectors;
for (i = 0; i < disks; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+ struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
atomic_inc(&rdev->nr_pending);
blocked_rdev = rdev;
@@ -1097,6 +1124,7 @@ read_again:
atomic_inc(&r1_bio->remaining);
spin_lock_irqsave(&conf->device_lock, flags);
bio_list_add(&conf->pending_bio_list, mbio);
+ conf->pending_count++;
spin_unlock_irqrestore(&conf->device_lock, flags);
}
/* Mustn't call r1_bio_write_done before this next test,
@@ -1127,16 +1155,16 @@ read_again:
return 0;
}
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
{
- conf_t *conf = mddev->private;
+ struct r1conf *conf = mddev->private;
int i;
seq_printf(seq, " [%d/%d] [", conf->raid_disks,
conf->raid_disks - mddev->degraded);
rcu_read_lock();
for (i = 0; i < conf->raid_disks; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+ struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
seq_printf(seq, "%s",
rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_");
}
@@ -1145,10 +1173,10 @@ static void status(struct seq_file *seq, mddev_t *mddev)
}
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+static void error(struct mddev *mddev, struct md_rdev *rdev)
{
char b[BDEVNAME_SIZE];
- conf_t *conf = mddev->private;
+ struct r1conf *conf = mddev->private;
/*
* If it is not operational, then we have already marked it as dead
@@ -1188,7 +1216,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
mdname(mddev), conf->raid_disks - mddev->degraded);
}
-static void print_conf(conf_t *conf)
+static void print_conf(struct r1conf *conf)
{
int i;
@@ -1203,7 +1231,7 @@ static void print_conf(conf_t *conf)
rcu_read_lock();
for (i = 0; i < conf->raid_disks; i++) {
char b[BDEVNAME_SIZE];
- mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+ struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
if (rdev)
printk(KERN_DEBUG " disk %d, wo:%d, o:%d, dev:%s\n",
i, !test_bit(In_sync, &rdev->flags),
@@ -1213,7 +1241,7 @@ static void print_conf(conf_t *conf)
rcu_read_unlock();
}
-static void close_sync(conf_t *conf)
+static void close_sync(struct r1conf *conf)
{
wait_barrier(conf);
allow_barrier(conf);
@@ -1222,10 +1250,10 @@ static void close_sync(conf_t *conf)
conf->r1buf_pool = NULL;
}
-static int raid1_spare_active(mddev_t *mddev)
+static int raid1_spare_active(struct mddev *mddev)
{
int i;
- conf_t *conf = mddev->private;
+ struct r1conf *conf = mddev->private;
int count = 0;
unsigned long flags;
@@ -1235,7 +1263,7 @@ static int raid1_spare_active(mddev_t *mddev)
* Called under mddev lock, so rcu protection not needed.
*/
for (i = 0; i < conf->raid_disks; i++) {
- mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+ struct md_rdev *rdev = conf->mirrors[i].rdev;
if (rdev
&& !test_bit(Faulty, &rdev->flags)
&& !test_and_set_bit(In_sync, &rdev->flags)) {
@@ -1252,12 +1280,12 @@ static int raid1_spare_active(mddev_t *mddev)
}
-static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
{
- conf_t *conf = mddev->private;
+ struct r1conf *conf = mddev->private;
int err = -EEXIST;
int mirror = 0;
- mirror_info_t *p;
+ struct mirror_info *p;
int first = 0;
int last = mddev->raid_disks - 1;
@@ -1300,12 +1328,12 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
return err;
}
-static int raid1_remove_disk(mddev_t *mddev, int number)
+static int raid1_remove_disk(struct mddev *mddev, int number)
{
- conf_t *conf = mddev->private;
+ struct r1conf *conf = mddev->private;
int err = 0;
- mdk_rdev_t *rdev;
- mirror_info_t *p = conf->mirrors+ number;
+ struct md_rdev *rdev;
+ struct mirror_info *p = conf->mirrors+ number;
print_conf(conf);
rdev = p->rdev;
@@ -1343,14 +1371,10 @@ abort:
static void end_sync_read(struct bio *bio, int error)
{
- r1bio_t *r1_bio = bio->bi_private;
- int i;
+ struct r1bio *r1_bio = bio->bi_private;
+
+ update_head_pos(r1_bio->read_disk, r1_bio);
- for (i=r1_bio->mddev->raid_disks; i--; )
- if (r1_bio->bios[i] == bio)
- break;
- BUG_ON(i < 0);
- update_head_pos(i, r1_bio);
/*
* we have read a block, now it needs to be re-written,
* or re-read if the read failed.
@@ -1366,19 +1390,15 @@ static void end_sync_read(struct bio *bio, int error)
static void end_sync_write(struct bio *bio, int error)
{
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
- r1bio_t *r1_bio = bio->bi_private;
- mddev_t *mddev = r1_bio->mddev;
- conf_t *conf = mddev->private;
- int i;
+ struct r1bio *r1_bio = bio->bi_private;
+ struct mddev *mddev = r1_bio->mddev;
+ struct r1conf *conf = mddev->private;
int mirror=0;
sector_t first_bad;
int bad_sectors;
- for (i = 0; i < conf->raid_disks; i++)
- if (r1_bio->bios[i] == bio) {
- mirror = i;
- break;
- }
+ mirror = find_bio_disk(r1_bio, bio);
+
if (!uptodate) {
sector_t sync_blocks = 0;
sector_t s = r1_bio->sector;
@@ -1404,8 +1424,6 @@ static void end_sync_write(struct bio *bio, int error)
)
set_bit(R1BIO_MadeGood, &r1_bio->state);
- update_head_pos(mirror, r1_bio);
-
if (atomic_dec_and_test(&r1_bio->remaining)) {
int s = r1_bio->sectors;
if (test_bit(R1BIO_MadeGood, &r1_bio->state) ||
@@ -1418,7 +1436,7 @@ static void end_sync_write(struct bio *bio, int error)
}
}
-static int r1_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
+static int r1_sync_page_io(struct md_rdev *rdev, sector_t sector,
int sectors, struct page *page, int rw)
{
if (sync_page_io(rdev, sector, sectors << 9, page, rw, false))
@@ -1432,7 +1450,7 @@ static int r1_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
return 0;
}
-static int fix_sync_read_error(r1bio_t *r1_bio)
+static int fix_sync_read_error(struct r1bio *r1_bio)
{
/* Try some synchronous reads of other devices to get
* good data, much like with normal read errors. Only
@@ -1445,8 +1463,8 @@ static int fix_sync_read_error(r1bio_t *r1_bio)
* made sure that anything with a bad block in range
* will have bi_end_io clear.
*/
- mddev_t *mddev = r1_bio->mddev;
- conf_t *conf = mddev->private;
+ struct mddev *mddev = r1_bio->mddev;
+ struct r1conf *conf = mddev->private;
struct bio *bio = r1_bio->bios[r1_bio->read_disk];
sector_t sect = r1_bio->sector;
int sectors = r1_bio->sectors;
@@ -1456,7 +1474,7 @@ static int fix_sync_read_error(r1bio_t *r1_bio)
int s = sectors;
int d = r1_bio->read_disk;
int success = 0;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int start;
if (s > (PAGE_SIZE>>9))
@@ -1501,7 +1519,8 @@ static int fix_sync_read_error(r1bio_t *r1_bio)
abort = 1;
}
if (abort) {
- mddev->recovery_disabled = 1;
+ conf->recovery_disabled =
+ mddev->recovery_disabled;
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
md_done_sync(mddev, r1_bio->sectors, 0);
put_buf(r1_bio);
@@ -1552,7 +1571,7 @@ static int fix_sync_read_error(r1bio_t *r1_bio)
return 1;
}
-static int process_checks(r1bio_t *r1_bio)
+static int process_checks(struct r1bio *r1_bio)
{
/* We have read all readable devices. If we haven't
* got the block, then there is no hope left.
@@ -1561,8 +1580,8 @@ static int process_checks(r1bio_t *r1_bio)
* If any blocks failed to read, then we need to
* attempt an over-write
*/
- mddev_t *mddev = r1_bio->mddev;
- conf_t *conf = mddev->private;
+ struct mddev *mddev = r1_bio->mddev;
+ struct r1conf *conf = mddev->private;
int primary;
int i;
@@ -1634,9 +1653,9 @@ static int process_checks(r1bio_t *r1_bio)
return 0;
}
-static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
+static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
{
- conf_t *conf = mddev->private;
+ struct r1conf *conf = mddev->private;
int i;
int disks = conf->raid_disks;
struct bio *bio, *wbio;
@@ -1686,16 +1705,16 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
* 3. Performs writes following reads for array synchronising.
*/
-static void fix_read_error(conf_t *conf, int read_disk,
+static void fix_read_error(struct r1conf *conf, int read_disk,
sector_t sect, int sectors)
{
- mddev_t *mddev = conf->mddev;
+ struct mddev *mddev = conf->mddev;
while(sectors) {
int s = sectors;
int d = read_disk;
int success = 0;
int start;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (s > (PAGE_SIZE>>9))
s = PAGE_SIZE >> 9;
@@ -1726,7 +1745,7 @@ static void fix_read_error(conf_t *conf, int read_disk,
if (!success) {
/* Cannot read from anywhere - mark it bad */
- mdk_rdev_t *rdev = conf->mirrors[read_disk].rdev;
+ struct md_rdev *rdev = conf->mirrors[read_disk].rdev;
if (!rdev_set_badblocks(rdev, sect, s, 0))
md_error(mddev, rdev);
break;
@@ -1789,11 +1808,11 @@ static int submit_bio_wait(int rw, struct bio *bio)
return test_bit(BIO_UPTODATE, &bio->bi_flags);
}
-static int narrow_write_error(r1bio_t *r1_bio, int i)
+static int narrow_write_error(struct r1bio *r1_bio, int i)
{
- mddev_t *mddev = r1_bio->mddev;
- conf_t *conf = mddev->private;
- mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+ struct mddev *mddev = r1_bio->mddev;
+ struct r1conf *conf = mddev->private;
+ struct md_rdev *rdev = conf->mirrors[i].rdev;
int vcnt, idx;
struct bio_vec *vec;
@@ -1865,12 +1884,12 @@ static int narrow_write_error(r1bio_t *r1_bio, int i)
return ok;
}
-static void handle_sync_write_finished(conf_t *conf, r1bio_t *r1_bio)
+static void handle_sync_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
{
int m;
int s = r1_bio->sectors;
for (m = 0; m < conf->raid_disks ; m++) {
- mdk_rdev_t *rdev = conf->mirrors[m].rdev;
+ struct md_rdev *rdev = conf->mirrors[m].rdev;
struct bio *bio = r1_bio->bios[m];
if (bio->bi_end_io == NULL)
continue;
@@ -1888,12 +1907,12 @@ static void handle_sync_write_finished(conf_t *conf, r1bio_t *r1_bio)
md_done_sync(conf->mddev, s, 1);
}
-static void handle_write_finished(conf_t *conf, r1bio_t *r1_bio)
+static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
{
int m;
for (m = 0; m < conf->raid_disks ; m++)
if (r1_bio->bios[m] == IO_MADE_GOOD) {
- mdk_rdev_t *rdev = conf->mirrors[m].rdev;
+ struct md_rdev *rdev = conf->mirrors[m].rdev;
rdev_clear_badblocks(rdev,
r1_bio->sector,
r1_bio->sectors);
@@ -1917,14 +1936,14 @@ static void handle_write_finished(conf_t *conf, r1bio_t *r1_bio)
raid_end_bio_io(r1_bio);
}
-static void handle_read_error(conf_t *conf, r1bio_t *r1_bio)
+static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
{
int disk;
int max_sectors;
- mddev_t *mddev = conf->mddev;
+ struct mddev *mddev = conf->mddev;
struct bio *bio;
char b[BDEVNAME_SIZE];
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
clear_bit(R1BIO_ReadError, &r1_bio->state);
/* we got a read error. Maybe the drive is bad. Maybe just
@@ -2007,11 +2026,11 @@ read_more:
}
}
-static void raid1d(mddev_t *mddev)
+static void raid1d(struct mddev *mddev)
{
- r1bio_t *r1_bio;
+ struct r1bio *r1_bio;
unsigned long flags;
- conf_t *conf = mddev->private;
+ struct r1conf *conf = mddev->private;
struct list_head *head = &conf->retry_list;
struct blk_plug plug;
@@ -2028,7 +2047,7 @@ static void raid1d(mddev_t *mddev)
spin_unlock_irqrestore(&conf->device_lock, flags);
break;
}
- r1_bio = list_entry(head->prev, r1bio_t, retry_list);
+ r1_bio = list_entry(head->prev, struct r1bio, retry_list);
list_del(head->prev);
conf->nr_queued--;
spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -2060,7 +2079,7 @@ static void raid1d(mddev_t *mddev)
}
-static int init_resync(conf_t *conf)
+static int init_resync(struct r1conf *conf)
{
int buffs;
@@ -2084,10 +2103,10 @@ static int init_resync(conf_t *conf)
* that can be installed to exclude normal IO requests.
*/
-static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster)
{
- conf_t *conf = mddev->private;
- r1bio_t *r1_bio;
+ struct r1conf *conf = mddev->private;
+ struct r1bio *r1_bio;
struct bio *bio;
sector_t max_sector, nr_sectors;
int disk = -1;
@@ -2167,7 +2186,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
set_bit(R1BIO_IsSync, &r1_bio->state);
for (i=0; i < conf->raid_disks; i++) {
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
bio = r1_bio->bios[i];
/* take from bio_init */
@@ -2239,7 +2258,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
int ok = 1;
for (i = 0 ; i < conf->raid_disks ; i++)
if (r1_bio->bios[i]->bi_end_io == end_sync_write) {
- mdk_rdev_t *rdev =
+ struct md_rdev *rdev =
rcu_dereference(conf->mirrors[i].rdev);
ok = rdev_set_badblocks(rdev, sector_nr,
min_bad, 0
@@ -2356,7 +2375,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return nr_sectors;
}
-static sector_t raid1_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t raid1_size(struct mddev *mddev, sector_t sectors, int raid_disks)
{
if (sectors)
return sectors;
@@ -2364,15 +2383,15 @@ static sector_t raid1_size(mddev_t *mddev, sector_t sectors, int raid_disks)
return mddev->dev_sectors;
}
-static conf_t *setup_conf(mddev_t *mddev)
+static struct r1conf *setup_conf(struct mddev *mddev)
{
- conf_t *conf;
+ struct r1conf *conf;
int i;
- mirror_info_t *disk;
- mdk_rdev_t *rdev;
+ struct mirror_info *disk;
+ struct md_rdev *rdev;
int err = -ENOMEM;
- conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
+ conf = kzalloc(sizeof(struct r1conf), GFP_KERNEL);
if (!conf)
goto abort;
@@ -2417,6 +2436,8 @@ static conf_t *setup_conf(mddev_t *mddev)
init_waitqueue_head(&conf->wait_barrier);
bio_list_init(&conf->pending_bio_list);
+ conf->pending_count = 0;
+ conf->recovery_disabled = mddev->recovery_disabled - 1;
conf->last_used = -1;
for (i = 0; i < conf->raid_disks; i++) {
@@ -2465,11 +2486,11 @@ static conf_t *setup_conf(mddev_t *mddev)
return ERR_PTR(err);
}
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
{
- conf_t *conf;
+ struct r1conf *conf;
int i;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (mddev->level != 1) {
printk(KERN_ERR "md/raid1:%s: raid level not set to mirroring (%d)\n",
@@ -2545,9 +2566,9 @@ static int run(mddev_t *mddev)
return md_integrity_register(mddev);
}
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
{
- conf_t *conf = mddev->private;
+ struct r1conf *conf = mddev->private;
struct bitmap *bitmap = mddev->bitmap;
/* wait for behind writes to complete */
@@ -2572,7 +2593,7 @@ static int stop(mddev_t *mddev)
return 0;
}
-static int raid1_resize(mddev_t *mddev, sector_t sectors)
+static int raid1_resize(struct mddev *mddev, sector_t sectors)
{
/* no resync is happening, and there is enough space
* on all devices, so we can resize.
@@ -2596,7 +2617,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
return 0;
}
-static int raid1_reshape(mddev_t *mddev)
+static int raid1_reshape(struct mddev *mddev)
{
/* We need to:
* 1/ resize the r1bio_pool
@@ -2611,8 +2632,8 @@ static int raid1_reshape(mddev_t *mddev)
*/
mempool_t *newpool, *oldpool;
struct pool_info *newpoolinfo;
- mirror_info_t *newmirrors;
- conf_t *conf = mddev->private;
+ struct mirror_info *newmirrors;
+ struct r1conf *conf = mddev->private;
int cnt, raid_disks;
unsigned long flags;
int d, d2, err;
@@ -2668,7 +2689,7 @@ static int raid1_reshape(mddev_t *mddev)
conf->r1bio_pool = newpool;
for (d = d2 = 0; d < conf->raid_disks; d++) {
- mdk_rdev_t *rdev = conf->mirrors[d].rdev;
+ struct md_rdev *rdev = conf->mirrors[d].rdev;
if (rdev && rdev->raid_disk != d2) {
sysfs_unlink_rdev(mddev, rdev);
rdev->raid_disk = d2;
@@ -2702,9 +2723,9 @@ static int raid1_reshape(mddev_t *mddev)
return 0;
}
-static void raid1_quiesce(mddev_t *mddev, int state)
+static void raid1_quiesce(struct mddev *mddev, int state)
{
- conf_t *conf = mddev->private;
+ struct r1conf *conf = mddev->private;
switch(state) {
case 2: /* wake for suspend */
@@ -2719,13 +2740,13 @@ static void raid1_quiesce(mddev_t *mddev, int state)
}
}
-static void *raid1_takeover(mddev_t *mddev)
+static void *raid1_takeover(struct mddev *mddev)
{
/* raid1 can take over:
* raid5 with 2 devices, any layout or chunk size
*/
if (mddev->level == 5 && mddev->raid_disks == 2) {
- conf_t *conf;
+ struct r1conf *conf;
mddev->new_level = 1;
mddev->new_layout = 0;
mddev->new_chunk_sectors = 0;
@@ -2737,7 +2758,7 @@ static void *raid1_takeover(mddev_t *mddev)
return ERR_PTR(-EINVAL);
}
-static struct mdk_personality raid1_personality =
+static struct md_personality raid1_personality =
{
.name = "raid1",
.level = 1,
@@ -2775,3 +2796,5 @@ MODULE_DESCRIPTION("RAID1 (mirroring) personality for MD");
MODULE_ALIAS("md-personality-3"); /* RAID1 */
MODULE_ALIAS("md-raid1");
MODULE_ALIAS("md-level-1");
+
+module_param(max_queued_requests, int, S_IRUGO|S_IWUSR);
diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h
index e0d676b48974..c732b6cce935 100644
--- a/drivers/md/raid1.h
+++ b/drivers/md/raid1.h
@@ -1,10 +1,8 @@
#ifndef _RAID1_H
#define _RAID1_H
-typedef struct mirror_info mirror_info_t;
-
struct mirror_info {
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t head_position;
};
@@ -17,61 +15,82 @@ struct mirror_info {
*/
struct pool_info {
- mddev_t *mddev;
+ struct mddev *mddev;
int raid_disks;
};
-
-typedef struct r1bio_s r1bio_t;
-
-struct r1_private_data_s {
- mddev_t *mddev;
- mirror_info_t *mirrors;
+struct r1conf {
+ struct mddev *mddev;
+ struct mirror_info *mirrors;
int raid_disks;
+
+ /* When choose the best device for a read (read_balance())
+ * we try to keep sequential reads one the same device
+ * using 'last_used' and 'next_seq_sect'
+ */
int last_used;
sector_t next_seq_sect;
+ /* During resync, read_balancing is only allowed on the part
+ * of the array that has been resynced. 'next_resync' tells us
+ * where that is.
+ */
+ sector_t next_resync;
+
spinlock_t device_lock;
+ /* list of 'struct r1bio' that need to be processed by raid1d,
+ * whether to retry a read, writeout a resync or recovery
+ * block, or anything else.
+ */
struct list_head retry_list;
- /* queue pending writes and submit them on unplug */
- struct bio_list pending_bio_list;
- /* for use when syncing mirrors: */
+ /* queue pending writes to be submitted on unplug */
+ struct bio_list pending_bio_list;
+ int pending_count;
+ /* for use when syncing mirrors:
+ * We don't allow both normal IO and resync/recovery IO at
+ * the same time - resync/recovery can only happen when there
+ * is no other IO. So when either is active, the other has to wait.
+ * See more details description in raid1.c near raise_barrier().
+ */
+ wait_queue_head_t wait_barrier;
spinlock_t resync_lock;
int nr_pending;
int nr_waiting;
int nr_queued;
int barrier;
- sector_t next_resync;
- int fullsync; /* set to 1 if a full sync is needed,
- * (fresh device added).
- * Cleared when a sync completes.
- */
- int recovery_disabled; /* when the same as
- * mddev->recovery_disabled
- * we don't allow recovery
- * to be attempted as we
- * expect a read error
- */
- wait_queue_head_t wait_barrier;
+ /* Set to 1 if a full sync is needed, (fresh device added).
+ * Cleared when a sync completes.
+ */
+ int fullsync;
+ /* When the same as mddev->recovery_disabled we don't allow
+ * recovery to be attempted as we expect a read error.
+ */
+ int recovery_disabled;
+
+
+ /* poolinfo contains information about the content of the
+ * mempools - it changes when the array grows or shrinks
+ */
struct pool_info *poolinfo;
+ mempool_t *r1bio_pool;
+ mempool_t *r1buf_pool;
+ /* temporary buffer to synchronous IO when attempting to repair
+ * a read error.
+ */
struct page *tmppage;
- mempool_t *r1bio_pool;
- mempool_t *r1buf_pool;
/* When taking over an array from a different personality, we store
* the new thread here until we fully activate the array.
*/
- struct mdk_thread_s *thread;
+ struct md_thread *thread;
};
-typedef struct r1_private_data_s conf_t;
-
/*
* this is our 'private' RAID1 bio.
*
@@ -79,7 +98,7 @@ typedef struct r1_private_data_s conf_t;
* for this RAID1 operation, and about their status:
*/
-struct r1bio_s {
+struct r1bio {
atomic_t remaining; /* 'have we finished' count,
* used from IRQ handlers
*/
@@ -89,7 +108,7 @@ struct r1bio_s {
sector_t sector;
int sectors;
unsigned long state;
- mddev_t *mddev;
+ struct mddev *mddev;
/*
* original bio going to /dev/mdx
*/
@@ -148,6 +167,6 @@ struct r1bio_s {
#define R1BIO_MadeGood 7
#define R1BIO_WriteError 8
-extern int md_raid1_congested(mddev_t *mddev, int bits);
+extern int md_raid1_congested(struct mddev *mddev, int bits);
#endif
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 0cd9672cf9cb..c025a8276dc1 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -58,13 +58,19 @@
*/
#define NR_RAID10_BIOS 256
-static void allow_barrier(conf_t *conf);
-static void lower_barrier(conf_t *conf);
+/* When there are this many requests queue to be written by
+ * the raid10 thread, we become 'congested' to provide back-pressure
+ * for writeback.
+ */
+static int max_queued_requests = 1024;
+
+static void allow_barrier(struct r10conf *conf);
+static void lower_barrier(struct r10conf *conf);
static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
{
- conf_t *conf = data;
- int size = offsetof(struct r10bio_s, devs[conf->copies]);
+ struct r10conf *conf = data;
+ int size = offsetof(struct r10bio, devs[conf->copies]);
/* allocate a r10bio with room for raid_disks entries in the bios array */
return kzalloc(size, gfp_flags);
@@ -92,9 +98,9 @@ static void r10bio_pool_free(void *r10_bio, void *data)
*/
static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
{
- conf_t *conf = data;
+ struct r10conf *conf = data;
struct page *page;
- r10bio_t *r10_bio;
+ struct r10bio *r10_bio;
struct bio *bio;
int i, j;
int nalloc;
@@ -158,8 +164,8 @@ out_free_bio:
static void r10buf_pool_free(void *__r10_bio, void *data)
{
int i;
- conf_t *conf = data;
- r10bio_t *r10bio = __r10_bio;
+ struct r10conf *conf = data;
+ struct r10bio *r10bio = __r10_bio;
int j;
for (j=0; j < conf->copies; j++) {
@@ -175,7 +181,7 @@ static void r10buf_pool_free(void *__r10_bio, void *data)
r10bio_pool_free(r10bio, conf);
}
-static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
+static void put_all_bios(struct r10conf *conf, struct r10bio *r10_bio)
{
int i;
@@ -187,28 +193,28 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
}
}
-static void free_r10bio(r10bio_t *r10_bio)
+static void free_r10bio(struct r10bio *r10_bio)
{
- conf_t *conf = r10_bio->mddev->private;
+ struct r10conf *conf = r10_bio->mddev->private;
put_all_bios(conf, r10_bio);
mempool_free(r10_bio, conf->r10bio_pool);
}
-static void put_buf(r10bio_t *r10_bio)
+static void put_buf(struct r10bio *r10_bio)
{
- conf_t *conf = r10_bio->mddev->private;
+ struct r10conf *conf = r10_bio->mddev->private;
mempool_free(r10_bio, conf->r10buf_pool);
lower_barrier(conf);
}
-static void reschedule_retry(r10bio_t *r10_bio)
+static void reschedule_retry(struct r10bio *r10_bio)
{
unsigned long flags;
- mddev_t *mddev = r10_bio->mddev;
- conf_t *conf = mddev->private;
+ struct mddev *mddev = r10_bio->mddev;
+ struct r10conf *conf = mddev->private;
spin_lock_irqsave(&conf->device_lock, flags);
list_add(&r10_bio->retry_list, &conf->retry_list);
@@ -226,11 +232,11 @@ static void reschedule_retry(r10bio_t *r10_bio)
* operation and are ready to return a success/failure code to the buffer
* cache layer.
*/
-static void raid_end_bio_io(r10bio_t *r10_bio)
+static void raid_end_bio_io(struct r10bio *r10_bio)
{
struct bio *bio = r10_bio->master_bio;
int done;
- conf_t *conf = r10_bio->mddev->private;
+ struct r10conf *conf = r10_bio->mddev->private;
if (bio->bi_phys_segments) {
unsigned long flags;
@@ -256,9 +262,9 @@ static void raid_end_bio_io(r10bio_t *r10_bio)
/*
* Update disk head position estimator based on IRQ completion info.
*/
-static inline void update_head_pos(int slot, r10bio_t *r10_bio)
+static inline void update_head_pos(int slot, struct r10bio *r10_bio)
{
- conf_t *conf = r10_bio->mddev->private;
+ struct r10conf *conf = r10_bio->mddev->private;
conf->mirrors[r10_bio->devs[slot].devnum].head_position =
r10_bio->devs[slot].addr + (r10_bio->sectors);
@@ -267,7 +273,7 @@ static inline void update_head_pos(int slot, r10bio_t *r10_bio)
/*
* Find the disk number which triggered given bio
*/
-static int find_bio_disk(conf_t *conf, r10bio_t *r10_bio,
+static int find_bio_disk(struct r10conf *conf, struct r10bio *r10_bio,
struct bio *bio, int *slotp)
{
int slot;
@@ -287,9 +293,9 @@ static int find_bio_disk(conf_t *conf, r10bio_t *r10_bio,
static void raid10_end_read_request(struct bio *bio, int error)
{
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
- r10bio_t *r10_bio = bio->bi_private;
+ struct r10bio *r10_bio = bio->bi_private;
int slot, dev;
- conf_t *conf = r10_bio->mddev->private;
+ struct r10conf *conf = r10_bio->mddev->private;
slot = r10_bio->read_slot;
@@ -327,7 +333,7 @@ static void raid10_end_read_request(struct bio *bio, int error)
}
}
-static void close_write(r10bio_t *r10_bio)
+static void close_write(struct r10bio *r10_bio)
{
/* clear the bitmap if all writes complete successfully */
bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
@@ -337,7 +343,7 @@ static void close_write(r10bio_t *r10_bio)
md_write_end(r10_bio->mddev);
}
-static void one_write_done(r10bio_t *r10_bio)
+static void one_write_done(struct r10bio *r10_bio)
{
if (atomic_dec_and_test(&r10_bio->remaining)) {
if (test_bit(R10BIO_WriteError, &r10_bio->state))
@@ -355,10 +361,10 @@ static void one_write_done(r10bio_t *r10_bio)
static void raid10_end_write_request(struct bio *bio, int error)
{
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
- r10bio_t *r10_bio = bio->bi_private;
+ struct r10bio *r10_bio = bio->bi_private;
int dev;
int dec_rdev = 1;
- conf_t *conf = r10_bio->mddev->private;
+ struct r10conf *conf = r10_bio->mddev->private;
int slot;
dev = find_bio_disk(conf, r10_bio, bio, &slot);
@@ -433,7 +439,7 @@ static void raid10_end_write_request(struct bio *bio, int error)
* sector offset to a virtual address
*/
-static void raid10_find_phys(conf_t *conf, r10bio_t *r10bio)
+static void raid10_find_phys(struct r10conf *conf, struct r10bio *r10bio)
{
int n,f;
sector_t sector;
@@ -481,7 +487,7 @@ static void raid10_find_phys(conf_t *conf, r10bio_t *r10bio)
BUG_ON(slot != conf->copies);
}
-static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev)
+static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev)
{
sector_t offset, chunk, vchunk;
@@ -522,7 +528,7 @@ static int raid10_mergeable_bvec(struct request_queue *q,
struct bvec_merge_data *bvm,
struct bio_vec *biovec)
{
- mddev_t *mddev = q->queuedata;
+ struct mddev *mddev = q->queuedata;
sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
int max;
unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -555,14 +561,14 @@ static int raid10_mergeable_bvec(struct request_queue *q,
* FIXME: possibly should rethink readbalancing and do it differently
* depending on near_copies / far_copies geometry.
*/
-static int read_balance(conf_t *conf, r10bio_t *r10_bio, int *max_sectors)
+static int read_balance(struct r10conf *conf, struct r10bio *r10_bio, int *max_sectors)
{
const sector_t this_sector = r10_bio->sector;
int disk, slot;
int sectors = r10_bio->sectors;
int best_good_sectors;
sector_t new_distance, best_dist;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int do_balance;
int best_slot;
@@ -677,15 +683,19 @@ retry:
static int raid10_congested(void *data, int bits)
{
- mddev_t *mddev = data;
- conf_t *conf = mddev->private;
+ struct mddev *mddev = data;
+ struct r10conf *conf = mddev->private;
int i, ret = 0;
+ if ((bits & (1 << BDI_async_congested)) &&
+ conf->pending_count >= max_queued_requests)
+ return 1;
+
if (mddev_congested(mddev, bits))
return 1;
rcu_read_lock();
for (i = 0; i < conf->raid_disks && ret == 0; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+ struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
if (rdev && !test_bit(Faulty, &rdev->flags)) {
struct request_queue *q = bdev_get_queue(rdev->bdev);
@@ -696,7 +706,7 @@ static int raid10_congested(void *data, int bits)
return ret;
}
-static void flush_pending_writes(conf_t *conf)
+static void flush_pending_writes(struct r10conf *conf)
{
/* Any writes that have been queued but are awaiting
* bitmap updates get flushed here.
@@ -706,10 +716,12 @@ static void flush_pending_writes(conf_t *conf)
if (conf->pending_bio_list.head) {
struct bio *bio;
bio = bio_list_get(&conf->pending_bio_list);
+ conf->pending_count = 0;
spin_unlock_irq(&conf->device_lock);
/* flush any pending bitmap writes to disk
* before proceeding w/ I/O */
bitmap_unplug(conf->mddev->bitmap);
+ wake_up(&conf->wait_barrier);
while (bio) { /* submit pending writes */
struct bio *next = bio->bi_next;
@@ -743,7 +755,7 @@ static void flush_pending_writes(conf_t *conf)
* lower_barrier when the particular background IO completes.
*/
-static void raise_barrier(conf_t *conf, int force)
+static void raise_barrier(struct r10conf *conf, int force)
{
BUG_ON(force && !conf->barrier);
spin_lock_irq(&conf->resync_lock);
@@ -763,7 +775,7 @@ static void raise_barrier(conf_t *conf, int force)
spin_unlock_irq(&conf->resync_lock);
}
-static void lower_barrier(conf_t *conf)
+static void lower_barrier(struct r10conf *conf)
{
unsigned long flags;
spin_lock_irqsave(&conf->resync_lock, flags);
@@ -772,7 +784,7 @@ static void lower_barrier(conf_t *conf)
wake_up(&conf->wait_barrier);
}
-static void wait_barrier(conf_t *conf)
+static void wait_barrier(struct r10conf *conf)
{
spin_lock_irq(&conf->resync_lock);
if (conf->barrier) {
@@ -786,7 +798,7 @@ static void wait_barrier(conf_t *conf)
spin_unlock_irq(&conf->resync_lock);
}
-static void allow_barrier(conf_t *conf)
+static void allow_barrier(struct r10conf *conf)
{
unsigned long flags;
spin_lock_irqsave(&conf->resync_lock, flags);
@@ -795,7 +807,7 @@ static void allow_barrier(conf_t *conf)
wake_up(&conf->wait_barrier);
}
-static void freeze_array(conf_t *conf)
+static void freeze_array(struct r10conf *conf)
{
/* stop syncio and normal IO and wait for everything to
* go quiet.
@@ -820,7 +832,7 @@ static void freeze_array(conf_t *conf)
spin_unlock_irq(&conf->resync_lock);
}
-static void unfreeze_array(conf_t *conf)
+static void unfreeze_array(struct r10conf *conf)
{
/* reverse the effect of the freeze */
spin_lock_irq(&conf->resync_lock);
@@ -830,11 +842,11 @@ static void unfreeze_array(conf_t *conf)
spin_unlock_irq(&conf->resync_lock);
}
-static int make_request(mddev_t *mddev, struct bio * bio)
+static int make_request(struct mddev *mddev, struct bio * bio)
{
- conf_t *conf = mddev->private;
- mirror_info_t *mirror;
- r10bio_t *r10_bio;
+ struct r10conf *conf = mddev->private;
+ struct mirror_info *mirror;
+ struct r10bio *r10_bio;
struct bio *read_bio;
int i;
int chunk_sects = conf->chunk_mask + 1;
@@ -842,7 +854,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
unsigned long flags;
- mdk_rdev_t *blocked_rdev;
+ struct md_rdev *blocked_rdev;
int plugged;
int sectors_handled;
int max_sectors;
@@ -996,6 +1008,11 @@ read_again:
/*
* WRITE:
*/
+ if (conf->pending_count >= max_queued_requests) {
+ md_wakeup_thread(mddev->thread);
+ wait_event(conf->wait_barrier,
+ conf->pending_count < max_queued_requests);
+ }
/* first select target devices under rcu_lock and
* inc refcount on their rdev. Record them by setting
* bios[x] to bio
@@ -1017,7 +1034,7 @@ retry_write:
for (i = 0; i < conf->copies; i++) {
int d = r10_bio->devs[i].devnum;
- mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[d].rdev);
+ struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
atomic_inc(&rdev->nr_pending);
blocked_rdev = rdev;
@@ -1129,6 +1146,7 @@ retry_write:
atomic_inc(&r10_bio->remaining);
spin_lock_irqsave(&conf->device_lock, flags);
bio_list_add(&conf->pending_bio_list, mbio);
+ conf->pending_count++;
spin_unlock_irqrestore(&conf->device_lock, flags);
}
@@ -1161,9 +1179,9 @@ retry_write:
return 0;
}
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
{
- conf_t *conf = mddev->private;
+ struct r10conf *conf = mddev->private;
int i;
if (conf->near_copies < conf->raid_disks)
@@ -1190,7 +1208,7 @@ static void status(struct seq_file *seq, mddev_t *mddev)
* Don't consider the device numbered 'ignore'
* as we might be about to remove it.
*/
-static int enough(conf_t *conf, int ignore)
+static int enough(struct r10conf *conf, int ignore)
{
int first = 0;
@@ -1209,10 +1227,10 @@ static int enough(conf_t *conf, int ignore)
return 1;
}
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+static void error(struct mddev *mddev, struct md_rdev *rdev)
{
char b[BDEVNAME_SIZE];
- conf_t *conf = mddev->private;
+ struct r10conf *conf = mddev->private;
/*
* If it is not operational, then we have already marked it as dead
@@ -1246,10 +1264,10 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
mdname(mddev), conf->raid_disks - mddev->degraded);
}
-static void print_conf(conf_t *conf)
+static void print_conf(struct r10conf *conf)
{
int i;
- mirror_info_t *tmp;
+ struct mirror_info *tmp;
printk(KERN_DEBUG "RAID10 conf printout:\n");
if (!conf) {
@@ -1270,7 +1288,7 @@ static void print_conf(conf_t *conf)
}
}
-static void close_sync(conf_t *conf)
+static void close_sync(struct r10conf *conf)
{
wait_barrier(conf);
allow_barrier(conf);
@@ -1279,11 +1297,11 @@ static void close_sync(conf_t *conf)
conf->r10buf_pool = NULL;
}
-static int raid10_spare_active(mddev_t *mddev)
+static int raid10_spare_active(struct mddev *mddev)
{
int i;
- conf_t *conf = mddev->private;
- mirror_info_t *tmp;
+ struct r10conf *conf = mddev->private;
+ struct mirror_info *tmp;
int count = 0;
unsigned long flags;
@@ -1309,9 +1327,9 @@ static int raid10_spare_active(mddev_t *mddev)
}
-static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
{
- conf_t *conf = mddev->private;
+ struct r10conf *conf = mddev->private;
int err = -EEXIST;
int mirror;
int first = 0;
@@ -1334,10 +1352,10 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
else
mirror = first;
for ( ; mirror <= last ; mirror++) {
- mirror_info_t *p = &conf->mirrors[mirror];
+ struct mirror_info *p = &conf->mirrors[mirror];
if (p->recovery_disabled == mddev->recovery_disabled)
continue;
- if (!p->rdev)
+ if (p->rdev)
continue;
disk_stack_limits(mddev->gendisk, rdev->bdev,
@@ -1355,6 +1373,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
}
p->head_position = 0;
+ p->recovery_disabled = mddev->recovery_disabled - 1;
rdev->raid_disk = mirror;
err = 0;
if (rdev->saved_raid_disk != mirror)
@@ -1368,12 +1387,12 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
return err;
}
-static int raid10_remove_disk(mddev_t *mddev, int number)
+static int raid10_remove_disk(struct mddev *mddev, int number)
{
- conf_t *conf = mddev->private;
+ struct r10conf *conf = mddev->private;
int err = 0;
- mdk_rdev_t *rdev;
- mirror_info_t *p = conf->mirrors+ number;
+ struct md_rdev *rdev;
+ struct mirror_info *p = conf->mirrors+ number;
print_conf(conf);
rdev = p->rdev;
@@ -1411,8 +1430,8 @@ abort:
static void end_sync_read(struct bio *bio, int error)
{
- r10bio_t *r10_bio = bio->bi_private;
- conf_t *conf = r10_bio->mddev->private;
+ struct r10bio *r10_bio = bio->bi_private;
+ struct r10conf *conf = r10_bio->mddev->private;
int d;
d = find_bio_disk(conf, r10_bio, bio, NULL);
@@ -1439,9 +1458,9 @@ static void end_sync_read(struct bio *bio, int error)
}
}
-static void end_sync_request(r10bio_t *r10_bio)
+static void end_sync_request(struct r10bio *r10_bio)
{
- mddev_t *mddev = r10_bio->mddev;
+ struct mddev *mddev = r10_bio->mddev;
while (atomic_dec_and_test(&r10_bio->remaining)) {
if (r10_bio->master_bio == NULL) {
@@ -1455,7 +1474,7 @@ static void end_sync_request(r10bio_t *r10_bio)
md_done_sync(mddev, s, 1);
break;
} else {
- r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio;
+ struct r10bio *r10_bio2 = (struct r10bio *)r10_bio->master_bio;
if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
test_bit(R10BIO_WriteError, &r10_bio->state))
reschedule_retry(r10_bio);
@@ -1469,9 +1488,9 @@ static void end_sync_request(r10bio_t *r10_bio)
static void end_sync_write(struct bio *bio, int error)
{
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
- r10bio_t *r10_bio = bio->bi_private;
- mddev_t *mddev = r10_bio->mddev;
- conf_t *conf = mddev->private;
+ struct r10bio *r10_bio = bio->bi_private;
+ struct mddev *mddev = r10_bio->mddev;
+ struct r10conf *conf = mddev->private;
int d;
sector_t first_bad;
int bad_sectors;
@@ -1509,9 +1528,9 @@ static void end_sync_write(struct bio *bio, int error)
* We check if all blocks are in-sync and only write to blocks that
* aren't in sync
*/
-static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
+static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
{
- conf_t *conf = mddev->private;
+ struct r10conf *conf = mddev->private;
int i, first;
struct bio *tbio, *fbio;
@@ -1609,7 +1628,7 @@ done:
* The second for writing.
*
*/
-static void fix_recovery_read_error(r10bio_t *r10_bio)
+static void fix_recovery_read_error(struct r10bio *r10_bio)
{
/* We got a read error during recovery.
* We repeat the read in smaller page-sized sections.
@@ -1618,8 +1637,8 @@ static void fix_recovery_read_error(r10bio_t *r10_bio)
* If a read fails, record a bad block on both old and
* new devices.
*/
- mddev_t *mddev = r10_bio->mddev;
- conf_t *conf = mddev->private;
+ struct mddev *mddev = r10_bio->mddev;
+ struct r10conf *conf = mddev->private;
struct bio *bio = r10_bio->devs[0].bio;
sector_t sect = 0;
int sectors = r10_bio->sectors;
@@ -1629,7 +1648,7 @@ static void fix_recovery_read_error(r10bio_t *r10_bio)
while (sectors) {
int s = sectors;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t addr;
int ok;
@@ -1663,7 +1682,7 @@ static void fix_recovery_read_error(r10bio_t *r10_bio)
if (rdev != conf->mirrors[dw].rdev) {
/* need bad block on destination too */
- mdk_rdev_t *rdev2 = conf->mirrors[dw].rdev;
+ struct md_rdev *rdev2 = conf->mirrors[dw].rdev;
addr = r10_bio->devs[1].addr + sect;
ok = rdev_set_badblocks(rdev2, addr, s, 0);
if (!ok) {
@@ -1688,9 +1707,9 @@ static void fix_recovery_read_error(r10bio_t *r10_bio)
}
}
-static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
+static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
{
- conf_t *conf = mddev->private;
+ struct r10conf *conf = mddev->private;
int d;
struct bio *wbio;
@@ -1719,7 +1738,7 @@ static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
* since the last recorded read error.
*
*/
-static void check_decay_read_errors(mddev_t *mddev, mdk_rdev_t *rdev)
+static void check_decay_read_errors(struct mddev *mddev, struct md_rdev *rdev)
{
struct timespec cur_time_mon;
unsigned long hours_since_last;
@@ -1750,7 +1769,7 @@ static void check_decay_read_errors(mddev_t *mddev, mdk_rdev_t *rdev)
atomic_set(&rdev->read_errors, read_errors >> hours_since_last);
}
-static int r10_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
+static int r10_sync_page_io(struct md_rdev *rdev, sector_t sector,
int sectors, struct page *page, int rw)
{
sector_t first_bad;
@@ -1778,11 +1797,11 @@ static int r10_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
* 3. Performs writes following reads for array synchronising.
*/
-static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
+static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10bio *r10_bio)
{
int sect = 0; /* Offset from r10_bio->sector */
int sectors = r10_bio->sectors;
- mdk_rdev_t*rdev;
+ struct md_rdev*rdev;
int max_read_errors = atomic_read(&mddev->max_corr_read_errors);
int d = r10_bio->devs[r10_bio->read_slot].devnum;
@@ -1983,12 +2002,12 @@ static int submit_bio_wait(int rw, struct bio *bio)
return test_bit(BIO_UPTODATE, &bio->bi_flags);
}
-static int narrow_write_error(r10bio_t *r10_bio, int i)
+static int narrow_write_error(struct r10bio *r10_bio, int i)
{
struct bio *bio = r10_bio->master_bio;
- mddev_t *mddev = r10_bio->mddev;
- conf_t *conf = mddev->private;
- mdk_rdev_t *rdev = conf->mirrors[r10_bio->devs[i].devnum].rdev;
+ struct mddev *mddev = r10_bio->mddev;
+ struct r10conf *conf = mddev->private;
+ struct md_rdev *rdev = conf->mirrors[r10_bio->devs[i].devnum].rdev;
/* bio has the data to be written to slot 'i' where
* we just recently had a write error.
* We repeatedly clone the bio and trim down to one block,
@@ -2040,13 +2059,13 @@ static int narrow_write_error(r10bio_t *r10_bio, int i)
return ok;
}
-static void handle_read_error(mddev_t *mddev, r10bio_t *r10_bio)
+static void handle_read_error(struct mddev *mddev, struct r10bio *r10_bio)
{
int slot = r10_bio->read_slot;
int mirror = r10_bio->devs[slot].devnum;
struct bio *bio;
- conf_t *conf = mddev->private;
- mdk_rdev_t *rdev;
+ struct r10conf *conf = mddev->private;
+ struct md_rdev *rdev;
char b[BDEVNAME_SIZE];
unsigned long do_sync;
int max_sectors;
@@ -2139,7 +2158,7 @@ read_more:
generic_make_request(bio);
}
-static void handle_write_completed(conf_t *conf, r10bio_t *r10_bio)
+static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
{
/* Some sort of write request has finished and it
* succeeded in writing where we thought there was a
@@ -2148,7 +2167,7 @@ static void handle_write_completed(conf_t *conf, r10bio_t *r10_bio)
* a bad block.
*/
int m;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (test_bit(R10BIO_IsSync, &r10_bio->state) ||
test_bit(R10BIO_IsRecover, &r10_bio->state)) {
@@ -2200,11 +2219,11 @@ static void handle_write_completed(conf_t *conf, r10bio_t *r10_bio)
}
}
-static void raid10d(mddev_t *mddev)
+static void raid10d(struct mddev *mddev)
{
- r10bio_t *r10_bio;
+ struct r10bio *r10_bio;
unsigned long flags;
- conf_t *conf = mddev->private;
+ struct r10conf *conf = mddev->private;
struct list_head *head = &conf->retry_list;
struct blk_plug plug;
@@ -2220,7 +2239,7 @@ static void raid10d(mddev_t *mddev)
spin_unlock_irqrestore(&conf->device_lock, flags);
break;
}
- r10_bio = list_entry(head->prev, r10bio_t, retry_list);
+ r10_bio = list_entry(head->prev, struct r10bio, retry_list);
list_del(head->prev);
conf->nr_queued--;
spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -2252,7 +2271,7 @@ static void raid10d(mddev_t *mddev)
}
-static int init_resync(conf_t *conf)
+static int init_resync(struct r10conf *conf)
{
int buffs;
@@ -2297,11 +2316,11 @@ static int init_resync(conf_t *conf)
*
*/
-static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
+static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
int *skipped, int go_faster)
{
- conf_t *conf = mddev->private;
- r10bio_t *r10_bio;
+ struct r10conf *conf = mddev->private;
+ struct r10bio *r10_bio;
struct bio *biolist = NULL, *bio;
sector_t max_sector, nr_sectors;
int i;
@@ -2393,7 +2412,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
for (i=0 ; i<conf->raid_disks; i++) {
int still_degraded;
- r10bio_t *rb2;
+ struct r10bio *rb2;
sector_t sect;
int must_sync;
int any_working;
@@ -2453,7 +2472,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
int k;
int d = r10_bio->devs[j].devnum;
sector_t from_addr, to_addr;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t sector, first_bad;
int bad_sectors;
if (!conf->mirrors[d].rdev ||
@@ -2547,8 +2566,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
}
if (biolist == NULL) {
while (r10_bio) {
- r10bio_t *rb2 = r10_bio;
- r10_bio = (r10bio_t*) rb2->master_bio;
+ struct r10bio *rb2 = r10_bio;
+ r10_bio = (struct r10bio*) rb2->master_bio;
rb2->master_bio = NULL;
put_buf(rb2);
}
@@ -2714,10 +2733,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
}
static sector_t
-raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+raid10_size(struct mddev *mddev, sector_t sectors, int raid_disks)
{
sector_t size;
- conf_t *conf = mddev->private;
+ struct r10conf *conf = mddev->private;
if (!raid_disks)
raid_disks = conf->raid_disks;
@@ -2733,9 +2752,9 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
}
-static conf_t *setup_conf(mddev_t *mddev)
+static struct r10conf *setup_conf(struct mddev *mddev)
{
- conf_t *conf = NULL;
+ struct r10conf *conf = NULL;
int nc, fc, fo;
sector_t stride, size;
int err = -EINVAL;
@@ -2760,7 +2779,7 @@ static conf_t *setup_conf(mddev_t *mddev)
}
err = -ENOMEM;
- conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
+ conf = kzalloc(sizeof(struct r10conf), GFP_KERNEL);
if (!conf)
goto out;
@@ -2836,12 +2855,12 @@ static conf_t *setup_conf(mddev_t *mddev)
return ERR_PTR(err);
}
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
{
- conf_t *conf;
+ struct r10conf *conf;
int i, disk_idx, chunk_size;
- mirror_info_t *disk;
- mdk_rdev_t *rdev;
+ struct mirror_info *disk;
+ struct md_rdev *rdev;
sector_t size;
/*
@@ -2913,6 +2932,7 @@ static int run(mddev_t *mddev)
if (disk->rdev)
conf->fullsync = 1;
}
+ disk->recovery_disabled = mddev->recovery_disabled - 1;
}
if (mddev->recovery_cp != MaxSector)
@@ -2966,9 +2986,9 @@ out:
return -EIO;
}
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
{
- conf_t *conf = mddev->private;
+ struct r10conf *conf = mddev->private;
raise_barrier(conf, 0);
lower_barrier(conf);
@@ -2983,9 +3003,9 @@ static int stop(mddev_t *mddev)
return 0;
}
-static void raid10_quiesce(mddev_t *mddev, int state)
+static void raid10_quiesce(struct mddev *mddev, int state)
{
- conf_t *conf = mddev->private;
+ struct r10conf *conf = mddev->private;
switch(state) {
case 1:
@@ -2997,10 +3017,10 @@ static void raid10_quiesce(mddev_t *mddev, int state)
}
}
-static void *raid10_takeover_raid0(mddev_t *mddev)
+static void *raid10_takeover_raid0(struct mddev *mddev)
{
- mdk_rdev_t *rdev;
- conf_t *conf;
+ struct md_rdev *rdev;
+ struct r10conf *conf;
if (mddev->degraded > 0) {
printk(KERN_ERR "md/raid10:%s: Error: degraded raid0!\n",
@@ -3029,17 +3049,17 @@ static void *raid10_takeover_raid0(mddev_t *mddev)
return conf;
}
-static void *raid10_takeover(mddev_t *mddev)
+static void *raid10_takeover(struct mddev *mddev)
{
- struct raid0_private_data *raid0_priv;
+ struct r0conf *raid0_conf;
/* raid10 can take over:
* raid0 - providing it has only two drives
*/
if (mddev->level == 0) {
/* for raid0 takeover only one zone is supported */
- raid0_priv = mddev->private;
- if (raid0_priv->nr_strip_zones > 1) {
+ raid0_conf = mddev->private;
+ if (raid0_conf->nr_strip_zones > 1) {
printk(KERN_ERR "md/raid10:%s: cannot takeover raid 0"
" with more than one zone.\n",
mdname(mddev));
@@ -3050,7 +3070,7 @@ static void *raid10_takeover(mddev_t *mddev)
return ERR_PTR(-EINVAL);
}
-static struct mdk_personality raid10_personality =
+static struct md_personality raid10_personality =
{
.name = "raid10",
.level = 10,
@@ -3086,3 +3106,5 @@ MODULE_DESCRIPTION("RAID10 (striped mirror) personality for MD");
MODULE_ALIAS("md-personality-9"); /* RAID10 */
MODULE_ALIAS("md-raid10");
MODULE_ALIAS("md-level-10");
+
+module_param(max_queued_requests, int, S_IRUGO|S_IWUSR);
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
index 79cb52a0d4a2..7facfdf841f4 100644
--- a/drivers/md/raid10.h
+++ b/drivers/md/raid10.h
@@ -1,10 +1,8 @@
#ifndef _RAID10_H
#define _RAID10_H
-typedef struct mirror_info mirror_info_t;
-
struct mirror_info {
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t head_position;
int recovery_disabled; /* matches
* mddev->recovery_disabled
@@ -13,11 +11,9 @@ struct mirror_info {
*/
};
-typedef struct r10bio_s r10bio_t;
-
-struct r10_private_data_s {
- mddev_t *mddev;
- mirror_info_t *mirrors;
+struct r10conf {
+ struct mddev *mddev;
+ struct mirror_info *mirrors;
int raid_disks;
spinlock_t device_lock;
@@ -46,7 +42,7 @@ struct r10_private_data_s {
struct list_head retry_list;
/* queue pending writes and submit them on unplug */
struct bio_list pending_bio_list;
-
+ int pending_count;
spinlock_t resync_lock;
int nr_pending;
@@ -68,11 +64,9 @@ struct r10_private_data_s {
/* When taking over an array from a different personality, we store
* the new thread here until we fully activate the array.
*/
- struct mdk_thread_s *thread;
+ struct md_thread *thread;
};
-typedef struct r10_private_data_s conf_t;
-
/*
* this is our 'private' RAID10 bio.
*
@@ -80,14 +74,14 @@ typedef struct r10_private_data_s conf_t;
* for this RAID10 operation, and about their status:
*/
-struct r10bio_s {
+struct r10bio {
atomic_t remaining; /* 'have we finished' count,
* used from IRQ handlers
*/
sector_t sector; /* virtual sector number */
int sectors;
unsigned long state;
- mddev_t *mddev;
+ struct mddev *mddev;
/*
* original bio going to /dev/mdx
*/
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index ac5e8b57e50f..f6fe053a5bed 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -70,7 +70,11 @@
#define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head))
#define HASH_MASK (NR_HASH - 1)
-#define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]))
+static inline struct hlist_head *stripe_hash(struct r5conf *conf, sector_t sect)
+{
+ int hash = (sect >> STRIPE_SHIFT) & HASH_MASK;
+ return &conf->stripe_hashtbl[hash];
+}
/* bio's attached to a stripe+device for I/O are linked together in bi_sector
* order without overlap. There may be several bio's per stripe+device, and
@@ -78,24 +82,17 @@
* When walking this list for a particular stripe+device, we must never proceed
* beyond a bio that extends past this device, as the next bio might no longer
* be valid.
- * This macro is used to determine the 'next' bio in the list, given the sector
+ * This function is used to determine the 'next' bio in the list, given the sector
* of the current stripe+device
*/
-#define r5_next_bio(bio, sect) ( ( (bio)->bi_sector + ((bio)->bi_size>>9) < sect + STRIPE_SECTORS) ? (bio)->bi_next : NULL)
-/*
- * The following can be used to debug the driver
- */
-#define RAID5_PARANOIA 1
-#if RAID5_PARANOIA && defined(CONFIG_SMP)
-# define CHECK_DEVLOCK() assert_spin_locked(&conf->device_lock)
-#else
-# define CHECK_DEVLOCK()
-#endif
-
-#ifdef DEBUG
-#define inline
-#define __inline__
-#endif
+static inline struct bio *r5_next_bio(struct bio *bio, sector_t sector)
+{
+ int sectors = bio->bi_size >> 9;
+ if (bio->bi_sector + sectors < sector + STRIPE_SECTORS)
+ return bio->bi_next;
+ else
+ return NULL;
+}
/*
* We maintain a biased count of active stripes in the bottom 16 bits of
@@ -183,7 +180,7 @@ static void return_io(struct bio *return_bi)
}
}
-static void print_raid5_conf (raid5_conf_t *conf);
+static void print_raid5_conf (struct r5conf *conf);
static int stripe_operations_active(struct stripe_head *sh)
{
@@ -192,7 +189,7 @@ static int stripe_operations_active(struct stripe_head *sh)
test_bit(STRIPE_COMPUTE_RUN, &sh->state);
}
-static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
+static void __release_stripe(struct r5conf *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count)) {
BUG_ON(!list_empty(&sh->lru));
@@ -228,7 +225,7 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
static void release_stripe(struct stripe_head *sh)
{
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
unsigned long flags;
spin_lock_irqsave(&conf->device_lock, flags);
@@ -244,25 +241,23 @@ static inline void remove_hash(struct stripe_head *sh)
hlist_del_init(&sh->hash);
}
-static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
+static inline void insert_hash(struct r5conf *conf, struct stripe_head *sh)
{
struct hlist_head *hp = stripe_hash(conf, sh->sector);
pr_debug("insert_hash(), stripe %llu\n",
(unsigned long long)sh->sector);
- CHECK_DEVLOCK();
hlist_add_head(&sh->hash, hp);
}
/* find an idle stripe, make sure it is unhashed, and return it. */
-static struct stripe_head *get_free_stripe(raid5_conf_t *conf)
+static struct stripe_head *get_free_stripe(struct r5conf *conf)
{
struct stripe_head *sh = NULL;
struct list_head *first;
- CHECK_DEVLOCK();
if (list_empty(&conf->inactive_list))
goto out;
first = conf->inactive_list.next;
@@ -306,19 +301,18 @@ static int grow_buffers(struct stripe_head *sh)
}
static void raid5_build_block(struct stripe_head *sh, int i, int previous);
-static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous,
+static void stripe_set_idx(sector_t stripe, struct r5conf *conf, int previous,
struct stripe_head *sh);
static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
{
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int i;
BUG_ON(atomic_read(&sh->count) != 0);
BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
BUG_ON(stripe_operations_active(sh));
- CHECK_DEVLOCK();
pr_debug("init_stripe called, stripe %llu\n",
(unsigned long long)sh->sector);
@@ -348,13 +342,12 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
insert_hash(conf, sh);
}
-static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector,
+static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
short generation)
{
struct stripe_head *sh;
struct hlist_node *hn;
- CHECK_DEVLOCK();
pr_debug("__find_stripe, sector %llu\n", (unsigned long long)sector);
hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
if (sh->sector == sector && sh->generation == generation)
@@ -376,7 +369,7 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector,
* of the two sections, and some non-in_sync devices may
* be insync in the section most affected by failed devices.
*/
-static int has_failed(raid5_conf_t *conf)
+static int has_failed(struct r5conf *conf)
{
int degraded;
int i;
@@ -386,7 +379,7 @@ static int has_failed(raid5_conf_t *conf)
rcu_read_lock();
degraded = 0;
for (i = 0; i < conf->previous_raid_disks; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+ struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
if (!rdev || test_bit(Faulty, &rdev->flags))
degraded++;
else if (test_bit(In_sync, &rdev->flags))
@@ -410,7 +403,7 @@ static int has_failed(raid5_conf_t *conf)
rcu_read_lock();
degraded = 0;
for (i = 0; i < conf->raid_disks; i++) {
- mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+ struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
if (!rdev || test_bit(Faulty, &rdev->flags))
degraded++;
else if (test_bit(In_sync, &rdev->flags))
@@ -431,7 +424,7 @@ static int has_failed(raid5_conf_t *conf)
}
static struct stripe_head *
-get_active_stripe(raid5_conf_t *conf, sector_t sector,
+get_active_stripe(struct r5conf *conf, sector_t sector,
int previous, int noblock, int noquiesce)
{
struct stripe_head *sh;
@@ -491,7 +484,7 @@ raid5_end_write_request(struct bio *bi, int error);
static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
{
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int i, disks = sh->disks;
might_sleep();
@@ -499,7 +492,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
for (i = disks; i--; ) {
int rw;
struct bio *bi;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) {
if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags))
rw = WRITE_FUA;
@@ -650,7 +643,7 @@ static void ops_complete_biofill(void *stripe_head_ref)
{
struct stripe_head *sh = stripe_head_ref;
struct bio *return_bi = NULL;
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int i;
pr_debug("%s: stripe %llu\n", __func__,
@@ -695,7 +688,7 @@ static void ops_complete_biofill(void *stripe_head_ref)
static void ops_run_biofill(struct stripe_head *sh)
{
struct dma_async_tx_descriptor *tx = NULL;
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
struct async_submit_ctl submit;
int i;
@@ -1246,7 +1239,7 @@ static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
{
int overlap_clear = 0, i, disks = sh->disks;
struct dma_async_tx_descriptor *tx = NULL;
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int level = conf->level;
struct raid5_percpu *percpu;
unsigned long cpu;
@@ -1337,7 +1330,7 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
#define raid_run_ops __raid_run_ops
#endif
-static int grow_one_stripe(raid5_conf_t *conf)
+static int grow_one_stripe(struct r5conf *conf)
{
struct stripe_head *sh;
sh = kmem_cache_zalloc(conf->slab_cache, GFP_KERNEL);
@@ -1362,7 +1355,7 @@ static int grow_one_stripe(raid5_conf_t *conf)
return 1;
}
-static int grow_stripes(raid5_conf_t *conf, int num)
+static int grow_stripes(struct r5conf *conf, int num)
{
struct kmem_cache *sc;
int devs = max(conf->raid_disks, conf->previous_raid_disks);
@@ -1411,7 +1404,7 @@ static size_t scribble_len(int num)
return len;
}
-static int resize_stripes(raid5_conf_t *conf, int newsize)
+static int resize_stripes(struct r5conf *conf, int newsize)
{
/* Make all the stripes able to hold 'newsize' devices.
* New slots in each stripe get 'page' set to a new page.
@@ -1556,7 +1549,7 @@ static int resize_stripes(raid5_conf_t *conf, int newsize)
return err;
}
-static int drop_one_stripe(raid5_conf_t *conf)
+static int drop_one_stripe(struct r5conf *conf)
{
struct stripe_head *sh;
@@ -1572,7 +1565,7 @@ static int drop_one_stripe(raid5_conf_t *conf)
return 1;
}
-static void shrink_stripes(raid5_conf_t *conf)
+static void shrink_stripes(struct r5conf *conf)
{
while (drop_one_stripe(conf))
;
@@ -1585,11 +1578,11 @@ static void shrink_stripes(raid5_conf_t *conf)
static void raid5_end_read_request(struct bio * bi, int error)
{
struct stripe_head *sh = bi->bi_private;
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int disks = sh->disks, i;
int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
char b[BDEVNAME_SIZE];
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
for (i=0 ; i<disks; i++)
@@ -1672,7 +1665,7 @@ static void raid5_end_read_request(struct bio * bi, int error)
static void raid5_end_write_request(struct bio *bi, int error)
{
struct stripe_head *sh = bi->bi_private;
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int disks = sh->disks, i;
int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
sector_t first_bad;
@@ -1726,10 +1719,10 @@ static void raid5_build_block(struct stripe_head *sh, int i, int previous)
dev->sector = compute_blocknr(sh, i, previous);
}
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+static void error(struct mddev *mddev, struct md_rdev *rdev)
{
char b[BDEVNAME_SIZE];
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
pr_debug("raid456: error called\n");
if (test_and_clear_bit(In_sync, &rdev->flags)) {
@@ -1758,7 +1751,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
* Input: a 'big' sector number,
* Output: index of the data and parity disk, and the sector # in them.
*/
-static sector_t raid5_compute_sector(raid5_conf_t *conf, sector_t r_sector,
+static sector_t raid5_compute_sector(struct r5conf *conf, sector_t r_sector,
int previous, int *dd_idx,
struct stripe_head *sh)
{
@@ -1963,7 +1956,7 @@ static sector_t raid5_compute_sector(raid5_conf_t *conf, sector_t r_sector,
static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous)
{
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int raid_disks = sh->disks;
int data_disks = raid_disks - conf->max_degraded;
sector_t new_sector = sh->sector, check;
@@ -2088,7 +2081,7 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
int rcw, int expand)
{
int i, pd_idx = sh->pd_idx, disks = sh->disks;
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int level = conf->level;
if (rcw) {
@@ -2173,7 +2166,7 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
{
struct bio **bip;
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int firstwrite=0;
pr_debug("adding bi b#%llu to stripe s#%llu\n",
@@ -2235,9 +2228,9 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
return 0;
}
-static void end_reshape(raid5_conf_t *conf);
+static void end_reshape(struct r5conf *conf);
-static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous,
+static void stripe_set_idx(sector_t stripe, struct r5conf *conf, int previous,
struct stripe_head *sh)
{
int sectors_per_chunk =
@@ -2254,7 +2247,7 @@ static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous,
}
static void
-handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
+handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
struct stripe_head_state *s, int disks,
struct bio **return_bi)
{
@@ -2264,7 +2257,7 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
int bitmap_end = 0;
if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
rcu_read_lock();
rdev = rcu_dereference(conf->disks[i].rdev);
if (rdev && test_bit(In_sync, &rdev->flags))
@@ -2359,7 +2352,7 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
}
static void
-handle_failed_sync(raid5_conf_t *conf, struct stripe_head *sh,
+handle_failed_sync(struct r5conf *conf, struct stripe_head *sh,
struct stripe_head_state *s)
{
int abort = 0;
@@ -2378,7 +2371,7 @@ handle_failed_sync(raid5_conf_t *conf, struct stripe_head *sh,
* refcounting of rdevs is not needed
*/
for (i = 0; i < conf->raid_disks; i++) {
- mdk_rdev_t *rdev = conf->disks[i].rdev;
+ struct md_rdev *rdev = conf->disks[i].rdev;
if (!rdev
|| test_bit(Faulty, &rdev->flags)
|| test_bit(In_sync, &rdev->flags))
@@ -2508,7 +2501,7 @@ static void handle_stripe_fill(struct stripe_head *sh,
* Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
* never LOCKED, so we don't need to test 'failed' directly.
*/
-static void handle_stripe_clean_event(raid5_conf_t *conf,
+static void handle_stripe_clean_event(struct r5conf *conf,
struct stripe_head *sh, int disks, struct bio **return_bi)
{
int i;
@@ -2553,7 +2546,7 @@ static void handle_stripe_clean_event(raid5_conf_t *conf,
md_wakeup_thread(conf->mddev->thread);
}
-static void handle_stripe_dirtying(raid5_conf_t *conf,
+static void handle_stripe_dirtying(struct r5conf *conf,
struct stripe_head *sh,
struct stripe_head_state *s,
int disks)
@@ -2655,7 +2648,7 @@ static void handle_stripe_dirtying(raid5_conf_t *conf,
schedule_reconstruction(sh, s, rcw == 0, 0);
}
-static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
+static void handle_parity_checks5(struct r5conf *conf, struct stripe_head *sh,
struct stripe_head_state *s, int disks)
{
struct r5dev *dev = NULL;
@@ -2743,7 +2736,7 @@ static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
}
-static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
+static void handle_parity_checks6(struct r5conf *conf, struct stripe_head *sh,
struct stripe_head_state *s,
int disks)
{
@@ -2906,7 +2899,7 @@ static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
}
}
-static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh)
+static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh)
{
int i;
@@ -2985,7 +2978,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh)
static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
{
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int disks = sh->disks;
struct r5dev *dev;
int i;
@@ -3002,7 +2995,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
rcu_read_lock();
spin_lock_irq(&conf->device_lock);
for (i=disks; i--; ) {
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t first_bad;
int bad_sectors;
int is_bad = 0;
@@ -3069,7 +3062,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
}
} else if (test_bit(In_sync, &rdev->flags))
set_bit(R5_Insync, &dev->flags);
- else {
+ else if (!test_bit(Faulty, &rdev->flags)) {
/* in sync if before recovery_offset */
if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
set_bit(R5_Insync, &dev->flags);
@@ -3109,7 +3102,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
static void handle_stripe(struct stripe_head *sh)
{
struct stripe_head_state s;
- raid5_conf_t *conf = sh->raid_conf;
+ struct r5conf *conf = sh->raid_conf;
int i;
int prexor;
int disks = sh->disks;
@@ -3341,7 +3334,7 @@ finish:
if (s.handle_bad_blocks)
for (i = disks; i--; ) {
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
struct r5dev *dev = &sh->dev[i];
if (test_and_clear_bit(R5_WriteError, &dev->flags)) {
/* We own a safe reference to the rdev */
@@ -3380,7 +3373,7 @@ finish:
clear_bit(STRIPE_ACTIVE, &sh->state);
}
-static void raid5_activate_delayed(raid5_conf_t *conf)
+static void raid5_activate_delayed(struct r5conf *conf)
{
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
while (!list_empty(&conf->delayed_list)) {
@@ -3396,7 +3389,7 @@ static void raid5_activate_delayed(raid5_conf_t *conf)
}
}
-static void activate_bit_delay(raid5_conf_t *conf)
+static void activate_bit_delay(struct r5conf *conf)
{
/* device_lock is held */
struct list_head head;
@@ -3410,9 +3403,9 @@ static void activate_bit_delay(raid5_conf_t *conf)
}
}
-int md_raid5_congested(mddev_t *mddev, int bits)
+int md_raid5_congested(struct mddev *mddev, int bits)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
/* No difference between reads and writes. Just check
* how busy the stripe_cache is
@@ -3431,7 +3424,7 @@ EXPORT_SYMBOL_GPL(md_raid5_congested);
static int raid5_congested(void *data, int bits)
{
- mddev_t *mddev = data;
+ struct mddev *mddev = data;
return mddev_congested(mddev, bits) ||
md_raid5_congested(mddev, bits);
@@ -3444,7 +3437,7 @@ static int raid5_mergeable_bvec(struct request_queue *q,
struct bvec_merge_data *bvm,
struct bio_vec *biovec)
{
- mddev_t *mddev = q->queuedata;
+ struct mddev *mddev = q->queuedata;
sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
int max;
unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -3464,7 +3457,7 @@ static int raid5_mergeable_bvec(struct request_queue *q,
}
-static int in_chunk_boundary(mddev_t *mddev, struct bio *bio)
+static int in_chunk_boundary(struct mddev *mddev, struct bio *bio)
{
sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -3480,7 +3473,7 @@ static int in_chunk_boundary(mddev_t *mddev, struct bio *bio)
* add bio to the retry LIFO ( in O(1) ... we are in interrupt )
* later sampled by raid5d.
*/
-static void add_bio_to_retry(struct bio *bi,raid5_conf_t *conf)
+static void add_bio_to_retry(struct bio *bi,struct r5conf *conf)
{
unsigned long flags;
@@ -3494,7 +3487,7 @@ static void add_bio_to_retry(struct bio *bi,raid5_conf_t *conf)
}
-static struct bio *remove_bio_from_retry(raid5_conf_t *conf)
+static struct bio *remove_bio_from_retry(struct r5conf *conf)
{
struct bio *bi;
@@ -3527,10 +3520,10 @@ static struct bio *remove_bio_from_retry(raid5_conf_t *conf)
static void raid5_align_endio(struct bio *bi, int error)
{
struct bio* raid_bi = bi->bi_private;
- mddev_t *mddev;
- raid5_conf_t *conf;
+ struct mddev *mddev;
+ struct r5conf *conf;
int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
bio_put(bi);
@@ -3574,12 +3567,12 @@ static int bio_fits_rdev(struct bio *bi)
}
-static int chunk_aligned_read(mddev_t *mddev, struct bio * raid_bio)
+static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
int dd_idx;
struct bio* align_bi;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (!in_chunk_boundary(mddev, raid_bio)) {
pr_debug("chunk_aligned_read : non aligned\n");
@@ -3652,7 +3645,7 @@ static int chunk_aligned_read(mddev_t *mddev, struct bio * raid_bio)
* head of the hold_list has changed, i.e. the head was promoted to the
* handle_list.
*/
-static struct stripe_head *__get_priority_stripe(raid5_conf_t *conf)
+static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
{
struct stripe_head *sh;
@@ -3695,9 +3688,9 @@ static struct stripe_head *__get_priority_stripe(raid5_conf_t *conf)
return sh;
}
-static int make_request(mddev_t *mddev, struct bio * bi)
+static int make_request(struct mddev *mddev, struct bio * bi)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
int dd_idx;
sector_t new_sector;
sector_t logical_sector, last_sector;
@@ -3855,9 +3848,9 @@ static int make_request(mddev_t *mddev, struct bio * bi)
return 0;
}
-static sector_t raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks);
+static sector_t raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks);
-static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped)
+static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *skipped)
{
/* reshaping is quite different to recovery/resync so it is
* handled quite separately ... here.
@@ -3868,7 +3861,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
* As the reads complete, handle_stripe will copy the data
* into the destination stripe and release that stripe.
*/
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
struct stripe_head *sh;
sector_t first_sector, last_sector;
int raid_disks = conf->previous_raid_disks;
@@ -4075,9 +4068,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
}
/* FIXME go_faster isn't used */
-static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
struct stripe_head *sh;
sector_t max_sector = mddev->dev_sectors;
sector_t sync_blocks;
@@ -4162,7 +4155,7 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
return STRIPE_SECTORS;
}
-static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
+static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
{
/* We may not be able to submit a whole bio at once as there
* may not be enough stripe_heads available.
@@ -4234,10 +4227,10 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
* During the scan, completed stripes are saved for us by the interrupt
* handler, so that they will not have to wait for our next wakeup.
*/
-static void raid5d(mddev_t *mddev)
+static void raid5d(struct mddev *mddev)
{
struct stripe_head *sh;
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
int handled;
struct blk_plug plug;
@@ -4301,9 +4294,9 @@ static void raid5d(mddev_t *mddev)
}
static ssize_t
-raid5_show_stripe_cache_size(mddev_t *mddev, char *page)
+raid5_show_stripe_cache_size(struct mddev *mddev, char *page)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
if (conf)
return sprintf(page, "%d\n", conf->max_nr_stripes);
else
@@ -4311,9 +4304,9 @@ raid5_show_stripe_cache_size(mddev_t *mddev, char *page)
}
int
-raid5_set_cache_size(mddev_t *mddev, int size)
+raid5_set_cache_size(struct mddev *mddev, int size)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
int err;
if (size <= 16 || size > 32768)
@@ -4337,9 +4330,9 @@ raid5_set_cache_size(mddev_t *mddev, int size)
EXPORT_SYMBOL(raid5_set_cache_size);
static ssize_t
-raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
+raid5_store_stripe_cache_size(struct mddev *mddev, const char *page, size_t len)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
unsigned long new;
int err;
@@ -4362,9 +4355,9 @@ raid5_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR,
raid5_store_stripe_cache_size);
static ssize_t
-raid5_show_preread_threshold(mddev_t *mddev, char *page)
+raid5_show_preread_threshold(struct mddev *mddev, char *page)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
if (conf)
return sprintf(page, "%d\n", conf->bypass_threshold);
else
@@ -4372,9 +4365,9 @@ raid5_show_preread_threshold(mddev_t *mddev, char *page)
}
static ssize_t
-raid5_store_preread_threshold(mddev_t *mddev, const char *page, size_t len)
+raid5_store_preread_threshold(struct mddev *mddev, const char *page, size_t len)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
unsigned long new;
if (len >= PAGE_SIZE)
return -EINVAL;
@@ -4396,9 +4389,9 @@ raid5_preread_bypass_threshold = __ATTR(preread_bypass_threshold,
raid5_store_preread_threshold);
static ssize_t
-stripe_cache_active_show(mddev_t *mddev, char *page)
+stripe_cache_active_show(struct mddev *mddev, char *page)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
if (conf)
return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
else
@@ -4420,9 +4413,9 @@ static struct attribute_group raid5_attrs_group = {
};
static sector_t
-raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
if (!sectors)
sectors = mddev->dev_sectors;
@@ -4435,7 +4428,7 @@ raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks)
return sectors * (raid_disks - conf->max_degraded);
}
-static void raid5_free_percpu(raid5_conf_t *conf)
+static void raid5_free_percpu(struct r5conf *conf)
{
struct raid5_percpu *percpu;
unsigned long cpu;
@@ -4457,7 +4450,7 @@ static void raid5_free_percpu(raid5_conf_t *conf)
free_percpu(conf->percpu);
}
-static void free_conf(raid5_conf_t *conf)
+static void free_conf(struct r5conf *conf)
{
shrink_stripes(conf);
raid5_free_percpu(conf);
@@ -4470,7 +4463,7 @@ static void free_conf(raid5_conf_t *conf)
static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
void *hcpu)
{
- raid5_conf_t *conf = container_of(nfb, raid5_conf_t, cpu_notify);
+ struct r5conf *conf = container_of(nfb, struct r5conf, cpu_notify);
long cpu = (long)hcpu;
struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
@@ -4505,7 +4498,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
}
#endif
-static int raid5_alloc_percpu(raid5_conf_t *conf)
+static int raid5_alloc_percpu(struct r5conf *conf)
{
unsigned long cpu;
struct page *spare_page;
@@ -4547,11 +4540,11 @@ static int raid5_alloc_percpu(raid5_conf_t *conf)
return err;
}
-static raid5_conf_t *setup_conf(mddev_t *mddev)
+static struct r5conf *setup_conf(struct mddev *mddev)
{
- raid5_conf_t *conf;
+ struct r5conf *conf;
int raid_disk, memory, max_disks;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
struct disk_info *disk;
if (mddev->new_level != 5
@@ -4583,7 +4576,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
return ERR_PTR(-EINVAL);
}
- conf = kzalloc(sizeof(raid5_conf_t), GFP_KERNEL);
+ conf = kzalloc(sizeof(struct r5conf), GFP_KERNEL);
if (conf == NULL)
goto abort;
spin_lock_init(&conf->device_lock);
@@ -4598,6 +4591,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
atomic_set(&conf->preread_active_stripes, 0);
atomic_set(&conf->active_aligned_reads, 0);
conf->bypass_threshold = BYPASS_THRESHOLD;
+ conf->recovery_disabled = mddev->recovery_disabled - 1;
conf->raid_disks = mddev->raid_disks;
if (mddev->reshape_position == MaxSector)
@@ -4712,12 +4706,12 @@ static int only_parity(int raid_disk, int algo, int raid_disks, int max_degraded
return 0;
}
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
{
- raid5_conf_t *conf;
+ struct r5conf *conf;
int working_disks = 0;
int dirty_parity_disks = 0;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t reshape_offset = 0;
if (mddev->recovery_cp != MaxSector)
@@ -4942,18 +4936,16 @@ static int run(mddev_t *mddev)
return 0;
abort:
md_unregister_thread(&mddev->thread);
- if (conf) {
- print_raid5_conf(conf);
- free_conf(conf);
- }
+ print_raid5_conf(conf);
+ free_conf(conf);
mddev->private = NULL;
printk(KERN_ALERT "md/raid:%s: failed to run raid set.\n", mdname(mddev));
return -EIO;
}
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
md_unregister_thread(&mddev->thread);
if (mddev->queue)
@@ -4964,44 +4956,9 @@ static int stop(mddev_t *mddev)
return 0;
}
-#ifdef DEBUG
-static void print_sh(struct seq_file *seq, struct stripe_head *sh)
-{
- int i;
-
- seq_printf(seq, "sh %llu, pd_idx %d, state %ld.\n",
- (unsigned long long)sh->sector, sh->pd_idx, sh->state);
- seq_printf(seq, "sh %llu, count %d.\n",
- (unsigned long long)sh->sector, atomic_read(&sh->count));
- seq_printf(seq, "sh %llu, ", (unsigned long long)sh->sector);
- for (i = 0; i < sh->disks; i++) {
- seq_printf(seq, "(cache%d: %p %ld) ",
- i, sh->dev[i].page, sh->dev[i].flags);
- }
- seq_printf(seq, "\n");
-}
-
-static void printall(struct seq_file *seq, raid5_conf_t *conf)
+static void status(struct seq_file *seq, struct mddev *mddev)
{
- struct stripe_head *sh;
- struct hlist_node *hn;
- int i;
-
- spin_lock_irq(&conf->device_lock);
- for (i = 0; i < NR_HASH; i++) {
- hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
- if (sh->raid_conf != conf)
- continue;
- print_sh(seq, sh);
- }
- }
- spin_unlock_irq(&conf->device_lock);
-}
-#endif
-
-static void status(struct seq_file *seq, mddev_t *mddev)
-{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
int i;
seq_printf(seq, " level %d, %dk chunk, algorithm %d", mddev->level,
@@ -5012,13 +4969,9 @@ static void status(struct seq_file *seq, mddev_t *mddev)
conf->disks[i].rdev &&
test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_");
seq_printf (seq, "]");
-#ifdef DEBUG
- seq_printf (seq, "\n");
- printall(seq, conf);
-#endif
}
-static void print_raid5_conf (raid5_conf_t *conf)
+static void print_raid5_conf (struct r5conf *conf)
{
int i;
struct disk_info *tmp;
@@ -5042,10 +4995,10 @@ static void print_raid5_conf (raid5_conf_t *conf)
}
}
-static int raid5_spare_active(mddev_t *mddev)
+static int raid5_spare_active(struct mddev *mddev)
{
int i;
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
struct disk_info *tmp;
int count = 0;
unsigned long flags;
@@ -5067,11 +5020,11 @@ static int raid5_spare_active(mddev_t *mddev)
return count;
}
-static int raid5_remove_disk(mddev_t *mddev, int number)
+static int raid5_remove_disk(struct mddev *mddev, int number)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
int err = 0;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
struct disk_info *p = conf->disks + number;
print_raid5_conf(conf);
@@ -5110,9 +5063,9 @@ abort:
return err;
}
-static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
int err = -EEXIST;
int disk;
struct disk_info *p;
@@ -5153,7 +5106,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
return err;
}
-static int raid5_resize(mddev_t *mddev, sector_t sectors)
+static int raid5_resize(struct mddev *mddev, sector_t sectors)
{
/* no resync is happening, and there is enough space
* on all devices, so we can resize.
@@ -5180,7 +5133,7 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
return 0;
}
-static int check_stripe_cache(mddev_t *mddev)
+static int check_stripe_cache(struct mddev *mddev)
{
/* Can only proceed if there are plenty of stripe_heads.
* We need a minimum of one full stripe,, and for sensible progress
@@ -5190,7 +5143,7 @@ static int check_stripe_cache(mddev_t *mddev)
* If the chunk size is greater, user-space should request more
* stripe_heads first.
*/
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
if (((mddev->chunk_sectors << 9) / STRIPE_SIZE) * 4
> conf->max_nr_stripes ||
((mddev->new_chunk_sectors << 9) / STRIPE_SIZE) * 4
@@ -5204,9 +5157,9 @@ static int check_stripe_cache(mddev_t *mddev)
return 1;
}
-static int check_reshape(mddev_t *mddev)
+static int check_reshape(struct mddev *mddev)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
if (mddev->delta_disks == 0 &&
mddev->new_layout == mddev->layout &&
@@ -5236,10 +5189,10 @@ static int check_reshape(mddev_t *mddev)
return resize_stripes(conf, conf->raid_disks + mddev->delta_disks);
}
-static int raid5_start_reshape(mddev_t *mddev)
+static int raid5_start_reshape(struct mddev *mddev)
{
- raid5_conf_t *conf = mddev->private;
- mdk_rdev_t *rdev;
+ struct r5conf *conf = mddev->private;
+ struct md_rdev *rdev;
int spares = 0;
unsigned long flags;
@@ -5353,7 +5306,7 @@ static int raid5_start_reshape(mddev_t *mddev)
/* This is called from the reshape thread and should make any
* changes needed in 'conf'
*/
-static void end_reshape(raid5_conf_t *conf)
+static void end_reshape(struct r5conf *conf)
{
if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
@@ -5380,9 +5333,9 @@ static void end_reshape(raid5_conf_t *conf)
/* This is called from the raid5d thread with mddev_lock held.
* It makes config changes to the device.
*/
-static void raid5_finish_reshape(mddev_t *mddev)
+static void raid5_finish_reshape(struct mddev *mddev)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
@@ -5401,7 +5354,7 @@ static void raid5_finish_reshape(mddev_t *mddev)
for (d = conf->raid_disks ;
d < conf->raid_disks - mddev->delta_disks;
d++) {
- mdk_rdev_t *rdev = conf->disks[d].rdev;
+ struct md_rdev *rdev = conf->disks[d].rdev;
if (rdev && raid5_remove_disk(mddev, d) == 0) {
sysfs_unlink_rdev(mddev, rdev);
rdev->raid_disk = -1;
@@ -5415,9 +5368,9 @@ static void raid5_finish_reshape(mddev_t *mddev)
}
}
-static void raid5_quiesce(mddev_t *mddev, int state)
+static void raid5_quiesce(struct mddev *mddev, int state)
{
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
switch(state) {
case 2: /* resume for a suspend */
@@ -5451,20 +5404,20 @@ static void raid5_quiesce(mddev_t *mddev, int state)
}
-static void *raid45_takeover_raid0(mddev_t *mddev, int level)
+static void *raid45_takeover_raid0(struct mddev *mddev, int level)
{
- struct raid0_private_data *raid0_priv = mddev->private;
+ struct r0conf *raid0_conf = mddev->private;
sector_t sectors;
/* for raid0 takeover only one zone is supported */
- if (raid0_priv->nr_strip_zones > 1) {
+ if (raid0_conf->nr_strip_zones > 1) {
printk(KERN_ERR "md/raid:%s: cannot takeover raid0 with more than one zone.\n",
mdname(mddev));
return ERR_PTR(-EINVAL);
}
- sectors = raid0_priv->strip_zone[0].zone_end;
- sector_div(sectors, raid0_priv->strip_zone[0].nb_dev);
+ sectors = raid0_conf->strip_zone[0].zone_end;
+ sector_div(sectors, raid0_conf->strip_zone[0].nb_dev);
mddev->dev_sectors = sectors;
mddev->new_level = level;
mddev->new_layout = ALGORITHM_PARITY_N;
@@ -5478,7 +5431,7 @@ static void *raid45_takeover_raid0(mddev_t *mddev, int level)
}
-static void *raid5_takeover_raid1(mddev_t *mddev)
+static void *raid5_takeover_raid1(struct mddev *mddev)
{
int chunksect;
@@ -5505,7 +5458,7 @@ static void *raid5_takeover_raid1(mddev_t *mddev)
return setup_conf(mddev);
}
-static void *raid5_takeover_raid6(mddev_t *mddev)
+static void *raid5_takeover_raid6(struct mddev *mddev)
{
int new_layout;
@@ -5539,14 +5492,14 @@ static void *raid5_takeover_raid6(mddev_t *mddev)
}
-static int raid5_check_reshape(mddev_t *mddev)
+static int raid5_check_reshape(struct mddev *mddev)
{
/* For a 2-drive array, the layout and chunk size can be changed
* immediately as not restriping is needed.
* For larger arrays we record the new value - after validation
* to be used by a reshape pass.
*/
- raid5_conf_t *conf = mddev->private;
+ struct r5conf *conf = mddev->private;
int new_chunk = mddev->new_chunk_sectors;
if (mddev->new_layout >= 0 && !algorithm_valid_raid5(mddev->new_layout))
@@ -5579,7 +5532,7 @@ static int raid5_check_reshape(mddev_t *mddev)
return check_reshape(mddev);
}
-static int raid6_check_reshape(mddev_t *mddev)
+static int raid6_check_reshape(struct mddev *mddev)
{
int new_chunk = mddev->new_chunk_sectors;
@@ -5599,7 +5552,7 @@ static int raid6_check_reshape(mddev_t *mddev)
return check_reshape(mddev);
}
-static void *raid5_takeover(mddev_t *mddev)
+static void *raid5_takeover(struct mddev *mddev)
{
/* raid5 can take over:
* raid0 - if there is only one strip zone - make it a raid4 layout
@@ -5622,7 +5575,7 @@ static void *raid5_takeover(mddev_t *mddev)
return ERR_PTR(-EINVAL);
}
-static void *raid4_takeover(mddev_t *mddev)
+static void *raid4_takeover(struct mddev *mddev)
{
/* raid4 can take over:
* raid0 - if there is only one strip zone
@@ -5639,9 +5592,9 @@ static void *raid4_takeover(mddev_t *mddev)
return ERR_PTR(-EINVAL);
}
-static struct mdk_personality raid5_personality;
+static struct md_personality raid5_personality;
-static void *raid6_takeover(mddev_t *mddev)
+static void *raid6_takeover(struct mddev *mddev)
{
/* Currently can only take over a raid5. We map the
* personality to an equivalent raid6 personality
@@ -5688,7 +5641,7 @@ static void *raid6_takeover(mddev_t *mddev)
}
-static struct mdk_personality raid6_personality =
+static struct md_personality raid6_personality =
{
.name = "raid6",
.level = 6,
@@ -5710,7 +5663,7 @@ static struct mdk_personality raid6_personality =
.quiesce = raid5_quiesce,
.takeover = raid6_takeover,
};
-static struct mdk_personality raid5_personality =
+static struct md_personality raid5_personality =
{
.name = "raid5",
.level = 5,
@@ -5733,7 +5686,7 @@ static struct mdk_personality raid5_personality =
.takeover = raid5_takeover,
};
-static struct mdk_personality raid4_personality =
+static struct md_personality raid4_personality =
{
.name = "raid4",
.level = 4,
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 11b9566184b2..e10c5531f9c5 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -197,7 +197,7 @@ enum reconstruct_states {
struct stripe_head {
struct hlist_node hash;
struct list_head lru; /* inactive_list or handle_list */
- struct raid5_private_data *raid_conf;
+ struct r5conf *raid_conf;
short generation; /* increments with every
* reshape */
sector_t sector; /* sector of this row */
@@ -248,7 +248,7 @@ struct stripe_head_state {
unsigned long ops_request;
struct bio *return_bi;
- mdk_rdev_t *blocked_rdev;
+ struct md_rdev *blocked_rdev;
int handle_bad_blocks;
};
@@ -344,12 +344,12 @@ enum {
struct disk_info {
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
};
-struct raid5_private_data {
+struct r5conf {
struct hlist_head *stripe_hashtbl;
- mddev_t *mddev;
+ struct mddev *mddev;
struct disk_info *spare;
int chunk_sectors;
int level, algorithm;
@@ -436,11 +436,9 @@ struct raid5_private_data {
/* When taking over an array from a different personality, we store
* the new thread here until we fully activate the array.
*/
- struct mdk_thread_s *thread;
+ struct md_thread *thread;
};
-typedef struct raid5_private_data raid5_conf_t;
-
/*
* Our supported algorithms
*/
@@ -503,7 +501,7 @@ static inline int algorithm_is_DDF(int layout)
return layout >= 8 && layout <= 10;
}
-extern int md_raid5_congested(mddev_t *mddev, int bits);
-extern void md_raid5_kick_device(raid5_conf_t *conf);
-extern int raid5_set_cache_size(mddev_t *mddev, int size);
+extern int md_raid5_congested(struct mddev *mddev, int bits);
+extern void md_raid5_kick_device(struct r5conf *conf);
+extern int raid5_set_cache_size(struct mddev *mddev, int size);
#endif
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 9af2140b57a4..f5d53a202344 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -18,6 +18,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <media/saa7146.h>
LIST_HEAD(saa7146_devices);
@@ -35,10 +37,9 @@ static void dump_registers(struct saa7146_dev* dev)
{
int i = 0;
- INFO((" @ %li jiffies:\n",jiffies));
- for(i = 0; i <= 0x148; i+=4) {
- printk("0x%03x: 0x%08x\n",i,saa7146_read(dev,i));
- }
+ pr_info(" @ %li jiffies:\n", jiffies);
+ for (i = 0; i <= 0x148; i += 4)
+ pr_info("0x%03x: 0x%08x\n", i, saa7146_read(dev, i));
}
#endif
@@ -72,9 +73,8 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
if (saa7146_read(dev, MC2) & 2)
break;
if (err) {
- printk(KERN_ERR "%s: %s timed out while waiting for "
- "registers getting programmed\n",
- dev->name, __func__);
+ pr_err("%s: %s timed out while waiting for registers getting programmed\n",
+ dev->name, __func__);
return -ETIMEDOUT;
}
msleep(1);
@@ -88,8 +88,8 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
break;
saa7146_read(dev, MC2);
if (err) {
- DEB_S(("%s: %s timed out while waiting for transfer "
- "completion\n", dev->name, __func__));
+ DEB_S("%s: %s timed out while waiting for transfer completion\n",
+ dev->name, __func__);
return -ETIMEDOUT;
}
msleep(1);
@@ -109,9 +109,8 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
if (saa7146_read(dev, MC2) & 2)
break;
if (!loops--) {
- printk(KERN_ERR "%s: %s timed out while waiting for "
- "registers getting programmed\n",
- dev->name, __func__);
+ pr_err("%s: %s timed out while waiting for registers getting programmed\n",
+ dev->name, __func__);
return -ETIMEDOUT;
}
udelay(1);
@@ -124,8 +123,8 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
break;
saa7146_read(dev, MC2);
if (!loops--) {
- DEB_S(("%s: %s timed out while waiting for transfer "
- "completion\n", dev->name, __func__));
+ DEB_S("%s: %s timed out while waiting for transfer completion\n",
+ dev->name, __func__);
return -ETIMEDOUT;
}
udelay(5);
@@ -264,7 +263,9 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
ptr = pt->cpu;
for (i = 0; i < sglen; i++, list++) {
/*
- printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset);
+ pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n",
+ i, sg_dma_address(list), sg_dma_len(list),
+ list->offset);
*/
for (p = 0; p * 4096 < list->length; p++, ptr++) {
*ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
@@ -281,9 +282,9 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
/*
ptr = pt->cpu;
- printk("offset: %d\n",pt->offset);
+ pr_debug("offset: %d\n", pt->offset);
for(i=0;i<5;i++) {
- printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
+ pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]);
}
*/
return 0;
@@ -314,7 +315,7 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
}
}
if (0 != (isr & (MASK_27))) {
- DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
+ DEB_INT("irq: RPS0 (0x%08x)\n", isr);
if (dev->vv_data && dev->vv_callback)
dev->vv_callback(dev,isr);
isr &= ~MASK_27;
@@ -333,14 +334,15 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
} else {
u32 psr = saa7146_read(dev, PSR);
u32 ssr = saa7146_read(dev, SSR);
- printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
- dev->name, isr, psr, ssr);
+ pr_warn("%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
+ dev->name, isr, psr, ssr);
}
isr &= ~(MASK_16|MASK_17);
}
if( 0 != isr ) {
- ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr));
- ERR(("disabling interrupt source(s)!\n"));
+ ERR("warning: interrupt enabled, but not handled properly.(0x%08x)\n",
+ isr);
+ ERR("disabling interrupt source(s)!\n");
SAA7146_IER_DISABLE(dev,isr);
}
saa7146_write(dev, ISR, ack_isr);
@@ -360,15 +362,15 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
/* clear out mem for sure */
dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
if (!dev) {
- ERR(("out of memory.\n"));
+ ERR("out of memory\n");
goto out;
}
- DEB_EE(("pci:%p\n",pci));
+ DEB_EE("pci:%p\n", pci);
err = pci_enable_device(pci);
if (err < 0) {
- ERR(("pci_enable_device() failed.\n"));
+ ERR("pci_enable_device() failed\n");
goto err_free;
}
@@ -389,7 +391,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
dev->mem = ioremap(pci_resource_start(pci, 0),
pci_resource_len(pci, 0));
if (!dev->mem) {
- ERR(("ioremap() failed.\n"));
+ ERR("ioremap() failed\n");
err = -ENODEV;
goto err_release;
}
@@ -414,7 +416,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED | IRQF_DISABLED,
dev->name, dev);
if (err < 0) {
- ERR(("request_irq() failed.\n"));
+ ERR("request_irq() failed\n");
goto err_unmap;
}
@@ -444,7 +446,9 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
/* create a nice device name */
sprintf(dev->name, "saa7146 (%d)", saa7146_num);
- INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
+ pr_info("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x)\n",
+ dev->mem, dev->revision, pci->irq,
+ pci->subsystem_vendor, pci->subsystem_device);
dev->ext = ext;
mutex_init(&dev->v4l2_lock);
@@ -464,12 +468,12 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
err = -ENODEV;
if (ext->probe && ext->probe(dev)) {
- DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
+ DEB_D("ext->probe() failed for %p. skipping device.\n", dev);
goto err_free_i2c;
}
if (ext->attach(dev, pci_ext)) {
- DEB_D(("ext->attach() failed for %p. skipping device.\n",dev));
+ DEB_D("ext->attach() failed for %p. skipping device.\n", dev);
goto err_free_i2c;
}
/* V4L extensions will set the pci drvdata to the v4l2_device in the
@@ -521,7 +525,7 @@ static void saa7146_remove_one(struct pci_dev *pdev)
{ NULL, 0 }
}, *p;
- DEB_EE(("dev:%p\n",dev));
+ DEB_EE("dev:%p\n", dev);
dev->ext->detach(dev);
/* Zero the PCI drvdata after use. */
@@ -552,21 +556,21 @@ static void saa7146_remove_one(struct pci_dev *pdev)
int saa7146_register_extension(struct saa7146_extension* ext)
{
- DEB_EE(("ext:%p\n",ext));
+ DEB_EE("ext:%p\n", ext);
ext->driver.name = ext->name;
ext->driver.id_table = ext->pci_tbl;
ext->driver.probe = saa7146_init_one;
ext->driver.remove = saa7146_remove_one;
- printk("saa7146: register extension '%s'.\n",ext->name);
+ pr_info("register extension '%s'\n", ext->name);
return pci_register_driver(&ext->driver);
}
int saa7146_unregister_extension(struct saa7146_extension* ext)
{
- DEB_EE(("ext:%p\n",ext));
- printk("saa7146: unregister extension '%s'.\n",ext->name);
+ DEB_EE("ext:%p\n", ext);
+ pr_info("unregister extension '%s'\n", ext->name);
pci_unregister_driver(&ext->driver);
return 0;
}
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 1bd3dd762c6b..a92546144eaa 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <media/saa7146_vv.h>
/****************************************************************************/
@@ -9,21 +11,23 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
struct saa7146_vv *vv = dev->vv_data;
if (fh->resources & bit) {
- DEB_D(("already allocated! want: 0x%02x, cur:0x%02x\n",bit,vv->resources));
+ DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",
+ bit, vv->resources);
/* have it already allocated */
return 1;
}
/* is it free? */
if (vv->resources & bit) {
- DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit));
+ DEB_D("locked! vv->resources:0x%02x, we want:0x%02x\n",
+ vv->resources, bit);
/* no, someone else uses it */
return 0;
}
/* it's free, grab it */
- fh->resources |= bit;
+ fh->resources |= bit;
vv->resources |= bit;
- DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources));
+ DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);
return 1;
}
@@ -34,9 +38,9 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
BUG_ON((fh->resources & bits) != bits);
- fh->resources &= ~bits;
+ fh->resources &= ~bits;
vv->resources &= ~bits;
- DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources));
+ DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);
}
@@ -47,7 +51,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
struct saa7146_buf *buf)
{
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
- DEB_EE(("dev:%p, buf:%p\n",dev,buf));
+ DEB_EE("dev:%p, buf:%p\n", dev, buf);
BUG_ON(in_interrupt());
@@ -66,18 +70,19 @@ int saa7146_buffer_queue(struct saa7146_dev *dev,
struct saa7146_buf *buf)
{
assert_spin_locked(&dev->slock);
- DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf));
+ DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);
BUG_ON(!q);
if (NULL == q->curr) {
q->curr = buf;
- DEB_D(("immediately activating buffer %p\n", buf));
+ DEB_D("immediately activating buffer %p\n", buf);
buf->activate(dev,buf,NULL);
} else {
list_add_tail(&buf->vb.queue,&q->queue);
buf->vb.state = VIDEOBUF_QUEUED;
- DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf));
+ DEB_D("adding buffer %p to queue. (active buffer present)\n",
+ buf);
}
return 0;
}
@@ -87,14 +92,14 @@ void saa7146_buffer_finish(struct saa7146_dev *dev,
int state)
{
assert_spin_locked(&dev->slock);
- DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state));
- DEB_EE(("q->curr:%p\n",q->curr));
+ DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
+ DEB_EE("q->curr:%p\n", q->curr);
BUG_ON(!q->curr);
/* finish current buffer */
if (NULL == q->curr) {
- DEB_D(("aiii. no current buffer\n"));
+ DEB_D("aiii. no current buffer\n");
return;
}
@@ -112,7 +117,7 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
BUG_ON(!q);
- DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
+ DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);
assert_spin_locked(&dev->slock);
if (!list_empty(&q->queue)) {
@@ -122,10 +127,11 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
if (!list_empty(&q->queue))
next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
q->curr = buf;
- DEB_INT(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
+ DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",
+ buf, q->queue.prev, q->queue.next);
buf->activate(dev,buf,next);
} else {
- DEB_INT(("no next buffer. stopping.\n"));
+ DEB_INT("no next buffer. stopping.\n");
if( 0 != vbi ) {
/* turn off video-dma3 */
saa7146_write(dev,MC1, MASK_20);
@@ -162,11 +168,11 @@ void saa7146_buffer_timeout(unsigned long data)
struct saa7146_dev *dev = q->dev;
unsigned long flags;
- DEB_EE(("dev:%p, dmaq:%p\n", dev, q));
+ DEB_EE("dev:%p, dmaq:%p\n", dev, q);
spin_lock_irqsave(&dev->slock,flags);
if (q->curr) {
- DEB_D(("timeout on %p\n", q->curr));
+ DEB_D("timeout on %p\n", q->curr);
saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
}
@@ -194,12 +200,12 @@ static int fops_open(struct file *file)
enum v4l2_buf_type type;
- DEB_EE(("file:%p, dev:%s\n", file, video_device_node_name(vdev)));
+ DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
if (mutex_lock_interruptible(&saa7146_devices_lock))
return -ERESTARTSYS;
- DEB_D(("using: %p\n",dev));
+ DEB_D("using: %p\n", dev);
type = vdev->vfl_type == VFL_TYPE_GRABBER
? V4L2_BUF_TYPE_VIDEO_CAPTURE
@@ -207,7 +213,7 @@ static int fops_open(struct file *file)
/* check if an extension is registered */
if( NULL == dev->ext ) {
- DEB_S(("no extension registered for this device.\n"));
+ DEB_S("no extension registered for this device\n");
result = -ENODEV;
goto out;
}
@@ -215,7 +221,7 @@ static int fops_open(struct file *file)
/* allocate per open data */
fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh) {
- DEB_S(("cannot allocate memory for per open data.\n"));
+ DEB_S("cannot allocate memory for per open data\n");
result = -ENOMEM;
goto out;
}
@@ -225,13 +231,13 @@ static int fops_open(struct file *file)
fh->type = type;
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
- DEB_S(("initializing vbi...\n"));
+ DEB_S("initializing vbi...\n");
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
result = saa7146_vbi_uops.open(dev,file);
if (dev->ext_vv_data->vbi_fops.open)
dev->ext_vv_data->vbi_fops.open(file);
} else {
- DEB_S(("initializing video...\n"));
+ DEB_S("initializing video...\n");
result = saa7146_video_uops.open(dev,file);
}
@@ -259,7 +265,7 @@ static int fops_release(struct file *file)
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
- DEB_EE(("file:%p\n", file));
+ DEB_EE("file:%p\n", file);
if (mutex_lock_interruptible(&saa7146_devices_lock))
return -ERESTARTSYS;
@@ -289,12 +295,14 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
- DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",file, vma));
+ DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",
+ file, vma);
q = &fh->video_q;
break;
}
case V4L2_BUF_TYPE_VBI_CAPTURE: {
- DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",file, vma));
+ DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
+ file, vma);
q = &fh->vbi_q;
break;
}
@@ -312,14 +320,14 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
struct videobuf_buffer *buf = NULL;
struct videobuf_queue *q;
- DEB_EE(("file:%p, poll:%p\n",file, wait));
+ DEB_EE("file:%p, poll:%p\n", file, wait);
if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
if( 0 == fh->vbi_q.streaming )
return videobuf_poll_stream(file, &fh->vbi_q, wait);
q = &fh->vbi_q;
} else {
- DEB_D(("using video queue.\n"));
+ DEB_D("using video queue\n");
q = &fh->video_q;
}
@@ -327,17 +335,17 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
if (!buf) {
- DEB_D(("buf == NULL!\n"));
+ DEB_D("buf == NULL!\n");
return POLLERR;
}
poll_wait(file, &buf->done, wait);
if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
- DEB_D(("poll succeeded!\n"));
+ DEB_D("poll succeeded!\n");
return POLLIN|POLLRDNORM;
}
- DEB_D(("nothing to poll for, buf->state:%d\n",buf->state));
+ DEB_D("nothing to poll for, buf->state:%d\n", buf->state);
return 0;
}
@@ -346,18 +354,20 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
struct saa7146_fh *fh = file->private_data;
switch (fh->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-// DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count));
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+/*
+ DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun",
+ file, data, (unsigned long)count);
+*/
return saa7146_video_uops.read(file,data,count,ppos);
- }
- case V4L2_BUF_TYPE_VBI_CAPTURE: {
-// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+/*
+ DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
+ file, data, (unsigned long)count);
+*/
if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
return saa7146_vbi_uops.read(file,data,count,ppos);
- else
- return -EINVAL;
- }
- break;
+ return -EINVAL;
default:
BUG();
return 0;
@@ -398,22 +408,22 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
{
u32 isr = status;
- DEB_INT(("dev:%p, isr:0x%08x\n",dev,(u32)status));
+ DEB_INT("dev:%p, isr:0x%08x\n", dev, (u32)status);
if (0 != (isr & (MASK_27))) {
- DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
+ DEB_INT("irq: RPS0 (0x%08x)\n", isr);
saa7146_video_uops.irq_done(dev,isr);
}
if (0 != (isr & (MASK_28))) {
u32 mc2 = saa7146_read(dev, MC2);
if( 0 != (mc2 & MASK_15)) {
- DEB_INT(("irq: RPS1 vbi workaround (0x%08x).\n",isr));
+ DEB_INT("irq: RPS1 vbi workaround (0x%08x)\n", isr);
wake_up(&dev->vv_data->vbi_wq);
saa7146_write(dev,MC2, MASK_31);
return;
}
- DEB_INT(("irq: RPS1 (0x%08x).\n",isr));
+ DEB_INT("irq: RPS1 (0x%08x)\n", isr);
saa7146_vbi_uops.irq_done(dev,isr);
}
}
@@ -429,13 +439,13 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
if (vv == NULL) {
- ERR(("out of memory. aborting.\n"));
+ ERR("out of memory. aborting.\n");
return -ENOMEM;
}
ext_vv->ops = saa7146_video_ioctl_ops;
ext_vv->core_ops = &saa7146_video_ioctl_ops;
- DEB_EE(("dev:%p\n",dev));
+ DEB_EE("dev:%p\n", dev);
/* set default values for video parts of the saa7146 */
saa7146_write(dev, BCS_CTRL, 0x80400040);
@@ -450,7 +460,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
if( NULL == vv->d_clipping.cpu_addr ) {
- ERR(("out of memory. aborting.\n"));
+ ERR("out of memory. aborting.\n");
kfree(vv);
return -1;
}
@@ -471,7 +481,7 @@ int saa7146_vv_release(struct saa7146_dev* dev)
{
struct saa7146_vv *vv = dev->vv_data;
- DEB_EE(("dev:%p\n",dev));
+ DEB_EE("dev:%p\n", dev);
v4l2_device_unregister(&dev->v4l2_dev);
pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
@@ -490,7 +500,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
int err;
int i;
- DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
+ DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
// released by vfd->release
vfd = video_device_alloc();
@@ -509,13 +519,13 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
err = video_register_device(vfd, type, -1);
if (err < 0) {
- ERR(("cannot register v4l2 device. skipping.\n"));
+ ERR("cannot register v4l2 device. skipping.\n");
video_device_release(vfd);
return err;
}
- INFO(("%s: registered device %s [v4l2]\n",
- dev->name, video_device_node_name(vfd)));
+ pr_info("%s: registered device %s [v4l2]\n",
+ dev->name, video_device_node_name(vfd));
*vid = vfd;
return 0;
@@ -524,7 +534,7 @@ EXPORT_SYMBOL_GPL(saa7146_register_device);
int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
{
- DEB_EE(("dev:%p\n",dev));
+ DEB_EE("dev:%p\n", dev);
video_unregister_device(*vid);
*vid = NULL;
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
index 1d1d8d200755..79ad73accb27 100644
--- a/drivers/media/common/saa7146_hlp.c
+++ b/drivers/media/common/saa7146_hlp.c
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <media/saa7146_vv.h>
@@ -711,8 +713,8 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
int depth = sfmt->depth;
- DEB_CAP(("[size=%dx%d,fields=%s]\n",
- width,height,v4l2_field_names[field]));
+ DEB_CAP("[size=%dx%d,fields=%s]\n",
+ width, height, v4l2_field_names[field]);
if( bytesperline != 0) {
vdma1.pitch = bytesperline*2;
@@ -837,8 +839,8 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71
BUG_ON(0 == buf->pt[1].dma);
BUG_ON(0 == buf->pt[2].dma);
- DEB_CAP(("[size=%dx%d,fields=%s]\n",
- width,height,v4l2_field_names[field]));
+ DEB_CAP("[size=%dx%d,fields=%s]\n",
+ width, height, v4l2_field_names[field]);
/* fixme: look at bytesperline! */
@@ -998,12 +1000,12 @@ void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struc
struct saa7146_vv *vv = dev->vv_data;
u32 vdma1_prot_addr;
- DEB_CAP(("buf:%p, next:%p\n",buf,next));
+ DEB_CAP("buf:%p, next:%p\n", buf, next);
vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
if( 0 == vdma1_prot_addr ) {
/* clear out beginning of streaming bit (rps register 0)*/
- DEB_CAP(("forcing sync to new frame\n"));
+ DEB_CAP("forcing sync to new frame\n");
saa7146_write(dev, MC2, MASK_27 );
}
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index b2ba9dc0dd6d..22027198129d 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -1,8 +1,10 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <media/saa7146_vv.h>
static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
{
-//fm DEB_I2C(("'%s'.\n", adapter->name));
+ /* DEB_I2C("'%s'\n", adapter->name); */
return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_QUICK
@@ -14,9 +16,7 @@ static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
{
u32 iicsta = saa7146_read(dev, I2C_STATUS);
-/*
- DEB_I2C(("status: 0x%08x\n",iicsta));
-*/
+ /* DEB_I2C("status: 0x%08x\n", iicsta); */
return iicsta;
}
@@ -39,10 +39,11 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, __le32 *op)
plus one extra byte to address the device */
mem = 1 + ((mem-1) / 3);
- /* we assume that op points to a memory of at least SAA7146_I2C_MEM bytes
- size. if we exceed this limit... */
- if ( (4*mem) > SAA7146_I2C_MEM ) {
-//fm DEB_I2C(("cannot prepare i2c-message.\n"));
+ /* we assume that op points to a memory of at least
+ * SAA7146_I2C_MEM bytes size. if we exceed this limit...
+ */
+ if ((4 * mem) > SAA7146_I2C_MEM) {
+ /* DEB_I2C("cannot prepare i2c-message\n"); */
return -ENOMEM;
}
@@ -123,7 +124,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
if ( 0 != ( status & SAA7146_I2C_BUSY) ) {
/* yes, kill ongoing operation */
- DEB_I2C(("busy_state detected.\n"));
+ DEB_I2C("busy_state detected\n");
/* set "ABORT-OPERATION"-bit (bit 7)*/
saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
@@ -141,7 +142,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
if ( dev->i2c_bitrate != status ) {
- DEB_I2C(("error_state detected. status:0x%08x\n",status));
+ DEB_I2C("error_state detected. status:0x%08x\n", status);
/* Repeat the abort operation. This seems to be necessary
after serious protocol errors caused by e.g. the SAA7740 */
@@ -164,7 +165,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
/* if any error is still present, a fatal error has occurred ... */
status = saa7146_i2c_status(dev);
if ( dev->i2c_bitrate != status ) {
- DEB_I2C(("fatal error. status:0x%08x\n",status));
+ DEB_I2C("fatal error. status:0x%08x\n", status);
return -1;
}
@@ -181,7 +182,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
unsigned long timeout;
/* write out i2c-command */
- DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
+ DEB_I2C("before: 0x%08x (status: 0x%08x), %d\n",
+ *dword, saa7146_read(dev, I2C_STATUS), dev->i2c_op);
if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
@@ -202,7 +204,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
/* a signal arrived */
return -ERESTARTSYS;
- printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
+ pr_warn("%s %s [irq]: timed out waiting for end of xfer\n",
dev->name, __func__);
return -EIO;
}
@@ -220,7 +222,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
break;
}
if (time_after(jiffies,timeout)) {
- printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
+ pr_warn("%s %s: timed out waiting for MC2\n",
dev->name, __func__);
return -EIO;
}
@@ -237,7 +239,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
/* this is normal when probing the bus
* (no answer from nonexisistant device...)
*/
- printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
+ pr_warn("%s %s [poll]: timed out waiting for end of xfer\n",
dev->name, __func__);
return -EIO;
}
@@ -257,24 +259,24 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
if ( 0 == (status & SAA7146_I2C_ERR) ||
0 == (status & SAA7146_I2C_BUSY) ) {
/* it may take some time until ERR goes high - ignore */
- DEB_I2C(("unexpected i2c status %04x\n", status));
+ DEB_I2C("unexpected i2c status %04x\n", status);
}
if( 0 != (status & SAA7146_I2C_SPERR) ) {
- DEB_I2C(("error due to invalid start/stop condition.\n"));
+ DEB_I2C("error due to invalid start/stop condition\n");
}
if( 0 != (status & SAA7146_I2C_DTERR) ) {
- DEB_I2C(("error in data transmission.\n"));
+ DEB_I2C("error in data transmission\n");
}
if( 0 != (status & SAA7146_I2C_DRERR) ) {
- DEB_I2C(("error when receiving data.\n"));
+ DEB_I2C("error when receiving data\n");
}
if( 0 != (status & SAA7146_I2C_AL) ) {
- DEB_I2C(("error because arbitration lost.\n"));
+ DEB_I2C("error because arbitration lost\n");
}
/* we handle address-errors here */
if( 0 != (status & SAA7146_I2C_APERR) ) {
- DEB_I2C(("error in address phase.\n"));
+ DEB_I2C("error in address phase\n");
return -EREMOTEIO;
}
@@ -284,7 +286,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
/* read back data, just in case we were reading ... */
*dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER));
- DEB_I2C(("after: 0x%08x\n",*dword));
+ DEB_I2C("after: 0x%08x\n", *dword);
return 0;
}
@@ -299,7 +301,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
return -ERESTARTSYS;
for(i=0;i<num;i++) {
- DEB_I2C(("msg:%d/%d\n",i+1,num));
+ DEB_I2C("msg:%d/%d\n", i+1, num);
}
/* prepare the message(s), get number of u32s to transfer */
@@ -316,7 +318,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
/* reset the i2c-device if necessary */
err = saa7146_i2c_reset(dev);
if ( 0 > err ) {
- DEB_I2C(("could not reset i2c-device.\n"));
+ DEB_I2C("could not reset i2c-device\n");
goto out;
}
@@ -336,7 +338,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
address error and trust the saa7146 address error detection. */
if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags))
goto out;
- DEB_I2C(("error while sending message(s). starting again.\n"));
+ DEB_I2C("error while sending message(s). starting again\n");
break;
}
}
@@ -356,13 +358,13 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
/* if any things had to be read, get the results */
if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
- DEB_I2C(("could not cleanup i2c-message.\n"));
+ DEB_I2C("could not cleanup i2c-message\n");
err = -1;
goto out;
}
/* return the number of delivered messages */
- DEB_I2C(("transmission successful. (msg:%d).\n",err));
+ DEB_I2C("transmission successful. (msg:%d)\n", err);
out:
/* another bug in revision 0: the i2c-registers get uploaded randomly by other
uploads, so we better clear them out before continuing */
@@ -370,7 +372,7 @@ out:
__le32 zero = 0;
saa7146_i2c_reset(dev);
if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
- INFO(("revision 0 error. this should never happen.\n"));
+ pr_info("revision 0 error. this should never happen\n");
}
}
@@ -400,7 +402,7 @@ static struct i2c_algorithm saa7146_algo = {
int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
{
- DEB_EE(("bitrate: 0x%08x\n",bitrate));
+ DEB_EE("bitrate: 0x%08x\n", bitrate);
/* enable i2c-port pins */
saa7146_write(dev, MC1, (MASK_08 | MASK_24));
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
index afe85801d6ca..b2e718343739 100644
--- a/drivers/media/common/saa7146_vbi.c
+++ b/drivers/media/common/saa7146_vbi.c
@@ -14,7 +14,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
DECLARE_WAITQUEUE(wait, current);
- DEB_VBI(("dev:%p\n",dev));
+ DEB_VBI("dev:%p\n", dev);
/* once again, a bug in the saa7146: the brs acquisition
is buggy and especially the BXO-counter does not work
@@ -40,14 +40,14 @@ static int vbi_workaround(struct saa7146_dev *dev)
WRITE_RPS1(0xc000008c);
/* wait for vbi_a or vbi_b*/
if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
- DEB_D(("...using port b\n"));
+ DEB_D("...using port b\n");
WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
/*
WRITE_RPS1(CMD_PAUSE | MASK_09);
*/
} else {
- DEB_D(("...using port a\n"));
+ DEB_D("...using port a\n");
WRITE_RPS1(CMD_PAUSE | MASK_10);
}
/* upload brs */
@@ -103,7 +103,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
schedule();
- DEB_VBI(("brs bug workaround %d/1.\n",i));
+ DEB_VBI("brs bug workaround %d/1\n", i);
remove_wait_queue(&vv->vbi_wq, &wait);
current->state = TASK_RUNNING;
@@ -116,7 +116,8 @@ static int vbi_workaround(struct saa7146_dev *dev)
if(signal_pending(current)) {
- DEB_VBI(("aborted (rps:0x%08x).\n",saa7146_read(dev,RPS_ADDR1)));
+ DEB_VBI("aborted (rps:0x%08x)\n",
+ saa7146_read(dev, RPS_ADDR1));
/* stop rps1 for sure */
saa7146_write(dev, MC1, MASK_29);
@@ -207,7 +208,7 @@ static int buffer_activate(struct saa7146_dev *dev,
struct saa7146_vv *vv = dev->vv_data;
buf->vb.state = VIDEOBUF_ACTIVE;
- DEB_VBI(("dev:%p, buf:%p, next:%p\n",dev,buf,next));
+ DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next);
saa7146_set_vbi_capture(dev,buf,next);
mod_timer(&vv->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
@@ -228,10 +229,10 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
llength = vbi_pixel_to_capture;
size = lines * llength;
- DEB_VBI(("vb:%p\n",vb));
+ DEB_VBI("vb:%p\n", vb);
if (0 != buf->vb.baddr && buf->vb.bsize < size) {
- DEB_VBI(("size mismatch.\n"));
+ DEB_VBI("size mismatch\n");
return -EINVAL;
}
@@ -263,7 +264,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
return 0;
oops:
- DEB_VBI(("error out.\n"));
+ DEB_VBI("error out\n");
saa7146_dma_free(dev,q,buf);
return err;
@@ -279,7 +280,7 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned
*size = lines * llength;
*count = 2;
- DEB_VBI(("count:%d, size:%d\n",*count,*size));
+ DEB_VBI("count:%d, size:%d\n", *count, *size);
return 0;
}
@@ -292,7 +293,7 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_vv *vv = dev->vv_data;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
- DEB_VBI(("vb:%p\n",vb));
+ DEB_VBI("vb:%p\n", vb);
saa7146_buffer_queue(dev,&vv->vbi_q,buf);
}
@@ -303,7 +304,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_dev *dev = fh->dev;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
- DEB_VBI(("vb:%p\n",vb));
+ DEB_VBI("vb:%p\n", vb);
saa7146_dma_free(dev,q,buf);
}
@@ -321,7 +322,7 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file)
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
unsigned long flags;
- DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
+ DEB_VBI("dev:%p, fh:%p\n", dev, fh);
spin_lock_irqsave(&dev->slock,flags);
@@ -354,14 +355,14 @@ static void vbi_read_timeout(unsigned long data)
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
- DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
+ DEB_VBI("dev:%p, fh:%p\n", dev, fh);
vbi_stop(fh, file);
}
static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
{
- DEB_VBI(("dev:%p\n",dev));
+ DEB_VBI("dev:%p\n", dev);
INIT_LIST_HEAD(&vv->vbi_q.queue);
@@ -380,11 +381,11 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
int ret = 0;
- DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+ DEB_VBI("dev:%p, fh:%p\n", dev, fh);
ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
if (0 == ret) {
- DEB_S(("cannot get vbi RESOURCE_DMA3_BRS resource\n"));
+ DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n");
return -EBUSY;
}
@@ -425,7 +426,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
saa7146_write(dev, BRS_CTRL, 0x00000001);
if (0 != (ret = vbi_workaround(dev))) {
- DEB_VBI(("vbi workaround failed!\n"));
+ DEB_VBI("vbi workaround failed!\n");
/* return ret;*/
}
}
@@ -439,7 +440,7 @@ static void vbi_close(struct saa7146_dev *dev, struct file *file)
{
struct saa7146_fh *fh = file->private_data;
struct saa7146_vv *vv = dev->vv_data;
- DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+ DEB_VBI("dev:%p, fh:%p\n", dev, fh);
if( fh == vv->vbi_streaming ) {
vbi_stop(fh, file);
@@ -453,13 +454,13 @@ static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
spin_lock(&dev->slock);
if (vv->vbi_q.curr) {
- DEB_VBI(("dev:%p, curr:%p\n",dev,vv->vbi_q.curr));
+ DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_q.curr);
/* this must be += 2, one count for each field */
vv->vbi_fieldcount+=2;
vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount;
saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
} else {
- DEB_VBI(("dev:%p\n",dev));
+ DEB_VBI("dev:%p\n", dev);
}
saa7146_buffer_next(dev,&vv->vbi_q,1);
@@ -473,7 +474,7 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
struct saa7146_vv *vv = dev->vv_data;
ssize_t ret = 0;
- DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+ DEB_VBI("dev:%p, fh:%p\n", dev, fh);
if( NULL == vv->vbi_streaming ) {
// fixme: check if dma3 is available
@@ -482,7 +483,8 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
}
if( fh != vv->vbi_streaming ) {
- DEB_VBI(("open %p is already using vbi capture.",vv->vbi_streaming));
+ DEB_VBI("open %p is already using vbi capture\n",
+ vv->vbi_streaming);
return -EBUSY;
}
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 9aafa4e969a8..384b358d3037 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <media/saa7146_vv.h>
#include <media/v4l2-chip-ident.h>
@@ -94,7 +96,7 @@ struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fou
}
}
- DEB_D(("unknown pixelformat:'%4.4s'\n",(char *)&fourcc));
+ DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
return NULL;
}
@@ -107,32 +109,32 @@ int saa7146_start_preview(struct saa7146_fh *fh)
struct v4l2_format fmt;
int ret = 0, err = 0;
- DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+ DEB_EE("dev:%p, fh:%p\n", dev, fh);
/* check if we have overlay informations */
if( NULL == fh->ov.fh ) {
- DEB_D(("no overlay data available. try S_FMT first.\n"));
+ DEB_D("no overlay data available. try S_FMT first.\n");
return -EAGAIN;
}
/* check if streaming capture is running */
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- DEB_D(("streaming capture is active.\n"));
+ DEB_D("streaming capture is active\n");
return -EBUSY;
}
/* check if overlay is running */
if (IS_OVERLAY_ACTIVE(fh) != 0) {
if (vv->video_fh == fh) {
- DEB_D(("overlay is already active.\n"));
+ DEB_D("overlay is already active\n");
return 0;
}
- DEB_D(("overlay is already active in another open.\n"));
+ DEB_D("overlay is already active in another open\n");
return -EBUSY;
}
if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
- DEB_D(("cannot get necessary overlay resources\n"));
+ DEB_D("cannot get necessary overlay resources\n");
return -EBUSY;
}
@@ -145,13 +147,13 @@ int saa7146_start_preview(struct saa7146_fh *fh)
fh->ov.win = fmt.fmt.win;
vv->ov_data = &fh->ov;
- DEB_D(("%dx%d+%d+%d %s field=%s\n",
- fh->ov.win.w.width,fh->ov.win.w.height,
- fh->ov.win.w.left,fh->ov.win.w.top,
- vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field]));
+ DEB_D("%dx%d+%d+%d %s field=%s\n",
+ fh->ov.win.w.width, fh->ov.win.w.height,
+ fh->ov.win.w.left, fh->ov.win.w.top,
+ vv->ov_fmt->name, v4l2_field_names[fh->ov.win.field]);
if (0 != (ret = saa7146_enable_overlay(fh))) {
- DEB_D(("enabling overlay failed: %d\n",ret));
+ DEB_D("enabling overlay failed: %d\n", ret);
saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
return ret;
}
@@ -168,22 +170,22 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
- DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+ DEB_EE("dev:%p, fh:%p\n", dev, fh);
/* check if streaming capture is running */
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- DEB_D(("streaming capture is active.\n"));
+ DEB_D("streaming capture is active\n");
return -EBUSY;
}
/* check if overlay is running at all */
if ((vv->video_status & STATUS_OVERLAY) == 0) {
- DEB_D(("no active overlay.\n"));
+ DEB_D("no active overlay\n");
return 0;
}
if (vv->video_fh != fh) {
- DEB_D(("overlay is active, but in another open.\n"));
+ DEB_D("overlay is active, but in another open\n");
return -EBUSY;
}
@@ -268,7 +270,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
int length = dma->sglen;
struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
- DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
+ DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
if( 0 != IS_PLANAR(sfmt->trans)) {
struct saa7146_pgtable *pt1 = &buf->pt[0];
@@ -288,7 +290,8 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
o1 = size%PAGE_SIZE;
o2 = (size+(size/4))%PAGE_SIZE;
- DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
+ DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
+ size, m1, m2, m3, o1, o2);
break;
}
case 16: {
@@ -298,7 +301,8 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
o1 = size%PAGE_SIZE;
o2 = (size+(size/2))%PAGE_SIZE;
- DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
+ DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
+ size, m1, m2, m3, o1, o2);
break;
}
default: {
@@ -387,23 +391,23 @@ static int video_begin(struct saa7146_fh *fh)
unsigned int resource;
int ret = 0, err = 0;
- DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+ DEB_EE("dev:%p, fh:%p\n", dev, fh);
if ((vv->video_status & STATUS_CAPTURE) != 0) {
if (vv->video_fh == fh) {
- DEB_S(("already capturing.\n"));
+ DEB_S("already capturing\n");
return 0;
}
- DEB_S(("already capturing in another open.\n"));
+ DEB_S("already capturing in another open\n");
return -EBUSY;
}
if ((vv->video_status & STATUS_OVERLAY) != 0) {
- DEB_S(("warning: suspending overlay video for streaming capture.\n"));
+ DEB_S("warning: suspending overlay video for streaming capture\n");
vv->ov_suspend = vv->video_fh;
err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
if (0 != err) {
- DEB_D(("suspending video failed. aborting\n"));
+ DEB_D("suspending video failed. aborting\n");
return err;
}
}
@@ -420,7 +424,7 @@ static int video_begin(struct saa7146_fh *fh)
ret = saa7146_res_get(fh, resource);
if (0 == ret) {
- DEB_S(("cannot get capture resource %d\n",resource));
+ DEB_S("cannot get capture resource %d\n", resource);
if (vv->ov_suspend != NULL) {
saa7146_start_preview(vv->ov_suspend);
vv->ov_suspend = NULL;
@@ -448,15 +452,15 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
unsigned long flags;
unsigned int resource;
u32 dmas = 0;
- DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+ DEB_EE("dev:%p, fh:%p\n", dev, fh);
if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
- DEB_S(("not capturing.\n"));
+ DEB_S("not capturing\n");
return 0;
}
if (vv->video_fh != fh) {
- DEB_S(("capturing, but in another open.\n"));
+ DEB_S("capturing, but in another open\n");
return -EBUSY;
}
@@ -530,7 +534,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
struct saa7146_vv *vv = dev->vv_data;
struct saa7146_format *fmt;
- DEB_EE(("VIDIOC_S_FBUF\n"));
+ DEB_EE("VIDIOC_S_FBUF\n");
if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
return -EPERM;
@@ -542,13 +546,13 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
/* planar formats are not allowed for overlay video, clipping and video dma would clash */
if (fmt->flags & FORMAT_IS_PLANAR)
- DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",
- (char *)&fmt->pixelformat));
+ DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n",
+ (char *)&fmt->pixelformat);
/* check if overlay is running */
if (IS_OVERLAY_ACTIVE(fh) != 0) {
if (vv->video_fh != fh) {
- DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
+ DEB_D("refusing to change framebuffer informations while overlay is active in another open\n");
return -EBUSY;
}
}
@@ -559,7 +563,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
- DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline));
+ DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
}
return 0;
}
@@ -588,7 +592,7 @@ static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *
if (ctrl == NULL)
return -EINVAL;
- DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n", c->id));
+ DEB_EE("VIDIOC_QUERYCTRL: id:%d\n", c->id);
*c = *ctrl;
return 0;
}
@@ -607,25 +611,25 @@ static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
case V4L2_CID_BRIGHTNESS:
value = saa7146_read(dev, BCS_CTRL);
c->value = 0xff & (value >> 24);
- DEB_D(("V4L2_CID_BRIGHTNESS: %d\n", c->value));
+ DEB_D("V4L2_CID_BRIGHTNESS: %d\n", c->value);
break;
case V4L2_CID_CONTRAST:
value = saa7146_read(dev, BCS_CTRL);
c->value = 0x7f & (value >> 16);
- DEB_D(("V4L2_CID_CONTRAST: %d\n", c->value));
+ DEB_D("V4L2_CID_CONTRAST: %d\n", c->value);
break;
case V4L2_CID_SATURATION:
value = saa7146_read(dev, BCS_CTRL);
c->value = 0x7f & (value >> 0);
- DEB_D(("V4L2_CID_SATURATION: %d\n", c->value));
+ DEB_D("V4L2_CID_SATURATION: %d\n", c->value);
break;
case V4L2_CID_VFLIP:
c->value = vv->vflip;
- DEB_D(("V4L2_CID_VFLIP: %d\n", c->value));
+ DEB_D("V4L2_CID_VFLIP: %d\n", c->value);
break;
case V4L2_CID_HFLIP:
c->value = vv->hflip;
- DEB_D(("V4L2_CID_HFLIP: %d\n", c->value));
+ DEB_D("V4L2_CID_HFLIP: %d\n", c->value);
break;
default:
return -EINVAL;
@@ -641,7 +645,7 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
ctrl = ctrl_by_id(c->id);
if (NULL == ctrl) {
- DEB_D(("unknown control %d\n", c->id));
+ DEB_D("unknown control %d\n", c->id);
return -EINVAL;
}
@@ -686,14 +690,14 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
case V4L2_CID_HFLIP:
/* fixme: we can support changing VFLIP and HFLIP here... */
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
+ DEB_D("V4L2_CID_HFLIP while active capture\n");
return -EBUSY;
}
vv->hflip = c->value;
break;
case V4L2_CID_VFLIP:
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
+ DEB_D("V4L2_CID_VFLIP while active capture\n");
return -EBUSY;
}
vv->vflip = c->value;
@@ -748,7 +752,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
int maxw, maxh;
int calc_bpl;
- DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
+ DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
if (NULL == fmt)
@@ -777,7 +781,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
vv->last_field = V4L2_FIELD_INTERLACED;
break;
default:
- DEB_D(("no known field mode '%d'.\n", field));
+ DEB_D("no known field mode '%d'\n", field);
return -EINVAL;
}
@@ -796,8 +800,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
f->fmt.pix.bytesperline = calc_bpl;
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
- DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", f->fmt.pix.width,
- f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage));
+ DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",
+ f->fmt.pix.width, f->fmt.pix.height,
+ f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
return 0;
}
@@ -811,22 +816,23 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_f
enum v4l2_field field;
int maxw, maxh;
- DEB_EE(("dev:%p\n", dev));
+ DEB_EE("dev:%p\n", dev);
if (NULL == vv->ov_fb.base) {
- DEB_D(("no fb base set.\n"));
+ DEB_D("no fb base set\n");
return -EINVAL;
}
if (NULL == vv->ov_fmt) {
- DEB_D(("no fb fmt set.\n"));
+ DEB_D("no fb fmt set\n");
return -EINVAL;
}
if (win->w.width < 48 || win->w.height < 32) {
- DEB_D(("min width/height. (%d,%d)\n", win->w.width, win->w.height));
+ DEB_D("min width/height. (%d,%d)\n",
+ win->w.width, win->w.height);
return -EINVAL;
}
if (win->clipcount > 16) {
- DEB_D(("clipcount too big.\n"));
+ DEB_D("clipcount too big\n");
return -EINVAL;
}
@@ -848,7 +854,7 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_f
case V4L2_FIELD_INTERLACED:
break;
default:
- DEB_D(("no known field mode '%d'.\n", field));
+ DEB_D("no known field mode '%d'\n", field);
return -EINVAL;
}
@@ -868,16 +874,17 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_forma
struct saa7146_vv *vv = dev->vv_data;
int err;
- DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
+ DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- DEB_EE(("streaming capture is active\n"));
+ DEB_EE("streaming capture is active\n");
return -EBUSY;
}
err = vidioc_try_fmt_vid_cap(file, fh, f);
if (0 != err)
return err;
fh->video_fmt = f->fmt.pix;
- DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat));
+ DEB_EE("set to pixelformat '%4.4s'\n",
+ (char *)&fh->video_fmt.pixelformat);
return 0;
}
@@ -888,7 +895,7 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_f
struct saa7146_vv *vv = dev->vv_data;
int err;
- DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh));
+ DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh);
err = vidioc_try_fmt_vid_overlay(file, fh, f);
if (0 != err)
return err;
@@ -931,7 +938,7 @@ static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
if (e->index < 0 )
return -EINVAL;
if( e->index < dev->ext_vv_data->num_stds ) {
- DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));
+ DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
return 0;
}
@@ -946,10 +953,10 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
int found = 0;
int err, i;
- DEB_EE(("VIDIOC_S_STD\n"));
+ DEB_EE("VIDIOC_S_STD\n");
if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
- DEB_D(("cannot change video standard while streaming capture is active\n"));
+ DEB_D("cannot change video standard while streaming capture is active\n");
return -EBUSY;
}
@@ -957,7 +964,7 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
vv->ov_suspend = vv->video_fh;
err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
if (0 != err) {
- DEB_D(("suspending video failed. aborting\n"));
+ DEB_D("suspending video failed. aborting\n");
return err;
}
}
@@ -978,11 +985,11 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
}
if (!found) {
- DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
+ DEB_EE("VIDIOC_S_STD: standard not found\n");
return -EINVAL;
}
- DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name));
+ DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name);
return 0;
}
@@ -990,7 +997,7 @@ static int vidioc_overlay(struct file *file, void *fh, unsigned int on)
{
int err;
- DEB_D(("VIDIOC_OVERLAY on:%d\n", on));
+ DEB_D("VIDIOC_OVERLAY on:%d\n", on);
if (on)
err = saa7146_start_preview(fh);
else
@@ -1047,7 +1054,7 @@ static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type typ
struct saa7146_fh *fh = __fh;
int err;
- DEB_D(("VIDIOC_STREAMON, type:%d\n", type));
+ DEB_D("VIDIOC_STREAMON, type:%d\n", type);
err = video_begin(fh);
if (err)
@@ -1066,18 +1073,18 @@ static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type ty
struct saa7146_vv *vv = dev->vv_data;
int err;
- DEB_D(("VIDIOC_STREAMOFF, type:%d\n", type));
+ DEB_D("VIDIOC_STREAMOFF, type:%d\n", type);
/* ugly: we need to copy some checks from video_end(),
because videobuf_streamoff() relies on the capture running.
check and fix this */
if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
- DEB_S(("not capturing.\n"));
+ DEB_S("not capturing\n");
return 0;
}
if (vv->video_fh != fh) {
- DEB_S(("capturing, but in another open.\n"));
+ DEB_S("capturing, but in another open\n");
return -EBUSY;
}
@@ -1087,7 +1094,7 @@ static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type ty
else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
err = videobuf_streamoff(&fh->vbi_q);
if (0 != err) {
- DEB_D(("warning: videobuf_streamoff() failed.\n"));
+ DEB_D("warning: videobuf_streamoff() failed\n");
video_end(fh, file);
} else {
err = video_end(fh, file);
@@ -1174,25 +1181,27 @@ static int buffer_prepare(struct videobuf_queue *q,
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
int size,err = 0;
- DEB_CAP(("vbuf:%p\n",vb));
+ DEB_CAP("vbuf:%p\n", vb);
/* sanity checks */
if (fh->video_fmt.width < 48 ||
fh->video_fmt.height < 32 ||
fh->video_fmt.width > vv->standard->h_max_out ||
fh->video_fmt.height > vv->standard->v_max_out) {
- DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
+ DEB_D("w (%d) / h (%d) out of bounds\n",
+ fh->video_fmt.width, fh->video_fmt.height);
return -EINVAL;
}
size = fh->video_fmt.sizeimage;
if (0 != buf->vb.baddr && buf->vb.bsize < size) {
- DEB_D(("size mismatch.\n"));
+ DEB_D("size mismatch\n");
return -EINVAL;
}
- DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
- fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));
+ DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
+ fh->video_fmt.width, fh->video_fmt.height,
+ size, v4l2_field_names[fh->video_fmt.field]);
if (buf->vb.width != fh->video_fmt.width ||
buf->vb.bytesperline != fh->video_fmt.bytesperline ||
buf->vb.height != fh->video_fmt.height ||
@@ -1238,7 +1247,7 @@ static int buffer_prepare(struct videobuf_queue *q,
return 0;
oops:
- DEB_D(("error out.\n"));
+ DEB_D("error out\n");
saa7146_dma_free(dev,q,buf);
return err;
@@ -1259,7 +1268,7 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned
*count = (max_memory*1048576) / *size;
}
- DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));
+ DEB_CAP("%d buffers, %d bytes each\n", *count, *size);
return 0;
}
@@ -1272,7 +1281,7 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_vv *vv = dev->vv_data;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
- DEB_CAP(("vbuf:%p\n",vb));
+ DEB_CAP("vbuf:%p\n", vb);
saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
}
@@ -1283,7 +1292,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_dev *dev = fh->dev;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
- DEB_CAP(("vbuf:%p\n",vb));
+ DEB_CAP("vbuf:%p\n", vb);
saa7146_dma_free(dev,q,buf);
@@ -1347,18 +1356,14 @@ static void video_close(struct saa7146_dev *dev, struct file *file)
struct saa7146_fh *fh = file->private_data;
struct saa7146_vv *vv = dev->vv_data;
struct videobuf_queue *q = &fh->video_q;
- int err;
- if (IS_CAPTURE_ACTIVE(fh) != 0) {
- err = video_end(fh, file);
- } else if (IS_OVERLAY_ACTIVE(fh) != 0) {
- err = saa7146_stop_preview(fh);
- }
+ if (IS_CAPTURE_ACTIVE(fh) != 0)
+ video_end(fh, file);
+ else if (IS_OVERLAY_ACTIVE(fh) != 0)
+ saa7146_stop_preview(fh);
videobuf_stop(q);
-
/* hmm, why is this function declared void? */
- /* return err */
}
@@ -1368,7 +1373,7 @@ static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
struct saa7146_dmaqueue *q = &vv->video_q;
spin_lock(&dev->slock);
- DEB_CAP(("called.\n"));
+ DEB_CAP("called\n");
/* only finish the buffer if we have one... */
if( NULL != q->curr ) {
@@ -1386,15 +1391,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo
struct saa7146_vv *vv = dev->vv_data;
ssize_t ret = 0;
- DEB_EE(("called.\n"));
+ DEB_EE("called\n");
if ((vv->video_status & STATUS_CAPTURE) != 0) {
/* fixme: should we allow read() captures while streaming capture? */
if (vv->video_fh == fh) {
- DEB_S(("already capturing.\n"));
+ DEB_S("already capturing\n");
return -EBUSY;
}
- DEB_S(("already capturing in another open.\n"));
+ DEB_S("already capturing in another open\n");
return -EBUSY;
}
diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile
index 20d24fca2cfb..196c12a55f9a 100644
--- a/drivers/media/common/tuners/Makefile
+++ b/drivers/media/common/tuners/Makefile
@@ -28,5 +28,5 @@ obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/common/tuners/mt20xx.c b/drivers/media/common/tuners/mt20xx.c
index d0e70e10a717..0e74e97e0d1a 100644
--- a/drivers/media/common/tuners/mt20xx.c
+++ b/drivers/media/common/tuners/mt20xx.c
@@ -430,11 +430,10 @@ static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna)
{
struct microtune_priv *priv = fe->tuner_priv;
unsigned char buf[2];
- int ret;
buf[0] = 6;
buf[1] = antenna ? 0x11 : 0x10;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
}
@@ -574,21 +573,20 @@ static int mt2050_init(struct dvb_frontend *fe)
{
struct microtune_priv *priv = fe->tuner_priv;
unsigned char buf[2];
- int ret;
- buf[0]=6;
- buf[1]=0x10;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // power
+ buf[0] = 6;
+ buf[1] = 0x10;
+ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* power */
- buf[0]=0x0f;
- buf[1]=0x0f;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo
+ buf[0] = 0x0f;
+ buf[1] = 0x0f;
+ tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* m1lo */
- buf[0]=0x0d;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
- tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
+ buf[0] = 0x0d;
+ tuner_i2c_xfer_send(&priv->i2c_props, buf, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
- tuner_dbg("mt2050: sro is %x\n",buf[0]);
+ tuner_dbg("mt2050: sro is %x\n", buf[0]);
memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c
index 56fe75c94deb..54be9e6faaaf 100644
--- a/drivers/media/common/tuners/mxl5005s.c
+++ b/drivers/media/common/tuners/mxl5005s.c
@@ -309,7 +309,6 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val);
static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
u8 *RegVal, int *count);
-static u32 MXL_GetXtalInt(u32 Xtal_Freq);
static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq);
static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe);
static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe);
@@ -2307,14 +2306,6 @@ static u16 MXL_IFSynthInit(struct dvb_frontend *fe)
return status ;
}
-static u32 MXL_GetXtalInt(u32 Xtal_Freq)
-{
- if ((Xtal_Freq % 1000000) == 0)
- return (Xtal_Freq / 10000);
- else
- return (((Xtal_Freq / 1000000) + 1)*100);
-}
-
static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
{
struct mxl5005s_state *state = fe->tuner_priv;
@@ -2324,13 +2315,10 @@ static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
u32 Kdbl_RF = 2;
u32 tg_divval;
u32 tg_lo;
- u32 Xtal_Int;
u32 Fref_TG;
u32 Fvco;
- Xtal_Int = MXL_GetXtalInt(state->Fxtal);
-
state->RF_IN = RF_Freq;
MXL_SynthRFTGLO_Calc(fe);
@@ -2779,6 +2767,16 @@ static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
tg_lo = (((Fmax/10 - Fvco)/100)*32) / ((Fmax-Fmin)/1000)+8;
/* below equation is same as above but much harder to debug.
+ *
+ * static u32 MXL_GetXtalInt(u32 Xtal_Freq)
+ * {
+ * if ((Xtal_Freq % 1000000) == 0)
+ * return (Xtal_Freq / 10000);
+ * else
+ * return (((Xtal_Freq / 1000000) + 1)*100);
+ * }
+ *
+ * u32 Xtal_Int = MXL_GetXtalInt(state->Fxtal);
* tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) -
* ((state->TG_LO/10000)*divider_val *
* (state->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 *
diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/common/tuners/tda18212.c
index 1f1db20d46b1..e29cc2bc113a 100644
--- a/drivers/media/common/tuners/tda18212.c
+++ b/drivers/media/common/tuners/tda18212.c
@@ -18,7 +18,20 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "tda18212_priv.h"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "tda18212.h"
+
+struct tda18212_priv {
+ struct tda18212_config *cfg;
+ struct i2c_adapter *i2c;
+};
+
+#define dbg(fmt, arg...) \
+do { \
+ if (debug) \
+ pr_info("%s: " fmt, __func__, ##arg); \
+} while (0)
static int debug;
module_param(debug, int, 0644);
@@ -46,7 +59,8 @@ static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
if (ret == 1) {
ret = 0;
} else {
- warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+ pr_warn("i2c wr failed ret:%d reg:%02x len:%d\n",
+ ret, reg, len);
ret = -EREMOTEIO;
}
return ret;
@@ -77,7 +91,8 @@ static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
memcpy(val, buf, len);
ret = 0;
} else {
- warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+ pr_warn("i2c rd failed ret:%d reg:%02x len:%d\n",
+ ret, reg, len);
ret = -EREMOTEIO;
}
@@ -129,8 +144,8 @@ static int tda18212_set_params(struct dvb_frontend *fe,
{ 0x92, 0x53, 0x03 }, /* DVB-C */
};
- dbg("%s: delsys=%d RF=%d BW=%d", __func__,
- c->delivery_system, c->frequency, c->bandwidth_hz);
+ dbg("delsys=%d RF=%d BW=%d\n",
+ c->delivery_system, c->frequency, c->bandwidth_hz);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
@@ -196,7 +211,7 @@ exit:
return ret;
error:
- dbg("%s: failed:%d", __func__, ret);
+ dbg("failed:%d\n", ret);
goto exit;
}
@@ -245,13 +260,13 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
- dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
+ dbg("ret:%d chip ID:%02x\n", ret, val);
if (ret || val != 0xc7) {
kfree(priv);
return NULL;
}
- info("NXP TDA18212HN successfully identified.");
+ pr_info("NXP TDA18212HN successfully identified\n");
memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
sizeof(struct dvb_tuner_ops));
diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c
index aae40e52af5b..39c645787b62 100644
--- a/drivers/media/common/tuners/tda18271-common.c
+++ b/drivers/media/common/tuners/tda18271-common.c
@@ -676,10 +676,28 @@ fail:
return ret;
}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
+int _tda_printk(struct tda18271_priv *state, const char *level,
+ const char *func, const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ int rtn;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ if (state)
+ rtn = printk("%s%s: [%d-%04x|%c] %pV",
+ level, func, i2c_adapter_id(state->i2c_props.adap),
+ state->i2c_props.addr,
+ (state->role == TDA18271_MASTER) ? 'M' : 'S',
+ &vaf);
+ else
+ rtn = printk("%s%s: %pV", level, func, &vaf);
+
+ va_end(args);
+
+ return rtn;
+}
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
index 57022e88e338..63cc4004e211 100644
--- a/drivers/media/common/tuners/tda18271-fe.c
+++ b/drivers/media/common/tuners/tda18271-fe.c
@@ -1230,7 +1230,7 @@ static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg)
return 0;
}
-static struct dvb_tuner_ops tda18271_tuner_ops = {
+static const struct dvb_tuner_ops tda18271_tuner_ops = {
.info = {
.name = "NXP TDA18271HD",
.frequency_min = 45000000,
diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h
index 9589ab0576d2..94340f47562b 100644
--- a/drivers/media/common/tuners/tda18271-priv.h
+++ b/drivers/media/common/tuners/tda18271-priv.h
@@ -136,29 +136,26 @@ extern int tda18271_debug;
#define DBG_ADV 8
#define DBG_CAL 16
-#define tda_printk(st, kern, fmt, arg...) do {\
- if (st) { \
- struct tda18271_priv *state = st; \
- printk(kern "%s: [%d-%04x|%s] " fmt, __func__, \
- i2c_adapter_id(state->i2c_props.adap), \
- state->i2c_props.addr, \
- (state->role == TDA18271_MASTER) \
- ? "M" : "S", ##arg); \
- } else \
- printk(kern "%s: " fmt, __func__, ##arg); \
+__attribute__((format(printf, 4, 5)))
+int _tda_printk(struct tda18271_priv *state, const char *level,
+ const char *func, const char *fmt, ...);
+
+#define tda_printk(st, lvl, fmt, arg...) \
+ _tda_printk(st, lvl, __func__, fmt, ##arg)
+
+#define tda_dprintk(st, lvl, fmt, arg...) \
+do { \
+ if (tda18271_debug & lvl) \
+ tda_printk(st, KERN_DEBUG, fmt, ##arg); \
} while (0)
-#define tda_dprintk(st, lvl, fmt, arg...) do {\
- if (tda18271_debug & lvl) \
- tda_printk(st, KERN_DEBUG, fmt, ##arg); } while (0)
-
-#define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
-#define tda_warn(fmt, arg...) tda_printk(priv, KERN_WARNING, fmt, ##arg)
-#define tda_err(fmt, arg...) tda_printk(priv, KERN_ERR, fmt, ##arg)
-#define tda_dbg(fmt, arg...) tda_dprintk(priv, DBG_INFO, fmt, ##arg)
-#define tda_map(fmt, arg...) tda_dprintk(priv, DBG_MAP, fmt, ##arg)
-#define tda_reg(fmt, arg...) tda_dprintk(priv, DBG_REG, fmt, ##arg)
-#define tda_cal(fmt, arg...) tda_dprintk(priv, DBG_CAL, fmt, ##arg)
+#define tda_info(fmt, arg...) pr_info(fmt, ##arg)
+#define tda_warn(fmt, arg...) tda_printk(priv, KERN_WARNING, fmt, ##arg)
+#define tda_err(fmt, arg...) tda_printk(priv, KERN_ERR, fmt, ##arg)
+#define tda_dbg(fmt, arg...) tda_dprintk(priv, DBG_INFO, fmt, ##arg)
+#define tda_map(fmt, arg...) tda_dprintk(priv, DBG_MAP, fmt, ##arg)
+#define tda_reg(fmt, arg...) tda_dprintk(priv, DBG_REG, fmt, ##arg)
+#define tda_cal(fmt, arg...) tda_dprintk(priv, DBG_CAL, fmt, ##arg)
#define tda_fail(ret) \
({ \
diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c
index b21b6ea68b25..e0d5b43772b8 100644
--- a/drivers/media/common/tuners/tda827x.c
+++ b/drivers/media/common/tuners/tda827x.c
@@ -176,7 +176,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
if_freq = 5000000;
break;
}
- tuner_freq = params->frequency + if_freq;
+ tuner_freq = params->frequency;
i = 0;
while (tda827x_table[i].lomax < tuner_freq) {
@@ -185,6 +185,8 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
i++;
}
+ tuner_freq += if_freq;
+
N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
buf[0] = 0;
buf[1] = (N>>8) | 0x40;
@@ -540,7 +542,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
if_freq = 5000000;
break;
}
- tuner_freq = params->frequency + if_freq;
+ tuner_freq = params->frequency;
if (fe->ops.info.type == FE_QAM) {
dprintk("%s select tda827xa_dvbc\n", __func__);
@@ -554,6 +556,8 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
i++;
}
+ tuner_freq += if_freq;
+
N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
buf[0] = 0; // subaddress
buf[1] = N >> 8;
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
index 16fba6b59616..3acbaa04e1b3 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -614,6 +614,13 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
p += len;
size -= len;
}
+
+ /* silently fail if the frontend doesn't support I2C flush */
+ rc = do_tuner_callback(fe, XC2028_I2C_FLUSH, 0);
+ if ((rc < 0) && (rc != -EINVAL)) {
+ tuner_err("error executing flush: %d\n", rc);
+ return rc;
+ }
}
return 0;
}
@@ -933,11 +940,16 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
* that xc2028 will be in a safe state.
* Maybe this might also be needed for DTV.
*/
- if (new_type == V4L2_TUNER_ANALOG_TV) {
+ switch (new_type) {
+ case V4L2_TUNER_ANALOG_TV:
rc = send_seq(priv, {0x00, 0x00});
- /* Analog modes require offset = 0 */
- } else {
+ /* Analog mode requires offset = 0 */
+ break;
+ case V4L2_TUNER_RADIO:
+ /* Radio mode requires offset = 0 */
+ break;
+ case V4L2_TUNER_DIGITAL_TV:
/*
* Digital modes require an offset to adjust to the
* proper frequency. The offset depends on what
diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h
index 9778c96a5006..9ebfb2d0ff14 100644
--- a/drivers/media/common/tuners/tuner-xc2028.h
+++ b/drivers/media/common/tuners/tuner-xc2028.h
@@ -54,6 +54,7 @@ struct xc2028_config {
/* xc2028 commands for callback */
#define XC2028_TUNER_RESET 0
#define XC2028_RESET_CLK 1
+#define XC2028_I2C_FLUSH 2
#if defined(CONFIG_MEDIA_TUNER_XC2028) || (defined(CONFIG_MEDIA_TUNER_XC2028_MODULE) && defined(MODULE))
extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
index b97cf7208a18..3d04a8dba99e 100644
--- a/drivers/media/dvb/b2c2/Makefile
+++ b/drivers/media/dvb/b2c2/Makefile
@@ -12,5 +12,5 @@ obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
b2c2-flexcop-usb-objs = flexcop-usb.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile
index d98f1d49ffa8..0713b3af2050 100644
--- a/drivers/media/dvb/bt8xx/Makefile
+++ b/drivers/media/dvb/bt8xx/Makefile
@@ -1,6 +1,6 @@
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video/bt8xx
+ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/ddbridge/Makefile b/drivers/media/dvb/ddbridge/Makefile
index de4fe193c3ef..cf7214edf65f 100644
--- a/drivers/media/dvb/ddbridge/Makefile
+++ b/drivers/media/dvb/ddbridge/Makefile
@@ -6,9 +6,9 @@ ddbridge-objs := ddbridge-core.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
# For the staging CI driver cxd2099
-EXTRA_CFLAGS += -Idrivers/staging/cxd2099/
+ccflags-y += -Idrivers/staging/cxd2099/
diff --git a/drivers/media/dvb/ddbridge/ddbridge-core.c b/drivers/media/dvb/ddbridge/ddbridge-core.c
index 573d540f213e..ba9a643b9c6a 100644
--- a/drivers/media/dvb/ddbridge/ddbridge-core.c
+++ b/drivers/media/dvb/ddbridge/ddbridge-core.c
@@ -507,15 +507,14 @@ static u32 ddb_input_avail(struct ddb_input *input)
return 0;
}
-static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
+static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
{
struct ddb *dev = input->port->dev;
u32 left = count;
- u32 idx, off, free, stat = input->stat;
+ u32 idx, free, stat = input->stat;
int ret;
idx = (stat >> 11) & 0x1f;
- off = (stat & 0x7ff) << 7;
while (left) {
if (input->cbuf == idx)
@@ -525,6 +524,8 @@ static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
free = left;
ret = copy_to_user(buf, input->vbuf[input->cbuf] +
input->coff, free);
+ if (ret)
+ return -EFAULT;
input->coff += free;
if (input->coff == input->dma_buf_size) {
input->coff = 0;
@@ -939,6 +940,8 @@ static ssize_t ts_read(struct file *file, char *buf,
break;
}
read = ddb_input_read(input, buf, left);
+ if (read < 0)
+ return read;
left -= read;
buf += read;
}
@@ -1438,7 +1441,7 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct ddb *dev = file->private_data;
void *parg = (void *)arg;
- int res = -EFAULT;
+ int res;
switch (cmd) {
case IOCTL_DDB_FLASHIO:
@@ -1447,29 +1450,29 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
u8 *rbuf, *wbuf;
if (copy_from_user(&fio, parg, sizeof(fio)))
- break;
- if (fio.write_len + fio.read_len > 1028) {
- printk(KERN_ERR "IOBUF too small\n");
- return -ENOMEM;
- }
+ return -EFAULT;
+
+ if (fio.write_len > 1028 || fio.read_len > 1028)
+ return -EINVAL;
+ if (fio.write_len + fio.read_len > 1028)
+ return -EINVAL;
+
wbuf = &dev->iobuf[0];
- if (!wbuf)
- return -ENOMEM;
rbuf = wbuf + fio.write_len;
- if (copy_from_user(wbuf, fio.write_buf, fio.write_len)) {
- vfree(wbuf);
- break;
- }
- res = flashio(dev, wbuf, fio.write_len,
- rbuf, fio.read_len);
+
+ if (copy_from_user(wbuf, fio.write_buf, fio.write_len))
+ return -EFAULT;
+ res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len);
+ if (res)
+ return res;
if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
- res = -EFAULT;
+ return -EFAULT;
break;
}
default:
- break;
+ return -ENOTTY;
}
- return res;
+ return 0;
}
static const struct file_operations ddb_fops = {
diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile
index 8ac28b0546af..95a008b71fe5 100644
--- a/drivers/media/dvb/dm1105/Makefile
+++ b/drivers/media/dvb/dm1105/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_DM1105) += dm1105.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index efe9c30605e8..2c0acdb4d811 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -149,30 +149,25 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
dprintk ("%s\n", __func__);
- if (mutex_lock_interruptible (&events->mtx))
- return;
+ if ((status & FE_HAS_LOCK) && fe->ops.get_frontend)
+ fe->ops.get_frontend(fe, &fepriv->parameters_out);
- wp = (events->eventw + 1) % MAX_EVENT;
+ mutex_lock(&events->mtx);
+ wp = (events->eventw + 1) % MAX_EVENT;
if (wp == events->eventr) {
events->overflow = 1;
events->eventr = (events->eventr + 1) % MAX_EVENT;
}
e = &events->events[events->eventw];
-
- if (status & FE_HAS_LOCK)
- if (fe->ops.get_frontend)
- fe->ops.get_frontend(fe, &fepriv->parameters_out);
-
+ e->status = status;
e->parameters = fepriv->parameters_out;
events->eventw = wp;
mutex_unlock(&events->mtx);
- e->status = status;
-
wake_up_interruptible (&events->wait_queue);
}
@@ -207,19 +202,24 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
return ret;
}
- if (mutex_lock_interruptible (&events->mtx))
- return -ERESTARTSYS;
-
- memcpy (event, &events->events[events->eventr],
- sizeof(struct dvb_frontend_event));
-
+ mutex_lock(&events->mtx);
+ *event = events->events[events->eventr];
events->eventr = (events->eventr + 1) % MAX_EVENT;
-
mutex_unlock(&events->mtx);
return 0;
}
+static void dvb_frontend_clear_events(struct dvb_frontend *fe)
+{
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ struct dvb_fe_events *events = &fepriv->events;
+
+ mutex_lock(&events->mtx);
+ events->eventr = events->eventw;
+ mutex_unlock(&events->mtx);
+}
+
static void dvb_frontend_init(struct dvb_frontend *fe)
{
dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n",
@@ -537,7 +537,6 @@ static int dvb_frontend_thread(void *data)
{
struct dvb_frontend *fe = data;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
- unsigned long timeout;
fe_status_t s;
enum dvbfe_algo algo;
@@ -558,7 +557,7 @@ static int dvb_frontend_thread(void *data)
while (1) {
up(&fepriv->sem); /* is locked when we enter the thread... */
restart:
- timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
+ wait_event_interruptible_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe) || kthread_should_stop()
|| freezing(current),
fepriv->delay);
@@ -577,12 +576,10 @@ restart:
if (fepriv->reinitialise) {
dvb_frontend_init(fe);
- if (fepriv->tone != -1) {
+ if (fe->ops.set_tone && fepriv->tone != -1)
fe->ops.set_tone(fe, fepriv->tone);
- }
- if (fepriv->voltage != -1) {
+ if (fe->ops.set_voltage && fepriv->voltage != -1)
fe->ops.set_voltage(fe, fepriv->voltage);
- }
fepriv->reinitialise = 0;
}
@@ -1019,6 +1016,29 @@ static int is_legacy_delivery_system(fe_delivery_system_t s)
return 0;
}
+/* Initialize the cache with some default values derived from the
+ * legacy frontend_info structure.
+ */
+static void dtv_property_cache_init(struct dvb_frontend *fe,
+ struct dtv_frontend_properties *c)
+{
+ switch (fe->ops.info.type) {
+ case FE_QPSK:
+ c->modulation = QPSK; /* implied for DVB-S in legacy API */
+ c->rolloff = ROLLOFF_35;/* implied for DVB-S */
+ c->delivery_system = SYS_DVBS;
+ break;
+ case FE_QAM:
+ c->delivery_system = SYS_DVBC_ANNEX_AC;
+ break;
+ case FE_OFDM:
+ c->delivery_system = SYS_DVBT;
+ break;
+ case FE_ATSC:
+ break;
+ }
+}
+
/* Synchronise the legacy tuning parameters into the cache, so that demodulator
* drivers can use a single set_frontend tuning function, regardless of whether
* it's being used for the legacy or new API, reducing code and complexity.
@@ -1032,17 +1052,13 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
switch (fe->ops.info.type) {
case FE_QPSK:
- c->modulation = QPSK; /* implied for DVB-S in legacy API */
- c->rolloff = ROLLOFF_35;/* implied for DVB-S */
c->symbol_rate = p->u.qpsk.symbol_rate;
c->fec_inner = p->u.qpsk.fec_inner;
- c->delivery_system = SYS_DVBS;
break;
case FE_QAM:
c->symbol_rate = p->u.qam.symbol_rate;
c->fec_inner = p->u.qam.fec_inner;
c->modulation = p->u.qam.modulation;
- c->delivery_system = SYS_DVBC_ANNEX_AC;
break;
case FE_OFDM:
if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
@@ -1060,7 +1076,6 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
c->transmission_mode = p->u.ofdm.transmission_mode;
c->guard_interval = p->u.ofdm.guard_interval;
c->hierarchy = p->u.ofdm.hierarchy_information;
- c->delivery_system = SYS_DVBT;
break;
case FE_ATSC:
c->modulation = p->u.vsb.modulation;
@@ -1132,16 +1147,13 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
p->frequency = c->frequency;
p->inversion = c->inversion;
- switch(c->modulation) {
- case PSK_8:
- case APSK_16:
- case APSK_32:
- case QPSK:
+ if (c->delivery_system == SYS_DSS ||
+ c->delivery_system == SYS_DVBS ||
+ c->delivery_system == SYS_DVBS2 ||
+ c->delivery_system == SYS_ISDBS ||
+ c->delivery_system == SYS_TURBO) {
p->u.qpsk.symbol_rate = c->symbol_rate;
p->u.qpsk.fec_inner = c->fec_inner;
- break;
- default:
- break;
}
/* Fake out a generic DVB-T request so we pass validation in the ioctl */
@@ -1824,9 +1836,17 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
memcpy (&fepriv->parameters_in, parg,
sizeof (struct dvb_frontend_parameters));
+ dtv_property_cache_init(fe, c);
dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
}
+ /*
+ * Initialize output parameters to match the values given by
+ * the user. FE_SET_FRONTEND triggers an initial frontend event
+ * with status = 0, which copies output parameters to userspace.
+ */
+ fepriv->parameters_out = fepriv->parameters_in;
+
memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
memcpy(&fetunesettings.parameters, parg,
sizeof (struct dvb_frontend_parameters));
@@ -1884,8 +1904,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
/* Request the search algorithm to search */
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
- dvb_frontend_wakeup(fe);
+ dvb_frontend_clear_events(fe);
dvb_frontend_add_event(fe, 0);
+ dvb_frontend_wakeup(fe);
fepriv->status = 0;
err = 0;
break;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 5590eb6eb408..67bbfa728016 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -209,6 +209,7 @@ struct dvb_tuner_ops {
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+ int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
#define TUNER_STATUS_LOCKED 1
#define TUNER_STATUS_STEREO 2
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 51752a9ef7a4..93d9869e0f15 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -1230,7 +1230,7 @@ static const struct net_device_ops dvb_netdev_ops = {
.ndo_open = dvb_net_open,
.ndo_stop = dvb_net_stop,
.ndo_start_xmit = dvb_net_tx,
- .ndo_set_multicast_list = dvb_net_set_multicast_list,
+ .ndo_set_rx_mode = dvb_net_set_multicast_list,
.ndo_set_mac_address = dvb_net_set_mac,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 5d73dec8ac07..58257165761e 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -258,6 +258,19 @@ config DVB_USB_AF9005_REMOTE
Say Y here to support the default remote control decoding for the
Afatech AF9005 based receiver.
+config DVB_USB_PCTV452E
+ tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600"
+ depends on DVB_USB
+ select TTPCI_EEPROM
+ select DVB_LNBP22 if !DVB_FE_CUSTOMISE
+ select DVB_STB0899 if !DVB_FE_CUSTOMISE
+ select DVB_STB6100 if !DVB_FE_CUSTOMISE
+ help
+ Support for external USB adapter designed by Pinnacle,
+ shipped under the brand name 'PCTV HDTV Pro USB'.
+ Also supports TT Connect S2-3600/3650 cards.
+ Say Y if you own such a device and want to use it.
+
config DVB_USB_DW2102
tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support"
depends on DVB_USB
@@ -374,3 +387,18 @@ config DVB_USB_TECHNISAT_USB2
select DVB_STV6110x if !DVB_FE_CUSTOMISE
help
Say Y here to support the Technisat USB2 DVB-S/S2 device
+
+config DVB_USB_IT913X
+ tristate "it913x driver"
+ depends on DVB_USB
+ select DVB_IT913X_FE
+ help
+ Say Y here to support the it913x device
+
+config DVB_USB_MXL111SF
+ tristate "MxL111SF DTV USB2.0 support"
+ depends on DVB_USB
+ select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
+ select VIDEO_TVEEPROM
+ help
+ Say Y here to support the MxL111SF USB2.0 DTV receiver.
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 4bac13da0c39..7d0710bb1978 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -64,6 +64,9 @@ obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
dvb-usb-anysee-objs = anysee.o
obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
+dvb-usb-pctv452e-objs = pctv452e.o
+obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o
+
dvb-usb-dw2102-objs = dw2102.o
obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
@@ -94,7 +97,15 @@ obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o
dvb-usb-technisat-usb2-objs = technisat-usb2.o
obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+dvb-usb-it913x-objs := it913x.o
+obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o
+
+dvb-usb-mxl111sf-objs = mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o mxl111sf-gpio.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
+
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
# due to tuner-xc3028
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/common/tuners
+EXTRA_CFLAGS += -Idrivers/media/dvb/ttpci
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index b95a95e17840..2aef3c89e9fa 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -127,6 +127,8 @@ static struct dvb_usb_device_properties a800_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.streaming_ctrl = dibusb2_0_streaming_ctrl,
@@ -147,7 +149,7 @@ static struct dvb_usb_device_properties a800_properties = {
}
}
},
-
+ }},
.size_of_priv = sizeof(struct dibusb_state),
},
},
diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c
index 6ad94745bbdd..3263e9749d09 100644
--- a/drivers/media/dvb/dvb-usb/af9005-fe.c
+++ b/drivers/media/dvb/dvb-usb/af9005-fe.c
@@ -63,11 +63,9 @@ static int af9005_write_word_agc(struct dvb_usb_device *d, u16 reghi,
u16 reglo, u8 pos, u8 len, u16 value)
{
int ret;
- u8 temp;
if ((ret = af9005_write_ofdm_register(d, reglo, (u8) (value & 0xff))))
return ret;
- temp = (u8) ((value & 0x0300) >> 8);
return af9005_write_register_bits(d, reghi, pos, len,
(u8) ((value & 0x300) >> 8));
}
diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c
index c3bc64ed405c..7e3961d0db6b 100644
--- a/drivers/media/dvb/dvb-usb/af9005-remote.c
+++ b/drivers/media/dvb/dvb-usb/af9005-remote.c
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * see Documentation/dvb/REDME.dvb-usb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
*/
#include "af9005.h"
/* debug */
diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c
index 51f6439dcfd5..bd51a764351b 100644
--- a/drivers/media/dvb/dvb-usb/af9005.c
+++ b/drivers/media/dvb/dvb-usb/af9005.c
@@ -19,7 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * see Documentation/dvb/REDME.dvb-usb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
*/
#include "af9005.h"
@@ -815,7 +815,7 @@ static int af9005_frontend_attach(struct dvb_usb_adapter *adap)
debug_dump(buf, 8, printk);
}
}
- adap->fe = af9005_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = af9005_fe_attach(adap->dev);
return 0;
}
@@ -999,6 +999,8 @@ static struct dvb_usb_device_properties af9005_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps =
DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1018,6 +1020,7 @@ static struct dvb_usb_device_properties af9005_properties = {
}
}
},
+ }},
}
},
.power_ctrl = af9005_power_ctrl,
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index d7ad05fc383b..c6c275bac08e 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -744,29 +744,31 @@ static const struct af9015_rc_setup af9015_rc_setup_hashes[] = {
};
static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
- { (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_RC,
+ { (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_RC,
RC_MAP_TERRATEC_SLIM_2 },
- { (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
+ { (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
RC_MAP_TERRATEC_SLIM },
- { (USB_VID_VISIONPLUS << 16) + USB_PID_AZUREWAVE_AD_TU700,
+ { (USB_VID_VISIONPLUS << 16) | USB_PID_AZUREWAVE_AD_TU700,
RC_MAP_AZUREWAVE_AD_TU700 },
- { (USB_VID_VISIONPLUS << 16) + USB_PID_TINYTWIN,
+ { (USB_VID_VISIONPLUS << 16) | USB_PID_TINYTWIN,
RC_MAP_AZUREWAVE_AD_TU700 },
- { (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGI_VOX_MINI_III,
+ { (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGI_VOX_MINI_III,
RC_MAP_MSI_DIGIVOX_III },
- { (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGIVOX_DUO,
+ { (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGIVOX_DUO,
RC_MAP_MSI_DIGIVOX_III },
- { (USB_VID_LEADTEK << 16) + USB_PID_WINFAST_DTV_DONGLE_GOLD,
+ { (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV_DONGLE_GOLD,
RC_MAP_LEADTEK_Y04G0051 },
- { (USB_VID_AVERMEDIA << 16) + USB_PID_AVERMEDIA_VOLAR_X,
+ { (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV2000DS,
+ RC_MAP_LEADTEK_Y04G0051 },
+ { (USB_VID_AVERMEDIA << 16) | USB_PID_AVERMEDIA_VOLAR_X,
RC_MAP_AVERMEDIA_M135A },
- { (USB_VID_AFATECH << 16) + USB_PID_TREKSTOR_DVBT,
+ { (USB_VID_AFATECH << 16) | USB_PID_TREKSTOR_DVBT,
RC_MAP_TREKSTOR },
- { (USB_VID_KWORLD_2 << 16) + USB_PID_TINYTWIN_2,
+ { (USB_VID_KWORLD_2 << 16) | USB_PID_TINYTWIN_2,
RC_MAP_DIGITALNOW_TINYTWIN },
- { (USB_VID_GTEK << 16) + USB_PID_TINYTWIN_3,
+ { (USB_VID_GTEK << 16) | USB_PID_TINYTWIN_3,
RC_MAP_DIGITALNOW_TINYTWIN },
- { (USB_VID_KWORLD_2 << 16) + USB_PID_SVEON_STV22,
+ { (USB_VID_KWORLD_2 << 16) | USB_PID_SVEON_STV22,
RC_MAP_MSI_DIGIVOX_III },
{ }
};
@@ -859,13 +861,13 @@ static int af9015_read_config(struct usb_device *udev)
for (i = 0; i < af9015_properties_count; i++) {
/* USB1.1 set smaller buffersize and disable 2nd adapter */
if (udev->speed == USB_SPEED_FULL) {
- af9015_properties[i].adapter[0].stream.u.bulk.buffersize
+ af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
= TS_USB11_FRAME_SIZE;
/* disable 2nd adapter because we don't have
PID-filters */
af9015_config.dual_mode = 0;
} else {
- af9015_properties[i].adapter[0].stream.u.bulk.buffersize
+ af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
= TS_USB20_FRAME_SIZE;
}
}
@@ -1111,10 +1113,10 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
}
/* attach demodulator */
- adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
+ adap->fe_adap[0].fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
&adap->dev->i2c_adap);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static struct mt2060_config af9015_mt2060_config = {
@@ -1188,49 +1190,49 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
switch (af9015_af9013_config[adap->id].tuner) {
case AF9013_TUNER_MT2060:
case AF9013_TUNER_MT2060_2:
- ret = dvb_attach(mt2060_attach, adap->fe, &adap->dev->i2c_adap,
+ ret = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&af9015_mt2060_config,
af9015_config.mt2060_if1[adap->id])
== NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_QT1010:
case AF9013_TUNER_QT1010A:
- ret = dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
+ ret = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&af9015_qt1010_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_TDA18271:
- ret = dvb_attach(tda18271_attach, adap->fe, 0xc0,
+ ret = dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0xc0,
&adap->dev->i2c_adap,
&af9015_tda18271_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_TDA18218:
- ret = dvb_attach(tda18218_attach, adap->fe,
+ ret = dvb_attach(tda18218_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap,
&af9015_tda18218_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_MXL5003D:
- ret = dvb_attach(mxl5005s_attach, adap->fe,
+ ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap,
&af9015_mxl5003_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_MXL5005D:
case AF9013_TUNER_MXL5005R:
- ret = dvb_attach(mxl5005s_attach, adap->fe,
+ ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap,
&af9015_mxl5005_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_ENV77H11D5:
- ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
+ ret = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0xc0,
&adap->dev->i2c_adap,
DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_MC44S803:
- ret = dvb_attach(mc44s803_attach, adap->fe,
+ ret = dvb_attach(mc44s803_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap,
&af9015_mc44s803_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_MXL5007T:
- ret = dvb_attach(mxl5007t_attach, adap->fe,
+ ret = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap,
0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
break;
@@ -1304,6 +1306,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1319,8 +1323,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.count = 6,
.endpoint = 0x84,
},
+ }},
},
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach =
af9015_af9013_frontend_attach,
.tuner_attach = af9015_tuner_attach,
@@ -1335,6 +1342,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
}
}
},
+ }},
}
},
@@ -1432,6 +1440,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1447,8 +1457,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.count = 6,
.endpoint = 0x84,
},
+ }},
},
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach =
af9015_af9013_frontend_attach,
.tuner_attach = af9015_tuner_attach,
@@ -1463,6 +1476,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
}
}
},
+ }},
}
},
@@ -1549,6 +1563,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1564,8 +1580,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.count = 6,
.endpoint = 0x84,
},
+ }},
},
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach =
af9015_af9013_frontend_attach,
.tuner_attach = af9015_tuner_attach,
@@ -1580,6 +1599,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
index 2cbf19a52e38..5f2278b73ee9 100644
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -446,6 +446,114 @@ static struct isl6423_config anysee_isl6423_config = {
* IOE[5] STV0903 1=enabled
*/
+static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct anysee_state *state = adap->dev->priv;
+ int ret;
+
+ deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
+
+ /* no frontend sleep control */
+ if (onoff == 0)
+ return 0;
+
+ switch (state->hw) {
+ case ANYSEE_HW_507FA: /* 15 */
+ /* E30 Combo Plus */
+ /* E30 C Plus */
+
+ if ((fe->id ^ dvb_usb_anysee_delsys) == 0) {
+ /* disable DVB-T demod on IOD[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+
+ /* enable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+ 0x20);
+ if (ret)
+ goto error;
+
+ /* enable DVB-C tuner on IOE[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+ } else {
+ /* disable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+ 0x20);
+ if (ret)
+ goto error;
+
+ /* enable DVB-T demod on IOD[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+
+ /* enable DVB-T tuner on IOE[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+ }
+
+ break;
+ case ANYSEE_HW_508TC: /* 18 */
+ case ANYSEE_HW_508PTC: /* 21 */
+ /* E7 TC */
+ /* E7 PTC */
+
+ if ((fe->id ^ dvb_usb_anysee_delsys) == 0) {
+ /* disable DVB-T demod on IOD[6] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
+ 0x40);
+ if (ret)
+ goto error;
+
+ /* enable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+ 0x20);
+ if (ret)
+ goto error;
+
+ /* enable IF route on IOE[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+ } else {
+ /* disable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+ 0x20);
+ if (ret)
+ goto error;
+
+ /* enable DVB-T demod on IOD[6] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+ 0x40);
+ if (ret)
+ goto error;
+
+ /* enable IF route on IOE[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+ 0x01);
+ if (ret)
+ goto error;
+ }
+
+ break;
+ default:
+ ret = 0;
+ }
+
+error:
+ return ret;
+}
+
static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
{
int ret;
@@ -466,41 +574,54 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
}
};
- /* Check which hardware we have.
- * We must do this call two times to get reliable values (hw bug).
- */
- ret = anysee_get_hw_info(adap->dev, hw_info);
- if (ret)
- goto error;
+ /* detect hardware only once */
+ if (adap->fe_adap[0].fe == NULL) {
+ /* Check which hardware we have.
+ * We must do this call two times to get reliable values (hw bug).
+ */
+ ret = anysee_get_hw_info(adap->dev, hw_info);
+ if (ret)
+ goto error;
- ret = anysee_get_hw_info(adap->dev, hw_info);
- if (ret)
- goto error;
+ ret = anysee_get_hw_info(adap->dev, hw_info);
+ if (ret)
+ goto error;
- /* Meaning of these info bytes are guessed. */
- info("firmware version:%d.%d hardware id:%d",
- hw_info[1], hw_info[2], hw_info[0]);
+ /* Meaning of these info bytes are guessed. */
+ info("firmware version:%d.%d hardware id:%d",
+ hw_info[1], hw_info[2], hw_info[0]);
- state->hw = hw_info[0];
+ state->hw = hw_info[0];
+ }
+
+ /* set current frondend ID for devices having two frondends */
+ if (adap->fe_adap[0].fe)
+ state->fe_id++;
switch (state->hw) {
case ANYSEE_HW_507T: /* 2 */
/* E30 */
+ if (state->fe_id)
+ break;
+
/* attach demod */
- adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach, &anysee_mt352_config,
&adap->dev->i2c_adap);
- if (adap->fe)
+ if (adap->fe_adap[0].fe)
break;
/* attach demod */
- adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
&adap->dev->i2c_adap);
break;
case ANYSEE_HW_507CD: /* 6 */
/* E30 Plus */
+ if (state->fe_id)
+ break;
+
/* enable DVB-T demod on IOD[0] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
if (ret)
@@ -512,33 +633,39 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach demod */
- adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
- &adap->dev->i2c_adap);
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+ &anysee_zl10353_config, &adap->dev->i2c_adap);
break;
case ANYSEE_HW_507DC: /* 10 */
/* E30 C Plus */
+ if (state->fe_id)
+ break;
+
/* enable DVB-C demod on IOD[0] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
if (ret)
goto error;
/* attach demod */
- adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
- &adap->dev->i2c_adap, 0x48);
+ adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
+ &anysee_tda10023_config, &adap->dev->i2c_adap, 0x48);
break;
case ANYSEE_HW_507SI: /* 11 */
/* E30 S2 Plus */
+ if (state->fe_id)
+ break;
+
/* enable DVB-S/S2 demod on IOD[0] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
if (ret)
goto error;
/* attach demod */
- adap->fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
+ adap->fe_adap[0].fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
&adap->dev->i2c_adap);
break;
@@ -564,55 +691,59 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
if (ret)
goto error;
- if (dvb_usb_anysee_delsys) {
- /* disable DVB-C demod on IOD[5] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
- 0x20);
+ if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) {
+ /* disable DVB-T demod on IOD[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
+ 0x01);
if (ret)
goto error;
- /* enable DVB-T demod on IOD[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
- 0x01);
+ /* enable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+ 0x20);
if (ret)
goto error;
/* attach demod */
if (tmp == 0xc7) {
/* TDA18212 config */
- adap->fe = dvb_attach(zl10353_attach,
- &anysee_zl10353_tda18212_config2,
- &adap->dev->i2c_adap);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(
+ tda10023_attach,
+ &anysee_tda10023_tda18212_config,
+ &adap->dev->i2c_adap, 0x48);
} else {
/* PLL config */
- adap->fe = dvb_attach(zl10353_attach,
- &anysee_zl10353_config,
- &adap->dev->i2c_adap);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(
+ tda10023_attach,
+ &anysee_tda10023_config,
+ &adap->dev->i2c_adap, 0x48);
}
} else {
- /* disable DVB-T demod on IOD[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
- 0x01);
+ /* disable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+ 0x20);
if (ret)
goto error;
- /* enable DVB-C demod on IOD[5] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
- 0x20);
+ /* enable DVB-T demod on IOD[0] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
+ 0x01);
if (ret)
goto error;
/* attach demod */
if (tmp == 0xc7) {
/* TDA18212 config */
- adap->fe = dvb_attach(tda10023_attach,
- &anysee_tda10023_tda18212_config,
- &adap->dev->i2c_adap, 0x48);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(
+ zl10353_attach,
+ &anysee_zl10353_tda18212_config2,
+ &adap->dev->i2c_adap);
} else {
/* PLL config */
- adap->fe = dvb_attach(tda10023_attach,
- &anysee_tda10023_config,
- &adap->dev->i2c_adap, 0x48);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(
+ zl10353_attach,
+ &anysee_zl10353_config,
+ &adap->dev->i2c_adap);
}
}
@@ -627,52 +758,40 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
if (ret)
goto error;
- if (dvb_usb_anysee_delsys) {
- /* disable DVB-C demod on IOD[5] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
- 0x20);
- if (ret)
- goto error;
-
- /* enable DVB-T demod on IOD[6] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+ if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) {
+ /* disable DVB-T demod on IOD[6] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
0x40);
if (ret)
goto error;
- /* enable IF route on IOE[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
- 0x01);
+ /* enable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+ 0x20);
if (ret)
goto error;
/* attach demod */
- adap->fe = dvb_attach(zl10353_attach,
- &anysee_zl10353_tda18212_config,
- &adap->dev->i2c_adap);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(tda10023_attach,
+ &anysee_tda10023_tda18212_config,
+ &adap->dev->i2c_adap, 0x48);
} else {
- /* disable DVB-T demod on IOD[6] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
- 0x40);
- if (ret)
- goto error;
-
- /* enable DVB-C demod on IOD[5] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+ /* disable DVB-C demod on IOD[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
0x20);
if (ret)
goto error;
- /* enable IF route on IOE[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
- 0x01);
+ /* enable DVB-T demod on IOD[6] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+ 0x40);
if (ret)
goto error;
/* attach demod */
- adap->fe = dvb_attach(tda10023_attach,
- &anysee_tda10023_tda18212_config,
- &adap->dev->i2c_adap, 0x48);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(zl10353_attach,
+ &anysee_zl10353_tda18212_config,
+ &adap->dev->i2c_adap);
}
break;
@@ -681,6 +800,9 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
/* E7 S2 */
/* E7 PS2 */
+ if (state->fe_id)
+ break;
+
/* enable transport stream on IOA[7] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
if (ret)
@@ -692,13 +814,13 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach demod */
- adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
+ adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
&adap->dev->i2c_adap, 0);
break;
}
- if (!adap->fe) {
+ if (!adap->fe_adap[0].fe) {
/* we have no frontend :-( */
ret = -ENODEV;
err("Unsupported Anysee version. " \
@@ -713,14 +835,14 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
struct anysee_state *state = adap->dev->priv;
struct dvb_frontend *fe;
int ret;
- deb_info("%s:\n", __func__);
+ deb_info("%s: fe=%d\n", __func__, state->fe_id);
switch (state->hw) {
case ANYSEE_HW_507T: /* 2 */
/* E30 */
/* attach tuner */
- fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+ fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
NULL, DVB_PLL_THOMSON_DTT7579);
break;
@@ -728,7 +850,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
/* E30 Plus */
/* attach tuner */
- fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+ fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
&adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579);
break;
@@ -736,7 +858,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
/* E30 C Plus */
/* attach tuner */
- fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
+ fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc0 >> 1),
&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
break;
@@ -744,28 +866,14 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
/* E30 S2 Plus */
/* attach LNB controller */
- fe = dvb_attach(isl6423_attach, adap->fe, &adap->dev->i2c_adap,
- &anysee_isl6423_config);
+ fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap, &anysee_isl6423_config);
break;
case ANYSEE_HW_507FA: /* 15 */
/* E30 Combo Plus */
/* E30 C Plus */
- if (dvb_usb_anysee_delsys) {
- /* enable DVB-T tuner on IOE[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
- 0x01);
- if (ret)
- goto error;
- } else {
- /* enable DVB-C tuner on IOE[0] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
- 0x01);
- if (ret)
- goto error;
- }
-
/* Try first attach TDA18212 silicon tuner on IOE[4], if that
* fails attach old simple PLL. */
@@ -775,8 +883,8 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach tuner */
- fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
- &anysee_tda18212_config);
+ fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
+ &adap->dev->i2c_adap, &anysee_tda18212_config);
if (fe)
break;
@@ -786,8 +894,9 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach tuner */
- fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
- &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+ fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe,
+ (0xc0 >> 1), &adap->dev->i2c_adap,
+ DVB_PLL_SAMSUNG_DTOS403IH102A);
break;
case ANYSEE_HW_508TC: /* 18 */
@@ -801,8 +910,8 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach tuner */
- fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
- &anysee_tda18212_config);
+ fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
+ &adap->dev->i2c_adap, &anysee_tda18212_config);
break;
case ANYSEE_HW_508S2: /* 19 */
@@ -811,12 +920,12 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
/* E7 PS2 */
/* attach tuner */
- fe = dvb_attach(stv6110_attach, adap->fe,
+ fe = dvb_attach(stv6110_attach, adap->fe_adap[0].fe,
&anysee_stv6110_config, &adap->dev->i2c_adap);
if (fe) {
/* attach LNB controller */
- fe = dvb_attach(isl6423_attach, adap->fe,
+ fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, &anysee_isl6423_config);
}
@@ -918,6 +1027,23 @@ static struct dvb_usb_device_properties anysee_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 2,
+ .frontend_ctrl = anysee_frontend_ctrl,
+ .fe = {{
+ .streaming_ctrl = anysee_streaming_ctrl,
+ .frontend_attach = anysee_frontend_attach,
+ .tuner_attach = anysee_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = (16*512),
+ }
+ }
+ },
+ }, {
.streaming_ctrl = anysee_streaming_ctrl,
.frontend_attach = anysee_frontend_attach,
.tuner_attach = anysee_tuner_attach,
@@ -931,6 +1057,7 @@ static struct dvb_usb_device_properties anysee_properties = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h
index ad6ccd1ea2d9..57ee500b8c0e 100644
--- a/drivers/media/dvb/dvb-usb/anysee.h
+++ b/drivers/media/dvb/dvb-usb/anysee.h
@@ -59,6 +59,7 @@ enum cmd {
struct anysee_state {
u8 hw; /* PCB ID */
u8 seq;
+ u8 fe_id:1; /* frondend ID */
};
#define ANYSEE_HW_507T 2 /* E30 */
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c
index 2351077ff2b3..b77994967b9b 100644
--- a/drivers/media/dvb/dvb-usb/au6610.c
+++ b/drivers/media/dvb/dvb-usb/au6610.c
@@ -140,9 +140,9 @@ static struct zl10353_config au6610_zl10353_config = {
static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
&adap->dev->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
return 0;
@@ -155,7 +155,7 @@ static struct qt1010_config au6610_qt1010_config = {
static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
{
return dvb_attach(qt1010_attach,
- adap->fe, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&au6610_qt1010_config) == NULL ? -ENODEV : 0;
}
@@ -204,6 +204,8 @@ static struct dvb_usb_device_properties au6610_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = au6610_zl10353_frontend_attach,
.tuner_attach = au6610_qt1010_tuner_attach,
@@ -219,6 +221,7 @@ static struct dvb_usb_device_properties au6610_properties = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c
index 57e2444d51ab..bf67b4dfd82b 100644
--- a/drivers/media/dvb/dvb-usb/az6027.c
+++ b/drivers/media/dvb/dvb-usb/az6027.c
@@ -40,7 +40,6 @@ static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = {
{ STB0899_DISRX_ST0 , 0x04 },
{ STB0899_DISRX_ST1 , 0x00 },
{ STB0899_DISPARITY , 0x00 },
- { STB0899_DISFIFO , 0x00 },
{ STB0899_DISSTATUS , 0x20 },
{ STB0899_DISF22 , 0x99 },
{ STB0899_DISF22RX , 0xa8 },
@@ -782,7 +781,6 @@ static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
u8 buf;
- int ret;
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct i2c_msg i2c_msg = {
@@ -800,17 +798,17 @@ static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
switch (voltage) {
case SEC_VOLTAGE_13:
buf = 1;
- ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+ i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
break;
case SEC_VOLTAGE_18:
buf = 2;
- ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+ i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
break;
case SEC_VOLTAGE_OFF:
buf = 0;
- ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+ i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
break;
default:
@@ -910,16 +908,16 @@ static int az6027_frontend_attach(struct dvb_usb_adapter *adap)
az6027_frontend_reset(adap);
deb_info("adap = %p, dev = %p\n", adap, adap->dev);
- adap->fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
+ adap->fe_adap[0].fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
- if (adap->fe) {
+ if (adap->fe_adap[0].fe) {
deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address);
- if (stb6100_attach(adap->fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
+ if (stb6100_attach(adap->fe_adap[0].fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address);
- adap->fe->ops.set_voltage = az6027_set_voltage;
+ adap->fe_adap[0].fe->ops.set_voltage = az6027_set_voltage;
az6027_ci_init(adap);
} else {
- adap->fe = NULL;
+ adap->fe_adap[0].fe = NULL;
}
} else
warn("no front-end attached\n");
@@ -954,7 +952,6 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0, j = 0, len = 0;
- int ret;
u16 index;
u16 value;
int length;
@@ -990,7 +987,7 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
value = msg[i].addr + (msg[i].len << 8);
length = msg[i + 1].len + 6;
- ret = az6027_usb_in_op(d, req, value, index, data, length);
+ az6027_usb_in_op(d, req, value, index, data, length);
len = msg[i + 1].len;
for (j = 0; j < len; j++)
msg[i + 1].buf[j] = data[j + 5];
@@ -1017,7 +1014,7 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
index = 0x0;
value = msg[i].addr;
length = msg[i].len + 6;
- ret = az6027_usb_in_op(d, req, value, index, data, length);
+ az6027_usb_in_op(d, req, value, index, data, length);
len = msg[i].len;
for (j = 0; j < len; j++)
msg[i].buf[j] = data[j + 5];
@@ -1106,6 +1103,8 @@ static struct dvb_usb_device_properties az6027_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = az6027_streaming_ctrl,
.frontend_attach = az6027_frontend_attach,
@@ -1120,6 +1119,7 @@ static struct dvb_usb_device_properties az6027_properties = {
}
}
},
+ }},
}
},
/*
diff --git a/drivers/media/dvb/dvb-usb/ce6230.c b/drivers/media/dvb/dvb-usb/ce6230.c
index 6d1a3041540d..57afb5a9157e 100644
--- a/drivers/media/dvb/dvb-usb/ce6230.c
+++ b/drivers/media/dvb/dvb-usb/ce6230.c
@@ -186,9 +186,9 @@ static struct zl10353_config ce6230_zl10353_config = {
static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
{
deb_info("%s:\n", __func__);
- adap->fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
&adap->dev->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
return 0;
}
@@ -214,7 +214,7 @@ static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
{
int ret;
deb_info("%s:\n", __func__);
- ret = dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
+ ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&ce6230_mxl5003s_config) == NULL ? -ENODEV : 0;
return ret;
}
@@ -273,6 +273,8 @@ static struct dvb_usb_device_properties ce6230_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = ce6230_zl10353_frontend_attach,
.tuner_attach = ce6230_mxl5003s_tuner_attach,
.stream = {
@@ -285,6 +287,7 @@ static struct dvb_usb_device_properties ce6230_properties = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c
index 16f2ce2bc15a..f9d905002ec9 100644
--- a/drivers/media/dvb/dvb-usb/cinergyT2-core.c
+++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c
@@ -69,7 +69,7 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
char state[3];
int ret;
- adap->fe = cinergyt2_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
sizeof(state), 0);
@@ -198,6 +198,8 @@ static struct dvb_usb_device_properties cinergyt2_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cinergyt2_streaming_ctrl,
.frontend_attach = cinergyt2_frontend_attach,
@@ -212,6 +214,7 @@ static struct dvb_usb_device_properties cinergyt2_properties = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index acb5fb2d2e73..9f2a02c48377 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -347,7 +347,7 @@ static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d)
static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d)
{
- struct usb_data_stream_properties *p = &d->props.adapter[0].stream;
+ struct usb_data_stream_properties *p = &d->props.adapter[0].fe[0].stream;
const int timeout = 100;
const int junk_len = p->u.bulk.buffersize;
u8 *junk;
@@ -725,7 +725,7 @@ static struct max2165_config mygica_d689_max2165_cfg = {
/* Callbacks for DVB USB */
static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(simple_tuner_attach, adap->fe,
+ dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, 0x61,
TUNER_PHILIPS_FMD1216ME_MK3);
return 0;
@@ -733,27 +733,27 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x61,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61,
NULL, DVB_PLL_THOMSON_DTT7579);
return 0;
}
static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_LG_Z201);
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_LG_Z201);
return 0;
}
static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
NULL, DVB_PLL_THOMSON_DTT7579);
return 0;
}
static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(simple_tuner_attach, adap->fe,
+ dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
return 0;
}
@@ -795,9 +795,9 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
};
/* FIXME: generalize & move to common area */
- adap->fe->callback = dvico_bluebird_xc2028_callback;
+ adap->fe_adap[0].fe->callback = dvico_bluebird_xc2028_callback;
- fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
+ fe = dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &cfg);
if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
return -EIO;
@@ -808,7 +808,7 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(mxl5005s_attach, adap->fe,
+ dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, &aver_a868r_tuner);
return 0;
}
@@ -816,7 +816,7 @@ static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dvb_frontend *fe;
- fe = dvb_attach(mxl5005s_attach, adap->fe,
+ fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, &d680_dmb_tuner);
return (fe == NULL) ? -EIO : 0;
}
@@ -824,7 +824,7 @@ static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_mygica_d689_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dvb_frontend *fe;
- fe = dvb_attach(max2165_attach, adap->fe,
+ fe = dvb_attach(max2165_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, &mygica_d689_max2165_cfg);
return (fe == NULL) ? -EIO : 0;
}
@@ -837,8 +837,9 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
- if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
- &adap->dev->i2c_adap)) != NULL)
+ adap->fe_adap[0].fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
return -EIO;
@@ -851,8 +852,10 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
- if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config,
- &adap->dev->i2c_adap)) != NULL)
+ adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach,
+ &cxusb_lgdt3303_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
return -EIO;
@@ -860,9 +863,9 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
+ adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
&adap->dev->i2c_adap);
- if (adap->fe != NULL)
+ if (adap->fe_adap[0].fe != NULL)
return 0;
return -EIO;
@@ -876,8 +879,9 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
- if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
- &adap->dev->i2c_adap)) != NULL)
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
return -EIO;
@@ -890,11 +894,15 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
- if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
- &adap->dev->i2c_adap)) != NULL) ||
- ((adap->fe = dvb_attach(zl10353_attach,
- &cxusb_zl10353_dee1601_config,
- &adap->dev->i2c_adap)) != NULL))
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
+ return 0;
+
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+ &cxusb_zl10353_dee1601_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
return -EIO;
@@ -917,9 +925,11 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
- if ((adap->fe = dvb_attach(zl10353_attach,
- &cxusb_zl10353_xc3028_config_no_i2c_gate,
- &adap->dev->i2c_adap)) == NULL)
+ adap->fe_adap[0].fe =
+ dvb_attach(zl10353_attach,
+ &cxusb_zl10353_xc3028_config_no_i2c_gate,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) == NULL)
return -EIO;
/* try to determine if there is no IR decoder on the I2C bus */
@@ -1031,9 +1041,9 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&cxusb_dualdig4_rev2_config);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
return 0;
@@ -1084,15 +1094,15 @@ static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c =
- dib7000p_get_i2c_master(adap->fe,
+ dib7000p_get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
&dib7070p_dib0070_config) == NULL)
return -ENODEV;
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
return 0;
}
@@ -1108,14 +1118,16 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
- if ((adap->fe = dvb_attach(zl10353_attach,
- &cxusb_zl10353_xc3028_config,
- &adap->dev->i2c_adap)) != NULL)
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+ &cxusb_zl10353_xc3028_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
- if ((adap->fe = dvb_attach(mt352_attach,
- &cxusb_mt352_xc3028_config,
- &adap->dev->i2c_adap)) != NULL)
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach,
+ &cxusb_mt352_xc3028_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL)
return 0;
return -EIO;
@@ -1150,7 +1162,7 @@ static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
usb_clear_halt(d->udev,
usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
usb_clear_halt(d->udev,
- usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
+ usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
/* Drain USB pipes to avoid hang after reboot */
for (n = 0; n < 5; n++) {
@@ -1172,8 +1184,8 @@ static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
msleep(100);
/* Attach frontend */
- adap->fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
- if (adap->fe == NULL)
+ adap->fe_adap[0].fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
return 0;
@@ -1207,7 +1219,7 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
usb_clear_halt(d->udev,
usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
usb_clear_halt(d->udev,
- usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
+ usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
/* Reset the tuner */
@@ -1223,9 +1235,9 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
msleep(100);
/* Attach frontend */
- adap->fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
+ adap->fe_adap[0].fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
&d->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
return 0;
@@ -1383,6 +1395,8 @@ static struct dvb_usb_device_properties cxusb_medion_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_cx22702_frontend_attach,
.tuner_attach = cxusb_fmd1216me_tuner_attach,
@@ -1397,7 +1411,7 @@ static struct dvb_usb_device_properties cxusb_medion_properties = {
}
}
},
-
+ }},
},
},
.power_ctrl = cxusb_power_ctrl,
@@ -1429,6 +1443,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_lgdt3303_frontend_attach,
.tuner_attach = cxusb_lgh064f_tuner_attach,
@@ -1444,6 +1460,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
}
}
},
+ }},
},
},
@@ -1483,6 +1500,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_dee1601_frontend_attach,
.tuner_attach = cxusb_dee1601_tuner_attach,
@@ -1497,6 +1516,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
}
}
},
+ }},
},
},
@@ -1544,6 +1564,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_mt352_frontend_attach,
.tuner_attach = cxusb_lgz201_tuner_attach,
@@ -1559,6 +1581,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
}
}
},
+ }},
},
},
.power_ctrl = cxusb_bluebird_power_ctrl,
@@ -1596,6 +1619,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_mt352_frontend_attach,
.tuner_attach = cxusb_dtt7579_tuner_attach,
@@ -1611,6 +1636,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
}
}
},
+ }},
},
},
.power_ctrl = cxusb_bluebird_power_ctrl,
@@ -1645,6 +1671,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_dualdig4_frontend_attach,
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
@@ -1659,6 +1687,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
}
}
},
+ }},
},
},
@@ -1695,6 +1724,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_nano2_frontend_attach,
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
@@ -1709,6 +1740,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
}
}
},
+ }},
},
},
@@ -1747,6 +1779,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_nano2_frontend_attach,
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
@@ -1761,6 +1795,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
}
}
},
+ }},
},
},
@@ -1796,6 +1831,8 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_aver_streaming_ctrl,
.frontend_attach = cxusb_aver_lgdt3303_frontend_attach,
.tuner_attach = cxusb_mxl5003s_tuner_attach,
@@ -1810,7 +1847,7 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
}
}
},
-
+ }},
},
},
.power_ctrl = cxusb_aver_power_ctrl,
@@ -1839,10 +1876,12 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
.num_adapters = 1,
.adapter = {
{
+ .size_of_priv = sizeof(struct dib0700_adapter_state),
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_dualdig4_rev2_frontend_attach,
.tuner_attach = cxusb_dualdig4_rev2_tuner_attach,
- .size_of_priv = sizeof(struct dib0700_adapter_state),
/* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
@@ -1854,6 +1893,7 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
}
}
},
+ }},
},
},
@@ -1889,6 +1929,8 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_d680_dmb_streaming_ctrl,
.frontend_attach = cxusb_d680_dmb_frontend_attach,
.tuner_attach = cxusb_d680_dmb_tuner_attach,
@@ -1904,6 +1946,7 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
}
}
},
+ }},
},
},
@@ -1940,6 +1983,8 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = cxusb_d680_dmb_streaming_ctrl,
.frontend_attach = cxusb_mygica_d689_frontend_attach,
.tuner_attach = cxusb_mygica_d689_tuner_attach,
@@ -1955,6 +2000,7 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
}
}
},
+ }},
},
},
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index 5eb91b4f8fd0..156cbfc9c79d 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
struct dib0700_state *st = d->priv;
int ret;
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+ err("could not acquire lock");
+ return 0;
+ }
+
ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
REQUEST_GET_VERSION,
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
if (fwtype != NULL)
*fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) |
(st->buf[14] << 8) | st->buf[15];
+ mutex_unlock(&d->usb_mutex);
return ret;
}
@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
{
struct dib0700_state *st = d->priv;
- s16 ret;
+ int ret;
+
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+ err("could not acquire lock");
+ return 0;
+ }
st->buf[0] = REQUEST_SET_GPIO;
st->buf[1] = gpio;
@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
ret = dib0700_ctrl_wr(d, st->buf, 3);
+ mutex_unlock(&d->usb_mutex);
return ret;
}
@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
int ret;
if (st->fw_version >= 0x10201) {
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+ err("could not acquire lock");
+ return 0;
+ }
+
st->buf[0] = REQUEST_SET_USB_XFER_LEN;
st->buf[1] = (nb_ts_packets >> 8) & 0xff;
st->buf[2] = nb_ts_packets & 0xff;
@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
ret = dib0700_ctrl_wr(d, st->buf, 3);
+ mutex_unlock(&d->usb_mutex);
} else {
deb_info("this firmware does not allow to change the USB xfer len\n");
ret = -EIO;
@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
} else {
/* Write request */
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+ err("could not acquire lock");
+ return 0;
+ }
st->buf[0] = REQUEST_NEW_I2C_WRITE;
st->buf[1] = msg[i].addr << 1;
st->buf[2] = (en_start << 7) | (en_stop << 6) |
@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
USB_TYPE_VENDOR | USB_DIR_OUT,
0, 0, st->buf, msg[i].len + 4,
USB_CTRL_GET_TIMEOUT);
+ mutex_unlock(&d->usb_mutex);
if (result < 0) {
deb_info("i2c write error (status = %d)\n", result);
break;
@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+ err("could not acquire lock");
+ return 0;
+ }
for (i = 0; i < num; i++) {
/* fill in the address */
@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
break;
}
}
+ mutex_unlock(&d->usb_mutex);
mutex_unlock(&d->i2c_mutex);
return i;
@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
{
struct dib0700_state *st = d->priv;
- s16 ret;
+ int ret;
+
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+ err("could not acquire lock");
+ return 0;
+ }
st->buf[0] = REQUEST_SET_CLOCK;
st->buf[1] = (en_pll << 7) | (pll_src << 6) |
@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
st->buf[9] = dsuScaler & 0xff; /* LSB */
ret = dib0700_ctrl_wr(d, st->buf, 10);
+ mutex_unlock(&d->usb_mutex);
return ret;
}
@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
{
struct dib0700_state *st = d->priv;
u16 divider;
+ int ret;
if (scl_kHz == 0)
return -EINVAL;
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+ err("could not acquire lock");
+ return 0;
+ }
+
st->buf[0] = REQUEST_SET_I2C_PARAM;
divider = (u16) (30000 / scl_kHz);
st->buf[1] = 0;
@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
(st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
- return dib0700_ctrl_wr(d, st->buf, 8);
+
+ ret = dib0700_ctrl_wr(d, st->buf, 8);
+ mutex_unlock(&d->usb_mutex);
+
+ return ret;
}
@@ -484,13 +528,13 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
adap_num++) {
if (fw_version >= 0x10201) {
- dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
+ dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
} else {
/* for fw version older than 1.20.1,
* the buffersize has to be n times 512 */
- dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
- if (dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize < 512)
- dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 512;
+ dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
+ if (dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize < 512)
+ dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 512;
}
}
}
@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
}
}
+ if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
+ err("could not acquire lock");
+ return 0;
+ }
+
st->buf[0] = REQUEST_ENABLE_VIDEO;
/* this bit gives a kind of command,
* rather than enabling something or not */
@@ -530,25 +579,28 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
st->channel_state &= ~0x3;
- if ((adap->stream.props.endpoint != 2)
- && (adap->stream.props.endpoint != 3)) {
- deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->stream.props.endpoint);
+ if ((adap->fe_adap[0].stream.props.endpoint != 2)
+ && (adap->fe_adap[0].stream.props.endpoint != 3)) {
+ deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].stream.props.endpoint);
if (onoff)
st->channel_state |= 1 << (adap->id);
else
st->channel_state |= 1 << ~(adap->id);
} else {
if (onoff)
- st->channel_state |= 1 << (adap->stream.props.endpoint-2);
+ st->channel_state |= 1 << (adap->fe_adap[0].stream.props.endpoint-2);
else
- st->channel_state |= 1 << (3-adap->stream.props.endpoint);
+ st->channel_state |= 1 << (3-adap->fe_adap[0].stream.props.endpoint);
}
st->buf[2] |= st->channel_state;
deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
- return dib0700_ctrl_wr(adap->dev, st->buf, 4);
+ ret = dib0700_ctrl_wr(adap->dev, st->buf, 4);
+ mutex_unlock(&adap->dev->usb_mutex);
+
+ return ret;
}
int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
struct dib0700_state *st = d->priv;
int new_proto, ret;
+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+ err("could not acquire lock");
+ return 0;
+ }
+
st->buf[0] = REQUEST_SET_RC;
st->buf[1] = 0;
st->buf[2] = 0;
@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
else if (rc_type == RC_TYPE_NEC)
new_proto = 0;
else if (rc_type == RC_TYPE_RC6) {
- if (st->fw_version < 0x10200)
- return -EINVAL;
+ if (st->fw_version < 0x10200) {
+ ret = -EINVAL;
+ goto out;
+ }
new_proto = 2;
- } else
- return -EINVAL;
+ } else {
+ ret = -EINVAL;
+ goto out;
+ }
st->buf[1] = new_proto;
ret = dib0700_ctrl_wr(d, st->buf, 3);
if (ret < 0) {
err("ir protocol setup failed");
- return ret;
+ goto out;
}
d->props.rc.core.protocol = rc_type;
+out:
+ mutex_unlock(&d->usb_mutex);
return ret;
}
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index d0ea5b64f6b4..f313182eb9d5 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -101,7 +101,7 @@ static int bristol_frontend_attach(struct dvb_usb_adapter *adap)
}
}
st->mt2060_if1[adap->id] = 1220;
- return (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
+ return (adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
(10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0;
}
@@ -118,15 +118,16 @@ static int eeprom_read(struct i2c_adapter *adap,u8 adrs,u8 *pval)
static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
- struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
+ struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
s8 a;
int if1=1220;
if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) &&
adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_500_2)) {
if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a;
}
- return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id],
- if1) == NULL ? -ENODEV : 0;
+ return dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c,
+ &bristol_mt2060_config[adap->id], if1) == NULL ?
+ -ENODEV : 0;
}
/* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */
@@ -279,10 +280,12 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
}
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
- &stk7700d_dib7000p_mt2266_config[adap->id]);
+ adap->fe_adap[0].fe =
+ dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ 0x80 + (adap->id << 1),
+ &stk7700d_dib7000p_mt2266_config[adap->id]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
@@ -306,17 +309,19 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
}
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
- &stk7700d_dib7000p_mt2266_config[adap->id]);
+ adap->fe_adap[0].fe =
+ dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ 0x80 + (adap->id << 1),
+ &stk7700d_dib7000p_mt2266_config[adap->id]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *tun_i2c;
- tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
- return dvb_attach(mt2266_attach, adap->fe, tun_i2c,
+ tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ return dvb_attach(mt2266_attach, adap->fe_adap[0].fe, tun_i2c,
&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;
}
@@ -396,8 +401,8 @@ static int stk7700ph_xc3028_callback(void *ptr, int component,
switch (command) {
case XC2028_TUNER_RESET:
/* Send the tuner in then out of reset */
- dib7000p_set_gpio(adap->fe, 8, 0, 0); msleep(10);
- dib7000p_set_gpio(adap->fe, 8, 0, 1);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0); msleep(10);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
break;
case XC2028_RESET_CLK:
break;
@@ -447,25 +452,25 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&stk7700ph_dib7700_xc3028_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *tun_i2c;
- tun_i2c = dib7000p_get_i2c_master(adap->fe,
+ tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
stk7700ph_xc3028_config.i2c_adap = tun_i2c;
/* FIXME: generalize & move to common area */
- adap->fe->callback = stk7700ph_xc3028_callback;
+ adap->fe_adap[0].fe->callback = stk7700ph_xc3028_callback;
- return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
+ return dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &stk7700ph_xc3028_config)
== NULL ? -ENODEV : 0;
}
@@ -685,12 +690,12 @@ static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
st->mt2060_if1[0] = 1220;
if (dib7000pc_detection(&adap->dev->i2c_adap)) {
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
st->is_dib7000pc = 1;
} else
- adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
+ adap->fe_adap[0].fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static struct mt2060_config stk7700p_mt2060_config = {
@@ -709,11 +714,11 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
}
if (st->is_dib7000pc)
- tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
else
- tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ tun_i2c = dib7000m_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
- return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
+ return dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk7700p_mt2060_config,
if1) == NULL ? -ENODEV : 0;
}
@@ -843,33 +848,33 @@ static int dib7770_set_param_override(struct dvb_frontend *fe,
static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe,
+ struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
- &dib7770p_dib0070_config) == NULL)
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
+ &dib7770p_dib0070_config) == NULL)
return -ENODEV;
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7770_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
return 0;
}
static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
if (adap->id == 0) {
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
return -ENODEV;
} else {
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
return -ENODEV;
}
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
return 0;
}
@@ -878,26 +883,26 @@ static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index,
{
struct dib0700_state *st = adapter->dev->priv;
if (st->is_dib7000pc)
- return dib7000p_pid_filter(adapter->fe, index, pid, onoff);
- return dib7000m_pid_filter(adapter->fe, index, pid, onoff);
+ return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+ return dib7000m_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
struct dib0700_state *st = adapter->dev->priv;
if (st->is_dib7000pc)
- return dib7000p_pid_filter_ctrl(adapter->fe, onoff);
- return dib7000m_pid_filter_ctrl(adapter->fe, onoff);
+ return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+ return dib7000m_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
{
- return dib7000p_pid_filter(adapter->fe, index, pid, onoff);
+ return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
- return dib7000p_pid_filter_ctrl(adapter->fe, onoff);
+ return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
@@ -955,9 +960,9 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&dib7070p_dib7000p_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* STK7770P */
@@ -1007,9 +1012,9 @@ static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&dib7770p_dib7000p_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* DIB807x generic */
@@ -1225,34 +1230,34 @@ static int dib807x_set_param_override(struct dvb_frontend *fe,
static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe,
+ struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
if (adap->id == 0) {
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
&dib807x_dib0070_config[0]) == NULL)
return -ENODEV;
} else {
- if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
&dib807x_dib0070_config[1]) == NULL)
return -ENODEV;
}
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib807x_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib807x_set_param_override;
return 0;
}
static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
u16 pid, int onoff)
{
- return dib8000_pid_filter(adapter->fe, index, pid, onoff);
+ return dib8000_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
int onoff)
{
- return dib8000_pid_filter_ctrl(adapter->fe, onoff);
+ return dib8000_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
/* STK807x */
@@ -1276,10 +1281,10 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
0x80);
- adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* STK807xPVR */
@@ -1305,10 +1310,10 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
/* initialize IC 0 */
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80);
- adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
@@ -1316,10 +1321,10 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
/* initialize IC 1 */
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82);
- adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
&dib807x_dib8000_config[1]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* STK8096GP */
@@ -1546,13 +1551,13 @@ static int dib8096_set_param_override(struct dvb_frontend *fe,
static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
- if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override;
return 0;
}
@@ -1575,30 +1580,30 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80);
- adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c;
- struct dvb_frontend *fe_slave = dib8000_get_slave_frontend(adap->fe, 1);
+ struct dvb_frontend *fe_slave = dib8000_get_slave_frontend(adap->fe_adap[0].fe, 1);
if (fe_slave) {
tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
- fe_slave->dvb = adap->fe->dvb;
+ fe_slave->dvb = adap->fe_adap[0].fe->dvb;
fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override;
}
- tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
- if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
+ tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override;
return 0;
}
@@ -1626,12 +1631,12 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80);
- adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
- if (adap->fe == NULL)
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
- dib8000_set_slave_frontend(adap->fe, fe_slave);
+ dib8000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
return fe_slave == NULL ? -ENODEV : 0;
}
@@ -1639,12 +1644,12 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
/* STK9090M */
static int dib90x0_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
{
- return dib9000_fw_pid_filter(adapter->fe, index, pid, onoff);
+ return dib9000_fw_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int dib90x0_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
- return dib9000_fw_pid_filter_ctrl(adapter->fe, onoff);
+ return dib9000_fw_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
static int dib90x0_tuner_reset(struct dvb_frontend *fe, int onoff)
@@ -1856,15 +1861,15 @@ static int stk9090m_frontend_attach(struct dvb_usb_adapter *adap)
stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size;
stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data;
- adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
+ adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *state = adap->priv;
- struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe);
+ struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe);
u16 data_dib190[10] = {
1, 0x1374,
2, 0x01a2,
@@ -1873,13 +1878,13 @@ static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
8, 0x0486,
};
- if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &dib9090_dib0090_config) == NULL)
+ if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &dib9090_dib0090_config) == NULL)
return -ENODEV;
- i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
+ i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0)
return -ENODEV;
dib0700_set_i2c_speed(adap->dev, 2000);
- if (dib9000_firmware_post_pll_init(adap->fe) < 0)
+ if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
return -ENODEV;
release_firmware(state->frontend_firmware);
return 0;
@@ -1925,16 +1930,16 @@ static int nim9090md_frontend_attach(struct dvb_usb_adapter *adap)
nim9090md_config[1].microcode_B_fe_buffer = state->frontend_firmware->data;
dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, 0x80);
- adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
+ adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
- i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
+ i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
dib9000_i2c_enumeration(i2c, 1, 0x12, 0x82);
fe_slave = dvb_attach(dib9000_attach, i2c, 0x82, &nim9090md_config[1]);
- dib9000_set_slave_frontend(adap->fe, fe_slave);
+ dib9000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
return fe_slave == NULL ? -ENODEV : 0;
}
@@ -1951,26 +1956,26 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
0, 0x00ef,
8, 0x0406,
};
- i2c = dib9000_get_tuner_interface(adap->fe);
- if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &nim9090md_dib0090_config[0]) == NULL)
+ i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe);
+ if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &nim9090md_dib0090_config[0]) == NULL)
return -ENODEV;
- i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
+ i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0)
return -ENODEV;
dib0700_set_i2c_speed(adap->dev, 2000);
- if (dib9000_firmware_post_pll_init(adap->fe) < 0)
+ if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
return -ENODEV;
- fe_slave = dib9000_get_slave_frontend(adap->fe, 1);
+ fe_slave = dib9000_get_slave_frontend(adap->fe_adap[0].fe, 1);
if (fe_slave != NULL) {
- i2c = dib9000_get_component_bus_interface(adap->fe);
+ i2c = dib9000_get_component_bus_interface(adap->fe_adap[0].fe);
dib9000_set_i2c_adapter(fe_slave, i2c);
i2c = dib9000_get_tuner_interface(fe_slave);
if (dvb_attach(dib0090_fw_register, fe_slave, i2c, &nim9090md_dib0090_config[1]) == NULL)
return -ENODEV;
- fe_slave->dvb = adap->fe->dvb;
- dib9000_fw_set_component_bus_speed(adap->fe, 2000);
+ fe_slave->dvb = adap->fe_adap[0].fe->dvb;
+ dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 2000);
if (dib9000_firmware_post_pll_init(fe_slave) < 0)
return -ENODEV;
}
@@ -2393,23 +2398,23 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+ struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
- if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &nim7090_dib0090_config) == NULL)
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &nim7090_dib0090_config) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe, 8, 0, 1);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
return 0;
}
@@ -2439,11 +2444,11 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
}
dib0700_set_i2c_speed(adap->dev, 340);
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
- if (adap->fe == NULL)
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
- dib7090_slave_reset(adap->fe);
+ dib7090_slave_reset(adap->fe_adap[0].fe);
return 0;
}
@@ -2452,50 +2457,50 @@ static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *i2c;
- if (adap->dev->adapter[0].fe == NULL) {
+ if (adap->dev->adapter[0].fe_adap[0].fe == NULL) {
err("the master dib7090 has to be initialized first");
return -ENODEV; /* the master device has not been initialized */
}
- i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
+ i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
dib0700_set_i2c_speed(adap->dev, 200);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+ struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
- if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe, 8, 0, 1);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
return 0;
}
static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+ struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
- if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe, 8, 0, 1);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
- st->set_param_save = adap->fe->ops.tuner_ops.set_params;
- adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
return 0;
}
@@ -2555,14 +2560,14 @@ static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
- return adap->fe == NULL ? -ENODEV : 0;
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
{
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
- return adap->fe == NULL ? -ENODEV : 0;
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* S5H1411 */
@@ -2617,9 +2622,9 @@ static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
/* GPIOs are initialized, do the attach */
- adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
+ adap->fe_adap[0].fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
&adap->dev->i2c_adap);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int dib0700_xc5000_tuner_callback(void *priv, int component,
@@ -2649,9 +2654,9 @@ static struct xc5000_config s5h1411_xc5000_tunerconfig = {
static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
{
/* FIXME: generalize & move to common area */
- adap->fe->callback = dib0700_xc5000_tuner_callback;
+ adap->fe_adap[0].fe->callback = dib0700_xc5000_tuner_callback;
- return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap,
+ return dvb_attach(xc5000_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&s5h1411_xc5000_tunerconfig)
== NULL ? -ENODEV : 0;
}
@@ -2663,9 +2668,9 @@ static int dib0700_xc4000_tuner_callback(void *priv, int component,
if (command == XC4000_TUNER_RESET) {
/* Reset the tuner */
- dib7000p_set_gpio(adap->fe, 8, 0, 0);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
msleep(10);
- dib7000p_set_gpio(adap->fe, 8, 0, 1);
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
} else {
err("xc4000: unknown tuner callback command: %d\n", command);
return -EINVAL;
@@ -2771,11 +2776,11 @@ static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap)
return -ENODEV;
}
- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
&pctv_340e_config);
st->is_dib7000pc = 1;
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static struct xc4000_config dib7000p_xc4000_tunerconfig = {
@@ -2791,7 +2796,7 @@ static int xc4000_tuner_attach(struct dvb_usb_adapter *adap)
struct i2c_adapter *tun_i2c;
/* The xc4000 is not on the main i2c bus */
- tun_i2c = dib7000p_get_i2c_master(adap->fe,
+ tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
if (tun_i2c == NULL) {
printk(KERN_ERR "Could not reach tuner i2c bus\n");
@@ -2799,9 +2804,9 @@ static int xc4000_tuner_attach(struct dvb_usb_adapter *adap)
}
/* Setup the reset callback */
- adap->fe->callback = dib0700_xc4000_tuner_callback;
+ adap->fe_adap[0].fe->callback = dib0700_xc4000_tuner_callback;
- return dvb_attach(xc4000_attach, adap->fe, tun_i2c,
+ return dvb_attach(xc4000_attach, adap->fe_adap[0].fe, tun_i2c,
&dib7000p_xc4000_tunerconfig)
== NULL ? -ENODEV : 0;
}
@@ -2857,16 +2862,16 @@ static int lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(30);
- adap->fe = dvb_attach(lgdt3305_attach,
+ adap->fe_adap[0].fe = dvb_attach(lgdt3305_attach,
&hcw_lgdt3305_config,
&adap->dev->i2c_adap);
- return adap->fe == NULL ? -ENODEV : 0;
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int mxl5007t_tuner_attach(struct dvb_usb_adapter *adap)
{
- return dvb_attach(mxl5007t_attach, adap->fe,
+ return dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, 0x60,
&hcw_mxl5007t_config) == NULL ? -ENODEV : 0;
}
@@ -2989,6 +2994,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk7700p_pid_filter,
@@ -2997,6 +3004,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = stk7700p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }},
},
},
@@ -3050,15 +3058,21 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = bristol_frontend_attach,
.tuner_attach = bristol_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }},
}, {
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = bristol_frontend_attach,
.tuner_attach = bristol_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+ }},
}
},
@@ -3084,6 +3098,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3092,7 +3108,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = stk7700d_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }},
}, {
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3101,6 +3120,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = stk7700d_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+ }},
}
},
@@ -3143,6 +3163,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3151,6 +3173,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = stk7700d_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }},
},
},
@@ -3185,6 +3208,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3193,7 +3218,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
},
},
@@ -3261,6 +3286,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3269,7 +3296,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
},
},
@@ -3305,6 +3332,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3313,9 +3342,11 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
}, {
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3324,7 +3355,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
}
},
@@ -3373,6 +3404,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3381,9 +3414,11 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
}, {
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3392,7 +3427,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7070p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+ }},
.size_of_priv = sizeof(struct dib0700_adapter_state),
}
},
@@ -3420,6 +3455,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3428,7 +3465,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = stk7700ph_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct
dib0700_adapter_state),
},
@@ -3488,11 +3525,13 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = s5h1411_frontend_attach,
.tuner_attach = xc5000_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct
dib0700_adapter_state),
},
@@ -3524,11 +3563,13 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = lgdt3305_frontend_attach,
.tuner_attach = mxl5007t_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct
dib0700_adapter_state),
},
@@ -3550,6 +3591,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
@@ -3558,7 +3601,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib7770p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3600,6 +3643,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk80xx_pid_filter,
@@ -3608,7 +3653,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib807x_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3644,6 +3689,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk80xx_pid_filter,
@@ -3652,11 +3699,13 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib807x_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk80xx_pid_filter,
@@ -3665,7 +3714,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib807x_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3693,6 +3742,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3702,7 +3753,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib809x_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3730,6 +3781,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3739,7 +3792,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = dib9090_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3767,6 +3820,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3776,7 +3831,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = nim8096md_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3804,6 +3859,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3813,7 +3870,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = nim9090md_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3841,6 +3898,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3850,7 +3909,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = nim7090_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3878,6 +3937,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 2,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3887,11 +3948,13 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = tfe7090pvr_tuner0_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -3901,7 +3964,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.tuner_attach = tfe7090pvr_tuner1_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
@@ -3929,11 +3992,13 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = pctv340e_frontend_attach,
.tuner_attach = xc4000_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+ }},
.size_of_priv = sizeof(struct
dib0700_adapter_state),
},
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 4c2a689c820e..a76bbb29ca36 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -23,7 +23,7 @@ int dibusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
if (adap->priv != NULL) {
struct dibusb_state *st = adap->priv;
if (st->ops.fifo_ctrl != NULL)
- if (st->ops.fifo_ctrl(adap->fe,onoff)) {
+ if (st->ops.fifo_ctrl(adap->fe_adap[0].fe, onoff)) {
err("error while controlling the fifo of the demod.");
return -ENODEV;
}
@@ -37,7 +37,8 @@ int dibusb_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onof
if (adap->priv != NULL) {
struct dibusb_state *st = adap->priv;
if (st->ops.pid_ctrl != NULL)
- st->ops.pid_ctrl(adap->fe,index,pid,onoff);
+ st->ops.pid_ctrl(adap->fe_adap[0].fe,
+ index, pid, onoff);
}
return 0;
}
@@ -48,7 +49,7 @@ int dibusb_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
if (adap->priv != NULL) {
struct dibusb_state *st = adap->priv;
if (st->ops.pid_parse != NULL)
- if (st->ops.pid_parse(adap->fe,onoff) < 0)
+ if (st->ops.pid_parse(adap->fe_adap[0].fe, onoff) < 0)
err("could not handle pid_parser");
}
return 0;
@@ -254,8 +255,16 @@ int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap)
msleep(1000);
}
- if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL ||
- (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) {
+ adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
+ &adap->dev->i2c_adap,
+ DEFAULT_DIB3000P_I2C_ADDRESS,
+ &mod3000p_dib3000p_config);
+ if ((adap->fe_adap[0].fe) == NULL)
+ adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
+ &adap->dev->i2c_adap,
+ DEFAULT_DIB3000MC_I2C_ADDRESS,
+ &mod3000p_dib3000p_config);
+ if ((adap->fe_adap[0].fe) != NULL) {
if (adap->priv != NULL) {
struct dibusb_state *st = adap->priv;
st->ops.pid_parse = dib3000mc_pid_parse;
@@ -309,15 +318,15 @@ int dibusb_dib3000mc_tuner_attach(struct dvb_usb_adapter *adap)
}
}
- tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
- if (dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
+ tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
+ if (dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
/* not found - use panasonic pll parameters */
- if (dvb_attach(dvb_pll_attach, adap->fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
+ if (dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
return -ENOMEM;
} else {
st->mt2060_present = 1;
/* set the correct parameters for the dib3000p */
- dib3000mc_set_config(adap->fe, &stk3000p_dib3000p_config);
+ dib3000mc_set_config(adap->fe_adap[0].fe, &stk3000p_dib3000p_config);
}
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 04d91bdd3562..7270791f8340 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -31,11 +31,12 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap)
demod_cfg.demod_address = 0x8;
- if ((adap->fe = dvb_attach(dib3000mb_attach, &demod_cfg,
- &adap->dev->i2c_adap, &st->ops)) == NULL)
+ adap->fe_adap[0].fe = dvb_attach(dib3000mb_attach, &demod_cfg,
+ &adap->dev->i2c_adap, &st->ops);
+ if ((adap->fe_adap[0].fe) == NULL)
return -ENODEV;
- adap->fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
return 0;
}
@@ -46,7 +47,7 @@ static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap)
st->tuner_addr = 0x61;
- dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap,
DVB_PLL_TUA6010XS);
return 0;
}
@@ -57,7 +58,7 @@ static int dibusb_panasonic_tuner_attach(struct dvb_usb_adapter *adap)
st->tuner_addr = 0x60;
- dvb_attach(dvb_pll_attach, adap->fe, 0x60, &adap->dev->i2c_adap,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap,
DVB_PLL_TDA665X);
return 0;
}
@@ -78,16 +79,16 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap)
/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
msg[0].addr = msg[1].addr = st->tuner_addr = 0x60;
- if (adap->fe->ops.i2c_gate_ctrl)
- adap->fe->ops.i2c_gate_ctrl(adap->fe,1);
+ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1);
if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
err("tuner i2c write failed.");
ret = -EREMOTEIO;
}
- if (adap->fe->ops.i2c_gate_ctrl)
- adap->fe->ops.i2c_gate_ctrl(adap->fe,0);
+ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0);
if (b2[0] == 0xfe) {
info("This device has the Thomson Cable onboard. Which is default.");
@@ -185,6 +186,8 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 16,
@@ -205,6 +208,7 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
@@ -272,6 +276,8 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
.pid_filter_count = 16,
@@ -292,6 +298,7 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct dibusb_state),
},
},
@@ -338,6 +345,8 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 16,
@@ -358,6 +367,7 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
@@ -398,6 +408,8 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 16,
@@ -417,6 +429,7 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
index c1d9094b61e5..9c165e2569d4 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -57,6 +57,8 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.streaming_ctrl = dibusb2_0_streaming_ctrl,
@@ -76,6 +78,7 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index f6344cdd360f..f7184111aa64 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -137,11 +137,16 @@ static int digitv_frontend_attach(struct dvb_usb_adapter *adap)
{
struct digitv_state *st = adap->dev->priv;
- if ((adap->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &adap->dev->i2c_adap)) != NULL) {
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach, &digitv_mt352_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL) {
st->is_nxt6000 = 0;
return 0;
}
- if ((adap->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &adap->dev->i2c_adap)) != NULL) {
+ adap->fe_adap[0].fe = dvb_attach(nxt6000_attach,
+ &digitv_nxt6000_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) != NULL) {
st->is_nxt6000 = 1;
return 0;
}
@@ -152,11 +157,11 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
{
struct digitv_state *st = adap->dev->priv;
- if (!dvb_attach(dvb_pll_attach, adap->fe, 0x60, NULL, DVB_PLL_TDED4))
+ if (!dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, NULL, DVB_PLL_TDED4))
return -ENODEV;
if (st->is_nxt6000)
- adap->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
return 0;
}
@@ -292,6 +297,8 @@ static struct dvb_usb_device_properties digitv_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = digitv_frontend_attach,
.tuner_attach = digitv_tuner_attach,
@@ -306,6 +313,7 @@ static struct dvb_usb_device_properties digitv_properties = {
}
}
},
+ }},
}
},
.identify_state = digitv_identify_state,
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index ecd86eca2548..106dfd55ff9c 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -90,7 +90,7 @@ static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = dtt200u_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = dtt200u_fe_attach(adap->dev);
return 0;
}
@@ -140,6 +140,8 @@ static struct dvb_usb_device_properties dtt200u_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
.pid_filter_count = 15,
@@ -157,6 +159,7 @@ static struct dvb_usb_device_properties dtt200u_properties = {
}
}
},
+ }},
}
},
.power_ctrl = dtt200u_power_ctrl,
@@ -187,6 +190,8 @@ static struct dvb_usb_device_properties wt220u_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
.pid_filter_count = 15,
@@ -204,6 +209,7 @@ static struct dvb_usb_device_properties wt220u_properties = {
}
}
},
+ }},
}
},
.power_ctrl = dtt200u_power_ctrl,
@@ -234,6 +240,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
.pid_filter_count = 15,
@@ -251,6 +259,7 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
}
}
},
+ }},
}
},
.power_ctrl = dtt200u_power_ctrl,
@@ -281,6 +290,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
.pid_filter_count = 15,
@@ -298,6 +309,7 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
}
}
},
+ }},
}
},
.power_ctrl = dtt200u_power_ctrl,
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c
index 078ce92ca436..7373132163d2 100644
--- a/drivers/media/dvb/dvb-usb/dtv5100.c
+++ b/drivers/media/dvb/dvb-usb/dtv5100.c
@@ -115,13 +115,13 @@ static struct zl10353_config dtv5100_zl10353_config = {
static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
&adap->dev->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
/* disable i2c gate, or it won't work... is this safe? */
- adap->fe->ops.i2c_gate_ctrl = NULL;
+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
return 0;
}
@@ -133,7 +133,7 @@ static struct qt1010_config dtv5100_qt1010_config = {
static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap)
{
return dvb_attach(qt1010_attach,
- adap->fe, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&dtv5100_qt1010_config) == NULL ? -ENODEV : 0;
}
@@ -180,6 +180,8 @@ static struct dvb_usb_device_properties dtv5100_properties = {
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = dtv5100_frontend_attach,
.tuner_attach = dtv5100_tuner_attach,
@@ -193,6 +195,7 @@ static struct dvb_usb_device_properties dtv5100_properties = {
}
}
},
+ }},
} },
.i2c_algo = &dtv5100_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index b3cb626ed56e..ba4a7517354f 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -17,15 +17,20 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
if (adap == NULL)
return -ENODEV;
+ if ((adap->active_fe < 0) ||
+ (adap->active_fe >= adap->num_frontends_initialized)) {
+ return -EINVAL;
+ }
+
newfeedcount = adap->feedcount + (onoff ? 1 : -1);
/* stop feed before setting a new pid if there will be no pid anymore */
if (newfeedcount == 0) {
deb_ts("stop feeding\n");
- usb_urb_kill(&adap->stream);
+ usb_urb_kill(&adap->fe_adap[adap->active_fe].stream);
- if (adap->props.streaming_ctrl != NULL) {
- ret = adap->props.streaming_ctrl(adap, 0);
+ if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
+ ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 0);
if (ret < 0) {
err("error while stopping stream.");
return ret;
@@ -36,36 +41,37 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
adap->feedcount = newfeedcount;
/* activate the pid on the device specific pid_filter */
- deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",adap->pid_filtering ?
- "yes" : "no", dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ?
- "on" : "off");
- if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
- adap->pid_filtering &&
- adap->props.pid_filter != NULL)
- adap->props.pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid,onoff);
+ deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",
+ adap->fe_adap[adap->active_fe].pid_filtering ?
+ "yes" : "no", dvbdmxfeed->pid, dvbdmxfeed->pid,
+ dvbdmxfeed->index, onoff ? "on" : "off");
+ if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+ adap->fe_adap[adap->active_fe].pid_filtering &&
+ adap->props.fe[adap->active_fe].pid_filter != NULL)
+ adap->props.fe[adap->active_fe].pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
/* start the feed if this was the first feed and there is still a feed
* for reception.
*/
if (adap->feedcount == onoff && adap->feedcount > 0) {
deb_ts("submitting all URBs\n");
- usb_urb_submit(&adap->stream);
+ usb_urb_submit(&adap->fe_adap[adap->active_fe].stream);
deb_ts("controlling pid parser\n");
- if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
- adap->props.caps &
+ if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+ adap->props.fe[adap->active_fe].caps &
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
- adap->props.pid_filter_ctrl != NULL) {
- ret = adap->props.pid_filter_ctrl(adap,
- adap->pid_filtering);
+ adap->props.fe[adap->active_fe].pid_filter_ctrl != NULL) {
+ ret = adap->props.fe[adap->active_fe].pid_filter_ctrl(adap,
+ adap->fe_adap[adap->active_fe].pid_filtering);
if (ret < 0) {
err("could not handle pid_parser");
return ret;
}
}
deb_ts("start feeding\n");
- if (adap->props.streaming_ctrl != NULL) {
- ret = adap->props.streaming_ctrl(adap, 1);
+ if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
+ ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 1);
if (ret < 0) {
err("error while enabling fifo.");
return ret;
@@ -90,6 +96,7 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
{
+ int i;
int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
adap->dev->owner, &adap->dev->udev->dev,
adapter_nums);
@@ -112,7 +119,12 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
adap->demux.priv = adap;
- adap->demux.feednum = adap->demux.filternum = adap->max_feed_count;
+ adap->demux.filternum = 0;
+ for (i = 0; i < adap->props.num_frontends; i++) {
+ if (adap->demux.filternum < adap->fe_adap[i].max_feed_count)
+ adap->demux.filternum = adap->fe_adap[i].max_feed_count;
+ }
+ adap->demux.feednum = adap->demux.filternum;
adap->demux.start_feed = dvb_usb_start_feed;
adap->demux.stop_feed = dvb_usb_stop_feed;
adap->demux.write_to_decoder = NULL;
@@ -156,14 +168,33 @@ int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap)
return 0;
}
+static int dvb_usb_set_active_fe(struct dvb_frontend *fe, int onoff)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+
+ int ret = (adap->props.frontend_ctrl) ?
+ adap->props.frontend_ctrl(fe, onoff) : 0;
+
+ if (ret < 0) {
+ err("frontend_ctrl request failed");
+ return ret;
+ }
+ if (onoff)
+ adap->active_fe = fe->id;
+
+ return 0;
+}
+
static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
dvb_usb_device_power_ctrl(adap->dev, 1);
- if (adap->fe_init)
- adap->fe_init(fe);
+ dvb_usb_set_active_fe(fe, 1);
+
+ if (adap->fe_adap[fe->id].fe_init)
+ adap->fe_adap[fe->id].fe_init(fe);
return 0;
}
@@ -172,45 +203,81 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
- if (adap->fe_sleep)
- adap->fe_sleep(fe);
+ if (adap->fe_adap[fe->id].fe_sleep)
+ adap->fe_adap[fe->id].fe_sleep(fe);
+
+ dvb_usb_set_active_fe(fe, 0);
return dvb_usb_device_power_ctrl(adap->dev, 0);
}
int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
{
- if (adap->props.frontend_attach == NULL) {
- err("strange: '%s' #%d doesn't want to attach a frontend.",adap->dev->desc->name, adap->id);
- return 0;
- }
+ int ret, i;
- /* re-assign sleep and wakeup functions */
- if (adap->props.frontend_attach(adap) == 0 && adap->fe != NULL) {
- adap->fe_init = adap->fe->ops.init; adap->fe->ops.init = dvb_usb_fe_wakeup;
- adap->fe_sleep = adap->fe->ops.sleep; adap->fe->ops.sleep = dvb_usb_fe_sleep;
+ /* register all given adapter frontends */
+ for (i = 0; i < adap->props.num_frontends; i++) {
- if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
- err("Frontend registration failed.");
- dvb_frontend_detach(adap->fe);
- adap->fe = NULL;
- return -ENODEV;
+ if (adap->props.fe[i].frontend_attach == NULL) {
+ err("strange: '%s' #%d,%d "
+ "doesn't want to attach a frontend.",
+ adap->dev->desc->name, adap->id, i);
+
+ return 0;
+ }
+
+ ret = adap->props.fe[i].frontend_attach(adap);
+ if (ret || adap->fe_adap[i].fe == NULL) {
+ /* only print error when there is no FE at all */
+ if (i == 0)
+ err("no frontend was attached by '%s'",
+ adap->dev->desc->name);
+
+ return 0;
+ }
+
+ adap->fe_adap[i].fe->id = i;
+
+ /* re-assign sleep and wakeup functions */
+ adap->fe_adap[i].fe_init = adap->fe_adap[i].fe->ops.init;
+ adap->fe_adap[i].fe->ops.init = dvb_usb_fe_wakeup;
+ adap->fe_adap[i].fe_sleep = adap->fe_adap[i].fe->ops.sleep;
+ adap->fe_adap[i].fe->ops.sleep = dvb_usb_fe_sleep;
+
+ if (dvb_register_frontend(&adap->dvb_adap, adap->fe_adap[i].fe)) {
+ err("Frontend %d registration failed.", i);
+ dvb_frontend_detach(adap->fe_adap[i].fe);
+ adap->fe_adap[i].fe = NULL;
+ /* In error case, do not try register more FEs,
+ * still leaving already registered FEs alive. */
+ if (i == 0)
+ return -ENODEV;
+ else
+ return 0;
}
/* only attach the tuner if the demod is there */
- if (adap->props.tuner_attach != NULL)
- adap->props.tuner_attach(adap);
- } else
- err("no frontend was attached by '%s'",adap->dev->desc->name);
+ if (adap->props.fe[i].tuner_attach != NULL)
+ adap->props.fe[i].tuner_attach(adap);
+
+ adap->num_frontends_initialized++;
+ }
return 0;
}
int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap)
{
- if (adap->fe != NULL) {
- dvb_unregister_frontend(adap->fe);
- dvb_frontend_detach(adap->fe);
+ int i = adap->num_frontends_initialized - 1;
+
+ /* unregister all given adapter frontends */
+ for (; i >= 0; i--) {
+ if (adap->fe_adap[i].fe != NULL) {
+ dvb_unregister_frontend(adap->fe_adap[i].fe);
+ dvb_frontend_detach(adap->fe_adap[i].fe);
+ }
}
+ adap->num_frontends_initialized = 0;
+
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 2a79b8fb3e8d..2ad33ba92ba2 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -136,6 +136,7 @@
#define USB_PID_KWORLD_PC160_2T 0xc160
#define USB_PID_KWORLD_PC160_T 0xc161
#define USB_PID_KWORLD_UB383_T 0xe383
+#define USB_PID_KWORLD_UB499_2T_T09 0xe409
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
#define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055
@@ -240,6 +241,9 @@
#define USB_PID_PCTV_200E 0x020e
#define USB_PID_PCTV_400E 0x020f
#define USB_PID_PCTV_450E 0x0222
+#define USB_PID_PCTV_452E 0x021f
+#define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007
+#define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a
#define USB_PID_NEBULA_DIGITV 0x0201
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index 2e3ea0fa28e0..169196ec2d4e 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -29,7 +29,7 @@ MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID
static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
{
struct dvb_usb_adapter *adap;
- int ret, n;
+ int ret, n, o;
for (n = 0; n < d->props.num_adapters; n++) {
adap = &d->adapter[n];
@@ -38,31 +38,42 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties));
+ for (o = 0; o < adap->props.num_frontends; o++) {
+ struct dvb_usb_adapter_fe_properties *props = &adap->props.fe[o];
/* speed - when running at FULL speed we need a HW PID filter */
- if (d->udev->speed == USB_SPEED_FULL && !(adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
+ if (d->udev->speed == USB_SPEED_FULL && !(props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
return -ENODEV;
}
- if ((d->udev->speed == USB_SPEED_FULL && adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
- (adap->props.caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
- info("will use the device's hardware PID filter (table count: %d).", adap->props.pid_filter_count);
- adap->pid_filtering = 1;
- adap->max_feed_count = adap->props.pid_filter_count;
+ if ((d->udev->speed == USB_SPEED_FULL && props->caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
+ (props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
+ info("will use the device's hardware PID filter (table count: %d).", props->pid_filter_count);
+ adap->fe_adap[o].pid_filtering = 1;
+ adap->fe_adap[o].max_feed_count = props->pid_filter_count;
} else {
info("will pass the complete MPEG2 transport stream to the software demuxer.");
- adap->pid_filtering = 0;
- adap->max_feed_count = 255;
+ adap->fe_adap[o].pid_filtering = 0;
+ adap->fe_adap[o].max_feed_count = 255;
}
- if (!adap->pid_filtering &&
+ if (!adap->fe_adap[o].pid_filtering &&
dvb_usb_force_pid_filter_usage &&
- adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) {
+ props->caps & DVB_USB_ADAP_HAS_PID_FILTER) {
info("pid filter enabled by module option.");
- adap->pid_filtering = 1;
- adap->max_feed_count = adap->props.pid_filter_count;
+ adap->fe_adap[o].pid_filtering = 1;
+ adap->fe_adap[o].max_feed_count = props->pid_filter_count;
}
+ if (props->size_of_priv > 0) {
+ adap->fe_adap[o].priv = kzalloc(props->size_of_priv, GFP_KERNEL);
+ if (adap->fe_adap[o].priv == NULL) {
+ err("no memory for priv for adapter %d fe %d.", n, o);
+ return -ENOMEM;
+ }
+ }
+ }
+
if (adap->props.size_of_priv > 0) {
adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL);
if (adap->priv == NULL) {
@@ -77,6 +88,10 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
return ret;
}
+ /* use exclusive FE lock if there is multiple shared FEs */
+ if (adap->fe_adap[1].fe)
+ adap->dvb_adap.mfe_shared = 1;
+
d->num_adapters_initialized++;
d->state |= DVB_USB_STATE_DVB;
}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
index bb46ba6a3573..53a5c30b51b2 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -82,16 +82,28 @@ static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buffer
int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
{
- adap->stream.udev = adap->dev->udev;
- if (adap->props.caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
- adap->stream.complete = dvb_usb_data_complete_204;
- else
- adap->stream.complete = dvb_usb_data_complete;
- adap->stream.user_priv = adap;
- return usb_urb_init(&adap->stream, &adap->props.stream);
+ int i, ret = 0;
+ for (i = 0; i < adap->props.num_frontends; i++) {
+
+ adap->fe_adap[i].stream.udev = adap->dev->udev;
+ if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
+ adap->fe_adap[i].stream.complete =
+ dvb_usb_data_complete_204;
+ else
+ adap->fe_adap[i].stream.complete = dvb_usb_data_complete;
+ adap->fe_adap[i].stream.user_priv = adap;
+ ret = usb_urb_init(&adap->fe_adap[i].stream,
+ &adap->props.fe[i].stream);
+ if (ret < 0)
+ break;
+ }
+ return ret;
}
int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap)
{
- return usb_urb_exit(&adap->stream);
+ int i;
+ for (i = 0; i < adap->props.num_frontends; i++)
+ usb_urb_exit(&adap->fe_adap[i].stream);
+ return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 7d35d078342b..6d7d13f9ce68 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -124,6 +124,8 @@ struct usb_data_stream_properties {
* @caps: capabilities of the DVB USB device.
* @pid_filter_count: number of PID filter position in the optional hardware
* PID-filter.
+ * @num_frontends: number of frontends of the DVB USB adapter.
+ * @frontend_ctrl: called to power on/off active frontend.
* @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the
* device (not URB submitting/killing).
* @pid_filter_ctrl: called to en/disable the PID filter, if any.
@@ -134,7 +136,7 @@ struct usb_data_stream_properties {
* pll_desc and pll_init_buf of struct dvb_usb_device).
* @stream: configuration of the USB streaming
*/
-struct dvb_usb_adapter_properties {
+struct dvb_usb_adapter_fe_properties {
#define DVB_USB_ADAP_HAS_PID_FILTER 0x01
#define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02
#define DVB_USB_ADAP_NEED_PID_FILTERING 0x04
@@ -152,9 +154,18 @@ struct dvb_usb_adapter_properties {
struct usb_data_stream_properties stream;
int size_of_priv;
+};
+
+#define MAX_NO_OF_FE_PER_ADAP 2
+struct dvb_usb_adapter_properties {
+ int size_of_priv;
+ int (*frontend_ctrl) (struct dvb_frontend *, int);
int (*fe_ioctl_override) (struct dvb_frontend *,
unsigned int, void *, unsigned int);
+
+ int num_frontends;
+ struct dvb_usb_adapter_fe_properties fe[MAX_NO_OF_FE_PER_ADAP];
};
/**
@@ -345,6 +356,20 @@ struct usb_data_stream {
*
* @stream: the usb data stream.
*/
+struct dvb_usb_fe_adapter {
+ struct dvb_frontend *fe;
+
+ int (*fe_init) (struct dvb_frontend *);
+ int (*fe_sleep) (struct dvb_frontend *);
+
+ struct usb_data_stream stream;
+
+ int pid_filtering;
+ int max_feed_count;
+
+ void *priv;
+};
+
struct dvb_usb_adapter {
struct dvb_usb_device *dev;
struct dvb_usb_adapter_properties props;
@@ -356,20 +381,16 @@ struct dvb_usb_adapter {
u8 id;
int feedcount;
- int pid_filtering;
/* dvb */
struct dvb_adapter dvb_adap;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dvb_net dvb_net;
- struct dvb_frontend *fe;
- int max_feed_count;
-
- int (*fe_init) (struct dvb_frontend *);
- int (*fe_sleep) (struct dvb_frontend *);
- struct usb_data_stream stream;
+ struct dvb_usb_fe_adapter fe_adap[MAX_NO_OF_FE_PER_ADAP];
+ int active_fe;
+ int num_frontends_initialized;
void *priv;
};
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index 058b2318abed..f103ec1fe82e 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -992,18 +992,18 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
struct dvb_tuner_ops *tuner_ops = NULL;
if (demod_probe & 4) {
- d->fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
+ d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
&d->dev->i2c_adap, 0);
- if (d->fe != NULL) {
- if (dvb_attach(stb6100_attach, d->fe,
+ if (d->fe_adap[0].fe != NULL) {
+ if (dvb_attach(stb6100_attach, d->fe_adap[0].fe,
&dw2104a_stb6100_config,
&d->dev->i2c_adap)) {
- tuner_ops = &d->fe->ops.tuner_ops;
+ tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops;
tuner_ops->set_frequency = stb6100_set_freq;
tuner_ops->get_frequency = stb6100_get_freq;
tuner_ops->set_bandwidth = stb6100_set_bandw;
tuner_ops->get_bandwidth = stb6100_get_bandw;
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached STV0900+STB6100!\n");
return 0;
}
@@ -1011,13 +1011,13 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
}
if (demod_probe & 2) {
- d->fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
+ d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
&d->dev->i2c_adap, 0);
- if (d->fe != NULL) {
- if (dvb_attach(stv6110_attach, d->fe,
+ if (d->fe_adap[0].fe != NULL) {
+ if (dvb_attach(stv6110_attach, d->fe_adap[0].fe,
&dw2104_stv6110_config,
&d->dev->i2c_adap)) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached STV0900+STV6110A!\n");
return 0;
}
@@ -1025,19 +1025,19 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
}
if (demod_probe & 1) {
- d->fe = dvb_attach(cx24116_attach, &dw2104_config,
+ d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ if (d->fe_adap[0].fe != NULL) {
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached cx24116!\n");
return 0;
}
}
- d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
+ d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ if (d->fe_adap[0].fe != NULL) {
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached DS3000!\n");
return 0;
}
@@ -1053,22 +1053,22 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
{
if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
/*dw2102_properties.adapter->tuner_attach = NULL;*/
- d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
+ d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ if (d->fe_adap[0].fe != NULL) {
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached si21xx!\n");
return 0;
}
}
if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
- d->fe = dvb_attach(stv0288_attach, &earda_config,
+ d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- if (dvb_attach(stb6000_attach, d->fe, 0x61,
+ if (d->fe_adap[0].fe != NULL) {
+ if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61,
&d->dev->i2c_adap)) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached stv0288!\n");
return 0;
}
@@ -1077,10 +1077,10 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
- d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
+ d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ if (d->fe_adap[0].fe != NULL) {
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached stv0299!\n");
return 0;
}
@@ -1090,9 +1090,9 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
{
- d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
+ d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
&d->dev->i2c_adap, 0x48);
- if (d->fe != NULL) {
+ if (d->fe_adap[0].fe != NULL) {
info("Attached tda10023!\n");
return 0;
}
@@ -1101,12 +1101,12 @@ static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
{
- d->fe = dvb_attach(mt312_attach, &zl313_config,
+ d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config,
&d->dev->i2c_adap);
- if (d->fe != NULL) {
- if (dvb_attach(zl10039_attach, d->fe, 0x60,
+ if (d->fe_adap[0].fe != NULL) {
+ if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60,
&d->dev->i2c_adap)) {
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
info("Attached zl100313+zl10039!\n");
return 0;
}
@@ -1119,16 +1119,16 @@ static int stv0288_frontend_attach(struct dvb_usb_adapter *d)
{
u8 obuf[] = {7, 1};
- d->fe = dvb_attach(stv0288_attach, &earda_config,
+ d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
&d->dev->i2c_adap);
- if (d->fe == NULL)
+ if (d->fe_adap[0].fe == NULL)
return -EIO;
- if (NULL == dvb_attach(stb6000_attach, d->fe, 0x61, &d->dev->i2c_adap))
+ if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap))
return -EIO;
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
@@ -1143,14 +1143,14 @@ static int ds3000_frontend_attach(struct dvb_usb_adapter *d)
struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
u8 obuf[] = {7, 1};
- d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
+ d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
&d->dev->i2c_adap);
- if (d->fe == NULL)
+ if (d->fe_adap[0].fe == NULL)
return -EIO;
- st->old_set_voltage = d->fe->ops.set_voltage;
- d->fe->ops.set_voltage = s660_set_voltage;
+ st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage;
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
@@ -1163,12 +1163,12 @@ static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
{
u8 obuf[] = {7, 1};
- d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
+ d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
&d->dev->i2c_adap, 0);
- if (d->fe == NULL)
+ if (d->fe_adap[0].fe == NULL)
return -EIO;
- d->fe->ops.set_voltage = dw210x_set_voltage;
+ d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
@@ -1204,9 +1204,9 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d)
if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
err("command 0x51 transfer failed.");
- d->fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
+ d->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
&d->dev->i2c_adap);
- if (d->fe == NULL)
+ if (d->fe_adap[0].fe == NULL)
return -EIO;
info("Attached DS3000!\n");
@@ -1216,14 +1216,14 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d)
static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
&adap->dev->i2c_adap, DVB_PLL_OPERA1);
return 0;
}
static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
&adap->dev->i2c_adap, DVB_PLL_TUA6034);
return 0;
@@ -1535,7 +1535,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
DW210X_READ_MSG);
if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
dw2102_properties.i2c_algo = &dw2102_i2c_algo;
- dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;
+ dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach;
break;
} else {
/* check STV0288 frontend */
@@ -1591,6 +1591,8 @@ static struct dvb_usb_device_properties dw2102_properties = {
.read_mac_address = dw210x_read_mac_address,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = dw2102_frontend_attach,
.stream = {
.type = USB_BULK,
@@ -1602,6 +1604,7 @@ static struct dvb_usb_device_properties dw2102_properties = {
}
}
},
+ }},
}
},
.num_device_descs = 3,
@@ -1642,6 +1645,8 @@ static struct dvb_usb_device_properties dw2104_properties = {
.read_mac_address = dw210x_read_mac_address,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = dw2104_frontend_attach,
.stream = {
.type = USB_BULK,
@@ -1653,6 +1658,7 @@ static struct dvb_usb_device_properties dw2104_properties = {
}
}
},
+ }},
}
},
.num_device_descs = 2,
@@ -1689,6 +1695,8 @@ static struct dvb_usb_device_properties dw3101_properties = {
.read_mac_address = dw210x_read_mac_address,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = dw3101_frontend_attach,
.tuner_attach = dw3101_tuner_attach,
.stream = {
@@ -1701,6 +1709,7 @@ static struct dvb_usb_device_properties dw3101_properties = {
}
}
},
+ }},
}
},
.num_device_descs = 1,
@@ -1733,6 +1742,8 @@ static struct dvb_usb_device_properties s6x0_properties = {
.read_mac_address = s6x0_read_mac_address,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = zl100313_frontend_attach,
.stream = {
.type = USB_BULK,
@@ -1744,6 +1755,7 @@ static struct dvb_usb_device_properties s6x0_properties = {
}
}
},
+ }},
}
},
.num_device_descs = 1,
@@ -1810,6 +1822,8 @@ static struct dvb_usb_device_properties su3000_properties = {
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = su3000_streaming_ctrl,
.frontend_attach = su3000_frontend_attach,
.stream = {
@@ -1822,6 +1836,7 @@ static struct dvb_usb_device_properties su3000_properties = {
}
}
}
+ }},
}
},
.num_device_descs = 3,
@@ -1855,7 +1870,7 @@ static int dw2102_probe(struct usb_interface *intf,
p1100->devices[0] = d1100;
p1100->rc.legacy.rc_map_table = rc_map_tbs_table;
p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
- p1100->adapter->frontend_attach = stv0288_frontend_attach;
+ p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
if (!s660) {
@@ -1869,7 +1884,7 @@ static int dw2102_probe(struct usb_interface *intf,
s660->devices[0] = d660;
s660->devices[1] = d480_1;
s660->devices[2] = d480_2;
- s660->adapter->frontend_attach = ds3000_frontend_attach;
+ s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
if (!p7500) {
@@ -1883,7 +1898,7 @@ static int dw2102_probe(struct usb_interface *intf,
p7500->devices[0] = d7500;
p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
- p7500->adapter->frontend_attach = prof_7500_frontend_attach;
+ p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
THIS_MODULE, NULL, adapter_nr) ||
diff --git a/drivers/media/dvb/dvb-usb/ec168.c b/drivers/media/dvb/dvb-usb/ec168.c
index 1ba3e5dbee10..78442fe4aa5e 100644
--- a/drivers/media/dvb/dvb-usb/ec168.c
+++ b/drivers/media/dvb/dvb-usb/ec168.c
@@ -200,9 +200,9 @@ static struct ec100_config ec168_ec100_config = {
static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)
{
deb_info("%s:\n", __func__);
- adap->fe = dvb_attach(ec100_attach, &ec168_ec100_config,
+ adap->fe_adap[0].fe = dvb_attach(ec100_attach, &ec168_ec100_config,
&adap->dev->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
return 0;
@@ -228,7 +228,7 @@ static struct mxl5005s_config ec168_mxl5003s_config = {
static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
{
deb_info("%s:\n", __func__);
- return dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
+ return dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&ec168_mxl5003s_config) == NULL ? -ENODEV : 0;
}
@@ -382,6 +382,8 @@ static struct dvb_usb_device_properties ec168_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = ec168_streaming_ctrl,
.frontend_attach = ec168_ec100_frontend_attach,
.tuner_attach = ec168_mxl5003s_tuner_attach,
@@ -395,6 +397,7 @@ static struct dvb_usb_device_properties ec168_properties = {
}
}
},
+ }},
}
},
diff --git a/drivers/media/dvb/dvb-usb/friio.c b/drivers/media/dvb/dvb-usb/friio.c
index 76159aed9bb0..b092dc2137cd 100644
--- a/drivers/media/dvb/dvb-usb/friio.c
+++ b/drivers/media/dvb/dvb-usb/friio.c
@@ -403,8 +403,8 @@ static int friio_frontend_attach(struct dvb_usb_adapter *adap)
if (friio_initialize(adap->dev) < 0)
return -EIO;
- adap->fe = jdvbt90502_attach(adap->dev);
- if (adap->fe == NULL)
+ adap->fe_adap[0].fe = jdvbt90502_attach(adap->dev);
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
return 0;
@@ -473,6 +473,8 @@ static struct dvb_usb_device_properties friio_properties = {
/* caps:0 => no pid filter, 188B TS packet */
/* GL861 has a HW pid filter, but no info available. */
{
+ .num_frontends = 1,
+ .fe = {{
.caps = 0,
.frontend_attach = friio_frontend_attach,
@@ -490,6 +492,7 @@ static struct dvb_usb_device_properties friio_properties = {
}
}
},
+ }},
}
},
.i2c_algo = &gl861_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c
index 6f596ed41761..63681df244c4 100644
--- a/drivers/media/dvb/dvb-usb/gl861.c
+++ b/drivers/media/dvb/dvb-usb/gl861.c
@@ -103,9 +103,9 @@ static struct zl10353_config gl861_zl10353_config = {
static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
&adap->dev->i2c_adap);
- if (adap->fe == NULL)
+ if (adap->fe_adap[0].fe == NULL)
return -EIO;
return 0;
@@ -118,7 +118,7 @@ static struct qt1010_config gl861_qt1010_config = {
static int gl861_tuner_attach(struct dvb_usb_adapter *adap)
{
return dvb_attach(qt1010_attach,
- adap->fe, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe, &adap->dev->i2c_adap,
&gl861_qt1010_config) == NULL ? -ENODEV : 0;
}
@@ -167,6 +167,8 @@ static struct dvb_usb_device_properties gl861_properties = {
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = gl861_frontend_attach,
.tuner_attach = gl861_tuner_attach,
@@ -181,6 +183,7 @@ static struct dvb_usb_device_properties gl861_properties = {
}
}
},
+ }},
} },
.i2c_algo = &gl861_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
index 60d11e57e7d0..5426267980c7 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
@@ -144,19 +144,25 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
cmd[6] = (freq >> 16) & 0xff;
cmd[7] = (freq >> 24) & 0xff;
+ /* backwards compatibility: DVB-S + 8-PSK were used for Turbo-FEC */
+ if (c->delivery_system == SYS_DVBS && c->modulation == PSK_8)
+ c->delivery_system = SYS_TURBO;
+
switch (c->delivery_system) {
case SYS_DVBS:
- /* Allow QPSK and 8PSK (even for DVB-S) */
- if (c->modulation != QPSK && c->modulation != PSK_8) {
+ if (c->modulation != QPSK) {
deb_fe("%s: unsupported modulation selected (%d)\n",
__func__, c->modulation);
return -EOPNOTSUPP;
}
c->fec_inner = FEC_AUTO;
break;
- case SYS_DVBS2:
+ case SYS_DVBS2: /* kept for backwards compatibility */
deb_fe("%s: DVB-S2 delivery system selected\n", __func__);
break;
+ case SYS_TURBO:
+ deb_fe("%s: Turbo-FEC delivery system selected\n", __func__);
+ break;
default:
deb_fe("%s: unsupported delivery system selected (%d)\n",
@@ -189,7 +195,10 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
default:
cmd[9] = 5; break;
}
- cmd[8] = ADV_MOD_DVB_QPSK;
+ if (c->delivery_system == SYS_TURBO)
+ cmd[8] = ADV_MOD_TURBO_QPSK;
+ else
+ cmd[8] = ADV_MOD_DVB_QPSK;
break;
case PSK_8: /* PSK_8 is for compatibility with DN */
cmd[8] = ADV_MOD_TURBO_8PSK;
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
index 1cb3d9a66e02..5f71284703d0 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -230,7 +230,7 @@ static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
{
- adap->fe = gp8psk_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = gp8psk_fe_attach(adap->dev);
return 0;
}
@@ -268,6 +268,8 @@ static struct dvb_usb_device_properties gp8psk_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = gp8psk_streaming_ctrl,
.frontend_attach = gp8psk_frontend_attach,
/* parameter for the MPEG2-data transfer */
@@ -281,6 +283,7 @@ static struct dvb_usb_device_properties gp8psk_properties = {
}
}
},
+ }},
}
},
.power_ctrl = gp8psk_power_ctrl,
diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c
new file mode 100644
index 000000000000..f027a2c1c3e8
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/it913x.c
@@ -0,0 +1,651 @@
+/* DVB USB compliant linux driver for IT9137
+ *
+ * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ * IT9137 (C) ITE Tech Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/dvb/it9137.txt for firmware information
+ *
+ */
+#define DVB_USB_LOG_PREFIX "it913x"
+
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <media/rc-core.h>
+
+#include "dvb-usb.h"
+#include "it913x-fe.h"
+
+/* debug */
+static int dvb_usb_it913x_debug;
+#define l_dprintk(var, level, args...) do { \
+ if ((var >= level)) \
+ printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \
+} while (0)
+
+#define deb_info(level, args...) l_dprintk(dvb_usb_it913x_debug, level, args)
+#define debug_data_snipet(level, name, p) \
+ deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
+ *p, *(p+1), *(p+2), *(p+3), *(p+4), \
+ *(p+5), *(p+6), *(p+7));
+
+
+module_param_named(debug, dvb_usb_it913x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."
+ DVB_USB_DEBUG_STATUS);
+
+static int pid_filter;
+module_param_named(pid, pid_filter, int, 0644);
+MODULE_PARM_DESC(pid, "set default 0=on 1=off");
+
+int cmd_counter;
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct it913x_state {
+ u8 id;
+};
+
+static int it913x_bulk_write(struct usb_device *dev,
+ u8 *snd, int len, u8 pipe)
+{
+ int ret, actual_l;
+
+ ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
+ snd, len , &actual_l, 100);
+ return ret;
+}
+
+static int it913x_bulk_read(struct usb_device *dev,
+ u8 *rev, int len, u8 pipe)
+{
+ int ret, actual_l;
+
+ ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
+ rev, len , &actual_l, 200);
+ return ret;
+}
+
+static u16 check_sum(u8 *p, u8 len)
+{
+ u16 sum = 0;
+ u8 i = 1;
+ while (i < len)
+ sum += (i++ & 1) ? (*p++) << 8 : *p++;
+ return ~sum;
+}
+
+static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
+ u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
+{
+ int ret = 0, i, buf_size = 1;
+ u8 *buff;
+ u8 rlen;
+ u16 chk_sum;
+
+ buff = kzalloc(256, GFP_KERNEL);
+ if (!buff) {
+ info("USB Buffer Failed");
+ return -ENOMEM;
+ }
+
+ buff[buf_size++] = pro;
+ buff[buf_size++] = cmd;
+ buff[buf_size++] = cmd_counter;
+
+ switch (mode) {
+ case READ_LONG:
+ case WRITE_LONG:
+ buff[buf_size++] = len;
+ buff[buf_size++] = 2;
+ buff[buf_size++] = (reg >> 24);
+ buff[buf_size++] = (reg >> 16) & 0xff;
+ buff[buf_size++] = (reg >> 8) & 0xff;
+ buff[buf_size++] = reg & 0xff;
+ break;
+ case READ_SHORT:
+ buff[buf_size++] = addr;
+ break;
+ case WRITE_SHORT:
+ buff[buf_size++] = len;
+ buff[buf_size++] = addr;
+ buff[buf_size++] = (reg >> 8) & 0xff;
+ buff[buf_size++] = reg & 0xff;
+ break;
+ case READ_DATA:
+ case WRITE_DATA:
+ break;
+ case WRITE_CMD:
+ mode = 7;
+ break;
+ default:
+ kfree(buff);
+ return -EINVAL;
+ }
+
+ if (mode & 1) {
+ for (i = 0; i < len ; i++)
+ buff[buf_size++] = data[i];
+ }
+ chk_sum = check_sum(&buff[1], buf_size);
+
+ buff[buf_size++] = chk_sum >> 8;
+ buff[0] = buf_size;
+ buff[buf_size++] = (chk_sum & 0xff);
+
+ ret = it913x_bulk_write(udev, buff, buf_size , 0x02);
+
+ ret |= it913x_bulk_read(udev, buff, (mode & 1) ?
+ 5 : len + 5 , 0x01);
+
+ rlen = (mode & 0x1) ? 0x1 : len;
+
+ if (mode & 1)
+ ret |= buff[2];
+ else
+ memcpy(data, &buff[3], rlen);
+
+ cmd_counter++;
+
+ kfree(buff);
+
+ return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_wr_reg(struct usb_device *udev, u8 pro, u32 reg , u8 data)
+{
+ int ret;
+ u8 b[1];
+ b[0] = data;
+ ret = it913x_io(udev, WRITE_LONG, pro,
+ CMD_DEMOD_WRITE, reg, 0, b, sizeof(b));
+
+ return ret;
+}
+
+static int it913x_read_reg(struct usb_device *udev, u32 reg)
+{
+ int ret;
+ u8 data[1];
+
+ ret = it913x_io(udev, READ_LONG, DEV_0,
+ CMD_DEMOD_READ, reg, 0, &data[0], 1);
+
+ return (ret < 0) ? ret : data[0];
+}
+
+static u32 it913x_query(struct usb_device *udev, u8 pro)
+{
+ int ret;
+ u32 res = 0;
+ u8 data[4];
+ ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
+ 0x1222, 0, &data[0], 1);
+ if (data[0] == 0x1) {
+ ret = it913x_io(udev, READ_SHORT, pro,
+ CMD_QUERYINFO, 0, 0x1, &data[0], 4);
+ res = (data[0] << 24) + (data[1] << 16) +
+ (data[2] << 8) + data[3];
+ }
+
+ return (ret < 0) ? 0 : res;
+}
+
+static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+ int ret = 0;
+ u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+ if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+ return -EAGAIN;
+ deb_info(1, "PID_C (%02x)", onoff);
+
+ if (!onoff)
+ ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
+
+ mutex_unlock(&adap->dev->i2c_mutex);
+ return ret;
+}
+
+static int it913x_pid_filter(struct dvb_usb_adapter *adap,
+ int index, u16 pid, int onoff)
+{
+ struct usb_device *udev = adap->dev->udev;
+ int ret = 0;
+ u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+ if (pid_filter > 0)
+ return 0;
+
+ if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+ return -EAGAIN;
+ deb_info(1, "PID_F (%02x)", onoff);
+ if (onoff) {
+ ret = it913x_wr_reg(udev, pro, PID_EN, 0x1);
+
+ ret |= it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff));
+
+ ret |= it913x_wr_reg(udev, pro, PID_MSB, (u8)(pid >> 8));
+
+ ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff);
+
+ ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
+
+ }
+
+ mutex_unlock(&adap->dev->i2c_mutex);
+ return 0;
+}
+
+
+static int it913x_return_status(struct usb_device *udev)
+{
+ u32 firm = 0;
+
+ firm = it913x_query(udev, DEV_0);
+ if (firm > 0)
+ info("Firmware Version %d", firm);
+
+ return (firm > 0) ? firm : 0;
+}
+
+static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ static u8 data[256];
+ int ret;
+ u32 reg;
+ u8 pro;
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ debug_data_snipet(1, "Message out", msg[0].buf);
+ deb_info(2, "num of messages %d address %02x", num, msg[0].addr);
+
+ pro = (msg[0].addr & 0x2) ? DEV_0_DMOD : 0x0;
+ pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0;
+ memcpy(data, msg[0].buf, msg[0].len);
+ reg = (data[0] << 24) + (data[1] << 16) +
+ (data[2] << 8) + data[3];
+ if (num == 2) {
+ ret = it913x_io(d->udev, READ_LONG, pro,
+ CMD_DEMOD_READ, reg, 0, data, msg[1].len);
+ memcpy(msg[1].buf, data, msg[1].len);
+ } else
+ ret = it913x_io(d->udev, WRITE_LONG, pro, CMD_DEMOD_WRITE,
+ reg, 0, &data[4], msg[0].len - 4);
+
+ mutex_unlock(&d->i2c_mutex);
+
+ return ret;
+}
+
+static u32 it913x_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm it913x_i2c_algo = {
+ .master_xfer = it913x_i2c_xfer,
+ .functionality = it913x_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+#define IT913X_POLL 250
+static int it913x_rc_query(struct dvb_usb_device *d)
+{
+ u8 ibuf[4];
+ int ret;
+ u32 key;
+ /* Avoid conflict with frontends*/
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET,
+ 0, 0, &ibuf[0], sizeof(ibuf));
+
+ if ((ibuf[2] + ibuf[3]) == 0xff) {
+ key = ibuf[2];
+ key += ibuf[0] << 8;
+ deb_info(1, "INT Key =%08x", key);
+ if (d->rc_dev != NULL)
+ rc_keydown(d->rc_dev, key, 0);
+ }
+ mutex_unlock(&d->i2c_mutex);
+
+ return ret;
+}
+static int it913x_identify_state(struct usb_device *udev,
+ struct dvb_usb_device_properties *props,
+ struct dvb_usb_device_description **desc,
+ int *cold)
+{
+ int ret = 0, firm_no;
+ u8 reg, adap, ep, tun0, tun1;
+
+ firm_no = it913x_return_status(udev);
+
+ ep = it913x_read_reg(udev, 0x49ac);
+ adap = it913x_read_reg(udev, 0x49c5);
+ tun0 = it913x_read_reg(udev, 0x49d0);
+ info("No. Adapters=%x Endpoints=%x Tuner Type=%x", adap, ep, tun0);
+
+ if (firm_no > 0) {
+ *cold = 0;
+ return 0;
+ }
+
+ if (adap > 2) {
+ tun1 = it913x_read_reg(udev, 0x49e0);
+ ret = it913x_wr_reg(udev, DEV_0, GPIOH1_EN, 0x1);
+ ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_ON, 0x1);
+ ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1);
+ msleep(50); /* Delay noticed reset cycle ? */
+ ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x0);
+ msleep(50);
+ reg = it913x_read_reg(udev, GPIOH1_O);
+ if (reg == 0) {
+ ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1);
+ ret |= it913x_return_status(udev);
+ if (ret != 0)
+ ret = it913x_wr_reg(udev, DEV_0,
+ GPIOH1_O, 0x0);
+ }
+ } else
+ props->num_adapters = 1;
+
+ reg = it913x_read_reg(udev, IO_MUX_POWER_CLK);
+
+ ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, CHIP2_I2C_ADDR);
+
+ ret |= it913x_wr_reg(udev, DEV_0, CLK_O_EN, 0x1);
+
+ *cold = 1;
+
+ return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+ int ret = 0;
+ u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+ if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+ return -EAGAIN;
+ deb_info(1, "STM (%02x)", onoff);
+
+ if (!onoff)
+ ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
+
+
+ mutex_unlock(&adap->dev->i2c_mutex);
+
+ return ret;
+}
+
+
+static int it913x_download_firmware(struct usb_device *udev,
+ const struct firmware *fw)
+{
+ int ret = 0, i;
+ u8 packet_size, dlen, tun1;
+ u8 *fw_data;
+
+ packet_size = 0x29;
+
+ tun1 = it913x_read_reg(udev, 0x49e0);
+
+ ret = it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_100);
+
+ info("FRM Starting Firmware Download");
+ /* This uses scatter write firmware headers follow */
+ /* 03 XX 00 XX = chip number? */
+
+ for (i = 0; i < fw->size; i += packet_size) {
+ if (i > 0)
+ packet_size = 0x39;
+ fw_data = (u8 *)(fw->data + i);
+ dlen = ((i + packet_size) > fw->size)
+ ? (fw->size - i) : packet_size;
+ ret |= it913x_io(udev, WRITE_DATA, DEV_0,
+ CMD_SCATTER_WRITE, 0, 0, fw_data, dlen);
+ udelay(1000);
+ }
+
+ ret |= it913x_io(udev, WRITE_CMD, DEV_0,
+ CMD_BOOT, 0, 0, NULL, 0);
+
+ msleep(100);
+
+ if (ret < 0)
+ info("FRM Firmware Download Failed (%04x)" , ret);
+ else
+ info("FRM Firmware Download Completed - Resetting Device");
+
+ ret |= it913x_return_status(udev);
+
+ msleep(30);
+
+ ret |= it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400);
+
+ /* Tuner function */
+ ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0);
+
+ ret |= it913x_wr_reg(udev, DEV_0, PADODPU, 0x0);
+ ret |= it913x_wr_reg(udev, DEV_0, AGC_O_D, 0x0);
+ if (tun1 > 0) {
+ ret |= it913x_wr_reg(udev, DEV_1, PADODPU, 0x0);
+ ret |= it913x_wr_reg(udev, DEV_1, AGC_O_D, 0x0);
+ }
+
+ return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_name(struct dvb_usb_adapter *adap)
+{
+ const char *desc = adap->dev->desc->name;
+ char *fe_name[] = {"_1", "_2", "_3", "_4"};
+ char *name = adap->fe_adap[0].fe->ops.info.name;
+
+ strlcpy(name, desc, 128);
+ strlcat(name, fe_name[adap->id], 128);
+
+ return 0;
+}
+
+static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct usb_device *udev = adap->dev->udev;
+ int ret = 0;
+ u8 adf = it913x_read_reg(udev, IO_MUX_POWER_CLK);
+ u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
+ u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize;
+
+ adap->fe_adap[0].fe = dvb_attach(it913x_fe_attach,
+ &adap->dev->i2c_adap, adap_addr, adf, IT9137);
+
+ if (adap->id == 0 && adap->fe_adap[0].fe) {
+ ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x1);
+ ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x1);
+ ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x0f);
+ ret = it913x_wr_reg(udev, DEV_0, EP0_TX_NAK, 0x1b);
+ ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x2f);
+ ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_LSB,
+ ep_size & 0xff);
+ ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8);
+ ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, 0x80);
+ } else if (adap->id == 1 && adap->fe_adap[0].fe) {
+ ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x6f);
+ ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_LSB,
+ ep_size & 0xff);
+ ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8);
+ ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, 0x80);
+ ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_EN, 0x1);
+ ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_SERIAL, 0x1);
+ ret = it913x_wr_reg(udev, DEV_1, TOP_HOSTB_SER_MODE, 0x1);
+ ret = it913x_wr_reg(udev, DEV_0_DMOD, TSIS_ENABLE, 0x1);
+ ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x0);
+ ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x0);
+ ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0);
+ ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF_STOP_EN, 0x1);
+ ret = it913x_wr_reg(udev, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0);
+ ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_STOP_EN, 0x0);
+ } else
+ return -ENODEV;
+
+ ret = it913x_name(adap);
+
+ return ret;
+}
+
+/* DVB USB Driver */
+static struct dvb_usb_device_properties it913x_properties;
+
+static int it913x_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ cmd_counter = 0;
+ if (0 == dvb_usb_device_init(intf, &it913x_properties,
+ THIS_MODULE, NULL, adapter_nr)) {
+ info("DEV registering device driver");
+ return 0;
+ }
+
+ info("DEV it913x Error");
+ return -ENODEV;
+
+}
+
+static struct usb_device_id it913x_table[] = {
+ { USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09) },
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, it913x_table);
+
+static struct dvb_usb_device_properties it913x_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .download_firmware = it913x_download_firmware,
+ .firmware = "dvb-usb-it9137-01.fw",
+ .no_reconnect = 1,
+ .size_of_priv = sizeof(struct it913x_state),
+ .num_adapters = 2,
+ .adapter = {
+ {
+ .num_frontends = 1,
+ .fe = {{
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER|
+ DVB_USB_ADAP_NEED_PID_FILTERING|
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+ .streaming_ctrl = it913x_streaming_ctrl,
+ .pid_filter_count = 31,
+ .pid_filter = it913x_pid_filter,
+ .pid_filter_ctrl = it913x_pid_filter_ctrl,
+ .frontend_attach = it913x_frontend_attach,
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 10,
+ .endpoint = 0x04,
+ .u = {/* Keep Low if PID filter on */
+ .bulk = {
+ .buffersize = 3584,
+
+ }
+ }
+ }
+ }},
+ },
+ {
+ .num_frontends = 1,
+ .fe = {{
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER|
+ DVB_USB_ADAP_NEED_PID_FILTERING|
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+ .streaming_ctrl = it913x_streaming_ctrl,
+ .pid_filter_count = 31,
+ .pid_filter = it913x_pid_filter,
+ .pid_filter_ctrl = it913x_pid_filter_ctrl,
+ .frontend_attach = it913x_frontend_attach,
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 5,
+ .endpoint = 0x05,
+ .u = {
+ .bulk = {
+ .buffersize = 3584,
+
+ }
+ }
+ }
+ }},
+ }
+ },
+ .identify_state = it913x_identify_state,
+ .rc.core = {
+ .protocol = RC_TYPE_NEC,
+ .module_name = "it913x",
+ .rc_query = it913x_rc_query,
+ .rc_interval = IT913X_POLL,
+ .allowed_protos = RC_TYPE_NEC,
+ .rc_codes = RC_MAP_KWORLD_315U,
+ },
+ .i2c_algo = &it913x_i2c_algo,
+ .num_device_descs = 1,
+ .devices = {
+ { "Kworld UB499-2T T09(IT9137)",
+ { &it913x_table[0], NULL },
+ },
+
+ }
+};
+
+static struct usb_driver it913x_driver = {
+ .name = "it913x",
+ .probe = it913x_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = it913x_table,
+};
+
+/* module stuff */
+static int __init it913x_module_init(void)
+{
+ int result = usb_register(&it913x_driver);
+ if (result) {
+ err("usb_register failed. Error number %d", result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit it913x_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&it913x_driver);
+}
+
+module_init(it913x_module_init);
+module_exit(it913x_module_exit);
+
+MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
+MODULE_DESCRIPTION("it913x USB 2 Driver");
+MODULE_VERSION("1.06");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c
index 37b146961ae2..b9228240f5ce 100644
--- a/drivers/media/dvb/dvb-usb/lmedm04.c
+++ b/drivers/media/dvb/dvb-usb/lmedm04.c
@@ -162,7 +162,7 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
int ret = 0;
if (st->usb_buffer == NULL) {
- st->usb_buffer = kmalloc(512, GFP_KERNEL);
+ st->usb_buffer = kmalloc(64, GFP_KERNEL);
if (st->usb_buffer == NULL) {
info("MEM Error no memory");
return -ENOMEM;
@@ -175,8 +175,8 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
if (ret < 0)
return -EAGAIN;
- /* the read/write capped at 512 */
- memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
+ /* the read/write capped at 64 */
+ memcpy(buff, wbuf, (wlen < 64) ? wlen : 64);
ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01));
@@ -186,8 +186,8 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01));
- ret |= lme2510_bulk_read(d->udev, buff, (rlen > 512) ?
- 512 : rlen , 0x01);
+ ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ?
+ rlen : 64 , 0x01);
if (rlen > 0)
memcpy(rbuf, buff, rlen);
@@ -333,7 +333,7 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
if (lme_int->lme_urb == NULL)
return -ENOMEM;
- lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 5000, GFP_ATOMIC,
+ lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 128, GFP_ATOMIC,
&lme_int->lme_urb->transfer_dma);
if (lme_int->buffer == NULL)
@@ -343,10 +343,10 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
adap->dev->udev,
usb_rcvintpipe(adap->dev->udev, 0xa),
lme_int->buffer,
- 4096,
+ 128,
lme2510_int_response,
adap,
- 11);
+ 8);
lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -580,7 +580,7 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
struct lme2510_state *st = d->priv;
- static u8 obuf[64], ibuf[512];
+ static u8 obuf[64], ibuf[64];
int i, read, read_o;
u16 len;
u8 gate = st->i2c_gate;
@@ -621,7 +621,7 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
len = msg[i].len+3;
}
- if (lme2510_msg(d, obuf, len, ibuf, 512) < 0) {
+ if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) {
deb_info(1, "i2c transfer failed.");
return -EAGAIN;
}
@@ -941,7 +941,7 @@ static int lme_name(struct dvb_usb_adapter *adap)
const char *desc = adap->dev->desc->name;
char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395",
" SHARP:BS2F7HZ0194"};
- char *name = adap->fe->ops.info.name;
+ char *name = adap->fe_adap[0].fe->ops.info.name;
strlcpy(name, desc, 128);
strlcat(name, fe_name[st->tuner_config], 128);
@@ -958,10 +958,10 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
st->i2c_talk_onoff = 1;
st->i2c_gate = 4;
- adap->fe = dvb_attach(tda10086_attach, &tda10086_config,
+ adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config,
&adap->dev->i2c_adap);
- if (adap->fe) {
+ if (adap->fe_adap[0].fe) {
info("TUN Found Frontend TDA10086");
st->i2c_tuner_gate_w = 4;
st->i2c_tuner_gate_r = 4;
@@ -975,9 +975,9 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
}
st->i2c_gate = 4;
- adap->fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
+ adap->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
&adap->dev->i2c_adap);
- if (adap->fe) {
+ if (adap->fe_adap[0].fe) {
info("FE Found Stv0299");
st->i2c_tuner_gate_w = 4;
st->i2c_tuner_gate_r = 5;
@@ -991,9 +991,9 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
}
st->i2c_gate = 5;
- adap->fe = dvb_attach(stv0288_attach, &lme_config,
+ adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config,
&adap->dev->i2c_adap);
- if (adap->fe) {
+ if (adap->fe_adap[0].fe) {
info("FE Found Stv0288");
st->i2c_tuner_gate_w = 4;
st->i2c_tuner_gate_r = 5;
@@ -1010,15 +1010,15 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
end: if (ret) {
- if (adap->fe) {
- dvb_frontend_detach(adap->fe);
- adap->fe = NULL;
+ if (adap->fe_adap[0].fe) {
+ dvb_frontend_detach(adap->fe_adap[0].fe);
+ adap->fe_adap[0].fe = NULL;
}
adap->dev->props.rc.core.rc_codes = NULL;
return -ENODEV;
}
- adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
+ adap->fe_adap[0].fe->ops.set_voltage = dm04_lme2510_set_voltage;
ret = lme_name(adap);
return ret;
}
@@ -1031,17 +1031,17 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
switch (st->tuner_config) {
case TUNER_LG:
- if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
+ if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0xc0,
&adap->dev->i2c_adap, 1))
ret = st->tuner_config;
break;
case TUNER_S7395:
- if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
+ if (dvb_attach(ix2505v_attach , adap->fe_adap[0].fe, &lme_tuner,
&adap->dev->i2c_adap))
ret = st->tuner_config;
break;
case TUNER_S0194:
- if (dvb_attach(dvb_pll_attach , adap->fe, 0xc0,
+ if (dvb_attach(dvb_pll_attach , adap->fe_adap[0].fe, 0xc0,
&adap->dev->i2c_adap, DVB_PLL_OPERA1))
ret = st->tuner_config;
break;
@@ -1145,6 +1145,8 @@ static struct dvb_usb_device_properties lme2510_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER|
DVB_USB_ADAP_NEED_PID_FILTERING|
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1166,6 +1168,7 @@ static struct dvb_usb_device_properties lme2510_properties = {
}
}
}
+ }},
}
},
.rc.core = {
@@ -1193,6 +1196,8 @@ static struct dvb_usb_device_properties lme2510c_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER|
DVB_USB_ADAP_NEED_PID_FILTERING|
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1214,6 +1219,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
}
}
}
+ }},
}
},
.rc.core = {
@@ -1241,7 +1247,7 @@ static void *lme2510_exit_int(struct dvb_usb_device *d)
void *buffer = NULL;
if (adap != NULL) {
- lme2510_kill_urb(&adap->stream);
+ lme2510_kill_urb(&adap->fe_adap[0].stream);
adap->feedcount = 0;
}
@@ -1255,7 +1261,7 @@ static void *lme2510_exit_int(struct dvb_usb_device *d)
if (st->lme_urb != NULL) {
usb_kill_urb(st->lme_urb);
- usb_free_coherent(d->udev, 5000, st->buffer,
+ usb_free_coherent(d->udev, 128, st->buffer,
st->lme_urb->transfer_dma);
info("Interrupt Service Stopped");
}
@@ -1306,5 +1312,5 @@ module_exit(lme2510_module_exit);
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.88");
+MODULE_VERSION("1.90");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
index 9456792f219b..a1e1287c949e 100644
--- a/drivers/media/dvb/dvb-usb/m920x.c
+++ b/drivers/media/dvb/dvb-usb/m920x.c
@@ -86,12 +86,12 @@ static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
}
for (i = 0; i < d->props.num_adapters; i++)
- flags |= d->adapter[i].props.caps;
+ flags |= d->adapter[i].props.fe[0].caps;
/* Some devices(Dposh) might crash if we attempt touch at all. */
if (flags & DVB_USB_ADAP_HAS_PID_FILTER) {
for (i = 0; i < d->props.num_adapters; i++) {
- epi = d->adapter[i].props.stream.endpoint - 0x81;
+ epi = d->adapter[i].props.fe[0].stream.endpoint - 0x81;
if (epi < 0 || epi >= M9206_MAX_ADAPTERS) {
printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n");
@@ -292,7 +292,7 @@ static int m920x_update_filters(struct dvb_usb_adapter *adap)
struct m920x_state *m = adap->dev->priv;
int enabled = m->filtering_enabled[adap->id];
int i, ret = 0, filter = 0;
- int ep = adap->props.stream.endpoint;
+ int ep = adap->props.fe[0].stream.endpoint;
for (i = 0; i < M9206_MAX_FILTERS; i++)
if (m->filters[adap->id][i] == 8192)
@@ -501,9 +501,10 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if ((adap->fe = dvb_attach(mt352_attach,
- &m920x_mt352_config,
- &adap->dev->i2c_adap)) == NULL)
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach,
+ &m920x_mt352_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) == NULL)
return -EIO;
return 0;
@@ -513,9 +514,10 @@ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if ((adap->fe = dvb_attach(tda10046_attach,
- &m920x_tda10046_08_config,
- &adap->dev->i2c_adap)) == NULL)
+ adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
+ &m920x_tda10046_08_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) == NULL)
return -EIO;
return 0;
@@ -525,9 +527,10 @@ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if ((adap->fe = dvb_attach(tda10046_attach,
- &m920x_tda10046_0b_config,
- &adap->dev->i2c_adap)) == NULL)
+ adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
+ &m920x_tda10046_0b_config,
+ &adap->dev->i2c_adap);
+ if ((adap->fe_adap[0].fe) == NULL)
return -EIO;
return 0;
@@ -537,7 +540,7 @@ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
+ if (dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
return -ENODEV;
return 0;
@@ -547,7 +550,7 @@ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
+ if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
return -ENODEV;
return 0;
@@ -557,7 +560,7 @@ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
{
deb("%s\n",__func__);
- if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
+ if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
return -ENODEV;
return 0;
@@ -565,7 +568,7 @@ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(simple_tuner_attach, adap->fe,
+ dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, 0x61,
TUNER_PHILIPS_FMD1216ME_MK3);
return 0;
@@ -807,6 +810,9 @@ static struct dvb_usb_device_properties megasky_properties = {
.identify_state = m920x_identify_state,
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
+
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -827,6 +833,7 @@ static struct dvb_usb_device_properties megasky_properties = {
}
}
},
+ }},
}},
.i2c_algo = &m920x_i2c_algo,
@@ -851,6 +858,9 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
.identify_state = m920x_identify_state,
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
+
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -871,6 +881,7 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
}
}
},
+ }},
}},
.i2c_algo = &m920x_i2c_algo,
@@ -910,6 +921,9 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
.identify_state = m920x_identify_state,
.num_adapters = 2,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
+
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -929,7 +943,11 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
.buffersize = 512,
}
}
+ }},
}},{
+ .num_frontends = 1,
+ .fe = {{
+
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -949,6 +967,7 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
.buffersize = 512,
}
}
+ }},
},
}},
.i2c_algo = &m920x_i2c_algo,
@@ -974,6 +993,8 @@ static struct dvb_usb_device_properties dposh_properties = {
.identify_state = m920x_identify_state,
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
/* Hardware pid filters don't work with this device/firmware */
.frontend_attach = m920x_mt352_frontend_attach,
@@ -989,6 +1010,7 @@ static struct dvb_usb_device_properties dposh_properties = {
}
}
},
+ }},
}},
.i2c_algo = &m920x_i2c_algo,
@@ -1019,6 +1041,9 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
.identify_state = m920x_identify_state,
.num_adapters = 1,
.adapter = {{
+ .num_frontends = 1,
+ .fe = {{
+
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1041,6 +1066,7 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
}
}
},
+ }},
} },
.i2c_algo = &m920x_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c b/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c
new file mode 100644
index 000000000000..e4121cb8f5ef
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c
@@ -0,0 +1,763 @@
+/*
+ * mxl111sf-gpio.c - driver for the MaxLinear MXL111SF
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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 "mxl111sf-gpio.h"
+#include "mxl111sf-i2c.h"
+#include "mxl111sf.h"
+
+/* ------------------------------------------------------------------------- */
+
+#define MXL_GPIO_MUX_REG_0 0x84
+#define MXL_GPIO_MUX_REG_1 0x89
+#define MXL_GPIO_MUX_REG_2 0x82
+
+#define MXL_GPIO_DIR_INPUT 0
+#define MXL_GPIO_DIR_OUTPUT 1
+
+
+static int mxl111sf_set_gpo_state(struct mxl111sf_state *state, u8 pin, u8 val)
+{
+ int ret;
+ u8 tmp;
+
+ mxl_debug_adv("(%d, %d)", pin, val);
+
+ if ((pin > 0) && (pin < 8)) {
+ ret = mxl111sf_read_reg(state, 0x19, &tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ tmp &= ~(1 << (pin - 1));
+ tmp |= (val << (pin - 1));
+ ret = mxl111sf_write_reg(state, 0x19, tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ } else if (pin <= 10) {
+ if (pin == 0)
+ pin += 7;
+ ret = mxl111sf_read_reg(state, 0x30, &tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ tmp &= ~(1 << (pin - 3));
+ tmp |= (val << (pin - 3));
+ ret = mxl111sf_write_reg(state, 0x30, tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ } else
+ ret = -EINVAL;
+fail:
+ return ret;
+}
+
+static int mxl111sf_get_gpi_state(struct mxl111sf_state *state, u8 pin, u8 *val)
+{
+ int ret;
+ u8 tmp;
+
+ mxl_debug("(0x%02x)", pin);
+
+ *val = 0;
+
+ switch (pin) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ ret = mxl111sf_read_reg(state, 0x23, &tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ *val = (tmp >> (pin + 4)) & 0x01;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ ret = mxl111sf_read_reg(state, 0x2f, &tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ *val = (tmp >> pin) & 0x01;
+ break;
+ case 8:
+ case 9:
+ case 10:
+ ret = mxl111sf_read_reg(state, 0x22, &tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ *val = (tmp >> (pin - 3)) & 0x01;
+ break;
+ default:
+ return -EINVAL; /* invalid pin */
+ }
+fail:
+ return ret;
+}
+
+struct mxl_gpio_cfg {
+ u8 pin;
+ u8 dir;
+ u8 val;
+};
+
+static int mxl111sf_config_gpio_pins(struct mxl111sf_state *state,
+ struct mxl_gpio_cfg *gpio_cfg)
+{
+ int ret;
+ u8 tmp;
+
+ mxl_debug_adv("(%d, %d)", gpio_cfg->pin, gpio_cfg->dir);
+
+ switch (gpio_cfg->pin) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_0, &tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ tmp &= ~(1 << (gpio_cfg->pin + 4));
+ tmp |= (gpio_cfg->dir << (gpio_cfg->pin + 4));
+ ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_0, tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_1, &tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ tmp &= ~(1 << gpio_cfg->pin);
+ tmp |= (gpio_cfg->dir << gpio_cfg->pin);
+ ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_1, tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ break;
+ case 8:
+ case 9:
+ case 10:
+ ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_2, &tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ tmp &= ~(1 << (gpio_cfg->pin - 3));
+ tmp |= (gpio_cfg->dir << (gpio_cfg->pin - 3));
+ ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_2, tmp);
+ if (mxl_fail(ret))
+ goto fail;
+ break;
+ default:
+ return -EINVAL; /* invalid pin */
+ }
+
+ ret = (MXL_GPIO_DIR_OUTPUT == gpio_cfg->dir) ?
+ mxl111sf_set_gpo_state(state,
+ gpio_cfg->pin, gpio_cfg->val) :
+ mxl111sf_get_gpi_state(state,
+ gpio_cfg->pin, &gpio_cfg->val);
+ mxl_fail(ret);
+fail:
+ return ret;
+}
+
+static int mxl111sf_hw_do_set_gpio(struct mxl111sf_state *state,
+ int gpio, int direction, int val)
+{
+ struct mxl_gpio_cfg gpio_config = {
+ .pin = gpio,
+ .dir = direction,
+ .val = val,
+ };
+
+ mxl_debug("(%d, %d, %d)", gpio, direction, val);
+
+ return mxl111sf_config_gpio_pins(state, &gpio_config);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#define PIN_MUX_MPEG_MODE_MASK 0x40 /* 0x17 <6> */
+#define PIN_MUX_MPEG_PAR_EN_MASK 0x01 /* 0x18 <0> */
+#define PIN_MUX_MPEG_SER_EN_MASK 0x02 /* 0x18 <1> */
+#define PIN_MUX_MPG_IN_MUX_MASK 0x80 /* 0x3D <7> */
+#define PIN_MUX_BT656_ENABLE_MASK 0x04 /* 0x12 <2> */
+#define PIN_MUX_I2S_ENABLE_MASK 0x40 /* 0x15 <6> */
+#define PIN_MUX_SPI_MODE_MASK 0x10 /* 0x3D <4> */
+#define PIN_MUX_MCLK_EN_CTRL_MASK 0x10 /* 0x82 <4> */
+#define PIN_MUX_MPSYN_EN_CTRL_MASK 0x20 /* 0x82 <5> */
+#define PIN_MUX_MDVAL_EN_CTRL_MASK 0x40 /* 0x82 <6> */
+#define PIN_MUX_MPERR_EN_CTRL_MASK 0x80 /* 0x82 <7> */
+#define PIN_MUX_MDAT_EN_0_MASK 0x10 /* 0x84 <4> */
+#define PIN_MUX_MDAT_EN_1_MASK 0x20 /* 0x84 <5> */
+#define PIN_MUX_MDAT_EN_2_MASK 0x40 /* 0x84 <6> */
+#define PIN_MUX_MDAT_EN_3_MASK 0x80 /* 0x84 <7> */
+#define PIN_MUX_MDAT_EN_4_MASK 0x10 /* 0x89 <4> */
+#define PIN_MUX_MDAT_EN_5_MASK 0x20 /* 0x89 <5> */
+#define PIN_MUX_MDAT_EN_6_MASK 0x40 /* 0x89 <6> */
+#define PIN_MUX_MDAT_EN_7_MASK 0x80 /* 0x89 <7> */
+
+int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
+ enum mxl111sf_mux_config pin_mux_config)
+{
+ u8 r12, r15, r17, r18, r3D, r82, r84, r89;
+ int ret;
+
+ mxl_debug("(%d)", pin_mux_config);
+
+ ret = mxl111sf_read_reg(state, 0x17, &r17);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_read_reg(state, 0x18, &r18);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_read_reg(state, 0x12, &r12);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_read_reg(state, 0x15, &r15);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_read_reg(state, 0x82, &r82);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_read_reg(state, 0x84, &r84);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_read_reg(state, 0x89, &r89);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_read_reg(state, 0x3D, &r3D);
+ if (mxl_fail(ret))
+ goto fail;
+
+ switch (pin_mux_config) {
+ case PIN_MUX_TS_OUT_PARALLEL:
+ /* mpeg_mode = 1 */
+ r17 |= PIN_MUX_MPEG_MODE_MASK;
+ /* mpeg_par_en = 1 */
+ r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
+ /* mpeg_ser_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+ /* mpg_in_mux = 0 */
+ r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+ /* bt656_enable = 0 */
+ r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+ /* i2s_enable = 0 */
+ r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+ /* spi_mode = 0 */
+ r3D &= ~PIN_MUX_SPI_MODE_MASK;
+ /* mclk_en_ctrl = 1 */
+ r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
+ /* mperr_en_ctrl = 1 */
+ r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
+ /* mdval_en_ctrl = 1 */
+ r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
+ /* mpsyn_en_ctrl = 1 */
+ r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
+ /* mdat_en_ctrl[3:0] = 0xF */
+ r84 |= 0xF0;
+ /* mdat_en_ctrl[7:4] = 0xF */
+ r89 |= 0xF0;
+ break;
+ case PIN_MUX_TS_OUT_SERIAL:
+ /* mpeg_mode = 1 */
+ r17 |= PIN_MUX_MPEG_MODE_MASK;
+ /* mpeg_par_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+ /* mpeg_ser_en = 1 */
+ r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+ /* mpg_in_mux = 0 */
+ r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+ /* bt656_enable = 0 */
+ r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+ /* i2s_enable = 0 */
+ r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+ /* spi_mode = 0 */
+ r3D &= ~PIN_MUX_SPI_MODE_MASK;
+ /* mclk_en_ctrl = 1 */
+ r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
+ /* mperr_en_ctrl = 1 */
+ r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
+ /* mdval_en_ctrl = 1 */
+ r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
+ /* mpsyn_en_ctrl = 1 */
+ r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
+ /* mdat_en_ctrl[3:0] = 0xF */
+ r84 |= 0xF0;
+ /* mdat_en_ctrl[7:4] = 0xF */
+ r89 |= 0xF0;
+ break;
+ case PIN_MUX_GPIO_MODE:
+ /* mpeg_mode = 0 */
+ r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+ /* mpeg_par_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+ /* mpeg_ser_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+ /* mpg_in_mux = 0 */
+ r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+ /* bt656_enable = 0 */
+ r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+ /* i2s_enable = 0 */
+ r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+ /* spi_mode = 0 */
+ r3D &= ~PIN_MUX_SPI_MODE_MASK;
+ /* mclk_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+ /* mperr_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+ /* mdval_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+ /* mpsyn_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+ /* mdat_en_ctrl[3:0] = 0x0 */
+ r84 &= 0x0F;
+ /* mdat_en_ctrl[7:4] = 0x0 */
+ r89 &= 0x0F;
+ break;
+ case PIN_MUX_TS_SERIAL_IN_MODE_0:
+ /* mpeg_mode = 0 */
+ r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+ /* mpeg_par_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+ /* mpeg_ser_en = 1 */
+ r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+ /* mpg_in_mux = 0 */
+ r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+ /* bt656_enable = 0 */
+ r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+ /* i2s_enable = 0 */
+ r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+ /* spi_mode = 0 */
+ r3D &= ~PIN_MUX_SPI_MODE_MASK;
+ /* mclk_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+ /* mperr_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+ /* mdval_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+ /* mpsyn_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+ /* mdat_en_ctrl[3:0] = 0x0 */
+ r84 &= 0x0F;
+ /* mdat_en_ctrl[7:4] = 0x0 */
+ r89 &= 0x0F;
+ break;
+ case PIN_MUX_TS_SERIAL_IN_MODE_1:
+ /* mpeg_mode = 0 */
+ r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+ /* mpeg_par_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+ /* mpeg_ser_en = 1 */
+ r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+ /* mpg_in_mux = 1 */
+ r3D |= PIN_MUX_MPG_IN_MUX_MASK;
+ /* bt656_enable = 0 */
+ r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+ /* i2s_enable = 0 */
+ r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+ /* spi_mode = 0 */
+ r3D &= ~PIN_MUX_SPI_MODE_MASK;
+ /* mclk_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+ /* mperr_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+ /* mdval_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+ /* mpsyn_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+ /* mdat_en_ctrl[3:0] = 0x0 */
+ r84 &= 0x0F;
+ /* mdat_en_ctrl[7:4] = 0x0 */
+ r89 &= 0x0F;
+ break;
+ case PIN_MUX_TS_SPI_IN_MODE_1:
+ /* mpeg_mode = 0 */
+ r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+ /* mpeg_par_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+ /* mpeg_ser_en = 1 */
+ r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+ /* mpg_in_mux = 1 */
+ r3D |= PIN_MUX_MPG_IN_MUX_MASK;
+ /* bt656_enable = 0 */
+ r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+ /* i2s_enable = 1 */
+ r15 |= PIN_MUX_I2S_ENABLE_MASK;
+ /* spi_mode = 1 */
+ r3D |= PIN_MUX_SPI_MODE_MASK;
+ /* mclk_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+ /* mperr_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+ /* mdval_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+ /* mpsyn_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+ /* mdat_en_ctrl[3:0] = 0x0 */
+ r84 &= 0x0F;
+ /* mdat_en_ctrl[7:4] = 0x0 */
+ r89 &= 0x0F;
+ break;
+ case PIN_MUX_TS_SPI_IN_MODE_0:
+ /* mpeg_mode = 0 */
+ r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+ /* mpeg_par_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+ /* mpeg_ser_en = 1 */
+ r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+ /* mpg_in_mux = 0 */
+ r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+ /* bt656_enable = 0 */
+ r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+ /* i2s_enable = 1 */
+ r15 |= PIN_MUX_I2S_ENABLE_MASK;
+ /* spi_mode = 1 */
+ r3D |= PIN_MUX_SPI_MODE_MASK;
+ /* mclk_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+ /* mperr_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+ /* mdval_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+ /* mpsyn_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+ /* mdat_en_ctrl[3:0] = 0x0 */
+ r84 &= 0x0F;
+ /* mdat_en_ctrl[7:4] = 0x0 */
+ r89 &= 0x0F;
+ break;
+ case PIN_MUX_TS_PARALLEL_IN:
+ /* mpeg_mode = 0 */
+ r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+ /* mpeg_par_en = 1 */
+ r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
+ /* mpeg_ser_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+ /* mpg_in_mux = 0 */
+ r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+ /* bt656_enable = 0 */
+ r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+ /* i2s_enable = 0 */
+ r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+ /* spi_mode = 0 */
+ r3D &= ~PIN_MUX_SPI_MODE_MASK;
+ /* mclk_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+ /* mperr_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+ /* mdval_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+ /* mpsyn_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+ /* mdat_en_ctrl[3:0] = 0x0 */
+ r84 &= 0x0F;
+ /* mdat_en_ctrl[7:4] = 0x0 */
+ r89 &= 0x0F;
+ break;
+ case PIN_MUX_BT656_I2S_MODE:
+ /* mpeg_mode = 0 */
+ r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+ /* mpeg_par_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+ /* mpeg_ser_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+ /* mpg_in_mux = 0 */
+ r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+ /* bt656_enable = 1 */
+ r12 |= PIN_MUX_BT656_ENABLE_MASK;
+ /* i2s_enable = 1 */
+ r15 |= PIN_MUX_I2S_ENABLE_MASK;
+ /* spi_mode = 0 */
+ r3D &= ~PIN_MUX_SPI_MODE_MASK;
+ /* mclk_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+ /* mperr_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+ /* mdval_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+ /* mpsyn_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+ /* mdat_en_ctrl[3:0] = 0x0 */
+ r84 &= 0x0F;
+ /* mdat_en_ctrl[7:4] = 0x0 */
+ r89 &= 0x0F;
+ break;
+ case PIN_MUX_DEFAULT:
+ default:
+ /* mpeg_mode = 1 */
+ r17 |= PIN_MUX_MPEG_MODE_MASK;
+ /* mpeg_par_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+ /* mpeg_ser_en = 0 */
+ r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+ /* mpg_in_mux = 0 */
+ r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+ /* bt656_enable = 0 */
+ r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+ /* i2s_enable = 0 */
+ r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+ /* spi_mode = 0 */
+ r3D &= ~PIN_MUX_SPI_MODE_MASK;
+ /* mclk_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+ /* mperr_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+ /* mdval_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+ /* mpsyn_en_ctrl = 0 */
+ r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+ /* mdat_en_ctrl[3:0] = 0x0 */
+ r84 &= 0x0F;
+ /* mdat_en_ctrl[7:4] = 0x0 */
+ r89 &= 0x0F;
+ break;
+ }
+
+ ret = mxl111sf_write_reg(state, 0x17, r17);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_write_reg(state, 0x18, r18);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_write_reg(state, 0x12, r12);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_write_reg(state, 0x15, r15);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_write_reg(state, 0x82, r82);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_write_reg(state, 0x84, r84);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_write_reg(state, 0x89, r89);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_write_reg(state, 0x3D, r3D);
+ if (mxl_fail(ret))
+ goto fail;
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl111sf_hw_set_gpio(struct mxl111sf_state *state, int gpio, int val)
+{
+ return mxl111sf_hw_do_set_gpio(state, gpio, MXL_GPIO_DIR_OUTPUT, val);
+}
+
+static int mxl111sf_hw_gpio_initialize(struct mxl111sf_state *state)
+{
+ u8 gpioval = 0x07; /* write protect enabled, signal LEDs off */
+ int i, ret;
+
+ mxl_debug("()");
+
+ for (i = 3; i < 8; i++) {
+ ret = mxl111sf_hw_set_gpio(state, i, (gpioval >> i) & 0x01);
+ if (mxl_fail(ret))
+ break;
+ }
+
+ return ret;
+}
+
+#define PCA9534_I2C_ADDR (0x40 >> 1)
+static int pca9534_set_gpio(struct mxl111sf_state *state, int gpio, int val)
+{
+ u8 w[2] = { 1, 0 };
+ u8 r = 0;
+ struct i2c_msg msg[] = {
+ { .addr = PCA9534_I2C_ADDR,
+ .flags = 0, .buf = w, .len = 1 },
+ { .addr = PCA9534_I2C_ADDR,
+ .flags = I2C_M_RD, .buf = &r, .len = 1 },
+ };
+
+ mxl_debug("(%d, %d)", gpio, val);
+
+ /* read current GPIO levels from flip-flop */
+ i2c_transfer(&state->d->i2c_adap, msg, 2);
+
+ /* prepare write buffer with current GPIO levels */
+ msg[0].len = 2;
+#if 0
+ w[0] = 1;
+#endif
+ w[1] = r;
+
+ /* clear the desired GPIO */
+ w[1] &= ~(1 << gpio);
+
+ /* set the desired GPIO value */
+ w[1] |= ((val ? 1 : 0) << gpio);
+
+ /* write new GPIO levels to flip-flop */
+ i2c_transfer(&state->d->i2c_adap, &msg[0], 1);
+
+ return 0;
+}
+
+static int pca9534_init_port_expander(struct mxl111sf_state *state)
+{
+ u8 w[2] = { 1, 0x07 }; /* write protect enabled, signal LEDs off */
+
+ struct i2c_msg msg = {
+ .addr = PCA9534_I2C_ADDR,
+ .flags = 0, .buf = w, .len = 2
+ };
+
+ mxl_debug("()");
+
+ i2c_transfer(&state->d->i2c_adap, &msg, 1);
+
+ /* configure all pins as outputs */
+ w[0] = 3;
+ w[1] = 0;
+
+ i2c_transfer(&state->d->i2c_adap, &msg, 1);
+
+ return 0;
+}
+
+int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val)
+{
+ mxl_debug("(%d, %d)", gpio, val);
+
+ switch (state->gpio_port_expander) {
+ default:
+ mxl_printk(KERN_ERR,
+ "gpio_port_expander undefined, assuming PCA9534");
+ /* fall-thru */
+ case mxl111sf_PCA9534:
+ return pca9534_set_gpio(state, gpio, val);
+ case mxl111sf_gpio_hw:
+ return mxl111sf_hw_set_gpio(state, gpio, val);
+ }
+}
+
+static int mxl111sf_probe_port_expander(struct mxl111sf_state *state)
+{
+ int ret;
+ u8 w = 1;
+ u8 r = 0;
+ struct i2c_msg msg[] = {
+ { .flags = 0, .buf = &w, .len = 1 },
+ { .flags = I2C_M_RD, .buf = &r, .len = 1 },
+ };
+
+ mxl_debug("()");
+
+ msg[0].addr = 0x70 >> 1;
+ msg[1].addr = 0x70 >> 1;
+
+ /* read current GPIO levels from flip-flop */
+ ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
+ if (ret == 2) {
+ state->port_expander_addr = msg[0].addr;
+ state->gpio_port_expander = mxl111sf_PCA9534;
+ mxl_debug("found port expander at 0x%02x",
+ state->port_expander_addr);
+ return 0;
+ }
+
+ msg[0].addr = 0x40 >> 1;
+ msg[1].addr = 0x40 >> 1;
+
+ ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
+ if (ret == 2) {
+ state->port_expander_addr = msg[0].addr;
+ state->gpio_port_expander = mxl111sf_PCA9534;
+ mxl_debug("found port expander at 0x%02x",
+ state->port_expander_addr);
+ return 0;
+ }
+ state->port_expander_addr = 0xff;
+ state->gpio_port_expander = mxl111sf_gpio_hw;
+ mxl_debug("using hardware gpio");
+ return 0;
+}
+
+int mxl111sf_init_port_expander(struct mxl111sf_state *state)
+{
+ mxl_debug("()");
+
+ if (0x00 == state->port_expander_addr)
+ mxl111sf_probe_port_expander(state);
+
+ switch (state->gpio_port_expander) {
+ default:
+ mxl_printk(KERN_ERR,
+ "gpio_port_expander undefined, assuming PCA9534");
+ /* fall-thru */
+ case mxl111sf_PCA9534:
+ return pca9534_init_port_expander(state);
+ case mxl111sf_gpio_hw:
+ return mxl111sf_hw_gpio_initialize(state);
+ }
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode)
+{
+/* GPO:
+ * 3 - ATSC/MH# | 1 = ATSC transport, 0 = MH transport | default 0
+ * 4 - ATSC_RST## | 1 = ATSC enable, 0 = ATSC Reset | default 0
+ * 5 - ATSC_EN | 1 = ATSC power enable, 0 = ATSC power off | default 0
+ * 6 - MH_RESET# | 1 = MH enable, 0 = MH Reset | default 0
+ * 7 - MH_EN | 1 = MH power enable, 0 = MH power off | default 0
+ */
+ mxl_debug("(%d)", mode);
+
+ switch (mode) {
+ case MXL111SF_GPIO_MOD_MH:
+ mxl111sf_set_gpio(state, 4, 0);
+ mxl111sf_set_gpio(state, 5, 0);
+ msleep(50);
+ mxl111sf_set_gpio(state, 7, 1);
+ msleep(50);
+ mxl111sf_set_gpio(state, 6, 1);
+ msleep(50);
+
+ mxl111sf_set_gpio(state, 3, 0);
+ break;
+ case MXL111SF_GPIO_MOD_ATSC:
+ mxl111sf_set_gpio(state, 6, 0);
+ mxl111sf_set_gpio(state, 7, 0);
+ msleep(50);
+ mxl111sf_set_gpio(state, 5, 1);
+ msleep(50);
+ mxl111sf_set_gpio(state, 4, 1);
+ msleep(50);
+ mxl111sf_set_gpio(state, 3, 1);
+ break;
+ default: /* DVBT / STANDBY */
+ mxl111sf_init_port_expander(state);
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h b/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h
new file mode 100644
index 000000000000..0220f54299a5
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h
@@ -0,0 +1,56 @@
+/*
+ * mxl111sf-gpio.h - driver for the MaxLinear MXL111SF
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ */
+
+#ifndef _DVB_USB_MXL111SF_GPIO_H_
+#define _DVB_USB_MXL111SF_GPIO_H_
+
+#include "mxl111sf.h"
+
+int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val);
+int mxl111sf_init_port_expander(struct mxl111sf_state *state);
+
+#define MXL111SF_GPIO_MOD_DVBT 0
+#define MXL111SF_GPIO_MOD_MH 1
+#define MXL111SF_GPIO_MOD_ATSC 2
+int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode);
+
+enum mxl111sf_mux_config {
+ PIN_MUX_DEFAULT = 0,
+ PIN_MUX_TS_OUT_PARALLEL,
+ PIN_MUX_TS_OUT_SERIAL,
+ PIN_MUX_GPIO_MODE,
+ PIN_MUX_TS_SERIAL_IN_MODE_0,
+ PIN_MUX_TS_SERIAL_IN_MODE_1,
+ PIN_MUX_TS_SPI_IN_MODE_0,
+ PIN_MUX_TS_SPI_IN_MODE_1,
+ PIN_MUX_TS_PARALLEL_IN,
+ PIN_MUX_BT656_I2S_MODE,
+};
+
+int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
+ enum mxl111sf_mux_config pin_mux_config);
+
+#endif /* _DVB_USB_MXL111SF_GPIO_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c b/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c
new file mode 100644
index 000000000000..2e8c288258a9
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c
@@ -0,0 +1,851 @@
+/*
+ * mxl111sf-i2c.c - driver for the MaxLinear MXL111SF
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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 "mxl111sf-i2c.h"
+#include "mxl111sf.h"
+
+/* SW-I2C ----------------------------------------------------------------- */
+
+#define SW_I2C_ADDR 0x1a
+#define SW_I2C_EN 0x02
+#define SW_SCL_OUT 0x04
+#define SW_SDA_OUT 0x08
+#define SW_SDA_IN 0x04
+
+#define SW_I2C_BUSY_ADDR 0x2f
+#define SW_I2C_BUSY 0x02
+
+static int mxl111sf_i2c_bitbang_sendbyte(struct mxl111sf_state *state,
+ u8 byte)
+{
+ int i, ret;
+ u8 data = 0;
+
+ mxl_i2c("(0x%02x)", byte);
+
+ ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
+ if (mxl_fail(ret))
+ goto fail;
+
+ for (i = 0; i < 8; i++) {
+
+ data = (byte & (0x80 >> i)) ? SW_SDA_OUT : 0;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | data);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | data | SW_SCL_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | data);
+ if (mxl_fail(ret))
+ goto fail;
+ }
+
+ /* last bit was 0 so we need to release SDA */
+ if (!(byte & 1)) {
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SDA_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+ }
+
+ /* CLK high for ACK readback */
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
+ if (mxl_fail(ret))
+ goto fail;
+
+ /* drop the CLK after getting ACK, SDA will go high right away */
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SDA_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ if (data & SW_SDA_IN)
+ ret = -EIO;
+fail:
+ return ret;
+}
+
+static int mxl111sf_i2c_bitbang_recvbyte(struct mxl111sf_state *state,
+ u8 *pbyte)
+{
+ int i, ret;
+ u8 byte = 0;
+ u8 data = 0;
+
+ mxl_i2c("()");
+
+ *pbyte = 0;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SDA_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ for (i = 0; i < 8; i++) {
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN |
+ SW_SCL_OUT | SW_SDA_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
+ if (mxl_fail(ret))
+ goto fail;
+
+ if (data & SW_SDA_IN)
+ byte |= (0x80 >> i);
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SDA_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+ }
+ *pbyte = byte;
+fail:
+ return ret;
+}
+
+static int mxl111sf_i2c_start(struct mxl111sf_state *state)
+{
+ int ret;
+
+ mxl_i2c("()");
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SCL_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN); /* start */
+ mxl_fail(ret);
+fail:
+ return ret;
+}
+
+static int mxl111sf_i2c_stop(struct mxl111sf_state *state)
+{
+ int ret;
+
+ mxl_i2c("()");
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN); /* stop */
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SCL_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_SCL_OUT | SW_SDA_OUT);
+ mxl_fail(ret);
+fail:
+ return ret;
+}
+
+static int mxl111sf_i2c_ack(struct mxl111sf_state *state)
+{
+ int ret;
+ u8 b = 0;
+
+ mxl_i2c("()");
+
+ ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &b);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN);
+ if (mxl_fail(ret))
+ goto fail;
+
+ /* pull SDA low */
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SCL_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SDA_OUT);
+ mxl_fail(ret);
+fail:
+ return ret;
+}
+
+static int mxl111sf_i2c_nack(struct mxl111sf_state *state)
+{
+ int ret;
+
+ mxl_i2c("()");
+
+ /* SDA high to signal last byte read from slave */
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+ 0x10 | SW_I2C_EN | SW_SDA_OUT);
+ mxl_fail(ret);
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_i2c_sw_xfer_msg(struct mxl111sf_state *state,
+ struct i2c_msg *msg)
+{
+ int i, ret;
+
+ mxl_i2c("()");
+
+ if (msg->flags & I2C_M_RD) {
+
+ ret = mxl111sf_i2c_start(state);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_i2c_bitbang_sendbyte(state,
+ (msg->addr << 1) | 0x01);
+ if (mxl_fail(ret)) {
+ mxl111sf_i2c_stop(state);
+ goto fail;
+ }
+
+ for (i = 0; i < msg->len; i++) {
+ ret = mxl111sf_i2c_bitbang_recvbyte(state,
+ &msg->buf[i]);
+ if (mxl_fail(ret)) {
+ mxl111sf_i2c_stop(state);
+ goto fail;
+ }
+
+ if (i < msg->len - 1)
+ mxl111sf_i2c_ack(state);
+ }
+
+ mxl111sf_i2c_nack(state);
+
+ ret = mxl111sf_i2c_stop(state);
+ if (mxl_fail(ret))
+ goto fail;
+
+ } else {
+
+ ret = mxl111sf_i2c_start(state);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_i2c_bitbang_sendbyte(state,
+ (msg->addr << 1) & 0xfe);
+ if (mxl_fail(ret)) {
+ mxl111sf_i2c_stop(state);
+ goto fail;
+ }
+
+ for (i = 0; i < msg->len; i++) {
+ ret = mxl111sf_i2c_bitbang_sendbyte(state,
+ msg->buf[i]);
+ if (mxl_fail(ret)) {
+ mxl111sf_i2c_stop(state);
+ goto fail;
+ }
+ }
+
+ /* FIXME: we only want to do this on the last transaction */
+ mxl111sf_i2c_stop(state);
+ }
+fail:
+ return ret;
+}
+
+/* HW-I2C ----------------------------------------------------------------- */
+
+#define USB_WRITE_I2C_CMD 0x99
+#define USB_READ_I2C_CMD 0xdd
+#define USB_END_I2C_CMD 0xfe
+
+#define USB_WRITE_I2C_CMD_LEN 26
+#define USB_READ_I2C_CMD_LEN 24
+
+#define I2C_MUX_REG 0x30
+#define I2C_CONTROL_REG 0x00
+#define I2C_SLAVE_ADDR_REG 0x08
+#define I2C_DATA_REG 0x0c
+#define I2C_INT_STATUS_REG 0x10
+
+static int mxl111sf_i2c_send_data(struct mxl111sf_state *state,
+ u8 index, u8 *wdata)
+{
+ int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
+ &wdata[1], 25, NULL, 0);
+ mxl_fail(ret);
+
+ return ret;
+}
+
+static int mxl111sf_i2c_get_data(struct mxl111sf_state *state,
+ u8 index, u8 *wdata, u8 *rdata)
+{
+ int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
+ &wdata[1], 25, rdata, 24);
+ mxl_fail(ret);
+
+ return ret;
+}
+
+static u8 mxl111sf_i2c_check_status(struct mxl111sf_state *state)
+{
+ u8 status = 0;
+ u8 buf[26];
+
+ mxl_i2c_adv("()");
+
+ buf[0] = USB_READ_I2C_CMD;
+ buf[1] = 0x00;
+
+ buf[2] = I2C_INT_STATUS_REG;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+
+ buf[5] = USB_END_I2C_CMD;
+
+ mxl111sf_i2c_get_data(state, 0, buf, buf);
+
+ if (buf[1] & 0x04)
+ status = 1;
+
+ return status;
+}
+
+static u8 mxl111sf_i2c_check_fifo(struct mxl111sf_state *state)
+{
+ u8 status = 0;
+ u8 buf[26];
+
+ mxl_i2c("()");
+
+ buf[0] = USB_READ_I2C_CMD;
+ buf[1] = 0x00;
+
+ buf[2] = I2C_MUX_REG;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+
+ buf[5] = I2C_INT_STATUS_REG;
+ buf[6] = 0x00;
+ buf[7] = 0x00;
+ buf[8] = USB_END_I2C_CMD;
+
+ mxl111sf_i2c_get_data(state, 0, buf, buf);
+
+ if (0x08 == (buf[1] & 0x08))
+ status = 1;
+
+ if ((buf[5] & 0x02) == 0x02)
+ mxl_i2c("(buf[5] & 0x02) == 0x02"); /* FIXME */
+
+ return status;
+}
+
+static int mxl111sf_i2c_readagain(struct mxl111sf_state *state,
+ u8 count, u8 *rbuf)
+{
+ u8 i2c_w_data[26];
+ u8 i2c_r_data[24];
+ u8 i = 0;
+ u8 fifo_status = 0;
+ int ret;
+ int status = 0;
+
+ mxl_i2c("read %d bytes", count);
+
+ while ((fifo_status == 0) && (i++ < 5))
+ fifo_status = mxl111sf_i2c_check_fifo(state);
+
+ i2c_w_data[0] = 0xDD;
+ i2c_w_data[1] = 0x00;
+
+ for (i = 2; i < 26; i++)
+ i2c_w_data[i] = 0xFE;
+
+ for (i = 0; i < count; i++) {
+ i2c_w_data[2+(i*3)] = 0x0C;
+ i2c_w_data[3+(i*3)] = 0x00;
+ i2c_w_data[4+(i*3)] = 0x00;
+ }
+
+ ret = mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data);
+
+ /* Check for I2C NACK status */
+ if (mxl111sf_i2c_check_status(state) == 1) {
+ mxl_i2c("error!");
+ } else {
+ for (i = 0; i < count; i++) {
+ rbuf[i] = i2c_r_data[(i*3)+1];
+ mxl_i2c("%02x\t %02x",
+ i2c_r_data[(i*3)+1],
+ i2c_r_data[(i*3)+2]);
+ }
+
+ status = 1;
+ }
+
+ return status;
+}
+
+#define HWI2C400 1
+static int mxl111sf_i2c_hw_xfer_msg(struct mxl111sf_state *state,
+ struct i2c_msg *msg)
+{
+ int i, k, ret = 0;
+ u16 index = 0;
+ u8 buf[26];
+ u8 i2c_r_data[24];
+ u16 block_len;
+ u16 left_over_len;
+ u8 rd_status[8];
+ u8 ret_status;
+ u8 readbuff[26];
+
+ mxl_i2c("addr: 0x%02x, read buff len: %d, write buff len: %d",
+ msg->addr, (msg->flags & I2C_M_RD) ? msg->len : 0,
+ (!(msg->flags & I2C_M_RD)) ? msg->len : 0);
+
+ for (index = 0; index < 26; index++)
+ buf[index] = USB_END_I2C_CMD;
+
+ /* command to indicate data payload is destined for I2C interface */
+ buf[0] = USB_WRITE_I2C_CMD;
+ buf[1] = 0x00;
+
+ /* enable I2C interface */
+ buf[2] = I2C_MUX_REG;
+ buf[3] = 0x80;
+ buf[4] = 0x00;
+
+ /* enable I2C interface */
+ buf[5] = I2C_MUX_REG;
+ buf[6] = 0x81;
+ buf[7] = 0x00;
+
+ /* set Timeout register on I2C interface */
+ buf[8] = 0x14;
+ buf[9] = 0xff;
+ buf[10] = 0x00;
+#if 0
+ /* enable Interrupts on I2C interface */
+ buf[8] = 0x24;
+ buf[9] = 0xF7;
+ buf[10] = 0x00;
+#endif
+ buf[11] = 0x24;
+ buf[12] = 0xF7;
+ buf[13] = 0x00;
+
+ ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+ /* write data on I2C bus */
+ if (!(msg->flags & I2C_M_RD) && (msg->len > 0)) {
+ mxl_i2c("%d\t%02x", msg->len, msg->buf[0]);
+
+ /* control register on I2C interface to initialize I2C bus */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0x5E;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+ /* I2C Slave device Address */
+ buf[5] = I2C_SLAVE_ADDR_REG;
+ buf[6] = (msg->addr);
+ buf[7] = 0x00;
+ buf[8] = USB_END_I2C_CMD;
+ ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+ /* check for slave device status */
+ if (mxl111sf_i2c_check_status(state) == 1) {
+ mxl_i2c("NACK writing slave address %02x",
+ msg->addr);
+ /* if NACK, stop I2C bus and exit */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0x4E;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+ ret = -EIO;
+ goto exit;
+ }
+
+ /* I2C interface can do I2C operations in block of 8 bytes of
+ I2C data. calculation to figure out number of blocks of i2c
+ data required to program */
+ block_len = (msg->len / 8);
+ left_over_len = (msg->len % 8);
+ index = 0;
+
+ mxl_i2c("block_len %d, left_over_len %d",
+ block_len, left_over_len);
+
+ for (index = 0; index < block_len; index++) {
+ for (i = 0; i < 8; i++) {
+ /* write data on I2C interface */
+ buf[2+(i*3)] = I2C_DATA_REG;
+ buf[3+(i*3)] = msg->buf[(index*8)+i];
+ buf[4+(i*3)] = 0x00;
+ }
+
+ ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+ /* check for I2C NACK status */
+ if (mxl111sf_i2c_check_status(state) == 1) {
+ mxl_i2c("NACK writing slave address %02x",
+ msg->addr);
+
+ /* if NACK, stop I2C bus and exit */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0x4E;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+ ret = -EIO;
+ goto exit;
+ }
+
+ }
+
+ if (left_over_len) {
+ for (k = 0; k < 26; k++)
+ buf[k] = USB_END_I2C_CMD;
+
+ buf[0] = 0x99;
+ buf[1] = 0x00;
+
+ for (i = 0; i < left_over_len; i++) {
+ buf[2+(i*3)] = I2C_DATA_REG;
+ buf[3+(i*3)] = msg->buf[(index*8)+i];
+ mxl_i2c("index = %d %d data %d",
+ index, i, msg->buf[(index*8)+i]);
+ buf[4+(i*3)] = 0x00;
+ }
+ ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+ /* check for I2C NACK status */
+ if (mxl111sf_i2c_check_status(state) == 1) {
+ mxl_i2c("NACK writing slave address %02x",
+ msg->addr);
+
+ /* if NACK, stop I2C bus and exit */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0x4E;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+ ret = -EIO;
+ goto exit;
+ }
+
+ }
+
+ /* issue I2C STOP after write */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0x4E;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+ }
+
+ /* read data from I2C bus */
+ if ((msg->flags & I2C_M_RD) && (msg->len > 0)) {
+ mxl_i2c("read buf len %d", msg->len);
+
+ /* command to indicate data payload is
+ destined for I2C interface */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0xDF;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+ /* I2C xfer length */
+ buf[5] = 0x14;
+ buf[6] = (msg->len & 0xFF);
+ buf[7] = 0;
+
+ /* I2C slave device Address */
+ buf[8] = I2C_SLAVE_ADDR_REG;
+ buf[9] = msg->addr;
+ buf[10] = 0x00;
+ buf[11] = USB_END_I2C_CMD;
+ ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+ /* check for I2C NACK status */
+ if (mxl111sf_i2c_check_status(state) == 1) {
+ mxl_i2c("NACK reading slave address %02x",
+ msg->addr);
+
+ /* if NACK, stop I2C bus and exit */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0xC7;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+ ret = -EIO;
+ goto exit;
+ }
+
+ /* I2C interface can do I2C operations in block of 8 bytes of
+ I2C data. calculation to figure out number of blocks of
+ i2c data required to program */
+ block_len = ((msg->len) / 8);
+ left_over_len = ((msg->len) % 8);
+ index = 0;
+
+ mxl_i2c("block_len %d, left_over_len %d",
+ block_len, left_over_len);
+
+ /* command to read data from I2C interface */
+ buf[0] = USB_READ_I2C_CMD;
+ buf[1] = 0x00;
+
+ for (index = 0; index < block_len; index++) {
+ /* setup I2C read request packet on I2C interface */
+ for (i = 0; i < 8; i++) {
+ buf[2+(i*3)] = I2C_DATA_REG;
+ buf[3+(i*3)] = 0x00;
+ buf[4+(i*3)] = 0x00;
+ }
+
+ ret = mxl111sf_i2c_get_data(state, 0, buf, i2c_r_data);
+
+ /* check for I2C NACK status */
+ if (mxl111sf_i2c_check_status(state) == 1) {
+ mxl_i2c("NACK reading slave address %02x",
+ msg->addr);
+
+ /* if NACK, stop I2C bus and exit */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0xC7;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+ ret = -EIO;
+ goto exit;
+ }
+
+ /* copy data from i2c data payload to read buffer */
+ for (i = 0; i < 8; i++) {
+ rd_status[i] = i2c_r_data[(i*3)+2];
+
+ if (rd_status[i] == 0x04) {
+ if (i < 7) {
+ mxl_i2c("i2c fifo empty!"
+ " @ %d", i);
+ msg->buf[(index*8)+i] =
+ i2c_r_data[(i*3)+1];
+ /* read again */
+ ret_status =
+ mxl111sf_i2c_readagain(
+ state, 8-(i+1),
+ readbuff);
+ if (ret_status == 1) {
+ for (k = 0;
+ k < 8-(i+1);
+ k++) {
+
+ msg->buf[(index*8)+(k+i+1)] =
+ readbuff[k];
+ mxl_i2c("read data: %02x\t %02x",
+ msg->buf[(index*8)+(k+i)],
+ (index*8)+(k+i));
+ mxl_i2c("read data: %02x\t %02x",
+ msg->buf[(index*8)+(k+i+1)],
+ readbuff[k]);
+
+ }
+ goto stop_copy;
+ } else {
+ mxl_i2c("readagain "
+ "ERROR!");
+ }
+ } else {
+ msg->buf[(index*8)+i] =
+ i2c_r_data[(i*3)+1];
+ }
+ } else {
+ msg->buf[(index*8)+i] =
+ i2c_r_data[(i*3)+1];
+ }
+ }
+stop_copy:
+ ;
+
+ }
+
+ if (left_over_len) {
+ for (k = 0; k < 26; k++)
+ buf[k] = USB_END_I2C_CMD;
+
+ buf[0] = 0xDD;
+ buf[1] = 0x00;
+
+ for (i = 0; i < left_over_len; i++) {
+ buf[2+(i*3)] = I2C_DATA_REG;
+ buf[3+(i*3)] = 0x00;
+ buf[4+(i*3)] = 0x00;
+ }
+ ret = mxl111sf_i2c_get_data(state, 0, buf,
+ i2c_r_data);
+
+ /* check for I2C NACK status */
+ if (mxl111sf_i2c_check_status(state) == 1) {
+ mxl_i2c("NACK reading slave address %02x",
+ msg->addr);
+
+ /* if NACK, stop I2C bus and exit */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0xC7;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+ ret = -EIO;
+ goto exit;
+ }
+
+ for (i = 0; i < left_over_len; i++) {
+ msg->buf[(block_len*8)+i] =
+ i2c_r_data[(i*3)+1];
+ mxl_i2c("read data: %02x\t %02x",
+ i2c_r_data[(i*3)+1],
+ i2c_r_data[(i*3)+2]);
+ }
+ }
+
+ /* indicate I2C interface to issue NACK
+ after next I2C read op */
+ buf[0] = USB_WRITE_I2C_CMD;
+ buf[1] = 0x00;
+
+ /* control register */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0x17;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+ buf[5] = USB_END_I2C_CMD;
+ ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+ /* control register */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0xC7;
+ buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+ }
+exit:
+ /* STOP and disable I2C MUX */
+ buf[0] = USB_WRITE_I2C_CMD;
+ buf[1] = 0x00;
+
+ /* de-initilize I2C BUS */
+ buf[5] = USB_END_I2C_CMD;
+ mxl111sf_i2c_send_data(state, 0, buf);
+
+ /* Control Register */
+ buf[2] = I2C_CONTROL_REG;
+ buf[3] = 0xDF;
+ buf[4] = 0x03;
+
+ /* disable I2C interface */
+ buf[5] = I2C_MUX_REG;
+ buf[6] = 0x00;
+ buf[7] = 0x00;
+
+ /* de-initilize I2C BUS */
+ buf[8] = USB_END_I2C_CMD;
+ mxl111sf_i2c_send_data(state, 0, buf);
+
+ /* disable I2C interface */
+ buf[2] = I2C_MUX_REG;
+ buf[3] = 0x81;
+ buf[4] = 0x00;
+
+ /* disable I2C interface */
+ buf[5] = I2C_MUX_REG;
+ buf[6] = 0x00;
+ buf[7] = 0x00;
+
+ /* disable I2C interface */
+ buf[8] = I2C_MUX_REG;
+ buf[9] = 0x00;
+ buf[10] = 0x00;
+
+ buf[11] = USB_END_I2C_CMD;
+ mxl111sf_i2c_send_data(state, 0, buf);
+
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
+ struct i2c_msg msg[], int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ struct mxl111sf_state *state = d->priv;
+ int hwi2c = (state->chip_rev > MXL111SF_V6);
+ int i, ret;
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ for (i = 0; i < num; i++) {
+ ret = (hwi2c) ?
+ mxl111sf_i2c_hw_xfer_msg(state, &msg[i]) :
+ mxl111sf_i2c_sw_xfer_msg(state, &msg[i]);
+ if (mxl_fail(ret)) {
+ mxl_debug_adv("failed with error %d on i2c "
+ "transaction %d of %d, %sing %d bytes "
+ "to/from 0x%02x", ret, i+1, num,
+ (msg[i].flags & I2C_M_RD) ?
+ "read" : "writ",
+ msg[i].len, msg[i].addr);
+
+ break;
+ }
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+
+ return i == num ? num : -EREMOTEIO;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h b/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h
new file mode 100644
index 000000000000..a57a45ffb9e4
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h
@@ -0,0 +1,35 @@
+/*
+ * mxl111sf-i2c.h - driver for the MaxLinear MXL111SF
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ */
+
+#ifndef _DVB_USB_MXL111SF_I2C_H_
+#define _DVB_USB_MXL111SF_I2C_H_
+
+#include <linux/i2c.h>
+
+int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
+ struct i2c_msg msg[], int num);
+
+#endif /* _DVB_USB_MXL111SF_I2C_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c b/drivers/media/dvb/dvb-usb/mxl111sf-phy.c
new file mode 100644
index 000000000000..91dc1fc2825b
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-phy.c
@@ -0,0 +1,342 @@
+/*
+ * mxl111sf-phy.c - driver for the MaxLinear MXL111SF
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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 "mxl111sf-phy.h"
+#include "mxl111sf-reg.h"
+
+int mxl111sf_init_tuner_demod(struct mxl111sf_state *state)
+{
+ struct mxl111sf_reg_ctrl_info mxl_111_overwrite_default[] = {
+ {0x07, 0xff, 0x0c},
+ {0x58, 0xff, 0x9d},
+ {0x09, 0xff, 0x00},
+ {0x06, 0xff, 0x06},
+ {0xc8, 0xff, 0x40}, /* ED_LE_WIN_OLD = 0 */
+ {0x8d, 0x01, 0x01}, /* NEGATE_Q */
+ {0x32, 0xff, 0xac}, /* DIG_RFREFSELECT = 12 */
+ {0x42, 0xff, 0x43}, /* DIG_REG_AMP = 4 */
+ {0x74, 0xff, 0xc4}, /* SSPUR_FS_PRIO = 4 */
+ {0x71, 0xff, 0xe6}, /* SPUR_ROT_PRIO_VAL = 1 */
+ {0x83, 0xff, 0x64}, /* INF_FILT1_THD_SC = 100 */
+ {0x85, 0xff, 0x64}, /* INF_FILT2_THD_SC = 100 */
+ {0x88, 0xff, 0xf0}, /* INF_THD = 240 */
+ {0x6f, 0xf0, 0xb0}, /* DFE_DLY = 11 */
+ {0x00, 0xff, 0x01}, /* Change to page 1 */
+ {0x81, 0xff, 0x11}, /* DSM_FERR_BYPASS = 1 */
+ {0xf4, 0xff, 0x07}, /* DIG_FREQ_CORR = 1 */
+ {0xd4, 0x1f, 0x0f}, /* SPUR_TEST_NOISE_TH = 15 */
+ {0xd6, 0xff, 0x0c}, /* SPUR_TEST_NOISE_PAPR = 12 */
+ {0x00, 0xff, 0x00}, /* Change to page 0 */
+ {0, 0, 0}
+ };
+
+ mxl_debug("()");
+
+ return mxl111sf_ctrl_program_regs(state, mxl_111_overwrite_default);
+}
+
+int mxl1x1sf_soft_reset(struct mxl111sf_state *state)
+{
+ int ret;
+ mxl_debug("()");
+
+ ret = mxl111sf_write_reg(state, 0xff, 0x00); /* AIC */
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_write_reg(state, 0x02, 0x01); /* get out of reset */
+ mxl_fail(ret);
+fail:
+ return ret;
+}
+
+int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode)
+{
+ int ret;
+
+ mxl_debug("(%s)", MXL_SOC_MODE == mode ?
+ "MXL_SOC_MODE" : "MXL_TUNER_MODE");
+
+ /* set device mode */
+ ret = mxl111sf_write_reg(state, 0x03,
+ MXL_SOC_MODE == mode ? 0x01 : 0x00);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg_mask(state,
+ 0x7d, 0x40, MXL_SOC_MODE == mode ?
+ 0x00 : /* enable impulse noise filter,
+ INF_BYP = 0 */
+ 0x40); /* disable impulse noise filter,
+ INF_BYP = 1 */
+ if (mxl_fail(ret))
+ goto fail;
+
+ state->device_mode = mode;
+fail:
+ return ret;
+}
+
+/* power up tuner */
+int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff)
+{
+ mxl_debug("(%d)", onoff);
+
+ return mxl111sf_write_reg(state, 0x01, onoff ? 0x01 : 0x00);
+}
+
+int mxl111sf_disable_656_port(struct mxl111sf_state *state)
+{
+ mxl_debug("()");
+
+ return mxl111sf_write_reg_mask(state, 0x12, 0x04, 0x00);
+}
+
+int mxl111sf_enable_usb_output(struct mxl111sf_state *state)
+{
+ mxl_debug("()");
+
+ return mxl111sf_write_reg_mask(state, 0x17, 0x40, 0x00);
+}
+
+/* initialize TSIF as input port of MxL1X1SF for MPEG2 data transfer */
+int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
+ unsigned int parallel_serial,
+ unsigned int msb_lsb_1st,
+ unsigned int clock_phase,
+ unsigned int mpeg_valid_pol,
+ unsigned int mpeg_sync_pol)
+{
+ int ret;
+ u8 mode, tmp;
+
+ mxl_debug("(%u,%u,%u,%u,%u)", parallel_serial, msb_lsb_1st,
+ clock_phase, mpeg_valid_pol, mpeg_sync_pol);
+
+ /* Enable PIN MUX */
+ ret = mxl111sf_write_reg(state, V6_PIN_MUX_MODE_REG, V6_ENABLE_PIN_MUX);
+ mxl_fail(ret);
+
+ /* Configure MPEG Clock phase */
+ mxl111sf_read_reg(state, V6_MPEG_IN_CLK_INV_REG, &mode);
+
+ if (clock_phase == TSIF_NORMAL)
+ mode &= ~V6_INVERTED_CLK_PHASE;
+ else
+ mode |= V6_INVERTED_CLK_PHASE;
+
+ ret = mxl111sf_write_reg(state, V6_MPEG_IN_CLK_INV_REG, mode);
+ mxl_fail(ret);
+
+ /* Configure data input mode, MPEG Valid polarity, MPEG Sync polarity
+ * Get current configuration */
+ ret = mxl111sf_read_reg(state, V6_MPEG_IN_CTRL_REG, &mode);
+ mxl_fail(ret);
+
+ /* Data Input mode */
+ if (parallel_serial == TSIF_INPUT_PARALLEL) {
+ /* Disable serial mode */
+ mode &= ~V6_MPEG_IN_DATA_SERIAL;
+
+ /* Enable Parallel mode */
+ mode |= V6_MPEG_IN_DATA_PARALLEL;
+ } else {
+ /* Disable Parallel mode */
+ mode &= ~V6_MPEG_IN_DATA_PARALLEL;
+
+ /* Enable Serial Mode */
+ mode |= V6_MPEG_IN_DATA_SERIAL;
+
+ /* If serial interface is chosen, configure
+ MSB or LSB order in transmission */
+ ret = mxl111sf_read_reg(state,
+ V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
+ &tmp);
+ mxl_fail(ret);
+
+ if (msb_lsb_1st == MPEG_SER_MSB_FIRST_ENABLED)
+ tmp |= V6_MPEG_SER_MSB_FIRST;
+ else
+ tmp &= ~V6_MPEG_SER_MSB_FIRST;
+
+ ret = mxl111sf_write_reg(state,
+ V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
+ tmp);
+ mxl_fail(ret);
+ }
+
+ /* MPEG Sync polarity */
+ if (mpeg_sync_pol == TSIF_NORMAL)
+ mode &= ~V6_INVERTED_MPEG_SYNC;
+ else
+ mode |= V6_INVERTED_MPEG_SYNC;
+
+ /* MPEG Valid polarity */
+ if (mpeg_valid_pol == 0)
+ mode &= ~V6_INVERTED_MPEG_VALID;
+ else
+ mode |= V6_INVERTED_MPEG_VALID;
+
+ ret = mxl111sf_write_reg(state, V6_MPEG_IN_CTRL_REG, mode);
+ mxl_fail(ret);
+
+ return ret;
+}
+
+int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size)
+{
+ static struct mxl111sf_reg_ctrl_info init_i2s[] = {
+ {0x1b, 0xff, 0x1e}, /* pin mux mode, Choose 656/I2S input */
+ {0x15, 0x60, 0x60}, /* Enable I2S */
+ {0x17, 0xe0, 0x20}, /* Input, MPEG MODE USB,
+ Inverted 656 Clock, I2S_SOFT_RESET,
+ 0 : Normal operation, 1 : Reset State */
+#if 0
+ {0x12, 0x01, 0x00}, /* AUDIO_IRQ_CLR (Overflow Indicator) */
+#endif
+ {0x00, 0xff, 0x02}, /* Change to Control Page */
+ {0x26, 0x0d, 0x0d}, /* I2S_MODE & BT656_SRC_SEL for FPGA only */
+ {0x00, 0xff, 0x00},
+ {0, 0, 0}
+ };
+ int ret;
+
+ mxl_debug("(0x%02x)", sample_size);
+
+ ret = mxl111sf_ctrl_program_regs(state, init_i2s);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, V6_I2S_NUM_SAMPLES_REG, sample_size);
+ mxl_fail(ret);
+fail:
+ return ret;
+}
+
+int mxl111sf_disable_i2s_port(struct mxl111sf_state *state)
+{
+ static struct mxl111sf_reg_ctrl_info disable_i2s[] = {
+ {0x15, 0x40, 0x00},
+ {0, 0, 0}
+ };
+
+ mxl_debug("()");
+
+ return mxl111sf_ctrl_program_regs(state, disable_i2s);
+}
+
+int mxl111sf_config_i2s(struct mxl111sf_state *state,
+ u8 msb_start_pos, u8 data_width)
+{
+ int ret;
+ u8 tmp;
+
+ mxl_debug("(0x%02x, 0x%02x)", msb_start_pos, data_width);
+
+ ret = mxl111sf_read_reg(state, V6_I2S_STREAM_START_BIT_REG, &tmp);
+ if (mxl_fail(ret))
+ goto fail;
+
+ tmp &= 0xe0;
+ tmp |= msb_start_pos;
+ ret = mxl111sf_write_reg(state, V6_I2S_STREAM_START_BIT_REG, tmp);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_read_reg(state, V6_I2S_STREAM_END_BIT_REG, &tmp);
+ if (mxl_fail(ret))
+ goto fail;
+
+ tmp &= 0xe0;
+ tmp |= data_width;
+ ret = mxl111sf_write_reg(state, V6_I2S_STREAM_END_BIT_REG, tmp);
+ mxl_fail(ret);
+fail:
+ return ret;
+}
+
+int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff)
+{
+ u8 val;
+ int ret;
+
+ mxl_debug("(%d)", onoff);
+
+ ret = mxl111sf_write_reg(state, 0x00, 0x02);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_read_reg(state, V8_SPI_MODE_REG, &val);
+ if (mxl_fail(ret))
+ goto fail;
+
+ if (onoff)
+ val |= 0x04;
+ else
+ val &= ~0x04;
+
+ ret = mxl111sf_write_reg(state, V8_SPI_MODE_REG, val);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_write_reg(state, 0x00, 0x00);
+ if (mxl_fail(ret))
+ goto fail;
+fail:
+ return ret;
+}
+
+int mxl111sf_idac_config(struct mxl111sf_state *state,
+ u8 control_mode, u8 current_setting,
+ u8 current_value, u8 hysteresis_value)
+{
+ int ret;
+ u8 val;
+ /* current value will be set for both automatic & manual IDAC control */
+ val = current_value;
+
+ if (control_mode == IDAC_MANUAL_CONTROL) {
+ /* enable manual control of IDAC */
+ val |= IDAC_MANUAL_CONTROL_BIT_MASK;
+
+ if (current_setting == IDAC_CURRENT_SINKING_ENABLE)
+ /* enable current sinking in manual mode */
+ val |= IDAC_CURRENT_SINKING_BIT_MASK;
+ else
+ /* disable current sinking in manual mode */
+ val &= ~IDAC_CURRENT_SINKING_BIT_MASK;
+ } else {
+ /* disable manual control of IDAC */
+ val &= ~IDAC_MANUAL_CONTROL_BIT_MASK;
+
+ /* set hysteresis value reg: 0x0B<5:0> */
+ ret = mxl111sf_write_reg(state, V6_IDAC_HYSTERESIS_REG,
+ (hysteresis_value & 0x3F));
+ }
+
+ ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val);
+
+ return val;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-phy.h b/drivers/media/dvb/dvb-usb/mxl111sf-phy.h
new file mode 100644
index 000000000000..f0756071d347
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-phy.h
@@ -0,0 +1,53 @@
+/*
+ * mxl111sf-phy.h - driver for the MaxLinear MXL111SF
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ */
+
+#ifndef _DVB_USB_MXL111SF_PHY_H_
+#define _DVB_USB_MXL111SF_PHY_H_
+
+#include "mxl111sf.h"
+
+int mxl1x1sf_soft_reset(struct mxl111sf_state *state);
+int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode);
+int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff);
+int mxl111sf_disable_656_port(struct mxl111sf_state *state);
+int mxl111sf_init_tuner_demod(struct mxl111sf_state *state);
+int mxl111sf_enable_usb_output(struct mxl111sf_state *state);
+int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
+ unsigned int parallel_serial,
+ unsigned int msb_lsb_1st,
+ unsigned int clock_phase,
+ unsigned int mpeg_valid_pol,
+ unsigned int mpeg_sync_pol);
+int mxl111sf_config_i2s(struct mxl111sf_state *state,
+ u8 msb_start_pos, u8 data_width);
+int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size);
+int mxl111sf_disable_i2s_port(struct mxl111sf_state *state);
+int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff);
+int mxl111sf_idac_config(struct mxl111sf_state *state,
+ u8 control_mode, u8 current_setting,
+ u8 current_value, u8 hysteresis_value);
+
+#endif /* _DVB_USB_MXL111SF_PHY_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-reg.h b/drivers/media/dvb/dvb-usb/mxl111sf-reg.h
new file mode 100644
index 000000000000..17831b0fb9db
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-reg.h
@@ -0,0 +1,179 @@
+/*
+ * mxl111sf-reg.h - driver for the MaxLinear MXL111SF
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ */
+
+#ifndef _DVB_USB_MXL111SF_REG_H_
+#define _DVB_USB_MXL111SF_REG_H_
+
+#define CHIP_ID_REG 0xFC
+#define TOP_CHIP_REV_ID_REG 0xFA
+
+#define V6_SNR_RB_LSB_REG 0x27
+#define V6_SNR_RB_MSB_REG 0x28
+
+#define V6_N_ACCUMULATE_REG 0x11
+#define V6_RS_AVG_ERRORS_LSB_REG 0x2C
+#define V6_RS_AVG_ERRORS_MSB_REG 0x2D
+
+#define V6_IRQ_STATUS_REG 0x24
+#define IRQ_MASK_FEC_LOCK 0x10
+
+#define V6_SYNC_LOCK_REG 0x28
+#define SYNC_LOCK_MASK 0x10
+
+#define V6_RS_LOCK_DET_REG 0x28
+#define RS_LOCK_DET_MASK 0x08
+
+#define V6_INITACQ_NODETECT_REG 0x20
+#define V6_FORCE_NFFT_CPSIZE_REG 0x20
+
+#define V6_CODE_RATE_TPS_REG 0x29
+#define V6_CODE_RATE_TPS_MASK 0x07
+
+
+#define V6_CP_LOCK_DET_REG 0x28
+#define V6_CP_LOCK_DET_MASK 0x04
+
+#define V6_TPS_HIERACHY_REG 0x29
+#define V6_TPS_HIERARCHY_INFO_MASK 0x40
+
+#define V6_MODORDER_TPS_REG 0x2A
+#define V6_PARAM_CONSTELLATION_MASK 0x30
+
+#define V6_MODE_TPS_REG 0x2A
+#define V6_PARAM_FFT_MODE_MASK 0x0C
+
+
+#define V6_CP_TPS_REG 0x29
+#define V6_PARAM_GI_MASK 0x30
+
+#define V6_TPS_LOCK_REG 0x2A
+#define V6_PARAM_TPS_LOCK_MASK 0x40
+
+#define V6_FEC_PER_COUNT_REG 0x2E
+#define V6_FEC_PER_SCALE_REG 0x2B
+#define V6_FEC_PER_SCALE_MASK 0x03
+#define V6_FEC_PER_CLR_REG 0x20
+#define V6_FEC_PER_CLR_MASK 0x01
+
+#define V6_PIN_MUX_MODE_REG 0x1B
+#define V6_ENABLE_PIN_MUX 0x1E
+
+#define V6_I2S_NUM_SAMPLES_REG 0x16
+
+#define V6_MPEG_IN_CLK_INV_REG 0x17
+#define V6_MPEG_IN_CTRL_REG 0x18
+
+#define V6_INVERTED_CLK_PHASE 0x20
+#define V6_MPEG_IN_DATA_PARALLEL 0x01
+#define V6_MPEG_IN_DATA_SERIAL 0x02
+
+#define V6_INVERTED_MPEG_SYNC 0x04
+#define V6_INVERTED_MPEG_VALID 0x08
+
+#define TSIF_INPUT_PARALLEL 0
+#define TSIF_INPUT_SERIAL 1
+#define TSIF_NORMAL 0
+
+#define V6_MPEG_INOUT_BIT_ORDER_CTRL_REG 0x19
+#define V6_MPEG_SER_MSB_FIRST 0x80
+#define MPEG_SER_MSB_FIRST_ENABLED 0x01
+
+#define V6_656_I2S_BUFF_STATUS_REG 0x2F
+#define V6_656_OVERFLOW_MASK_BIT 0x08
+#define V6_I2S_OVERFLOW_MASK_BIT 0x01
+
+#define V6_I2S_STREAM_START_BIT_REG 0x14
+#define V6_I2S_STREAM_END_BIT_REG 0x15
+#define I2S_RIGHT_JUSTIFIED 0
+#define I2S_LEFT_JUSTIFIED 1
+#define I2S_DATA_FORMAT 2
+
+#define V6_TUNER_LOOP_THRU_CONTROL_REG 0x09
+#define V6_ENABLE_LOOP_THRU 0x01
+
+#define TOTAL_NUM_IF_OUTPUT_FREQ 16
+
+#define TUNER_NORMAL_IF_SPECTRUM 0x0
+#define TUNER_INVERT_IF_SPECTRUM 0x10
+
+#define V6_TUNER_IF_SEL_REG 0x06
+#define V6_TUNER_IF_FCW_REG 0x3C
+#define V6_TUNER_IF_FCW_BYP_REG 0x3D
+#define V6_RF_LOCK_STATUS_REG 0x23
+
+#define NUM_DIG_TV_CHANNEL 1000
+
+#define V6_DIG_CLK_FREQ_SEL_REG 0x07
+#define V6_REF_SYNTH_INT_REG 0x5C
+#define V6_REF_SYNTH_REMAIN_REG 0x58
+#define V6_DIG_RFREFSELECT_REG 0x32
+#define V6_XTAL_CLK_OUT_GAIN_REG 0x31
+#define V6_TUNER_LOOP_THRU_CTRL_REG 0x09
+#define V6_DIG_XTAL_ENABLE_REG 0x06
+#define V6_DIG_XTAL_BIAS_REG 0x66
+#define V6_XTAL_CAP_REG 0x08
+
+#define V6_GPO_CTRL_REG 0x18
+#define MXL_GPO_0 0x00
+#define MXL_GPO_1 0x01
+#define V6_GPO_0_MASK 0x10
+#define V6_GPO_1_MASK 0x20
+
+#define V6_111SF_GPO_CTRL_REG 0x19
+#define MXL_111SF_GPO_1 0x00
+#define MXL_111SF_GPO_2 0x01
+#define MXL_111SF_GPO_3 0x02
+#define MXL_111SF_GPO_4 0x03
+#define MXL_111SF_GPO_5 0x04
+#define MXL_111SF_GPO_6 0x05
+#define MXL_111SF_GPO_7 0x06
+
+#define MXL_111SF_GPO_0_MASK 0x01
+#define MXL_111SF_GPO_1_MASK 0x02
+#define MXL_111SF_GPO_2_MASK 0x04
+#define MXL_111SF_GPO_3_MASK 0x08
+#define MXL_111SF_GPO_4_MASK 0x10
+#define MXL_111SF_GPO_5_MASK 0x20
+#define MXL_111SF_GPO_6_MASK 0x40
+
+#define V6_ATSC_CONFIG_REG 0x0A
+
+#define MXL_MODE_REG 0x03
+#define START_TUNE_REG 0x1C
+
+#define V6_IDAC_HYSTERESIS_REG 0x0B
+#define V6_IDAC_SETTINGS_REG 0x0C
+#define IDAC_MANUAL_CONTROL 1
+#define IDAC_CURRENT_SINKING_ENABLE 1
+#define IDAC_MANUAL_CONTROL_BIT_MASK 0x80
+#define IDAC_CURRENT_SINKING_BIT_MASK 0x40
+
+#define V8_SPI_MODE_REG 0xE9
+
+#define V6_DIG_RF_PWR_LSB_REG 0x46
+#define V6_DIG_RF_PWR_MSB_REG 0x47
+
+#endif /* _DVB_USB_MXL111SF_REG_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
new file mode 100644
index 000000000000..a6341058c4e7
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
@@ -0,0 +1,476 @@
+/*
+ * mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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 "mxl111sf-tuner.h"
+#include "mxl111sf-phy.h"
+#include "mxl111sf-reg.h"
+
+/* debug */
+static int mxl111sf_tuner_debug;
+module_param_named(debug, mxl111sf_tuner_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define mxl_dbg(fmt, arg...) \
+ if (mxl111sf_tuner_debug) \
+ mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+/* ------------------------------------------------------------------------ */
+
+struct mxl111sf_tuner_state {
+ struct mxl111sf_state *mxl_state;
+
+ struct mxl111sf_tuner_config *cfg;
+
+ u32 frequency;
+ u32 bandwidth;
+};
+
+static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state,
+ u8 addr, u8 *data)
+{
+ return (state->cfg->read_reg) ?
+ state->cfg->read_reg(state->mxl_state, addr, data) :
+ -EINVAL;
+}
+
+static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state,
+ u8 addr, u8 data)
+{
+ return (state->cfg->write_reg) ?
+ state->cfg->write_reg(state->mxl_state, addr, data) :
+ -EINVAL;
+}
+
+static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state,
+ struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
+{
+ return (state->cfg->program_regs) ?
+ state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
+ -EINVAL;
+}
+
+static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state,
+ int onoff)
+{
+ return (state->cfg->top_master_ctrl) ?
+ state->cfg->top_master_ctrl(state->mxl_state, onoff) :
+ -EINVAL;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = {
+ {0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
+ DIG_MODEINDEX, _A, _CSF, */
+ {0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
+ {0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
+ {0, 0, 0}
+};
+
+/* ------------------------------------------------------------------------ */
+
+static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq,
+ u8 bw)
+{
+ u8 filt_bw;
+
+ /* set channel bandwidth */
+ switch (bw) {
+ case 0: /* ATSC */
+ filt_bw = 25;
+ break;
+ case 1: /* QAM */
+ filt_bw = 69;
+ break;
+ case 6:
+ filt_bw = 21;
+ break;
+ case 7:
+ filt_bw = 42;
+ break;
+ case 8:
+ filt_bw = 63;
+ break;
+ default:
+ err("%s: invalid bandwidth setting!", __func__);
+ return NULL;
+ }
+
+ /* calculate RF channel */
+ freq /= 1000000;
+
+ freq *= 64;
+#if 0
+ /* do round */
+ freq += 0.5;
+#endif
+ /* set bandwidth */
+ mxl_phy_tune_rf[0].data = filt_bw;
+
+ /* set RF */
+ mxl_phy_tune_rf[1].data = (freq & 0xff);
+ mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff;
+
+ /* start tune */
+ return mxl_phy_tune_rf;
+}
+
+static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
+{
+ int ret;
+ u8 ctrl;
+#if 0
+ u16 iffcw;
+ u32 if_freq;
+#endif
+ mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
+ state->cfg->invert_spectrum, state->cfg->if_freq);
+
+ /* set IF polarity */
+ ctrl = state->cfg->invert_spectrum;
+
+ ctrl |= state->cfg->if_freq;
+
+ ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl);
+ if (mxl_fail(ret))
+ goto fail;
+
+#if 0
+ if_freq /= 1000000;
+
+ /* do round */
+ if_freq += 0.5;
+
+ if (MXL_IF_LO == state->cfg->if_freq) {
+ ctrl = 0x08;
+ iffcw = (u16)(if_freq / (108 * 4096));
+ } else if (MXL_IF_HI == state->cfg->if_freq) {
+ ctrl = 0x08;
+ iffcw = (u16)(if_freq / (216 * 4096));
+ } else {
+ ctrl = 0;
+ iffcw = 0;
+ }
+
+ ctrl |= (iffcw >> 8);
+#endif
+ ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ctrl &= 0xf0;
+ ctrl |= 0x90;
+
+ ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl);
+ if (mxl_fail(ret))
+ goto fail;
+
+#if 0
+ ctrl = iffcw & 0x00ff;
+#endif
+ ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
+ mxl_fail(ret);
+fail:
+ return ret;
+}
+
+static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw)
+{
+ struct mxl111sf_tuner_state *state = fe->tuner_priv;
+ static struct mxl111sf_reg_ctrl_info *reg_ctrl_array;
+ int ret;
+ u8 mxl_mode;
+
+ mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw);
+
+ /* stop tune */
+ ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0);
+ if (mxl_fail(ret))
+ goto fail;
+
+ /* check device mode */
+ ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode);
+ if (mxl_fail(ret))
+ goto fail;
+
+ /* Fill out registers for channel tune */
+ reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw);
+ if (!reg_ctrl_array)
+ return -EINVAL;
+
+ ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array);
+ if (mxl_fail(ret))
+ goto fail;
+
+ if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) {
+ /* IF tuner mode only */
+ mxl1x1sf_tuner_top_master_ctrl(state, 0);
+ mxl1x1sf_tuner_top_master_ctrl(state, 1);
+ mxl1x1sf_tuner_set_if_output_freq(state);
+ }
+
+ ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1);
+ if (mxl_fail(ret))
+ goto fail;
+
+ if (state->cfg->ant_hunt)
+ state->cfg->ant_hunt(fe);
+fail:
+ return ret;
+}
+
+static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state,
+ int *rf_synth_lock,
+ int *ref_synth_lock)
+{
+ int ret;
+ u8 data;
+
+ *rf_synth_lock = 0;
+ *ref_synth_lock = 0;
+
+ ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data);
+ if (mxl_fail(ret))
+ goto fail;
+
+ *ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0;
+ *rf_synth_lock = ((data & 0x0c) == 0x0c) ? 1 : 0;
+fail:
+ return ret;
+}
+
+#if 0
+static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
+ int onoff)
+{
+ return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG,
+ onoff ? 1 : 0);
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_tuner_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ struct mxl111sf_tuner_state *state = fe->tuner_priv;
+ int ret;
+ u8 bw;
+
+ mxl_dbg("()");
+
+ if (fe->ops.info.type == FE_ATSC) {
+ switch (params->u.vsb.modulation) {
+ case VSB_8:
+ case VSB_16:
+ bw = 0; /* ATSC */
+ break;
+ case QAM_64:
+ case QAM_256:
+ bw = 1; /* US CABLE */
+ break;
+ default:
+ err("%s: modulation not set!", __func__);
+ return -EINVAL;
+ }
+ } else if (fe->ops.info.type == FE_OFDM) {
+ switch (params->u.ofdm.bandwidth) {
+ case BANDWIDTH_6_MHZ:
+ bw = 6;
+ break;
+ case BANDWIDTH_7_MHZ:
+ bw = 7;
+ break;
+ case BANDWIDTH_8_MHZ:
+ bw = 8;
+ break;
+ default:
+ err("%s: bandwidth not set!", __func__);
+ return -EINVAL;
+ }
+ } else {
+ err("%s: modulation type not supported!", __func__);
+ return -EINVAL;
+ }
+ ret = mxl1x1sf_tune_rf(fe, params->frequency, bw);
+ if (mxl_fail(ret))
+ goto fail;
+
+ state->frequency = params->frequency;
+ state->bandwidth = (fe->ops.info.type == FE_OFDM) ?
+ params->u.ofdm.bandwidth : 0;
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#if 0
+static int mxl111sf_tuner_init(struct dvb_frontend *fe)
+{
+ struct mxl111sf_tuner_state *state = fe->tuner_priv;
+ int ret;
+
+ /* wake from standby handled by usb driver */
+
+ return ret;
+}
+
+static int mxl111sf_tuner_sleep(struct dvb_frontend *fe)
+{
+ struct mxl111sf_tuner_state *state = fe->tuner_priv;
+ int ret;
+
+ /* enter standby mode handled by usb driver */
+
+ return ret;
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status)
+{
+ struct mxl111sf_tuner_state *state = fe->tuner_priv;
+ int rf_locked, ref_locked, ret;
+
+ *status = 0;
+
+ ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked);
+ if (mxl_fail(ret))
+ goto fail;
+ mxl_info("%s%s", rf_locked ? "rf locked " : "",
+ ref_locked ? "ref locked" : "");
+
+ if ((rf_locked) || (ref_locked))
+ *status |= TUNER_STATUS_LOCKED;
+fail:
+ return ret;
+}
+
+static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct mxl111sf_tuner_state *state = fe->tuner_priv;
+ u8 val1, val2;
+ int ret;
+
+ *strength = 0;
+
+ ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2);
+ if (mxl_fail(ret))
+ goto fail;
+
+ *strength = val1 | ((val2 & 0x07) << 8);
+fail:
+ ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00);
+ mxl_fail(ret);
+
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct mxl111sf_tuner_state *state = fe->tuner_priv;
+ *frequency = state->frequency;
+ return 0;
+}
+
+static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ struct mxl111sf_tuner_state *state = fe->tuner_priv;
+ *bandwidth = state->bandwidth;
+ return 0;
+}
+
+static int mxl111sf_tuner_release(struct dvb_frontend *fe)
+{
+ struct mxl111sf_tuner_state *state = fe->tuner_priv;
+ mxl_dbg("()");
+ kfree(state);
+ fe->tuner_priv = NULL;
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
+ .info = {
+ .name = "MaxLinear MxL111SF",
+#if 0
+ .frequency_min = ,
+ .frequency_max = ,
+ .frequency_step = ,
+#endif
+ },
+#if 0
+ .init = mxl111sf_tuner_init,
+ .sleep = mxl111sf_tuner_sleep,
+#endif
+ .set_params = mxl111sf_tuner_set_params,
+ .get_status = mxl111sf_tuner_get_status,
+ .get_rf_strength = mxl111sf_get_rf_strength,
+ .get_frequency = mxl111sf_tuner_get_frequency,
+ .get_bandwidth = mxl111sf_tuner_get_bandwidth,
+ .release = mxl111sf_tuner_release,
+};
+
+struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
+ struct mxl111sf_state *mxl_state,
+ struct mxl111sf_tuner_config *cfg)
+{
+ struct mxl111sf_tuner_state *state = NULL;
+
+ mxl_dbg("()");
+
+ state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL);
+ if (state == NULL)
+ return NULL;
+
+ state->mxl_state = mxl_state;
+ state->cfg = cfg;
+
+ memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+
+ fe->tuner_priv = state;
+ return fe;
+}
+EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
+
+MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h
new file mode 100644
index 000000000000..ff333960b184
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h
@@ -0,0 +1,89 @@
+/*
+ * mxl111sf-tuner.h - driver for the MaxLinear MXL111SF CMOS tuner
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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.
+ */
+
+#ifndef __MXL111SF_TUNER_H__
+#define __MXL111SF_TUNER_H__
+
+#include "dvb_frontend.h"
+
+#include "mxl111sf.h"
+
+enum mxl_if_freq {
+#if 0
+ MXL_IF_LO = 0x00, /* other IF < 9MHz */
+#endif
+ MXL_IF_4_0 = 0x01, /* 4.0 MHz */
+ MXL_IF_4_5 = 0x02, /* 4.5 MHz */
+ MXL_IF_4_57 = 0x03, /* 4.57 MHz */
+ MXL_IF_5_0 = 0x04, /* 5.0 MHz */
+ MXL_IF_5_38 = 0x05, /* 5.38 MHz */
+ MXL_IF_6_0 = 0x06, /* 6.0 MHz */
+ MXL_IF_6_28 = 0x07, /* 6.28 MHz */
+ MXL_IF_7_2 = 0x08, /* 7.2 MHz */
+ MXL_IF_35_25 = 0x09, /* 35.25 MHz */
+ MXL_IF_36 = 0x0a, /* 36 MHz */
+ MXL_IF_36_15 = 0x0b, /* 36.15 MHz */
+ MXL_IF_44 = 0x0c, /* 44 MHz */
+#if 0
+ MXL_IF_HI = 0x0f, /* other IF > 35 MHz and < 45 MHz */
+#endif
+};
+
+struct mxl111sf_tuner_config {
+ enum mxl_if_freq if_freq;
+ unsigned int invert_spectrum:1;
+
+ int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data);
+ int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data);
+ int (*program_regs)(struct mxl111sf_state *state,
+ struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
+ int (*top_master_ctrl)(struct mxl111sf_state *state, int onoff);
+ int (*ant_hunt)(struct dvb_frontend *fe);
+};
+
+/* ------------------------------------------------------------------------ */
+
+#if defined(CONFIG_DVB_USB_MXL111SF) || \
+ (defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
+extern
+struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
+ struct mxl111sf_state *mxl_state,
+ struct mxl111sf_tuner_config *cfg);
+#else
+static inline
+struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
+ struct mxl111sf_state *mxl_state
+ struct mxl111sf_tuner_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
+#endif /* __MXL111SF_TUNER_H__ */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.c b/drivers/media/dvb/dvb-usb/mxl111sf.c
new file mode 100644
index 000000000000..546ba5915a5b
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf.c
@@ -0,0 +1,864 @@
+/*
+ * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/i2c.h>
+
+#include "mxl111sf.h"
+#include "mxl111sf-reg.h"
+#include "mxl111sf-phy.h"
+#include "mxl111sf-i2c.h"
+#include "mxl111sf-gpio.h"
+
+#include "mxl111sf-tuner.h"
+
+#include "lgdt3305.h"
+
+int dvb_usb_mxl111sf_debug;
+module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level "
+ "(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able)).");
+
+int dvb_usb_mxl111sf_isoc;
+module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644);
+MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc).");
+
+#define ANT_PATH_AUTO 0
+#define ANT_PATH_EXTERNAL 1
+#define ANT_PATH_INTERNAL 2
+
+int dvb_usb_mxl111sf_rfswitch =
+#if 0
+ ANT_PATH_AUTO;
+#else
+ ANT_PATH_EXTERNAL;
+#endif
+
+module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644);
+MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define deb_info(args...) dprintk(dvb_usb_mxl111sf_debug, 0x13, args)
+#define deb_reg(args...) dprintk(dvb_usb_mxl111sf_debug, 0x08, args)
+#define deb_adv(args...) dprintk(dvb_usb_mxl111sf_debug, MXL_ADV_DBG, args)
+
+int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
+ u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+ int wo = (rbuf == NULL || rlen == 0); /* write-only */
+ int ret;
+ u8 sndbuf[1+wlen];
+
+ deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
+
+ memset(sndbuf, 0, 1+wlen);
+
+ sndbuf[0] = cmd;
+ memcpy(&sndbuf[1], wbuf, wlen);
+
+ ret = (wo) ? dvb_usb_generic_write(d, sndbuf, 1+wlen) :
+ dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
+ mxl_fail(ret);
+
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#define MXL_CMD_REG_READ 0xaa
+#define MXL_CMD_REG_WRITE 0x55
+
+int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data)
+{
+ u8 buf[2];
+ int ret;
+
+ ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
+ if (mxl_fail(ret)) {
+ mxl_debug("error reading reg: 0x%02x", addr);
+ goto fail;
+ }
+
+ if (buf[0] == addr)
+ *data = buf[1];
+ else {
+ err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x",
+ addr, buf[0], buf[1]);
+ ret = -EINVAL;
+ }
+
+ deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data);
+fail:
+ return ret;
+}
+
+int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data)
+{
+ u8 buf[] = { addr, data };
+ int ret;
+
+ deb_reg("W: (0x%02x, 0x%02x)\n", addr, data);
+
+ ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
+ if (mxl_fail(ret))
+ err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
+ u8 addr, u8 mask, u8 data)
+{
+ int ret;
+ u8 val;
+
+ if (mask != 0xff) {
+ ret = mxl111sf_read_reg(state, addr, &val);
+#if 1
+ /* dont know why this usually errors out on the first try */
+ if (mxl_fail(ret))
+ err("error writing addr: 0x%02x, mask: 0x%02x, "
+ "data: 0x%02x, retrying...", addr, mask, data);
+
+ ret = mxl111sf_read_reg(state, addr, &val);
+#endif
+ if (mxl_fail(ret))
+ goto fail;
+ }
+ val &= ~mask;
+ val |= data;
+
+ ret = mxl111sf_write_reg(state, addr, val);
+ mxl_fail(ret);
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
+ struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
+{
+ int i, ret = 0;
+
+ for (i = 0; ctrl_reg_info[i].addr |
+ ctrl_reg_info[i].mask |
+ ctrl_reg_info[i].data; i++) {
+
+ ret = mxl111sf_write_reg_mask(state,
+ ctrl_reg_info[i].addr,
+ ctrl_reg_info[i].mask,
+ ctrl_reg_info[i].data);
+ if (mxl_fail(ret)) {
+ err("failed on reg #%d (0x%02x)", i,
+ ctrl_reg_info[i].addr);
+ break;
+ }
+ }
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state)
+{
+ int ret;
+ u8 id, ver;
+ char *mxl_chip, *mxl_rev;
+
+ if ((state->chip_id) && (state->chip_ver))
+ return 0;
+
+ ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id);
+ if (mxl_fail(ret))
+ goto fail;
+ state->chip_id = id;
+
+ ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver);
+ if (mxl_fail(ret))
+ goto fail;
+ state->chip_ver = ver;
+
+ switch (id) {
+ case 0x61:
+ mxl_chip = "MxL101SF";
+ break;
+ case 0x63:
+ mxl_chip = "MxL111SF";
+ break;
+ default:
+ mxl_chip = "UNKNOWN MxL1X1";
+ break;
+ }
+ switch (ver) {
+ case 0x36:
+ state->chip_rev = MXL111SF_V6;
+ mxl_rev = "v6";
+ break;
+ case 0x08:
+ state->chip_rev = MXL111SF_V8_100;
+ mxl_rev = "v8_100";
+ break;
+ case 0x18:
+ state->chip_rev = MXL111SF_V8_200;
+ mxl_rev = "v8_200";
+ break;
+ default:
+ state->chip_rev = 0;
+ mxl_rev = "UNKNOWN REVISION";
+ break;
+ }
+ info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver);
+fail:
+ return ret;
+}
+
+#define get_chip_info(state) \
+({ \
+ int ___ret; \
+ ___ret = mxl1x1sf_get_chip_info(state); \
+ if (mxl_fail(___ret)) { \
+ mxl_debug("failed to get chip info" \
+ " on first probe attempt"); \
+ ___ret = mxl1x1sf_get_chip_info(state); \
+ if (mxl_fail(___ret)) \
+ err("failed to get chip info during probe"); \
+ else \
+ mxl_debug("probe needed a retry " \
+ "in order to succeed."); \
+ } \
+ ___ret; \
+})
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ /* power control depends on which adapter is being woken:
+ * save this for init, instead, via mxl111sf_adap_fe_init */
+ return 0;
+}
+
+static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dvb_usb_device *d = adap->dev;
+ struct mxl111sf_state *state = d->priv;
+ struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
+
+ int err;
+
+ /* exit if we didnt initialize the driver yet */
+ if (!state->chip_id) {
+ mxl_debug("driver not yet initialized, exit.");
+ goto fail;
+ }
+
+ deb_info("%s()\n", __func__);
+
+ mutex_lock(&state->fe_lock);
+
+ state->alt_mode = adap_state->alt_mode;
+
+ if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+ err("set interface failed");
+
+ err = mxl1x1sf_soft_reset(state);
+ mxl_fail(err);
+ err = mxl111sf_init_tuner_demod(state);
+ mxl_fail(err);
+ err = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+
+ mxl_fail(err);
+ mxl111sf_enable_usb_output(state);
+ mxl_fail(err);
+ mxl1x1sf_top_master_ctrl(state, 1);
+ mxl_fail(err);
+
+ if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) &&
+ (state->chip_rev > MXL111SF_V6)) {
+ mxl111sf_config_pin_mux_modes(state,
+ PIN_MUX_TS_SPI_IN_MODE_1);
+ mxl_fail(err);
+ }
+ err = mxl111sf_init_port_expander(state);
+ if (!mxl_fail(err)) {
+ state->gpio_mode = adap_state->gpio_mode;
+ err = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+ mxl_fail(err);
+#if 0
+ err = fe->ops.init(fe);
+#endif
+ msleep(100); /* add short delay after enabling
+ * the demod before touching it */
+ }
+
+ return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0;
+fail:
+ return -ENODEV;
+}
+
+static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dvb_usb_device *d = adap->dev;
+ struct mxl111sf_state *state = d->priv;
+ struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
+ int err;
+
+ /* exit if we didnt initialize the driver yet */
+ if (!state->chip_id) {
+ mxl_debug("driver not yet initialized, exit.");
+ goto fail;
+ }
+
+ deb_info("%s()\n", __func__);
+
+ err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0;
+
+ mutex_unlock(&state->fe_lock);
+
+ return err;
+fail:
+ return -ENODEV;
+}
+
+
+static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+ struct dvb_usb_device *d = adap->dev;
+ struct mxl111sf_state *state = d->priv;
+ struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv;
+ int ret = 0;
+ u8 tmp;
+
+ deb_info("%s(%d)\n", __func__, onoff);
+
+ if (onoff) {
+ ret = mxl111sf_enable_usb_output(state);
+ mxl_fail(ret);
+ ret = mxl111sf_config_mpeg_in(state, 1, 1,
+ adap_state->ep6_clockphase,
+ 0, 0);
+ mxl_fail(ret);
+ } else {
+ ret = mxl111sf_disable_656_port(state);
+ mxl_fail(ret);
+ }
+
+ mxl111sf_read_reg(state, 0x12, &tmp);
+ tmp &= ~0x04;
+ mxl111sf_write_reg(state, 0x12, tmp);
+
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct lgdt3305_config hauppauge_lgdt3305_config = {
+ .i2c_addr = 0xb2 >> 1,
+ .mpeg_mode = LGDT3305_MPEG_SERIAL,
+ .tpclk_edge = LGDT3305_TPCLK_RISING_EDGE,
+ .tpvalid_polarity = LGDT3305_TP_VALID_HIGH,
+ .deny_i2c_rptr = 1,
+ .spectral_inversion = 0,
+ .qam_if_khz = 6000,
+ .vsb_if_khz = 6000,
+};
+
+static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap->dev;
+ struct mxl111sf_state *state = d->priv;
+ int fe_id = adap->num_frontends_initialized;
+ struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
+ int ret;
+
+ deb_adv("%s()\n", __func__);
+
+ /* save a pointer to the dvb_usb_device in device state */
+ state->d = d;
+ adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
+ state->alt_mode = adap_state->alt_mode;
+
+ if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+ err("set interface failed");
+
+ state->gpio_mode = MXL111SF_GPIO_MOD_ATSC;
+ adap_state->gpio_mode = state->gpio_mode;
+ adap_state->device_mode = MXL_TUNER_MODE;
+ adap_state->ep6_clockphase = 1;
+
+ ret = mxl1x1sf_soft_reset(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_init_tuner_demod(state);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_enable_usb_output(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl1x1sf_top_master_ctrl(state, 1);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_init_port_expander(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+ if (mxl_fail(ret))
+ goto fail;
+
+ adap->fe_adap[fe_id].fe = dvb_attach(lgdt3305_attach,
+ &hauppauge_lgdt3305_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe_adap[fe_id].fe) {
+ adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
+ adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
+ adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
+ adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
+ return 0;
+ }
+ ret = -EIO;
+fail:
+ return ret;
+}
+
+static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state,
+ int antpath)
+{
+ return mxl111sf_idac_config(state, 1, 1,
+ (antpath == ANT_PATH_INTERNAL) ?
+ 0x3f : 0x00, 0);
+}
+
+#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \
+ err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \
+ __func__, __LINE__, \
+ (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \
+ pwr0, pwr1, pwr2, pwr3)
+
+#define ANT_HUNT_SLEEP 90
+#define ANT_EXT_TWEAK 0
+
+static int mxl111sf_ant_hunt(struct dvb_frontend *fe)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dvb_usb_device *d = adap->dev;
+ struct mxl111sf_state *state = d->priv;
+
+ int antctrl = dvb_usb_mxl111sf_rfswitch;
+
+ u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2;
+
+ /* FIXME: must force EXTERNAL for QAM - done elsewhere */
+ mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ?
+ ANT_PATH_EXTERNAL : antctrl);
+
+ if (antctrl == ANT_PATH_AUTO) {
+#if 0
+ msleep(ANT_HUNT_SLEEP);
+#endif
+ fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA);
+
+ mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+ msleep(ANT_HUNT_SLEEP);
+ fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0);
+
+ mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+ msleep(ANT_HUNT_SLEEP);
+ fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1);
+
+ mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL);
+ msleep(ANT_HUNT_SLEEP);
+ fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2);
+
+ if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) {
+ /* return with EXTERNAL enabled */
+ mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+ DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA,
+ rxPwr0, rxPwr1, rxPwr2);
+ } else {
+ /* return with INTERNAL enabled */
+ DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA,
+ rxPwr0, rxPwr1, rxPwr2);
+ }
+ }
+ return 0;
+}
+
+static struct mxl111sf_tuner_config mxl_tuner_config = {
+ .if_freq = MXL_IF_6_0, /* applies to external IF output, only */
+ .invert_spectrum = 0,
+ .read_reg = mxl111sf_read_reg,
+ .write_reg = mxl111sf_write_reg,
+ .program_regs = mxl111sf_ctrl_program_regs,
+ .top_master_ctrl = mxl1x1sf_top_master_ctrl,
+ .ant_hunt = mxl111sf_ant_hunt,
+};
+
+static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap->dev;
+ struct mxl111sf_state *state = d->priv;
+ int fe_id = adap->num_frontends_initialized;
+
+ deb_adv("%s()\n", __func__);
+
+ if (NULL != dvb_attach(mxl111sf_tuner_attach,
+ adap->fe_adap[fe_id].fe, state,
+ &mxl_tuner_config))
+ return 0;
+
+ return -EIO;
+}
+
+static int mxl111sf_fe_ioctl_override(struct dvb_frontend *fe,
+ unsigned int cmd, void *parg,
+ unsigned int stage)
+{
+ int err = 0;
+
+ switch (stage) {
+ case DVB_FE_IOCTL_PRE:
+
+ switch (cmd) {
+ case FE_READ_SIGNAL_STRENGTH:
+ err = fe->ops.tuner_ops.get_rf_strength(fe, parg);
+ /* If no error occurs, prevent dvb-core from handling
+ * this IOCTL, otherwise return the error */
+ if (0 == err)
+ err = 1;
+ break;
+ }
+ break;
+
+ case DVB_FE_IOCTL_POST:
+ /* no post-ioctl handling required */
+ break;
+ }
+ return err;
+};
+
+static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+struct i2c_algorithm mxl111sf_i2c_algo = {
+ .master_xfer = mxl111sf_i2c_xfer,
+ .functionality = mxl111sf_i2c_func,
+#ifdef NEED_ALGO_CONTROL
+ .algo_control = dummy_algo_control,
+#endif
+};
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties;
+
+static int mxl111sf_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct dvb_usb_device *d = NULL;
+
+ deb_adv("%s()\n", __func__);
+
+ if (((dvb_usb_mxl111sf_isoc) &&
+ (0 == dvb_usb_device_init(intf,
+ &mxl111sf_atsc_isoc_properties,
+ THIS_MODULE, &d, adapter_nr))) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_atsc_bulk_properties,
+ THIS_MODULE, &d, adapter_nr) || 0) {
+
+ struct mxl111sf_state *state = d->priv;
+ static u8 eeprom[256];
+ struct i2c_client c;
+ int ret;
+
+ ret = get_chip_info(state);
+ if (mxl_fail(ret))
+ err("failed to get chip info during probe");
+
+ mutex_init(&state->fe_lock);
+
+ if (state->chip_rev > MXL111SF_V6)
+ mxl111sf_config_pin_mux_modes(state,
+ PIN_MUX_TS_SPI_IN_MODE_1);
+
+ c.adapter = &d->i2c_adap;
+ c.addr = 0xa0 >> 1;
+
+ ret = tveeprom_read(&c, eeprom, sizeof(eeprom));
+ if (mxl_fail(ret))
+ return 0;
+ tveeprom_hauppauge_analog(&c, &state->tv,
+ (0x84 == eeprom[0xa0]) ?
+ eeprom + 0xa0 : eeprom + 0x80);
+#if 0
+ switch (state->tv.model) {
+ case 117001:
+ case 126001:
+ case 138001:
+ break;
+ default:
+ printk(KERN_WARNING "%s: warning: "
+ "unknown hauppauge model #%d\n",
+ __func__, state->tv.model);
+ }
+#endif
+ return 0;
+ }
+ err("Your device is not yet supported by this driver. "
+ "See kernellabs.com for more info");
+ return -EINVAL;
+}
+
+static struct usb_device_id mxl111sf_table[] = {
+/* 0 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600) }, /* ATSC+ IR */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601) }, /* ATSC */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602) }, /* + */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603) }, /* ATSC+ */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604) }, /* DVBT */
+/* 5 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609) }, /* ATSC IR */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a) }, /* + IR */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b) }, /* ATSC+ IR */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c) }, /* DVBT IR */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653) }, /* ATSC+ */
+/*10 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b) }, /* ATSC+ IR */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700) }, /* ATSC+ sw */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701) }, /* ATSC sw */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702) }, /* + sw */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703) }, /* ATSC+ sw */
+/*15 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704) }, /* DVBT sw */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753) }, /* ATSC+ sw */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763) }, /* ATSC+ no */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764) }, /* DVBT no */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853) }, /* ATSC+ sw */
+/*20 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854) }, /* DVBT sw */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863) }, /* ATSC+ no */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864) }, /* DVBT no */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3) }, /* ATSC+ sw */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4) }, /* DVBT sw */
+/*25 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3) }, /* ATSC+ no */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4) }, /* DVBT no */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff) }, /* ATSC+ */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612) }, /* + */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613) }, /* ATSC+ */
+/*30 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a) }, /* + IR */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b) }, /* ATSC+ IR */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757) }, /* ATSC+DVBT sw */
+ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767) }, /* ATSC+DVBT no */
+ {} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, mxl111sf_table);
+
+
+#define MXL111SF_EP6_BULK_STREAMING_CONFIG \
+ .streaming_ctrl = mxl111sf_ep6_streaming_ctrl, \
+ .stream = { \
+ .type = USB_BULK, \
+ .count = 5, \
+ .endpoint = 0x06, \
+ .u = { \
+ .bulk = { \
+ .buffersize = 8192, \
+ } \
+ } \
+ }
+
+/* FIXME */
+#define MXL111SF_EP6_ISOC_STREAMING_CONFIG \
+ .streaming_ctrl = mxl111sf_ep6_streaming_ctrl, \
+ .stream = { \
+ .type = USB_ISOC, \
+ .count = 5, \
+ .endpoint = 0x06, \
+ .u = { \
+ .isoc = { \
+ .framesperurb = 24, \
+ .framesize = 3072, \
+ .interval = 1, \
+ } \
+ } \
+ }
+
+#define MXL111SF_DEFAULT_DEVICE_PROPERTIES \
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER, \
+ .usb_ctrl = DEVICE_SPECIFIC, \
+ /* use usb alt setting 1 for EP4 ISOC transfer (dvb-t), \
+ EP6 BULK transfer (atsc/qam), \
+ use usb alt setting 2 for EP4 BULK transfer (dvb-t), \
+ EP6 ISOC transfer (atsc/qam), \
+ */ \
+ .power_ctrl = mxl111sf_power_ctrl, \
+ .i2c_algo = &mxl111sf_i2c_algo, \
+ .generic_bulk_ctrl_endpoint = MXL_EP2_REG_WRITE, \
+ .generic_bulk_ctrl_endpoint_response = MXL_EP1_REG_READ, \
+ .size_of_priv = sizeof(struct mxl111sf_state)
+
+static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 1,
+ .fe = {{
+ .size_of_priv = sizeof(struct mxl111sf_adap_state),
+
+ .frontend_attach = mxl111sf_lgdt3305_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_BULK_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 6,
+ .devices = {
+ { "Hauppauge 126xxx ATSC (bulk)",
+ { NULL },
+ { &mxl111sf_table[1], &mxl111sf_table[5],
+ NULL },
+ },
+ { "Hauppauge 117xxx ATSC (bulk)",
+ { NULL },
+ { &mxl111sf_table[12],
+ NULL },
+ },
+ { "Hauppauge 126xxx ATSC+ (bulk)",
+ { NULL },
+ { &mxl111sf_table[0], &mxl111sf_table[3],
+ &mxl111sf_table[7], &mxl111sf_table[9],
+ &mxl111sf_table[10], NULL },
+ },
+ { "Hauppauge 117xxx ATSC+ (bulk)",
+ { NULL },
+ { &mxl111sf_table[11], &mxl111sf_table[14],
+ &mxl111sf_table[16], &mxl111sf_table[17],
+ &mxl111sf_table[32], &mxl111sf_table[33],
+ NULL },
+ },
+ { "Hauppauge Mercury (tp-bulk)",
+ { NULL },
+ { &mxl111sf_table[19], &mxl111sf_table[21],
+ &mxl111sf_table[23], &mxl111sf_table[25],
+ &mxl111sf_table[27], NULL },
+ },
+ { "Hauppauge WinTV-Aero-M",
+ { NULL },
+ { &mxl111sf_table[29], &mxl111sf_table[31],
+ NULL },
+ },
+ }
+};
+
+static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 1,
+ .fe = {{
+ .size_of_priv = sizeof(struct mxl111sf_adap_state),
+
+ .frontend_attach = mxl111sf_lgdt3305_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_ISOC_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 6,
+ .devices = {
+ { "Hauppauge 126xxx ATSC (isoc)",
+ { NULL },
+ { &mxl111sf_table[1], &mxl111sf_table[5],
+ NULL },
+ },
+ { "Hauppauge 117xxx ATSC (isoc)",
+ { NULL },
+ { &mxl111sf_table[12],
+ NULL },
+ },
+ { "Hauppauge 126xxx ATSC+ (isoc)",
+ { NULL },
+ { &mxl111sf_table[0], &mxl111sf_table[3],
+ &mxl111sf_table[7], &mxl111sf_table[9],
+ &mxl111sf_table[10], NULL },
+ },
+ { "Hauppauge 117xxx ATSC+ (isoc)",
+ { NULL },
+ { &mxl111sf_table[11], &mxl111sf_table[14],
+ &mxl111sf_table[16], &mxl111sf_table[17],
+ &mxl111sf_table[32], &mxl111sf_table[33],
+ NULL },
+ },
+ { "Hauppauge Mercury (tp-isoc)",
+ { NULL },
+ { &mxl111sf_table[19], &mxl111sf_table[21],
+ &mxl111sf_table[23], &mxl111sf_table[25],
+ &mxl111sf_table[27], NULL },
+ },
+ { "Hauppauge WinTV-Aero-M (tp-isoc)",
+ { NULL },
+ { &mxl111sf_table[29], &mxl111sf_table[31],
+ NULL },
+ },
+ }
+};
+
+static struct usb_driver mxl111sf_driver = {
+ .name = "dvb_usb_mxl111sf",
+ .probe = mxl111sf_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = mxl111sf_table,
+};
+
+static int __init mxl111sf_module_init(void)
+{
+ int result = usb_register(&mxl111sf_driver);
+ if (result) {
+ err("usb_register failed. Error number %d", result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit mxl111sf_module_exit(void)
+{
+ usb_deregister(&mxl111sf_driver);
+}
+
+module_init(mxl111sf_module_init);
+module_exit(mxl111sf_module_exit);
+
+MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.h b/drivers/media/dvb/dvb-usb/mxl111sf.h
new file mode 100644
index 000000000000..5a2c7bb386cd
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/mxl111sf.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+#ifndef _DVB_USB_MXL111SF_H_
+#define _DVB_USB_MXL111SF_H_
+
+#ifdef DVB_USB_LOG_PREFIX
+#undef DVB_USB_LOG_PREFIX
+#endif
+#define DVB_USB_LOG_PREFIX "mxl111sf"
+#include "dvb-usb.h"
+#include <media/tveeprom.h>
+
+#define MXL_EP1_REG_READ 1
+#define MXL_EP2_REG_WRITE 2
+#define MXL_EP3_INTERRUPT 3
+#define MXL_EP4_MPEG2 4
+#define MXL_EP5_I2S 5
+#define MXL_EP6_656 6
+#define MXL_EP6_MPEG2 6
+
+#ifdef USING_ENUM_mxl111sf_current_mode
+enum mxl111sf_current_mode {
+ mxl_mode_dvbt = MXL_EP4_MPEG2,
+ mxl_mode_mh = MXL_EP5_I2S,
+ mxl_mode_atsc = MXL_EP6_MPEG2,
+};
+#endif
+
+enum mxl111sf_gpio_port_expander {
+ mxl111sf_gpio_hw,
+ mxl111sf_PCA9534,
+};
+
+struct mxl111sf_state {
+ struct dvb_usb_device *d;
+
+ enum mxl111sf_gpio_port_expander gpio_port_expander;
+ u8 port_expander_addr;
+
+ u8 chip_id;
+ u8 chip_ver;
+#define MXL111SF_V6 1
+#define MXL111SF_V8_100 2
+#define MXL111SF_V8_200 3
+ u8 chip_rev;
+
+#ifdef USING_ENUM_mxl111sf_current_mode
+ enum mxl111sf_current_mode current_mode;
+#endif
+
+#define MXL_TUNER_MODE 0
+#define MXL_SOC_MODE 1
+#define MXL_DEV_MODE_MASK 0x01
+#if 1
+ int device_mode;
+#endif
+ /* use usb alt setting 1 for EP4 ISOC transfer (dvb-t),
+ EP5 BULK transfer (atsc-mh),
+ EP6 BULK transfer (atsc/qam),
+ use usb alt setting 2 for EP4 BULK transfer (dvb-t),
+ EP5 ISOC transfer (atsc-mh),
+ EP6 ISOC transfer (atsc/qam),
+ */
+ int alt_mode;
+ int gpio_mode;
+ struct tveeprom tv;
+
+ struct mutex fe_lock;
+};
+
+struct mxl111sf_adap_state {
+ int alt_mode;
+ int gpio_mode;
+ int device_mode;
+ int ep6_clockphase;
+ int (*fe_init)(struct dvb_frontend *);
+ int (*fe_sleep)(struct dvb_frontend *);
+};
+
+int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data);
+int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data);
+
+struct mxl111sf_reg_ctrl_info {
+ u8 addr;
+ u8 mask;
+ u8 data;
+};
+
+int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
+ u8 addr, u8 mask, u8 data);
+int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
+ struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
+
+/* needed for hardware i2c functions in mxl111sf-i2c.c:
+ * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */
+int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
+ u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen);
+
+#define mxl_printk(kern, fmt, arg...) \
+ printk(kern "%s: " fmt "\n", __func__, ##arg)
+
+#define mxl_info(fmt, arg...) \
+ mxl_printk(KERN_INFO, fmt, ##arg)
+
+extern int dvb_usb_mxl111sf_debug;
+#define mxl_debug(fmt, arg...) \
+ if (dvb_usb_mxl111sf_debug) \
+ mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+#define MXL_I2C_DBG 0x04
+#define MXL_ADV_DBG 0x10
+#define mxl_debug_adv(fmt, arg...) \
+ if (dvb_usb_mxl111sf_debug & MXL_ADV_DBG) \
+ mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+#define mxl_i2c(fmt, arg...) \
+ if (dvb_usb_mxl111sf_debug & MXL_I2C_DBG) \
+ mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+#define mxl_i2c_adv(fmt, arg...) \
+ if ((dvb_usb_mxl111sf_debug & (MXL_I2C_DBG | MXL_ADV_DBG)) == \
+ (MXL_I2C_DBG | MXL_ADV_DBG)) \
+ mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+/* The following allows the mxl_fail() macro defined below to work
+ * in externel modules, such as mxl111sf-tuner.ko, even though
+ * dvb_usb_mxl111sf_debug is not defined within those modules */
+#ifdef __MXL111SF_TUNER_H__
+#define MXL_ADV_DEBUG_ENABLED MXL_ADV_DBG
+#else
+#define MXL_ADV_DEBUG_ENABLED dvb_usb_mxl111sf_debug
+#endif
+
+#define mxl_fail(ret) \
+({ \
+ int __ret; \
+ __ret = (ret < 0); \
+ if ((__ret) && (MXL_ADV_DEBUG_ENABLED & MXL_ADV_DBG)) \
+ mxl_printk(KERN_ERR, "error %d on line %d", \
+ ret, __LINE__); \
+ __ret; \
+})
+
+#endif /* _DVB_USB_MXL111SF_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index bc350e982b72..21384da6570e 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -166,6 +166,8 @@ static struct dvb_usb_device_properties nova_t_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
@@ -186,7 +188,7 @@ static struct dvb_usb_device_properties nova_t_properties = {
}
}
},
-
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
index 2e4fab7215f5..98fd9a6092b7 100644
--- a/drivers/media/dvb/dvb-usb/opera1.c
+++ b/drivers/media/dvb/dvb-usb/opera1.c
@@ -263,10 +263,10 @@ static struct stv0299_config opera1_stv0299_config = {
static int opera1_frontend_attach(struct dvb_usb_adapter *d)
{
- if ((d->fe =
- dvb_attach(stv0299_attach, &opera1_stv0299_config,
- &d->dev->i2c_adap)) != NULL) {
- d->fe->ops.set_voltage = opera1_set_voltage;
+ d->fe_adap[0].fe = dvb_attach(stv0299_attach, &opera1_stv0299_config,
+ &d->dev->i2c_adap);
+ if ((d->fe_adap[0].fe) != NULL) {
+ d->fe_adap[0].fe->ops.set_voltage = opera1_set_voltage;
return 0;
}
info("not attached stv0299");
@@ -276,7 +276,7 @@ static int opera1_frontend_attach(struct dvb_usb_adapter *d)
static int opera1_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(
- dvb_pll_attach, adap->fe, 0xc0>>1,
+ dvb_pll_attach, adap->fe_adap[0].fe, 0xc0>>1,
&adap->dev->i2c_adap, DVB_PLL_OPERA1
);
return 0;
@@ -516,6 +516,8 @@ static struct dvb_usb_device_properties opera1_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = opera1_frontend_attach,
.streaming_ctrl = opera1_streaming_ctrl,
.tuner_attach = opera1_tuner_attach,
@@ -535,6 +537,7 @@ static struct dvb_usb_device_properties opera1_properties = {
}
}
},
+ }},
}
},
.num_device_descs = 1,
diff --git a/drivers/media/dvb/dvb-usb/pctv452e.c b/drivers/media/dvb/dvb-usb/pctv452e.c
new file mode 100644
index 000000000000..f9aec5cb6e77
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/pctv452e.c
@@ -0,0 +1,1079 @@
+/*
+ * PCTV 452e DVB driver
+ *
+ * Copyright (c) 2006-2008 Dominik Kuhlen <dkuhlen@gmx.net>
+ *
+ * TT connect S2-3650-CI Common Interface support, MAC readout
+ * Copyright (C) 2008 Michael H. Schimek <mschimek@gmx.at>
+ *
+ * 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.
+ */
+
+/* dvb usb framework */
+#define DVB_USB_LOG_PREFIX "pctv452e"
+#include "dvb-usb.h"
+
+/* Demodulator */
+#include "stb0899_drv.h"
+#include "stb0899_reg.h"
+#include "stb0899_cfg.h"
+/* Tuner */
+#include "stb6100.h"
+#include "stb6100_cfg.h"
+/* FE Power */
+#include "lnbp22.h"
+
+#include "dvb_ca_en50221.h"
+#include "ttpci-eeprom.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define ISOC_INTERFACE_ALTERNATIVE 3
+
+#define SYNC_BYTE_OUT 0xaa
+#define SYNC_BYTE_IN 0x55
+
+/* guessed: (copied from ttusb-budget) */
+#define PCTV_CMD_RESET 0x15
+/* command to poll IR receiver */
+#define PCTV_CMD_IR 0x1b
+/* command to send I2C */
+#define PCTV_CMD_I2C 0x31
+
+#define I2C_ADDR_STB0899 (0xd0 >> 1)
+#define I2C_ADDR_STB6100 (0xc0 >> 1)
+#define I2C_ADDR_LNBP22 (0x10 >> 1)
+#define I2C_ADDR_24C16 (0xa0 >> 1)
+#define I2C_ADDR_24C64 (0xa2 >> 1)
+
+
+/* pctv452e sends us this amount of data for each issued usb-command */
+#define PCTV_ANSWER_LEN 64
+/* Wait up to 1000ms for device */
+#define PCTV_TIMEOUT 1000
+
+
+#define PCTV_LED_GPIO STB0899_GPIO01
+#define PCTV_LED_GREEN 0x82
+#define PCTV_LED_ORANGE 0x02
+
+#define ci_dbg(format, arg...) \
+do { \
+ if (0) \
+ printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
+ ": " format "\n" , ## arg); \
+} while (0)
+
+enum {
+ TT3650_CMD_CI_TEST = 0x40,
+ TT3650_CMD_CI_RD_CTRL,
+ TT3650_CMD_CI_WR_CTRL,
+ TT3650_CMD_CI_RD_ATTR,
+ TT3650_CMD_CI_WR_ATTR,
+ TT3650_CMD_CI_RESET,
+ TT3650_CMD_CI_SET_VIDEO_PORT
+};
+
+
+static struct stb0899_postproc pctv45e_postproc[] = {
+ { PCTV_LED_GPIO, STB0899_GPIOPULLUP },
+ { 0, 0 }
+};
+
+/*
+ * stores all private variables for communication with the PCTV452e DVB-S2
+ */
+struct pctv452e_state {
+ struct dvb_ca_en50221 ca;
+ struct mutex ca_mutex;
+
+ u8 c; /* transaction counter, wraps around... */
+ u8 initialized; /* set to 1 if 0x15 has been sent */
+ u16 last_rc_key;
+};
+
+static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
+ unsigned int write_len, unsigned int read_len)
+{
+ struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ u8 buf[64];
+ u8 id;
+ unsigned int rlen;
+ int ret;
+
+ BUG_ON(NULL == data && 0 != (write_len | read_len));
+ BUG_ON(write_len > 64 - 4);
+ BUG_ON(read_len > 64 - 4);
+
+ id = state->c++;
+
+ buf[0] = SYNC_BYTE_OUT;
+ buf[1] = id;
+ buf[2] = cmd;
+ buf[3] = write_len;
+
+ memcpy(buf + 4, data, write_len);
+
+ rlen = (read_len > 0) ? 64 : 0;
+ ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
+ buf, rlen, /* delay_ms */ 0);
+ if (0 != ret)
+ goto failed;
+
+ ret = -EIO;
+ if (SYNC_BYTE_IN != buf[0] || id != buf[1])
+ goto failed;
+
+ memcpy(data, buf + 4, read_len);
+
+ return 0;
+
+failed:
+ err("CI error %d; %02X %02X %02X -> %02X %02X %02X.",
+ ret, SYNC_BYTE_OUT, id, cmd, buf[0], buf[1], buf[2]);
+
+ return ret;
+}
+
+static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca,
+ u8 cmd, u8 *data, unsigned int write_len,
+ unsigned int read_len)
+{
+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ int ret;
+
+ mutex_lock(&state->ca_mutex);
+ ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
+ mutex_unlock(&state->ca_mutex);
+
+ return ret;
+}
+
+static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
+ int slot, int address)
+{
+ u8 buf[3];
+ int ret;
+
+ if (0 != slot)
+ return -EINVAL;
+
+ buf[0] = (address >> 8) & 0x0F;
+ buf[1] = address;
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
+
+ ci_dbg("%s %04x -> %d 0x%02x",
+ __func__, address, ret, buf[2]);
+
+ if (ret < 0)
+ return ret;
+
+ return buf[2];
+}
+
+static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
+ int slot, int address, u8 value)
+{
+ u8 buf[3];
+
+ ci_dbg("%s %d 0x%04x 0x%02x",
+ __func__, slot, address, value);
+
+ if (0 != slot)
+ return -EINVAL;
+
+ buf[0] = (address >> 8) & 0x0F;
+ buf[1] = address;
+ buf[2] = value;
+
+ return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
+}
+
+static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca,
+ int slot,
+ u8 address)
+{
+ u8 buf[2];
+ int ret;
+
+ if (0 != slot)
+ return -EINVAL;
+
+ buf[0] = address & 3;
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
+
+ ci_dbg("%s 0x%02x -> %d 0x%02x",
+ __func__, address, ret, buf[1]);
+
+ if (ret < 0)
+ return ret;
+
+ return buf[1];
+}
+
+static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca,
+ int slot,
+ u8 address,
+ u8 value)
+{
+ u8 buf[2];
+
+ ci_dbg("%s %d 0x%02x 0x%02x",
+ __func__, slot, address, value);
+
+ if (0 != slot)
+ return -EINVAL;
+
+ buf[0] = address;
+ buf[1] = value;
+
+ return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
+}
+
+static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca,
+ int slot,
+ int enable)
+{
+ u8 buf[1];
+ int ret;
+
+ ci_dbg("%s %d %d", __func__, slot, enable);
+
+ if (0 != slot)
+ return -EINVAL;
+
+ enable = !!enable;
+ buf[0] = enable;
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+ if (ret < 0)
+ return ret;
+
+ if (enable != buf[0]) {
+ err("CI not %sabled.", enable ? "en" : "dis");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+ return tt3650_ci_set_video_port(ca, slot, /* enable */ 0);
+}
+
+static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+ return tt3650_ci_set_video_port(ca, slot, /* enable */ 1);
+}
+
+static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ u8 buf[1];
+ int ret;
+
+ ci_dbg("%s %d", __func__, slot);
+
+ if (0 != slot)
+ return -EINVAL;
+
+ buf[0] = 0;
+
+ mutex_lock(&state->ca_mutex);
+
+ ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+ if (0 != ret)
+ goto failed;
+
+ msleep(500);
+
+ buf[0] = 1;
+
+ ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+ if (0 != ret)
+ goto failed;
+
+ msleep(500);
+
+ buf[0] = 0; /* FTA */
+
+ ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+
+ failed:
+ mutex_unlock(&state->ca_mutex);
+
+ return ret;
+}
+
+static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca,
+ int slot,
+ int open)
+{
+ u8 buf[1];
+ int ret;
+
+ if (0 != slot)
+ return -EINVAL;
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
+ if (0 != ret)
+ return ret;
+
+ if (1 == buf[0])
+ return DVB_CA_EN50221_POLL_CAM_PRESENT |
+ DVB_CA_EN50221_POLL_CAM_READY;
+
+ return 0;
+
+}
+
+static void tt3650_ci_uninit(struct dvb_usb_device *d)
+{
+ struct pctv452e_state *state;
+
+ ci_dbg("%s", __func__);
+
+ if (NULL == d)
+ return;
+
+ state = (struct pctv452e_state *)d->priv;
+ if (NULL == state)
+ return;
+
+ if (NULL == state->ca.data)
+ return;
+
+ /* Error ignored. */
+ tt3650_ci_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0);
+
+ dvb_ca_en50221_release(&state->ca);
+
+ memset(&state->ca, 0, sizeof(state->ca));
+}
+
+static int tt3650_ci_init(struct dvb_usb_adapter *a)
+{
+ struct dvb_usb_device *d = a->dev;
+ struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ int ret;
+
+ ci_dbg("%s", __func__);
+
+ mutex_init(&state->ca_mutex);
+
+ state->ca.owner = THIS_MODULE;
+ state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
+ state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
+ state->ca.read_cam_control = tt3650_ci_read_cam_control;
+ state->ca.write_cam_control = tt3650_ci_write_cam_control;
+ state->ca.slot_reset = tt3650_ci_slot_reset;
+ state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
+ state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
+ state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
+ state->ca.data = d;
+
+ ret = dvb_ca_en50221_init(&a->dvb_adap,
+ &state->ca,
+ /* flags */ 0,
+ /* n_slots */ 1);
+ if (0 != ret) {
+ err("Cannot initialize CI: Error %d.", ret);
+ memset(&state->ca, 0, sizeof(state->ca));
+ return ret;
+ }
+
+ info("CI initialized.");
+
+ return 0;
+}
+
+#define CMD_BUFFER_SIZE 0x28
+static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
+ const u8 *snd_buf, u8 snd_len,
+ u8 *rcv_buf, u8 rcv_len)
+{
+ struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ u8 buf[64];
+ u8 id;
+ int ret;
+
+ id = state->c++;
+
+ ret = -EINVAL;
+ if (snd_len > 64 - 7 || rcv_len > 64 - 7)
+ goto failed;
+
+ buf[0] = SYNC_BYTE_OUT;
+ buf[1] = id;
+ buf[2] = PCTV_CMD_I2C;
+ buf[3] = snd_len + 3;
+ buf[4] = addr << 1;
+ buf[5] = snd_len;
+ buf[6] = rcv_len;
+
+ memcpy(buf + 7, snd_buf, snd_len);
+
+ ret = dvb_usb_generic_rw(d, buf, 7 + snd_len,
+ buf, /* rcv_len */ 64,
+ /* delay_ms */ 0);
+ if (ret < 0)
+ goto failed;
+
+ /* TT USB protocol error. */
+ ret = -EIO;
+ if (SYNC_BYTE_IN != buf[0] || id != buf[1])
+ goto failed;
+
+ /* I2C device didn't respond as expected. */
+ ret = -EREMOTEIO;
+ if (buf[5] < snd_len || buf[6] < rcv_len)
+ goto failed;
+
+ memcpy(rcv_buf, buf + 7, rcv_len);
+
+ return rcv_len;
+
+failed:
+ err("I2C error %d; %02X %02X %02X %02X %02X -> "
+ "%02X %02X %02X %02X %02X.",
+ ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
+ buf[0], buf[1], buf[4], buf[5], buf[6]);
+
+ return ret;
+}
+
+static int pctv452e_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg,
+ int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adapter);
+ int i;
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ for (i = 0; i < num; i++) {
+ u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf;
+ int ret;
+
+ if (msg[i].flags & I2C_M_RD) {
+ addr = msg[i].addr;
+ snd_buf = NULL;
+ snd_len = 0;
+ rcv_buf = msg[i].buf;
+ rcv_len = msg[i].len;
+ } else {
+ addr = msg[i].addr;
+ snd_buf = msg[i].buf;
+ snd_len = msg[i].len;
+ rcv_buf = NULL;
+ rcv_len = 0;
+ }
+
+ ret = pctv452e_i2c_msg(d, addr, snd_buf, snd_len, rcv_buf,
+ rcv_len);
+ if (ret < rcv_len)
+ break;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ return i;
+}
+
+static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
+{
+ struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ u8 b0[] = { 0xaa, 0, PCTV_CMD_RESET, 1, 0 };
+ u8 rx[PCTV_ANSWER_LEN];
+ int ret;
+
+ info("%s: %d\n", __func__, i);
+
+ if (!i)
+ return 0;
+
+ if (state->initialized)
+ return 0;
+
+ /* hmm where shoud this should go? */
+ ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
+ if (ret != 0)
+ info("%s: Warning set interface returned: %d\n",
+ __func__, ret);
+
+ /* this is a one-time initialization, dont know where to put */
+ b0[1] = state->c++;
+ /* reset board */
+ ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0);
+ if (ret)
+ return ret;
+
+ b0[1] = state->c++;
+ b0[4] = 1;
+ /* reset board (again?) */
+ ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0);
+ if (ret)
+ return ret;
+
+ state->initialized = 1;
+
+ return 0;
+}
+
+static int pctv452e_rc_query(struct dvb_usb_device *d)
+{
+ struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+ u8 b[CMD_BUFFER_SIZE];
+ u8 rx[PCTV_ANSWER_LEN];
+ int ret, i;
+ u8 id = state->c++;
+
+ /* prepare command header */
+ b[0] = SYNC_BYTE_OUT;
+ b[1] = id;
+ b[2] = PCTV_CMD_IR;
+ b[3] = 0;
+
+ /* send ir request */
+ ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0);
+ if (ret != 0)
+ return ret;
+
+ if (debug > 3) {
+ info("%s: read: %2d: %02x %02x %02x: ", __func__,
+ ret, rx[0], rx[1], rx[2]);
+ for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
+ info(" %02x", rx[i+3]);
+
+ info("\n");
+ }
+
+ if ((rx[3] == 9) && (rx[12] & 0x01)) {
+ /* got a "press" event */
+ state->last_rc_key = (rx[7] << 8) | rx[6];
+ if (debug > 2)
+ info("%s: cmd=0x%02x sys=0x%02x\n",
+ __func__, rx[6], rx[7]);
+
+ rc_keydown(d->rc_dev, state->last_rc_key, 0);
+ } else if (state->last_rc_key) {
+ rc_keyup(d->rc_dev);
+ state->last_rc_key = 0;
+ }
+
+ return 0;
+}
+
+static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+{
+ const u8 mem_addr[] = { 0x1f, 0xcc };
+ u8 encoded_mac[20];
+ int ret;
+
+ ret = -EAGAIN;
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ goto failed;
+
+ ret = pctv452e_i2c_msg(d, I2C_ADDR_24C16,
+ mem_addr + 1, /* snd_len */ 1,
+ encoded_mac, /* rcv_len */ 20);
+ if (-EREMOTEIO == ret)
+ /* Caution! A 24C16 interprets 0xA2 0x1F 0xCC as a
+ byte write if /WC is low. */
+ ret = pctv452e_i2c_msg(d, I2C_ADDR_24C64,
+ mem_addr, 2,
+ encoded_mac, 20);
+
+ mutex_unlock(&d->i2c_mutex);
+
+ if (20 != ret)
+ goto failed;
+
+ ret = ttpci_eeprom_decode_mac(mac, encoded_mac);
+ if (0 != ret)
+ goto failed;
+
+ return 0;
+
+failed:
+ memset(mac, 0, 6);
+
+ return ret;
+}
+
+static const struct stb0899_s1_reg pctv452e_init_dev[] = {
+ { STB0899_DISCNTRL1, 0x26 },
+ { STB0899_DISCNTRL2, 0x80 },
+ { STB0899_DISRX_ST0, 0x04 },
+ { STB0899_DISRX_ST1, 0x20 },
+ { STB0899_DISPARITY, 0x00 },
+ { STB0899_DISFIFO, 0x00 },
+ { STB0899_DISF22, 0x99 },
+ { STB0899_DISF22RX, 0x85 }, /* 0xa8 */
+ { STB0899_ACRPRESC, 0x11 },
+ { STB0899_ACRDIV1, 0x0a },
+ { STB0899_ACRDIV2, 0x05 },
+ { STB0899_DACR1 , 0x00 },
+ { STB0899_DACR2 , 0x00 },
+ { STB0899_OUTCFG, 0x00 },
+ { STB0899_MODECFG, 0x00 }, /* Inversion */
+ { STB0899_IRQMSK_3, 0xf3 },
+ { STB0899_IRQMSK_2, 0xfc },
+ { STB0899_IRQMSK_1, 0xff },
+ { STB0899_IRQMSK_0, 0xff },
+ { STB0899_I2CCFG, 0x88 },
+ { STB0899_I2CRPT, 0x58 },
+ { STB0899_GPIO00CFG, 0x82 },
+ { STB0899_GPIO01CFG, 0x82 }, /* LED: 0x02 green, 0x82 orange */
+ { STB0899_GPIO02CFG, 0x82 },
+ { STB0899_GPIO03CFG, 0x82 },
+ { STB0899_GPIO04CFG, 0x82 },
+ { STB0899_GPIO05CFG, 0x82 },
+ { STB0899_GPIO06CFG, 0x82 },
+ { STB0899_GPIO07CFG, 0x82 },
+ { STB0899_GPIO08CFG, 0x82 },
+ { STB0899_GPIO09CFG, 0x82 },
+ { STB0899_GPIO10CFG, 0x82 },
+ { STB0899_GPIO11CFG, 0x82 },
+ { STB0899_GPIO12CFG, 0x82 },
+ { STB0899_GPIO13CFG, 0x82 },
+ { STB0899_GPIO14CFG, 0x82 },
+ { STB0899_GPIO15CFG, 0x82 },
+ { STB0899_GPIO16CFG, 0x82 },
+ { STB0899_GPIO17CFG, 0x82 },
+ { STB0899_GPIO18CFG, 0x82 },
+ { STB0899_GPIO19CFG, 0x82 },
+ { STB0899_GPIO20CFG, 0x82 },
+ { STB0899_SDATCFG, 0xb8 },
+ { STB0899_SCLTCFG, 0xba },
+ { STB0899_AGCRFCFG, 0x1c }, /* 0x11 DVB-S; 0x1c DVB-S2 (1c, rjkm) */
+ { STB0899_GPIO22, 0x82 },
+ { STB0899_GPIO21, 0x91 },
+ { STB0899_DIRCLKCFG, 0x82 },
+ { STB0899_CLKOUT27CFG, 0x7e },
+ { STB0899_STDBYCFG, 0x82 },
+ { STB0899_CS0CFG, 0x82 },
+ { STB0899_CS1CFG, 0x82 },
+ { STB0899_DISEQCOCFG, 0x20 },
+ { STB0899_NCOARSE, 0x15 }, /* 0x15 27Mhz, F/3 198MHz, F/6 108MHz */
+ { STB0899_SYNTCTRL, 0x00 }, /* 0x00 CLKI, 0x02 XTALI */
+ { STB0899_FILTCTRL, 0x00 },
+ { STB0899_SYSCTRL, 0x00 },
+ { STB0899_STOPCLK1, 0x20 }, /* orig: 0x00 budget-ci: 0x20 */
+ { STB0899_STOPCLK2, 0x00 },
+ { STB0899_INTBUFCTRL, 0x0a },
+ { STB0899_AGC2I1, 0x00 },
+ { STB0899_AGC2I2, 0x00 },
+ { STB0899_AGCIQIN, 0x00 },
+ { STB0899_TSTRES, 0x40 }, /* rjkm */
+ { 0xffff, 0xff },
+};
+
+static const struct stb0899_s1_reg pctv452e_init_s1_demod[] = {
+ { STB0899_DEMOD, 0x00 },
+ { STB0899_RCOMPC, 0xc9 },
+ { STB0899_AGC1CN, 0x01 },
+ { STB0899_AGC1REF, 0x10 },
+ { STB0899_RTC, 0x23 },
+ { STB0899_TMGCFG, 0x4e },
+ { STB0899_AGC2REF, 0x34 },
+ { STB0899_TLSR, 0x84 },
+ { STB0899_CFD, 0xf7 },
+ { STB0899_ACLC, 0x87 },
+ { STB0899_BCLC, 0x94 },
+ { STB0899_EQON, 0x41 },
+ { STB0899_LDT, 0xf1 },
+ { STB0899_LDT2, 0xe3 },
+ { STB0899_EQUALREF, 0xb4 },
+ { STB0899_TMGRAMP, 0x10 },
+ { STB0899_TMGTHD, 0x30 },
+ { STB0899_IDCCOMP, 0xfd },
+ { STB0899_QDCCOMP, 0xff },
+ { STB0899_POWERI, 0x0c },
+ { STB0899_POWERQ, 0x0f },
+ { STB0899_RCOMP, 0x6c },
+ { STB0899_AGCIQIN, 0x80 },
+ { STB0899_AGC2I1, 0x06 },
+ { STB0899_AGC2I2, 0x00 },
+ { STB0899_TLIR, 0x30 },
+ { STB0899_RTF, 0x7f },
+ { STB0899_DSTATUS, 0x00 },
+ { STB0899_LDI, 0xbc },
+ { STB0899_CFRM, 0xea },
+ { STB0899_CFRL, 0x31 },
+ { STB0899_NIRM, 0x2b },
+ { STB0899_NIRL, 0x80 },
+ { STB0899_ISYMB, 0x1d },
+ { STB0899_QSYMB, 0xa6 },
+ { STB0899_SFRH, 0x2f },
+ { STB0899_SFRM, 0x68 },
+ { STB0899_SFRL, 0x40 },
+ { STB0899_SFRUPH, 0x2f },
+ { STB0899_SFRUPM, 0x68 },
+ { STB0899_SFRUPL, 0x40 },
+ { STB0899_EQUAI1, 0x02 },
+ { STB0899_EQUAQ1, 0xff },
+ { STB0899_EQUAI2, 0x04 },
+ { STB0899_EQUAQ2, 0x05 },
+ { STB0899_EQUAI3, 0x02 },
+ { STB0899_EQUAQ3, 0xfd },
+ { STB0899_EQUAI4, 0x03 },
+ { STB0899_EQUAQ4, 0x07 },
+ { STB0899_EQUAI5, 0x08 },
+ { STB0899_EQUAQ5, 0xf5 },
+ { STB0899_DSTATUS2, 0x00 },
+ { STB0899_VSTATUS, 0x00 },
+ { STB0899_VERROR, 0x86 },
+ { STB0899_IQSWAP, 0x2a },
+ { STB0899_ECNT1M, 0x00 },
+ { STB0899_ECNT1L, 0x00 },
+ { STB0899_ECNT2M, 0x00 },
+ { STB0899_ECNT2L, 0x00 },
+ { STB0899_ECNT3M, 0x0a },
+ { STB0899_ECNT3L, 0xad },
+ { STB0899_FECAUTO1, 0x06 },
+ { STB0899_FECM, 0x01 },
+ { STB0899_VTH12, 0xb0 },
+ { STB0899_VTH23, 0x7a },
+ { STB0899_VTH34, 0x58 },
+ { STB0899_VTH56, 0x38 },
+ { STB0899_VTH67, 0x34 },
+ { STB0899_VTH78, 0x24 },
+ { STB0899_PRVIT, 0xff },
+ { STB0899_VITSYNC, 0x19 },
+ { STB0899_RSULC, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+ { STB0899_TSULC, 0x42 },
+ { STB0899_RSLLC, 0x41 },
+ { STB0899_TSLPL, 0x12 },
+ { STB0899_TSCFGH, 0x0c },
+ { STB0899_TSCFGM, 0x00 },
+ { STB0899_TSCFGL, 0x00 },
+ { STB0899_TSOUT, 0x69 }, /* 0x0d for CAM */
+ { STB0899_RSSYNCDEL, 0x00 },
+ { STB0899_TSINHDELH, 0x02 },
+ { STB0899_TSINHDELM, 0x00 },
+ { STB0899_TSINHDELL, 0x00 },
+ { STB0899_TSLLSTKM, 0x1b },
+ { STB0899_TSLLSTKL, 0xb3 },
+ { STB0899_TSULSTKM, 0x00 },
+ { STB0899_TSULSTKL, 0x00 },
+ { STB0899_PCKLENUL, 0xbc },
+ { STB0899_PCKLENLL, 0xcc },
+ { STB0899_RSPCKLEN, 0xbd },
+ { STB0899_TSSTATUS, 0x90 },
+ { STB0899_ERRCTRL1, 0xb6 },
+ { STB0899_ERRCTRL2, 0x95 },
+ { STB0899_ERRCTRL3, 0x8d },
+ { STB0899_DMONMSK1, 0x27 },
+ { STB0899_DMONMSK0, 0x03 },
+ { STB0899_DEMAPVIT, 0x5c },
+ { STB0899_PLPARM, 0x19 },
+ { STB0899_PDELCTRL, 0x48 },
+ { STB0899_PDELCTRL2, 0x00 },
+ { STB0899_BBHCTRL1, 0x00 },
+ { STB0899_BBHCTRL2, 0x00 },
+ { STB0899_HYSTTHRESH, 0x77 },
+ { STB0899_MATCSTM, 0x00 },
+ { STB0899_MATCSTL, 0x00 },
+ { STB0899_UPLCSTM, 0x00 },
+ { STB0899_UPLCSTL, 0x00 },
+ { STB0899_DFLCSTM, 0x00 },
+ { STB0899_DFLCSTL, 0x00 },
+ { STB0899_SYNCCST, 0x00 },
+ { STB0899_SYNCDCSTM, 0x00 },
+ { STB0899_SYNCDCSTL, 0x00 },
+ { STB0899_ISI_ENTRY, 0x00 },
+ { STB0899_ISI_BIT_EN, 0x00 },
+ { STB0899_MATSTRM, 0xf0 },
+ { STB0899_MATSTRL, 0x02 },
+ { STB0899_UPLSTRM, 0x45 },
+ { STB0899_UPLSTRL, 0x60 },
+ { STB0899_DFLSTRM, 0xe3 },
+ { STB0899_DFLSTRL, 0x00 },
+ { STB0899_SYNCSTR, 0x47 },
+ { STB0899_SYNCDSTRM, 0x05 },
+ { STB0899_SYNCDSTRL, 0x18 },
+ { STB0899_CFGPDELSTATUS1, 0x19 },
+ { STB0899_CFGPDELSTATUS2, 0x2b },
+ { STB0899_BBFERRORM, 0x00 },
+ { STB0899_BBFERRORL, 0x01 },
+ { STB0899_UPKTERRORM, 0x00 },
+ { STB0899_UPKTERRORL, 0x00 },
+ { 0xffff, 0xff },
+};
+
+static struct stb0899_config stb0899_config = {
+ .init_dev = pctv452e_init_dev,
+ .init_s2_demod = stb0899_s2_init_2,
+ .init_s1_demod = pctv452e_init_s1_demod,
+ .init_s2_fec = stb0899_s2_init_4,
+ .init_tst = stb0899_s1_init_5,
+
+ .demod_address = I2C_ADDR_STB0899, /* I2C Address */
+ .block_sync_mode = STB0899_SYNC_FORCED, /* ? */
+
+ .xtal_freq = 27000000, /* Assume Hz ? */
+ .inversion = IQ_SWAP_ON, /* ? */
+
+ .lo_clk = 76500000,
+ .hi_clk = 99000000,
+
+ .ts_output_mode = 0, /* Use parallel mode */
+ .clock_polarity = 0,
+ .data_clk_parity = 0,
+ .fec_mode = 0,
+
+ .esno_ave = STB0899_DVBS2_ESNO_AVE,
+ .esno_quant = STB0899_DVBS2_ESNO_QUANT,
+ .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
+ .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
+ .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
+ .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
+ .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
+ .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
+ .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
+
+ .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
+ .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+ .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
+ .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
+
+ .tuner_get_frequency = stb6100_get_frequency,
+ .tuner_set_frequency = stb6100_set_frequency,
+ .tuner_set_bandwidth = stb6100_set_bandwidth,
+ .tuner_get_bandwidth = stb6100_get_bandwidth,
+ .tuner_set_rfsiggain = NULL,
+
+ /* helper for switching LED green/orange */
+ .postproc = pctv45e_postproc
+};
+
+static struct stb6100_config stb6100_config = {
+ .tuner_address = I2C_ADDR_STB6100,
+ .refclock = 27000000
+};
+
+
+static struct i2c_algorithm pctv452e_i2c_algo = {
+ .master_xfer = pctv452e_i2c_xfer,
+ .functionality = pctv452e_i2c_func
+};
+
+static int pctv452e_frontend_attach(struct dvb_usb_adapter *a)
+{
+ struct usb_device_id *id;
+
+ a->fe_adap[0].fe = dvb_attach(stb0899_attach, &stb0899_config,
+ &a->dev->i2c_adap);
+ if (!a->fe_adap[0].fe)
+ return -ENODEV;
+ if ((dvb_attach(lnbp22_attach, a->fe_adap[0].fe,
+ &a->dev->i2c_adap)) == 0)
+ err("Cannot attach lnbp22\n");
+
+ id = a->dev->desc->warm_ids[0];
+ if (USB_VID_TECHNOTREND == id->idVendor
+ && USB_PID_TECHNOTREND_CONNECT_S2_3650_CI == id->idProduct)
+ /* Error ignored. */
+ tt3650_ci_init(a);
+
+ return 0;
+}
+
+static int pctv452e_tuner_attach(struct dvb_usb_adapter *a)
+{
+ if (!a->fe_adap[0].fe)
+ return -ENODEV;
+ if (dvb_attach(stb6100_attach, a->fe_adap[0].fe, &stb6100_config,
+ &a->dev->i2c_adap) == 0) {
+ err("%s failed\n", __func__);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static struct usb_device_id pctv452e_usb_table[] = {
+ {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_452E)},
+ {USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_S2_3600)},
+ {USB_DEVICE(USB_VID_TECHNOTREND,
+ USB_PID_TECHNOTREND_CONNECT_S2_3650_CI)},
+ {}
+};
+MODULE_DEVICE_TABLE(usb, pctv452e_usb_table);
+
+static struct dvb_usb_device_properties pctv452e_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */
+ .usb_ctrl = DEVICE_SPECIFIC,
+
+ .size_of_priv = sizeof(struct pctv452e_state),
+
+ .power_ctrl = pctv452e_power_ctrl,
+
+ .rc.core = {
+ .rc_codes = RC_MAP_DIB0700_RC5_TABLE,
+ .allowed_protos = RC_TYPE_UNKNOWN,
+ .rc_query = pctv452e_rc_query,
+ .rc_interval = 100,
+ },
+
+ .num_adapters = 1,
+ .adapter = {{
+ .num_frontends = 1,
+ .fe = {{
+ .frontend_attach = pctv452e_frontend_attach,
+ .tuner_attach = pctv452e_tuner_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_ISOC,
+ .count = 4,
+ .endpoint = 0x02,
+ .u = {
+ .isoc = {
+ .framesperurb = 4,
+ .framesize = 940,
+ .interval = 1
+ }
+ }
+ },
+ } },
+ } },
+
+ .i2c_algo = &pctv452e_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 1, /* allow generice rw function */
+
+ .num_device_descs = 1,
+ .devices = {
+ { .name = "PCTV HDTV USB",
+ .cold_ids = { NULL, NULL }, /* this is a warm only device */
+ .warm_ids = { &pctv452e_usb_table[0], NULL }
+ },
+ { 0 },
+ }
+};
+
+static struct dvb_usb_device_properties tt_connect_s2_3600_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */
+ .usb_ctrl = DEVICE_SPECIFIC,
+
+ .size_of_priv = sizeof(struct pctv452e_state),
+
+ .power_ctrl = pctv452e_power_ctrl,
+ .read_mac_address = pctv452e_read_mac_address,
+
+ .rc.core = {
+ .rc_codes = RC_MAP_TT_1500,
+ .allowed_protos = RC_TYPE_UNKNOWN,
+ .rc_query = pctv452e_rc_query,
+ .rc_interval = 100,
+ },
+
+ .num_adapters = 1,
+ .adapter = {{
+ .num_frontends = 1,
+ .fe = {{
+ .frontend_attach = pctv452e_frontend_attach,
+ .tuner_attach = pctv452e_tuner_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_ISOC,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .isoc = {
+ .framesperurb = 4,
+ .framesize = 940,
+ .interval = 1
+ }
+ }
+ },
+
+ } },
+ } },
+
+ .i2c_algo = &pctv452e_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 1, /* allow generic rw function*/
+
+ .num_device_descs = 2,
+ .devices = {
+ { .name = "Technotrend TT Connect S2-3600",
+ .cold_ids = { NULL, NULL }, /* this is a warm only device */
+ .warm_ids = { &pctv452e_usb_table[1], NULL }
+ },
+ { .name = "Technotrend TT Connect S2-3650-CI",
+ .cold_ids = { NULL, NULL },
+ .warm_ids = { &pctv452e_usb_table[2], NULL }
+ },
+ { 0 },
+ }
+};
+
+static void pctv452e_usb_disconnect(struct usb_interface *intf)
+{
+ struct dvb_usb_device *d = usb_get_intfdata(intf);
+
+ tt3650_ci_uninit(d);
+ dvb_usb_device_exit(intf);
+}
+
+static int pctv452e_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ if (0 == dvb_usb_device_init(intf, &pctv452e_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &tt_connect_s2_3600_properties,
+ THIS_MODULE, NULL, adapter_nr))
+ return 0;
+
+ return -ENODEV;
+}
+
+static struct usb_driver pctv452e_usb_driver = {
+ .name = "pctv452e",
+ .probe = pctv452e_usb_probe,
+ .disconnect = pctv452e_usb_disconnect,
+ .id_table = pctv452e_usb_table,
+};
+
+static int __init pctv452e_usb_init(void)
+{
+ int ret = usb_register(&pctv452e_usb_driver);
+ if (ret)
+ err("%s: usb_register failed! Error %d", __FILE__, ret);
+
+ return ret;
+}
+
+static void __exit pctv452e_usb_exit(void)
+{
+ usb_deregister(&pctv452e_usb_driver);
+}
+
+module_init(pctv452e_usb_init);
+module_exit(pctv452e_usb_exit);
+
+MODULE_AUTHOR("Dominik Kuhlen <dkuhlen@gmx.net>");
+MODULE_AUTHOR("Andre Weidemann <Andre.Weidemann@web.de>");
+MODULE_AUTHOR("Michael H. Schimek <mschimek@gmx.at>");
+MODULE_DESCRIPTION("Pinnacle PCTV HDTV USB DVB / TT connect S2-3600 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/technisat-usb2.c b/drivers/media/dvb/dvb-usb/technisat-usb2.c
index 473b95ed4d52..0998fe961950 100644
--- a/drivers/media/dvb/dvb-usb/technisat-usb2.c
+++ b/drivers/media/dvb/dvb-usb/technisat-usb2.c
@@ -292,7 +292,7 @@ static void technisat_usb2_green_led_control(struct work_struct *work)
{
struct technisat_usb2_state *state =
container_of(work, struct technisat_usb2_state, green_led_work.work);
- struct dvb_frontend *fe = state->dev->adapter[0].fe;
+ struct dvb_frontend *fe = state->dev->adapter[0].fe_adap[0].fe;
if (state->power_state == 0)
goto schedule;
@@ -505,14 +505,14 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
struct usb_device *udev = a->dev->udev;
int ret;
- a->fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
+ a->fe_adap[0].fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
&a->dev->i2c_adap, STV090x_DEMODULATOR_0);
- if (a->fe) {
+ if (a->fe_adap[0].fe) {
struct stv6110x_devctl *ctl;
ctl = dvb_attach(stv6110x_attach,
- a->fe,
+ a->fe_adap[0].fe,
&technisat_usb2_stv6110x_config,
&a->dev->i2c_adap);
@@ -532,8 +532,8 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
/* call the init function once to initialize
tuner's clock output divider and demod's
master clock */
- if (a->fe->ops.init)
- a->fe->ops.init(a->fe);
+ if (a->fe_adap[0].fe->ops.init)
+ a->fe_adap[0].fe->ops.init(a->fe_adap[0].fe);
if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0)
return -EAGAIN;
@@ -548,20 +548,20 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
if (ret != 0)
err("could not set IF_CLK to external");
- a->fe->ops.set_voltage = technisat_usb2_set_voltage;
+ a->fe_adap[0].fe->ops.set_voltage = technisat_usb2_set_voltage;
/* if everything was successful assign a nice name to the frontend */
- strlcpy(a->fe->ops.info.name, a->dev->desc->name,
- sizeof(a->fe->ops.info.name));
+ strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name,
+ sizeof(a->fe_adap[0].fe->ops.info.name));
} else {
- dvb_frontend_detach(a->fe);
- a->fe = NULL;
+ dvb_frontend_detach(a->fe_adap[0].fe);
+ a->fe_adap[0].fe = NULL;
}
}
technisat_usb2_set_led_timer(a->dev, 1, 1);
- return a->fe == NULL ? -ENODEV : 0;
+ return a->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
/* Remote control */
@@ -697,6 +697,8 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = technisat_usb2_frontend_attach,
.stream = {
@@ -711,7 +713,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
}
}
},
-
+ }},
.size_of_priv = 0,
},
},
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
index 0d4709ff9cbb..ea4eab8b3965 100644
--- a/drivers/media/dvb/dvb-usb/ttusb2.c
+++ b/drivers/media/dvb/dvb-usb/ttusb2.c
@@ -30,18 +30,43 @@
#include "tda826x.h"
#include "tda10086.h"
#include "tda1002x.h"
+#include "tda10048.h"
#include "tda827x.h"
#include "lnbp21.h"
+/* CA */
+#include "dvb_ca_en50221.h"
/* debug */
static int dvb_usb_ttusb2_debug;
#define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args)
module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
+static int dvb_usb_ttusb2_debug_ci;
+module_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644);
+MODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+#define ci_dbg(format, arg...) \
+do { \
+ if (dvb_usb_ttusb2_debug_ci) \
+ printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
+ ": %s " format "\n" , __func__, ## arg); \
+} while (0)
+
+enum {
+ TT3650_CMD_CI_TEST = 0x40,
+ TT3650_CMD_CI_RD_CTRL,
+ TT3650_CMD_CI_WR_CTRL,
+ TT3650_CMD_CI_RD_ATTR,
+ TT3650_CMD_CI_WR_ATTR,
+ TT3650_CMD_CI_RESET,
+ TT3650_CMD_CI_SET_VIDEO_PORT
+};
+
struct ttusb2_state {
+ struct dvb_ca_en50221 ca;
+ struct mutex ca_mutex;
u8 id;
u16 last_rc_key;
};
@@ -78,11 +103,260 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
return 0;
}
+/* ci */
+static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
+{
+ int ret;
+ u8 rx[60];/* (64 -4) */
+ ret = ttusb2_msg(d, cmd, data, write_len, rx, read_len);
+ if (!ret)
+ memcpy(data, rx, read_len);
+ return ret;
+}
+
+static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
+{
+ struct dvb_usb_device *d = ca->data;
+ struct ttusb2_state *state = d->priv;
+ int ret;
+
+ mutex_lock(&state->ca_mutex);
+ ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
+ mutex_unlock(&state->ca_mutex);
+
+ return ret;
+}
+
+static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
+{
+ u8 buf[3];
+ int ret = 0;
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = (address >> 8) & 0x0F;
+ buf[1] = address;
+
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
+
+ ci_dbg("%04x -> %d 0x%02x", address, ret, buf[2]);
+
+ if (ret < 0)
+ return ret;
+
+ return buf[2];
+}
+
+static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
+{
+ u8 buf[3];
+
+ ci_dbg("%d 0x%04x 0x%02x", slot, address, value);
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = (address >> 8) & 0x0F;
+ buf[1] = address;
+ buf[2] = value;
+
+ return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
+}
+
+static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
+{
+ u8 buf[2];
+ int ret;
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = address & 3;
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
+
+ ci_dbg("0x%02x -> %d 0x%02x", address, ret, buf[1]);
+
+ if (ret < 0)
+ return ret;
+
+ return buf[1];
+}
+
+static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
+{
+ u8 buf[2];
+
+ ci_dbg("%d 0x%02x 0x%02x", slot, address, value);
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = address;
+ buf[1] = value;
+
+ return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
+}
+
+static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, int slot, int enable)
+{
+ u8 buf[1];
+ int ret;
+
+ ci_dbg("%d %d", slot, enable);
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = enable;
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+ if (ret < 0)
+ return ret;
+
+ if (enable != buf[0]) {
+ err("CI not %sabled.", enable ? "en" : "dis");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+ return tt3650_ci_set_video_port(ca, slot, 0);
+}
+
+static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+ return tt3650_ci_set_video_port(ca, slot, 1);
+}
+
+static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+ struct dvb_usb_device *d = ca->data;
+ struct ttusb2_state *state = d->priv;
+ u8 buf[1];
+ int ret;
+
+ ci_dbg("%d", slot);
+
+ if (slot)
+ return -EINVAL;
+
+ buf[0] = 0;
+
+ mutex_lock(&state->ca_mutex);
+
+ ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+ if (ret)
+ goto failed;
+
+ msleep(500);
+
+ buf[0] = 1;
+
+ ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+ if (ret)
+ goto failed;
+
+ msleep(500);
+
+ buf[0] = 0; /* FTA */
+
+ ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+
+ msleep(1100);
+
+ failed:
+ mutex_unlock(&state->ca_mutex);
+
+ return ret;
+}
+
+static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
+{
+ u8 buf[1];
+ int ret;
+
+ if (slot)
+ return -EINVAL;
+
+ ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
+ if (ret)
+ return ret;
+
+ if (1 == buf[0]) {
+ return DVB_CA_EN50221_POLL_CAM_PRESENT |
+ DVB_CA_EN50221_POLL_CAM_READY;
+ }
+ return 0;
+}
+
+static void tt3650_ci_uninit(struct dvb_usb_device *d)
+{
+ struct ttusb2_state *state;
+
+ ci_dbg("");
+
+ if (NULL == d)
+ return;
+
+ state = d->priv;
+ if (NULL == state)
+ return;
+
+ if (NULL == state->ca.data)
+ return;
+
+ dvb_ca_en50221_release(&state->ca);
+
+ memset(&state->ca, 0, sizeof(state->ca));
+}
+
+static int tt3650_ci_init(struct dvb_usb_adapter *a)
+{
+ struct dvb_usb_device *d = a->dev;
+ struct ttusb2_state *state = d->priv;
+ int ret;
+
+ ci_dbg("");
+
+ mutex_init(&state->ca_mutex);
+
+ state->ca.owner = THIS_MODULE;
+ state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
+ state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
+ state->ca.read_cam_control = tt3650_ci_read_cam_control;
+ state->ca.write_cam_control = tt3650_ci_write_cam_control;
+ state->ca.slot_reset = tt3650_ci_slot_reset;
+ state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
+ state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
+ state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
+ state->ca.data = d;
+
+ ret = dvb_ca_en50221_init(&a->dvb_adap,
+ &state->ca,
+ /* flags */ 0,
+ /* n_slots */ 1);
+ if (ret) {
+ err("Cannot initialize CI: Error %d.", ret);
+ memset(&state->ca, 0, sizeof(state->ca));
+ return ret;
+ }
+
+ info("CI initialized.");
+
+ return 0;
+}
+
static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
static u8 obuf[60], ibuf[60];
- int i,read;
+ int i, write_read, read;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
@@ -91,28 +365,35 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
warn("more than 2 i2c messages at a time is not handled yet. TODO.");
for (i = 0; i < num; i++) {
- read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+ write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+ read = msg[i].flags & I2C_M_RD;
- obuf[0] = (msg[i].addr << 1) | read;
- obuf[1] = msg[i].len;
+ obuf[0] = (msg[i].addr << 1) | (write_read | read);
+ if (read)
+ obuf[1] = 0;
+ else
+ obuf[1] = msg[i].len;
/* read request */
- if (read)
+ if (write_read)
obuf[2] = msg[i+1].len;
+ else if (read)
+ obuf[2] = msg[i].len;
else
obuf[2] = 0;
- memcpy(&obuf[3],msg[i].buf,msg[i].len);
+ memcpy(&obuf[3], msg[i].buf, msg[i].len);
if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
err("i2c transfer failed.");
break;
}
- if (read) {
- memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len);
+ if (write_read) {
+ memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len);
i++;
- }
+ } else if (read)
+ memcpy(msg[i].buf, &ibuf[3], msg[i].len);
}
mutex_unlock(&d->i2c_mutex);
@@ -190,12 +471,31 @@ static struct tda10023_config tda10023_config = {
.deltaf = 0xa511,
};
+static struct tda10048_config tda10048_config = {
+ .demod_address = 0x10 >> 1,
+ .output_mode = TDA10048_PARALLEL_OUTPUT,
+ .inversion = TDA10048_INVERSION_ON,
+ .dtv6_if_freq_khz = TDA10048_IF_4000,
+ .dtv7_if_freq_khz = TDA10048_IF_4500,
+ .dtv8_if_freq_khz = TDA10048_IF_5000,
+ .clk_freq_khz = TDA10048_CLK_16000,
+ .no_firmware = 1,
+ .set_pll = true ,
+ .pll_m = 5,
+ .pll_n = 3,
+ .pll_p = 0,
+};
+
+static struct tda827x_config tda827x_config = {
+ .config = 0,
+};
+
static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
{
if (usb_set_interface(adap->dev->udev,0,3) < 0)
err("set interface to alts=3 failed");
- if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
+ if ((adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
deb_info("TDA10086 attach failed\n");
return -ENODEV;
}
@@ -203,20 +503,57 @@ static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int ttusb2_ct3650_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+
+ return adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, enable);
+}
+
static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
{
if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
err("set interface to alts=3 failed");
- if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) {
- deb_info("TDA10023 attach failed\n");
- return -ENODEV;
+
+ if (adap->fe_adap[0].fe == NULL) {
+ /* FE 0 DVB-C */
+ adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
+ &tda10023_config, &adap->dev->i2c_adap, 0x48);
+
+ if (adap->fe_adap[0].fe == NULL) {
+ deb_info("TDA10023 attach failed\n");
+ return -ENODEV;
+ }
+ tt3650_ci_init(adap);
+ } else {
+ adap->fe_adap[1].fe = dvb_attach(tda10048_attach,
+ &tda10048_config, &adap->dev->i2c_adap);
+
+ if (adap->fe_adap[1].fe == NULL) {
+ deb_info("TDA10048 attach failed\n");
+ return -ENODEV;
+ }
+
+ /* tuner is behind TDA10023 I2C-gate */
+ adap->fe_adap[1].fe->ops.i2c_gate_ctrl = ttusb2_ct3650_i2c_gate_ctrl;
+
}
+
return 0;
}
static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
{
- if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) {
+ struct dvb_frontend *fe;
+
+ /* MFE: select correct FE to attach tuner since that's called twice */
+ if (adap->fe_adap[1].fe == NULL)
+ fe = adap->fe_adap[0].fe;
+ else
+ fe = adap->fe_adap[1].fe;
+
+ /* attach tuner */
+ if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) {
printk(KERN_ERR "%s: No tda827x found!\n", __func__);
return -ENODEV;
}
@@ -225,12 +562,12 @@ static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
{
- if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
+ if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
deb_info("TDA8263 attach failed\n");
return -ENODEV;
}
- if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
+ if (dvb_attach(lnbp21_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
deb_info("LNBP21 attach failed\n");
return -ENODEV;
}
@@ -242,6 +579,14 @@ static struct dvb_usb_device_properties ttusb2_properties;
static struct dvb_usb_device_properties ttusb2_properties_s2400;
static struct dvb_usb_device_properties ttusb2_properties_ct3650;
+static void ttusb2_usb_disconnect(struct usb_interface *intf)
+{
+ struct dvb_usb_device *d = usb_get_intfdata(intf);
+
+ tt3650_ci_uninit(d);
+ dvb_usb_device_exit(intf);
+}
+
static int ttusb2_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -277,6 +622,8 @@ static struct dvb_usb_device_properties ttusb2_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = NULL, // ttusb2_streaming_ctrl,
.frontend_attach = ttusb2_frontend_tda10086_attach,
@@ -295,6 +642,7 @@ static struct dvb_usb_device_properties ttusb2_properties = {
}
}
}
+ }},
}
},
@@ -329,6 +677,8 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = NULL,
.frontend_attach = ttusb2_frontend_tda10086_attach,
@@ -347,6 +697,7 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
}
}
}
+ }},
}
},
@@ -383,6 +734,27 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 2,
+ .fe = {{
+ .streaming_ctrl = NULL,
+
+ .frontend_attach = ttusb2_frontend_tda10023_attach,
+ .tuner_attach = ttusb2_tuner_tda827x_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_ISOC,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .isoc = {
+ .framesperurb = 4,
+ .framesize = 940,
+ .interval = 1,
+ }
+ }
+ }
+ }, {
.streaming_ctrl = NULL,
.frontend_attach = ttusb2_frontend_tda10023_attach,
@@ -401,6 +773,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
}
}
}
+ }},
},
},
@@ -422,7 +795,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
static struct usb_driver ttusb2_driver = {
.name = "dvb_usb_ttusb2",
.probe = ttusb2_probe,
- .disconnect = dvb_usb_device_exit,
+ .disconnect = ttusb2_usb_disconnect,
.id_table = ttusb2_table,
};
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 118aab1a3e54..463673a5c2b2 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -60,14 +60,14 @@ static int umt_mt352_frontend_attach(struct dvb_usb_adapter *adap)
umt_config.demod_init = umt_mt352_demod_init;
umt_config.demod_address = 0xf;
- adap->fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
return 0;
}
static int umt_tuner_attach (struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_TUA6034);
+ dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_TUA6034);
return 0;
}
@@ -100,6 +100,8 @@ static struct dvb_usb_device_properties umt_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.streaming_ctrl = dibusb2_0_streaming_ctrl,
.frontend_attach = umt_mt352_frontend_attach,
.tuner_attach = umt_tuner_attach,
@@ -115,7 +117,7 @@ static struct dvb_usb_device_properties umt_properties = {
}
}
},
-
+ }},
.size_of_priv = sizeof(struct dibusb_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/dvb/dvb-usb/usb-urb.c
index 86d68933b6b4..d62ee0f5a165 100644
--- a/drivers/media/dvb/dvb-usb/usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/usb-urb.c
@@ -148,7 +148,7 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream)
if (!stream->urb_list[i]) {
deb_mem("not enough memory for urb_alloc_urb!.\n");
for (j = 0; j < i; j++)
- usb_free_urb(stream->urb_list[i]);
+ usb_free_urb(stream->urb_list[j]);
return -ENOMEM;
}
usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
@@ -181,7 +181,7 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream)
if (!stream->urb_list[i]) {
deb_mem("not enough memory for urb_alloc_urb!\n");
for (j = 0; j < i; j++)
- usb_free_urb(stream->urb_list[i]);
+ usb_free_urb(stream->urb_list[j]);
return -ENOMEM;
}
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index 54355f84a98f..45e31f224814 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -320,7 +320,7 @@ static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
vp702x_init_pid_filter(adap);
- adap->fe = vp702x_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = vp702x_fe_attach(adap->dev);
vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
return 0;
@@ -383,6 +383,8 @@ static struct dvb_usb_device_properties vp702x_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
.streaming_ctrl = vp702x_streaming_ctrl,
@@ -399,6 +401,7 @@ static struct dvb_usb_device_properties vp702x_properties = {
}
}
},
+ }},
.size_of_priv = sizeof(struct vp702x_adapter_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 536c16c943bd..90873af5682e 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -214,7 +214,7 @@ static int vp7045_frontend_attach(struct dvb_usb_adapter *adap)
/* Dump the EEPROM */
/* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
- adap->fe = vp7045_fe_attach(adap->dev);
+ adap->fe_adap[0].fe = vp7045_fe_attach(adap->dev);
return 0;
}
@@ -245,6 +245,8 @@ static struct dvb_usb_device_properties vp7045_properties = {
.num_adapters = 1,
.adapter = {
{
+ .num_frontends = 1,
+ .fe = {{
.frontend_attach = vp7045_frontend_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
@@ -257,6 +259,7 @@ static struct dvb_usb_device_properties vp7045_properties = {
}
}
},
+ }},
}
},
.power_ctrl = vp7045_power_ctrl,
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 32e08e351525..4a2d2e6c91ab 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -236,6 +236,13 @@ config DVB_MB86A16
A DVB-S/DSS Direct Conversion reveiver.
Say Y when you want to support this frontend.
+config DVB_TDA10071
+ tristate "NXP TDA10071"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ Say Y when you want to support this frontend.
+
comment "DVB-T (terrestrial) frontends"
depends on DVB_CORE
@@ -600,6 +607,16 @@ config DVB_LNBP21
help
An SEC control chips.
+config DVB_LNBP22
+ tristate "LNBP22 SEC controllers"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ LNB power supply and control voltage
+ regulator chip with step-up converter
+ and I2C interface.
+ Say Y when you want to support this chip.
+
config DVB_ISL6405
tristate "ISL6405 SEC controller"
depends on DVB_CORE && I2C
@@ -621,6 +638,11 @@ config DVB_ISL6423
help
A SEC controller chip from Intersil
+config DVB_A8293
+ tristate "Allegro A8293"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+
config DVB_LGS8GL5
tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
depends on DVB_CORE && I2C
@@ -661,6 +683,14 @@ config DVB_IX2505V
help
A DVB-S tuner module. Say Y when you want to support this frontend.
+config DVB_IT913X_FE
+ tristate "it913x frontend and it9137 tuner"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-T tuner module.
+ Say Y when you want to support this frontend.
+
comment "Tools to develop new frontends"
config DVB_DUMMY_FE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 6a6ba053ead4..f639f6781551 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -2,8 +2,8 @@
# Makefile for the kernel DVB frontend device drivers.
#
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/common/tuners/
stb0899-objs = stb0899_drv.o stb0899_algo.o
stv0900-objs = stv0900_core.o stv0900_sw.o
@@ -52,6 +52,7 @@ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_LNBP22) += lnbp22.o
obj-$(CONFIG_DVB_ISL6405) += isl6405.o
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
obj-$(CONFIG_DVB_TDA10086) += tda10086.o
@@ -91,4 +92,7 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o
obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
obj-$(CONFIG_DVB_DRXK) += drxk.o
obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
+obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
+obj-$(CONFIG_DVB_A8293) += a8293.o
+obj-$(CONFIG_DVB_TDA10071) += tda10071.o
diff --git a/drivers/media/dvb/frontends/a8293.c b/drivers/media/dvb/frontends/a8293.c
new file mode 100644
index 000000000000..bb56497e940a
--- /dev/null
+++ b/drivers/media/dvb/frontends/a8293.c
@@ -0,0 +1,184 @@
+/*
+ * Allegro A8293 SEC driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 "dvb_frontend.h"
+#include "a8293.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define LOG_PREFIX "a8293"
+
+#undef dbg
+#define dbg(f, arg...) \
+ if (debug) \
+ printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+
+struct a8293_priv {
+ struct i2c_adapter *i2c;
+ const struct a8293_config *cfg;
+ u8 reg[2];
+};
+
+static int a8293_i2c(struct a8293_priv *priv, u8 *val, int len, bool rd)
+{
+ int ret;
+ struct i2c_msg msg[1] = {
+ {
+ .addr = priv->cfg->i2c_addr,
+ .len = len,
+ .buf = val,
+ }
+ };
+
+ if (rd)
+ msg[0].flags = I2C_M_RD;
+ else
+ msg[0].flags = 0;
+
+ ret = i2c_transfer(priv->i2c, msg, 1);
+ if (ret == 1) {
+ ret = 0;
+ } else {
+ warn("i2c failed=%d rd=%d", ret, rd);
+ ret = -EREMOTEIO;
+ }
+
+ return ret;
+}
+
+static int a8293_wr(struct a8293_priv *priv, u8 *val, int len)
+{
+ return a8293_i2c(priv, val, len, 0);
+}
+
+static int a8293_rd(struct a8293_priv *priv, u8 *val, int len)
+{
+ return a8293_i2c(priv, val, len, 1);
+}
+
+static int a8293_set_voltage(struct dvb_frontend *fe,
+ fe_sec_voltage_t fe_sec_voltage)
+{
+ struct a8293_priv *priv = fe->sec_priv;
+ int ret;
+
+ dbg("%s: fe_sec_voltage=%d", __func__, fe_sec_voltage);
+
+ switch (fe_sec_voltage) {
+ case SEC_VOLTAGE_OFF:
+ /* ENB=0 */
+ priv->reg[0] = 0x10;
+ break;
+ case SEC_VOLTAGE_13:
+ /* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/
+ priv->reg[0] = 0x31;
+ break;
+ case SEC_VOLTAGE_18:
+ /* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/
+ priv->reg[0] = 0x38;
+ break;
+ default:
+ ret = -EINVAL;
+ goto err;
+ };
+
+ ret = a8293_wr(priv, &priv->reg[0], 1);
+ if (ret)
+ goto err;
+
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static void a8293_release_sec(struct dvb_frontend *fe)
+{
+ dbg("%s:", __func__);
+
+ a8293_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+ kfree(fe->sec_priv);
+ fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c, const struct a8293_config *cfg)
+{
+ int ret;
+ struct a8293_priv *priv = NULL;
+ u8 buf[2];
+
+ /* allocate memory for the internal priv */
+ priv = kzalloc(sizeof(struct a8293_priv), GFP_KERNEL);
+ if (priv == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* setup the priv */
+ priv->i2c = i2c;
+ priv->cfg = cfg;
+ fe->sec_priv = priv;
+
+ /* check if the SEC is there */
+ ret = a8293_rd(priv, buf, 2);
+ if (ret)
+ goto err;
+
+ /* ENB=0 */
+ priv->reg[0] = 0x10;
+ ret = a8293_wr(priv, &priv->reg[1], 1);
+ if (ret)
+ goto err;
+
+ /* TMODE=0, TGATE=1 */
+ priv->reg[1] = 0x82;
+ ret = a8293_wr(priv, &priv->reg[1], 1);
+ if (ret)
+ goto err;
+
+ info("Allegro A8293 SEC attached.");
+
+ fe->ops.release_sec = a8293_release_sec;
+
+ /* override frontend ops */
+ fe->ops.set_voltage = a8293_set_voltage;
+
+ return fe;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ kfree(priv);
+ return NULL;
+}
+EXPORT_SYMBOL(a8293_attach);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Allegro A8293 SEC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/tda18212_priv.h b/drivers/media/dvb/frontends/a8293.h
index 9adff9356b73..ed29e5504f76 100644
--- a/drivers/media/common/tuners/tda18212_priv.h
+++ b/drivers/media/dvb/frontends/a8293.h
@@ -1,5 +1,5 @@
/*
- * NXP TDA18212HN silicon tuner driver
+ * Allegro A8293 SEC driver
*
* Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
*
@@ -18,27 +18,24 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef TDA18212_PRIV_H
-#define TDA18212_PRIV_H
+#ifndef A8293_H
+#define A8293_H
-#include "tda18212.h"
-
-#define LOG_PREFIX "tda18212"
-
-#undef dbg
-#define dbg(f, arg...) \
- if (debug) \
- printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-struct tda18212_priv {
- struct tda18212_config *cfg;
- struct i2c_adapter *i2c;
+struct a8293_config {
+ u8 i2c_addr;
};
+#if defined(CONFIG_DVB_A8293) || \
+ (defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE))
+extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c, const struct a8293_config *cfg);
+#else
+static inline struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c, const struct a8293_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
#endif
+
+#endif /* A8293_H */
diff --git a/drivers/media/dvb/frontends/cxd2820r.h b/drivers/media/dvb/frontends/cxd2820r.h
index 2906582dc94c..03cab7b547fb 100644
--- a/drivers/media/dvb/frontends/cxd2820r.h
+++ b/drivers/media/dvb/frontends/cxd2820r.h
@@ -93,9 +93,6 @@ extern struct dvb_frontend *cxd2820r_attach(
struct i2c_adapter *i2c,
struct dvb_frontend *fe
);
-extern struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
- struct dvb_frontend *fe
-);
#else
static inline struct dvb_frontend *cxd2820r_attach(
const struct cxd2820r_config *config,
@@ -106,12 +103,6 @@ static inline struct dvb_frontend *cxd2820r_attach(
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-static inline struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
- struct dvb_frontend *fe
-)
-{
- return NULL;
-}
#endif
diff --git a/drivers/media/dvb/frontends/cxd2820r_c.c b/drivers/media/dvb/frontends/cxd2820r_c.c
index 3c07d400731d..b85f5011e344 100644
--- a/drivers/media/dvb/frontends/cxd2820r_c.c
+++ b/drivers/media/dvb/frontends/cxd2820r_c.c
@@ -335,4 +335,3 @@ int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
return 0;
}
-
diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb/frontends/cxd2820r_core.c
index d416e85589e1..036480f967b7 100644
--- a/drivers/media/dvb/frontends/cxd2820r_core.c
+++ b/drivers/media/dvb/frontends/cxd2820r_core.c
@@ -727,72 +727,22 @@ static void cxd2820r_release(struct dvb_frontend *fe)
struct cxd2820r_priv *priv = fe->demodulator_priv;
dbg("%s", __func__);
- if (fe->ops.info.type == FE_OFDM) {
- i2c_del_adapter(&priv->tuner_i2c_adapter);
+ if (fe->ops.info.type == FE_OFDM)
kfree(priv);
- }
return;
}
-static u32 cxd2820r_tuner_i2c_func(struct i2c_adapter *adapter)
-{
- return I2C_FUNC_I2C;
-}
-
-static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg msg[], int num)
-{
- struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap);
- int ret;
- u8 *obuf = kmalloc(msg[0].len + 2, GFP_KERNEL);
- struct i2c_msg msg2[2] = {
- {
- .addr = priv->cfg.i2c_address,
- .flags = 0,
- .len = msg[0].len + 2,
- .buf = obuf,
- }, {
- .addr = priv->cfg.i2c_address,
- .flags = I2C_M_RD,
- .len = msg[1].len,
- .buf = msg[1].buf,
- }
- };
-
- if (!obuf)
- return -ENOMEM;
-
- obuf[0] = 0x09;
- obuf[1] = (msg[0].addr << 1);
- if (num == 2) { /* I2C read */
- obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */
- msg2[0].len = msg[0].len + 2 - 1; /* '-1' maybe HW bug ? */
- }
- memcpy(&obuf[2], msg[0].buf, msg[0].len);
-
- ret = i2c_transfer(priv->i2c, msg2, num);
- if (ret < 0)
- warn("tuner i2c failed ret:%d", ret);
-
- kfree(obuf);
-
- return ret;
-}
-
-static struct i2c_algorithm cxd2820r_tuner_i2c_algo = {
- .master_xfer = cxd2820r_tuner_i2c_xfer,
- .functionality = cxd2820r_tuner_i2c_func,
-};
-
-struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
- return &priv->tuner_i2c_adapter;
+ dbg("%s: %d", __func__, enable);
+
+ /* Bit 0 of reg 0xdb in bank 0x00 controls I2C repeater */
+ return cxd2820r_wr_reg_mask(priv, 0xdb, enable ? 1 : 0, 0x1);
}
-EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter);
-static struct dvb_frontend_ops cxd2820r_ops[2];
+static const struct dvb_frontend_ops cxd2820r_ops[2];
struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
struct i2c_adapter *i2c, struct dvb_frontend *fe)
@@ -831,18 +781,6 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
priv->fe[0].demodulator_priv = priv;
priv->fe[1].demodulator_priv = priv;
- /* create tuner i2c adapter */
- strlcpy(priv->tuner_i2c_adapter.name,
- "CXD2820R tuner I2C adapter",
- sizeof(priv->tuner_i2c_adapter.name));
- priv->tuner_i2c_adapter.algo = &cxd2820r_tuner_i2c_algo;
- priv->tuner_i2c_adapter.algo_data = NULL;
- i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
- if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
- err("tuner I2C bus could not be initialized");
- goto error;
- }
-
return &priv->fe[0];
} else {
@@ -858,7 +796,7 @@ error:
}
EXPORT_SYMBOL(cxd2820r_attach);
-static struct dvb_frontend_ops cxd2820r_ops[2] = {
+static const struct dvb_frontend_ops cxd2820r_ops[2] = {
{
/* DVB-T/T2 */
.info = {
@@ -883,6 +821,7 @@ static struct dvb_frontend_ops cxd2820r_ops[2] = {
.sleep = cxd2820r_sleep,
.get_tune_settings = cxd2820r_get_tune_settings,
+ .i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
.get_frontend = cxd2820r_get_frontend,
@@ -911,6 +850,7 @@ static struct dvb_frontend_ops cxd2820r_ops[2] = {
.sleep = cxd2820r_sleep,
.get_tune_settings = cxd2820r_get_tune_settings,
+ .i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
.set_frontend = cxd2820r_set_frontend,
.get_frontend = cxd2820r_get_frontend,
diff --git a/drivers/media/dvb/frontends/cxd2820r_priv.h b/drivers/media/dvb/frontends/cxd2820r_priv.h
index 0c0ebc9d5c4a..95539134efdb 100644
--- a/drivers/media/dvb/frontends/cxd2820r_priv.h
+++ b/drivers/media/dvb/frontends/cxd2820r_priv.h
@@ -50,7 +50,6 @@ struct cxd2820r_priv {
struct i2c_adapter *i2c;
struct dvb_frontend fe[2];
struct cxd2820r_config cfg;
- struct i2c_adapter tuner_i2c_adapter;
struct mutex fe_lock; /* FE lock */
int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */
diff --git a/drivers/media/dvb/frontends/cxd2820r_t.c b/drivers/media/dvb/frontends/cxd2820r_t.c
index 6582564c930c..a04f9c810101 100644
--- a/drivers/media/dvb/frontends/cxd2820r_t.c
+++ b/drivers/media/dvb/frontends/cxd2820r_t.c
@@ -446,4 +446,3 @@ int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
return 0;
}
-
diff --git a/drivers/media/dvb/frontends/cxd2820r_t2.c b/drivers/media/dvb/frontends/cxd2820r_t2.c
index c47b35c8acf1..6548588309f7 100644
--- a/drivers/media/dvb/frontends/cxd2820r_t2.c
+++ b/drivers/media/dvb/frontends/cxd2820r_t2.c
@@ -420,4 +420,3 @@ int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
return 0;
}
-
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c
index 1d47d4da7d4c..dc1cb17a6ea7 100644
--- a/drivers/media/dvb/frontends/dib0070.c
+++ b/drivers/media/dvb/frontends/dib0070.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/mutex.h>
#include "dvb_frontend.h"
@@ -78,10 +79,18 @@ struct dib0070_state {
struct i2c_msg msg[2];
u8 i2c_write_buffer[3];
u8 i2c_read_buffer[2];
+ struct mutex i2c_buffer_lock;
};
-static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
+static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
{
+ u16 ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return 0;
+ }
+
state->i2c_write_buffer[0] = reg;
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
@@ -96,13 +105,23 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
printk(KERN_WARNING "DiB0070 I2C read failed\n");
- return 0;
- }
- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ ret = 0;
+ } else
+ ret = (state->i2c_read_buffer[0] << 8)
+ | state->i2c_read_buffer[1];
+
+ mutex_unlock(&state->i2c_buffer_lock);
+ return ret;
}
static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
{
+ int ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
state->i2c_write_buffer[0] = reg;
state->i2c_write_buffer[1] = val >> 8;
state->i2c_write_buffer[2] = val & 0xff;
@@ -115,9 +134,12 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
printk(KERN_WARNING "DiB0070 I2C write failed\n");
- return -EREMOTEIO;
- }
- return 0;
+ ret = -EREMOTEIO;
+ } else
+ ret = 0;
+
+ mutex_unlock(&state->i2c_buffer_lock);
+ return ret;
}
#define HARD_RESET(state) do { \
@@ -734,6 +756,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
state->cfg = cfg;
state->i2c = i2c;
state->fe = fe;
+ mutex_init(&state->i2c_buffer_lock);
fe->tuner_priv = state;
if (dib0070_reset(fe) != 0)
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c
index c9c935ae41e4..b174d1c78583 100644
--- a/drivers/media/dvb/frontends/dib0090.c
+++ b/drivers/media/dvb/frontends/dib0090.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/mutex.h>
#include "dvb_frontend.h"
@@ -196,6 +197,7 @@ struct dib0090_state {
struct i2c_msg msg[2];
u8 i2c_write_buffer[3];
u8 i2c_read_buffer[2];
+ struct mutex i2c_buffer_lock;
};
struct dib0090_fw_state {
@@ -208,10 +210,18 @@ struct dib0090_fw_state {
struct i2c_msg msg;
u8 i2c_write_buffer[2];
u8 i2c_read_buffer[2];
+ struct mutex i2c_buffer_lock;
};
static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
{
+ u16 ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return 0;
+ }
+
state->i2c_write_buffer[0] = reg;
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
@@ -226,14 +236,24 @@ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
printk(KERN_WARNING "DiB0090 I2C read failed\n");
- return 0;
- }
+ ret = 0;
+ } else
+ ret = (state->i2c_read_buffer[0] << 8)
+ | state->i2c_read_buffer[1];
- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ mutex_unlock(&state->i2c_buffer_lock);
+ return ret;
}
static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
{
+ int ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
+
state->i2c_write_buffer[0] = reg & 0xff;
state->i2c_write_buffer[1] = val >> 8;
state->i2c_write_buffer[2] = val & 0xff;
@@ -246,13 +266,23 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
printk(KERN_WARNING "DiB0090 I2C write failed\n");
- return -EREMOTEIO;
- }
- return 0;
+ ret = -EREMOTEIO;
+ } else
+ ret = 0;
+
+ mutex_unlock(&state->i2c_buffer_lock);
+ return ret;
}
static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
{
+ u16 ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return 0;
+ }
+
state->i2c_write_buffer[0] = reg;
memset(&state->msg, 0, sizeof(struct i2c_msg));
@@ -262,13 +292,24 @@ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
state->msg.len = 2;
if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
printk(KERN_WARNING "DiB0090 I2C read failed\n");
- return 0;
- }
- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ ret = 0;
+ } else
+ ret = (state->i2c_read_buffer[0] << 8)
+ | state->i2c_read_buffer[1];
+
+ mutex_unlock(&state->i2c_buffer_lock);
+ return ret;
}
static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
{
+ int ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
+
state->i2c_write_buffer[0] = val >> 8;
state->i2c_write_buffer[1] = val & 0xff;
@@ -279,9 +320,12 @@ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
state->msg.len = 2;
if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
printk(KERN_WARNING "DiB0090 I2C write failed\n");
- return -EREMOTEIO;
- }
- return 0;
+ ret = -EREMOTEIO;
+ } else
+ ret = 0;
+
+ mutex_unlock(&state->i2c_buffer_lock);
+ return ret;
}
#define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0)
@@ -2440,6 +2484,7 @@ struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapte
st->config = config;
st->i2c = i2c;
st->fe = fe;
+ mutex_init(&st->i2c_buffer_lock);
fe->tuner_priv = st;
if (config->wbd == NULL)
@@ -2471,6 +2516,7 @@ struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_ada
st->config = config;
st->i2c = i2c;
st->fe = fe;
+ mutex_init(&st->i2c_buffer_lock);
fe->tuner_priv = st;
if (dib0090_fw_reset_digital(fe, st->config) != 0)
diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
index ba917359fa65..404f63a6f26b 100644
--- a/drivers/media/dvb/frontends/dib3000.h
+++ b/drivers/media/dvb/frontends/dib3000.h
@@ -17,7 +17,7 @@
* Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
* sources, on which this driver (and the dvb-dibusb) are based.
*
- * see Documentation/dvb/README.dibusb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
*
*/
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index e80c59796368..437904cbf3e6 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -17,7 +17,7 @@
* Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
* sources, on which this driver (and the dvb-dibusb) are based.
*
- * see Documentation/dvb/README.dibusb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
*
*/
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
index 79cb1c20df24..dbb76d75c932 100644
--- a/drivers/media/dvb/frontends/dib7000m.c
+++ b/drivers/media/dvb/frontends/dib7000m.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/mutex.h>
#include "dvb_frontend.h"
@@ -55,6 +56,7 @@ struct dib7000m_state {
struct i2c_msg msg[2];
u8 i2c_write_buffer[4];
u8 i2c_read_buffer[2];
+ struct mutex i2c_buffer_lock;
};
enum dib7000m_power_mode {
@@ -69,6 +71,13 @@ enum dib7000m_power_mode {
static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
{
+ u16 ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return 0;
+ }
+
state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
state->i2c_write_buffer[1] = reg & 0xff;
@@ -85,11 +94,21 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
dprintk("i2c read error on %d",reg);
- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ mutex_unlock(&state->i2c_buffer_lock);
+
+ return ret;
}
static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
{
+ int ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
+
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
state->i2c_write_buffer[1] = reg & 0xff;
state->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -101,7 +120,10 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
state->msg[0].buf = state->i2c_write_buffer;
state->msg[0].len = 4;
- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
+ -EREMOTEIO : 0);
+ mutex_unlock(&state->i2c_buffer_lock);
+ return ret;
}
static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
{
@@ -1385,6 +1407,7 @@ struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
demod = &st->demod;
demod->demodulator_priv = st;
memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
+ mutex_init(&st->i2c_buffer_lock);
st->timf_default = cfg->bw->timf;
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index a64a538ba364..ce8534ff142e 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/mutex.h>
#include "dvb_math.h"
#include "dvb_frontend.h"
@@ -68,6 +69,7 @@ struct dib7000p_state {
struct i2c_msg msg[2];
u8 i2c_write_buffer[4];
u8 i2c_read_buffer[2];
+ struct mutex i2c_buffer_lock;
};
enum dib7000p_power_mode {
@@ -81,6 +83,13 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
{
+ u16 ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return 0;
+ }
+
state->i2c_write_buffer[0] = reg >> 8;
state->i2c_write_buffer[1] = reg & 0xff;
@@ -97,11 +106,20 @@ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
dprintk("i2c read error on %d", reg);
- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ mutex_unlock(&state->i2c_buffer_lock);
+ return ret;
}
static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
{
+ int ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
+
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
state->i2c_write_buffer[1] = reg & 0xff;
state->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -113,7 +131,10 @@ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
state->msg[0].buf = state->i2c_write_buffer;
state->msg[0].len = 4;
- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
+ -EREMOTEIO : 0);
+ mutex_unlock(&state->i2c_buffer_lock);
+ return ret;
}
static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
@@ -1577,8 +1598,8 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap)
return -ENOMEM;
rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
if (!rx) {
- goto rx_memory_error;
ret = -ENOMEM;
+ goto rx_memory_error;
}
msg[0].buf = tx;
@@ -1646,6 +1667,7 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
return -ENOMEM;
dpst->i2c_adap = i2c;
+ mutex_init(&dpst->i2c_buffer_lock);
for (k = no_of_demods - 1; k >= 0; k--) {
dpst->cfg = cfg[k];
@@ -2324,6 +2346,7 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
demod = &st->demod;
demod->demodulator_priv = st;
memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
+ mutex_init(&st->i2c_buffer_lock);
dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */
@@ -2333,8 +2356,9 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
st->version = dib7000p_read_word(st, 897);
/* FIXME: make sure the dev.parent field is initialized, or else
- request_firmware() will hit an OOPS (this should be moved somewhere
- more common) */
+ request_firmware() will hit an OOPS (this should be moved somewhere
+ more common) */
+ st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
/* FIXME: make sure the dev.parent field is initialized, or else
request_firmware() will hit an OOPS (this should be moved somewhere
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c
index 7d2ea112ae2b..fe284d5292f5 100644
--- a/drivers/media/dvb/frontends/dib8000.c
+++ b/drivers/media/dvb/frontends/dib8000.c
@@ -10,6 +10,8 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/mutex.h>
+
#include "dvb_math.h"
#include "dvb_frontend.h"
@@ -37,6 +39,7 @@ struct i2c_device {
u8 addr;
u8 *i2c_write_buffer;
u8 *i2c_read_buffer;
+ struct mutex *i2c_buffer_lock;
};
struct dib8000_state {
@@ -77,6 +80,7 @@ struct dib8000_state {
struct i2c_msg msg[2];
u8 i2c_write_buffer[4];
u8 i2c_read_buffer[2];
+ struct mutex i2c_buffer_lock;
};
enum dib8000_power_mode {
@@ -86,24 +90,39 @@ enum dib8000_power_mode {
static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
{
+ u16 ret;
struct i2c_msg msg[2] = {
- {.addr = i2c->addr >> 1, .flags = 0,
- .buf = i2c->i2c_write_buffer, .len = 2},
- {.addr = i2c->addr >> 1, .flags = I2C_M_RD,
- .buf = i2c->i2c_read_buffer, .len = 2},
+ {.addr = i2c->addr >> 1, .flags = 0, .len = 2},
+ {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2},
};
+ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return 0;
+ }
+
+ msg[0].buf = i2c->i2c_write_buffer;
msg[0].buf[0] = reg >> 8;
msg[0].buf[1] = reg & 0xff;
+ msg[1].buf = i2c->i2c_read_buffer;
if (i2c_transfer(i2c->adap, msg, 2) != 2)
dprintk("i2c read error on %d", reg);
- return (msg[1].buf[0] << 8) | msg[1].buf[1];
+ ret = (msg[1].buf[0] << 8) | msg[1].buf[1];
+ mutex_unlock(i2c->i2c_buffer_lock);
+ return ret;
}
static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
{
+ u16 ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return 0;
+ }
+
state->i2c_write_buffer[0] = reg >> 8;
state->i2c_write_buffer[1] = reg & 0xff;
@@ -120,7 +139,10 @@ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
dprintk("i2c read error on %d", reg);
- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+ mutex_unlock(&state->i2c_buffer_lock);
+
+ return ret;
}
static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
@@ -135,22 +157,35 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
{
- struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0,
- .buf = i2c->i2c_write_buffer, .len = 4};
+ struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4};
int ret = 0;
+ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
+
+ msg.buf = i2c->i2c_write_buffer;
msg.buf[0] = (reg >> 8) & 0xff;
msg.buf[1] = reg & 0xff;
msg.buf[2] = (val >> 8) & 0xff;
msg.buf[3] = val & 0xff;
ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+ mutex_unlock(i2c->i2c_buffer_lock);
return ret;
}
static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
{
+ int ret;
+
+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
+
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
state->i2c_write_buffer[1] = reg & 0xff;
state->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -162,7 +197,11 @@ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
state->msg[0].buf = state->i2c_write_buffer;
state->msg[0].len = 4;
- return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+ ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ?
+ -EREMOTEIO : 0);
+ mutex_unlock(&state->i2c_buffer_lock);
+
+ return ret;
}
static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
@@ -2434,8 +2473,15 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
if (!client.i2c_read_buffer) {
dprintk("%s: not enough memory", __func__);
ret = -ENOMEM;
- goto error_memory;
+ goto error_memory_read;
+ }
+ client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
+ if (!client.i2c_buffer_lock) {
+ dprintk("%s: not enough memory", __func__);
+ ret = -ENOMEM;
+ goto error_memory_lock;
}
+ mutex_init(client.i2c_buffer_lock);
for (k = no_of_demods - 1; k >= 0; k--) {
/* designated i2c address */
@@ -2476,8 +2522,10 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
}
error:
+ kfree(client.i2c_buffer_lock);
+error_memory_lock:
kfree(client.i2c_read_buffer);
-error_memory:
+error_memory_read:
kfree(client.i2c_write_buffer);
return ret;
@@ -2581,6 +2629,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s
state->i2c.addr = i2c_addr;
state->i2c.i2c_write_buffer = state->i2c_write_buffer;
state->i2c.i2c_read_buffer = state->i2c_read_buffer;
+ mutex_init(&state->i2c_buffer_lock);
+ state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock;
state->gpio_val = cfg->gpio_val;
state->gpio_dir = cfg->gpio_dir;
diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c
index a0855883b5ce..660f80661ed4 100644
--- a/drivers/media/dvb/frontends/dib9000.c
+++ b/drivers/media/dvb/frontends/dib9000.c
@@ -38,6 +38,15 @@ struct i2c_device {
#define DibInitLock(lock) mutex_init(lock)
#define DibFreeLock(lock)
+struct dib9000_pid_ctrl {
+#define DIB9000_PID_FILTER_CTRL 0
+#define DIB9000_PID_FILTER 1
+ u8 cmd;
+ u8 id;
+ u16 pid;
+ u8 onoff;
+};
+
struct dib9000_state {
struct i2c_device i2c;
@@ -99,6 +108,10 @@ struct dib9000_state {
struct i2c_msg msg[2];
u8 i2c_write_buffer[255];
u8 i2c_read_buffer[255];
+ DIB_LOCK demod_lock;
+ u8 get_frontend_internal;
+ struct dib9000_pid_ctrl pid_ctrl[10];
+ s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */
};
static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1167,8 +1180,8 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
- goto error;
ret = -EIO;
+ goto error;
}
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
@@ -1743,19 +1756,56 @@ EXPORT_SYMBOL(dib9000_set_gpio);
int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
{
struct dib9000_state *state = fe->demodulator_priv;
- u16 val = dib9000_read_word(state, 294 + 1) & 0xffef;
+ u16 val;
+ int ret;
+
+ if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) {
+ /* postpone the pid filtering cmd */
+ dprintk("pid filter cmd postpone");
+ state->pid_ctrl_index++;
+ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL;
+ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
+ return 0;
+ }
+
+ DibAcquireLock(&state->demod_lock);
+
+ val = dib9000_read_word(state, 294 + 1) & 0xffef;
val |= (onoff & 0x1) << 4;
dprintk("PID filter enabled %d", onoff);
- return dib9000_write_word(state, 294 + 1, val);
+ ret = dib9000_write_word(state, 294 + 1, val);
+ DibReleaseLock(&state->demod_lock);
+ return ret;
+
}
EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl);
int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
struct dib9000_state *state = fe->demodulator_priv;
+ int ret;
+
+ if (state->pid_ctrl_index != -2) {
+ /* postpone the pid filtering cmd */
+ dprintk("pid filter postpone");
+ if (state->pid_ctrl_index < 9) {
+ state->pid_ctrl_index++;
+ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER;
+ state->pid_ctrl[state->pid_ctrl_index].id = id;
+ state->pid_ctrl[state->pid_ctrl_index].pid = pid;
+ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
+ } else
+ dprintk("can not add any more pid ctrl cmd");
+ return 0;
+ }
+
+ DibAcquireLock(&state->demod_lock);
dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
- return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0);
+ ret = dib9000_write_word(state, 300 + 1 + id,
+ onoff ? (1 << 13) | pid : 0);
+ DibReleaseLock(&state->demod_lock);
+ return ret;
}
EXPORT_SYMBOL(dib9000_fw_pid_filter);
@@ -1778,6 +1828,7 @@ static void dib9000_release(struct dvb_frontend *demod)
DibFreeLock(&state->platform.risc.mbx_lock);
DibFreeLock(&state->platform.risc.mem_lock);
DibFreeLock(&state->platform.risc.mem_mbx_lock);
+ DibFreeLock(&state->demod_lock);
dibx000_exit_i2c_master(&st->i2c_master);
i2c_del_adapter(&st->tuner_adap);
@@ -1795,14 +1846,19 @@ static int dib9000_sleep(struct dvb_frontend *fe)
{
struct dib9000_state *state = fe->demodulator_priv;
u8 index_frontend;
- int ret;
+ int ret = 0;
+ DibAcquireLock(&state->demod_lock);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
if (ret < 0)
- return ret;
+ goto error;
}
- return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
+ ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
+
+error:
+ DibReleaseLock(&state->demod_lock);
+ return ret;
}
static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
@@ -1816,7 +1872,10 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
struct dib9000_state *state = fe->demodulator_priv;
u8 index_frontend, sub_index_frontend;
fe_status_t stat;
- int ret;
+ int ret = 0;
+
+ if (state->get_frontend_internal == 0)
+ DibAcquireLock(&state->demod_lock);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
@@ -1846,14 +1905,15 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
state->fe[index_frontend]->dtv_property_cache.rolloff;
}
}
- return 0;
+ ret = 0;
+ goto return_value;
}
}
/* get the channel from master chip */
ret = dib9000_fw_get_channel(fe, fep);
if (ret != 0)
- return ret;
+ goto return_value;
/* synchronize the cache with the other frontends */
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
@@ -1866,8 +1926,12 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP;
state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff;
}
+ ret = 0;
- return 0;
+return_value:
+ if (state->get_frontend_internal == 0)
+ DibReleaseLock(&state->demod_lock);
+ return ret;
}
static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
@@ -1912,6 +1976,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
dprintk("dib9000: must specify bandwidth ");
return 0;
}
+
+ state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
+ DibAcquireLock(&state->demod_lock);
+
fe->dtv_property_cache.delivery_system = SYS_DVBT;
/* set the master status */
@@ -1974,13 +2042,18 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
/* check the tune result */
if (exit_condition == 1) { /* tune failed */
dprintk("tune failed");
+ DibReleaseLock(&state->demod_lock);
+ /* tune failed; put all the pid filtering cmd to junk */
+ state->pid_ctrl_index = -1;
return 0;
}
dprintk("tune success on frontend%i", index_frontend_success);
/* synchronize all the channel cache */
+ state->get_frontend_internal = 1;
dib9000_get_frontend(state->fe[0], fep);
+ state->get_frontend_internal = 0;
/* retune the other frontends with the found channel */
channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
@@ -2025,6 +2098,28 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
/* turn off the diversity for the last frontend */
dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
+ DibReleaseLock(&state->demod_lock);
+ if (state->pid_ctrl_index >= 0) {
+ u8 index_pid_filter_cmd;
+ u8 pid_ctrl_index = state->pid_ctrl_index;
+
+ state->pid_ctrl_index = -2;
+ for (index_pid_filter_cmd = 0;
+ index_pid_filter_cmd <= pid_ctrl_index;
+ index_pid_filter_cmd++) {
+ if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL)
+ dib9000_fw_pid_filter_ctrl(state->fe[0],
+ state->pid_ctrl[index_pid_filter_cmd].onoff);
+ else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER)
+ dib9000_fw_pid_filter(state->fe[0],
+ state->pid_ctrl[index_pid_filter_cmd].id,
+ state->pid_ctrl[index_pid_filter_cmd].pid,
+ state->pid_ctrl[index_pid_filter_cmd].onoff);
+ }
+ }
+ /* do not postpone any more the pid filtering */
+ state->pid_ctrl_index = -2;
+
return 0;
}
@@ -2041,6 +2136,7 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
u8 index_frontend;
u16 lock = 0, lock_slave = 0;
+ DibAcquireLock(&state->demod_lock);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
@@ -2059,6 +2155,8 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
if ((lock & 0x0008) || (lock_slave & 0x0008))
*stat |= FE_HAS_LOCK;
+ DibReleaseLock(&state->demod_lock);
+
return 0;
}
@@ -2066,10 +2164,15 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
{
struct dib9000_state *state = fe->demodulator_priv;
u16 *c;
+ int ret = 0;
+ DibAcquireLock(&state->demod_lock);
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
- return -EIO;
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ ret = -EIO;
+ goto error;
+ }
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
state->i2c_read_buffer, 16 * 2);
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
@@ -2077,7 +2180,10 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
c = (u16 *)state->i2c_read_buffer;
*ber = c[10] << 16 | c[11];
- return 0;
+
+error:
+ DibReleaseLock(&state->demod_lock);
+ return ret;
}
static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
@@ -2086,7 +2192,9 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
u8 index_frontend;
u16 *c = (u16 *)state->i2c_read_buffer;
u16 val;
+ int ret = 0;
+ DibAcquireLock(&state->demod_lock);
*strength = 0;
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
@@ -2097,8 +2205,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
}
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
- return -EIO;
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+ ret = -EIO;
+ goto error;
+ }
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
@@ -2107,7 +2217,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
*strength = 65535;
else
*strength += val;
- return 0;
+
+error:
+ DibReleaseLock(&state->demod_lock);
+ return ret;
}
static u32 dib9000_get_snr(struct dvb_frontend *fe)
@@ -2151,6 +2264,7 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
u8 index_frontend;
u32 snr_master;
+ DibAcquireLock(&state->demod_lock);
snr_master = dib9000_get_snr(fe);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
snr_master += dib9000_get_snr(state->fe[index_frontend]);
@@ -2161,6 +2275,8 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
} else
*snr = 0;
+ DibReleaseLock(&state->demod_lock);
+
return 0;
}
@@ -2168,15 +2284,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
{
struct dib9000_state *state = fe->demodulator_priv;
u16 *c = (u16 *)state->i2c_read_buffer;
+ int ret = 0;
+ DibAcquireLock(&state->demod_lock);
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
- return -EIO;
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+ ret = -EIO;
+ goto error;
+ }
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
*unc = c[12];
- return 0;
+
+error:
+ DibReleaseLock(&state->demod_lock);
+ return ret;
}
int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
@@ -2322,6 +2445,10 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c
DibInitLock(&st->platform.risc.mbx_lock);
DibInitLock(&st->platform.risc.mem_lock);
DibInitLock(&st->platform.risc.mem_mbx_lock);
+ DibInitLock(&st->demod_lock);
+ st->get_frontend_internal = 0;
+
+ st->pid_ctrl_index = -2;
st->fe[0] = fe;
fe->demodulator_priv = st;
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c
index dc5d17a67579..774d507b66cc 100644
--- a/drivers/media/dvb/frontends/dibx000_common.c
+++ b/drivers/media/dvb/frontends/dibx000_common.c
@@ -1,4 +1,5 @@
#include <linux/i2c.h>
+#include <linux/mutex.h>
#include "dibx000_common.h"
@@ -10,6 +11,13 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
{
+ int ret;
+
+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
+
mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
mst->i2c_write_buffer[1] = reg & 0xff;
mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -21,11 +29,21 @@ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
mst->msg[0].buf = mst->i2c_write_buffer;
mst->msg[0].len = 4;
- return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
+ ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
+ mutex_unlock(&mst->i2c_buffer_lock);
+
+ return ret;
}
static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
{
+ u16 ret;
+
+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return 0;
+ }
+
mst->i2c_write_buffer[0] = reg >> 8;
mst->i2c_write_buffer[1] = reg & 0xff;
@@ -42,7 +60,10 @@ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
dprintk("i2c read error on %d", reg);
- return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
+ ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
+ mutex_unlock(&mst->i2c_buffer_lock);
+
+ return ret;
}
static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
@@ -257,6 +278,7 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg msg[], int num)
{
struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+ int ret;
if (num > 32) {
dprintk("%s: too much I2C message to be transmitted (%i).\
@@ -264,10 +286,15 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
return -ENOMEM;
}
- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
-
dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
+
+ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
/* open the gate */
dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
mst->msg[0].addr = mst->i2c_addr;
@@ -282,7 +309,11 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
mst->msg[num + 1].len = 4;
- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
+ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
+ num : -EIO);
+
+ mutex_unlock(&mst->i2c_buffer_lock);
+ return ret;
}
static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
@@ -294,6 +325,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg msg[], int num)
{
struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+ int ret;
if (num > 32) {
dprintk("%s: too much I2C message to be transmitted (%i).\
@@ -301,10 +333,14 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
return -ENOMEM;
}
- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
-
dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
+ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
/* open the gate */
dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
mst->msg[0].addr = mst->i2c_addr;
@@ -319,7 +355,10 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
mst->msg[num + 1].len = 4;
- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
+ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
+ num : -EIO);
+ mutex_unlock(&mst->i2c_buffer_lock);
+ return ret;
}
static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
@@ -390,8 +429,18 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
struct i2c_adapter *i2c_adap, u8 i2c_addr)
{
- u8 tx[4];
- struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 };
+ int ret;
+
+ mutex_init(&mst->i2c_buffer_lock);
+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+ dprintk("could not acquire lock");
+ return -EINVAL;
+ }
+ memset(mst->msg, 0, sizeof(struct i2c_msg));
+ mst->msg[0].addr = i2c_addr >> 1;
+ mst->msg[0].flags = 0;
+ mst->msg[0].buf = mst->i2c_write_buffer;
+ mst->msg[0].len = 4;
mst->device_rev = device_rev;
mst->i2c_adap = i2c_adap;
@@ -431,9 +480,12 @@ int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
"DiBX000: could not initialize the master i2c_adapter\n");
/* initialize the i2c-master by closing the gate */
- dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
+ dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
+
+ ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);
+ mutex_unlock(&mst->i2c_buffer_lock);
- return i2c_transfer(i2c_adap, &m, 1) == 1;
+ return ret;
}
EXPORT_SYMBOL(dibx000_init_i2c_master);
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h
index f031165c0459..5e011474be43 100644
--- a/drivers/media/dvb/frontends/dibx000_common.h
+++ b/drivers/media/dvb/frontends/dibx000_common.h
@@ -33,6 +33,7 @@ struct dibx000_i2c_master {
struct i2c_msg msg[34];
u8 i2c_write_buffer[8];
u8 i2c_read_buffer[2];
+ struct mutex i2c_buffer_lock;
};
extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
diff --git a/drivers/media/dvb/frontends/drxd_hard.c b/drivers/media/dvb/frontends/drxd_hard.c
index 2238bf0be959..88e46f4cdbb2 100644
--- a/drivers/media/dvb/frontends/drxd_hard.c
+++ b/drivers/media/dvb/frontends/drxd_hard.c
@@ -889,10 +889,15 @@ static int ReadIFAgc(struct drxd_state *state, u32 * pValue)
u32 R2 = state->if_agc_cfg.R2;
u32 R3 = state->if_agc_cfg.R3;
- u32 Vmax = (3300 * R2) / (R1 + R2);
- u32 Rpar = (R2 * R3) / (R3 + R2);
- u32 Vmin = (3300 * Rpar) / (R1 + Rpar);
- u32 Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
+ u32 Vmax, Rpar, Vmin, Vout;
+
+ if (R2 == 0 && (R1 == 0 || R3 == 0))
+ return 0;
+
+ Vmax = (3300 * R2) / (R1 + R2);
+ Rpar = (R2 * R3) / (R3 + R2);
+ Vmin = (3300 * Rpar) / (R1 + Rpar);
+ Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
*pValue = Vout;
}
@@ -926,16 +931,15 @@ static int DownloadMicrocode(struct drxd_state *state,
const u8 *pMCImage, u32 Length)
{
u8 *pSrc;
- u16 Flags;
u32 Address;
u16 nBlocks;
u16 BlockSize;
- u16 BlockCRC;
u32 offset = 0;
int i, status = 0;
pSrc = (u8 *) pMCImage;
- Flags = (pSrc[0] << 8) | pSrc[1];
+ /* We're not using Flags */
+ /* Flags = (pSrc[0] << 8) | pSrc[1]; */
pSrc += sizeof(u16);
offset += sizeof(u16);
nBlocks = (pSrc[0] << 8) | pSrc[1];
@@ -952,11 +956,13 @@ static int DownloadMicrocode(struct drxd_state *state,
pSrc += sizeof(u16);
offset += sizeof(u16);
- Flags = (pSrc[0] << 8) | pSrc[1];
+ /* We're not using Flags */
+ /* u16 Flags = (pSrc[0] << 8) | pSrc[1]; */
pSrc += sizeof(u16);
offset += sizeof(u16);
- BlockCRC = (pSrc[0] << 8) | pSrc[1];
+ /* We're not using BlockCRC */
+ /* u16 BlockCRC = (pSrc[0] << 8) | pSrc[1]; */
pSrc += sizeof(u16);
offset += sizeof(u16);
diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c
index 41b083820dae..f6431ef827dc 100644
--- a/drivers/media/dvb/frontends/drxk_hard.c
+++ b/drivers/media/dvb/frontends/drxk_hard.c
@@ -6211,6 +6211,14 @@ static int drxk_set_parameters(struct dvb_frontend *fe,
u32 IF;
dprintk(1, "\n");
+
+ if (!fe->ops.tuner_ops.get_if_frequency) {
+ printk(KERN_ERR
+ "drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
+ return -EINVAL;
+ }
+
+
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
if (fe->ops.tuner_ops.set_params)
@@ -6218,7 +6226,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe,
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
state->param = *p;
- fe->ops.tuner_ops.get_frequency(fe, &IF);
+ fe->ops.tuner_ops.get_if_frequency(fe, &IF);
Start(state, 0, IF);
/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
diff --git a/drivers/media/dvb/frontends/it913x-fe-priv.h b/drivers/media/dvb/frontends/it913x-fe-priv.h
new file mode 100644
index 000000000000..1c6fb4b66255
--- /dev/null
+++ b/drivers/media/dvb/frontends/it913x-fe-priv.h
@@ -0,0 +1,336 @@
+
+struct it913xset { u32 pro;
+ u32 address;
+ u8 reg[15];
+ u8 count;
+};
+
+struct adctable { u32 adcFrequency;
+ u32 bandwidth;
+ u32 coeff_1_2048;
+ u32 coeff_1_4096;
+ u32 coeff_1_8191;
+ u32 coeff_1_8192;
+ u32 coeff_1_8193;
+ u32 coeff_2_2k;
+ u32 coeff_2_4k;
+ u32 coeff_2_8k;
+ u16 bfsfcw_fftinx_ratio;
+ u16 fftinx_bfsfcw_ratio;
+};
+
+/* clock and coeff tables only table 3 is used with IT9137*/
+/* TODO other tables relate AF9035 may be removed */
+static struct adctable tab1[] = {
+ { 20156250, BANDWIDTH_6_MHZ,
+ 0x02b8ba6e, 0x015c5d37, 0x00ae340d, 0x00ae2e9b, 0x00ae292a,
+ 0x015c5d37, 0x00ae2e9b, 0x0057174e, 0x02f1, 0x015c },
+ { 20156250, BANDWIDTH_7_MHZ,
+ 0x032cd980, 0x01966cc0, 0x00cb3cba, 0x00cb3660, 0x00cb3007,
+ 0x01966cc0, 0x00cb3660, 0x00659b30, 0x0285, 0x0196 },
+ { 20156250, BANDWIDTH_8_MHZ,
+ 0x03a0f893, 0x01d07c49, 0x00e84567, 0x00e83e25, 0x00e836e3,
+ 0x01d07c49, 0x00e83e25, 0x00741f12, 0x0234, 0x01d0 },
+ { 20156250, BANDWIDTH_5_MHZ,
+ 0x02449b5c, 0x01224dae, 0x00912b60, 0x009126d7, 0x0091224e,
+ 0x01224dae, 0x009126d7, 0x0048936b, 0x0387, 0x0122 }
+};
+
+static struct adctable tab2[] = {
+ { 20187500, BANDWIDTH_6_MHZ,
+ 0x02b7a654, 0x015bd32a, 0x00adef04, 0x00ade995, 0x00ade426,
+ 0x015bd32a, 0x00ade995, 0x0056f4ca, 0x02f2, 0x015c },
+ { 20187500, BANDWIDTH_7_MHZ,
+ 0x032b9761, 0x0195cbb1, 0x00caec30, 0x00cae5d8, 0x00cadf81,
+ 0x0195cbb1, 0x00cae5d8, 0x006572ec, 0x0286, 0x0196 },
+ { 20187500, BANDWIDTH_8_MHZ,
+ 0x039f886f, 0x01cfc438, 0x00e7e95b, 0x00e7e21c, 0x00e7dadd,
+ 0x01cfc438, 0x00e7e21c, 0x0073f10e, 0x0235, 0x01d0 },
+ { 20187500, BANDWIDTH_5_MHZ,
+ 0x0243b546, 0x0121daa3, 0x0090f1d9, 0x0090ed51, 0x0090e8ca,
+ 0x0121daa3, 0x0090ed51, 0x004876a9, 0x0388, 0x0122 }
+
+};
+
+static struct adctable tab3[] = {
+ { 20250000, BANDWIDTH_6_MHZ,
+ 0x02b580ad, 0x015ac057, 0x00ad6597, 0x00ad602b, 0x00ad5ac1,
+ 0x015ac057, 0x00ad602b, 0x0056b016, 0x02f4, 0x015b },
+ { 20250000, BANDWIDTH_7_MHZ,
+ 0x03291620, 0x01948b10, 0x00ca4bda, 0x00ca4588, 0x00ca3f36,
+ 0x01948b10, 0x00ca4588, 0x006522c4, 0x0288, 0x0195 },
+ { 20250000, BANDWIDTH_8_MHZ,
+ 0x039cab92, 0x01ce55c9, 0x00e7321e, 0x00e72ae4, 0x00e723ab,
+ 0x01ce55c9, 0x00e72ae4, 0x00739572, 0x0237, 0x01ce },
+ { 20250000, BANDWIDTH_5_MHZ,
+ 0x0241eb3b, 0x0120f59e, 0x00907f53, 0x00907acf, 0x0090764b,
+ 0x0120f59e, 0x00907acf, 0x00483d67, 0x038b, 0x0121 }
+
+};
+
+static struct adctable tab4[] = {
+ { 20583333, BANDWIDTH_6_MHZ,
+ 0x02aa4598, 0x015522cc, 0x00aa96bb, 0x00aa9166, 0x00aa8c12,
+ 0x015522cc, 0x00aa9166, 0x005548b3, 0x0300, 0x0155 },
+ { 20583333, BANDWIDTH_7_MHZ,
+ 0x031bfbdc, 0x018dfdee, 0x00c7052f, 0x00c6fef7, 0x00c6f8bf,
+ 0x018dfdee, 0x00c6fef7, 0x00637f7b, 0x0293, 0x018e },
+ { 20583333, BANDWIDTH_8_MHZ,
+ 0x038db21f, 0x01c6d910, 0x00e373a3, 0x00e36c88, 0x00e3656d,
+ 0x01c6d910, 0x00e36c88, 0x0071b644, 0x0240, 0x01c7 },
+ { 20583333, BANDWIDTH_5_MHZ,
+ 0x02388f54, 0x011c47aa, 0x008e2846, 0x008e23d5, 0x008e1f64,
+ 0x011c47aa, 0x008e23d5, 0x004711ea, 0x039a, 0x011c }
+
+};
+
+static struct adctable tab5[] = {
+ { 20416667, BANDWIDTH_6_MHZ,
+ 0x02afd765, 0x0157ebb3, 0x00abfb39, 0x00abf5d9, 0x00abf07a,
+ 0x0157ebb3, 0x00abf5d9, 0x0055faed, 0x02fa, 0x0158 },
+ { 20416667, BANDWIDTH_7_MHZ,
+ 0x03227b4b, 0x01913da6, 0x00c8a518, 0x00c89ed3, 0x00c8988e,
+ 0x01913da6, 0x00c89ed3, 0x00644f69, 0x028d, 0x0191 },
+ { 20416667, BANDWIDTH_8_MHZ,
+ 0x03951f32, 0x01ca8f99, 0x00e54ef7, 0x00e547cc, 0x00e540a2,
+ 0x01ca8f99, 0x00e547cc, 0x0072a3e6, 0x023c, 0x01cb },
+ { 20416667, BANDWIDTH_5_MHZ,
+ 0x023d337f, 0x011e99c0, 0x008f515a, 0x008f4ce0, 0x008f4865,
+ 0x011e99c0, 0x008f4ce0, 0x0047a670, 0x0393, 0x011f }
+
+};
+
+static struct adctable tab6[] = {
+ { 20480000, BANDWIDTH_6_MHZ,
+ 0x02adb6db, 0x0156db6e, 0x00ab7312, 0x00ab6db7, 0x00ab685c,
+ 0x0156db6e, 0x00ab6db7, 0x0055b6db, 0x02fd, 0x0157 },
+ { 20480000, BANDWIDTH_7_MHZ,
+ 0x03200000, 0x01900000, 0x00c80640, 0x00c80000, 0x00c7f9c0,
+ 0x01900000, 0x00c80000, 0x00640000, 0x028f, 0x0190 },
+ { 20480000, BANDWIDTH_8_MHZ,
+ 0x03924925, 0x01c92492, 0x00e4996e, 0x00e49249, 0x00e48b25,
+ 0x01c92492, 0x00e49249, 0x00724925, 0x023d, 0x01c9 },
+ { 20480000, BANDWIDTH_5_MHZ,
+ 0x023b6db7, 0x011db6db, 0x008edfe5, 0x008edb6e, 0x008ed6f7,
+ 0x011db6db, 0x008edb6e, 0x00476db7, 0x0396, 0x011e }
+};
+
+static struct adctable tab7[] = {
+ { 20500000, BANDWIDTH_6_MHZ,
+ 0x02ad0b99, 0x015685cc, 0x00ab4840, 0x00ab42e6, 0x00ab3d8c,
+ 0x015685cc, 0x00ab42e6, 0x0055a173, 0x02fd, 0x0157 },
+ { 20500000, BANDWIDTH_7_MHZ,
+ 0x031f3832, 0x018f9c19, 0x00c7d44b, 0x00c7ce0c, 0x00c7c7ce,
+ 0x018f9c19, 0x00c7ce0c, 0x0063e706, 0x0290, 0x0190 },
+ { 20500000, BANDWIDTH_8_MHZ,
+ 0x039164cb, 0x01c8b266, 0x00e46056, 0x00e45933, 0x00e45210,
+ 0x01c8b266, 0x00e45933, 0x00722c99, 0x023e, 0x01c9 },
+ { 20500000, BANDWIDTH_5_MHZ,
+ 0x023adeff, 0x011d6f80, 0x008ebc36, 0x008eb7c0, 0x008eb34a,
+ 0x011d6f80, 0x008eb7c0, 0x00475be0, 0x0396, 0x011d }
+
+};
+
+static struct adctable tab8[] = {
+ { 20625000, BANDWIDTH_6_MHZ,
+ 0x02a8e4bd, 0x0154725e, 0x00aa3e81, 0x00aa392f, 0x00aa33de,
+ 0x0154725e, 0x00aa392f, 0x00551c98, 0x0302, 0x0154 },
+ { 20625000, BANDWIDTH_7_MHZ,
+ 0x031a6032, 0x018d3019, 0x00c69e41, 0x00c6980c, 0x00c691d8,
+ 0x018d3019, 0x00c6980c, 0x00634c06, 0x0294, 0x018d },
+ { 20625000, BANDWIDTH_8_MHZ,
+ 0x038bdba6, 0x01c5edd3, 0x00e2fe02, 0x00e2f6ea, 0x00e2efd2,
+ 0x01c5edd3, 0x00e2f6ea, 0x00717b75, 0x0242, 0x01c6 },
+ { 20625000, BANDWIDTH_5_MHZ,
+ 0x02376948, 0x011bb4a4, 0x008ddec1, 0x008dda52, 0x008dd5e3,
+ 0x011bb4a4, 0x008dda52, 0x0046ed29, 0x039c, 0x011c }
+
+};
+
+struct table {
+ u32 xtal;
+ struct adctable *table;
+};
+
+static struct table fe_clockTable[] = {
+ {12000000, tab3}, /* FPGA */
+ {16384000, tab6}, /* 16.38MHz */
+ {20480000, tab6}, /* 20.48MHz */
+ {36000000, tab3}, /* 36.00MHz */
+ {30000000, tab1}, /* 30.00MHz */
+ {26000000, tab4}, /* 26.00MHz */
+ {28000000, tab5}, /* 28.00MHz */
+ {32000000, tab7}, /* 32.00MHz */
+ {34000000, tab2}, /* 34.00MHz */
+ {24000000, tab1}, /* 24.00MHz */
+ {22000000, tab8}, /* 22.00MHz */
+ {12000000, tab3} /* 12.00MHz */
+};
+
+/* fe get */
+fe_code_rate_t fe_code[] = {
+ FEC_1_2,
+ FEC_2_3,
+ FEC_3_4,
+ FEC_5_6,
+ FEC_7_8,
+ FEC_NONE,
+};
+
+fe_guard_interval_t fe_gi[] = {
+ GUARD_INTERVAL_1_32,
+ GUARD_INTERVAL_1_16,
+ GUARD_INTERVAL_1_8,
+ GUARD_INTERVAL_1_4,
+};
+
+fe_hierarchy_t fe_hi[] = {
+ HIERARCHY_NONE,
+ HIERARCHY_1,
+ HIERARCHY_2,
+ HIERARCHY_4,
+};
+
+fe_transmit_mode_t fe_mode[] = {
+ TRANSMISSION_MODE_2K,
+ TRANSMISSION_MODE_8K,
+ TRANSMISSION_MODE_4K,
+};
+
+fe_modulation_t fe_con[] = {
+ QPSK,
+ QAM_16,
+ QAM_64,
+};
+
+/* Standard demodulator functions */
+static struct it913xset set_solo_fe[] = {
+ {PRO_LINK, DVBT_INTEN, {0x04}, 0x01},
+ {PRO_LINK, DVBT_ENABLE, {0x05}, 0x01},
+ {PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
+ {PRO_LINK, HOSTB_MPEG_SER_MODE, {0x00}, 0x01},
+ {PRO_LINK, HOSTB_MPEG_PAR_MODE, {0x00}, 0x01},
+ {PRO_DMOD, DCA_UPPER_CHIP, {0x00}, 0x01},
+ {PRO_LINK, HOSTB_DCA_UPPER, {0x00}, 0x01},
+ {PRO_DMOD, DCA_LOWER_CHIP, {0x00}, 0x01},
+ {PRO_LINK, HOSTB_DCA_LOWER, {0x00}, 0x01},
+ {PRO_DMOD, DCA_PLATCH, {0x00}, 0x01},
+ {PRO_DMOD, DCA_FPGA_LATCH, {0x00}, 0x01},
+ {PRO_DMOD, DCA_STAND_ALONE, {0x01}, 0x01},
+ {PRO_DMOD, DCA_ENABLE, {0x00}, 0x01},
+ {PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
+ {PRO_DMOD, BFS_FCW, {0x00, 0x00, 0x00}, 0x03},
+ {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+
+static struct it913xset init_1[] = {
+ {PRO_LINK, LOCK3_OUT, {0x01}, 0x01},
+ {PRO_LINK, PADMISCDRSR, {0x01}, 0x01},
+ {PRO_LINK, PADMISCDR2, {0x00}, 0x01},
+ {PRO_LINK, PADMISCDR4, {0x00}, 0x01}, /* Power up */
+ {PRO_LINK, PADMISCDR8, {0x00}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+/* ---------IT9137 0x38 tuner init---------- */
+static struct it913xset it9137_set[] = {
+ {PRO_DMOD, 0x0043, {0x00}, 0x01},
+ {PRO_DMOD, 0x0046, {0x38}, 0x01},
+ {PRO_DMOD, 0x0051, {0x01}, 0x01},
+ {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0x0068, {0x0a}, 0x01},
+ {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+ {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
+ {PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
+ {PRO_DMOD, 0x0081, { 0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc8, 0xb8,
+ 0xd0, 0xc3, 0x01 }, 0x0a},
+ {PRO_DMOD, 0x008e, {0x01}, 0x01},
+ {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+ {PRO_DMOD, 0x0099, {0x01}, 0x01},
+ {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+ {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+ {PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+ {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+ {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+ {PRO_DMOD, 0x00b3, {0x02, 0x32}, 0x02},
+ {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+ {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
+ {PRO_DMOD, 0x00c4, {0x00}, 0x01},
+ {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+ {PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
+ {PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
+ {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+ {PRO_DMOD, 0x00fc, { 0x02, 0x02, 0x02, 0x09, 0x50, 0x7b, 0x77,
+ 0x00, 0x02, 0xc8, 0x05, 0x7b }, 0x0c},
+ {PRO_DMOD, 0x0109, {0x02}, 0x01},
+ {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+ {PRO_DMOD, 0x011a, {0xc8, 0x7b, 0xbc, 0xa0}, 0x04},
+ {PRO_DMOD, 0x0122, {0x02, 0x18, 0xc3}, 0x03},
+ {PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
+ {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+ {PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
+ {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8}, 0x04},
+ {PRO_DMOD, 0xf130, {0x04}, 0x01},
+ {PRO_DMOD, 0xf132, {0x04}, 0x01},
+ {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+ {PRO_DMOD, 0xf146, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+ {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+ {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+ {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+ {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+ {PRO_DMOD, 0xf163, {0x05}, 0x01},
+ {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+ {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf183, {0x01}, 0x01},
+ {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+ {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+ {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+ {PRO_DMOD, 0xf204, {0x10}, 0x01},
+ {PRO_DMOD, 0xf214, {0x00}, 0x01},
+ {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+ {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+ {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+ {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+ {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+ {PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
+ {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+ {PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+ {PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+ {PRO_DMOD, 0xf600, { 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+ 0x1f }, 0x08},
+ {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+ {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+ {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+ {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+ {PRO_DMOD, 0xf905, {0x01}, 0x01},
+ {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+ {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+ {PRO_LINK, GPIOH5_EN, {0x01}, 0x01},
+ {PRO_LINK, GPIOH5_ON, {0x01}, 0x01},
+ {PRO_LINK, GPIOH5_O, {0x00}, 0x01},
+ {PRO_LINK, GPIOH5_O, {0x01}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+static struct it913xset it9137_tuner_off[] = {
+ {PRO_DMOD, 0xfba8, {0x01}, 0x01}, /* Tuner Clock Off */
+ {PRO_DMOD, 0xec40, {0x00}, 0x01}, /* Power Down Tuner */
+ {PRO_DMOD, 0xec02, {0x3f, 0x1f, 0x3f, 0x3f}, 0x04},
+ {PRO_DMOD, 0xec3f, {0x01}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+static struct it913xset set_it9137_template[] = {
+ {PRO_DMOD, 0xee06, {0x00}, 0x01},
+ {PRO_DMOD, 0xec56, {0x00}, 0x01},
+ {PRO_DMOD, 0xec4c, {0x00}, 0x01},
+ {PRO_DMOD, 0xec4d, {0x00}, 0x01},
+ {PRO_DMOD, 0xec4e, {0x00}, 0x01},
+ {PRO_DMOD, 0xec4f, {0x00}, 0x01},
+ {PRO_DMOD, 0xec50, {0x00}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb/frontends/it913x-fe.c
new file mode 100644
index 000000000000..d4bd24eb4700
--- /dev/null
+++ b/drivers/media/dvb/frontends/it913x-fe.c
@@ -0,0 +1,839 @@
+/*
+ * Driver for it913x-fe Frontend
+ *
+ * with support for on chip it9137 integral tuner
+ *
+ * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ * IT9137 Copyright (C) ITE Tech 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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "dvb_frontend.h"
+#include "it913x-fe.h"
+#include "it913x-fe-priv.h"
+
+static int it913x_debug;
+
+module_param_named(debug, it913x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define dprintk(level, args...) do { \
+ if (level & it913x_debug) \
+ printk(KERN_DEBUG "it913x-fe: " args); \
+} while (0)
+
+#define deb_info(args...) dprintk(0x01, args)
+#define debug_data_snipet(level, name, p) \
+ dprintk(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
+ *p, *(p+1), *(p+2), *(p+3), *(p+4), \
+ *(p+5), *(p+6), *(p+7));
+
+struct it913x_fe_state {
+ struct dvb_frontend frontend;
+ struct i2c_adapter *i2c_adap;
+ u8 i2c_addr;
+ u32 frequency;
+ u8 adf;
+ u32 crystalFrequency;
+ u32 adcFrequency;
+ u8 tuner_type;
+ struct adctable *table;
+ fe_status_t it913x_status;
+ u16 tun_xtal;
+ u8 tun_fdiv;
+ u8 tun_clk_mode;
+ u32 tun_fn_min;
+};
+
+static int it913x_read_reg(struct it913x_fe_state *state,
+ u32 reg, u8 *data, u8 count)
+{
+ int ret;
+ u8 pro = PRO_DMOD; /* All reads from demodulator */
+ u8 b[4];
+ struct i2c_msg msg[2] = {
+ { .addr = state->i2c_addr + (pro << 1), .flags = 0,
+ .buf = b, .len = sizeof(b) },
+ { .addr = state->i2c_addr + (pro << 1), .flags = I2C_M_RD,
+ .buf = data, .len = count }
+ };
+ b[0] = (u8) reg >> 24;
+ b[1] = (u8)(reg >> 16) & 0xff;
+ b[2] = (u8)(reg >> 8) & 0xff;
+ b[3] = (u8) reg & 0xff;
+
+ ret = i2c_transfer(state->i2c_adap, msg, 2);
+
+ return ret;
+}
+
+static int it913x_read_reg_u8(struct it913x_fe_state *state, u32 reg)
+{
+ int ret;
+ u8 b[1];
+ ret = it913x_read_reg(state, reg, &b[0], sizeof(b));
+ return (ret < 0) ? -ENODEV : b[0];
+}
+
+static int it913x_write(struct it913x_fe_state *state,
+ u8 pro, u32 reg, u8 buf[], u8 count)
+{
+ u8 b[256];
+ struct i2c_msg msg[1] = {
+ { .addr = state->i2c_addr + (pro << 1), .flags = 0,
+ .buf = b, .len = count + 4 }
+ };
+ int ret;
+
+ b[0] = (u8) reg >> 24;
+ b[1] = (u8)(reg >> 16) & 0xff;
+ b[2] = (u8)(reg >> 8) & 0xff;
+ b[3] = (u8) reg & 0xff;
+ memcpy(&b[4], buf, count);
+
+ ret = i2c_transfer(state->i2c_adap, msg, 1);
+
+ if (ret < 0)
+ return -EIO;
+
+ return 0;
+}
+
+static int it913x_write_reg(struct it913x_fe_state *state,
+ u8 pro, u32 reg, u32 data)
+{
+ int ret;
+ u8 b[4];
+ u8 s;
+
+ b[0] = data >> 24;
+ b[1] = (data >> 16) & 0xff;
+ b[2] = (data >> 8) & 0xff;
+ b[3] = data & 0xff;
+ /* expand write as needed */
+ if (data < 0x100)
+ s = 3;
+ else if (data < 0x1000)
+ s = 2;
+ else if (data < 0x100000)
+ s = 1;
+ else
+ s = 0;
+
+ ret = it913x_write(state, pro, reg, &b[s], sizeof(b) - s);
+
+ return ret;
+}
+
+static int it913x_fe_script_loader(struct it913x_fe_state *state,
+ struct it913xset *loadscript)
+{
+ int ret, i;
+ if (loadscript == NULL)
+ return -EINVAL;
+
+ for (i = 0; i < 1000; ++i) {
+ if (loadscript[i].pro == 0xff)
+ break;
+ ret = it913x_write(state, loadscript[i].pro,
+ loadscript[i].address,
+ loadscript[i].reg, loadscript[i].count);
+ if (ret < 0)
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static int it913x_init_tuner(struct it913x_fe_state *state)
+{
+ int ret, i, reg;
+ u8 val, nv_val;
+ u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2};
+ u8 b[2];
+
+ reg = it913x_read_reg_u8(state, 0xec86);
+ switch (reg) {
+ case 0:
+ state->tun_clk_mode = reg;
+ state->tun_xtal = 2000;
+ state->tun_fdiv = 3;
+ val = 16;
+ break;
+ case -ENODEV:
+ return -ENODEV;
+ case 1:
+ default:
+ state->tun_clk_mode = reg;
+ state->tun_xtal = 640;
+ state->tun_fdiv = 1;
+ val = 6;
+ break;
+ }
+
+ reg = it913x_read_reg_u8(state, 0xed03);
+
+ if (reg < 0)
+ return -ENODEV;
+ else if (reg < sizeof(nv))
+ nv_val = nv[reg];
+ else
+ nv_val = 2;
+
+ for (i = 0; i < 50; i++) {
+ ret = it913x_read_reg(state, 0xed23, &b[0], sizeof(b));
+ reg = (b[1] << 8) + b[0];
+ if (reg > 0)
+ break;
+ if (ret < 0)
+ return -ENODEV;
+ udelay(2000);
+ }
+ state->tun_fn_min = state->tun_xtal * reg;
+ state->tun_fn_min /= (state->tun_fdiv * nv_val);
+ deb_info("Tuner fn_min %d", state->tun_fn_min);
+
+ for (i = 0; i < 50; i++) {
+ reg = it913x_read_reg_u8(state, 0xec82);
+ if (reg > 0)
+ break;
+ if (reg < 0)
+ return -ENODEV;
+ udelay(2000);
+ }
+
+ return it913x_write_reg(state, PRO_DMOD, 0xed81, val);
+}
+
+static int it9137_set_tuner(struct it913x_fe_state *state,
+ enum fe_bandwidth bandwidth, u32 frequency_m)
+{
+ struct it913xset *set_tuner = set_it9137_template;
+ int ret, reg;
+ u32 frequency = frequency_m / 1000;
+ u32 freq, temp_f, tmp;
+ u16 iqik_m_cal;
+ u16 n_div;
+ u8 n;
+ u8 l_band;
+ u8 lna_band;
+ u8 bw;
+
+ deb_info("Tuner Frequency %d Bandwidth %d", frequency, bandwidth);
+
+ if (frequency >= 51000 && frequency <= 440000) {
+ l_band = 0;
+ lna_band = 0;
+ } else if (frequency > 440000 && frequency <= 484000) {
+ l_band = 1;
+ lna_band = 1;
+ } else if (frequency > 484000 && frequency <= 533000) {
+ l_band = 1;
+ lna_band = 2;
+ } else if (frequency > 533000 && frequency <= 587000) {
+ l_band = 1;
+ lna_band = 3;
+ } else if (frequency > 587000 && frequency <= 645000) {
+ l_band = 1;
+ lna_band = 4;
+ } else if (frequency > 645000 && frequency <= 710000) {
+ l_band = 1;
+ lna_band = 5;
+ } else if (frequency > 710000 && frequency <= 782000) {
+ l_band = 1;
+ lna_band = 6;
+ } else if (frequency > 782000 && frequency <= 860000) {
+ l_band = 1;
+ lna_band = 7;
+ } else if (frequency > 1450000 && frequency <= 1492000) {
+ l_band = 1;
+ lna_band = 0;
+ } else if (frequency > 1660000 && frequency <= 1685000) {
+ l_band = 1;
+ lna_band = 1;
+ } else
+ return -EINVAL;
+ set_tuner[0].reg[0] = lna_band;
+
+ if (bandwidth == BANDWIDTH_5_MHZ)
+ bw = 0;
+ else if (bandwidth == BANDWIDTH_6_MHZ)
+ bw = 2;
+ else if (bandwidth == BANDWIDTH_7_MHZ)
+ bw = 4;
+ else if (bandwidth == BANDWIDTH_8_MHZ)
+ bw = 6;
+ else
+ bw = 6;
+
+ set_tuner[1].reg[0] = bw;
+ set_tuner[2].reg[0] = 0xa0 | (l_band << 3);
+
+ if (frequency > 53000 && frequency <= 74000) {
+ n_div = 48;
+ n = 0;
+ } else if (frequency > 74000 && frequency <= 111000) {
+ n_div = 32;
+ n = 1;
+ } else if (frequency > 111000 && frequency <= 148000) {
+ n_div = 24;
+ n = 2;
+ } else if (frequency > 148000 && frequency <= 222000) {
+ n_div = 16;
+ n = 3;
+ } else if (frequency > 222000 && frequency <= 296000) {
+ n_div = 12;
+ n = 4;
+ } else if (frequency > 296000 && frequency <= 445000) {
+ n_div = 8;
+ n = 5;
+ } else if (frequency > 445000 && frequency <= state->tun_fn_min) {
+ n_div = 6;
+ n = 6;
+ } else if (frequency > state->tun_fn_min && frequency <= 950000) {
+ n_div = 4;
+ n = 7;
+ } else if (frequency > 1450000 && frequency <= 1680000) {
+ n_div = 2;
+ n = 0;
+ } else
+ return -EINVAL;
+
+ reg = it913x_read_reg_u8(state, 0xed81);
+ iqik_m_cal = (u16)reg * n_div;
+
+ if (reg < 0x20) {
+ if (state->tun_clk_mode == 0)
+ iqik_m_cal = (iqik_m_cal * 9) >> 5;
+ else
+ iqik_m_cal >>= 1;
+ } else {
+ iqik_m_cal = 0x40 - iqik_m_cal;
+ if (state->tun_clk_mode == 0)
+ iqik_m_cal = ~((iqik_m_cal * 9) >> 5);
+ else
+ iqik_m_cal = ~(iqik_m_cal >> 1);
+ }
+
+ temp_f = frequency * (u32)n_div * (u32)state->tun_fdiv;
+ freq = temp_f / state->tun_xtal;
+ tmp = freq * state->tun_xtal;
+
+ if ((temp_f - tmp) >= (state->tun_xtal >> 1))
+ freq++;
+
+ freq += (u32) n << 13;
+ /* Frequency OMEGA_IQIK_M_CAL_MID*/
+ temp_f = freq + (u32)iqik_m_cal;
+
+ set_tuner[3].reg[0] = temp_f & 0xff;
+ set_tuner[4].reg[0] = (temp_f >> 8) & 0xff;
+
+ deb_info("High Frequency = %04x", temp_f);
+
+ /* Lower frequency */
+ set_tuner[5].reg[0] = freq & 0xff;
+ set_tuner[6].reg[0] = (freq >> 8) & 0xff;
+
+ deb_info("low Frequency = %04x", freq);
+
+ ret = it913x_fe_script_loader(state, set_tuner);
+
+ return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_fe_select_bw(struct it913x_fe_state *state,
+ enum fe_bandwidth bandwidth, u32 adcFrequency)
+{
+ int ret, i;
+ u8 buffer[256];
+ u32 coeff[8];
+ u16 bfsfcw_fftinx_ratio;
+ u16 fftinx_bfsfcw_ratio;
+ u8 count;
+ u8 bw;
+ u8 adcmultiplier;
+
+ deb_info("Bandwidth %d Adc %d", bandwidth, adcFrequency);
+
+ if (bandwidth == BANDWIDTH_5_MHZ)
+ bw = 3;
+ else if (bandwidth == BANDWIDTH_6_MHZ)
+ bw = 0;
+ else if (bandwidth == BANDWIDTH_7_MHZ)
+ bw = 1;
+ else if (bandwidth == BANDWIDTH_8_MHZ)
+ bw = 2;
+ else
+ bw = 2;
+
+ ret = it913x_write_reg(state, PRO_DMOD, REG_BW, bw);
+
+ if (state->table == NULL)
+ return -EINVAL;
+
+ /* In write order */
+ coeff[0] = state->table[bw].coeff_1_2048;
+ coeff[1] = state->table[bw].coeff_2_2k;
+ coeff[2] = state->table[bw].coeff_1_8191;
+ coeff[3] = state->table[bw].coeff_1_8192;
+ coeff[4] = state->table[bw].coeff_1_8193;
+ coeff[5] = state->table[bw].coeff_2_8k;
+ coeff[6] = state->table[bw].coeff_1_4096;
+ coeff[7] = state->table[bw].coeff_2_4k;
+ bfsfcw_fftinx_ratio = state->table[bw].bfsfcw_fftinx_ratio;
+ fftinx_bfsfcw_ratio = state->table[bw].fftinx_bfsfcw_ratio;
+
+ /* ADC multiplier */
+ ret = it913x_read_reg_u8(state, ADC_X_2);
+ if (ret < 0)
+ return -EINVAL;
+
+ adcmultiplier = ret;
+
+ count = 0;
+
+ /* Build Buffer for COEFF Registers */
+ for (i = 0; i < 8; i++) {
+ if (adcmultiplier == 1)
+ coeff[i] /= 2;
+ buffer[count++] = (coeff[i] >> 24) & 0x3;
+ buffer[count++] = (coeff[i] >> 16) & 0xff;
+ buffer[count++] = (coeff[i] >> 8) & 0xff;
+ buffer[count++] = coeff[i] & 0xff;
+ }
+
+ /* bfsfcw_fftinx_ratio register 0x21-0x22 */
+ buffer[count++] = bfsfcw_fftinx_ratio & 0xff;
+ buffer[count++] = (bfsfcw_fftinx_ratio >> 8) & 0xff;
+ /* fftinx_bfsfcw_ratio register 0x23-0x24 */
+ buffer[count++] = fftinx_bfsfcw_ratio & 0xff;
+ buffer[count++] = (fftinx_bfsfcw_ratio >> 8) & 0xff;
+ /* start at COEFF_1_2048 and write through to fftinx_bfsfcw_ratio*/
+ ret = it913x_write(state, PRO_DMOD, COEFF_1_2048, buffer, count);
+
+ for (i = 0; i < 42; i += 8)
+ debug_data_snipet(0x1, "Buffer", &buffer[i]);
+
+ return ret;
+}
+
+
+
+static int it913x_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct it913x_fe_state *state = fe->demodulator_priv;
+ int ret, i;
+ fe_status_t old_status = state->it913x_status;
+ *status = 0;
+
+ if (state->it913x_status == 0) {
+ ret = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
+ if (ret == 0x1) {
+ *status |= FE_HAS_SIGNAL;
+ for (i = 0; i < 40; i++) {
+ ret = it913x_read_reg_u8(state, MP2IF_SYNC_LK);
+ if (ret == 0x1)
+ break;
+ msleep(25);
+ }
+ if (ret == 0x1)
+ *status |= FE_HAS_CARRIER
+ | FE_HAS_VITERBI
+ | FE_HAS_SYNC;
+ state->it913x_status = *status;
+ }
+ }
+
+ if (state->it913x_status & FE_HAS_SYNC) {
+ ret = it913x_read_reg_u8(state, TPSD_LOCK);
+ if (ret == 0x1)
+ *status |= FE_HAS_LOCK
+ | state->it913x_status;
+ else
+ state->it913x_status = 0;
+ if (old_status != state->it913x_status)
+ ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, ret);
+ }
+
+ return 0;
+}
+
+static int it913x_fe_read_signal_strength(struct dvb_frontend *fe,
+ u16 *strength)
+{
+ struct it913x_fe_state *state = fe->demodulator_priv;
+ int ret = it913x_read_reg_u8(state, SIGNAL_LEVEL);
+ /*SIGNAL_LEVEL always returns 100%! so using FE_HAS_SIGNAL as switch*/
+ if (state->it913x_status & FE_HAS_SIGNAL)
+ ret = (ret * 0xff) / 0x64;
+ else
+ ret = 0x0;
+ ret |= ret << 0x8;
+ *strength = ret;
+ return 0;
+}
+
+static int it913x_fe_read_snr(struct dvb_frontend *fe, u16* snr)
+{
+ struct it913x_fe_state *state = fe->demodulator_priv;
+ int ret = it913x_read_reg_u8(state, SIGNAL_QUALITY);
+ ret = (ret * 0xff) / 0x64;
+ ret |= (ret << 0x8);
+ *snr = ~ret;
+ return 0;
+}
+
+static int it913x_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ *ber = 0;
+ return 0;
+}
+
+static int it913x_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ *ucblocks = 0;
+ return 0;
+}
+
+static int it913x_fe_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct it913x_fe_state *state = fe->demodulator_priv;
+ int ret;
+ u8 reg[8];
+
+ ret = it913x_read_reg(state, REG_TPSD_TX_MODE, reg, sizeof(reg));
+
+ if (reg[3] < 3)
+ p->u.ofdm.constellation = fe_con[reg[3]];
+
+ if (reg[0] < 3)
+ p->u.ofdm.transmission_mode = fe_mode[reg[0]];
+
+ if (reg[1] < 4)
+ p->u.ofdm.guard_interval = fe_gi[reg[1]];
+
+ if (reg[2] < 4)
+ p->u.ofdm.hierarchy_information = fe_hi[reg[2]];
+
+ p->u.ofdm.code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
+ p->u.ofdm.code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
+
+ return 0;
+}
+
+static int it913x_fe_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct it913x_fe_state *state = fe->demodulator_priv;
+ int ret, i;
+ u8 empty_ch, last_ch;
+
+ state->it913x_status = 0;
+
+ /* Set bw*/
+ ret = it913x_fe_select_bw(state, p->u.ofdm.bandwidth,
+ state->adcFrequency);
+
+ /* Training Mode Off */
+ ret = it913x_write_reg(state, PRO_LINK, TRAINING_MODE, 0x0);
+
+ /* Clear Empty Channel */
+ ret = it913x_write_reg(state, PRO_DMOD, EMPTY_CHANNEL_STATUS, 0x0);
+
+ /* Clear bits */
+ ret = it913x_write_reg(state, PRO_DMOD, MP2IF_SYNC_LK, 0x0);
+ /* LED on */
+ ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
+ /* Select Band*/
+ if ((p->frequency >= 51000000) && (p->frequency <= 230000000))
+ i = 0;
+ else if ((p->frequency >= 350000000) && (p->frequency <= 900000000))
+ i = 1;
+ else if ((p->frequency >= 1450000000) && (p->frequency <= 1680000000))
+ i = 2;
+ else
+ return -EOPNOTSUPP;
+
+ ret = it913x_write_reg(state, PRO_DMOD, FREE_BAND, i);
+
+ deb_info("Frontend Set Tuner Type %02x", state->tuner_type);
+ switch (state->tuner_type) {
+ case IT9137: /* Tuner type 0x38 */
+ ret = it9137_set_tuner(state,
+ p->u.ofdm.bandwidth, p->frequency);
+ break;
+ default:
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+ break;
+ }
+ /* LED off */
+ ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
+ /* Trigger ofsm */
+ ret = it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
+ last_ch = 2;
+ for (i = 0; i < 40; ++i) {
+ empty_ch = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
+ if (last_ch == 1 && empty_ch == 1)
+ break;
+ if (last_ch == 2 && empty_ch == 2)
+ return 0;
+ last_ch = empty_ch;
+ msleep(25);
+ }
+ for (i = 0; i < 40; ++i) {
+ if (it913x_read_reg_u8(state, D_TPSD_LOCK) == 1)
+ break;
+ msleep(25);
+ }
+
+ state->frequency = p->frequency;
+ return 0;
+}
+
+static int it913x_fe_suspend(struct it913x_fe_state *state)
+{
+ int ret, i;
+ u8 b;
+
+ ret = it913x_write_reg(state, PRO_DMOD, SUSPEND_FLAG, 0x1);
+
+ ret |= it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
+
+ for (i = 0; i < 128; i++) {
+ ret = it913x_read_reg(state, SUSPEND_FLAG, &b, 1);
+ if (ret < 0)
+ return -ENODEV;
+ if (b == 0)
+ break;
+
+ }
+
+ ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x8);
+ /* Turn LED off */
+ ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
+
+ ret |= it913x_fe_script_loader(state, it9137_tuner_off);
+
+ return (ret < 0) ? -ENODEV : 0;
+}
+
+/* Power sequence */
+/* Power Up Tuner on -> Frontend suspend off -> Tuner clk on */
+/* Power Down Frontend suspend on -> Tuner clk off -> Tuner off */
+
+static int it913x_fe_sleep(struct dvb_frontend *fe)
+{
+ struct it913x_fe_state *state = fe->demodulator_priv;
+ return it913x_fe_suspend(state);
+}
+
+static u32 compute_div(u32 a, u32 b, u32 x)
+{
+ u32 res = 0;
+ u32 c = 0;
+ u32 i = 0;
+
+ if (a > b) {
+ c = a / b;
+ a = a - c * b;
+ }
+
+ for (i = 0; i < x; i++) {
+ if (a >= b) {
+ res += 1;
+ a -= b;
+ }
+ a <<= 1;
+ res <<= 1;
+ }
+
+ res = (c << x) + res;
+
+ return res;
+}
+
+static int it913x_fe_start(struct it913x_fe_state *state)
+{
+ struct it913xset *set_fe;
+ struct it913xset *set_mode;
+ int ret;
+ u8 adf = (state->adf & 0xf);
+ u32 adc, xtal;
+ u8 b[4];
+
+ ret = it913x_init_tuner(state);
+
+ if (adf < 12) {
+ state->crystalFrequency = fe_clockTable[adf].xtal ;
+ state->table = fe_clockTable[adf].table;
+ state->adcFrequency = state->table->adcFrequency;
+
+ adc = compute_div(state->adcFrequency, 1000000ul, 19ul);
+ xtal = compute_div(state->crystalFrequency, 1000000ul, 19ul);
+
+ } else
+ return -EINVAL;
+
+ deb_info("Xtal Freq :%d Adc Freq :%d Adc %08x Xtal %08x",
+ state->crystalFrequency, state->adcFrequency, adc, xtal);
+
+ /* Set LED indicator on GPIOH3 */
+ ret = it913x_write_reg(state, PRO_LINK, GPIOH3_EN, 0x1);
+ ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1);
+ ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
+
+ ret |= it913x_write_reg(state, PRO_LINK, 0xf641, state->tuner_type);
+ ret |= it913x_write_reg(state, PRO_DMOD, 0xf5ca, 0x01);
+ ret |= it913x_write_reg(state, PRO_DMOD, 0xf715, 0x01);
+
+ b[0] = xtal & 0xff;
+ b[1] = (xtal >> 8) & 0xff;
+ b[2] = (xtal >> 16) & 0xff;
+ b[3] = (xtal >> 24);
+ ret |= it913x_write(state, PRO_DMOD, XTAL_CLK, b , 4);
+
+ b[0] = adc & 0xff;
+ b[1] = (adc >> 8) & 0xff;
+ b[2] = (adc >> 16) & 0xff;
+ ret |= it913x_write(state, PRO_DMOD, ADC_FREQ, b, 3);
+
+ switch (state->tuner_type) {
+ case IT9137: /* Tuner type 0x38 */
+ set_fe = it9137_set;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* set the demod */
+ ret = it913x_fe_script_loader(state, set_fe);
+ /* Always solo frontend */
+ set_mode = set_solo_fe;
+ ret |= it913x_fe_script_loader(state, set_mode);
+
+ ret |= it913x_fe_suspend(state);
+ return 0;
+}
+
+static int it913x_fe_init(struct dvb_frontend *fe)
+{
+ struct it913x_fe_state *state = fe->demodulator_priv;
+ int ret = 0;
+ /* Power Up Tuner - common all versions */
+ ret = it913x_write_reg(state, PRO_DMOD, 0xec40, 0x1);
+
+ ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0);
+
+ ret |= it913x_fe_script_loader(state, init_1);
+
+ switch (state->tuner_type) {
+ case IT9137:
+ ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return (ret < 0) ? -ENODEV : 0;
+}
+
+static void it913x_fe_release(struct dvb_frontend *fe)
+{
+ struct it913x_fe_state *state = fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops it913x_fe_ofdm_ops;
+
+struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
+ u8 i2c_addr, u8 adf, u8 type)
+{
+ struct it913x_fe_state *state = NULL;
+ int ret;
+ /* allocate memory for the internal state */
+ state = kzalloc(sizeof(struct it913x_fe_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ state->i2c_adap = i2c_adap;
+ state->i2c_addr = i2c_addr;
+ state->adf = adf;
+ state->tuner_type = type;
+
+ ret = it913x_fe_start(state);
+ if (ret < 0)
+ goto error;
+
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &it913x_fe_ofdm_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
+ return &state->frontend;
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(it913x_fe_attach);
+
+static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
+
+ .info = {
+ .name = "it913x-fe DVB-T",
+ .type = FE_OFDM,
+ .frequency_min = 51000000,
+ .frequency_max = 1680000000,
+ .frequency_stepsize = 62500,
+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+ FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO,
+ },
+
+ .release = it913x_fe_release,
+
+ .init = it913x_fe_init,
+ .sleep = it913x_fe_sleep,
+
+ .set_frontend = it913x_fe_set_frontend,
+ .get_frontend = it913x_fe_get_frontend,
+
+ .read_status = it913x_fe_read_status,
+ .read_signal_strength = it913x_fe_read_signal_strength,
+ .read_snr = it913x_fe_read_snr,
+ .read_ber = it913x_fe_read_ber,
+ .read_ucblocks = it913x_fe_read_ucblocks,
+};
+
+MODULE_DESCRIPTION("it913x Frontend and it9137 tuner");
+MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
+MODULE_VERSION("1.07");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/it913x-fe.h b/drivers/media/dvb/frontends/it913x-fe.h
new file mode 100644
index 000000000000..9d97f32e690b
--- /dev/null
+++ b/drivers/media/dvb/frontends/it913x-fe.h
@@ -0,0 +1,196 @@
+/*
+ * Driver for it913x Frontend
+ *
+ *
+ * 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.=
+ */
+
+#ifndef IT913X_FE_H
+#define IT913X_FE_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+#if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \
+defined(MODULE))
+extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
+ u8 i2c_addr, u8 adf, u8 type);
+#else
+static inline struct dvb_frontend *it913x_fe_attach(
+ struct i2c_adapter *i2c_adap, u8 i2c_addr, u8 adf, u8 type)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_IT913X_FE */
+#define I2C_BASE_ADDR 0x10
+#define DEV_0 0x0
+#define DEV_1 0x10
+#define PRO_LINK 0x0
+#define PRO_DMOD 0x1
+#define DEV_0_DMOD (PRO_DMOD << 0x7)
+#define DEV_1_DMOD (DEV_0_DMOD | DEV_1)
+#define CHIP2_I2C_ADDR 0x3a
+
+#define AFE_MEM0 0xfb24
+
+#define MP2_SW_RST 0xf99d
+#define MP2IF2_SW_RST 0xf9a4
+
+#define PADODPU 0xd827
+#define THIRDODPU 0xd828
+#define AGC_O_D 0xd829
+
+#define EP0_TX_EN 0xdd11
+#define EP0_TX_NAK 0xdd13
+#define EP4_TX_LEN_LSB 0xdd88
+#define EP4_TX_LEN_MSB 0xdd89
+#define EP4_MAX_PKT 0xdd0c
+#define EP5_TX_LEN_LSB 0xdd8a
+#define EP5_TX_LEN_MSB 0xdd8b
+#define EP5_MAX_PKT 0xdd0d
+
+#define IO_MUX_POWER_CLK 0xd800
+#define CLK_O_EN 0xd81a
+#define I2C_CLK 0xf103
+#define I2C_CLK_100 0x7
+#define I2C_CLK_400 0x1a
+
+#define D_TPSD_LOCK 0xf5a9
+#define MP2IF2_EN 0xf9a3
+#define MP2IF_SERIAL 0xf985
+#define TSIS_ENABLE 0xf9cd
+#define MP2IF2_HALF_PSB 0xf9a5
+#define MP2IF_STOP_EN 0xf9b5
+#define MPEG_FULL_SPEED 0xf990
+#define TOP_HOSTB_SER_MODE 0xd91c
+
+#define PID_RST 0xf992
+#define PID_EN 0xf993
+#define PID_INX_EN 0xf994
+#define PID_INX 0xf995
+#define PID_LSB 0xf996
+#define PID_MSB 0xf997
+
+#define MP2IF_MPEG_PAR_MODE 0xf986
+#define DCA_UPPER_CHIP 0xf731
+#define DCA_LOWER_CHIP 0xf732
+#define DCA_PLATCH 0xf730
+#define DCA_FPGA_LATCH 0xf778
+#define DCA_STAND_ALONE 0xf73c
+#define DCA_ENABLE 0xf776
+
+#define DVBT_INTEN 0xf41f
+#define DVBT_ENABLE 0xf41a
+#define HOSTB_DCA_LOWER 0xd91f
+#define HOSTB_MPEG_PAR_MODE 0xd91b
+#define HOSTB_MPEG_SER_MODE 0xd91c
+#define HOSTB_MPEG_SER_DO7 0xd91d
+#define HOSTB_DCA_UPPER 0xd91e
+#define PADMISCDR2 0xd830
+#define PADMISCDR4 0xd831
+#define PADMISCDR8 0xd832
+#define PADMISCDRSR 0xd833
+#define LOCK3_OUT 0xd8fd
+
+#define GPIOH1_O 0xd8af
+#define GPIOH1_EN 0xd8b0
+#define GPIOH1_ON 0xd8b1
+#define GPIOH3_O 0xd8b3
+#define GPIOH3_EN 0xd8b4
+#define GPIOH3_ON 0xd8b5
+#define GPIOH5_O 0xd8bb
+#define GPIOH5_EN 0xd8bc
+#define GPIOH5_ON 0xd8bd
+
+#define AFE_MEM0 0xfb24
+
+#define REG_TPSD_TX_MODE 0xf900
+#define REG_TPSD_GI 0xf901
+#define REG_TPSD_HIER 0xf902
+#define REG_TPSD_CONST 0xf903
+#define REG_BW 0xf904
+#define REG_PRIV 0xf905
+#define REG_TPSD_HP_CODE 0xf906
+#define REG_TPSD_LP_CODE 0xf907
+
+#define MP2IF_SYNC_LK 0xf999
+#define ADC_FREQ 0xf1cd
+
+#define TRIGGER_OFSM 0x0000
+/* COEFF Registers start at 0x0001 to 0x0020 */
+#define COEFF_1_2048 0x0001
+#define XTAL_CLK 0x0025
+#define BFS_FCW 0x0029
+#define TPSD_LOCK 0x003c
+#define TRAINING_MODE 0x0040
+#define ADC_X_2 0x0045
+#define TUNER_ID 0x0046
+#define EMPTY_CHANNEL_STATUS 0x0047
+#define SIGNAL_LEVEL 0x0048
+#define SIGNAL_QUALITY 0x0049
+#define EST_SIGNAL_LEVEL 0x004a
+#define FREE_BAND 0x004b
+#define SUSPEND_FLAG 0x004c
+/* Build in tuners */
+#define IT9137 0x38
+
+enum {
+ CMD_DEMOD_READ = 0,
+ CMD_DEMOD_WRITE,
+ CMD_TUNER_READ,
+ CMD_TUNER_WRITE,
+ CMD_REG_EEPROM_READ,
+ CMD_REG_EEPROM_WRITE,
+ CMD_DATA_READ,
+ CMD_VAR_READ = 8,
+ CMD_VAR_WRITE,
+ CMD_PLATFORM_GET,
+ CMD_PLATFORM_SET,
+ CMD_IP_CACHE,
+ CMD_IP_ADD,
+ CMD_IP_REMOVE,
+ CMD_PID_ADD,
+ CMD_PID_REMOVE,
+ CMD_SIPSI_GET,
+ CMD_SIPSI_MPE_RESET,
+ CMD_H_PID_ADD = 0x15,
+ CMD_H_PID_REMOVE,
+ CMD_ABORT,
+ CMD_IR_GET,
+ CMD_IR_SET,
+ CMD_FW_DOWNLOAD = 0x21,
+ CMD_QUERYINFO,
+ CMD_BOOT,
+ CMD_FW_DOWNLOAD_BEGIN,
+ CMD_FW_DOWNLOAD_END,
+ CMD_RUN_CODE,
+ CMD_SCATTER_READ = 0x28,
+ CMD_SCATTER_WRITE,
+ CMD_GENERIC_READ,
+ CMD_GENERIC_WRITE
+};
+
+enum {
+ READ_LONG,
+ WRITE_LONG,
+ READ_SHORT,
+ WRITE_SHORT,
+ READ_DATA,
+ WRITE_DATA,
+ WRITE_CMD,
+};
+
+#endif /* IT913X_FE_H */
diff --git a/drivers/media/dvb/frontends/lnbp22.c b/drivers/media/dvb/frontends/lnbp22.c
new file mode 100644
index 000000000000..84ad0390a4a1
--- /dev/null
+++ b/drivers/media/dvb/frontends/lnbp22.c
@@ -0,0 +1,148 @@
+/*
+ * lnbp22.h - driver for lnb supply and control ic lnbp22
+ *
+ * Copyright (C) 2006 Dominik Kuhlen
+ * Based on lnbp21 driver
+ *
+ * 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "lnbp22.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+
+#define dprintk(lvl, arg...) if (debug >= (lvl)) printk(arg)
+
+struct lnbp22 {
+ u8 config[4];
+ struct i2c_adapter *i2c;
+};
+
+static int lnbp22_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+ struct lnbp22 *lnbp22 = (struct lnbp22 *)fe->sec_priv;
+ struct i2c_msg msg = {
+ .addr = 0x08,
+ .flags = 0,
+ .buf = (char *)&lnbp22->config,
+ .len = sizeof(lnbp22->config),
+ };
+
+ dprintk(1, "%s: %d (18V=%d 13V=%d)\n", __func__, voltage,
+ SEC_VOLTAGE_18, SEC_VOLTAGE_13);
+
+ lnbp22->config[3] = 0x60; /* Power down */
+ switch (voltage) {
+ case SEC_VOLTAGE_OFF:
+ break;
+ case SEC_VOLTAGE_13:
+ lnbp22->config[3] |= LNBP22_EN;
+ break;
+ case SEC_VOLTAGE_18:
+ lnbp22->config[3] |= (LNBP22_EN | LNBP22_VSEL);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]);
+ return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int lnbp22_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+ struct lnbp22 *lnbp22 = (struct lnbp22 *) fe->sec_priv;
+ struct i2c_msg msg = {
+ .addr = 0x08,
+ .flags = 0,
+ .buf = (char *)&lnbp22->config,
+ .len = sizeof(lnbp22->config),
+ };
+
+ dprintk(1, "%s: %d\n", __func__, (int)arg);
+ if (arg)
+ lnbp22->config[3] |= LNBP22_LLC;
+ else
+ lnbp22->config[3] &= ~LNBP22_LLC;
+
+ return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void lnbp22_release(struct dvb_frontend *fe)
+{
+ dprintk(1, "%s\n", __func__);
+ /* LNBP power off */
+ lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+ /* free data */
+ kfree(fe->sec_priv);
+ fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c)
+{
+ struct lnbp22 *lnbp22 = kmalloc(sizeof(struct lnbp22), GFP_KERNEL);
+ if (!lnbp22)
+ return NULL;
+
+ /* default configuration */
+ lnbp22->config[0] = 0x00; /* ? */
+ lnbp22->config[1] = 0x28; /* ? */
+ lnbp22->config[2] = 0x48; /* ? */
+ lnbp22->config[3] = 0x60; /* Power down */
+ lnbp22->i2c = i2c;
+ fe->sec_priv = lnbp22;
+
+ /* detect if it is present or not */
+ if (lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+ dprintk(0, "%s LNBP22 not found\n", __func__);
+ kfree(lnbp22);
+ fe->sec_priv = NULL;
+ return NULL;
+ }
+
+ /* install release callback */
+ fe->ops.release_sec = lnbp22_release;
+
+ /* override frontend ops */
+ fe->ops.set_voltage = lnbp22_set_voltage;
+ fe->ops.enable_high_lnb_voltage = lnbp22_enable_high_lnb_voltage;
+
+ return fe;
+}
+EXPORT_SYMBOL(lnbp22_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp22");
+MODULE_AUTHOR("Dominik Kuhlen");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/lnbp22.h b/drivers/media/dvb/frontends/lnbp22.h
new file mode 100644
index 000000000000..63e2dec7e68a
--- /dev/null
+++ b/drivers/media/dvb/frontends/lnbp22.h
@@ -0,0 +1,57 @@
+/*
+ * lnbp22.h - driver for lnb supply and control ic lnbp22
+ *
+ * Copyright (C) 2006 Dominik Kuhlen
+ * Based on lnbp21.h
+ *
+ * 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _LNBP22_H
+#define _LNBP22_H
+
+/* Enable */
+#define LNBP22_EN 0x10
+/* Voltage selection */
+#define LNBP22_VSEL 0x02
+/* Plus 1 Volt Bit */
+#define LNBP22_LLC 0x01
+
+#include <linux/dvb/frontend.h>
+
+#if defined(CONFIG_DVB_LNBP22) || \
+ (defined(CONFIG_DVB_LNBP22_MODULE) && defined(MODULE))
+/*
+ * override_set and override_clear control which system register bits (above)
+ * to always set & clear
+ */
+extern struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_LNBP22 */
+
+#endif /* _LNBP22_H */
diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c
index d70eee00f33a..117a56926dca 100644
--- a/drivers/media/dvb/frontends/stb0899_algo.c
+++ b/drivers/media/dvb/frontends/stb0899_algo.c
@@ -358,6 +358,9 @@ static enum stb0899_status stb0899_check_data(struct stb0899_state *state)
else
dataTime = 500;
+ /* clear previous failed END_LOOPVIT */
+ stb0899_read_reg(state, STB0899_VSTATUS);
+
stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop */
while (1) {
/* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP */
diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c
index 37a222d9ddb3..8408ef877b4b 100644
--- a/drivers/media/dvb/frontends/stb0899_drv.c
+++ b/drivers/media/dvb/frontends/stb0899_drv.c
@@ -706,7 +706,7 @@ static int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma
stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
for (i = 0; i < cmd->msg_len; i++) {
/* wait for FIFO empty */
- if (stb0899_wait_diseqc_fifo_empty(state, 10) < 0)
+ if (stb0899_wait_diseqc_fifo_empty(state, 100) < 0)
return -ETIMEDOUT;
stb0899_write_reg(state, STB0899_DISFIFO, cmd->msg[i]);
@@ -1426,9 +1426,9 @@ static void stb0899_set_iterations(struct stb0899_state *state)
if (iter_scale > config->ldpc_max_iter)
iter_scale = config->ldpc_max_iter;
- reg = STB0899_READ_S2REG(STB0899_S2DEMOD, MAX_ITER);
+ reg = STB0899_READ_S2REG(STB0899_S2FEC, MAX_ITER);
STB0899_SETFIELD_VAL(MAX_ITERATIONS, reg, iter_scale);
- stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
+ stb0899_write_s2reg(state, STB0899_S2FEC, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
}
static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c
index 8e0cfadba688..0aa3962ff18b 100644
--- a/drivers/media/dvb/frontends/stv0288.c
+++ b/drivers/media/dvb/frontends/stv0288.c
@@ -127,6 +127,11 @@ static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate)
if ((srate < 1000000) || (srate > 45000000))
return -EINVAL;
+ stv0288_writeregI(state, 0x22, 0);
+ stv0288_writeregI(state, 0x23, 0);
+ stv0288_writeregI(state, 0x2b, 0xff);
+ stv0288_writeregI(state, 0x2c, 0xf7);
+
temp = (unsigned int)srate / 1000;
temp = temp * 32768;
@@ -461,6 +466,7 @@ static int stv0288_set_frontend(struct dvb_frontend *fe,
char tm;
unsigned char tda[3];
+ u8 reg, time_out = 0;
dprintk("%s : FE_SET_FRONTEND\n", __func__);
@@ -488,22 +494,29 @@ static int stv0288_set_frontend(struct dvb_frontend *fe,
/* Carrier lock control register */
stv0288_writeregI(state, 0x15, 0xc5);
- tda[0] = 0x2b; /* CFRM */
tda[2] = 0x0; /* CFRL */
- for (tm = -6; tm < 7;) {
+ for (tm = -9; tm < 7;) {
/* Viterbi status */
- if (stv0288_readreg(state, 0x24) & 0x8)
- break;
-
- tda[2] += 40;
- if (tda[2] < 40)
+ reg = stv0288_readreg(state, 0x24);
+ if (reg & 0x8)
+ break;
+ if (reg & 0x80) {
+ time_out++;
+ if (time_out > 10)
+ break;
+ tda[2] += 40;
+ if (tda[2] < 40)
+ tm++;
+ } else {
tm++;
+ tda[2] = 0;
+ time_out = 0;
+ }
tda[1] = (unsigned char)tm;
stv0288_writeregI(state, 0x2b, tda[1]);
stv0288_writeregI(state, 0x2c, tda[2]);
udelay(30);
}
-
state->tuner_frequency = c->frequency;
state->fec_inner = FEC_AUTO;
state->symbol_rate = c->symbol_rate;
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
index 52d8712411e5..ebda41936b90 100644
--- a/drivers/media/dvb/frontends/stv090x.c
+++ b/drivers/media/dvb/frontends/stv090x.c
@@ -3463,9 +3463,15 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron
static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct stv090x_state *state = fe->demodulator_priv;
- u32 reg;
+ u32 reg, dstatus;
u8 search_state;
+ *status = 0;
+
+ dstatus = STV090x_READ_DEMOD(state, DSTATUS);
+ if (STV090x_GETFIELD_Px(dstatus, CAR_LOCK_FIELD))
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
reg = STV090x_READ_DEMOD(state, DMDSTATE);
search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
@@ -3474,41 +3480,30 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
case 1: /* first PLH detected */
default:
dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
- *status = 0;
break;
case 2: /* DVB-S2 mode */
dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2");
- reg = STV090x_READ_DEMOD(state, DSTATUS);
- if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+ if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) {
+ *status |= FE_HAS_VITERBI;
reg = STV090x_READ_DEMOD(state, TSSTATUS);
- if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
- *status = FE_HAS_SIGNAL |
- FE_HAS_CARRIER |
- FE_HAS_VITERBI |
- FE_HAS_SYNC |
- FE_HAS_LOCK;
- }
+ if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
}
}
break;
case 3: /* DVB-S1/legacy mode */
dprintk(FE_DEBUG, 1, "Delivery system: DVB-S");
- reg = STV090x_READ_DEMOD(state, DSTATUS);
- if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+ if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
+ *status |= FE_HAS_VITERBI;
reg = STV090x_READ_DEMOD(state, TSSTATUS);
- if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
- *status = FE_HAS_SIGNAL |
- FE_HAS_CARRIER |
- FE_HAS_VITERBI |
- FE_HAS_SYNC |
- FE_HAS_LOCK;
- }
+ if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
}
}
break;
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
index 93f6a75c238e..7f105946a434 100644
--- a/drivers/media/dvb/frontends/tda10048.c
+++ b/drivers/media/dvb/frontends/tda10048.c
@@ -206,15 +206,16 @@ static struct init_tab {
static struct pll_tab {
u32 clk_freq_khz;
u32 if_freq_khz;
- u8 m, n, p;
} pll_tab[] = {
- { TDA10048_CLK_4000, TDA10048_IF_36130, 10, 0, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_3300, 10, 3, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_3500, 10, 3, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_3800, 10, 3, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 },
- { TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 },
+ { TDA10048_CLK_4000, TDA10048_IF_36130 },
+ { TDA10048_CLK_16000, TDA10048_IF_3300 },
+ { TDA10048_CLK_16000, TDA10048_IF_3500 },
+ { TDA10048_CLK_16000, TDA10048_IF_3800 },
+ { TDA10048_CLK_16000, TDA10048_IF_4000 },
+ { TDA10048_CLK_16000, TDA10048_IF_4300 },
+ { TDA10048_CLK_16000, TDA10048_IF_4500 },
+ { TDA10048_CLK_16000, TDA10048_IF_5000 },
+ { TDA10048_CLK_16000, TDA10048_IF_36130 },
};
static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
@@ -460,9 +461,6 @@ static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw)
state->freq_if_hz = pll_tab[i].if_freq_khz * 1000;
state->xtal_hz = pll_tab[i].clk_freq_khz * 1000;
- state->pll_mfactor = pll_tab[i].m;
- state->pll_nfactor = pll_tab[i].n;
- state->pll_pfactor = pll_tab[i].p;
break;
}
}
@@ -781,6 +779,10 @@ static int tda10048_init(struct dvb_frontend *fe)
dprintk(1, "%s()\n", __func__);
+ /* PLL */
+ init_tab[4].data = (u8)(state->pll_mfactor);
+ init_tab[5].data = (u8)(state->pll_nfactor) | 0x40;
+
/* Apply register defaults */
for (i = 0; i < ARRAY_SIZE(init_tab); i++)
tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
@@ -1123,7 +1125,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
/* setup the state and clone the config */
memcpy(&state->config, config, sizeof(*config));
state->i2c = i2c;
- state->fwloaded = 0;
+ state->fwloaded = config->no_firmware;
state->bandwidth = BANDWIDTH_8_MHZ;
/* check if the demod is present */
@@ -1135,6 +1137,17 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
+ /* set pll */
+ if (config->set_pll) {
+ state->pll_mfactor = config->pll_m;
+ state->pll_nfactor = config->pll_n;
+ state->pll_pfactor = config->pll_p;
+ } else {
+ state->pll_mfactor = 10;
+ state->pll_nfactor = 3;
+ state->pll_pfactor = 0;
+ }
+
/* Establish any defaults the the user didn't pass */
tda10048_establish_defaults(&state->frontend);
diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
index 8828ceaf74bb..fb2ef5ac9487 100644
--- a/drivers/media/dvb/frontends/tda10048.h
+++ b/drivers/media/dvb/frontends/tda10048.h
@@ -51,6 +51,7 @@ struct tda10048_config {
#define TDA10048_IF_4300 4300
#define TDA10048_IF_4500 4500
#define TDA10048_IF_4750 4750
+#define TDA10048_IF_5000 5000
#define TDA10048_IF_36130 36130
u16 dtv6_if_freq_khz;
u16 dtv7_if_freq_khz;
@@ -62,6 +63,13 @@ struct tda10048_config {
/* Disable I2C gate access */
u8 disable_gate_access;
+
+ bool no_firmware;
+
+ bool set_pll;
+ u8 pll_m;
+ u8 pll_p;
+ u8 pll_n;
};
#if defined(CONFIG_DVB_TDA10048) || \
diff --git a/drivers/media/dvb/frontends/tda10071.c b/drivers/media/dvb/frontends/tda10071.c
new file mode 100644
index 000000000000..0c37434d19e2
--- /dev/null
+++ b/drivers/media/dvb/frontends/tda10071.c
@@ -0,0 +1,1269 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 "tda10071_priv.h"
+
+int tda10071_debug;
+module_param_named(debug, tda10071_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+static struct dvb_frontend_ops tda10071_ops;
+
+/* write multiple registers */
+static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
+ int len)
+{
+ int ret;
+ u8 buf[len+1];
+ struct i2c_msg msg[1] = {
+ {
+ .addr = priv->cfg.i2c_address,
+ .flags = 0,
+ .len = sizeof(buf),
+ .buf = buf,
+ }
+ };
+
+ buf[0] = reg;
+ memcpy(&buf[1], val, len);
+
+ ret = i2c_transfer(priv->i2c, msg, 1);
+ if (ret == 1) {
+ ret = 0;
+ } else {
+ warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
+ ret = -EREMOTEIO;
+ }
+ return ret;
+}
+
+/* read multiple registers */
+static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
+ int len)
+{
+ int ret;
+ u8 buf[len];
+ struct i2c_msg msg[2] = {
+ {
+ .addr = priv->cfg.i2c_address,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg,
+ }, {
+ .addr = priv->cfg.i2c_address,
+ .flags = I2C_M_RD,
+ .len = sizeof(buf),
+ .buf = buf,
+ }
+ };
+
+ ret = i2c_transfer(priv->i2c, msg, 2);
+ if (ret == 2) {
+ memcpy(val, buf, len);
+ ret = 0;
+ } else {
+ warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
+ ret = -EREMOTEIO;
+ }
+ return ret;
+}
+
+/* write single register */
+static int tda10071_wr_reg(struct tda10071_priv *priv, u8 reg, u8 val)
+{
+ return tda10071_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int tda10071_rd_reg(struct tda10071_priv *priv, u8 reg, u8 *val)
+{
+ return tda10071_rd_regs(priv, reg, val, 1);
+}
+
+/* write single register with mask */
+int tda10071_wr_reg_mask(struct tda10071_priv *priv, u8 reg, u8 val, u8 mask)
+{
+ int ret;
+ u8 tmp;
+
+ /* no need for read if whole reg is written */
+ if (mask != 0xff) {
+ ret = tda10071_rd_regs(priv, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ val &= mask;
+ tmp &= ~mask;
+ val |= tmp;
+ }
+
+ return tda10071_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register with mask */
+int tda10071_rd_reg_mask(struct tda10071_priv *priv, u8 reg, u8 *val, u8 mask)
+{
+ int ret, i;
+ u8 tmp;
+
+ ret = tda10071_rd_regs(priv, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ tmp &= mask;
+
+ /* find position of the first bit */
+ for (i = 0; i < 8; i++) {
+ if ((mask >> i) & 0x01)
+ break;
+ }
+ *val = tmp >> i;
+
+ return 0;
+}
+
+/* execute firmware command */
+static int tda10071_cmd_execute(struct tda10071_priv *priv,
+ struct tda10071_cmd *cmd)
+{
+ int ret, i;
+ u8 tmp;
+
+ if (!priv->warm) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ /* write cmd and args for firmware */
+ ret = tda10071_wr_regs(priv, 0x00, cmd->args, cmd->len);
+ if (ret)
+ goto error;
+
+ /* start cmd execution */
+ ret = tda10071_wr_reg(priv, 0x1f, 1);
+ if (ret)
+ goto error;
+
+ /* wait cmd execution terminate */
+ for (i = 1000, tmp = 1; i && tmp; i--) {
+ ret = tda10071_rd_reg(priv, 0x1f, &tmp);
+ if (ret)
+ goto error;
+
+ usleep_range(200, 5000);
+ }
+
+ dbg("%s: loop=%d", __func__, i);
+
+ if (i == 0) {
+ ret = -ETIMEDOUT;
+ goto error;
+ }
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_set_tone(struct dvb_frontend *fe,
+ fe_sec_tone_mode_t fe_sec_tone_mode)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct tda10071_cmd cmd;
+ int ret;
+ u8 tone;
+
+ if (!priv->warm) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ dbg("%s: tone_mode=%d", __func__, fe_sec_tone_mode);
+
+ switch (fe_sec_tone_mode) {
+ case SEC_TONE_ON:
+ tone = 1;
+ break;
+ case SEC_TONE_OFF:
+ tone = 0;
+ break;
+ default:
+ dbg("%s: invalid fe_sec_tone_mode", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ cmd.args[0x00] = CMD_LNB_PCB_CONFIG;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = 0x00;
+ cmd.args[0x03] = 0x00;
+ cmd.args[0x04] = tone;
+ cmd.len = 0x05;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_set_voltage(struct dvb_frontend *fe,
+ fe_sec_voltage_t fe_sec_voltage)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct tda10071_cmd cmd;
+ int ret;
+ u8 voltage;
+
+ if (!priv->warm) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ dbg("%s: voltage=%d", __func__, fe_sec_voltage);
+
+ switch (fe_sec_voltage) {
+ case SEC_VOLTAGE_13:
+ voltage = 0;
+ break;
+ case SEC_VOLTAGE_18:
+ voltage = 1;
+ break;
+ case SEC_VOLTAGE_OFF:
+ voltage = 0;
+ break;
+ default:
+ dbg("%s: invalid fe_sec_voltage", __func__);
+ ret = -EINVAL;
+ goto error;
+ };
+
+ cmd.args[0x00] = CMD_LNB_SET_DC_LEVEL;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = voltage;
+ cmd.len = 0x03;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *diseqc_cmd)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct tda10071_cmd cmd;
+ int ret, i;
+ u8 tmp;
+
+ if (!priv->warm) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ dbg("%s: msg_len=%d", __func__, diseqc_cmd->msg_len);
+
+ if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 16) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* wait LNB TX */
+ for (i = 500, tmp = 0; i && !tmp; i--) {
+ ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01);
+ if (ret)
+ goto error;
+
+ usleep_range(10000, 20000);
+ }
+
+ dbg("%s: loop=%d", __func__, i);
+
+ if (i == 0) {
+ ret = -ETIMEDOUT;
+ goto error;
+ }
+
+ ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01);
+ if (ret)
+ goto error;
+
+ cmd.args[0x00] = CMD_LNB_SEND_DISEQC;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = 0;
+ cmd.args[0x03] = 0;
+ cmd.args[0x04] = 2;
+ cmd.args[0x05] = 0;
+ cmd.args[0x06] = diseqc_cmd->msg_len;
+ memcpy(&cmd.args[0x07], diseqc_cmd->msg, diseqc_cmd->msg_len);
+ cmd.len = 0x07 + diseqc_cmd->msg_len;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
+ struct dvb_diseqc_slave_reply *reply)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct tda10071_cmd cmd;
+ int ret, i;
+ u8 tmp;
+
+ if (!priv->warm) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ dbg("%s:", __func__);
+
+ /* wait LNB RX */
+ for (i = 500, tmp = 0; i && !tmp; i--) {
+ ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x02);
+ if (ret)
+ goto error;
+
+ usleep_range(10000, 20000);
+ }
+
+ dbg("%s: loop=%d", __func__, i);
+
+ if (i == 0) {
+ ret = -ETIMEDOUT;
+ goto error;
+ }
+
+ /* reply len */
+ ret = tda10071_rd_reg(priv, 0x46, &tmp);
+ if (ret)
+ goto error;
+
+ reply->msg_len = tmp & 0x1f; /* [4:0] */;
+ if (reply->msg_len > sizeof(reply->msg))
+ reply->msg_len = sizeof(reply->msg); /* truncate API max */
+
+ /* read reply */
+ cmd.args[0x00] = CMD_LNB_UPDATE_REPLY;
+ cmd.args[0x01] = 0;
+ cmd.len = 0x02;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ ret = tda10071_rd_regs(priv, cmd.len, reply->msg, reply->msg_len);
+ if (ret)
+ goto error;
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
+ fe_sec_mini_cmd_t fe_sec_mini_cmd)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct tda10071_cmd cmd;
+ int ret, i;
+ u8 tmp, burst;
+
+ if (!priv->warm) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ dbg("%s: fe_sec_mini_cmd=%d", __func__, fe_sec_mini_cmd);
+
+ switch (fe_sec_mini_cmd) {
+ case SEC_MINI_A:
+ burst = 0;
+ break;
+ case SEC_MINI_B:
+ burst = 1;
+ break;
+ default:
+ dbg("%s: invalid fe_sec_mini_cmd", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* wait LNB TX */
+ for (i = 500, tmp = 0; i && !tmp; i--) {
+ ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01);
+ if (ret)
+ goto error;
+
+ usleep_range(10000, 20000);
+ }
+
+ dbg("%s: loop=%d", __func__, i);
+
+ if (i == 0) {
+ ret = -ETIMEDOUT;
+ goto error;
+ }
+
+ ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01);
+ if (ret)
+ goto error;
+
+ cmd.args[0x00] = CMD_LNB_SEND_TONEBURST;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = burst;
+ cmd.len = 0x03;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ int ret;
+ u8 tmp;
+
+ *status = 0;
+
+ if (!priv->warm) {
+ ret = 0;
+ goto error;
+ }
+
+ ret = tda10071_rd_reg(priv, 0x39, &tmp);
+ if (ret)
+ goto error;
+
+ if (tmp & 0x01) /* tuner PLL */
+ *status |= FE_HAS_SIGNAL;
+ if (tmp & 0x02) /* demod PLL */
+ *status |= FE_HAS_CARRIER;
+ if (tmp & 0x04) /* viterbi or LDPC*/
+ *status |= FE_HAS_VITERBI;
+ if (tmp & 0x08) /* RS or BCH */
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+ priv->fe_status = *status;
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ int ret;
+ u8 buf[2];
+
+ if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+ *snr = 0;
+ ret = 0;
+ goto error;
+ }
+
+ ret = tda10071_rd_regs(priv, 0x3a, buf, 2);
+ if (ret)
+ goto error;
+
+ /* Es/No dBx10 */
+ *snr = buf[0] << 8 | buf[1];
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct tda10071_cmd cmd;
+ int ret;
+ u8 tmp;
+
+ if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+ *strength = 0;
+ ret = 0;
+ goto error;
+ }
+
+ cmd.args[0x00] = CMD_GET_AGCACC;
+ cmd.args[0x01] = 0;
+ cmd.len = 0x02;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ /* input power estimate dBm */
+ ret = tda10071_rd_reg(priv, 0x50, &tmp);
+ if (ret)
+ goto error;
+
+ if (tmp < 181)
+ tmp = 181; /* -75 dBm */
+ else if (tmp > 236)
+ tmp = 236; /* -20 dBm */
+
+ /* scale value to 0x0000-0xffff */
+ *strength = (tmp-181) * 0xffff / (236-181);
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct tda10071_cmd cmd;
+ int ret, i, len;
+ u8 tmp, reg, buf[8];
+
+ if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+ *ber = priv->ber = 0;
+ ret = 0;
+ goto error;
+ }
+
+ switch (priv->delivery_system) {
+ case SYS_DVBS:
+ reg = 0x4c;
+ len = 8;
+ i = 1;
+ break;
+ case SYS_DVBS2:
+ reg = 0x4d;
+ len = 4;
+ i = 0;
+ break;
+ default:
+ *ber = priv->ber = 0;
+ return 0;
+ }
+
+ ret = tda10071_rd_reg(priv, reg, &tmp);
+ if (ret)
+ goto error;
+
+ if (priv->meas_count[i] == tmp) {
+ dbg("%s: meas not ready=%02x", __func__, tmp);
+ *ber = priv->ber;
+ return 0;
+ } else {
+ priv->meas_count[i] = tmp;
+ }
+
+ cmd.args[0x00] = CMD_BER_UPDATE_COUNTERS;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = i;
+ cmd.len = 0x03;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ ret = tda10071_rd_regs(priv, cmd.len, buf, len);
+ if (ret)
+ goto error;
+
+ if (priv->delivery_system == SYS_DVBS) {
+ *ber = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ priv->ucb += (buf[4] << 8) | buf[5];
+ } else {
+ *ber = (buf[0] << 8) | buf[1];
+ }
+ priv->ber = *ber;
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ int ret = 0;
+
+ if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+ *ucblocks = 0;
+ goto error;
+ }
+
+ /* UCB is updated when BER is read. Assume BER is read anyway. */
+
+ *ucblocks = priv->ucb;
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct tda10071_cmd cmd;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ int ret, i;
+ u8 mode, rolloff, pilot, inversion, div;
+
+ dbg("%s: delivery_system=%d modulation=%d frequency=%d " \
+ "symbol_rate=%d inversion=%d pilot=%d rolloff=%d", __func__,
+ c->delivery_system, c->modulation, c->frequency,
+ c->symbol_rate, c->inversion, c->pilot, c->rolloff);
+
+ priv->delivery_system = SYS_UNDEFINED;
+
+ if (!priv->warm) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ switch (c->inversion) {
+ case INVERSION_OFF:
+ inversion = 1;
+ break;
+ case INVERSION_ON:
+ inversion = 0;
+ break;
+ case INVERSION_AUTO:
+ /* 2 = auto; try first on then off
+ * 3 = auto; try first off then on */
+ inversion = 3;
+ break;
+ default:
+ dbg("%s: invalid inversion", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ switch (c->delivery_system) {
+ case SYS_DVBS:
+ rolloff = 0;
+ pilot = 2;
+ break;
+ case SYS_DVBS2:
+ switch (c->rolloff) {
+ case ROLLOFF_20:
+ rolloff = 2;
+ break;
+ case ROLLOFF_25:
+ rolloff = 1;
+ break;
+ case ROLLOFF_35:
+ rolloff = 0;
+ break;
+ case ROLLOFF_AUTO:
+ default:
+ dbg("%s: invalid rolloff", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ switch (c->pilot) {
+ case PILOT_OFF:
+ pilot = 0;
+ break;
+ case PILOT_ON:
+ pilot = 1;
+ break;
+ case PILOT_AUTO:
+ pilot = 2;
+ break;
+ default:
+ dbg("%s: invalid pilot", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ break;
+ default:
+ dbg("%s: invalid delivery_system", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ for (i = 0, mode = 0xff; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
+ if (c->delivery_system == TDA10071_MODCOD[i].delivery_system &&
+ c->modulation == TDA10071_MODCOD[i].modulation &&
+ c->fec_inner == TDA10071_MODCOD[i].fec) {
+ mode = TDA10071_MODCOD[i].val;
+ dbg("%s: mode found=%02x", __func__, mode);
+ break;
+ }
+ }
+
+ if (mode == 0xff) {
+ dbg("%s: invalid parameter combination", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (c->symbol_rate <= 5000000)
+ div = 14;
+ else
+ div = 4;
+
+ ret = tda10071_wr_reg(priv, 0x81, div);
+ if (ret)
+ goto error;
+
+ ret = tda10071_wr_reg(priv, 0xe3, div);
+ if (ret)
+ goto error;
+
+ cmd.args[0x00] = CMD_CHANGE_CHANNEL;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = mode;
+ cmd.args[0x03] = (c->frequency >> 16) & 0xff;
+ cmd.args[0x04] = (c->frequency >> 8) & 0xff;
+ cmd.args[0x05] = (c->frequency >> 0) & 0xff;
+ cmd.args[0x06] = ((c->symbol_rate / 1000) >> 8) & 0xff;
+ cmd.args[0x07] = ((c->symbol_rate / 1000) >> 0) & 0xff;
+ cmd.args[0x08] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff;
+ cmd.args[0x09] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff;
+ cmd.args[0x0a] = rolloff;
+ cmd.args[0x0b] = inversion;
+ cmd.args[0x0c] = pilot;
+ cmd.args[0x0d] = 0x00;
+ cmd.args[0x0e] = 0x00;
+ cmd.len = 0x0f;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ priv->delivery_system = c->delivery_system;
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ int ret, i;
+ u8 buf[5], tmp;
+
+ if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ ret = tda10071_rd_regs(priv, 0x30, buf, 5);
+ if (ret)
+ goto error;
+
+ tmp = buf[0] & 0x3f;
+ for (i = 0; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
+ if (tmp == TDA10071_MODCOD[i].val) {
+ c->modulation = TDA10071_MODCOD[i].modulation;
+ c->fec_inner = TDA10071_MODCOD[i].fec;
+ c->delivery_system = TDA10071_MODCOD[i].delivery_system;
+ }
+ }
+
+ switch ((buf[1] >> 0) & 0x01) {
+ case 0:
+ c->inversion = INVERSION_OFF;
+ break;
+ case 1:
+ c->inversion = INVERSION_ON;
+ break;
+ }
+
+ switch ((buf[1] >> 7) & 0x01) {
+ case 0:
+ c->pilot = PILOT_OFF;
+ break;
+ case 1:
+ c->pilot = PILOT_ON;
+ break;
+ }
+
+ c->frequency = (buf[2] << 16) | (buf[3] << 8) | (buf[4] << 0);
+
+ ret = tda10071_rd_regs(priv, 0x52, buf, 3);
+ if (ret)
+ goto error;
+
+ c->symbol_rate = (buf[0] << 16) | (buf[1] << 8) | (buf[2] << 0);
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_init(struct dvb_frontend *fe)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct tda10071_cmd cmd;
+ int ret, i, len, remaining, fw_size;
+ const struct firmware *fw;
+ u8 *fw_file = TDA10071_DEFAULT_FIRMWARE;
+ u8 tmp, buf[4];
+ struct tda10071_reg_val_mask tab[] = {
+ { 0xcd, 0x00, 0x07 },
+ { 0x80, 0x00, 0x02 },
+ { 0xcd, 0x00, 0xc0 },
+ { 0xce, 0x00, 0x1b },
+ { 0x9d, 0x00, 0x01 },
+ { 0x9d, 0x00, 0x02 },
+ { 0x9e, 0x00, 0x01 },
+ { 0x87, 0x00, 0x80 },
+ { 0xce, 0x00, 0x08 },
+ { 0xce, 0x00, 0x10 },
+ };
+ struct tda10071_reg_val_mask tab2[] = {
+ { 0xf1, 0x70, 0xff },
+ { 0x88, priv->cfg.pll_multiplier, 0x3f },
+ { 0x89, 0x00, 0x10 },
+ { 0x89, 0x10, 0x10 },
+ { 0xc0, 0x01, 0x01 },
+ { 0xc0, 0x00, 0x01 },
+ { 0xe0, 0xff, 0xff },
+ { 0xe0, 0x00, 0xff },
+ { 0x96, 0x1e, 0x7e },
+ { 0x8b, 0x08, 0x08 },
+ { 0x8b, 0x00, 0x08 },
+ { 0x8f, 0x1a, 0x7e },
+ { 0x8c, 0x68, 0xff },
+ { 0x8d, 0x08, 0xff },
+ { 0x8e, 0x4c, 0xff },
+ { 0x8f, 0x01, 0x01 },
+ { 0x8b, 0x04, 0x04 },
+ { 0x8b, 0x00, 0x04 },
+ { 0x87, 0x05, 0x07 },
+ { 0x80, 0x00, 0x20 },
+ { 0xc8, 0x01, 0xff },
+ { 0xb4, 0x47, 0xff },
+ { 0xb5, 0x9c, 0xff },
+ { 0xb6, 0x7d, 0xff },
+ { 0xba, 0x00, 0x03 },
+ { 0xb7, 0x47, 0xff },
+ { 0xb8, 0x9c, 0xff },
+ { 0xb9, 0x7d, 0xff },
+ { 0xba, 0x00, 0x0c },
+ { 0xc8, 0x00, 0xff },
+ { 0xcd, 0x00, 0x04 },
+ { 0xcd, 0x00, 0x20 },
+ { 0xe8, 0x02, 0xff },
+ { 0xcf, 0x20, 0xff },
+ { 0x9b, 0xd7, 0xff },
+ { 0x9a, 0x01, 0x03 },
+ { 0xa8, 0x05, 0x0f },
+ { 0xa8, 0x65, 0xf0 },
+ { 0xa6, 0xa0, 0xf0 },
+ { 0x9d, 0x50, 0xfc },
+ { 0x9e, 0x20, 0xe0 },
+ { 0xa3, 0x1c, 0x7c },
+ { 0xd5, 0x03, 0x03 },
+ };
+
+ /* firmware status */
+ ret = tda10071_rd_reg(priv, 0x51, &tmp);
+ if (ret)
+ goto error;
+
+ if (!tmp) {
+ /* warm state - wake up device from sleep */
+ priv->warm = 1;
+
+ for (i = 0; i < ARRAY_SIZE(tab); i++) {
+ ret = tda10071_wr_reg_mask(priv, tab[i].reg,
+ tab[i].val, tab[i].mask);
+ if (ret)
+ goto error;
+ }
+
+ cmd.args[0x00] = CMD_SET_SLEEP_MODE;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = 0;
+ cmd.len = 0x03;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+ } else {
+ /* cold state - try to download firmware */
+ priv->warm = 0;
+
+ /* request the firmware, this will block and timeout */
+ ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
+ if (ret) {
+ err("did not find the firmware file. (%s) "
+ "Please see linux/Documentation/dvb/ for more" \
+ " details on firmware-problems. (%d)",
+ fw_file, ret);
+ goto error;
+ }
+
+ /* init */
+ for (i = 0; i < ARRAY_SIZE(tab2); i++) {
+ ret = tda10071_wr_reg_mask(priv, tab2[i].reg,
+ tab2[i].val, tab2[i].mask);
+ if (ret)
+ goto error_release_firmware;
+ }
+
+ /* download firmware */
+ ret = tda10071_wr_reg(priv, 0xe0, 0x7f);
+ if (ret)
+ goto error_release_firmware;
+
+ ret = tda10071_wr_reg(priv, 0xf7, 0x81);
+ if (ret)
+ goto error_release_firmware;
+
+ ret = tda10071_wr_reg(priv, 0xf8, 0x00);
+ if (ret)
+ goto error_release_firmware;
+
+ ret = tda10071_wr_reg(priv, 0xf9, 0x00);
+ if (ret)
+ goto error_release_firmware;
+
+ info("found a '%s' in cold state, will try to load a firmware",
+ tda10071_ops.info.name);
+
+ info("downloading firmware from file '%s'", fw_file);
+
+ /* do not download last byte */
+ fw_size = fw->size - 1;
+
+ for (remaining = fw_size; remaining > 0;
+ remaining -= (priv->cfg.i2c_wr_max - 1)) {
+ len = remaining;
+ if (len > (priv->cfg.i2c_wr_max - 1))
+ len = (priv->cfg.i2c_wr_max - 1);
+
+ ret = tda10071_wr_regs(priv, 0xfa,
+ (u8 *) &fw->data[fw_size - remaining], len);
+ if (ret) {
+ err("firmware download failed=%d", ret);
+ if (ret)
+ goto error_release_firmware;
+ }
+ }
+ release_firmware(fw);
+
+ ret = tda10071_wr_reg(priv, 0xf7, 0x0c);
+ if (ret)
+ goto error;
+
+ ret = tda10071_wr_reg(priv, 0xe0, 0x00);
+ if (ret)
+ goto error;
+
+ /* wait firmware start */
+ msleep(250);
+
+ /* firmware status */
+ ret = tda10071_rd_reg(priv, 0x51, &tmp);
+ if (ret)
+ goto error;
+
+ if (tmp) {
+ info("firmware did not run");
+ ret = -EFAULT;
+ goto error;
+ } else {
+ priv->warm = 1;
+ }
+
+ cmd.args[0x00] = CMD_GET_FW_VERSION;
+ cmd.len = 0x01;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ ret = tda10071_rd_regs(priv, cmd.len, buf, 4);
+ if (ret)
+ goto error;
+
+ info("firmware version %d.%d.%d.%d",
+ buf[0], buf[1], buf[2], buf[3]);
+ info("found a '%s' in warm state.", tda10071_ops.info.name);
+
+ ret = tda10071_rd_regs(priv, 0x81, buf, 2);
+ if (ret)
+ goto error;
+
+ cmd.args[0x00] = CMD_DEMOD_INIT;
+ cmd.args[0x01] = ((priv->cfg.xtal / 1000) >> 8) & 0xff;
+ cmd.args[0x02] = ((priv->cfg.xtal / 1000) >> 0) & 0xff;
+ cmd.args[0x03] = buf[0];
+ cmd.args[0x04] = buf[1];
+ cmd.args[0x05] = priv->cfg.pll_multiplier;
+ cmd.args[0x06] = priv->cfg.spec_inv;
+ cmd.args[0x07] = 0x00;
+ cmd.len = 0x08;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ cmd.args[0x00] = CMD_TUNER_INIT;
+ cmd.args[0x01] = 0x00;
+ cmd.args[0x02] = 0x00;
+ cmd.args[0x03] = 0x00;
+ cmd.args[0x04] = 0x00;
+ cmd.args[0x05] = 0x14;
+ cmd.args[0x06] = 0x00;
+ cmd.args[0x07] = 0x03;
+ cmd.args[0x08] = 0x02;
+ cmd.args[0x09] = 0x02;
+ cmd.args[0x0a] = 0x00;
+ cmd.args[0x0b] = 0x00;
+ cmd.args[0x0c] = 0x00;
+ cmd.args[0x0d] = 0x00;
+ cmd.args[0x0e] = 0x00;
+ cmd.len = 0x0f;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ cmd.args[0x00] = CMD_MPEG_CONFIG;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = priv->cfg.ts_mode;
+ cmd.args[0x03] = 0x00;
+ cmd.args[0x04] = 0x04;
+ cmd.args[0x05] = 0x00;
+ cmd.len = 0x06;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ ret = tda10071_wr_reg_mask(priv, 0xf0, 0x01, 0x01);
+ if (ret)
+ goto error;
+
+ cmd.args[0x00] = CMD_LNB_CONFIG;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = 150;
+ cmd.args[0x03] = 3;
+ cmd.args[0x04] = 22;
+ cmd.args[0x05] = 1;
+ cmd.args[0x06] = 1;
+ cmd.args[0x07] = 30;
+ cmd.args[0x08] = 30;
+ cmd.args[0x09] = 30;
+ cmd.args[0x0a] = 30;
+ cmd.len = 0x0b;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ cmd.args[0x00] = CMD_BER_CONTROL;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = 14;
+ cmd.args[0x03] = 14;
+ cmd.len = 0x04;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+ }
+
+ return ret;
+error_release_firmware:
+ release_firmware(fw);
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_sleep(struct dvb_frontend *fe)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ struct tda10071_cmd cmd;
+ int ret, i;
+ struct tda10071_reg_val_mask tab[] = {
+ { 0xcd, 0x07, 0x07 },
+ { 0x80, 0x02, 0x02 },
+ { 0xcd, 0xc0, 0xc0 },
+ { 0xce, 0x1b, 0x1b },
+ { 0x9d, 0x01, 0x01 },
+ { 0x9d, 0x02, 0x02 },
+ { 0x9e, 0x01, 0x01 },
+ { 0x87, 0x80, 0x80 },
+ { 0xce, 0x08, 0x08 },
+ { 0xce, 0x10, 0x10 },
+ };
+
+ if (!priv->warm) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ cmd.args[0x00] = CMD_SET_SLEEP_MODE;
+ cmd.args[0x01] = 0;
+ cmd.args[0x02] = 1;
+ cmd.len = 0x03;
+ ret = tda10071_cmd_execute(priv, &cmd);
+ if (ret)
+ goto error;
+
+ for (i = 0; i < ARRAY_SIZE(tab); i++) {
+ ret = tda10071_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+ tab[i].mask);
+ if (ret)
+ goto error;
+ }
+
+ return ret;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int tda10071_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *s)
+{
+ s->min_delay_ms = 8000;
+ s->step_size = 0;
+ s->max_drift = 0;
+
+ return 0;
+}
+
+static void tda10071_release(struct dvb_frontend *fe)
+{
+ struct tda10071_priv *priv = fe->demodulator_priv;
+ kfree(priv);
+}
+
+struct dvb_frontend *tda10071_attach(const struct tda10071_config *config,
+ struct i2c_adapter *i2c)
+{
+ int ret;
+ struct tda10071_priv *priv = NULL;
+ u8 tmp;
+
+ /* allocate memory for the internal priv */
+ priv = kzalloc(sizeof(struct tda10071_priv), GFP_KERNEL);
+ if (priv == NULL) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ /* setup the priv */
+ priv->i2c = i2c;
+ memcpy(&priv->cfg, config, sizeof(struct tda10071_config));
+
+ /* chip ID */
+ ret = tda10071_rd_reg(priv, 0xff, &tmp);
+ if (ret || tmp != 0x0f)
+ goto error;
+
+ /* chip type */
+ ret = tda10071_rd_reg(priv, 0xdd, &tmp);
+ if (ret || tmp != 0x00)
+ goto error;
+
+ /* chip version */
+ ret = tda10071_rd_reg(priv, 0xfe, &tmp);
+ if (ret || tmp != 0x01)
+ goto error;
+
+ /* create dvb_frontend */
+ memcpy(&priv->fe.ops, &tda10071_ops, sizeof(struct dvb_frontend_ops));
+ priv->fe.demodulator_priv = priv;
+
+ return &priv->fe;
+error:
+ dbg("%s: failed=%d", __func__, ret);
+ kfree(priv);
+ return NULL;
+}
+EXPORT_SYMBOL(tda10071_attach);
+
+static struct dvb_frontend_ops tda10071_ops = {
+ .info = {
+ .name = "NXP TDA10071",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_tolerance = 5000,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_1_2 |
+ FE_CAN_FEC_2_3 |
+ FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_4_5 |
+ FE_CAN_FEC_5_6 |
+ FE_CAN_FEC_6_7 |
+ FE_CAN_FEC_7_8 |
+ FE_CAN_FEC_8_9 |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK |
+ FE_CAN_RECOVER |
+ FE_CAN_2G_MODULATION
+ },
+
+ .release = tda10071_release,
+
+ .get_tune_settings = tda10071_get_tune_settings,
+
+ .init = tda10071_init,
+ .sleep = tda10071_sleep,
+
+ .set_frontend = tda10071_set_frontend,
+ .get_frontend = tda10071_get_frontend,
+
+ .read_status = tda10071_read_status,
+ .read_snr = tda10071_read_snr,
+ .read_signal_strength = tda10071_read_signal_strength,
+ .read_ber = tda10071_read_ber,
+ .read_ucblocks = tda10071_read_ucblocks,
+
+ .diseqc_send_master_cmd = tda10071_diseqc_send_master_cmd,
+ .diseqc_recv_slave_reply = tda10071_diseqc_recv_slave_reply,
+ .diseqc_send_burst = tda10071_diseqc_send_burst,
+
+ .set_tone = tda10071_set_tone,
+ .set_voltage = tda10071_set_voltage,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda10071.h b/drivers/media/dvb/frontends/tda10071.h
new file mode 100644
index 000000000000..21163c4b555c
--- /dev/null
+++ b/drivers/media/dvb/frontends/tda10071.h
@@ -0,0 +1,81 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 TDA10071_H
+#define TDA10071_H
+
+#include <linux/dvb/frontend.h>
+
+struct tda10071_config {
+ /* Demodulator I2C address.
+ * Default: none, must set
+ * Values: 0x55,
+ */
+ u8 i2c_address;
+
+ /* Max bytes I2C provider can write at once.
+ * Note: Buffer is taken from the stack currently!
+ * Default: none, must set
+ * Values:
+ */
+ u16 i2c_wr_max;
+
+ /* TS output mode.
+ * Default: TDA10071_TS_SERIAL
+ * Values:
+ */
+#define TDA10071_TS_SERIAL 0
+#define TDA10071_TS_PARALLEL 1
+ u8 ts_mode;
+
+ /* Input spectrum inversion.
+ * Default: 0
+ * Values: 0, 1
+ */
+ bool spec_inv;
+
+ /* Xtal frequency Hz
+ * Default: none, must set
+ * Values:
+ */
+ u32 xtal;
+
+ /* PLL multiplier.
+ * Default: none, must set
+ * Values:
+ */
+ u8 pll_multiplier;
+};
+
+
+#if defined(CONFIG_DVB_TDA10071) || \
+ (defined(CONFIG_DVB_TDA10071_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10071_attach(
+ const struct tda10071_config *config, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *tda10071_attach(
+ const struct tda10071_config *config, struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
+#endif /* TDA10071_H */
diff --git a/drivers/media/dvb/frontends/tda10071_priv.h b/drivers/media/dvb/frontends/tda10071_priv.h
new file mode 100644
index 000000000000..93c5e6317f07
--- /dev/null
+++ b/drivers/media/dvb/frontends/tda10071_priv.h
@@ -0,0 +1,122 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 TDA10071_PRIV
+#define TDA10071_PRIV
+
+#include "dvb_frontend.h"
+#include "tda10071.h"
+#include <linux/firmware.h>
+
+#define LOG_PREFIX "tda10071"
+
+#undef dbg
+#define dbg(f, arg...) \
+ if (tda10071_debug) \
+ printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+struct tda10071_priv {
+ struct i2c_adapter *i2c;
+ struct dvb_frontend fe;
+ struct tda10071_config cfg;
+
+ u8 meas_count[2];
+ u32 ber;
+ u32 ucb;
+ fe_status_t fe_status;
+ fe_delivery_system_t delivery_system;
+ bool warm; /* FW running */
+};
+
+static struct tda10071_modcod {
+ fe_delivery_system_t delivery_system;
+ fe_modulation_t modulation;
+ fe_code_rate_t fec;
+ u8 val;
+} TDA10071_MODCOD[] = {
+ /* NBC-QPSK */
+ { SYS_DVBS2, QPSK, FEC_AUTO, 0x00 },
+ { SYS_DVBS2, QPSK, FEC_1_2, 0x04 },
+ { SYS_DVBS2, QPSK, FEC_3_5, 0x05 },
+ { SYS_DVBS2, QPSK, FEC_2_3, 0x06 },
+ { SYS_DVBS2, QPSK, FEC_3_4, 0x07 },
+ { SYS_DVBS2, QPSK, FEC_4_5, 0x08 },
+ { SYS_DVBS2, QPSK, FEC_5_6, 0x09 },
+ { SYS_DVBS2, QPSK, FEC_8_9, 0x0a },
+ { SYS_DVBS2, QPSK, FEC_9_10, 0x0b },
+ /* 8PSK */
+ { SYS_DVBS2, PSK_8, FEC_3_5, 0x0c },
+ { SYS_DVBS2, PSK_8, FEC_2_3, 0x0d },
+ { SYS_DVBS2, PSK_8, FEC_3_4, 0x0e },
+ { SYS_DVBS2, PSK_8, FEC_5_6, 0x0f },
+ { SYS_DVBS2, PSK_8, FEC_8_9, 0x10 },
+ { SYS_DVBS2, PSK_8, FEC_9_10, 0x11 },
+ /* QPSK */
+ { SYS_DVBS, QPSK, FEC_AUTO, 0x2d },
+ { SYS_DVBS, QPSK, FEC_1_2, 0x2e },
+ { SYS_DVBS, QPSK, FEC_2_3, 0x2f },
+ { SYS_DVBS, QPSK, FEC_3_4, 0x30 },
+ { SYS_DVBS, QPSK, FEC_5_6, 0x31 },
+ { SYS_DVBS, QPSK, FEC_7_8, 0x32 },
+};
+
+struct tda10071_reg_val_mask {
+ u8 reg;
+ u8 val;
+ u8 mask;
+};
+
+/* firmware filename */
+#define TDA10071_DEFAULT_FIRMWARE "dvb-fe-tda10071.fw"
+
+/* firmware commands */
+#define CMD_DEMOD_INIT 0x10
+#define CMD_CHANGE_CHANNEL 0x11
+#define CMD_MPEG_CONFIG 0x13
+#define CMD_TUNER_INIT 0x15
+#define CMD_GET_AGCACC 0x1a
+
+#define CMD_LNB_CONFIG 0x20
+#define CMD_LNB_SEND_DISEQC 0x21
+#define CMD_LNB_SET_DC_LEVEL 0x22
+#define CMD_LNB_PCB_CONFIG 0x23
+#define CMD_LNB_SEND_TONEBURST 0x24
+#define CMD_LNB_UPDATE_REPLY 0x25
+
+#define CMD_GET_FW_VERSION 0x35
+#define CMD_SET_SLEEP_MODE 0x36
+#define CMD_BER_CONTROL 0x3e
+#define CMD_BER_UPDATE_COUNTERS 0x3f
+
+/* firmare command struct */
+#define TDA10071_ARGLEN 0x1e
+struct tda10071_cmd {
+ u8 args[TDA10071_ARGLEN];
+ u8 len;
+};
+
+
+#endif /* TDA10071_PRIV */
diff --git a/drivers/media/dvb/frontends/tda18271c2dd.c b/drivers/media/dvb/frontends/tda18271c2dd.c
index 0384e8da4f5e..1b1bf200c55c 100644
--- a/drivers/media/dvb/frontends/tda18271c2dd.c
+++ b/drivers/media/dvb/frontends/tda18271c2dd.c
@@ -1195,7 +1195,7 @@ static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
}
#endif
-static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
+static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct tda_state *state = fe->tuner_priv;
@@ -1222,7 +1222,7 @@ static struct dvb_tuner_ops tuner_ops = {
.sleep = sleep,
.set_params = set_params,
.release = release,
- .get_frequency = get_frequency,
+ .get_if_frequency = get_if_frequency,
.get_bandwidth = get_bandwidth,
};
diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile
index 98dc5cd258ac..ec8116dcb368 100644
--- a/drivers/media/dvb/mantis/Makefile
+++ b/drivers/media/dvb/mantis/Makefile
@@ -25,4 +25,4 @@ obj-$(CONFIG_MANTIS_CORE) += mantis_core.o
obj-$(CONFIG_DVB_MANTIS) += mantis.o
obj-$(CONFIG_DVB_HOPPER) += hopper.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c
index 1402062f2c89..71622f65c037 100644
--- a/drivers/media/dvb/mantis/hopper_cards.c
+++ b/drivers/media/dvb/mantis/hopper_cards.c
@@ -65,7 +65,7 @@ static int devs;
static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
{
- u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
+ u32 stat = 0, mask = 0, lstat = 0;
u32 rst_stat = 0, rst_mask = 0;
struct mantis_pci *mantis;
@@ -80,7 +80,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
stat = mmread(MANTIS_INT_STAT);
mask = mmread(MANTIS_INT_MASK);
- mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
+ lstat = stat & ~MANTIS_INT_RISCSTAT;
if (!(stat & mask))
return IRQ_NONE;
@@ -126,7 +126,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
}
if (stat & MANTIS_INT_RISCI) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
- mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+ mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
tasklet_schedule(&mantis->tasklet);
}
if (stat & MANTIS_INT_I2CDONE) {
diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c
index 05cbb9d95727..c2bb90b3e529 100644
--- a/drivers/media/dvb/mantis/mantis_cards.c
+++ b/drivers/media/dvb/mantis/mantis_cards.c
@@ -73,7 +73,7 @@ static char *label[10] = {
static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
{
- u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
+ u32 stat = 0, mask = 0, lstat = 0;
u32 rst_stat = 0, rst_mask = 0;
struct mantis_pci *mantis;
@@ -88,7 +88,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
stat = mmread(MANTIS_INT_STAT);
mask = mmread(MANTIS_INT_MASK);
- mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
+ lstat = stat & ~MANTIS_INT_RISCSTAT;
if (!(stat & mask))
return IRQ_NONE;
@@ -134,7 +134,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
}
if (stat & MANTIS_INT_RISCI) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
- mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+ mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
tasklet_schedule(&mantis->tasklet);
}
if (stat & MANTIS_INT_I2CDONE) {
diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h
index 49dbca145bb8..f2410cf0a6bf 100644
--- a/drivers/media/dvb/mantis/mantis_common.h
+++ b/drivers/media/dvb/mantis/mantis_common.h
@@ -123,11 +123,8 @@ struct mantis_pci {
unsigned int num;
/* RISC Core */
- u32 finished_block;
+ u32 busy_block;
u32 last_block;
- u32 line_bytes;
- u32 line_count;
- u32 risc_pos;
u8 *buf_cpu;
dma_addr_t buf_dma;
u32 *risc_cpu;
diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c
index 46202a4012aa..c61ca7d3daea 100644
--- a/drivers/media/dvb/mantis/mantis_dma.c
+++ b/drivers/media/dvb/mantis/mantis_dma.c
@@ -43,13 +43,17 @@
#define RISC_IRQ (0x01 << 24)
#define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16))
-#define RISC_FLUSH() (mantis->risc_pos = 0)
-#define RISC_INSTR(opcode) (mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode))
+#define RISC_FLUSH(risc_pos) (risc_pos = 0)
+#define RISC_INSTR(risc_pos, opcode) (mantis->risc_cpu[risc_pos++] = cpu_to_le32(opcode))
#define MANTIS_BUF_SIZE (64 * 1024)
-#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4)
-#define MANTIS_BLOCK_COUNT (1 << 4)
-#define MANTIS_RISC_SIZE PAGE_SIZE
+#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE / 4)
+#define MANTIS_DMA_TR_BYTES (2 * 1024) /* upper limit: 4095 bytes. */
+#define MANTIS_BLOCK_COUNT (MANTIS_BUF_SIZE / MANTIS_BLOCK_BYTES)
+
+#define MANTIS_DMA_TR_UNITS (MANTIS_BLOCK_BYTES / MANTIS_DMA_TR_BYTES)
+/* MANTIS_BUF_SIZE / MANTIS_DMA_TR_UNITS must not exceed MANTIS_RISC_SIZE (4k RISC cmd buffer) */
+#define MANTIS_RISC_SIZE PAGE_SIZE /* RISC program must fit here. */
int mantis_dma_exit(struct mantis_pci *mantis)
{
@@ -124,27 +128,6 @@ err:
return -ENOMEM;
}
-static inline int mantis_calc_lines(struct mantis_pci *mantis)
-{
- mantis->line_bytes = MANTIS_BLOCK_BYTES;
- mantis->line_count = MANTIS_BLOCK_COUNT;
-
- while (mantis->line_bytes > 4095) {
- mantis->line_bytes >>= 1;
- mantis->line_count <<= 1;
- }
-
- dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]",
- MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count);
-
- if (mantis->line_count > 255) {
- dprintk(MANTIS_ERROR, 1, "Buffer size error");
- return -EINVAL;
- }
-
- return 0;
-}
-
int mantis_dma_init(struct mantis_pci *mantis)
{
int err = 0;
@@ -158,12 +141,6 @@ int mantis_dma_init(struct mantis_pci *mantis)
goto err;
}
- err = mantis_calc_lines(mantis);
- if (err < 0) {
- dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed");
-
- goto err;
- }
return 0;
err:
@@ -174,31 +151,32 @@ EXPORT_SYMBOL_GPL(mantis_dma_init);
static inline void mantis_risc_program(struct mantis_pci *mantis)
{
u32 buf_pos = 0;
- u32 line;
+ u32 line, step;
+ u32 risc_pos;
dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program");
- RISC_FLUSH();
-
- dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u",
- mantis->line_count, mantis->line_bytes);
-
- for (line = 0; line < mantis->line_count; line++) {
- dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line);
- if (!(buf_pos % MANTIS_BLOCK_BYTES)) {
- RISC_INSTR(RISC_WRITE |
- RISC_IRQ |
- RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) +
- (MANTIS_BLOCK_COUNT - 1)) %
- MANTIS_BLOCK_COUNT) |
- mantis->line_bytes);
- } else {
- RISC_INSTR(RISC_WRITE | mantis->line_bytes);
- }
- RISC_INSTR(mantis->buf_dma + buf_pos);
- buf_pos += mantis->line_bytes;
+ RISC_FLUSH(risc_pos);
+
+ dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u, bytes per DMA tr %u",
+ MANTIS_BLOCK_COUNT, MANTIS_BLOCK_BYTES, MANTIS_DMA_TR_BYTES);
+
+ for (line = 0; line < MANTIS_BLOCK_COUNT; line++) {
+ for (step = 0; step < MANTIS_DMA_TR_UNITS; step++) {
+ dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d], step=[%d]", line, step);
+ if (step == 0) {
+ RISC_INSTR(risc_pos, RISC_WRITE |
+ RISC_IRQ |
+ RISC_STATUS(line) |
+ MANTIS_DMA_TR_BYTES);
+ } else {
+ RISC_INSTR(risc_pos, RISC_WRITE | MANTIS_DMA_TR_BYTES);
+ }
+ RISC_INSTR(risc_pos, mantis->buf_dma + buf_pos);
+ buf_pos += MANTIS_DMA_TR_BYTES;
+ }
}
- RISC_INSTR(RISC_JUMP);
- RISC_INSTR(mantis->risc_dma);
+ RISC_INSTR(risc_pos, RISC_JUMP);
+ RISC_INSTR(risc_pos, mantis->risc_dma);
}
void mantis_dma_start(struct mantis_pci *mantis)
@@ -210,7 +188,7 @@ void mantis_dma_start(struct mantis_pci *mantis)
mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
mmwrite(0, MANTIS_DMA_CTL);
- mantis->last_block = mantis->finished_block = 0;
+ mantis->last_block = mantis->busy_block = 0;
mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);
@@ -245,9 +223,9 @@ void mantis_dma_xfer(unsigned long data)
struct mantis_pci *mantis = (struct mantis_pci *) data;
struct mantis_hwconfig *config = mantis->hwconfig;
- while (mantis->last_block != mantis->finished_block) {
+ while (mantis->last_block != mantis->busy_block) {
dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]",
- mantis->last_block, mantis->finished_block);
+ mantis->last_block, mantis->busy_block);
(config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
(&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES);
diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c
index 38a436ca2fdf..07aa887a4b4a 100644
--- a/drivers/media/dvb/mantis/mantis_vp1041.c
+++ b/drivers/media/dvb/mantis/mantis_vp1041.c
@@ -51,7 +51,6 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = {
{ STB0899_DISRX_ST0 , 0x04 },
{ STB0899_DISRX_ST1 , 0x00 },
{ STB0899_DISPARITY , 0x00 },
- { STB0899_DISFIFO , 0x00 },
{ STB0899_DISSTATUS , 0x20 },
{ STB0899_DISF22 , 0x99 },
{ STB0899_DISF22RX , 0xa8 },
diff --git a/drivers/media/dvb/ngene/Makefile b/drivers/media/dvb/ngene/Makefile
index 2bc96874d044..89873615e683 100644
--- a/drivers/media/dvb/ngene/Makefile
+++ b/drivers/media/dvb/ngene/Makefile
@@ -6,9 +6,9 @@ ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o
obj-$(CONFIG_DVB_NGENE) += ngene.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
# For the staging CI driver cxd2099
-EXTRA_CFLAGS += -Idrivers/staging/cxd2099/
+ccflags-y += -Idrivers/staging/cxd2099/
diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile
index 7ac128724df8..700822350ec5 100644
--- a/drivers/media/dvb/pluto2/Makefile
+++ b/drivers/media/dvb/pluto2/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/pt1/Makefile b/drivers/media/dvb/pt1/Makefile
index a66da17bbe31..d80d8e8e7c57 100644
--- a/drivers/media/dvb/pt1/Makefile
+++ b/drivers/media/dvb/pt1/Makefile
@@ -2,4 +2,4 @@ earth-pt1-objs := pt1.o va1j5jf8007s.o va1j5jf8007t.o
obj-$(CONFIG_DVB_PT1) += earth-pt1.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile
index c54140b5ab5a..f233b57c86fb 100644
--- a/drivers/media/dvb/siano/Makefile
+++ b/drivers/media/dvb/siano/Makefile
@@ -5,7 +5,7 @@ obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index 8a4d5bb20a5b..f6e869372e30 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -17,5 +17,5 @@ obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o
obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index cdd31cae46c4..ee8ee1d481fa 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -25,6 +25,8 @@
* the project's page is at http://www.linuxtv.org/
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/delay.h>
@@ -253,7 +255,7 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
switch (av7110->current_input) {
case 1:
- dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
+ dprintk(1, "switching SAA7113 to Analog Tuner Input\n");
msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
@@ -263,7 +265,7 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
- dprintk(1, "setting band in demodulator failed.\n");
+ dprintk(1, "setting band in demodulator failed\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
@@ -272,17 +274,17 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
break;
case 2:
- dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
+ dprintk(1, "switching SAA7113 to Video AV CVBS Input\n");
if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
break;
case 3:
- dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
+ dprintk(1, "switching SAA7113 to Video AV Y/C Input\n");
if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
break;
default:
- dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
+ dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input\n");
}
} else {
adswitch = 0;
@@ -299,7 +301,7 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
- dprintk(1, "setting band in demodulator failed.\n");
+ dprintk(1, "setting band in demodulator failed\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
@@ -413,7 +415,7 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
- dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
+ dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x\n", f->frequency);
if (!av7110->analog_tuner_flags || av7110->current_input != 1)
return -EINVAL;
@@ -429,7 +431,7 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
- dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
+ dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x\n", f->frequency);
if (!av7110->analog_tuner_flags || av7110->current_input != 1)
return -EINVAL;
@@ -689,12 +691,12 @@ int av7110_init_analog_module(struct av7110 *av7110)
if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
- printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
+ pr_info("DVB-C analog module @ card %d detected, initializing MSP3400\n",
av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_MSP34x0;
} else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
- printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n",
+ pr_info("DVB-C analog module @ card %d detected, initializing MSP3415\n",
av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_MSP34x5;
} else
@@ -715,7 +717,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART
if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
- INFO(("saa7113 not accessible.\n"));
+ pr_info("saa7113 not accessible\n");
} else {
u8 *i = saa7113_init_regs;
@@ -733,7 +735,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
/* setup for DVB by default */
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
- dprintk(1, "setting band in demodulator failed.\n");
+ dprintk(1, "setting band in demodulator failed\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
@@ -797,7 +799,7 @@ int av7110_init_v4l(struct av7110 *av7110)
ret = saa7146_vv_init(dev, vv_data);
if (ret) {
- ERR(("cannot init capture device. skipping.\n"));
+ ERR("cannot init capture device. skipping\n");
return -ENODEV;
}
vv_data->ops.vidioc_enum_input = vidioc_enum_input;
@@ -814,12 +816,12 @@ int av7110_init_v4l(struct av7110 *av7110)
vv_data->ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
- ERR(("cannot register capture device. skipping.\n"));
+ ERR("cannot register capture device. skipping\n");
saa7146_vv_release(dev);
return -ENODEV;
}
if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
- ERR(("cannot register vbi v4l2 device. skipping.\n"));
+ ERR("cannot register vbi v4l2 device. skipping\n");
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index e957d7690bcc..78d32f7e49fc 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -33,6 +33,8 @@
* the project's page is at http://www.linuxtv.org/
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "budget.h"
#include "stv0299.h"
#include "stb0899_drv.h"
@@ -149,7 +151,7 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
if (result == -ETIMEDOUT) {
ciintf_slot_shutdown(ca, slot);
- printk(KERN_INFO "budget-av: cam ejected 1\n");
+ pr_info("cam ejected 1\n");
}
return result;
}
@@ -168,7 +170,7 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
if (result == -ETIMEDOUT) {
ciintf_slot_shutdown(ca, slot);
- printk(KERN_INFO "budget-av: cam ejected 2\n");
+ pr_info("cam ejected 2\n");
}
return result;
}
@@ -187,7 +189,7 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
if (result == -ETIMEDOUT) {
ciintf_slot_shutdown(ca, slot);
- printk(KERN_INFO "budget-av: cam ejected 3\n");
+ pr_info("cam ejected 3\n");
return -ETIMEDOUT;
}
return result;
@@ -207,7 +209,7 @@ static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addr
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
if (result == -ETIMEDOUT) {
ciintf_slot_shutdown(ca, slot);
- printk(KERN_INFO "budget-av: cam ejected 5\n");
+ pr_info("cam ejected 5\n");
}
return result;
}
@@ -289,7 +291,7 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
if (saa7146_read(saa, PSR) & MASK_06) {
if (budget_av->slot_status == SLOTSTATUS_NONE) {
budget_av->slot_status = SLOTSTATUS_PRESENT;
- printk(KERN_INFO "budget-av: cam inserted A\n");
+ pr_info("cam inserted A\n");
}
}
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
@@ -306,11 +308,11 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
budget_av->slot_status = SLOTSTATUS_PRESENT;
- printk(KERN_INFO "budget-av: cam inserted B\n");
+ pr_info("cam inserted B\n");
} else if (result < 0) {
if (budget_av->slot_status != SLOTSTATUS_NONE) {
ciintf_slot_shutdown(ca, slot);
- printk(KERN_INFO "budget-av: cam ejected 5\n");
+ pr_info("cam ejected 5\n");
return 0;
}
}
@@ -365,11 +367,11 @@ static int ciintf_init(struct budget_av *budget_av)
if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
&budget_av->ca, 0, 1)) != 0) {
- printk(KERN_ERR "budget-av: ci initialisation failed.\n");
+ pr_err("ci initialisation failed\n");
goto error;
}
- printk(KERN_INFO "budget-av: ci interface initialised.\n");
+ pr_info("ci interface initialised\n");
return 0;
error:
@@ -896,7 +898,6 @@ static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = {
{ STB0899_DISRX_ST0 , 0x04 },
{ STB0899_DISRX_ST1 , 0x00 },
{ STB0899_DISPARITY , 0x00 },
- { STB0899_DISFIFO , 0x00 },
{ STB0899_DISSTATUS , 0x20 },
{ STB0899_DISF22 , 0x8c },
{ STB0899_DISF22RX , 0x9a },
@@ -1197,6 +1198,7 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBC_KNC1 0x0020
#define SUBID_DVBC_KNC1_PLUS 0x0021
#define SUBID_DVBC_KNC1_MK3 0x0022
+#define SUBID_DVBC_KNC1_TDA10024 0x0028
#define SUBID_DVBC_KNC1_PLUS_MK3 0x0023
#define SUBID_DVBC_CINERGY1200 0x1156
#define SUBID_DVBC_CINERGY1200_MK3 0x1176
@@ -1316,6 +1318,7 @@ static void frontend_init(struct budget_av *budget_av)
case SUBID_DVBC_EASYWATCH_MK3:
case SUBID_DVBC_CINERGY1200_MK3:
case SUBID_DVBC_KNC1_MK3:
+ case SUBID_DVBC_KNC1_TDA10024:
case SUBID_DVBC_KNC1_PLUS_MK3:
budget_av->reinitialise_demod = 1;
budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
@@ -1343,8 +1346,7 @@ static void frontend_init(struct budget_av *budget_av)
}
if (fe == NULL) {
- printk(KERN_ERR "budget-av: A frontend driver was not found "
- "for device [%04x:%04x] subsystem [%04x:%04x]\n",
+ pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
saa->pci->vendor,
saa->pci->device,
saa->pci->subsystem_vendor,
@@ -1356,7 +1358,7 @@ static void frontend_init(struct budget_av *budget_av)
if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
budget_av->budget.dvb_frontend)) {
- printk(KERN_ERR "budget-av: Frontend registration failed!\n");
+ pr_err("Frontend registration failed!\n");
dvb_frontend_detach(budget_av->budget.dvb_frontend);
budget_av->budget.dvb_frontend = NULL;
}
@@ -1414,7 +1416,7 @@ static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{
- dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
+ dprintk(1, "VIDIOC_ENUMINPUT %d\n", i->index);
if (i->index >= KNC1_INPUTS)
return -EINVAL;
memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
@@ -1428,7 +1430,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
*i = budget_av->cur_input;
- dprintk(1, "VIDIOC_G_INPUT %d.\n", *i);
+ dprintk(1, "VIDIOC_G_INPUT %d\n", *i);
return 0;
}
@@ -1437,7 +1439,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
- dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
+ dprintk(1, "VIDIOC_S_INPUT %d\n", input);
return saa7113_setinput(budget_av, input);
}
@@ -1476,7 +1478,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
if (0 != saa7146_vv_init(dev, &vv_data)) {
/* fixme: proper cleanup here */
- ERR(("cannot init vv subsystem.\n"));
+ ERR("cannot init vv subsystem\n");
return err;
}
vv_data.ops.vidioc_enum_input = vidioc_enum_input;
@@ -1485,7 +1487,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
/* fixme: proper cleanup here */
- ERR(("cannot register capture v4l2 device.\n"));
+ ERR("cannot register capture v4l2 device\n");
saa7146_vv_release(dev);
return err;
}
@@ -1502,13 +1504,12 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
mac = budget_av->budget.dvb_adapter.proposed_mac;
if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
- printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n",
+ pr_err("KNC1-%d: Could not read MAC from KNC1 card\n",
budget_av->budget.dvb_adapter.num);
memset(mac, 0, 6);
} else {
- printk(KERN_INFO "KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
- budget_av->budget.dvb_adapter.num,
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ pr_info("KNC1-%d: MAC addr = %pM\n",
+ budget_av->budget.dvb_adapter.num, mac);
}
budget_av->budget.dvb_adapter.priv = budget_av;
@@ -1558,6 +1559,7 @@ MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP);
MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);
+MAKE_BUDGET_INFO(knc1ctda10024, "KNC1 DVB-C TDA10024", BUDGET_KNC1C_TDA10024);
MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);
MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
@@ -1587,6 +1589,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),
+ MAKE_EXTENSION_PCI(knc1ctda10024, 0x1894, 0x0028),
MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023),
MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 926f299b5225..ca02e9722172 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -1053,7 +1053,6 @@ static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
{ STB0899_DISRX_ST0 , 0x04 },
{ STB0899_DISRX_ST1 , 0x00 },
{ STB0899_DISPARITY , 0x00 },
- { STB0899_DISFIFO , 0x00 },
{ STB0899_DISSTATUS , 0x20 },
{ STB0899_DISF22 , 0x8c },
{ STB0899_DISF22RX , 0x9a },
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 37666d4edab6..37d02fe09137 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -110,6 +110,7 @@ static int start_ts_capture(struct budget *budget)
break;
case BUDGET_CIN1200C_MK3:
case BUDGET_KNC1C_MK3:
+ case BUDGET_KNC1C_TDA10024:
case BUDGET_KNC1CP_MK3:
if (budget->video_port == BUDGET_VIDEO_PORTA) {
saa7146_write(dev, DD1_INIT, 0x06000200);
@@ -434,6 +435,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
case BUDGET_KNC1CP:
case BUDGET_CIN1200C:
case BUDGET_KNC1C_MK3:
+ case BUDGET_KNC1C_TDA10024:
case BUDGET_KNC1CP_MK3:
case BUDGET_CIN1200C_MK3:
budget->buffer_width = TS_WIDTH_DVBC;
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index 3ad0c6789ba7..3d8a806c20bb 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -104,6 +104,7 @@ static struct saa7146_pci_extension_data x_var = { \
#define BUDGET_KNC1C_MK3 16
#define BUDGET_KNC1CP_MK3 17
#define BUDGET_KNC1S2 18
+#define BUDGET_KNC1C_TDA10024 19
#define BUDGET_VIDEO_PORTA 0
#define BUDGET_VIDEO_PORTB 1
diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c
index 7dd54b3026a2..32d43156c548 100644
--- a/drivers/media/dvb/ttpci/ttpci-eeprom.c
+++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c
@@ -85,6 +85,35 @@ static int getmac_tt(u8 * decodedMAC, u8 * encodedMAC)
return 0;
}
+int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC)
+{
+ u8 xor[20] = { 0x72, 0x23, 0x68, 0x19, 0x5c, 0xa8, 0x71, 0x2c,
+ 0x54, 0xd3, 0x7b, 0xf1, 0x9E, 0x23, 0x16, 0xf6,
+ 0x1d, 0x36, 0x64, 0x78};
+ u8 data[20];
+ int i;
+
+ memcpy(data, encodedMAC, 20);
+
+ for (i = 0; i < 20; i++)
+ data[i] ^= xor[i];
+ for (i = 0; i < 10; i++)
+ data[i] = ((data[2 * i + 1] << 8) | data[2 * i])
+ >> ((data[2 * i + 1] >> 6) & 3);
+
+ if (check_mac_tt(data))
+ return -ENODEV;
+
+ decodedMAC[0] = data[2];
+ decodedMAC[1] = data[1];
+ decodedMAC[2] = data[0];
+ decodedMAC[3] = data[6];
+ decodedMAC[4] = data[5];
+ decodedMAC[5] = data[4];
+ return 0;
+}
+EXPORT_SYMBOL(ttpci_eeprom_decode_mac);
+
static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encodedMAC)
{
int ret;
diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.h b/drivers/media/dvb/ttpci/ttpci-eeprom.h
index e2dc6cfe205c..dcc33d5a5cb1 100644
--- a/drivers/media/dvb/ttpci/ttpci-eeprom.h
+++ b/drivers/media/dvb/ttpci/ttpci-eeprom.h
@@ -28,6 +28,7 @@
#include <linux/types.h>
#include <linux/i2c.h>
+extern int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC);
extern int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *propsed_mac);
#endif
diff --git a/drivers/media/dvb/ttusb-budget/Makefile b/drivers/media/dvb/ttusb-budget/Makefile
index fbe2b9514c21..8d6c4acb7f1d 100644
--- a/drivers/media/dvb/ttusb-budget/Makefile
+++ b/drivers/media/dvb/ttusb-budget/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/ttusb-dec/Makefile b/drivers/media/dvb/ttusb-dec/Makefile
index 2d70a8269391..ed28b5384d20 100644
--- a/drivers/media/dvb/ttusb-dec/Makefile
+++ b/drivers/media/dvb/ttusb-dec/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index f484a6e04eb2..390daf94d847 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -27,4 +27,4 @@ obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o
obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o
obj-$(CONFIG_RADIO_WL128X) += wl128x/
-EXTRA_CFLAGS += -Isound
+ccflags-y += -Isound
diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c
index 444b4cf7e65c..d1fab5885061 100644
--- a/drivers/media/radio/radio-si4713.c
+++ b/drivers/media/radio/radio-si4713.c
@@ -92,10 +92,6 @@ static int radio_si4713_s_audout(struct file *file, void *priv,
static int radio_si4713_querycap(struct file *file, void *priv,
struct v4l2_capability *capability)
{
- struct radio_si4713_device *rsdev;
-
- rsdev = video_get_drvdata(video_devdata(file));
-
strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver));
strlcpy(capability->card, "Silicon Labs Si4713 Modulator",
sizeof(capability->card));
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index 46cacf845049..6d1e4e750f63 100644
--- a/drivers/media/radio/radio-wl1273.c
+++ b/drivers/media/radio/radio-wl1273.c
@@ -2109,7 +2109,7 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
V4L2_CID_TUNE_ANTENNA_CAPACITOR,
0, 255, 1, 255);
if (ctrl)
- ctrl->is_volatile = 1;
+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
if (radio->ctrl_handler.error) {
r = radio->ctrl_handler.error;
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c
index 4cf537043f99..a6ad707fae96 100644
--- a/drivers/media/radio/si470x/radio-si470x-usb.c
+++ b/drivers/media/radio/si470x/radio-si470x-usb.c
@@ -395,7 +395,6 @@ int si470x_disconnect_check(struct si470x_device *radio)
static void si470x_int_in_callback(struct urb *urb)
{
struct si470x_device *radio = urb->context;
- unsigned char buf[RDS_REPORT_SIZE];
int retval;
unsigned char regnr;
unsigned char blocknum;
@@ -423,7 +422,6 @@ static void si470x_int_in_callback(struct urb *urb)
if (urb->actual_length > 0) {
/* Update RDS registers with URB data */
- buf[0] = RDS_REPORT;
for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
radio->registers[STATUSRSSI + regnr] =
get_unaligned_be16(&radio->int_in_buffer[
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
index 8c0e19276970..b93d8cf23b03 100644
--- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
@@ -84,12 +84,14 @@ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf,
ret = copy_from_user(&rds, buf, sizeof(rds));
fmdbg("(%d)type: %d, text %s, af %d\n",
ret, rds.text_type, rds.text, rds.af_freq);
+ if (ret)
+ return -EFAULT;
fmdev = video_drvdata(file);
fm_tx_set_radio_text(fmdev, rds.text, rds.text_type);
fm_tx_set_af(fmdev, rds.af_freq);
- return 0;
+ return sizeof(rds);
}
static u32 fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts)
@@ -402,7 +404,7 @@ static int fm_v4l2_vidioc_s_hw_freq_seek(struct file *file, void *priv,
static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv,
struct v4l2_modulator *mod)
{
- struct fmdev *fmdev = video_drvdata(file);;
+ struct fmdev *fmdev = video_drvdata(file);
if (mod->index != 0)
return -EINVAL;
@@ -557,7 +559,7 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
255, 1, 255);
if (ctrl)
- ctrl->is_volatile = 1;
+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
return 0;
}
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 899f783d92fb..aeb7f43dfb65 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -4,8 +4,8 @@ menuconfig RC_CORE
default INPUT
---help---
Enable support for Remote Controllers on Linux. This is
- needed in order to support several video capture adapters.
- Currently, all supported devices use InfraRed.
+ needed in order to support several video capture adapters,
+ standalone IR receivers/transmitters, and RF receivers.
Enable this option if you have a video capture board even
if you don't need IR, as otherwise, you may not be able to
@@ -108,6 +108,25 @@ config IR_LIRC_CODEC
Enable this option to pass raw IR to and from userspace via
the LIRC interface.
+config RC_ATI_REMOTE
+ tristate "ATI / X10 based USB RF remote controls"
+ depends on USB_ARCH_HAS_HCD
+ depends on RC_CORE
+ select USB
+ help
+ Say Y here if you want to use an X10 based USB remote control.
+ These are RF remotes with USB receivers.
+
+ Such devices include the ATI remote that comes with many of ATI's
+ All-In-Wonder video cards, the X10 "Lola" remote, NVIDIA RF remote,
+ Medion RF remote, and SnapStream FireFly remote.
+
+ This driver provides mouse pointer, left and right mouse buttons,
+ and maps all the other remote buttons to keypress events.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ati_remote.
+
config IR_ENE
tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
depends on PNP
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index f224db027c41..2156e786b557 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
# stand-alone IR receivers/transmitters
+obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o
obj-$(CONFIG_IR_IMON) += imon.o
obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
obj-$(CONFIG_IR_MCEUSB) += mceusb.o
diff --git a/drivers/input/misc/ati_remote.c b/drivers/media/rc/ati_remote.c
index bce57129afba..303f22ea04c0 100644
--- a/drivers/input/misc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -1,6 +1,7 @@
/*
* USB ATI Remote support
*
+ * Copyright (c) 2011 Anssi Hannula <anssi.hannula@iki.fi>
* Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
* Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev
*
@@ -90,9 +91,11 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/usb/input.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
+#include <media/rc-core.h>
/*
* Module and Version Information, Module Parameters
@@ -104,8 +107,9 @@
#define ATI_REMOTE_PRODUCT_ID 0x0004
#define NVIDIA_REMOTE_PRODUCT_ID 0x0005
#define MEDION_REMOTE_PRODUCT_ID 0x0006
+#define FIREFLY_REMOTE_PRODUCT_ID 0x0008
-#define DRIVER_VERSION "2.2.1"
+#define DRIVER_VERSION "2.2.1"
#define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>"
#define DRIVER_DESC "ATI/X10 RF USB Remote Control"
@@ -139,16 +143,21 @@ static int repeat_delay = REPEAT_DELAY;
module_param(repeat_delay, int, 0644);
MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec");
+static bool mouse = true;
+module_param(mouse, bool, 0444);
+MODULE_PARM_DESC(mouse, "Enable mouse device, default = yes");
+
#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
#undef err
#define err(format, arg...) printk(KERN_ERR format , ## arg)
static struct usb_device_id ati_remote_table[] = {
- { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) },
- { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID) },
- { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) },
- { USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID) },
- { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) },
+ { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_ATI_X10 },
+ { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_ATI_X10 },
+ { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_ATI_X10 },
+ { USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_ATI_X10 },
+ { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_MEDION_X10 },
+ { USB_DEVICE(ATI_REMOTE_VENDOR_ID, FIREFLY_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_SNAPSTREAM_FIREFLY },
{} /* Terminating entry */
};
@@ -167,6 +176,7 @@ static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
struct ati_remote {
struct input_dev *idev;
+ struct rc_dev *rdev;
struct usb_device *udev;
struct usb_interface *interface;
@@ -186,11 +196,16 @@ struct ati_remote {
unsigned int repeat_count;
- char name[NAME_BUFSIZE];
- char phys[NAME_BUFSIZE];
+ char rc_name[NAME_BUFSIZE];
+ char rc_phys[NAME_BUFSIZE];
+ char mouse_name[NAME_BUFSIZE];
+ char mouse_phys[NAME_BUFSIZE];
wait_queue_head_t wait;
int send_flags;
+
+ int users; /* 0-2, users are rc and input */
+ struct mutex open_mutex;
};
/* "Kinds" of messages sent from the hardware to the driver. */
@@ -233,64 +248,11 @@ static const struct {
{KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
{KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
- /* keyboard. */
- {KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1},
- {KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1},
- {KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1},
- {KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1},
- {KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1},
- {KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1},
- {KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1},
- {KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1},
- {KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1},
- {KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1},
- {KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_A, 1},
- {KIND_FILTERED, 0xc6, 0x01, EV_KEY, KEY_B, 1},
- {KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_C, 1},
- {KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_D, 1},
- {KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_E, 1},
- {KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_F, 1},
-
- /* "special" keys */
- {KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1}, /* "check" */
- {KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1}, /* "menu" */
- {KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1}, /* Power */
- {KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_TV, 1}, /* TV */
- {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1}, /* DVD */
- {KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1}, /* WEB */
- {KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1}, /* "book" */
- {KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1}, /* "hand" */
- {KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_COFFEE, 1}, /* "timer" */
- {KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_FRONT, 1}, /* "max" */
- {KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1}, /* left */
- {KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1}, /* right */
- {KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1}, /* down */
- {KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1}, /* up */
- {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1}, /* "OK" */
- {KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */
- {KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1}, /* VOL - */
- {KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1}, /* MUTE */
- {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1}, /* CH + */
- {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */
- {KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1}, /* ( o) red */
- {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */
- {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */
- {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */
- {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */
- {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */
- {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */
- {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */
- {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */
- {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */
- {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */
- {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */
-
+ /* Non-mouse events are handled by rc-core */
{KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0}
};
/* Local function prototypes */
-static int ati_remote_open (struct input_dev *inputdev);
-static void ati_remote_close (struct input_dev *inputdev);
static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data);
static void ati_remote_irq_out (struct urb *urb);
static void ati_remote_irq_in (struct urb *urb);
@@ -313,9 +275,10 @@ static struct usb_driver ati_remote_driver = {
static void ati_remote_dump(struct device *dev, unsigned char *data,
unsigned int len)
{
- if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00))
- dev_warn(dev, "Weird byte 0x%02x\n", data[0]);
- else if (len == 4)
+ if (len == 1) {
+ if (data[0] != (unsigned char)0xff && data[0] != 0x00)
+ dev_warn(dev, "Weird byte 0x%02x\n", data[0]);
+ } else if (len == 4)
dev_warn(dev, "Weird key %02x %02x %02x %02x\n",
data[0], data[1], data[2], data[3]);
else
@@ -326,29 +289,60 @@ static void ati_remote_dump(struct device *dev, unsigned char *data,
/*
* ati_remote_open
*/
-static int ati_remote_open(struct input_dev *inputdev)
+static int ati_remote_open(struct ati_remote *ati_remote)
{
- struct ati_remote *ati_remote = input_get_drvdata(inputdev);
+ int err = 0;
+
+ mutex_lock(&ati_remote->open_mutex);
+
+ if (ati_remote->users++ != 0)
+ goto out; /* one was already active */
/* On first open, submit the read urb which was set up previously. */
ati_remote->irq_urb->dev = ati_remote->udev;
if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
dev_err(&ati_remote->interface->dev,
"%s: usb_submit_urb failed!\n", __func__);
- return -EIO;
+ err = -EIO;
}
- return 0;
+out: mutex_unlock(&ati_remote->open_mutex);
+ return err;
}
/*
* ati_remote_close
*/
-static void ati_remote_close(struct input_dev *inputdev)
+static void ati_remote_close(struct ati_remote *ati_remote)
+{
+ mutex_lock(&ati_remote->open_mutex);
+ if (--ati_remote->users == 0)
+ usb_kill_urb(ati_remote->irq_urb);
+ mutex_unlock(&ati_remote->open_mutex);
+}
+
+static int ati_remote_input_open(struct input_dev *inputdev)
{
struct ati_remote *ati_remote = input_get_drvdata(inputdev);
+ return ati_remote_open(ati_remote);
+}
- usb_kill_urb(ati_remote->irq_urb);
+static void ati_remote_input_close(struct input_dev *inputdev)
+{
+ struct ati_remote *ati_remote = input_get_drvdata(inputdev);
+ ati_remote_close(ati_remote);
+}
+
+static int ati_remote_rc_open(struct rc_dev *rdev)
+{
+ struct ati_remote *ati_remote = rdev->priv;
+ return ati_remote_open(ati_remote);
+}
+
+static void ati_remote_rc_close(struct rc_dev *rdev)
+{
+ struct ati_remote *ati_remote = rdev->priv;
+ ati_remote_close(ati_remote);
}
/*
@@ -413,10 +407,8 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2)
/*
* Decide if the table entry matches the remote input.
*/
- if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) &&
- ((((ati_remote_tbl[i].data1 >> 4) -
- (d1 >> 4) + rem) & 0x0f) == 0x0f) &&
- (ati_remote_tbl[i].data2 == d2))
+ if (ati_remote_tbl[i].data1 == d1 &&
+ ati_remote_tbl[i].data2 == d2)
return i;
}
@@ -468,8 +460,10 @@ static void ati_remote_input_report(struct urb *urb)
struct ati_remote *ati_remote = urb->context;
unsigned char *data= ati_remote->inbuf;
struct input_dev *dev = ati_remote->idev;
- int index, acc;
+ int index = -1;
+ int acc;
int remote_num;
+ unsigned char scancode[2];
/* Deal with strange looking inputs */
if ( (urb->actual_length != 4) || (data[0] != 0x14) ||
@@ -481,26 +475,41 @@ static void ati_remote_input_report(struct urb *urb)
/* Mask unwanted remote channels. */
/* note: remote_num is 0-based, channel 1 on remote == 0 here */
remote_num = (data[3] >> 4) & 0x0f;
- if (channel_mask & (1 << (remote_num + 1))) {
+ if (channel_mask & (1 << (remote_num + 1))) {
dbginfo(&ati_remote->interface->dev,
"Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n",
remote_num, data[1], data[2], channel_mask);
return;
}
- /* Look up event code index in translation table */
- index = ati_remote_event_lookup(remote_num, data[1], data[2]);
- if (index < 0) {
- dev_warn(&ati_remote->interface->dev,
- "Unknown input from channel 0x%02x: data %02x,%02x\n",
- remote_num, data[1], data[2]);
- return;
- }
- dbginfo(&ati_remote->interface->dev,
- "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n",
- remote_num, data[1], data[2], index, ati_remote_tbl[index].code);
+ scancode[0] = (((data[1] - ((remote_num + 1) << 4)) & 0xf0) | (data[1] & 0x0f));
- if (ati_remote_tbl[index].kind == KIND_LITERAL) {
+ /*
+ * Some devices (e.g. SnapStream Firefly) use 8080 as toggle code,
+ * so we have to clear them. The first bit is a bit tricky as the
+ * "non-toggled" state depends on remote_num, so we xor it with the
+ * second bit which is only used for toggle.
+ */
+ scancode[0] ^= (data[2] & 0x80);
+
+ scancode[1] = data[2] & ~0x80;
+
+ /* Look up event code index in mouse translation table. */
+ index = ati_remote_event_lookup(remote_num, scancode[0], scancode[1]);
+
+ if (index >= 0) {
+ dbginfo(&ati_remote->interface->dev,
+ "channel 0x%02x; mouse data %02x,%02x; index %d; keycode %d\n",
+ remote_num, data[1], data[2], index, ati_remote_tbl[index].code);
+ if (!dev)
+ return; /* no mouse device */
+ } else
+ dbginfo(&ati_remote->interface->dev,
+ "channel 0x%02x; key data %02x,%02x, scancode %02x,%02x\n",
+ remote_num, data[1], data[2], scancode[0], scancode[1]);
+
+
+ if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) {
input_event(dev, ati_remote_tbl[index].type,
ati_remote_tbl[index].code,
ati_remote_tbl[index].value);
@@ -510,7 +519,7 @@ static void ati_remote_input_report(struct urb *urb)
return;
}
- if (ati_remote_tbl[index].kind == KIND_FILTERED) {
+ if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) {
unsigned long now = jiffies;
/* Filter duplicate events which happen "too close" together. */
@@ -538,6 +547,20 @@ static void ati_remote_input_report(struct urb *urb)
msecs_to_jiffies(repeat_delay))))
return;
+ if (index < 0) {
+ /* Not a mouse event, hand it to rc-core. */
+ u32 rc_code = (scancode[0] << 8) | scancode[1];
+
+ /*
+ * We don't use the rc-core repeat handling yet as
+ * it would cause ghost repeats which would be a
+ * regression for this driver.
+ */
+ rc_keydown_notimeout(ati_remote->rdev, rc_code,
+ data[2]);
+ rc_keyup(ati_remote->rdev);
+ return;
+ }
input_event(dev, ati_remote_tbl[index].type,
ati_remote_tbl[index].code, 1);
@@ -630,7 +653,7 @@ static int ati_remote_alloc_buffers(struct usb_device *udev,
return -1;
ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
- &ati_remote->outbuf_dma);
+ &ati_remote->outbuf_dma);
if (!ati_remote->outbuf)
return -1;
@@ -675,14 +698,33 @@ static void ati_remote_input_init(struct ati_remote *ati_remote)
input_set_drvdata(idev, ati_remote);
- idev->open = ati_remote_open;
- idev->close = ati_remote_close;
+ idev->open = ati_remote_input_open;
+ idev->close = ati_remote_input_close;
- idev->name = ati_remote->name;
- idev->phys = ati_remote->phys;
+ idev->name = ati_remote->mouse_name;
+ idev->phys = ati_remote->mouse_phys;
usb_to_input_id(ati_remote->udev, &idev->id);
- idev->dev.parent = &ati_remote->udev->dev;
+ idev->dev.parent = &ati_remote->interface->dev;
+}
+
+static void ati_remote_rc_init(struct ati_remote *ati_remote)
+{
+ struct rc_dev *rdev = ati_remote->rdev;
+
+ rdev->priv = ati_remote;
+ rdev->driver_type = RC_DRIVER_SCANCODE;
+ rdev->allowed_protos = RC_TYPE_OTHER;
+ rdev->driver_name = "ati_remote";
+
+ rdev->open = ati_remote_rc_open;
+ rdev->close = ati_remote_rc_close;
+
+ rdev->input_name = ati_remote->rc_name;
+ rdev->input_phys = ati_remote->rc_phys;
+
+ usb_to_input_id(ati_remote->udev, &rdev->input_id);
+ rdev->dev.parent = &ati_remote->interface->dev;
}
static int ati_remote_initialize(struct ati_remote *ati_remote)
@@ -735,6 +777,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
struct usb_endpoint_descriptor *endpoint_in, *endpoint_out;
struct ati_remote *ati_remote;
struct input_dev *input_dev;
+ struct rc_dev *rc_dev;
int err = -ENOMEM;
if (iface_host->desc.bNumEndpoints != 2) {
@@ -755,8 +798,8 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
}
ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!ati_remote || !input_dev)
+ rc_dev = rc_allocate_device();
+ if (!ati_remote || !rc_dev)
goto fail1;
/* Allocate URB buffers, URBs */
@@ -766,44 +809,78 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
ati_remote->endpoint_in = endpoint_in;
ati_remote->endpoint_out = endpoint_out;
ati_remote->udev = udev;
- ati_remote->idev = input_dev;
+ ati_remote->rdev = rc_dev;
ati_remote->interface = interface;
- usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys));
- strlcat(ati_remote->phys, "/input0", sizeof(ati_remote->phys));
+ usb_make_path(udev, ati_remote->rc_phys, sizeof(ati_remote->rc_phys));
+ strlcpy(ati_remote->mouse_phys, ati_remote->rc_phys,
+ sizeof(ati_remote->mouse_phys));
+
+ strlcat(ati_remote->rc_phys, "/input0", sizeof(ati_remote->rc_phys));
+ strlcat(ati_remote->mouse_phys, "/input1", sizeof(ati_remote->mouse_phys));
if (udev->manufacturer)
- strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name));
+ strlcpy(ati_remote->rc_name, udev->manufacturer,
+ sizeof(ati_remote->rc_name));
if (udev->product)
- snprintf(ati_remote->name, sizeof(ati_remote->name),
- "%s %s", ati_remote->name, udev->product);
+ snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name),
+ "%s %s", ati_remote->rc_name, udev->product);
- if (!strlen(ati_remote->name))
- snprintf(ati_remote->name, sizeof(ati_remote->name),
+ if (!strlen(ati_remote->rc_name))
+ snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name),
DRIVER_DESC "(%04x,%04x)",
le16_to_cpu(ati_remote->udev->descriptor.idVendor),
le16_to_cpu(ati_remote->udev->descriptor.idProduct));
- ati_remote_input_init(ati_remote);
+ snprintf(ati_remote->mouse_name, sizeof(ati_remote->mouse_name),
+ "%s mouse", ati_remote->rc_name);
+
+ if (id->driver_info)
+ rc_dev->map_name = (const char *)id->driver_info;
+ else
+ rc_dev->map_name = RC_MAP_ATI_X10;
+
+ ati_remote_rc_init(ati_remote);
+ mutex_init(&ati_remote->open_mutex);
/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
err = ati_remote_initialize(ati_remote);
if (err)
goto fail3;
- /* Set up and register input device */
- err = input_register_device(ati_remote->idev);
+ /* Set up and register rc device */
+ err = rc_register_device(ati_remote->rdev);
if (err)
goto fail3;
+ /* use our delay for rc_dev */
+ ati_remote->rdev->input_dev->rep[REP_DELAY] = repeat_delay;
+
+ /* Set up and register mouse input device */
+ if (mouse) {
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ goto fail4;
+
+ ati_remote->idev = input_dev;
+ ati_remote_input_init(ati_remote);
+ err = input_register_device(input_dev);
+
+ if (err)
+ goto fail5;
+ }
+
usb_set_intfdata(interface, ati_remote);
return 0;
+ fail5: input_free_device(input_dev);
+ fail4: rc_unregister_device(rc_dev);
+ rc_dev = NULL;
fail3: usb_kill_urb(ati_remote->irq_urb);
usb_kill_urb(ati_remote->out_urb);
fail2: ati_remote_free_buffers(ati_remote);
- fail1: input_free_device(input_dev);
+ fail1: rc_free_device(rc_dev);
kfree(ati_remote);
return err;
}
@@ -824,7 +901,9 @@ static void ati_remote_disconnect(struct usb_interface *interface)
usb_kill_urb(ati_remote->irq_urb);
usb_kill_urb(ati_remote->out_urb);
- input_unregister_device(ati_remote->idev);
+ if (ati_remote->idev)
+ input_unregister_device(ati_remote->idev);
+ rc_unregister_device(ati_remote->rdev);
ati_remote_free_buffers(ati_remote);
kfree(ati_remote);
}
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index 2b9c2569d74a..cf10ecf5acec 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -30,6 +30,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pnp.h>
@@ -118,31 +120,31 @@ static int ene_hw_detect(struct ene_device *dev)
dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 2 : 4;
if (hw_revision == 0xFF) {
- ene_warn("device seems to be disabled");
- ene_warn("send a mail to lirc-list@lists.sourceforge.net");
- ene_warn("please attach output of acpidump and dmidecode");
+ pr_warn("device seems to be disabled\n");
+ pr_warn("send a mail to lirc-list@lists.sourceforge.net\n");
+ pr_warn("please attach output of acpidump and dmidecode\n");
return -ENODEV;
}
- ene_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x",
- chip_major, chip_minor, old_ver, hw_revision);
+ pr_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x\n",
+ chip_major, chip_minor, old_ver, hw_revision);
- ene_notice("PLL freq = %d", dev->pll_freq);
+ pr_notice("PLL freq = %d\n", dev->pll_freq);
if (chip_major == 0x33) {
- ene_warn("chips 0x33xx aren't supported");
+ pr_warn("chips 0x33xx aren't supported\n");
return -ENODEV;
}
if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
dev->hw_revision = ENE_HW_C;
- ene_notice("KB3926C detected");
+ pr_notice("KB3926C detected\n");
} else if (old_ver == 0x24 && hw_revision == 0xC0) {
dev->hw_revision = ENE_HW_B;
- ene_notice("KB3926B detected");
+ pr_notice("KB3926B detected\n");
} else {
dev->hw_revision = ENE_HW_D;
- ene_notice("KB3926D or higher detected");
+ pr_notice("KB3926D or higher detected\n");
}
/* detect features hardware supports */
@@ -152,7 +154,7 @@ static int ene_hw_detect(struct ene_device *dev)
fw_reg1 = ene_read_reg(dev, ENE_FW1);
fw_reg2 = ene_read_reg(dev, ENE_FW2);
- ene_notice("Firmware regs: %02x %02x", fw_reg1, fw_reg2);
+ pr_notice("Firmware regs: %02x %02x\n", fw_reg1, fw_reg2);
dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A);
dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING);
@@ -161,30 +163,29 @@ static int ene_hw_detect(struct ene_device *dev)
if (dev->hw_learning_and_tx_capable)
dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT);
- ene_notice("Hardware features:");
+ pr_notice("Hardware features:\n");
if (dev->hw_learning_and_tx_capable) {
- ene_notice("* Supports transmitting & learning mode");
- ene_notice(" This feature is rare and therefore,");
- ene_notice(" you are welcome to test it,");
- ene_notice(" and/or contact the author via:");
- ene_notice(" lirc-list@lists.sourceforge.net");
- ene_notice(" or maximlevitsky@gmail.com");
+ pr_notice("* Supports transmitting & learning mode\n");
+ pr_notice(" This feature is rare and therefore,\n");
+ pr_notice(" you are welcome to test it,\n");
+ pr_notice(" and/or contact the author via:\n");
+ pr_notice(" lirc-list@lists.sourceforge.net\n");
+ pr_notice(" or maximlevitsky@gmail.com\n");
- ene_notice("* Uses GPIO %s for IR raw input",
- dev->hw_use_gpio_0a ? "40" : "0A");
+ pr_notice("* Uses GPIO %s for IR raw input\n",
+ dev->hw_use_gpio_0a ? "40" : "0A");
if (dev->hw_fan_input)
- ene_notice("* Uses unused fan feedback input as source"
- " of demodulated IR data");
+ pr_notice("* Uses unused fan feedback input as source of demodulated IR data\n");
}
if (!dev->hw_fan_input)
- ene_notice("* Uses GPIO %s for IR demodulated input",
- dev->hw_use_gpio_0a ? "0A" : "40");
+ pr_notice("* Uses GPIO %s for IR demodulated input\n",
+ dev->hw_use_gpio_0a ? "0A" : "40");
if (dev->hw_extra_buffer)
- ene_notice("* Uses new style input buffer");
+ pr_notice("* Uses new style input buffer\n");
return 0;
}
@@ -215,13 +216,13 @@ static void ene_rx_setup_hw_buffer(struct ene_device *dev)
dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8;
- ene_notice("Hardware uses 2 extended buffers:");
- ene_notice(" 0x%04x - len : %d", dev->extra_buf1_address,
- dev->extra_buf1_len);
- ene_notice(" 0x%04x - len : %d", dev->extra_buf2_address,
- dev->extra_buf2_len);
+ pr_notice("Hardware uses 2 extended buffers:\n");
+ pr_notice(" 0x%04x - len : %d\n",
+ dev->extra_buf1_address, dev->extra_buf1_len);
+ pr_notice(" 0x%04x - len : %d\n",
+ dev->extra_buf2_address, dev->extra_buf2_len);
- ene_notice("Total buffer len = %d", dev->buffer_len);
+ pr_notice("Total buffer len = %d\n", dev->buffer_len);
if (dev->buffer_len > 64 || dev->buffer_len < 16)
goto error;
@@ -240,7 +241,7 @@ static void ene_rx_setup_hw_buffer(struct ene_device *dev)
ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
return;
error:
- ene_warn("Error validating extra buffers, device probably won't work");
+ pr_warn("Error validating extra buffers, device probably won't work\n");
dev->hw_extra_buffer = false;
ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
}
@@ -588,7 +589,7 @@ static void ene_tx_enable(struct ene_device *dev)
dbg("TX: Transmitter #2 is connected");
if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
- ene_warn("TX: transmitter cable isn't connected!");
+ pr_warn("TX: transmitter cable isn't connected!\n");
/* disable receive on revc */
if (dev->hw_revision == ENE_HW_C)
@@ -615,7 +616,7 @@ static void ene_tx_sample(struct ene_device *dev)
bool pulse = dev->tx_sample_pulse;
if (!dev->tx_buffer) {
- ene_warn("TX: BUG: attempt to transmit NULL buffer");
+ pr_warn("TX: BUG: attempt to transmit NULL buffer\n");
return;
}
@@ -1049,7 +1050,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
dev->hw_learning_and_tx_capable = true;
setup_timer(&dev->tx_sim_timer, ene_tx_irqsim,
(long unsigned int)dev);
- ene_warn("Simulation of TX activated");
+ pr_warn("Simulation of TX activated\n");
}
if (!dev->hw_learning_and_tx_capable)
@@ -1089,7 +1090,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
if (error < 0)
goto error;
- ene_notice("driver has been successfully loaded");
+ pr_notice("driver has been successfully loaded\n");
return 0;
error:
if (dev && dev->irq >= 0)
diff --git a/drivers/media/rc/ene_ir.h b/drivers/media/rc/ene_ir.h
index 017c209cdf8a..fd108d90f750 100644
--- a/drivers/media/rc/ene_ir.h
+++ b/drivers/media/rc/ene_ir.h
@@ -182,20 +182,11 @@
#define ENE_HW_C 2 /* 3926C */
#define ENE_HW_D 3 /* 3926D or later */
-#define ene_printk(level, text, ...) \
- printk(level ENE_DRIVER_NAME ": " text "\n", ## __VA_ARGS__)
-
-#define ene_notice(text, ...) ene_printk(KERN_NOTICE, text, ## __VA_ARGS__)
-#define ene_warn(text, ...) ene_printk(KERN_WARNING, text, ## __VA_ARGS__)
-
-
-#define __dbg(level, format, ...) \
- do { \
- if (debug >= level) \
- printk(KERN_DEBUG ENE_DRIVER_NAME \
- ": " format "\n", ## __VA_ARGS__); \
- } while (0)
-
+#define __dbg(level, format, ...) \
+do { \
+ if (debug >= level) \
+ pr_debug(format "\n", ## __VA_ARGS__); \
+} while (0)
#define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__)
#define dbg_verbose(format, ...) __dbg(2, format, ## __VA_ARGS__)
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 6bc35eeb653b..6ed96465137a 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
+#include <linux/ratelimit.h>
#include <linux/input.h>
#include <linux/usb.h>
@@ -516,19 +517,19 @@ static int send_packet(struct imon_context *ictx)
if (retval) {
ictx->tx.busy = false;
smp_rmb(); /* ensure later readers know we're not busy */
- pr_err("error submitting urb(%d)\n", retval);
+ pr_err_ratelimited("error submitting urb(%d)\n", retval);
} else {
/* Wait for transmission to complete (or abort) */
mutex_unlock(&ictx->lock);
retval = wait_for_completion_interruptible(
&ictx->tx.finished);
if (retval)
- pr_err("task interrupted\n");
+ pr_err_ratelimited("task interrupted\n");
mutex_lock(&ictx->lock);
retval = ictx->tx.status;
if (retval)
- pr_err("packet tx failed (%d)\n", retval);
+ pr_err_ratelimited("packet tx failed (%d)\n", retval);
}
kfree(control_req);
@@ -830,20 +831,20 @@ static ssize_t vfd_write(struct file *file, const char *buf,
ictx = file->private_data;
if (!ictx) {
- pr_err("no context for device\n");
+ pr_err_ratelimited("no context for device\n");
return -ENODEV;
}
mutex_lock(&ictx->lock);
if (!ictx->dev_present_intf0) {
- pr_err("no iMON device present\n");
+ pr_err_ratelimited("no iMON device present\n");
retval = -ENODEV;
goto exit;
}
if (n_bytes <= 0 || n_bytes > 32) {
- pr_err("invalid payload size\n");
+ pr_err_ratelimited("invalid payload size\n");
retval = -EINVAL;
goto exit;
}
@@ -869,7 +870,7 @@ static ssize_t vfd_write(struct file *file, const char *buf,
retval = send_packet(ictx);
if (retval) {
- pr_err("send packet failed for packet #%d\n", seq / 2);
+ pr_err_ratelimited("send packet #%d failed\n", seq / 2);
goto exit;
} else {
seq += 2;
@@ -883,7 +884,7 @@ static ssize_t vfd_write(struct file *file, const char *buf,
ictx->usb_tx_buf[7] = (unsigned char) seq;
retval = send_packet(ictx);
if (retval)
- pr_err("send packet failed for packet #%d\n", seq / 2);
+ pr_err_ratelimited("send packet #%d failed\n", seq / 2);
exit:
mutex_unlock(&ictx->lock);
@@ -912,20 +913,21 @@ static ssize_t lcd_write(struct file *file, const char *buf,
ictx = file->private_data;
if (!ictx) {
- pr_err("no context for device\n");
+ pr_err_ratelimited("no context for device\n");
return -ENODEV;
}
mutex_lock(&ictx->lock);
if (!ictx->display_supported) {
- pr_err("no iMON display present\n");
+ pr_err_ratelimited("no iMON display present\n");
retval = -ENODEV;
goto exit;
}
if (n_bytes != 8) {
- pr_err("invalid payload size: %d (expected 8)\n", (int)n_bytes);
+ pr_err_ratelimited("invalid payload size: %d (expected 8)\n",
+ (int)n_bytes);
retval = -EINVAL;
goto exit;
}
@@ -937,7 +939,7 @@ static ssize_t lcd_write(struct file *file, const char *buf,
retval = send_packet(ictx);
if (retval) {
- pr_err("send packet failed!\n");
+ pr_err_ratelimited("send packet failed!\n");
goto exit;
} else {
dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n",
@@ -1656,7 +1658,7 @@ static void usb_rx_callback_intf0(struct urb *urb)
return;
ictx = (struct imon_context *)urb->context;
- if (!ictx)
+ if (!ictx || !ictx->dev_present_intf0)
return;
switch (urb->status) {
@@ -1688,7 +1690,7 @@ static void usb_rx_callback_intf1(struct urb *urb)
return;
ictx = (struct imon_context *)urb->context;
- if (!ictx)
+ if (!ictx || !ictx->dev_present_intf1)
return;
switch (urb->status) {
@@ -2116,7 +2118,6 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
ictx->dev = dev;
ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf));
- ictx->dev_present_intf0 = true;
ictx->rx_urb_intf0 = rx_urb;
ictx->tx_urb = tx_urb;
ictx->rf_device = false;
@@ -2155,6 +2156,8 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
goto rdev_setup_failed;
}
+ ictx->dev_present_intf0 = true;
+
mutex_unlock(&ictx->lock);
return ictx;
@@ -2198,7 +2201,6 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf,
}
ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf));
- ictx->dev_present_intf1 = true;
ictx->rx_urb_intf1 = rx_urb;
ret = -ENODEV;
@@ -2227,6 +2229,8 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf,
goto urb_submit_failed;
}
+ ictx->dev_present_intf1 = true;
+
mutex_unlock(&ictx->lock);
return ictx;
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index e5eeec4da76e..ec2e67fd236b 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -98,7 +98,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
return 0;
}
-static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
+static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
size_t n, loff_t *ppos)
{
struct lirc_codec *lirc;
@@ -140,10 +140,11 @@ out:
}
static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
- unsigned long __user arg)
+ unsigned long arg)
{
struct lirc_codec *lirc;
struct rc_dev *dev;
+ u32 __user *argp = (u32 __user *)(arg);
int ret = 0;
__u32 val = 0, tmp;
@@ -156,7 +157,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
return -EFAULT;
if (_IOC_DIR(cmd) & _IOC_WRITE) {
- ret = get_user(val, (__u32 *)arg);
+ ret = get_user(val, argp);
if (ret)
return ret;
}
@@ -265,7 +266,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
}
if (_IOC_DIR(cmd) & _IOC_READ)
- ret = put_user(val, (__u32 *)arg);
+ ret = put_user(val, argp);
return ret;
}
diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
index b57fc83fb4d2..36e4d5e8dd6a 100644
--- a/drivers/media/rc/keymaps/Makefile
+++ b/drivers/media/rc/keymaps/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
rc-apac-viewcomp.o \
rc-asus-pc39.o \
rc-ati-tv-wonder-hd-600.o \
+ rc-ati-x10.o \
rc-avermedia-a16d.o \
rc-avermedia.o \
rc-avermedia-cardbus.o \
@@ -47,6 +48,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
rc-lirc.o \
rc-lme2510.o \
rc-manli.o \
+ rc-medion-x10.o \
rc-msi-digivox-ii.o \
rc-msi-digivox-iii.o \
rc-msi-tvanywhere.o \
@@ -70,6 +72,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
rc-hauppauge.o \
rc-rc6-mce.o \
rc-real-audio-220-32-keys.o \
+ rc-snapstream-firefly.o \
rc-streamzap.o \
rc-tbs-nec.o \
rc-technisat-usb2.o \
diff --git a/drivers/media/rc/keymaps/rc-ati-x10.c b/drivers/media/rc/keymaps/rc-ati-x10.c
new file mode 100644
index 000000000000..e1b8b2605c48
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-ati-x10.c
@@ -0,0 +1,104 @@
+/*
+ * ATI X10 RF remote keytable
+ *
+ * Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi>
+ *
+ * This file is based on the static generic keytable previously found in
+ * ati_remote.c, which is
+ * Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
+ * Copyright (c) 2002 Vladimir Dergachev
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <media/rc-map.h>
+
+static struct rc_map_table ati_x10[] = {
+ { 0xd20d, KEY_1 },
+ { 0xd30e, KEY_2 },
+ { 0xd40f, KEY_3 },
+ { 0xd510, KEY_4 },
+ { 0xd611, KEY_5 },
+ { 0xd712, KEY_6 },
+ { 0xd813, KEY_7 },
+ { 0xd914, KEY_8 },
+ { 0xda15, KEY_9 },
+ { 0xdc17, KEY_0 },
+ { 0xc500, KEY_A },
+ { 0xc601, KEY_B },
+ { 0xde19, KEY_C },
+ { 0xe01b, KEY_D },
+ { 0xe621, KEY_E },
+ { 0xe823, KEY_F },
+
+ { 0xdd18, KEY_KPENTER }, /* "check" */
+ { 0xdb16, KEY_MENU }, /* "menu" */
+ { 0xc702, KEY_POWER }, /* Power */
+ { 0xc803, KEY_TV }, /* TV */
+ { 0xc904, KEY_DVD }, /* DVD */
+ { 0xca05, KEY_WWW }, /* WEB */
+ { 0xcb06, KEY_BOOKMARKS }, /* "book" */
+ { 0xcc07, KEY_EDIT }, /* "hand" */
+ { 0xe11c, KEY_COFFEE }, /* "timer" */
+ { 0xe520, KEY_FRONT }, /* "max" */
+ { 0xe21d, KEY_LEFT }, /* left */
+ { 0xe41f, KEY_RIGHT }, /* right */
+ { 0xe722, KEY_DOWN }, /* down */
+ { 0xdf1a, KEY_UP }, /* up */
+ { 0xe31e, KEY_OK }, /* "OK" */
+ { 0xce09, KEY_VOLUMEDOWN }, /* VOL + */
+ { 0xcd08, KEY_VOLUMEUP }, /* VOL - */
+ { 0xcf0a, KEY_MUTE }, /* MUTE */
+ { 0xd00b, KEY_CHANNELUP }, /* CH + */
+ { 0xd10c, KEY_CHANNELDOWN },/* CH - */
+ { 0xec27, KEY_RECORD }, /* ( o) red */
+ { 0xea25, KEY_PLAY }, /* ( >) */
+ { 0xe924, KEY_REWIND }, /* (<<) */
+ { 0xeb26, KEY_FORWARD }, /* (>>) */
+ { 0xed28, KEY_STOP }, /* ([]) */
+ { 0xee29, KEY_PAUSE }, /* ('') */
+ { 0xf02b, KEY_PREVIOUS }, /* (<-) */
+ { 0xef2a, KEY_NEXT }, /* (>+) */
+ { 0xf22d, KEY_INFO }, /* PLAYING */
+ { 0xf32e, KEY_HOME }, /* TOP */
+ { 0xf42f, KEY_END }, /* END */
+ { 0xf530, KEY_SELECT }, /* SELECT */
+};
+
+static struct rc_map_list ati_x10_map = {
+ .map = {
+ .scan = ati_x10,
+ .size = ARRAY_SIZE(ati_x10),
+ .rc_type = RC_TYPE_OTHER,
+ .name = RC_MAP_ATI_X10,
+ }
+};
+
+static int __init init_rc_map_ati_x10(void)
+{
+ return rc_map_register(&ati_x10_map);
+}
+
+static void __exit exit_rc_map_ati_x10(void)
+{
+ rc_map_unregister(&ati_x10_map);
+}
+
+module_init(init_rc_map_ati_x10)
+module_exit(exit_rc_map_ati_x10)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-medion-x10.c b/drivers/media/rc/keymaps/rc-medion-x10.c
new file mode 100644
index 000000000000..09e2cc01d110
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-medion-x10.c
@@ -0,0 +1,117 @@
+/*
+ * Medion X10 RF remote keytable
+ *
+ * Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi>
+ *
+ * This file is based on a keytable provided by
+ * Jan Losinski <losinski@wh2.tu-dresden.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <media/rc-map.h>
+
+static struct rc_map_table medion_x10[] = {
+ { 0xf12c, KEY_TV }, /* TV */
+ { 0xf22d, KEY_VCR }, /* VCR */
+ { 0xc904, KEY_DVD }, /* DVD */
+ { 0xcb06, KEY_AUDIO }, /* MUSIC */
+
+ { 0xf32e, KEY_RADIO }, /* RADIO */
+ { 0xca05, KEY_DIRECTORY }, /* PHOTO */
+ { 0xf42f, KEY_INFO }, /* TV-PREVIEW */
+ { 0xf530, KEY_LIST }, /* CHANNEL-LST */
+
+ { 0xe01b, KEY_SETUP }, /* SETUP */
+ { 0xf631, KEY_VIDEO }, /* VIDEO DESKTOP */
+
+ { 0xcd08, KEY_VOLUMEDOWN }, /* VOL - */
+ { 0xce09, KEY_VOLUMEUP }, /* VOL + */
+ { 0xd00b, KEY_CHANNELUP }, /* CHAN + */
+ { 0xd10c, KEY_CHANNELDOWN }, /* CHAN - */
+ { 0xc500, KEY_MUTE }, /* MUTE */
+
+ { 0xf732, KEY_RED }, /* red */
+ { 0xf833, KEY_GREEN }, /* green */
+ { 0xf934, KEY_YELLOW }, /* yellow */
+ { 0xfa35, KEY_BLUE }, /* blue */
+ { 0xdb16, KEY_TEXT }, /* TXT */
+
+ { 0xd20d, KEY_1 },
+ { 0xd30e, KEY_2 },
+ { 0xd40f, KEY_3 },
+ { 0xd510, KEY_4 },
+ { 0xd611, KEY_5 },
+ { 0xd712, KEY_6 },
+ { 0xd813, KEY_7 },
+ { 0xd914, KEY_8 },
+ { 0xda15, KEY_9 },
+ { 0xdc17, KEY_0 },
+ { 0xe11c, KEY_SEARCH }, /* TV/RAD, CH SRC */
+ { 0xe520, KEY_DELETE }, /* DELETE */
+
+ { 0xfb36, KEY_KEYBOARD }, /* RENAME */
+ { 0xdd18, KEY_SCREEN }, /* SNAPSHOT */
+
+ { 0xdf1a, KEY_UP }, /* up */
+ { 0xe722, KEY_DOWN }, /* down */
+ { 0xe21d, KEY_LEFT }, /* left */
+ { 0xe41f, KEY_RIGHT }, /* right */
+ { 0xe31e, KEY_OK }, /* OK */
+
+ { 0xfc37, KEY_SELECT }, /* ACQUIRE IMAGE */
+ { 0xfd38, KEY_EDIT }, /* EDIT IMAGE */
+
+ { 0xe924, KEY_REWIND }, /* rewind (<<) */
+ { 0xea25, KEY_PLAY }, /* play ( >) */
+ { 0xeb26, KEY_FORWARD }, /* forward (>>) */
+ { 0xec27, KEY_RECORD }, /* record ( o) */
+ { 0xed28, KEY_STOP }, /* stop ([]) */
+ { 0xee29, KEY_PAUSE }, /* pause ('') */
+
+ { 0xe621, KEY_PREVIOUS }, /* prev */
+ { 0xfe39, KEY_SWITCHVIDEOMODE }, /* F SCR */
+ { 0xe823, KEY_NEXT }, /* next */
+ { 0xde19, KEY_MENU }, /* MENU */
+ { 0xff3a, KEY_LANGUAGE }, /* AUDIO */
+
+ { 0xc702, KEY_POWER }, /* POWER */
+};
+
+static struct rc_map_list medion_x10_map = {
+ .map = {
+ .scan = medion_x10,
+ .size = ARRAY_SIZE(medion_x10),
+ .rc_type = RC_TYPE_OTHER,
+ .name = RC_MAP_MEDION_X10,
+ }
+};
+
+static int __init init_rc_map_medion_x10(void)
+{
+ return rc_map_register(&medion_x10_map);
+}
+
+static void __exit exit_rc_map_medion_x10(void)
+{
+ rc_map_unregister(&medion_x10_map);
+}
+
+module_init(init_rc_map_medion_x10)
+module_exit(exit_rc_map_medion_x10)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
diff --git a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
index 8d558ae63456..31fc64cd17ba 100644
--- a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
+++ b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
@@ -20,6 +20,7 @@ static struct rc_map_table pinnacle_pctv_hd[] = {
{ 0x0701, KEY_MENU }, /* Pinnacle logo */
{ 0x0739, KEY_POWER },
{ 0x0703, KEY_VOLUMEUP },
+ { 0x0705, KEY_OK },
{ 0x0709, KEY_VOLUMEDOWN },
{ 0x0706, KEY_CHANNELUP },
{ 0x070c, KEY_CHANNELDOWN },
diff --git a/drivers/media/rc/keymaps/rc-snapstream-firefly.c b/drivers/media/rc/keymaps/rc-snapstream-firefly.c
new file mode 100644
index 000000000000..ef146520931c
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-snapstream-firefly.c
@@ -0,0 +1,107 @@
+/*
+ * SnapStream Firefly X10 RF remote keytable
+ *
+ * Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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/module.h>
+#include <media/rc-map.h>
+
+static struct rc_map_table snapstream_firefly[] = {
+ { 0xf12c, KEY_ZOOM }, /* Maximize */
+ { 0xc702, KEY_CLOSE },
+
+ { 0xd20d, KEY_1 },
+ { 0xd30e, KEY_2 },
+ { 0xd40f, KEY_3 },
+ { 0xd510, KEY_4 },
+ { 0xd611, KEY_5 },
+ { 0xd712, KEY_6 },
+ { 0xd813, KEY_7 },
+ { 0xd914, KEY_8 },
+ { 0xda15, KEY_9 },
+ { 0xdc17, KEY_0 },
+ { 0xdb16, KEY_BACK },
+ { 0xdd18, KEY_KPENTER }, /* ent */
+
+ { 0xce09, KEY_VOLUMEUP },
+ { 0xcd08, KEY_VOLUMEDOWN },
+ { 0xcf0a, KEY_MUTE },
+ { 0xd00b, KEY_CHANNELUP },
+ { 0xd10c, KEY_CHANNELDOWN },
+ { 0xc500, KEY_VENDOR }, /* firefly */
+
+ { 0xf32e, KEY_INFO },
+ { 0xf42f, KEY_OPTION },
+
+ { 0xe21d, KEY_LEFT },
+ { 0xe41f, KEY_RIGHT },
+ { 0xe722, KEY_DOWN },
+ { 0xdf1a, KEY_UP },
+ { 0xe31e, KEY_OK },
+
+ { 0xe11c, KEY_MENU },
+ { 0xe520, KEY_EXIT },
+
+ { 0xec27, KEY_RECORD },
+ { 0xea25, KEY_PLAY },
+ { 0xed28, KEY_STOP },
+ { 0xe924, KEY_REWIND },
+ { 0xeb26, KEY_FORWARD },
+ { 0xee29, KEY_PAUSE },
+ { 0xf02b, KEY_PREVIOUS },
+ { 0xef2a, KEY_NEXT },
+
+ { 0xcb06, KEY_AUDIO }, /* Music */
+ { 0xca05, KEY_IMAGES }, /* Photos */
+ { 0xc904, KEY_DVD },
+ { 0xc803, KEY_TV },
+ { 0xcc07, KEY_VIDEO },
+
+ { 0xc601, KEY_HELP },
+ { 0xf22d, KEY_MODE }, /* Mouse */
+
+ { 0xde19, KEY_A },
+ { 0xe01b, KEY_B },
+ { 0xe621, KEY_C },
+ { 0xe823, KEY_D },
+};
+
+static struct rc_map_list snapstream_firefly_map = {
+ .map = {
+ .scan = snapstream_firefly,
+ .size = ARRAY_SIZE(snapstream_firefly),
+ .rc_type = RC_TYPE_OTHER,
+ .name = RC_MAP_SNAPSTREAM_FIREFLY,
+ }
+};
+
+static int __init init_rc_map_snapstream_firefly(void)
+{
+ return rc_map_register(&snapstream_firefly_map);
+}
+
+static void __exit exit_rc_map_snapstream_firefly(void)
+{
+ rc_map_unregister(&snapstream_firefly_map);
+}
+
+module_init(init_rc_map_snapstream_firefly)
+module_exit(exit_rc_map_snapstream_firefly)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 85ff9a1ffb39..60d3c1e09712 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1,7 +1,7 @@
/*
* Driver for USB Windows Media Center Ed. eHome Infrared Transceivers
*
- * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
+ * Copyright (c) 2010-2011, Jarod Wilson <jarod@redhat.com>
*
* Based on the original lirc_mceusb and lirc_mceusb2 drivers, by Dan
* Conti, Martin Blatter and Daniel Melander, the latter of which was
@@ -15,6 +15,11 @@
* Jon Smirl, which included enhancements and simplifications to the
* incoming IR buffer parsing routines.
*
+ * Updated in July of 2011 with the aid of Microsoft's official
+ * remote/transceiver requirements and specification document, found at
+ * download.microsoft.com, title
+ * Windows-Media-Center-RC-IR-Collection-Green-Button-Specification-03-08-2011-V2.pdf
+ *
*
* 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
@@ -37,10 +42,11 @@
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/input.h>
+#include <linux/pm_wakeup.h>
#include <media/rc-core.h>
-#define DRIVER_VERSION "1.91"
-#define DRIVER_AUTHOR "Jarod Wilson <jarod@wilsonet.com>"
+#define DRIVER_VERSION "1.92"
+#define DRIVER_AUTHOR "Jarod Wilson <jarod@redhat.com>"
#define DRIVER_DESC "Windows Media Center Ed. eHome Infrared Transceiver " \
"device driver"
#define DRIVER_NAME "mceusb"
@@ -63,43 +69,90 @@
#define MCE_PULSE_MASK 0x7f /* Pulse mask */
#define MCE_MAX_PULSE_LENGTH 0x7f /* Longest transmittable pulse symbol */
-#define MCE_HW_CMD_HEADER 0xff /* MCE hardware command header */
-#define MCE_COMMAND_HEADER 0x9f /* MCE command header */
-#define MCE_COMMAND_MASK 0xe0 /* Mask out command bits */
-#define MCE_COMMAND_NULL 0x00 /* These show up various places... */
-/* if buf[i] & MCE_COMMAND_MASK == 0x80 and buf[i] != MCE_COMMAND_HEADER,
- * then we're looking at a raw IR data sample */
-#define MCE_COMMAND_IRDATA 0x80
-#define MCE_PACKET_LENGTH_MASK 0x1f /* Packet length mask */
-
-/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
+/*
+ * The interface between the host and the IR hardware is command-response
+ * based. All commands and responses have a consistent format, where a lead
+ * byte always identifies the type of data following it. The lead byte has
+ * a port value in the 3 highest bits and a length value in the 5 lowest
+ * bits.
+ *
+ * The length field is overloaded, with a value of 11111 indicating that the
+ * following byte is a command or response code, and the length of the entire
+ * message is determined by the code. If the length field is not 11111, then
+ * it specifies the number of bytes of port data that follow.
+ */
+#define MCE_CMD 0x1f
+#define MCE_PORT_IR 0x4 /* (0x4 << 5) | MCE_CMD = 0x9f */
+#define MCE_PORT_SYS 0x7 /* (0x7 << 5) | MCE_CMD = 0xff */
+#define MCE_PORT_SER 0x6 /* 0xc0 thru 0xdf flush & 0x1f bytes */
+#define MCE_PORT_MASK 0xe0 /* Mask out command bits */
+
+/* Command port headers */
+#define MCE_CMD_PORT_IR 0x9f /* IR-related cmd/rsp */
+#define MCE_CMD_PORT_SYS 0xff /* System (non-IR) device cmd/rsp */
+
+/* Commands that set device state (2-4 bytes in length) */
+#define MCE_CMD_RESET 0xfe /* Reset device, 2 bytes */
+#define MCE_CMD_RESUME 0xaa /* Resume device after error, 2 bytes */
+#define MCE_CMD_SETIRCFS 0x06 /* Set tx carrier, 4 bytes */
+#define MCE_CMD_SETIRTIMEOUT 0x0c /* Set timeout, 4 bytes */
+#define MCE_CMD_SETIRTXPORTS 0x08 /* Set tx ports, 3 bytes */
+#define MCE_CMD_SETIRRXPORTEN 0x14 /* Set rx ports, 3 bytes */
+#define MCE_CMD_FLASHLED 0x23 /* Flash receiver LED, 2 bytes */
+
+/* Commands that query device state (all 2 bytes, unless noted) */
+#define MCE_CMD_GETIRCFS 0x07 /* Get carrier */
+#define MCE_CMD_GETIRTIMEOUT 0x0d /* Get timeout */
+#define MCE_CMD_GETIRTXPORTS 0x13 /* Get tx ports */
+#define MCE_CMD_GETIRRXPORTEN 0x15 /* Get rx ports */
+#define MCE_CMD_GETPORTSTATUS 0x11 /* Get tx port status, 3 bytes */
+#define MCE_CMD_GETIRNUMPORTS 0x16 /* Get number of ports */
+#define MCE_CMD_GETWAKESOURCE 0x17 /* Get wake source */
+#define MCE_CMD_GETEMVER 0x22 /* Get emulator interface version */
+#define MCE_CMD_GETDEVDETAILS 0x21 /* Get device details (em ver2 only) */
+#define MCE_CMD_GETWAKESUPPORT 0x20 /* Get wake details (em ver2 only) */
+#define MCE_CMD_GETWAKEVERSION 0x18 /* Get wake pattern (em ver2 only) */
+
+/* Misc commands */
+#define MCE_CMD_NOP 0xff /* No operation */
+
+/* Responses to commands (non-error cases) */
+#define MCE_RSP_EQIRCFS 0x06 /* tx carrier, 4 bytes */
+#define MCE_RSP_EQIRTIMEOUT 0x0c /* rx timeout, 4 bytes */
+#define MCE_RSP_GETWAKESOURCE 0x17 /* wake source, 3 bytes */
+#define MCE_RSP_EQIRTXPORTS 0x08 /* tx port mask, 3 bytes */
+#define MCE_RSP_EQIRRXPORTEN 0x14 /* rx port mask, 3 bytes */
+#define MCE_RSP_GETPORTSTATUS 0x11 /* tx port status, 7 bytes */
+#define MCE_RSP_EQIRRXCFCNT 0x15 /* rx carrier count, 4 bytes */
+#define MCE_RSP_EQIRNUMPORTS 0x16 /* number of ports, 4 bytes */
+#define MCE_RSP_EQWAKESUPPORT 0x20 /* wake capabilities, 3 bytes */
+#define MCE_RSP_EQWAKEVERSION 0x18 /* wake pattern details, 6 bytes */
+#define MCE_RSP_EQDEVDETAILS 0x21 /* device capabilities, 3 bytes */
+#define MCE_RSP_EQEMVER 0x22 /* emulator interface ver, 3 bytes */
+#define MCE_RSP_FLASHLED 0x23 /* success flashing LED, 2 bytes */
+
+/* Responses to error cases, must send MCE_CMD_RESUME to clear them */
+#define MCE_RSP_CMD_ILLEGAL 0xfe /* illegal command for port, 2 bytes */
+#define MCE_RSP_TX_TIMEOUT 0x81 /* tx timed out, 2 bytes */
+
+/* Misc commands/responses not defined in the MCE remote/transceiver spec */
#define MCE_CMD_SIG_END 0x01 /* End of signal */
#define MCE_CMD_PING 0x03 /* Ping device */
#define MCE_CMD_UNKNOWN 0x04 /* Unknown */
#define MCE_CMD_UNKNOWN2 0x05 /* Unknown */
-#define MCE_CMD_S_CARRIER 0x06 /* Set TX carrier frequency */
-#define MCE_CMD_G_CARRIER 0x07 /* Get TX carrier frequency */
-#define MCE_CMD_S_TXMASK 0x08 /* Set TX port bitmask */
#define MCE_CMD_UNKNOWN3 0x09 /* Unknown */
#define MCE_CMD_UNKNOWN4 0x0a /* Unknown */
#define MCE_CMD_G_REVISION 0x0b /* Get hw/sw revision */
-#define MCE_CMD_S_TIMEOUT 0x0c /* Set RX timeout value */
-#define MCE_CMD_G_TIMEOUT 0x0d /* Get RX timeout value */
#define MCE_CMD_UNKNOWN5 0x0e /* Unknown */
#define MCE_CMD_UNKNOWN6 0x0f /* Unknown */
-#define MCE_CMD_G_RXPORTSTS 0x11 /* Get RX port status */
-#define MCE_CMD_G_TXMASK 0x13 /* Set TX port bitmask */
-#define MCE_CMD_S_RXSENSOR 0x14 /* Set RX sensor (std/learning) */
-#define MCE_CMD_G_RXSENSOR 0x15 /* Get RX sensor (std/learning) */
-#define MCE_RSP_PULSE_COUNT 0x15 /* RX pulse count (only if learning) */
-#define MCE_CMD_TX_PORTS 0x16 /* Get number of TX ports */
-#define MCE_CMD_G_WAKESRC 0x17 /* Get wake source */
-#define MCE_CMD_UNKNOWN7 0x18 /* Unknown */
#define MCE_CMD_UNKNOWN8 0x19 /* Unknown */
#define MCE_CMD_UNKNOWN9 0x1b /* Unknown */
-#define MCE_CMD_DEVICE_RESET 0xaa /* Reset the hardware */
-#define MCE_RSP_CMD_INVALID 0xfe /* Invalid command issued */
+#define MCE_CMD_NULL 0x00 /* These show up various places... */
+/* if buf[i] & MCE_PORT_MASK == 0x80 and buf[i] != MCE_CMD_PORT_IR,
+ * then we're looking at a raw IR data sample */
+#define MCE_COMMAND_IRDATA 0x80
+#define MCE_PACKET_LENGTH_MASK 0x1f /* Packet length mask */
/* module parameters */
#ifdef CONFIG_USB_DEBUG
@@ -388,48 +441,37 @@ struct mceusb_dev {
char name[128];
char phys[64];
enum mceusb_model_type model;
+
+ bool need_reset; /* flag to issue a device resume cmd */
+ u8 emver; /* emulator interface version */
+ u8 num_txports; /* number of transmit ports */
+ u8 num_rxports; /* number of receive sensors */
+ u8 txports_cabled; /* bitmask of transmitters with cable */
+ u8 rxports_active; /* bitmask of active receive sensors */
};
-/*
- * MCE Device Command Strings
- * Device command responses vary from device to device...
- * - DEVICE_RESET resets the hardware to its default state
- * - GET_REVISION fetches the hardware/software revision, common
- * replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42
- * - GET_CARRIER_FREQ gets the carrier mode and frequency of the
- * device, with replies in the form of 9f 06 MM FF, where MM is 0-3,
- * meaning clk of 10000000, 2500000, 625000 or 156250, and FF is
- * ((clk / frequency) - 1)
- * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us,
- * response in the form of 9f 0c msb lsb
- * - GET_TX_BITMASK fetches the transmitter bitmask, replies in
- * the form of 9f 08 bm, where bm is the bitmask
- * - GET_RX_SENSOR fetches the RX sensor setting -- long-range
- * general use one or short-range learning one, in the form of
- * 9f 14 ss, where ss is either 01 for long-range or 02 for short
- * - SET_CARRIER_FREQ sets a new carrier mode and frequency
- * - SET_TX_BITMASK sets the transmitter bitmask
- * - SET_RX_TIMEOUT sets the receiver timeout
- * - SET_RX_SENSOR sets which receiver sensor to use
- */
-static char DEVICE_RESET[] = {MCE_COMMAND_NULL, MCE_HW_CMD_HEADER,
- MCE_CMD_DEVICE_RESET};
-static char GET_REVISION[] = {MCE_HW_CMD_HEADER, MCE_CMD_G_REVISION};
-static char GET_UNKNOWN[] = {MCE_HW_CMD_HEADER, MCE_CMD_UNKNOWN7};
-static char GET_UNKNOWN2[] = {MCE_COMMAND_HEADER, MCE_CMD_UNKNOWN2};
-static char GET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER, MCE_CMD_G_CARRIER};
-static char GET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TIMEOUT};
-static char GET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TXMASK};
-static char GET_RX_SENSOR[] = {MCE_COMMAND_HEADER, MCE_CMD_G_RXSENSOR};
+/* MCE Device Command Strings, generally a port and command pair */
+static char DEVICE_RESUME[] = {MCE_CMD_NULL, MCE_CMD_PORT_SYS,
+ MCE_CMD_RESUME};
+static char GET_REVISION[] = {MCE_CMD_PORT_SYS, MCE_CMD_G_REVISION};
+static char GET_EMVER[] = {MCE_CMD_PORT_SYS, MCE_CMD_GETEMVER};
+static char GET_WAKEVERSION[] = {MCE_CMD_PORT_SYS, MCE_CMD_GETWAKEVERSION};
+static char FLASH_LED[] = {MCE_CMD_PORT_SYS, MCE_CMD_FLASHLED};
+static char GET_UNKNOWN2[] = {MCE_CMD_PORT_IR, MCE_CMD_UNKNOWN2};
+static char GET_CARRIER_FREQ[] = {MCE_CMD_PORT_IR, MCE_CMD_GETIRCFS};
+static char GET_RX_TIMEOUT[] = {MCE_CMD_PORT_IR, MCE_CMD_GETIRTIMEOUT};
+static char GET_NUM_PORTS[] = {MCE_CMD_PORT_IR, MCE_CMD_GETIRNUMPORTS};
+static char GET_TX_BITMASK[] = {MCE_CMD_PORT_IR, MCE_CMD_GETIRTXPORTS};
+static char GET_RX_SENSOR[] = {MCE_CMD_PORT_IR, MCE_CMD_GETIRRXPORTEN};
/* sub in desired values in lower byte or bytes for full command */
/* FIXME: make use of these for transmit.
-static char SET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER,
- MCE_CMD_S_CARRIER, 0x00, 0x00};
-static char SET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_S_TXMASK, 0x00};
-static char SET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER,
- MCE_CMD_S_TIMEOUT, 0x00, 0x00};
-static char SET_RX_SENSOR[] = {MCE_COMMAND_HEADER,
- MCE_CMD_S_RXSENSOR, 0x00};
+static char SET_CARRIER_FREQ[] = {MCE_CMD_PORT_IR,
+ MCE_CMD_SETIRCFS, 0x00, 0x00};
+static char SET_TX_BITMASK[] = {MCE_CMD_PORT_IR, MCE_CMD_SETIRTXPORTS, 0x00};
+static char SET_RX_TIMEOUT[] = {MCE_CMD_PORT_IR,
+ MCE_CMD_SETIRTIMEOUT, 0x00, 0x00};
+static char SET_RX_SENSOR[] = {MCE_CMD_PORT_IR,
+ MCE_RSP_EQIRRXPORTEN, 0x00};
*/
static int mceusb_cmdsize(u8 cmd, u8 subcmd)
@@ -437,27 +479,33 @@ static int mceusb_cmdsize(u8 cmd, u8 subcmd)
int datasize = 0;
switch (cmd) {
- case MCE_COMMAND_NULL:
- if (subcmd == MCE_HW_CMD_HEADER)
+ case MCE_CMD_NULL:
+ if (subcmd == MCE_CMD_PORT_SYS)
datasize = 1;
break;
- case MCE_HW_CMD_HEADER:
+ case MCE_CMD_PORT_SYS:
switch (subcmd) {
+ case MCE_RSP_EQWAKEVERSION:
+ datasize = 4;
+ break;
case MCE_CMD_G_REVISION:
datasize = 2;
break;
+ case MCE_RSP_EQWAKESUPPORT:
+ datasize = 1;
+ break;
}
- case MCE_COMMAND_HEADER:
+ case MCE_CMD_PORT_IR:
switch (subcmd) {
case MCE_CMD_UNKNOWN:
- case MCE_CMD_S_CARRIER:
- case MCE_CMD_S_TIMEOUT:
- case MCE_RSP_PULSE_COUNT:
+ case MCE_RSP_EQIRCFS:
+ case MCE_RSP_EQIRTIMEOUT:
+ case MCE_RSP_EQIRRXCFCNT:
datasize = 2;
break;
case MCE_CMD_SIG_END:
- case MCE_CMD_S_TXMASK:
- case MCE_CMD_S_RXSENSOR:
+ case MCE_RSP_EQIRTXPORTS:
+ case MCE_RSP_EQIRRXPORTEN:
datasize = 1;
break;
}
@@ -470,9 +518,10 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
{
char codes[USB_BUFLEN * 3 + 1];
char inout[9];
- u8 cmd, subcmd, data1, data2;
+ u8 cmd, subcmd, data1, data2, data3, data4, data5;
struct device *dev = ir->dev;
int i, start, skip = 0;
+ u32 carrier, period;
if (!debug)
return;
@@ -500,18 +549,28 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
subcmd = buf[start + 1] & 0xff;
data1 = buf[start + 2] & 0xff;
data2 = buf[start + 3] & 0xff;
+ data3 = buf[start + 4] & 0xff;
+ data4 = buf[start + 5] & 0xff;
+ data5 = buf[start + 6] & 0xff;
switch (cmd) {
- case MCE_COMMAND_NULL:
- if ((subcmd == MCE_HW_CMD_HEADER) &&
- (data1 == MCE_CMD_DEVICE_RESET))
- dev_info(dev, "Device reset requested\n");
+ case MCE_CMD_NULL:
+ if (subcmd == MCE_CMD_NULL)
+ break;
+ if ((subcmd == MCE_CMD_PORT_SYS) &&
+ (data1 == MCE_CMD_RESUME))
+ dev_info(dev, "Device resume requested\n");
else
dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
cmd, subcmd);
break;
- case MCE_HW_CMD_HEADER:
+ case MCE_CMD_PORT_SYS:
switch (subcmd) {
+ case MCE_RSP_EQEMVER:
+ if (!out)
+ dev_info(dev, "Emulator interface version %x\n",
+ data1);
+ break;
case MCE_CMD_G_REVISION:
if (len == 2)
dev_info(dev, "Get hw/sw rev?\n");
@@ -520,21 +579,35 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
"0x%02x 0x%02x\n", data1, data2,
buf[start + 4], buf[start + 5]);
break;
- case MCE_CMD_DEVICE_RESET:
- dev_info(dev, "Device reset requested\n");
+ case MCE_CMD_RESUME:
+ dev_info(dev, "Device resume requested\n");
+ break;
+ case MCE_RSP_CMD_ILLEGAL:
+ dev_info(dev, "Illegal PORT_SYS command\n");
break;
- case MCE_RSP_CMD_INVALID:
- dev_info(dev, "Previous command not supported\n");
+ case MCE_RSP_EQWAKEVERSION:
+ if (!out)
+ dev_info(dev, "Wake version, proto: 0x%02x, "
+ "payload: 0x%02x, address: 0x%02x, "
+ "version: 0x%02x\n",
+ data1, data2, data3, data4);
+ break;
+ case MCE_RSP_GETPORTSTATUS:
+ if (!out)
+ /* We use data1 + 1 here, to match hw labels */
+ dev_info(dev, "TX port %d: blaster is%s connected\n",
+ data1 + 1, data4 ? " not" : "");
+ break;
+ case MCE_CMD_FLASHLED:
+ dev_info(dev, "Attempting to flash LED\n");
break;
- case MCE_CMD_UNKNOWN7:
- case MCE_CMD_UNKNOWN9:
default:
dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
cmd, subcmd);
break;
}
break;
- case MCE_COMMAND_HEADER:
+ case MCE_CMD_PORT_IR:
switch (subcmd) {
case MCE_CMD_SIG_END:
dev_info(dev, "End of signal\n");
@@ -546,47 +619,55 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n",
data1, data2);
break;
- case MCE_CMD_S_CARRIER:
- dev_info(dev, "%s carrier mode and freq of "
- "0x%02x 0x%02x\n", inout, data1, data2);
+ case MCE_RSP_EQIRCFS:
+ period = DIV_ROUND_CLOSEST(
+ (1 << data1 * 2) * (data2 + 1), 10);
+ if (!period)
+ break;
+ carrier = (1000 * 1000) / period;
+ dev_info(dev, "%s carrier of %u Hz (period %uus)\n",
+ inout, carrier, period);
break;
- case MCE_CMD_G_CARRIER:
+ case MCE_CMD_GETIRCFS:
dev_info(dev, "Get carrier mode and freq\n");
break;
- case MCE_CMD_S_TXMASK:
+ case MCE_RSP_EQIRTXPORTS:
dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
inout, data1);
break;
- case MCE_CMD_S_TIMEOUT:
+ case MCE_RSP_EQIRTIMEOUT:
/* value is in units of 50us, so x*50/1000 ms */
+ period = ((data1 << 8) | data2) * MCE_TIME_UNIT / 1000;
dev_info(dev, "%s receive timeout of %d ms\n",
- inout,
- ((data1 << 8) | data2) * MCE_TIME_UNIT / 1000);
+ inout, period);
break;
- case MCE_CMD_G_TIMEOUT:
+ case MCE_CMD_GETIRTIMEOUT:
dev_info(dev, "Get receive timeout\n");
break;
- case MCE_CMD_G_TXMASK:
+ case MCE_CMD_GETIRTXPORTS:
dev_info(dev, "Get transmit blaster mask\n");
break;
- case MCE_CMD_S_RXSENSOR:
+ case MCE_RSP_EQIRRXPORTEN:
dev_info(dev, "%s %s-range receive sensor in use\n",
inout, data1 == 0x02 ? "short" : "long");
break;
- case MCE_CMD_G_RXSENSOR:
- /* aka MCE_RSP_PULSE_COUNT */
+ case MCE_CMD_GETIRRXPORTEN:
+ /* aka MCE_RSP_EQIRRXCFCNT */
if (out)
dev_info(dev, "Get receive sensor\n");
else if (ir->learning_enabled)
dev_info(dev, "RX pulse count: %d\n",
((data1 << 8) | data2));
break;
- case MCE_RSP_CMD_INVALID:
- dev_info(dev, "Error! Hardware is likely wedged...\n");
+ case MCE_RSP_EQIRNUMPORTS:
+ if (out)
+ break;
+ dev_info(dev, "Num TX ports: %x, num RX ports: %x\n",
+ data1, data2);
+ break;
+ case MCE_RSP_CMD_ILLEGAL:
+ dev_info(dev, "Illegal PORT_IR command\n");
break;
- case MCE_CMD_UNKNOWN2:
- case MCE_CMD_UNKNOWN3:
- case MCE_CMD_UNKNOWN5:
default:
dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
cmd, subcmd);
@@ -599,8 +680,8 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
if (cmd == MCE_IRDATA_TRAILER)
dev_info(dev, "End of raw IR data\n");
- else if ((cmd != MCE_COMMAND_HEADER) &&
- ((cmd & MCE_COMMAND_MASK) == MCE_COMMAND_IRDATA))
+ else if ((cmd != MCE_CMD_PORT_IR) &&
+ ((cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA))
dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem);
}
@@ -616,9 +697,6 @@ static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
if (ir) {
len = urb->actual_length;
- mce_dbg(ir->dev, "callback called (status=%d len=%d)\n",
- urb->status, len);
-
mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
}
@@ -683,7 +761,16 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
{
+ int rsize = sizeof(DEVICE_RESUME);
+
+ if (ir->need_reset) {
+ ir->need_reset = false;
+ mce_request_packet(ir, DEVICE_RESUME, rsize, MCEUSB_TX);
+ msleep(10);
+ }
+
mce_request_packet(ir, data, size, MCEUSB_TX);
+ msleep(10);
}
static void mce_flush_rx_buffer(struct mceusb_dev *ir, int size)
@@ -708,8 +795,8 @@ static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
return -ENOMEM;
/* MCE tx init header */
- cmdbuf[cmdcount++] = MCE_COMMAND_HEADER;
- cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK;
+ cmdbuf[cmdcount++] = MCE_CMD_PORT_IR;
+ cmdbuf[cmdcount++] = MCE_CMD_SETIRTXPORTS;
cmdbuf[cmdcount++] = ir->tx_mask;
/* Generate mce packet data */
@@ -795,8 +882,8 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)
struct mceusb_dev *ir = dev->priv;
int clk = 10000000;
int prescaler = 0, divisor = 0;
- unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER,
- MCE_CMD_S_CARRIER, 0x00, 0x00 };
+ unsigned char cmdbuf[4] = { MCE_CMD_PORT_IR,
+ MCE_CMD_SETIRCFS, 0x00, 0x00 };
/* Carrier has changed */
if (ir->carrier != carrier) {
@@ -844,17 +931,34 @@ static void mceusb_handle_command(struct mceusb_dev *ir, int index)
u8 lo = ir->buf_in[index + 2] & 0xff;
switch (ir->buf_in[index]) {
+ /* the one and only 5-byte return value command */
+ case MCE_RSP_GETPORTSTATUS:
+ if ((ir->buf_in[index + 4] & 0xff) == 0x00)
+ ir->txports_cabled |= 1 << hi;
+ break;
+
/* 2-byte return value commands */
- case MCE_CMD_S_TIMEOUT:
+ case MCE_RSP_EQIRTIMEOUT:
ir->rc->timeout = US_TO_NS((hi << 8 | lo) * MCE_TIME_UNIT);
break;
+ case MCE_RSP_EQIRNUMPORTS:
+ ir->num_txports = hi;
+ ir->num_rxports = lo;
+ break;
/* 1-byte return value commands */
- case MCE_CMD_S_TXMASK:
+ case MCE_RSP_EQEMVER:
+ ir->emver = hi;
+ break;
+ case MCE_RSP_EQIRTXPORTS:
ir->tx_mask = hi;
break;
- case MCE_CMD_S_RXSENSOR:
- ir->learning_enabled = (hi == 0x02);
+ case MCE_RSP_EQIRRXPORTEN:
+ ir->learning_enabled = ((hi & 0x02) == 0x02);
+ ir->rxports_active = hi;
+ break;
+ case MCE_RSP_CMD_ILLEGAL:
+ ir->need_reset = true;
break;
default:
break;
@@ -903,8 +1007,8 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
/* decode mce packets of the form (84),AA,BB,CC,DD */
/* IR data packets can span USB messages - rem */
ir->cmd = ir->buf_in[i];
- if ((ir->cmd == MCE_COMMAND_HEADER) ||
- ((ir->cmd & MCE_COMMAND_MASK) !=
+ if ((ir->cmd == MCE_CMD_PORT_IR) ||
+ ((ir->cmd & MCE_PORT_MASK) !=
MCE_COMMAND_IRDATA)) {
ir->parser_state = SUBCMD;
continue;
@@ -969,6 +1073,13 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
usb_submit_urb(urb, GFP_ATOMIC);
}
+static void mceusb_get_emulator_version(struct mceusb_dev *ir)
+{
+ /* If we get no reply or an illegal command reply, its ver 1, says MS */
+ ir->emver = 1;
+ mce_async_out(ir, GET_EMVER, sizeof(GET_EMVER));
+}
+
static void mceusb_gen1_init(struct mceusb_dev *ir)
{
int ret;
@@ -1011,8 +1122,8 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
0x0000, 0x0100, NULL, 0, HZ * 3);
mce_dbg(dev, "%s - retC = %d\n", __func__, ret);
- /* device reset */
- mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
+ /* device resume */
+ mce_async_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME));
/* get hw/sw revision? */
mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
@@ -1022,23 +1133,36 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
static void mceusb_gen2_init(struct mceusb_dev *ir)
{
- /* device reset */
- mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
+ /* device resume */
+ mce_async_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME));
/* get hw/sw revision? */
mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
- /* unknown what the next two actually return... */
- mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN));
+ /* get wake version (protocol, key, address) */
+ mce_async_out(ir, GET_WAKEVERSION, sizeof(GET_WAKEVERSION));
+
+ /* unknown what this one actually returns... */
mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2));
}
static void mceusb_get_parameters(struct mceusb_dev *ir)
{
+ int i;
+ unsigned char cmdbuf[3] = { MCE_CMD_PORT_SYS,
+ MCE_CMD_GETPORTSTATUS, 0x00 };
+
+ /* defaults, if the hardware doesn't support querying */
+ ir->num_txports = 2;
+ ir->num_rxports = 2;
+
+ /* get number of tx and rx ports */
+ mce_async_out(ir, GET_NUM_PORTS, sizeof(GET_NUM_PORTS));
+
/* get the carrier and frequency */
mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
- if (!ir->flags.no_tx)
+ if (ir->num_txports && !ir->flags.no_tx)
/* get the transmitter bitmask */
mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
@@ -1047,6 +1171,19 @@ static void mceusb_get_parameters(struct mceusb_dev *ir)
/* get receiver sensor setting */
mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR));
+
+ for (i = 0; i < ir->num_txports; i++) {
+ cmdbuf[2] = i;
+ mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+ }
+}
+
+static void mceusb_flash_led(struct mceusb_dev *ir)
+{
+ if (ir->emver < 2)
+ return;
+
+ mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED));
}
static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
@@ -1220,6 +1357,9 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
mce_dbg(&intf->dev, "Flushing receive buffers\n");
mce_flush_rx_buffer(ir, maxp);
+ /* figure out which firmware/emulator version this hardware has */
+ mceusb_get_emulator_version(ir);
+
/* initialize device */
if (ir->flags.microsoft_gen1)
mceusb_gen1_init(ir);
@@ -1228,13 +1368,23 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
mceusb_get_parameters(ir);
+ mceusb_flash_led(ir);
+
if (!ir->flags.no_tx)
mceusb_set_tx_mask(ir->rc, MCE_DEFAULT_TX_MASK);
usb_set_intfdata(intf, ir);
- dev_info(&intf->dev, "Registered %s on usb%d:%d\n", name,
- dev->bus->busnum, dev->devnum);
+ /* enable wake via this device */
+ device_set_wakeup_capable(ir->dev, true);
+ device_set_wakeup_enable(ir->dev, true);
+
+ dev_info(&intf->dev, "Registered %s with mce emulator interface "
+ "version %x\n", name, ir->emver);
+ dev_info(&intf->dev, "%x tx ports (0x%x cabled) and "
+ "%x rx sensors (0x%x active)\n",
+ ir->num_txports, ir->txports_cabled,
+ ir->num_rxports, ir->rxports_active);
return 0;
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 04c2c722b6ec..c6ca870e8b7e 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -162,49 +162,49 @@ void ir_raw_init(void);
#ifdef CONFIG_IR_NEC_DECODER_MODULE
#define load_nec_decode() request_module("ir-nec-decoder")
#else
-#define load_nec_decode() 0
+static inline void load_nec_decode(void) { }
#endif
/* from ir-rc5-decoder.c */
#ifdef CONFIG_IR_RC5_DECODER_MODULE
#define load_rc5_decode() request_module("ir-rc5-decoder")
#else
-#define load_rc5_decode() 0
+static inline void load_rc5_decode(void) { }
#endif
/* from ir-rc6-decoder.c */
#ifdef CONFIG_IR_RC6_DECODER_MODULE
#define load_rc6_decode() request_module("ir-rc6-decoder")
#else
-#define load_rc6_decode() 0
+static inline void load_rc6_decode(void) { }
#endif
/* from ir-jvc-decoder.c */
#ifdef CONFIG_IR_JVC_DECODER_MODULE
#define load_jvc_decode() request_module("ir-jvc-decoder")
#else
-#define load_jvc_decode() 0
+static inline void load_jvc_decode(void) { }
#endif
/* from ir-sony-decoder.c */
#ifdef CONFIG_IR_SONY_DECODER_MODULE
#define load_sony_decode() request_module("ir-sony-decoder")
#else
-#define load_sony_decode() 0
+static inline void load_sony_decode(void) { }
#endif
/* from ir-mce_kbd-decoder.c */
#ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE
#define load_mce_kbd_decode() request_module("ir-mce_kbd-decoder")
#else
-#define load_mce_kbd_decode() 0
+static inline void load_mce_kbd_decode(void) { }
#endif
/* from ir-lirc-codec.c */
#ifdef CONFIG_IR_LIRC_CODEC_MODULE
#define load_lirc_codec() request_module("ir-lirc-codec")
#else
-#define load_lirc_codec() 0
+static inline void load_lirc_codec(void) { }
#endif
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 51a23f48bc7d..666d4bb5b1fb 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -928,10 +928,6 @@ out:
static void rc_dev_release(struct device *device)
{
- struct rc_dev *dev = to_rc_dev(device);
-
- kfree(dev);
- module_put(THIS_MODULE);
}
#define ADD_HOTPLUG_VAR(fmt, val...) \
@@ -945,6 +941,9 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
{
struct rc_dev *dev = to_rc_dev(device);
+ if (!dev || !dev->input_dev)
+ return -ENODEV;
+
if (dev->rc_map.name)
ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
if (dev->driver_name)
@@ -1013,10 +1012,16 @@ EXPORT_SYMBOL_GPL(rc_allocate_device);
void rc_free_device(struct rc_dev *dev)
{
- if (dev) {
+ if (!dev)
+ return;
+
+ if (dev->input_dev)
input_free_device(dev->input_dev);
- put_device(&dev->dev);
- }
+
+ put_device(&dev->dev);
+
+ kfree(dev);
+ module_put(THIS_MODULE);
}
EXPORT_SYMBOL_GPL(rc_free_device);
@@ -1143,14 +1148,18 @@ void rc_unregister_device(struct rc_dev *dev)
if (dev->driver_type == RC_DRIVER_IR_RAW)
ir_raw_event_unregister(dev);
+ /* Freeing the table should also call the stop callback */
+ ir_free_table(&dev->rc_map);
+ IR_dprintk(1, "Freed keycode table\n");
+
input_unregister_device(dev->input_dev);
dev->input_dev = NULL;
- ir_free_table(&dev->rc_map);
- IR_dprintk(1, "Freed keycode table\n");
+ device_del(&dev->dev);
- device_unregister(&dev->dev);
+ rc_free_device(dev);
}
+
EXPORT_SYMBOL_GPL(rc_unregister_device);
/*
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index a16604477917..61287fcca61a 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -195,11 +195,6 @@ struct redrat3_dev {
dma_addr_t dma_in;
dma_addr_t dma_out;
- /* true if write urb is busy */
- bool write_busy;
- /* wait for the write to finish */
- struct completion write_finished;
-
/* locks this structure */
struct mutex lock;
@@ -207,8 +202,6 @@ struct redrat3_dev {
struct timer_list rx_timeout;
u32 hw_timeout;
- /* Is the device currently receiving? */
- bool recv_in_progress;
/* is the detector enabled*/
bool det_enabled;
/* Is the device currently transmitting?*/
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index bec8abc965f7..13f54b51194a 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -41,6 +41,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/pnp.h>
#include <linux/interrupt.h>
@@ -1155,12 +1157,12 @@ wbcir_init(void)
case IR_PROTOCOL_RC6:
break;
default:
- printk(KERN_ERR DRVNAME ": Invalid power-on protocol\n");
+ pr_err("Invalid power-on protocol\n");
}
ret = pnp_register_driver(&wbcir_driver);
if (ret)
- printk(KERN_ERR DRVNAME ": Unable to register driver\n");
+ pr_err("Unable to register driver\n");
return ret;
}
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index f574dc012cad..d285c8c92819 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -467,6 +467,20 @@ config VIDEO_OV7670
OV7670 VGA camera. It currently only works with the M88ALP01
controller.
+config VIDEO_MT9P031
+ tristate "Aptina MT9P031 support"
+ depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ ---help---
+ This is a Video4Linux2 sensor-level driver for the Aptina
+ (Micron) mt9p031 5 Mpixel camera.
+
+config VIDEO_MT9T001
+ tristate "Aptina MT9T001 support"
+ depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ ---help---
+ This is a Video4Linux2 sensor-level driver for the Aptina
+ (Micron) mt0t001 3 Mpixel camera.
+
config VIDEO_MT9V011
tristate "Micron mt9v011 sensor support"
depends on I2C && VIDEO_V4L2
@@ -489,6 +503,20 @@ config VIDEO_TCM825X
This is a driver for the Toshiba TCM825x VGA camera sensor.
It is used for example in Nokia N800.
+config VIDEO_SR030PC30
+ tristate "Siliconfile SR030PC30 sensor support"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ This driver supports SR030PC30 VGA camera from Siliconfile
+
+config VIDEO_NOON010PC30
+ tristate "Siliconfile NOON010PC30 sensor support"
+ depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API
+ ---help---
+ This driver supports NOON010PC30 CIF camera from Siliconfile
+
+source "drivers/media/video/m5mols/Kconfig"
+
comment "Flash devices"
config VIDEO_ADP1653
@@ -737,12 +765,6 @@ config VIDEO_M32R_AR_M64278
To compile this driver as a module, choose M here: the
module will be called arv.
-config VIDEO_SR030PC30
- tristate "SR030PC30 VGA camera sensor support"
- depends on I2C && VIDEO_V4L2
- ---help---
- This driver supports SR030PC30 VGA camera from Siliconfile
-
config VIDEO_VIA_CAMERA
tristate "VIAFB camera controller support"
depends on FB_VIA
@@ -753,18 +775,9 @@ config VIDEO_VIA_CAMERA
Chrome9 chipsets. Currently only tested on OLPC xo-1.5 systems
with ov7670 sensors.
-config VIDEO_NOON010PC30
- tristate "NOON010PC30 CIF camera sensor support"
- depends on I2C && VIDEO_V4L2
- ---help---
- This driver supports NOON010PC30 CIF camera from Siliconfile
-
-source "drivers/media/video/m5mols/Kconfig"
-
config VIDEO_OMAP3
tristate "OMAP 3 Camera support (EXPERIMENTAL)"
- select OMAP_IOMMU
- depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
+ depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
---help---
Driver for an OMAP 3 camera controller.
@@ -949,8 +962,9 @@ config VIDEO_MX2
Interface
config VIDEO_SAMSUNG_S5P_FIMC
- tristate "Samsung S5P and EXYNOS4 camera host interface driver"
- depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
+ tristate "Samsung S5P and EXYNOS4 camera interface driver (EXPERIMENTAL)"
+ depends on VIDEO_V4L2 && I2C && PLAT_S5P && PM_RUNTIME && \
+ VIDEO_V4L2_SUBDEV_API && EXPERIMENTAL
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
---help---
@@ -1004,6 +1018,8 @@ source "drivers/media/video/tlg2300/Kconfig"
source "drivers/media/video/cx231xx/Kconfig"
+source "drivers/media/video/tm6000/Kconfig"
+
source "drivers/media/video/usbvision/Kconfig"
source "drivers/media/video/et61x251/Kconfig"
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 272390072aef..11fff97e7196 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -65,6 +65,8 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
+obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
+obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o
obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
@@ -105,6 +107,7 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
+obj-$(CONFIG_VIDEO_TM6000) += tm6000/
obj-$(CONFIG_VIDEO_MXB) += mxb.o
obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
@@ -190,6 +193,6 @@ obj-y += davinci/
obj-$(CONFIG_ARCH_OMAP) += omap/
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/video/adp1653.c b/drivers/media/video/adp1653.c
index be7befd60947..5914390211ff 100644
--- a/drivers/media/video/adp1653.c
+++ b/drivers/media/video/adp1653.c
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <media/adp1653.h>
@@ -258,7 +259,7 @@ static int adp1653_init_controls(struct adp1653_flash *flash)
if (flash->ctrls.error)
return flash->ctrls.error;
- fault->is_volatile = 1;
+ fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
flash->subdev.ctrl_handler = &flash->ctrls;
return 0;
@@ -413,6 +414,10 @@ static int adp1653_probe(struct i2c_client *client,
struct adp1653_flash *flash;
int ret;
+ /* we couldn't work without platform data */
+ if (client->dev.platform_data == NULL)
+ return -ENODEV;
+
flash = kzalloc(sizeof(*flash), GFP_KERNEL);
if (flash == NULL)
return -ENOMEM;
@@ -425,12 +430,21 @@ static int adp1653_probe(struct i2c_client *client,
flash->subdev.internal_ops = &adp1653_internal_ops;
flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- adp1653_init_controls(flash);
+ ret = adp1653_init_controls(flash);
+ if (ret)
+ goto free_and_quit;
ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
if (ret < 0)
- kfree(flash);
+ goto free_and_quit;
+
+ flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
+
+ return 0;
+free_and_quit:
+ v4l2_ctrl_handler_free(&flash->ctrls);
+ kfree(flash);
return ret;
}
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index d2327dbb473f..206078eca853 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -61,6 +61,11 @@ static inline struct adv7175 *to_adv7175(struct v4l2_subdev *sd)
static char *inputs[] = { "pass_through", "play_back", "color_bar" };
+static enum v4l2_mbus_pixelcode adv7175_codes[] = {
+ V4L2_MBUS_FMT_UYVY8_2X8,
+ V4L2_MBUS_FMT_UYVY8_1X16,
+};
+
/* ----------------------------------------------------------------------- */
static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value)
@@ -296,6 +301,60 @@ static int adv7175_s_routing(struct v4l2_subdev *sd,
return 0;
}
+static int adv7175_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+ enum v4l2_mbus_pixelcode *code)
+{
+ if (index >= ARRAY_SIZE(adv7175_codes))
+ return -EINVAL;
+
+ *code = adv7175_codes[index];
+ return 0;
+}
+
+static int adv7175_g_fmt(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *mf)
+{
+ u8 val = adv7175_read(sd, 0x7);
+
+ if ((val & 0x40) == (1 << 6))
+ mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
+ else
+ mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+
+ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ mf->width = 0;
+ mf->height = 0;
+ mf->field = V4L2_FIELD_ANY;
+
+ return 0;
+}
+
+static int adv7175_s_fmt(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *mf)
+{
+ u8 val = adv7175_read(sd, 0x7);
+ int ret;
+
+ switch (mf->code) {
+ case V4L2_MBUS_FMT_UYVY8_2X8:
+ val &= ~0x40;
+ break;
+
+ case V4L2_MBUS_FMT_UYVY8_1X16:
+ val |= 0x40;
+ break;
+
+ default:
+ v4l2_dbg(1, debug, sd,
+ "illegal v4l2_mbus_framefmt code: %d\n", mf->code);
+ return -EINVAL;
+ }
+
+ ret = adv7175_write(sd, 0x7, val);
+
+ return ret;
+}
+
static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -324,6 +383,9 @@ static const struct v4l2_subdev_core_ops adv7175_core_ops = {
static const struct v4l2_subdev_video_ops adv7175_video_ops = {
.s_std_output = adv7175_s_std_output,
.s_routing = adv7175_s_routing,
+ .s_mbus_fmt = adv7175_s_fmt,
+ .g_mbus_fmt = adv7175_g_fmt,
+ .enum_mbus_fmt = adv7175_enum_fmt,
};
static const struct v4l2_subdev_ops adv7175_ops = {
diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c
index 7b89f00501b8..774715d2f84f 100644
--- a/drivers/media/video/atmel-isi.c
+++ b/drivers/media/video/atmel-isi.c
@@ -249,7 +249,7 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset)
Videobuf operations
------------------------------------------------------------------*/
static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned long sizes[],
+ unsigned int *nplanes, unsigned int sizes[],
void *alloc_ctxs[])
{
struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
@@ -341,7 +341,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
/* Initialize the dma descriptor */
desc->p_fbd->fb_address =
- vb2_dma_contig_plane_paddr(vb, 0);
+ vb2_dma_contig_plane_dma_addr(vb, 0);
desc->p_fbd->next_fbd_address = 0;
set_dma_ctrl(desc->p_fbd, ISI_DMA_CTRL_WB);
@@ -404,12 +404,13 @@ static void buffer_queue(struct vb2_buffer *vb)
if (isi->active == NULL) {
isi->active = buf;
- start_dma(isi, buf);
+ if (vb2_is_streaming(vb->vb2_queue))
+ start_dma(isi, buf);
}
spin_unlock_irqrestore(&isi->lock, flags);
}
-static int start_streaming(struct vb2_queue *vq)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -431,17 +432,26 @@ static int start_streaming(struct vb2_queue *vq)
ret = wait_event_interruptible(isi->vsync_wq,
isi->state != ISI_STATE_IDLE);
if (ret)
- return ret;
+ goto err;
- if (isi->state != ISI_STATE_READY)
- return -EIO;
+ if (isi->state != ISI_STATE_READY) {
+ ret = -EIO;
+ goto err;
+ }
spin_lock_irq(&isi->lock);
isi->state = ISI_STATE_WAIT_SOF;
isi_writel(isi, ISI_INTDIS, ISI_SR_VSYNC);
+ if (count)
+ start_dma(isi, isi->active);
spin_unlock_irq(&isi->lock);
return 0;
+err:
+ isi->active = NULL;
+ isi->sequence = 0;
+ INIT_LIST_HEAD(&isi->video_buffer_list);
+ return ret;
}
/* abort streaming and wait for last buffer */
diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile
index 5c7f2f7d9805..bd22223f8d9f 100644
--- a/drivers/media/video/au0828/Makefile
+++ b/drivers/media/video/au0828/Makefile
@@ -2,8 +2,8 @@ au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-vid
obj-$(CONFIG_VIDEO_AU0828) += au0828.o
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index f87204461cb4..859eabf57978 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -229,7 +229,7 @@ static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
if (pstd)
*pstd = std;
if (pstatus)
- *pstatus = status;
+ *pstatus = res;
v4l2_dbg(1, debug, sd, "get status %x\n", status);
return 0;
diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile
index e415f6fc447c..3f9a2b22d3d4 100644
--- a/drivers/media/video/bt8xx/Makefile
+++ b/drivers/media/video/bt8xx/Makefile
@@ -8,6 +8,6 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
obj-$(CONFIG_VIDEO_BT848) += bttv.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index 5b15f63bf065..5939021d8eba 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -25,6 +25,8 @@
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/kmod.h>
@@ -2905,19 +2907,17 @@ void __devinit bttv_idcard(struct bttv *btv)
if (type != -1) {
/* found it */
- printk(KERN_INFO "bttv%d: detected: %s [card=%d], "
- "PCI subsystem ID is %04x:%04x\n",
- btv->c.nr,cards[type].name,cards[type].cardnr,
- btv->cardid & 0xffff,
- (btv->cardid >> 16) & 0xffff);
+ pr_info("%d: detected: %s [card=%d], PCI subsystem ID is %04x:%04x\n",
+ btv->c.nr, cards[type].name, cards[type].cardnr,
+ btv->cardid & 0xffff,
+ (btv->cardid >> 16) & 0xffff);
btv->c.type = cards[type].cardnr;
} else {
/* 404 */
- printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n",
- btv->c.nr, btv->cardid & 0xffff,
- (btv->cardid >> 16) & 0xffff);
- printk(KERN_DEBUG "please mail id, board name and "
- "the correct card= insmod option to linux-media@vger.kernel.org\n");
+ pr_info("%d: subsystem: %04x:%04x (UNKNOWN)\n",
+ btv->c.nr, btv->cardid & 0xffff,
+ (btv->cardid >> 16) & 0xffff);
+ pr_debug("please mail id, board name and the correct card= insmod option to linux-media@vger.kernel.org\n");
}
}
@@ -2926,10 +2926,10 @@ void __devinit bttv_idcard(struct bttv *btv)
btv->c.type=card[btv->c.nr];
/* print which card config we are using */
- printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->c.nr,
- bttv_tvcards[btv->c.type].name, btv->c.type,
- card[btv->c.nr] < bttv_num_tvcards
- ? "insmod option" : "autodetected");
+ pr_info("%d: using: %s [card=%d,%s]\n",
+ btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type,
+ card[btv->c.nr] < bttv_num_tvcards
+ ? "insmod option" : "autodetected");
/* overwrite gpio stuff ?? */
if (UNSET == audioall && UNSET == audiomux[0])
@@ -2948,12 +2948,13 @@ void __devinit bttv_idcard(struct bttv *btv)
}
}
bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
- printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=",
- btv->c.nr,bttv_tvcards[btv->c.type].gpiomask);
+ pr_info("%d: gpio config override: mask=0x%x, mux=",
+ btv->c.nr, bttv_tvcards[btv->c.type].gpiomask);
for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
- printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
+ pr_cont("%s0x%x",
+ i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
}
- printk("\n");
+ pr_cont("\n");
}
/*
@@ -2974,8 +2975,8 @@ static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
if (-1 != type) {
btv->c.type = type;
- printk("bttv%d: detected by eeprom: %s [card=%d]\n",
- btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
+ pr_info("%d: detected by eeprom: %s [card=%d]\n",
+ btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
}
}
@@ -3019,7 +3020,7 @@ static void flyvideo_gpio(struct bttv *btv)
tuner_type = 3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
break;
default:
- printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr);
+ pr_info("%d: FlyVideo_gpio: unknown tuner type\n", btv->c.nr);
break;
}
@@ -3036,13 +3037,13 @@ static void flyvideo_gpio(struct bttv *btv)
if (is_capture_only)
tuner_type = TUNER_ABSENT; /* No tuner present */
- printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
- btv->c.nr, has_radio ? "yes" : "no ",
- has_remote ? "yes" : "no ", tuner_type, gpio);
- printk(KERN_INFO "bttv%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n",
- btv->c.nr, is_lr90 ? "yes" : "no ",
- has_tda9820_tda9821 ? "yes" : "no ",
- is_capture_only ? "yes" : "no ");
+ pr_info("%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
+ btv->c.nr, has_radio ? "yes" : "no",
+ has_remote ? "yes" : "no", tuner_type, gpio);
+ pr_info("%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n",
+ btv->c.nr, is_lr90 ? "yes" : "no",
+ has_tda9820_tda9821 ? "yes" : "no",
+ is_capture_only ? "yes" : "no");
if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */
btv->tuner_type = tuner_type;
@@ -3091,12 +3092,11 @@ static void miro_pinnacle_gpio(struct bttv *btv)
if (btv->c.type == BTTV_BOARD_PINNACLE)
btv->c.type = BTTV_BOARD_PINNACLEPRO;
}
- printk(KERN_INFO
- "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
- btv->c.nr, id+1, btv->tuner_type,
- !btv->has_radio ? "no" :
- (btv->has_matchbox ? "matchbox" : "fmtuner"),
- (-1 == msp) ? "no" : "yes");
+ pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+ btv->c.nr, id+1, btv->tuner_type,
+ !btv->has_radio ? "no" :
+ (btv->has_matchbox ? "matchbox" : "fmtuner"),
+ (-1 == msp) ? "no" : "yes");
} else {
/* new cards with microtune tuner */
id = 63 - id;
@@ -3138,9 +3138,8 @@ static void miro_pinnacle_gpio(struct bttv *btv)
}
if (-1 != msp)
btv->c.type = BTTV_BOARD_PINNACLEPRO;
- printk(KERN_INFO
- "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
- btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
+ pr_info("%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
+ btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
btv->tuner_type = TUNER_MT2032;
}
}
@@ -3202,7 +3201,7 @@ static void gvc1100_muxsel(struct bttv *btv, unsigned int input)
static void init_lmlbt4x(struct bttv *btv)
{
- printk(KERN_DEBUG "LMLBT4x init\n");
+ pr_debug("LMLBT4x init\n");
btwrite(0x000000, BT848_GPIO_REG_INP);
gpio_inout(0xffffff, 0x0006C0);
gpio_write(0x000000);
@@ -3246,7 +3245,7 @@ static void bttv_reset_audio(struct bttv *btv)
return;
if (bttv_debug)
- printk("bttv%d: BT878A ARESET\n",btv->c.nr);
+ pr_debug("%d: BT878A ARESET\n", btv->c.nr);
btwrite((1<<7), 0x058);
udelay(10);
btwrite( 0, 0x058);
@@ -3349,7 +3348,8 @@ void __devinit bttv_init_card2(struct bttv *btv)
case BTTV_BOARD_MAGICTVIEW061:
if (btv->cardid == 0x3002144f) {
btv->has_radio=1;
- printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr);
+ pr_info("%d: radio detected by subsystem id (CPH05x)\n",
+ btv->c.nr);
}
break;
case BTTV_BOARD_STB2:
@@ -3438,17 +3438,16 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->tuner_type = tuner[btv->c.nr];
if (btv->tuner_type == TUNER_ABSENT)
- printk(KERN_INFO "bttv%d: tuner absent\n", btv->c.nr);
- else if(btv->tuner_type == UNSET)
- printk(KERN_WARNING "bttv%d: tuner type unset\n", btv->c.nr);
+ pr_info("%d: tuner absent\n", btv->c.nr);
+ else if (btv->tuner_type == UNSET)
+ pr_warn("%d: tuner type unset\n", btv->c.nr);
else
- printk(KERN_INFO "bttv%d: tuner type=%d\n", btv->c.nr,
- btv->tuner_type);
+ pr_info("%d: tuner type=%d\n", btv->c.nr, btv->tuner_type);
if (autoload != UNSET) {
- printk(KERN_WARNING "bttv%d: the autoload option is obsolete.\n", btv->c.nr);
- printk(KERN_WARNING "bttv%d: use option msp3400, tda7432 or tvaudio to\n", btv->c.nr);
- printk(KERN_WARNING "bttv%d: override which audio module should be used.\n", btv->c.nr);
+ pr_warn("%d: the autoload option is obsolete\n", btv->c.nr);
+ pr_warn("%d: use option msp3400, tda7432 or tvaudio to override which audio module should be used\n",
+ btv->c.nr);
}
if (UNSET == btv->tuner_type)
@@ -3541,8 +3540,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
}
default:
- printk(KERN_WARNING "bttv%d: unknown audiodev value!\n",
- btv->c.nr);
+ pr_warn("%d: unknown audiodev value!\n", btv->c.nr);
return;
}
@@ -3585,8 +3583,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
return;
no_audio:
- printk(KERN_WARNING "bttv%d: audio absent, no audio device found!\n",
- btv->c.nr);
+ pr_warn("%d: audio absent, no audio device found!\n", btv->c.nr);
}
@@ -3639,19 +3636,19 @@ static void modtec_eeprom(struct bttv *btv)
{
if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) {
btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I;
- printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
- btv->c.nr,&eeprom_data[0x1e]);
+ pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+ btv->c.nr, &eeprom_data[0x1e]);
} else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) {
btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I;
- printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
- btv->c.nr,&eeprom_data[0x1e]);
+ pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+ btv->c.nr, &eeprom_data[0x1e]);
} else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) {
btv->tuner_type=TUNER_PHILIPS_NTSC;
- printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
- btv->c.nr,&eeprom_data[0x1e]);
+ pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+ btv->c.nr, &eeprom_data[0x1e]);
} else {
- printk("bttv%d: Modtec: Unknown TunerString: %s\n",
- btv->c.nr,&eeprom_data[0x1e]);
+ pr_info("%d: Modtec: Unknown TunerString: %s\n",
+ btv->c.nr, &eeprom_data[0x1e]);
}
}
@@ -3663,7 +3660,7 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
btv->tuner_type = tv.tuner_type;
btv->has_radio = tv.has_radio;
- printk("bttv%d: Hauppauge eeprom indicates model#%d\n",
+ pr_info("%d: Hauppauge eeprom indicates model#%d\n",
btv->c.nr, tv.model);
/*
@@ -3671,7 +3668,7 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
* type based on model #.
*/
if(tv.model == 64900) {
- printk("bttv%d: Switching board type from %s to %s\n",
+ pr_info("%d: Switching board type from %s to %s\n",
btv->c.nr,
bttv_tvcards[btv->c.type].name,
bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name);
@@ -3698,8 +3695,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv)
freq=88000/62.5;
tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
if (0x1ed8 == tea5757_read(btv)) {
- printk("bttv%d: Terratec Active Radio Upgrade found.\n",
- btv->c.nr);
+ pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
btv->has_radio = 1;
btv->has_saa6588 = 1;
btv->has_matchbox = 1;
@@ -3771,13 +3767,12 @@ static int __devinit pvr_boot(struct bttv *btv)
rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev);
if (rc != 0) {
- printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n",
- btv->c.nr);
+ pr_warn("%d: no altera firmware [via hotplug]\n", btv->c.nr);
return rc;
}
rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size);
- printk(KERN_INFO "bttv%d: altera firmware upload %s\n",
- btv->c.nr, (rc < 0) ? "failed" : "ok");
+ pr_info("%d: altera firmware upload %s\n",
+ btv->c.nr, (rc < 0) ? "failed" : "ok");
release_firmware(fw_entry);
return rc;
}
@@ -3873,29 +3868,27 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
break;
default:
/* unknown...leave generic, but get serial # */
- printk(KERN_INFO "bttv%d: "
- "osprey eeprom: unknown card type 0x%04x\n",
- btv->c.nr, type);
+ pr_info("%d: osprey eeprom: unknown card type 0x%04x\n",
+ btv->c.nr, type);
break;
}
serial = get_unaligned_be32((__be32 *)(ee+6));
}
- printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n",
- btv->c.nr, cardid,
- cardid>0 ? bttv_tvcards[cardid].name : "Unknown", serial);
+ pr_info("%d: osprey eeprom: card=%d '%s' serial=%u\n",
+ btv->c.nr, cardid,
+ cardid > 0 ? bttv_tvcards[cardid].name : "Unknown", serial);
if (cardid<0 || btv->c.type == cardid)
return;
/* card type isn't set correctly */
if (card[btv->c.nr] < bttv_num_tvcards) {
- printk(KERN_WARNING "bttv%d: osprey eeprom: "
- "Not overriding user specified card type\n", btv->c.nr);
+ pr_warn("%d: osprey eeprom: Not overriding user specified card type\n",
+ btv->c.nr);
} else {
- printk(KERN_INFO "bttv%d: osprey eeprom: "
- "Changing card type from %d to %d\n", btv->c.nr,
- btv->c.type, cardid);
+ pr_info("%d: osprey eeprom: Changing card type from %d to %d\n",
+ btv->c.nr, btv->c.type, cardid);
btv->c.type = cardid;
}
}
@@ -3938,14 +3931,14 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
if (tuner_format == 0x09)
tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
- printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
+ pr_info("%d: Avermedia eeprom[0x%02x%02x]: tuner=",
btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]);
if (tuner_type) {
btv->tuner_type = tuner_type;
- printk(KERN_CONT "%d", tuner_type);
+ pr_cont("%d", tuner_type);
} else
- printk(KERN_CONT "Unknown type");
- printk(KERN_CONT " radio:%s remote control:%s\n",
+ pr_cont("Unknown type");
+ pr_cont(" radio:%s remote control:%s\n",
tuner_tv_fm ? "yes" : "no",
btv->has_remote ? "yes" : "no");
}
@@ -3993,8 +3986,8 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin)
if (bttv_gpio)
bttv_gpio_tracking(btv,"msp34xx");
if (bttv_verbose)
- printk(KERN_INFO "bttv%d: Hauppauge/Voodoo msp34xx: reset line "
- "init [%d]\n", btv->c.nr, pin);
+ pr_info("%d: Hauppauge/Voodoo msp34xx: reset line init [%d]\n",
+ btv->c.nr, pin);
}
/* ----------------------------------------------------------------------- */
@@ -4034,7 +4027,7 @@ static void __devinit init_PXC200(struct bttv *btv)
btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
/* Initialise MAX517 DAC */
- printk(KERN_INFO "Setting DAC reference voltage level ...\n");
+ pr_info("Setting DAC reference voltage level ...\n");
bttv_I2CWrite(btv,0x5E,0,0x80,1);
/* Initialise 12C508 PIC */
@@ -4043,7 +4036,7 @@ static void __devinit init_PXC200(struct bttv *btv)
* argument so the numbers are different */
- printk(KERN_INFO "Initialising 12C508 PIC chip ...\n");
+ pr_info("Initialising 12C508 PIC chip ...\n");
/* First of all, enable the clock line. This is used in the PXC200-F */
val = btread(BT848_GPIO_DMA_CTL);
@@ -4062,13 +4055,12 @@ static void __devinit init_PXC200(struct bttv *btv)
for (i = 0; i < ARRAY_SIZE(vals); i++) {
tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1);
if (tmp != -1) {
- printk(KERN_INFO
- "I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
+ pr_info("I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL));
}
}
- printk(KERN_INFO "PXC200 Initialised.\n");
+ pr_info("PXC200 Initialised\n");
}
@@ -4107,8 +4099,7 @@ init_RTV24 (struct bttv *btv)
uint32_t dataRead = 0;
long watchdog_value = 0x0E;
- printk (KERN_INFO
- "bttv%d: Adlink RTV-24 initialisation in progress ...\n",
+ pr_info("%d: Adlink RTV-24 initialisation in progress ...\n",
btv->c.nr);
btwrite (0x00c3feff, BT848_GPIO_OUT_EN);
@@ -4122,8 +4113,7 @@ init_RTV24 (struct bttv *btv)
dataRead = btread (BT848_GPIO_DATA);
if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) {
- printk (KERN_INFO
- "bttv%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
+ pr_info("%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
btv->c.nr, dataRead);
}
@@ -4136,15 +4126,13 @@ init_RTV24 (struct bttv *btv)
dataRead = btread (BT848_GPIO_DATA);
if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) {
- printk (KERN_INFO
- "bttv%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
+ pr_info("%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
btv->c.nr, dataRead);
return;
}
- printk (KERN_INFO
- "bttv%d: Adlink RTV-24 initialisation complete.\n", btv->c.nr);
+ pr_info("%d: Adlink RTV-24 initialisation complete\n", btv->c.nr);
}
@@ -4261,22 +4249,25 @@ static int tea5757_read(struct bttv *btv)
while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
schedule();
if (bus_in(btv,btv->mbox_data)) {
- printk(KERN_WARNING "bttv%d: tea5757: read timeout\n",btv->c.nr);
+ pr_warn("%d: tea5757: read timeout\n", btv->c.nr);
return -1;
}
- dprintk("bttv%d: tea5757:",btv->c.nr);
+ dprintk("%d: tea5757:", btv->c.nr);
for (i = 0; i < 24; i++) {
udelay(5);
bus_high(btv,btv->mbox_clk);
udelay(5);
- dprintk("%c",(bus_in(btv,btv->mbox_most) == 0)?'T':'-');
+ dprintk_cont("%c",
+ bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-');
bus_low(btv,btv->mbox_clk);
value <<= 1;
value |= (bus_in(btv,btv->mbox_data) == 0)?0:1; /* MSB first */
- dprintk("%c", (bus_in(btv,btv->mbox_most) == 0)?'S':'M');
+ dprintk_cont("%c",
+ bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M');
}
- dprintk("\nbttv%d: tea5757: read 0x%X\n", btv->c.nr, value);
+ dprintk_cont("\n");
+ dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value);
return value;
}
@@ -4295,7 +4286,7 @@ static int tea5757_write(struct bttv *btv, int value)
if (bttv_gpio)
bttv_gpio_tracking(btv,"tea5757 write");
- dprintk("bttv%d: tea5757: write 0x%X\n", btv->c.nr, value);
+ dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value);
bus_low(btv,btv->mbox_clk);
bus_high(btv,btv->mbox_we);
for (i = 0; i < 25; i++) {
@@ -4547,7 +4538,7 @@ static void picolo_tetra_init(struct bttv *btv)
static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
{
- dprintk (KERN_DEBUG "bttv%d : picolo_tetra_muxsel => input = %d\n",btv->c.nr,input);
+ dprintk("%d : picolo_tetra_muxsel => input = %d\n", btv->c.nr, input);
/*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/
/*GPIO[20]&GPIO[21] used to choose the right input*/
btwrite (input<<20,BT848_GPIO_DATA);
@@ -4592,7 +4583,7 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input)
int key = input % 4;
int matrix = input / 4;
- dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
+ dprintk("%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
btv->c.nr, input, matrix, key);
/* Handles the input selection on the TDA8540's */
@@ -4649,15 +4640,17 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input)
buf[1]=0;
rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1);
if (rc) {
- printk(KERN_DEBUG "bttv%d: PXC200_muxsel: pic cfg write failed:%d\n", btv->c.nr,rc);
+ pr_debug("%d: PXC200_muxsel: pic cfg write failed:%d\n",
+ btv->c.nr, rc);
/* not PXC ? do nothing */
- return;
+ return;
}
rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL);
if (!(rc & PX_CFG_PXC200F)) {
- printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc);
- return;
+ pr_debug("%d: PXC200_muxsel: not PXC200F rc:%d\n",
+ btv->c.nr, rc);
+ return;
}
@@ -4696,7 +4689,7 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input)
else /* older device */
btand(~BT848_IFORM_MUXSEL,BT848_IFORM);
- printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux);
+ pr_debug("%d: setting input channel to:%d\n", btv->c.nr, (int)mux);
}
static void phytec_muxsel(struct bttv *btv, unsigned int input)
@@ -4847,29 +4840,27 @@ void __init bttv_check_chipset(void)
/* print warnings about any quirks found */
if (triton1)
- printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n");
+ pr_info("Host bridge needs ETBF enabled\n");
if (vsfx)
- printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n");
+ pr_info("Host bridge needs VSFX enabled\n");
if (pcipci_fail) {
- printk(KERN_INFO "bttv: bttv and your chipset may not work "
- "together.\n");
+ pr_info("bttv and your chipset may not work together\n");
if (!no_overlay) {
- printk(KERN_INFO "bttv: overlay will be disabled.\n");
+ pr_info("overlay will be disabled\n");
no_overlay = 1;
} else {
- printk(KERN_INFO "bttv: overlay forced. Use this "
- "option at your own risk.\n");
+ pr_info("overlay forced. Use this option at your own risk.\n");
}
}
if (UNSET != latency)
- printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency);
+ pr_info("pci latency fixup [%d]\n", latency);
while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82441, dev))) {
unsigned char b;
pci_read_config_byte(dev, 0x53, &b);
if (bttv_debug)
- printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "
- "bufcon=0x%02x\n",b);
+ pr_info("Host bridge: 82441FX Natoma, bufcon=0x%02x\n",
+ b);
}
}
@@ -4882,12 +4873,13 @@ int __devinit bttv_handle_chipset(struct bttv *btv)
if (bttv_verbose) {
if (triton1)
- printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->c.nr);
+ pr_info("%d: enabling ETBF (430FX/VP3 compatibility)\n",
+ btv->c.nr);
if (vsfx && btv->id >= 878)
- printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->c.nr);
+ pr_info("%d: enabling VSFX\n", btv->c.nr);
if (UNSET != latency)
- printk(KERN_INFO "bttv%d: setting pci timer to %d\n",
- btv->c.nr,latency);
+ pr_info("%d: setting pci timer to %d\n",
+ btv->c.nr, latency);
}
if (btv->id < 878) {
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 14444de67d5e..3dd06607aec2 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -34,6 +34,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -942,8 +944,8 @@ static
void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
{
if ((fh->resources & bits) != bits) {
- /* trying to free ressources not allocated by us ... */
- printk("bttv: BUG! (btres)\n");
+ /* trying to free resources not allocated by us ... */
+ pr_err("BUG! (btres)\n");
}
fh->resources &= ~bits;
btv->resources &= ~bits;
@@ -1000,7 +1002,7 @@ static void set_pll(struct bttv *btv)
return;
if (btv->pll.pll_ofreq == btv->pll.pll_current) {
- dprintk("bttv%d: PLL: no change required\n",btv->c.nr);
+ dprintk("%d: PLL: no change required\n", btv->c.nr);
return;
}
@@ -1008,21 +1010,23 @@ static void set_pll(struct bttv *btv)
/* no PLL needed */
if (btv->pll.pll_current == 0)
return;
- bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
- btv->c.nr,btv->pll.pll_ifreq);
+ if (bttv_verbose)
+ pr_info("%d: PLL can sleep, using XTAL (%d)\n",
+ btv->c.nr, btv->pll.pll_ifreq);
btwrite(0x00,BT848_TGCTRL);
btwrite(0x00,BT848_PLL_XCI);
btv->pll.pll_current = 0;
return;
}
- bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
- btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+ if (bttv_verbose)
+ pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
+ btv->c.nr,
+ btv->pll.pll_ifreq, btv->pll.pll_ofreq);
set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
for (i=0; i<10; i++) {
/* Let other people run while the PLL stabilizes */
- bttv_printk(".");
msleep(10);
if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
@@ -1030,12 +1034,14 @@ static void set_pll(struct bttv *btv)
} else {
btwrite(0x08,BT848_TGCTRL);
btv->pll.pll_current = btv->pll.pll_ofreq;
- bttv_printk(" ok\n");
+ if (bttv_verbose)
+ pr_info("PLL set ok\n");
return;
}
}
btv->pll.pll_current = -1;
- bttv_printk("failed\n");
+ if (bttv_verbose)
+ pr_info("Setting PLL failed\n");
return;
}
@@ -1047,7 +1053,7 @@ static void bt848A_set_timing(struct bttv *btv)
int fsc = bttv_tvnorms[btv->tvnorm].Fsc;
if (btv->input == btv->dig) {
- dprintk("bttv%d: load digital timing table (table_idx=%d)\n",
+ dprintk("%d: load digital timing table (table_idx=%d)\n",
btv->c.nr,table_idx);
/* timing change...reset timing generator address */
@@ -1076,7 +1082,7 @@ static void bt848_bright(struct bttv *btv, int bright)
{
int value;
- // printk("bttv: set bright: %d\n",bright); // DEBUG
+ // printk("set bright: %d\n", bright); // DEBUG
btv->bright = bright;
/* We want -128 to 127 we get 0-65535 */
@@ -1150,8 +1156,7 @@ video_mux(struct bttv *btv, unsigned int input)
}
mux = bttv_muxsel(btv, input);
btaor(mux<<5, ~(3<<5), BT848_IFORM);
- dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n",
- btv->c.nr,input,mux);
+ dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
/* card specific hook */
if(bttv_tvcards[btv->c.type].muxsel_hook)
@@ -1440,7 +1445,7 @@ static void bttv_reinit_bt848(struct bttv *btv)
unsigned long flags;
if (bttv_verbose)
- printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr);
+ pr_info("%d: reset, reinitialize\n", btv->c.nr);
spin_lock_irqsave(&btv->s_lock,flags);
btv->errors=0;
bttv_set_dma(btv,0);
@@ -1622,8 +1627,8 @@ void bttv_gpio_tracking(struct bttv *btv, char *comment)
unsigned int outbits, data;
outbits = btread(BT848_GPIO_OUT_EN);
data = btread(BT848_GPIO_DATA);
- printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
- btv->c.nr,outbits,data & outbits, data & ~outbits, comment);
+ pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
+ btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
}
static void bttv_field_count(struct bttv *btv)
@@ -1668,7 +1673,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
unsigned long flags;
int retval = 0;
- dprintk("switch_overlay: enter [new=%p]\n",new);
+ dprintk("switch_overlay: enter [new=%p]\n", new);
if (new)
new->vb.state = VIDEOBUF_DONE;
spin_lock_irqsave(&btv->s_lock,flags);
@@ -1678,7 +1683,8 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
bttv_set_dma(btv, 0x03);
spin_unlock_irqrestore(&btv->s_lock,flags);
if (NULL != old) {
- dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
+ dprintk("switch_overlay: old=%p state is %d\n",
+ old, old->vb.state);
bttv_dma_free(&fh->cap,btv, old);
kfree(old);
}
@@ -2029,11 +2035,11 @@ static int bttv_log_status(struct file *file, void *f)
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
- printk(KERN_INFO "bttv%d: ======== START STATUS CARD #%d ========\n",
- btv->c.nr, btv->c.nr);
+ pr_info("%d: ======== START STATUS CARD #%d ========\n",
+ btv->c.nr, btv->c.nr);
bttv_call_all(btv, core, log_status);
- printk(KERN_INFO "bttv%d: ======== END STATUS CARD #%d ========\n",
- btv->c.nr, btv->c.nr);
+ pr_info("%d: ======== END STATUS CARD #%d ========\n",
+ btv->c.nr, btv->c.nr);
return 0;
}
@@ -2598,7 +2604,7 @@ static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
struct bttv *btv = fh->btv;
if (no_overlay > 0) {
- printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
return -EINVAL;
}
@@ -2673,7 +2679,7 @@ static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
int rc;
if (no_overlay > 0) {
- printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
return -EINVAL;
}
@@ -2714,7 +2720,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
return -EINVAL;
}
if (unlikely(!fh->ov.setup_ok)) {
- dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr);
+ dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
retval = -EINVAL;
}
if (retval)
@@ -3091,8 +3097,8 @@ static ssize_t bttv_read(struct file *file, char __user *data,
if (fh->btv->errors)
bttv_reinit_bt848(fh->btv);
- dprintk("bttv%d: read count=%d type=%s\n",
- fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]);
+ dprintk("%d: read count=%d type=%s\n",
+ fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -3174,7 +3180,7 @@ static int bttv_open(struct file *file)
struct bttv_fh *fh;
enum v4l2_buf_type type = 0;
- dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev));
+ dprintk("open dev=%s\n", video_device_node_name(vdev));
if (vdev->vfl_type == VFL_TYPE_GRABBER) {
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -3185,8 +3191,8 @@ static int bttv_open(struct file *file)
return -ENODEV;
}
- dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
- btv->c.nr,v4l2_type_names[type]);
+ dprintk("%d: open called (type=%s)\n",
+ btv->c.nr, v4l2_type_names[type]);
/* allocate per filehandle data */
fh = kmalloc(sizeof(*fh), GFP_KERNEL);
@@ -3288,7 +3294,7 @@ bttv_mmap(struct file *file, struct vm_area_struct *vma)
{
struct bttv_fh *fh = file->private_data;
- dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n",
+ dprintk("%d: mmap type=%s 0x%lx+%ld\n",
fh->btv->c.nr, v4l2_type_names[fh->type],
vma->vm_start, vma->vm_end - vma->vm_start);
return videobuf_mmap_mapper(bttv_queue(fh),vma);
@@ -3370,9 +3376,9 @@ static int radio_open(struct file *file)
struct bttv *btv = video_drvdata(file);
struct bttv_fh *fh;
- dprintk("bttv: open dev=%s\n", video_device_node_name(vdev));
+ dprintk("open dev=%s\n", video_device_node_name(vdev));
- dprintk("bttv%d: open called (radio)\n",btv->c.nr);
+ dprintk("%d: open called (radio)\n", btv->c.nr);
/* allocate per filehandle data */
fh = kmalloc(sizeof(*fh), GFP_KERNEL);
@@ -3616,12 +3622,12 @@ static int bttv_risc_decode(u32 risc)
};
int i;
- printk("0x%08x [ %s", risc,
+ pr_cont("0x%08x [ %s", risc,
instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
if (risc & (1 << (i + 12)))
- printk(" %s",bits[i]);
- printk(" count=%d ]\n", risc & 0xfff);
+ pr_cont(" %s", bits[i]);
+ pr_cont(" count=%d ]\n", risc & 0xfff);
return incr[risc >> 28] ? incr[risc >> 28] : 1;
}
@@ -3630,16 +3636,18 @@ static void bttv_risc_disasm(struct bttv *btv,
{
unsigned int i,j,n;
- printk("%s: risc disasm: %p [dma=0x%08lx]\n",
- btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
+ pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
+ btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
for (i = 0; i < (risc->size >> 2); i += n) {
- printk("%s: 0x%lx: ", btv->c.v4l2_dev.name,
- (unsigned long)(risc->dma + (i<<2)));
+ pr_info("%s: 0x%lx: ",
+ btv->c.v4l2_dev.name,
+ (unsigned long)(risc->dma + (i<<2)));
n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
for (j = 1; j < n; j++)
- printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
- btv->c.v4l2_dev.name, (unsigned long)(risc->dma + ((i+j)<<2)),
- risc->cpu[i+j], j);
+ pr_info("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
+ btv->c.v4l2_dev.name,
+ (unsigned long)(risc->dma + ((i+j)<<2)),
+ risc->cpu[i+j], j);
if (0 == risc->cpu[i])
break;
}
@@ -3647,17 +3655,18 @@ static void bttv_risc_disasm(struct bttv *btv,
static void bttv_print_riscaddr(struct bttv *btv)
{
- printk(" main: %08Lx\n",
- (unsigned long long)btv->main.dma);
- printk(" vbi : o=%08Lx e=%08Lx\n",
- btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
- btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
- printk(" cap : o=%08Lx e=%08Lx\n",
- btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
- btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
- printk(" scr : o=%08Lx e=%08Lx\n",
- btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
- btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
+ pr_info(" main: %08llx\n", (unsigned long long)btv->main.dma);
+ pr_info(" vbi : o=%08llx e=%08llx\n",
+ btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
+ btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
+ pr_info(" cap : o=%08llx e=%08llx\n",
+ btv->curr.top
+ ? (unsigned long long)btv->curr.top->top.dma : 0,
+ btv->curr.bottom
+ ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
+ pr_info(" scr : o=%08llx e=%08llx\n",
+ btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
+ btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
bttv_risc_disasm(btv, &btv->main);
}
@@ -3690,34 +3699,34 @@ static void bttv_print_irqbits(u32 print, u32 mark)
{
unsigned int i;
- printk("bits:");
+ pr_cont("bits:");
for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
if (print & (1 << i))
- printk(" %s",irq_name[i]);
+ pr_cont(" %s", irq_name[i]);
if (mark & (1 << i))
- printk("*");
+ pr_cont("*");
}
}
static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
{
- printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
- btv->c.nr,
- (unsigned long)btv->main.dma,
- (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
- (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
- (unsigned long)rc);
+ pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
+ btv->c.nr,
+ (unsigned long)btv->main.dma,
+ (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
+ (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
+ (unsigned long)rc);
if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
- printk("bttv%d: Oh, there (temporarely?) is no input signal. "
- "Ok, then this is harmless, don't worry ;)\n",
- btv->c.nr);
+ pr_notice("%d: Oh, there (temporarily?) is no input signal. "
+ "Ok, then this is harmless, don't worry ;)\n",
+ btv->c.nr);
return;
}
- printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n",
- btv->c.nr);
- printk("bttv%d: Lets try to catch the culpit red-handed ...\n",
- btv->c.nr);
+ pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
+ btv->c.nr);
+ pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
+ btv->c.nr);
dump_stack();
}
@@ -3798,9 +3807,9 @@ bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
}
}
- dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
- btv->c.nr,set->top, set->bottom,
- btv->screen,set->frame_irq,set->top_irq);
+ dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
+ btv->c.nr, set->top, set->bottom,
+ btv->screen, set->frame_irq, set->top_irq);
return 0;
}
@@ -3815,7 +3824,8 @@ bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
if (wakeup->top == wakeup->bottom) {
if (NULL != wakeup->top && curr->top != wakeup->top) {
if (irq_debug > 1)
- printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top);
+ pr_debug("%d: wakeup: both=%p\n",
+ btv->c.nr, wakeup->top);
wakeup->top->vb.ts = ts;
wakeup->top->vb.field_count = btv->field_count;
wakeup->top->vb.state = state;
@@ -3824,7 +3834,8 @@ bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
} else {
if (NULL != wakeup->top && curr->top != wakeup->top) {
if (irq_debug > 1)
- printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top);
+ pr_debug("%d: wakeup: top=%p\n",
+ btv->c.nr, wakeup->top);
wakeup->top->vb.ts = ts;
wakeup->top->vb.field_count = btv->field_count;
wakeup->top->vb.state = state;
@@ -3832,7 +3843,8 @@ bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
}
if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
if (irq_debug > 1)
- printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom);
+ pr_debug("%d: wakeup: bottom=%p\n",
+ btv->c.nr, wakeup->bottom);
wakeup->bottom->vb.ts = ts;
wakeup->bottom->vb.field_count = btv->field_count;
wakeup->bottom->vb.state = state;
@@ -3866,11 +3878,11 @@ static void bttv_irq_timeout(unsigned long data)
unsigned long flags;
if (bttv_verbose) {
- printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
- btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
- btread(BT848_RISC_COUNT));
+ pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
+ btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
+ btread(BT848_RISC_COUNT));
bttv_print_irqbits(btread(BT848_INT_STAT),0);
- printk("\n");
+ pr_cont("\n");
}
spin_lock_irqsave(&btv->s_lock,flags);
@@ -4033,21 +4045,23 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
dstat=btread(BT848_DSTATUS);
if (irq_debug) {
- printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
- "riscs=%x, riscc=%08x, ",
- btv->c.nr, count, btv->field_count,
- stat>>28, btread(BT848_RISC_COUNT));
+ pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
+ btv->c.nr, count, btv->field_count,
+ stat>>28, btread(BT848_RISC_COUNT));
bttv_print_irqbits(stat,astat);
if (stat & BT848_INT_HLOCK)
- printk(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC)
- ? "yes" : "no");
+ pr_cont(" HLOC => %s",
+ dstat & BT848_DSTATUS_HLOC
+ ? "yes" : "no");
if (stat & BT848_INT_VPRES)
- printk(" PRES => %s", (dstat & BT848_DSTATUS_PRES)
- ? "yes" : "no");
+ pr_cont(" PRES => %s",
+ dstat & BT848_DSTATUS_PRES
+ ? "yes" : "no");
if (stat & BT848_INT_FMTCHG)
- printk(" NUML => %s", (dstat & BT848_DSTATUS_NUML)
- ? "625" : "525");
- printk("\n");
+ pr_cont(" NUML => %s",
+ dstat & BT848_DSTATUS_NUML
+ ? "625" : "525");
+ pr_cont("\n");
}
if (astat&BT848_INT_VSYNC)
@@ -4075,18 +4089,19 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
audio_mute(btv, btv->mute); /* trigger automute */
if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
- printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
- (astat & BT848_INT_SCERR) ? "SCERR" : "",
- (astat & BT848_INT_OCERR) ? "OCERR" : "",
- btread(BT848_RISC_COUNT));
+ pr_info("%d: %s%s @ %08x,",
+ btv->c.nr,
+ (astat & BT848_INT_SCERR) ? "SCERR" : "",
+ (astat & BT848_INT_OCERR) ? "OCERR" : "",
+ btread(BT848_RISC_COUNT));
bttv_print_irqbits(stat,astat);
- printk("\n");
+ pr_cont("\n");
if (bttv_debug)
bttv_print_riscaddr(btv);
}
if (fdsr && astat & BT848_INT_FDSR) {
- printk(KERN_INFO "bttv%d: FDSR @ %08x\n",
- btv->c.nr,btread(BT848_RISC_COUNT));
+ pr_info("%d: FDSR @ %08x\n",
+ btv->c.nr, btread(BT848_RISC_COUNT));
if (bttv_debug)
bttv_print_riscaddr(btv);
}
@@ -4097,11 +4112,11 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
if (count > 8 || !(astat & BT848_INT_GPINT)) {
btwrite(0, BT848_INT_MASK);
- printk(KERN_ERR
- "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
+ pr_err("%d: IRQ lockup, cleared int mask [",
+ btv->c.nr);
} else {
- printk(KERN_ERR
- "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr);
+ pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
+ btv->c.nr);
btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
BT848_INT_MASK);
@@ -4109,7 +4124,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
bttv_print_irqbits(stat,astat);
- printk("]\n");
+ pr_cont("]\n");
}
}
btv->irq_total++;
@@ -4171,7 +4186,7 @@ static void bttv_unregister_video(struct bttv *btv)
static int __devinit bttv_register_video(struct bttv *btv)
{
if (no_overlay > 0)
- printk("bttv: Overlay support disabled.\n");
+ pr_notice("Overlay support disabled\n");
/* video */
btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
@@ -4181,12 +4196,11 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
video_nr[btv->c.nr]) < 0)
goto err;
- printk(KERN_INFO "bttv%d: registered device %s\n",
- btv->c.nr, video_device_node_name(btv->video_dev));
+ pr_info("%d: registered device %s\n",
+ btv->c.nr, video_device_node_name(btv->video_dev));
if (device_create_file(&btv->video_dev->dev,
&dev_attr_card)<0) {
- printk(KERN_ERR "bttv%d: device_create_file 'card' "
- "failed\n", btv->c.nr);
+ pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
goto err;
}
@@ -4198,8 +4212,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
vbi_nr[btv->c.nr]) < 0)
goto err;
- printk(KERN_INFO "bttv%d: registered device %s\n",
- btv->c.nr, video_device_node_name(btv->vbi_dev));
+ pr_info("%d: registered device %s\n",
+ btv->c.nr, video_device_node_name(btv->vbi_dev));
if (!btv->has_radio)
return 0;
@@ -4210,8 +4224,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
radio_nr[btv->c.nr]) < 0)
goto err;
- printk(KERN_INFO "bttv%d: registered device %s\n",
- btv->c.nr, video_device_node_name(btv->radio_dev));
+ pr_info("%d: registered device %s\n",
+ btv->c.nr, video_device_node_name(btv->radio_dev));
/* all done */
return 0;
@@ -4244,10 +4258,10 @@ static int __devinit bttv_probe(struct pci_dev *dev,
if (bttv_num == BTTV_MAX)
return -ENOMEM;
- printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
+ pr_info("Bt8xx card found (%d)\n", bttv_num);
bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
if (btv == NULL) {
- printk(KERN_ERR "bttv: out of memory.\n");
+ pr_err("out of memory\n");
return -ENOMEM;
}
btv->c.nr = bttv_num;
@@ -4277,21 +4291,19 @@ static int __devinit bttv_probe(struct pci_dev *dev,
btv->c.pci = dev;
btv->id = dev->device;
if (pci_enable_device(dev)) {
- printk(KERN_WARNING "bttv%d: Can't enable device.\n",
- btv->c.nr);
+ pr_warn("%d: Can't enable device\n", btv->c.nr);
return -EIO;
}
if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
- printk(KERN_WARNING "bttv%d: No suitable DMA available.\n",
- btv->c.nr);
+ pr_warn("%d: No suitable DMA available\n", btv->c.nr);
return -EIO;
}
if (!request_mem_region(pci_resource_start(dev,0),
pci_resource_len(dev,0),
btv->c.v4l2_dev.name)) {
- printk(KERN_WARNING "bttv%d: can't request iomem (0x%llx).\n",
- btv->c.nr,
- (unsigned long long)pci_resource_start(dev,0));
+ pr_warn("%d: can't request iomem (0x%llx)\n",
+ btv->c.nr,
+ (unsigned long long)pci_resource_start(dev, 0));
return -EBUSY;
}
pci_set_master(dev);
@@ -4299,22 +4311,21 @@ static int __devinit bttv_probe(struct pci_dev *dev,
result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
if (result < 0) {
- printk(KERN_WARNING "bttv%d: v4l2_device_register() failed\n", btv->c.nr);
+ pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
goto fail0;
}
btv->revision = dev->revision;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
- printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ",
- bttv_num,btv->id, btv->revision, pci_name(dev));
- printk("irq: %d, latency: %d, mmio: 0x%llx\n",
- btv->c.pci->irq, lat,
- (unsigned long long)pci_resource_start(dev,0));
+ pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
+ bttv_num, btv->id, btv->revision, pci_name(dev),
+ btv->c.pci->irq, lat,
+ (unsigned long long)pci_resource_start(dev, 0));
schedule();
btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
if (NULL == btv->bt848_mmio) {
- printk("bttv%d: ioremap() failed\n", btv->c.nr);
+ pr_err("%d: ioremap() failed\n", btv->c.nr);
result = -EIO;
goto fail1;
}
@@ -4327,8 +4338,8 @@ static int __devinit bttv_probe(struct pci_dev *dev,
result = request_irq(btv->c.pci->irq, bttv_irq,
IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
if (result < 0) {
- printk(KERN_ERR "bttv%d: can't get IRQ %d\n",
- bttv_num,btv->c.pci->irq);
+ pr_err("%d: can't get IRQ %d\n",
+ bttv_num, btv->c.pci->irq);
goto fail1;
}
@@ -4433,7 +4444,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev)
struct bttv *btv = to_bttv(v4l2_dev);
if (bttv_verbose)
- printk("bttv%d: unloading\n",btv->c.nr);
+ pr_info("%d: unloading\n", btv->c.nr);
if (bttv_tvcards[btv->c.type].has_dvb)
flush_request_modules(btv);
@@ -4481,7 +4492,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
struct bttv_buffer_set idle;
unsigned long flags;
- dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
+ dprintk("%d: suspend %d\n", btv->c.nr, state.event);
/* stop dma + irqs */
spin_lock_irqsave(&btv->s_lock,flags);
@@ -4517,14 +4528,13 @@ static int bttv_resume(struct pci_dev *pci_dev)
unsigned long flags;
int err;
- dprintk("bttv%d: resume\n", btv->c.nr);
+ dprintk("%d: resume\n", btv->c.nr);
/* restore pci state */
if (btv->state.disabled) {
err=pci_enable_device(pci_dev);
if (err) {
- printk(KERN_WARNING "bttv%d: Can't enable device.\n",
- btv->c.nr);
+ pr_warn("%d: Can't enable device\n", btv->c.nr);
return err;
}
btv->state.disabled = 0;
@@ -4532,8 +4542,7 @@ static int bttv_resume(struct pci_dev *pci_dev)
err=pci_set_power_state(pci_dev, PCI_D0);
if (err) {
pci_disable_device(pci_dev);
- printk(KERN_WARNING "bttv%d: Can't enable device.\n",
- btv->c.nr);
+ pr_warn("%d: Can't enable device\n", btv->c.nr);
btv->state.disabled = 1;
return err;
}
@@ -4585,22 +4594,21 @@ static int __init bttv_init_module(void)
bttv_num = 0;
- printk(KERN_INFO "bttv: driver version %s loaded\n",
- BTTV_VERSION);
+ pr_info("driver version %s loaded\n", BTTV_VERSION);
if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
gbuffers = 2;
if (gbufsize > BTTV_MAX_FBUF)
gbufsize = BTTV_MAX_FBUF;
gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
if (bttv_verbose)
- printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n",
- gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
+ pr_info("using %d buffers with %dk (%d pages) each for capture\n",
+ gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
bttv_check_chipset();
ret = bus_register(&bttv_sub_bus_type);
if (ret < 0) {
- printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
+ pr_warn("bus_register error: %d\n", ret);
return ret;
}
ret = pci_register_driver(&bttv_pci_driver);
diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c
index 13ce72c04b33..922e8233fd0b 100644
--- a/drivers/media/video/bt8xx/bttv-gpio.c
+++ b/drivers/media/video/bt8xx/bttv-gpio.c
@@ -26,6 +26,8 @@
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -99,7 +101,7 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
kfree(sub);
return err;
}
- printk("bttv%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
+ pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
list_add_tail(&sub->list,&core->subs);
return 0;
}
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index d49b675045fe..e3952af7e56e 100644
--- a/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -27,6 +27,8 @@
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -154,9 +156,7 @@ bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
if (retval == 0)
goto eio;
if (i2c_debug) {
- printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
- if (!(xmit & BT878_I2C_NOSTOP))
- printk(" >\n");
+ pr_cont(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
}
for (cnt = 1; cnt < msg->len; cnt++ ) {
@@ -170,19 +170,18 @@ bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
goto err;
if (retval == 0)
goto eio;
- if (i2c_debug) {
- printk(" %02x", msg->buf[cnt]);
- if (!(xmit & BT878_I2C_NOSTOP))
- printk(" >\n");
- }
+ if (i2c_debug)
+ pr_cont(" %02x", msg->buf[cnt]);
}
+ if (!(xmit & BT878_I2C_NOSTOP))
+ pr_cont(">\n");
return msg->len;
eio:
retval = -EIO;
err:
if (i2c_debug)
- printk(" ERR: %d\n",retval);
+ pr_cont(" ERR: %d\n",retval);
return retval;
}
@@ -193,7 +192,7 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
u32 cnt;
int retval;
- for(cnt = 0; cnt < msg->len; cnt++) {
+ for (cnt = 0; cnt < msg->len; cnt++) {
xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
if (cnt < msg->len-1)
xmit |= BT848_I2C_W3B;
@@ -201,6 +200,12 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
xmit |= BT878_I2C_NOSTOP;
if (cnt)
xmit |= BT878_I2C_NOSTART;
+
+ if (i2c_debug) {
+ if (!(xmit & BT878_I2C_NOSTART))
+ pr_cont(" <R %02x", (msg->addr << 1) +1);
+ }
+
btwrite(xmit, BT848_I2C);
retval = bttv_i2c_wait_done(btv);
if (retval < 0)
@@ -209,20 +214,20 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
goto eio;
msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
if (i2c_debug) {
- if (!(xmit & BT878_I2C_NOSTART))
- printk(" <R %02x", (msg->addr << 1) +1);
- printk(" =%02x", msg->buf[cnt]);
- if (!(xmit & BT878_I2C_NOSTOP))
- printk(" >\n");
+ pr_cont(" =%02x", msg->buf[cnt]);
}
+ if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
+ pr_cont(" >\n");
}
+
+
return msg->len;
eio:
retval = -EIO;
err:
if (i2c_debug)
- printk(" ERR: %d\n",retval);
+ pr_cont(" ERR: %d\n",retval);
return retval;
}
@@ -234,7 +239,8 @@ static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int
int i;
if (i2c_debug)
- printk("bt-i2c:");
+ pr_debug("bt-i2c:");
+
btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
for (i = 0 ; i < num; i++) {
if (msgs[i].flags & I2C_M_RD) {
@@ -271,20 +277,20 @@ int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
if (0 != btv->i2c_rc)
return -1;
if (bttv_verbose && NULL != probe_for)
- printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ",
- btv->c.nr,probe_for,addr);
+ pr_info("%d: i2c: checking for %s @ 0x%02x... ",
+ btv->c.nr, probe_for, addr);
btv->i2c_client.addr = addr >> 1;
if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
if (NULL != probe_for) {
if (bttv_verbose)
- printk("not found\n");
+ pr_cont("not found\n");
} else
- printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n",
- btv->c.nr,addr);
+ pr_warn("%d: i2c read 0x%x: error\n",
+ btv->c.nr, addr);
return -1;
}
if (bttv_verbose && NULL != probe_for)
- printk("found\n");
+ pr_cont("found\n");
return buffer;
}
@@ -335,8 +341,8 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
rc = i2c_master_recv(c,&buf,0);
if (rc < 0)
continue;
- printk("%s: i2c scan: found device @ 0x%x [%s]\n",
- name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+ pr_info("%s: i2c scan: found device @ 0x%x [%s]\n",
+ name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
}
}
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index 677d70c0e1ce..ef4c7cd41982 100644
--- a/drivers/media/video/bt8xx/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -36,9 +38,10 @@ static int ir_rc5_remote_gap = 885;
module_param(ir_rc5_remote_gap, int, 0644);
#undef dprintk
-#define dprintk(arg...) do { \
- if (ir_debug >= 1) \
- printk(arg); \
+#define dprintk(fmt, ...) \
+do { \
+ if (ir_debug >= 1) \
+ pr_info(fmt, ##__VA_ARGS__); \
} while (0)
#define DEVNAME "bttv-input"
@@ -62,7 +65,7 @@ static void ir_handle_key(struct bttv *btv)
/* extract data */
data = ir_extract_bits(gpio, ir->mask_keycode);
- dprintk(KERN_INFO DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
+ dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
gpio, data,
ir->polling ? "poll" : "irq",
(gpio & ir->mask_keydown) ? " down" : "",
@@ -96,7 +99,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0;
if ((ir->last_gpio & 0x7f) != data) {
- dprintk(KERN_INFO DEVNAME ": gpio=0x%x code=%d | %s\n",
+ dprintk("gpio=0x%x code=%d | %s\n",
gpio, data,
(gpio & ir->mask_keyup) ? " up" : "up/down");
@@ -107,7 +110,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
if ((ir->last_gpio & 1 << 31) == keyup)
return;
- dprintk(KERN_INFO DEVNAME ":(cnt) gpio=0x%x code=%d | %s\n",
+ dprintk("(cnt) gpio=0x%x code=%d | %s\n",
gpio, data,
(gpio & ir->mask_keyup) ? " up" : "down");
@@ -177,13 +180,12 @@ static u32 bttv_rc5_decode(unsigned int code)
rc5 |= 1;
break;
case 3:
- dprintk(KERN_INFO DEVNAME ":rc5_decode(%x) bad code\n",
+ dprintk("rc5_decode(%x) bad code\n",
org_code);
return 0;
}
}
- dprintk(KERN_INFO DEVNAME ":"
- "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+ dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
"instr=%x\n", rc5, org_code, RC5_START(rc5),
RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
return rc5;
@@ -212,20 +214,20 @@ static void bttv_rc5_timer_end(unsigned long data)
/* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
if (gap < 28000) {
- dprintk(KERN_INFO DEVNAME ": spurious timer_end\n");
+ dprintk("spurious timer_end\n");
return;
}
if (ir->last_bit < 20) {
/* ignore spurious codes (caused by light/other remotes) */
- dprintk(KERN_INFO DEVNAME ": short code: %x\n", ir->code);
+ dprintk("short code: %x\n", ir->code);
} else {
ir->code = (ir->code << ir->shift_by) | 1;
rc5 = bttv_rc5_decode(ir->code);
/* two start bits? */
if (RC5_START(rc5) != ir->start) {
- printk(KERN_INFO DEVNAME ":"
+ pr_info(DEVNAME ":"
" rc5 start bits invalid: %u\n", RC5_START(rc5));
/* right address? */
@@ -235,8 +237,7 @@ static void bttv_rc5_timer_end(unsigned long data)
/* Good code */
rc_keydown(ir->dev, instr, toggle);
- dprintk(KERN_INFO DEVNAME ":"
- " instruction %x, toggle %x\n",
+ dprintk("instruction %x, toggle %x\n",
instr, toggle);
}
}
@@ -265,7 +266,7 @@ static int bttv_rc5_irq(struct bttv *btv)
tv.tv_usec - ir->base_time.tv_usec;
}
- dprintk(KERN_INFO DEVNAME ": RC5 IRQ: gap %d us for %s\n",
+ dprintk("RC5 IRQ: gap %d us for %s\n",
gap, (gpio & 0x20) ? "mark" : "space");
/* remote IRQ? */
@@ -340,14 +341,14 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
/* poll IR chip */
if (1 != i2c_master_recv(ir->c, &b, 1)) {
- dprintk(KERN_INFO DEVNAME ": read error\n");
+ dprintk("read error\n");
return -EIO;
}
/* ignore 0xaa */
if (b==0xaa)
return 0;
- dprintk(KERN_INFO DEVNAME ": key %02x\n", b);
+ dprintk("key %02x\n", b);
/*
* NOTE:
@@ -517,7 +518,7 @@ int bttv_input_init(struct bttv *btv)
break;
}
if (NULL == ir_codes) {
- dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
+ dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
err = -ENODEV;
goto err_out_free;
}
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c
index 9b57d091da48..82cc47d2e3fa 100644
--- a/drivers/media/video/bt8xx/bttv-risc.c
+++ b/drivers/media/video/bt8xx/bttv-risc.c
@@ -24,6 +24,8 @@
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -473,8 +475,7 @@ bttv_set_dma(struct bttv *btv, int override)
capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */
capctl |= override;
- d2printk(KERN_DEBUG
- "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
+ d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
btv->c.nr,capctl,btv->loop_irq,
btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
@@ -517,8 +518,8 @@ bttv_risc_init_main(struct bttv *btv)
if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
return rc;
- dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
- btv->c.nr,(unsigned long long)btv->main.dma);
+ dprintk("%d: risc main @ %08llx\n",
+ btv->c.nr, (unsigned long long)btv->main.dma);
btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
BT848_FIFO_STATUS_VRE);
@@ -557,12 +558,12 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
unsigned long next = btv->main.dma + ((slot+2) << 2);
if (NULL == risc) {
- d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",
- btv->c.nr,risc,slot);
+ d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
btv->main.cpu[slot+1] = cpu_to_le32(next);
} else {
- d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
- btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);
+ d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
+ btv->c.nr, risc, slot,
+ (unsigned long long)risc->dma, irqflags);
cmd = BT848_RISC_JUMP;
if (irqflags) {
cmd |= BT848_RISC_IRQ;
@@ -708,8 +709,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
- dprintk(KERN_DEBUG
- "bttv%d: buffer field: %s format: %s size: %dx%d\n",
+ dprintk("%d: buffer field: %s format: %s size: %dx%d\n",
btv->c.nr, v4l2_field_names[buf->vb.field],
buf->fmt->name, buf->vb.width, buf->vb.height);
@@ -870,10 +870,9 @@ bttv_overlay_risc(struct bttv *btv,
struct bttv_buffer *buf)
{
/* check interleave, bottom+top fields */
- dprintk(KERN_DEBUG
- "bttv%d: overlay fields: %s format: %s size: %dx%d\n",
+ dprintk("%d: overlay fields: %s format: %s size: %dx%d\n",
btv->c.nr, v4l2_field_names[buf->vb.field],
- fmt->name,ov->w.width,ov->w.height);
+ fmt->name, ov->w.width, ov->w.height);
/* calculate geometry */
bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index e79a402fa6cd..b433267d9aa9 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -23,6 +23,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
@@ -65,8 +67,11 @@ MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)");
#ifdef dprintk
# undef dprintk
#endif
-#define dprintk(fmt, arg...) if (vbi_debug) \
- printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg)
+#define dprintk(fmt, ...) \
+do { \
+ if (vbi_debug) \
+ pr_debug("%d: " fmt, btv->c.nr, ##__VA_ARGS__); \
+} while (0)
#define IMAGE_SIZE(fmt) \
(((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index 318edf2830b4..db943a8d580d 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -310,9 +310,21 @@ extern unsigned int bttv_gpio;
extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
extern int init_bttv_i2c(struct bttv *btv);
-#define bttv_printk if (bttv_verbose) printk
-#define dprintk if (bttv_debug >= 1) printk
-#define d2printk if (bttv_debug >= 2) printk
+#define dprintk(fmt, ...) \
+do { \
+ if (bttv_debug >= 1) \
+ pr_debug(fmt, ##__VA_ARGS__); \
+} while (0)
+#define dprintk_cont(fmt, ...) \
+do { \
+ if (bttv_debug >= 1) \
+ pr_cont(fmt, ##__VA_ARGS__); \
+} while (0)
+#define d2printk(fmt, ...) \
+do { \
+ if (bttv_debug >= 2) \
+ printk(fmt, ##__VA_ARGS__); \
+} while (0)
#define BTTV_MAX_FBUF 0x208000
#define BTTV_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile
index 2fadd9ded340..a86bab5893ef 100644
--- a/drivers/media/video/cx18/Makefile
+++ b/drivers/media/video/cx18/Makefile
@@ -8,6 +8,6 @@ cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o
obj-$(CONFIG_VIDEO_CX18) += cx18.o
obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 183420723060..b9a94fc5146d 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -409,6 +409,7 @@ struct cx18_stream {
/* Videobuf for YUV video */
u32 pixelformat;
+ u32 vb_bytes_per_frame;
struct list_head vb_capture; /* video capture queue */
spinlock_t vb_lock;
struct timer_list vb_timeout;
@@ -430,10 +431,6 @@ struct cx18_open_id {
u32 open_id;
int type;
struct cx18 *cx;
-
- struct videobuf_queue vbuf_q;
- spinlock_t s_lock; /* Protect vbuf_q */
- enum v4l2_buf_type vb_type;
};
static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 07411f34885a..14cb961c22bd 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -784,8 +784,6 @@ int cx18_v4l2_close(struct file *filp)
cx18_release_stream(s);
} else {
cx18_stop_capture(id, 0);
- if (id->type == CX18_ENC_STREAM_TYPE_YUV)
- videobuf_mmap_free(&id->vbuf_q);
}
kfree(id);
mutex_unlock(&cx->serialize_lock);
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index afe0a29e7200..66b1c15c3541 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -160,12 +160,7 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
pixfmt->priv = 0;
if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
pixfmt->pixelformat = s->pixelformat;
- /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
- UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
- if (s->pixelformat == V4L2_PIX_FMT_HM12)
- pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
- else
- pixfmt->sizeimage = pixfmt->height * 720 * 2;
+ pixfmt->sizeimage = s->vb_bytes_per_frame;
pixfmt->bytesperline = 720;
} else {
pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -296,6 +291,12 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
return -EBUSY;
s->pixelformat = fmt->fmt.pix.pixelformat;
+ /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+ UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+ if (s->pixelformat == V4L2_PIX_FMT_HM12)
+ s->vb_bytes_per_frame = h * 720 * 3 / 2;
+ else
+ s->vb_bytes_per_frame = h * 720 * 2;
mbus_fmt.width = cx->cxhdl.width = w;
mbus_fmt.height = cx->cxhdl.height = h;
@@ -463,13 +464,16 @@ static int cx18_s_register(struct file *file, void *fh,
static int cx18_querycap(struct file *file, void *fh,
struct v4l2_capability *vcap)
{
- struct cx18 *cx = fh2id(fh)->cx;
+ struct cx18_open_id *id = fh2id(fh);
+ struct cx18 *cx = id->cx;
strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
snprintf(vcap->bus_info, sizeof(vcap->bus_info),
"PCI:%s", pci_name(cx->pci_dev));
vcap->capabilities = cx->v4l2_cap; /* capabilities */
+ if (id->type == CX18_ENC_STREAM_TYPE_YUV)
+ vcap->capabilities |= V4L2_CAP_STREAMING;
return 0;
}
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index c07191e09fcb..0c7796e76ac0 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -196,7 +196,7 @@ static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
}
/* If we've filled the buffer as per the callers res then dispatch it */
- if (vb_buf->bytes_used >= (vb_buf->vb.width * vb_buf->vb.height * 2)) {
+ if (vb_buf->bytes_used >= s->vb_bytes_per_frame) {
dispatch = 1;
vb_buf->bytes_used = 0;
}
diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h
index 05fe6bdbe062..b63fdfaac49e 100644
--- a/drivers/media/video/cx18/cx18-mailbox.h
+++ b/drivers/media/video/cx18/cx18-mailbox.h
@@ -69,7 +69,7 @@ struct cx18_mailbox {
/* Each command can have up to 6 arguments */
u32 args[MAX_MB_ARGUMENTS];
/* The return code can be one of the codes in the file cx23418.h. If the
- command is completed successfuly, the error will be ERR_SYS_SUCCESS.
+ command is completed successfully, the error will be ERR_SYS_SUCCESS.
If it is pending, the code is ERR_SYS_PENDING. If it failed, the error
code would indicate the task from which the error originated and will
be one of the errors in cx23418.h. In that case, the following
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 852f420fd271..638cca156b58 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -138,6 +138,12 @@ static int cx18_prepare_buffer(struct videobuf_queue *q,
buf->tvnorm = cx->std;
s->pixelformat = pixelformat;
+ /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+ UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+ if (s->pixelformat == V4L2_PIX_FMT_HM12)
+ s->vb_bytes_per_frame = height * 720 * 3 / 2;
+ else
+ s->vb_bytes_per_frame = height * 720 * 2;
cx18_dma_free(q, s, buf);
}
@@ -154,6 +160,12 @@ static int cx18_prepare_buffer(struct videobuf_queue *q,
buf->tvnorm = cx->std;
s->pixelformat = pixelformat;
+ /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+ UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+ if (s->pixelformat == V4L2_PIX_FMT_HM12)
+ s->vb_bytes_per_frame = height * 720 * 3 / 2;
+ else
+ s->vb_bytes_per_frame = height * 720 * 2;
rc = videobuf_iolock(q, &buf->vb, NULL);
if (rc != 0)
goto fail;
@@ -287,6 +299,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
/* Assume the previous pixel default */
s->pixelformat = V4L2_PIX_FMT_HM12;
+ s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
}
}
diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile
index 2c2484355449..b3348975c7c2 100644
--- a/drivers/media/video/cx231xx/Makefile
+++ b/drivers/media/video/cx231xx/Makefile
@@ -8,9 +8,9 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o
obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o
obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-usb
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index caab1bfb79e2..b391e9bda877 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -38,7 +38,7 @@ config VIDEO_CX23885
config MEDIA_ALTERA_CI
tristate "Altera FPGA based CI module"
depends on VIDEO_CX23885 && DVB_CORE
- select STAPL_ALTERA
+ select ALTERA_STAPL
---help---
An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card.
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
index 23293c7b6ac7..f81f2796a0f9 100644
--- a/drivers/media/video/cx23885/Makefile
+++ b/drivers/media/video/cx23885/Makefile
@@ -2,14 +2,14 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
- cx23885-f300.o
+ cx23885-f300.o cx23885-alsa.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/cx23885/cx23885-alsa.c b/drivers/media/video/cx23885/cx23885-alsa.c
new file mode 100644
index 000000000000..795169237e70
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-alsa.c
@@ -0,0 +1,535 @@
+/*
+ *
+ * Support for CX23885 analog audio capture
+ *
+ * (c) 2008 Mijhail Moreyra <mijhail.moreyra@gmail.com>
+ * Adapted from cx88-alsa.c
+ * (c) 2009 Steven Toth <stoth@kernellabs.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/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+
+#include <asm/delay.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
+#include <sound/tlv.h>
+
+
+#include "cx23885.h"
+#include "cx23885-reg.h"
+
+#define AUDIO_SRAM_CHANNEL SRAM_CH07
+
+#define dprintk(level, fmt, arg...) if (audio_debug >= level) \
+ printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg)
+
+#define dprintk_core(level, fmt, arg...) if (audio_debug >= level) \
+ printk(KERN_DEBUG "%s: " fmt, chip->dev->name , ## arg)
+
+/****************************************************************************
+ Module global static vars
+ ****************************************************************************/
+
+static unsigned int disable_analog_audio;
+module_param(disable_analog_audio, int, 0644);
+MODULE_PARM_DESC(disable_analog_audio, "disable analog audio ALSA driver");
+
+static unsigned int audio_debug;
+module_param(audio_debug, int, 0644);
+MODULE_PARM_DESC(audio_debug, "enable debug messages [analog audio]");
+
+/****************************************************************************
+ Board specific funtions
+ ****************************************************************************/
+
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1 (1 << 0)
+#define AUD_INT_UP_RISCI1 (1 << 1)
+#define AUD_INT_RDS_DN_RISCI1 (1 << 2)
+#define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2 (1 << 5)
+#define AUD_INT_RDS_DN_RISCI2 (1 << 6)
+#define AUD_INT_DN_SYNC (1 << 12)
+#define AUD_INT_UP_SYNC (1 << 13)
+#define AUD_INT_RDS_DN_SYNC (1 << 14)
+#define AUD_INT_OPC_ERR (1 << 16)
+#define AUD_INT_BER_IRQ (1 << 20)
+#define AUD_INT_MCHG_IRQ (1 << 21)
+#define GP_COUNT_CONTROL_RESET 0x3
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int cx23885_start_audio_dma(struct cx23885_audio_dev *chip)
+{
+ struct cx23885_audio_buffer *buf = chip->buf;
+ struct cx23885_dev *dev = chip->dev;
+ struct sram_channel *audio_ch =
+ &dev->sram_channels[AUDIO_SRAM_CHANNEL];
+
+ dprintk(1, "%s()\n", __func__);
+
+ /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+ cx_clear(AUD_INT_DMA_CTL, 0x11);
+
+ /* setup fifo + format - out channel */
+ cx23885_sram_channel_setup(chip->dev, audio_ch, buf->bpl,
+ buf->risc.dma);
+
+ /* sets bpl size */
+ cx_write(AUD_INT_A_LNGTH, buf->bpl);
+
+ /* This is required to get good audio (1 seems to be ok) */
+ cx_write(AUD_INT_A_MODE, 1);
+
+ /* reset counter */
+ cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+ atomic_set(&chip->count, 0);
+
+ dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
+ "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start+12)>>1,
+ chip->num_periods, buf->bpl * chip->num_periods);
+
+ /* Enables corresponding bits at AUD_INT_STAT */
+ cx_write(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+ AUD_INT_DN_RISCI1);
+
+ /* Clean any pending interrupt bits already set */
+ cx_write(AUDIO_INT_INT_STAT, ~0);
+
+ /* enable audio irqs */
+ cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+ /* start dma */
+ cx_set(DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
+ cx_set(AUD_INT_DMA_CTL, 0x11); /* audio downstream FIFO and
+ RISC enable */
+ if (audio_debug)
+ cx23885_sram_channel_dump(chip->dev, audio_ch);
+
+ return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int cx23885_stop_audio_dma(struct cx23885_audio_dev *chip)
+{
+ struct cx23885_dev *dev = chip->dev;
+ dprintk(1, "Stopping audio DMA\n");
+
+ /* stop dma */
+ cx_clear(AUD_INT_DMA_CTL, 0x11);
+
+ /* disable irqs */
+ cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+ cx_clear(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+ AUD_INT_DN_RISCI1);
+
+ if (audio_debug)
+ cx23885_sram_channel_dump(chip->dev,
+ &dev->sram_channels[AUDIO_SRAM_CHANNEL]);
+
+ return 0;
+}
+
+/*
+ * BOARD Specific: Handles audio IRQ
+ */
+int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask)
+{
+ struct cx23885_audio_dev *chip = dev->audio_dev;
+
+ if (0 == (status & mask))
+ return 0;
+
+ cx_write(AUDIO_INT_INT_STAT, status);
+
+ /* risc op code error */
+ if (status & AUD_INT_OPC_ERR) {
+ printk(KERN_WARNING "%s/1: Audio risc op code error\n",
+ dev->name);
+ cx_clear(AUD_INT_DMA_CTL, 0x11);
+ cx23885_sram_channel_dump(dev,
+ &dev->sram_channels[AUDIO_SRAM_CHANNEL]);
+ }
+ if (status & AUD_INT_DN_SYNC) {
+ dprintk(1, "Downstream sync error\n");
+ cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+ return 1;
+ }
+ /* risc1 downstream */
+ if (status & AUD_INT_DN_RISCI1) {
+ atomic_set(&chip->count, cx_read(AUD_INT_A_GPCNT));
+ snd_pcm_period_elapsed(chip->substream);
+ }
+ /* FIXME: Any other status should deserve a special handling? */
+
+ return 1;
+}
+
+static int dsp_buffer_free(struct cx23885_audio_dev *chip)
+{
+ BUG_ON(!chip->dma_size);
+
+ dprintk(2, "Freeing buffer\n");
+ videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
+ videobuf_dma_free(chip->dma_risc);
+ btcx_riscmem_free(chip->pci, &chip->buf->risc);
+ kfree(chip->buf);
+
+ chip->dma_risc = NULL;
+ chip->dma_size = 0;
+
+ return 0;
+}
+
+/****************************************************************************
+ ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE 4096
+
+static struct snd_pcm_hardware snd_cx23885_digital_hw = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* Analog audio output will be full of clicks and pops if there
+ are not exactly four lines in the SRAM FIFO buffer. */
+ .period_bytes_min = DEFAULT_FIFO_SIZE/4,
+ .period_bytes_max = DEFAULT_FIFO_SIZE/4,
+ .periods_min = 1,
+ .periods_max = 1024,
+ .buffer_bytes_max = (1024*1024),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx23885_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+
+ if (!chip) {
+ printk(KERN_ERR "BUG: cx23885 can't find device struct."
+ " Can't proceed with open\n");
+ return -ENODEV;
+ }
+
+ err = snd_pcm_hw_constraint_pow2(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0)
+ goto _error;
+
+ chip->substream = substream;
+
+ runtime->hw = snd_cx23885_digital_hw;
+
+ if (chip->dev->sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
+ DEFAULT_FIFO_SIZE) {
+ unsigned int bpl = chip->dev->
+ sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 4;
+ bpl &= ~7; /* must be multiple of 8 */
+ runtime->hw.period_bytes_min = bpl;
+ runtime->hw.period_bytes_max = bpl;
+ }
+
+ return 0;
+_error:
+ dprintk(1, "Error opening PCM!\n");
+ return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx23885_close(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+ struct videobuf_dmabuf *dma;
+
+ struct cx23885_audio_buffer *buf;
+ int ret;
+
+ if (substream->runtime->dma_area) {
+ dsp_buffer_free(chip);
+ substream->runtime->dma_area = NULL;
+ }
+
+ chip->period_size = params_period_bytes(hw_params);
+ chip->num_periods = params_periods(hw_params);
+ chip->dma_size = chip->period_size * params_periods(hw_params);
+
+ BUG_ON(!chip->dma_size);
+ BUG_ON(chip->num_periods & (chip->num_periods-1));
+
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ if (NULL == buf)
+ return -ENOMEM;
+
+ buf->bpl = chip->period_size;
+
+ dma = &buf->dma;
+ videobuf_dma_init(dma);
+ ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+ (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+ if (ret < 0)
+ goto error;
+
+ ret = videobuf_dma_map(&chip->pci->dev, dma);
+ if (ret < 0)
+ goto error;
+
+ ret = cx23885_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
+ chip->period_size, chip->num_periods, 1);
+ if (ret < 0)
+ goto error;
+
+ /* Loop back to start of program */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ chip->buf = buf;
+ chip->dma_risc = dma;
+
+ substream->runtime->dma_area = chip->dma_risc->vaddr;
+ substream->runtime->dma_bytes = chip->dma_size;
+ substream->runtime->dma_addr = 0;
+
+ return 0;
+
+error:
+ kfree(buf);
+ return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx23885_hw_free(struct snd_pcm_substream *substream)
+{
+
+ struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+
+ if (substream->runtime->dma_area) {
+ dsp_buffer_free(chip);
+ substream->runtime->dma_area = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx23885_prepare(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx23885_card_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+ int err;
+
+ /* Local interrupts are already disabled by ALSA */
+ spin_lock(&chip->lock);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ err = cx23885_start_audio_dma(chip);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ err = cx23885_stop_audio_dma(chip);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ spin_unlock(&chip->lock);
+
+ return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx23885_pointer(
+ struct snd_pcm_substream *substream)
+{
+ struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ u16 count;
+
+ count = atomic_read(&chip->count);
+
+ return runtime->period_size * (count & (runtime->periods-1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx23885_page(struct snd_pcm_substream *substream,
+ unsigned long offset)
+{
+ void *pageptr = substream->runtime->dma_area + offset;
+ return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx23885_pcm_ops = {
+ .open = snd_cx23885_pcm_open,
+ .close = snd_cx23885_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cx23885_hw_params,
+ .hw_free = snd_cx23885_hw_free,
+ .prepare = snd_cx23885_prepare,
+ .trigger = snd_cx23885_card_trigger,
+ .pointer = snd_cx23885_pointer,
+ .page = snd_cx23885_page,
+};
+
+/*
+ * create a PCM device
+ */
+static int snd_cx23885_pcm(struct cx23885_audio_dev *chip, int device,
+ char *name)
+{
+ int err;
+ struct snd_pcm *pcm;
+
+ err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+ if (err < 0)
+ return err;
+ pcm->private_data = chip;
+ strcpy(pcm->name, name);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx23885_pcm_ops);
+
+ return 0;
+}
+
+/****************************************************************************
+ Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * Alsa Constructor - Component probe
+ */
+
+struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
+{
+ struct snd_card *card;
+ struct cx23885_audio_dev *chip;
+ int err;
+
+ if (disable_analog_audio)
+ return NULL;
+
+ if (dev->sram_channels[AUDIO_SRAM_CHANNEL].cmds_start == 0) {
+ printk(KERN_WARNING "%s(): Missing SRAM channel configuration "
+ "for analog TV Audio\n", __func__);
+ return NULL;
+ }
+
+ err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+ THIS_MODULE, sizeof(struct cx23885_audio_dev), &card);
+ if (err < 0)
+ goto error;
+
+ chip = (struct cx23885_audio_dev *) card->private_data;
+ chip->dev = dev;
+ chip->pci = dev->pci;
+ chip->card = card;
+ spin_lock_init(&chip->lock);
+
+ snd_card_set_dev(card, &dev->pci->dev);
+
+ err = snd_cx23885_pcm(chip, 0, "CX23885 Digital");
+ if (err < 0)
+ goto error;
+
+ strcpy(card->driver, "CX23885");
+ sprintf(card->shortname, "Conexant CX23885");
+ sprintf(card->longname, "%s at %s", card->shortname, dev->name);
+
+ err = snd_card_register(card);
+ if (err < 0)
+ goto error;
+
+ dprintk(0, "registered ALSA audio device\n");
+
+ return chip;
+
+error:
+ snd_card_free(card);
+ printk(KERN_ERR "%s(): Failed to register analog "
+ "audio adapter\n", __func__);
+
+ return NULL;
+}
+
+/*
+ * ALSA destructor
+ */
+void cx23885_audio_unregister(struct cx23885_dev *dev)
+{
+ struct cx23885_audio_dev *chip = dev->audio_dev;
+
+ snd_card_free(chip->card);
+}
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index 76b7563de39c..c3cf08945e4c 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -25,8 +25,8 @@
#include <linux/delay.h>
#include <media/cx25840.h>
#include <linux/firmware.h>
+#include <misc/altera.h>
-#include "../../../staging/altera-stapl/altera.h"
#include "cx23885.h"
#include "tuner-xc2028.h"
#include "netup-eeprom.h"
@@ -106,12 +106,14 @@ struct cx23885_board cx23885_boards[] = {
.vmux = CX25840_VIN7_CH3 |
CX25840_VIN5_CH2 |
CX25840_VIN2_CH1,
+ .amux = CX25840_AUDIO8,
.gpio0 = 0,
}, {
.type = CX23885_VMUX_COMPOSITE1,
.vmux = CX25840_VIN7_CH3 |
CX25840_VIN4_CH2 |
CX25840_VIN6_CH1,
+ .amux = CX25840_AUDIO7,
.gpio0 = 0,
}, {
.type = CX23885_VMUX_SVIDEO,
@@ -119,6 +121,7 @@ struct cx23885_board cx23885_boards[] = {
CX25840_VIN4_CH2 |
CX25840_VIN8_CH1 |
CX25840_SVIDEO_ON,
+ .amux = CX25840_AUDIO7,
.gpio0 = 0,
} },
},
@@ -153,7 +156,30 @@ struct cx23885_board cx23885_boards[] = {
},
[CX23885_BOARD_HAUPPAUGE_HVR1500] = {
.name = "Hauppauge WinTV-HVR1500",
+ .porta = CX23885_ANALOG_VIDEO,
.portc = CX23885_MPEG_DVB,
+ .tuner_type = TUNER_XC2028,
+ .tuner_addr = 0x61, /* 0xc2 >> 1 */
+ .input = {{
+ .type = CX23885_VMUX_TELEVISION,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN5_CH2 |
+ CX25840_VIN2_CH1,
+ .gpio0 = 0,
+ }, {
+ .type = CX23885_VMUX_COMPOSITE1,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN4_CH2 |
+ CX25840_VIN6_CH1,
+ .gpio0 = 0,
+ }, {
+ .type = CX23885_VMUX_SVIDEO,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN4_CH2 |
+ CX25840_VIN8_CH1 |
+ CX25840_SVIDEO_ON,
+ .gpio0 = 0,
+ } },
},
[CX23885_BOARD_HAUPPAUGE_HVR1200] = {
.name = "Hauppauge WinTV-HVR1200",
@@ -387,6 +413,31 @@ struct cx23885_board cx23885_boards[] = {
.vmux = CX25840_COMPOSITE1,
} },
},
+ [CX23885_BOARD_MPX885] = {
+ .name = "MPX-885",
+ .porta = CX23885_ANALOG_VIDEO,
+ .input = {{
+ .type = CX23885_VMUX_COMPOSITE1,
+ .vmux = CX25840_COMPOSITE1,
+ .amux = CX25840_AUDIO6,
+ .gpio0 = 0,
+ }, {
+ .type = CX23885_VMUX_COMPOSITE2,
+ .vmux = CX25840_COMPOSITE2,
+ .amux = CX25840_AUDIO6,
+ .gpio0 = 0,
+ }, {
+ .type = CX23885_VMUX_COMPOSITE3,
+ .vmux = CX25840_COMPOSITE3,
+ .amux = CX25840_AUDIO7,
+ .gpio0 = 0,
+ }, {
+ .type = CX23885_VMUX_COMPOSITE4,
+ .vmux = CX25840_COMPOSITE4,
+ .amux = CX25840_AUDIO7,
+ .gpio0 = 0,
+ } },
+ },
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -1415,6 +1466,8 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1290:
case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+ case CX23885_BOARD_HAUPPAUGE_HVR1500:
+ case CX23885_BOARD_MPX885:
dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
&dev->i2c_bus[2].i2c_adap,
"cx25840", 0x88 >> 1, NULL);
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index ee41a8882f58..40e68b22015e 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -54,7 +54,7 @@ MODULE_PARM_DESC(card, "card type");
#define dprintk(level, fmt, arg...)\
do { if (debug >= level)\
- printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+ printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
} while (0)
static unsigned int cx23885_devcount;
@@ -155,12 +155,12 @@ static struct sram_channel cx23885_sram_channels[] = {
.cnt2_reg = DMA5_CNT2,
},
[SRAM_CH07] = {
- .name = "ch7",
- .cmds_start = 0x0,
- .ctrl_start = 0x0,
- .cdt = 0x0,
- .fifo_start = 0x0,
- .fifo_size = 0x0,
+ .name = "TV Audio",
+ .cmds_start = 0x10190,
+ .ctrl_start = 0x10480,
+ .cdt = 0x10a00,
+ .fifo_start = 0x7000,
+ .fifo_size = 0x1000,
.ptr1_reg = DMA6_PTR1,
.ptr2_reg = DMA6_PTR2,
.cnt1_reg = DMA6_CNT1,
@@ -1082,10 +1082,10 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
- unsigned int lines)
+ unsigned int lines, unsigned int lpi)
{
struct scatterlist *sg;
- unsigned int line, todo;
+ unsigned int line, todo, sol;
/* sync instruction */
if (sync_line != NO_SYNC_LINE)
@@ -1098,16 +1098,22 @@ static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
offset -= sg_dma_len(sg);
sg++;
}
+
+ if (lpi && line > 0 && !(line % lpi))
+ sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+ else
+ sol = RISC_SOL;
+
if (bpl <= sg_dma_len(sg)-offset) {
/* fits into current chunk */
- *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
+ *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
offset += bpl;
} else {
/* scanline needs to be split */
todo = bpl;
- *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|
+ *(rp++) = cpu_to_le32(RISC_WRITE|sol|
(sg_dma_len(sg)-offset));
*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
@@ -1164,10 +1170,10 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
rp = risc->cpu;
if (UNSET != top_offset)
rp = cx23885_risc_field(rp, sglist, top_offset, 0,
- bpl, padding, lines);
+ bpl, padding, lines, 0);
if (UNSET != bottom_offset)
rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200,
- bpl, padding, lines);
+ bpl, padding, lines, 0);
/* save pointer to jmp instruction address */
risc->jmp = rp;
@@ -1175,11 +1181,11 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
return 0;
}
-static int cx23885_risc_databuffer(struct pci_dev *pci,
+int cx23885_risc_databuffer(struct pci_dev *pci,
struct btcx_riscmem *risc,
struct scatterlist *sglist,
unsigned int bpl,
- unsigned int lines)
+ unsigned int lines, unsigned int lpi)
{
u32 instructions;
__le32 *rp;
@@ -1199,7 +1205,55 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
/* write risc instructions */
rp = risc->cpu;
- rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
+ rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE,
+ bpl, 0, lines, lpi);
+
+ /* save pointer to jmp instruction address */
+ risc->jmp = rp;
+ BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+ return 0;
+}
+
+int cx23885_risc_vbibuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+ struct scatterlist *sglist, unsigned int top_offset,
+ unsigned int bottom_offset, unsigned int bpl,
+ unsigned int padding, unsigned int lines)
+{
+ u32 instructions, fields;
+ __le32 *rp;
+ int rc;
+
+ fields = 0;
+ if (UNSET != top_offset)
+ fields++;
+ if (UNSET != bottom_offset)
+ fields++;
+
+ /* estimate risc mem: worst case is one write per page border +
+ one write per scan line + syncs + jump (all 2 dwords). Padding
+ can cause next bpl to start close to a page border. First DMA
+ region may be smaller than PAGE_SIZE */
+ /* write and jump need and extra dword */
+ instructions = fields * (1 + ((bpl + padding) * lines)
+ / PAGE_SIZE + lines);
+ instructions += 2;
+ rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+ if (rc < 0)
+ return rc;
+ /* write risc instructions */
+ rp = risc->cpu;
+
+ /* Sync to line 6, so US CC line 21 will appear in line '12'
+ * in the userland vbi payload */
+ if (UNSET != top_offset)
+ rp = cx23885_risc_field(rp, sglist, top_offset, 6,
+ bpl, padding, lines, 0);
+
+ if (UNSET != bottom_offset)
+ rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x207,
+ bpl, padding, lines, 0);
+
+
/* save pointer to jmp instruction address */
risc->jmp = rp;
@@ -1207,6 +1261,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
return 0;
}
+
int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value)
{
@@ -1517,7 +1572,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
goto fail;
cx23885_risc_databuffer(dev->pci, &buf->risc,
videobuf_to_dma(&buf->vb)->sglist,
- buf->vb.width, buf->vb.height);
+ buf->vb.width, buf->vb.height, 0);
}
buf->vb.state = VIDEOBUF_PREPARED;
return 0;
@@ -1741,15 +1796,19 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
struct cx23885_tsport *ts2 = &dev->ts2;
u32 pci_status, pci_mask;
u32 vida_status, vida_mask;
+ u32 audint_status, audint_mask;
u32 ts1_status, ts1_mask;
u32 ts2_status, ts2_mask;
int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
+ int audint_count = 0;
bool subdev_handled;
pci_status = cx_read(PCI_INT_STAT);
pci_mask = cx23885_irq_get_mask(dev);
vida_status = cx_read(VID_A_INT_STAT);
vida_mask = cx_read(VID_A_INT_MSK);
+ audint_status = cx_read(AUDIO_INT_INT_STAT);
+ audint_mask = cx_read(AUDIO_INT_INT_MSK);
ts1_status = cx_read(VID_B_INT_STAT);
ts1_mask = cx_read(VID_B_INT_MSK);
ts2_status = cx_read(VID_C_INT_STAT);
@@ -1759,12 +1818,15 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
goto out;
vida_count = cx_read(VID_A_GPCNT);
+ audint_count = cx_read(AUD_INT_A_GPCNT);
ts1_count = cx_read(ts1->reg_gpcnt);
ts2_count = cx_read(ts2->reg_gpcnt);
dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n",
pci_status, pci_mask);
dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n",
vida_status, vida_mask, vida_count);
+ dprintk(7, "audint_status: 0x%08x audint_mask: 0x%08x count: 0x%x\n",
+ audint_status, audint_mask, audint_count);
dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n",
ts1_status, ts1_mask, ts1_count);
dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n",
@@ -1861,6 +1923,9 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
if (vida_status)
handled += cx23885_video_irq(dev, vida_status);
+ if (audint_status)
+ handled += cx23885_audio_irq(dev, audint_status, audint_mask);
+
if (pci_status & PCI_MSK_IR) {
subdev_handled = false;
v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine,
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index aa83f07b1b0f..bcb45be44bb2 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -844,7 +844,7 @@ static int dvb_register(struct cx23885_tsport *port)
static struct xc2028_ctrl ctl = {
.fname = XC3028L_DEFAULT_FIRMWARE,
.max_len = 64,
- .demod = 5000,
+ .demod = XC3028_FE_DIBCOM52,
/* This is true for all demods with
v36 firmware? */
.type = XC2028_D2633,
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index 307ff543c254..0ff7a9e98f3e 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -287,6 +287,7 @@ static char *i2c_devs[128] = {
[0x32 >> 1] = "cx24227",
[0x88 >> 1] = "cx25837",
[0x84 >> 1] = "tda8295",
+ [0x98 >> 1] = "flatiron",
[0xa0 >> 1] = "eeprom",
[0xc0 >> 1] = "tuner/mt2131/tda8275",
[0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h
index c87ac682ebbe..a99936e0cbc2 100644
--- a/drivers/media/video/cx23885/cx23885-reg.h
+++ b/drivers/media/video/cx23885/cx23885-reg.h
@@ -203,6 +203,7 @@ Channel manager Data Structure entry = 20 DWORD
#define SD2_BIAS_CTRL 0x0000000A
#define AMP_BIAS_CTRL 0x0000000C
#define CH_PWR_CTRL1 0x0000000E
+#define FLD_CH_SEL (1 << 3)
#define CH_PWR_CTRL2 0x0000000F
#define DSM_STATUS1 0x00000010
#define DSM_STATUS2 0x00000011
@@ -271,7 +272,9 @@ Channel manager Data Structure entry = 20 DWORD
#define VID_BC_MSK_OPC_ERR (1 << 16)
#define VID_BC_MSK_SYNC (1 << 12)
#define VID_BC_MSK_OF (1 << 8)
+#define VID_BC_MSK_VBI_RISCI2 (1 << 5)
#define VID_BC_MSK_RISCI2 (1 << 4)
+#define VID_BC_MSK_VBI_RISCI1 (1 << 1)
#define VID_BC_MSK_RISCI1 1
#define VID_C_INT_MSK 0x00040040
diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c
index c0b60382ad13..a1154f035bc1 100644
--- a/drivers/media/video/cx23885/cx23885-vbi.c
+++ b/drivers/media/video/cx23885/cx23885-vbi.c
@@ -41,6 +41,12 @@ MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]");
/* ------------------------------------------------------------------ */
+#define VBI_LINE_LENGTH 1440
+#define NTSC_VBI_START_LINE 10 /* line 10 - 21 */
+#define NTSC_VBI_END_LINE 21
+#define NTSC_VBI_LINES (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1)
+
+
int cx23885_vbi_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
@@ -49,43 +55,86 @@ int cx23885_vbi_fmt(struct file *file, void *priv,
if (dev->tvnorm & V4L2_STD_525_60) {
/* ntsc */
- f->fmt.vbi.sampling_rate = 28636363;
+ f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+ f->fmt.vbi.sampling_rate = 27000000;
+ f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+ f->fmt.vbi.offset = 0;
+ f->fmt.vbi.flags = 0;
f->fmt.vbi.start[0] = 10;
- f->fmt.vbi.start[1] = 273;
-
+ f->fmt.vbi.count[0] = 17;
+ f->fmt.vbi.start[1] = 263 + 10 + 1;
+ f->fmt.vbi.count[1] = 17;
} else if (dev->tvnorm & V4L2_STD_625_50) {
/* pal */
f->fmt.vbi.sampling_rate = 35468950;
f->fmt.vbi.start[0] = 7 - 1;
f->fmt.vbi.start[1] = 319 - 1;
}
+
return 0;
}
+/* We're given the Video Interrupt status register.
+ * The cx23885_video_irq() func has already validated
+ * the potential error bits, we just need to
+ * deal with vbi payload and return indication if
+ * we actually processed any payload.
+ */
+int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status)
+{
+ u32 count;
+ int handled = 0;
+
+ if (status & VID_BC_MSK_VBI_RISCI1) {
+ dprintk(1, "%s() VID_BC_MSK_VBI_RISCI1\n", __func__);
+ spin_lock(&dev->slock);
+ count = cx_read(VID_A_GPCNT);
+ cx23885_video_wakeup(dev, &dev->vbiq, count);
+ spin_unlock(&dev->slock);
+ handled++;
+ }
+
+ if (status & VID_BC_MSK_VBI_RISCI2) {
+ dprintk(1, "%s() VID_BC_MSK_VBI_RISCI2\n", __func__);
+ dprintk(2, "stopper vbi\n");
+ spin_lock(&dev->slock);
+ cx23885_restart_vbi_queue(dev, &dev->vbiq);
+ spin_unlock(&dev->slock);
+ handled++;
+ }
+
+ return handled;
+}
+
static int cx23885_start_vbi_dma(struct cx23885_dev *dev,
struct cx23885_dmaqueue *q,
struct cx23885_buffer *buf)
{
+ dprintk(1, "%s()\n", __func__);
+
/* setup fifo + format */
cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02],
buf->vb.width, buf->risc.dma);
/* reset counter */
+ cx_write(VID_A_GPCNT_CTL, 3);
+ cx_write(VID_A_VBI_CTRL, 3);
+ cx_write(VBI_A_GPCNT_CTL, 3);
q->count = 1;
- /* enable irqs */
+ /* enable irq */
cx23885_irq_add_enable(dev, 0x01);
cx_set(VID_A_INT_MSK, 0x000022);
/* start dma */
cx_set(DEV_CNTRL2, (1<<5));
- cx_set(VID_A_DMA_CTL, 0x00000022);
+ cx_set(VID_A_DMA_CTL, 0x22); /* FIFO and RISC enable */
return 0;
}
-static int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
+int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
struct cx23885_dmaqueue *q)
{
struct cx23885_buffer *buf;
@@ -102,7 +151,7 @@ static int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
buf = list_entry(item, struct cx23885_buffer, vb.queue);
buf->count = q->count++;
}
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
return 0;
}
@@ -113,8 +162,7 @@ void cx23885_vbi_timeout(unsigned long data)
struct cx23885_buffer *buf;
unsigned long flags;
- cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH02]);
-
+ /* Stop the VBI engine */
cx_clear(VID_A_DMA_CTL, 0x22);
spin_lock_irqsave(&dev->slock, flags);
@@ -132,7 +180,7 @@ void cx23885_vbi_timeout(unsigned long data)
}
/* ------------------------------------------------------------------ */
-#define VBI_LINE_LENGTH 2048
+#define VBI_LINE_LENGTH 1440
#define VBI_LINE_COUNT 17
static int
@@ -173,7 +221,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
rc = videobuf_iolock(q, &buf->vb, NULL);
if (0 != rc)
goto fail;
- cx23885_risc_buffer(dev->pci, &buf->risc,
+ cx23885_risc_vbibuffer(dev->pci, &buf->risc,
dma->sglist,
0, buf->vb.width * buf->vb.height,
buf->vb.width, 0,
@@ -207,7 +255,7 @@ vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
cx23885_start_vbi_dma(dev, q, buf);
buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
dprintk(2, "[%p/%d] vbi_queue - first active\n",
buf, buf->vb.i);
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index 896bb32dbf03..e730b9263016 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -37,6 +37,8 @@
#include "cx23885-ioctl.h"
#include "tuner-xc2028.h"
+#include <media/cx25840.h>
+
MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
MODULE_LICENSE("GPL");
@@ -69,14 +71,14 @@ MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
#define dprintk(level, fmt, arg...)\
do { if (video_debug >= level)\
- printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+ printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
} while (0)
/* ------------------------------------------------------------------- */
/* static data */
#define FORMAT_FLAGS_PACKED 0x01
-
+#if 0
static struct cx23885_fmt formats[] = {
{
.name = "8 bpp, gray",
@@ -130,6 +132,23 @@ static struct cx23885_fmt formats[] = {
.flags = FORMAT_FLAGS_PACKED,
},
};
+#else
+static struct cx23885_fmt formats[] = {
+ {
+#if 0
+ .name = "4:2:2, packed, UYVY",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .depth = 16,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+#endif
+ .name = "4:2:2, packed, YUYV",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ .flags = FORMAT_FLAGS_PACKED,
+ }
+};
+#endif
static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
{
@@ -139,7 +158,12 @@ static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
if (formats[i].fourcc == fourcc)
return formats+i;
- printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+ printk(KERN_ERR "%s(%c%c%c%c) NOT FOUND\n", __func__,
+ (fourcc & 0xff),
+ ((fourcc >> 8) & 0xff),
+ ((fourcc >> 16) & 0xff),
+ ((fourcc >> 24) & 0xff)
+ );
return NULL;
}
@@ -171,7 +195,7 @@ static struct cx23885_ctrl cx23885_ctls[] = {
.id = V4L2_CID_CONTRAST,
.name = "Contrast",
.minimum = 0,
- .maximum = 0xff,
+ .maximum = 0x7f,
.step = 1,
.default_value = 0x3f,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -184,10 +208,10 @@ static struct cx23885_ctrl cx23885_ctls[] = {
.v = {
.id = V4L2_CID_HUE,
.name = "Hue",
- .minimum = 0,
- .maximum = 0xff,
+ .minimum = -127,
+ .maximum = 128,
.step = 1,
- .default_value = 0x7f,
+ .default_value = 0x0,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.off = 128,
@@ -202,9 +226,9 @@ static struct cx23885_ctrl cx23885_ctls[] = {
.id = V4L2_CID_SATURATION,
.name = "Saturation",
.minimum = 0,
- .maximum = 0xff,
+ .maximum = 0x7f,
.step = 1,
- .default_value = 0x7f,
+ .default_value = 0x3f,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.off = 0,
@@ -258,8 +282,8 @@ static const u32 *ctrl_classes[] = {
NULL
};
-static void cx23885_video_wakeup(struct cx23885_dev *dev,
- struct cx23885_dmaqueue *q, u32 count)
+void cx23885_video_wakeup(struct cx23885_dev *dev,
+ struct cx23885_dmaqueue *q, u32 count)
{
struct cx23885_buffer *buf;
int bc;
@@ -393,6 +417,71 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
mutex_unlock(&dev->lock);
}
+static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
+{
+ /* 8 bit registers, 8 bit values */
+ u8 buf[] = { reg, data };
+
+ struct i2c_msg msg = { .addr = 0x98 >> 1,
+ .flags = 0, .buf = buf, .len = 2 };
+
+ return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
+}
+
+static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
+{
+ /* 8 bit registers, 8 bit values */
+ int ret;
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+
+ struct i2c_msg msg[] = {
+ { .addr = 0x98 >> 1, .flags = 0, .buf = b0, .len = 1 },
+ { .addr = 0x98 >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+ };
+
+ ret = i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg[0], 2);
+ if (ret != 2)
+ printk(KERN_ERR "%s() error\n", __func__);
+
+ return b1[0];
+}
+
+static void cx23885_flatiron_dump(struct cx23885_dev *dev)
+{
+ int i;
+ dprintk(1, "Flatiron dump\n");
+ for (i = 0; i < 0x24; i++) {
+ dprintk(1, "FI[%02x] = %02x\n", i,
+ cx23885_flatiron_read(dev, i));
+ }
+}
+
+static int cx23885_flatiron_mux(struct cx23885_dev *dev, int input)
+{
+ u8 val;
+ dprintk(1, "%s(input = %d)\n", __func__, input);
+
+ if (input == 1)
+ val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) & ~FLD_CH_SEL;
+ else if (input == 2)
+ val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) | FLD_CH_SEL;
+ else
+ return -EINVAL;
+
+ val |= 0x20; /* Enable clock to delta-sigma and dec filter */
+
+ cx23885_flatiron_write(dev, CH_PWR_CTRL1, val);
+
+ /* Wake up */
+ cx23885_flatiron_write(dev, CH_PWR_CTRL2, 0);
+
+ if (video_debug)
+ cx23885_flatiron_dump(dev);
+
+ return 0;
+}
+
static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
{
dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
@@ -413,27 +502,59 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
v4l2_subdev_call(dev->sd_cx25840, video, s_routing,
INPUT(input)->vmux, 0, 0);
+ if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
+ (dev->board == CX23885_BOARD_MPX885)) {
+ /* Configure audio routing */
+ v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
+ INPUT(input)->amux, 0, 0);
+
+ if (INPUT(input)->amux == CX25840_AUDIO7)
+ cx23885_flatiron_mux(dev, 1);
+ else if (INPUT(input)->amux == CX25840_AUDIO6)
+ cx23885_flatiron_mux(dev, 2);
+ }
+
return 0;
}
-/* ------------------------------------------------------------------ */
-static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
- unsigned int height, enum v4l2_field field)
+static int cx23885_audio_mux(struct cx23885_dev *dev, unsigned int input)
{
- dprintk(1, "%s()\n", __func__);
+ dprintk(1, "%s(input=%d)\n", __func__, input);
+
+ /* The baseband video core of the cx23885 has two audio inputs.
+ * LR1 and LR2. In almost every single case so far only HVR1xxx
+ * cards we've only ever supported LR1. Time to support LR2,
+ * which is available via the optional white breakout header on
+ * the board.
+ * We'll use a could of existing enums in the card struct to allow
+ * devs to specify which baseband input they need, or just default
+ * to what we've always used.
+ */
+ if (INPUT(input)->amux == CX25840_AUDIO7)
+ cx23885_flatiron_mux(dev, 1);
+ else if (INPUT(input)->amux == CX25840_AUDIO6)
+ cx23885_flatiron_mux(dev, 2);
+ else {
+ /* Not specifically defined, assume the default. */
+ cx23885_flatiron_mux(dev, 1);
+ }
+
return 0;
}
+/* ------------------------------------------------------------------ */
static int cx23885_start_video_dma(struct cx23885_dev *dev,
struct cx23885_dmaqueue *q,
struct cx23885_buffer *buf)
{
dprintk(1, "%s()\n", __func__);
+ /* Stop the dma/fifo before we tamper with it's risc programs */
+ cx_clear(VID_A_DMA_CTL, 0x11);
+
/* setup fifo + format */
cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
buf->bpl, buf->risc.dma);
- cx23885_set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field);
/* reset counter */
cx_write(VID_A_GPCNT_CTL, 3);
@@ -748,7 +869,7 @@ static int video_open(struct file *file)
fh->type = type;
fh->width = 320;
fh->height = 240;
- fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+ fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV);
videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops,
&dev->pci->dev, &dev->slock,
@@ -757,6 +878,14 @@ static int video_open(struct file *file)
sizeof(struct cx23885_buffer),
fh, NULL);
+ videobuf_queue_sg_init(&fh->vbiq, &cx23885_vbi_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VBI_CAPTURE,
+ V4L2_FIELD_SEQ_TB,
+ sizeof(struct cx23885_buffer),
+ fh, NULL);
+
+
dprintk(1, "post videobuf_queue_init()\n");
return 0;
@@ -884,8 +1013,9 @@ static int cx23885_get_control(struct cx23885_dev *dev,
static int cx23885_set_control(struct cx23885_dev *dev,
struct v4l2_control *ctl)
{
- dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
- " (disabled - no action)\n", __func__);
+ dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__);
+ call_all(dev, core, s_ctrl, ctl);
+
return 0;
}
@@ -1059,13 +1189,22 @@ static int vidioc_streamon(struct file *file, void *priv,
struct cx23885_dev *dev = fh->dev;
dprintk(1, "%s()\n", __func__);
- if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+ if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+ (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
return -EINVAL;
if (unlikely(i != fh->type))
return -EINVAL;
if (unlikely(!res_get(dev, fh, get_resource(fh))))
return -EBUSY;
+
+ /* Don't start VBI streaming unless vida streaming
+ * has already started.
+ */
+ if ((fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) &&
+ ((cx_read(VID_A_DMA_CTL) & 0x11) == 0))
+ return -EINVAL;
+
return videobuf_streamon(get_queue(fh));
}
@@ -1076,7 +1215,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
int err, res;
dprintk(1, "%s()\n", __func__);
- if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+ (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
return -EINVAL;
if (i != fh->type)
return -EINVAL;
@@ -1119,7 +1259,7 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
dprintk(1, "%s()\n", __func__);
n = i->index;
- if (n >= 4)
+ if (n >= MAX_CX23885_INPUT)
return -EINVAL;
if (0 == INPUT(n)->type)
@@ -1133,6 +1273,11 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
i->type = V4L2_INPUT_TYPE_TUNER;
i->std = CX23885_NORMS;
}
+
+ /* Two selectable audio inputs for non-tv inputs */
+ if (INPUT(n)->type != CX23885_VMUX_TELEVISION)
+ i->audioset = 0x3;
+
return 0;
}
@@ -1159,13 +1304,20 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
dprintk(1, "%s(%d)\n", __func__, i);
- if (i >= 4) {
+ if (i >= MAX_CX23885_INPUT) {
dprintk(1, "%s() -EINVAL\n", __func__);
return -EINVAL;
}
+ if (INPUT(i)->type == 0)
+ return -EINVAL;
+
mutex_lock(&dev->lock);
cx23885_video_mux(dev, i);
+
+ /* By default establish the default audio input for the card also */
+ /* Caller is free to use VIDIOC_S_AUDIO to override afterwards */
+ cx23885_audio_mux(dev, i);
mutex_unlock(&dev->lock);
return 0;
}
@@ -1185,6 +1337,64 @@ static int vidioc_log_status(struct file *file, void *priv)
return 0;
}
+static int cx23885_query_audinput(struct file *file, void *priv,
+ struct v4l2_audio *i)
+{
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+ static const char *iname[] = {
+ [0] = "Baseband L/R 1",
+ [1] = "Baseband L/R 2",
+ };
+ unsigned int n;
+ dprintk(1, "%s()\n", __func__);
+
+ n = i->index;
+ if (n >= 2)
+ return -EINVAL;
+
+ memset(i, 0, sizeof(*i));
+ i->index = n;
+ strcpy(i->name, iname[n]);
+ i->capability = V4L2_AUDCAP_STEREO;
+ i->mode = V4L2_AUDMODE_AVL;
+ return 0;
+
+}
+
+static int vidioc_enum_audinput(struct file *file, void *priv,
+ struct v4l2_audio *i)
+{
+ return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_g_audinput(struct file *file, void *priv,
+ struct v4l2_audio *i)
+{
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+ i->index = dev->audinput;
+ dprintk(1, "%s(input=%d)\n", __func__, i->index);
+
+ return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_s_audinput(struct file *file, void *priv,
+ struct v4l2_audio *i)
+{
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+ if (i->index >= 2)
+ return -EINVAL;
+
+ dprintk(1, "%s(%d)\n", __func__, i->index);
+
+ dev->audinput = i->index;
+
+ /* Skip the audio defaults from the cards struct, caller wants
+ * directly touch the audio mux hardware. */
+ cx23885_flatiron_mux(dev, dev->audinput + 1);
+ return 0;
+}
+
static int vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qctrl)
{
@@ -1221,10 +1431,8 @@ static int vidioc_g_tuner(struct file *file, void *priv,
return -EINVAL;
strcpy(t->name, "Television");
- t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM;
- t->rangehigh = 0xffffffffUL;
- t->signal = 0xffff ; /* LOCKED */
+
+ call_all(dev, tuner, g_tuner, t);
return 0;
}
@@ -1237,6 +1445,9 @@ static int vidioc_s_tuner(struct file *file, void *priv,
return -EINVAL;
if (0 != t->index)
return -EINVAL;
+ /* Update the A/V core */
+ call_all(dev, tuner, s_tuner, t);
+
return 0;
}
@@ -1302,10 +1513,6 @@ static void cx23885_vid_timeout(unsigned long data)
struct cx23885_buffer *buf;
unsigned long flags;
- cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]);
-
- cx_clear(VID_A_DMA_CTL, 0x11);
-
spin_lock_irqsave(&dev->slock, flags);
while (!list_empty(&q->active)) {
buf = list_entry(q->active.next,
@@ -1313,7 +1520,7 @@ static void cx23885_vid_timeout(unsigned long data)
list_del(&buf->vb.queue);
buf->vb.state = VIDEOBUF_ERROR;
wake_up(&buf->vb.done);
- printk(KERN_ERR "%s/0: [%p/%d] timeout - dma=0x%08lx\n",
+ printk(KERN_ERR "%s: [%p/%d] timeout - dma=0x%08lx\n",
dev->name, buf, buf->vb.i,
(unsigned long)buf->risc.dma);
}
@@ -1329,27 +1536,43 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
mask = cx_read(VID_A_INT_MSK);
if (0 == (status & mask))
return handled;
+
cx_write(VID_A_INT_STAT, status);
- dprintk(2, "%s() status = 0x%08x\n", __func__, status);
- /* risc op code error */
- if (status & (1 << 16)) {
- printk(KERN_WARNING "%s/0: video risc op code error\n",
- dev->name);
- cx_clear(VID_A_DMA_CTL, 0x11);
- cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]);
+ /* risc op code error, fifo overflow or line sync detection error */
+ if ((status & VID_BC_MSK_OPC_ERR) ||
+ (status & VID_BC_MSK_SYNC) ||
+ (status & VID_BC_MSK_OF)) {
+
+ if (status & VID_BC_MSK_OPC_ERR) {
+ dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
+ VID_BC_MSK_OPC_ERR);
+ printk(KERN_WARNING "%s: video risc op code error\n",
+ dev->name);
+ cx23885_sram_channel_dump(dev,
+ &dev->sram_channels[SRAM_CH01]);
+ }
+
+ if (status & VID_BC_MSK_SYNC)
+ dprintk(7, " (VID_BC_MSK_SYNC 0x%08x) "
+ "video lines miss-match\n",
+ VID_BC_MSK_SYNC);
+
+ if (status & VID_BC_MSK_OF)
+ dprintk(7, " (VID_BC_MSK_OF 0x%08x) fifo overflow\n",
+ VID_BC_MSK_OF);
+
}
- /* risc1 y */
- if (status & 0x01) {
+ /* Video */
+ if (status & VID_BC_MSK_RISCI1) {
spin_lock(&dev->slock);
count = cx_read(VID_A_GPCNT);
cx23885_video_wakeup(dev, &dev->vidq, count);
spin_unlock(&dev->slock);
handled++;
}
- /* risc2 y */
- if (status & 0x10) {
+ if (status & VID_BC_MSK_RISCI2) {
dprintk(2, "stopper video\n");
spin_lock(&dev->slock);
cx23885_restart_video_queue(dev, &dev->vidq);
@@ -1357,6 +1580,9 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
handled++;
}
+ /* Allow the VBI framework to process it's payload */
+ handled += cx23885_vbi_irq(dev, status);
+
return handled;
}
@@ -1405,6 +1631,9 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_g_register = cx23885_g_register,
.vidioc_s_register = cx23885_s_register,
#endif
+ .vidioc_enumaudio = vidioc_enum_audinput,
+ .vidioc_g_audio = vidioc_g_audinput,
+ .vidioc_s_audio = vidioc_s_audinput,
};
static struct video_device cx23885_vbi_template;
@@ -1429,6 +1658,14 @@ void cx23885_video_unregister(struct cx23885_dev *dev)
dprintk(1, "%s()\n", __func__);
cx23885_irq_remove(dev, 0x01);
+ if (dev->vbi_dev) {
+ if (video_is_registered(dev->vbi_dev))
+ video_unregister_device(dev->vbi_dev);
+ else
+ video_device_release(dev->vbi_dev);
+ dev->vbi_dev = NULL;
+ btcx_riscmem_free(dev->pci, &dev->vbiq.stopper);
+ }
if (dev->video_dev) {
if (video_is_registered(dev->video_dev))
video_unregister_device(dev->video_dev);
@@ -1438,6 +1675,9 @@ void cx23885_video_unregister(struct cx23885_dev *dev)
btcx_riscmem_free(dev->pci, &dev->vidq.stopper);
}
+
+ if (dev->audio_dev)
+ cx23885_audio_unregister(dev);
}
int cx23885_video_register(struct cx23885_dev *dev)
@@ -1463,7 +1703,14 @@ int cx23885_video_register(struct cx23885_dev *dev)
cx23885_risc_stopper(dev->pci, &dev->vidq.stopper,
VID_A_DMA_CTL, 0x11, 0x00);
- /* Don't enable VBI yet */
+ /* init vbi dma queues */
+ INIT_LIST_HEAD(&dev->vbiq.active);
+ INIT_LIST_HEAD(&dev->vbiq.queued);
+ dev->vbiq.timeout.function = cx23885_vbi_timeout;
+ dev->vbiq.timeout.data = (unsigned long)dev;
+ init_timer(&dev->vbiq.timeout);
+ cx23885_risc_stopper(dev->pci, &dev->vbiq.stopper,
+ VID_A_DMA_CTL, 0x22, 0x00);
cx23885_irq_add_enable(dev, 0x01);
@@ -1504,8 +1751,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
}
}
-
- /* register v4l devices */
+ /* register Video device */
dev->video_dev = cx23885_vdev_init(dev, dev->pci,
&cx23885_video_template, "video");
err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
@@ -1515,13 +1761,31 @@ int cx23885_video_register(struct cx23885_dev *dev)
dev->name);
goto fail_unreg;
}
- printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
+ printk(KERN_INFO "%s: registered device %s [v4l2]\n",
dev->name, video_device_node_name(dev->video_dev));
+
+ /* register VBI device */
+ dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
+ &cx23885_vbi_template, "vbi");
+ err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+ vbi_nr[dev->nr]);
+ if (err < 0) {
+ printk(KERN_INFO "%s: can't register vbi device\n",
+ dev->name);
+ goto fail_unreg;
+ }
+ printk(KERN_INFO "%s: registered device %s\n",
+ dev->name, video_device_node_name(dev->vbi_dev));
+
+ /* Register ALSA audio device */
+ dev->audio_dev = cx23885_audio_register(dev);
+
/* initial device configuration */
mutex_lock(&dev->lock);
cx23885_set_tvnorm(dev, dev->tvnorm);
init_controls(dev);
cx23885_video_mux(dev, 0);
+ cx23885_audio_mux(dev, 0);
mutex_unlock(&dev->lock);
return 0;
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index d86bc0b1317b..b49036fe3ffd 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -86,6 +86,7 @@
#define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID 29
#define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31
+#define CX23885_BOARD_MPX885 32
#define GPIO_0 0x00000001
#define GPIO_1 0x00000002
@@ -192,6 +193,7 @@ struct cx23885_buffer {
struct cx23885_input {
enum cx23885_itype type;
unsigned int vmux;
+ unsigned int amux;
u32 gpio0, gpio1, gpio2, gpio3;
};
@@ -318,6 +320,34 @@ struct cx23885_kernel_ir {
struct rc_dev *rc;
};
+struct cx23885_audio_buffer {
+ unsigned int bpl;
+ struct btcx_riscmem risc;
+ struct videobuf_dmabuf dma;
+};
+
+struct cx23885_audio_dev {
+ struct cx23885_dev *dev;
+
+ struct pci_dev *pci;
+
+ struct snd_card *card;
+
+ spinlock_t lock;
+
+ atomic_t count;
+
+ unsigned int dma_size;
+ unsigned int period_size;
+ unsigned int num_periods;
+
+ struct videobuf_dmabuf *dma_risc;
+
+ struct cx23885_audio_buffer *buf;
+
+ struct snd_pcm_substream *substream;
+};
+
struct cx23885_dev {
atomic_t refcount;
struct v4l2_device v4l2_dev;
@@ -362,6 +392,7 @@ struct cx23885_dev {
/* Analog video */
u32 resources;
unsigned int input;
+ unsigned int audinput; /* Selectable audio input */
u32 tvaudio;
v4l2_std_id tvnorm;
unsigned int tuner_type;
@@ -400,6 +431,9 @@ struct cx23885_dev {
atomic_t v4l_reader_count;
struct cx23885_tvnorm encodernorm;
+ /* Analog raw audio */
+ struct cx23885_audio_dev *audio_dev;
+
};
static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
@@ -478,6 +512,11 @@ extern int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
unsigned int top_offset, unsigned int bottom_offset,
unsigned int bpl, unsigned int padding, unsigned int lines);
+extern int cx23885_risc_vbibuffer(struct pci_dev *pci,
+ struct btcx_riscmem *risc, struct scatterlist *sglist,
+ unsigned int top_offset, unsigned int bottom_offset,
+ unsigned int bpl, unsigned int padding, unsigned int lines);
+
void cx23885_cancel_buffers(struct cx23885_tsport *port);
extern int cx23885_restart_queue(struct cx23885_tsport *port,
@@ -533,6 +572,8 @@ extern void cx23885_free_buffer(struct videobuf_queue *q,
extern int cx23885_video_register(struct cx23885_dev *dev);
extern void cx23885_video_unregister(struct cx23885_dev *dev);
extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status);
+extern void cx23885_video_wakeup(struct cx23885_dev *dev,
+ struct cx23885_dmaqueue *q, u32 count);
/* ----------------------------------------------------------- */
/* cx23885-vbi.c */
@@ -540,6 +581,9 @@ extern int cx23885_vbi_fmt(struct file *file, void *priv,
struct v4l2_format *f);
extern void cx23885_vbi_timeout(unsigned long data);
extern struct videobuf_queue_ops cx23885_vbi_qops;
+extern int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
+ struct cx23885_dmaqueue *q);
+extern int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status);
/* cx23885-i2c.c */
extern int cx23885_i2c_register(struct cx23885_i2c *bus);
@@ -563,6 +607,18 @@ extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask);
extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask);
extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput);
+/* ----------------------------------------------------------- */
+/* cx23885-alsa.c */
+extern struct cx23885_audio_dev *cx23885_audio_register(
+ struct cx23885_dev *dev);
+extern void cx23885_audio_unregister(struct cx23885_dev *dev);
+extern int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask);
+extern int cx23885_risc_databuffer(struct pci_dev *pci,
+ struct btcx_riscmem *risc,
+ struct scatterlist *sglist,
+ unsigned int bpl,
+ unsigned int lines,
+ unsigned int lpi);
/* ----------------------------------------------------------- */
/* tv norms */
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
index e37be6fcf67d..bb1ce346425d 100644
--- a/drivers/media/video/cx23885/cx23888-ir.c
+++ b/drivers/media/video/cx23885/cx23888-ir.c
@@ -673,7 +673,7 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
unsigned int i, n;
union cx23888_ir_fifo_rec *p;
- unsigned u, v;
+ unsigned u, v, w;
n = count / sizeof(union cx23888_ir_fifo_rec)
* sizeof(union cx23888_ir_fifo_rec);
@@ -692,11 +692,12 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
/* Assume RTO was because of no IR light input */
u = 0;
- v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
+ w = 1;
} else {
u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
if (invert)
u = u ? 0 : 1;
+ w = 0;
}
v = (unsigned) pulse_width_count_to_ns(
@@ -707,9 +708,12 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
init_ir_raw_event(&p->ir_core_data);
p->ir_core_data.pulse = u;
p->ir_core_data.duration = v;
+ p->ir_core_data.timeout = w;
- v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n",
- v, u ? "mark" : "space");
+ v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s %s\n",
+ v, u ? "mark" : "space", w ? "(timed out)" : "");
+ if (w)
+ v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
}
return 0;
}
diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile
index 2ee96d3973b8..dc40dde2e0c8 100644
--- a/drivers/media/video/cx25840/Makefile
+++ b/drivers/media/video/cx25840/Makefile
@@ -3,4 +3,4 @@ cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \
obj-$(CONFIG_VIDEO_CX25840) += cx25840.o
-EXTRA_CFLAGS += -Idrivers/media/video
+ccflags-y += -Idrivers/media/video
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index 34b96c7cfd62..005f11093642 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -480,6 +480,7 @@ void cx25840_audio_set_path(struct i2c_client *client)
static void set_volume(struct i2c_client *client, int volume)
{
+ struct cx25840_state *state = to_state(i2c_get_clientdata(client));
int vol;
/* Convert the volume to msp3400 values (0-127) */
@@ -495,7 +496,14 @@ static void set_volume(struct i2c_client *client, int volume)
}
/* PATH1_VOLUME */
- cx25840_write(client, 0x8d4, 228 - (vol * 2));
+ if (is_cx2388x(state)) {
+ /* for cx23885 volume doesn't work,
+ * the calculation always results in
+ * e4 regardless.
+ */
+ cx25840_write(client, 0x8d4, volume);
+ } else
+ cx25840_write(client, 0x8d4, 228 - (vol * 2));
}
static void set_balance(struct i2c_client *client, int balance)
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index b7ee2ae70583..cd9976408ab3 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -702,6 +702,13 @@ static void cx231xx_initialize(struct i2c_client *client)
/* start microcontroller */
cx25840_and_or(client, 0x803, ~0x10, 0x10);
+
+ /* CC raw enable */
+ cx25840_write(client, 0x404, 0x0b);
+
+ /* CC on */
+ cx25840_write(client, 0x42f, 0x66);
+ cx25840_write4(client, 0x474, 0x1e1e601a);
}
/* ----------------------------------------------------------------------- */
@@ -1067,6 +1074,18 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
cx25840_write(client, 0x919, 0x01);
}
+ if (is_cx2388x(state) && ((aud_input == CX25840_AUDIO7) ||
+ (aud_input == CX25840_AUDIO6))) {
+ /* Configure audio from LR1 or LR2 input */
+ cx25840_write4(client, 0x910, 0);
+ cx25840_write4(client, 0x8d0, 0x63073);
+ } else
+ if (is_cx2388x(state) && (aud_input == CX25840_AUDIO8)) {
+ /* Configure audio from tuner/sif input */
+ cx25840_write4(client, 0x910, 0x12b000c9);
+ cx25840_write4(client, 0x8d0, 0x1f063870);
+ }
+
return 0;
}
diff --git a/drivers/media/video/cx25840/cx25840-ir.c b/drivers/media/video/cx25840/cx25840-ir.c
index 7eb79af28aa3..b718a3a4bed3 100644
--- a/drivers/media/video/cx25840/cx25840-ir.c
+++ b/drivers/media/video/cx25840/cx25840-ir.c
@@ -668,7 +668,7 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
u16 divider;
unsigned int i, n;
union cx25840_ir_fifo_rec *p;
- unsigned u, v;
+ unsigned u, v, w;
if (ir_state == NULL)
return -ENODEV;
@@ -694,11 +694,12 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
/* Assume RTO was because of no IR light input */
u = 0;
- v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
+ w = 1;
} else {
u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
if (invert)
u = u ? 0 : 1;
+ w = 0;
}
v = (unsigned) pulse_width_count_to_ns(
@@ -709,9 +710,12 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
init_ir_raw_event(&p->ir_core_data);
p->ir_core_data.pulse = u;
p->ir_core_data.duration = v;
+ p->ir_core_data.timeout = w;
- v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns %s\n",
- v, u ? "mark" : "space");
+ v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns %s %s\n",
+ v, u ? "mark" : "space", w ? "(timed out)" : "");
+ if (w)
+ v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
}
return 0;
}
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 5b7e26761f0a..c1a2785ba243 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o
obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index fbcaa1c5b09d..fbfdd8067937 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -636,9 +636,6 @@ int cx88_reset(struct cx88_core *core)
cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
- /* set default notch filter */
- cx_andor(MO_HTOTAL, 0x1800, (HLNotchFilter4xFsc << 11));
-
/* Reset on-board parts */
cx_write(MO_SRST_IO, 0);
msleep(10);
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 60d28fdd7791..921c56d115d6 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -266,7 +266,7 @@ static const struct cx88_ctrl cx8800_ctls[] = {
.id = V4L2_CID_BAND_STOP_FILTER,
.name = "Notch filter",
.minimum = 0,
- .maximum = 3,
+ .maximum = 1,
.step = 1,
.default_value = 0x0,
.type = V4L2_CTRL_TYPE_INTEGER,
diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/video/davinci/vpbe_display.c
index 7f1d83a6d575..8588a86d9b45 100644
--- a/drivers/media/video/davinci/vpbe_display.c
+++ b/drivers/media/video/davinci/vpbe_display.c
@@ -43,7 +43,6 @@
static int debug;
-#define VPBE_DISPLAY_SD_BUF_SIZE (720*576*2)
#define VPBE_DEFAULT_NUM_BUFS 3
module_param(debug, int, 0644);
diff --git a/drivers/media/video/davinci/vpbe_osd.c b/drivers/media/video/davinci/vpbe_osd.c
index 5352884998f5..ceccf4302518 100644
--- a/drivers/media/video/davinci/vpbe_osd.c
+++ b/drivers/media/video/davinci/vpbe_osd.c
@@ -1162,7 +1162,7 @@ static int osd_probe(struct platform_device *pdev)
goto free_mem;
}
osd->osd_base_phys = res->start;
- osd->osd_size = res->end - res->start + 1;
+ osd->osd_size = resource_size(res);
if (!request_mem_region(osd->osd_base_phys, osd->osd_size,
MODULE_NAME)) {
dev_err(osd->dev, "Unable to reserve OSD MMIO region\n");
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
index 281ee427c2ab..f6f622e123bd 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -41,6 +41,8 @@ config VIDEO_EM28XX_DVB
select DVB_CXD2820R if !DVB_FE_CUSTOMISE
select DVB_DRXK if !DVB_FE_CUSTOMISE
select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
+ select DVB_TDA10071 if !DVB_FE_CUSTOMISE
+ select DVB_A8293 if !DVB_FE_CUSTOMISE
select VIDEOBUF_DVB
---help---
This adds support for DVB cards based on the
diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile
index 38aaa004f57d..2abdf76c5203 100644
--- a/drivers/media/video/em28xx/Makefile
+++ b/drivers/media/video/em28xx/Makefile
@@ -9,8 +9,8 @@ obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 3e3959fee419..4240f0b720fa 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -60,7 +60,7 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card, "card type");
-/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
+/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
static unsigned long em28xx_devused;
struct em28xx_hash_table {
@@ -317,6 +317,25 @@ static struct em28xx_reg_seq terratec_h5_digital[] = {
};
#endif
+/* 2013:024f PCTV DVB-S2 Stick 460e
+ * GPIO_0 - POWER_ON
+ * GPIO_1 - BOOST
+ * GPIO_2 - VUV_LNB (red LED)
+ * GPIO_3 - EXT_12V
+ * GPIO_4 - INT_DEM (DEMOD GPIO_0)
+ * GPIO_5 - INT_LNB
+ * GPIO_6 - RESET_DEM
+ * GPIO_7 - LED (green LED)
+ */
+static struct em28xx_reg_seq pctv_460e[] = {
+ {EM2874_R80_GPIO, 0x01, 0xff, 50},
+ {0x0d, 0xff, 0xff, 50},
+ {EM2874_R80_GPIO, 0x41, 0xff, 50}, /* GPIO_6=1 */
+ {0x0d, 0x42, 0xff, 50},
+ {EM2874_R80_GPIO, 0x61, 0xff, 50}, /* GPIO_5=1 */
+ { -1, -1, -1, -1},
+};
+
/*
* Board definitions
*/
@@ -1810,6 +1829,17 @@ struct em28xx_board em28xx_boards[] = {
.has_dvb = 1,
.ir_codes = RC_MAP_PINNACLE_PCTV_HD,
},
+ /* 2013:024f PCTV DVB-S2 Stick 460e
+ * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293 */
+ [EM28174_BOARD_PCTV_460E] = {
+ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
+ EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+ .name = "PCTV DVB-S2 Stick (460e)",
+ .tuner_type = TUNER_ABSENT,
+ .tuner_gpio = pctv_460e,
+ .has_dvb = 1,
+ .ir_codes = RC_MAP_PINNACLE_PCTV_HD,
+ },
};
const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
@@ -1941,6 +1971,8 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM2870_BOARD_KWORLD_A340 },
{ USB_DEVICE(0x2013, 0x024f),
.driver_info = EM28174_BOARD_PCTV_290E },
+ { USB_DEVICE(0x2013, 0x024c),
+ .driver_info = EM28174_BOARD_PCTV_460E },
{ },
};
MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -2768,9 +2800,9 @@ static void flush_request_modules(struct em28xx *dev)
#endif /* CONFIG_MODULES */
/*
- * em28xx_realease_resources()
+ * em28xx_release_resources()
* unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
+ * called when the device gets disconnected or at module unload
*/
void em28xx_release_resources(struct em28xx *dev)
{
@@ -2784,8 +2816,6 @@ void em28xx_release_resources(struct em28xx *dev)
em28xx_release_analog_resources(dev);
- em28xx_remove_from_devlist(dev);
-
em28xx_i2c_unregister(dev);
v4l2_device_unregister(&dev->v4l2_dev);
@@ -2793,7 +2823,7 @@ void em28xx_release_resources(struct em28xx *dev)
usb_put_dev(dev->udev);
/* Mark device as unused */
- em28xx_devused &= ~(1 << dev->devno);
+ clear_bit(dev->devno, &em28xx_devused);
};
/*
@@ -2806,7 +2836,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
{
struct em28xx *dev = *devhandle;
int retval;
- int errCode;
dev->udev = udev;
mutex_init(&dev->ctrl_urb_lock);
@@ -2883,10 +2912,9 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
}
if (dev->is_audio_only) {
- errCode = em28xx_audio_setup(dev);
- if (errCode)
+ retval = em28xx_audio_setup(dev);
+ if (retval)
return -ENODEV;
- em28xx_add_into_devlist(dev);
em28xx_init_extension(dev);
return 0;
@@ -2903,7 +2931,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
/* Resets I2C speed */
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
if (retval < 0) {
- em28xx_errdev("%s: em28xx_write_regs_req failed!"
+ em28xx_errdev("%s: em28xx_write_reg failed!"
" retval [%d]\n",
__func__, retval);
return retval;
@@ -2917,12 +2945,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
}
/* register i2c bus */
- errCode = em28xx_i2c_register(dev);
- if (errCode < 0) {
- v4l2_device_unregister(&dev->v4l2_dev);
- em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n",
- __func__, errCode);
- return errCode;
+ retval = em28xx_i2c_register(dev);
+ if (retval < 0) {
+ em28xx_errdev("%s: em28xx_i2c_register - error [%d]!\n",
+ __func__, retval);
+ goto unregister_dev;
}
/*
@@ -2936,11 +2963,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
em28xx_card_setup(dev);
/* Configure audio */
- errCode = em28xx_audio_setup(dev);
- if (errCode < 0) {
- v4l2_device_unregister(&dev->v4l2_dev);
- em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n",
- __func__, errCode);
+ retval = em28xx_audio_setup(dev);
+ if (retval < 0) {
+ em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
+ __func__, retval);
+ goto fail;
}
/* wake i2c devices */
@@ -2954,41 +2981,41 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
if (dev->board.has_msp34xx) {
/* Send a reset to other chips via gpio */
- errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
- if (errCode < 0) {
- em28xx_errdev("%s: em28xx_write_regs_req - "
- "msp34xx(1) failed! errCode [%d]\n",
- __func__, errCode);
- return errCode;
+ retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
+ if (retval < 0) {
+ em28xx_errdev("%s: em28xx_write_reg - "
+ "msp34xx(1) failed! error [%d]\n",
+ __func__, retval);
+ goto fail;
}
msleep(3);
- errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
- if (errCode < 0) {
- em28xx_errdev("%s: em28xx_write_regs_req - "
- "msp34xx(2) failed! errCode [%d]\n",
- __func__, errCode);
- return errCode;
+ retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
+ if (retval < 0) {
+ em28xx_errdev("%s: em28xx_write_reg - "
+ "msp34xx(2) failed! error [%d]\n",
+ __func__, retval);
+ goto fail;
}
msleep(3);
}
- em28xx_add_into_devlist(dev);
-
retval = em28xx_register_analog_devices(dev);
if (retval < 0) {
- em28xx_release_resources(dev);
- goto fail_reg_devices;
+ goto fail;
}
- em28xx_init_extension(dev);
-
/* Save some power by putting tuner to sleep */
v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
return 0;
-fail_reg_devices:
+fail:
+ em28xx_i2c_unregister(dev);
+
+unregister_dev:
+ v4l2_device_unregister(&dev->v4l2_dev);
+
return retval;
}
@@ -3015,8 +3042,16 @@ static int em28xx_usb_probe(struct usb_interface *interface,
udev = usb_get_dev(interface_to_usbdev(interface));
/* Check to see next free device and mark as used */
- nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
- em28xx_devused |= 1<<nr;
+ do {
+ nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
+ if (nr >= EM28XX_MAXBOARDS) {
+ /* No free device slots */
+ printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
+ EM28XX_MAXBOARDS);
+ retval = -ENOMEM;
+ goto err_no_slot;
+ }
+ } while (test_and_set_bit(nr, &em28xx_devused));
/* Don't register audio interfaces */
if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
@@ -3027,7 +3062,6 @@ static int em28xx_usb_probe(struct usb_interface *interface,
ifnum,
interface->altsetting[0].desc.bInterfaceClass);
- em28xx_devused &= ~(1<<nr);
retval = -ENODEV;
goto err;
}
@@ -3076,7 +3110,6 @@ static int em28xx_usb_probe(struct usb_interface *interface,
em28xx_err(DRIVER_NAME " This is an anciliary "
"interface not used by the driver\n");
- em28xx_devused &= ~(1<<nr);
retval = -ENODEV;
goto err;
}
@@ -3132,29 +3165,19 @@ static int em28xx_usb_probe(struct usb_interface *interface,
printk(DRIVER_NAME ": Device initialization failed.\n");
printk(DRIVER_NAME ": Device must be connected to a high-speed"
" USB 2.0 port.\n");
- em28xx_devused &= ~(1<<nr);
retval = -ENODEV;
goto err;
}
- if (nr >= EM28XX_MAXBOARDS) {
- printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
- EM28XX_MAXBOARDS);
- em28xx_devused &= ~(1<<nr);
- retval = -ENOMEM;
- goto err;
- }
-
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
em28xx_err(DRIVER_NAME ": out of memory!\n");
- em28xx_devused &= ~(1<<nr);
retval = -ENOMEM;
goto err;
}
- snprintf(dev->name, 29, "em28xx #%d", nr);
+ snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr);
dev->devno = nr;
dev->model = id->driver_info;
dev->alt = -1;
@@ -3177,7 +3200,6 @@ static int em28xx_usb_probe(struct usb_interface *interface,
if (dev->alt_max_pkt_size == NULL) {
em28xx_errdev("out of memory!\n");
- em28xx_devused &= ~(1<<nr);
kfree(dev);
retval = -ENOMEM;
goto err;
@@ -3204,8 +3226,8 @@ static int em28xx_usb_probe(struct usb_interface *interface,
mutex_lock(&dev->lock);
retval = em28xx_init_dev(&dev, udev, interface, nr);
if (retval) {
- em28xx_devused &= ~(1<<dev->devno);
mutex_unlock(&dev->lock);
+ kfree(dev->alt_max_pkt_size);
kfree(dev);
goto err;
}
@@ -3217,15 +3239,26 @@ static int em28xx_usb_probe(struct usb_interface *interface,
*/
mutex_unlock(&dev->lock);
+ /*
+ * These extensions can be modules. If the modules are already
+ * loaded then we can initialise the device now, otherwise we
+ * will initialise it when the modules load instead.
+ */
+ em28xx_init_extension(dev);
+
return 0;
err:
+ clear_bit(nr, &em28xx_devused);
+
+err_no_slot:
+ usb_put_dev(udev);
return retval;
}
/*
* em28xx_usb_disconnect()
- * called when the device gets diconencted
+ * called when the device gets disconnected
* video device will be unregistered on v4l2_close in case it is still open
*/
static void em28xx_usb_disconnect(struct usb_interface *interface)
@@ -3273,10 +3306,10 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
em28xx_release_resources(dev);
}
- em28xx_close_extension(dev);
-
mutex_unlock(&dev->lock);
+ em28xx_close_extension(dev);
+
if (!dev->users) {
kfree(dev->alt_max_pkt_size);
kfree(dev);
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 57b1b5c6d885..804a4ab47ac6 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -1184,25 +1184,6 @@ static LIST_HEAD(em28xx_devlist);
static DEFINE_MUTEX(em28xx_devlist_mutex);
/*
- * em28xx_realease_resources()
- * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
-*/
-void em28xx_remove_from_devlist(struct em28xx *dev)
-{
- mutex_lock(&em28xx_devlist_mutex);
- list_del(&dev->devlist);
- mutex_unlock(&em28xx_devlist_mutex);
-};
-
-void em28xx_add_into_devlist(struct em28xx *dev)
-{
- mutex_lock(&em28xx_devlist_mutex);
- list_add_tail(&dev->devlist, &em28xx_devlist);
- mutex_unlock(&em28xx_devlist_mutex);
-};
-
-/*
* Extension interface
*/
@@ -1217,8 +1198,8 @@ int em28xx_register_extension(struct em28xx_ops *ops)
list_for_each_entry(dev, &em28xx_devlist, devlist) {
ops->init(dev);
}
- printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
mutex_unlock(&em28xx_devlist_mutex);
+ printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
return 0;
}
EXPORT_SYMBOL(em28xx_register_extension);
@@ -1231,36 +1212,34 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
list_for_each_entry(dev, &em28xx_devlist, devlist) {
ops->fini(dev);
}
- printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
list_del(&ops->next);
mutex_unlock(&em28xx_devlist_mutex);
+ printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
}
EXPORT_SYMBOL(em28xx_unregister_extension);
void em28xx_init_extension(struct em28xx *dev)
{
- struct em28xx_ops *ops = NULL;
+ const struct em28xx_ops *ops = NULL;
mutex_lock(&em28xx_devlist_mutex);
- if (!list_empty(&em28xx_extension_devlist)) {
- list_for_each_entry(ops, &em28xx_extension_devlist, next) {
- if (ops->init)
- ops->init(dev);
- }
+ list_add_tail(&dev->devlist, &em28xx_devlist);
+ list_for_each_entry(ops, &em28xx_extension_devlist, next) {
+ if (ops->init)
+ ops->init(dev);
}
mutex_unlock(&em28xx_devlist_mutex);
}
void em28xx_close_extension(struct em28xx *dev)
{
- struct em28xx_ops *ops = NULL;
+ const struct em28xx_ops *ops = NULL;
mutex_lock(&em28xx_devlist_mutex);
- if (!list_empty(&em28xx_extension_devlist)) {
- list_for_each_entry(ops, &em28xx_extension_devlist, next) {
- if (ops->fini)
- ops->fini(dev);
- }
+ list_for_each_entry(ops, &em28xx_extension_devlist, next) {
+ if (ops->fini)
+ ops->fini(dev);
}
+ list_del(&dev->devlist);
mutex_unlock(&em28xx_devlist_mutex);
}
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index e5916dee4094..cef7a2d409cb 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -42,6 +42,8 @@
#include "cxd2820r.h"
#include "tda18271c2dd.h"
#include "drxk.h"
+#include "tda10071.h"
+#include "a8293.h"
MODULE_DESCRIPTION("driver for em28xx based DVB cards");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -122,7 +124,7 @@ static inline void print_err_status(struct em28xx *dev,
}
}
-static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
+static inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
{
int i;
@@ -155,7 +157,7 @@ static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
return 0;
}
-static int start_streaming(struct em28xx_dvb *dvb)
+static int em28xx_start_streaming(struct em28xx_dvb *dvb)
{
int rc;
struct em28xx *dev = dvb->adapter.priv;
@@ -175,10 +177,10 @@ static int start_streaming(struct em28xx_dvb *dvb)
return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
EM28XX_DVB_NUM_BUFS, max_dvb_packet_size,
- dvb_isoc_copy);
+ em28xx_dvb_isoc_copy);
}
-static int stop_streaming(struct em28xx_dvb *dvb)
+static int em28xx_stop_streaming(struct em28xx_dvb *dvb)
{
struct em28xx *dev = dvb->adapter.priv;
@@ -189,7 +191,7 @@ static int stop_streaming(struct em28xx_dvb *dvb)
return 0;
}
-static int start_feed(struct dvb_demux_feed *feed)
+static int em28xx_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct em28xx_dvb *dvb = demux->priv;
@@ -203,7 +205,7 @@ static int start_feed(struct dvb_demux_feed *feed)
rc = dvb->nfeeds;
if (dvb->nfeeds == 1) {
- ret = start_streaming(dvb);
+ ret = em28xx_start_streaming(dvb);
if (ret < 0)
rc = ret;
}
@@ -212,7 +214,7 @@ static int start_feed(struct dvb_demux_feed *feed)
return rc;
}
-static int stop_feed(struct dvb_demux_feed *feed)
+static int em28xx_stop_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct em28xx_dvb *dvb = demux->priv;
@@ -222,7 +224,7 @@ static int stop_feed(struct dvb_demux_feed *feed)
dvb->nfeeds--;
if (0 == dvb->nfeeds)
- err = stop_streaming(dvb);
+ err = em28xx_stop_streaming(dvb);
mutex_unlock(&dvb->lock);
return err;
@@ -380,7 +382,7 @@ static void terratec_h5_init(struct em28xx *dev)
em28xx_gpio_set(dev, terratec_h5_end);
};
-static int mt352_terratec_xs_init(struct dvb_frontend *fe)
+static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
{
/* Values extracted from a USB trace of the Terratec Windows driver */
static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c };
@@ -412,7 +414,7 @@ static struct mt352_config terratec_xs_mt352_cfg = {
.demod_address = (0x1e >> 1),
.no_tuner = 1,
.if2 = 45600,
- .demod_init = mt352_terratec_xs_init,
+ .demod_init = em28xx_mt352_terratec_xs_init,
};
static struct tda10023_config em28xx_tda10023_config = {
@@ -438,11 +440,25 @@ static struct cxd2820r_config em28xx_cxd2820r_config = {
static struct tda18271_config em28xx_cxd2820r_tda18271_config = {
.output_opt = TDA18271_OUTPUT_LT_OFF,
+ .gate = TDA18271_GATE_DIGITAL,
+};
+
+static const struct tda10071_config em28xx_tda10071_config = {
+ .i2c_address = 0x55, /* (0xaa >> 1) */
+ .i2c_wr_max = 64,
+ .ts_mode = TDA10071_TS_SERIAL,
+ .spec_inv = 0,
+ .xtal = 40444000, /* 40.444 MHz */
+ .pll_multiplier = 20,
+};
+
+static const struct a8293_config em28xx_a8293_config = {
+ .i2c_addr = 0x08, /* (0x10 >> 1) */
};
/* ------------------------------------------------------------------ */
-static int attach_xc3028(u8 addr, struct em28xx *dev)
+static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
{
struct dvb_frontend *fe;
struct xc2028_config cfg;
@@ -472,10 +488,8 @@ static int attach_xc3028(u8 addr, struct em28xx *dev)
/* ------------------------------------------------------------------ */
-static int register_dvb(struct em28xx_dvb *dvb,
- struct module *module,
- struct em28xx *dev,
- struct device *device)
+static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module,
+ struct em28xx *dev, struct device *device)
{
int result;
@@ -522,8 +536,8 @@ static int register_dvb(struct em28xx_dvb *dvb,
dvb->demux.priv = dvb;
dvb->demux.filternum = 256;
dvb->demux.feednum = 256;
- dvb->demux.start_feed = start_feed;
- dvb->demux.stop_feed = stop_feed;
+ dvb->demux.start_feed = em28xx_start_feed;
+ dvb->demux.stop_feed = em28xx_stop_feed;
result = dvb_dmx_init(&dvb->demux);
if (result < 0) {
@@ -591,7 +605,7 @@ fail_adapter:
return result;
}
-static void unregister_dvb(struct em28xx_dvb *dvb)
+static void em28xx_unregister_dvb(struct em28xx_dvb *dvb)
{
dvb_net_release(&dvb->net);
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
@@ -607,9 +621,9 @@ static void unregister_dvb(struct em28xx_dvb *dvb)
dvb_unregister_adapter(&dvb->adapter);
}
-static int dvb_init(struct em28xx *dev)
+static int em28xx_dvb_init(struct em28xx *dev)
{
- int result = 0;
+ int result = 0, mfe_shared = 0;
struct em28xx_dvb *dvb;
if (!dev->board.has_dvb) {
@@ -648,7 +662,7 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(lgdt330x_attach,
&em2880_lgdt3303_dev,
&dev->i2c_adap);
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -657,7 +671,7 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(zl10353_attach,
&em28xx_zl10353_with_xc3028,
&dev->i2c_adap);
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -668,7 +682,7 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(zl10353_attach,
&em28xx_zl10353_xc3028_no_i2c_gate,
&dev->i2c_adap);
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -689,7 +703,7 @@ static int dvb_init(struct em28xx *dev)
&dev->i2c_adap);
}
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -699,7 +713,7 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(s5h1409_attach,
&em28xx_s5h1409_with_xc3028,
&dev->i2c_adap);
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -720,7 +734,7 @@ static int dvb_init(struct em28xx *dev)
case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
&dev->i2c_adap, &dev->udev->dev);
- if (attach_xc3028(0x61, dev) < 0) {
+ if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
@@ -753,11 +767,9 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(cxd2820r_attach,
&em28xx_cxd2820r_config, &dev->i2c_adap, NULL);
if (dvb->fe[0]) {
- struct i2c_adapter *i2c_tuner;
- i2c_tuner = cxd2820r_get_tuner_i2c_adapter(dvb->fe[0]);
/* FE 0 attach tuner */
if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
- i2c_tuner, &em28xx_cxd2820r_tda18271_config)) {
+ &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
dvb_frontend_detach(dvb->fe[0]);
result = -EINVAL;
goto out_free;
@@ -768,10 +780,12 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[1]->id = 1;
/* FE 1 attach tuner */
if (!dvb_attach(tda18271_attach, dvb->fe[1], 0x60,
- i2c_tuner, &em28xx_cxd2820r_tda18271_config)) {
+ &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
dvb_frontend_detach(dvb->fe[1]);
/* leave FE 0 still active */
}
+
+ mfe_shared = 1;
}
break;
case EM2884_BOARD_TERRATEC_H5:
@@ -809,6 +823,16 @@ static int dvb_init(struct em28xx *dev)
sizeof(dvb->fe[0]->ops.tuner_ops));
break;
+ case EM28174_BOARD_PCTV_460E:
+ /* attach demod */
+ dvb->fe[0] = dvb_attach(tda10071_attach,
+ &em28xx_tda10071_config, &dev->i2c_adap);
+
+ /* attach SEC */
+ if (dvb->fe[0])
+ dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap,
+ &em28xx_a8293_config);
+ break;
default:
em28xx_errdev("/2: The frontend of your DVB/ATSC card"
" isn't supported yet\n");
@@ -823,11 +847,14 @@ static int dvb_init(struct em28xx *dev)
dvb->fe[0]->callback = em28xx_tuner_callback;
/* register everything */
- result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+ result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
if (result < 0)
goto out_free;
+ /* MFE lock */
+ dvb->adapter.mfe_shared = mfe_shared;
+
em28xx_info("Successfully loaded em28xx-dvb\n");
ret:
em28xx_set_mode(dev, EM28XX_SUSPEND);
@@ -840,7 +867,14 @@ out_free:
goto ret;
}
-static int dvb_fini(struct em28xx *dev)
+static inline void prevent_sleep(struct dvb_frontend_ops *ops)
+{
+ ops->set_voltage = NULL;
+ ops->sleep = NULL;
+ ops->tuner_ops.sleep = NULL;
+}
+
+static int em28xx_dvb_fini(struct em28xx *dev)
{
if (!dev->board.has_dvb) {
/* This device does not support the extension */
@@ -848,8 +882,19 @@ static int dvb_fini(struct em28xx *dev)
}
if (dev->dvb) {
- unregister_dvb(dev->dvb);
- kfree(dev->dvb);
+ struct em28xx_dvb *dvb = dev->dvb;
+
+ if (dev->state & DEV_DISCONNECTED) {
+ /* We cannot tell the device to sleep
+ * once it has been unplugged. */
+ if (dvb->fe[0])
+ prevent_sleep(&dvb->fe[0]->ops);
+ if (dvb->fe[1])
+ prevent_sleep(&dvb->fe[1]->ops);
+ }
+
+ em28xx_unregister_dvb(dvb);
+ kfree(dvb);
dev->dvb = NULL;
}
@@ -859,8 +904,8 @@ static int dvb_fini(struct em28xx *dev)
static struct em28xx_ops dvb_ops = {
.id = EM28XX_DVB,
.name = "Em28xx dvb Extension",
- .init = dvb_init,
- .fini = dvb_fini,
+ .init = em28xx_dvb_init,
+ .fini = em28xx_dvb_fini,
};
static int __init em28xx_dvb_register(void)
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 5d12b14282e3..679da4804281 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -463,11 +463,11 @@ int em28xx_ir_fini(struct em28xx *dev)
if (!ir)
return 0;
- em28xx_ir_stop(ir->rc);
- rc_unregister_device(ir->rc);
- kfree(ir);
+ if (ir->rc)
+ rc_unregister_device(ir->rc);
/* done */
+ kfree(ir);
dev->ir = NULL;
return 0;
}
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index d176dc0394e2..9b4557a2f6d0 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1156,6 +1156,21 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
return 0;
}
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
+{
+ struct em28xx_fh *fh = priv;
+ struct em28xx *dev = fh->dev;
+ int rc;
+
+ rc = check_dev(dev);
+ if (rc < 0)
+ return rc;
+
+ v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
+
+ return 0;
+}
+
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
{
struct em28xx_fh *fh = priv;
@@ -1787,6 +1802,45 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct em28xx_fh *fh = priv;
+ struct em28xx *dev = fh->dev;
+ struct em28xx_fmt *fmt;
+ unsigned int maxw = norm_maxw(dev);
+ unsigned int maxh = norm_maxh(dev);
+
+ fmt = format_by_fourcc(fsize->pixel_format);
+ if (!fmt) {
+ em28xx_videodbg("Fourcc format (%08x) invalid.\n",
+ fsize->pixel_format);
+ return -EINVAL;
+ }
+
+ if (dev->board.is_em2800) {
+ if (fsize->index > 1)
+ return -EINVAL;
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = maxw / (1 + fsize->index);
+ fsize->discrete.height = maxh / (1 + fsize->index);
+ return 0;
+ }
+
+ if (fsize->index != 0)
+ return -EINVAL;
+
+ /* Report a continuous range */
+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ fsize->stepwise.min_width = 48;
+ fsize->stepwise.min_height = 32;
+ fsize->stepwise.max_width = maxw;
+ fsize->stepwise.max_height = maxh;
+ fsize->stepwise.step_width = 1;
+ fsize->stepwise.step_height = 1;
+ return 0;
+}
+
/* Sliced VBI ioctls */
static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
struct v4l2_format *f)
@@ -2200,6 +2254,7 @@ static int em28xx_v4l2_close(struct file *filp)
free the remaining resources */
if (dev->state & DEV_DISCONNECTED) {
em28xx_release_resources(dev);
+ kfree(dev->alt_max_pkt_size);
kfree(dev);
return 0;
}
@@ -2340,10 +2395,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
.vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
.vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
+ .vidioc_enum_framesizes = vidioc_enum_framesizes,
.vidioc_g_audio = vidioc_g_audio,
.vidioc_s_audio = vidioc_s_audio,
.vidioc_cropcap = vidioc_cropcap,
-
.vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap,
.vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
.vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
@@ -2353,6 +2408,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_g_std = vidioc_g_std,
+ .vidioc_querystd = vidioc_querystd,
.vidioc_s_std = vidioc_s_std,
.vidioc_g_parm = vidioc_g_parm,
.vidioc_s_parm = vidioc_s_parm,
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index d80658bf3da9..2a2cb7ed0014 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -120,6 +120,7 @@
#define EM2874_BOARD_LEADERSHIP_ISDBT 77
#define EM28174_BOARD_PCTV_290E 78
#define EM2884_BOARD_TERRATEC_H5 79
+#define EM28174_BOARD_PCTV_460E 80
/* Limits minimum and default number of buffers */
#define EM28XX_MIN_BUF 4
@@ -677,8 +678,6 @@ int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev);
int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
void em28xx_wake_i2c(struct em28xx *dev);
-void em28xx_remove_from_devlist(struct em28xx *dev);
-void em28xx_add_into_devlist(struct em28xx *dev);
int em28xx_register_extension(struct em28xx_ops *dev);
void em28xx_unregister_extension(struct em28xx_ops *dev);
void em28xx_init_extension(struct em28xx *dev);
diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h
index 14bb907d650e..337ded4a6388 100644
--- a/drivers/media/video/et61x251/et61x251.h
+++ b/drivers/media/video/et61x251/et61x251.h
@@ -165,45 +165,49 @@ et61x251_attach_sensor(struct et61x251_device* cam,
#undef DBG
#undef KDBG
#ifdef ET61X251_DEBUG
-# define DBG(level, fmt, args...) \
-do { \
- if (debug >= (level)) { \
- if ((level) == 1) \
- dev_err(&cam->usbdev->dev, fmt "\n", ## args); \
- else if ((level) == 2) \
- dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
- else if ((level) >= 3) \
- dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
- __FILE__, __func__, __LINE__ , ## args); \
- } \
+#define DBG(level, fmt, ...) \
+do { \
+ if (debug >= (level)) { \
+ if ((level) == 1) \
+ dev_err(&cam->usbdev->dev, fmt "\n", \
+ ##__VA_ARGS__); \
+ else if ((level) == 2) \
+ dev_info(&cam->usbdev->dev, fmt "\n", \
+ ##__VA_ARGS__); \
+ else if ((level) >= 3) \
+ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
+ __FILE__, __func__, __LINE__, \
+ ##__VA_ARGS__); \
+ } \
} while (0)
-# define KDBG(level, fmt, args...) \
-do { \
- if (debug >= (level)) { \
- if ((level) == 1 || (level) == 2) \
- pr_info("et61x251: " fmt "\n", ## args); \
- else if ((level) == 3) \
- pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \
- __func__, __LINE__ , ## args); \
- } \
+#define KDBG(level, fmt, ...) \
+do { \
+ if (debug >= (level)) { \
+ if ((level) == 1 || (level) == 2) \
+ pr_info(fmt "\n", ##__VA_ARGS__); \
+ else if ((level) == 3) \
+ pr_debug("[%s:%s:%d] " fmt "\n", \
+ __FILE__, __func__, __LINE__, \
+ ##__VA_ARGS__); \
+ } \
} while (0)
-# define V4LDBG(level, name, cmd) \
-do { \
- if (debug >= (level)) \
- v4l_print_ioctl(name, cmd); \
+#define V4LDBG(level, name, cmd) \
+do { \
+ if (debug >= (level)) \
+ v4l_print_ioctl(name, cmd); \
} while (0)
#else
-# define DBG(level, fmt, args...) do {;} while(0)
-# define KDBG(level, fmt, args...) do {;} while(0)
-# define V4LDBG(level, name, cmd) do {;} while(0)
+#define DBG(level, fmt, ...) do {;} while(0)
+#define KDBG(level, fmt, ...) do {;} while(0)
+#define V4LDBG(level, name, cmd) do {;} while(0)
#endif
#undef PDBG
-#define PDBG(fmt, args...) \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \
- __LINE__ , ## args)
+#define PDBG(fmt, ...) \
+ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
+ __FILE__, __func__, __LINE__, ##__VA_ARGS__)
#undef PDBGG
-#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
+#define PDBGG(fmt, args...) do {;} while (0) /* placeholder */
#endif /* _ET61X251_H_ */
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 9a1e80a1e145..d3777c86e1de 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
***************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/media/video/et61x251/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c
index 04b7fbb310a8..ced2e167935d 100644
--- a/drivers/media/video/et61x251/et61x251_tas5130d1b.c
+++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
***************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "et61x251_sensor.h"
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
index 43d9a20caebc..103af3fe5aa0 100644
--- a/drivers/media/video/gspca/Kconfig
+++ b/drivers/media/video/gspca/Kconfig
@@ -356,6 +356,16 @@ config USB_GSPCA_T613
To compile this driver as a module, choose M here: the
module will be called gspca_t613.
+config USB_GSPCA_TOPRO
+ tristate "TOPRO USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the
+ TP6800 and TP6810 Topro chips.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_topro.
+
config USB_GSPCA_TV8532
tristate "TV8532 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
index d6364a86333a..f345f494d0f3 100644
--- a/drivers/media/video/gspca/Makefile
+++ b/drivers/media/video/gspca/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o
obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o
obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o
obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o
+obj-$(CONFIG_USB_GSPCA_TOPRO) += gspca_topro.o
obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o
obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o
obj-$(CONFIG_USB_GSPCA_VICAM) += gspca_vicam.o
@@ -78,6 +79,7 @@ gspca_stk014-objs := stk014.o
gspca_stv0680-objs := stv0680.o
gspca_sunplus-objs := sunplus.o
gspca_t613-objs := t613.o
+gspca_topro-objs := topro.o
gspca_tv8532-objs := tv8532.o
gspca_vc032x-objs := vc032x.o
gspca_vicam-objs := vicam.o
diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c
index a09c4709d613..6ae26160b81f 100644
--- a/drivers/media/video/gspca/benq.c
+++ b/drivers/media/video/gspca/benq.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "benq"
#include "gspca.h"
@@ -62,7 +64,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
0,
500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -84,20 +86,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
return 0;
}
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
- int ret;
-
- ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface,
- gspca_dev->nbalt - 1);
- if (ret < 0) {
- err("usb_set_interface failed");
- return ret;
- }
-/* reg_w(gspca_dev, 0x0003, 0x0002); */
- return 0;
-}
-
/* -- start the camera -- */
static int sd_start(struct gspca_dev *gspca_dev)
{
@@ -113,7 +101,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
for (n = 0; n < 4; n++) {
urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
if (!urb) {
- err("usb_alloc_urb failed");
+ pr_err("usb_alloc_urb failed\n");
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
@@ -123,7 +111,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
&urb->transfer_dma);
if (urb->transfer_buffer == NULL) {
- err("usb_alloc_coherent failed");
+ pr_err("usb_alloc_coherent failed\n");
return -ENOMEM;
}
urb->dev = gspca_dev->dev;
@@ -181,7 +169,7 @@ static void sd_isoc_irq(struct urb *urb)
if (gspca_dev->frozen)
return;
#endif
- err("urb status: %d", urb->status);
+ pr_err("urb status: %d\n", urb->status);
return;
}
@@ -209,7 +197,7 @@ static void sd_isoc_irq(struct urb *urb)
if (st == 0)
st = urb->iso_frame_desc[i].status;
if (st) {
- err("ISOC data error: [%d] status=%d",
+ pr_err("ISOC data error: [%d] status=%d\n",
i, st);
gspca_dev->last_packet_type = DISCARD_PACKET;
continue;
@@ -256,10 +244,10 @@ static void sd_isoc_irq(struct urb *urb)
/* resubmit the URBs */
st = usb_submit_urb(urb0, GFP_ATOMIC);
if (st < 0)
- err("usb_submit_urb(0) ret %d", st);
+ pr_err("usb_submit_urb(0) ret %d\n", st);
st = usb_submit_urb(urb, GFP_ATOMIC);
if (st < 0)
- err("usb_submit_urb() ret %d", st);
+ pr_err("usb_submit_urb() ret %d\n", st);
}
/* sub-driver description */
@@ -269,7 +257,6 @@ static const struct sd_desc sd_desc = {
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.init = sd_init,
- .isoc_init = sd_isoc_init,
.start = sd_start,
.stopN = sd_stopN,
.pkt_scan = sd_pkt_scan,
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
index 8b398493f96b..4c56dbef6d92 100644
--- a/drivers/media/video/gspca/conex.c
+++ b/drivers/media/video/gspca/conex.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "conex"
#include "gspca.h"
@@ -129,7 +131,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_r: buffer overflow");
+ pr_err("reg_r: buffer overflow\n");
return;
}
#endif
@@ -169,7 +171,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_w: buffer overflow");
+ pr_err("reg_w: buffer overflow\n");
return;
}
PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c
index f2a9451eea19..f9b86b2484b0 100644
--- a/drivers/media/video/gspca/cpia1.c
+++ b/drivers/media/video/gspca/cpia1.c
@@ -26,6 +26,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "cpia1"
#include <linux/input.h>
@@ -550,8 +552,7 @@ retry:
gspca_dev->usb_buf, databytes, 1000);
if (ret < 0)
- err("usb_control_msg %02x, error %d", command[1],
- ret);
+ pr_err("usb_control_msg %02x, error %d\n", command[1], ret);
if (ret == -EPIPE && retries > 0) {
retries--;
@@ -1279,7 +1280,7 @@ static void monitor_exposure(struct gspca_dev *gspca_dev)
cmd[7] = 0;
ret = cpia_usb_transferCmd(gspca_dev, cmd);
if (ret) {
- err("ReadVPRegs(30,4,9,8) - failed: %d", ret);
+ pr_err("ReadVPRegs(30,4,9,8) - failed: %d\n", ret);
return;
}
exp_acc = gspca_dev->usb_buf[0];
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
index 4b2c483fce6f..0357d6d461d1 100644
--- a/drivers/media/video/gspca/etoms.c
+++ b/drivers/media/video/gspca/etoms.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "etoms"
#include "gspca.h"
@@ -236,7 +238,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_r: buffer overflow");
+ pr_err("reg_r: buffer overflow\n");
return;
}
#endif
@@ -274,7 +276,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_w: buffer overflow");
+ pr_err("reg_w: buffer overflow\n");
return;
}
PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c
index 987b4b69d7ab..ea48200fd3a0 100644
--- a/drivers/media/video/gspca/finepix.c
+++ b/drivers/media/video/gspca/finepix.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "finepix"
#include "gspca.h"
@@ -182,7 +184,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* Init the device */
ret = command(gspca_dev, 0);
if (ret < 0) {
- err("init failed %d", ret);
+ pr_err("init failed %d\n", ret);
return ret;
}
@@ -194,14 +196,14 @@ static int sd_start(struct gspca_dev *gspca_dev)
FPIX_MAX_TRANSFER, &len,
FPIX_TIMEOUT);
if (ret < 0) {
- err("usb_bulk_msg failed %d", ret);
+ pr_err("usb_bulk_msg failed %d\n", ret);
return ret;
}
/* Request a frame, but don't read it */
ret = command(gspca_dev, 1);
if (ret < 0) {
- err("frame request failed %d", ret);
+ pr_err("frame request failed %d\n", ret);
return ret;
}
diff --git a/drivers/media/video/gspca/gl860/Makefile b/drivers/media/video/gspca/gl860/Makefile
index 13c9403cc87d..f511eccdfd9c 100644
--- a/drivers/media/video/gspca/gl860/Makefile
+++ b/drivers/media/video/gspca/gl860/Makefile
@@ -6,5 +6,5 @@ gspca_gl860-objs := gl860.o \
gl860-ov9655.o \
gl860-mi2020.o
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c
index e8e071aa212f..2ced3b73994f 100644
--- a/drivers/media/video/gspca/gl860/gl860.c
+++ b/drivers/media/video/gspca/gl860/gl860.c
@@ -18,6 +18,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "gspca.h"
#include "gl860.h"
@@ -572,9 +575,8 @@ int gl860_RTx(struct gspca_dev *gspca_dev,
}
if (r < 0)
- err("ctrl transfer failed %4d "
- "[p%02x r%d v%04x i%04x len%d]",
- r, pref, req, val, index, len);
+ pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
+ r, pref, req, val, index, len);
else if (len > 1 && r < len)
PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len);
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 5da4879f47f2..881e04c7ffe6 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -21,7 +21,9 @@
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define MODULE_NAME "gspca"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define GSPCA_VERSION "2.14.0"
#include <linux/init.h>
#include <linux/fs.h>
@@ -50,12 +52,10 @@
#error "DEF_NURBS too big"
#endif
-#define DRIVER_VERSION_NUMBER "2.13.0"
-
MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("GSPCA USB Camera Driver");
MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION_NUMBER);
+MODULE_VERSION(GSPCA_VERSION);
#ifdef GSPCA_DEBUG
int gspca_debug = D_ERR | D_PROBE;
@@ -148,7 +148,7 @@ static void int_irq(struct urb *urb)
if (ret == 0) {
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret < 0)
- err("Resubmit URB failed with error %i", ret);
+ pr_err("Resubmit URB failed with error %i\n", ret);
}
}
@@ -177,8 +177,8 @@ static int gspca_input_connect(struct gspca_dev *dev)
err = input_register_device(input_dev);
if (err) {
- err("Input device registration failed with error %i",
- err);
+ pr_err("Input device registration failed with error %i\n",
+ err);
input_dev->dev.parent = NULL;
input_free_device(input_dev);
} else {
@@ -323,8 +323,8 @@ static void fill_frame(struct gspca_dev *gspca_dev,
/* check the packet status and length */
st = urb->iso_frame_desc[i].status;
if (st) {
- err("ISOC data error: [%d] len=%d, status=%d",
- i, len, st);
+ pr_err("ISOC data error: [%d] len=%d, status=%d\n",
+ i, len, st);
gspca_dev->last_packet_type = DISCARD_PACKET;
continue;
}
@@ -346,7 +346,7 @@ resubmit:
/* resubmit the URB */
st = usb_submit_urb(urb, GFP_ATOMIC);
if (st < 0)
- err("usb_submit_urb() ret %d", st);
+ pr_err("usb_submit_urb() ret %d\n", st);
}
/*
@@ -400,7 +400,7 @@ resubmit:
if (gspca_dev->cam.bulk_nurbs != 0) {
st = usb_submit_urb(urb, GFP_ATOMIC);
if (st < 0)
- err("usb_submit_urb() ret %d", st);
+ pr_err("usb_submit_urb() ret %d\n", st);
}
}
@@ -464,7 +464,7 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
} else {
/* !! image is NULL only when last pkt is LAST or DISCARD
if (gspca_dev->image == NULL) {
- err("gspca_frame_add() image == NULL");
+ pr_err("gspca_frame_add() image == NULL\n");
return;
}
*/
@@ -497,19 +497,6 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
}
EXPORT_SYMBOL(gspca_frame_add);
-static int gspca_is_compressed(__u32 format)
-{
- switch (format) {
- case V4L2_PIX_FMT_MJPEG:
- case V4L2_PIX_FMT_JPEG:
- case V4L2_PIX_FMT_SPCA561:
- case V4L2_PIX_FMT_PAC207:
- case V4L2_PIX_FMT_MR97310A:
- return 1;
- }
- return 0;
-}
-
static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
enum v4l2_memory memory, unsigned int count)
{
@@ -525,7 +512,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
count = GSPCA_MAX_FRAMES - 1;
gspca_dev->frbuf = vmalloc_32(frsz * count);
if (!gspca_dev->frbuf) {
- err("frame alloc failed");
+ pr_err("frame alloc failed\n");
return -ENOMEM;
}
gspca_dev->capt_file = file;
@@ -597,7 +584,7 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
return 0;
ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
if (ret < 0)
- err("set alt 0 err %d", ret);
+ pr_err("set alt 0 err %d\n", ret);
return ret;
}
@@ -640,53 +627,104 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
return NULL;
}
+/* compute the minimum bandwidth for the current transfer */
+static u32 which_bandwidth(struct gspca_dev *gspca_dev)
+{
+ u32 bandwidth;
+ int i;
+
+ i = gspca_dev->curr_mode;
+ bandwidth = gspca_dev->cam.cam_mode[i].sizeimage;
+
+ /* if the image is compressed, estimate the mean image size */
+ if (bandwidth < gspca_dev->cam.cam_mode[i].width *
+ gspca_dev->cam.cam_mode[i].height)
+ bandwidth /= 3;
+
+ /* estimate the frame rate */
+ if (gspca_dev->sd_desc->get_streamparm) {
+ struct v4l2_streamparm parm;
+
+ parm.parm.capture.timeperframe.denominator = 15;
+ gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm);
+ bandwidth *= parm.parm.capture.timeperframe.denominator;
+ } else {
+ bandwidth *= 15; /* 15 fps */
+ }
+
+ PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth);
+ return bandwidth;
+}
+
+/* endpoint table */
+#define MAX_ALT 16
+struct ep_tb_s {
+ u32 alt;
+ u32 bandwidth;
+};
+
/*
- * look for an input (isoc or bulk) endpoint
- *
- * The endpoint is defined by the subdriver.
- * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
- * This routine may be called many times when the bandwidth is too small
- * (the bandwidth is checked on urb submit).
+ * build the table of the endpoints
+ * and compute the minimum bandwidth for the image transfer
*/
-static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
+static int build_ep_tb(struct gspca_dev *gspca_dev,
+ struct usb_interface *intf,
+ int xfer,
+ struct ep_tb_s *ep_tb)
{
- struct usb_interface *intf;
struct usb_host_endpoint *ep;
- int xfer, i, ret;
+ int i, j, nbalt, psize, found;
+ u32 bandwidth, last_bw;
- intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
- ep = NULL;
- xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
- : USB_ENDPOINT_XFER_ISOC;
- i = gspca_dev->alt; /* previous alt setting */
- if (gspca_dev->cam.reverse_alts) {
- while (++i < gspca_dev->nbalt) {
- ep = alt_xfer(&intf->altsetting[i], xfer);
- if (ep)
- break;
- }
- } else {
- while (--i >= 0) {
- ep = alt_xfer(&intf->altsetting[i], xfer);
- if (ep)
- break;
- }
- }
- if (ep == NULL) {
- err("no transfer endpoint found");
- return NULL;
- }
- PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
- i, ep->desc.bEndpointAddress);
- gspca_dev->alt = i; /* memorize the current alt setting */
- if (gspca_dev->nbalt > 1) {
- ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
- if (ret < 0) {
- err("set alt %d err %d", i, ret);
- ep = NULL;
+ nbalt = intf->num_altsetting;
+ if (nbalt > MAX_ALT)
+ nbalt = MAX_ALT; /* fixme: should warn */
+
+ /* build the endpoint table */
+ i = 0;
+ last_bw = 0;
+ for (;;) {
+ ep_tb->bandwidth = 2000 * 2000 * 120;
+ found = 0;
+ for (j = 0; j < nbalt; j++) {
+ ep = alt_xfer(&intf->altsetting[j], xfer);
+ if (ep == NULL)
+ continue;
+ psize = le16_to_cpu(ep->desc.wMaxPacketSize);
+ if (!gspca_dev->cam.bulk) /* isoc */
+ psize = (psize & 0x07ff) *
+ (1 + ((psize >> 11) & 3));
+ bandwidth = psize * ep->desc.bInterval * 1000;
+ if (gspca_dev->dev->speed == USB_SPEED_HIGH
+ || gspca_dev->dev->speed == USB_SPEED_SUPER)
+ bandwidth *= 8;
+ if (bandwidth <= last_bw)
+ continue;
+ if (bandwidth < ep_tb->bandwidth) {
+ ep_tb->bandwidth = bandwidth;
+ ep_tb->alt = j;
+ found = 1;
+ }
}
+ if (!found)
+ break;
+ PDEBUG(D_STREAM, "alt %d bandwidth %d",
+ ep_tb->alt, ep_tb->bandwidth);
+ last_bw = ep_tb->bandwidth;
+ i++;
+ ep_tb++;
+ }
+
+ /* get the requested bandwidth and start at the highest atlsetting */
+ bandwidth = which_bandwidth(gspca_dev);
+ ep_tb--;
+ while (i > 1) {
+ ep_tb--;
+ if (ep_tb->bandwidth < bandwidth)
+ break;
+ i--;
}
- return ep;
+ return i;
}
/*
@@ -731,7 +769,7 @@ static int create_urbs(struct gspca_dev *gspca_dev,
for (n = 0; n < nurbs; n++) {
urb = usb_alloc_urb(npkt, GFP_KERNEL);
if (!urb) {
- err("usb_alloc_urb failed");
+ pr_err("usb_alloc_urb failed\n");
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
@@ -741,7 +779,7 @@ static int create_urbs(struct gspca_dev *gspca_dev,
&urb->transfer_dma);
if (urb->transfer_buffer == NULL) {
- err("usb_alloc_coherent failed");
+ pr_err("usb_alloc_coherent failed\n");
return -ENOMEM;
}
urb->dev = gspca_dev->dev;
@@ -752,7 +790,10 @@ static int create_urbs(struct gspca_dev *gspca_dev,
ep->desc.bEndpointAddress);
urb->transfer_flags = URB_ISO_ASAP
| URB_NO_TRANSFER_DMA_MAP;
- urb->interval = ep->desc.bInterval;
+ if (gspca_dev->dev->speed == USB_SPEED_LOW)
+ urb->interval = ep->desc.bInterval;
+ else
+ urb->interval = 1 << (ep->desc.bInterval - 1);
urb->complete = isoc_irq;
urb->number_of_packets = npkt;
for (i = 0; i < npkt; i++) {
@@ -774,9 +815,11 @@ static int create_urbs(struct gspca_dev *gspca_dev,
*/
static int gspca_init_transfer(struct gspca_dev *gspca_dev)
{
+ struct usb_interface *intf;
struct usb_host_endpoint *ep;
struct urb *urb;
- int n, ret;
+ struct ep_tb_s ep_tb[MAX_ALT];
+ int n, ret, xfer, alt, alt_idx;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
@@ -794,30 +837,65 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
gspca_dev->usb_err = 0;
- /* set the higher alternate setting and
- * loop until urb submit succeeds */
- if (gspca_dev->cam.reverse_alts)
- gspca_dev->alt = 0;
- else
- gspca_dev->alt = gspca_dev->nbalt;
-
+ /* do the specific subdriver stuff before endpoint selection */
+ gspca_dev->alt = 0;
if (gspca_dev->sd_desc->isoc_init) {
ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
if (ret < 0)
goto unlock;
}
+ intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+ xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
+ : USB_ENDPOINT_XFER_ISOC;
- gspca_input_destroy_urb(gspca_dev);
- ep = get_ep(gspca_dev);
- if (ep == NULL) {
- ret = -EIO;
- goto out;
+ /* if the subdriver forced an altsetting, get the endpoint */
+ if (gspca_dev->alt != 0) {
+ gspca_dev->alt--; /* (previous version compatibility) */
+ ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
+ if (ep == NULL) {
+ pr_err("bad altsetting %d\n", gspca_dev->alt);
+ ret = -EIO;
+ goto out;
+ }
+ ep_tb[0].alt = gspca_dev->alt;
+ alt_idx = 1;
+ } else {
+
+ /* else, compute the minimum bandwidth
+ * and build the endpoint table */
+ alt_idx = build_ep_tb(gspca_dev, intf, xfer, ep_tb);
+ if (alt_idx <= 0) {
+ pr_err("no transfer endpoint found\n");
+ ret = -EIO;
+ goto unlock;
+ }
}
+
+ /* set the highest alternate setting and
+ * loop until urb submit succeeds */
+ gspca_input_destroy_urb(gspca_dev);
+
+ gspca_dev->alt = ep_tb[--alt_idx].alt;
+ alt = -1;
for (;;) {
+ if (alt != gspca_dev->alt) {
+ alt = gspca_dev->alt;
+ if (gspca_dev->nbalt > 1) {
+ ret = usb_set_interface(gspca_dev->dev,
+ gspca_dev->iface,
+ alt);
+ if (ret < 0) {
+ if (ret == -ENOSPC)
+ goto retry; /*fixme: ugly*/
+ pr_err("set alt %d err %d\n", alt, ret);
+ goto out;
+ }
+ }
+ }
if (!gspca_dev->cam.no_urb_create) {
- PDEBUG(D_STREAM, "init transfer alt %d",
- gspca_dev->alt);
- ret = create_urbs(gspca_dev, ep);
+ PDEBUG(D_STREAM, "init transfer alt %d", alt);
+ ret = create_urbs(gspca_dev,
+ alt_xfer(&intf->altsetting[alt], xfer));
if (ret < 0) {
destroy_urbs(gspca_dev);
goto out;
@@ -851,29 +929,35 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
break;
}
if (ret >= 0)
- break;
+ break; /* transfer is started */
+
+ /* something when wrong
+ * stop the webcam and free the transfer resources */
gspca_stream_off(gspca_dev);
if (ret != -ENOSPC) {
- err("usb_submit_urb alt %d err %d",
- gspca_dev->alt, ret);
+ pr_err("usb_submit_urb alt %d err %d\n",
+ gspca_dev->alt, ret);
goto out;
}
/* the bandwidth is not wide enough
* negotiate or try a lower alternate setting */
+retry:
PDEBUG(D_ERR|D_STREAM,
- "bandwidth not wide enough - trying again");
+ "alt %d - bandwidth not wide enough - trying again",
+ alt);
msleep(20); /* wait for kill complete */
if (gspca_dev->sd_desc->isoc_nego) {
ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
if (ret < 0)
goto out;
} else {
- ep = get_ep(gspca_dev);
- if (ep == NULL) {
+ if (alt_idx <= 0) {
+ pr_err("no transfer endpoint found\n");
ret = -EIO;
goto out;
}
+ alt = ep_tb[--alt_idx].alt;
}
}
out:
@@ -1044,7 +1128,9 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL; /* no more format */
fmtdesc->pixelformat = fmt_tb[index];
- if (gspca_is_compressed(fmt_tb[index]))
+ if (gspca_dev->cam.cam_mode[i].sizeimage <
+ gspca_dev->cam.cam_mode[i].width *
+ gspca_dev->cam.cam_mode[i].height)
fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
@@ -2195,19 +2281,20 @@ int gspca_dev_probe2(struct usb_interface *intf,
struct usb_device *dev = interface_to_usbdev(intf);
int ret;
- PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
+ pr_info("%s-" GSPCA_VERSION " probing %04x:%04x\n",
+ sd_desc->name, id->idVendor, id->idProduct);
/* create the device */
if (dev_size < sizeof *gspca_dev)
dev_size = sizeof *gspca_dev;
gspca_dev = kzalloc(dev_size, GFP_KERNEL);
if (!gspca_dev) {
- err("couldn't kzalloc gspca struct");
+ pr_err("couldn't kzalloc gspca struct\n");
return -ENOMEM;
}
gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
if (!gspca_dev->usb_buf) {
- err("out of memory");
+ pr_err("out of memory\n");
ret = -ENOMEM;
goto out;
}
@@ -2264,7 +2351,7 @@ int gspca_dev_probe2(struct usb_interface *intf,
VFL_TYPE_GRABBER,
-1);
if (ret < 0) {
- err("video_register_device err %d", ret);
+ pr_err("video_register_device err %d\n", ret);
goto out;
}
@@ -2296,8 +2383,8 @@ int gspca_dev_probe(struct usb_interface *intf,
/* we don't handle multi-config cameras */
if (dev->descriptor.bNumConfigurations != 1) {
- err("%04x:%04x too many config",
- id->idVendor, id->idProduct);
+ pr_err("%04x:%04x too many config\n",
+ id->idVendor, id->idProduct);
return -ENODEV;
}
@@ -2480,7 +2567,7 @@ EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
/* -- module insert / remove -- */
static int __init gspca_init(void)
{
- info("v" DRIVER_VERSION_NUMBER " registered");
+ pr_info("v" GSPCA_VERSION " registered\n");
return 0;
}
static void __exit gspca_exit(void)
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 49e2fcbe81fb..e444f16e1497 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -14,11 +14,12 @@
#ifdef GSPCA_DEBUG
/* GSPCA our debug messages */
extern int gspca_debug;
-#define PDEBUG(level, fmt, args...) \
- do {\
- if (gspca_debug & (level)) \
- printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
- } while (0)
+#define PDEBUG(level, fmt, ...) \
+do { \
+ if (gspca_debug & (level)) \
+ pr_info(fmt, ##__VA_ARGS__); \
+} while (0)
+
#define D_ERR 0x01
#define D_PROBE 0x02
#define D_CONF 0x04
@@ -29,17 +30,8 @@ extern int gspca_debug;
#define D_USBO 0x00
#define D_V4L2 0x0100
#else
-#define PDEBUG(level, fmt, args...)
+#define PDEBUG(level, fmt, ...)
#endif
-#undef err
-#define err(fmt, args...) \
- printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args)
-#undef info
-#define info(fmt, args...) \
- printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args)
-#undef warn
-#define warn(fmt, args...) \
- printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args)
#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
/* image transfers */
diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c
index 1bd9c4b542dd..8e3dabe30077 100644
--- a/drivers/media/video/gspca/jeilinj.c
+++ b/drivers/media/video/gspca/jeilinj.c
@@ -24,6 +24,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "jeilinj"
#include <linux/slab.h>
@@ -113,8 +115,8 @@ static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
usb_sndbulkpipe(gspca_dev->dev, 3),
gspca_dev->usb_buf, 2, NULL, 500);
if (retval < 0) {
- err("command write [%02x] error %d",
- gspca_dev->usb_buf[0], retval);
+ pr_err("command write [%02x] error %d\n",
+ gspca_dev->usb_buf[0], retval);
gspca_dev->usb_err = retval;
}
}
@@ -131,8 +133,8 @@ static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
gspca_dev->usb_buf, 1, NULL, 500);
response = gspca_dev->usb_buf[0];
if (retval < 0) {
- err("read command [%02x] error %d",
- gspca_dev->usb_buf[0], retval);
+ pr_err("read command [%02x] error %d\n",
+ gspca_dev->usb_buf[0], retval);
gspca_dev->usb_err = retval;
}
}
@@ -403,13 +405,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
dev->type = id->driver_info;
gspca_dev->cam.ctrls = dev->ctrls;
dev->quality = QUALITY_DEF;
- dev->ctrls[LIGHTFREQ].def = V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
- dev->ctrls[RED].def = RED_BALANCE_DEF;
- dev->ctrls[GREEN].def = GREEN_BALANCE_DEF;
- dev->ctrls[BLUE].def = BLUE_BALANCE_DEF;
- PDEBUG(D_PROBE,
- "JEILINJ camera detected"
- " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+
cam->cam_mode = jlj_mode;
cam->nmodes = ARRAY_SIZE(jlj_mode);
cam->bulk = 1;
@@ -422,7 +418,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
{
int i;
u8 *buf;
- u8 stop_commands[][2] = {
+ static u8 stop_commands[][2] = {
{0x71, 0x00},
{0x70, 0x09},
{0x71, 0x80},
diff --git a/drivers/media/video/gspca/kinect.c b/drivers/media/video/gspca/kinect.c
index 26fc206f095e..4fe51fda80f3 100644
--- a/drivers/media/video/gspca/kinect.c
+++ b/drivers/media/video/gspca/kinect.c
@@ -24,6 +24,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "kinect"
#include "gspca.h"
@@ -34,11 +36,6 @@ MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
MODULE_LICENSE("GPL");
-#ifdef GSPCA_DEBUG
-int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK |
- D_USBI | D_USBO | D_V4L2;
-#endif
-
struct pkt_hdr {
uint8_t magic[2];
uint8_t pad;
@@ -141,7 +138,7 @@ static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
struct cam_hdr *rhdr = (void *)ibuf;
if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
- err("send_cmd: Invalid command length (0x%x)", cmd_len);
+ pr_err("send_cmd: Invalid command length (0x%x)\n", cmd_len);
return -1;
}
@@ -157,7 +154,7 @@ static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd,
sd->cam_tag, cmd_len, res);
if (res < 0) {
- err("send_cmd: Output control transfer failed (%d)", res);
+ pr_err("send_cmd: Output control transfer failed (%d)\n", res);
return res;
}
@@ -166,33 +163,35 @@ static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
} while (actual_len == 0);
PDEBUG(D_USBO, "Control reply: %d", res);
if (actual_len < sizeof(*rhdr)) {
- err("send_cmd: Input control transfer failed (%d)", res);
+ pr_err("send_cmd: Input control transfer failed (%d)\n", res);
return res;
}
actual_len -= sizeof(*rhdr);
if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
- err("send_cmd: Bad magic %02x %02x", rhdr->magic[0],
- rhdr->magic[1]);
+ pr_err("send_cmd: Bad magic %02x %02x\n",
+ rhdr->magic[0], rhdr->magic[1]);
return -1;
}
if (rhdr->cmd != chdr->cmd) {
- err("send_cmd: Bad cmd %02x != %02x", rhdr->cmd, chdr->cmd);
+ pr_err("send_cmd: Bad cmd %02x != %02x\n",
+ rhdr->cmd, chdr->cmd);
return -1;
}
if (rhdr->tag != chdr->tag) {
- err("send_cmd: Bad tag %04x != %04x", rhdr->tag, chdr->tag);
+ pr_err("send_cmd: Bad tag %04x != %04x\n",
+ rhdr->tag, chdr->tag);
return -1;
}
if (cpu_to_le16(rhdr->len) != (actual_len/2)) {
- err("send_cmd: Bad len %04x != %04x",
- cpu_to_le16(rhdr->len), (int)(actual_len/2));
+ pr_err("send_cmd: Bad len %04x != %04x\n",
+ cpu_to_le16(rhdr->len), (int)(actual_len/2));
return -1;
}
if (actual_len > reply_len) {
- warn("send_cmd: Data buffer is %d bytes long, but got %d bytes",
- reply_len, actual_len);
+ pr_warn("send_cmd: Data buffer is %d bytes long, but got %d bytes\n",
+ reply_len, actual_len);
memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
} else {
memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
@@ -218,8 +217,8 @@ static int write_register(struct gspca_dev *gspca_dev, uint16_t reg,
if (res < 0)
return res;
if (res != 2) {
- warn("send_cmd returned %d [%04x %04x], 0000 expected",
- res, reply[0], reply[1]);
+ pr_warn("send_cmd returned %d [%04x %04x], 0000 expected\n",
+ res, reply[0], reply[1]);
}
return 0;
}
@@ -353,8 +352,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
return;
if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
- warn("[Stream %02x] Invalid magic %02x%02x", sd->stream_flag,
- hdr->magic[0], hdr->magic[1]);
+ pr_warn("[Stream %02x] Invalid magic %02x%02x\n",
+ sd->stream_flag, hdr->magic[0], hdr->magic[1]);
return;
}
@@ -368,7 +367,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen);
else
- warn("Packet type not recognized...");
+ pr_warn("Packet type not recognized...\n");
}
/* sub-driver description */
diff --git a/drivers/media/video/gspca/konica.c b/drivers/media/video/gspca/konica.c
index 5964691c0e95..f3f7fe0ec4b7 100644
--- a/drivers/media/video/gspca/konica.c
+++ b/drivers/media/video/gspca/konica.c
@@ -28,6 +28,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "konica"
#include <linux/input.h>
@@ -200,7 +202,7 @@ static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
0,
1000);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -221,7 +223,7 @@ static void reg_r(struct gspca_dev *gspca_dev, u16 value, u16 index)
2,
1000);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -284,7 +286,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
if (!alt) {
- err("Couldn't get altsetting");
+ pr_err("Couldn't get altsetting\n");
return -EIO;
}
@@ -315,7 +317,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
le16_to_cpu(alt->endpoint[i].desc.wMaxPacketSize);
urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
if (!urb) {
- err("usb_alloc_urb failed");
+ pr_err("usb_alloc_urb failed\n");
return -ENOMEM;
}
gspca_dev->urb[n] = urb;
@@ -324,7 +326,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
GFP_KERNEL,
&urb->transfer_dma);
if (urb->transfer_buffer == NULL) {
- err("usb_buffer_alloc failed");
+ pr_err("usb_buffer_alloc failed\n");
return -ENOMEM;
}
@@ -386,7 +388,7 @@ static void sd_isoc_irq(struct urb *urb)
PDEBUG(D_ERR, "urb status: %d", urb->status);
st = usb_submit_urb(urb, GFP_ATOMIC);
if (st < 0)
- err("resubmit urb error %d", st);
+ pr_err("resubmit urb error %d\n", st);
return;
}
@@ -477,7 +479,7 @@ resubmit:
}
st = usb_submit_urb(status_urb, GFP_ATOMIC);
if (st < 0)
- err("usb_submit_urb(status_urb) ret %d", st);
+ pr_err("usb_submit_urb(status_urb) ret %d\n", st);
}
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile
index bf7a19a1e6d1..7f52961f439c 100644
--- a/drivers/media/video/gspca/m5602/Makefile
+++ b/drivers/media/video/gspca/m5602/Makefile
@@ -8,4 +8,4 @@ gspca_m5602-objs := m5602_core.o \
m5602_s5k83a.o \
m5602_s5k4aa.o
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
index a7722b1aef9b..67533e5582a6 100644
--- a/drivers/media/video/gspca/m5602/m5602_core.c
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_ov9650.h"
#include "m5602_ov7660.h"
#include "m5602_mt9m111.h"
@@ -192,10 +194,9 @@ static void m5602_dump_bridge(struct sd *sd)
for (i = 0; i < 0x80; i++) {
unsigned char val = 0;
m5602_read_bridge(sd, i, &val);
- info("ALi m5602 address 0x%x contains 0x%x", i, val);
+ pr_info("ALi m5602 address 0x%x contains 0x%x\n", i, val);
}
- info("Warning: The ALi m5602 webcam probably won't work "
- "until it's power cycled");
+ pr_info("Warning: The ALi m5602 webcam probably won't work until it's power cycled\n");
}
static int m5602_probe_sensor(struct sd *sd)
@@ -231,7 +232,7 @@ static int m5602_probe_sensor(struct sd *sd)
return 0;
/* More sensor probe function goes here */
- info("Failed to find a sensor");
+ pr_info("Failed to find a sensor\n");
sd->sensor = NULL;
return -ENODEV;
}
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
index 0d605a52b924..6268aa24ec5d 100644
--- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_mt9m111.h"
static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
@@ -163,7 +165,7 @@ int mt9m111_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == MT9M111_SENSOR) {
- info("Forcing a %s sensor", mt9m111.name);
+ pr_info("Forcing a %s sensor\n", mt9m111.name);
goto sensor_found;
}
/* If we want to force another sensor, don't try to probe this
@@ -191,7 +193,7 @@ int mt9m111_probe(struct sd *sd)
return -ENODEV;
if ((data[0] == 0x14) && (data[1] == 0x3a)) {
- info("Detected a mt9m111 sensor");
+ pr_info("Detected a mt9m111 sensor\n");
goto sensor_found;
}
@@ -612,34 +614,34 @@ static void mt9m111_dump_registers(struct sd *sd)
{
u8 address, value[2] = {0x00, 0x00};
- info("Dumping the mt9m111 register state");
+ pr_info("Dumping the mt9m111 register state\n");
- info("Dumping the mt9m111 sensor core registers");
+ pr_info("Dumping the mt9m111 sensor core registers\n");
value[1] = MT9M111_SENSOR_CORE;
m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
for (address = 0; address < 0xff; address++) {
m5602_read_sensor(sd, address, value, 2);
- info("register 0x%x contains 0x%x%x",
- address, value[0], value[1]);
+ pr_info("register 0x%x contains 0x%x%x\n",
+ address, value[0], value[1]);
}
- info("Dumping the mt9m111 color pipeline registers");
+ pr_info("Dumping the mt9m111 color pipeline registers\n");
value[1] = MT9M111_COLORPIPE;
m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
for (address = 0; address < 0xff; address++) {
m5602_read_sensor(sd, address, value, 2);
- info("register 0x%x contains 0x%x%x",
- address, value[0], value[1]);
+ pr_info("register 0x%x contains 0x%x%x\n",
+ address, value[0], value[1]);
}
- info("Dumping the mt9m111 camera control registers");
+ pr_info("Dumping the mt9m111 camera control registers\n");
value[1] = MT9M111_CAMERA_CONTROL;
m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
for (address = 0; address < 0xff; address++) {
m5602_read_sensor(sd, address, value, 2);
- info("register 0x%x contains 0x%x%x",
- address, value[0], value[1]);
+ pr_info("register 0x%x contains 0x%x%x\n",
+ address, value[0], value[1]);
}
- info("mt9m111 register state dump complete");
+ pr_info("mt9m111 register state dump complete\n");
}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.c b/drivers/media/video/gspca/m5602/m5602_ov7660.c
index b12f60464b3b..9a14835c128f 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov7660.c
+++ b/drivers/media/video/gspca/m5602/m5602_ov7660.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_ov7660.h"
static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
@@ -149,7 +151,7 @@ int ov7660_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == OV7660_SENSOR) {
- info("Forcing an %s sensor", ov7660.name);
+ pr_info("Forcing an %s sensor\n", ov7660.name);
goto sensor_found;
}
/* If we want to force another sensor,
@@ -180,10 +182,10 @@ int ov7660_probe(struct sd *sd)
if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
return -ENODEV;
- info("Sensor reported 0x%x%x", prod_id, ver_id);
+ pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id);
if ((prod_id == 0x76) && (ver_id == 0x60)) {
- info("Detected a ov7660 sensor");
+ pr_info("Detected a ov7660 sensor\n");
goto sensor_found;
}
return -ENODEV;
@@ -457,17 +459,16 @@ static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
static void ov7660_dump_registers(struct sd *sd)
{
int address;
- info("Dumping the ov7660 register state");
+ pr_info("Dumping the ov7660 register state\n");
for (address = 0; address < 0xa9; address++) {
u8 value;
m5602_read_sensor(sd, address, &value, 1);
- info("register 0x%x contains 0x%x",
- address, value);
+ pr_info("register 0x%x contains 0x%x\n", address, value);
}
- info("ov7660 register state dump complete");
+ pr_info("ov7660 register state dump complete\n");
- info("Probing for which registers that are read/write");
+ pr_info("Probing for which registers that are read/write\n");
for (address = 0; address < 0xff; address++) {
u8 old_value, ctrl_value;
u8 test_value[2] = {0xff, 0xff};
@@ -477,9 +478,9 @@ static void ov7660_dump_registers(struct sd *sd)
m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value[0])
- info("register 0x%x is writeable", address);
+ pr_info("register 0x%x is writeable\n", address);
else
- info("register 0x%x is read only", address);
+ pr_info("register 0x%x is read only\n", address);
/* Restore original value */
m5602_write_sensor(sd, address, &old_value, 1);
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
index 703d48670a24..2114a8b90ec9 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.c
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_ov9650.h"
static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
@@ -299,7 +301,7 @@ int ov9650_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == OV9650_SENSOR) {
- info("Forcing an %s sensor", ov9650.name);
+ pr_info("Forcing an %s sensor\n", ov9650.name);
goto sensor_found;
}
/* If we want to force another sensor,
@@ -330,7 +332,7 @@ int ov9650_probe(struct sd *sd)
return -ENODEV;
if ((prod_id == 0x96) && (ver_id == 0x52)) {
- info("Detected an ov9650 sensor");
+ pr_info("Detected an ov9650 sensor\n");
goto sensor_found;
}
return -ENODEV;
@@ -850,17 +852,16 @@ static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
static void ov9650_dump_registers(struct sd *sd)
{
int address;
- info("Dumping the ov9650 register state");
+ pr_info("Dumping the ov9650 register state\n");
for (address = 0; address < 0xa9; address++) {
u8 value;
m5602_read_sensor(sd, address, &value, 1);
- info("register 0x%x contains 0x%x",
- address, value);
+ pr_info("register 0x%x contains 0x%x\n", address, value);
}
- info("ov9650 register state dump complete");
+ pr_info("ov9650 register state dump complete\n");
- info("Probing for which registers that are read/write");
+ pr_info("Probing for which registers that are read/write\n");
for (address = 0; address < 0xff; address++) {
u8 old_value, ctrl_value;
u8 test_value[2] = {0xff, 0xff};
@@ -870,9 +871,9 @@ static void ov9650_dump_registers(struct sd *sd)
m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value[0])
- info("register 0x%x is writeable", address);
+ pr_info("register 0x%x is writeable\n", address);
else
- info("register 0x%x is read only", address);
+ pr_info("register 0x%x is read only\n", address);
/* Restore original value */
m5602_write_sensor(sd, address, &old_value, 1);
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c
index 1febd34c2f05..b8771698cbcb 100644
--- a/drivers/media/video/gspca/m5602/m5602_po1030.c
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_po1030.h"
static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
@@ -197,7 +199,7 @@ int po1030_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == PO1030_SENSOR) {
- info("Forcing a %s sensor", po1030.name);
+ pr_info("Forcing a %s sensor\n", po1030.name);
goto sensor_found;
}
/* If we want to force another sensor, don't try to probe this
@@ -221,7 +223,7 @@ int po1030_probe(struct sd *sd)
return -ENODEV;
if (dev_id_h == 0x30) {
- info("Detected a po1030 sensor");
+ pr_info("Detected a po1030 sensor\n");
goto sensor_found;
}
return -ENODEV;
@@ -267,7 +269,7 @@ int po1030_init(struct sd *sd)
break;
default:
- info("Invalid stream command, exiting init");
+ pr_info("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -733,16 +735,15 @@ static void po1030_dump_registers(struct sd *sd)
int address;
u8 value = 0;
- info("Dumping the po1030 sensor core registers");
+ pr_info("Dumping the po1030 sensor core registers\n");
for (address = 0; address < 0x7f; address++) {
m5602_read_sensor(sd, address, &value, 1);
- info("register 0x%x contains 0x%x",
- address, value);
+ pr_info("register 0x%x contains 0x%x\n", address, value);
}
- info("po1030 register state dump complete");
+ pr_info("po1030 register state dump complete\n");
- info("Probing for which registers that are read/write");
+ pr_info("Probing for which registers that are read/write\n");
for (address = 0; address < 0xff; address++) {
u8 old_value, ctrl_value;
u8 test_value[2] = {0xff, 0xff};
@@ -752,9 +753,9 @@ static void po1030_dump_registers(struct sd *sd)
m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value[0])
- info("register 0x%x is writeable", address);
+ pr_info("register 0x%x is writeable\n", address);
else
- info("register 0x%x is read only", address);
+ pr_info("register 0x%x is read only\n", address);
/* Restore original value */
m5602_write_sensor(sd, address, &old_value, 1);
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
index d27280be9852..cc8ec3f7e8dc 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "m5602_s5k4aa.h"
static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
@@ -240,7 +242,7 @@ int s5k4aa_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == S5K4AA_SENSOR) {
- info("Forcing a %s sensor", s5k4aa.name);
+ pr_info("Forcing a %s sensor\n", s5k4aa.name);
goto sensor_found;
}
/* If we want to force another sensor, don't try to probe this
@@ -276,7 +278,7 @@ int s5k4aa_probe(struct sd *sd)
data, 2);
break;
default:
- info("Invalid stream command, exiting init");
+ pr_info("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -292,7 +294,7 @@ int s5k4aa_probe(struct sd *sd)
if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
return -ENODEV;
else
- info("Detected a s5k4aa sensor");
+ pr_info("Detected a s5k4aa sensor\n");
sensor_found:
sensor_settings = kmalloc(
@@ -347,7 +349,7 @@ int s5k4aa_start(struct sd *sd)
break;
default:
- err("Invalid stream command, exiting init");
+ pr_err("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -383,7 +385,7 @@ int s5k4aa_start(struct sd *sd)
break;
default:
- err("Invalid stream command, exiting init");
+ pr_err("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -447,7 +449,7 @@ int s5k4aa_init(struct sd *sd)
init_s5k4aa[i][1], data, 2);
break;
default:
- info("Invalid stream command, exiting init");
+ pr_info("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -686,20 +688,21 @@ static void s5k4aa_dump_registers(struct sd *sd)
m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
for (page = 0; page < 16; page++) {
m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
- info("Dumping the s5k4aa register state for page 0x%x", page);
+ pr_info("Dumping the s5k4aa register state for page 0x%x\n",
+ page);
for (address = 0; address <= 0xff; address++) {
u8 value = 0;
m5602_read_sensor(sd, address, &value, 1);
- info("register 0x%x contains 0x%x",
- address, value);
+ pr_info("register 0x%x contains 0x%x\n",
+ address, value);
}
}
- info("s5k4aa register state dump complete");
+ pr_info("s5k4aa register state dump complete\n");
for (page = 0; page < 16; page++) {
m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
- info("Probing for which registers that are "
- "read/write for page 0x%x", page);
+ pr_info("Probing for which registers that are read/write for page 0x%x\n",
+ page);
for (address = 0; address <= 0xff; address++) {
u8 old_value, ctrl_value, test_value = 0xff;
@@ -708,14 +711,16 @@ static void s5k4aa_dump_registers(struct sd *sd)
m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value)
- info("register 0x%x is writeable", address);
+ pr_info("register 0x%x is writeable\n",
+ address);
else
- info("register 0x%x is read only", address);
+ pr_info("register 0x%x is read only\n",
+ address);
/* Restore original value */
m5602_write_sensor(sd, address, &old_value, 1);
}
}
- info("Read/write register probing complete");
+ pr_info("Read/write register probing complete\n");
m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
index fbd91545497a..1de743a02b02 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
@@ -16,6 +16,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kthread.h>
#include "m5602_s5k83a.h"
@@ -135,7 +137,7 @@ int s5k83a_probe(struct sd *sd)
if (force_sensor) {
if (force_sensor == S5K83A_SENSOR) {
- info("Forcing a %s sensor", s5k83a.name);
+ pr_info("Forcing a %s sensor\n", s5k83a.name);
goto sensor_found;
}
/* If we want to force another sensor, don't try to probe this
@@ -168,7 +170,7 @@ int s5k83a_probe(struct sd *sd)
if ((prod_id == 0xff) || (ver_id == 0xff))
return -ENODEV;
else
- info("Detected a s5k83a sensor");
+ pr_info("Detected a s5k83a sensor\n");
sensor_found:
sens_priv = kmalloc(
@@ -227,7 +229,7 @@ int s5k83a_init(struct sd *sd)
init_s5k83a[i][1], data, 2);
break;
default:
- info("Invalid stream command, exiting init");
+ pr_info("Invalid stream command, exiting init\n");
return -EINVAL;
}
}
@@ -273,7 +275,7 @@ static int rotation_thread_function(void *data)
s5k83a_get_rotation(sd, &reg);
if (previous_rotation != reg) {
previous_rotation = reg;
- info("Camera was flipped");
+ pr_info("Camera was flipped\n");
s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
@@ -566,20 +568,20 @@ static void s5k83a_dump_registers(struct sd *sd)
for (page = 0; page < 16; page++) {
m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
- info("Dumping the s5k83a register state for page 0x%x", page);
+ pr_info("Dumping the s5k83a register state for page 0x%x\n",
+ page);
for (address = 0; address <= 0xff; address++) {
u8 val = 0;
m5602_read_sensor(sd, address, &val, 1);
- info("register 0x%x contains 0x%x",
- address, val);
+ pr_info("register 0x%x contains 0x%x\n", address, val);
}
}
- info("s5k83a register state dump complete");
+ pr_info("s5k83a register state dump complete\n");
for (page = 0; page < 16; page++) {
m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
- info("Probing for which registers that are read/write "
- "for page 0x%x", page);
+ pr_info("Probing for which registers that are read/write for page 0x%x\n",
+ page);
for (address = 0; address <= 0xff; address++) {
u8 old_val, ctrl_val, test_val = 0xff;
@@ -588,14 +590,16 @@ static void s5k83a_dump_registers(struct sd *sd)
m5602_read_sensor(sd, address, &ctrl_val, 1);
if (ctrl_val == test_val)
- info("register 0x%x is writeable", address);
+ pr_info("register 0x%x is writeable\n",
+ address);
else
- info("register 0x%x is read only", address);
+ pr_info("register 0x%x is read only\n",
+ address);
/* Restore original val */
m5602_write_sensor(sd, address, &old_val, 1);
}
}
- info("Read/write register probing complete");
+ pr_info("Read/write register probing complete\n");
m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
}
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
index 0196209a948a..ef45fa575752 100644
--- a/drivers/media/video/gspca/mars.c
+++ b/drivers/media/video/gspca/mars.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "mars"
#include "gspca.h"
@@ -178,8 +180,8 @@ static void reg_w(struct gspca_dev *gspca_dev,
&alen,
500); /* timeout in milliseconds */
if (ret < 0) {
- err("reg write [%02x] error %d",
- gspca_dev->usb_buf[0], ret);
+ pr_err("reg write [%02x] error %d\n",
+ gspca_dev->usb_buf[0], ret);
gspca_dev->usb_err = ret;
}
}
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
index 97e507967434..473e813b680e 100644
--- a/drivers/media/video/gspca/mr97310a.c
+++ b/drivers/media/video/gspca/mr97310a.c
@@ -40,6 +40,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "mr97310a"
#include "gspca.h"
@@ -267,7 +269,7 @@ static int mr_write(struct gspca_dev *gspca_dev, int len)
usb_sndbulkpipe(gspca_dev->dev, 4),
gspca_dev->usb_buf, len, NULL, 500);
if (rc < 0)
- err("reg write [%02x] error %d",
+ pr_err("reg write [%02x] error %d\n",
gspca_dev->usb_buf[0], rc);
return rc;
}
@@ -281,7 +283,7 @@ static int mr_read(struct gspca_dev *gspca_dev, int len)
usb_rcvbulkpipe(gspca_dev->dev, 3),
gspca_dev->usb_buf, len, NULL, 500);
if (rc < 0)
- err("reg read [%02x] error %d",
+ pr_err("reg read [%02x] error %d\n",
gspca_dev->usb_buf[0], rc);
return rc;
}
@@ -540,7 +542,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->sensor_type = 1;
break;
default:
- err("Unknown CIF Sensor id : %02x",
+ pr_err("Unknown CIF Sensor id : %02x\n",
gspca_dev->usb_buf[1]);
return -ENODEV;
}
@@ -575,10 +577,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->sensor_type = 2;
} else if ((gspca_dev->usb_buf[0] != 0x03) &&
(gspca_dev->usb_buf[0] != 0x04)) {
- err("Unknown VGA Sensor id Byte 0: %02x",
- gspca_dev->usb_buf[0]);
- err("Defaults assumed, may not work");
- err("Please report this");
+ pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
+ gspca_dev->usb_buf[0]);
+ pr_err("Defaults assumed, may not work\n");
+ pr_err("Please report this\n");
}
/* Sakar Digital color needs to be adjusted. */
if ((gspca_dev->usb_buf[0] == 0x03) &&
@@ -595,10 +597,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
/* Nothing to do here. */
break;
default:
- err("Unknown VGA Sensor id Byte 1: %02x",
- gspca_dev->usb_buf[1]);
- err("Defaults assumed, may not work");
- err("Please report this");
+ pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
+ gspca_dev->usb_buf[1]);
+ pr_err("Defaults assumed, may not work\n");
+ pr_err("Please report this\n");
}
}
PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
diff --git a/drivers/media/video/gspca/nw80x.c b/drivers/media/video/gspca/nw80x.c
index 8e754fd4dc5e..7681814e594f 100644
--- a/drivers/media/video/gspca/nw80x.c
+++ b/drivers/media/video/gspca/nw80x.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "nw80x"
#include "gspca.h"
@@ -1571,7 +1573,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
len,
500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1592,7 +1594,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
0x00, index,
gspca_dev->usb_buf, len, 500);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
return;
}
@@ -1802,7 +1804,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
}
}
if (webcam_chip[sd->webcam] != sd->bridge) {
- err("Bad webcam type %d for NW80%d", sd->webcam, sd->bridge);
+ pr_err("Bad webcam type %d for NW80%d\n",
+ sd->webcam, sd->bridge);
gspca_dev->usb_err = -ENODEV;
return gspca_dev->usb_err;
}
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 18305c89083c..6a01b35a9478 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -36,6 +36,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "ov519"
#include <linux/input.h>
@@ -2171,7 +2174,7 @@ static void reg_w(struct sd *sd, u16 index, u16 value)
sd->gspca_dev.usb_buf, 1, 500);
leave:
if (ret < 0) {
- err("reg_w %02x failed %d", index, ret);
+ pr_err("reg_w %02x failed %d\n", index, ret);
sd->gspca_dev.usb_err = ret;
return;
}
@@ -2210,7 +2213,7 @@ static int reg_r(struct sd *sd, u16 index)
PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
req, index, ret);
} else {
- err("reg_r %02x failed %d", index, ret);
+ pr_err("reg_r %02x failed %d\n", index, ret);
sd->gspca_dev.usb_err = ret;
}
@@ -2235,7 +2238,7 @@ static int reg_r8(struct sd *sd,
if (ret >= 0) {
ret = sd->gspca_dev.usb_buf[0];
} else {
- err("reg_r8 %02x failed %d", index, ret);
+ pr_err("reg_r8 %02x failed %d\n", index, ret);
sd->gspca_dev.usb_err = ret;
}
@@ -2288,7 +2291,7 @@ static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
0, index,
sd->gspca_dev.usb_buf, n, 500);
if (ret < 0) {
- err("reg_w32 %02x failed %d", index, ret);
+ pr_err("reg_w32 %02x failed %d\n", index, ret);
sd->gspca_dev.usb_err = ret;
}
}
@@ -2457,7 +2460,7 @@ static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
(u16) value, (u16) reg, NULL, 0, 500);
if (ret < 0) {
- err("ovfx2_i2c_w %02x failed %d", reg, ret);
+ pr_err("ovfx2_i2c_w %02x failed %d\n", reg, ret);
sd->gspca_dev.usb_err = ret;
}
@@ -2481,7 +2484,7 @@ static int ovfx2_i2c_r(struct sd *sd, u8 reg)
ret = sd->gspca_dev.usb_buf[0];
PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
} else {
- err("ovfx2_i2c_r %02x failed %d", reg, ret);
+ pr_err("ovfx2_i2c_r %02x failed %d\n", reg, ret);
sd->gspca_dev.usb_err = ret;
}
@@ -2727,7 +2730,7 @@ static void ov_hires_configure(struct sd *sd)
int high, low;
if (sd->bridge != BRIDGE_OVFX2) {
- err("error hires sensors only supported with ovfx2");
+ pr_err("error hires sensors only supported with ovfx2\n");
return;
}
@@ -2762,7 +2765,7 @@ static void ov_hires_configure(struct sd *sd)
}
break;
}
- err("Error unknown sensor type: %02x%02x", high, low);
+ pr_err("Error unknown sensor type: %02x%02x\n", high, low);
}
/* This initializes the OV8110, OV8610 sensor. The OV8110 uses
@@ -2783,7 +2786,7 @@ static void ov8xx0_configure(struct sd *sd)
if ((rc & 3) == 1)
sd->sensor = SEN_OV8610;
else
- err("Unknown image sensor version: %d", rc & 3);
+ pr_err("Unknown image sensor version: %d\n", rc & 3);
}
/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
@@ -2840,8 +2843,8 @@ static void ov7xx0_configure(struct sd *sd)
if (high == 0x76) {
switch (low) {
case 0x30:
- err("Sensor is an OV7630/OV7635");
- err("7630 is not supported by this driver");
+ pr_err("Sensor is an OV7630/OV7635\n");
+ pr_err("7630 is not supported by this driver\n");
return;
case 0x40:
PDEBUG(D_PROBE, "Sensor is an OV7645");
@@ -2868,7 +2871,7 @@ static void ov7xx0_configure(struct sd *sd)
sd->sensor = SEN_OV7620;
}
} else {
- err("Unknown image sensor version: %d", rc & 3);
+ pr_err("Unknown image sensor version: %d\n", rc & 3);
}
}
@@ -2891,8 +2894,7 @@ static void ov6xx0_configure(struct sd *sd)
switch (rc) {
case 0x00:
sd->sensor = SEN_OV6630;
- warn("WARNING: Sensor is an OV66308. Your camera may have");
- warn("been misdetected in previous driver versions.");
+ pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n");
break;
case 0x01:
sd->sensor = SEN_OV6620;
@@ -2908,11 +2910,10 @@ static void ov6xx0_configure(struct sd *sd)
break;
case 0x90:
sd->sensor = SEN_OV6630;
- warn("WARNING: Sensor is an OV66307. Your camera may have");
- warn("been misdetected in previous driver versions.");
+ pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n");
break;
default:
- err("FATAL: Unknown sensor version: 0x%02x", rc);
+ pr_err("FATAL: Unknown sensor version: 0x%02x\n", rc);
return;
}
@@ -3405,7 +3406,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
} else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
ov_hires_configure(sd);
} else {
- err("Can't determine sensor slave IDs");
+ pr_err("Can't determine sensor slave IDs\n");
goto error;
}
@@ -3590,7 +3591,7 @@ static void ov511_mode_init_regs(struct sd *sd)
intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
if (!alt) {
- err("Couldn't get altsetting");
+ pr_err("Couldn't get altsetting\n");
sd->gspca_dev.usb_err = -EIO;
return;
}
@@ -3713,7 +3714,7 @@ static void ov518_mode_init_regs(struct sd *sd)
intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
if (!alt) {
- err("Couldn't get altsetting");
+ pr_err("Couldn't get altsetting\n");
sd->gspca_dev.usb_err = -EIO;
return;
}
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c
index 0c6369b7fe18..76907eced4a1 100644
--- a/drivers/media/video/gspca/ov534.c
+++ b/drivers/media/video/gspca/ov534.c
@@ -28,6 +28,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "ov534"
#include "gspca.h"
@@ -775,7 +777,7 @@ static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
if (ret < 0) {
- err("write failed %d", ret);
+ pr_err("write failed %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -794,7 +796,7 @@ static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
if (ret < 0) {
- err("read failed %d", ret);
+ pr_err("read failed %d\n", ret);
gspca_dev->usb_err = ret;
}
return gspca_dev->usb_buf[0];
@@ -858,7 +860,7 @@ static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
if (!sccb_check_status(gspca_dev)) {
- err("sccb_reg_write failed");
+ pr_err("sccb_reg_write failed\n");
gspca_dev->usb_err = -EIO;
}
}
@@ -868,11 +870,11 @@ static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
if (!sccb_check_status(gspca_dev))
- err("sccb_reg_read failed 1");
+ pr_err("sccb_reg_read failed 1\n");
ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
if (!sccb_check_status(gspca_dev))
- err("sccb_reg_read failed 2");
+ pr_err("sccb_reg_read failed 2\n");
return ov534_reg_read(gspca_dev, OV534_REG_READ);
}
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c
index aaf5428c57f5..b3b1ea60a841 100644
--- a/drivers/media/video/gspca/ov534_9.c
+++ b/drivers/media/video/gspca/ov534_9.c
@@ -1,7 +1,7 @@
/*
- * ov534-ov965x gspca driver
+ * ov534-ov9xxx gspca driver
*
- * Copyright (C) 2009-2010 Jean-Francois Moine http://moinejf.free.fr
+ * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr
* Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
* Copyright (C) 2008 Jim Paris <jim@jtan.com>
*
@@ -24,6 +24,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "ov534_9"
#include "gspca.h"
@@ -45,39 +47,44 @@ MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
MODULE_LICENSE("GPL");
+/* controls */
+enum e_ctrl {
+ BRIGHTNESS,
+ CONTRAST,
+ AUTOGAIN,
+ EXPOSURE,
+ SHARPNESS,
+ SATUR,
+ LIGHTFREQ,
+ NCTRLS /* number of controls */
+};
+
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
+ struct gspca_ctrl ctrls[NCTRLS];
__u32 last_pts;
u8 last_fid;
- u8 brightness;
- u8 contrast;
- u8 autogain;
- u8 exposure;
- s8 sharpness;
- u8 satur;
- u8 freq;
+ u8 sensor;
+};
+enum sensors {
+ SENSOR_OV965x, /* ov9657 */
+ SENSOR_OV971x, /* ov9712 */
+ NSENSORS
};
/* V4L2 controls supported by the driver */
-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
-
-static const struct ctrl sd_ctrls[] = {
- { /* 0 */
+static void setbrightness(struct gspca_dev *gspca_dev);
+static void setcontrast(struct gspca_dev *gspca_dev);
+static void setautogain(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
+static void setsharpness(struct gspca_dev *gspca_dev);
+static void setsatur(struct gspca_dev *gspca_dev);
+static void setlightfreq(struct gspca_dev *gspca_dev);
+
+static const struct ctrl sd_ctrls[NCTRLS] = {
+[BRIGHTNESS] = {
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -85,13 +92,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 15,
.step = 1,
-#define BRIGHTNESS_DEF 7
- .default_value = BRIGHTNESS_DEF,
+ .default_value = 7
},
- .set = sd_setbrightness,
- .get = sd_getbrightness,
+ .set_control = setbrightness
},
- { /* 1 */
+[CONTRAST] = {
{
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -99,13 +104,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 15,
.step = 1,
-#define CONTRAST_DEF 3
- .default_value = CONTRAST_DEF,
+ .default_value = 3
},
- .set = sd_setcontrast,
- .get = sd_getcontrast,
+ .set_control = setcontrast
},
- { /* 2 */
+[AUTOGAIN] = {
{
.id = V4L2_CID_AUTOGAIN,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -116,11 +119,9 @@ static const struct ctrl sd_ctrls[] = {
#define AUTOGAIN_DEF 1
.default_value = AUTOGAIN_DEF,
},
- .set = sd_setautogain,
- .get = sd_getautogain,
+ .set_control = setautogain
},
-#define EXPO_IDX 3
- { /* 3 */
+[EXPOSURE] = {
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -128,13 +129,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 3,
.step = 1,
-#define EXPO_DEF 0
- .default_value = EXPO_DEF,
+ .default_value = 0
},
- .set = sd_setexposure,
- .get = sd_getexposure,
+ .set_control = setexposure
},
- { /* 4 */
+[SHARPNESS] = {
{
.id = V4L2_CID_SHARPNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -142,13 +141,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = -1, /* -1 = auto */
.maximum = 4,
.step = 1,
-#define SHARPNESS_DEF -1
- .default_value = SHARPNESS_DEF,
+ .default_value = -1
},
- .set = sd_setsharpness,
- .get = sd_getsharpness,
+ .set_control = setsharpness
},
- { /* 5 */
+[SATUR] = {
{
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -156,13 +153,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 4,
.step = 1,
-#define SATUR_DEF 2
- .default_value = SATUR_DEF,
+ .default_value = 2
},
- .set = sd_setsatur,
- .get = sd_getsatur,
+ .set_control = setsatur
},
- {
+[LIGHTFREQ] = {
{
.id = V4L2_CID_POWER_LINE_FREQUENCY,
.type = V4L2_CTRL_TYPE_MENU,
@@ -170,11 +165,9 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
.step = 1,
-#define FREQ_DEF 0
- .default_value = FREQ_DEF,
+ .default_value = 0
},
- .set = sd_setfreq,
- .get = sd_getfreq,
+ .set_control = setlightfreq
},
};
@@ -206,6 +199,14 @@ static const struct v4l2_pix_format ov965x_mode[] = {
.colorspace = V4L2_COLORSPACE_JPEG},
};
+static const struct v4l2_pix_format ov971x_mode[] = {
+ {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+ .bytesperline = 640,
+ .sizeimage = 640 * 480,
+ .colorspace = V4L2_COLORSPACE_SRGB
+ }
+};
+
static const u8 bridge_init[][2] = {
{0x88, 0xf8},
{0x89, 0xff},
@@ -240,7 +241,7 @@ static const u8 bridge_init[][2] = {
{0x94, 0x11},
};
-static const u8 sensor_init[][2] = {
+static const u8 ov965x_init[][2] = {
{0x12, 0x80}, /* com7 - SSCB reset */
{0x00, 0x00}, /* gain */
{0x01, 0x80}, /* blue */
@@ -450,7 +451,7 @@ static const u8 bridge_init_2[][2] = {
{0x94, 0x11},
};
-static const u8 sensor_init_2[][2] = {
+static const u8 ov965x_init_2[][2] = {
{0x3b, 0xc4},
{0x1e, 0x04}, /* mvfp */
{0x13, 0xe0}, /* com8 */
@@ -492,7 +493,65 @@ static const u8 sensor_init_2[][2] = {
{0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
};
-static const u8 sensor_start_1_vga[][2] = { /* same for qvga */
+static const u8 ov971x_init[][2] = {
+ {0x12, 0x80},
+ {0x09, 0x10},
+ {0x1e, 0x07},
+ {0x5f, 0x18},
+ {0x69, 0x04},
+ {0x65, 0x2a},
+ {0x68, 0x0a},
+ {0x39, 0x28},
+ {0x4d, 0x90},
+ {0xc1, 0x80},
+ {0x0c, 0x30},
+ {0x6d, 0x02},
+ {0x96, 0xf1},
+ {0xbc, 0x68},
+ {0x12, 0x00},
+ {0x3b, 0x00},
+ {0x97, 0x80},
+ {0x17, 0x25},
+ {0x18, 0xa2},
+ {0x19, 0x01},
+ {0x1a, 0xca},
+ {0x03, 0x0a},
+ {0x32, 0x07},
+ {0x98, 0x40}, /*{0x98, 0x00},*/
+ {0x99, 0xA0}, /*{0x99, 0x00},*/
+ {0x9a, 0x01}, /*{0x9a, 0x00},*/
+ {0x57, 0x00},
+ {0x58, 0x78}, /*{0x58, 0xc8},*/
+ {0x59, 0x50}, /*{0x59, 0xa0},*/
+ {0x4c, 0x13},
+ {0x4b, 0x36},
+ {0x3d, 0x3c},
+ {0x3e, 0x03},
+ {0xbd, 0x50}, /*{0xbd, 0xa0},*/
+ {0xbe, 0x78}, /*{0xbe, 0xc8},*/
+ {0x4e, 0x55},
+ {0x4f, 0x55},
+ {0x50, 0x55},
+ {0x51, 0x55},
+ {0x24, 0x55},
+ {0x25, 0x40},
+ {0x26, 0xa1},
+ {0x5c, 0x59},
+ {0x5d, 0x00},
+ {0x11, 0x00},
+ {0x2a, 0x98},
+ {0x2b, 0x06},
+ {0x2d, 0x00},
+ {0x2e, 0x00},
+ {0x13, 0xa5},
+ {0x14, 0x40},
+ {0x4a, 0x00},
+ {0x49, 0xce},
+ {0x22, 0x03},
+ {0x09, 0x00}
+};
+
+static const u8 ov965x_start_1_vga[][2] = { /* same for qvga */
{0x12, 0x62}, /* com7 - 30fps VGA YUV */
{0x36, 0xfa}, /* aref3 */
{0x69, 0x0a}, /* hv */
@@ -515,7 +574,7 @@ static const u8 sensor_start_1_vga[][2] = { /* same for qvga */
{0xc0, 0xaa},
};
-static const u8 sensor_start_1_svga[][2] = {
+static const u8 ov965x_start_1_svga[][2] = {
{0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */
{0x36, 0xf8}, /* aref3 */
{0x69, 0x02}, /* hv */
@@ -537,7 +596,7 @@ static const u8 sensor_start_1_svga[][2] = {
{0xc0, 0xe2},
};
-static const u8 sensor_start_1_xga[][2] = {
+static const u8 ov965x_start_1_xga[][2] = {
{0x12, 0x02}, /* com7 */
{0x36, 0xf8}, /* aref3 */
{0x69, 0x02}, /* hv */
@@ -560,7 +619,7 @@ static const u8 sensor_start_1_xga[][2] = {
{0xc0, 0xe2},
};
-static const u8 sensor_start_1_sxga[][2] = {
+static const u8 ov965x_start_1_sxga[][2] = {
{0x12, 0x02}, /* com7 */
{0x36, 0xf8}, /* aref3 */
{0x69, 0x02}, /* hv */
@@ -709,7 +768,7 @@ static const u8 bridge_start_sxga[][2] = {
{0x94, 0x11},
};
-static const u8 sensor_start_2_qvga[][2] = {
+static const u8 ov965x_start_2_qvga[][2] = {
{0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */
{0x1e, 0x04}, /* mvfp */
{0x13, 0xe0}, /* com8 */
@@ -727,7 +786,7 @@ static const u8 sensor_start_2_qvga[][2] = {
{0x3a, 0x80}, /* tslb - yuyv */
};
-static const u8 sensor_start_2_vga[][2] = {
+static const u8 ov965x_start_2_vga[][2] = {
{0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
{0x1e, 0x04}, /* mvfp */
{0x13, 0xe0}, /* com8 */
@@ -743,7 +802,7 @@ static const u8 sensor_start_2_vga[][2] = {
{0x2d, 0x00}, /* advfl */
};
-static const u8 sensor_start_2_svga[][2] = { /* same for xga */
+static const u8 ov965x_start_2_svga[][2] = { /* same for xga */
{0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
{0x1e, 0x04}, /* mvfp */
{0x13, 0xe0}, /* com8 */
@@ -757,7 +816,7 @@ static const u8 sensor_start_2_svga[][2] = { /* same for xga */
{0xa3, 0x41}, /* bd60 */
};
-static const u8 sensor_start_2_sxga[][2] = {
+static const u8 ov965x_start_2_sxga[][2] = {
{0x13, 0xe0}, /* com8 */
{0x00, 0x00},
{0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
@@ -785,7 +844,7 @@ static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
if (ret < 0) {
- err("reg_w failed %d", ret);
+ pr_err("reg_w failed %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -810,7 +869,7 @@ static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
}
return gspca_dev->usb_buf[0];
@@ -848,7 +907,7 @@ static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
if (!sccb_check_status(gspca_dev))
- err("sccb_write failed");
+ pr_err("sccb_write failed\n");
}
static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
@@ -856,11 +915,11 @@ static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
if (!sccb_check_status(gspca_dev))
- err("sccb_read failed 1");
+ pr_err("sccb_read failed 1\n");
reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
if (!sccb_check_status(gspca_dev))
- err("sccb_read failed 2");
+ pr_err("sccb_read failed 2\n");
return reg_r(gspca_dev, OV534_REG_READ);
}
@@ -922,7 +981,9 @@ static void setbrightness(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
u8 val;
- val = sd->brightness;
+ if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS))
+ return;
+ val = sd->ctrls[BRIGHTNESS].val;
if (val < 8)
val = 15 - val; /* f .. 8 */
else
@@ -935,8 +996,10 @@ static void setcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ if (gspca_dev->ctrl_dis & (1 << CONTRAST))
+ return;
sccb_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */
- sd->contrast << 4);
+ sd->ctrls[CONTRAST].val << 4);
}
static void setautogain(struct gspca_dev *gspca_dev)
@@ -944,10 +1007,12 @@ static void setautogain(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
u8 val;
+ if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
+ return;
/*fixme: should adjust agc/awb/aec by different controls */
val = sccb_read(gspca_dev, 0x13); /* com8 */
sccb_write(gspca_dev, 0xff, 0x00);
- if (sd->autogain)
+ if (sd->ctrls[AUTOGAIN].val)
val |= 0x05; /* agc & aec */
else
val &= 0xfa;
@@ -960,8 +1025,10 @@ static void setexposure(struct gspca_dev *gspca_dev)
u8 val;
static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
+ if (gspca_dev->ctrl_dis & (1 << EXPOSURE))
+ return;
sccb_write(gspca_dev, 0x10, /* aec[9:2] */
- expo[sd->exposure]);
+ expo[sd->ctrls[EXPOSURE].val]);
val = sccb_read(gspca_dev, 0x13); /* com8 */
sccb_write(gspca_dev, 0xff, 0x00);
@@ -977,7 +1044,9 @@ static void setsharpness(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
s8 val;
- val = sd->sharpness;
+ if (gspca_dev->ctrl_dis & (1 << SHARPNESS))
+ return;
+ val = sd->ctrls[SHARPNESS].val;
if (val < 0) { /* auto */
val = sccb_read(gspca_dev, 0x42); /* com17 */
sccb_write(gspca_dev, 0xff, 0x00);
@@ -1006,8 +1075,10 @@ static void setsatur(struct gspca_dev *gspca_dev)
{0x48, 0x90}
};
- val1 = matrix[sd->satur][0];
- val2 = matrix[sd->satur][1];
+ if (gspca_dev->ctrl_dis & (1 << SATUR))
+ return;
+ val1 = matrix[sd->ctrls[SATUR].val][0];
+ val2 = matrix[sd->ctrls[SATUR].val][1];
val3 = val1 + val2;
sccb_write(gspca_dev, 0x4f, val3); /* matrix coeff */
sccb_write(gspca_dev, 0x50, val3);
@@ -1022,14 +1093,16 @@ static void setsatur(struct gspca_dev *gspca_dev)
sccb_write(gspca_dev, 0x41, val1);
}
-static void setfreq(struct gspca_dev *gspca_dev)
+static void setlightfreq(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
u8 val;
+ if (gspca_dev->ctrl_dis & (1 << LIGHTFREQ))
+ return;
val = sccb_read(gspca_dev, 0x13); /* com8 */
sccb_write(gspca_dev, 0xff, 0x00);
- if (sd->freq == 0) {
+ if (sd->ctrls[LIGHTFREQ].val == 0) {
sccb_write(gspca_dev, 0x13, val & 0xdf);
return;
}
@@ -1037,7 +1110,7 @@ static void setfreq(struct gspca_dev *gspca_dev)
val = sccb_read(gspca_dev, 0x42); /* com17 */
sccb_write(gspca_dev, 0xff, 0x00);
- if (sd->freq == 1)
+ if (sd->ctrls[LIGHTFREQ].val == 1)
val |= 0x01;
else
val &= 0xfe;
@@ -1049,34 +1122,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
- struct cam *cam;
-
- cam = &gspca_dev->cam;
- cam->cam_mode = ov965x_mode;
- cam->nmodes = ARRAY_SIZE(ov965x_mode);
+ gspca_dev->cam.ctrls = sd->ctrls;
- sd->brightness = BRIGHTNESS_DEF;
- sd->contrast = CONTRAST_DEF;
#if AUTOGAIN_DEF != 0
- sd->autogain = AUTOGAIN_DEF;
- gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
-#endif
-#if EXPO_DEF != 0
- sd->exposure = EXPO_DEF;
-#endif
-#if SHARPNESS_DEF != 0
- sd->sharpness = SHARPNESS_DEF;
+ gspca_dev->ctrl_inac |= (1 << EXPOSURE);
#endif
- sd->satur = SATUR_DEF;
- sd->freq = FREQ_DEF;
-
return 0;
}
/* this function is called at probe and resume time */
static int sd_init(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
u16 sensor_id;
/* reset bridge */
@@ -1099,68 +1157,117 @@ static int sd_init(struct gspca_dev *gspca_dev)
PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
/* initialize */
- reg_w_array(gspca_dev, bridge_init,
- ARRAY_SIZE(bridge_init));
- sccb_w_array(gspca_dev, sensor_init,
- ARRAY_SIZE(sensor_init));
- reg_w_array(gspca_dev, bridge_init_2,
- ARRAY_SIZE(bridge_init_2));
- sccb_w_array(gspca_dev, sensor_init_2,
- ARRAY_SIZE(sensor_init_2));
- reg_w(gspca_dev, 0xe0, 0x00);
- reg_w(gspca_dev, 0xe0, 0x01);
- set_led(gspca_dev, 0);
- reg_w(gspca_dev, 0xe0, 0x00);
+ if ((sensor_id & 0xfff0) == 0x9650) {
+ sd->sensor = SENSOR_OV965x;
+
+ gspca_dev->cam.cam_mode = ov965x_mode;
+ gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);
+
+ reg_w_array(gspca_dev, bridge_init,
+ ARRAY_SIZE(bridge_init));
+ sccb_w_array(gspca_dev, ov965x_init,
+ ARRAY_SIZE(ov965x_init));
+ reg_w_array(gspca_dev, bridge_init_2,
+ ARRAY_SIZE(bridge_init_2));
+ sccb_w_array(gspca_dev, ov965x_init_2,
+ ARRAY_SIZE(ov965x_init_2));
+ reg_w(gspca_dev, 0xe0, 0x00);
+ reg_w(gspca_dev, 0xe0, 0x01);
+ set_led(gspca_dev, 0);
+ reg_w(gspca_dev, 0xe0, 0x00);
+ } else if ((sensor_id & 0xfff0) == 0x9710) {
+ const char *p;
+ int l;
+
+ sd->sensor = SENSOR_OV971x;
+
+ gspca_dev->cam.cam_mode = ov971x_mode;
+ gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);
+
+ /* no control yet */
+ gspca_dev->ctrl_dis = (1 << NCTRLS) - 1;
+
+ gspca_dev->cam.bulk = 1;
+ gspca_dev->cam.bulk_size = 16384;
+ gspca_dev->cam.bulk_nurbs = 2;
+
+ sccb_w_array(gspca_dev, ov971x_init,
+ ARRAY_SIZE(ov971x_init));
+
+ /* set video format on bridge processor */
+ /* access bridge processor's video format registers at: 0x00 */
+ reg_w(gspca_dev, 0x1c, 0x00);
+ /*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/
+ reg_w(gspca_dev, 0x1d, 0x00);
+
+ /* Will W. specific stuff
+ * set VSYNC to
+ * output (0x1f) if first webcam
+ * input (0x17) if 2nd or 3rd webcam */
+ p = video_device_node_name(&gspca_dev->vdev);
+ l = strlen(p) - 1;
+ if (p[l] == '0')
+ reg_w(gspca_dev, 0x56, 0x1f);
+ else
+ reg_w(gspca_dev, 0x56, 0x17);
+ } else {
+ err("Unknown sensor %04x", sensor_id);
+ return -EINVAL;
+ }
return gspca_dev->usb_err;
}
static int sd_start(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->sensor == SENSOR_OV971x)
+ return gspca_dev->usb_err;
switch (gspca_dev->curr_mode) {
case QVGA_MODE: /* 320x240 */
- sccb_w_array(gspca_dev, sensor_start_1_vga,
- ARRAY_SIZE(sensor_start_1_vga));
+ sccb_w_array(gspca_dev, ov965x_start_1_vga,
+ ARRAY_SIZE(ov965x_start_1_vga));
reg_w_array(gspca_dev, bridge_start_qvga,
ARRAY_SIZE(bridge_start_qvga));
- sccb_w_array(gspca_dev, sensor_start_2_qvga,
- ARRAY_SIZE(sensor_start_2_qvga));
+ sccb_w_array(gspca_dev, ov965x_start_2_qvga,
+ ARRAY_SIZE(ov965x_start_2_qvga));
break;
case VGA_MODE: /* 640x480 */
- sccb_w_array(gspca_dev, sensor_start_1_vga,
- ARRAY_SIZE(sensor_start_1_vga));
+ sccb_w_array(gspca_dev, ov965x_start_1_vga,
+ ARRAY_SIZE(ov965x_start_1_vga));
reg_w_array(gspca_dev, bridge_start_vga,
ARRAY_SIZE(bridge_start_vga));
- sccb_w_array(gspca_dev, sensor_start_2_vga,
- ARRAY_SIZE(sensor_start_2_vga));
+ sccb_w_array(gspca_dev, ov965x_start_2_vga,
+ ARRAY_SIZE(ov965x_start_2_vga));
break;
case SVGA_MODE: /* 800x600 */
- sccb_w_array(gspca_dev, sensor_start_1_svga,
- ARRAY_SIZE(sensor_start_1_svga));
+ sccb_w_array(gspca_dev, ov965x_start_1_svga,
+ ARRAY_SIZE(ov965x_start_1_svga));
reg_w_array(gspca_dev, bridge_start_svga,
ARRAY_SIZE(bridge_start_svga));
- sccb_w_array(gspca_dev, sensor_start_2_svga,
- ARRAY_SIZE(sensor_start_2_svga));
+ sccb_w_array(gspca_dev, ov965x_start_2_svga,
+ ARRAY_SIZE(ov965x_start_2_svga));
break;
case XGA_MODE: /* 1024x768 */
- sccb_w_array(gspca_dev, sensor_start_1_xga,
- ARRAY_SIZE(sensor_start_1_xga));
+ sccb_w_array(gspca_dev, ov965x_start_1_xga,
+ ARRAY_SIZE(ov965x_start_1_xga));
reg_w_array(gspca_dev, bridge_start_xga,
ARRAY_SIZE(bridge_start_xga));
- sccb_w_array(gspca_dev, sensor_start_2_svga,
- ARRAY_SIZE(sensor_start_2_svga));
+ sccb_w_array(gspca_dev, ov965x_start_2_svga,
+ ARRAY_SIZE(ov965x_start_2_svga));
break;
default:
/* case SXGA_MODE: * 1280x1024 */
- sccb_w_array(gspca_dev, sensor_start_1_sxga,
- ARRAY_SIZE(sensor_start_1_sxga));
+ sccb_w_array(gspca_dev, ov965x_start_1_sxga,
+ ARRAY_SIZE(ov965x_start_1_sxga));
reg_w_array(gspca_dev, bridge_start_sxga,
ARRAY_SIZE(bridge_start_sxga));
- sccb_w_array(gspca_dev, sensor_start_2_sxga,
- ARRAY_SIZE(sensor_start_2_sxga));
+ sccb_w_array(gspca_dev, ov965x_start_2_sxga,
+ ARRAY_SIZE(ov965x_start_2_sxga));
break;
}
- setfreq(gspca_dev);
+ setlightfreq(gspca_dev);
setautogain(gspca_dev);
setbrightness(gspca_dev);
setcontrast(gspca_dev);
@@ -1198,9 +1305,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
__u32 this_pts;
u8 this_fid;
int remaining_len = len;
+ int payload_len;
+ payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
do {
- len = min(remaining_len, 2040);
+ len = min(remaining_len, payload_len);
/* Payloads are prefixed with a UVC-style header. We
consider a frame to start when the FID toggles, or the PTS
@@ -1262,138 +1371,6 @@ scan_next:
} while (remaining_len > 0);
}
-/* controls */
-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->brightness = val;
- if (gspca_dev->streaming)
- setbrightness(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->brightness;
- return 0;
-}
-
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->contrast = val;
- if (gspca_dev->streaming)
- setcontrast(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->contrast;
- return 0;
-}
-
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->autogain = val;
-
- if (gspca_dev->streaming) {
- if (val)
- gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
- else
- gspca_dev->ctrl_inac &= ~(1 << EXPO_IDX);
- setautogain(gspca_dev);
- }
- return gspca_dev->usb_err;
-}
-
-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->autogain;
- return 0;
-}
-
-static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->exposure = val;
- if (gspca_dev->streaming)
- setexposure(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->exposure;
- return 0;
-}
-
-static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->sharpness = val;
- if (gspca_dev->streaming)
- setsharpness(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->sharpness;
- return 0;
-}
-
-static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->satur = val;
- if (gspca_dev->streaming)
- setsatur(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->satur;
- return 0;
-}
-static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- sd->freq = val;
- if (gspca_dev->streaming)
- setfreq(gspca_dev);
- return gspca_dev->usb_err;
-}
-
-static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- *val = sd->freq;
- return 0;
-}
-
static int sd_querymenu(struct gspca_dev *gspca_dev,
struct v4l2_querymenu *menu)
{
@@ -1419,7 +1396,7 @@ static int sd_querymenu(struct gspca_dev *gspca_dev,
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
- .nctrls = ARRAY_SIZE(sd_ctrls),
+ .nctrls = NCTRLS,
.config = sd_config,
.init = sd_init,
.start = sd_start,
@@ -1430,6 +1407,7 @@ static const struct sd_desc sd_desc = {
/* -- module initialisation -- */
static const struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x05a9, 0x8065)},
{USB_DEVICE(0x06f8, 0x3003)},
{}
};
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
index 81739a2f205e..1600df152fd6 100644
--- a/drivers/media/video/gspca/pac207.c
+++ b/drivers/media/video/gspca/pac207.c
@@ -23,6 +23,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "pac207"
#include <linux/input.h>
@@ -178,8 +180,8 @@ static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
0x00, index,
gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
if (err < 0)
- err("Failed to write registers to index 0x%04X, error %d)",
- index, err);
+ pr_err("Failed to write registers to index 0x%04X, error %d\n",
+ index, err);
return err;
}
@@ -194,8 +196,8 @@ static int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
if (err)
- err("Failed to write a register (index 0x%04X,"
- " value 0x%02X, error %d)", index, value, err);
+ pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
+ index, value, err);
return err;
}
@@ -210,8 +212,8 @@ static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
0x00, index,
gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
if (res < 0) {
- err("Failed to read a register (index 0x%04X, error %d)",
- index, res);
+ pr_err("Failed to read a register (index 0x%04X, error %d)\n",
+ index, res);
return res;
}
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c
index 5615d7bd8304..1c44f78ff9e2 100644
--- a/drivers/media/video/gspca/pac7302.c
+++ b/drivers/media/video/gspca/pac7302.c
@@ -61,6 +61,8 @@
3 | 0x21 | sethvflip()
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "pac7302"
#include <linux/input.h>
@@ -408,8 +410,8 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
index, gspca_dev->usb_buf, len,
500);
if (ret < 0) {
- err("reg_w_buf failed index 0x%02x, error %d",
- index, ret);
+ pr_err("reg_w_buf failed index 0x%02x, error %d\n",
+ index, ret);
gspca_dev->usb_err = ret;
}
}
@@ -431,8 +433,8 @@ static void reg_w(struct gspca_dev *gspca_dev,
0, index, gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
- index, value, ret);
+ pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
+ index, value, ret);
gspca_dev->usb_err = ret;
}
}
@@ -466,9 +468,8 @@ static void reg_w_page(struct gspca_dev *gspca_dev,
0, index, gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w_page() failed index 0x%02x, "
- "value 0x%02x, error %d",
- index, page[index], ret);
+ pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
+ index, page[index], ret);
gspca_dev->usb_err = ret;
break;
}
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index f8801b50e64f..7509d05dc065 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -49,6 +49,8 @@
for max gain, 0x14 for minimal gain.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "pac7311"
#include <linux/input.h>
@@ -276,8 +278,8 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
index, gspca_dev->usb_buf, len,
500);
if (ret < 0) {
- err("reg_w_buf() failed index 0x%02x, error %d",
- index, ret);
+ pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
+ index, ret);
gspca_dev->usb_err = ret;
}
}
@@ -299,8 +301,8 @@ static void reg_w(struct gspca_dev *gspca_dev,
0, index, gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
- index, value, ret);
+ pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
+ index, value, ret);
gspca_dev->usb_err = ret;
}
}
@@ -334,9 +336,8 @@ static void reg_w_page(struct gspca_dev *gspca_dev,
0, index, gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w_page() failed index 0x%02x, "
- "value 0x%02x, error %d",
- index, page[index], ret);
+ pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
+ index, page[index], ret);
gspca_dev->usb_err = ret;
break;
}
diff --git a/drivers/media/video/gspca/se401.c b/drivers/media/video/gspca/se401.c
index 4c283c24c752..3b71bbcd977a 100644
--- a/drivers/media/video/gspca/se401.c
+++ b/drivers/media/video/gspca/se401.c
@@ -23,6 +23,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "se401"
#define BULK_SIZE 4096
@@ -144,8 +146,8 @@ static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value,
value, 0, NULL, 0, 1000);
if (err < 0) {
if (!silent)
- err("write req failed req %#04x val %#04x error %d",
- req, value, err);
+ pr_err("write req failed req %#04x val %#04x error %d\n",
+ req, value, err);
gspca_dev->usb_err = err;
}
}
@@ -158,7 +160,7 @@ static void se401_read_req(struct gspca_dev *gspca_dev, u16 req, int silent)
return;
if (USB_BUF_SZ < READ_REQ_SIZE) {
- err("USB_BUF_SZ too small!!");
+ pr_err("USB_BUF_SZ too small!!\n");
gspca_dev->usb_err = -ENOBUFS;
return;
}
@@ -169,7 +171,8 @@ static void se401_read_req(struct gspca_dev *gspca_dev, u16 req, int silent)
0, 0, gspca_dev->usb_buf, READ_REQ_SIZE, 1000);
if (err < 0) {
if (!silent)
- err("read req failed req %#04x error %d", req, err);
+ pr_err("read req failed req %#04x error %d\n",
+ req, err);
gspca_dev->usb_err = err;
}
}
@@ -188,8 +191,8 @@ static void se401_set_feature(struct gspca_dev *gspca_dev,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
param, selector, NULL, 0, 1000);
if (err < 0) {
- err("set feature failed sel %#04x param %#04x error %d",
- selector, param, err);
+ pr_err("set feature failed sel %#04x param %#04x error %d\n",
+ selector, param, err);
gspca_dev->usb_err = err;
}
}
@@ -202,7 +205,7 @@ static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector)
return gspca_dev->usb_err;
if (USB_BUF_SZ < 2) {
- err("USB_BUF_SZ too small!!");
+ pr_err("USB_BUF_SZ too small!!\n");
gspca_dev->usb_err = -ENOBUFS;
return gspca_dev->usb_err;
}
@@ -213,7 +216,8 @@ static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, selector, gspca_dev->usb_buf, 2, 1000);
if (err < 0) {
- err("get feature failed sel %#04x error %d", selector, err);
+ pr_err("get feature failed sel %#04x error %d\n",
+ selector, err);
gspca_dev->usb_err = err;
return err;
}
@@ -300,21 +304,21 @@ static int sd_config(struct gspca_dev *gspca_dev,
return gspca_dev->usb_err;
if (cd[1] != 0x41) {
- err("Wrong descriptor type");
+ pr_err("Wrong descriptor type\n");
return -ENODEV;
}
if (!(cd[2] & SE401_FORMAT_BAYER)) {
- err("Bayer format not supported!");
+ pr_err("Bayer format not supported!\n");
return -ENODEV;
}
if (cd[3])
- info("ExtraFeatures: %d", cd[3]);
+ pr_info("ExtraFeatures: %d\n", cd[3]);
n = cd[4] | (cd[5] << 8);
if (n > MAX_MODES) {
- err("Too many frame sizes");
+ pr_err("Too many frame sizes\n");
return -ENODEV;
}
@@ -353,15 +357,16 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8;
sd->fmts[i].bytesperline = widths[i];
sd->fmts[i].sizeimage = widths[i] * heights[i];
- info("Frame size: %dx%d bayer", widths[i], heights[i]);
+ pr_info("Frame size: %dx%d bayer\n",
+ widths[i], heights[i]);
} else {
/* Found a match use janggu compression */
sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401;
sd->fmts[i].bytesperline = 0;
sd->fmts[i].sizeimage = widths[i] * heights[i] * 3;
- info("Frame size: %dx%d 1/%dth janggu",
- widths[i], heights[i],
- sd->fmts[i].priv * sd->fmts[i].priv);
+ pr_info("Frame size: %dx%d 1/%dth janggu\n",
+ widths[i], heights[i],
+ sd->fmts[i].priv * sd->fmts[i].priv);
}
}
@@ -571,11 +576,12 @@ static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len)
plen = ((bits + 47) >> 4) << 1;
/* Sanity checks */
if (plen > 1024) {
- err("invalid packet len %d restarting stream", plen);
+ pr_err("invalid packet len %d restarting stream\n",
+ plen);
goto error;
}
if (info == 3) {
- err("unknown frame info value restarting stream");
+ pr_err("unknown frame info value restarting stream\n");
goto error;
}
@@ -599,8 +605,8 @@ static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len)
break;
case 1: /* EOF */
if (sd->pixels_read != imagesize) {
- err("frame size %d expected %d",
- sd->pixels_read, imagesize);
+ pr_err("frame size %d expected %d\n",
+ sd->pixels_read, imagesize);
goto error;
}
sd_complete_frame(gspca_dev, sd->packet, plen);
diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c
index 4271f86dfe01..48aae3926a33 100644
--- a/drivers/media/video/gspca/sn9c2028.c
+++ b/drivers/media/video/gspca/sn9c2028.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sn9c2028"
#include "gspca.h"
@@ -75,8 +77,8 @@ static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
2, 0, gspca_dev->usb_buf, 6, 500);
if (rc < 0) {
- err("command write [%02x] error %d",
- gspca_dev->usb_buf[0], rc);
+ pr_err("command write [%02x] error %d\n",
+ gspca_dev->usb_buf[0], rc);
return rc;
}
@@ -93,7 +95,7 @@ static int sn9c2028_read1(struct gspca_dev *gspca_dev)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1, 0, gspca_dev->usb_buf, 1, 500);
if (rc != 1) {
- err("read1 error %d", rc);
+ pr_err("read1 error %d\n", rc);
return (rc < 0) ? rc : -EIO;
}
PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
@@ -109,7 +111,7 @@ static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
4, 0, gspca_dev->usb_buf, 4, 500);
if (rc != 4) {
- err("read4 error %d", rc);
+ pr_err("read4 error %d\n", rc);
return (rc < 0) ? rc : -EIO;
}
memcpy(reading, gspca_dev->usb_buf, 4);
@@ -131,7 +133,7 @@ static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
for (i = 0; i < 256 && status < 2; i++)
status = sn9c2028_read1(gspca_dev);
if (status != 2) {
- err("long command status read error %d", status);
+ pr_err("long command status read error %d\n", status);
return (status < 0) ? status : -EIO;
}
@@ -638,7 +640,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
err_code = start_vivitar_cam(gspca_dev);
break;
default:
- err("Starting unknown camera, please report this");
+ pr_err("Starting unknown camera, please report this\n");
return -ENXIO;
}
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
index c431900cd292..86e07a139a16 100644
--- a/drivers/media/video/gspca/sn9c20x.c
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/input.h>
#include "gspca.h"
@@ -1123,7 +1125,7 @@ static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
length,
500);
if (unlikely(result < 0 || result != length)) {
- err("Read register failed 0x%02X", reg);
+ pr_err("Read register failed 0x%02X\n", reg);
return -EIO;
}
return 0;
@@ -1144,7 +1146,7 @@ static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
length,
500);
if (unlikely(result < 0 || result != length)) {
- err("Write register failed index 0x%02X", reg);
+ pr_err("Write register failed index 0x%02X\n", reg);
return -EIO;
}
return 0;
@@ -1275,14 +1277,14 @@ static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
return -EINVAL;
if (id != 0x7fa2) {
- err("sensor id for ov9650 doesn't match (0x%04x)", id);
+ pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
return -ENODEV;
}
for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
if (i2c_w1(gspca_dev, ov9650_init[i].reg,
ov9650_init[i].val) < 0) {
- err("OV9650 sensor initialization failed");
+ pr_err("OV9650 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1299,7 +1301,7 @@ static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
if (i2c_w1(gspca_dev, ov9655_init[i].reg,
ov9655_init[i].val) < 0) {
- err("OV9655 sensor initialization failed");
+ pr_err("OV9655 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1318,7 +1320,7 @@ static int soi968_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
if (i2c_w1(gspca_dev, soi968_init[i].reg,
soi968_init[i].val) < 0) {
- err("SOI968 sensor initialization failed");
+ pr_err("SOI968 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1338,7 +1340,7 @@ static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
if (i2c_w1(gspca_dev, ov7660_init[i].reg,
ov7660_init[i].val) < 0) {
- err("OV7660 sensor initialization failed");
+ pr_err("OV7660 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1355,7 +1357,7 @@ static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
if (i2c_w1(gspca_dev, ov7670_init[i].reg,
ov7670_init[i].val) < 0) {
- err("OV7670 sensor initialization failed");
+ pr_err("OV7670 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1379,14 +1381,14 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
mt9v011_init[i].val) < 0) {
- err("MT9V011 sensor initialization failed");
+ pr_err("MT9V011 sensor initialization failed\n");
return -ENODEV;
}
}
sd->hstart = 2;
sd->vstart = 2;
sd->sensor = SENSOR_MT9V011;
- info("MT9V011 sensor detected");
+ pr_info("MT9V011 sensor detected\n");
return 0;
}
@@ -1397,7 +1399,7 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
mt9v111_init[i].val) < 0) {
- err("MT9V111 sensor initialization failed");
+ pr_err("MT9V111 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1407,7 +1409,7 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
sd->hstart = 2;
sd->vstart = 2;
sd->sensor = SENSOR_MT9V111;
- info("MT9V111 sensor detected");
+ pr_info("MT9V111 sensor detected\n");
return 0;
}
@@ -1422,14 +1424,14 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
mt9v112_init[i].val) < 0) {
- err("MT9V112 sensor initialization failed");
+ pr_err("MT9V112 sensor initialization failed\n");
return -ENODEV;
}
}
sd->hstart = 6;
sd->vstart = 2;
sd->sensor = SENSOR_MT9V112;
- info("MT9V112 sensor detected");
+ pr_info("MT9V112 sensor detected\n");
return 0;
}
@@ -1443,7 +1445,7 @@ static int mt9m112_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
mt9m112_init[i].val) < 0) {
- err("MT9M112 sensor initialization failed");
+ pr_err("MT9M112 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1461,7 +1463,7 @@ static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
mt9m111_init[i].val) < 0) {
- err("MT9M111 sensor initialization failed");
+ pr_err("MT9M111 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1485,20 +1487,20 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
switch (id) {
case 0x8411:
case 0x8421:
- info("MT9M001 color sensor detected");
+ pr_info("MT9M001 color sensor detected\n");
break;
case 0x8431:
- info("MT9M001 mono sensor detected");
+ pr_info("MT9M001 mono sensor detected\n");
break;
default:
- err("No MT9M001 chip detected, ID = %x\n", id);
+ pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
return -ENODEV;
}
for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
mt9m001_init[i].val) < 0) {
- err("MT9M001 sensor initialization failed");
+ pr_err("MT9M001 sensor initialization failed\n");
return -ENODEV;
}
}
@@ -1517,7 +1519,7 @@ static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
hv7131r_init[i].val) < 0) {
- err("HV7131R Sensor initialization failed");
+ pr_err("HV7131R Sensor initialization failed\n");
return -ENODEV;
}
}
@@ -2103,7 +2105,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
value = bridge_init[i][1];
if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
- err("Device initialization failed");
+ pr_err("Device initialization failed\n");
return -ENODEV;
}
}
@@ -2114,7 +2116,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x1006, 0x20);
if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
- err("Device initialization failed");
+ pr_err("Device initialization failed\n");
return -ENODEV;
}
@@ -2122,27 +2124,27 @@ static int sd_init(struct gspca_dev *gspca_dev)
case SENSOR_OV9650:
if (ov9650_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("OV9650 sensor detected");
+ pr_info("OV9650 sensor detected\n");
break;
case SENSOR_OV9655:
if (ov9655_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("OV9655 sensor detected");
+ pr_info("OV9655 sensor detected\n");
break;
case SENSOR_SOI968:
if (soi968_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("SOI968 sensor detected");
+ pr_info("SOI968 sensor detected\n");
break;
case SENSOR_OV7660:
if (ov7660_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("OV7660 sensor detected");
+ pr_info("OV7660 sensor detected\n");
break;
case SENSOR_OV7670:
if (ov7670_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("OV7670 sensor detected");
+ pr_info("OV7670 sensor detected\n");
break;
case SENSOR_MT9VPRB:
if (mt9v_init_sensor(gspca_dev) < 0)
@@ -2151,12 +2153,12 @@ static int sd_init(struct gspca_dev *gspca_dev)
case SENSOR_MT9M111:
if (mt9m111_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("MT9M111 sensor detected");
+ pr_info("MT9M111 sensor detected\n");
break;
case SENSOR_MT9M112:
if (mt9m112_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("MT9M112 sensor detected");
+ pr_info("MT9M112 sensor detected\n");
break;
case SENSOR_MT9M001:
if (mt9m001_init_sensor(gspca_dev) < 0)
@@ -2165,10 +2167,10 @@ static int sd_init(struct gspca_dev *gspca_dev)
case SENSOR_HV7131R:
if (hv7131r_init_sensor(gspca_dev) < 0)
return -ENODEV;
- info("HV7131R sensor detected");
+ pr_info("HV7131R sensor detected\n");
break;
default:
- info("Unsupported Sensor");
+ pr_info("Unsupported Sensor\n");
return -ENODEV;
}
@@ -2263,19 +2265,19 @@ static int sd_start(struct gspca_dev *gspca_dev)
switch (mode & SCALE_MASK) {
case SCALE_1280x1024:
scale = 0xc0;
- info("Set 1280x1024");
+ pr_info("Set 1280x1024\n");
break;
case SCALE_640x480:
scale = 0x80;
- info("Set 640x480");
+ pr_info("Set 640x480\n");
break;
case SCALE_320x240:
scale = 0x90;
- info("Set 320x240");
+ pr_info("Set 320x240\n");
break;
case SCALE_160x120:
scale = 0xa0;
- info("Set 160x120");
+ pr_info("Set 160x120\n");
break;
}
@@ -2513,7 +2515,7 @@ static const struct usb_device_id device_table[] = {
{USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
{USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
{USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
- {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
+ {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
{USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
{USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
{USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index c477ad11f103..c746bf19ca14 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -1,7 +1,7 @@
/*
* Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
*
- * Copyright (C) 2009-2010 Jean-François Moine <http://moinejf.free.fr>
+ * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr>
* Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
*
* This program is free software; you can redistribute it and/or modify
@@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sonixj"
#include <linux/input.h>
@@ -136,7 +138,7 @@ static void setillum(struct gspca_dev *gspca_dev);
static void setfreq(struct gspca_dev *gspca_dev);
static const struct ctrl sd_ctrls[NCTRLS] = {
-[BRIGHTNESS] = {
+[BRIGHTNESS] = {
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -157,7 +159,7 @@ static const struct ctrl sd_ctrls[NCTRLS] = {
#define CONTRAST_MAX 127
.maximum = CONTRAST_MAX,
.step = 1,
- .default_value = 63,
+ .default_value = 20,
},
.set_control = setcontrast
},
@@ -737,7 +739,7 @@ static const u8 mi0360_sensor_init[][8] = {
{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
- {0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10},
+ {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
@@ -1277,7 +1279,7 @@ static const u8 soi768_sensor_param1[][8] = {
/* global gain ? : 07 - change with 0x15 at the end */
{0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
{0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
- {0xb1, 0x21, 0x2d, 0x00, 0x02, 0x00, 0x00, 0x10},
+ {0xb1, 0x21, 0x2d, 0x63, 0x03, 0x00, 0x00, 0x10},
/* exposure ? : 0200 - change with 0x1e at the end */
{}
};
@@ -1395,7 +1397,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
return;
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_r: buffer overflow");
+ pr_err("reg_r: buffer overflow\n");
return;
}
#endif
@@ -1408,7 +1410,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
500);
PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1432,7 +1434,7 @@ static void reg_w1(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w1 err %d", ret);
+ pr_err("reg_w1 err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1449,7 +1451,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
value, buffer[0], buffer[1]);
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_w: buffer overflow");
+ pr_err("reg_w: buffer overflow\n");
return;
}
#endif
@@ -1462,7 +1464,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, len,
500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1502,7 +1504,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
gspca_dev->usb_buf, 8,
500);
if (ret < 0) {
- err("i2c_w1 err %d", ret);
+ pr_err("i2c_w1 err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1527,7 +1529,7 @@ static void i2c_w8(struct gspca_dev *gspca_dev,
500);
msleep(2);
if (ret < 0) {
- err("i2c_w8 err %d", ret);
+ pr_err("i2c_w8 err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -1591,7 +1593,7 @@ static void hv7131r_probe(struct gspca_dev *gspca_dev)
PDEBUG(D_PROBE, "Sensor HV7131R found");
return;
}
- warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x",
+ pr_warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x\n",
gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
gspca_dev->usb_buf[2]);
}
@@ -1710,7 +1712,7 @@ static void ov7648_probe(struct gspca_dev *gspca_dev)
sd->sensor = SENSOR_PO1030;
return;
}
- err("Unknown sensor %04x", val);
+ pr_err("Unknown sensor %04x\n", val);
}
/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
@@ -1748,7 +1750,7 @@ static void po2030n_probe(struct gspca_dev *gspca_dev)
PDEBUG(D_PROBE, "Sensor po2030n");
/* sd->sensor = SENSOR_PO2030N; */
} else {
- err("Unknown sensor ID %04x", val);
+ pr_err("Unknown sensor ID %04x\n", val);
}
}
@@ -2006,8 +2008,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
case SENSOR_OM6802:
expo = brightness << 2;
sd->exposure = setexposure(gspca_dev, expo);
- k2 = brightness >> 3;
- break;
+ return; /* Y offset already set */
}
reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */
@@ -2019,13 +2020,13 @@ static void setcontrast(struct gspca_dev *gspca_dev)
u8 k2;
u8 contrast[6];
- k2 = sd->ctrls[CONTRAST].val * 0x30 / (CONTRAST_MAX + 1)
- + 0x10; /* 10..40 */
+ k2 = sd->ctrls[CONTRAST].val * 37 / (CONTRAST_MAX + 1)
+ + 37; /* 37..73 */
contrast[0] = (k2 + 1) / 2; /* red */
contrast[1] = 0;
contrast[2] = k2; /* green */
contrast[3] = 0;
- contrast[4] = (k2 + 1) / 5; /* blue */
+ contrast[4] = k2 / 5; /* blue */
contrast[5] = 0;
reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
}
@@ -2507,9 +2508,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
break;
case SENSOR_HV7131R:
case SENSOR_MI0360:
- if (mode)
- reg01 |= SYS_SEL_48M; /* 320x240: clk 48Mhz */
- else
+ if (!mode)
reg01 &= ~SYS_SEL_48M; /* 640x480: clk 24Mhz */
reg17 &= ~MCK_SIZE_MASK;
reg17 |= 0x01; /* clock / 1 */
diff --git a/drivers/media/video/gspca/spca1528.c b/drivers/media/video/gspca/spca1528.c
index 76c006b2bc83..695673106e76 100644
--- a/drivers/media/video/gspca/spca1528.c
+++ b/drivers/media/video/gspca/spca1528.c
@@ -1,7 +1,7 @@
/*
* spca1528 subdriver
*
- * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
+ * Copyright (C) 2010-2011 Jean-Francois Moine (http://moinejf.free.fr)
*
* 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,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca1528"
#include "gspca.h"
@@ -171,7 +173,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
gspca_dev->usb_buf[0]);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -193,7 +195,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
value, index,
NULL, 0, 500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -217,21 +219,23 @@ static void reg_wb(struct gspca_dev *gspca_dev,
value, index,
gspca_dev->usb_buf, 1, 500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
static void wait_status_0(struct gspca_dev *gspca_dev)
{
- int i;
+ int i, w;
- i = 20;
+ i = 16;
+ w = 0;
do {
reg_r(gspca_dev, 0x21, 0x0000, 1);
if (gspca_dev->usb_buf[0] == 0)
return;
- msleep(30);
+ w += 15;
+ msleep(w);
} while (--i > 0);
PDEBUG(D_ERR, "wait_status_0 timeout");
gspca_dev->usb_err = -ETIME;
@@ -307,8 +311,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->color = COLOR_DEF;
sd->sharpness = SHARPNESS_DEF;
- gspca_dev->nbalt = 4; /* use alternate setting 3 */
-
return 0;
}
@@ -347,8 +349,12 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
reg_r(gspca_dev, 0x25, 0x0004, 1);
- reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);
+ reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06); /* 420 */
reg_r(gspca_dev, 0x27, 0x0000, 1);
+
+/* not useful..
+ gspca_dev->alt = 4; * use alternate setting 3 */
+
return gspca_dev->usb_err;
}
@@ -361,8 +367,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x22); /* JPEG 411 */
- /* the JPEG quality seems to be 82% */
- jpeg_set_qual(sd->jpeg_hdr, 82);
+ /* the JPEG quality shall be 85% */
+ jpeg_set_qual(sd->jpeg_hdr, 85);
/* set the controls */
setbrightness(gspca_dev);
@@ -377,7 +383,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* start the capture */
wait_status_0(gspca_dev);
- reg_w(gspca_dev, 0x31, 0x0000, 0x0004);
+ reg_w(gspca_dev, 0x31, 0x0000, 0x0004); /* start request */
wait_status_1(gspca_dev);
wait_status_0(gspca_dev);
msleep(200);
@@ -390,7 +396,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
{
/* stop the capture */
wait_status_0(gspca_dev);
- reg_w(gspca_dev, 0x31, 0x0000, 0x0000);
+ reg_w(gspca_dev, 0x31, 0x0000, 0x0000); /* stop request */
wait_status_1(gspca_dev);
wait_status_0(gspca_dev);
}
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
index 3e76951e3c19..bb82c94ece14 100644
--- a/drivers/media/video/gspca/spca500.c
+++ b/drivers/media/video/gspca/spca500.c
@@ -19,6 +19,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca500"
#include "gspca.h"
@@ -396,7 +398,7 @@ static int reg_w(struct gspca_dev *gspca_dev,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index, NULL, 0, 500);
if (ret < 0)
- err("reg write: error %d", ret);
+ pr_err("reg write: error %d\n", ret);
return ret;
}
@@ -418,7 +420,7 @@ static int reg_r_12(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, length,
500); /* timeout */
if (ret < 0) {
- err("reg_r_12 err %d", ret);
+ pr_err("reg_r_12 err %d\n", ret);
return ret;
}
return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c
index f7ef282cc600..7aaac72aee91 100644
--- a/drivers/media/video/gspca/spca501.c
+++ b/drivers/media/video/gspca/spca501.c
@@ -19,6 +19,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca501"
#include "gspca.h"
@@ -1852,7 +1854,7 @@ static int reg_write(struct usb_device *dev,
PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x",
req, index, value);
if (ret < 0)
- err("reg write: error %d", ret);
+ pr_err("reg write: error %d\n", ret);
return ret;
}
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
index e5bf865147d7..16722dc60394 100644
--- a/drivers/media/video/gspca/spca505.c
+++ b/drivers/media/video/gspca/spca505.c
@@ -19,6 +19,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca505"
#include "gspca.h"
@@ -578,7 +580,7 @@ static int reg_write(struct usb_device *dev,
PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
req, index, value, ret);
if (ret < 0)
- err("reg write: error %d", ret);
+ pr_err("reg write: error %d\n", ret);
return ret;
}
@@ -685,8 +687,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
return ret;
}
if (ret != 0x0101) {
- err("After vector read returns 0x%04x should be 0x0101",
- ret);
+ pr_err("After vector read returns 0x%04x should be 0x0101\n",
+ ret);
}
ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
index 9d0b46027b93..a44fe3d25965 100644
--- a/drivers/media/video/gspca/spca508.c
+++ b/drivers/media/video/gspca/spca508.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca508"
#include "gspca.h"
@@ -1275,7 +1277,7 @@ static int reg_write(struct usb_device *dev,
PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
index, value);
if (ret < 0)
- err("reg write: error %d", ret);
+ pr_err("reg write: error %d\n", ret);
return ret;
}
@@ -1297,7 +1299,7 @@ static int reg_read(struct gspca_dev *gspca_dev,
PDEBUG(D_USBI, "reg read i:%04x --> %02x",
index, gspca_dev->usb_buf[0]);
if (ret < 0) {
- err("reg_read err %d", ret);
+ pr_err("reg_read err %d\n", ret);
return ret;
}
return gspca_dev->usb_buf[0];
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index e836e778dfb6..c82fd53cef95 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "spca561"
#include <linux/input.h>
@@ -315,7 +317,7 @@ static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
value, index, NULL, 0, 500);
PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
if (ret < 0)
- err("reg write: error %d", ret);
+ pr_err("reg write: error %d\n", ret);
}
static void write_vector(struct gspca_dev *gspca_dev,
diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c
index 5ba96aff2252..df805f798282 100644
--- a/drivers/media/video/gspca/sq905.c
+++ b/drivers/media/video/gspca/sq905.c
@@ -33,6 +33,8 @@
* drivers.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sq905"
#include <linux/workqueue.h>
@@ -123,8 +125,7 @@ static int sq905_command(struct gspca_dev *gspca_dev, u16 index)
SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
SQ905_CMD_TIMEOUT);
if (ret < 0) {
- err("%s: usb_control_msg failed (%d)",
- __func__, ret);
+ pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
return ret;
}
@@ -135,8 +136,7 @@ static int sq905_command(struct gspca_dev *gspca_dev, u16 index)
SQ905_PING, 0, gspca_dev->usb_buf, 1,
SQ905_CMD_TIMEOUT);
if (ret < 0) {
- err("%s: usb_control_msg failed 2 (%d)",
- __func__, ret);
+ pr_err("%s: usb_control_msg failed 2 (%d)\n", __func__, ret);
return ret;
}
@@ -158,7 +158,7 @@ static int sq905_ack_frame(struct gspca_dev *gspca_dev)
SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1,
SQ905_CMD_TIMEOUT);
if (ret < 0) {
- err("%s: usb_control_msg failed (%d)", __func__, ret);
+ pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
return ret;
}
@@ -186,7 +186,7 @@ sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
if (need_lock)
mutex_unlock(&gspca_dev->usb_lock);
if (ret < 0) {
- err("%s: usb_control_msg failed (%d)", __func__, ret);
+ pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
return ret;
}
ret = usb_bulk_msg(gspca_dev->dev,
@@ -195,8 +195,7 @@ sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
/* successful, it returns 0, otherwise negative */
if (ret < 0 || act_len != size) {
- err("bulk read fail (%d) len %d/%d",
- ret, act_len, size);
+ pr_err("bulk read fail (%d) len %d/%d\n", ret, act_len, size);
return -EIO;
}
return 0;
@@ -226,7 +225,7 @@ static void sq905_dostream(struct work_struct *work)
buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
if (!buffer) {
- err("Couldn't allocate USB buffer");
+ pr_err("Couldn't allocate USB buffer\n");
goto quit_stream;
}
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
index 457563b7a71b..c2c056056e08 100644
--- a/drivers/media/video/gspca/sq905c.c
+++ b/drivers/media/video/gspca/sq905c.c
@@ -27,6 +27,8 @@
* and may contain code fragments from it.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sq905c"
#include <linux/workqueue.h>
@@ -95,8 +97,7 @@ static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
command, index, NULL, 0,
SQ905C_CMD_TIMEOUT);
if (ret < 0) {
- err("%s: usb_control_msg failed (%d)",
- __func__, ret);
+ pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
return ret;
}
@@ -115,8 +116,7 @@ static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index,
command, index, gspca_dev->usb_buf, size,
SQ905C_CMD_TIMEOUT);
if (ret < 0) {
- err("%s: usb_control_msg failed (%d)",
- __func__, ret);
+ pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
return ret;
}
@@ -146,7 +146,7 @@ static void sq905c_dostream(struct work_struct *work)
buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
if (!buffer) {
- err("Couldn't allocate USB buffer");
+ pr_err("Couldn't allocate USB buffer\n");
goto quit_stream;
}
diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c
index 8215d5dcd456..e4255b4905e7 100644
--- a/drivers/media/video/gspca/sq930x.c
+++ b/drivers/media/video/gspca/sq930x.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sq930x"
#include "gspca.h"
@@ -468,7 +470,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
value, 0, gspca_dev->usb_buf, len,
500);
if (ret < 0) {
- err("reg_r %04x failed %d", value, ret);
+ pr_err("reg_r %04x failed %d\n", value, ret);
gspca_dev->usb_err = ret;
}
}
@@ -488,7 +490,7 @@ static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
500);
msleep(30);
if (ret < 0) {
- err("reg_w %04x %04x failed %d", value, index, ret);
+ pr_err("reg_w %04x %04x failed %d\n", value, index, ret);
gspca_dev->usb_err = ret;
}
}
@@ -511,7 +513,7 @@ static void reg_wb(struct gspca_dev *gspca_dev, u16 value, u16 index,
1000);
msleep(30);
if (ret < 0) {
- err("reg_wb %04x %04x failed %d", value, index, ret);
+ pr_err("reg_wb %04x %04x failed %d\n", value, index, ret);
gspca_dev->usb_err = ret;
}
}
@@ -556,7 +558,7 @@ static void i2c_write(struct sd *sd,
gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
500);
if (ret < 0) {
- err("i2c_write failed %d", ret);
+ pr_err("i2c_write failed %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -575,7 +577,7 @@ static void ucbus_write(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if ((batchsize - 1) * 3 > USB_BUF_SZ) {
- err("Bug: usb_buf overflow");
+ pr_err("Bug: usb_buf overflow\n");
gspca_dev->usb_err = -ENOMEM;
return;
}
@@ -612,7 +614,7 @@ static void ucbus_write(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
500);
if (ret < 0) {
- err("ucbus_write failed %d", ret);
+ pr_err("ucbus_write failed %d\n", ret);
gspca_dev->usb_err = ret;
return;
}
@@ -688,7 +690,7 @@ static void cmos_probe(struct gspca_dev *gspca_dev)
break;
}
if (i >= ARRAY_SIZE(probe_order)) {
- err("Unknown sensor");
+ pr_err("Unknown sensor\n");
gspca_dev->usb_err = -EINVAL;
return;
}
@@ -696,7 +698,8 @@ static void cmos_probe(struct gspca_dev *gspca_dev)
switch (sd->sensor) {
case SENSOR_OV7660:
case SENSOR_OV9630:
- err("Sensor %s not yet treated", sensor_tb[sd->sensor].name);
+ pr_err("Sensor %s not yet treated\n",
+ sensor_tb[sd->sensor].name);
gspca_dev->usb_err = -EINVAL;
break;
}
@@ -1091,7 +1094,7 @@ static void sd_dq_callback(struct gspca_dev *gspca_dev)
gspca_dev->cam.bulk_nurbs = 1;
ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC);
if (ret < 0)
- err("sd_dq_callback() err %d", ret);
+ pr_err("sd_dq_callback() err %d\n", ret);
/* wait a little time, otherwise the webcam crashes */
msleep(100);
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
index 763747700f10..42a7a28a6c8b 100644
--- a/drivers/media/video/gspca/stk014.c
+++ b/drivers/media/video/gspca/stk014.c
@@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "stk014"
#include "gspca.h"
@@ -137,7 +139,7 @@ static u8 reg_r(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
return 0;
}
@@ -162,7 +164,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
0,
500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -192,7 +194,7 @@ static void rcv_val(struct gspca_dev *gspca_dev,
&alen,
500); /* timeout in milliseconds */
if (ret < 0) {
- err("rcv_val err %d", ret);
+ pr_err("rcv_val err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -235,7 +237,7 @@ static void snd_val(struct gspca_dev *gspca_dev,
&alen,
500); /* timeout in milliseconds */
if (ret < 0) {
- err("snd_val err %d", ret);
+ pr_err("snd_val err %d\n", ret);
gspca_dev->usb_err = ret;
} else {
if (ads == 0x003f08) {
@@ -315,7 +317,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
ret = reg_r(gspca_dev, 0x0740);
if (gspca_dev->usb_err >= 0) {
if (ret != 0xff) {
- err("init reg: 0x%02x", ret);
+ pr_err("init reg: 0x%02x\n", ret);
gspca_dev->usb_err = -EIO;
}
}
@@ -349,8 +351,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
gspca_dev->iface,
gspca_dev->alt);
if (ret < 0) {
- err("set intf %d %d failed",
- gspca_dev->iface, gspca_dev->alt);
+ pr_err("set intf %d %d failed\n",
+ gspca_dev->iface, gspca_dev->alt);
gspca_dev->usb_err = ret;
goto out;
}
diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c
index e2ef41cf72d7..4dcc7e37f9fd 100644
--- a/drivers/media/video/gspca/stv0680.c
+++ b/drivers/media/video/gspca/stv0680.c
@@ -27,6 +27,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "stv0680"
#include "gspca.h"
@@ -79,7 +81,7 @@ static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val,
val, 0, gspca_dev->usb_buf, size, 500);
if ((ret < 0) && (req != 0x0a))
- err("usb_control_msg error %i, request = 0x%x, error = %i",
+ pr_err("usb_control_msg error %i, request = 0x%x, error = %i\n",
set, req, ret);
return ret;
@@ -236,7 +238,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 ||
gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) {
- err("Could not get descriptor 0100.");
+ pr_err("Could not get descriptor 0100\n");
return stv0680_handle_error(gspca_dev, -EIO);
}
diff --git a/drivers/media/video/gspca/stv06xx/Makefile b/drivers/media/video/gspca/stv06xx/Makefile
index 2f3c3a606ce4..5b318faf9aa8 100644
--- a/drivers/media/video/gspca/stv06xx/Makefile
+++ b/drivers/media/video/gspca/stv06xx/Makefile
@@ -6,5 +6,5 @@ gspca_stv06xx-objs := stv06xx.o \
stv06xx_pb0100.o \
stv06xx_st6422.o
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
index abf1658fa33e..b1fca7db1015 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -27,6 +27,8 @@
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/input.h>
#include "stv06xx_sensor.h"
@@ -189,7 +191,7 @@ int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value)
0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH,
STV06XX_URB_MSG_TIMEOUT);
if (err < 0) {
- err("I2C: Read error writing address: %d", err);
+ pr_err("I2C: Read error writing address: %d\n", err);
return err;
}
@@ -213,14 +215,14 @@ static void stv06xx_dump_bridge(struct sd *sd)
int i;
u8 data, buf;
- info("Dumping all stv06xx bridge registers");
+ pr_info("Dumping all stv06xx bridge registers\n");
for (i = 0x1400; i < 0x160f; i++) {
stv06xx_read_bridge(sd, i, &data);
- info("Read 0x%x from address 0x%x", data, i);
+ pr_info("Read 0x%x from address 0x%x\n", data, i);
}
- info("Testing stv06xx bridge registers for writability");
+ pr_info("Testing stv06xx bridge registers for writability\n");
for (i = 0x1400; i < 0x160f; i++) {
stv06xx_read_bridge(sd, i, &data);
buf = data;
@@ -228,12 +230,12 @@ static void stv06xx_dump_bridge(struct sd *sd)
stv06xx_write_bridge(sd, i, 0xff);
stv06xx_read_bridge(sd, i, &data);
if (data == 0xff)
- info("Register 0x%x is read/write", i);
+ pr_info("Register 0x%x is read/write\n", i);
else if (data != buf)
- info("Register 0x%x is read/write,"
- " but only partially", i);
+ pr_info("Register 0x%x is read/write, but only partially\n",
+ i);
else
- info("Register 0x%x is read-only", i);
+ pr_info("Register 0x%x is read-only\n", i);
stv06xx_write_bridge(sd, i, buf);
}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h
index e0f63c51f40d..d270a5981afe 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.h
@@ -37,6 +37,8 @@
#define STV_ISOC_ENDPOINT_ADDR 0x81
+#define STV_R 0x0509
+
#define STV_REG23 0x0423
/* Control registers of the STV0600 ASIC */
@@ -61,7 +63,9 @@
/* Refers to the CIF 352x288 and QCIF 176x144 */
/* 1: 288 lines, 2: 144 lines */
-#define STV_Y_CTRL 0x15c3
+#define STV_Y_CTRL 0x15c3
+
+#define STV_RESET 0x1620
/* 0xa: 352 columns, 0x6: 176 columns */
#define STV_X_CTRL 0x1680
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
index b8156855f2b7..a8698b7a7566 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
@@ -28,6 +28,8 @@
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "stv06xx_hdcs.h"
static const struct ctrl hdcs1x00_ctrl[] = {
@@ -428,7 +430,7 @@ static int hdcs_probe_1x00(struct sd *sd)
if (ret < 0 || sensor != 0x08)
return -ENODEV;
- info("HDCS-1000/1100 sensor detected");
+ pr_info("HDCS-1000/1100 sensor detected\n");
sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
@@ -487,7 +489,7 @@ static int hdcs_probe_1020(struct sd *sd)
if (ret < 0 || sensor != 0x10)
return -ENODEV;
- info("HDCS-1020 sensor detected");
+ pr_info("HDCS-1020 sensor detected\n");
sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
@@ -601,11 +603,11 @@ static int hdcs_dump(struct sd *sd)
{
u16 reg, val;
- info("Dumping sensor registers:");
+ pr_info("Dumping sensor registers:\n");
for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
stv06xx_read_sensor(sd, reg, &val);
- info("reg 0x%02x = 0x%02x", reg, val);
+ pr_info("reg 0x%02x = 0x%02x\n", reg, val);
}
return 0;
}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
index 75a5b9c2f15f..26f14fc4a135 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
@@ -44,6 +44,8 @@
* PB_CFILLIN = R5 = 0x0E (14 dec) : Sets the frame rate
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "stv06xx_pb0100.h"
static const struct ctrl pb0100_ctrl[] = {
@@ -190,7 +192,7 @@ static int pb0100_probe(struct sd *sd)
if (!sensor_settings)
return -ENOMEM;
- info("Photobit pb0100 sensor detected");
+ pr_info("Photobit pb0100 sensor detected\n");
sd->gspca_dev.cam.cam_mode = pb0100_mode;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
index 8a456de4970a..9940e035b3ab 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
@@ -26,6 +26,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "stv06xx_st6422.h"
/* controls */
@@ -136,7 +138,7 @@ static int st6422_probe(struct sd *sd)
if (sd->bridge != BRIDGE_ST6422)
return -ENODEV;
- info("st6422 sensor detected");
+ pr_info("st6422 sensor detected\n");
sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
if (!sensor_settings)
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
index f8398434c328..a5c69d9ebdd4 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
@@ -27,6 +27,8 @@
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "stv06xx_vv6410.h"
static struct v4l2_pix_format vv6410_mode[] = {
@@ -112,7 +114,7 @@ static int vv6410_probe(struct sd *sd)
return -ENODEV;
if (data == 0x19) {
- info("vv6410 sensor detected");
+ pr_info("vv6410 sensor detected\n");
sensor_settings = kmalloc(ARRAY_SIZE(vv6410_ctrl) * sizeof(s32),
GFP_KERNEL);
@@ -138,18 +140,7 @@ static int vv6410_init(struct sd *sd)
s32 *sensor_settings = sd->sensor_priv;
for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
- /* if NULL then len contains single value */
- if (stv_bridge_init[i].data == NULL) {
- err = stv06xx_write_bridge(sd,
- stv_bridge_init[i].start,
- stv_bridge_init[i].len);
- } else {
- int j;
- for (j = 0; j < stv_bridge_init[i].len; j++)
- err = stv06xx_write_bridge(sd,
- stv_bridge_init[i].start + j,
- stv_bridge_init[i].data[j]);
- }
+ stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data);
}
if (err < 0)
@@ -183,15 +174,6 @@ static int vv6410_start(struct sd *sd)
struct cam *cam = &sd->gspca_dev.cam;
u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
- if (priv & VV6410_CROP_TO_QVGA) {
- PDEBUG(D_CONF, "Cropping to QVGA");
- stv06xx_write_sensor(sd, VV6410_XENDH, 320 - 1);
- stv06xx_write_sensor(sd, VV6410_YENDH, 240 - 1);
- } else {
- stv06xx_write_sensor(sd, VV6410_XENDH, 360 - 1);
- stv06xx_write_sensor(sd, VV6410_YENDH, 294 - 1);
- }
-
if (priv & VV6410_SUBSAMPLE) {
PDEBUG(D_CONF, "Enabling subsampling");
stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
@@ -201,8 +183,8 @@ static int vv6410_start(struct sd *sd)
} else {
stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
+ stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00);
- stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
}
/* Turn on LED */
@@ -242,11 +224,11 @@ static int vv6410_dump(struct sd *sd)
u8 i;
int err = 0;
- info("Dumping all vv6410 sensor registers");
+ pr_info("Dumping all vv6410 sensor registers\n");
for (i = 0; i < 0xff && !err; i++) {
u16 data;
err = stv06xx_read_sensor(sd, i, &data);
- info("Register 0x%x contained 0x%x", i, data);
+ pr_info("Register 0x%x contained 0x%x\n", i, data);
}
return (err < 0) ? err : 0;
}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
index 7fe3587f5f71..a25b8873f2e6 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
@@ -211,49 +211,49 @@ const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
/* If NULL, only single value to write, stored in len */
struct stv_init {
- const u8 *data;
- u16 start;
- u8 len;
-};
-
-static const u8 x1500[] = { /* 0x1500 - 0x150f */
- 0x0b, 0xa7, 0xb7, 0x00, 0x00
-};
-
-static const u8 x1536[] = { /* 0x1536 - 0x153b */
- 0x02, 0x00, 0x60, 0x01, 0x20, 0x01
+ u16 addr;
+ u8 data;
};
static const struct stv_init stv_bridge_init[] = {
/* This reg is written twice. Some kind of reset? */
- {NULL, 0x1620, 0x80},
- {NULL, 0x1620, 0x00},
- {NULL, 0x1443, 0x00},
- {NULL, 0x1423, 0x04},
- {x1500, 0x1500, ARRAY_SIZE(x1500)},
- {x1536, 0x1536, ARRAY_SIZE(x1536)},
+ {STV_RESET, 0x80},
+ {STV_RESET, 0x00},
+ {STV_SCAN_RATE, 0x00},
+ {STV_I2C_FLUSH, 0x04},
+ {STV_REG00, 0x0b},
+ {STV_REG01, 0xa7},
+ {STV_REG02, 0xb7},
+ {STV_REG03, 0x00},
+ {STV_REG04, 0x00},
+ {0x1536, 0x02},
+ {0x1537, 0x00},
+ {0x1538, 0x60},
+ {0x1539, 0x01},
+ {0x153a, 0x20},
+ {0x153b, 0x01},
};
static const u8 vv6410_sensor_init[][2] = {
/* Setup registers */
- {VV6410_SETUP0, VV6410_SOFT_RESET},
- {VV6410_SETUP0, VV6410_LOW_POWER_MODE},
+ {VV6410_SETUP0, VV6410_SOFT_RESET},
+ {VV6410_SETUP0, VV6410_LOW_POWER_MODE},
/* Use shuffled read-out mode */
- {VV6410_SETUP1, BIT(6)},
- /* All modes to 1 */
- {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
- {VV6410_PINMAPPING, 0x00},
+ {VV6410_SETUP1, BIT(6)},
+ /* All modes to 1, FST, Fast QCK, Free running QCK, Free running LST, FST will qualify visible pixels */
+ {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
+ {VV6410_PINMAPPING, 0x00},
/* Pre-clock generator divide off */
- {VV6410_DATAFORMAT, BIT(7) | BIT(0)},
+ {VV6410_DATAFORMAT, BIT(7) | BIT(0)},
- {VV6410_CLKDIV, VV6410_CLK_DIV_2},
+ {VV6410_CLKDIV, VV6410_CLK_DIV_2},
/* System registers */
/* Enable voltage doubler */
- {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
- {VV6410_AT0, 0x00},
+ {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
+ {VV6410_AT0, 0x00},
/* Power up audio, differential */
- {VV6410_AT1, BIT(4)|BIT(0)},
+ {VV6410_AT1, BIT(4) | BIT(0)},
};
#endif
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
index 6ec232902183..c8909772435a 100644
--- a/drivers/media/video/gspca/sunplus.c
+++ b/drivers/media/video/gspca/sunplus.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "sunplus"
#include "gspca.h"
@@ -325,7 +327,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
- err("reg_r: buffer overflow");
+ pr_err("reg_r: buffer overflow\n");
return;
}
#endif
@@ -340,7 +342,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
len ? gspca_dev->usb_buf : NULL, len,
500);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -365,7 +367,7 @@ static void reg_w_1(struct gspca_dev *gspca_dev,
gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_w_1 err %d", ret);
+ pr_err("reg_w_1 err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -385,7 +387,7 @@ static void reg_w_riv(struct gspca_dev *gspca_dev,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index, NULL, 0, 500);
if (ret < 0) {
- err("reg_w_riv err %d", ret);
+ pr_err("reg_w_riv err %d\n", ret);
gspca_dev->usb_err = ret;
return;
}
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
index d1d733b9359b..90f0877eb599 100644
--- a/drivers/media/video/gspca/t613.c
+++ b/drivers/media/video/gspca/t613.c
@@ -26,6 +26,8 @@
* Costantino Leandro
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "t613"
#include <linux/slab.h>
@@ -572,7 +574,7 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
if (!tmpbuf) {
- err("Out of memory");
+ pr_err("Out of memory\n");
return;
}
usb_control_msg(gspca_dev->dev,
@@ -598,7 +600,7 @@ static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
} else {
p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
if (!tmpbuf) {
- err("Out of memory");
+ pr_err("Out of memory\n");
return;
}
}
@@ -652,7 +654,7 @@ static void om6802_sensor_init(struct gspca_dev *gspca_dev)
}
byte = reg_r(gspca_dev, 0x0063);
if (byte != 0x17) {
- err("Bad sensor reset %02x", byte);
+ pr_err("Bad sensor reset %02x\n", byte);
/* continue? */
}
@@ -890,7 +892,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
sd->sensor = SENSOR_OM6802;
break;
default:
- err("unknown sensor %04x", sensor_id);
+ pr_err("unknown sensor %04x\n", sensor_id);
return -EINVAL;
}
@@ -905,7 +907,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
break; /* OK */
}
if (i < 0) {
- err("Bad sensor reset %02x", test_byte);
+ pr_err("Bad sensor reset %02x\n", test_byte);
return -EIO;
}
reg_w_buf(gspca_dev, n2, sizeof n2);
diff --git a/drivers/media/video/gspca/topro.c b/drivers/media/video/gspca/topro.c
new file mode 100644
index 000000000000..29596c59837f
--- /dev/null
+++ b/drivers/media/video/gspca/topro.c
@@ -0,0 +1,4989 @@
+/*
+ * Topro TP6800/6810 webcam driver.
+ *
+ * Copyright (C) 2011 Jean-François Moine (http://moinejf.free.fr)
+ * Copyright (C) 2009 Anders Blomdell (anders.blomdell@control.lth.se)
+ * Copyright (C) 2008 Thomas Champagne (lafeuil@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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "gspca.h"
+
+MODULE_DESCRIPTION("Topro TP6800/6810 gspca webcam driver");
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
+ "Anders Blomdell <anders.blomdell@control.lth.se>");
+MODULE_LICENSE("GPL");
+
+static int force_sensor = -1;
+
+/* JPEG header */
+static const u8 jpeg_head[] = {
+ 0xff, 0xd8, /* jpeg */
+
+/* quantization table quality 50% */
+ 0xff, 0xdb, 0x00, 0x84, /* DQT */
+0,
+#define JPEG_QT0_OFFSET 7
+ 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+ 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+ 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+ 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+ 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+ 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+ 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+ 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+1,
+#define JPEG_QT1_OFFSET 72
+ 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+ 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+
+ /* Define Huffman table (thanks to Thomas Kaiser) */
+ 0xff, 0xc4, 0x01, 0x5e,
+ 0x00, 0x00, 0x02, 0x03,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
+ 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+ 0x07, 0x05, 0x04, 0x06, 0x01, 0x00, 0x00, 0x57,
+ 0x01, 0x02, 0x03, 0x00, 0x11, 0x04, 0x12, 0x21,
+ 0x31, 0x13, 0x41, 0x51, 0x61, 0x05, 0x22, 0x32,
+ 0x14, 0x71, 0x81, 0x91, 0x15, 0x23, 0x42, 0x52,
+ 0x62, 0xa1, 0xb1, 0x06, 0x33, 0x72, 0xc1, 0xd1,
+ 0x24, 0x43, 0x53, 0x82, 0x16, 0x34, 0x92, 0xa2,
+ 0xe1, 0xf1, 0xf0, 0x07, 0x08, 0x17, 0x18, 0x25,
+ 0x26, 0x27, 0x28, 0x35, 0x36, 0x37, 0x38, 0x44,
+ 0x45, 0x46, 0x47, 0x48, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x73,
+ 0x74, 0x75, 0x76, 0x77, 0x78, 0x83, 0x84, 0x85,
+ 0x86, 0x87, 0x88, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2,
+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5,
+ 0xe6, 0xe7, 0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
+ 0xf7, 0xf8, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0x09, 0x11, 0x00, 0x02,
+ 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
+ 0x04, 0x06, 0x01, 0x00, 0x00, 0x57, 0x00, 0x01,
+ 0x11, 0x02, 0x21, 0x03, 0x12, 0x31, 0x41, 0x13,
+ 0x22, 0x51, 0x61, 0x04, 0x32, 0x71, 0x05, 0x14,
+ 0x23, 0x42, 0x33, 0x52, 0x81, 0x91, 0xa1, 0xb1,
+ 0xf0, 0x06, 0x15, 0xc1, 0xd1, 0xe1, 0x24, 0x43,
+ 0x62, 0xf1, 0x16, 0x25, 0x34, 0x53, 0x72, 0x82,
+ 0x92, 0x07, 0x08, 0x17, 0x18, 0x26, 0x27, 0x28,
+ 0x35, 0x36, 0x37, 0x38, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x63, 0x64,
+ 0x65, 0x66, 0x67, 0x68, 0x73, 0x74, 0x75, 0x76,
+ 0x77, 0x78, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+ 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xff, 0xc0, 0x00, 0x11, /* SOF0 (start of frame 0 */
+ 0x08, /* data precision */
+#define JPEG_HEIGHT_OFFSET 493
+ 0x01, 0xe0, /* height */
+ 0x02, 0x80, /* width */
+ 0x03, /* component number */
+ 0x01,
+ 0x21, /* samples Y = jpeg 422 */
+ 0x00, /* quant Y */
+ 0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */
+ 0x03, 0x11, 0x01,
+
+ 0xff, 0xda, 0x00, 0x0c, /* SOS (start of scan) */
+ 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+#define JPEG_HDR_SZ 521
+};
+
+enum e_ctrl {
+ EXPOSURE,
+ QUALITY,
+ SHARPNESS,
+ RGAIN,
+ GAIN,
+ BGAIN,
+ GAMMA,
+ AUTOGAIN,
+ NCTRLS /* number of controls */
+};
+
+#define AUTOGAIN_DEF 1
+
+struct sd {
+ struct gspca_dev gspca_dev; /* !! must be the first item */
+
+ struct gspca_ctrl ctrls[NCTRLS];
+
+ u8 framerate;
+ u8 quality; /* webcam current JPEG quality (0..16) */
+ s8 ag_cnt; /* autogain / start counter for tp6810 */
+#define AG_CNT_START 13 /* check gain every N frames */
+
+ u8 bridge;
+ u8 sensor;
+
+ u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+enum bridges {
+ BRIDGE_TP6800,
+ BRIDGE_TP6810,
+};
+
+enum sensors {
+ SENSOR_CX0342,
+ SENSOR_SOI763A, /* ~= ov7630 / ov7648 */
+ NSENSORS
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+ {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240 * 4 / 8 + 590,
+ .colorspace = V4L2_COLORSPACE_JPEG},
+ {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ .bytesperline = 640,
+ .sizeimage = 640 * 480 * 3 / 8 + 590,
+ .colorspace = V4L2_COLORSPACE_JPEG}
+};
+
+/*
+ * JPEG quality
+ * index: webcam compression
+ * value: JPEG quality in %
+ */
+static const u8 jpeg_q[17] = {
+ 88, 77, 67, 57, 55, 55, 45, 45, 36, 36, 30, 30, 26, 26, 22, 22, 94
+};
+
+#define BULK_OUT_SIZE 0x20
+#if BULK_OUT_SIZE > USB_BUF_SZ
+#error "USB buffer too small"
+#endif
+
+static const u8 rates[] = {30, 20, 15, 10, 7, 5};
+static const struct framerates framerates[] = {
+ {
+ .rates = rates,
+ .nrates = ARRAY_SIZE(rates)
+ },
+ {
+ .rates = rates,
+ .nrates = ARRAY_SIZE(rates)
+ }
+};
+static const u8 rates_6810[] = {30, 15, 10, 7, 5};
+static const struct framerates framerates_6810[] = {
+ {
+ .rates = rates_6810,
+ .nrates = ARRAY_SIZE(rates_6810)
+ },
+ {
+ .rates = rates_6810,
+ .nrates = ARRAY_SIZE(rates_6810)
+ }
+};
+
+/*
+ * webcam quality in %
+ * the last value is the ultra fine quality
+ */
+
+/* TP6800 register offsets */
+#define TP6800_R10_SIF_TYPE 0x10
+#define TP6800_R11_SIF_CONTROL 0x11
+#define TP6800_R12_SIF_ADDR_S 0x12
+#define TP6800_R13_SIF_TX_DATA 0x13
+#define TP6800_R14_SIF_RX_DATA 0x14
+#define TP6800_R15_GPIO_PU 0x15
+#define TP6800_R16_GPIO_PD 0x16
+#define TP6800_R17_GPIO_IO 0x17
+#define TP6800_R18_GPIO_DATA 0x18
+#define TP6800_R19_SIF_ADDR_S2 0x19
+#define TP6800_R1A_SIF_TX_DATA2 0x1a
+#define TP6800_R1B_SIF_RX_DATA2 0x1b
+#define TP6800_R21_ENDP_1_CTL 0x21
+#define TP6800_R2F_TIMING_CFG 0x2f
+#define TP6800_R30_SENSOR_CFG 0x30
+#define TP6800_R31_PIXEL_START 0x31
+#define TP6800_R32_PIXEL_END_L 0x32
+#define TP6800_R33_PIXEL_END_H 0x33
+#define TP6800_R34_LINE_START 0x34
+#define TP6800_R35_LINE_END_L 0x35
+#define TP6800_R36_LINE_END_H 0x36
+#define TP6800_R37_FRONT_DARK_ST 0x37
+#define TP6800_R38_FRONT_DARK_END 0x38
+#define TP6800_R39_REAR_DARK_ST_L 0x39
+#define TP6800_R3A_REAR_DARK_ST_H 0x3a
+#define TP6800_R3B_REAR_DARK_END_L 0x3b
+#define TP6800_R3C_REAR_DARK_END_H 0x3c
+#define TP6800_R3D_HORIZ_DARK_LINE_L 0x3d
+#define TP6800_R3E_HORIZ_DARK_LINE_H 0x3e
+#define TP6800_R3F_FRAME_RATE 0x3f
+#define TP6800_R50 0x50
+#define TP6800_R51 0x51
+#define TP6800_R52 0x52
+#define TP6800_R53 0x53
+#define TP6800_R54_DARK_CFG 0x54
+#define TP6800_R55_GAMMA_R 0x55
+#define TP6800_R56_GAMMA_G 0x56
+#define TP6800_R57_GAMMA_B 0x57
+#define TP6800_R5C_EDGE_THRLD 0x5c
+#define TP6800_R5D_DEMOSAIC_CFG 0x5d
+#define TP6800_R78_FORMAT 0x78
+#define TP6800_R79_QUALITY 0x79
+#define TP6800_R7A_BLK_THRLD 0x7a
+
+/* CX0342 register offsets */
+
+#define CX0342_SENSOR_ID 0x00
+#define CX0342_VERSION_NO 0x01
+#define CX0342_ORG_X_L 0x02
+#define CX0342_ORG_X_H 0x03
+#define CX0342_ORG_Y_L 0x04
+#define CX0342_ORG_Y_H 0x05
+#define CX0342_STOP_X_L 0x06
+#define CX0342_STOP_X_H 0x07
+#define CX0342_STOP_Y_L 0x08
+#define CX0342_STOP_Y_H 0x09
+#define CX0342_FRAME_WIDTH_L 0x0a
+#define CX0342_FRAME_WIDTH_H 0x0b
+#define CX0342_FRAME_HEIGH_L 0x0c
+#define CX0342_FRAME_HEIGH_H 0x0d
+#define CX0342_EXPO_LINE_L 0x10
+#define CX0342_EXPO_LINE_H 0x11
+#define CX0342_EXPO_CLK_L 0x12
+#define CX0342_EXPO_CLK_H 0x13
+#define CX0342_RAW_GRGAIN_L 0x14
+#define CX0342_RAW_GRGAIN_H 0x15
+#define CX0342_RAW_GBGAIN_L 0x16
+#define CX0342_RAW_GBGAIN_H 0x17
+#define CX0342_RAW_RGAIN_L 0x18
+#define CX0342_RAW_RGAIN_H 0x19
+#define CX0342_RAW_BGAIN_L 0x1a
+#define CX0342_RAW_BGAIN_H 0x1b
+#define CX0342_GLOBAL_GAIN 0x1c
+#define CX0342_SYS_CTRL_0 0x20
+#define CX0342_SYS_CTRL_1 0x21
+#define CX0342_SYS_CTRL_2 0x22
+#define CX0342_BYPASS_MODE 0x23
+#define CX0342_SYS_CTRL_3 0x24
+#define CX0342_TIMING_EN 0x25
+#define CX0342_OUTPUT_CTRL 0x26
+#define CX0342_AUTO_ADC_CALIB 0x27
+#define CX0342_SYS_CTRL_4 0x28
+#define CX0342_ADCGN 0x30
+#define CX0342_SLPCR 0x31
+#define CX0342_SLPFN_LO 0x32
+#define CX0342_ADC_CTL 0x33
+#define CX0342_LVRST_BLBIAS 0x34
+#define CX0342_VTHSEL 0x35
+#define CX0342_RAMP_RIV 0x36
+#define CX0342_LDOSEL 0x37
+#define CX0342_CLOCK_GEN 0x40
+#define CX0342_SOFT_RESET 0x41
+#define CX0342_PLL 0x42
+#define CX0342_DR_ENH_PULSE_OFFSET_L 0x43
+#define CX0342_DR_ENH_PULSE_OFFSET_H 0x44
+#define CX0342_DR_ENH_PULSE_POS_L 0x45
+#define CX0342_DR_ENH_PULSE_POS_H 0x46
+#define CX0342_DR_ENH_PULSE_WIDTH 0x47
+#define CX0342_AS_CURRENT_CNT_L 0x48
+#define CX0342_AS_CURRENT_CNT_H 0x49
+#define CX0342_AS_PREVIOUS_CNT_L 0x4a
+#define CX0342_AS_PREVIOUS_CNT_H 0x4b
+#define CX0342_SPV_VALUE_L 0x4c
+#define CX0342_SPV_VALUE_H 0x4d
+#define CX0342_GPXLTHD_L 0x50
+#define CX0342_GPXLTHD_H 0x51
+#define CX0342_RBPXLTHD_L 0x52
+#define CX0342_RBPXLTHD_H 0x53
+#define CX0342_PLANETHD_L 0x54
+#define CX0342_PLANETHD_H 0x55
+#define CX0342_ROWDARK_TH 0x56
+#define CX0342_ROWDARK_TOL 0x57
+#define CX0342_RB_GAP_L 0x58
+#define CX0342_RB_GAP_H 0x59
+#define CX0342_G_GAP_L 0x5a
+#define CX0342_G_GAP_H 0x5b
+#define CX0342_AUTO_ROW_DARK 0x60
+#define CX0342_MANUAL_DARK_VALUE 0x61
+#define CX0342_GB_DARK_OFFSET 0x62
+#define CX0342_GR_DARK_OFFSET 0x63
+#define CX0342_RED_DARK_OFFSET 0x64
+#define CX0342_BLUE_DARK_OFFSET 0x65
+#define CX0342_DATA_SCALING_MULTI 0x66
+#define CX0342_AUTOD_Q_FRAME 0x67
+#define CX0342_AUTOD_ALLOW_VARI 0x68
+#define CX0342_AUTO_DARK_VALUE_L 0x69
+#define CX0342_AUTO_DARK_VALUE_H 0x6a
+#define CX0342_IO_CTRL_0 0x70
+#define CX0342_IO_CTRL_1 0x71
+#define CX0342_IO_CTRL_2 0x72
+#define CX0342_IDLE_CTRL 0x73
+#define CX0342_TEST_MODE 0x74
+#define CX0342_FRAME_FIX_DATA_TEST 0x75
+#define CX0342_FRAME_CNT_TEST 0x76
+#define CX0342_RST_OVERFLOW_L 0x80
+#define CX0342_RST_OVERFLOW_H 0x81
+#define CX0342_RST_UNDERFLOW_L 0x82
+#define CX0342_RST_UNDERFLOW_H 0x83
+#define CX0342_DATA_OVERFLOW_L 0x84
+#define CX0342_DATA_OVERFLOW_H 0x85
+#define CX0342_DATA_UNDERFLOW_L 0x86
+#define CX0342_DATA_UNDERFLOW_H 0x87
+#define CX0342_CHANNEL_0_0_L_irst 0x90
+#define CX0342_CHANNEL_0_0_H_irst 0x91
+#define CX0342_CHANNEL_0_1_L_irst 0x92
+#define CX0342_CHANNEL_0_1_H_irst 0x93
+#define CX0342_CHANNEL_0_2_L_irst 0x94
+#define CX0342_CHANNEL_0_2_H_irst 0x95
+#define CX0342_CHANNEL_0_3_L_irst 0x96
+#define CX0342_CHANNEL_0_3_H_irst 0x97
+#define CX0342_CHANNEL_0_4_L_irst 0x98
+#define CX0342_CHANNEL_0_4_H_irst 0x99
+#define CX0342_CHANNEL_0_5_L_irst 0x9a
+#define CX0342_CHANNEL_0_5_H_irst 0x9b
+#define CX0342_CHANNEL_0_6_L_irst 0x9c
+#define CX0342_CHANNEL_0_6_H_irst 0x9d
+#define CX0342_CHANNEL_0_7_L_irst 0x9e
+#define CX0342_CHANNEL_0_7_H_irst 0x9f
+#define CX0342_CHANNEL_1_0_L_itx 0xa0
+#define CX0342_CHANNEL_1_0_H_itx 0xa1
+#define CX0342_CHANNEL_1_1_L_itx 0xa2
+#define CX0342_CHANNEL_1_1_H_itx 0xa3
+#define CX0342_CHANNEL_1_2_L_itx 0xa4
+#define CX0342_CHANNEL_1_2_H_itx 0xa5
+#define CX0342_CHANNEL_1_3_L_itx 0xa6
+#define CX0342_CHANNEL_1_3_H_itx 0xa7
+#define CX0342_CHANNEL_1_4_L_itx 0xa8
+#define CX0342_CHANNEL_1_4_H_itx 0xa9
+#define CX0342_CHANNEL_1_5_L_itx 0xaa
+#define CX0342_CHANNEL_1_5_H_itx 0xab
+#define CX0342_CHANNEL_1_6_L_itx 0xac
+#define CX0342_CHANNEL_1_6_H_itx 0xad
+#define CX0342_CHANNEL_1_7_L_itx 0xae
+#define CX0342_CHANNEL_1_7_H_itx 0xaf
+#define CX0342_CHANNEL_2_0_L_iwl 0xb0
+#define CX0342_CHANNEL_2_0_H_iwl 0xb1
+#define CX0342_CHANNEL_2_1_L_iwl 0xb2
+#define CX0342_CHANNEL_2_1_H_iwl 0xb3
+#define CX0342_CHANNEL_2_2_L_iwl 0xb4
+#define CX0342_CHANNEL_2_2_H_iwl 0xb5
+#define CX0342_CHANNEL_2_3_L_iwl 0xb6
+#define CX0342_CHANNEL_2_3_H_iwl 0xb7
+#define CX0342_CHANNEL_2_4_L_iwl 0xb8
+#define CX0342_CHANNEL_2_4_H_iwl 0xb9
+#define CX0342_CHANNEL_2_5_L_iwl 0xba
+#define CX0342_CHANNEL_2_5_H_iwl 0xbb
+#define CX0342_CHANNEL_2_6_L_iwl 0xbc
+#define CX0342_CHANNEL_2_6_H_iwl 0xbd
+#define CX0342_CHANNEL_2_7_L_iwl 0xbe
+#define CX0342_CHANNEL_2_7_H_iwl 0xbf
+#define CX0342_CHANNEL_3_0_L_ensp 0xc0
+#define CX0342_CHANNEL_3_0_H_ensp 0xc1
+#define CX0342_CHANNEL_3_1_L_ensp 0xc2
+#define CX0342_CHANNEL_3_1_H_ensp 0xc3
+#define CX0342_CHANNEL_3_2_L_ensp 0xc4
+#define CX0342_CHANNEL_3_2_H_ensp 0xc5
+#define CX0342_CHANNEL_3_3_L_ensp 0xc6
+#define CX0342_CHANNEL_3_3_H_ensp 0xc7
+#define CX0342_CHANNEL_3_4_L_ensp 0xc8
+#define CX0342_CHANNEL_3_4_H_ensp 0xc9
+#define CX0342_CHANNEL_3_5_L_ensp 0xca
+#define CX0342_CHANNEL_3_5_H_ensp 0xcb
+#define CX0342_CHANNEL_3_6_L_ensp 0xcc
+#define CX0342_CHANNEL_3_6_H_ensp 0xcd
+#define CX0342_CHANNEL_3_7_L_ensp 0xce
+#define CX0342_CHANNEL_3_7_H_ensp 0xcf
+#define CX0342_CHANNEL_4_0_L_sela 0xd0
+#define CX0342_CHANNEL_4_0_H_sela 0xd1
+#define CX0342_CHANNEL_4_1_L_sela 0xd2
+#define CX0342_CHANNEL_4_1_H_sela 0xd3
+#define CX0342_CHANNEL_5_0_L_intla 0xe0
+#define CX0342_CHANNEL_5_0_H_intla 0xe1
+#define CX0342_CHANNEL_5_1_L_intla 0xe2
+#define CX0342_CHANNEL_5_1_H_intla 0xe3
+#define CX0342_CHANNEL_5_2_L_intla 0xe4
+#define CX0342_CHANNEL_5_2_H_intla 0xe5
+#define CX0342_CHANNEL_5_3_L_intla 0xe6
+#define CX0342_CHANNEL_5_3_H_intla 0xe7
+#define CX0342_CHANNEL_6_0_L_xa_sel_pos 0xf0
+#define CX0342_CHANNEL_6_0_H_xa_sel_pos 0xf1
+#define CX0342_CHANNEL_7_1_L_cds_pos 0xf2
+#define CX0342_CHANNEL_7_1_H_cds_pos 0xf3
+#define CX0342_SENSOR_HEIGHT_L 0xfb
+#define CX0342_SENSOR_HEIGHT_H 0xfc
+#define CX0342_SENSOR_WIDTH_L 0xfd
+#define CX0342_SENSOR_WIDTH_H 0xfe
+#define CX0342_VSYNC_HSYNC_READ 0xff
+
+struct cmd {
+ u8 reg;
+ u8 val;
+};
+
+static const u8 DQT[17][130] = {
+ /* Define quantization table (thanks to Thomas Kaiser) */
+ { /* Quality 0 */
+ 0x00,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x01,
+ 0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0b, 0x06,
+ 0x06, 0x0b, 0x18, 0x10, 0x0e, 0x10, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ },
+ { /* Quality 1 */
+ 0x00,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x01,
+ 0x08, 0x09, 0x09, 0x0c, 0x0a, 0x0c, 0x17, 0x0d,
+ 0x0d, 0x17, 0x31, 0x21, 0x1c, 0x21, 0x31, 0x31,
+ 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+ 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+ 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+ 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+ 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+ 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+ },
+ { /* Quality 2 */
+ 0x00,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04,
+ 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+ 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+ 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+ 0x01,
+ 0x0c, 0x0d, 0x0d, 0x12, 0x0f, 0x12, 0x23, 0x13,
+ 0x13, 0x23, 0x4a, 0x31, 0x2a, 0x31, 0x4a, 0x4a,
+ 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+ 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+ 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+ 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+ 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+ 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+ },
+ { /* Quality 3 */
+ 0x00,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
+ 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x13, 0x13, 0x13, 0x13, 0x13,
+ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
+ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
+ 0x01,
+ 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+ 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ },
+ { /* Quality 4 */
+ 0x00,
+ 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x0a, 0x0a, 0x0a, 0x05, 0x05, 0x05,
+ 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+ 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+ 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+ 0x0a, 0x0a, 0x0a, 0x17, 0x17, 0x17, 0x17, 0x17,
+ 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+ 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+ 0x01,
+ 0x11, 0x16, 0x16, 0x1e, 0x1a, 0x1e, 0x3a, 0x20,
+ 0x20, 0x3a, 0x7b, 0x52, 0x46, 0x52, 0x7b, 0x7b,
+ 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+ 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+ 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+ 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+ 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+ 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+ },
+ { /* Quality 5 */
+ 0x00,
+ 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x06,
+ 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+ 0x01,
+ 0x11, 0x1b, 0x1b, 0x24, 0x1f, 0x24, 0x46, 0x27,
+ 0x27, 0x46, 0x94, 0x63, 0x54, 0x63, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+ },
+ { /* Quality 6 */
+ 0x00,
+ 0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x0e, 0x0e, 0x0e, 0x07, 0x07, 0x07,
+ 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+ 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+ 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+ 0x0e, 0x0e, 0x0e, 0x21, 0x21, 0x21, 0x21, 0x21,
+ 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+ 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+ 0x01,
+ 0x15, 0x1f, 0x1f, 0x2a, 0x24, 0x2a, 0x52, 0x2d,
+ 0x2d, 0x52, 0xad, 0x73, 0x62, 0x73, 0xad, 0xad,
+ 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+ 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+ 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+ 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+ 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+ 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+ },
+ { /* Quality 7 */
+ 0x00,
+ 0x05, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08,
+ 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x26, 0x26, 0x26, 0x26, 0x26,
+ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
+ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
+ 0x01,
+ 0x15, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34,
+ 0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ },
+ { /* Quality 8 */
+ 0x00,
+ 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+ 0x0a, 0x0a, 0x14, 0x14, 0x14, 0x0a, 0x0a, 0x0a,
+ 0x0a, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+ 0x01,
+ 0x19, 0x2d, 0x2d, 0x3c, 0x34, 0x3c, 0x75, 0x41,
+ 0x41, 0x75, 0xf7, 0xa5, 0x8c, 0xa5, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ },
+ { /* Quality 9 */
+ 0x00,
+ 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x39, 0x39, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+ 0x01,
+ 0x19, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e,
+ 0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },
+ { /* Quality 10 */
+ 0x00,
+ 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+ 0x0e, 0x0e, 0x1c, 0x1c, 0x1c, 0x0e, 0x0e, 0x0e,
+ 0x0e, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+ 0x1c, 0x1c, 0x1c, 0x42, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+ 0x01,
+ 0x1d, 0x3f, 0x3f, 0x54, 0x49, 0x54, 0xa4, 0x5b,
+ 0x5b, 0xa4, 0xff, 0xe7, 0xc4, 0xe7, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },
+ { /* Quality 11 */
+ 0x00,
+ 0x07, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10,
+ 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+ 0x01,
+ 0x1d, 0x48, 0x48, 0x60, 0x54, 0x60, 0xbc, 0x68,
+ 0x68, 0xbc, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },
+ { /* Quality 12 */
+ 0x00,
+ 0x08, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x28, 0x28, 0x28, 0x14, 0x14, 0x14,
+ 0x14, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0x28, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+ 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+ 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+ 0x01,
+ 0x22, 0x5a, 0x5a, 0x78, 0x69, 0x78, 0xeb, 0x82,
+ 0x82, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },
+ { /* Quality 13 */
+ 0x00,
+ 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18,
+ 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x72, 0x72, 0x72, 0x72, 0x72,
+ 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+ 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+ 0x01,
+ 0x22, 0x6c, 0x6c, 0x90, 0x7e, 0x90, 0xff, 0x9c,
+ 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },
+ { /* Quality 14 */
+ 0x00,
+ 0x0a, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+ 0x1c, 0x1c, 0x38, 0x38, 0x38, 0x1c, 0x1c, 0x1c,
+ 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+ 0x38, 0x38, 0x38, 0x85, 0x85, 0x85, 0x85, 0x85,
+ 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+ 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+ 0x01,
+ 0x2a, 0x7e, 0x7e, 0xa8, 0x93, 0xa8, 0xff, 0xb6,
+ 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },
+ { /* Quality 15 */
+ 0x00,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20,
+ 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x98, 0x98, 0x98, 0x98, 0x98,
+ 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+ 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+ 0x01,
+ 0x2a, 0x90, 0x90, 0xc0, 0xa8, 0xc0, 0xff, 0xd0,
+ 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },
+ { /* Quality 16-31 */
+ 0x00,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x01,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ }
+};
+
+static const struct cmd tp6810_cx_init_common[] = {
+ {0x1c, 0x00},
+ {TP6800_R10_SIF_TYPE, 0x00},
+ {0x4e, 0x00},
+ {0x4f, 0x00},
+ {TP6800_R50, 0xff},
+ {TP6800_R51, 0x03},
+ {0x00, 0x07},
+ {TP6800_R79_QUALITY, 0x03},
+ {TP6800_R2F_TIMING_CFG, 0x37},
+ {TP6800_R30_SENSOR_CFG, 0x10},
+ {TP6800_R21_ENDP_1_CTL, 0x00},
+ {TP6800_R52, 0x40},
+ {TP6800_R53, 0x40},
+ {TP6800_R54_DARK_CFG, 0x40},
+ {TP6800_R30_SENSOR_CFG, 0x18},
+ {0x4b, 0x00},
+ {TP6800_R3F_FRAME_RATE, 0x83},
+ {TP6800_R79_QUALITY, 0x05},
+ {TP6800_R21_ENDP_1_CTL, 0x00},
+ {0x7c, 0x04},
+ {0x25, 0x14},
+ {0x26, 0x0f},
+ {0x7b, 0x10},
+};
+
+static const struct cmd tp6810_ov_init_common[] = {
+ {0x1c, 0x00},
+ {TP6800_R10_SIF_TYPE, 0x00},
+ {0x4e, 0x00},
+ {0x4f, 0x00},
+ {TP6800_R50, 0xff},
+ {TP6800_R51, 0x03},
+ {0x00, 0x07},
+ {TP6800_R52, 0x40},
+ {TP6800_R53, 0x40},
+ {TP6800_R54_DARK_CFG, 0x40},
+ {TP6800_R79_QUALITY, 0x03},
+ {TP6800_R2F_TIMING_CFG, 0x17},
+ {TP6800_R30_SENSOR_CFG, 0x18},
+ {TP6800_R21_ENDP_1_CTL, 0x00},
+ {TP6800_R3F_FRAME_RATE, 0x86},
+ {0x25, 0x18},
+ {0x26, 0x0f},
+ {0x7b, 0x90},
+};
+
+static const struct cmd tp6810_bridge_start[] = {
+ {0x59, 0x88},
+ {0x5a, 0x0f},
+ {0x5b, 0x4e},
+ {TP6800_R5C_EDGE_THRLD, 0x63},
+ {TP6800_R5D_DEMOSAIC_CFG, 0x00},
+ {0x03, 0x7f},
+ {0x04, 0x80},
+ {0x06, 0x00},
+ {0x00, 0x00},
+};
+
+static const struct cmd tp6810_late_start[] = {
+ {0x7d, 0x01},
+ {0xb0, 0x04},
+ {0xb1, 0x04},
+ {0xb2, 0x04},
+ {0xb3, 0x04},
+ {0xb4, 0x04},
+ {0xb5, 0x04},
+ {0xb6, 0x08},
+ {0xb7, 0x08},
+ {0xb8, 0x04},
+ {0xb9, 0x04},
+ {0xba, 0x04},
+ {0xbb, 0x04},
+ {0xbc, 0x04},
+ {0xbd, 0x08},
+ {0xbe, 0x08},
+ {0xbf, 0x08},
+ {0xc0, 0x04},
+ {0xc1, 0x04},
+ {0xc2, 0x08},
+ {0xc3, 0x08},
+ {0xc4, 0x08},
+ {0xc5, 0x08},
+ {0xc6, 0x08},
+ {0xc7, 0x13},
+ {0xc8, 0x04},
+ {0xc9, 0x08},
+ {0xca, 0x08},
+ {0xcb, 0x08},
+ {0xcc, 0x08},
+ {0xcd, 0x08},
+ {0xce, 0x13},
+ {0xcf, 0x13},
+ {0xd0, 0x08},
+ {0xd1, 0x08},
+ {0xd2, 0x08},
+ {0xd3, 0x08},
+ {0xd4, 0x08},
+ {0xd5, 0x13},
+ {0xd6, 0x13},
+ {0xd7, 0x13},
+ {0xd8, 0x08},
+ {0xd9, 0x08},
+ {0xda, 0x08},
+ {0xdb, 0x08},
+ {0xdc, 0x13},
+ {0xdd, 0x13},
+ {0xde, 0x13},
+ {0xdf, 0x13},
+ {0xe0, 0x08},
+ {0xe1, 0x08},
+ {0xe2, 0x08},
+ {0xe3, 0x13},
+ {0xe4, 0x13},
+ {0xe5, 0x13},
+ {0xe6, 0x13},
+ {0xe7, 0x13},
+ {0xe8, 0x08},
+ {0xe9, 0x08},
+ {0xea, 0x13},
+ {0xeb, 0x13},
+ {0xec, 0x13},
+ {0xed, 0x13},
+ {0xee, 0x13},
+ {0xef, 0x13},
+ {0x7d, 0x02},
+
+ /* later after isoc start */
+ {0x7d, 0x08},
+ {0x7d, 0x00},
+};
+
+static const struct cmd cx0342_timing_seq[] = {
+ {CX0342_CHANNEL_0_1_L_irst, 0x20},
+ {CX0342_CHANNEL_0_2_L_irst, 0x24},
+ {CX0342_CHANNEL_0_2_H_irst, 0x00},
+ {CX0342_CHANNEL_0_3_L_irst, 0x2f},
+ {CX0342_CHANNEL_0_3_H_irst, 0x00},
+ {CX0342_CHANNEL_1_0_L_itx, 0x02},
+ {CX0342_CHANNEL_1_0_H_itx, 0x00},
+ {CX0342_CHANNEL_1_1_L_itx, 0x20},
+ {CX0342_CHANNEL_1_1_H_itx, 0x00},
+ {CX0342_CHANNEL_1_2_L_itx, 0xe4},
+ {CX0342_CHANNEL_1_2_H_itx, 0x00},
+ {CX0342_CHANNEL_1_3_L_itx, 0xee},
+ {CX0342_CHANNEL_1_3_H_itx, 0x00},
+ {CX0342_CHANNEL_2_0_L_iwl, 0x30},
+ {CX0342_CHANNEL_2_0_H_iwl, 0x00},
+ {CX0342_CHANNEL_3_0_L_ensp, 0x34},
+ {CX0342_CHANNEL_3_1_L_ensp, 0xe2},
+ {CX0342_CHANNEL_3_1_H_ensp, 0x00},
+ {CX0342_CHANNEL_3_2_L_ensp, 0xf6},
+ {CX0342_CHANNEL_3_2_H_ensp, 0x00},
+ {CX0342_CHANNEL_3_3_L_ensp, 0xf4},
+ {CX0342_CHANNEL_3_3_H_ensp, 0x02},
+ {CX0342_CHANNEL_4_0_L_sela, 0x26},
+ {CX0342_CHANNEL_4_0_H_sela, 0x00},
+ {CX0342_CHANNEL_4_1_L_sela, 0xe2},
+ {CX0342_CHANNEL_4_1_H_sela, 0x00},
+ {CX0342_CHANNEL_5_0_L_intla, 0x26},
+ {CX0342_CHANNEL_5_1_L_intla, 0x29},
+ {CX0342_CHANNEL_5_2_L_intla, 0xf0},
+ {CX0342_CHANNEL_5_2_H_intla, 0x00},
+ {CX0342_CHANNEL_5_3_L_intla, 0xf3},
+ {CX0342_CHANNEL_5_3_H_intla, 0x00},
+ {CX0342_CHANNEL_6_0_L_xa_sel_pos, 0x24},
+ {CX0342_CHANNEL_7_1_L_cds_pos, 0x02},
+ {CX0342_TIMING_EN, 0x01},
+};
+
+/* define the JPEG header */
+static void jpeg_define(u8 *jpeg_hdr,
+ int height,
+ int width)
+{
+ memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
+ jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
+ jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height;
+ jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
+ jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width;
+}
+
+/* set the JPEG quality for sensor soi763a */
+static void jpeg_set_qual(u8 *jpeg_hdr,
+ int quality)
+{
+ int i, sc;
+
+ if (quality < 50)
+ sc = 5000 / quality;
+ else
+ sc = 200 - quality * 2;
+ for (i = 0; i < 64; i++) {
+ jpeg_hdr[JPEG_QT0_OFFSET + i] =
+ (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
+ jpeg_hdr[JPEG_QT1_OFFSET + i] =
+ (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
+ }
+}
+
+static void reg_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
+{
+ struct usb_device *dev = gspca_dev->dev;
+ int ret;
+
+ if (gspca_dev->usb_err < 0)
+ return;
+ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 0x0e,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index, NULL, 0, 500);
+ if (ret < 0) {
+ pr_err("reg_w err %d\n", ret);
+ gspca_dev->usb_err = ret;
+ }
+}
+
+/* the returned value is in gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev, u8 index)
+{
+ struct usb_device *dev = gspca_dev->dev;
+ int ret;
+
+ if (gspca_dev->usb_err < 0)
+ return;
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ 0x0d,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index, gspca_dev->usb_buf, 1, 500);
+ if (ret < 0) {
+ pr_err("reg_r err %d\n", ret);
+ gspca_dev->usb_err = ret;
+ }
+}
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+ const struct cmd *p, int l)
+{
+ do {
+ reg_w(gspca_dev, p->reg, p->val);
+ p++;
+ } while (--l > 0);
+}
+
+static int i2c_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+ reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
+ reg_w(gspca_dev, TP6800_R13_SIF_TX_DATA, value);
+ reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x01);
+ if (sd->bridge == BRIDGE_TP6800)
+ return 0;
+ msleep(5);
+ reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
+ if (gspca_dev->usb_buf[0] == 0)
+ return 0;
+ reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+ return -1; /* error */
+}
+
+static void i2c_w_buf(struct gspca_dev *gspca_dev,
+ const struct cmd *p, int l)
+{
+ do {
+ i2c_w(gspca_dev, p->reg, p->val);
+ p++;
+ } while (--l > 0);
+}
+
+static int i2c_r(struct gspca_dev *gspca_dev, u8 index, int len)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int v;
+
+ reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
+ reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x02);
+ msleep(5);
+ reg_r(gspca_dev, TP6800_R14_SIF_RX_DATA);
+ v = gspca_dev->usb_buf[0];
+ if (sd->bridge == BRIDGE_TP6800)
+ return v;
+ if (len > 1) {
+ reg_r(gspca_dev, TP6800_R1B_SIF_RX_DATA2);
+ v |= (gspca_dev->usb_buf[0] << 8);
+ }
+ reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
+ if (gspca_dev->usb_buf[0] == 0)
+ return v;
+ reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+ return -1;
+}
+
+static void bulk_w(struct gspca_dev *gspca_dev,
+ u8 tag,
+ const u8 *data,
+ int length)
+{
+ struct usb_device *dev = gspca_dev->dev;
+ int count, actual_count, ret;
+
+ if (gspca_dev->usb_err < 0)
+ return;
+ for (;;) {
+ count = length > BULK_OUT_SIZE - 1
+ ? BULK_OUT_SIZE - 1 : length;
+ gspca_dev->usb_buf[0] = tag;
+ memcpy(&gspca_dev->usb_buf[1], data, count);
+ ret = usb_bulk_msg(dev,
+ usb_sndbulkpipe(dev, 3),
+ gspca_dev->usb_buf, count + 1,
+ &actual_count, 500);
+ if (ret < 0) {
+ pr_err("bulk write error %d tag=%02x\n",
+ ret, tag);
+ gspca_dev->usb_err = ret;
+ return;
+ }
+ length -= count;
+ if (length <= 0)
+ break;
+ data += count;
+ }
+}
+
+static int probe_6810(struct gspca_dev *gspca_dev)
+{
+ u8 gpio;
+ int ret;
+
+ reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+ gpio = gspca_dev->usb_buf[0];
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+ reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04); /* i2c 16 bits */
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21); /* ov??? */
+ reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x00);
+ if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
+ return SENSOR_SOI763A;
+
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00); /* i2c 8 bits */
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x7f); /* (unknown i2c) */
+ if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
+ return -2;
+
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00); /* i2c 8 bits */
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x11); /* tas??? / hv??? */
+ ret = i2c_r(gspca_dev, 0x00, 1);
+ if (ret > 0)
+ return -3;
+
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x6e); /* po??? */
+ ret = i2c_r(gspca_dev, 0x00, 1);
+ if (ret > 0)
+ return -4;
+
+ ret = i2c_r(gspca_dev, 0x01, 1);
+ if (ret > 0)
+ return -5;
+
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04); /* i2c 16 bits */
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5d); /* mi/mt??? */
+ ret = i2c_r(gspca_dev, 0x00, 2);
+ if (ret > 0)
+ return -6;
+
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5c); /* mi/mt??? */
+ ret = i2c_r(gspca_dev, 0x36, 2);
+ if (ret > 0)
+ return -7;
+
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x61); /* (unknown i2c) */
+ reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x10);
+ if (i2c_w(gspca_dev, 0xff, 0x00) >= 0)
+ return -8;
+
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+ reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00); /* i2c 8 bits */
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20); /* cx0342 */
+ ret = i2c_r(gspca_dev, 0x00, 1);
+ if (ret > 0)
+ return SENSOR_CX0342;
+ return -9;
+}
+
+static void cx0342_6810_init(struct gspca_dev *gspca_dev)
+{
+ static const struct cmd reg_init_1[] = {
+ {TP6800_R2F_TIMING_CFG, 0x2f},
+ {0x25, 0x02},
+ {TP6800_R21_ENDP_1_CTL, 0x00},
+ {TP6800_R3F_FRAME_RATE, 0x80},
+ {TP6800_R2F_TIMING_CFG, 0x2f},
+ {TP6800_R18_GPIO_DATA, 0xe1},
+ {TP6800_R18_GPIO_DATA, 0xc1},
+ {TP6800_R18_GPIO_DATA, 0xe1},
+ {TP6800_R11_SIF_CONTROL, 0x00},
+ };
+ static const struct cmd reg_init_2[] = {
+ {TP6800_R78_FORMAT, 0x48},
+ {TP6800_R11_SIF_CONTROL, 0x00},
+ };
+ static const struct cmd sensor_init[] = {
+ {CX0342_OUTPUT_CTRL, 0x07},
+ {CX0342_BYPASS_MODE, 0x58},
+ {CX0342_GPXLTHD_L, 0x28},
+ {CX0342_RBPXLTHD_L, 0x28},
+ {CX0342_PLANETHD_L, 0x50},
+ {CX0342_PLANETHD_H, 0x03},
+ {CX0342_RB_GAP_L, 0xff},
+ {CX0342_RB_GAP_H, 0x07},
+ {CX0342_G_GAP_L, 0xff},
+ {CX0342_G_GAP_H, 0x07},
+ {CX0342_RST_OVERFLOW_L, 0x5c},
+ {CX0342_RST_OVERFLOW_H, 0x01},
+ {CX0342_DATA_OVERFLOW_L, 0xfc},
+ {CX0342_DATA_OVERFLOW_H, 0x03},
+ {CX0342_DATA_UNDERFLOW_L, 0x00},
+ {CX0342_DATA_UNDERFLOW_H, 0x00},
+ {CX0342_SYS_CTRL_0, 0x40},
+ {CX0342_GLOBAL_GAIN, 0x01},
+ {CX0342_CLOCK_GEN, 0x00},
+ {CX0342_SYS_CTRL_0, 0x02},
+ {CX0342_IDLE_CTRL, 0x05},
+ {CX0342_ADCGN, 0x00},
+ {CX0342_ADC_CTL, 0x00},
+ {CX0342_LVRST_BLBIAS, 0x01},
+ {CX0342_VTHSEL, 0x0b},
+ {CX0342_RAMP_RIV, 0x0b},
+ {CX0342_LDOSEL, 0x07},
+ {CX0342_SPV_VALUE_L, 0x40},
+ {CX0342_SPV_VALUE_H, 0x02},
+
+ {CX0342_AUTO_ADC_CALIB, 0x81},
+ {CX0342_TIMING_EN, 0x01},
+ };
+
+ reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
+ reg_w_buf(gspca_dev, tp6810_cx_init_common,
+ ARRAY_SIZE(tp6810_cx_init_common));
+ reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
+
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20); /* cx0342 I2C addr */
+ i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+ i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
+}
+
+static void soi763a_6810_init(struct gspca_dev *gspca_dev)
+{
+ static const struct cmd reg_init_1[] = {
+ {TP6800_R2F_TIMING_CFG, 0x2f},
+ {TP6800_R18_GPIO_DATA, 0xe1},
+ {0x25, 0x02},
+ {TP6800_R21_ENDP_1_CTL, 0x00},
+ {TP6800_R3F_FRAME_RATE, 0x80},
+ {TP6800_R2F_TIMING_CFG, 0x2f},
+ {TP6800_R18_GPIO_DATA, 0xc1},
+ };
+ static const struct cmd reg_init_2[] = {
+ {TP6800_R78_FORMAT, 0x54},
+ };
+ static const struct cmd sensor_init[] = {
+ {0x00, 0x00},
+ {0x01, 0x80},
+ {0x02, 0x80},
+ {0x03, 0x90},
+ {0x04, 0x20},
+ {0x05, 0x20},
+ {0x06, 0x80},
+ {0x07, 0x00},
+ {0x08, 0xff},
+ {0x09, 0xff},
+ {0x0a, 0x76}, /* 7630 = soi673a */
+ {0x0b, 0x30},
+ {0x0c, 0x20},
+ {0x0d, 0x20},
+ {0x0e, 0xff},
+ {0x0f, 0xff},
+ {0x10, 0x41},
+ {0x15, 0x14},
+ {0x11, 0x40},
+ {0x12, 0x48},
+ {0x13, 0x80},
+ {0x14, 0x80},
+ {0x16, 0x03},
+ {0x28, 0xb0},
+ {0x71, 0x20},
+ {0x75, 0x8e},
+ {0x17, 0x1b},
+ {0x18, 0xbd},
+ {0x19, 0x05},
+ {0x1a, 0xf6},
+ {0x1b, 0x04},
+ {0x1c, 0x7f}, /* omnivision */
+ {0x1d, 0xa2},
+ {0x1e, 0x00},
+ {0x1f, 0x00},
+ {0x20, 0x45},
+ {0x21, 0x80},
+ {0x22, 0x80},
+ {0x23, 0xee},
+ {0x24, 0x50},
+ {0x25, 0x7a},
+ {0x26, 0xa0},
+ {0x27, 0x9a},
+ {0x29, 0x30},
+ {0x2a, 0x80},
+ {0x2b, 0x00},
+ {0x2c, 0xac},
+ {0x2d, 0x05},
+ {0x2e, 0x80},
+ {0x2f, 0x3c},
+ {0x30, 0x22},
+ {0x31, 0x00},
+ {0x32, 0x86},
+ {0x33, 0x08},
+ {0x34, 0xff},
+ {0x35, 0xff},
+ {0x36, 0xff},
+ {0x37, 0xff},
+ {0x38, 0xff},
+ {0x39, 0xff},
+ {0x3a, 0xfe},
+ {0x3b, 0xfe},
+ {0x3c, 0xfe},
+ {0x3d, 0xfe},
+ {0x3e, 0xfe},
+ {0x3f, 0x71},
+ {0x40, 0xff},
+ {0x41, 0xff},
+ {0x42, 0xff},
+ {0x43, 0xff},
+ {0x44, 0xff},
+ {0x45, 0xff},
+ {0x46, 0xff},
+ {0x47, 0xff},
+ {0x48, 0xff},
+ {0x49, 0xff},
+ {0x4a, 0xfe},
+ {0x4b, 0xff},
+ {0x4c, 0x00},
+ {0x4d, 0x00},
+ {0x4e, 0xff},
+ {0x4f, 0xff},
+ {0x50, 0xff},
+ {0x51, 0xff},
+ {0x52, 0xff},
+ {0x53, 0xff},
+ {0x54, 0xff},
+ {0x55, 0xff},
+ {0x56, 0xff},
+ {0x57, 0xff},
+ {0x58, 0xff},
+ {0x59, 0xff},
+ {0x5a, 0xff},
+ {0x5b, 0xfe},
+ {0x5c, 0xff},
+ {0x5d, 0x8f},
+ {0x5e, 0xff},
+ {0x5f, 0x8f},
+ {0x60, 0xa2},
+ {0x61, 0x4a},
+ {0x62, 0xf3},
+ {0x63, 0x75},
+ {0x64, 0xf0},
+ {0x65, 0x00},
+ {0x66, 0x55},
+ {0x67, 0x92},
+ {0x68, 0xa0},
+ {0x69, 0x4a},
+ {0x6a, 0x22},
+ {0x6b, 0x00},
+ {0x6c, 0x33},
+ {0x6d, 0x44},
+ {0x6e, 0x22},
+ {0x6f, 0x84},
+ {0x70, 0x0b},
+ {0x72, 0x10},
+ {0x73, 0x50},
+ {0x74, 0x21},
+ {0x76, 0x00},
+ {0x77, 0xa5},
+ {0x78, 0x80},
+ {0x79, 0x80},
+ {0x7a, 0x80},
+ {0x7b, 0xe2},
+ {0x7c, 0x00},
+ {0x7d, 0xf7},
+ {0x7e, 0x00},
+ {0x7f, 0x00},
+ };
+
+ reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
+ reg_w_buf(gspca_dev, tp6810_ov_init_common,
+ ARRAY_SIZE(tp6810_ov_init_common));
+ reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
+
+ i2c_w(gspca_dev, 0x12, 0x80); /* sensor reset */
+ msleep(10);
+ i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+}
+
+/* set the gain and exposure */
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->sensor == SENSOR_CX0342) {
+ int expo;
+
+ expo = (sd->ctrls[EXPOSURE].val << 2) - 1;
+ i2c_w(gspca_dev, CX0342_EXPO_LINE_L, expo);
+ i2c_w(gspca_dev, CX0342_EXPO_LINE_H, expo >> 8);
+ if (sd->bridge == BRIDGE_TP6800)
+ i2c_w(gspca_dev, CX0342_RAW_GBGAIN_H,
+ sd->ctrls[GAIN].val >> 8);
+ i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, sd->ctrls[GAIN].val);
+ if (sd->bridge == BRIDGE_TP6800)
+ i2c_w(gspca_dev, CX0342_RAW_GRGAIN_H,
+ sd->ctrls[GAIN].val >> 8);
+ i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, sd->ctrls[GAIN].val);
+ if (sd->bridge == BRIDGE_TP6800)
+ i2c_w(gspca_dev, CX0342_RAW_BGAIN_H,
+ sd->ctrls[BGAIN].val >> 8);
+ i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, sd->ctrls[BGAIN].val);
+ if (sd->bridge == BRIDGE_TP6800)
+ i2c_w(gspca_dev, CX0342_RAW_RGAIN_H,
+ sd->ctrls[RGAIN].val >> 8);
+ i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, sd->ctrls[RGAIN].val);
+ i2c_w(gspca_dev, CX0342_SYS_CTRL_0,
+ sd->bridge == BRIDGE_TP6800 ? 0x80 : 0x81);
+ return;
+ }
+
+ /* soi763a */
+ i2c_w(gspca_dev, 0x10, /* AEC_H (exposure time) */
+ sd->ctrls[EXPOSURE].val);
+/* i2c_w(gspca_dev, 0x76, 0x02); * AEC_L ([1:0] */
+ i2c_w(gspca_dev, 0x00, /* gain */
+ sd->ctrls[GAIN].val);
+}
+
+/* set the JPEG quantization tables */
+static void set_dqt(struct gspca_dev *gspca_dev, u8 q)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ /* update the jpeg quantization tables */
+ PDEBUG(D_STREAM, "q %d -> %d", sd->quality, q);
+ sd->quality = q;
+ if (q > 16)
+ q = 16;
+ if (sd->sensor == SENSOR_SOI763A)
+ jpeg_set_qual(sd->jpeg_hdr, jpeg_q[q]);
+ else
+ memcpy(&sd->jpeg_hdr[JPEG_QT0_OFFSET - 1],
+ DQT[q], sizeof DQT[0]);
+}
+
+/* set the JPEG compression quality factor */
+static void setquality(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u16 q;
+
+ q = sd->ctrls[QUALITY].val;
+ if (q != 16)
+ q = 15 - q;
+
+ reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x00);
+ reg_w(gspca_dev, TP6800_R79_QUALITY, 0x04);
+ reg_w(gspca_dev, TP6800_R79_QUALITY, q);
+
+ /* auto quality */
+ if (q == 15 && sd->bridge == BRIDGE_TP6810) {
+ msleep(4);
+ reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x19);
+ }
+}
+
+static const u8 color_null[18] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+static const u8 color_gain[NSENSORS][18] = {
+[SENSOR_CX0342] =
+ {0x4c, 0x00, 0xa9, 0x00, 0x31, 0x00, /* Y R/G/B (LE values) */
+ 0xb6, 0x03, 0x6c, 0x03, 0xe0, 0x00, /* U R/G/B */
+ 0xdf, 0x00, 0x46, 0x03, 0xdc, 0x03}, /* V R/G/B */
+[SENSOR_SOI763A] =
+ {0x4c, 0x00, 0x95, 0x00, 0x1d, 0x00, /* Y R/G/B (LE values) */
+ 0xb6, 0x03, 0x6c, 0x03, 0xd7, 0x00, /* U R/G/B */
+ 0xd5, 0x00, 0x46, 0x03, 0xdc, 0x03}, /* V R/G/B */
+};
+
+static void setgamma(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int gamma;
+#define NGAMMA 6
+ static const u8 gamma_tb[NGAMMA][3][1024] = {
+ { /* gamma 0 - from tp6800 + soi763a */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+ 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+ 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+ 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+ 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+ 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+ 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+ 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+ 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+ 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+ 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+ 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+ 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+ 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+ 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+ 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+ 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+ 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+ 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+ 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+ 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+ 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+ 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+ 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+ 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+ 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+ 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+ 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+ 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+ 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+ 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+ 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+ 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+ 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+ 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+ 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+ 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+ 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+ 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+ 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+ 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+ 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+ 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+ 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+ 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+ 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+ 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+ 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+ 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+ 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+ 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+ 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+ 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+ 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+ 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+ 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+ 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+ 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+ 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+ 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+ 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+ 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+ 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+ 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+ 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+ 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+ 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+ 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+ 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+ 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+ 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+ 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+ 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+ 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+ 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+ 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+ 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+ 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+ 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+ 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+ 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+ 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+ 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+ 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+ 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+ 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+ 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+ 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+ 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+ 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+ 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+ 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+ 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+ 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+ 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+ 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+ 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+ 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+ 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+ 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+ 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+ 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+ 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+ 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+ 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+ 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+ 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+ 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+ 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+ 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+ 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+ 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+ 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+ 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+ 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+ 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+ 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+ 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+ 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+ 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+ 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+ 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+ 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+ 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+ 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+ 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+ 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+ 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+ 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+ 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+ 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+ 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+ 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+ 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+ 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+ 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+ 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+ 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+ 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+ 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+ 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+ 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+ 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+ 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+ 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+ 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+ 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+ 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+ 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+ 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+ 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+ 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+ 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+ 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+ 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+ 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+ 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+ 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+ 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+ 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+ 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+ 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+ 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+ 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+ 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+ 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+ 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+ 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+ 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+ 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+ 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+ 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+ 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+ 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+ 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+ 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+ 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+ 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+ 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+ 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+ 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+ 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+ 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+ 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+ 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+ 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+ 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+ 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+ 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76,
+ 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+ 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+ 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+ 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+ 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+ 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+ 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+ 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+ 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+ 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+ 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+ 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+ 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+ 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+ 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+ 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+ 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+ 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+ 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+ 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+ 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+ 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+ 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+ 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+ 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+ 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+ 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+ 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+ 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+ 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+ 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+ 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+ 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+ 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+ 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+ 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+ 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+ 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+ 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+ 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+ 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+ 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+ 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+ 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+ 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+ 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+ 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+ 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+ 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+ 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+ 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+ 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+ 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+ 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+ 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+ },
+ { /* gamma 1 - from tp6810 + soi763a */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x03, 0x05, 0x07, 0x08, 0x09, 0x0a,
+ 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15,
+ 0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
+ 0x1f, 0x20, 0x22, 0x22, 0x23, 0x25, 0x26, 0x27,
+ 0x27, 0x28, 0x29, 0x2b, 0x2b, 0x2c, 0x2d, 0x2f,
+ 0x2f, 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x35,
+ 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c,
+ 0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
+ 0x43, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48, 0x49,
+ 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d,
+ 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+ 0x54, 0x54, 0x55, 0x56, 0x56, 0x58, 0x58, 0x59,
+ 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5e,
+ 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61,
+ 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x65, 0x66,
+ 0x66, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x69,
+ 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+ 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
+ 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
+ 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
+ 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
+ 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+ 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84, 0x84,
+ 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
+ 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
+ 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
+ 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91,
+ 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93,
+ 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x97,
+ 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+ 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
+ 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9e,
+ 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+ 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
+ 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+ 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xab,
+ 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xae,
+ 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
+ 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+ 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
+ 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+ 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+ 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+ 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
+ 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+ 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+ 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4,
+ 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
+ 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+ 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+ 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+ 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+ 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
+ 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+ 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+ 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
+ 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+ 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+ 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+ 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+ 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+ 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+ 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8,
+ 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
+ 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
+ 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed,
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+ 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+ 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+ 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+ 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe,
+ 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
+ 0x05, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0d,
+ 0x0e, 0x10, 0x10, 0x11, 0x12, 0x14, 0x15, 0x15,
+ 0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
+ 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x25,
+ 0x26, 0x27, 0x27, 0x28, 0x29, 0x29, 0x2b, 0x2c,
+ 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x31,
+ 0x33, 0x34, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38,
+ 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d,
+ 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x43,
+ 0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48,
+ 0x48, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c,
+ 0x4c, 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50,
+ 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55,
+ 0x55, 0x56, 0x56, 0x56, 0x58, 0x58, 0x59, 0x59,
+ 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
+ 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60,
+ 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x65,
+ 0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67,
+ 0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a,
+ 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e,
+ 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
+ 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
+ 0x75, 0x75, 0x75, 0x77, 0x77, 0x77, 0x78, 0x78,
+ 0x78, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a,
+ 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d,
+ 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+ 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+ 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+ 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, 0x89,
+ 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b,
+ 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
+ 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
+ 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+ 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+ 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
+ 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
+ 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
+ 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+ 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
+ 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+ 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+ 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+ 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
+ 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+ 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+ 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+ 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+ 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+ 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+ 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+ 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+ 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+ 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
+ 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+ 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+ 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9,
+ 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+ 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcf,
+ 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+ 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+ 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4,
+ 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+ 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
+ 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
+ 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
+ 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+ 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+ 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2,
+ 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3,
+ 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+ 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+ 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+ 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+ 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+ 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
+ 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
+ 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8,
+ 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
+ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+ 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
+ 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x02, 0x03, 0x05, 0x05, 0x07,
+ 0x08, 0x09, 0x0a, 0x0a, 0x0c, 0x0d, 0x0e, 0x0e,
+ 0x10, 0x11, 0x12, 0x12, 0x14, 0x15, 0x16, 0x16,
+ 0x17, 0x18, 0x18, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+ 0x1e, 0x1f, 0x1f, 0x20, 0x22, 0x22, 0x23, 0x23,
+ 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x29, 0x29,
+ 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f, 0x30,
+ 0x30, 0x31, 0x31, 0x33, 0x33, 0x34, 0x34, 0x35,
+ 0x35, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a,
+ 0x3a, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d,
+ 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x42, 0x43,
+ 0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x47,
+ 0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4b,
+ 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4f,
+ 0x4f, 0x50, 0x50, 0x50, 0x52, 0x52, 0x52, 0x53,
+ 0x53, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56,
+ 0x56, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5a,
+ 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
+ 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60,
+ 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63,
+ 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66,
+ 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69,
+ 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+ 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e,
+ 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
+ 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74,
+ 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x77, 0x77,
+ 0x77, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79,
+ 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b,
+ 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+ 0x7d, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+ 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82,
+ 0x82, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
+ 0x85, 0x86, 0x86, 0x86, 0x86, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a,
+ 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
+ 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
+ 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
+ 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96,
+ 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+ 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+ 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
+ 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+ 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0,
+ 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
+ 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
+ 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+ 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6,
+ 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
+ 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac,
+ 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae,
+ 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+ 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+ 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2,
+ 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
+ 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6,
+ 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
+ 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+ 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+ 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+ 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+ 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
+ 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+ 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+ 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+ 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
+ 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
+ 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+ 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
+ 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+ 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
+ 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7,
+ 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+ 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
+ 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+ 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
+ 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0,
+ 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+ 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3,
+ 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4,
+ 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+ 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
+ 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
+ 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+ 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
+ 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef,
+ 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1,
+ 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+ 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc,
+ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd,
+ 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ { /* gamma 2 */
+ {0x00, 0x01, 0x02, 0x05, 0x07, 0x08, 0x0a, 0x0c,
+ 0x0d, 0x0e, 0x10, 0x12, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x22,
+ 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
+ 0x2d, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34,
+ 0x35, 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3b, 0x3b,
+ 0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
+ 0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x49, 0x49,
+ 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4f, 0x4f,
+ 0x50, 0x50, 0x52, 0x53, 0x53, 0x54, 0x54, 0x55,
+ 0x55, 0x56, 0x56, 0x58, 0x58, 0x59, 0x5a, 0x5a,
+ 0x5b, 0x5b, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
+ 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63,
+ 0x65, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
+ 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+ 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x70,
+ 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74,
+ 0x74, 0x75, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78,
+ 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
+ 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
+ 0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82,
+ 0x82, 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
+ 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x89, 0x89,
+ 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8d,
+ 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
+ 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+ 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
+ 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+ 0x97, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99,
+ 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
+ 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+ 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
+ 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3,
+ 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8,
+ 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+ 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad,
+ 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0,
+ 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
+ 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4,
+ 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+ 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+ 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+ 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+ 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0,
+ 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
+ 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4,
+ 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
+ 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+ 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
+ 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce,
+ 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
+ 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
+ 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4,
+ 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+ 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+ 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+ 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
+ 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
+ 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
+ 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+ 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
+ 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
+ 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
+ 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
+ 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
+ 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
+ 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+ 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1,
+ 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+ {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x05,
+ 0x07, 0x08, 0x09, 0x0a, 0x0d, 0x0e, 0x10, 0x11,
+ 0x12, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x1a,
+ 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23,
+ 0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x29, 0x2b,
+ 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x33,
+ 0x33, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38, 0x39,
+ 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3d, 0x3f,
+ 0x3f, 0x40, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44,
+ 0x45, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49, 0x4a,
+ 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d,
+ 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+ 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x58,
+ 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+ 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f,
+ 0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x63,
+ 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x67,
+ 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
+ 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d,
+ 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+ 0x70, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x73,
+ 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77, 0x77,
+ 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79,
+ 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c,
+ 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f,
+ 0x7f, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81,
+ 0x82, 0x82, 0x82, 0x82, 0x84, 0x84, 0x84, 0x84,
+ 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
+ 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a,
+ 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
+ 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f,
+ 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+ 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+ 0x94, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+ 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99,
+ 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b,
+ 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9c,
+ 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e,
+ 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
+ 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2,
+ 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+ 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+ 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
+ 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae,
+ 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf,
+ 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
+ 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
+ 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
+ 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
+ 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
+ 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
+ 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
+ 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
+ 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
+ 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+ 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
+ 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
+ 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+ 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+ 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+ 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
+ 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
+ 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+ 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+ 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+ 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+ 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+ 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+ 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+ 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
+ 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
+ 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
+ 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+ 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+ 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+ 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
+ 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+ 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+ 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xef,
+ 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+ 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
+ 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+ {0x00, 0x00, 0x00, 0x01, 0x02, 0x05, 0x07, 0x08,
+ 0x09, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12, 0x14,
+ 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1e,
+ 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x26, 0x27,
+ 0x28, 0x28, 0x29, 0x2b, 0x2c, 0x2d, 0x2d, 0x2f,
+ 0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x35, 0x37,
+ 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3c,
+ 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x43, 0x43,
+ 0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49,
+ 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d,
+ 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+ 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58,
+ 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
+ 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+ 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65,
+ 0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68,
+ 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+ 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f,
+ 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x73, 0x73,
+ 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+ 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a,
+ 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
+ 0x7c, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80,
+ 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82,
+ 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85,
+ 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+ 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b,
+ 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
+ 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90,
+ 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+ 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+ 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
+ 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
+ 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
+ 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+ 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
+ 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+ 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+ 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+ 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
+ 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+ 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
+ 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
+ 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
+ 0xb3, 0xb3, 0xb3, 0xb4, 0xb3, 0xb4, 0xb4, 0xb4,
+ 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+ 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
+ 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
+ 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
+ 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+ 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+ 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+ 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+ 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+ 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
+ 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
+ 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+ 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
+ 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+ 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+ 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+ 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
+ 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
+ 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
+ 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+ 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+ 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
+ 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+ 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
+ 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+ 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6,
+ 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+ 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
+ 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
+ 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
+ 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+ 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1,
+ 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+ 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+ 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+ },
+ { /* gamma 3 - from tp6810 + cx0342 */
+ {0x08, 0x09, 0x0c, 0x0d, 0x10, 0x11, 0x14, 0x15,
+ 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x1f, 0x20, 0x23,
+ 0x25, 0x26, 0x27, 0x28, 0x2b, 0x2c, 0x2d, 0x2f,
+ 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38, 0x39,
+ 0x3a, 0x3b, 0x3c, 0x3d, 0x3f, 0x40, 0x42, 0x43,
+ 0x44, 0x45, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4d, 0x4f, 0x50, 0x52, 0x53, 0x53,
+ 0x54, 0x55, 0x56, 0x56, 0x58, 0x59, 0x5a, 0x5a,
+ 0x5b, 0x5c, 0x5c, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
+ 0x61, 0x62, 0x63, 0x63, 0x65, 0x66, 0x66, 0x67,
+ 0x68, 0x68, 0x69, 0x69, 0x6a, 0x6c, 0x6c, 0x6d,
+ 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x73,
+ 0x73, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77, 0x78,
+ 0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c,
+ 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81,
+ 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+ 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
+ 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f,
+ 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x93,
+ 0x93, 0x93, 0x94, 0x94, 0x96, 0x96, 0x97, 0x97,
+ 0x97, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+ 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
+ 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+ 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+ 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
+ 0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
+ 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+ 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+ 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3,
+ 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+ 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+ 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+ 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
+ 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
+ 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5,
+ 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+ 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+ 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+ 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce,
+ 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+ 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3,
+ 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
+ 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+ 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda,
+ 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
+ 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
+ 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+ 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4,
+ 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+ 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
+ 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+ 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+ 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+ 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+ 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+ 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
+ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ {0x03, 0x05, 0x07, 0x09, 0x0a, 0x0c, 0x0d, 0x10,
+ 0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1a, 0x1b,
+ 0x1c, 0x1e, 0x1f, 0x20, 0x22, 0x23, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2f,
+ 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x37, 0x38,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f,
+ 0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
+ 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b,
+ 0x4c, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52,
+ 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, 0x58,
+ 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c,
+ 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+ 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x66,
+ 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69,
+ 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
+ 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
+ 0x71, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
+ 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
+ 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
+ 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80,
+ 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84,
+ 0x84, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86,
+ 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a,
+ 0x8a, 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e,
+ 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90,
+ 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
+ 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96,
+ 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98,
+ 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a,
+ 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
+ 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e,
+ 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
+ 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3,
+ 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+ 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+ 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad,
+ 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+ 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
+ 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
+ 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4,
+ 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+ 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
+ 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+ 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+ 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
+ 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
+ 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
+ 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+ 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+ 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
+ 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+ 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0,
+ 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
+ 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
+ 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
+ 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+ 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+ 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+ 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+ 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+ 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
+ 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2,
+ 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+ 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+ 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+ 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+ 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec,
+ 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+ 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+ 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+ 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc,
+ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+ 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
+ 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ {0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
+ 0x16, 0x17, 0x18, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
+ 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2d,
+ 0x2f, 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38,
+ 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f, 0x40,
+ 0x42, 0x43, 0x44, 0x44, 0x45, 0x47, 0x48, 0x49,
+ 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4f, 0x50,
+ 0x52, 0x52, 0x53, 0x54, 0x55, 0x55, 0x56, 0x58,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e,
+ 0x5f, 0x5f, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63,
+ 0x65, 0x65, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
+ 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e,
+ 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x74,
+ 0x74, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78, 0x79,
+ 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d,
+ 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81,
+ 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+ 0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
+ 0x8b, 0x8b, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f,
+ 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
+ 0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96,
+ 0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+ 0x99, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+ 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
+ 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
+ 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
+ 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9,
+ 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac,
+ 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+ 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1,
+ 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
+ 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+ 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+ 0xb9, 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc,
+ 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
+ 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+ 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4,
+ 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9,
+ 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb,
+ 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf,
+ 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
+ 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3,
+ 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+ 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+ 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
+ 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
+ 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+ 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+ 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+ 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
+ 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+ 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+ 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+ 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+ 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+ 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd,
+ 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+ },
+ { /* gamma 4 - from tp6800 + soi763a */
+ {0x11, 0x14, 0x15, 0x17, 0x1a, 0x1b, 0x1e, 0x1f,
+ 0x22, 0x23, 0x25, 0x27, 0x28, 0x2b, 0x2c, 0x2d,
+ 0x2f, 0x31, 0x33, 0x34, 0x35, 0x38, 0x39, 0x3a,
+ 0x3b, 0x3c, 0x3d, 0x40, 0x42, 0x43, 0x44, 0x45,
+ 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f,
+ 0x50, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56, 0x58,
+ 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5f, 0x60,
+ 0x61, 0x61, 0x62, 0x63, 0x65, 0x65, 0x66, 0x67,
+ 0x68, 0x68, 0x69, 0x6a, 0x6c, 0x6c, 0x6d, 0x6e,
+ 0x6f, 0x6f, 0x70, 0x71, 0x71, 0x73, 0x74, 0x74,
+ 0x75, 0x77, 0x77, 0x78, 0x79, 0x79, 0x7a, 0x7a,
+ 0x7b, 0x7c, 0x7c, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
+ 0x81, 0x81, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86,
+ 0x86, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b,
+ 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x90, 0x91,
+ 0x91, 0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x96,
+ 0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+ 0x9a, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
+ 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2,
+ 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5,
+ 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9, 0xab,
+ 0xab, 0xab, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
+ 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1,
+ 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4,
+ 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8,
+ 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xbc,
+ 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
+ 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
+ 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+ 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc9,
+ 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+ 0xcb, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xce,
+ 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
+ 0xd0, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+ 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+ 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+ 0xd9, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
+ 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf,
+ 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
+ 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+ 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+ 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+ 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
+ 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
+ 0xec, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+ 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
+ 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xfa, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+ {0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x14, 0x15,
+ 0x16, 0x17, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
+ 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
+ 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34, 0x35,
+ 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d,
+ 0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
+ 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b, 0x4c,
+ 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52, 0x53, 0x54,
+ 0x54, 0x55, 0x55, 0x56, 0x58, 0x58, 0x59, 0x5a,
+ 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
+ 0x60, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63, 0x65,
+ 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
+ 0x69, 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
+ 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73,
+ 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77,
+ 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b,
+ 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
+ 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82,
+ 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x86,
+ 0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
+ 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
+ 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91,
+ 0x91, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x94,
+ 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+ 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a,
+ 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
+ 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
+ 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+ 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6,
+ 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+ 0xaa, 0xab, 0xab, 0xac, 0xac, 0xac, 0xad, 0xad,
+ 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+ 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+ 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
+ 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
+ 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8,
+ 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+ 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+ 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+ 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+ 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+ 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9,
+ 0xca, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+ 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+ 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+ 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3,
+ 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+ 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+ 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+ 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
+ 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+ 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
+ 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+ 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
+ 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+ 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
+ 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+ 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+ 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+ 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+ 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+ 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+ {0x0d, 0x10, 0x11, 0x14, 0x15, 0x17, 0x18, 0x1b,
+ 0x1c, 0x1e, 0x20, 0x22, 0x23, 0x26, 0x27, 0x28,
+ 0x29, 0x2b, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34,
+ 0x35, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
+ 0x3f, 0x40, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48,
+ 0x49, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4f, 0x50,
+ 0x52, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58,
+ 0x59, 0x5a, 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f,
+ 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x65, 0x65,
+ 0x66, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6c,
+ 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+ 0x71, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x77,
+ 0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
+ 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
+ 0x81, 0x81, 0x82, 0x82, 0x84, 0x84, 0x85, 0x85,
+ 0x86, 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a,
+ 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f,
+ 0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92,
+ 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x97,
+ 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
+ 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
+ 0x9d, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+ 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+ 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
+ 0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
+ 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+ 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+ 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
+ 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+ 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba,
+ 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+ 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+ 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc3,
+ 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+ 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
+ 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+ 0xca, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+ 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0,
+ 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+ 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+ 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8,
+ 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+ 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf,
+ 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
+ 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+ 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+ 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
+ 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8,
+ 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
+ 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+ 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+ 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+ 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8,
+ 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+ },
+ { /* gamma 5 */
+ {0x16, 0x18, 0x19, 0x1b, 0x1d, 0x1e, 0x20, 0x21,
+ 0x23, 0x24, 0x25, 0x27, 0x28, 0x2a, 0x2b, 0x2c,
+ 0x2d, 0x2f, 0x30, 0x31, 0x32, 0x34, 0x35, 0x36,
+ 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
+ 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55,
+ 0x56, 0x56, 0x57, 0x58, 0x59, 0x59, 0x5a, 0x5b,
+ 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
+ 0x62, 0x62, 0x63, 0x64, 0x64, 0x65, 0x66, 0x66,
+ 0x67, 0x68, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6b,
+ 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+ 0x71, 0x71, 0x72, 0x73, 0x73, 0x74, 0x74, 0x75,
+ 0x75, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79,
+ 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e,
+ 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x82,
+ 0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
+ 0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89,
+ 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8d,
+ 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x90, 0x90,
+ 0x91, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93, 0x94,
+ 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x96, 0x97,
+ 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
+ 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
+ 0x9d, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0xa0, 0xa0,
+ 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
+ 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6,
+ 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8,
+ 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+ 0xab, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
+ 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+ 0xb0, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3,
+ 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5,
+ 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
+ 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+ 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc,
+ 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+ 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+ 0xc1, 0xc1, 0xc1, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+ 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+ 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7,
+ 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9, 0xc9,
+ 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+ 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf,
+ 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+ 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3,
+ 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5,
+ 0xd5, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+ 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+ 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+ 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde,
+ 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
+ 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+ 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+ 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+ 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+ 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea, 0xeb,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+ 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+ 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+ 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
+ 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ {0x0f, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19,
+ 0x1a, 0x1b, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x31, 0x32,
+ 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x38, 0x39,
+ 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3e, 0x3f, 0x3f,
+ 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x44, 0x45,
+ 0x46, 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b,
+ 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0x4e, 0x4f, 0x50,
+ 0x50, 0x51, 0x51, 0x52, 0x53, 0x53, 0x54, 0x54,
+ 0x55, 0x55, 0x56, 0x56, 0x57, 0x58, 0x58, 0x59,
+ 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5d,
+ 0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+ 0x61, 0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x65,
+ 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68,
+ 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c,
+ 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f,
+ 0x6f, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72,
+ 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x75,
+ 0x76, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78,
+ 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+ 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e,
+ 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81,
+ 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83,
+ 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86,
+ 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88,
+ 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b,
+ 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d,
+ 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f,
+ 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+ 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
+ 0x94, 0x94, 0x94, 0x95, 0x95, 0x95, 0x96, 0x96,
+ 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98,
+ 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+ 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+ 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e,
+ 0x9e, 0x9e, 0x9f, 0x9f, 0x9f, 0x9f, 0xa0, 0xa0,
+ 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+ 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+ 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa6, 0xa6, 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa7,
+ 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9,
+ 0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+ 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+ 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+ 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+ 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+ 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5,
+ 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+ 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+ 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+ 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+ 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
+ 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+ 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
+ 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+ 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9,
+ 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca,
+ 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce,
+ 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+ 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+ 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
+ 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+ 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
+ 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+ 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+ 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
+ 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb,
+ 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde,
+ 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf,
+ 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
+ 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+ 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
+ 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+ 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+ 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+ 0xe9, 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea,
+ 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+ 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+ 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
+ 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+ 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+ 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+ 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
+ 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ {0x13, 0x15, 0x16, 0x18, 0x19, 0x1b, 0x1c, 0x1e,
+ 0x1f, 0x20, 0x22, 0x23, 0x24, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
+ 0x42, 0x43, 0x44, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e,
+ 0x4f, 0x50, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54,
+ 0x55, 0x55, 0x56, 0x57, 0x57, 0x58, 0x59, 0x59,
+ 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5f,
+ 0x5f, 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x63,
+ 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
+ 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c,
+ 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+ 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74,
+ 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78,
+ 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c,
+ 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f,
+ 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x83,
+ 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+ 0x86, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89,
+ 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c,
+ 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
+ 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
+ 0x92, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95,
+ 0x95, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+ 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+ 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d,
+ 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f,
+ 0x9f, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2,
+ 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+ 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6,
+ 0xa7, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8, 0xa9,
+ 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+ 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad,
+ 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf,
+ 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
+ 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+ 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5,
+ 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
+ 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+ 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
+ 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
+ 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1,
+ 0xc1, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+ 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+ 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+ 0xc7, 0xc7, 0xc7, 0xc7, 0xc8, 0xc8, 0xc8, 0xc8,
+ 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+ 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+ 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+ 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+ 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
+ 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
+ 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6,
+ 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+ 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
+ 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
+ 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+ 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+ 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+ 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+ 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+ 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6,
+ 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+ 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
+ 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
+ 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+ 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2,
+ 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
+ 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+ 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
+ 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+ 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe,
+ 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ },
+ };
+
+ reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+ if (sd->bridge == BRIDGE_TP6810)
+ reg_w(gspca_dev, 0x02, 0x28);
+/* msleep(50); */
+ gamma = sd->ctrls[GAMMA].val;
+ bulk_w(gspca_dev, 0x00, gamma_tb[gamma][0], 1024);
+ bulk_w(gspca_dev, 0x01, gamma_tb[gamma][1], 1024);
+ bulk_w(gspca_dev, 0x02, gamma_tb[gamma][2], 1024);
+ if (sd->bridge == BRIDGE_TP6810) {
+ int i;
+
+ reg_w(gspca_dev, 0x02, 0x2b);
+ reg_w(gspca_dev, 0x02, 0x28);
+ for (i = 0; i < 6; i++)
+ reg_w(gspca_dev, TP6800_R55_GAMMA_R,
+ gamma_tb[gamma][0][i]);
+ reg_w(gspca_dev, 0x02, 0x2b);
+ reg_w(gspca_dev, 0x02, 0x28);
+ for (i = 0; i < 6; i++)
+ reg_w(gspca_dev, TP6800_R56_GAMMA_G,
+ gamma_tb[gamma][1][i]);
+ reg_w(gspca_dev, 0x02, 0x2b);
+ reg_w(gspca_dev, 0x02, 0x28);
+ for (i = 0; i < 6; i++)
+ reg_w(gspca_dev, TP6800_R57_GAMMA_B,
+ gamma_tb[gamma][2][i]);
+ reg_w(gspca_dev, 0x02, 0x28);
+ }
+ reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+/* msleep(50); */
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 val;
+
+ if (sd->bridge == BRIDGE_TP6800) {
+ val = sd->ctrls[SHARPNESS].val
+ | 0x08; /* grid compensation enable */
+ if (gspca_dev->width == 640)
+ reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
+ else
+ val |= 0x04; /* scaling down enable */
+ reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, val);
+ } else {
+ val = (sd->ctrls[SHARPNESS].val << 5) | 0x08;
+ reg_w(gspca_dev, 0x59, val);
+ }
+}
+
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
+ return;
+ if (sd->ctrls[AUTOGAIN].val) {
+ sd->ag_cnt = AG_CNT_START;
+ gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
+ } else {
+ sd->ag_cnt = -1;
+ gspca_dev->ctrl_inac &= ~((1 << EXPOSURE) | (1 << GAIN));
+ }
+}
+
+/* set the resolution for sensor cx0342 */
+static void set_resolution(struct gspca_dev *gspca_dev)
+{
+ reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+ if (gspca_dev->width == 320) {
+ reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06);
+ msleep(100);
+ i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+ msleep(100);
+ reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+ reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */
+ reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x0d);
+ i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0x37);
+ i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x01);
+ } else {
+ reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x05);
+ msleep(100);
+ i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+ msleep(100);
+ reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+ reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
+ reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x09);
+ i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0xcf);
+ i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
+ }
+ i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
+ bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
+ ARRAY_SIZE(color_gain[0]));
+ setgamma(gspca_dev);
+ setquality(gspca_dev);
+}
+
+/* convert the frame rate to a tp68x0 value */
+static int get_fr_idx(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int i;
+
+ if (sd->bridge == BRIDGE_TP6800) {
+ for (i = 0; i < ARRAY_SIZE(rates) - 1; i++) {
+ if (sd->framerate >= rates[i])
+ break;
+ }
+ i = 6 - i; /* 1 = 5fps .. 6 = 30fps */
+
+ /* 640x480 * 30 fps does not work */
+ if (i == 6 /* if 30 fps */
+ && gspca_dev->width == 640)
+ i = 0x86; /* 15 fps */
+ } else {
+ for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) {
+ if (sd->framerate >= rates_6810[i])
+ break;
+ }
+ i = 7 - i; /* 3 = 5fps .. 7 = 30fps */
+
+ /* 640x480 * 30 fps does not work */
+ if (i == 7 /* if 30 fps */
+ && gspca_dev->width == 640)
+ i = 6; /* 15 fps */
+ i |= 0x80; /* clock * 1 */
+ }
+ return i;
+}
+
+static void setframerate(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 fr_idx;
+
+ fr_idx = get_fr_idx(gspca_dev);
+
+ if (sd->bridge == BRIDGE_TP6810) {
+ reg_r(gspca_dev, 0x7b);
+ reg_w(gspca_dev, 0x7b,
+ sd->sensor == SENSOR_CX0342 ? 0x10 : 0x90);
+ if (sd->ctrls[EXPOSURE].val >= 128)
+ fr_idx = 0xf0; /* lower frame rate */
+ }
+
+ reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, fr_idx);
+
+ if (sd->sensor == SENSOR_CX0342)
+ i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+}
+
+static void setrgain(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int rgain;
+
+ rgain = sd->ctrls[RGAIN].val;
+ i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, rgain >> 8);
+ i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, rgain);
+ i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
+}
+
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->sensor == SENSOR_CX0342) {
+ sd->ctrls[BGAIN].val = sd->ctrls[BGAIN].val
+ * val / sd->ctrls[GAIN].val;
+ if (sd->ctrls[BGAIN].val > 4095)
+ sd->ctrls[BGAIN].val = 4095;
+ sd->ctrls[RGAIN].val = sd->ctrls[RGAIN].val
+ * val / sd->ctrls[GAIN].val;
+ if (sd->ctrls[RGAIN].val > 4095)
+ sd->ctrls[RGAIN].val = 4095;
+ }
+ sd->ctrls[GAIN].val = val;
+ if (gspca_dev->streaming)
+ setexposure(gspca_dev);
+ return gspca_dev->usb_err;
+}
+
+static void setbgain(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int bgain;
+
+ bgain = sd->ctrls[BGAIN].val;
+ i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, bgain >> 8);
+ i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, bgain);
+ i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+ const struct usb_device_id *id)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->bridge = id->driver_info;
+
+ gspca_dev->cam.cam_mode = vga_mode;
+ gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
+ gspca_dev->cam.mode_framerates = sd->bridge == BRIDGE_TP6800 ?
+ framerates : framerates_6810;
+
+ sd->framerate = 30; /* default: 30 fps */
+ gspca_dev->cam.ctrls = sd->ctrls;
+ return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ static const struct cmd tp6800_preinit[] = {
+ {TP6800_R10_SIF_TYPE, 0x01}, /* sif */
+ {TP6800_R11_SIF_CONTROL, 0x01},
+ {TP6800_R15_GPIO_PU, 0x9f},
+ {TP6800_R16_GPIO_PD, 0x9f},
+ {TP6800_R17_GPIO_IO, 0x80},
+ {TP6800_R18_GPIO_DATA, 0x40}, /* LED off */
+ };
+ static const struct cmd tp6810_preinit[] = {
+ {TP6800_R2F_TIMING_CFG, 0x2f},
+ {TP6800_R15_GPIO_PU, 0x6f},
+ {TP6800_R16_GPIO_PD, 0x40},
+ {TP6800_R17_GPIO_IO, 0x9f},
+ {TP6800_R18_GPIO_DATA, 0xc1}, /* LED off */
+ };
+
+ if (sd->bridge == BRIDGE_TP6800)
+ reg_w_buf(gspca_dev, tp6800_preinit,
+ ARRAY_SIZE(tp6800_preinit));
+ else
+ reg_w_buf(gspca_dev, tp6810_preinit,
+ ARRAY_SIZE(tp6810_preinit));
+ msleep(15);
+ reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+ PDEBUG(D_PROBE, "gpio: %02x", gspca_dev->usb_buf[0]);
+/* values:
+ * 0x80: snapshot button
+ * 0x40: LED
+ * 0x20: (bridge / sensor) reset for tp6810 ?
+ * 0x07: sensor type ?
+ */
+
+ /* guess the sensor type */
+ if (force_sensor >= 0) {
+ sd->sensor = force_sensor;
+ } else {
+ if (sd->bridge == BRIDGE_TP6800) {
+/*fixme: not sure this is working*/
+ switch (gspca_dev->usb_buf[0] & 0x07) {
+ case 0:
+ sd->sensor = SENSOR_SOI763A;
+ break;
+ case 1:
+ sd->sensor = SENSOR_CX0342;
+ break;
+ }
+ } else {
+ int sensor;
+
+ sensor = probe_6810(gspca_dev);
+ if (sensor < 0) {
+ pr_warn("Unknown sensor %d - forced to soi763a\n",
+ -sensor);
+ sensor = SENSOR_SOI763A;
+ }
+ sd->sensor = sensor;
+ }
+ }
+ if (sd->sensor == SENSOR_SOI763A) {
+ pr_info("Sensor soi763a\n");
+ sd->ctrls[GAMMA].def = sd->bridge == BRIDGE_TP6800 ? 0 : 1;
+ sd->ctrls[GAIN].max = 15;
+ sd->ctrls[GAIN].def = 3;
+ gspca_dev->ctrl_dis = (1 << RGAIN) | (1 << BGAIN);
+ if (sd->bridge == BRIDGE_TP6810) {
+ soi763a_6810_init(gspca_dev);
+#if AUTOGAIN_DEF
+ gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
+#endif
+ } else {
+ gspca_dev->ctrl_dis |= (1 << AUTOGAIN);
+ }
+ } else {
+ pr_info("Sensor cx0342\n");
+ if (sd->bridge == BRIDGE_TP6810) {
+ cx0342_6810_init(gspca_dev);
+#if AUTOGAIN_DEF
+ gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
+#endif
+ } else {
+ gspca_dev->ctrl_dis |= (1 << AUTOGAIN);
+ }
+ }
+
+ if (sd->bridge == BRIDGE_TP6810)
+ sd->ctrls[QUALITY].def = 0; /* auto quality */
+ set_dqt(gspca_dev, 0);
+ return 0;
+}
+
+/* This function is called before choosing the alt setting */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ static const struct cmd cx_sensor_init[] = {
+ {CX0342_AUTO_ADC_CALIB, 0x81},
+ {CX0342_EXPO_LINE_L, 0x37},
+ {CX0342_EXPO_LINE_H, 0x01},
+ {CX0342_RAW_GRGAIN_L, 0x00},
+ {CX0342_RAW_GBGAIN_L, 0x00},
+ {CX0342_RAW_RGAIN_L, 0x00},
+ {CX0342_RAW_BGAIN_L, 0x00},
+ {CX0342_SYS_CTRL_0, 0x81},
+ };
+ static const struct cmd cx_bridge_init[] = {
+ {0x4d, 0x00},
+ {0x4c, 0xff},
+ {0x4e, 0xff},
+ {0x4f, 0x00},
+ };
+ static const struct cmd ov_sensor_init[] = {
+ {0x10, 0x75}, /* exposure */
+ {0x76, 0x03},
+ {0x00, 0x00}, /* gain */
+ };
+ static const struct cmd ov_bridge_init[] = {
+ {0x7b, 0x90},
+ {TP6800_R3F_FRAME_RATE, 0x87},
+ };
+
+ if (sd->bridge == BRIDGE_TP6800)
+ return 0;
+ if (sd->sensor == SENSOR_CX0342) {
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);
+ reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
+ i2c_w_buf(gspca_dev, cx_sensor_init,
+ ARRAY_SIZE(cx_sensor_init));
+ reg_w_buf(gspca_dev, cx_bridge_init,
+ ARRAY_SIZE(cx_bridge_init));
+ bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
+ reg_w(gspca_dev, 0x59, 0x40);
+ } else {
+ reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21);
+ i2c_w_buf(gspca_dev, ov_sensor_init,
+ ARRAY_SIZE(ov_sensor_init));
+ reg_r(gspca_dev, 0x7b);
+ reg_w_buf(gspca_dev, ov_bridge_init,
+ ARRAY_SIZE(ov_bridge_init));
+ }
+ reg_w(gspca_dev, TP6800_R78_FORMAT,
+ gspca_dev->curr_mode ? 0x00 : 0x01);
+ return gspca_dev->usb_err;
+}
+
+static void set_led(struct gspca_dev *gspca_dev, int on)
+{
+ u8 data;
+
+ reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+ data = gspca_dev->usb_buf[0];
+ if (on)
+ data &= ~0x40;
+ else
+ data |= 0x40;
+ reg_w(gspca_dev, TP6800_R18_GPIO_DATA, data);
+}
+
+static void cx0342_6800_start(struct gspca_dev *gspca_dev)
+{
+ static const struct cmd reg_init[] = {
+/*fixme: is this usefull?*/
+ {TP6800_R17_GPIO_IO, 0x9f},
+ {TP6800_R16_GPIO_PD, 0x40},
+ {TP6800_R10_SIF_TYPE, 0x00}, /* i2c 8 bits */
+ {TP6800_R50, 0x00},
+ {TP6800_R51, 0x00},
+ {TP6800_R52, 0xff},
+ {TP6800_R53, 0x03},
+ {TP6800_R54_DARK_CFG, 0x07},
+ {TP6800_R5C_EDGE_THRLD, 0x40},
+ {TP6800_R7A_BLK_THRLD, 0x40},
+ {TP6800_R2F_TIMING_CFG, 0x17},
+ {TP6800_R30_SENSOR_CFG, 0x18}, /* G1B..RG0 */
+ {TP6800_R37_FRONT_DARK_ST, 0x00},
+ {TP6800_R38_FRONT_DARK_END, 0x00},
+ {TP6800_R39_REAR_DARK_ST_L, 0x00},
+ {TP6800_R3A_REAR_DARK_ST_H, 0x00},
+ {TP6800_R3B_REAR_DARK_END_L, 0x00},
+ {TP6800_R3C_REAR_DARK_END_H, 0x00},
+ {TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
+ {TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
+ {TP6800_R21_ENDP_1_CTL, 0x03},
+
+ {TP6800_R31_PIXEL_START, 0x0b},
+ {TP6800_R32_PIXEL_END_L, 0x8a},
+ {TP6800_R33_PIXEL_END_H, 0x02},
+ {TP6800_R34_LINE_START, 0x0e},
+ {TP6800_R35_LINE_END_L, 0xf4},
+ {TP6800_R36_LINE_END_H, 0x01},
+ {TP6800_R78_FORMAT, 0x00},
+ {TP6800_R12_SIF_ADDR_S, 0x20}, /* cx0342 i2c addr */
+ };
+ static const struct cmd sensor_init[] = {
+ {CX0342_OUTPUT_CTRL, 0x07},
+ {CX0342_BYPASS_MODE, 0x58},
+ {CX0342_GPXLTHD_L, 0x16},
+ {CX0342_RBPXLTHD_L, 0x16},
+ {CX0342_PLANETHD_L, 0xc0},
+ {CX0342_PLANETHD_H, 0x03},
+ {CX0342_RB_GAP_L, 0xff},
+ {CX0342_RB_GAP_H, 0x07},
+ {CX0342_G_GAP_L, 0xff},
+ {CX0342_G_GAP_H, 0x07},
+ {CX0342_RST_OVERFLOW_L, 0x5c},
+ {CX0342_RST_OVERFLOW_H, 0x01},
+ {CX0342_DATA_OVERFLOW_L, 0xfc},
+ {CX0342_DATA_OVERFLOW_H, 0x03},
+ {CX0342_DATA_UNDERFLOW_L, 0x00},
+ {CX0342_DATA_UNDERFLOW_H, 0x00},
+ {CX0342_SYS_CTRL_0, 0x40},
+ {CX0342_GLOBAL_GAIN, 0x01},
+ {CX0342_CLOCK_GEN, 0x00},
+ {CX0342_SYS_CTRL_0, 0x02},
+ {CX0342_IDLE_CTRL, 0x05},
+ {CX0342_ADCGN, 0x00},
+ {CX0342_ADC_CTL, 0x00},
+ {CX0342_LVRST_BLBIAS, 0x01},
+ {CX0342_VTHSEL, 0x0b},
+ {CX0342_RAMP_RIV, 0x0b},
+ {CX0342_LDOSEL, 0x07},
+ {CX0342_SPV_VALUE_L, 0x40},
+ {CX0342_SPV_VALUE_H, 0x02},
+ };
+
+ reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
+ i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+ i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
+ reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
+ reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
+ i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
+ i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
+ setexposure(gspca_dev);
+ set_led(gspca_dev, 1);
+ set_resolution(gspca_dev);
+}
+
+static void cx0342_6810_start(struct gspca_dev *gspca_dev)
+{
+ static const struct cmd sensor_init_2[] = {
+ {CX0342_EXPO_LINE_L, 0x6f},
+ {CX0342_EXPO_LINE_H, 0x02},
+ {CX0342_RAW_GRGAIN_L, 0x00},
+ {CX0342_RAW_GBGAIN_L, 0x00},
+ {CX0342_RAW_RGAIN_L, 0x00},
+ {CX0342_RAW_BGAIN_L, 0x00},
+ {CX0342_SYS_CTRL_0, 0x81},
+ };
+ static const struct cmd bridge_init_2[] = {
+ {0x4d, 0x00},
+ {0x4c, 0xff},
+ {0x4e, 0xff},
+ {0x4f, 0x00},
+ {TP6800_R7A_BLK_THRLD, 0x00},
+ {TP6800_R79_QUALITY, 0x04},
+ {TP6800_R79_QUALITY, 0x01},
+ };
+ static const struct cmd bridge_init_3[] = {
+ {TP6800_R31_PIXEL_START, 0x08},
+ {TP6800_R32_PIXEL_END_L, 0x87},
+ {TP6800_R33_PIXEL_END_H, 0x02},
+ {TP6800_R34_LINE_START, 0x0e},
+ {TP6800_R35_LINE_END_L, 0xf4},
+ {TP6800_R36_LINE_END_H, 0x01},
+ };
+ static const struct cmd sensor_init_3[] = {
+ {CX0342_AUTO_ADC_CALIB, 0x81},
+ {CX0342_EXPO_LINE_L, 0x6f},
+ {CX0342_EXPO_LINE_H, 0x02},
+ {CX0342_RAW_GRGAIN_L, 0x00},
+ {CX0342_RAW_GBGAIN_L, 0x00},
+ {CX0342_RAW_RGAIN_L, 0x00},
+ {CX0342_RAW_BGAIN_L, 0x00},
+ {CX0342_SYS_CTRL_0, 0x81},
+ };
+ static const struct cmd bridge_init_5[] = {
+ {0x4d, 0x00},
+ {0x4c, 0xff},
+ {0x4e, 0xff},
+ {0x4f, 0x00},
+ };
+ static const struct cmd sensor_init_4[] = {
+ {CX0342_EXPO_LINE_L, 0xd3},
+ {CX0342_EXPO_LINE_H, 0x01},
+/*fixme: gains, but 00..80 only*/
+ {CX0342_RAW_GRGAIN_L, 0x40},
+ {CX0342_RAW_GBGAIN_L, 0x40},
+ {CX0342_RAW_RGAIN_L, 0x40},
+ {CX0342_RAW_BGAIN_L, 0x40},
+ {CX0342_SYS_CTRL_0, 0x81},
+ };
+ static const struct cmd sensor_init_5[] = {
+ {CX0342_IDLE_CTRL, 0x05},
+ {CX0342_ADCGN, 0x00},
+ {CX0342_ADC_CTL, 0x00},
+ {CX0342_LVRST_BLBIAS, 0x01},
+ {CX0342_VTHSEL, 0x0b},
+ {CX0342_RAMP_RIV, 0x0b},
+ {CX0342_LDOSEL, 0x07},
+ {CX0342_SPV_VALUE_L, 0x40},
+ {CX0342_SPV_VALUE_H, 0x02},
+ {CX0342_AUTO_ADC_CALIB, 0x81},
+ };
+
+ reg_w(gspca_dev, 0x22, gspca_dev->alt);
+ i2c_w_buf(gspca_dev, sensor_init_2, ARRAY_SIZE(sensor_init_2));
+ reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
+ reg_w_buf(gspca_dev, tp6810_cx_init_common,
+ ARRAY_SIZE(tp6810_cx_init_common));
+ reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
+ if (gspca_dev->curr_mode) {
+ reg_w(gspca_dev, 0x4a, 0x7f);
+ reg_w(gspca_dev, 0x07, 0x05);
+ reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
+ } else {
+ reg_w(gspca_dev, 0x4a, 0xff);
+ reg_w(gspca_dev, 0x07, 0x85);
+ reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */
+ }
+ setgamma(gspca_dev);
+ reg_w_buf(gspca_dev, tp6810_bridge_start,
+ ARRAY_SIZE(tp6810_bridge_start));
+ setsharpness(gspca_dev);
+ bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
+ ARRAY_SIZE(color_gain[0]));
+ reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
+ i2c_w_buf(gspca_dev, sensor_init_3, ARRAY_SIZE(sensor_init_3));
+ reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
+ i2c_w_buf(gspca_dev, sensor_init_4, ARRAY_SIZE(sensor_init_4));
+ reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
+ i2c_w_buf(gspca_dev, sensor_init_5, ARRAY_SIZE(sensor_init_5));
+
+ set_led(gspca_dev, 1);
+/* setquality(gspca_dev); */
+}
+
+static void soi763a_6800_start(struct gspca_dev *gspca_dev)
+{
+ static const struct cmd reg_init[] = {
+ {TP6800_R79_QUALITY, 0x04},
+ {TP6800_R79_QUALITY, 0x01},
+ {TP6800_R10_SIF_TYPE, 0x00}, /* i2c 8 bits */
+
+ {TP6800_R50, 0x00},
+ {TP6800_R51, 0x00},
+ {TP6800_R52, 0xff},
+ {TP6800_R53, 0x03},
+ {TP6800_R54_DARK_CFG, 0x07},
+ {TP6800_R5C_EDGE_THRLD, 0x40},
+
+ {TP6800_R79_QUALITY, 0x03},
+ {TP6800_R7A_BLK_THRLD, 0x40},
+
+ {TP6800_R2F_TIMING_CFG, 0x46},
+ {TP6800_R30_SENSOR_CFG, 0x10}, /* BG1..G0R */
+ {TP6800_R37_FRONT_DARK_ST, 0x00},
+ {TP6800_R38_FRONT_DARK_END, 0x00},
+ {TP6800_R39_REAR_DARK_ST_L, 0x00},
+ {TP6800_R3A_REAR_DARK_ST_H, 0x00},
+ {TP6800_R3B_REAR_DARK_END_L, 0x00},
+ {TP6800_R3C_REAR_DARK_END_H, 0x00},
+ {TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
+ {TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
+ {TP6800_R21_ENDP_1_CTL, 0x03},
+
+ {TP6800_R3F_FRAME_RATE, 0x04}, /* 15 fps */
+ {TP6800_R5D_DEMOSAIC_CFG, 0x0e}, /* scale down - medium edge */
+
+ {TP6800_R31_PIXEL_START, 0x1b},
+ {TP6800_R32_PIXEL_END_L, 0x9a},
+ {TP6800_R33_PIXEL_END_H, 0x02},
+ {TP6800_R34_LINE_START, 0x0f},
+ {TP6800_R35_LINE_END_L, 0xf4},
+ {TP6800_R36_LINE_END_H, 0x01},
+ {TP6800_R78_FORMAT, 0x01}, /* qvga */
+ {TP6800_R12_SIF_ADDR_S, 0x21}, /* soi763a i2c addr */
+ {TP6800_R1A_SIF_TX_DATA2, 0x00},
+ };
+ static const struct cmd sensor_init[] = {
+ {0x12, 0x48}, /* mirror - RGB */
+ {0x13, 0xa0}, /* clock - no AGC nor AEC */
+ {0x03, 0xa4}, /* saturation */
+ {0x04, 0x30}, /* hue */
+ {0x05, 0x88}, /* contrast */
+ {0x06, 0x60}, /* brightness */
+ {0x10, 0x41}, /* AEC */
+ {0x11, 0x40}, /* clock rate */
+ {0x13, 0xa0},
+ {0x14, 0x00}, /* 640x480 */
+ {0x15, 0x14},
+ {0x1f, 0x41},
+ {0x20, 0x80},
+ {0x23, 0xee},
+ {0x24, 0x50},
+ {0x25, 0x7a},
+ {0x26, 0x00},
+ {0x27, 0xe2},
+ {0x28, 0xb0},
+ {0x2a, 0x00},
+ {0x2b, 0x00},
+ {0x2d, 0x81},
+ {0x2f, 0x9d},
+ {0x60, 0x80},
+ {0x61, 0x00},
+ {0x62, 0x88},
+ {0x63, 0x11},
+ {0x64, 0x89},
+ {0x65, 0x00},
+ {0x67, 0x94},
+ {0x68, 0x7a},
+ {0x69, 0x0f},
+ {0x6c, 0x80},
+ {0x6d, 0x80},
+ {0x6e, 0x80},
+ {0x6f, 0xff},
+ {0x71, 0x20},
+ {0x74, 0x20},
+ {0x75, 0x86},
+ {0x77, 0xb5},
+ {0x17, 0x18}, /* H href start */
+ {0x18, 0xbf}, /* H href end */
+ {0x19, 0x03}, /* V start */
+ {0x1a, 0xf8}, /* V end */
+ {0x01, 0x80}, /* blue gain */
+ {0x02, 0x80}, /* red gain */
+ };
+
+ reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
+
+ i2c_w(gspca_dev, 0x12, 0x80); /* sensor reset */
+ msleep(10);
+
+ i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+
+ reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
+ reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
+
+ setsharpness(gspca_dev);
+
+ bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
+ ARRAY_SIZE(color_gain[0]));
+
+ set_led(gspca_dev, 1);
+ setexposure(gspca_dev);
+ setquality(gspca_dev);
+ setgamma(gspca_dev);
+}
+
+static void soi763a_6810_start(struct gspca_dev *gspca_dev)
+{
+ static const struct cmd bridge_init_2[] = {
+ {TP6800_R7A_BLK_THRLD, 0x00},
+ {TP6800_R79_QUALITY, 0x04},
+ {TP6800_R79_QUALITY, 0x01},
+ };
+ static const struct cmd bridge_init_3[] = {
+ {TP6800_R31_PIXEL_START, 0x20},
+ {TP6800_R32_PIXEL_END_L, 0x9f},
+ {TP6800_R33_PIXEL_END_H, 0x02},
+ {TP6800_R34_LINE_START, 0x13},
+ {TP6800_R35_LINE_END_L, 0xf8},
+ {TP6800_R36_LINE_END_H, 0x01},
+ };
+ static const struct cmd bridge_init_6[] = {
+ {0x08, 0xff},
+ {0x09, 0xff},
+ {0x0a, 0x5f},
+ {0x0b, 0x80},
+ };
+
+ reg_w(gspca_dev, 0x22, gspca_dev->alt);
+ bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
+ reg_w(gspca_dev, 0x59, 0x40);
+ setexposure(gspca_dev);
+ reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
+ reg_w_buf(gspca_dev, tp6810_ov_init_common,
+ ARRAY_SIZE(tp6810_ov_init_common));
+ reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
+ if (gspca_dev->curr_mode) {
+ reg_w(gspca_dev, 0x4a, 0x7f);
+ reg_w(gspca_dev, 0x07, 0x05);
+ reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
+ } else {
+ reg_w(gspca_dev, 0x4a, 0xff);
+ reg_w(gspca_dev, 0x07, 0x85);
+ reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */
+ }
+ setgamma(gspca_dev);
+ reg_w_buf(gspca_dev, tp6810_bridge_start,
+ ARRAY_SIZE(tp6810_bridge_start));
+
+ if (gspca_dev->curr_mode) {
+ reg_w(gspca_dev, 0x4f, 0x00);
+ reg_w(gspca_dev, 0x4e, 0x7c);
+ }
+
+ reg_w(gspca_dev, 0x00, 0x00);
+
+ setsharpness(gspca_dev);
+ bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
+ ARRAY_SIZE(color_gain[0]));
+ set_led(gspca_dev, 1);
+ reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0xf0);
+ setexposure(gspca_dev);
+ reg_w_buf(gspca_dev, bridge_init_6, ARRAY_SIZE(bridge_init_6));
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width);
+ set_dqt(gspca_dev, sd->quality);
+ if (sd->bridge == BRIDGE_TP6800) {
+ if (sd->sensor == SENSOR_CX0342)
+ cx0342_6800_start(gspca_dev);
+ else
+ soi763a_6800_start(gspca_dev);
+ } else {
+ if (sd->sensor == SENSOR_CX0342)
+ cx0342_6810_start(gspca_dev);
+ else
+ soi763a_6810_start(gspca_dev);
+ reg_w_buf(gspca_dev, tp6810_late_start,
+ ARRAY_SIZE(tp6810_late_start));
+ reg_w(gspca_dev, 0x80, 0x03);
+ reg_w(gspca_dev, 0x82, gspca_dev->curr_mode ? 0x0a : 0x0e);
+
+ setexposure(gspca_dev);
+ setquality(gspca_dev);
+ setautogain(gspca_dev);
+ }
+
+ setframerate(gspca_dev);
+
+ return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->bridge == BRIDGE_TP6800)
+ reg_w(gspca_dev, TP6800_R2F_TIMING_CFG, 0x03);
+ set_led(gspca_dev, 0);
+ reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ u8 *data,
+ int len)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ /* the start of frame contains:
+ * ff d8
+ * ff fe
+ * width / 16
+ * height / 8
+ * quality
+ */
+ if (sd->bridge == BRIDGE_TP6810) {
+ if (*data != 0x5a) {
+/*fixme: don't discard the whole frame..*/
+ if (*data == 0xaa || *data == 0x00)
+ return;
+ if (*data > 0xc0) {
+ PDEBUG(D_FRAM, "bad frame");
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ return;
+ }
+ }
+ data++;
+ len--;
+ if (*data == 0xff && data[1] == 0xd8) {
+/*fixme: there may be information in the 4 high bits*/
+ if ((data[6] & 0x0f) != sd->quality)
+ set_dqt(gspca_dev, data[6] & 0x0f);
+ gspca_frame_add(gspca_dev, FIRST_PACKET,
+ sd->jpeg_hdr, JPEG_HDR_SZ);
+ gspca_frame_add(gspca_dev, INTER_PACKET,
+ data + 7, len - 7);
+ } else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
+ gspca_frame_add(gspca_dev, LAST_PACKET,
+ data, len);
+ } else {
+ gspca_frame_add(gspca_dev, INTER_PACKET,
+ data, len);
+ }
+ return;
+ }
+
+ switch (*data) {
+ case 0x55:
+ gspca_frame_add(gspca_dev, LAST_PACKET, data, 0);
+
+ if (len < 8
+ || data[1] != 0xff || data[2] != 0xd8
+ || data[3] != 0xff || data[4] != 0xfe) {
+
+ /* Have only seen this with corrupt frames */
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ return;
+ }
+ if (data[7] != sd->quality)
+ set_dqt(gspca_dev, data[7]);
+ gspca_frame_add(gspca_dev, FIRST_PACKET,
+ sd->jpeg_hdr, JPEG_HDR_SZ);
+ gspca_frame_add(gspca_dev, INTER_PACKET,
+ data + 8, len - 8);
+ break;
+ case 0xaa:
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ break;
+ case 0xcc:
+ if (data[1] != 0xff || data[2] != 0xd8)
+ gspca_frame_add(gspca_dev, INTER_PACKET,
+ data + 1, len - 1);
+ else
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ break;
+ }
+}
+
+/* -- do autogain -- */
+/* gain setting is done in setexposure() for tp6810 */
+static void setgain(struct gspca_dev *gspca_dev) {}
+/* !! coarse_grained_expo_autogain is not used !! */
+#define exp_too_low_cnt bridge
+#define exp_too_high_cnt sensor
+
+#include "autogain_functions.h"
+static void sd_dq_callback(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int ret, alen;
+ int luma, expo;
+
+ if (sd->ag_cnt < 0)
+ return;
+ if (--sd->ag_cnt > 5)
+ return;
+ switch (sd->ag_cnt) {
+/* case 5: */
+ default:
+ reg_w(gspca_dev, 0x7d, 0x00);
+ break;
+ case 4:
+ reg_w(gspca_dev, 0x27, 0xb0);
+ break;
+ case 3:
+ reg_w(gspca_dev, 0x0c, 0x01);
+ break;
+ case 2:
+ ret = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x02),
+ gspca_dev->usb_buf,
+ 32,
+ &alen,
+ 500);
+ if (ret < 0) {
+ pr_err("bulk err %d\n", ret);
+ break;
+ }
+ /* values not used (unknown) */
+ break;
+ case 1:
+ reg_w(gspca_dev, 0x27, 0xd0);
+ break;
+ case 0:
+ ret = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x02),
+ gspca_dev->usb_buf,
+ 32,
+ &alen,
+ 500);
+ if (ret < 0) {
+ pr_err("bulk err %d\n", ret);
+ break;
+ }
+ luma = ((gspca_dev->usb_buf[8] << 8) + gspca_dev->usb_buf[7] +
+ (gspca_dev->usb_buf[11] << 8) + gspca_dev->usb_buf[10] +
+ (gspca_dev->usb_buf[14] << 8) + gspca_dev->usb_buf[13] +
+ (gspca_dev->usb_buf[17] << 8) + gspca_dev->usb_buf[16] +
+ (gspca_dev->usb_buf[20] << 8) + gspca_dev->usb_buf[19] +
+ (gspca_dev->usb_buf[23] << 8) + gspca_dev->usb_buf[22] +
+ (gspca_dev->usb_buf[26] << 8) + gspca_dev->usb_buf[25] +
+ (gspca_dev->usb_buf[29] << 8) + gspca_dev->usb_buf[28])
+ / 8;
+ if (gspca_dev->width == 640)
+ luma /= 4;
+ reg_w(gspca_dev, 0x7d, 0x00);
+
+ expo = sd->ctrls[EXPOSURE].val;
+ ret = auto_gain_n_exposure(gspca_dev, luma,
+ 60, /* desired luma */
+ 6, /* dead zone */
+ 2, /* gain knee */
+ 70); /* expo knee */
+ sd->ag_cnt = AG_CNT_START;
+ if (sd->bridge == BRIDGE_TP6810) {
+ if ((expo >= 128 && sd->ctrls[EXPOSURE].val < 128)
+ || (expo < 128 && sd->ctrls[EXPOSURE].val >= 128))
+ setframerate(gspca_dev);
+ }
+ break;
+ }
+}
+
+/* get stream parameters (framerate) */
+static void sd_get_streamparm(struct gspca_dev *gspca_dev,
+ struct v4l2_streamparm *parm)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct v4l2_captureparm *cp = &parm->parm.capture;
+ struct v4l2_fract *tpf = &cp->timeperframe;
+ int fr, i;
+
+ cp->capability |= V4L2_CAP_TIMEPERFRAME;
+ tpf->numerator = 1;
+ i = get_fr_idx(gspca_dev);
+ if (i & 0x80) {
+ if (sd->bridge == BRIDGE_TP6800)
+ fr = rates[6 - (i & 0x07)];
+ else
+ fr = rates_6810[7 - (i & 0x07)];
+ } else {
+ fr = rates[6 - i];
+ }
+ tpf->denominator = fr;
+}
+
+/* set stream parameters (framerate) */
+static void sd_set_streamparm(struct gspca_dev *gspca_dev,
+ struct v4l2_streamparm *parm)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct v4l2_captureparm *cp = &parm->parm.capture;
+ struct v4l2_fract *tpf = &cp->timeperframe;
+ int fr, i;
+
+ sd->framerate = tpf->denominator / tpf->numerator;
+ if (gspca_dev->streaming)
+ setframerate(gspca_dev);
+
+ /* Return the actual framerate */
+ i = get_fr_idx(gspca_dev);
+ if (i & 0x80)
+ fr = rates_6810[7 - (i & 0x07)];
+ else
+ fr = rates[6 - i];
+ tpf->numerator = 1;
+ tpf->denominator = fr;
+}
+
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+ struct v4l2_jpegcompression *jcomp)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->sensor == SENSOR_SOI763A)
+ jpeg_set_qual(sd->jpeg_hdr, jcomp->quality);
+/* else
+ fixme: TODO
+*/
+ return gspca_dev->usb_err;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+ struct v4l2_jpegcompression *jcomp)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ memset(jcomp, 0, sizeof *jcomp);
+ jcomp->quality = jpeg_q[sd->quality];
+ jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+ | V4L2_JPEG_MARKER_DQT;
+ return 0;
+}
+
+static struct ctrl sd_ctrls[NCTRLS] = {
+[EXPOSURE] = {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure",
+ .minimum = 0x01,
+ .maximum = 0xdc,
+ .step = 1,
+ .default_value = 0x4e,
+ },
+ .set_control = setexposure
+ },
+[QUALITY] = {
+ {
+ .id = V4L2_CID_PRIVATE_BASE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Compression quality",
+ .minimum = 0,
+ .maximum = 15,
+ .step = 1,
+ .default_value = 13,
+ },
+ .set_control = setquality
+ },
+[RGAIN] = {
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Red balance",
+ .minimum = 0,
+ .maximum = 4095,
+ .step = 1,
+ .default_value = 256,
+ },
+ .set_control = setrgain
+ },
+[GAIN] = {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = 0,
+ .maximum = 4095,
+ .step = 1,
+ .default_value = 256,
+ },
+ .set = sd_setgain
+ },
+[BGAIN] = {
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Blue balance",
+ .minimum = 0,
+ .maximum = 4095,
+ .step = 1,
+ .default_value = 256,
+ },
+ .set_control = setbgain
+ },
+[SHARPNESS] = {
+ {
+ .id = V4L2_CID_SHARPNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Sharpness",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 2,
+ },
+ .set_control = setsharpness
+ },
+[GAMMA] = {
+ {
+ .id = V4L2_CID_GAMMA,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gamma",
+ .minimum = 0,
+ .maximum = NGAMMA - 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ .set_control = setgamma
+ },
+[AUTOGAIN] = {
+ {
+ .id = V4L2_CID_AUTOGAIN,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Auto Gain",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = AUTOGAIN_DEF
+ },
+ .set_control = setautogain
+ },
+};
+
+static const struct sd_desc sd_desc = {
+ .name = KBUILD_MODNAME,
+ .ctrls = sd_ctrls,
+ .nctrls = NCTRLS,
+ .config = sd_config,
+ .init = sd_init,
+ .isoc_init = sd_isoc_init,
+ .start = sd_start,
+ .stopN = sd_stopN,
+ .pkt_scan = sd_pkt_scan,
+ .dq_callback = sd_dq_callback,
+ .get_streamparm = sd_get_streamparm,
+ .set_streamparm = sd_set_streamparm,
+ .get_jcomp = sd_get_jcomp,
+ .set_jcomp = sd_set_jcomp,
+};
+
+static const struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x06a2, 0x0003), .driver_info = BRIDGE_TP6800},
+ {USB_DEVICE(0x06a2, 0x6810), .driver_info = BRIDGE_TP6810},
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+static int sd_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ return gspca_dev_probe(interface, id, &sd_desc, sizeof(struct sd),
+ THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = device_table,
+ .probe = sd_probe,
+ .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+ .reset_resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+ return usb_register(&sd_driver);
+}
+static void __exit sd_mod_exit(void)
+{
+ usb_deregister(&sd_driver);
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
+
+module_param(force_sensor, int, 0644);
+MODULE_PARM_DESC(force_sensor,
+ "Force sensor. 0: cx0342, 1: soi763a");
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index 6caed734a06a..7ee2c8271dcc 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "vc032x"
#include "gspca.h"
@@ -3169,7 +3171,7 @@ static void reg_r_i(struct gspca_dev *gspca_dev,
index, gspca_dev->usb_buf, len,
500);
if (ret < 0) {
- err("reg_r err %d", ret);
+ pr_err("reg_r err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -3210,7 +3212,7 @@ static void reg_w_i(struct gspca_dev *gspca_dev,
value, index, NULL, 0,
500);
if (ret < 0) {
- err("reg_w err %d", ret);
+ pr_err("reg_w err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -3235,8 +3237,7 @@ static u16 read_sensor_register(struct gspca_dev *gspca_dev,
reg_r(gspca_dev, 0xa1, 0xb33f, 1);
if (!(gspca_dev->usb_buf[0] & 0x02)) {
- err("I2c Bus Busy Wait %02x",
- gspca_dev->usb_buf[0]);
+ pr_err("I2c Bus Busy Wait %02x\n", gspca_dev->usb_buf[0]);
return 0;
}
reg_w(gspca_dev, 0xa0, address, 0xb33a);
@@ -3349,7 +3350,7 @@ static void i2c_write(struct gspca_dev *gspca_dev,
msleep(20);
} while (--retry > 0);
if (retry <= 0)
- err("i2c_write timeout");
+ pr_err("i2c_write timeout\n");
}
static void put_tab_to_reg(struct gspca_dev *gspca_dev,
@@ -3446,7 +3447,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
switch (sensor) {
case -1:
- err("Unknown sensor...");
+ pr_err("Unknown sensor...\n");
return -EINVAL;
case SENSOR_HV7131R:
PDEBUG(D_PROBE, "Find Sensor HV7131R");
diff --git a/drivers/media/video/gspca/vicam.c b/drivers/media/video/gspca/vicam.c
index 84dfbab923b5..81dd4c99d025 100644
--- a/drivers/media/video/gspca/vicam.c
+++ b/drivers/media/video/gspca/vicam.c
@@ -26,6 +26,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "vicam"
#define HEADER_SIZE 64
@@ -117,7 +119,7 @@ static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index, data, len, 1000);
if (ret < 0)
- err("control msg req %02X error %d", request, ret);
+ pr_err("control msg req %02X error %d\n", request, ret);
return ret;
}
@@ -189,8 +191,8 @@ static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
data, size, &act_len, 10000);
/* successful, it returns 0, otherwise negative */
if (ret < 0 || act_len != size) {
- err("bulk read fail (%d) len %d/%d",
- ret, act_len, size);
+ pr_err("bulk read fail (%d) len %d/%d\n",
+ ret, act_len, size);
return -EIO;
}
return 0;
@@ -216,7 +218,7 @@ static void vicam_dostream(struct work_struct *work)
HEADER_SIZE;
buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA);
if (!buffer) {
- err("Couldn't allocate USB buffer");
+ pr_err("Couldn't allocate USB buffer\n");
goto exit;
}
@@ -269,7 +271,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
ret = request_ihex_firmware(&fw, "vicam/firmware.fw",
&gspca_dev->dev->dev);
if (ret) {
- err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
+ pr_err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
return ret;
}
diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c
index 4a9e622e5e1b..27d2cef0692a 100644
--- a/drivers/media/video/gspca/w996Xcf.c
+++ b/drivers/media/video/gspca/w996Xcf.c
@@ -31,6 +31,8 @@
the sensor drivers to v4l2 sub drivers, and properly split of this
driver from ov519.c */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */
#define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET])
@@ -81,7 +83,7 @@ static void w9968cf_write_fsb(struct sd *sd, u16* data)
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
if (ret < 0) {
- err("Write FSB registers failed (%d)", ret);
+ pr_err("Write FSB registers failed (%d)\n", ret);
sd->gspca_dev.usb_err = ret;
}
}
@@ -108,7 +110,7 @@ static void w9968cf_write_sb(struct sd *sd, u16 value)
udelay(W9968CF_I2C_BUS_DELAY);
if (ret < 0) {
- err("Write SB reg [01] %04x failed", value);
+ pr_err("Write SB reg [01] %04x failed\n", value);
sd->gspca_dev.usb_err = ret;
}
}
@@ -135,7 +137,7 @@ static int w9968cf_read_sb(struct sd *sd)
ret = sd->gspca_dev.usb_buf[0] |
(sd->gspca_dev.usb_buf[1] << 8);
} else {
- err("Read SB reg [01] failed");
+ pr_err("Read SB reg [01] failed\n");
sd->gspca_dev.usb_err = ret;
}
diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c
index c089a0f6f1d0..3aed42acdb5a 100644
--- a/drivers/media/video/gspca/xirlink_cit.c
+++ b/drivers/media/video/gspca/xirlink_cit.c
@@ -27,6 +27,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "xirlink-cit"
#include <linux/input.h>
@@ -800,8 +802,8 @@ static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
value, index, NULL, 0, 1000);
if (err < 0)
- err("Failed to write a register (index 0x%04X,"
- " value 0x%02X, error %d)", index, value, err);
+ pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
+ index, value, err);
return 0;
}
@@ -816,8 +818,8 @@ static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
0x00, index, buf, 8, 1000);
if (res < 0) {
- err("Failed to read a register (index 0x%04X, error %d)",
- index, res);
+ pr_err("Failed to read a register (index 0x%04X, error %d)\n",
+ index, res);
return res;
}
@@ -1587,7 +1589,7 @@ static int cit_get_packet_size(struct gspca_dev *gspca_dev)
intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
alt = usb_altnum_to_altsetting(intf, gspca_dev->alt);
if (!alt) {
- err("Couldn't get altsetting");
+ pr_err("Couldn't get altsetting\n");
return -EIO;
}
@@ -2824,7 +2826,7 @@ static int sd_isoc_nego(struct gspca_dev *gspca_dev)
ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
if (ret < 0)
- err("set alt 1 err %d", ret);
+ pr_err("set alt 1 err %d\n", ret);
return ret;
}
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 61cdd56a74a9..30ea1e479492 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define MODULE_NAME "zc3xx"
#include <linux/input.h>
@@ -5666,7 +5668,7 @@ static u8 reg_r_i(struct gspca_dev *gspca_dev,
index, gspca_dev->usb_buf, 1,
500);
if (ret < 0) {
- err("reg_r_i err %d", ret);
+ pr_err("reg_r_i err %d\n", ret);
gspca_dev->usb_err = ret;
return 0;
}
@@ -5698,7 +5700,7 @@ static void reg_w_i(struct gspca_dev *gspca_dev,
value, index, NULL, 0,
500);
if (ret < 0) {
- err("reg_w_i err %d", ret);
+ pr_err("reg_w_i err %d\n", ret);
gspca_dev->usb_err = ret;
}
}
@@ -5724,7 +5726,7 @@ static u16 i2c_read(struct gspca_dev *gspca_dev,
msleep(20);
retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
if (retbyte != 0x00)
- err("i2c_r status error %02x", retbyte);
+ pr_err("i2c_r status error %02x\n", retbyte);
retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */
retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */
PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)",
@@ -5748,7 +5750,7 @@ static u8 i2c_write(struct gspca_dev *gspca_dev,
msleep(1);
retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
if (retbyte != 0x00)
- err("i2c_w status error %02x", retbyte);
+ pr_err("i2c_w status error %02x\n", retbyte);
PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)",
reg, valH, valL, retbyte);
return retbyte;
@@ -6497,7 +6499,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
PDEBUG(D_PROBE, "Sensor GC0303");
break;
default:
- warn("Unknown sensor - set to TAS5130C");
+ pr_warn("Unknown sensor - set to TAS5130C\n");
sd->sensor = SENSOR_TAS5130C;
}
break;
@@ -6603,7 +6605,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
sd->sensor = SENSOR_OV7620; /* same sensor (?) */
break;
default:
- err("Unknown sensor %04x", sensor);
+ pr_err("Unknown sensor %04x\n", sensor);
return -EINVAL;
}
}
@@ -6970,6 +6972,7 @@ static const struct sd_desc sd_desc = {
};
static const struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x03f0, 0x1b07)},
{USB_DEVICE(0x041e, 0x041e)},
{USB_DEVICE(0x041e, 0x4017)},
{USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile
index 3baa9f613ca3..52f057f24e39 100644
--- a/drivers/media/video/hdpvr/Makefile
+++ b/drivers/media/video/hdpvr/Makefile
@@ -2,6 +2,6 @@ hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o
obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
-EXTRA_CFLAGS += -Idrivers/media/video
+ccflags-y += -Idrivers/media/video
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
index cbc505a2fc29..9cb039e593db 100644
--- a/drivers/media/video/hexium_gemini.c
+++ b/drivers/media/video/hexium_gemini.c
@@ -21,6 +21,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define DEBUG_VARIABLE debug
#include <media/saa7146_vv.h>
@@ -175,13 +177,14 @@ static int hexium_init_done(struct saa7146_dev *dev)
union i2c_smbus_data data;
int i = 0;
- DEB_D(("hexium_init_done called.\n"));
+ DEB_D("hexium_init_done called\n");
/* initialize the helper ics to useful values */
for (i = 0; i < sizeof(hexium_ks0127b); i++) {
data.byte = hexium_ks0127b[i];
if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
- printk("hexium_gemini: hexium_init_done() failed for address 0x%02x\n", i);
+ pr_err("hexium_init_done() failed for address 0x%02x\n",
+ i);
}
}
@@ -192,7 +195,7 @@ static int hexium_set_input(struct hexium *hexium, int input)
{
union i2c_smbus_data data;
- DEB_D((".\n"));
+ DEB_D("\n");
data.byte = hexium_input_select[input].byte;
if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) {
@@ -207,12 +210,13 @@ static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)
union i2c_smbus_data data;
int i = 0;
- DEB_D((".\n"));
+ DEB_D("\n");
while (vdec[i].adr != -1) {
data.byte = vdec[i].byte;
if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {
- printk("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n", i);
+ pr_err("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n",
+ i);
return -1;
}
i++;
@@ -222,14 +226,14 @@ static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{
- DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+ DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
if (i->index >= HEXIUM_INPUTS)
return -EINVAL;
memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
- DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
+ DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
return 0;
}
@@ -240,7 +244,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
*input = hexium->cur_input;
- DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
+ DEB_D("VIDIOC_G_INPUT: %d\n", *input);
return 0;
}
@@ -249,7 +253,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
- DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
+ DEB_EE("VIDIOC_S_INPUT %d\n", input);
if (input >= HEXIUM_INPUTS)
return -EINVAL;
@@ -270,7 +274,7 @@ static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *
for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
if (hexium_controls[i].id == qc->id) {
*qc = hexium_controls[i];
- DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
+ DEB_D("VIDIOC_QUERYCTRL %d\n", qc->id);
return 0;
}
}
@@ -293,7 +297,7 @@ static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
if (vc->id == V4L2_CID_PRIVATE_BASE) {
vc->value = hexium->cur_bw;
- DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
+ DEB_D("VIDIOC_G_CTRL BW:%d\n", vc->value);
return 0;
}
return -EINVAL;
@@ -316,7 +320,7 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
if (vc->id == V4L2_CID_PRIVATE_BASE)
hexium->cur_bw = vc->value;
- DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
+ DEB_D("VIDIOC_S_CTRL BW:%d\n", hexium->cur_bw);
if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
hexium_set_standard(hexium, hexium_pal);
@@ -351,14 +355,14 @@ static struct saa7146_ext_vv vv_data;
/* this function only gets called when the probing was successful */
static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
{
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
+ struct hexium *hexium;
int ret;
- DEB_EE((".\n"));
+ DEB_EE("\n");
hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
if (NULL == hexium) {
- printk("hexium_gemini: not enough kernel memory in hexium_attach().\n");
+ pr_err("not enough kernel memory in hexium_attach()\n");
return -ENOMEM;
}
dev->ext_priv = hexium;
@@ -371,7 +375,7 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
};
saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
- DEB_S(("cannot register i2c-device. skipping.\n"));
+ DEB_S("cannot register i2c-device. skipping.\n");
kfree(hexium);
return -EFAULT;
}
@@ -402,11 +406,11 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
vv_data.ops.vidioc_s_input = vidioc_s_input;
ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER);
if (ret < 0) {
- printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n");
+ pr_err("cannot register capture v4l2 device. skipping.\n");
return ret;
}
- printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num);
+ pr_info("found 'hexium gemini' frame grabber-%d\n", hexium_num);
hexium_num++;
return 0;
@@ -416,7 +420,7 @@ static int hexium_detach(struct saa7146_dev *dev)
{
struct hexium *hexium = (struct hexium *) dev->ext_priv;
- DEB_EE(("dev:%p\n", dev));
+ DEB_EE("dev:%p\n", dev);
saa7146_unregister_device(&hexium->video_dev, dev);
saa7146_vv_release(dev);
@@ -508,7 +512,7 @@ static struct saa7146_extension hexium_extension = {
static int __init hexium_init_module(void)
{
if (0 != saa7146_register_extension(&hexium_extension)) {
- DEB_S(("failed to register extension.\n"));
+ DEB_S("failed to register extension\n");
return -ENODEV;
}
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
index 6ad7e1c8b922..74861a4b601a 100644
--- a/drivers/media/video/hexium_orion.c
+++ b/drivers/media/video/hexium_orion.c
@@ -21,6 +21,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define DEBUG_VARIABLE debug
#include <media/saa7146_vv.h>
@@ -209,7 +211,7 @@ static int hexium_probe(struct saa7146_dev *dev)
union i2c_smbus_data data;
int err = 0;
- DEB_EE((".\n"));
+ DEB_EE("\n");
/* there are no hexium orion cards with revision 0 saa7146s */
if (0 == dev->revision) {
@@ -218,7 +220,7 @@ static int hexium_probe(struct saa7146_dev *dev)
hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
if (NULL == hexium) {
- printk("hexium_orion: hexium_probe: not enough kernel memory.\n");
+ pr_err("hexium_probe: not enough kernel memory\n");
return -ENOMEM;
}
@@ -234,7 +236,7 @@ static int hexium_probe(struct saa7146_dev *dev)
};
saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
- DEB_S(("cannot register i2c-device. skipping.\n"));
+ DEB_S("cannot register i2c-device. skipping.\n");
kfree(hexium);
return -EFAULT;
}
@@ -248,7 +250,7 @@ static int hexium_probe(struct saa7146_dev *dev)
/* detect newer Hexium Orion cards by subsystem ids */
if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) {
- printk("hexium_orion: device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs.\n");
+ pr_info("device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs\n");
/* we store the pointer in our private data field */
dev->ext_priv = hexium;
hexium->type = HEXIUM_ORION_1SVHS_3BNC;
@@ -256,7 +258,7 @@ static int hexium_probe(struct saa7146_dev *dev)
}
if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) {
- printk("hexium_orion: device is a Hexium Orion w/ 4 BNC inputs.\n");
+ pr_info("device is a Hexium Orion w/ 4 BNC inputs\n");
/* we store the pointer in our private data field */
dev->ext_priv = hexium;
hexium->type = HEXIUM_ORION_4BNC;
@@ -266,7 +268,7 @@ static int hexium_probe(struct saa7146_dev *dev)
/* check if this is an old hexium Orion card by looking at
a saa7110 at address 0x4e */
if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) {
- printk("hexium_orion: device is a Hexium HV-PCI6/Orion (old).\n");
+ pr_info("device is a Hexium HV-PCI6/Orion (old)\n");
/* we store the pointer in our private data field */
dev->ext_priv = hexium;
hexium->type = HEXIUM_HV_PCI6_ORION;
@@ -288,13 +290,13 @@ static int hexium_init_done(struct saa7146_dev *dev)
union i2c_smbus_data data;
int i = 0;
- DEB_D(("hexium_init_done called.\n"));
+ DEB_D("hexium_init_done called\n");
/* initialize the helper ics to useful values */
for (i = 0; i < sizeof(hexium_saa7110); i++) {
data.byte = hexium_saa7110[i];
if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
- printk("hexium_orion: failed for address 0x%02x\n", i);
+ pr_err("failed for address 0x%02x\n", i);
}
}
@@ -306,7 +308,7 @@ static int hexium_set_input(struct hexium *hexium, int input)
union i2c_smbus_data data;
int i = 0;
- DEB_D((".\n"));
+ DEB_D("\n");
for (i = 0; i < 8; i++) {
int adr = hexium_input_select[input].data[i].adr;
@@ -314,7 +316,7 @@ static int hexium_set_input(struct hexium *hexium, int input)
if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, adr, I2C_SMBUS_BYTE_DATA, &data)) {
return -1;
}
- printk("%d: 0x%02x => 0x%02x\n",input, adr,data.byte);
+ pr_debug("%d: 0x%02x => 0x%02x\n", input, adr, data.byte);
}
return 0;
@@ -322,14 +324,14 @@ static int hexium_set_input(struct hexium *hexium, int input)
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{
- DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+ DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
if (i->index >= HEXIUM_INPUTS)
return -EINVAL;
memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
- DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
+ DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
return 0;
}
@@ -340,7 +342,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
*input = hexium->cur_input;
- DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
+ DEB_D("VIDIOC_G_INPUT: %d\n", *input);
return 0;
}
@@ -365,18 +367,18 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
{
struct hexium *hexium = (struct hexium *) dev->ext_priv;
- DEB_EE((".\n"));
+ DEB_EE("\n");
saa7146_vv_init(dev, &vv_data);
vv_data.ops.vidioc_enum_input = vidioc_enum_input;
vv_data.ops.vidioc_g_input = vidioc_g_input;
vv_data.ops.vidioc_s_input = vidioc_s_input;
if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
- printk("hexium_orion: cannot register capture v4l2 device. skipping.\n");
+ pr_err("cannot register capture v4l2 device. skipping.\n");
return -1;
}
- printk("hexium_orion: found 'hexium orion' frame grabber-%d.\n", hexium_num);
+ pr_err("found 'hexium orion' frame grabber-%d\n", hexium_num);
hexium_num++;
/* the rest */
@@ -390,7 +392,7 @@ static int hexium_detach(struct saa7146_dev *dev)
{
struct hexium *hexium = (struct hexium *) dev->ext_priv;
- DEB_EE(("dev:%p\n", dev));
+ DEB_EE("dev:%p\n", dev);
saa7146_unregister_device(&hexium->video_dev, dev);
saa7146_vv_release(dev);
@@ -479,7 +481,7 @@ static struct saa7146_extension extension = {
static int __init hexium_init_module(void)
{
if (0 != saa7146_register_extension(&extension)) {
- DEB_S(("failed to register extension.\n"));
+ DEB_S("failed to register extension\n");
return -ENODEV;
}
diff --git a/drivers/media/video/ivtv/Makefile b/drivers/media/video/ivtv/Makefile
index 26ce0d6eaee1..71ab76a5ab26 100644
--- a/drivers/media/video/ivtv/Makefile
+++ b/drivers/media/video/ivtv/Makefile
@@ -7,8 +7,8 @@ ivtv-objs := ivtv-routing.o ivtv-cards.o ivtv-controls.o \
obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 3e5c090af112..ecafa697326e 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -1203,9 +1203,7 @@ static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced
cap->service_lines[f][l] = set;
}
}
- return 0;
- }
- if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
+ } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
return -EINVAL;
if (itv->is_60hz) {
@@ -1215,9 +1213,16 @@ static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced
cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
cap->service_lines[0][16] = V4L2_SLICED_VPS;
}
- return 0;
+ } else {
+ return -EINVAL;
}
- return -EINVAL;
+
+ set = 0;
+ for (f = 0; f < 2; f++)
+ for (l = 0; l < 24; l++)
+ set |= cap->service_lines[f][l];
+ cap->service_set = set;
+ return 0;
}
static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c
index fb8e4a7a9dd2..5d21d056d6a3 100644
--- a/drivers/media/video/m5mols/m5mols_core.c
+++ b/drivers/media/video/m5mols/m5mols_core.c
@@ -936,7 +936,7 @@ static int __devinit m5mols_probe(struct i2c_client *client,
return -EINVAL;
}
- if (!pdata->irq) {
+ if (!client->irq) {
dev_err(&client->dev, "Interrupt not assigned\n");
return -EINVAL;
}
@@ -973,7 +973,7 @@ static int __devinit m5mols_probe(struct i2c_client *client,
init_waitqueue_head(&info->irq_waitq);
INIT_WORK(&info->work_irq, m5mols_irq_work);
- ret = request_irq(pdata->irq, m5mols_irq_handler,
+ ret = request_irq(client->irq, m5mols_irq_handler,
IRQF_TRIGGER_RISING, MODULE_NAME, sd);
if (ret) {
dev_err(&client->dev, "Interrupt request failed: %d\n", ret);
@@ -998,7 +998,7 @@ static int __devexit m5mols_remove(struct i2c_client *client)
struct m5mols_info *info = to_m5mols(sd);
v4l2_device_unregister_subdev(sd);
- free_irq(info->pdata->irq, sd);
+ free_irq(client->irq, sd);
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
gpio_free(info->pdata->gpio_reset);
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c
index 83c14514cd52..1141b976dff4 100644
--- a/drivers/media/video/marvell-ccic/mcam-core.c
+++ b/drivers/media/video/marvell-ccic/mcam-core.c
@@ -450,7 +450,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
buf = cam->vb_bufs[frame ^ 0x1];
cam->vb_bufs[frame] = buf;
mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
- vb2_dma_contig_plane_paddr(&buf->vb_buf, 0));
+ vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
set_bit(CF_SINGLE_BUFFER, &cam->flags);
singles++;
return;
@@ -461,7 +461,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
list_del_init(&buf->queue);
mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
- vb2_dma_contig_plane_paddr(&buf->vb_buf, 0));
+ vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
cam->vb_bufs[frame] = buf;
clear_bit(CF_SINGLE_BUFFER, &cam->flags);
}
@@ -884,7 +884,7 @@ static int mcam_read_setup(struct mcam_camera *cam)
*/
static int mcam_vb_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
- unsigned int *num_planes, unsigned long sizes[],
+ unsigned int *num_planes, unsigned int sizes[],
void *alloc_ctxs[])
{
struct mcam_camera *cam = vb2_get_drv_priv(vq);
@@ -940,12 +940,14 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
/*
* These need to be called with the mutex held from vb2
*/
-static int mcam_vb_start_streaming(struct vb2_queue *vq)
+static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct mcam_camera *cam = vb2_get_drv_priv(vq);
- if (cam->state != S_IDLE)
+ if (cam->state != S_IDLE) {
+ INIT_LIST_HEAD(&cam->buffers);
return -EINVAL;
+ }
cam->sequence = 0;
/*
* Videobuf2 sneakily hoards all the buffers and won't
diff --git a/drivers/media/video/marvell-ccic/mmp-driver.c b/drivers/media/video/marvell-ccic/mmp-driver.c
index d6b764541375..fb0b124b35f3 100644
--- a/drivers/media/video/marvell-ccic/mmp-driver.c
+++ b/drivers/media/video/marvell-ccic/mmp-driver.c
@@ -29,6 +29,7 @@
#include "mcam-core.h"
+MODULE_ALIAS("platform:mmp-camera");
MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c
index 166bf9349c10..9594b52f8605 100644
--- a/drivers/media/video/mem2mem_testdev.c
+++ b/drivers/media/video/mem2mem_testdev.c
@@ -739,7 +739,7 @@ static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = {
*/
static int m2mtest_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned long sizes[],
+ unsigned int *nplanes, unsigned int sizes[],
void *alloc_ctxs[])
{
struct m2mtest_ctx *ctx = vb2_get_drv_priv(vq);
@@ -793,10 +793,24 @@ static void m2mtest_buf_queue(struct vb2_buffer *vb)
v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
}
+static void m2mtest_wait_prepare(struct vb2_queue *q)
+{
+ struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
+ m2mtest_unlock(ctx);
+}
+
+static void m2mtest_wait_finish(struct vb2_queue *q)
+{
+ struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
+ m2mtest_lock(ctx);
+}
+
static struct vb2_ops m2mtest_qops = {
.queue_setup = m2mtest_queue_setup,
.buf_prepare = m2mtest_buf_prepare,
.buf_queue = m2mtest_buf_queue,
+ .wait_prepare = m2mtest_wait_prepare,
+ .wait_finish = m2mtest_wait_finish,
};
static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index c43c81f5f978..d0f538857285 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -426,6 +426,20 @@ static int msp_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
return 0;
}
+static int msp_querystd(struct v4l2_subdev *sd, v4l2_std_id *id)
+{
+ struct msp_state *state = to_state(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ *id &= state->detected_std;
+
+ v4l_dbg(2, msp_debug, client,
+ "detected standard: %s(0x%08Lx)\n",
+ msp_standard_std_name(state->std), state->detected_std);
+
+ return 0;
+}
+
static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id)
{
struct msp_state *state = to_state(sd);
@@ -616,6 +630,10 @@ static const struct v4l2_subdev_core_ops msp_core_ops = {
.s_std = msp_s_std,
};
+static const struct v4l2_subdev_video_ops msp_video_ops = {
+ .querystd = msp_querystd,
+};
+
static const struct v4l2_subdev_tuner_ops msp_tuner_ops = {
.s_frequency = msp_s_frequency,
.g_tuner = msp_g_tuner,
@@ -630,6 +648,7 @@ static const struct v4l2_subdev_audio_ops msp_audio_ops = {
static const struct v4l2_subdev_ops msp_ops = {
.core = &msp_core_ops,
+ .video = &msp_video_ops,
.tuner = &msp_tuner_ops,
.audio = &msp_audio_ops,
};
@@ -664,6 +683,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
v4l2_i2c_subdev_init(sd, client, &msp_ops);
state->v4l2_std = V4L2_STD_NTSC;
+ state->detected_std = V4L2_STD_ALL;
state->audmode = V4L2_TUNER_MODE_STEREO;
state->input = -1;
state->i2s_mode = 0;
diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h
index 32a478e532f3..831e8db4368c 100644
--- a/drivers/media/video/msp3400-driver.h
+++ b/drivers/media/video/msp3400-driver.h
@@ -75,7 +75,7 @@ struct msp_state {
int opmode;
int std;
int mode;
- v4l2_std_id v4l2_std;
+ v4l2_std_id v4l2_std, detected_std;
int nicam_on;
int acb;
int in_scart;
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index 80387e2c3eca..f8b51714f2f9 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -37,29 +37,49 @@ static struct {
int retval;
int main, second;
char *name;
+ v4l2_std_id std;
} msp_stdlist[] = {
- { 0x0000, 0, 0, "could not detect sound standard" },
- { 0x0001, 0, 0, "autodetect start" },
- { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" },
- { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" },
- { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" },
- { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" },
- { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" },
- { 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), "6.5/5.74 D/K3 Dual FM-Stereo" },
- { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" },
- { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" },
- { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" },
- { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" },
- { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" },
- { 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV3)" },
- { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" },
- { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" },
- { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" },
- { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" },
- { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" },
- { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" },
- { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" },
- { -1, 0, 0, NULL }, /* EOF */
+ { 0x0000, 0, 0, "could not detect sound standard", V4L2_STD_ALL },
+ { 0x0001, 0, 0, "autodetect start", V4L2_STD_ALL },
+ { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72),
+ "4.5/4.72 M Dual FM-Stereo", V4L2_STD_MN },
+ { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875),
+ "5.5/5.74 B/G Dual FM-Stereo", V4L2_STD_BG },
+ { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125),
+ "6.5/6.25 D/K1 Dual FM-Stereo", V4L2_STD_DK },
+ { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875),
+ "6.5/6.74 D/K2 Dual FM-Stereo", V4L2_STD_DK },
+ { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+ "6.5 D/K FM-Mono (HDEV3)", V4L2_STD_DK },
+ { 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875),
+ "6.5/5.74 D/K3 Dual FM-Stereo", V4L2_STD_DK },
+ { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85),
+ "5.5/5.85 B/G NICAM FM", V4L2_STD_BG },
+ { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+ "6.5/5.85 L NICAM AM", V4L2_STD_L },
+ { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55),
+ "6.0/6.55 I NICAM FM", V4L2_STD_PAL_I },
+ { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+ "6.5/5.85 D/K NICAM FM", V4L2_STD_DK },
+ { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+ "6.5/5.85 D/K NICAM FM (HDEV2)", V4L2_STD_DK },
+ { 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+ "6.5/5.85 D/K NICAM FM (HDEV3)", V4L2_STD_DK },
+ { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+ "4.5 M BTSC-Stereo", V4L2_STD_MTS },
+ { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+ "4.5 M BTSC-Mono + SAP", V4L2_STD_MTS },
+ { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+ "4.5 M EIA-J Japan Stereo", V4L2_STD_NTSC_M_JP },
+ { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7),
+ "10.7 FM-Stereo Radio", V4L2_STD_ALL },
+ { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+ "6.5 SAT-Mono", V4L2_STD_ALL },
+ { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20),
+ "7.02/7.20 SAT-Stereo", V4L2_STD_ALL },
+ { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2),
+ "7.2 SAT ADR", V4L2_STD_ALL },
+ { -1, 0, 0, NULL, 0 }, /* EOF */
};
static struct msp3400c_init_data_dem {
@@ -156,6 +176,16 @@ const char *msp_standard_std_name(int std)
return "unknown";
}
+static v4l2_std_id msp_standard_std(int std)
+{
+ int i;
+
+ for (i = 0; msp_stdlist[i].name != NULL; i++)
+ if (msp_stdlist[i].retval == std)
+ return msp_stdlist[i].std;
+ return V4L2_STD_ALL;
+}
+
static void msp_set_source(struct i2c_client *client, u16 src)
{
struct msp_state *state = to_state(i2c_get_clientdata(client));
@@ -479,6 +509,7 @@ int msp3400c_thread(void *data)
int count, max1, max2, val1, val2, val, i;
v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+ state->detected_std = V4L2_STD_ALL;
set_freezable();
for (;;) {
v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
@@ -579,6 +610,7 @@ restart:
state->main = msp3400c_carrier_detect_main[max1].cdo;
switch (max1) {
case 1: /* 5.5 */
+ state->detected_std = V4L2_STD_BG | V4L2_STD_PAL_H;
if (max2 == 0) {
/* B/G FM-stereo */
state->second = msp3400c_carrier_detect_55[max2].cdo;
@@ -596,6 +628,7 @@ restart:
break;
case 2: /* 6.0 */
/* PAL I NICAM */
+ state->detected_std = V4L2_STD_PAL_I;
state->second = MSP_CARRIER(6.552);
msp3400c_set_mode(client, MSP_MODE_FM_NICAM2);
state->nicam_on = 1;
@@ -607,22 +640,26 @@ restart:
state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
state->watch_stereo = 1;
+ state->detected_std = V4L2_STD_DK;
} else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) {
/* L NICAM or AM-mono */
state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
state->watch_stereo = 1;
+ state->detected_std = V4L2_STD_L;
} else if (max2 == 0 && state->has_nicam) {
/* D/K NICAM */
state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
state->nicam_on = 1;
state->watch_stereo = 1;
+ state->detected_std = V4L2_STD_DK;
} else {
goto no_second;
}
break;
case 0: /* 4.5 */
+ state->detected_std = V4L2_STD_MN;
default:
no_second:
state->second = msp3400c_carrier_detect_main[max1].cdo;
@@ -662,6 +699,7 @@ int msp3410d_thread(void *data)
int val, i, std, count;
v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
+ state->detected_std = V4L2_STD_ALL;
set_freezable();
for (;;) {
v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
@@ -743,6 +781,8 @@ restart:
msp_stdlist[8].name : "unknown", val);
state->std = val = 0x0009;
msp_write_dem(client, 0x20, val);
+ } else {
+ state->detected_std = msp_standard_std(state->std);
}
/* set stereo */
@@ -957,6 +997,7 @@ int msp34xxg_thread(void *data)
int val, i;
v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
+ state->detected_std = V4L2_STD_ALL;
set_freezable();
for (;;) {
v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
@@ -1013,6 +1054,7 @@ unmute:
v4l_dbg(1, msp_debug, client,
"detected standard: %s (0x%04x)\n",
msp_standard_std_name(state->std), state->std);
+ state->detected_std = msp_standard_std(state->std);
if (state->std == 9) {
/* AM NICAM mode */
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index a357aa889fc6..07af26e6bebd 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -184,6 +184,7 @@ struct mt9m111 {
struct mutex power_lock; /* lock to protect power_count */
int power_count;
const struct mt9m111_datafmt *fmt;
+ int lastpage; /* PageMap cache value */
unsigned int gain;
unsigned char autoexposure;
unsigned char datawidth;
@@ -202,17 +203,17 @@ static int reg_page_map_set(struct i2c_client *client, const u16 reg)
{
int ret;
u16 page;
- static int lastpage = -1; /* PageMap cache value */
+ struct mt9m111 *mt9m111 = to_mt9m111(client);
page = (reg >> 8);
- if (page == lastpage)
+ if (page == mt9m111->lastpage)
return 0;
if (page > 2)
return -EINVAL;
ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page));
if (!ret)
- lastpage = page;
+ mt9m111->lastpage = page;
return ret;
}
@@ -932,6 +933,8 @@ static int mt9m111_video_probe(struct soc_camera_device *icd,
BUG_ON(!icd->parent ||
to_soc_camera_host(icd->parent)->nr != icd->iface);
+ mt9m111->lastpage = -1;
+
mt9m111->autoexposure = 1;
mt9m111->autowhitebalance = 1;
diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c
new file mode 100644
index 000000000000..73c068993f05
--- /dev/null
+++ b/drivers/media/video/mt9p031.c
@@ -0,0 +1,964 @@
+/*
+ * Driver for MT9P031 CMOS Image Sensor from Aptina
+ *
+ * Copyright (C) 2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ * Copyright (C) 2011, Javier Martin <javier.martin@vista-silicon.com>
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * Based on the MT9V032 driver and Bastian Hecht's code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <media/v4l2-subdev.h>
+#include <linux/videodev2.h>
+
+#include <media/mt9p031.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#define MT9P031_PIXEL_ARRAY_WIDTH 2752
+#define MT9P031_PIXEL_ARRAY_HEIGHT 2004
+
+#define MT9P031_CHIP_VERSION 0x00
+#define MT9P031_CHIP_VERSION_VALUE 0x1801
+#define MT9P031_ROW_START 0x01
+#define MT9P031_ROW_START_MIN 0
+#define MT9P031_ROW_START_MAX 2004
+#define MT9P031_ROW_START_DEF 54
+#define MT9P031_COLUMN_START 0x02
+#define MT9P031_COLUMN_START_MIN 0
+#define MT9P031_COLUMN_START_MAX 2750
+#define MT9P031_COLUMN_START_DEF 16
+#define MT9P031_WINDOW_HEIGHT 0x03
+#define MT9P031_WINDOW_HEIGHT_MIN 2
+#define MT9P031_WINDOW_HEIGHT_MAX 2006
+#define MT9P031_WINDOW_HEIGHT_DEF 1944
+#define MT9P031_WINDOW_WIDTH 0x04
+#define MT9P031_WINDOW_WIDTH_MIN 2
+#define MT9P031_WINDOW_WIDTH_MAX 2752
+#define MT9P031_WINDOW_WIDTH_DEF 2592
+#define MT9P031_HORIZONTAL_BLANK 0x05
+#define MT9P031_HORIZONTAL_BLANK_MIN 0
+#define MT9P031_HORIZONTAL_BLANK_MAX 4095
+#define MT9P031_VERTICAL_BLANK 0x06
+#define MT9P031_VERTICAL_BLANK_MIN 0
+#define MT9P031_VERTICAL_BLANK_MAX 4095
+#define MT9P031_VERTICAL_BLANK_DEF 25
+#define MT9P031_OUTPUT_CONTROL 0x07
+#define MT9P031_OUTPUT_CONTROL_CEN 2
+#define MT9P031_OUTPUT_CONTROL_SYN 1
+#define MT9P031_OUTPUT_CONTROL_DEF 0x1f82
+#define MT9P031_SHUTTER_WIDTH_UPPER 0x08
+#define MT9P031_SHUTTER_WIDTH_LOWER 0x09
+#define MT9P031_SHUTTER_WIDTH_MIN 1
+#define MT9P031_SHUTTER_WIDTH_MAX 1048575
+#define MT9P031_SHUTTER_WIDTH_DEF 1943
+#define MT9P031_PLL_CONTROL 0x10
+#define MT9P031_PLL_CONTROL_PWROFF 0x0050
+#define MT9P031_PLL_CONTROL_PWRON 0x0051
+#define MT9P031_PLL_CONTROL_USEPLL 0x0052
+#define MT9P031_PLL_CONFIG_1 0x11
+#define MT9P031_PLL_CONFIG_2 0x12
+#define MT9P031_PIXEL_CLOCK_CONTROL 0x0a
+#define MT9P031_FRAME_RESTART 0x0b
+#define MT9P031_SHUTTER_DELAY 0x0c
+#define MT9P031_RST 0x0d
+#define MT9P031_RST_ENABLE 1
+#define MT9P031_RST_DISABLE 0
+#define MT9P031_READ_MODE_1 0x1e
+#define MT9P031_READ_MODE_2 0x20
+#define MT9P031_READ_MODE_2_ROW_MIR (1 << 15)
+#define MT9P031_READ_MODE_2_COL_MIR (1 << 14)
+#define MT9P031_READ_MODE_2_ROW_BLC (1 << 6)
+#define MT9P031_ROW_ADDRESS_MODE 0x22
+#define MT9P031_COLUMN_ADDRESS_MODE 0x23
+#define MT9P031_GLOBAL_GAIN 0x35
+#define MT9P031_GLOBAL_GAIN_MIN 8
+#define MT9P031_GLOBAL_GAIN_MAX 1024
+#define MT9P031_GLOBAL_GAIN_DEF 8
+#define MT9P031_GLOBAL_GAIN_MULT (1 << 6)
+#define MT9P031_ROW_BLACK_DEF_OFFSET 0x4b
+#define MT9P031_TEST_PATTERN 0xa0
+#define MT9P031_TEST_PATTERN_SHIFT 3
+#define MT9P031_TEST_PATTERN_ENABLE (1 << 0)
+#define MT9P031_TEST_PATTERN_DISABLE (0 << 0)
+#define MT9P031_TEST_PATTERN_GREEN 0xa1
+#define MT9P031_TEST_PATTERN_RED 0xa2
+#define MT9P031_TEST_PATTERN_BLUE 0xa3
+
+struct mt9p031_pll_divs {
+ u32 ext_freq;
+ u32 target_freq;
+ u8 m;
+ u8 n;
+ u8 p1;
+};
+
+struct mt9p031 {
+ struct v4l2_subdev subdev;
+ struct media_pad pad;
+ struct v4l2_rect crop; /* Sensor window */
+ struct v4l2_mbus_framefmt format;
+ struct v4l2_ctrl_handler ctrls;
+ struct mt9p031_platform_data *pdata;
+ struct mutex power_lock; /* lock to protect power_count */
+ int power_count;
+ u16 xskip;
+ u16 yskip;
+
+ const struct mt9p031_pll_divs *pll;
+
+ /* Registers cache */
+ u16 output_control;
+ u16 mode2;
+};
+
+static struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct mt9p031, subdev);
+}
+
+static int mt9p031_read(struct i2c_client *client, u8 reg)
+{
+ s32 data = i2c_smbus_read_word_data(client, reg);
+ return data < 0 ? data : be16_to_cpu(data);
+}
+
+static int mt9p031_write(struct i2c_client *client, u8 reg, u16 data)
+{
+ return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+}
+
+static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear,
+ u16 set)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+ u16 value = (mt9p031->output_control & ~clear) | set;
+ int ret;
+
+ ret = mt9p031_write(client, MT9P031_OUTPUT_CONTROL, value);
+ if (ret < 0)
+ return ret;
+
+ mt9p031->output_control = value;
+ return 0;
+}
+
+static int mt9p031_set_mode2(struct mt9p031 *mt9p031, u16 clear, u16 set)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+ u16 value = (mt9p031->mode2 & ~clear) | set;
+ int ret;
+
+ ret = mt9p031_write(client, MT9P031_READ_MODE_2, value);
+ if (ret < 0)
+ return ret;
+
+ mt9p031->mode2 = value;
+ return 0;
+}
+
+static int mt9p031_reset(struct mt9p031 *mt9p031)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+ int ret;
+
+ /* Disable chip output, synchronous option update */
+ ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_ENABLE);
+ if (ret < 0)
+ return ret;
+ ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_DISABLE);
+ if (ret < 0)
+ return ret;
+
+ return mt9p031_set_output_control(mt9p031, MT9P031_OUTPUT_CONTROL_CEN,
+ 0);
+}
+
+/*
+ * This static table uses ext_freq and vdd_io values to select suitable
+ * PLL dividers m, n and p1 which have been calculated as specifiec in p36
+ * of Aptina's mt9p031 datasheet. New values should be added here.
+ */
+static const struct mt9p031_pll_divs mt9p031_divs[] = {
+ /* ext_freq target_freq m n p1 */
+ {21000000, 48000000, 26, 2, 6}
+};
+
+static int mt9p031_pll_get_divs(struct mt9p031 *mt9p031)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mt9p031_divs); i++) {
+ if (mt9p031_divs[i].ext_freq == mt9p031->pdata->ext_freq &&
+ mt9p031_divs[i].target_freq == mt9p031->pdata->target_freq) {
+ mt9p031->pll = &mt9p031_divs[i];
+ return 0;
+ }
+ }
+
+ dev_err(&client->dev, "Couldn't find PLL dividers for ext_freq = %d, "
+ "target_freq = %d\n", mt9p031->pdata->ext_freq,
+ mt9p031->pdata->target_freq);
+ return -EINVAL;
+}
+
+static int mt9p031_pll_enable(struct mt9p031 *mt9p031)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+ int ret;
+
+ ret = mt9p031_write(client, MT9P031_PLL_CONTROL,
+ MT9P031_PLL_CONTROL_PWRON);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9p031_write(client, MT9P031_PLL_CONFIG_1,
+ (mt9p031->pll->m << 8) | (mt9p031->pll->n - 1));
+ if (ret < 0)
+ return ret;
+
+ ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll->p1 - 1);
+ if (ret < 0)
+ return ret;
+
+ usleep_range(1000, 2000);
+ ret = mt9p031_write(client, MT9P031_PLL_CONTROL,
+ MT9P031_PLL_CONTROL_PWRON |
+ MT9P031_PLL_CONTROL_USEPLL);
+ return ret;
+}
+
+static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+
+ return mt9p031_write(client, MT9P031_PLL_CONTROL,
+ MT9P031_PLL_CONTROL_PWROFF);
+}
+
+static int mt9p031_power_on(struct mt9p031 *mt9p031)
+{
+ /* Ensure RESET_BAR is low */
+ if (mt9p031->pdata->reset) {
+ mt9p031->pdata->reset(&mt9p031->subdev, 1);
+ usleep_range(1000, 2000);
+ }
+
+ /* Emable clock */
+ if (mt9p031->pdata->set_xclk)
+ mt9p031->pdata->set_xclk(&mt9p031->subdev,
+ mt9p031->pdata->ext_freq);
+
+ /* Now RESET_BAR must be high */
+ if (mt9p031->pdata->reset) {
+ mt9p031->pdata->reset(&mt9p031->subdev, 0);
+ usleep_range(1000, 2000);
+ }
+
+ return 0;
+}
+
+static void mt9p031_power_off(struct mt9p031 *mt9p031)
+{
+ if (mt9p031->pdata->reset) {
+ mt9p031->pdata->reset(&mt9p031->subdev, 1);
+ usleep_range(1000, 2000);
+ }
+
+ if (mt9p031->pdata->set_xclk)
+ mt9p031->pdata->set_xclk(&mt9p031->subdev, 0);
+}
+
+static int __mt9p031_set_power(struct mt9p031 *mt9p031, bool on)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+ int ret;
+
+ if (!on) {
+ mt9p031_power_off(mt9p031);
+ return 0;
+ }
+
+ ret = mt9p031_power_on(mt9p031);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9p031_reset(mt9p031);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to reset the camera\n");
+ return ret;
+ }
+
+ return v4l2_ctrl_handler_setup(&mt9p031->ctrls);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev video operations
+ */
+
+static int mt9p031_set_params(struct mt9p031 *mt9p031)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+ struct v4l2_mbus_framefmt *format = &mt9p031->format;
+ const struct v4l2_rect *crop = &mt9p031->crop;
+ unsigned int hblank;
+ unsigned int vblank;
+ unsigned int xskip;
+ unsigned int yskip;
+ unsigned int xbin;
+ unsigned int ybin;
+ int ret;
+
+ /* Windows position and size.
+ *
+ * TODO: Make sure the start coordinates and window size match the
+ * skipping, binning and mirroring (see description of registers 2 and 4
+ * in table 13, and Binning section on page 41).
+ */
+ ret = mt9p031_write(client, MT9P031_COLUMN_START, crop->left);
+ if (ret < 0)
+ return ret;
+ ret = mt9p031_write(client, MT9P031_ROW_START, crop->top);
+ if (ret < 0)
+ return ret;
+ ret = mt9p031_write(client, MT9P031_WINDOW_WIDTH, crop->width - 1);
+ if (ret < 0)
+ return ret;
+ ret = mt9p031_write(client, MT9P031_WINDOW_HEIGHT, crop->height - 1);
+ if (ret < 0)
+ return ret;
+
+ /* Row and column binning and skipping. Use the maximum binning value
+ * compatible with the skipping settings.
+ */
+ xskip = DIV_ROUND_CLOSEST(crop->width, format->width);
+ yskip = DIV_ROUND_CLOSEST(crop->height, format->height);
+ xbin = 1 << (ffs(xskip) - 1);
+ ybin = 1 << (ffs(yskip) - 1);
+
+ ret = mt9p031_write(client, MT9P031_COLUMN_ADDRESS_MODE,
+ ((xbin - 1) << 4) | (xskip - 1));
+ if (ret < 0)
+ return ret;
+ ret = mt9p031_write(client, MT9P031_ROW_ADDRESS_MODE,
+ ((ybin - 1) << 4) | (yskip - 1));
+ if (ret < 0)
+ return ret;
+
+ /* Blanking - use minimum value for horizontal blanking and default
+ * value for vertical blanking.
+ */
+ hblank = 346 * ybin + 64 + (80 >> max_t(unsigned int, xbin, 3));
+ vblank = MT9P031_VERTICAL_BLANK_DEF;
+
+ ret = mt9p031_write(client, MT9P031_HORIZONTAL_BLANK, hblank);
+ if (ret < 0)
+ return ret;
+ ret = mt9p031_write(client, MT9P031_VERTICAL_BLANK, vblank);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+
+static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+ int ret;
+
+ if (!enable) {
+ /* Stop sensor readout */
+ ret = mt9p031_set_output_control(mt9p031,
+ MT9P031_OUTPUT_CONTROL_CEN, 0);
+ if (ret < 0)
+ return ret;
+
+ return mt9p031_pll_disable(mt9p031);
+ }
+
+ ret = mt9p031_set_params(mt9p031);
+ if (ret < 0)
+ return ret;
+
+ /* Switch to master "normal" mode */
+ ret = mt9p031_set_output_control(mt9p031, 0,
+ MT9P031_OUTPUT_CONTROL_CEN);
+ if (ret < 0)
+ return ret;
+
+ return mt9p031_pll_enable(mt9p031);
+}
+
+static int mt9p031_enum_mbus_code(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+ if (code->pad || code->index)
+ return -EINVAL;
+
+ code->code = mt9p031->format.code;
+ return 0;
+}
+
+static int mt9p031_enum_frame_size(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+ if (fse->index >= 8 || fse->code != mt9p031->format.code)
+ return -EINVAL;
+
+ fse->min_width = MT9P031_WINDOW_WIDTH_DEF
+ / min_t(unsigned int, 7, fse->index + 1);
+ fse->max_width = fse->min_width;
+ fse->min_height = MT9P031_WINDOW_HEIGHT_DEF / (fse->index + 1);
+ fse->max_height = fse->min_height;
+
+ return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+__mt9p031_get_pad_format(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
+ unsigned int pad, u32 which)
+{
+ switch (which) {
+ case V4L2_SUBDEV_FORMAT_TRY:
+ return v4l2_subdev_get_try_format(fh, pad);
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
+ return &mt9p031->format;
+ default:
+ return NULL;
+ }
+}
+
+static struct v4l2_rect *
+__mt9p031_get_pad_crop(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
+ unsigned int pad, u32 which)
+{
+ switch (which) {
+ case V4L2_SUBDEV_FORMAT_TRY:
+ return v4l2_subdev_get_try_crop(fh, pad);
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
+ return &mt9p031->crop;
+ default:
+ return NULL;
+ }
+}
+
+static int mt9p031_get_format(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
+{
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+ fmt->format = *__mt9p031_get_pad_format(mt9p031, fh, fmt->pad,
+ fmt->which);
+ return 0;
+}
+
+static int mt9p031_set_format(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *format)
+{
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+ struct v4l2_mbus_framefmt *__format;
+ struct v4l2_rect *__crop;
+ unsigned int width;
+ unsigned int height;
+ unsigned int hratio;
+ unsigned int vratio;
+
+ __crop = __mt9p031_get_pad_crop(mt9p031, fh, format->pad,
+ format->which);
+
+ /* Clamp the width and height to avoid dividing by zero. */
+ width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
+ max(__crop->width / 7, MT9P031_WINDOW_WIDTH_MIN),
+ __crop->width);
+ height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
+ max(__crop->height / 8, MT9P031_WINDOW_HEIGHT_MIN),
+ __crop->height);
+
+ hratio = DIV_ROUND_CLOSEST(__crop->width, width);
+ vratio = DIV_ROUND_CLOSEST(__crop->height, height);
+
+ __format = __mt9p031_get_pad_format(mt9p031, fh, format->pad,
+ format->which);
+ __format->width = __crop->width / hratio;
+ __format->height = __crop->height / vratio;
+
+ format->format = *__format;
+
+ return 0;
+}
+
+static int mt9p031_get_crop(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_crop *crop)
+{
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+ crop->rect = *__mt9p031_get_pad_crop(mt9p031, fh, crop->pad,
+ crop->which);
+ return 0;
+}
+
+static int mt9p031_set_crop(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_crop *crop)
+{
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+ struct v4l2_mbus_framefmt *__format;
+ struct v4l2_rect *__crop;
+ struct v4l2_rect rect;
+
+ /* Clamp the crop rectangle boundaries and align them to a multiple of 2
+ * pixels to ensure a GRBG Bayer pattern.
+ */
+ rect.left = clamp(ALIGN(crop->rect.left, 2), MT9P031_COLUMN_START_MIN,
+ MT9P031_COLUMN_START_MAX);
+ rect.top = clamp(ALIGN(crop->rect.top, 2), MT9P031_ROW_START_MIN,
+ MT9P031_ROW_START_MAX);
+ rect.width = clamp(ALIGN(crop->rect.width, 2),
+ MT9P031_WINDOW_WIDTH_MIN,
+ MT9P031_WINDOW_WIDTH_MAX);
+ rect.height = clamp(ALIGN(crop->rect.height, 2),
+ MT9P031_WINDOW_HEIGHT_MIN,
+ MT9P031_WINDOW_HEIGHT_MAX);
+
+ rect.width = min(rect.width, MT9P031_PIXEL_ARRAY_WIDTH - rect.left);
+ rect.height = min(rect.height, MT9P031_PIXEL_ARRAY_HEIGHT - rect.top);
+
+ __crop = __mt9p031_get_pad_crop(mt9p031, fh, crop->pad, crop->which);
+
+ if (rect.width != __crop->width || rect.height != __crop->height) {
+ /* Reset the output image size if the crop rectangle size has
+ * been modified.
+ */
+ __format = __mt9p031_get_pad_format(mt9p031, fh, crop->pad,
+ crop->which);
+ __format->width = rect.width;
+ __format->height = rect.height;
+ }
+
+ *__crop = rect;
+ crop->rect = rect;
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+#define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001)
+
+static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct mt9p031 *mt9p031 =
+ container_of(ctrl->handler, struct mt9p031, ctrls);
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+ u16 data;
+ int ret;
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ ret = mt9p031_write(client, MT9P031_SHUTTER_WIDTH_UPPER,
+ (ctrl->val >> 16) & 0xffff);
+ if (ret < 0)
+ return ret;
+
+ return mt9p031_write(client, MT9P031_SHUTTER_WIDTH_LOWER,
+ ctrl->val & 0xffff);
+
+ case V4L2_CID_GAIN:
+ /* Gain is controlled by 2 analog stages and a digital stage.
+ * Valid values for the 3 stages are
+ *
+ * Stage Min Max Step
+ * ------------------------------------------
+ * First analog stage x1 x2 1
+ * Second analog stage x1 x4 0.125
+ * Digital stage x1 x16 0.125
+ *
+ * To minimize noise, the gain stages should be used in the
+ * second analog stage, first analog stage, digital stage order.
+ * Gain from a previous stage should be pushed to its maximum
+ * value before the next stage is used.
+ */
+ if (ctrl->val <= 32) {
+ data = ctrl->val;
+ } else if (ctrl->val <= 64) {
+ ctrl->val &= ~1;
+ data = (1 << 6) | (ctrl->val >> 1);
+ } else {
+ ctrl->val &= ~7;
+ data = ((ctrl->val - 64) << 5) | (1 << 6) | 32;
+ }
+
+ return mt9p031_write(client, MT9P031_GLOBAL_GAIN, data);
+
+ case V4L2_CID_HFLIP:
+ if (ctrl->val)
+ return mt9p031_set_mode2(mt9p031,
+ 0, MT9P031_READ_MODE_2_COL_MIR);
+ else
+ return mt9p031_set_mode2(mt9p031,
+ MT9P031_READ_MODE_2_COL_MIR, 0);
+
+ case V4L2_CID_VFLIP:
+ if (ctrl->val)
+ return mt9p031_set_mode2(mt9p031,
+ 0, MT9P031_READ_MODE_2_ROW_MIR);
+ else
+ return mt9p031_set_mode2(mt9p031,
+ MT9P031_READ_MODE_2_ROW_MIR, 0);
+
+ case V4L2_CID_TEST_PATTERN:
+ if (!ctrl->val) {
+ ret = mt9p031_set_mode2(mt9p031,
+ 0, MT9P031_READ_MODE_2_ROW_BLC);
+ if (ret < 0)
+ return ret;
+
+ return mt9p031_write(client, MT9P031_TEST_PATTERN,
+ MT9P031_TEST_PATTERN_DISABLE);
+ }
+
+ ret = mt9p031_write(client, MT9P031_TEST_PATTERN_GREEN, 0x05a0);
+ if (ret < 0)
+ return ret;
+ ret = mt9p031_write(client, MT9P031_TEST_PATTERN_RED, 0x0a50);
+ if (ret < 0)
+ return ret;
+ ret = mt9p031_write(client, MT9P031_TEST_PATTERN_BLUE, 0x0aa0);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9p031_set_mode2(mt9p031, MT9P031_READ_MODE_2_ROW_BLC,
+ 0);
+ if (ret < 0)
+ return ret;
+ ret = mt9p031_write(client, MT9P031_ROW_BLACK_DEF_OFFSET, 0);
+ if (ret < 0)
+ return ret;
+
+ return mt9p031_write(client, MT9P031_TEST_PATTERN,
+ ((ctrl->val - 1) << MT9P031_TEST_PATTERN_SHIFT)
+ | MT9P031_TEST_PATTERN_ENABLE);
+ }
+ return 0;
+}
+
+static struct v4l2_ctrl_ops mt9p031_ctrl_ops = {
+ .s_ctrl = mt9p031_s_ctrl,
+};
+
+static const char * const mt9p031_test_pattern_menu[] = {
+ "Disabled",
+ "Color Field",
+ "Horizontal Gradient",
+ "Vertical Gradient",
+ "Diagonal Gradient",
+ "Classic Test Pattern",
+ "Walking 1s",
+ "Monochrome Horizontal Bars",
+ "Monochrome Vertical Bars",
+ "Vertical Color Bars",
+};
+
+static const struct v4l2_ctrl_config mt9p031_ctrls[] = {
+ {
+ .ops = &mt9p031_ctrl_ops,
+ .id = V4L2_CID_TEST_PATTERN,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Test Pattern",
+ .min = 0,
+ .max = ARRAY_SIZE(mt9p031_test_pattern_menu) - 1,
+ .step = 0,
+ .def = 0,
+ .flags = 0,
+ .menu_skip_mask = 0,
+ .qmenu = mt9p031_test_pattern_menu,
+ }
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev core operations
+ */
+
+static int mt9p031_set_power(struct v4l2_subdev *subdev, int on)
+{
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+ int ret = 0;
+
+ mutex_lock(&mt9p031->power_lock);
+
+ /* If the power count is modified from 0 to != 0 or from != 0 to 0,
+ * update the power state.
+ */
+ if (mt9p031->power_count == !on) {
+ ret = __mt9p031_set_power(mt9p031, !!on);
+ if (ret < 0)
+ goto out;
+ }
+
+ /* Update the power count. */
+ mt9p031->power_count += on ? 1 : -1;
+ WARN_ON(mt9p031->power_count < 0);
+
+out:
+ mutex_unlock(&mt9p031->power_lock);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev internal operations
+ */
+
+static int mt9p031_registered(struct v4l2_subdev *subdev)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(subdev);
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+ s32 data;
+ int ret;
+
+ ret = mt9p031_power_on(mt9p031);
+ if (ret < 0) {
+ dev_err(&client->dev, "MT9P031 power up failed\n");
+ return ret;
+ }
+
+ /* Read out the chip version register */
+ data = mt9p031_read(client, MT9P031_CHIP_VERSION);
+ if (data != MT9P031_CHIP_VERSION_VALUE) {
+ dev_err(&client->dev, "MT9P031 not detected, wrong version "
+ "0x%04x\n", data);
+ return -ENODEV;
+ }
+
+ mt9p031_power_off(mt9p031);
+
+ dev_info(&client->dev, "MT9P031 detected at address 0x%02x\n",
+ client->addr);
+
+ return ret;
+}
+
+static int mt9p031_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+ struct v4l2_mbus_framefmt *format;
+ struct v4l2_rect *crop;
+
+ crop = v4l2_subdev_get_try_crop(fh, 0);
+ crop->left = MT9P031_COLUMN_START_DEF;
+ crop->top = MT9P031_ROW_START_DEF;
+ crop->width = MT9P031_WINDOW_WIDTH_DEF;
+ crop->height = MT9P031_WINDOW_HEIGHT_DEF;
+
+ format = v4l2_subdev_get_try_format(fh, 0);
+
+ if (mt9p031->pdata->version == MT9P031_MONOCHROME_VERSION)
+ format->code = V4L2_MBUS_FMT_Y12_1X12;
+ else
+ format->code = V4L2_MBUS_FMT_SGRBG12_1X12;
+
+ format->width = MT9P031_WINDOW_WIDTH_DEF;
+ format->height = MT9P031_WINDOW_HEIGHT_DEF;
+ format->field = V4L2_FIELD_NONE;
+ format->colorspace = V4L2_COLORSPACE_SRGB;
+
+ mt9p031->xskip = 1;
+ mt9p031->yskip = 1;
+ return mt9p031_set_power(subdev, 1);
+}
+
+static int mt9p031_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+ return mt9p031_set_power(subdev, 0);
+}
+
+static struct v4l2_subdev_core_ops mt9p031_subdev_core_ops = {
+ .s_power = mt9p031_set_power,
+};
+
+static struct v4l2_subdev_video_ops mt9p031_subdev_video_ops = {
+ .s_stream = mt9p031_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
+ .enum_mbus_code = mt9p031_enum_mbus_code,
+ .enum_frame_size = mt9p031_enum_frame_size,
+ .get_fmt = mt9p031_get_format,
+ .set_fmt = mt9p031_set_format,
+ .get_crop = mt9p031_get_crop,
+ .set_crop = mt9p031_set_crop,
+};
+
+static struct v4l2_subdev_ops mt9p031_subdev_ops = {
+ .core = &mt9p031_subdev_core_ops,
+ .video = &mt9p031_subdev_video_ops,
+ .pad = &mt9p031_subdev_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
+ .registered = mt9p031_registered,
+ .open = mt9p031_open,
+ .close = mt9p031_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Driver initialization and probing
+ */
+
+static int mt9p031_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+{
+ struct mt9p031_platform_data *pdata = client->dev.platform_data;
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct mt9p031 *mt9p031;
+ unsigned int i;
+ int ret;
+
+ if (pdata == NULL) {
+ dev_err(&client->dev, "No platform data\n");
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+ dev_warn(&client->dev,
+ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+ return -EIO;
+ }
+
+ mt9p031 = kzalloc(sizeof(*mt9p031), GFP_KERNEL);
+ if (mt9p031 == NULL)
+ return -ENOMEM;
+
+ mt9p031->pdata = pdata;
+ mt9p031->output_control = MT9P031_OUTPUT_CONTROL_DEF;
+ mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC;
+
+ v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 4);
+
+ v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+ V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
+ MT9P031_SHUTTER_WIDTH_MAX, 1,
+ MT9P031_SHUTTER_WIDTH_DEF);
+ v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+ V4L2_CID_GAIN, MT9P031_GLOBAL_GAIN_MIN,
+ MT9P031_GLOBAL_GAIN_MAX, 1, MT9P031_GLOBAL_GAIN_DEF);
+ v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+ for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
+ v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);
+
+ mt9p031->subdev.ctrl_handler = &mt9p031->ctrls;
+
+ if (mt9p031->ctrls.error)
+ printk(KERN_INFO "%s: control initialization error %d\n",
+ __func__, mt9p031->ctrls.error);
+
+ mutex_init(&mt9p031->power_lock);
+ v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops);
+ mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops;
+
+ mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0);
+ if (ret < 0)
+ goto done;
+
+ mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ mt9p031->crop.width = MT9P031_WINDOW_WIDTH_DEF;
+ mt9p031->crop.height = MT9P031_WINDOW_HEIGHT_DEF;
+ mt9p031->crop.left = MT9P031_COLUMN_START_DEF;
+ mt9p031->crop.top = MT9P031_ROW_START_DEF;
+
+ if (mt9p031->pdata->version == MT9P031_MONOCHROME_VERSION)
+ mt9p031->format.code = V4L2_MBUS_FMT_Y12_1X12;
+ else
+ mt9p031->format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
+
+ mt9p031->format.width = MT9P031_WINDOW_WIDTH_DEF;
+ mt9p031->format.height = MT9P031_WINDOW_HEIGHT_DEF;
+ mt9p031->format.field = V4L2_FIELD_NONE;
+ mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB;
+
+ ret = mt9p031_pll_get_divs(mt9p031);
+
+done:
+ if (ret < 0) {
+ v4l2_ctrl_handler_free(&mt9p031->ctrls);
+ media_entity_cleanup(&mt9p031->subdev.entity);
+ kfree(mt9p031);
+ }
+
+ return ret;
+}
+
+static int mt9p031_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+ struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+ v4l2_ctrl_handler_free(&mt9p031->ctrls);
+ v4l2_device_unregister_subdev(subdev);
+ media_entity_cleanup(&subdev->entity);
+ kfree(mt9p031);
+
+ return 0;
+}
+
+static const struct i2c_device_id mt9p031_id[] = {
+ { "mt9p031", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9p031_id);
+
+static struct i2c_driver mt9p031_i2c_driver = {
+ .driver = {
+ .name = "mt9p031",
+ },
+ .probe = mt9p031_probe,
+ .remove = mt9p031_remove,
+ .id_table = mt9p031_id,
+};
+
+static int __init mt9p031_mod_init(void)
+{
+ return i2c_add_driver(&mt9p031_i2c_driver);
+}
+
+static void __exit mt9p031_mod_exit(void)
+{
+ i2c_del_driver(&mt9p031_i2c_driver);
+}
+
+module_init(mt9p031_mod_init);
+module_exit(mt9p031_mod_exit);
+
+MODULE_DESCRIPTION("Aptina MT9P031 Camera driver");
+MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/mt9t001.c b/drivers/media/video/mt9t001.c
new file mode 100644
index 000000000000..08074b8a2736
--- /dev/null
+++ b/drivers/media/video/mt9t001.c
@@ -0,0 +1,836 @@
+/*
+ * Driver for MT9T001 CMOS Image Sensor from Aptina (Micron)
+ *
+ * Copyright (C) 2010-2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on the MT9M001 driver,
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/log2.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/v4l2-mediabus.h>
+
+#include <media/mt9t001.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#define MT9T001_PIXEL_ARRAY_HEIGHT 1568
+#define MT9T001_PIXEL_ARRAY_WIDTH 2112
+
+#define MT9T001_CHIP_VERSION 0x00
+#define MT9T001_CHIP_ID 0x1621
+#define MT9T001_ROW_START 0x01
+#define MT9T001_ROW_START_MIN 0
+#define MT9T001_ROW_START_DEF 20
+#define MT9T001_ROW_START_MAX 1534
+#define MT9T001_COLUMN_START 0x02
+#define MT9T001_COLUMN_START_MIN 0
+#define MT9T001_COLUMN_START_DEF 32
+#define MT9T001_COLUMN_START_MAX 2046
+#define MT9T001_WINDOW_HEIGHT 0x03
+#define MT9T001_WINDOW_HEIGHT_MIN 1
+#define MT9T001_WINDOW_HEIGHT_DEF 1535
+#define MT9T001_WINDOW_HEIGHT_MAX 1567
+#define MT9T001_WINDOW_WIDTH 0x04
+#define MT9T001_WINDOW_WIDTH_MIN 1
+#define MT9T001_WINDOW_WIDTH_DEF 2047
+#define MT9T001_WINDOW_WIDTH_MAX 2111
+#define MT9T001_HORIZONTAL_BLANKING 0x05
+#define MT9T001_HORIZONTAL_BLANKING_MIN 21
+#define MT9T001_HORIZONTAL_BLANKING_MAX 1023
+#define MT9T001_VERTICAL_BLANKING 0x06
+#define MT9T001_VERTICAL_BLANKING_MIN 3
+#define MT9T001_VERTICAL_BLANKING_MAX 1023
+#define MT9T001_OUTPUT_CONTROL 0x07
+#define MT9T001_OUTPUT_CONTROL_SYNC (1 << 0)
+#define MT9T001_OUTPUT_CONTROL_CHIP_ENABLE (1 << 1)
+#define MT9T001_OUTPUT_CONTROL_TEST_DATA (1 << 6)
+#define MT9T001_SHUTTER_WIDTH_HIGH 0x08
+#define MT9T001_SHUTTER_WIDTH_LOW 0x09
+#define MT9T001_SHUTTER_WIDTH_MIN 1
+#define MT9T001_SHUTTER_WIDTH_DEF 1561
+#define MT9T001_SHUTTER_WIDTH_MAX (1024 * 1024)
+#define MT9T001_PIXEL_CLOCK 0x0a
+#define MT9T001_PIXEL_CLOCK_INVERT (1 << 15)
+#define MT9T001_PIXEL_CLOCK_SHIFT_MASK (7 << 8)
+#define MT9T001_PIXEL_CLOCK_SHIFT_SHIFT 8
+#define MT9T001_PIXEL_CLOCK_DIVIDE_MASK (0x7f << 0)
+#define MT9T001_FRAME_RESTART 0x0b
+#define MT9T001_SHUTTER_DELAY 0x0c
+#define MT9T001_SHUTTER_DELAY_MAX 2047
+#define MT9T001_RESET 0x0d
+#define MT9T001_READ_MODE1 0x1e
+#define MT9T001_READ_MODE_SNAPSHOT (1 << 8)
+#define MT9T001_READ_MODE_STROBE_ENABLE (1 << 9)
+#define MT9T001_READ_MODE_STROBE_WIDTH (1 << 10)
+#define MT9T001_READ_MODE_STROBE_OVERRIDE (1 << 11)
+#define MT9T001_READ_MODE2 0x20
+#define MT9T001_READ_MODE_BAD_FRAMES (1 << 0)
+#define MT9T001_READ_MODE_LINE_VALID_CONTINUOUS (1 << 9)
+#define MT9T001_READ_MODE_LINE_VALID_FRAME (1 << 10)
+#define MT9T001_READ_MODE3 0x21
+#define MT9T001_READ_MODE_GLOBAL_RESET (1 << 0)
+#define MT9T001_READ_MODE_GHST_CTL (1 << 1)
+#define MT9T001_ROW_ADDRESS_MODE 0x22
+#define MT9T001_ROW_SKIP_MASK (7 << 0)
+#define MT9T001_ROW_BIN_MASK (3 << 3)
+#define MT9T001_ROW_BIN_SHIFT 3
+#define MT9T001_COLUMN_ADDRESS_MODE 0x23
+#define MT9T001_COLUMN_SKIP_MASK (7 << 0)
+#define MT9T001_COLUMN_BIN_MASK (3 << 3)
+#define MT9T001_COLUMN_BIN_SHIFT 3
+#define MT9T001_GREEN1_GAIN 0x2b
+#define MT9T001_BLUE_GAIN 0x2c
+#define MT9T001_RED_GAIN 0x2d
+#define MT9T001_GREEN2_GAIN 0x2e
+#define MT9T001_TEST_DATA 0x32
+#define MT9T001_GLOBAL_GAIN 0x35
+#define MT9T001_GLOBAL_GAIN_MIN 8
+#define MT9T001_GLOBAL_GAIN_MAX 1024
+#define MT9T001_BLACK_LEVEL 0x49
+#define MT9T001_ROW_BLACK_DEFAULT_OFFSET 0x4b
+#define MT9T001_BLC_DELTA_THRESHOLDS 0x5d
+#define MT9T001_CAL_THRESHOLDS 0x5f
+#define MT9T001_GREEN1_OFFSET 0x60
+#define MT9T001_GREEN2_OFFSET 0x61
+#define MT9T001_BLACK_LEVEL_CALIBRATION 0x62
+#define MT9T001_BLACK_LEVEL_OVERRIDE (1 << 0)
+#define MT9T001_BLACK_LEVEL_DISABLE_OFFSET (1 << 1)
+#define MT9T001_BLACK_LEVEL_RECALCULATE (1 << 12)
+#define MT9T001_BLACK_LEVEL_LOCK_RED_BLUE (1 << 13)
+#define MT9T001_BLACK_LEVEL_LOCK_GREEN (1 << 14)
+#define MT9T001_RED_OFFSET 0x63
+#define MT9T001_BLUE_OFFSET 0x64
+
+struct mt9t001 {
+ struct v4l2_subdev subdev;
+ struct media_pad pad;
+
+ struct v4l2_mbus_framefmt format;
+ struct v4l2_rect crop;
+
+ struct v4l2_ctrl_handler ctrls;
+ struct v4l2_ctrl *gains[4];
+
+ u16 output_control;
+ u16 black_level;
+};
+
+static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct mt9t001, subdev);
+}
+
+static int mt9t001_read(struct i2c_client *client, u8 reg)
+{
+ s32 data = i2c_smbus_read_word_data(client, reg);
+ return data < 0 ? data : be16_to_cpu(data);
+}
+
+static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data)
+{
+ return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+}
+
+static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
+ u16 set)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
+ u16 value = (mt9t001->output_control & ~clear) | set;
+ int ret;
+
+ if (value == mt9t001->output_control)
+ return 0;
+
+ ret = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, value);
+ if (ret < 0)
+ return ret;
+
+ mt9t001->output_control = value;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev video operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__mt9t001_get_pad_format(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+ switch (which) {
+ case V4L2_SUBDEV_FORMAT_TRY:
+ return v4l2_subdev_get_try_format(fh, pad);
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
+ return &mt9t001->format;
+ default:
+ return NULL;
+ }
+}
+
+static struct v4l2_rect *
+__mt9t001_get_pad_crop(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+ switch (which) {
+ case V4L2_SUBDEV_FORMAT_TRY:
+ return v4l2_subdev_get_try_crop(fh, pad);
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
+ return &mt9t001->crop;
+ default:
+ return NULL;
+ }
+}
+
+static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+ const u16 mode = MT9T001_OUTPUT_CONTROL_CHIP_ENABLE;
+ struct i2c_client *client = v4l2_get_subdevdata(subdev);
+ struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+ struct v4l2_mbus_framefmt *format = &mt9t001->format;
+ struct v4l2_rect *crop = &mt9t001->crop;
+ unsigned int hratio;
+ unsigned int vratio;
+ int ret;
+
+ if (!enable)
+ return mt9t001_set_output_control(mt9t001, mode, 0);
+
+ /* Configure the window size and row/column bin */
+ hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
+ vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
+
+ ret = mt9t001_write(client, MT9T001_ROW_ADDRESS_MODE, hratio - 1);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9t001_write(client, MT9T001_COLUMN_ADDRESS_MODE, vratio - 1);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9t001_write(client, MT9T001_COLUMN_START, crop->left);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9t001_write(client, MT9T001_ROW_START, crop->top);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9t001_write(client, MT9T001_WINDOW_WIDTH, crop->width - 1);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9t001_write(client, MT9T001_WINDOW_HEIGHT, crop->height - 1);
+ if (ret < 0)
+ return ret;
+
+ /* Switch to master "normal" mode */
+ return mt9t001_set_output_control(mt9t001, 0, mode);
+}
+
+static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index > 0)
+ return -EINVAL;
+
+ code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+ return 0;
+}
+
+static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
+ return -EINVAL;
+
+ fse->min_width = (MT9T001_WINDOW_WIDTH_DEF + 1) / fse->index;
+ fse->max_width = fse->min_width;
+ fse->min_height = (MT9T001_WINDOW_HEIGHT_DEF + 1) / fse->index;
+ fse->max_height = fse->min_height;
+
+ return 0;
+}
+
+static int mt9t001_get_format(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *format)
+{
+ struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+ format->format = *__mt9t001_get_pad_format(mt9t001, fh, format->pad,
+ format->which);
+ return 0;
+}
+
+static int mt9t001_set_format(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *format)
+{
+ struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+ struct v4l2_mbus_framefmt *__format;
+ struct v4l2_rect *__crop;
+ unsigned int width;
+ unsigned int height;
+ unsigned int hratio;
+ unsigned int vratio;
+
+ __crop = __mt9t001_get_pad_crop(mt9t001, fh, format->pad,
+ format->which);
+
+ /* Clamp the width and height to avoid dividing by zero. */
+ width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
+ max(__crop->width / 8, MT9T001_WINDOW_HEIGHT_MIN + 1),
+ __crop->width);
+ height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
+ max(__crop->height / 8, MT9T001_WINDOW_HEIGHT_MIN + 1),
+ __crop->height);
+
+ hratio = DIV_ROUND_CLOSEST(__crop->width, width);
+ vratio = DIV_ROUND_CLOSEST(__crop->height, height);
+
+ __format = __mt9t001_get_pad_format(mt9t001, fh, format->pad,
+ format->which);
+ __format->width = __crop->width / hratio;
+ __format->height = __crop->height / vratio;
+
+ format->format = *__format;
+
+ return 0;
+}
+
+static int mt9t001_get_crop(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_crop *crop)
+{
+ struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+ crop->rect = *__mt9t001_get_pad_crop(mt9t001, fh, crop->pad,
+ crop->which);
+ return 0;
+}
+
+static int mt9t001_set_crop(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_crop *crop)
+{
+ struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+ struct v4l2_mbus_framefmt *__format;
+ struct v4l2_rect *__crop;
+ struct v4l2_rect rect;
+
+ /* Clamp the crop rectangle boundaries and align them to a multiple of 2
+ * pixels.
+ */
+ rect.left = clamp(ALIGN(crop->rect.left, 2),
+ MT9T001_COLUMN_START_MIN,
+ MT9T001_COLUMN_START_MAX);
+ rect.top = clamp(ALIGN(crop->rect.top, 2),
+ MT9T001_ROW_START_MIN,
+ MT9T001_ROW_START_MAX);
+ rect.width = clamp(ALIGN(crop->rect.width, 2),
+ MT9T001_WINDOW_WIDTH_MIN + 1,
+ MT9T001_WINDOW_WIDTH_MAX + 1);
+ rect.height = clamp(ALIGN(crop->rect.height, 2),
+ MT9T001_WINDOW_HEIGHT_MIN + 1,
+ MT9T001_WINDOW_HEIGHT_MAX + 1);
+
+ rect.width = min(rect.width, MT9T001_PIXEL_ARRAY_WIDTH - rect.left);
+ rect.height = min(rect.height, MT9T001_PIXEL_ARRAY_HEIGHT - rect.top);
+
+ __crop = __mt9t001_get_pad_crop(mt9t001, fh, crop->pad, crop->which);
+
+ if (rect.width != __crop->width || rect.height != __crop->height) {
+ /* Reset the output image size if the crop rectangle size has
+ * been modified.
+ */
+ __format = __mt9t001_get_pad_format(mt9t001, fh, crop->pad,
+ crop->which);
+ __format->width = rect.width;
+ __format->height = rect.height;
+ }
+
+ *__crop = rect;
+ crop->rect = rect;
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+#define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_BLACK_LEVEL_AUTO (V4L2_CID_USER_BASE | 0x1002)
+#define V4L2_CID_BLACK_LEVEL_OFFSET (V4L2_CID_USER_BASE | 0x1003)
+#define V4L2_CID_BLACK_LEVEL_CALIBRATE (V4L2_CID_USER_BASE | 0x1004)
+
+#define V4L2_CID_GAIN_RED (V4L2_CTRL_CLASS_CAMERA | 0x1001)
+#define V4L2_CID_GAIN_GREEN_RED (V4L2_CTRL_CLASS_CAMERA | 0x1002)
+#define V4L2_CID_GAIN_GREEN_BLUE (V4L2_CTRL_CLASS_CAMERA | 0x1003)
+#define V4L2_CID_GAIN_BLUE (V4L2_CTRL_CLASS_CAMERA | 0x1004)
+
+static u16 mt9t001_gain_value(s32 *gain)
+{
+ /* Gain is controlled by 2 analog stages and a digital stage. Valid
+ * values for the 3 stages are
+ *
+ * Stage Min Max Step
+ * ------------------------------------------
+ * First analog stage x1 x2 1
+ * Second analog stage x1 x4 0.125
+ * Digital stage x1 x16 0.125
+ *
+ * To minimize noise, the gain stages should be used in the second
+ * analog stage, first analog stage, digital stage order. Gain from a
+ * previous stage should be pushed to its maximum value before the next
+ * stage is used.
+ */
+ if (*gain <= 32)
+ return *gain;
+
+ if (*gain <= 64) {
+ *gain &= ~1;
+ return (1 << 6) | (*gain >> 1);
+ }
+
+ *gain &= ~7;
+ return ((*gain - 64) << 5) | (1 << 6) | 32;
+}
+
+static int mt9t001_ctrl_freeze(struct mt9t001 *mt9t001, bool freeze)
+{
+ return mt9t001_set_output_control(mt9t001,
+ freeze ? 0 : MT9T001_OUTPUT_CONTROL_SYNC,
+ freeze ? MT9T001_OUTPUT_CONTROL_SYNC : 0);
+}
+
+static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ static const u8 gains[4] = {
+ MT9T001_RED_GAIN, MT9T001_GREEN1_GAIN,
+ MT9T001_GREEN2_GAIN, MT9T001_BLUE_GAIN
+ };
+
+ struct mt9t001 *mt9t001 =
+ container_of(ctrl->handler, struct mt9t001, ctrls);
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
+ unsigned int count;
+ unsigned int i;
+ u16 value;
+ int ret;
+
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN_RED:
+ case V4L2_CID_GAIN_GREEN_RED:
+ case V4L2_CID_GAIN_GREEN_BLUE:
+ case V4L2_CID_GAIN_BLUE:
+
+ /* Disable control updates if more than one control has changed
+ * in the cluster.
+ */
+ for (i = 0, count = 0; i < 4; ++i) {
+ struct v4l2_ctrl *gain = mt9t001->gains[i];
+
+ if (gain->val != gain->cur.val)
+ count++;
+ }
+
+ if (count > 1) {
+ ret = mt9t001_ctrl_freeze(mt9t001, true);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Update the gain controls. */
+ for (i = 0; i < 4; ++i) {
+ struct v4l2_ctrl *gain = mt9t001->gains[i];
+
+ if (gain->val == gain->cur.val)
+ continue;
+
+ value = mt9t001_gain_value(&gain->val);
+ ret = mt9t001_write(client, gains[i], value);
+ if (ret < 0) {
+ mt9t001_ctrl_freeze(mt9t001, false);
+ return ret;
+ }
+ }
+
+ /* Enable control updates. */
+ if (count > 1) {
+ ret = mt9t001_ctrl_freeze(mt9t001, false);
+ if (ret < 0)
+ return ret;
+ }
+
+ break;
+
+ case V4L2_CID_EXPOSURE:
+ ret = mt9t001_write(client, MT9T001_SHUTTER_WIDTH_LOW,
+ ctrl->val & 0xffff);
+ if (ret < 0)
+ return ret;
+
+ return mt9t001_write(client, MT9T001_SHUTTER_WIDTH_HIGH,
+ ctrl->val >> 16);
+
+ case V4L2_CID_TEST_PATTERN:
+ ret = mt9t001_set_output_control(mt9t001,
+ ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA,
+ ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0);
+ if (ret < 0)
+ return ret;
+
+ return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2);
+
+ case V4L2_CID_BLACK_LEVEL_AUTO:
+ value = ctrl->val ? 0 : MT9T001_BLACK_LEVEL_OVERRIDE;
+ ret = mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
+ value);
+ if (ret < 0)
+ return ret;
+
+ mt9t001->black_level = value;
+ break;
+
+ case V4L2_CID_BLACK_LEVEL_OFFSET:
+ ret = mt9t001_write(client, MT9T001_GREEN1_OFFSET, ctrl->val);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9t001_write(client, MT9T001_GREEN2_OFFSET, ctrl->val);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9t001_write(client, MT9T001_RED_OFFSET, ctrl->val);
+ if (ret < 0)
+ return ret;
+
+ return mt9t001_write(client, MT9T001_BLUE_OFFSET, ctrl->val);
+
+ case V4L2_CID_BLACK_LEVEL_CALIBRATE:
+ return mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
+ MT9T001_BLACK_LEVEL_RECALCULATE |
+ mt9t001->black_level);
+ }
+
+ return 0;
+}
+
+static struct v4l2_ctrl_ops mt9t001_ctrl_ops = {
+ .s_ctrl = mt9t001_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config mt9t001_ctrls[] = {
+ {
+ .ops = &mt9t001_ctrl_ops,
+ .id = V4L2_CID_TEST_PATTERN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Test pattern",
+ .min = 0,
+ .max = 1023,
+ .step = 1,
+ .def = 0,
+ .flags = 0,
+ }, {
+ .ops = &mt9t001_ctrl_ops,
+ .id = V4L2_CID_BLACK_LEVEL_AUTO,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Black Level, Auto",
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 1,
+ .flags = 0,
+ }, {
+ .ops = &mt9t001_ctrl_ops,
+ .id = V4L2_CID_BLACK_LEVEL_OFFSET,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Black Level, Offset",
+ .min = -256,
+ .max = 255,
+ .step = 1,
+ .def = 32,
+ .flags = 0,
+ }, {
+ .ops = &mt9t001_ctrl_ops,
+ .id = V4L2_CID_BLACK_LEVEL_CALIBRATE,
+ .type = V4L2_CTRL_TYPE_BUTTON,
+ .name = "Black Level, Calibrate",
+ .min = 0,
+ .max = 0,
+ .step = 0,
+ .def = 0,
+ .flags = V4L2_CTRL_FLAG_WRITE_ONLY,
+ },
+};
+
+static const struct v4l2_ctrl_config mt9t001_gains[] = {
+ {
+ .ops = &mt9t001_ctrl_ops,
+ .id = V4L2_CID_GAIN_RED,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain, Red",
+ .min = MT9T001_GLOBAL_GAIN_MIN,
+ .max = MT9T001_GLOBAL_GAIN_MAX,
+ .step = 1,
+ .def = MT9T001_GLOBAL_GAIN_MIN,
+ .flags = 0,
+ }, {
+ .ops = &mt9t001_ctrl_ops,
+ .id = V4L2_CID_GAIN_GREEN_RED,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain, Green (R)",
+ .min = MT9T001_GLOBAL_GAIN_MIN,
+ .max = MT9T001_GLOBAL_GAIN_MAX,
+ .step = 1,
+ .def = MT9T001_GLOBAL_GAIN_MIN,
+ .flags = 0,
+ }, {
+ .ops = &mt9t001_ctrl_ops,
+ .id = V4L2_CID_GAIN_GREEN_BLUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain, Green (B)",
+ .min = MT9T001_GLOBAL_GAIN_MIN,
+ .max = MT9T001_GLOBAL_GAIN_MAX,
+ .step = 1,
+ .def = MT9T001_GLOBAL_GAIN_MIN,
+ .flags = 0,
+ }, {
+ .ops = &mt9t001_ctrl_ops,
+ .id = V4L2_CID_GAIN_BLUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain, Blue",
+ .min = MT9T001_GLOBAL_GAIN_MIN,
+ .max = MT9T001_GLOBAL_GAIN_MAX,
+ .step = 1,
+ .def = MT9T001_GLOBAL_GAIN_MIN,
+ .flags = 0,
+ },
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev internal operations
+ */
+
+static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+ struct v4l2_mbus_framefmt *format;
+ struct v4l2_rect *crop;
+
+ crop = v4l2_subdev_get_try_crop(fh, 0);
+ crop->left = MT9T001_COLUMN_START_DEF;
+ crop->top = MT9T001_ROW_START_DEF;
+ crop->width = MT9T001_WINDOW_WIDTH_DEF + 1;
+ crop->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+
+ format = v4l2_subdev_get_try_format(fh, 0);
+ format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+ format->width = MT9T001_WINDOW_WIDTH_DEF + 1;
+ format->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+ format->field = V4L2_FIELD_NONE;
+ format->colorspace = V4L2_COLORSPACE_SRGB;
+
+ return 0;
+}
+
+static struct v4l2_subdev_video_ops mt9t001_subdev_video_ops = {
+ .s_stream = mt9t001_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
+ .enum_mbus_code = mt9t001_enum_mbus_code,
+ .enum_frame_size = mt9t001_enum_frame_size,
+ .get_fmt = mt9t001_get_format,
+ .set_fmt = mt9t001_set_format,
+ .get_crop = mt9t001_get_crop,
+ .set_crop = mt9t001_set_crop,
+};
+
+static struct v4l2_subdev_ops mt9t001_subdev_ops = {
+ .video = &mt9t001_subdev_video_ops,
+ .pad = &mt9t001_subdev_pad_ops,
+};
+
+static struct v4l2_subdev_internal_ops mt9t001_subdev_internal_ops = {
+ .open = mt9t001_open,
+};
+
+static int mt9t001_video_probe(struct i2c_client *client)
+{
+ struct mt9t001_platform_data *pdata = client->dev.platform_data;
+ s32 data;
+ int ret;
+
+ dev_info(&client->dev, "Probing MT9T001 at address 0x%02x\n",
+ client->addr);
+
+ /* Reset the chip and stop data read out */
+ ret = mt9t001_write(client, MT9T001_RESET, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9t001_write(client, MT9T001_RESET, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, 0);
+ if (ret < 0)
+ return ret;
+
+ /* Configure the pixel clock polarity */
+ if (pdata && pdata->clk_pol) {
+ ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
+ MT9T001_PIXEL_CLOCK_INVERT);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Read and check the sensor version */
+ data = mt9t001_read(client, MT9T001_CHIP_VERSION);
+ if (data != MT9T001_CHIP_ID) {
+ dev_err(&client->dev, "MT9T001 not detected, wrong version "
+ "0x%04x\n", data);
+ return -ENODEV;
+ }
+
+ dev_info(&client->dev, "MT9T001 detected at address 0x%02x\n",
+ client->addr);
+
+ return ret;
+}
+
+static int mt9t001_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+{
+ struct mt9t001 *mt9t001;
+ unsigned int i;
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WORD_DATA)) {
+ dev_warn(&client->adapter->dev,
+ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+ return -EIO;
+ }
+
+ ret = mt9t001_video_probe(client);
+ if (ret < 0)
+ return ret;
+
+ mt9t001 = kzalloc(sizeof(*mt9t001), GFP_KERNEL);
+ if (!mt9t001)
+ return -ENOMEM;
+
+ v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
+ ARRAY_SIZE(mt9t001_gains) + 2);
+
+ v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
+ V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
+ MT9T001_SHUTTER_WIDTH_MAX, 1,
+ MT9T001_SHUTTER_WIDTH_DEF);
+ v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
+ V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1);
+
+ for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
+ v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
+
+ for (i = 0; i < ARRAY_SIZE(mt9t001_gains); ++i)
+ mt9t001->gains[i] = v4l2_ctrl_new_custom(&mt9t001->ctrls,
+ &mt9t001_gains[i], NULL);
+
+ v4l2_ctrl_cluster(ARRAY_SIZE(mt9t001_gains), mt9t001->gains);
+
+ mt9t001->subdev.ctrl_handler = &mt9t001->ctrls;
+
+ if (mt9t001->ctrls.error) {
+ printk(KERN_INFO "%s: control initialization error %d\n",
+ __func__, mt9t001->ctrls.error);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ mt9t001->crop.left = MT9T001_COLUMN_START_DEF;
+ mt9t001->crop.top = MT9T001_ROW_START_DEF;
+ mt9t001->crop.width = MT9T001_WINDOW_WIDTH_DEF + 1;
+ mt9t001->crop.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+
+ mt9t001->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+ mt9t001->format.width = MT9T001_WINDOW_WIDTH_DEF + 1;
+ mt9t001->format.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+ mt9t001->format.field = V4L2_FIELD_NONE;
+ mt9t001->format.colorspace = V4L2_COLORSPACE_SRGB;
+
+ v4l2_i2c_subdev_init(&mt9t001->subdev, client, &mt9t001_subdev_ops);
+ mt9t001->subdev.internal_ops = &mt9t001_subdev_internal_ops;
+ mt9t001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ mt9t001->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_init(&mt9t001->subdev.entity, 1, &mt9t001->pad, 0);
+
+done:
+ if (ret < 0) {
+ v4l2_ctrl_handler_free(&mt9t001->ctrls);
+ media_entity_cleanup(&mt9t001->subdev.entity);
+ kfree(mt9t001);
+ }
+
+ return ret;
+}
+
+static int mt9t001_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+ struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+ v4l2_ctrl_handler_free(&mt9t001->ctrls);
+ v4l2_device_unregister_subdev(subdev);
+ media_entity_cleanup(&subdev->entity);
+ kfree(mt9t001);
+ return 0;
+}
+
+static const struct i2c_device_id mt9t001_id[] = {
+ { "mt9t001", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9t001_id);
+
+static struct i2c_driver mt9t001_driver = {
+ .driver = {
+ .name = "mt9t001",
+ },
+ .probe = mt9t001_probe,
+ .remove = mt9t001_remove,
+ .id_table = mt9t001_id,
+};
+
+static int __init mt9t001_init(void)
+{
+ return i2c_add_driver(&mt9t001_driver);
+}
+
+static void __exit mt9t001_exit(void)
+{
+ i2c_del_driver(&mt9t001_driver);
+}
+
+module_init(mt9t001_init);
+module_exit(mt9t001_exit);
+
+MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver");
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index c045b47803ad..c8e958a07e91 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -191,7 +191,7 @@ static void mx3_cam_dma_done(void *arg)
*/
static int mx3_videobuf_setup(struct vb2_queue *vq,
unsigned int *count, unsigned int *num_planes,
- unsigned long sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], void *alloc_ctxs[])
{
struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -247,7 +247,7 @@ static int mx3_videobuf_prepare(struct vb2_buffer *vb)
}
if (buf->state == CSI_BUF_NEEDS_INIT) {
- sg_dma_address(sg) = vb2_dma_contig_plane_paddr(vb, 0);
+ sg_dma_address(sg) = vb2_dma_contig_plane_dma_addr(vb, 0);
sg_dma_len(sg) = new_size;
buf->txd = ichan->dma_chan.device->device_prep_slave_sg(
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index 0b3850023505..f0c3968ac7eb 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -21,6 +21,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define DEBUG_VARIABLE debug
#include <media/saa7146_vv.h>
@@ -171,7 +173,7 @@ static int mxb_probe(struct saa7146_dev *dev)
mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
if (mxb == NULL) {
- DEB_D(("not enough kernel memory.\n"));
+ DEB_D("not enough kernel memory\n");
return -ENOMEM;
}
@@ -179,7 +181,7 @@ static int mxb_probe(struct saa7146_dev *dev)
saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
- DEB_S(("cannot register i2c-device. skipping.\n"));
+ DEB_S("cannot register i2c-device. skipping.\n");
kfree(mxb);
return -EFAULT;
}
@@ -200,7 +202,7 @@ static int mxb_probe(struct saa7146_dev *dev)
/* check if all devices are present */
if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
!mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
- printk("mxb: did not find all i2c devices. aborting\n");
+ pr_err("did not find all i2c devices. aborting\n");
i2c_del_adapter(&mxb->i2c_adapter);
kfree(mxb);
return -ENODEV;
@@ -346,11 +348,11 @@ static int mxb_init_done(struct saa7146_dev* dev)
msg.buf = &mxb_saa7740_init[i].data[0];
err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
if (err != 1) {
- DEB_D(("failed to initialize 'sound arena module'.\n"));
+ DEB_D("failed to initialize 'sound arena module'\n");
goto err;
}
}
- INFO(("'sound arena module' detected.\n"));
+ pr_info("'sound arena module' detected\n");
}
err:
/* the rest for saa7146: you should definitely set some basic values
@@ -390,7 +392,7 @@ static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *
for (i = MAXCONTROLS - 1; i >= 0; i--) {
if (mxb_controls[i].id == qc->id) {
*qc = mxb_controls[i];
- DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
+ DEB_D("VIDIOC_QUERYCTRL %d\n", qc->id);
return 0;
}
}
@@ -413,11 +415,11 @@ static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
if (vc->id == V4L2_CID_AUDIO_MUTE) {
vc->value = mxb->cur_mute;
- DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
+ DEB_D("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value);
return 0;
}
- DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
+ DEB_EE("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value);
return 0;
}
@@ -440,14 +442,14 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
/* switch the audio-source */
tea6420_route_line(mxb, vc->value ? 6 :
video_audio_connect[mxb->cur_input]);
- DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
+ DEB_EE("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d\n", vc->value);
}
return 0;
}
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{
- DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+ DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
if (i->index >= MXB_INPUTS)
return -EINVAL;
memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
@@ -460,7 +462,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
struct mxb *mxb = (struct mxb *)dev->ext_priv;
*i = mxb->cur_input;
- DEB_EE(("VIDIOC_G_INPUT %d.\n", *i));
+ DEB_EE("VIDIOC_G_INPUT %d\n", *i);
return 0;
}
@@ -471,7 +473,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
int err = 0;
int i = 0;
- DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
+ DEB_EE("VIDIOC_S_INPUT %d\n", input);
if (input >= MXB_INPUTS)
return -EINVAL;
@@ -514,7 +516,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
/* switch video in saa7111a */
if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
- printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a.\n");
+ pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
/* switch the audio-source only if necessary */
if (0 == mxb->cur_mute)
@@ -529,11 +531,12 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
struct mxb *mxb = (struct mxb *)dev->ext_priv;
if (t->index) {
- DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
+ DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
+ t->index);
return -EINVAL;
}
- DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
+ DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
memset(t, 0, sizeof(*t));
strlcpy(t->name, "TV Tuner", sizeof(t->name));
@@ -550,7 +553,8 @@ static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
struct mxb *mxb = (struct mxb *)dev->ext_priv;
if (t->index) {
- DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n", t->index));
+ DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
+ t->index);
return -EINVAL;
}
@@ -564,14 +568,14 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency
struct mxb *mxb = (struct mxb *)dev->ext_priv;
if (mxb->cur_input) {
- DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
- mxb->cur_input));
+ DEB_D("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
+ mxb->cur_input);
return -EINVAL;
}
*f = mxb->cur_freq;
- DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency));
+ DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
return 0;
}
@@ -588,12 +592,13 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency
return -EINVAL;
if (mxb->cur_input) {
- DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
+ DEB_D("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",
+ mxb->cur_input);
return -EINVAL;
}
mxb->cur_freq = *f;
- DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency));
+ DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
/* tune in desired frequency */
tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
@@ -612,18 +617,18 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
struct mxb *mxb = (struct mxb *)dev->ext_priv;
if (a->index > MXB_INPUTS) {
- DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
+ DEB_D("VIDIOC_G_AUDIO %d out of range\n", a->index);
return -EINVAL;
}
- DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
+ DEB_EE("VIDIOC_G_AUDIO %d\n", a->index);
memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
return 0;
}
static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
{
- DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
+ DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
return 0;
}
@@ -655,11 +660,11 @@ static long vidioc_default(struct file *file, void *fh, bool valid_prio,
int i = *(int *)arg;
if (i < 0 || i >= MXB_AUDIOS) {
- DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n", i));
+ DEB_D("invalid argument to MXB_S_AUDIO_CD: i:%d\n", i);
return -EINVAL;
}
- DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i));
+ DEB_EE("MXB_S_AUDIO_CD: i:%d\n", i);
tea6420_route_cd(mxb, i);
return 0;
@@ -669,17 +674,18 @@ static long vidioc_default(struct file *file, void *fh, bool valid_prio,
int i = *(int *)arg;
if (i < 0 || i >= MXB_AUDIOS) {
- DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n", i));
+ DEB_D("invalid argument to MXB_S_AUDIO_LINE: i:%d\n",
+ i);
return -EINVAL;
}
- DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i));
+ DEB_EE("MXB_S_AUDIO_LINE: i:%d\n", i);
tea6420_route_line(mxb, i);
return 0;
}
default:
/*
- DEB2(printk("does not handle this ioctl.\n"));
+ DEB2(pr_err("does not handle this ioctl\n"));
*/
return -ENOIOCTLCMD;
}
@@ -693,7 +699,7 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data
{
struct mxb *mxb;
- DEB_EE(("dev:%p\n", dev));
+ DEB_EE("dev:%p\n", dev);
saa7146_vv_init(dev, &vv_data);
if (mxb_probe(dev)) {
@@ -720,7 +726,7 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data
#endif
vv_data.ops.vidioc_default = vidioc_default;
if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
- ERR(("cannot register capture v4l2 device. skipping.\n"));
+ ERR("cannot register capture v4l2 device. skipping.\n");
saa7146_vv_release(dev);
return -1;
}
@@ -728,11 +734,11 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data
/* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
if (MXB_BOARD_CAN_DO_VBI(dev)) {
if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
- ERR(("cannot register vbi v4l2 device. skipping.\n"));
+ ERR("cannot register vbi v4l2 device. skipping.\n");
}
}
- printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num);
+ pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
mxb_num++;
mxb_init_done(dev);
@@ -743,7 +749,7 @@ static int mxb_detach(struct saa7146_dev *dev)
{
struct mxb *mxb = (struct mxb *)dev->ext_priv;
- DEB_EE(("dev:%p\n", dev));
+ DEB_EE("dev:%p\n", dev);
saa7146_unregister_device(&mxb->video_dev,dev);
if (MXB_BOARD_CAN_DO_VBI(dev))
@@ -765,7 +771,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa
if (V4L2_STD_PAL_I == standard->id) {
v4l2_std_id std = V4L2_STD_PAL_I;
- DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
+ DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
/* set the 7146 gpio register -- I don't know what this does exactly */
saa7146_write(dev, GPIO_CTRL, 0x00404050);
/* unset the 7111 gpio register -- I don't know what this does exactly */
@@ -774,7 +780,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa
} else {
v4l2_std_id std = V4L2_STD_PAL_BG;
- DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
+ DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
/* set the 7146 gpio register -- I don't know what this does exactly */
saa7146_write(dev, GPIO_CTRL, 0x00404050);
/* set the 7111 gpio register -- I don't know what this does exactly */
@@ -852,7 +858,7 @@ static struct saa7146_extension extension = {
static int __init mxb_init_module(void)
{
if (saa7146_register_extension(&extension)) {
- DEB_S(("failed to register extension.\n"));
+ DEB_S("failed to register extension\n");
return -ENODEV;
}
diff --git a/drivers/media/video/noon010pc30.c b/drivers/media/video/noon010pc30.c
index 35f722a88f76..6cd21cf91b44 100644
--- a/drivers/media/video/noon010pc30.c
+++ b/drivers/media/video/noon010pc30.c
@@ -1,7 +1,7 @@
/*
* Driver for SiliconFile NOON010PC30 CIF (1/11") Image Sensor with ISP
*
- * Copyright (C) 2010 Samsung Electronics
+ * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd.
* Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
*
* Initial register configuration based on a driver authored by
@@ -10,7 +10,7 @@
* 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 vergsion.
+ * (at your option) any later version.
*/
#include <linux/delay.h>
@@ -131,17 +131,23 @@ static const char * const noon010_supply_name[] = {
struct noon010_info {
struct v4l2_subdev sd;
+ struct media_pad pad;
struct v4l2_ctrl_handler hdl;
- const struct noon010pc30_platform_data *pdata;
+ struct regulator_bulk_data supply[NOON010_NUM_SUPPLIES];
+ u32 gpio_nreset;
+ u32 gpio_nstby;
+
+ /* Protects the struct members below */
+ struct mutex lock;
+
const struct noon010_format *curr_fmt;
const struct noon010_frmsize *curr_win;
+ unsigned int apply_new_cfg:1;
+ unsigned int streaming:1;
unsigned int hflip:1;
unsigned int vflip:1;
unsigned int power:1;
u8 i2c_reg_page;
- struct regulator_bulk_data supply[NOON010_NUM_SUPPLIES];
- u32 gpio_nreset;
- u32 gpio_nstby;
};
struct i2c_regval {
@@ -292,8 +298,10 @@ static int noon010_power_ctrl(struct v4l2_subdev *sd, bool reset, bool sleep)
u8 reg = sleep ? 0xF1 : 0xF0;
int ret = 0;
- if (reset)
+ if (reset) {
ret = cam_i2c_write(sd, POWER_CTRL_REG, reg | 0x02);
+ udelay(20);
+ }
if (!ret) {
ret = cam_i2c_write(sd, POWER_CTRL_REG, reg);
if (reset && !ret)
@@ -313,6 +321,7 @@ static int noon010_enable_autowhitebalance(struct v4l2_subdev *sd, int on)
return ret;
}
+/* Called with struct noon010_info.lock mutex held */
static int noon010_set_flip(struct v4l2_subdev *sd, int hflip, int vflip)
{
struct noon010_info *info = to_noon010(sd);
@@ -340,21 +349,18 @@ static int noon010_set_flip(struct v4l2_subdev *sd, int hflip, int vflip)
static int noon010_set_params(struct v4l2_subdev *sd)
{
struct noon010_info *info = to_noon010(sd);
- int ret;
- if (!info->curr_win)
- return -EINVAL;
-
- ret = cam_i2c_write(sd, VDO_CTL_REG(0), info->curr_win->vid_ctl1);
-
- if (!ret && info->curr_fmt)
- ret = cam_i2c_write(sd, ISP_CTL_REG(0),
- info->curr_fmt->ispctl1_reg);
- return ret;
+ int ret = cam_i2c_write(sd, VDO_CTL_REG(0),
+ info->curr_win->vid_ctl1);
+ if (ret)
+ return ret;
+ return cam_i2c_write(sd, ISP_CTL_REG(0),
+ info->curr_fmt->ispctl1_reg);
}
/* Find nearest matching image pixel size. */
-static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf)
+static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf,
+ const struct noon010_frmsize **size)
{
unsigned int min_err = ~0;
int i = ARRAY_SIZE(noon010_sizes);
@@ -374,11 +380,14 @@ static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf)
if (match) {
mf->width = match->width;
mf->height = match->height;
+ if (size)
+ *size = match;
return 0;
}
return -EINVAL;
}
+/* Called with info.lock mutex held */
static int power_enable(struct noon010_info *info)
{
int ret;
@@ -419,6 +428,7 @@ static int power_enable(struct noon010_info *info)
return 0;
}
+/* Called with info.lock mutex held */
static int power_disable(struct noon010_info *info)
{
int ret;
@@ -448,147 +458,175 @@ static int power_disable(struct noon010_info *info)
static int noon010_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = to_sd(ctrl);
+ struct noon010_info *info = to_noon010(sd);
+ int ret = 0;
v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
__func__, ctrl->id, ctrl->val);
+ mutex_lock(&info->lock);
+ /*
+ * If the device is not powered up by the host driver do
+ * not apply any controls to H/W at this time. Instead
+ * the controls will be restored right after power-up.
+ */
+ if (!info->power)
+ goto unlock;
+
switch (ctrl->id) {
case V4L2_CID_AUTO_WHITE_BALANCE:
- return noon010_enable_autowhitebalance(sd, ctrl->val);
+ ret = noon010_enable_autowhitebalance(sd, ctrl->val);
+ break;
case V4L2_CID_BLUE_BALANCE:
- return cam_i2c_write(sd, MWB_BGAIN_REG, ctrl->val);
+ ret = cam_i2c_write(sd, MWB_BGAIN_REG, ctrl->val);
+ break;
case V4L2_CID_RED_BALANCE:
- return cam_i2c_write(sd, MWB_RGAIN_REG, ctrl->val);
+ ret = cam_i2c_write(sd, MWB_RGAIN_REG, ctrl->val);
+ break;
default:
- return -EINVAL;
+ ret = -EINVAL;
}
+unlock:
+ mutex_unlock(&info->lock);
+ return ret;
}
-static int noon010_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- enum v4l2_mbus_pixelcode *code)
+static int noon010_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (!code || index >= ARRAY_SIZE(noon010_formats))
+ if (code->index >= ARRAY_SIZE(noon010_formats))
return -EINVAL;
- *code = noon010_formats[index].code;
+ code->code = noon010_formats[code->index].code;
return 0;
}
-static int noon010_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+static int noon010_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
{
struct noon010_info *info = to_noon010(sd);
- int ret;
-
- if (!mf)
- return -EINVAL;
+ struct v4l2_mbus_framefmt *mf;
- if (!info->curr_win || !info->curr_fmt) {
- ret = noon010_set_params(sd);
- if (ret)
- return ret;
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ if (fh) {
+ mf = v4l2_subdev_get_try_format(fh, 0);
+ fmt->format = *mf;
+ }
+ return 0;
}
+ mf = &fmt->format;
- mf->width = info->curr_win->width;
- mf->height = info->curr_win->height;
- mf->code = info->curr_fmt->code;
- mf->colorspace = info->curr_fmt->colorspace;
- mf->field = V4L2_FIELD_NONE;
+ mutex_lock(&info->lock);
+ mf->width = info->curr_win->width;
+ mf->height = info->curr_win->height;
+ mf->code = info->curr_fmt->code;
+ mf->colorspace = info->curr_fmt->colorspace;
+ mf->field = V4L2_FIELD_NONE;
+ mutex_unlock(&info->lock);
return 0;
}
/* Return nearest media bus frame format. */
-static const struct noon010_format *try_fmt(struct v4l2_subdev *sd,
+static const struct noon010_format *noon010_try_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *mf)
{
int i = ARRAY_SIZE(noon010_formats);
- noon010_try_frame_size(mf);
-
- while (i--)
+ while (--i)
if (mf->code == noon010_formats[i].code)
break;
-
mf->code = noon010_formats[i].code;
return &noon010_formats[i];
}
-static int noon010_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- if (!sd || !mf)
- return -EINVAL;
-
- try_fmt(sd, mf);
- return 0;
-}
-
-static int noon010_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
{
struct noon010_info *info = to_noon010(sd);
+ const struct noon010_frmsize *size = NULL;
+ const struct noon010_format *nf;
+ struct v4l2_mbus_framefmt *mf;
+ int ret = 0;
- if (!sd || !mf)
- return -EINVAL;
-
- info->curr_fmt = try_fmt(sd, mf);
+ nf = noon010_try_fmt(sd, &fmt->format);
+ noon010_try_frame_size(&fmt->format, &size);
+ fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
- return noon010_set_params(sd);
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ if (fh) {
+ mf = v4l2_subdev_get_try_format(fh, 0);
+ *mf = fmt->format;
+ }
+ return 0;
+ }
+ mutex_lock(&info->lock);
+ if (!info->streaming) {
+ info->apply_new_cfg = 1;
+ info->curr_fmt = nf;
+ info->curr_win = size;
+ } else {
+ ret = -EBUSY;
+ }
+ mutex_unlock(&info->lock);
+ return ret;
}
+/* Called with struct noon010_info.lock mutex held */
static int noon010_base_config(struct v4l2_subdev *sd)
{
- struct noon010_info *info = to_noon010(sd);
- int ret;
-
- ret = noon010_bulk_write_reg(sd, noon010_base_regs);
- if (!ret) {
- info->curr_fmt = &noon010_formats[0];
- info->curr_win = &noon010_sizes[0];
+ int ret = noon010_bulk_write_reg(sd, noon010_base_regs);
+ if (!ret)
ret = noon010_set_params(sd);
- }
if (!ret)
ret = noon010_set_flip(sd, 1, 0);
- if (!ret)
- ret = noon010_power_ctrl(sd, false, false);
- /* sync the handler and the registers state */
- v4l2_ctrl_handler_setup(&to_noon010(sd)->hdl);
return ret;
}
static int noon010_s_power(struct v4l2_subdev *sd, int on)
{
struct noon010_info *info = to_noon010(sd);
- const struct noon010pc30_platform_data *pdata = info->pdata;
- int ret = 0;
-
- if (WARN(pdata == NULL, "No platform data!\n"))
- return -ENOMEM;
+ int ret;
+ mutex_lock(&info->lock);
if (on) {
ret = power_enable(info);
- if (ret)
- return ret;
- ret = noon010_base_config(sd);
+ if (!ret)
+ ret = noon010_base_config(sd);
} else {
noon010_power_ctrl(sd, false, true);
ret = power_disable(info);
- info->curr_win = NULL;
- info->curr_fmt = NULL;
}
+ mutex_unlock(&info->lock);
+
+ /* Restore the controls state */
+ if (!ret && on)
+ ret = v4l2_ctrl_handler_setup(&info->hdl);
return ret;
}
-static int noon010_g_chip_ident(struct v4l2_subdev *sd,
- struct v4l2_dbg_chip_ident *chip)
+static int noon010_s_stream(struct v4l2_subdev *sd, int on)
{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct noon010_info *info = to_noon010(sd);
+ int ret = 0;
- return v4l2_chip_ident_i2c_client(client, chip,
- V4L2_IDENT_NOON010PC30, 0);
+ mutex_lock(&info->lock);
+ if (!info->streaming != !on) {
+ ret = noon010_power_ctrl(sd, false, !on);
+ if (!ret)
+ info->streaming = on;
+ }
+ if (!ret && on && info->apply_new_cfg) {
+ ret = noon010_set_params(sd);
+ if (!ret)
+ info->apply_new_cfg = 0;
+ }
+ mutex_unlock(&info->lock);
+ return ret;
}
static int noon010_log_status(struct v4l2_subdev *sd)
@@ -599,12 +637,27 @@ static int noon010_log_status(struct v4l2_subdev *sd)
return 0;
}
+static int noon010_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0);
+
+ mf->width = noon010_sizes[0].width;
+ mf->height = noon010_sizes[0].height;
+ mf->code = noon010_formats[0].code;
+ mf->colorspace = V4L2_COLORSPACE_JPEG;
+ mf->field = V4L2_FIELD_NONE;
+ return 0;
+}
+
+static const struct v4l2_subdev_internal_ops noon010_subdev_internal_ops = {
+ .open = noon010_open,
+};
+
static const struct v4l2_ctrl_ops noon010_ctrl_ops = {
.s_ctrl = noon010_s_ctrl,
};
static const struct v4l2_subdev_core_ops noon010_core_ops = {
- .g_chip_ident = noon010_g_chip_ident,
.s_power = noon010_s_power,
.g_ctrl = v4l2_subdev_g_ctrl,
.s_ctrl = v4l2_subdev_s_ctrl,
@@ -616,15 +669,19 @@ static const struct v4l2_subdev_core_ops noon010_core_ops = {
.log_status = noon010_log_status,
};
-static const struct v4l2_subdev_video_ops noon010_video_ops = {
- .g_mbus_fmt = noon010_g_fmt,
- .s_mbus_fmt = noon010_s_fmt,
- .try_mbus_fmt = noon010_try_fmt,
- .enum_mbus_fmt = noon010_enum_fmt,
+static struct v4l2_subdev_pad_ops noon010_pad_ops = {
+ .enum_mbus_code = noon010_enum_mbus_code,
+ .get_fmt = noon010_get_fmt,
+ .set_fmt = noon010_set_fmt,
+};
+
+static struct v4l2_subdev_video_ops noon010_video_ops = {
+ .s_stream = noon010_s_stream,
};
static const struct v4l2_subdev_ops noon010_ops = {
.core = &noon010_core_ops,
+ .pad = &noon010_pad_ops,
.video = &noon010_video_ops,
};
@@ -665,10 +722,14 @@ static int noon010_probe(struct i2c_client *client,
if (!info)
return -ENOMEM;
+ mutex_init(&info->lock);
sd = &info->sd;
strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
v4l2_i2c_subdev_init(sd, client, &noon010_ops);
+ sd->internal_ops = &noon010_subdev_internal_ops;
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
v4l2_ctrl_handler_init(&info->hdl, 3);
v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
@@ -684,10 +745,11 @@ static int noon010_probe(struct i2c_client *client,
if (ret)
goto np_err;
- info->pdata = client->dev.platform_data;
info->i2c_reg_page = -1;
info->gpio_nreset = -EINVAL;
info->gpio_nstby = -EINVAL;
+ info->curr_fmt = &noon010_formats[0];
+ info->curr_win = &noon010_sizes[0];
if (gpio_is_valid(pdata->gpio_nreset)) {
ret = gpio_request(pdata->gpio_nreset, "NOON010PC30 NRST");
@@ -719,11 +781,17 @@ static int noon010_probe(struct i2c_client *client,
if (ret)
goto np_reg_err;
+ info->pad.flags = MEDIA_PAD_FL_SOURCE;
+ sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+ ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
+ if (ret < 0)
+ goto np_me_err;
+
ret = noon010_detect(client, info);
if (!ret)
return 0;
- /* the sensor detection failed */
+np_me_err:
regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply);
np_reg_err:
if (gpio_is_valid(info->gpio_nstby))
@@ -754,6 +822,7 @@ static int noon010_remove(struct i2c_client *client)
if (gpio_is_valid(info->gpio_nstby))
gpio_free(info->gpio_nstby);
+ media_entity_cleanup(&sd->entity);
kfree(info);
return 0;
}
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index b3a5ecdb33ac..30d8896bb710 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -400,7 +400,6 @@ static int omapvid_setup_overlay(struct omap_vout_device *vout,
ovl->get_overlay_info(ovl, &info);
info.paddr = addr;
- info.vaddr = NULL;
info.width = cropwidth;
info.height = cropheight;
info.color_mode = vout->dss_mode;
@@ -1165,12 +1164,17 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,
{
int ret = 0;
struct omap_vout_device *vout = fh;
+ struct omap_overlay *ovl;
+ struct omapvideo_info *ovid;
struct v4l2_window *win = &f->fmt.win;
+ ovid = &vout->vid_info;
+ ovl = ovid->overlays[0];
+
ret = omap_vout_try_window(&vout->fbuf, win);
if (!ret) {
- if (vout->vid == OMAP_VIDEO1)
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
win->global_alpha = 255;
else
win->global_alpha = f->fmt.win.global_alpha;
@@ -1194,8 +1198,8 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
if (!ret) {
- /* Video1 plane does not support global alpha */
- if (ovl->id == OMAP_DSS_VIDEO1)
+ /* Video1 plane does not support global alpha on OMAP3 */
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
vout->win.global_alpha = 255;
else
vout->win.global_alpha = f->fmt.win.global_alpha;
@@ -1788,7 +1792,9 @@ static int vidioc_s_fbuf(struct file *file, void *fh,
if (ovl->manager && ovl->manager->get_manager_info &&
ovl->manager->set_manager_info) {
ovl->manager->get_manager_info(ovl->manager, &info);
- info.alpha_enabled = enable;
+ /* enable this only if there is no zorder cap */
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+ info.partial_alpha_enabled = enable;
if (ovl->manager->set_manager_info(ovl->manager, &info))
return -EINVAL;
}
@@ -1820,7 +1826,7 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
}
if (ovl->manager && ovl->manager->get_manager_info) {
ovl->manager->get_manager_info(ovl->manager, &info);
- if (info.alpha_enabled)
+ if (info.partial_alpha_enabled)
a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
}
diff --git a/drivers/media/video/omap3isp/Makefile b/drivers/media/video/omap3isp/Makefile
index b1b344774ae7..e8847e79e31a 100644
--- a/drivers/media/video/omap3isp/Makefile
+++ b/drivers/media/video/omap3isp/Makefile
@@ -1,8 +1,6 @@
# Makefile for OMAP3 ISP driver
-ifdef CONFIG_VIDEO_OMAP3_DEBUG
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_VIDEO_OMAP3_DEBUG) += -DDEBUG
omap3-isp-objs += \
isp.o ispqueue.o ispvideo.o \
diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c
index 5cea2bbd7014..678e1252047a 100644
--- a/drivers/media/video/omap3isp/isp.c
+++ b/drivers/media/video/omap3isp/isp.c
@@ -80,6 +80,13 @@
#include "isph3a.h"
#include "isphist.h"
+/*
+ * this is provided as an interim solution until omap3isp doesn't need
+ * any omap-specific iommu API
+ */
+#define to_iommu(dev) \
+ (struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
+
static unsigned int autoidle;
module_param(autoidle, int, 0444);
MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support");
@@ -732,7 +739,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
struct media_pad *pad;
struct v4l2_subdev *subdev;
unsigned long flags;
- int ret = 0;
+ int ret;
spin_lock_irqsave(&pipe->lock, flags);
pipe->state &= ~(ISP_PIPELINE_IDLE_INPUT | ISP_PIPELINE_IDLE_OUTPUT);
@@ -756,7 +763,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
ret = v4l2_subdev_call(subdev, video, s_stream, mode);
if (ret < 0 && ret != -ENOIOCTLCMD)
- break;
+ return ret;
if (subdev == &isp->isp_ccdc.subdev) {
v4l2_subdev_call(&isp->isp_aewb.subdev, video,
@@ -777,7 +784,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
if (pipe->do_propagation && mode == ISP_PIPELINE_STREAM_SINGLESHOT)
atomic_inc(&pipe->frame_number);
- return ret;
+ return 0;
}
static int isp_pipeline_wait_resizer(struct isp_device *isp)
@@ -1108,7 +1115,7 @@ static void isp_save_ctx(struct isp_device *isp)
{
isp_save_context(isp, isp_reg_list);
if (isp->iommu)
- iommu_save_ctx(isp->iommu);
+ omap_iommu_save_ctx(isp->iommu);
}
/*
@@ -1122,7 +1129,7 @@ static void isp_restore_ctx(struct isp_device *isp)
{
isp_restore_context(isp, isp_reg_list);
if (isp->iommu)
- iommu_restore_ctx(isp->iommu);
+ omap_iommu_restore_ctx(isp->iommu);
omap3isp_ccdc_restore_context(isp);
omap3isp_preview_restore_context(isp);
}
@@ -1975,7 +1982,8 @@ static int isp_remove(struct platform_device *pdev)
isp_cleanup_modules(isp);
omap3isp_get(isp);
- iommu_put(isp->iommu);
+ iommu_detach_device(isp->domain, isp->iommu_dev);
+ iommu_domain_free(isp->domain);
omap3isp_put(isp);
free_irq(isp->irq_num, isp);
@@ -2123,25 +2131,41 @@ static int isp_probe(struct platform_device *pdev)
}
/* IOMMU */
- isp->iommu = iommu_get("isp");
- if (IS_ERR_OR_NULL(isp->iommu)) {
- isp->iommu = NULL;
+ isp->iommu_dev = omap_find_iommu_device("isp");
+ if (!isp->iommu_dev) {
+ dev_err(isp->dev, "omap_find_iommu_device failed\n");
ret = -ENODEV;
goto error_isp;
}
+ /* to be removed once iommu migration is complete */
+ isp->iommu = to_iommu(isp->iommu_dev);
+
+ isp->domain = iommu_domain_alloc(pdev->dev.bus);
+ if (!isp->domain) {
+ dev_err(isp->dev, "can't alloc iommu domain\n");
+ ret = -ENOMEM;
+ goto error_isp;
+ }
+
+ ret = iommu_attach_device(isp->domain, isp->iommu_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret);
+ goto free_domain;
+ }
+
/* Interrupt */
isp->irq_num = platform_get_irq(pdev, 0);
if (isp->irq_num <= 0) {
dev_err(isp->dev, "No IRQ resource\n");
ret = -ENODEV;
- goto error_isp;
+ goto detach_dev;
}
if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) {
dev_err(isp->dev, "Unable to request IRQ\n");
ret = -EINVAL;
- goto error_isp;
+ goto detach_dev;
}
/* Entities */
@@ -2162,8 +2186,11 @@ error_modules:
isp_cleanup_modules(isp);
error_irq:
free_irq(isp->irq_num, isp);
+detach_dev:
+ iommu_detach_device(isp->domain, isp->iommu_dev);
+free_domain:
+ iommu_domain_free(isp->domain);
error_isp:
- iommu_put(isp->iommu);
omap3isp_put(isp);
error:
isp_put_clocks(isp);
diff --git a/drivers/media/video/omap3isp/isp.h b/drivers/media/video/omap3isp/isp.h
index 529e582ef948..705946ef4d60 100644
--- a/drivers/media/video/omap3isp/isp.h
+++ b/drivers/media/video/omap3isp/isp.h
@@ -27,11 +27,13 @@
#ifndef OMAP3_ISP_CORE_H
#define OMAP3_ISP_CORE_H
+#include <media/omap3isp.h>
#include <media/v4l2-device.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/wait.h>
+#include <linux/iommu.h>
#include <plat/iommu.h>
#include <plat/iovmm.h>
@@ -94,14 +96,6 @@ enum isp_subclk_resource {
OMAP3_ISP_SUBCLK_RESIZER = (1 << 4),
};
-enum isp_interface_type {
- ISP_INTERFACE_PARALLEL,
- ISP_INTERFACE_CSI2A_PHY2,
- ISP_INTERFACE_CCP2B_PHY1,
- ISP_INTERFACE_CCP2B_PHY2,
- ISP_INTERFACE_CSI2C_PHY1,
-};
-
/* ISP: OMAP 34xx ES 1.0 */
#define ISP_REVISION_1_0 0x10
/* ISP2: OMAP 34xx ES 2.0, 2.1 and 3.0 */
@@ -130,82 +124,6 @@ struct isp_reg {
u32 val;
};
-/**
- * struct isp_parallel_platform_data - Parallel interface platform data
- * @data_lane_shift: Data lane shifter
- * 0 - CAMEXT[13:0] -> CAM[13:0]
- * 1 - CAMEXT[13:2] -> CAM[11:0]
- * 2 - CAMEXT[13:4] -> CAM[9:0]
- * 3 - CAMEXT[13:6] -> CAM[7:0]
- * @clk_pol: Pixel clock polarity
- * 0 - Non Inverted, 1 - Inverted
- * @hs_pol: Horizontal synchronization polarity
- * 0 - Active high, 1 - Active low
- * @vs_pol: Vertical synchronization polarity
- * 0 - Active high, 1 - Active low
- * @bridge: CCDC Bridge input control
- * ISPCTRL_PAR_BRIDGE_DISABLE - Disable
- * ISPCTRL_PAR_BRIDGE_LENDIAN - Little endian
- * ISPCTRL_PAR_BRIDGE_BENDIAN - Big endian
- */
-struct isp_parallel_platform_data {
- unsigned int data_lane_shift:2;
- unsigned int clk_pol:1;
- unsigned int hs_pol:1;
- unsigned int vs_pol:1;
- unsigned int bridge:4;
-};
-
-/**
- * struct isp_ccp2_platform_data - CCP2 interface platform data
- * @strobe_clk_pol: Strobe/clock polarity
- * 0 - Non Inverted, 1 - Inverted
- * @crc: Enable the cyclic redundancy check
- * @ccp2_mode: Enable CCP2 compatibility mode
- * 0 - MIPI-CSI1 mode, 1 - CCP2 mode
- * @phy_layer: Physical layer selection
- * ISPCCP2_CTRL_PHY_SEL_CLOCK - Data/clock physical layer
- * ISPCCP2_CTRL_PHY_SEL_STROBE - Data/strobe physical layer
- * @vpclk_div: Video port output clock control
- */
-struct isp_ccp2_platform_data {
- unsigned int strobe_clk_pol:1;
- unsigned int crc:1;
- unsigned int ccp2_mode:1;
- unsigned int phy_layer:1;
- unsigned int vpclk_div:2;
-};
-
-/**
- * struct isp_csi2_platform_data - CSI2 interface platform data
- * @crc: Enable the cyclic redundancy check
- * @vpclk_div: Video port output clock control
- */
-struct isp_csi2_platform_data {
- unsigned crc:1;
- unsigned vpclk_div:2;
-};
-
-struct isp_subdev_i2c_board_info {
- struct i2c_board_info *board_info;
- int i2c_adapter_id;
-};
-
-struct isp_v4l2_subdevs_group {
- struct isp_subdev_i2c_board_info *subdevs;
- enum isp_interface_type interface;
- union {
- struct isp_parallel_platform_data parallel;
- struct isp_ccp2_platform_data ccp2;
- struct isp_csi2_platform_data csi2;
- } bus; /* gcc < 4.6.0 chokes on anonymous union initializers */
-};
-
-struct isp_platform_data {
- struct isp_v4l2_subdevs_group *subdevs;
- void (*set_constraints)(struct isp_device *isp, bool enable);
-};
-
struct isp_platform_callback {
u32 (*set_xclk)(struct isp_device *isp, u32 xclk, u8 xclksel);
int (*csiphy_config)(struct isp_csiphy *phy,
@@ -294,7 +212,9 @@ struct isp_device {
unsigned int sbl_resources;
unsigned int subclk_resources;
- struct iommu *iommu;
+ struct omap_iommu *iommu;
+ struct iommu_domain *domain;
+ struct device *iommu_dev;
struct isp_platform_callback platform_cb;
};
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index 80796eb0c53e..253fdcce2df2 100644
--- a/drivers/media/video/omap3isp/ispccdc.c
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -366,7 +366,7 @@ static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc,
dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
req->iovm->sgt->nents, DMA_TO_DEVICE);
if (req->table)
- iommu_vfree(isp->iommu, req->table);
+ omap_iommu_vfree(isp->domain, isp->iommu, req->table);
kfree(req);
}
@@ -438,15 +438,15 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
req->enable = 1;
- req->table = iommu_vmalloc(isp->iommu, 0, req->config.size,
- IOMMU_FLAG);
+ req->table = omap_iommu_vmalloc(isp->domain, isp->iommu, 0,
+ req->config.size, IOMMU_FLAG);
if (IS_ERR_VALUE(req->table)) {
req->table = 0;
ret = -ENOMEM;
goto done;
}
- req->iovm = find_iovm_area(isp->iommu, req->table);
+ req->iovm = omap_find_iovm_area(isp->iommu, req->table);
if (req->iovm == NULL) {
ret = -ENOMEM;
goto done;
@@ -462,7 +462,7 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl,
req->iovm->sgt->nents, DMA_TO_DEVICE);
- table = da_to_va(isp->iommu, req->table);
+ table = omap_da_to_va(isp->iommu, req->table);
if (copy_from_user(table, config->lsc, req->config.size)) {
ret = -EFAULT;
goto done;
@@ -731,18 +731,19 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
/*
* table_new must be 64-bytes aligned, but it's
- * already done by iommu_vmalloc().
+ * already done by omap_iommu_vmalloc().
*/
size = ccdc->fpc.fpnum * 4;
- table_new = iommu_vmalloc(isp->iommu, 0, size,
- IOMMU_FLAG);
+ table_new = omap_iommu_vmalloc(isp->domain, isp->iommu,
+ 0, size, IOMMU_FLAG);
if (IS_ERR_VALUE(table_new))
return -ENOMEM;
- if (copy_from_user(da_to_va(isp->iommu, table_new),
+ if (copy_from_user(omap_da_to_va(isp->iommu, table_new),
(__force void __user *)
ccdc->fpc.fpcaddr, size)) {
- iommu_vfree(isp->iommu, table_new);
+ omap_iommu_vfree(isp->domain, isp->iommu,
+ table_new);
return -EFAULT;
}
@@ -752,7 +753,7 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
ccdc_configure_fpc(ccdc);
if (table_old != 0)
- iommu_vfree(isp->iommu, table_old);
+ omap_iommu_vfree(isp->domain, isp->iommu, table_old);
}
return ccdc_lsc_config(ccdc, ccdc_struct);
@@ -1405,11 +1406,14 @@ static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
{
+ struct isp_pipeline *pipe =
+ to_isp_pipeline(&ccdc->video_out.video.entity);
struct video_device *vdev = &ccdc->subdev.devnode;
struct v4l2_event event;
memset(&event, 0, sizeof(event));
- event.type = V4L2_EVENT_OMAP3ISP_HS_VS;
+ event.type = V4L2_EVENT_FRAME_SYNC;
+ event.u.frame_sync.frame_sequence = atomic_read(&pipe->frame_number);
v4l2_event_queue(vdev, &event);
}
@@ -1691,7 +1695,11 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
- if (sub->type != V4L2_EVENT_OMAP3ISP_HS_VS)
+ if (sub->type != V4L2_EVENT_FRAME_SYNC)
+ return -EINVAL;
+
+ /* line number is zero at frame start */
+ if (sub->id != 0)
return -EINVAL;
return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS);
@@ -2287,5 +2295,5 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp)
ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
if (ccdc->fpc.fpcaddr != 0)
- iommu_vfree(isp->iommu, ccdc->fpc.fpcaddr);
+ omap_iommu_vfree(isp->domain, isp->iommu, ccdc->fpc.fpcaddr);
}
diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c
index ec9e395f3339..fa1d09b0ad98 100644
--- a/drivers/media/video/omap3isp/ispccp2.c
+++ b/drivers/media/video/omap3isp/ispccp2.c
@@ -243,9 +243,9 @@ static int ccp2_phyif_config(struct isp_ccp2_device *ccp2,
val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
if (!(val & ISPCCP2_CTRL_MODE)) {
- if (pdata->ccp2_mode)
+ if (pdata->ccp2_mode == ISP_CCP2_MODE_CCP2)
dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");
- if (pdata->phy_layer == ISPCCP2_CTRL_PHY_SEL_STROBE)
+ if (pdata->phy_layer == ISP_CCP2_PHY_DATA_STROBE)
/* Strobe mode requires CCP2 */
return -EIO;
}
diff --git a/drivers/media/video/omap3isp/ispqueue.c b/drivers/media/video/omap3isp/ispqueue.c
index 9c317148205f..9bebb1e57aab 100644
--- a/drivers/media/video/omap3isp/ispqueue.c
+++ b/drivers/media/video/omap3isp/ispqueue.c
@@ -868,6 +868,10 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
goto done;
if (vbuf->memory == V4L2_MEMORY_USERPTR &&
+ vbuf->length < buf->vbuf.length)
+ goto done;
+
+ if (vbuf->memory == V4L2_MEMORY_USERPTR &&
vbuf->m.userptr != buf->vbuf.m.userptr) {
isp_video_buffer_cleanup(buf);
buf->vbuf.m.userptr = vbuf->m.userptr;
diff --git a/drivers/media/video/omap3isp/ispstat.c b/drivers/media/video/omap3isp/ispstat.c
index 808065948ac1..732905552261 100644
--- a/drivers/media/video/omap3isp/ispstat.c
+++ b/drivers/media/video/omap3isp/ispstat.c
@@ -366,7 +366,8 @@ static void isp_stat_bufs_free(struct ispstat *stat)
dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
buf->iovm->sgt->nents,
DMA_FROM_DEVICE);
- iommu_vfree(isp->iommu, buf->iommu_addr);
+ omap_iommu_vfree(isp->domain, isp->iommu,
+ buf->iommu_addr);
} else {
if (!buf->virt_addr)
continue;
@@ -399,8 +400,8 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
struct iovm_struct *iovm;
WARN_ON(buf->dma_addr);
- buf->iommu_addr = iommu_vmalloc(isp->iommu, 0, size,
- IOMMU_FLAG);
+ buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->iommu, 0,
+ size, IOMMU_FLAG);
if (IS_ERR((void *)buf->iommu_addr)) {
dev_err(stat->isp->dev,
"%s: Can't acquire memory for "
@@ -409,7 +410,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
return -ENOMEM;
}
- iovm = find_iovm_area(isp->iommu, buf->iommu_addr);
+ iovm = omap_find_iovm_area(isp->iommu, buf->iommu_addr);
if (!iovm ||
!dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
DMA_FROM_DEVICE)) {
@@ -418,7 +419,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
}
buf->iovm = iovm;
- buf->virt_addr = da_to_va(stat->isp->iommu,
+ buf->virt_addr = omap_da_to_va(stat->isp->iommu,
(u32)buf->iommu_addr);
buf->empty = 1;
dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c
index fd965adfd597..0cb8a9f9d675 100644
--- a/drivers/media/video/omap3isp/ispvideo.c
+++ b/drivers/media/video/omap3isp/ispvideo.c
@@ -278,7 +278,8 @@ isp_video_far_end(struct isp_video *video)
* limits reported by every block in the pipeline.
*
* Return 0 if all formats match, or -EPIPE if at least one link is found with
- * different formats on its two ends.
+ * different formats on its two ends or if the pipeline doesn't start with a
+ * video source (either a subdev with no input pad, or a non-subdev entity).
*/
static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
{
@@ -329,10 +330,15 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
* in the middle of it. */
shifter_link = subdev == &isp->isp_ccdc.subdev;
- /* Retrieve the source format */
+ /* Retrieve the source format. Return an error if no source
+ * entity can be found, and stop checking the pipeline if the
+ * source entity isn't a subdev.
+ */
pad = media_entity_remote_source(pad);
- if (pad == NULL ||
- media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ if (pad == NULL)
+ return -EPIPE;
+
+ if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
break;
subdev = media_entity_to_v4l2_subdev(pad->entity);
@@ -446,7 +452,7 @@ ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
sgt->nents = sglen;
sgt->orig_nents = sglen;
- da = iommu_vmap(isp->iommu, 0, sgt, IOMMU_FLAG);
+ da = omap_iommu_vmap(isp->domain, isp->iommu, 0, sgt, IOMMU_FLAG);
if (IS_ERR_VALUE(da))
kfree(sgt);
@@ -462,7 +468,7 @@ static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
{
struct sg_table *sgt;
- sgt = iommu_vunmap(isp->iommu, (u32)da);
+ sgt = omap_iommu_vunmap(isp->domain, isp->iommu, (u32)da);
kfree(sgt);
}
@@ -1050,6 +1056,14 @@ error:
if (video->isp->pdata->set_constraints)
video->isp->pdata->set_constraints(video->isp, false);
media_entity_pipeline_stop(&video->video.entity);
+ /* The DMA queue must be emptied here, otherwise CCDC interrupts
+ * that will get triggered the next time the CCDC is powered up
+ * will try to access buffers that might have been freed but
+ * still present in the DMA queue. This can easily get triggered
+ * if the above omap3isp_pipeline_set_stream() call fails on a
+ * system with a free-running sensor.
+ */
+ INIT_LIST_HEAD(&video->dmaqueue);
video->queue = NULL;
}
diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile
index de2fc14f043b..c17f37d964ad 100644
--- a/drivers/media/video/pvrusb2/Makefile
+++ b/drivers/media/video/pvrusb2/Makefile
@@ -16,7 +16,7 @@ pvrusb2-objs := pvrusb2-i2c-core.o \
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index e98d38212791..5a6f24d1246d 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -2993,6 +2993,13 @@ static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id,
pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \
}
+int pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw, v4l2_std_id *std)
+{
+ v4l2_device_call_all(&hdw->v4l2_dev, 0,
+ video, querystd, std);
+ return 0;
+}
+
/* Execute whatever commands are required to update the state of all the
sub-devices so that they match our current control values. */
static void pvr2_subdev_update(struct pvr2_hdw *hdw)
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index d7753ae9ff46..66546580b17d 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -214,6 +214,9 @@ struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *);
int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,struct v4l2_standard *std,
unsigned int idx);
+/* Get the detected video standard */
+int pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw, v4l2_std_id *std);
+
/* Enable / disable retrieval of CPU firmware or prom contents. This must
be enabled before pvr2_hdw_cpufw_get() will function. Note that doing
this may prevent the device from running (and leaving this mode may
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index e27f8ab76966..ce7ac4595276 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -227,6 +227,14 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
break;
}
+ case VIDIOC_QUERYSTD:
+ {
+ v4l2_std_id *std = arg;
+ *std = V4L2_STD_ALL;
+ ret = pvr2_hdw_get_detected_std(hdw, std);
+ break;
+ }
+
case VIDIOC_G_STD:
{
int val = 0;
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 51ca3589b1b5..360be226718d 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -745,7 +745,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
/* Videobuf2 operations */
static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned long sizes[],
+ unsigned int *nplanes, unsigned int sizes[],
void *alloc_ctxs[])
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
@@ -816,7 +816,7 @@ static void buffer_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
}
-static int start_streaming(struct vb2_queue *vq)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index 8c70e64444e7..a10ff6b64acf 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -83,6 +83,7 @@ static const struct v4l2_ctrl_config pwc_contour_cfg = {
.id = PWC_CID_CUSTOM(contour),
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contour",
+ .flags = V4L2_CTRL_FLAG_SLIDER,
.min = 0,
.max = 63,
.step = 1,
@@ -206,8 +207,7 @@ int pwc_init_controls(struct pwc_device *pdev)
pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
V4L2_CID_BLUE_BALANCE, 0, 255, 1, def);
- v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual,
- pdev->auto_white_balance->cur.val == awb_auto);
+ v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual, true);
/* autogain, gain */
r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AGC_MODE_FORMATTER, &def);
@@ -331,12 +331,12 @@ int pwc_init_controls(struct pwc_device *pdev)
pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg,
NULL);
if (pdev->restore_user)
- pdev->restore_user->flags = V4L2_CTRL_FLAG_UPDATE;
+ pdev->restore_user->flags |= V4L2_CTRL_FLAG_UPDATE;
pdev->restore_factory = v4l2_ctrl_new_custom(hdl,
&pwc_restore_factory_cfg,
NULL);
if (pdev->restore_factory)
- pdev->restore_factory->flags = V4L2_CTRL_FLAG_UPDATE;
+ pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE;
if (!(pdev->features & FEATURE_MOTOR_PANTILT))
return hdl->error;
@@ -563,8 +563,10 @@ static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case V4L2_CID_AUTO_WHITE_BALANCE:
- if (pdev->color_bal_valid && time_before(jiffies,
- pdev->last_color_bal_update + HZ / 4)) {
+ if (pdev->color_bal_valid &&
+ (pdev->auto_white_balance->val != awb_auto ||
+ time_before(jiffies,
+ pdev->last_color_bal_update + HZ / 4))) {
pdev->red_balance->val = pdev->last_red_balance;
pdev->blue_balance->val = pdev->last_blue_balance;
break;
@@ -630,7 +632,7 @@ leave:
static int pwc_set_awb(struct pwc_device *pdev)
{
- int ret = 0;
+ int ret;
if (pdev->auto_white_balance->is_new) {
ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
@@ -639,52 +641,34 @@ static int pwc_set_awb(struct pwc_device *pdev)
if (ret)
return ret;
- /* Update val when coming from auto or going to a preset */
- if (pdev->red_balance->is_volatile ||
- pdev->auto_white_balance->val == awb_indoor ||
- pdev->auto_white_balance->val == awb_outdoor ||
- pdev->auto_white_balance->val == awb_fl) {
- if (!pdev->red_balance->is_new)
- pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
- READ_RED_GAIN_FORMATTER,
- &pdev->red_balance->val);
- if (!pdev->blue_balance->is_new)
- pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
- READ_BLUE_GAIN_FORMATTER,
- &pdev->blue_balance->val);
- }
- if (pdev->auto_white_balance->val == awb_auto) {
- pdev->red_balance->is_volatile = true;
- pdev->blue_balance->is_volatile = true;
+ if (pdev->auto_white_balance->val != awb_manual)
pdev->color_bal_valid = false; /* Force cache update */
- } else {
- pdev->red_balance->is_volatile = false;
- pdev->blue_balance->is_volatile = false;
- }
}
+ if (pdev->auto_white_balance->val != awb_manual)
+ return 0;
- if (ret == 0 && pdev->red_balance->is_new) {
- if (pdev->auto_white_balance->val != awb_manual)
- return -EBUSY;
+ if (pdev->red_balance->is_new) {
ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
PRESET_MANUAL_RED_GAIN_FORMATTER,
pdev->red_balance->val);
+ if (ret)
+ return ret;
}
- if (ret == 0 && pdev->blue_balance->is_new) {
- if (pdev->auto_white_balance->val != awb_manual)
- return -EBUSY;
+ if (pdev->blue_balance->is_new) {
ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
PRESET_MANUAL_BLUE_GAIN_FORMATTER,
pdev->blue_balance->val);
+ if (ret)
+ return ret;
}
- return ret;
+ return 0;
}
/* For CODEC2 models which have separate autogain and auto exposure */
static int pwc_set_autogain(struct pwc_device *pdev)
{
- int ret = 0;
+ int ret;
if (pdev->autogain->is_new) {
ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
@@ -692,27 +676,28 @@ static int pwc_set_autogain(struct pwc_device *pdev)
pdev->autogain->val ? 0 : 0xff);
if (ret)
return ret;
+
if (pdev->autogain->val)
pdev->gain_valid = false; /* Force cache update */
- else if (!pdev->gain->is_new)
- pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
- READ_AGC_FORMATTER,
- &pdev->gain->val);
}
- if (ret == 0 && pdev->gain->is_new) {
- if (pdev->autogain->val)
- return -EBUSY;
+
+ if (pdev->autogain->val)
+ return 0;
+
+ if (pdev->gain->is_new) {
ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
PRESET_AGC_FORMATTER,
pdev->gain->val);
+ if (ret)
+ return ret;
}
- return ret;
+ return 0;
}
/* For CODEC2 models which have separate autogain and auto exposure */
static int pwc_set_exposure_auto(struct pwc_device *pdev)
{
- int ret = 0;
+ int ret;
int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO;
if (pdev->exposure_auto->is_new) {
@@ -721,27 +706,28 @@ static int pwc_set_exposure_auto(struct pwc_device *pdev)
is_auto ? 0 : 0xff);
if (ret)
return ret;
+
if (is_auto)
pdev->exposure_valid = false; /* Force cache update */
- else if (!pdev->exposure->is_new)
- pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
- READ_SHUTTER_FORMATTER,
- &pdev->exposure->val);
}
- if (ret == 0 && pdev->exposure->is_new) {
- if (is_auto)
- return -EBUSY;
+
+ if (is_auto)
+ return 0;
+
+ if (pdev->exposure->is_new) {
ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
PRESET_SHUTTER_FORMATTER,
pdev->exposure->val);
+ if (ret)
+ return ret;
}
- return ret;
+ return 0;
}
/* For CODEC3 models which have autogain controlling both gain and exposure */
static int pwc_set_autogain_expo(struct pwc_device *pdev)
{
- int ret = 0;
+ int ret;
if (pdev->autogain->is_new) {
ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
@@ -749,35 +735,32 @@ static int pwc_set_autogain_expo(struct pwc_device *pdev)
pdev->autogain->val ? 0 : 0xff);
if (ret)
return ret;
+
if (pdev->autogain->val) {
pdev->gain_valid = false; /* Force cache update */
pdev->exposure_valid = false; /* Force cache update */
- } else {
- if (!pdev->gain->is_new)
- pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
- READ_AGC_FORMATTER,
- &pdev->gain->val);
- if (!pdev->exposure->is_new)
- pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
- READ_SHUTTER_FORMATTER,
- &pdev->exposure->val);
}
}
- if (ret == 0 && pdev->gain->is_new) {
- if (pdev->autogain->val)
- return -EBUSY;
+
+ if (pdev->autogain->val)
+ return 0;
+
+ if (pdev->gain->is_new) {
ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
PRESET_AGC_FORMATTER,
pdev->gain->val);
+ if (ret)
+ return ret;
}
- if (ret == 0 && pdev->exposure->is_new) {
- if (pdev->autogain->val)
- return -EBUSY;
+
+ if (pdev->exposure->is_new) {
ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
PRESET_SHUTTER_FORMATTER,
pdev->exposure->val);
+ if (ret)
+ return ret;
}
- return ret;
+ return 0;
}
static int pwc_set_motor(struct pwc_device *pdev)
@@ -878,10 +861,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
pdev->autocontour->val ? 0 : 0xff);
}
if (ret == 0 && pdev->contour->is_new) {
- if (pdev->autocontour->val) {
- ret = -EBUSY;
- break;
- }
ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
PRESET_CONTOUR_FORMATTER,
pdev->contour->val);
@@ -1099,6 +1078,14 @@ static int pwc_enum_frameintervals(struct file *file, void *fh,
return 0;
}
+static int pwc_log_status(struct file *file, void *priv)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+
+ v4l2_ctrl_handler_log_status(&pdev->ctrl_handler, PWC_NAME);
+ return 0;
+}
+
static long pwc_default(struct file *file, void *fh, bool valid_prio,
int cmd, void *arg)
{
@@ -1122,6 +1109,7 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = {
.vidioc_dqbuf = pwc_dqbuf,
.vidioc_streamon = pwc_streamon,
.vidioc_streamoff = pwc_streamoff,
+ .vidioc_log_status = pwc_log_status,
.vidioc_enum_framesizes = pwc_enum_framesizes,
.vidioc_enum_frameintervals = pwc_enum_frameintervals,
.vidioc_default = pwc_default,
diff --git a/drivers/media/video/s5p-fimc/Makefile b/drivers/media/video/s5p-fimc/Makefile
index df6954ab1d99..33dec7f890e7 100644
--- a/drivers/media/video/s5p-fimc/Makefile
+++ b/drivers/media/video/s5p-fimc/Makefile
@@ -1,4 +1,4 @@
-s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-capture.o
+s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-capture.o fimc-mdevice.o
s5p-csis-objs := mipi-csis.o
obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 0d730e55605d..931f469604b0 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -16,11 +16,9 @@
#include <linux/bug.h>
#include <linux/interrupt.h>
#include <linux/device.h>
-#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/list.h>
#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/v4l2-device.h>
@@ -29,135 +27,88 @@
#include <media/videobuf2-core.h>
#include <media/videobuf2-dma-contig.h>
+#include "fimc-mdevice.h"
#include "fimc-core.h"
-static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
- struct s5p_fimc_isp_info *isp_info)
+static int fimc_init_capture(struct fimc_dev *fimc)
{
- struct i2c_adapter *i2c_adap;
- struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
- struct v4l2_subdev *sd = NULL;
-
- i2c_adap = i2c_get_adapter(isp_info->i2c_bus_num);
- if (!i2c_adap)
- return ERR_PTR(-ENOMEM);
-
- sd = v4l2_i2c_new_subdev_board(&vid_cap->v4l2_dev, i2c_adap,
- isp_info->board_info, NULL);
- if (!sd) {
- v4l2_err(&vid_cap->v4l2_dev, "failed to acquire subdev\n");
- return NULL;
- }
+ struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+ struct fimc_sensor_info *sensor;
+ unsigned long flags;
+ int ret = 0;
- v4l2_info(&vid_cap->v4l2_dev, "subdevice %s registered successfuly\n",
- isp_info->board_info->type);
+ if (fimc->pipeline.sensor == NULL || ctx == NULL)
+ return -ENXIO;
+ if (ctx->s_frame.fmt == NULL)
+ return -EINVAL;
- return sd;
-}
+ sensor = v4l2_get_subdev_hostdata(fimc->pipeline.sensor);
-static void fimc_subdev_unregister(struct fimc_dev *fimc)
-{
- struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
- struct i2c_client *client;
+ spin_lock_irqsave(&fimc->slock, flags);
+ fimc_prepare_dma_offset(ctx, &ctx->d_frame);
+ fimc_set_yuv_order(ctx);
- if (vid_cap->input_index < 0)
- return; /* Subdevice already released or not registered. */
+ fimc_hw_set_camera_polarity(fimc, sensor->pdata);
+ fimc_hw_set_camera_type(fimc, sensor->pdata);
+ fimc_hw_set_camera_source(fimc, sensor->pdata);
+ fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
- if (vid_cap->sd) {
- v4l2_device_unregister_subdev(vid_cap->sd);
- client = v4l2_get_subdevdata(vid_cap->sd);
- i2c_unregister_device(client);
- i2c_put_adapter(client->adapter);
- vid_cap->sd = NULL;
+ ret = fimc_set_scaler_info(ctx);
+ if (!ret) {
+ fimc_hw_set_input_path(ctx);
+ fimc_hw_set_prescaler(ctx);
+ fimc_hw_set_mainscaler(ctx);
+ fimc_hw_set_target_format(ctx);
+ fimc_hw_set_rotation(ctx);
+ fimc_hw_set_effect(ctx, false);
+ fimc_hw_set_output_path(ctx);
+ fimc_hw_set_out_dma(ctx);
+ clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
}
-
- vid_cap->input_index = -1;
+ spin_unlock_irqrestore(&fimc->slock, flags);
+ return ret;
}
-/**
- * fimc_subdev_attach - attach v4l2_subdev to camera host interface
- *
- * @fimc: FIMC device information
- * @index: index to the array of available subdevices,
- * -1 for full array search or non negative value
- * to select specific subdevice
- */
-static int fimc_subdev_attach(struct fimc_dev *fimc, int index)
+static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
{
- struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
- struct s5p_platform_fimc *pdata = fimc->pdata;
- struct s5p_fimc_isp_info *isp_info;
- struct v4l2_subdev *sd;
- int i;
-
- for (i = 0; i < pdata->num_clients; ++i) {
- isp_info = &pdata->isp_info[i];
+ struct fimc_vid_cap *cap = &fimc->vid_cap;
+ struct fimc_vid_buffer *buf;
+ unsigned long flags;
+ bool streaming;
- if (index >= 0 && i != index)
- continue;
+ spin_lock_irqsave(&fimc->slock, flags);
+ streaming = fimc->state & (1 << ST_CAPT_ISP_STREAM);
- sd = fimc_subdev_register(fimc, isp_info);
- if (!IS_ERR_OR_NULL(sd)) {
- vid_cap->sd = sd;
- vid_cap->input_index = i;
+ fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_SHUT |
+ 1 << ST_CAPT_STREAM | 1 << ST_CAPT_ISP_STREAM);
+ if (!suspend)
+ fimc->state &= ~(1 << ST_CAPT_PEND | 1 << ST_CAPT_SUSPENDED);
- return 0;
- }
+ /* Release unused buffers */
+ while (!suspend && !list_empty(&cap->pending_buf_q)) {
+ buf = fimc_pending_queue_pop(cap);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
}
+ /* If suspending put unused buffers onto pending queue */
+ while (!list_empty(&cap->active_buf_q)) {
+ buf = fimc_active_queue_pop(cap);
+ if (suspend)
+ fimc_pending_queue_add(cap, buf);
+ else
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ }
+ set_bit(ST_CAPT_SUSPENDED, &fimc->state);
+ spin_unlock_irqrestore(&fimc->slock, flags);
- vid_cap->input_index = -1;
- vid_cap->sd = NULL;
- v4l2_err(&vid_cap->v4l2_dev, "fimc%d: sensor attach failed\n",
- fimc->id);
- return -ENODEV;
-}
-
-static int fimc_isp_subdev_init(struct fimc_dev *fimc, unsigned int index)
-{
- struct s5p_fimc_isp_info *isp_info;
- struct s5p_platform_fimc *pdata = fimc->pdata;
- int ret;
-
- if (index >= pdata->num_clients)
- return -EINVAL;
-
- isp_info = &pdata->isp_info[index];
-
- if (isp_info->clk_frequency)
- clk_set_rate(fimc->clock[CLK_CAM], isp_info->clk_frequency);
-
- ret = clk_enable(fimc->clock[CLK_CAM]);
- if (ret)
- return ret;
-
- ret = fimc_subdev_attach(fimc, index);
- if (ret)
- return ret;
-
- ret = fimc_hw_set_camera_polarity(fimc, isp_info);
- if (ret)
- return ret;
-
- ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 1);
- if (!ret)
- return ret;
-
- /* enabling power failed so unregister subdev */
- fimc_subdev_unregister(fimc);
-
- v4l2_err(&fimc->vid_cap.v4l2_dev, "ISP initialization failed: %d\n",
- ret);
-
- return ret;
+ if (streaming)
+ return fimc_pipeline_s_stream(fimc, 0);
+ else
+ return 0;
}
-static int fimc_stop_capture(struct fimc_dev *fimc)
+static int fimc_stop_capture(struct fimc_dev *fimc, bool suspend)
{
unsigned long flags;
- struct fimc_vid_cap *cap;
- struct fimc_vid_buffer *buf;
-
- cap = &fimc->vid_cap;
if (!fimc_capture_active(fimc))
return 0;
@@ -169,81 +120,73 @@ static int fimc_stop_capture(struct fimc_dev *fimc)
wait_event_timeout(fimc->irq_queue,
!test_bit(ST_CAPT_SHUT, &fimc->state),
- FIMC_SHUTDOWN_TIMEOUT);
-
- v4l2_subdev_call(cap->sd, video, s_stream, 0);
+ (2*HZ/10)); /* 200 ms */
- spin_lock_irqsave(&fimc->slock, flags);
- fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND |
- 1 << ST_CAPT_SHUT | 1 << ST_CAPT_STREAM);
+ return fimc_capture_state_cleanup(fimc, suspend);
+}
- fimc->vid_cap.active_buf_cnt = 0;
+/**
+ * fimc_capture_config_update - apply the camera interface configuration
+ *
+ * To be called from within the interrupt handler with fimc.slock
+ * spinlock held. It updates the camera pixel crop, rotation and
+ * image flip in H/W.
+ */
+int fimc_capture_config_update(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *fimc = ctx->fimc_dev;
+ int ret;
- /* Release buffers that were enqueued in the driver by videobuf2. */
- while (!list_empty(&cap->pending_buf_q)) {
- buf = pending_queue_pop(cap);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
- }
+ if (test_bit(ST_CAPT_APPLY_CFG, &fimc->state))
+ return 0;
- while (!list_empty(&cap->active_buf_q)) {
- buf = active_queue_pop(cap);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ spin_lock(&ctx->slock);
+ fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
+ ret = fimc_set_scaler_info(ctx);
+ if (ret == 0) {
+ fimc_hw_set_prescaler(ctx);
+ fimc_hw_set_mainscaler(ctx);
+ fimc_hw_set_target_format(ctx);
+ fimc_hw_set_rotation(ctx);
+ fimc_prepare_dma_offset(ctx, &ctx->d_frame);
+ fimc_hw_set_out_dma(ctx);
+ set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
}
-
- spin_unlock_irqrestore(&fimc->slock, flags);
-
- dbg("state: 0x%lx", fimc->state);
- return 0;
+ spin_unlock(&ctx->slock);
+ return ret;
}
-static int start_streaming(struct vb2_queue *q)
+static int start_streaming(struct vb2_queue *q, unsigned int count)
{
struct fimc_ctx *ctx = q->drv_priv;
struct fimc_dev *fimc = ctx->fimc_dev;
- struct s5p_fimc_isp_info *isp_info;
+ struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
+ int min_bufs;
int ret;
fimc_hw_reset(fimc);
+ vid_cap->frame_count = 0;
- ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1);
- if (ret && ret != -ENOIOCTLCMD)
- return ret;
-
- ret = fimc_prepare_config(ctx, ctx->state);
+ ret = fimc_init_capture(fimc);
if (ret)
- return ret;
-
- isp_info = &fimc->pdata->isp_info[fimc->vid_cap.input_index];
- fimc_hw_set_camera_type(fimc, isp_info);
- fimc_hw_set_camera_source(fimc, isp_info);
- fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
+ goto error;
- if (ctx->state & FIMC_PARAMS) {
- ret = fimc_set_scaler_info(ctx);
- if (ret) {
- err("Scaler setup error");
- return ret;
- }
- fimc_hw_set_input_path(ctx);
- fimc_hw_set_prescaler(ctx);
- fimc_hw_set_mainscaler(ctx);
- fimc_hw_set_target_format(ctx);
- fimc_hw_set_rotation(ctx);
- fimc_hw_set_effect(ctx);
- }
+ set_bit(ST_CAPT_PEND, &fimc->state);
- fimc_hw_set_output_path(ctx);
- fimc_hw_set_out_dma(ctx);
+ min_bufs = fimc->vid_cap.reqbufs_count > 1 ? 2 : 1;
- INIT_LIST_HEAD(&fimc->vid_cap.pending_buf_q);
- INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
- fimc->vid_cap.active_buf_cnt = 0;
- fimc->vid_cap.frame_count = 0;
- fimc->vid_cap.buf_index = 0;
+ if (vid_cap->active_buf_cnt >= min_bufs &&
+ !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) {
+ fimc_activate_capture(ctx);
- set_bit(ST_CAPT_PEND, &fimc->state);
+ if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
+ fimc_pipeline_s_stream(fimc, 1);
+ }
return 0;
+error:
+ fimc_capture_state_cleanup(fimc, false);
+ return ret;
}
static int stop_streaming(struct vb2_queue *q)
@@ -254,7 +197,46 @@ static int stop_streaming(struct vb2_queue *q)
if (!fimc_capture_active(fimc))
return -EINVAL;
- return fimc_stop_capture(fimc);
+ return fimc_stop_capture(fimc, false);
+}
+
+int fimc_capture_suspend(struct fimc_dev *fimc)
+{
+ bool suspend = fimc_capture_busy(fimc);
+
+ int ret = fimc_stop_capture(fimc, suspend);
+ if (ret)
+ return ret;
+ return fimc_pipeline_shutdown(fimc);
+}
+
+static void buffer_queue(struct vb2_buffer *vb);
+
+int fimc_capture_resume(struct fimc_dev *fimc)
+{
+ struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
+ struct fimc_vid_buffer *buf;
+ int i;
+
+ if (!test_and_clear_bit(ST_CAPT_SUSPENDED, &fimc->state))
+ return 0;
+
+ INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
+ vid_cap->buf_index = 0;
+ fimc_pipeline_initialize(fimc, &fimc->vid_cap.vfd->entity,
+ false);
+ fimc_init_capture(fimc);
+
+ clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
+
+ for (i = 0; i < vid_cap->reqbufs_count; i++) {
+ if (list_empty(&vid_cap->pending_buf_q))
+ break;
+ buf = fimc_pending_queue_pop(vid_cap);
+ buffer_queue(&buf->vb);
+ }
+ return 0;
+
}
static unsigned int get_plane_size(struct fimc_frame *fr, unsigned int plane)
@@ -265,7 +247,7 @@ static unsigned int get_plane_size(struct fimc_frame *fr, unsigned int plane)
}
static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
- unsigned int *num_planes, unsigned long sizes[],
+ unsigned int *num_planes, unsigned int sizes[],
void *allocators[])
{
struct fimc_ctx *ctx = vq->drv_priv;
@@ -289,21 +271,20 @@ static int buffer_prepare(struct vb2_buffer *vb)
{
struct vb2_queue *vq = vb->vb2_queue;
struct fimc_ctx *ctx = vq->drv_priv;
- struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev;
int i;
- if (!ctx->d_frame.fmt || vq->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ if (ctx->d_frame.fmt == NULL)
return -EINVAL;
for (i = 0; i < ctx->d_frame.fmt->memplanes; i++) {
- unsigned long size = get_plane_size(&ctx->d_frame, i);
+ unsigned long size = ctx->d_frame.payload[i];
if (vb2_plane_size(vb, i) < size) {
- v4l2_err(v4l2_dev, "User buffer too small (%ld < %ld)\n",
+ v4l2_err(ctx->fimc_dev->vid_cap.vfd,
+ "User buffer too small (%ld < %ld)\n",
vb2_plane_size(vb, i), size);
return -EINVAL;
}
-
vb2_set_plane_payload(vb, i, size);
}
@@ -312,10 +293,10 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
- struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- struct fimc_dev *fimc = ctx->fimc_dev;
struct fimc_vid_buffer *buf
= container_of(vb, struct fimc_vid_buffer, vb);
+ struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ struct fimc_dev *fimc = ctx->fimc_dev;
struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
unsigned long flags;
int min_bufs;
@@ -323,15 +304,16 @@ static void buffer_queue(struct vb2_buffer *vb)
spin_lock_irqsave(&fimc->slock, flags);
fimc_prepare_addr(ctx, &buf->vb, &ctx->d_frame, &buf->paddr);
- if (!test_bit(ST_CAPT_STREAM, &fimc->state)
- && vid_cap->active_buf_cnt < FIMC_MAX_OUT_BUFS) {
+ if (!test_bit(ST_CAPT_SUSPENDED, &fimc->state) &&
+ !test_bit(ST_CAPT_STREAM, &fimc->state) &&
+ vid_cap->active_buf_cnt < FIMC_MAX_OUT_BUFS) {
/* Setup the buffer directly for processing. */
int buf_id = (vid_cap->reqbufs_count == 1) ? -1 :
vid_cap->buf_index;
fimc_hw_set_output_addr(fimc, &buf->paddr, buf_id);
buf->index = vid_cap->buf_index;
- active_queue_add(vid_cap, buf);
+ fimc_active_queue_add(vid_cap, buf);
if (++vid_cap->buf_index >= FIMC_MAX_OUT_BUFS)
vid_cap->buf_index = 0;
@@ -341,10 +323,17 @@ static void buffer_queue(struct vb2_buffer *vb)
min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1;
- if (vid_cap->active_buf_cnt >= min_bufs &&
- !test_and_set_bit(ST_CAPT_STREAM, &fimc->state))
+
+ if (vb2_is_streaming(&vid_cap->vbq) &&
+ vid_cap->active_buf_cnt >= min_bufs &&
+ !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) {
fimc_activate_capture(ctx);
+ spin_unlock_irqrestore(&fimc->slock, flags);
+ if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
+ fimc_pipeline_s_stream(fimc, 1);
+ return;
+ }
spin_unlock_irqrestore(&fimc->slock, flags);
}
@@ -370,10 +359,40 @@ static struct vb2_ops fimc_capture_qops = {
.stop_streaming = stop_streaming,
};
+/**
+ * fimc_capture_ctrls_create - initialize the control handler
+ * Initialize the capture video node control handler and fill it
+ * with the FIMC controls. Inherit any sensor's controls if the
+ * 'user_subdev_api' flag is false (default behaviour).
+ * This function need to be called with the graph mutex held.
+ */
+int fimc_capture_ctrls_create(struct fimc_dev *fimc)
+{
+ struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
+ int ret;
+
+ if (WARN_ON(vid_cap->ctx == NULL))
+ return -ENXIO;
+ if (vid_cap->ctx->ctrls_rdy)
+ return 0;
+
+ ret = fimc_ctrls_create(vid_cap->ctx);
+ if (ret || vid_cap->user_subdev_api)
+ return ret;
+
+ return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrl_handler,
+ fimc->pipeline.sensor->ctrl_handler);
+}
+
+static int fimc_capture_set_default_format(struct fimc_dev *fimc);
+
static int fimc_capture_open(struct file *file)
{
struct fimc_dev *fimc = video_drvdata(file);
- int ret = 0;
+ int ret = v4l2_fh_open(file);
+
+ if (ret)
+ return ret;
dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
@@ -381,17 +400,27 @@ static int fimc_capture_open(struct file *file)
if (fimc_m2m_active(fimc))
return -EBUSY;
+ set_bit(ST_CAPT_BUSY, &fimc->state);
+ pm_runtime_get_sync(&fimc->pdev->dev);
+
if (++fimc->vid_cap.refcnt == 1) {
- ret = fimc_isp_subdev_init(fimc, 0);
- if (ret) {
+ ret = fimc_pipeline_initialize(fimc,
+ &fimc->vid_cap.vfd->entity, true);
+ if (ret < 0) {
+ dev_err(&fimc->pdev->dev,
+ "Video pipeline initialization failed\n");
+ pm_runtime_put_sync(&fimc->pdev->dev);
fimc->vid_cap.refcnt--;
- return -EIO;
+ v4l2_fh_release(file);
+ clear_bit(ST_CAPT_BUSY, &fimc->state);
+ return ret;
}
- }
-
- file->private_data = fimc->vid_cap.ctx;
+ ret = fimc_capture_ctrls_create(fimc);
- return 0;
+ if (!ret && !fimc->vid_cap.user_subdev_api)
+ ret = fimc_capture_set_default_format(fimc);
+ }
+ return ret;
}
static int fimc_capture_close(struct file *file)
@@ -401,37 +430,36 @@ static int fimc_capture_close(struct file *file)
dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
if (--fimc->vid_cap.refcnt == 0) {
- fimc_stop_capture(fimc);
- vb2_queue_release(&fimc->vid_cap.vbq);
+ clear_bit(ST_CAPT_BUSY, &fimc->state);
+ fimc_stop_capture(fimc, false);
+ fimc_pipeline_shutdown(fimc);
+ clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
+ }
- v4l2_err(&fimc->vid_cap.v4l2_dev, "releasing ISP\n");
+ pm_runtime_put(&fimc->pdev->dev);
- v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
- clk_disable(fimc->clock[CLK_CAM]);
- fimc_subdev_unregister(fimc);
+ if (fimc->vid_cap.refcnt == 0) {
+ vb2_queue_release(&fimc->vid_cap.vbq);
+ fimc_ctrls_delete(fimc->vid_cap.ctx);
}
-
- return 0;
+ return v4l2_fh_release(file);
}
static unsigned int fimc_capture_poll(struct file *file,
struct poll_table_struct *wait)
{
- struct fimc_ctx *ctx = file->private_data;
- struct fimc_dev *fimc = ctx->fimc_dev;
+ struct fimc_dev *fimc = video_drvdata(file);
return vb2_poll(&fimc->vid_cap.vbq, file, wait);
}
static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct fimc_ctx *ctx = file->private_data;
- struct fimc_dev *fimc = ctx->fimc_dev;
+ struct fimc_dev *fimc = video_drvdata(file);
return vb2_mmap(&fimc->vid_cap.vbq, vma);
}
-/* video device file operations */
static const struct v4l2_file_operations fimc_capture_fops = {
.owner = THIS_MODULE,
.open = fimc_capture_open,
@@ -441,263 +469,553 @@ static const struct v4l2_file_operations fimc_capture_fops = {
.mmap = fimc_capture_mmap,
};
+/*
+ * Format and crop negotiation helpers
+ */
+
+static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
+ u32 *width, u32 *height,
+ u32 *code, u32 *fourcc, int pad)
+{
+ bool rotation = ctx->rotation == 90 || ctx->rotation == 270;
+ struct fimc_dev *fimc = ctx->fimc_dev;
+ struct samsung_fimc_variant *var = fimc->variant;
+ struct fimc_pix_limit *pl = var->pix_limit;
+ struct fimc_frame *dst = &ctx->d_frame;
+ u32 depth, min_w, max_w, min_h, align_h = 3;
+ u32 mask = FMT_FLAGS_CAM;
+ struct fimc_fmt *ffmt;
+
+ /* Color conversion from/to JPEG is not supported */
+ if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE &&
+ fimc_fmt_is_jpeg(ctx->s_frame.fmt->color))
+ *code = V4L2_MBUS_FMT_JPEG_1X8;
+
+ if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK)
+ mask |= FMT_FLAGS_M2M;
+
+ ffmt = fimc_find_format(fourcc, code, mask, 0);
+ if (WARN_ON(!ffmt))
+ return NULL;
+ if (code)
+ *code = ffmt->mbus_code;
+ if (fourcc)
+ *fourcc = ffmt->fourcc;
+
+ if (pad == FIMC_SD_PAD_SINK) {
+ max_w = fimc_fmt_is_jpeg(ffmt->color) ?
+ pl->scaler_dis_w : pl->scaler_en_w;
+ /* Apply the camera input interface pixel constraints */
+ v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4,
+ height, max_t(u32, *height, 32),
+ FIMC_CAMIF_MAX_HEIGHT,
+ fimc_fmt_is_jpeg(ffmt->color) ? 3 : 1,
+ 0);
+ return ffmt;
+ }
+ /* Can't scale or crop in transparent (JPEG) transfer mode */
+ if (fimc_fmt_is_jpeg(ffmt->color)) {
+ *width = ctx->s_frame.f_width;
+ *height = ctx->s_frame.f_height;
+ return ffmt;
+ }
+ /* Apply the scaler and the output DMA constraints */
+ max_w = rotation ? pl->out_rot_en_w : pl->out_rot_dis_w;
+ min_w = ctx->state & FIMC_DST_CROP ? dst->width : var->min_out_pixsize;
+ min_h = ctx->state & FIMC_DST_CROP ? dst->height : var->min_out_pixsize;
+ if (fimc->id == 1 && var->pix_hoff)
+ align_h = fimc_fmt_is_rgb(ffmt->color) ? 0 : 1;
+
+ depth = fimc_get_format_depth(ffmt);
+ v4l_bound_align_image(width, min_w, max_w,
+ ffs(var->min_out_pixsize) - 1,
+ height, min_h, FIMC_CAMIF_MAX_HEIGHT,
+ align_h,
+ 64/(ALIGN(depth, 8)));
+
+ dbg("pad%d: code: 0x%x, %dx%d. dst fmt: %dx%d",
+ pad, code ? *code : 0, *width, *height,
+ dst->f_width, dst->f_height);
+
+ return ffmt;
+}
+
+static void fimc_capture_try_crop(struct fimc_ctx *ctx, struct v4l2_rect *r,
+ int pad)
+{
+ bool rotate = ctx->rotation == 90 || ctx->rotation == 270;
+ struct fimc_dev *fimc = ctx->fimc_dev;
+ struct samsung_fimc_variant *var = fimc->variant;
+ struct fimc_pix_limit *pl = var->pix_limit;
+ struct fimc_frame *sink = &ctx->s_frame;
+ u32 max_w, max_h, min_w = 0, min_h = 0, min_sz;
+ u32 align_sz = 0, align_h = 4;
+ u32 max_sc_h, max_sc_v;
+
+ /* In JPEG transparent transfer mode cropping is not supported */
+ if (fimc_fmt_is_jpeg(ctx->d_frame.fmt->color)) {
+ r->width = sink->f_width;
+ r->height = sink->f_height;
+ r->left = r->top = 0;
+ return;
+ }
+ if (pad == FIMC_SD_PAD_SOURCE) {
+ if (ctx->rotation != 90 && ctx->rotation != 270)
+ align_h = 1;
+ max_sc_h = min(SCALER_MAX_HRATIO, 1 << (ffs(sink->width) - 3));
+ max_sc_v = min(SCALER_MAX_VRATIO, 1 << (ffs(sink->height) - 1));
+ min_sz = var->min_out_pixsize;
+ } else {
+ u32 depth = fimc_get_format_depth(sink->fmt);
+ align_sz = 64/ALIGN(depth, 8);
+ min_sz = var->min_inp_pixsize;
+ min_w = min_h = min_sz;
+ max_sc_h = max_sc_v = 1;
+ }
+ /*
+ * For the crop rectangle at source pad the following constraints
+ * must be met:
+ * - it must fit in the sink pad format rectangle (f_width/f_height);
+ * - maximum downscaling ratio is 64;
+ * - maximum crop size depends if the rotator is used or not;
+ * - the sink pad format width/height must be 4 multiple of the
+ * prescaler ratios determined by sink pad size and source pad crop,
+ * the prescaler ratio is returned by fimc_get_scaler_factor().
+ */
+ max_w = min_t(u32,
+ rotate ? pl->out_rot_en_w : pl->out_rot_dis_w,
+ rotate ? sink->f_height : sink->f_width);
+ max_h = min_t(u32, FIMC_CAMIF_MAX_HEIGHT, sink->f_height);
+ if (pad == FIMC_SD_PAD_SOURCE) {
+ min_w = min_t(u32, max_w, sink->f_width / max_sc_h);
+ min_h = min_t(u32, max_h, sink->f_height / max_sc_v);
+ if (rotate) {
+ swap(max_sc_h, max_sc_v);
+ swap(min_w, min_h);
+ }
+ }
+ v4l_bound_align_image(&r->width, min_w, max_w, ffs(min_sz) - 1,
+ &r->height, min_h, max_h, align_h,
+ align_sz);
+ /* Adjust left/top if cropping rectangle is out of bounds */
+ r->left = clamp_t(u32, r->left, 0, sink->f_width - r->width);
+ r->top = clamp_t(u32, r->top, 0, sink->f_height - r->height);
+ r->left = round_down(r->left, var->hor_offs_align);
+
+ dbg("pad%d: (%d,%d)/%dx%d, sink fmt: %dx%d",
+ pad, r->left, r->top, r->width, r->height,
+ sink->f_width, sink->f_height);
+}
+
+/*
+ * The video node ioctl operations
+ */
static int fimc_vidioc_querycap_capture(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct fimc_ctx *ctx = file->private_data;
- struct fimc_dev *fimc = ctx->fimc_dev;
+ struct fimc_dev *fimc = video_drvdata(file);
strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
cap->bus_info[0] = 0;
- cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+ cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
return 0;
}
-/* Synchronize formats of the camera interface input and attached sensor. */
-static int sync_capture_fmt(struct fimc_ctx *ctx)
+static int fimc_cap_enum_fmt_mplane(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ struct fimc_fmt *fmt;
+
+ fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM | FMT_FLAGS_M2M,
+ f->index);
+ if (!fmt)
+ return -EINVAL;
+ strncpy(f->description, fmt->name, sizeof(f->description) - 1);
+ f->pixelformat = fmt->fourcc;
+ if (fmt->fourcc == V4L2_MBUS_FMT_JPEG_1X8)
+ f->flags |= V4L2_FMT_FLAG_COMPRESSED;
+ return 0;
+}
+
+/**
+ * fimc_pipeline_try_format - negotiate and/or set formats at pipeline
+ * elements
+ * @ctx: FIMC capture context
+ * @tfmt: media bus format to try/set on subdevs
+ * @fmt_id: fimc pixel format id corresponding to returned @tfmt (output)
+ * @set: true to set format on subdevs, false to try only
+ */
+static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
+ struct v4l2_mbus_framefmt *tfmt,
+ struct fimc_fmt **fmt_id,
+ bool set)
{
- struct fimc_frame *frame = &ctx->s_frame;
struct fimc_dev *fimc = ctx->fimc_dev;
- struct v4l2_mbus_framefmt *fmt = &fimc->vid_cap.fmt;
- int ret;
+ struct v4l2_subdev *sd = fimc->pipeline.sensor;
+ struct v4l2_subdev *csis = fimc->pipeline.csis;
+ struct v4l2_subdev_format sfmt;
+ struct v4l2_mbus_framefmt *mf = &sfmt.format;
+ struct fimc_fmt *ffmt = NULL;
+ int ret, i = 0;
+
+ if (WARN_ON(!sd || !tfmt))
+ return -EINVAL;
- fmt->width = ctx->d_frame.o_width;
- fmt->height = ctx->d_frame.o_height;
+ memset(&sfmt, 0, sizeof(sfmt));
+ sfmt.format = *tfmt;
+
+ sfmt.which = set ? V4L2_SUBDEV_FORMAT_ACTIVE : V4L2_SUBDEV_FORMAT_TRY;
+ while (1) {
+ ffmt = fimc_find_format(NULL, mf->code != 0 ? &mf->code : NULL,
+ FMT_FLAGS_CAM, i++);
+ if (ffmt == NULL) {
+ /*
+ * Notify user-space if common pixel code for
+ * host and sensor does not exist.
+ */
+ return -EINVAL;
+ }
+ mf->code = tfmt->code = ffmt->mbus_code;
- ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_mbus_fmt, fmt);
- if (ret == -ENOIOCTLCMD) {
- err("s_mbus_fmt failed");
- return ret;
- }
- dbg("w: %d, h: %d, code= %d", fmt->width, fmt->height, fmt->code);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt);
+ if (ret)
+ return ret;
+ if (mf->code != tfmt->code) {
+ mf->code = 0;
+ continue;
+ }
+ if (mf->width != tfmt->width || mf->width != tfmt->width) {
+ u32 fcc = ffmt->fourcc;
+ tfmt->width = mf->width;
+ tfmt->height = mf->height;
+ ffmt = fimc_capture_try_format(ctx,
+ &tfmt->width, &tfmt->height,
+ NULL, &fcc, FIMC_SD_PAD_SOURCE);
+ if (ffmt && ffmt->mbus_code)
+ mf->code = ffmt->mbus_code;
+ if (mf->width != tfmt->width || mf->width != tfmt->width)
+ continue;
+ tfmt->code = mf->code;
+ }
+ if (csis)
+ ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt);
- frame->fmt = find_mbus_format(fmt, FMT_FLAGS_CAM);
- if (!frame->fmt) {
- err("fimc source format not found\n");
- return -EINVAL;
+ if (mf->code == tfmt->code &&
+ mf->width == tfmt->width && mf->width == tfmt->width)
+ break;
}
- frame->f_width = fmt->width;
- frame->f_height = fmt->height;
- frame->width = fmt->width;
- frame->height = fmt->height;
- frame->o_width = fmt->width;
- frame->o_height = fmt->height;
- frame->offs_h = 0;
- frame->offs_v = 0;
+ if (fmt_id && ffmt)
+ *fmt_id = ffmt;
+ *tfmt = *mf;
+ dbg("code: 0x%x, %dx%d, %p", mf->code, mf->width, mf->height, ffmt);
return 0;
}
-static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
+static int fimc_cap_g_fmt_mplane(struct file *file, void *fh,
struct v4l2_format *f)
{
- struct fimc_ctx *ctx = priv;
- struct fimc_dev *fimc = ctx->fimc_dev;
- struct fimc_frame *frame;
- struct v4l2_pix_format_mplane *pix;
- int ret;
- int i;
+ struct fimc_dev *fimc = video_drvdata(file);
+ struct fimc_ctx *ctx = fimc->vid_cap.ctx;
if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
return -EINVAL;
- ret = fimc_vidioc_try_fmt_mplane(file, priv, f);
- if (ret)
- return ret;
-
- if (vb2_is_busy(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
- return -EBUSY;
+ return fimc_fill_format(&ctx->d_frame, f);
+}
- frame = &ctx->d_frame;
+static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+ struct fimc_dev *fimc = video_drvdata(file);
+ struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+ struct v4l2_mbus_framefmt mf;
+ struct fimc_fmt *ffmt = NULL;
- pix = &f->fmt.pix_mp;
- frame->fmt = find_format(f, FMT_FLAGS_M2M | FMT_FLAGS_CAM);
- if (!frame->fmt) {
- err("fimc target format not found\n");
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
return -EINVAL;
+
+ if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+ fimc_capture_try_format(ctx, &pix->width, &pix->height,
+ NULL, &pix->pixelformat,
+ FIMC_SD_PAD_SINK);
+ ctx->s_frame.f_width = pix->width;
+ ctx->s_frame.f_height = pix->height;
}
+ ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height,
+ NULL, &pix->pixelformat,
+ FIMC_SD_PAD_SOURCE);
+ if (!ffmt)
+ return -EINVAL;
- for (i = 0; i < frame->fmt->colplanes; i++) {
- frame->payload[i] =
- (pix->width * pix->height * frame->fmt->depth[i]) >> 3;
+ if (!fimc->vid_cap.user_subdev_api) {
+ mf.width = pix->width;
+ mf.height = pix->height;
+ mf.code = ffmt->mbus_code;
+ fimc_md_graph_lock(fimc);
+ fimc_pipeline_try_format(ctx, &mf, &ffmt, false);
+ fimc_md_graph_unlock(fimc);
+
+ pix->width = mf.width;
+ pix->height = mf.height;
+ if (ffmt)
+ pix->pixelformat = ffmt->fourcc;
}
- /* Output DMA frame pixel size and offsets. */
- frame->f_width = pix->plane_fmt[0].bytesperline * 8
- / frame->fmt->depth[0];
- frame->f_height = pix->height;
- frame->width = pix->width;
- frame->height = pix->height;
- frame->o_width = pix->width;
- frame->o_height = pix->height;
- frame->offs_h = 0;
- frame->offs_v = 0;
+ fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
+ return 0;
+}
- ctx->state |= (FIMC_PARAMS | FIMC_DST_FMT);
+static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, bool jpeg)
+{
+ ctx->scaler.enabled = !jpeg;
+ fimc_ctrls_activate(ctx, !jpeg);
- ret = sync_capture_fmt(ctx);
- return ret;
+ if (jpeg)
+ set_bit(ST_CAPT_JPEG, &ctx->fimc_dev->state);
+ else
+ clear_bit(ST_CAPT_JPEG, &ctx->fimc_dev->state);
}
-static int fimc_cap_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
+static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
{
- struct fimc_ctx *ctx = priv;
- struct s5p_platform_fimc *pldata = ctx->fimc_dev->pdata;
- struct s5p_fimc_isp_info *isp_info;
+ struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+ struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+ struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.mf;
+ struct fimc_frame *ff = &ctx->d_frame;
+ struct fimc_fmt *s_fmt = NULL;
+ int ret, i;
- if (i->index >= pldata->num_clients)
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
return -EINVAL;
+ if (vb2_is_busy(&fimc->vid_cap.vbq))
+ return -EBUSY;
- isp_info = &pldata->isp_info[i->index];
+ /* Pre-configure format at camera interface input, for JPEG only */
+ if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+ fimc_capture_try_format(ctx, &pix->width, &pix->height,
+ NULL, &pix->pixelformat,
+ FIMC_SD_PAD_SINK);
+ ctx->s_frame.f_width = pix->width;
+ ctx->s_frame.f_height = pix->height;
+ }
+ /* Try the format at the scaler and the DMA output */
+ ff->fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height,
+ NULL, &pix->pixelformat,
+ FIMC_SD_PAD_SOURCE);
+ if (!ff->fmt)
+ return -EINVAL;
+ /* Try to match format at the host and the sensor */
+ if (!fimc->vid_cap.user_subdev_api) {
+ mf->code = ff->fmt->mbus_code;
+ mf->width = pix->width;
+ mf->height = pix->height;
+
+ fimc_md_graph_lock(fimc);
+ ret = fimc_pipeline_try_format(ctx, mf, &s_fmt, true);
+ fimc_md_graph_unlock(fimc);
+ if (ret)
+ return ret;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ }
+ fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
+ for (i = 0; i < ff->fmt->colplanes; i++)
+ ff->payload[i] =
+ (pix->width * pix->height * ff->fmt->depth[i]) / 8;
+
+ set_frame_bounds(ff, pix->width, pix->height);
+ /* Reset the composition rectangle if not yet configured */
+ if (!(ctx->state & FIMC_DST_CROP))
+ set_frame_crop(ff, 0, 0, pix->width, pix->height);
+
+ fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ff->fmt->color));
+
+ /* Reset cropping and set format at the camera interface input */
+ if (!fimc->vid_cap.user_subdev_api) {
+ ctx->s_frame.fmt = s_fmt;
+ set_frame_bounds(&ctx->s_frame, pix->width, pix->height);
+ set_frame_crop(&ctx->s_frame, 0, 0, pix->width, pix->height);
+ }
- i->type = V4L2_INPUT_TYPE_CAMERA;
- strncpy(i->name, isp_info->board_info->type, 32);
- return 0;
+ return ret;
}
-static int fimc_cap_s_input(struct file *file, void *priv,
- unsigned int i)
+static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
{
- struct fimc_ctx *ctx = priv;
- struct fimc_dev *fimc = ctx->fimc_dev;
- struct s5p_platform_fimc *pdata = fimc->pdata;
-
- if (fimc_capture_active(ctx->fimc_dev))
- return -EBUSY;
+ struct fimc_dev *fimc = video_drvdata(file);
- if (i >= pdata->num_clients)
- return -EINVAL;
+ return fimc_capture_set_format(fimc, f);
+}
+static int fimc_cap_enum_input(struct file *file, void *priv,
+ struct v4l2_input *i)
+{
+ struct fimc_dev *fimc = video_drvdata(file);
+ struct v4l2_subdev *sd = fimc->pipeline.sensor;
- if (fimc->vid_cap.sd) {
- int ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
- if (ret)
- err("s_power failed: %d", ret);
+ if (i->index != 0)
+ return -EINVAL;
- clk_disable(fimc->clock[CLK_CAM]);
- }
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ if (sd)
+ strlcpy(i->name, sd->name, sizeof(i->name));
+ return 0;
+}
- /* Release the attached sensor subdevice. */
- fimc_subdev_unregister(fimc);
+static int fimc_cap_s_input(struct file *file, void *priv, unsigned int i)
+{
+ return i == 0 ? i : -EINVAL;
+}
- return fimc_isp_subdev_init(fimc, i);
+static int fimc_cap_g_input(struct file *file, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
}
-static int fimc_cap_g_input(struct file *file, void *priv,
- unsigned int *i)
+/**
+ * fimc_pipeline_validate - check for formats inconsistencies
+ * between source and sink pad of each link
+ *
+ * Return 0 if all formats match or -EPIPE otherwise.
+ */
+static int fimc_pipeline_validate(struct fimc_dev *fimc)
{
- struct fimc_ctx *ctx = priv;
- struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
+ struct v4l2_subdev_format sink_fmt, src_fmt;
+ struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
+ struct v4l2_subdev *sd;
+ struct media_pad *pad;
+ int ret;
- *i = cap->input_index;
+ /* Start with the video capture node pad */
+ pad = media_entity_remote_source(&vid_cap->vd_pad);
+ if (pad == NULL)
+ return -EPIPE;
+ /* FIMC.{N} subdevice */
+ sd = media_entity_to_v4l2_subdev(pad->entity);
+
+ while (1) {
+ /* Retrieve format at the sink pad */
+ pad = &sd->entity.pads[0];
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ break;
+ /* Don't call FIMC subdev operation to avoid nested locking */
+ if (sd == fimc->vid_cap.subdev) {
+ struct fimc_frame *ff = &vid_cap->ctx->s_frame;
+ sink_fmt.format.width = ff->f_width;
+ sink_fmt.format.height = ff->f_height;
+ sink_fmt.format.code = ff->fmt ? ff->fmt->mbus_code : 0;
+ } else {
+ sink_fmt.pad = pad->index;
+ sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sink_fmt);
+ if (ret < 0 && ret != -ENOIOCTLCMD)
+ return -EPIPE;
+ }
+ /* Retrieve format at the source pad */
+ pad = media_entity_remote_source(pad);
+ if (pad == NULL ||
+ media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ break;
+
+ sd = media_entity_to_v4l2_subdev(pad->entity);
+ src_fmt.pad = pad->index;
+ src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt);
+ if (ret < 0 && ret != -ENOIOCTLCMD)
+ return -EPIPE;
+
+ if (src_fmt.format.width != sink_fmt.format.width ||
+ src_fmt.format.height != sink_fmt.format.height ||
+ src_fmt.format.code != sink_fmt.format.code)
+ return -EPIPE;
+ }
return 0;
}
static int fimc_cap_streamon(struct file *file, void *priv,
enum v4l2_buf_type type)
{
- struct fimc_ctx *ctx = priv;
- struct fimc_dev *fimc = ctx->fimc_dev;
+ struct fimc_dev *fimc = video_drvdata(file);
+ struct fimc_pipeline *p = &fimc->pipeline;
+ int ret;
- if (fimc_capture_active(fimc) || !fimc->vid_cap.sd)
+ if (fimc_capture_active(fimc))
return -EBUSY;
- if (!(ctx->state & FIMC_DST_FMT)) {
- v4l2_err(&fimc->vid_cap.v4l2_dev, "Format is not set\n");
- return -EINVAL;
- }
+ media_entity_pipeline_start(&p->sensor->entity, p->pipe);
+ if (fimc->vid_cap.user_subdev_api) {
+ ret = fimc_pipeline_validate(fimc);
+ if (ret)
+ return ret;
+ }
return vb2_streamon(&fimc->vid_cap.vbq, type);
}
static int fimc_cap_streamoff(struct file *file, void *priv,
enum v4l2_buf_type type)
{
- struct fimc_ctx *ctx = priv;
- struct fimc_dev *fimc = ctx->fimc_dev;
+ struct fimc_dev *fimc = video_drvdata(file);
+ struct v4l2_subdev *sd = fimc->pipeline.sensor;
+ int ret;
- return vb2_streamoff(&fimc->vid_cap.vbq, type);
+ ret = vb2_streamoff(&fimc->vid_cap.vbq, type);
+ if (ret == 0)
+ media_entity_pipeline_stop(&sd->entity);
+ return ret;
}
static int fimc_cap_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *reqbufs)
{
- struct fimc_ctx *ctx = priv;
- struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
- int ret;
-
+ struct fimc_dev *fimc = video_drvdata(file);
+ int ret = vb2_reqbufs(&fimc->vid_cap.vbq, reqbufs);
- ret = vb2_reqbufs(&cap->vbq, reqbufs);
if (!ret)
- cap->reqbufs_count = reqbufs->count;
-
+ fimc->vid_cap.reqbufs_count = reqbufs->count;
return ret;
}
static int fimc_cap_querybuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
- struct fimc_ctx *ctx = priv;
- struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
+ struct fimc_dev *fimc = video_drvdata(file);
- return vb2_querybuf(&cap->vbq, buf);
+ return vb2_querybuf(&fimc->vid_cap.vbq, buf);
}
static int fimc_cap_qbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
- struct fimc_ctx *ctx = priv;
- struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
- return vb2_qbuf(&cap->vbq, buf);
+ struct fimc_dev *fimc = video_drvdata(file);
+
+ return vb2_qbuf(&fimc->vid_cap.vbq, buf);
}
static int fimc_cap_dqbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
- struct fimc_ctx *ctx = priv;
- return vb2_dqbuf(&ctx->fimc_dev->vid_cap.vbq, buf,
- file->f_flags & O_NONBLOCK);
-}
-
-static int fimc_cap_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct fimc_ctx *ctx = priv;
- int ret = -EINVAL;
+ struct fimc_dev *fimc = video_drvdata(file);
- /* Allow any controls but 90/270 rotation while streaming */
- if (!fimc_capture_active(ctx->fimc_dev) ||
- ctrl->id != V4L2_CID_ROTATE ||
- (ctrl->value != 90 && ctrl->value != 270)) {
- ret = check_ctrl_val(ctx, ctrl);
- if (!ret) {
- ret = fimc_s_ctrl(ctx, ctrl);
- if (!ret)
- ctx->state |= FIMC_PARAMS;
- }
- }
- if (ret == -EINVAL)
- ret = v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
- core, s_ctrl, ctrl);
- return ret;
+ return vb2_dqbuf(&fimc->vid_cap.vbq, buf, file->f_flags & O_NONBLOCK);
}
static int fimc_cap_cropcap(struct file *file, void *fh,
struct v4l2_cropcap *cr)
{
- struct fimc_frame *f;
- struct fimc_ctx *ctx = fh;
+ struct fimc_dev *fimc = video_drvdata(file);
+ struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
return -EINVAL;
- f = &ctx->s_frame;
-
cr->bounds.left = 0;
cr->bounds.top = 0;
cr->bounds.width = f->o_width;
@@ -709,10 +1027,8 @@ static int fimc_cap_cropcap(struct file *file, void *fh,
static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
{
- struct fimc_frame *f;
- struct fimc_ctx *ctx = file->private_data;
-
- f = &ctx->s_frame;
+ struct fimc_dev *fimc = video_drvdata(file);
+ struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
cr->c.left = f->offs_h;
cr->c.top = f->offs_v;
@@ -722,53 +1038,31 @@ static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
return 0;
}
-static int fimc_cap_s_crop(struct file *file, void *fh,
- struct v4l2_crop *cr)
+static int fimc_cap_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
{
- struct fimc_frame *f;
- struct fimc_ctx *ctx = file->private_data;
- struct fimc_dev *fimc = ctx->fimc_dev;
- int ret = -EINVAL;
-
- if (fimc_capture_active(fimc))
- return -EBUSY;
-
- ret = fimc_try_crop(ctx, cr);
- if (ret)
- return ret;
-
- if (!(ctx->state & FIMC_DST_FMT)) {
- v4l2_err(&fimc->vid_cap.v4l2_dev,
- "Capture color format not set\n");
- return -EINVAL; /* TODO: make sure this is the right value */
- }
+ struct fimc_dev *fimc = video_drvdata(file);
+ struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+ struct fimc_frame *ff;
+ unsigned long flags;
- f = &ctx->s_frame;
- /* Check for the pixel scaling ratio when cropping input image. */
- ret = fimc_check_scaler_ratio(cr->c.width, cr->c.height,
- ctx->d_frame.width, ctx->d_frame.height,
- ctx->rotation);
- if (ret) {
- v4l2_err(&fimc->vid_cap.v4l2_dev, "Out of the scaler range\n");
- return ret;
- }
+ fimc_capture_try_crop(ctx, &cr->c, FIMC_SD_PAD_SINK);
+ ff = &ctx->s_frame;
- f->offs_h = cr->c.left;
- f->offs_v = cr->c.top;
- f->width = cr->c.width;
- f->height = cr->c.height;
+ spin_lock_irqsave(&fimc->slock, flags);
+ set_frame_crop(ff, cr->c.left, cr->c.top, cr->c.width, cr->c.height);
+ set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
+ spin_unlock_irqrestore(&fimc->slock, flags);
return 0;
}
-
static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
.vidioc_querycap = fimc_vidioc_querycap_capture,
- .vidioc_enum_fmt_vid_cap_mplane = fimc_vidioc_enum_fmt_mplane,
- .vidioc_try_fmt_vid_cap_mplane = fimc_vidioc_try_fmt_mplane,
+ .vidioc_enum_fmt_vid_cap_mplane = fimc_cap_enum_fmt_mplane,
+ .vidioc_try_fmt_vid_cap_mplane = fimc_cap_try_fmt_mplane,
.vidioc_s_fmt_vid_cap_mplane = fimc_cap_s_fmt_mplane,
- .vidioc_g_fmt_vid_cap_mplane = fimc_vidioc_g_fmt_mplane,
+ .vidioc_g_fmt_vid_cap_mplane = fimc_cap_g_fmt_mplane,
.vidioc_reqbufs = fimc_cap_reqbufs,
.vidioc_querybuf = fimc_cap_querybuf,
@@ -779,10 +1073,6 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
.vidioc_streamon = fimc_cap_streamon,
.vidioc_streamoff = fimc_cap_streamoff,
- .vidioc_queryctrl = fimc_vidioc_queryctrl,
- .vidioc_g_ctrl = fimc_vidioc_g_ctrl,
- .vidioc_s_ctrl = fimc_cap_s_ctrl,
-
.vidioc_g_crop = fimc_cap_g_crop,
.vidioc_s_crop = fimc_cap_s_crop,
.vidioc_cropcap = fimc_cap_cropcap,
@@ -792,17 +1082,328 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
.vidioc_g_input = fimc_cap_g_input,
};
+/* Capture subdev media entity operations */
+static int fimc_link_setup(struct media_entity *entity,
+ const struct media_pad *local,
+ const struct media_pad *remote, u32 flags)
+{
+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+ struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+
+ if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ return -EINVAL;
+
+ if (WARN_ON(fimc == NULL))
+ return 0;
+
+ dbg("%s --> %s, flags: 0x%x. input: 0x%x",
+ local->entity->name, remote->entity->name, flags,
+ fimc->vid_cap.input);
+
+ if (flags & MEDIA_LNK_FL_ENABLED) {
+ if (fimc->vid_cap.input != 0)
+ return -EBUSY;
+ fimc->vid_cap.input = sd->grp_id;
+ return 0;
+ }
+
+ fimc->vid_cap.input = 0;
+ return 0;
+}
+
+static const struct media_entity_operations fimc_sd_media_ops = {
+ .link_setup = fimc_link_setup,
+};
+
+/**
+ * fimc_sensor_notify - v4l2_device notification from a sensor subdev
+ * @sd: pointer to a subdev generating the notification
+ * @notification: the notification type, must be S5P_FIMC_TX_END_NOTIFY
+ * @arg: pointer to an u32 type integer that stores the frame payload value
+ *
+ * The End Of Frame notification sent by sensor subdev in its still capture
+ * mode. If there is only a single VSYNC generated by the sensor at the
+ * beginning of a frame transmission, FIMC does not issue the LastIrq
+ * (end of frame) interrupt. And this notification is used to complete the
+ * frame capture and returning a buffer to user-space. Subdev drivers should
+ * call this notification from their last 'End of frame capture' interrupt.
+ */
+void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
+ void *arg)
+{
+ struct fimc_sensor_info *sensor;
+ struct fimc_vid_buffer *buf;
+ struct fimc_md *fmd;
+ struct fimc_dev *fimc;
+ unsigned long flags;
+
+ if (sd == NULL)
+ return;
+
+ sensor = v4l2_get_subdev_hostdata(sd);
+ fmd = entity_to_fimc_mdev(&sd->entity);
+
+ spin_lock_irqsave(&fmd->slock, flags);
+ fimc = sensor ? sensor->host : NULL;
+
+ if (fimc && arg && notification == S5P_FIMC_TX_END_NOTIFY &&
+ test_bit(ST_CAPT_PEND, &fimc->state)) {
+ unsigned long irq_flags;
+ spin_lock_irqsave(&fimc->slock, irq_flags);
+ if (!list_empty(&fimc->vid_cap.active_buf_q)) {
+ buf = list_entry(fimc->vid_cap.active_buf_q.next,
+ struct fimc_vid_buffer, list);
+ vb2_set_plane_payload(&buf->vb, 0, *((u32 *)arg));
+ }
+ fimc_capture_irq_handler(fimc, true);
+ fimc_deactivate_capture(fimc);
+ spin_unlock_irqrestore(&fimc->slock, irq_flags);
+ }
+ spin_unlock_irqrestore(&fmd->slock, flags);
+}
+
+static int fimc_subdev_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct fimc_fmt *fmt;
+
+ fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, code->index);
+ if (!fmt)
+ return -EINVAL;
+ code->code = fmt->mbus_code;
+ return 0;
+}
+
+static int fimc_subdev_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
+{
+ struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+ struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+ struct v4l2_mbus_framefmt *mf;
+ struct fimc_frame *ff;
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+ fmt->format = *mf;
+ return 0;
+ }
+ mf = &fmt->format;
+ mf->colorspace = V4L2_COLORSPACE_JPEG;
+ ff = fmt->pad == FIMC_SD_PAD_SINK ? &ctx->s_frame : &ctx->d_frame;
+
+ mutex_lock(&fimc->lock);
+ /* The pixel code is same on both input and output pad */
+ if (!WARN_ON(ctx->s_frame.fmt == NULL))
+ mf->code = ctx->s_frame.fmt->mbus_code;
+ mf->width = ff->f_width;
+ mf->height = ff->f_height;
+ mutex_unlock(&fimc->lock);
+
+ return 0;
+}
+
+static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
+{
+ struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+ struct v4l2_mbus_framefmt *mf = &fmt->format;
+ struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+ struct fimc_frame *ff;
+ struct fimc_fmt *ffmt;
+
+ dbg("pad%d: code: 0x%x, %dx%d",
+ fmt->pad, mf->code, mf->width, mf->height);
+
+ if (fmt->pad == FIMC_SD_PAD_SOURCE &&
+ vb2_is_busy(&fimc->vid_cap.vbq))
+ return -EBUSY;
+
+ mutex_lock(&fimc->lock);
+ ffmt = fimc_capture_try_format(ctx, &mf->width, &mf->height,
+ &mf->code, NULL, fmt->pad);
+ mutex_unlock(&fimc->lock);
+ mf->colorspace = V4L2_COLORSPACE_JPEG;
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+ mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+ *mf = fmt->format;
+ return 0;
+ }
+ fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color));
+
+ ff = fmt->pad == FIMC_SD_PAD_SINK ?
+ &ctx->s_frame : &ctx->d_frame;
+
+ mutex_lock(&fimc->lock);
+ set_frame_bounds(ff, mf->width, mf->height);
+ ff->fmt = ffmt;
+
+ /* Reset the crop rectangle if required. */
+ if (!(fmt->pad == FIMC_SD_PAD_SOURCE && (ctx->state & FIMC_DST_CROP)))
+ set_frame_crop(ff, 0, 0, mf->width, mf->height);
+
+ if (fmt->pad == FIMC_SD_PAD_SINK)
+ ctx->state &= ~FIMC_DST_CROP;
+ mutex_unlock(&fimc->lock);
+ return 0;
+}
+
+static int fimc_subdev_get_crop(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_crop *crop)
+{
+ struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+ struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+ struct v4l2_rect *r = &crop->rect;
+ struct fimc_frame *ff;
+
+ if (crop->which == V4L2_SUBDEV_FORMAT_TRY) {
+ crop->rect = *v4l2_subdev_get_try_crop(fh, crop->pad);
+ return 0;
+ }
+ ff = crop->pad == FIMC_SD_PAD_SINK ?
+ &ctx->s_frame : &ctx->d_frame;
+
+ mutex_lock(&fimc->lock);
+ r->left = ff->offs_h;
+ r->top = ff->offs_v;
+ r->width = ff->width;
+ r->height = ff->height;
+ mutex_unlock(&fimc->lock);
+
+ dbg("ff:%p, pad%d: l:%d, t:%d, %dx%d, f_w: %d, f_h: %d",
+ ff, crop->pad, r->left, r->top, r->width, r->height,
+ ff->f_width, ff->f_height);
+
+ return 0;
+}
+
+static int fimc_subdev_set_crop(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_crop *crop)
+{
+ struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+ struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+ struct v4l2_rect *r = &crop->rect;
+ struct fimc_frame *ff;
+ unsigned long flags;
+
+ dbg("(%d,%d)/%dx%d", r->left, r->top, r->width, r->height);
+
+ ff = crop->pad == FIMC_SD_PAD_SOURCE ?
+ &ctx->d_frame : &ctx->s_frame;
+
+ mutex_lock(&fimc->lock);
+ fimc_capture_try_crop(ctx, r, crop->pad);
+
+ if (crop->which == V4L2_SUBDEV_FORMAT_TRY) {
+ mutex_lock(&fimc->lock);
+ *v4l2_subdev_get_try_crop(fh, crop->pad) = *r;
+ return 0;
+ }
+ spin_lock_irqsave(&fimc->slock, flags);
+ set_frame_crop(ff, r->left, r->top, r->width, r->height);
+ if (crop->pad == FIMC_SD_PAD_SOURCE)
+ ctx->state |= FIMC_DST_CROP;
+
+ set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
+ spin_unlock_irqrestore(&fimc->slock, flags);
+
+ dbg("pad%d: (%d,%d)/%dx%d", crop->pad, r->left, r->top,
+ r->width, r->height);
+
+ mutex_unlock(&fimc->lock);
+ return 0;
+}
+
+static struct v4l2_subdev_pad_ops fimc_subdev_pad_ops = {
+ .enum_mbus_code = fimc_subdev_enum_mbus_code,
+ .get_fmt = fimc_subdev_get_fmt,
+ .set_fmt = fimc_subdev_set_fmt,
+ .get_crop = fimc_subdev_get_crop,
+ .set_crop = fimc_subdev_set_crop,
+};
+
+static struct v4l2_subdev_ops fimc_subdev_ops = {
+ .pad = &fimc_subdev_pad_ops,
+};
+
+static int fimc_create_capture_subdev(struct fimc_dev *fimc,
+ struct v4l2_device *v4l2_dev)
+{
+ struct v4l2_subdev *sd;
+ int ret;
+
+ sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+ if (!sd)
+ return -ENOMEM;
+
+ v4l2_subdev_init(sd, &fimc_subdev_ops);
+ sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id);
+
+ fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+ fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM,
+ fimc->vid_cap.sd_pads, 0);
+ if (ret)
+ goto me_err;
+ ret = v4l2_device_register_subdev(v4l2_dev, sd);
+ if (ret)
+ goto sd_err;
+
+ fimc->vid_cap.subdev = sd;
+ v4l2_set_subdevdata(sd, fimc);
+ sd->entity.ops = &fimc_sd_media_ops;
+ return 0;
+sd_err:
+ media_entity_cleanup(&sd->entity);
+me_err:
+ kfree(sd);
+ return ret;
+}
+
+static void fimc_destroy_capture_subdev(struct fimc_dev *fimc)
+{
+ struct v4l2_subdev *sd = fimc->vid_cap.subdev;
+
+ if (!sd)
+ return;
+ media_entity_cleanup(&sd->entity);
+ v4l2_device_unregister_subdev(sd);
+ kfree(sd);
+ sd = NULL;
+}
+
+/* Set default format at the sensor and host interface */
+static int fimc_capture_set_default_format(struct fimc_dev *fimc)
+{
+ struct v4l2_format fmt = {
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ .fmt.pix_mp = {
+ .width = 640,
+ .height = 480,
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ .field = V4L2_FIELD_NONE,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+ };
+
+ return fimc_capture_set_format(fimc, &fmt);
+}
+
/* fimc->lock must be already initialized */
-int fimc_register_capture_device(struct fimc_dev *fimc)
+int fimc_register_capture_device(struct fimc_dev *fimc,
+ struct v4l2_device *v4l2_dev)
{
- struct v4l2_device *v4l2_dev = &fimc->vid_cap.v4l2_dev;
struct video_device *vfd;
struct fimc_vid_cap *vid_cap;
struct fimc_ctx *ctx;
- struct v4l2_format f;
- struct fimc_frame *fr;
struct vb2_queue *q;
- int ret;
+ int ret = -ENOMEM;
ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
if (!ctx)
@@ -812,33 +1413,21 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
ctx->in_path = FIMC_CAMERA;
ctx->out_path = FIMC_DMA;
ctx->state = FIMC_CTX_CAP;
-
- /* Default format of the output frames */
- f.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
- fr = &ctx->d_frame;
- fr->fmt = find_format(&f, FMT_FLAGS_M2M);
- fr->width = fr->f_width = fr->o_width = 640;
- fr->height = fr->f_height = fr->o_height = 480;
-
- if (!v4l2_dev->name[0])
- snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
- "%s.capture", dev_name(&fimc->pdev->dev));
-
- ret = v4l2_device_register(NULL, v4l2_dev);
- if (ret)
- goto err_info;
+ ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0);
+ ctx->d_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0);
vfd = video_device_alloc();
if (!vfd) {
v4l2_err(v4l2_dev, "Failed to allocate video device\n");
- goto err_v4l2_reg;
+ goto err_vd_alloc;
}
- snprintf(vfd->name, sizeof(vfd->name), "%s:cap",
+ snprintf(vfd->name, sizeof(vfd->name), "%s.capture",
dev_name(&fimc->pdev->dev));
vfd->fops = &fimc_capture_fops;
vfd->ioctl_ops = &fimc_capture_ioctl_ops;
+ vfd->v4l2_dev = v4l2_dev;
vfd->minor = -1;
vfd->release = video_device_release;
vfd->lock = &fimc->lock;
@@ -849,8 +1438,6 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
vid_cap->active_buf_cnt = 0;
vid_cap->reqbufs_count = 0;
vid_cap->refcnt = 0;
- /* Default color format for image sensor */
- vid_cap->fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
INIT_LIST_HEAD(&vid_cap->pending_buf_q);
INIT_LIST_HEAD(&vid_cap->active_buf_q);
@@ -868,34 +1455,37 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
vb2_queue_init(q);
- ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
- if (ret) {
- v4l2_err(v4l2_dev, "Failed to register video device\n");
- goto err_vd_reg;
- }
-
- v4l2_info(v4l2_dev,
- "FIMC capture driver registered as /dev/video%d\n",
- vfd->num);
+ fimc->vid_cap.vd_pad.flags = MEDIA_PAD_FL_SINK;
+ ret = media_entity_init(&vfd->entity, 1, &fimc->vid_cap.vd_pad, 0);
+ if (ret)
+ goto err_ent;
+ ret = fimc_create_capture_subdev(fimc, v4l2_dev);
+ if (ret)
+ goto err_sd_reg;
+ vfd->ctrl_handler = &ctx->ctrl_handler;
return 0;
-err_vd_reg:
+err_sd_reg:
+ media_entity_cleanup(&vfd->entity);
+err_ent:
video_device_release(vfd);
-err_v4l2_reg:
- v4l2_device_unregister(v4l2_dev);
-err_info:
+err_vd_alloc:
kfree(ctx);
- dev_err(&fimc->pdev->dev, "failed to install\n");
return ret;
}
void fimc_unregister_capture_device(struct fimc_dev *fimc)
{
- struct fimc_vid_cap *capture = &fimc->vid_cap;
-
- if (capture->vfd)
- video_unregister_device(capture->vfd);
+ struct video_device *vfd = fimc->vid_cap.vfd;
- kfree(capture->ctx);
+ if (vfd) {
+ media_entity_cleanup(&vfd->entity);
+ /* Can also be called if video device was
+ not registered */
+ video_unregister_device(vfd);
+ }
+ fimc_destroy_capture_subdev(fimc);
+ kfree(fimc->vid_cap.ctx);
+ fimc->vid_cap.ctx = NULL;
}
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index aa550666cc0b..6c1c9cb55378 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/list.h>
#include <linux/io.h>
#include <linux/slab.h>
@@ -27,9 +28,10 @@
#include <media/videobuf2-dma-contig.h>
#include "fimc-core.h"
+#include "fimc-mdevice.h"
static char *fimc_clocks[MAX_FIMC_CLOCKS] = {
- "sclk_fimc", "fimc", "sclk_cam"
+ "sclk_fimc", "fimc"
};
static struct fimc_fmt fimc_formats[] = {
@@ -157,59 +159,28 @@ static struct fimc_fmt fimc_formats[] = {
.memplanes = 2,
.colplanes = 2,
.flags = FMT_FLAGS_M2M,
- },
-};
-
-static struct v4l2_queryctrl fimc_ctrls[] = {
- {
- .id = V4L2_CID_HFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Horizontal flip",
- .minimum = 0,
- .maximum = 1,
- .default_value = 0,
}, {
- .id = V4L2_CID_VFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Vertical flip",
- .minimum = 0,
- .maximum = 1,
- .default_value = 0,
- }, {
- .id = V4L2_CID_ROTATE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Rotation (CCW)",
- .minimum = 0,
- .maximum = 270,
- .step = 90,
- .default_value = 0,
+ .name = "JPEG encoded data",
+ .fourcc = V4L2_PIX_FMT_JPEG,
+ .color = S5P_FIMC_JPEG,
+ .depth = { 8 },
+ .memplanes = 1,
+ .colplanes = 1,
+ .mbus_code = V4L2_MBUS_FMT_JPEG_1X8,
+ .flags = FMT_FLAGS_CAM,
},
};
-
-static struct v4l2_queryctrl *get_ctrl(int id)
+int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
+ int dw, int dh, int rotation)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(fimc_ctrls); ++i)
- if (id == fimc_ctrls[i].id)
- return &fimc_ctrls[i];
- return NULL;
-}
+ if (rotation == 90 || rotation == 270)
+ swap(dw, dh);
-int fimc_check_scaler_ratio(int sw, int sh, int dw, int dh, int rot)
-{
- int tx, ty;
-
- if (rot == 90 || rot == 270) {
- ty = dw;
- tx = dh;
- } else {
- tx = dw;
- ty = dh;
- }
+ if (!ctx->scaler.enabled)
+ return (sw == dw && sh == dh) ? 0 : -EINVAL;
- if ((sw >= SCALER_MAX_HRATIO * tx) || (sh >= SCALER_MAX_VRATIO * ty))
+ if ((sw >= SCALER_MAX_HRATIO * dw) || (sh >= SCALER_MAX_VRATIO * dh))
return -EINVAL;
return 0;
@@ -235,10 +206,11 @@ static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
int fimc_set_scaler_info(struct fimc_ctx *ctx)
{
+ struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+ struct device *dev = &ctx->fimc_dev->pdev->dev;
struct fimc_scaler *sc = &ctx->scaler;
struct fimc_frame *s_frame = &ctx->s_frame;
struct fimc_frame *d_frame = &ctx->d_frame;
- struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
int tx, ty, sx, sy;
int ret;
@@ -250,15 +222,14 @@ int fimc_set_scaler_info(struct fimc_ctx *ctx)
ty = d_frame->height;
}
if (tx <= 0 || ty <= 0) {
- v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
- "invalid target size: %d x %d", tx, ty);
+ dev_err(dev, "Invalid target size: %dx%d", tx, ty);
return -EINVAL;
}
sx = s_frame->width;
sy = s_frame->height;
if (sx <= 0 || sy <= 0) {
- err("invalid source size: %d x %d", sx, sy);
+ dev_err(dev, "Invalid source size: %dx%d", sx, sy);
return -EINVAL;
}
sc->real_width = sx;
@@ -301,7 +272,6 @@ int fimc_set_scaler_info(struct fimc_ctx *ctx)
static void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state)
{
struct vb2_buffer *src_vb, *dst_vb;
- struct fimc_dev *fimc = ctx->fimc_dev;
if (!ctx || !ctx->m2m_ctx)
return;
@@ -312,54 +282,68 @@ static void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state)
if (src_vb && dst_vb) {
v4l2_m2m_buf_done(src_vb, vb_state);
v4l2_m2m_buf_done(dst_vb, vb_state);
- v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx);
+ v4l2_m2m_job_finish(ctx->fimc_dev->m2m.m2m_dev,
+ ctx->m2m_ctx);
}
}
/* Complete the transaction which has been scheduled for execution. */
-static void fimc_m2m_shutdown(struct fimc_ctx *ctx)
+static int fimc_m2m_shutdown(struct fimc_ctx *ctx)
{
struct fimc_dev *fimc = ctx->fimc_dev;
int ret;
if (!fimc_m2m_pending(fimc))
- return;
+ return 0;
fimc_ctx_state_lock_set(FIMC_CTX_SHUT, ctx);
ret = wait_event_timeout(fimc->irq_queue,
!fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx),
FIMC_SHUTDOWN_TIMEOUT);
- /*
- * In case of a timeout the buffers are not released in the interrupt
- * handler so return them here with the error flag set, if there are
- * any on the queue.
- */
- if (ret == 0)
- fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
+
+ return ret == 0 ? -ETIMEDOUT : ret;
+}
+
+static int start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct fimc_ctx *ctx = q->drv_priv;
+ int ret;
+
+ ret = pm_runtime_get_sync(&ctx->fimc_dev->pdev->dev);
+ return ret > 0 ? 0 : ret;
}
static int stop_streaming(struct vb2_queue *q)
{
struct fimc_ctx *ctx = q->drv_priv;
+ int ret;
- fimc_m2m_shutdown(ctx);
+ ret = fimc_m2m_shutdown(ctx);
+ if (ret == -ETIMEDOUT)
+ fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
+ pm_runtime_put(&ctx->fimc_dev->pdev->dev);
return 0;
}
-static void fimc_capture_irq_handler(struct fimc_dev *fimc)
+void fimc_capture_irq_handler(struct fimc_dev *fimc, bool final)
{
struct fimc_vid_cap *cap = &fimc->vid_cap;
struct fimc_vid_buffer *v_buf;
struct timeval *tv;
struct timespec ts;
+ if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
+ wake_up(&fimc->irq_queue);
+ return;
+ }
+
if (!list_empty(&cap->active_buf_q) &&
- test_bit(ST_CAPT_RUN, &fimc->state)) {
+ test_bit(ST_CAPT_RUN, &fimc->state) && final) {
ktime_get_real_ts(&ts);
- v_buf = active_queue_pop(cap);
+ v_buf = fimc_active_queue_pop(cap);
tv = &v_buf->vb.v4l2_buf.timestamp;
tv->tv_sec = ts.tv_sec;
@@ -369,19 +353,14 @@ static void fimc_capture_irq_handler(struct fimc_dev *fimc)
vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
}
- if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
- wake_up(&fimc->irq_queue);
- return;
- }
-
if (!list_empty(&cap->pending_buf_q)) {
- v_buf = pending_queue_pop(cap);
+ v_buf = fimc_pending_queue_pop(cap);
fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index);
v_buf->index = cap->buf_index;
/* Move the buffer to the capture active queue */
- active_queue_add(cap, v_buf);
+ fimc_active_queue_add(cap, v_buf);
dbg("next frame: %d, done frame: %d",
fimc_hw_get_frame_index(fimc), v_buf->index);
@@ -391,7 +370,8 @@ static void fimc_capture_irq_handler(struct fimc_dev *fimc)
}
if (cap->active_buf_cnt == 0) {
- clear_bit(ST_CAPT_RUN, &fimc->state);
+ if (final)
+ clear_bit(ST_CAPT_RUN, &fimc->state);
if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
cap->buf_index = 0;
@@ -399,11 +379,13 @@ static void fimc_capture_irq_handler(struct fimc_dev *fimc)
set_bit(ST_CAPT_RUN, &fimc->state);
}
+ fimc_capture_config_update(cap->ctx);
+
dbg("frame: %d, active_buf_cnt: %d",
fimc_hw_get_frame_index(fimc), cap->active_buf_cnt);
}
-static irqreturn_t fimc_isr(int irq, void *priv)
+static irqreturn_t fimc_irq_handler(int irq, void *priv)
{
struct fimc_dev *fimc = priv;
struct fimc_vid_cap *cap = &fimc->vid_cap;
@@ -411,9 +393,17 @@ static irqreturn_t fimc_isr(int irq, void *priv)
fimc_hw_clear_irq(fimc);
+ spin_lock(&fimc->slock);
+
if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) {
+ if (test_and_clear_bit(ST_M2M_SUSPENDING, &fimc->state)) {
+ set_bit(ST_M2M_SUSPENDED, &fimc->state);
+ wake_up(&fimc->irq_queue);
+ goto out;
+ }
ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev);
if (ctx != NULL) {
+ spin_unlock(&fimc->slock);
fimc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE);
spin_lock(&ctx->slock);
@@ -423,21 +413,16 @@ static irqreturn_t fimc_isr(int irq, void *priv)
}
spin_unlock(&ctx->slock);
}
-
return IRQ_HANDLED;
- }
-
- spin_lock(&fimc->slock);
-
- if (test_bit(ST_CAPT_PEND, &fimc->state)) {
- fimc_capture_irq_handler(fimc);
-
+ } else if (test_bit(ST_CAPT_PEND, &fimc->state)) {
+ fimc_capture_irq_handler(fimc,
+ !test_bit(ST_CAPT_JPEG, &fimc->state));
if (cap->active_buf_cnt == 1) {
fimc_deactivate_capture(fimc);
clear_bit(ST_CAPT_STREAM, &fimc->state);
}
}
-
+out:
spin_unlock(&fimc->slock);
return IRQ_HANDLED;
}
@@ -457,7 +442,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
dbg("memplanes= %d, colplanes= %d, pix_size= %d",
frame->fmt->memplanes, frame->fmt->colplanes, pix_size);
- paddr->y = vb2_dma_contig_plane_paddr(vb, 0);
+ paddr->y = vb2_dma_contig_plane_dma_addr(vb, 0);
if (frame->fmt->memplanes == 1) {
switch (frame->fmt->colplanes) {
@@ -485,10 +470,10 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
}
} else {
if (frame->fmt->memplanes >= 2)
- paddr->cb = vb2_dma_contig_plane_paddr(vb, 1);
+ paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
if (frame->fmt->memplanes == 3)
- paddr->cr = vb2_dma_contig_plane_paddr(vb, 2);
+ paddr->cr = vb2_dma_contig_plane_dma_addr(vb, 2);
}
dbg("PHYS_ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d",
@@ -498,7 +483,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
}
/* Set order for 1 and 2 plane YCBCR 4:2:2 formats. */
-static void fimc_set_yuv_order(struct fimc_ctx *ctx)
+void fimc_set_yuv_order(struct fimc_ctx *ctx)
{
/* The one only mode supported in SoC. */
ctx->in_order_2p = S5P_FIMC_LSB_CRCB;
@@ -540,7 +525,7 @@ static void fimc_set_yuv_order(struct fimc_ctx *ctx)
dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
}
-static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
+void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
{
struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
u32 i, depth = 0;
@@ -606,9 +591,6 @@ int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
fimc_set_yuv_order(ctx);
}
- /* Input DMA mode is not allowed when the scaler is disabled. */
- ctx->scaler.enabled = 1;
-
if (flags & FIMC_SRC_ADDR) {
vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
ret = fimc_prepare_addr(ctx, vb, s_frame, &s_frame->paddr);
@@ -635,10 +617,10 @@ static void fimc_dma_run(void *priv)
return;
fimc = ctx->fimc_dev;
-
- spin_lock_irqsave(&ctx->slock, flags);
+ spin_lock_irqsave(&fimc->slock, flags);
set_bit(ST_M2M_PEND, &fimc->state);
+ spin_lock(&ctx->slock);
ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR);
ret = fimc_prepare_config(ctx, ctx->state);
if (ret)
@@ -649,8 +631,6 @@ static void fimc_dma_run(void *priv)
ctx->state |= FIMC_PARAMS;
fimc->m2m.ctx = ctx;
}
-
- spin_lock(&fimc->slock);
fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr);
if (ctx->state & FIMC_PARAMS) {
@@ -665,7 +645,7 @@ static void fimc_dma_run(void *priv)
fimc_hw_set_mainscaler(ctx);
fimc_hw_set_target_format(ctx);
fimc_hw_set_rotation(ctx);
- fimc_hw_set_effect(ctx);
+ fimc_hw_set_effect(ctx, false);
}
fimc_hw_set_output_path(ctx);
@@ -680,10 +660,9 @@ static void fimc_dma_run(void *priv)
ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP |
FIMC_SRC_FMT | FIMC_DST_FMT);
fimc_hw_activate_input_dma(fimc, true);
- spin_unlock(&fimc->slock);
-
dma_unlock:
- spin_unlock_irqrestore(&ctx->slock, flags);
+ spin_unlock(&ctx->slock);
+ spin_unlock_irqrestore(&fimc->slock, flags);
}
static void fimc_job_abort(void *priv)
@@ -692,7 +671,7 @@ static void fimc_job_abort(void *priv)
}
static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
- unsigned int *num_planes, unsigned long sizes[],
+ unsigned int *num_planes, unsigned int sizes[],
void *allocators[])
{
struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
@@ -762,146 +741,296 @@ static struct vb2_ops fimc_qops = {
.wait_prepare = fimc_unlock,
.wait_finish = fimc_lock,
.stop_streaming = stop_streaming,
+ .start_streaming = start_streaming,
};
-static int fimc_m2m_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
+/*
+ * V4L2 controls handling
+ */
+#define ctrl_to_ctx(__ctrl) \
+ container_of((__ctrl)->handler, struct fimc_ctx, ctrl_handler)
+
+static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
{
- struct fimc_ctx *ctx = file->private_data;
+ struct fimc_ctx *ctx = ctrl_to_ctx(ctrl);
+ struct fimc_dev *fimc = ctx->fimc_dev;
+ struct samsung_fimc_variant *variant = fimc->variant;
+ unsigned long flags;
+ int ret = 0;
+
+ if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_HFLIP:
+ spin_lock_irqsave(&ctx->slock, flags);
+ ctx->hflip = ctrl->val;
+ break;
+
+ case V4L2_CID_VFLIP:
+ spin_lock_irqsave(&ctx->slock, flags);
+ ctx->vflip = ctrl->val;
+ break;
+
+ case V4L2_CID_ROTATE:
+ if (fimc_capture_pending(fimc) ||
+ fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
+ ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
+ ctx->s_frame.height, ctx->d_frame.width,
+ ctx->d_frame.height, ctrl->val);
+ }
+ if (ret) {
+ v4l2_err(fimc->m2m.vfd, "Out of scaler range\n");
+ return -EINVAL;
+ }
+ if ((ctrl->val == 90 || ctrl->val == 270) &&
+ !variant->has_out_rot)
+ return -EINVAL;
+ spin_lock_irqsave(&ctx->slock, flags);
+ ctx->rotation = ctrl->val;
+ break;
+
+ default:
+ v4l2_err(fimc->v4l2_dev, "Invalid control: 0x%X\n", ctrl->id);
+ return -EINVAL;
+ }
+ ctx->state |= FIMC_PARAMS;
+ set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
+ spin_unlock_irqrestore(&ctx->slock, flags);
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops fimc_ctrl_ops = {
+ .s_ctrl = fimc_s_ctrl,
+};
+
+int fimc_ctrls_create(struct fimc_ctx *ctx)
+{
+ if (ctx->ctrls_rdy)
+ return 0;
+ v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
+
+ ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+ ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
+ V4L2_CID_ROTATE, 0, 270, 90, 0);
+ ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
+
+ return ctx->ctrl_handler.error;
+}
+
+void fimc_ctrls_delete(struct fimc_ctx *ctx)
+{
+ if (ctx->ctrls_rdy) {
+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+ ctx->ctrls_rdy = false;
+ }
+}
+
+void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
+{
+ if (!ctx->ctrls_rdy)
+ return;
+
+ mutex_lock(&ctx->ctrl_handler.lock);
+ v4l2_ctrl_activate(ctx->ctrl_rotate, active);
+ v4l2_ctrl_activate(ctx->ctrl_hflip, active);
+ v4l2_ctrl_activate(ctx->ctrl_vflip, active);
+
+ if (active) {
+ ctx->rotation = ctx->ctrl_rotate->val;
+ ctx->hflip = ctx->ctrl_hflip->val;
+ ctx->vflip = ctx->ctrl_vflip->val;
+ } else {
+ ctx->rotation = 0;
+ ctx->hflip = 0;
+ ctx->vflip = 0;
+ }
+ mutex_unlock(&ctx->ctrl_handler.lock);
+}
+
+/*
+ * V4L2 ioctl handlers
+ */
+static int fimc_m2m_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
struct fimc_dev *fimc = ctx->fimc_dev;
strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
cap->bus_info[0] = 0;
cap->capabilities = V4L2_CAP_STREAMING |
- V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
return 0;
}
-int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
+static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
{
struct fimc_fmt *fmt;
- if (f->index >= ARRAY_SIZE(fimc_formats))
+ fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_M2M, f->index);
+ if (!fmt)
return -EINVAL;
- fmt = &fimc_formats[f->index];
strncpy(f->description, fmt->name, sizeof(f->description) - 1);
f->pixelformat = fmt->fourcc;
-
return 0;
}
-int fimc_vidioc_g_fmt_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
+int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f)
{
- struct fimc_ctx *ctx = priv;
- struct fimc_frame *frame;
- struct v4l2_pix_format_mplane *pixm;
+ struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
int i;
- frame = ctx_get_frame(ctx, f->type);
- if (IS_ERR(frame))
- return PTR_ERR(frame);
-
- pixm = &f->fmt.pix_mp;
-
- pixm->width = frame->width;
- pixm->height = frame->height;
- pixm->field = V4L2_FIELD_NONE;
- pixm->pixelformat = frame->fmt->fourcc;
- pixm->colorspace = V4L2_COLORSPACE_JPEG;
- pixm->num_planes = frame->fmt->memplanes;
+ pixm->width = frame->o_width;
+ pixm->height = frame->o_height;
+ pixm->field = V4L2_FIELD_NONE;
+ pixm->pixelformat = frame->fmt->fourcc;
+ pixm->colorspace = V4L2_COLORSPACE_JPEG;
+ pixm->num_planes = frame->fmt->memplanes;
for (i = 0; i < pixm->num_planes; ++i) {
- int bpl = frame->o_width;
-
+ int bpl = frame->f_width;
if (frame->fmt->colplanes == 1) /* packed formats */
bpl = (bpl * frame->fmt->depth[0]) / 8;
-
pixm->plane_fmt[i].bytesperline = bpl;
-
pixm->plane_fmt[i].sizeimage = (frame->o_width *
frame->o_height * frame->fmt->depth[i]) / 8;
}
-
return 0;
}
-struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask)
+void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f)
{
- struct fimc_fmt *fmt;
- unsigned int i;
+ struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
+
+ frame->f_width = pixm->plane_fmt[0].bytesperline;
+ if (frame->fmt->colplanes == 1)
+ frame->f_width = (frame->f_width * 8) / frame->fmt->depth[0];
+ frame->f_height = pixm->height;
+ frame->width = pixm->width;
+ frame->height = pixm->height;
+ frame->o_width = pixm->width;
+ frame->o_height = pixm->height;
+ frame->offs_h = 0;
+ frame->offs_v = 0;
+}
- for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
- fmt = &fimc_formats[i];
- if (fmt->fourcc == f->fmt.pix_mp.pixelformat &&
- (fmt->flags & mask))
- break;
+/**
+ * fimc_adjust_mplane_format - adjust bytesperline/sizeimage for each plane
+ * @fmt: fimc pixel format description (input)
+ * @width: requested pixel width
+ * @height: requested pixel height
+ * @pix: multi-plane format to adjust
+ */
+void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
+ struct v4l2_pix_format_mplane *pix)
+{
+ u32 bytesperline = 0;
+ int i;
+
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+ pix->field = V4L2_FIELD_NONE;
+ pix->num_planes = fmt->memplanes;
+ pix->height = height;
+ pix->width = width;
+
+ for (i = 0; i < pix->num_planes; ++i) {
+ u32 bpl = pix->plane_fmt[i].bytesperline;
+ u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
+
+ if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
+ bpl = pix->width; /* Planar */
+
+ if (fmt->colplanes == 1 && /* Packed */
+ (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
+ bpl = (pix->width * fmt->depth[0]) / 8;
+
+ if (i == 0) /* Same bytesperline for each plane. */
+ bytesperline = bpl;
+
+ pix->plane_fmt[i].bytesperline = bytesperline;
+ *sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
}
+}
- return (i == ARRAY_SIZE(fimc_formats)) ? NULL : fmt;
+static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
+ struct fimc_frame *frame = ctx_get_frame(ctx, f->type);
+
+ if (IS_ERR(frame))
+ return PTR_ERR(frame);
+
+ return fimc_fill_format(frame, f);
}
-struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
- unsigned int mask)
+/**
+ * fimc_find_format - lookup fimc color format by fourcc or media bus format
+ * @pixelformat: fourcc to match, ignored if null
+ * @mbus_code: media bus code to match, ignored if null
+ * @mask: the color flags to match
+ * @index: offset in the fimc_formats array, ignored if negative
+ */
+struct fimc_fmt *fimc_find_format(u32 *pixelformat, u32 *mbus_code,
+ unsigned int mask, int index)
{
- struct fimc_fmt *fmt;
+ struct fimc_fmt *fmt, *def_fmt = NULL;
unsigned int i;
+ int id = 0;
+
+ if (index >= ARRAY_SIZE(fimc_formats))
+ return NULL;
for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
fmt = &fimc_formats[i];
- if (fmt->mbus_code == f->code && (fmt->flags & mask))
- break;
+ if (!(fmt->flags & mask))
+ continue;
+ if (pixelformat && fmt->fourcc == *pixelformat)
+ return fmt;
+ if (mbus_code && fmt->mbus_code == *mbus_code)
+ return fmt;
+ if (index == id)
+ def_fmt = fmt;
+ id++;
}
-
- return (i == ARRAY_SIZE(fimc_formats)) ? NULL : fmt;
+ return def_fmt;
}
-
-int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
+static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f)
{
- struct fimc_ctx *ctx = priv;
struct fimc_dev *fimc = ctx->fimc_dev;
struct samsung_fimc_variant *variant = fimc->variant;
struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
struct fimc_fmt *fmt;
- u32 max_width, mod_x, mod_y, mask;
- int i, is_output = 0;
-
+ u32 max_w, mod_x, mod_y;
- if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx))
- return -EINVAL;
- is_output = 1;
- } else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (!IS_M2M(f->type))
return -EINVAL;
- }
dbg("w: %d, h: %d", pix->width, pix->height);
- mask = is_output ? FMT_FLAGS_M2M : FMT_FLAGS_M2M | FMT_FLAGS_CAM;
- fmt = find_format(f, mask);
- if (!fmt) {
- v4l2_err(&fimc->m2m.v4l2_dev, "Fourcc format (0x%X) invalid.\n",
- pix->pixelformat);
+ fmt = fimc_find_format(&pix->pixelformat, NULL, FMT_FLAGS_M2M, 0);
+ if (WARN(fmt == NULL, "Pixel format lookup failed"))
return -EINVAL;
- }
if (pix->field == V4L2_FIELD_ANY)
pix->field = V4L2_FIELD_NONE;
- else if (V4L2_FIELD_NONE != pix->field)
+ else if (pix->field != V4L2_FIELD_NONE)
return -EINVAL;
- if (is_output) {
- max_width = variant->pix_limit->scaler_dis_w;
+ if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ max_w = variant->pix_limit->scaler_dis_w;
mod_x = ffs(variant->min_inp_pixsize) - 1;
} else {
- max_width = variant->pix_limit->out_rot_dis_w;
+ max_w = variant->pix_limit->out_rot_dis_w;
mod_x = ffs(variant->min_out_pixsize) - 1;
}
@@ -914,70 +1043,52 @@ int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
else
mod_y = mod_x;
}
+ dbg("mod_x: %d, mod_y: %d, max_w: %d", mod_x, mod_y, max_w);
- dbg("mod_x: %d, mod_y: %d, max_w: %d", mod_x, mod_y, max_width);
-
- v4l_bound_align_image(&pix->width, 16, max_width, mod_x,
+ v4l_bound_align_image(&pix->width, 16, max_w, mod_x,
&pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0);
- pix->num_planes = fmt->memplanes;
- pix->colorspace = V4L2_COLORSPACE_JPEG;
-
-
- for (i = 0; i < pix->num_planes; ++i) {
- u32 bpl = pix->plane_fmt[i].bytesperline;
- u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
-
- if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
- bpl = pix->width; /* Planar */
-
- if (fmt->colplanes == 1 && /* Packed */
- (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
- bpl = (pix->width * fmt->depth[0]) / 8;
-
- if (i == 0) /* Same bytesperline for each plane. */
- mod_x = bpl;
+ fimc_adjust_mplane_format(fmt, pix->width, pix->height, &f->fmt.pix_mp);
+ return 0;
+}
- pix->plane_fmt[i].bytesperline = mod_x;
- *sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
- }
+static int fimc_m2m_try_fmt_mplane(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
- return 0;
+ return fimc_try_fmt_mplane(ctx, f);
}
-static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
+static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
struct v4l2_format *f)
{
- struct fimc_ctx *ctx = priv;
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
struct fimc_dev *fimc = ctx->fimc_dev;
struct vb2_queue *vq;
struct fimc_frame *frame;
struct v4l2_pix_format_mplane *pix;
int i, ret = 0;
- ret = fimc_vidioc_try_fmt_mplane(file, priv, f);
+ ret = fimc_try_fmt_mplane(ctx, f);
if (ret)
return ret;
vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
if (vb2_is_busy(vq)) {
- v4l2_err(&fimc->m2m.v4l2_dev, "queue (%d) busy\n", f->type);
+ v4l2_err(fimc->m2m.vfd, "queue (%d) busy\n", f->type);
return -EBUSY;
}
- if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
frame = &ctx->s_frame;
- } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ else
frame = &ctx->d_frame;
- } else {
- v4l2_err(&fimc->m2m.v4l2_dev,
- "Wrong buffer/video queue type (%d)\n", f->type);
- return -EINVAL;
- }
pix = &f->fmt.pix_mp;
- frame->fmt = find_format(f, FMT_FLAGS_M2M);
+ frame->fmt = fimc_find_format(&pix->pixelformat, NULL,
+ FMT_FLAGS_M2M, 0);
if (!frame->fmt)
return -EINVAL;
@@ -986,15 +1097,9 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
(pix->width * pix->height * frame->fmt->depth[i]) / 8;
}
- frame->f_width = pix->plane_fmt[0].bytesperline * 8 /
- frame->fmt->depth[0];
- frame->f_height = pix->height;
- frame->width = pix->width;
- frame->height = pix->height;
- frame->o_width = pix->width;
- frame->o_height = pix->height;
- frame->offs_h = 0;
- frame->offs_v = 0;
+ fimc_fill_frame(frame, f);
+
+ ctx->scaler.enabled = 1;
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_DST_FMT, ctx);
@@ -1006,39 +1111,42 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
return 0;
}
-static int fimc_m2m_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *reqbufs)
+static int fimc_m2m_reqbufs(struct file *file, void *fh,
+ struct v4l2_requestbuffers *reqbufs)
{
- struct fimc_ctx *ctx = priv;
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
+
return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
}
-static int fimc_m2m_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *buf)
+static int fimc_m2m_querybuf(struct file *file, void *fh,
+ struct v4l2_buffer *buf)
{
- struct fimc_ctx *ctx = priv;
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
+
return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
}
-static int fimc_m2m_qbuf(struct file *file, void *priv,
- struct v4l2_buffer *buf)
+static int fimc_m2m_qbuf(struct file *file, void *fh,
+ struct v4l2_buffer *buf)
{
- struct fimc_ctx *ctx = priv;
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
}
-static int fimc_m2m_dqbuf(struct file *file, void *priv,
- struct v4l2_buffer *buf)
+static int fimc_m2m_dqbuf(struct file *file, void *fh,
+ struct v4l2_buffer *buf)
{
- struct fimc_ctx *ctx = priv;
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
+
return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
}
-static int fimc_m2m_streamon(struct file *file, void *priv,
- enum v4l2_buf_type type)
+static int fimc_m2m_streamon(struct file *file, void *fh,
+ enum v4l2_buf_type type)
{
- struct fimc_ctx *ctx = priv;
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
/* The source and target color format need to be set */
if (V4L2_TYPE_IS_OUTPUT(type)) {
@@ -1051,149 +1159,19 @@ static int fimc_m2m_streamon(struct file *file, void *priv,
return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
}
-static int fimc_m2m_streamoff(struct file *file, void *priv,
+static int fimc_m2m_streamoff(struct file *file, void *fh,
enum v4l2_buf_type type)
{
- struct fimc_ctx *ctx = priv;
- return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
-}
-
-int fimc_vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- struct fimc_ctx *ctx = priv;
- struct v4l2_queryctrl *c;
- int ret = -EINVAL;
-
- c = get_ctrl(qc->id);
- if (c) {
- *qc = *c;
- return 0;
- }
-
- if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx)) {
- return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
- core, queryctrl, qc);
- }
- return ret;
-}
-
-int fimc_vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct fimc_ctx *ctx = priv;
- struct fimc_dev *fimc = ctx->fimc_dev;
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
- switch (ctrl->id) {
- case V4L2_CID_HFLIP:
- ctrl->value = (FLIP_X_AXIS & ctx->flip) ? 1 : 0;
- break;
- case V4L2_CID_VFLIP:
- ctrl->value = (FLIP_Y_AXIS & ctx->flip) ? 1 : 0;
- break;
- case V4L2_CID_ROTATE:
- ctrl->value = ctx->rotation;
- break;
- default:
- if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx)) {
- return v4l2_subdev_call(fimc->vid_cap.sd, core,
- g_ctrl, ctrl);
- } else {
- v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n");
- return -EINVAL;
- }
- }
- dbg("ctrl->value= %d", ctrl->value);
-
- return 0;
-}
-
-int check_ctrl_val(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
-{
- struct v4l2_queryctrl *c;
- c = get_ctrl(ctrl->id);
- if (!c)
- return -EINVAL;
-
- if (ctrl->value < c->minimum || ctrl->value > c->maximum
- || (c->step != 0 && ctrl->value % c->step != 0)) {
- v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
- "Invalid control value\n");
- return -ERANGE;
- }
-
- return 0;
-}
-
-int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
-{
- struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
- struct fimc_dev *fimc = ctx->fimc_dev;
- int ret = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_HFLIP:
- if (ctrl->value)
- ctx->flip |= FLIP_X_AXIS;
- else
- ctx->flip &= ~FLIP_X_AXIS;
- break;
-
- case V4L2_CID_VFLIP:
- if (ctrl->value)
- ctx->flip |= FLIP_Y_AXIS;
- else
- ctx->flip &= ~FLIP_Y_AXIS;
- break;
-
- case V4L2_CID_ROTATE:
- if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
- ret = fimc_check_scaler_ratio(ctx->s_frame.width,
- ctx->s_frame.height, ctx->d_frame.width,
- ctx->d_frame.height, ctrl->value);
- }
-
- if (ret) {
- v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range\n");
- return -EINVAL;
- }
-
- /* Check for the output rotator availability */
- if ((ctrl->value == 90 || ctrl->value == 270) &&
- (ctx->in_path == FIMC_DMA && !variant->has_out_rot))
- return -EINVAL;
- ctx->rotation = ctrl->value;
- break;
-
- default:
- v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n");
- return -EINVAL;
- }
-
- fimc_ctx_state_lock_set(FIMC_PARAMS, ctx);
-
- return 0;
-}
-
-static int fimc_m2m_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct fimc_ctx *ctx = priv;
- int ret = 0;
-
- ret = check_ctrl_val(ctx, ctrl);
- if (ret)
- return ret;
-
- ret = fimc_s_ctrl(ctx, ctrl);
- return 0;
+ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
}
static int fimc_m2m_cropcap(struct file *file, void *fh,
- struct v4l2_cropcap *cr)
+ struct v4l2_cropcap *cr)
{
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
struct fimc_frame *frame;
- struct fimc_ctx *ctx = fh;
frame = ctx_get_frame(ctx, cr->type);
if (IS_ERR(frame))
@@ -1201,8 +1179,8 @@ static int fimc_m2m_cropcap(struct file *file, void *fh,
cr->bounds.left = 0;
cr->bounds.top = 0;
- cr->bounds.width = frame->f_width;
- cr->bounds.height = frame->f_height;
+ cr->bounds.width = frame->o_width;
+ cr->bounds.height = frame->o_height;
cr->defrect = cr->bounds;
return 0;
@@ -1210,8 +1188,8 @@ static int fimc_m2m_cropcap(struct file *file, void *fh,
static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
{
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
struct fimc_frame *frame;
- struct fimc_ctx *ctx = file->private_data;
frame = ctx_get_frame(ctx, cr->type);
if (IS_ERR(frame))
@@ -1225,26 +1203,21 @@ static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
return 0;
}
-int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
+static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
{
struct fimc_dev *fimc = ctx->fimc_dev;
struct fimc_frame *f;
u32 min_size, halign, depth = 0;
- bool is_capture_ctx;
int i;
if (cr->c.top < 0 || cr->c.left < 0) {
- v4l2_err(&fimc->m2m.v4l2_dev,
+ v4l2_err(fimc->m2m.vfd,
"doesn't support negative values for top & left\n");
return -EINVAL;
}
-
- is_capture_ctx = fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx);
-
if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
- f = is_capture_ctx ? &ctx->s_frame : &ctx->d_frame;
- else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
- !is_capture_ctx)
+ f = &ctx->d_frame;
+ else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
f = &ctx->s_frame;
else
return -EINVAL;
@@ -1253,15 +1226,10 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
/* Get pixel alignment constraints. */
- if (is_capture_ctx) {
- min_size = 16;
- halign = 4;
- } else {
- if (fimc->id == 1 && fimc->variant->pix_hoff)
- halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1;
- else
- halign = ffs(min_size) - 1;
- }
+ if (fimc->id == 1 && fimc->variant->pix_hoff)
+ halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1;
+ else
+ halign = ffs(min_size) - 1;
for (i = 0; i < f->fmt->colplanes; i++)
depth += f->fmt->depth[i];
@@ -1278,7 +1246,7 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
cr->c.top = f->o_height - cr->c.height;
cr->c.left = round_down(cr->c.left, min_size);
- cr->c.top = round_down(cr->c.top, is_capture_ctx ? 16 : 8);
+ cr->c.top = round_down(cr->c.top, fimc->variant->hor_offs_align);
dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d",
cr->c.left, cr->c.top, cr->c.width, cr->c.height,
@@ -1289,12 +1257,12 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
{
- struct fimc_ctx *ctx = file->private_data;
+ struct fimc_ctx *ctx = fh_to_ctx(fh);
struct fimc_dev *fimc = ctx->fimc_dev;
struct fimc_frame *f;
int ret;
- ret = fimc_try_crop(ctx, cr);
+ ret = fimc_m2m_try_crop(ctx, cr);
if (ret)
return ret;
@@ -1304,18 +1272,16 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
/* Check to see if scaling ratio is within supported range */
if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- ret = fimc_check_scaler_ratio(cr->c.width, cr->c.height,
- ctx->d_frame.width,
- ctx->d_frame.height,
- ctx->rotation);
+ ret = fimc_check_scaler_ratio(ctx, cr->c.width,
+ cr->c.height, ctx->d_frame.width,
+ ctx->d_frame.height, ctx->rotation);
} else {
- ret = fimc_check_scaler_ratio(ctx->s_frame.width,
- ctx->s_frame.height,
- cr->c.width, cr->c.height,
- ctx->rotation);
+ ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
+ ctx->s_frame.height, cr->c.width,
+ cr->c.height, ctx->rotation);
}
if (ret) {
- v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range\n");
+ v4l2_err(fimc->m2m.vfd, "Out of scaler range\n");
return -EINVAL;
}
}
@@ -1333,14 +1299,14 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
.vidioc_querycap = fimc_m2m_querycap,
- .vidioc_enum_fmt_vid_cap_mplane = fimc_vidioc_enum_fmt_mplane,
- .vidioc_enum_fmt_vid_out_mplane = fimc_vidioc_enum_fmt_mplane,
+ .vidioc_enum_fmt_vid_cap_mplane = fimc_m2m_enum_fmt_mplane,
+ .vidioc_enum_fmt_vid_out_mplane = fimc_m2m_enum_fmt_mplane,
- .vidioc_g_fmt_vid_cap_mplane = fimc_vidioc_g_fmt_mplane,
- .vidioc_g_fmt_vid_out_mplane = fimc_vidioc_g_fmt_mplane,
+ .vidioc_g_fmt_vid_cap_mplane = fimc_m2m_g_fmt_mplane,
+ .vidioc_g_fmt_vid_out_mplane = fimc_m2m_g_fmt_mplane,
- .vidioc_try_fmt_vid_cap_mplane = fimc_vidioc_try_fmt_mplane,
- .vidioc_try_fmt_vid_out_mplane = fimc_vidioc_try_fmt_mplane,
+ .vidioc_try_fmt_vid_cap_mplane = fimc_m2m_try_fmt_mplane,
+ .vidioc_try_fmt_vid_out_mplane = fimc_m2m_try_fmt_mplane,
.vidioc_s_fmt_vid_cap_mplane = fimc_m2m_s_fmt_mplane,
.vidioc_s_fmt_vid_out_mplane = fimc_m2m_s_fmt_mplane,
@@ -1354,10 +1320,6 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
.vidioc_streamon = fimc_m2m_streamon,
.vidioc_streamoff = fimc_m2m_streamoff,
- .vidioc_queryctrl = fimc_vidioc_queryctrl,
- .vidioc_g_ctrl = fimc_vidioc_g_ctrl,
- .vidioc_s_ctrl = fimc_m2m_s_ctrl,
-
.vidioc_g_crop = fimc_m2m_g_crop,
.vidioc_s_crop = fimc_m2m_s_crop,
.vidioc_cropcap = fimc_m2m_cropcap
@@ -1396,7 +1358,8 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
static int fimc_m2m_open(struct file *file)
{
struct fimc_dev *fimc = video_drvdata(file);
- struct fimc_ctx *ctx = NULL;
+ struct fimc_ctx *ctx;
+ int ret;
dbg("pid: %d, state: 0x%lx, refcnt: %d",
task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt);
@@ -1408,19 +1371,24 @@ static int fimc_m2m_open(struct file *file)
if (fimc->vid_cap.refcnt > 0)
return -EBUSY;
- fimc->m2m.refcnt++;
- set_bit(ST_OUTDMA_RUN, &fimc->state);
-
ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
if (!ctx)
return -ENOMEM;
+ v4l2_fh_init(&ctx->fh, fimc->m2m.vfd);
+ ret = fimc_ctrls_create(ctx);
+ if (ret)
+ goto error_fh;
+
+ /* Use separate control handler per file handle */
+ ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+ file->private_data = &ctx->fh;
+ v4l2_fh_add(&ctx->fh);
- file->private_data = ctx;
ctx->fimc_dev = fimc;
/* Default color format */
ctx->s_frame.fmt = &fimc_formats[0];
ctx->d_frame.fmt = &fimc_formats[0];
- /* Setup the device context for mem2mem mode. */
+ /* Setup the device context for memory-to-memory mode */
ctx->state = FIMC_CTX_M2M;
ctx->flags = 0;
ctx->in_path = FIMC_DMA;
@@ -1429,34 +1397,46 @@ static int fimc_m2m_open(struct file *file)
ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init);
if (IS_ERR(ctx->m2m_ctx)) {
- int err = PTR_ERR(ctx->m2m_ctx);
- kfree(ctx);
- return err;
+ ret = PTR_ERR(ctx->m2m_ctx);
+ goto error_c;
}
+ if (fimc->m2m.refcnt++ == 0)
+ set_bit(ST_M2M_RUN, &fimc->state);
return 0;
+
+error_c:
+ fimc_ctrls_delete(ctx);
+error_fh:
+ v4l2_fh_del(&ctx->fh);
+ v4l2_fh_exit(&ctx->fh);
+ kfree(ctx);
+ return ret;
}
static int fimc_m2m_release(struct file *file)
{
- struct fimc_ctx *ctx = file->private_data;
+ struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
struct fimc_dev *fimc = ctx->fimc_dev;
dbg("pid: %d, state: 0x%lx, refcnt= %d",
task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
v4l2_m2m_ctx_release(ctx->m2m_ctx);
- kfree(ctx);
- if (--fimc->m2m.refcnt <= 0)
- clear_bit(ST_OUTDMA_RUN, &fimc->state);
+ fimc_ctrls_delete(ctx);
+ v4l2_fh_del(&ctx->fh);
+ v4l2_fh_exit(&ctx->fh);
+ if (--fimc->m2m.refcnt <= 0)
+ clear_bit(ST_M2M_RUN, &fimc->state);
+ kfree(ctx);
return 0;
}
static unsigned int fimc_m2m_poll(struct file *file,
- struct poll_table_struct *wait)
+ struct poll_table_struct *wait)
{
- struct fimc_ctx *ctx = file->private_data;
+ struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
}
@@ -1464,7 +1444,7 @@ static unsigned int fimc_m2m_poll(struct file *file,
static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct fimc_ctx *ctx = file->private_data;
+ struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
}
@@ -1483,92 +1463,73 @@ static struct v4l2_m2m_ops m2m_ops = {
.job_abort = fimc_job_abort,
};
-static int fimc_register_m2m_device(struct fimc_dev *fimc)
+int fimc_register_m2m_device(struct fimc_dev *fimc,
+ struct v4l2_device *v4l2_dev)
{
struct video_device *vfd;
struct platform_device *pdev;
- struct v4l2_device *v4l2_dev;
int ret = 0;
if (!fimc)
return -ENODEV;
pdev = fimc->pdev;
- v4l2_dev = &fimc->m2m.v4l2_dev;
-
- /* set name if it is empty */
- if (!v4l2_dev->name[0])
- snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
- "%s.m2m", dev_name(&pdev->dev));
-
- ret = v4l2_device_register(&pdev->dev, v4l2_dev);
- if (ret)
- goto err_m2m_r1;
+ fimc->v4l2_dev = v4l2_dev;
vfd = video_device_alloc();
if (!vfd) {
v4l2_err(v4l2_dev, "Failed to allocate video device\n");
- goto err_m2m_r1;
+ return -ENOMEM;
}
vfd->fops = &fimc_m2m_fops;
vfd->ioctl_ops = &fimc_m2m_ioctl_ops;
+ vfd->v4l2_dev = v4l2_dev;
vfd->minor = -1;
vfd->release = video_device_release;
vfd->lock = &fimc->lock;
- snprintf(vfd->name, sizeof(vfd->name), "%s:m2m", dev_name(&pdev->dev));
-
+ snprintf(vfd->name, sizeof(vfd->name), "%s.m2m", dev_name(&pdev->dev));
video_set_drvdata(vfd, fimc);
- platform_set_drvdata(pdev, fimc);
fimc->m2m.vfd = vfd;
fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops);
if (IS_ERR(fimc->m2m.m2m_dev)) {
v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n");
ret = PTR_ERR(fimc->m2m.m2m_dev);
- goto err_m2m_r2;
- }
-
- ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
- if (ret) {
- v4l2_err(v4l2_dev,
- "%s(): failed to register video device\n", __func__);
- goto err_m2m_r3;
+ goto err_init;
}
- v4l2_info(v4l2_dev,
- "FIMC m2m driver registered as /dev/video%d\n", vfd->num);
- return 0;
+ ret = media_entity_init(&vfd->entity, 0, NULL, 0);
+ if (!ret)
+ return 0;
-err_m2m_r3:
v4l2_m2m_release(fimc->m2m.m2m_dev);
-err_m2m_r2:
+err_init:
video_device_release(fimc->m2m.vfd);
-err_m2m_r1:
- v4l2_device_unregister(v4l2_dev);
-
return ret;
}
-static void fimc_unregister_m2m_device(struct fimc_dev *fimc)
+void fimc_unregister_m2m_device(struct fimc_dev *fimc)
{
- if (fimc) {
+ if (!fimc)
+ return;
+
+ if (fimc->m2m.m2m_dev)
v4l2_m2m_release(fimc->m2m.m2m_dev);
+ if (fimc->m2m.vfd) {
+ media_entity_cleanup(&fimc->m2m.vfd->entity);
+ /* Can also be called if video device wasn't registered */
video_unregister_device(fimc->m2m.vfd);
-
- v4l2_device_unregister(&fimc->m2m.v4l2_dev);
}
}
-static void fimc_clk_release(struct fimc_dev *fimc)
+static void fimc_clk_put(struct fimc_dev *fimc)
{
int i;
for (i = 0; i < fimc->num_clocks; i++) {
- if (fimc->clock[i]) {
- clk_disable(fimc->clock[i]);
+ if (fimc->clock[i])
clk_put(fimc->clock[i]);
- }
}
}
@@ -1577,15 +1538,50 @@ static int fimc_clk_get(struct fimc_dev *fimc)
int i;
for (i = 0; i < fimc->num_clocks; i++) {
fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]);
-
- if (!IS_ERR_OR_NULL(fimc->clock[i])) {
- clk_enable(fimc->clock[i]);
+ if (!IS_ERR_OR_NULL(fimc->clock[i]))
continue;
- }
dev_err(&fimc->pdev->dev, "failed to get fimc clock: %s\n",
fimc_clocks[i]);
return -ENXIO;
}
+
+ return 0;
+}
+
+static int fimc_m2m_suspend(struct fimc_dev *fimc)
+{
+ unsigned long flags;
+ int timeout;
+
+ spin_lock_irqsave(&fimc->slock, flags);
+ if (!fimc_m2m_pending(fimc)) {
+ spin_unlock_irqrestore(&fimc->slock, flags);
+ return 0;
+ }
+ clear_bit(ST_M2M_SUSPENDED, &fimc->state);
+ set_bit(ST_M2M_SUSPENDING, &fimc->state);
+ spin_unlock_irqrestore(&fimc->slock, flags);
+
+ timeout = wait_event_timeout(fimc->irq_queue,
+ test_bit(ST_M2M_SUSPENDED, &fimc->state),
+ FIMC_SHUTDOWN_TIMEOUT);
+
+ clear_bit(ST_M2M_SUSPENDING, &fimc->state);
+ return timeout == 0 ? -EAGAIN : 0;
+}
+
+static int fimc_m2m_resume(struct fimc_dev *fimc)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&fimc->slock, flags);
+ /* Clear for full H/W setup in first run after resume */
+ fimc->m2m.ctx = NULL;
+ spin_unlock_irqrestore(&fimc->slock, flags);
+
+ if (test_and_clear_bit(ST_M2M_SUSPENDED, &fimc->state))
+ fimc_m2m_job_finish(fimc->m2m.ctx,
+ VB2_BUF_STATE_ERROR);
return 0;
}
@@ -1596,7 +1592,6 @@ static int fimc_probe(struct platform_device *pdev)
struct samsung_fimc_driverdata *drv_data;
struct s5p_platform_fimc *pdata;
int ret = 0;
- int cap_input_index = -1;
dev_dbg(&pdev->dev, "%s():\n", __func__);
@@ -1614,15 +1609,16 @@ static int fimc_probe(struct platform_device *pdev)
return -ENOMEM;
fimc->id = pdev->id;
+
fimc->variant = drv_data->variant[fimc->id];
fimc->pdev = pdev;
pdata = pdev->dev.platform_data;
fimc->pdata = pdata;
- fimc->state = ST_IDLE;
+
+ set_bit(ST_LPM, &fimc->state);
init_waitqueue_head(&fimc->irq_queue);
spin_lock_init(&fimc->slock);
-
mutex_init(&fimc->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1647,71 +1643,51 @@ static int fimc_probe(struct platform_device *pdev)
goto err_req_region;
}
- fimc->num_clocks = MAX_FIMC_CLOCKS - 1;
-
- /* Check if a video capture node needs to be registered. */
- if (pdata && pdata->num_clients > 0) {
- cap_input_index = 0;
- fimc->num_clocks++;
- }
-
- ret = fimc_clk_get(fimc);
- if (ret)
- goto err_regs_unmap;
- clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);
-
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_err(&pdev->dev, "failed to get IRQ resource\n");
ret = -ENXIO;
- goto err_clk;
+ goto err_regs_unmap;
}
fimc->irq = res->start;
- fimc_hw_reset(fimc);
+ fimc->num_clocks = MAX_FIMC_CLOCKS;
+ ret = fimc_clk_get(fimc);
+ if (ret)
+ goto err_regs_unmap;
+ clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);
+ clk_enable(fimc->clock[CLK_BUS]);
- ret = request_irq(fimc->irq, fimc_isr, 0, pdev->name, fimc);
+ platform_set_drvdata(pdev, fimc);
+
+ ret = request_irq(fimc->irq, fimc_irq_handler, 0, pdev->name, fimc);
if (ret) {
dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
goto err_clk;
}
+ pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0)
+ goto err_irq;
/* Initialize contiguous memory allocator */
- fimc->alloc_ctx = vb2_dma_contig_init_ctx(&fimc->pdev->dev);
+ fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
if (IS_ERR(fimc->alloc_ctx)) {
ret = PTR_ERR(fimc->alloc_ctx);
- goto err_irq;
+ goto err_pm;
}
- ret = fimc_register_m2m_device(fimc);
- if (ret)
- goto err_irq;
-
- /* At least one camera sensor is required to register capture node */
- if (cap_input_index >= 0) {
- ret = fimc_register_capture_device(fimc);
- if (ret)
- goto err_m2m;
- clk_disable(fimc->clock[CLK_CAM]);
- }
- /*
- * Exclude the additional output DMA address registers by masking
- * them out on HW revisions that provide extended capabilites.
- */
- if (fimc->variant->out_buf_count > 4)
- fimc_hw_set_dma_seq(fimc, 0xF);
-
- dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n",
- __func__, fimc->id);
+ dev_dbg(&pdev->dev, "FIMC.%d registered successfully\n", fimc->id);
+ pm_runtime_put(&pdev->dev);
return 0;
-err_m2m:
- fimc_unregister_m2m_device(fimc);
+err_pm:
+ pm_runtime_put(&pdev->dev);
err_irq:
free_irq(fimc->irq, fimc);
err_clk:
- fimc_clk_release(fimc);
+ fimc_clk_put(fimc);
err_regs_unmap:
iounmap(fimc->regs);
err_req_region:
@@ -1719,31 +1695,105 @@ err_req_region:
kfree(fimc->regs_res);
err_info:
kfree(fimc);
+ return ret;
+}
+static int fimc_runtime_resume(struct device *dev)
+{
+ struct fimc_dev *fimc = dev_get_drvdata(dev);
+
+ dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
+
+ /* Enable clocks and perform basic initalization */
+ clk_enable(fimc->clock[CLK_GATE]);
+ fimc_hw_reset(fimc);
+ if (fimc->variant->out_buf_count > 4)
+ fimc_hw_set_dma_seq(fimc, 0xF);
+
+ /* Resume the capture or mem-to-mem device */
+ if (fimc_capture_busy(fimc))
+ return fimc_capture_resume(fimc);
+ else if (fimc_m2m_pending(fimc))
+ return fimc_m2m_resume(fimc);
+ return 0;
+}
+
+static int fimc_runtime_suspend(struct device *dev)
+{
+ struct fimc_dev *fimc = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (fimc_capture_busy(fimc))
+ ret = fimc_capture_suspend(fimc);
+ else
+ ret = fimc_m2m_suspend(fimc);
+ if (!ret)
+ clk_disable(fimc->clock[CLK_GATE]);
+
+ dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
return ret;
}
-static int __devexit fimc_remove(struct platform_device *pdev)
+#ifdef CONFIG_PM_SLEEP
+static int fimc_resume(struct device *dev)
{
- struct fimc_dev *fimc =
- (struct fimc_dev *)platform_get_drvdata(pdev);
+ struct fimc_dev *fimc = dev_get_drvdata(dev);
+ unsigned long flags;
- free_irq(fimc->irq, fimc);
+ dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
+
+ /* Do not resume if the device was idle before system suspend */
+ spin_lock_irqsave(&fimc->slock, flags);
+ if (!test_and_clear_bit(ST_LPM, &fimc->state) ||
+ (!fimc_m2m_active(fimc) && !fimc_capture_busy(fimc))) {
+ spin_unlock_irqrestore(&fimc->slock, flags);
+ return 0;
+ }
fimc_hw_reset(fimc);
+ if (fimc->variant->out_buf_count > 4)
+ fimc_hw_set_dma_seq(fimc, 0xF);
+ spin_unlock_irqrestore(&fimc->slock, flags);
+
+ if (fimc_capture_busy(fimc))
+ return fimc_capture_resume(fimc);
- fimc_unregister_m2m_device(fimc);
- fimc_unregister_capture_device(fimc);
+ return fimc_m2m_resume(fimc);
+}
+
+static int fimc_suspend(struct device *dev)
+{
+ struct fimc_dev *fimc = dev_get_drvdata(dev);
+
+ dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
- fimc_clk_release(fimc);
+ if (test_and_set_bit(ST_LPM, &fimc->state))
+ return 0;
+ if (fimc_capture_busy(fimc))
+ return fimc_capture_suspend(fimc);
+
+ return fimc_m2m_suspend(fimc);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static int __devexit fimc_remove(struct platform_device *pdev)
+{
+ struct fimc_dev *fimc = platform_get_drvdata(pdev);
+
+ pm_runtime_disable(&pdev->dev);
+ fimc_runtime_suspend(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
+ clk_disable(fimc->clock[CLK_BUS]);
+ fimc_clk_put(fimc);
+ free_irq(fimc->irq, fimc);
iounmap(fimc->regs);
release_resource(fimc->regs_res);
kfree(fimc->regs_res);
kfree(fimc);
- dev_info(&pdev->dev, "%s driver unloaded\n", pdev->name);
+ dev_info(&pdev->dev, "driver unloaded\n");
return 0;
}
@@ -1786,6 +1836,7 @@ static struct fimc_pix_limit s5p_pix_limit[4] = {
static struct samsung_fimc_variant fimc0_variant_s5p = {
.has_inp_rot = 1,
.has_out_rot = 1,
+ .has_cam_if = 1,
.min_inp_pixsize = 16,
.min_out_pixsize = 16,
.hor_offs_align = 8,
@@ -1794,6 +1845,7 @@ static struct samsung_fimc_variant fimc0_variant_s5p = {
};
static struct samsung_fimc_variant fimc2_variant_s5p = {
+ .has_cam_if = 1,
.min_inp_pixsize = 16,
.min_out_pixsize = 16,
.hor_offs_align = 8,
@@ -1805,6 +1857,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv210 = {
.pix_hoff = 1,
.has_inp_rot = 1,
.has_out_rot = 1,
+ .has_cam_if = 1,
.min_inp_pixsize = 16,
.min_out_pixsize = 16,
.hor_offs_align = 8,
@@ -1816,6 +1869,7 @@ static struct samsung_fimc_variant fimc1_variant_s5pv210 = {
.pix_hoff = 1,
.has_inp_rot = 1,
.has_out_rot = 1,
+ .has_cam_if = 1,
.has_mainscaler_ext = 1,
.min_inp_pixsize = 16,
.min_out_pixsize = 16,
@@ -1825,6 +1879,7 @@ static struct samsung_fimc_variant fimc1_variant_s5pv210 = {
};
static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
+ .has_cam_if = 1,
.pix_hoff = 1,
.min_inp_pixsize = 16,
.min_out_pixsize = 16,
@@ -1837,22 +1892,24 @@ static struct samsung_fimc_variant fimc0_variant_exynos4 = {
.pix_hoff = 1,
.has_inp_rot = 1,
.has_out_rot = 1,
+ .has_cam_if = 1,
.has_cistatus2 = 1,
.has_mainscaler_ext = 1,
.min_inp_pixsize = 16,
.min_out_pixsize = 16,
- .hor_offs_align = 1,
+ .hor_offs_align = 2,
.out_buf_count = 32,
.pix_limit = &s5p_pix_limit[1],
};
-static struct samsung_fimc_variant fimc2_variant_exynos4 = {
+static struct samsung_fimc_variant fimc3_variant_exynos4 = {
.pix_hoff = 1,
+ .has_cam_if = 1,
.has_cistatus2 = 1,
.has_mainscaler_ext = 1,
.min_inp_pixsize = 16,
.min_out_pixsize = 16,
- .hor_offs_align = 1,
+ .hor_offs_align = 2,
.out_buf_count = 32,
.pix_limit = &s5p_pix_limit[3],
};
@@ -1885,7 +1942,7 @@ static struct samsung_fimc_driverdata fimc_drvdata_exynos4 = {
[0] = &fimc0_variant_exynos4,
[1] = &fimc0_variant_exynos4,
[2] = &fimc0_variant_exynos4,
- [3] = &fimc2_variant_exynos4,
+ [3] = &fimc3_variant_exynos4,
},
.num_entities = 4,
.lclk_frequency = 166000000UL,
@@ -1906,33 +1963,28 @@ static struct platform_device_id fimc_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
+static const struct dev_pm_ops fimc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
+ SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
+};
+
static struct platform_driver fimc_driver = {
.probe = fimc_probe,
- .remove = __devexit_p(fimc_remove),
+ .remove = __devexit_p(fimc_remove),
.id_table = fimc_driver_ids,
.driver = {
- .name = MODULE_NAME,
+ .name = FIMC_MODULE_NAME,
.owner = THIS_MODULE,
+ .pm = &fimc_pm_ops,
}
};
-static int __init fimc_init(void)
+int __init fimc_register_driver(void)
{
- int ret = platform_driver_register(&fimc_driver);
- if (ret)
- err("platform_driver_register failed: %d\n", ret);
- return ret;
+ return platform_driver_probe(&fimc_driver, fimc_probe);
}
-static void __exit fimc_exit(void)
+void __exit fimc_unregister_driver(void)
{
platform_driver_unregister(&fimc_driver);
}
-
-module_init(fimc_init);
-module_exit(fimc_exit);
-
-MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
-MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.1");
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 1f70772daaf0..a6936dad5b10 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -11,12 +11,16 @@
/*#define DEBUG*/
+#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include <linux/io.h>
+
+#include <media/media-entity.h>
#include <media/videobuf2-core.h>
+#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-mediabus.h>
@@ -32,38 +36,46 @@
/* Time to wait for next frame VSYNC interrupt while stopping operation. */
#define FIMC_SHUTDOWN_TIMEOUT ((100*HZ)/1000)
-#define MAX_FIMC_CLOCKS 3
-#define MODULE_NAME "s5p-fimc"
+#define MAX_FIMC_CLOCKS 2
+#define FIMC_MODULE_NAME "s5p-fimc"
#define FIMC_MAX_DEVS 4
#define FIMC_MAX_OUT_BUFS 4
#define SCALER_MAX_HRATIO 64
#define SCALER_MAX_VRATIO 64
#define DMA_MIN_SIZE 8
+#define FIMC_CAMIF_MAX_HEIGHT 0x2000
/* indices to the clocks array */
enum {
CLK_BUS,
CLK_GATE,
- CLK_CAM,
};
enum fimc_dev_flags {
- /* for m2m node */
- ST_IDLE,
- ST_OUTDMA_RUN,
+ ST_LPM,
+ /* m2m node */
+ ST_M2M_RUN,
ST_M2M_PEND,
- /* for capture node */
+ ST_M2M_SUSPENDING,
+ ST_M2M_SUSPENDED,
+ /* capture node */
ST_CAPT_PEND,
ST_CAPT_RUN,
ST_CAPT_STREAM,
+ ST_CAPT_ISP_STREAM,
+ ST_CAPT_SUSPENDED,
ST_CAPT_SHUT,
+ ST_CAPT_BUSY,
+ ST_CAPT_APPLY_CFG,
+ ST_CAPT_JPEG,
};
-#define fimc_m2m_active(dev) test_bit(ST_OUTDMA_RUN, &(dev)->state)
+#define fimc_m2m_active(dev) test_bit(ST_M2M_RUN, &(dev)->state)
#define fimc_m2m_pending(dev) test_bit(ST_M2M_PEND, &(dev)->state)
#define fimc_capture_running(dev) test_bit(ST_CAPT_RUN, &(dev)->state)
#define fimc_capture_pending(dev) test_bit(ST_CAPT_PEND, &(dev)->state)
+#define fimc_capture_busy(dev) test_bit(ST_CAPT_BUSY, &(dev)->state)
enum fimc_datapath {
FIMC_CAMERA,
@@ -83,9 +95,14 @@ enum fimc_color_fmt {
S5P_FIMC_CBYCRY422,
S5P_FIMC_CRYCBY422,
S5P_FIMC_YCBCR444_LOCAL,
+ S5P_FIMC_JPEG = 0x40,
};
-#define fimc_fmt_is_rgb(x) ((x) & 0x10)
+#define fimc_fmt_is_rgb(x) (!!((x) & 0x10))
+#define fimc_fmt_is_jpeg(x) (!!((x) & 0x40))
+
+#define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \
+ __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
/* Cb/Cr chrominance components order for 2 plane Y/CbCr 4:2:2 formats. */
#define S5P_FIMC_LSB_CRCB S5P_CIOCTRL_ORDER422_2P_LSB_CRCB
@@ -104,9 +121,10 @@ enum fimc_color_fmt {
#define FIMC_DST_ADDR (1 << 2)
#define FIMC_SRC_FMT (1 << 3)
#define FIMC_DST_FMT (1 << 4)
-#define FIMC_CTX_M2M (1 << 5)
-#define FIMC_CTX_CAP (1 << 6)
-#define FIMC_CTX_SHUT (1 << 7)
+#define FIMC_DST_CROP (1 << 5)
+#define FIMC_CTX_M2M (1 << 16)
+#define FIMC_CTX_CAP (1 << 17)
+#define FIMC_CTX_SHUT (1 << 18)
/* Image conversion flags */
#define FIMC_IN_DMA_ACCESS_TILED (1 << 0)
@@ -122,11 +140,6 @@ enum fimc_color_fmt {
/* Y (16 ~ 235), Cb/Cr (16 ~ 240) */
#define FIMC_COLOR_RANGE_NARROW (1 << 3)
-#define FLIP_NONE 0
-#define FLIP_X_AXIS 1
-#define FLIP_Y_AXIS 2
-#define FLIP_XY_AXIS (FLIP_X_AXIS | FLIP_Y_AXIS)
-
/**
* struct fimc_fmt - the driver's internal color format data
* @mbus_code: Media Bus pixel code, -1 if not applicable
@@ -275,26 +288,29 @@ struct fimc_frame {
/**
* struct fimc_m2m_device - v4l2 memory-to-memory device data
* @vfd: the video device node for v4l2 m2m mode
- * @v4l2_dev: v4l2 device for m2m mode
* @m2m_dev: v4l2 memory-to-memory device data
* @ctx: hardware context data
* @refcnt: the reference counter
*/
struct fimc_m2m_device {
struct video_device *vfd;
- struct v4l2_device v4l2_dev;
struct v4l2_m2m_dev *m2m_dev;
struct fimc_ctx *ctx;
int refcnt;
};
+#define FIMC_SD_PAD_SINK 0
+#define FIMC_SD_PAD_SOURCE 1
+#define FIMC_SD_PADS_NUM 2
+
/**
* struct fimc_vid_cap - camera capture device information
* @ctx: hardware context data
* @vfd: video device node for camera capture mode
- * @v4l2_dev: v4l2_device struct to manage subdevs
- * @sd: pointer to camera sensor subdevice currently in use
- * @fmt: Media Bus format configured at selected image sensor
+ * @subdev: subdev exposing the FIMC processing block
+ * @vd_pad: fimc video capture node pad
+ * @sd_pads: fimc video processing block pads
+ * @mf: media bus format at the FIMC camera input (and the scaler output) pad
* @pending_buf_q: the pending buffer queue head
* @active_buf_q: the queue head of buffers scheduled in hardware
* @vbq: the capture am video buffer queue
@@ -304,14 +320,17 @@ struct fimc_m2m_device {
* @reqbufs_count: the number of buffers requested in REQBUFS ioctl
* @input_index: input (camera sensor) index
* @refcnt: driver's private reference counter
+ * @input: capture input type, grp_id of the attached subdev
+ * @user_subdev_api: true if subdevs are not configured by the host driver
*/
struct fimc_vid_cap {
struct fimc_ctx *ctx;
struct vb2_alloc_ctx *alloc_ctx;
struct video_device *vfd;
- struct v4l2_device v4l2_dev;
- struct v4l2_subdev *sd;;
- struct v4l2_mbus_framefmt fmt;
+ struct v4l2_subdev *subdev;
+ struct media_pad vd_pad;
+ struct v4l2_mbus_framefmt mf;
+ struct media_pad sd_pads[FIMC_SD_PADS_NUM];
struct list_head pending_buf_q;
struct list_head active_buf_q;
struct vb2_queue vbq;
@@ -321,6 +340,8 @@ struct fimc_vid_cap {
unsigned int reqbufs_count;
int input_index;
int refcnt;
+ u32 input;
+ bool user_subdev_api;
};
/**
@@ -351,6 +372,7 @@ struct fimc_pix_limit {
* @has_cistatus2: 1 if CISTATUS2 register is present in this IP revision
* @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register
* are present in this IP revision
+ * @has_cam_if: set if this instance has a camera input interface
* @pix_limit: pixel size constraints for the scaler
* @min_inp_pixsize: minimum input pixel size
* @min_out_pixsize: minimum output pixel size
@@ -363,6 +385,7 @@ struct samsung_fimc_variant {
unsigned int has_out_rot:1;
unsigned int has_cistatus2:1;
unsigned int has_mainscaler_ext:1;
+ unsigned int has_cam_if:1;
struct fimc_pix_limit *pix_limit;
u16 min_inp_pixsize;
u16 min_out_pixsize;
@@ -383,6 +406,12 @@ struct samsung_fimc_driverdata {
int num_entities;
};
+struct fimc_pipeline {
+ struct media_pipeline *pipe;
+ struct v4l2_subdev *sensor;
+ struct v4l2_subdev *csis;
+};
+
struct fimc_ctx;
/**
@@ -399,10 +428,12 @@ struct fimc_ctx;
* @regs_res: the resource claimed for IO registers
* @irq: FIMC interrupt number
* @irq_queue: interrupt handler waitqueue
+ * @v4l2_dev: root v4l2_device
* @m2m: memory-to-memory V4L2 device information
* @vid_cap: camera capture device information
* @state: flags used to synchronize m2m and capture mode operation
* @alloc_ctx: videobuf2 memory allocator context
+ * @pipeline: fimc video capture pipeline data structure
*/
struct fimc_dev {
spinlock_t slock;
@@ -417,10 +448,12 @@ struct fimc_dev {
struct resource *regs_res;
int irq;
wait_queue_head_t irq_queue;
+ struct v4l2_device *v4l2_dev;
struct fimc_m2m_device m2m;
struct fimc_vid_cap vid_cap;
unsigned long state;
struct vb2_alloc_ctx *alloc_ctx;
+ struct fimc_pipeline pipeline;
};
/**
@@ -437,11 +470,18 @@ struct fimc_dev {
* @scaler: image scaler properties
* @effect: image effect
* @rotation: image clockwise rotation in degrees
- * @flip: image flip mode
+ * @hflip: indicates image horizontal flip if set
+ * @vflip: indicates image vertical flip if set
* @flags: additional flags for image conversion
* @state: flags to keep track of user configuration
* @fimc_dev: the FIMC device this context applies to
* @m2m_ctx: memory-to-memory device context
+ * @fh: v4l2 file handle
+ * @ctrl_handler: v4l2 controls handler
+ * @ctrl_rotate image rotation control
+ * @ctrl_hflip horizontal flip control
+ * @ctrl_vflip vartical flip control
+ * @ctrls_rdy: true if the control handler is initialized
*/
struct fimc_ctx {
spinlock_t slock;
@@ -456,13 +496,49 @@ struct fimc_ctx {
struct fimc_scaler scaler;
struct fimc_effect effect;
int rotation;
- u32 flip;
+ unsigned int hflip:1;
+ unsigned int vflip:1;
u32 flags;
u32 state;
struct fimc_dev *fimc_dev;
struct v4l2_m2m_ctx *m2m_ctx;
+ struct v4l2_fh fh;
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *ctrl_rotate;
+ struct v4l2_ctrl *ctrl_hflip;
+ struct v4l2_ctrl *ctrl_vflip;
+ bool ctrls_rdy;
};
+#define fh_to_ctx(__fh) container_of(__fh, struct fimc_ctx, fh)
+
+static inline void set_frame_bounds(struct fimc_frame *f, u32 width, u32 height)
+{
+ f->o_width = width;
+ f->o_height = height;
+ f->f_width = width;
+ f->f_height = height;
+}
+
+static inline void set_frame_crop(struct fimc_frame *f,
+ u32 left, u32 top, u32 width, u32 height)
+{
+ f->offs_h = left;
+ f->offs_v = top;
+ f->width = width;
+ f->height = height;
+}
+
+static inline u32 fimc_get_format_depth(struct fimc_fmt *ff)
+{
+ u32 i, depth = 0;
+
+ if (ff != NULL)
+ for (i = 0; i < ff->colplanes; i++)
+ depth += ff->depth[i];
+ return depth;
+}
+
static inline bool fimc_capture_active(struct fimc_dev *fimc)
{
unsigned long flags;
@@ -561,7 +637,7 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
} else if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == type) {
frame = &ctx->d_frame;
} else {
- v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
+ v4l2_err(ctx->fimc_dev->v4l2_dev,
"Wrong buffer/video queue type (%d)\n", type);
return ERR_PTR(-EINVAL);
}
@@ -595,7 +671,7 @@ void fimc_hw_en_irq(struct fimc_dev *fimc, int enable);
void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
void fimc_hw_set_mainscaler(struct fimc_ctx *ctx);
void fimc_hw_en_capture(struct fimc_ctx *ctx);
-void fimc_hw_set_effect(struct fimc_ctx *ctx);
+void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active);
void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
void fimc_hw_set_input_path(struct fimc_ctx *ctx);
void fimc_hw_set_output_path(struct fimc_ctx *ctx);
@@ -614,36 +690,45 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
/* fimc-core.c */
int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
struct v4l2_fmtdesc *f);
-int fimc_vidioc_g_fmt_mplane(struct file *file, void *priv,
- struct v4l2_format *f);
-int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
- struct v4l2_format *f);
-int fimc_vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc);
-int fimc_vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl);
-
-int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr);
-int check_ctrl_val(struct fimc_ctx *ctx, struct v4l2_control *ctrl);
-int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl);
-
-struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask);
-struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
- unsigned int mask);
-
-int fimc_check_scaler_ratio(int sw, int sh, int dw, int dh, int rot);
+int fimc_ctrls_create(struct fimc_ctx *ctx);
+void fimc_ctrls_delete(struct fimc_ctx *ctx);
+void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active);
+int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f);
+void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
+ struct v4l2_pix_format_mplane *pix);
+struct fimc_fmt *fimc_find_format(u32 *pixelformat, u32 *mbus_code,
+ unsigned int mask, int index);
+
+int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
+ int dw, int dh, int rotation);
int fimc_set_scaler_info(struct fimc_ctx *ctx);
int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags);
int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
struct fimc_frame *frame, struct fimc_addr *paddr);
+void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f);
+void fimc_set_yuv_order(struct fimc_ctx *ctx);
+void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f);
+void fimc_capture_irq_handler(struct fimc_dev *fimc, bool done);
+
+int fimc_register_m2m_device(struct fimc_dev *fimc,
+ struct v4l2_device *v4l2_dev);
+void fimc_unregister_m2m_device(struct fimc_dev *fimc);
+int fimc_register_driver(void);
+void fimc_unregister_driver(void);
/* -----------------------------------------------------*/
/* fimc-capture.c */
-int fimc_register_capture_device(struct fimc_dev *fimc);
+int fimc_register_capture_device(struct fimc_dev *fimc,
+ struct v4l2_device *v4l2_dev);
void fimc_unregister_capture_device(struct fimc_dev *fimc);
-int fimc_sensor_sd_init(struct fimc_dev *fimc, int index);
+int fimc_capture_ctrls_create(struct fimc_dev *fimc);
int fimc_vid_cap_buf_queue(struct fimc_dev *fimc,
struct fimc_vid_buffer *fimc_vb);
+void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
+ void *arg);
+int fimc_capture_suspend(struct fimc_dev *fimc);
+int fimc_capture_resume(struct fimc_dev *fimc);
+int fimc_capture_config_update(struct fimc_ctx *ctx);
/* Locking: the caller holds fimc->slock */
static inline void fimc_activate_capture(struct fimc_ctx *ctx)
@@ -661,22 +746,27 @@ static inline void fimc_deactivate_capture(struct fimc_dev *fimc)
}
/*
- * Add buf to the capture active buffers queue.
- * Locking: Need to be called with fimc_dev::slock held.
+ * Buffer list manipulation functions. Must be called with fimc.slock held.
*/
-static inline void active_queue_add(struct fimc_vid_cap *vid_cap,
- struct fimc_vid_buffer *buf)
+
+/**
+ * fimc_active_queue_add - add buffer to the capture active buffers queue
+ * @buf: buffer to add to the active buffers list
+ */
+static inline void fimc_active_queue_add(struct fimc_vid_cap *vid_cap,
+ struct fimc_vid_buffer *buf)
{
list_add_tail(&buf->list, &vid_cap->active_buf_q);
vid_cap->active_buf_cnt++;
}
-/*
- * Pop a video buffer from the capture active buffers queue
- * Locking: Need to be called with fimc_dev::slock held.
+/**
+ * fimc_active_queue_pop - pop buffer from the capture active buffers queue
+ *
+ * The caller must assure the active_buf_q list is not empty.
*/
-static inline struct fimc_vid_buffer *
-active_queue_pop(struct fimc_vid_cap *vid_cap)
+static inline struct fimc_vid_buffer *fimc_active_queue_pop(
+ struct fimc_vid_cap *vid_cap)
{
struct fimc_vid_buffer *buf;
buf = list_entry(vid_cap->active_buf_q.next,
@@ -686,16 +776,23 @@ active_queue_pop(struct fimc_vid_cap *vid_cap)
return buf;
}
-/* Add video buffer to the capture pending buffers queue */
+/**
+ * fimc_pending_queue_add - add buffer to the capture pending buffers queue
+ * @buf: buffer to add to the pending buffers list
+ */
static inline void fimc_pending_queue_add(struct fimc_vid_cap *vid_cap,
struct fimc_vid_buffer *buf)
{
list_add_tail(&buf->list, &vid_cap->pending_buf_q);
}
-/* Add video buffer to the capture pending buffers queue */
-static inline struct fimc_vid_buffer *
-pending_queue_pop(struct fimc_vid_cap *vid_cap)
+/**
+ * fimc_pending_queue_pop - pop buffer from the capture pending buffers queue
+ *
+ * The caller must assure the pending_buf_q list is not empty.
+ */
+static inline struct fimc_vid_buffer *fimc_pending_queue_pop(
+ struct fimc_vid_cap *vid_cap)
{
struct fimc_vid_buffer *buf;
buf = list_entry(vid_cap->pending_buf_q.next,
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c
new file mode 100644
index 000000000000..cc337b1de913
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c
@@ -0,0 +1,858 @@
+/*
+ * S5P/EXYNOS4 SoC series camera host interface media device driver
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 2 of the License,
+ * or (at your option) any later version.
+ */
+
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <media/v4l2-ctrls.h>
+#include <media/media-device.h>
+
+#include "fimc-core.h"
+#include "fimc-mdevice.h"
+#include "mipi-csis.h"
+
+static int __fimc_md_set_camclk(struct fimc_md *fmd,
+ struct fimc_sensor_info *s_info,
+ bool on);
+/**
+ * fimc_pipeline_prepare - update pipeline information with subdevice pointers
+ * @fimc: fimc device terminating the pipeline
+ *
+ * Caller holds the graph mutex.
+ */
+void fimc_pipeline_prepare(struct fimc_dev *fimc, struct media_entity *me)
+{
+ struct media_entity_graph graph;
+ struct v4l2_subdev *sd;
+
+ media_entity_graph_walk_start(&graph, me);
+
+ while ((me = media_entity_graph_walk_next(&graph))) {
+ if (media_entity_type(me) != MEDIA_ENT_T_V4L2_SUBDEV)
+ continue;
+ sd = media_entity_to_v4l2_subdev(me);
+
+ if (sd->grp_id == SENSOR_GROUP_ID)
+ fimc->pipeline.sensor = sd;
+ else if (sd->grp_id == CSIS_GROUP_ID)
+ fimc->pipeline.csis = sd;
+ }
+}
+
+/**
+ * __subdev_set_power - change power state of a single subdev
+ * @sd: subdevice to change power state for
+ * @on: 1 to enable power or 0 to disable
+ *
+ * Return result of s_power subdev operation or -ENXIO if sd argument
+ * is NULL. Return 0 if the subdevice does not implement s_power.
+ */
+static int __subdev_set_power(struct v4l2_subdev *sd, int on)
+{
+ int *use_count;
+ int ret;
+
+ if (sd == NULL)
+ return -ENXIO;
+
+ use_count = &sd->entity.use_count;
+ if (on && (*use_count)++ > 0)
+ return 0;
+ else if (!on && (*use_count == 0 || --(*use_count) > 0))
+ return 0;
+ ret = v4l2_subdev_call(sd, core, s_power, on);
+
+ return ret != -ENOIOCTLCMD ? ret : 0;
+}
+
+/**
+ * fimc_pipeline_s_power - change power state of all pipeline subdevs
+ * @fimc: fimc device terminating the pipeline
+ * @state: 1 to enable power or 0 for power down
+ *
+ * Need to be called with the graph mutex held.
+ */
+int fimc_pipeline_s_power(struct fimc_dev *fimc, int state)
+{
+ int ret = 0;
+
+ if (fimc->pipeline.sensor == NULL)
+ return -ENXIO;
+
+ if (state) {
+ ret = __subdev_set_power(fimc->pipeline.csis, 1);
+ if (ret && ret != -ENXIO)
+ return ret;
+ return __subdev_set_power(fimc->pipeline.sensor, 1);
+ }
+
+ ret = __subdev_set_power(fimc->pipeline.sensor, 0);
+ if (ret)
+ return ret;
+ ret = __subdev_set_power(fimc->pipeline.csis, 0);
+
+ return ret == -ENXIO ? 0 : ret;
+}
+
+/**
+ * __fimc_pipeline_initialize - update the pipeline information, enable power
+ * of all pipeline subdevs and the sensor clock
+ * @me: media entity to start graph walk with
+ * @prep: true to acquire sensor (and csis) subdevs
+ *
+ * This function must be called with the graph mutex held.
+ */
+static int __fimc_pipeline_initialize(struct fimc_dev *fimc,
+ struct media_entity *me, bool prep)
+{
+ int ret;
+
+ if (prep)
+ fimc_pipeline_prepare(fimc, me);
+ if (fimc->pipeline.sensor == NULL)
+ return -EINVAL;
+ ret = fimc_md_set_camclk(fimc->pipeline.sensor, true);
+ if (ret)
+ return ret;
+ return fimc_pipeline_s_power(fimc, 1);
+}
+
+int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me,
+ bool prep)
+{
+ int ret;
+
+ mutex_lock(&me->parent->graph_mutex);
+ ret = __fimc_pipeline_initialize(fimc, me, prep);
+ mutex_unlock(&me->parent->graph_mutex);
+
+ return ret;
+}
+
+/**
+ * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power
+ * @fimc: fimc device terminating the pipeline
+ *
+ * Disable power of all subdevs in the pipeline and turn off the external
+ * sensor clock.
+ * Called with the graph mutex held.
+ */
+int __fimc_pipeline_shutdown(struct fimc_dev *fimc)
+{
+ int ret = 0;
+
+ if (fimc->pipeline.sensor) {
+ ret = fimc_pipeline_s_power(fimc, 0);
+ fimc_md_set_camclk(fimc->pipeline.sensor, false);
+ }
+ return ret == -ENXIO ? 0 : ret;
+}
+
+int fimc_pipeline_shutdown(struct fimc_dev *fimc)
+{
+ struct media_entity *me = &fimc->vid_cap.vfd->entity;
+ int ret;
+
+ mutex_lock(&me->parent->graph_mutex);
+ ret = __fimc_pipeline_shutdown(fimc);
+ mutex_unlock(&me->parent->graph_mutex);
+
+ return ret;
+}
+
+/**
+ * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs
+ * @fimc: fimc device terminating the pipeline
+ * @on: passed as the s_stream call argument
+ */
+int fimc_pipeline_s_stream(struct fimc_dev *fimc, int on)
+{
+ struct fimc_pipeline *p = &fimc->pipeline;
+ int ret = 0;
+
+ if (p->sensor == NULL)
+ return -ENODEV;
+
+ if ((on && p->csis) || !on)
+ ret = v4l2_subdev_call(on ? p->csis : p->sensor,
+ video, s_stream, on);
+ if (ret < 0 && ret != -ENOIOCTLCMD)
+ return ret;
+ if ((!on && p->csis) || on)
+ ret = v4l2_subdev_call(on ? p->sensor : p->csis,
+ video, s_stream, on);
+ return ret == -ENOIOCTLCMD ? 0 : ret;
+}
+
+/*
+ * Sensor subdevice helper functions
+ */
+static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
+ struct fimc_sensor_info *s_info)
+{
+ struct i2c_adapter *adapter;
+ struct v4l2_subdev *sd = NULL;
+
+ if (!s_info || !fmd)
+ return NULL;
+
+ adapter = i2c_get_adapter(s_info->pdata->i2c_bus_num);
+ if (!adapter)
+ return NULL;
+ sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter,
+ s_info->pdata->board_info, NULL);
+ if (IS_ERR_OR_NULL(sd)) {
+ v4l2_err(&fmd->v4l2_dev, "Failed to acquire subdev\n");
+ return NULL;
+ }
+ v4l2_set_subdev_hostdata(sd, s_info);
+ sd->grp_id = SENSOR_GROUP_ID;
+
+ v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
+ s_info->pdata->board_info->type);
+ return sd;
+}
+
+static void fimc_md_unregister_sensor(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ if (!client)
+ return;
+ v4l2_device_unregister_subdev(sd);
+ i2c_unregister_device(client);
+ i2c_put_adapter(client->adapter);
+}
+
+static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
+{
+ struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
+ struct fimc_dev *fd = NULL;
+ int num_clients, ret, i;
+
+ /*
+ * Runtime resume one of the FIMC entities to make sure
+ * the sclk_cam clocks are not globally disabled.
+ */
+ for (i = 0; !fd && i < ARRAY_SIZE(fmd->fimc); i++)
+ if (fmd->fimc[i])
+ fd = fmd->fimc[i];
+ if (!fd)
+ return -ENXIO;
+ ret = pm_runtime_get_sync(&fd->pdev->dev);
+ if (ret < 0)
+ return ret;
+
+ WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor));
+ num_clients = min_t(u32, pdata->num_clients, ARRAY_SIZE(fmd->sensor));
+
+ fmd->num_sensors = num_clients;
+ for (i = 0; i < num_clients; i++) {
+ fmd->sensor[i].pdata = &pdata->isp_info[i];
+ ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true);
+ if (ret)
+ break;
+ fmd->sensor[i].subdev =
+ fimc_md_register_sensor(fmd, &fmd->sensor[i]);
+ ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], false);
+ if (ret)
+ break;
+ }
+ pm_runtime_put(&fd->pdev->dev);
+ return ret;
+}
+
+/*
+ * MIPI CSIS and FIMC platform devices registration.
+ */
+static int fimc_register_callback(struct device *dev, void *p)
+{
+ struct fimc_dev *fimc = dev_get_drvdata(dev);
+ struct fimc_md *fmd = p;
+ int ret;
+
+ if (!fimc || !fimc->pdev)
+ return 0;
+ if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
+ return 0;
+
+ fmd->fimc[fimc->pdev->id] = fimc;
+ ret = fimc_register_m2m_device(fimc, &fmd->v4l2_dev);
+ if (ret)
+ return ret;
+ ret = fimc_register_capture_device(fimc, &fmd->v4l2_dev);
+ if (!ret)
+ fimc->vid_cap.user_subdev_api = fmd->user_subdev_api;
+ return ret;
+}
+
+static int csis_register_callback(struct device *dev, void *p)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct platform_device *pdev;
+ struct fimc_md *fmd = p;
+ int id, ret;
+
+ if (!sd)
+ return 0;
+ pdev = v4l2_get_subdevdata(sd);
+ if (!pdev || pdev->id < 0 || pdev->id >= CSIS_MAX_ENTITIES)
+ return 0;
+ v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name);
+
+ id = pdev->id < 0 ? 0 : pdev->id;
+ fmd->csis[id].sd = sd;
+ sd->grp_id = CSIS_GROUP_ID;
+ ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
+ if (ret)
+ v4l2_err(&fmd->v4l2_dev,
+ "Failed to register CSIS subdevice: %d\n", ret);
+ return ret;
+}
+
+/**
+ * fimc_md_register_platform_entities - register FIMC and CSIS media entities
+ */
+static int fimc_md_register_platform_entities(struct fimc_md *fmd)
+{
+ struct device_driver *driver;
+ int ret;
+
+ driver = driver_find(FIMC_MODULE_NAME, &platform_bus_type);
+ if (!driver)
+ return -ENODEV;
+ ret = driver_for_each_device(driver, NULL, fmd,
+ fimc_register_callback);
+ put_driver(driver);
+ if (ret)
+ return ret;
+
+ driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type);
+ if (driver) {
+ ret = driver_for_each_device(driver, NULL, fmd,
+ csis_register_callback);
+ put_driver(driver);
+ }
+ return ret;
+}
+
+static void fimc_md_unregister_entities(struct fimc_md *fmd)
+{
+ int i;
+
+ for (i = 0; i < FIMC_MAX_DEVS; i++) {
+ if (fmd->fimc[i] == NULL)
+ continue;
+ fimc_unregister_m2m_device(fmd->fimc[i]);
+ fimc_unregister_capture_device(fmd->fimc[i]);
+ fmd->fimc[i] = NULL;
+ }
+ for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
+ if (fmd->csis[i].sd == NULL)
+ continue;
+ v4l2_device_unregister_subdev(fmd->csis[i].sd);
+ fmd->csis[i].sd = NULL;
+ }
+ for (i = 0; i < fmd->num_sensors; i++) {
+ if (fmd->sensor[i].subdev == NULL)
+ continue;
+ fimc_md_unregister_sensor(fmd->sensor[i].subdev);
+ fmd->sensor[i].subdev = NULL;
+ }
+}
+
+static int fimc_md_register_video_nodes(struct fimc_md *fmd)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < FIMC_MAX_DEVS && !ret; i++) {
+ if (!fmd->fimc[i])
+ continue;
+
+ if (fmd->fimc[i]->m2m.vfd)
+ ret = video_register_device(fmd->fimc[i]->m2m.vfd,
+ VFL_TYPE_GRABBER, -1);
+ if (ret)
+ break;
+ if (fmd->fimc[i]->vid_cap.vfd)
+ ret = video_register_device(fmd->fimc[i]->vid_cap.vfd,
+ VFL_TYPE_GRABBER, -1);
+ }
+
+ return ret;
+}
+
+/**
+ * __fimc_md_create_fimc_links - create links to all FIMC entities
+ * @fmd: fimc media device
+ * @source: the source entity to create links to all fimc entities from
+ * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null
+ * @pad: the source entity pad index
+ * @fimc_id: index of the fimc device for which link should be enabled
+ */
+static int __fimc_md_create_fimc_links(struct fimc_md *fmd,
+ struct media_entity *source,
+ struct v4l2_subdev *sensor,
+ int pad, int fimc_id)
+{
+ struct fimc_sensor_info *s_info;
+ struct media_entity *sink;
+ unsigned int flags;
+ int ret, i;
+
+ for (i = 0; i < FIMC_MAX_DEVS; i++) {
+ if (!fmd->fimc[i])
+ break;
+ /*
+ * Some FIMC variants are not fitted with camera capture
+ * interface. Skip creating a link from sensor for those.
+ */
+ if (sensor->grp_id == SENSOR_GROUP_ID &&
+ !fmd->fimc[i]->variant->has_cam_if)
+ continue;
+
+ flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0;
+ sink = &fmd->fimc[i]->vid_cap.subdev->entity;
+ ret = media_entity_create_link(source, pad, sink,
+ FIMC_SD_PAD_SINK, flags);
+ if (ret)
+ return ret;
+
+ /* Notify FIMC capture subdev entity */
+ ret = media_entity_call(sink, link_setup, &sink->pads[0],
+ &source->pads[pad], flags);
+ if (ret)
+ break;
+
+ v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
+ source->name, flags ? '=' : '-', sink->name);
+
+ if (flags == 0)
+ continue;
+ s_info = v4l2_get_subdev_hostdata(sensor);
+ if (!WARN_ON(s_info == NULL)) {
+ unsigned long irq_flags;
+ spin_lock_irqsave(&fmd->slock, irq_flags);
+ s_info->host = fmd->fimc[i];
+ spin_unlock_irqrestore(&fmd->slock, irq_flags);
+ }
+ }
+ return 0;
+}
+
+/**
+ * fimc_md_create_links - create default links between registered entities
+ *
+ * Parallel interface sensor entities are connected directly to FIMC capture
+ * entities. The sensors using MIPI CSIS bus are connected through immutable
+ * link with CSI receiver entity specified by mux_id. Any registered CSIS
+ * entity has a link to each registered FIMC capture entity. Enabled links
+ * are created by default between each subsequent registered sensor and
+ * subsequent FIMC capture entity. The number of default active links is
+ * determined by the number of available sensors or FIMC entities,
+ * whichever is less.
+ */
+static int fimc_md_create_links(struct fimc_md *fmd)
+{
+ struct v4l2_subdev *sensor, *csis;
+ struct s5p_fimc_isp_info *pdata;
+ struct fimc_sensor_info *s_info;
+ struct media_entity *source, *sink;
+ int i, pad, fimc_id = 0;
+ int ret = 0;
+ u32 flags;
+
+ for (i = 0; i < fmd->num_sensors; i++) {
+ if (fmd->sensor[i].subdev == NULL)
+ continue;
+
+ sensor = fmd->sensor[i].subdev;
+ s_info = v4l2_get_subdev_hostdata(sensor);
+ if (!s_info || !s_info->pdata)
+ continue;
+
+ source = NULL;
+ pdata = s_info->pdata;
+
+ switch (pdata->bus_type) {
+ case FIMC_MIPI_CSI2:
+ if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES,
+ "Wrong CSI channel id: %d\n", pdata->mux_id))
+ return -EINVAL;
+
+ csis = fmd->csis[pdata->mux_id].sd;
+ if (WARN(csis == NULL,
+ "MIPI-CSI interface specified "
+ "but s5p-csis module is not loaded!\n"))
+ continue;
+
+ ret = media_entity_create_link(&sensor->entity, 0,
+ &csis->entity, CSIS_PAD_SINK,
+ MEDIA_LNK_FL_IMMUTABLE |
+ MEDIA_LNK_FL_ENABLED);
+ if (ret)
+ return ret;
+
+ v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]",
+ sensor->entity.name, csis->entity.name);
+
+ source = &csis->entity;
+ pad = CSIS_PAD_SOURCE;
+ break;
+
+ case FIMC_ITU_601...FIMC_ITU_656:
+ source = &sensor->entity;
+ pad = 0;
+ break;
+
+ default:
+ v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n",
+ pdata->bus_type);
+ return -EINVAL;
+ }
+ if (source == NULL)
+ continue;
+
+ ret = __fimc_md_create_fimc_links(fmd, source, sensor, pad,
+ fimc_id++);
+ }
+ /* Create immutable links between each FIMC's subdev and video node */
+ flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
+ for (i = 0; i < FIMC_MAX_DEVS; i++) {
+ if (!fmd->fimc[i])
+ continue;
+ source = &fmd->fimc[i]->vid_cap.subdev->entity;
+ sink = &fmd->fimc[i]->vid_cap.vfd->entity;
+ ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
+ sink, 0, flags);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * The peripheral sensor clock management.
+ */
+static int fimc_md_get_clocks(struct fimc_md *fmd)
+{
+ char clk_name[32];
+ struct clk *clock;
+ int i;
+
+ for (i = 0; i < FIMC_MAX_CAMCLKS; i++) {
+ snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i);
+ clock = clk_get(NULL, clk_name);
+ if (IS_ERR_OR_NULL(clock)) {
+ v4l2_err(&fmd->v4l2_dev, "Failed to get clock: %s",
+ clk_name);
+ return -ENXIO;
+ }
+ fmd->camclk[i].clock = clock;
+ }
+ return 0;
+}
+
+static void fimc_md_put_clocks(struct fimc_md *fmd)
+{
+ int i = FIMC_MAX_CAMCLKS;
+
+ while (--i >= 0) {
+ if (IS_ERR_OR_NULL(fmd->camclk[i].clock))
+ continue;
+ clk_put(fmd->camclk[i].clock);
+ fmd->camclk[i].clock = NULL;
+ }
+}
+
+static int __fimc_md_set_camclk(struct fimc_md *fmd,
+ struct fimc_sensor_info *s_info,
+ bool on)
+{
+ struct s5p_fimc_isp_info *pdata = s_info->pdata;
+ struct fimc_camclk_info *camclk;
+ int ret = 0;
+
+ if (WARN_ON(pdata->clk_id >= FIMC_MAX_CAMCLKS) || fmd == NULL)
+ return -EINVAL;
+
+ if (s_info->clk_on == on)
+ return 0;
+ camclk = &fmd->camclk[pdata->clk_id];
+
+ dbg("camclk %d, f: %lu, clk: %p, on: %d",
+ pdata->clk_id, pdata->clk_frequency, camclk, on);
+
+ if (on) {
+ if (camclk->use_count > 0 &&
+ camclk->frequency != pdata->clk_frequency)
+ return -EINVAL;
+
+ if (camclk->use_count++ == 0) {
+ clk_set_rate(camclk->clock, pdata->clk_frequency);
+ camclk->frequency = pdata->clk_frequency;
+ ret = clk_enable(camclk->clock);
+ }
+ s_info->clk_on = 1;
+ dbg("Enabled camclk %d: f: %lu", pdata->clk_id,
+ clk_get_rate(camclk->clock));
+
+ return ret;
+ }
+
+ if (WARN_ON(camclk->use_count == 0))
+ return 0;
+
+ if (--camclk->use_count == 0) {
+ clk_disable(camclk->clock);
+ s_info->clk_on = 0;
+ dbg("Disabled camclk %d", pdata->clk_id);
+ }
+ return ret;
+}
+
+/**
+ * fimc_md_set_camclk - peripheral sensor clock setup
+ * @sd: sensor subdev to configure sclk_cam clock for
+ * @on: 1 to enable or 0 to disable the clock
+ *
+ * There are 2 separate clock outputs available in the SoC for external
+ * image processors. These clocks are shared between all registered FIMC
+ * devices to which sensors can be attached, either directly or through
+ * the MIPI CSI receiver. The clock is allowed here to be used by
+ * multiple sensors concurrently if they use same frequency.
+ * The per sensor subdev clk_on attribute helps to synchronize accesses
+ * to the sclk_cam clocks from the video and media device nodes.
+ * This function should only be called when the graph mutex is held.
+ */
+int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
+{
+ struct fimc_sensor_info *s_info = v4l2_get_subdev_hostdata(sd);
+ struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity);
+
+ return __fimc_md_set_camclk(fmd, s_info, on);
+}
+
+static int fimc_md_link_notify(struct media_pad *source,
+ struct media_pad *sink, u32 flags)
+{
+ struct v4l2_subdev *sd;
+ struct fimc_dev *fimc;
+ int ret = 0;
+
+ if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ return 0;
+
+ sd = media_entity_to_v4l2_subdev(sink->entity);
+ fimc = v4l2_get_subdevdata(sd);
+
+ if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+ ret = __fimc_pipeline_shutdown(fimc);
+ fimc->pipeline.sensor = NULL;
+ fimc->pipeline.csis = NULL;
+
+ mutex_lock(&fimc->lock);
+ fimc_ctrls_delete(fimc->vid_cap.ctx);
+ mutex_unlock(&fimc->lock);
+ return ret;
+ }
+ /*
+ * Link activation. Enable power of pipeline elements only if the
+ * pipeline is already in use, i.e. its video node is opened.
+ * Recreate the controls destroyed during the link deactivation.
+ */
+ mutex_lock(&fimc->lock);
+ if (fimc->vid_cap.refcnt > 0) {
+ ret = __fimc_pipeline_initialize(fimc, source->entity, true);
+ if (!ret)
+ ret = fimc_capture_ctrls_create(fimc);
+ }
+ mutex_unlock(&fimc->lock);
+
+ return ret ? -EPIPE : ret;
+}
+
+static ssize_t fimc_md_sysfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fimc_md *fmd = platform_get_drvdata(pdev);
+
+ if (fmd->user_subdev_api)
+ return strlcpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE);
+
+ return strlcpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
+}
+
+static ssize_t fimc_md_sysfs_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fimc_md *fmd = platform_get_drvdata(pdev);
+ bool subdev_api;
+ int i;
+
+ if (!strcmp(buf, "vid-dev\n"))
+ subdev_api = false;
+ else if (!strcmp(buf, "sub-dev\n"))
+ subdev_api = true;
+ else
+ return count;
+
+ fmd->user_subdev_api = subdev_api;
+ for (i = 0; i < FIMC_MAX_DEVS; i++)
+ if (fmd->fimc[i])
+ fmd->fimc[i]->vid_cap.user_subdev_api = subdev_api;
+ return count;
+}
+/*
+ * This device attribute is to select video pipeline configuration method.
+ * There are following valid values:
+ * vid-dev - for V4L2 video node API only, subdevice will be configured
+ * by the host driver.
+ * sub-dev - for media controller API, subdevs must be configured in user
+ * space before starting streaming.
+ */
+static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
+ fimc_md_sysfs_show, fimc_md_sysfs_store);
+
+static int __devinit fimc_md_probe(struct platform_device *pdev)
+{
+ struct v4l2_device *v4l2_dev;
+ struct fimc_md *fmd;
+ int ret;
+
+ if (WARN(!pdev->dev.platform_data, "Platform data not specified!\n"))
+ return -EINVAL;
+
+ fmd = kzalloc(sizeof(struct fimc_md), GFP_KERNEL);
+ if (!fmd)
+ return -ENOMEM;
+
+ spin_lock_init(&fmd->slock);
+ fmd->pdev = pdev;
+
+ strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
+ sizeof(fmd->media_dev.model));
+ fmd->media_dev.link_notify = fimc_md_link_notify;
+ fmd->media_dev.dev = &pdev->dev;
+
+ v4l2_dev = &fmd->v4l2_dev;
+ v4l2_dev->mdev = &fmd->media_dev;
+ v4l2_dev->notify = fimc_sensor_notify;
+ snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s",
+ dev_name(&pdev->dev));
+
+ ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev);
+ if (ret < 0) {
+ v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
+ goto err1;
+ }
+ ret = media_device_register(&fmd->media_dev);
+ if (ret < 0) {
+ v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
+ goto err2;
+ }
+ ret = fimc_md_get_clocks(fmd);
+ if (ret)
+ goto err3;
+
+ fmd->user_subdev_api = false;
+ ret = fimc_md_register_platform_entities(fmd);
+ if (ret)
+ goto err3;
+
+ ret = fimc_md_register_sensor_entities(fmd);
+ if (ret)
+ goto err3;
+ ret = fimc_md_create_links(fmd);
+ if (ret)
+ goto err3;
+ ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
+ if (ret)
+ goto err3;
+ ret = fimc_md_register_video_nodes(fmd);
+ if (ret)
+ goto err3;
+
+ ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
+ if (!ret) {
+ platform_set_drvdata(pdev, fmd);
+ return 0;
+ }
+err3:
+ media_device_unregister(&fmd->media_dev);
+ fimc_md_put_clocks(fmd);
+ fimc_md_unregister_entities(fmd);
+err2:
+ v4l2_device_unregister(&fmd->v4l2_dev);
+err1:
+ kfree(fmd);
+ return ret;
+}
+
+static int __devexit fimc_md_remove(struct platform_device *pdev)
+{
+ struct fimc_md *fmd = platform_get_drvdata(pdev);
+
+ if (!fmd)
+ return 0;
+ device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
+ fimc_md_unregister_entities(fmd);
+ media_device_unregister(&fmd->media_dev);
+ fimc_md_put_clocks(fmd);
+ kfree(fmd);
+ return 0;
+}
+
+static struct platform_driver fimc_md_driver = {
+ .probe = fimc_md_probe,
+ .remove = __devexit_p(fimc_md_remove),
+ .driver = {
+ .name = "s5p-fimc-md",
+ .owner = THIS_MODULE,
+ }
+};
+
+int __init fimc_md_init(void)
+{
+ int ret;
+ request_module("s5p-csis");
+ ret = fimc_register_driver();
+ if (ret)
+ return ret;
+ return platform_driver_register(&fimc_md_driver);
+}
+void __exit fimc_md_exit(void)
+{
+ platform_driver_unregister(&fimc_md_driver);
+ fimc_unregister_driver();
+}
+
+module_init(fimc_md_init);
+module_exit(fimc_md_exit);
+
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("2.0.1");
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.h b/drivers/media/video/s5p-fimc/fimc-mdevice.h
new file mode 100644
index 000000000000..da3780823e7d
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * 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 FIMC_MDEVICE_H_
+#define FIMC_MDEVICE_H_
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <media/media-device.h>
+#include <media/media-entity.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include "fimc-core.h"
+#include "mipi-csis.h"
+
+/* Group IDs of sensor, MIPI CSIS and the writeback subdevs. */
+#define SENSOR_GROUP_ID (1 << 8)
+#define CSIS_GROUP_ID (1 << 9)
+#define WRITEBACK_GROUP_ID (1 << 10)
+
+#define FIMC_MAX_SENSORS 8
+#define FIMC_MAX_CAMCLKS 2
+
+struct fimc_csis_info {
+ struct v4l2_subdev *sd;
+ int id;
+};
+
+struct fimc_camclk_info {
+ struct clk *clock;
+ int use_count;
+ unsigned long frequency;
+};
+
+/**
+ * struct fimc_sensor_info - image data source subdev information
+ * @pdata: sensor's atrributes passed as media device's platform data
+ * @subdev: image sensor v4l2 subdev
+ * @host: fimc device the sensor is currently linked to
+ * @clk_on: sclk_cam clock's state associated with this subdev
+ *
+ * This data structure applies to image sensor and the writeback subdevs.
+ */
+struct fimc_sensor_info {
+ struct s5p_fimc_isp_info *pdata;
+ struct v4l2_subdev *subdev;
+ struct fimc_dev *host;
+ bool clk_on;
+};
+
+/**
+ * struct fimc_md - fimc media device information
+ * @csis: MIPI CSIS subdevs data
+ * @sensor: array of registered sensor subdevs
+ * @num_sensors: actual number of registered sensors
+ * @camclk: external sensor clock information
+ * @fimc: array of registered fimc devices
+ * @media_dev: top level media device
+ * @v4l2_dev: top level v4l2_device holding up the subdevs
+ * @pdev: platform device this media device is hooked up into
+ * @user_subdev_api: true if subdevs are not configured by the host driver
+ * @slock: spinlock protecting @sensor array
+ */
+struct fimc_md {
+ struct fimc_csis_info csis[CSIS_MAX_ENTITIES];
+ struct fimc_sensor_info sensor[FIMC_MAX_SENSORS];
+ int num_sensors;
+ struct fimc_camclk_info camclk[FIMC_MAX_CAMCLKS];
+ struct fimc_dev *fimc[FIMC_MAX_DEVS];
+ struct media_device media_dev;
+ struct v4l2_device v4l2_dev;
+ struct platform_device *pdev;
+ bool user_subdev_api;
+ spinlock_t slock;
+};
+
+#define is_subdev_pad(pad) (pad == NULL || \
+ media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV)
+
+#define me_subtype(me) \
+ ((me->type) & (MEDIA_ENT_TYPE_MASK | MEDIA_ENT_SUBTYPE_MASK))
+
+#define subdev_has_devnode(__sd) (__sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)
+
+static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me)
+{
+ return me->parent == NULL ? NULL :
+ container_of(me->parent, struct fimc_md, media_dev);
+}
+
+static inline void fimc_md_graph_lock(struct fimc_dev *fimc)
+{
+ BUG_ON(fimc->vid_cap.vfd == NULL);
+ mutex_lock(&fimc->vid_cap.vfd->entity.parent->graph_mutex);
+}
+
+static inline void fimc_md_graph_unlock(struct fimc_dev *fimc)
+{
+ BUG_ON(fimc->vid_cap.vfd == NULL);
+ mutex_unlock(&fimc->vid_cap.vfd->entity.parent->graph_mutex);
+}
+
+int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
+void fimc_pipeline_prepare(struct fimc_dev *fimc, struct media_entity *me);
+int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me,
+ bool resume);
+int fimc_pipeline_shutdown(struct fimc_dev *fimc);
+int fimc_pipeline_s_power(struct fimc_dev *fimc, int state);
+int fimc_pipeline_s_stream(struct fimc_dev *fimc, int state);
+
+#endif
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c
index 4893b2d91d84..20e664e34163 100644
--- a/drivers/media/video/s5p-fimc/fimc-reg.c
+++ b/drivers/media/video/s5p-fimc/fimc-reg.c
@@ -30,7 +30,7 @@ void fimc_hw_reset(struct fimc_dev *dev)
cfg = readl(dev->regs + S5P_CIGCTRL);
cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL);
writel(cfg, dev->regs + S5P_CIGCTRL);
- udelay(1000);
+ udelay(10);
cfg = readl(dev->regs + S5P_CIGCTRL);
cfg &= ~S5P_CIGCTRL_SWRST;
@@ -41,19 +41,11 @@ static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
{
u32 flip = S5P_MSCTRL_FLIP_NORMAL;
- switch (ctx->flip) {
- case FLIP_X_AXIS:
+ if (ctx->hflip)
flip = S5P_MSCTRL_FLIP_X_MIRROR;
- break;
- case FLIP_Y_AXIS:
+ if (ctx->vflip)
flip = S5P_MSCTRL_FLIP_Y_MIRROR;
- break;
- case FLIP_XY_AXIS:
- flip = S5P_MSCTRL_FLIP_180;
- break;
- default:
- break;
- }
+
if (ctx->rotation <= 90)
return flip;
@@ -64,19 +56,11 @@ static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
{
u32 flip = S5P_CITRGFMT_FLIP_NORMAL;
- switch (ctx->flip) {
- case FLIP_X_AXIS:
- flip = S5P_CITRGFMT_FLIP_X_MIRROR;
- break;
- case FLIP_Y_AXIS:
- flip = S5P_CITRGFMT_FLIP_Y_MIRROR;
- break;
- case FLIP_XY_AXIS:
- flip = S5P_CITRGFMT_FLIP_180;
- break;
- default:
- break;
- }
+ if (ctx->hflip)
+ flip |= S5P_CITRGFMT_FLIP_X_MIRROR;
+ if (ctx->vflip)
+ flip |= S5P_CITRGFMT_FLIP_Y_MIRROR;
+
if (ctx->rotation <= 90)
return flip;
@@ -368,17 +352,19 @@ void fimc_hw_en_capture(struct fimc_ctx *ctx)
writel(cfg | S5P_CIIMGCPT_IMGCPTEN, dev->regs + S5P_CIIMGCPT);
}
-void fimc_hw_set_effect(struct fimc_ctx *ctx)
+void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active)
{
struct fimc_dev *dev = ctx->fimc_dev;
struct fimc_effect *effect = &ctx->effect;
- u32 cfg = (S5P_CIIMGEFF_IE_ENABLE | S5P_CIIMGEFF_IE_SC_AFTER);
-
- cfg |= effect->type;
+ u32 cfg = 0;
- if (effect->type == S5P_FIMC_EFFECT_ARBITRARY) {
- cfg |= S5P_CIIMGEFF_PAT_CB(effect->pat_cb);
- cfg |= S5P_CIIMGEFF_PAT_CR(effect->pat_cr);
+ if (active) {
+ cfg |= S5P_CIIMGEFF_IE_SC_AFTER | S5P_CIIMGEFF_IE_ENABLE;
+ cfg |= effect->type;
+ if (effect->type == S5P_FIMC_EFFECT_ARBITRARY) {
+ cfg |= S5P_CIIMGEFF_PAT_CB(effect->pat_cb);
+ cfg |= S5P_CIIMGEFF_PAT_CR(effect->pat_cr);
+ }
}
writel(cfg, dev->regs + S5P_CIIMGEFF);
@@ -547,20 +533,24 @@ int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
u32 cfg = readl(fimc->regs + S5P_CIGCTRL);
cfg &= ~(S5P_CIGCTRL_INVPOLPCLK | S5P_CIGCTRL_INVPOLVSYNC |
- S5P_CIGCTRL_INVPOLHREF | S5P_CIGCTRL_INVPOLHSYNC);
+ S5P_CIGCTRL_INVPOLHREF | S5P_CIGCTRL_INVPOLHSYNC |
+ S5P_CIGCTRL_INVPOLFIELD);
- if (cam->flags & FIMC_CLK_INV_PCLK)
+ if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
cfg |= S5P_CIGCTRL_INVPOLPCLK;
- if (cam->flags & FIMC_CLK_INV_VSYNC)
+ if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
cfg |= S5P_CIGCTRL_INVPOLVSYNC;
- if (cam->flags & FIMC_CLK_INV_HREF)
+ if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
cfg |= S5P_CIGCTRL_INVPOLHREF;
- if (cam->flags & FIMC_CLK_INV_HSYNC)
+ if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
cfg |= S5P_CIGCTRL_INVPOLHSYNC;
+ if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW)
+ cfg |= S5P_CIGCTRL_INVPOLFIELD;
+
writel(cfg, fimc->regs + S5P_CIGCTRL);
return 0;
@@ -588,7 +578,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) {
for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
- if (fimc->vid_cap.fmt.code == pix_desc[i].pixelcode) {
+ if (fimc->vid_cap.mf.code == pix_desc[i].pixelcode) {
cfg = pix_desc[i].cisrcfmt;
bus_width = pix_desc[i].bus_width;
break;
@@ -596,9 +586,9 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
}
if (i == ARRAY_SIZE(pix_desc)) {
- v4l2_err(&fimc->vid_cap.v4l2_dev,
+ v4l2_err(fimc->vid_cap.vfd,
"Camera color format not supported: %d\n",
- fimc->vid_cap.fmt.code);
+ fimc->vid_cap.mf.code);
return -EINVAL;
}
@@ -608,6 +598,9 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
else if (bus_width == 16)
cfg |= S5P_CISRCFMT_ITU601_16BIT;
} /* else defaults to ITU-R BT.656 8-bit */
+ } else if (cam->bus_type == FIMC_MIPI_CSI2) {
+ if (fimc_fmt_is_jpeg(f->fmt->color))
+ cfg |= S5P_CISRCFMT_ITU601_8BIT;
}
cfg |= S5P_CISRCFMT_HSIZE(f->o_width) | S5P_CISRCFMT_VSIZE(f->o_height);
@@ -649,7 +642,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
/* Select ITU B interface, disable Writeback path and test pattern. */
cfg &= ~(S5P_CIGCTRL_TESTPAT_MASK | S5P_CIGCTRL_SELCAM_ITU_A |
S5P_CIGCTRL_SELCAM_MIPI | S5P_CIGCTRL_CAMIF_SELWB |
- S5P_CIGCTRL_SELCAM_MIPI_A);
+ S5P_CIGCTRL_SELCAM_MIPI_A | S5P_CIGCTRL_CAM_JPEG);
if (cam->bus_type == FIMC_MIPI_CSI2) {
cfg |= S5P_CIGCTRL_SELCAM_MIPI;
@@ -658,11 +651,18 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
cfg |= S5P_CIGCTRL_SELCAM_MIPI_A;
/* TODO: add remaining supported formats. */
- if (vid_cap->fmt.code == V4L2_MBUS_FMT_VYUY8_2X8) {
+ switch (vid_cap->mf.code) {
+ case V4L2_MBUS_FMT_VYUY8_2X8:
tmp = S5P_CSIIMGFMT_YCBCR422_8BIT;
- } else {
- err("camera image format not supported: %d",
- vid_cap->fmt.code);
+ break;
+ case V4L2_MBUS_FMT_JPEG_1X8:
+ tmp = S5P_CSIIMGFMT_USER(1);
+ cfg |= S5P_CIGCTRL_CAM_JPEG;
+ break;
+ default:
+ v4l2_err(fimc->vid_cap.vfd,
+ "Not supported camera pixel format: %d",
+ vid_cap->mf.code);
return -EINVAL;
}
tmp |= (cam->csi_data_align == 32) << 8;
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c
index ef056d6605ca..59d79bc2f58a 100644
--- a/drivers/media/video/s5p-fimc/mipi-csis.c
+++ b/drivers/media/video/s5p-fimc/mipi-csis.c
@@ -81,6 +81,12 @@ static char *csi_clock_name[] = {
};
#define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
+static const char * const csis_supply_name[] = {
+ "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
+ "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
+};
+#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
+
enum {
ST_POWERED = 1,
ST_STREAMING = 2,
@@ -109,9 +115,9 @@ struct csis_state {
struct platform_device *pdev;
struct resource *regs_res;
void __iomem *regs;
+ struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
struct clk *clock[NUM_CSIS_CLOCKS];
int irq;
- struct regulator *supply;
u32 flags;
const struct csis_pix_format *csis_fmt;
struct v4l2_mbus_framefmt format;
@@ -460,6 +466,7 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
struct resource *regs_res;
struct csis_state *state;
int ret = -ENOMEM;
+ int i;
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state)
@@ -519,14 +526,13 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
goto e_clkput;
}
- if (!pdata->fixed_phy_vdd) {
- state->supply = regulator_get(&pdev->dev, "vdd");
- if (IS_ERR(state->supply)) {
- ret = PTR_ERR(state->supply);
- state->supply = NULL;
- goto e_clkput;
- }
- }
+ for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
+ state->supplies[i].supply = csis_supply_name[i];
+
+ ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES,
+ state->supplies);
+ if (ret)
+ goto e_clkput;
ret = request_irq(state->irq, s5pcsis_irq_handler, 0,
dev_name(&pdev->dev), state);
@@ -553,7 +559,6 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
/* .. and a pointer to the subdev. */
platform_set_drvdata(pdev, &state->sd);
- state->flags = ST_SUSPENDED;
pm_runtime_enable(&pdev->dev);
return 0;
@@ -561,8 +566,7 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
e_irqfree:
free_irq(state->irq, state);
e_regput:
- if (state->supply)
- regulator_put(state->supply);
+ regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
e_clkput:
clk_disable(state->clock[CSIS_CLK_MUX]);
s5pcsis_clk_put(state);
@@ -575,7 +579,7 @@ e_free:
return ret;
}
-static int s5pcsis_suspend(struct device *dev)
+static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
{
struct s5p_platform_mipi_csis *pdata = dev->platform_data;
struct platform_device *pdev = to_platform_device(dev);
@@ -592,21 +596,21 @@ static int s5pcsis_suspend(struct device *dev)
ret = pdata->phy_enable(state->pdev, false);
if (ret)
goto unlock;
- if (state->supply) {
- ret = regulator_disable(state->supply);
- if (ret)
- goto unlock;
- }
+ ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
+ state->supplies);
+ if (ret)
+ goto unlock;
clk_disable(state->clock[CSIS_CLK_GATE]);
state->flags &= ~ST_POWERED;
+ if (!runtime)
+ state->flags |= ST_SUSPENDED;
}
- state->flags |= ST_SUSPENDED;
unlock:
mutex_unlock(&state->lock);
return ret ? -EAGAIN : 0;
}
-static int s5pcsis_resume(struct device *dev)
+static int s5pcsis_pm_resume(struct device *dev, bool runtime)
{
struct s5p_platform_mipi_csis *pdata = dev->platform_data;
struct platform_device *pdev = to_platform_device(dev);
@@ -618,20 +622,20 @@ static int s5pcsis_resume(struct device *dev)
__func__, state->flags);
mutex_lock(&state->lock);
- if (!(state->flags & ST_SUSPENDED))
+ if (!runtime && !(state->flags & ST_SUSPENDED))
goto unlock;
if (!(state->flags & ST_POWERED)) {
- if (state->supply)
- ret = regulator_enable(state->supply);
+ ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES,
+ state->supplies);
if (ret)
goto unlock;
-
ret = pdata->phy_enable(state->pdev, true);
if (!ret) {
state->flags |= ST_POWERED;
- } else if (state->supply) {
- regulator_disable(state->supply);
+ } else {
+ regulator_bulk_disable(CSIS_NUM_SUPPLIES,
+ state->supplies);
goto unlock;
}
clk_enable(state->clock[CSIS_CLK_GATE]);
@@ -646,24 +650,26 @@ static int s5pcsis_resume(struct device *dev)
}
#ifdef CONFIG_PM_SLEEP
-static int s5pcsis_pm_suspend(struct device *dev)
+static int s5pcsis_suspend(struct device *dev)
{
- return s5pcsis_suspend(dev);
+ return s5pcsis_pm_suspend(dev, false);
}
-static int s5pcsis_pm_resume(struct device *dev)
+static int s5pcsis_resume(struct device *dev)
{
- int ret;
-
- ret = s5pcsis_resume(dev);
+ return s5pcsis_pm_resume(dev, false);
+}
+#endif
- if (!ret) {
- pm_runtime_disable(dev);
- ret = pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
- }
+#ifdef CONFIG_PM_RUNTIME
+static int s5pcsis_runtime_suspend(struct device *dev)
+{
+ return s5pcsis_pm_suspend(dev, true);
+}
- return ret;
+static int s5pcsis_runtime_resume(struct device *dev)
+{
+ return s5pcsis_pm_resume(dev, true);
}
#endif
@@ -679,8 +685,7 @@ static int __devexit s5pcsis_remove(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
s5pcsis_clk_put(state);
- if (state->supply)
- regulator_put(state->supply);
+ regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
media_entity_cleanup(&state->sd.entity);
free_irq(state->irq, state);
@@ -692,8 +697,9 @@ static int __devexit s5pcsis_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops s5pcsis_pm_ops = {
- SET_RUNTIME_PM_OPS(s5pcsis_suspend, s5pcsis_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_pm_suspend, s5pcsis_pm_resume)
+ SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume,
+ NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
};
static struct platform_driver s5pcsis_driver = {
diff --git a/drivers/media/video/s5p-fimc/regs-fimc.h b/drivers/media/video/s5p-fimc/regs-fimc.h
index 0fea3e635d76..c8e3b94bd91d 100644
--- a/drivers/media/video/s5p-fimc/regs-fimc.h
+++ b/drivers/media/video/s5p-fimc/regs-fimc.h
@@ -54,12 +54,14 @@
#define S5P_CIGCTRL_IRQ_CLR (1 << 19)
#define S5P_CIGCTRL_IRQ_ENABLE (1 << 16)
#define S5P_CIGCTRL_SHDW_DISABLE (1 << 12)
+#define S5P_CIGCTRL_CAM_JPEG (1 << 8)
#define S5P_CIGCTRL_SELCAM_MIPI_A (1 << 7)
#define S5P_CIGCTRL_CAMIF_SELWB (1 << 6)
/* 0 - ITU601; 1 - ITU709 */
#define S5P_CIGCTRL_CSC_ITU601_709 (1 << 5)
#define S5P_CIGCTRL_INVPOLHSYNC (1 << 4)
#define S5P_CIGCTRL_SELCAM_MIPI (1 << 3)
+#define S5P_CIGCTRL_INVPOLFIELD (1 << 1)
#define S5P_CIGCTRL_INTERLACE (1 << 0)
/* Window offset 2 */
@@ -184,7 +186,6 @@
/* Image effect */
#define S5P_CIIMGEFF 0xd0
-#define S5P_CIIMGEFF_IE_DISABLE (0 << 30)
#define S5P_CIIMGEFF_IE_ENABLE (1 << 30)
#define S5P_CIIMGEFF_IE_SC_BEFORE (0 << 29)
#define S5P_CIIMGEFF_IE_SC_AFTER (1 << 29)
@@ -286,10 +287,8 @@
#define S5P_CSIIMGFMT_RAW8 0x2a
#define S5P_CSIIMGFMT_RAW10 0x2b
#define S5P_CSIIMGFMT_RAW12 0x2c
-#define S5P_CSIIMGFMT_USER1 0x30
-#define S5P_CSIIMGFMT_USER2 0x31
-#define S5P_CSIIMGFMT_USER3 0x32
-#define S5P_CSIIMGFMT_USER4 0x33
+/* User defined formats. x = 0...16. */
+#define S5P_CSIIMGFMT_USER(x) (0x30 + x - 1)
/* Output frame buffer sequence mask */
#define S5P_CIFCNTSEQ 0x1FC
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
index 7dc7eab58b38..8be8b54eb749 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
@@ -202,7 +202,7 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
appropraite flags */
src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
- if (vb2_dma_contig_plane_paddr(dst_buf->b, 0) == dec_y_addr) {
+ if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) {
memcpy(&dst_buf->b->v4l2_buf.timecode,
&src_buf->b->v4l2_buf.timecode,
sizeof(struct v4l2_timecode));
@@ -248,7 +248,7 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
* check which videobuf does it correspond to */
list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
/* Check if this is the buffer we're looking for */
- if (vb2_dma_contig_plane_paddr(dst_buf->b, 0) == dspl_y_addr) {
+ if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dspl_y_addr) {
list_del(&dst_buf->list);
ctx->dst_queue_cnt--;
dst_buf->b->v4l2_buf.sequence = ctx->sequence;
@@ -940,9 +940,8 @@ static int match_child(struct device *dev, void *data)
return !strcmp(dev_name(dev), (char *)data);
}
-
/* MFC probe function */
-static int __devinit s5p_mfc_probe(struct platform_device *pdev)
+static int s5p_mfc_probe(struct platform_device *pdev)
{
struct s5p_mfc_dev *dev;
struct video_device *vfd;
@@ -1236,7 +1235,7 @@ static const struct dev_pm_ops s5p_mfc_pm_ops = {
NULL)
};
-static struct platform_driver s5p_mfc_pdrv = {
+static struct platform_driver s5p_mfc_driver = {
.probe = s5p_mfc_probe,
.remove = __devexit_p(s5p_mfc_remove),
.driver = {
@@ -1254,15 +1253,15 @@ static int __init s5p_mfc_init(void)
int ret;
pr_info("%s", banner);
- ret = platform_driver_register(&s5p_mfc_pdrv);
+ ret = platform_driver_register(&s5p_mfc_driver);
if (ret)
pr_err("Platform device registration failed.\n");
return ret;
}
-static void __devexit s5p_mfc_exit(void)
+static void __exit s5p_mfc_exit(void)
{
- platform_driver_unregister(&s5p_mfc_pdrv);
+ platform_driver_unregister(&s5p_mfc_driver);
}
module_init(s5p_mfc_init);
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
index b2c5052a9c41..bfbe08432050 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
@@ -165,7 +165,7 @@ static struct mfc_control controls[] = {
.maximum = 32,
.step = 1,
.default_value = 1,
- .is_volatile = 1,
+ .flags = V4L2_CTRL_FLAG_VOLATILE,
},
};
@@ -745,7 +745,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
};
static int s5p_mfc_queue_setup(struct vb2_queue *vq, unsigned int *buf_count,
- unsigned int *plane_count, unsigned long psize[],
+ unsigned int *plane_count, unsigned int psize[],
void *allocators[])
{
struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
@@ -824,7 +824,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
return 0;
for (i = 0; i <= ctx->src_fmt->num_planes ; i++) {
if (IS_ERR_OR_NULL(ERR_PTR(
- vb2_dma_contig_plane_paddr(vb, i)))) {
+ vb2_dma_contig_plane_dma_addr(vb, i)))) {
mfc_err("Plane mem not allocated\n");
return -EINVAL;
}
@@ -837,13 +837,13 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
i = vb->v4l2_buf.index;
ctx->dst_bufs[i].b = vb;
ctx->dst_bufs[i].cookie.raw.luma =
- vb2_dma_contig_plane_paddr(vb, 0);
+ vb2_dma_contig_plane_dma_addr(vb, 0);
ctx->dst_bufs[i].cookie.raw.chroma =
- vb2_dma_contig_plane_paddr(vb, 1);
+ vb2_dma_contig_plane_dma_addr(vb, 1);
ctx->dst_bufs_cnt++;
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
if (IS_ERR_OR_NULL(ERR_PTR(
- vb2_dma_contig_plane_paddr(vb, 0)))) {
+ vb2_dma_contig_plane_dma_addr(vb, 0)))) {
mfc_err("Plane memory not allocated\n");
return -EINVAL;
}
@@ -855,7 +855,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
i = vb->v4l2_buf.index;
ctx->src_bufs[i].b = vb;
ctx->src_bufs[i].cookie.stream =
- vb2_dma_contig_plane_paddr(vb, 0);
+ vb2_dma_contig_plane_dma_addr(vb, 0);
ctx->src_bufs_cnt++;
} else {
mfc_err("s5p_mfc_buf_init: unknown queue type\n");
@@ -864,7 +864,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
return 0;
}
-static int s5p_mfc_start_streaming(struct vb2_queue *q)
+static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
struct s5p_mfc_dev *dev = ctx->dev;
@@ -1020,7 +1020,7 @@ int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx)
return ctx->ctrl_handler.error;
}
if (controls[i].is_volatile && ctx->ctrls[i])
- ctx->ctrls[i]->is_volatile = 1;
+ ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE;
}
return 0;
}
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
index fee094a14f4c..4c90e53bd964 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
@@ -599,8 +599,8 @@ static void cleanup_ref_queue(struct s5p_mfc_ctx *ctx)
while (!list_empty(&ctx->ref_queue)) {
mb_entry = list_entry((&ctx->ref_queue)->next,
struct s5p_mfc_buf, list);
- mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
- mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
+ mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
+ mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
list_del(&mb_entry->list);
ctx->ref_queue_cnt--;
list_add_tail(&mb_entry->list, &ctx->src_queue);
@@ -622,7 +622,7 @@ static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
spin_lock_irqsave(&dev->irqlock, flags);
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
- dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
dst_size = vb2_plane_size(dst_mb->b, 0);
s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -668,14 +668,14 @@ static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx)
spin_lock_irqsave(&dev->irqlock, flags);
src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
- src_y_addr = vb2_dma_contig_plane_paddr(src_mb->b, 0);
- src_c_addr = vb2_dma_contig_plane_paddr(src_mb->b, 1);
+ src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
+ src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
spin_unlock_irqrestore(&dev->irqlock, flags);
spin_lock_irqsave(&dev->irqlock, flags);
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
- dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
dst_size = vb2_plane_size(dst_mb->b, 0);
s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -703,8 +703,8 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
if (slice_type >= 0) {
s5p_mfc_get_enc_frame_buffer(ctx, &enc_y_addr, &enc_c_addr);
list_for_each_entry(mb_entry, &ctx->src_queue, list) {
- mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
- mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
+ mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
+ mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
if ((enc_y_addr == mb_y_addr) &&
(enc_c_addr == mb_c_addr)) {
list_del(&mb_entry->list);
@@ -715,8 +715,8 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
}
}
list_for_each_entry(mb_entry, &ctx->ref_queue, list) {
- mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
- mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
+ mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
+ mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
if ((enc_y_addr == mb_y_addr) &&
(enc_c_addr == mb_c_addr)) {
list_del(&mb_entry->list);
@@ -1501,20 +1501,20 @@ static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
return -EINVAL;
}
for (i = 0; i < fmt->num_planes; i++) {
- if (!vb2_dma_contig_plane_paddr(vb, i)) {
+ if (!vb2_dma_contig_plane_dma_addr(vb, i)) {
mfc_err("failed to get plane cookie\n");
return -EINVAL;
}
mfc_debug(2, "index: %d, plane[%d] cookie: 0x%08zx",
vb->v4l2_buf.index, i,
- vb2_dma_contig_plane_paddr(vb, i));
+ vb2_dma_contig_plane_dma_addr(vb, i));
}
return 0;
}
static int s5p_mfc_queue_setup(struct vb2_queue *vq,
unsigned int *buf_count, unsigned int *plane_count,
- unsigned long psize[], void *allocators[])
+ unsigned int psize[], void *allocators[])
{
struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
@@ -1584,7 +1584,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
i = vb->v4l2_buf.index;
ctx->dst_bufs[i].b = vb;
ctx->dst_bufs[i].cookie.stream =
- vb2_dma_contig_plane_paddr(vb, 0);
+ vb2_dma_contig_plane_dma_addr(vb, 0);
ctx->dst_bufs_cnt++;
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
ret = check_vb_with_fmt(ctx->src_fmt, vb);
@@ -1593,9 +1593,9 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
i = vb->v4l2_buf.index;
ctx->src_bufs[i].b = vb;
ctx->src_bufs[i].cookie.raw.luma =
- vb2_dma_contig_plane_paddr(vb, 0);
+ vb2_dma_contig_plane_dma_addr(vb, 0);
ctx->src_bufs[i].cookie.raw.chroma =
- vb2_dma_contig_plane_paddr(vb, 1);
+ vb2_dma_contig_plane_dma_addr(vb, 1);
ctx->src_bufs_cnt++;
} else {
mfc_err("inavlid queue type: %d\n", vq->type);
@@ -1640,7 +1640,7 @@ static int s5p_mfc_buf_prepare(struct vb2_buffer *vb)
return 0;
}
-static int s5p_mfc_start_streaming(struct vb2_queue *q)
+static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
struct s5p_mfc_dev *dev = ctx->dev;
@@ -1814,7 +1814,7 @@ int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx)
return ctx->ctrl_handler.error;
}
if (controls[i].is_volatile && ctx->ctrls[i])
- ctx->ctrls[i]->is_volatile = 1;
+ ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE;
}
return 0;
}
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
index 7b239168c199..e08b21c50ebf 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
@@ -1135,7 +1135,7 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
temp_vb->used = 1;
s5p_mfc_set_dec_stream_buffer(ctx,
- vb2_dma_contig_plane_paddr(temp_vb->b, 0), ctx->consumed_stream,
+ vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream,
temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
index = temp_vb->b->v4l2_buf.index;
@@ -1172,12 +1172,12 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
}
src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
src_mb->used = 1;
- src_y_addr = vb2_dma_contig_plane_paddr(src_mb->b, 0);
- src_c_addr = vb2_dma_contig_plane_paddr(src_mb->b, 1);
+ src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
+ src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
dst_mb->used = 1;
- dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
dst_size = vb2_plane_size(dst_mb->b, 0);
s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -1200,7 +1200,7 @@ static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
s5p_mfc_set_dec_desc_buffer(ctx);
mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
s5p_mfc_set_dec_stream_buffer(ctx,
- vb2_dma_contig_plane_paddr(temp_vb->b, 0),
+ vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
0, temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
@@ -1219,7 +1219,7 @@ static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
s5p_mfc_set_enc_ref_buffer(ctx);
spin_lock_irqsave(&dev->irqlock, flags);
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
- dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
dst_size = vb2_plane_size(dst_mb->b, 0);
s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -1255,7 +1255,7 @@ static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
s5p_mfc_set_dec_stream_buffer(ctx,
- vb2_dma_contig_plane_paddr(temp_vb->b, 0),
+ vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
0, temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
diff --git a/drivers/media/video/s5p-tv/Kconfig b/drivers/media/video/s5p-tv/Kconfig
index 9c37dee7bc59..f2a09779ec8f 100644
--- a/drivers/media/video/s5p-tv/Kconfig
+++ b/drivers/media/video/s5p-tv/Kconfig
@@ -8,7 +8,7 @@
config VIDEO_SAMSUNG_S5P_TV
bool "Samsung TV driver for S5P platform (experimental)"
- depends on PLAT_S5P
+ depends on PLAT_S5P && PM_RUNTIME
depends on EXPERIMENTAL
default n
---help---
diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/video/s5p-tv/hdmi_drv.c
index 06d6663f4594..0279e6e89feb 100644
--- a/drivers/media/video/s5p-tv/hdmi_drv.c
+++ b/drivers/media/video/s5p-tv/hdmi_drv.c
@@ -210,20 +210,17 @@ static void hdmi_reg_init(struct hdmi_device *hdev)
/* enable HPD interrupts */
hdmi_write_mask(hdev, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
- /* choose HDMI mode */
+ /* choose DVI mode */
hdmi_write_mask(hdev, HDMI_MODE_SEL,
- HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
+ HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
+ hdmi_write_mask(hdev, HDMI_CON_2, ~0,
+ HDMI_DVI_PERAMBLE_EN | HDMI_DVI_BAND_EN);
/* disable bluescreen */
hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
/* choose bluescreen (fecal) color */
hdmi_writeb(hdev, HDMI_BLUE_SCREEN_0, 0x12);
hdmi_writeb(hdev, HDMI_BLUE_SCREEN_1, 0x34);
hdmi_writeb(hdev, HDMI_BLUE_SCREEN_2, 0x56);
- /* enable AVI packet every vsync, fixes purple line problem */
- hdmi_writeb(hdev, HDMI_AVI_CON, 0x02);
- /* force YUV444, look to CEA-861-D, table 7 for more detail */
- hdmi_writeb(hdev, HDMI_AVI_BYTE(0), 2 << 5);
- hdmi_write_mask(hdev, HDMI_CON_1, 2, 3 << 5);
}
static void hdmi_timing_apply(struct hdmi_device *hdev,
@@ -443,6 +440,7 @@ static const struct hdmi_preset_conf hdmi_conf_480p = {
.height = 480,
.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
.field = V4L2_FIELD_NONE,
+ .colorspace = V4L2_COLORSPACE_SRGB,
},
};
@@ -475,6 +473,7 @@ static const struct hdmi_preset_conf hdmi_conf_720p60 = {
.height = 720,
.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
.field = V4L2_FIELD_NONE,
+ .colorspace = V4L2_COLORSPACE_SRGB,
},
};
@@ -507,6 +506,7 @@ static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
.height = 1080,
.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
.field = V4L2_FIELD_NONE,
+ .colorspace = V4L2_COLORSPACE_SRGB,
},
};
@@ -539,6 +539,7 @@ static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
.height = 1080,
.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
.field = V4L2_FIELD_NONE,
+ .colorspace = V4L2_COLORSPACE_SRGB,
},
};
diff --git a/drivers/media/video/s5p-tv/mixer.h b/drivers/media/video/s5p-tv/mixer.h
index e2242243f63d..51ad59b30358 100644
--- a/drivers/media/video/s5p-tv/mixer.h
+++ b/drivers/media/video/s5p-tv/mixer.h
@@ -111,8 +111,6 @@ struct mxr_buffer {
enum mxr_layer_state {
/** layers is not shown */
MXR_LAYER_IDLE = 0,
- /** state between STREAMON and hardware start */
- MXR_LAYER_STREAMING_START,
/** layer is shown */
MXR_LAYER_STREAMING,
/** state before STREAMOFF is finished */
diff --git a/drivers/media/video/s5p-tv/mixer_grp_layer.c b/drivers/media/video/s5p-tv/mixer_grp_layer.c
index 58f0ba49580f..de8270c2b6e7 100644
--- a/drivers/media/video/s5p-tv/mixer_grp_layer.c
+++ b/drivers/media/video/s5p-tv/mixer_grp_layer.c
@@ -86,7 +86,7 @@ static void mxr_graph_buffer_set(struct mxr_layer *layer,
dma_addr_t addr = 0;
if (buf)
- addr = vb2_dma_contig_plane_paddr(&buf->vb, 0);
+ addr = vb2_dma_contig_plane_dma_addr(&buf->vb, 0);
mxr_reg_graph_buffer(layer->mdev, layer->idx, addr);
}
diff --git a/drivers/media/video/s5p-tv/mixer_reg.c b/drivers/media/video/s5p-tv/mixer_reg.c
index 38dac672aa1c..4800a3cbb297 100644
--- a/drivers/media/video/s5p-tv/mixer_reg.c
+++ b/drivers/media/video/s5p-tv/mixer_reg.c
@@ -90,7 +90,7 @@ void mxr_reg_reset(struct mxr_device *mdev)
mxr_vsync_set_update(mdev, MXR_DISABLE);
/* set output in RGB888 mode */
- mxr_write(mdev, MXR_CFG, MXR_CFG_OUT_YUV444);
+ mxr_write(mdev, MXR_CFG, MXR_CFG_OUT_RGB888);
/* 16 beat burst in DMA */
mxr_write_mask(mdev, MXR_STATUS, MXR_STATUS_16_BURST,
@@ -376,6 +376,12 @@ void mxr_reg_set_mbus_fmt(struct mxr_device *mdev,
spin_lock_irqsave(&mdev->reg_slock, flags);
mxr_vsync_set_update(mdev, MXR_DISABLE);
+ /* selecting colorspace accepted by output */
+ if (fmt->colorspace == V4L2_COLORSPACE_JPEG)
+ val |= MXR_CFG_OUT_YUV444;
+ else
+ val |= MXR_CFG_OUT_RGB888;
+
/* choosing between interlace and progressive mode */
if (fmt->field == V4L2_FIELD_INTERLACED)
val |= MXR_CFG_SCAN_INTERLACE;
@@ -394,7 +400,8 @@ void mxr_reg_set_mbus_fmt(struct mxr_device *mdev,
else
WARN(1, "unrecognized mbus height %u!\n", fmt->height);
- mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_SCAN_MASK);
+ mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_SCAN_MASK |
+ MXR_CFG_OUT_MASK);
val = (fmt->field == V4L2_FIELD_INTERLACED) ? ~0 : 0;
vp_write_mask(mdev, VP_MODE, val,
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
index 43ac22f35bc7..4917e2c2b321 100644
--- a/drivers/media/video/s5p-tv/mixer_video.c
+++ b/drivers/media/video/s5p-tv/mixer_video.c
@@ -728,7 +728,7 @@ static const struct v4l2_file_operations mxr_fops = {
};
static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned long sizes[],
+ unsigned int *nplanes, unsigned int sizes[],
void *alloc_ctxs[])
{
struct mxr_layer *layer = vb2_get_drv_priv(vq);
@@ -764,19 +764,10 @@ static void buf_queue(struct vb2_buffer *vb)
struct mxr_layer *layer = vb2_get_drv_priv(vb->vb2_queue);
struct mxr_device *mdev = layer->mdev;
unsigned long flags;
- int must_start = 0;
spin_lock_irqsave(&layer->enq_slock, flags);
- if (layer->state == MXR_LAYER_STREAMING_START) {
- layer->state = MXR_LAYER_STREAMING;
- must_start = 1;
- }
list_add_tail(&buffer->list, &layer->enq_list);
spin_unlock_irqrestore(&layer->enq_slock, flags);
- if (must_start) {
- layer->ops.stream_set(layer, MXR_ENABLE);
- mxr_streamer_get(mdev);
- }
mxr_dbg(mdev, "queuing buffer\n");
}
@@ -797,13 +788,19 @@ static void wait_unlock(struct vb2_queue *vq)
mutex_unlock(&layer->mutex);
}
-static int start_streaming(struct vb2_queue *vq)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct mxr_layer *layer = vb2_get_drv_priv(vq);
struct mxr_device *mdev = layer->mdev;
unsigned long flags;
mxr_dbg(mdev, "%s\n", __func__);
+
+ if (count == 0) {
+ mxr_dbg(mdev, "no output buffers queued\n");
+ return -EINVAL;
+ }
+
/* block any changes in output configuration */
mxr_output_get(mdev);
@@ -814,9 +811,12 @@ static int start_streaming(struct vb2_queue *vq)
layer->ops.format_set(layer);
/* enabling layer in hardware */
spin_lock_irqsave(&layer->enq_slock, flags);
- layer->state = MXR_LAYER_STREAMING_START;
+ layer->state = MXR_LAYER_STREAMING;
spin_unlock_irqrestore(&layer->enq_slock, flags);
+ layer->ops.stream_set(layer, MXR_ENABLE);
+ mxr_streamer_get(mdev);
+
return 0;
}
diff --git a/drivers/media/video/s5p-tv/mixer_vp_layer.c b/drivers/media/video/s5p-tv/mixer_vp_layer.c
index 6950ed8ac1a0..f3bb2e34cb51 100644
--- a/drivers/media/video/s5p-tv/mixer_vp_layer.c
+++ b/drivers/media/video/s5p-tv/mixer_vp_layer.c
@@ -97,9 +97,9 @@ static void mxr_vp_buffer_set(struct mxr_layer *layer,
mxr_reg_vp_buffer(layer->mdev, luma_addr, chroma_addr);
return;
}
- luma_addr[0] = vb2_dma_contig_plane_paddr(&buf->vb, 0);
+ luma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb, 0);
if (layer->fmt->num_subframes == 2) {
- chroma_addr[0] = vb2_dma_contig_plane_paddr(&buf->vb, 1);
+ chroma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb, 1);
} else {
/* FIXME: mxr_get_plane_size compute integer division,
* which is slow and should not be performed in interrupt */
diff --git a/drivers/media/video/s5p-tv/regs-hdmi.h b/drivers/media/video/s5p-tv/regs-hdmi.h
index ac93ad6f2bc3..33247d13e4c0 100644
--- a/drivers/media/video/s5p-tv/regs-hdmi.h
+++ b/drivers/media/video/s5p-tv/regs-hdmi.h
@@ -127,6 +127,10 @@
#define HDMI_BLUE_SCR_EN (1 << 5)
#define HDMI_EN (1 << 0)
+/* HDMI_CON_2 */
+#define HDMI_DVI_PERAMBLE_EN (1 << 5)
+#define HDMI_DVI_BAND_EN (1 << 1)
+
/* HDMI_PHY_STATUS */
#define HDMI_PHY_STATUS_READY (1 << 0)
diff --git a/drivers/media/video/s5p-tv/regs-mixer.h b/drivers/media/video/s5p-tv/regs-mixer.h
index 3c8442609c1a..158abb43d0a4 100644
--- a/drivers/media/video/s5p-tv/regs-mixer.h
+++ b/drivers/media/video/s5p-tv/regs-mixer.h
@@ -67,6 +67,7 @@
/* bits for MXR_CFG */
#define MXR_CFG_OUT_YUV444 (0 << 8)
#define MXR_CFG_OUT_RGB888 (1 << 8)
+#define MXR_CFG_OUT_MASK (1 << 8)
#define MXR_CFG_DST_SDO (0 << 7)
#define MXR_CFG_DST_HDMI (1 << 7)
#define MXR_CFG_DST_MASK (1 << 7)
diff --git a/drivers/media/video/s5p-tv/sdo_drv.c b/drivers/media/video/s5p-tv/sdo_drv.c
index 4dddd6bd635b..8cec67ef48c9 100644
--- a/drivers/media/video/s5p-tv/sdo_drv.c
+++ b/drivers/media/video/s5p-tv/sdo_drv.c
@@ -170,6 +170,7 @@ static int sdo_g_mbus_fmt(struct v4l2_subdev *sd,
fmt->height = sdev->fmt->height;
fmt->code = V4L2_MBUS_FMT_FIXED;
fmt->field = V4L2_FIELD_INTERLACED;
+ fmt->colorspace = V4L2_COLORSPACE_JPEG;
return 0;
}
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index f2ae405c74ac..5cfdbc78b918 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -793,7 +793,6 @@ static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
else
saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
- v4l2_ctrl_activate(state->gain, !state->agc->val);
break;
default:
@@ -1345,35 +1344,57 @@ static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_dat
static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
{
struct saa711x_state *state = to_state(sd);
- int reg1e;
+ int reg1f, reg1e;
- *std = V4L2_STD_ALL;
- if (state->ident != V4L2_IDENT_SAA7115) {
- int reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+ /*
+ * The V4L2 core already initializes std with all supported
+ * Standards. All driver needs to do is to mask it, to remove
+ * standards that don't apply from the mask
+ */
- if (reg1f & 0x20)
- *std = V4L2_STD_525_60;
- else
- *std = V4L2_STD_625_50;
+ reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+ v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
- return 0;
- }
+ /* horizontal/vertical not locked */
+ if (reg1f & 0x40)
+ goto ret;
+
+ if (reg1f & 0x20)
+ *std &= V4L2_STD_525_60;
+ else
+ *std &= V4L2_STD_625_50;
+
+ if (state->ident != V4L2_IDENT_SAA7115)
+ goto ret;
reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
switch (reg1e & 0x03) {
case 1:
- *std = V4L2_STD_NTSC;
+ *std &= V4L2_STD_NTSC;
break;
case 2:
- *std = V4L2_STD_PAL;
+ /*
+ * V4L2_STD_PAL just cover the european PAL standards.
+ * This is wrong, as the device could also be using an
+ * other PAL standard.
+ */
+ *std &= V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc |
+ V4L2_STD_PAL_M | V4L2_STD_PAL_60;
break;
case 3:
- *std = V4L2_STD_SECAM;
+ *std &= V4L2_STD_SECAM;
break;
default:
+ /* Can't detect anything */
break;
}
+
+ v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
+
+ret:
+ v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
+
return 0;
}
@@ -1601,7 +1622,6 @@ static int saa711x_probe(struct i2c_client *client,
V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
- state->gain->is_volatile = 1;
sd->ctrl_handler = hdl;
if (hdl->error) {
int err = hdl->error;
@@ -1610,8 +1630,7 @@ static int saa711x_probe(struct i2c_client *client,
kfree(state);
return err;
}
- state->agc->flags |= V4L2_CTRL_FLAG_UPDATE;
- v4l2_ctrl_cluster(2, &state->agc);
+ v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
state->input = -1;
state->output = SAA7115_IPORT_ON;
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index 8a5ff4d3cf15..a646ccf51696 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/saa7164/Makefile b/drivers/media/video/saa7164/Makefile
index 6303a8e60eac..ecd5811dc486 100644
--- a/drivers/media/video/saa7164/Makefile
+++ b/drivers/media/video/saa7164/Makefile
@@ -4,9 +4,9 @@ saa7164-objs := saa7164-cards.o saa7164-core.o saa7164-i2c.o saa7164-dvb.o \
obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/saa7164/saa7164-cards.c b/drivers/media/video/saa7164/saa7164-cards.c
index 69822a4e7275..971591d6450f 100644
--- a/drivers/media/video/saa7164/saa7164-cards.c
+++ b/drivers/media/video/saa7164/saa7164-cards.c
@@ -203,6 +203,66 @@ struct saa7164_board saa7164_boards[] = {
.i2c_reg_len = REGLEN_8bit,
} },
},
+ [SAA7164_BOARD_HAUPPAUGE_HVR2200_4] = {
+ .name = "Hauppauge WinTV-HVR2200",
+ .porta = SAA7164_MPEG_DVB,
+ .portb = SAA7164_MPEG_DVB,
+ .portc = SAA7164_MPEG_ENCODER,
+ .portd = SAA7164_MPEG_ENCODER,
+ .porte = SAA7164_MPEG_VBI,
+ .portf = SAA7164_MPEG_VBI,
+ .chiprev = SAA7164_CHIP_REV3,
+ .unit = {{
+ .id = 0x1d,
+ .type = SAA7164_UNIT_EEPROM,
+ .name = "4K EEPROM",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xa0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x04,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "TDA18271-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x05,
+ .type = SAA7164_UNIT_ANALOG_DEMODULATOR,
+ .name = "TDA8290-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0x84 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x1b,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "TDA18271-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x1c,
+ .type = SAA7164_UNIT_ANALOG_DEMODULATOR,
+ .name = "TDA8290-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0x84 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x1e,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "TDA10048-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0x10 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x1f,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "TDA10048-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0x12 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ } },
+ },
[SAA7164_BOARD_HAUPPAUGE_HVR2250] = {
.name = "Hauppauge WinTV-HVR2250",
.porta = SAA7164_MPEG_DVB,
@@ -387,6 +447,62 @@ struct saa7164_board saa7164_boards[] = {
.i2c_reg_len = REGLEN_8bit,
} },
},
+ [SAA7164_BOARD_HAUPPAUGE_HVR2200_5] = {
+ .name = "Hauppauge WinTV-HVR2200",
+ .porta = SAA7164_MPEG_DVB,
+ .portb = SAA7164_MPEG_DVB,
+ .chiprev = SAA7164_CHIP_REV3,
+ .unit = {{
+ .id = 0x23,
+ .type = SAA7164_UNIT_EEPROM,
+ .name = "4K EEPROM",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xa0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x04,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "TDA18271-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x05,
+ .type = SAA7164_UNIT_ANALOG_DEMODULATOR,
+ .name = "TDA8290-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0x84 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x21,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "TDA18271-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x22,
+ .type = SAA7164_UNIT_ANALOG_DEMODULATOR,
+ .name = "TDA8290-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0x84 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x24,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "TDA10048-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0x10 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x25,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "TDA10048-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0x12 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ } },
+ },
};
const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
@@ -426,6 +542,14 @@ struct saa7164_subid saa7164_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x8851,
.card = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x8940,
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_4,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x8953,
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2200_5,
},
};
const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
@@ -469,6 +593,8 @@ void saa7164_gpio_setup(struct saa7164_dev *dev)
case SAA7164_BOARD_HAUPPAUGE_HVR2200:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
case SAA7164_BOARD_HAUPPAUGE_HVR2250:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
@@ -549,6 +675,8 @@ void saa7164_card_setup(struct saa7164_dev *dev)
case SAA7164_BOARD_HAUPPAUGE_HVR2200:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
case SAA7164_BOARD_HAUPPAUGE_HVR2250:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
diff --git a/drivers/media/video/saa7164/saa7164-dvb.c b/drivers/media/video/saa7164/saa7164-dvb.c
index f65eab63ca87..5c5cc3ebf9bd 100644
--- a/drivers/media/video/saa7164/saa7164-dvb.c
+++ b/drivers/media/video/saa7164/saa7164-dvb.c
@@ -475,6 +475,8 @@ int saa7164_dvb_register(struct saa7164_port *port)
case SAA7164_BOARD_HAUPPAUGE_HVR2200:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
i2c_bus = &dev->i2c_bus[port->nr + 1];
switch (port->nr) {
case 0:
diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h
index 6678bf1e7816..742b34103b5d 100644
--- a/drivers/media/video/saa7164/saa7164.h
+++ b/drivers/media/video/saa7164/saa7164.h
@@ -82,6 +82,8 @@
#define SAA7164_BOARD_HAUPPAUGE_HVR2200_3 6
#define SAA7164_BOARD_HAUPPAUGE_HVR2250_2 7
#define SAA7164_BOARD_HAUPPAUGE_HVR2250_3 8
+#define SAA7164_BOARD_HAUPPAUGE_HVR2200_4 9
+#define SAA7164_BOARD_HAUPPAUGE_HVR2200_5 10
#define SAA7164_MAX_UNITS 8
#define SAA7164_TS_NUMBER_OF_LINES 312
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index e54089802b6b..8615fb81775f 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -218,7 +218,7 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev)
*/
static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
unsigned int *count, unsigned int *num_planes,
- unsigned long sizes[], void *alloc_ctxs[])
+ unsigned int sizes[], void *alloc_ctxs[])
{
struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -243,7 +243,7 @@ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
*count = pcdev->video_limit / PAGE_ALIGN(sizes[0]);
}
- dev_dbg(icd->parent, "count=%d, size=%lu\n", *count, sizes[0]);
+ dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]);
return 0;
}
@@ -312,7 +312,7 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
bottom2 = CDBCR;
}
- phys_addr_top = vb2_dma_contig_plane_paddr(pcdev->active, 0);
+ phys_addr_top = vb2_dma_contig_plane_dma_addr(pcdev->active, 0);
ceu_write(pcdev, top1, phys_addr_top);
if (V4L2_FIELD_NONE != pcdev->field) {
diff --git a/drivers/media/video/sr030pc30.c b/drivers/media/video/sr030pc30.c
index 8afb0e8a2e00..10aff3f943a8 100644
--- a/drivers/media/video/sr030pc30.c
+++ b/drivers/media/video/sr030pc30.c
@@ -714,11 +714,6 @@ static int sr030pc30_base_config(struct v4l2_subdev *sd)
return ret;
}
-static int sr030pc30_s_stream(struct v4l2_subdev *sd, int enable)
-{
- return 0;
-}
-
static int sr030pc30_s_power(struct v4l2_subdev *sd, int on)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -764,7 +759,6 @@ static const struct v4l2_subdev_core_ops sr030pc30_core_ops = {
};
static const struct v4l2_subdev_video_ops sr030pc30_video_ops = {
- .s_stream = sr030pc30_s_stream,
.g_mbus_fmt = sr030pc30_g_fmt,
.s_mbus_fmt = sr030pc30_s_fmt,
.try_mbus_fmt = sr030pc30_try_fmt,
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
index d1a2cefbf55b..cbc105f975de 100644
--- a/drivers/media/video/stk-webcam.c
+++ b/drivers/media/video/stk-webcam.c
@@ -55,6 +55,8 @@ MODULE_AUTHOR("Jaime Velasco Juan <jsagarribay@gmail.com> and Nicolas VIVIEN");
MODULE_DESCRIPTION("Syntek DC1125 webcam driver");
+/* bool for webcam LED management */
+int first_init = 1;
/* Some cameras have audio interfaces, we aren't interested in those */
static struct usb_device_id stkwebcam_table[] = {
@@ -518,7 +520,7 @@ static int stk_prepare_sio_buffers(struct stk_camera *dev, unsigned n_sbufs)
return -ENOMEM;
for (i = 0; i < n_sbufs; i++) {
if (stk_setup_siobuf(dev, i))
- return (dev->n_sbufs > 1)? 0 : -ENOMEM;
+ return (dev->n_sbufs > 1 ? 0 : -ENOMEM);
dev->n_sbufs = i+1;
}
}
@@ -558,9 +560,14 @@ static int v4l_stk_open(struct file *fp)
vdev = video_devdata(fp);
dev = vdev_to_camera(vdev);
- if (dev == NULL || !is_present(dev)) {
+ if (dev == NULL || !is_present(dev))
return -ENXIO;
- }
+
+ if (!first_init)
+ stk_camera_write_reg(dev, 0x0, 0x24);
+ else
+ first_init = 0;
+
fp->private_data = dev;
usb_autopm_get_interface(dev->interface);
@@ -574,10 +581,12 @@ static int v4l_stk_release(struct file *fp)
if (dev->owner == fp) {
stk_stop_stream(dev);
stk_free_buffers(dev);
+ stk_camera_write_reg(dev, 0x0, 0x49); /* turn off the LED */
+ unset_initialised(dev);
dev->owner = NULL;
}
- if(is_present(dev))
+ if (is_present(dev))
usb_autopm_put_interface(dev->interface);
return 0;
@@ -654,7 +663,7 @@ static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait)
return POLLERR;
if (!list_empty(&dev->sio_full))
- return (POLLIN | POLLRDNORM);
+ return POLLIN | POLLRDNORM;
return 0;
}
@@ -891,9 +900,9 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
struct stk_camera *dev = priv;
int i;
- for (i = 0; i < ARRAY_SIZE(stk_sizes)
- && stk_sizes[i].m != dev->vsettings.mode;
- i++);
+ for (i = 0; i < ARRAY_SIZE(stk_sizes) &&
+ stk_sizes[i].m != dev->vsettings.mode; i++)
+ ;
if (i == ARRAY_SIZE(stk_sizes)) {
STK_ERROR("ERROR: mode invalid\n");
return -EINVAL;
@@ -1305,9 +1314,8 @@ static int stk_camera_probe(struct usb_interface *interface,
usb_set_intfdata(interface, dev);
err = stk_register_video_device(dev);
- if (err) {
+ if (err)
goto error;
- }
return 0;
@@ -1350,6 +1358,7 @@ static int stk_camera_resume(struct usb_interface *intf)
return 0;
unset_initialised(dev);
stk_initialise(dev);
+ stk_camera_write_reg(dev, 0x0, 0x49);
stk_setup_format(dev);
if (is_streaming(dev))
stk_start_stream(dev);
diff --git a/drivers/media/video/tlg2300/Makefile b/drivers/media/video/tlg2300/Makefile
index 81bb7fdd1e3d..ea09b9af2d30 100644
--- a/drivers/media/video/tlg2300/Makefile
+++ b/drivers/media/video/tlg2300/Makefile
@@ -2,8 +2,8 @@ poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o
obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/staging/tm6000/Kconfig b/drivers/media/video/tm6000/Kconfig
index 114eec8a630a..114eec8a630a 100644
--- a/drivers/staging/tm6000/Kconfig
+++ b/drivers/media/video/tm6000/Kconfig
diff --git a/drivers/staging/tm6000/Makefile b/drivers/media/video/tm6000/Makefile
index 395515b4a888..395515b4a888 100644
--- a/drivers/staging/tm6000/Makefile
+++ b/drivers/media/video/tm6000/Makefile
diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/media/video/tm6000/tm6000-alsa.c
index bd5fa89af07c..7d675c72fd47 100644
--- a/drivers/staging/tm6000/tm6000-alsa.c
+++ b/drivers/media/video/tm6000/tm6000-alsa.c
@@ -80,7 +80,7 @@ static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip)
dprintk(1, "Starting audio DMA\n");
/* Enables audio */
- tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0x40, 0x40);
+ tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x40, 0x40);
tm6000_set_audio_bitrate(core, 48000);
@@ -97,7 +97,7 @@ static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip)
dprintk(1, "Stopping audio DMA\n");
/* Disables audio */
- tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0x00, 0x40);
+ tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x00, 0x40);
return 0;
}
@@ -304,6 +304,7 @@ static int snd_tm6000_hw_free(struct snd_pcm_substream *substream)
schedule_work(&core->wq_trigger);
}
+ dsp_buffer_free(substream);
return 0;
}
@@ -397,7 +398,7 @@ static struct snd_pcm_ops snd_tm6000_pcm_ops = {
/*
* Alsa Constructor - Component probe
*/
-int tm6000_audio_init(struct tm6000_core *dev)
+static int tm6000_audio_init(struct tm6000_core *dev)
{
struct snd_card *card;
struct snd_tm6000_card *chip;
@@ -490,7 +491,7 @@ static int tm6000_audio_fini(struct tm6000_core *dev)
return 0;
}
-struct tm6000_ops audio_ops = {
+static struct tm6000_ops audio_ops = {
.type = TM6000_AUDIO,
.name = "TM6000 Audio Extension",
.init = tm6000_audio_init,
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/media/video/tm6000/tm6000-cards.c
index 9227db5d8955..ec2578a0fdf7 100644
--- a/drivers/staging/tm6000/tm6000-cards.c
+++ b/drivers/media/video/tm6000/tm6000-cards.c
@@ -87,7 +87,7 @@ struct tm6000_board {
char *ir_codes;
};
-struct tm6000_board tm6000_boards[] = {
+static struct tm6000_board tm6000_boards[] = {
[TM6000_BOARD_UNKNOWN] = {
.name = "Unknown tm6000 video grabber",
.caps = {
@@ -394,7 +394,7 @@ struct tm6000_board tm6000_boards[] = {
.has_zl10353 = 1,
.has_eeprom = 1,
.has_remote = 1,
- .has_radio = 1.
+ .has_radio = 1,
},
.gpio = {
.tuner_reset = TM6010_GPIO_0,
@@ -468,6 +468,7 @@ struct tm6000_board tm6000_boards[] = {
.has_zl10353 = 1,
.has_eeprom = 1,
.has_remote = 1,
+ .has_radio = 1,
},
.gpio = {
.tuner_reset = TM6010_GPIO_2,
@@ -493,6 +494,10 @@ struct tm6000_board tm6000_boards[] = {
.amux = TM6000_AMUX_ADC2,
},
},
+ .rinput = {
+ .type = TM6000_INPUT_RADIO,
+ .amux = TM6000_AMUX_SIF1,
+ },
},
[TM5600_BOARD_TERRATEC_GRABSTER] = {
.name = "Terratec Grabster AV 150/250 MX",
@@ -611,7 +616,7 @@ struct tm6000_board tm6000_boards[] = {
};
/* table of devices that work with this driver */
-struct usb_device_id tm6000_id_table[] = {
+static struct usb_device_id tm6000_id_table[] = {
{ USB_DEVICE(0x6000, 0x0001), .driver_info = TM5600_BOARD_GENERIC },
{ USB_DEVICE(0x6000, 0x0002), .driver_info = TM6010_BOARD_GENERIC },
{ USB_DEVICE(0x06e1, 0xf332), .driver_info = TM6000_BOARD_ADSTECH_DUAL_TV },
@@ -632,7 +637,7 @@ struct usb_device_id tm6000_id_table[] = {
{ USB_DEVICE(0x13d3, 0x3264), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
{ USB_DEVICE(0x6000, 0xdec2), .driver_info = TM6010_BOARD_BEHOLD_WANDER_LITE },
{ USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE },
- { },
+ { }
};
/* Control power led for show some activity */
@@ -780,6 +785,11 @@ int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
rc = tm6000_i2c_reset(dev, 100);
break;
}
+ break;
+ case XC2028_I2C_FLUSH:
+ tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
+ tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
+ break;
}
return rc;
}
@@ -787,8 +797,6 @@ EXPORT_SYMBOL_GPL(tm6000_tuner_callback);
int tm6000_cards_setup(struct tm6000_core *dev)
{
- int i, rc;
-
/*
* Board-specific initialization sequence. Handles all GPIO
* initialization sequences that are board-specific.
@@ -860,6 +868,9 @@ int tm6000_cards_setup(struct tm6000_core *dev)
*/
if (dev->gpio.tuner_reset) {
+ int rc;
+ int i;
+
for (i = 0; i < 2; i++) {
rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
dev->gpio.tuner_reset, 0x00);
@@ -988,6 +999,16 @@ static int fill_board_specific_data(struct tm6000_core *dev)
dev->vinput[2] = tm6000_boards[dev->model].vinput[2];
dev->rinput = tm6000_boards[dev->model].rinput;
+ /* setup per-model quirks */
+ switch (dev->model) {
+ case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+ dev->quirks |= TM6000_QUIRK_NO_USB_DELAY;
+ break;
+
+ default:
+ break;
+ }
+
/* initialize hardware */
rc = tm6000_init(dev);
if (rc < 0)
@@ -1162,13 +1183,14 @@ static int tm6000_usb_probe(struct usb_interface *interface,
return -ENOMEM;
}
spin_lock_init(&dev->slock);
+ mutex_init(&dev->usb_lock);
/* Increment usage count */
- tm6000_devused |= 1<<nr;
+ set_bit(nr, &tm6000_devused);
snprintf(dev->name, 29, "tm6000 #%d", nr);
dev->model = id->driver_info;
- if ((card[nr] >= 0) && (card[nr] < ARRAY_SIZE(tm6000_boards)))
+ if (card[nr] < ARRAY_SIZE(tm6000_boards))
dev->model = card[nr];
dev->udev = usbdev;
@@ -1189,8 +1211,6 @@ static int tm6000_usb_probe(struct usb_interface *interface,
speed = "unknown";
}
-
-
/* Get endpoints */
for (i = 0; i < interface->num_altsetting; i++) {
int ep;
@@ -1274,7 +1294,6 @@ static int tm6000_usb_probe(struct usb_interface *interface,
printk(KERN_INFO "tm6000: Found %s\n", tm6000_boards[dev->model].name);
rc = tm6000_init_dev(dev);
-
if (rc < 0)
goto err;
@@ -1283,7 +1302,7 @@ static int tm6000_usb_probe(struct usb_interface *interface,
err:
printk(KERN_ERR "tm6000: Error %d while registering\n", rc);
- tm6000_devused &= ~(1<<nr);
+ clear_bit(nr, &tm6000_devused);
usb_put_dev(usbdev);
kfree(dev);
@@ -1341,6 +1360,7 @@ static void tm6000_usb_disconnect(struct usb_interface *interface)
tm6000_close_extension(dev);
tm6000_remove_from_devlist(dev);
+ clear_bit(dev->devno, &tm6000_devused);
kfree(dev);
}
diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c
index d7eb2e23cdbd..9783616a0da2 100644
--- a/drivers/staging/tm6000/tm6000-core.c
+++ b/drivers/media/video/tm6000/tm6000-core.c
@@ -39,10 +39,11 @@ int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
unsigned int pipe;
u8 *data = NULL;
+ mutex_lock(&dev->usb_lock);
+
if (len)
data = kzalloc(len, GFP_KERNEL);
-
if (req_type & USB_DIR_IN)
pipe = usb_rcvctrlpipe(dev->udev, 0);
else {
@@ -51,18 +52,18 @@ int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
}
if (tm6000_debug & V4L2_DEBUG_I2C) {
- printk("(dev %p, pipe %08x): ", dev->udev, pipe);
+ printk(KERN_DEBUG "(dev %p, pipe %08x): ", dev->udev, pipe);
- printk("%s: %02x %02x %02x %02x %02x %02x %02x %02x ",
+ printk(KERN_CONT "%s: %02x %02x %02x %02x %02x %02x %02x %02x ",
(req_type & USB_DIR_IN) ? " IN" : "OUT",
req_type, req, value&0xff, value>>8, index&0xff,
index>>8, len&0xff, len>>8);
if (!(req_type & USB_DIR_IN)) {
- printk(">>> ");
+ printk(KERN_CONT ">>> ");
for (i = 0; i < len; i++)
- printk(" %02x", buf[i]);
- printk("\n");
+ printk(KERN_CONT " %02x", buf[i]);
+ printk(KERN_CONT "\n");
}
}
@@ -75,21 +76,21 @@ int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
if (tm6000_debug & V4L2_DEBUG_I2C) {
if (ret < 0) {
if (req_type & USB_DIR_IN)
- printk("<<< (len=%d)\n", len);
+ printk(KERN_DEBUG "<<< (len=%d)\n", len);
- printk("%s: Error #%d\n", __FUNCTION__, ret);
+ printk(KERN_CONT "%s: Error #%d\n", __func__, ret);
} else if (req_type & USB_DIR_IN) {
- printk("<<< ");
+ printk(KERN_CONT "<<< ");
for (i = 0; i < len; i++)
- printk(" %02x", buf[i]);
- printk("\n");
+ printk(KERN_CONT " %02x", buf[i]);
+ printk(KERN_CONT "\n");
}
}
kfree(data);
-
msleep(5);
+ mutex_unlock(&dev->usb_lock);
return ret;
}
@@ -188,11 +189,11 @@ void tm6000_set_fourcc_format(struct tm6000_core *dev)
if (dev->dev_type == TM6010) {
int val;
- val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0) & 0xfc;
+ val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, 0) & 0xfc;
if (dev->fourcc == V4L2_PIX_FMT_UYVY)
- tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val);
+ tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val);
else
- tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val | 1);
+ tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val | 1);
} else {
if (dev->fourcc == V4L2_PIX_FMT_UYVY)
tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
@@ -268,9 +269,14 @@ int tm6000_init_analog_mode(struct tm6000_core *dev)
struct v4l2_frequency f;
if (dev->dev_type == TM6010) {
+ u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE;
+
+ if (!dev->radio)
+ active |= TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE;
+
/* Enable video and audio */
- tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF,
- 0x60, 0x60);
+ tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
+ active, 0x60);
/* Disable TS input */
tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
0x00, 0x40);
@@ -308,7 +314,7 @@ int tm6000_init_analog_mode(struct tm6000_core *dev)
* FIXME: This is a hack! xc3028 "sleeps" when no channel is detected
* for more than a few seconds. Not sure why, as this behavior does
* not happen on other devices with xc3028. So, I suspect that it
- * is yet another bug at tm6000. After start sleeping, decoding
+ * is yet another bug at tm6000. After start sleeping, decoding
* doesn't start automatically. Instead, it requires some
* I2C commands to wake it up. As we want to have image at the
* beginning, we needed to add this hack. The better would be to
@@ -335,7 +341,7 @@ int tm6000_init_digital_mode(struct tm6000_core *dev)
{
if (dev->dev_type == TM6010) {
/* Disable video and audio */
- tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF,
+ tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
0x00, 0x60);
/* Enable TS input */
tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
@@ -390,7 +396,7 @@ struct reg_init {
};
/* The meaning of those initializations are unknown */
-struct reg_init tm6000_init_tab[] = {
+static struct reg_init tm6000_init_tab[] = {
/* REG VALUE */
{ TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f },
{ TM6010_REQ07_RFF_SOFT_RESET, 0x08 },
@@ -458,12 +464,12 @@ struct reg_init tm6000_init_tab[] = {
{ TM6010_REQ05_R18_IMASK7, 0x00 },
};
-struct reg_init tm6010_init_tab[] = {
+static struct reg_init tm6010_init_tab[] = {
{ TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 },
{ TM6010_REQ07_RC4_HSTART0, 0xa0 },
{ TM6010_REQ07_RC6_HEND0, 0x40 },
{ TM6010_REQ07_RCA_VEND0, 0x31 },
- { TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0xe1 },
+ { TM6010_REQ07_RCC_ACTIVE_IF, 0xe1 },
{ TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 },
{ TM6010_REQ07_RFE_POWER_DOWN, 0x7f },
@@ -593,6 +599,56 @@ int tm6000_init(struct tm6000_core *dev)
return rc;
}
+int tm6000_reset(struct tm6000_core *dev)
+{
+ int pipe;
+ int err;
+
+ msleep(500);
+
+ err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 0);
+ if (err < 0) {
+ tm6000_err("failed to select interface %d, alt. setting 0\n",
+ dev->isoc_in.bInterfaceNumber);
+ return err;
+ }
+
+ err = usb_reset_configuration(dev->udev);
+ if (err < 0) {
+ tm6000_err("failed to reset configuration\n");
+ return err;
+ }
+
+ if ((dev->quirks & TM6000_QUIRK_NO_USB_DELAY) == 0)
+ msleep(5);
+
+ /*
+ * Not all devices have int_in defined
+ */
+ if (!dev->int_in.endp)
+ return 0;
+
+ err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2);
+ if (err < 0) {
+ tm6000_err("failed to select interface %d, alt. setting 2\n",
+ dev->isoc_in.bInterfaceNumber);
+ return err;
+ }
+
+ msleep(5);
+
+ pipe = usb_rcvintpipe(dev->udev,
+ dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+
+ err = usb_clear_halt(dev->udev, pipe);
+ if (err < 0) {
+ tm6000_err("usb_clear_halt failed: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
{
int val = 0;
@@ -687,7 +743,7 @@ int tm6000_set_audio_rinput(struct tm6000_core *dev)
return 0;
}
-void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
+static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
{
u8 mute_reg = 0;
@@ -697,7 +753,7 @@ void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08);
}
-void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute)
+static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute)
{
u8 mute_reg = 0;
@@ -749,7 +805,7 @@ int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute)
return 0;
}
-void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
+static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
{
u8 vol_reg;
@@ -762,7 +818,7 @@ void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg);
}
-void tm6010_set_volume_adc(struct tm6000_core *dev, int vol)
+static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol)
{
u8 vol_reg;
diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/media/video/tm6000/tm6000-dvb.c
index 0e0dfce05821..5e6c129a4beb 100644
--- a/drivers/staging/tm6000/tm6000-dvb.c
+++ b/drivers/media/video/tm6000/tm6000-dvb.c
@@ -105,7 +105,7 @@ static void tm6000_urb_received(struct urb *urb)
}
}
-int tm6000_start_stream(struct tm6000_core *dev)
+static int tm6000_start_stream(struct tm6000_core *dev)
{
int ret;
unsigned int pipe, size;
@@ -166,7 +166,7 @@ int tm6000_start_stream(struct tm6000_core *dev)
return 0;
}
-void tm6000_stop_stream(struct tm6000_core *dev)
+static void tm6000_stop_stream(struct tm6000_core *dev)
{
struct tm6000_dvb *dvb = dev->dvb;
@@ -180,7 +180,7 @@ void tm6000_stop_stream(struct tm6000_core *dev)
}
}
-int tm6000_start_feed(struct dvb_demux_feed *feed)
+static int tm6000_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct tm6000_core *dev = demux->priv;
@@ -199,7 +199,7 @@ int tm6000_start_feed(struct dvb_demux_feed *feed)
return 0;
}
-int tm6000_stop_feed(struct dvb_demux_feed *feed)
+static int tm6000_stop_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct tm6000_core *dev = demux->priv;
@@ -222,7 +222,7 @@ int tm6000_stop_feed(struct dvb_demux_feed *feed)
return 0;
}
-int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
+static int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
{
struct tm6000_dvb *dvb = dev->dvb;
@@ -247,7 +247,7 @@ int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-int register_dvb(struct tm6000_core *dev)
+static int register_dvb(struct tm6000_core *dev)
{
int ret = -1;
struct tm6000_dvb *dvb = dev->dvb;
@@ -330,7 +330,7 @@ int register_dvb(struct tm6000_core *dev)
dvb->demux.write_to_decoder = NULL;
ret = dvb_dmx_init(&dvb->demux);
if (ret < 0) {
- printk("tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
+ printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
goto frontend_err;
}
@@ -340,7 +340,7 @@ int register_dvb(struct tm6000_core *dev)
ret = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
if (ret < 0) {
- printk("tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
+ printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
goto dvb_dmx_err;
}
@@ -359,7 +359,7 @@ err:
return ret;
}
-void unregister_dvb(struct tm6000_core *dev)
+static void unregister_dvb(struct tm6000_core *dev)
{
struct tm6000_dvb *dvb = dev->dvb;
diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/media/video/tm6000/tm6000-i2c.c
index 5a651ea5f60a..0290bbf00c3e 100644
--- a/drivers/staging/tm6000/tm6000-i2c.c
+++ b/drivers/media/video/tm6000/tm6000-i2c.c
@@ -189,7 +189,7 @@ static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
/* 1 or 2 byte write followed by a read */
if (i2c_debug >= 2)
for (byte = 0; byte < msgs[i].len; byte++)
- printk(" %02x", msgs[i].buf[byte]);
+ printk(KERN_CONT " %02x", msgs[i].buf[byte]);
i2c_dprintk(2, "; joined to read %s len=%d:",
i == num - 2 ? "stop" : "nonstop",
msgs[i + 1].len);
@@ -211,22 +211,17 @@ static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
}
if (i2c_debug >= 2)
for (byte = 0; byte < msgs[i].len; byte++)
- printk(" %02x", msgs[i].buf[byte]);
+ printk(KERN_CONT " %02x", msgs[i].buf[byte]);
} else {
/* write bytes */
if (i2c_debug >= 2)
for (byte = 0; byte < msgs[i].len; byte++)
- printk(" %02x", msgs[i].buf[byte]);
+ printk(KERN_CONT " %02x", msgs[i].buf[byte]);
rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0],
msgs[i].buf + 1, msgs[i].len - 1);
-
- if (addr == dev->tuner_addr << 1) {
- tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
- tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
- }
}
if (i2c_debug >= 2)
- printk("\n");
+ printk(KERN_CONT "\n");
if (rc < 0)
goto err;
}
@@ -264,7 +259,7 @@ static int tm6000_i2c_eeprom(struct tm6000_core *dev)
p++;
if (0 == (i % 16))
printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
- printk(" %02x", dev->eedata[i]);
+ printk(KERN_CONT " %02x", dev->eedata[i]);
if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z'))
bytes[i%16] = dev->eedata[i];
else
@@ -274,14 +269,14 @@ static int tm6000_i2c_eeprom(struct tm6000_core *dev)
if (0 == (i % 16)) {
bytes[16] = '\0';
- printk(" %s\n", bytes);
+ printk(KERN_CONT " %s\n", bytes);
}
}
if (0 != (i%16)) {
bytes[i%16] = '\0';
for (i %= 16; i < 16; i++)
- printk(" ");
- printk(" %s\n", bytes);
+ printk(KERN_CONT " ");
+ printk(KERN_CONT " %s\n", bytes);
}
return 0;
diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c
index 70a2c5f557c1..405d12729d05 100644
--- a/drivers/staging/tm6000/tm6000-input.c
+++ b/drivers/media/video/tm6000/tm6000-input.c
@@ -284,7 +284,7 @@ static void tm6000_ir_stop(struct rc_dev *rc)
cancel_delayed_work_sync(&ir->work);
}
-int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
{
struct tm6000_IR *ir = rc->priv;
diff --git a/drivers/staging/tm6000/tm6000-regs.h b/drivers/media/video/tm6000/tm6000-regs.h
index 5375a8347374..7f491b6de933 100644
--- a/drivers/staging/tm6000/tm6000-regs.h
+++ b/drivers/media/video/tm6000/tm6000-regs.h
@@ -90,7 +90,7 @@
*/
enum {
- TM6000_URB_MSG_VIDEO=1,
+ TM6000_URB_MSG_VIDEO = 1,
TM6000_URB_MSG_AUDIO,
TM6000_URB_MSG_VBI,
TM6000_URB_MSG_PTS,
@@ -270,7 +270,9 @@ enum {
#define TM6010_REQ07_RCA_VEND0 0x07, 0xca
#define TM6010_REQ07_RCB_DELAY 0x07, 0xcb
/* ONLY for TM6010 */
-#define TM6010_REQ07_RCC_ACTIVE_VIDEO_IF 0x07, 0xcc
+#define TM6010_REQ07_RCC_ACTIVE_IF 0x07, 0xcc
+#define TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE (1 << 5)
+#define TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE (1 << 6)
#define TM6010_REQ07_RD0_USB_PERIPHERY_CONTROL 0x07, 0xd0
#define TM6010_REQ07_RD1_ADDR_FOR_REQ1 0x07, 0xd1
#define TM6010_REQ07_RD2_ADDR_FOR_REQ2 0x07, 0xd2
diff --git a/drivers/media/video/tm6000/tm6000-stds.c b/drivers/media/video/tm6000/tm6000-stds.c
new file mode 100644
index 000000000000..9a4145dc3d87
--- /dev/null
+++ b/drivers/media/video/tm6000/tm6000-stds.c
@@ -0,0 +1,659 @@
+/*
+ * tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ * Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@redhat.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 in the hope that it will be useful,
+ * but WITHOUT 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/module.h>
+#include <linux/kernel.h>
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+static unsigned int tm6010_a_mode;
+module_param(tm6010_a_mode, int, 0644);
+MODULE_PARM_DESC(tm6010_a_mode, "set tm6010 sif audio mode");
+
+struct tm6000_reg_settings {
+ unsigned char req;
+ unsigned char reg;
+ unsigned char value;
+};
+
+
+struct tm6000_std_settings {
+ v4l2_std_id id;
+ struct tm6000_reg_settings *common;
+};
+
+static struct tm6000_reg_settings composite_pal_m[] = {
+ { TM6010_REQ07_R3F_RESET, 0x01 },
+ { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x04 },
+ { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+ { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+ { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+ { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+ { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+ { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
+ { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
+ { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
+ { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+ { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+ { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+ { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+ { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+ { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x20 },
+ { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+ { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+ { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+ { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+ { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+ { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+ { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+ { TM6010_REQ07_R3F_RESET, 0x00 },
+ { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_pal_nc[] = {
+ { TM6010_REQ07_R3F_RESET, 0x01 },
+ { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x36 },
+ { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+ { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+ { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+ { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+ { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+ { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
+ { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
+ { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
+ { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+ { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+ { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+ { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+ { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+ { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+ { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+ { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+ { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+ { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+ { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+ { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+ { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+ { TM6010_REQ07_R3F_RESET, 0x00 },
+ { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_pal[] = {
+ { TM6010_REQ07_R3F_RESET, 0x01 },
+ { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x32 },
+ { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+ { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+ { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+ { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+ { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
+ { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
+ { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
+ { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
+ { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+ { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+ { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+ { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+ { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+ { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+ { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+ { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+ { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+ { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+ { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+ { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+ { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+ { TM6010_REQ07_R3F_RESET, 0x00 },
+ { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_secam[] = {
+ { TM6010_REQ07_R3F_RESET, 0x01 },
+ { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x38 },
+ { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+ { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+ { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+ { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+ { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
+ { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
+ { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
+ { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
+ { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+ { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+ { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+ { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+ { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+ { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+ { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+ { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
+ { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
+ { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+ { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
+ { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+ { TM6010_REQ07_R3F_RESET, 0x00 },
+ { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_ntsc[] = {
+ { TM6010_REQ07_R3F_RESET, 0x01 },
+ { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
+ { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
+ { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+ { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+ { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+ { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+ { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+ { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+ { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+ { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+ { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+ { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+ { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+ { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+ { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+ { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+ { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+ { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+ { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+ { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+ { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
+ { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+ { TM6010_REQ07_R3F_RESET, 0x00 },
+ { 0, 0, 0 }
+};
+
+static struct tm6000_std_settings composite_stds[] = {
+ { .id = V4L2_STD_PAL_M, .common = composite_pal_m, },
+ { .id = V4L2_STD_PAL_Nc, .common = composite_pal_nc, },
+ { .id = V4L2_STD_PAL, .common = composite_pal, },
+ { .id = V4L2_STD_SECAM, .common = composite_secam, },
+ { .id = V4L2_STD_NTSC, .common = composite_ntsc, },
+};
+
+static struct tm6000_reg_settings svideo_pal_m[] = {
+ { TM6010_REQ07_R3F_RESET, 0x01 },
+ { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x05 },
+ { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+ { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+ { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+ { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+ { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+ { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
+ { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
+ { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
+ { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+ { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+ { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+ { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+ { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+ { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+ { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+ { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+ { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+ { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+ { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+ { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+ { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+ { TM6010_REQ07_R3F_RESET, 0x00 },
+ { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_pal_nc[] = {
+ { TM6010_REQ07_R3F_RESET, 0x01 },
+ { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x37 },
+ { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+ { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+ { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+ { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+ { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+ { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
+ { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
+ { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
+ { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+ { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+ { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+ { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+ { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+ { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+ { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+ { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+ { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+ { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+ { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+ { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+ { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+ { TM6010_REQ07_R3F_RESET, 0x00 },
+ { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_pal[] = {
+ { TM6010_REQ07_R3F_RESET, 0x01 },
+ { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x33 },
+ { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+ { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+ { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+ { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
+ { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
+ { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
+ { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
+ { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
+ { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+ { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+ { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+ { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+ { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+ { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
+ { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+ { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+ { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+ { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+ { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+ { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+ { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+ { TM6010_REQ07_R3F_RESET, 0x00 },
+ { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_secam[] = {
+ { TM6010_REQ07_R3F_RESET, 0x01 },
+ { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x39 },
+ { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+ { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+ { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
+ { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+ { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
+ { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
+ { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
+ { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
+ { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+ { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+ { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+ { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+ { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+ { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
+ { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+ { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
+ { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
+ { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+ { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
+ { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+ { TM6010_REQ07_R3F_RESET, 0x00 },
+ { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_ntsc[] = {
+ { TM6010_REQ07_R3F_RESET, 0x01 },
+ { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x01 },
+ { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
+ { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+ { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
+ { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
+ { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0x8b },
+ { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+ { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+ { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+ { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+ { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+ { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+ { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+ { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+ { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+ { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+ { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+ { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+ { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+ { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+ { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+ { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
+ { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+ { TM6010_REQ07_R3F_RESET, 0x00 },
+ { 0, 0, 0 }
+};
+
+static struct tm6000_std_settings svideo_stds[] = {
+ { .id = V4L2_STD_PAL_M, .common = svideo_pal_m, },
+ { .id = V4L2_STD_PAL_Nc, .common = svideo_pal_nc, },
+ { .id = V4L2_STD_PAL, .common = svideo_pal, },
+ { .id = V4L2_STD_SECAM, .common = svideo_secam, },
+ { .id = V4L2_STD_NTSC, .common = svideo_ntsc, },
+};
+
+static int tm6000_set_audio_std(struct tm6000_core *dev)
+{
+ uint8_t areg_02 = 0x04; /* GC1 Fixed gain 0dB */
+ uint8_t areg_05 = 0x01; /* Auto 4.5 = M Japan, Auto 6.5 = DK */
+ uint8_t areg_06 = 0x02; /* Auto de-emphasis, mannual channel mode */
+ uint8_t nicam_flag = 0; /* No NICAM */
+
+ if (dev->radio) {
+ tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, 0x04);
+ tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0x80);
+ tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, 0x0c);
+ /* set mono or stereo */
+ if (dev->amode == V4L2_TUNER_MODE_MONO)
+ tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00);
+ else if (dev->amode == V4L2_TUNER_MODE_STEREO)
+ tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x02);
+ tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x18);
+ tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x0a);
+ tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x40);
+ tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe);
+ tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
+ tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
+ tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0xff);
+ return 0;
+ }
+
+ switch (tm6010_a_mode) {
+ /* auto */
+ case 0:
+ switch (dev->norm) {
+ case V4L2_STD_NTSC_M_KR:
+ areg_05 |= 0x00;
+ break;
+ case V4L2_STD_NTSC_M_JP:
+ areg_05 |= 0x40;
+ break;
+ case V4L2_STD_NTSC_M:
+ case V4L2_STD_PAL_M:
+ case V4L2_STD_PAL_N:
+ areg_05 |= 0x20;
+ break;
+ case V4L2_STD_PAL_Nc:
+ areg_05 |= 0x60;
+ break;
+ case V4L2_STD_SECAM_L:
+ areg_05 |= 0x00;
+ break;
+ case V4L2_STD_DK:
+ areg_05 |= 0x10;
+ break;
+ }
+ break;
+ /* A2 */
+ case 1:
+ switch (dev->norm) {
+ case V4L2_STD_B:
+ case V4L2_STD_GH:
+ areg_05 = 0x05;
+ break;
+ case V4L2_STD_DK:
+ areg_05 = 0x09;
+ break;
+ }
+ break;
+ /* NICAM */
+ case 2:
+ switch (dev->norm) {
+ case V4L2_STD_B:
+ case V4L2_STD_GH:
+ areg_05 = 0x07;
+ break;
+ case V4L2_STD_DK:
+ areg_05 = 0x06;
+ break;
+ case V4L2_STD_PAL_I:
+ areg_05 = 0x08;
+ break;
+ case V4L2_STD_SECAM_L:
+ areg_05 = 0x0a;
+ areg_02 = 0x02;
+ break;
+ }
+ nicam_flag = 1;
+ break;
+ /* other */
+ case 3:
+ switch (dev->norm) {
+ /* DK3_A2 */
+ case V4L2_STD_DK:
+ areg_05 = 0x0b;
+ break;
+ /* Korea */
+ case V4L2_STD_NTSC_M_KR:
+ areg_05 = 0x04;
+ break;
+ /* EIAJ */
+ case V4L2_STD_NTSC_M_JP:
+ areg_05 = 0x03;
+ break;
+ default:
+ areg_05 = 0x02;
+ break;
+ }
+ break;
+ }
+
+ tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, areg_02);
+ tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0xa0);
+ tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, areg_05);
+ tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, areg_06);
+ tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x08);
+ tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0x91);
+ tm6000_set_reg(dev, TM6010_REQ08_R0B_A_ASD_THRES1, 0x20);
+ tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x12);
+ tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x20);
+ tm6000_set_reg(dev, TM6010_REQ08_R0E_A_MONO_THRES1, 0xf0);
+ tm6000_set_reg(dev, TM6010_REQ08_R0F_A_MONO_THRES2, 0x80);
+ tm6000_set_reg(dev, TM6010_REQ08_R10_A_MUTE_THRES1, 0xc0);
+ tm6000_set_reg(dev, TM6010_REQ08_R11_A_MUTE_THRES2, 0x80);
+ tm6000_set_reg(dev, TM6010_REQ08_R12_A_AGC_U, 0x12);
+ tm6000_set_reg(dev, TM6010_REQ08_R13_A_AGC_ERR_T, 0xfe);
+ tm6000_set_reg(dev, TM6010_REQ08_R14_A_AGC_GAIN_INIT, 0x20);
+ tm6000_set_reg(dev, TM6010_REQ08_R15_A_AGC_STEP_THR, 0x14);
+ tm6000_set_reg(dev, TM6010_REQ08_R16_A_AGC_GAIN_MAX, 0xfe);
+ tm6000_set_reg(dev, TM6010_REQ08_R17_A_AGC_GAIN_MIN, 0x01);
+ tm6000_set_reg(dev, TM6010_REQ08_R18_A_TR_CTRL, 0xa0);
+ tm6000_set_reg(dev, TM6010_REQ08_R19_A_FH_2FH_GAIN, 0x32);
+ tm6000_set_reg(dev, TM6010_REQ08_R1A_A_NICAM_SER_MAX, 0x64);
+ tm6000_set_reg(dev, TM6010_REQ08_R1B_A_NICAM_SER_MIN, 0x20);
+ tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1c, 0x00);
+ tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1d, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
+ tm6000_set_reg(dev, TM6010_REQ08_R1F_A_TEST_INTF_SEL, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_R20_A_TEST_PIN_SEL, 0x00);
+ tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
+
+ return 0;
+}
+
+void tm6000_get_std_res(struct tm6000_core *dev)
+{
+ /* Currently, those are the only supported resoltions */
+ if (dev->norm & V4L2_STD_525_60)
+ dev->height = 480;
+ else
+ dev->height = 576;
+
+ dev->width = 720;
+}
+
+static int tm6000_load_std(struct tm6000_core *dev, struct tm6000_reg_settings *set)
+{
+ int i, rc;
+
+ /* Load board's initialization table */
+ for (i = 0; set[i].req; i++) {
+ rc = tm6000_set_reg(dev, set[i].req, set[i].reg, set[i].value);
+ if (rc < 0) {
+ printk(KERN_ERR "Error %i while setting "
+ "req %d, reg %d to value %d\n",
+ rc, set[i].req, set[i].reg, set[i].value);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+int tm6000_set_standard(struct tm6000_core *dev)
+{
+ struct tm6000_input *input;
+ int i, rc = 0;
+ u8 reg_07_fe = 0x8a;
+ u8 reg_08_f1 = 0xfc;
+ u8 reg_08_e2 = 0xf0;
+ u8 reg_08_e6 = 0x0f;
+
+ tm6000_get_std_res(dev);
+
+ if (!dev->radio)
+ input = &dev->vinput[dev->input];
+ else
+ input = &dev->rinput;
+
+ if (dev->dev_type == TM6010) {
+ switch (input->vmux) {
+ case TM6000_VMUX_VIDEO_A:
+ tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4);
+ tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
+ tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
+ tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+ tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
+ reg_07_fe |= 0x01;
+ break;
+ case TM6000_VMUX_VIDEO_B:
+ tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8);
+ tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
+ tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
+ tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+ tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
+ reg_07_fe |= 0x01;
+ break;
+ case TM6000_VMUX_VIDEO_AB:
+ tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc);
+ tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8);
+ reg_08_e6 = 0x00;
+ tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2);
+ tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0);
+ tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+ tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe0);
+ break;
+ default:
+ break;
+ }
+ switch (input->amux) {
+ case TM6000_AMUX_ADC1:
+ tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+ 0x00, 0x0f);
+ break;
+ case TM6000_AMUX_ADC2:
+ tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+ 0x08, 0x0f);
+ break;
+ case TM6000_AMUX_SIF1:
+ reg_08_e2 |= 0x02;
+ reg_08_e6 = 0x08;
+ reg_07_fe |= 0x40;
+ reg_08_f1 |= 0x02;
+ tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3);
+ tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+ 0x02, 0x0f);
+ break;
+ case TM6000_AMUX_SIF2:
+ reg_08_e2 |= 0x02;
+ reg_08_e6 = 0x08;
+ reg_07_fe |= 0x40;
+ reg_08_f1 |= 0x02;
+ tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7);
+ tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+ 0x02, 0x0f);
+ break;
+ default:
+ break;
+ }
+ tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, reg_08_e2);
+ tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, reg_08_e6);
+ tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, reg_08_f1);
+ tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, reg_07_fe);
+ } else {
+ switch (input->vmux) {
+ case TM6000_VMUX_VIDEO_A:
+ tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
+ tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
+ tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
+ tm6000_set_reg(dev,
+ REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
+ break;
+ case TM6000_VMUX_VIDEO_B:
+ tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x00);
+ tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
+ tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
+ tm6000_set_reg(dev,
+ REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
+ break;
+ case TM6000_VMUX_VIDEO_AB:
+ tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
+ tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x10);
+ tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00);
+ tm6000_set_reg(dev,
+ REQ_03_SET_GET_MCU_PIN, input->v_gpio, 1);
+ break;
+ default:
+ break;
+ }
+ switch (input->amux) {
+ case TM6000_AMUX_ADC1:
+ tm6000_set_reg_mask(dev,
+ TM6000_REQ07_REB_VADC_AADC_MODE, 0x00, 0x0f);
+ break;
+ case TM6000_AMUX_ADC2:
+ tm6000_set_reg_mask(dev,
+ TM6000_REQ07_REB_VADC_AADC_MODE, 0x04, 0x0f);
+ break;
+ default:
+ break;
+ }
+ }
+ if (input->type == TM6000_INPUT_SVIDEO) {
+ for (i = 0; i < ARRAY_SIZE(svideo_stds); i++) {
+ if (dev->norm & svideo_stds[i].id) {
+ rc = tm6000_load_std(dev, svideo_stds[i].common);
+ goto ret;
+ }
+ }
+ return -EINVAL;
+ } else {
+ for (i = 0; i < ARRAY_SIZE(composite_stds); i++) {
+ if (dev->norm & composite_stds[i].id) {
+ rc = tm6000_load_std(dev, composite_stds[i].common);
+ goto ret;
+ }
+ }
+ return -EINVAL;
+ }
+
+ret:
+ if (rc < 0)
+ return rc;
+
+ if ((dev->dev_type == TM6010) &&
+ ((input->amux == TM6000_AMUX_SIF1) ||
+ (input->amux == TM6000_AMUX_SIF2)))
+ tm6000_set_audio_std(dev);
+
+ msleep(40);
+
+ return 0;
+}
diff --git a/drivers/staging/tm6000/tm6000-usb-isoc.h b/drivers/media/video/tm6000/tm6000-usb-isoc.h
index 084c2a8904a3..99d15a55aa03 100644
--- a/drivers/staging/tm6000/tm6000-usb-isoc.h
+++ b/drivers/media/video/tm6000/tm6000-usb-isoc.h
@@ -46,5 +46,5 @@ struct usb_isoc_ctl {
int tmp_buf_len;
/* Stores already requested buffers */
- struct tm6000_buffer *buf;
+ struct tm6000_buffer *buf;
};
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c
index 8d8b939915d8..1e5ace0b5d10 100644
--- a/drivers/staging/tm6000/tm6000-video.c
+++ b/drivers/media/video/tm6000/tm6000-video.c
@@ -19,6 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -202,17 +203,6 @@ static inline void buffer_filled(struct tm6000_core *dev,
wake_up(&buf->vb.done);
}
-const char *tm6000_msg_type[] = {
- "unknown(0)", /* 0 */
- "video", /* 1 */
- "audio", /* 2 */
- "vbi", /* 3 */
- "pts", /* 4 */
- "err", /* 5 */
- "unknown(6)", /* 6 */
- "unknown(7)", /* 7 */
-};
-
/*
* Identify the tm5600/6000 buffer header type and properly handles
*/
@@ -286,17 +276,18 @@ static int copy_streams(u8 *data, unsigned long len,
if (size > TM6000_URB_MSG_LEN)
size = TM6000_URB_MSG_LEN;
pktsize = TM6000_URB_MSG_LEN;
- /* calculate position in buffer
- * and change the buffer
+ /*
+ * calculate position in buffer and change the buffer
*/
switch (cmd) {
case TM6000_URB_MSG_VIDEO:
if (!dev->radio) {
if ((dev->isoc_ctl.vfield != field) &&
(field == 1)) {
- /* Announces that a new buffer
- * were filled
- */
+ /*
+ * Announces that a new buffer
+ * were filled
+ */
buffer_filled(dev, dma_q, vbuf);
dprintk(dev, V4L2_DEBUG_ISOC,
"new buffer filled\n");
@@ -321,7 +312,7 @@ static int copy_streams(u8 *data, unsigned long len,
break;
case TM6000_URB_MSG_AUDIO:
case TM6000_URB_MSG_PTS:
- size = pktsize; /* Size is always 180 bytes */
+ size = pktsize; /* Size is always 180 bytes */
break;
}
} else {
@@ -363,7 +354,8 @@ static int copy_streams(u8 *data, unsigned long len,
}
}
if (ptr + pktsize > endp) {
- /* End of URB packet, but cmd processing is not
+ /*
+ * End of URB packet, but cmd processing is not
* complete. Preserve the state for a next packet
*/
dev->isoc_ctl.pos = pos + cpysize;
@@ -521,9 +513,21 @@ static void tm6000_irq_callback(struct urb *urb)
struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
int i;
- if (!dev)
+ switch (urb->status) {
+ case 0:
+ case -ETIMEDOUT:
+ break;
+
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
return;
+ default:
+ tm6000_err("urb completion error %d.\n", urb->status);
+ break;
+ }
+
spin_lock(&dev->slock);
tm6000_isoc_copy(urb);
spin_unlock(&dev->slock);
@@ -750,7 +754,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
struct tm6000_fh *fh = vq->priv_data;
struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
struct tm6000_core *dev = fh->dev;
- int rc = 0, urb_init = 0;
+ int rc = 0;
BUG_ON(NULL == fh->fmt);
@@ -776,13 +780,9 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
rc = videobuf_iolock(vq, &buf->vb, NULL);
if (rc != 0)
goto fail;
- urb_init = 1;
}
- if (!dev->isoc_ctl.num_bufs)
- urb_init = 1;
-
- if (urb_init) {
+ if (!dev->isoc_ctl.num_bufs) {
rc = tm6000_prepare_isoc(dev);
if (rc < 0)
goto fail;
@@ -1035,8 +1035,8 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
- struct tm6000_fh *fh = priv;
- struct tm6000_core *dev = fh->dev;
+ struct tm6000_fh *fh = priv;
+ struct tm6000_core *dev = fh->dev;
if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -1050,11 +1050,12 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{
- struct tm6000_fh *fh = priv;
- struct tm6000_core *dev = fh->dev;
+ struct tm6000_fh *fh = priv;
+ struct tm6000_core *dev = fh->dev;
if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
+
if (i != fh->type)
return -EINVAL;
@@ -1067,7 +1068,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
{
int rc = 0;
- struct tm6000_fh *fh = priv;
+ struct tm6000_fh *fh = priv;
struct tm6000_core *dev = fh->dev;
dev->norm = *norm;
@@ -1464,9 +1465,6 @@ static int tm6000_open(struct file *file)
int i, rc;
int radio = 0;
- printk(KERN_INFO "tm6000: open called (dev=%s)\n",
- video_device_node_name(vdev));
-
dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n",
video_device_node_name(vdev));
@@ -1507,12 +1505,13 @@ static int tm6000_open(struct file *file)
tm6000_get_std_res(dev);
- fh->width = dev->width;
- fh->height = dev->height;
+ fh->width = dev->width;
+ fh->height = dev->height;
dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, "
"dev->vidq=0x%08lx\n",
- (unsigned long)fh, (unsigned long)dev, (unsigned long)&dev->vidq);
+ (unsigned long)fh, (unsigned long)dev,
+ (unsigned long)&dev->vidq);
dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
"queued=%d\n", list_empty(&dev->vidq.queued));
dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
@@ -1531,13 +1530,13 @@ static int tm6000_open(struct file *file)
dev->mode = TM6000_MODE_ANALOG;
}
- videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
- NULL, &dev->slock,
- fh->type,
- V4L2_FIELD_INTERLACED,
- sizeof(struct tm6000_buffer), fh, &dev->lock);
-
- if (fh->radio) {
+ if (!fh->radio) {
+ videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
+ NULL, &dev->slock,
+ fh->type,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct tm6000_buffer), fh, &dev->lock);
+ } else {
dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n");
dev->input = 5;
tm6000_set_audio_rinput(dev);
@@ -1583,8 +1582,7 @@ tm6000_poll(struct file *file, struct poll_table_struct *wait)
buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream);
} else {
/* read() capture */
- return videobuf_poll_stream(file, &fh->vb_vidq,
- wait);
+ return videobuf_poll_stream(file, &fh->vb_vidq, wait);
}
poll_wait(file, &buf->vb.done, wait);
if (buf->vb.state == VIDEOBUF_DONE ||
@@ -1605,9 +1603,18 @@ static int tm6000_release(struct file *file)
dev->users--;
res_free(dev, fh);
+
if (!dev->users) {
+ int err;
+
tm6000_uninit_isoc(dev);
- videobuf_mmap_free(&fh->vb_vidq);
+
+ if (!fh->radio)
+ videobuf_mmap_free(&fh->vb_vidq);
+
+ err = tm6000_reset(dev);
+ if (err < 0)
+ dev_err(&vdev->dev, "reset failed: %d\n", err);
}
kfree(fh);
@@ -1617,22 +1624,19 @@ static int tm6000_release(struct file *file)
static int tm6000_mmap(struct file *file, struct vm_area_struct * vma)
{
- struct tm6000_fh *fh = file->private_data;
- int ret;
-
- ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+ struct tm6000_fh *fh = file->private_data;
- return ret;
+ return videobuf_mmap_mapper(&fh->vb_vidq, vma);
}
static struct v4l2_file_operations tm6000_fops = {
- .owner = THIS_MODULE,
- .open = tm6000_open,
- .release = tm6000_release,
- .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
- .read = tm6000_read,
- .poll = tm6000_poll,
- .mmap = tm6000_mmap,
+ .owner = THIS_MODULE,
+ .open = tm6000_open,
+ .release = tm6000_release,
+ .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+ .read = tm6000_read,
+ .poll = tm6000_poll,
+ .mmap = tm6000_mmap,
};
static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1693,7 +1697,7 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
.vidioc_s_frequency = vidioc_s_frequency,
};
-struct video_device tm6000_radio_template = {
+static struct video_device tm6000_radio_template = {
.name = "tm6000",
.fops = &radio_fops,
.ioctl_ops = &radio_ioctl_ops,
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/media/video/tm6000/tm6000.h
index c56da628dbef..2777e514eff2 100644
--- a/drivers/staging/tm6000/tm6000.h
+++ b/drivers/media/video/tm6000/tm6000.h
@@ -20,9 +20,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* Use the tm6000-hack, instead of the proper initialization code i*/
-/* #define HACK 1 */
-
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/videobuf-vmalloc.h>
@@ -30,7 +27,7 @@
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <media/v4l2-device.h>
-#include <linux/version.h>
+
#include <linux/dvb/frontend.h>
#include "dvb_demux.h"
#include "dvb_frontend.h"
@@ -172,6 +169,8 @@ struct tm6000_endpoint {
unsigned maxsize;
};
+#define TM6000_QUIRK_NO_USB_DELAY (1 << 0)
+
struct tm6000_core {
/* generic device properties */
char name[30]; /* name (including minor) of the device */
@@ -248,6 +247,7 @@ struct tm6000_core {
/* locks */
struct mutex lock;
+ struct mutex usb_lock;
/* usb transfer */
struct usb_device *udev; /* the usb device */
@@ -262,6 +262,8 @@ struct tm6000_core {
struct usb_isoc_ctl isoc_ctl;
spinlock_t slock;
+
+ unsigned long quirks;
};
enum tm6000_ops_type {
@@ -313,6 +315,7 @@ int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
u16 index, u16 mask);
int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep);
int tm6000_init(struct tm6000_core *dev);
+int tm6000_reset(struct tm6000_core *dev);
int tm6000_init_analog_mode(struct tm6000_core *dev);
int tm6000_init_digital_mode(struct tm6000_core *dev);
@@ -381,7 +384,7 @@ extern int tm6000_debug;
#define dprintk(dev, level, fmt, arg...) do {\
if (tm6000_debug & level) \
printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \
- dev->name, __FUNCTION__ , ##arg); } while (0)
+ dev->name, __func__ , ##arg); } while (0)
#define V4L2_DEBUG_REG 0x0004
#define V4L2_DEBUG_I2C 0x0008
@@ -392,4 +395,4 @@ extern int tm6000_debug;
#define tm6000_err(fmt, arg...) do {\
printk(KERN_ERR "tm6000 %s :"fmt, \
- __FUNCTION__ , ##arg); } while (0)
+ __func__ , ##arg); } while (0)
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index c46a3bb95852..f22dbef9b95b 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -1695,14 +1695,17 @@ static int tvaudio_s_ctrl(struct v4l2_subdev *sd,
case V4L2_CID_AUDIO_BALANCE:
{
int volume, balance;
+
if (!(desc->flags & CHIP_HAS_VOLUME))
break;
- volume = max(chip->left,chip->right);
+ volume = max(chip->left, chip->right);
balance = ctrl->value;
+ chip->left = (min(65536 - balance, 32768) * volume) / 32768;
+ chip->right = (min(balance, volume * (__u16)32768)) / 32768;
- chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
- chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
+ chip_write(chip, desc->leftreg, desc->volfunc(chip->left));
+ chip_write(chip, desc->rightreg, desc->volfunc(chip->right));
return 0;
}
diff --git a/drivers/media/video/tvp5150_reg.h b/drivers/media/video/tvp5150_reg.h
index 4240043c0b2a..25a994944918 100644
--- a/drivers/media/video/tvp5150_reg.h
+++ b/drivers/media/video/tvp5150_reg.h
@@ -45,7 +45,22 @@
/* Reserved 1Fh-27h */
-#define TVP5150_VIDEO_STD 0x28 /* Video standard */
+#define VIDEO_STD_MASK (0x07 >> 1)
+#define TVP5150_VIDEO_STD 0x28 /* Video standard */
+#define VIDEO_STD_AUTO_SWITCH_BIT 0x00
+#define VIDEO_STD_NTSC_MJ_BIT 0x02
+#define VIDEO_STD_PAL_BDGHIN_BIT 0x04
+#define VIDEO_STD_PAL_M_BIT 0x06
+#define VIDEO_STD_PAL_COMBINATION_N_BIT 0x08
+#define VIDEO_STD_NTSC_4_43_BIT 0x0a
+#define VIDEO_STD_SECAM_BIT 0x0c
+
+#define VIDEO_STD_NTSC_MJ_BIT_AS 0x01
+#define VIDEO_STD_PAL_BDGHIN_BIT_AS 0x03
+#define VIDEO_STD_PAL_M_BIT_AS 0x05
+#define VIDEO_STD_PAL_COMBINATION_N_BIT_AS 0x07
+#define VIDEO_STD_NTSC_4_43_BIT_AS 0x09
+#define VIDEO_STD_SECAM_BIT_AS 0x0b
/* Reserved 29h-2bh */
diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c
index b799851bf3d0..2e6059a52e9f 100644
--- a/drivers/media/video/tvp7002.c
+++ b/drivers/media/video/tvp7002.c
@@ -128,7 +128,7 @@ static const struct i2c_reg_value tvp7002_init_default[] = {
{ TVP7002_ADC_SETUP, 0x50, TVP7002_WRITE },
{ TVP7002_COARSE_CLAMP_CTL, 0x00, TVP7002_WRITE },
{ TVP7002_SOG_CLAMP, 0x80, TVP7002_WRITE },
- { TVP7002_RGB_COARSE_CLAMP_CTL, 0x00, TVP7002_WRITE },
+ { TVP7002_RGB_COARSE_CLAMP_CTL, 0x8c, TVP7002_WRITE },
{ TVP7002_SOG_COARSE_CLAMP_CTL, 0x04, TVP7002_WRITE },
{ TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE },
{ 0x32, 0x18, TVP7002_RESERVED },
@@ -182,7 +182,6 @@ static const struct i2c_reg_value tvp7002_parms_480P[] = {
{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x35, TVP7002_WRITE },
{ TVP7002_HPLL_FDBK_DIV_LSBS, 0xa0, TVP7002_WRITE },
{ TVP7002_HPLL_CRTL, 0x02, TVP7002_WRITE },
- { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_LSBS, 0x91, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x0B, TVP7002_WRITE },
@@ -204,7 +203,6 @@ static const struct i2c_reg_value tvp7002_parms_576P[] = {
{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x36, TVP7002_WRITE },
{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x00, TVP7002_WRITE },
{ TVP7002_HPLL_CRTL, 0x18, TVP7002_WRITE },
- { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_LSBS, 0x9B, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x0F, TVP7002_WRITE },
@@ -226,7 +224,6 @@ static const struct i2c_reg_value tvp7002_parms_1080I60[] = {
{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE },
{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x80, TVP7002_WRITE },
{ TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
- { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE },
@@ -248,7 +245,6 @@ static const struct i2c_reg_value tvp7002_parms_1080P60[] = {
{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE },
{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x80, TVP7002_WRITE },
{ TVP7002_HPLL_CRTL, 0xE0, TVP7002_WRITE },
- { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE },
@@ -270,7 +266,6 @@ static const struct i2c_reg_value tvp7002_parms_1080I50[] = {
{ TVP7002_HPLL_FDBK_DIV_MSBS, 0xa5, TVP7002_WRITE },
{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x00, TVP7002_WRITE },
{ TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
- { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE },
@@ -292,7 +287,6 @@ static const struct i2c_reg_value tvp7002_parms_720P60[] = {
{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE },
{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x20, TVP7002_WRITE },
{ TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE },
- { TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x4B, TVP7002_WRITE },
@@ -314,7 +308,6 @@ static const struct i2c_reg_value tvp7002_parms_720P50[] = {
{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x7b, TVP7002_WRITE },
{ TVP7002_HPLL_FDBK_DIV_LSBS, 0xc0, TVP7002_WRITE },
{ TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
- { TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x4B, TVP7002_WRITE },
@@ -687,6 +680,9 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd,
u8 cpl_msb;
int index;
+ /* Return invalid preset if no active input is detected */
+ qpreset->preset = V4L2_DV_INVALID;
+
device = to_tvp7002(sd);
/* Read standards from device registers */
@@ -720,8 +716,6 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd,
if (index == NUM_PRESETS) {
v4l2_dbg(1, debug, sd, "detection failed: lpf = %x, cpl = %x\n",
lpfr, cpln);
- /* Could not detect a signal, so return the 'invalid' preset */
- qpreset->preset = V4L2_DV_INVALID;
return 0;
}
diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/video/usbvision/Makefile
index 338718750945..aea1e3b5f06b 100644
--- a/drivers/media/video/usbvision/Makefile
+++ b/drivers/media/video/usbvision/Makefile
@@ -2,5 +2,5 @@ usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-
obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index e4100b1f68df..656d4c9e3b9f 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -114,6 +114,11 @@ static struct uvc_format_desc uvc_fmts[] = {
.guid = UVC_GUID_FORMAT_RGBP,
.fcc = V4L2_PIX_FMT_RGB565,
},
+ {
+ .name = "H.264",
+ .guid = UVC_GUID_FORMAT_H264,
+ .fcc = V4L2_PIX_FMT_H264,
+ },
};
/* ------------------------------------------------------------------------
@@ -2331,6 +2336,14 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_DEF },
+ /* The Imaging Source USB CCD cameras */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x199e,
+ .idProduct = 0x8102,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0 },
/* Bodelin ProScopeHR */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_DEV_HI
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index ea71d5f1f6db..dadf11f704dc 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -32,7 +32,7 @@
* UVC ioctls
*/
static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
- struct uvc_xu_control_mapping *xmap, int old)
+ struct uvc_xu_control_mapping *xmap)
{
struct uvc_control_mapping *map;
unsigned int size;
@@ -58,13 +58,6 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
break;
case V4L2_CTRL_TYPE_MENU:
- if (old) {
- uvc_trace(UVC_TRACE_CONTROL, "V4L2_CTRL_TYPE_MENU not "
- "supported for UVCIOC_CTRL_MAP_OLD.\n");
- ret = -EINVAL;
- goto done;
- }
-
size = xmap->menu_count * sizeof(*map->menu_info);
map->menu_info = kmalloc(size, GFP_KERNEL);
if (map->menu_info == NULL) {
@@ -538,20 +531,6 @@ static int uvc_v4l2_release(struct file *file)
return 0;
}
-static void uvc_v4l2_ioctl_warn(void)
-{
- static int warned;
-
- if (warned)
- return;
-
- uvc_printk(KERN_INFO, "Deprecated UVCIOC_CTRL_{ADD,MAP_OLD,GET,SET} "
- "ioctls will be removed in 2.6.42.\n");
- uvc_printk(KERN_INFO, "See http://www.ideasonboard.org/uvc/upgrade/ "
- "for upgrade instructions.\n");
- warned = 1;
-}
-
static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
@@ -1032,37 +1011,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
return -EINVAL;
- /* Dynamic controls. UVCIOC_CTRL_ADD, UVCIOC_CTRL_MAP_OLD,
- * UVCIOC_CTRL_GET and UVCIOC_CTRL_SET are deprecated and scheduled for
- * removal in 2.6.42.
- */
- case __UVCIOC_CTRL_ADD:
- uvc_v4l2_ioctl_warn();
- return -EEXIST;
-
- case __UVCIOC_CTRL_MAP_OLD:
- uvc_v4l2_ioctl_warn();
- case __UVCIOC_CTRL_MAP:
case UVCIOC_CTRL_MAP:
- return uvc_ioctl_ctrl_map(chain, arg,
- cmd == __UVCIOC_CTRL_MAP_OLD);
-
- case __UVCIOC_CTRL_GET:
- case __UVCIOC_CTRL_SET:
- {
- struct uvc_xu_control *xctrl = arg;
- struct uvc_xu_control_query xqry = {
- .unit = xctrl->unit,
- .selector = xctrl->selector,
- .query = cmd == __UVCIOC_CTRL_GET
- ? UVC_GET_CUR : UVC_SET_CUR,
- .size = xctrl->size,
- .data = xctrl->data,
- };
-
- uvc_v4l2_ioctl_warn();
- return uvc_xu_ctrl_query(chain, &xqry);
- }
+ return uvc_ioctl_ctrl_map(chain, arg);
case UVCIOC_CTRL_QUERY:
return uvc_xu_ctrl_query(chain, arg);
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index ffd1158628b6..b015e8e5e8b0 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -790,8 +790,12 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream)
for (i = 0; i < UVC_URBS; ++i) {
if (stream->urb_buffer[i]) {
+#ifndef CONFIG_DMA_NONCOHERENT
usb_free_coherent(stream->dev->udev, stream->urb_size,
stream->urb_buffer[i], stream->urb_dma[i]);
+#else
+ kfree(stream->urb_buffer[i]);
+#endif
stream->urb_buffer[i] = NULL;
}
}
@@ -831,9 +835,14 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
for (; npackets > 1; npackets /= 2) {
for (i = 0; i < UVC_URBS; ++i) {
stream->urb_size = psize * npackets;
+#ifndef CONFIG_DMA_NONCOHERENT
stream->urb_buffer[i] = usb_alloc_coherent(
stream->dev->udev, stream->urb_size,
gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]);
+#else
+ stream->urb_buffer[i] =
+ kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN);
+#endif
if (!stream->urb_buffer[i]) {
uvc_free_urb_buffers(stream);
break;
@@ -908,10 +917,14 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
urb->context = stream;
urb->pipe = usb_rcvisocpipe(stream->dev->udev,
ep->desc.bEndpointAddress);
+#ifndef CONFIG_DMA_NONCOHERENT
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+ urb->transfer_dma = stream->urb_dma[i];
+#else
+ urb->transfer_flags = URB_ISO_ASAP;
+#endif
urb->interval = ep->desc.bInterval;
urb->transfer_buffer = stream->urb_buffer[i];
- urb->transfer_dma = stream->urb_dma[i];
urb->complete = uvc_video_complete;
urb->number_of_packets = npackets;
urb->transfer_buffer_length = size;
@@ -969,8 +982,10 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
usb_fill_bulk_urb(urb, stream->dev->udev, pipe,
stream->urb_buffer[i], size, uvc_video_complete,
stream);
+#ifndef CONFIG_DMA_NONCOHERENT
urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
urb->transfer_dma = stream->urb_dma[i];
+#endif
stream->urb[i] = urb;
}
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index cbdd49bf8b67..4c1392ebcd4b 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -1,106 +1,16 @@
#ifndef _USB_VIDEO_H_
#define _USB_VIDEO_H_
-#include <linux/kernel.h>
-#include <linux/videodev2.h>
-
-#ifndef __KERNEL__
-/*
- * This header provides binary compatibility with applications using the private
- * uvcvideo API. This API is deprecated and will be removed in 2.6.42.
- * Applications should be recompiled against the public linux/uvcvideo.h header.
- */
-#warn "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead."
-
-/*
- * Dynamic controls
- */
-
-/* Data types for UVC control data */
-#define UVC_CTRL_DATA_TYPE_RAW 0
-#define UVC_CTRL_DATA_TYPE_SIGNED 1
-#define UVC_CTRL_DATA_TYPE_UNSIGNED 2
-#define UVC_CTRL_DATA_TYPE_BOOLEAN 3
-#define UVC_CTRL_DATA_TYPE_ENUM 4
-#define UVC_CTRL_DATA_TYPE_BITMASK 5
-
-/* Control flags */
-#define UVC_CONTROL_SET_CUR (1 << 0)
-#define UVC_CONTROL_GET_CUR (1 << 1)
-#define UVC_CONTROL_GET_MIN (1 << 2)
-#define UVC_CONTROL_GET_MAX (1 << 3)
-#define UVC_CONTROL_GET_RES (1 << 4)
-#define UVC_CONTROL_GET_DEF (1 << 5)
-#define UVC_CONTROL_RESTORE (1 << 6)
-#define UVC_CONTROL_AUTO_UPDATE (1 << 7)
-
-#define UVC_CONTROL_GET_RANGE (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \
- UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \
- UVC_CONTROL_GET_DEF)
-
-struct uvc_menu_info {
- __u32 value;
- __u8 name[32];
-};
-
-struct uvc_xu_control_mapping {
- __u32 id;
- __u8 name[32];
- __u8 entity[16];
- __u8 selector;
-
- __u8 size;
- __u8 offset;
- __u32 v4l2_type;
- __u32 data_type;
-
- struct uvc_menu_info __user *menu_info;
- __u32 menu_count;
-
- __u32 reserved[4];
-};
-
-#endif
-
-struct uvc_xu_control_info {
- __u8 entity[16];
- __u8 index;
- __u8 selector;
- __u16 size;
- __u32 flags;
-};
-
-struct uvc_xu_control_mapping_old {
- __u8 reserved[64];
-};
-
-struct uvc_xu_control {
- __u8 unit;
- __u8 selector;
- __u16 size;
- __u8 __user *data;
-};
-
#ifndef __KERNEL__
-#define UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info)
-#define UVCIOC_CTRL_MAP_OLD _IOWR('U', 2, struct uvc_xu_control_mapping_old)
-#define UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping)
-#define UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control)
-#define UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control)
-#else
-#define __UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info)
-#define __UVCIOC_CTRL_MAP_OLD _IOWR('U', 2, struct uvc_xu_control_mapping_old)
-#define __UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping)
-#define __UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control)
-#define __UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control)
-#endif
-
-#ifdef __KERNEL__
+#error "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead."
+#endif /* __KERNEL__ */
+#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/usb.h>
#include <linux/usb/video.h>
#include <linux/uvcvideo.h>
+#include <linux/videodev2.h>
#include <media/media-device.h>
#include <media/v4l2-device.h>
@@ -179,6 +89,10 @@ struct uvc_xu_control {
{ 'M', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, \
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_H264 \
+ { 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, \
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+
/* ------------------------------------------------------------------------
* Driver specific constants.
*/
@@ -698,6 +612,4 @@ extern struct usb_host_endpoint *uvc_find_endpoint(
void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
struct uvc_buffer *buf);
-#endif /* __KERNEL__ */
-
#endif
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 06b6014d4fb4..fc8666ae408f 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -43,7 +43,7 @@ struct v4l2_ctrl_helper {
};
/* Small helper function to determine if the autocluster is set to manual
- mode. In that case the is_volatile flag should be ignored. */
+ mode. */
static bool is_cur_manual(const struct v4l2_ctrl *master)
{
return master->is_auto && master->cur.val == master->manual_mode_value;
@@ -937,9 +937,14 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
break;
}
if (update_inactive) {
- ctrl->flags &= ~V4L2_CTRL_FLAG_INACTIVE;
- if (!is_cur_manual(ctrl->cluster[0]))
+ /* Note: update_inactive can only be true for auto clusters. */
+ ctrl->flags &=
+ ~(V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_VOLATILE);
+ if (!is_cur_manual(ctrl->cluster[0])) {
ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+ if (ctrl->cluster[0]->has_volatiles)
+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+ }
}
if (changed || update_inactive) {
/* If a control was changed that was not one of the controls
@@ -1394,10 +1399,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
type, min, max,
is_menu ? cfg->menu_skip_mask : step,
def, flags, qmenu, priv);
- if (ctrl) {
+ if (ctrl)
ctrl->is_private = cfg->is_private;
- ctrl->is_volatile = cfg->is_volatile;
- }
return ctrl;
}
EXPORT_SYMBOL(v4l2_ctrl_new_custom);
@@ -1491,6 +1494,7 @@ EXPORT_SYMBOL(v4l2_ctrl_add_handler);
/* Cluster controls */
void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
{
+ bool has_volatiles = false;
int i;
/* The first control is the master control and it must not be NULL */
@@ -1500,8 +1504,11 @@ void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
if (controls[i]) {
controls[i]->cluster = controls;
controls[i]->ncontrols = ncontrols;
+ if (controls[i]->flags & V4L2_CTRL_FLAG_VOLATILE)
+ has_volatiles = true;
}
}
+ controls[0]->has_volatiles = has_volatiles;
}
EXPORT_SYMBOL(v4l2_ctrl_cluster);
@@ -1509,22 +1516,25 @@ void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
u8 manual_val, bool set_volatile)
{
struct v4l2_ctrl *master = controls[0];
- u32 flag;
+ u32 flag = 0;
int i;
v4l2_ctrl_cluster(ncontrols, controls);
WARN_ON(ncontrols <= 1);
WARN_ON(manual_val < master->minimum || manual_val > master->maximum);
+ WARN_ON(set_volatile && !has_op(master, g_volatile_ctrl));
master->is_auto = true;
+ master->has_volatiles = set_volatile;
master->manual_mode_value = manual_val;
master->flags |= V4L2_CTRL_FLAG_UPDATE;
- flag = is_cur_manual(master) ? 0 : V4L2_CTRL_FLAG_INACTIVE;
+
+ if (!is_cur_manual(master))
+ flag = V4L2_CTRL_FLAG_INACTIVE |
+ (set_volatile ? V4L2_CTRL_FLAG_VOLATILE : 0);
for (i = 1; i < ncontrols; i++)
- if (controls[i]) {
- controls[i]->is_volatile = set_volatile;
+ if (controls[i])
controls[i]->flags |= flag;
- }
}
EXPORT_SYMBOL(v4l2_ctrl_auto_cluster);
@@ -1579,9 +1589,6 @@ EXPORT_SYMBOL(v4l2_ctrl_grab);
static void log_ctrl(const struct v4l2_ctrl *ctrl,
const char *prefix, const char *colon)
{
- int fl_inact = ctrl->flags & V4L2_CTRL_FLAG_INACTIVE;
- int fl_grabbed = ctrl->flags & V4L2_CTRL_FLAG_GRABBED;
-
if (ctrl->flags & (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_WRITE_ONLY))
return;
if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
@@ -1612,14 +1619,17 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl,
printk(KERN_CONT "unknown type %d", ctrl->type);
break;
}
- if (fl_inact && fl_grabbed)
- printk(KERN_CONT " (inactive, grabbed)\n");
- else if (fl_inact)
- printk(KERN_CONT " (inactive)\n");
- else if (fl_grabbed)
- printk(KERN_CONT " (grabbed)\n");
- else
- printk(KERN_CONT "\n");
+ if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE |
+ V4L2_CTRL_FLAG_GRABBED |
+ V4L2_CTRL_FLAG_VOLATILE)) {
+ if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
+ printk(KERN_CONT " inactive");
+ if (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)
+ printk(KERN_CONT " grabbed");
+ if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE)
+ printk(KERN_CONT " volatile");
+ }
+ printk(KERN_CONT "\n");
}
/* Log all controls owned by the handler */
@@ -1959,7 +1969,8 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs
v4l2_ctrl_lock(master);
/* g_volatile_ctrl will update the new control values */
- if (has_op(master, g_volatile_ctrl) && !is_cur_manual(master)) {
+ if ((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
+ (master->has_volatiles && !is_cur_manual(master))) {
for (j = 0; j < master->ncontrols; j++)
cur_to_new(master->cluster[j]);
ret = call_op(master, g_volatile_ctrl);
@@ -2004,7 +2015,7 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
v4l2_ctrl_lock(master);
/* g_volatile_ctrl will update the current control values */
- if (ctrl->is_volatile && !is_cur_manual(master)) {
+ if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
for (i = 0; i < master->ncontrols; i++)
cur_to_new(master->cluster[i]);
ret = call_op(master, g_volatile_ctrl);
@@ -2120,6 +2131,20 @@ static int validate_ctrls(struct v4l2_ext_controls *cs,
return 0;
}
+/* Obtain the current volatile values of an autocluster and mark them
+ as new. */
+static void update_from_auto_cluster(struct v4l2_ctrl *master)
+{
+ int i;
+
+ for (i = 0; i < master->ncontrols; i++)
+ cur_to_new(master->cluster[i]);
+ if (!call_op(master, g_volatile_ctrl))
+ for (i = 1; i < master->ncontrols; i++)
+ if (master->cluster[i])
+ master->cluster[i]->is_new = 1;
+}
+
/* Try or try-and-set controls */
static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
struct v4l2_ext_controls *cs,
@@ -2165,6 +2190,31 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
if (master->cluster[j])
master->cluster[j]->is_new = 0;
+ /* For volatile autoclusters that are currently in auto mode
+ we need to discover if it will be set to manual mode.
+ If so, then we have to copy the current volatile values
+ first since those will become the new manual values (which
+ may be overwritten by explicit new values from this set
+ of controls). */
+ if (master->is_auto && master->has_volatiles &&
+ !is_cur_manual(master)) {
+ /* Pick an initial non-manual value */
+ s32 new_auto_val = master->manual_mode_value + 1;
+ u32 tmp_idx = idx;
+
+ do {
+ /* Check if the auto control is part of the
+ list, and remember the new value. */
+ if (helpers[tmp_idx].ctrl == master)
+ new_auto_val = cs->controls[tmp_idx].value;
+ tmp_idx = helpers[tmp_idx].next;
+ } while (tmp_idx);
+ /* If the new value == the manual value, then copy
+ the current volatile values. */
+ if (new_auto_val == master->manual_mode_value)
+ update_from_auto_cluster(master);
+ }
+
/* Copy the new caller-supplied control values.
user_to_new() sets 'is_new' to 1. */
do {
@@ -2235,6 +2285,12 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
if (master->cluster[i])
master->cluster[i]->is_new = 0;
+ /* For autoclusters with volatiles that are switched from auto to
+ manual mode we have to update the current volatile values since
+ those will become the initial manual values after such a switch. */
+ if (master->is_auto && master->has_volatiles && ctrl == master &&
+ !is_cur_manual(master) && *val == master->manual_mode_value)
+ update_from_auto_cluster(master);
ctrl->val = *val;
ctrl->is_new = 1;
ret = try_or_set_cluster(fh, master, true);
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 002ce1363443..24fd43322150 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -55,6 +55,19 @@
memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
+#define have_fmt_ops(foo) ( \
+ ops->vidioc_##foo##_fmt_vid_cap || \
+ ops->vidioc_##foo##_fmt_vid_out || \
+ ops->vidioc_##foo##_fmt_vid_cap_mplane || \
+ ops->vidioc_##foo##_fmt_vid_out_mplane || \
+ ops->vidioc_##foo##_fmt_vid_overlay || \
+ ops->vidioc_##foo##_fmt_vbi_cap || \
+ ops->vidioc_##foo##_fmt_vid_out_overlay || \
+ ops->vidioc_##foo##_fmt_vbi_out || \
+ ops->vidioc_##foo##_fmt_sliced_vbi_cap || \
+ ops->vidioc_##foo##_fmt_sliced_vbi_out || \
+ ops->vidioc_##foo##_fmt_type_private)
+
struct std_descr {
v4l2_std_id std;
const char *descr;
@@ -477,63 +490,6 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
return -EINVAL;
}
-/**
- * fmt_sp_to_mp() - Convert a single-plane format to its multi-planar 1-plane
- * equivalent
- */
-static int fmt_sp_to_mp(const struct v4l2_format *f_sp,
- struct v4l2_format *f_mp)
-{
- struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
- const struct v4l2_pix_format *pix = &f_sp->fmt.pix;
-
- if (f_sp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- f_mp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- else if (f_sp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
- f_mp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- else
- return -EINVAL;
-
- pix_mp->width = pix->width;
- pix_mp->height = pix->height;
- pix_mp->pixelformat = pix->pixelformat;
- pix_mp->field = pix->field;
- pix_mp->colorspace = pix->colorspace;
- pix_mp->num_planes = 1;
- pix_mp->plane_fmt[0].sizeimage = pix->sizeimage;
- pix_mp->plane_fmt[0].bytesperline = pix->bytesperline;
-
- return 0;
-}
-
-/**
- * fmt_mp_to_sp() - Convert a multi-planar 1-plane format to its single-planar
- * equivalent
- */
-static int fmt_mp_to_sp(const struct v4l2_format *f_mp,
- struct v4l2_format *f_sp)
-{
- const struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
- struct v4l2_pix_format *pix = &f_sp->fmt.pix;
-
- if (f_mp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
- f_sp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- else if (f_mp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
- f_sp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- else
- return -EINVAL;
-
- pix->width = pix_mp->width;
- pix->height = pix_mp->height;
- pix->pixelformat = pix_mp->pixelformat;
- pix->field = pix_mp->field;
- pix->colorspace = pix_mp->colorspace;
- pix->sizeimage = pix_mp->plane_fmt[0].sizeimage;
- pix->bytesperline = pix_mp->plane_fmt[0].bytesperline;
-
- return 0;
-}
-
static long __video_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
@@ -541,8 +497,8 @@ static long __video_do_ioctl(struct file *file,
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
void *fh = file->private_data;
struct v4l2_fh *vfh = NULL;
- struct v4l2_format f_copy;
int use_fh_prio = 0;
+ long ret_prio = 0;
long ret = -ENOTTY;
if (ops == NULL) {
@@ -562,39 +518,8 @@ static long __video_do_ioctl(struct file *file,
use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
}
- if (use_fh_prio) {
- switch (cmd) {
- case VIDIOC_S_CTRL:
- case VIDIOC_S_STD:
- case VIDIOC_S_INPUT:
- case VIDIOC_S_OUTPUT:
- case VIDIOC_S_TUNER:
- case VIDIOC_S_FREQUENCY:
- case VIDIOC_S_FMT:
- case VIDIOC_S_CROP:
- case VIDIOC_S_AUDIO:
- case VIDIOC_S_AUDOUT:
- case VIDIOC_S_EXT_CTRLS:
- case VIDIOC_S_FBUF:
- case VIDIOC_S_PRIORITY:
- case VIDIOC_S_DV_PRESET:
- case VIDIOC_S_DV_TIMINGS:
- case VIDIOC_S_JPEGCOMP:
- case VIDIOC_S_MODULATOR:
- case VIDIOC_S_PARM:
- case VIDIOC_S_HW_FREQ_SEEK:
- case VIDIOC_ENCODER_CMD:
- case VIDIOC_OVERLAY:
- case VIDIOC_REQBUFS:
- case VIDIOC_STREAMON:
- case VIDIOC_STREAMOFF:
- ret = v4l2_prio_check(vfd->prio, vfh->prio);
- if (ret)
- goto exit_prio;
- ret = -EINVAL;
- break;
- }
- }
+ if (use_fh_prio)
+ ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
switch (cmd) {
@@ -638,12 +563,14 @@ static long __video_do_ioctl(struct file *file,
enum v4l2_priority *p = arg;
if (!ops->vidioc_s_priority && !use_fh_prio)
- break;
+ break;
dbgarg(cmd, "setting priority to %d\n", *p);
if (ops->vidioc_s_priority)
ret = ops->vidioc_s_priority(file, fh, *p);
else
- ret = v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
+ ret = ret_prio ? ret_prio :
+ v4l2_prio_change(&vfd->v4l2_dev->prio,
+ &vfh->prio, *p);
break;
}
@@ -654,37 +581,37 @@ static long __video_do_ioctl(struct file *file,
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (ops->vidioc_enum_fmt_vid_cap)
+ if (likely(ops->vidioc_enum_fmt_vid_cap))
ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- if (ops->vidioc_enum_fmt_vid_cap_mplane)
+ if (likely(ops->vidioc_enum_fmt_vid_cap_mplane))
ret = ops->vidioc_enum_fmt_vid_cap_mplane(file,
fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (ops->vidioc_enum_fmt_vid_overlay)
+ if (likely(ops->vidioc_enum_fmt_vid_overlay))
ret = ops->vidioc_enum_fmt_vid_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (ops->vidioc_enum_fmt_vid_out)
+ if (likely(ops->vidioc_enum_fmt_vid_out))
ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- if (ops->vidioc_enum_fmt_vid_out_mplane)
+ if (likely(ops->vidioc_enum_fmt_vid_out_mplane))
ret = ops->vidioc_enum_fmt_vid_out_mplane(file,
fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
- if (ops->vidioc_enum_fmt_type_private)
+ if (likely(ops->vidioc_enum_fmt_type_private))
ret = ops->vidioc_enum_fmt_type_private(file,
fh, f);
break;
default:
break;
}
- if (!ret)
+ if (likely (!ret))
dbgarg(cmd, "index=%d, type=%d, flags=%d, "
"pixelformat=%c%c%c%c, description='%s'\n",
f->index, f->type, f->flags,
@@ -693,6 +620,14 @@ static long __video_do_ioctl(struct file *file,
(f->pixelformat >> 16) & 0xff,
(f->pixelformat >> 24) & 0xff,
f->description);
+ else if (ret == -ENOTTY &&
+ (ops->vidioc_enum_fmt_vid_cap ||
+ ops->vidioc_enum_fmt_vid_out ||
+ ops->vidioc_enum_fmt_vid_cap_mplane ||
+ ops->vidioc_enum_fmt_vid_out_mplane ||
+ ops->vidioc_enum_fmt_vid_overlay ||
+ ops->vidioc_enum_fmt_type_private))
+ ret = -EINVAL;
break;
}
case VIDIOC_G_FMT:
@@ -704,119 +639,67 @@ static long __video_do_ioctl(struct file *file,
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (ops->vidioc_g_fmt_vid_cap) {
+ if (ops->vidioc_g_fmt_vid_cap)
ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
- } else if (ops->vidioc_g_fmt_vid_cap_mplane) {
- if (fmt_sp_to_mp(f, &f_copy))
- break;
- ret = ops->vidioc_g_fmt_vid_cap_mplane(file, fh,
- &f_copy);
- if (ret)
- break;
-
- /* Driver is currently in multi-planar format,
- * we can't return it in single-planar API*/
- if (f_copy.fmt.pix_mp.num_planes > 1) {
- ret = -EBUSY;
- break;
- }
-
- ret = fmt_mp_to_sp(&f_copy, f);
- }
if (!ret)
v4l_print_pix_fmt(vfd, &f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- if (ops->vidioc_g_fmt_vid_cap_mplane) {
+ if (ops->vidioc_g_fmt_vid_cap_mplane)
ret = ops->vidioc_g_fmt_vid_cap_mplane(file,
fh, f);
- } else if (ops->vidioc_g_fmt_vid_cap) {
- if (fmt_mp_to_sp(f, &f_copy))
- break;
- ret = ops->vidioc_g_fmt_vid_cap(file,
- fh, &f_copy);
- if (ret)
- break;
-
- ret = fmt_sp_to_mp(&f_copy, f);
- }
if (!ret)
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (ops->vidioc_g_fmt_vid_overlay)
+ if (likely(ops->vidioc_g_fmt_vid_overlay))
ret = ops->vidioc_g_fmt_vid_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (ops->vidioc_g_fmt_vid_out) {
+ if (ops->vidioc_g_fmt_vid_out)
ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
- } else if (ops->vidioc_g_fmt_vid_out_mplane) {
- if (fmt_sp_to_mp(f, &f_copy))
- break;
- ret = ops->vidioc_g_fmt_vid_out_mplane(file, fh,
- &f_copy);
- if (ret)
- break;
-
- /* Driver is currently in multi-planar format,
- * we can't return it in single-planar API*/
- if (f_copy.fmt.pix_mp.num_planes > 1) {
- ret = -EBUSY;
- break;
- }
-
- ret = fmt_mp_to_sp(&f_copy, f);
- }
if (!ret)
v4l_print_pix_fmt(vfd, &f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- if (ops->vidioc_g_fmt_vid_out_mplane) {
+ if (ops->vidioc_g_fmt_vid_out_mplane)
ret = ops->vidioc_g_fmt_vid_out_mplane(file,
fh, f);
- } else if (ops->vidioc_g_fmt_vid_out) {
- if (fmt_mp_to_sp(f, &f_copy))
- break;
- ret = ops->vidioc_g_fmt_vid_out(file,
- fh, &f_copy);
- if (ret)
- break;
-
- ret = fmt_sp_to_mp(&f_copy, f);
- }
if (!ret)
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
- if (ops->vidioc_g_fmt_vid_out_overlay)
+ if (likely(ops->vidioc_g_fmt_vid_out_overlay))
ret = ops->vidioc_g_fmt_vid_out_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
- if (ops->vidioc_g_fmt_vbi_cap)
+ if (likely(ops->vidioc_g_fmt_vbi_cap))
ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
- if (ops->vidioc_g_fmt_vbi_out)
+ if (likely(ops->vidioc_g_fmt_vbi_out))
ret = ops->vidioc_g_fmt_vbi_out(file, fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- if (ops->vidioc_g_fmt_sliced_vbi_cap)
+ if (likely(ops->vidioc_g_fmt_sliced_vbi_cap))
ret = ops->vidioc_g_fmt_sliced_vbi_cap(file,
fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- if (ops->vidioc_g_fmt_sliced_vbi_out)
+ if (likely(ops->vidioc_g_fmt_sliced_vbi_out))
ret = ops->vidioc_g_fmt_sliced_vbi_out(file,
fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
- if (ops->vidioc_g_fmt_type_private)
+ if (likely(ops->vidioc_g_fmt_type_private))
ret = ops->vidioc_g_fmt_type_private(file,
fh, f);
break;
}
+ if (unlikely(ret == -ENOTTY && have_fmt_ops(g)))
+ ret = -EINVAL;
break;
}
@@ -824,6 +707,14 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_format *f = (struct v4l2_format *)arg;
+ if (!have_fmt_ops(s))
+ break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
+ ret = -EINVAL;
+
/* FIXME: Should be one dump per type */
dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
@@ -831,44 +722,15 @@ static long __video_do_ioctl(struct file *file,
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.pix);
v4l_print_pix_fmt(vfd, &f->fmt.pix);
- if (ops->vidioc_s_fmt_vid_cap) {
+ if (ops->vidioc_s_fmt_vid_cap)
ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
- } else if (ops->vidioc_s_fmt_vid_cap_mplane) {
- if (fmt_sp_to_mp(f, &f_copy))
- break;
- ret = ops->vidioc_s_fmt_vid_cap_mplane(file, fh,
- &f_copy);
- if (ret)
- break;
-
- if (f_copy.fmt.pix_mp.num_planes > 1) {
- /* Drivers shouldn't adjust from 1-plane
- * to more than 1-plane formats */
- ret = -EBUSY;
- WARN_ON(1);
- break;
- }
-
- ret = fmt_mp_to_sp(&f_copy, f);
- }
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
CLEAR_AFTER_FIELD(f, fmt.pix_mp);
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
- if (ops->vidioc_s_fmt_vid_cap_mplane) {
+ if (ops->vidioc_s_fmt_vid_cap_mplane)
ret = ops->vidioc_s_fmt_vid_cap_mplane(file,
fh, f);
- } else if (ops->vidioc_s_fmt_vid_cap &&
- f->fmt.pix_mp.num_planes == 1) {
- if (fmt_mp_to_sp(f, &f_copy))
- break;
- ret = ops->vidioc_s_fmt_vid_cap(file,
- fh, &f_copy);
- if (ret)
- break;
-
- ret = fmt_sp_to_mp(&f_copy, f);
- }
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
CLEAR_AFTER_FIELD(f, fmt.win);
@@ -879,44 +741,15 @@ static long __video_do_ioctl(struct file *file,
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.pix);
v4l_print_pix_fmt(vfd, &f->fmt.pix);
- if (ops->vidioc_s_fmt_vid_out) {
+ if (ops->vidioc_s_fmt_vid_out)
ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
- } else if (ops->vidioc_s_fmt_vid_out_mplane) {
- if (fmt_sp_to_mp(f, &f_copy))
- break;
- ret = ops->vidioc_s_fmt_vid_out_mplane(file, fh,
- &f_copy);
- if (ret)
- break;
-
- if (f_copy.fmt.pix_mp.num_planes > 1) {
- /* Drivers shouldn't adjust from 1-plane
- * to more than 1-plane formats */
- ret = -EBUSY;
- WARN_ON(1);
- break;
- }
-
- ret = fmt_mp_to_sp(&f_copy, f);
- }
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
CLEAR_AFTER_FIELD(f, fmt.pix_mp);
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
- if (ops->vidioc_s_fmt_vid_out_mplane) {
+ if (ops->vidioc_s_fmt_vid_out_mplane)
ret = ops->vidioc_s_fmt_vid_out_mplane(file,
fh, f);
- } else if (ops->vidioc_s_fmt_vid_out &&
- f->fmt.pix_mp.num_planes == 1) {
- if (fmt_mp_to_sp(f, &f_copy))
- break;
- ret = ops->vidioc_s_fmt_vid_out(file,
- fh, &f_copy);
- if (ret)
- break;
-
- ret = fmt_mp_to_sp(&f_copy, f);
- }
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
CLEAR_AFTER_FIELD(f, fmt.win);
@@ -926,29 +759,30 @@ static long __video_do_ioctl(struct file *file,
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.vbi);
- if (ops->vidioc_s_fmt_vbi_cap)
+ if (likely(ops->vidioc_s_fmt_vbi_cap))
ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.vbi);
- if (ops->vidioc_s_fmt_vbi_out)
+ if (likely(ops->vidioc_s_fmt_vbi_out))
ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.sliced);
- if (ops->vidioc_s_fmt_sliced_vbi_cap)
+ if (likely(ops->vidioc_s_fmt_sliced_vbi_cap))
ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.sliced);
- if (ops->vidioc_s_fmt_sliced_vbi_out)
+ if (likely(ops->vidioc_s_fmt_sliced_vbi_out))
ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
fh, f);
+
break;
case V4L2_BUF_TYPE_PRIVATE:
/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
- if (ops->vidioc_s_fmt_type_private)
+ if (likely(ops->vidioc_s_fmt_type_private))
ret = ops->vidioc_s_fmt_type_private(file,
fh, f);
break;
@@ -965,132 +799,77 @@ static long __video_do_ioctl(struct file *file,
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.pix);
- if (ops->vidioc_try_fmt_vid_cap) {
+ if (ops->vidioc_try_fmt_vid_cap)
ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
- } else if (ops->vidioc_try_fmt_vid_cap_mplane) {
- if (fmt_sp_to_mp(f, &f_copy))
- break;
- ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
- fh, &f_copy);
- if (ret)
- break;
-
- if (f_copy.fmt.pix_mp.num_planes > 1) {
- /* Drivers shouldn't adjust from 1-plane
- * to more than 1-plane formats */
- ret = -EBUSY;
- WARN_ON(1);
- break;
- }
- ret = fmt_mp_to_sp(&f_copy, f);
- }
if (!ret)
v4l_print_pix_fmt(vfd, &f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
CLEAR_AFTER_FIELD(f, fmt.pix_mp);
- if (ops->vidioc_try_fmt_vid_cap_mplane) {
+ if (ops->vidioc_try_fmt_vid_cap_mplane)
ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
fh, f);
- } else if (ops->vidioc_try_fmt_vid_cap &&
- f->fmt.pix_mp.num_planes == 1) {
- if (fmt_mp_to_sp(f, &f_copy))
- break;
- ret = ops->vidioc_try_fmt_vid_cap(file,
- fh, &f_copy);
- if (ret)
- break;
-
- ret = fmt_sp_to_mp(&f_copy, f);
- }
if (!ret)
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
CLEAR_AFTER_FIELD(f, fmt.win);
- if (ops->vidioc_try_fmt_vid_overlay)
+ if (likely(ops->vidioc_try_fmt_vid_overlay))
ret = ops->vidioc_try_fmt_vid_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.pix);
- if (ops->vidioc_try_fmt_vid_out) {
+ if (ops->vidioc_try_fmt_vid_out)
ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
- } else if (ops->vidioc_try_fmt_vid_out_mplane) {
- if (fmt_sp_to_mp(f, &f_copy))
- break;
- ret = ops->vidioc_try_fmt_vid_out_mplane(file,
- fh, &f_copy);
- if (ret)
- break;
-
- if (f_copy.fmt.pix_mp.num_planes > 1) {
- /* Drivers shouldn't adjust from 1-plane
- * to more than 1-plane formats */
- ret = -EBUSY;
- WARN_ON(1);
- break;
- }
- ret = fmt_mp_to_sp(&f_copy, f);
- }
if (!ret)
v4l_print_pix_fmt(vfd, &f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
CLEAR_AFTER_FIELD(f, fmt.pix_mp);
- if (ops->vidioc_try_fmt_vid_out_mplane) {
+ if (ops->vidioc_try_fmt_vid_out_mplane)
ret = ops->vidioc_try_fmt_vid_out_mplane(file,
fh, f);
- } else if (ops->vidioc_try_fmt_vid_out &&
- f->fmt.pix_mp.num_planes == 1) {
- if (fmt_mp_to_sp(f, &f_copy))
- break;
- ret = ops->vidioc_try_fmt_vid_out(file,
- fh, &f_copy);
- if (ret)
- break;
-
- ret = fmt_sp_to_mp(&f_copy, f);
- }
if (!ret)
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
CLEAR_AFTER_FIELD(f, fmt.win);
- if (ops->vidioc_try_fmt_vid_out_overlay)
+ if (likely(ops->vidioc_try_fmt_vid_out_overlay))
ret = ops->vidioc_try_fmt_vid_out_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.vbi);
- if (ops->vidioc_try_fmt_vbi_cap)
+ if (likely(ops->vidioc_try_fmt_vbi_cap))
ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.vbi);
- if (ops->vidioc_try_fmt_vbi_out)
+ if (likely(ops->vidioc_try_fmt_vbi_out))
ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.sliced);
- if (ops->vidioc_try_fmt_sliced_vbi_cap)
+ if (likely(ops->vidioc_try_fmt_sliced_vbi_cap))
ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.sliced);
- if (ops->vidioc_try_fmt_sliced_vbi_out)
+ if (likely(ops->vidioc_try_fmt_sliced_vbi_out))
ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
- if (ops->vidioc_try_fmt_type_private)
+ if (likely(ops->vidioc_try_fmt_type_private))
ret = ops->vidioc_try_fmt_type_private(file,
fh, f);
break;
}
-
+ if (unlikely(ret == -ENOTTY && have_fmt_ops(try)))
+ ret = -EINVAL;
break;
}
/* FIXME: Those buf reqs could be handled here,
@@ -1103,6 +882,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_reqbufs)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -1168,6 +951,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_overlay)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_overlay(file, fh, *i);
break;
@@ -1193,6 +980,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_fbuf)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
p->capability, p->flags, (unsigned long)p->base);
v4l_print_pix_fmt(vfd, &p->fmt);
@@ -1205,6 +996,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_streamon)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
ret = ops->vidioc_streamon(file, fh, i);
break;
@@ -1215,6 +1010,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_streamoff)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
ret = ops->vidioc_streamoff(file, fh, i);
break;
@@ -1227,6 +1026,10 @@ static long __video_do_ioctl(struct file *file,
unsigned int index = p->index, i, j = 0;
const char *descr = "";
+ if (id == 0)
+ break;
+ ret = -EINVAL;
+
/* Return norm array in a canonical way */
for (i = 0; i <= index && id; i++) {
/* last std value in the standards array is 0, so this
@@ -1262,16 +1065,15 @@ static long __video_do_ioctl(struct file *file,
{
v4l2_std_id *id = arg;
- ret = 0;
/* Calls the specific handler */
if (ops->vidioc_g_std)
ret = ops->vidioc_g_std(file, fh, id);
- else if (vfd->current_norm)
+ else if (vfd->current_norm) {
+ ret = 0;
*id = vfd->current_norm;
- else
- ret = -EINVAL;
+ }
- if (!ret)
+ if (likely(!ret))
dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
break;
}
@@ -1281,15 +1083,20 @@ static long __video_do_ioctl(struct file *file,
dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
+ if (!ops->vidioc_s_std)
+ break;
+
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
+ ret = -EINVAL;
norm = (*id) & vfd->tvnorms;
if (vfd->tvnorms && !norm) /* Check if std is supported */
break;
/* Calls the specific handler */
- if (ops->vidioc_s_std)
- ret = ops->vidioc_s_std(file, fh, &norm);
- else
- ret = -EINVAL;
+ ret = ops->vidioc_s_std(file, fh, &norm);
/* Updates standard information */
if (ret >= 0)
@@ -1302,6 +1109,14 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_querystd)
break;
+ /*
+ * If nothing detected, it should return all supported
+ * Drivers just need to mask the std argument, in order
+ * to remove the standards that don't apply from the mask.
+ * This means that tuners, audio and video decoders can join
+ * their efforts to improve the standards detection
+ */
+ *p = vfd->tvnorms;
ret = ops->vidioc_querystd(file, fh, arg);
if (!ret)
dbgarg(cmd, "detected std=%08Lx\n",
@@ -1358,6 +1173,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_input)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_s_input(file, fh, *i);
break;
@@ -1410,6 +1229,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_output)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_s_output(file, fh, *i);
break;
@@ -1479,6 +1302,10 @@ static long __video_do_ioctl(struct file *file,
if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
@@ -1504,6 +1331,8 @@ static long __video_do_ioctl(struct file *file,
ctrl.value = p->value;
if (check_ext_ctrls(&ctrls, 1))
ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
+ else
+ ret = -EINVAL;
break;
}
case VIDIOC_G_EXT_CTRLS:
@@ -1515,8 +1344,10 @@ static long __video_do_ioctl(struct file *file,
ret = v4l2_g_ext_ctrls(vfh->ctrl_handler, p);
else if (vfd->ctrl_handler)
ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
- else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))
- ret = ops->vidioc_g_ext_ctrls(file, fh, p);
+ else if (ops->vidioc_g_ext_ctrls)
+ ret = check_ext_ctrls(p, 0) ?
+ ops->vidioc_g_ext_ctrls(file, fh, p) :
+ -EINVAL;
else
break;
v4l_print_ext_ctrls(cmd, vfd, p, !ret);
@@ -1530,6 +1361,10 @@ static long __video_do_ioctl(struct file *file,
if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
!ops->vidioc_s_ext_ctrls)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
v4l_print_ext_ctrls(cmd, vfd, p, 1);
if (vfh && vfh->ctrl_handler)
ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
@@ -1537,6 +1372,8 @@ static long __video_do_ioctl(struct file *file,
ret = v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p);
else if (check_ext_ctrls(p, 0))
ret = ops->vidioc_s_ext_ctrls(file, fh, p);
+ else
+ ret = -EINVAL;
break;
}
case VIDIOC_TRY_EXT_CTRLS:
@@ -1554,6 +1391,8 @@ static long __video_do_ioctl(struct file *file,
ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
else if (check_ext_ctrls(p, 0))
ret = ops->vidioc_try_ext_ctrls(file, fh, p);
+ else
+ ret = -EINVAL;
break;
}
case VIDIOC_QUERYMENU:
@@ -1614,6 +1453,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_audio)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
"mode=0x%x\n", p->index, p->name,
p->capability, p->mode);
@@ -1654,6 +1497,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_audout)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "index=%d, name=%s, capability=%d, "
"mode=%d\n", p->index, p->name,
p->capability, p->mode);
@@ -1683,6 +1530,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_modulator)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "index=%d, name=%s, capability=%d, "
"rangelow=%d, rangehigh=%d, txsubchans=%d\n",
p->index, p->name, p->capability, p->rangelow,
@@ -1709,6 +1560,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_crop)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
dbgrect(vfd, "", &p->c);
ret = ops->vidioc_s_crop(file, fh, p);
@@ -1752,11 +1607,15 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_g_jpegcomp)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
"COM_len=%d, jpeg_markers=%d\n",
p->quality, p->APPn, p->APP_len,
p->COM_len, p->jpeg_markers);
- ret = ops->vidioc_s_jpegcomp(file, fh, p);
+ ret = ops->vidioc_s_jpegcomp(file, fh, p);
break;
}
case VIDIOC_G_ENC_INDEX:
@@ -1777,6 +1636,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_encoder_cmd)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
ret = ops->vidioc_encoder_cmd(file, fh, p);
if (!ret)
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1797,6 +1660,8 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_streamparm *p = arg;
+ if (!ops->vidioc_g_parm && !vfd->current_norm)
+ break;
if (ops->vidioc_g_parm) {
ret = check_fmt(ops, p->type);
if (ret)
@@ -1805,14 +1670,13 @@ static long __video_do_ioctl(struct file *file,
} else {
v4l2_std_id std = vfd->current_norm;
+ ret = -EINVAL;
if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
break;
ret = 0;
if (ops->vidioc_g_std)
ret = ops->vidioc_g_std(file, fh, &std);
- else if (std == 0)
- ret = -EINVAL;
if (ret == 0)
v4l2_video_std_frame_period(std,
&p->parm.capture.timeperframe);
@@ -1827,6 +1691,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_parm)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -1862,6 +1730,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_tuner)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1896,6 +1768,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_frequency)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
p->tuner, p->type, p->frequency);
ret = ops->vidioc_s_frequency(file, fh, p);
@@ -1970,6 +1846,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_hw_freq_seek)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd,
@@ -2074,6 +1954,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_dv_preset)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
dbgarg(cmd, "preset=%d\n", p->preset);
ret = ops->vidioc_s_dv_preset(file, fh, p);
@@ -2109,6 +1993,10 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_s_dv_timings)
break;
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
switch (p->type) {
case V4L2_DV_BT_656_1120:
@@ -2217,19 +2105,12 @@ static long __video_do_ioctl(struct file *file,
break;
}
default:
- {
- bool valid_prio = true;
-
if (!ops->vidioc_default)
break;
- if (use_fh_prio)
- valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0;
- ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg);
+ ret = ops->vidioc_default(file, fh, ret_prio >= 0, cmd, arg);
break;
- }
} /* switch */
-exit_prio:
if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
if (ret < 0) {
v4l_print_ioctl(vfd->name, cmd);
diff --git a/drivers/media/video/v4l2-mem2mem.c b/drivers/media/video/v4l2-mem2mem.c
index 3b15bf5892a8..975d0fa938c6 100644
--- a/drivers/media/video/v4l2-mem2mem.c
+++ b/drivers/media/video/v4l2-mem2mem.c
@@ -97,11 +97,12 @@ void *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx)
spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
- if (list_empty(&q_ctx->rdy_queue))
- goto end;
+ if (list_empty(&q_ctx->rdy_queue)) {
+ spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
+ return NULL;
+ }
b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer, list);
-end:
spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
return &b->vb;
}
@@ -117,12 +118,13 @@ void *v4l2_m2m_buf_remove(struct v4l2_m2m_queue_ctx *q_ctx)
unsigned long flags;
spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
- if (!list_empty(&q_ctx->rdy_queue)) {
- b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer,
- list);
- list_del(&b->list);
- q_ctx->num_rdy--;
+ if (list_empty(&q_ctx->rdy_queue)) {
+ spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
+ return NULL;
}
+ b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer, list);
+ list_del(&b->list);
+ q_ctx->num_rdy--;
spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
return &b->vb;
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index b7967c9dc4ae..179e20e23fc4 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -173,6 +173,25 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_UNSUBSCRIBE_EVENT:
return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg);
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_DBG_G_REGISTER:
+ {
+ struct v4l2_dbg_register *p = arg;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ return v4l2_subdev_call(sd, core, g_register, p);
+ }
+ case VIDIOC_DBG_S_REGISTER:
+ {
+ struct v4l2_dbg_register *p = arg;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ return v4l2_subdev_call(sd, core, s_register, p);
+ }
+#endif
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
case VIDIOC_SUBDEV_G_FMT: {
struct v4l2_subdev_format *format = arg;
diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c
index bb7f17f2a33c..cbf13d09b4ac 100644
--- a/drivers/media/video/via-camera.c
+++ b/drivers/media/video/via-camera.c
@@ -21,7 +21,7 @@
#include <media/videobuf-dma-sg.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
#include <linux/via-core.h>
#include <linux/via-gpio.h>
#include <linux/via_i2c.h>
@@ -69,7 +69,7 @@ struct via_camera {
struct mutex lock;
enum viacam_opstate opstate;
unsigned long flags;
- struct pm_qos_request_list qos_request;
+ struct pm_qos_request qos_request;
/*
* GPIO info for power/reset management
*/
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index 3015e6000946..3f5c7a38e6e8 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -43,8 +43,7 @@ module_param(debug, int, 0644);
/**
* __vb2_buf_mem_alloc() - allocate video memory for the given buffer
*/
-static int __vb2_buf_mem_alloc(struct vb2_buffer *vb,
- unsigned long *plane_sizes)
+static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
{
struct vb2_queue *q = vb->vb2_queue;
void *mem_priv;
@@ -53,13 +52,13 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb,
/* Allocate memory for all planes in this buffer */
for (plane = 0; plane < vb->num_planes; ++plane) {
mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
- plane_sizes[plane]);
+ q->plane_sizes[plane]);
if (IS_ERR_OR_NULL(mem_priv))
goto free;
/* Associate allocator private data with this plane */
vb->planes[plane].mem_priv = mem_priv;
- vb->v4l2_planes[plane].length = plane_sizes[plane];
+ vb->v4l2_planes[plane].length = q->plane_sizes[plane];
}
return 0;
@@ -141,8 +140,7 @@ static void __setup_offsets(struct vb2_queue *q)
* Returns the number of buffers successfully allocated.
*/
static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
- unsigned int num_buffers, unsigned int num_planes,
- unsigned long plane_sizes[])
+ unsigned int num_buffers, unsigned int num_planes)
{
unsigned int buffer;
struct vb2_buffer *vb;
@@ -169,7 +167,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
/* Allocate video buffer memory for the MMAP type */
if (memory == V4L2_MEMORY_MMAP) {
- ret = __vb2_buf_mem_alloc(vb, plane_sizes);
+ ret = __vb2_buf_mem_alloc(vb);
if (ret) {
dprintk(1, "Failed allocating memory for "
"buffer %d\n", buffer);
@@ -279,6 +277,41 @@ static int __verify_planes_array(struct vb2_buffer *vb, struct v4l2_buffer *b)
}
/**
+ * __buffer_in_use() - return true if the buffer is in use and
+ * the queue cannot be freed (by the means of REQBUFS(0)) call
+ */
+static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
+{
+ unsigned int plane;
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ /*
+ * If num_users() has not been provided, call_memop
+ * will return 0, apparently nobody cares about this
+ * case anyway. If num_users() returns more than 1,
+ * we are not the only user of the plane's memory.
+ */
+ if (call_memop(q, plane, num_users,
+ vb->planes[plane].mem_priv) > 1)
+ return true;
+ }
+ return false;
+}
+
+/**
+ * __buffers_in_use() - return true if any buffers on the queue are in use and
+ * the queue cannot be freed (by the means of REQBUFS(0)) call
+ */
+static bool __buffers_in_use(struct vb2_queue *q)
+{
+ unsigned int buffer;
+ for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+ if (__buffer_in_use(q, q->bufs[buffer]))
+ return true;
+ }
+ return false;
+}
+
+/**
* __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
* returned to userspace
*/
@@ -337,7 +370,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
break;
}
- if (vb->num_planes_mapped == vb->num_planes)
+ if (__buffer_in_use(q, vb))
b->flags |= V4L2_BUF_FLAG_MAPPED;
return ret;
@@ -402,33 +435,6 @@ static int __verify_mmap_ops(struct vb2_queue *q)
}
/**
- * __buffers_in_use() - return true if any buffers on the queue are in use and
- * the queue cannot be freed (by the means of REQBUFS(0)) call
- */
-static bool __buffers_in_use(struct vb2_queue *q)
-{
- unsigned int buffer, plane;
- struct vb2_buffer *vb;
-
- for (buffer = 0; buffer < q->num_buffers; ++buffer) {
- vb = q->bufs[buffer];
- for (plane = 0; plane < vb->num_planes; ++plane) {
- /*
- * If num_users() has not been provided, call_memop
- * will return 0, apparently nobody cares about this
- * case anyway. If num_users() returns more than 1,
- * we are not the only user of the plane's memory.
- */
- if (call_memop(q, plane, num_users,
- vb->planes[plane].mem_priv) > 1)
- return true;
- }
- }
-
- return false;
-}
-
-/**
* vb2_reqbufs() - Initiate streaming
* @q: videobuf2 queue
* @req: struct passed from userspace to vidioc_reqbufs handler in driver
@@ -454,7 +460,6 @@ static bool __buffers_in_use(struct vb2_queue *q)
int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
{
unsigned int num_buffers, num_planes;
- unsigned long plane_sizes[VIDEO_MAX_PLANES];
int ret = 0;
if (q->fileio) {
@@ -516,7 +521,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
* Make sure the requested values and current defaults are sane.
*/
num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
- memset(plane_sizes, 0, sizeof(plane_sizes));
+ memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
q->memory = req->memory;
@@ -525,13 +530,12 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
* Driver also sets the size and allocator context for each plane.
*/
ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
- plane_sizes, q->alloc_ctx);
+ q->plane_sizes, q->alloc_ctx);
if (ret)
return ret;
/* Finally, allocate buffers and video memory */
- ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes,
- plane_sizes);
+ ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
if (ret == 0) {
dprintk(1, "Memory allocation failed\n");
return -ENOMEM;
@@ -545,7 +549,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
orig_num_buffers = num_buffers = ret;
ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
- plane_sizes, q->alloc_ctx);
+ q->plane_sizes, q->alloc_ctx);
if (ret)
goto free_mem;
@@ -745,12 +749,20 @@ static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b)
dprintk(3, "qbuf: userspace address for plane %d changed, "
"reacquiring memory\n", plane);
+ /* Check if the provided plane buffer is large enough */
+ if (planes[plane].length < q->plane_sizes[plane]) {
+ ret = -EINVAL;
+ goto err;
+ }
+
/* Release previously acquired memory if present */
if (vb->planes[plane].mem_priv)
call_memop(q, plane, put_userptr,
vb->planes[plane].mem_priv);
vb->planes[plane].mem_priv = NULL;
+ vb->v4l2_planes[plane].m.userptr = 0;
+ vb->v4l2_planes[plane].length = 0;
/* Acquire each plane's memory */
if (q->mem_ops->get_userptr) {
@@ -788,10 +800,13 @@ static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b)
return 0;
err:
/* In case of errors, release planes that were already acquired */
- for (; plane > 0; --plane) {
- call_memop(q, plane, put_userptr,
- vb->planes[plane - 1].mem_priv);
- vb->planes[plane - 1].mem_priv = NULL;
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ if (vb->planes[plane].mem_priv)
+ call_memop(q, plane, put_userptr,
+ vb->planes[plane].mem_priv);
+ vb->planes[plane].mem_priv = NULL;
+ vb->v4l2_planes[plane].m.userptr = 0;
+ vb->v4l2_planes[plane].length = 0;
}
return ret;
@@ -1096,6 +1111,43 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
EXPORT_SYMBOL_GPL(vb2_dqbuf);
/**
+ * __vb2_queue_cancel() - cancel and stop (pause) streaming
+ *
+ * Removes all queued buffers from driver's queue and all buffers queued by
+ * userspace from videobuf's queue. Returns to state after reqbufs.
+ */
+static void __vb2_queue_cancel(struct vb2_queue *q)
+{
+ unsigned int i;
+
+ /*
+ * Tell driver to stop all transactions and release all queued
+ * buffers.
+ */
+ if (q->streaming)
+ call_qop(q, stop_streaming, q);
+ q->streaming = 0;
+
+ /*
+ * Remove all buffers from videobuf's list...
+ */
+ INIT_LIST_HEAD(&q->queued_list);
+ /*
+ * ...and done list; userspace will not receive any buffers it
+ * has not already dequeued before initiating cancel.
+ */
+ INIT_LIST_HEAD(&q->done_list);
+ atomic_set(&q->queued_count, 0);
+ wake_up_all(&q->done_wq);
+
+ /*
+ * Reinitialize all buffers for next use.
+ */
+ for (i = 0; i < q->num_buffers; ++i)
+ q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED;
+}
+
+/**
* vb2_streamon - start streaming
* @q: videobuf2 queue
* @type: type argument passed from userspace to vidioc_streamon handler
@@ -1103,7 +1155,7 @@ EXPORT_SYMBOL_GPL(vb2_dqbuf);
* Should be called from vidioc_streamon handler of a driver.
* This function:
* 1) verifies current state
- * 2) starts streaming and passes any previously queued buffers to the driver
+ * 2) passes any previously queued buffers to the driver and starts streaming
*
* The return values from this function are intended to be directly returned
* from vidioc_streamon handler in the driver.
@@ -1129,75 +1181,29 @@ int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
}
/*
- * Cannot start streaming on an OUTPUT device if no buffers have
- * been queued yet.
+ * If any buffers were queued before streamon,
+ * we can now pass them to driver for processing.
*/
- if (V4L2_TYPE_IS_OUTPUT(q->type)) {
- if (list_empty(&q->queued_list)) {
- dprintk(1, "streamon: no output buffers queued\n");
- return -EINVAL;
- }
- }
+ list_for_each_entry(vb, &q->queued_list, queued_entry)
+ __enqueue_in_driver(vb);
/*
* Let driver notice that streaming state has been enabled.
*/
- ret = call_qop(q, start_streaming, q);
+ ret = call_qop(q, start_streaming, q, atomic_read(&q->queued_count));
if (ret) {
dprintk(1, "streamon: driver refused to start streaming\n");
+ __vb2_queue_cancel(q);
return ret;
}
q->streaming = 1;
- /*
- * If any buffers were queued before streamon,
- * we can now pass them to driver for processing.
- */
- list_for_each_entry(vb, &q->queued_list, queued_entry)
- __enqueue_in_driver(vb);
-
dprintk(3, "Streamon successful\n");
return 0;
}
EXPORT_SYMBOL_GPL(vb2_streamon);
-/**
- * __vb2_queue_cancel() - cancel and stop (pause) streaming
- *
- * Removes all queued buffers from driver's queue and all buffers queued by
- * userspace from videobuf's queue. Returns to state after reqbufs.
- */
-static void __vb2_queue_cancel(struct vb2_queue *q)
-{
- unsigned int i;
-
- /*
- * Tell driver to stop all transactions and release all queued
- * buffers.
- */
- if (q->streaming)
- call_qop(q, stop_streaming, q);
- q->streaming = 0;
-
- /*
- * Remove all buffers from videobuf's list...
- */
- INIT_LIST_HEAD(&q->queued_list);
- /*
- * ...and done list; userspace will not receive any buffers it
- * has not already dequeued before initiating cancel.
- */
- INIT_LIST_HEAD(&q->done_list);
- atomic_set(&q->queued_count, 0);
- wake_up_all(&q->done_wq);
-
- /*
- * Reinitialize all buffers for next use.
- */
- for (i = 0; i < q->num_buffers; ++i)
- q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED;
-}
/**
* vb2_streamoff - stop streaming
@@ -1336,9 +1342,6 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
if (ret)
return ret;
- vb_plane->mapped = 1;
- vb->num_planes_mapped++;
-
dprintk(3, "Buffer %d, plane %d successfully mapped\n", buffer, plane);
return 0;
}
diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index a790a5f8c06f..f17ad98fcc5f 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -24,7 +24,7 @@ struct vb2_dc_conf {
struct vb2_dc_buf {
struct vb2_dc_conf *conf;
void *vaddr;
- dma_addr_t paddr;
+ dma_addr_t dma_addr;
unsigned long size;
struct vm_area_struct *vma;
atomic_t refcount;
@@ -42,7 +42,7 @@ static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
if (!buf)
return ERR_PTR(-ENOMEM);
- buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->paddr,
+ buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->dma_addr,
GFP_KERNEL);
if (!buf->vaddr) {
dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
@@ -69,7 +69,7 @@ static void vb2_dma_contig_put(void *buf_priv)
if (atomic_dec_and_test(&buf->refcount)) {
dma_free_coherent(buf->conf->dev, buf->size, buf->vaddr,
- buf->paddr);
+ buf->dma_addr);
kfree(buf);
}
}
@@ -78,7 +78,7 @@ static void *vb2_dma_contig_cookie(void *buf_priv)
{
struct vb2_dc_buf *buf = buf_priv;
- return &buf->paddr;
+ return &buf->dma_addr;
}
static void *vb2_dma_contig_vaddr(void *buf_priv)
@@ -106,7 +106,7 @@ static int vb2_dma_contig_mmap(void *buf_priv, struct vm_area_struct *vma)
return -EINVAL;
}
- return vb2_mmap_pfn_range(vma, buf->paddr, buf->size,
+ return vb2_mmap_pfn_range(vma, buf->dma_addr, buf->size,
&vb2_common_vm_ops, &buf->handler);
}
@@ -115,14 +115,14 @@ static void *vb2_dma_contig_get_userptr(void *alloc_ctx, unsigned long vaddr,
{
struct vb2_dc_buf *buf;
struct vm_area_struct *vma;
- dma_addr_t paddr = 0;
+ dma_addr_t dma_addr = 0;
int ret;
buf = kzalloc(sizeof *buf, GFP_KERNEL);
if (!buf)
return ERR_PTR(-ENOMEM);
- ret = vb2_get_contig_userptr(vaddr, size, &vma, &paddr);
+ ret = vb2_get_contig_userptr(vaddr, size, &vma, &dma_addr);
if (ret) {
printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n",
vaddr);
@@ -131,7 +131,7 @@ static void *vb2_dma_contig_get_userptr(void *alloc_ctx, unsigned long vaddr,
}
buf->size = size;
- buf->paddr = paddr;
+ buf->dma_addr = dma_addr;
buf->vma = vma;
return buf;
diff --git a/drivers/media/video/videobuf2-dma-sg.c b/drivers/media/video/videobuf2-dma-sg.c
index 065f468faf8f..3bad8b105fea 100644
--- a/drivers/media/video/videobuf2-dma-sg.c
+++ b/drivers/media/video/videobuf2-dma-sg.c
@@ -75,12 +75,6 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
printk(KERN_DEBUG "%s: Allocated buffer of %d pages\n",
__func__, buf->sg_desc.num_pages);
-
- if (!buf->vaddr)
- buf->vaddr = vm_map_ram(buf->pages,
- buf->sg_desc.num_pages,
- -1,
- PAGE_KERNEL);
return buf;
fail_pages_alloc:
diff --git a/drivers/media/video/videobuf2-memops.c b/drivers/media/video/videobuf2-memops.c
index 569eeb3dfd50..71a7a78c3fc0 100644
--- a/drivers/media/video/videobuf2-memops.c
+++ b/drivers/media/video/videobuf2-memops.c
@@ -68,12 +68,12 @@ void vb2_put_vma(struct vm_area_struct *vma)
if (!vma)
return;
- if (vma->vm_file)
- fput(vma->vm_file);
-
if (vma->vm_ops && vma->vm_ops->close)
vma->vm_ops->close(vma);
+ if (vma->vm_file)
+ fput(vma->vm_file);
+
kfree(vma);
}
EXPORT_SYMBOL_GPL(vb2_put_vma);
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index a848bd2af97f..7cf94c09d99a 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -651,7 +651,7 @@ static void vivi_stop_generating(struct vivi_dev *dev)
Videobuf operations
------------------------------------------------------------------*/
static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned long sizes[],
+ unsigned int *nplanes, unsigned int sizes[],
void *alloc_ctxs[])
{
struct vivi_dev *dev = vb2_get_drv_priv(vq);
@@ -766,7 +766,7 @@ static void buffer_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&dev->slock, flags);
}
-static int start_streaming(struct vb2_queue *vq)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct vivi_dev *dev = vb2_get_drv_priv(vq);
dprintk(dev, 1, "%s\n", __func__);
@@ -852,6 +852,11 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
(f->fmt.pix.width * dev->fmt->depth) >> 3;
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
+ if (dev->fmt->fourcc == V4L2_PIX_FMT_YUYV ||
+ dev->fmt->fourcc == V4L2_PIX_FMT_UYVY)
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ else
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
return 0;
}
@@ -885,6 +890,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
+ if (fmt->fourcc == V4L2_PIX_FMT_YUYV ||
+ fmt->fourcc == V4L2_PIX_FMT_UYVY)
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ else
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
return 0;
}
@@ -948,6 +958,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
return vb2_streamoff(&dev->vb_vidq, i);
}
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct vivi_dev *dev = video_drvdata(file);
+
+ v4l2_ctrl_handler_log_status(&dev->ctrl_handler, dev->v4l2_dev.name);
+ return 0;
+}
+
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
{
return 0;
@@ -1191,6 +1209,7 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
.vidioc_s_input = vidioc_s_input,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
+ .vidioc_log_status = vidioc_log_status,
.vidioc_subscribe_event = vidioc_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index ca372eb911d0..e5cad6ff64a1 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -331,7 +331,7 @@ static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pst
if (pstd)
*pstd = std;
if (pstatus)
- *pstatus = status;
+ *pstatus = res;
return 0;
}
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
index c492846c1c5a..e78cf94f491e 100644
--- a/drivers/media/video/zr364xx.c
+++ b/drivers/media/video/zr364xx.c
@@ -1638,6 +1638,9 @@ static int zr364xx_probe(struct usb_interface *intf,
if (!cam->read_endpoint) {
dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
+ video_device_release(cam->vdev);
+ kfree(cam);
+ cam = NULL;
return -ENOMEM;
}
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 7956a10f9488..e9c6a6047a00 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -63,6 +63,8 @@
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
+#include <linux/kthread.h>
+#include <scsi/scsi_host.h>
#include "mptbase.h"
#include "lsi/mpi_log_fc.h"
@@ -323,6 +325,32 @@ mpt_is_discovery_complete(MPT_ADAPTER *ioc)
return rc;
}
+
+/**
+ * mpt_remove_dead_ioc_func - kthread context to remove dead ioc
+ * @arg: input argument, used to derive ioc
+ *
+ * Return 0 if controller is removed from pci subsystem.
+ * Return -1 for other case.
+ */
+static int mpt_remove_dead_ioc_func(void *arg)
+{
+ MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+ struct pci_dev *pdev;
+
+ if ((ioc == NULL))
+ return -1;
+
+ pdev = ioc->pcidev;
+ if ((pdev == NULL))
+ return -1;
+
+ pci_remove_bus_device(pdev);
+ return 0;
+}
+
+
+
/**
* mpt_fault_reset_work - work performed on workq after ioc fault
* @work: input argument, used to derive ioc
@@ -336,12 +364,45 @@ mpt_fault_reset_work(struct work_struct *work)
u32 ioc_raw_state;
int rc;
unsigned long flags;
+ MPT_SCSI_HOST *hd;
+ struct task_struct *p;
if (ioc->ioc_reset_in_progress || !ioc->active)
goto out;
+
ioc_raw_state = mpt_GetIocState(ioc, 0);
- if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
+ if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_MASK) {
+ printk(MYIOC_s_INFO_FMT "%s: IOC is non-operational !!!!\n",
+ ioc->name, __func__);
+
+ /*
+ * Call mptscsih_flush_pending_cmds callback so that we
+ * flush all pending commands back to OS.
+ * This call is required to aovid deadlock at block layer.
+ * Dead IOC will fail to do diag reset,and this call is safe
+ * since dead ioc will never return any command back from HW.
+ */
+ hd = shost_priv(ioc->sh);
+ ioc->schedule_dead_ioc_flush_running_cmds(hd);
+
+ /*Remove the Dead Host */
+ p = kthread_run(mpt_remove_dead_ioc_func, ioc,
+ "mpt_dead_ioc_%d", ioc->id);
+ if (IS_ERR(p)) {
+ printk(MYIOC_s_ERR_FMT
+ "%s: Running mpt_dead_ioc thread failed !\n",
+ ioc->name, __func__);
+ } else {
+ printk(MYIOC_s_WARN_FMT
+ "%s: Running mpt_dead_ioc thread success !\n",
+ ioc->name, __func__);
+ }
+ return; /* don't rearm timer */
+ }
+
+ if ((ioc_raw_state & MPI_IOC_STATE_MASK)
+ == MPI_IOC_STATE_FAULT) {
printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
@@ -6413,8 +6474,19 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
pReq->Action, ioc->mptbase_cmds.status, timeleft));
if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
goto out;
- if (!timeleft)
+ if (!timeleft) {
+ spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+ if (ioc->ioc_reset_in_progress) {
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock,
+ flags);
+ printk(MYIOC_s_INFO_FMT "%s: host reset in"
+ " progress mpt_config timed out.!!\n",
+ __func__, ioc->name);
+ return -EFAULT;
+ }
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
issue_hard_reset = 1;
+ }
goto out;
}
@@ -7128,7 +7200,18 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
if (ioc->ioc_reset_in_progress) {
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
- return 0;
+ ioc->wait_on_reset_completion = 1;
+ do {
+ ssleep(1);
+ } while (ioc->ioc_reset_in_progress == 1);
+ ioc->wait_on_reset_completion = 0;
+ return ioc->reset_status;
+ }
+ if (ioc->wait_on_reset_completion) {
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+ rc = 0;
+ time_count = jiffies;
+ goto exit;
}
ioc->ioc_reset_in_progress = 1;
if (ioc->alt_ioc)
@@ -7165,6 +7248,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
ioc->ioc_reset_in_progress = 0;
ioc->taskmgmt_quiesce_io = 0;
ioc->taskmgmt_in_progress = 0;
+ ioc->reset_status = rc;
if (ioc->alt_ioc) {
ioc->alt_ioc->ioc_reset_in_progress = 0;
ioc->alt_ioc->taskmgmt_quiesce_io = 0;
@@ -7180,7 +7264,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
ioc->alt_ioc, MPT_IOC_POST_RESET);
}
}
-
+exit:
dtmprintk(ioc,
printk(MYIOC_s_DEBUG_FMT
"HardResetHandler: completed (%d seconds): %s\n", ioc->name,
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index fe902338539b..b4d24dc081ae 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.04.19"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.19"
+#define MPT_LINUX_VERSION_COMMON "3.04.20"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.20"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -554,10 +554,47 @@ struct mptfc_rport_info
u8 flags;
};
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/*
+ * MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers
+ * Private to the driver.
+ */
+
+#define MPT_HOST_BUS_UNKNOWN (0xFF)
+#define MPT_HOST_TOO_MANY_TM (0x05)
+#define MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
+#define MPT_HOST_NO_CHAIN (0xFFFFFFFF)
+#define MPT_NVRAM_MASK_TIMEOUT (0x000000FF)
+#define MPT_NVRAM_SYNC_MASK (0x0000FF00)
+#define MPT_NVRAM_SYNC_SHIFT (8)
+#define MPT_NVRAM_DISCONNECT_ENABLE (0x00010000)
+#define MPT_NVRAM_ID_SCAN_ENABLE (0x00020000)
+#define MPT_NVRAM_LUN_SCAN_ENABLE (0x00040000)
+#define MPT_NVRAM_TAG_QUEUE_ENABLE (0x00080000)
+#define MPT_NVRAM_WIDE_DISABLE (0x00100000)
+#define MPT_NVRAM_BOOT_CHOICE (0x00200000)
+
+typedef enum {
+ FC,
+ SPI,
+ SAS
+} BUS_TYPE;
+
+typedef struct _MPT_SCSI_HOST {
+ struct _MPT_ADAPTER *ioc;
+ ushort sel_timeout[MPT_MAX_FC_DEVICES];
+ char *info_kbuf;
+ long last_queue_full;
+ u16 spi_pending;
+ struct list_head target_reset_list;
+} MPT_SCSI_HOST;
+
typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr);
typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length,
dma_addr_t dma_addr);
typedef void (*MPT_SCHEDULE_TARGET_RESET)(void *ioc);
+typedef void (*MPT_FLUSH_RUNNING_CMDS)(MPT_SCSI_HOST *hd);
/*
* Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
@@ -716,7 +753,10 @@ typedef struct _MPT_ADAPTER
int taskmgmt_in_progress;
u8 taskmgmt_quiesce_io;
u8 ioc_reset_in_progress;
+ u8 reset_status;
+ u8 wait_on_reset_completion;
MPT_SCHEDULE_TARGET_RESET schedule_target_reset;
+ MPT_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
struct work_struct sas_persist_task;
struct work_struct fc_setup_reset_work;
@@ -830,19 +870,6 @@ typedef struct _MPT_LOCAL_REPLY {
u32 pad;
} MPT_LOCAL_REPLY;
-#define MPT_HOST_BUS_UNKNOWN (0xFF)
-#define MPT_HOST_TOO_MANY_TM (0x05)
-#define MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
-#define MPT_HOST_NO_CHAIN (0xFFFFFFFF)
-#define MPT_NVRAM_MASK_TIMEOUT (0x000000FF)
-#define MPT_NVRAM_SYNC_MASK (0x0000FF00)
-#define MPT_NVRAM_SYNC_SHIFT (8)
-#define MPT_NVRAM_DISCONNECT_ENABLE (0x00010000)
-#define MPT_NVRAM_ID_SCAN_ENABLE (0x00020000)
-#define MPT_NVRAM_LUN_SCAN_ENABLE (0x00040000)
-#define MPT_NVRAM_TAG_QUEUE_ENABLE (0x00080000)
-#define MPT_NVRAM_WIDE_DISABLE (0x00100000)
-#define MPT_NVRAM_BOOT_CHOICE (0x00200000)
/* The TM_STATE variable is used to provide strict single threading of TM
* requests as well as communicate TM error conditions.
@@ -851,21 +878,6 @@ typedef struct _MPT_LOCAL_REPLY {
#define TM_STATE_IN_PROGRESS (1)
#define TM_STATE_ERROR (2)
-typedef enum {
- FC,
- SPI,
- SAS
-} BUS_TYPE;
-
-typedef struct _MPT_SCSI_HOST {
- MPT_ADAPTER *ioc;
- ushort sel_timeout[MPT_MAX_FC_DEVICES];
- char *info_kbuf;
- long last_queue_full;
- u16 spi_pending;
- struct list_head target_reset_list;
-} MPT_SCSI_HOST;
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* More Dynamic Multi-Pathing stuff...
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 7596aecd5072..9d9504298549 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -92,6 +92,11 @@ static int max_lun = MPTSAS_MAX_LUN;
module_param(max_lun, int, 0);
MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+static int mpt_loadtime_max_sectors = 8192;
+module_param(mpt_loadtime_max_sectors, int, 0);
+MODULE_PARM_DESC(mpt_loadtime_max_sectors,
+ " Maximum sector define for Host Bus Adaptor.Range 64 to 8192 default=8192");
+
static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
@@ -285,10 +290,11 @@ mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
spin_lock_irqsave(&ioc->fw_event_lock, flags);
list_add_tail(&fw_event->list, &ioc->fw_event_list);
INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
- devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
- ioc->name, __func__, fw_event));
- queue_delayed_work(ioc->fw_event_q, &fw_event->work,
- delay);
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)"
+ "on cpuid %d\n", ioc->name, __func__,
+ fw_event, smp_processor_id()));
+ queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q,
+ &fw_event->work, delay);
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
@@ -300,10 +306,11 @@ mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
unsigned long flags;
spin_lock_irqsave(&ioc->fw_event_lock, flags);
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
- "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
+ "(fw_event=0x%p)on cpuid %d\n", ioc->name, __func__,
+ fw_event, smp_processor_id()));
fw_event->retries++;
- queue_delayed_work(ioc->fw_event_q, &fw_event->work,
- msecs_to_jiffies(delay));
+ queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q,
+ &fw_event->work, msecs_to_jiffies(delay));
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
@@ -1943,6 +1950,15 @@ static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)
goto done;
}
+ /* In case if IOC is in reset from internal context.
+ * Do not execute EEH for the same IOC. SML should to reset timer.
+ */
+ if (ioc->ioc_reset_in_progress) {
+ dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: ioc is in reset,"
+ "SML need to reset the timer (sc=%p)\n",
+ ioc->name, __func__, sc));
+ rc = BLK_EH_RESET_TIMER;
+ }
vdevice = sc->device->hostdata;
if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD
|| vdevice->vtarget->deleted)) {
@@ -5142,6 +5158,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->TaskCtx = mptsasTaskCtx;
ioc->InternalCtx = mptsasInternalCtx;
ioc->schedule_target_reset = &mptsas_schedule_target_reset;
+ ioc->schedule_dead_ioc_flush_running_cmds =
+ &mptscsih_flush_running_cmds;
/* Added sanity check on readiness of the MPT adapter.
*/
if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
@@ -5239,6 +5257,21 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->sg_tablesize = numSGE;
}
+ if (mpt_loadtime_max_sectors) {
+ if (mpt_loadtime_max_sectors < 64 ||
+ mpt_loadtime_max_sectors > 8192) {
+ printk(MYIOC_s_INFO_FMT "Invalid value passed for"
+ "mpt_loadtime_max_sectors %d."
+ "Range from 64 to 8192\n", ioc->name,
+ mpt_loadtime_max_sectors);
+ }
+ mpt_loadtime_max_sectors &= 0xFFFFFFFE;
+ dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+ "Resetting max sector to %d from %d\n",
+ ioc->name, mpt_loadtime_max_sectors, sh->max_sectors));
+ sh->max_sectors = mpt_loadtime_max_sectors;
+ }
+
hd = shost_priv(sh);
hd->ioc = ioc;
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index ce61a5769765..0c3ced70707b 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -830,7 +830,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
if ((pScsiReq->CDB[0] == READ_6 && ((pScsiReq->CDB[1] & 0x02) == 0)) ||
pScsiReq->CDB[0] == READ_10 ||
pScsiReq->CDB[0] == READ_12 ||
- pScsiReq->CDB[0] == READ_16 ||
+ (pScsiReq->CDB[0] == READ_16 &&
+ ((pScsiReq->CDB[1] & 0x02) == 0)) ||
pScsiReq->CDB[0] == VERIFY ||
pScsiReq->CDB[0] == VERIFY_16) {
if (scsi_bufflen(sc) !=
@@ -1024,7 +1025,7 @@ out:
*
* Must be called while new I/Os are being queued.
*/
-static void
+void
mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
{
MPT_ADAPTER *ioc = hd->ioc;
@@ -1055,6 +1056,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
sc->scsi_done(sc);
}
}
+EXPORT_SYMBOL(mptscsih_flush_running_cmds);
/*
* mptscsih_search_running_cmds - Delete any commands associated
@@ -1629,7 +1631,13 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,
return 0;
}
- if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
+ /* DOORBELL ACTIVE check is not required if
+ * MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q is supported.
+ */
+
+ if (!((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q)
+ && (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) &&
+ (ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
printk(MYIOC_s_WARN_FMT
"TaskMgmt type=%x: ioc_state: "
"DOORBELL_ACTIVE (0x%x)!\n",
@@ -1728,7 +1736,9 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,
printk(MYIOC_s_WARN_FMT
"Issuing Reset from %s!! doorbell=0x%08x\n",
ioc->name, __func__, mpt_GetIocState(ioc, 0));
- retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
+ retval = (ioc->bus_type == SAS) ?
+ mpt_HardResetHandler(ioc, CAN_SLEEP) :
+ mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
mpt_free_msg_frame(ioc, mf);
}
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 45a5ff3eff61..43e75ff39921 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -135,3 +135,4 @@ extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
extern struct device_attribute *mptscsih_host_attrs[];
extern struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
+extern void mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 74d4893a8f21..f1391c21ef26 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -390,6 +390,7 @@ config MFD_WM831X_I2C
bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C"
select MFD_CORE
select MFD_WM831X
+ select REGMAP_I2C
depends on I2C=y && GENERIC_HARDIRQS
help
Support for the Wolfson Microelecronics WM831x and WM832x PMICs
@@ -401,6 +402,7 @@ config MFD_WM831X_SPI
bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI"
select MFD_CORE
select MFD_WM831X
+ select REGMAP_SPI
depends on SPI_MASTER && GENERIC_HARDIRQS
help
Support for the Wolfson Microelecronics WM831x and WM832x PMICs
@@ -474,6 +476,7 @@ config MFD_WM8350_I2C
config MFD_WM8994
bool "Support Wolfson Microelectronics WM8994"
select MFD_CORE
+ select REGMAP_I2C
depends on I2C=y && GENERIC_HARDIRQS
help
The WM8994 is a highly integrated hi-fi CODEC designed for
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c
index ded870e22155..cb4910ac4d12 100644
--- a/drivers/mfd/menelaus.c
+++ b/drivers/mfd/menelaus.c
@@ -44,7 +44,7 @@
#include <asm/mach/irq.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <plat/menelaus.h>
#define DRIVER_NAME "menelaus"
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index 24d436c2fe4a..268f80fd0439 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -34,7 +34,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/twl6040.h>
-static struct platform_device *twl6040_dev;
+#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
{
@@ -42,10 +42,16 @@ int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
u8 val = 0;
mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
- if (ret < 0) {
- mutex_unlock(&twl6040->io_mutex);
- return ret;
+ /* Vibra control registers from cache */
+ if (unlikely(reg == TWL6040_REG_VIBCTLL ||
+ reg == TWL6040_REG_VIBCTLR)) {
+ val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
+ } else {
+ ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+ if (ret < 0) {
+ mutex_unlock(&twl6040->io_mutex);
+ return ret;
+ }
}
mutex_unlock(&twl6040->io_mutex);
@@ -59,6 +65,9 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
mutex_lock(&twl6040->io_mutex);
ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+ /* Cache the vibra control registers */
+ if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
+ twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
mutex_unlock(&twl6040->io_mutex);
return ret;
@@ -203,11 +212,11 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data)
if (intid & TWL6040_THINT) {
status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
if (status & TWL6040_TSHUTDET) {
- dev_warn(&twl6040_dev->dev,
+ dev_warn(twl6040->dev,
"Thermal shutdown, powering-off");
twl6040_power(twl6040, 0);
} else {
- dev_warn(&twl6040_dev->dev,
+ dev_warn(twl6040->dev,
"Leaving thermal shutdown, powering-on");
twl6040_power(twl6040, 1);
}
@@ -227,7 +236,7 @@ static int twl6040_power_up_completion(struct twl6040 *twl6040,
if (!time_left) {
intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
if (!(intid & TWL6040_READYINT)) {
- dev_err(&twl6040_dev->dev,
+ dev_err(twl6040->dev,
"timeout waiting for READYINT\n");
return -ETIMEDOUT;
}
@@ -255,7 +264,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
/* wait for power-up completion */
ret = twl6040_power_up_completion(twl6040, naudint);
if (ret) {
- dev_err(&twl6040_dev->dev,
+ dev_err(twl6040->dev,
"automatic power-down failed\n");
twl6040->power_count = 0;
goto out;
@@ -264,7 +273,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
/* use manual power-up sequence */
ret = twl6040_power_up(twl6040);
if (ret) {
- dev_err(&twl6040_dev->dev,
+ dev_err(twl6040->dev,
"manual power-up failed\n");
twl6040->power_count = 0;
goto out;
@@ -276,7 +285,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
} else {
/* already powered-down */
if (!twl6040->power_count) {
- dev_err(&twl6040_dev->dev,
+ dev_err(twl6040->dev,
"device is already powered-off\n");
ret = -EPERM;
goto out;
@@ -326,7 +335,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
lppllctl &= ~TWL6040_LPLLFIN;
break;
default:
- dev_err(&twl6040_dev->dev,
+ dev_err(twl6040->dev,
"freq_out %d not supported\n", freq_out);
ret = -EINVAL;
goto pll_out;
@@ -347,7 +356,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
hppllctl);
break;
default:
- dev_err(&twl6040_dev->dev,
+ dev_err(twl6040->dev,
"freq_in %d not supported\n", freq_in);
ret = -EINVAL;
goto pll_out;
@@ -356,7 +365,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
case TWL6040_SYSCLK_SEL_HPPLL:
/* high-performance PLL can provide only 19.2 MHz */
if (freq_out != 19200000) {
- dev_err(&twl6040_dev->dev,
+ dev_err(twl6040->dev,
"freq_out %d not supported\n", freq_out);
ret = -EINVAL;
goto pll_out;
@@ -389,7 +398,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
TWL6040_HPLLENA;
break;
default:
- dev_err(&twl6040_dev->dev,
+ dev_err(twl6040->dev,
"freq_in %d not supported\n", freq_in);
ret = -EINVAL;
goto pll_out;
@@ -406,7 +415,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
break;
default:
- dev_err(&twl6040_dev->dev, "unknown pll id %d\n", pll_id);
+ dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
ret = -EINVAL;
goto pll_out;
}
@@ -435,6 +444,18 @@ unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
}
EXPORT_SYMBOL(twl6040_get_sysclk);
+/* Get the combined status of the vibra control register */
+int twl6040_get_vibralr_status(struct twl6040 *twl6040)
+{
+ u8 status;
+
+ status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1];
+ status &= (TWL6040_VIBENA | TWL6040_VIBSEL);
+
+ return status;
+}
+EXPORT_SYMBOL(twl6040_get_vibralr_status);
+
static struct resource twl6040_vibra_rsrc[] = {
{
.flags = IORESOURCE_IRQ,
@@ -471,9 +492,7 @@ static int __devinit twl6040_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, twl6040);
- twl6040_dev = pdev;
twl6040->dev = &pdev->dev;
- twl6040->audpwron = pdata->audpwron_gpio;
twl6040->irq = pdata->naudint_irq;
twl6040->irq_base = pdata->irq_base;
@@ -483,6 +502,12 @@ static int __devinit twl6040_probe(struct platform_device *pdev)
twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
+ /* ERRATA: Automatic power-up is not possible in ES1.0 */
+ if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0)
+ twl6040->audpwron = pdata->audpwron_gpio;
+ else
+ twl6040->audpwron = -EINVAL;
+
if (gpio_is_valid(twl6040->audpwron)) {
ret = gpio_request(twl6040->audpwron, "audpwron");
if (ret)
@@ -493,10 +518,6 @@ static int __devinit twl6040_probe(struct platform_device *pdev)
goto gpio2_err;
}
- /* ERRATA: Automatic power-up is not possible in ES1.0 */
- if (twl6040->rev == TWL6040_REV_ES1_0)
- twl6040->audpwron = -EINVAL;
-
/* codec interrupt */
ret = twl6040_irq_init(twl6040);
if (ret)
@@ -566,7 +587,6 @@ gpio2_err:
gpio1_err:
platform_set_drvdata(pdev, NULL);
kfree(twl6040);
- twl6040_dev = NULL;
return ret;
}
@@ -586,7 +606,6 @@ static int __devexit twl6040_remove(struct platform_device *pdev)
mfd_remove_devices(&pdev->dev);
platform_set_drvdata(pdev, NULL);
kfree(twl6040);
- twl6040_dev = NULL;
return 0;
}
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 099b6104d150..0a2b8d41a702 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
+#include <linux/err.h>
#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h>
@@ -161,27 +162,350 @@ int wm831x_reg_unlock(struct wm831x *wm831x)
}
EXPORT_SYMBOL_GPL(wm831x_reg_unlock);
-static int wm831x_read(struct wm831x *wm831x, unsigned short reg,
- int bytes, void *dest)
+static bool wm831x_reg_readable(struct device *dev, unsigned int reg)
{
- int ret, i;
- u16 *buf = dest;
-
- BUG_ON(bytes % 2);
- BUG_ON(bytes <= 0);
+ switch (reg) {
+ case WM831X_RESET_ID:
+ case WM831X_REVISION:
+ case WM831X_PARENT_ID:
+ case WM831X_SYSVDD_CONTROL:
+ case WM831X_THERMAL_MONITORING:
+ case WM831X_POWER_STATE:
+ case WM831X_WATCHDOG:
+ case WM831X_ON_PIN_CONTROL:
+ case WM831X_RESET_CONTROL:
+ case WM831X_CONTROL_INTERFACE:
+ case WM831X_SECURITY_KEY:
+ case WM831X_SOFTWARE_SCRATCH:
+ case WM831X_OTP_CONTROL:
+ case WM831X_GPIO_LEVEL:
+ case WM831X_SYSTEM_STATUS:
+ case WM831X_ON_SOURCE:
+ case WM831X_OFF_SOURCE:
+ case WM831X_SYSTEM_INTERRUPTS:
+ case WM831X_INTERRUPT_STATUS_1:
+ case WM831X_INTERRUPT_STATUS_2:
+ case WM831X_INTERRUPT_STATUS_3:
+ case WM831X_INTERRUPT_STATUS_4:
+ case WM831X_INTERRUPT_STATUS_5:
+ case WM831X_IRQ_CONFIG:
+ case WM831X_SYSTEM_INTERRUPTS_MASK:
+ case WM831X_INTERRUPT_STATUS_1_MASK:
+ case WM831X_INTERRUPT_STATUS_2_MASK:
+ case WM831X_INTERRUPT_STATUS_3_MASK:
+ case WM831X_INTERRUPT_STATUS_4_MASK:
+ case WM831X_INTERRUPT_STATUS_5_MASK:
+ case WM831X_RTC_WRITE_COUNTER:
+ case WM831X_RTC_TIME_1:
+ case WM831X_RTC_TIME_2:
+ case WM831X_RTC_ALARM_1:
+ case WM831X_RTC_ALARM_2:
+ case WM831X_RTC_CONTROL:
+ case WM831X_RTC_TRIM:
+ case WM831X_TOUCH_CONTROL_1:
+ case WM831X_TOUCH_CONTROL_2:
+ case WM831X_TOUCH_DATA_X:
+ case WM831X_TOUCH_DATA_Y:
+ case WM831X_TOUCH_DATA_Z:
+ case WM831X_AUXADC_DATA:
+ case WM831X_AUXADC_CONTROL:
+ case WM831X_AUXADC_SOURCE:
+ case WM831X_COMPARATOR_CONTROL:
+ case WM831X_COMPARATOR_1:
+ case WM831X_COMPARATOR_2:
+ case WM831X_COMPARATOR_3:
+ case WM831X_COMPARATOR_4:
+ case WM831X_GPIO1_CONTROL:
+ case WM831X_GPIO2_CONTROL:
+ case WM831X_GPIO3_CONTROL:
+ case WM831X_GPIO4_CONTROL:
+ case WM831X_GPIO5_CONTROL:
+ case WM831X_GPIO6_CONTROL:
+ case WM831X_GPIO7_CONTROL:
+ case WM831X_GPIO8_CONTROL:
+ case WM831X_GPIO9_CONTROL:
+ case WM831X_GPIO10_CONTROL:
+ case WM831X_GPIO11_CONTROL:
+ case WM831X_GPIO12_CONTROL:
+ case WM831X_GPIO13_CONTROL:
+ case WM831X_GPIO14_CONTROL:
+ case WM831X_GPIO15_CONTROL:
+ case WM831X_GPIO16_CONTROL:
+ case WM831X_CHARGER_CONTROL_1:
+ case WM831X_CHARGER_CONTROL_2:
+ case WM831X_CHARGER_STATUS:
+ case WM831X_BACKUP_CHARGER_CONTROL:
+ case WM831X_STATUS_LED_1:
+ case WM831X_STATUS_LED_2:
+ case WM831X_CURRENT_SINK_1:
+ case WM831X_CURRENT_SINK_2:
+ case WM831X_DCDC_ENABLE:
+ case WM831X_LDO_ENABLE:
+ case WM831X_DCDC_STATUS:
+ case WM831X_LDO_STATUS:
+ case WM831X_DCDC_UV_STATUS:
+ case WM831X_LDO_UV_STATUS:
+ case WM831X_DC1_CONTROL_1:
+ case WM831X_DC1_CONTROL_2:
+ case WM831X_DC1_ON_CONFIG:
+ case WM831X_DC1_SLEEP_CONTROL:
+ case WM831X_DC1_DVS_CONTROL:
+ case WM831X_DC2_CONTROL_1:
+ case WM831X_DC2_CONTROL_2:
+ case WM831X_DC2_ON_CONFIG:
+ case WM831X_DC2_SLEEP_CONTROL:
+ case WM831X_DC2_DVS_CONTROL:
+ case WM831X_DC3_CONTROL_1:
+ case WM831X_DC3_CONTROL_2:
+ case WM831X_DC3_ON_CONFIG:
+ case WM831X_DC3_SLEEP_CONTROL:
+ case WM831X_DC4_CONTROL:
+ case WM831X_DC4_SLEEP_CONTROL:
+ case WM831X_EPE1_CONTROL:
+ case WM831X_EPE2_CONTROL:
+ case WM831X_LDO1_CONTROL:
+ case WM831X_LDO1_ON_CONTROL:
+ case WM831X_LDO1_SLEEP_CONTROL:
+ case WM831X_LDO2_CONTROL:
+ case WM831X_LDO2_ON_CONTROL:
+ case WM831X_LDO2_SLEEP_CONTROL:
+ case WM831X_LDO3_CONTROL:
+ case WM831X_LDO3_ON_CONTROL:
+ case WM831X_LDO3_SLEEP_CONTROL:
+ case WM831X_LDO4_CONTROL:
+ case WM831X_LDO4_ON_CONTROL:
+ case WM831X_LDO4_SLEEP_CONTROL:
+ case WM831X_LDO5_CONTROL:
+ case WM831X_LDO5_ON_CONTROL:
+ case WM831X_LDO5_SLEEP_CONTROL:
+ case WM831X_LDO6_CONTROL:
+ case WM831X_LDO6_ON_CONTROL:
+ case WM831X_LDO6_SLEEP_CONTROL:
+ case WM831X_LDO7_CONTROL:
+ case WM831X_LDO7_ON_CONTROL:
+ case WM831X_LDO7_SLEEP_CONTROL:
+ case WM831X_LDO8_CONTROL:
+ case WM831X_LDO8_ON_CONTROL:
+ case WM831X_LDO8_SLEEP_CONTROL:
+ case WM831X_LDO9_CONTROL:
+ case WM831X_LDO9_ON_CONTROL:
+ case WM831X_LDO9_SLEEP_CONTROL:
+ case WM831X_LDO10_CONTROL:
+ case WM831X_LDO10_ON_CONTROL:
+ case WM831X_LDO10_SLEEP_CONTROL:
+ case WM831X_LDO11_ON_CONTROL:
+ case WM831X_LDO11_SLEEP_CONTROL:
+ case WM831X_POWER_GOOD_SOURCE_1:
+ case WM831X_POWER_GOOD_SOURCE_2:
+ case WM831X_CLOCK_CONTROL_1:
+ case WM831X_CLOCK_CONTROL_2:
+ case WM831X_FLL_CONTROL_1:
+ case WM831X_FLL_CONTROL_2:
+ case WM831X_FLL_CONTROL_3:
+ case WM831X_FLL_CONTROL_4:
+ case WM831X_FLL_CONTROL_5:
+ case WM831X_UNIQUE_ID_1:
+ case WM831X_UNIQUE_ID_2:
+ case WM831X_UNIQUE_ID_3:
+ case WM831X_UNIQUE_ID_4:
+ case WM831X_UNIQUE_ID_5:
+ case WM831X_UNIQUE_ID_6:
+ case WM831X_UNIQUE_ID_7:
+ case WM831X_UNIQUE_ID_8:
+ case WM831X_FACTORY_OTP_ID:
+ case WM831X_FACTORY_OTP_1:
+ case WM831X_FACTORY_OTP_2:
+ case WM831X_FACTORY_OTP_3:
+ case WM831X_FACTORY_OTP_4:
+ case WM831X_FACTORY_OTP_5:
+ case WM831X_CUSTOMER_OTP_ID:
+ case WM831X_DC1_OTP_CONTROL:
+ case WM831X_DC2_OTP_CONTROL:
+ case WM831X_DC3_OTP_CONTROL:
+ case WM831X_LDO1_2_OTP_CONTROL:
+ case WM831X_LDO3_4_OTP_CONTROL:
+ case WM831X_LDO5_6_OTP_CONTROL:
+ case WM831X_LDO7_8_OTP_CONTROL:
+ case WM831X_LDO9_10_OTP_CONTROL:
+ case WM831X_LDO11_EPE_CONTROL:
+ case WM831X_GPIO1_OTP_CONTROL:
+ case WM831X_GPIO2_OTP_CONTROL:
+ case WM831X_GPIO3_OTP_CONTROL:
+ case WM831X_GPIO4_OTP_CONTROL:
+ case WM831X_GPIO5_OTP_CONTROL:
+ case WM831X_GPIO6_OTP_CONTROL:
+ case WM831X_DBE_CHECK_DATA:
+ return true;
+ default:
+ return false;
+ }
+}
- ret = wm831x->read_dev(wm831x, reg, bytes, dest);
- if (ret < 0)
- return ret;
+static bool wm831x_reg_writeable(struct device *dev, unsigned int reg)
+{
+ struct wm831x *wm831x = dev_get_drvdata(dev);
- for (i = 0; i < bytes / 2; i++) {
- buf[i] = be16_to_cpu(buf[i]);
+ if (wm831x_reg_locked(wm831x, reg))
+ return false;
- dev_vdbg(wm831x->dev, "Read %04x from R%d(0x%x)\n",
- buf[i], reg + i, reg + i);
+ switch (reg) {
+ case WM831X_SYSVDD_CONTROL:
+ case WM831X_THERMAL_MONITORING:
+ case WM831X_POWER_STATE:
+ case WM831X_WATCHDOG:
+ case WM831X_ON_PIN_CONTROL:
+ case WM831X_RESET_CONTROL:
+ case WM831X_CONTROL_INTERFACE:
+ case WM831X_SECURITY_KEY:
+ case WM831X_SOFTWARE_SCRATCH:
+ case WM831X_OTP_CONTROL:
+ case WM831X_GPIO_LEVEL:
+ case WM831X_INTERRUPT_STATUS_1:
+ case WM831X_INTERRUPT_STATUS_2:
+ case WM831X_INTERRUPT_STATUS_3:
+ case WM831X_INTERRUPT_STATUS_4:
+ case WM831X_INTERRUPT_STATUS_5:
+ case WM831X_IRQ_CONFIG:
+ case WM831X_SYSTEM_INTERRUPTS_MASK:
+ case WM831X_INTERRUPT_STATUS_1_MASK:
+ case WM831X_INTERRUPT_STATUS_2_MASK:
+ case WM831X_INTERRUPT_STATUS_3_MASK:
+ case WM831X_INTERRUPT_STATUS_4_MASK:
+ case WM831X_INTERRUPT_STATUS_5_MASK:
+ case WM831X_RTC_TIME_1:
+ case WM831X_RTC_TIME_2:
+ case WM831X_RTC_ALARM_1:
+ case WM831X_RTC_ALARM_2:
+ case WM831X_RTC_CONTROL:
+ case WM831X_RTC_TRIM:
+ case WM831X_TOUCH_CONTROL_1:
+ case WM831X_TOUCH_CONTROL_2:
+ case WM831X_AUXADC_CONTROL:
+ case WM831X_AUXADC_SOURCE:
+ case WM831X_COMPARATOR_CONTROL:
+ case WM831X_COMPARATOR_1:
+ case WM831X_COMPARATOR_2:
+ case WM831X_COMPARATOR_3:
+ case WM831X_COMPARATOR_4:
+ case WM831X_GPIO1_CONTROL:
+ case WM831X_GPIO2_CONTROL:
+ case WM831X_GPIO3_CONTROL:
+ case WM831X_GPIO4_CONTROL:
+ case WM831X_GPIO5_CONTROL:
+ case WM831X_GPIO6_CONTROL:
+ case WM831X_GPIO7_CONTROL:
+ case WM831X_GPIO8_CONTROL:
+ case WM831X_GPIO9_CONTROL:
+ case WM831X_GPIO10_CONTROL:
+ case WM831X_GPIO11_CONTROL:
+ case WM831X_GPIO12_CONTROL:
+ case WM831X_GPIO13_CONTROL:
+ case WM831X_GPIO14_CONTROL:
+ case WM831X_GPIO15_CONTROL:
+ case WM831X_GPIO16_CONTROL:
+ case WM831X_CHARGER_CONTROL_1:
+ case WM831X_CHARGER_CONTROL_2:
+ case WM831X_CHARGER_STATUS:
+ case WM831X_BACKUP_CHARGER_CONTROL:
+ case WM831X_STATUS_LED_1:
+ case WM831X_STATUS_LED_2:
+ case WM831X_CURRENT_SINK_1:
+ case WM831X_CURRENT_SINK_2:
+ case WM831X_DCDC_ENABLE:
+ case WM831X_LDO_ENABLE:
+ case WM831X_DC1_CONTROL_1:
+ case WM831X_DC1_CONTROL_2:
+ case WM831X_DC1_ON_CONFIG:
+ case WM831X_DC1_SLEEP_CONTROL:
+ case WM831X_DC1_DVS_CONTROL:
+ case WM831X_DC2_CONTROL_1:
+ case WM831X_DC2_CONTROL_2:
+ case WM831X_DC2_ON_CONFIG:
+ case WM831X_DC2_SLEEP_CONTROL:
+ case WM831X_DC2_DVS_CONTROL:
+ case WM831X_DC3_CONTROL_1:
+ case WM831X_DC3_CONTROL_2:
+ case WM831X_DC3_ON_CONFIG:
+ case WM831X_DC3_SLEEP_CONTROL:
+ case WM831X_DC4_CONTROL:
+ case WM831X_DC4_SLEEP_CONTROL:
+ case WM831X_EPE1_CONTROL:
+ case WM831X_EPE2_CONTROL:
+ case WM831X_LDO1_CONTROL:
+ case WM831X_LDO1_ON_CONTROL:
+ case WM831X_LDO1_SLEEP_CONTROL:
+ case WM831X_LDO2_CONTROL:
+ case WM831X_LDO2_ON_CONTROL:
+ case WM831X_LDO2_SLEEP_CONTROL:
+ case WM831X_LDO3_CONTROL:
+ case WM831X_LDO3_ON_CONTROL:
+ case WM831X_LDO3_SLEEP_CONTROL:
+ case WM831X_LDO4_CONTROL:
+ case WM831X_LDO4_ON_CONTROL:
+ case WM831X_LDO4_SLEEP_CONTROL:
+ case WM831X_LDO5_CONTROL:
+ case WM831X_LDO5_ON_CONTROL:
+ case WM831X_LDO5_SLEEP_CONTROL:
+ case WM831X_LDO6_CONTROL:
+ case WM831X_LDO6_ON_CONTROL:
+ case WM831X_LDO6_SLEEP_CONTROL:
+ case WM831X_LDO7_CONTROL:
+ case WM831X_LDO7_ON_CONTROL:
+ case WM831X_LDO7_SLEEP_CONTROL:
+ case WM831X_LDO8_CONTROL:
+ case WM831X_LDO8_ON_CONTROL:
+ case WM831X_LDO8_SLEEP_CONTROL:
+ case WM831X_LDO9_CONTROL:
+ case WM831X_LDO9_ON_CONTROL:
+ case WM831X_LDO9_SLEEP_CONTROL:
+ case WM831X_LDO10_CONTROL:
+ case WM831X_LDO10_ON_CONTROL:
+ case WM831X_LDO10_SLEEP_CONTROL:
+ case WM831X_LDO11_ON_CONTROL:
+ case WM831X_LDO11_SLEEP_CONTROL:
+ case WM831X_POWER_GOOD_SOURCE_1:
+ case WM831X_POWER_GOOD_SOURCE_2:
+ case WM831X_CLOCK_CONTROL_1:
+ case WM831X_CLOCK_CONTROL_2:
+ case WM831X_FLL_CONTROL_1:
+ case WM831X_FLL_CONTROL_2:
+ case WM831X_FLL_CONTROL_3:
+ case WM831X_FLL_CONTROL_4:
+ case WM831X_FLL_CONTROL_5:
+ return true;
+ default:
+ return false;
}
+}
- return 0;
+static bool wm831x_reg_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM831X_SYSTEM_STATUS:
+ case WM831X_ON_SOURCE:
+ case WM831X_OFF_SOURCE:
+ case WM831X_GPIO_LEVEL:
+ case WM831X_SYSTEM_INTERRUPTS:
+ case WM831X_INTERRUPT_STATUS_1:
+ case WM831X_INTERRUPT_STATUS_2:
+ case WM831X_INTERRUPT_STATUS_3:
+ case WM831X_INTERRUPT_STATUS_4:
+ case WM831X_INTERRUPT_STATUS_5:
+ case WM831X_RTC_TIME_1:
+ case WM831X_RTC_TIME_2:
+ case WM831X_TOUCH_DATA_X:
+ case WM831X_TOUCH_DATA_Y:
+ case WM831X_TOUCH_DATA_Z:
+ case WM831X_AUXADC_DATA:
+ case WM831X_CHARGER_STATUS:
+ case WM831X_DCDC_STATUS:
+ case WM831X_LDO_STATUS:
+ case WM831X_DCDC_UV_STATUS:
+ case WM831X_LDO_UV_STATUS:
+ return true;
+ default:
+ return false;
+ }
}
/**
@@ -192,14 +516,10 @@ static int wm831x_read(struct wm831x *wm831x, unsigned short reg,
*/
int wm831x_reg_read(struct wm831x *wm831x, unsigned short reg)
{
- unsigned short val;
+ unsigned int val;
int ret;
- mutex_lock(&wm831x->io_lock);
-
- ret = wm831x_read(wm831x, reg, 2, &val);
-
- mutex_unlock(&wm831x->io_lock);
+ ret = regmap_read(wm831x->regmap, reg, &val);
if (ret < 0)
return ret;
@@ -219,15 +539,7 @@ EXPORT_SYMBOL_GPL(wm831x_reg_read);
int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
int count, u16 *buf)
{
- int ret;
-
- mutex_lock(&wm831x->io_lock);
-
- ret = wm831x_read(wm831x, reg, count * 2, buf);
-
- mutex_unlock(&wm831x->io_lock);
-
- return ret;
+ return regmap_bulk_read(wm831x->regmap, reg, buf, count);
}
EXPORT_SYMBOL_GPL(wm831x_bulk_read);
@@ -235,7 +547,7 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
int bytes, void *src)
{
u16 *buf = src;
- int i;
+ int i, ret;
BUG_ON(bytes % 2);
BUG_ON(bytes <= 0);
@@ -246,11 +558,10 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n",
buf[i], reg + i, reg + i);
-
- buf[i] = cpu_to_be16(buf[i]);
+ ret = regmap_write(wm831x->regmap, reg + i, buf[i]);
}
- return wm831x->write_dev(wm831x, reg, bytes, src);
+ return 0;
}
/**
@@ -287,20 +598,14 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
unsigned short mask, unsigned short val)
{
int ret;
- u16 r;
mutex_lock(&wm831x->io_lock);
- ret = wm831x_read(wm831x, reg, 2, &r);
- if (ret < 0)
- goto out;
-
- r &= ~mask;
- r |= val & mask;
-
- ret = wm831x_write(wm831x, reg, 2, &r);
+ if (!wm831x_reg_locked(wm831x, reg))
+ ret = regmap_update_bits(wm831x->regmap, reg, mask, val);
+ else
+ ret = -EPERM;
-out:
mutex_unlock(&wm831x->io_lock);
return ret;
@@ -1293,6 +1598,19 @@ static struct mfd_cell backlight_devs[] = {
},
};
+struct regmap_config wm831x_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .cache_type = REGCACHE_RBTREE,
+
+ .max_register = WM831X_DBE_CHECK_DATA,
+ .readable_reg = wm831x_reg_readable,
+ .writeable_reg = wm831x_reg_writeable,
+ .volatile_reg = wm831x_reg_volatile,
+};
+EXPORT_SYMBOL_GPL(wm831x_regmap_config);
+
/*
* Instantiate the generic non-control parts of the device.
*/
@@ -1311,7 +1629,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
if (ret < 0) {
dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
- goto err;
+ goto err_regmap;
}
switch (ret) {
case 0x6204:
@@ -1320,20 +1638,20 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
default:
dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
ret = -EINVAL;
- goto err;
+ goto err_regmap;
}
ret = wm831x_reg_read(wm831x, WM831X_REVISION);
if (ret < 0) {
dev_err(wm831x->dev, "Failed to read revision: %d\n", ret);
- goto err;
+ goto err_regmap;
}
rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT;
ret = wm831x_reg_read(wm831x, WM831X_RESET_ID);
if (ret < 0) {
dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret);
- goto err;
+ goto err_regmap;
}
/* Some engineering samples do not have the ID set, rely on
@@ -1408,7 +1726,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
default:
dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
ret = -EINVAL;
- goto err;
+ goto err_regmap;
}
/* This will need revisiting in future but is OK for all
@@ -1422,7 +1740,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY);
if (ret < 0) {
dev_err(wm831x->dev, "Failed to read security key: %d\n", ret);
- goto err;
+ goto err_regmap;
}
if (ret != 0) {
dev_warn(wm831x->dev, "Security key had non-zero value %x\n",
@@ -1435,7 +1753,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret = pdata->pre_init(wm831x);
if (ret != 0) {
dev_err(wm831x->dev, "pre_init() failed: %d\n", ret);
- goto err;
+ goto err_regmap;
}
}
@@ -1458,7 +1776,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret = wm831x_irq_init(wm831x, irq);
if (ret != 0)
- goto err;
+ goto err_regmap;
wm831x_auxadc_init(wm831x);
@@ -1554,8 +1872,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
err_irq:
wm831x_irq_exit(wm831x);
-err:
+err_regmap:
mfd_remove_devices(wm831x->dev);
+ regmap_exit(wm831x->regmap);
kfree(wm831x);
return ret;
}
@@ -1567,6 +1886,7 @@ void wm831x_device_exit(struct wm831x *wm831x)
if (wm831x->irq_base)
free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
wm831x_irq_exit(wm831x);
+ regmap_exit(wm831x->regmap);
kfree(wm831x);
}
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c
index 3ff8c13db2a8..ac8da1d439da 100644
--- a/drivers/mfd/wm831x-i2c.c
+++ b/drivers/mfd/wm831x-i2c.c
@@ -18,67 +18,17 @@
#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/regmap.h>
#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h>
-static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg,
- int bytes, void *dest)
-{
- struct i2c_client *i2c = wm831x->control_data;
- int ret;
- u16 r = cpu_to_be16(reg);
-
- ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
- if (ret < 0)
- return ret;
- if (ret != 2)
- return -EIO;
-
- ret = i2c_master_recv(i2c, dest, bytes);
- if (ret < 0)
- return ret;
- if (ret != bytes)
- return -EIO;
- return 0;
-}
-
-/* Currently we allocate the write buffer on the stack; this is OK for
- * small writes - if we need to do large writes this will need to be
- * revised.
- */
-static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
- int bytes, void *src)
-{
- struct i2c_client *i2c = wm831x->control_data;
- struct i2c_msg xfer[2];
- int ret;
-
- reg = cpu_to_be16(reg);
-
- xfer[0].addr = i2c->addr;
- xfer[0].flags = 0;
- xfer[0].len = 2;
- xfer[0].buf = (char *)&reg;
-
- xfer[1].addr = i2c->addr;
- xfer[1].flags = I2C_M_NOSTART;
- xfer[1].len = bytes;
- xfer[1].buf = (char *)src;
-
- ret = i2c_transfer(i2c->adapter, xfer, 2);
- if (ret < 0)
- return ret;
- if (ret != 2)
- return -EIO;
-
- return 0;
-}
-
static int wm831x_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm831x *wm831x;
+ int ret;
wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
if (wm831x == NULL)
@@ -86,9 +36,15 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm831x);
wm831x->dev = &i2c->dev;
- wm831x->control_data = i2c;
- wm831x->read_dev = wm831x_i2c_read_device;
- wm831x->write_dev = wm831x_i2c_write_device;
+
+ wm831x->regmap = regmap_init_i2c(i2c, &wm831x_regmap_config);
+ if (IS_ERR(wm831x->regmap)) {
+ ret = PTR_ERR(wm831x->regmap);
+ dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
+ ret);
+ kfree(wm831x);
+ return ret;
+ }
return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
}
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index 8e8138ba0267..8d6a9a969dbc 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -16,78 +16,19 @@
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
#include <linux/mfd/wm831x/core.h>
-static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg,
- int bytes, void *dest)
-{
- u16 tx_val;
- u16 *d = dest;
- int r, ret;
-
- /* Go register at a time */
- for (r = reg; r < reg + (bytes / 2); r++) {
- tx_val = r | 0x8000;
-
- ret = spi_write_then_read(wm831x->control_data,
- (u8 *)&tx_val, 2, (u8 *)d, 2);
- if (ret != 0)
- return ret;
-
- *d = be16_to_cpu(*d);
-
- d++;
- }
-
- return 0;
-}
-
-static int wm831x_spi_write_device(struct wm831x *wm831x, unsigned short reg,
- int bytes, void *src)
-{
- struct spi_device *spi = wm831x->control_data;
- u16 *s = src;
- u16 data[2];
- int ret, r;
-
- /* Go register at a time */
- for (r = reg; r < reg + (bytes / 2); r++) {
- data[0] = r;
- data[1] = *s++;
-
- ret = spi_write(spi, (char *)&data, sizeof(data));
- if (ret != 0)
- return ret;
- }
-
- return 0;
-}
-
static int __devinit wm831x_spi_probe(struct spi_device *spi)
{
+ const struct spi_device_id *id = spi_get_device_id(spi);
struct wm831x *wm831x;
enum wm831x_parent type;
+ int ret;
- /* Currently SPI support for ID tables is unmerged, we're faking it */
- if (strcmp(spi->modalias, "wm8310") == 0)
- type = WM8310;
- else if (strcmp(spi->modalias, "wm8311") == 0)
- type = WM8311;
- else if (strcmp(spi->modalias, "wm8312") == 0)
- type = WM8312;
- else if (strcmp(spi->modalias, "wm8320") == 0)
- type = WM8320;
- else if (strcmp(spi->modalias, "wm8321") == 0)
- type = WM8321;
- else if (strcmp(spi->modalias, "wm8325") == 0)
- type = WM8325;
- else if (strcmp(spi->modalias, "wm8326") == 0)
- type = WM8326;
- else {
- dev_err(&spi->dev, "Unknown device type\n");
- return -EINVAL;
- }
+ type = (enum wm831x_parent)id->driver_data;
wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
if (wm831x == NULL)
@@ -98,9 +39,15 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
dev_set_drvdata(&spi->dev, wm831x);
wm831x->dev = &spi->dev;
- wm831x->control_data = spi;
- wm831x->read_dev = wm831x_spi_read_device;
- wm831x->write_dev = wm831x_spi_write_device;
+
+ wm831x->regmap = regmap_init_spi(spi, &wm831x_regmap_config);
+ if (IS_ERR(wm831x->regmap)) {
+ ret = PTR_ERR(wm831x->regmap);
+ dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
+ ret);
+ kfree(wm831x);
+ return ret;
+ }
return wm831x_device_init(wm831x, type, spi->irq);
}
@@ -133,115 +80,38 @@ static const struct dev_pm_ops wm831x_spi_pm = {
.suspend = wm831x_spi_suspend,
};
-static struct spi_driver wm8310_spi_driver = {
- .driver = {
- .name = "wm8310",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- .pm = &wm831x_spi_pm,
- },
- .probe = wm831x_spi_probe,
- .remove = __devexit_p(wm831x_spi_remove),
+static const struct spi_device_id wm831x_spi_ids[] = {
+ { "wm8310", WM8310 },
+ { "wm8311", WM8311 },
+ { "wm8312", WM8312 },
+ { "wm8320", WM8320 },
+ { "wm8321", WM8321 },
+ { "wm8325", WM8325 },
+ { "wm8326", WM8326 },
+ { },
};
+MODULE_DEVICE_TABLE(spi, wm831x_spi_id);
-static struct spi_driver wm8311_spi_driver = {
+static struct spi_driver wm831x_spi_driver = {
.driver = {
- .name = "wm8311",
+ .name = "wm831x",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},
+ .id_table = wm831x_spi_ids,
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
.shutdown = wm831x_spi_shutdown,
};
-static struct spi_driver wm8312_spi_driver = {
- .driver = {
- .name = "wm8312",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- .pm = &wm831x_spi_pm,
- },
- .probe = wm831x_spi_probe,
- .remove = __devexit_p(wm831x_spi_remove),
-};
-
-static struct spi_driver wm8320_spi_driver = {
- .driver = {
- .name = "wm8320",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- .pm = &wm831x_spi_pm,
- },
- .probe = wm831x_spi_probe,
- .remove = __devexit_p(wm831x_spi_remove),
-};
-
-static struct spi_driver wm8321_spi_driver = {
- .driver = {
- .name = "wm8321",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- .pm = &wm831x_spi_pm,
- },
- .probe = wm831x_spi_probe,
- .remove = __devexit_p(wm831x_spi_remove),
-};
-
-static struct spi_driver wm8325_spi_driver = {
- .driver = {
- .name = "wm8325",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- .pm = &wm831x_spi_pm,
- },
- .probe = wm831x_spi_probe,
- .remove = __devexit_p(wm831x_spi_remove),
-};
-
-static struct spi_driver wm8326_spi_driver = {
- .driver = {
- .name = "wm8326",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- .pm = &wm831x_spi_pm,
- },
- .probe = wm831x_spi_probe,
- .remove = __devexit_p(wm831x_spi_remove),
-};
-
static int __init wm831x_spi_init(void)
{
int ret;
- ret = spi_register_driver(&wm8310_spi_driver);
- if (ret != 0)
- pr_err("Failed to register WM8310 SPI driver: %d\n", ret);
-
- ret = spi_register_driver(&wm8311_spi_driver);
- if (ret != 0)
- pr_err("Failed to register WM8311 SPI driver: %d\n", ret);
-
- ret = spi_register_driver(&wm8312_spi_driver);
- if (ret != 0)
- pr_err("Failed to register WM8312 SPI driver: %d\n", ret);
-
- ret = spi_register_driver(&wm8320_spi_driver);
- if (ret != 0)
- pr_err("Failed to register WM8320 SPI driver: %d\n", ret);
-
- ret = spi_register_driver(&wm8321_spi_driver);
- if (ret != 0)
- pr_err("Failed to register WM8321 SPI driver: %d\n", ret);
-
- ret = spi_register_driver(&wm8325_spi_driver);
- if (ret != 0)
- pr_err("Failed to register WM8325 SPI driver: %d\n", ret);
-
- ret = spi_register_driver(&wm8326_spi_driver);
+ ret = spi_register_driver(&wm831x_spi_driver);
if (ret != 0)
- pr_err("Failed to register WM8326 SPI driver: %d\n", ret);
+ pr_err("Failed to register WM831x SPI driver: %d\n", ret);
return 0;
}
@@ -249,13 +119,7 @@ subsys_initcall(wm831x_spi_init);
static void __exit wm831x_spi_exit(void)
{
- spi_unregister_driver(&wm8326_spi_driver);
- spi_unregister_driver(&wm8325_spi_driver);
- spi_unregister_driver(&wm8321_spi_driver);
- spi_unregister_driver(&wm8320_spi_driver);
- spi_unregister_driver(&wm8312_spi_driver);
- spi_unregister_driver(&wm8311_spi_driver);
- spi_unregister_driver(&wm8310_spi_driver);
+ spi_unregister_driver(&wm831x_spi_driver);
}
module_exit(wm831x_spi_exit);
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index 597f82edacaa..e06ba9440cdb 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -13,11 +13,13 @@
*/
#include <linux/bug.h>
+#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/mfd/wm8400-private.h>
#include <linux/mfd/wm8400-audio.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
static struct {
@@ -123,14 +125,9 @@ static int wm8400_read(struct wm8400 *wm8400, u8 reg, int num_regs, u16 *dest)
/* If there are any volatile reads then read back the entire block */
for (i = reg; i < reg + num_regs; i++)
if (reg_data[i].vol) {
- ret = wm8400->read_dev(wm8400->io_data, reg,
- num_regs, dest);
- if (ret != 0)
- return ret;
- for (i = 0; i < num_regs; i++)
- dest[i] = be16_to_cpu(dest[i]);
-
- return 0;
+ ret = regmap_bulk_read(wm8400->regmap, reg, dest,
+ num_regs);
+ return ret;
}
/* Otherwise use the cache */
@@ -149,14 +146,11 @@ static int wm8400_write(struct wm8400 *wm8400, u8 reg, int num_regs,
for (i = 0; i < num_regs; i++) {
BUG_ON(!reg_data[reg + i].writable);
wm8400->reg_cache[reg + i] = src[i];
- src[i] = cpu_to_be16(src[i]);
+ ret = regmap_write(wm8400->regmap, reg, src[i]);
+ if (ret != 0)
+ return ret;
}
- /* Do the actual I/O */
- ret = wm8400->write_dev(wm8400->io_data, reg, num_regs, src);
- if (ret != 0)
- return -EIO;
-
return 0;
}
@@ -270,14 +264,14 @@ static int wm8400_init(struct wm8400 *wm8400,
dev_set_drvdata(wm8400->dev, wm8400);
/* Check that this is actually a WM8400 */
- ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, &reg);
+ ret = regmap_read(wm8400->regmap, WM8400_RESET_ID, &i);
if (ret != 0) {
dev_err(wm8400->dev, "Chip ID register read failed\n");
return -EIO;
}
- if (be16_to_cpu(reg) != reg_data[WM8400_RESET_ID].default_val) {
+ if (i != reg_data[WM8400_RESET_ID].default_val) {
dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n",
- be16_to_cpu(reg));
+ reg);
return -ENODEV;
}
@@ -285,9 +279,8 @@ static int wm8400_init(struct wm8400 *wm8400,
* is a PMIC we can't reset it safely so initialise the register
* cache from the hardware.
*/
- ret = wm8400->read_dev(wm8400->io_data, 0,
- ARRAY_SIZE(wm8400->reg_cache),
- wm8400->reg_cache);
+ ret = regmap_raw_read(wm8400->regmap, 0, wm8400->reg_cache,
+ ARRAY_SIZE(wm8400->reg_cache));
if (ret != 0) {
dev_err(wm8400->dev, "Register cache read failed\n");
return -EIO;
@@ -337,60 +330,13 @@ static void wm8400_release(struct wm8400 *wm8400)
mfd_remove_devices(wm8400->dev);
}
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static int wm8400_i2c_read(void *io_data, char reg, int count, u16 *dest)
-{
- struct i2c_client *i2c = io_data;
- struct i2c_msg xfer[2];
- int ret;
-
- /* Write register */
- xfer[0].addr = i2c->addr;
- xfer[0].flags = 0;
- xfer[0].len = 1;
- xfer[0].buf = &reg;
-
- /* Read data */
- xfer[1].addr = i2c->addr;
- xfer[1].flags = I2C_M_RD;
- xfer[1].len = count * sizeof(u16);
- xfer[1].buf = (u8 *)dest;
-
- ret = i2c_transfer(i2c->adapter, xfer, 2);
- if (ret == 2)
- ret = 0;
- else if (ret >= 0)
- ret = -EIO;
-
- return ret;
-}
-
-static int wm8400_i2c_write(void *io_data, char reg, int count, const u16 *src)
-{
- struct i2c_client *i2c = io_data;
- u8 *msg;
- int ret;
-
- /* We add 1 byte for device register - ideally I2C would gather. */
- msg = kmalloc((count * sizeof(u16)) + 1, GFP_KERNEL);
- if (msg == NULL)
- return -ENOMEM;
-
- msg[0] = reg;
- memcpy(&msg[1], src, count * sizeof(u16));
-
- ret = i2c_master_send(i2c, msg, (count * sizeof(u16)) + 1);
-
- if (ret == (count * 2) + 1)
- ret = 0;
- else if (ret >= 0)
- ret = -EIO;
-
- kfree(msg);
-
- return ret;
-}
+static const struct regmap_config wm8400_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = WM8400_REGISTER_COUNT - 1,
+};
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static int wm8400_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -403,18 +349,23 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
goto err;
}
- wm8400->io_data = i2c;
- wm8400->read_dev = wm8400_i2c_read;
- wm8400->write_dev = wm8400_i2c_write;
+ wm8400->regmap = regmap_init_i2c(i2c, &wm8400_regmap_config);
+ if (IS_ERR(wm8400->regmap)) {
+ ret = PTR_ERR(wm8400->regmap);
+ goto struct_err;
+ }
+
wm8400->dev = &i2c->dev;
i2c_set_clientdata(i2c, wm8400);
ret = wm8400_init(wm8400, i2c->dev.platform_data);
if (ret != 0)
- goto struct_err;
+ goto map_err;
return 0;
+map_err:
+ regmap_exit(wm8400->regmap);
struct_err:
kfree(wm8400);
err:
@@ -426,6 +377,7 @@ static int wm8400_i2c_remove(struct i2c_client *i2c)
struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
wm8400_release(wm8400);
+ regmap_exit(wm8400->regmap);
kfree(wm8400);
return 0;
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 9b01a22c3e70..5d6ba132837e 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -16,9 +16,11 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/err.h>
#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h>
@@ -29,22 +31,7 @@
static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
int bytes, void *dest)
{
- int ret, i;
- u16 *buf = dest;
-
- BUG_ON(bytes % 2);
- BUG_ON(bytes <= 0);
-
- ret = wm8994->read_dev(wm8994, reg, bytes, dest);
- if (ret < 0)
- return ret;
-
- for (i = 0; i < bytes / 2; i++) {
- dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n",
- be16_to_cpu(buf[i]), reg + i, reg + i);
- }
-
- return 0;
+ return regmap_raw_read(wm8994->regmap, reg, dest, bytes);
}
/**
@@ -55,19 +42,15 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
*/
int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
{
- unsigned short val;
+ unsigned int val;
int ret;
- mutex_lock(&wm8994->io_lock);
-
- ret = wm8994_read(wm8994, reg, 2, &val);
-
- mutex_unlock(&wm8994->io_lock);
+ ret = regmap_read(wm8994->regmap, reg, &val);
if (ret < 0)
return ret;
else
- return be16_to_cpu(val);
+ return val;
}
EXPORT_SYMBOL_GPL(wm8994_reg_read);
@@ -82,33 +65,13 @@ EXPORT_SYMBOL_GPL(wm8994_reg_read);
int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
int count, u16 *buf)
{
- int ret;
-
- mutex_lock(&wm8994->io_lock);
-
- ret = wm8994_read(wm8994, reg, count * 2, buf);
-
- mutex_unlock(&wm8994->io_lock);
-
- return ret;
+ return regmap_bulk_read(wm8994->regmap, reg, buf, count);
}
-EXPORT_SYMBOL_GPL(wm8994_bulk_read);
static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
int bytes, const void *src)
{
- const u16 *buf = src;
- int i;
-
- BUG_ON(bytes % 2);
- BUG_ON(bytes <= 0);
-
- for (i = 0; i < bytes / 2; i++) {
- dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n",
- be16_to_cpu(buf[i]), reg + i, reg + i);
- }
-
- return wm8994->write_dev(wm8994, reg, bytes, src);
+ return regmap_raw_write(wm8994->regmap, reg, src, bytes);
}
/**
@@ -121,17 +84,7 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
unsigned short val)
{
- int ret;
-
- val = cpu_to_be16(val);
-
- mutex_lock(&wm8994->io_lock);
-
- ret = wm8994_write(wm8994, reg, 2, &val);
-
- mutex_unlock(&wm8994->io_lock);
-
- return ret;
+ return regmap_write(wm8994->regmap, reg, val);
}
EXPORT_SYMBOL_GPL(wm8994_reg_write);
@@ -146,15 +99,7 @@ EXPORT_SYMBOL_GPL(wm8994_reg_write);
int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
int count, const u16 *buf)
{
- int ret;
-
- mutex_lock(&wm8994->io_lock);
-
- ret = wm8994_write(wm8994, reg, count * 2, buf);
-
- mutex_unlock(&wm8994->io_lock);
-
- return ret;
+ return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16));
}
EXPORT_SYMBOL_GPL(wm8994_bulk_write);
@@ -169,28 +114,7 @@ EXPORT_SYMBOL_GPL(wm8994_bulk_write);
int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
unsigned short mask, unsigned short val)
{
- int ret;
- u16 r;
-
- mutex_lock(&wm8994->io_lock);
-
- ret = wm8994_read(wm8994, reg, 2, &r);
- if (ret < 0)
- goto out;
-
- r = be16_to_cpu(r);
-
- r &= ~mask;
- r |= val;
-
- r = cpu_to_be16(r);
-
- ret = wm8994_write(wm8994, reg, 2, &r);
-
-out:
- mutex_unlock(&wm8994->io_lock);
-
- return ret;
+ return regmap_update_bits(wm8994->regmap, reg, mask, val);
}
EXPORT_SYMBOL_GPL(wm8994_set_bits);
@@ -243,6 +167,18 @@ static struct mfd_cell wm8994_devs[] = {
* and should be handled via the standard regulator API supply
* management.
*/
+static const char *wm1811_main_supplies[] = {
+ "DBVDD1",
+ "DBVDD2",
+ "DBVDD3",
+ "DCVDD",
+ "AVDD1",
+ "AVDD2",
+ "CPVDD",
+ "SPKVDD1",
+ "SPKVDD2",
+};
+
static const char *wm8994_main_supplies[] = {
"DBVDD",
"DCVDD",
@@ -424,6 +360,11 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
}
#endif
+static struct regmap_config wm8994_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+};
+
/*
* Instantiate the generic non-control parts of the device.
*/
@@ -433,7 +374,6 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
const char *devname;
int ret, i;
- mutex_init(&wm8994->io_lock);
dev_set_drvdata(wm8994->dev, wm8994);
/* Add the on-chip regulators first for bootstrapping */
@@ -443,10 +383,13 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
NULL, 0);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
- goto err;
+ goto err_regmap;
}
switch (wm8994->type) {
+ case WM1811:
+ wm8994->num_supplies = ARRAY_SIZE(wm1811_main_supplies);
+ break;
case WM8994:
wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);
break;
@@ -455,7 +398,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
break;
default:
BUG();
- goto err;
+ goto err_regmap;
}
wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
@@ -463,10 +406,14 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
GFP_KERNEL);
if (!wm8994->supplies) {
ret = -ENOMEM;
- goto err;
+ goto err_regmap;
}
switch (wm8994->type) {
+ case WM1811:
+ for (i = 0; i < ARRAY_SIZE(wm1811_main_supplies); i++)
+ wm8994->supplies[i].supply = wm1811_main_supplies[i];
+ break;
case WM8994:
for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
wm8994->supplies[i].supply = wm8994_main_supplies[i];
@@ -477,7 +424,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
break;
default:
BUG();
- goto err;
+ goto err_regmap;
}
ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
@@ -500,6 +447,13 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
goto err_enable;
}
switch (ret) {
+ case 0x1811:
+ devname = "WM1811";
+ if (wm8994->type != WM1811)
+ dev_warn(wm8994->dev, "Device registered as type %d\n",
+ wm8994->type);
+ wm8994->type = WM1811;
+ break;
case 0x8994:
devname = "WM8994";
if (wm8994->type != WM8994)
@@ -607,7 +561,8 @@ err_get:
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
err_supplies:
kfree(wm8994->supplies);
-err:
+err_regmap:
+ regmap_exit(wm8994->regmap);
mfd_remove_devices(wm8994->dev);
kfree(wm8994);
return ret;
@@ -622,62 +577,15 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
wm8994->supplies);
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
kfree(wm8994->supplies);
+ regmap_exit(wm8994->regmap);
kfree(wm8994);
}
-static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg,
- int bytes, void *dest)
-{
- struct i2c_client *i2c = wm8994->control_data;
- int ret;
- u16 r = cpu_to_be16(reg);
-
- ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
- if (ret < 0)
- return ret;
- if (ret != 2)
- return -EIO;
-
- ret = i2c_master_recv(i2c, dest, bytes);
- if (ret < 0)
- return ret;
- if (ret != bytes)
- return -EIO;
- return 0;
-}
-
-static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg,
- int bytes, const void *src)
-{
- struct i2c_client *i2c = wm8994->control_data;
- struct i2c_msg xfer[2];
- int ret;
-
- reg = cpu_to_be16(reg);
-
- xfer[0].addr = i2c->addr;
- xfer[0].flags = 0;
- xfer[0].len = 2;
- xfer[0].buf = (char *)&reg;
-
- xfer[1].addr = i2c->addr;
- xfer[1].flags = I2C_M_NOSTART;
- xfer[1].len = bytes;
- xfer[1].buf = (char *)src;
-
- ret = i2c_transfer(i2c->adapter, xfer, 2);
- if (ret < 0)
- return ret;
- if (ret != 2)
- return -EIO;
-
- return 0;
-}
-
static int wm8994_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8994 *wm8994;
+ int ret;
wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
if (wm8994 == NULL)
@@ -685,12 +593,18 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8994);
wm8994->dev = &i2c->dev;
- wm8994->control_data = i2c;
- wm8994->read_dev = wm8994_i2c_read_device;
- wm8994->write_dev = wm8994_i2c_write_device;
wm8994->irq = i2c->irq;
wm8994->type = id->driver_data;
+ wm8994->regmap = regmap_init_i2c(i2c, &wm8994_regmap_config);
+ if (IS_ERR(wm8994->regmap)) {
+ ret = PTR_ERR(wm8994->regmap);
+ dev_err(wm8994->dev, "Failed to allocate register map: %d\n",
+ ret);
+ kfree(wm8994);
+ return ret;
+ }
+
return wm8994_device_init(wm8994, i2c->irq);
}
@@ -704,6 +618,7 @@ static int wm8994_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8994_i2c_id[] = {
+ { "wm1811", WM1811 },
{ "wm8994", WM8994 },
{ "wm8958", WM8958 },
{ }
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2d6423c2d193..d593878d66d0 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -63,7 +63,7 @@ config AD525X_DPOT_SPI
config ATMEL_PWM
tristate "Atmel AT32/AT91 PWM support"
- depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9
+ depends on HAVE_CLK
help
This option enables device driver support for the PWM channels
on certain Atmel processors. Pulse Width Modulation is used for
@@ -506,5 +506,6 @@ source "drivers/misc/iwmc3200top/Kconfig"
source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/carma/Kconfig"
+source "drivers/misc/altera-stapl/Kconfig"
endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 8f3efb68a141..b26495a02554 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o
obj-y += lis3lv02d/
obj-y += carma/
obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
+obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
index 4ff73c215746..a39e0555df63 100644
--- a/drivers/misc/ad525x_dpot-i2c.c
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -98,6 +98,7 @@ static const struct i2c_device_id ad_dpot_id[] = {
{"ad5282", AD5282_ID},
{"adn2860", ADN2860_ID},
{"ad5273", AD5273_ID},
+ {"ad5161", AD5161_ID},
{"ad5171", AD5171_ID},
{"ad5170", AD5170_ID},
{"ad5172", AD5172_ID},
diff --git a/drivers/staging/altera-stapl/Kconfig b/drivers/misc/altera-stapl/Kconfig
index b6537321ed72..7f01d8e93992 100644
--- a/drivers/staging/altera-stapl/Kconfig
+++ b/drivers/misc/altera-stapl/Kconfig
@@ -1,3 +1,5 @@
+comment "Altera FPGA firmware download module"
+
config ALTERA_STAPL
tristate "Altera FPGA firmware download module"
depends on I2C
diff --git a/drivers/misc/altera-stapl/Makefile b/drivers/misc/altera-stapl/Makefile
new file mode 100644
index 000000000000..055f61ee781a
--- /dev/null
+++ b/drivers/misc/altera-stapl/Makefile
@@ -0,0 +1,3 @@
+altera-stapl-objs = altera-lpt.o altera-jtag.o altera-comp.o altera.o
+
+obj-$(CONFIG_ALTERA_STAPL) += altera-stapl.o
diff --git a/drivers/staging/altera-stapl/altera-comp.c b/drivers/misc/altera-stapl/altera-comp.c
index 49b103bedaaf..49b103bedaaf 100644
--- a/drivers/staging/altera-stapl/altera-comp.c
+++ b/drivers/misc/altera-stapl/altera-comp.c
diff --git a/drivers/staging/altera-stapl/altera-exprt.h b/drivers/misc/altera-stapl/altera-exprt.h
index 39c38d84a670..39c38d84a670 100644
--- a/drivers/staging/altera-stapl/altera-exprt.h
+++ b/drivers/misc/altera-stapl/altera-exprt.h
diff --git a/drivers/staging/altera-stapl/altera-jtag.c b/drivers/misc/altera-stapl/altera-jtag.c
index 8b1620b1b2d0..f4bf20096972 100644
--- a/drivers/staging/altera-stapl/altera-jtag.c
+++ b/drivers/misc/altera-stapl/altera-jtag.c
@@ -26,7 +26,7 @@
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/slab.h>
-#include "altera.h"
+#include <misc/altera.h>
#include "altera-exprt.h"
#include "altera-jtag.h"
diff --git a/drivers/staging/altera-stapl/altera-jtag.h b/drivers/misc/altera-stapl/altera-jtag.h
index 2f97e36a2fbc..2f97e36a2fbc 100644
--- a/drivers/staging/altera-stapl/altera-jtag.h
+++ b/drivers/misc/altera-stapl/altera-jtag.h
diff --git a/drivers/staging/altera-stapl/altera-lpt.c b/drivers/misc/altera-stapl/altera-lpt.c
index 91456a03612d..91456a03612d 100644
--- a/drivers/staging/altera-stapl/altera-lpt.c
+++ b/drivers/misc/altera-stapl/altera-lpt.c
diff --git a/drivers/staging/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c
index 8d73a8642736..24272e022bec 100644
--- a/drivers/staging/altera-stapl/altera.c
+++ b/drivers/misc/altera-stapl/altera.c
@@ -28,7 +28,8 @@
#include <linux/string.h>
#include <linux/firmware.h>
#include <linux/slab.h>
-#include "altera.h"
+#include <linux/module.h>
+#include <misc/altera.h>
#include "altera-exprt.h"
#include "altera-jtag.h"
@@ -2384,7 +2385,7 @@ static int altera_get_act_info(u8 *p,
act_proc_attribute =
(p[proc_table + (13 * act_proc_id) + 8] & 0x03);
- procptr = (struct altera_procinfo *)
+ procptr =
kzalloc(sizeof(struct altera_procinfo),
GFP_KERNEL);
diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c
index 27dc0d21aafa..f6586d53e1a3 100644
--- a/drivers/misc/fsa9480.c
+++ b/drivers/misc/fsa9480.c
@@ -400,7 +400,8 @@ static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw)
return ret;
}
- device_init_wakeup(&client->dev, pdata->wakeup);
+ if (pdata)
+ device_init_wakeup(&client->dev, pdata->wakeup);
}
return 0;
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c
index 8b51cd62d067..29d12a70eb1b 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d.c
@@ -163,7 +163,7 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
int i;
if (lis3->blkread) {
- if (lis3_dev.whoami == WAI_12B) {
+ if (lis3->whoami == WAI_12B) {
u16 data[3];
lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
for (i = 0; i < 3; i++)
@@ -195,18 +195,30 @@ static int lis3_8_rates[2] = {100, 400};
static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
/* ODR is Output Data Rate */
-static int lis3lv02d_get_odr(void)
+static int lis3lv02d_get_odr(struct lis3lv02d *lis3)
{
u8 ctrl;
int shift;
- lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
- ctrl &= lis3_dev.odr_mask;
- shift = ffs(lis3_dev.odr_mask) - 1;
- return lis3_dev.odrs[(ctrl >> shift)];
+ lis3->read(lis3, CTRL_REG1, &ctrl);
+ ctrl &= lis3->odr_mask;
+ shift = ffs(lis3->odr_mask) - 1;
+ return lis3->odrs[(ctrl >> shift)];
}
-static int lis3lv02d_set_odr(int rate)
+static int lis3lv02d_get_pwron_wait(struct lis3lv02d *lis3)
+{
+ int div = lis3lv02d_get_odr(lis3);
+
+ if (WARN_ONCE(div == 0, "device returned spurious data"))
+ return -ENXIO;
+
+ /* LIS3 power on delay is quite long */
+ msleep(lis3->pwron_delay / div);
+ return 0;
+}
+
+static int lis3lv02d_set_odr(struct lis3lv02d *lis3, int rate)
{
u8 ctrl;
int i, len, shift;
@@ -214,14 +226,14 @@ static int lis3lv02d_set_odr(int rate)
if (!rate)
return -EINVAL;
- lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
- ctrl &= ~lis3_dev.odr_mask;
- len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
- shift = ffs(lis3_dev.odr_mask) - 1;
+ lis3->read(lis3, CTRL_REG1, &ctrl);
+ ctrl &= ~lis3->odr_mask;
+ len = 1 << hweight_long(lis3->odr_mask); /* # of possible values */
+ shift = ffs(lis3->odr_mask) - 1;
for (i = 0; i < len; i++)
- if (lis3_dev.odrs[i] == rate) {
- lis3_dev.write(&lis3_dev, CTRL_REG1,
+ if (lis3->odrs[i] == rate) {
+ lis3->write(lis3, CTRL_REG1,
ctrl | (i << shift));
return 0;
}
@@ -240,12 +252,12 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
mutex_lock(&lis3->mutex);
irq_cfg = lis3->irq_cfg;
- if (lis3_dev.whoami == WAI_8B) {
+ if (lis3->whoami == WAI_8B) {
lis3->data_ready_count[IRQ_LINE0] = 0;
lis3->data_ready_count[IRQ_LINE1] = 0;
/* Change interrupt cfg to data ready for selftest */
- atomic_inc(&lis3_dev.wake_thread);
+ atomic_inc(&lis3->wake_thread);
lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
@@ -253,12 +265,12 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
}
- if (lis3_dev.whoami == WAI_3DC) {
+ if (lis3->whoami == WAI_3DC) {
ctlreg = CTRL_REG4;
selftest = CTRL4_ST0;
} else {
ctlreg = CTRL_REG1;
- if (lis3_dev.whoami == WAI_12B)
+ if (lis3->whoami == WAI_12B)
selftest = CTRL1_ST;
else
selftest = CTRL1_STP;
@@ -266,7 +278,9 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
lis3->read(lis3, ctlreg, &reg);
lis3->write(lis3, ctlreg, (reg | selftest));
- msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+ ret = lis3lv02d_get_pwron_wait(lis3);
+ if (ret)
+ goto fail;
/* Read directly to avoid axis remap */
x = lis3->read_data(lis3, OUTX);
@@ -275,7 +289,9 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
/* back to normal settings */
lis3->write(lis3, ctlreg, reg);
- msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+ ret = lis3lv02d_get_pwron_wait(lis3);
+ if (ret)
+ goto fail;
results[0] = x - lis3->read_data(lis3, OUTX);
results[1] = y - lis3->read_data(lis3, OUTY);
@@ -283,9 +299,9 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
ret = 0;
- if (lis3_dev.whoami == WAI_8B) {
+ if (lis3->whoami == WAI_8B) {
/* Restore original interrupt configuration */
- atomic_dec(&lis3_dev.wake_thread);
+ atomic_dec(&lis3->wake_thread);
lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
lis3->irq_cfg = irq_cfg;
@@ -363,8 +379,9 @@ void lis3lv02d_poweroff(struct lis3lv02d *lis3)
}
EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
-void lis3lv02d_poweron(struct lis3lv02d *lis3)
+int lis3lv02d_poweron(struct lis3lv02d *lis3)
{
+ int err;
u8 reg;
lis3->init(lis3);
@@ -384,35 +401,41 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3)
lis3->write(lis3, CTRL_REG2, reg);
}
- /* LIS3 power on delay is quite long */
- msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+ err = lis3lv02d_get_pwron_wait(lis3);
+ if (err)
+ return err;
if (lis3->reg_ctrl)
lis3_context_restore(lis3);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
{
+ struct lis3lv02d *lis3 = pidev->private;
int x, y, z;
- mutex_lock(&lis3_dev.mutex);
- lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+ mutex_lock(&lis3->mutex);
+ lis3lv02d_get_xyz(lis3, &x, &y, &z);
input_report_abs(pidev->input, ABS_X, x);
input_report_abs(pidev->input, ABS_Y, y);
input_report_abs(pidev->input, ABS_Z, z);
input_sync(pidev->input);
- mutex_unlock(&lis3_dev.mutex);
+ mutex_unlock(&lis3->mutex);
}
static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
{
- if (lis3_dev.pm_dev)
- pm_runtime_get_sync(lis3_dev.pm_dev);
+ struct lis3lv02d *lis3 = pidev->private;
- if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
- atomic_set(&lis3_dev.wake_thread, 1);
+ if (lis3->pm_dev)
+ pm_runtime_get_sync(lis3->pm_dev);
+
+ if (lis3->pdata && lis3->whoami == WAI_8B && lis3->idev)
+ atomic_set(&lis3->wake_thread, 1);
/*
* Update coordinates for the case where poll interval is 0 and
* the chip in running purely under interrupt control
@@ -422,14 +445,18 @@ static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
{
- atomic_set(&lis3_dev.wake_thread, 0);
- if (lis3_dev.pm_dev)
- pm_runtime_put(lis3_dev.pm_dev);
+ struct lis3lv02d *lis3 = pidev->private;
+
+ atomic_set(&lis3->wake_thread, 0);
+ if (lis3->pm_dev)
+ pm_runtime_put(lis3->pm_dev);
}
-static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
+static irqreturn_t lis302dl_interrupt(int irq, void *data)
{
- if (!test_bit(0, &lis3_dev.misc_opened))
+ struct lis3lv02d *lis3 = data;
+
+ if (!test_bit(0, &lis3->misc_opened))
goto out;
/*
@@ -437,12 +464,12 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
* the lid is closed. This leads to interrupts as soon as a little move
* is done.
*/
- atomic_inc(&lis3_dev.count);
+ atomic_inc(&lis3->count);
- wake_up_interruptible(&lis3_dev.misc_wait);
- kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
+ wake_up_interruptible(&lis3->misc_wait);
+ kill_fasync(&lis3->async_queue, SIGIO, POLL_IN);
out:
- if (atomic_read(&lis3_dev.wake_thread))
+ if (atomic_read(&lis3->wake_thread))
return IRQ_WAKE_THREAD;
return IRQ_HANDLED;
}
@@ -514,28 +541,37 @@ static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
{
- if (test_and_set_bit(0, &lis3_dev.misc_opened))
+ struct lis3lv02d *lis3 = container_of(file->private_data,
+ struct lis3lv02d, miscdev);
+
+ if (test_and_set_bit(0, &lis3->misc_opened))
return -EBUSY; /* already open */
- if (lis3_dev.pm_dev)
- pm_runtime_get_sync(lis3_dev.pm_dev);
+ if (lis3->pm_dev)
+ pm_runtime_get_sync(lis3->pm_dev);
- atomic_set(&lis3_dev.count, 0);
+ atomic_set(&lis3->count, 0);
return 0;
}
static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
{
- fasync_helper(-1, file, 0, &lis3_dev.async_queue);
- clear_bit(0, &lis3_dev.misc_opened); /* release the device */
- if (lis3_dev.pm_dev)
- pm_runtime_put(lis3_dev.pm_dev);
+ struct lis3lv02d *lis3 = container_of(file->private_data,
+ struct lis3lv02d, miscdev);
+
+ fasync_helper(-1, file, 0, &lis3->async_queue);
+ clear_bit(0, &lis3->misc_opened); /* release the device */
+ if (lis3->pm_dev)
+ pm_runtime_put(lis3->pm_dev);
return 0;
}
static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
+ struct lis3lv02d *lis3 = container_of(file->private_data,
+ struct lis3lv02d, miscdev);
+
DECLARE_WAITQUEUE(wait, current);
u32 data;
unsigned char byte_data;
@@ -544,10 +580,10 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
if (count < 1)
return -EINVAL;
- add_wait_queue(&lis3_dev.misc_wait, &wait);
+ add_wait_queue(&lis3->misc_wait, &wait);
while (true) {
set_current_state(TASK_INTERRUPTIBLE);
- data = atomic_xchg(&lis3_dev.count, 0);
+ data = atomic_xchg(&lis3->count, 0);
if (data)
break;
@@ -577,22 +613,28 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
out:
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&lis3_dev.misc_wait, &wait);
+ remove_wait_queue(&lis3->misc_wait, &wait);
return retval;
}
static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
{
- poll_wait(file, &lis3_dev.misc_wait, wait);
- if (atomic_read(&lis3_dev.count))
+ struct lis3lv02d *lis3 = container_of(file->private_data,
+ struct lis3lv02d, miscdev);
+
+ poll_wait(file, &lis3->misc_wait, wait);
+ if (atomic_read(&lis3->count))
return POLLIN | POLLRDNORM;
return 0;
}
static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
{
- return fasync_helper(fd, file, on, &lis3_dev.async_queue);
+ struct lis3lv02d *lis3 = container_of(file->private_data,
+ struct lis3lv02d, miscdev);
+
+ return fasync_helper(fd, file, on, &lis3->async_queue);
}
static const struct file_operations lis3lv02d_misc_fops = {
@@ -605,85 +647,80 @@ static const struct file_operations lis3lv02d_misc_fops = {
.fasync = lis3lv02d_misc_fasync,
};
-static struct miscdevice lis3lv02d_misc_device = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "freefall",
- .fops = &lis3lv02d_misc_fops,
-};
-
-int lis3lv02d_joystick_enable(void)
+int lis3lv02d_joystick_enable(struct lis3lv02d *lis3)
{
struct input_dev *input_dev;
int err;
int max_val, fuzz, flat;
int btns[] = {BTN_X, BTN_Y, BTN_Z};
- if (lis3_dev.idev)
+ if (lis3->idev)
return -EINVAL;
- lis3_dev.idev = input_allocate_polled_device();
- if (!lis3_dev.idev)
+ lis3->idev = input_allocate_polled_device();
+ if (!lis3->idev)
return -ENOMEM;
- lis3_dev.idev->poll = lis3lv02d_joystick_poll;
- lis3_dev.idev->open = lis3lv02d_joystick_open;
- lis3_dev.idev->close = lis3lv02d_joystick_close;
- lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
- lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
- lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
- input_dev = lis3_dev.idev->input;
+ lis3->idev->poll = lis3lv02d_joystick_poll;
+ lis3->idev->open = lis3lv02d_joystick_open;
+ lis3->idev->close = lis3lv02d_joystick_close;
+ lis3->idev->poll_interval = MDPS_POLL_INTERVAL;
+ lis3->idev->poll_interval_min = MDPS_POLL_MIN;
+ lis3->idev->poll_interval_max = MDPS_POLL_MAX;
+ lis3->idev->private = lis3;
+ input_dev = lis3->idev->input;
input_dev->name = "ST LIS3LV02DL Accelerometer";
input_dev->phys = DRIVER_NAME "/input0";
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0;
- input_dev->dev.parent = &lis3_dev.pdev->dev;
+ input_dev->dev.parent = &lis3->pdev->dev;
set_bit(EV_ABS, input_dev->evbit);
- max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
- if (lis3_dev.whoami == WAI_12B) {
+ max_val = (lis3->mdps_max_val * lis3->scale) / LIS3_ACCURACY;
+ if (lis3->whoami == WAI_12B) {
fuzz = LIS3_DEFAULT_FUZZ_12B;
flat = LIS3_DEFAULT_FLAT_12B;
} else {
fuzz = LIS3_DEFAULT_FUZZ_8B;
flat = LIS3_DEFAULT_FLAT_8B;
}
- fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
- flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
+ fuzz = (fuzz * lis3->scale) / LIS3_ACCURACY;
+ flat = (flat * lis3->scale) / LIS3_ACCURACY;
input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
- lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
- lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
- lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
+ lis3->mapped_btns[0] = lis3lv02d_get_axis(abs(lis3->ac.x), btns);
+ lis3->mapped_btns[1] = lis3lv02d_get_axis(abs(lis3->ac.y), btns);
+ lis3->mapped_btns[2] = lis3lv02d_get_axis(abs(lis3->ac.z), btns);
- err = input_register_polled_device(lis3_dev.idev);
+ err = input_register_polled_device(lis3->idev);
if (err) {
- input_free_polled_device(lis3_dev.idev);
- lis3_dev.idev = NULL;
+ input_free_polled_device(lis3->idev);
+ lis3->idev = NULL;
}
return err;
}
EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
-void lis3lv02d_joystick_disable(void)
+void lis3lv02d_joystick_disable(struct lis3lv02d *lis3)
{
- if (lis3_dev.irq)
- free_irq(lis3_dev.irq, &lis3_dev);
- if (lis3_dev.pdata && lis3_dev.pdata->irq2)
- free_irq(lis3_dev.pdata->irq2, &lis3_dev);
+ if (lis3->irq)
+ free_irq(lis3->irq, lis3);
+ if (lis3->pdata && lis3->pdata->irq2)
+ free_irq(lis3->pdata->irq2, lis3);
- if (!lis3_dev.idev)
+ if (!lis3->idev)
return;
- if (lis3_dev.irq)
- misc_deregister(&lis3lv02d_misc_device);
- input_unregister_polled_device(lis3_dev.idev);
- input_free_polled_device(lis3_dev.idev);
- lis3_dev.idev = NULL;
+ if (lis3->irq)
+ misc_deregister(&lis3->miscdev);
+ input_unregister_polled_device(lis3->idev);
+ input_free_polled_device(lis3->idev);
+ lis3->idev = NULL;
}
EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
@@ -708,6 +745,7 @@ static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
static ssize_t lis3lv02d_selftest_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct lis3lv02d *lis3 = dev_get_drvdata(dev);
s16 values[3];
static const char ok[] = "OK";
@@ -715,8 +753,8 @@ static ssize_t lis3lv02d_selftest_show(struct device *dev,
static const char irq[] = "FAIL_IRQ";
const char *res;
- lis3lv02d_sysfs_poweron(&lis3_dev);
- switch (lis3lv02d_selftest(&lis3_dev, values)) {
+ lis3lv02d_sysfs_poweron(lis3);
+ switch (lis3lv02d_selftest(lis3, values)) {
case SELFTEST_FAIL:
res = fail;
break;
@@ -735,33 +773,37 @@ static ssize_t lis3lv02d_selftest_show(struct device *dev,
static ssize_t lis3lv02d_position_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct lis3lv02d *lis3 = dev_get_drvdata(dev);
int x, y, z;
- lis3lv02d_sysfs_poweron(&lis3_dev);
- mutex_lock(&lis3_dev.mutex);
- lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
- mutex_unlock(&lis3_dev.mutex);
+ lis3lv02d_sysfs_poweron(lis3);
+ mutex_lock(&lis3->mutex);
+ lis3lv02d_get_xyz(lis3, &x, &y, &z);
+ mutex_unlock(&lis3->mutex);
return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
}
static ssize_t lis3lv02d_rate_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- lis3lv02d_sysfs_poweron(&lis3_dev);
- return sprintf(buf, "%d\n", lis3lv02d_get_odr());
+ struct lis3lv02d *lis3 = dev_get_drvdata(dev);
+
+ lis3lv02d_sysfs_poweron(lis3);
+ return sprintf(buf, "%d\n", lis3lv02d_get_odr(lis3));
}
static ssize_t lis3lv02d_rate_set(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
+ struct lis3lv02d *lis3 = dev_get_drvdata(dev);
unsigned long rate;
if (strict_strtoul(buf, 0, &rate))
return -EINVAL;
- lis3lv02d_sysfs_poweron(&lis3_dev);
- if (lis3lv02d_set_odr(rate))
+ lis3lv02d_sysfs_poweron(lis3);
+ if (lis3lv02d_set_odr(lis3, rate))
return -EINVAL;
return count;
@@ -790,6 +832,7 @@ static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
if (IS_ERR(lis3->pdev))
return PTR_ERR(lis3->pdev);
+ platform_set_drvdata(lis3->pdev, lis3);
return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
}
@@ -803,7 +846,7 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
/* SYSFS may have left chip running. Turn off if necessary */
if (!pm_runtime_suspended(lis3->pm_dev))
- lis3lv02d_poweroff(&lis3_dev);
+ lis3lv02d_poweroff(lis3);
pm_runtime_disable(lis3->pm_dev);
pm_runtime_set_suspended(lis3->pm_dev);
@@ -813,24 +856,24 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
}
EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
-static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
+static void lis3lv02d_8b_configure(struct lis3lv02d *lis3,
struct lis3lv02d_platform_data *p)
{
int err;
int ctrl2 = p->hipass_ctrl;
if (p->click_flags) {
- dev->write(dev, CLICK_CFG, p->click_flags);
- dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
- dev->write(dev, CLICK_LATENCY, p->click_latency);
- dev->write(dev, CLICK_WINDOW, p->click_window);
- dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
- dev->write(dev, CLICK_THSY_X,
+ lis3->write(lis3, CLICK_CFG, p->click_flags);
+ lis3->write(lis3, CLICK_TIMELIMIT, p->click_time_limit);
+ lis3->write(lis3, CLICK_LATENCY, p->click_latency);
+ lis3->write(lis3, CLICK_WINDOW, p->click_window);
+ lis3->write(lis3, CLICK_THSZ, p->click_thresh_z & 0xf);
+ lis3->write(lis3, CLICK_THSY_X,
(p->click_thresh_x & 0xf) |
(p->click_thresh_y << 4));
- if (dev->idev) {
- struct input_dev *input_dev = lis3_dev.idev->input;
+ if (lis3->idev) {
+ struct input_dev *input_dev = lis3->idev->input;
input_set_capability(input_dev, EV_KEY, BTN_X);
input_set_capability(input_dev, EV_KEY, BTN_Y);
input_set_capability(input_dev, EV_KEY, BTN_Z);
@@ -838,22 +881,22 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
}
if (p->wakeup_flags) {
- dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
- dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
+ lis3->write(lis3, FF_WU_CFG_1, p->wakeup_flags);
+ lis3->write(lis3, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
/* pdata value + 1 to keep this backward compatible*/
- dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
+ lis3->write(lis3, FF_WU_DURATION_1, p->duration1 + 1);
ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
}
if (p->wakeup_flags2) {
- dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
- dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
+ lis3->write(lis3, FF_WU_CFG_2, p->wakeup_flags2);
+ lis3->write(lis3, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
/* pdata value + 1 to keep this backward compatible*/
- dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
+ lis3->write(lis3, FF_WU_DURATION_2, p->duration2 + 1);
ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
}
/* Configure hipass filters */
- dev->write(dev, CTRL_REG2, ctrl2);
+ lis3->write(lis3, CTRL_REG2, ctrl2);
if (p->irq2) {
err = request_threaded_irq(p->irq2,
@@ -861,7 +904,7 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
lis302dl_interrupt_thread2_8b,
IRQF_TRIGGER_RISING | IRQF_ONESHOT |
(p->irq_flags2 & IRQF_TRIGGER_MASK),
- DRIVER_NAME, &lis3_dev);
+ DRIVER_NAME, lis3);
if (err < 0)
pr_err("No second IRQ. Limited functionality\n");
}
@@ -871,93 +914,97 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
* Initialise the accelerometer and the various subsystems.
* Should be rather independent of the bus system.
*/
-int lis3lv02d_init_device(struct lis3lv02d *dev)
+int lis3lv02d_init_device(struct lis3lv02d *lis3)
{
int err;
irq_handler_t thread_fn;
int irq_flags = 0;
- dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
+ lis3->whoami = lis3lv02d_read_8(lis3, WHO_AM_I);
- switch (dev->whoami) {
+ switch (lis3->whoami) {
case WAI_12B:
pr_info("12 bits sensor found\n");
- dev->read_data = lis3lv02d_read_12;
- dev->mdps_max_val = 2048;
- dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
- dev->odrs = lis3_12_rates;
- dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
- dev->scale = LIS3_SENSITIVITY_12B;
- dev->regs = lis3_wai12_regs;
- dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
+ lis3->read_data = lis3lv02d_read_12;
+ lis3->mdps_max_val = 2048;
+ lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
+ lis3->odrs = lis3_12_rates;
+ lis3->odr_mask = CTRL1_DF0 | CTRL1_DF1;
+ lis3->scale = LIS3_SENSITIVITY_12B;
+ lis3->regs = lis3_wai12_regs;
+ lis3->regs_size = ARRAY_SIZE(lis3_wai12_regs);
break;
case WAI_8B:
pr_info("8 bits sensor found\n");
- dev->read_data = lis3lv02d_read_8;
- dev->mdps_max_val = 128;
- dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
- dev->odrs = lis3_8_rates;
- dev->odr_mask = CTRL1_DR;
- dev->scale = LIS3_SENSITIVITY_8B;
- dev->regs = lis3_wai8_regs;
- dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
+ lis3->read_data = lis3lv02d_read_8;
+ lis3->mdps_max_val = 128;
+ lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+ lis3->odrs = lis3_8_rates;
+ lis3->odr_mask = CTRL1_DR;
+ lis3->scale = LIS3_SENSITIVITY_8B;
+ lis3->regs = lis3_wai8_regs;
+ lis3->regs_size = ARRAY_SIZE(lis3_wai8_regs);
break;
case WAI_3DC:
pr_info("8 bits 3DC sensor found\n");
- dev->read_data = lis3lv02d_read_8;
- dev->mdps_max_val = 128;
- dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
- dev->odrs = lis3_3dc_rates;
- dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
- dev->scale = LIS3_SENSITIVITY_8B;
+ lis3->read_data = lis3lv02d_read_8;
+ lis3->mdps_max_val = 128;
+ lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+ lis3->odrs = lis3_3dc_rates;
+ lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
+ lis3->scale = LIS3_SENSITIVITY_8B;
break;
default:
- pr_err("unknown sensor type 0x%X\n", dev->whoami);
+ pr_err("unknown sensor type 0x%X\n", lis3->whoami);
return -EINVAL;
}
- dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
+ lis3->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
sizeof(lis3_wai12_regs)), GFP_KERNEL);
- if (dev->reg_cache == NULL) {
+ if (lis3->reg_cache == NULL) {
printk(KERN_ERR DRIVER_NAME "out of memory\n");
return -ENOMEM;
}
- mutex_init(&dev->mutex);
- atomic_set(&dev->wake_thread, 0);
+ mutex_init(&lis3->mutex);
+ atomic_set(&lis3->wake_thread, 0);
- lis3lv02d_add_fs(dev);
- lis3lv02d_poweron(dev);
+ lis3lv02d_add_fs(lis3);
+ err = lis3lv02d_poweron(lis3);
+ if (err) {
+ lis3lv02d_remove_fs(lis3);
+ return err;
+ }
- if (dev->pm_dev) {
- pm_runtime_set_active(dev->pm_dev);
- pm_runtime_enable(dev->pm_dev);
+ if (lis3->pm_dev) {
+ pm_runtime_set_active(lis3->pm_dev);
+ pm_runtime_enable(lis3->pm_dev);
}
- if (lis3lv02d_joystick_enable())
+ if (lis3lv02d_joystick_enable(lis3))
pr_err("joystick initialization failed\n");
/* passing in platform specific data is purely optional and only
* used by the SPI transport layer at the moment */
- if (dev->pdata) {
- struct lis3lv02d_platform_data *p = dev->pdata;
+ if (lis3->pdata) {
+ struct lis3lv02d_platform_data *p = lis3->pdata;
- if (dev->whoami == WAI_8B)
- lis3lv02d_8b_configure(dev, p);
+ if (lis3->whoami == WAI_8B)
+ lis3lv02d_8b_configure(lis3, p);
irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
- dev->irq_cfg = p->irq_cfg;
+ lis3->irq_cfg = p->irq_cfg;
if (p->irq_cfg)
- dev->write(dev, CTRL_REG3, p->irq_cfg);
+ lis3->write(lis3, CTRL_REG3, p->irq_cfg);
if (p->default_rate)
- lis3lv02d_set_odr(p->default_rate);
+ lis3lv02d_set_odr(lis3, p->default_rate);
}
/* bail if we did not get an IRQ from the bus layer */
- if (!dev->irq) {
+ if (!lis3->irq) {
pr_debug("No IRQ. Disabling /dev/freefall\n");
goto out;
}
@@ -973,23 +1020,27 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
* io-apic is not configurable (and generates a warning) but I keep it
* in case of support for other hardware.
*/
- if (dev->pdata && dev->whoami == WAI_8B)
+ if (lis3->pdata && lis3->whoami == WAI_8B)
thread_fn = lis302dl_interrupt_thread1_8b;
else
thread_fn = NULL;
- err = request_threaded_irq(dev->irq, lis302dl_interrupt,
+ err = request_threaded_irq(lis3->irq, lis302dl_interrupt,
thread_fn,
IRQF_TRIGGER_RISING | IRQF_ONESHOT |
irq_flags,
- DRIVER_NAME, &lis3_dev);
+ DRIVER_NAME, lis3);
if (err < 0) {
pr_err("Cannot get IRQ\n");
goto out;
}
- if (misc_register(&lis3lv02d_misc_device))
+ lis3->miscdev.minor = MISC_DYNAMIC_MINOR;
+ lis3->miscdev.name = "freefall";
+ lis3->miscdev.fops = &lis3lv02d_misc_fops;
+
+ if (misc_register(&lis3->miscdev))
pr_err("misc_register failed\n");
out:
return 0;
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.h b/drivers/misc/lis3lv02d/lis3lv02d.h
index a1939589eb2c..2b1482ad3f16 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d.h
+++ b/drivers/misc/lis3lv02d/lis3lv02d.h
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/input-polldev.h>
#include <linux/regulator/consumer.h>
+#include <linux/miscdevice.h>
/*
* This driver tries to support the "digital" accelerometer chips from
@@ -273,6 +274,8 @@ struct lis3lv02d {
struct fasync_struct *async_queue; /* queue for the misc device */
wait_queue_head_t misc_wait; /* Wait queue for the misc device */
unsigned long misc_opened; /* bit0: whether the device is open */
+ struct miscdevice miscdev;
+
int data_ready_count[2];
atomic_t wake_thread;
unsigned char irq_cfg;
@@ -282,10 +285,10 @@ struct lis3lv02d {
};
int lis3lv02d_init_device(struct lis3lv02d *lis3);
-int lis3lv02d_joystick_enable(void);
-void lis3lv02d_joystick_disable(void);
+int lis3lv02d_joystick_enable(struct lis3lv02d *lis3);
+void lis3lv02d_joystick_disable(struct lis3lv02d *lis3);
void lis3lv02d_poweroff(struct lis3lv02d *lis3);
-void lis3lv02d_poweron(struct lis3lv02d *lis3);
+int lis3lv02d_poweron(struct lis3lv02d *lis3);
int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
extern struct lis3lv02d lis3_dev;
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
index b20dfb4522d2..c02fea029dcf 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
@@ -79,8 +79,7 @@ static int lis3_i2c_init(struct lis3lv02d *lis3)
u8 reg;
int ret;
- if (lis3->reg_ctrl)
- lis3_reg_ctrl(lis3, LIS3_REG_ON);
+ lis3_reg_ctrl(lis3, LIS3_REG_ON);
lis3->read(lis3, WHO_AM_I, &reg);
if (reg != lis3->whoami)
@@ -106,10 +105,6 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
if (pdata) {
- /* Regulator control is optional */
- if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
- lis3_dev.reg_ctrl = lis3_reg_ctrl;
-
if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
(i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_I2C_BLOCK)))
@@ -131,15 +126,13 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
goto fail;
}
- if (lis3_dev.reg_ctrl) {
- lis3_dev.regulators[0].supply = reg_vdd;
- lis3_dev.regulators[1].supply = reg_vdd_io;
- ret = regulator_bulk_get(&client->dev,
- ARRAY_SIZE(lis3_dev.regulators),
- lis3_dev.regulators);
- if (ret < 0)
- goto fail;
- }
+ lis3_dev.regulators[0].supply = reg_vdd;
+ lis3_dev.regulators[1].supply = reg_vdd_io;
+ ret = regulator_bulk_get(&client->dev,
+ ARRAY_SIZE(lis3_dev.regulators),
+ lis3_dev.regulators);
+ if (ret < 0)
+ goto fail;
lis3_dev.pdata = pdata;
lis3_dev.bus_priv = client;
@@ -153,16 +146,19 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, &lis3_dev);
/* Provide power over the init call */
- if (lis3_dev.reg_ctrl)
- lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
+ lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
ret = lis3lv02d_init_device(&lis3_dev);
- if (lis3_dev.reg_ctrl)
- lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
+ lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
- if (ret == 0)
- return 0;
+ if (ret)
+ goto fail2;
+ return 0;
+
+fail2:
+ regulator_bulk_free(ARRAY_SIZE(lis3_dev.regulators),
+ lis3_dev.regulators);
fail:
if (pdata && pdata->release_resources)
pdata->release_resources();
@@ -177,12 +173,11 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
if (pdata && pdata->release_resources)
pdata->release_resources();
- lis3lv02d_joystick_disable();
+ lis3lv02d_joystick_disable(lis3);
lis3lv02d_remove_fs(&lis3_dev);
- if (lis3_dev.reg_ctrl)
- regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
- lis3_dev.regulators);
+ regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
+ lis3_dev.regulators);
return 0;
}
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
index c1f8a8fbf694..b2c1be12d16f 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
@@ -83,7 +83,7 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi)
static int __devexit lis302dl_spi_remove(struct spi_device *spi)
{
struct lis3lv02d *lis3 = spi_get_drvdata(spi);
- lis3lv02d_joystick_disable();
+ lis3lv02d_joystick_disable(lis3);
lis3lv02d_poweroff(lis3);
return lis3lv02d_remove_fs(&lis3_dev);
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
index 0fd7e77bee29..dee33addcaeb 100644
--- a/drivers/misc/pch_phub.c
+++ b/drivers/misc/pch_phub.c
@@ -90,6 +90,7 @@
#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C
#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040
#define CLKCFG_REG_OFFSET 0x500
+#define FUNCSEL_REG_OFFSET 0x508
#define PCH_PHUB_OROM_SIZE 15360
@@ -108,6 +109,7 @@
* @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val
* @int_reduce_control_reg: INT_REDUCE_CONTROL registers val
* @clkcfg_reg: CLK CFG register val
+ * @funcsel_reg: Function select register value
* @pch_phub_base_address: Register base address
* @pch_phub_extrom_base_address: external rom base address
* @pch_mac_start_address: MAC address area start address
@@ -128,6 +130,7 @@ struct pch_phub_reg {
u32 intpin_reg_wpermit_reg3;
u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
u32 clkcfg_reg;
+ u32 funcsel_reg;
void __iomem *pch_phub_base_address;
void __iomem *pch_phub_extrom_base_address;
u32 pch_mac_start_address;
@@ -211,6 +214,8 @@ static void pch_phub_save_reg_conf(struct pci_dev *pdev)
__func__, i, chip->int_reduce_control_reg[i]);
}
chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
+ if ((chip->ioh_type == 2) || (chip->ioh_type == 4))
+ chip->funcsel_reg = ioread32(p + FUNCSEL_REG_OFFSET);
}
/* pch_phub_restore_reg_conf - restore register configuration */
@@ -271,6 +276,8 @@ static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
}
iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET);
+ if ((chip->ioh_type == 2) || (chip->ioh_type == 4))
+ iowrite32(chip->funcsel_reg, p + FUNCSEL_REG_OFFSET);
}
/**
@@ -594,8 +601,7 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
pch_phub_read_gbe_mac_addr(chip, mac);
- return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ return sprintf(buf, "%pM\n", mac);
}
static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 053d36caf955..cd41d403c9df 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -151,7 +151,7 @@ MODULE_LICENSE("GPL");
struct vmballoon_stats {
unsigned int timer;
- /* allocation statustics */
+ /* allocation statistics */
unsigned int alloc;
unsigned int alloc_fail;
unsigned int sleep_alloc;
@@ -412,6 +412,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
gfp_t flags;
unsigned int hv_status;
bool locked = false;
+ flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;
do {
if (!can_sleep)
@@ -419,7 +420,6 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
else
STATS_INC(b->stats.sleep_alloc);
- flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;
page = alloc_page(flags);
if (!page) {
if (!can_sleep)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 4c1a648d00fc..a1cb21f95302 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -94,6 +94,11 @@ struct mmc_blk_data {
unsigned int read_only;
unsigned int part_type;
unsigned int name_idx;
+ unsigned int reset_done;
+#define MMC_BLK_READ BIT(0)
+#define MMC_BLK_WRITE BIT(1)
+#define MMC_BLK_DISCARD BIT(2)
+#define MMC_BLK_SECDISCARD BIT(3)
/*
* Only set in main mmc_blk_data associated
@@ -109,11 +114,11 @@ static DEFINE_MUTEX(open_lock);
enum mmc_blk_status {
MMC_BLK_SUCCESS = 0,
MMC_BLK_PARTIAL,
- MMC_BLK_RETRY,
- MMC_BLK_RETRY_SINGLE,
- MMC_BLK_DATA_ERR,
MMC_BLK_CMD_ERR,
+ MMC_BLK_RETRY,
MMC_BLK_ABORT,
+ MMC_BLK_DATA_ERR,
+ MMC_BLK_ECC_ERR,
};
module_param(perdev_minors, int, 0444);
@@ -291,7 +296,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
struct mmc_card *card;
struct mmc_command cmd = {0};
struct mmc_data data = {0};
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
struct scatterlist sg;
int err;
@@ -442,19 +447,24 @@ static inline int mmc_blk_part_switch(struct mmc_card *card,
{
int ret;
struct mmc_blk_data *main_md = mmc_get_drvdata(card);
+
if (main_md->part_curr == md->part_type)
return 0;
if (mmc_card_mmc(card)) {
- card->ext_csd.part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
- card->ext_csd.part_config |= md->part_type;
+ u8 part_config = card->ext_csd.part_config;
+
+ part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
+ part_config |= md->part_type;
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_PART_CONFIG, card->ext_csd.part_config,
+ EXT_CSD_PART_CONFIG, part_config,
card->ext_csd.part_time);
if (ret)
return ret;
-}
+
+ card->ext_csd.part_config = part_config;
+ }
main_md->part_curr = md->part_type;
return 0;
@@ -466,7 +476,7 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
u32 result;
__be32 *blocks;
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
unsigned int timeout_us;
@@ -616,7 +626,7 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
* Otherwise we don't understand what happened, so abort.
*/
static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
- struct mmc_blk_request *brq)
+ struct mmc_blk_request *brq, int *ecc_err)
{
bool prev_cmd_status_valid = true;
u32 status, stop_status = 0;
@@ -641,6 +651,12 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
if (err)
return ERR_ABORT;
+ /* Flag ECC errors */
+ if ((status & R1_CARD_ECC_FAILED) ||
+ (brq->stop.resp[0] & R1_CARD_ECC_FAILED) ||
+ (brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
+ *ecc_err = 1;
+
/*
* Check the current card state. If it is in some data transfer
* mode, tell it to stop (and hopefully transition back to TRAN.)
@@ -658,6 +674,8 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
*/
if (err)
return ERR_ABORT;
+ if (stop_status & R1_CARD_ECC_FAILED)
+ *ecc_err = 1;
}
/* Check for set block count errors */
@@ -670,6 +688,10 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
return mmc_blk_cmd_error(req, "r/w cmd", brq->cmd.error,
prev_cmd_status_valid, status);
+ /* Data errors */
+ if (!brq->stop.error)
+ return ERR_CONTINUE;
+
/* Now for stop errors. These aren't fatal to the transfer. */
pr_err("%s: error %d sending stop command, original cmd response %#x, card status %#x\n",
req->rq_disk->disk_name, brq->stop.error,
@@ -686,12 +708,45 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
return ERR_CONTINUE;
}
+static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
+ int type)
+{
+ int err;
+
+ if (md->reset_done & type)
+ return -EEXIST;
+
+ md->reset_done |= type;
+ err = mmc_hw_reset(host);
+ /* Ensure we switch back to the correct partition */
+ if (err != -EOPNOTSUPP) {
+ struct mmc_blk_data *main_md = mmc_get_drvdata(host->card);
+ int part_err;
+
+ main_md->part_curr = main_md->part_type;
+ part_err = mmc_blk_part_switch(host->card, md);
+ if (part_err) {
+ /*
+ * We have failed to get back into the correct
+ * partition, so we need to abort the whole request.
+ */
+ return -ENODEV;
+ }
+ }
+ return err;
+}
+
+static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
+{
+ md->reset_done &= ~type;
+}
+
static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
{
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
unsigned int from, nr, arg;
- int err = 0;
+ int err = 0, type = MMC_BLK_DISCARD;
if (!mmc_can_erase(card)) {
err = -EOPNOTSUPP;
@@ -701,11 +756,13 @@ static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
from = blk_rq_pos(req);
nr = blk_rq_sectors(req);
- if (mmc_can_trim(card))
+ if (mmc_can_discard(card))
+ arg = MMC_DISCARD_ARG;
+ else if (mmc_can_trim(card))
arg = MMC_TRIM_ARG;
else
arg = MMC_ERASE_ARG;
-
+retry:
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
INAND_CMD38_ARG_EXT_CSD,
@@ -718,6 +775,10 @@ static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
}
err = mmc_erase(card, from, nr, arg);
out:
+ if (err == -EIO && !mmc_blk_reset(md, card->host, type))
+ goto retry;
+ if (!err)
+ mmc_blk_reset_success(md, type);
spin_lock_irq(&md->lock);
__blk_end_request(req, err, blk_rq_bytes(req));
spin_unlock_irq(&md->lock);
@@ -731,13 +792,20 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
unsigned int from, nr, arg;
- int err = 0;
+ int err = 0, type = MMC_BLK_SECDISCARD;
- if (!mmc_can_secure_erase_trim(card)) {
+ if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) {
err = -EOPNOTSUPP;
goto out;
}
+ /* The sanitize operation is supported at v4.5 only */
+ if (mmc_can_sanitize(card)) {
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_SANITIZE_START, 1, 0);
+ goto out;
+ }
+
from = blk_rq_pos(req);
nr = blk_rq_sectors(req);
@@ -745,7 +813,7 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
arg = MMC_SECURE_TRIM1_ARG;
else
arg = MMC_SECURE_ERASE_ARG;
-
+retry:
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
INAND_CMD38_ARG_EXT_CSD,
@@ -769,6 +837,10 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
}
out:
+ if (err == -EIO && !mmc_blk_reset(md, card->host, type))
+ goto retry;
+ if (!err)
+ mmc_blk_reset_success(md, type);
spin_lock_irq(&md->lock);
__blk_end_request(req, err, blk_rq_bytes(req));
spin_unlock_irq(&md->lock);
@@ -779,16 +851,18 @@ out:
static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
{
struct mmc_blk_data *md = mq->data;
+ struct mmc_card *card = md->queue.card;
+ int ret = 0;
+
+ ret = mmc_flush_cache(card);
+ if (ret)
+ ret = -EIO;
- /*
- * No-op, only service this because we need REQ_FUA for reliable
- * writes.
- */
spin_lock_irq(&md->lock);
- __blk_end_request_all(req, 0);
+ __blk_end_request_all(req, ret);
spin_unlock_irq(&md->lock);
- return 1;
+ return ret ? 0 : 1;
}
/*
@@ -825,11 +899,11 @@ static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
static int mmc_blk_err_check(struct mmc_card *card,
struct mmc_async_req *areq)
{
- enum mmc_blk_status ret = MMC_BLK_SUCCESS;
struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req,
mmc_active);
struct mmc_blk_request *brq = &mq_mrq->brq;
struct request *req = mq_mrq->req;
+ int ecc_err = 0;
/*
* sbc.error indicates a problem with the set block count
@@ -841,8 +915,9 @@ static int mmc_blk_err_check(struct mmc_card *card,
* stop.error indicates a problem with the stop command. Data
* may have been transferred, or may still be transferring.
*/
- if (brq->sbc.error || brq->cmd.error || brq->stop.error) {
- switch (mmc_blk_cmd_recovery(card, req, brq)) {
+ if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
+ brq->data.error) {
+ switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) {
case ERR_RETRY:
return MMC_BLK_RETRY;
case ERR_ABORT:
@@ -873,7 +948,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
do {
int err = get_card_status(card, &status, 5);
if (err) {
- printk(KERN_ERR "%s: error %d requesting status\n",
+ pr_err("%s: error %d requesting status\n",
req->rq_disk->disk_name, err);
return MMC_BLK_CMD_ERR;
}
@@ -894,23 +969,21 @@ static int mmc_blk_err_check(struct mmc_card *card,
brq->cmd.resp[0], brq->stop.resp[0]);
if (rq_data_dir(req) == READ) {
- if (brq->data.blocks > 1) {
- /* Redo read one sector at a time */
- pr_warning("%s: retrying using single block read\n",
- req->rq_disk->disk_name);
- return MMC_BLK_RETRY_SINGLE;
- }
+ if (ecc_err)
+ return MMC_BLK_ECC_ERR;
return MMC_BLK_DATA_ERR;
} else {
return MMC_BLK_CMD_ERR;
}
}
- if (ret == MMC_BLK_SUCCESS &&
- blk_rq_bytes(req) != brq->data.bytes_xfered)
- ret = MMC_BLK_PARTIAL;
+ if (!brq->data.bytes_xfered)
+ return MMC_BLK_RETRY;
- return ret;
+ if (blk_rq_bytes(req) != brq->data.bytes_xfered)
+ return MMC_BLK_PARTIAL;
+
+ return MMC_BLK_SUCCESS;
}
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
@@ -957,13 +1030,20 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
if (brq->data.blocks > card->host->max_blk_count)
brq->data.blocks = card->host->max_blk_count;
- /*
- * After a read error, we redo the request one sector at a time
- * in order to accurately determine which sectors can be read
- * successfully.
- */
- if (disable_multi && brq->data.blocks > 1)
- brq->data.blocks = 1;
+ if (brq->data.blocks > 1) {
+ /*
+ * After a read error, we redo the request one sector
+ * at a time in order to accurately determine which
+ * sectors can be read successfully.
+ */
+ if (disable_multi)
+ brq->data.blocks = 1;
+
+ /* Some controllers can't do multiblock reads due to hw bugs */
+ if (card->host->caps2 & MMC_CAP2_NO_MULTI_READ &&
+ rq_data_dir(req) == READ)
+ brq->data.blocks = 1;
+ }
if (brq->data.blocks > 1 || do_rel_wr) {
/* SPI multiblock writes terminate using a special
@@ -1049,12 +1129,41 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
mmc_queue_bounce_pre(mqrq);
}
+static int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
+ struct mmc_blk_request *brq, struct request *req,
+ int ret)
+{
+ /*
+ * If this is an SD card and we're writing, we can first
+ * mark the known good sectors as ok.
+ *
+ * If the card is not SD, we can still ok written sectors
+ * as reported by the controller (which might be less than
+ * the real number of written sectors, but never more).
+ */
+ if (mmc_card_sd(card)) {
+ u32 blocks;
+
+ blocks = mmc_sd_num_wr_blocks(card);
+ if (blocks != (u32)-1) {
+ spin_lock_irq(&md->lock);
+ ret = __blk_end_request(req, 0, blocks << 9);
+ spin_unlock_irq(&md->lock);
+ }
+ } else {
+ spin_lock_irq(&md->lock);
+ ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
+ spin_unlock_irq(&md->lock);
+ }
+ return ret;
+}
+
static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
{
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
struct mmc_blk_request *brq = &mq->mqrq_cur->brq;
- int ret = 1, disable_multi = 0, retry = 0;
+ int ret = 1, disable_multi = 0, retry = 0, type;
enum mmc_blk_status status;
struct mmc_queue_req *mq_rq;
struct request *req;
@@ -1076,6 +1185,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
mq_rq = container_of(areq, struct mmc_queue_req, mmc_active);
brq = &mq_rq->brq;
req = mq_rq->req;
+ type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
mmc_queue_bounce_post(mq_rq);
switch (status) {
@@ -1084,18 +1194,18 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
/*
* A block was successfully transferred.
*/
+ mmc_blk_reset_success(md, type);
spin_lock_irq(&md->lock);
ret = __blk_end_request(req, 0,
brq->data.bytes_xfered);
spin_unlock_irq(&md->lock);
+ /*
+ * If the blk_end_request function returns non-zero even
+ * though all data has been transferred and no errors
+ * were returned by the host controller, it's a bug.
+ */
if (status == MMC_BLK_SUCCESS && ret) {
- /*
- * The blk_end_request has returned non zero
- * even though all data is transfered and no
- * erros returned by host.
- * If this happen it's a bug.
- */
- printk(KERN_ERR "%s BUG rq_tot %d d_xfer %d\n",
+ pr_err("%s BUG rq_tot %d d_xfer %d\n",
__func__, blk_rq_bytes(req),
brq->data.bytes_xfered);
rqc = NULL;
@@ -1103,16 +1213,36 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
}
break;
case MMC_BLK_CMD_ERR:
- goto cmd_err;
- case MMC_BLK_RETRY_SINGLE:
- disable_multi = 1;
- break;
+ ret = mmc_blk_cmd_err(md, card, brq, req, ret);
+ if (!mmc_blk_reset(md, card->host, type))
+ break;
+ goto cmd_abort;
case MMC_BLK_RETRY:
if (retry++ < 5)
break;
+ /* Fall through */
case MMC_BLK_ABORT:
+ if (!mmc_blk_reset(md, card->host, type))
+ break;
goto cmd_abort;
- case MMC_BLK_DATA_ERR:
+ case MMC_BLK_DATA_ERR: {
+ int err;
+
+ err = mmc_blk_reset(md, card->host, type);
+ if (!err)
+ break;
+ if (err == -ENODEV)
+ goto cmd_abort;
+ /* Fall through */
+ }
+ case MMC_BLK_ECC_ERR:
+ if (brq->data.blocks > 1) {
+ /* Redo read one sector at a time */
+ pr_warning("%s: retrying using single block read\n",
+ req->rq_disk->disk_name);
+ disable_multi = 1;
+ break;
+ }
/*
* After an error, we redo I/O one sector at a
* time, so we only reach here after trying to
@@ -1129,7 +1259,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
if (ret) {
/*
- * In case of a none complete request
+ * In case of a incomplete request
* prepare it again and resend.
*/
mmc_blk_rw_rq_prep(mq_rq, card, disable_multi, mq);
@@ -1139,30 +1269,6 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
return 1;
- cmd_err:
- /*
- * If this is an SD card and we're writing, we can first
- * mark the known good sectors as ok.
- *
- * If the card is not SD, we can still ok written sectors
- * as reported by the controller (which might be less than
- * the real number of written sectors, but never more).
- */
- if (mmc_card_sd(card)) {
- u32 blocks;
-
- blocks = mmc_sd_num_wr_blocks(card);
- if (blocks != (u32)-1) {
- spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, 0, blocks << 9);
- spin_unlock_irq(&md->lock);
- }
- } else {
- spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
- spin_unlock_irq(&md->lock);
- }
-
cmd_abort:
spin_lock_irq(&md->lock);
while (ret)
@@ -1190,6 +1296,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
ret = mmc_blk_part_switch(card, md);
if (ret) {
+ if (req) {
+ spin_lock_irq(&md->lock);
+ __blk_end_request_all(req, -EIO);
+ spin_unlock_irq(&md->lock);
+ }
ret = 0;
goto out;
}
@@ -1374,32 +1485,35 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2,
cap_str, sizeof(cap_str));
- printk(KERN_INFO "%s: %s %s partition %u %s\n",
+ pr_info("%s: %s %s partition %u %s\n",
part_md->disk->disk_name, mmc_card_id(card),
mmc_card_name(card), part_md->part_type, cap_str);
return 0;
}
+/* MMC Physical partitions consist of two boot partitions and
+ * up to four general purpose partitions.
+ * For each partition enabled in EXT_CSD a block device will be allocatedi
+ * to provide access to the partition.
+ */
+
static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
{
- int ret = 0;
+ int idx, ret = 0;
if (!mmc_card_mmc(card))
return 0;
- if (card->ext_csd.boot_size) {
- ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT0,
- card->ext_csd.boot_size >> 9,
- true,
- "boot0");
- if (ret)
- return ret;
- ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT1,
- card->ext_csd.boot_size >> 9,
- true,
- "boot1");
- if (ret)
- return ret;
+ for (idx = 0; idx < card->nr_parts; idx++) {
+ if (card->part[idx].size) {
+ ret = mmc_blk_alloc_part(card, md,
+ card->part[idx].part_cfg,
+ card->part[idx].size >> 9,
+ card->part[idx].force_ro,
+ card->part[idx].name);
+ if (ret)
+ return ret;
+ }
}
return ret;
@@ -1415,7 +1529,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
mmc_release_host(card->host);
if (err) {
- printk(KERN_ERR "%s: unable to set block size to 512: %d\n",
+ pr_err("%s: unable to set block size to 512: %d\n",
md->disk->disk_name, err);
return -EINVAL;
}
@@ -1517,7 +1631,7 @@ static int mmc_blk_probe(struct mmc_card *card)
string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
cap_str, sizeof(cap_str));
- printk(KERN_INFO "%s: %s %s %s %s\n",
+ pr_info("%s: %s %s %s %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
cap_str, md->read_only ? "(ro)" : "");
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 2bf229acd3b8..b038c4a9468b 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -22,6 +22,7 @@
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#define RESULT_OK 0
#define RESULT_FAIL 1
@@ -250,7 +251,7 @@ static int mmc_test_wait_busy(struct mmc_test_card *test)
if (!busy && mmc_test_busy(&cmd)) {
busy = 1;
if (test->card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
- printk(KERN_INFO "%s: Warning: Host did not "
+ pr_info("%s: Warning: Host did not "
"wait for busy state to end.\n",
mmc_hostname(test->card->host));
}
@@ -552,7 +553,7 @@ static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes,
rate = mmc_test_rate(bytes, &ts);
iops = mmc_test_rate(100, &ts); /* I/O ops per sec x 100 */
- printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu "
+ pr_info("%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu "
"seconds (%u kB/s, %u KiB/s, %u.%02u IOPS)\n",
mmc_hostname(test->card->host), sectors, sectors >> 1,
(sectors & 1 ? ".5" : ""), (unsigned long)ts.tv_sec,
@@ -578,7 +579,7 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
rate = mmc_test_rate(tot, &ts);
iops = mmc_test_rate(count * 100, &ts); /* I/O ops per sec x 100 */
- printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took "
+ pr_info("%s: Transfer of %u x %u sectors (%u x %u%s KiB) took "
"%lu.%09lu seconds (%u kB/s, %u KiB/s, "
"%u.%02u IOPS, sg_len %d)\n",
mmc_hostname(test->card->host), count, sectors, count,
@@ -1408,7 +1409,7 @@ static int mmc_test_multi_read_high(struct mmc_test_card *test)
static int mmc_test_no_highmem(struct mmc_test_card *test)
{
- printk(KERN_INFO "%s: Highmem not configured - test skipped\n",
+ pr_info("%s: Highmem not configured - test skipped\n",
mmc_hostname(test->card->host));
return 0;
}
@@ -1435,7 +1436,7 @@ static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz,
t->max_seg_sz, &t->sg_len, min_sg_len);
}
if (err)
- printk(KERN_INFO "%s: Failed to map sg list\n",
+ pr_info("%s: Failed to map sg list\n",
mmc_hostname(test->card->host));
return err;
}
@@ -2135,7 +2136,7 @@ static int mmc_test_rw_multiple(struct mmc_test_card *test,
return ret;
err:
- printk(KERN_INFO "[%s] error\n", __func__);
+ pr_info("[%s] error\n", __func__);
return ret;
}
@@ -2149,7 +2150,7 @@ static int mmc_test_rw_multiple_size(struct mmc_test_card *test,
if (rw->do_nonblock_req &&
((!pre_req && post_req) || (pre_req && !post_req))) {
- printk(KERN_INFO "error: only one of pre/post is defined\n");
+ pr_info("error: only one of pre/post is defined\n");
return -EINVAL;
}
@@ -2328,6 +2329,31 @@ static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
return mmc_test_rw_multiple_sg_len(test, &test_data);
}
+/*
+ * eMMC hardware reset.
+ */
+static int mmc_test_hw_reset(struct mmc_test_card *test)
+{
+ struct mmc_card *card = test->card;
+ struct mmc_host *host = card->host;
+ int err;
+
+ err = mmc_hw_reset_check(host);
+ if (!err)
+ return RESULT_OK;
+
+ if (err == -ENOSYS)
+ return RESULT_FAIL;
+
+ if (err != -EOPNOTSUPP)
+ return err;
+
+ if (!mmc_can_reset(card))
+ return RESULT_UNSUP_CARD;
+
+ return RESULT_UNSUP_HOST;
+}
+
static const struct mmc_test_case mmc_test_cases[] = {
{
.name = "Basic write (no data verification)",
@@ -2650,6 +2676,11 @@ static const struct mmc_test_case mmc_test_cases[] = {
.run = mmc_test_profile_sglen_r_nonblock_perf,
.cleanup = mmc_test_area_cleanup,
},
+
+ {
+ .name = "eMMC hardware reset",
+ .run = mmc_test_hw_reset,
+ },
};
static DEFINE_MUTEX(mmc_test_lock);
@@ -2660,7 +2691,7 @@ static void mmc_test_run(struct mmc_test_card *test, int testcase)
{
int i, ret;
- printk(KERN_INFO "%s: Starting tests of card %s...\n",
+ pr_info("%s: Starting tests of card %s...\n",
mmc_hostname(test->card->host), mmc_card_id(test->card));
mmc_claim_host(test->card->host);
@@ -2671,14 +2702,14 @@ static void mmc_test_run(struct mmc_test_card *test, int testcase)
if (testcase && ((i + 1) != testcase))
continue;
- printk(KERN_INFO "%s: Test case %d. %s...\n",
+ pr_info("%s: Test case %d. %s...\n",
mmc_hostname(test->card->host), i + 1,
mmc_test_cases[i].name);
if (mmc_test_cases[i].prepare) {
ret = mmc_test_cases[i].prepare(test);
if (ret) {
- printk(KERN_INFO "%s: Result: Prepare "
+ pr_info("%s: Result: Prepare "
"stage failed! (%d)\n",
mmc_hostname(test->card->host),
ret);
@@ -2708,25 +2739,25 @@ static void mmc_test_run(struct mmc_test_card *test, int testcase)
ret = mmc_test_cases[i].run(test);
switch (ret) {
case RESULT_OK:
- printk(KERN_INFO "%s: Result: OK\n",
+ pr_info("%s: Result: OK\n",
mmc_hostname(test->card->host));
break;
case RESULT_FAIL:
- printk(KERN_INFO "%s: Result: FAILED\n",
+ pr_info("%s: Result: FAILED\n",
mmc_hostname(test->card->host));
break;
case RESULT_UNSUP_HOST:
- printk(KERN_INFO "%s: Result: UNSUPPORTED "
+ pr_info("%s: Result: UNSUPPORTED "
"(by host)\n",
mmc_hostname(test->card->host));
break;
case RESULT_UNSUP_CARD:
- printk(KERN_INFO "%s: Result: UNSUPPORTED "
+ pr_info("%s: Result: UNSUPPORTED "
"(by card)\n",
mmc_hostname(test->card->host));
break;
default:
- printk(KERN_INFO "%s: Result: ERROR (%d)\n",
+ pr_info("%s: Result: ERROR (%d)\n",
mmc_hostname(test->card->host), ret);
}
@@ -2737,7 +2768,7 @@ static void mmc_test_run(struct mmc_test_card *test, int testcase)
if (mmc_test_cases[i].cleanup) {
ret = mmc_test_cases[i].cleanup(test);
if (ret) {
- printk(KERN_INFO "%s: Warning: Cleanup "
+ pr_info("%s: Warning: Cleanup "
"stage failed! (%d)\n",
mmc_hostname(test->card->host),
ret);
@@ -2747,7 +2778,7 @@ static void mmc_test_run(struct mmc_test_card *test, int testcase)
mmc_release_host(test->card->host);
- printk(KERN_INFO "%s: Tests completed.\n",
+ pr_info("%s: Tests completed.\n",
mmc_hostname(test->card->host));
}
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 45fb362e3f01..dcad59cbfef1 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -108,7 +108,7 @@ static void mmc_request(struct request_queue *q)
wake_up_process(mq->thread);
}
-struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
+static struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
{
struct scatterlist *sg;
@@ -140,7 +140,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,
/* granularity must not be greater than max. discard */
if (card->pref_erase > max_discard)
q->limits.discard_granularity = 0;
- if (mmc_can_secure_erase_trim(card))
+ if (mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))
queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q);
}
@@ -197,13 +197,13 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
if (bouncesz > 512) {
mqrq_cur->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
if (!mqrq_cur->bounce_buf) {
- printk(KERN_WARNING "%s: unable to "
+ pr_warning("%s: unable to "
"allocate bounce cur buffer\n",
mmc_card_name(card));
}
mqrq_prev->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
if (!mqrq_prev->bounce_buf) {
- printk(KERN_WARNING "%s: unable to "
+ pr_warning("%s: unable to "
"allocate bounce prev buffer\n",
mmc_card_name(card));
kfree(mqrq_cur->bounce_buf);
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index c8c9edb3d7cb..2c151e18c9e8 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -1082,7 +1082,7 @@ static int sdio_uart_probe(struct sdio_func *func,
return -ENOMEM;
if (func->class == SDIO_CLASS_UART) {
- printk(KERN_WARNING "%s: need info on UART class basic setup\n",
+ pr_warning("%s: need info on UART class basic setup\n",
sdio_func_id(func));
kfree(port);
return -ENOSYS;
@@ -1101,23 +1101,23 @@ static int sdio_uart_probe(struct sdio_func *func,
break;
}
if (!tpl) {
- printk(KERN_WARNING
+ pr_warning(
"%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n",
sdio_func_id(func));
kfree(port);
return -EINVAL;
}
- printk(KERN_DEBUG "%s: Register ID = 0x%02x, Exp ID = 0x%02x\n",
+ pr_debug("%s: Register ID = 0x%02x, Exp ID = 0x%02x\n",
sdio_func_id(func), tpl->data[2], tpl->data[3]);
port->regs_offset = (tpl->data[4] << 0) |
(tpl->data[5] << 8) |
(tpl->data[6] << 16);
- printk(KERN_DEBUG "%s: regs offset = 0x%x\n",
+ pr_debug("%s: regs offset = 0x%x\n",
sdio_func_id(func), port->regs_offset);
port->uartclk = tpl->data[7] * 115200;
if (port->uartclk == 0)
port->uartclk = 115200;
- printk(KERN_DEBUG "%s: clk %d baudcode %u 4800-div %u\n",
+ pr_debug("%s: clk %d baudcode %u 4800-div %u\n",
sdio_func_id(func), port->uartclk,
tpl->data[7], tpl->data[8] | (tpl->data[9] << 8));
} else {
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 393d817ed040..46b6e84d953e 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -295,7 +295,7 @@ int mmc_add_card(struct mmc_card *card)
}
if (mmc_host_is_spi(card->host)) {
- printk(KERN_INFO "%s: new %s%s%s card on SPI\n",
+ pr_info("%s: new %s%s%s card on SPI\n",
mmc_hostname(card->host),
mmc_card_highspeed(card) ? "high speed " : "",
mmc_card_ddr_mode(card) ? "DDR " : "",
@@ -334,10 +334,10 @@ void mmc_remove_card(struct mmc_card *card)
if (mmc_card_present(card)) {
if (mmc_host_is_spi(card->host)) {
- printk(KERN_INFO "%s: SPI card removed\n",
+ pr_info("%s: SPI card removed\n",
mmc_hostname(card->host));
} else {
- printk(KERN_INFO "%s: card %04x removed\n",
+ pr_info("%s: card %04x removed\n",
mmc_hostname(card->host), card->rca);
}
device_del(&card->dev);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b27b94078c21..5278ffb20e74 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -24,6 +24,8 @@
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
+#include <linux/fault-inject.h>
+#include <linux/random.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -83,6 +85,43 @@ static void mmc_flush_scheduled_work(void)
flush_workqueue(workqueue);
}
+#ifdef CONFIG_FAIL_MMC_REQUEST
+
+/*
+ * Internal function. Inject random data errors.
+ * If mmc_data is NULL no errors are injected.
+ */
+static void mmc_should_fail_request(struct mmc_host *host,
+ struct mmc_request *mrq)
+{
+ struct mmc_command *cmd = mrq->cmd;
+ struct mmc_data *data = mrq->data;
+ static const int data_errors[] = {
+ -ETIMEDOUT,
+ -EILSEQ,
+ -EIO,
+ };
+
+ if (!data)
+ return;
+
+ if (cmd->error || data->error ||
+ !should_fail(&host->fail_mmc_request, data->blksz * data->blocks))
+ return;
+
+ data->error = data_errors[random32() % ARRAY_SIZE(data_errors)];
+ data->bytes_xfered = (random32() % (data->bytes_xfered >> 9)) << 9;
+}
+
+#else /* CONFIG_FAIL_MMC_REQUEST */
+
+static inline void mmc_should_fail_request(struct mmc_host *host,
+ struct mmc_request *mrq)
+{
+}
+
+#endif /* CONFIG_FAIL_MMC_REQUEST */
+
/**
* mmc_request_done - finish processing an MMC request
* @host: MMC host which completed request
@@ -102,13 +141,15 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
}
if (err && cmd->retries) {
- pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
- mmc_hostname(host), cmd->opcode, err);
-
- cmd->retries--;
- cmd->error = 0;
- host->ops->request(host, mrq);
+ /*
+ * Request starter must handle retries - see
+ * mmc_wait_for_req_done().
+ */
+ if (mrq->done)
+ mrq->done(mrq);
} else {
+ mmc_should_fail_request(host, mrq);
+
led_trigger_event(host->led, LED_OFF);
pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
@@ -212,7 +253,21 @@ static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
static void mmc_wait_for_req_done(struct mmc_host *host,
struct mmc_request *mrq)
{
- wait_for_completion(&mrq->completion);
+ struct mmc_command *cmd;
+
+ while (1) {
+ wait_for_completion(&mrq->completion);
+
+ cmd = mrq->cmd;
+ if (!cmd->error || !cmd->retries)
+ break;
+
+ pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
+ mmc_hostname(host), cmd->opcode, cmd->error);
+ cmd->retries--;
+ cmd->error = 0;
+ host->ops->request(host, mrq);
+ }
}
/**
@@ -279,8 +334,14 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
mmc_wait_for_req_done(host, host->areq->mrq);
err = host->areq->err_check(host->card, host->areq);
if (err) {
+ /* post process the completed failed request */
mmc_post_req(host, host->areq->mrq, 0);
if (areq)
+ /*
+ * Cancel the new prepared request, because
+ * it can't run until the failed
+ * request has been properly handled.
+ */
mmc_post_req(host, areq->mrq, -EINVAL);
host->areq = NULL;
@@ -319,6 +380,63 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
EXPORT_SYMBOL(mmc_wait_for_req);
/**
+ * mmc_interrupt_hpi - Issue for High priority Interrupt
+ * @card: the MMC card associated with the HPI transfer
+ *
+ * Issued High Priority Interrupt, and check for card status
+ * util out-of prg-state.
+ */
+int mmc_interrupt_hpi(struct mmc_card *card)
+{
+ int err;
+ u32 status;
+
+ BUG_ON(!card);
+
+ if (!card->ext_csd.hpi_en) {
+ pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host));
+ return 1;
+ }
+
+ mmc_claim_host(card->host);
+ err = mmc_send_status(card, &status);
+ if (err) {
+ pr_err("%s: Get card status fail\n", mmc_hostname(card->host));
+ goto out;
+ }
+
+ /*
+ * If the card status is in PRG-state, we can send the HPI command.
+ */
+ if (R1_CURRENT_STATE(status) == R1_STATE_PRG) {
+ do {
+ /*
+ * We don't know when the HPI command will finish
+ * processing, so we need to resend HPI until out
+ * of prg-state, and keep checking the card status
+ * with SEND_STATUS. If a timeout error occurs when
+ * sending the HPI command, we are already out of
+ * prg-state.
+ */
+ err = mmc_send_hpi_cmd(card, &status);
+ if (err)
+ pr_debug("%s: abort HPI (%d error)\n",
+ mmc_hostname(card->host), err);
+
+ err = mmc_send_status(card, &status);
+ if (err)
+ break;
+ } while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
+ } else
+ pr_debug("%s: Left prg-state\n", mmc_hostname(card->host));
+
+out:
+ mmc_release_host(card->host);
+ return err;
+}
+EXPORT_SYMBOL(mmc_interrupt_hpi);
+
+/**
* mmc_wait_for_cmd - start a command and wait for completion
* @host: MMC host to start command
* @cmd: MMC command to start
@@ -330,7 +448,7 @@ EXPORT_SYMBOL(mmc_wait_for_req);
*/
int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
{
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
WARN_ON(!host->claimed);
@@ -1119,13 +1237,11 @@ static void mmc_power_up(struct mmc_host *host)
bit = fls(host->ocr_avail) - 1;
host->ios.vdd = bit;
- if (mmc_host_is_spi(host)) {
+ if (mmc_host_is_spi(host))
host->ios.chip_select = MMC_CS_HIGH;
- host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
- } else {
+ else
host->ios.chip_select = MMC_CS_DONTCARE;
- host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
- }
+ host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
host->ios.power_mode = MMC_POWER_UP;
host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ios.timing = MMC_TIMING_LEGACY;
@@ -1151,13 +1267,45 @@ static void mmc_power_up(struct mmc_host *host)
mmc_host_clk_release(host);
}
-static void mmc_power_off(struct mmc_host *host)
+void mmc_power_off(struct mmc_host *host)
{
+ struct mmc_card *card;
+ unsigned int notify_type;
+ unsigned int timeout;
+ int err;
+
mmc_host_clk_hold(host);
+ card = host->card;
host->ios.clock = 0;
host->ios.vdd = 0;
+ if (card && mmc_card_mmc(card) &&
+ (card->poweroff_notify_state == MMC_POWERED_ON)) {
+
+ if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
+ notify_type = EXT_CSD_POWER_OFF_SHORT;
+ timeout = card->ext_csd.generic_cmd6_time;
+ card->poweroff_notify_state = MMC_POWEROFF_SHORT;
+ } else {
+ notify_type = EXT_CSD_POWER_OFF_LONG;
+ timeout = card->ext_csd.power_off_longtime;
+ card->poweroff_notify_state = MMC_POWEROFF_LONG;
+ }
+
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_POWER_OFF_NOTIFICATION,
+ notify_type, timeout);
+
+ if (err && err != -EBADMSG)
+ pr_err("Device failed to respond within %d poweroff "
+ "time. Forcefully powering down the device\n",
+ timeout);
+
+ /* Set the card state to no notification after the poweroff */
+ card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
+ }
+
/*
* Reset ocr mask to be the highest possible voltage supported for
* this mmc host. This value will be used at next power up.
@@ -1173,6 +1321,13 @@ static void mmc_power_off(struct mmc_host *host)
host->ios.timing = MMC_TIMING_LEGACY;
mmc_set_ios(host);
+ /*
+ * Some configurations, such as the 802.11 SDIO card in the OLPC
+ * XO-1.5, require a short delay after poweroff before the card
+ * can be successfully turned on again.
+ */
+ mmc_delay(1);
+
mmc_host_clk_release(host);
}
@@ -1241,8 +1396,7 @@ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
}
/*
- * Remove the current bus handler from a host. Assumes that there are
- * no interesting cards left, so the bus is powered down.
+ * Remove the current bus handler from a host.
*/
void mmc_detach_bus(struct mmc_host *host)
{
@@ -1259,8 +1413,6 @@ void mmc_detach_bus(struct mmc_host *host)
spin_unlock_irqrestore(&host->lock, flags);
- mmc_power_off(host);
-
mmc_bus_put(host);
}
@@ -1478,9 +1630,9 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
- printk(KERN_ERR "mmc_erase: group start error %d, "
+ pr_err("mmc_erase: group start error %d, "
"status %#x\n", err, cmd.resp[0]);
- err = -EINVAL;
+ err = -EIO;
goto out;
}
@@ -1493,9 +1645,9 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
- printk(KERN_ERR "mmc_erase: group end error %d, status %#x\n",
+ pr_err("mmc_erase: group end error %d, status %#x\n",
err, cmd.resp[0]);
- err = -EINVAL;
+ err = -EIO;
goto out;
}
@@ -1506,7 +1658,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
cmd.cmd_timeout_ms = mmc_erase_timeout(card, arg, qty);
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
- printk(KERN_ERR "mmc_erase: erase error %d, status %#x\n",
+ pr_err("mmc_erase: erase error %d, status %#x\n",
err, cmd.resp[0]);
err = -EIO;
goto out;
@@ -1523,7 +1675,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
/* Do not retry else we can't see errors */
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err || (cmd.resp[0] & 0xFDF92000)) {
- printk(KERN_ERR "error %d requesting status %#x\n",
+ pr_err("error %d requesting status %#x\n",
err, cmd.resp[0]);
err = -EIO;
goto out;
@@ -1614,10 +1766,32 @@ int mmc_can_trim(struct mmc_card *card)
{
if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)
return 1;
+ if (mmc_can_discard(card))
+ return 1;
return 0;
}
EXPORT_SYMBOL(mmc_can_trim);
+int mmc_can_discard(struct mmc_card *card)
+{
+ /*
+ * As there's no way to detect the discard support bit at v4.5
+ * use the s/w feature support filed.
+ */
+ if (card->ext_csd.feature_support & MMC_DISCARD_FEATURE)
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL(mmc_can_discard);
+
+int mmc_can_sanitize(struct mmc_card *card)
+{
+ if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE)
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL(mmc_can_sanitize);
+
int mmc_can_secure_erase_trim(struct mmc_card *card)
{
if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN)
@@ -1727,6 +1901,94 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
}
EXPORT_SYMBOL(mmc_set_blocklen);
+static void mmc_hw_reset_for_init(struct mmc_host *host)
+{
+ if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
+ return;
+ mmc_host_clk_hold(host);
+ host->ops->hw_reset(host);
+ mmc_host_clk_release(host);
+}
+
+int mmc_can_reset(struct mmc_card *card)
+{
+ u8 rst_n_function;
+
+ if (!mmc_card_mmc(card))
+ return 0;
+ rst_n_function = card->ext_csd.rst_n_function;
+ if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED)
+ return 0;
+ return 1;
+}
+EXPORT_SYMBOL(mmc_can_reset);
+
+static int mmc_do_hw_reset(struct mmc_host *host, int check)
+{
+ struct mmc_card *card = host->card;
+
+ if (!host->bus_ops->power_restore)
+ return -EOPNOTSUPP;
+
+ if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
+ return -EOPNOTSUPP;
+
+ if (!card)
+ return -EINVAL;
+
+ if (!mmc_can_reset(card))
+ return -EOPNOTSUPP;
+
+ mmc_host_clk_hold(host);
+ mmc_set_clock(host, host->f_init);
+
+ host->ops->hw_reset(host);
+
+ /* If the reset has happened, then a status command will fail */
+ if (check) {
+ struct mmc_command cmd = {0};
+ int err;
+
+ cmd.opcode = MMC_SEND_STATUS;
+ if (!mmc_host_is_spi(card->host))
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
+ err = mmc_wait_for_cmd(card->host, &cmd, 0);
+ if (!err) {
+ mmc_host_clk_release(host);
+ return -ENOSYS;
+ }
+ }
+
+ host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
+ if (mmc_host_is_spi(host)) {
+ host->ios.chip_select = MMC_CS_HIGH;
+ host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
+ } else {
+ host->ios.chip_select = MMC_CS_DONTCARE;
+ host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+ }
+ host->ios.bus_width = MMC_BUS_WIDTH_1;
+ host->ios.timing = MMC_TIMING_LEGACY;
+ mmc_set_ios(host);
+
+ mmc_host_clk_release(host);
+
+ return host->bus_ops->power_restore(host);
+}
+
+int mmc_hw_reset(struct mmc_host *host)
+{
+ return mmc_do_hw_reset(host, 0);
+}
+EXPORT_SYMBOL(mmc_hw_reset);
+
+int mmc_hw_reset_check(struct mmc_host *host)
+{
+ return mmc_do_hw_reset(host, 1);
+}
+EXPORT_SYMBOL(mmc_hw_reset_check);
+
static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
{
host->f_init = freq;
@@ -1738,6 +2000,12 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
mmc_power_up(host);
/*
+ * Some eMMCs (with VCCQ always on) may not be reset after power up, so
+ * do a hardware reset if possible.
+ */
+ mmc_hw_reset_for_init(host);
+
+ /*
* sdio_reset sends CMD52 to reset card. Since we do not know
* if the card is being re-initialized, just send it. CMD52
* should be ignored by SD/eMMC cards.
@@ -1845,6 +2113,7 @@ void mmc_stop_host(struct mmc_host *host)
mmc_claim_host(host);
mmc_detach_bus(host);
+ mmc_power_off(host);
mmc_release_host(host);
mmc_bus_put(host);
return;
@@ -1946,6 +2215,65 @@ int mmc_card_can_sleep(struct mmc_host *host)
}
EXPORT_SYMBOL(mmc_card_can_sleep);
+/*
+ * Flush the cache to the non-volatile storage.
+ */
+int mmc_flush_cache(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ int err = 0;
+
+ if (!(host->caps2 & MMC_CAP2_CACHE_CTRL))
+ return err;
+
+ if (mmc_card_mmc(card) &&
+ (card->ext_csd.cache_size > 0) &&
+ (card->ext_csd.cache_ctrl & 1)) {
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_FLUSH_CACHE, 1, 0);
+ if (err)
+ pr_err("%s: cache flush error %d\n",
+ mmc_hostname(card->host), err);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(mmc_flush_cache);
+
+/*
+ * Turn the cache ON/OFF.
+ * Turning the cache OFF shall trigger flushing of the data
+ * to the non-volatile storage.
+ */
+int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
+{
+ struct mmc_card *card = host->card;
+ int err = 0;
+
+ if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
+ mmc_card_is_removable(host))
+ return err;
+
+ if (card && mmc_card_mmc(card) &&
+ (card->ext_csd.cache_size > 0)) {
+ enable = !!enable;
+
+ if (card->ext_csd.cache_ctrl ^ enable)
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_CACHE_CTRL, enable, 0);
+ if (err)
+ pr_err("%s: cache %s error %d\n",
+ mmc_hostname(card->host),
+ enable ? "on" : "off",
+ err);
+ else
+ card->ext_csd.cache_ctrl = enable;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(mmc_cache_ctrl);
+
#ifdef CONFIG_PM
/**
@@ -1960,23 +2288,39 @@ int mmc_suspend_host(struct mmc_host *host)
cancel_delayed_work(&host->disable);
cancel_delayed_work(&host->detect);
mmc_flush_scheduled_work();
+ err = mmc_cache_ctrl(host, 0);
+ if (err)
+ goto out;
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
- if (host->bus_ops->suspend)
- err = host->bus_ops->suspend(host);
- if (err == -ENOSYS || !host->bus_ops->resume) {
- /*
- * We simply "remove" the card in this case.
- * It will be redetected on resume.
- */
- if (host->bus_ops->remove)
- host->bus_ops->remove(host);
- mmc_claim_host(host);
- mmc_detach_bus(host);
- mmc_release_host(host);
- host->pm_flags = 0;
- err = 0;
+
+ /*
+ * A long response time is not acceptable for device drivers
+ * when doing suspend. Prevent mmc_claim_host in the suspend
+ * sequence, to potentially wait "forever" by trying to
+ * pre-claim the host.
+ */
+ if (mmc_try_claim_host(host)) {
+ if (host->bus_ops->suspend)
+ err = host->bus_ops->suspend(host);
+ if (err == -ENOSYS || !host->bus_ops->resume) {
+ /*
+ * We simply "remove" the card in this case.
+ * It will be redetected on resume.
+ */
+ if (host->bus_ops->remove)
+ host->bus_ops->remove(host);
+ mmc_claim_host(host);
+ mmc_detach_bus(host);
+ mmc_power_off(host);
+ mmc_release_host(host);
+ host->pm_flags = 0;
+ err = 0;
+ }
+ mmc_do_release_host(host);
+ } else {
+ err = -EBUSY;
}
}
mmc_bus_put(host);
@@ -1984,6 +2328,7 @@ int mmc_suspend_host(struct mmc_host *host)
if (!err && !mmc_card_keep_power(host))
mmc_power_off(host);
+out:
return err;
}
@@ -2018,7 +2363,7 @@ int mmc_resume_host(struct mmc_host *host)
BUG_ON(!host->bus_ops->resume);
err = host->bus_ops->resume(host);
if (err) {
- printk(KERN_WARNING "%s: error %d during resume "
+ pr_warning("%s: error %d during resume "
"(card was removed?)\n",
mmc_hostname(host), err);
err = 0;
@@ -2049,6 +2394,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
spin_lock_irqsave(&host->lock, flags);
host->rescan_disable = 1;
+ host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
spin_unlock_irqrestore(&host->lock, flags);
cancel_delayed_work_sync(&host->detect);
@@ -2061,6 +2407,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
host->bus_ops->remove(host);
mmc_detach_bus(host);
+ mmc_power_off(host);
mmc_release_host(host);
host->pm_flags = 0;
break;
@@ -2071,6 +2418,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
spin_lock_irqsave(&host->lock, flags);
host->rescan_disable = 0;
+ host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
spin_unlock_irqrestore(&host->lock, flags);
mmc_detect_change(host, 0);
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index d9411ed2a39b..14664f1fb16f 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -43,6 +43,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage,
bool cmd11);
void mmc_set_timing(struct mmc_host *host, unsigned int timing);
void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
+void mmc_power_off(struct mmc_host *host);
static inline void mmc_delay(unsigned int ms)
{
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 998797ed67a6..6045ea469362 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -7,11 +7,13 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/moduleparam.h>
#include <linux/debugfs.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/stat.h>
+#include <linux/fault-inject.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -19,6 +21,14 @@
#include "core.h"
#include "mmc_ops.h"
+#ifdef CONFIG_FAIL_MMC_REQUEST
+
+static DECLARE_FAULT_ATTR(fail_default_attr);
+static char *fail_request;
+module_param(fail_request, charp, 0);
+
+#endif /* CONFIG_FAIL_MMC_REQUEST */
+
/* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
static int mmc_ios_show(struct seq_file *s, void *data)
{
@@ -113,6 +123,15 @@ static int mmc_ios_show(struct seq_file *s, void *data)
case MMC_TIMING_SD_HS:
str = "sd high-speed";
break;
+ case MMC_TIMING_UHS_SDR50:
+ str = "sd uhs SDR50";
+ break;
+ case MMC_TIMING_UHS_SDR104:
+ str = "sd uhs SDR104";
+ break;
+ case MMC_TIMING_UHS_DDR50:
+ str = "sd uhs DDR50";
+ break;
default:
str = "invalid";
break;
@@ -188,6 +207,15 @@ void mmc_add_host_debugfs(struct mmc_host *host)
root, &host->clk_delay))
goto err_node;
#endif
+#ifdef CONFIG_FAIL_MMC_REQUEST
+ if (fail_request)
+ setup_fault_attr(&fail_default_attr, fail_request);
+ host->fail_mmc_request = fail_default_attr;
+ if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request",
+ root,
+ &host->fail_mmc_request)))
+ goto err_node;
+#endif
return;
err_node:
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 793d0a0dad8d..ca2e4f50f615 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -301,6 +301,17 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
host->max_blk_size = 512;
host->max_blk_count = PAGE_CACHE_SIZE / 512;
+ /*
+ * Enable runtime power management by default. This flag was added due
+ * to runtime power management causing disruption for some users, but
+ * the power on/off code has been improved since then.
+ *
+ * We'll enable this flag by default as an experiment, and if no
+ * problems are reported, we will follow up later and remove the flag
+ * altogether.
+ */
+ host->caps = MMC_CAP_POWER_OFF_CARD;
+
return host;
free:
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 5700b1cbdfec..36270449dd9d 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -101,7 +101,7 @@ static int mmc_decode_cid(struct mmc_card *card)
break;
default:
- printk(KERN_ERR "%s: card has unknown MMCA version %d\n",
+ pr_err("%s: card has unknown MMCA version %d\n",
mmc_hostname(card->host), card->csd.mmca_vsn);
return -EINVAL;
}
@@ -135,7 +135,7 @@ static int mmc_decode_csd(struct mmc_card *card)
*/
csd->structure = UNSTUFF_BITS(resp, 126, 2);
if (csd->structure == 0) {
- printk(KERN_ERR "%s: unrecognised CSD structure version %d\n",
+ pr_err("%s: unrecognised CSD structure version %d\n",
mmc_hostname(card->host), csd->structure);
return -EINVAL;
}
@@ -195,7 +195,7 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
*/
ext_csd = kmalloc(512, GFP_KERNEL);
if (!ext_csd) {
- printk(KERN_ERR "%s: could not allocate a buffer to "
+ pr_err("%s: could not allocate a buffer to "
"receive the ext_csd.\n", mmc_hostname(card->host));
return -ENOMEM;
}
@@ -217,12 +217,12 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
* stored in their CSD.
*/
if (card->csd.capacity == (4096 * 512)) {
- printk(KERN_ERR "%s: unable to read EXT_CSD "
+ pr_err("%s: unable to read EXT_CSD "
"on a possible high capacity card. "
"Card will be ignored.\n",
mmc_hostname(card->host));
} else {
- printk(KERN_WARNING "%s: unable to read "
+ pr_warning("%s: unable to read "
"EXT_CSD, performance might "
"suffer.\n",
mmc_hostname(card->host));
@@ -239,7 +239,9 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
*/
static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
{
- int err = 0;
+ int err = 0, idx;
+ unsigned int part_size;
+ u8 hc_erase_grp_sz = 0, hc_wp_grp_sz = 0;
BUG_ON(!card);
@@ -250,7 +252,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE];
if (card->csd.structure == 3) {
if (card->ext_csd.raw_ext_csd_structure > 2) {
- printk(KERN_ERR "%s: unrecognised EXT_CSD structure "
+ pr_err("%s: unrecognised EXT_CSD structure "
"version %d\n", mmc_hostname(card->host),
card->ext_csd.raw_ext_csd_structure);
err = -EINVAL;
@@ -260,7 +262,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->ext_csd.rev = ext_csd[EXT_CSD_REV];
if (card->ext_csd.rev > 6) {
- printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n",
+ pr_err("%s: unrecognised EXT_CSD revision %d\n",
mmc_hostname(card->host), card->ext_csd.rev);
err = -EINVAL;
goto out;
@@ -306,7 +308,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
break;
default:
/* MMC v4 spec says this cannot happen */
- printk(KERN_WARNING "%s: card is mmc v4 but doesn't "
+ pr_warning("%s: card is mmc v4 but doesn't "
"support any high-speed modes.\n",
mmc_hostname(card->host));
}
@@ -340,7 +342,14 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
* There are two boot regions of equal size, defined in
* multiples of 128K.
*/
- card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT] << 17;
+ if (ext_csd[EXT_CSD_BOOT_MULT] && mmc_boot_partition_access(card->host)) {
+ for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) {
+ part_size = ext_csd[EXT_CSD_BOOT_MULT] << 17;
+ mmc_part_add(card, part_size,
+ EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx,
+ "boot%d", idx, true);
+ }
+ }
}
card->ext_csd.raw_hc_erase_gap_size =
@@ -359,11 +368,12 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
* card has the Enhanced area enabled. If so, export enhanced
* area offset and size to user by adding sysfs interface.
*/
+ card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
(ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
- u8 hc_erase_grp_sz =
+ hc_erase_grp_sz =
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
- u8 hc_wp_grp_sz =
+ hc_wp_grp_sz =
ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
card->ext_csd.enhanced_area_en = 1;
@@ -392,6 +402,41 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->ext_csd.enhanced_area_offset = -EINVAL;
card->ext_csd.enhanced_area_size = -EINVAL;
}
+
+ /*
+ * General purpose partition feature support --
+ * If ext_csd has the size of general purpose partitions,
+ * set size, part_cfg, partition name in mmc_part.
+ */
+ if (ext_csd[EXT_CSD_PARTITION_SUPPORT] &
+ EXT_CSD_PART_SUPPORT_PART_EN) {
+ if (card->ext_csd.enhanced_area_en != 1) {
+ hc_erase_grp_sz =
+ ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+ hc_wp_grp_sz =
+ ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+
+ card->ext_csd.enhanced_area_en = 1;
+ }
+
+ for (idx = 0; idx < MMC_NUM_GP_PARTITION; idx++) {
+ if (!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3] &&
+ !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] &&
+ !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2])
+ continue;
+ part_size =
+ (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2]
+ << 16) +
+ (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1]
+ << 8) +
+ ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3];
+ part_size *= (size_t)(hc_erase_grp_sz *
+ hc_wp_grp_sz);
+ mmc_part_add(card, part_size << 19,
+ EXT_CSD_PART_CONFIG_ACC_GP0 + idx,
+ "gp%d", idx, false);
+ }
+ }
card->ext_csd.sec_trim_mult =
ext_csd[EXT_CSD_SEC_TRIM_MULT];
card->ext_csd.sec_erase_mult =
@@ -402,14 +447,48 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
ext_csd[EXT_CSD_TRIM_MULT];
}
- if (card->ext_csd.rev >= 5)
+ if (card->ext_csd.rev >= 5) {
+ /* check whether the eMMC card supports HPI */
+ if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) {
+ card->ext_csd.hpi = 1;
+ if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
+ card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
+ else
+ card->ext_csd.hpi_cmd = MMC_SEND_STATUS;
+ /*
+ * Indicate the maximum timeout to close
+ * a command interrupted by HPI
+ */
+ card->ext_csd.out_of_int_time =
+ ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10;
+ }
+
card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
+ card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION];
+ }
+ card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT];
if (ext_csd[EXT_CSD_ERASED_MEM_CONT])
card->erased_byte = 0xFF;
else
card->erased_byte = 0x0;
+ /* eMMC v4.5 or later */
+ if (card->ext_csd.rev >= 6) {
+ card->ext_csd.feature_support |= MMC_DISCARD_FEATURE;
+
+ card->ext_csd.generic_cmd6_time = 10 *
+ ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
+ card->ext_csd.power_off_longtime = 10 *
+ ext_csd[EXT_CSD_POWER_OFF_LONG_TIME];
+
+ card->ext_csd.cache_size =
+ ext_csd[EXT_CSD_CACHE_SIZE + 0] << 0 |
+ ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
+ ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 |
+ ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24;
+ }
+
out:
return err;
}
@@ -530,6 +609,86 @@ static struct device_type mmc_type = {
};
/*
+ * Select the PowerClass for the current bus width
+ * If power class is defined for 4/8 bit bus in the
+ * extended CSD register, select it by executing the
+ * mmc_switch command.
+ */
+static int mmc_select_powerclass(struct mmc_card *card,
+ unsigned int bus_width, u8 *ext_csd)
+{
+ int err = 0;
+ unsigned int pwrclass_val;
+ unsigned int index = 0;
+ struct mmc_host *host;
+
+ BUG_ON(!card);
+
+ host = card->host;
+ BUG_ON(!host);
+
+ if (ext_csd == NULL)
+ return 0;
+
+ /* Power class selection is supported for versions >= 4.0 */
+ if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+ return 0;
+
+ /* Power class values are defined only for 4/8 bit bus */
+ if (bus_width == EXT_CSD_BUS_WIDTH_1)
+ return 0;
+
+ switch (1 << host->ios.vdd) {
+ case MMC_VDD_165_195:
+ if (host->ios.clock <= 26000000)
+ index = EXT_CSD_PWR_CL_26_195;
+ else if (host->ios.clock <= 52000000)
+ index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
+ EXT_CSD_PWR_CL_52_195 :
+ EXT_CSD_PWR_CL_DDR_52_195;
+ else if (host->ios.clock <= 200000000)
+ index = EXT_CSD_PWR_CL_200_195;
+ break;
+ case MMC_VDD_32_33:
+ case MMC_VDD_33_34:
+ case MMC_VDD_34_35:
+ case MMC_VDD_35_36:
+ if (host->ios.clock <= 26000000)
+ index = EXT_CSD_PWR_CL_26_360;
+ else if (host->ios.clock <= 52000000)
+ index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
+ EXT_CSD_PWR_CL_52_360 :
+ EXT_CSD_PWR_CL_DDR_52_360;
+ else if (host->ios.clock <= 200000000)
+ index = EXT_CSD_PWR_CL_200_360;
+ break;
+ default:
+ pr_warning("%s: Voltage range not supported "
+ "for power class.\n", mmc_hostname(host));
+ return -EINVAL;
+ }
+
+ pwrclass_val = ext_csd[index];
+
+ if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8))
+ pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >>
+ EXT_CSD_PWR_CL_8BIT_SHIFT;
+ else
+ pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_4BIT_MASK) >>
+ EXT_CSD_PWR_CL_4BIT_SHIFT;
+
+ /* If the power class is different from the default value */
+ if (pwrclass_val > 0) {
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_POWER_CLASS,
+ pwrclass_val,
+ card->ext_csd.generic_cmd6_time);
+ }
+
+ return err;
+}
+
+/*
* Handle the detection and initialisation of a card.
*
* In the case of a resume, "oldcard" will contain the card
@@ -548,11 +707,16 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
BUG_ON(!host);
WARN_ON(!host->claimed);
+ /* Set correct bus mode for MMC before attempting init */
+ if (!mmc_host_is_spi(host))
+ mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
+
/*
* Since we're changing the OCR value, we seem to
* need to tell some cards to go back to the idle
* state. We wait 1ms to give cards time to
* respond.
+ * mmc_go_idle is needed for eMMC that are asleep
*/
mmc_go_idle(host);
@@ -668,7 +832,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
*/
if (card->ext_csd.enhanced_area_en) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_ERASE_GROUP_DEF, 1, 0);
+ EXT_CSD_ERASE_GROUP_DEF, 1,
+ card->ext_csd.generic_cmd6_time);
if (err && err != -EBADMSG)
goto free_card;
@@ -706,17 +871,35 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
/*
+ * If the host supports the power_off_notify capability then
+ * set the notification byte in the ext_csd register of device
+ */
+ if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) &&
+ (card->poweroff_notify_state == MMC_NO_POWER_NOTIFICATION)) {
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_POWER_OFF_NOTIFICATION,
+ EXT_CSD_POWER_ON,
+ card->ext_csd.generic_cmd6_time);
+ if (err && err != -EBADMSG)
+ goto free_card;
+ }
+
+ if (!err)
+ card->poweroff_notify_state = MMC_POWERED_ON;
+
+ /*
* Activate high speed (if supported)
*/
if ((card->ext_csd.hs_max_dtr != 0) &&
(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, 1, 0);
+ EXT_CSD_HS_TIMING, 1,
+ card->ext_csd.generic_cmd6_time);
if (err && err != -EBADMSG)
goto free_card;
if (err) {
- printk(KERN_WARNING "%s: switch to highspeed failed\n",
+ pr_warning("%s: switch to highspeed failed\n",
mmc_hostname(card->host));
err = 0;
} else {
@@ -726,6 +909,22 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
/*
+ * Enable HPI feature (if supported)
+ */
+ if (card->ext_csd.hpi) {
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HPI_MGMT, 1, 0);
+ if (err && err != -EBADMSG)
+ goto free_card;
+ if (err) {
+ pr_warning("%s: Enabling HPI failed\n",
+ mmc_hostname(card->host));
+ err = 0;
+ } else
+ card->ext_csd.hpi_en = 1;
+ }
+
+ /*
* Compute bus speed.
*/
max_dtr = (unsigned int)-1;
@@ -780,10 +979,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
bus_width = bus_widths[idx];
if (bus_width == MMC_BUS_WIDTH_1)
ddr = 0; /* no DDR for 1-bit width */
+ err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
+ ext_csd);
+ if (err)
+ pr_err("%s: power class selection to "
+ "bus width %d failed\n",
+ mmc_hostname(card->host),
+ 1 << bus_width);
+
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
ext_csd_bits[idx][0],
- 0);
+ card->ext_csd.generic_cmd6_time);
if (!err) {
mmc_set_bus_width(card->host, bus_width);
@@ -803,13 +1010,21 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
if (!err && ddr) {
+ err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
+ ext_csd);
+ if (err)
+ pr_err("%s: power class selection to "
+ "bus width %d ddr %d failed\n",
+ mmc_hostname(card->host),
+ 1 << bus_width, ddr);
+
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
ext_csd_bits[idx][1],
- 0);
+ card->ext_csd.generic_cmd6_time);
}
if (err) {
- printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
+ pr_warning("%s: switch to bus width %d ddr %d "
"failed\n", mmc_hostname(card->host),
1 << bus_width, ddr);
goto free_card;
@@ -840,6 +1055,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
}
+ /*
+ * If cache size is higher than 0, this indicates
+ * the existence of cache and it can be turned on.
+ */
+ if ((host->caps2 & MMC_CAP2_CACHE_CTRL) &&
+ card->ext_csd.cache_size > 0) {
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_CACHE_CTRL, 1, 0);
+ if (err && err != -EBADMSG)
+ goto free_card;
+
+ /*
+ * Only if no error, cache is turned on successfully.
+ */
+ card->ext_csd.cache_ctrl = err ? 0 : 1;
+ }
+
if (!oldcard)
host->card = card;
@@ -891,6 +1123,7 @@ static void mmc_detect(struct mmc_host *host)
mmc_claim_host(host);
mmc_detach_bus(host);
+ mmc_power_off(host);
mmc_release_host(host);
}
}
@@ -900,16 +1133,20 @@ static void mmc_detect(struct mmc_host *host)
*/
static int mmc_suspend(struct mmc_host *host)
{
+ int err = 0;
+
BUG_ON(!host);
BUG_ON(!host->card);
mmc_claim_host(host);
- if (!mmc_host_is_spi(host))
+ if (mmc_card_can_sleep(host))
+ err = mmc_card_sleep(host);
+ else if (!mmc_host_is_spi(host))
mmc_deselect_cards(host);
host->card->state &= ~MMC_STATE_HIGHSPEED;
mmc_release_host(host);
- return 0;
+ return err;
}
/*
@@ -1016,6 +1253,10 @@ int mmc_attach_mmc(struct mmc_host *host)
BUG_ON(!host);
WARN_ON(!host->claimed);
+ /* Set correct bus mode for MMC before attempting attach */
+ if (!mmc_host_is_spi(host))
+ mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
+
err = mmc_send_op_cond(host, 0, &ocr);
if (err)
return err;
@@ -1038,7 +1279,7 @@ int mmc_attach_mmc(struct mmc_host *host)
* support.
*/
if (ocr & 0x7F) {
- printk(KERN_WARNING "%s: card claims to support voltages "
+ pr_warning("%s: card claims to support voltages "
"below the defined range. These will be ignored.\n",
mmc_hostname(host));
ocr &= ~0x7F;
@@ -1077,7 +1318,7 @@ remove_card:
err:
mmc_detach_bus(host);
- printk(KERN_ERR "%s: error %d whilst initialising MMC card\n",
+ pr_err("%s: error %d whilst initialising MMC card\n",
mmc_hostname(host), err);
return err;
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 770c3d06f5dc..007863eea4fb 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -233,7 +233,7 @@ static int
mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
u32 opcode, void *buf, unsigned len)
{
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
struct scatterlist sg;
@@ -414,7 +414,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
return -EBADMSG;
} else {
if (status & 0xFDFFA000)
- printk(KERN_WARNING "%s: unexpected status %#x after "
+ pr_warning("%s: unexpected status %#x after "
"switch", mmc_hostname(card->host), status);
if (status & R1_SWITCH_ERROR)
return -EBADMSG;
@@ -454,7 +454,7 @@ static int
mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
u8 len)
{
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
struct scatterlist sg;
@@ -476,7 +476,7 @@ mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
else if (len == 4)
test_buf = testdata_4bit;
else {
- printk(KERN_ERR "%s: Invalid bus_width %d\n",
+ pr_err("%s: Invalid bus_width %d\n",
mmc_hostname(host), len);
kfree(data_buf);
return -EINVAL;
@@ -547,3 +547,34 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width)
err = mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width);
return err;
}
+
+int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
+{
+ struct mmc_command cmd = {0};
+ unsigned int opcode;
+ unsigned int flags;
+ int err;
+
+ opcode = card->ext_csd.hpi_cmd;
+ if (opcode == MMC_STOP_TRANSMISSION)
+ flags = MMC_RSP_R1 | MMC_CMD_AC;
+ else if (opcode == MMC_SEND_STATUS)
+ flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+ cmd.opcode = opcode;
+ cmd.arg = card->rca << 16 | 1;
+ cmd.flags = flags;
+ cmd.cmd_timeout_ms = card->ext_csd.out_of_int_time;
+
+ err = mmc_wait_for_cmd(card->host, &cmd, 0);
+ if (err) {
+ pr_warn("%s: error %d interrupting operation. "
+ "HPI command response %#x\n", mmc_hostname(card->host),
+ err, cmd.resp[0]);
+ return err;
+ }
+ if (status)
+ *status = cmd.resp[0];
+
+ return 0;
+}
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 9276946fa5b7..3dd8941c2980 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -26,6 +26,7 @@ int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
int mmc_card_sleepawake(struct mmc_host *host, int sleep);
int mmc_bus_test(struct mmc_card *card, u8 bus_width);
+int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
#endif
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
index 3a596217029e..6c3cf98a62eb 100644
--- a/drivers/mmc/core/quirks.c
+++ b/drivers/mmc/core/quirks.c
@@ -21,6 +21,14 @@
#define SDIO_DEVICE_ID_TI_WL1271 0x4076
#endif
+#ifndef SDIO_VENDOR_ID_STE
+#define SDIO_VENDOR_ID_STE 0x0020
+#endif
+
+#ifndef SDIO_DEVICE_ID_STE_CW1200
+#define SDIO_DEVICE_ID_STE_CW1200 0x2280
+#endif
+
/*
* This hook just adds a quirk for all sdio devices
*/
@@ -46,6 +54,9 @@ static const struct mmc_fixup mmc_fixup_methods[] = {
SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
add_quirk, MMC_QUIRK_DISABLE_CD),
+ SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200,
+ add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512),
+
END_FIXUP
};
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 0370e03e3142..a230e7f9d77a 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -163,7 +163,7 @@ static int mmc_decode_csd(struct mmc_card *card)
csd->erase_size = 1;
break;
default:
- printk(KERN_ERR "%s: unrecognised CSD structure version %d\n",
+ pr_err("%s: unrecognised CSD structure version %d\n",
mmc_hostname(card->host), csd_struct);
return -EINVAL;
}
@@ -187,7 +187,7 @@ static int mmc_decode_scr(struct mmc_card *card)
scr_struct = UNSTUFF_BITS(resp, 60, 4);
if (scr_struct != 0) {
- printk(KERN_ERR "%s: unrecognised SCR structure version %d\n",
+ pr_err("%s: unrecognised SCR structure version %d\n",
mmc_hostname(card->host), scr_struct);
return -EINVAL;
}
@@ -218,7 +218,7 @@ static int mmc_read_ssr(struct mmc_card *card)
u32 *ssr;
if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
- printk(KERN_WARNING "%s: card lacks mandatory SD Status "
+ pr_warning("%s: card lacks mandatory SD Status "
"function.\n", mmc_hostname(card->host));
return 0;
}
@@ -229,7 +229,7 @@ static int mmc_read_ssr(struct mmc_card *card)
err = mmc_app_sd_status(card, ssr);
if (err) {
- printk(KERN_WARNING "%s: problem reading SD Status "
+ pr_warning("%s: problem reading SD Status "
"register.\n", mmc_hostname(card->host));
err = 0;
goto out;
@@ -253,7 +253,7 @@ static int mmc_read_ssr(struct mmc_card *card)
card->ssr.erase_offset = eo * 1000;
}
} else {
- printk(KERN_WARNING "%s: SD Status: Invalid Allocation Unit "
+ pr_warning("%s: SD Status: Invalid Allocation Unit "
"size.\n", mmc_hostname(card->host));
}
out:
@@ -273,7 +273,7 @@ static int mmc_read_switch(struct mmc_card *card)
return 0;
if (!(card->csd.cmdclass & CCC_SWITCH)) {
- printk(KERN_WARNING "%s: card lacks mandatory switch "
+ pr_warning("%s: card lacks mandatory switch "
"function, performance might suffer.\n",
mmc_hostname(card->host));
return 0;
@@ -283,7 +283,7 @@ static int mmc_read_switch(struct mmc_card *card)
status = kmalloc(64, GFP_KERNEL);
if (!status) {
- printk(KERN_ERR "%s: could not allocate a buffer for "
+ pr_err("%s: could not allocate a buffer for "
"switch capabilities.\n",
mmc_hostname(card->host));
return -ENOMEM;
@@ -299,13 +299,16 @@ static int mmc_read_switch(struct mmc_card *card)
if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
goto out;
- printk(KERN_WARNING "%s: problem reading Bus Speed modes.\n",
+ pr_warning("%s: problem reading Bus Speed modes.\n",
mmc_hostname(card->host));
err = 0;
goto out;
}
+ if (status[13] & UHS_SDR50_BUS_SPEED)
+ card->sw_caps.hs_max_dtr = 50000000;
+
if (card->scr.sda_spec3) {
card->sw_caps.sd3_bus_mode = status[13];
@@ -319,7 +322,7 @@ static int mmc_read_switch(struct mmc_card *card)
if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
goto out;
- printk(KERN_WARNING "%s: problem reading "
+ pr_warning("%s: problem reading "
"Driver Strength.\n",
mmc_hostname(card->host));
err = 0;
@@ -339,7 +342,7 @@ static int mmc_read_switch(struct mmc_card *card)
if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
goto out;
- printk(KERN_WARNING "%s: problem reading "
+ pr_warning("%s: problem reading "
"Current Limit.\n",
mmc_hostname(card->host));
err = 0;
@@ -348,9 +351,6 @@ static int mmc_read_switch(struct mmc_card *card)
}
card->sw_caps.sd3_curr_limit = status[7];
- } else {
- if (status[13] & 0x02)
- card->sw_caps.hs_max_dtr = 50000000;
}
out:
@@ -383,7 +383,7 @@ int mmc_sd_switch_hs(struct mmc_card *card)
status = kmalloc(64, GFP_KERNEL);
if (!status) {
- printk(KERN_ERR "%s: could not allocate a buffer for "
+ pr_err("%s: could not allocate a buffer for "
"switch capabilities.\n", mmc_hostname(card->host));
return -ENOMEM;
}
@@ -393,7 +393,7 @@ int mmc_sd_switch_hs(struct mmc_card *card)
goto out;
if ((status[16] & 0xF) != 1) {
- printk(KERN_WARNING "%s: Problem switching card "
+ pr_warning("%s: Problem switching card "
"into high-speed mode!\n",
mmc_hostname(card->host));
err = 0;
@@ -459,7 +459,7 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status)
return err;
if ((status[15] & 0xF) != drive_strength) {
- printk(KERN_WARNING "%s: Problem setting drive strength!\n",
+ pr_warning("%s: Problem setting drive strength!\n",
mmc_hostname(card->host));
return 0;
}
@@ -538,7 +538,7 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
return err;
if ((status[16] & 0xF) != card->sd_bus_speed)
- printk(KERN_WARNING "%s: Problem setting bus speed mode!\n",
+ pr_warning("%s: Problem setting bus speed mode!\n",
mmc_hostname(card->host));
else {
mmc_set_timing(card->host, timing);
@@ -600,7 +600,7 @@ static int sd_set_current_limit(struct mmc_card *card, u8 *status)
return err;
if (((status[15] >> 4) & 0x0F) != current_limit)
- printk(KERN_WARNING "%s: Problem setting current limit!\n",
+ pr_warning("%s: Problem setting current limit!\n",
mmc_hostname(card->host));
return 0;
@@ -622,7 +622,7 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
status = kmalloc(64, GFP_KERNEL);
if (!status) {
- printk(KERN_ERR "%s: could not allocate a buffer for "
+ pr_err("%s: could not allocate a buffer for "
"switch capabilities.\n", mmc_hostname(card->host));
return -ENOMEM;
}
@@ -852,7 +852,7 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
ro = host->ops->get_ro(host);
if (ro < 0) {
- printk(KERN_WARNING "%s: host does not "
+ pr_warning("%s: host does not "
"support reading read-only "
"switch. assuming write-enable.\n",
mmc_hostname(host));
@@ -929,8 +929,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
err = mmc_send_relative_addr(host, &card->rca);
if (err)
return err;
-
- mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
}
if (!oldcard) {
@@ -1043,6 +1041,7 @@ static void mmc_sd_detect(struct mmc_host *host)
mmc_claim_host(host);
mmc_detach_bus(host);
+ mmc_power_off(host);
mmc_release_host(host);
}
}
@@ -1167,7 +1166,7 @@ int mmc_attach_sd(struct mmc_host *host)
* support.
*/
if (ocr & 0x7F) {
- printk(KERN_WARNING "%s: card claims to support voltages "
+ pr_warning("%s: card claims to support voltages "
"below the defined range. These will be ignored.\n",
mmc_hostname(host));
ocr &= ~0x7F;
@@ -1175,7 +1174,7 @@ int mmc_attach_sd(struct mmc_host *host)
if ((ocr & MMC_VDD_165_195) &&
!(host->ocr_avail_sd & MMC_VDD_165_195)) {
- printk(KERN_WARNING "%s: SD card claims to support the "
+ pr_warning("%s: SD card claims to support the "
"incompletely defined 'low voltage range'. This "
"will be ignored.\n", mmc_hostname(host));
ocr &= ~MMC_VDD_165_195;
@@ -1214,7 +1213,7 @@ remove_card:
err:
mmc_detach_bus(host);
- printk(KERN_ERR "%s: error %d whilst initialising SD card\n",
+ pr_err("%s: error %d whilst initialising SD card\n",
mmc_hostname(host), err);
return err;
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index 021fed153804..46a785419fab 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(mmc_app_cmd);
int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
struct mmc_command *cmd, int retries)
{
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
int i, err;
@@ -244,7 +244,7 @@ int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca)
int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
{
int err;
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
struct scatterlist sg;
@@ -303,7 +303,7 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
int mmc_sd_switch(struct mmc_card *card, int mode, int group,
u8 value, u8 *resp)
{
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
struct scatterlist sg;
@@ -348,7 +348,7 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group,
int mmc_app_sd_status(struct mmc_card *card, void *ssr)
{
int err;
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
struct scatterlist sg;
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 262fff019177..3ab565e32a6a 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -111,8 +111,8 @@ static int sdio_read_cccr(struct mmc_card *card)
cccr_vsn = data & 0x0f;
- if (cccr_vsn > SDIO_CCCR_REV_1_20) {
- printk(KERN_ERR "%s: unrecognised CCCR structure version %d\n",
+ if (cccr_vsn > SDIO_CCCR_REV_3_00) {
+ pr_err("%s: unrecognised CCCR structure version %d\n",
mmc_hostname(card->host), cccr_vsn);
return -EINVAL;
}
@@ -408,8 +408,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
*/
if (oldcard)
oldcard->rca = card->rca;
-
- mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
}
/*
@@ -597,6 +595,7 @@ out:
mmc_claim_host(host);
mmc_detach_bus(host);
+ mmc_power_off(host);
mmc_release_host(host);
}
}
@@ -778,7 +777,7 @@ int mmc_attach_sdio(struct mmc_host *host)
* support.
*/
if (ocr & 0x7F) {
- printk(KERN_WARNING "%s: card claims to support voltages "
+ pr_warning("%s: card claims to support voltages "
"below the defined range. These will be ignored.\n",
mmc_hostname(host));
ocr &= ~0x7F;
@@ -875,7 +874,7 @@ remove:
err:
mmc_detach_bus(host);
- printk(KERN_ERR "%s: error %d whilst initialising SDIO card\n",
+ pr_err("%s: error %d whilst initialising SDIO card\n",
mmc_hostname(host), err);
return err;
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index e4e6822d09e3..c643b2f78bf1 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -173,7 +173,7 @@ static int sdio_bus_remove(struct device *dev)
drv->remove(func);
if (func->irq_handler) {
- printk(KERN_WARNING "WARNING: driver %s did not remove "
+ pr_warning("WARNING: driver %s did not remove "
"its interrupt handler!\n", drv->name);
sdio_claim_host(func);
sdio_release_irq(func);
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index 541bdb89e0c5..f1c7ed8f4d85 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -132,7 +132,7 @@ static int cis_tpl_parse(struct mmc_card *card, struct sdio_func *func,
ret = -EINVAL;
}
if (ret && ret != -EILSEQ && ret != -ENOENT) {
- printk(KERN_ERR "%s: bad %s tuple 0x%02x (%u bytes)\n",
+ pr_err("%s: bad %s tuple 0x%02x (%u bytes)\n",
mmc_hostname(card->host), tpl_descr, code, size);
}
} else {
@@ -313,7 +313,7 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
if (ret == -ENOENT) {
/* warn about unknown tuples */
- printk(KERN_WARNING "%s: queuing unknown"
+ pr_warning("%s: queuing unknown"
" CIS tuple 0x%02x (%u bytes)\n",
mmc_hostname(card->host),
tpl_code, tpl_link);
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 03ead028d2ce..b644dd59c16e 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -45,7 +45,7 @@ static int process_sdio_pending_irqs(struct mmc_card *card)
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending);
if (ret) {
- printk(KERN_DEBUG "%s: error %d reading SDIO_CCCR_INTx\n",
+ pr_debug("%s: error %d reading SDIO_CCCR_INTx\n",
mmc_card_id(card), ret);
return ret;
}
@@ -55,7 +55,7 @@ static int process_sdio_pending_irqs(struct mmc_card *card)
if (pending & (1 << i)) {
func = card->sdio_func[i - 1];
if (!func) {
- printk(KERN_WARNING "%s: pending IRQ for "
+ pr_warning("%s: pending IRQ for "
"non-existent function\n",
mmc_card_id(card));
ret = -EINVAL;
@@ -63,7 +63,7 @@ static int process_sdio_pending_irqs(struct mmc_card *card)
func->irq_handler(func);
count++;
} else {
- printk(KERN_WARNING "%s: pending IRQ with no handler\n",
+ pr_warning("%s: pending IRQ with no handler\n",
sdio_func_id(func));
ret = -EINVAL;
}
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index f087d876c573..b0517cc06200 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -121,7 +121,7 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
{
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
struct scatterlist sg;
@@ -144,8 +144,11 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
cmd.arg |= fn << 28;
cmd.arg |= incr_addr ? 0x04000000 : 0x00000000;
cmd.arg |= addr << 9;
- if (blocks == 1 && blksz <= 512)
- cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */
+ if (blocks == 1 && blksz < 512)
+ cmd.arg |= blksz; /* byte mode */
+ else if (blocks == 1 && blksz == 512 &&
+ !(mmc_card_broken_byte_mode_512(card)))
+ cmd.arg |= 0; /* byte mode, 0==512 */
else
cmd.arg |= 0x08000000 | blocks; /* block mode */
cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 8c87096531e9..87d5067ba629 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -130,13 +130,13 @@ config MMC_SDHCI_CNS3XXX
If unsure, say N.
config MMC_SDHCI_ESDHC_IMX
- tristate "SDHCI platform support for the Freescale eSDHC i.MX controller"
- depends on ARCH_MX25 || ARCH_MX35 || ARCH_MX5
+ tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
+ depends on ARCH_MXC
depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
help
- This selects the Freescale eSDHC controller support on the platform
- bus, found on platforms like mx35/51.
+ This selects the Freescale eSDHC/uSDHC controller support
+ found on i.MX25, i.MX35 i.MX5x and i.MX6x.
If you have a controller with this interface, say Y or M here.
@@ -326,11 +326,11 @@ config MMC_MSM
support for SDIO devices.
config MMC_MXC
- tristate "Freescale i.MX2/3 Multimedia Card Interface support"
- depends on MACH_MX21 || MACH_MX27 || ARCH_MX31
+ tristate "Freescale i.MX21/27/31 Multimedia Card Interface support"
+ depends on ARCH_MXC
help
- This selects the Freescale i.MX2/3 Multimedia card Interface.
- If you have a i.MX platform with a Multimedia Card slot,
+ This selects the Freescale i.MX21, i.MX27 and i.MX31 Multimedia card
+ Interface. If you have a i.MX platform with a Multimedia Card slot,
say Y or M here.
If unsure, say N.
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index a4aa3af86fed..a8b4d2aa18e5 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -869,7 +869,11 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
{
struct at91mci_host *host = _host;
- int present = !gpio_get_value(irq_to_gpio(irq));
+ int present;
+
+ /* entering this ISR means that we have configured det_pin:
+ * we can use its value in board structure */
+ present = !gpio_get_value(host->board->det_pin);
/*
* we expect this irq on both insert and remove,
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h
index fc8a0fe7c5c5..000b3ad0f5ca 100644
--- a/drivers/mmc/host/atmel-mci-regs.h
+++ b/drivers/mmc/host/atmel-mci-regs.h
@@ -17,112 +17,126 @@
#define __DRIVERS_MMC_ATMEL_MCI_H__
/* MCI Register Definitions */
-#define MCI_CR 0x0000 /* Control */
-# define MCI_CR_MCIEN ( 1 << 0) /* MCI Enable */
-# define MCI_CR_MCIDIS ( 1 << 1) /* MCI Disable */
-# define MCI_CR_PWSEN ( 1 << 2) /* Power Save Enable */
-# define MCI_CR_PWSDIS ( 1 << 3) /* Power Save Disable */
-# define MCI_CR_SWRST ( 1 << 7) /* Software Reset */
-#define MCI_MR 0x0004 /* Mode */
-# define MCI_MR_CLKDIV(x) ((x) << 0) /* Clock Divider */
-# define MCI_MR_PWSDIV(x) ((x) << 8) /* Power Saving Divider */
-# define MCI_MR_RDPROOF ( 1 << 11) /* Read Proof */
-# define MCI_MR_WRPROOF ( 1 << 12) /* Write Proof */
-# define MCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */
-# define MCI_MR_PDCPADV ( 1 << 14) /* Padding Value */
-# define MCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */
-#define MCI_DTOR 0x0008 /* Data Timeout */
-# define MCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */
-# define MCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */
-#define MCI_SDCR 0x000c /* SD Card / SDIO */
-# define MCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */
-# define MCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */
-# define MCI_SDCSEL_MASK ( 3 << 0)
-# define MCI_SDCBUS_1BIT ( 0 << 6) /* 1-bit data bus */
-# define MCI_SDCBUS_4BIT ( 2 << 6) /* 4-bit data bus */
-# define MCI_SDCBUS_8BIT ( 3 << 6) /* 8-bit data bus[2] */
-# define MCI_SDCBUS_MASK ( 3 << 6)
-#define MCI_ARGR 0x0010 /* Command Argument */
-#define MCI_CMDR 0x0014 /* Command */
-# define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */
-# define MCI_CMDR_RSPTYP_NONE ( 0 << 6) /* No response */
-# define MCI_CMDR_RSPTYP_48BIT ( 1 << 6) /* 48-bit response */
-# define MCI_CMDR_RSPTYP_136BIT ( 2 << 6) /* 136-bit response */
-# define MCI_CMDR_SPCMD_INIT ( 1 << 8) /* Initialization command */
-# define MCI_CMDR_SPCMD_SYNC ( 2 << 8) /* Synchronized command */
-# define MCI_CMDR_SPCMD_INT ( 4 << 8) /* Interrupt command */
-# define MCI_CMDR_SPCMD_INTRESP ( 5 << 8) /* Interrupt response */
-# define MCI_CMDR_OPDCMD ( 1 << 11) /* Open Drain */
-# define MCI_CMDR_MAXLAT_5CYC ( 0 << 12) /* Max latency 5 cycles */
-# define MCI_CMDR_MAXLAT_64CYC ( 1 << 12) /* Max latency 64 cycles */
-# define MCI_CMDR_START_XFER ( 1 << 16) /* Start data transfer */
-# define MCI_CMDR_STOP_XFER ( 2 << 16) /* Stop data transfer */
-# define MCI_CMDR_TRDIR_WRITE ( 0 << 18) /* Write data */
-# define MCI_CMDR_TRDIR_READ ( 1 << 18) /* Read data */
-# define MCI_CMDR_BLOCK ( 0 << 19) /* Single-block transfer */
-# define MCI_CMDR_MULTI_BLOCK ( 1 << 19) /* Multi-block transfer */
-# define MCI_CMDR_STREAM ( 2 << 19) /* MMC Stream transfer */
-# define MCI_CMDR_SDIO_BYTE ( 4 << 19) /* SDIO Byte transfer */
-# define MCI_CMDR_SDIO_BLOCK ( 5 << 19) /* SDIO Block transfer */
-# define MCI_CMDR_SDIO_SUSPEND ( 1 << 24) /* SDIO Suspend Command */
-# define MCI_CMDR_SDIO_RESUME ( 2 << 24) /* SDIO Resume Command */
-#define MCI_BLKR 0x0018 /* Block */
-# define MCI_BCNT(x) ((x) << 0) /* Data Block Count */
-# define MCI_BLKLEN(x) ((x) << 16) /* Data Block Length */
-#define MCI_CSTOR 0x001c /* Completion Signal Timeout[2] */
-# define MCI_CSTOCYC(x) ((x) << 0) /* CST cycles */
-# define MCI_CSTOMUL(x) ((x) << 4) /* CST multiplier */
-#define MCI_RSPR 0x0020 /* Response 0 */
-#define MCI_RSPR1 0x0024 /* Response 1 */
-#define MCI_RSPR2 0x0028 /* Response 2 */
-#define MCI_RSPR3 0x002c /* Response 3 */
-#define MCI_RDR 0x0030 /* Receive Data */
-#define MCI_TDR 0x0034 /* Transmit Data */
-#define MCI_SR 0x0040 /* Status */
-#define MCI_IER 0x0044 /* Interrupt Enable */
-#define MCI_IDR 0x0048 /* Interrupt Disable */
-#define MCI_IMR 0x004c /* Interrupt Mask */
-# define MCI_CMDRDY ( 1 << 0) /* Command Ready */
-# define MCI_RXRDY ( 1 << 1) /* Receiver Ready */
-# define MCI_TXRDY ( 1 << 2) /* Transmitter Ready */
-# define MCI_BLKE ( 1 << 3) /* Data Block Ended */
-# define MCI_DTIP ( 1 << 4) /* Data Transfer In Progress */
-# define MCI_NOTBUSY ( 1 << 5) /* Data Not Busy */
-# define MCI_SDIOIRQA ( 1 << 8) /* SDIO IRQ in slot A */
-# define MCI_SDIOIRQB ( 1 << 9) /* SDIO IRQ in slot B */
-# define MCI_RINDE ( 1 << 16) /* Response Index Error */
-# define MCI_RDIRE ( 1 << 17) /* Response Direction Error */
-# define MCI_RCRCE ( 1 << 18) /* Response CRC Error */
-# define MCI_RENDE ( 1 << 19) /* Response End Bit Error */
-# define MCI_RTOE ( 1 << 20) /* Response Time-Out Error */
-# define MCI_DCRCE ( 1 << 21) /* Data CRC Error */
-# define MCI_DTOE ( 1 << 22) /* Data Time-Out Error */
-# define MCI_OVRE ( 1 << 30) /* RX Overrun Error */
-# define MCI_UNRE ( 1 << 31) /* TX Underrun Error */
-#define MCI_DMA 0x0050 /* DMA Configuration[2] */
-# define MCI_DMA_OFFSET(x) ((x) << 0) /* DMA Write Buffer Offset */
-# define MCI_DMA_CHKSIZE(x) ((x) << 4) /* DMA Channel Read and Write Chunk Size */
-# define MCI_DMAEN ( 1 << 8) /* DMA Hardware Handshaking Enable */
-#define MCI_CFG 0x0054 /* Configuration[2] */
-# define MCI_CFG_FIFOMODE_1DATA ( 1 << 0) /* MCI Internal FIFO control mode */
-# define MCI_CFG_FERRCTRL_COR ( 1 << 4) /* Flow Error flag reset control mode */
-# define MCI_CFG_HSMODE ( 1 << 8) /* High Speed Mode */
-# define MCI_CFG_LSYNC ( 1 << 12) /* Synchronize on the last block */
-#define MCI_WPMR 0x00e4 /* Write Protection Mode[2] */
-# define MCI_WP_EN ( 1 << 0) /* WP Enable */
-# define MCI_WP_KEY (0x4d4349 << 8) /* WP Key */
-#define MCI_WPSR 0x00e8 /* Write Protection Status[2] */
-# define MCI_GET_WP_VS(x) ((x) & 0x0f)
-# define MCI_GET_WP_VSRC(x) (((x) >> 8) & 0xffff)
-#define MCI_FIFO_APERTURE 0x0200 /* FIFO Aperture[2] */
+#define ATMCI_CR 0x0000 /* Control */
+# define ATMCI_CR_MCIEN ( 1 << 0) /* MCI Enable */
+# define ATMCI_CR_MCIDIS ( 1 << 1) /* MCI Disable */
+# define ATMCI_CR_PWSEN ( 1 << 2) /* Power Save Enable */
+# define ATMCI_CR_PWSDIS ( 1 << 3) /* Power Save Disable */
+# define ATMCI_CR_SWRST ( 1 << 7) /* Software Reset */
+#define ATMCI_MR 0x0004 /* Mode */
+# define ATMCI_MR_CLKDIV(x) ((x) << 0) /* Clock Divider */
+# define ATMCI_MR_PWSDIV(x) ((x) << 8) /* Power Saving Divider */
+# define ATMCI_MR_RDPROOF ( 1 << 11) /* Read Proof */
+# define ATMCI_MR_WRPROOF ( 1 << 12) /* Write Proof */
+# define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */
+# define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */
+# define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */
+#define ATMCI_DTOR 0x0008 /* Data Timeout */
+# define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */
+# define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */
+#define ATMCI_SDCR 0x000c /* SD Card / SDIO */
+# define ATMCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */
+# define ATMCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */
+# define ATMCI_SDCSEL_MASK ( 3 << 0)
+# define ATMCI_SDCBUS_1BIT ( 0 << 6) /* 1-bit data bus */
+# define ATMCI_SDCBUS_4BIT ( 2 << 6) /* 4-bit data bus */
+# define ATMCI_SDCBUS_8BIT ( 3 << 6) /* 8-bit data bus[2] */
+# define ATMCI_SDCBUS_MASK ( 3 << 6)
+#define ATMCI_ARGR 0x0010 /* Command Argument */
+#define ATMCI_CMDR 0x0014 /* Command */
+# define ATMCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */
+# define ATMCI_CMDR_RSPTYP_NONE ( 0 << 6) /* No response */
+# define ATMCI_CMDR_RSPTYP_48BIT ( 1 << 6) /* 48-bit response */
+# define ATMCI_CMDR_RSPTYP_136BIT ( 2 << 6) /* 136-bit response */
+# define ATMCI_CMDR_SPCMD_INIT ( 1 << 8) /* Initialization command */
+# define ATMCI_CMDR_SPCMD_SYNC ( 2 << 8) /* Synchronized command */
+# define ATMCI_CMDR_SPCMD_INT ( 4 << 8) /* Interrupt command */
+# define ATMCI_CMDR_SPCMD_INTRESP ( 5 << 8) /* Interrupt response */
+# define ATMCI_CMDR_OPDCMD ( 1 << 11) /* Open Drain */
+# define ATMCI_CMDR_MAXLAT_5CYC ( 0 << 12) /* Max latency 5 cycles */
+# define ATMCI_CMDR_MAXLAT_64CYC ( 1 << 12) /* Max latency 64 cycles */
+# define ATMCI_CMDR_START_XFER ( 1 << 16) /* Start data transfer */
+# define ATMCI_CMDR_STOP_XFER ( 2 << 16) /* Stop data transfer */
+# define ATMCI_CMDR_TRDIR_WRITE ( 0 << 18) /* Write data */
+# define ATMCI_CMDR_TRDIR_READ ( 1 << 18) /* Read data */
+# define ATMCI_CMDR_BLOCK ( 0 << 19) /* Single-block transfer */
+# define ATMCI_CMDR_MULTI_BLOCK ( 1 << 19) /* Multi-block transfer */
+# define ATMCI_CMDR_STREAM ( 2 << 19) /* MMC Stream transfer */
+# define ATMCI_CMDR_SDIO_BYTE ( 4 << 19) /* SDIO Byte transfer */
+# define ATMCI_CMDR_SDIO_BLOCK ( 5 << 19) /* SDIO Block transfer */
+# define ATMCI_CMDR_SDIO_SUSPEND ( 1 << 24) /* SDIO Suspend Command */
+# define ATMCI_CMDR_SDIO_RESUME ( 2 << 24) /* SDIO Resume Command */
+#define ATMCI_BLKR 0x0018 /* Block */
+# define ATMCI_BCNT(x) ((x) << 0) /* Data Block Count */
+# define ATMCI_BLKLEN(x) ((x) << 16) /* Data Block Length */
+#define ATMCI_CSTOR 0x001c /* Completion Signal Timeout[2] */
+# define ATMCI_CSTOCYC(x) ((x) << 0) /* CST cycles */
+# define ATMCI_CSTOMUL(x) ((x) << 4) /* CST multiplier */
+#define ATMCI_RSPR 0x0020 /* Response 0 */
+#define ATMCI_RSPR1 0x0024 /* Response 1 */
+#define ATMCI_RSPR2 0x0028 /* Response 2 */
+#define ATMCI_RSPR3 0x002c /* Response 3 */
+#define ATMCI_RDR 0x0030 /* Receive Data */
+#define ATMCI_TDR 0x0034 /* Transmit Data */
+#define ATMCI_SR 0x0040 /* Status */
+#define ATMCI_IER 0x0044 /* Interrupt Enable */
+#define ATMCI_IDR 0x0048 /* Interrupt Disable */
+#define ATMCI_IMR 0x004c /* Interrupt Mask */
+# define ATMCI_CMDRDY ( 1 << 0) /* Command Ready */
+# define ATMCI_RXRDY ( 1 << 1) /* Receiver Ready */
+# define ATMCI_TXRDY ( 1 << 2) /* Transmitter Ready */
+# define ATMCI_BLKE ( 1 << 3) /* Data Block Ended */
+# define ATMCI_DTIP ( 1 << 4) /* Data Transfer In Progress */
+# define ATMCI_NOTBUSY ( 1 << 5) /* Data Not Busy */
+# define ATMCI_ENDRX ( 1 << 6) /* End of RX Buffer */
+# define ATMCI_ENDTX ( 1 << 7) /* End of TX Buffer */
+# define ATMCI_SDIOIRQA ( 1 << 8) /* SDIO IRQ in slot A */
+# define ATMCI_SDIOIRQB ( 1 << 9) /* SDIO IRQ in slot B */
+# define ATMCI_SDIOWAIT ( 1 << 12) /* SDIO Read Wait Operation Status */
+# define ATMCI_CSRCV ( 1 << 13) /* CE-ATA Completion Signal Received */
+# define ATMCI_RXBUFF ( 1 << 14) /* RX Buffer Full */
+# define ATMCI_TXBUFE ( 1 << 15) /* TX Buffer Empty */
+# define ATMCI_RINDE ( 1 << 16) /* Response Index Error */
+# define ATMCI_RDIRE ( 1 << 17) /* Response Direction Error */
+# define ATMCI_RCRCE ( 1 << 18) /* Response CRC Error */
+# define ATMCI_RENDE ( 1 << 19) /* Response End Bit Error */
+# define ATMCI_RTOE ( 1 << 20) /* Response Time-Out Error */
+# define ATMCI_DCRCE ( 1 << 21) /* Data CRC Error */
+# define ATMCI_DTOE ( 1 << 22) /* Data Time-Out Error */
+# define ATMCI_CSTOE ( 1 << 23) /* Completion Signal Time-out Error */
+# define ATMCI_BLKOVRE ( 1 << 24) /* DMA Block Overrun Error */
+# define ATMCI_DMADONE ( 1 << 25) /* DMA Transfer Done */
+# define ATMCI_FIFOEMPTY ( 1 << 26) /* FIFO Empty Flag */
+# define ATMCI_XFRDONE ( 1 << 27) /* Transfer Done Flag */
+# define ATMCI_ACKRCV ( 1 << 28) /* Boot Operation Acknowledge Received */
+# define ATMCI_ACKRCVE ( 1 << 29) /* Boot Operation Acknowledge Error */
+# define ATMCI_OVRE ( 1 << 30) /* RX Overrun Error */
+# define ATMCI_UNRE ( 1 << 31) /* TX Underrun Error */
+#define ATMCI_DMA 0x0050 /* DMA Configuration[2] */
+# define ATMCI_DMA_OFFSET(x) ((x) << 0) /* DMA Write Buffer Offset */
+# define ATMCI_DMA_CHKSIZE(x) ((x) << 4) /* DMA Channel Read and Write Chunk Size */
+# define ATMCI_DMAEN ( 1 << 8) /* DMA Hardware Handshaking Enable */
+#define ATMCI_CFG 0x0054 /* Configuration[2] */
+# define ATMCI_CFG_FIFOMODE_1DATA ( 1 << 0) /* MCI Internal FIFO control mode */
+# define ATMCI_CFG_FERRCTRL_COR ( 1 << 4) /* Flow Error flag reset control mode */
+# define ATMCI_CFG_HSMODE ( 1 << 8) /* High Speed Mode */
+# define ATMCI_CFG_LSYNC ( 1 << 12) /* Synchronize on the last block */
+#define ATMCI_WPMR 0x00e4 /* Write Protection Mode[2] */
+# define ATMCI_WP_EN ( 1 << 0) /* WP Enable */
+# define ATMCI_WP_KEY (0x4d4349 << 8) /* WP Key */
+#define ATMCI_WPSR 0x00e8 /* Write Protection Status[2] */
+# define ATMCI_GET_WP_VS(x) ((x) & 0x0f)
+# define ATMCI_GET_WP_VSRC(x) (((x) >> 8) & 0xffff)
+#define ATMCI_VERSION 0x00FC /* Version */
+#define ATMCI_FIFO_APERTURE 0x0200 /* FIFO Aperture[2] */
/* This is not including the FIFO Aperture on MCI2 */
-#define MCI_REGS_SIZE 0x100
+#define ATMCI_REGS_SIZE 0x100
/* Register access macros */
-#define mci_readl(port,reg) \
- __raw_readl((port)->regs + MCI_##reg)
-#define mci_writel(port,reg,value) \
- __raw_writel((value), (port)->regs + MCI_##reg)
+#define atmci_readl(port,reg) \
+ __raw_readl((port)->regs + reg)
+#define atmci_writel(port,reg,value) \
+ __raw_writel((value), (port)->regs + reg)
#endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index fa8cae1d7005..a7ee50271465 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -30,6 +30,7 @@
#include <mach/atmel-mci.h>
#include <linux/atmel-mci.h>
+#include <linux/atmel_pdc.h>
#include <asm/io.h>
#include <asm/unaligned.h>
@@ -39,7 +40,7 @@
#include "atmel-mci-regs.h"
-#define ATMCI_DATA_ERROR_FLAGS (MCI_DCRCE | MCI_DTOE | MCI_OVRE | MCI_UNRE)
+#define ATMCI_DATA_ERROR_FLAGS (ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE)
#define ATMCI_DMA_THRESHOLD 16
enum {
@@ -58,18 +59,35 @@ enum atmel_mci_state {
STATE_DATA_ERROR,
};
+enum atmci_xfer_dir {
+ XFER_RECEIVE = 0,
+ XFER_TRANSMIT,
+};
+
+enum atmci_pdc_buf {
+ PDC_FIRST_BUF = 0,
+ PDC_SECOND_BUF,
+};
+
+struct atmel_mci_caps {
+ bool has_dma;
+ bool has_pdc;
+ bool has_cfg_reg;
+ bool has_cstor_reg;
+ bool has_highspeed;
+ bool has_rwproof;
+};
+
struct atmel_mci_dma {
-#ifdef CONFIG_MMC_ATMELMCI_DMA
struct dma_chan *chan;
struct dma_async_tx_descriptor *data_desc;
-#endif
};
/**
* struct atmel_mci - MMC controller state shared between all slots
* @lock: Spinlock protecting the queue and associated data.
* @regs: Pointer to MMIO registers.
- * @sg: Scatterlist entry currently being processed by PIO code, if any.
+ * @sg: Scatterlist entry currently being processed by PIO or PDC code.
* @pio_offset: Offset into the current scatterlist entry.
* @cur_slot: The slot which is currently using the controller.
* @mrq: The request currently being processed on @cur_slot,
@@ -77,6 +95,7 @@ struct atmel_mci_dma {
* @cmd: The command currently being sent to the card, or NULL.
* @data: The data currently being transferred, or NULL if no data
* transfer is in progress.
+ * @data_size: just data->blocks * data->blksz.
* @dma: DMA client state.
* @data_chan: DMA channel being used for the current data transfer.
* @cmd_status: Snapshot of SR taken upon completion of the current
@@ -103,6 +122,13 @@ struct atmel_mci_dma {
* @mck: The peripheral bus clock hooked up to the MMC controller.
* @pdev: Platform device associated with the MMC controller.
* @slot: Slots sharing this MMC controller.
+ * @caps: MCI capabilities depending on MCI version.
+ * @prepare_data: function to setup MCI before data transfer which
+ * depends on MCI capabilities.
+ * @submit_data: function to start data transfer which depends on MCI
+ * capabilities.
+ * @stop_transfer: function to stop data transfer which depends on MCI
+ * capabilities.
*
* Locking
* =======
@@ -143,6 +169,7 @@ struct atmel_mci {
struct mmc_request *mrq;
struct mmc_command *cmd;
struct mmc_data *data;
+ unsigned int data_size;
struct atmel_mci_dma dma;
struct dma_chan *data_chan;
@@ -166,7 +193,13 @@ struct atmel_mci {
struct clk *mck;
struct platform_device *pdev;
- struct atmel_mci_slot *slot[ATMEL_MCI_MAX_NR_SLOTS];
+ struct atmel_mci_slot *slot[ATMCI_MAX_NR_SLOTS];
+
+ struct atmel_mci_caps caps;
+
+ u32 (*prepare_data)(struct atmel_mci *host, struct mmc_data *data);
+ void (*submit_data)(struct atmel_mci *host, struct mmc_data *data);
+ void (*stop_transfer)(struct atmel_mci *host);
};
/**
@@ -220,31 +253,6 @@ struct atmel_mci_slot {
set_bit(event, &host->pending_events)
/*
- * Enable or disable features/registers based on
- * whether the processor supports them
- */
-static bool mci_has_rwproof(void)
-{
- if (cpu_is_at91sam9261() || cpu_is_at91rm9200())
- return false;
- else
- return true;
-}
-
-/*
- * The new MCI2 module isn't 100% compatible with the old MCI module,
- * and it has a few nice features which we want to use...
- */
-static inline bool atmci_is_mci2(void)
-{
- if (cpu_is_at91sam9g45())
- return true;
-
- return false;
-}
-
-
-/*
* The debugfs stuff below is mostly optimized away when
* CONFIG_DEBUG_FS is not set.
*/
@@ -352,7 +360,7 @@ static int atmci_regs_show(struct seq_file *s, void *v)
struct atmel_mci *host = s->private;
u32 *buf;
- buf = kmalloc(MCI_REGS_SIZE, GFP_KERNEL);
+ buf = kmalloc(ATMCI_REGS_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -363,47 +371,50 @@ static int atmci_regs_show(struct seq_file *s, void *v)
*/
spin_lock_bh(&host->lock);
clk_enable(host->mck);
- memcpy_fromio(buf, host->regs, MCI_REGS_SIZE);
+ memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE);
clk_disable(host->mck);
spin_unlock_bh(&host->lock);
seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n",
- buf[MCI_MR / 4],
- buf[MCI_MR / 4] & MCI_MR_RDPROOF ? " RDPROOF" : "",
- buf[MCI_MR / 4] & MCI_MR_WRPROOF ? " WRPROOF" : "",
- buf[MCI_MR / 4] & 0xff);
- seq_printf(s, "DTOR:\t0x%08x\n", buf[MCI_DTOR / 4]);
- seq_printf(s, "SDCR:\t0x%08x\n", buf[MCI_SDCR / 4]);
- seq_printf(s, "ARGR:\t0x%08x\n", buf[MCI_ARGR / 4]);
+ buf[ATMCI_MR / 4],
+ buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "",
+ buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "",
+ buf[ATMCI_MR / 4] & 0xff);
+ seq_printf(s, "DTOR:\t0x%08x\n", buf[ATMCI_DTOR / 4]);
+ seq_printf(s, "SDCR:\t0x%08x\n", buf[ATMCI_SDCR / 4]);
+ seq_printf(s, "ARGR:\t0x%08x\n", buf[ATMCI_ARGR / 4]);
seq_printf(s, "BLKR:\t0x%08x BCNT=%u BLKLEN=%u\n",
- buf[MCI_BLKR / 4],
- buf[MCI_BLKR / 4] & 0xffff,
- (buf[MCI_BLKR / 4] >> 16) & 0xffff);
- if (atmci_is_mci2())
- seq_printf(s, "CSTOR:\t0x%08x\n", buf[MCI_CSTOR / 4]);
+ buf[ATMCI_BLKR / 4],
+ buf[ATMCI_BLKR / 4] & 0xffff,
+ (buf[ATMCI_BLKR / 4] >> 16) & 0xffff);
+ if (host->caps.has_cstor_reg)
+ seq_printf(s, "CSTOR:\t0x%08x\n", buf[ATMCI_CSTOR / 4]);
/* Don't read RSPR and RDR; it will consume the data there */
- atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]);
- atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]);
+ atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]);
+ atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]);
- if (atmci_is_mci2()) {
+ if (host->caps.has_dma) {
u32 val;
- val = buf[MCI_DMA / 4];
+ val = buf[ATMCI_DMA / 4];
seq_printf(s, "DMA:\t0x%08x OFFSET=%u CHKSIZE=%u%s\n",
val, val & 3,
((val >> 4) & 3) ?
1 << (((val >> 4) & 3) + 1) : 1,
- val & MCI_DMAEN ? " DMAEN" : "");
+ val & ATMCI_DMAEN ? " DMAEN" : "");
+ }
+ if (host->caps.has_cfg_reg) {
+ u32 val;
- val = buf[MCI_CFG / 4];
+ val = buf[ATMCI_CFG / 4];
seq_printf(s, "CFG:\t0x%08x%s%s%s%s\n",
val,
- val & MCI_CFG_FIFOMODE_1DATA ? " FIFOMODE_ONE_DATA" : "",
- val & MCI_CFG_FERRCTRL_COR ? " FERRCTRL_CLEAR_ON_READ" : "",
- val & MCI_CFG_HSMODE ? " HSMODE" : "",
- val & MCI_CFG_LSYNC ? " LSYNC" : "");
+ val & ATMCI_CFG_FIFOMODE_1DATA ? " FIFOMODE_ONE_DATA" : "",
+ val & ATMCI_CFG_FERRCTRL_COR ? " FERRCTRL_CLEAR_ON_READ" : "",
+ val & ATMCI_CFG_HSMODE ? " HSMODE" : "",
+ val & ATMCI_CFG_LSYNC ? " LSYNC" : "");
}
kfree(buf);
@@ -466,7 +477,7 @@ err:
dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
}
-static inline unsigned int ns_to_clocks(struct atmel_mci *host,
+static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
unsigned int ns)
{
return (ns * (host->bus_hz / 1000000) + 999) / 1000;
@@ -482,7 +493,8 @@ static void atmci_set_timeout(struct atmel_mci *host,
unsigned dtocyc;
unsigned dtomul;
- timeout = ns_to_clocks(host, data->timeout_ns) + data->timeout_clks;
+ timeout = atmci_ns_to_clocks(host, data->timeout_ns)
+ + data->timeout_clks;
for (dtomul = 0; dtomul < 8; dtomul++) {
unsigned shift = dtomul_to_shift[dtomul];
@@ -498,7 +510,7 @@ static void atmci_set_timeout(struct atmel_mci *host,
dev_vdbg(&slot->mmc->class_dev, "setting timeout to %u cycles\n",
dtocyc << dtomul_to_shift[dtomul]);
- mci_writel(host, DTOR, (MCI_DTOMUL(dtomul) | MCI_DTOCYC(dtocyc)));
+ atmci_writel(host, ATMCI_DTOR, (ATMCI_DTOMUL(dtomul) | ATMCI_DTOCYC(dtocyc)));
}
/*
@@ -512,13 +524,13 @@ static u32 atmci_prepare_command(struct mmc_host *mmc,
cmd->error = -EINPROGRESS;
- cmdr = MCI_CMDR_CMDNB(cmd->opcode);
+ cmdr = ATMCI_CMDR_CMDNB(cmd->opcode);
if (cmd->flags & MMC_RSP_PRESENT) {
if (cmd->flags & MMC_RSP_136)
- cmdr |= MCI_CMDR_RSPTYP_136BIT;
+ cmdr |= ATMCI_CMDR_RSPTYP_136BIT;
else
- cmdr |= MCI_CMDR_RSPTYP_48BIT;
+ cmdr |= ATMCI_CMDR_RSPTYP_48BIT;
}
/*
@@ -526,34 +538,34 @@ static u32 atmci_prepare_command(struct mmc_host *mmc,
* it's too difficult to determine whether this is an ACMD or
* not. Better make it 64.
*/
- cmdr |= MCI_CMDR_MAXLAT_64CYC;
+ cmdr |= ATMCI_CMDR_MAXLAT_64CYC;
if (mmc->ios.bus_mode == MMC_BUSMODE_OPENDRAIN)
- cmdr |= MCI_CMDR_OPDCMD;
+ cmdr |= ATMCI_CMDR_OPDCMD;
data = cmd->data;
if (data) {
- cmdr |= MCI_CMDR_START_XFER;
+ cmdr |= ATMCI_CMDR_START_XFER;
if (cmd->opcode == SD_IO_RW_EXTENDED) {
- cmdr |= MCI_CMDR_SDIO_BLOCK;
+ cmdr |= ATMCI_CMDR_SDIO_BLOCK;
} else {
if (data->flags & MMC_DATA_STREAM)
- cmdr |= MCI_CMDR_STREAM;
+ cmdr |= ATMCI_CMDR_STREAM;
else if (data->blocks > 1)
- cmdr |= MCI_CMDR_MULTI_BLOCK;
+ cmdr |= ATMCI_CMDR_MULTI_BLOCK;
else
- cmdr |= MCI_CMDR_BLOCK;
+ cmdr |= ATMCI_CMDR_BLOCK;
}
if (data->flags & MMC_DATA_READ)
- cmdr |= MCI_CMDR_TRDIR_READ;
+ cmdr |= ATMCI_CMDR_TRDIR_READ;
}
return cmdr;
}
-static void atmci_start_command(struct atmel_mci *host,
+static void atmci_send_command(struct atmel_mci *host,
struct mmc_command *cmd, u32 cmd_flags)
{
WARN_ON(host->cmd);
@@ -563,43 +575,119 @@ static void atmci_start_command(struct atmel_mci *host,
"start command: ARGR=0x%08x CMDR=0x%08x\n",
cmd->arg, cmd_flags);
- mci_writel(host, ARGR, cmd->arg);
- mci_writel(host, CMDR, cmd_flags);
+ atmci_writel(host, ATMCI_ARGR, cmd->arg);
+ atmci_writel(host, ATMCI_CMDR, cmd_flags);
}
-static void send_stop_cmd(struct atmel_mci *host, struct mmc_data *data)
+static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data)
{
- atmci_start_command(host, data->stop, host->stop_cmdr);
- mci_writel(host, IER, MCI_CMDRDY);
+ atmci_send_command(host, data->stop, host->stop_cmdr);
+ atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY);
}
-#ifdef CONFIG_MMC_ATMELMCI_DMA
-static void atmci_dma_cleanup(struct atmel_mci *host)
+/*
+ * Configure given PDC buffer taking care of alignement issues.
+ * Update host->data_size and host->sg.
+ */
+static void atmci_pdc_set_single_buf(struct atmel_mci *host,
+ enum atmci_xfer_dir dir, enum atmci_pdc_buf buf_nb)
+{
+ u32 pointer_reg, counter_reg;
+
+ if (dir == XFER_RECEIVE) {
+ pointer_reg = ATMEL_PDC_RPR;
+ counter_reg = ATMEL_PDC_RCR;
+ } else {
+ pointer_reg = ATMEL_PDC_TPR;
+ counter_reg = ATMEL_PDC_TCR;
+ }
+
+ if (buf_nb == PDC_SECOND_BUF) {
+ pointer_reg += ATMEL_PDC_SCND_BUF_OFF;
+ counter_reg += ATMEL_PDC_SCND_BUF_OFF;
+ }
+
+ atmci_writel(host, pointer_reg, sg_dma_address(host->sg));
+ if (host->data_size <= sg_dma_len(host->sg)) {
+ if (host->data_size & 0x3) {
+ /* If size is different from modulo 4, transfer bytes */
+ atmci_writel(host, counter_reg, host->data_size);
+ atmci_writel(host, ATMCI_MR, host->mode_reg | ATMCI_MR_PDCFBYTE);
+ } else {
+ /* Else transfer 32-bits words */
+ atmci_writel(host, counter_reg, host->data_size / 4);
+ }
+ host->data_size = 0;
+ } else {
+ /* We assume the size of a page is 32-bits aligned */
+ atmci_writel(host, counter_reg, sg_dma_len(host->sg) / 4);
+ host->data_size -= sg_dma_len(host->sg);
+ if (host->data_size)
+ host->sg = sg_next(host->sg);
+ }
+}
+
+/*
+ * Configure PDC buffer according to the data size ie configuring one or two
+ * buffers. Don't use this function if you want to configure only the second
+ * buffer. In this case, use atmci_pdc_set_single_buf.
+ */
+static void atmci_pdc_set_both_buf(struct atmel_mci *host, int dir)
{
- struct mmc_data *data = host->data;
+ atmci_pdc_set_single_buf(host, dir, PDC_FIRST_BUF);
+ if (host->data_size)
+ atmci_pdc_set_single_buf(host, dir, PDC_SECOND_BUF);
+}
+
+/*
+ * Unmap sg lists, called when transfer is finished.
+ */
+static void atmci_pdc_cleanup(struct atmel_mci *host)
+{
+ struct mmc_data *data = host->data;
if (data)
- dma_unmap_sg(host->dma.chan->device->dev,
- data->sg, data->sg_len,
- ((data->flags & MMC_DATA_WRITE)
- ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
+ dma_unmap_sg(&host->pdev->dev,
+ data->sg, data->sg_len,
+ ((data->flags & MMC_DATA_WRITE)
+ ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
}
-static void atmci_stop_dma(struct atmel_mci *host)
+/*
+ * Disable PDC transfers. Update pending flags to EVENT_XFER_COMPLETE after
+ * having received ATMCI_TXBUFE or ATMCI_RXBUFF interrupt. Enable ATMCI_NOTBUSY
+ * interrupt needed for both transfer directions.
+ */
+static void atmci_pdc_complete(struct atmel_mci *host)
{
- struct dma_chan *chan = host->data_chan;
+ atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+ atmci_pdc_cleanup(host);
- if (chan) {
- dmaengine_terminate_all(chan);
- atmci_dma_cleanup(host);
- } else {
- /* Data transfer was stopped by the interrupt handler */
+ /*
+ * If the card was removed, data will be NULL. No point trying
+ * to send the stop command or waiting for NBUSY in this case.
+ */
+ if (host->data) {
atmci_set_pending(host, EVENT_XFER_COMPLETE);
- mci_writel(host, IER, MCI_NOTBUSY);
+ tasklet_schedule(&host->tasklet);
+ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
}
}
-/* This function is called by the DMA driver from tasklet context. */
+static void atmci_dma_cleanup(struct atmel_mci *host)
+{
+ struct mmc_data *data = host->data;
+
+ if (data)
+ dma_unmap_sg(host->dma.chan->device->dev,
+ data->sg, data->sg_len,
+ ((data->flags & MMC_DATA_WRITE)
+ ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
+}
+
+/*
+ * This function is called by the DMA driver from tasklet context.
+ */
static void atmci_dma_complete(void *arg)
{
struct atmel_mci *host = arg;
@@ -607,9 +695,9 @@ static void atmci_dma_complete(void *arg)
dev_vdbg(&host->pdev->dev, "DMA complete\n");
- if (atmci_is_mci2())
+ if (host->caps.has_dma)
/* Disable DMA hardware handshaking on MCI */
- mci_writel(host, DMA, mci_readl(host, DMA) & ~MCI_DMAEN);
+ atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN);
atmci_dma_cleanup(host);
@@ -641,11 +729,93 @@ static void atmci_dma_complete(void *arg)
* completion callback" rule of the dma engine
* framework.
*/
- mci_writel(host, IER, MCI_NOTBUSY);
+ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
}
}
-static int
+/*
+ * Returns a mask of interrupt flags to be enabled after the whole
+ * request has been prepared.
+ */
+static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data)
+{
+ u32 iflags;
+
+ data->error = -EINPROGRESS;
+
+ host->sg = data->sg;
+ host->data = data;
+ host->data_chan = NULL;
+
+ iflags = ATMCI_DATA_ERROR_FLAGS;
+
+ /*
+ * Errata: MMC data write operation with less than 12
+ * bytes is impossible.
+ *
+ * Errata: MCI Transmit Data Register (TDR) FIFO
+ * corruption when length is not multiple of 4.
+ */
+ if (data->blocks * data->blksz < 12
+ || (data->blocks * data->blksz) & 3)
+ host->need_reset = true;
+
+ host->pio_offset = 0;
+ if (data->flags & MMC_DATA_READ)
+ iflags |= ATMCI_RXRDY;
+ else
+ iflags |= ATMCI_TXRDY;
+
+ return iflags;
+}
+
+/*
+ * Set interrupt flags and set block length into the MCI mode register even
+ * if this value is also accessible in the MCI block register. It seems to be
+ * necessary before the High Speed MCI version. It also map sg and configure
+ * PDC registers.
+ */
+static u32
+atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data)
+{
+ u32 iflags, tmp;
+ unsigned int sg_len;
+ enum dma_data_direction dir;
+
+ data->error = -EINPROGRESS;
+
+ host->data = data;
+ host->sg = data->sg;
+ iflags = ATMCI_DATA_ERROR_FLAGS;
+
+ /* Enable pdc mode */
+ atmci_writel(host, ATMCI_MR, host->mode_reg | ATMCI_MR_PDCMODE);
+
+ if (data->flags & MMC_DATA_READ) {
+ dir = DMA_FROM_DEVICE;
+ iflags |= ATMCI_ENDRX | ATMCI_RXBUFF;
+ } else {
+ dir = DMA_TO_DEVICE;
+ iflags |= ATMCI_ENDTX | ATMCI_TXBUFE;
+ }
+
+ /* Set BLKLEN */
+ tmp = atmci_readl(host, ATMCI_MR);
+ tmp &= 0x0000ffff;
+ tmp |= ATMCI_BLKLEN(data->blksz);
+ atmci_writel(host, ATMCI_MR, tmp);
+
+ /* Configure PDC */
+ host->data_size = data->blocks * data->blksz;
+ sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir);
+ if (host->data_size)
+ atmci_pdc_set_both_buf(host,
+ ((dir == DMA_FROM_DEVICE) ? XFER_RECEIVE : XFER_TRANSMIT));
+
+ return iflags;
+}
+
+static u32
atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
{
struct dma_chan *chan;
@@ -654,6 +824,15 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
unsigned int i;
enum dma_data_direction direction;
unsigned int sglen;
+ u32 iflags;
+
+ data->error = -EINPROGRESS;
+
+ WARN_ON(host->data);
+ host->sg = NULL;
+ host->data = data;
+
+ iflags = ATMCI_DATA_ERROR_FLAGS;
/*
* We don't do DMA on "complex" transfers, i.e. with
@@ -661,13 +840,13 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
* with all the DMA setup overhead for short transfers.
*/
if (data->blocks * data->blksz < ATMCI_DMA_THRESHOLD)
- return -EINVAL;
+ return atmci_prepare_data(host, data);
if (data->blksz & 3)
- return -EINVAL;
+ return atmci_prepare_data(host, data);
for_each_sg(data->sg, sg, data->sg_len, i) {
if (sg->offset & 3 || sg->length & 3)
- return -EINVAL;
+ return atmci_prepare_data(host, data);
}
/* If we don't have a channel, we can't do DMA */
@@ -678,8 +857,8 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
if (!chan)
return -ENODEV;
- if (atmci_is_mci2())
- mci_writel(host, DMA, MCI_DMA_CHKSIZE(3) | MCI_DMAEN);
+ if (host->caps.has_dma)
+ atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN);
if (data->flags & MMC_DATA_READ)
direction = DMA_FROM_DEVICE;
@@ -687,7 +866,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
direction = DMA_TO_DEVICE;
sglen = dma_map_sg(chan->device->dev, data->sg,
- data->sg_len, direction);
+ data->sg_len, direction);
desc = chan->device->device_prep_slave_sg(chan,
data->sg, sglen, direction,
@@ -699,13 +878,32 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
desc->callback = atmci_dma_complete;
desc->callback_param = host;
- return 0;
+ return iflags;
unmap_exit:
dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, direction);
return -ENOMEM;
}
-static void atmci_submit_data(struct atmel_mci *host)
+static void
+atmci_submit_data(struct atmel_mci *host, struct mmc_data *data)
+{
+ return;
+}
+
+/*
+ * Start PDC according to transfer direction.
+ */
+static void
+atmci_submit_data_pdc(struct atmel_mci *host, struct mmc_data *data)
+{
+ if (data->flags & MMC_DATA_READ)
+ atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
+ else
+ atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
+}
+
+static void
+atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data)
{
struct dma_chan *chan = host->data_chan;
struct dma_async_tx_descriptor *desc = host->dma.data_desc;
@@ -716,64 +914,39 @@ static void atmci_submit_data(struct atmel_mci *host)
}
}
-#else /* CONFIG_MMC_ATMELMCI_DMA */
-
-static int atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
-{
- return -ENOSYS;
-}
-
-static void atmci_submit_data(struct atmel_mci *host) {}
-
-static void atmci_stop_dma(struct atmel_mci *host)
+static void atmci_stop_transfer(struct atmel_mci *host)
{
- /* Data transfer was stopped by the interrupt handler */
atmci_set_pending(host, EVENT_XFER_COMPLETE);
- mci_writel(host, IER, MCI_NOTBUSY);
+ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
}
-#endif /* CONFIG_MMC_ATMELMCI_DMA */
-
/*
- * Returns a mask of interrupt flags to be enabled after the whole
- * request has been prepared.
+ * Stop data transfer because error(s) occured.
*/
-static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data)
+static void atmci_stop_transfer_pdc(struct atmel_mci *host)
{
- u32 iflags;
-
- data->error = -EINPROGRESS;
-
- WARN_ON(host->data);
- host->sg = NULL;
- host->data = data;
-
- iflags = ATMCI_DATA_ERROR_FLAGS;
- if (atmci_prepare_data_dma(host, data)) {
- host->data_chan = NULL;
+ atmci_set_pending(host, EVENT_XFER_COMPLETE);
+ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
+}
- /*
- * Errata: MMC data write operation with less than 12
- * bytes is impossible.
- *
- * Errata: MCI Transmit Data Register (TDR) FIFO
- * corruption when length is not multiple of 4.
- */
- if (data->blocks * data->blksz < 12
- || (data->blocks * data->blksz) & 3)
- host->need_reset = true;
+static void atmci_stop_transfer_dma(struct atmel_mci *host)
+{
+ struct dma_chan *chan = host->data_chan;
- host->sg = data->sg;
- host->pio_offset = 0;
- if (data->flags & MMC_DATA_READ)
- iflags |= MCI_RXRDY;
- else
- iflags |= MCI_TXRDY;
+ if (chan) {
+ dmaengine_terminate_all(chan);
+ atmci_dma_cleanup(host);
+ } else {
+ /* Data transfer was stopped by the interrupt handler */
+ atmci_set_pending(host, EVENT_XFER_COMPLETE);
+ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
}
-
- return iflags;
}
+/*
+ * Start a request: prepare data if needed, prepare the command and activate
+ * interrupts.
+ */
static void atmci_start_request(struct atmel_mci *host,
struct atmel_mci_slot *slot)
{
@@ -792,24 +965,24 @@ static void atmci_start_request(struct atmel_mci *host,
host->data_status = 0;
if (host->need_reset) {
- mci_writel(host, CR, MCI_CR_SWRST);
- mci_writel(host, CR, MCI_CR_MCIEN);
- mci_writel(host, MR, host->mode_reg);
- if (atmci_is_mci2())
- mci_writel(host, CFG, host->cfg_reg);
+ atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
+ atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
+ atmci_writel(host, ATMCI_MR, host->mode_reg);
+ if (host->caps.has_cfg_reg)
+ atmci_writel(host, ATMCI_CFG, host->cfg_reg);
host->need_reset = false;
}
- mci_writel(host, SDCR, slot->sdc_reg);
+ atmci_writel(host, ATMCI_SDCR, slot->sdc_reg);
- iflags = mci_readl(host, IMR);
- if (iflags & ~(MCI_SDIOIRQA | MCI_SDIOIRQB))
+ iflags = atmci_readl(host, ATMCI_IMR);
+ if (iflags & ~(ATMCI_SDIOIRQA | ATMCI_SDIOIRQB))
dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n",
iflags);
if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) {
/* Send init sequence (74 clock cycles) */
- mci_writel(host, CMDR, MCI_CMDR_SPCMD_INIT);
- while (!(mci_readl(host, SR) & MCI_CMDRDY))
+ atmci_writel(host, ATMCI_CMDR, ATMCI_CMDR_SPCMD_INIT);
+ while (!(atmci_readl(host, ATMCI_SR) & ATMCI_CMDRDY))
cpu_relax();
}
iflags = 0;
@@ -818,31 +991,31 @@ static void atmci_start_request(struct atmel_mci *host,
atmci_set_timeout(host, slot, data);
/* Must set block count/size before sending command */
- mci_writel(host, BLKR, MCI_BCNT(data->blocks)
- | MCI_BLKLEN(data->blksz));
+ atmci_writel(host, ATMCI_BLKR, ATMCI_BCNT(data->blocks)
+ | ATMCI_BLKLEN(data->blksz));
dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n",
- MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz));
+ ATMCI_BCNT(data->blocks) | ATMCI_BLKLEN(data->blksz));
- iflags |= atmci_prepare_data(host, data);
+ iflags |= host->prepare_data(host, data);
}
- iflags |= MCI_CMDRDY;
+ iflags |= ATMCI_CMDRDY;
cmd = mrq->cmd;
cmdflags = atmci_prepare_command(slot->mmc, cmd);
- atmci_start_command(host, cmd, cmdflags);
+ atmci_send_command(host, cmd, cmdflags);
if (data)
- atmci_submit_data(host);
+ host->submit_data(host, data);
if (mrq->stop) {
host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop);
- host->stop_cmdr |= MCI_CMDR_STOP_XFER;
+ host->stop_cmdr |= ATMCI_CMDR_STOP_XFER;
if (!(data->flags & MMC_DATA_WRITE))
- host->stop_cmdr |= MCI_CMDR_TRDIR_READ;
+ host->stop_cmdr |= ATMCI_CMDR_TRDIR_READ;
if (data->flags & MMC_DATA_STREAM)
- host->stop_cmdr |= MCI_CMDR_STREAM;
+ host->stop_cmdr |= ATMCI_CMDR_STREAM;
else
- host->stop_cmdr |= MCI_CMDR_MULTI_BLOCK;
+ host->stop_cmdr |= ATMCI_CMDR_MULTI_BLOCK;
}
/*
@@ -851,7 +1024,7 @@ static void atmci_start_request(struct atmel_mci *host,
* conditions (e.g. command and data complete, but stop not
* prepared yet.)
*/
- mci_writel(host, IER, iflags);
+ atmci_writel(host, ATMCI_IER, iflags);
}
static void atmci_queue_request(struct atmel_mci *host,
@@ -909,13 +1082,13 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct atmel_mci *host = slot->host;
unsigned int i;
- slot->sdc_reg &= ~MCI_SDCBUS_MASK;
+ slot->sdc_reg &= ~ATMCI_SDCBUS_MASK;
switch (ios->bus_width) {
case MMC_BUS_WIDTH_1:
- slot->sdc_reg |= MCI_SDCBUS_1BIT;
+ slot->sdc_reg |= ATMCI_SDCBUS_1BIT;
break;
case MMC_BUS_WIDTH_4:
- slot->sdc_reg |= MCI_SDCBUS_4BIT;
+ slot->sdc_reg |= ATMCI_SDCBUS_4BIT;
break;
}
@@ -926,10 +1099,10 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
spin_lock_bh(&host->lock);
if (!host->mode_reg) {
clk_enable(host->mck);
- mci_writel(host, CR, MCI_CR_SWRST);
- mci_writel(host, CR, MCI_CR_MCIEN);
- if (atmci_is_mci2())
- mci_writel(host, CFG, host->cfg_reg);
+ atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
+ atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
+ if (host->caps.has_cfg_reg)
+ atmci_writel(host, ATMCI_CFG, host->cfg_reg);
}
/*
@@ -937,7 +1110,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
* core ios update when finding the minimum.
*/
slot->clock = ios->clock;
- for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
if (host->slot[i] && host->slot[i]->clock
&& host->slot[i]->clock < clock_min)
clock_min = host->slot[i]->clock;
@@ -952,28 +1125,28 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
clkdiv = 255;
}
- host->mode_reg = MCI_MR_CLKDIV(clkdiv);
+ host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
/*
* WRPROOF and RDPROOF prevent overruns/underruns by
* stopping the clock when the FIFO is full/empty.
* This state is not expected to last for long.
*/
- if (mci_has_rwproof())
- host->mode_reg |= (MCI_MR_WRPROOF | MCI_MR_RDPROOF);
+ if (host->caps.has_rwproof)
+ host->mode_reg |= (ATMCI_MR_WRPROOF | ATMCI_MR_RDPROOF);
- if (atmci_is_mci2()) {
+ if (host->caps.has_cfg_reg) {
/* setup High Speed mode in relation with card capacity */
if (ios->timing == MMC_TIMING_SD_HS)
- host->cfg_reg |= MCI_CFG_HSMODE;
+ host->cfg_reg |= ATMCI_CFG_HSMODE;
else
- host->cfg_reg &= ~MCI_CFG_HSMODE;
+ host->cfg_reg &= ~ATMCI_CFG_HSMODE;
}
if (list_empty(&host->queue)) {
- mci_writel(host, MR, host->mode_reg);
- if (atmci_is_mci2())
- mci_writel(host, CFG, host->cfg_reg);
+ atmci_writel(host, ATMCI_MR, host->mode_reg);
+ if (host->caps.has_cfg_reg)
+ atmci_writel(host, ATMCI_CFG, host->cfg_reg);
} else {
host->need_clock_update = true;
}
@@ -984,16 +1157,16 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
spin_lock_bh(&host->lock);
slot->clock = 0;
- for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
if (host->slot[i] && host->slot[i]->clock) {
any_slot_active = true;
break;
}
}
if (!any_slot_active) {
- mci_writel(host, CR, MCI_CR_MCIDIS);
+ atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
if (host->mode_reg) {
- mci_readl(host, MR);
+ atmci_readl(host, ATMCI_MR);
clk_disable(host->mck);
}
host->mode_reg = 0;
@@ -1057,9 +1230,9 @@ static void atmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
struct atmel_mci *host = slot->host;
if (enable)
- mci_writel(host, IER, slot->sdio_irq);
+ atmci_writel(host, ATMCI_IER, slot->sdio_irq);
else
- mci_writel(host, IDR, slot->sdio_irq);
+ atmci_writel(host, ATMCI_IDR, slot->sdio_irq);
}
static const struct mmc_host_ops atmci_ops = {
@@ -1086,9 +1259,9 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq)
* busy transferring data.
*/
if (host->need_clock_update) {
- mci_writel(host, MR, host->mode_reg);
- if (atmci_is_mci2())
- mci_writel(host, CFG, host->cfg_reg);
+ atmci_writel(host, ATMCI_MR, host->mode_reg);
+ if (host->caps.has_cfg_reg)
+ atmci_writel(host, ATMCI_CFG, host->cfg_reg);
}
host->cur_slot->mrq = NULL;
@@ -1117,16 +1290,16 @@ static void atmci_command_complete(struct atmel_mci *host,
u32 status = host->cmd_status;
/* Read the response from the card (up to 16 bytes) */
- cmd->resp[0] = mci_readl(host, RSPR);
- cmd->resp[1] = mci_readl(host, RSPR);
- cmd->resp[2] = mci_readl(host, RSPR);
- cmd->resp[3] = mci_readl(host, RSPR);
+ cmd->resp[0] = atmci_readl(host, ATMCI_RSPR);
+ cmd->resp[1] = atmci_readl(host, ATMCI_RSPR);
+ cmd->resp[2] = atmci_readl(host, ATMCI_RSPR);
+ cmd->resp[3] = atmci_readl(host, ATMCI_RSPR);
- if (status & MCI_RTOE)
+ if (status & ATMCI_RTOE)
cmd->error = -ETIMEDOUT;
- else if ((cmd->flags & MMC_RSP_CRC) && (status & MCI_RCRCE))
+ else if ((cmd->flags & MMC_RSP_CRC) && (status & ATMCI_RCRCE))
cmd->error = -EILSEQ;
- else if (status & (MCI_RINDE | MCI_RDIRE | MCI_RENDE))
+ else if (status & (ATMCI_RINDE | ATMCI_RDIRE | ATMCI_RENDE))
cmd->error = -EIO;
else
cmd->error = 0;
@@ -1136,10 +1309,10 @@ static void atmci_command_complete(struct atmel_mci *host,
"command error: status=0x%08x\n", status);
if (cmd->data) {
- atmci_stop_dma(host);
+ host->stop_transfer(host);
host->data = NULL;
- mci_writel(host, IDR, MCI_NOTBUSY
- | MCI_TXRDY | MCI_RXRDY
+ atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY
+ | ATMCI_TXRDY | ATMCI_RXRDY
| ATMCI_DATA_ERROR_FLAGS);
}
}
@@ -1191,11 +1364,11 @@ static void atmci_detect_change(unsigned long data)
* Reset controller to terminate any ongoing
* commands or data transfers.
*/
- mci_writel(host, CR, MCI_CR_SWRST);
- mci_writel(host, CR, MCI_CR_MCIEN);
- mci_writel(host, MR, host->mode_reg);
- if (atmci_is_mci2())
- mci_writel(host, CFG, host->cfg_reg);
+ atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
+ atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
+ atmci_writel(host, ATMCI_MR, host->mode_reg);
+ if (host->caps.has_cfg_reg)
+ atmci_writel(host, ATMCI_CFG, host->cfg_reg);
host->data = NULL;
host->cmd = NULL;
@@ -1210,7 +1383,7 @@ static void atmci_detect_change(unsigned long data)
/* fall through */
case STATE_SENDING_DATA:
mrq->data->error = -ENOMEDIUM;
- atmci_stop_dma(host);
+ host->stop_transfer(host);
break;
case STATE_DATA_BUSY:
case STATE_DATA_ERROR:
@@ -1261,7 +1434,7 @@ static void atmci_tasklet_func(unsigned long priv)
dev_vdbg(&host->pdev->dev,
"tasklet: state %u pending/completed/mask %lx/%lx/%x\n",
state, host->pending_events, host->completed_events,
- mci_readl(host, IMR));
+ atmci_readl(host, ATMCI_IMR));
do {
prev_state = state;
@@ -1289,9 +1462,9 @@ static void atmci_tasklet_func(unsigned long priv)
case STATE_SENDING_DATA:
if (atmci_test_and_clear_pending(host,
EVENT_DATA_ERROR)) {
- atmci_stop_dma(host);
+ host->stop_transfer(host);
if (data->stop)
- send_stop_cmd(host, data);
+ atmci_send_stop_cmd(host, data);
state = STATE_DATA_ERROR;
break;
}
@@ -1313,11 +1486,11 @@ static void atmci_tasklet_func(unsigned long priv)
atmci_set_completed(host, EVENT_DATA_COMPLETE);
status = host->data_status;
if (unlikely(status & ATMCI_DATA_ERROR_FLAGS)) {
- if (status & MCI_DTOE) {
+ if (status & ATMCI_DTOE) {
dev_dbg(&host->pdev->dev,
"data timeout error\n");
data->error = -ETIMEDOUT;
- } else if (status & MCI_DCRCE) {
+ } else if (status & ATMCI_DCRCE) {
dev_dbg(&host->pdev->dev,
"data CRC error\n");
data->error = -EILSEQ;
@@ -1330,7 +1503,7 @@ static void atmci_tasklet_func(unsigned long priv)
} else {
data->bytes_xfered = data->blocks * data->blksz;
data->error = 0;
- mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS);
+ atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS);
}
if (!data->stop) {
@@ -1340,7 +1513,7 @@ static void atmci_tasklet_func(unsigned long priv)
prev_state = state = STATE_SENDING_STOP;
if (!data->error)
- send_stop_cmd(host, data);
+ atmci_send_stop_cmd(host, data);
/* fall through */
case STATE_SENDING_STOP:
@@ -1380,7 +1553,7 @@ static void atmci_read_data_pio(struct atmel_mci *host)
unsigned int nbytes = 0;
do {
- value = mci_readl(host, RDR);
+ value = atmci_readl(host, ATMCI_RDR);
if (likely(offset + 4 <= sg->length)) {
put_unaligned(value, (u32 *)(buf + offset));
@@ -1412,9 +1585,9 @@ static void atmci_read_data_pio(struct atmel_mci *host)
nbytes += offset;
}
- status = mci_readl(host, SR);
+ status = atmci_readl(host, ATMCI_SR);
if (status & ATMCI_DATA_ERROR_FLAGS) {
- mci_writel(host, IDR, (MCI_NOTBUSY | MCI_RXRDY
+ atmci_writel(host, ATMCI_IDR, (ATMCI_NOTBUSY | ATMCI_RXRDY
| ATMCI_DATA_ERROR_FLAGS));
host->data_status = status;
data->bytes_xfered += nbytes;
@@ -1423,7 +1596,7 @@ static void atmci_read_data_pio(struct atmel_mci *host)
tasklet_schedule(&host->tasklet);
return;
}
- } while (status & MCI_RXRDY);
+ } while (status & ATMCI_RXRDY);
host->pio_offset = offset;
data->bytes_xfered += nbytes;
@@ -1431,8 +1604,8 @@ static void atmci_read_data_pio(struct atmel_mci *host)
return;
done:
- mci_writel(host, IDR, MCI_RXRDY);
- mci_writel(host, IER, MCI_NOTBUSY);
+ atmci_writel(host, ATMCI_IDR, ATMCI_RXRDY);
+ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
data->bytes_xfered += nbytes;
smp_wmb();
atmci_set_pending(host, EVENT_XFER_COMPLETE);
@@ -1451,7 +1624,7 @@ static void atmci_write_data_pio(struct atmel_mci *host)
do {
if (likely(offset + 4 <= sg->length)) {
value = get_unaligned((u32 *)(buf + offset));
- mci_writel(host, TDR, value);
+ atmci_writel(host, ATMCI_TDR, value);
offset += 4;
nbytes += 4;
@@ -1472,20 +1645,20 @@ static void atmci_write_data_pio(struct atmel_mci *host)
host->sg = sg = sg_next(sg);
if (!sg) {
- mci_writel(host, TDR, value);
+ atmci_writel(host, ATMCI_TDR, value);
goto done;
}
offset = 4 - remaining;
buf = sg_virt(sg);
memcpy((u8 *)&value + remaining, buf, offset);
- mci_writel(host, TDR, value);
+ atmci_writel(host, ATMCI_TDR, value);
nbytes += offset;
}
- status = mci_readl(host, SR);
+ status = atmci_readl(host, ATMCI_SR);
if (status & ATMCI_DATA_ERROR_FLAGS) {
- mci_writel(host, IDR, (MCI_NOTBUSY | MCI_TXRDY
+ atmci_writel(host, ATMCI_IDR, (ATMCI_NOTBUSY | ATMCI_TXRDY
| ATMCI_DATA_ERROR_FLAGS));
host->data_status = status;
data->bytes_xfered += nbytes;
@@ -1494,7 +1667,7 @@ static void atmci_write_data_pio(struct atmel_mci *host)
tasklet_schedule(&host->tasklet);
return;
}
- } while (status & MCI_TXRDY);
+ } while (status & ATMCI_TXRDY);
host->pio_offset = offset;
data->bytes_xfered += nbytes;
@@ -1502,8 +1675,8 @@ static void atmci_write_data_pio(struct atmel_mci *host)
return;
done:
- mci_writel(host, IDR, MCI_TXRDY);
- mci_writel(host, IER, MCI_NOTBUSY);
+ atmci_writel(host, ATMCI_IDR, ATMCI_TXRDY);
+ atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
data->bytes_xfered += nbytes;
smp_wmb();
atmci_set_pending(host, EVENT_XFER_COMPLETE);
@@ -1511,7 +1684,7 @@ done:
static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status)
{
- mci_writel(host, IDR, MCI_CMDRDY);
+ atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY);
host->cmd_status = status;
smp_wmb();
@@ -1523,7 +1696,7 @@ static void atmci_sdio_interrupt(struct atmel_mci *host, u32 status)
{
int i;
- for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
struct atmel_mci_slot *slot = host->slot[i];
if (slot && (status & slot->sdio_irq)) {
mmc_signal_sdio_irq(slot->mmc);
@@ -1539,40 +1712,92 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
unsigned int pass_count = 0;
do {
- status = mci_readl(host, SR);
- mask = mci_readl(host, IMR);
+ status = atmci_readl(host, ATMCI_SR);
+ mask = atmci_readl(host, ATMCI_IMR);
pending = status & mask;
if (!pending)
break;
if (pending & ATMCI_DATA_ERROR_FLAGS) {
- mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS
- | MCI_RXRDY | MCI_TXRDY);
- pending &= mci_readl(host, IMR);
+ atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS
+ | ATMCI_RXRDY | ATMCI_TXRDY);
+ pending &= atmci_readl(host, ATMCI_IMR);
host->data_status = status;
smp_wmb();
atmci_set_pending(host, EVENT_DATA_ERROR);
tasklet_schedule(&host->tasklet);
}
- if (pending & MCI_NOTBUSY) {
- mci_writel(host, IDR,
- ATMCI_DATA_ERROR_FLAGS | MCI_NOTBUSY);
+
+ if (pending & ATMCI_TXBUFE) {
+ atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE);
+ atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
+ /*
+ * We can receive this interruption before having configured
+ * the second pdc buffer, so we need to reconfigure first and
+ * second buffers again
+ */
+ if (host->data_size) {
+ atmci_pdc_set_both_buf(host, XFER_TRANSMIT);
+ atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
+ atmci_writel(host, ATMCI_IER, ATMCI_TXBUFE);
+ } else {
+ atmci_pdc_complete(host);
+ }
+ } else if (pending & ATMCI_ENDTX) {
+ atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
+
+ if (host->data_size) {
+ atmci_pdc_set_single_buf(host,
+ XFER_TRANSMIT, PDC_SECOND_BUF);
+ atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
+ }
+ }
+
+ if (pending & ATMCI_RXBUFF) {
+ atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF);
+ atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
+ /*
+ * We can receive this interruption before having configured
+ * the second pdc buffer, so we need to reconfigure first and
+ * second buffers again
+ */
+ if (host->data_size) {
+ atmci_pdc_set_both_buf(host, XFER_RECEIVE);
+ atmci_writel(host, ATMCI_IER, ATMCI_ENDRX);
+ atmci_writel(host, ATMCI_IER, ATMCI_RXBUFF);
+ } else {
+ atmci_pdc_complete(host);
+ }
+ } else if (pending & ATMCI_ENDRX) {
+ atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
+
+ if (host->data_size) {
+ atmci_pdc_set_single_buf(host,
+ XFER_RECEIVE, PDC_SECOND_BUF);
+ atmci_writel(host, ATMCI_IER, ATMCI_ENDRX);
+ }
+ }
+
+
+ if (pending & ATMCI_NOTBUSY) {
+ atmci_writel(host, ATMCI_IDR,
+ ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY);
if (!host->data_status)
host->data_status = status;
smp_wmb();
atmci_set_pending(host, EVENT_DATA_COMPLETE);
tasklet_schedule(&host->tasklet);
}
- if (pending & MCI_RXRDY)
+ if (pending & ATMCI_RXRDY)
atmci_read_data_pio(host);
- if (pending & MCI_TXRDY)
+ if (pending & ATMCI_TXRDY)
atmci_write_data_pio(host);
- if (pending & MCI_CMDRDY)
+ if (pending & ATMCI_CMDRDY)
atmci_cmd_interrupt(host, status);
- if (pending & (MCI_SDIOIRQA | MCI_SDIOIRQB))
+ if (pending & (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB))
atmci_sdio_interrupt(host, status);
} while (pass_count++ < 5);
@@ -1621,7 +1846,7 @@ static int __init atmci_init_slot(struct atmel_mci *host,
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
if (sdio_irq)
mmc->caps |= MMC_CAP_SDIO_IRQ;
- if (atmci_is_mci2())
+ if (host->caps.has_highspeed)
mmc->caps |= MMC_CAP_SD_HIGHSPEED;
if (slot_data->bus_width >= 4)
mmc->caps |= MMC_CAP_4_BIT_DATA;
@@ -1704,8 +1929,7 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot,
mmc_free_host(slot->mmc);
}
-#ifdef CONFIG_MMC_ATMELMCI_DMA
-static bool filter(struct dma_chan *chan, void *slave)
+static bool atmci_filter(struct dma_chan *chan, void *slave)
{
struct mci_dma_data *sl = slave;
@@ -1730,14 +1954,14 @@ static void atmci_configure_dma(struct atmel_mci *host)
dma_cap_mask_t mask;
setup_dma_addr(pdata->dma_slave,
- host->mapbase + MCI_TDR,
- host->mapbase + MCI_RDR);
+ host->mapbase + ATMCI_TDR,
+ host->mapbase + ATMCI_RDR);
/* Try to grab a DMA channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
host->dma.chan =
- dma_request_channel(mask, filter, pdata->dma_slave);
+ dma_request_channel(mask, atmci_filter, pdata->dma_slave);
}
if (!host->dma.chan)
dev_notice(&host->pdev->dev, "DMA not available, using PIO\n");
@@ -1746,9 +1970,60 @@ static void atmci_configure_dma(struct atmel_mci *host)
"Using %s for DMA transfers\n",
dma_chan_name(host->dma.chan));
}
+
+static inline unsigned int atmci_get_version(struct atmel_mci *host)
+{
+ return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
+}
+
+/*
+ * HSMCI (High Speed MCI) module is not fully compatible with MCI module.
+ * HSMCI provides DMA support and a new config register but no more supports
+ * PDC.
+ */
+static void __init atmci_get_cap(struct atmel_mci *host)
+{
+ unsigned int version;
+
+ version = atmci_get_version(host);
+ dev_info(&host->pdev->dev,
+ "version: 0x%x\n", version);
+
+ host->caps.has_dma = 0;
+ host->caps.has_pdc = 0;
+ host->caps.has_cfg_reg = 0;
+ host->caps.has_cstor_reg = 0;
+ host->caps.has_highspeed = 0;
+ host->caps.has_rwproof = 0;
+
+ /* keep only major version number */
+ switch (version & 0xf00) {
+ case 0x100:
+ case 0x200:
+ host->caps.has_pdc = 1;
+ host->caps.has_rwproof = 1;
+ break;
+ case 0x300:
+ case 0x400:
+ case 0x500:
+#ifdef CONFIG_AT_HDMAC
+ host->caps.has_dma = 1;
#else
-static void atmci_configure_dma(struct atmel_mci *host) {}
+ host->caps.has_dma = 0;
+ dev_info(&host->pdev->dev,
+ "has dma capability but dma engine is not selected, then use pio\n");
#endif
+ host->caps.has_cfg_reg = 1;
+ host->caps.has_cstor_reg = 1;
+ host->caps.has_highspeed = 1;
+ host->caps.has_rwproof = 1;
+ break;
+ default:
+ dev_warn(&host->pdev->dev,
+ "Unmanaged mci version, set minimum capabilities\n");
+ break;
+ }
+}
static int __init atmci_probe(struct platform_device *pdev)
{
@@ -1789,7 +2064,7 @@ static int __init atmci_probe(struct platform_device *pdev)
goto err_ioremap;
clk_enable(host->mck);
- mci_writel(host, CR, MCI_CR_SWRST);
+ atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
host->bus_hz = clk_get_rate(host->mck);
clk_disable(host->mck);
@@ -1801,7 +2076,27 @@ static int __init atmci_probe(struct platform_device *pdev)
if (ret)
goto err_request_irq;
- atmci_configure_dma(host);
+ /* Get MCI capabilities and set operations according to it */
+ atmci_get_cap(host);
+ if (host->caps.has_dma) {
+ dev_info(&pdev->dev, "using DMA\n");
+ host->prepare_data = &atmci_prepare_data_dma;
+ host->submit_data = &atmci_submit_data_dma;
+ host->stop_transfer = &atmci_stop_transfer_dma;
+ } else if (host->caps.has_pdc) {
+ dev_info(&pdev->dev, "using PDC\n");
+ host->prepare_data = &atmci_prepare_data_pdc;
+ host->submit_data = &atmci_submit_data_pdc;
+ host->stop_transfer = &atmci_stop_transfer_pdc;
+ } else {
+ dev_info(&pdev->dev, "no DMA, no PDC\n");
+ host->prepare_data = &atmci_prepare_data;
+ host->submit_data = &atmci_submit_data;
+ host->stop_transfer = &atmci_stop_transfer;
+ }
+
+ if (host->caps.has_dma)
+ atmci_configure_dma(host);
platform_set_drvdata(pdev, host);
@@ -1810,13 +2105,13 @@ static int __init atmci_probe(struct platform_device *pdev)
ret = -ENODEV;
if (pdata->slot[0].bus_width) {
ret = atmci_init_slot(host, &pdata->slot[0],
- 0, MCI_SDCSEL_SLOT_A, MCI_SDIOIRQA);
+ 0, ATMCI_SDCSEL_SLOT_A, ATMCI_SDIOIRQA);
if (!ret)
nr_slots++;
}
if (pdata->slot[1].bus_width) {
ret = atmci_init_slot(host, &pdata->slot[1],
- 1, MCI_SDCSEL_SLOT_B, MCI_SDIOIRQB);
+ 1, ATMCI_SDCSEL_SLOT_B, ATMCI_SDIOIRQB);
if (!ret)
nr_slots++;
}
@@ -1833,10 +2128,8 @@ static int __init atmci_probe(struct platform_device *pdev)
return 0;
err_init_slot:
-#ifdef CONFIG_MMC_ATMELMCI_DMA
if (host->dma.chan)
dma_release_channel(host->dma.chan);
-#endif
free_irq(irq, host);
err_request_irq:
iounmap(host->regs);
@@ -1854,15 +2147,15 @@ static int __exit atmci_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
- for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
if (host->slot[i])
atmci_cleanup_slot(host->slot[i], i);
}
clk_enable(host->mck);
- mci_writel(host, IDR, ~0UL);
- mci_writel(host, CR, MCI_CR_MCIDIS);
- mci_readl(host, SR);
+ atmci_writel(host, ATMCI_IDR, ~0UL);
+ atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
+ atmci_readl(host, ATMCI_SR);
clk_disable(host->mck);
#ifdef CONFIG_MMC_ATMELMCI_DMA
@@ -1885,7 +2178,7 @@ static int atmci_suspend(struct device *dev)
struct atmel_mci *host = dev_get_drvdata(dev);
int i;
- for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
struct atmel_mci_slot *slot = host->slot[i];
int ret;
@@ -1916,7 +2209,7 @@ static int atmci_resume(struct device *dev)
int i;
int ret = 0;
- for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+ for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
struct atmel_mci_slot *slot = host->slot[i];
int err;
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index ef72e874ca36..707bc7dddd22 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -55,7 +55,7 @@
#ifdef DEBUG
#define DBG(fmt, idx, args...) \
- printk(KERN_DEBUG "au1xmmc(%d): DEBUG: " fmt, idx, ##args)
+ pr_debug("au1xmmc(%d): DEBUG: " fmt, idx, ##args)
#else
#define DBG(fmt, idx, args...) do {} while (0)
#endif
@@ -268,7 +268,7 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
mmccmd |= SD_CMD_RT_3;
break;
default:
- printk(KERN_INFO "au1xmmc: unhandled response type %02x\n",
+ pr_info("au1xmmc: unhandled response type %02x\n",
mmc_resp_type(cmd));
return -EINVAL;
}
@@ -1031,7 +1031,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
#ifdef CONFIG_SOC_AU1200
ret = au1xmmc_dbdma_init(host);
if (ret)
- printk(KERN_INFO DRIVER_NAME ": DBDMA init failed; using PIO\n");
+ pr_info(DRIVER_NAME ": DBDMA init failed; using PIO\n");
#endif
#ifdef CONFIG_LEDS_CLASS
@@ -1056,7 +1056,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
- printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
+ pr_info(DRIVER_NAME ": MMC Controller %d set up at %8.8X"
" (mode=%s)\n", pdev->id, host->iobase,
host->flags & HOST_F_DMA ? "dma" : "pio");
@@ -1188,7 +1188,7 @@ static int __init au1xmmc_init(void)
*/
memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
if (!memid)
- printk(KERN_ERR "au1xmmc: cannot add memory dbdma dev\n");
+ pr_err("au1xmmc: cannot add memory dbdma dev\n");
#endif
return platform_driver_register(&au1xmmc_driver);
}
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 0076c7448fe6..64a8325a4a8a 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -807,12 +807,25 @@ static void calculate_clk_divider(struct mmc_host *mmc, struct mmc_ios *ios)
static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct mmc_davinci_host *host = mmc_priv(mmc);
+ struct platform_device *pdev = to_platform_device(mmc->parent);
+ struct davinci_mmc_config *config = pdev->dev.platform_data;
dev_dbg(mmc_dev(host->mmc),
"clock %dHz busmode %d powermode %d Vdd %04x\n",
ios->clock, ios->bus_mode, ios->power_mode,
ios->vdd);
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+ if (config && config->set_power)
+ config->set_power(pdev->id, false);
+ break;
+ case MMC_POWER_UP:
+ if (config && config->set_power)
+ config->set_power(pdev->id, true);
+ break;
+ }
+
switch (ios->bus_width) {
case MMC_BUS_WIDTH_8:
dev_dbg(mmc_dev(host->mmc), "Enabling 8 bit mode\n");
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index ff0f714b012c..3aaeb0841914 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -764,11 +764,29 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
return present;
}
+static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
+{
+ struct dw_mci_slot *slot = mmc_priv(mmc);
+ struct dw_mci *host = slot->host;
+ u32 int_mask;
+
+ /* Enable/disable Slot Specific SDIO interrupt */
+ int_mask = mci_readl(host, INTMASK);
+ if (enb) {
+ mci_writel(host, INTMASK,
+ (int_mask | (1 << SDMMC_INT_SDIO(slot->id))));
+ } else {
+ mci_writel(host, INTMASK,
+ (int_mask & ~(1 << SDMMC_INT_SDIO(slot->id))));
+ }
+}
+
static const struct mmc_host_ops dw_mci_ops = {
- .request = dw_mci_request,
- .set_ios = dw_mci_set_ios,
- .get_ro = dw_mci_get_ro,
- .get_cd = dw_mci_get_cd,
+ .request = dw_mci_request,
+ .set_ios = dw_mci_set_ios,
+ .get_ro = dw_mci_get_ro,
+ .get_cd = dw_mci_get_cd,
+ .enable_sdio_irq = dw_mci_enable_sdio_irq,
};
static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
@@ -1025,7 +1043,8 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
buf += len;
cnt -= len;
if (!sg_next(host->sg) || host->part_buf_count == 2) {
- mci_writew(host, DATA, host->part_buf16);
+ mci_writew(host, DATA(host->data_offset),
+ host->part_buf16);
host->part_buf_count = 0;
}
}
@@ -1042,21 +1061,23 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
cnt -= len;
/* push data from aligned buffer into fifo */
for (i = 0; i < items; ++i)
- mci_writew(host, DATA, aligned_buf[i]);
+ mci_writew(host, DATA(host->data_offset),
+ aligned_buf[i]);
}
} else
#endif
{
u16 *pdata = buf;
for (; cnt >= 2; cnt -= 2)
- mci_writew(host, DATA, *pdata++);
+ mci_writew(host, DATA(host->data_offset), *pdata++);
buf = pdata;
}
/* put anything remaining in the part_buf */
if (cnt) {
dw_mci_set_part_bytes(host, buf, cnt);
if (!sg_next(host->sg))
- mci_writew(host, DATA, host->part_buf16);
+ mci_writew(host, DATA(host->data_offset),
+ host->part_buf16);
}
}
@@ -1071,7 +1092,8 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
int items = len >> 1;
int i;
for (i = 0; i < items; ++i)
- aligned_buf[i] = mci_readw(host, DATA);
+ aligned_buf[i] = mci_readw(host,
+ DATA(host->data_offset));
/* memcpy from aligned buffer into output buffer */
memcpy(buf, aligned_buf, len);
buf += len;
@@ -1082,11 +1104,11 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
{
u16 *pdata = buf;
for (; cnt >= 2; cnt -= 2)
- *pdata++ = mci_readw(host, DATA);
+ *pdata++ = mci_readw(host, DATA(host->data_offset));
buf = pdata;
}
if (cnt) {
- host->part_buf16 = mci_readw(host, DATA);
+ host->part_buf16 = mci_readw(host, DATA(host->data_offset));
dw_mci_pull_final_bytes(host, buf, cnt);
}
}
@@ -1099,7 +1121,8 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
buf += len;
cnt -= len;
if (!sg_next(host->sg) || host->part_buf_count == 4) {
- mci_writel(host, DATA, host->part_buf32);
+ mci_writel(host, DATA(host->data_offset),
+ host->part_buf32);
host->part_buf_count = 0;
}
}
@@ -1116,21 +1139,23 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
cnt -= len;
/* push data from aligned buffer into fifo */
for (i = 0; i < items; ++i)
- mci_writel(host, DATA, aligned_buf[i]);
+ mci_writel(host, DATA(host->data_offset),
+ aligned_buf[i]);
}
} else
#endif
{
u32 *pdata = buf;
for (; cnt >= 4; cnt -= 4)
- mci_writel(host, DATA, *pdata++);
+ mci_writel(host, DATA(host->data_offset), *pdata++);
buf = pdata;
}
/* put anything remaining in the part_buf */
if (cnt) {
dw_mci_set_part_bytes(host, buf, cnt);
if (!sg_next(host->sg))
- mci_writel(host, DATA, host->part_buf32);
+ mci_writel(host, DATA(host->data_offset),
+ host->part_buf32);
}
}
@@ -1145,7 +1170,8 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
int items = len >> 2;
int i;
for (i = 0; i < items; ++i)
- aligned_buf[i] = mci_readl(host, DATA);
+ aligned_buf[i] = mci_readl(host,
+ DATA(host->data_offset));
/* memcpy from aligned buffer into output buffer */
memcpy(buf, aligned_buf, len);
buf += len;
@@ -1156,11 +1182,11 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
{
u32 *pdata = buf;
for (; cnt >= 4; cnt -= 4)
- *pdata++ = mci_readl(host, DATA);
+ *pdata++ = mci_readl(host, DATA(host->data_offset));
buf = pdata;
}
if (cnt) {
- host->part_buf32 = mci_readl(host, DATA);
+ host->part_buf32 = mci_readl(host, DATA(host->data_offset));
dw_mci_pull_final_bytes(host, buf, cnt);
}
}
@@ -1173,7 +1199,8 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
buf += len;
cnt -= len;
if (!sg_next(host->sg) || host->part_buf_count == 8) {
- mci_writew(host, DATA, host->part_buf);
+ mci_writew(host, DATA(host->data_offset),
+ host->part_buf);
host->part_buf_count = 0;
}
}
@@ -1190,21 +1217,23 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
cnt -= len;
/* push data from aligned buffer into fifo */
for (i = 0; i < items; ++i)
- mci_writeq(host, DATA, aligned_buf[i]);
+ mci_writeq(host, DATA(host->data_offset),
+ aligned_buf[i]);
}
} else
#endif
{
u64 *pdata = buf;
for (; cnt >= 8; cnt -= 8)
- mci_writeq(host, DATA, *pdata++);
+ mci_writeq(host, DATA(host->data_offset), *pdata++);
buf = pdata;
}
/* put anything remaining in the part_buf */
if (cnt) {
dw_mci_set_part_bytes(host, buf, cnt);
if (!sg_next(host->sg))
- mci_writeq(host, DATA, host->part_buf);
+ mci_writeq(host, DATA(host->data_offset),
+ host->part_buf);
}
}
@@ -1219,7 +1248,8 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
int items = len >> 3;
int i;
for (i = 0; i < items; ++i)
- aligned_buf[i] = mci_readq(host, DATA);
+ aligned_buf[i] = mci_readq(host,
+ DATA(host->data_offset));
/* memcpy from aligned buffer into output buffer */
memcpy(buf, aligned_buf, len);
buf += len;
@@ -1230,11 +1260,11 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
{
u64 *pdata = buf;
for (; cnt >= 8; cnt -= 8)
- *pdata++ = mci_readq(host, DATA);
+ *pdata++ = mci_readq(host, DATA(host->data_offset));
buf = pdata;
}
if (cnt) {
- host->part_buf = mci_readq(host, DATA);
+ host->part_buf = mci_readq(host, DATA(host->data_offset));
dw_mci_pull_final_bytes(host, buf, cnt);
}
}
@@ -1406,6 +1436,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
struct dw_mci *host = dev_id;
u32 status, pending;
unsigned int pass_count = 0;
+ int i;
do {
status = mci_readl(host, RINTSTS);
@@ -1477,6 +1508,15 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
queue_work(dw_mci_card_workqueue, &host->card_work);
}
+ /* Handle SDIO Interrupts */
+ for (i = 0; i < host->num_slots; i++) {
+ struct dw_mci_slot *slot = host->slot[i];
+ if (pending & SDMMC_INT_SDIO(i)) {
+ mci_writel(host, RINTSTS, SDMMC_INT_SDIO(i));
+ mmc_signal_sdio_irq(slot->mmc);
+ }
+ }
+
} while (pass_count++ < 5);
#ifdef CONFIG_MMC_DW_IDMAC
@@ -1673,7 +1713,7 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
if (IS_ERR(host->vmmc)) {
- printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc));
+ pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
host->vmmc = NULL;
} else
regulator_enable(host->vmmc);
@@ -1924,6 +1964,18 @@ static int dw_mci_probe(struct platform_device *pdev)
}
/*
+ * In 2.40a spec, Data offset is changed.
+ * Need to check the version-id and set data-offset for DATA register.
+ */
+ host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
+ dev_info(&pdev->dev, "Version ID is %04x\n", host->verid);
+
+ if (host->verid < DW_MMC_240A)
+ host->data_offset = DATA_OFFSET;
+ else
+ host->data_offset = DATA_240A_OFFSET;
+
+ /*
* Enable interrupts for command done, data over, data empty, card det,
* receive ready and error such as transmit, receive timeout, crc error
*/
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 027d37735394..72c071f6e001 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -14,6 +14,8 @@
#ifndef _DW_MMC_H_
#define _DW_MMC_H_
+#define DW_MMC_240A 0x240a
+
#define SDMMC_CTRL 0x000
#define SDMMC_PWREN 0x004
#define SDMMC_CLKDIV 0x008
@@ -51,7 +53,14 @@
#define SDMMC_IDINTEN 0x090
#define SDMMC_DSCADDR 0x094
#define SDMMC_BUFADDR 0x098
-#define SDMMC_DATA 0x100
+#define SDMMC_DATA(x) (x)
+
+/*
+ * Data offset is difference according to Version
+ * Lower than 2.40a : data register offest is 0x100
+ */
+#define DATA_OFFSET 0x100
+#define DATA_240A_OFFSET 0x200
/* shift bit field */
#define _SBF(f, v) ((v) << (f))
@@ -82,7 +91,7 @@
#define SDMMC_CTYPE_4BIT BIT(0)
#define SDMMC_CTYPE_1BIT 0
/* Interrupt status & mask register defines */
-#define SDMMC_INT_SDIO BIT(16)
+#define SDMMC_INT_SDIO(n) BIT(16 + (n))
#define SDMMC_INT_EBE BIT(15)
#define SDMMC_INT_ACD BIT(14)
#define SDMMC_INT_SBE BIT(13)
@@ -130,6 +139,8 @@
#define SDMMC_IDMAC_ENABLE BIT(7)
#define SDMMC_IDMAC_FB BIT(1)
#define SDMMC_IDMAC_SWRESET BIT(0)
+/* Version ID register define */
+#define SDMMC_GET_VERID(x) ((x) & 0xFFFF)
/* Register access macros */
#define mci_readl(dev, reg) \
diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c
index 881f7ba545ae..ea0f3cedef21 100644
--- a/drivers/mmc/host/imxmmc.c
+++ b/drivers/mmc/host/imxmmc.c
@@ -942,7 +942,7 @@ static int __init imxmci_probe(struct platform_device *pdev)
int ret = 0, irq;
u16 rev_no;
- printk(KERN_INFO "i.MX mmc driver\n");
+ pr_info("i.MX mmc driver\n");
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 7c1e16aaf17f..92946b84e9fa 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -27,6 +27,7 @@
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/bio.h>
#include <linux/dma-mapping.h>
#include <linux/crc7.h>
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 56e9a4168264..50b5f9926f64 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -29,6 +29,7 @@
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/amba/mmci.h>
+#include <linux/pm_runtime.h>
#include <asm/div64.h>
#include <asm/io.h>
@@ -170,6 +171,7 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
* back into the driver...
*/
spin_unlock(&host->lock);
+ pm_runtime_put(mmc_dev(host->mmc));
mmc_request_done(host->mmc, mrq);
spin_lock(&host->lock);
}
@@ -464,7 +466,7 @@ static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
struct mmci_host_next *next = &host->next_data;
if (data->host_cookie && data->host_cookie != next->cookie) {
- printk(KERN_WARNING "[%s] invalid cookie: data->host_cookie %d"
+ pr_warning("[%s] invalid cookie: data->host_cookie %d"
" host->next_data.cookie %d\n",
__func__, data->host_cookie, host->next_data.cookie);
data->host_cookie = 0;
@@ -529,7 +531,7 @@ static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq,
if (chan) {
if (err)
dmaengine_terminate_all(chan);
- if (err || data->host_cookie)
+ if (data->host_cookie)
dma_unmap_sg(mmc_dev(host->mmc), data->sg,
data->sg_len, dir);
mrq->data->host_cookie = 0;
@@ -984,6 +986,8 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
return;
}
+ pm_runtime_get_sync(mmc_dev(mmc));
+
spin_lock_irqsave(&host->lock, flags);
host->mrq = mrq;
@@ -1156,10 +1160,14 @@ static int __devinit mmci_probe(struct amba_device *dev,
goto host_free;
}
- ret = clk_enable(host->clk);
+ ret = clk_prepare(host->clk);
if (ret)
goto clk_free;
+ ret = clk_enable(host->clk);
+ if (ret)
+ goto clk_unprep;
+
host->plat = plat;
host->variant = variant;
host->mclk = clk_get_rate(host->clk);
@@ -1327,6 +1335,8 @@ static int __devinit mmci_probe(struct amba_device *dev,
mmci_dma_setup(host);
+ pm_runtime_put(&dev->dev);
+
mmc_add_host(mmc);
return 0;
@@ -1345,6 +1355,8 @@ static int __devinit mmci_probe(struct amba_device *dev,
iounmap(host->base);
clk_disable:
clk_disable(host->clk);
+ clk_unprep:
+ clk_unprepare(host->clk);
clk_free:
clk_put(host->clk);
host_free:
@@ -1364,6 +1376,12 @@ static int __devexit mmci_remove(struct amba_device *dev)
if (mmc) {
struct mmci_host *host = mmc_priv(mmc);
+ /*
+ * Undo pm_runtime_put() in probe. We use the _sync
+ * version here so that we can access the primecell.
+ */
+ pm_runtime_get_sync(&dev->dev);
+
mmc_remove_host(mmc);
writel(0, host->base + MMCIMASK0);
@@ -1386,6 +1404,7 @@ static int __devexit mmci_remove(struct amba_device *dev)
iounmap(host->base);
clk_disable(host->clk);
+ clk_unprepare(host->clk);
clk_put(host->clk);
if (host->vcc)
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index a4c865a5286b..80d8eb143b48 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -213,7 +213,8 @@ msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd)
msmsdcc_writel(host, host->cmd_timeout, MMCIDATATIMER);
msmsdcc_writel(host, (unsigned int)host->curr.xfer_size,
MMCIDATALENGTH);
- msmsdcc_writel(host, host->cmd_pio_irqmask, MMCIMASK1);
+ msmsdcc_writel(host, (msmsdcc_readl(host, MMCIMASK0) &
+ (~MCI_IRQ_PIO)) | host->cmd_pio_irqmask, MMCIMASK0);
msmsdcc_writel(host, host->cmd_datactrl, MMCIDATACTRL);
if (host->cmd_cmd) {
@@ -388,7 +389,7 @@ static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
host->dma.num_ents, host->dma.dir);
if (n == 0) {
- printk(KERN_ERR "%s: Unable to map in all sg elements\n",
+ pr_err("%s: Unable to map in all sg elements\n",
mmc_hostname(host->mmc));
host->dma.sg = NULL;
host->dma.num_ents = 0;
@@ -474,7 +475,7 @@ msmsdcc_start_command_deferred(struct msmsdcc_host *host,
*c |= MCI_CSPM_MCIABORT;
if (host->curr.cmd != NULL) {
- printk(KERN_ERR "%s: Overlapping command requests\n",
+ pr_err("%s: Overlapping command requests\n",
mmc_hostname(host->mmc));
}
host->curr.cmd = cmd;
@@ -543,7 +544,9 @@ msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data,
msmsdcc_writel(host, host->curr.xfer_size, MMCIDATALENGTH);
- msmsdcc_writel(host, pio_irqmask, MMCIMASK1);
+ msmsdcc_writel(host, (msmsdcc_readl(host, MMCIMASK0) &
+ (~MCI_IRQ_PIO)) | pio_irqmask, MMCIMASK0);
+
msmsdcc_writel(host, datactrl, MMCIDATACTRL);
if (cmd) {
@@ -659,8 +662,13 @@ msmsdcc_pio_irq(int irq, void *dev_id)
{
struct msmsdcc_host *host = dev_id;
uint32_t status;
+ u32 mci_mask0;
status = msmsdcc_readl(host, MMCISTATUS);
+ mci_mask0 = msmsdcc_readl(host, MMCIMASK0);
+
+ if (((mci_mask0 & status) & MCI_IRQ_PIO) == 0)
+ return IRQ_NONE;
do {
unsigned long flags;
@@ -719,10 +727,12 @@ msmsdcc_pio_irq(int irq, void *dev_id)
} while (1);
if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE)
- msmsdcc_writel(host, MCI_RXDATAAVLBLMASK, MMCIMASK1);
+ msmsdcc_writel(host, (mci_mask0 & (~MCI_IRQ_PIO)) |
+ MCI_RXDATAAVLBLMASK, MMCIMASK0);
if (!host->curr.xfer_remain)
- msmsdcc_writel(host, 0, MMCIMASK1);
+ msmsdcc_writel(host, (mci_mask0 & (~MCI_IRQ_PIO)) | 0,
+ MMCIMASK0);
return IRQ_HANDLED;
}
@@ -854,6 +864,8 @@ msmsdcc_irq(int irq, void *dev_id)
do {
status = msmsdcc_readl(host, MMCISTATUS);
status &= msmsdcc_readl(host, MMCIMASK0);
+ if ((status & (~MCI_IRQ_PIO)) == 0)
+ break;
msmsdcc_writel(host, status, MMCICLEAR);
if (status & MCI_SDIOINTR)
@@ -939,7 +951,7 @@ static void msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
struct msm_mmc_gpio_data *curr;
int i, rc = 0;
- if (!host->plat->gpio_data && host->gpio_config_status == enable)
+ if (!host->plat->gpio_data || host->gpio_config_status == enable)
return;
curr = host->plat->gpio_data;
@@ -1052,10 +1064,19 @@ static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
spin_unlock_irqrestore(&host->lock, flags);
}
+static void msmsdcc_init_card(struct mmc_host *mmc, struct mmc_card *card)
+{
+ struct msmsdcc_host *host = mmc_priv(mmc);
+
+ if (host->plat->init_card)
+ host->plat->init_card(card);
+}
+
static const struct mmc_host_ops msmsdcc_ops = {
.request = msmsdcc_request,
.set_ios = msmsdcc_set_ios,
.enable_sdio_irq = msmsdcc_enable_sdio_irq,
+ .init_card = msmsdcc_init_card,
};
static void
@@ -1092,7 +1113,7 @@ msmsdcc_platform_status_irq(int irq, void *dev_id)
{
struct msmsdcc_host *host = dev_id;
- printk(KERN_DEBUG "%s: %d\n", __func__, irq);
+ pr_debug("%s: %d\n", __func__, irq);
msmsdcc_check_status((unsigned long) host);
return IRQ_HANDLED;
}
@@ -1102,7 +1123,7 @@ msmsdcc_status_notify_cb(int card_present, void *dev_id)
{
struct msmsdcc_host *host = dev_id;
- printk(KERN_DEBUG "%s: card_present %d\n", mmc_hostname(host->mmc),
+ pr_debug("%s: card_present %d\n", mmc_hostname(host->mmc),
card_present);
msmsdcc_check_status((unsigned long) host);
}
@@ -1150,7 +1171,6 @@ msmsdcc_probe(struct platform_device *pdev)
struct msmsdcc_host *host;
struct mmc_host *mmc;
struct resource *cmd_irqres = NULL;
- struct resource *pio_irqres = NULL;
struct resource *stat_irqres = NULL;
struct resource *memres = NULL;
struct resource *dmares = NULL;
@@ -1175,12 +1195,10 @@ msmsdcc_probe(struct platform_device *pdev)
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
cmd_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
"cmd_irq");
- pio_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
- "pio_irq");
stat_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
"status_irq");
- if (!cmd_irqres || !pio_irqres || !memres) {
+ if (!cmd_irqres || !memres) {
pr_err("%s: Invalid resource\n", __func__);
return -ENXIO;
}
@@ -1200,17 +1218,20 @@ msmsdcc_probe(struct platform_device *pdev)
host->plat = plat;
host->mmc = mmc;
host->curr.cmd = NULL;
+ init_timer(&host->busclk_timer);
+ host->busclk_timer.data = (unsigned long) host;
+ host->busclk_timer.function = msmsdcc_busclk_expired;
+
host->cmdpoll = 1;
host->base = ioremap(memres->start, PAGE_SIZE);
if (!host->base) {
ret = -ENOMEM;
- goto out;
+ goto host_free;
}
host->cmd_irqres = cmd_irqres;
- host->pio_irqres = pio_irqres;
host->memres = memres;
host->dmares = dmares;
spin_lock_init(&host->lock);
@@ -1221,13 +1242,19 @@ msmsdcc_probe(struct platform_device *pdev)
/*
* Setup DMA
*/
- msmsdcc_init_dma(host);
+ if (host->dmares) {
+ ret = msmsdcc_init_dma(host);
+ if (ret)
+ goto ioremap_free;
+ } else {
+ host->dma.channel = -1;
+ }
/* Get our clocks */
host->pclk = clk_get(&pdev->dev, "sdc_pclk");
if (IS_ERR(host->pclk)) {
ret = PTR_ERR(host->pclk);
- goto host_free;
+ goto dma_free;
}
host->clk = clk_get(&pdev->dev, "sdc_clk");
@@ -1236,17 +1263,17 @@ msmsdcc_probe(struct platform_device *pdev)
goto pclk_put;
}
- /* Enable clocks */
- ret = msmsdcc_enable_clocks(host);
- if (ret)
- goto clk_put;
-
ret = clk_set_rate(host->clk, msmsdcc_fmin);
if (ret) {
pr_err("%s: Clock rate set failed (%d)\n", __func__, ret);
- goto clk_disable;
+ goto clk_put;
}
+ /* Enable clocks */
+ ret = msmsdcc_enable_clocks(host);
+ if (ret)
+ goto clk_put;
+
host->pclk_rate = clk_get_rate(host->pclk);
host->clk_rate = clk_get_rate(host->clk);
@@ -1316,16 +1343,12 @@ msmsdcc_probe(struct platform_device *pdev)
host->eject = !host->oldstat;
}
- init_timer(&host->busclk_timer);
- host->busclk_timer.data = (unsigned long) host;
- host->busclk_timer.function = msmsdcc_busclk_expired;
-
ret = request_irq(cmd_irqres->start, msmsdcc_irq, IRQF_SHARED,
DRIVER_NAME " (cmd)", host);
if (ret)
goto stat_irq_free;
- ret = request_irq(pio_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
+ ret = request_irq(cmd_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
DRIVER_NAME " (pio)", host);
if (ret)
goto cmd_irq_free;
@@ -1368,6 +1391,13 @@ msmsdcc_probe(struct platform_device *pdev)
clk_put(host->clk);
pclk_put:
clk_put(host->pclk);
+dma_free:
+ if (host->dmares)
+ dma_free_coherent(NULL, sizeof(struct msmsdcc_nc_dmadata),
+ host->dma.nc, host->dma.nc_busaddr);
+ioremap_free:
+ tasklet_kill(&host->dma_tlet);
+ iounmap(host->base);
host_free:
mmc_free_host(mmc);
out:
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 42d7bbc977c5..402028d16b86 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -140,6 +140,11 @@
MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \
MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK|MCI_PROGDONEMASK)
+#define MCI_IRQ_PIO \
+ (MCI_RXDATAAVLBLMASK | MCI_TXDATAAVLBLMASK | MCI_RXFIFOEMPTYMASK | \
+ MCI_TXFIFOEMPTYMASK | MCI_RXFIFOFULLMASK | MCI_TXFIFOFULLMASK | \
+ MCI_RXFIFOHALFFULLMASK | MCI_TXFIFOHALFEMPTYMASK | \
+ MCI_RXACTIVEMASK | MCI_TXACTIVEMASK)
/*
* The size of the FIFO in bytes.
*/
@@ -202,7 +207,6 @@ struct msmsdcc_stats {
struct msmsdcc_host {
struct resource *cmd_irqres;
- struct resource *pio_irqres;
struct resource *memres;
struct resource *dmares;
void __iomem *base;
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index a5bf60e01af4..211a4959c293 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -117,7 +117,7 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data)
host->pio_size = data->blocks * data->blksz;
host->pio_ptr = sg_virt(data->sg);
if (!nodma)
- printk(KERN_DEBUG "%s: fallback to PIO for data "
+ pr_debug("%s: fallback to PIO for data "
"at 0x%p size %d\n",
mmc_hostname(host->mmc),
host->pio_ptr, host->pio_size);
@@ -471,7 +471,7 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
if (mrq->data)
err_status = mvsd_finish_data(host, mrq->data, err_status);
if (err_status) {
- printk(KERN_ERR "%s: unhandled error status %#04x\n",
+ pr_err("%s: unhandled error status %#04x\n",
mmc_hostname(host->mmc), err_status);
cmd->error = -ENOMSG;
}
@@ -489,7 +489,7 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
if (irq_handled)
return IRQ_HANDLED;
- printk(KERN_ERR "%s: unhandled interrupt status=0x%04x en=0x%04x "
+ pr_err("%s: unhandled interrupt status=0x%04x en=0x%04x "
"pio=%d\n", mmc_hostname(host->mmc), intr_status,
host->intr_en, host->pio_size);
return IRQ_NONE;
@@ -505,9 +505,9 @@ static void mvsd_timeout_timer(unsigned long data)
spin_lock_irqsave(&host->lock, flags);
mrq = host->mrq;
if (mrq) {
- printk(KERN_ERR "%s: Timeout waiting for hardware interrupt.\n",
+ pr_err("%s: Timeout waiting for hardware interrupt.\n",
mmc_hostname(host->mmc));
- printk(KERN_ERR "%s: hw_state=0x%04x, intr_status=0x%04x "
+ pr_err("%s: hw_state=0x%04x, intr_status=0x%04x "
"intr_en=0x%04x\n", mmc_hostname(host->mmc),
mvsd_read(MVSD_HW_STATE),
mvsd_read(MVSD_NOR_INTR_STATUS),
@@ -762,7 +762,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host);
if (ret) {
- printk(KERN_ERR "%s: cannot assign irq %d\n", DRIVER_NAME, irq);
+ pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq);
goto out;
} else
host->irq = irq;
@@ -802,7 +802,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
if (ret)
goto out;
- printk(KERN_NOTICE "%s: %s driver initialized, ",
+ pr_notice("%s: %s driver initialized, ",
mmc_hostname(mmc), DRIVER_NAME);
if (host->gpio_card_detect)
printk("using GPIO %d for card detection\n",
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 14aa213b00da..325ea61e12d3 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -40,6 +40,7 @@
#include <mach/mmc.h>
#include <mach/dma.h>
+#include <mach/hardware.h>
#define DRIVER_NAME "mxc-mmc"
@@ -842,7 +843,7 @@ static int mxcmci_probe(struct platform_device *pdev)
int ret = 0, irq;
dma_cap_mask_t mask;
- printk(KERN_INFO "i.MX SDHC driver\n");
+ pr_info("i.MX SDHC driver\n");
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index d513d47364d0..99b449d26a4d 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -37,6 +37,7 @@
#include <linux/mmc/sdio.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
+#include <linux/module.h>
#include <mach/mxs.h>
#include <mach/common.h>
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index a6c329040140..2dba999caf2c 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -33,7 +33,7 @@
#include <plat/board.h>
#include <plat/mmc.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <plat/dma.h>
#include <plat/mux.h>
#include <plat/fpga.h>
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 21e4a799df48..101cd31c8220 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -450,15 +450,14 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
* framework is fixed, we need a workaround like this
* (which is safe for MMC, but not in general).
*/
- if (regulator_is_enabled(host->vcc) > 0) {
- regulator_enable(host->vcc);
- regulator_disable(host->vcc);
- }
- if (host->vcc_aux) {
- if (regulator_is_enabled(reg) > 0) {
- regulator_enable(reg);
- regulator_disable(reg);
- }
+ if (regulator_is_enabled(host->vcc) > 0 ||
+ (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) {
+ int vdd = ffs(mmc_slot(host).ocr_mask) - 1;
+
+ mmc_slot(host).set_power(host->dev, host->slot_id,
+ 1, vdd);
+ mmc_slot(host).set_power(host->dev, host->slot_id,
+ 0, 0);
}
}
@@ -1264,14 +1263,14 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host)
host->reqs_blocked = 0;
if (mmc_slot(host).get_cover_state(host->dev, host->slot_id)) {
if (host->protect_card) {
- printk(KERN_INFO "%s: cover is closed, "
+ pr_info("%s: cover is closed, "
"card is now accessible\n",
mmc_hostname(host->mmc));
host->protect_card = 0;
}
} else {
if (!host->protect_card) {
- printk(KERN_INFO "%s: cover is open, "
+ pr_info("%s: cover is open, "
"card is now inaccessible\n",
mmc_hostname(host->mmc));
host->protect_card = 1;
@@ -1422,7 +1421,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
if (!next && data->host_cookie &&
data->host_cookie != host->next_data.cookie) {
- printk(KERN_WARNING "[%s] invalid cookie: data->host_cookie %d"
+ pr_warning("[%s] invalid cookie: data->host_cookie %d"
" host->next_data.cookie %d\n",
__func__, data->host_cookie, host->next_data.cookie);
data->host_cookie = 0;
@@ -1943,6 +1942,10 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
omap_hsmmc_context_save(host);
mmc->caps |= MMC_CAP_DISABLE;
+ if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) {
+ dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n");
+ mmc->caps2 |= MMC_CAP2_NO_MULTI_READ;
+ }
pm_runtime_enable(host->dev);
pm_runtime_get_sync(host->dev);
@@ -2015,7 +2018,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
}
/* Request IRQ for MMC operations */
- ret = request_irq(host->irq, omap_hsmmc_irq, IRQF_DISABLED,
+ ret = request_irq(host->irq, omap_hsmmc_irq, 0,
mmc_hostname(mmc), host);
if (ret) {
dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
@@ -2043,8 +2046,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
if ((mmc_slot(host).card_detect_irq)) {
ret = request_irq(mmc_slot(host).card_detect_irq,
omap_hsmmc_cd_handler,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
- | IRQF_DISABLED,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
mmc_hostname(mmc), host);
if (ret) {
dev_dbg(mmc_dev(host->mmc),
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 7257738fd7da..fc4356e00d46 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -558,7 +558,7 @@ static void pxamci_dma_irq(int dma, void *devid)
if (dcsr & DCSR_ENDINTR) {
writel(BUF_PART_FULL, host->base + MMC_PRTBUF);
} else {
- printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
+ pr_err("%s: DMA error on channel %d (DCSR=%#x)\n",
mmc_hostname(host->mmc), dma, dcsr);
host->data->error = -EIO;
pxamci_data_done(host, 0);
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index a04f87d7ee3d..d2856b6b2a62 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -247,7 +247,7 @@ static void s3cmci_check_sdio_irq(struct s3cmci_host *host)
{
if (host->sdio_irqen) {
if (gpio_get_value(S3C2410_GPE(8)) == 0) {
- printk(KERN_DEBUG "%s: signalling irq\n", __func__);
+ pr_debug("%s: signalling irq\n", __func__);
mmc_signal_sdio_irq(host->mmc);
}
}
@@ -344,7 +344,7 @@ static void s3cmci_disable_irq(struct s3cmci_host *host, bool transfer)
local_irq_save(flags);
- //printk(KERN_DEBUG "%s: transfer %d\n", __func__, transfer);
+ /* pr_debug("%s: transfer %d\n", __func__, transfer); */
host->irq_disabled = transfer;
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 4dc0028086a3..ae57769ba50d 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -32,6 +32,15 @@
/* VENDOR SPEC register */
#define SDHCI_VENDOR_SPEC 0xC0
#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
+#define SDHCI_MIX_CTRL 0x48
+
+/*
+ * There is an INT DMA ERR mis-match between eSDHC and STD SDHC SPEC:
+ * Bit25 is used in STD SPEC, and is reserved in fsl eSDHC design,
+ * but bit28 is used as the INT DMA ERR in fsl eSDHC design.
+ * Define this macro DMA error INT for fsl eSDHC
+ */
+#define SDHCI_INT_VENDOR_SPEC_DMA_ERR 0x10000000
/*
* The CMDTYPE of the CMD register (offset 0xE) should be set to
@@ -51,6 +60,7 @@ enum imx_esdhc_type {
IMX35_ESDHC,
IMX51_ESDHC,
IMX53_ESDHC,
+ IMX6Q_USDHC,
};
struct pltfm_imx_data {
@@ -74,6 +84,9 @@ static struct platform_device_id imx_esdhc_devtype[] = {
.name = "sdhci-esdhc-imx53",
.driver_data = IMX53_ESDHC,
}, {
+ .name = "sdhci-usdhc-imx6q",
+ .driver_data = IMX6Q_USDHC,
+ }, {
/* sentinel */
}
};
@@ -84,6 +97,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
{ .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], },
{ .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], },
{ .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], },
+ { .compatible = "fsl,imx6q-usdhc", .data = &imx_esdhc_devtype[IMX6Q_USDHC], },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
@@ -108,6 +122,11 @@ static inline int is_imx53_esdhc(struct pltfm_imx_data *data)
return data->devtype == IMX53_ESDHC;
}
+static inline int is_imx6q_usdhc(struct pltfm_imx_data *data)
+{
+ return data->devtype == IMX6Q_USDHC;
+}
+
static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
{
void __iomem *base = host->ioaddr + (reg & ~0x3);
@@ -135,6 +154,27 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
val |= SDHCI_CARD_PRESENT;
}
+ if (unlikely(reg == SDHCI_CAPABILITIES)) {
+ /* In FSL esdhc IC module, only bit20 is used to indicate the
+ * ADMA2 capability of esdhc, but this bit is messed up on
+ * some SOCs (e.g. on MX25, MX35 this bit is set, but they
+ * don't actually support ADMA2). So set the BROKEN_ADMA
+ * uirk on MX25/35 platforms.
+ */
+
+ if (val & SDHCI_CAN_DO_ADMA1) {
+ val &= ~SDHCI_CAN_DO_ADMA1;
+ val |= SDHCI_CAN_DO_ADMA2;
+ }
+ }
+
+ if (unlikely(reg == SDHCI_INT_STATUS)) {
+ if (val & SDHCI_INT_VENDOR_SPEC_DMA_ERR) {
+ val &= ~SDHCI_INT_VENDOR_SPEC_DMA_ERR;
+ val |= SDHCI_INT_ADMA_ERROR;
+ }
+ }
+
return val;
}
@@ -179,13 +219,28 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
}
+ if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
+ if (val & SDHCI_INT_ADMA_ERROR) {
+ val &= ~SDHCI_INT_ADMA_ERROR;
+ val |= SDHCI_INT_VENDOR_SPEC_DMA_ERR;
+ }
+ }
+
writel(val, host->ioaddr + reg);
}
static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
{
- if (unlikely(reg == SDHCI_HOST_VERSION))
- reg ^= 2;
+ if (unlikely(reg == SDHCI_HOST_VERSION)) {
+ u16 val = readw(host->ioaddr + (reg ^ 2));
+ /*
+ * uSDHC supports SDHCI v3.0, but it's encoded as value
+ * 0x3 in host controller version register, which violates
+ * SDHCI_SPEC_300 definition. Work it around here.
+ */
+ if ((val & SDHCI_SPEC_VER_MASK) == 3)
+ return --val;
+ }
return readw(host->ioaddr + reg);
}
@@ -216,8 +271,17 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
if ((host->cmd->opcode == MMC_STOP_TRANSMISSION)
&& (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
val |= SDHCI_CMD_ABORTCMD;
- writel(val << 16 | imx_data->scratchpad,
- host->ioaddr + SDHCI_TRANSFER_MODE);
+
+ if (is_imx6q_usdhc(imx_data)) {
+ u32 m = readl(host->ioaddr + SDHCI_MIX_CTRL);
+ m = imx_data->scratchpad | (m & 0xffff0000);
+ writel(m, host->ioaddr + SDHCI_MIX_CTRL);
+ writel(val << 16,
+ host->ioaddr + SDHCI_TRANSFER_MODE);
+ } else {
+ writel(val << 16 | imx_data->scratchpad,
+ host->ioaddr + SDHCI_TRANSFER_MODE);
+ }
return;
case SDHCI_BLOCK_SIZE:
val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
@@ -311,9 +375,10 @@ static struct sdhci_ops sdhci_esdhc_ops = {
};
static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
- .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
+ .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT
+ | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
+ | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC
| SDHCI_QUIRK_BROKEN_CARD_DETECTION,
- /* ADMA has issues. Might be fixable */
.ops = &sdhci_esdhc_ops,
};
@@ -405,7 +470,8 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
- host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+ host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
+ | SDHCI_QUIRK_BROKEN_ADMA;
if (is_imx53_esdhc(imx_data))
imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index fe604df65011..59e9d003e589 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -1,7 +1,7 @@
/*
* Freescale eSDHC controller driver.
*
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2007, 2010 Freescale Semiconductor, Inc.
* Copyright (c) 2009 MontaVista Software, Inc.
*
* Authors: Xiaobo Xie <X.Xie@freescale.com>
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/mmc/host.h>
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
@@ -22,11 +23,21 @@
static u16 esdhc_readw(struct sdhci_host *host, int reg)
{
u16 ret;
+ int base = reg & ~0x3;
+ int shift = (reg & 0x2) * 8;
if (unlikely(reg == SDHCI_HOST_VERSION))
- ret = in_be16(host->ioaddr + reg);
+ ret = in_be32(host->ioaddr + base) & 0xffff;
else
- ret = sdhci_be32bs_readw(host, reg);
+ ret = (in_be32(host->ioaddr + base) >> shift) & 0xffff;
+ return ret;
+}
+
+static u8 esdhc_readb(struct sdhci_host *host, int reg)
+{
+ int base = reg & ~0x3;
+ int shift = (reg & 0x3) * 8;
+ u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff;
return ret;
}
@@ -74,7 +85,7 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = sdhci_be32bs_readl,
.read_w = esdhc_readw,
- .read_b = sdhci_be32bs_readb,
+ .read_b = esdhc_readb,
.write_l = sdhci_be32bs_writel,
.write_w = esdhc_writew,
.write_b = esdhc_writeb,
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index 735be131dca9..9b0d794a4f69 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -20,6 +20,7 @@
*/
#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/mmc/host.h>
#include "sdhci-pltfm.h"
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 26c528648f3c..d833d9c2f7e3 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -14,6 +14,7 @@
#include <linux/delay.h>
#include <linux/highmem.h>
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
@@ -21,6 +22,9 @@
#include <linux/mmc/host.h>
#include <linux/scatterlist.h>
#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/sfi.h>
+#include <linux/pm_runtime.h>
#include "sdhci.h"
@@ -43,6 +47,7 @@ struct sdhci_pci_slot;
struct sdhci_pci_fixes {
unsigned int quirks;
+ bool allow_runtime_pm;
int (*probe) (struct sdhci_pci_chip *);
@@ -59,12 +64,16 @@ struct sdhci_pci_slot {
struct sdhci_host *host;
int pci_bar;
+ int rst_n_gpio;
+ int cd_gpio;
+ int cd_irq;
};
struct sdhci_pci_chip {
struct pci_dev *pdev;
unsigned int quirks;
+ bool allow_runtime_pm;
const struct sdhci_pci_fixes *fixes;
int num_slots; /* Slots on controller */
@@ -163,12 +172,129 @@ static int mrst_hc_probe(struct sdhci_pci_chip *chip)
return 0;
}
+/* Medfield eMMC hardware reset GPIOs */
+static int mfd_emmc0_rst_gpio = -EINVAL;
+static int mfd_emmc1_rst_gpio = -EINVAL;
+
+static int mfd_emmc_gpio_parse(struct sfi_table_header *table)
+{
+ struct sfi_table_simple *sb = (struct sfi_table_simple *)table;
+ struct sfi_gpio_table_entry *entry;
+ int i, num;
+
+ num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry);
+ entry = (struct sfi_gpio_table_entry *)sb->pentry;
+
+ for (i = 0; i < num; i++, entry++) {
+ if (!strncmp(entry->pin_name, "emmc0_rst", SFI_NAME_LEN))
+ mfd_emmc0_rst_gpio = entry->pin_no;
+ else if (!strncmp(entry->pin_name, "emmc1_rst", SFI_NAME_LEN))
+ mfd_emmc1_rst_gpio = entry->pin_no;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+
+static irqreturn_t mfd_sd_cd(int irq, void *dev_id)
+{
+ struct sdhci_pci_slot *slot = dev_id;
+ struct sdhci_host *host = slot->host;
+
+ mmc_detect_change(host->mmc, msecs_to_jiffies(200));
+ return IRQ_HANDLED;
+}
+
+#define MFLD_SD_CD_PIN 69
+
+static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot)
+{
+ int err, irq, gpio = MFLD_SD_CD_PIN;
+
+ slot->cd_gpio = -EINVAL;
+ slot->cd_irq = -EINVAL;
+
+ err = gpio_request(gpio, "sd_cd");
+ if (err < 0)
+ goto out;
+
+ err = gpio_direction_input(gpio);
+ if (err < 0)
+ goto out_free;
+
+ irq = gpio_to_irq(gpio);
+ if (irq < 0)
+ goto out_free;
+
+ err = request_irq(irq, mfd_sd_cd, IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING, "sd_cd", slot);
+ if (err)
+ goto out_free;
+
+ slot->cd_gpio = gpio;
+ slot->cd_irq = irq;
+ slot->host->quirks2 |= SDHCI_QUIRK2_OWN_CARD_DETECTION;
+
+ return 0;
+
+out_free:
+ gpio_free(gpio);
+out:
+ dev_warn(&slot->chip->pdev->dev, "failed to setup card detect wake up\n");
+ return 0;
+}
+
+static void mfd_sd_remove_slot(struct sdhci_pci_slot *slot, int dead)
+{
+ if (slot->cd_irq >= 0)
+ free_irq(slot->cd_irq, slot);
+ gpio_free(slot->cd_gpio);
+}
+
+#else
+
+#define mfd_sd_probe_slot NULL
+#define mfd_sd_remove_slot NULL
+
+#endif
+
static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
{
- slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+ const char *name = NULL;
+ int gpio = -EINVAL;
+
+ sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, mfd_emmc_gpio_parse);
+
+ switch (slot->chip->pdev->device) {
+ case PCI_DEVICE_ID_INTEL_MFD_EMMC0:
+ gpio = mfd_emmc0_rst_gpio;
+ name = "eMMC0_reset";
+ break;
+ case PCI_DEVICE_ID_INTEL_MFD_EMMC1:
+ gpio = mfd_emmc1_rst_gpio;
+ name = "eMMC1_reset";
+ break;
+ }
+
+ if (!gpio_request(gpio, name)) {
+ gpio_direction_output(gpio, 1);
+ slot->rst_n_gpio = gpio;
+ slot->host->mmc->caps |= MMC_CAP_HW_RESET;
+ }
+
+ slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE;
+
+ slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC;
+
return 0;
}
+static void mfd_emmc_remove_slot(struct sdhci_pci_slot *slot, int dead)
+{
+ gpio_free(slot->rst_n_gpio);
+}
+
static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = {
.quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
.probe_slot = mrst_hc_probe_slot,
@@ -181,15 +307,21 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = {
static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+ .allow_runtime_pm = true,
+ .probe_slot = mfd_sd_probe_slot,
+ .remove_slot = mfd_sd_remove_slot,
};
static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+ .allow_runtime_pm = true,
};
static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+ .allow_runtime_pm = true,
.probe_slot = mfd_emmc_probe_slot,
+ .remove_slot = mfd_emmc_remove_slot,
};
/* O2Micro extra registers */
@@ -832,9 +964,25 @@ static int sdhci_pci_8bit_width(struct sdhci_host *host, int width)
return 0;
}
+static void sdhci_pci_hw_reset(struct sdhci_host *host)
+{
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
+ int rst_n_gpio = slot->rst_n_gpio;
+
+ if (!gpio_is_valid(rst_n_gpio))
+ return;
+ gpio_set_value_cansleep(rst_n_gpio, 0);
+ /* For eMMC, minimum is 1us but give it 10us for good measure */
+ udelay(10);
+ gpio_set_value_cansleep(rst_n_gpio, 1);
+ /* For eMMC, minimum is 200us but give it 300us for good measure */
+ usleep_range(300, 1000);
+}
+
static struct sdhci_ops sdhci_pci_ops = {
.enable_dma = sdhci_pci_enable_dma,
.platform_8bit_width = sdhci_pci_8bit_width,
+ .hw_reset = sdhci_pci_hw_reset,
};
/*****************************************************************************\
@@ -944,6 +1092,95 @@ static int sdhci_pci_resume(struct pci_dev *pdev)
#endif /* CONFIG_PM */
+#ifdef CONFIG_PM_RUNTIME
+
+static int sdhci_pci_runtime_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct sdhci_pci_chip *chip;
+ struct sdhci_pci_slot *slot;
+ pm_message_t state = { .event = PM_EVENT_SUSPEND };
+ int i, ret;
+
+ chip = pci_get_drvdata(pdev);
+ if (!chip)
+ return 0;
+
+ for (i = 0; i < chip->num_slots; i++) {
+ slot = chip->slots[i];
+ if (!slot)
+ continue;
+
+ ret = sdhci_runtime_suspend_host(slot->host);
+
+ if (ret) {
+ for (i--; i >= 0; i--)
+ sdhci_runtime_resume_host(chip->slots[i]->host);
+ return ret;
+ }
+ }
+
+ if (chip->fixes && chip->fixes->suspend) {
+ ret = chip->fixes->suspend(chip, state);
+ if (ret) {
+ for (i = chip->num_slots - 1; i >= 0; i--)
+ sdhci_runtime_resume_host(chip->slots[i]->host);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int sdhci_pci_runtime_resume(struct device *dev)
+{
+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct sdhci_pci_chip *chip;
+ struct sdhci_pci_slot *slot;
+ int i, ret;
+
+ chip = pci_get_drvdata(pdev);
+ if (!chip)
+ return 0;
+
+ if (chip->fixes && chip->fixes->resume) {
+ ret = chip->fixes->resume(chip);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < chip->num_slots; i++) {
+ slot = chip->slots[i];
+ if (!slot)
+ continue;
+
+ ret = sdhci_runtime_resume_host(slot->host);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int sdhci_pci_runtime_idle(struct device *dev)
+{
+ return 0;
+}
+
+#else
+
+#define sdhci_pci_runtime_suspend NULL
+#define sdhci_pci_runtime_resume NULL
+#define sdhci_pci_runtime_idle NULL
+
+#endif
+
+static const struct dev_pm_ops sdhci_pci_pm_ops = {
+ .runtime_suspend = sdhci_pci_runtime_suspend,
+ .runtime_resume = sdhci_pci_runtime_resume,
+ .runtime_idle = sdhci_pci_runtime_idle,
+};
+
/*****************************************************************************\
* *
* Device probing/removal *
@@ -988,6 +1225,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
slot->chip = chip;
slot->host = host;
slot->pci_bar = bar;
+ slot->rst_n_gpio = -EINVAL;
host->hw_name = "PCI";
host->ops = &sdhci_pci_ops;
@@ -1058,6 +1296,21 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
sdhci_free_host(slot->host);
}
+static void __devinit sdhci_pci_runtime_pm_allow(struct device *dev)
+{
+ pm_runtime_put_noidle(dev);
+ pm_runtime_allow(dev);
+ pm_runtime_set_autosuspend_delay(dev, 50);
+ pm_runtime_use_autosuspend(dev);
+ pm_suspend_ignore_children(dev, 1);
+}
+
+static void __devexit sdhci_pci_runtime_pm_forbid(struct device *dev)
+{
+ pm_runtime_forbid(dev);
+ pm_runtime_get_noresume(dev);
+}
+
static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1107,8 +1360,10 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
chip->pdev = pdev;
chip->fixes = (const struct sdhci_pci_fixes *)ent->driver_data;
- if (chip->fixes)
+ if (chip->fixes) {
chip->quirks = chip->fixes->quirks;
+ chip->allow_runtime_pm = chip->fixes->allow_runtime_pm;
+ }
chip->num_slots = slots;
pci_set_drvdata(pdev, chip);
@@ -1133,6 +1388,9 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
chip->slots[i] = slot;
}
+ if (chip->allow_runtime_pm)
+ sdhci_pci_runtime_pm_allow(&pdev->dev);
+
return 0;
free:
@@ -1152,6 +1410,9 @@ static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
chip = pci_get_drvdata(pdev);
if (chip) {
+ if (chip->allow_runtime_pm)
+ sdhci_pci_runtime_pm_forbid(&pdev->dev);
+
for (i = 0; i < chip->num_slots; i++)
sdhci_pci_remove_slot(chip->slots[i]);
@@ -1169,6 +1430,9 @@ static struct pci_driver sdhci_driver = {
.remove = __devexit_p(sdhci_pci_remove),
.suspend = sdhci_pci_suspend,
.resume = sdhci_pci_resume,
+ .driver = {
+ .pm = &sdhci_pci_pm_ops
+ },
};
/*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 6414efeddca0..a9e12ea05583 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -29,6 +29,7 @@
*/
#include <linux/err.h>
+#include <linux/module.h>
#include <linux/of.h>
#ifdef CONFIG_PPC
#include <asm/machdep.h>
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 38f58994f79a..d4bf6d30c7ba 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/module.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/mmc/card.h>
@@ -59,7 +60,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
* tune timing of read data/command when crc error happen
* no performance impact
*/
- if (pdata->clk_delay_sel == 1) {
+ if (pdata && pdata->clk_delay_sel == 1) {
tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
tmp &= ~(SDCLK_DELAY_MASK << SDCLK_DELAY_SHIFT);
@@ -71,7 +72,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
}
- if (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING) {
+ if (pdata && (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING)) {
tmp = readw(host->ioaddr + SD_FIFO_PARAM);
tmp &= ~CLK_GATE_SETTING_BITS;
writew(tmp, host->ioaddr + SD_FIFO_PARAM);
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index fc7e4a515629..cff4ad3e7a59 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -27,6 +27,7 @@
#include <linux/platform_data/pxa_sdhci.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include "sdhci.h"
#include "sdhci-pltfm.h"
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index fe886d6c474a..3d00e722efc9 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -203,17 +203,23 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
}
- /* reconfigure the hardware for new clock rate */
-
- {
- struct mmc_ios ios;
-
- ios.clock = clock;
-
- if (ourhost->pdata->cfg_card)
- (ourhost->pdata->cfg_card)(ourhost->pdev, host->ioaddr,
- &ios, NULL);
- }
+ /* reprogram default hardware configuration */
+ writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA,
+ host->ioaddr + S3C64XX_SDHCI_CONTROL4);
+
+ ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
+ ctrl |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
+ S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
+ S3C_SDHCI_CTRL2_ENFBCLKRX |
+ S3C_SDHCI_CTRL2_DFCNT_NONE |
+ S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
+ writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
+
+ /* reconfigure the controller for new clock rate */
+ ctrl = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
+ if (clock < 25 * 1000000)
+ ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2);
+ writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL3);
}
/**
@@ -561,8 +567,10 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
err_req_regs:
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
- clk_disable(sc->clk_bus[ptr]);
- clk_put(sc->clk_bus[ptr]);
+ if (sc->clk_bus[ptr]) {
+ clk_disable(sc->clk_bus[ptr]);
+ clk_put(sc->clk_bus[ptr]);
+ }
}
err_no_busclks:
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
index 60a4c97d3d18..63cc8b6a1c9e 100644
--- a/drivers/mmc/host/sdhci-spear.c
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/highmem.h>
+#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
@@ -177,8 +178,6 @@ static int __devinit sdhci_probe(struct platform_device *pdev)
sdhci->data->card_power_gpio);
goto err_pgpio_direction;
}
-
- gpio_set_value(sdhci->data->card_power_gpio, 1);
}
if (sdhci->data->card_int_gpio >= 0) {
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 18b0bd31de78..067a4cded9cf 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -17,11 +17,16 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
+#include <linux/module.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
+
+#include <mach/gpio-tegra.h>
#include <mach/sdhci.h>
#include "sdhci-pltfm.h"
@@ -73,10 +78,8 @@ static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
static unsigned int tegra_sdhci_get_ro(struct sdhci_host *sdhci)
{
- struct platform_device *pdev = to_platform_device(mmc_dev(sdhci->mmc));
- struct tegra_sdhci_platform_data *plat;
-
- plat = pdev->dev.platform_data;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
+ struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
if (!gpio_is_valid(plat->wp_gpio))
return -1;
@@ -94,12 +97,10 @@ static irqreturn_t carddetect_irq(int irq, void *data)
static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width)
{
- struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
- struct tegra_sdhci_platform_data *plat;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
u32 ctrl;
- plat = pdev->dev.platform_data;
-
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
if (plat->is_8bit && bus_width == MMC_BUS_WIDTH_8) {
ctrl &= ~SDHCI_CTRL_4BITBUS;
@@ -131,6 +132,36 @@ static struct sdhci_pltfm_data sdhci_tegra_pdata = {
.ops = &tegra_sdhci_ops,
};
+static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra20-sdhci", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sdhci_dt_ids);
+
+static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
+ struct platform_device *pdev)
+{
+ struct tegra_sdhci_platform_data *plat;
+ struct device_node *np = pdev->dev.of_node;
+
+ if (!np)
+ return NULL;
+
+ plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
+ if (!plat) {
+ dev_err(&pdev->dev, "Can't allocate platform data\n");
+ return NULL;
+ }
+
+ plat->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
+ plat->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
+ plat->power_gpio = of_get_named_gpio(np, "power-gpios", 0);
+ if (of_find_property(np, "support-8bit", NULL))
+ plat->is_8bit = 1;
+
+ return plat;
+}
+
static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
{
struct sdhci_pltfm_host *pltfm_host;
@@ -147,12 +178,17 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
plat = pdev->dev.platform_data;
+ if (plat == NULL)
+ plat = sdhci_tegra_dt_parse_pdata(pdev);
+
if (plat == NULL) {
dev_err(mmc_dev(host->mmc), "missing platform data\n");
rc = -ENXIO;
goto err_no_plat;
}
+ pltfm_host->priv = plat;
+
if (gpio_is_valid(plat->power_gpio)) {
rc = gpio_request(plat->power_gpio, "sdhci_power");
if (rc) {
@@ -247,13 +283,11 @@ static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct tegra_sdhci_platform_data *plat;
+ struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
sdhci_remove_host(host, dead);
- plat = pdev->dev.platform_data;
-
if (gpio_is_valid(plat->wp_gpio)) {
tegra_gpio_disable(plat->wp_gpio);
gpio_free(plat->wp_gpio);
@@ -282,6 +316,7 @@ static struct platform_driver sdhci_tegra_driver = {
.driver = {
.name = "sdhci-tegra",
.owner = THIS_MODULE,
+ .of_match_table = sdhci_tegra_dt_match,
},
.probe = sdhci_tegra_probe,
.remove = __devexit_p(sdhci_tegra_remove),
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0e02cc1df12e..6d8eea323541 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -16,10 +16,12 @@
#include <linux/delay.h>
#include <linux/highmem.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/scatterlist.h>
#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
#include <linux/leds.h>
@@ -41,6 +43,7 @@
#define MAX_TUNING_LOOP 40
static unsigned int debug_quirks = 0;
+static unsigned int debug_quirks2;
static void sdhci_finish_data(struct sdhci_host *);
@@ -49,53 +52,67 @@ static void sdhci_finish_command(struct sdhci_host *);
static int sdhci_execute_tuning(struct mmc_host *mmc);
static void sdhci_tuning_timer(unsigned long data);
+#ifdef CONFIG_PM_RUNTIME
+static int sdhci_runtime_pm_get(struct sdhci_host *host);
+static int sdhci_runtime_pm_put(struct sdhci_host *host);
+#else
+static inline int sdhci_runtime_pm_get(struct sdhci_host *host)
+{
+ return 0;
+}
+static inline int sdhci_runtime_pm_put(struct sdhci_host *host)
+{
+ return 0;
+}
+#endif
+
static void sdhci_dumpregs(struct sdhci_host *host)
{
- printk(KERN_DEBUG DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
+ pr_debug(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
mmc_hostname(host->mmc));
- printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n",
sdhci_readl(host, SDHCI_DMA_ADDRESS),
sdhci_readw(host, SDHCI_HOST_VERSION));
- printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n",
sdhci_readw(host, SDHCI_BLOCK_SIZE),
sdhci_readw(host, SDHCI_BLOCK_COUNT));
- printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
sdhci_readl(host, SDHCI_ARGUMENT),
sdhci_readw(host, SDHCI_TRANSFER_MODE));
- printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n",
sdhci_readl(host, SDHCI_PRESENT_STATE),
sdhci_readb(host, SDHCI_HOST_CONTROL));
- printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n",
sdhci_readb(host, SDHCI_POWER_CONTROL),
sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
- printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n",
sdhci_readb(host, SDHCI_WAKE_UP_CONTROL),
sdhci_readw(host, SDHCI_CLOCK_CONTROL));
- printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n",
sdhci_readb(host, SDHCI_TIMEOUT_CONTROL),
sdhci_readl(host, SDHCI_INT_STATUS));
- printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
sdhci_readl(host, SDHCI_INT_ENABLE),
sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
- printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
sdhci_readw(host, SDHCI_ACMD12_ERR),
sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
- printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n",
sdhci_readl(host, SDHCI_CAPABILITIES),
sdhci_readl(host, SDHCI_CAPABILITIES_1));
- printk(KERN_DEBUG DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n",
sdhci_readw(host, SDHCI_COMMAND),
sdhci_readl(host, SDHCI_MAX_CURRENT));
- printk(KERN_DEBUG DRIVER_NAME ": Host ctl2: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n",
sdhci_readw(host, SDHCI_HOST_CONTROL2));
if (host->flags & SDHCI_USE_ADMA)
- printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
+ pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
readl(host->ioaddr + SDHCI_ADMA_ERROR),
readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
- printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
+ pr_debug(DRIVER_NAME ": ===========================================\n");
}
/*****************************************************************************\
@@ -132,6 +149,9 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
return;
+ if (host->quirks2 & SDHCI_QUIRK2_OWN_CARD_DETECTION)
+ return;
+
present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
SDHCI_CARD_PRESENT;
irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
@@ -180,7 +200,7 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
/* hw clears the bit when it's done */
while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
if (timeout == 0) {
- printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
+ pr_err("%s: Reset 0x%x never completed.\n",
mmc_hostname(host->mmc), (int)mask);
sdhci_dumpregs(host);
return;
@@ -251,11 +271,14 @@ static void sdhci_led_control(struct led_classdev *led,
spin_lock_irqsave(&host->lock, flags);
+ if (host->runtime_suspended)
+ goto out;
+
if (brightness == LED_OFF)
sdhci_deactivate_led(host);
else
sdhci_activate_led(host);
-
+out:
spin_unlock_irqrestore(&host->lock, flags);
}
#endif
@@ -654,7 +677,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
}
if (count >= 0xF) {
- printk(KERN_WARNING "%s: Too large timeout requested for CMD%d!\n",
+ pr_warning("%s: Too large timeout requested for CMD%d!\n",
mmc_hostname(host->mmc), cmd->opcode);
count = 0xE;
}
@@ -949,7 +972,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
if (timeout == 0) {
- printk(KERN_ERR "%s: Controller never released "
+ pr_err("%s: Controller never released "
"inhibit bit(s).\n", mmc_hostname(host->mmc));
sdhci_dumpregs(host);
cmd->error = -EIO;
@@ -971,7 +994,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
sdhci_set_transfer_mode(host, cmd);
if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
- printk(KERN_ERR "%s: Unsupported response type!\n",
+ pr_err("%s: Unsupported response type!\n",
mmc_hostname(host->mmc));
cmd->error = -EINVAL;
tasklet_schedule(&host->finish_tasklet);
@@ -1121,7 +1144,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
& SDHCI_CLOCK_INT_STABLE)) {
if (timeout == 0) {
- printk(KERN_ERR "%s: Internal clock never "
+ pr_err("%s: Internal clock never "
"stabilised.\n", mmc_hostname(host->mmc));
sdhci_dumpregs(host);
return;
@@ -1209,6 +1232,8 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
host = mmc_priv(mmc);
+ sdhci_runtime_pm_get(host);
+
spin_lock_irqsave(&host->lock, flags);
WARN_ON(host->mrq != NULL);
@@ -1269,14 +1294,11 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
spin_unlock_irqrestore(&host->lock, flags);
}
-static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
{
- struct sdhci_host *host;
unsigned long flags;
u8 ctrl;
- host = mmc_priv(mmc);
-
spin_lock_irqsave(&host->lock, flags);
if (host->flags & SDHCI_DEVICE_DEAD)
@@ -1426,7 +1448,16 @@ out:
spin_unlock_irqrestore(&host->lock, flags);
}
-static int check_ro(struct sdhci_host *host)
+static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ sdhci_runtime_pm_get(host);
+ sdhci_do_set_ios(host, ios);
+ sdhci_runtime_pm_put(host);
+}
+
+static int sdhci_check_ro(struct sdhci_host *host)
{
unsigned long flags;
int is_readonly;
@@ -1450,19 +1481,16 @@ static int check_ro(struct sdhci_host *host)
#define SAMPLE_COUNT 5
-static int sdhci_get_ro(struct mmc_host *mmc)
+static int sdhci_do_get_ro(struct sdhci_host *host)
{
- struct sdhci_host *host;
int i, ro_count;
- host = mmc_priv(mmc);
-
if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
- return check_ro(host);
+ return sdhci_check_ro(host);
ro_count = 0;
for (i = 0; i < SAMPLE_COUNT; i++) {
- if (check_ro(host)) {
+ if (sdhci_check_ro(host)) {
if (++ro_count > SAMPLE_COUNT / 2)
return 1;
}
@@ -1471,38 +1499,64 @@ static int sdhci_get_ro(struct mmc_host *mmc)
return 0;
}
-static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+static void sdhci_hw_reset(struct mmc_host *mmc)
{
- struct sdhci_host *host;
- unsigned long flags;
+ struct sdhci_host *host = mmc_priv(mmc);
- host = mmc_priv(mmc);
+ if (host->ops && host->ops->hw_reset)
+ host->ops->hw_reset(host);
+}
- spin_lock_irqsave(&host->lock, flags);
+static int sdhci_get_ro(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ int ret;
+ sdhci_runtime_pm_get(host);
+ ret = sdhci_do_get_ro(host);
+ sdhci_runtime_pm_put(host);
+ return ret;
+}
+
+static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
+{
if (host->flags & SDHCI_DEVICE_DEAD)
goto out;
if (enable)
+ host->flags |= SDHCI_SDIO_IRQ_ENABLED;
+ else
+ host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
+
+ /* SDIO IRQ will be enabled as appropriate in runtime resume */
+ if (host->runtime_suspended)
+ goto out;
+
+ if (enable)
sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
else
sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
out:
mmiowb();
+}
+
+static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ unsigned long flags;
+ spin_lock_irqsave(&host->lock, flags);
+ sdhci_enable_sdio_irq_nolock(host, enable);
spin_unlock_irqrestore(&host->lock, flags);
}
-static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
- struct mmc_ios *ios)
+static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
+ struct mmc_ios *ios)
{
- struct sdhci_host *host;
u8 pwr;
u16 clk, ctrl;
u32 present_state;
- host = mmc_priv(mmc);
-
/*
* Signal Voltage Switching is only applicable for Host Controllers
* v3.00 and above.
@@ -1528,7 +1582,7 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
if (!(ctrl & SDHCI_CTRL_VDD_180))
return 0;
else {
- printk(KERN_INFO DRIVER_NAME ": Switching to 3.3V "
+ pr_info(DRIVER_NAME ": Switching to 3.3V "
"signalling voltage failed\n");
return -EIO;
}
@@ -1587,7 +1641,7 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
pwr |= SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
- printk(KERN_INFO DRIVER_NAME ": Switching to 1.8V signalling "
+ pr_info(DRIVER_NAME ": Switching to 1.8V signalling "
"voltage failed, retrying with S18R set to 0\n");
return -EAGAIN;
} else
@@ -1595,6 +1649,20 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
return 0;
}
+static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
+ struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ int err;
+
+ if (host->version < SDHCI_SPEC_300)
+ return 0;
+ sdhci_runtime_pm_get(host);
+ err = sdhci_do_start_signal_voltage_switch(host, ios);
+ sdhci_runtime_pm_put(host);
+ return err;
+}
+
static int sdhci_execute_tuning(struct mmc_host *mmc)
{
struct sdhci_host *host;
@@ -1606,6 +1674,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
host = mmc_priv(mmc);
+ sdhci_runtime_pm_get(host);
disable_irq(host->irq);
spin_lock(&host->lock);
@@ -1623,6 +1692,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
else {
spin_unlock(&host->lock);
enable_irq(host->irq);
+ sdhci_runtime_pm_put(host);
return 0;
}
@@ -1648,7 +1718,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
timeout = 150;
do {
struct mmc_command cmd = {0};
- struct mmc_request mrq = {0};
+ struct mmc_request mrq = {NULL};
if (!tuning_loop_counter && !timeout)
break;
@@ -1694,7 +1764,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
spin_lock(&host->lock);
if (!host->tuning_done) {
- printk(KERN_INFO DRIVER_NAME ": Timeout waiting for "
+ pr_info(DRIVER_NAME ": Timeout waiting for "
"Buffer Read Ready interrupt during tuning "
"procedure, falling back to fixed sampling "
"clock\n");
@@ -1724,7 +1794,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
} else {
if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
- printk(KERN_INFO DRIVER_NAME ": Tuning procedure"
+ pr_info(DRIVER_NAME ": Tuning procedure"
" failed, falling back to fixed sampling"
" clock\n");
err = -EIO;
@@ -1766,18 +1836,16 @@ out:
sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
spin_unlock(&host->lock);
enable_irq(host->irq);
+ sdhci_runtime_pm_put(host);
return err;
}
-static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
+static void sdhci_do_enable_preset_value(struct sdhci_host *host, bool enable)
{
- struct sdhci_host *host;
u16 ctrl;
unsigned long flags;
- host = mmc_priv(mmc);
-
/* Host Controller v3.00 defines preset value registers */
if (host->version < SDHCI_SPEC_300)
return;
@@ -1793,18 +1861,30 @@ static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+ host->flags |= SDHCI_PV_ENABLED;
} else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+ host->flags &= ~SDHCI_PV_ENABLED;
}
spin_unlock_irqrestore(&host->lock, flags);
}
+static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ sdhci_runtime_pm_get(host);
+ sdhci_do_enable_preset_value(host, enable);
+ sdhci_runtime_pm_put(host);
+}
+
static const struct mmc_host_ops sdhci_ops = {
.request = sdhci_request,
.set_ios = sdhci_set_ios,
.get_ro = sdhci_get_ro,
+ .hw_reset = sdhci_hw_reset,
.enable_sdio_irq = sdhci_enable_sdio_irq,
.start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
.execute_tuning = sdhci_execute_tuning,
@@ -1826,19 +1906,19 @@ static void sdhci_tasklet_card(unsigned long param)
spin_lock_irqsave(&host->lock, flags);
- if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
- if (host->mrq) {
- printk(KERN_ERR "%s: Card removed during transfer!\n",
- mmc_hostname(host->mmc));
- printk(KERN_ERR "%s: Resetting controller.\n",
- mmc_hostname(host->mmc));
+ /* Check host->mrq first in case we are runtime suspended */
+ if (host->mrq &&
+ !(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
+ pr_err("%s: Card removed during transfer!\n",
+ mmc_hostname(host->mmc));
+ pr_err("%s: Resetting controller.\n",
+ mmc_hostname(host->mmc));
- sdhci_reset(host, SDHCI_RESET_CMD);
- sdhci_reset(host, SDHCI_RESET_DATA);
+ sdhci_reset(host, SDHCI_RESET_CMD);
+ sdhci_reset(host, SDHCI_RESET_DATA);
- host->mrq->cmd->error = -ENOMEDIUM;
- tasklet_schedule(&host->finish_tasklet);
- }
+ host->mrq->cmd->error = -ENOMEDIUM;
+ tasklet_schedule(&host->finish_tasklet);
}
spin_unlock_irqrestore(&host->lock, flags);
@@ -1854,14 +1934,16 @@ static void sdhci_tasklet_finish(unsigned long param)
host = (struct sdhci_host*)param;
+ spin_lock_irqsave(&host->lock, flags);
+
/*
* If this tasklet gets rescheduled while running, it will
* be run again afterwards but without any active request.
*/
- if (!host->mrq)
+ if (!host->mrq) {
+ spin_unlock_irqrestore(&host->lock, flags);
return;
-
- spin_lock_irqsave(&host->lock, flags);
+ }
del_timer(&host->timer);
@@ -1905,6 +1987,7 @@ static void sdhci_tasklet_finish(unsigned long param)
spin_unlock_irqrestore(&host->lock, flags);
mmc_request_done(host->mmc, mrq);
+ sdhci_runtime_pm_put(host);
}
static void sdhci_timeout_timer(unsigned long data)
@@ -1917,7 +2000,7 @@ static void sdhci_timeout_timer(unsigned long data)
spin_lock_irqsave(&host->lock, flags);
if (host->mrq) {
- printk(KERN_ERR "%s: Timeout waiting for hardware "
+ pr_err("%s: Timeout waiting for hardware "
"interrupt.\n", mmc_hostname(host->mmc));
sdhci_dumpregs(host);
@@ -1963,7 +2046,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
BUG_ON(intmask == 0);
if (!host->cmd) {
- printk(KERN_ERR "%s: Got command interrupt 0x%08x even "
+ pr_err("%s: Got command interrupt 0x%08x even "
"though no command operation was in progress.\n",
mmc_hostname(host->mmc), (unsigned)intmask);
sdhci_dumpregs(host);
@@ -2063,7 +2146,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
}
}
- printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
+ pr_err("%s: Got data interrupt 0x%08x even "
"though no data operation was in progress.\n",
mmc_hostname(host->mmc), (unsigned)intmask);
sdhci_dumpregs(host);
@@ -2080,7 +2163,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
!= MMC_BUS_TEST_R)
host->data->error = -EILSEQ;
else if (intmask & SDHCI_INT_ADMA_ERROR) {
- printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc));
+ pr_err("%s: ADMA error\n", mmc_hostname(host->mmc));
sdhci_show_adma_error(host);
host->data->error = -EIO;
}
@@ -2136,12 +2219,19 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
static irqreturn_t sdhci_irq(int irq, void *dev_id)
{
irqreturn_t result;
- struct sdhci_host* host = dev_id;
+ struct sdhci_host *host = dev_id;
u32 intmask;
int cardint = 0;
spin_lock(&host->lock);
+ if (host->runtime_suspended) {
+ spin_unlock(&host->lock);
+ pr_warning("%s: got irq while runtime suspended\n",
+ mmc_hostname(host->mmc));
+ return IRQ_HANDLED;
+ }
+
intmask = sdhci_readl(host, SDHCI_INT_STATUS);
if (!intmask || intmask == 0xffffffff) {
@@ -2194,7 +2284,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
intmask &= ~SDHCI_INT_ERROR;
if (intmask & SDHCI_INT_BUS_POWER) {
- printk(KERN_ERR "%s: Card is consuming too much power!\n",
+ pr_err("%s: Card is consuming too much power!\n",
mmc_hostname(host->mmc));
sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS);
}
@@ -2207,7 +2297,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
intmask &= ~SDHCI_INT_CARD_INT;
if (intmask) {
- printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
+ pr_err("%s: Unexpected interrupt 0x%08x.\n",
mmc_hostname(host->mmc), intmask);
sdhci_dumpregs(host);
@@ -2275,7 +2365,6 @@ int sdhci_resume_host(struct sdhci_host *host)
return ret;
}
-
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if (host->ops->enable_dma)
host->ops->enable_dma(host);
@@ -2314,6 +2403,90 @@ EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups);
#endif /* CONFIG_PM */
+#ifdef CONFIG_PM_RUNTIME
+
+static int sdhci_runtime_pm_get(struct sdhci_host *host)
+{
+ return pm_runtime_get_sync(host->mmc->parent);
+}
+
+static int sdhci_runtime_pm_put(struct sdhci_host *host)
+{
+ pm_runtime_mark_last_busy(host->mmc->parent);
+ return pm_runtime_put_autosuspend(host->mmc->parent);
+}
+
+int sdhci_runtime_suspend_host(struct sdhci_host *host)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable tuning since we are suspending */
+ if (host->version >= SDHCI_SPEC_300 &&
+ host->tuning_mode == SDHCI_TUNING_MODE_1) {
+ del_timer_sync(&host->tuning_timer);
+ host->flags &= ~SDHCI_NEEDS_RETUNING;
+ }
+
+ spin_lock_irqsave(&host->lock, flags);
+ sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ synchronize_irq(host->irq);
+
+ spin_lock_irqsave(&host->lock, flags);
+ host->runtime_suspended = true;
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host);
+
+int sdhci_runtime_resume_host(struct sdhci_host *host)
+{
+ unsigned long flags;
+ int ret = 0, host_flags = host->flags;
+
+ if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
+ if (host->ops->enable_dma)
+ host->ops->enable_dma(host);
+ }
+
+ sdhci_init(host, 0);
+
+ /* Force clock and power re-program */
+ host->pwr = 0;
+ host->clock = 0;
+ sdhci_do_set_ios(host, &host->mmc->ios);
+
+ sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
+ if (host_flags & SDHCI_PV_ENABLED)
+ sdhci_do_enable_preset_value(host, true);
+
+ /* Set the re-tuning expiration flag */
+ if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
+ (host->tuning_mode == SDHCI_TUNING_MODE_1))
+ host->flags |= SDHCI_NEEDS_RETUNING;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ host->runtime_suspended = false;
+
+ /* Enable SDIO IRQ */
+ if ((host->flags & SDHCI_SDIO_IRQ_ENABLED))
+ sdhci_enable_sdio_irq_nolock(host, true);
+
+ /* Enable Card Detection */
+ sdhci_enable_card_detection(host);
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host);
+
+#endif
+
/*****************************************************************************\
* *
* Device allocation/registration *
@@ -2356,6 +2529,8 @@ int sdhci_add_host(struct sdhci_host *host)
if (debug_quirks)
host->quirks = debug_quirks;
+ if (debug_quirks2)
+ host->quirks2 = debug_quirks2;
sdhci_reset(host, SDHCI_RESET_ALL);
@@ -2363,7 +2538,7 @@ int sdhci_add_host(struct sdhci_host *host)
host->version = (host->version & SDHCI_SPEC_VER_MASK)
>> SDHCI_SPEC_VER_SHIFT;
if (host->version > SDHCI_SPEC_300) {
- printk(KERN_ERR "%s: Unknown controller version (%d). "
+ pr_err("%s: Unknown controller version (%d). "
"You may experience problems.\n", mmc_hostname(mmc),
host->version);
}
@@ -2400,7 +2575,7 @@ int sdhci_add_host(struct sdhci_host *host)
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if (host->ops->enable_dma) {
if (host->ops->enable_dma(host)) {
- printk(KERN_WARNING "%s: No suitable DMA "
+ pr_warning("%s: No suitable DMA "
"available. Falling back to PIO.\n",
mmc_hostname(mmc));
host->flags &=
@@ -2420,7 +2595,7 @@ int sdhci_add_host(struct sdhci_host *host)
if (!host->adma_desc || !host->align_buffer) {
kfree(host->adma_desc);
kfree(host->align_buffer);
- printk(KERN_WARNING "%s: Unable to allocate ADMA "
+ pr_warning("%s: Unable to allocate ADMA "
"buffers. Falling back to standard DMA.\n",
mmc_hostname(mmc));
host->flags &= ~SDHCI_USE_ADMA;
@@ -2448,8 +2623,7 @@ int sdhci_add_host(struct sdhci_host *host)
if (host->max_clk == 0 || host->quirks &
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) {
if (!host->ops->get_max_clock) {
- printk(KERN_ERR
- "%s: Hardware doesn't specify base clock "
+ pr_err("%s: Hardware doesn't specify base clock "
"frequency.\n", mmc_hostname(mmc));
return -ENODEV;
}
@@ -2495,8 +2669,7 @@ int sdhci_add_host(struct sdhci_host *host)
host->timeout_clk = host->ops->get_timeout_clock(host);
} else if (!(host->quirks &
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
- printk(KERN_ERR
- "%s: Hardware doesn't specify timeout clock "
+ pr_err("%s: Hardware doesn't specify timeout clock "
"frequency.\n", mmc_hostname(mmc));
return -ENODEV;
}
@@ -2566,6 +2739,15 @@ int sdhci_add_host(struct sdhci_host *host)
if (caps[1] & SDHCI_DRIVER_TYPE_D)
mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
+ /*
+ * If Power Off Notify capability is enabled by the host,
+ * set notify to short power off notify timeout value.
+ */
+ if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY)
+ mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
+ else
+ mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE;
+
/* Initial value for re-tuning timer count */
host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >>
SDHCI_RETUNING_TIMER_COUNT_SHIFT;
@@ -2655,7 +2837,7 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->ocr_avail_mmc &= host->ocr_avail_mmc;
if (mmc->ocr_avail == 0) {
- printk(KERN_ERR "%s: Hardware doesn't report any "
+ pr_err("%s: Hardware doesn't report any "
"support voltages.\n", mmc_hostname(mmc));
return -ENODEV;
}
@@ -2703,7 +2885,7 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->max_blk_size = (caps[0] & SDHCI_MAX_BLOCK_MASK) >>
SDHCI_MAX_BLOCK_SHIFT;
if (mmc->max_blk_size >= 3) {
- printk(KERN_WARNING "%s: Invalid maximum block size, "
+ pr_warning("%s: Invalid maximum block size, "
"assuming 512 bytes\n", mmc_hostname(mmc));
mmc->max_blk_size = 0;
}
@@ -2742,7 +2924,7 @@ int sdhci_add_host(struct sdhci_host *host)
host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
if (IS_ERR(host->vmmc)) {
- printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc));
+ pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
host->vmmc = NULL;
} else {
regulator_enable(host->vmmc);
@@ -2771,7 +2953,7 @@ int sdhci_add_host(struct sdhci_host *host)
mmc_add_host(mmc);
- printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s\n",
+ pr_info("%s: SDHCI controller on %s [%s] using %s\n",
mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
(host->flags & SDHCI_USE_ADMA) ? "ADMA" :
(host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
@@ -2804,7 +2986,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
host->flags |= SDHCI_DEVICE_DEAD;
if (host->mrq) {
- printk(KERN_ERR "%s: Controller removed during "
+ pr_err("%s: Controller removed during "
" transfer!\n", mmc_hostname(host->mmc));
host->mrq->cmd->error = -ENOMEDIUM;
@@ -2863,9 +3045,9 @@ EXPORT_SYMBOL_GPL(sdhci_free_host);
static int __init sdhci_drv_init(void)
{
- printk(KERN_INFO DRIVER_NAME
+ pr_info(DRIVER_NAME
": Secure Digital Host Controller Interface driver\n");
- printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
+ pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
return 0;
}
@@ -2878,9 +3060,11 @@ module_init(sdhci_drv_init);
module_exit(sdhci_drv_exit);
module_param(debug_quirks, uint, 0444);
+module_param(debug_quirks2, uint, 0444);
MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver");
MODULE_LICENSE("GPL");
MODULE_PARM_DESC(debug_quirks, "Force certain quirks.");
+MODULE_PARM_DESC(debug_quirks2, "Force certain other quirks.");
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 745c42fa41ed..0a5b65460d8a 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -273,7 +273,7 @@ struct sdhci_ops {
void (*platform_reset_enter)(struct sdhci_host *host, u8 mask);
void (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
-
+ void (*hw_reset)(struct sdhci_host *host);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
@@ -379,4 +379,9 @@ extern int sdhci_resume_host(struct sdhci_host *host);
extern void sdhci_enable_irq_wakeups(struct sdhci_host *host);
#endif
+#ifdef CONFIG_PM_RUNTIME
+extern int sdhci_runtime_suspend_host(struct sdhci_host *host);
+extern int sdhci_runtime_resume_host(struct sdhci_host *host);
+#endif
+
#endif /* __SDHCI_HW_H */
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c
index 496b7efbc6b0..7009f17ad6cd 100644
--- a/drivers/mmc/host/sdricoh_cs.c
+++ b/drivers/mmc/host/sdricoh_cs.c
@@ -26,6 +26,7 @@
*/
#include <linux/delay.h>
#include <linux/highmem.h>
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/scatterlist.h>
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 557886bee9ce..369366c8e205 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -31,6 +31,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/spinlock.h>
+#include <linux/module.h>
#define DRIVER_NAME "sh_mmcif"
#define DRIVER_VERSION "2010-04-28"
@@ -165,6 +166,8 @@ struct sh_mmcif_host {
struct mmc_host *mmc;
struct mmc_data *data;
struct platform_device *pd;
+ struct sh_dmae_slave dma_slave_tx;
+ struct sh_dmae_slave dma_slave_rx;
struct clk *hclk;
unsigned int clk;
int bus_width;
@@ -323,25 +326,35 @@ static bool sh_mmcif_filter(struct dma_chan *chan, void *arg)
static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
struct sh_mmcif_plat_data *pdata)
{
+ struct sh_dmae_slave *tx, *rx;
host->dma_active = false;
/* We can only either use DMA for both Tx and Rx or not use it at all */
if (pdata->dma) {
+ dev_warn(&host->pd->dev,
+ "Update your platform to use embedded DMA slave IDs\n");
+ tx = &pdata->dma->chan_priv_tx;
+ rx = &pdata->dma->chan_priv_rx;
+ } else {
+ tx = &host->dma_slave_tx;
+ tx->slave_id = pdata->slave_id_tx;
+ rx = &host->dma_slave_rx;
+ rx->slave_id = pdata->slave_id_rx;
+ }
+ if (tx->slave_id > 0 && rx->slave_id > 0) {
dma_cap_mask_t mask;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- host->chan_tx = dma_request_channel(mask, sh_mmcif_filter,
- &pdata->dma->chan_priv_tx);
+ host->chan_tx = dma_request_channel(mask, sh_mmcif_filter, tx);
dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
host->chan_tx);
if (!host->chan_tx)
return;
- host->chan_rx = dma_request_channel(mask, sh_mmcif_filter,
- &pdata->dma->chan_priv_rx);
+ host->chan_rx = dma_request_channel(mask, sh_mmcif_filter, rx);
dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
host->chan_rx);
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 0c4a672f5db6..41ae6466bd83 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mobile_sdhi.h>
@@ -96,7 +97,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
struct tmio_mmc_host *host;
char clk_name[8];
- int i, irq, ret;
+ int irq, ret, i = 0;
+ bool multiplexed_isr = true;
priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL);
if (priv == NULL) {
@@ -153,27 +155,60 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
if (ret < 0)
goto eprobe;
- for (i = 0; i < 3; i++) {
- irq = platform_get_irq(pdev, i);
- if (irq < 0) {
- if (i) {
- continue;
- } else {
- ret = irq;
- goto eirq;
- }
- }
- ret = request_irq(irq, tmio_mmc_irq, 0,
+ /*
+ * Allow one or more specific (named) ISRs or
+ * one or more multiplexed (un-named) ISRs.
+ */
+
+ irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT);
+ if (irq >= 0) {
+ multiplexed_isr = false;
+ ret = request_irq(irq, tmio_mmc_card_detect_irq, 0,
+ dev_name(&pdev->dev), host);
+ if (ret)
+ goto eirq_card_detect;
+ }
+
+ irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO);
+ if (irq >= 0) {
+ multiplexed_isr = false;
+ ret = request_irq(irq, tmio_mmc_sdio_irq, 0,
+ dev_name(&pdev->dev), host);
+ if (ret)
+ goto eirq_sdio;
+ }
+
+ irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDCARD);
+ if (irq >= 0) {
+ multiplexed_isr = false;
+ ret = request_irq(irq, tmio_mmc_sdcard_irq, 0,
dev_name(&pdev->dev), host);
- if (ret) {
- while (i--) {
- irq = platform_get_irq(pdev, i);
- if (irq >= 0)
- free_irq(irq, host);
- }
- goto eirq;
+ if (ret)
+ goto eirq_sdcard;
+ } else if (!multiplexed_isr) {
+ dev_err(&pdev->dev,
+ "Principal SD-card IRQ is missing among named interrupts\n");
+ ret = irq;
+ goto eirq_sdcard;
+ }
+
+ if (multiplexed_isr) {
+ while (1) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ break;
+ i++;
+ ret = request_irq(irq, tmio_mmc_irq, 0,
+ dev_name(&pdev->dev), host);
+ if (ret)
+ goto eirq_multiplexed;
}
+
+ /* There must be at least one IRQ source */
+ if (!i)
+ goto eirq_multiplexed;
}
+
dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n",
mmc_hostname(host->mmc), (unsigned long)
(platform_get_resource(pdev,IORESOURCE_MEM, 0)->start),
@@ -181,7 +216,20 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
return ret;
-eirq:
+eirq_multiplexed:
+ while (i--) {
+ irq = platform_get_irq(pdev, i);
+ free_irq(irq, host);
+ }
+eirq_sdcard:
+ irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO);
+ if (irq >= 0)
+ free_irq(irq, host);
+eirq_sdio:
+ irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT);
+ if (irq >= 0)
+ free_irq(irq, host);
+eirq_card_detect:
tmio_mmc_host_remove(host);
eprobe:
clk_disable(priv->clk);
@@ -197,16 +245,17 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
struct tmio_mmc_host *host = mmc_priv(mmc);
struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
- int i, irq;
+ int i = 0, irq;
p->pdata = NULL;
tmio_mmc_host_remove(host);
- for (i = 0; i < 3; i++) {
- irq = platform_get_irq(pdev, i);
- if (irq >= 0)
- free_irq(irq, host);
+ while (1) {
+ irq = platform_get_irq(pdev, i++);
+ if (irq < 0)
+ break;
+ free_irq(irq, host);
}
clk_disable(priv->clk);
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c
index 457c26ea09de..f70d04664cac 100644
--- a/drivers/mmc/host/tifm_sd.c
+++ b/drivers/mmc/host/tifm_sd.c
@@ -16,6 +16,7 @@
#include <linux/mmc/host.h>
#include <linux/highmem.h>
#include <linux/scatterlist.h>
+#include <linux/module.h>
#include <asm/io.h>
#define DRIVER_NAME "tifm_sd"
@@ -631,7 +632,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
}
if (host->req) {
- printk(KERN_ERR "%s : unfinished request detected\n",
+ pr_err("%s : unfinished request detected\n",
dev_name(&sock->dev));
mrq->cmd->error = -ETIMEDOUT;
goto err_out;
@@ -671,7 +672,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
r_data->flags & MMC_DATA_WRITE
? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE)) {
- printk(KERN_ERR "%s : scatterlist map failed\n",
+ pr_err("%s : scatterlist map failed\n",
dev_name(&sock->dev));
mrq->cmd->error = -ENOMEM;
goto err_out;
@@ -683,7 +684,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE);
if (host->sg_len < 1) {
- printk(KERN_ERR "%s : scatterlist map failed\n",
+ pr_err("%s : scatterlist map failed\n",
dev_name(&sock->dev));
tifm_unmap_sg(sock, &host->bounce_buf, 1,
r_data->flags & MMC_DATA_WRITE
@@ -747,7 +748,7 @@ static void tifm_sd_end_cmd(unsigned long data)
host->req = NULL;
if (!mrq) {
- printk(KERN_ERR " %s : no request to complete?\n",
+ pr_err(" %s : no request to complete?\n",
dev_name(&sock->dev));
spin_unlock_irqrestore(&sock->lock, flags);
return;
@@ -786,8 +787,7 @@ static void tifm_sd_abort(unsigned long data)
{
struct tifm_sd *host = (struct tifm_sd*)data;
- printk(KERN_ERR
- "%s : card failed to respond for a long period of time "
+ pr_err("%s : card failed to respond for a long period of time "
"(%x, %x)\n",
dev_name(&host->dev->dev), host->req->cmd->opcode, host->cmd_flags);
@@ -905,7 +905,7 @@ static int tifm_sd_initialize_host(struct tifm_sd *host)
}
if (rc) {
- printk(KERN_ERR "%s : controller failed to reset\n",
+ pr_err("%s : controller failed to reset\n",
dev_name(&sock->dev));
return -ENODEV;
}
@@ -931,8 +931,7 @@ static int tifm_sd_initialize_host(struct tifm_sd *host)
}
if (rc) {
- printk(KERN_ERR
- "%s : card not ready - probe failed on initialization\n",
+ pr_err("%s : card not ready - probe failed on initialization\n",
dev_name(&sock->dev));
return -ENODEV;
}
@@ -953,7 +952,7 @@ static int tifm_sd_probe(struct tifm_dev *sock)
if (!(TIFM_SOCK_STATE_OCCUPIED
& readl(sock->addr + SOCK_PRESENT_STATE))) {
- printk(KERN_WARNING "%s : card gone, unexpectedly\n",
+ pr_warning("%s : card gone, unexpectedly\n",
dev_name(&sock->dev));
return rc;
}
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 44a9668c4b7a..a4ea10242787 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -88,8 +88,8 @@ static int __devinit tmio_mmc_probe(struct platform_device *pdev)
if (ret)
goto cell_disable;
- ret = request_irq(irq, tmio_mmc_irq, IRQF_DISABLED |
- IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), host);
+ ret = request_irq(irq, tmio_mmc_irq, IRQF_TRIGGER_FALLING,
+ dev_name(&pdev->dev), host);
if (ret)
goto host_remove;
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index eeaf64391fbe..3020f98218f0 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -79,6 +79,10 @@ struct tmio_mmc_host {
struct delayed_work delayed_reset_work;
struct work_struct done;
+ /* Cache IRQ mask */
+ u32 sdcard_irq_mask;
+ u32 sdio_irq_mask;
+
spinlock_t lock; /* protect host private data */
unsigned long last_req_ts;
struct mutex ios_lock; /* protect set_ios() context */
@@ -93,6 +97,9 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host);
void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
irqreturn_t tmio_mmc_irq(int irq, void *devid);
+irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid);
+irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid);
+irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid);
static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
unsigned long *flags)
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 1f16357e7301..d85a60cda167 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -48,14 +48,14 @@
void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i)
{
- u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) & ~(i & TMIO_MASK_IRQ);
- sd_ctrl_write32(host, CTL_IRQ_MASK, mask);
+ host->sdcard_irq_mask &= ~(i & TMIO_MASK_IRQ);
+ sd_ctrl_write32(host, CTL_IRQ_MASK, host->sdcard_irq_mask);
}
void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i)
{
- u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) | (i & TMIO_MASK_IRQ);
- sd_ctrl_write32(host, CTL_IRQ_MASK, mask);
+ host->sdcard_irq_mask |= (i & TMIO_MASK_IRQ);
+ sd_ctrl_write32(host, CTL_IRQ_MASK, host->sdcard_irq_mask);
}
static void tmio_mmc_ack_mmc_irqs(struct tmio_mmc_host *host, u32 i)
@@ -92,7 +92,7 @@ static int tmio_mmc_next_sg(struct tmio_mmc_host *host)
static void pr_debug_status(u32 status)
{
int i = 0;
- printk(KERN_DEBUG "status: %08x = ", status);
+ pr_debug("status: %08x = ", status);
STATUS_TO_TEXT(CARD_REMOVE, status, i);
STATUS_TO_TEXT(CARD_INSERT, status, i);
STATUS_TO_TEXT(SIGSTATE, status, i);
@@ -127,11 +127,13 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
if (enable) {
host->sdio_irq_enabled = 1;
+ host->sdio_irq_mask = TMIO_SDIO_MASK_ALL &
+ ~TMIO_SDIO_STAT_IOIRQ;
sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
- sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK,
- (TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ));
+ sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask);
} else {
- sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL);
+ host->sdio_irq_mask = TMIO_SDIO_MASK_ALL;
+ sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask);
sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
host->sdio_irq_enabled = 0;
}
@@ -543,45 +545,20 @@ out:
spin_unlock(&host->lock);
}
-irqreturn_t tmio_mmc_irq(int irq, void *devid)
+static void tmio_mmc_card_irq_status(struct tmio_mmc_host *host,
+ int *ireg, int *status)
{
- struct tmio_mmc_host *host = devid;
- struct mmc_host *mmc = host->mmc;
- struct tmio_mmc_data *pdata = host->pdata;
- unsigned int ireg, irq_mask, status;
- unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
-
- pr_debug("MMC IRQ begin\n");
-
- status = sd_ctrl_read32(host, CTL_STATUS);
- irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
- ireg = status & TMIO_MASK_IRQ & ~irq_mask;
-
- sdio_ireg = 0;
- if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) {
- sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
- sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK);
- sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ~sdio_irq_mask;
+ *status = sd_ctrl_read32(host, CTL_STATUS);
+ *ireg = *status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask;
- sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL);
-
- if (sdio_ireg && !host->sdio_irq_enabled) {
- pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n",
- sdio_status, sdio_irq_mask, sdio_ireg);
- tmio_mmc_enable_sdio_irq(mmc, 0);
- goto out;
- }
-
- if (mmc->caps & MMC_CAP_SDIO_IRQ &&
- sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
- mmc_signal_sdio_irq(mmc);
-
- if (sdio_ireg)
- goto out;
- }
+ pr_debug_status(*status);
+ pr_debug_status(*ireg);
+}
- pr_debug_status(status);
- pr_debug_status(ireg);
+static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host,
+ int ireg, int status)
+{
+ struct mmc_host *mmc = host->mmc;
/* Card insert / remove attempts */
if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
@@ -591,43 +568,102 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) &&
!work_pending(&mmc->detect.work))
mmc_detect_change(host->mmc, msecs_to_jiffies(100));
- goto out;
+ return true;
}
- /* CRC and other errors */
-/* if (ireg & TMIO_STAT_ERR_IRQ)
- * handled |= tmio_error_irq(host, irq, stat);
- */
+ return false;
+}
+
+irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid)
+{
+ unsigned int ireg, status;
+ struct tmio_mmc_host *host = devid;
+
+ tmio_mmc_card_irq_status(host, &ireg, &status);
+ __tmio_mmc_card_detect_irq(host, ireg, status);
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(tmio_mmc_card_detect_irq);
+
+static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host,
+ int ireg, int status)
+{
/* Command completion */
if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
tmio_mmc_ack_mmc_irqs(host,
TMIO_STAT_CMDRESPEND |
TMIO_STAT_CMDTIMEOUT);
tmio_mmc_cmd_irq(host, status);
- goto out;
+ return true;
}
/* Data transfer */
if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
tmio_mmc_pio_irq(host);
- goto out;
+ return true;
}
/* Data transfer completion */
if (ireg & TMIO_STAT_DATAEND) {
tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
tmio_mmc_data_irq(host);
- goto out;
+ return true;
}
- pr_warning("tmio_mmc: Spurious irq, disabling! "
- "0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
- pr_debug_status(status);
- tmio_mmc_disable_mmc_irqs(host, status & ~irq_mask);
+ return false;
+}
+
+irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid)
+{
+ unsigned int ireg, status;
+ struct tmio_mmc_host *host = devid;
+
+ tmio_mmc_card_irq_status(host, &ireg, &status);
+ __tmio_mmc_sdcard_irq(host, ireg, status);
+
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(tmio_mmc_sdcard_irq);
+
+irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid)
+{
+ struct tmio_mmc_host *host = devid;
+ struct mmc_host *mmc = host->mmc;
+ struct tmio_mmc_data *pdata = host->pdata;
+ unsigned int ireg, status;
+
+ if (!(pdata->flags & TMIO_MMC_SDIO_IRQ))
+ return IRQ_HANDLED;
+
+ status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
+ ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask;
+
+ sd_ctrl_write16(host, CTL_SDIO_STATUS, status & ~TMIO_SDIO_MASK_ALL);
+
+ if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ)
+ mmc_signal_sdio_irq(mmc);
+
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(tmio_mmc_sdio_irq);
+
+irqreturn_t tmio_mmc_irq(int irq, void *devid)
+{
+ struct tmio_mmc_host *host = devid;
+ unsigned int ireg, status;
+
+ pr_debug("MMC IRQ begin\n");
+
+ tmio_mmc_card_irq_status(host, &ireg, &status);
+ if (__tmio_mmc_card_detect_irq(host, ireg, status))
+ return IRQ_HANDLED;
+ if (__tmio_mmc_sdcard_irq(host, ireg, status))
+ return IRQ_HANDLED;
+
+ tmio_mmc_sdio_irq(irq, devid);
-out:
return IRQ_HANDLED;
}
EXPORT_SYMBOL(tmio_mmc_irq);
@@ -882,6 +918,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
tmio_mmc_clk_stop(_host);
tmio_mmc_reset(_host);
+ _host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK);
tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL);
if (pdata->flags & TMIO_MMC_SDIO_IRQ)
tmio_mmc_enable_sdio_irq(mmc, 0);
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index 4dfe2c02ea91..4b83c43f950d 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -9,6 +9,7 @@
*/
#include <linux/pci.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/highmem.h>
#include <linux/delay.h>
@@ -1191,7 +1192,7 @@ static void __devexit via_sd_remove(struct pci_dev *pcidev)
mmiowb();
if (sdhost->mrq) {
- printk(KERN_ERR "%s: Controller removed during "
+ pr_err("%s: Controller removed during "
"transfer\n", mmc_hostname(sdhost->mmc));
/* make sure all DMA is stopped */
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index 62e5a4d171e1..64acd9ce141c 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -194,7 +194,7 @@ static void wbsd_reset(struct wbsd_host *host)
{
u8 setup;
- printk(KERN_ERR "%s: Resetting chip\n", mmc_hostname(host->mmc));
+ pr_err("%s: Resetting chip\n", mmc_hostname(host->mmc));
/*
* Soft reset of chip (SD/MMC part).
@@ -721,7 +721,7 @@ static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
* Any leftover data?
*/
if (count) {
- printk(KERN_ERR "%s: Incomplete DMA transfer. "
+ pr_err("%s: Incomplete DMA transfer. "
"%d bytes left.\n",
mmc_hostname(host->mmc), count);
@@ -803,7 +803,7 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
default:
#ifdef CONFIG_MMC_DEBUG
- printk(KERN_WARNING "%s: Data command %d is not "
+ pr_warning("%s: Data command %d is not "
"supported by this controller.\n",
mmc_hostname(host->mmc), cmd->opcode);
#endif
@@ -1029,7 +1029,7 @@ static void wbsd_tasklet_card(unsigned long param)
host->flags &= ~WBSD_FCARD_PRESENT;
if (host->mrq) {
- printk(KERN_ERR "%s: Card removed during transfer!\n",
+ pr_err("%s: Card removed during transfer!\n",
mmc_hostname(host->mmc));
wbsd_reset(host);
@@ -1429,7 +1429,7 @@ free:
free_dma(dma);
err:
- printk(KERN_WARNING DRIVER_NAME ": Unable to allocate DMA %d. "
+ pr_warning(DRIVER_NAME ": Unable to allocate DMA %d. "
"Falling back on FIFO.\n", dma);
}
@@ -1664,7 +1664,7 @@ static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
ret = wbsd_scan(host);
if (ret) {
if (pnp && (ret == -ENODEV)) {
- printk(KERN_WARNING DRIVER_NAME
+ pr_warning(DRIVER_NAME
": Unable to confirm device presence. You may "
"experience lock-ups.\n");
} else {
@@ -1688,7 +1688,7 @@ static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
*/
if (pnp) {
if ((host->config != 0) && !wbsd_chip_validate(host)) {
- printk(KERN_WARNING DRIVER_NAME
+ pr_warning(DRIVER_NAME
": PnP active but chip not configured! "
"You probably have a buggy BIOS. "
"Configuring chip manually.\n");
@@ -1720,7 +1720,7 @@ static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
mmc_add_host(mmc);
- printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
+ pr_info("%s: W83L51xD", mmc_hostname(mmc));
if (host->chip_id != 0)
printk(" id %x", (int)host->chip_id);
printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
@@ -1909,7 +1909,7 @@ static int wbsd_pnp_resume(struct pnp_dev *pnp_dev)
*/
if (host->config != 0) {
if (!wbsd_chip_validate(host)) {
- printk(KERN_WARNING DRIVER_NAME
+ pr_warning(DRIVER_NAME
": PnP active but chip not configured! "
"You probably have a buggy BIOS. "
"Configuring chip manually.\n");
@@ -1973,9 +1973,9 @@ static int __init wbsd_drv_init(void)
{
int result;
- printk(KERN_INFO DRIVER_NAME
+ pr_info(DRIVER_NAME
": Winbond W83L51xD SD/MMC card interface driver\n");
- printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
+ pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
#ifdef CONFIG_PNP
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 4be8373d43e5..66b616ebe536 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -142,7 +142,7 @@ config MTD_OF_PARTS
help
This provides a partition parsing function which derives
the partition map from the children of the flash node,
- as described in Documentation/powerpc/booting-without-of.txt.
+ as described in Documentation/devicetree/booting-without-of.txt.
config MTD_AR7_PARTS
tristate "TI AR7 partitioning support"
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index f1af2228a1b1..61086ea3cc6b 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1144,7 +1144,7 @@ static void mtdchar_notify_remove(struct mtd_info *mtd)
if (mtd_ino) {
/* Destroy the inode if it exists */
- mtd_ino->i_nlink = 0;
+ clear_nlink(mtd_ino);
iput(mtd_ino);
}
}
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index 78017eb9318e..9e6b498c9beb 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -26,7 +26,7 @@
#include <asm/io.h>
#include <mach/hardware.h>
#include <asm/sizes.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <plat/board-ams-delta.h>
/*
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index a916dec29215..6a1d6d9a2df9 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -40,7 +40,7 @@
#include <asm/mach/flash.h>
#include <plat/gpmc.h>
#include <plat/onenand.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <plat/dma.h>
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index a44874e24f2a..583f66cd5bbd 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2,9 +2,6 @@
# Network device configuration
#
-config HAVE_NET_MACB
- bool
-
menuconfig NETDEVICES
default y if UML
depends on NET
@@ -28,18 +25,32 @@ menuconfig NETDEVICES
# that for each of the symbols.
if NETDEVICES
-config IFB
- tristate "Intermediate Functional Block support"
- depends on NET_CLS_ACT
+config NET_CORE
+ default y
+ bool "Network core driver support"
---help---
- This is an intermediate driver that allows sharing of
- resources.
+ You can say N here if you do not intend to use any of the
+ networking core drivers (i.e. VLAN, bridging, bonding, etc.)
+
+if NET_CORE
+
+config BONDING
+ tristate "Bonding driver support"
+ depends on INET
+ depends on IPV6 || IPV6=n
+ ---help---
+ Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
+ Channels together. This is called 'Etherchannel' by Cisco,
+ 'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux.
+
+ The driver supports multiple bonding modes to allow for both high
+ performance and high availability operation.
+
+ Refer to <file:Documentation/networking/bonding.txt> for more
+ information.
+
To compile this driver as a module, choose M here: the module
- will be called ifb. If you want to use more than one ifb
- device at a time, you need to compile this driver as a module.
- Instead of 'ifb', the devices will then be called 'ifb0',
- 'ifb1' etc.
- Look at the iproute2 documentation directory for usage etc
+ will be called bonding.
config DUMMY
tristate "Dummy net driver support"
@@ -60,23 +71,59 @@ config DUMMY
Instead of 'dummy', the devices will then be called 'dummy0',
'dummy1' etc.
-config BONDING
- tristate "Bonding driver support"
- depends on INET
- depends on IPV6 || IPV6=n
+config EQUALIZER
+ tristate "EQL (serial line load balancing) support"
---help---
- Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
- Channels together. This is called 'Etherchannel' by Cisco,
- 'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux.
+ If you have two serial connections to some other computer (this
+ usually requires two modems and two telephone lines) and you use
+ SLIP (the protocol for sending Internet traffic over telephone
+ lines) or PPP (a better SLIP) on them, you can make them behave like
+ one double speed connection using this driver. Naturally, this has
+ to be supported at the other end as well, either with a similar EQL
+ Linux driver or with a Livingston Portmaster 2e.
- The driver supports multiple bonding modes to allow for both high
- performance and high availability operation.
+ Say Y if you want this and read
+ <file:Documentation/networking/eql.txt>. You may also want to read
+ section 6.2 of the NET-3-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
- Refer to <file:Documentation/networking/bonding.txt> for more
- information.
+ To compile this driver as a module, choose M here: the module
+ will be called eql. If unsure, say N.
+
+config NET_FC
+ bool "Fibre Channel driver support"
+ depends on SCSI && PCI
+ help
+ Fibre Channel is a high speed serial protocol mainly used to connect
+ large storage devices to the computer; it is compatible with and
+ intended to replace SCSI.
+
+ If you intend to use Fibre Channel, you need to have a Fibre channel
+ adaptor card in your computer; say Y here and to the driver for your
+ adaptor below. You also should have said Y to "SCSI support" and
+ "SCSI generic support".
+
+config MII
+ tristate "Generic Media Independent Interface device support"
+ help
+ Most ethernet controllers have MII transceiver either as an external
+ or internal device. It is safe to say Y or M here even if your
+ ethernet card lacks MII.
+source "drivers/ieee802154/Kconfig"
+
+config IFB
+ tristate "Intermediate Functional Block support"
+ depends on NET_CLS_ACT
+ ---help---
+ This is an intermediate driver that allows sharing of
+ resources.
To compile this driver as a module, choose M here: the module
- will be called bonding.
+ will be called ifb. If you want to use more than one ifb
+ device at a time, you need to compile this driver as a module.
+ Instead of 'ifb', the devices will then be called 'ifb0',
+ 'ifb1' etc.
+ Look at the iproute2 documentation directory for usage etc
config MACVLAN
tristate "MAC-VLAN support (EXPERIMENTAL)"
@@ -105,24 +152,46 @@ config MACVTAP
To compile this driver as a module, choose M here: the module
will be called macvtap.
-config EQUALIZER
- tristate "EQL (serial line load balancing) support"
+config NETCONSOLE
+ tristate "Network console logging support"
---help---
- If you have two serial connections to some other computer (this
- usually requires two modems and two telephone lines) and you use
- SLIP (the protocol for sending Internet traffic over telephone
- lines) or PPP (a better SLIP) on them, you can make them behave like
- one double speed connection using this driver. Naturally, this has
- to be supported at the other end as well, either with a similar EQL
- Linux driver or with a Livingston Portmaster 2e.
+ If you want to log kernel messages over the network, enable this.
+ See <file:Documentation/networking/netconsole.txt> for details.
- Say Y if you want this and read
- <file:Documentation/networking/eql.txt>. You may also want to read
- section 6.2 of the NET-3-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
+config NETCONSOLE_DYNAMIC
+ bool "Dynamic reconfiguration of logging targets"
+ depends on NETCONSOLE && SYSFS && CONFIGFS_FS && \
+ !(NETCONSOLE=y && CONFIGFS_FS=m)
+ help
+ This option enables the ability to dynamically reconfigure target
+ parameters (interface, IP addresses, port numbers, MAC addresses)
+ at runtime through a userspace interface exported using configfs.
+ See <file:Documentation/networking/netconsole.txt> for details.
- To compile this driver as a module, choose M here: the module
- will be called eql. If unsure, say N.
+config NETPOLL
+ def_bool NETCONSOLE
+
+config NETPOLL_TRAP
+ bool "Netpoll traffic trapping"
+ default n
+ depends on NETPOLL
+
+config NET_POLL_CONTROLLER
+ def_bool NETPOLL
+
+config RIONET
+ tristate "RapidIO Ethernet over messaging driver support"
+ depends on RAPIDIO
+
+config RIONET_TX_SIZE
+ int "Number of outbound queue entries"
+ depends on RIONET
+ default "128"
+
+config RIONET_RX_SIZE
+ int "Number of inbound queue entries"
+ depends on RIONET
+ default "128"
config TUN
tristate "Universal TUN/TAP device driver support"
@@ -154,6 +223,28 @@ config VETH
When one end receives the packet it appears on its pair and vice
versa.
+config VIRTIO_NET
+ tristate "Virtio network driver (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && VIRTIO
+ ---help---
+ This is the virtual network driver for virtio. It can be used with
+ lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
+
+endif # NET_CORE
+
+config SUNGEM_PHY
+ tristate
+
+source "drivers/net/arcnet/Kconfig"
+
+source "drivers/atm/Kconfig"
+
+source "drivers/net/caif/Kconfig"
+
+source "drivers/net/ethernet/Kconfig"
+
+source "drivers/net/fddi/Kconfig"
+
config NET_SB1000
tristate "General Instruments Surfboard 1000"
depends on PNP
@@ -178,2791 +269,26 @@ config NET_SB1000
If you don't have this card, of course say N.
-source "drivers/net/arcnet/Kconfig"
-
-config MII
- tristate "Generic Media Independent Interface device support"
- help
- Most ethernet controllers have MII transceiver either as an external
- or internal device. It is safe to say Y or M here even if your
- ethernet card lacks MII.
-
source "drivers/net/phy/Kconfig"
-#
-# Ethernet
-#
+source "drivers/net/plip/Kconfig"
-menuconfig NET_ETHERNET
- bool "Ethernet (10 or 100Mbit)"
- depends on !UML
- ---help---
- Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
- type of Local Area Network (LAN) in universities and companies.
-
- Common varieties of Ethernet are: 10BASE-2 or Thinnet (10 Mbps over
- coaxial cable, linking computers in a chain), 10BASE-T or twisted
- pair (10 Mbps over twisted pair cable, linking computers to central
- hubs), 10BASE-F (10 Mbps over optical fiber links, using hubs),
- 100BASE-TX (100 Mbps over two twisted pair cables, using hubs),
- 100BASE-T4 (100 Mbps over 4 standard voice-grade twisted pair
- cables, using hubs), 100BASE-FX (100 Mbps over optical fiber links)
- [the 100BASE varieties are also known as Fast Ethernet], and Gigabit
- Ethernet (1 Gbps over optical fiber or short copper links).
-
- If your Linux machine will be connected to an Ethernet and you have
- an Ethernet network interface card (NIC) installed in your computer,
- say Y here and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>. You will then also have
- to say Y to the driver for your particular NIC.
-
- Note that the answer to this question won't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about Ethernet network cards. If unsure, say N.
-
-if NET_ETHERNET
-
-config MACB
- tristate "Atmel MACB support"
- depends on HAVE_NET_MACB
- select PHYLIB
- help
- The Atmel MACB ethernet interface is found on many AT32 and AT91
- parts. Say Y to include support for the MACB chip.
+source "drivers/net/ppp/Kconfig"
- To compile this driver as a module, choose M here: the module
- will be called macb.
+source "drivers/net/slip/Kconfig"
-source "drivers/net/arm/Kconfig"
-
-config AX88796
- tristate "ASIX AX88796 NE2000 clone support"
- depends on ARM || MIPS || SUPERH
- select PHYLIB
- select MDIO_BITBANG
- help
- AX88796 driver, using platform bus to provide
- chip detection and resources
-
-config AX88796_93CX6
- bool "ASIX AX88796 external 93CX6 eeprom support"
- depends on AX88796
- select EEPROM_93CX6
- help
- Select this if your platform comes with an external 93CX6 eeprom.
-
-config MACE
- tristate "MACE (Power Mac ethernet) support"
- depends on PPC_PMAC && PPC32
- select CRC32
- help
- Power Macintoshes and clones with Ethernet built-in on the
- motherboard will usually use a MACE (Medium Access Control for
- Ethernet) interface. Say Y to include support for the MACE chip.
-
- To compile this driver as a module, choose M here: the module
- will be called mace.
-
-config MACE_AAUI_PORT
- bool "Use AAUI port instead of TP by default"
- depends on MACE
- help
- Some Apple machines (notably the Apple Network Server) which use the
- MACE ethernet chip have an Apple AUI port (small 15-pin connector),
- instead of an 8-pin RJ45 connector for twisted-pair ethernet. Say
- Y here if you have such a machine. If unsure, say N.
- The driver will default to AAUI on ANS anyway, and if you use it as
- a module, you can provide the port_aaui=0|1 to force the driver.
-
-config BMAC
- tristate "BMAC (G3 ethernet) support"
- depends on PPC_PMAC && PPC32
- select CRC32
- help
- Say Y for support of BMAC Ethernet interfaces. These are used on G3
- computers.
-
- To compile this driver as a module, choose M here: the module
- will be called bmac.
-
-config ARIADNE
- tristate "Ariadne support"
- depends on ZORRO
- help
- If you have a Village Tronic Ariadne Ethernet adapter, say Y.
- Otherwise, say N.
-
- To compile this driver as a module, choose M here: the module
- will be called ariadne.
-
-config A2065
- tristate "A2065 support"
- depends on ZORRO
- select CRC32
- help
- If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
- say N.
-
- To compile this driver as a module, choose M here: the module
- will be called a2065.
-
-config HYDRA
- tristate "Hydra support"
- depends on ZORRO
- select CRC32
- help
- If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
-
- To compile this driver as a module, choose M here: the module
- will be called hydra.
-
-config ZORRO8390
- tristate "Zorro NS8390-based Ethernet support"
- depends on ZORRO
- select CRC32
- help
- This driver is for Zorro Ethernet cards using an NS8390-compatible
- chipset, like the Village Tronic Ariadne II and the Individual
- Computers X-Surf Ethernet cards. If you have such a card, say Y.
- Otherwise, say N.
-
- To compile this driver as a module, choose M here: the module
- will be called zorro8390.
-
-config APNE
- tristate "PCMCIA NE2000 support"
- depends on AMIGA_PCMCIA
- select CRC32
- help
- If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
- say N.
-
- To compile this driver as a module, choose M here: the module
- will be called apne.
-
-config MAC8390
- bool "Macintosh NS 8390 based ethernet cards"
- depends on MAC
- select CRC32
- help
- If you want to include a driver to support Nubus or LC-PDS
- Ethernet cards using an NS8390 chipset or its equivalent, say Y
- and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
-config MAC89x0
- tristate "Macintosh CS89x0 based ethernet cards"
- depends on MAC
- ---help---
- Support for CS89x0 chipset based Ethernet cards. If you have a
- Nubus or LC-PDS network (Ethernet) card of this type, say Y and
- read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. This module will
- be called mac89x0.
-
-config MACSONIC
- tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
- depends on MAC
- ---help---
- Support for NatSemi SONIC based Ethernet devices. This includes
- the onboard Ethernet in many Quadras as well as some LC-PDS,
- a few Nubus and all known Comm Slot Ethernet cards. If you have
- one of these say Y and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. This module will
- be called macsonic.
-
-config MACMACE
- bool "Macintosh (AV) onboard MACE ethernet"
- depends on MAC
- select CRC32
- help
- Support for the onboard AMD 79C940 MACE Ethernet controller used in
- the 660AV and 840AV Macintosh. If you have one of these Macintoshes
- say Y and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
-config MVME147_NET
- tristate "MVME147 (Lance) Ethernet support"
- depends on MVME147
- select CRC32
- help
- Support for the on-board Ethernet interface on the Motorola MVME147
- single-board computer. Say Y here to include the
- driver for this chip in your kernel.
- To compile this driver as a module, choose M here.
-
-config MVME16x_NET
- tristate "MVME16x Ethernet support"
- depends on MVME16x
- help
- This is the driver for the Ethernet interface on the Motorola
- MVME162, 166, 167, 172 and 177 boards. Say Y here to include the
- driver for this chip in your kernel.
- To compile this driver as a module, choose M here.
-
-config BVME6000_NET
- tristate "BVME6000 Ethernet support"
- depends on BVME6000
- help
- This is the driver for the Ethernet interface on BVME4000 and
- BVME6000 VME boards. Say Y here to include the driver for this chip
- in your kernel.
- To compile this driver as a module, choose M here.
-
-config ATARILANCE
- tristate "Atari Lance support"
- depends on ATARI
- help
- Say Y to include support for several Atari Ethernet adapters based
- on the AMD Lance chipset: RieblCard (with or without battery), or
- PAMCard VME (also the version by Rhotron, with different addresses).
-
-config SUN3LANCE
- tristate "Sun3/Sun3x on-board LANCE support"
- depends on SUN3 || SUN3X
- help
- Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
- featured an AMD Lance 10Mbit Ethernet controller on board; say Y
- here to compile in the Linux driver for this and enable Ethernet.
- General Linux information on the Sun 3 and 3x series (now
- discontinued) is at
- <http://www.angelfire.com/ca2/tech68k/sun3.html>.
-
- If you're not building a kernel for a Sun 3, say N.
-
-config SUN3_82586
- bool "Sun3 on-board Intel 82586 support"
- depends on SUN3
- help
- This driver enables support for the on-board Intel 82586 based
- Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note
- that this driver does not support 82586-based adapters on additional
- VME boards.
-
-config HPLANCE
- bool "HP on-board LANCE support"
- depends on DIO
- select CRC32
- help
- If you want to use the builtin "LANCE" Ethernet controller on an
- HP300 machine, say Y here.
-
-config LASI_82596
- tristate "Lasi ethernet"
- depends on GSC
- help
- Say Y here to support the builtin Intel 82596 ethernet controller
- found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
-
-config SNI_82596
- tristate "SNI RM ethernet"
- depends on NET_ETHERNET && SNI_RM
- help
- Say Y here to support the on-board Intel 82596 ethernet controller
- built into SNI RM machines.
-
-config KORINA
- tristate "Korina (IDT RC32434) Ethernet support"
- depends on NET_ETHERNET && MIKROTIK_RB532
- help
- If you have a Mikrotik RouterBoard 500 or IDT RC32434
- based system say Y. Otherwise say N.
-
-config MIPS_JAZZ_SONIC
- tristate "MIPS JAZZ onboard SONIC Ethernet support"
- depends on MACH_JAZZ
- help
- This is the driver for the onboard card of MIPS Magnum 4000,
- Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
-
-config XTENSA_XT2000_SONIC
- tristate "Xtensa XT2000 onboard SONIC Ethernet support"
- depends on XTENSA_PLATFORM_XT2000
- help
- This is the driver for the onboard card of the Xtensa XT2000 board.
-
-config MIPS_AU1X00_ENET
- tristate "MIPS AU1000 Ethernet support"
- depends on MIPS_ALCHEMY
- select PHYLIB
- select CRC32
- help
- If you have an Alchemy Semi AU1X00 based system
- say Y. Otherwise, say N.
-
-config SGI_IOC3_ETH
- bool "SGI IOC3 Ethernet"
- depends on PCI && SGI_IP27
- select CRC32
- select MII
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
-config MIPS_SIM_NET
- tristate "MIPS simulator Network device"
- depends on MIPS_SIM
- help
- The MIPSNET device is a simple Ethernet network device which is
- emulated by the MIPS Simulator.
- If you are not using a MIPSsim or are unsure, say N.
-
-config SGI_O2MACE_ETH
- tristate "SGI O2 MACE Fast Ethernet support"
- depends on SGI_IP32=y
-
-config STNIC
- tristate "National DP83902AV support"
- depends on SUPERH
- select CRC32
- help
- Support for cards based on the National Semiconductor DP83902AV
- ST-NIC Serial Network Interface Controller for Twisted Pair. This
- is a 10Mbit/sec Ethernet controller. Product overview and specs at
- <http://www.national.com/pf/DP/DP83902A.html>.
-
- If unsure, say N.
-
-config SH_ETH
- tristate "Renesas SuperH Ethernet support"
- depends on SUPERH && \
- (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
- CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
- CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7757)
- select CRC32
- select MII
- select MDIO_BITBANG
- select PHYLIB
- help
- Renesas SuperH Ethernet device driver.
- This driver supporting CPUs are:
- - SH7710, SH7712, SH7763, SH7619, SH7724, and SH7757.
-
-config SUNLANCE
- tristate "Sun LANCE support"
- depends on SBUS
- select CRC32
- help
- This driver supports the "le" interface present on all 32-bit Sparc
- systems, on some older Ultra systems and as an Sbus option. These
- cards are based on the AMD Lance chipset, which is better known
- via the NE2100 cards.
-
- To compile this driver as a module, choose M here: the module
- will be called sunlance.
-
-config HAPPYMEAL
- tristate "Sun Happy Meal 10/100baseT support"
- depends on SBUS || PCI
- select CRC32
- help
- This driver supports the "hme" interface present on most Ultra
- systems and as an option on older Sbus systems. This driver supports
- both PCI and Sbus devices. This driver also supports the "qfe" quad
- 100baseT device available in both PCI and Sbus configurations.
-
- To compile this driver as a module, choose M here: the module
- will be called sunhme.
-
-config SUNBMAC
- tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
- depends on SBUS && EXPERIMENTAL
- select CRC32
- help
- This driver supports the "be" interface available as an Sbus option.
- This is Sun's older 100baseT Ethernet device.
-
- To compile this driver as a module, choose M here: the module
- will be called sunbmac.
-
-config SUNQE
- tristate "Sun QuadEthernet support"
- depends on SBUS
- select CRC32
- help
- This driver supports the "qe" 10baseT Ethernet device, available as
- an Sbus option. Note that this is not the same as Quad FastEthernet
- "qfe" which is supported by the Happy Meal driver instead.
-
- To compile this driver as a module, choose M here: the module
- will be called sunqe.
-
-config SUNGEM
- tristate "Sun GEM support"
- depends on PCI
- select CRC32
- help
- Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also
- <http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>.
-
-config CASSINI
- tristate "Sun Cassini support"
- depends on PCI
- select CRC32
- help
- Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
- <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
-
-config SUNVNET
- tristate "Sun Virtual Network support"
- depends on SUN_LDOMS
- help
- Support for virtual network devices under Sun Logical Domains.
-
-config NET_VENDOR_3COM
- bool "3COM cards"
- depends on ISA || EISA || MCA || PCI
- help
- If you have a network (Ethernet) card belonging to this class, say Y
- and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about 3COM cards. If you say Y, you will be asked for
- your specific card in the following questions.
-
-config EL1
- tristate "3c501 \"EtherLink\" support"
- depends on NET_VENDOR_3COM && ISA
- ---help---
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>. Also, consider buying a
- new card, since the 3c501 is slow, broken, and obsolete: you will
- have problems. Some people suggest to ping ("man ping") a nearby
- machine every minute ("man cron") when using this card.
-
- To compile this driver as a module, choose M here. The module
- will be called 3c501.
-
-config EL2
- tristate "3c503 \"EtherLink II\" support"
- depends on NET_VENDOR_3COM && ISA
- select CRC32
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called 3c503.
-
-config ELPLUS
- tristate "3c505 \"EtherLink Plus\" support"
- depends on NET_VENDOR_3COM && ISA && ISA_DMA_API
- ---help---
- Information about this network (Ethernet) card can be found in
- <file:Documentation/networking/3c505.txt>. If you have a card of
- this type, say Y and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called 3c505.
-
-config EL16
- tristate "3c507 \"EtherLink 16\" support (EXPERIMENTAL)"
- depends on NET_VENDOR_3COM && ISA && EXPERIMENTAL
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called 3c507.
-
-config EL3
- tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support"
- depends on NET_VENDOR_3COM && (ISA || EISA || MCA)
- ---help---
- If you have a network (Ethernet) card belonging to the 3Com
- EtherLinkIII series, say Y and read the Ethernet-HOWTO, available
- from <http://www.tldp.org/docs.html#howto>.
-
- If your card is not working you may need to use the DOS
- setup disk to disable Plug & Play mode, and to select the default
- media type.
-
- To compile this driver as a module, choose M here. The module
- will be called 3c509.
-
-config 3C515
- tristate "3c515 ISA \"Fast EtherLink\""
- depends on NET_VENDOR_3COM && (ISA || EISA) && ISA_DMA_API
- help
- If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet
- network card, say Y and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called 3c515.
-
-config ELMC
- tristate "3c523 \"EtherLink/MC\" support"
- depends on NET_VENDOR_3COM && MCA_LEGACY
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called 3c523.
-
-config ELMC_II
- tristate "3c527 \"EtherLink/MC 32\" support (EXPERIMENTAL)"
- depends on NET_VENDOR_3COM && MCA && MCA_LEGACY
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called 3c527.
-
-config VORTEX
- tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
- depends on NET_VENDOR_3COM && (PCI || EISA)
- select MII
- ---help---
- This option enables driver support for a large number of 10Mbps and
- 10/100Mbps EISA, PCI and PCMCIA 3Com network cards:
-
- "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI
- "Boomerang" (EtherLink XL 3c900 or 3c905) PCI
- "Cyclone" (3c540/3c900/3c905/3c980/3c575/3c656) PCI and Cardbus
- "Tornado" (3c905) PCI
- "Hurricane" (3c555/3cSOHO) PCI
-
- If you have such a card, say Y and read the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>. More
- specific information is in
- <file:Documentation/networking/vortex.txt> and in the comments at
- the beginning of <file:drivers/net/3c59x.c>.
-
- To compile this support as a module, choose M here.
-
-config TYPHOON
- tristate "3cr990 series \"Typhoon\" support"
- depends on NET_VENDOR_3COM && PCI
- select CRC32
- ---help---
- This option enables driver support for the 3cr990 series of cards:
-
- 3C990-TX, 3CR990-TX-95, 3CR990-TX-97, 3CR990-FX-95, 3CR990-FX-97,
- 3CR990SVR, 3CR990SVR95, 3CR990SVR97, 3CR990-FX-95 Server,
- 3CR990-FX-97 Server, 3C990B-TX-M, 3C990BSVR
-
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called typhoon.
-
-config LANCE
- tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
- depends on ISA && ISA_DMA_API
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>. Some LinkSys cards are
- of this type.
-
- To compile this driver as a module, choose M here: the module
- will be called lance. This is recommended.
-
-config NET_VENDOR_SMC
- bool "Western Digital/SMC cards"
- depends on ISA || MCA || EISA || MAC
- help
- If you have a network (Ethernet) card belonging to this class, say Y
- and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about Western Digital cards. If you say Y, you will be
- asked for your specific card in the following questions.
-
-config WD80x3
- tristate "WD80*3 support"
- depends on NET_VENDOR_SMC && ISA
- select CRC32
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called wd.
-
-config ULTRAMCA
- tristate "SMC Ultra MCA support"
- depends on NET_VENDOR_SMC && MCA
- select CRC32
- help
- If you have a network (Ethernet) card of this type and are running
- an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called smc-mca.
-
-config ULTRA
- tristate "SMC Ultra support"
- depends on NET_VENDOR_SMC && ISA
- select CRC32
- ---help---
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- Important: There have been many reports that, with some motherboards
- mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible,
- such as some BusLogic models) causes corruption problems with many
- operating systems. The Linux smc-ultra driver has a work-around for
- this but keep it in mind if you have such a SCSI card and have
- problems.
-
- To compile this driver as a module, choose M here. The module
- will be called smc-ultra.
-
-config ULTRA32
- tristate "SMC Ultra32 EISA support"
- depends on NET_VENDOR_SMC && EISA
- select CRC32
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called smc-ultra32.
-
-config BFIN_MAC
- tristate "Blackfin on-chip MAC support"
- depends on NET_ETHERNET && (BF516 || BF518 || BF526 || BF527 || BF536 || BF537)
- select CRC32
- select MII
- select PHYLIB
- select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE
- help
- This is the driver for Blackfin on-chip mac device. Say Y if you want it
- compiled into the kernel. This driver is also available as a module
- ( = code which can be inserted in and removed from the running kernel
- whenever you want). The module will be called bfin_mac.
-
-config BFIN_MAC_USE_L1
- bool "Use L1 memory for rx/tx packets"
- depends on BFIN_MAC && (BF527 || BF537)
- default y
- help
- To get maximum network performance, you should use L1 memory as rx/tx buffers.
- Say N here if you want to reserve L1 memory for other uses.
-
-config BFIN_TX_DESC_NUM
- int "Number of transmit buffer packets"
- depends on BFIN_MAC
- range 6 10 if BFIN_MAC_USE_L1
- range 10 100
- default "10"
- help
- Set the number of buffer packets used in driver.
-
-config BFIN_RX_DESC_NUM
- int "Number of receive buffer packets"
- depends on BFIN_MAC
- range 20 100 if BFIN_MAC_USE_L1
- range 20 800
- default "20"
- help
- Set the number of buffer packets used in driver.
-
-config BFIN_MAC_USE_HWSTAMP
- bool "Use IEEE 1588 hwstamp"
- depends on BFIN_MAC && BF518
- default y
- help
- To support the IEEE 1588 Precision Time Protocol (PTP), select y here
-
-config SMC9194
- tristate "SMC 9194 support"
- depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
- select CRC32
- ---help---
- This is support for the SMC9xxx based Ethernet cards. Choose this
- option if you have a DELL laptop with the docking station, or
- another SMC9192/9194 based chipset. Say Y if you want it compiled
- into the kernel, and read the file
- <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called smc9194.
-
-config SMC91X
- tristate "SMC 91C9x/91C1xxx support"
- select CRC32
- select MII
- depends on ARM || M32R || SUPERH || \
- MIPS || BLACKFIN || MN10300 || COLDFIRE
- help
- This is a driver for SMC's 91x series of Ethernet chipsets,
- including the SMC91C94 and the SMC91C111. Say Y if you want it
- compiled into the kernel, and read the file
- <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- This driver is also available as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module will be called smc91x. If you want to compile it as a
- module, say M here and read <file:Documentation/kbuild/modules.txt>.
-
-config PXA168_ETH
- tristate "Marvell pxa168 ethernet support"
- depends on CPU_PXA168
- select PHYLIB
- help
- This driver supports the pxa168 Ethernet ports.
-
- To compile this driver as a module, choose M here. The module
- will be called pxa168_eth.
-
-config NET_NETX
- tristate "NetX Ethernet support"
- select MII
- depends on ARCH_NETX
- help
- This is support for the Hilscher netX builtin Ethernet ports
-
- To compile this driver as a module, choose M here. The module
- will be called netx-eth.
-
-config TI_DAVINCI_EMAC
- tristate "TI DaVinci EMAC Support"
- depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
- select TI_DAVINCI_MDIO
- select TI_DAVINCI_CPDMA
- select PHYLIB
- help
- This driver supports TI's DaVinci Ethernet .
-
- To compile this driver as a module, choose M here: the module
- will be called davinci_emac_driver. This is recommended.
-
-config TI_DAVINCI_MDIO
- tristate "TI DaVinci MDIO Support"
- depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
- select PHYLIB
- help
- This driver supports TI's DaVinci MDIO module.
-
- To compile this driver as a module, choose M here: the module
- will be called davinci_mdio. This is recommended.
-
-config TI_DAVINCI_CPDMA
- tristate "TI DaVinci CPDMA Support"
- depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
- help
- This driver supports TI's DaVinci CPDMA dma engine.
-
- To compile this driver as a module, choose M here: the module
- will be called davinci_cpdma. This is recommended.
-
-config DM9000
- tristate "DM9000 support"
- depends on ARM || BLACKFIN || MIPS
- select CRC32
- select MII
- ---help---
- Support for DM9000 chipset.
-
- To compile this driver as a module, choose M here. The module
- will be called dm9000.
-
-config DM9000_DEBUGLEVEL
- int "DM9000 maximum debug level"
- depends on DM9000
- default 4
- help
- The maximum level of debugging code compiled into the DM9000
- driver.
-
-config DM9000_FORCE_SIMPLE_PHY_POLL
- bool "Force simple NSR based PHY polling"
- depends on DM9000
- ---help---
- This configuration forces the DM9000 to use the NSR's LinkStatus
- bit to determine if the link is up or down instead of the more
- costly MII PHY reads. Note, this will not work if the chip is
- operating with an external PHY.
-
-config ENC28J60
- tristate "ENC28J60 support"
- depends on EXPERIMENTAL && SPI && NET_ETHERNET
- select CRC32
- ---help---
- Support for the Microchip EN28J60 ethernet chip.
-
- To compile this driver as a module, choose M here. The module will be
- called enc28j60.
-
-config ENC28J60_WRITEVERIFY
- bool "Enable write verify"
- depends on ENC28J60
- ---help---
- Enable the verify after the buffer write useful for debugging purpose.
- If unsure, say N.
-
-config ETHOC
- tristate "OpenCores 10/100 Mbps Ethernet MAC support"
- depends on NET_ETHERNET && HAS_IOMEM && HAS_DMA
- select MII
- select PHYLIB
- select CRC32
- select BITREVERSE
- help
- Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC.
-
-config GRETH
- tristate "Aeroflex Gaisler GRETH Ethernet MAC support"
- depends on SPARC
- select PHYLIB
- select CRC32
- help
- Say Y here if you want to use the Aeroflex Gaisler GRETH Ethernet MAC.
-
-config SMC911X
- tristate "SMSC LAN911[5678] support"
- select CRC32
- select MII
- depends on ARM || SUPERH || MN10300
- help
- This is a driver for SMSC's LAN911x series of Ethernet chipsets
- including the new LAN9115, LAN9116, LAN9117, and LAN9118.
- Say Y if you want it compiled into the kernel,
- and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- This driver is also available as a module. The module will be
- called smc911x. If you want to compile it as a module, say M
- here and read <file:Documentation/kbuild/modules.txt>
-
-config SMSC911X
- tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
- depends on ARM || SUPERH || BLACKFIN || MIPS || MN10300
- select CRC32
- select MII
- select PHYLIB
- ---help---
- Say Y here if you want support for SMSC LAN911x and LAN921x families
- of ethernet controllers.
-
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
- will be called smsc911x.
-
-config SMSC911X_ARCH_HOOKS
- def_bool n
- depends on SMSC911X
- help
- If the arch enables this, it allows the arch to implement various
- hooks for more comprehensive interrupt control and also to override
- the source of the MAC address.
-
-config NET_VENDOR_RACAL
- bool "Racal-Interlan (Micom) NI cards"
- depends on ISA
- help
- If you have a network (Ethernet) card belonging to this class, such
- as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about NI cards. If you say Y, you will be asked for
- your specific card in the following questions.
-
-config NI5010
- tristate "NI5010 support (EXPERIMENTAL)"
- depends on NET_VENDOR_RACAL && ISA && EXPERIMENTAL && BROKEN_ON_SMP
- ---help---
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>. Note that this is still
- experimental code.
-
- To compile this driver as a module, choose M here. The module
- will be called ni5010.
-
-config NI52
- tristate "NI5210 support"
- depends on NET_VENDOR_RACAL && ISA
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called ni52.
-
-config NI65
- tristate "NI6510 support"
- depends on NET_VENDOR_RACAL && ISA && ISA_DMA_API
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called ni65.
-
-config DNET
- tristate "Dave ethernet support (DNET)"
- depends on NET_ETHERNET && HAS_IOMEM
- select PHYLIB
- help
- The Dave ethernet interface (DNET) is found on Qong Board FPGA.
- Say Y to include support for the DNET chip.
-
- To compile this driver as a module, choose M here: the module
- will be called dnet.
-
-source "drivers/net/tulip/Kconfig"
-
-config AT1700
- tristate "AT1700/1720 support (EXPERIMENTAL)"
- depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
- select CRC32
- ---help---
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called at1700.
-
-config DEPCA
- tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
- depends on ISA || EISA || MCA
- select CRC32
- ---help---
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto> as well as
- <file:drivers/net/depca.c>.
-
- To compile this driver as a module, choose M here. The module
- will be called depca.
-
-config HP100
- tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
- depends on ISA || EISA || PCI
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called hp100.
-
-config NET_ISA
- bool "Other ISA cards"
- depends on ISA
- ---help---
- If your network (Ethernet) card hasn't been mentioned yet and its
- bus system (that's the way the cards talks to the other components
- of your computer) is ISA (as opposed to EISA, VLB or PCI), say Y.
- Make sure you know the name of your card. Read the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- If unsure, say Y.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the remaining ISA network card questions. If you say Y, you will be
- asked for your specific card in the following questions.
-
-config E2100
- tristate "Cabletron E21xx support"
- depends on NET_ISA
- select CRC32
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called e2100.
-
-config EWRK3
- tristate "EtherWORKS 3 (DE203, DE204, DE205) support"
- depends on NET_ISA
- select CRC32
- ---help---
- This driver supports the DE203, DE204 and DE205 network (Ethernet)
- cards. If this is for you, say Y and read
- <file:Documentation/networking/ewrk3.txt> in the kernel source as
- well as the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called ewrk3.
-
-config EEXPRESS
- tristate "EtherExpress 16 support"
- depends on NET_ISA
- ---help---
- If you have an EtherExpress16 network (Ethernet) card, say Y and
- read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>. Note that the Intel
- EtherExpress16 card used to be regarded as a very poor choice
- because the driver was very unreliable. We now have a new driver
- that should do better.
-
- To compile this driver as a module, choose M here. The module
- will be called eexpress.
-
-config EEXPRESS_PRO
- tristate "EtherExpressPro support/EtherExpress 10 (i82595) support"
- depends on NET_ISA
- ---help---
- If you have a network (Ethernet) card of this type, say Y. This
- driver supports Intel i82595{FX,TX} based boards. Note however
- that the EtherExpress PRO/100 Ethernet card has its own separate
- driver. Please read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called eepro.
-
-config HPLAN_PLUS
- tristate "HP PCLAN+ (27247B and 27252A) support"
- depends on NET_ISA
- select CRC32
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called hp-plus.
-
-config HPLAN
- tristate "HP PCLAN (27245 and other 27xxx series) support"
- depends on NET_ISA
- select CRC32
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called hp.
-
-config LP486E
- tristate "LP486E on board Ethernet"
- depends on NET_ISA
- help
- Say Y here to support the 82596-based on-board Ethernet controller
- for the Panther motherboard, which is one of the two shipped in the
- Intel Professional Workstation.
-
-config ETH16I
- tristate "ICL EtherTeam 16i/32 support"
- depends on NET_ISA
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called eth16i.
-
-config NE2000
- tristate "NE2000/NE1000 support"
- depends on NET_ISA || (Q40 && m) || M32R || MACH_TX49XX
- select CRC32
- ---help---
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>. Many Ethernet cards
- without a specific driver are compatible with NE2000.
-
- If you have a PCI NE2000 card however, say N here and Y to "PCI
- NE2000 and clone support" under "EISA, VLB, PCI and on board
- controllers" below. If you have a NE2000 card and are running on
- an MCA system (a bus system used on some IBM PS/2 computers and
- laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
- below.
-
- To compile this driver as a module, choose M here. The module
- will be called ne.
-
-config ZNET
- tristate "Zenith Z-Note support (EXPERIMENTAL)"
- depends on NET_ISA && EXPERIMENTAL && ISA_DMA_API
- help
- The Zenith Z-Note notebook computer has a built-in network
- (Ethernet) card, and this is the Linux driver for it. Note that the
- IBM Thinkpad 300 is compatible with the Z-Note and is also supported
- by this driver. Read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
-config SEEQ8005
- tristate "SEEQ8005 support (EXPERIMENTAL)"
- depends on NET_ISA && EXPERIMENTAL
- help
- This is a driver for the SEEQ 8005 network (Ethernet) card. If this
- is for you, read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called seeq8005.
-
-config NE2_MCA
- tristate "NE/2 (ne2000 MCA version) support"
- depends on MCA_LEGACY
- select CRC32
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called ne2.
-
-config IBMLANA
- tristate "IBM LAN Adapter/A support"
- depends on MCA
- ---help---
- This is a Micro Channel Ethernet adapter. You need to set
- CONFIG_MCA to use this driver. It is both available as an in-kernel
- driver and as a module.
-
- To compile this driver as a module, choose M here. The only
- currently supported card is the IBM LAN Adapter/A for Ethernet. It
- will both support 16K and 32K memory windows, however a 32K window
- gives a better security against packet losses. Usage of multiple
- boards with this driver should be possible, but has not been tested
- up to now due to lack of hardware.
-
-config IBMVETH
- tristate "IBM LAN Virtual Ethernet support"
- depends on PPC_PSERIES
- ---help---
- This driver supports virtual ethernet adapters on newer IBM iSeries
- and pSeries systems.
-
- To compile this driver as a module, choose M here. The module will
- be called ibmveth.
-
-source "drivers/net/ibm_newemac/Kconfig"
-
-config NET_PCI
- bool "EISA, VLB, PCI and on board controllers"
- depends on ISA || EISA || PCI
- help
- This is another class of network cards which attach directly to the
- bus. If you have one of those, say Y and read the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about this class of network cards. If you say Y, you
- will be asked for your specific card in the following questions. If
- you are unsure, say Y.
-
-config PCNET32
- tristate "AMD PCnet32 PCI support"
- depends on NET_PCI && PCI
- select CRC32
- select MII
- help
- If you have a PCnet32 or PCnetPCI based network (Ethernet) card,
- answer Y here and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called pcnet32.
-
-config AMD8111_ETH
- tristate "AMD 8111 (new PCI lance) support"
- depends on NET_PCI && PCI
- select CRC32
- select MII
- help
- If you have an AMD 8111-based PCI lance ethernet card,
- answer Y here and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called amd8111e.
-
-config ADAPTEC_STARFIRE
- tristate "Adaptec Starfire/DuraLAN support"
- depends on NET_PCI && PCI
- select CRC32
- select MII
- help
- Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network
- adapter. The DuraLAN chip is used on the 64 bit PCI boards from
- Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip
- driver.
-
- To compile this driver as a module, choose M here: the module
- will be called starfire. This is recommended.
-
-config AC3200
- tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
- depends on NET_PCI && (ISA || EISA) && EXPERIMENTAL
- select CRC32
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called ac3200.
-
-config KSZ884X_PCI
- tristate "Micrel KSZ8841/2 PCI"
- depends on NET_PCI && PCI
- select MII
- select CRC32
- help
- This PCI driver is for Micrel KSZ8841/KSZ8842 PCI Ethernet chip.
-
- To compile this driver as a module, choose M here. The module
- will be called ksz884x.
-
-config APRICOT
- tristate "Apricot Xen-II on board Ethernet"
- depends on NET_PCI && ISA
- help
- If you have a network (Ethernet) controller of this type, say Y and
- read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called apricot.
-
-config B44
- tristate "Broadcom 440x/47xx ethernet support"
- depends on SSB_POSSIBLE && HAS_DMA
- select SSB
- select MII
- help
- If you have a network (Ethernet) controller of this type, say Y
- or M and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called b44.
-
-# Auto-select SSB PCI-HOST support, if possible
-config B44_PCI_AUTOSELECT
- bool
- depends on B44 && SSB_PCIHOST_POSSIBLE
- select SSB_PCIHOST
- default y
-
-# Auto-select SSB PCICORE driver, if possible
-config B44_PCICORE_AUTOSELECT
- bool
- depends on B44 && SSB_DRIVER_PCICORE_POSSIBLE
- select SSB_DRIVER_PCICORE
- default y
-
-config B44_PCI
- bool
- depends on B44_PCI_AUTOSELECT && B44_PCICORE_AUTOSELECT
- default y
-
-config FORCEDETH
- tristate "nForce Ethernet support"
- depends on NET_PCI && PCI
- help
- If you have a network (Ethernet) controller of this type, say Y and
- read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called forcedeth.
-
-config CS89x0
- tristate "CS89x0 support"
- depends on NET_ETHERNET && (ISA || EISA || MACH_IXDP2351 \
- || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440)
- ---help---
- Support for CS89x0 chipset based Ethernet cards. If you have a
- network (Ethernet) card of this type, say Y and read the
- Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto> as well as
- <file:Documentation/networking/cs89x0.txt>.
-
- To compile this driver as a module, choose M here. The module
- will be called cs89x0.
-
-config CS89x0_NONISA_IRQ
- def_bool y
- depends on CS89x0 != n
- depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440
-
-config TC35815
- tristate "TOSHIBA TC35815 Ethernet support"
- depends on NET_PCI && PCI && MIPS
- select PHYLIB
-
-config E100
- tristate "Intel(R) PRO/100+ support"
- depends on NET_PCI && PCI
- select MII
- ---help---
- This driver supports Intel(R) PRO/100 family of adapters.
- To verify that your adapter is supported, find the board ID number
- on the adapter. Look for a label that has a barcode and a number
- in the format 123456-001 (six digits hyphen three digits).
-
- Use the above information and the Adapter & Driver ID Guide at:
-
- <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
- to identify the adapter.
-
- For the latest Intel PRO/100 network driver for Linux, see:
-
- <http://www.intel.com/p/en_US/support/highlights/network/pro100plus>
-
- More specific information on configuring the driver is in
- <file:Documentation/networking/e100.txt>.
-
- To compile this driver as a module, choose M here. The module
- will be called e100.
-
-config LNE390
- tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
- depends on NET_PCI && EISA && EXPERIMENTAL
- select CRC32
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called lne390.
-
-config FEALNX
- tristate "Myson MTD-8xx PCI Ethernet support"
- depends on NET_PCI && PCI
- select CRC32
- select MII
- help
- Say Y here to support the Myson MTD-800 family of PCI-based Ethernet
- cards. <http://www.myson.com.tw/>
-
-config NATSEMI
- tristate "National Semiconductor DP8381x series PCI Ethernet support"
- depends on NET_PCI && PCI
- select CRC32
- help
- This driver is for the National Semiconductor DP83810 series,
- which is used in cards from PureData, NetGear, Linksys
- and others, including the 83815 chip.
- More specific information and updates are available from
- <http://www.scyld.com/network/natsemi.html>.
-
-config NE2K_PCI
- tristate "PCI NE2000 and clones support (see help)"
- depends on NET_PCI && PCI
- select CRC32
- ---help---
- This driver is for NE2000 compatible PCI cards. It will not work
- with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
- support" below). If you have a PCI NE2000 network (Ethernet) card,
- say Y and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- This driver also works for the following NE2000 clone cards:
- RealTek RTL-8029 Winbond 89C940 Compex RL2000 KTI ET32P2
- NetVin NV5000SC Via 86C926 SureCom NE34 Winbond
- Holtek HT80232 Holtek HT80229
-
- To compile this driver as a module, choose M here. The module
- will be called ne2k-pci.
-
-config NE3210
- tristate "Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)"
- depends on NET_PCI && EISA && EXPERIMENTAL
- select CRC32
- ---help---
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>. Note that this driver
- will NOT WORK for NE3200 cards as they are completely different.
-
- To compile this driver as a module, choose M here. The module
- will be called ne3210.
-
-config ES3210
- tristate "Racal-Interlan EISA ES3210 support (EXPERIMENTAL)"
- depends on NET_PCI && EISA && EXPERIMENTAL
- select CRC32
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called es3210.
-
-config 8139CP
- tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)"
- depends on NET_PCI && PCI && EXPERIMENTAL
- select CRC32
- select MII
- help
- This is a driver for the Fast Ethernet PCI network cards based on
- the RTL8139C+ chips. If you have one of those, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here: the module
- will be called 8139cp. This is recommended.
-
-config 8139TOO
- tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support"
- depends on NET_PCI && PCI
- select CRC32
- select MII
- ---help---
- This is a driver for the Fast Ethernet PCI network cards based on
- the RTL 8129/8130/8139 chips. If you have one of those, say Y and
- read the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here: the module
- will be called 8139too. This is recommended.
-
-config 8139TOO_PIO
- bool "Use PIO instead of MMIO"
- default y
- depends on 8139TOO
- help
- This instructs the driver to use programmed I/O ports (PIO) instead
- of PCI shared memory (MMIO). This can possibly solve some problems
- in case your mainboard has memory consistency issues. If unsure,
- say N.
-
-config 8139TOO_TUNE_TWISTER
- bool "Support for uncommon RTL-8139 rev. K (automatic channel equalization)"
- depends on 8139TOO
- help
- This implements a function which might come in handy in case you
- are using low quality on long cabling. It is required for RealTek
- RTL-8139 revision K boards, and totally unused otherwise. It tries
- to match the transceiver to the cable characteristics. This is
- experimental since hardly documented by the manufacturer.
- If unsure, say Y.
-
-config 8139TOO_8129
- bool "Support for older RTL-8129/8130 boards"
- depends on 8139TOO
- help
- This enables support for the older and uncommon RTL-8129 and
- RTL-8130 chips, which support MII via an external transceiver,
- instead of an internal one. Disabling this option will save some
- memory by making the code size smaller. If unsure, say Y.
-
-config 8139_OLD_RX_RESET
- bool "Use older RX-reset method"
- depends on 8139TOO
- help
- The 8139too driver was recently updated to contain a more rapid
- reset sequence, in the face of severe receive errors. This "new"
- RX-reset method should be adequate for all boards. But if you
- experience problems, you can enable this option to restore the
- old RX-reset behavior. If unsure, say N.
-
-config R6040
- tristate "RDC R6040 Fast Ethernet Adapter support"
- depends on NET_PCI && PCI
- select CRC32
- select MII
- select PHYLIB
- help
- This is a driver for the R6040 Fast Ethernet MACs found in the
- the RDC R-321x System-on-chips.
-
- To compile this driver as a module, choose M here: the module
- will be called r6040. This is recommended.
-
-config SIS900
- tristate "SiS 900/7016 PCI Fast Ethernet Adapter support"
- depends on NET_PCI && PCI
- select CRC32
- select MII
- ---help---
- This is a driver for the Fast Ethernet PCI network cards based on
- the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in
- SiS 630 and SiS 540 chipsets.
-
- This driver also supports AMD 79C901 HomePNA so that you can use
- your phone line as a network cable.
-
- To compile this driver as a module, choose M here: the module
- will be called sis900. This is recommended.
-
-config EPIC100
- tristate "SMC EtherPower II"
- depends on NET_PCI && PCI
- select CRC32
- select MII
- help
- This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC,
- which is based on the SMC83c17x (EPIC/100).
- More specific information and updates are available from
- <http://www.scyld.com/network/epic100.html>.
-
-config SMSC9420
- tristate "SMSC LAN9420 PCI ethernet adapter support"
- depends on NET_PCI && PCI
- select CRC32
- select PHYLIB
- select SMSC_PHY
- help
- This is a driver for SMSC's LAN9420 PCI ethernet adapter.
- Say Y if you want it compiled into the kernel,
- and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- This driver is also available as a module. The module will be
- called smsc9420. If you want to compile it as a module, say M
- here and read <file:Documentation/kbuild/modules.txt>
-
-config SUNDANCE
- tristate "Sundance Alta support"
- depends on NET_PCI && PCI
- select CRC32
- select MII
- help
- This driver is for the Sundance "Alta" chip.
- More specific information and updates are available from
- <http://www.scyld.com/network/sundance.html>.
-
-config SUNDANCE_MMIO
- bool "Use MMIO instead of PIO"
- depends on SUNDANCE
- help
- Enable memory-mapped I/O for interaction with Sundance NIC registers.
- Do NOT enable this by default, PIO (enabled when MMIO is disabled)
- is known to solve bugs on certain chips.
-
- If unsure, say N.
-
-config TLAN
- tristate "TI ThunderLAN support"
- depends on NET_PCI && (PCI || EISA)
- ---help---
- If you have a PCI Ethernet network card based on the ThunderLAN chip
- which is supported by this driver, say Y and read the
- Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- Devices currently supported by this driver are Compaq Netelligent,
- Compaq NetFlex and Olicom cards. Please read the file
- <file:Documentation/networking/tlan.txt> for more details.
-
- To compile this driver as a module, choose M here. The module
- will be called tlan.
-
- Please email feedback to <torben.mathiasen@compaq.com>.
-
-config KS8842
- tristate "Micrel KSZ8841/42 with generic bus interface"
- depends on HAS_IOMEM && DMA_ENGINE
- help
- This platform driver is for KSZ8841(1-port) / KS8842(2-port)
- ethernet switch chip (managed, VLAN, QoS) from Micrel or
- Timberdale(FPGA).
-
-config KS8851
- tristate "Micrel KS8851 SPI"
- depends on SPI
- select MII
- select CRC32
- help
- SPI driver for Micrel KS8851 SPI attached network chip.
-
-config KS8851_MLL
- tristate "Micrel KS8851 MLL"
- depends on HAS_IOMEM
- select MII
- help
- This platform driver is for Micrel KS8851 Address/data bus
- multiplexed network chip.
-
-config VIA_RHINE
- tristate "VIA Rhine support"
- depends on NET_PCI && PCI
- select CRC32
- select MII
- help
- If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A),
- Rhine-II (VT6102), or Rhine-III (VT6105)), say Y here. Rhine-type
- Ethernet functions can also be found integrated on South Bridges
- (e.g. VT8235).
-
- To compile this driver as a module, choose M here. The module
- will be called via-rhine.
-
-config VIA_RHINE_MMIO
- bool "Use MMIO instead of PIO"
- depends on VIA_RHINE
- help
- This instructs the driver to use PCI shared memory (MMIO) instead of
- programmed I/O ports (PIO). Enabling this gives an improvement in
- processing time in parts of the driver.
-
- If unsure, say Y.
-
-config SC92031
- tristate "Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)"
- depends on NET_PCI && PCI && EXPERIMENTAL
- select CRC32
- ---help---
- This is a driver for the Fast Ethernet PCI network cards based on
- the Silan SC92031 chip (sometimes also called Rsltek 8139D). If you
- have one of these, say Y here.
-
- To compile this driver as a module, choose M here: the module
- will be called sc92031. This is recommended.
-
-config CPMAC
- tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
- depends on NET_ETHERNET && EXPERIMENTAL && AR7
- select PHYLIB
- help
- TI AR7 CPMAC Ethernet support
-
-config NET_POCKET
- bool "Pocket and portable adapters"
- depends on PARPORT
- ---help---
- Cute little network (Ethernet) devices which attach to the parallel
- port ("pocket adapters"), commonly used with laptops. If you have
- one of those, say Y and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- If you want to plug a network (or some other) card into the PCMCIA
- (or PC-card) slot of your laptop instead (PCMCIA is the standard for
- credit card size extension cards used by all modern laptops), you
- need the pcmcia-cs package (location contained in the file
- <file:Documentation/Changes>) and you can say N here.
-
- Laptop users should read the Linux Laptop home page at
- <http://www.linux-on-laptops.com/> or
- Tuxmobil - Linux on Mobile Computers at <http://www.tuxmobil.org/>.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about this class of network devices. If you say Y, you
- will be asked for your specific device in the following questions.
-
-config ATP
- tristate "AT-LAN-TEC/RealTek pocket adapter support"
- depends on NET_POCKET && PARPORT && X86
- select CRC32
- ---help---
- This is a network (Ethernet) device which attaches to your parallel
- port. Read <file:drivers/net/atp.c> as well as the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>, if you
- want to use this. If you intend to use this driver, you should have
- said N to the "Parallel printer support", because the two drivers
- don't like each other.
-
- To compile this driver as a module, choose M here: the module
- will be called atp.
-
-config DE600
- tristate "D-Link DE600 pocket adapter support"
- depends on NET_POCKET && PARPORT
- ---help---
- This is a network (Ethernet) device which attaches to your parallel
- port. Read <file:Documentation/networking/DLINK.txt> as well as the
- Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, if you want to use
- this. It is possible to have several devices share a single parallel
- port and it is safe to compile the corresponding drivers into the
- kernel.
-
- To compile this driver as a module, choose M here: the module
- will be called de600.
-
-config DE620
- tristate "D-Link DE620 pocket adapter support"
- depends on NET_POCKET && PARPORT
- ---help---
- This is a network (Ethernet) device which attaches to your parallel
- port. Read <file:Documentation/networking/DLINK.txt> as well as the
- Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, if you want to use
- this. It is possible to have several devices share a single parallel
- port and it is safe to compile the corresponding drivers into the
- kernel.
-
- To compile this driver as a module, choose M here: the module
- will be called de620.
-
-config SGISEEQ
- tristate "SGI Seeq ethernet controller support"
- depends on SGI_HAS_SEEQ
- help
- Say Y here if you have an Seeq based Ethernet network card. This is
- used in many Silicon Graphics machines.
-
-config DECLANCE
- tristate "DEC LANCE ethernet controller support"
- depends on MACH_DECSTATION
- select CRC32
- help
- This driver is for the series of Ethernet controllers produced by
- DEC (now Compaq) based on the AMD Lance chipset, including the
- DEPCA series. (This chipset is better known via the NE2100 cards.)
-
-config FEC
- bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
- depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
- IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC
- default IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC if ARM
- select PHYLIB
- help
- Say Y here if you want to use the built-in 10/100 Fast ethernet
- controller on some Motorola ColdFire and Freescale i.MX processors.
-
-config FEC_MPC52xx
- tristate "MPC52xx FEC driver"
- depends on PPC_MPC52xx && PPC_BESTCOMM
- select CRC32
- select PHYLIB
- select PPC_BESTCOMM_FEC
- ---help---
- This option enables support for the MPC5200's on-chip
- Fast Ethernet Controller
- If compiled as module, it will be called fec_mpc52xx.
-
-config FEC_MPC52xx_MDIO
- bool "MPC52xx FEC MDIO bus driver"
- depends on FEC_MPC52xx
- default y
- ---help---
- The MPC5200's FEC can connect to the Ethernet either with
- an external MII PHY chip or 10 Mbps 7-wire interface
- (Motorola? industry standard).
- If your board uses an external PHY connected to FEC, enable this.
- If not sure, enable.
- If compiled as module, it will be called fec_mpc52xx_phy.
-
-config NE_H8300
- tristate "NE2000 compatible support for H8/300"
- depends on H8300
- help
- Say Y here if you want to use the NE2000 compatible
- controller on the Renesas H8/300 processor.
-
-config ATL2
- tristate "Atheros L2 Fast Ethernet support"
- depends on PCI
- select CRC32
- select MII
- help
- This driver supports the Atheros L2 fast ethernet adapter.
-
- To compile this driver as a module, choose M here. The module
- will be called atl2.
-
-config XILINX_EMACLITE
- tristate "Xilinx 10/100 Ethernet Lite support"
- depends on PPC32 || MICROBLAZE
- select PHYLIB
- help
- This driver supports the 10/100 Ethernet Lite from Xilinx.
-
-config BCM63XX_ENET
- tristate "Broadcom 63xx internal mac support"
- depends on BCM63XX
- select MII
- select PHYLIB
- help
- This driver supports the ethernet MACs in the Broadcom 63xx
- MIPS chipset family (BCM63XX).
-
-config FTMAC100
- tristate "Faraday FTMAC100 10/100 Ethernet support"
- depends on ARM
- select MII
- help
- This driver supports the FTMAC100 10/100 Ethernet controller
- from Faraday. It is used on Faraday A320, Andes AG101 and some
- other ARM/NDS32 SoC's.
-
-config LANTIQ_ETOP
- tristate "Lantiq SoC ETOP driver"
- depends on SOC_TYPE_XWAY
- help
- Support for the MII0 inside the Lantiq SoC
-
-
-source "drivers/net/fs_enet/Kconfig"
-
-source "drivers/net/octeon/Kconfig"
-
-endif # NET_ETHERNET
-
-#
-# Gigabit Ethernet
-#
-
-menuconfig NETDEV_1000
- bool "Ethernet (1000 Mbit)"
- depends on !UML
- default y
- ---help---
- Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
- type of Local Area Network (LAN) in universities and companies.
-
- Say Y here to get to see options for Gigabit Ethernet drivers.
- This option alone does not add any kernel code.
- Note that drivers supporting both 100 and 1000 MBit may be listed
- under "Ethernet (10 or 100MBit)" instead.
-
- If you say N, all options in this submenu will be skipped and disabled.
-
-if NETDEV_1000
-
-config ACENIC
- tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
- depends on PCI
- ---help---
- Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear
- GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet
- adapter. The driver allows for using the Jumbo Frame option (9000
- bytes/frame) however it requires that your switches can handle this
- as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig
- line.
-
- To compile this driver as a module, choose M here: the
- module will be called acenic.
-
-config ACENIC_OMIT_TIGON_I
- bool "Omit support for old Tigon I based AceNICs"
- depends on ACENIC
- help
- Say Y here if you only have Tigon II based AceNICs and want to leave
- out support for the older Tigon I based cards which are no longer
- being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B
- version)). This will reduce the size of the driver object by
- app. 100KB. If you are not sure whether your card is a Tigon I or a
- Tigon II, say N here.
-
- The safe and default value for this is N.
-
-config DL2K
- tristate "DL2000/TC902x-based Gigabit Ethernet support"
- depends on PCI
- select CRC32
- help
- This driver supports DL2000/TC902x-based Gigabit ethernet cards,
- which includes
- D-Link DGE-550T Gigabit Ethernet Adapter.
- D-Link DL2000-based Gigabit Ethernet Adapter.
- Sundance/Tamarack TC902x Gigabit Ethernet Adapter.
-
- To compile this driver as a module, choose M here: the
- module will be called dl2k.
-
-config E1000
- tristate "Intel(R) PRO/1000 Gigabit Ethernet support"
- depends on PCI
- ---help---
- This driver supports Intel(R) PRO/1000 gigabit ethernet family of
- adapters. For more information on how to identify your adapter, go
- to the Adapter & Driver ID Guide at:
-
- <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
- For general information and support, go to the Intel support
- website at:
-
- <http://support.intel.com>
-
- More specific information on configuring the driver is in
- <file:Documentation/networking/e1000.txt>.
-
- To compile this driver as a module, choose M here. The module
- will be called e1000.
-
-config E1000E
- tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
- depends on PCI && (!SPARC32 || BROKEN)
- select CRC32
- ---help---
- This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
- ethernet family of adapters. For PCI or PCI-X e1000 adapters,
- use the regular e1000 driver For more information on how to
- identify your adapter, go to the Adapter & Driver ID Guide at:
-
- <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
- For general information and support, go to the Intel support
- website at:
-
- <http://support.intel.com>
-
- To compile this driver as a module, choose M here. The module
- will be called e1000e.
-
-config IP1000
- tristate "IP1000 Gigabit Ethernet support"
- depends on PCI && EXPERIMENTAL
- select MII
- ---help---
- This driver supports IP1000 gigabit Ethernet cards.
-
- To compile this driver as a module, choose M here: the module
- will be called ipg. This is recommended.
-
-config IGB
- tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
- depends on PCI
- ---help---
- This driver supports Intel(R) 82575/82576 gigabit ethernet family of
- adapters. For more information on how to identify your adapter, go
- to the Adapter & Driver ID Guide at:
-
- <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
- For general information and support, go to the Intel support
- website at:
-
- <http://support.intel.com>
-
- More specific information on configuring the driver is in
- <file:Documentation/networking/e1000.txt>.
-
- To compile this driver as a module, choose M here. The module
- will be called igb.
-
-config IGB_DCA
- bool "Direct Cache Access (DCA) Support"
- default y
- depends on IGB && DCA && !(IGB=y && DCA=m)
- ---help---
- Say Y here if you want to use Direct Cache Access (DCA) in the
- 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 IGBVF
- tristate "Intel(R) 82576 Virtual Function Ethernet support"
- depends on PCI
- ---help---
- This driver supports Intel(R) 82576 virtual functions. For more
- information on how to identify your adapter, go to the Adapter &
- Driver ID Guide at:
-
- <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
- For general information and support, go to the Intel support
- website at:
-
- <http://support.intel.com>
-
- More specific information on configuring the driver is in
- <file:Documentation/networking/e1000.txt>.
-
- To compile this driver as a module, choose M here. The module
- will be called igbvf.
-
-source "drivers/net/ixp2000/Kconfig"
-
-config NS83820
- tristate "National Semiconductor DP83820 support"
- depends on PCI
- help
- This is a driver for the National Semiconductor DP83820 series
- of gigabit ethernet MACs. Cards using this chipset include
- the D-Link DGE-500T, PureData's PDP8023Z-TG, SMC's SMC9462TX,
- SOHO-GA2000T, SOHO-GA2500T. The driver supports the use of
- zero copy.
-
-config HAMACHI
- tristate "Packet Engines Hamachi GNIC-II support"
- depends on PCI
- select MII
- help
- If you have a Gigabit Ethernet card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module will be
- called hamachi.
-
-config YELLOWFIN
- tristate "Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
- select CRC32
- ---help---
- Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet
- adapter or the SYM53C885 Ethernet controller. The Gigabit adapter is
- used by the Beowulf Linux cluster project. See
- <http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html> for more
- information about this driver in particular and Beowulf in general.
-
- To compile this driver as a module, choose M here: the module
- will be called yellowfin. This is recommended.
-
-config R8169
- tristate "Realtek 8169 gigabit ethernet support"
- depends on PCI
- select FW_LOADER
- select CRC32
- select MII
- ---help---
- Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter.
-
- To compile this driver as a module, choose M here: the module
- will be called r8169. This is recommended.
-
-config SB1250_MAC
- tristate "SB1250 Gigabit Ethernet support"
- depends on SIBYTE_SB1xxx_SOC
- select PHYLIB
- ---help---
- This driver supports Gigabit Ethernet interfaces based on the
- Broadcom SiByte family of System-On-a-Chip parts. They include
- the BCM1120, BCM1125, BCM1125H, BCM1250, BCM1255, BCM1280, BCM1455
- and BCM1480 chips.
-
- To compile this driver as a module, choose M here: the module
- will be called sb1250-mac.
-
-config SIS190
- tristate "SiS190/SiS191 gigabit ethernet support"
- depends on PCI
- select CRC32
- select MII
- ---help---
- Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or
- a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to
- appear in lan on motherboard designs which are based on SiS 965
- and SiS 966 south bridge.
-
- To compile this driver as a module, choose M here: the module
- will be called sis190. This is recommended.
-
-config SKGE
- tristate "Marvell Yukon Gigabit Ethernet support"
- depends on PCI
- select CRC32
- ---help---
- This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
- and related Gigabit Ethernet adapters. It is a new smaller driver
- with better performance and more complete ethtool support.
-
- It does not support the link failover and network management
- features that "portable" vendor supplied sk98lin driver does.
-
- This driver supports adapters based on the original Yukon chipset:
- Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
- Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872.
-
- It does not support the newer Yukon2 chipset: a separate driver,
- sky2, is provided for these adapters.
-
- To compile this driver as a module, choose M here: the module
- will be called skge. This is recommended.
-
-config SKGE_DEBUG
- bool "Debugging interface"
- depends on SKGE && DEBUG_FS
- help
- This option adds the ability to dump driver state for debugging.
- The file /sys/kernel/debug/skge/ethX displays the state of the internal
- transmit and receive rings.
-
- If unsure, say N.
-
-config SKGE_GENESIS
- bool "Support for older SysKonnect Genesis boards"
- depends on SKGE
- help
- This enables support for the older and uncommon SysKonnect Genesis
- chips, which support MII via an external transceiver, instead of
- an internal one. Disabling this option will save some memory
- by making code smaller. If unsure say Y.
-
-config SKY2
- tristate "Marvell Yukon 2 support"
- depends on PCI
- select CRC32
- ---help---
- This driver supports Gigabit Ethernet adapters based on the
- Marvell Yukon 2 chipset:
- Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/
- 88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21
-
- There is companion driver for the older Marvell Yukon and
- SysKonnect Genesis based adapters: skge.
-
- To compile this driver as a module, choose M here: the module
- will be called sky2. This is recommended.
-
-config SKY2_DEBUG
- bool "Debugging interface"
- depends on SKY2 && DEBUG_FS
- help
- This option adds the ability to dump driver state for debugging.
- The file /sys/kernel/debug/sky2/ethX displays the state of the internal
- transmit and receive rings.
-
- If unsure, say N.
-
-config VIA_VELOCITY
- tristate "VIA Velocity support"
- depends on PCI
- select CRC32
- select CRC_CCITT
- select MII
- help
- If you have a VIA "Velocity" based network card say Y here.
-
- To compile this driver as a module, choose M here. The module
- will be called via-velocity.
-
-config TIGON3
- tristate "Broadcom Tigon3 support"
- depends on PCI
- select PHYLIB
- help
- This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
-
- To compile this driver as a module, choose M here: the module
- will be called tg3. This is recommended.
-
-config BNX2
- tristate "Broadcom NetXtremeII support"
- depends on PCI
- select CRC32
- select FW_LOADER
- help
- This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
-
- To compile this driver as a module, choose M here: the module
- will be called bnx2. This is recommended.
-
-config CNIC
- tristate "Broadcom CNIC support"
- depends on PCI
- select BNX2
- select UIO
- help
- This driver supports offload features of Broadcom NetXtremeII
- gigabit Ethernet cards.
-
- To compile this driver as a module, choose M here: the module
- will be called cnic. This is recommended.
-
-config SPIDER_NET
- tristate "Spider Gigabit Ethernet driver"
- depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB)
- select FW_LOADER
- help
- This driver supports the Gigabit Ethernet chips present on the
- Cell Processor-Based Blades from IBM.
-
-config TSI108_ETH
- tristate "Tundra TSI108 gigabit Ethernet support"
- depends on TSI108_BRIDGE
- help
- This driver supports Tundra TSI108 gigabit Ethernet ports.
- To compile this driver as a module, choose M here: the module
- will be called tsi108_eth.
-
-config GELIC_NET
- tristate "PS3 Gigabit Ethernet driver"
- depends on PPC_PS3
- select PS3_SYS_MANAGER
- help
- This driver supports the network device on the PS3 game
- console. This driver has built-in support for Ethernet.
-
- To compile this driver as a module, choose M here: the
- module will be called ps3_gelic.
-
-config GELIC_WIRELESS
- bool "PS3 Wireless support"
- depends on WLAN
- depends on GELIC_NET
- select WIRELESS_EXT
- help
- This option adds the support for the wireless feature of PS3.
- If you have the wireless-less model of PS3 or have no plan to
- use wireless feature, disabling this option saves memory. As
- the driver automatically distinguishes the models, you can
- safely enable this option even if you have a wireless-less model.
-
-config FSL_PQ_MDIO
- tristate "Freescale PQ MDIO"
- depends on FSL_SOC
- select PHYLIB
- help
- This driver supports the MDIO bus used by the gianfar and UCC drivers.
-
-config GIANFAR
- tristate "Gianfar Ethernet"
- depends on FSL_SOC
- select FSL_PQ_MDIO
- select PHYLIB
- select CRC32
- help
- This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
- and MPC86xx family of chips, and the FEC on the 8540.
-
-config UCC_GETH
- tristate "Freescale QE Gigabit Ethernet"
- depends on QUICC_ENGINE
- select FSL_PQ_MDIO
- select PHYLIB
- help
- This driver supports the Gigabit Ethernet mode of the QUICC Engine,
- which is available on some Freescale SOCs.
-
-config UGETH_TX_ON_DEMAND
- bool "Transmit on Demand support"
- depends on UCC_GETH
-
-config MV643XX_ETH
- tristate "Marvell Discovery (643XX) and Orion ethernet support"
- depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
- select INET_LRO
- select PHYLIB
- help
- This driver supports the gigabit ethernet MACs in the
- Marvell Discovery PPC/MIPS chipset family (MV643XX) and
- in the Marvell Orion ARM SoC family.
-
- Some boards that use the Discovery chipset are the Momenco
- Ocelot C and Jaguar ATX and Pegasos II.
-
-config XILINX_LL_TEMAC
- tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
- depends on PPC || MICROBLAZE
- select PHYLIB
- help
- This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
- core used in Xilinx Spartan and Virtex FPGAs
-
-config QLA3XXX
- tristate "QLogic QLA3XXX Network Driver Support"
- depends on PCI
- help
- This driver supports QLogic ISP3XXX gigabit Ethernet cards.
-
- To compile this driver as a module, choose M here: the module
- will be called qla3xxx.
-
-config ATL1
- tristate "Atheros/Attansic L1 Gigabit Ethernet support"
- depends on PCI
- select CRC32
- select MII
- help
- This driver supports the Atheros/Attansic L1 gigabit ethernet
- adapter.
-
- To compile this driver as a module, choose M here. The module
- will be called atl1.
-
-config ATL1E
- tristate "Atheros L1E Gigabit Ethernet support (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
- select CRC32
- select MII
- help
- This driver supports the Atheros L1E gigabit ethernet adapter.
-
- To compile this driver as a module, choose M here. The module
- will be called atl1e.
-
-config ATL1C
- tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
- select CRC32
- select MII
- help
- This driver supports the Atheros L1C gigabit ethernet adapter.
-
- To compile this driver as a module, choose M here. The module
- will be called atl1c.
-
-config JME
- tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
- depends on PCI
- select CRC32
- select MII
- ---help---
- This driver supports the PCI-Express gigabit ethernet adapters
- based on JMicron JMC250 chipset.
-
- To compile this driver as a module, choose M here. The module
- will be called jme.
-
-config S6GMAC
- tristate "S6105 GMAC ethernet support"
- depends on XTENSA_VARIANT_S6000
- select PHYLIB
- help
- This driver supports the on chip ethernet device on the
- S6105 xtensa processor.
-
- To compile this driver as a module, choose M here. The module
- will be called s6gmac.
-
-source "drivers/net/stmmac/Kconfig"
-
-config PCH_GBE
- tristate "Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE"
- depends on PCI
- select MII
- ---help---
- This is a gigabit ethernet driver for EG20T PCH.
- EG20T PCH is the platform controller hub that is used in Intel's
- general embedded platform.
- EG20T PCH has Gigabit Ethernet interface.
- Using this interface, it is able to access system devices connected
- to Gigabit Ethernet.
- This driver enables Gigabit Ethernet function.
-
- This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
- Output Hub), ML7223/ML7831.
- ML7223 IOH is for MP(Media Phone) use. ML7831 IOH is for general
- purpose use.
- ML7223/ML7831 is companion chip for Intel Atom E6xx series.
- ML7223/ML7831 is completely compatible for Intel EG20T PCH.
-
-config FTGMAC100
- tristate "Faraday FTGMAC100 Gigabit Ethernet support"
- depends on ARM
- select PHYLIB
- help
- This driver supports the FTGMAC100 Gigabit Ethernet controller
- from Faraday. It is used on Faraday A369, Andes AG102 and some
- other ARM/NDS32 SoC's.
-
-endif # NETDEV_1000
-
-#
-# 10 Gigabit Ethernet
-#
-
-menuconfig NETDEV_10000
- bool "Ethernet (10000 Mbit)"
- depends on !UML
- default y
- ---help---
- Say Y here to get to see options for 10 Gigabit Ethernet drivers.
- This option alone does not add any kernel code.
-
- If you say N, all options in this submenu will be skipped and disabled.
-
-if NETDEV_10000
-
-config MDIO
- tristate
-
-config CHELSIO_T1
- tristate "Chelsio 10Gb Ethernet support"
- depends on PCI
- select CRC32
- select MDIO
- help
- This driver supports Chelsio gigabit and 10-gigabit
- Ethernet cards. More information about adapter features and
- performance tuning is in <file:Documentation/networking/cxgb.txt>.
-
- For general information about Chelsio and our products, visit
- our website at <http://www.chelsio.com>.
-
- For customer support, please visit our customer support page at
- <http://www.chelsio.com/support.html>.
-
- Please send feedback to <linux-bugs@chelsio.com>.
-
- To compile this driver as a module, choose M here: the module
- will be called cxgb.
-
-config CHELSIO_T1_1G
- bool "Chelsio gigabit Ethernet support"
- depends on CHELSIO_T1
- help
- Enables support for Chelsio's gigabit Ethernet PCI cards. If you
- are using only 10G cards say 'N' here.
-
-config CHELSIO_T3
- tristate "Chelsio Communications T3 10Gb Ethernet support"
- depends on PCI && INET
- select FW_LOADER
- select MDIO
- help
- This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
- adapters.
-
- For general information about Chelsio and our products, visit
- our website at <http://www.chelsio.com>.
-
- For customer support, please visit our customer support page at
- <http://www.chelsio.com/support.html>.
-
- Please send feedback to <linux-bugs@chelsio.com>.
-
- To compile this driver as a module, choose M here: the module
- will be called cxgb3.
-
-config CHELSIO_T4
- tristate "Chelsio Communications T4 Ethernet support"
- depends on PCI
- select FW_LOADER
- select MDIO
- help
- This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
- adapters.
-
- For general information about Chelsio and our products, visit
- our website at <http://www.chelsio.com>.
-
- For customer support, please visit our customer support page at
- <http://www.chelsio.com/support.html>.
-
- Please send feedback to <linux-bugs@chelsio.com>.
-
- To compile this driver as a module choose M here; the module
- will be called cxgb4.
-
-config CHELSIO_T4VF
- tristate "Chelsio Communications T4 Virtual Function Ethernet support"
- depends on PCI
- help
- This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
- adapters with PCI-E SR-IOV Virtual Functions.
-
- For general information about Chelsio and our products, visit
- our website at <http://www.chelsio.com>.
-
- For customer support, please visit our customer support page at
- <http://www.chelsio.com/support.html>.
-
- Please send feedback to <linux-bugs@chelsio.com>.
-
- To compile this driver as a module choose M here; the module
- will be called cxgb4vf.
-
-config EHEA
- tristate "eHEA Ethernet support"
- depends on IBMEBUS && INET && SPARSEMEM
- select INET_LRO
- ---help---
- This driver supports the IBM pSeries eHEA ethernet adapter.
-
- To compile the driver as a module, choose M here. The module
- will be called ehea.
-
-config ENIC
- tristate "Cisco VIC Ethernet NIC Support"
- depends on PCI && INET
- help
- This enables the support for the Cisco VIC Ethernet card.
-
-config IXGBE
- tristate "Intel(R) 10GbE PCI Express adapters support"
- depends on PCI && INET
- select MDIO
- ---help---
- This driver supports Intel(R) 10GbE PCI Express family of
- adapters. For more information on how to identify your adapter, go
- to the Adapter & Driver ID Guide at:
-
- <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
- For general information and support, go to the Intel support
- website at:
-
- <http://support.intel.com>
-
- To compile this driver as a module, choose M here. The module
- will be called ixgbe.
-
-config IXGBE_DCA
- bool "Direct Cache Access (DCA) Support"
- default y
- depends on IXGBE && DCA && !(IXGBE=y && DCA=m)
- ---help---
- Say Y here if you want to use Direct Cache Access (DCA) in the
- 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 IXGBE_DCB
- bool "Data Center Bridging (DCB) Support"
- default n
- depends on IXGBE && DCB
- ---help---
- Say Y here if you want to use Data Center Bridging (DCB) in the
- driver.
-
- If unsure, say N.
-
-config IXGBEVF
- tristate "Intel(R) 82599 Virtual Function Ethernet support"
- depends on PCI_MSI
- ---help---
- This driver supports Intel(R) 82599 virtual functions. For more
- information on how to identify your adapter, go to the Adapter &
- Driver ID Guide at:
-
- <http://support.intel.com/support/network/sb/CS-008441.htm>
-
- For general information and support, go to the Intel support
- website at:
-
- <http://support.intel.com>
-
- More specific information on configuring the driver is in
- <file:Documentation/networking/ixgbevf.txt>.
-
- To compile this driver as a module, choose M here. The module
- will be called ixgbevf. MSI-X interrupt support is required
- for this driver to work correctly.
-
-config IXGB
- tristate "Intel(R) PRO/10GbE support"
- depends on PCI
- ---help---
- This driver supports Intel(R) PRO/10GbE family of adapters for
- PCI-X type cards. For PCI-E type cards, use the "ixgbe" driver
- instead. For more information on how to identify your adapter, go
- to the Adapter & Driver ID Guide at:
-
- <http://support.intel.com/support/network/adapter/pro100/21397.htm>
-
- For general information and support, go to the Intel support
- website at:
-
- <http://support.intel.com>
-
- More specific information on configuring the driver is in
- <file:Documentation/networking/ixgb.txt>.
-
- To compile this driver as a module, choose M here. The module
- will be called ixgb.
-
-config S2IO
- tristate "Exar Xframe 10Gb Ethernet Adapter"
- depends on PCI
- ---help---
- This driver supports Exar Corp's Xframe Series 10Gb Ethernet Adapters.
-
- More specific information on configuring the driver is in
- <file:Documentation/networking/s2io.txt>.
-
- To compile this driver as a module, choose M here. The module
- will be called s2io.
-
-config VXGE
- tristate "Exar X3100 Series 10GbE PCIe Server Adapter"
- depends on PCI && INET
- ---help---
- This driver supports Exar Corp's X3100 Series 10 GbE PCIe
- I/O Virtualized Server Adapter.
-
- More specific information on configuring the driver is in
- <file:Documentation/networking/vxge.txt>.
-
- To compile this driver as a module, choose M here. The module
- will be called vxge.
-
-config VXGE_DEBUG_TRACE_ALL
- bool "Enabling All Debug trace statments in driver"
- default n
- depends on VXGE
- ---help---
- Say Y here if you want to enabling all the debug trace statements in
- the vxge driver. By default only few debug trace statements are
- enabled.
-
-config MYRI10GE
- tristate "Myricom Myri-10G Ethernet support"
- 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,
- you will need a newer firmware image.
- You may get this image or more information, at:
-
- <http://www.myri.com/scs/download-Myri10GE.html>
-
- To compile this driver as a module, choose M here. The module
- will be called myri10ge.
-
-config MYRI10GE_DCA
- bool "Direct Cache Access (DCA) Support"
- default y
- depends on MYRI10GE && DCA && !(MYRI10GE=y && DCA=m)
- ---help---
- Say Y here if you want to use Direct Cache Access (DCA) in the
- 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 NETXEN_NIC
- tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
- depends on PCI
- select FW_LOADER
- help
- This enables the support for NetXen's Gigabit Ethernet card.
-
-config NIU
- tristate "Sun Neptune 10Gbit Ethernet support"
- depends on PCI
- select CRC32
- help
- This enables support for cards based upon Sun's
- Neptune chipset.
-
-config PASEMI_MAC
- tristate "PA Semi 1/10Gbit MAC"
- depends on PPC_PASEMI && PCI && INET
- select PHYLIB
- select INET_LRO
- help
- This driver supports the on-chip 1/10Gbit Ethernet controller on
- PA Semi's PWRficient line of chips.
-
-config MLX4_EN
- tristate "Mellanox Technologies 10Gbit Ethernet support"
- depends on PCI && INET
- select MLX4_CORE
- select INET_LRO
- help
- This driver supports Mellanox Technologies ConnectX Ethernet
- devices.
-
-config MLX4_CORE
- tristate
- depends on PCI
- default n
-
-config MLX4_DEBUG
- bool "Verbose debugging output" if (MLX4_CORE && EXPERT)
- depends on MLX4_CORE
- default y
- ---help---
- This option causes debugging code to be compiled into the
- mlx4_core driver. The output can be turned on via the
- debug_level module parameter (which can also be set after
- the driver is loaded through sysfs).
-
-config TEHUTI
- tristate "Tehuti Networks 10G Ethernet"
- depends on PCI
- help
- Tehuti Networks 10G Ethernet NIC
-
-config BNX2X
- tristate "Broadcom NetXtremeII 10Gb support"
- depends on PCI
- select FW_LOADER
- select ZLIB_INFLATE
- select LIBCRC32C
- select MDIO
- help
- This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
- To compile this driver as a module, choose M here: the module
- will be called bnx2x. This is recommended.
-
-config QLCNIC
- tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
- depends on PCI
- select FW_LOADER
- help
- This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
- devices.
-
-config QLGE
- tristate "QLogic QLGE 10Gb Ethernet Driver Support"
- depends on PCI
- help
- This driver supports QLogic ISP8XXX 10Gb Ethernet cards.
-
- To compile this driver as a module, choose M here: the module
- will be called qlge.
-
-config BNA
- tristate "Brocade 1010/1020 10Gb Ethernet Driver support"
- depends on PCI
- ---help---
- This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet
- cards.
- To compile this driver as a module, choose M here: the module
- will be called bna.
-
- For general information and support, go to the Brocade support
- website at:
-
- <http://support.brocade.com>
-
-source "drivers/net/sfc/Kconfig"
-
-source "drivers/net/benet/Kconfig"
-
-endif # NETDEV_10000
+source "drivers/s390/net/Kconfig"
source "drivers/net/tokenring/Kconfig"
+source "drivers/net/usb/Kconfig"
+
source "drivers/net/wireless/Kconfig"
source "drivers/net/wimax/Kconfig"
-source "drivers/net/usb/Kconfig"
-
-source "drivers/net/pcmcia/Kconfig"
-
source "drivers/net/wan/Kconfig"
-source "drivers/atm/Kconfig"
-
-source "drivers/ieee802154/Kconfig"
-
-source "drivers/s390/net/Kconfig"
-
-source "drivers/net/caif/Kconfig"
-
-config TILE_NET
- tristate "Tilera GBE/XGBE network driver support"
- depends on TILE
- default y
- select CRC32
- help
- This is a standard Linux network device driver for the
- on-chip Tilera Gigabit Ethernet and XAUI interfaces.
-
- To compile this driver as a module, choose M here: the module
- will be called tile_net.
-
config XEN_NETDEV_FRONTEND
tristate "Xen network device frontend driver"
depends on XEN
@@ -3002,448 +328,6 @@ config XEN_NETDEV_BACKEND
compile this driver as a module, chose M here: the module
will be called xen-netback.
-config ISERIES_VETH
- tristate "iSeries Virtual Ethernet driver support"
- depends on PPC_ISERIES
-
-config RIONET
- tristate "RapidIO Ethernet over messaging driver support"
- depends on RAPIDIO
-
-config RIONET_TX_SIZE
- int "Number of outbound queue entries"
- depends on RIONET
- default "128"
-
-config RIONET_RX_SIZE
- int "Number of inbound queue entries"
- depends on RIONET
- default "128"
-
-config FDDI
- tristate "FDDI driver support"
- depends on (PCI || EISA || TC)
- help
- Fiber Distributed Data Interface is a high speed local area network
- design; essentially a replacement for high speed Ethernet. FDDI can
- run over copper or fiber. If you are connected to such a network and
- want a driver for the FDDI card in your computer, say Y here (and
- then also Y to the driver for your FDDI card, below). Most people
- will say N.
-
-config DEFXX
- tristate "Digital DEFTA/DEFEA/DEFPA adapter support"
- depends on FDDI && (PCI || EISA || TC)
- ---help---
- This is support for the DIGITAL series of TURBOchannel (DEFTA),
- EISA (DEFEA) and PCI (DEFPA) controllers which can connect you
- to a local FDDI network.
-
- To compile this driver as a module, choose M here: the module
- will be called defxx. If unsure, say N.
-
-config DEFXX_MMIO
- bool
- prompt "Use MMIO instead of PIO" if PCI || EISA
- depends on DEFXX
- default n if PCI || EISA
- default y
- ---help---
- This instructs the driver to use EISA or PCI memory-mapped I/O
- (MMIO) as appropriate instead of programmed I/O ports (PIO).
- Enabling this gives an improvement in processing time in parts
- of the driver, but it may cause problems with EISA (DEFEA)
- adapters. TURBOchannel does not have the concept of I/O ports,
- so MMIO is always used for these (DEFTA) adapters.
-
- If unsure, say N.
-
-config SKFP
- tristate "SysKonnect FDDI PCI support"
- depends on FDDI && PCI
- select BITREVERSE
- ---help---
- Say Y here if you have a SysKonnect FDDI PCI adapter.
- The following adapters are supported by this driver:
- - SK-5521 (SK-NET FDDI-UP)
- - SK-5522 (SK-NET FDDI-UP DAS)
- - SK-5541 (SK-NET FDDI-FP)
- - SK-5543 (SK-NET FDDI-LP)
- - SK-5544 (SK-NET FDDI-LP DAS)
- - SK-5821 (SK-NET FDDI-UP64)
- - SK-5822 (SK-NET FDDI-UP64 DAS)
- - SK-5841 (SK-NET FDDI-FP64)
- - SK-5843 (SK-NET FDDI-LP64)
- - SK-5844 (SK-NET FDDI-LP64 DAS)
- - Netelligent 100 FDDI DAS Fibre SC
- - Netelligent 100 FDDI SAS Fibre SC
- - Netelligent 100 FDDI DAS UTP
- - Netelligent 100 FDDI SAS UTP
- - Netelligent 100 FDDI SAS Fibre MIC
-
- Read <file:Documentation/networking/skfp.txt> for information about
- the driver.
-
- Questions concerning this driver can be addressed to:
- <linux@syskonnect.de>
-
- To compile this driver as a module, choose M here: the module
- will be called skfp. This is recommended.
-
-config HIPPI
- bool "HIPPI driver support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && INET && PCI
- help
- HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
- 1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
- can run over copper (25m) or fiber (300m on multi-mode or 10km on
- single-mode). HIPPI networks are commonly used for clusters and to
- connect to super computers. If you are connected to a HIPPI network
- and have a HIPPI network card in your computer that you want to use
- under Linux, say Y here (you must also remember to enable the driver
- for your HIPPI card below). Most people will say N here.
-
-config ROADRUNNER
- tristate "Essential RoadRunner HIPPI PCI adapter support (EXPERIMENTAL)"
- depends on HIPPI && PCI
- help
- Say Y here if this is your PCI HIPPI network card.
-
- To compile this driver as a module, choose M here: the module
- will be called rrunner. If unsure, say N.
-
-config ROADRUNNER_LARGE_RINGS
- bool "Use large TX/RX rings (EXPERIMENTAL)"
- depends on ROADRUNNER
- help
- If you say Y here, the RoadRunner driver will preallocate up to 2 MB
- of additional memory to allow for fastest operation, both for
- transmitting and receiving. This memory cannot be used by any other
- kernel code or by user space programs. Say Y here only if you have
- the memory.
-
-config PLIP
- tristate "PLIP (parallel port) support"
- depends on PARPORT
- ---help---
- PLIP (Parallel Line Internet Protocol) is used to create a
- reasonably fast mini network consisting of two (or, rarely, more)
- local machines. A PLIP link from a Linux box is a popular means to
- install a Linux distribution on a machine which doesn't have a
- CD-ROM drive (a minimal system has to be transferred with floppies
- first). The kernels on both machines need to have this PLIP option
- enabled for this to work.
-
- The PLIP driver has two modes, mode 0 and mode 1. The parallel
- ports (the connectors at the computers with 25 holes) are connected
- with "null printer" or "Turbo Laplink" cables which can transmit 4
- bits at a time (mode 0) or with special PLIP cables, to be used on
- bidirectional parallel ports only, which can transmit 8 bits at a
- time (mode 1); you can find the wiring of these cables in
- <file:Documentation/networking/PLIP.txt>. The cables can be up to
- 15m long. Mode 0 works also if one of the machines runs DOS/Windows
- and has some PLIP software installed, e.g. the Crynwr PLIP packet
- driver (<http://oak.oakland.edu/simtel.net/msdos/pktdrvr-pre.html>)
- and winsock or NCSA's telnet.
-
- If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well
- as the NET-3-HOWTO, both available from
- <http://www.tldp.org/docs.html#howto>. Note that the PLIP
- protocol has been changed and this PLIP driver won't work together
- with the PLIP support in Linux versions 1.0.x. This option enlarges
- your kernel by about 8 KB.
-
- To compile this driver as a module, choose M here. The module
- will be called plip. If unsure, say Y or M, in case you buy
- a laptop later.
-
-config PPP
- tristate "PPP (point-to-point protocol) support"
- select SLHC
- ---help---
- PPP (Point to Point Protocol) is a newer and better SLIP. It serves
- the same purpose: sending Internet traffic over telephone (and other
- serial) lines. Ask your access provider if they support it, because
- otherwise you can't use it; most Internet access providers these
- days support PPP rather than SLIP.
-
- To use PPP, you need an additional program called pppd as described
- in the PPP-HOWTO, available at
- <http://www.tldp.org/docs.html#howto>. Make sure that you have
- the version of pppd recommended in <file:Documentation/Changes>.
- The PPP option enlarges your kernel by about 16 KB.
-
- There are actually two versions of PPP: the traditional PPP for
- asynchronous lines, such as regular analog phone lines, and
- synchronous PPP which can be used over digital ISDN lines for
- example. If you want to use PPP over phone lines or other
- asynchronous serial lines, you need to say Y (or M) here and also to
- the next option, "PPP support for async serial ports". For PPP over
- synchronous lines, you should say Y (or M) here and to "Support
- synchronous PPP", below.
-
- If you said Y to "Version information on all symbols" above, then
- you cannot compile the PPP driver into the kernel; you can then only
- compile it as a module. To compile this driver as a module, choose M
- here. The module will be called ppp_generic.
-
-config PPP_MULTILINK
- bool "PPP multilink support (EXPERIMENTAL)"
- depends on PPP && EXPERIMENTAL
- help
- PPP multilink is a protocol (defined in RFC 1990) which allows you
- to combine several (logical or physical) lines into one logical PPP
- connection, so that you can utilize your full bandwidth.
-
- This has to be supported at the other end as well and you need a
- version of the pppd daemon which understands the multilink protocol.
-
- If unsure, say N.
-
-config PPP_FILTER
- bool "PPP filtering"
- depends on PPP
- help
- Say Y here if you want to be able to filter the packets passing over
- PPP interfaces. This allows you to control which packets count as
- activity (i.e. which packets will reset the idle timer or bring up
- a demand-dialed link) and which packets are to be dropped entirely.
- You need to say Y here if you wish to use the pass-filter and
- active-filter options to pppd.
-
- If unsure, say N.
-
-config PPP_ASYNC
- tristate "PPP support for async serial ports"
- depends on PPP
- select CRC_CCITT
- ---help---
- Say Y (or M) here if you want to be able to use PPP over standard
- asynchronous serial ports, such as COM1 or COM2 on a PC. If you use
- a modem (not a synchronous or ISDN modem) to contact your ISP, you
- need this option.
-
- To compile this driver as a module, choose M here.
-
- If unsure, say Y.
-
-config PPP_SYNC_TTY
- tristate "PPP support for sync tty ports"
- depends on PPP
- help
- Say Y (or M) here if you want to be able to use PPP over synchronous
- (HDLC) tty devices, such as the SyncLink adapter. These devices
- are often used for high-speed leased lines like T1/E1.
-
- To compile this driver as a module, choose M here.
-
-config PPP_DEFLATE
- tristate "PPP Deflate compression"
- depends on PPP
- select ZLIB_INFLATE
- select ZLIB_DEFLATE
- ---help---
- Support for the Deflate compression method for PPP, which uses the
- Deflate algorithm (the same algorithm that gzip uses) to compress
- each PPP packet before it is sent over the wire. The machine at the
- other end of the PPP link (usually your ISP) has to support the
- Deflate compression method as well for this to be useful. Even if
- they don't support it, it is safe to say Y here.
-
- To compile this driver as a module, choose M here.
-
-config PPP_BSDCOMP
- tristate "PPP BSD-Compress compression"
- depends on PPP
- ---help---
- Support for the BSD-Compress compression method for PPP, which uses
- the LZW compression method to compress each PPP packet before it is
- sent over the wire. The machine at the other end of the PPP link
- (usually your ISP) has to support the BSD-Compress compression
- method as well for this to be useful. Even if they don't support it,
- it is safe to say Y here.
-
- The PPP Deflate compression method ("PPP Deflate compression",
- above) is preferable to BSD-Compress, because it compresses better
- and is patent-free.
-
- Note that the BSD compression code will always be compiled as a
- module; it is called bsd_comp and will show up in the directory
- modules once you have said "make modules". If unsure, say N.
-
-config PPP_MPPE
- tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)"
- depends on PPP && EXPERIMENTAL
- select CRYPTO
- select CRYPTO_SHA1
- select CRYPTO_ARC4
- select CRYPTO_ECB
- ---help---
- Support for the MPPE Encryption protocol, as employed by the
- Microsoft Point-to-Point Tunneling Protocol.
-
- See http://pptpclient.sourceforge.net/ for information on
- configuring PPTP clients and servers to utilize this method.
-
-config PPPOE
- tristate "PPP over Ethernet (EXPERIMENTAL)"
- depends on EXPERIMENTAL && PPP
- help
- Support for PPP over Ethernet.
-
- This driver requires the latest version of pppd from the CVS
- repository at cvs.samba.org. Alternatively, see the
- RoaringPenguin package (<http://www.roaringpenguin.com/pppoe>)
- which contains instruction on how to use this driver (under
- the heading "Kernel mode PPPoE").
-
-config PPTP
- tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
- depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
- help
- Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
-
- This driver requires pppd plugin to work in client mode or
- modified pptpd (poptop) to work in server mode.
- See http://accel-pptp.sourceforge.net/ for information how to
- utilize this module.
-
-config PPPOATM
- tristate "PPP over ATM"
- depends on ATM && PPP
- help
- Support PPP (Point to Point Protocol) encapsulated in ATM frames.
- This implementation does not yet comply with section 8 of RFC2364,
- which can lead to bad results if the ATM peer loses state and
- changes its encapsulation unilaterally.
-
-config PPPOL2TP
- tristate "PPP over L2TP (EXPERIMENTAL)"
- depends on EXPERIMENTAL && L2TP && PPP
- help
- Support for PPP-over-L2TP socket family. L2TP is a protocol
- used by ISPs and enterprises to tunnel PPP traffic over UDP
- tunnels. L2TP is replacing PPTP for VPN uses.
-
-config SLIP
- tristate "SLIP (serial line) support"
- ---help---
- Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
- connect to your Internet service provider or to connect to some
- other local Unix box or if you want to configure your Linux box as a
- Slip/CSlip server for other people to dial in. SLIP (Serial Line
- Internet Protocol) is a protocol used to send Internet traffic over
- serial connections such as telephone lines or null modem cables;
- nowadays, the protocol PPP is more commonly used for this same
- purpose.
-
- Normally, your access provider has to support SLIP in order for you
- to be able to use it, but there is now a SLIP emulator called SLiRP
- around (available from
- <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
- allows you to use SLIP over a regular dial up shell connection. If
- you plan to use SLiRP, make sure to say Y to CSLIP, below. The
- NET-3-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, explains how to
- configure SLIP. Note that you don't need this option if you just
- want to run term (term is a program which gives you almost full
- Internet connectivity if you have a regular dial up shell account on
- some Internet connected Unix computer. Read
- <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
- support will enlarge your kernel by about 4 KB. If unsure, say N.
-
- To compile this driver as a module, choose M here. The module
- will be called slip.
-
-config SLIP_COMPRESSED
- bool "CSLIP compressed headers"
- depends on SLIP
- select SLHC
- ---help---
- This protocol is faster than SLIP because it uses compression on the
- TCP/IP headers (not on the data itself), but it has to be supported
- on both ends. Ask your access provider if you are not sure and
- answer Y, just in case. You will still be able to use plain SLIP. If
- you plan to use SLiRP, the SLIP emulator (available from
- <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
- allows you to use SLIP over a regular dial up shell connection, you
- definitely want to say Y here. The NET-3-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, explains how to configure
- CSLIP. This won't enlarge your kernel.
-
-config SLHC
- tristate
- help
- This option enables Van Jacobsen serial line header compression
- routines.
-
-config SLIP_SMART
- bool "Keepalive and linefill"
- depends on SLIP
- help
- Adds additional capabilities to the SLIP driver to support the
- RELCOM line fill and keepalive monitoring. Ideal on poor quality
- analogue lines.
-
-config SLIP_MODE_SLIP6
- bool "Six bit SLIP encapsulation"
- depends on SLIP
- help
- Just occasionally you may need to run IP over hostile serial
- networks that don't pass all control characters or are only seven
- bit. Saying Y here adds an extra mode you can use with SLIP:
- "slip6". In this mode, SLIP will only send normal ASCII symbols over
- the serial device. Naturally, this has to be supported at the other
- end of the link as well. It's good enough, for example, to run IP
- over the async ports of a Camtec JNT Pad. If unsure, say N.
-
-config NET_FC
- bool "Fibre Channel driver support"
- depends on SCSI && PCI
- help
- Fibre Channel is a high speed serial protocol mainly used to connect
- large storage devices to the computer; it is compatible with and
- intended to replace SCSI.
-
- If you intend to use Fibre Channel, you need to have a Fibre channel
- adaptor card in your computer; say Y here and to the driver for your
- adaptor below. You also should have said Y to "SCSI support" and
- "SCSI generic support".
-
-config NETCONSOLE
- tristate "Network console logging support"
- ---help---
- If you want to log kernel messages over the network, enable this.
- See <file:Documentation/networking/netconsole.txt> for details.
-
-config NETCONSOLE_DYNAMIC
- bool "Dynamic reconfiguration of logging targets"
- depends on NETCONSOLE && SYSFS && CONFIGFS_FS && \
- !(NETCONSOLE=y && CONFIGFS_FS=m)
- help
- This option enables the ability to dynamically reconfigure target
- parameters (interface, IP addresses, port numbers, MAC addresses)
- at runtime through a userspace interface exported using configfs.
- See <file:Documentation/networking/netconsole.txt> for details.
-
-config NETPOLL
- def_bool NETCONSOLE
-
-config NETPOLL_TRAP
- bool "Netpoll traffic trapping"
- default n
- depends on NETPOLL
-
-config NET_POLL_CONTROLLER
- def_bool NETPOLL
-
-config VIRTIO_NET
- tristate "Virtio network driver (EXPERIMENTAL)"
- depends on EXPERIMENTAL && VIRTIO
- ---help---
- This is the virtual network driver for virtio. It can be used with
- lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
-
config VMXNET3
tristate "VMware VMXNET3 ethernet driver"
depends on PCI && INET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index e1eca2ab505e..fa877cd2b139 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -1,278 +1,61 @@
#
-# Makefile for the Linux network (ethercard) device drivers.
+# Makefile for the Linux network device drivers.
#
-obj-$(CONFIG_MII) += mii.o
-obj-$(CONFIG_MDIO) += mdio.o
-obj-$(CONFIG_PHYLIB) += phy/
-
-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_E1000) += e1000/
-obj-$(CONFIG_E1000E) += e1000e/
-obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/
-obj-$(CONFIG_IGB) += igb/
-obj-$(CONFIG_IGBVF) += igbvf/
-obj-$(CONFIG_IXGBE) += ixgbe/
-obj-$(CONFIG_IXGBEVF) += ixgbevf/
-obj-$(CONFIG_IXGB) += ixgb/
-obj-$(CONFIG_IP1000) += ipg.o
-obj-$(CONFIG_CHELSIO_T1) += chelsio/
-obj-$(CONFIG_CHELSIO_T3) += cxgb3/
-obj-$(CONFIG_CHELSIO_T4) += cxgb4/
-obj-$(CONFIG_CHELSIO_T4VF) += cxgb4vf/
-obj-$(CONFIG_EHEA) += ehea/
-obj-$(CONFIG_CAN) += can/
-obj-$(CONFIG_BONDING) += bonding/
-obj-$(CONFIG_ATL1) += atlx/
-obj-$(CONFIG_ATL2) += atlx/
-obj-$(CONFIG_ATL1E) += atl1e/
-obj-$(CONFIG_ATL1C) += atl1c/
-obj-$(CONFIG_GIANFAR) += gianfar_driver.o
-obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
-obj-$(CONFIG_TEHUTI) += tehuti.o
-obj-$(CONFIG_ENIC) += enic/
-obj-$(CONFIG_JME) += jme.o
-obj-$(CONFIG_BE2NET) += benet/
-obj-$(CONFIG_VMXNET3) += vmxnet3/
-obj-$(CONFIG_BNA) += bna/
-
-gianfar_driver-objs := gianfar.o \
- gianfar_ethtool.o \
- gianfar_sysfs.o
-
-obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
-ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
-
-obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o
-
-#
-# link order important here
#
-obj-$(CONFIG_PLIP) += plip.o
-
-obj-$(CONFIG_ROADRUNNER) += rrunner.o
-
-obj-$(CONFIG_HAPPYMEAL) += sunhme.o
-obj-$(CONFIG_SUNLANCE) += sunlance.o
-obj-$(CONFIG_SUNQE) += sunqe.o
-obj-$(CONFIG_SUNBMAC) += sunbmac.o
-obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
-obj-$(CONFIG_CASSINI) += cassini.o
-obj-$(CONFIG_SUNVNET) += sunvnet.o
-
-obj-$(CONFIG_MACE) += mace.o
-obj-$(CONFIG_BMAC) += bmac.o
-
-obj-$(CONFIG_VORTEX) += 3c59x.o
-obj-$(CONFIG_TYPHOON) += typhoon.o
-obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
-obj-$(CONFIG_PCNET32) += pcnet32.o
-obj-$(CONFIG_E100) += e100.o
-obj-$(CONFIG_TLAN) += tlan.o
-obj-$(CONFIG_EPIC100) += epic100.o
-obj-$(CONFIG_SMSC9420) += smsc9420.o
-obj-$(CONFIG_SIS190) += sis190.o
-obj-$(CONFIG_SIS900) += sis900.o
-obj-$(CONFIG_R6040) += r6040.o
-obj-$(CONFIG_YELLOWFIN) += yellowfin.o
-obj-$(CONFIG_ACENIC) += acenic.o
-obj-$(CONFIG_ISERIES_VETH) += iseries_veth.o
-obj-$(CONFIG_NATSEMI) += natsemi.o
-obj-$(CONFIG_NS83820) += ns83820.o
-obj-$(CONFIG_STNIC) += stnic.o 8390.o
-obj-$(CONFIG_FEALNX) += fealnx.o
-obj-$(CONFIG_TIGON3) += tg3.o
-obj-$(CONFIG_BNX2) += bnx2.o
-obj-$(CONFIG_CNIC) += cnic.o
-obj-$(CONFIG_BNX2X) += bnx2x/
-spidernet-y += spider_net.o spider_net_ethtool.o
-obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o
-obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
-gelic_wireless-$(CONFIG_GELIC_WIRELESS) += ps3_gelic_wireless.o
-ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y)
-obj-$(CONFIG_TC35815) += tc35815.o
-obj-$(CONFIG_SKGE) += skge.o
-obj-$(CONFIG_SKY2) += sky2.o
-obj-$(CONFIG_SKFP) += skfp/
-obj-$(CONFIG_KS8842) += ks8842.o
-obj-$(CONFIG_KS8851) += ks8851.o
-obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
-obj-$(CONFIG_KSZ884X_PCI) += ksz884x.o
-obj-$(CONFIG_VIA_RHINE) += via-rhine.o
-obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
-obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
-obj-$(CONFIG_RIONET) += rionet.o
-obj-$(CONFIG_SH_ETH) += sh_eth.o
-obj-$(CONFIG_STMMAC_ETH) += stmmac/
-
+# Networking Core Drivers
#
-# end link order section
-#
-
-obj-$(CONFIG_SUNDANCE) += sundance.o
-obj-$(CONFIG_HAMACHI) += hamachi.o
-obj-$(CONFIG_NET) += Space.o loopback.o
-obj-$(CONFIG_SEEQ8005) += seeq8005.o
-obj-$(CONFIG_NET_SB1000) += sb1000.o
-obj-$(CONFIG_MAC8390) += mac8390.o
-obj-$(CONFIG_APNE) += apne.o 8390.o
-obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
-obj-$(CONFIG_HP100) += hp100.o
-obj-$(CONFIG_SMC9194) += smc9194.o
-obj-$(CONFIG_FEC) += fec.o
-obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
-ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
- obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
-endif
-obj-$(CONFIG_WD80x3) += wd.o 8390.o
-obj-$(CONFIG_EL2) += 3c503.o 8390p.o
-obj-$(CONFIG_NE2000) += ne.o 8390p.o
-obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o
-obj-$(CONFIG_HPLAN) += hp.o 8390p.o
-obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o
-obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
-obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
-obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
-obj-$(CONFIG_E2100) += e2100.o 8390.o
-obj-$(CONFIG_ES3210) += es3210.o 8390.o
-obj-$(CONFIG_LNE390) += lne390.o 8390.o
-obj-$(CONFIG_NE3210) += ne3210.o 8390.o
-obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
-obj-$(CONFIG_B44) += b44.o
-obj-$(CONFIG_FORCEDETH) += forcedeth.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o
-obj-$(CONFIG_AX88796) += ax88796.o
-obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
-obj-$(CONFIG_FTGMAC100) += ftgmac100.o
-obj-$(CONFIG_FTMAC100) += ftmac100.o
-
-obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
-obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
-ll_temac-objs := ll_temac_main.o ll_temac_mdio.o
-obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o
-obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
-obj-$(CONFIG_QLA3XXX) += qla3xxx.o
-obj-$(CONFIG_QLCNIC) += qlcnic/
-obj-$(CONFIG_QLGE) += qlge/
-
-obj-$(CONFIG_PPP) += ppp_generic.o
-obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
-obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
-obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
-obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
-obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
-obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
-obj-$(CONFIG_PPPOL2TP) += pppox.o
-obj-$(CONFIG_PPTP) += pppox.o pptp.o
-
-obj-$(CONFIG_SLIP) += slip.o
-obj-$(CONFIG_SLHC) += slhc.o
-
-obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
-obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/
-
+obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_DUMMY) += dummy.o
+obj-$(CONFIG_EQUALIZER) += eql.o
obj-$(CONFIG_IFB) += ifb.o
obj-$(CONFIG_MACVLAN) += macvlan.o
obj-$(CONFIG_MACVTAP) += macvtap.o
-obj-$(CONFIG_DE600) += de600.o
-obj-$(CONFIG_DE620) += de620.o
-obj-$(CONFIG_LANCE) += lance.o
-obj-$(CONFIG_SUN3_82586) += sun3_82586.o
-obj-$(CONFIG_SUN3LANCE) += sun3lance.o
-obj-$(CONFIG_DEFXX) += defxx.o
-obj-$(CONFIG_SGISEEQ) += sgiseeq.o
-obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o
-obj-$(CONFIG_AT1700) += at1700.o
-obj-$(CONFIG_EL1) += 3c501.o
-obj-$(CONFIG_EL16) += 3c507.o
-obj-$(CONFIG_ELMC) += 3c523.o
-obj-$(CONFIG_IBMLANA) += ibmlana.o
-obj-$(CONFIG_ELMC_II) += 3c527.o
-obj-$(CONFIG_EL3) += 3c509.o
-obj-$(CONFIG_3C515) += 3c515.o
-obj-$(CONFIG_EEXPRESS) += eexpress.o
-obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
-obj-$(CONFIG_8139CP) += 8139cp.o
-obj-$(CONFIG_8139TOO) += 8139too.o
-obj-$(CONFIG_ZNET) += znet.o
-obj-$(CONFIG_CPMAC) += cpmac.o
-obj-$(CONFIG_DEPCA) += depca.o
-obj-$(CONFIG_EWRK3) += ewrk3.o
-obj-$(CONFIG_ATP) += atp.o
-obj-$(CONFIG_NI5010) += ni5010.o
-obj-$(CONFIG_NI52) += ni52.o
-obj-$(CONFIG_NI65) += ni65.o
-obj-$(CONFIG_ELPLUS) += 3c505.o
-obj-$(CONFIG_AC3200) += ac3200.o 8390.o
-obj-$(CONFIG_APRICOT) += 82596.o
-obj-$(CONFIG_LASI_82596) += lasi_82596.o
-obj-$(CONFIG_SNI_82596) += sni_82596.o
-obj-$(CONFIG_MVME16x_NET) += 82596.o
-obj-$(CONFIG_BVME6000_NET) += 82596.o
-obj-$(CONFIG_SC92031) += sc92031.o
-
-# This is also a 82596 and should probably be merged
-obj-$(CONFIG_LP486E) += lp486e.o
-
-obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_ZORRO8390) += zorro8390.o
-obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
-obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
-obj-$(CONFIG_EQUALIZER) += eql.o
-obj-$(CONFIG_KORINA) += korina.o
-obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
-obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
-obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
-obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
-obj-$(CONFIG_DECLANCE) += declance.o
-obj-$(CONFIG_ATARILANCE) += atarilance.o
-obj-$(CONFIG_A2065) += a2065.o
-obj-$(CONFIG_HYDRA) += hydra.o
-obj-$(CONFIG_ARIADNE) += ariadne.o
-obj-$(CONFIG_CS89x0) += cs89x0.o
-obj-$(CONFIG_MACSONIC) += macsonic.o
-obj-$(CONFIG_MACMACE) += macmace.o
-obj-$(CONFIG_MAC89x0) += mac89x0.o
+obj-$(CONFIG_MII) += mii.o
+obj-$(CONFIG_MDIO) += mdio.o
+obj-$(CONFIG_NET) += Space.o loopback.o
+obj-$(CONFIG_NETCONSOLE) += netconsole.o
+obj-$(CONFIG_PHYLIB) += phy/
+obj-$(CONFIG_RIONET) += rionet.o
obj-$(CONFIG_TUN) += tun.o
obj-$(CONFIG_VETH) += veth.o
-obj-$(CONFIG_NET_NETX) += netx-eth.o
-obj-$(CONFIG_DL2K) += dl2k.o
-obj-$(CONFIG_R8169) += r8169.o
-obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
-obj-$(CONFIG_IBMVETH) += ibmveth.o
-obj-$(CONFIG_S2IO) += s2io.o
-obj-$(CONFIG_VXGE) += vxge/
-obj-$(CONFIG_MYRI10GE) += myri10ge/
-obj-$(CONFIG_SMC91X) += smc91x.o
-obj-$(CONFIG_SMC911X) += smc911x.o
-obj-$(CONFIG_SMSC911X) += smsc911x.o
-obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
-obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
-obj-$(CONFIG_DM9000) += dm9000.o
-obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
-pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
-obj-$(CONFIG_MLX4_CORE) += mlx4/
-obj-$(CONFIG_ENC28J60) += enc28j60.o
-obj-$(CONFIG_ETHOC) += ethoc.o
-obj-$(CONFIG_GRETH) += greth.o
-obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
-
-obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
-
-obj-$(CONFIG_DNET) += dnet.o
-obj-$(CONFIG_MACB) += macb.o
-obj-$(CONFIG_S6GMAC) += s6gmac.o
+obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
-obj-$(CONFIG_ARM) += arm/
+#
+# Networking Drivers
+#
+obj-$(CONFIG_ARCNET) += arcnet/
obj-$(CONFIG_DEV_APPLETALK) += appletalk/
+obj-$(CONFIG_CAIF) += caif/
+obj-$(CONFIG_CAN) += can/
+obj-$(CONFIG_ETRAX_ETHERNET) += cris/
+obj-$(CONFIG_ETHERNET) += ethernet/
+obj-$(CONFIG_FDDI) += fddi/
+obj-$(CONFIG_HIPPI) += hippi/
+obj-$(CONFIG_HAMRADIO) += hamradio/
+obj-$(CONFIG_IRDA) += irda/
+obj-$(CONFIG_PLIP) += plip/
+obj-$(CONFIG_PPP) += ppp/
+obj-$(CONFIG_PPP_ASYNC) += ppp/
+obj-$(CONFIG_PPP_BSDCOMP) += ppp/
+obj-$(CONFIG_PPP_DEFLATE) += ppp/
+obj-$(CONFIG_PPP_MPPE) += ppp/
+obj-$(CONFIG_PPP_SYNC_TTY) += ppp/
+obj-$(CONFIG_PPPOE) += ppp/
+obj-$(CONFIG_PPPOL2TP) += ppp/
+obj-$(CONFIG_PPTP) += ppp/
+obj-$(CONFIG_SLIP) += slip/
+obj-$(CONFIG_SLHC) += slip/
+obj-$(CONFIG_NET_SB1000) += sb1000.o
+obj-$(CONFIG_SUNGEM_PHY) += sungem_phy.o
obj-$(CONFIG_TR) += tokenring/
obj-$(CONFIG_WAN) += wan/
-obj-$(CONFIG_ARCNET) += arcnet/
-obj-$(CONFIG_NET_PCMCIA) += pcmcia/
+obj-$(CONFIG_WLAN) += wireless/
+obj-$(CONFIG_WIMAX) += wimax/
+
+obj-$(CONFIG_VMXNET3) += vmxnet3/
+obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
+obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/
obj-$(CONFIG_USB_CATC) += usb/
obj-$(CONFIG_USB_KAWETH) += usb/
@@ -283,26 +66,3 @@ obj-$(CONFIG_USB_USBNET) += usb/
obj-$(CONFIG_USB_ZD1201) += usb/
obj-$(CONFIG_USB_IPHETH) += usb/
obj-$(CONFIG_USB_CDC_PHONET) += usb/
-
-obj-$(CONFIG_WLAN) += wireless/
-obj-$(CONFIG_NET_TULIP) += tulip/
-obj-$(CONFIG_HAMRADIO) += hamradio/
-obj-$(CONFIG_IRDA) += irda/
-obj-$(CONFIG_ETRAX_ETHERNET) += cris/
-obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
-
-obj-$(CONFIG_NETCONSOLE) += netconsole.o
-
-obj-$(CONFIG_FS_ENET) += fs_enet/
-
-obj-$(CONFIG_NETXEN_NIC) += netxen/
-obj-$(CONFIG_NIU) += niu.o
-obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
-obj-$(CONFIG_SFC) += sfc/
-
-obj-$(CONFIG_WIMAX) += wimax/
-obj-$(CONFIG_CAIF) += caif/
-
-obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
-obj-$(CONFIG_PCH_GBE) += pch_gbe/
-obj-$(CONFIG_TILE_NET) += tile/
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index 748c9f526e71..9abd4eb86dc1 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -264,7 +264,7 @@ static const struct net_device_ops cops_netdev_ops = {
.ndo_start_xmit = cops_send_packet,
.ndo_tx_timeout = cops_timeout,
.ndo_do_ioctl = cops_ioctl,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
};
/*
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index 34ffb5422628..6057b30417a2 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -1014,7 +1014,7 @@ static int __init ltpc_probe_dma(int base, int dma)
static const struct net_device_ops ltpc_netdev = {
.ndo_start_xmit = ltpc_xmit,
.ndo_do_ioctl = ltpc_ioctl,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
};
struct net_device * __init ltpc_probe(void)
diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig
index 3b2f7f115464..a73d9dc80ff6 100644
--- a/drivers/net/arcnet/Kconfig
+++ b/drivers/net/arcnet/Kconfig
@@ -3,8 +3,8 @@
#
menuconfig ARCNET
- depends on NETDEVICES && (ISA || PCI)
- tristate "ARCnet support"
+ depends on NETDEVICES && (ISA || PCI || PCMCIA)
+ bool "ARCnet support"
---help---
If you have a network card of this type, say Y and check out the
(arguably) beautiful poetry in
@@ -123,4 +123,14 @@ config ARCNET_COM20020_PCI
tristate "Support for COM20020 on PCI"
depends on ARCNET_COM20020 && PCI
+config ARCNET_COM20020_CS
+ tristate "COM20020 ARCnet PCMCIA support"
+ depends on ARCNET_COM20020 && PCMCIA
+ help
+ Say Y here if you intend to attach this type of ARCnet PCMCIA card
+ to your computer.
+
+ To compile this driver as a module, choose M here: the module will be
+ called com20020_cs. If unsure, say N.
+
endif # ARCNET
diff --git a/drivers/net/arcnet/Makefile b/drivers/net/arcnet/Makefile
index 5861af543d42..5ce8ee63e435 100644
--- a/drivers/net/arcnet/Makefile
+++ b/drivers/net/arcnet/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_ARCNET_RIM_I) += arc-rimi.o
obj-$(CONFIG_ARCNET_COM20020) += com20020.o
obj-$(CONFIG_ARCNET_COM20020_ISA) += com20020-isa.o
obj-$(CONFIG_ARCNET_COM20020_PCI) += com20020-pci.o
+obj-$(CONFIG_ARCNET_COM20020_CS) += com20020_cs.o
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index 7bfb91f32857..7b96c5f47e8d 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -154,7 +154,7 @@ const struct net_device_ops com20020_netdev_ops = {
.ndo_stop = arcnet_close,
.ndo_start_xmit = arcnet_send_packet,
.ndo_tx_timeout = arcnet_timeout,
- .ndo_set_multicast_list = com20020_set_mc_list,
+ .ndo_set_rx_mode = com20020_set_mc_list,
};
/* Set up the struct net_device associated with this card. Called after
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c
index 980e65c14936..980e65c14936 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/arcnet/com20020_cs.c
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
deleted file mode 100644
index 39e1c0d39476..000000000000
--- a/drivers/net/arm/Kconfig
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# Acorn Network device configuration
-# These are for Acorn's Expansion card network interfaces
-#
-config ARM_AM79C961A
- bool "ARM EBSA110 AM79C961A support"
- depends on ARM && ARCH_EBSA110
- select CRC32
- help
- If you wish to compile a kernel for the EBSA-110, then you should
- always answer Y to this.
-
-config ARM_ETHER1
- tristate "Acorn Ether1 support"
- depends on ARM && ARCH_ACORN
- help
- If you have an Acorn system with one of these (AKA25) network cards,
- you should say Y to this option if you wish to use it with Linux.
-
-config ARM_ETHER3
- tristate "Acorn/ANT Ether3 support"
- depends on ARM && ARCH_ACORN
- help
- If you have an Acorn system with one of these network cards, you
- should say Y to this option if you wish to use it with Linux.
-
-config ARM_ETHERH
- tristate "I-cubed EtherH/ANT EtherM support"
- depends on ARM && ARCH_ACORN
- select CRC32
- help
- If you have an Acorn system with one of these network cards, you
- should say Y to this option if you wish to use it with Linux.
-
-config ARM_AT91_ETHER
- tristate "AT91RM9200 Ethernet support"
- depends on ARM && ARCH_AT91RM9200
- select MII
- help
- If you wish to compile a kernel for the AT91RM9200 and enable
- ethernet support, then you should always answer Y to this.
-
-config ARM_KS8695_ETHER
- tristate "KS8695 Ethernet support"
- depends on ARM && ARCH_KS8695
- select MII
- help
- If you wish to compile a kernel for the KS8695 and want to
- use the internal ethernet then you should answer Y to this.
-
-config EP93XX_ETH
- tristate "EP93xx Ethernet support"
- depends on ARM && ARCH_EP93XX
- select MII
- help
- This is a driver for the ethernet hardware included in EP93xx CPUs.
- Say Y if you are building a kernel for EP93xx based devices.
-
-config IXP4XX_ETH
- tristate "Intel IXP4xx Ethernet support"
- depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR
- select PHYLIB
- help
- Say Y here if you want to use built-in Ethernet ports
- on IXP4xx processor.
-
-config W90P910_ETH
- tristate "Nuvoton w90p910 Ethernet support"
- depends on ARM && ARCH_W90X900
- select PHYLIB
- select MII
- help
- Say Y here if you want to use built-in Ethernet ports
- on w90p910 processor.
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
deleted file mode 100644
index 303171f589e6..000000000000
--- a/drivers/net/arm/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# File: drivers/net/arm/Makefile
-#
-# Makefile for the ARM network device drivers
-#
-
-obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
-obj-$(CONFIG_ARM_ETHERH) += etherh.o
-obj-$(CONFIG_ARM_ETHER3) += ether3.o
-obj-$(CONFIG_ARM_ETHER1) += ether1.o
-obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o
-obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
-obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o
-obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o
-obj-$(CONFIG_W90P910_ETH) += w90p910_ether.o
diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig
deleted file mode 100644
index 1a41a49bb619..000000000000
--- a/drivers/net/benet/Kconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-config BE2NET
- tristate "ServerEngines' 10Gbps NIC - BladeEngine"
- depends on PCI && INET
- help
- This driver implements the NIC functionality for ServerEngines'
- 10Gbps network adapter - BladeEngine.
diff --git a/drivers/net/bna/bfa_ioc_ct.c b/drivers/net/bna/bfa_ioc_ct.c
deleted file mode 100644
index 87aecdf22cf9..000000000000
--- a/drivers/net/bna/bfa_ioc_ct.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#include "bfa_ioc.h"
-#include "cna.h"
-#include "bfi.h"
-#include "bfi_ctreg.h"
-#include "bfa_defs.h"
-
-#define bfa_ioc_ct_sync_pos(__ioc) \
- ((u32) (1 << bfa_ioc_pcifn(__ioc)))
-#define BFA_IOC_SYNC_REQD_SH 16
-#define bfa_ioc_ct_get_sync_ackd(__val) (__val & 0x0000ffff)
-#define bfa_ioc_ct_clear_sync_ackd(__val) (__val & 0xffff0000)
-#define bfa_ioc_ct_get_sync_reqd(__val) (__val >> BFA_IOC_SYNC_REQD_SH)
-#define bfa_ioc_ct_sync_reqd_pos(__ioc) \
- (bfa_ioc_ct_sync_pos(__ioc) << BFA_IOC_SYNC_REQD_SH)
-
-/*
- * forward declarations
- */
-static bool bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
-static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
-static bool bfa_ioc_ct_sync_start(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc);
-static bool bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc);
-static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode);
-
-static struct bfa_ioc_hwif nw_hwif_ct;
-
-/**
- * Called from bfa_ioc_attach() to map asic specific calls.
- */
-void
-bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc)
-{
- nw_hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
- nw_hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
- nw_hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
- nw_hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
- nw_hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
- nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
- nw_hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
- nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
- nw_hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start;
- nw_hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
- nw_hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
- nw_hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
- nw_hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
-
- ioc->ioc_hwif = &nw_hwif_ct;
-}
-
-/**
- * Return true if firmware of current driver matches the running firmware.
- */
-static bool
-bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc)
-{
- enum bfi_ioc_state ioc_fwstate;
- u32 usecnt;
- struct bfi_ioc_image_hdr fwhdr;
-
- /**
- * Firmware match check is relevant only for CNA.
- */
- if (!ioc->cna)
- return true;
-
- /**
- * If bios boot (flash based) -- do not increment usage count
- */
- if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
- BFA_IOC_FWIMG_MINSZ)
- return true;
-
- bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
- usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
-
- /**
- * If usage count is 0, always return TRUE.
- */
- if (usecnt == 0) {
- writel(1, ioc->ioc_regs.ioc_usage_reg);
- bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
- writel(0, ioc->ioc_regs.ioc_fail_sync);
- return true;
- }
-
- ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
-
- /**
- * Use count cannot be non-zero and chip in uninitialized state.
- */
- BUG_ON(!(ioc_fwstate != BFI_IOC_UNINIT));
-
- /**
- * Check if another driver with a different firmware is active
- */
- bfa_nw_ioc_fwver_get(ioc, &fwhdr);
- if (!bfa_nw_ioc_fwver_cmp(ioc, &fwhdr)) {
- bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
- return false;
- }
-
- /**
- * Same firmware version. Increment the reference count.
- */
- usecnt++;
- writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
- bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
- return true;
-}
-
-static void
-bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc)
-{
- u32 usecnt;
-
- /**
- * Firmware lock is relevant only for CNA.
- */
- if (!ioc->cna)
- return;
-
- /**
- * If bios boot (flash based) -- do not decrement usage count
- */
- if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
- BFA_IOC_FWIMG_MINSZ)
- return;
-
- /**
- * decrement usage count
- */
- bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
- usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
- BUG_ON(!(usecnt > 0));
-
- usecnt--;
- writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
-
- bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
-}
-
-/**
- * Notify other functions on HB failure.
- */
-static void
-bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc)
-{
- if (ioc->cna) {
- writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
- writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
- /* Wait for halt to take effect */
- readl(ioc->ioc_regs.ll_halt);
- readl(ioc->ioc_regs.alt_ll_halt);
- } else {
- writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
- readl(ioc->ioc_regs.err_set);
- }
-}
-
-/**
- * Host to LPU mailbox message addresses
- */
-static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
- { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
- { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
- { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
- { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 }
-};
-
-/**
- * Host <-> LPU mailbox command/status registers - port 0
- */
-static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = {
- { HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT },
- { HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT },
- { HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT },
- { HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT }
-};
-
-/**
- * Host <-> LPU mailbox command/status registers - port 1
- */
-static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = {
- { HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT },
- { HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT },
- { HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT },
- { HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT }
-};
-
-static void
-bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
-{
- void __iomem *rb;
- int pcifn = bfa_ioc_pcifn(ioc);
-
- rb = bfa_ioc_bar0(ioc);
-
- ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
- ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
- ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
-
- if (ioc->port_id == 0) {
- ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
- ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
- ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
- ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
- ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
- ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
- ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
- } else {
- ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
- ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
- ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG;
- ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
- ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
- ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
- ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
- }
-
- /*
- * PSS control registers
- */
- ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
- ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
- ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
- ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
-
- /*
- * IOC semaphore registers and serialization
- */
- ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
- ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
- ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
- ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
- ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC);
-
- /**
- * sram memory access
- */
- ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
- ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
-
- /*
- * err set reg : for notification of hb failure in fcmode
- */
- ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
-}
-
-/**
- * Initialize IOC to port mapping.
- */
-
-#define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8)
-static void
-bfa_ioc_ct_map_port(struct bfa_ioc *ioc)
-{
- void __iomem *rb = ioc->pcidev.pci_bar_kva;
- u32 r32;
-
- /**
- * For catapult, base port id on personality register and IOC type
- */
- r32 = readl(rb + FNC_PERS_REG);
- r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
- ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
-
-}
-
-/**
- * Set interrupt mode for a function: INTX or MSIX
- */
-static void
-bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix)
-{
- void __iomem *rb = ioc->pcidev.pci_bar_kva;
- u32 r32, mode;
-
- r32 = readl(rb + FNC_PERS_REG);
-
- mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
- __F0_INTX_STATUS;
-
- /**
- * If already in desired mode, do not change anything
- */
- if (!msix && mode)
- return;
-
- if (msix)
- mode = __F0_INTX_STATUS_MSIX;
- else
- mode = __F0_INTX_STATUS_INTA;
-
- r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
- r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
-
- writel(r32, rb + FNC_PERS_REG);
-}
-
-/**
- * Cleanup hw semaphore and usecnt registers
- */
-static void
-bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc)
-{
- if (ioc->cna) {
- bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
- writel(0, ioc->ioc_regs.ioc_usage_reg);
- bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
- }
-
- /*
- * Read the hw sem reg to make sure that it is locked
- * before we clear it. If it is not locked, writing 1
- * will lock it instead of clearing it.
- */
- readl(ioc->ioc_regs.ioc_sem_reg);
- bfa_nw_ioc_hw_sem_release(ioc);
-}
-
-/**
- * Synchronized IOC failure processing routines
- */
-static bool
-bfa_ioc_ct_sync_start(struct bfa_ioc *ioc)
-{
- u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
- u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
-
- /*
- * Driver load time. If the sync required bit for this PCI fn
- * is set, it is due to an unclean exit by the driver for this
- * PCI fn in the previous incarnation. Whoever comes here first
- * should clean it up, no matter which PCI fn.
- */
-
- if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) {
- writel(0, ioc->ioc_regs.ioc_fail_sync);
- writel(1, ioc->ioc_regs.ioc_usage_reg);
- writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
- writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
- return true;
- }
-
- return bfa_ioc_ct_sync_complete(ioc);
-}
-/**
- * Synchronized IOC failure processing routines
- */
-static void
-bfa_ioc_ct_sync_join(struct bfa_ioc *ioc)
-{
- u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
- u32 sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc);
-
- writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync);
-}
-
-static void
-bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc)
-{
- u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
- u32 sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) |
- bfa_ioc_ct_sync_pos(ioc);
-
- writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync);
-}
-
-static void
-bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc)
-{
- u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
-
- writel((r32 | bfa_ioc_ct_sync_pos(ioc)), ioc->ioc_regs.ioc_fail_sync);
-}
-
-static bool
-bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc)
-{
- u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
- u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
- u32 sync_ackd = bfa_ioc_ct_get_sync_ackd(r32);
- u32 tmp_ackd;
-
- if (sync_ackd == 0)
- return true;
-
- /**
- * The check below is to see whether any other PCI fn
- * has reinitialized the ASIC (reset sync_ackd bits)
- * and failed again while this IOC was waiting for hw
- * semaphore (in bfa_iocpf_sm_semwait()).
- */
- tmp_ackd = sync_ackd;
- if ((sync_reqd & bfa_ioc_ct_sync_pos(ioc)) &&
- !(sync_ackd & bfa_ioc_ct_sync_pos(ioc)))
- sync_ackd |= bfa_ioc_ct_sync_pos(ioc);
-
- if (sync_reqd == sync_ackd) {
- writel(bfa_ioc_ct_clear_sync_ackd(r32),
- ioc->ioc_regs.ioc_fail_sync);
- writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
- writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate);
- return true;
- }
-
- /**
- * If another PCI fn reinitialized and failed again while
- * this IOC was waiting for hw sem, the sync_ackd bit for
- * this IOC need to be set again to allow reinitialization.
- */
- if (tmp_ackd != sync_ackd)
- writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync);
-
- return false;
-}
-
-static enum bfa_status
-bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
-{
- u32 pll_sclk, pll_fclk, r32;
-
- pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
- __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
- __APP_PLL_312_JITLMT0_1(3U) |
- __APP_PLL_312_CNTLMT0_1(1U);
- pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
- __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
- __APP_PLL_425_JITLMT0_1(3U) |
- __APP_PLL_425_CNTLMT0_1(1U);
- if (fcmode) {
- writel(0, (rb + OP_MODE));
- writel(__APP_EMS_CMLCKSEL |
- __APP_EMS_REFCKBUFEN2 |
- __APP_EMS_CHANNEL_SEL,
- (rb + ETH_MAC_SER_REG));
- } else {
- writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE));
- writel(__APP_EMS_REFCKBUFEN1,
- (rb + ETH_MAC_SER_REG));
- }
- writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
- writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
- writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
- writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
- writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
- writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
- writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
- writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
- writel(pll_sclk |
- __APP_PLL_312_LOGIC_SOFT_RESET,
- rb + APP_PLL_312_CTL_REG);
- writel(pll_fclk |
- __APP_PLL_425_LOGIC_SOFT_RESET,
- rb + APP_PLL_425_CTL_REG);
- writel(pll_sclk |
- __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE,
- rb + APP_PLL_312_CTL_REG);
- writel(pll_fclk |
- __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE,
- rb + APP_PLL_425_CTL_REG);
- readl(rb + HOSTFN0_INT_MSK);
- udelay(2000);
- writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
- writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
- writel(pll_sclk |
- __APP_PLL_312_ENABLE,
- rb + APP_PLL_312_CTL_REG);
- writel(pll_fclk |
- __APP_PLL_425_ENABLE,
- rb + APP_PLL_425_CTL_REG);
- if (!fcmode) {
- writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));
- writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1));
- }
- r32 = readl((rb + PSS_CTL_REG));
- r32 &= ~__PSS_LMEM_RESET;
- writel(r32, (rb + PSS_CTL_REG));
- udelay(1000);
- if (!fcmode) {
- writel(0, (rb + PMM_1T_RESET_REG_P0));
- writel(0, (rb + PMM_1T_RESET_REG_P1));
- }
-
- writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG));
- udelay(1000);
- r32 = readl((rb + MBIST_STAT_REG));
- writel(0, (rb + MBIST_CTL_REG));
- return BFA_STATUS_OK;
-}
diff --git a/drivers/net/bna/bfi_ctreg.h b/drivers/net/bna/bfi_ctreg.h
deleted file mode 100644
index 5130d7918660..000000000000
--- a/drivers/net/bna/bfi_ctreg.h
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-/*
- * bfi_ctreg.h catapult host block register definitions
- *
- * !!! Do not edit. Auto generated. !!!
- */
-
-#ifndef __BFI_CTREG_H__
-#define __BFI_CTREG_H__
-
-#define HOSTFN0_LPU_MBOX0_0 0x00019200
-#define HOSTFN1_LPU_MBOX0_8 0x00019260
-#define LPU_HOSTFN0_MBOX0_0 0x00019280
-#define LPU_HOSTFN1_MBOX0_8 0x000192e0
-#define HOSTFN2_LPU_MBOX0_0 0x00019400
-#define HOSTFN3_LPU_MBOX0_8 0x00019460
-#define LPU_HOSTFN2_MBOX0_0 0x00019480
-#define LPU_HOSTFN3_MBOX0_8 0x000194e0
-#define HOSTFN0_INT_STATUS 0x00014000
-#define __HOSTFN0_HALT_OCCURRED 0x01000000
-#define __HOSTFN0_INT_STATUS_LVL_MK 0x00f00000
-#define __HOSTFN0_INT_STATUS_LVL_SH 20
-#define __HOSTFN0_INT_STATUS_LVL(_v) ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
-#define __HOSTFN0_INT_STATUS_P_MK 0x000f0000
-#define __HOSTFN0_INT_STATUS_P_SH 16
-#define __HOSTFN0_INT_STATUS_P(_v) ((_v) << __HOSTFN0_INT_STATUS_P_SH)
-#define __HOSTFN0_INT_STATUS_F 0x0000ffff
-#define HOSTFN0_INT_MSK 0x00014004
-#define HOST_PAGE_NUM_FN0 0x00014008
-#define __HOST_PAGE_NUM_FN 0x000001ff
-#define HOST_MSIX_ERR_INDEX_FN0 0x0001400c
-#define __MSIX_ERR_INDEX_FN 0x000001ff
-#define HOSTFN1_INT_STATUS 0x00014100
-#define __HOSTFN1_HALT_OCCURRED 0x01000000
-#define __HOSTFN1_INT_STATUS_LVL_MK 0x00f00000
-#define __HOSTFN1_INT_STATUS_LVL_SH 20
-#define __HOSTFN1_INT_STATUS_LVL(_v) ((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
-#define __HOSTFN1_INT_STATUS_P_MK 0x000f0000
-#define __HOSTFN1_INT_STATUS_P_SH 16
-#define __HOSTFN1_INT_STATUS_P(_v) ((_v) << __HOSTFN1_INT_STATUS_P_SH)
-#define __HOSTFN1_INT_STATUS_F 0x0000ffff
-#define HOSTFN1_INT_MSK 0x00014104
-#define HOST_PAGE_NUM_FN1 0x00014108
-#define HOST_MSIX_ERR_INDEX_FN1 0x0001410c
-#define APP_PLL_425_CTL_REG 0x00014204
-#define __P_425_PLL_LOCK 0x80000000
-#define __APP_PLL_425_SRAM_USE_100MHZ 0x00100000
-#define __APP_PLL_425_RESET_TIMER_MK 0x000e0000
-#define __APP_PLL_425_RESET_TIMER_SH 17
-#define __APP_PLL_425_RESET_TIMER(_v) ((_v) << __APP_PLL_425_RESET_TIMER_SH)
-#define __APP_PLL_425_LOGIC_SOFT_RESET 0x00010000
-#define __APP_PLL_425_CNTLMT0_1_MK 0x0000c000
-#define __APP_PLL_425_CNTLMT0_1_SH 14
-#define __APP_PLL_425_CNTLMT0_1(_v) ((_v) << __APP_PLL_425_CNTLMT0_1_SH)
-#define __APP_PLL_425_JITLMT0_1_MK 0x00003000
-#define __APP_PLL_425_JITLMT0_1_SH 12
-#define __APP_PLL_425_JITLMT0_1(_v) ((_v) << __APP_PLL_425_JITLMT0_1_SH)
-#define __APP_PLL_425_HREF 0x00000800
-#define __APP_PLL_425_HDIV 0x00000400
-#define __APP_PLL_425_P0_1_MK 0x00000300
-#define __APP_PLL_425_P0_1_SH 8
-#define __APP_PLL_425_P0_1(_v) ((_v) << __APP_PLL_425_P0_1_SH)
-#define __APP_PLL_425_Z0_2_MK 0x000000e0
-#define __APP_PLL_425_Z0_2_SH 5
-#define __APP_PLL_425_Z0_2(_v) ((_v) << __APP_PLL_425_Z0_2_SH)
-#define __APP_PLL_425_RSEL200500 0x00000010
-#define __APP_PLL_425_ENARST 0x00000008
-#define __APP_PLL_425_BYPASS 0x00000004
-#define __APP_PLL_425_LRESETN 0x00000002
-#define __APP_PLL_425_ENABLE 0x00000001
-#define APP_PLL_312_CTL_REG 0x00014208
-#define __P_312_PLL_LOCK 0x80000000
-#define __ENABLE_MAC_AHB_1 0x00800000
-#define __ENABLE_MAC_AHB_0 0x00400000
-#define __ENABLE_MAC_1 0x00200000
-#define __ENABLE_MAC_0 0x00100000
-#define __APP_PLL_312_RESET_TIMER_MK 0x000e0000
-#define __APP_PLL_312_RESET_TIMER_SH 17
-#define __APP_PLL_312_RESET_TIMER(_v) ((_v) << __APP_PLL_312_RESET_TIMER_SH)
-#define __APP_PLL_312_LOGIC_SOFT_RESET 0x00010000
-#define __APP_PLL_312_CNTLMT0_1_MK 0x0000c000
-#define __APP_PLL_312_CNTLMT0_1_SH 14
-#define __APP_PLL_312_CNTLMT0_1(_v) ((_v) << __APP_PLL_312_CNTLMT0_1_SH)
-#define __APP_PLL_312_JITLMT0_1_MK 0x00003000
-#define __APP_PLL_312_JITLMT0_1_SH 12
-#define __APP_PLL_312_JITLMT0_1(_v) ((_v) << __APP_PLL_312_JITLMT0_1_SH)
-#define __APP_PLL_312_HREF 0x00000800
-#define __APP_PLL_312_HDIV 0x00000400
-#define __APP_PLL_312_P0_1_MK 0x00000300
-#define __APP_PLL_312_P0_1_SH 8
-#define __APP_PLL_312_P0_1(_v) ((_v) << __APP_PLL_312_P0_1_SH)
-#define __APP_PLL_312_Z0_2_MK 0x000000e0
-#define __APP_PLL_312_Z0_2_SH 5
-#define __APP_PLL_312_Z0_2(_v) ((_v) << __APP_PLL_312_Z0_2_SH)
-#define __APP_PLL_312_RSEL200500 0x00000010
-#define __APP_PLL_312_ENARST 0x00000008
-#define __APP_PLL_312_BYPASS 0x00000004
-#define __APP_PLL_312_LRESETN 0x00000002
-#define __APP_PLL_312_ENABLE 0x00000001
-#define MBIST_CTL_REG 0x00014220
-#define __EDRAM_BISTR_START 0x00000004
-#define __MBIST_RESET 0x00000002
-#define __MBIST_START 0x00000001
-#define MBIST_STAT_REG 0x00014224
-#define __EDRAM_BISTR_STATUS 0x00000008
-#define __EDRAM_BISTR_DONE 0x00000004
-#define __MEM_BIT_STATUS 0x00000002
-#define __MBIST_DONE 0x00000001
-#define HOST_SEM0_REG 0x00014230
-#define __HOST_SEMAPHORE 0x00000001
-#define HOST_SEM1_REG 0x00014234
-#define HOST_SEM2_REG 0x00014238
-#define HOST_SEM3_REG 0x0001423c
-#define HOST_SEM0_INFO_REG 0x00014240
-#define HOST_SEM1_INFO_REG 0x00014244
-#define HOST_SEM2_INFO_REG 0x00014248
-#define HOST_SEM3_INFO_REG 0x0001424c
-#define ETH_MAC_SER_REG 0x00014288
-#define __APP_EMS_CKBUFAMPIN 0x00000020
-#define __APP_EMS_REFCLKSEL 0x00000010
-#define __APP_EMS_CMLCKSEL 0x00000008
-#define __APP_EMS_REFCKBUFEN2 0x00000004
-#define __APP_EMS_REFCKBUFEN1 0x00000002
-#define __APP_EMS_CHANNEL_SEL 0x00000001
-#define HOSTFN2_INT_STATUS 0x00014300
-#define __HOSTFN2_HALT_OCCURRED 0x01000000
-#define __HOSTFN2_INT_STATUS_LVL_MK 0x00f00000
-#define __HOSTFN2_INT_STATUS_LVL_SH 20
-#define __HOSTFN2_INT_STATUS_LVL(_v) ((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
-#define __HOSTFN2_INT_STATUS_P_MK 0x000f0000
-#define __HOSTFN2_INT_STATUS_P_SH 16
-#define __HOSTFN2_INT_STATUS_P(_v) ((_v) << __HOSTFN2_INT_STATUS_P_SH)
-#define __HOSTFN2_INT_STATUS_F 0x0000ffff
-#define HOSTFN2_INT_MSK 0x00014304
-#define HOST_PAGE_NUM_FN2 0x00014308
-#define HOST_MSIX_ERR_INDEX_FN2 0x0001430c
-#define HOSTFN3_INT_STATUS 0x00014400
-#define __HALT_OCCURRED 0x01000000
-#define __HOSTFN3_INT_STATUS_LVL_MK 0x00f00000
-#define __HOSTFN3_INT_STATUS_LVL_SH 20
-#define __HOSTFN3_INT_STATUS_LVL(_v) ((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
-#define __HOSTFN3_INT_STATUS_P_MK 0x000f0000
-#define __HOSTFN3_INT_STATUS_P_SH 16
-#define __HOSTFN3_INT_STATUS_P(_v) ((_v) << __HOSTFN3_INT_STATUS_P_SH)
-#define __HOSTFN3_INT_STATUS_F 0x0000ffff
-#define HOSTFN3_INT_MSK 0x00014404
-#define HOST_PAGE_NUM_FN3 0x00014408
-#define HOST_MSIX_ERR_INDEX_FN3 0x0001440c
-#define FNC_ID_REG 0x00014600
-#define __FUNCTION_NUMBER 0x00000007
-#define FNC_PERS_REG 0x00014604
-#define __F3_FUNCTION_ACTIVE 0x80000000
-#define __F3_FUNCTION_MODE 0x40000000
-#define __F3_PORT_MAP_MK 0x30000000
-#define __F3_PORT_MAP_SH 28
-#define __F3_PORT_MAP(_v) ((_v) << __F3_PORT_MAP_SH)
-#define __F3_VM_MODE 0x08000000
-#define __F3_INTX_STATUS_MK 0x07000000
-#define __F3_INTX_STATUS_SH 24
-#define __F3_INTX_STATUS(_v) ((_v) << __F3_INTX_STATUS_SH)
-#define __F2_FUNCTION_ACTIVE 0x00800000
-#define __F2_FUNCTION_MODE 0x00400000
-#define __F2_PORT_MAP_MK 0x00300000
-#define __F2_PORT_MAP_SH 20
-#define __F2_PORT_MAP(_v) ((_v) << __F2_PORT_MAP_SH)
-#define __F2_VM_MODE 0x00080000
-#define __F2_INTX_STATUS_MK 0x00070000
-#define __F2_INTX_STATUS_SH 16
-#define __F2_INTX_STATUS(_v) ((_v) << __F2_INTX_STATUS_SH)
-#define __F1_FUNCTION_ACTIVE 0x00008000
-#define __F1_FUNCTION_MODE 0x00004000
-#define __F1_PORT_MAP_MK 0x00003000
-#define __F1_PORT_MAP_SH 12
-#define __F1_PORT_MAP(_v) ((_v) << __F1_PORT_MAP_SH)
-#define __F1_VM_MODE 0x00000800
-#define __F1_INTX_STATUS_MK 0x00000700
-#define __F1_INTX_STATUS_SH 8
-#define __F1_INTX_STATUS(_v) ((_v) << __F1_INTX_STATUS_SH)
-#define __F0_FUNCTION_ACTIVE 0x00000080
-#define __F0_FUNCTION_MODE 0x00000040
-#define __F0_PORT_MAP_MK 0x00000030
-#define __F0_PORT_MAP_SH 4
-#define __F0_PORT_MAP(_v) ((_v) << __F0_PORT_MAP_SH)
-#define __F0_VM_MODE 0x00000008
-#define __F0_INTX_STATUS 0x00000007
-enum {
- __F0_INTX_STATUS_MSIX = 0x0,
- __F0_INTX_STATUS_INTA = 0x1,
- __F0_INTX_STATUS_INTB = 0x2,
- __F0_INTX_STATUS_INTC = 0x3,
- __F0_INTX_STATUS_INTD = 0x4,
-};
-#define OP_MODE 0x0001460c
-#define __APP_ETH_CLK_LOWSPEED 0x00000004
-#define __GLOBAL_CORECLK_HALFSPEED 0x00000002
-#define __GLOBAL_FCOE_MODE 0x00000001
-#define HOST_SEM4_REG 0x00014610
-#define HOST_SEM5_REG 0x00014614
-#define HOST_SEM6_REG 0x00014618
-#define HOST_SEM7_REG 0x0001461c
-#define HOST_SEM4_INFO_REG 0x00014620
-#define HOST_SEM5_INFO_REG 0x00014624
-#define HOST_SEM6_INFO_REG 0x00014628
-#define HOST_SEM7_INFO_REG 0x0001462c
-#define HOSTFN0_LPU0_MBOX0_CMD_STAT 0x00019000
-#define __HOSTFN0_LPU0_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN0_LPU0_MBOX0_INFO_SH 1
-#define __HOSTFN0_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN0_LPU1_MBOX0_CMD_STAT 0x00019004
-#define __HOSTFN0_LPU1_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN0_LPU1_MBOX0_INFO_SH 1
-#define __HOSTFN0_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN0_MBOX0_CMD_STAT 0x00019008
-#define __LPU0_HOSTFN0_MBOX0_INFO_MK 0xfffffffe
-#define __LPU0_HOSTFN0_MBOX0_INFO_SH 1
-#define __LPU0_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN0_MBOX0_CMD_STAT 0x0001900c
-#define __LPU1_HOSTFN0_MBOX0_INFO_MK 0xfffffffe
-#define __LPU1_HOSTFN0_MBOX0_INFO_SH 1
-#define __LPU1_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU0_MBOX0_CMD_STAT 0x00019010
-#define __HOSTFN1_LPU0_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN1_LPU0_MBOX0_INFO_SH 1
-#define __HOSTFN1_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU1_MBOX0_CMD_STAT 0x00019014
-#define __HOSTFN1_LPU1_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN1_LPU1_MBOX0_INFO_SH 1
-#define __HOSTFN1_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN1_MBOX0_CMD_STAT 0x00019018
-#define __LPU0_HOSTFN1_MBOX0_INFO_MK 0xfffffffe
-#define __LPU0_HOSTFN1_MBOX0_INFO_SH 1
-#define __LPU0_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN1_MBOX0_CMD_STAT 0x0001901c
-#define __LPU1_HOSTFN1_MBOX0_INFO_MK 0xfffffffe
-#define __LPU1_HOSTFN1_MBOX0_INFO_SH 1
-#define __LPU1_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN2_LPU0_MBOX0_CMD_STAT 0x00019150
-#define __HOSTFN2_LPU0_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN2_LPU0_MBOX0_INFO_SH 1
-#define __HOSTFN2_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN2_LPU1_MBOX0_CMD_STAT 0x00019154
-#define __HOSTFN2_LPU1_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN2_LPU1_MBOX0_INFO_SH 1
-#define __HOSTFN2_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN2_MBOX0_CMD_STAT 0x00019158
-#define __LPU0_HOSTFN2_MBOX0_INFO_MK 0xfffffffe
-#define __LPU0_HOSTFN2_MBOX0_INFO_SH 1
-#define __LPU0_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN2_MBOX0_CMD_STAT 0x0001915c
-#define __LPU1_HOSTFN2_MBOX0_INFO_MK 0xfffffffe
-#define __LPU1_HOSTFN2_MBOX0_INFO_SH 1
-#define __LPU1_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN3_LPU0_MBOX0_CMD_STAT 0x00019160
-#define __HOSTFN3_LPU0_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN3_LPU0_MBOX0_INFO_SH 1
-#define __HOSTFN3_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN3_LPU1_MBOX0_CMD_STAT 0x00019164
-#define __HOSTFN3_LPU1_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN3_LPU1_MBOX0_INFO_SH 1
-#define __HOSTFN3_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN3_MBOX0_CMD_STAT 0x00019168
-#define __LPU0_HOSTFN3_MBOX0_INFO_MK 0xfffffffe
-#define __LPU0_HOSTFN3_MBOX0_INFO_SH 1
-#define __LPU0_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN3_MBOX0_CMD_STAT 0x0001916c
-#define __LPU1_HOSTFN3_MBOX0_INFO_MK 0xfffffffe
-#define __LPU1_HOSTFN3_MBOX0_INFO_SH 1
-#define __LPU1_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
-#define FW_INIT_HALT_P0 0x000191ac
-#define __FW_INIT_HALT_P 0x00000001
-#define FW_INIT_HALT_P1 0x000191bc
-#define CPE_PI_PTR_Q0 0x00038000
-#define __CPE_PI_UNUSED_MK 0xffff0000
-#define __CPE_PI_UNUSED_SH 16
-#define __CPE_PI_UNUSED(_v) ((_v) << __CPE_PI_UNUSED_SH)
-#define __CPE_PI_PTR 0x0000ffff
-#define CPE_PI_PTR_Q1 0x00038040
-#define CPE_CI_PTR_Q0 0x00038004
-#define __CPE_CI_UNUSED_MK 0xffff0000
-#define __CPE_CI_UNUSED_SH 16
-#define __CPE_CI_UNUSED(_v) ((_v) << __CPE_CI_UNUSED_SH)
-#define __CPE_CI_PTR 0x0000ffff
-#define CPE_CI_PTR_Q1 0x00038044
-#define CPE_DEPTH_Q0 0x00038008
-#define __CPE_DEPTH_UNUSED_MK 0xf8000000
-#define __CPE_DEPTH_UNUSED_SH 27
-#define __CPE_DEPTH_UNUSED(_v) ((_v) << __CPE_DEPTH_UNUSED_SH)
-#define __CPE_MSIX_VEC_INDEX_MK 0x07ff0000
-#define __CPE_MSIX_VEC_INDEX_SH 16
-#define __CPE_MSIX_VEC_INDEX(_v) ((_v) << __CPE_MSIX_VEC_INDEX_SH)
-#define __CPE_DEPTH 0x0000ffff
-#define CPE_DEPTH_Q1 0x00038048
-#define CPE_QCTRL_Q0 0x0003800c
-#define __CPE_CTRL_UNUSED30_MK 0xfc000000
-#define __CPE_CTRL_UNUSED30_SH 26
-#define __CPE_CTRL_UNUSED30(_v) ((_v) << __CPE_CTRL_UNUSED30_SH)
-#define __CPE_FUNC_INT_CTRL_MK 0x03000000
-#define __CPE_FUNC_INT_CTRL_SH 24
-#define __CPE_FUNC_INT_CTRL(_v) ((_v) << __CPE_FUNC_INT_CTRL_SH)
-enum {
- __CPE_FUNC_INT_CTRL_DISABLE = 0x0,
- __CPE_FUNC_INT_CTRL_F2NF = 0x1,
- __CPE_FUNC_INT_CTRL_3QUART = 0x2,
- __CPE_FUNC_INT_CTRL_HALF = 0x3,
-};
-#define __CPE_CTRL_UNUSED20_MK 0x00f00000
-#define __CPE_CTRL_UNUSED20_SH 20
-#define __CPE_CTRL_UNUSED20(_v) ((_v) << __CPE_CTRL_UNUSED20_SH)
-#define __CPE_SCI_TH_MK 0x000f0000
-#define __CPE_SCI_TH_SH 16
-#define __CPE_SCI_TH(_v) ((_v) << __CPE_SCI_TH_SH)
-#define __CPE_CTRL_UNUSED10_MK 0x0000c000
-#define __CPE_CTRL_UNUSED10_SH 14
-#define __CPE_CTRL_UNUSED10(_v) ((_v) << __CPE_CTRL_UNUSED10_SH)
-#define __CPE_ACK_PENDING 0x00002000
-#define __CPE_CTRL_UNUSED40_MK 0x00001c00
-#define __CPE_CTRL_UNUSED40_SH 10
-#define __CPE_CTRL_UNUSED40(_v) ((_v) << __CPE_CTRL_UNUSED40_SH)
-#define __CPE_PCIEID_MK 0x00000300
-#define __CPE_PCIEID_SH 8
-#define __CPE_PCIEID(_v) ((_v) << __CPE_PCIEID_SH)
-#define __CPE_CTRL_UNUSED00_MK 0x000000fe
-#define __CPE_CTRL_UNUSED00_SH 1
-#define __CPE_CTRL_UNUSED00(_v) ((_v) << __CPE_CTRL_UNUSED00_SH)
-#define __CPE_ESIZE 0x00000001
-#define CPE_QCTRL_Q1 0x0003804c
-#define __CPE_CTRL_UNUSED31_MK 0xfc000000
-#define __CPE_CTRL_UNUSED31_SH 26
-#define __CPE_CTRL_UNUSED31(_v) ((_v) << __CPE_CTRL_UNUSED31_SH)
-#define __CPE_CTRL_UNUSED21_MK 0x00f00000
-#define __CPE_CTRL_UNUSED21_SH 20
-#define __CPE_CTRL_UNUSED21(_v) ((_v) << __CPE_CTRL_UNUSED21_SH)
-#define __CPE_CTRL_UNUSED11_MK 0x0000c000
-#define __CPE_CTRL_UNUSED11_SH 14
-#define __CPE_CTRL_UNUSED11(_v) ((_v) << __CPE_CTRL_UNUSED11_SH)
-#define __CPE_CTRL_UNUSED41_MK 0x00001c00
-#define __CPE_CTRL_UNUSED41_SH 10
-#define __CPE_CTRL_UNUSED41(_v) ((_v) << __CPE_CTRL_UNUSED41_SH)
-#define __CPE_CTRL_UNUSED01_MK 0x000000fe
-#define __CPE_CTRL_UNUSED01_SH 1
-#define __CPE_CTRL_UNUSED01(_v) ((_v) << __CPE_CTRL_UNUSED01_SH)
-#define RME_PI_PTR_Q0 0x00038020
-#define __LATENCY_TIME_STAMP_MK 0xffff0000
-#define __LATENCY_TIME_STAMP_SH 16
-#define __LATENCY_TIME_STAMP(_v) ((_v) << __LATENCY_TIME_STAMP_SH)
-#define __RME_PI_PTR 0x0000ffff
-#define RME_PI_PTR_Q1 0x00038060
-#define RME_CI_PTR_Q0 0x00038024
-#define __DELAY_TIME_STAMP_MK 0xffff0000
-#define __DELAY_TIME_STAMP_SH 16
-#define __DELAY_TIME_STAMP(_v) ((_v) << __DELAY_TIME_STAMP_SH)
-#define __RME_CI_PTR 0x0000ffff
-#define RME_CI_PTR_Q1 0x00038064
-#define RME_DEPTH_Q0 0x00038028
-#define __RME_DEPTH_UNUSED_MK 0xf8000000
-#define __RME_DEPTH_UNUSED_SH 27
-#define __RME_DEPTH_UNUSED(_v) ((_v) << __RME_DEPTH_UNUSED_SH)
-#define __RME_MSIX_VEC_INDEX_MK 0x07ff0000
-#define __RME_MSIX_VEC_INDEX_SH 16
-#define __RME_MSIX_VEC_INDEX(_v) ((_v) << __RME_MSIX_VEC_INDEX_SH)
-#define __RME_DEPTH 0x0000ffff
-#define RME_DEPTH_Q1 0x00038068
-#define RME_QCTRL_Q0 0x0003802c
-#define __RME_INT_LATENCY_TIMER_MK 0xff000000
-#define __RME_INT_LATENCY_TIMER_SH 24
-#define __RME_INT_LATENCY_TIMER(_v) ((_v) << __RME_INT_LATENCY_TIMER_SH)
-#define __RME_INT_DELAY_TIMER_MK 0x00ff0000
-#define __RME_INT_DELAY_TIMER_SH 16
-#define __RME_INT_DELAY_TIMER(_v) ((_v) << __RME_INT_DELAY_TIMER_SH)
-#define __RME_INT_DELAY_DISABLE 0x00008000
-#define __RME_DLY_DELAY_DISABLE 0x00004000
-#define __RME_ACK_PENDING 0x00002000
-#define __RME_FULL_INTERRUPT_DISABLE 0x00001000
-#define __RME_CTRL_UNUSED10_MK 0x00000c00
-#define __RME_CTRL_UNUSED10_SH 10
-#define __RME_CTRL_UNUSED10(_v) ((_v) << __RME_CTRL_UNUSED10_SH)
-#define __RME_PCIEID_MK 0x00000300
-#define __RME_PCIEID_SH 8
-#define __RME_PCIEID(_v) ((_v) << __RME_PCIEID_SH)
-#define __RME_CTRL_UNUSED00_MK 0x000000fe
-#define __RME_CTRL_UNUSED00_SH 1
-#define __RME_CTRL_UNUSED00(_v) ((_v) << __RME_CTRL_UNUSED00_SH)
-#define __RME_ESIZE 0x00000001
-#define RME_QCTRL_Q1 0x0003806c
-#define __RME_CTRL_UNUSED11_MK 0x00000c00
-#define __RME_CTRL_UNUSED11_SH 10
-#define __RME_CTRL_UNUSED11(_v) ((_v) << __RME_CTRL_UNUSED11_SH)
-#define __RME_CTRL_UNUSED01_MK 0x000000fe
-#define __RME_CTRL_UNUSED01_SH 1
-#define __RME_CTRL_UNUSED01(_v) ((_v) << __RME_CTRL_UNUSED01_SH)
-#define PSS_CTL_REG 0x00018800
-#define __PSS_I2C_CLK_DIV_MK 0x007f0000
-#define __PSS_I2C_CLK_DIV_SH 16
-#define __PSS_I2C_CLK_DIV(_v) ((_v) << __PSS_I2C_CLK_DIV_SH)
-#define __PSS_LMEM_INIT_DONE 0x00001000
-#define __PSS_LMEM_RESET 0x00000200
-#define __PSS_LMEM_INIT_EN 0x00000100
-#define __PSS_LPU1_RESET 0x00000002
-#define __PSS_LPU0_RESET 0x00000001
-#define PSS_ERR_STATUS_REG 0x00018810
-#define __PSS_LPU1_TCM_READ_ERR 0x00200000
-#define __PSS_LPU0_TCM_READ_ERR 0x00100000
-#define __PSS_LMEM5_CORR_ERR 0x00080000
-#define __PSS_LMEM4_CORR_ERR 0x00040000
-#define __PSS_LMEM3_CORR_ERR 0x00020000
-#define __PSS_LMEM2_CORR_ERR 0x00010000
-#define __PSS_LMEM1_CORR_ERR 0x00008000
-#define __PSS_LMEM0_CORR_ERR 0x00004000
-#define __PSS_LMEM5_UNCORR_ERR 0x00002000
-#define __PSS_LMEM4_UNCORR_ERR 0x00001000
-#define __PSS_LMEM3_UNCORR_ERR 0x00000800
-#define __PSS_LMEM2_UNCORR_ERR 0x00000400
-#define __PSS_LMEM1_UNCORR_ERR 0x00000200
-#define __PSS_LMEM0_UNCORR_ERR 0x00000100
-#define __PSS_BAL_PERR 0x00000080
-#define __PSS_DIP_IF_ERR 0x00000040
-#define __PSS_IOH_IF_ERR 0x00000020
-#define __PSS_TDS_IF_ERR 0x00000010
-#define __PSS_RDS_IF_ERR 0x00000008
-#define __PSS_SGM_IF_ERR 0x00000004
-#define __PSS_LPU1_RAM_ERR 0x00000002
-#define __PSS_LPU0_RAM_ERR 0x00000001
-#define ERR_SET_REG 0x00018818
-#define __PSS_ERR_STATUS_SET 0x003fffff
-#define PMM_1T_RESET_REG_P0 0x0002381c
-#define __PMM_1T_RESET_P 0x00000001
-#define PMM_1T_RESET_REG_P1 0x00023c1c
-#define HQM_QSET0_RXQ_DRBL_P0 0x00038000
-#define __RXQ0_ADD_VECTORS_P 0x80000000
-#define __RXQ0_STOP_P 0x40000000
-#define __RXQ0_PRD_PTR_P 0x0000ffff
-#define HQM_QSET1_RXQ_DRBL_P0 0x00038080
-#define __RXQ1_ADD_VECTORS_P 0x80000000
-#define __RXQ1_STOP_P 0x40000000
-#define __RXQ1_PRD_PTR_P 0x0000ffff
-#define HQM_QSET0_RXQ_DRBL_P1 0x0003c000
-#define HQM_QSET1_RXQ_DRBL_P1 0x0003c080
-#define HQM_QSET0_TXQ_DRBL_P0 0x00038020
-#define __TXQ0_ADD_VECTORS_P 0x80000000
-#define __TXQ0_STOP_P 0x40000000
-#define __TXQ0_PRD_PTR_P 0x0000ffff
-#define HQM_QSET1_TXQ_DRBL_P0 0x000380a0
-#define __TXQ1_ADD_VECTORS_P 0x80000000
-#define __TXQ1_STOP_P 0x40000000
-#define __TXQ1_PRD_PTR_P 0x0000ffff
-#define HQM_QSET0_TXQ_DRBL_P1 0x0003c020
-#define HQM_QSET1_TXQ_DRBL_P1 0x0003c0a0
-#define HQM_QSET0_IB_DRBL_1_P0 0x00038040
-#define __IB1_0_ACK_P 0x80000000
-#define __IB1_0_DISABLE_P 0x40000000
-#define __IB1_0_COALESCING_CFG_P_MK 0x00ff0000
-#define __IB1_0_COALESCING_CFG_P_SH 16
-#define __IB1_0_COALESCING_CFG_P(_v) ((_v) << __IB1_0_COALESCING_CFG_P_SH)
-#define __IB1_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff
-#define HQM_QSET1_IB_DRBL_1_P0 0x000380c0
-#define __IB1_1_ACK_P 0x80000000
-#define __IB1_1_DISABLE_P 0x40000000
-#define __IB1_1_COALESCING_CFG_P_MK 0x00ff0000
-#define __IB1_1_COALESCING_CFG_P_SH 16
-#define __IB1_1_COALESCING_CFG_P(_v) ((_v) << __IB1_1_COALESCING_CFG_P_SH)
-#define __IB1_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff
-#define HQM_QSET0_IB_DRBL_1_P1 0x0003c040
-#define HQM_QSET1_IB_DRBL_1_P1 0x0003c0c0
-#define HQM_QSET0_IB_DRBL_2_P0 0x00038060
-#define __IB2_0_ACK_P 0x80000000
-#define __IB2_0_DISABLE_P 0x40000000
-#define __IB2_0_COALESCING_CFG_P_MK 0x00ff0000
-#define __IB2_0_COALESCING_CFG_P_SH 16
-#define __IB2_0_COALESCING_CFG_P(_v) ((_v) << __IB2_0_COALESCING_CFG_P_SH)
-#define __IB2_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff
-#define HQM_QSET1_IB_DRBL_2_P0 0x000380e0
-#define __IB2_1_ACK_P 0x80000000
-#define __IB2_1_DISABLE_P 0x40000000
-#define __IB2_1_COALESCING_CFG_P_MK 0x00ff0000
-#define __IB2_1_COALESCING_CFG_P_SH 16
-#define __IB2_1_COALESCING_CFG_P(_v) ((_v) << __IB2_1_COALESCING_CFG_P_SH)
-#define __IB2_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff
-#define HQM_QSET0_IB_DRBL_2_P1 0x0003c060
-#define HQM_QSET1_IB_DRBL_2_P1 0x0003c0e0
-
-/*
- * These definitions are either in error/missing in spec. Its auto-generated
- * from hard coded values in regparse.pl.
- */
-#define __EMPHPOST_AT_4G_MK_FIX 0x0000001c
-#define __EMPHPOST_AT_4G_SH_FIX 0x00000002
-#define __EMPHPRE_AT_4G_FIX 0x00000003
-#define __SFP_TXRATE_EN_FIX 0x00000100
-#define __SFP_RXRATE_EN_FIX 0x00000080
-
-/*
- * These register definitions are auto-generated from hard coded values
- * in regparse.pl.
- */
-
-/*
- * These register mapping definitions are auto-generated from mapping tables
- * in regparse.pl.
- */
-#define BFA_IOC0_HBEAT_REG HOST_SEM0_INFO_REG
-#define BFA_IOC0_STATE_REG HOST_SEM1_INFO_REG
-#define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG
-#define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG
-#define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG
-#define BFA_IOC_FAIL_SYNC HOST_SEM5_INFO_REG
-
-#define CPE_DEPTH_Q(__n) \
- (CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
-#define CPE_QCTRL_Q(__n) \
- (CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
-#define CPE_PI_PTR_Q(__n) \
- (CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
-#define CPE_CI_PTR_Q(__n) \
- (CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
-#define RME_DEPTH_Q(__n) \
- (RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
-#define RME_QCTRL_Q(__n) \
- (RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
-#define RME_PI_PTR_Q(__n) \
- (RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
-#define RME_CI_PTR_Q(__n) \
- (RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
-#define HQM_QSET_RXQ_DRBL_P0(__n) \
- (HQM_QSET0_RXQ_DRBL_P0 + (__n) * \
- (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
-#define HQM_QSET_TXQ_DRBL_P0(__n) \
- (HQM_QSET0_TXQ_DRBL_P0 + (__n) * \
- (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
-#define HQM_QSET_IB_DRBL_1_P0(__n) \
- (HQM_QSET0_IB_DRBL_1_P0 + (__n) * \
- (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
-#define HQM_QSET_IB_DRBL_2_P0(__n) \
- (HQM_QSET0_IB_DRBL_2_P0 + (__n) * \
- (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
-#define HQM_QSET_RXQ_DRBL_P1(__n) \
- (HQM_QSET0_RXQ_DRBL_P1 + (__n) * \
- (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
-#define HQM_QSET_TXQ_DRBL_P1(__n) \
- (HQM_QSET0_TXQ_DRBL_P1 + (__n) * \
- (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
-#define HQM_QSET_IB_DRBL_1_P1(__n) \
- (HQM_QSET0_IB_DRBL_1_P1 + (__n) * \
- (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
-#define HQM_QSET_IB_DRBL_2_P1(__n) \
- (HQM_QSET0_IB_DRBL_2_P1 + (__n) * \
- (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
-
-#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
-#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
-#define CPE_Q_MASK(__q) ((__q) & 0x3)
-#define RME_Q_MASK(__q) ((__q) & 0x3)
-
-/*
- * PCI MSI-X vector defines
- */
-enum {
- BFA_MSIX_CPE_Q0 = 0,
- BFA_MSIX_CPE_Q1 = 1,
- BFA_MSIX_CPE_Q2 = 2,
- BFA_MSIX_CPE_Q3 = 3,
- BFA_MSIX_RME_Q0 = 4,
- BFA_MSIX_RME_Q1 = 5,
- BFA_MSIX_RME_Q2 = 6,
- BFA_MSIX_RME_Q3 = 7,
- BFA_MSIX_LPU_ERR = 8,
- BFA_MSIX_CT_MAX = 9,
-};
-
-/*
- * And corresponding host interrupt status bit field defines
- */
-#define __HFN_INT_CPE_Q0 0x00000001U
-#define __HFN_INT_CPE_Q1 0x00000002U
-#define __HFN_INT_CPE_Q2 0x00000004U
-#define __HFN_INT_CPE_Q3 0x00000008U
-#define __HFN_INT_CPE_Q4 0x00000010U
-#define __HFN_INT_CPE_Q5 0x00000020U
-#define __HFN_INT_CPE_Q6 0x00000040U
-#define __HFN_INT_CPE_Q7 0x00000080U
-#define __HFN_INT_RME_Q0 0x00000100U
-#define __HFN_INT_RME_Q1 0x00000200U
-#define __HFN_INT_RME_Q2 0x00000400U
-#define __HFN_INT_RME_Q3 0x00000800U
-#define __HFN_INT_RME_Q4 0x00001000U
-#define __HFN_INT_RME_Q5 0x00002000U
-#define __HFN_INT_RME_Q6 0x00004000U
-#define __HFN_INT_RME_Q7 0x00008000U
-#define __HFN_INT_ERR_EMC 0x00010000U
-#define __HFN_INT_ERR_LPU0 0x00020000U
-#define __HFN_INT_ERR_LPU1 0x00040000U
-#define __HFN_INT_ERR_PSS 0x00080000U
-#define __HFN_INT_MBOX_LPU0 0x00100000U
-#define __HFN_INT_MBOX_LPU1 0x00200000U
-#define __HFN_INT_MBOX1_LPU0 0x00400000U
-#define __HFN_INT_MBOX1_LPU1 0x00800000U
-#define __HFN_INT_LL_HALT 0x01000000U
-#define __HFN_INT_CPE_MASK 0x000000ffU
-#define __HFN_INT_RME_MASK 0x0000ff00U
-
-/*
- * catapult memory map.
- */
-#define LL_PGN_HQM0 0x0096
-#define LL_PGN_HQM1 0x0097
-#define PSS_SMEM_PAGE_START 0x8000
-#define PSS_SMEM_PGNUM(_pg0, _ma) ((_pg0) + ((_ma) >> 15))
-#define PSS_SMEM_PGOFF(_ma) ((_ma) & 0x7fff)
-
-/*
- * End of catapult memory map
- */
-
-#endif /* __BFI_CTREG_H__ */
diff --git a/drivers/net/bna/bfi_ll.h b/drivers/net/bna/bfi_ll.h
deleted file mode 100644
index bee4d054066a..000000000000
--- a/drivers/net/bna/bfi_ll.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#ifndef __BFI_LL_H__
-#define __BFI_LL_H__
-
-#include "bfi.h"
-
-#pragma pack(1)
-
-/**
- * @brief
- * "enums" for all LL mailbox messages other than IOC
- */
-enum {
- BFI_LL_H2I_MAC_UCAST_SET_REQ = 1,
- BFI_LL_H2I_MAC_UCAST_ADD_REQ = 2,
- BFI_LL_H2I_MAC_UCAST_DEL_REQ = 3,
-
- BFI_LL_H2I_MAC_MCAST_ADD_REQ = 4,
- BFI_LL_H2I_MAC_MCAST_DEL_REQ = 5,
- BFI_LL_H2I_MAC_MCAST_FILTER_REQ = 6,
- BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ = 7,
-
- BFI_LL_H2I_PORT_ADMIN_REQ = 8,
- BFI_LL_H2I_STATS_GET_REQ = 9,
- BFI_LL_H2I_STATS_CLEAR_REQ = 10,
-
- BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ = 11,
- BFI_LL_H2I_RXF_DEFAULT_SET_REQ = 12,
-
- BFI_LL_H2I_TXQ_STOP_REQ = 13,
- BFI_LL_H2I_RXQ_STOP_REQ = 14,
-
- BFI_LL_H2I_DIAG_LOOPBACK_REQ = 15,
-
- BFI_LL_H2I_SET_PAUSE_REQ = 16,
- BFI_LL_H2I_MTU_INFO_REQ = 17,
-
- BFI_LL_H2I_RX_REQ = 18,
-} ;
-
-enum {
- BFI_LL_I2H_MAC_UCAST_SET_RSP = BFA_I2HM(1),
- BFI_LL_I2H_MAC_UCAST_ADD_RSP = BFA_I2HM(2),
- BFI_LL_I2H_MAC_UCAST_DEL_RSP = BFA_I2HM(3),
-
- BFI_LL_I2H_MAC_MCAST_ADD_RSP = BFA_I2HM(4),
- BFI_LL_I2H_MAC_MCAST_DEL_RSP = BFA_I2HM(5),
- BFI_LL_I2H_MAC_MCAST_FILTER_RSP = BFA_I2HM(6),
- BFI_LL_I2H_MAC_MCAST_DEL_ALL_RSP = BFA_I2HM(7),
-
- BFI_LL_I2H_PORT_ADMIN_RSP = BFA_I2HM(8),
- BFI_LL_I2H_STATS_GET_RSP = BFA_I2HM(9),
- BFI_LL_I2H_STATS_CLEAR_RSP = BFA_I2HM(10),
-
- BFI_LL_I2H_RXF_PROMISCUOUS_SET_RSP = BFA_I2HM(11),
- BFI_LL_I2H_RXF_DEFAULT_SET_RSP = BFA_I2HM(12),
-
- BFI_LL_I2H_TXQ_STOP_RSP = BFA_I2HM(13),
- BFI_LL_I2H_RXQ_STOP_RSP = BFA_I2HM(14),
-
- BFI_LL_I2H_DIAG_LOOPBACK_RSP = BFA_I2HM(15),
-
- BFI_LL_I2H_SET_PAUSE_RSP = BFA_I2HM(16),
-
- BFI_LL_I2H_MTU_INFO_RSP = BFA_I2HM(17),
- BFI_LL_I2H_RX_RSP = BFA_I2HM(18),
-
- BFI_LL_I2H_LINK_DOWN_AEN = BFA_I2HM(19),
- BFI_LL_I2H_LINK_UP_AEN = BFA_I2HM(20),
-
- BFI_LL_I2H_PORT_ENABLE_AEN = BFA_I2HM(21),
- BFI_LL_I2H_PORT_DISABLE_AEN = BFA_I2HM(22),
-} ;
-
-/**
- * @brief bfi_ll_mac_addr_req is used by:
- * BFI_LL_H2I_MAC_UCAST_SET_REQ
- * BFI_LL_H2I_MAC_UCAST_ADD_REQ
- * BFI_LL_H2I_MAC_UCAST_DEL_REQ
- * BFI_LL_H2I_MAC_MCAST_ADD_REQ
- * BFI_LL_H2I_MAC_MCAST_DEL_REQ
- */
-struct bfi_ll_mac_addr_req {
- struct bfi_mhdr mh; /*!< common msg header */
- u8 rxf_id;
- u8 rsvd1[3];
- mac_t mac_addr;
- u8 rsvd2[2];
-};
-
-/**
- * @brief bfi_ll_mcast_filter_req is used by:
- * BFI_LL_H2I_MAC_MCAST_FILTER_REQ
- */
-struct bfi_ll_mcast_filter_req {
- struct bfi_mhdr mh; /*!< common msg header */
- u8 rxf_id;
- u8 enable;
- u8 rsvd[2];
-};
-
-/**
- * @brief bfi_ll_mcast_del_all is used by:
- * BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ
- */
-struct bfi_ll_mcast_del_all_req {
- struct bfi_mhdr mh; /*!< common msg header */
- u8 rxf_id;
- u8 rsvd[3];
-};
-
-/**
- * @brief bfi_ll_q_stop_req is used by:
- * BFI_LL_H2I_TXQ_STOP_REQ
- * BFI_LL_H2I_RXQ_STOP_REQ
- */
-struct bfi_ll_q_stop_req {
- struct bfi_mhdr mh; /*!< common msg header */
- u32 q_id_mask[2]; /* !< bit-mask for queue ids */
-};
-
-/**
- * @brief bfi_ll_stats_req is used by:
- * BFI_LL_I2H_STATS_GET_REQ
- * BFI_LL_I2H_STATS_CLEAR_REQ
- */
-struct bfi_ll_stats_req {
- struct bfi_mhdr mh; /*!< common msg header */
- u16 stats_mask; /* !< bit-mask for non-function statistics */
- u8 rsvd[2];
- u32 rxf_id_mask[2]; /* !< bit-mask for RxF Statistics */
- u32 txf_id_mask[2]; /* !< bit-mask for TxF Statistics */
- union bfi_addr_u host_buffer; /* !< where statistics are returned */
-};
-
-/**
- * @brief defines for "stats_mask" above.
- */
-#define BFI_LL_STATS_MAC (1 << 0) /* !< MAC Statistics */
-#define BFI_LL_STATS_BPC (1 << 1) /* !< Pause Stats from BPC */
-#define BFI_LL_STATS_RAD (1 << 2) /* !< Rx Admission Statistics */
-#define BFI_LL_STATS_RX_FC (1 << 3) /* !< Rx FC Stats from RxA */
-#define BFI_LL_STATS_TX_FC (1 << 4) /* !< Tx FC Stats from TxA */
-
-#define BFI_LL_STATS_ALL 0x1f
-
-/**
- * @brief bfi_ll_port_admin_req
- */
-struct bfi_ll_port_admin_req {
- struct bfi_mhdr mh; /*!< common msg header */
- u8 up;
- u8 rsvd[3];
-};
-
-/**
- * @brief bfi_ll_rxf_req is used by:
- * BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ
- * BFI_LL_H2I_RXF_DEFAULT_SET_REQ
- */
-struct bfi_ll_rxf_req {
- struct bfi_mhdr mh; /*!< common msg header */
- u8 rxf_id;
- u8 enable;
- u8 rsvd[2];
-};
-
-/**
- * @brief bfi_ll_rxf_multi_req is used by:
- * BFI_LL_H2I_RX_REQ
- */
-struct bfi_ll_rxf_multi_req {
- struct bfi_mhdr mh; /*!< common msg header */
- u32 rxf_id_mask[2];
- u8 enable;
- u8 rsvd[3];
-};
-
-/**
- * @brief enum for Loopback opmodes
- */
-enum {
- BFI_LL_DIAG_LB_OPMODE_EXT = 0,
- BFI_LL_DIAG_LB_OPMODE_CBL = 1,
-};
-
-/**
- * @brief bfi_ll_set_pause_req is used by:
- * BFI_LL_H2I_SET_PAUSE_REQ
- */
-struct bfi_ll_set_pause_req {
- struct bfi_mhdr mh;
- u8 tx_pause; /* 1 = enable, 0 = disable */
- u8 rx_pause; /* 1 = enable, 0 = disable */
- u8 rsvd[2];
-};
-
-/**
- * @brief bfi_ll_mtu_info_req is used by:
- * BFI_LL_H2I_MTU_INFO_REQ
- */
-struct bfi_ll_mtu_info_req {
- struct bfi_mhdr mh;
- u16 mtu;
- u8 rsvd[2];
-};
-
-/**
- * @brief
- * Response header format used by all responses
- * For both responses and asynchronous notifications
- */
-struct bfi_ll_rsp {
- struct bfi_mhdr mh; /*!< common msg header */
- u8 error;
- u8 rsvd[3];
-};
-
-/**
- * @brief bfi_ll_cee_aen is used by:
- * BFI_LL_I2H_LINK_DOWN_AEN
- * BFI_LL_I2H_LINK_UP_AEN
- */
-struct bfi_ll_aen {
- struct bfi_mhdr mh; /*!< common msg header */
- u32 reason;
- u8 cee_linkup;
- u8 prio_map; /*!< LL priority bit-map */
- u8 rsvd[2];
-};
-
-/**
- * @brief
- * The following error codes can be returned
- * by the mbox commands
- */
-enum {
- BFI_LL_CMD_OK = 0,
- BFI_LL_CMD_FAIL = 1,
- BFI_LL_CMD_DUP_ENTRY = 2, /* !< Duplicate entry in CAM */
- BFI_LL_CMD_CAM_FULL = 3, /* !< CAM is full */
- BFI_LL_CMD_NOT_OWNER = 4, /* !< Not permitted, b'cos not owner */
- BFI_LL_CMD_NOT_EXEC = 5, /* !< Was not sent to f/w at all */
- BFI_LL_CMD_WAITING = 6, /* !< Waiting for completion (VMware) */
- BFI_LL_CMD_PORT_DISABLED = 7, /* !< port in disabled state */
-} ;
-
-/* Statistics */
-#define BFI_LL_TXF_ID_MAX 64
-#define BFI_LL_RXF_ID_MAX 64
-
-/* TxF Frame Statistics */
-struct bfi_ll_stats_txf {
- u64 ucast_octets;
- u64 ucast;
- u64 ucast_vlan;
-
- u64 mcast_octets;
- u64 mcast;
- u64 mcast_vlan;
-
- u64 bcast_octets;
- u64 bcast;
- u64 bcast_vlan;
-
- u64 errors;
- u64 filter_vlan; /* frames filtered due to VLAN */
- u64 filter_mac_sa; /* frames filtered due to SA check */
-};
-
-/* RxF Frame Statistics */
-struct bfi_ll_stats_rxf {
- u64 ucast_octets;
- u64 ucast;
- u64 ucast_vlan;
-
- u64 mcast_octets;
- u64 mcast;
- u64 mcast_vlan;
-
- u64 bcast_octets;
- u64 bcast;
- u64 bcast_vlan;
- u64 frame_drops;
-};
-
-/* FC Tx Frame Statistics */
-struct bfi_ll_stats_fc_tx {
- u64 txf_ucast_octets;
- u64 txf_ucast;
- u64 txf_ucast_vlan;
-
- u64 txf_mcast_octets;
- u64 txf_mcast;
- u64 txf_mcast_vlan;
-
- u64 txf_bcast_octets;
- u64 txf_bcast;
- u64 txf_bcast_vlan;
-
- u64 txf_parity_errors;
- u64 txf_timeout;
- u64 txf_fid_parity_errors;
-};
-
-/* FC Rx Frame Statistics */
-struct bfi_ll_stats_fc_rx {
- u64 rxf_ucast_octets;
- u64 rxf_ucast;
- u64 rxf_ucast_vlan;
-
- u64 rxf_mcast_octets;
- u64 rxf_mcast;
- u64 rxf_mcast_vlan;
-
- u64 rxf_bcast_octets;
- u64 rxf_bcast;
- u64 rxf_bcast_vlan;
-};
-
-/* RAD Frame Statistics */
-struct bfi_ll_stats_rad {
- u64 rx_frames;
- u64 rx_octets;
- u64 rx_vlan_frames;
-
- u64 rx_ucast;
- u64 rx_ucast_octets;
- u64 rx_ucast_vlan;
-
- u64 rx_mcast;
- u64 rx_mcast_octets;
- u64 rx_mcast_vlan;
-
- u64 rx_bcast;
- u64 rx_bcast_octets;
- u64 rx_bcast_vlan;
-
- u64 rx_drops;
-};
-
-/* BPC Tx Registers */
-struct bfi_ll_stats_bpc {
- /* transmit stats */
- u64 tx_pause[8];
- u64 tx_zero_pause[8]; /*!< Pause cancellation */
- /*!<Pause initiation rather than retention */
- u64 tx_first_pause[8];
-
- /* receive stats */
- u64 rx_pause[8];
- u64 rx_zero_pause[8]; /*!< Pause cancellation */
- /*!<Pause initiation rather than retention */
- u64 rx_first_pause[8];
-};
-
-/* MAC Rx Statistics */
-struct bfi_ll_stats_mac {
- 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 */
- u64 frame_256_511; /* both rx and tx counter */
- u64 frame_512_1023; /* both rx and tx counter */
- u64 frame_1024_1518; /* both rx and tx counter */
- u64 frame_1519_1522; /* both rx and tx counter */
-
- /* receive stats */
- u64 rx_bytes;
- u64 rx_packets;
- u64 rx_fcs_error;
- u64 rx_multicast;
- u64 rx_broadcast;
- u64 rx_control_frames;
- u64 rx_pause;
- u64 rx_unknown_opcode;
- u64 rx_alignment_error;
- u64 rx_frame_length_error;
- u64 rx_code_error;
- u64 rx_carrier_sense_error;
- u64 rx_undersize;
- u64 rx_oversize;
- u64 rx_fragments;
- u64 rx_jabber;
- u64 rx_drop;
-
- /* transmit stats */
- u64 tx_bytes;
- u64 tx_packets;
- u64 tx_multicast;
- u64 tx_broadcast;
- u64 tx_pause;
- u64 tx_deferral;
- u64 tx_excessive_deferral;
- u64 tx_single_collision;
- u64 tx_muliple_collision;
- u64 tx_late_collision;
- u64 tx_excessive_collision;
- u64 tx_total_collision;
- u64 tx_pause_honored;
- u64 tx_drop;
- u64 tx_jabber;
- u64 tx_fcs_error;
- u64 tx_control_frame;
- u64 tx_oversize;
- u64 tx_undersize;
- u64 tx_fragments;
-};
-
-/* Complete statistics */
-struct bfi_ll_stats {
- struct bfi_ll_stats_mac mac_stats;
- struct bfi_ll_stats_bpc bpc_stats;
- struct bfi_ll_stats_rad rad_stats;
- struct bfi_ll_stats_fc_rx fc_rx_stats;
- struct bfi_ll_stats_fc_tx fc_tx_stats;
- struct bfi_ll_stats_rxf rxf_stats[BFI_LL_RXF_ID_MAX];
- struct bfi_ll_stats_txf txf_stats[BFI_LL_TXF_ID_MAX];
-};
-
-#pragma pack()
-
-#endif /* __BFI_LL_H__ */
diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c
deleted file mode 100644
index cb2594c564dc..000000000000
--- a/drivers/net/bna/bna_ctrl.c
+++ /dev/null
@@ -1,3076 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#include "bna.h"
-#include "bfa_cs.h"
-
-static void bna_device_cb_port_stopped(void *arg, enum bna_cb_status status);
-
-static void
-bna_port_cb_link_up(struct bna_port *port, struct bfi_ll_aen *aen,
- int status)
-{
- int i;
- u8 prio_map;
-
- port->llport.link_status = BNA_LINK_UP;
- if (aen->cee_linkup)
- port->llport.link_status = BNA_CEE_UP;
-
- /* Compute the priority */
- prio_map = aen->prio_map;
- if (prio_map) {
- for (i = 0; i < 8; i++) {
- if ((prio_map >> i) & 0x1)
- break;
- }
- port->priority = i;
- } else
- port->priority = 0;
-
- /* Dispatch events */
- bna_tx_mod_cee_link_status(&port->bna->tx_mod, aen->cee_linkup);
- bna_tx_mod_prio_changed(&port->bna->tx_mod, port->priority);
- port->link_cbfn(port->bna->bnad, port->llport.link_status);
-}
-
-static void
-bna_port_cb_link_down(struct bna_port *port, int status)
-{
- port->llport.link_status = BNA_LINK_DOWN;
-
- /* Dispatch events */
- bna_tx_mod_cee_link_status(&port->bna->tx_mod, BNA_LINK_DOWN);
- port->link_cbfn(port->bna->bnad, BNA_LINK_DOWN);
-}
-
-static inline int
-llport_can_be_up(struct bna_llport *llport)
-{
- int ready = 0;
- if (llport->type == BNA_PORT_T_REGULAR)
- ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
- (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
- (llport->flags & BNA_LLPORT_F_PORT_ENABLED));
- else
- ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
- (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
- !(llport->flags & BNA_LLPORT_F_PORT_ENABLED));
- return ready;
-}
-
-#define llport_is_up llport_can_be_up
-
-enum bna_llport_event {
- LLPORT_E_START = 1,
- LLPORT_E_STOP = 2,
- LLPORT_E_FAIL = 3,
- LLPORT_E_UP = 4,
- LLPORT_E_DOWN = 5,
- LLPORT_E_FWRESP_UP_OK = 6,
- LLPORT_E_FWRESP_UP_FAIL = 7,
- LLPORT_E_FWRESP_DOWN = 8
-};
-
-static void
-bna_llport_cb_port_enabled(struct bna_llport *llport)
-{
- llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
-
- if (llport_can_be_up(llport))
- bfa_fsm_send_event(llport, LLPORT_E_UP);
-}
-
-static void
-bna_llport_cb_port_disabled(struct bna_llport *llport)
-{
- int llport_up = llport_is_up(llport);
-
- llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
-
- if (llport_up)
- bfa_fsm_send_event(llport, LLPORT_E_DOWN);
-}
-
-/**
- * MBOX
- */
-static int
-bna_is_aen(u8 msg_id)
-{
- switch (msg_id) {
- case BFI_LL_I2H_LINK_DOWN_AEN:
- case BFI_LL_I2H_LINK_UP_AEN:
- case BFI_LL_I2H_PORT_ENABLE_AEN:
- case BFI_LL_I2H_PORT_DISABLE_AEN:
- return 1;
-
- default:
- return 0;
- }
-}
-
-static void
-bna_mbox_aen_callback(struct bna *bna, struct bfi_mbmsg *msg)
-{
- struct bfi_ll_aen *aen = (struct bfi_ll_aen *)(msg);
-
- switch (aen->mh.msg_id) {
- case BFI_LL_I2H_LINK_UP_AEN:
- bna_port_cb_link_up(&bna->port, aen, aen->reason);
- break;
- case BFI_LL_I2H_LINK_DOWN_AEN:
- bna_port_cb_link_down(&bna->port, aen->reason);
- break;
- case BFI_LL_I2H_PORT_ENABLE_AEN:
- bna_llport_cb_port_enabled(&bna->port.llport);
- break;
- case BFI_LL_I2H_PORT_DISABLE_AEN:
- bna_llport_cb_port_disabled(&bna->port.llport);
- break;
- default:
- break;
- }
-}
-
-static void
-bna_ll_isr(void *llarg, struct bfi_mbmsg *msg)
-{
- struct bna *bna = (struct bna *)(llarg);
- struct bfi_ll_rsp *mb_rsp = (struct bfi_ll_rsp *)(msg);
- struct bfi_mhdr *cmd_h, *rsp_h;
- struct bna_mbox_qe *mb_qe = NULL;
- int to_post = 0;
- u8 aen = 0;
- char message[BNA_MESSAGE_SIZE];
-
- aen = bna_is_aen(mb_rsp->mh.msg_id);
-
- if (!aen) {
- mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
- cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]);
- rsp_h = (struct bfi_mhdr *)(&mb_rsp->mh);
-
- if ((BFA_I2HM(cmd_h->msg_id) == rsp_h->msg_id) &&
- (cmd_h->mtag.i2htok == rsp_h->mtag.i2htok)) {
- /* Remove the request from posted_q, update state */
- list_del(&mb_qe->qe);
- bna->mbox_mod.msg_pending--;
- if (list_empty(&bna->mbox_mod.posted_q))
- bna->mbox_mod.state = BNA_MBOX_FREE;
- else
- to_post = 1;
-
- /* Dispatch the cbfn */
- if (mb_qe->cbfn)
- mb_qe->cbfn(mb_qe->cbarg, mb_rsp->error);
-
- /* Post the next entry, if needed */
- if (to_post) {
- mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
- bfa_nw_ioc_mbox_queue(&bna->device.ioc,
- &mb_qe->cmd);
- }
- } else {
- snprintf(message, BNA_MESSAGE_SIZE,
- "No matching rsp for [%d:%d:%d]\n",
- mb_rsp->mh.msg_class, mb_rsp->mh.msg_id,
- mb_rsp->mh.mtag.i2htok);
- pr_info("%s", message);
- }
-
- } else
- bna_mbox_aen_callback(bna, msg);
-}
-
-static void
-bna_err_handler(struct bna *bna, u32 intr_status)
-{
- u32 init_halt;
-
- if (intr_status & __HALT_STATUS_BITS) {
- init_halt = readl(bna->device.ioc.ioc_regs.ll_halt);
- init_halt &= ~__FW_INIT_HALT_P;
- writel(init_halt, bna->device.ioc.ioc_regs.ll_halt);
- }
-
- bfa_nw_ioc_error_isr(&bna->device.ioc);
-}
-
-void
-bna_mbox_handler(struct bna *bna, u32 intr_status)
-{
- if (BNA_IS_ERR_INTR(intr_status)) {
- bna_err_handler(bna, intr_status);
- return;
- }
- if (BNA_IS_MBOX_INTR(intr_status))
- bfa_nw_ioc_mbox_isr(&bna->device.ioc);
-}
-
-void
-bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe)
-{
- struct bfi_mhdr *mh;
-
- mh = (struct bfi_mhdr *)(&mbox_qe->cmd.msg[0]);
-
- mh->mtag.i2htok = htons(bna->mbox_mod.msg_ctr);
- bna->mbox_mod.msg_ctr++;
- bna->mbox_mod.msg_pending++;
- if (bna->mbox_mod.state == BNA_MBOX_FREE) {
- list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
- bfa_nw_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd);
- bna->mbox_mod.state = BNA_MBOX_POSTED;
- } else {
- list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
- }
-}
-
-static void
-bna_mbox_flush_q(struct bna *bna, struct list_head *q)
-{
- struct bna_mbox_qe *mb_qe = NULL;
- struct list_head *mb_q;
- void (*cbfn)(void *arg, int status);
- void *cbarg;
-
- mb_q = &bna->mbox_mod.posted_q;
-
- while (!list_empty(mb_q)) {
- bfa_q_deq(mb_q, &mb_qe);
- cbfn = mb_qe->cbfn;
- cbarg = mb_qe->cbarg;
- bfa_q_qe_init(mb_qe);
- bna->mbox_mod.msg_pending--;
-
- if (cbfn)
- cbfn(cbarg, BNA_CB_NOT_EXEC);
- }
-
- bna->mbox_mod.state = BNA_MBOX_FREE;
-}
-
-static void
-bna_mbox_mod_start(struct bna_mbox_mod *mbox_mod)
-{
-}
-
-static void
-bna_mbox_mod_stop(struct bna_mbox_mod *mbox_mod)
-{
- bna_mbox_flush_q(mbox_mod->bna, &mbox_mod->posted_q);
-}
-
-static void
-bna_mbox_mod_init(struct bna_mbox_mod *mbox_mod, struct bna *bna)
-{
- bfa_nw_ioc_mbox_regisr(&bna->device.ioc, BFI_MC_LL, bna_ll_isr, bna);
- mbox_mod->state = BNA_MBOX_FREE;
- mbox_mod->msg_ctr = mbox_mod->msg_pending = 0;
- INIT_LIST_HEAD(&mbox_mod->posted_q);
- mbox_mod->bna = bna;
-}
-
-static void
-bna_mbox_mod_uninit(struct bna_mbox_mod *mbox_mod)
-{
- mbox_mod->bna = NULL;
-}
-
-/**
- * LLPORT
- */
-#define call_llport_stop_cbfn(llport, status)\
-do {\
- if ((llport)->stop_cbfn)\
- (llport)->stop_cbfn(&(llport)->bna->port, status);\
- (llport)->stop_cbfn = NULL;\
-} while (0)
-
-static void bna_fw_llport_up(struct bna_llport *llport);
-static void bna_fw_cb_llport_up(void *arg, int status);
-static void bna_fw_llport_down(struct bna_llport *llport);
-static void bna_fw_cb_llport_down(void *arg, int status);
-static void bna_llport_start(struct bna_llport *llport);
-static void bna_llport_stop(struct bna_llport *llport);
-static void bna_llport_fail(struct bna_llport *llport);
-
-enum bna_llport_state {
- BNA_LLPORT_STOPPED = 1,
- BNA_LLPORT_DOWN = 2,
- BNA_LLPORT_UP_RESP_WAIT = 3,
- BNA_LLPORT_DOWN_RESP_WAIT = 4,
- BNA_LLPORT_UP = 5,
- BNA_LLPORT_LAST_RESP_WAIT = 6
-};
-
-bfa_fsm_state_decl(bna_llport, stopped, struct bna_llport,
- enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, down, struct bna_llport,
- enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, up_resp_wait, struct bna_llport,
- enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, down_resp_wait, struct bna_llport,
- enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, up, struct bna_llport,
- enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, last_resp_wait, struct bna_llport,
- enum bna_llport_event);
-
-static struct bfa_sm_table llport_sm_table[] = {
- {BFA_SM(bna_llport_sm_stopped), BNA_LLPORT_STOPPED},
- {BFA_SM(bna_llport_sm_down), BNA_LLPORT_DOWN},
- {BFA_SM(bna_llport_sm_up_resp_wait), BNA_LLPORT_UP_RESP_WAIT},
- {BFA_SM(bna_llport_sm_down_resp_wait), BNA_LLPORT_DOWN_RESP_WAIT},
- {BFA_SM(bna_llport_sm_up), BNA_LLPORT_UP},
- {BFA_SM(bna_llport_sm_last_resp_wait), BNA_LLPORT_LAST_RESP_WAIT}
-};
-
-static void
-bna_llport_sm_stopped_entry(struct bna_llport *llport)
-{
- llport->bna->port.link_cbfn((llport)->bna->bnad, BNA_LINK_DOWN);
- call_llport_stop_cbfn(llport, BNA_CB_SUCCESS);
-}
-
-static void
-bna_llport_sm_stopped(struct bna_llport *llport,
- enum bna_llport_event event)
-{
- switch (event) {
- case LLPORT_E_START:
- bfa_fsm_set_state(llport, bna_llport_sm_down);
- break;
-
- case LLPORT_E_STOP:
- call_llport_stop_cbfn(llport, BNA_CB_SUCCESS);
- break;
-
- case LLPORT_E_FAIL:
- break;
-
- case LLPORT_E_DOWN:
- /* This event is received due to Rx objects failing */
- /* No-op */
- break;
-
- case LLPORT_E_FWRESP_UP_OK:
- case LLPORT_E_FWRESP_DOWN:
- /**
- * These events are received due to flushing of mbox when
- * device fails
- */
- /* No-op */
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_llport_sm_down_entry(struct bna_llport *llport)
-{
- bnad_cb_port_link_status((llport)->bna->bnad, BNA_LINK_DOWN);
-}
-
-static void
-bna_llport_sm_down(struct bna_llport *llport,
- enum bna_llport_event event)
-{
- switch (event) {
- case LLPORT_E_STOP:
- bfa_fsm_set_state(llport, bna_llport_sm_stopped);
- break;
-
- case LLPORT_E_FAIL:
- bfa_fsm_set_state(llport, bna_llport_sm_stopped);
- break;
-
- case LLPORT_E_UP:
- bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
- bna_fw_llport_up(llport);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_llport_sm_up_resp_wait_entry(struct bna_llport *llport)
-{
- BUG_ON(!llport_can_be_up(llport));
- /**
- * NOTE: Do not call bna_fw_llport_up() here. That will over step
- * mbox due to down_resp_wait -> up_resp_wait transition on event
- * LLPORT_E_UP
- */
-}
-
-static void
-bna_llport_sm_up_resp_wait(struct bna_llport *llport,
- enum bna_llport_event event)
-{
- switch (event) {
- case LLPORT_E_STOP:
- bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
- break;
-
- case LLPORT_E_FAIL:
- bfa_fsm_set_state(llport, bna_llport_sm_stopped);
- break;
-
- case LLPORT_E_DOWN:
- bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
- break;
-
- case LLPORT_E_FWRESP_UP_OK:
- bfa_fsm_set_state(llport, bna_llport_sm_up);
- break;
-
- case LLPORT_E_FWRESP_UP_FAIL:
- bfa_fsm_set_state(llport, bna_llport_sm_down);
- break;
-
- case LLPORT_E_FWRESP_DOWN:
- /* down_resp_wait -> up_resp_wait transition on LLPORT_E_UP */
- bna_fw_llport_up(llport);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_llport_sm_down_resp_wait_entry(struct bna_llport *llport)
-{
- /**
- * NOTE: Do not call bna_fw_llport_down() here. That will over step
- * mbox due to up_resp_wait -> down_resp_wait transition on event
- * LLPORT_E_DOWN
- */
-}
-
-static void
-bna_llport_sm_down_resp_wait(struct bna_llport *llport,
- enum bna_llport_event event)
-{
- switch (event) {
- case LLPORT_E_STOP:
- bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
- break;
-
- case LLPORT_E_FAIL:
- bfa_fsm_set_state(llport, bna_llport_sm_stopped);
- break;
-
- case LLPORT_E_UP:
- bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
- break;
-
- case LLPORT_E_FWRESP_UP_OK:
- /* up_resp_wait->down_resp_wait transition on LLPORT_E_DOWN */
- bna_fw_llport_down(llport);
- break;
-
- case LLPORT_E_FWRESP_UP_FAIL:
- case LLPORT_E_FWRESP_DOWN:
- bfa_fsm_set_state(llport, bna_llport_sm_down);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_llport_sm_up_entry(struct bna_llport *llport)
-{
-}
-
-static void
-bna_llport_sm_up(struct bna_llport *llport,
- enum bna_llport_event event)
-{
- switch (event) {
- case LLPORT_E_STOP:
- bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
- bna_fw_llport_down(llport);
- break;
-
- case LLPORT_E_FAIL:
- bfa_fsm_set_state(llport, bna_llport_sm_stopped);
- break;
-
- case LLPORT_E_DOWN:
- bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
- bna_fw_llport_down(llport);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_llport_sm_last_resp_wait_entry(struct bna_llport *llport)
-{
-}
-
-static void
-bna_llport_sm_last_resp_wait(struct bna_llport *llport,
- enum bna_llport_event event)
-{
- switch (event) {
- case LLPORT_E_FAIL:
- bfa_fsm_set_state(llport, bna_llport_sm_stopped);
- break;
-
- case LLPORT_E_DOWN:
- /**
- * This event is received due to Rx objects stopping in
- * parallel to llport
- */
- /* No-op */
- break;
-
- case LLPORT_E_FWRESP_UP_OK:
- /* up_resp_wait->last_resp_wait transition on LLPORT_T_STOP */
- bna_fw_llport_down(llport);
- break;
-
- case LLPORT_E_FWRESP_UP_FAIL:
- case LLPORT_E_FWRESP_DOWN:
- bfa_fsm_set_state(llport, bna_llport_sm_stopped);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_fw_llport_admin_up(struct bna_llport *llport)
-{
- struct bfi_ll_port_admin_req ll_req;
-
- memset(&ll_req, 0, sizeof(ll_req));
- ll_req.mh.msg_class = BFI_MC_LL;
- ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
- ll_req.mh.mtag.h2i.lpu_id = 0;
-
- ll_req.up = BNA_STATUS_T_ENABLED;
-
- bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req),
- bna_fw_cb_llport_up, llport);
-
- bna_mbox_send(llport->bna, &llport->mbox_qe);
-}
-
-static void
-bna_fw_llport_up(struct bna_llport *llport)
-{
- if (llport->type == BNA_PORT_T_REGULAR)
- bna_fw_llport_admin_up(llport);
-}
-
-static void
-bna_fw_cb_llport_up(void *arg, int status)
-{
- struct bna_llport *llport = (struct bna_llport *)arg;
-
- bfa_q_qe_init(&llport->mbox_qe.qe);
- if (status == BFI_LL_CMD_FAIL) {
- if (llport->type == BNA_PORT_T_REGULAR)
- llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
- else
- llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
- bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_FAIL);
- } else
- bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_OK);
-}
-
-static void
-bna_fw_llport_admin_down(struct bna_llport *llport)
-{
- struct bfi_ll_port_admin_req ll_req;
-
- memset(&ll_req, 0, sizeof(ll_req));
- ll_req.mh.msg_class = BFI_MC_LL;
- ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
- ll_req.mh.mtag.h2i.lpu_id = 0;
-
- ll_req.up = BNA_STATUS_T_DISABLED;
-
- bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req),
- bna_fw_cb_llport_down, llport);
-
- bna_mbox_send(llport->bna, &llport->mbox_qe);
-}
-
-static void
-bna_fw_llport_down(struct bna_llport *llport)
-{
- if (llport->type == BNA_PORT_T_REGULAR)
- bna_fw_llport_admin_down(llport);
-}
-
-static void
-bna_fw_cb_llport_down(void *arg, int status)
-{
- struct bna_llport *llport = (struct bna_llport *)arg;
-
- bfa_q_qe_init(&llport->mbox_qe.qe);
- bfa_fsm_send_event(llport, LLPORT_E_FWRESP_DOWN);
-}
-
-static void
-bna_port_cb_llport_stopped(struct bna_port *port,
- enum bna_cb_status status)
-{
- bfa_wc_down(&port->chld_stop_wc);
-}
-
-static void
-bna_llport_init(struct bna_llport *llport, struct bna *bna)
-{
- llport->flags |= BNA_LLPORT_F_ADMIN_UP;
- llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
- llport->type = BNA_PORT_T_REGULAR;
- llport->bna = bna;
-
- llport->link_status = BNA_LINK_DOWN;
-
- llport->rx_started_count = 0;
-
- llport->stop_cbfn = NULL;
-
- bfa_q_qe_init(&llport->mbox_qe.qe);
-
- bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-}
-
-static void
-bna_llport_uninit(struct bna_llport *llport)
-{
- llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
- llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
-
- llport->bna = NULL;
-}
-
-static void
-bna_llport_start(struct bna_llport *llport)
-{
- bfa_fsm_send_event(llport, LLPORT_E_START);
-}
-
-static void
-bna_llport_stop(struct bna_llport *llport)
-{
- llport->stop_cbfn = bna_port_cb_llport_stopped;
-
- bfa_fsm_send_event(llport, LLPORT_E_STOP);
-}
-
-static void
-bna_llport_fail(struct bna_llport *llport)
-{
- /* Reset the physical port status to enabled */
- llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
- bfa_fsm_send_event(llport, LLPORT_E_FAIL);
-}
-
-static int
-bna_llport_state_get(struct bna_llport *llport)
-{
- return bfa_sm_to_state(llport_sm_table, llport->fsm);
-}
-
-void
-bna_llport_rx_started(struct bna_llport *llport)
-{
- llport->rx_started_count++;
-
- if (llport->rx_started_count == 1) {
-
- llport->flags |= BNA_LLPORT_F_RX_STARTED;
-
- if (llport_can_be_up(llport))
- bfa_fsm_send_event(llport, LLPORT_E_UP);
- }
-}
-
-void
-bna_llport_rx_stopped(struct bna_llport *llport)
-{
- int llport_up = llport_is_up(llport);
-
- llport->rx_started_count--;
-
- if (llport->rx_started_count == 0) {
-
- llport->flags &= ~BNA_LLPORT_F_RX_STARTED;
-
- if (llport_up)
- bfa_fsm_send_event(llport, LLPORT_E_DOWN);
- }
-}
-
-/**
- * PORT
- */
-#define bna_port_chld_start(port)\
-do {\
- enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
- BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\
- enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
- BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
- bna_llport_start(&(port)->llport);\
- bna_tx_mod_start(&(port)->bna->tx_mod, tx_type);\
- bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define bna_port_chld_stop(port)\
-do {\
- enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
- BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\
- enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
- BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
- bfa_wc_up(&(port)->chld_stop_wc);\
- bfa_wc_up(&(port)->chld_stop_wc);\
- bfa_wc_up(&(port)->chld_stop_wc);\
- bna_llport_stop(&(port)->llport);\
- bna_tx_mod_stop(&(port)->bna->tx_mod, tx_type);\
- bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define bna_port_chld_fail(port)\
-do {\
- bna_llport_fail(&(port)->llport);\
- bna_tx_mod_fail(&(port)->bna->tx_mod);\
- bna_rx_mod_fail(&(port)->bna->rx_mod);\
-} while (0)
-
-#define bna_port_rx_start(port)\
-do {\
- enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
- BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
- bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define bna_port_rx_stop(port)\
-do {\
- enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
- BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
- bfa_wc_up(&(port)->chld_stop_wc);\
- bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define call_port_stop_cbfn(port, status)\
-do {\
- if ((port)->stop_cbfn)\
- (port)->stop_cbfn((port)->stop_cbarg, status);\
- (port)->stop_cbfn = NULL;\
- (port)->stop_cbarg = NULL;\
-} while (0)
-
-#define call_port_pause_cbfn(port, status)\
-do {\
- if ((port)->pause_cbfn)\
- (port)->pause_cbfn((port)->bna->bnad, status);\
- (port)->pause_cbfn = NULL;\
-} while (0)
-
-#define call_port_mtu_cbfn(port, status)\
-do {\
- if ((port)->mtu_cbfn)\
- (port)->mtu_cbfn((port)->bna->bnad, status);\
- (port)->mtu_cbfn = NULL;\
-} while (0)
-
-static void bna_fw_pause_set(struct bna_port *port);
-static void bna_fw_cb_pause_set(void *arg, int status);
-static void bna_fw_mtu_set(struct bna_port *port);
-static void bna_fw_cb_mtu_set(void *arg, int status);
-
-enum bna_port_event {
- PORT_E_START = 1,
- PORT_E_STOP = 2,
- PORT_E_FAIL = 3,
- PORT_E_PAUSE_CFG = 4,
- PORT_E_MTU_CFG = 5,
- PORT_E_CHLD_STOPPED = 6,
- PORT_E_FWRESP_PAUSE = 7,
- PORT_E_FWRESP_MTU = 8
-};
-
-enum bna_port_state {
- BNA_PORT_STOPPED = 1,
- BNA_PORT_MTU_INIT_WAIT = 2,
- BNA_PORT_PAUSE_INIT_WAIT = 3,
- BNA_PORT_LAST_RESP_WAIT = 4,
- BNA_PORT_STARTED = 5,
- BNA_PORT_PAUSE_CFG_WAIT = 6,
- BNA_PORT_RX_STOP_WAIT = 7,
- BNA_PORT_MTU_CFG_WAIT = 8,
- BNA_PORT_CHLD_STOP_WAIT = 9
-};
-
-bfa_fsm_state_decl(bna_port, stopped, struct bna_port,
- enum bna_port_event);
-bfa_fsm_state_decl(bna_port, mtu_init_wait, struct bna_port,
- enum bna_port_event);
-bfa_fsm_state_decl(bna_port, pause_init_wait, struct bna_port,
- enum bna_port_event);
-bfa_fsm_state_decl(bna_port, last_resp_wait, struct bna_port,
- enum bna_port_event);
-bfa_fsm_state_decl(bna_port, started, struct bna_port,
- enum bna_port_event);
-bfa_fsm_state_decl(bna_port, pause_cfg_wait, struct bna_port,
- enum bna_port_event);
-bfa_fsm_state_decl(bna_port, rx_stop_wait, struct bna_port,
- enum bna_port_event);
-bfa_fsm_state_decl(bna_port, mtu_cfg_wait, struct bna_port,
- enum bna_port_event);
-bfa_fsm_state_decl(bna_port, chld_stop_wait, struct bna_port,
- enum bna_port_event);
-
-static struct bfa_sm_table port_sm_table[] = {
- {BFA_SM(bna_port_sm_stopped), BNA_PORT_STOPPED},
- {BFA_SM(bna_port_sm_mtu_init_wait), BNA_PORT_MTU_INIT_WAIT},
- {BFA_SM(bna_port_sm_pause_init_wait), BNA_PORT_PAUSE_INIT_WAIT},
- {BFA_SM(bna_port_sm_last_resp_wait), BNA_PORT_LAST_RESP_WAIT},
- {BFA_SM(bna_port_sm_started), BNA_PORT_STARTED},
- {BFA_SM(bna_port_sm_pause_cfg_wait), BNA_PORT_PAUSE_CFG_WAIT},
- {BFA_SM(bna_port_sm_rx_stop_wait), BNA_PORT_RX_STOP_WAIT},
- {BFA_SM(bna_port_sm_mtu_cfg_wait), BNA_PORT_MTU_CFG_WAIT},
- {BFA_SM(bna_port_sm_chld_stop_wait), BNA_PORT_CHLD_STOP_WAIT}
-};
-
-static void
-bna_port_sm_stopped_entry(struct bna_port *port)
-{
- call_port_pause_cbfn(port, BNA_CB_SUCCESS);
- call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
- call_port_stop_cbfn(port, BNA_CB_SUCCESS);
-}
-
-static void
-bna_port_sm_stopped(struct bna_port *port, enum bna_port_event event)
-{
- switch (event) {
- case PORT_E_START:
- bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait);
- break;
-
- case PORT_E_STOP:
- call_port_stop_cbfn(port, BNA_CB_SUCCESS);
- break;
-
- case PORT_E_FAIL:
- /* No-op */
- break;
-
- case PORT_E_PAUSE_CFG:
- call_port_pause_cbfn(port, BNA_CB_SUCCESS);
- break;
-
- case PORT_E_MTU_CFG:
- call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
- break;
-
- case PORT_E_CHLD_STOPPED:
- /**
- * This event is received due to LLPort, Tx and Rx objects
- * failing
- */
- /* No-op */
- break;
-
- case PORT_E_FWRESP_PAUSE:
- case PORT_E_FWRESP_MTU:
- /**
- * These events are received due to flushing of mbox when
- * device fails
- */
- /* No-op */
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_port_sm_mtu_init_wait_entry(struct bna_port *port)
-{
- bna_fw_mtu_set(port);
-}
-
-static void
-bna_port_sm_mtu_init_wait(struct bna_port *port, enum bna_port_event event)
-{
- switch (event) {
- case PORT_E_STOP:
- bfa_fsm_set_state(port, bna_port_sm_last_resp_wait);
- break;
-
- case PORT_E_FAIL:
- bfa_fsm_set_state(port, bna_port_sm_stopped);
- break;
-
- case PORT_E_PAUSE_CFG:
- /* No-op */
- break;
-
- case PORT_E_MTU_CFG:
- port->flags |= BNA_PORT_F_MTU_CHANGED;
- break;
-
- case PORT_E_FWRESP_MTU:
- if (port->flags & BNA_PORT_F_MTU_CHANGED) {
- port->flags &= ~BNA_PORT_F_MTU_CHANGED;
- bna_fw_mtu_set(port);
- } else {
- bfa_fsm_set_state(port, bna_port_sm_pause_init_wait);
- }
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_port_sm_pause_init_wait_entry(struct bna_port *port)
-{
- bna_fw_pause_set(port);
-}
-
-static void
-bna_port_sm_pause_init_wait(struct bna_port *port,
- enum bna_port_event event)
-{
- switch (event) {
- case PORT_E_STOP:
- bfa_fsm_set_state(port, bna_port_sm_last_resp_wait);
- break;
-
- case PORT_E_FAIL:
- bfa_fsm_set_state(port, bna_port_sm_stopped);
- break;
-
- case PORT_E_PAUSE_CFG:
- port->flags |= BNA_PORT_F_PAUSE_CHANGED;
- break;
-
- case PORT_E_MTU_CFG:
- port->flags |= BNA_PORT_F_MTU_CHANGED;
- break;
-
- case PORT_E_FWRESP_PAUSE:
- if (port->flags & BNA_PORT_F_PAUSE_CHANGED) {
- port->flags &= ~BNA_PORT_F_PAUSE_CHANGED;
- bna_fw_pause_set(port);
- } else if (port->flags & BNA_PORT_F_MTU_CHANGED) {
- port->flags &= ~BNA_PORT_F_MTU_CHANGED;
- bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait);
- } else {
- bfa_fsm_set_state(port, bna_port_sm_started);
- bna_port_chld_start(port);
- }
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_port_sm_last_resp_wait_entry(struct bna_port *port)
-{
-}
-
-static void
-bna_port_sm_last_resp_wait(struct bna_port *port,
- enum bna_port_event event)
-{
- switch (event) {
- case PORT_E_FAIL:
- case PORT_E_FWRESP_PAUSE:
- case PORT_E_FWRESP_MTU:
- bfa_fsm_set_state(port, bna_port_sm_stopped);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_port_sm_started_entry(struct bna_port *port)
-{
- /**
- * NOTE: Do not call bna_port_chld_start() here, since it will be
- * inadvertently called during pause_cfg_wait->started transition
- * as well
- */
- call_port_pause_cbfn(port, BNA_CB_SUCCESS);
- call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
-}
-
-static void
-bna_port_sm_started(struct bna_port *port,
- enum bna_port_event event)
-{
- switch (event) {
- case PORT_E_STOP:
- bfa_fsm_set_state(port, bna_port_sm_chld_stop_wait);
- break;
-
- case PORT_E_FAIL:
- bfa_fsm_set_state(port, bna_port_sm_stopped);
- bna_port_chld_fail(port);
- break;
-
- case PORT_E_PAUSE_CFG:
- bfa_fsm_set_state(port, bna_port_sm_pause_cfg_wait);
- break;
-
- case PORT_E_MTU_CFG:
- bfa_fsm_set_state(port, bna_port_sm_rx_stop_wait);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_port_sm_pause_cfg_wait_entry(struct bna_port *port)
-{
- bna_fw_pause_set(port);
-}
-
-static void
-bna_port_sm_pause_cfg_wait(struct bna_port *port,
- enum bna_port_event event)
-{
- switch (event) {
- case PORT_E_FAIL:
- bfa_fsm_set_state(port, bna_port_sm_stopped);
- bna_port_chld_fail(port);
- break;
-
- case PORT_E_FWRESP_PAUSE:
- bfa_fsm_set_state(port, bna_port_sm_started);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_port_sm_rx_stop_wait_entry(struct bna_port *port)
-{
- bna_port_rx_stop(port);
-}
-
-static void
-bna_port_sm_rx_stop_wait(struct bna_port *port,
- enum bna_port_event event)
-{
- switch (event) {
- case PORT_E_FAIL:
- bfa_fsm_set_state(port, bna_port_sm_stopped);
- bna_port_chld_fail(port);
- break;
-
- case PORT_E_CHLD_STOPPED:
- bfa_fsm_set_state(port, bna_port_sm_mtu_cfg_wait);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_port_sm_mtu_cfg_wait_entry(struct bna_port *port)
-{
- bna_fw_mtu_set(port);
-}
-
-static void
-bna_port_sm_mtu_cfg_wait(struct bna_port *port, enum bna_port_event event)
-{
- switch (event) {
- case PORT_E_FAIL:
- bfa_fsm_set_state(port, bna_port_sm_stopped);
- bna_port_chld_fail(port);
- break;
-
- case PORT_E_FWRESP_MTU:
- bfa_fsm_set_state(port, bna_port_sm_started);
- bna_port_rx_start(port);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_port_sm_chld_stop_wait_entry(struct bna_port *port)
-{
- bna_port_chld_stop(port);
-}
-
-static void
-bna_port_sm_chld_stop_wait(struct bna_port *port,
- enum bna_port_event event)
-{
- switch (event) {
- case PORT_E_FAIL:
- bfa_fsm_set_state(port, bna_port_sm_stopped);
- bna_port_chld_fail(port);
- break;
-
- case PORT_E_CHLD_STOPPED:
- bfa_fsm_set_state(port, bna_port_sm_stopped);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_fw_pause_set(struct bna_port *port)
-{
- struct bfi_ll_set_pause_req ll_req;
-
- memset(&ll_req, 0, sizeof(ll_req));
- ll_req.mh.msg_class = BFI_MC_LL;
- ll_req.mh.msg_id = BFI_LL_H2I_SET_PAUSE_REQ;
- ll_req.mh.mtag.h2i.lpu_id = 0;
-
- ll_req.tx_pause = port->pause_config.tx_pause;
- ll_req.rx_pause = port->pause_config.rx_pause;
-
- bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req),
- bna_fw_cb_pause_set, port);
-
- bna_mbox_send(port->bna, &port->mbox_qe);
-}
-
-static void
-bna_fw_cb_pause_set(void *arg, int status)
-{
- struct bna_port *port = (struct bna_port *)arg;
-
- bfa_q_qe_init(&port->mbox_qe.qe);
- bfa_fsm_send_event(port, PORT_E_FWRESP_PAUSE);
-}
-
-void
-bna_fw_mtu_set(struct bna_port *port)
-{
- struct bfi_ll_mtu_info_req ll_req;
-
- bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_MTU_INFO_REQ, 0);
- ll_req.mtu = htons((u16)port->mtu);
-
- bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req),
- bna_fw_cb_mtu_set, port);
- bna_mbox_send(port->bna, &port->mbox_qe);
-}
-
-void
-bna_fw_cb_mtu_set(void *arg, int status)
-{
- struct bna_port *port = (struct bna_port *)arg;
-
- bfa_q_qe_init(&port->mbox_qe.qe);
- bfa_fsm_send_event(port, PORT_E_FWRESP_MTU);
-}
-
-static void
-bna_port_cb_chld_stopped(void *arg)
-{
- struct bna_port *port = (struct bna_port *)arg;
-
- bfa_fsm_send_event(port, PORT_E_CHLD_STOPPED);
-}
-
-static void
-bna_port_init(struct bna_port *port, struct bna *bna)
-{
- port->bna = bna;
- port->flags = 0;
- port->mtu = 0;
- port->type = BNA_PORT_T_REGULAR;
-
- port->link_cbfn = bnad_cb_port_link_status;
-
- port->chld_stop_wc.wc_resume = bna_port_cb_chld_stopped;
- port->chld_stop_wc.wc_cbarg = port;
- port->chld_stop_wc.wc_count = 0;
-
- port->stop_cbfn = NULL;
- port->stop_cbarg = NULL;
-
- port->pause_cbfn = NULL;
-
- port->mtu_cbfn = NULL;
-
- bfa_q_qe_init(&port->mbox_qe.qe);
-
- bfa_fsm_set_state(port, bna_port_sm_stopped);
-
- bna_llport_init(&port->llport, bna);
-}
-
-static void
-bna_port_uninit(struct bna_port *port)
-{
- bna_llport_uninit(&port->llport);
-
- port->flags = 0;
-
- port->bna = NULL;
-}
-
-static int
-bna_port_state_get(struct bna_port *port)
-{
- return bfa_sm_to_state(port_sm_table, port->fsm);
-}
-
-static void
-bna_port_start(struct bna_port *port)
-{
- port->flags |= BNA_PORT_F_DEVICE_READY;
- if (port->flags & BNA_PORT_F_ENABLED)
- bfa_fsm_send_event(port, PORT_E_START);
-}
-
-static void
-bna_port_stop(struct bna_port *port)
-{
- port->stop_cbfn = bna_device_cb_port_stopped;
- port->stop_cbarg = &port->bna->device;
-
- port->flags &= ~BNA_PORT_F_DEVICE_READY;
- bfa_fsm_send_event(port, PORT_E_STOP);
-}
-
-static void
-bna_port_fail(struct bna_port *port)
-{
- port->flags &= ~BNA_PORT_F_DEVICE_READY;
- bfa_fsm_send_event(port, PORT_E_FAIL);
-}
-
-void
-bna_port_cb_tx_stopped(struct bna_port *port, enum bna_cb_status status)
-{
- bfa_wc_down(&port->chld_stop_wc);
-}
-
-void
-bna_port_cb_rx_stopped(struct bna_port *port, enum bna_cb_status status)
-{
- bfa_wc_down(&port->chld_stop_wc);
-}
-
-int
-bna_port_mtu_get(struct bna_port *port)
-{
- return port->mtu;
-}
-
-void
-bna_port_enable(struct bna_port *port)
-{
- if (port->fsm != (bfa_sm_t)bna_port_sm_stopped)
- return;
-
- port->flags |= BNA_PORT_F_ENABLED;
-
- if (port->flags & BNA_PORT_F_DEVICE_READY)
- bfa_fsm_send_event(port, PORT_E_START);
-}
-
-void
-bna_port_disable(struct bna_port *port, enum bna_cleanup_type type,
- void (*cbfn)(void *, enum bna_cb_status))
-{
- if (type == BNA_SOFT_CLEANUP) {
- (*cbfn)(port->bna->bnad, BNA_CB_SUCCESS);
- return;
- }
-
- port->stop_cbfn = cbfn;
- port->stop_cbarg = port->bna->bnad;
-
- port->flags &= ~BNA_PORT_F_ENABLED;
-
- bfa_fsm_send_event(port, PORT_E_STOP);
-}
-
-void
-bna_port_pause_config(struct bna_port *port,
- struct bna_pause_config *pause_config,
- void (*cbfn)(struct bnad *, enum bna_cb_status))
-{
- port->pause_config = *pause_config;
-
- port->pause_cbfn = cbfn;
-
- bfa_fsm_send_event(port, PORT_E_PAUSE_CFG);
-}
-
-void
-bna_port_mtu_set(struct bna_port *port, int mtu,
- void (*cbfn)(struct bnad *, enum bna_cb_status))
-{
- port->mtu = mtu;
-
- port->mtu_cbfn = cbfn;
-
- bfa_fsm_send_event(port, PORT_E_MTU_CFG);
-}
-
-void
-bna_port_mac_get(struct bna_port *port, mac_t *mac)
-{
- *mac = bfa_nw_ioc_get_mac(&port->bna->device.ioc);
-}
-
-/**
- * DEVICE
- */
-#define enable_mbox_intr(_device)\
-do {\
- u32 intr_status;\
- bna_intr_status_get((_device)->bna, intr_status);\
- bnad_cb_device_enable_mbox_intr((_device)->bna->bnad);\
- bna_mbox_intr_enable((_device)->bna);\
-} while (0)
-
-#define disable_mbox_intr(_device)\
-do {\
- bna_mbox_intr_disable((_device)->bna);\
- bnad_cb_device_disable_mbox_intr((_device)->bna->bnad);\
-} while (0)
-
-static const struct bna_chip_regs_offset reg_offset[] =
-{{HOST_PAGE_NUM_FN0, HOSTFN0_INT_STATUS,
- HOSTFN0_INT_MASK, HOST_MSIX_ERR_INDEX_FN0},
-{HOST_PAGE_NUM_FN1, HOSTFN1_INT_STATUS,
- HOSTFN1_INT_MASK, HOST_MSIX_ERR_INDEX_FN1},
-{HOST_PAGE_NUM_FN2, HOSTFN2_INT_STATUS,
- HOSTFN2_INT_MASK, HOST_MSIX_ERR_INDEX_FN2},
-{HOST_PAGE_NUM_FN3, HOSTFN3_INT_STATUS,
- HOSTFN3_INT_MASK, HOST_MSIX_ERR_INDEX_FN3},
-};
-
-enum bna_device_event {
- DEVICE_E_ENABLE = 1,
- DEVICE_E_DISABLE = 2,
- DEVICE_E_IOC_READY = 3,
- DEVICE_E_IOC_FAILED = 4,
- DEVICE_E_IOC_DISABLED = 5,
- DEVICE_E_IOC_RESET = 6,
- DEVICE_E_PORT_STOPPED = 7,
-};
-
-enum bna_device_state {
- BNA_DEVICE_STOPPED = 1,
- BNA_DEVICE_IOC_READY_WAIT = 2,
- BNA_DEVICE_READY = 3,
- BNA_DEVICE_PORT_STOP_WAIT = 4,
- BNA_DEVICE_IOC_DISABLE_WAIT = 5,
- BNA_DEVICE_FAILED = 6
-};
-
-bfa_fsm_state_decl(bna_device, stopped, struct bna_device,
- enum bna_device_event);
-bfa_fsm_state_decl(bna_device, ioc_ready_wait, struct bna_device,
- enum bna_device_event);
-bfa_fsm_state_decl(bna_device, ready, struct bna_device,
- enum bna_device_event);
-bfa_fsm_state_decl(bna_device, port_stop_wait, struct bna_device,
- enum bna_device_event);
-bfa_fsm_state_decl(bna_device, ioc_disable_wait, struct bna_device,
- enum bna_device_event);
-bfa_fsm_state_decl(bna_device, failed, struct bna_device,
- enum bna_device_event);
-
-static struct bfa_sm_table device_sm_table[] = {
- {BFA_SM(bna_device_sm_stopped), BNA_DEVICE_STOPPED},
- {BFA_SM(bna_device_sm_ioc_ready_wait), BNA_DEVICE_IOC_READY_WAIT},
- {BFA_SM(bna_device_sm_ready), BNA_DEVICE_READY},
- {BFA_SM(bna_device_sm_port_stop_wait), BNA_DEVICE_PORT_STOP_WAIT},
- {BFA_SM(bna_device_sm_ioc_disable_wait), BNA_DEVICE_IOC_DISABLE_WAIT},
- {BFA_SM(bna_device_sm_failed), BNA_DEVICE_FAILED},
-};
-
-static void
-bna_device_sm_stopped_entry(struct bna_device *device)
-{
- if (device->stop_cbfn)
- device->stop_cbfn(device->stop_cbarg, BNA_CB_SUCCESS);
-
- device->stop_cbfn = NULL;
- device->stop_cbarg = NULL;
-}
-
-static void
-bna_device_sm_stopped(struct bna_device *device,
- enum bna_device_event event)
-{
- switch (event) {
- case DEVICE_E_ENABLE:
- if (device->intr_type == BNA_INTR_T_MSIX)
- bna_mbox_msix_idx_set(device);
- bfa_nw_ioc_enable(&device->ioc);
- bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait);
- break;
-
- case DEVICE_E_DISABLE:
- bfa_fsm_set_state(device, bna_device_sm_stopped);
- break;
-
- case DEVICE_E_IOC_RESET:
- enable_mbox_intr(device);
- break;
-
- case DEVICE_E_IOC_FAILED:
- bfa_fsm_set_state(device, bna_device_sm_failed);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_device_sm_ioc_ready_wait_entry(struct bna_device *device)
-{
- /**
- * Do not call bfa_ioc_enable() here. It must be called in the
- * previous state due to failed -> ioc_ready_wait transition.
- */
-}
-
-static void
-bna_device_sm_ioc_ready_wait(struct bna_device *device,
- enum bna_device_event event)
-{
- switch (event) {
- case DEVICE_E_DISABLE:
- if (device->ready_cbfn)
- device->ready_cbfn(device->ready_cbarg,
- BNA_CB_INTERRUPT);
- device->ready_cbfn = NULL;
- device->ready_cbarg = NULL;
- bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
- break;
-
- case DEVICE_E_IOC_READY:
- bfa_fsm_set_state(device, bna_device_sm_ready);
- break;
-
- case DEVICE_E_IOC_FAILED:
- bfa_fsm_set_state(device, bna_device_sm_failed);
- break;
-
- case DEVICE_E_IOC_RESET:
- enable_mbox_intr(device);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_device_sm_ready_entry(struct bna_device *device)
-{
- bna_mbox_mod_start(&device->bna->mbox_mod);
- bna_port_start(&device->bna->port);
-
- if (device->ready_cbfn)
- device->ready_cbfn(device->ready_cbarg,
- BNA_CB_SUCCESS);
- device->ready_cbfn = NULL;
- device->ready_cbarg = NULL;
-}
-
-static void
-bna_device_sm_ready(struct bna_device *device, enum bna_device_event event)
-{
- switch (event) {
- case DEVICE_E_DISABLE:
- bfa_fsm_set_state(device, bna_device_sm_port_stop_wait);
- break;
-
- case DEVICE_E_IOC_FAILED:
- bfa_fsm_set_state(device, bna_device_sm_failed);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_device_sm_port_stop_wait_entry(struct bna_device *device)
-{
- bna_port_stop(&device->bna->port);
-}
-
-static void
-bna_device_sm_port_stop_wait(struct bna_device *device,
- enum bna_device_event event)
-{
- switch (event) {
- case DEVICE_E_PORT_STOPPED:
- bna_mbox_mod_stop(&device->bna->mbox_mod);
- bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
- break;
-
- case DEVICE_E_IOC_FAILED:
- disable_mbox_intr(device);
- bna_port_fail(&device->bna->port);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_device_sm_ioc_disable_wait_entry(struct bna_device *device)
-{
- bfa_nw_ioc_disable(&device->ioc);
-}
-
-static void
-bna_device_sm_ioc_disable_wait(struct bna_device *device,
- enum bna_device_event event)
-{
- switch (event) {
- case DEVICE_E_IOC_DISABLED:
- disable_mbox_intr(device);
- bfa_fsm_set_state(device, bna_device_sm_stopped);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_device_sm_failed_entry(struct bna_device *device)
-{
- disable_mbox_intr(device);
- bna_port_fail(&device->bna->port);
- bna_mbox_mod_stop(&device->bna->mbox_mod);
-
- if (device->ready_cbfn)
- device->ready_cbfn(device->ready_cbarg,
- BNA_CB_FAIL);
- device->ready_cbfn = NULL;
- device->ready_cbarg = NULL;
-}
-
-static void
-bna_device_sm_failed(struct bna_device *device,
- enum bna_device_event event)
-{
- switch (event) {
- case DEVICE_E_DISABLE:
- bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
- break;
-
- case DEVICE_E_IOC_RESET:
- enable_mbox_intr(device);
- bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-/* IOC callback functions */
-
-static void
-bna_device_cb_iocll_ready(void *dev, enum bfa_status error)
-{
- struct bna_device *device = (struct bna_device *)dev;
-
- if (error)
- bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED);
- else
- bfa_fsm_send_event(device, DEVICE_E_IOC_READY);
-}
-
-static void
-bna_device_cb_iocll_disabled(void *dev)
-{
- struct bna_device *device = (struct bna_device *)dev;
-
- bfa_fsm_send_event(device, DEVICE_E_IOC_DISABLED);
-}
-
-static void
-bna_device_cb_iocll_failed(void *dev)
-{
- struct bna_device *device = (struct bna_device *)dev;
-
- bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED);
-}
-
-static void
-bna_device_cb_iocll_reset(void *dev)
-{
- struct bna_device *device = (struct bna_device *)dev;
-
- bfa_fsm_send_event(device, DEVICE_E_IOC_RESET);
-}
-
-static struct bfa_ioc_cbfn bfa_iocll_cbfn = {
- bna_device_cb_iocll_ready,
- bna_device_cb_iocll_disabled,
- bna_device_cb_iocll_failed,
- bna_device_cb_iocll_reset
-};
-
-/* device */
-static void
-bna_adv_device_init(struct bna_device *device, struct bna *bna,
- struct bna_res_info *res_info)
-{
- u8 *kva;
- u64 dma;
-
- device->bna = bna;
-
- kva = res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mdl[0].kva;
-
- /**
- * Attach common modules (Diag, SFP, CEE, Port) and claim respective
- * DMA memory.
- */
- BNA_GET_DMA_ADDR(
- &res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].dma, dma);
- kva = res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].kva;
-
- bfa_nw_cee_attach(&bna->cee, &device->ioc, bna);
- bfa_nw_cee_mem_claim(&bna->cee, kva, dma);
- kva += bfa_nw_cee_meminfo();
- dma += bfa_nw_cee_meminfo();
-
-}
-
-static void
-bna_device_init(struct bna_device *device, struct bna *bna,
- struct bna_res_info *res_info)
-{
- u64 dma;
-
- device->bna = bna;
-
- /**
- * Attach IOC and claim:
- * 1. DMA memory for IOC attributes
- * 2. Kernel memory for FW trace
- */
- bfa_nw_ioc_attach(&device->ioc, device, &bfa_iocll_cbfn);
- bfa_nw_ioc_pci_init(&device->ioc, &bna->pcidev, BFI_MC_LL);
-
- BNA_GET_DMA_ADDR(
- &res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].dma, dma);
- bfa_nw_ioc_mem_claim(&device->ioc,
- res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].kva,
- dma);
-
- bna_adv_device_init(device, bna, res_info);
- /*
- * Initialize mbox_mod only after IOC, so that mbox handler
- * registration goes through
- */
- device->intr_type =
- res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type;
- device->vector =
- res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.idl[0].vector;
- bna_mbox_mod_init(&bna->mbox_mod, bna);
-
- device->ready_cbfn = device->stop_cbfn = NULL;
- device->ready_cbarg = device->stop_cbarg = NULL;
-
- bfa_fsm_set_state(device, bna_device_sm_stopped);
-}
-
-static void
-bna_device_uninit(struct bna_device *device)
-{
- bna_mbox_mod_uninit(&device->bna->mbox_mod);
-
- bfa_nw_ioc_detach(&device->ioc);
-
- device->bna = NULL;
-}
-
-static void
-bna_device_cb_port_stopped(void *arg, enum bna_cb_status status)
-{
- struct bna_device *device = (struct bna_device *)arg;
-
- bfa_fsm_send_event(device, DEVICE_E_PORT_STOPPED);
-}
-
-static int
-bna_device_status_get(struct bna_device *device)
-{
- return device->fsm == (bfa_fsm_t)bna_device_sm_ready;
-}
-
-void
-bna_device_enable(struct bna_device *device)
-{
- if (device->fsm != (bfa_fsm_t)bna_device_sm_stopped) {
- bnad_cb_device_enabled(device->bna->bnad, BNA_CB_BUSY);
- return;
- }
-
- device->ready_cbfn = bnad_cb_device_enabled;
- device->ready_cbarg = device->bna->bnad;
-
- bfa_fsm_send_event(device, DEVICE_E_ENABLE);
-}
-
-void
-bna_device_disable(struct bna_device *device, enum bna_cleanup_type type)
-{
- if (type == BNA_SOFT_CLEANUP) {
- bnad_cb_device_disabled(device->bna->bnad, BNA_CB_SUCCESS);
- return;
- }
-
- device->stop_cbfn = bnad_cb_device_disabled;
- device->stop_cbarg = device->bna->bnad;
-
- bfa_fsm_send_event(device, DEVICE_E_DISABLE);
-}
-
-static int
-bna_device_state_get(struct bna_device *device)
-{
- return bfa_sm_to_state(device_sm_table, device->fsm);
-}
-
-const u32 bna_napi_dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX] = {
- {12, 12},
- {6, 10},
- {5, 10},
- {4, 8},
- {3, 6},
- {3, 6},
- {2, 4},
- {1, 2},
-};
-
-/* utils */
-
-static void
-bna_adv_res_req(struct bna_res_info *res_info)
-{
- /* DMA memory for COMMON_MODULE */
- res_info[BNA_RES_MEM_T_COM].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
- res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN(
- bfa_nw_cee_meminfo(), PAGE_SIZE);
-
- /* Virtual memory for retreiving fw_trc */
- res_info[BNA_RES_MEM_T_FWTRC].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.num = 0;
- res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.len = 0;
-
- /* DMA memory for retreiving stats */
- res_info[BNA_RES_MEM_T_STATS].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
- res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.len =
- ALIGN(BFI_HW_STATS_SIZE, PAGE_SIZE);
-
- /* Virtual memory for soft stats */
- res_info[BNA_RES_MEM_T_SWSTATS].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.len =
- sizeof(struct bna_sw_stats);
-}
-
-static void
-bna_sw_stats_get(struct bna *bna, struct bna_sw_stats *sw_stats)
-{
- struct bna_tx *tx;
- struct bna_txq *txq;
- struct bna_rx *rx;
- struct bna_rxp *rxp;
- struct list_head *qe;
- struct list_head *txq_qe;
- struct list_head *rxp_qe;
- struct list_head *mac_qe;
- int i;
-
- sw_stats->device_state = bna_device_state_get(&bna->device);
- sw_stats->port_state = bna_port_state_get(&bna->port);
- sw_stats->port_flags = bna->port.flags;
- sw_stats->llport_state = bna_llport_state_get(&bna->port.llport);
- sw_stats->priority = bna->port.priority;
-
- i = 0;
- list_for_each(qe, &bna->tx_mod.tx_active_q) {
- tx = (struct bna_tx *)qe;
- sw_stats->tx_stats[i].tx_state = bna_tx_state_get(tx);
- sw_stats->tx_stats[i].tx_flags = tx->flags;
-
- sw_stats->tx_stats[i].num_txqs = 0;
- sw_stats->tx_stats[i].txq_bmap[0] = 0;
- sw_stats->tx_stats[i].txq_bmap[1] = 0;
- list_for_each(txq_qe, &tx->txq_q) {
- txq = (struct bna_txq *)txq_qe;
- if (txq->txq_id < 32)
- sw_stats->tx_stats[i].txq_bmap[0] |=
- ((u32)1 << txq->txq_id);
- else
- sw_stats->tx_stats[i].txq_bmap[1] |=
- ((u32)
- 1 << (txq->txq_id - 32));
- sw_stats->tx_stats[i].num_txqs++;
- }
-
- sw_stats->tx_stats[i].txf_id = tx->txf.txf_id;
-
- i++;
- }
- sw_stats->num_active_tx = i;
-
- i = 0;
- list_for_each(qe, &bna->rx_mod.rx_active_q) {
- rx = (struct bna_rx *)qe;
- sw_stats->rx_stats[i].rx_state = bna_rx_state_get(rx);
- sw_stats->rx_stats[i].rx_flags = rx->rx_flags;
-
- sw_stats->rx_stats[i].num_rxps = 0;
- sw_stats->rx_stats[i].num_rxqs = 0;
- sw_stats->rx_stats[i].rxq_bmap[0] = 0;
- sw_stats->rx_stats[i].rxq_bmap[1] = 0;
- sw_stats->rx_stats[i].cq_bmap[0] = 0;
- sw_stats->rx_stats[i].cq_bmap[1] = 0;
- list_for_each(rxp_qe, &rx->rxp_q) {
- rxp = (struct bna_rxp *)rxp_qe;
-
- sw_stats->rx_stats[i].num_rxqs += 1;
-
- if (rxp->type == BNA_RXP_SINGLE) {
- if (rxp->rxq.single.only->rxq_id < 32) {
- sw_stats->rx_stats[i].rxq_bmap[0] |=
- ((u32)1 <<
- rxp->rxq.single.only->rxq_id);
- } else {
- sw_stats->rx_stats[i].rxq_bmap[1] |=
- ((u32)1 <<
- (rxp->rxq.single.only->rxq_id - 32));
- }
- } else {
- if (rxp->rxq.slr.large->rxq_id < 32) {
- sw_stats->rx_stats[i].rxq_bmap[0] |=
- ((u32)1 <<
- rxp->rxq.slr.large->rxq_id);
- } else {
- sw_stats->rx_stats[i].rxq_bmap[1] |=
- ((u32)1 <<
- (rxp->rxq.slr.large->rxq_id - 32));
- }
-
- if (rxp->rxq.slr.small->rxq_id < 32) {
- sw_stats->rx_stats[i].rxq_bmap[0] |=
- ((u32)1 <<
- rxp->rxq.slr.small->rxq_id);
- } else {
- sw_stats->rx_stats[i].rxq_bmap[1] |=
- ((u32)1 <<
- (rxp->rxq.slr.small->rxq_id - 32));
- }
- sw_stats->rx_stats[i].num_rxqs += 1;
- }
-
- if (rxp->cq.cq_id < 32)
- sw_stats->rx_stats[i].cq_bmap[0] |=
- (1 << rxp->cq.cq_id);
- else
- sw_stats->rx_stats[i].cq_bmap[1] |=
- (1 << (rxp->cq.cq_id - 32));
-
- sw_stats->rx_stats[i].num_rxps++;
- }
-
- sw_stats->rx_stats[i].rxf_id = rx->rxf.rxf_id;
- sw_stats->rx_stats[i].rxf_state = bna_rxf_state_get(&rx->rxf);
- sw_stats->rx_stats[i].rxf_oper_state = rx->rxf.rxf_oper_state;
-
- sw_stats->rx_stats[i].num_active_ucast = 0;
- if (rx->rxf.ucast_active_mac)
- sw_stats->rx_stats[i].num_active_ucast++;
- list_for_each(mac_qe, &rx->rxf.ucast_active_q)
- sw_stats->rx_stats[i].num_active_ucast++;
-
- sw_stats->rx_stats[i].num_active_mcast = 0;
- list_for_each(mac_qe, &rx->rxf.mcast_active_q)
- sw_stats->rx_stats[i].num_active_mcast++;
-
- sw_stats->rx_stats[i].rxmode_active = rx->rxf.rxmode_active;
- sw_stats->rx_stats[i].vlan_filter_status =
- rx->rxf.vlan_filter_status;
- memcpy(sw_stats->rx_stats[i].vlan_filter_table,
- rx->rxf.vlan_filter_table,
- sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32));
-
- sw_stats->rx_stats[i].rss_status = rx->rxf.rss_status;
- sw_stats->rx_stats[i].hds_status = rx->rxf.hds_status;
-
- i++;
- }
- sw_stats->num_active_rx = i;
-}
-
-static void
-bna_fw_cb_stats_get(void *arg, int status)
-{
- struct bna *bna = (struct bna *)arg;
- u64 *p_stats;
- int i, count;
- int rxf_count, txf_count;
- u64 rxf_bmap, txf_bmap;
-
- bfa_q_qe_init(&bna->mbox_qe.qe);
-
- if (status == 0) {
- p_stats = (u64 *)bna->stats.hw_stats;
- count = sizeof(struct bfi_ll_stats) / sizeof(u64);
- for (i = 0; i < count; i++)
- p_stats[i] = cpu_to_be64(p_stats[i]);
-
- rxf_count = 0;
- rxf_bmap = (u64)bna->stats.rxf_bmap[0] |
- ((u64)bna->stats.rxf_bmap[1] << 32);
- for (i = 0; i < BFI_LL_RXF_ID_MAX; i++)
- if (rxf_bmap & ((u64)1 << i))
- rxf_count++;
-
- txf_count = 0;
- txf_bmap = (u64)bna->stats.txf_bmap[0] |
- ((u64)bna->stats.txf_bmap[1] << 32);
- for (i = 0; i < BFI_LL_TXF_ID_MAX; i++)
- if (txf_bmap & ((u64)1 << i))
- txf_count++;
-
- p_stats = (u64 *)&bna->stats.hw_stats->rxf_stats[0] +
- ((rxf_count * sizeof(struct bfi_ll_stats_rxf) +
- txf_count * sizeof(struct bfi_ll_stats_txf))/
- sizeof(u64));
-
- /* Populate the TXF stats from the firmware DMAed copy */
- for (i = (BFI_LL_TXF_ID_MAX - 1); i >= 0; i--)
- if (txf_bmap & ((u64)1 << i)) {
- p_stats -= sizeof(struct bfi_ll_stats_txf)/
- sizeof(u64);
- memcpy(&bna->stats.hw_stats->txf_stats[i],
- p_stats,
- sizeof(struct bfi_ll_stats_txf));
- }
-
- /* Populate the RXF stats from the firmware DMAed copy */
- for (i = (BFI_LL_RXF_ID_MAX - 1); i >= 0; i--)
- if (rxf_bmap & ((u64)1 << i)) {
- p_stats -= sizeof(struct bfi_ll_stats_rxf)/
- sizeof(u64);
- memcpy(&bna->stats.hw_stats->rxf_stats[i],
- p_stats,
- sizeof(struct bfi_ll_stats_rxf));
- }
-
- bna_sw_stats_get(bna, bna->stats.sw_stats);
- bnad_cb_stats_get(bna->bnad, BNA_CB_SUCCESS, &bna->stats);
- } else
- bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
-}
-
-static void
-bna_fw_stats_get(struct bna *bna)
-{
- struct bfi_ll_stats_req ll_req;
-
- bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_GET_REQ, 0);
- ll_req.stats_mask = htons(BFI_LL_STATS_ALL);
-
- ll_req.rxf_id_mask[0] = htonl(bna->rx_mod.rxf_bmap[0]);
- ll_req.rxf_id_mask[1] = htonl(bna->rx_mod.rxf_bmap[1]);
- ll_req.txf_id_mask[0] = htonl(bna->tx_mod.txf_bmap[0]);
- ll_req.txf_id_mask[1] = htonl(bna->tx_mod.txf_bmap[1]);
-
- ll_req.host_buffer.a32.addr_hi = bna->hw_stats_dma.msb;
- ll_req.host_buffer.a32.addr_lo = bna->hw_stats_dma.lsb;
-
- bna_mbox_qe_fill(&bna->mbox_qe, &ll_req, sizeof(ll_req),
- bna_fw_cb_stats_get, bna);
- bna_mbox_send(bna, &bna->mbox_qe);
-
- bna->stats.rxf_bmap[0] = bna->rx_mod.rxf_bmap[0];
- bna->stats.rxf_bmap[1] = bna->rx_mod.rxf_bmap[1];
- bna->stats.txf_bmap[0] = bna->tx_mod.txf_bmap[0];
- bna->stats.txf_bmap[1] = bna->tx_mod.txf_bmap[1];
-}
-
-void
-bna_stats_get(struct bna *bna)
-{
- if (bna_device_status_get(&bna->device))
- bna_fw_stats_get(bna);
- else
- bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
-}
-
-/* IB */
-static void
-bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo)
-{
- ib->ib_config.coalescing_timeo = coalescing_timeo;
-
- if (ib->start_count)
- ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
- (u32)ib->ib_config.coalescing_timeo, 0);
-}
-
-/* RxF */
-void
-bna_rxf_adv_init(struct bna_rxf *rxf,
- struct bna_rx *rx,
- struct bna_rx_config *q_config)
-{
- switch (q_config->rxp_type) {
- case BNA_RXP_SINGLE:
- /* No-op */
- break;
- case BNA_RXP_SLR:
- rxf->ctrl_flags |= BNA_RXF_CF_SM_LG_RXQ;
- break;
- case BNA_RXP_HDS:
- rxf->hds_cfg.hdr_type = q_config->hds_config.hdr_type;
- rxf->hds_cfg.header_size =
- q_config->hds_config.header_size;
- rxf->forced_offset = 0;
- break;
- default:
- break;
- }
-
- if (q_config->rss_status == BNA_STATUS_T_ENABLED) {
- rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE;
- rxf->rss_cfg.hash_type = q_config->rss_config.hash_type;
- rxf->rss_cfg.hash_mask = q_config->rss_config.hash_mask;
- memcpy(&rxf->rss_cfg.toeplitz_hash_key[0],
- &q_config->rss_config.toeplitz_hash_key[0],
- sizeof(rxf->rss_cfg.toeplitz_hash_key));
- }
-}
-
-static void
-rxf_fltr_mbox_cmd(struct bna_rxf *rxf, u8 cmd, enum bna_status status)
-{
- struct bfi_ll_rxf_req req;
-
- bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0);
-
- req.rxf_id = rxf->rxf_id;
- req.enable = status;
-
- bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req),
- rxf_cb_cam_fltr_mbox_cmd, rxf);
-
- bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-int
-rxf_process_packet_filter_ucast(struct bna_rxf *rxf)
-{
- struct bna_mac *mac = NULL;
- struct list_head *qe;
-
- /* Add additional MAC entries */
- if (!list_empty(&rxf->ucast_pending_add_q)) {
- bfa_q_deq(&rxf->ucast_pending_add_q, &qe);
- bfa_q_qe_init(qe);
- mac = (struct bna_mac *)qe;
- rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_ADD_REQ, mac);
- list_add_tail(&mac->qe, &rxf->ucast_active_q);
- return 1;
- }
-
- /* Delete MAC addresses previousely added */
- if (!list_empty(&rxf->ucast_pending_del_q)) {
- bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
- bfa_q_qe_init(qe);
- mac = (struct bna_mac *)qe;
- rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
- bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
- return 1;
- }
-
- return 0;
-}
-
-int
-rxf_process_packet_filter_promisc(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
-
- /* Enable/disable promiscuous mode */
- if (is_promisc_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* move promisc configuration from pending -> active */
- promisc_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active |= BNA_RXMODE_PROMISC;
-
- /* Disable VLAN filter to allow all VLANs */
- __rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED);
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
- BNA_STATUS_T_ENABLED);
- return 1;
- } else if (is_promisc_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* move promisc configuration from pending -> active */
- promisc_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
- bna->rxf_promisc_id = BFI_MAX_RXF;
-
- /* Revert VLAN filter */
- __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
- BNA_STATUS_T_DISABLED);
- return 1;
- }
-
- return 0;
-}
-
-int
-rxf_process_packet_filter_allmulti(struct bna_rxf *rxf)
-{
- /* Enable/disable allmulti mode */
- if (is_allmulti_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* move allmulti configuration from pending -> active */
- allmulti_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active |= BNA_RXMODE_ALLMULTI;
-
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
- BNA_STATUS_T_ENABLED);
- return 1;
- } else if (is_allmulti_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* move allmulti configuration from pending -> active */
- allmulti_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
- BNA_STATUS_T_DISABLED);
- return 1;
- }
-
- return 0;
-}
-
-int
-rxf_clear_packet_filter_ucast(struct bna_rxf *rxf)
-{
- struct bna_mac *mac = NULL;
- struct list_head *qe;
-
- /* 1. delete pending ucast entries */
- if (!list_empty(&rxf->ucast_pending_del_q)) {
- bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
- bfa_q_qe_init(qe);
- mac = (struct bna_mac *)qe;
- rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
- bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
- return 1;
- }
-
- /* 2. clear active ucast entries; move them to pending_add_q */
- if (!list_empty(&rxf->ucast_active_q)) {
- bfa_q_deq(&rxf->ucast_active_q, &qe);
- bfa_q_qe_init(qe);
- mac = (struct bna_mac *)qe;
- rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
- list_add_tail(&mac->qe, &rxf->ucast_pending_add_q);
- return 1;
- }
-
- return 0;
-}
-
-int
-rxf_clear_packet_filter_promisc(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
-
- /* 6. Execute pending promisc mode disable command */
- if (is_promisc_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* move promisc configuration from pending -> active */
- promisc_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
- bna->rxf_promisc_id = BFI_MAX_RXF;
-
- /* Revert VLAN filter */
- __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
- BNA_STATUS_T_DISABLED);
- return 1;
- }
-
- /* 7. Clear active promisc mode; move it to pending enable */
- if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
- /* move promisc configuration from active -> pending */
- promisc_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-
- /* Revert VLAN filter */
- __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
- BNA_STATUS_T_DISABLED);
- return 1;
- }
-
- return 0;
-}
-
-int
-rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf)
-{
- /* 10. Execute pending allmulti mode disable command */
- if (is_allmulti_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* move allmulti configuration from pending -> active */
- allmulti_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
- BNA_STATUS_T_DISABLED);
- return 1;
- }
-
- /* 11. Clear active allmulti mode; move it to pending enable */
- if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
- /* move allmulti configuration from active -> pending */
- allmulti_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
- rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
- BNA_STATUS_T_DISABLED);
- return 1;
- }
-
- return 0;
-}
-
-void
-rxf_reset_packet_filter_ucast(struct bna_rxf *rxf)
-{
- struct list_head *qe;
- struct bna_mac *mac;
-
- /* 1. Move active ucast entries to pending_add_q */
- while (!list_empty(&rxf->ucast_active_q)) {
- bfa_q_deq(&rxf->ucast_active_q, &qe);
- bfa_q_qe_init(qe);
- list_add_tail(qe, &rxf->ucast_pending_add_q);
- }
-
- /* 2. Throw away delete pending ucast entries */
- while (!list_empty(&rxf->ucast_pending_del_q)) {
- bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
- bfa_q_qe_init(qe);
- mac = (struct bna_mac *)qe;
- bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
- }
-}
-
-void
-rxf_reset_packet_filter_promisc(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
-
- /* 6. Clear pending promisc mode disable */
- if (is_promisc_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- promisc_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
- bna->rxf_promisc_id = BFI_MAX_RXF;
- }
-
- /* 7. Move promisc mode config from active -> pending */
- if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
- promisc_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
- }
-
-}
-
-void
-rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf)
-{
- /* 10. Clear pending allmulti mode disable */
- if (is_allmulti_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- allmulti_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
- }
-
- /* 11. Move allmulti mode config from active -> pending */
- if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
- allmulti_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
- }
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- * Returns:
- * 0 = no h/w change
- * 1 = need h/w change
- */
-static int
-rxf_promisc_enable(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
- int ret = 0;
-
- /* There can not be any pending disable command */
-
- /* Do nothing if pending enable or already enabled */
- if (is_promisc_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask) ||
- (rxf->rxmode_active & BNA_RXMODE_PROMISC)) {
- /* Schedule enable */
- } else {
- /* Promisc mode should not be active in the system */
- promisc_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- bna->rxf_promisc_id = rxf->rxf_id;
- ret = 1;
- }
-
- return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- * Returns:
- * 0 = no h/w change
- * 1 = need h/w change
- */
-static int
-rxf_promisc_disable(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
- int ret = 0;
-
- /* There can not be any pending disable */
-
- /* Turn off pending enable command , if any */
- if (is_promisc_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* Promisc mode should not be active */
- /* system promisc state should be pending */
- promisc_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- /* Remove the promisc state from the system */
- bna->rxf_promisc_id = BFI_MAX_RXF;
-
- /* Schedule disable */
- } else if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
- /* Promisc mode should be active in the system */
- promisc_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- ret = 1;
-
- /* Do nothing if already disabled */
- } else {
- }
-
- return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- * Returns:
- * 0 = no h/w change
- * 1 = need h/w change
- */
-static int
-rxf_allmulti_enable(struct bna_rxf *rxf)
-{
- int ret = 0;
-
- /* There can not be any pending disable command */
-
- /* Do nothing if pending enable or already enabled */
- if (is_allmulti_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask) ||
- (rxf->rxmode_active & BNA_RXMODE_ALLMULTI)) {
- /* Schedule enable */
- } else {
- allmulti_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- ret = 1;
- }
-
- return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- * Returns:
- * 0 = no h/w change
- * 1 = need h/w change
- */
-static int
-rxf_allmulti_disable(struct bna_rxf *rxf)
-{
- int ret = 0;
-
- /* There can not be any pending disable */
-
- /* Turn off pending enable command , if any */
- if (is_allmulti_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* Allmulti mode should not be active */
- allmulti_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
-
- /* Schedule disable */
- } else if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
- allmulti_disable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- ret = 1;
- }
-
- return ret;
-}
-
-/* RxF <- bnad */
-enum bna_cb_status
-bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode,
- enum bna_rxmode bitmask,
- void (*cbfn)(struct bnad *, struct bna_rx *,
- enum bna_cb_status))
-{
- struct bna_rxf *rxf = &rx->rxf;
- int need_hw_config = 0;
-
- /* Process the commands */
-
- if (is_promisc_enable(new_mode, bitmask)) {
- /* If promisc mode is already enabled elsewhere in the system */
- if ((rx->bna->rxf_promisc_id != BFI_MAX_RXF) &&
- (rx->bna->rxf_promisc_id != rxf->rxf_id))
- goto err_return;
- if (rxf_promisc_enable(rxf))
- need_hw_config = 1;
- } else if (is_promisc_disable(new_mode, bitmask)) {
- if (rxf_promisc_disable(rxf))
- need_hw_config = 1;
- }
-
- if (is_allmulti_enable(new_mode, bitmask)) {
- if (rxf_allmulti_enable(rxf))
- need_hw_config = 1;
- } else if (is_allmulti_disable(new_mode, bitmask)) {
- if (rxf_allmulti_disable(rxf))
- need_hw_config = 1;
- }
-
- /* Trigger h/w if needed */
-
- if (need_hw_config) {
- rxf->cam_fltr_cbfn = cbfn;
- rxf->cam_fltr_cbarg = rx->bna->bnad;
- bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
- } else if (cbfn)
- (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-
- return BNA_CB_SUCCESS;
-
-err_return:
- return BNA_CB_FAIL;
-}
-
-void
-/* RxF <- bnad */
-bna_rx_vlanfilter_enable(struct bna_rx *rx)
-{
- struct bna_rxf *rxf = &rx->rxf;
-
- if (rxf->vlan_filter_status == BNA_STATUS_T_DISABLED) {
- rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
- rxf->vlan_filter_status = BNA_STATUS_T_ENABLED;
- bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
- }
-}
-
-/* Rx */
-
-/* Rx <- bnad */
-void
-bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo)
-{
- struct bna_rxp *rxp;
- struct list_head *qe;
-
- list_for_each(qe, &rx->rxp_q) {
- rxp = (struct bna_rxp *)qe;
- rxp->cq.ccb->rx_coalescing_timeo = coalescing_timeo;
- bna_ib_coalescing_timeo_set(rxp->cq.ib, coalescing_timeo);
- }
-}
-
-/* Rx <- bnad */
-void
-bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX])
-{
- int i, j;
-
- for (i = 0; i < BNA_LOAD_T_MAX; i++)
- for (j = 0; j < BNA_BIAS_T_MAX; j++)
- bna->rx_mod.dim_vector[i][j] = vector[i][j];
-}
-
-/* Rx <- bnad */
-void
-bna_rx_dim_update(struct bna_ccb *ccb)
-{
- struct bna *bna = ccb->cq->rx->bna;
- u32 load, bias;
- u32 pkt_rt, small_rt, large_rt;
- u8 coalescing_timeo;
-
- if ((ccb->pkt_rate.small_pkt_cnt == 0) &&
- (ccb->pkt_rate.large_pkt_cnt == 0))
- return;
-
- /* Arrive at preconfigured coalescing timeo value based on pkt rate */
-
- small_rt = ccb->pkt_rate.small_pkt_cnt;
- large_rt = ccb->pkt_rate.large_pkt_cnt;
-
- pkt_rt = small_rt + large_rt;
-
- if (pkt_rt < BNA_PKT_RATE_10K)
- load = BNA_LOAD_T_LOW_4;
- else if (pkt_rt < BNA_PKT_RATE_20K)
- load = BNA_LOAD_T_LOW_3;
- else if (pkt_rt < BNA_PKT_RATE_30K)
- load = BNA_LOAD_T_LOW_2;
- else if (pkt_rt < BNA_PKT_RATE_40K)
- load = BNA_LOAD_T_LOW_1;
- else if (pkt_rt < BNA_PKT_RATE_50K)
- load = BNA_LOAD_T_HIGH_1;
- else if (pkt_rt < BNA_PKT_RATE_60K)
- load = BNA_LOAD_T_HIGH_2;
- else if (pkt_rt < BNA_PKT_RATE_80K)
- load = BNA_LOAD_T_HIGH_3;
- else
- load = BNA_LOAD_T_HIGH_4;
-
- if (small_rt > (large_rt << 1))
- bias = 0;
- else
- bias = 1;
-
- ccb->pkt_rate.small_pkt_cnt = 0;
- ccb->pkt_rate.large_pkt_cnt = 0;
-
- coalescing_timeo = bna->rx_mod.dim_vector[load][bias];
- ccb->rx_coalescing_timeo = coalescing_timeo;
-
- /* Set it to IB */
- bna_ib_coalescing_timeo_set(ccb->cq->ib, coalescing_timeo);
-}
-
-/* Tx */
-/* TX <- bnad */
-void
-bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo)
-{
- struct bna_txq *txq;
- struct list_head *qe;
-
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- bna_ib_coalescing_timeo_set(txq->ib, coalescing_timeo);
- }
-}
-
-/*
- * Private data
- */
-
-struct bna_ritseg_pool_cfg {
- u32 pool_size;
- u32 pool_entry_size;
-};
-init_ritseg_pool(ritseg_pool_cfg);
-
-/*
- * Private functions
- */
-static void
-bna_ucam_mod_init(struct bna_ucam_mod *ucam_mod, struct bna *bna,
- struct bna_res_info *res_info)
-{
- int i;
-
- ucam_mod->ucmac = (struct bna_mac *)
- res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
-
- INIT_LIST_HEAD(&ucam_mod->free_q);
- for (i = 0; i < BFI_MAX_UCMAC; i++) {
- bfa_q_qe_init(&ucam_mod->ucmac[i].qe);
- list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->free_q);
- }
-
- ucam_mod->bna = bna;
-}
-
-static void
-bna_ucam_mod_uninit(struct bna_ucam_mod *ucam_mod)
-{
- struct list_head *qe;
- int i = 0;
-
- list_for_each(qe, &ucam_mod->free_q)
- i++;
-
- ucam_mod->bna = NULL;
-}
-
-static void
-bna_mcam_mod_init(struct bna_mcam_mod *mcam_mod, struct bna *bna,
- struct bna_res_info *res_info)
-{
- int i;
-
- mcam_mod->mcmac = (struct bna_mac *)
- res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
-
- INIT_LIST_HEAD(&mcam_mod->free_q);
- for (i = 0; i < BFI_MAX_MCMAC; i++) {
- bfa_q_qe_init(&mcam_mod->mcmac[i].qe);
- list_add_tail(&mcam_mod->mcmac[i].qe, &mcam_mod->free_q);
- }
-
- mcam_mod->bna = bna;
-}
-
-static void
-bna_mcam_mod_uninit(struct bna_mcam_mod *mcam_mod)
-{
- struct list_head *qe;
- int i = 0;
-
- list_for_each(qe, &mcam_mod->free_q)
- i++;
-
- mcam_mod->bna = NULL;
-}
-
-static void
-bna_rit_mod_init(struct bna_rit_mod *rit_mod,
- struct bna_res_info *res_info)
-{
- int i;
- int j;
- int count;
- int offset;
-
- rit_mod->rit = (struct bna_rit_entry *)
- res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mdl[0].kva;
- rit_mod->rit_segment = (struct bna_rit_segment *)
- res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mdl[0].kva;
-
- count = 0;
- offset = 0;
- for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
- INIT_LIST_HEAD(&rit_mod->rit_seg_pool[i]);
- for (j = 0; j < ritseg_pool_cfg[i].pool_size; j++) {
- bfa_q_qe_init(&rit_mod->rit_segment[count].qe);
- rit_mod->rit_segment[count].max_rit_size =
- ritseg_pool_cfg[i].pool_entry_size;
- rit_mod->rit_segment[count].rit_offset = offset;
- rit_mod->rit_segment[count].rit =
- &rit_mod->rit[offset];
- list_add_tail(&rit_mod->rit_segment[count].qe,
- &rit_mod->rit_seg_pool[i]);
- count++;
- offset += ritseg_pool_cfg[i].pool_entry_size;
- }
- }
-}
-
-/*
- * Public functions
- */
-
-/* Called during probe(), before calling bna_init() */
-void
-bna_res_req(struct bna_res_info *res_info)
-{
- bna_adv_res_req(res_info);
-
- /* DMA memory for retrieving IOC attributes */
- res_info[BNA_RES_MEM_T_ATTR].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
- res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.len =
- ALIGN(bfa_nw_ioc_meminfo(), PAGE_SIZE);
-
- /* DMA memory for index segment of an IB */
- res_info[BNA_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
- res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.len =
- BFI_IBIDX_SIZE * BFI_IBIDX_MAX_SEGSIZE;
- res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.num = BFI_MAX_IB;
-
- /* Virtual memory for IB objects - stored by IB module */
- res_info[BNA_RES_MEM_T_IB_ARRAY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.len =
- BFI_MAX_IB * sizeof(struct bna_ib);
-
- /* Virtual memory for intr objects - stored by IB module */
- res_info[BNA_RES_MEM_T_INTR_ARRAY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.len =
- BFI_MAX_IB * sizeof(struct bna_intr);
-
- /* Virtual memory for idx_seg objects - stored by IB module */
- res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.len =
- BFI_IBIDX_TOTAL_SEGS * sizeof(struct bna_ibidx_seg);
-
- /* Virtual memory for Tx objects - stored by Tx module */
- res_info[BNA_RES_MEM_T_TX_ARRAY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.len =
- BFI_MAX_TXQ * sizeof(struct bna_tx);
-
- /* Virtual memory for TxQ - stored by Tx module */
- res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.len =
- BFI_MAX_TXQ * sizeof(struct bna_txq);
-
- /* Virtual memory for Rx objects - stored by Rx module */
- res_info[BNA_RES_MEM_T_RX_ARRAY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.len =
- BFI_MAX_RXQ * sizeof(struct bna_rx);
-
- /* Virtual memory for RxPath - stored by Rx module */
- res_info[BNA_RES_MEM_T_RXP_ARRAY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.len =
- BFI_MAX_RXQ * sizeof(struct bna_rxp);
-
- /* Virtual memory for RxQ - stored by Rx module */
- res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.len =
- BFI_MAX_RXQ * sizeof(struct bna_rxq);
-
- /* Virtual memory for Unicast MAC address - stored by ucam module */
- res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.len =
- BFI_MAX_UCMAC * sizeof(struct bna_mac);
-
- /* Virtual memory for Multicast MAC address - stored by mcam module */
- res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.len =
- BFI_MAX_MCMAC * sizeof(struct bna_mac);
-
- /* Virtual memory for RIT entries */
- res_info[BNA_RES_MEM_T_RIT_ENTRY].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.len =
- BFI_MAX_RIT_SIZE * sizeof(struct bna_rit_entry);
-
- /* Virtual memory for RIT segment table */
- res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_type = BNA_RES_T_MEM;
- res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mem_type =
- BNA_MEM_T_KVA;
- res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.num = 1;
- res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.len =
- BFI_RIT_TOTAL_SEGS * sizeof(struct bna_rit_segment);
-
- /* Interrupt resource for mailbox interrupt */
- res_info[BNA_RES_INTR_T_MBOX].res_type = BNA_RES_T_INTR;
- res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type =
- BNA_INTR_T_MSIX;
- res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.num = 1;
-}
-
-/* Called during probe() */
-void
-bna_init(struct bna *bna, struct bnad *bnad, struct bfa_pcidev *pcidev,
- struct bna_res_info *res_info)
-{
- bna->bnad = bnad;
- bna->pcidev = *pcidev;
-
- bna->stats.hw_stats = (struct bfi_ll_stats *)
- res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].kva;
- bna->hw_stats_dma.msb =
- res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.msb;
- bna->hw_stats_dma.lsb =
- res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.lsb;
- bna->stats.sw_stats = (struct bna_sw_stats *)
- res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mdl[0].kva;
-
- bna->regs.page_addr = bna->pcidev.pci_bar_kva +
- reg_offset[bna->pcidev.pci_func].page_addr;
- bna->regs.fn_int_status = bna->pcidev.pci_bar_kva +
- reg_offset[bna->pcidev.pci_func].fn_int_status;
- bna->regs.fn_int_mask = bna->pcidev.pci_bar_kva +
- reg_offset[bna->pcidev.pci_func].fn_int_mask;
-
- if (bna->pcidev.pci_func < 3)
- bna->port_num = 0;
- else
- bna->port_num = 1;
-
- /* Also initializes diag, cee, sfp, phy_port and mbox_mod */
- bna_device_init(&bna->device, bna, res_info);
-
- bna_port_init(&bna->port, bna);
-
- bna_tx_mod_init(&bna->tx_mod, bna, res_info);
-
- bna_rx_mod_init(&bna->rx_mod, bna, res_info);
-
- bna_ib_mod_init(&bna->ib_mod, bna, res_info);
-
- bna_rit_mod_init(&bna->rit_mod, res_info);
-
- bna_ucam_mod_init(&bna->ucam_mod, bna, res_info);
-
- bna_mcam_mod_init(&bna->mcam_mod, bna, res_info);
-
- bna->rxf_promisc_id = BFI_MAX_RXF;
-
- /* Mbox q element for posting stat request to f/w */
- bfa_q_qe_init(&bna->mbox_qe.qe);
-}
-
-void
-bna_uninit(struct bna *bna)
-{
- bna_mcam_mod_uninit(&bna->mcam_mod);
-
- bna_ucam_mod_uninit(&bna->ucam_mod);
-
- bna_ib_mod_uninit(&bna->ib_mod);
-
- bna_rx_mod_uninit(&bna->rx_mod);
-
- bna_tx_mod_uninit(&bna->tx_mod);
-
- bna_port_uninit(&bna->port);
-
- bna_device_uninit(&bna->device);
-
- bna->bnad = NULL;
-}
-
-struct bna_mac *
-bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod)
-{
- struct list_head *qe;
-
- if (list_empty(&ucam_mod->free_q))
- return NULL;
-
- bfa_q_deq(&ucam_mod->free_q, &qe);
-
- return (struct bna_mac *)qe;
-}
-
-void
-bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, struct bna_mac *mac)
-{
- list_add_tail(&mac->qe, &ucam_mod->free_q);
-}
-
-struct bna_mac *
-bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod)
-{
- struct list_head *qe;
-
- if (list_empty(&mcam_mod->free_q))
- return NULL;
-
- bfa_q_deq(&mcam_mod->free_q, &qe);
-
- return (struct bna_mac *)qe;
-}
-
-void
-bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, struct bna_mac *mac)
-{
- list_add_tail(&mac->qe, &mcam_mod->free_q);
-}
-
-/**
- * Note: This should be called in the same locking context as the call to
- * bna_rit_mod_seg_get()
- */
-int
-bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size)
-{
- int i;
-
- /* Select the pool for seg_size */
- for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
- if (seg_size <= ritseg_pool_cfg[i].pool_entry_size)
- break;
- }
-
- if (i == BFI_RIT_SEG_TOTAL_POOLS)
- return 0;
-
- if (list_empty(&rit_mod->rit_seg_pool[i]))
- return 0;
-
- return 1;
-}
-
-struct bna_rit_segment *
-bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size)
-{
- struct bna_rit_segment *seg;
- struct list_head *qe;
- int i;
-
- /* Select the pool for seg_size */
- for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
- if (seg_size <= ritseg_pool_cfg[i].pool_entry_size)
- break;
- }
-
- if (i == BFI_RIT_SEG_TOTAL_POOLS)
- return NULL;
-
- if (list_empty(&rit_mod->rit_seg_pool[i]))
- return NULL;
-
- bfa_q_deq(&rit_mod->rit_seg_pool[i], &qe);
- seg = (struct bna_rit_segment *)qe;
- bfa_q_qe_init(&seg->qe);
- seg->rit_size = seg_size;
-
- return seg;
-}
-
-void
-bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod,
- struct bna_rit_segment *seg)
-{
- int i;
-
- /* Select the pool for seg->max_rit_size */
- for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
- if (seg->max_rit_size == ritseg_pool_cfg[i].pool_entry_size)
- break;
- }
-
- seg->rit_size = 0;
- list_add_tail(&seg->qe, &rit_mod->rit_seg_pool[i]);
-}
diff --git a/drivers/net/bna/bna_hw.h b/drivers/net/bna/bna_hw.h
deleted file mode 100644
index cad233da843a..000000000000
--- a/drivers/net/bna/bna_hw.h
+++ /dev/null
@@ -1,1490 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * File for interrupt macros and functions
- */
-
-#ifndef __BNA_HW_H__
-#define __BNA_HW_H__
-
-#include "bfi_ctreg.h"
-
-/**
- *
- * SW imposed limits
- *
- */
-
-#ifndef BNA_BIOS_BUILD
-
-#define BFI_MAX_TXQ 64
-#define BFI_MAX_RXQ 64
-#define BFI_MAX_RXF 64
-#define BFI_MAX_IB 128
-#define BFI_MAX_RIT_SIZE 256
-#define BFI_RSS_RIT_SIZE 64
-#define BFI_NONRSS_RIT_SIZE 1
-#define BFI_MAX_UCMAC 256
-#define BFI_MAX_MCMAC 512
-#define BFI_IBIDX_SIZE 4
-#define BFI_MAX_VLAN 4095
-
-/**
- * There are 2 free IB index pools:
- * pool1: 120 segments of 1 index each
- * pool8: 1 segment of 8 indexes
- */
-#define BFI_IBIDX_POOL1_SIZE 116
-#define BFI_IBIDX_POOL1_ENTRY_SIZE 1
-#define BFI_IBIDX_POOL2_SIZE 2
-#define BFI_IBIDX_POOL2_ENTRY_SIZE 2
-#define BFI_IBIDX_POOL8_SIZE 1
-#define BFI_IBIDX_POOL8_ENTRY_SIZE 8
-#define BFI_IBIDX_TOTAL_POOLS 3
-#define BFI_IBIDX_TOTAL_SEGS 119 /* (POOL1 + POOL2 + POOL8)_SIZE */
-#define BFI_IBIDX_MAX_SEGSIZE 8
-#define init_ibidx_pool(name) \
-static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] = \
-{ \
- { BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE }, \
- { BFI_IBIDX_POOL2_SIZE, BFI_IBIDX_POOL2_ENTRY_SIZE }, \
- { BFI_IBIDX_POOL8_SIZE, BFI_IBIDX_POOL8_ENTRY_SIZE } \
-}
-
-/**
- * There are 2 free RIT segment pools:
- * Pool1: 192 segments of 1 RIT entry each
- * Pool2: 1 segment of 64 RIT entry
- */
-#define BFI_RIT_SEG_POOL1_SIZE 192
-#define BFI_RIT_SEG_POOL1_ENTRY_SIZE 1
-#define BFI_RIT_SEG_POOLRSS_SIZE 1
-#define BFI_RIT_SEG_POOLRSS_ENTRY_SIZE 64
-#define BFI_RIT_SEG_TOTAL_POOLS 2
-#define BFI_RIT_TOTAL_SEGS 193 /* POOL1_SIZE + POOLRSS_SIZE */
-#define init_ritseg_pool(name) \
-static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \
-{ \
- { BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE }, \
- { BFI_RIT_SEG_POOLRSS_SIZE, BFI_RIT_SEG_POOLRSS_ENTRY_SIZE } \
-}
-
-#else /* BNA_BIOS_BUILD */
-
-#define BFI_MAX_TXQ 1
-#define BFI_MAX_RXQ 1
-#define BFI_MAX_RXF 1
-#define BFI_MAX_IB 2
-#define BFI_MAX_RIT_SIZE 2
-#define BFI_RSS_RIT_SIZE 64
-#define BFI_NONRSS_RIT_SIZE 1
-#define BFI_MAX_UCMAC 1
-#define BFI_MAX_MCMAC 8
-#define BFI_IBIDX_SIZE 4
-#define BFI_MAX_VLAN 4095
-/* There is one free pool: 2 segments of 1 index each */
-#define BFI_IBIDX_POOL1_SIZE 2
-#define BFI_IBIDX_POOL1_ENTRY_SIZE 1
-#define BFI_IBIDX_TOTAL_POOLS 1
-#define BFI_IBIDX_TOTAL_SEGS 2 /* POOL1_SIZE */
-#define BFI_IBIDX_MAX_SEGSIZE 1
-#define init_ibidx_pool(name) \
-static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] = \
-{ \
- { BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE } \
-}
-
-#define BFI_RIT_SEG_POOL1_SIZE 1
-#define BFI_RIT_SEG_POOL1_ENTRY_SIZE 1
-#define BFI_RIT_SEG_TOTAL_POOLS 1
-#define BFI_RIT_TOTAL_SEGS 1 /* POOL1_SIZE */
-#define init_ritseg_pool(name) \
-static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \
-{ \
- { BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE } \
-}
-
-#endif /* BNA_BIOS_BUILD */
-
-#define BFI_RSS_HASH_KEY_LEN 10
-
-#define BFI_COALESCING_TIMER_UNIT 5 /* 5us */
-#define BFI_MAX_COALESCING_TIMEO 0xFF /* in 5us units */
-#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_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 */
-
-#define BFI_TXQ_WI_SIZE 64 /* bytes */
-#define BFI_RXQ_WI_SIZE 8 /* bytes */
-#define BFI_CQ_WI_SIZE 16 /* bytes */
-#define BFI_TX_MAX_WRR_QUOTA 0xFFF
-
-#define BFI_TX_MAX_VECTORS_PER_WI 4
-#define BFI_TX_MAX_VECTORS_PER_PKT 0xFF
-#define BFI_TX_MAX_DATA_PER_VECTOR 0xFFFF
-#define BFI_TX_MAX_DATA_PER_PKT 0xFFFFFF
-
-/* Small Q buffer size */
-#define BFI_SMALL_RXBUF_SIZE 128
-
-/* Defined separately since BFA_FLASH_DMA_BUF_SZ is in bfa_flash.c */
-#define BFI_FLASH_DMA_BUF_SZ 0x010000 /* 64K DMA */
-#define BFI_HW_STATS_SIZE 0x4000 /* 16K DMA */
-
-/**
- *
- * HW register offsets, macros
- *
- */
-
-/* DMA Block Register Host Window Start Address */
-#define DMA_BLK_REG_ADDR 0x00013000
-
-/* DMA Block Internal Registers */
-#define DMA_CTRL_REG0 (DMA_BLK_REG_ADDR + 0x000)
-#define DMA_CTRL_REG1 (DMA_BLK_REG_ADDR + 0x004)
-#define DMA_ERR_INT_STATUS (DMA_BLK_REG_ADDR + 0x008)
-#define DMA_ERR_INT_ENABLE (DMA_BLK_REG_ADDR + 0x00c)
-#define DMA_ERR_INT_STATUS_SET (DMA_BLK_REG_ADDR + 0x010)
-
-/* APP Block Register Address Offset from BAR0 */
-#define APP_BLK_REG_ADDR 0x00014000
-
-/* Host Function Interrupt Mask Registers */
-#define HOSTFN0_INT_MASK (APP_BLK_REG_ADDR + 0x004)
-#define HOSTFN1_INT_MASK (APP_BLK_REG_ADDR + 0x104)
-#define HOSTFN2_INT_MASK (APP_BLK_REG_ADDR + 0x304)
-#define HOSTFN3_INT_MASK (APP_BLK_REG_ADDR + 0x404)
-
-/**
- * Host Function PCIe Error Registers
- * Duplicates "Correctable" & "Uncorrectable"
- * registers in PCIe Config space.
- */
-#define FN0_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x014)
-#define FN1_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x114)
-#define FN2_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x314)
-#define FN3_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x414)
-
-/* Host Function Error Type Status Registers */
-#define FN0_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x018)
-#define FN1_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x118)
-#define FN2_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x318)
-#define FN3_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x418)
-
-/* Host Function Error Type Mask Registers */
-#define FN0_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x01c)
-#define FN1_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x11c)
-#define FN2_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x31c)
-#define FN3_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x41c)
-
-/* Catapult Host Semaphore Status Registers (App block) */
-#define HOST_SEM_STS0_REG (APP_BLK_REG_ADDR + 0x630)
-#define HOST_SEM_STS1_REG (APP_BLK_REG_ADDR + 0x634)
-#define HOST_SEM_STS2_REG (APP_BLK_REG_ADDR + 0x638)
-#define HOST_SEM_STS3_REG (APP_BLK_REG_ADDR + 0x63c)
-#define HOST_SEM_STS4_REG (APP_BLK_REG_ADDR + 0x640)
-#define HOST_SEM_STS5_REG (APP_BLK_REG_ADDR + 0x644)
-#define HOST_SEM_STS6_REG (APP_BLK_REG_ADDR + 0x648)
-#define HOST_SEM_STS7_REG (APP_BLK_REG_ADDR + 0x64c)
-
-/* PCIe Misc Register */
-#define PCIE_MISC_REG (APP_BLK_REG_ADDR + 0x200)
-
-/* Temp Sensor Control Registers */
-#define TEMPSENSE_CNTL_REG (APP_BLK_REG_ADDR + 0x250)
-#define TEMPSENSE_STAT_REG (APP_BLK_REG_ADDR + 0x254)
-
-/* APP Block local error registers */
-#define APP_LOCAL_ERR_STAT (APP_BLK_REG_ADDR + 0x258)
-#define APP_LOCAL_ERR_MSK (APP_BLK_REG_ADDR + 0x25c)
-
-/* PCIe Link Error registers */
-#define PCIE_LNK_ERR_STAT (APP_BLK_REG_ADDR + 0x260)
-#define PCIE_LNK_ERR_MSK (APP_BLK_REG_ADDR + 0x264)
-
-/**
- * FCoE/FIP Ethertype Register
- * 31:16 -- Chip wide value for FIP type
- * 15:0 -- Chip wide value for FCoE type
- */
-#define FCOE_FIP_ETH_TYPE (APP_BLK_REG_ADDR + 0x280)
-
-/**
- * Reserved Ethertype Register
- * 31:16 -- Reserved
- * 15:0 -- Other ethertype
- */
-#define RESV_ETH_TYPE (APP_BLK_REG_ADDR + 0x284)
-
-/**
- * Host Command Status Registers
- * Each set consists of 3 registers :
- * clear, set, cmd
- * 16 such register sets in all
- * See catapult_spec.pdf for detailed functionality
- * Put each type in a single macro accessed by _num ?
- */
-#define HOST_CMDSTS0_CLR_REG (APP_BLK_REG_ADDR + 0x500)
-#define HOST_CMDSTS0_SET_REG (APP_BLK_REG_ADDR + 0x504)
-#define HOST_CMDSTS0_REG (APP_BLK_REG_ADDR + 0x508)
-#define HOST_CMDSTS1_CLR_REG (APP_BLK_REG_ADDR + 0x510)
-#define HOST_CMDSTS1_SET_REG (APP_BLK_REG_ADDR + 0x514)
-#define HOST_CMDSTS1_REG (APP_BLK_REG_ADDR + 0x518)
-#define HOST_CMDSTS2_CLR_REG (APP_BLK_REG_ADDR + 0x520)
-#define HOST_CMDSTS2_SET_REG (APP_BLK_REG_ADDR + 0x524)
-#define HOST_CMDSTS2_REG (APP_BLK_REG_ADDR + 0x528)
-#define HOST_CMDSTS3_CLR_REG (APP_BLK_REG_ADDR + 0x530)
-#define HOST_CMDSTS3_SET_REG (APP_BLK_REG_ADDR + 0x534)
-#define HOST_CMDSTS3_REG (APP_BLK_REG_ADDR + 0x538)
-#define HOST_CMDSTS4_CLR_REG (APP_BLK_REG_ADDR + 0x540)
-#define HOST_CMDSTS4_SET_REG (APP_BLK_REG_ADDR + 0x544)
-#define HOST_CMDSTS4_REG (APP_BLK_REG_ADDR + 0x548)
-#define HOST_CMDSTS5_CLR_REG (APP_BLK_REG_ADDR + 0x550)
-#define HOST_CMDSTS5_SET_REG (APP_BLK_REG_ADDR + 0x554)
-#define HOST_CMDSTS5_REG (APP_BLK_REG_ADDR + 0x558)
-#define HOST_CMDSTS6_CLR_REG (APP_BLK_REG_ADDR + 0x560)
-#define HOST_CMDSTS6_SET_REG (APP_BLK_REG_ADDR + 0x564)
-#define HOST_CMDSTS6_REG (APP_BLK_REG_ADDR + 0x568)
-#define HOST_CMDSTS7_CLR_REG (APP_BLK_REG_ADDR + 0x570)
-#define HOST_CMDSTS7_SET_REG (APP_BLK_REG_ADDR + 0x574)
-#define HOST_CMDSTS7_REG (APP_BLK_REG_ADDR + 0x578)
-#define HOST_CMDSTS8_CLR_REG (APP_BLK_REG_ADDR + 0x580)
-#define HOST_CMDSTS8_SET_REG (APP_BLK_REG_ADDR + 0x584)
-#define HOST_CMDSTS8_REG (APP_BLK_REG_ADDR + 0x588)
-#define HOST_CMDSTS9_CLR_REG (APP_BLK_REG_ADDR + 0x590)
-#define HOST_CMDSTS9_SET_REG (APP_BLK_REG_ADDR + 0x594)
-#define HOST_CMDSTS9_REG (APP_BLK_REG_ADDR + 0x598)
-#define HOST_CMDSTS10_CLR_REG (APP_BLK_REG_ADDR + 0x5A0)
-#define HOST_CMDSTS10_SET_REG (APP_BLK_REG_ADDR + 0x5A4)
-#define HOST_CMDSTS10_REG (APP_BLK_REG_ADDR + 0x5A8)
-#define HOST_CMDSTS11_CLR_REG (APP_BLK_REG_ADDR + 0x5B0)
-#define HOST_CMDSTS11_SET_REG (APP_BLK_REG_ADDR + 0x5B4)
-#define HOST_CMDSTS11_REG (APP_BLK_REG_ADDR + 0x5B8)
-#define HOST_CMDSTS12_CLR_REG (APP_BLK_REG_ADDR + 0x5C0)
-#define HOST_CMDSTS12_SET_REG (APP_BLK_REG_ADDR + 0x5C4)
-#define HOST_CMDSTS12_REG (APP_BLK_REG_ADDR + 0x5C8)
-#define HOST_CMDSTS13_CLR_REG (APP_BLK_REG_ADDR + 0x5D0)
-#define HOST_CMDSTS13_SET_REG (APP_BLK_REG_ADDR + 0x5D4)
-#define HOST_CMDSTS13_REG (APP_BLK_REG_ADDR + 0x5D8)
-#define HOST_CMDSTS14_CLR_REG (APP_BLK_REG_ADDR + 0x5E0)
-#define HOST_CMDSTS14_SET_REG (APP_BLK_REG_ADDR + 0x5E4)
-#define HOST_CMDSTS14_REG (APP_BLK_REG_ADDR + 0x5E8)
-#define HOST_CMDSTS15_CLR_REG (APP_BLK_REG_ADDR + 0x5F0)
-#define HOST_CMDSTS15_SET_REG (APP_BLK_REG_ADDR + 0x5F4)
-#define HOST_CMDSTS15_REG (APP_BLK_REG_ADDR + 0x5F8)
-
-/**
- * LPU0 Block Register Address Offset from BAR0
- * Range 0x18000 - 0x18033
- */
-#define LPU0_BLK_REG_ADDR 0x00018000
-
-/**
- * LPU0 Registers
- * Should they be directly used from host,
- * except for diagnostics ?
- * CTL_REG : Control register
- * CMD_REG : Triggers exec. of cmd. in
- * Mailbox memory
- */
-#define LPU0_MBOX_CTL_REG (LPU0_BLK_REG_ADDR + 0x000)
-#define LPU0_MBOX_CMD_REG (LPU0_BLK_REG_ADDR + 0x004)
-#define LPU0_MBOX_LINK_0REG (LPU0_BLK_REG_ADDR + 0x008)
-#define LPU1_MBOX_LINK_0REG (LPU0_BLK_REG_ADDR + 0x00c)
-#define LPU0_MBOX_STATUS_0REG (LPU0_BLK_REG_ADDR + 0x010)
-#define LPU1_MBOX_STATUS_0REG (LPU0_BLK_REG_ADDR + 0x014)
-#define LPU0_ERR_STATUS_REG (LPU0_BLK_REG_ADDR + 0x018)
-#define LPU0_ERR_SET_REG (LPU0_BLK_REG_ADDR + 0x020)
-
-/**
- * LPU1 Block Register Address Offset from BAR0
- * Range 0x18400 - 0x18433
- */
-#define LPU1_BLK_REG_ADDR 0x00018400
-
-/**
- * LPU1 Registers
- * Same as LPU0 registers above
- */
-#define LPU1_MBOX_CTL_REG (LPU1_BLK_REG_ADDR + 0x000)
-#define LPU1_MBOX_CMD_REG (LPU1_BLK_REG_ADDR + 0x004)
-#define LPU0_MBOX_LINK_1REG (LPU1_BLK_REG_ADDR + 0x008)
-#define LPU1_MBOX_LINK_1REG (LPU1_BLK_REG_ADDR + 0x00c)
-#define LPU0_MBOX_STATUS_1REG (LPU1_BLK_REG_ADDR + 0x010)
-#define LPU1_MBOX_STATUS_1REG (LPU1_BLK_REG_ADDR + 0x014)
-#define LPU1_ERR_STATUS_REG (LPU1_BLK_REG_ADDR + 0x018)
-#define LPU1_ERR_SET_REG (LPU1_BLK_REG_ADDR + 0x020)
-
-/**
- * PSS Block Register Address Offset from BAR0
- * Range 0x18800 - 0x188DB
- */
-#define PSS_BLK_REG_ADDR 0x00018800
-
-/**
- * PSS Registers
- * For details, see catapult_spec.pdf
- * ERR_STATUS_REG : Indicates error in PSS module
- * RAM_ERR_STATUS_REG : Indicates RAM module that detected error
- */
-#define ERR_STATUS_SET (PSS_BLK_REG_ADDR + 0x018)
-#define PSS_RAM_ERR_STATUS_REG (PSS_BLK_REG_ADDR + 0x01C)
-
-/**
- * PSS Semaphore Lock Registers, total 16
- * First read when unlocked returns 0,
- * and is set to 1, atomically.
- * Subsequent reads returns 1.
- * To clear set the value to 0.
- * Range : 0x20 to 0x5c
- */
-#define PSS_SEM_LOCK_REG(_num) \
- (PSS_BLK_REG_ADDR + 0x020 + ((_num) << 2))
-
-/**
- * PSS Semaphore Status Registers,
- * corresponding to the lock registers above
- */
-#define PSS_SEM_STATUS_REG(_num) \
- (PSS_BLK_REG_ADDR + 0x060 + ((_num) << 2))
-
-/**
- * Catapult CPQ Registers
- * Defines for Mailbox Registers
- * Used to send mailbox commands to firmware from
- * host. The data part is written to the MBox
- * memory, registers are used to indicate that
- * a commnad is resident in memory.
- *
- * Note : LPU0<->LPU1 mailboxes are not listed here
- */
-#define CPQ_BLK_REG_ADDR 0x00019000
-
-#define HOSTFN0_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x130)
-#define HOSTFN0_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x134)
-#define LPU0_HOSTFN0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x138)
-#define LPU1_HOSTFN0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x13C)
-
-#define HOSTFN1_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x140)
-#define HOSTFN1_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x144)
-#define LPU0_HOSTFN1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x148)
-#define LPU1_HOSTFN1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x14C)
-
-#define HOSTFN2_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x170)
-#define HOSTFN2_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x174)
-#define LPU0_HOSTFN2_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x178)
-#define LPU1_HOSTFN2_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x17C)
-
-#define HOSTFN3_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x180)
-#define HOSTFN3_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x184)
-#define LPU0_HOSTFN3_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x188)
-#define LPU1_HOSTFN3_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x18C)
-
-/* Host Function Force Parity Error Registers */
-#define HOSTFN0_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x120)
-#define HOSTFN1_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x124)
-#define HOSTFN2_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x128)
-#define HOSTFN3_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x12C)
-
-/* LL Port[0|1] Halt Mask Registers */
-#define LL_HALT_MSK_P0 (CPQ_BLK_REG_ADDR + 0x1A0)
-#define LL_HALT_MSK_P1 (CPQ_BLK_REG_ADDR + 0x1B0)
-
-/* LL Port[0|1] Error Mask Registers */
-#define LL_ERR_MSK_P0 (CPQ_BLK_REG_ADDR + 0x1D0)
-#define LL_ERR_MSK_P1 (CPQ_BLK_REG_ADDR + 0x1D4)
-
-/* EMC FLI (Flash Controller) Block Register Address Offset from BAR0 */
-#define FLI_BLK_REG_ADDR 0x0001D000
-
-/* EMC FLI Registers */
-#define FLI_CMD_REG (FLI_BLK_REG_ADDR + 0x000)
-#define FLI_ADDR_REG (FLI_BLK_REG_ADDR + 0x004)
-#define FLI_CTL_REG (FLI_BLK_REG_ADDR + 0x008)
-#define FLI_WRDATA_REG (FLI_BLK_REG_ADDR + 0x00C)
-#define FLI_RDDATA_REG (FLI_BLK_REG_ADDR + 0x010)
-#define FLI_DEV_STATUS_REG (FLI_BLK_REG_ADDR + 0x014)
-#define FLI_SIG_WD_REG (FLI_BLK_REG_ADDR + 0x018)
-
-/**
- * RO register
- * 31:16 -- Vendor Id
- * 15:0 -- Device Id
- */
-#define FLI_DEV_VENDOR_REG (FLI_BLK_REG_ADDR + 0x01C)
-#define FLI_ERR_STATUS_REG (FLI_BLK_REG_ADDR + 0x020)
-
-/**
- * RAD (RxAdm) Block Register Address Offset from BAR0
- * RAD0 Range : 0x20000 - 0x203FF
- * RAD1 Range : 0x20400 - 0x207FF
- */
-#define RAD0_BLK_REG_ADDR 0x00020000
-#define RAD1_BLK_REG_ADDR 0x00020400
-
-/* RAD0 Registers */
-#define RAD0_CTL_REG (RAD0_BLK_REG_ADDR + 0x000)
-#define RAD0_PE_PARM_REG (RAD0_BLK_REG_ADDR + 0x004)
-#define RAD0_BCN_REG (RAD0_BLK_REG_ADDR + 0x008)
-
-/* Default function ID register */
-#define RAD0_DEFAULT_REG (RAD0_BLK_REG_ADDR + 0x00C)
-
-/* Default promiscuous ID register */
-#define RAD0_PROMISC_REG (RAD0_BLK_REG_ADDR + 0x010)
-
-#define RAD0_BCNQ_REG (RAD0_BLK_REG_ADDR + 0x014)
-
-/*
- * This register selects 1 of 8 PM Q's using
- * VLAN pri, for non-BCN packets without a VLAN tag
- */
-#define RAD0_DEFAULTQ_REG (RAD0_BLK_REG_ADDR + 0x018)
-
-#define RAD0_ERR_STS (RAD0_BLK_REG_ADDR + 0x01C)
-#define RAD0_SET_ERR_STS (RAD0_BLK_REG_ADDR + 0x020)
-#define RAD0_ERR_INT_EN (RAD0_BLK_REG_ADDR + 0x024)
-#define RAD0_FIRST_ERR (RAD0_BLK_REG_ADDR + 0x028)
-#define RAD0_FORCE_ERR (RAD0_BLK_REG_ADDR + 0x02C)
-
-#define RAD0_IF_RCVD (RAD0_BLK_REG_ADDR + 0x030)
-#define RAD0_IF_RCVD_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x034)
-#define RAD0_IF_RCVD_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x038)
-#define RAD0_IF_RCVD_VLAN (RAD0_BLK_REG_ADDR + 0x03C)
-#define RAD0_IF_RCVD_UCAST (RAD0_BLK_REG_ADDR + 0x040)
-#define RAD0_IF_RCVD_UCAST_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x044)
-#define RAD0_IF_RCVD_UCAST_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x048)
-#define RAD0_IF_RCVD_UCAST_VLAN (RAD0_BLK_REG_ADDR + 0x04C)
-#define RAD0_IF_RCVD_MCAST (RAD0_BLK_REG_ADDR + 0x050)
-#define RAD0_IF_RCVD_MCAST_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x054)
-#define RAD0_IF_RCVD_MCAST_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x058)
-#define RAD0_IF_RCVD_MCAST_VLAN (RAD0_BLK_REG_ADDR + 0x05C)
-#define RAD0_IF_RCVD_BCAST (RAD0_BLK_REG_ADDR + 0x060)
-#define RAD0_IF_RCVD_BCAST_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x064)
-#define RAD0_IF_RCVD_BCAST_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x068)
-#define RAD0_IF_RCVD_BCAST_VLAN (RAD0_BLK_REG_ADDR + 0x06C)
-#define RAD0_DROPPED_FRAMES (RAD0_BLK_REG_ADDR + 0x070)
-
-#define RAD0_MAC_MAN_1H (RAD0_BLK_REG_ADDR + 0x080)
-#define RAD0_MAC_MAN_1L (RAD0_BLK_REG_ADDR + 0x084)
-#define RAD0_MAC_MAN_2H (RAD0_BLK_REG_ADDR + 0x088)
-#define RAD0_MAC_MAN_2L (RAD0_BLK_REG_ADDR + 0x08C)
-#define RAD0_MAC_MAN_3H (RAD0_BLK_REG_ADDR + 0x090)
-#define RAD0_MAC_MAN_3L (RAD0_BLK_REG_ADDR + 0x094)
-#define RAD0_MAC_MAN_4H (RAD0_BLK_REG_ADDR + 0x098)
-#define RAD0_MAC_MAN_4L (RAD0_BLK_REG_ADDR + 0x09C)
-
-#define RAD0_LAST4_IP (RAD0_BLK_REG_ADDR + 0x100)
-
-/* RAD1 Registers */
-#define RAD1_CTL_REG (RAD1_BLK_REG_ADDR + 0x000)
-#define RAD1_PE_PARM_REG (RAD1_BLK_REG_ADDR + 0x004)
-#define RAD1_BCN_REG (RAD1_BLK_REG_ADDR + 0x008)
-
-/* Default function ID register */
-#define RAD1_DEFAULT_REG (RAD1_BLK_REG_ADDR + 0x00C)
-
-/* Promiscuous function ID register */
-#define RAD1_PROMISC_REG (RAD1_BLK_REG_ADDR + 0x010)
-
-#define RAD1_BCNQ_REG (RAD1_BLK_REG_ADDR + 0x014)
-
-/*
- * This register selects 1 of 8 PM Q's using
- * VLAN pri, for non-BCN packets without a VLAN tag
- */
-#define RAD1_DEFAULTQ_REG (RAD1_BLK_REG_ADDR + 0x018)
-
-#define RAD1_ERR_STS (RAD1_BLK_REG_ADDR + 0x01C)
-#define RAD1_SET_ERR_STS (RAD1_BLK_REG_ADDR + 0x020)
-#define RAD1_ERR_INT_EN (RAD1_BLK_REG_ADDR + 0x024)
-
-/**
- * TXA Block Register Address Offset from BAR0
- * TXA0 Range : 0x21000 - 0x213FF
- * TXA1 Range : 0x21400 - 0x217FF
- */
-#define TXA0_BLK_REG_ADDR 0x00021000
-#define TXA1_BLK_REG_ADDR 0x00021400
-
-/* TXA Registers */
-#define TXA0_CTRL_REG (TXA0_BLK_REG_ADDR + 0x000)
-#define TXA1_CTRL_REG (TXA1_BLK_REG_ADDR + 0x000)
-
-/**
- * TSO Sequence # Registers (RO)
- * Total 8 (for 8 queues)
- * Holds the last seq.# for TSO frames
- * See catapult_spec.pdf for more details
- */
-#define TXA0_TSO_TCP_SEQ_REG(_num) \
- (TXA0_BLK_REG_ADDR + 0x020 + ((_num) << 2))
-
-#define TXA1_TSO_TCP_SEQ_REG(_num) \
- (TXA1_BLK_REG_ADDR + 0x020 + ((_num) << 2))
-
-/**
- * TSO IP ID # Registers (RO)
- * Total 8 (for 8 queues)
- * Holds the last IP ID for TSO frames
- * See catapult_spec.pdf for more details
- */
-#define TXA0_TSO_IP_INFO_REG(_num) \
- (TXA0_BLK_REG_ADDR + 0x040 + ((_num) << 2))
-
-#define TXA1_TSO_IP_INFO_REG(_num) \
- (TXA1_BLK_REG_ADDR + 0x040 + ((_num) << 2))
-
-/**
- * RXA Block Register Address Offset from BAR0
- * RXA0 Range : 0x21800 - 0x21BFF
- * RXA1 Range : 0x21C00 - 0x21FFF
- */
-#define RXA0_BLK_REG_ADDR 0x00021800
-#define RXA1_BLK_REG_ADDR 0x00021C00
-
-/* RXA Registers */
-#define RXA0_CTL_REG (RXA0_BLK_REG_ADDR + 0x040)
-#define RXA1_CTL_REG (RXA1_BLK_REG_ADDR + 0x040)
-
-/**
- * PPLB Block Register Address Offset from BAR0
- * PPLB0 Range : 0x22000 - 0x223FF
- * PPLB1 Range : 0x22400 - 0x227FF
- */
-#define PLB0_BLK_REG_ADDR 0x00022000
-#define PLB1_BLK_REG_ADDR 0x00022400
-
-/**
- * PLB Registers
- * Holds RL timer used time stamps in RLT tagged frames
- */
-#define PLB0_ECM_TIMER_REG (PLB0_BLK_REG_ADDR + 0x05C)
-#define PLB1_ECM_TIMER_REG (PLB1_BLK_REG_ADDR + 0x05C)
-
-/* Controls the rate-limiter on each of the priority class */
-#define PLB0_RL_CTL (PLB0_BLK_REG_ADDR + 0x060)
-#define PLB1_RL_CTL (PLB1_BLK_REG_ADDR + 0x060)
-
-/**
- * Max byte register, total 8, 0-7
- * see catapult_spec.pdf for details
- */
-#define PLB0_RL_MAX_BC(_num) \
- (PLB0_BLK_REG_ADDR + 0x064 + ((_num) << 2))
-#define PLB1_RL_MAX_BC(_num) \
- (PLB1_BLK_REG_ADDR + 0x064 + ((_num) << 2))
-
-/**
- * RL Time Unit Register for priority 0-7
- * 4 bits per priority
- * (2^rl_unit)*1us is the actual time period
- */
-#define PLB0_RL_TU_PRIO (PLB0_BLK_REG_ADDR + 0x084)
-#define PLB1_RL_TU_PRIO (PLB1_BLK_REG_ADDR + 0x084)
-
-/**
- * RL byte count register,
- * bytes transmitted in (rl_unit*1)us time period
- * 1 per priority, 8 in all, 0-7.
- */
-#define PLB0_RL_BYTE_CNT(_num) \
- (PLB0_BLK_REG_ADDR + 0x088 + ((_num) << 2))
-#define PLB1_RL_BYTE_CNT(_num) \
- (PLB1_BLK_REG_ADDR + 0x088 + ((_num) << 2))
-
-/**
- * RL Min factor register
- * 2 bits per priority,
- * 4 factors possible: 1, 0.5, 0.25, 0
- * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
- */
-#define PLB0_RL_MIN_REG (PLB0_BLK_REG_ADDR + 0x0A8)
-#define PLB1_RL_MIN_REG (PLB1_BLK_REG_ADDR + 0x0A8)
-
-/**
- * RL Max factor register
- * 2 bits per priority,
- * 4 factors possible: 1, 0.5, 0.25, 0
- * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
- */
-#define PLB0_RL_MAX_REG (PLB0_BLK_REG_ADDR + 0x0AC)
-#define PLB1_RL_MAX_REG (PLB1_BLK_REG_ADDR + 0x0AC)
-
-/* MAC SERDES Address Paging register */
-#define PLB0_EMS_ADD_REG (PLB0_BLK_REG_ADDR + 0xD0)
-#define PLB1_EMS_ADD_REG (PLB1_BLK_REG_ADDR + 0xD0)
-
-/* LL EMS Registers */
-#define LL_EMS0_BLK_REG_ADDR 0x00026800
-#define LL_EMS1_BLK_REG_ADDR 0x00026C00
-
-/**
- * BPC Block Register Address Offset from BAR0
- * BPC0 Range : 0x23000 - 0x233FF
- * BPC1 Range : 0x23400 - 0x237FF
- */
-#define BPC0_BLK_REG_ADDR 0x00023000
-#define BPC1_BLK_REG_ADDR 0x00023400
-
-/**
- * PMM Block Register Address Offset from BAR0
- * PMM0 Range : 0x23800 - 0x23BFF
- * PMM1 Range : 0x23C00 - 0x23FFF
- */
-#define PMM0_BLK_REG_ADDR 0x00023800
-#define PMM1_BLK_REG_ADDR 0x00023C00
-
-/**
- * HQM Block Register Address Offset from BAR0
- * HQM0 Range : 0x24000 - 0x243FF
- * HQM1 Range : 0x24400 - 0x247FF
- */
-#define HQM0_BLK_REG_ADDR 0x00024000
-#define HQM1_BLK_REG_ADDR 0x00024400
-
-/**
- * HQM Control Register
- * Controls some aspects of IB
- * See catapult_spec.pdf for details
- */
-#define HQM0_CTL_REG (HQM0_BLK_REG_ADDR + 0x000)
-#define HQM1_CTL_REG (HQM1_BLK_REG_ADDR + 0x000)
-
-/**
- * HQM Stop Q Semaphore Registers.
- * Only one Queue resource can be stopped at
- * any given time. This register controls access
- * to the single stop Q resource.
- * See catapult_spec.pdf for details
- */
-#define HQM0_RXQ_STOP_SEM (HQM0_BLK_REG_ADDR + 0x028)
-#define HQM0_TXQ_STOP_SEM (HQM0_BLK_REG_ADDR + 0x02C)
-#define HQM1_RXQ_STOP_SEM (HQM1_BLK_REG_ADDR + 0x028)
-#define HQM1_TXQ_STOP_SEM (HQM1_BLK_REG_ADDR + 0x02C)
-
-/**
- * LUT Block Register Address Offset from BAR0
- * LUT0 Range : 0x25800 - 0x25BFF
- * LUT1 Range : 0x25C00 - 0x25FFF
- */
-#define LUT0_BLK_REG_ADDR 0x00025800
-#define LUT1_BLK_REG_ADDR 0x00025C00
-
-/**
- * LUT Registers
- * See catapult_spec.pdf for details
- */
-#define LUT0_ERR_STS (LUT0_BLK_REG_ADDR + 0x000)
-#define LUT1_ERR_STS (LUT1_BLK_REG_ADDR + 0x000)
-#define LUT0_SET_ERR_STS (LUT0_BLK_REG_ADDR + 0x004)
-#define LUT1_SET_ERR_STS (LUT1_BLK_REG_ADDR + 0x004)
-
-/**
- * TRC (Debug/Trace) Register Offset from BAR0
- * Range : 0x26000 -- 0x263FFF
- */
-#define TRC_BLK_REG_ADDR 0x00026000
-
-/**
- * TRC Registers
- * See catapult_spec.pdf for details of each
- */
-#define TRC_CTL_REG (TRC_BLK_REG_ADDR + 0x000)
-#define TRC_MODS_REG (TRC_BLK_REG_ADDR + 0x004)
-#define TRC_TRGC_REG (TRC_BLK_REG_ADDR + 0x008)
-#define TRC_CNT1_REG (TRC_BLK_REG_ADDR + 0x010)
-#define TRC_CNT2_REG (TRC_BLK_REG_ADDR + 0x014)
-#define TRC_NXTS_REG (TRC_BLK_REG_ADDR + 0x018)
-#define TRC_DIRR_REG (TRC_BLK_REG_ADDR + 0x01C)
-
-/**
- * TRC Trigger match filters, total 10
- * Determines the trigger condition
- */
-#define TRC_TRGM_REG(_num) \
- (TRC_BLK_REG_ADDR + 0x040 + ((_num) << 2))
-
-/**
- * TRC Next State filters, total 10
- * Determines the next state conditions
- */
-#define TRC_NXTM_REG(_num) \
- (TRC_BLK_REG_ADDR + 0x080 + ((_num) << 2))
-
-/**
- * TRC Store Match filters, total 10
- * Determines the store conditions
- */
-#define TRC_STRM_REG(_num) \
- (TRC_BLK_REG_ADDR + 0x0C0 + ((_num) << 2))
-
-/* DOORBELLS ACCESS */
-
-/**
- * Catapult doorbells
- * Each doorbell-queue set has
- * 1 RxQ, 1 TxQ, 2 IBs in that order
- * Size of each entry in 32 bytes, even though only 1 word
- * is used. For Non-VM case each doorbell-q set is
- * separated by 128 bytes, for VM case it is separated
- * by 4K bytes
- * Non VM case Range : 0x38000 - 0x39FFF
- * VM case Range : 0x100000 - 0x11FFFF
- * The range applies to both HQMs
- */
-#define HQM_DOORBELL_BLK_BASE_ADDR 0x00038000
-#define HQM_DOORBELL_VM_BLK_BASE_ADDR 0x00100000
-
-/* MEMORY ACCESS */
-
-/**
- * Catapult H/W Block Memory Access Address
- * To the host a memory space of 32K (page) is visible
- * at a time. The address range is from 0x08000 to 0x0FFFF
- */
-#define HW_BLK_HOST_MEM_ADDR 0x08000
-
-/**
- * Catapult LUT Memory Access Page Numbers
- * Range : LUT0 0xa0-0xa1
- * LUT1 0xa2-0xa3
- */
-#define LUT0_MEM_BLK_BASE_PG_NUM 0x000000A0
-#define LUT1_MEM_BLK_BASE_PG_NUM 0x000000A2
-
-/**
- * Catapult RxFn Database Memory Block Base Offset
- *
- * The Rx function database exists in LUT block.
- * In PCIe space this is accessible as a 256x32
- * bit block. Each entry in this database is 4
- * (4 byte) words. Max. entries is 64.
- * Address of an entry corresponding to a function
- * = base_addr + (function_no. * 16)
- */
-#define RX_FNDB_RAM_BASE_OFFSET 0x0000B400
-
-/**
- * Catapult TxFn Database Memory Block Base Offset Address
- *
- * The Tx function database exists in LUT block.
- * In PCIe space this is accessible as a 64x32
- * bit block. Each entry in this database is 1
- * (4 byte) word. Max. entries is 64.
- * Address of an entry corresponding to a function
- * = base_addr + (function_no. * 4)
- */
-#define TX_FNDB_RAM_BASE_OFFSET 0x0000B800
-
-/**
- * Catapult Unicast CAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Shared by both the LL & FCoE driver.
- * Size is 256x48 bits; mapped to PCIe space
- * 512x32 bit blocks. For each address, bits
- * are written in the order : [47:32] and then
- * [31:0].
- */
-#define UCAST_CAM_BASE_OFFSET 0x0000A800
-
-/**
- * Catapult Unicast RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Shared by both the LL & FCoE driver.
- * Size is 256x9 bits.
- */
-#define UCAST_RAM_BASE_OFFSET 0x0000B000
-
-/**
- * Catapult Mulicast CAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Shared by both the LL & FCoE driver.
- * Size is 256x48 bits; mapped to PCIe space
- * 512x32 bit blocks. For each address, bits
- * are written in the order : [47:32] and then
- * [31:0].
- */
-#define MCAST_CAM_BASE_OFFSET 0x0000A000
-
-/**
- * Catapult VLAN RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Size is 4096x66 bits; mapped to PCIe space as
- * 8192x32 bit blocks.
- * All the 4K entries are within the address range
- * 0x0000 to 0x8000, so in the first LUT page.
- */
-#define VLAN_RAM_BASE_OFFSET 0x00000000
-
-/**
- * Catapult Tx Stats RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Size is 1024x33 bits;
- * Each Tx function has 64 bytes of space
- */
-#define TX_STATS_RAM_BASE_OFFSET 0x00009000
-
-/**
- * Catapult Rx Stats RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Size is 1024x33 bits;
- * Each Rx function has 64 bytes of space
- */
-#define RX_STATS_RAM_BASE_OFFSET 0x00008000
-
-/* Catapult RXA Memory Access Page Numbers */
-#define RXA0_MEM_BLK_BASE_PG_NUM 0x0000008C
-#define RXA1_MEM_BLK_BASE_PG_NUM 0x0000008D
-
-/**
- * Catapult Multicast Vector Table Base Offset Address
- *
- * Exists in RxA memory space.
- * Organized as 512x65 bit block.
- * However for each entry 16 bytes allocated (power of 2)
- * Total size 512*16 bytes.
- * There are two logical divisions, 256 entries each :
- * a) Entries 0x00 to 0xff (256) -- Approx. MVT
- * Offset 0x000 to 0xFFF
- * b) Entries 0x100 to 0x1ff (256) -- Exact MVT
- * Offsets 0x1000 to 0x1FFF
- */
-#define MCAST_APPROX_MVT_BASE_OFFSET 0x00000000
-#define MCAST_EXACT_MVT_BASE_OFFSET 0x00001000
-
-/**
- * Catapult RxQ Translate Table (RIT) Base Offset Address
- *
- * Exists in RxA memory space
- * Total no. of entries 64
- * Each entry is 1 (4 byte) word.
- * 31:12 -- Reserved
- * 11:0 -- Two 6 bit RxQ Ids
- */
-#define FUNCTION_TO_RXQ_TRANSLATE 0x00002000
-
-/* Catapult RxAdm (RAD) Memory Access Page Numbers */
-#define RAD0_MEM_BLK_BASE_PG_NUM 0x00000086
-#define RAD1_MEM_BLK_BASE_PG_NUM 0x00000087
-
-/**
- * Catapult RSS Table Base Offset Address
- *
- * Exists in RAD memory space.
- * Each entry is 352 bits, but aligned on
- * 64 byte (512 bit) boundary. Accessed
- * 4 byte words, the whole entry can be
- * broken into 11 word accesses.
- */
-#define RSS_TABLE_BASE_OFFSET 0x00000800
-
-/**
- * Catapult CPQ Block Page Number
- * This value is written to the page number registers
- * to access the memory associated with the mailboxes.
- */
-#define CPQ_BLK_PG_NUM 0x00000005
-
-/**
- * Clarification :
- * LL functions are 2 & 3; can HostFn0/HostFn1
- * <-> LPU0/LPU1 memories be used ?
- */
-/**
- * Catapult HostFn0/HostFn1 to LPU0/LPU1 Mbox memory
- * Per catapult_spec.pdf, the offset of the mbox
- * memory is in the register space at an offset of 0x200
- */
-#define CPQ_BLK_REG_MBOX_ADDR (CPQ_BLK_REG_ADDR + 0x200)
-
-#define HOSTFN_LPU_MBOX (CPQ_BLK_REG_MBOX_ADDR + 0x000)
-
-/* Catapult LPU0/LPU1 to HostFn0/HostFn1 Mbox memory */
-#define LPU_HOSTFN_MBOX (CPQ_BLK_REG_MBOX_ADDR + 0x080)
-
-/**
- * Catapult HQM Block Page Number
- * This is written to the page number register for
- * the appropriate function to access the memory
- * associated with HQM
- */
-#define HQM0_BLK_PG_NUM 0x00000096
-#define HQM1_BLK_PG_NUM 0x00000097
-
-/**
- * Note that TxQ and RxQ entries are interlaced
- * the HQM memory, i.e RXQ0, TXQ0, RXQ1, TXQ1.. etc.
- */
-
-#define HQM_RXTX_Q_RAM_BASE_OFFSET 0x00004000
-
-/**
- * CQ Memory
- * Exists in HQM Memory space
- * Each entry is 16 (4 byte) words of which
- * only 12 words are used for configuration
- * Total 64 entries per HQM memory space
- */
-#define HQM_CQ_RAM_BASE_OFFSET 0x00006000
-
-/**
- * Interrupt Block (IB) Memory
- * Exists in HQM Memory space
- * Each entry is 8 (4 byte) words of which
- * only 5 words are used for configuration
- * Total 128 entries per HQM memory space
- */
-#define HQM_IB_RAM_BASE_OFFSET 0x00001000
-
-/**
- * Index Table (IT) Memory
- * Exists in HQM Memory space
- * Each entry is 1 (4 byte) word which
- * is used for configuration
- * Total 128 entries per HQM memory space
- */
-#define HQM_INDX_TBL_RAM_BASE_OFFSET 0x00002000
-
-/**
- * PSS Block Memory Page Number
- * This is written to the appropriate page number
- * register to access the CPU memory.
- * Also known as the PSS secondary memory (SMEM).
- * Range : 0x180 to 0x1CF
- * See catapult_spec.pdf for details
- */
-#define PSS_BLK_PG_NUM 0x00000180
-
-/**
- * Offsets of different instances of PSS SMEM
- * 2.5M of continuous 1T memory space : 2 blocks
- * of 1M each (32 pages each, page=32KB) and 4 smaller
- * blocks of 128K each (4 pages each, page=32KB)
- * PSS_LMEM_INST0 is used for firmware download
- */
-#define PSS_LMEM_INST0 0x00000000
-#define PSS_LMEM_INST1 0x00100000
-#define PSS_LMEM_INST2 0x00200000
-#define PSS_LMEM_INST3 0x00220000
-#define PSS_LMEM_INST4 0x00240000
-#define PSS_LMEM_INST5 0x00260000
-
-#define BNA_PCI_REG_CT_ADDRSZ (0x40000)
-
-#define BNA_GET_PAGE_NUM(_base_page, _offset) \
- ((_base_page) + ((_offset) >> 15))
-
-#define BNA_GET_PAGE_OFFSET(_offset) \
- ((_offset) & 0x7fff)
-
-#define BNA_GET_MEM_BASE_ADDR(_bar0, _base_offset) \
- ((_bar0) + HW_BLK_HOST_MEM_ADDR \
- + BNA_GET_PAGE_OFFSET((_base_offset)))
-
-#define BNA_GET_VLAN_MEM_ENTRY_ADDR(_bar0, _fn_id, _vlan_id)\
- (_bar0 + (HW_BLK_HOST_MEM_ADDR) \
- + (BNA_GET_PAGE_OFFSET(VLAN_RAM_BASE_OFFSET)) \
- + (((_fn_id) & 0x3f) << 9) \
- + (((_vlan_id) & 0xfe0) >> 3))
-
-/**
- *
- * Interrupt related bits, flags and macros
- *
- */
-
-#define __LPU02HOST_MBOX0_STATUS_BITS 0x00100000
-#define __LPU12HOST_MBOX0_STATUS_BITS 0x00200000
-#define __LPU02HOST_MBOX1_STATUS_BITS 0x00400000
-#define __LPU12HOST_MBOX1_STATUS_BITS 0x00800000
-
-#define __LPU02HOST_MBOX0_MASK_BITS 0x00100000
-#define __LPU12HOST_MBOX0_MASK_BITS 0x00200000
-#define __LPU02HOST_MBOX1_MASK_BITS 0x00400000
-#define __LPU12HOST_MBOX1_MASK_BITS 0x00800000
-
-#define __LPU2HOST_MBOX_MASK_BITS \
- (__LPU02HOST_MBOX0_MASK_BITS | __LPU02HOST_MBOX1_MASK_BITS | \
- __LPU12HOST_MBOX0_MASK_BITS | __LPU12HOST_MBOX1_MASK_BITS)
-
-#define __LPU2HOST_IB_STATUS_BITS 0x0000ffff
-
-#define BNA_IS_LPU0_MBOX_INTR(_intr_status) \
- ((_intr_status) & (__LPU02HOST_MBOX0_STATUS_BITS | \
- __LPU02HOST_MBOX1_STATUS_BITS))
-
-#define BNA_IS_LPU1_MBOX_INTR(_intr_status) \
- ((_intr_status) & (__LPU12HOST_MBOX0_STATUS_BITS | \
- __LPU12HOST_MBOX1_STATUS_BITS))
-
-#define BNA_IS_MBOX_INTR(_intr_status) \
- ((_intr_status) & \
- (__LPU02HOST_MBOX0_STATUS_BITS | \
- __LPU02HOST_MBOX1_STATUS_BITS | \
- __LPU12HOST_MBOX0_STATUS_BITS | \
- __LPU12HOST_MBOX1_STATUS_BITS))
-
-#define __EMC_ERROR_STATUS_BITS 0x00010000
-#define __LPU0_ERROR_STATUS_BITS 0x00020000
-#define __LPU1_ERROR_STATUS_BITS 0x00040000
-#define __PSS_ERROR_STATUS_BITS 0x00080000
-
-#define __HALT_STATUS_BITS 0x01000000
-
-#define __EMC_ERROR_MASK_BITS 0x00010000
-#define __LPU0_ERROR_MASK_BITS 0x00020000
-#define __LPU1_ERROR_MASK_BITS 0x00040000
-#define __PSS_ERROR_MASK_BITS 0x00080000
-
-#define __HALT_MASK_BITS 0x01000000
-
-#define __ERROR_MASK_BITS \
- (__EMC_ERROR_MASK_BITS | __LPU0_ERROR_MASK_BITS | \
- __LPU1_ERROR_MASK_BITS | __PSS_ERROR_MASK_BITS | \
- __HALT_MASK_BITS)
-
-#define BNA_IS_ERR_INTR(_intr_status) \
- ((_intr_status) & \
- (__EMC_ERROR_STATUS_BITS | \
- __LPU0_ERROR_STATUS_BITS | \
- __LPU1_ERROR_STATUS_BITS | \
- __PSS_ERROR_STATUS_BITS | \
- __HALT_STATUS_BITS))
-
-#define BNA_IS_MBOX_ERR_INTR(_intr_status) \
- (BNA_IS_MBOX_INTR((_intr_status)) | \
- BNA_IS_ERR_INTR((_intr_status)))
-
-#define BNA_IS_INTX_DATA_INTR(_intr_status) \
- ((_intr_status) & __LPU2HOST_IB_STATUS_BITS)
-
-#define BNA_INTR_STATUS_MBOX_CLR(_intr_status) \
-do { \
- (_intr_status) &= ~(__LPU02HOST_MBOX0_STATUS_BITS | \
- __LPU02HOST_MBOX1_STATUS_BITS | \
- __LPU12HOST_MBOX0_STATUS_BITS | \
- __LPU12HOST_MBOX1_STATUS_BITS); \
-} while (0)
-
-#define BNA_INTR_STATUS_ERR_CLR(_intr_status) \
-do { \
- (_intr_status) &= ~(__EMC_ERROR_STATUS_BITS | \
- __LPU0_ERROR_STATUS_BITS | \
- __LPU1_ERROR_STATUS_BITS | \
- __PSS_ERROR_STATUS_BITS | \
- __HALT_STATUS_BITS); \
-} while (0)
-
-#define bna_intx_disable(_bna, _cur_mask) \
-{ \
- (_cur_mask) = readl((_bna)->regs.fn_int_mask);\
- writel(0xffffffff, (_bna)->regs.fn_int_mask);\
-}
-
-#define bna_intx_enable(bna, new_mask) \
- writel((new_mask), (bna)->regs.fn_int_mask)
-
-#define bna_mbox_intr_disable(bna) \
- writel((readl((bna)->regs.fn_int_mask) | \
- (__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \
- (bna)->regs.fn_int_mask)
-
-#define bna_mbox_intr_enable(bna) \
- writel((readl((bna)->regs.fn_int_mask) & \
- ~(__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \
- (bna)->regs.fn_int_mask)
-
-#define bna_intr_status_get(_bna, _status) \
-{ \
- (_status) = readl((_bna)->regs.fn_int_status); \
- if ((_status)) { \
- writel((_status) & ~(__LPU02HOST_MBOX0_STATUS_BITS |\
- __LPU02HOST_MBOX1_STATUS_BITS |\
- __LPU12HOST_MBOX0_STATUS_BITS |\
- __LPU12HOST_MBOX1_STATUS_BITS), \
- (_bna)->regs.fn_int_status);\
- } \
-}
-
-#define bna_intr_status_get_no_clr(_bna, _status) \
- (_status) = readl((_bna)->regs.fn_int_status)
-
-#define bna_intr_mask_get(bna, mask) \
- (*mask) = readl((bna)->regs.fn_int_mask)
-
-#define bna_intr_ack(bna, intr_bmap) \
- writel((intr_bmap), (bna)->regs.fn_int_status)
-
-#define bna_ib_intx_disable(bna, ib_id) \
- writel(readl((bna)->regs.fn_int_mask) | \
- (1 << (ib_id)), \
- (bna)->regs.fn_int_mask)
-
-#define bna_ib_intx_enable(bna, ib_id) \
- writel(readl((bna)->regs.fn_int_mask) & \
- ~(1 << (ib_id)), \
- (bna)->regs.fn_int_mask)
-
-#define bna_mbox_msix_idx_set(_device) \
-do {\
- writel(((_device)->vector & 0x000001FF), \
- (_device)->bna->pcidev.pci_bar_kva + \
- reg_offset[(_device)->bna->pcidev.pci_func].msix_idx);\
-} while (0)
-
-/**
- *
- * TxQ, RxQ, CQ related bits, offsets, macros
- *
- */
-
-#define BNA_Q_IDLE_STATE 0x00008001
-
-#define BNA_GET_DOORBELL_BASE_ADDR(_bar0) \
- ((_bar0) + HQM_DOORBELL_BLK_BASE_ADDR)
-
-#define BNA_GET_DOORBELL_ENTRY_OFFSET(_entry) \
- ((HQM_DOORBELL_BLK_BASE_ADDR) \
- + (_entry << 7))
-
-#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
- (0x80000000 | ((_timeout) << 16) | (_events))
-
-#define BNA_DOORBELL_IB_INT_DISABLE (0x40000000)
-
-/* TxQ Entry Opcodes */
-#define BNA_TXQ_WI_SEND (0x402) /* Single Frame Transmission */
-#define BNA_TXQ_WI_SEND_LSO (0x403) /* Multi-Frame Transmission */
-#define BNA_TXQ_WI_EXTENSION (0x104) /* Extension WI */
-
-/* TxQ Entry Control Flags */
-#define BNA_TXQ_WI_CF_FCOE_CRC (1 << 8)
-#define BNA_TXQ_WI_CF_IPID_MODE (1 << 5)
-#define BNA_TXQ_WI_CF_INS_PRIO (1 << 4)
-#define BNA_TXQ_WI_CF_INS_VLAN (1 << 3)
-#define BNA_TXQ_WI_CF_UDP_CKSUM (1 << 2)
-#define BNA_TXQ_WI_CF_TCP_CKSUM (1 << 1)
-#define BNA_TXQ_WI_CF_IP_CKSUM (1 << 0)
-
-#define BNA_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
- (((_hdr_size) << 10) | ((_offset) & 0x3FF))
-
-/*
- * Completion Q defines
- */
-/* CQ Entry Flags */
-#define BNA_CQ_EF_MAC_ERROR (1 << 0)
-#define BNA_CQ_EF_FCS_ERROR (1 << 1)
-#define BNA_CQ_EF_TOO_LONG (1 << 2)
-#define BNA_CQ_EF_FC_CRC_OK (1 << 3)
-
-#define BNA_CQ_EF_RSVD1 (1 << 4)
-#define BNA_CQ_EF_L4_CKSUM_OK (1 << 5)
-#define BNA_CQ_EF_L3_CKSUM_OK (1 << 6)
-#define BNA_CQ_EF_HDS_HEADER (1 << 7)
-
-#define BNA_CQ_EF_UDP (1 << 8)
-#define BNA_CQ_EF_TCP (1 << 9)
-#define BNA_CQ_EF_IP_OPTIONS (1 << 10)
-#define BNA_CQ_EF_IPV6 (1 << 11)
-
-#define BNA_CQ_EF_IPV4 (1 << 12)
-#define BNA_CQ_EF_VLAN (1 << 13)
-#define BNA_CQ_EF_RSS (1 << 14)
-#define BNA_CQ_EF_RSVD2 (1 << 15)
-
-#define BNA_CQ_EF_MCAST_MATCH (1 << 16)
-#define BNA_CQ_EF_MCAST (1 << 17)
-#define BNA_CQ_EF_BCAST (1 << 18)
-#define BNA_CQ_EF_REMOTE (1 << 19)
-
-#define BNA_CQ_EF_LOCAL (1 << 20)
-
-/**
- *
- * Data structures
- *
- */
-
-enum txf_flags {
- BFI_TXF_CF_ENABLE = 1 << 0,
- BFI_TXF_CF_VLAN_FILTER = 1 << 8,
- BFI_TXF_CF_VLAN_ADMIT = 1 << 9,
- BFI_TXF_CF_VLAN_INSERT = 1 << 10,
- BFI_TXF_CF_RSVD1 = 1 << 11,
- BFI_TXF_CF_MAC_SA_CHECK = 1 << 12,
- BFI_TXF_CF_VLAN_WI_BASED = 1 << 13,
- BFI_TXF_CF_VSWITCH_MCAST = 1 << 14,
- BFI_TXF_CF_VSWITCH_UCAST = 1 << 15,
- BFI_TXF_CF_RSVD2 = 0x7F << 1
-};
-
-enum ib_flags {
- BFI_IB_CF_MASTER_ENABLE = (1 << 0),
- BFI_IB_CF_MSIX_MODE = (1 << 1),
- BFI_IB_CF_COALESCING_MODE = (1 << 2),
- BFI_IB_CF_INTER_PKT_ENABLE = (1 << 3),
- BFI_IB_CF_INT_ENABLE = (1 << 4),
- BFI_IB_CF_INTER_PKT_DMA = (1 << 5),
- BFI_IB_CF_ACK_PENDING = (1 << 6),
- BFI_IB_CF_RESERVED1 = (1 << 7)
-};
-
-enum rss_hash_type {
- BFI_RSS_T_V4_TCP = (1 << 11),
- BFI_RSS_T_V4_IP = (1 << 10),
- BFI_RSS_T_V6_TCP = (1 << 9),
- BFI_RSS_T_V6_IP = (1 << 8)
-};
-enum hds_header_type {
- BNA_HDS_T_V4_TCP = (1 << 11),
- BNA_HDS_T_V4_UDP = (1 << 10),
- BNA_HDS_T_V6_TCP = (1 << 9),
- BNA_HDS_T_V6_UDP = (1 << 8),
- BNA_HDS_FORCED = (1 << 7),
-};
-enum rxf_flags {
- BNA_RXF_CF_SM_LG_RXQ = (1 << 15),
- BNA_RXF_CF_DEFAULT_VLAN = (1 << 14),
- BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE = (1 << 13),
- BNA_RXF_CF_VLAN_STRIP = (1 << 12),
- BNA_RXF_CF_RSS_ENABLE = (1 << 8)
-};
-struct bna_chip_regs_offset {
- u32 page_addr;
- u32 fn_int_status;
- u32 fn_int_mask;
- u32 msix_idx;
-};
-
-struct bna_chip_regs {
- void __iomem *page_addr;
- void __iomem *fn_int_status;
- void __iomem *fn_int_mask;
-};
-
-struct bna_txq_mem {
- u32 pg_tbl_addr_lo;
- u32 pg_tbl_addr_hi;
- u32 cur_q_entry_lo;
- u32 cur_q_entry_hi;
- u32 reserved1;
- u32 reserved2;
- u32 pg_cnt_n_prd_ptr; /* 31:16->total page count */
- /* 15:0 ->producer pointer (index?) */
- u32 entry_n_pg_size; /* 31:16->entry size */
- /* 15:0 ->page size */
- u32 int_blk_n_cns_ptr; /* 31:24->Int Blk Id; */
- /* 23:16->Int Blk Offset */
- /* 15:0 ->consumer pointer(index?) */
- u32 cns_ptr2_n_q_state; /* 31:16->cons. ptr 2; 15:0-> Q state */
- u32 nxt_qid_n_fid_n_pri; /* 17:10->next */
- /* QId;9:3->FID;2:0->Priority */
- u32 wvc_n_cquota_n_rquota; /* 31:24->WI Vector Count; */
- /* 23:12->Cfg Quota; */
- /* 11:0 ->Run Quota */
- u32 reserved3[4];
-};
-
-struct bna_rxq_mem {
- u32 pg_tbl_addr_lo;
- u32 pg_tbl_addr_hi;
- u32 cur_q_entry_lo;
- u32 cur_q_entry_hi;
- u32 reserved1;
- u32 reserved2;
- u32 pg_cnt_n_prd_ptr; /* 31:16->total page count */
- /* 15:0 ->producer pointer (index?) */
- u32 entry_n_pg_size; /* 31:16->entry size */
- /* 15:0 ->page size */
- u32 sg_n_cq_n_cns_ptr; /* 31:28->reserved; 27:24->sg count */
- /* 23:16->CQ; */
- /* 15:0->consumer pointer(index?) */
- u32 buf_sz_n_q_state; /* 31:16->buffer size; 15:0-> Q state */
- u32 next_qid; /* 17:10->next QId */
- u32 reserved3;
- u32 reserved4[4];
-};
-
-struct bna_rxtx_q_mem {
- struct bna_rxq_mem rxq;
- struct bna_txq_mem txq;
-};
-
-struct bna_cq_mem {
- u32 pg_tbl_addr_lo;
- u32 pg_tbl_addr_hi;
- u32 cur_q_entry_lo;
- u32 cur_q_entry_hi;
-
- u32 reserved1;
- u32 reserved2;
- u32 pg_cnt_n_prd_ptr; /* 31:16->total page count */
- /* 15:0 ->producer pointer (index?) */
- u32 entry_n_pg_size; /* 31:16->entry size */
- /* 15:0 ->page size */
- u32 int_blk_n_cns_ptr; /* 31:24->Int Blk Id; */
- /* 23:16->Int Blk Offset */
- /* 15:0 ->consumer pointer(index?) */
- u32 q_state; /* 31:16->reserved; 15:0-> Q state */
- u32 reserved3[2];
- u32 reserved4[4];
-};
-
-struct bna_ib_blk_mem {
- u32 host_addr_lo;
- u32 host_addr_hi;
- u32 clsc_n_ctrl_n_msix; /* 31:24->coalescing; */
- /* 23:16->coalescing cfg; */
- /* 15:8 ->control; */
- /* 7:0 ->msix; */
- u32 ipkt_n_ent_n_idxof;
- u32 ipkt_cnt_cfg_n_unacked;
-
- u32 reserved[3];
-};
-
-struct bna_idx_tbl_mem {
- u32 idx; /* !< 31:16->res;15:0->idx; */
-};
-
-struct bna_doorbell_qset {
- u32 rxq[0x20 >> 2];
- u32 txq[0x20 >> 2];
- u32 ib0[0x20 >> 2];
- u32 ib1[0x20 >> 2];
-};
-
-struct bna_rx_fndb_ram {
- u32 rss_prop;
- u32 size_routing_props;
- u32 rit_hds_mcastq;
- u32 control_flags;
-};
-
-struct bna_tx_fndb_ram {
- u32 vlan_n_ctrl_flags;
-};
-
-/**
- * @brief
- * Structure which maps to RxFn Indirection Table (RIT)
- * Size : 1 word
- * See catapult_spec.pdf, RxA for details
- */
-struct bna_rit_mem {
- u32 rxq_ids; /* !< 31:12->res;11:0->two 6 bit RxQ Ids */
-};
-
-/**
- * @brief
- * Structure which maps to RSS Table entry
- * Size : 16 words
- * See catapult_spec.pdf, RAD for details
- */
-struct bna_rss_mem {
- /*
- * 31:12-> res
- * 11:8 -> protocol type
- * 7:0 -> hash index
- */
- u32 type_n_hash;
- u32 hash_key[10]; /* !< 40 byte Toeplitz hash key */
- u32 reserved[5];
-};
-
-/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */
-struct bna_dma_addr {
- u32 msb;
- u32 lsb;
-};
-
-struct bna_txq_wi_vector {
- u16 reserved;
- u16 length; /* Only 14 LSB are valid */
- struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */
-};
-
-typedef u16 bna_txq_wi_opcode_t;
-
-typedef u16 bna_txq_wi_ctrl_flag_t;
-
-/**
- * TxQ Entry Structure
- *
- * BEWARE: Load values into this structure with correct endianess.
- */
-struct bna_txq_entry {
- union {
- struct {
- u8 reserved;
- u8 num_vectors; /* number of vectors present */
- bna_txq_wi_opcode_t opcode; /* Either */
- /* BNA_TXQ_WI_SEND or */
- /* BNA_TXQ_WI_SEND_LSO */
- bna_txq_wi_ctrl_flag_t flags; /* OR of all the flags */
- u16 l4_hdr_size_n_offset;
- u16 vlan_tag;
- u16 lso_mss; /* Only 14 LSB are valid */
- u32 frame_length; /* Only 24 LSB are valid */
- } wi;
-
- struct {
- u16 reserved;
- bna_txq_wi_opcode_t opcode; /* Must be */
- /* BNA_TXQ_WI_EXTENSION */
- u32 reserved2[3]; /* Place holder for */
- /* removed vector (12 bytes) */
- } wi_ext;
- } hdr;
- struct bna_txq_wi_vector vector[4];
-};
-#define wi_hdr hdr.wi
-#define wi_ext_hdr hdr.wi_ext
-
-/* RxQ Entry Structure */
-struct bna_rxq_entry { /* Rx-Buffer */
- struct bna_dma_addr host_addr; /* Rx-Buffer DMA address */
-};
-
-typedef u32 bna_cq_e_flag_t;
-
-/* CQ Entry Structure */
-struct bna_cq_entry {
- bna_cq_e_flag_t flags;
- u16 vlan_tag;
- u16 length;
- u32 rss_hash;
- u8 valid;
- u8 reserved1;
- u8 reserved2;
- u8 rxq_id;
-};
-
-#endif /* __BNA_HW_H__ */
diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c
deleted file mode 100644
index f0983c832447..000000000000
--- a/drivers/net/bna/bna_txrx.c
+++ /dev/null
@@ -1,4185 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#include "bna.h"
-#include "bfa_cs.h"
-#include "bfi.h"
-
-/**
- * IB
- */
-#define bna_ib_find_free_ibidx(_mask, _pos)\
-do {\
- (_pos) = 0;\
- while (((_pos) < (BFI_IBIDX_MAX_SEGSIZE)) &&\
- ((1 << (_pos)) & (_mask)))\
- (_pos)++;\
-} while (0)
-
-#define bna_ib_count_ibidx(_mask, _count)\
-do {\
- int pos = 0;\
- (_count) = 0;\
- while (pos < (BFI_IBIDX_MAX_SEGSIZE)) {\
- if ((1 << pos) & (_mask))\
- (_count) = pos + 1;\
- pos++;\
- } \
-} while (0)
-
-#define bna_ib_select_segpool(_count, _q_idx)\
-do {\
- int i;\
- (_q_idx) = -1;\
- for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {\
- if ((_count <= ibidx_pool[i].pool_entry_size)) {\
- (_q_idx) = i;\
- break;\
- } \
- } \
-} while (0)
-
-struct bna_ibidx_pool {
- int pool_size;
- int pool_entry_size;
-};
-init_ibidx_pool(ibidx_pool);
-
-static struct bna_intr *
-bna_intr_get(struct bna_ib_mod *ib_mod, enum bna_intr_type intr_type,
- int vector)
-{
- struct bna_intr *intr;
- struct list_head *qe;
-
- list_for_each(qe, &ib_mod->intr_active_q) {
- intr = (struct bna_intr *)qe;
-
- if ((intr->intr_type == intr_type) &&
- (intr->vector == vector)) {
- intr->ref_count++;
- return intr;
- }
- }
-
- if (list_empty(&ib_mod->intr_free_q))
- return NULL;
-
- bfa_q_deq(&ib_mod->intr_free_q, &intr);
- bfa_q_qe_init(&intr->qe);
-
- intr->ref_count = 1;
- intr->intr_type = intr_type;
- intr->vector = vector;
-
- list_add_tail(&intr->qe, &ib_mod->intr_active_q);
-
- return intr;
-}
-
-static void
-bna_intr_put(struct bna_ib_mod *ib_mod,
- struct bna_intr *intr)
-{
- intr->ref_count--;
-
- if (intr->ref_count == 0) {
- intr->ib = NULL;
- list_del(&intr->qe);
- bfa_q_qe_init(&intr->qe);
- list_add_tail(&intr->qe, &ib_mod->intr_free_q);
- }
-}
-
-void
-bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna,
- struct bna_res_info *res_info)
-{
- int i;
- int j;
- int count;
- u8 offset;
- struct bna_doorbell_qset *qset;
- unsigned long off;
-
- ib_mod->bna = bna;
-
- ib_mod->ib = (struct bna_ib *)
- res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mdl[0].kva;
- ib_mod->intr = (struct bna_intr *)
- res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mdl[0].kva;
- ib_mod->idx_seg = (struct bna_ibidx_seg *)
- res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mdl[0].kva;
-
- INIT_LIST_HEAD(&ib_mod->ib_free_q);
- INIT_LIST_HEAD(&ib_mod->intr_free_q);
- INIT_LIST_HEAD(&ib_mod->intr_active_q);
-
- for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++)
- INIT_LIST_HEAD(&ib_mod->ibidx_seg_pool[i]);
-
- for (i = 0; i < BFI_MAX_IB; i++) {
- ib_mod->ib[i].ib_id = i;
-
- ib_mod->ib[i].ib_seg_host_addr_kva =
- res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].kva;
- ib_mod->ib[i].ib_seg_host_addr.lsb =
- res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.lsb;
- ib_mod->ib[i].ib_seg_host_addr.msb =
- res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.msb;
-
- qset = (struct bna_doorbell_qset *)0;
- off = (unsigned long)(&qset[i >> 1].ib0[(i & 0x1)
- * (0x20 >> 2)]);
- ib_mod->ib[i].door_bell.doorbell_addr = off +
- BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva);
-
- bfa_q_qe_init(&ib_mod->ib[i].qe);
- list_add_tail(&ib_mod->ib[i].qe, &ib_mod->ib_free_q);
-
- bfa_q_qe_init(&ib_mod->intr[i].qe);
- list_add_tail(&ib_mod->intr[i].qe, &ib_mod->intr_free_q);
- }
-
- count = 0;
- offset = 0;
- for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {
- for (j = 0; j < ibidx_pool[i].pool_size; j++) {
- bfa_q_qe_init(&ib_mod->idx_seg[count]);
- ib_mod->idx_seg[count].ib_seg_size =
- ibidx_pool[i].pool_entry_size;
- ib_mod->idx_seg[count].ib_idx_tbl_offset = offset;
- list_add_tail(&ib_mod->idx_seg[count].qe,
- &ib_mod->ibidx_seg_pool[i]);
- count++;
- offset += ibidx_pool[i].pool_entry_size;
- }
- }
-}
-
-void
-bna_ib_mod_uninit(struct bna_ib_mod *ib_mod)
-{
- int i;
- int j;
- struct list_head *qe;
-
- i = 0;
- list_for_each(qe, &ib_mod->ib_free_q)
- i++;
-
- i = 0;
- list_for_each(qe, &ib_mod->intr_free_q)
- i++;
-
- for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {
- j = 0;
- list_for_each(qe, &ib_mod->ibidx_seg_pool[i])
- j++;
- }
-
- ib_mod->bna = NULL;
-}
-
-static struct bna_ib *
-bna_ib_get(struct bna_ib_mod *ib_mod,
- enum bna_intr_type intr_type,
- int vector)
-{
- struct bna_ib *ib;
- struct bna_intr *intr;
-
- if (intr_type == BNA_INTR_T_INTX)
- vector = (1 << vector);
-
- intr = bna_intr_get(ib_mod, intr_type, vector);
- if (intr == NULL)
- return NULL;
-
- if (intr->ib) {
- if (intr->ib->ref_count == BFI_IBIDX_MAX_SEGSIZE) {
- bna_intr_put(ib_mod, intr);
- return NULL;
- }
- intr->ib->ref_count++;
- return intr->ib;
- }
-
- if (list_empty(&ib_mod->ib_free_q)) {
- bna_intr_put(ib_mod, intr);
- return NULL;
- }
-
- bfa_q_deq(&ib_mod->ib_free_q, &ib);
- bfa_q_qe_init(&ib->qe);
-
- ib->ref_count = 1;
- ib->start_count = 0;
- ib->idx_mask = 0;
-
- ib->intr = intr;
- ib->idx_seg = NULL;
- intr->ib = ib;
-
- ib->bna = ib_mod->bna;
-
- return ib;
-}
-
-static void
-bna_ib_put(struct bna_ib_mod *ib_mod, struct bna_ib *ib)
-{
- bna_intr_put(ib_mod, ib->intr);
-
- ib->ref_count--;
-
- if (ib->ref_count == 0) {
- ib->intr = NULL;
- ib->bna = NULL;
- list_add_tail(&ib->qe, &ib_mod->ib_free_q);
- }
-}
-
-/* Returns index offset - starting from 0 */
-static int
-bna_ib_reserve_idx(struct bna_ib *ib)
-{
- struct bna_ib_mod *ib_mod = &ib->bna->ib_mod;
- struct bna_ibidx_seg *idx_seg;
- int idx;
- int num_idx;
- int q_idx;
-
- /* Find the first free index position */
- bna_ib_find_free_ibidx(ib->idx_mask, idx);
- if (idx == BFI_IBIDX_MAX_SEGSIZE)
- return -1;
-
- /*
- * Calculate the total number of indexes held by this IB,
- * including the index newly reserved above.
- */
- bna_ib_count_ibidx((ib->idx_mask | (1 << idx)), num_idx);
-
- /* See if there is a free space in the index segment held by this IB */
- if (ib->idx_seg && (num_idx <= ib->idx_seg->ib_seg_size)) {
- ib->idx_mask |= (1 << idx);
- return idx;
- }
-
- if (ib->start_count)
- return -1;
-
- /* Allocate a new segment */
- bna_ib_select_segpool(num_idx, q_idx);
- while (1) {
- if (q_idx == BFI_IBIDX_TOTAL_POOLS)
- return -1;
- if (!list_empty(&ib_mod->ibidx_seg_pool[q_idx]))
- break;
- q_idx++;
- }
- bfa_q_deq(&ib_mod->ibidx_seg_pool[q_idx], &idx_seg);
- bfa_q_qe_init(&idx_seg->qe);
-
- /* Free the old segment */
- if (ib->idx_seg) {
- bna_ib_select_segpool(ib->idx_seg->ib_seg_size, q_idx);
- list_add_tail(&ib->idx_seg->qe, &ib_mod->ibidx_seg_pool[q_idx]);
- }
-
- ib->idx_seg = idx_seg;
-
- ib->idx_mask |= (1 << idx);
-
- return idx;
-}
-
-static void
-bna_ib_release_idx(struct bna_ib *ib, int idx)
-{
- struct bna_ib_mod *ib_mod = &ib->bna->ib_mod;
- struct bna_ibidx_seg *idx_seg;
- int num_idx;
- int cur_q_idx;
- int new_q_idx;
-
- ib->idx_mask &= ~(1 << idx);
-
- if (ib->start_count)
- return;
-
- bna_ib_count_ibidx(ib->idx_mask, num_idx);
-
- /*
- * Free the segment, if there are no more indexes in the segment
- * held by this IB
- */
- if (!num_idx) {
- bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx);
- list_add_tail(&ib->idx_seg->qe,
- &ib_mod->ibidx_seg_pool[cur_q_idx]);
- ib->idx_seg = NULL;
- return;
- }
-
- /* See if we can move to a smaller segment */
- bna_ib_select_segpool(num_idx, new_q_idx);
- bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx);
- while (new_q_idx < cur_q_idx) {
- if (!list_empty(&ib_mod->ibidx_seg_pool[new_q_idx]))
- break;
- new_q_idx++;
- }
- if (new_q_idx < cur_q_idx) {
- /* Select the new smaller segment */
- bfa_q_deq(&ib_mod->ibidx_seg_pool[new_q_idx], &idx_seg);
- bfa_q_qe_init(&idx_seg->qe);
- /* Free the old segment */
- list_add_tail(&ib->idx_seg->qe,
- &ib_mod->ibidx_seg_pool[cur_q_idx]);
- ib->idx_seg = idx_seg;
- }
-}
-
-static int
-bna_ib_config(struct bna_ib *ib, struct bna_ib_config *ib_config)
-{
- if (ib->start_count)
- return -1;
-
- ib->ib_config.coalescing_timeo = ib_config->coalescing_timeo;
- ib->ib_config.interpkt_timeo = ib_config->interpkt_timeo;
- ib->ib_config.interpkt_count = ib_config->interpkt_count;
- ib->ib_config.ctrl_flags = ib_config->ctrl_flags;
-
- ib->ib_config.ctrl_flags |= BFI_IB_CF_MASTER_ENABLE;
- if (ib->intr->intr_type == BNA_INTR_T_MSIX)
- ib->ib_config.ctrl_flags |= BFI_IB_CF_MSIX_MODE;
-
- return 0;
-}
-
-static void
-bna_ib_start(struct bna_ib *ib)
-{
- struct bna_ib_blk_mem ib_cfg;
- struct bna_ib_blk_mem *ib_mem;
- u32 pg_num;
- u32 intx_mask;
- int i;
- void __iomem *base_addr;
- unsigned long off;
-
- ib->start_count++;
-
- if (ib->start_count > 1)
- return;
-
- ib_cfg.host_addr_lo = (u32)(ib->ib_seg_host_addr.lsb);
- ib_cfg.host_addr_hi = (u32)(ib->ib_seg_host_addr.msb);
-
- ib_cfg.clsc_n_ctrl_n_msix = (((u32)
- ib->ib_config.coalescing_timeo << 16) |
- ((u32)ib->ib_config.ctrl_flags << 8) |
- (ib->intr->vector));
- ib_cfg.ipkt_n_ent_n_idxof =
- ((u32)
- (ib->ib_config.interpkt_timeo & 0xf) << 16) |
- ((u32)ib->idx_seg->ib_seg_size << 8) |
- (ib->idx_seg->ib_idx_tbl_offset);
- ib_cfg.ipkt_cnt_cfg_n_unacked = ((u32)
- ib->ib_config.interpkt_count << 24);
-
- pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num,
- HQM_IB_RAM_BASE_OFFSET);
- writel(pg_num, ib->bna->regs.page_addr);
-
- base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva,
- HQM_IB_RAM_BASE_OFFSET);
-
- ib_mem = (struct bna_ib_blk_mem *)0;
- off = (unsigned long)&ib_mem[ib->ib_id].host_addr_lo;
- writel(htonl(ib_cfg.host_addr_lo), base_addr + off);
-
- off = (unsigned long)&ib_mem[ib->ib_id].host_addr_hi;
- writel(htonl(ib_cfg.host_addr_hi), base_addr + off);
-
- off = (unsigned long)&ib_mem[ib->ib_id].clsc_n_ctrl_n_msix;
- writel(ib_cfg.clsc_n_ctrl_n_msix, base_addr + off);
-
- off = (unsigned long)&ib_mem[ib->ib_id].ipkt_n_ent_n_idxof;
- writel(ib_cfg.ipkt_n_ent_n_idxof, base_addr + off);
-
- off = (unsigned long)&ib_mem[ib->ib_id].ipkt_cnt_cfg_n_unacked;
- writel(ib_cfg.ipkt_cnt_cfg_n_unacked, base_addr + off);
-
- ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
- (u32)ib->ib_config.coalescing_timeo, 0);
-
- pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num,
- HQM_INDX_TBL_RAM_BASE_OFFSET);
- writel(pg_num, ib->bna->regs.page_addr);
-
- base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva,
- HQM_INDX_TBL_RAM_BASE_OFFSET);
- for (i = 0; i < ib->idx_seg->ib_seg_size; i++) {
- off = (unsigned long)
- ((ib->idx_seg->ib_idx_tbl_offset + i) * BFI_IBIDX_SIZE);
- writel(0, base_addr + off);
- }
-
- if (ib->intr->intr_type == BNA_INTR_T_INTX) {
- bna_intx_disable(ib->bna, intx_mask);
- intx_mask &= ~(ib->intr->vector);
- bna_intx_enable(ib->bna, intx_mask);
- }
-}
-
-static void
-bna_ib_stop(struct bna_ib *ib)
-{
- u32 intx_mask;
-
- ib->start_count--;
-
- if (ib->start_count == 0) {
- writel(BNA_DOORBELL_IB_INT_DISABLE,
- ib->door_bell.doorbell_addr);
- if (ib->intr->intr_type == BNA_INTR_T_INTX) {
- bna_intx_disable(ib->bna, intx_mask);
- intx_mask |= (ib->intr->vector);
- bna_intx_enable(ib->bna, intx_mask);
- }
- }
-}
-
-static void
-bna_ib_fail(struct bna_ib *ib)
-{
- ib->start_count = 0;
-}
-
-/**
- * RXF
- */
-static void rxf_enable(struct bna_rxf *rxf);
-static void rxf_disable(struct bna_rxf *rxf);
-static void __rxf_config_set(struct bna_rxf *rxf);
-static void __rxf_rit_set(struct bna_rxf *rxf);
-static void __bna_rxf_stat_clr(struct bna_rxf *rxf);
-static int rxf_process_packet_filter(struct bna_rxf *rxf);
-static int rxf_clear_packet_filter(struct bna_rxf *rxf);
-static void rxf_reset_packet_filter(struct bna_rxf *rxf);
-static void rxf_cb_enabled(void *arg, int status);
-static void rxf_cb_disabled(void *arg, int status);
-static void bna_rxf_cb_stats_cleared(void *arg, int status);
-static void __rxf_enable(struct bna_rxf *rxf);
-static void __rxf_disable(struct bna_rxf *rxf);
-
-bfa_fsm_state_decl(bna_rxf, stopped, struct bna_rxf,
- enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, start_wait, struct bna_rxf,
- enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, cam_fltr_mod_wait, struct bna_rxf,
- enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, started, struct bna_rxf,
- enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, cam_fltr_clr_wait, struct bna_rxf,
- enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, stop_wait, struct bna_rxf,
- enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, pause_wait, struct bna_rxf,
- enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, resume_wait, struct bna_rxf,
- enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, stat_clr_wait, struct bna_rxf,
- enum bna_rxf_event);
-
-static struct bfa_sm_table rxf_sm_table[] = {
- {BFA_SM(bna_rxf_sm_stopped), BNA_RXF_STOPPED},
- {BFA_SM(bna_rxf_sm_start_wait), BNA_RXF_START_WAIT},
- {BFA_SM(bna_rxf_sm_cam_fltr_mod_wait), BNA_RXF_CAM_FLTR_MOD_WAIT},
- {BFA_SM(bna_rxf_sm_started), BNA_RXF_STARTED},
- {BFA_SM(bna_rxf_sm_cam_fltr_clr_wait), BNA_RXF_CAM_FLTR_CLR_WAIT},
- {BFA_SM(bna_rxf_sm_stop_wait), BNA_RXF_STOP_WAIT},
- {BFA_SM(bna_rxf_sm_pause_wait), BNA_RXF_PAUSE_WAIT},
- {BFA_SM(bna_rxf_sm_resume_wait), BNA_RXF_RESUME_WAIT},
- {BFA_SM(bna_rxf_sm_stat_clr_wait), BNA_RXF_STAT_CLR_WAIT}
-};
-
-static void
-bna_rxf_sm_stopped_entry(struct bna_rxf *rxf)
-{
- call_rxf_stop_cbfn(rxf, BNA_CB_SUCCESS);
-}
-
-static void
-bna_rxf_sm_stopped(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
- switch (event) {
- case RXF_E_START:
- bfa_fsm_set_state(rxf, bna_rxf_sm_start_wait);
- break;
-
- case RXF_E_STOP:
- bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
- break;
-
- case RXF_E_FAIL:
- /* No-op */
- break;
-
- case RXF_E_CAM_FLTR_MOD:
- call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
- break;
-
- case RXF_E_STARTED:
- case RXF_E_STOPPED:
- case RXF_E_CAM_FLTR_RESP:
- /**
- * These events are received due to flushing of mbox
- * when device fails
- */
- /* No-op */
- break;
-
- case RXF_E_PAUSE:
- rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
- call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS);
- break;
-
- case RXF_E_RESUME:
- rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
- call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_rxf_sm_start_wait_entry(struct bna_rxf *rxf)
-{
- __rxf_config_set(rxf);
- __rxf_rit_set(rxf);
- rxf_enable(rxf);
-}
-
-static void
-bna_rxf_sm_start_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
- switch (event) {
- case RXF_E_STOP:
- /**
- * STOP is originated from bnad. When this happens,
- * it can not be waiting for filter update
- */
- call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT);
- bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait);
- break;
-
- case RXF_E_FAIL:
- call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
- call_rxf_start_cbfn(rxf, BNA_CB_FAIL);
- bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
- break;
-
- case RXF_E_CAM_FLTR_MOD:
- /* No-op */
- break;
-
- case RXF_E_STARTED:
- /**
- * Force rxf_process_filter() to go through initial
- * config
- */
- if ((rxf->ucast_active_mac != NULL) &&
- (rxf->ucast_pending_set == 0))
- rxf->ucast_pending_set = 1;
-
- if (rxf->rss_status == BNA_STATUS_T_ENABLED)
- rxf->rxf_flags |= BNA_RXF_FL_RSS_CONFIG_PENDING;
-
- rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
-
- bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait);
- break;
-
- case RXF_E_PAUSE:
- case RXF_E_RESUME:
- rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED;
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_rxf_sm_cam_fltr_mod_wait_entry(struct bna_rxf *rxf)
-{
- if (!rxf_process_packet_filter(rxf)) {
- /* No more pending CAM entries to update */
- bfa_fsm_set_state(rxf, bna_rxf_sm_started);
- }
-}
-
-static void
-bna_rxf_sm_cam_fltr_mod_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
- switch (event) {
- case RXF_E_STOP:
- /**
- * STOP is originated from bnad. When this happens,
- * it can not be waiting for filter update
- */
- call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT);
- bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait);
- break;
-
- case RXF_E_FAIL:
- rxf_reset_packet_filter(rxf);
- call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
- call_rxf_start_cbfn(rxf, BNA_CB_FAIL);
- bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
- break;
-
- case RXF_E_CAM_FLTR_MOD:
- /* No-op */
- break;
-
- case RXF_E_CAM_FLTR_RESP:
- if (!rxf_process_packet_filter(rxf)) {
- /* No more pending CAM entries to update */
- call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
- bfa_fsm_set_state(rxf, bna_rxf_sm_started);
- }
- break;
-
- case RXF_E_PAUSE:
- case RXF_E_RESUME:
- rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED;
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_rxf_sm_started_entry(struct bna_rxf *rxf)
-{
- call_rxf_start_cbfn(rxf, BNA_CB_SUCCESS);
-
- if (rxf->rxf_flags & BNA_RXF_FL_OPERSTATE_CHANGED) {
- if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
- bfa_fsm_send_event(rxf, RXF_E_PAUSE);
- else
- bfa_fsm_send_event(rxf, RXF_E_RESUME);
- }
-
-}
-
-static void
-bna_rxf_sm_started(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
- switch (event) {
- case RXF_E_STOP:
- bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait);
- /* Hack to get FSM start clearing CAM entries */
- bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP);
- break;
-
- case RXF_E_FAIL:
- rxf_reset_packet_filter(rxf);
- bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
- break;
-
- case RXF_E_CAM_FLTR_MOD:
- bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait);
- break;
-
- case RXF_E_PAUSE:
- bfa_fsm_set_state(rxf, bna_rxf_sm_pause_wait);
- break;
-
- case RXF_E_RESUME:
- bfa_fsm_set_state(rxf, bna_rxf_sm_resume_wait);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_rxf_sm_cam_fltr_clr_wait_entry(struct bna_rxf *rxf)
-{
- /**
- * Note: Do not add rxf_clear_packet_filter here.
- * It will overstep mbox when this transition happens:
- * cam_fltr_mod_wait -> cam_fltr_clr_wait on RXF_E_STOP event
- */
-}
-
-static void
-bna_rxf_sm_cam_fltr_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
- switch (event) {
- case RXF_E_FAIL:
- /**
- * FSM was in the process of stopping, initiated by
- * bnad. When this happens, no one can be waiting for
- * start or filter update
- */
- rxf_reset_packet_filter(rxf);
- bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
- break;
-
- case RXF_E_CAM_FLTR_RESP:
- if (!rxf_clear_packet_filter(rxf)) {
- /* No more pending CAM entries to clear */
- bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait);
- rxf_disable(rxf);
- }
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_rxf_sm_stop_wait_entry(struct bna_rxf *rxf)
-{
- /**
- * NOTE: Do not add rxf_disable here.
- * It will overstep mbox when this transition happens:
- * start_wait -> stop_wait on RXF_E_STOP event
- */
-}
-
-static void
-bna_rxf_sm_stop_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
- switch (event) {
- case RXF_E_FAIL:
- /**
- * FSM was in the process of stopping, initiated by
- * bnad. When this happens, no one can be waiting for
- * start or filter update
- */
- bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
- break;
-
- case RXF_E_STARTED:
- /**
- * This event is received due to abrupt transition from
- * bna_rxf_sm_start_wait state on receiving
- * RXF_E_STOP event
- */
- rxf_disable(rxf);
- break;
-
- case RXF_E_STOPPED:
- /**
- * FSM was in the process of stopping, initiated by
- * bnad. When this happens, no one can be waiting for
- * start or filter update
- */
- bfa_fsm_set_state(rxf, bna_rxf_sm_stat_clr_wait);
- break;
-
- case RXF_E_PAUSE:
- rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
- break;
-
- case RXF_E_RESUME:
- rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_rxf_sm_pause_wait_entry(struct bna_rxf *rxf)
-{
- rxf->rxf_flags &=
- ~(BNA_RXF_FL_OPERSTATE_CHANGED | BNA_RXF_FL_RXF_ENABLED);
- __rxf_disable(rxf);
-}
-
-static void
-bna_rxf_sm_pause_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
- switch (event) {
- case RXF_E_FAIL:
- /**
- * FSM was in the process of disabling rxf, initiated by
- * bnad.
- */
- call_rxf_pause_cbfn(rxf, BNA_CB_FAIL);
- bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
- break;
-
- case RXF_E_STOPPED:
- rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
- call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS);
- bfa_fsm_set_state(rxf, bna_rxf_sm_started);
- break;
-
- /*
- * Since PAUSE/RESUME can only be sent by bnad, we don't expect
- * any other event during these states
- */
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_rxf_sm_resume_wait_entry(struct bna_rxf *rxf)
-{
- rxf->rxf_flags &= ~(BNA_RXF_FL_OPERSTATE_CHANGED);
- rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED;
- __rxf_enable(rxf);
-}
-
-static void
-bna_rxf_sm_resume_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
- switch (event) {
- case RXF_E_FAIL:
- /**
- * FSM was in the process of disabling rxf, initiated by
- * bnad.
- */
- call_rxf_resume_cbfn(rxf, BNA_CB_FAIL);
- bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
- break;
-
- case RXF_E_STARTED:
- rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
- call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS);
- bfa_fsm_set_state(rxf, bna_rxf_sm_started);
- break;
-
- /*
- * Since PAUSE/RESUME can only be sent by bnad, we don't expect
- * any other event during these states
- */
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_rxf_sm_stat_clr_wait_entry(struct bna_rxf *rxf)
-{
- __bna_rxf_stat_clr(rxf);
-}
-
-static void
-bna_rxf_sm_stat_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
- switch (event) {
- case RXF_E_FAIL:
- case RXF_E_STAT_CLEARED:
- bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-__rxf_enable(struct bna_rxf *rxf)
-{
- struct bfi_ll_rxf_multi_req ll_req;
- u32 bm[2] = {0, 0};
-
- if (rxf->rxf_id < 32)
- bm[0] = 1 << rxf->rxf_id;
- else
- bm[1] = 1 << (rxf->rxf_id - 32);
-
- bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
- ll_req.rxf_id_mask[0] = htonl(bm[0]);
- ll_req.rxf_id_mask[1] = htonl(bm[1]);
- ll_req.enable = 1;
-
- bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
- rxf_cb_enabled, rxf);
-
- bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static void
-__rxf_disable(struct bna_rxf *rxf)
-{
- struct bfi_ll_rxf_multi_req ll_req;
- u32 bm[2] = {0, 0};
-
- if (rxf->rxf_id < 32)
- bm[0] = 1 << rxf->rxf_id;
- else
- bm[1] = 1 << (rxf->rxf_id - 32);
-
- bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
- ll_req.rxf_id_mask[0] = htonl(bm[0]);
- ll_req.rxf_id_mask[1] = htonl(bm[1]);
- ll_req.enable = 0;
-
- bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
- rxf_cb_disabled, rxf);
-
- bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static void
-__rxf_config_set(struct bna_rxf *rxf)
-{
- u32 i;
- struct bna_rss_mem *rss_mem;
- struct bna_rx_fndb_ram *rx_fndb_ram;
- struct bna *bna = rxf->rx->bna;
- void __iomem *base_addr;
- unsigned long off;
-
- base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
- RSS_TABLE_BASE_OFFSET);
-
- rss_mem = (struct bna_rss_mem *)0;
-
- /* Configure RSS if required */
- if (rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE) {
- /* configure RSS Table */
- writel(BNA_GET_PAGE_NUM(RAD0_MEM_BLK_BASE_PG_NUM +
- bna->port_num, RSS_TABLE_BASE_OFFSET),
- bna->regs.page_addr);
-
- /* temporarily disable RSS, while hash value is written */
- off = (unsigned long)&rss_mem[0].type_n_hash;
- writel(0, base_addr + off);
-
- for (i = 0; i < BFI_RSS_HASH_KEY_LEN; i++) {
- off = (unsigned long)
- &rss_mem[0].hash_key[(BFI_RSS_HASH_KEY_LEN - 1) - i];
- writel(htonl(rxf->rss_cfg.toeplitz_hash_key[i]),
- base_addr + off);
- }
-
- off = (unsigned long)&rss_mem[0].type_n_hash;
- writel(rxf->rss_cfg.hash_type | rxf->rss_cfg.hash_mask,
- base_addr + off);
- }
-
- /* Configure RxF */
- writel(BNA_GET_PAGE_NUM(
- LUT0_MEM_BLK_BASE_PG_NUM + (bna->port_num * 2),
- RX_FNDB_RAM_BASE_OFFSET),
- bna->regs.page_addr);
-
- base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
- RX_FNDB_RAM_BASE_OFFSET);
-
- rx_fndb_ram = (struct bna_rx_fndb_ram *)0;
-
- /* We always use RSS table 0 */
- off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rss_prop;
- writel(rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE,
- base_addr + off);
-
- /* small large buffer enable/disable */
- off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].size_routing_props;
- writel((rxf->ctrl_flags & BNA_RXF_CF_SM_LG_RXQ) | 0x80,
- base_addr + off);
-
- /* RIT offset, HDS forced offset, multicast RxQ Id */
- off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rit_hds_mcastq;
- writel((rxf->rit_segment->rit_offset << 16) |
- (rxf->forced_offset << 8) |
- (rxf->hds_cfg.hdr_type & BNA_HDS_FORCED) | rxf->mcast_rxq_id,
- base_addr + off);
-
- /*
- * default vlan tag, default function enable, strip vlan bytes,
- * HDS type, header size
- */
-
- off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].control_flags;
- writel(((u32)rxf->default_vlan_tag << 16) |
- (rxf->ctrl_flags &
- (BNA_RXF_CF_DEFAULT_VLAN |
- BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE |
- BNA_RXF_CF_VLAN_STRIP)) |
- (rxf->hds_cfg.hdr_type & ~BNA_HDS_FORCED) |
- rxf->hds_cfg.header_size,
- base_addr + off);
-}
-
-void
-__rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status)
-{
- struct bna *bna = rxf->rx->bna;
- int i;
-
- writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
- (bna->port_num * 2), VLAN_RAM_BASE_OFFSET),
- bna->regs.page_addr);
-
- if (status == BNA_STATUS_T_ENABLED) {
- /* enable VLAN filtering on this function */
- for (i = 0; i <= BFI_MAX_VLAN / 32; i++) {
- writel(rxf->vlan_filter_table[i],
- BNA_GET_VLAN_MEM_ENTRY_ADDR
- (bna->pcidev.pci_bar_kva, rxf->rxf_id,
- i * 32));
- }
- } else {
- /* disable VLAN filtering on this function */
- for (i = 0; i <= BFI_MAX_VLAN / 32; i++) {
- writel(0xffffffff,
- BNA_GET_VLAN_MEM_ENTRY_ADDR
- (bna->pcidev.pci_bar_kva, rxf->rxf_id,
- i * 32));
- }
- }
-}
-
-static void
-__rxf_rit_set(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
- struct bna_rit_mem *rit_mem;
- int i;
- void __iomem *base_addr;
- unsigned long off;
-
- base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
- FUNCTION_TO_RXQ_TRANSLATE);
-
- rit_mem = (struct bna_rit_mem *)0;
-
- writel(BNA_GET_PAGE_NUM(RXA0_MEM_BLK_BASE_PG_NUM + bna->port_num,
- FUNCTION_TO_RXQ_TRANSLATE),
- bna->regs.page_addr);
-
- for (i = 0; i < rxf->rit_segment->rit_size; i++) {
- off = (unsigned long)&rit_mem[i + rxf->rit_segment->rit_offset];
- writel(rxf->rit_segment->rit[i].large_rxq_id << 6 |
- rxf->rit_segment->rit[i].small_rxq_id,
- base_addr + off);
- }
-}
-
-static void
-__bna_rxf_stat_clr(struct bna_rxf *rxf)
-{
- struct bfi_ll_stats_req ll_req;
- u32 bm[2] = {0, 0};
-
- if (rxf->rxf_id < 32)
- bm[0] = 1 << rxf->rxf_id;
- else
- bm[1] = 1 << (rxf->rxf_id - 32);
-
- bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
- ll_req.stats_mask = 0;
- ll_req.txf_id_mask[0] = 0;
- ll_req.txf_id_mask[1] = 0;
-
- ll_req.rxf_id_mask[0] = htonl(bm[0]);
- ll_req.rxf_id_mask[1] = htonl(bm[1]);
-
- bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
- bna_rxf_cb_stats_cleared, rxf);
- bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static void
-rxf_enable(struct bna_rxf *rxf)
-{
- if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
- bfa_fsm_send_event(rxf, RXF_E_STARTED);
- else {
- rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED;
- __rxf_enable(rxf);
- }
-}
-
-static void
-rxf_cb_enabled(void *arg, int status)
-{
- struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
- bfa_q_qe_init(&rxf->mbox_qe.qe);
- bfa_fsm_send_event(rxf, RXF_E_STARTED);
-}
-
-static void
-rxf_disable(struct bna_rxf *rxf)
-{
- if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
- bfa_fsm_send_event(rxf, RXF_E_STOPPED);
- else
- rxf->rxf_flags &= ~BNA_RXF_FL_RXF_ENABLED;
- __rxf_disable(rxf);
-}
-
-static void
-rxf_cb_disabled(void *arg, int status)
-{
- struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
- bfa_q_qe_init(&rxf->mbox_qe.qe);
- bfa_fsm_send_event(rxf, RXF_E_STOPPED);
-}
-
-void
-rxf_cb_cam_fltr_mbox_cmd(void *arg, int status)
-{
- struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
- bfa_q_qe_init(&rxf->mbox_qe.qe);
-
- bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP);
-}
-
-static void
-bna_rxf_cb_stats_cleared(void *arg, int status)
-{
- struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
- bfa_q_qe_init(&rxf->mbox_qe.qe);
- bfa_fsm_send_event(rxf, RXF_E_STAT_CLEARED);
-}
-
-void
-rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd,
- const struct bna_mac *mac_addr)
-{
- struct bfi_ll_mac_addr_req req;
-
- bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0);
-
- req.rxf_id = rxf->rxf_id;
- memcpy(&req.mac_addr, (void *)&mac_addr->addr, ETH_ALEN);
-
- bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req),
- rxf_cb_cam_fltr_mbox_cmd, rxf);
-
- bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static int
-rxf_process_packet_filter_mcast(struct bna_rxf *rxf)
-{
- struct bna_mac *mac = NULL;
- struct list_head *qe;
-
- /* Add multicast entries */
- if (!list_empty(&rxf->mcast_pending_add_q)) {
- bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
- bfa_q_qe_init(qe);
- mac = (struct bna_mac *)qe;
- rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_ADD_REQ, mac);
- list_add_tail(&mac->qe, &rxf->mcast_active_q);
- return 1;
- }
-
- /* Delete multicast entries previousely added */
- if (!list_empty(&rxf->mcast_pending_del_q)) {
- bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
- bfa_q_qe_init(qe);
- mac = (struct bna_mac *)qe;
- rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
- bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
- return 1;
- }
-
- return 0;
-}
-
-static int
-rxf_process_packet_filter_vlan(struct bna_rxf *rxf)
-{
- /* Apply the VLAN filter */
- if (rxf->rxf_flags & BNA_RXF_FL_VLAN_CONFIG_PENDING) {
- rxf->rxf_flags &= ~BNA_RXF_FL_VLAN_CONFIG_PENDING;
- if (!(rxf->rxmode_active & BNA_RXMODE_PROMISC))
- __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
- }
-
- /* Apply RSS configuration */
- if (rxf->rxf_flags & BNA_RXF_FL_RSS_CONFIG_PENDING) {
- rxf->rxf_flags &= ~BNA_RXF_FL_RSS_CONFIG_PENDING;
- if (rxf->rss_status == BNA_STATUS_T_DISABLED) {
- /* RSS is being disabled */
- rxf->ctrl_flags &= ~BNA_RXF_CF_RSS_ENABLE;
- __rxf_rit_set(rxf);
- __rxf_config_set(rxf);
- } else {
- /* RSS is being enabled or reconfigured */
- rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE;
- __rxf_rit_set(rxf);
- __rxf_config_set(rxf);
- }
- }
-
- return 0;
-}
-
-/**
- * Processes pending ucast, mcast entry addition/deletion and issues mailbox
- * command. Also processes pending filter configuration - promiscuous mode,
- * default mode, allmutli mode and issues mailbox command or directly applies
- * to h/w
- */
-static int
-rxf_process_packet_filter(struct bna_rxf *rxf)
-{
- /* Set the default MAC first */
- if (rxf->ucast_pending_set > 0) {
- rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_SET_REQ,
- rxf->ucast_active_mac);
- rxf->ucast_pending_set--;
- return 1;
- }
-
- if (rxf_process_packet_filter_ucast(rxf))
- return 1;
-
- if (rxf_process_packet_filter_mcast(rxf))
- return 1;
-
- if (rxf_process_packet_filter_promisc(rxf))
- return 1;
-
- if (rxf_process_packet_filter_allmulti(rxf))
- return 1;
-
- if (rxf_process_packet_filter_vlan(rxf))
- return 1;
-
- return 0;
-}
-
-static int
-rxf_clear_packet_filter_mcast(struct bna_rxf *rxf)
-{
- struct bna_mac *mac = NULL;
- struct list_head *qe;
-
- /* 3. delete pending mcast entries */
- if (!list_empty(&rxf->mcast_pending_del_q)) {
- bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
- bfa_q_qe_init(qe);
- mac = (struct bna_mac *)qe;
- rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
- bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
- return 1;
- }
-
- /* 4. clear active mcast entries; move them to pending_add_q */
- if (!list_empty(&rxf->mcast_active_q)) {
- bfa_q_deq(&rxf->mcast_active_q, &qe);
- bfa_q_qe_init(qe);
- mac = (struct bna_mac *)qe;
- rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
- list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
- return 1;
- }
-
- return 0;
-}
-
-/**
- * In the rxf stop path, processes pending ucast/mcast delete queue and issues
- * the mailbox command. Moves the active ucast/mcast entries to pending add q,
- * so that they are added to CAM again in the rxf start path. Moves the current
- * filter settings - promiscuous, default, allmutli - to pending filter
- * configuration
- */
-static int
-rxf_clear_packet_filter(struct bna_rxf *rxf)
-{
- if (rxf_clear_packet_filter_ucast(rxf))
- return 1;
-
- if (rxf_clear_packet_filter_mcast(rxf))
- return 1;
-
- /* 5. clear active default MAC in the CAM */
- if (rxf->ucast_pending_set > 0)
- rxf->ucast_pending_set = 0;
-
- if (rxf_clear_packet_filter_promisc(rxf))
- return 1;
-
- if (rxf_clear_packet_filter_allmulti(rxf))
- return 1;
-
- return 0;
-}
-
-static void
-rxf_reset_packet_filter_mcast(struct bna_rxf *rxf)
-{
- struct list_head *qe;
- struct bna_mac *mac;
-
- /* 3. Move active mcast entries to pending_add_q */
- while (!list_empty(&rxf->mcast_active_q)) {
- bfa_q_deq(&rxf->mcast_active_q, &qe);
- bfa_q_qe_init(qe);
- list_add_tail(qe, &rxf->mcast_pending_add_q);
- }
-
- /* 4. Throw away delete pending mcast entries */
- while (!list_empty(&rxf->mcast_pending_del_q)) {
- bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
- bfa_q_qe_init(qe);
- mac = (struct bna_mac *)qe;
- bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
- }
-}
-
-/**
- * In the rxf fail path, throws away the ucast/mcast entries pending for
- * deletion, moves all active ucast/mcast entries to pending queue so that
- * they are added back to CAM in the rxf start path. Also moves the current
- * filter configuration to pending filter configuration.
- */
-static void
-rxf_reset_packet_filter(struct bna_rxf *rxf)
-{
- rxf_reset_packet_filter_ucast(rxf);
-
- rxf_reset_packet_filter_mcast(rxf);
-
- /* 5. Turn off ucast set flag */
- rxf->ucast_pending_set = 0;
-
- rxf_reset_packet_filter_promisc(rxf);
-
- rxf_reset_packet_filter_allmulti(rxf);
-}
-
-static void
-bna_rxf_init(struct bna_rxf *rxf,
- struct bna_rx *rx,
- struct bna_rx_config *q_config)
-{
- struct list_head *qe;
- struct bna_rxp *rxp;
-
- /* rxf_id is initialized during rx_mod init */
- rxf->rx = rx;
-
- INIT_LIST_HEAD(&rxf->ucast_pending_add_q);
- INIT_LIST_HEAD(&rxf->ucast_pending_del_q);
- rxf->ucast_pending_set = 0;
- INIT_LIST_HEAD(&rxf->ucast_active_q);
- rxf->ucast_active_mac = NULL;
-
- INIT_LIST_HEAD(&rxf->mcast_pending_add_q);
- INIT_LIST_HEAD(&rxf->mcast_pending_del_q);
- INIT_LIST_HEAD(&rxf->mcast_active_q);
-
- bfa_q_qe_init(&rxf->mbox_qe.qe);
-
- if (q_config->vlan_strip_status == BNA_STATUS_T_ENABLED)
- rxf->ctrl_flags |= BNA_RXF_CF_VLAN_STRIP;
-
- rxf->rxf_oper_state = (q_config->paused) ?
- BNA_RXF_OPER_STATE_PAUSED : BNA_RXF_OPER_STATE_RUNNING;
-
- bna_rxf_adv_init(rxf, rx, q_config);
-
- rxf->rit_segment = bna_rit_mod_seg_get(&rxf->rx->bna->rit_mod,
- q_config->num_paths);
-
- list_for_each(qe, &rx->rxp_q) {
- rxp = (struct bna_rxp *)qe;
- if (q_config->rxp_type == BNA_RXP_SINGLE)
- rxf->mcast_rxq_id = rxp->rxq.single.only->rxq_id;
- else
- rxf->mcast_rxq_id = rxp->rxq.slr.large->rxq_id;
- break;
- }
-
- rxf->vlan_filter_status = BNA_STATUS_T_DISABLED;
- memset(rxf->vlan_filter_table, 0,
- (sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32)));
-
- /* Set up VLAN 0 for pure priority tagged packets */
- rxf->vlan_filter_table[0] |= 1;
-
- bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-}
-
-static void
-bna_rxf_uninit(struct bna_rxf *rxf)
-{
- struct bna *bna = rxf->rx->bna;
- struct bna_mac *mac;
-
- bna_rit_mod_seg_put(&rxf->rx->bna->rit_mod, rxf->rit_segment);
- rxf->rit_segment = NULL;
-
- rxf->ucast_pending_set = 0;
-
- while (!list_empty(&rxf->ucast_pending_add_q)) {
- bfa_q_deq(&rxf->ucast_pending_add_q, &mac);
- bfa_q_qe_init(&mac->qe);
- bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
- }
-
- if (rxf->ucast_active_mac) {
- bfa_q_qe_init(&rxf->ucast_active_mac->qe);
- bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod,
- rxf->ucast_active_mac);
- rxf->ucast_active_mac = NULL;
- }
-
- while (!list_empty(&rxf->mcast_pending_add_q)) {
- bfa_q_deq(&rxf->mcast_pending_add_q, &mac);
- bfa_q_qe_init(&mac->qe);
- bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
- }
-
- /* Turn off pending promisc mode */
- if (is_promisc_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- /* system promisc state should be pending */
- BUG_ON(!(bna->rxf_promisc_id == rxf->rxf_id));
- promisc_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- bna->rxf_promisc_id = BFI_MAX_RXF;
- }
- /* Promisc mode should not be active */
- BUG_ON(rxf->rxmode_active & BNA_RXMODE_PROMISC);
-
- /* Turn off pending all-multi mode */
- if (is_allmulti_enable(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask)) {
- allmulti_inactive(rxf->rxmode_pending,
- rxf->rxmode_pending_bitmask);
- }
- /* Allmulti mode should not be active */
- BUG_ON(rxf->rxmode_active & BNA_RXMODE_ALLMULTI);
-
- rxf->rx = NULL;
-}
-
-static void
-bna_rx_cb_rxf_started(struct bna_rx *rx, enum bna_cb_status status)
-{
- bfa_fsm_send_event(rx, RX_E_RXF_STARTED);
- if (rx->rxf.rxf_id < 32)
- rx->bna->rx_mod.rxf_bmap[0] |= ((u32)1 << rx->rxf.rxf_id);
- else
- rx->bna->rx_mod.rxf_bmap[1] |= ((u32)
- 1 << (rx->rxf.rxf_id - 32));
-}
-
-static void
-bna_rxf_start(struct bna_rxf *rxf)
-{
- rxf->start_cbfn = bna_rx_cb_rxf_started;
- rxf->start_cbarg = rxf->rx;
- rxf->rxf_flags &= ~BNA_RXF_FL_FAILED;
- bfa_fsm_send_event(rxf, RXF_E_START);
-}
-
-static void
-bna_rx_cb_rxf_stopped(struct bna_rx *rx, enum bna_cb_status status)
-{
- bfa_fsm_send_event(rx, RX_E_RXF_STOPPED);
- if (rx->rxf.rxf_id < 32)
- rx->bna->rx_mod.rxf_bmap[0] &= ~(u32)1 << rx->rxf.rxf_id;
- else
- rx->bna->rx_mod.rxf_bmap[1] &= ~(u32)
- 1 << (rx->rxf.rxf_id - 32);
-}
-
-static void
-bna_rxf_stop(struct bna_rxf *rxf)
-{
- rxf->stop_cbfn = bna_rx_cb_rxf_stopped;
- rxf->stop_cbarg = rxf->rx;
- bfa_fsm_send_event(rxf, RXF_E_STOP);
-}
-
-static void
-bna_rxf_fail(struct bna_rxf *rxf)
-{
- rxf->rxf_flags |= BNA_RXF_FL_FAILED;
- bfa_fsm_send_event(rxf, RXF_E_FAIL);
-}
-
-int
-bna_rxf_state_get(struct bna_rxf *rxf)
-{
- return bfa_sm_to_state(rxf_sm_table, rxf->fsm);
-}
-
-enum bna_cb_status
-bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
- void (*cbfn)(struct bnad *, struct bna_rx *,
- enum bna_cb_status))
-{
- struct bna_rxf *rxf = &rx->rxf;
-
- if (rxf->ucast_active_mac == NULL) {
- rxf->ucast_active_mac =
- bna_ucam_mod_mac_get(&rxf->rx->bna->ucam_mod);
- if (rxf->ucast_active_mac == NULL)
- return BNA_CB_UCAST_CAM_FULL;
- bfa_q_qe_init(&rxf->ucast_active_mac->qe);
- }
-
- memcpy(rxf->ucast_active_mac->addr, ucmac, ETH_ALEN);
- rxf->ucast_pending_set++;
- rxf->cam_fltr_cbfn = cbfn;
- rxf->cam_fltr_cbarg = rx->bna->bnad;
-
- bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-
- return BNA_CB_SUCCESS;
-}
-
-enum bna_cb_status
-bna_rx_mcast_add(struct bna_rx *rx, u8 *addr,
- void (*cbfn)(struct bnad *, struct bna_rx *,
- enum bna_cb_status))
-{
- struct bna_rxf *rxf = &rx->rxf;
- struct list_head *qe;
- struct bna_mac *mac;
-
- /* Check if already added */
- list_for_each(qe, &rxf->mcast_active_q) {
- mac = (struct bna_mac *)qe;
- if (BNA_MAC_IS_EQUAL(mac->addr, addr)) {
- if (cbfn)
- (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
- return BNA_CB_SUCCESS;
- }
- }
-
- /* Check if pending addition */
- list_for_each(qe, &rxf->mcast_pending_add_q) {
- mac = (struct bna_mac *)qe;
- if (BNA_MAC_IS_EQUAL(mac->addr, addr)) {
- if (cbfn)
- (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
- return BNA_CB_SUCCESS;
- }
- }
-
- mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
- if (mac == NULL)
- return BNA_CB_MCAST_LIST_FULL;
- bfa_q_qe_init(&mac->qe);
- memcpy(mac->addr, addr, ETH_ALEN);
- list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
-
- rxf->cam_fltr_cbfn = cbfn;
- rxf->cam_fltr_cbarg = rx->bna->bnad;
-
- bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-
- return BNA_CB_SUCCESS;
-}
-
-enum bna_cb_status
-bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
- void (*cbfn)(struct bnad *, struct bna_rx *,
- enum bna_cb_status))
-{
- struct bna_rxf *rxf = &rx->rxf;
- struct list_head list_head;
- struct list_head *qe;
- u8 *mcaddr;
- struct bna_mac *mac;
- struct bna_mac *mac1;
- int skip;
- int delete;
- int need_hw_config = 0;
- int i;
-
- /* Allocate nodes */
- INIT_LIST_HEAD(&list_head);
- for (i = 0, mcaddr = mclist; i < count; i++) {
- mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
- if (mac == NULL)
- goto err_return;
- bfa_q_qe_init(&mac->qe);
- memcpy(mac->addr, mcaddr, ETH_ALEN);
- list_add_tail(&mac->qe, &list_head);
-
- mcaddr += ETH_ALEN;
- }
-
- /* Schedule for addition */
- while (!list_empty(&list_head)) {
- bfa_q_deq(&list_head, &qe);
- mac = (struct bna_mac *)qe;
- bfa_q_qe_init(&mac->qe);
-
- skip = 0;
-
- /* Skip if already added */
- list_for_each(qe, &rxf->mcast_active_q) {
- mac1 = (struct bna_mac *)qe;
- if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) {
- bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod,
- mac);
- skip = 1;
- break;
- }
- }
-
- if (skip)
- continue;
-
- /* Skip if pending addition */
- list_for_each(qe, &rxf->mcast_pending_add_q) {
- mac1 = (struct bna_mac *)qe;
- if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) {
- bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod,
- mac);
- skip = 1;
- break;
- }
- }
-
- if (skip)
- continue;
-
- need_hw_config = 1;
- list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
- }
-
- /**
- * Delete the entries that are in the pending_add_q but not
- * in the new list
- */
- while (!list_empty(&rxf->mcast_pending_add_q)) {
- bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
- mac = (struct bna_mac *)qe;
- bfa_q_qe_init(&mac->qe);
- for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) {
- if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) {
- delete = 0;
- break;
- }
- mcaddr += ETH_ALEN;
- }
- if (delete)
- bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
- else
- list_add_tail(&mac->qe, &list_head);
- }
- while (!list_empty(&list_head)) {
- bfa_q_deq(&list_head, &qe);
- mac = (struct bna_mac *)qe;
- bfa_q_qe_init(&mac->qe);
- list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
- }
-
- /**
- * Schedule entries for deletion that are in the active_q but not
- * in the new list
- */
- while (!list_empty(&rxf->mcast_active_q)) {
- bfa_q_deq(&rxf->mcast_active_q, &qe);
- mac = (struct bna_mac *)qe;
- bfa_q_qe_init(&mac->qe);
- for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) {
- if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) {
- delete = 0;
- break;
- }
- mcaddr += ETH_ALEN;
- }
- if (delete) {
- list_add_tail(&mac->qe, &rxf->mcast_pending_del_q);
- need_hw_config = 1;
- } else {
- list_add_tail(&mac->qe, &list_head);
- }
- }
- while (!list_empty(&list_head)) {
- bfa_q_deq(&list_head, &qe);
- mac = (struct bna_mac *)qe;
- bfa_q_qe_init(&mac->qe);
- list_add_tail(&mac->qe, &rxf->mcast_active_q);
- }
-
- if (need_hw_config) {
- rxf->cam_fltr_cbfn = cbfn;
- rxf->cam_fltr_cbarg = rx->bna->bnad;
- bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
- } else if (cbfn)
- (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-
- return BNA_CB_SUCCESS;
-
-err_return:
- while (!list_empty(&list_head)) {
- bfa_q_deq(&list_head, &qe);
- mac = (struct bna_mac *)qe;
- bfa_q_qe_init(&mac->qe);
- bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
- }
-
- return BNA_CB_MCAST_LIST_FULL;
-}
-
-void
-bna_rx_vlan_add(struct bna_rx *rx, int vlan_id)
-{
- struct bna_rxf *rxf = &rx->rxf;
- int index = (vlan_id >> 5);
- int bit = (1 << (vlan_id & 0x1F));
-
- rxf->vlan_filter_table[index] |= bit;
- if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
- rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
- bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
- }
-}
-
-void
-bna_rx_vlan_del(struct bna_rx *rx, int vlan_id)
-{
- struct bna_rxf *rxf = &rx->rxf;
- int index = (vlan_id >> 5);
- int bit = (1 << (vlan_id & 0x1F));
-
- rxf->vlan_filter_table[index] &= ~bit;
- if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
- rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
- bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
- }
-}
-
-/**
- * RX
- */
-#define RXQ_RCB_INIT(q, rxp, qdepth, bna, _id, unmapq_mem) do { \
- struct bna_doorbell_qset *_qset; \
- unsigned long off; \
- (q)->rcb->producer_index = (q)->rcb->consumer_index = 0; \
- (q)->rcb->q_depth = (qdepth); \
- (q)->rcb->unmap_q = unmapq_mem; \
- (q)->rcb->rxq = (q); \
- (q)->rcb->cq = &(rxp)->cq; \
- (q)->rcb->bnad = (bna)->bnad; \
- _qset = (struct bna_doorbell_qset *)0; \
- off = (unsigned long)&_qset[(q)->rxq_id].rxq[0]; \
- (q)->rcb->q_dbell = off + \
- BNA_GET_DOORBELL_BASE_ADDR((bna)->pcidev.pci_bar_kva); \
- (q)->rcb->id = _id; \
-} while (0)
-
-#define BNA_GET_RXQS(qcfg) (((qcfg)->rxp_type == BNA_RXP_SINGLE) ? \
- (qcfg)->num_paths : ((qcfg)->num_paths * 2))
-
-#define SIZE_TO_PAGES(size) (((size) >> PAGE_SHIFT) + ((((size) &\
- (PAGE_SIZE - 1)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
-
-#define call_rx_stop_callback(rx, status) \
- if ((rx)->stop_cbfn) { \
- (*(rx)->stop_cbfn)((rx)->stop_cbarg, rx, (status)); \
- (rx)->stop_cbfn = NULL; \
- (rx)->stop_cbarg = NULL; \
- }
-
-/*
- * Since rx_enable is synchronous callback, there is no start_cbfn required.
- * Instead, we'll call bnad_rx_post(rxp) so that bnad can post the buffers
- * for each rxpath.
- */
-
-#define call_rx_disable_cbfn(rx, status) \
- if ((rx)->disable_cbfn) { \
- (*(rx)->disable_cbfn)((rx)->disable_cbarg, \
- status); \
- (rx)->disable_cbfn = NULL; \
- (rx)->disable_cbarg = NULL; \
- } \
-
-#define rxqs_reqd(type, num_rxqs) \
- (((type) == BNA_RXP_SINGLE) ? (num_rxqs) : ((num_rxqs) * 2))
-
-#define rx_ib_fail(rx) \
-do { \
- struct bna_rxp *rxp; \
- struct list_head *qe; \
- list_for_each(qe, &(rx)->rxp_q) { \
- rxp = (struct bna_rxp *)qe; \
- bna_ib_fail(rxp->cq.ib); \
- } \
-} while (0)
-
-static void __bna_multi_rxq_stop(struct bna_rxp *, u32 *);
-static void __bna_rxq_start(struct bna_rxq *rxq);
-static void __bna_cq_start(struct bna_cq *cq);
-static void bna_rit_create(struct bna_rx *rx);
-static void bna_rx_cb_multi_rxq_stopped(void *arg, int status);
-static void bna_rx_cb_rxq_stopped_all(void *arg);
-
-bfa_fsm_state_decl(bna_rx, stopped,
- 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,
- struct bna_rx, enum bna_rx_event);
-bfa_fsm_state_decl(bna_rx, rxf_stop_wait,
- struct bna_rx, enum bna_rx_event);
-bfa_fsm_state_decl(bna_rx, rxq_stop_wait,
- struct bna_rx, enum bna_rx_event);
-
-static const struct bfa_sm_table rx_sm_table[] = {
- {BFA_SM(bna_rx_sm_stopped), BNA_RX_STOPPED},
- {BFA_SM(bna_rx_sm_rxf_start_wait), BNA_RX_RXF_START_WAIT},
- {BFA_SM(bna_rx_sm_started), BNA_RX_STARTED},
- {BFA_SM(bna_rx_sm_rxf_stop_wait), BNA_RX_RXF_STOP_WAIT},
- {BFA_SM(bna_rx_sm_rxq_stop_wait), BNA_RX_RXQ_STOP_WAIT},
-};
-
-static void bna_rx_sm_stopped_entry(struct bna_rx *rx)
-{
- struct bna_rxp *rxp;
- struct list_head *qe_rxp;
-
- list_for_each(qe_rxp, &rx->rxp_q) {
- rxp = (struct bna_rxp *)qe_rxp;
- rx->rx_cleanup_cbfn(rx->bna->bnad, rxp->cq.ccb);
- }
-
- call_rx_stop_callback(rx, BNA_CB_SUCCESS);
-}
-
-static void bna_rx_sm_stopped(struct bna_rx *rx,
- enum bna_rx_event event)
-{
- switch (event) {
- case RX_E_START:
- bfa_fsm_set_state(rx, bna_rx_sm_rxf_start_wait);
- break;
- case RX_E_STOP:
- call_rx_stop_callback(rx, BNA_CB_SUCCESS);
- break;
- case RX_E_FAIL:
- /* no-op */
- break;
- default:
- bfa_sm_fault(event);
- break;
- }
-
-}
-
-static void bna_rx_sm_rxf_start_wait_entry(struct bna_rx *rx)
-{
- struct bna_rxp *rxp;
- struct list_head *qe_rxp;
- struct bna_rxq *q0 = NULL, *q1 = NULL;
-
- /* Setup the RIT */
- bna_rit_create(rx);
-
- list_for_each(qe_rxp, &rx->rxp_q) {
- rxp = (struct bna_rxp *)qe_rxp;
- bna_ib_start(rxp->cq.ib);
- GET_RXQS(rxp, q0, q1);
- q0->buffer_size = bna_port_mtu_get(&rx->bna->port);
- __bna_rxq_start(q0);
- rx->rx_post_cbfn(rx->bna->bnad, q0->rcb);
- if (q1) {
- __bna_rxq_start(q1);
- rx->rx_post_cbfn(rx->bna->bnad, q1->rcb);
- }
- __bna_cq_start(&rxp->cq);
- }
-
- bna_rxf_start(&rx->rxf);
-}
-
-static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx,
- enum bna_rx_event event)
-{
- switch (event) {
- case RX_E_STOP:
- bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
- break;
- case RX_E_FAIL:
- bfa_fsm_set_state(rx, bna_rx_sm_stopped);
- rx_ib_fail(rx);
- bna_rxf_fail(&rx->rxf);
- break;
- case RX_E_RXF_STARTED:
- bfa_fsm_set_state(rx, bna_rx_sm_started);
- break;
- default:
- bfa_sm_fault(event);
- break;
- }
-}
-
-void
-bna_rx_sm_started_entry(struct bna_rx *rx)
-{
- struct bna_rxp *rxp;
- struct list_head *qe_rxp;
-
- /* Start IB */
- list_for_each(qe_rxp, &rx->rxp_q) {
- rxp = (struct bna_rxp *)qe_rxp;
- bna_ib_ack(&rxp->cq.ib->door_bell, 0);
- }
-
- bna_llport_rx_started(&rx->bna->port.llport);
-}
-
-void
-bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
-{
- switch (event) {
- case RX_E_FAIL:
- bna_llport_rx_stopped(&rx->bna->port.llport);
- bfa_fsm_set_state(rx, bna_rx_sm_stopped);
- rx_ib_fail(rx);
- bna_rxf_fail(&rx->rxf);
- break;
- case RX_E_STOP:
- bna_llport_rx_stopped(&rx->bna->port.llport);
- bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
- break;
- default:
- bfa_sm_fault(event);
- break;
- }
-}
-
-void
-bna_rx_sm_rxf_stop_wait_entry(struct bna_rx *rx)
-{
- bna_rxf_stop(&rx->rxf);
-}
-
-void
-bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
-{
- switch (event) {
- case RX_E_RXF_STOPPED:
- bfa_fsm_set_state(rx, bna_rx_sm_rxq_stop_wait);
- break;
- case RX_E_RXF_STARTED:
- /**
- * RxF was in the process of starting up when
- * RXF_E_STOP was issued. Ignore this event
- */
- break;
- case RX_E_FAIL:
- bfa_fsm_set_state(rx, bna_rx_sm_stopped);
- rx_ib_fail(rx);
- bna_rxf_fail(&rx->rxf);
- break;
- default:
- bfa_sm_fault(event);
- break;
- }
-
-}
-
-void
-bna_rx_sm_rxq_stop_wait_entry(struct bna_rx *rx)
-{
- struct bna_rxp *rxp = NULL;
- struct bna_rxq *q0 = NULL;
- struct bna_rxq *q1 = NULL;
- struct list_head *qe;
- u32 rxq_mask[2] = {0, 0};
-
- /* Only one call to multi-rxq-stop for all RXPs in this RX */
- bfa_wc_up(&rx->rxq_stop_wc);
- list_for_each(qe, &rx->rxp_q) {
- rxp = (struct bna_rxp *)qe;
- GET_RXQS(rxp, q0, q1);
- if (q0->rxq_id < 32)
- rxq_mask[0] |= ((u32)1 << q0->rxq_id);
- else
- rxq_mask[1] |= ((u32)1 << (q0->rxq_id - 32));
- if (q1) {
- if (q1->rxq_id < 32)
- rxq_mask[0] |= ((u32)1 << q1->rxq_id);
- else
- rxq_mask[1] |= ((u32)
- 1 << (q1->rxq_id - 32));
- }
- }
-
- __bna_multi_rxq_stop(rxp, rxq_mask);
-}
-
-void
-bna_rx_sm_rxq_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
-{
- struct bna_rxp *rxp = NULL;
- struct list_head *qe;
-
- switch (event) {
- case RX_E_RXQ_STOPPED:
- list_for_each(qe, &rx->rxp_q) {
- rxp = (struct bna_rxp *)qe;
- bna_ib_stop(rxp->cq.ib);
- }
- /* Fall through */
- case RX_E_FAIL:
- bfa_fsm_set_state(rx, bna_rx_sm_stopped);
- break;
- default:
- bfa_sm_fault(event);
- break;
- }
-}
-
-void
-__bna_multi_rxq_stop(struct bna_rxp *rxp, u32 * rxq_id_mask)
-{
- struct bfi_ll_q_stop_req ll_req;
-
- bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RXQ_STOP_REQ, 0);
- ll_req.q_id_mask[0] = htonl(rxq_id_mask[0]);
- ll_req.q_id_mask[1] = htonl(rxq_id_mask[1]);
- bna_mbox_qe_fill(&rxp->mbox_qe, &ll_req, sizeof(ll_req),
- bna_rx_cb_multi_rxq_stopped, rxp);
- bna_mbox_send(rxp->rx->bna, &rxp->mbox_qe);
-}
-
-void
-__bna_rxq_start(struct bna_rxq *rxq)
-{
- struct bna_rxtx_q_mem *q_mem;
- struct bna_rxq_mem rxq_cfg, *rxq_mem;
- struct bna_dma_addr cur_q_addr;
- /* struct bna_doorbell_qset *qset; */
- struct bna_qpt *qpt;
- u32 pg_num;
- struct bna *bna = rxq->rx->bna;
- void __iomem *base_addr;
- unsigned long off;
-
- qpt = &rxq->qpt;
- cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
-
- rxq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
- rxq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
- rxq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
- rxq_cfg.cur_q_entry_hi = cur_q_addr.msb;
-
- rxq_cfg.pg_cnt_n_prd_ptr = ((u32)qpt->page_count << 16) | 0x0;
- rxq_cfg.entry_n_pg_size = ((u32)(BFI_RXQ_WI_SIZE >> 2) << 16) |
- (qpt->page_size >> 2);
- rxq_cfg.sg_n_cq_n_cns_ptr =
- ((u32)(rxq->rxp->cq.cq_id & 0xff) << 16) | 0x0;
- rxq_cfg.buf_sz_n_q_state = ((u32)rxq->buffer_size << 16) |
- BNA_Q_IDLE_STATE;
- rxq_cfg.next_qid = 0x0 | (0x3 << 8);
-
- /* Write the page number register */
- pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num,
- HQM_RXTX_Q_RAM_BASE_OFFSET);
- writel(pg_num, bna->regs.page_addr);
-
- /* Write to h/w */
- base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
- HQM_RXTX_Q_RAM_BASE_OFFSET);
-
- q_mem = (struct bna_rxtx_q_mem *)0;
- rxq_mem = &q_mem[rxq->rxq_id].rxq;
-
- off = (unsigned long)&rxq_mem->pg_tbl_addr_lo;
- writel(htonl(rxq_cfg.pg_tbl_addr_lo), base_addr + off);
-
- off = (unsigned long)&rxq_mem->pg_tbl_addr_hi;
- writel(htonl(rxq_cfg.pg_tbl_addr_hi), base_addr + off);
-
- off = (unsigned long)&rxq_mem->cur_q_entry_lo;
- writel(htonl(rxq_cfg.cur_q_entry_lo), base_addr + off);
-
- off = (unsigned long)&rxq_mem->cur_q_entry_hi;
- writel(htonl(rxq_cfg.cur_q_entry_hi), base_addr + off);
-
- off = (unsigned long)&rxq_mem->pg_cnt_n_prd_ptr;
- writel(rxq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
-
- off = (unsigned long)&rxq_mem->entry_n_pg_size;
- writel(rxq_cfg.entry_n_pg_size, base_addr + off);
-
- off = (unsigned long)&rxq_mem->sg_n_cq_n_cns_ptr;
- writel(rxq_cfg.sg_n_cq_n_cns_ptr, base_addr + off);
-
- off = (unsigned long)&rxq_mem->buf_sz_n_q_state;
- writel(rxq_cfg.buf_sz_n_q_state, base_addr + off);
-
- off = (unsigned long)&rxq_mem->next_qid;
- writel(rxq_cfg.next_qid, base_addr + off);
-
- rxq->rcb->producer_index = 0;
- rxq->rcb->consumer_index = 0;
-}
-
-void
-__bna_cq_start(struct bna_cq *cq)
-{
- struct bna_cq_mem cq_cfg, *cq_mem;
- const struct bna_qpt *qpt;
- struct bna_dma_addr cur_q_addr;
- u32 pg_num;
- struct bna *bna = cq->rx->bna;
- void __iomem *base_addr;
- unsigned long off;
-
- qpt = &cq->qpt;
- cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
-
- /*
- * Fill out structure, to be subsequently written
- * to hardware
- */
- cq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
- cq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
- cq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
- cq_cfg.cur_q_entry_hi = cur_q_addr.msb;
-
- cq_cfg.pg_cnt_n_prd_ptr = (qpt->page_count << 16) | 0x0;
- cq_cfg.entry_n_pg_size =
- ((u32)(BFI_CQ_WI_SIZE >> 2) << 16) | (qpt->page_size >> 2);
- cq_cfg.int_blk_n_cns_ptr = ((((u32)cq->ib_seg_offset) << 24) |
- ((u32)(cq->ib->ib_id & 0xff) << 16) | 0x0);
- cq_cfg.q_state = BNA_Q_IDLE_STATE;
-
- /* Write the page number register */
- pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num,
- HQM_CQ_RAM_BASE_OFFSET);
-
- writel(pg_num, bna->regs.page_addr);
-
- /* H/W write */
- base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
- HQM_CQ_RAM_BASE_OFFSET);
-
- cq_mem = (struct bna_cq_mem *)0;
-
- off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_lo;
- writel(htonl(cq_cfg.pg_tbl_addr_lo), base_addr + off);
-
- off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_hi;
- writel(htonl(cq_cfg.pg_tbl_addr_hi), base_addr + off);
-
- off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_lo;
- writel(htonl(cq_cfg.cur_q_entry_lo), base_addr + off);
-
- off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_hi;
- writel(htonl(cq_cfg.cur_q_entry_hi), base_addr + off);
-
- off = (unsigned long)&cq_mem[cq->cq_id].pg_cnt_n_prd_ptr;
- writel(cq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
-
- off = (unsigned long)&cq_mem[cq->cq_id].entry_n_pg_size;
- writel(cq_cfg.entry_n_pg_size, base_addr + off);
-
- off = (unsigned long)&cq_mem[cq->cq_id].int_blk_n_cns_ptr;
- writel(cq_cfg.int_blk_n_cns_ptr, base_addr + off);
-
- off = (unsigned long)&cq_mem[cq->cq_id].q_state;
- writel(cq_cfg.q_state, base_addr + off);
-
- cq->ccb->producer_index = 0;
- *(cq->ccb->hw_producer_index) = 0;
-}
-
-void
-bna_rit_create(struct bna_rx *rx)
-{
- struct list_head *qe_rxp;
- struct bna_rxp *rxp;
- struct bna_rxq *q0 = NULL;
- struct bna_rxq *q1 = NULL;
- int offset;
-
- offset = 0;
- list_for_each(qe_rxp, &rx->rxp_q) {
- rxp = (struct bna_rxp *)qe_rxp;
- GET_RXQS(rxp, q0, q1);
- rx->rxf.rit_segment->rit[offset].large_rxq_id = q0->rxq_id;
- rx->rxf.rit_segment->rit[offset].small_rxq_id =
- (q1 ? q1->rxq_id : 0);
- offset++;
- }
-}
-
-static int
-_rx_can_satisfy(struct bna_rx_mod *rx_mod,
- struct bna_rx_config *rx_cfg)
-{
- if ((rx_mod->rx_free_count == 0) ||
- (rx_mod->rxp_free_count == 0) ||
- (rx_mod->rxq_free_count == 0))
- return 0;
-
- if (rx_cfg->rxp_type == BNA_RXP_SINGLE) {
- if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
- (rx_mod->rxq_free_count < rx_cfg->num_paths))
- return 0;
- } else {
- if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
- (rx_mod->rxq_free_count < (2 * rx_cfg->num_paths)))
- return 0;
- }
-
- if (!bna_rit_mod_can_satisfy(&rx_mod->bna->rit_mod, rx_cfg->num_paths))
- return 0;
-
- return 1;
-}
-
-static struct bna_rxq *
-_get_free_rxq(struct bna_rx_mod *rx_mod)
-{
- struct bna_rxq *rxq = NULL;
- struct list_head *qe = NULL;
-
- bfa_q_deq(&rx_mod->rxq_free_q, &qe);
- if (qe) {
- rx_mod->rxq_free_count--;
- rxq = (struct bna_rxq *)qe;
- }
- return rxq;
-}
-
-static void
-_put_free_rxq(struct bna_rx_mod *rx_mod, struct bna_rxq *rxq)
-{
- bfa_q_qe_init(&rxq->qe);
- list_add_tail(&rxq->qe, &rx_mod->rxq_free_q);
- rx_mod->rxq_free_count++;
-}
-
-static struct bna_rxp *
-_get_free_rxp(struct bna_rx_mod *rx_mod)
-{
- struct list_head *qe = NULL;
- struct bna_rxp *rxp = NULL;
-
- bfa_q_deq(&rx_mod->rxp_free_q, &qe);
- if (qe) {
- rx_mod->rxp_free_count--;
-
- rxp = (struct bna_rxp *)qe;
- }
-
- return rxp;
-}
-
-static void
-_put_free_rxp(struct bna_rx_mod *rx_mod, struct bna_rxp *rxp)
-{
- bfa_q_qe_init(&rxp->qe);
- list_add_tail(&rxp->qe, &rx_mod->rxp_free_q);
- rx_mod->rxp_free_count++;
-}
-
-static struct bna_rx *
-_get_free_rx(struct bna_rx_mod *rx_mod)
-{
- struct list_head *qe = NULL;
- struct bna_rx *rx = NULL;
-
- bfa_q_deq(&rx_mod->rx_free_q, &qe);
- if (qe) {
- rx_mod->rx_free_count--;
-
- rx = (struct bna_rx *)qe;
- bfa_q_qe_init(qe);
- list_add_tail(&rx->qe, &rx_mod->rx_active_q);
- }
-
- return rx;
-}
-
-static void
-_put_free_rx(struct bna_rx_mod *rx_mod, struct bna_rx *rx)
-{
- bfa_q_qe_init(&rx->qe);
- list_add_tail(&rx->qe, &rx_mod->rx_free_q);
- rx_mod->rx_free_count++;
-}
-
-static void
-_rx_init(struct bna_rx *rx, struct bna *bna)
-{
- rx->bna = bna;
- rx->rx_flags = 0;
-
- INIT_LIST_HEAD(&rx->rxp_q);
-
- rx->rxq_stop_wc.wc_resume = bna_rx_cb_rxq_stopped_all;
- rx->rxq_stop_wc.wc_cbarg = rx;
- rx->rxq_stop_wc.wc_count = 0;
-
- rx->stop_cbfn = NULL;
- rx->stop_cbarg = NULL;
-}
-
-static void
-_rxp_add_rxqs(struct bna_rxp *rxp,
- struct bna_rxq *q0,
- struct bna_rxq *q1)
-{
- switch (rxp->type) {
- case BNA_RXP_SINGLE:
- rxp->rxq.single.only = q0;
- rxp->rxq.single.reserved = NULL;
- break;
- case BNA_RXP_SLR:
- rxp->rxq.slr.large = q0;
- rxp->rxq.slr.small = q1;
- break;
- case BNA_RXP_HDS:
- rxp->rxq.hds.data = q0;
- rxp->rxq.hds.hdr = q1;
- break;
- default:
- break;
- }
-}
-
-static void
-_rxq_qpt_init(struct bna_rxq *rxq,
- struct bna_rxp *rxp,
- u32 page_count,
- u32 page_size,
- struct bna_mem_descr *qpt_mem,
- struct bna_mem_descr *swqpt_mem,
- struct bna_mem_descr *page_mem)
-{
- int i;
-
- rxq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
- rxq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
- rxq->qpt.kv_qpt_ptr = qpt_mem->kva;
- rxq->qpt.page_count = page_count;
- rxq->qpt.page_size = page_size;
-
- rxq->rcb->sw_qpt = (void **) swqpt_mem->kva;
-
- for (i = 0; i < rxq->qpt.page_count; i++) {
- rxq->rcb->sw_qpt[i] = page_mem[i].kva;
- ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].lsb =
- page_mem[i].dma.lsb;
- ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].msb =
- page_mem[i].dma.msb;
-
- }
-}
-
-static void
-_rxp_cqpt_setup(struct bna_rxp *rxp,
- u32 page_count,
- u32 page_size,
- struct bna_mem_descr *qpt_mem,
- struct bna_mem_descr *swqpt_mem,
- struct bna_mem_descr *page_mem)
-{
- int i;
-
- rxp->cq.qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
- rxp->cq.qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
- rxp->cq.qpt.kv_qpt_ptr = qpt_mem->kva;
- rxp->cq.qpt.page_count = page_count;
- rxp->cq.qpt.page_size = page_size;
-
- rxp->cq.ccb->sw_qpt = (void **) swqpt_mem->kva;
-
- for (i = 0; i < rxp->cq.qpt.page_count; i++) {
- rxp->cq.ccb->sw_qpt[i] = page_mem[i].kva;
-
- ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].lsb =
- page_mem[i].dma.lsb;
- ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].msb =
- page_mem[i].dma.msb;
-
- }
-}
-
-static void
-_rx_add_rxp(struct bna_rx *rx, struct bna_rxp *rxp)
-{
- list_add_tail(&rxp->qe, &rx->rxp_q);
-}
-
-static void
-_init_rxmod_queues(struct bna_rx_mod *rx_mod)
-{
- INIT_LIST_HEAD(&rx_mod->rx_free_q);
- INIT_LIST_HEAD(&rx_mod->rxq_free_q);
- INIT_LIST_HEAD(&rx_mod->rxp_free_q);
- INIT_LIST_HEAD(&rx_mod->rx_active_q);
-
- rx_mod->rx_free_count = 0;
- rx_mod->rxq_free_count = 0;
- rx_mod->rxp_free_count = 0;
-}
-
-static void
-_rx_ctor(struct bna_rx *rx, int id)
-{
- bfa_q_qe_init(&rx->qe);
- INIT_LIST_HEAD(&rx->rxp_q);
- rx->bna = NULL;
-
- rx->rxf.rxf_id = id;
-
- /* FIXME: mbox_qe ctor()?? */
- bfa_q_qe_init(&rx->mbox_qe.qe);
-
- rx->stop_cbfn = NULL;
- rx->stop_cbarg = NULL;
-}
-
-void
-bna_rx_cb_multi_rxq_stopped(void *arg, int status)
-{
- struct bna_rxp *rxp = (struct bna_rxp *)arg;
-
- bfa_wc_down(&rxp->rx->rxq_stop_wc);
-}
-
-void
-bna_rx_cb_rxq_stopped_all(void *arg)
-{
- struct bna_rx *rx = (struct bna_rx *)arg;
-
- bfa_fsm_send_event(rx, RX_E_RXQ_STOPPED);
-}
-
-static void
-bna_rx_mod_cb_rx_stopped(void *arg, struct bna_rx *rx,
- enum bna_cb_status status)
-{
- struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
-
- bfa_wc_down(&rx_mod->rx_stop_wc);
-}
-
-static void
-bna_rx_mod_cb_rx_stopped_all(void *arg)
-{
- struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
-
- if (rx_mod->stop_cbfn)
- rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS);
- rx_mod->stop_cbfn = NULL;
-}
-
-static void
-bna_rx_start(struct bna_rx *rx)
-{
- rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
- if (rx->rx_flags & BNA_RX_F_ENABLE)
- bfa_fsm_send_event(rx, RX_E_START);
-}
-
-static void
-bna_rx_stop(struct bna_rx *rx)
-{
- rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED;
- if (rx->fsm == (bfa_fsm_t) bna_rx_sm_stopped)
- bna_rx_mod_cb_rx_stopped(&rx->bna->rx_mod, rx, BNA_CB_SUCCESS);
- else {
- rx->stop_cbfn = bna_rx_mod_cb_rx_stopped;
- rx->stop_cbarg = &rx->bna->rx_mod;
- bfa_fsm_send_event(rx, RX_E_STOP);
- }
-}
-
-static void
-bna_rx_fail(struct bna_rx *rx)
-{
- /* Indicate port is not enabled, and failed */
- rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED;
- rx->rx_flags |= BNA_RX_F_PORT_FAILED;
- bfa_fsm_send_event(rx, RX_E_FAIL);
-}
-
-void
-bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
-{
- struct bna_rx *rx;
- struct list_head *qe;
-
- rx_mod->flags |= BNA_RX_MOD_F_PORT_STARTED;
- if (type == BNA_RX_T_LOOPBACK)
- rx_mod->flags |= BNA_RX_MOD_F_PORT_LOOPBACK;
-
- list_for_each(qe, &rx_mod->rx_active_q) {
- rx = (struct bna_rx *)qe;
- if (rx->type == type)
- bna_rx_start(rx);
- }
-}
-
-void
-bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
-{
- struct bna_rx *rx;
- struct list_head *qe;
-
- rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED;
- rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK;
-
- rx_mod->stop_cbfn = bna_port_cb_rx_stopped;
-
- /**
- * Before calling bna_rx_stop(), increment rx_stop_wc as many times
- * as we are going to call bna_rx_stop
- */
- list_for_each(qe, &rx_mod->rx_active_q) {
- rx = (struct bna_rx *)qe;
- if (rx->type == type)
- bfa_wc_up(&rx_mod->rx_stop_wc);
- }
-
- if (rx_mod->rx_stop_wc.wc_count == 0) {
- rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS);
- rx_mod->stop_cbfn = NULL;
- return;
- }
-
- list_for_each(qe, &rx_mod->rx_active_q) {
- rx = (struct bna_rx *)qe;
- if (rx->type == type)
- bna_rx_stop(rx);
- }
-}
-
-void
-bna_rx_mod_fail(struct bna_rx_mod *rx_mod)
-{
- struct bna_rx *rx;
- struct list_head *qe;
-
- rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED;
- rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK;
-
- list_for_each(qe, &rx_mod->rx_active_q) {
- rx = (struct bna_rx *)qe;
- bna_rx_fail(rx);
- }
-}
-
-void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
- struct bna_res_info *res_info)
-{
- int index;
- struct bna_rx *rx_ptr;
- struct bna_rxp *rxp_ptr;
- struct bna_rxq *rxq_ptr;
-
- rx_mod->bna = bna;
- rx_mod->flags = 0;
-
- rx_mod->rx = (struct bna_rx *)
- res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mdl[0].kva;
- rx_mod->rxp = (struct bna_rxp *)
- res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mdl[0].kva;
- rx_mod->rxq = (struct bna_rxq *)
- res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mdl[0].kva;
-
- /* Initialize the queues */
- _init_rxmod_queues(rx_mod);
-
- /* Build RX queues */
- for (index = 0; index < BFI_MAX_RXQ; index++) {
- rx_ptr = &rx_mod->rx[index];
- _rx_ctor(rx_ptr, index);
- list_add_tail(&rx_ptr->qe, &rx_mod->rx_free_q);
- rx_mod->rx_free_count++;
- }
-
- /* build RX-path queue */
- for (index = 0; index < BFI_MAX_RXQ; index++) {
- rxp_ptr = &rx_mod->rxp[index];
- rxp_ptr->cq.cq_id = index;
- bfa_q_qe_init(&rxp_ptr->qe);
- list_add_tail(&rxp_ptr->qe, &rx_mod->rxp_free_q);
- rx_mod->rxp_free_count++;
- }
-
- /* build RXQ queue */
- for (index = 0; index < BFI_MAX_RXQ; index++) {
- rxq_ptr = &rx_mod->rxq[index];
- rxq_ptr->rxq_id = index;
-
- bfa_q_qe_init(&rxq_ptr->qe);
- list_add_tail(&rxq_ptr->qe, &rx_mod->rxq_free_q);
- rx_mod->rxq_free_count++;
- }
-
- rx_mod->rx_stop_wc.wc_resume = bna_rx_mod_cb_rx_stopped_all;
- rx_mod->rx_stop_wc.wc_cbarg = rx_mod;
- rx_mod->rx_stop_wc.wc_count = 0;
-}
-
-void
-bna_rx_mod_uninit(struct bna_rx_mod *rx_mod)
-{
- struct list_head *qe;
- int i;
-
- i = 0;
- list_for_each(qe, &rx_mod->rx_free_q)
- i++;
-
- i = 0;
- list_for_each(qe, &rx_mod->rxp_free_q)
- i++;
-
- i = 0;
- list_for_each(qe, &rx_mod->rxq_free_q)
- i++;
-
- rx_mod->bna = NULL;
-}
-
-int
-bna_rx_state_get(struct bna_rx *rx)
-{
- return bfa_sm_to_state(rx_sm_table, rx->fsm);
-}
-
-void
-bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info)
-{
- u32 cq_size, hq_size, dq_size;
- u32 cpage_count, hpage_count, dpage_count;
- struct bna_mem_info *mem_info;
- u32 cq_depth;
- u32 hq_depth;
- u32 dq_depth;
-
- dq_depth = q_cfg->q_depth;
- hq_depth = ((q_cfg->rxp_type == BNA_RXP_SINGLE) ? 0 : q_cfg->q_depth);
- cq_depth = dq_depth + hq_depth;
-
- BNA_TO_POWER_OF_2_HIGH(cq_depth);
- cq_size = cq_depth * BFI_CQ_WI_SIZE;
- cq_size = ALIGN(cq_size, PAGE_SIZE);
- cpage_count = SIZE_TO_PAGES(cq_size);
-
- BNA_TO_POWER_OF_2_HIGH(dq_depth);
- dq_size = dq_depth * BFI_RXQ_WI_SIZE;
- dq_size = ALIGN(dq_size, PAGE_SIZE);
- dpage_count = SIZE_TO_PAGES(dq_size);
-
- if (BNA_RXP_SINGLE != q_cfg->rxp_type) {
- BNA_TO_POWER_OF_2_HIGH(hq_depth);
- hq_size = hq_depth * BFI_RXQ_WI_SIZE;
- hq_size = ALIGN(hq_size, PAGE_SIZE);
- hpage_count = SIZE_TO_PAGES(hq_size);
- } else {
- hpage_count = 0;
- }
-
- /* CCB structures */
- res_info[BNA_RX_RES_MEM_T_CCB].res_type = BNA_RES_T_MEM;
- mem_info = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info;
- mem_info->mem_type = BNA_MEM_T_KVA;
- mem_info->len = sizeof(struct bna_ccb);
- mem_info->num = q_cfg->num_paths;
-
- /* RCB structures */
- res_info[BNA_RX_RES_MEM_T_RCB].res_type = BNA_RES_T_MEM;
- mem_info = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info;
- mem_info->mem_type = BNA_MEM_T_KVA;
- mem_info->len = sizeof(struct bna_rcb);
- mem_info->num = BNA_GET_RXQS(q_cfg);
-
- /* Completion QPT */
- res_info[BNA_RX_RES_MEM_T_CQPT].res_type = BNA_RES_T_MEM;
- mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info;
- mem_info->mem_type = BNA_MEM_T_DMA;
- mem_info->len = cpage_count * sizeof(struct bna_dma_addr);
- mem_info->num = q_cfg->num_paths;
-
- /* Completion s/w QPT */
- res_info[BNA_RX_RES_MEM_T_CSWQPT].res_type = BNA_RES_T_MEM;
- mem_info = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info;
- mem_info->mem_type = BNA_MEM_T_KVA;
- mem_info->len = cpage_count * sizeof(void *);
- mem_info->num = q_cfg->num_paths;
-
- /* Completion QPT pages */
- 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;
-
- /* Data QPTs */
- 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;
- mem_info->mem_type = BNA_MEM_T_DMA;
- mem_info->len = dpage_count * sizeof(struct bna_dma_addr);
- mem_info->num = q_cfg->num_paths;
-
- /* Data s/w QPTs */
- res_info[BNA_RX_RES_MEM_T_DSWQPT].res_type = BNA_RES_T_MEM;
- mem_info = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info;
- mem_info->mem_type = BNA_MEM_T_KVA;
- mem_info->len = dpage_count * sizeof(void *);
- mem_info->num = q_cfg->num_paths;
-
- /* Data QPT pages */
- 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;
-
- /* Hdr QPTs */
- 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;
- mem_info->mem_type = BNA_MEM_T_DMA;
- mem_info->len = hpage_count * sizeof(struct bna_dma_addr);
- mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
-
- /* Hdr s/w QPTs */
- res_info[BNA_RX_RES_MEM_T_HSWQPT].res_type = BNA_RES_T_MEM;
- mem_info = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info;
- mem_info->mem_type = BNA_MEM_T_KVA;
- mem_info->len = hpage_count * sizeof(void *);
- mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
-
- /* Hdr QPT pages */
- 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);
-
- /* RX Interrupts */
- res_info[BNA_RX_RES_T_INTR].res_type = BNA_RES_T_INTR;
- res_info[BNA_RX_RES_T_INTR].res_u.intr_info.intr_type = BNA_INTR_T_MSIX;
- res_info[BNA_RX_RES_T_INTR].res_u.intr_info.num = q_cfg->num_paths;
-}
-
-struct bna_rx *
-bna_rx_create(struct bna *bna, struct bnad *bnad,
- struct bna_rx_config *rx_cfg,
- struct bna_rx_event_cbfn *rx_cbfn,
- struct bna_res_info *res_info,
- void *priv)
-{
- struct bna_rx_mod *rx_mod = &bna->rx_mod;
- struct bna_rx *rx;
- struct bna_rxp *rxp;
- struct bna_rxq *q0;
- struct bna_rxq *q1;
- struct bna_intr_info *intr_info;
- u32 page_count;
- struct bna_mem_descr *ccb_mem;
- struct bna_mem_descr *rcb_mem;
- struct bna_mem_descr *unmapq_mem;
- struct bna_mem_descr *cqpt_mem;
- struct bna_mem_descr *cswqpt_mem;
- struct bna_mem_descr *cpage_mem;
- struct bna_mem_descr *hqpt_mem; /* Header/Small Q qpt */
- struct bna_mem_descr *dqpt_mem; /* Data/Large Q qpt */
- struct bna_mem_descr *hsqpt_mem; /* s/w qpt for hdr */
- struct bna_mem_descr *dsqpt_mem; /* s/w qpt for data */
- struct bna_mem_descr *hpage_mem; /* hdr page mem */
- struct bna_mem_descr *dpage_mem; /* data page mem */
- int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0;
- int dpage_count, hpage_count, rcb_idx;
- struct bna_ib_config ibcfg;
- /* Fail if we don't have enough RXPs, RXQs */
- if (!_rx_can_satisfy(rx_mod, rx_cfg))
- return NULL;
-
- /* Initialize resource pointers */
- intr_info = &res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
- ccb_mem = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info.mdl[0];
- rcb_mem = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info.mdl[0];
- unmapq_mem = &res_info[BNA_RX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[0];
- cqpt_mem = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info.mdl[0];
- cswqpt_mem = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info.mdl[0];
- cpage_mem = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.mdl[0];
- hqpt_mem = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info.mdl[0];
- dqpt_mem = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info.mdl[0];
- hsqpt_mem = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info.mdl[0];
- dsqpt_mem = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info.mdl[0];
- 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];
-
- /* Compute q depth & page count */
- page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.num /
- rx_cfg->num_paths;
-
- dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.num /
- rx_cfg->num_paths;
-
- hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.num /
- rx_cfg->num_paths;
- /* Get RX pointer */
- rx = _get_free_rx(rx_mod);
- _rx_init(rx, bna);
- rx->priv = priv;
- rx->type = rx_cfg->rx_type;
-
- rx->rcb_setup_cbfn = rx_cbfn->rcb_setup_cbfn;
- rx->rcb_destroy_cbfn = rx_cbfn->rcb_destroy_cbfn;
- rx->ccb_setup_cbfn = rx_cbfn->ccb_setup_cbfn;
- rx->ccb_destroy_cbfn = rx_cbfn->ccb_destroy_cbfn;
- /* Following callbacks are mandatory */
- rx->rx_cleanup_cbfn = rx_cbfn->rx_cleanup_cbfn;
- rx->rx_post_cbfn = rx_cbfn->rx_post_cbfn;
-
- if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_STARTED) {
- switch (rx->type) {
- case BNA_RX_T_REGULAR:
- if (!(rx->bna->rx_mod.flags &
- BNA_RX_MOD_F_PORT_LOOPBACK))
- rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
- break;
- case BNA_RX_T_LOOPBACK:
- if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_LOOPBACK)
- rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
- break;
- }
- }
-
- for (i = 0, rcb_idx = 0; i < rx_cfg->num_paths; i++) {
- rxp = _get_free_rxp(rx_mod);
- rxp->type = rx_cfg->rxp_type;
- rxp->rx = rx;
- rxp->cq.rx = rx;
-
- /* Get required RXQs, and queue them to rx-path */
- q0 = _get_free_rxq(rx_mod);
- if (BNA_RXP_SINGLE == rx_cfg->rxp_type)
- q1 = NULL;
- else
- q1 = _get_free_rxq(rx_mod);
-
- /* Initialize IB */
- if (1 == intr_info->num) {
- rxp->cq.ib = bna_ib_get(&bna->ib_mod,
- intr_info->intr_type,
- intr_info->idl[0].vector);
- rxp->vector = intr_info->idl[0].vector;
- } else {
- rxp->cq.ib = bna_ib_get(&bna->ib_mod,
- intr_info->intr_type,
- intr_info->idl[i].vector);
-
- /* Map the MSI-x vector used for this RXP */
- rxp->vector = intr_info->idl[i].vector;
- }
-
- rxp->cq.ib_seg_offset = bna_ib_reserve_idx(rxp->cq.ib);
-
- ibcfg.coalescing_timeo = BFI_RX_COALESCING_TIMEO;
- ibcfg.interpkt_count = BFI_RX_INTERPKT_COUNT;
- ibcfg.interpkt_timeo = BFI_RX_INTERPKT_TIMEO;
- ibcfg.ctrl_flags = BFI_IB_CF_INT_ENABLE;
-
- bna_ib_config(rxp->cq.ib, &ibcfg);
-
- /* Link rxqs to rxp */
- _rxp_add_rxqs(rxp, q0, q1);
-
- /* Link rxp to rx */
- _rx_add_rxp(rx, rxp);
-
- q0->rx = rx;
- q0->rxp = rxp;
-
- /* Initialize RCB for the large / data q */
- q0->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
- RXQ_RCB_INIT(q0, rxp, rx_cfg->q_depth, bna, 0,
- (void *)unmapq_mem[rcb_idx].kva);
- rcb_idx++;
- (q0)->rx_packets = (q0)->rx_bytes = 0;
- (q0)->rx_packets_with_error = (q0)->rxbuf_alloc_failed = 0;
-
- /* Initialize RXQs */
- _rxq_qpt_init(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;
-
- /* Call bnad to complete rcb setup */
- if (rx->rcb_setup_cbfn)
- rx->rcb_setup_cbfn(bnad, q0->rcb);
-
- if (q1) {
- q1->rx = rx;
- q1->rxp = rxp;
-
- q1->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
- RXQ_RCB_INIT(q1, rxp, rx_cfg->q_depth, bna, 1,
- (void *)unmapq_mem[rcb_idx].kva);
- rcb_idx++;
- (q1)->buffer_size = (rx_cfg)->small_buff_size;
- (q1)->rx_packets = (q1)->rx_bytes = 0;
- (q1)->rx_packets_with_error =
- (q1)->rxbuf_alloc_failed = 0;
-
- _rxq_qpt_init(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;
-
- /* Call bnad to complete rcb setup */
- if (rx->rcb_setup_cbfn)
- rx->rcb_setup_cbfn(bnad, q1->rcb);
- }
- /* Setup RXP::CQ */
- rxp->cq.ccb = (struct bna_ccb *) ccb_mem[i].kva;
- _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;
-
- rxp->cq.ccb->pkt_rate.small_pkt_cnt = 0;
- rxp->cq.ccb->pkt_rate.large_pkt_cnt = 0;
-
- rxp->cq.ccb->producer_index = 0;
- rxp->cq.ccb->q_depth = rx_cfg->q_depth +
- ((rx_cfg->rxp_type == BNA_RXP_SINGLE) ?
- 0 : rx_cfg->q_depth);
- rxp->cq.ccb->i_dbell = &rxp->cq.ib->door_bell;
- rxp->cq.ccb->rcb[0] = q0->rcb;
- if (q1)
- rxp->cq.ccb->rcb[1] = q1->rcb;
- rxp->cq.ccb->cq = &rxp->cq;
- rxp->cq.ccb->bnad = bna->bnad;
- rxp->cq.ccb->hw_producer_index =
- ((volatile u32 *)rxp->cq.ib->ib_seg_host_addr_kva +
- (rxp->cq.ib_seg_offset * BFI_IBIDX_SIZE));
- *(rxp->cq.ccb->hw_producer_index) = 0;
- rxp->cq.ccb->intr_type = intr_info->intr_type;
- rxp->cq.ccb->intr_vector = (intr_info->num == 1) ?
- intr_info->idl[0].vector :
- intr_info->idl[i].vector;
- rxp->cq.ccb->rx_coalescing_timeo =
- rxp->cq.ib->ib_config.coalescing_timeo;
- rxp->cq.ccb->id = i;
-
- /* Call bnad to complete CCB setup */
- if (rx->ccb_setup_cbfn)
- rx->ccb_setup_cbfn(bnad, rxp->cq.ccb);
-
- } /* for each rx-path */
-
- bna_rxf_init(&rx->rxf, rx, rx_cfg);
-
- bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-
- return rx;
-}
-
-void
-bna_rx_destroy(struct bna_rx *rx)
-{
- struct bna_rx_mod *rx_mod = &rx->bna->rx_mod;
- struct bna_ib_mod *ib_mod = &rx->bna->ib_mod;
- struct bna_rxq *q0 = NULL;
- struct bna_rxq *q1 = NULL;
- struct bna_rxp *rxp;
- struct list_head *qe;
-
- bna_rxf_uninit(&rx->rxf);
-
- while (!list_empty(&rx->rxp_q)) {
- bfa_q_deq(&rx->rxp_q, &rxp);
- GET_RXQS(rxp, q0, q1);
- /* Callback to bnad for destroying RCB */
- if (rx->rcb_destroy_cbfn)
- rx->rcb_destroy_cbfn(rx->bna->bnad, q0->rcb);
- q0->rcb = NULL;
- q0->rxp = NULL;
- q0->rx = NULL;
- _put_free_rxq(rx_mod, q0);
- if (q1) {
- /* Callback to bnad for destroying RCB */
- if (rx->rcb_destroy_cbfn)
- rx->rcb_destroy_cbfn(rx->bna->bnad, q1->rcb);
- q1->rcb = NULL;
- q1->rxp = NULL;
- q1->rx = NULL;
- _put_free_rxq(rx_mod, q1);
- }
- rxp->rxq.slr.large = NULL;
- rxp->rxq.slr.small = NULL;
- if (rxp->cq.ib) {
- if (rxp->cq.ib_seg_offset != 0xff)
- bna_ib_release_idx(rxp->cq.ib,
- rxp->cq.ib_seg_offset);
- bna_ib_put(ib_mod, rxp->cq.ib);
- rxp->cq.ib = NULL;
- }
- /* Callback to bnad for destroying CCB */
- if (rx->ccb_destroy_cbfn)
- rx->ccb_destroy_cbfn(rx->bna->bnad, rxp->cq.ccb);
- rxp->cq.ccb = NULL;
- rxp->rx = NULL;
- _put_free_rxp(rx_mod, rxp);
- }
-
- list_for_each(qe, &rx_mod->rx_active_q) {
- if (qe == &rx->qe) {
- list_del(&rx->qe);
- bfa_q_qe_init(&rx->qe);
- break;
- }
- }
-
- rx->bna = NULL;
- rx->priv = NULL;
- _put_free_rx(rx_mod, rx);
-}
-
-void
-bna_rx_enable(struct bna_rx *rx)
-{
- if (rx->fsm != (bfa_sm_t)bna_rx_sm_stopped)
- return;
-
- rx->rx_flags |= BNA_RX_F_ENABLE;
- if (rx->rx_flags & BNA_RX_F_PORT_ENABLED)
- bfa_fsm_send_event(rx, RX_E_START);
-}
-
-void
-bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
- void (*cbfn)(void *, struct bna_rx *,
- enum bna_cb_status))
-{
- if (type == BNA_SOFT_CLEANUP) {
- /* h/w should not be accessed. Treat we're stopped */
- (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
- } else {
- rx->stop_cbfn = cbfn;
- rx->stop_cbarg = rx->bna->bnad;
-
- rx->rx_flags &= ~BNA_RX_F_ENABLE;
-
- bfa_fsm_send_event(rx, RX_E_STOP);
- }
-}
-
-/**
- * TX
- */
-#define call_tx_stop_cbfn(tx, status)\
-do {\
- if ((tx)->stop_cbfn)\
- (tx)->stop_cbfn((tx)->stop_cbarg, (tx), status);\
- (tx)->stop_cbfn = NULL;\
- (tx)->stop_cbarg = NULL;\
-} while (0)
-
-#define call_tx_prio_change_cbfn(tx, status)\
-do {\
- if ((tx)->prio_change_cbfn)\
- (tx)->prio_change_cbfn((tx)->bna->bnad, (tx), status);\
- (tx)->prio_change_cbfn = NULL;\
-} while (0)
-
-static void bna_tx_mod_cb_tx_stopped(void *tx_mod, struct bna_tx *tx,
- enum bna_cb_status status);
-static void bna_tx_cb_txq_stopped(void *arg, int status);
-static void bna_tx_cb_stats_cleared(void *arg, int status);
-static void __bna_tx_stop(struct bna_tx *tx);
-static void __bna_tx_start(struct bna_tx *tx);
-static void __bna_txf_stat_clr(struct bna_tx *tx);
-
-enum bna_tx_event {
- TX_E_START = 1,
- TX_E_STOP = 2,
- TX_E_FAIL = 3,
- TX_E_TXQ_STOPPED = 4,
- TX_E_PRIO_CHANGE = 5,
- TX_E_STAT_CLEARED = 6,
-};
-
-enum bna_tx_state {
- BNA_TX_STOPPED = 1,
- BNA_TX_STARTED = 2,
- BNA_TX_TXQ_STOP_WAIT = 3,
- BNA_TX_PRIO_STOP_WAIT = 4,
- BNA_TX_STAT_CLR_WAIT = 5,
-};
-
-bfa_fsm_state_decl(bna_tx, stopped, struct bna_tx,
- enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, started, struct bna_tx,
- enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, txq_stop_wait, struct bna_tx,
- enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, prio_stop_wait, struct bna_tx,
- enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, stat_clr_wait, struct bna_tx,
- enum bna_tx_event);
-
-static struct bfa_sm_table tx_sm_table[] = {
- {BFA_SM(bna_tx_sm_stopped), BNA_TX_STOPPED},
- {BFA_SM(bna_tx_sm_started), BNA_TX_STARTED},
- {BFA_SM(bna_tx_sm_txq_stop_wait), BNA_TX_TXQ_STOP_WAIT},
- {BFA_SM(bna_tx_sm_prio_stop_wait), BNA_TX_PRIO_STOP_WAIT},
- {BFA_SM(bna_tx_sm_stat_clr_wait), BNA_TX_STAT_CLR_WAIT},
-};
-
-static void
-bna_tx_sm_stopped_entry(struct bna_tx *tx)
-{
- struct bna_txq *txq;
- struct list_head *qe;
-
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- (tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb);
- }
-
- call_tx_stop_cbfn(tx, BNA_CB_SUCCESS);
-}
-
-static void
-bna_tx_sm_stopped(struct bna_tx *tx, enum bna_tx_event event)
-{
- switch (event) {
- case TX_E_START:
- bfa_fsm_set_state(tx, bna_tx_sm_started);
- break;
-
- case TX_E_STOP:
- bfa_fsm_set_state(tx, bna_tx_sm_stopped);
- break;
-
- case TX_E_FAIL:
- /* No-op */
- break;
-
- case TX_E_PRIO_CHANGE:
- call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS);
- break;
-
- case TX_E_TXQ_STOPPED:
- /**
- * This event is received due to flushing of mbox when
- * device fails
- */
- /* No-op */
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_tx_sm_started_entry(struct bna_tx *tx)
-{
- struct bna_txq *txq;
- struct list_head *qe;
-
- __bna_tx_start(tx);
-
- /* Start IB */
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- bna_ib_ack(&txq->ib->door_bell, 0);
- }
-}
-
-static void
-bna_tx_sm_started(struct bna_tx *tx, enum bna_tx_event event)
-{
- struct bna_txq *txq;
- struct list_head *qe;
-
- switch (event) {
- case TX_E_STOP:
- bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait);
- __bna_tx_stop(tx);
- break;
-
- case TX_E_FAIL:
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- bna_ib_fail(txq->ib);
- (tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb);
- }
- bfa_fsm_set_state(tx, bna_tx_sm_stopped);
- break;
-
- case TX_E_PRIO_CHANGE:
- bfa_fsm_set_state(tx, bna_tx_sm_prio_stop_wait);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_tx_sm_txq_stop_wait_entry(struct bna_tx *tx)
-{
-}
-
-static void
-bna_tx_sm_txq_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
-{
- struct bna_txq *txq;
- struct list_head *qe;
-
- switch (event) {
- case TX_E_FAIL:
- bfa_fsm_set_state(tx, bna_tx_sm_stopped);
- break;
-
- case TX_E_TXQ_STOPPED:
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- bna_ib_stop(txq->ib);
- }
- bfa_fsm_set_state(tx, bna_tx_sm_stat_clr_wait);
- break;
-
- case TX_E_PRIO_CHANGE:
- /* No-op */
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_tx_sm_prio_stop_wait_entry(struct bna_tx *tx)
-{
- __bna_tx_stop(tx);
-}
-
-static void
-bna_tx_sm_prio_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
-{
- struct bna_txq *txq;
- struct list_head *qe;
-
- switch (event) {
- case TX_E_STOP:
- bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait);
- break;
-
- case TX_E_FAIL:
- call_tx_prio_change_cbfn(tx, BNA_CB_FAIL);
- bfa_fsm_set_state(tx, bna_tx_sm_stopped);
- break;
-
- case TX_E_TXQ_STOPPED:
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- bna_ib_stop(txq->ib);
- (tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb);
- }
- call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS);
- bfa_fsm_set_state(tx, bna_tx_sm_started);
- break;
-
- case TX_E_PRIO_CHANGE:
- /* No-op */
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-bna_tx_sm_stat_clr_wait_entry(struct bna_tx *tx)
-{
- __bna_txf_stat_clr(tx);
-}
-
-static void
-bna_tx_sm_stat_clr_wait(struct bna_tx *tx, enum bna_tx_event event)
-{
- switch (event) {
- case TX_E_FAIL:
- case TX_E_STAT_CLEARED:
- bfa_fsm_set_state(tx, bna_tx_sm_stopped);
- break;
-
- default:
- bfa_sm_fault(event);
- }
-}
-
-static void
-__bna_txq_start(struct bna_tx *tx, struct bna_txq *txq)
-{
- struct bna_rxtx_q_mem *q_mem;
- struct bna_txq_mem txq_cfg;
- struct bna_txq_mem *txq_mem;
- struct bna_dma_addr cur_q_addr;
- u32 pg_num;
- void __iomem *base_addr;
- unsigned long off;
-
- /* Fill out structure, to be subsequently written to hardware */
- txq_cfg.pg_tbl_addr_lo = txq->qpt.hw_qpt_ptr.lsb;
- txq_cfg.pg_tbl_addr_hi = txq->qpt.hw_qpt_ptr.msb;
- cur_q_addr = *((struct bna_dma_addr *)(txq->qpt.kv_qpt_ptr));
- txq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
- txq_cfg.cur_q_entry_hi = cur_q_addr.msb;
-
- txq_cfg.pg_cnt_n_prd_ptr = (txq->qpt.page_count << 16) | 0x0;
-
- txq_cfg.entry_n_pg_size = ((u32)(BFI_TXQ_WI_SIZE >> 2) << 16) |
- (txq->qpt.page_size >> 2);
- txq_cfg.int_blk_n_cns_ptr = ((((u32)txq->ib_seg_offset) << 24) |
- ((u32)(txq->ib->ib_id & 0xff) << 16) | 0x0);
-
- txq_cfg.cns_ptr2_n_q_state = BNA_Q_IDLE_STATE;
- txq_cfg.nxt_qid_n_fid_n_pri = (((tx->txf.txf_id & 0x3f) << 3) |
- (txq->priority & 0x7));
- txq_cfg.wvc_n_cquota_n_rquota =
- ((((u32)BFI_TX_MAX_WRR_QUOTA & 0xfff) << 12) |
- (BFI_TX_MAX_WRR_QUOTA & 0xfff));
-
- /* Setup the page and write to H/W */
-
- pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + tx->bna->port_num,
- HQM_RXTX_Q_RAM_BASE_OFFSET);
- writel(pg_num, tx->bna->regs.page_addr);
-
- base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
- HQM_RXTX_Q_RAM_BASE_OFFSET);
- q_mem = (struct bna_rxtx_q_mem *)0;
- txq_mem = &q_mem[txq->txq_id].txq;
-
- /*
- * The following 4 lines, is a hack b'cos the H/W needs to read
- * these DMA addresses as little endian
- */
-
- off = (unsigned long)&txq_mem->pg_tbl_addr_lo;
- writel(htonl(txq_cfg.pg_tbl_addr_lo), base_addr + off);
-
- off = (unsigned long)&txq_mem->pg_tbl_addr_hi;
- writel(htonl(txq_cfg.pg_tbl_addr_hi), base_addr + off);
-
- off = (unsigned long)&txq_mem->cur_q_entry_lo;
- writel(htonl(txq_cfg.cur_q_entry_lo), base_addr + off);
-
- off = (unsigned long)&txq_mem->cur_q_entry_hi;
- writel(htonl(txq_cfg.cur_q_entry_hi), base_addr + off);
-
- off = (unsigned long)&txq_mem->pg_cnt_n_prd_ptr;
- writel(txq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
-
- off = (unsigned long)&txq_mem->entry_n_pg_size;
- writel(txq_cfg.entry_n_pg_size, base_addr + off);
-
- off = (unsigned long)&txq_mem->int_blk_n_cns_ptr;
- writel(txq_cfg.int_blk_n_cns_ptr, base_addr + off);
-
- off = (unsigned long)&txq_mem->cns_ptr2_n_q_state;
- writel(txq_cfg.cns_ptr2_n_q_state, base_addr + off);
-
- off = (unsigned long)&txq_mem->nxt_qid_n_fid_n_pri;
- writel(txq_cfg.nxt_qid_n_fid_n_pri, base_addr + off);
-
- off = (unsigned long)&txq_mem->wvc_n_cquota_n_rquota;
- writel(txq_cfg.wvc_n_cquota_n_rquota, base_addr + off);
-
- txq->tcb->producer_index = 0;
- txq->tcb->consumer_index = 0;
- *(txq->tcb->hw_consumer_index) = 0;
-
-}
-
-static void
-__bna_txq_stop(struct bna_tx *tx, struct bna_txq *txq)
-{
- struct bfi_ll_q_stop_req ll_req;
- u32 bit_mask[2] = {0, 0};
- if (txq->txq_id < 32)
- bit_mask[0] = (u32)1 << txq->txq_id;
- else
- bit_mask[1] = (u32)1 << (txq->txq_id - 32);
-
- memset(&ll_req, 0, sizeof(ll_req));
- ll_req.mh.msg_class = BFI_MC_LL;
- ll_req.mh.msg_id = BFI_LL_H2I_TXQ_STOP_REQ;
- ll_req.mh.mtag.h2i.lpu_id = 0;
- ll_req.q_id_mask[0] = htonl(bit_mask[0]);
- ll_req.q_id_mask[1] = htonl(bit_mask[1]);
-
- bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req),
- bna_tx_cb_txq_stopped, tx);
-
- bna_mbox_send(tx->bna, &tx->mbox_qe);
-}
-
-static void
-__bna_txf_start(struct bna_tx *tx)
-{
- struct bna_tx_fndb_ram *tx_fndb;
- struct bna_txf *txf = &tx->txf;
- void __iomem *base_addr;
- unsigned long off;
-
- writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
- (tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET),
- tx->bna->regs.page_addr);
-
- base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
- TX_FNDB_RAM_BASE_OFFSET);
-
- tx_fndb = (struct bna_tx_fndb_ram *)0;
- off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags;
-
- writel(((u32)txf->vlan << 16) | txf->ctrl_flags,
- base_addr + off);
-
- if (tx->txf.txf_id < 32)
- tx->bna->tx_mod.txf_bmap[0] |= ((u32)1 << tx->txf.txf_id);
- else
- tx->bna->tx_mod.txf_bmap[1] |= ((u32)
- 1 << (tx->txf.txf_id - 32));
-}
-
-static void
-__bna_txf_stop(struct bna_tx *tx)
-{
- struct bna_tx_fndb_ram *tx_fndb;
- u32 page_num;
- u32 ctl_flags;
- struct bna_txf *txf = &tx->txf;
- void __iomem *base_addr;
- unsigned long off;
-
- /* retrieve the running txf_flags & turn off enable bit */
- page_num = BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
- (tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET);
- writel(page_num, tx->bna->regs.page_addr);
-
- base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
- TX_FNDB_RAM_BASE_OFFSET);
- tx_fndb = (struct bna_tx_fndb_ram *)0;
- off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags;
-
- ctl_flags = readl(base_addr + off);
- ctl_flags &= ~BFI_TXF_CF_ENABLE;
-
- writel(ctl_flags, base_addr + off);
-
- if (tx->txf.txf_id < 32)
- tx->bna->tx_mod.txf_bmap[0] &= ~((u32)1 << tx->txf.txf_id);
- else
- tx->bna->tx_mod.txf_bmap[0] &= ~((u32)
- 1 << (tx->txf.txf_id - 32));
-}
-
-static void
-__bna_txf_stat_clr(struct bna_tx *tx)
-{
- struct bfi_ll_stats_req ll_req;
- u32 txf_bmap[2] = {0, 0};
- if (tx->txf.txf_id < 32)
- txf_bmap[0] = ((u32)1 << tx->txf.txf_id);
- else
- txf_bmap[1] = ((u32)1 << (tx->txf.txf_id - 32));
- bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
- ll_req.stats_mask = 0;
- ll_req.rxf_id_mask[0] = 0;
- ll_req.rxf_id_mask[1] = 0;
- ll_req.txf_id_mask[0] = htonl(txf_bmap[0]);
- ll_req.txf_id_mask[1] = htonl(txf_bmap[1]);
-
- bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req),
- bna_tx_cb_stats_cleared, tx);
- bna_mbox_send(tx->bna, &tx->mbox_qe);
-}
-
-static void
-__bna_tx_start(struct bna_tx *tx)
-{
- struct bna_txq *txq;
- struct list_head *qe;
-
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- bna_ib_start(txq->ib);
- __bna_txq_start(tx, txq);
- }
-
- __bna_txf_start(tx);
-
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- txq->tcb->priority = txq->priority;
- (tx->tx_resume_cbfn)(tx->bna->bnad, txq->tcb);
- }
-}
-
-static void
-__bna_tx_stop(struct bna_tx *tx)
-{
- struct bna_txq *txq;
- struct list_head *qe;
-
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- (tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb);
- }
-
- __bna_txf_stop(tx);
-
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- bfa_wc_up(&tx->txq_stop_wc);
- }
-
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- __bna_txq_stop(tx, txq);
- }
-}
-
-static void
-bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size,
- struct bna_mem_descr *qpt_mem,
- struct bna_mem_descr *swqpt_mem,
- struct bna_mem_descr *page_mem)
-{
- int i;
-
- txq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
- txq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
- txq->qpt.kv_qpt_ptr = qpt_mem->kva;
- txq->qpt.page_count = page_count;
- txq->qpt.page_size = page_size;
-
- txq->tcb->sw_qpt = (void **) swqpt_mem->kva;
-
- for (i = 0; i < page_count; i++) {
- txq->tcb->sw_qpt[i] = page_mem[i].kva;
-
- ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].lsb =
- page_mem[i].dma.lsb;
- ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].msb =
- page_mem[i].dma.msb;
-
- }
-}
-
-static void
-bna_tx_free(struct bna_tx *tx)
-{
- struct bna_tx_mod *tx_mod = &tx->bna->tx_mod;
- struct bna_txq *txq;
- struct bna_ib_mod *ib_mod = &tx->bna->ib_mod;
- struct list_head *qe;
-
- while (!list_empty(&tx->txq_q)) {
- bfa_q_deq(&tx->txq_q, &txq);
- bfa_q_qe_init(&txq->qe);
- if (txq->ib) {
- if (txq->ib_seg_offset != -1)
- bna_ib_release_idx(txq->ib,
- txq->ib_seg_offset);
- bna_ib_put(ib_mod, txq->ib);
- txq->ib = NULL;
- }
- txq->tcb = NULL;
- txq->tx = NULL;
- list_add_tail(&txq->qe, &tx_mod->txq_free_q);
- }
-
- list_for_each(qe, &tx_mod->tx_active_q) {
- if (qe == &tx->qe) {
- list_del(&tx->qe);
- bfa_q_qe_init(&tx->qe);
- break;
- }
- }
-
- tx->bna = NULL;
- tx->priv = NULL;
- list_add_tail(&tx->qe, &tx_mod->tx_free_q);
-}
-
-static void
-bna_tx_cb_txq_stopped(void *arg, int status)
-{
- struct bna_tx *tx = (struct bna_tx *)arg;
-
- bfa_q_qe_init(&tx->mbox_qe.qe);
- bfa_wc_down(&tx->txq_stop_wc);
-}
-
-static void
-bna_tx_cb_txq_stopped_all(void *arg)
-{
- struct bna_tx *tx = (struct bna_tx *)arg;
-
- bfa_fsm_send_event(tx, TX_E_TXQ_STOPPED);
-}
-
-static void
-bna_tx_cb_stats_cleared(void *arg, int status)
-{
- struct bna_tx *tx = (struct bna_tx *)arg;
-
- bfa_q_qe_init(&tx->mbox_qe.qe);
-
- bfa_fsm_send_event(tx, TX_E_STAT_CLEARED);
-}
-
-static void
-bna_tx_start(struct bna_tx *tx)
-{
- tx->flags |= BNA_TX_F_PORT_STARTED;
- if (tx->flags & BNA_TX_F_ENABLED)
- bfa_fsm_send_event(tx, TX_E_START);
-}
-
-static void
-bna_tx_stop(struct bna_tx *tx)
-{
- tx->stop_cbfn = bna_tx_mod_cb_tx_stopped;
- tx->stop_cbarg = &tx->bna->tx_mod;
-
- tx->flags &= ~BNA_TX_F_PORT_STARTED;
- bfa_fsm_send_event(tx, TX_E_STOP);
-}
-
-static void
-bna_tx_fail(struct bna_tx *tx)
-{
- tx->flags &= ~BNA_TX_F_PORT_STARTED;
- bfa_fsm_send_event(tx, TX_E_FAIL);
-}
-
-static void
-bna_tx_prio_changed(struct bna_tx *tx, int prio)
-{
- struct bna_txq *txq;
- struct list_head *qe;
-
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- txq->priority = prio;
- }
-
- bfa_fsm_send_event(tx, TX_E_PRIO_CHANGE);
-}
-
-static void
-bna_tx_cee_link_status(struct bna_tx *tx, int cee_link)
-{
- if (cee_link)
- tx->flags |= BNA_TX_F_PRIO_LOCK;
- else
- tx->flags &= ~BNA_TX_F_PRIO_LOCK;
-}
-
-static void
-bna_tx_mod_cb_tx_stopped(void *arg, struct bna_tx *tx,
- enum bna_cb_status status)
-{
- struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
-
- bfa_wc_down(&tx_mod->tx_stop_wc);
-}
-
-static void
-bna_tx_mod_cb_tx_stopped_all(void *arg)
-{
- struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
-
- if (tx_mod->stop_cbfn)
- tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS);
- tx_mod->stop_cbfn = NULL;
-}
-
-void
-bna_tx_res_req(int num_txq, int txq_depth, struct bna_res_info *res_info)
-{
- u32 q_size;
- u32 page_count;
- struct bna_mem_info *mem_info;
-
- res_info[BNA_TX_RES_MEM_T_TCB].res_type = BNA_RES_T_MEM;
- mem_info = &res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info;
- mem_info->mem_type = BNA_MEM_T_KVA;
- mem_info->len = sizeof(struct bna_tcb);
- mem_info->num = num_txq;
-
- q_size = txq_depth * BFI_TXQ_WI_SIZE;
- q_size = ALIGN(q_size, PAGE_SIZE);
- page_count = q_size >> PAGE_SHIFT;
-
- res_info[BNA_TX_RES_MEM_T_QPT].res_type = BNA_RES_T_MEM;
- mem_info = &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info;
- mem_info->mem_type = BNA_MEM_T_DMA;
- mem_info->len = page_count * sizeof(struct bna_dma_addr);
- mem_info->num = num_txq;
-
- res_info[BNA_TX_RES_MEM_T_SWQPT].res_type = BNA_RES_T_MEM;
- mem_info = &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info;
- mem_info->mem_type = BNA_MEM_T_KVA;
- mem_info->len = page_count * sizeof(void *);
- mem_info->num = num_txq;
-
- 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;
-
- res_info[BNA_TX_RES_INTR_T_TXCMPL].res_type = BNA_RES_T_INTR;
- res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.intr_type =
- BNA_INTR_T_MSIX;
- res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.num = num_txq;
-}
-
-struct bna_tx *
-bna_tx_create(struct bna *bna, struct bnad *bnad,
- struct bna_tx_config *tx_cfg,
- struct bna_tx_event_cbfn *tx_cbfn,
- struct bna_res_info *res_info, void *priv)
-{
- struct bna_intr_info *intr_info;
- struct bna_tx_mod *tx_mod = &bna->tx_mod;
- struct bna_tx *tx;
- struct bna_txq *txq;
- struct list_head *qe;
- struct bna_ib_mod *ib_mod = &bna->ib_mod;
- struct bna_doorbell_qset *qset;
- struct bna_ib_config ib_config;
- int page_count;
- int page_size;
- int page_idx;
- int i;
- unsigned long off;
-
- 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;
-
- /**
- * Get resources
- */
-
- if ((intr_info->num != 1) && (intr_info->num != tx_cfg->num_txq))
- return NULL;
-
- /* Tx */
-
- if (list_empty(&tx_mod->tx_free_q))
- return NULL;
- bfa_q_deq(&tx_mod->tx_free_q, &tx);
- bfa_q_qe_init(&tx->qe);
-
- /* TxQs */
-
- INIT_LIST_HEAD(&tx->txq_q);
- for (i = 0; i < tx_cfg->num_txq; i++) {
- if (list_empty(&tx_mod->txq_free_q))
- goto err_return;
-
- bfa_q_deq(&tx_mod->txq_free_q, &txq);
- bfa_q_qe_init(&txq->qe);
- list_add_tail(&txq->qe, &tx->txq_q);
- txq->ib = NULL;
- txq->ib_seg_offset = -1;
- txq->tx = tx;
- }
-
- /* IBs */
- i = 0;
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
-
- if (intr_info->num == 1)
- txq->ib = bna_ib_get(ib_mod, intr_info->intr_type,
- intr_info->idl[0].vector);
- else
- txq->ib = bna_ib_get(ib_mod, intr_info->intr_type,
- intr_info->idl[i].vector);
-
- if (txq->ib == NULL)
- goto err_return;
-
- txq->ib_seg_offset = bna_ib_reserve_idx(txq->ib);
- if (txq->ib_seg_offset == -1)
- goto err_return;
-
- i++;
- }
-
- /*
- * Initialize
- */
-
- /* Tx */
-
- tx->tcb_setup_cbfn = tx_cbfn->tcb_setup_cbfn;
- tx->tcb_destroy_cbfn = tx_cbfn->tcb_destroy_cbfn;
- /* Following callbacks are mandatory */
- tx->tx_stall_cbfn = tx_cbfn->tx_stall_cbfn;
- tx->tx_resume_cbfn = tx_cbfn->tx_resume_cbfn;
- tx->tx_cleanup_cbfn = tx_cbfn->tx_cleanup_cbfn;
-
- list_add_tail(&tx->qe, &tx_mod->tx_active_q);
- tx->bna = bna;
- tx->priv = priv;
- tx->txq_stop_wc.wc_resume = bna_tx_cb_txq_stopped_all;
- tx->txq_stop_wc.wc_cbarg = tx;
- tx->txq_stop_wc.wc_count = 0;
-
- tx->type = tx_cfg->tx_type;
-
- tx->flags = 0;
- if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_STARTED) {
- switch (tx->type) {
- case BNA_TX_T_REGULAR:
- if (!(tx->bna->tx_mod.flags &
- BNA_TX_MOD_F_PORT_LOOPBACK))
- tx->flags |= BNA_TX_F_PORT_STARTED;
- break;
- case BNA_TX_T_LOOPBACK:
- if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_LOOPBACK)
- tx->flags |= BNA_TX_F_PORT_STARTED;
- break;
- }
- }
- if (tx->bna->tx_mod.cee_link)
- tx->flags |= BNA_TX_F_PRIO_LOCK;
-
- /* TxQ */
-
- i = 0;
- page_idx = 0;
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- txq->priority = tx_mod->priority;
- txq->tcb = (struct bna_tcb *)
- res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info.mdl[i].kva;
- txq->tx_packets = 0;
- txq->tx_bytes = 0;
-
- /* IB */
-
- ib_config.coalescing_timeo = BFI_TX_COALESCING_TIMEO;
- ib_config.interpkt_timeo = 0; /* Not used */
- ib_config.interpkt_count = BFI_TX_INTERPKT_COUNT;
- ib_config.ctrl_flags = (BFI_IB_CF_INTER_PKT_DMA |
- BFI_IB_CF_INT_ENABLE |
- BFI_IB_CF_COALESCING_MODE);
- bna_ib_config(txq->ib, &ib_config);
-
- /* TCB */
-
- txq->tcb->producer_index = 0;
- txq->tcb->consumer_index = 0;
- txq->tcb->hw_consumer_index = (volatile u32 *)
- ((volatile u8 *)txq->ib->ib_seg_host_addr_kva +
- (txq->ib_seg_offset * BFI_IBIDX_SIZE));
- *(txq->tcb->hw_consumer_index) = 0;
- txq->tcb->q_depth = tx_cfg->txq_depth;
- txq->tcb->unmap_q = (void *)
- res_info[BNA_TX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[i].kva;
- qset = (struct bna_doorbell_qset *)0;
- off = (unsigned long)&qset[txq->txq_id].txq[0];
- txq->tcb->q_dbell = off +
- BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva);
- txq->tcb->i_dbell = &txq->ib->door_bell;
- txq->tcb->intr_type = intr_info->intr_type;
- txq->tcb->intr_vector = (intr_info->num == 1) ?
- intr_info->idl[0].vector :
- intr_info->idl[i].vector;
- txq->tcb->txq = txq;
- txq->tcb->bnad = bnad;
- txq->tcb->id = i;
-
- /* QPT, SWQPT, Pages */
- 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;
-
- /* Callback to bnad for setting up TCB */
- if (tx->tcb_setup_cbfn)
- (tx->tcb_setup_cbfn)(bna->bnad, txq->tcb);
-
- i++;
- }
-
- /* TxF */
-
- tx->txf.ctrl_flags = BFI_TXF_CF_ENABLE | BFI_TXF_CF_VLAN_WI_BASED;
- tx->txf.vlan = 0;
-
- /* Mbox element */
- bfa_q_qe_init(&tx->mbox_qe.qe);
-
- bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-
- return tx;
-
-err_return:
- bna_tx_free(tx);
- return NULL;
-}
-
-void
-bna_tx_destroy(struct bna_tx *tx)
-{
- /* Callback to bnad for destroying TCB */
- if (tx->tcb_destroy_cbfn) {
- struct bna_txq *txq;
- struct list_head *qe;
-
- list_for_each(qe, &tx->txq_q) {
- txq = (struct bna_txq *)qe;
- (tx->tcb_destroy_cbfn)(tx->bna->bnad, txq->tcb);
- }
- }
-
- bna_tx_free(tx);
-}
-
-void
-bna_tx_enable(struct bna_tx *tx)
-{
- if (tx->fsm != (bfa_sm_t)bna_tx_sm_stopped)
- return;
-
- tx->flags |= BNA_TX_F_ENABLED;
-
- if (tx->flags & BNA_TX_F_PORT_STARTED)
- bfa_fsm_send_event(tx, TX_E_START);
-}
-
-void
-bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
- void (*cbfn)(void *, struct bna_tx *, enum bna_cb_status))
-{
- if (type == BNA_SOFT_CLEANUP) {
- (*cbfn)(tx->bna->bnad, tx, BNA_CB_SUCCESS);
- return;
- }
-
- tx->stop_cbfn = cbfn;
- tx->stop_cbarg = tx->bna->bnad;
-
- tx->flags &= ~BNA_TX_F_ENABLED;
-
- bfa_fsm_send_event(tx, TX_E_STOP);
-}
-
-int
-bna_tx_state_get(struct bna_tx *tx)
-{
- return bfa_sm_to_state(tx_sm_table, tx->fsm);
-}
-
-void
-bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
- struct bna_res_info *res_info)
-{
- int i;
-
- tx_mod->bna = bna;
- tx_mod->flags = 0;
-
- tx_mod->tx = (struct bna_tx *)
- res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mdl[0].kva;
- tx_mod->txq = (struct bna_txq *)
- res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mdl[0].kva;
-
- INIT_LIST_HEAD(&tx_mod->tx_free_q);
- INIT_LIST_HEAD(&tx_mod->tx_active_q);
-
- INIT_LIST_HEAD(&tx_mod->txq_free_q);
-
- for (i = 0; i < BFI_MAX_TXQ; i++) {
- tx_mod->tx[i].txf.txf_id = i;
- bfa_q_qe_init(&tx_mod->tx[i].qe);
- list_add_tail(&tx_mod->tx[i].qe, &tx_mod->tx_free_q);
-
- tx_mod->txq[i].txq_id = i;
- bfa_q_qe_init(&tx_mod->txq[i].qe);
- list_add_tail(&tx_mod->txq[i].qe, &tx_mod->txq_free_q);
- }
-
- tx_mod->tx_stop_wc.wc_resume = bna_tx_mod_cb_tx_stopped_all;
- tx_mod->tx_stop_wc.wc_cbarg = tx_mod;
- tx_mod->tx_stop_wc.wc_count = 0;
-}
-
-void
-bna_tx_mod_uninit(struct bna_tx_mod *tx_mod)
-{
- struct list_head *qe;
- int i;
-
- i = 0;
- list_for_each(qe, &tx_mod->tx_free_q)
- i++;
-
- i = 0;
- list_for_each(qe, &tx_mod->txq_free_q)
- i++;
-
- tx_mod->bna = NULL;
-}
-
-void
-bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
-{
- struct bna_tx *tx;
- struct list_head *qe;
-
- tx_mod->flags |= BNA_TX_MOD_F_PORT_STARTED;
- if (type == BNA_TX_T_LOOPBACK)
- tx_mod->flags |= BNA_TX_MOD_F_PORT_LOOPBACK;
-
- list_for_each(qe, &tx_mod->tx_active_q) {
- tx = (struct bna_tx *)qe;
- if (tx->type == type)
- bna_tx_start(tx);
- }
-}
-
-void
-bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
-{
- struct bna_tx *tx;
- struct list_head *qe;
-
- tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED;
- tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK;
-
- tx_mod->stop_cbfn = bna_port_cb_tx_stopped;
-
- /**
- * Before calling bna_tx_stop(), increment tx_stop_wc as many times
- * as we are going to call bna_tx_stop
- */
- list_for_each(qe, &tx_mod->tx_active_q) {
- tx = (struct bna_tx *)qe;
- if (tx->type == type)
- bfa_wc_up(&tx_mod->tx_stop_wc);
- }
-
- if (tx_mod->tx_stop_wc.wc_count == 0) {
- tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS);
- tx_mod->stop_cbfn = NULL;
- return;
- }
-
- list_for_each(qe, &tx_mod->tx_active_q) {
- tx = (struct bna_tx *)qe;
- if (tx->type == type)
- bna_tx_stop(tx);
- }
-}
-
-void
-bna_tx_mod_fail(struct bna_tx_mod *tx_mod)
-{
- struct bna_tx *tx;
- struct list_head *qe;
-
- tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED;
- tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK;
-
- list_for_each(qe, &tx_mod->tx_active_q) {
- tx = (struct bna_tx *)qe;
- bna_tx_fail(tx);
- }
-}
-
-void
-bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio)
-{
- struct bna_tx *tx;
- struct list_head *qe;
-
- if (prio != tx_mod->priority) {
- tx_mod->priority = prio;
-
- list_for_each(qe, &tx_mod->tx_active_q) {
- tx = (struct bna_tx *)qe;
- bna_tx_prio_changed(tx, prio);
- }
- }
-}
-
-void
-bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link)
-{
- struct bna_tx *tx;
- struct list_head *qe;
-
- tx_mod->cee_link = cee_link;
-
- list_for_each(qe, &tx_mod->tx_active_q) {
- tx = (struct bna_tx *)qe;
- bna_tx_cee_link_status(tx, cee_link);
- }
-}
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 47b928ed08f8..0ae0d7c54ccf 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -1135,13 +1135,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
__record_pdu(lacpdu, port);
port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT));
port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
- // verify that if the aggregator is enabled, the port is enabled too.
- //(because if the link goes down for a short time, the 802.3ad will not
- // catch it, and the port will continue to be disabled)
- if (port->aggregator
- && port->aggregator->is_active
- && !__port_is_enabled(port))
- __enable_port(port);
break;
default: //to silence the compiler
break;
@@ -2117,9 +2110,6 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
read_lock(&bond->lock);
- if (bond->kill_timers)
- goto out;
-
//check if there are any slaves
if (bond->slave_cnt == 0)
goto re_arm;
@@ -2168,9 +2158,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
}
re_arm:
- if (!bond->kill_timers)
- queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks);
-out:
+ queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks);
+
read_unlock(&bond->lock);
}
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index d4fbd2e62616..106b88a04738 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1343,10 +1343,6 @@ void bond_alb_monitor(struct work_struct *work)
read_lock(&bond->lock);
- if (bond->kill_timers) {
- goto out;
- }
-
if (bond->slave_cnt == 0) {
bond_info->tx_rebalance_counter = 0;
bond_info->lp_counter = 0;
@@ -1401,10 +1397,13 @@ void bond_alb_monitor(struct work_struct *work)
/*
* dev_set_promiscuity requires rtnl and
- * nothing else.
+ * nothing else. Avoid race with bond_close.
*/
read_unlock(&bond->lock);
- rtnl_lock();
+ if (!rtnl_trylock()) {
+ read_lock(&bond->lock);
+ goto re_arm;
+ }
bond_info->rlb_promisc_timeout_counter = 0;
@@ -1440,9 +1439,8 @@ void bond_alb_monitor(struct work_struct *work)
}
re_arm:
- if (!bond->kill_timers)
- queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks);
-out:
+ queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks);
+
read_unlock(&bond->lock);
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index de3d351ccb6b..c34cc1e7c6f6 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -395,7 +395,6 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
struct net_device *slave_dev)
{
skb->dev = slave_dev;
- skb->priority = 1;
skb->queue_mapping = bond_queue_mapping(skb);
@@ -557,7 +556,7 @@ down:
static int bond_update_speed_duplex(struct slave *slave)
{
struct net_device *slave_dev = slave->dev;
- struct ethtool_cmd etool = { .cmd = ETHTOOL_GSET };
+ struct ethtool_cmd ecmd;
u32 slave_speed;
int res;
@@ -565,18 +564,15 @@ static int bond_update_speed_duplex(struct slave *slave)
slave->speed = SPEED_100;
slave->duplex = DUPLEX_FULL;
- if (!slave_dev->ethtool_ops || !slave_dev->ethtool_ops->get_settings)
- return -1;
-
- res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool);
+ res = __ethtool_get_settings(slave_dev, &ecmd);
if (res < 0)
return -1;
- slave_speed = ethtool_cmd_speed(&etool);
+ slave_speed = ethtool_cmd_speed(&ecmd);
if (slave_speed == 0 || slave_speed == ((__u32) -1))
return -1;
- switch (etool.duplex) {
+ switch (ecmd.duplex) {
case DUPLEX_FULL:
case DUPLEX_HALF:
break;
@@ -585,7 +581,7 @@ static int bond_update_speed_duplex(struct slave *slave)
}
slave->speed = slave_speed;
- slave->duplex = etool.duplex;
+ slave->duplex = ecmd.duplex;
return 0;
}
@@ -777,9 +773,6 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
read_lock(&bond->lock);
- if (bond->kill_timers)
- goto out;
-
/* rejoin all groups on bond device */
__bond_resend_igmp_join_requests(bond->dev);
@@ -793,9 +786,9 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
__bond_resend_igmp_join_requests(vlan_dev);
}
- if ((--bond->igmp_retrans > 0) && !bond->kill_timers)
+ if (--bond->igmp_retrans > 0)
queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5);
-out:
+
read_unlock(&bond->lock);
}
@@ -2521,10 +2514,11 @@ void bond_mii_monitor(struct work_struct *work)
struct bonding *bond = container_of(work, struct bonding,
mii_work.work);
bool should_notify_peers = false;
+ unsigned long delay;
read_lock(&bond->lock);
- if (bond->kill_timers)
- goto out;
+
+ delay = msecs_to_jiffies(bond->params.miimon);
if (bond->slave_cnt == 0)
goto re_arm;
@@ -2533,7 +2527,15 @@ void bond_mii_monitor(struct work_struct *work)
if (bond_miimon_inspect(bond)) {
read_unlock(&bond->lock);
- rtnl_lock();
+
+ /* Race avoidance with bond_close cancel of workqueue */
+ if (!rtnl_trylock()) {
+ read_lock(&bond->lock);
+ delay = 1;
+ should_notify_peers = false;
+ goto re_arm;
+ }
+
read_lock(&bond->lock);
bond_miimon_commit(bond);
@@ -2544,14 +2546,18 @@ void bond_mii_monitor(struct work_struct *work)
}
re_arm:
- if (bond->params.miimon && !bond->kill_timers)
- queue_delayed_work(bond->wq, &bond->mii_work,
- msecs_to_jiffies(bond->params.miimon));
-out:
+ if (bond->params.miimon)
+ queue_delayed_work(bond->wq, &bond->mii_work, delay);
+
read_unlock(&bond->lock);
if (should_notify_peers) {
- rtnl_lock();
+ if (!rtnl_trylock()) {
+ read_lock(&bond->lock);
+ bond->send_peer_notif++;
+ read_unlock(&bond->lock);
+ return;
+ }
netdev_bonding_change(bond->dev, NETDEV_NOTIFY_PEERS);
rtnl_unlock();
}
@@ -2793,9 +2799,6 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
- if (bond->kill_timers)
- goto out;
-
if (bond->slave_cnt == 0)
goto re_arm;
@@ -2892,9 +2895,9 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
}
re_arm:
- if (bond->params.arp_interval && !bond->kill_timers)
+ if (bond->params.arp_interval)
queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
-out:
+
read_unlock(&bond->lock);
}
@@ -3135,9 +3138,6 @@ void bond_activebackup_arp_mon(struct work_struct *work)
read_lock(&bond->lock);
- if (bond->kill_timers)
- goto out;
-
delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
if (bond->slave_cnt == 0)
@@ -3147,7 +3147,15 @@ void bond_activebackup_arp_mon(struct work_struct *work)
if (bond_ab_arp_inspect(bond, delta_in_ticks)) {
read_unlock(&bond->lock);
- rtnl_lock();
+
+ /* Race avoidance with bond_close flush of workqueue */
+ if (!rtnl_trylock()) {
+ read_lock(&bond->lock);
+ delta_in_ticks = 1;
+ should_notify_peers = false;
+ goto re_arm;
+ }
+
read_lock(&bond->lock);
bond_ab_arp_commit(bond, delta_in_ticks);
@@ -3160,13 +3168,18 @@ void bond_activebackup_arp_mon(struct work_struct *work)
bond_ab_arp_probe(bond);
re_arm:
- if (bond->params.arp_interval && !bond->kill_timers)
+ if (bond->params.arp_interval)
queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
-out:
+
read_unlock(&bond->lock);
if (should_notify_peers) {
- rtnl_lock();
+ if (!rtnl_trylock()) {
+ read_lock(&bond->lock);
+ bond->send_peer_notif++;
+ read_unlock(&bond->lock);
+ return;
+ }
netdev_bonding_change(bond->dev, NETDEV_NOTIFY_PEERS);
rtnl_unlock();
}
@@ -3428,8 +3441,6 @@ static int bond_open(struct net_device *bond_dev)
struct slave *slave;
int i;
- bond->kill_timers = 0;
-
/* reset slave->backup and slave->inactive */
read_lock(&bond->lock);
if (bond->slave_cnt > 0) {
@@ -3498,33 +3509,30 @@ static int bond_close(struct net_device *bond_dev)
bond->send_peer_notif = 0;
- /* signal timers not to re-arm */
- bond->kill_timers = 1;
-
write_unlock_bh(&bond->lock);
if (bond->params.miimon) { /* link check interval, in milliseconds. */
- cancel_delayed_work(&bond->mii_work);
+ cancel_delayed_work_sync(&bond->mii_work);
}
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- cancel_delayed_work(&bond->arp_work);
+ cancel_delayed_work_sync(&bond->arp_work);
}
switch (bond->params.mode) {
case BOND_MODE_8023AD:
- cancel_delayed_work(&bond->ad_work);
+ cancel_delayed_work_sync(&bond->ad_work);
break;
case BOND_MODE_TLB:
case BOND_MODE_ALB:
- cancel_delayed_work(&bond->alb_work);
+ cancel_delayed_work_sync(&bond->alb_work);
break;
default:
break;
}
if (delayed_work_pending(&bond->mcast_work))
- cancel_delayed_work(&bond->mcast_work);
+ cancel_delayed_work_sync(&bond->mcast_work);
if (bond_is_lb(bond)) {
/* Must be called only after all
@@ -3710,44 +3718,27 @@ static bool bond_addr_in_mc_list(unsigned char *addr,
return false;
}
-static void bond_set_multicast_list(struct net_device *bond_dev)
+static void bond_change_rx_flags(struct net_device *bond_dev, int change)
{
struct bonding *bond = netdev_priv(bond_dev);
- struct netdev_hw_addr *ha;
- bool found;
-
- /*
- * Do promisc before checking multicast_mode
- */
- if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC))
- /*
- * FIXME: Need to handle the error when one of the multi-slaves
- * encounters error.
- */
- bond_set_promiscuity(bond, 1);
-
-
- if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC))
- bond_set_promiscuity(bond, -1);
-
-
- /* set allmulti flag to slaves */
- if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI))
- /*
- * FIXME: Need to handle the error when one of the multi-slaves
- * encounters error.
- */
- bond_set_allmulti(bond, 1);
+ if (change & IFF_PROMISC)
+ bond_set_promiscuity(bond,
+ bond_dev->flags & IFF_PROMISC ? 1 : -1);
- if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI))
- bond_set_allmulti(bond, -1);
+ if (change & IFF_ALLMULTI)
+ bond_set_allmulti(bond,
+ bond_dev->flags & IFF_ALLMULTI ? 1 : -1);
+}
+static void bond_set_multicast_list(struct net_device *bond_dev)
+{
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct netdev_hw_addr *ha;
+ bool found;
read_lock(&bond->lock);
- bond->flags = bond_dev->flags;
-
/* looking for addresses to add to slaves' mc list */
netdev_for_each_mc_addr(ha, bond_dev) {
found = bond_addr_in_mc_list(ha->addr, &bond->mc_list,
@@ -4306,7 +4297,8 @@ static const struct net_device_ops bond_netdev_ops = {
.ndo_select_queue = bond_select_queue,
.ndo_get_stats64 = bond_get_stats,
.ndo_do_ioctl = bond_do_ioctl,
- .ndo_set_multicast_list = bond_set_multicast_list,
+ .ndo_change_rx_flags = bond_change_rx_flags,
+ .ndo_set_rx_mode = bond_set_multicast_list,
.ndo_change_mtu = bond_change_mtu,
.ndo_set_mac_address = bond_set_mac_address,
.ndo_neigh_setup = bond_neigh_setup,
@@ -4387,26 +4379,22 @@ static void bond_setup(struct net_device *bond_dev)
static void bond_work_cancel_all(struct bonding *bond)
{
- write_lock_bh(&bond->lock);
- bond->kill_timers = 1;
- write_unlock_bh(&bond->lock);
-
if (bond->params.miimon && delayed_work_pending(&bond->mii_work))
- cancel_delayed_work(&bond->mii_work);
+ cancel_delayed_work_sync(&bond->mii_work);
if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work))
- cancel_delayed_work(&bond->arp_work);
+ cancel_delayed_work_sync(&bond->arp_work);
if (bond->params.mode == BOND_MODE_ALB &&
delayed_work_pending(&bond->alb_work))
- cancel_delayed_work(&bond->alb_work);
+ cancel_delayed_work_sync(&bond->alb_work);
if (bond->params.mode == BOND_MODE_8023AD &&
delayed_work_pending(&bond->ad_work))
- cancel_delayed_work(&bond->ad_work);
+ cancel_delayed_work_sync(&bond->ad_work);
if (delayed_work_pending(&bond->mcast_work))
- cancel_delayed_work(&bond->mcast_work);
+ cancel_delayed_work_sync(&bond->mcast_work);
}
/*
@@ -4852,11 +4840,20 @@ static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
return 0;
}
+static int bond_get_tx_queues(struct net *net, struct nlattr *tb[],
+ unsigned int *num_queues,
+ unsigned int *real_num_queues)
+{
+ *num_queues = tx_queues;
+ return 0;
+}
+
static struct rtnl_link_ops bond_link_ops __read_mostly = {
.kind = "bond",
.priv_size = sizeof(struct bonding),
.setup = bond_setup,
.validate = bond_validate,
+ .get_tx_queues = bond_get_tx_queues,
};
/* Create a new bond based on the specified name and bonding parameters.
@@ -4901,6 +4898,7 @@ static int __net_init bond_net_init(struct net *net)
INIT_LIST_HEAD(&bn->dev_list);
bond_create_proc_dir(bn);
+ bond_create_sysfs(bn);
return 0;
}
@@ -4909,6 +4907,7 @@ static void __net_exit bond_net_exit(struct net *net)
{
struct bond_net *bn = net_generic(net, bond_net_id);
+ bond_destroy_sysfs(bn);
bond_destroy_proc_dir(bn);
}
@@ -4946,10 +4945,6 @@ static int __init bonding_init(void)
goto err;
}
- res = bond_create_sysfs();
- if (res)
- goto err;
-
register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier);
out:
@@ -4967,7 +4962,6 @@ static void __exit bonding_exit(void)
unregister_netdevice_notifier(&bond_netdev_notifier);
unregister_inetaddr_notifier(&bond_inetaddr_notifier);
- bond_destroy_sysfs();
bond_destroy_debugfs();
rtnl_link_unregister(&bond_link_ops);
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 2dfb4bf90087..5a20804fdece 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -55,8 +55,8 @@ static ssize_t bonding_show_bonds(struct class *cls,
struct class_attribute *attr,
char *buf)
{
- struct net *net = current->nsproxy->net_ns;
- struct bond_net *bn = net_generic(net, bond_net_id);
+ struct bond_net *bn =
+ container_of(attr, struct bond_net, class_attr_bonding_masters);
int res = 0;
struct bonding *bond;
@@ -79,9 +79,8 @@ static ssize_t bonding_show_bonds(struct class *cls,
return res;
}
-static struct net_device *bond_get_by_name(struct net *net, const char *ifname)
+static struct net_device *bond_get_by_name(struct bond_net *bn, const char *ifname)
{
- struct bond_net *bn = net_generic(net, bond_net_id);
struct bonding *bond;
list_for_each_entry(bond, &bn->dev_list, bond_list) {
@@ -103,7 +102,8 @@ static ssize_t bonding_store_bonds(struct class *cls,
struct class_attribute *attr,
const char *buffer, size_t count)
{
- struct net *net = current->nsproxy->net_ns;
+ struct bond_net *bn =
+ container_of(attr, struct bond_net, class_attr_bonding_masters);
char command[IFNAMSIZ + 1] = {0, };
char *ifname;
int rv, res = count;
@@ -116,7 +116,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
if (command[0] == '+') {
pr_info("%s is being created...\n", ifname);
- rv = bond_create(net, ifname);
+ rv = bond_create(bn->net, ifname);
if (rv) {
if (rv == -EEXIST)
pr_info("%s already exists.\n", ifname);
@@ -128,7 +128,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
struct net_device *bond_dev;
rtnl_lock();
- bond_dev = bond_get_by_name(net, ifname);
+ bond_dev = bond_get_by_name(bn, ifname);
if (bond_dev) {
pr_info("%s is being deleted...\n", ifname);
unregister_netdevice(bond_dev);
@@ -150,9 +150,24 @@ err_no_cmd:
return -EPERM;
}
+static const void *bonding_namespace(struct class *cls,
+ const struct class_attribute *attr)
+{
+ const struct bond_net *bn =
+ container_of(attr, struct bond_net, class_attr_bonding_masters);
+ return bn->net;
+}
+
/* class attribute for bond_masters file. This ends up in /sys/class/net */
-static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
- bonding_show_bonds, bonding_store_bonds);
+static const struct class_attribute class_attr_bonding_masters = {
+ .attr = {
+ .name = "bonding_masters",
+ .mode = S_IWUSR | S_IRUGO,
+ },
+ .show = bonding_show_bonds,
+ .store = bonding_store_bonds,
+ .namespace = bonding_namespace,
+};
int bond_create_slave_symlinks(struct net_device *master,
struct net_device *slave)
@@ -1655,11 +1670,14 @@ static struct attribute_group bonding_group = {
* Initialize sysfs. This sets up the bonding_masters file in
* /sys/class/net.
*/
-int bond_create_sysfs(void)
+int bond_create_sysfs(struct bond_net *bn)
{
int ret;
- ret = netdev_class_create_file(&class_attr_bonding_masters);
+ bn->class_attr_bonding_masters = class_attr_bonding_masters;
+ sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
+
+ ret = netdev_class_create_file(&bn->class_attr_bonding_masters);
/*
* Permit multiple loads of the module by ignoring failures to
* create the bonding_masters sysfs file. Bonding devices
@@ -1673,7 +1691,7 @@ int bond_create_sysfs(void)
*/
if (ret == -EEXIST) {
/* Is someone being kinky and naming a device bonding_master? */
- if (__dev_get_by_name(&init_net,
+ if (__dev_get_by_name(bn->net,
class_attr_bonding_masters.attr.name))
pr_err("network device named %s already exists in sysfs",
class_attr_bonding_masters.attr.name);
@@ -1687,9 +1705,9 @@ int bond_create_sysfs(void)
/*
* Remove /sys/class/net/bonding_masters.
*/
-void bond_destroy_sysfs(void)
+void bond_destroy_sysfs(struct bond_net *bn)
{
- netdev_class_remove_file(&class_attr_bonding_masters);
+ netdev_class_remove_file(&bn->class_attr_bonding_masters);
}
/*
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 43526a2d275c..1aecc37e5b4d 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -222,7 +222,6 @@ struct bonding {
struct slave *);
rwlock_t lock;
rwlock_t curr_slave_lock;
- s8 kill_timers;
u8 send_peer_notif;
s8 setup_by_slave;
s8 igmp_retrans;
@@ -234,7 +233,6 @@ struct bonding {
struct netdev_hw_addr_list mc_list;
int (*xmit_hash_policy)(struct sk_buff *, int);
__be32 master_ip;
- u16 flags;
u16 rr_tx_counter;
struct ad_bond_info ad_info;
struct alb_bond_info alb_info;
@@ -380,11 +378,13 @@ static inline bool bond_is_slave_inactive(struct slave *slave)
return slave->inactive;
}
+struct bond_net;
+
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
int bond_create(struct net *net, const char *name);
-int bond_create_sysfs(void);
-void bond_destroy_sysfs(void);
+int bond_create_sysfs(struct bond_net *net);
+void bond_destroy_sysfs(struct bond_net *net);
void bond_prepare_sysfs_group(struct bonding *bond);
int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
@@ -410,6 +410,7 @@ struct bond_net {
#ifdef CONFIG_PROC_FS
struct proc_dir_entry * proc_dir;
#endif
+ struct class_attribute class_attr_bonding_masters;
};
#ifdef CONFIG_PROC_FS
diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c
index b41c2fced0a7..073352517adc 100644
--- a/drivers/net/caif/caif_hsi.c
+++ b/drivers/net/caif/caif_hsi.c
@@ -18,6 +18,7 @@
#include <linux/sched.h>
#include <linux/if_arp.h>
#include <linux/timer.h>
+#include <linux/rtnetlink.h>
#include <net/caif/caif_layer.h>
#include <net/caif/caif_hsi.h>
@@ -29,6 +30,10 @@ MODULE_DESCRIPTION("CAIF HSI driver");
#define PAD_POW2(x, pow) ((((x)&((pow)-1)) == 0) ? 0 :\
(((pow)-((x)&((pow)-1)))))
+static int inactivity_timeout = 1000;
+module_param(inactivity_timeout, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(inactivity_timeout, "Inactivity timeout on HSI, ms.");
+
/*
* HSI padding options.
* Warning: must be a base of 2 (& operation used) and can not be zero !
@@ -98,7 +103,8 @@ static void cfhsi_abort_tx(struct cfhsi *cfhsi)
}
cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
if (!test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
- mod_timer(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+ mod_timer(&cfhsi->timer,
+ jiffies + cfhsi->inactivity_timeout);
spin_unlock_bh(&cfhsi->lock);
}
@@ -145,7 +151,7 @@ static int cfhsi_flush_fifo(struct cfhsi *cfhsi)
}
ret = 5 * HZ;
- wait_event_interruptible_timeout(cfhsi->flush_fifo_wait,
+ ret = wait_event_interruptible_timeout(cfhsi->flush_fifo_wait,
!test_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits), ret);
if (ret < 0) {
@@ -178,6 +184,9 @@ static int cfhsi_tx_frm(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
if (!skb)
return 0;
+ /* Clear offset. */
+ desc->offset = 0;
+
/* Check if we can embed a CAIF frame. */
if (skb->len < CFHSI_MAX_EMB_FRM_SZ) {
struct caif_payload_info *info;
@@ -206,9 +215,7 @@ static int cfhsi_tx_frm(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
consume_skb(skb);
skb = NULL;
}
- } else
- /* Clear offset. */
- desc->offset = 0;
+ }
/* Create payload CAIF frames. */
pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
@@ -271,16 +278,13 @@ static int cfhsi_tx_frm(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
return CFHSI_DESC_SZ + pld_len;
}
-static void cfhsi_tx_done_work(struct work_struct *work)
+static void cfhsi_tx_done(struct cfhsi *cfhsi)
{
- struct cfhsi *cfhsi = NULL;
struct cfhsi_desc *desc = NULL;
int len = 0;
int res;
- cfhsi = container_of(work, struct cfhsi, tx_done_work);
- dev_dbg(&cfhsi->ndev->dev, "%s.\n",
- __func__);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n", __func__);
if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
return;
@@ -303,14 +307,22 @@ static void cfhsi_tx_done_work(struct work_struct *work)
spin_unlock_bh(&cfhsi->lock);
/* Create HSI frame. */
- len = cfhsi_tx_frm(desc, cfhsi);
- if (!len) {
- cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
- /* Start inactivity timer. */
- mod_timer(&cfhsi->timer,
- jiffies + CFHSI_INACTIVITY_TOUT);
- break;
- }
+ do {
+ len = cfhsi_tx_frm(desc, cfhsi);
+ if (!len) {
+ spin_lock_bh(&cfhsi->lock);
+ if (unlikely(skb_peek(&cfhsi->qhead))) {
+ spin_unlock_bh(&cfhsi->lock);
+ continue;
+ }
+ cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
+ /* Start inactivity timer. */
+ mod_timer(&cfhsi->timer,
+ jiffies + cfhsi->inactivity_timeout);
+ spin_unlock_bh(&cfhsi->lock);
+ goto done;
+ }
+ } while (!len);
/* Set up new transfer. */
res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
@@ -319,6 +331,9 @@ static void cfhsi_tx_done_work(struct work_struct *work)
__func__, res);
}
} while (res < 0);
+
+done:
+ return;
}
static void cfhsi_tx_done_cb(struct cfhsi_drv *drv)
@@ -331,8 +346,7 @@ static void cfhsi_tx_done_cb(struct cfhsi_drv *drv)
if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
return;
-
- queue_work(cfhsi->wq, &cfhsi->tx_done_work);
+ cfhsi_tx_done(cfhsi);
}
static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
@@ -346,14 +360,14 @@ static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
(desc->offset > CFHSI_MAX_EMB_FRM_SZ)) {
dev_err(&cfhsi->ndev->dev, "%s: Invalid descriptor.\n",
__func__);
- return 0;
+ return -EPROTO;
}
/* Check for embedded CAIF frame. */
if (desc->offset) {
struct sk_buff *skb;
u8 *dst = NULL;
- int len = 0, retries = 0;
+ int len = 0;
pfrm = ((u8 *)desc) + desc->offset;
/* Remove offset padding. */
@@ -364,26 +378,19 @@ static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
len |= ((*(pfrm+1)) << 8) & 0xFF00;
len += 2; /* Add FCS fields. */
+ /* Sanity check length of CAIF frame. */
+ if (unlikely(len > CFHSI_MAX_CAIF_FRAME_SZ)) {
+ dev_err(&cfhsi->ndev->dev, "%s: Invalid length.\n",
+ __func__);
+ return -EPROTO;
+ }
/* Allocate SKB (OK even in IRQ context). */
- skb = alloc_skb(len + 1, GFP_KERNEL);
- while (!skb) {
- retries++;
- schedule_timeout(1);
- skb = alloc_skb(len + 1, GFP_KERNEL);
- if (skb) {
- printk(KERN_WARNING "%s: slept for %u "
- "before getting memory\n",
- __func__, retries);
- break;
- }
- if (retries > HZ) {
- printk(KERN_ERR "%s: slept for 1HZ and "
- "did not get memory\n",
- __func__);
- cfhsi->ndev->stats.rx_dropped++;
- goto drop_frame;
- }
+ skb = alloc_skb(len + 1, GFP_ATOMIC);
+ if (!skb) {
+ dev_err(&cfhsi->ndev->dev, "%s: Out of memory !\n",
+ __func__);
+ return -ENOMEM;
}
caif_assert(skb != NULL);
@@ -409,7 +416,6 @@ static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
cfhsi->ndev->stats.rx_bytes += len;
}
-drop_frame:
/* Calculate transfer length. */
plen = desc->cffrm_len;
while (nfrms < CFHSI_MAX_PKTS && *plen) {
@@ -422,13 +428,12 @@ drop_frame:
if (desc->header & CFHSI_PIGGY_DESC)
xfer_sz += CFHSI_DESC_SZ;
- if (xfer_sz % 4) {
+ if ((xfer_sz % 4) || (xfer_sz > (CFHSI_BUF_SZ_RX - CFHSI_DESC_SZ))) {
dev_err(&cfhsi->ndev->dev,
"%s: Invalid payload len: %d, ignored.\n",
__func__, xfer_sz);
- xfer_sz = 0;
+ return -EPROTO;
}
-
return xfer_sz;
}
@@ -444,23 +449,27 @@ static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
(desc->offset > CFHSI_MAX_EMB_FRM_SZ))) {
dev_err(&cfhsi->ndev->dev, "%s: Invalid descriptor.\n",
__func__);
- return -EINVAL;
+ return -EPROTO;
}
/* Set frame pointer to start of payload. */
pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
plen = desc->cffrm_len;
+
+ /* Skip already processed frames. */
+ while (nfrms < cfhsi->rx_state.nfrms) {
+ pfrm += *plen;
+ rx_sz += *plen;
+ plen++;
+ nfrms++;
+ }
+
+ /* Parse payload. */
while (nfrms < CFHSI_MAX_PKTS && *plen) {
struct sk_buff *skb;
u8 *dst = NULL;
u8 *pcffrm = NULL;
- int len = 0, retries = 0;
-
- if (WARN_ON(desc->cffrm_len[nfrms] > CFHSI_MAX_PAYLOAD_SZ)) {
- dev_err(&cfhsi->ndev->dev, "%s: Invalid payload.\n",
- __func__);
- return -EINVAL;
- }
+ int len = 0;
/* CAIF frame starts after head padding. */
pcffrm = pfrm + *pfrm + 1;
@@ -470,25 +479,20 @@ static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
len |= ((*(pcffrm + 1)) << 8) & 0xFF00;
len += 2; /* Add FCS fields. */
+ /* Sanity check length of CAIF frames. */
+ if (unlikely(len > CFHSI_MAX_CAIF_FRAME_SZ)) {
+ dev_err(&cfhsi->ndev->dev, "%s: Invalid length.\n",
+ __func__);
+ return -EPROTO;
+ }
+
/* Allocate SKB (OK even in IRQ context). */
- skb = alloc_skb(len + 1, GFP_KERNEL);
- while (!skb) {
- retries++;
- schedule_timeout(1);
- skb = alloc_skb(len + 1, GFP_KERNEL);
- if (skb) {
- printk(KERN_WARNING "%s: slept for %u "
- "before getting memory\n",
- __func__, retries);
- break;
- }
- if (retries > HZ) {
- printk(KERN_ERR "%s: slept for 1HZ "
- "and did not get memory\n",
- __func__);
- cfhsi->ndev->stats.rx_dropped++;
- goto drop_frame;
- }
+ skb = alloc_skb(len + 1, GFP_ATOMIC);
+ if (!skb) {
+ dev_err(&cfhsi->ndev->dev, "%s: Out of memory !\n",
+ __func__);
+ cfhsi->rx_state.nfrms = nfrms;
+ return -ENOMEM;
}
caif_assert(skb != NULL);
@@ -512,7 +516,6 @@ static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
cfhsi->ndev->stats.rx_packets++;
cfhsi->ndev->stats.rx_bytes += len;
-drop_frame:
pfrm += *plen;
rx_sz += *plen;
plen++;
@@ -522,40 +525,56 @@ drop_frame:
return rx_sz;
}
-static void cfhsi_rx_done_work(struct work_struct *work)
+static void cfhsi_rx_done(struct cfhsi *cfhsi)
{
int res;
int desc_pld_len = 0;
- struct cfhsi *cfhsi = NULL;
struct cfhsi_desc *desc = NULL;
- cfhsi = container_of(work, struct cfhsi, rx_done_work);
desc = (struct cfhsi_desc *)cfhsi->rx_buf;
- dev_dbg(&cfhsi->ndev->dev, "%s: Kick timer if pending.\n",
- __func__);
+ dev_dbg(&cfhsi->ndev->dev, "%s\n", __func__);
if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
return;
/* Update inactivity timer if pending. */
- mod_timer_pending(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+ spin_lock_bh(&cfhsi->lock);
+ mod_timer_pending(&cfhsi->timer,
+ jiffies + cfhsi->inactivity_timeout);
+ spin_unlock_bh(&cfhsi->lock);
- if (cfhsi->rx_state == CFHSI_RX_STATE_DESC) {
+ if (cfhsi->rx_state.state == CFHSI_RX_STATE_DESC) {
desc_pld_len = cfhsi_rx_desc(desc, cfhsi);
+ if (desc_pld_len == -ENOMEM)
+ goto restart;
+ if (desc_pld_len == -EPROTO)
+ goto out_of_sync;
} else {
int pld_len;
- pld_len = cfhsi_rx_pld(desc, cfhsi);
+ if (!cfhsi->rx_state.piggy_desc) {
+ pld_len = cfhsi_rx_pld(desc, cfhsi);
+ if (pld_len == -ENOMEM)
+ goto restart;
+ if (pld_len == -EPROTO)
+ goto out_of_sync;
+ cfhsi->rx_state.pld_len = pld_len;
+ } else {
+ pld_len = cfhsi->rx_state.pld_len;
+ }
if ((pld_len > 0) && (desc->header & CFHSI_PIGGY_DESC)) {
struct cfhsi_desc *piggy_desc;
piggy_desc = (struct cfhsi_desc *)
(desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ +
pld_len);
+ cfhsi->rx_state.piggy_desc = true;
/* Extract piggy-backed descriptor. */
desc_pld_len = cfhsi_rx_desc(piggy_desc, cfhsi);
+ if (desc_pld_len == -ENOMEM)
+ goto restart;
/*
* Copy needed information from the piggy-backed
@@ -563,19 +582,22 @@ static void cfhsi_rx_done_work(struct work_struct *work)
*/
memcpy((u8 *)desc, (u8 *)piggy_desc,
CFHSI_DESC_SHORT_SZ);
+
+ if (desc_pld_len == -EPROTO)
+ goto out_of_sync;
}
}
+ memset(&cfhsi->rx_state, 0, sizeof(cfhsi->rx_state));
if (desc_pld_len) {
- cfhsi->rx_state = CFHSI_RX_STATE_PAYLOAD;
+ cfhsi->rx_state.state = CFHSI_RX_STATE_PAYLOAD;
cfhsi->rx_ptr = cfhsi->rx_buf + CFHSI_DESC_SZ;
cfhsi->rx_len = desc_pld_len;
} else {
- cfhsi->rx_state = CFHSI_RX_STATE_DESC;
+ cfhsi->rx_state.state = CFHSI_RX_STATE_DESC;
cfhsi->rx_ptr = cfhsi->rx_buf;
cfhsi->rx_len = CFHSI_DESC_SZ;
}
- clear_bit(CFHSI_PENDING_RX, &cfhsi->bits);
if (test_bit(CFHSI_AWAKE, &cfhsi->bits)) {
/* Set up new transfer. */
@@ -590,6 +612,33 @@ static void cfhsi_rx_done_work(struct work_struct *work)
cfhsi->ndev->stats.rx_dropped++;
}
}
+ return;
+
+restart:
+ if (++cfhsi->rx_state.retries > CFHSI_MAX_RX_RETRIES) {
+ dev_err(&cfhsi->ndev->dev, "%s: No memory available "
+ "in %d iterations.\n",
+ __func__, CFHSI_MAX_RX_RETRIES);
+ BUG();
+ }
+ mod_timer(&cfhsi->rx_slowpath_timer, jiffies + 1);
+ return;
+
+out_of_sync:
+ dev_err(&cfhsi->ndev->dev, "%s: Out of sync.\n", __func__);
+ print_hex_dump_bytes("--> ", DUMP_PREFIX_NONE,
+ cfhsi->rx_buf, CFHSI_DESC_SZ);
+ schedule_work(&cfhsi->out_of_sync_work);
+}
+
+static void cfhsi_rx_slowpath(unsigned long arg)
+{
+ struct cfhsi *cfhsi = (struct cfhsi *)arg;
+
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+ __func__);
+
+ cfhsi_rx_done(cfhsi);
}
static void cfhsi_rx_done_cb(struct cfhsi_drv *drv)
@@ -603,12 +652,10 @@ static void cfhsi_rx_done_cb(struct cfhsi_drv *drv)
if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
return;
- set_bit(CFHSI_PENDING_RX, &cfhsi->bits);
-
if (test_and_clear_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits))
wake_up_interruptible(&cfhsi->flush_fifo_wait);
else
- queue_work(cfhsi->wq, &cfhsi->rx_done_work);
+ cfhsi_rx_done(cfhsi);
}
static void cfhsi_wake_up(struct work_struct *work)
@@ -627,6 +674,7 @@ static void cfhsi_wake_up(struct work_struct *work)
/* It happenes when wakeup is requested by
* both ends at the same time. */
clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+ clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
return;
}
@@ -637,25 +685,53 @@ static void cfhsi_wake_up(struct work_struct *work)
__func__);
/* Wait for acknowledge. */
- ret = CFHSI_WAKEUP_TOUT;
- wait_event_interruptible_timeout(cfhsi->wake_up_wait,
- test_bit(CFHSI_WAKE_UP_ACK,
+ ret = CFHSI_WAKE_TOUT;
+ ret = wait_event_interruptible_timeout(cfhsi->wake_up_wait,
+ test_and_clear_bit(CFHSI_WAKE_UP_ACK,
&cfhsi->bits), ret);
if (unlikely(ret < 0)) {
/* Interrupted by signal. */
- dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
+ dev_err(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
__func__, ret);
+
clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
return;
} else if (!ret) {
+ bool ca_wake = false;
+ size_t fifo_occupancy = 0;
+
/* Wakeup timeout */
dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
__func__);
+
+ /* Check FIFO to check if modem has sent something. */
+ WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+ &fifo_occupancy));
+
+ dev_err(&cfhsi->ndev->dev, "%s: Bytes in FIFO: %u.\n",
+ __func__, (unsigned) fifo_occupancy);
+
+ /* Check if we misssed the interrupt. */
+ WARN_ON(cfhsi->dev->cfhsi_get_peer_wake(cfhsi->dev,
+ &ca_wake));
+
+ if (ca_wake) {
+ dev_err(&cfhsi->ndev->dev, "%s: CA Wake missed !.\n",
+ __func__);
+
+ /* Clear the CFHSI_WAKE_UP_ACK bit to prevent race. */
+ clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
+
+ /* Continue execution. */
+ goto wake_ack;
+ }
+
clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
return;
}
+wake_ack:
dev_dbg(&cfhsi->ndev->dev, "%s: Woken.\n",
__func__);
@@ -664,16 +740,11 @@ static void cfhsi_wake_up(struct work_struct *work)
clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
/* Resume read operation. */
- if (!test_bit(CFHSI_PENDING_RX, &cfhsi->bits)) {
- dev_dbg(&cfhsi->ndev->dev, "%s: Start RX.\n",
- __func__);
- res = cfhsi->dev->cfhsi_rx(cfhsi->rx_ptr,
- cfhsi->rx_len, cfhsi->dev);
- if (WARN_ON(res < 0)) {
- dev_err(&cfhsi->ndev->dev, "%s: RX error %d.\n",
- __func__, res);
- }
- }
+ dev_dbg(&cfhsi->ndev->dev, "%s: Start RX.\n", __func__);
+ res = cfhsi->dev->cfhsi_rx(cfhsi->rx_ptr, cfhsi->rx_len, cfhsi->dev);
+
+ if (WARN_ON(res < 0))
+ dev_err(&cfhsi->ndev->dev, "%s: RX err %d.\n", __func__, res);
/* Clear power up acknowledment. */
clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
@@ -686,7 +757,7 @@ static void cfhsi_wake_up(struct work_struct *work)
__func__);
/* Start inactivity timer. */
mod_timer(&cfhsi->timer,
- jiffies + CFHSI_INACTIVITY_TOUT);
+ jiffies + cfhsi->inactivity_timeout);
spin_unlock_bh(&cfhsi->lock);
return;
}
@@ -712,79 +783,81 @@ static void cfhsi_wake_up(struct work_struct *work)
"%s: Failed to create HSI frame: %d.\n",
__func__, len);
}
-
}
static void cfhsi_wake_down(struct work_struct *work)
{
long ret;
struct cfhsi *cfhsi = NULL;
- size_t fifo_occupancy;
+ size_t fifo_occupancy = 0;
+ int retry = CFHSI_WAKE_TOUT;
cfhsi = container_of(work, struct cfhsi, wake_down_work);
- dev_dbg(&cfhsi->ndev->dev, "%s.\n",
- __func__);
+ dev_dbg(&cfhsi->ndev->dev, "%s.\n", __func__);
if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
return;
- /* Check if there is something in FIFO. */
- if (WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
- &fifo_occupancy)))
- fifo_occupancy = 0;
-
- if (fifo_occupancy) {
- dev_dbg(&cfhsi->ndev->dev,
- "%s: %u words in RX FIFO, restart timer.\n",
- __func__, (unsigned) fifo_occupancy);
- spin_lock_bh(&cfhsi->lock);
- mod_timer(&cfhsi->timer,
- jiffies + CFHSI_INACTIVITY_TOUT);
- spin_unlock_bh(&cfhsi->lock);
- return;
- }
-
- /* Cancel pending RX requests */
- cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
-
/* Deactivate wake line. */
cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
/* Wait for acknowledge. */
- ret = CFHSI_WAKEUP_TOUT;
+ ret = CFHSI_WAKE_TOUT;
ret = wait_event_interruptible_timeout(cfhsi->wake_down_wait,
- test_bit(CFHSI_WAKE_DOWN_ACK,
- &cfhsi->bits),
- ret);
+ test_and_clear_bit(CFHSI_WAKE_DOWN_ACK,
+ &cfhsi->bits), ret);
if (ret < 0) {
/* Interrupted by signal. */
- dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
+ dev_err(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
__func__, ret);
return;
} else if (!ret) {
+ bool ca_wake = true;
+
/* Timeout */
- dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
- __func__);
+ dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n", __func__);
+
+ /* Check if we misssed the interrupt. */
+ WARN_ON(cfhsi->dev->cfhsi_get_peer_wake(cfhsi->dev,
+ &ca_wake));
+ if (!ca_wake)
+ dev_err(&cfhsi->ndev->dev, "%s: CA Wake missed !.\n",
+ __func__);
}
- /* Clear power down acknowledment. */
- clear_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
+ /* Check FIFO occupancy. */
+ while (retry) {
+ WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+ &fifo_occupancy));
+
+ if (!fifo_occupancy)
+ break;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ retry--;
+ }
+
+ if (!retry)
+ dev_err(&cfhsi->ndev->dev, "%s: FIFO Timeout.\n", __func__);
+
+ /* Clear AWAKE condition. */
clear_bit(CFHSI_AWAKE, &cfhsi->bits);
- /* Check if there is something in FIFO. */
- if (WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
- &fifo_occupancy)))
- fifo_occupancy = 0;
+ /* Cancel pending RX requests. */
+ cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
- if (fifo_occupancy) {
- dev_dbg(&cfhsi->ndev->dev,
- "%s: %u words in RX FIFO, wakeup forced.\n",
- __func__, (unsigned) fifo_occupancy);
- if (!test_and_set_bit(CFHSI_WAKE_UP, &cfhsi->bits))
- queue_work(cfhsi->wq, &cfhsi->wake_up_work);
- } else
- dev_dbg(&cfhsi->ndev->dev, "%s: Done.\n",
- __func__);
+}
+
+static void cfhsi_out_of_sync(struct work_struct *work)
+{
+ struct cfhsi *cfhsi = NULL;
+
+ cfhsi = container_of(work, struct cfhsi, out_of_sync_work);
+
+ rtnl_lock();
+ dev_close(cfhsi->ndev);
+ rtnl_unlock();
}
static void cfhsi_wake_up_cb(struct cfhsi_drv *drv)
@@ -854,17 +927,15 @@ static int cfhsi_xmit(struct sk_buff *skb, struct net_device *dev)
start_xfer = 1;
}
- spin_unlock_bh(&cfhsi->lock);
-
- if (!start_xfer)
+ if (!start_xfer) {
+ spin_unlock_bh(&cfhsi->lock);
return 0;
+ }
/* Delete inactivity timer if started. */
-#ifdef CONFIG_SMP
timer_active = del_timer_sync(&cfhsi->timer);
-#else
- timer_active = del_timer(&cfhsi->timer);
-#endif /* CONFIG_SMP */
+
+ spin_unlock_bh(&cfhsi->lock);
if (timer_active) {
struct cfhsi_desc *desc = (struct cfhsi_desc *)cfhsi->tx_buf;
@@ -937,11 +1008,8 @@ int cfhsi_probe(struct platform_device *pdev)
int res;
ndev = alloc_netdev(sizeof(struct cfhsi), "cfhsi%d", cfhsi_setup);
- if (!ndev) {
- dev_err(&pdev->dev, "%s: alloc_netdev failed.\n",
- __func__);
+ if (!ndev)
return -ENODEV;
- }
cfhsi = netdev_priv(ndev);
cfhsi->ndev = ndev;
@@ -949,7 +1017,7 @@ int cfhsi_probe(struct platform_device *pdev)
/* Initialize state vaiables. */
cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
- cfhsi->rx_state = CFHSI_RX_STATE_DESC;
+ cfhsi->rx_state.state = CFHSI_RX_STATE_DESC;
/* Set flow info */
cfhsi->flow_off_sent = 0;
@@ -969,8 +1037,6 @@ int cfhsi_probe(struct platform_device *pdev)
*/
cfhsi->tx_buf = kzalloc(CFHSI_BUF_SZ_TX, GFP_KERNEL);
if (!cfhsi->tx_buf) {
- dev_err(&ndev->dev, "%s: Failed to allocate TX buffer.\n",
- __func__);
res = -ENODEV;
goto err_alloc_tx;
}
@@ -981,13 +1047,23 @@ int cfhsi_probe(struct platform_device *pdev)
*/
cfhsi->rx_buf = kzalloc(CFHSI_BUF_SZ_RX, GFP_KERNEL);
if (!cfhsi->rx_buf) {
- dev_err(&ndev->dev, "%s: Failed to allocate RX buffer.\n",
- __func__);
res = -ENODEV;
goto err_alloc_rx;
}
- /* Initialize receive variables. */
+ /* Pre-calculate inactivity timeout. */
+ if (inactivity_timeout != -1) {
+ cfhsi->inactivity_timeout =
+ inactivity_timeout * HZ / 1000;
+ if (!cfhsi->inactivity_timeout)
+ cfhsi->inactivity_timeout = 1;
+ else if (cfhsi->inactivity_timeout > NEXT_TIMER_MAX_DELTA)
+ cfhsi->inactivity_timeout = NEXT_TIMER_MAX_DELTA;
+ } else {
+ cfhsi->inactivity_timeout = NEXT_TIMER_MAX_DELTA;
+ }
+
+ /* Initialize recieve vaiables. */
cfhsi->rx_ptr = cfhsi->rx_buf;
cfhsi->rx_len = CFHSI_DESC_SZ;
@@ -997,19 +1073,19 @@ int cfhsi_probe(struct platform_device *pdev)
/* Set up the driver. */
cfhsi->drv.tx_done_cb = cfhsi_tx_done_cb;
cfhsi->drv.rx_done_cb = cfhsi_rx_done_cb;
+ cfhsi->drv.wake_up_cb = cfhsi_wake_up_cb;
+ cfhsi->drv.wake_down_cb = cfhsi_wake_down_cb;
/* Initialize the work queues. */
INIT_WORK(&cfhsi->wake_up_work, cfhsi_wake_up);
INIT_WORK(&cfhsi->wake_down_work, cfhsi_wake_down);
- INIT_WORK(&cfhsi->rx_done_work, cfhsi_rx_done_work);
- INIT_WORK(&cfhsi->tx_done_work, cfhsi_tx_done_work);
+ INIT_WORK(&cfhsi->out_of_sync_work, cfhsi_out_of_sync);
/* Clear all bit fields. */
clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
clear_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
clear_bit(CFHSI_AWAKE, &cfhsi->bits);
- clear_bit(CFHSI_PENDING_RX, &cfhsi->bits);
/* Create work thread. */
cfhsi->wq = create_singlethread_workqueue(pdev->name);
@@ -1029,6 +1105,10 @@ int cfhsi_probe(struct platform_device *pdev)
init_timer(&cfhsi->timer);
cfhsi->timer.data = (unsigned long)cfhsi;
cfhsi->timer.function = cfhsi_inactivity_tout;
+ /* Setup the slowpath RX timer. */
+ init_timer(&cfhsi->rx_slowpath_timer);
+ cfhsi->rx_slowpath_timer.data = (unsigned long)cfhsi;
+ cfhsi->rx_slowpath_timer.function = cfhsi_rx_slowpath;
/* Add CAIF HSI device to list. */
spin_lock(&cfhsi_list_lock);
@@ -1052,9 +1132,6 @@ int cfhsi_probe(struct platform_device *pdev)
goto err_net_reg;
}
- cfhsi->drv.wake_up_cb = cfhsi_wake_up_cb;
- cfhsi->drv.wake_down_cb = cfhsi_wake_down_cb;
-
/* Register network device. */
res = register_netdev(ndev);
if (res) {
@@ -1081,7 +1158,7 @@ int cfhsi_probe(struct platform_device *pdev)
return res;
}
-static void cfhsi_shutdown(struct cfhsi *cfhsi, bool remove_platform_dev)
+static void cfhsi_shutdown(struct cfhsi *cfhsi)
{
u8 *tx_buf, *rx_buf;
@@ -1091,28 +1168,17 @@ static void cfhsi_shutdown(struct cfhsi *cfhsi, bool remove_platform_dev)
/* going to shutdown driver */
set_bit(CFHSI_SHUTDOWN, &cfhsi->bits);
- if (remove_platform_dev) {
- /* Flush workqueue */
- flush_workqueue(cfhsi->wq);
-
- /* Notify device. */
- platform_device_unregister(cfhsi->pdev);
- }
-
/* Flush workqueue */
flush_workqueue(cfhsi->wq);
- /* Delete timer if pending */
-#ifdef CONFIG_SMP
+ /* Delete timers if pending */
del_timer_sync(&cfhsi->timer);
-#else
- del_timer(&cfhsi->timer);
-#endif /* CONFIG_SMP */
+ del_timer_sync(&cfhsi->rx_slowpath_timer);
/* Cancel pending RX request (if any) */
cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
- /* Flush again and destroy workqueue */
+ /* Destroy workqueue */
destroy_workqueue(cfhsi->wq);
/* Store bufferes: will be freed later. */
@@ -1151,7 +1217,7 @@ int cfhsi_remove(struct platform_device *pdev)
spin_unlock(&cfhsi_list_lock);
/* Shutdown driver. */
- cfhsi_shutdown(cfhsi, false);
+ cfhsi_shutdown(cfhsi);
return 0;
}
@@ -1184,7 +1250,7 @@ static void __exit cfhsi_exit_module(void)
spin_unlock(&cfhsi_list_lock);
/* Shutdown driver. */
- cfhsi_shutdown(cfhsi, true);
+ cfhsi_shutdown(cfhsi);
spin_lock(&cfhsi_list_lock);
}
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index 0f8defc73307..05e791f46aef 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -664,8 +664,6 @@ int cfspi_spi_probe(struct platform_device *pdev)
/* Allocate DMA buffers. */
cfspi->xfer.va_tx = dma_alloc(&cfspi->xfer.pa_tx);
if (!cfspi->xfer.va_tx) {
- printk(KERN_WARNING
- "CFSPI: failed to allocate dma TX buffer.\n");
res = -ENODEV;
goto err_dma_alloc_tx;
}
@@ -673,8 +671,6 @@ int cfspi_spi_probe(struct platform_device *pdev)
cfspi->xfer.va_rx = dma_alloc(&cfspi->xfer.pa_rx);
if (!cfspi->xfer.va_rx) {
- printk(KERN_WARNING
- "CFSPI: failed to allocate dma TX buffer.\n");
res = -ENODEV;
goto err_dma_alloc_rx;
}
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 121ede663e20..044ea0647b04 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -8,8 +8,6 @@
* Public License ("GPL") version 2 as distributed in the 'COPYING'
* file from the main directory of the linux kernel source.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*
* Your platform definition file should specify something like:
*
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 9bf1116e5b5e..25695bde0549 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -150,7 +150,19 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)
bt->prop_seg = tseg1 / 2;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;
- bt->sjw = 1;
+
+ /* check for sjw user settings */
+ if (!bt->sjw || !btc->sjw_max)
+ bt->sjw = 1;
+ else {
+ /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
+ if (bt->sjw > btc->sjw_max)
+ bt->sjw = btc->sjw_max;
+ /* bt->sjw must not be higher than tseg2 */
+ if (tseg2 < bt->sjw)
+ bt->sjw = tseg2;
+ }
+
bt->brp = best_brp;
/* real bit-rate */
bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1));
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 17678117ed69..e02337953f41 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -33,10 +33,9 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
-#include <mach/clock.h>
-
#define DRV_NAME "flexcan"
/* 8 for RX fifo and 2 error handling */
@@ -192,6 +191,31 @@ static struct can_bittiming_const flexcan_bittiming_const = {
};
/*
+ * Abstract off the read/write for arm versus ppc.
+ */
+#if defined(__BIG_ENDIAN)
+static inline u32 flexcan_read(void __iomem *addr)
+{
+ return in_be32(addr);
+}
+
+static inline void flexcan_write(u32 val, void __iomem *addr)
+{
+ out_be32(addr, val);
+}
+#else
+static inline u32 flexcan_read(void __iomem *addr)
+{
+ return readl(addr);
+}
+
+static inline void flexcan_write(u32 val, void __iomem *addr)
+{
+ writel(val, addr);
+}
+#endif
+
+/*
* Swtich transceiver on or off
*/
static void flexcan_transceiver_switch(const struct flexcan_priv *priv, int on)
@@ -212,9 +236,9 @@ static inline void flexcan_chip_enable(struct flexcan_priv *priv)
struct flexcan_regs __iomem *regs = priv->base;
u32 reg;
- reg = readl(&regs->mcr);
+ reg = flexcan_read(&regs->mcr);
reg &= ~FLEXCAN_MCR_MDIS;
- writel(reg, &regs->mcr);
+ flexcan_write(reg, &regs->mcr);
udelay(10);
}
@@ -224,9 +248,9 @@ static inline void flexcan_chip_disable(struct flexcan_priv *priv)
struct flexcan_regs __iomem *regs = priv->base;
u32 reg;
- reg = readl(&regs->mcr);
+ reg = flexcan_read(&regs->mcr);
reg |= FLEXCAN_MCR_MDIS;
- writel(reg, &regs->mcr);
+ flexcan_write(reg, &regs->mcr);
}
static int flexcan_get_berr_counter(const struct net_device *dev,
@@ -234,7 +258,7 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
{
const struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base;
- u32 reg = readl(&regs->ecr);
+ u32 reg = flexcan_read(&regs->ecr);
bec->txerr = (reg >> 0) & 0xff;
bec->rxerr = (reg >> 8) & 0xff;
@@ -268,15 +292,15 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (cf->can_dlc > 0) {
u32 data = be32_to_cpup((__be32 *)&cf->data[0]);
- writel(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
+ flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
}
if (cf->can_dlc > 3) {
u32 data = be32_to_cpup((__be32 *)&cf->data[4]);
- writel(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
+ flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
}
- writel(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
- writel(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+ flexcan_write(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
+ flexcan_write(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
kfree_skb(skb);
@@ -464,8 +488,8 @@ static void flexcan_read_fifo(const struct net_device *dev,
struct flexcan_mb __iomem *mb = &regs->cantxfg[0];
u32 reg_ctrl, reg_id;
- reg_ctrl = readl(&mb->can_ctrl);
- reg_id = readl(&mb->can_id);
+ reg_ctrl = flexcan_read(&mb->can_ctrl);
+ reg_id = flexcan_read(&mb->can_id);
if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
else
@@ -475,12 +499,12 @@ static void flexcan_read_fifo(const struct net_device *dev,
cf->can_id |= CAN_RTR_FLAG;
cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);
- *(__be32 *)(cf->data + 0) = cpu_to_be32(readl(&mb->data[0]));
- *(__be32 *)(cf->data + 4) = cpu_to_be32(readl(&mb->data[1]));
+ *(__be32 *)(cf->data + 0) = cpu_to_be32(flexcan_read(&mb->data[0]));
+ *(__be32 *)(cf->data + 4) = cpu_to_be32(flexcan_read(&mb->data[1]));
/* mark as read */
- writel(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
- readl(&regs->timer);
+ flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
+ flexcan_read(&regs->timer);
}
static int flexcan_read_frame(struct net_device *dev)
@@ -516,17 +540,17 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
* The error bits are cleared on read,
* use saved value from irq handler.
*/
- reg_esr = readl(&regs->esr) | priv->reg_esr;
+ reg_esr = flexcan_read(&regs->esr) | priv->reg_esr;
/* handle state changes */
work_done += flexcan_poll_state(dev, reg_esr);
/* handle RX-FIFO */
- reg_iflag1 = readl(&regs->iflag1);
+ reg_iflag1 = flexcan_read(&regs->iflag1);
while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE &&
work_done < quota) {
work_done += flexcan_read_frame(dev);
- reg_iflag1 = readl(&regs->iflag1);
+ reg_iflag1 = flexcan_read(&regs->iflag1);
}
/* report bus errors */
@@ -536,8 +560,8 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
if (work_done < quota) {
napi_complete(napi);
/* enable IRQs */
- writel(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
- writel(priv->reg_ctrl_default, &regs->ctrl);
+ flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+ flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
}
return work_done;
@@ -551,9 +575,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
struct flexcan_regs __iomem *regs = priv->base;
u32 reg_iflag1, reg_esr;
- reg_iflag1 = readl(&regs->iflag1);
- reg_esr = readl(&regs->esr);
- writel(FLEXCAN_ESR_ERR_INT, &regs->esr); /* ACK err IRQ */
+ reg_iflag1 = flexcan_read(&regs->iflag1);
+ reg_esr = flexcan_read(&regs->esr);
+ flexcan_write(FLEXCAN_ESR_ERR_INT, &regs->esr); /* ACK err IRQ */
/*
* schedule NAPI in case of:
@@ -569,16 +593,16 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
* save them for later use.
*/
priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
- writel(FLEXCAN_IFLAG_DEFAULT & ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE,
- &regs->imask1);
- writel(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
+ flexcan_write(FLEXCAN_IFLAG_DEFAULT &
+ ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->imask1);
+ flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
&regs->ctrl);
napi_schedule(&priv->napi);
}
/* FIFO overflow */
if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) {
- writel(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
+ flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
dev->stats.rx_over_errors++;
dev->stats.rx_errors++;
}
@@ -587,7 +611,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) {
/* tx_bytes is incremented in flexcan_start_xmit */
stats->tx_packets++;
- writel((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
+ flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
netif_wake_queue(dev);
}
@@ -601,7 +625,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
struct flexcan_regs __iomem *regs = priv->base;
u32 reg;
- reg = readl(&regs->ctrl);
+ reg = flexcan_read(&regs->ctrl);
reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) |
FLEXCAN_CTRL_RJW(0x3) |
FLEXCAN_CTRL_PSEG1(0x7) |
@@ -625,11 +649,11 @@ static void flexcan_set_bittiming(struct net_device *dev)
reg |= FLEXCAN_CTRL_SMP;
dev_info(dev->dev.parent, "writing ctrl=0x%08x\n", reg);
- writel(reg, &regs->ctrl);
+ flexcan_write(reg, &regs->ctrl);
/* print chip status */
dev_dbg(dev->dev.parent, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__,
- readl(&regs->mcr), readl(&regs->ctrl));
+ flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
}
/*
@@ -650,10 +674,10 @@ static int flexcan_chip_start(struct net_device *dev)
flexcan_chip_enable(priv);
/* soft reset */
- writel(FLEXCAN_MCR_SOFTRST, &regs->mcr);
+ flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
udelay(10);
- reg_mcr = readl(&regs->mcr);
+ reg_mcr = flexcan_read(&regs->mcr);
if (reg_mcr & FLEXCAN_MCR_SOFTRST) {
dev_err(dev->dev.parent,
"Failed to softreset can module (mcr=0x%08x)\n",
@@ -675,12 +699,12 @@ static int flexcan_chip_start(struct net_device *dev)
* choose format C
*
*/
- reg_mcr = readl(&regs->mcr);
+ reg_mcr = flexcan_read(&regs->mcr);
reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
FLEXCAN_MCR_IDAM_C;
dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
- writel(reg_mcr, &regs->mcr);
+ flexcan_write(reg_mcr, &regs->mcr);
/*
* CTRL
@@ -698,7 +722,7 @@ static int flexcan_chip_start(struct net_device *dev)
* (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any
* warning or bus passive interrupts.
*/
- reg_ctrl = readl(&regs->ctrl);
+ reg_ctrl = flexcan_read(&regs->ctrl);
reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK;
@@ -706,38 +730,39 @@ static int flexcan_chip_start(struct net_device *dev)
/* save for later use */
priv->reg_ctrl_default = reg_ctrl;
dev_dbg(dev->dev.parent, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
- writel(reg_ctrl, &regs->ctrl);
+ flexcan_write(reg_ctrl, &regs->ctrl);
for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) {
- writel(0, &regs->cantxfg[i].can_ctrl);
- writel(0, &regs->cantxfg[i].can_id);
- writel(0, &regs->cantxfg[i].data[0]);
- writel(0, &regs->cantxfg[i].data[1]);
+ flexcan_write(0, &regs->cantxfg[i].can_ctrl);
+ flexcan_write(0, &regs->cantxfg[i].can_id);
+ flexcan_write(0, &regs->cantxfg[i].data[0]);
+ flexcan_write(0, &regs->cantxfg[i].data[1]);
/* put MB into rx queue */
- writel(FLEXCAN_MB_CNT_CODE(0x4), &regs->cantxfg[i].can_ctrl);
+ flexcan_write(FLEXCAN_MB_CNT_CODE(0x4),
+ &regs->cantxfg[i].can_ctrl);
}
/* acceptance mask/acceptance code (accept everything) */
- writel(0x0, &regs->rxgmask);
- writel(0x0, &regs->rx14mask);
- writel(0x0, &regs->rx15mask);
+ flexcan_write(0x0, &regs->rxgmask);
+ flexcan_write(0x0, &regs->rx14mask);
+ flexcan_write(0x0, &regs->rx15mask);
flexcan_transceiver_switch(priv, 1);
/* synchronize with the can bus */
- reg_mcr = readl(&regs->mcr);
+ reg_mcr = flexcan_read(&regs->mcr);
reg_mcr &= ~FLEXCAN_MCR_HALT;
- writel(reg_mcr, &regs->mcr);
+ flexcan_write(reg_mcr, &regs->mcr);
priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* enable FIFO interrupts */
- writel(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+ flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
/* print chip status */
dev_dbg(dev->dev.parent, "%s: reading mcr=0x%08x ctrl=0x%08x\n",
- __func__, readl(&regs->mcr), readl(&regs->ctrl));
+ __func__, flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
return 0;
@@ -759,12 +784,12 @@ static void flexcan_chip_stop(struct net_device *dev)
u32 reg;
/* Disable all interrupts */
- writel(0, &regs->imask1);
+ flexcan_write(0, &regs->imask1);
/* Disable + halt module */
- reg = readl(&regs->mcr);
+ reg = flexcan_read(&regs->mcr);
reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT;
- writel(reg, &regs->mcr);
+ flexcan_write(reg, &regs->mcr);
flexcan_transceiver_switch(priv, 0);
priv->can.state = CAN_STATE_STOPPED;
@@ -856,24 +881,24 @@ static int __devinit register_flexcandev(struct net_device *dev)
/* select "bus clock", chip must be disabled */
flexcan_chip_disable(priv);
- reg = readl(&regs->ctrl);
+ reg = flexcan_read(&regs->ctrl);
reg |= FLEXCAN_CTRL_CLK_SRC;
- writel(reg, &regs->ctrl);
+ flexcan_write(reg, &regs->ctrl);
flexcan_chip_enable(priv);
/* set freeze, halt and activate FIFO, restrict register access */
- reg = readl(&regs->mcr);
+ reg = flexcan_read(&regs->mcr);
reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
- writel(reg, &regs->mcr);
+ flexcan_write(reg, &regs->mcr);
/*
* Currently we only support newer versions of this core
* featuring a RX FIFO. Older cores found on some Coldfire
* derivates are not yet supported.
*/
- reg = readl(&regs->mcr);
+ reg = flexcan_read(&regs->mcr);
if (!(reg & FLEXCAN_MCR_FEN)) {
dev_err(dev->dev.parent,
"Could not enable RX FIFO, unsupported core\n");
@@ -901,16 +926,29 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
struct net_device *dev;
struct flexcan_priv *priv;
struct resource *mem;
- struct clk *clk;
+ struct clk *clk = NULL;
void __iomem *base;
resource_size_t mem_size;
int err, irq;
+ u32 clock_freq = 0;
+
+ if (pdev->dev.of_node) {
+ const u32 *clock_freq_p;
- clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "no clock defined\n");
- err = PTR_ERR(clk);
- goto failed_clock;
+ clock_freq_p = of_get_property(pdev->dev.of_node,
+ "clock-frequency", NULL);
+ if (clock_freq_p)
+ clock_freq = *clock_freq_p;
+ }
+
+ if (!clock_freq) {
+ clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "no clock defined\n");
+ err = PTR_ERR(clk);
+ goto failed_clock;
+ }
+ clock_freq = clk_get_rate(clk);
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -943,7 +981,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
dev->flags |= IFF_ECHO; /* we support local echo in hardware */
priv = netdev_priv(dev);
- priv->can.clock.freq = clk_get_rate(clk);
+ priv->can.clock.freq = clock_freq;
priv->can.bittiming_const = &flexcan_bittiming_const;
priv->can.do_set_mode = flexcan_set_mode;
priv->can.do_get_berr_counter = flexcan_get_berr_counter;
@@ -978,7 +1016,8 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
failed_map:
release_mem_region(mem->start, mem_size);
failed_get:
- clk_put(clk);
+ if (clk)
+ clk_put(clk);
failed_clock:
return err;
}
@@ -996,15 +1035,27 @@ static int __devexit flexcan_remove(struct platform_device *pdev)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, resource_size(mem));
- clk_put(priv->clk);
+ if (priv->clk)
+ clk_put(priv->clk);
free_candev(dev);
return 0;
}
+static struct of_device_id flexcan_of_match[] = {
+ {
+ .compatible = "fsl,p1010-flexcan",
+ },
+ {},
+};
+
static struct platform_driver flexcan_driver = {
- .driver.name = DRV_NAME,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = flexcan_of_match,
+ },
.probe = flexcan_probe,
.remove = __devexit_p(flexcan_remove),
};
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index 4cc6f44c2ba2..ec4a3119e2c9 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -62,7 +62,7 @@ static enum can_state state_map[] = {
static int mscan_set_mode(struct net_device *dev, u8 mode)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
int ret = 0;
int i;
u8 canctl1;
@@ -138,7 +138,7 @@ static int mscan_set_mode(struct net_device *dev, u8 mode)
static int mscan_start(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
u8 canrflg;
int err;
@@ -178,7 +178,7 @@ static int mscan_restart(struct net_device *dev)
struct mscan_priv *priv = netdev_priv(dev);
if (priv->type == MSCAN_TYPE_MPC5121) {
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
priv->can.state = CAN_STATE_ERROR_ACTIVE;
WARN(!(in_8(&regs->canmisc) & MSCAN_BOHOLD),
@@ -199,7 +199,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct can_frame *frame = (struct can_frame *)skb->data;
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
int i, rtr, buf_id;
u32 can_id;
@@ -307,7 +307,7 @@ static enum can_state check_set_state(struct net_device *dev, u8 canrflg)
static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
u32 can_id;
int i;
@@ -348,7 +348,7 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame,
u8 canrflg)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct net_device_stats *stats = &dev->stats;
enum can_state old_state;
@@ -411,7 +411,7 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
{
struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
struct net_device *dev = napi->dev;
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct net_device_stats *stats = &dev->stats;
int npackets = 0;
int ret = 1;
@@ -458,7 +458,7 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct net_device_stats *stats = &dev->stats;
u8 cantier, cantflg, canrflg;
irqreturn_t ret = IRQ_NONE;
@@ -542,7 +542,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
static int mscan_do_set_bittiming(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct can_bittiming *bt = &priv->can.bittiming;
u8 btr0, btr1;
@@ -564,7 +564,7 @@ static int mscan_open(struct net_device *dev)
{
int ret;
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
/* common open */
ret = open_candev(dev);
@@ -603,7 +603,7 @@ exit_napi_disable:
static int mscan_close(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
netif_stop_queue(dev);
napi_disable(&priv->napi);
@@ -627,7 +627,7 @@ static const struct net_device_ops mscan_netdev_ops = {
int register_mscandev(struct net_device *dev, int mscan_clksrc)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
u8 ctl1;
ctl1 = in_8(&regs->canctl1);
@@ -664,7 +664,7 @@ int register_mscandev(struct net_device *dev, int mscan_clksrc)
void unregister_mscandev(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
mscan_set_mode(dev, MSCAN_INIT_MODE);
clrbits8(&regs->canctl1, MSCAN_CANE);
unregister_candev(dev);
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index 6fdc031daaae..fe9e64d476eb 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -29,6 +29,13 @@ config CAN_SJA1000_OF_PLATFORM
OpenFirmware bindings, e.g. if you have a PowerPC based system
you may want to enable this option.
+config CAN_EMS_PCMCIA
+ tristate "EMS CPC-CARD Card"
+ depends on PCMCIA
+ ---help---
+ This driver is for the one or two channel CPC-CARD cards from
+ EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
+
config CAN_EMS_PCI
tristate "EMS CPC-PCI, CPC-PCIe and CPC-104P Card"
depends on PCI
@@ -37,6 +44,13 @@ config CAN_EMS_PCI
CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
(http://www.ems-wuensche.de).
+config CAN_PEAK_PCI
+ tristate "PEAK PCAN PCI/PCIe Cards"
+ depends on PCI
+ ---help---
+ This driver is for the PCAN PCI/PCIe cards (1, 2, 3 or 4 channels)
+ from PEAK Systems (http://www.peak-system.com).
+
config CAN_KVASER_PCI
tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
depends on PCI
diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile
index 2c591eb321c7..0604f240c8b1 100644
--- a/drivers/net/can/sja1000/Makefile
+++ b/drivers/net/can/sja1000/Makefile
@@ -6,8 +6,10 @@ obj-$(CONFIG_CAN_SJA1000) += sja1000.o
obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o
obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o
+obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o
obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o
obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o
+obj-$(CONFIG_CAN_PEAK_PCI) += peak_pci.o
obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o
obj-$(CONFIG_CAN_TSCAN1) += tscan1.o
diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c
new file mode 100644
index 000000000000..075a5457a190
--- /dev/null
+++ b/drivers/net/can/sja1000/ems_pcmcia.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2008 Sebastian Haas (initial chardev implementation)
+ * Copyright (C) 2010 Markus Plessing <plessing@ems-wuensche.com>
+ * Rework for mainline by Oliver Hartkopp <socketcan@hartkopp.net>
+ *
+ * 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
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include "sja1000.h"
+
+#define DRV_NAME "ems_pcmcia"
+
+MODULE_AUTHOR("Markus Plessing <plessing@ems-wuensche.com>");
+MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-CARD cards");
+MODULE_SUPPORTED_DEVICE("EMS CPC-CARD CAN card");
+MODULE_LICENSE("GPL v2");
+
+#define EMS_PCMCIA_MAX_CHAN 2
+
+struct ems_pcmcia_card {
+ int channels;
+ struct pcmcia_device *pcmcia_dev;
+ struct net_device *net_dev[EMS_PCMCIA_MAX_CHAN];
+ void __iomem *base_addr;
+};
+
+#define EMS_PCMCIA_CAN_CLOCK (16000000 / 2)
+
+/*
+ * The board configuration is probably following:
+ * RX1 is connected to ground.
+ * TX1 is not connected.
+ * CLKO is not connected.
+ * Setting the OCR register to 0xDA is a good idea.
+ * This means normal output mode , push-pull and the correct polarity.
+ */
+#define EMS_PCMCIA_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
+
+/*
+ * In the CDR register, you should set CBP to 1.
+ * You will probably also want to set the clock divider value to 7
+ * (meaning direct oscillator output) because the second SJA1000 chip
+ * is driven by the first one CLKOUT output.
+ */
+#define EMS_PCMCIA_CDR (CDR_CBP | CDR_CLKOUT_MASK)
+#define EMS_PCMCIA_MEM_SIZE 4096 /* Size of the remapped io-memory */
+#define EMS_PCMCIA_CAN_BASE_OFFSET 0x100 /* Offset where controllers starts */
+#define EMS_PCMCIA_CAN_CTRL_SIZE 0x80 /* Memory size for each controller */
+
+#define EMS_CMD_RESET 0x00 /* Perform a reset of the card */
+#define EMS_CMD_MAP 0x03 /* Map CAN controllers into card' memory */
+#define EMS_CMD_UMAP 0x02 /* Unmap CAN controllers from card' memory */
+
+static struct pcmcia_device_id ems_pcmcia_tbl[] = {
+ PCMCIA_DEVICE_PROD_ID123("EMS_T_W", "CPC-Card", "V2.0", 0xeab1ea23,
+ 0xa338573f, 0xe4575800),
+ PCMCIA_DEVICE_NULL,
+};
+
+MODULE_DEVICE_TABLE(pcmcia, ems_pcmcia_tbl);
+
+static u8 ems_pcmcia_read_reg(const struct sja1000_priv *priv, int port)
+{
+ return readb(priv->reg_base + port);
+}
+
+static void ems_pcmcia_write_reg(const struct sja1000_priv *priv, int port,
+ u8 val)
+{
+ writeb(val, priv->reg_base + port);
+}
+
+static irqreturn_t ems_pcmcia_interrupt(int irq, void *dev_id)
+{
+ struct ems_pcmcia_card *card = dev_id;
+ struct net_device *dev;
+ irqreturn_t retval = IRQ_NONE;
+ int i, again;
+
+ /* Card not present */
+ if (readw(card->base_addr) != 0xAA55)
+ return IRQ_HANDLED;
+
+ do {
+ again = 0;
+
+ /* Check interrupt for each channel */
+ for (i = 0; i < card->channels; i++) {
+ dev = card->net_dev[i];
+ if (!dev)
+ continue;
+
+ if (sja1000_interrupt(irq, dev) == IRQ_HANDLED)
+ again = 1;
+ }
+ /* At least one channel handled the interrupt */
+ if (again)
+ retval = IRQ_HANDLED;
+
+ } while (again);
+
+ return retval;
+}
+
+/*
+ * Check if a CAN controller is present at the specified location
+ * by trying to set 'em into the PeliCAN mode
+ */
+static inline int ems_pcmcia_check_chan(struct sja1000_priv *priv)
+{
+ /* Make sure SJA1000 is in reset mode */
+ ems_pcmcia_write_reg(priv, REG_MOD, 1);
+ ems_pcmcia_write_reg(priv, REG_CDR, CDR_PELICAN);
+
+ /* read reset-values */
+ if (ems_pcmcia_read_reg(priv, REG_CDR) == CDR_PELICAN)
+ return 1;
+
+ return 0;
+}
+
+static void ems_pcmcia_del_card(struct pcmcia_device *pdev)
+{
+ struct ems_pcmcia_card *card = pdev->priv;
+ struct net_device *dev;
+ int i;
+
+ free_irq(pdev->irq, card);
+
+ for (i = 0; i < card->channels; i++) {
+ dev = card->net_dev[i];
+ if (!dev)
+ continue;
+
+ printk(KERN_INFO "%s: removing %s on channel #%d\n",
+ DRV_NAME, dev->name, i);
+ unregister_sja1000dev(dev);
+ free_sja1000dev(dev);
+ }
+
+ writeb(EMS_CMD_UMAP, card->base_addr);
+ iounmap(card->base_addr);
+ kfree(card);
+
+ pdev->priv = NULL;
+}
+
+/*
+ * 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)
+{
+ struct sja1000_priv *priv;
+ struct net_device *dev;
+ struct ems_pcmcia_card *card;
+ int err, i;
+
+ /* Allocating card structures to hold addresses, ... */
+ card = kzalloc(sizeof(struct ems_pcmcia_card), GFP_KERNEL);
+ if (!card)
+ return -ENOMEM;
+
+ pdev->priv = card;
+ card->channels = 0;
+
+ card->base_addr = ioremap(base, EMS_PCMCIA_MEM_SIZE);
+ if (!card->base_addr) {
+ err = -ENOMEM;
+ goto failure_cleanup;
+ }
+
+ /* Check for unique EMS CAN signature */
+ if (readw(card->base_addr) != 0xAA55) {
+ err = -ENODEV;
+ goto failure_cleanup;
+ }
+
+ /* Request board reset */
+ writeb(EMS_CMD_RESET, card->base_addr);
+
+ /* Make sure CAN controllers are mapped into card's memory space */
+ writeb(EMS_CMD_MAP, card->base_addr);
+
+ /* Detect available channels */
+ for (i = 0; i < EMS_PCMCIA_MAX_CHAN; i++) {
+ dev = alloc_sja1000dev(0);
+ if (!dev) {
+ err = -ENOMEM;
+ goto failure_cleanup;
+ }
+
+ card->net_dev[i] = dev;
+ priv = netdev_priv(dev);
+ priv->priv = card;
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ priv->irq_flags = IRQF_SHARED;
+ dev->irq = pdev->irq;
+ priv->reg_base = card->base_addr + EMS_PCMCIA_CAN_BASE_OFFSET +
+ (i * EMS_PCMCIA_CAN_CTRL_SIZE);
+
+ /* Check if channel is present */
+ if (ems_pcmcia_check_chan(priv)) {
+ priv->read_reg = ems_pcmcia_read_reg;
+ priv->write_reg = ems_pcmcia_write_reg;
+ priv->can.clock.freq = EMS_PCMCIA_CAN_CLOCK;
+ priv->ocr = EMS_PCMCIA_OCR;
+ priv->cdr = EMS_PCMCIA_CDR;
+ priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER;
+
+ /* Register SJA1000 device */
+ err = register_sja1000dev(dev);
+ if (err) {
+ free_sja1000dev(dev);
+ goto failure_cleanup;
+ }
+
+ card->channels++;
+
+ printk(KERN_INFO "%s: registered %s on channel "
+ "#%d at 0x%p, irq %d\n", DRV_NAME, dev->name,
+ i, priv->reg_base, dev->irq);
+ } else
+ free_sja1000dev(dev);
+ }
+
+ err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
+ DRV_NAME, card);
+ if (!err)
+ return 0;
+
+failure_cleanup:
+ ems_pcmcia_del_card(pdev);
+ return err;
+}
+
+/*
+ * Setup PCMCIA socket and probe for EMS CPC-CARD
+ */
+static int __devinit ems_pcmcia_probe(struct pcmcia_device *dev)
+{
+ int csval;
+
+ /* General socket configuration */
+ dev->config_flags |= CONF_ENABLE_IRQ;
+ dev->config_index = 1;
+ dev->config_regs = PRESENT_OPTION;
+
+ /* The io structure describes IO port mapping */
+ dev->resource[0]->end = 16;
+ dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ dev->resource[1]->end = 16;
+ dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
+ dev->io_lines = 5;
+
+ /* Allocate a memory window */
+ dev->resource[2]->flags =
+ (WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE);
+ dev->resource[2]->start = dev->resource[2]->end = 0;
+
+ csval = pcmcia_request_window(dev, dev->resource[2], 0);
+ if (csval) {
+ dev_err(&dev->dev, "pcmcia_request_window failed (err=%d)\n",
+ csval);
+ return 0;
+ }
+
+ csval = pcmcia_map_mem_page(dev, dev->resource[2], dev->config_base);
+ if (csval) {
+ dev_err(&dev->dev, "pcmcia_map_mem_page failed (err=%d)\n",
+ csval);
+ return 0;
+ }
+
+ csval = pcmcia_enable_device(dev);
+ if (csval) {
+ dev_err(&dev->dev, "pcmcia_enable_device failed (err=%d)\n",
+ csval);
+ return 0;
+ }
+
+ ems_pcmcia_add_card(dev, dev->resource[2]->start);
+ return 0;
+}
+
+/*
+ * Release claimed resources
+ */
+static void ems_pcmcia_remove(struct pcmcia_device *dev)
+{
+ ems_pcmcia_del_card(dev);
+ pcmcia_disable_device(dev);
+}
+
+static struct pcmcia_driver ems_pcmcia_driver = {
+ .name = DRV_NAME,
+ .probe = ems_pcmcia_probe,
+ .remove = ems_pcmcia_remove,
+ .id_table = ems_pcmcia_tbl,
+};
+
+static int __init ems_pcmcia_init(void)
+{
+ return pcmcia_register_driver(&ems_pcmcia_driver);
+}
+module_init(ems_pcmcia_init);
+
+static void __exit ems_pcmcia_exit(void)
+{
+ pcmcia_unregister_driver(&ems_pcmcia_driver);
+}
+module_exit(ems_pcmcia_exit);
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
new file mode 100644
index 000000000000..905bce0b3a43
--- /dev/null
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2007, 2011 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * Derived from the PCAN project file driver/src/pcan_pci.c:
+ *
+ * Copyright (C) 2001-2006 PEAK System-Technik GmbH
+ *
+ * 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
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+
+#include "sja1000.h"
+
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI/PCIe cards");
+MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe CAN card");
+MODULE_LICENSE("GPL v2");
+
+#define DRV_NAME "peak_pci"
+
+struct peak_pci_chan {
+ void __iomem *cfg_base; /* Common for all channels */
+ struct net_device *next_dev; /* Chain of network devices */
+ u16 icr_mask; /* Interrupt mask for fast ack */
+};
+
+#define PEAK_PCI_CAN_CLOCK (16000000 / 2)
+
+#define PEAK_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK)
+#define PEAK_PCI_OCR OCR_TX0_PUSHPULL
+
+/*
+ * Important PITA registers
+ */
+#define PITA_ICR 0x00 /* Interrupt control register */
+#define PITA_GPIOICR 0x18 /* GPIO interface control register */
+#define PITA_MISC 0x1C /* Miscellaneous register */
+
+#define PEAK_PCI_CFG_SIZE 0x1000 /* Size of the config PCI bar */
+#define PEAK_PCI_CHAN_SIZE 0x0400 /* Size used by the channel */
+
+#define PEAK_PCI_VENDOR_ID 0x001C /* The PCI device and vendor IDs */
+#define PEAK_PCI_DEVICE_ID 0x0001 /* for PCI/PCIe slot cards */
+
+static const u16 peak_pci_icr_masks[] = {0x02, 0x01, 0x40, 0x80};
+
+static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = {
+ {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, peak_pci_tbl);
+
+static u8 peak_pci_read_reg(const struct sja1000_priv *priv, int port)
+{
+ return readb(priv->reg_base + (port << 2));
+}
+
+static void peak_pci_write_reg(const struct sja1000_priv *priv,
+ int port, u8 val)
+{
+ writeb(val, priv->reg_base + (port << 2));
+}
+
+static void peak_pci_post_irq(const struct sja1000_priv *priv)
+{
+ struct peak_pci_chan *chan = priv->priv;
+ u16 icr;
+
+ /* Select and clear in PITA stored interrupt */
+ icr = readw(chan->cfg_base + PITA_ICR);
+ if (icr & chan->icr_mask)
+ 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)
+{
+ struct sja1000_priv *priv;
+ struct peak_pci_chan *chan;
+ struct net_device *dev, *dev0 = NULL;
+ void __iomem *cfg_base, *reg_base;
+ u16 sub_sys_id, icr;
+ int i, err, channels;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err)
+ goto failure_disable_pci;
+
+ err = pci_read_config_word(pdev, 0x2e, &sub_sys_id);
+ if (err)
+ goto failure_release_regions;
+
+ dev_dbg(&pdev->dev, "probing device %04x:%04x:%04x\n",
+ pdev->vendor, pdev->device, sub_sys_id);
+
+ err = pci_write_config_word(pdev, 0x44, 0);
+ if (err)
+ goto failure_release_regions;
+
+ if (sub_sys_id >= 12)
+ channels = 4;
+ else if (sub_sys_id >= 10)
+ channels = 3;
+ else if (sub_sys_id >= 4)
+ channels = 2;
+ else
+ channels = 1;
+
+ cfg_base = pci_iomap(pdev, 0, PEAK_PCI_CFG_SIZE);
+ if (!cfg_base) {
+ dev_err(&pdev->dev, "failed to map PCI resource #0\n");
+ goto failure_release_regions;
+ }
+
+ reg_base = pci_iomap(pdev, 1, PEAK_PCI_CHAN_SIZE * channels);
+ if (!reg_base) {
+ dev_err(&pdev->dev, "failed to map PCI resource #1\n");
+ goto failure_unmap_cfg_base;
+ }
+
+ /* Set GPIO control register */
+ writew(0x0005, cfg_base + PITA_GPIOICR + 2);
+ /* Enable all channels of this card */
+ writeb(0x00, cfg_base + PITA_GPIOICR);
+ /* Toggle reset */
+ writeb(0x05, cfg_base + PITA_MISC + 3);
+ mdelay(5);
+ /* Leave parport mux mode */
+ writeb(0x04, cfg_base + PITA_MISC + 3);
+
+ icr = readw(cfg_base + PITA_ICR + 2);
+
+ for (i = 0; i < channels; i++) {
+ dev = alloc_sja1000dev(sizeof(struct peak_pci_chan));
+ if (!dev) {
+ err = -ENOMEM;
+ goto failure_remove_channels;
+ }
+
+ priv = netdev_priv(dev);
+ chan = priv->priv;
+
+ chan->cfg_base = cfg_base;
+ priv->reg_base = reg_base + i * PEAK_PCI_CHAN_SIZE;
+
+ priv->read_reg = peak_pci_read_reg;
+ priv->write_reg = peak_pci_write_reg;
+ priv->post_irq = peak_pci_post_irq;
+
+ priv->can.clock.freq = PEAK_PCI_CAN_CLOCK;
+ priv->ocr = PEAK_PCI_OCR;
+ priv->cdr = PEAK_PCI_CDR;
+ /* Neither a slave nor a single device distributes the clock */
+ if (channels == 1 || i > 0)
+ priv->cdr |= CDR_CLK_OFF;
+
+ /* Setup interrupt handling */
+ priv->irq_flags = IRQF_SHARED;
+ dev->irq = pdev->irq;
+
+ chan->icr_mask = peak_pci_icr_masks[i];
+ icr |= chan->icr_mask;
+
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ err = register_sja1000dev(dev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register device\n");
+ free_sja1000dev(dev);
+ goto failure_remove_channels;
+ }
+
+ /* Create chain of SJA1000 devices */
+ if (i == 0)
+ dev0 = dev;
+ else
+ chan->next_dev = dev;
+
+ dev_info(&pdev->dev,
+ "%s at reg_base=0x%p cfg_base=0x%p irq=%d\n",
+ dev->name, priv->reg_base, chan->cfg_base, dev->irq);
+ }
+
+ pci_set_drvdata(pdev, dev0);
+
+ /* Enable interrupts */
+ writew(icr, cfg_base + PITA_ICR + 2);
+
+ return 0;
+
+failure_remove_channels:
+ /* Disable interrupts */
+ writew(0x0, cfg_base + PITA_ICR + 2);
+
+ for (dev = dev0; dev; dev = chan->next_dev) {
+ unregister_sja1000dev(dev);
+ free_sja1000dev(dev);
+ priv = netdev_priv(dev);
+ chan = priv->priv;
+ dev = chan->next_dev;
+ }
+
+ pci_iounmap(pdev, reg_base);
+
+failure_unmap_cfg_base:
+ pci_iounmap(pdev, cfg_base);
+
+failure_release_regions:
+ pci_release_regions(pdev);
+
+failure_disable_pci:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void __devexit peak_pci_remove(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev); /* First device */
+ struct sja1000_priv *priv = netdev_priv(dev);
+ struct peak_pci_chan *chan = priv->priv;
+ void __iomem *cfg_base = chan->cfg_base;
+ void __iomem *reg_base = priv->reg_base;
+
+ /* Disable interrupts */
+ writew(0x0, cfg_base + PITA_ICR + 2);
+
+ /* Loop over all registered devices */
+ while (1) {
+ dev_info(&pdev->dev, "removing device %s\n", dev->name);
+ unregister_sja1000dev(dev);
+ free_sja1000dev(dev);
+ dev = chan->next_dev;
+ if (!dev)
+ break;
+ priv = netdev_priv(dev);
+ chan = priv->priv;
+ }
+
+ pci_iounmap(pdev, reg_base);
+ pci_iounmap(pdev, cfg_base);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+ pci_set_drvdata(pdev, NULL);
+}
+
+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),
+};
+
+static int __init peak_pci_init(void)
+{
+ return pci_register_driver(&peak_pci_driver);
+}
+module_init(peak_pci_init);
+
+static void __exit peak_pci_exit(void)
+{
+ pci_unregister_driver(&peak_pci_driver);
+}
+module_exit(peak_pci_exit);
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index f501bba1fc6f..04a3f1b756a8 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -40,8 +40,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*/
#include <linux/module.h>
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index 78bd4ecac140..23fff06875f5 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -40,8 +40,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*/
#ifndef SJA1000_DEV_H
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index cee6ba2b8b58..c3dd9d09be57 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -29,7 +29,7 @@
* nxp,external-clock-frequency = <16000000>;
* };
*
- * See "Documentation/powerpc/dts-bindings/can/sja1000.txt" for further
+ * See "Documentation/devicetree/bindings/net/can/sja1000.txt" for further
* information.
*/
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 4b70b7e8bdeb..a979b006f459 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -35,8 +35,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*/
#include <linux/module.h>
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
index a30b8f480f61..f93e2d6fc88c 100644
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -37,8 +37,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
*/
#include <linux/module.h>
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index e66aceb57cef..7cb2785e209d 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -261,7 +261,7 @@ static const struct net_device_ops e100_netdev_ops = {
.ndo_start_xmit = e100_send_packet,
.ndo_tx_timeout = e100_tx_timeout,
.ndo_get_stats = e100_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_do_ioctl = e100_ioctl,
.ndo_set_mac_address = e100_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 39cf9b9bd673..a7c5e8831e8c 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -116,7 +116,7 @@ static const struct net_device_ops dummy_netdev_ops = {
.ndo_init = dummy_dev_init,
.ndo_start_xmit = dummy_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_set_mac_address = dummy_set_address,
.ndo_get_stats64 = dummy_get_stats64,
};
diff --git a/drivers/net/3c501.c b/drivers/net/ethernet/3com/3c501.c
index 5420f6de27df..68da81d476f3 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/ethernet/3com/3c501.c
@@ -201,7 +201,7 @@ static const struct net_device_ops el_netdev_ops = {
.ndo_stop = el1_close,
.ndo_start_xmit = el_start_xmit,
.ndo_tx_timeout = el_timeout,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/3c501.h b/drivers/net/ethernet/3com/3c501.h
index 183fd55f03cb..183fd55f03cb 100644
--- a/drivers/net/3c501.h
+++ b/drivers/net/ethernet/3com/3c501.h
diff --git a/drivers/net/3c509.c b/drivers/net/ethernet/3com/3c509.c
index 44b28b2d7003..92053e6fc980 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/ethernet/3com/3c509.c
@@ -545,7 +545,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_stop = el3_close,
.ndo_start_xmit = el3_start_xmit,
.ndo_get_stats = el3_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = el3_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/3c515.c b/drivers/net/ethernet/3com/3c515.c
index d2bb4b254c57..f67a5d3a200c 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/ethernet/3com/3c515.c
@@ -569,7 +569,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_start_xmit = corkscrew_start_xmit,
.ndo_tx_timeout = corkscrew_timeout,
.ndo_get_stats = corkscrew_get_stats,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c
index 34c5e1cbf65d..9c01bc9235b3 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/ethernet/3com/3c574_cs.c
@@ -255,7 +255,7 @@ static const struct net_device_ops el3_netdev_ops = {
.ndo_tx_timeout = el3_tx_timeout,
.ndo_get_stats = el3_get_stats,
.ndo_do_ioctl = el3_ioctl,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c
index 4a1a35809807..972f80ecc510 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/ethernet/3com/3c589_cs.c
@@ -184,7 +184,7 @@ static const struct net_device_ops el3_netdev_ops = {
.ndo_tx_timeout = el3_tx_timeout,
.ndo_set_config = el3_config,
.ndo_get_stats = el3_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 8cc22568ebd3..b42c06baba89 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -1055,7 +1055,7 @@ static const struct net_device_ops boomrang_netdev_ops = {
#ifdef CONFIG_PCI
.ndo_do_ioctl = vortex_ioctl,
#endif
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
@@ -1073,7 +1073,7 @@ static const struct net_device_ops vortex_netdev_ops = {
#ifdef CONFIG_PCI
.ndo_do_ioctl = vortex_ioctl,
#endif
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
@@ -2179,14 +2179,15 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
vp->tx_ring[entry].frag[i+1].addr =
- cpu_to_le32(pci_map_single(VORTEX_PCI(vp),
- (void*)page_address(frag->page) + frag->page_offset,
- frag->size, PCI_DMA_TODEVICE));
+ cpu_to_le32(pci_map_single(
+ VORTEX_PCI(vp),
+ (void *)skb_frag_address(frag),
+ skb_frag_size(frag), PCI_DMA_TODEVICE));
if (i == skb_shinfo(skb)->nr_frags-1)
- vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(frag->size|LAST_FRAG);
+ vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag)|LAST_FRAG);
else
- vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(frag->size);
+ vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag));
}
}
#else
diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig
new file mode 100644
index 000000000000..a8bb30cf512d
--- /dev/null
+++ b/drivers/net/ethernet/3com/Kconfig
@@ -0,0 +1,122 @@
+#
+# 3Com Ethernet device configuration
+#
+
+config NET_VENDOR_3COM
+ bool "3Com devices"
+ default y
+ depends on ISA || EISA || MCA || PCI || PCMCIA
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about 3Com cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_3COM
+
+config EL1
+ tristate "3c501 \"EtherLink\" support"
+ depends on ISA
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Also, consider buying a
+ new card, since the 3c501 is slow, broken, and obsolete: you will
+ have problems. Some people suggest to ping ("man ping") a nearby
+ machine every minute ("man cron") when using this card.
+
+ To compile this driver as a module, choose M here. The module
+ will be called 3c501.
+
+config EL3
+ tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support"
+ depends on (ISA || EISA || MCA)
+ ---help---
+ If you have a network (Ethernet) card belonging to the 3Com
+ EtherLinkIII series, say Y and read the Ethernet-HOWTO, available
+ from <http://www.tldp.org/docs.html#howto>.
+
+ If your card is not working you may need to use the DOS
+ setup disk to disable Plug & Play mode, and to select the default
+ media type.
+
+ To compile this driver as a module, choose M here. The module
+ will be called 3c509.
+
+config 3C515
+ tristate "3c515 ISA \"Fast EtherLink\""
+ depends on (ISA || EISA) && ISA_DMA_API
+ ---help---
+ If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet
+ network card, say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called 3c515.
+
+config PCMCIA_3C574
+ tristate "3Com 3c574 PCMCIA support"
+ depends on PCMCIA
+ ---help---
+ Say Y here if you intend to attach a 3Com 3c574 or compatible PCMCIA
+ (PC-card) Fast Ethernet card to your computer.
+
+ To compile this driver as a module, choose M here: the module will be
+ called 3c574_cs. If unsure, say N.
+
+config PCMCIA_3C589
+ tristate "3Com 3c589 PCMCIA support"
+ depends on PCMCIA
+ ---help---
+ Say Y here if you intend to attach a 3Com 3c589 or compatible PCMCIA
+ (PC-card) Ethernet card to your computer.
+
+ To compile this driver as a module, choose M here: the module will be
+ called 3c589_cs. If unsure, say N.
+
+config VORTEX
+ tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
+ depends on (PCI || EISA)
+ select NET_CORE
+ select MII
+ ---help---
+ This option enables driver support for a large number of 10Mbps and
+ 10/100Mbps EISA, PCI and PCMCIA 3Com network cards:
+
+ "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI
+ "Boomerang" (EtherLink XL 3c900 or 3c905) PCI
+ "Cyclone" (3c540/3c900/3c905/3c980/3c575/3c656) PCI and Cardbus
+ "Tornado" (3c905) PCI
+ "Hurricane" (3c555/3cSOHO) PCI
+
+ If you have such a card, say Y and read the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>. More
+ specific information is in
+ <file:Documentation/networking/vortex.txt> and in the comments at
+ the beginning of <file:drivers/net/3c59x.c>.
+
+ To compile this support as a module, choose M here.
+
+config TYPHOON
+ tristate "3cr990 series \"Typhoon\" support"
+ depends on PCI
+ select CRC32
+ ---help---
+ This option enables driver support for the 3cr990 series of cards:
+
+ 3C990-TX, 3CR990-TX-95, 3CR990-TX-97, 3CR990-FX-95, 3CR990-FX-97,
+ 3CR990SVR, 3CR990SVR95, 3CR990SVR97, 3CR990-FX-95 Server,
+ 3CR990-FX-97 Server, 3C990B-TX-M, 3C990BSVR
+
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called typhoon.
+
+endif # NET_VENDOR_3COM
diff --git a/drivers/net/ethernet/3com/Makefile b/drivers/net/ethernet/3com/Makefile
new file mode 100644
index 000000000000..1e5382a30ead
--- /dev/null
+++ b/drivers/net/ethernet/3com/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the 3Com Ethernet device drivers
+#
+
+obj-$(CONFIG_EL1) += 3c501.o
+obj-$(CONFIG_EL3) += 3c509.o
+obj-$(CONFIG_3C515) += 3c515.o
+obj-$(CONFIG_PCMCIA_3C589) += 3c589_cs.o
+obj-$(CONFIG_PCMCIA_3C574) += 3c574_cs.o
+obj-$(CONFIG_VORTEX) += 3c59x.o
+obj-$(CONFIG_TYPHOON) += typhoon.o
diff --git a/drivers/net/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index 1d5091a1e49a..20ea07508ac7 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -810,17 +810,16 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
txd->frag.addrHi = 0;
first_txd->numDesc++;
- for(i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
void *frag_addr;
txd = (struct tx_desc *) (txRing->ringBase +
txRing->lastWrite);
typhoon_inc_tx_index(&txRing->lastWrite, 1);
- len = frag->size;
- frag_addr = (void *) page_address(frag->page) +
- frag->page_offset;
+ len = skb_frag_size(frag);
+ frag_addr = skb_frag_address(frag);
skb_dma = pci_map_single(tp->tx_pdev, frag_addr, len,
PCI_DMA_TODEVICE);
txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID;
@@ -1149,13 +1148,9 @@ static void
typhoon_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
{
ering->rx_max_pending = RXENT_ENTRIES;
- ering->rx_mini_max_pending = 0;
- ering->rx_jumbo_max_pending = 0;
ering->tx_max_pending = TXLO_ENTRIES - 1;
ering->rx_pending = RXENT_ENTRIES;
- ering->rx_mini_pending = 0;
- ering->rx_jumbo_pending = 0;
ering->tx_pending = TXLO_ENTRIES - 1;
}
@@ -2266,7 +2261,7 @@ static const struct net_device_ops typhoon_netdev_ops = {
.ndo_open = typhoon_open,
.ndo_stop = typhoon_close,
.ndo_start_xmit = typhoon_start_tx,
- .ndo_set_multicast_list = typhoon_set_rx_mode,
+ .ndo_set_rx_mode = typhoon_set_rx_mode,
.ndo_tx_timeout = typhoon_tx_timeout,
.ndo_get_stats = typhoon_get_stats,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/typhoon.h b/drivers/net/ethernet/3com/typhoon.h
index 88187fc84aa3..88187fc84aa3 100644
--- a/drivers/net/typhoon.h
+++ b/drivers/net/ethernet/3com/typhoon.h
diff --git a/drivers/net/3c503.c b/drivers/net/ethernet/8390/3c503.c
index 84e68f1b9adf..fbab1367505f 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/ethernet/8390/3c503.c
@@ -176,7 +176,7 @@ static const struct net_device_ops el2_netdev_ops = {
.ndo_start_xmit = eip_start_xmit,
.ndo_tx_timeout = eip_tx_timeout,
.ndo_get_stats = eip_get_stats,
- .ndo_set_multicast_list = eip_set_multicast_list,
+ .ndo_set_rx_mode = eip_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/3c503.h b/drivers/net/ethernet/8390/3c503.h
index e2367b82a2ec..e2367b82a2ec 100644
--- a/drivers/net/3c503.h
+++ b/drivers/net/ethernet/8390/3c503.h
diff --git a/drivers/net/8390.c b/drivers/net/ethernet/8390/8390.c
index 7c7518be1756..5db1f55abef4 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/ethernet/8390/8390.c
@@ -61,7 +61,7 @@ const struct net_device_ops ei_netdev_ops = {
.ndo_start_xmit = ei_start_xmit,
.ndo_tx_timeout = ei_tx_timeout,
.ndo_get_stats = ei_get_stats,
- .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/8390.h b/drivers/net/ethernet/8390/8390.h
index 58a12e4c78f9..58a12e4c78f9 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/ethernet/8390/8390.h
diff --git a/drivers/net/8390p.c b/drivers/net/ethernet/8390/8390p.c
index a2a64ea0b691..e8fc2e87e840 100644
--- a/drivers/net/8390p.c
+++ b/drivers/net/ethernet/8390/8390p.c
@@ -66,7 +66,7 @@ const struct net_device_ops eip_netdev_ops = {
.ndo_start_xmit = eip_start_xmit,
.ndo_tx_timeout = eip_tx_timeout,
.ndo_get_stats = eip_get_stats,
- .ndo_set_multicast_list = eip_set_multicast_list,
+ .ndo_set_rx_mode = eip_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
new file mode 100644
index 000000000000..e04ade444247
--- /dev/null
+++ b/drivers/net/ethernet/8390/Kconfig
@@ -0,0 +1,337 @@
+#
+# 8390 device configuration
+#
+
+config NET_VENDOR_8390
+ bool "National Semi-conductor 8390 devices"
+ default y
+ depends on NET_VENDOR_NATSEMI && (AMIGA_PCMCIA || PCI || SUPERH || \
+ ISA || MCA || EISA || MAC || M32R || MACH_TX49XX || \
+ MCA_LEGACY || H8300 || ARM || MIPS || ZORRO || PCMCIA || \
+ EXPERIMENTAL)
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Western Digital cards. If you say Y, you will be
+ asked for your specific card in the following questions.
+
+if NET_VENDOR_8390
+
+config EL2
+ tristate "3c503 \"EtherLink II\" support"
+ depends on ISA
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called 3c503.
+
+config AC3200
+ tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
+ depends on PCI && (ISA || EISA) && EXPERIMENTAL
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ac3200.
+
+config PCMCIA_AXNET
+ tristate "Asix AX88190 PCMCIA support"
+ depends on PCMCIA
+ ---help---
+ Say Y here if you intend to attach an Asix AX88190-based PCMCIA
+ (PC-card) Fast Ethernet card to your computer. These cards are
+ nearly NE2000 compatible but need a separate driver due to a few
+ misfeatures.
+
+ To compile this driver as a module, choose M here: the module will be
+ called axnet_cs. If unsure, say N.
+
+config AX88796
+ tristate "ASIX AX88796 NE2000 clone support"
+ depends on (ARM || MIPS || SUPERH)
+ select PHYLIB
+ select MDIO_BITBANG
+ ---help---
+ AX88796 driver, using platform bus to provide
+ chip detection and resources
+
+config AX88796_93CX6
+ bool "ASIX AX88796 external 93CX6 eeprom support"
+ depends on AX88796
+ select EEPROM_93CX6
+ ---help---
+ Select this if your platform comes with an external 93CX6 eeprom.
+
+config E2100
+ tristate "Cabletron E21xx support"
+ depends on ISA
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called e2100.
+
+config ES3210
+ tristate "Racal-Interlan EISA ES3210 support (EXPERIMENTAL)"
+ depends on PCI && EISA && EXPERIMENTAL
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called es3210.
+
+config HPLAN_PLUS
+ tristate "HP PCLAN+ (27247B and 27252A) support"
+ depends on ISA
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called hp-plus.
+
+config HPLAN
+ tristate "HP PCLAN (27245 and other 27xxx series) support"
+ depends on ISA
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called hp.
+
+config HYDRA
+ tristate "Hydra support"
+ depends on ZORRO
+ select CRC32
+ ---help---
+ If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
+
+ To compile this driver as a module, choose M here: the module
+ will be called hydra.
+
+config ARM_ETHERH
+ tristate "I-cubed EtherH/ANT EtherM support"
+ depends on ARM && ARCH_ACORN
+ select CRC32
+ ---help---
+ If you have an Acorn system with one of these network cards, you
+ should say Y to this option if you wish to use it with Linux.
+
+config LNE390
+ tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
+ depends on PCI && EISA && EXPERIMENTAL
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called lne390.
+
+config MAC8390
+ bool "Macintosh NS 8390 based ethernet cards"
+ depends on MAC
+ select CRC32
+ ---help---
+ If you want to include a driver to support Nubus or LC-PDS
+ Ethernet cards using an NS8390 chipset or its equivalent, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+config NE2000
+ tristate "NE2000/NE1000 support"
+ depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX)
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Many Ethernet cards
+ without a specific driver are compatible with NE2000.
+
+ If you have a PCI NE2000 card however, say N here and Y to "PCI
+ NE2000 and clone support" under "EISA, VLB, PCI and on board
+ controllers" below. If you have a NE2000 card and are running on
+ an MCA system (a bus system used on some IBM PS/2 computers and
+ laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
+ below.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ne.
+
+config NE2_MCA
+ tristate "NE/2 (ne2000 MCA version) support"
+ depends on MCA_LEGACY
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ne2.
+
+config NE2K_PCI
+ tristate "PCI NE2000 and clones support (see help)"
+ depends on PCI
+ select CRC32
+ ---help---
+ This driver is for NE2000 compatible PCI cards. It will not work
+ with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
+ support" below). If you have a PCI NE2000 network (Ethernet) card,
+ say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver also works for the following NE2000 clone cards:
+ RealTek RTL-8029 Winbond 89C940 Compex RL2000 KTI ET32P2
+ NetVin NV5000SC Via 86C926 SureCom NE34 Winbond
+ Holtek HT80232 Holtek HT80229
+
+ To compile this driver as a module, choose M here. The module
+ will be called ne2k-pci.
+
+config APNE
+ tristate "PCMCIA NE2000 support"
+ depends on AMIGA_PCMCIA
+ select CRC32
+ ---help---
+ If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
+ say N.
+
+ To compile this driver as a module, choose M here: the module
+ will be called apne.
+
+config NE3210
+ tristate "Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)"
+ depends on PCI && EISA && EXPERIMENTAL
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Note that this driver
+ will NOT WORK for NE3200 cards as they are completely different.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ne3210.
+
+config PCMCIA_PCNET
+ tristate "NE2000 compatible PCMCIA support"
+ depends on PCMCIA
+ select CRC32
+ ---help---
+ Say Y here if you intend to attach an NE2000 compatible PCMCIA
+ (PC-card) Ethernet or Fast Ethernet card to your computer.
+
+ To compile this driver as a module, choose M here: the module will be
+ called pcnet_cs. If unsure, say N.
+
+config NE_H8300
+ tristate "NE2000 compatible support for H8/300"
+ depends on H8300
+ ---help---
+ Say Y here if you want to use the NE2000 compatible
+ controller on the Renesas H8/300 processor.
+
+config STNIC
+ tristate "National DP83902AV support"
+ depends on SUPERH
+ select CRC32
+ ---help---
+ Support for cards based on the National Semiconductor DP83902AV
+ ST-NIC Serial Network Interface Controller for Twisted Pair. This
+ is a 10Mbit/sec Ethernet controller. Product overview and specs at
+ <http://www.national.com/pf/DP/DP83902A.html>.
+
+ If unsure, say N.
+
+config ULTRAMCA
+ tristate "SMC Ultra MCA support"
+ depends on MCA
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type and are running
+ an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called smc-mca.
+
+config ULTRA
+ tristate "SMC Ultra support"
+ depends on ISA
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Important: There have been many reports that, with some motherboards
+ mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible,
+ such as some BusLogic models) causes corruption problems with many
+ operating systems. The Linux smc-ultra driver has a work-around for
+ this but keep it in mind if you have such a SCSI card and have
+ problems.
+
+ To compile this driver as a module, choose M here. The module
+ will be called smc-ultra.
+
+config ULTRA32
+ tristate "SMC Ultra32 EISA support"
+ depends on EISA
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called smc-ultra32.
+
+config WD80x3
+ tristate "WD80*3 support"
+ depends on ISA
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called wd.
+
+config ZORRO8390
+ tristate "Zorro NS8390-based Ethernet support"
+ depends on ZORRO
+ select CRC32
+ ---help---
+ This driver is for Zorro Ethernet cards using an NS8390-compatible
+ chipset, like the Village Tronic Ariadne II and the Individual
+ Computers X-Surf Ethernet cards. If you have such a card, say Y.
+ Otherwise, say N.
+
+ To compile this driver as a module, choose M here: the module
+ will be called zorro8390.
+
+endif # NET_VENDOR_8390
diff --git a/drivers/net/ethernet/8390/Makefile b/drivers/net/ethernet/8390/Makefile
new file mode 100644
index 000000000000..3337d7fb4344
--- /dev/null
+++ b/drivers/net/ethernet/8390/Makefile
@@ -0,0 +1,29 @@
+#
+# Makefile for the 8390 network device drivers.
+#
+
+obj-$(CONFIG_MAC8390) += mac8390.o
+obj-$(CONFIG_AC3200) += ac3200.o 8390.o
+obj-$(CONFIG_APNE) += apne.o 8390.o
+obj-$(CONFIG_ARM_ETHERH) += etherh.o
+obj-$(CONFIG_AX88796) += ax88796.o
+obj-$(CONFIG_E2100) += e2100.o 8390.o
+obj-$(CONFIG_EL2) += 3c503.o 8390p.o
+obj-$(CONFIG_ES3210) += es3210.o 8390.o
+obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o
+obj-$(CONFIG_HPLAN) += hp.o 8390p.o
+obj-$(CONFIG_HYDRA) += hydra.o 8390.o
+obj-$(CONFIG_LNE390) += lne390.o 8390.o
+obj-$(CONFIG_NE2000) += ne.o 8390p.o
+obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o
+obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
+obj-$(CONFIG_NE3210) += ne3210.o 8390.o
+obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o 8390.o
+obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o 8390.o
+obj-$(CONFIG_STNIC) += stnic.o 8390.o
+obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
+obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
+obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
+obj-$(CONFIG_WD80x3) += wd.o 8390.o
+obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
diff --git a/drivers/net/ac3200.c b/drivers/net/ethernet/8390/ac3200.c
index f07b2e980fbc..5337dd0a59b0 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ethernet/8390/ac3200.c
@@ -151,7 +151,7 @@ static const struct net_device_ops ac_netdev_ops = {
.ndo_start_xmit = ei_start_xmit,
.ndo_tx_timeout = ei_tx_timeout,
.ndo_get_stats = ei_get_stats,
- .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/apne.c b/drivers/net/ethernet/8390/apne.c
index 547737340cbb..547737340cbb 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/ethernet/8390/apne.c
diff --git a/drivers/net/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index e7cb8c8b9776..e9f8432f55b4 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -543,7 +543,7 @@ static const struct net_device_ops ax_netdev_ops = {
.ndo_start_xmit = ax_ei_start_xmit,
.ndo_tx_timeout = ax_ei_tx_timeout,
.ndo_get_stats = ax_ei_get_stats,
- .ndo_set_multicast_list = ax_ei_set_multicast_list,
+ .ndo_set_rx_mode = ax_ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c
index 9953db711969..bba51cdc74a1 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/ethernet/8390/axnet_cs.c
@@ -38,7 +38,7 @@
#include <linux/etherdevice.h>
#include <linux/crc32.h>
#include <linux/mii.h>
-#include "../8390.h"
+#include "8390.h"
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
@@ -134,7 +134,7 @@ static const struct net_device_ops axnet_netdev_ops = {
.ndo_start_xmit = axnet_start_xmit,
.ndo_tx_timeout = axnet_tx_timeout,
.ndo_get_stats = get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/e2100.c b/drivers/net/ethernet/8390/e2100.c
index d50a9998ae77..d16dc53c1813 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/ethernet/8390/e2100.c
@@ -168,7 +168,7 @@ static const struct net_device_ops e21_netdev_ops = {
.ndo_start_xmit = ei_start_xmit,
.ndo_tx_timeout = ei_tx_timeout,
.ndo_get_stats = ei_get_stats,
- .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/es3210.c b/drivers/net/ethernet/8390/es3210.c
index 7a09575ecff0..7a09575ecff0 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/ethernet/8390/es3210.c
diff --git a/drivers/net/arm/etherh.c b/drivers/net/ethernet/8390/etherh.c
index 03e217a868d4..48c4948750d1 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/ethernet/8390/etherh.c
@@ -65,7 +65,7 @@
static char version[] __initdata =
"EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n";
-#include "../lib8390.c"
+#include "lib8390.c"
static unsigned int net_debug = NET_DEBUG;
@@ -644,7 +644,7 @@ static const struct net_device_ops etherh_netdev_ops = {
.ndo_start_xmit = __ei_start_xmit,
.ndo_tx_timeout = __ei_tx_timeout,
.ndo_get_stats = __ei_get_stats,
- .ndo_set_multicast_list = __ei_set_multicast_list,
+ .ndo_set_rx_mode = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/hp-plus.c b/drivers/net/ethernet/8390/hp-plus.c
index 29917363ebfb..eeac843dcd2d 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/ethernet/8390/hp-plus.c
@@ -165,7 +165,7 @@ static const struct net_device_ops hpp_netdev_ops = {
.ndo_start_xmit = eip_start_xmit,
.ndo_tx_timeout = eip_tx_timeout,
.ndo_get_stats = eip_get_stats,
- .ndo_set_multicast_list = eip_set_multicast_list,
+ .ndo_set_rx_mode = eip_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/hp.c b/drivers/net/ethernet/8390/hp.c
index 18564d4a7c04..18564d4a7c04 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/ethernet/8390/hp.c
diff --git a/drivers/net/hydra.c b/drivers/net/ethernet/8390/hydra.c
index 1cd481c04202..3dac937a67c4 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/ethernet/8390/hydra.c
@@ -101,7 +101,7 @@ static const struct net_device_ops hydra_netdev_ops = {
.ndo_start_xmit = __ei_start_xmit,
.ndo_tx_timeout = __ei_tx_timeout,
.ndo_get_stats = __ei_get_stats,
- .ndo_set_multicast_list = __ei_set_multicast_list,
+ .ndo_set_rx_mode = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/lib8390.c b/drivers/net/ethernet/8390/lib8390.c
index 05ae21435bfd..05ae21435bfd 100644
--- a/drivers/net/lib8390.c
+++ b/drivers/net/ethernet/8390/lib8390.c
diff --git a/drivers/net/lne390.c b/drivers/net/ethernet/8390/lne390.c
index f9888d20177b..f9888d20177b 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/ethernet/8390/lne390.c
diff --git a/drivers/net/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
index f84f5e6ededb..af5d9822cad9 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -494,7 +494,7 @@ static const struct net_device_ops mac8390_netdev_ops = {
.ndo_start_xmit = __ei_start_xmit,
.ndo_tx_timeout = __ei_tx_timeout,
.ndo_get_stats = __ei_get_stats,
- .ndo_set_multicast_list = __ei_set_multicast_list,
+ .ndo_set_rx_mode = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ethernet/8390/ne-h8300.c
index 7298a34bc795..cd36a6a5f408 100644
--- a/drivers/net/ne-h8300.c
+++ b/drivers/net/ethernet/8390/ne-h8300.c
@@ -200,7 +200,7 @@ static const struct net_device_ops ne_netdev_ops = {
.ndo_start_xmit = __ei_start_xmit,
.ndo_tx_timeout = __ei_tx_timeout,
.ndo_get_stats = __ei_get_stats,
- .ndo_set_multicast_list = __ei_set_multicast_list,
+ .ndo_set_rx_mode = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/ne.c b/drivers/net/ethernet/8390/ne.c
index 1063093b3afc..1063093b3afc 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ethernet/8390/ne.c
diff --git a/drivers/net/ne2.c b/drivers/net/ethernet/8390/ne2.c
index 70cdc6996342..70cdc6996342 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ethernet/8390/ne2.c
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c
index 3c333cb5d34e..39923425ba25 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ethernet/8390/ne2k-pci.c
@@ -207,7 +207,7 @@ static const struct net_device_ops ne2k_netdev_ops = {
.ndo_start_xmit = ei_start_xmit,
.ndo_tx_timeout = ei_tx_timeout,
.ndo_get_stats = ei_get_stats,
- .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/ne3210.c b/drivers/net/ethernet/8390/ne3210.c
index 243ed2aee88e..243ed2aee88e 100644
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ethernet/8390/ne3210.c
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
index b4fd7c3ed077..053b2551a72d 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/ethernet/8390/pcnet_cs.c
@@ -41,7 +41,7 @@
#include <linux/log2.h>
#include <linux/etherdevice.h>
#include <linux/mii.h>
-#include "../8390.h"
+#include "8390.h"
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
@@ -227,7 +227,7 @@ static const struct net_device_ops pcnet_netdev_ops = {
.ndo_start_xmit = ei_start_xmit,
.ndo_get_stats = ei_get_stats,
.ndo_do_ioctl = ei_ioctl,
- .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_set_rx_mode = ei_set_multicast_list,
.ndo_tx_timeout = ei_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/smc-mca.c b/drivers/net/ethernet/8390/smc-mca.c
index 34934fb23b97..77efec44fea0 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/ethernet/8390/smc-mca.c
@@ -191,7 +191,7 @@ static const struct net_device_ops ultramca_netdev_ops = {
.ndo_start_xmit = ei_start_xmit,
.ndo_tx_timeout = ei_tx_timeout,
.ndo_get_stats = ei_get_stats,
- .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/smc-ultra.c b/drivers/net/ethernet/8390/smc-ultra.c
index ba44ede29198..1cc306a83ff7 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/ethernet/8390/smc-ultra.c
@@ -192,7 +192,7 @@ static const struct net_device_ops ultra_netdev_ops = {
.ndo_start_xmit = ei_start_xmit,
.ndo_tx_timeout = ei_tx_timeout,
.ndo_get_stats = ei_get_stats,
- .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/ethernet/8390/smc-ultra32.c
index e459c3b2510a..bb87053eb3da 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/ethernet/8390/smc-ultra32.c
@@ -160,7 +160,7 @@ static const struct net_device_ops ultra32_netdev_ops = {
.ndo_start_xmit = ei_start_xmit,
.ndo_tx_timeout = ei_tx_timeout,
.ndo_get_stats = ei_get_stats,
- .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/stnic.c b/drivers/net/ethernet/8390/stnic.c
index d85f0a84bc7b..d85f0a84bc7b 100644
--- a/drivers/net/stnic.c
+++ b/drivers/net/ethernet/8390/stnic.c
diff --git a/drivers/net/wd.c b/drivers/net/ethernet/8390/wd.c
index 8831a3393ecf..c175fadb597b 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/ethernet/8390/wd.c
@@ -153,7 +153,7 @@ static const struct net_device_ops wd_netdev_ops = {
.ndo_start_xmit = ei_start_xmit,
.ndo_tx_timeout = ei_tx_timeout,
.ndo_get_stats = ei_get_stats,
- .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_set_rx_mode = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c
index 15e7751a273c..3aa9fe9999b5 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/ethernet/8390/zorro8390.c
@@ -278,7 +278,7 @@ static const struct net_device_ops zorro8390_netdev_ops = {
.ndo_start_xmit = __ei_start_xmit,
.ndo_tx_timeout = __ei_tx_timeout,
.ndo_get_stats = __ei_get_stats,
- .ndo_set_multicast_list = __ei_set_multicast_list,
+ .ndo_set_rx_mode = __ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
new file mode 100644
index 000000000000..6dff5a0e733f
--- /dev/null
+++ b/drivers/net/ethernet/Kconfig
@@ -0,0 +1,177 @@
+#
+# Ethernet LAN device configuration
+#
+
+menuconfig ETHERNET
+ bool "Ethernet driver support"
+ depends on NET
+ default y
+ ---help---
+ This section contains all the Ethernet device drivers.
+
+if ETHERNET
+
+config MDIO
+ tristate
+
+config SUNGEM_PHY
+ tristate
+
+source "drivers/net/ethernet/3com/Kconfig"
+source "drivers/net/ethernet/adaptec/Kconfig"
+source "drivers/net/ethernet/aeroflex/Kconfig"
+source "drivers/net/ethernet/alteon/Kconfig"
+source "drivers/net/ethernet/amd/Kconfig"
+source "drivers/net/ethernet/apple/Kconfig"
+source "drivers/net/ethernet/atheros/Kconfig"
+source "drivers/net/ethernet/cadence/Kconfig"
+source "drivers/net/ethernet/adi/Kconfig"
+source "drivers/net/ethernet/broadcom/Kconfig"
+source "drivers/net/ethernet/brocade/Kconfig"
+source "drivers/net/ethernet/chelsio/Kconfig"
+source "drivers/net/ethernet/cirrus/Kconfig"
+source "drivers/net/ethernet/cisco/Kconfig"
+source "drivers/net/ethernet/davicom/Kconfig"
+
+config DNET
+ tristate "Dave ethernet support (DNET)"
+ depends on HAS_IOMEM
+ select PHYLIB
+ ---help---
+ The Dave ethernet interface (DNET) is found on Qong Board FPGA.
+ Say Y to include support for the DNET chip.
+
+ To compile this driver as a module, choose M here: the module
+ will be called dnet.
+
+source "drivers/net/ethernet/dec/Kconfig"
+source "drivers/net/ethernet/dlink/Kconfig"
+source "drivers/net/ethernet/emulex/Kconfig"
+source "drivers/net/ethernet/neterion/Kconfig"
+source "drivers/net/ethernet/faraday/Kconfig"
+source "drivers/net/ethernet/freescale/Kconfig"
+source "drivers/net/ethernet/fujitsu/Kconfig"
+source "drivers/net/ethernet/hp/Kconfig"
+source "drivers/net/ethernet/ibm/Kconfig"
+source "drivers/net/ethernet/intel/Kconfig"
+source "drivers/net/ethernet/i825xx/Kconfig"
+source "drivers/net/ethernet/xscale/Kconfig"
+source "drivers/net/ethernet/icplus/Kconfig"
+
+config JME
+ tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This driver supports the PCI-Express gigabit ethernet adapters
+ based on JMicron JMC250 chipset.
+
+ To compile this driver as a module, choose M here. The module
+ will be called jme.
+
+config KORINA
+ tristate "Korina (IDT RC32434) Ethernet support"
+ depends on MIKROTIK_RB532
+ ---help---
+ If you have a Mikrotik RouterBoard 500 or IDT RC32434
+ based system say Y. Otherwise say N.
+
+config LANTIQ_ETOP
+ tristate "Lantiq SoC ETOP driver"
+ depends on SOC_TYPE_XWAY
+ ---help---
+ Support for the MII0 inside the Lantiq SoC
+
+source "drivers/net/ethernet/marvell/Kconfig"
+source "drivers/net/ethernet/mellanox/Kconfig"
+source "drivers/net/ethernet/micrel/Kconfig"
+source "drivers/net/ethernet/microchip/Kconfig"
+
+config MIPS_SIM_NET
+ tristate "MIPS simulator Network device"
+ depends on MIPS_SIM
+ ---help---
+ The MIPSNET device is a simple Ethernet network device which is
+ emulated by the MIPS Simulator.
+ If you are not using a MIPSsim or are unsure, say N.
+
+source "drivers/net/ethernet/myricom/Kconfig"
+
+config FEALNX
+ tristate "Myson MTD-8xx PCI Ethernet support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ Say Y here to support the Myson MTD-800 family of PCI-based Ethernet
+ cards. <http://www.myson.com.tw/>
+
+source "drivers/net/ethernet/natsemi/Kconfig"
+source "drivers/net/ethernet/8390/Kconfig"
+
+config NET_NETX
+ tristate "NetX Ethernet support"
+ select NET_CORE
+ select MII
+ depends on ARCH_NETX
+ ---help---
+ This is support for the Hilscher netX builtin Ethernet ports
+
+ To compile this driver as a module, choose M here. The module
+ will be called netx-eth.
+
+source "drivers/net/ethernet/nuvoton/Kconfig"
+source "drivers/net/ethernet/nvidia/Kconfig"
+source "drivers/net/ethernet/octeon/Kconfig"
+source "drivers/net/ethernet/oki-semi/Kconfig"
+
+config ETHOC
+ tristate "OpenCores 10/100 Mbps Ethernet MAC support"
+ depends on HAS_IOMEM && HAS_DMA
+ select NET_CORE
+ select MII
+ select PHYLIB
+ select CRC32
+ select BITREVERSE
+ ---help---
+ Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC.
+
+source "drivers/net/ethernet/packetengines/Kconfig"
+source "drivers/net/ethernet/pasemi/Kconfig"
+source "drivers/net/ethernet/qlogic/Kconfig"
+source "drivers/net/ethernet/racal/Kconfig"
+source "drivers/net/ethernet/realtek/Kconfig"
+source "drivers/net/ethernet/renesas/Kconfig"
+source "drivers/net/ethernet/rdc/Kconfig"
+
+config S6GMAC
+ tristate "S6105 GMAC ethernet support"
+ depends on XTENSA_VARIANT_S6000
+ select PHYLIB
+ ---help---
+ This driver supports the on chip ethernet device on the
+ S6105 xtensa processor.
+
+ To compile this driver as a module, choose M here. The module
+ will be called s6gmac.
+
+source "drivers/net/ethernet/seeq/Kconfig"
+source "drivers/net/ethernet/sis/Kconfig"
+source "drivers/net/ethernet/sfc/Kconfig"
+source "drivers/net/ethernet/sgi/Kconfig"
+source "drivers/net/ethernet/smsc/Kconfig"
+source "drivers/net/ethernet/stmicro/Kconfig"
+source "drivers/net/ethernet/sun/Kconfig"
+source "drivers/net/ethernet/tehuti/Kconfig"
+source "drivers/net/ethernet/ti/Kconfig"
+source "drivers/net/ethernet/tile/Kconfig"
+source "drivers/net/ethernet/toshiba/Kconfig"
+source "drivers/net/ethernet/tundra/Kconfig"
+source "drivers/net/ethernet/via/Kconfig"
+source "drivers/net/ethernet/xilinx/Kconfig"
+source "drivers/net/ethernet/xircom/Kconfig"
+
+endif # ETHERNET
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
new file mode 100644
index 000000000000..c53ad3afc991
--- /dev/null
+++ b/drivers/net/ethernet/Makefile
@@ -0,0 +1,74 @@
+#
+# Makefile for the Linux network Ethernet device drivers.
+#
+
+obj-$(CONFIG_NET_VENDOR_3COM) += 3com/
+obj-$(CONFIG_NET_VENDOR_8390) += 8390/
+obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
+obj-$(CONFIG_GRETH) += aeroflex/
+obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
+obj-$(CONFIG_NET_VENDOR_AMD) += amd/
+obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
+obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
+obj-$(CONFIG_NET_ATMEL) += cadence/
+obj-$(CONFIG_NET_BFIN) += adi/
+obj-$(CONFIG_NET_VENDOR_BROADCOM) += broadcom/
+obj-$(CONFIG_NET_VENDOR_BROCADE) += brocade/
+obj-$(CONFIG_NET_VENDOR_CHELSIO) += chelsio/
+obj-$(CONFIG_NET_VENDOR_CIRRUS) += cirrus/
+obj-$(CONFIG_NET_VENDOR_CISCO) += cisco/
+obj-$(CONFIG_DM9000) += davicom/
+obj-$(CONFIG_DNET) += dnet.o
+obj-$(CONFIG_NET_VENDOR_DEC) += dec/
+obj-$(CONFIG_NET_VENDOR_DLINK) += dlink/
+obj-$(CONFIG_NET_VENDOR_EMULEX) += emulex/
+obj-$(CONFIG_NET_VENDOR_EXAR) += neterion/
+obj-$(CONFIG_NET_VENDOR_FARADAY) += faraday/
+obj-$(CONFIG_NET_VENDOR_FREESCALE) += freescale/
+obj-$(CONFIG_NET_VENDOR_FUJITSU) += fujitsu/
+obj-$(CONFIG_NET_VENDOR_HP) += hp/
+obj-$(CONFIG_NET_VENDOR_IBM) += ibm/
+obj-$(CONFIG_NET_VENDOR_INTEL) += intel/
+obj-$(CONFIG_NET_VENDOR_I825XX) += i825xx/
+obj-$(CONFIG_NET_VENDOR_XSCALE) += xscale/
+obj-$(CONFIG_IP1000) += icplus/
+obj-$(CONFIG_JME) += jme.o
+obj-$(CONFIG_KORINA) += korina.o
+obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
+obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/
+obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/
+obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/
+obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/
+obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
+obj-$(CONFIG_NET_VENDOR_MYRI) += myricom/
+obj-$(CONFIG_FEALNX) += fealnx.o
+obj-$(CONFIG_NET_VENDOR_NATSEMI) += natsemi/
+obj-$(CONFIG_NET_NETX) += netx-eth.o
+obj-$(CONFIG_NET_VENDOR_NUVOTON) += nuvoton/
+obj-$(CONFIG_NET_VENDOR_NVIDIA) += nvidia/
+obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
+obj-$(CONFIG_NET_VENDOR_OKI) += oki-semi/
+obj-$(CONFIG_ETHOC) += ethoc.o
+obj-$(CONFIG_NET_PACKET_ENGINE) += packetengines/
+obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/
+obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
+obj-$(CONFIG_NET_VENDOR_RACAL) += racal/
+obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
+obj-$(CONFIG_SH_ETH) += renesas/
+obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
+obj-$(CONFIG_S6GMAC) += s6gmac.o
+obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/
+obj-$(CONFIG_NET_VENDOR_SIS) += sis/
+obj-$(CONFIG_SFC) += sfc/
+obj-$(CONFIG_NET_VENDOR_SGI) += sgi/
+obj-$(CONFIG_NET_VENDOR_SMSC) += smsc/
+obj-$(CONFIG_NET_VENDOR_STMICRO) += stmicro/
+obj-$(CONFIG_NET_VENDOR_SUN) += sun/
+obj-$(CONFIG_NET_VENDOR_TEHUTI) += tehuti/
+obj-$(CONFIG_NET_VENDOR_TI) += ti/
+obj-$(CONFIG_TILE_NET) += tile/
+obj-$(CONFIG_NET_VENDOR_TOSHIBA) += toshiba/
+obj-$(CONFIG_NET_VENDOR_TUNDRA) += tundra/
+obj-$(CONFIG_NET_VENDOR_VIA) += via/
+obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
+obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
diff --git a/drivers/net/ethernet/adaptec/Kconfig b/drivers/net/ethernet/adaptec/Kconfig
new file mode 100644
index 000000000000..0bff571b1bb3
--- /dev/null
+++ b/drivers/net/ethernet/adaptec/Kconfig
@@ -0,0 +1,36 @@
+#
+# Adaptec network device configuration
+#
+
+config NET_VENDOR_ADAPTEC
+ bool "Adaptec devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Adaptec cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_ADAPTEC
+
+config ADAPTEC_STARFIRE
+ tristate "Adaptec Starfire/DuraLAN support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network
+ adapter. The DuraLAN chip is used on the 64 bit PCI boards from
+ Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip
+ driver.
+
+ To compile this driver as a module, choose M here: the module
+ will be called starfire. This is recommended.
+
+endif # NET_VENDOR_ADAPTEC
diff --git a/drivers/net/ethernet/adaptec/Makefile b/drivers/net/ethernet/adaptec/Makefile
new file mode 100644
index 000000000000..6c07b758ac0a
--- /dev/null
+++ b/drivers/net/ethernet/adaptec/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Adaptec network device drivers.
+#
+
+obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
diff --git a/drivers/net/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index 7ae1f990a98e..6d9f6911000f 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -639,7 +639,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_start_xmit = start_tx,
.ndo_tx_timeout = tx_timeout,
.ndo_get_stats = get_stats,
- .ndo_set_multicast_list = &set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = netdev_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
@@ -1256,10 +1256,13 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
np->tx_info[entry].mapping =
pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
} else {
- skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1];
- status |= this_frag->size;
+ const skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1];
+ status |= skb_frag_size(this_frag);
np->tx_info[entry].mapping =
- pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE);
+ pci_map_single(np->pci_dev,
+ skb_frag_address(this_frag),
+ skb_frag_size(this_frag),
+ PCI_DMA_TODEVICE);
}
np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
@@ -1375,7 +1378,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
pci_unmap_single(np->pci_dev,
np->tx_info[entry].mapping,
- skb_shinfo(skb)->frags[i].size,
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
PCI_DMA_TODEVICE);
np->dirty_tx++;
entry++;
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig
new file mode 100644
index 000000000000..49a30d37ae4a
--- /dev/null
+++ b/drivers/net/ethernet/adi/Kconfig
@@ -0,0 +1,69 @@
+#
+# Blackfin device configuration
+#
+
+config NET_BFIN
+ bool "Blackfin devices"
+ depends on BF516 || BF518 || BF526 || BF527 || BF536 || BF537
+ ---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,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ If unsure, say Y.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the remaining Blackfin card questions. If you say Y, you will be
+ asked for your specific card in the following questions.
+
+if NET_BFIN
+
+config BFIN_MAC
+ tristate "Blackfin on-chip MAC support"
+ depends on (BF516 || BF518 || BF526 || BF527 || BF536 || BF537)
+ select CRC32
+ select NET_CORE
+ select MII
+ select PHYLIB
+ select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE
+ ---help---
+ This is the driver for Blackfin on-chip mac device. Say Y if you want
+ it compiled into the kernel. This driver is also available as a
+ module ( = code which can be inserted in and removed from the running
+ kernel whenever you want). The module will be called bfin_mac.
+
+config BFIN_MAC_USE_L1
+ bool "Use L1 memory for rx/tx packets"
+ depends on BFIN_MAC && (BF527 || BF537)
+ default y
+ ---help---
+ To get maximum network performance, you should use L1 memory as rx/tx
+ buffers. Say N here if you want to reserve L1 memory for other uses.
+
+config BFIN_TX_DESC_NUM
+ int "Number of transmit buffer packets"
+ depends on BFIN_MAC
+ range 6 10 if BFIN_MAC_USE_L1
+ range 10 100
+ default "10"
+ ---help---
+ Set the number of buffer packets used in driver.
+
+config BFIN_RX_DESC_NUM
+ int "Number of receive buffer packets"
+ depends on BFIN_MAC
+ range 20 100 if BFIN_MAC_USE_L1
+ range 20 800
+ default "20"
+ ---help---
+ Set the number of buffer packets used in driver.
+
+config BFIN_MAC_USE_HWSTAMP
+ bool "Use IEEE 1588 hwstamp"
+ depends on BFIN_MAC && BF518
+ default y
+ ---help---
+ To support the IEEE 1588 Precision Time Protocol (PTP), select y here
+
+endif # NET_BFIN
diff --git a/drivers/net/ethernet/adi/Makefile b/drivers/net/ethernet/adi/Makefile
new file mode 100644
index 000000000000..b1fbe195d0e8
--- /dev/null
+++ b/drivers/net/ethernet/adi/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Blackfin device drivers.
+#
+
+obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
diff --git a/drivers/net/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index 6c019e148546..b6d69c91db96 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -1449,7 +1449,7 @@ static const struct net_device_ops bfin_mac_netdev_ops = {
.ndo_start_xmit = bfin_mac_hard_start_xmit,
.ndo_set_mac_address = bfin_mac_set_mac_address,
.ndo_tx_timeout = bfin_mac_timeout,
- .ndo_set_multicast_list = bfin_mac_set_multicast_list,
+ .ndo_set_rx_mode = bfin_mac_set_multicast_list,
.ndo_do_ioctl = bfin_mac_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/bfin_mac.h b/drivers/net/ethernet/adi/bfin_mac.h
index f8559ac9a403..f8559ac9a403 100644
--- a/drivers/net/bfin_mac.h
+++ b/drivers/net/ethernet/adi/bfin_mac.h
diff --git a/drivers/net/ethernet/aeroflex/Kconfig b/drivers/net/ethernet/aeroflex/Kconfig
new file mode 100644
index 000000000000..4f4a8d78fd54
--- /dev/null
+++ b/drivers/net/ethernet/aeroflex/Kconfig
@@ -0,0 +1,11 @@
+#
+# Aeroflex Gaisler network device configuration
+#
+
+config GRETH
+ tristate "Aeroflex Gaisler GRETH Ethernet MAC support"
+ depends on SPARC
+ select PHYLIB
+ select CRC32
+ ---help---
+ Say Y here if you want to use the Aeroflex Gaisler GRETH Ethernet MAC.
diff --git a/drivers/net/ethernet/aeroflex/Makefile b/drivers/net/ethernet/aeroflex/Makefile
new file mode 100644
index 000000000000..6e62a679282f
--- /dev/null
+++ b/drivers/net/ethernet/aeroflex/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Aeroflex Gaisler network device drivers.
+#
+
+obj-$(CONFIG_GRETH) += greth.o
diff --git a/drivers/net/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 52a39000c42c..442fefa4f2ca 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -113,9 +113,8 @@ static void greth_print_tx_packet(struct sk_buff *skb)
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
print_hex_dump(KERN_DEBUG, "TX: ", DUMP_PREFIX_OFFSET, 16, 1,
- phys_to_virt(page_to_phys(skb_shinfo(skb)->frags[i].page)) +
- skb_shinfo(skb)->frags[i].page_offset,
- length, true);
+ skb_frag_address(&skb_shinfo(skb)->frags[i]),
+ skb_shinfo(skb)->frags[i].size, true);
}
}
@@ -199,7 +198,7 @@ static void greth_clean_rings(struct greth_private *greth)
dma_unmap_page(greth->dev,
greth_read_bd(&tx_bdp->addr),
- frag->size,
+ skb_frag_size(frag),
DMA_TO_DEVICE);
greth->tx_last = NEXT_TX(greth->tx_last);
@@ -518,7 +517,7 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
status = GRETH_BD_EN;
if (skb->ip_summed == CHECKSUM_PARTIAL)
status |= GRETH_TXBD_CSALL;
- status |= frag->size & GRETH_BD_LEN;
+ status |= skb_frag_size(frag) & GRETH_BD_LEN;
/* Wrap around descriptor ring */
if (curr_tx == GRETH_TXBD_NUM_MASK)
@@ -532,11 +531,8 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
greth_write_bd(&bdp->stat, status);
- dma_addr = dma_map_page(greth->dev,
- frag->page,
- frag->page_offset,
- frag->size,
- DMA_TO_DEVICE);
+ dma_addr = skb_frag_dma_map(greth->dev, frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(greth->dev, dma_addr)))
goto frag_map_error;
@@ -717,7 +713,7 @@ static void greth_clean_tx_gbit(struct net_device *dev)
dma_unmap_page(greth->dev,
greth_read_bd(&bdp->addr),
- frag->size,
+ skb_frag_size(frag),
DMA_TO_DEVICE);
greth->tx_last = NEXT_TX(greth->tx_last);
@@ -1547,7 +1543,7 @@ static int __devinit greth_of_probe(struct platform_device *ofdev)
}
if (greth->multicast) {
- greth_netdev_ops.ndo_set_multicast_list = greth_set_multicast_list;
+ greth_netdev_ops.ndo_set_rx_mode = greth_set_multicast_list;
dev->flags |= IFF_MULTICAST;
} else {
dev->flags &= ~IFF_MULTICAST;
diff --git a/drivers/net/greth.h b/drivers/net/ethernet/aeroflex/greth.h
index 232a622a85b7..232a622a85b7 100644
--- a/drivers/net/greth.h
+++ b/drivers/net/ethernet/aeroflex/greth.h
diff --git a/drivers/net/ethernet/alteon/Kconfig b/drivers/net/ethernet/alteon/Kconfig
new file mode 100644
index 000000000000..799a85282070
--- /dev/null
+++ b/drivers/net/ethernet/alteon/Kconfig
@@ -0,0 +1,48 @@
+#
+# Alteon network device configuration
+#
+
+config NET_VENDOR_ALTEON
+ bool "Alteon devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Alteon cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_ALTEON
+
+config ACENIC
+ tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
+ depends on PCI
+ ---help---
+ Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear
+ GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet
+ adapter. The driver allows for using the Jumbo Frame option (9000
+ bytes/frame) however it requires that your switches can handle this
+ as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig
+ line.
+
+ To compile this driver as a module, choose M here: the
+ module will be called acenic.
+
+config ACENIC_OMIT_TIGON_I
+ bool "Omit support for old Tigon I based AceNICs"
+ depends on ACENIC
+ ---help---
+ Say Y here if you only have Tigon II based AceNICs and want to leave
+ out support for the older Tigon I based cards which are no longer
+ being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B
+ version)). This will reduce the size of the driver object by
+ app. 100KB. If you are not sure whether your card is a Tigon I or a
+ Tigon II, say N here.
+
+ The safe and default value for this is N.
+
+endif # NET_VENDOR_ALTEON
diff --git a/drivers/net/ethernet/alteon/Makefile b/drivers/net/ethernet/alteon/Makefile
new file mode 100644
index 000000000000..a2ca173f2a50
--- /dev/null
+++ b/drivers/net/ethernet/alteon/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Alteon network device drivers.
+#
+
+obj-$(CONFIG_ACENIC) += acenic.o
diff --git a/drivers/net/acenic.c b/drivers/net/ethernet/alteon/acenic.c
index 31798f5f5d06..f872748ab4e6 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/ethernet/alteon/acenic.c
@@ -449,7 +449,7 @@ static const struct net_device_ops ace_netdev_ops = {
.ndo_tx_timeout = ace_watchdog,
.ndo_get_stats = ace_get_stats,
.ndo_start_xmit = ace_start_xmit,
- .ndo_set_multicast_list = ace_set_multicast_list,
+ .ndo_set_rx_mode = ace_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ace_set_mac_addr,
.ndo_change_mtu = ace_change_mtu,
@@ -2478,18 +2478,18 @@ restart:
idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
struct tx_ring_info *info;
- len += frag->size;
+ len += skb_frag_size(frag);
info = ap->skb->tx_skbuff + idx;
desc = ap->tx_ring + idx;
- mapping = pci_map_page(ap->pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
+ mapping = skb_frag_dma_map(&ap->pdev->dev, frag, 0,
+ skb_frag_size(frag),
+ DMA_TO_DEVICE);
- flagsize = (frag->size << 16);
+ flagsize = skb_frag_size(frag) << 16;
if (skb->ip_summed == CHECKSUM_PARTIAL)
flagsize |= BD_FLG_TCP_UDP_SUM;
idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
@@ -2508,7 +2508,7 @@ restart:
info->skb = NULL;
}
dma_unmap_addr_set(info, mapping, mapping);
- dma_unmap_len_set(info, maplen, frag->size);
+ dma_unmap_len_set(info, maplen, skb_frag_size(frag));
ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
}
}
diff --git a/drivers/net/acenic.h b/drivers/net/ethernet/alteon/acenic.h
index 51c486cfbb8c..51c486cfbb8c 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/ethernet/alteon/acenic.h
diff --git a/drivers/net/7990.c b/drivers/net/ethernet/amd/7990.c
index 60b35fb5f524..60b35fb5f524 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/ethernet/amd/7990.c
diff --git a/drivers/net/7990.h b/drivers/net/ethernet/amd/7990.h
index 0a5837b96421..0a5837b96421 100644
--- a/drivers/net/7990.h
+++ b/drivers/net/ethernet/amd/7990.h
diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
new file mode 100644
index 000000000000..238b537b68fe
--- /dev/null
+++ b/drivers/net/ethernet/amd/Kconfig
@@ -0,0 +1,195 @@
+#
+# AMD network device configuration
+#
+
+config NET_VENDOR_AMD
+ bool "AMD devices"
+ default y
+ depends on DIO || MACH_DECSTATION || MVME147 || ATARI || SUN3 || \
+ SUN3X || SBUS || PCI || ZORRO || (ISA && ISA_DMA_API) || \
+ (ARM && ARCH_EBSA110) || ISA || EISA || MCA || PCMCIA
+ ---help---
+ If you have a network (Ethernet) chipset belonging to this class,
+ say Y.
+
+ Note that the answer to this question does not directly affect
+ the kernel: saying N will just case the configurator to skip all
+ the questions regarding AMD chipsets. If you say Y, you will be asked
+ for your specific chipset/driver in the following questions.
+
+if NET_VENDOR_AMD
+
+config A2065
+ tristate "A2065 support"
+ depends on ZORRO
+ select CRC32
+ ---help---
+ If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
+ say N.
+
+ To compile this driver as a module, choose M here: the module
+ will be called a2065.
+
+config AMD8111_ETH
+ tristate "AMD 8111 (new PCI LANCE) support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ If you have an AMD 8111-based PCI LANCE ethernet card,
+ answer Y here and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called amd8111e.
+
+config LANCE
+ tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
+ depends on ISA && ISA_DMA_API
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Some LinkSys cards are
+ of this type.
+
+ To compile this driver as a module, choose M here: the module
+ will be called lance. This is recommended.
+
+config PCNET32
+ tristate "AMD PCnet32 PCI support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ If you have a PCnet32 or PCnetPCI based network (Ethernet) card,
+ answer Y here and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called pcnet32.
+
+config ARIADNE
+ tristate "Ariadne support"
+ depends on ZORRO
+ ---help---
+ If you have a Village Tronic Ariadne Ethernet adapter, say Y.
+ Otherwise, say N.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ariadne.
+
+config ARM_AM79C961A
+ bool "ARM EBSA110 AM79C961A support"
+ depends on ARM && ARCH_EBSA110
+ select CRC32
+ ---help---
+ If you wish to compile a kernel for the EBSA-110, then you should
+ always answer Y to this.
+
+config ATARILANCE
+ tristate "Atari LANCE support"
+ depends on ATARI
+ ---help---
+ Say Y to include support for several Atari Ethernet adapters based
+ on the AMD LANCE chipset: RieblCard (with or without battery), or
+ PAMCard VME (also the version by Rhotron, with different addresses).
+
+config DECLANCE
+ tristate "DEC LANCE ethernet controller support"
+ depends on MACH_DECSTATION
+ select CRC32
+ ---help---
+ This driver is for the series of Ethernet controllers produced by
+ DEC (now Compaq) based on the AMD LANCE chipset, including the
+ DEPCA series. (This chipset is better known via the NE2100 cards.)
+
+config DEPCA
+ tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
+ depends on (ISA || EISA || MCA)
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto> as well as
+ <file:drivers/net/depca.c>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called depca.
+
+config HPLANCE
+ bool "HP on-board LANCE support"
+ depends on DIO
+ select CRC32
+ ---help---
+ If you want to use the builtin "LANCE" Ethernet controller on an
+ HP300 machine, say Y here.
+
+config MIPS_AU1X00_ENET
+ tristate "MIPS AU1000 Ethernet support"
+ depends on MIPS_ALCHEMY
+ select PHYLIB
+ select CRC32
+ ---help---
+ If you have an Alchemy Semi AU1X00 based system
+ say Y. Otherwise, say N.
+
+config MVME147_NET
+ tristate "MVME147 (LANCE) Ethernet support"
+ depends on MVME147
+ select CRC32
+ ---help---
+ Support for the on-board Ethernet interface on the Motorola MVME147
+ single-board computer. Say Y here to include the
+ driver for this chip in your kernel.
+ To compile this driver as a module, choose M here.
+
+config PCMCIA_NMCLAN
+ tristate "New Media PCMCIA support"
+ depends on PCMCIA
+ help
+ Say Y here if you intend to attach a New Media Ethernet or LiveWire
+ PCMCIA (PC-card) Ethernet card to your computer.
+
+ To compile this driver as a module, choose M here: the module will be
+ called nmclan_cs. If unsure, say N.
+
+config NI65
+ tristate "NI6510 support"
+ depends on ISA && ISA_DMA_API
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ni65.
+
+config SUN3LANCE
+ tristate "Sun3/Sun3x on-board LANCE support"
+ depends on (SUN3 || SUN3X)
+ ---help---
+ Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
+ featured an AMD LANCE 10Mbit Ethernet controller on board; say Y
+ here to compile in the Linux driver for this and enable Ethernet.
+ General Linux information on the Sun 3 and 3x series (now
+ discontinued) is at
+ <http://www.angelfire.com/ca2/tech68k/sun3.html>.
+
+ If you're not building a kernel for a Sun 3, say N.
+
+config SUNLANCE
+ tristate "Sun LANCE support"
+ depends on SBUS
+ select CRC32
+ ---help---
+ This driver supports the "le" interface present on all 32-bit Sparc
+ systems, on some older Ultra systems and as an Sbus option. These
+ cards are based on the AMD LANCE chipset, which is better known
+ via the NE2100 cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sunlance.
+
+endif # NET_VENDOR_AMD
diff --git a/drivers/net/ethernet/amd/Makefile b/drivers/net/ethernet/amd/Makefile
new file mode 100644
index 000000000000..175caa5328c9
--- /dev/null
+++ b/drivers/net/ethernet/amd/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for the AMD network device drivers.
+#
+
+obj-$(CONFIG_A2065) += a2065.o
+obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
+obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
+obj-$(CONFIG_ARIADNE) += ariadne.o
+obj-$(CONFIG_ATARILANCE) += atarilance.o
+obj-$(CONFIG_DECLANCE) += declance.o
+obj-$(CONFIG_DEPCA) += depca.o
+obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
+obj-$(CONFIG_LANCE) += lance.o
+obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
+obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
+obj-$(CONFIG_PCMCIA_NMCLAN) += nmclan_cs.o
+obj-$(CONFIG_NI65) += ni65.o
+obj-$(CONFIG_PCNET32) += pcnet32.o
+obj-$(CONFIG_SUN3LANCE) += sun3lance.o
+obj-$(CONFIG_SUNLANCE) += sunlance.o
diff --git a/drivers/net/a2065.c b/drivers/net/ethernet/amd/a2065.c
index e1e1b07d9b8d..825e5d4ef4c3 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/ethernet/amd/a2065.c
@@ -664,7 +664,7 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_stop = lance_close,
.ndo_start_xmit = lance_start_xmit,
.ndo_tx_timeout = lance_tx_timeout,
- .ndo_set_multicast_list = lance_set_multicast,
+ .ndo_set_rx_mode = lance_set_multicast,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/a2065.h b/drivers/net/ethernet/amd/a2065.h
index 5117759d4e9c..5117759d4e9c 100644
--- a/drivers/net/a2065.h
+++ b/drivers/net/ethernet/amd/a2065.h
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c
index 3b1416e3d217..7d5ded80d2d7 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/ethernet/amd/am79c961a.c
@@ -662,7 +662,7 @@ static const struct net_device_ops am79c961_netdev_ops = {
.ndo_open = am79c961_open,
.ndo_stop = am79c961_close,
.ndo_start_xmit = am79c961_sendpacket,
- .ndo_set_multicast_list = am79c961_setmulticastlist,
+ .ndo_set_rx_mode = am79c961_setmulticastlist,
.ndo_tx_timeout = am79c961_timeout,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/arm/am79c961a.h b/drivers/net/ethernet/amd/am79c961a.h
index fd634d32756b..fd634d32756b 100644
--- a/drivers/net/arm/am79c961a.h
+++ b/drivers/net/ethernet/amd/am79c961a.h
diff --git a/drivers/net/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
index 78002ef9c0e5..a9745f4ddbfe 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/ethernet/amd/amd8111e.c
@@ -1798,7 +1798,7 @@ static const struct net_device_ops amd8111e_netdev_ops = {
.ndo_start_xmit = amd8111e_start_xmit,
.ndo_tx_timeout = amd8111e_tx_timeout,
.ndo_get_stats = amd8111e_get_stats,
- .ndo_set_multicast_list = amd8111e_set_multicast_list,
+ .ndo_set_rx_mode = amd8111e_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = amd8111e_set_mac_address,
.ndo_do_ioctl = amd8111e_ioctl,
diff --git a/drivers/net/amd8111e.h b/drivers/net/ethernet/amd/amd8111e.h
index 2ff2e7a12dd0..2ff2e7a12dd0 100644
--- a/drivers/net/amd8111e.h
+++ b/drivers/net/ethernet/amd/amd8111e.h
diff --git a/drivers/net/ariadne.c b/drivers/net/ethernet/amd/ariadne.c
index 7ed78f402042..eb18e1fe65c8 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ethernet/amd/ariadne.c
@@ -704,7 +704,7 @@ static const struct net_device_ops ariadne_netdev_ops = {
.ndo_start_xmit = ariadne_start_xmit,
.ndo_tx_timeout = ariadne_tx_timeout,
.ndo_get_stats = ariadne_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ariadne.h b/drivers/net/ethernet/amd/ariadne.h
index 727be5cdd1ea..727be5cdd1ea 100644
--- a/drivers/net/ariadne.h
+++ b/drivers/net/ethernet/amd/ariadne.h
diff --git a/drivers/net/atarilance.c b/drivers/net/ethernet/amd/atarilance.c
index 1264d781b554..15bfa28d6c53 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/ethernet/amd/atarilance.c
@@ -456,7 +456,7 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_open = lance_open,
.ndo_stop = lance_close,
.ndo_start_xmit = lance_start_xmit,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_set_mac_address = lance_set_mac_address,
.ndo_tx_timeout = lance_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index b9debcfb61a0..82386677bb8c 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -1010,7 +1010,7 @@ static const struct net_device_ops au1000_netdev_ops = {
.ndo_open = au1000_open,
.ndo_stop = au1000_close,
.ndo_start_xmit = au1000_tx,
- .ndo_set_multicast_list = au1000_multicast_list,
+ .ndo_set_rx_mode = au1000_multicast_list,
.ndo_do_ioctl = au1000_ioctl,
.ndo_tx_timeout = au1000_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/au1000_eth.h b/drivers/net/ethernet/amd/au1000_eth.h
index 6229c774552c..6229c774552c 100644
--- a/drivers/net/au1000_eth.h
+++ b/drivers/net/ethernet/amd/au1000_eth.h
diff --git a/drivers/net/declance.c b/drivers/net/ethernet/amd/declance.c
index d5598f6584a3..73f8d4fa682d 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/ethernet/amd/declance.c
@@ -1015,7 +1015,7 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_stop = lance_close,
.ndo_start_xmit = lance_start_xmit,
.ndo_tx_timeout = lance_tx_timeout,
- .ndo_set_multicast_list = lance_set_multicast,
+ .ndo_set_rx_mode = lance_set_multicast,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/depca.c b/drivers/net/ethernet/amd/depca.c
index f2015a851977..681970c07f22 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/ethernet/amd/depca.c
@@ -572,7 +572,7 @@ static const struct net_device_ops depca_netdev_ops = {
.ndo_open = depca_open,
.ndo_start_xmit = depca_start_xmit,
.ndo_stop = depca_close,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_do_ioctl = depca_ioctl,
.ndo_tx_timeout = depca_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/depca.h b/drivers/net/ethernet/amd/depca.h
index ee42648dbde6..cdcfe4252c16 100644
--- a/drivers/net/depca.h
+++ b/drivers/net/ethernet/amd/depca.h
@@ -157,8 +157,6 @@
*/
#include <linux/sockios.h>
-#define DEPCAIOCTL SIOCDEVPRIVATE
-
struct depca_ioctl {
unsigned short cmd; /* Command to run */
unsigned short len; /* Length of the data buffer */
diff --git a/drivers/net/hplance.c b/drivers/net/ethernet/amd/hplance.c
index a900d5bf2948..86aa0d546a5b 100644
--- a/drivers/net/hplance.c
+++ b/drivers/net/ethernet/amd/hplance.c
@@ -74,7 +74,7 @@ static const struct net_device_ops hplance_netdev_ops = {
.ndo_open = hplance_open,
.ndo_stop = hplance_close,
.ndo_start_xmit = lance_start_xmit,
- .ndo_set_multicast_list = lance_set_multicast,
+ .ndo_set_rx_mode = lance_set_multicast,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/hplance.h b/drivers/net/ethernet/amd/hplance.h
index 04aee9e0376a..04aee9e0376a 100644
--- a/drivers/net/hplance.h
+++ b/drivers/net/ethernet/amd/hplance.h
diff --git a/drivers/net/lance.c b/drivers/net/ethernet/amd/lance.c
index 02336edce748..a6e2e840884e 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/ethernet/amd/lance.c
@@ -459,7 +459,7 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_start_xmit = lance_start_xmit,
.ndo_stop = lance_close,
.ndo_get_stats = lance_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = lance_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/mvme147.c b/drivers/net/ethernet/amd/mvme147.c
index 3a7ad840d5b5..56bc47a94186 100644
--- a/drivers/net/mvme147.c
+++ b/drivers/net/ethernet/amd/mvme147.c
@@ -61,7 +61,7 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_open = m147lance_open,
.ndo_stop = m147lance_close,
.ndo_start_xmit = lance_start_xmit,
- .ndo_set_multicast_list = lance_set_multicast,
+ .ndo_set_rx_mode = lance_set_multicast,
.ndo_tx_timeout = lance_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/ni65.c b/drivers/net/ethernet/amd/ni65.c
index c75ae85eb918..6e6aa7213aab 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ethernet/amd/ni65.c
@@ -406,7 +406,7 @@ static const struct net_device_ops ni65_netdev_ops = {
.ndo_stop = ni65_close,
.ndo_start_xmit = ni65_send_packet,
.ndo_tx_timeout = ni65_timeout,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/ni65.h b/drivers/net/ethernet/amd/ni65.h
index e6217e35edf0..e6217e35edf0 100644
--- a/drivers/net/ni65.h
+++ b/drivers/net/ethernet/amd/ni65.h
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c
index 9d70b6595220..3accd5d21b08 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/ethernet/amd/nmclan_cs.c
@@ -430,7 +430,7 @@ static const struct net_device_ops mace_netdev_ops = {
.ndo_tx_timeout = mace_tx_timeout,
.ndo_set_config = mace_config,
.ndo_get_stats = mace_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
index 80b6f36a8074..f92bc6e34828 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -270,7 +270,7 @@ struct pcnet32_private {
struct sk_buff **rx_skbuff;
dma_addr_t *tx_dma_addr;
dma_addr_t *rx_dma_addr;
- struct pcnet32_access a;
+ const struct pcnet32_access *a;
spinlock_t lock; /* Guard lock */
unsigned int cur_rx, cur_tx; /* The next free ring entry */
unsigned int rx_ring_size; /* current rx ring size */
@@ -379,7 +379,7 @@ static int pcnet32_wio_check(unsigned long addr)
return inw(addr + PCNET32_WIO_RAP) == 88;
}
-static struct pcnet32_access pcnet32_wio = {
+static const struct pcnet32_access pcnet32_wio = {
.read_csr = pcnet32_wio_read_csr,
.write_csr = pcnet32_wio_write_csr,
.read_bcr = pcnet32_wio_read_bcr,
@@ -434,7 +434,7 @@ static int pcnet32_dwio_check(unsigned long addr)
return (inl(addr + PCNET32_DWIO_RAP) & 0xffff) == 88;
}
-static struct pcnet32_access pcnet32_dwio = {
+static const struct pcnet32_access pcnet32_dwio = {
.read_csr = pcnet32_dwio_read_csr,
.write_csr = pcnet32_dwio_write_csr,
.read_bcr = pcnet32_dwio_read_bcr,
@@ -460,9 +460,9 @@ static void pcnet32_netif_start(struct net_device *dev)
u16 val;
netif_wake_queue(dev);
- val = lp->a.read_csr(ioaddr, CSR3);
+ val = lp->a->read_csr(ioaddr, CSR3);
val &= 0x00ff;
- lp->a.write_csr(ioaddr, CSR3, val);
+ lp->a->write_csr(ioaddr, CSR3, val);
napi_enable(&lp->napi);
}
@@ -730,7 +730,7 @@ static u32 pcnet32_get_link(struct net_device *dev)
r = mii_link_ok(&lp->mii_if);
} else if (lp->chip_version >= PCNET32_79C970A) {
ulong ioaddr = dev->base_addr; /* card base I/O address */
- r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
+ r = (lp->a->read_bcr(ioaddr, 4) != 0xc0);
} else { /* can not detect link on really old chips */
r = 1;
}
@@ -792,7 +792,7 @@ static int pcnet32_set_ringparam(struct net_device *dev,
pcnet32_netif_stop(dev);
spin_lock_irqsave(&lp->lock, flags);
- lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */
+ lp->a->write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */
size = min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE);
@@ -868,7 +868,7 @@ static void pcnet32_ethtool_test(struct net_device *dev,
static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
{
struct pcnet32_private *lp = netdev_priv(dev);
- struct pcnet32_access *a = &lp->a; /* access to registers */
+ const struct pcnet32_access *a = lp->a; /* access to registers */
ulong ioaddr = dev->base_addr; /* card base I/O address */
struct sk_buff *skb; /* sk buff */
int x, i; /* counters */
@@ -888,21 +888,21 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
pcnet32_netif_stop(dev);
spin_lock_irqsave(&lp->lock, flags);
- lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */
+ lp->a->write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */
numbuffs = min(numbuffs, (int)min(lp->rx_ring_size, lp->tx_ring_size));
/* Reset the PCNET32 */
- lp->a.reset(ioaddr);
- lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */
+ lp->a->reset(ioaddr);
+ lp->a->write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */
/* switch pcnet32 to 32bit mode */
- lp->a.write_bcr(ioaddr, 20, 2);
+ lp->a->write_bcr(ioaddr, 20, 2);
/* purge & init rings but don't actually restart */
pcnet32_restart(dev, 0x0000);
- lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
+ lp->a->write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
/* Initialize Transmit buffers. */
size = data_len + 15;
@@ -947,10 +947,10 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
/* set int loopback in CSR15 */
x = a->read_csr(ioaddr, CSR15) & 0xfffc;
- lp->a.write_csr(ioaddr, CSR15, x | 0x0044);
+ lp->a->write_csr(ioaddr, CSR15, x | 0x0044);
teststatus = cpu_to_le16(0x8000);
- lp->a.write_csr(ioaddr, CSR0, CSR0_START); /* Set STRT bit */
+ lp->a->write_csr(ioaddr, CSR0, CSR0_START); /* Set STRT bit */
/* Check status of descriptors */
for (x = 0; x < numbuffs; x++) {
@@ -969,7 +969,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
}
}
- lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
+ lp->a->write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
wmb();
if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
netdev_printk(KERN_DEBUG, dev, "RX loopback packets:\n");
@@ -1015,7 +1015,7 @@ clean_up:
pcnet32_restart(dev, CSR0_NORMAL);
} else {
pcnet32_purge_rx_ring(dev);
- lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
+ lp->a->write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
}
spin_unlock_irqrestore(&lp->lock, flags);
@@ -1026,7 +1026,7 @@ static int pcnet32_set_phys_id(struct net_device *dev,
enum ethtool_phys_id_state state)
{
struct pcnet32_private *lp = netdev_priv(dev);
- struct pcnet32_access *a = &lp->a;
+ const struct pcnet32_access *a = lp->a;
ulong ioaddr = dev->base_addr;
unsigned long flags;
int i;
@@ -1067,7 +1067,7 @@ static int pcnet32_suspend(struct net_device *dev, unsigned long *flags,
{
int csr5;
struct pcnet32_private *lp = netdev_priv(dev);
- struct pcnet32_access *a = &lp->a;
+ const struct pcnet32_access *a = lp->a;
ulong ioaddr = dev->base_addr;
int ticks;
@@ -1324,8 +1324,8 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
spin_lock_irqsave(&lp->lock, flags);
if (pcnet32_tx(dev)) {
/* reset the chip to clear the error condition, then restart */
- lp->a.reset(ioaddr);
- lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */
+ lp->a->reset(ioaddr);
+ lp->a->write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */
pcnet32_restart(dev, CSR0_START);
netif_wake_queue(dev);
}
@@ -1337,12 +1337,12 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
__napi_complete(napi);
/* clear interrupt masks */
- val = lp->a.read_csr(ioaddr, CSR3);
+ val = lp->a->read_csr(ioaddr, CSR3);
val &= 0x00ff;
- lp->a.write_csr(ioaddr, CSR3, val);
+ lp->a->write_csr(ioaddr, CSR3, val);
/* Set interrupt enable. */
- lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN);
+ lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN);
spin_unlock_irqrestore(&lp->lock, flags);
}
@@ -1365,7 +1365,7 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
int i, csr0;
u16 *buff = ptr;
struct pcnet32_private *lp = netdev_priv(dev);
- struct pcnet32_access *a = &lp->a;
+ const struct pcnet32_access *a = lp->a;
ulong ioaddr = dev->base_addr;
unsigned long flags;
@@ -1401,9 +1401,9 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
for (j = 0; j < PCNET32_MAX_PHYS; j++) {
if (lp->phymask & (1 << j)) {
for (i = 0; i < PCNET32_REGS_PER_PHY; i++) {
- lp->a.write_bcr(ioaddr, 33,
+ lp->a->write_bcr(ioaddr, 33,
(j << 5) | i);
- *buff++ = lp->a.read_bcr(ioaddr, 34);
+ *buff++ = lp->a->read_bcr(ioaddr, 34);
}
}
}
@@ -1505,7 +1505,7 @@ static const struct net_device_ops pcnet32_netdev_ops = {
.ndo_start_xmit = pcnet32_start_xmit,
.ndo_tx_timeout = pcnet32_tx_timeout,
.ndo_get_stats = pcnet32_get_stats,
- .ndo_set_multicast_list = pcnet32_set_multicast_list,
+ .ndo_set_rx_mode = pcnet32_set_multicast_list,
.ndo_do_ioctl = pcnet32_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
@@ -1528,7 +1528,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
int chip_version;
char *chipname;
struct net_device *dev;
- struct pcnet32_access *a = NULL;
+ const struct pcnet32_access *a = NULL;
u8 promaddr[6];
int ret = -ENODEV;
@@ -1785,7 +1785,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
((cards_found >= MAX_UNITS) || full_duplex[cards_found]))
lp->options |= PCNET32_PORT_FD;
- lp->a = *a;
+ lp->a = a;
/* prior to register_netdev, dev->name is not yet correct */
if (pcnet32_alloc_ring(dev, pci_name(lp->pci_dev))) {
@@ -1844,7 +1844,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
if (lp->mii) {
/* lp->phycount and lp->phymask are set to 0 by memset above */
- lp->mii_if.phy_id = ((lp->a.read_bcr(ioaddr, 33)) >> 5) & 0x1f;
+ lp->mii_if.phy_id = ((lp->a->read_bcr(ioaddr, 33)) >> 5) & 0x1f;
/* scan for PHYs */
for (i = 0; i < PCNET32_MAX_PHYS; i++) {
unsigned short id1, id2;
@@ -1864,7 +1864,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
pr_info("Found PHY %04x:%04x at address %d\n",
id1, id2, i);
}
- lp->a.write_bcr(ioaddr, 33, (lp->mii_if.phy_id) << 5);
+ lp->a->write_bcr(ioaddr, 33, (lp->mii_if.phy_id) << 5);
if (lp->phycount > 1)
lp->options |= PCNET32_PORT_MII;
}
@@ -2020,10 +2020,10 @@ static int pcnet32_open(struct net_device *dev)
}
/* Reset the PCNET32 */
- lp->a.reset(ioaddr);
+ lp->a->reset(ioaddr);
/* switch pcnet32 to 32bit mode */
- lp->a.write_bcr(ioaddr, 20, 2);
+ lp->a->write_bcr(ioaddr, 20, 2);
netif_printk(lp, ifup, KERN_DEBUG, dev,
"%s() irq %d tx/rx rings %#x/%#x init %#x\n",
@@ -2032,14 +2032,14 @@ static int pcnet32_open(struct net_device *dev)
(u32) (lp->init_dma_addr));
/* set/reset autoselect bit */
- val = lp->a.read_bcr(ioaddr, 2) & ~2;
+ val = lp->a->read_bcr(ioaddr, 2) & ~2;
if (lp->options & PCNET32_PORT_ASEL)
val |= 2;
- lp->a.write_bcr(ioaddr, 2, val);
+ lp->a->write_bcr(ioaddr, 2, val);
/* handle full duplex setting */
if (lp->mii_if.full_duplex) {
- val = lp->a.read_bcr(ioaddr, 9) & ~3;
+ val = lp->a->read_bcr(ioaddr, 9) & ~3;
if (lp->options & PCNET32_PORT_FD) {
val |= 1;
if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI))
@@ -2049,14 +2049,14 @@ static int pcnet32_open(struct net_device *dev)
if (lp->chip_version == 0x2627)
val |= 3;
}
- lp->a.write_bcr(ioaddr, 9, val);
+ lp->a->write_bcr(ioaddr, 9, val);
}
/* set/reset GPSI bit in test register */
- val = lp->a.read_csr(ioaddr, 124) & ~0x10;
+ val = lp->a->read_csr(ioaddr, 124) & ~0x10;
if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI)
val |= 0x10;
- lp->a.write_csr(ioaddr, 124, val);
+ lp->a->write_csr(ioaddr, 124, val);
/* Allied Telesyn AT 2700/2701 FX are 100Mbit only and do not negotiate */
if (pdev && pdev->subsystem_vendor == PCI_VENDOR_ID_AT &&
@@ -2075,24 +2075,24 @@ static int pcnet32_open(struct net_device *dev)
* duplex, and/or enable auto negotiation, and clear DANAS
*/
if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
- lp->a.write_bcr(ioaddr, 32,
- lp->a.read_bcr(ioaddr, 32) | 0x0080);
+ lp->a->write_bcr(ioaddr, 32,
+ lp->a->read_bcr(ioaddr, 32) | 0x0080);
/* disable Auto Negotiation, set 10Mpbs, HD */
- val = lp->a.read_bcr(ioaddr, 32) & ~0xb8;
+ val = lp->a->read_bcr(ioaddr, 32) & ~0xb8;
if (lp->options & PCNET32_PORT_FD)
val |= 0x10;
if (lp->options & PCNET32_PORT_100)
val |= 0x08;
- lp->a.write_bcr(ioaddr, 32, val);
+ lp->a->write_bcr(ioaddr, 32, val);
} else {
if (lp->options & PCNET32_PORT_ASEL) {
- lp->a.write_bcr(ioaddr, 32,
- lp->a.read_bcr(ioaddr,
+ lp->a->write_bcr(ioaddr, 32,
+ lp->a->read_bcr(ioaddr,
32) | 0x0080);
/* enable auto negotiate, setup, disable fd */
- val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
+ val = lp->a->read_bcr(ioaddr, 32) & ~0x98;
val |= 0x20;
- lp->a.write_bcr(ioaddr, 32, val);
+ lp->a->write_bcr(ioaddr, 32, val);
}
}
} else {
@@ -2105,10 +2105,10 @@ static int pcnet32_open(struct net_device *dev)
* There is really no good other way to handle multiple PHYs
* other than turning off all automatics
*/
- val = lp->a.read_bcr(ioaddr, 2);
- lp->a.write_bcr(ioaddr, 2, val & ~2);
- val = lp->a.read_bcr(ioaddr, 32);
- lp->a.write_bcr(ioaddr, 32, val & ~(1 << 7)); /* stop MII manager */
+ val = lp->a->read_bcr(ioaddr, 2);
+ lp->a->write_bcr(ioaddr, 2, val & ~2);
+ val = lp->a->read_bcr(ioaddr, 32);
+ lp->a->write_bcr(ioaddr, 32, val & ~(1 << 7)); /* stop MII manager */
if (!(lp->options & PCNET32_PORT_ASEL)) {
/* setup ecmd */
@@ -2118,7 +2118,7 @@ static int pcnet32_open(struct net_device *dev)
ethtool_cmd_speed_set(&ecmd,
(lp->options & PCNET32_PORT_100) ?
SPEED_100 : SPEED_10);
- bcr9 = lp->a.read_bcr(ioaddr, 9);
+ bcr9 = lp->a->read_bcr(ioaddr, 9);
if (lp->options & PCNET32_PORT_FD) {
ecmd.duplex = DUPLEX_FULL;
@@ -2127,7 +2127,7 @@ static int pcnet32_open(struct net_device *dev)
ecmd.duplex = DUPLEX_HALF;
bcr9 |= ~(1 << 0);
}
- lp->a.write_bcr(ioaddr, 9, bcr9);
+ lp->a->write_bcr(ioaddr, 9, bcr9);
}
for (i = 0; i < PCNET32_MAX_PHYS; i++) {
@@ -2158,9 +2158,9 @@ static int pcnet32_open(struct net_device *dev)
#ifdef DO_DXSUFLO
if (lp->dxsuflo) { /* Disable transmit stop on underflow */
- val = lp->a.read_csr(ioaddr, CSR3);
+ val = lp->a->read_csr(ioaddr, CSR3);
val |= 0x40;
- lp->a.write_csr(ioaddr, CSR3, val);
+ lp->a->write_csr(ioaddr, CSR3, val);
}
#endif
@@ -2176,11 +2176,11 @@ static int pcnet32_open(struct net_device *dev)
napi_enable(&lp->napi);
/* Re-initialize the PCNET32, and start it when done. */
- lp->a.write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff));
- lp->a.write_csr(ioaddr, 2, (lp->init_dma_addr >> 16));
+ lp->a->write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff));
+ lp->a->write_csr(ioaddr, 2, (lp->init_dma_addr >> 16));
- lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */
- lp->a.write_csr(ioaddr, CSR0, CSR0_INIT);
+ lp->a->write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */
+ lp->a->write_csr(ioaddr, CSR0, CSR0_INIT);
netif_start_queue(dev);
@@ -2192,19 +2192,19 @@ static int pcnet32_open(struct net_device *dev)
i = 0;
while (i++ < 100)
- if (lp->a.read_csr(ioaddr, CSR0) & CSR0_IDON)
+ if (lp->a->read_csr(ioaddr, CSR0) & CSR0_IDON)
break;
/*
* We used to clear the InitDone bit, 0x0100, here but Mark Stockton
* reports that doing so triggers a bug in the '974.
*/
- lp->a.write_csr(ioaddr, CSR0, CSR0_NORMAL);
+ lp->a->write_csr(ioaddr, CSR0, CSR0_NORMAL);
netif_printk(lp, ifup, KERN_DEBUG, dev,
"pcnet32 open after %d ticks, init block %#x csr0 %4.4x\n",
i,
(u32) (lp->init_dma_addr),
- lp->a.read_csr(ioaddr, CSR0));
+ lp->a->read_csr(ioaddr, CSR0));
spin_unlock_irqrestore(&lp->lock, flags);
@@ -2218,7 +2218,7 @@ err_free_ring:
* Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot
*/
- lp->a.write_bcr(ioaddr, 20, 4);
+ lp->a->write_bcr(ioaddr, 20, 4);
err_free_irq:
spin_unlock_irqrestore(&lp->lock, flags);
@@ -2323,7 +2323,7 @@ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits)
/* wait for stop */
for (i = 0; i < 100; i++)
- if (lp->a.read_csr(ioaddr, CSR0) & CSR0_STOP)
+ if (lp->a->read_csr(ioaddr, CSR0) & CSR0_STOP)
break;
if (i >= 100)
@@ -2335,13 +2335,13 @@ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits)
return;
/* ReInit Ring */
- lp->a.write_csr(ioaddr, CSR0, CSR0_INIT);
+ lp->a->write_csr(ioaddr, CSR0, CSR0_INIT);
i = 0;
while (i++ < 1000)
- if (lp->a.read_csr(ioaddr, CSR0) & CSR0_IDON)
+ if (lp->a->read_csr(ioaddr, CSR0) & CSR0_IDON)
break;
- lp->a.write_csr(ioaddr, CSR0, csr0_bits);
+ lp->a->write_csr(ioaddr, CSR0, csr0_bits);
}
static void pcnet32_tx_timeout(struct net_device *dev)
@@ -2353,8 +2353,8 @@ static void pcnet32_tx_timeout(struct net_device *dev)
/* Transmitter timeout, serious problems. */
if (pcnet32_debug & NETIF_MSG_DRV)
pr_err("%s: transmit timed out, status %4.4x, resetting\n",
- dev->name, lp->a.read_csr(ioaddr, CSR0));
- lp->a.write_csr(ioaddr, CSR0, CSR0_STOP);
+ dev->name, lp->a->read_csr(ioaddr, CSR0));
+ lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);
dev->stats.tx_errors++;
if (netif_msg_tx_err(lp)) {
int i;
@@ -2397,7 +2397,7 @@ static netdev_tx_t pcnet32_start_xmit(struct sk_buff *skb,
netif_printk(lp, tx_queued, KERN_DEBUG, dev,
"%s() called, csr0 %4.4x\n",
- __func__, lp->a.read_csr(ioaddr, CSR0));
+ __func__, lp->a->read_csr(ioaddr, CSR0));
/* Default status -- will not enable Successful-TxDone
* interrupt when that option is available to us.
@@ -2427,7 +2427,7 @@ static netdev_tx_t pcnet32_start_xmit(struct sk_buff *skb,
dev->stats.tx_bytes += skb->len;
/* Trigger an immediate send poll. */
- lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_TXPOLL);
+ lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_TXPOLL);
if (lp->tx_ring[(entry + 1) & lp->tx_mod_mask].base != 0) {
lp->tx_full = 1;
@@ -2452,16 +2452,16 @@ pcnet32_interrupt(int irq, void *dev_id)
spin_lock(&lp->lock);
- csr0 = lp->a.read_csr(ioaddr, CSR0);
+ csr0 = lp->a->read_csr(ioaddr, CSR0);
while ((csr0 & 0x8f00) && --boguscnt >= 0) {
if (csr0 == 0xffff)
break; /* PCMCIA remove happened */
/* Acknowledge all of the current interrupt sources ASAP. */
- lp->a.write_csr(ioaddr, CSR0, csr0 & ~0x004f);
+ lp->a->write_csr(ioaddr, CSR0, csr0 & ~0x004f);
netif_printk(lp, intr, KERN_DEBUG, dev,
"interrupt csr0=%#2.2x new csr=%#2.2x\n",
- csr0, lp->a.read_csr(ioaddr, CSR0));
+ csr0, lp->a->read_csr(ioaddr, CSR0));
/* Log misc errors. */
if (csr0 & 0x4000)
@@ -2488,19 +2488,19 @@ pcnet32_interrupt(int irq, void *dev_id)
if (napi_schedule_prep(&lp->napi)) {
u16 val;
/* set interrupt masks */
- val = lp->a.read_csr(ioaddr, CSR3);
+ val = lp->a->read_csr(ioaddr, CSR3);
val |= 0x5f00;
- lp->a.write_csr(ioaddr, CSR3, val);
+ lp->a->write_csr(ioaddr, CSR3, val);
__napi_schedule(&lp->napi);
break;
}
- csr0 = lp->a.read_csr(ioaddr, CSR0);
+ csr0 = lp->a->read_csr(ioaddr, CSR0);
}
netif_printk(lp, intr, KERN_DEBUG, dev,
"exiting interrupt, csr0=%#4.4x\n",
- lp->a.read_csr(ioaddr, CSR0));
+ lp->a->read_csr(ioaddr, CSR0));
spin_unlock(&lp->lock);
@@ -2520,20 +2520,20 @@ static int pcnet32_close(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
- dev->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112);
+ dev->stats.rx_missed_errors = lp->a->read_csr(ioaddr, 112);
netif_printk(lp, ifdown, KERN_DEBUG, dev,
"Shutting down ethercard, status was %2.2x\n",
- lp->a.read_csr(ioaddr, CSR0));
+ lp->a->read_csr(ioaddr, CSR0));
/* We stop the PCNET32 here -- it occasionally polls memory if we don't. */
- lp->a.write_csr(ioaddr, CSR0, CSR0_STOP);
+ lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);
/*
* Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot
*/
- lp->a.write_bcr(ioaddr, 20, 4);
+ lp->a->write_bcr(ioaddr, 20, 4);
spin_unlock_irqrestore(&lp->lock, flags);
@@ -2556,7 +2556,7 @@ static struct net_device_stats *pcnet32_get_stats(struct net_device *dev)
unsigned long flags;
spin_lock_irqsave(&lp->lock, flags);
- dev->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112);
+ dev->stats.rx_missed_errors = lp->a->read_csr(ioaddr, 112);
spin_unlock_irqrestore(&lp->lock, flags);
return &dev->stats;
@@ -2577,10 +2577,10 @@ static void pcnet32_load_multicast(struct net_device *dev)
if (dev->flags & IFF_ALLMULTI) {
ib->filter[0] = cpu_to_le32(~0U);
ib->filter[1] = cpu_to_le32(~0U);
- lp->a.write_csr(ioaddr, PCNET32_MC_FILTER, 0xffff);
- lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+1, 0xffff);
- lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+2, 0xffff);
- lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+3, 0xffff);
+ lp->a->write_csr(ioaddr, PCNET32_MC_FILTER, 0xffff);
+ lp->a->write_csr(ioaddr, PCNET32_MC_FILTER+1, 0xffff);
+ lp->a->write_csr(ioaddr, PCNET32_MC_FILTER+2, 0xffff);
+ lp->a->write_csr(ioaddr, PCNET32_MC_FILTER+3, 0xffff);
return;
}
/* clear the multicast filter */
@@ -2594,7 +2594,7 @@ static void pcnet32_load_multicast(struct net_device *dev)
mcast_table[crc >> 4] |= cpu_to_le16(1 << (crc & 0xf));
}
for (i = 0; i < 4; i++)
- lp->a.write_csr(ioaddr, PCNET32_MC_FILTER + i,
+ lp->a->write_csr(ioaddr, PCNET32_MC_FILTER + i,
le16_to_cpu(mcast_table[i]));
}
@@ -2609,28 +2609,28 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
suspended = pcnet32_suspend(dev, &flags, 0);
- csr15 = lp->a.read_csr(ioaddr, CSR15);
+ csr15 = lp->a->read_csr(ioaddr, CSR15);
if (dev->flags & IFF_PROMISC) {
/* Log any net taps. */
netif_info(lp, hw, dev, "Promiscuous mode enabled\n");
lp->init_block->mode =
cpu_to_le16(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) <<
7);
- lp->a.write_csr(ioaddr, CSR15, csr15 | 0x8000);
+ lp->a->write_csr(ioaddr, CSR15, csr15 | 0x8000);
} else {
lp->init_block->mode =
cpu_to_le16((lp->options & PCNET32_PORT_PORTSEL) << 7);
- lp->a.write_csr(ioaddr, CSR15, csr15 & 0x7fff);
+ lp->a->write_csr(ioaddr, CSR15, csr15 & 0x7fff);
pcnet32_load_multicast(dev);
}
if (suspended) {
int csr5;
/* clear SUSPEND (SPND) - CSR5 bit 0 */
- csr5 = lp->a.read_csr(ioaddr, CSR5);
- lp->a.write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND));
+ csr5 = lp->a->read_csr(ioaddr, CSR5);
+ lp->a->write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND));
} else {
- lp->a.write_csr(ioaddr, CSR0, CSR0_STOP);
+ lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);
pcnet32_restart(dev, CSR0_NORMAL);
netif_wake_queue(dev);
}
@@ -2648,8 +2648,8 @@ static int mdio_read(struct net_device *dev, int phy_id, int reg_num)
if (!lp->mii)
return 0;
- lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
- val_out = lp->a.read_bcr(ioaddr, 34);
+ lp->a->write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
+ val_out = lp->a->read_bcr(ioaddr, 34);
return val_out;
}
@@ -2663,8 +2663,8 @@ static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val)
if (!lp->mii)
return;
- lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
- lp->a.write_bcr(ioaddr, 34, val);
+ lp->a->write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
+ lp->a->write_bcr(ioaddr, 34, val);
}
static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2741,7 +2741,7 @@ static void pcnet32_check_media(struct net_device *dev, int verbose)
curr_link = mii_link_ok(&lp->mii_if);
} else {
ulong ioaddr = dev->base_addr; /* card base I/O address */
- curr_link = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
+ curr_link = (lp->a->read_bcr(ioaddr, 4) != 0xc0);
}
if (!curr_link) {
if (prev_link || verbose) {
@@ -2764,13 +2764,13 @@ static void pcnet32_check_media(struct net_device *dev, int verbose)
(ecmd.duplex == DUPLEX_FULL)
? "full" : "half");
}
- bcr9 = lp->a.read_bcr(dev->base_addr, 9);
+ bcr9 = lp->a->read_bcr(dev->base_addr, 9);
if ((bcr9 & (1 << 0)) != lp->mii_if.full_duplex) {
if (lp->mii_if.full_duplex)
bcr9 |= (1 << 0);
else
bcr9 &= ~(1 << 0);
- lp->a.write_bcr(dev->base_addr, 9, bcr9);
+ lp->a->write_bcr(dev->base_addr, 9, bcr9);
}
} else {
netif_info(lp, link, dev, "link up\n");
diff --git a/drivers/net/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c
index 7d9ec23aabf6..080b71fcc683 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/ethernet/amd/sun3lance.c
@@ -297,7 +297,7 @@ static const struct net_device_ops lance_netdev_ops = {
.ndo_open = lance_open,
.ndo_stop = lance_close,
.ndo_start_xmit = lance_start_xmit,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_set_mac_address = NULL,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/sunlance.c b/drivers/net/ethernet/amd/sunlance.c
index 06f2d4382dc4..8fda457f94cf 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/ethernet/amd/sunlance.c
@@ -1298,7 +1298,7 @@ static const struct net_device_ops sparc_lance_ops = {
.ndo_open = lance_open,
.ndo_stop = lance_close,
.ndo_start_xmit = lance_start_xmit,
- .ndo_set_multicast_list = lance_set_multicast,
+ .ndo_set_rx_mode = lance_set_multicast,
.ndo_tx_timeout = lance_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ethernet/apple/Kconfig b/drivers/net/ethernet/apple/Kconfig
new file mode 100644
index 000000000000..a759d5483ab9
--- /dev/null
+++ b/drivers/net/ethernet/apple/Kconfig
@@ -0,0 +1,77 @@
+#
+# Apple device configuration
+#
+
+config NET_VENDOR_APPLE
+ bool "Apple devices"
+ default y
+ depends on (PPC_PMAC && PPC32) || MAC
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about IBM devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_APPLE
+
+config MACE
+ tristate "MACE (Power Mac ethernet) support"
+ depends on PPC_PMAC && PPC32
+ select CRC32
+ ---help---
+ Power Macintoshes and clones with Ethernet built-in on the
+ motherboard will usually use a MACE (Medium Access Control for
+ Ethernet) interface. Say Y to include support for the MACE chip.
+
+ To compile this driver as a module, choose M here: the module
+ will be called mace.
+
+config MACE_AAUI_PORT
+ bool "Use AAUI port instead of TP by default"
+ depends on MACE
+ ---help---
+ Some Apple machines (notably the Apple Network Server) which use the
+ MACE ethernet chip have an Apple AUI port (small 15-pin connector),
+ instead of an 8-pin RJ45 connector for twisted-pair ethernet. Say
+ Y here if you have such a machine. If unsure, say N.
+ The driver will default to AAUI on ANS anyway, and if you use it as
+ a module, you can provide the port_aaui=0|1 to force the driver.
+
+config BMAC
+ tristate "BMAC (G3 ethernet) support"
+ depends on PPC_PMAC && PPC32
+ select CRC32
+ ---help---
+ Say Y for support of BMAC Ethernet interfaces. These are used on G3
+ computers.
+
+ To compile this driver as a module, choose M here: the module
+ will be called bmac.
+
+config MAC89x0
+ tristate "Macintosh CS89x0 based ethernet cards"
+ depends on MAC
+ ---help---
+ Support for CS89x0 chipset based Ethernet cards. If you have a
+ Nubus or LC-PDS network (Ethernet) card of this type, say Y and
+ read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. This module will
+ be called mac89x0.
+
+config MACMACE
+ bool "Macintosh (AV) onboard MACE ethernet"
+ depends on MAC
+ select CRC32
+ ---help---
+ Support for the onboard AMD 79C940 MACE Ethernet controller used in
+ the 660AV and 840AV Macintosh. If you have one of these Macintoshes
+ say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+endif # NET_VENDOR_APPLE
diff --git a/drivers/net/ethernet/apple/Makefile b/drivers/net/ethernet/apple/Makefile
new file mode 100644
index 000000000000..0d3a5919c95b
--- /dev/null
+++ b/drivers/net/ethernet/apple/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Apple network device drivers.
+#
+
+obj-$(CONFIG_MACE) += mace.o
+obj-$(CONFIG_BMAC) += bmac.o
+obj-$(CONFIG_MAC89x0) += mac89x0.o
+obj-$(CONFIG_MACMACE) += macmace.o
diff --git a/drivers/net/bmac.c b/drivers/net/ethernet/apple/bmac.c
index 45e45e8d3d66..d070b229dbf7 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/ethernet/apple/bmac.c
@@ -1237,7 +1237,7 @@ static const struct net_device_ops bmac_netdev_ops = {
.ndo_open = bmac_open,
.ndo_stop = bmac_close,
.ndo_start_xmit = bmac_output,
- .ndo_set_multicast_list = bmac_set_multicast,
+ .ndo_set_rx_mode = bmac_set_multicast,
.ndo_set_mac_address = bmac_set_address,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/bmac.h b/drivers/net/ethernet/apple/bmac.h
index a1d19d867ba5..a1d19d867ba5 100644
--- a/drivers/net/bmac.h
+++ b/drivers/net/ethernet/apple/bmac.h
diff --git a/drivers/net/mac89x0.c b/drivers/net/ethernet/apple/mac89x0.c
index 669b317974a8..83781f316d1f 100644
--- a/drivers/net/mac89x0.c
+++ b/drivers/net/ethernet/apple/mac89x0.c
@@ -170,7 +170,7 @@ static const struct net_device_ops mac89x0_netdev_ops = {
.ndo_stop = net_close,
.ndo_start_xmit = net_send_packet,
.ndo_get_stats = net_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_set_mac_address = set_mac_address,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/mace.c b/drivers/net/ethernet/apple/mace.c
index 2074e9724ba3..bec87bd9195c 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/ethernet/apple/mace.c
@@ -100,7 +100,7 @@ static const struct net_device_ops mace_netdev_ops = {
.ndo_open = mace_open,
.ndo_stop = mace_close,
.ndo_start_xmit = mace_xmit_start,
- .ndo_set_multicast_list = mace_set_multicast,
+ .ndo_set_rx_mode = mace_set_multicast,
.ndo_set_mac_address = mace_set_address,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/mace.h b/drivers/net/ethernet/apple/mace.h
index 30b7ec0cedb5..30b7ec0cedb5 100644
--- a/drivers/net/mace.h
+++ b/drivers/net/ethernet/apple/mace.h
diff --git a/drivers/net/macmace.c b/drivers/net/ethernet/apple/macmace.c
index 4286e67f9634..7cf81bbffe0e 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/ethernet/apple/macmace.c
@@ -31,9 +31,8 @@
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/gfp.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/mac_psc.h>
#include <asm/page.h>
@@ -185,7 +184,7 @@ static const struct net_device_ops mace_netdev_ops = {
.ndo_stop = mace_close,
.ndo_start_xmit = mace_xmit_start,
.ndo_tx_timeout = mace_tx_timeout,
- .ndo_set_multicast_list = mace_set_multicast,
+ .ndo_set_rx_mode = mace_set_multicast,
.ndo_set_mac_address = mace_set_address,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
@@ -203,14 +202,8 @@ static int __devinit mace_probe(struct platform_device *pdev)
unsigned char *addr;
struct net_device *dev;
unsigned char checksum = 0;
- static int found = 0;
int err;
- if (found || macintosh_config->ether_type != MAC_ETHER_MACE)
- return -ENODEV;
-
- found = 1; /* prevent 'finding' one on every device probe */
-
dev = alloc_etherdev(PRIV_BYTES);
if (!dev)
return -ENOMEM;
diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig
new file mode 100644
index 000000000000..1ed886d421f8
--- /dev/null
+++ b/drivers/net/ethernet/atheros/Kconfig
@@ -0,0 +1,70 @@
+#
+# Atheros device configuration
+#
+
+config NET_VENDOR_ATHEROS
+ bool "Atheros devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Atheros devices. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_ATHEROS
+
+config ATL2
+ tristate "Atheros L2 Fast Ethernet support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This driver supports the Atheros L2 fast ethernet adapter.
+
+ To compile this driver as a module, choose M here. The module
+ will be called atl2.
+
+config ATL1
+ tristate "Atheros/Attansic L1 Gigabit Ethernet support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This driver supports the Atheros/Attansic L1 gigabit ethernet
+ adapter.
+
+ To compile this driver as a module, choose M here. The module
+ will be called atl1.
+
+config ATL1E
+ tristate "Atheros L1E Gigabit Ethernet support (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This driver supports the Atheros L1E gigabit ethernet adapter.
+
+ To compile this driver as a module, choose M here. The module
+ will be called atl1e.
+
+config ATL1C
+ tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This driver supports the Atheros L1C gigabit ethernet adapter.
+
+ To compile this driver as a module, choose M here. The module
+ will be called atl1c.
+
+endif # NET_VENDOR_ATHEROS
diff --git a/drivers/net/ethernet/atheros/Makefile b/drivers/net/ethernet/atheros/Makefile
new file mode 100644
index 000000000000..e7e76fb576ff
--- /dev/null
+++ b/drivers/net/ethernet/atheros/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Atheros network device drivers.
+#
+
+obj-$(CONFIG_ATL1) += atlx/
+obj-$(CONFIG_ATL2) += atlx/
+obj-$(CONFIG_ATL1E) += atl1e/
+obj-$(CONFIG_ATL1C) += atl1c/
diff --git a/drivers/net/atl1c/Makefile b/drivers/net/ethernet/atheros/atl1c/Makefile
index c37d966952ee..c37d966952ee 100644
--- a/drivers/net/atl1c/Makefile
+++ b/drivers/net/ethernet/atheros/atl1c/Makefile
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h
index ca70e16b6e2c..ca70e16b6e2c 100644
--- a/drivers/net/atl1c/atl1c.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h
diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
index 7be884d0aaf6..7be884d0aaf6 100644
--- a/drivers/net/atl1c/atl1c_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 23f2ab0f2fa8..23f2ab0f2fa8 100644
--- a/drivers/net/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
diff --git a/drivers/net/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index 655fc6c4a8a4..655fc6c4a8a4 100644
--- a/drivers/net/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 972244218408..02c7ed8d9eca 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2179,12 +2179,11 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
- buffer_info->length = frag->size;
- buffer_info->dma =
- pci_map_page(adapter->pdev, frag->page,
- frag->page_offset,
- buffer_info->length,
- PCI_DMA_TODEVICE);
+ buffer_info->length = skb_frag_size(frag);
+ buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev,
+ frag, 0,
+ buffer_info->length,
+ DMA_TO_DEVICE);
ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE,
ATL1C_PCIMAP_TODEVICE);
@@ -2600,7 +2599,7 @@ static const struct net_device_ops atl1c_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_start_xmit = atl1c_xmit_frame,
.ndo_set_mac_address = atl1c_set_mac_addr,
- .ndo_set_multicast_list = atl1c_set_multi,
+ .ndo_set_rx_mode = atl1c_set_multi,
.ndo_change_mtu = atl1c_change_mtu,
.ndo_fix_features = atl1c_fix_features,
.ndo_set_features = atl1c_set_features,
diff --git a/drivers/net/atl1e/Makefile b/drivers/net/ethernet/atheros/atl1e/Makefile
index bc11be824e76..bc11be824e76 100644
--- a/drivers/net/atl1e/Makefile
+++ b/drivers/net/ethernet/atheros/atl1e/Makefile
diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/ethernet/atheros/atl1e/atl1e.h
index 829b5ad71d0d..829b5ad71d0d 100644
--- a/drivers/net/atl1e/atl1e.h
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e.h
diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
index 6269438d365f..6269438d365f 100644
--- a/drivers/net/atl1e/atl1e_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c
index 923063d2e5bb..923063d2e5bb 100644
--- a/drivers/net/atl1e/atl1e_hw.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c
diff --git a/drivers/net/atl1e/atl1e_hw.h b/drivers/net/ethernet/atheros/atl1e/atl1e_hw.h
index 74df16aef793..74df16aef793 100644
--- a/drivers/net/atl1e/atl1e_hw.h
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_hw.h
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index d8d411998fa3..95483bcac1d0 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -1593,7 +1593,7 @@ static u16 atl1e_cal_tdp_req(const struct sk_buff *skb)
u16 proto_hdr_len = 0;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- fg_size = skb_shinfo(skb)->frags[i].size;
+ fg_size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
tpd_req += ((fg_size + MAX_TX_BUF_LEN - 1) >> MAX_TX_BUF_SHIFT);
}
@@ -1744,12 +1744,12 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
}
for (f = 0; f < nr_frags; f++) {
- struct skb_frag_struct *frag;
+ const struct skb_frag_struct *frag;
u16 i;
u16 seg_num;
frag = &skb_shinfo(skb)->frags[f];
- buf_len = frag->size;
+ buf_len = skb_frag_size(frag);
seg_num = (buf_len + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
for (i = 0; i < seg_num; i++) {
@@ -1765,12 +1765,11 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
MAX_TX_BUF_LEN : buf_len;
buf_len -= tx_buffer->length;
- tx_buffer->dma =
- pci_map_page(adapter->pdev, frag->page,
- frag->page_offset +
- (i * MAX_TX_BUF_LEN),
- tx_buffer->length,
- PCI_DMA_TODEVICE);
+ tx_buffer->dma = skb_frag_dma_map(&adapter->pdev->dev,
+ frag,
+ (i * MAX_TX_BUF_LEN),
+ tx_buffer->length,
+ DMA_TO_DEVICE);
ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE);
use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
@@ -2212,7 +2211,7 @@ static const struct net_device_ops atl1e_netdev_ops = {
.ndo_stop = atl1e_close,
.ndo_start_xmit = atl1e_xmit_frame,
.ndo_get_stats = atl1e_get_stats,
- .ndo_set_multicast_list = atl1e_set_multi,
+ .ndo_set_rx_mode = atl1e_set_multi,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = atl1e_set_mac_addr,
.ndo_fix_features = atl1e_fix_features,
diff --git a/drivers/net/atl1e/atl1e_param.c b/drivers/net/ethernet/atheros/atl1e/atl1e_param.c
index 0ce60b6e7ef0..0ce60b6e7ef0 100644
--- a/drivers/net/atl1e/atl1e_param.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_param.c
diff --git a/drivers/net/atlx/Makefile b/drivers/net/ethernet/atheros/atlx/Makefile
index e4f6022ca552..e4f6022ca552 100644
--- a/drivers/net/atlx/Makefile
+++ b/drivers/net/ethernet/atheros/atlx/Makefile
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 97e6954304ea..33a4e35f5ee8 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -858,7 +858,7 @@ static s32 atl1_init_hw(struct atl1_hw *hw)
atl1_init_flash_opcode(hw);
if (!hw->phy_configured) {
- /* enable GPHY LinkChange Interrrupt */
+ /* enable GPHY LinkChange Interrupt */
ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
if (ret_val)
return ret_val;
@@ -2267,11 +2267,11 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
}
for (f = 0; f < nr_frags; f++) {
- struct skb_frag_struct *frag;
+ const struct skb_frag_struct *frag;
u16 i, nseg;
frag = &skb_shinfo(skb)->frags[f];
- buf_len = frag->size;
+ buf_len = skb_frag_size(frag);
nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) /
ATL1_MAX_TX_BUF_LEN;
@@ -2283,10 +2283,9 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
ATL1_MAX_TX_BUF_LEN : buf_len;
buf_len -= buffer_info->length;
- buffer_info->dma = pci_map_page(adapter->pdev,
- frag->page,
- frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
- buffer_info->length, PCI_DMA_TODEVICE);
+ buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev,
+ frag, i * ATL1_MAX_TX_BUF_LEN,
+ buffer_info->length, DMA_TO_DEVICE);
if (++next_to_use == tpd_ring->count)
next_to_use = 0;
@@ -2357,7 +2356,6 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
int count = 1;
int ret_val;
struct tx_packet_desc *ptpd;
- u16 frag_size;
u16 vlan_tag;
unsigned int nr_frags = 0;
unsigned int mss = 0;
@@ -2373,10 +2371,9 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
nr_frags = skb_shinfo(skb)->nr_frags;
for (f = 0; f < nr_frags; f++) {
- frag_size = skb_shinfo(skb)->frags[f].size;
- if (frag_size)
- count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
- ATL1_MAX_TX_BUF_LEN;
+ unsigned int f_size = skb_frag_size(&skb_shinfo(skb)->frags[f]);
+ count += (f_size + ATL1_MAX_TX_BUF_LEN - 1) /
+ ATL1_MAX_TX_BUF_LEN;
}
mss = skb_shinfo(skb)->gso_size;
@@ -2869,7 +2866,7 @@ static const struct net_device_ops atl1_netdev_ops = {
.ndo_open = atl1_open,
.ndo_stop = atl1_close,
.ndo_start_xmit = atl1_xmit_frame,
- .ndo_set_multicast_list = atlx_set_multi,
+ .ndo_set_rx_mode = atlx_set_multi,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = atl1_set_mac,
.ndo_change_mtu = atl1_change_mtu,
@@ -3474,12 +3471,8 @@ static void atl1_get_ringparam(struct net_device *netdev,
ring->rx_max_pending = ATL1_MAX_RFD;
ring->tx_max_pending = ATL1_MAX_TPD;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = rxdr->count;
ring->tx_pending = txdr->count;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
static int atl1_set_ringparam(struct net_device *netdev,
diff --git a/drivers/net/atlx/atl1.h b/drivers/net/ethernet/atheros/atlx/atl1.h
index 109d6da8be97..109d6da8be97 100644
--- a/drivers/net/atlx/atl1.h
+++ b/drivers/net/ethernet/atheros/atlx/atl1.h
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index d4f7dda39721..1feae5928a4b 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -1325,7 +1325,7 @@ static const struct net_device_ops atl2_netdev_ops = {
.ndo_open = atl2_open,
.ndo_stop = atl2_close,
.ndo_start_xmit = atl2_xmit_frame,
- .ndo_set_multicast_list = atl2_set_multi,
+ .ndo_set_rx_mode = atl2_set_multi,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = atl2_set_mac,
.ndo_change_mtu = atl2_change_mtu,
diff --git a/drivers/net/atlx/atl2.h b/drivers/net/ethernet/atheros/atlx/atl2.h
index bf9016ebdd9b..bf9016ebdd9b 100644
--- a/drivers/net/atlx/atl2.h
+++ b/drivers/net/ethernet/atheros/atlx/atl2.h
diff --git a/drivers/net/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index aabcf4b5745a..aabcf4b5745a 100644
--- a/drivers/net/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
diff --git a/drivers/net/atlx/atlx.h b/drivers/net/ethernet/atheros/atlx/atlx.h
index 14054b75aa62..14054b75aa62 100644
--- a/drivers/net/atlx/atlx.h
+++ b/drivers/net/ethernet/atheros/atlx/atlx.h
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
new file mode 100644
index 000000000000..f15e72e81ac4
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -0,0 +1,122 @@
+#
+# Broadcom device configuration
+#
+
+config NET_VENDOR_BROADCOM
+ bool "Broadcom devices"
+ default y
+ depends on (SSB_POSSIBLE && HAS_DMA) || PCI || BCM63XX || \
+ SIBYTE_SB1xxx_SOC
+ ---help---
+ If you have a network (Ethernet) chipset belonging to this class,
+ say Y.
+
+ Note that the answer to this question does not directly affect
+ the kernel: saying N will just case the configurator to skip all
+ the questions regarding AMD chipsets. If you say Y, you will be asked
+ for your specific chipset/driver in the following questions.
+
+if NET_VENDOR_BROADCOM
+
+config B44
+ tristate "Broadcom 440x/47xx ethernet support"
+ depends on SSB_POSSIBLE && HAS_DMA
+ select SSB
+ select NET_CORE
+ select MII
+ ---help---
+ If you have a network (Ethernet) controller of this type, say Y
+ or M and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called b44.
+
+# Auto-select SSB PCI-HOST support, if possible
+config B44_PCI_AUTOSELECT
+ bool
+ depends on B44 && SSB_PCIHOST_POSSIBLE
+ select SSB_PCIHOST
+ default y
+
+# Auto-select SSB PCICORE driver, if possible
+config B44_PCICORE_AUTOSELECT
+ bool
+ depends on B44 && SSB_DRIVER_PCICORE_POSSIBLE
+ select SSB_DRIVER_PCICORE
+ default y
+
+config B44_PCI
+ bool
+ depends on B44_PCI_AUTOSELECT && B44_PCICORE_AUTOSELECT
+ default y
+
+config BCM63XX_ENET
+ tristate "Broadcom 63xx internal mac support"
+ depends on BCM63XX
+ select NET_CORE
+ select MII
+ select PHYLIB
+ help
+ This driver supports the ethernet MACs in the Broadcom 63xx
+ MIPS chipset family (BCM63XX).
+
+config BNX2
+ tristate "Broadcom NetXtremeII support"
+ depends on PCI
+ select CRC32
+ select FW_LOADER
+ ---help---
+ This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called bnx2. This is recommended.
+
+config CNIC
+ tristate "Broadcom CNIC support"
+ depends on PCI
+ select BNX2
+ select UIO
+ ---help---
+ This driver supports offload features of Broadcom NetXtremeII
+ gigabit Ethernet cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called cnic. This is recommended.
+
+config SB1250_MAC
+ tristate "SB1250 Gigabit Ethernet support"
+ depends on SIBYTE_SB1xxx_SOC
+ select PHYLIB
+ ---help---
+ This driver supports Gigabit Ethernet interfaces based on the
+ Broadcom SiByte family of System-On-a-Chip parts. They include
+ the BCM1120, BCM1125, BCM1125H, BCM1250, BCM1255, BCM1280, BCM1455
+ and BCM1480 chips.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sb1250-mac.
+
+config TIGON3
+ tristate "Broadcom Tigon3 support"
+ depends on PCI
+ select PHYLIB
+ ---help---
+ This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called tg3. This is recommended.
+
+config BNX2X
+ tristate "Broadcom NetXtremeII 10Gb support"
+ depends on PCI
+ select FW_LOADER
+ select ZLIB_INFLATE
+ select LIBCRC32C
+ select MDIO
+ ---help---
+ This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
+ To compile this driver as a module, choose M here: the module
+ will be called bnx2x. This is recommended.
+
+endif # NET_VENDOR_BROADCOM
diff --git a/drivers/net/ethernet/broadcom/Makefile b/drivers/net/ethernet/broadcom/Makefile
new file mode 100644
index 000000000000..b7896051d54e
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the Broadcom network device drivers.
+#
+
+obj-$(CONFIG_B44) += b44.o
+obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
+obj-$(CONFIG_BNX2) += bnx2.o
+obj-$(CONFIG_CNIC) += cnic.o
+obj-$(CONFIG_BNX2X) += bnx2x/
+obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
+obj-$(CONFIG_TIGON3) += tg3.o
diff --git a/drivers/net/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 41ea84e3f69c..4cf835dbc122 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2114,7 +2114,7 @@ static const struct net_device_ops b44_netdev_ops = {
.ndo_stop = b44_close,
.ndo_start_xmit = b44_start_xmit,
.ndo_get_stats = b44_get_stats,
- .ndo_set_multicast_list = b44_set_rx_mode,
+ .ndo_set_rx_mode = b44_set_rx_mode,
.ndo_set_mac_address = b44_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = b44_ioctl,
diff --git a/drivers/net/b44.h b/drivers/net/ethernet/broadcom/b44.h
index e1905a49279f..e1905a49279f 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/ethernet/broadcom/b44.h
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 1d9b9858067c..a11a8ad94226 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1398,8 +1398,6 @@ static void bcm_enet_get_ringparam(struct net_device *dev,
/* rx/tx ring is actually only limited by memory */
ering->rx_max_pending = 8192;
ering->tx_max_pending = 8192;
- ering->rx_mini_max_pending = 0;
- ering->rx_jumbo_max_pending = 0;
ering->rx_pending = priv->rx_ring_size;
ering->tx_pending = priv->tx_ring_size;
}
@@ -1603,7 +1601,7 @@ static const struct net_device_ops bcm_enet_ops = {
.ndo_stop = bcm_enet_stop,
.ndo_start_xmit = bcm_enet_start_xmit,
.ndo_set_mac_address = bcm_enet_set_mac_address,
- .ndo_set_multicast_list = bcm_enet_set_multicast_list,
+ .ndo_set_rx_mode = bcm_enet_set_multicast_list,
.ndo_do_ioctl = bcm_enet_ioctl,
.ndo_change_mtu = bcm_enet_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/bcm63xx_enet.h b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
index 0e3048b788c2..0e3048b788c2 100644
--- a/drivers/net/bcm63xx_enet.h
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
diff --git a/drivers/net/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 4b2b57018a02..965c7235804d 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -36,6 +36,7 @@
#include <linux/time.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
+#include <linux/if.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/tcp.h>
@@ -2870,7 +2871,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
dma_unmap_addr(
&txr->tx_buf_ring[TX_RING_IDX(sw_cons)],
mapping),
- skb_shinfo(skb)->frags[i].size,
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
PCI_DMA_TODEVICE);
}
@@ -2929,8 +2930,8 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
shinfo = skb_shinfo(skb);
shinfo->nr_frags--;
- page = shinfo->frags[shinfo->nr_frags].page;
- shinfo->frags[shinfo->nr_frags].page = NULL;
+ page = skb_frag_page(&shinfo->frags[shinfo->nr_frags]);
+ __skb_frag_set_page(&shinfo->frags[shinfo->nr_frags], NULL);
cons_rx_pg->page = page;
dev_kfree_skb(skb);
@@ -3048,9 +3049,8 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
} else {
skb_frag_t *frag =
&skb_shinfo(skb)->frags[i - 1];
- frag->size -= tail;
+ skb_frag_size_sub(frag, tail);
skb->data_len -= tail;
- skb->truesize -= tail;
}
return 0;
}
@@ -3082,7 +3082,7 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
frag_size -= frag_len;
skb->data_len += frag_len;
- skb->truesize += frag_len;
+ skb->truesize += PAGE_SIZE;
skb->len += frag_len;
pg_prod = NEXT_RX_BD(pg_prod);
@@ -3622,7 +3622,7 @@ bnx2_set_rx_mode(struct net_device *dev)
spin_unlock_bh(&bp->phy_lock);
}
-static int __devinit
+static int
check_fw_section(const struct firmware *fw,
const struct bnx2_fw_file_section *section,
u32 alignment, bool non_empty)
@@ -3638,7 +3638,7 @@ check_fw_section(const struct firmware *fw,
return 0;
}
-static int __devinit
+static int
check_mips_fw_entry(const struct firmware *fw,
const struct bnx2_mips_fw_file_entry *entry)
{
@@ -3649,8 +3649,16 @@ check_mips_fw_entry(const struct firmware *fw,
return 0;
}
-static int __devinit
-bnx2_request_firmware(struct bnx2 *bp)
+static void bnx2_release_firmware(struct bnx2 *bp)
+{
+ if (bp->rv2p_firmware) {
+ release_firmware(bp->mips_firmware);
+ release_firmware(bp->rv2p_firmware);
+ bp->rv2p_firmware = NULL;
+ }
+}
+
+static int bnx2_request_uncached_firmware(struct bnx2 *bp)
{
const char *mips_fw_file, *rv2p_fw_file;
const struct bnx2_mips_fw_file *mips_fw;
@@ -3672,13 +3680,13 @@ bnx2_request_firmware(struct bnx2 *bp)
rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev);
if (rc) {
pr_err("Can't load firmware file \"%s\"\n", mips_fw_file);
- return rc;
+ goto out;
}
rc = request_firmware(&bp->rv2p_firmware, rv2p_fw_file, &bp->pdev->dev);
if (rc) {
pr_err("Can't load firmware file \"%s\"\n", rv2p_fw_file);
- return rc;
+ goto err_release_mips_firmware;
}
mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
rv2p_fw = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
@@ -3689,16 +3697,30 @@ bnx2_request_firmware(struct bnx2 *bp)
check_mips_fw_entry(bp->mips_firmware, &mips_fw->tpat) ||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->txp)) {
pr_err("Firmware file \"%s\" is invalid\n", mips_fw_file);
- return -EINVAL;
+ rc = -EINVAL;
+ goto err_release_firmware;
}
if (bp->rv2p_firmware->size < sizeof(*rv2p_fw) ||
check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc1.rv2p, 8, true) ||
check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc2.rv2p, 8, true)) {
pr_err("Firmware file \"%s\" is invalid\n", rv2p_fw_file);
- return -EINVAL;
+ rc = -EINVAL;
+ goto err_release_firmware;
}
+out:
+ return rc;
- return 0;
+err_release_firmware:
+ release_firmware(bp->rv2p_firmware);
+ bp->rv2p_firmware = NULL;
+err_release_mips_firmware:
+ release_firmware(bp->mips_firmware);
+ goto out;
+}
+
+static int bnx2_request_firmware(struct bnx2 *bp)
+{
+ return bp->rv2p_firmware ? 0 : bnx2_request_uncached_firmware(bp);
}
static u32
@@ -5373,7 +5395,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)];
dma_unmap_page(&bp->pdev->dev,
dma_unmap_addr(tx_buf, mapping),
- skb_shinfo(skb)->frags[k].size,
+ skb_frag_size(&skb_shinfo(skb)->frags[k]),
PCI_DMA_TODEVICE);
}
dev_kfree_skb(skb);
@@ -6266,6 +6288,10 @@ bnx2_open(struct net_device *dev)
struct bnx2 *bp = netdev_priv(dev);
int rc;
+ rc = bnx2_request_firmware(bp);
+ if (rc < 0)
+ goto out;
+
netif_carrier_off(dev);
bnx2_set_power_state(bp, PCI_D0);
@@ -6326,8 +6352,8 @@ bnx2_open(struct net_device *dev)
netdev_info(dev, "using MSIX\n");
netif_tx_start_all_queues(dev);
-
- return 0;
+out:
+ return rc;
open_err:
bnx2_napi_disable(bp);
@@ -6335,7 +6361,8 @@ open_err:
bnx2_free_irq(bp);
bnx2_free_mem(bp);
bnx2_del_napi(bp);
- return rc;
+ bnx2_release_firmware(bp);
+ goto out;
}
static void
@@ -6503,15 +6530,15 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_buf->is_gso = skb_is_gso(skb);
for (i = 0; i < last_frag; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
prod = NEXT_TX_BD(prod);
ring_prod = TX_RING_IDX(prod);
txbd = &txr->tx_desc_ring[ring_prod];
- len = frag->size;
- mapping = dma_map_page(&bp->pdev->dev, frag->page, frag->page_offset,
- len, PCI_DMA_TODEVICE);
+ len = skb_frag_size(frag);
+ mapping = skb_frag_dma_map(&bp->pdev->dev, frag, 0, len,
+ DMA_TO_DEVICE);
if (dma_mapping_error(&bp->pdev->dev, mapping))
goto dma_error;
dma_unmap_addr_set(&txr->tx_buf_ring[ring_prod], mapping,
@@ -6567,7 +6594,7 @@ dma_error:
ring_prod = 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_shinfo(skb)->frags[i].size,
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
PCI_DMA_TODEVICE);
}
@@ -7127,11 +7154,9 @@ 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_mini_max_pending = 0;
ering->rx_jumbo_max_pending = MAX_TOTAL_RX_PG_DESC_CNT;
ering->rx_pending = bp->rx_ring_size;
- ering->rx_mini_pending = 0;
ering->rx_jumbo_pending = bp->rx_pg_ring_size;
ering->tx_max_pending = MAX_TX_DESC_CNT;
@@ -8353,10 +8378,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev);
- rc = bnx2_request_firmware(bp);
- if (rc)
- goto error;
-
memcpy(dev->dev_addr, bp->mac_addr, 6);
memcpy(dev->perm_addr, bp->mac_addr, 6);
@@ -8370,6 +8391,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->vlan_features = dev->hw_features;
dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->features |= dev->hw_features;
+ dev->priv_flags |= IFF_UNICAST_FLT;
if ((rc = register_netdev(dev))) {
dev_err(&pdev->dev, "Cannot register net device\n");
@@ -8387,11 +8409,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
error:
- if (bp->mips_firmware)
- release_firmware(bp->mips_firmware);
- if (bp->rv2p_firmware)
- release_firmware(bp->rv2p_firmware);
-
if (bp->regview)
iounmap(bp->regview);
pci_release_regions(pdev);
@@ -8412,11 +8429,6 @@ bnx2_remove_one(struct pci_dev *pdev)
del_timer_sync(&bp->timer);
cancel_work_sync(&bp->reset_task);
- if (bp->mips_firmware)
- release_firmware(bp->mips_firmware);
- if (bp->rv2p_firmware)
- release_firmware(bp->rv2p_firmware);
-
if (bp->regview)
iounmap(bp->regview);
@@ -8427,6 +8439,8 @@ bnx2_remove_one(struct pci_dev *pdev)
bp->flags &= ~BNX2_FLAG_AER_ENABLED;
}
+ bnx2_release_firmware(bp);
+
free_netdev(dev);
pci_release_regions(pdev);
diff --git a/drivers/net/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h
index fc50d4267df8..99d31a7d6aaa 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/ethernet/broadcom/bnx2.h
@@ -5617,7 +5617,7 @@ struct l2_fhdr {
#define BNX2_TXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_TXP_CPU_STATE_SOFT_HALTED (1L<<10)
#define BNX2_TXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_TXP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_TXP_CPU_STATE_INTERRUPT (1L<<12)
#define BNX2_TXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
#define BNX2_TXP_CPU_STATE_INST_FETCH_STALL (1L<<15)
#define BNX2_TXP_CPU_STATE_BLOCKED_READ (1L<<31)
@@ -5712,7 +5712,7 @@ struct l2_fhdr {
#define BNX2_TPAT_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_TPAT_CPU_STATE_SOFT_HALTED (1L<<10)
#define BNX2_TPAT_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_TPAT_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_TPAT_CPU_STATE_INTERRUPT (1L<<12)
#define BNX2_TPAT_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
#define BNX2_TPAT_CPU_STATE_INST_FETCH_STALL (1L<<15)
#define BNX2_TPAT_CPU_STATE_BLOCKED_READ (1L<<31)
@@ -5807,7 +5807,7 @@ struct l2_fhdr {
#define BNX2_RXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_RXP_CPU_STATE_SOFT_HALTED (1L<<10)
#define BNX2_RXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_RXP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_RXP_CPU_STATE_INTERRUPT (1L<<12)
#define BNX2_RXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
#define BNX2_RXP_CPU_STATE_INST_FETCH_STALL (1L<<15)
#define BNX2_RXP_CPU_STATE_BLOCKED_READ (1L<<31)
@@ -5953,7 +5953,7 @@ struct l2_fhdr {
#define BNX2_COM_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_COM_CPU_STATE_SOFT_HALTED (1L<<10)
#define BNX2_COM_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_COM_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_COM_CPU_STATE_INTERRUPT (1L<<12)
#define BNX2_COM_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
#define BNX2_COM_CPU_STATE_INST_FETCH_STALL (1L<<15)
#define BNX2_COM_CPU_STATE_BLOCKED_READ (1L<<31)
@@ -6119,7 +6119,7 @@ struct l2_fhdr {
#define BNX2_CP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_CP_CPU_STATE_SOFT_HALTED (1L<<10)
#define BNX2_CP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_CP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_CP_CPU_STATE_INTERRUPT (1L<<12)
#define BNX2_CP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
#define BNX2_CP_CPU_STATE_INST_FETCH_STALL (1L<<15)
#define BNX2_CP_CPU_STATE_BLOCKED_READ (1L<<31)
@@ -6291,7 +6291,7 @@ struct l2_fhdr {
#define BNX2_MCP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
#define BNX2_MCP_CPU_STATE_SOFT_HALTED (1L<<10)
#define BNX2_MCP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
-#define BNX2_MCP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_MCP_CPU_STATE_INTERRUPT (1L<<12)
#define BNX2_MCP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
#define BNX2_MCP_CPU_STATE_INST_FETCH_STALL (1L<<15)
#define BNX2_MCP_CPU_STATE_BLOCKED_READ (1L<<31)
diff --git a/drivers/net/bnx2_fw.h b/drivers/net/ethernet/broadcom/bnx2_fw.h
index 940eb91f209d..940eb91f209d 100644
--- a/drivers/net/bnx2_fw.h
+++ b/drivers/net/ethernet/broadcom/bnx2_fw.h
diff --git a/drivers/net/bnx2x/Makefile b/drivers/net/ethernet/broadcom/bnx2x/Makefile
index 48fbdd48f88f..48fbdd48f88f 100644
--- a/drivers/net/bnx2x/Makefile
+++ b/drivers/net/ethernet/broadcom/bnx2x/Makefile
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 9a7eb3b36cf3..aec7212ac983 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -23,8 +23,8 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */
-#define DRV_MODULE_VERSION "1.70.00-0"
-#define DRV_MODULE_RELDATE "2011/06/13"
+#define DRV_MODULE_VERSION "1.70.30-0"
+#define DRV_MODULE_RELDATE "2011/10/25"
#define BNX2X_BC_VER 0x040200
#if defined(CONFIG_DCB)
@@ -66,73 +66,68 @@
#define BNX2X_MSG_SP 0x100000 /* was: NETIF_MSG_INTR */
#define BNX2X_MSG_FP 0x200000 /* was: NETIF_MSG_INTR */
-#define DP_LEVEL KERN_NOTICE /* was: KERN_DEBUG */
-
/* regular debug print */
-#define DP(__mask, __fmt, __args...) \
+#define DP(__mask, fmt, ...) \
do { \
if (bp->msg_enable & (__mask)) \
- printk(DP_LEVEL "[%s:%d(%s)]" __fmt, \
- __func__, __LINE__, \
- bp->dev ? (bp->dev->name) : "?", \
- ##__args); \
+ pr_notice("[%s:%d(%s)]" fmt, \
+ __func__, __LINE__, \
+ bp->dev ? (bp->dev->name) : "?", \
+ ##__VA_ARGS__); \
} while (0)
-#define DP_CONT(__mask, __fmt, __args...) \
+#define DP_CONT(__mask, fmt, ...) \
do { \
if (bp->msg_enable & (__mask)) \
- pr_cont(__fmt, ##__args); \
+ pr_cont(fmt, ##__VA_ARGS__); \
} while (0)
/* errors debug print */
-#define BNX2X_DBG_ERR(__fmt, __args...) \
+#define BNX2X_DBG_ERR(fmt, ...) \
do { \
if (netif_msg_probe(bp)) \
- pr_err("[%s:%d(%s)]" __fmt, \
+ pr_err("[%s:%d(%s)]" fmt, \
__func__, __LINE__, \
bp->dev ? (bp->dev->name) : "?", \
- ##__args); \
+ ##__VA_ARGS__); \
} while (0)
/* for errors (never masked) */
-#define BNX2X_ERR(__fmt, __args...) \
+#define BNX2X_ERR(fmt, ...) \
do { \
- pr_err("[%s:%d(%s)]" __fmt, \
+ pr_err("[%s:%d(%s)]" fmt, \
__func__, __LINE__, \
bp->dev ? (bp->dev->name) : "?", \
- ##__args); \
- } while (0)
+ ##__VA_ARGS__); \
+} while (0)
-#define BNX2X_ERROR(__fmt, __args...) do { \
- pr_err("[%s:%d]" __fmt, __func__, __LINE__, ##__args); \
- } while (0)
+#define BNX2X_ERROR(fmt, ...) \
+ pr_err("[%s:%d]" fmt, __func__, __LINE__, ##__VA_ARGS__)
/* before we have a dev->name use dev_info() */
-#define BNX2X_DEV_INFO(__fmt, __args...) \
+#define BNX2X_DEV_INFO(fmt, ...) \
do { \
if (netif_msg_probe(bp)) \
- dev_info(&bp->pdev->dev, __fmt, ##__args); \
+ dev_info(&bp->pdev->dev, fmt, ##__VA_ARGS__); \
} while (0)
-#define BNX2X_MAC_FMT "%pM"
-#define BNX2X_MAC_PRN_LIST(mac) (mac)
-
-
#ifdef BNX2X_STOP_ON_ERROR
void bnx2x_int_disable(struct bnx2x *bp);
-#define bnx2x_panic() do { \
- bp->panic = 1; \
- BNX2X_ERR("driver assert\n"); \
- bnx2x_int_disable(bp); \
- bnx2x_panic_dump(bp); \
- } while (0)
+#define bnx2x_panic() \
+do { \
+ bp->panic = 1; \
+ BNX2X_ERR("driver assert\n"); \
+ bnx2x_int_disable(bp); \
+ bnx2x_panic_dump(bp); \
+} while (0)
#else
-#define bnx2x_panic() do { \
- bp->panic = 1; \
- BNX2X_ERR("driver assert\n"); \
- bnx2x_panic_dump(bp); \
- } while (0)
+#define bnx2x_panic() \
+do { \
+ bp->panic = 1; \
+ BNX2X_ERR("driver assert\n"); \
+ bnx2x_panic_dump(bp); \
+} while (0)
#endif
#define bnx2x_mc_addr(ha) ((ha)->addr)
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index c4cbf9736414..580b44edb066 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -15,6 +15,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
#include <linux/interrupt.h>
@@ -452,7 +454,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
skb_fill_page_desc(skb, j, old_rx_pg.page, 0, frag_len);
skb->data_len += frag_len;
- skb->truesize += frag_len;
+ skb->truesize += SGE_PAGE_SIZE * PAGES_PER_SGE;
skb->len += frag_len;
frag_size -= frag_len;
@@ -954,15 +956,16 @@ void __bnx2x_link_report(struct bnx2x *bp)
netdev_err(bp->dev, "NIC Link is Down\n");
return;
} else {
+ const char *duplex;
+ const char *flow;
+
netif_carrier_on(bp->dev);
- netdev_info(bp->dev, "NIC Link is Up, ");
- pr_cont("%d Mbps ", cur_data.line_speed);
if (test_and_clear_bit(BNX2X_LINK_REPORT_FD,
&cur_data.link_report_flags))
- pr_cont("full duplex");
+ duplex = "full";
else
- pr_cont("half duplex");
+ duplex = "half";
/* Handle the FC at the end so that only these flags would be
* possibly set. This way we may easily check if there is no FC
@@ -971,16 +974,19 @@ void __bnx2x_link_report(struct bnx2x *bp)
if (cur_data.link_report_flags) {
if (test_bit(BNX2X_LINK_REPORT_RX_FC_ON,
&cur_data.link_report_flags)) {
- pr_cont(", receive ");
if (test_bit(BNX2X_LINK_REPORT_TX_FC_ON,
&cur_data.link_report_flags))
- pr_cont("& transmit ");
+ flow = "ON - receive & transmit";
+ else
+ flow = "ON - receive";
} else {
- pr_cont(", transmit ");
+ flow = "ON - transmit";
}
- pr_cont("flow control ON");
+ } else {
+ flow = "none";
}
- pr_cont("\n");
+ netdev_info(bp->dev, "NIC Link is Up, %d Mbps %s duplex, Flow control: %s\n",
+ cur_data.line_speed, duplex, flow);
}
}
@@ -2357,7 +2363,7 @@ static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb,
/* Calculate the first sum - it's special */
for (frag_idx = 0; frag_idx < wnd_size - 1; frag_idx++)
wnd_sum +=
- skb_shinfo(skb)->frags[frag_idx].size;
+ skb_frag_size(&skb_shinfo(skb)->frags[frag_idx]);
/* If there was data on linear skb data - check it */
if (first_bd_sz > 0) {
@@ -2373,14 +2379,14 @@ static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb,
check all windows */
for (wnd_idx = 0; wnd_idx <= num_wnds; wnd_idx++) {
wnd_sum +=
- skb_shinfo(skb)->frags[wnd_idx + wnd_size - 1].size;
+ skb_frag_size(&skb_shinfo(skb)->frags[wnd_idx + wnd_size - 1]);
if (unlikely(wnd_sum < lso_mss)) {
to_copy = 1;
break;
}
wnd_sum -=
- skb_shinfo(skb)->frags[wnd_idx].size;
+ skb_frag_size(&skb_shinfo(skb)->frags[wnd_idx]);
}
} else {
/* in non-LSO too fragmented packet should always
@@ -2601,7 +2607,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
#endif
/* enable this debug print to view the transmission queue being used
- DP(BNX2X_MSG_FP, "indices: txq %d, fp %d, txdata %d",
+ DP(BNX2X_MSG_FP, "indices: txq %d, fp %d, txdata %d\n",
txq_index, fp_index, txdata_index); */
/* locate the fastpath and the txdata */
@@ -2610,7 +2616,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* enable this debug print to view the tranmission details
DP(BNX2X_MSG_FP,"transmitting packet cid %d fp index %d txdata_index %d"
- " tx_data ptr %p fp pointer %p",
+ " tx_data ptr %p fp pointer %p\n",
txdata->cid, fp_index, txdata_index, txdata, fp); */
if (unlikely(bnx2x_tx_avail(bp, txdata) <
@@ -2790,9 +2796,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- mapping = dma_map_page(&bp->pdev->dev, frag->page,
- frag->page_offset, frag->size,
- DMA_TO_DEVICE);
+ mapping = skb_frag_dma_map(&bp->pdev->dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
DP(NETIF_MSG_TX_QUEUED, "Unable to map page - "
@@ -2816,8 +2821,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_data_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
tx_data_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
- tx_data_bd->nbytes = cpu_to_le16(frag->size);
- le16_add_cpu(&pkt_size, frag->size);
+ tx_data_bd->nbytes = cpu_to_le16(skb_frag_size(frag));
+ le16_add_cpu(&pkt_size, skb_frag_size(frag));
nbd++;
DP(NETIF_MSG_TX_QUEUED,
@@ -2927,14 +2932,14 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
/* requested to support too many traffic classes */
if (num_tc > bp->max_cos) {
DP(NETIF_MSG_TX_ERR, "support for too many traffic classes"
- " requested: %d. max supported is %d",
+ " requested: %d. max supported is %d\n",
num_tc, bp->max_cos);
return -EINVAL;
}
/* declare amount of supported traffic classes */
if (netdev_set_num_tc(dev, num_tc)) {
- DP(NETIF_MSG_TX_ERR, "failed to declare %d traffic classes",
+ DP(NETIF_MSG_TX_ERR, "failed to declare %d traffic classes\n",
num_tc);
return -EINVAL;
}
@@ -2942,7 +2947,7 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
/* configure priority to traffic class mapping */
for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) {
netdev_set_prio_tc_map(dev, prio, bp->prio_to_cos[prio]);
- DP(BNX2X_MSG_SP, "mapping priority %d to tc %d",
+ DP(BNX2X_MSG_SP, "mapping priority %d to tc %d\n",
prio, bp->prio_to_cos[prio]);
}
@@ -2951,10 +2956,10 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
This can be used for ets or pfc, and save the effort of setting
up a multio class queue disc or negotiating DCBX with a switch
netdev_set_prio_tc_map(dev, 0, 0);
- DP(BNX2X_MSG_SP, "mapping priority %d to tc %d", 0, 0);
+ DP(BNX2X_MSG_SP, "mapping priority %d to tc %d\n", 0, 0);
for (prio = 1; prio < 16; prio++) {
netdev_set_prio_tc_map(dev, prio, 1);
- DP(BNX2X_MSG_SP, "mapping priority %d to tc %d", prio, 1);
+ DP(BNX2X_MSG_SP, "mapping priority %d to tc %d\n", prio, 1);
} */
/* configure traffic class to transmission queue mapping */
@@ -2962,7 +2967,7 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
count = BNX2X_NUM_ETH_QUEUES(bp);
offset = cos * MAX_TXQS_PER_COS;
netdev_set_tc_queue(dev, cos, count, offset);
- DP(BNX2X_MSG_SP, "mapping tc %d to offset %d count %d",
+ DP(BNX2X_MSG_SP, "mapping tc %d to offset %d count %d\n",
cos, offset, count);
}
@@ -3050,7 +3055,7 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
DP(BNX2X_MSG_SP,
- "freeing tx memory of fp %d cos %d cid %d",
+ "freeing tx memory of fp %d cos %d cid %d\n",
fp_index, cos, txdata->cid);
BNX2X_FREE(txdata->tx_buf_ring);
@@ -3137,7 +3142,7 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
DP(BNX2X_MSG_SP, "allocating tx memory of "
- "fp %d cos %d",
+ "fp %d cos %d\n",
index, cos);
BNX2X_ALLOC(txdata->tx_buf_ring,
@@ -3387,7 +3392,7 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
struct bnx2x *bp = netdev_priv(dev);
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- printk(KERN_ERR "Handling parity error recovery. Try again later\n");
+ pr_err("Handling parity error recovery. Try again later\n");
return -EAGAIN;
}
@@ -3513,7 +3518,7 @@ int bnx2x_resume(struct pci_dev *pdev)
bp = netdev_priv(dev);
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- printk(KERN_ERR "Handling parity error recovery. Try again later\n");
+ pr_err("Handling parity error recovery. Try again later\n");
return -EAGAIN;
}
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 2dc1199239d0..283d663da180 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -522,7 +522,7 @@ void bnx2x_free_mem_bp(struct bnx2x *bp);
*/
int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
-#if defined(BCM_CNIC) && (defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE))
+#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
/**
* bnx2x_fcoe_get_wwn - return the requested WWN value for this port
*
@@ -1289,7 +1289,7 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp,
txdata->txq_index = txq_index;
txdata->tx_cons_sb = tx_cons_sb;
- DP(BNX2X_MSG_SP, "created tx data cid %d, txq %d",
+ DP(BNX2X_MSG_SP, "created tx data cid %d, txq %d\n",
txdata->cid, txdata->txq_index);
}
@@ -1333,7 +1333,7 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
bnx2x_init_txdata(bp, &bnx2x_fcoe(bp, txdata[0]),
fp->cid, FCOE_TXQ_IDX(bp), BNX2X_FCOE_L2_TX_INDEX);
- DP(BNX2X_MSG_SP, "created fcoe tx data (fp index %d)", fp->index);
+ DP(BNX2X_MSG_SP, "created fcoe tx data (fp index %d)\n", fp->index);
/* qZone id equals to FW (per path) client id */
bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
@@ -1481,8 +1481,8 @@ static inline u16 bnx2x_extract_max_cfg(struct bnx2x *bp, u32 mf_cfg)
u16 max_cfg = (mf_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
FUNC_MF_CFG_MAX_BW_SHIFT;
if (!max_cfg) {
- BNX2X_ERR("Illegal configuration detected for Max BW - "
- "using 100 instead\n");
+ DP(NETIF_MSG_LINK,
+ "Max BW configured to 0 - using 100 instead\n");
max_cfg = 100;
}
return max_cfg;
diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
index 0b4acf67e0c6..51bd7485ab18 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
@@ -16,6 +16,9 @@
* Written by: Dmitry Kravkov
*
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/netdevice.h>
#include <linux/types.h>
#include <linux/errno.h>
@@ -350,7 +353,7 @@ static void bnx2x_dcbx_map_nw(struct bnx2x *bp)
if (cos_params[i].pri_bitmask & nw_prio) {
/* extend the bitmask with unmapped */
DP(NETIF_MSG_LINK,
- "cos %d extended with 0x%08x", i, unmapped);
+ "cos %d extended with 0x%08x\n", i, unmapped);
cos_params[i].pri_bitmask |= unmapped;
break;
}
diff --git a/drivers/net/bnx2x/bnx2x_dcb.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h
index 2c6a3bca6f28..2c6a3bca6f28 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h
diff --git a/drivers/net/bnx2x/bnx2x_dump.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h
index b983825d0ee9..b983825d0ee9 100644
--- a/drivers/net/bnx2x/bnx2x_dump.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index cf3e47914dd7..f0ca8b27a55e 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -14,6 +14,9 @@
* Statistics and Link management by Yitchak Gertner
*
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/types.h>
@@ -239,9 +242,9 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->maxrxpkt = 0;
DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
- DP_LEVEL " supported 0x%x advertising 0x%x speed %u\n"
- DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n"
- DP_LEVEL " autoneg %d maxtxpkt %d maxrxpkt %d\n",
+ " supported 0x%x advertising 0x%x speed %u\n"
+ " duplex %d port %d phy_address %d transceiver %d\n"
+ " autoneg %d maxtxpkt %d maxrxpkt %d\n",
cmd->cmd, cmd->supported, cmd->advertising,
ethtool_cmd_speed(cmd),
cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
@@ -326,6 +329,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
break;
case PORT_FIBRE:
+ case PORT_DA:
if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
break; /* no port change */
@@ -519,7 +523,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
}
DP(NETIF_MSG_LINK, "req_line_speed %d\n"
- DP_LEVEL " req_duplex %d advertising 0x%x\n",
+ " req_duplex %d advertising 0x%x\n",
bp->link_params.req_line_speed[cfg_idx],
bp->link_params.req_duplex[cfg_idx],
bp->port.advertising[cfg_idx]);
@@ -1065,7 +1069,7 @@ static int bnx2x_get_eeprom(struct net_device *dev,
return -EAGAIN;
DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
- DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n",
+ " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n",
eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
eeprom->len, eeprom->len);
@@ -1236,7 +1240,7 @@ static int bnx2x_set_eeprom(struct net_device *dev,
return -EAGAIN;
DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
- DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n",
+ " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n",
eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
eeprom->len, eeprom->len);
@@ -1341,17 +1345,12 @@ static void bnx2x_get_ringparam(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);
ering->rx_max_pending = MAX_RX_AVAIL;
- ering->rx_mini_max_pending = 0;
- ering->rx_jumbo_max_pending = 0;
if (bp->rx_ring_size)
ering->rx_pending = bp->rx_ring_size;
else
ering->rx_pending = MAX_RX_AVAIL;
- ering->rx_mini_pending = 0;
- ering->rx_jumbo_pending = 0;
-
ering->tx_max_pending = MAX_TX_AVAIL;
ering->tx_pending = bp->tx_ring_size;
}
@@ -1362,7 +1361,7 @@ static int bnx2x_set_ringparam(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- printk(KERN_ERR "Handling parity error recovery. Try again later\n");
+ pr_err("Handling parity error recovery. Try again later\n");
return -EAGAIN;
}
@@ -1393,7 +1392,7 @@ static void bnx2x_get_pauseparam(struct net_device *dev,
BNX2X_FLOW_CTRL_TX);
DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
- DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n",
+ " autoneg %d rx_pause %d tx_pause %d\n",
epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
}
@@ -1406,7 +1405,7 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
return 0;
DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
- DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n",
+ " autoneg %d rx_pause %d tx_pause %d\n",
epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO;
@@ -2004,7 +2003,7 @@ static void bnx2x_self_test(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);
u8 is_serdes;
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- printk(KERN_ERR "Handling parity error recovery. Try again later\n");
+ pr_err("Handling parity error recovery. Try again later\n");
etest->flags |= ETH_TEST_FL_FAILED;
return;
}
@@ -2272,7 +2271,7 @@ static int bnx2x_set_phys_id(struct net_device *dev,
}
static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
- void *rules __always_unused)
+ u32 *rules __always_unused)
{
struct bnx2x *bp = netdev_priv(dev);
diff --git a/drivers/net/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
index 998652a1b858..998652a1b858 100644
--- a/drivers/net/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
diff --git a/drivers/net/bnx2x/bnx2x_fw_file_hdr.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h
index f4a07fbaed05..f4a07fbaed05 100644
--- a/drivers/net/bnx2x/bnx2x_fw_file_hdr.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h
diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index dc24de40e336..fc754cb6cc0f 100644
--- a/drivers/net/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
@@ -704,6 +704,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833 0x00000d00
#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_FAILURE 0x0000fd00
#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00
@@ -759,6 +760,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833 0x00000d00
#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_DIRECT_WC 0x0000fc00
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00
#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00
@@ -2548,7 +2550,7 @@ struct host_func_stats {
#define BCM_5710_FW_MAJOR_VERSION 7
#define BCM_5710_FW_MINOR_VERSION 0
-#define BCM_5710_FW_REVISION_VERSION 23
+#define BCM_5710_FW_REVISION_VERSION 29
#define BCM_5710_FW_ENGINEERING_VERSION 0
#define BCM_5710_FW_COMPILE_FLAGS 1
diff --git a/drivers/net/bnx2x/bnx2x_init.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
index 4d748e77d1ac..4d748e77d1ac 100644
--- a/drivers/net/bnx2x/bnx2x_init.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
diff --git a/drivers/net/bnx2x/bnx2x_init_ops.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
index 7ec1724753ad..7ec1724753ad 100644
--- a/drivers/net/bnx2x/bnx2x_init_ops.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index ba15bdc5a1a9..bce203fa4b9e 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -45,6 +45,9 @@
#define MCPR_IMC_COMMAND_READ_OP 1
#define MCPR_IMC_COMMAND_WRITE_OP 2
+/* LED Blink rate that will achieve ~15.9Hz */
+#define LED_BLINK_RATE_VAL_E3 354
+#define LED_BLINK_RATE_VAL_E1X_E2 480
/***********************************************************/
/* Shortcut definitions */
/***********************************************************/
@@ -258,6 +261,7 @@
#define MAX_PACKET_SIZE (9700)
#define WC_UC_TIMEOUT 100
+#define MAX_KR_LINK_RETRY 4
/**********************************************************/
/* INTERFACE */
@@ -694,8 +698,8 @@ static int bnx2x_ets_e3b0_disabled(const struct link_params *params,
struct bnx2x *bp = params->bp;
if (!CHIP_IS_E3B0(bp)) {
- DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
- "\n");
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_e3b0_disabled the chip isn't E3B0\n");
return -EINVAL;
}
@@ -860,12 +864,12 @@ static int bnx2x_ets_e3b0_get_total_bw(
/* Check total BW is valid */
if ((100 != *total_bw) || (0 == *total_bw)) {
if (0 == *total_bw) {
- DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW"
- "shouldn't be 0\n");
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_E3B0_config toatl BW shouldn't be 0\n");
return -EINVAL;
}
- DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW should be"
- "100\n");
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_E3B0_config toatl BW should be 100\n");
/**
* We can handle a case whre the BW isn't 100 this can happen
* if the TC are joined.
@@ -902,13 +906,13 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
if (DCBX_INVALID_COS != sp_pri_to_cos[pri]) {
DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
- "parameter There can't be two COS's with"
+ "parameter There can't be two COS's with "
"the same strict pri\n");
return -EINVAL;
}
if (pri > max_num_of_cos) {
- DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid"
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
"parameter Illegal strict priority\n");
return -EINVAL;
}
@@ -1084,8 +1088,8 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
u8 cos_entry = 0;
if (!CHIP_IS_E3B0(bp)) {
- DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
- "\n");
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_e3b0_disabled the chip isn't E3B0\n");
return -EINVAL;
}
@@ -1102,8 +1106,8 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
bnx2x_status = bnx2x_ets_e3b0_get_total_bw(params, ets_params,
&total_bw);
if (0 != bnx2x_status) {
- DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config get_total_bw failed "
- "\n");
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_E3B0_config get_total_bw failed\n");
return -EINVAL;
}
@@ -1138,13 +1142,13 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
cos_entry);
} else {
- DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_config cos state not"
- " valid\n");
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_e3b0_config cos state not valid\n");
return -EINVAL;
}
if (0 != bnx2x_status) {
- DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_config set cos bw "
- "failed\n");
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_e3b0_config set cos bw failed\n");
return bnx2x_status;
}
}
@@ -1154,8 +1158,8 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
sp_pri_to_cos);
if (0 != bnx2x_status) {
- DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config set_pri_cli_reg "
- "failed\n");
+ DP(NETIF_MSG_LINK,
+ "bnx2x_ets_E3B0_config set_pri_cli_reg failed\n");
return bnx2x_status;
}
@@ -1490,6 +1494,18 @@ static void bnx2x_set_xumac_nig(struct link_params *params,
NIG_REG_P0_MAC_PAUSE_OUT_EN, tx_pause_en);
}
+static void bnx2x_umac_disable(struct link_params *params)
+{
+ u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
+ struct bnx2x *bp = params->bp;
+ if (!(REG_RD(bp, MISC_REG_RESET_REG_2) &
+ (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port)))
+ return;
+
+ /* Disable RX and TX */
+ REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, 0);
+}
+
static void bnx2x_umac_enable(struct link_params *params,
struct link_vars *vars, u8 lb)
{
@@ -1599,8 +1615,9 @@ static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
}
/* Define the XMAC mode */
-static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed)
+static void bnx2x_xmac_init(struct link_params *params, u32 max_speed)
{
+ struct bnx2x *bp = params->bp;
u32 is_port4mode = bnx2x_is_4_port_mode(bp);
/**
@@ -1610,10 +1627,11 @@ static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed)
* ports of the path
**/
- if (is_port4mode && (REG_RD(bp, MISC_REG_RESET_REG_2) &
+ if ((CHIP_NUM(bp) == CHIP_NUM_57840) &&
+ (REG_RD(bp, MISC_REG_RESET_REG_2) &
MISC_REGISTERS_RESET_REG_2_XMAC)) {
- DP(NETIF_MSG_LINK, "XMAC already out of reset"
- " in 4-port mode\n");
+ DP(NETIF_MSG_LINK,
+ "XMAC already out of reset in 4-port mode\n");
return;
}
@@ -1636,13 +1654,13 @@ static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed)
/* Set the number of ports on the system side to 1 */
REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 0);
if (max_speed == SPEED_10000) {
- DP(NETIF_MSG_LINK, "Init XMAC to 10G x 1"
- " port per path\n");
+ DP(NETIF_MSG_LINK,
+ "Init XMAC to 10G x 1 port per path\n");
/* Set the number of ports on the Warp Core to 10G */
REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
} else {
- DP(NETIF_MSG_LINK, "Init XMAC to 20G x 2 ports"
- " per path\n");
+ DP(NETIF_MSG_LINK,
+ "Init XMAC to 20G x 2 ports per path\n");
/* Set the number of ports on the Warp Core to 20G */
REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 1);
}
@@ -1677,10 +1695,6 @@ static void bnx2x_xmac_disable(struct link_params *params)
(pfc_ctrl | (1<<1)));
DP(NETIF_MSG_LINK, "Disable XMAC on port %x\n", port);
REG_WR(bp, xmac_base + XMAC_REG_CTRL, 0);
- usleep_range(1000, 1000);
- bnx2x_set_xumac_nig(params, 0, 0);
- REG_WR(bp, xmac_base + XMAC_REG_CTRL,
- XMAC_CTRL_REG_SOFT_RESET);
}
}
@@ -1693,7 +1707,7 @@ static int bnx2x_xmac_enable(struct link_params *params,
xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
- bnx2x_xmac_init(bp, vars->line_speed);
+ bnx2x_xmac_init(params, vars->line_speed);
/*
* This register determines on which events the MAC will assert
@@ -3575,6 +3589,11 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
u16 val16 = 0, lane, bam37 = 0;
struct bnx2x *bp = params->bp;
DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
+
+ /* Disable Autoneg: re-enable it after adv is done. */
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0);
+
/* Check adding advertisement for 1G KX */
if (((vars->line_speed == SPEED_AUTO_NEG) &&
(phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
@@ -3616,9 +3635,6 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL,
0x03f0);
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
- 0x383f);
/* Advertised speeds */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
@@ -3645,19 +3661,22 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
/* Advertise pause */
bnx2x_ext_phy_set_pause(params, phy, vars);
- /* Enable Autoneg */
- bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
- MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1000);
-
- /* Over 1G - AN local device user page 1 */
- bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
+ vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_DIGITAL5_MISC7, &val16);
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_DIGITAL5_MISC7, val16 | 0x100);
+
+ /* Over 1G - AN local device user page 1 */
+ 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, 0x1000);
+
}
static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
@@ -3959,8 +3978,8 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
val16 |= 0x0040;
break;
default:
- DP(NETIF_MSG_LINK, "Speed not supported: 0x%x"
- "\n", phy->req_line_speed);
+ DP(NETIF_MSG_LINK,
+ "Speed not supported: 0x%x\n", phy->req_line_speed);
return;
}
@@ -4092,9 +4111,9 @@ 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",
- cfg_pin);
+ DP(NETIF_MSG_LINK,
+ "ERROR: Invalid cfg pin %x for module detect indication\n",
+ cfg_pin);
return -EINVAL;
}
@@ -4126,6 +4145,85 @@ static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy,
else
return 0;
}
+static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ u16 gp2_status_reg0, lane;
+ struct bnx2x *bp = params->bp;
+
+ lane = bnx2x_get_warpcore_lane(phy, params);
+
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_0,
+ &gp2_status_reg0);
+
+ return (gp2_status_reg0 >> (8+lane)) & 0x1;
+}
+
+static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u32 serdes_net_if;
+ u16 gp_status1 = 0, lnkup = 0, lnkup_kr = 0;
+ u16 lane = bnx2x_get_warpcore_lane(phy, params);
+
+ vars->turn_to_run_wc_rt = vars->turn_to_run_wc_rt ? 0 : 1;
+
+ if (!vars->turn_to_run_wc_rt)
+ return;
+
+ /* return if there is no link partner */
+ if (!(bnx2x_warpcore_get_sigdet(phy, params))) {
+ DP(NETIF_MSG_LINK, "bnx2x_warpcore_get_sigdet false\n");
+ return;
+ }
+
+ if (vars->rx_tx_asic_rst) {
+ serdes_net_if = (REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_hw_config[params->port].default_cfg)) &
+ PORT_HW_CFG_NET_SERDES_IF_MASK);
+
+ switch (serdes_net_if) {
+ case PORT_HW_CFG_NET_SERDES_IF_KR:
+ /* Do we get link yet? */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 0x81d1,
+ &gp_status1);
+ lnkup = (gp_status1 >> (8+lane)) & 0x1;/* 1G */
+ /*10G KR*/
+ lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
+
+ DP(NETIF_MSG_LINK,
+ "gp_status1 0x%x\n", gp_status1);
+
+ if (lnkup_kr || lnkup) {
+ vars->rx_tx_asic_rst = 0;
+ DP(NETIF_MSG_LINK,
+ "link up, rx_tx_asic_rst 0x%x\n",
+ vars->rx_tx_asic_rst);
+ } else {
+ /*reset the lane to see if link comes up.*/
+ bnx2x_warpcore_reset_lane(bp, phy, 1);
+ bnx2x_warpcore_reset_lane(bp, phy, 0);
+
+ /* restart Autoneg */
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
+
+ vars->rx_tx_asic_rst--;
+ DP(NETIF_MSG_LINK, "0x%x retry left\n",
+ vars->rx_tx_asic_rst);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ } /*params->rx_tx_asic_rst*/
+
+}
static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
struct link_params *params,
@@ -4222,8 +4320,9 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
break;
default:
- DP(NETIF_MSG_LINK, "Unsupported Serdes Net Interface "
- "0x%x\n", serdes_net_if);
+ DP(NETIF_MSG_LINK,
+ "Unsupported Serdes Net Interface 0x%x\n",
+ serdes_net_if);
return;
}
}
@@ -5895,7 +5994,13 @@ int bnx2x_set_led(struct link_params *params,
SHARED_HW_CFG_LED_MAC1);
tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
- EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
+ if (params->phy[EXT_PHY1].type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
+ EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp & 0xfff1);
+ else {
+ EMAC_WR(bp, EMAC_REG_EMAC_LED,
+ (tmp | EMAC_LED_OVERRIDE));
+ }
break;
case LED_MODE_OPER:
@@ -5948,17 +6053,33 @@ int bnx2x_set_led(struct link_params *params,
else
REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
hw_led_mode);
+ } else if ((params->phy[EXT_PHY1].type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) &&
+ (mode != LED_MODE_OPER)) {
+ REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
+ tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
+ EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp | 0x3);
} else
- REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
+ REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
+ hw_led_mode);
REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port*4, 0);
/* Set blinking rate to ~15.9Hz */
- REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
- LED_BLINK_RATE_VAL);
+ if (CHIP_IS_E3(bp))
+ REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
+ LED_BLINK_RATE_VAL_E3);
+ else
+ REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
+ LED_BLINK_RATE_VAL_E1X_E2);
REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
port*4, 1);
- tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
- EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp & (~EMAC_LED_OVERRIDE)));
+ if ((params->phy[EXT_PHY1].type !=
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) &&
+ (mode != LED_MODE_OPER)) {
+ tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
+ EMAC_WR(bp, EMAC_REG_EMAC_LED,
+ (tmp & (~EMAC_LED_OVERRIDE)));
+ }
if (CHIP_IS_E1(bp) &&
((speed == SPEED_2500) ||
@@ -6131,8 +6252,8 @@ static int bnx2x_link_initialize(struct link_params *params,
if (phy_index == EXT_PHY2 &&
(bnx2x_phy_selection(params) ==
PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
- DP(NETIF_MSG_LINK, "Not initializing"
- " second phy\n");
+ DP(NETIF_MSG_LINK,
+ "Not initializing second phy\n");
continue;
}
params->phy[phy_index].config_init(
@@ -6217,8 +6338,10 @@ static int bnx2x_update_link_down(struct link_params *params,
MISC_REGISTERS_RESET_REG_2_CLEAR,
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
}
- if (CHIP_IS_E3(bp))
+ if (CHIP_IS_E3(bp)) {
bnx2x_xmac_disable(params);
+ bnx2x_umac_disable(params);
+ }
return 0;
}
@@ -6451,8 +6574,8 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
*/
if (active_external_phy == EXT_PHY1) {
if (params->phy[EXT_PHY2].phy_specific_func) {
- DP(NETIF_MSG_LINK, "Disabling TX on"
- " EXT_PHY2\n");
+ DP(NETIF_MSG_LINK,
+ "Disabling TX on EXT_PHY2\n");
params->phy[EXT_PHY2].phy_specific_func(
&params->phy[EXT_PHY2],
params, DISABLE_TX);
@@ -7345,8 +7468,8 @@ static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
u16 val = 0;
u16 i;
if (byte_cnt > 16) {
- DP(NETIF_MSG_LINK, "Reading from eeprom is"
- " is limited to 0xf\n");
+ DP(NETIF_MSG_LINK,
+ "Reading from eeprom is limited to 0xf\n");
return -EINVAL;
}
/* Set the read command byte count */
@@ -7417,8 +7540,8 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
" addr %d, cnt %d\n",
addr, byte_cnt);*/
if (byte_cnt > 16) {
- DP(NETIF_MSG_LINK, "Reading from eeprom is"
- " is limited to 16 bytes\n");
+ DP(NETIF_MSG_LINK,
+ "Reading from eeprom is limited to 16 bytes\n");
return -EINVAL;
}
@@ -7447,8 +7570,8 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
u16 val, i;
if (byte_cnt > 16) {
- DP(NETIF_MSG_LINK, "Reading from eeprom is"
- " is limited to 0xf\n");
+ DP(NETIF_MSG_LINK,
+ "Reading from eeprom is limited to 0xf\n");
return -EINVAL;
}
@@ -7595,13 +7718,14 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
check_limiting_mode = 1;
} else if (copper_module_type &
SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
- DP(NETIF_MSG_LINK, "Passive Copper"
- " cable detected\n");
+ DP(NETIF_MSG_LINK,
+ "Passive Copper cable detected\n");
*edc_mode =
EDC_MODE_PASSIVE_DAC;
} else {
- DP(NETIF_MSG_LINK, "Unknown copper-cable-"
- "type 0x%x !!!\n", copper_module_type);
+ DP(NETIF_MSG_LINK,
+ "Unknown copper-cable-type 0x%x !!!\n",
+ copper_module_type);
return -EINVAL;
}
break;
@@ -7639,8 +7763,8 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
SFP_EEPROM_OPTIONS_ADDR,
SFP_EEPROM_OPTIONS_SIZE,
options) != 0) {
- DP(NETIF_MSG_LINK, "Failed to read Option"
- " field from module EEPROM\n");
+ DP(NETIF_MSG_LINK,
+ "Failed to read Option field from module EEPROM\n");
return -EINVAL;
}
if ((options[0] & SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
@@ -7681,15 +7805,15 @@ static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) {
/* Use first phy request only in case of non-dual media*/
if (DUAL_MEDIA(params)) {
- DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
- "verification\n");
+ DP(NETIF_MSG_LINK,
+ "FW does not support OPT MDL verification\n");
return -EINVAL;
}
cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL;
} else {
/* No support in OPT MDL detection */
- DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
- "verification\n");
+ DP(NETIF_MSG_LINK,
+ "FW does not support OPT MDL verification\n");
return -EINVAL;
}
@@ -7740,8 +7864,9 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
for (timeout = 0; timeout < 60; timeout++) {
if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
== 0) {
- DP(NETIF_MSG_LINK, "SFP+ module initialization "
- "took %d ms\n", timeout * 5);
+ DP(NETIF_MSG_LINK,
+ "SFP+ module initialization took %d ms\n",
+ timeout * 5);
return 0;
}
msleep(5);
@@ -8510,8 +8635,8 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
/* Set TX PreEmphasis if needed */
if ((params->feature_config_flags &
FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
- DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
- "TX_CTRL2 0x%x\n",
+ DP(NETIF_MSG_LINK,
+ "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
phy->tx_preemphasis[0],
phy->tx_preemphasis[1]);
bnx2x_cl45_write(bp, phy,
@@ -8792,8 +8917,8 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
if (mod_abs & (1<<8)) {
/* Module is absent */
- DP(NETIF_MSG_LINK, "MOD_ABS indication "
- "show module is absent\n");
+ DP(NETIF_MSG_LINK,
+ "MOD_ABS indication show module is absent\n");
phy->media_type = ETH_PHY_NOT_PRESENT;
/*
* 1. Set mod_abs to detect next module
@@ -8820,8 +8945,8 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
} else {
/* Module is present */
- DP(NETIF_MSG_LINK, "MOD_ABS indication "
- "show module is present\n");
+ DP(NETIF_MSG_LINK,
+ "MOD_ABS indication show module is present\n");
/*
* First disable transmitter, and if the module is ok, the
* module_detection will enable it
@@ -8912,8 +9037,9 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
if ((val1 & (1<<8)) == 0) {
if (!CHIP_IS_E1x(bp))
oc_port = BP_PATH(bp) + (params->port << 1);
- DP(NETIF_MSG_LINK, "8727 Power fault has been detected"
- " on port %d\n", oc_port);
+ DP(NETIF_MSG_LINK,
+ "8727 Power fault has been detected on port %d\n",
+ oc_port);
netdev_err(bp->dev, "Error: Power fault on Port %d has"
" been detected and the power to "
"that SFP+ module has been removed"
@@ -9694,8 +9820,8 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
&legacy_status);
- DP(NETIF_MSG_LINK, "Legacy speed status"
- " = 0x%x\n", legacy_status);
+ DP(NETIF_MSG_LINK, "Legacy speed status = 0x%x\n",
+ legacy_status);
link_up = ((legacy_status & (1<<11)) == (1<<11));
if (link_up) {
legacy_speed = (legacy_status & (3<<9));
@@ -9713,9 +9839,10 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
else
vars->duplex = DUPLEX_HALF;
- DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
- " is_duplex_full= %d\n", vars->line_speed,
- (vars->duplex == DUPLEX_FULL));
+ DP(NETIF_MSG_LINK,
+ "Link is up in %dMbps, is_duplex_full= %d\n",
+ vars->line_speed,
+ (vars->duplex == DUPLEX_FULL));
/* Check legacy speed AN resolution */
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD,
@@ -10200,22 +10327,6 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
return 0;
}
-static void bnx2x_54618se_set_link_led(struct bnx2x_phy *phy,
- struct link_params *params, u8 mode)
-{
- struct bnx2x *bp = params->bp;
- DP(NETIF_MSG_LINK, "54618SE set link led (mode=%x)\n", mode);
- switch (mode) {
- case LED_MODE_FRONT_PANEL_OFF:
- case LED_MODE_OFF:
- case LED_MODE_OPER:
- case LED_MODE_ON:
- default:
- break;
- }
- return;
-}
-
static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy,
struct link_params *params)
{
@@ -10290,9 +10401,10 @@ static u8 bnx2x_54618se_read_status(struct bnx2x_phy *phy,
} else /* Should not happen */
vars->line_speed = 0;
- DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
- " is_duplex_full= %d\n", vars->line_speed,
- (vars->duplex == DUPLEX_FULL));
+ DP(NETIF_MSG_LINK,
+ "Link is up in %dMbps, is_duplex_full= %d\n",
+ vars->line_speed,
+ (vars->duplex == DUPLEX_FULL));
/* Check legacy speed AN resolution */
bnx2x_cl22_read(bp, phy,
@@ -10991,7 +11103,7 @@ static struct bnx2x_phy phy_54618se = {
.config_loopback = (config_loopback_t)bnx2x_54618se_config_loopback,
.format_fw_ver = (format_fw_ver_t)NULL,
.hw_reset = (hw_reset_t)NULL,
- .set_link_led = (set_link_led_t)bnx2x_54618se_set_link_led,
+ .set_link_led = (set_link_led_t)NULL,
.phy_specific_func = (phy_specific_func_t)NULL
};
/*****************************************************************/
@@ -11236,6 +11348,7 @@ 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_BCM54616:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
*phy = phy_54618se;
break;
@@ -11336,8 +11449,9 @@ static void bnx2x_phy_def_cfg(struct link_params *params,
dev_info.
port_hw_config[params->port].speed_capability_mask));
}
- DP(NETIF_MSG_LINK, "Default config phy idx %x cfg 0x%x speed_cap_mask"
- " 0x%x\n", phy_index, link_config, phy->speed_cap_mask);
+ DP(NETIF_MSG_LINK,
+ "Default config phy idx %x cfg 0x%x speed_cap_mask 0x%x\n",
+ phy_index, link_config, phy->speed_cap_mask);
phy->req_duplex = DUPLEX_FULL;
switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
@@ -11710,8 +11824,10 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
/* Stop BigMac rx */
if (!CHIP_IS_E3(bp))
bnx2x_bmac_rx_disable(bp, port);
- else
+ else {
bnx2x_xmac_disable(params);
+ bnx2x_umac_disable(params);
+ }
/* disable emac */
if (!CHIP_IS_E3(bp))
REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
@@ -11749,14 +11865,21 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
if (params->phy[INT_PHY].link_reset)
params->phy[INT_PHY].link_reset(
&params->phy[INT_PHY], params);
- /* reset BigMac */
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
- (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
/* disable nig ingress interface */
if (!CHIP_IS_E3(bp)) {
+ /* reset BigMac */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
+ } else {
+ u32 xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+ bnx2x_set_xumac_nig(params, 0, 0);
+ if (REG_RD(bp, MISC_REG_RESET_REG_2) &
+ MISC_REGISTERS_RESET_REG_2_XMAC)
+ REG_WR(bp, xmac_base + XMAC_REG_CTRL,
+ XMAC_CTRL_REG_SOFT_RESET);
}
vars->link_up = 0;
vars->phy_flags = 0;
@@ -12324,11 +12447,6 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u16 phy_idx;
- if (!params) {
- DP(NETIF_MSG_LINK, "Uninitialized params !\n");
- return;
- }
-
for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
bnx2x_set_aer_mmd(params, &params->phy[phy_idx]);
@@ -12337,8 +12455,13 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
}
}
- if (CHIP_IS_E3(bp))
+ if (CHIP_IS_E3(bp)) {
+ struct bnx2x_phy *phy = &params->phy[INT_PHY];
+ bnx2x_set_aer_mmd(params, phy);
bnx2x_check_over_curr(params, vars);
+ bnx2x_warpcore_config_runtime(phy, params, vars);
+ }
+
}
u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index c12db6da213e..2a46e633abe9 100644
--- a/drivers/net/bnx2x/bnx2x_link.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
@@ -303,6 +303,9 @@ struct link_vars {
#define PERIODIC_FLAGS_LINK_EVENT 0x0001
u32 aeu_int_mask;
+ u8 rx_tx_asic_rst;
+ u8 turn_to_run_wc_rt;
+ u16 rsrv2;
};
/***********************************************************/
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 15f800085bb2..6486ab8c8fc8 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -15,6 +15,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -37,6 +39,7 @@
#include <linux/time.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
+#include <linux/if.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/ipv6.h>
@@ -350,17 +353,15 @@ static void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae,
default:
if (src_type == DMAE_CMD_SRC_PCI)
DP(msglvl, "DMAE: opcode 0x%08x\n"
- DP_LEVEL "src_addr [%x:%08x] len [%d * 4] "
- "dst_addr [none]\n"
- DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n",
+ "src_addr [%x:%08x] len [%d * 4] dst_addr [none]\n"
+ "comp_addr [%x:%08x] comp_val 0x%08x\n",
dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
dmae->comp_val);
else
DP(msglvl, "DMAE: opcode 0x%08x\n"
- DP_LEVEL "src_addr [%08x] len [%d * 4] "
- "dst_addr [none]\n"
- DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n",
+ "src_addr [%08x] len [%d * 4] dst_addr [none]\n"
+ "comp_addr [%x:%08x] comp_val 0x%08x\n",
dmae->opcode, dmae->src_addr_lo >> 2,
dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
dmae->comp_val);
@@ -789,18 +790,15 @@ void bnx2x_panic_dump(struct bnx2x *bp)
BNX2X_ERR(" def (");
for (i = 0; i < HC_SP_SB_MAX_INDICES; i++)
pr_cont("0x%x%s",
- bp->def_status_blk->sp_sb.index_values[i],
- (i == HC_SP_SB_MAX_INDICES - 1) ? ") " : " ");
+ bp->def_status_blk->sp_sb.index_values[i],
+ (i == HC_SP_SB_MAX_INDICES - 1) ? ") " : " ");
for (i = 0; i < sizeof(struct hc_sp_status_block_data)/sizeof(u32); i++)
*((u32 *)&sp_sb_data + i) = REG_RD(bp, BAR_CSTRORM_INTMEM +
CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
i*sizeof(u32));
- pr_cont("igu_sb_id(0x%x) igu_seg_id(0x%x) "
- "pf_id(0x%x) vnic_id(0x%x) "
- "vf_id(0x%x) vf_valid (0x%x) "
- "state(0x%x)\n",
+ pr_cont("igu_sb_id(0x%x) igu_seg_id(0x%x) pf_id(0x%x) vnic_id(0x%x) vf_id(0x%x) vf_valid (0x%x) state(0x%x)\n",
sp_sb_data.igu_sb_id,
sp_sb_data.igu_seg_id,
sp_sb_data.p_func.pf_id,
@@ -3741,9 +3739,7 @@ static inline void bnx2x_clear_load_cnt(struct bnx2x *bp)
static inline void _print_next_block(int idx, const char *blk)
{
- if (idx)
- pr_cont(", ");
- pr_cont("%s", blk);
+ pr_cont("%s%s", idx ? ", " : "", blk);
}
static inline int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
@@ -4357,8 +4353,6 @@ static inline void bnx2x_handle_classification_eqe(struct bnx2x *bp,
vlan_mac_obj = &bp->fp[cid].mac_obj;
break;
- vlan_mac_obj = &bp->fp[cid].mac_obj;
-
case BNX2X_FILTER_MCAST_PENDING:
/* This is only relevant for 57710 where multicast MACs are
* configured as unicast MACs using the same ramrod.
@@ -4408,7 +4402,7 @@ static inline void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
static inline struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj(
struct bnx2x *bp, u32 cid)
{
- DP(BNX2X_MSG_SP, "retrieving fp from cid %d", cid);
+ DP(BNX2X_MSG_SP, "retrieving fp from cid %d\n", cid);
#ifdef BCM_CNIC
if (cid == BNX2X_FCOE_ETH_CID)
return &bnx2x_fcoe(bp, q_obj);
@@ -7243,7 +7237,7 @@ static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp,
/* set maximum number of COSs supported by this queue */
init_params->max_cos = fp->max_cos;
- DP(BNX2X_MSG_SP, "fp: %d setting queue params max cos to: %d",
+ DP(BNX2X_MSG_SP, "fp: %d setting queue params max cos to: %d\n",
fp->index, init_params->max_cos);
/* set the context pointers queue object */
@@ -7276,7 +7270,7 @@ int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
DP(BNX2X_MSG_SP, "preparing to send tx-only ramrod for connection:"
"cos %d, primary cid %d, cid %d, "
- "client id %d, sp-client id %d, flags %lx",
+ "client id %d, sp-client id %d, flags %lx\n",
tx_index, q_params->q_obj->cids[FIRST_TX_COS_INDEX],
q_params->q_obj->cids[tx_index], q_params->q_obj->cl_id,
tx_only_params->gen_params.spcl_id, tx_only_params->flags);
@@ -7308,7 +7302,7 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
int rc;
u8 tx_index;
- DP(BNX2X_MSG_SP, "setting up queue %d", fp->index);
+ DP(BNX2X_MSG_SP, "setting up queue %d\n", fp->index);
/* reset IGU state skip FCoE L2 queue */
if (!IS_FCOE_FP(fp))
@@ -7332,7 +7326,7 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
return rc;
}
- DP(BNX2X_MSG_SP, "init complete");
+ DP(BNX2X_MSG_SP, "init complete\n");
/* Now move the Queue to the SETUP state... */
@@ -7386,7 +7380,7 @@ static int bnx2x_stop_queue(struct bnx2x *bp, int index)
struct bnx2x_queue_state_params q_params = {0};
int rc, tx_index;
- DP(BNX2X_MSG_SP, "stopping queue %d cid %d", index, fp->cid);
+ DP(BNX2X_MSG_SP, "stopping queue %d cid %d\n", index, fp->cid);
q_params.q_obj = &fp->q_obj;
/* We want to wait for completion in this context */
@@ -7401,7 +7395,7 @@ static int bnx2x_stop_queue(struct bnx2x *bp, int index)
/* ascertain this is a normal queue*/
txdata = &fp->txdata[tx_index];
- DP(BNX2X_MSG_SP, "stopping tx-only queue %d",
+ DP(BNX2X_MSG_SP, "stopping tx-only queue %d\n",
txdata->txq_index);
/* send halt terminate on tx-only connection */
@@ -9391,9 +9385,8 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
val = MF_CFG_RD(bp, func_ext_config[func].
iscsi_mac_addr_lower);
bnx2x_set_mac_buf(iscsi_mac, val, val2);
- BNX2X_DEV_INFO("Read iSCSI MAC: "
- BNX2X_MAC_FMT"\n",
- BNX2X_MAC_PRN_LIST(iscsi_mac));
+ BNX2X_DEV_INFO("Read iSCSI MAC: %pM\n",
+ iscsi_mac);
} else
bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
@@ -9403,9 +9396,8 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
val = MF_CFG_RD(bp, func_ext_config[func].
fcoe_mac_addr_lower);
bnx2x_set_mac_buf(fip_mac, val, val2);
- BNX2X_DEV_INFO("Read FCoE L2 MAC to "
- BNX2X_MAC_FMT"\n",
- BNX2X_MAC_PRN_LIST(fip_mac));
+ BNX2X_DEV_INFO("Read FCoE L2 MAC to %pM\n",
+ fip_mac);
} else
bp->flags |= NO_FCOE_FLAG;
@@ -9460,9 +9452,9 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
if (!is_valid_ether_addr(bp->dev->dev_addr))
dev_err(&bp->pdev->dev,
"bad Ethernet MAC address configuration: "
- BNX2X_MAC_FMT", change it manually before bringing up "
+ "%pM, change it manually before bringing up "
"the appropriate network interface\n",
- BNX2X_MAC_PRN_LIST(bp->dev->dev_addr));
+ bp->dev->dev_addr);
}
static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
@@ -10366,9 +10358,11 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->netdev_ops = &bnx2x_netdev_ops;
bnx2x_set_ethtool_ops(dev);
+ dev->priv_flags |= IFF_UNICAST_FLT;
+
dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
- NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
- NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_HW_VLAN_TX;
+ NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_LRO |
+ NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_HW_VLAN_TX;
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
@@ -10799,7 +10793,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
return rc;
}
- DP(NETIF_MSG_DRV, "max_non_def_sbs %d", max_non_def_sbs);
+ DP(NETIF_MSG_DRV, "max_non_def_sbs %d\n", max_non_def_sbs);
rc = bnx2x_init_bp(bp);
if (rc)
@@ -10854,15 +10848,14 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
- netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx,"
- " IRQ %d, ", board_info[ent->driver_data].name,
- (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
- pcie_width,
- ((!CHIP_IS_E2(bp) && pcie_speed == 2) ||
- (CHIP_IS_E2(bp) && pcie_speed == 1)) ?
- "5GHz (Gen2)" : "2.5GHz",
- dev->base_addr, bp->pdev->irq);
- pr_cont("node addr %pM\n", dev->dev_addr);
+ netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n",
+ board_info[ent->driver_data].name,
+ (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
+ pcie_width,
+ ((!CHIP_IS_E2(bp) && pcie_speed == 2) ||
+ (CHIP_IS_E2(bp) && pcie_speed == 1)) ?
+ "5GHz (Gen2)" : "2.5GHz",
+ dev->base_addr, bp->pdev->irq, dev->dev_addr);
return 0;
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index fc7bd0f23c0b..fc7bd0f23c0b 100644
--- a/drivers/net/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index df52f110c6c5..0440425c83d6 100644
--- a/drivers/net/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -16,6 +16,9 @@
* Written by: Vladislav Zolotarov
*
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/crc32.h>
#include <linux/netdevice.h>
@@ -707,9 +710,8 @@ static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_MAC,
&rule_entry->mac.header);
- DP(BNX2X_MSG_SP, "About to %s MAC "BNX2X_MAC_FMT" for "
- "Queue %d\n", (add ? "add" : "delete"),
- BNX2X_MAC_PRN_LIST(mac), raw->cl_id);
+ DP(BNX2X_MSG_SP, "About to %s MAC %pM for Queue %d\n",
+ add ? "add" : "delete", mac, raw->cl_id);
/* Set a MAC itself */
bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
@@ -801,9 +803,9 @@ static inline void bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x *bp,
bnx2x_vlan_mac_set_cfg_entry_e1x(bp, o, add, opcode, mac, vlan_id,
cfg_entry);
- DP(BNX2X_MSG_SP, "%s MAC "BNX2X_MAC_FMT" CLID %d CAM offset %d\n",
- (add ? "setting" : "clearing"),
- BNX2X_MAC_PRN_LIST(mac), raw->cl_id, cam_offset);
+ DP(BNX2X_MSG_SP, "%s MAC %pM CLID %d CAM offset %d\n",
+ add ? "setting" : "clearing",
+ mac, raw->cl_id, cam_offset);
}
/**
@@ -2579,9 +2581,8 @@ static inline void bnx2x_mcast_hdl_pending_add_e2(struct bnx2x *bp,
cnt++;
- DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
- " mcast MAC\n",
- BNX2X_MAC_PRN_LIST(pmac_pos->mac));
+ DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
+ pmac_pos->mac);
list_del(&pmac_pos->link);
@@ -2702,9 +2703,8 @@ static inline void bnx2x_mcast_hdl_add(struct bnx2x *bp,
cnt++;
- DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
- " mcast MAC\n",
- BNX2X_MAC_PRN_LIST(mlist_pos->mac));
+ DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
+ mlist_pos->mac);
}
*line_idx = cnt;
@@ -2998,9 +2998,8 @@ static inline void bnx2x_mcast_hdl_add_e1h(struct bnx2x *bp,
bit = bnx2x_mcast_bin_from_mac(mlist_pos->mac);
BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
- DP(BNX2X_MSG_SP, "About to configure "
- BNX2X_MAC_FMT" mcast MAC, bin %d\n",
- BNX2X_MAC_PRN_LIST(mlist_pos->mac), bit);
+ DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC, bin %d\n",
+ mlist_pos->mac, bit);
/* bookkeeping... */
BIT_VEC64_SET_BIT(o->registry.aprox_match.vec,
@@ -3049,8 +3048,8 @@ static int bnx2x_mcast_setup_e1h(struct bnx2x *bp,
break;
case BNX2X_MCAST_CMD_DEL:
- DP(BNX2X_MSG_SP, "Invalidating multicast "
- "MACs configuration\n");
+ DP(BNX2X_MSG_SP,
+ "Invalidating multicast MACs configuration\n");
/* clear the registry */
memset(o->registry.aprox_match.vec, 0,
@@ -3233,9 +3232,8 @@ static inline int bnx2x_mcast_handle_restore_cmd_e1(
i++;
- DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
- " mcast MAC\n",
- BNX2X_MAC_PRN_LIST(cfg_data.mac));
+ DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
+ cfg_data.mac);
}
*rdata_idx = i;
@@ -3270,9 +3268,8 @@ static inline int bnx2x_mcast_handle_pending_cmds_e1(
cnt++;
- DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
- " mcast MAC\n",
- BNX2X_MAC_PRN_LIST(pmac_pos->mac));
+ DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n",
+ pmac_pos->mac);
}
break;
@@ -3357,9 +3354,8 @@ static inline int bnx2x_mcast_refresh_registry_e1(struct bnx2x *bp,
&data->config_table[i].middle_mac_addr,
&data->config_table[i].lsb_mac_addr,
elem->mac);
- DP(BNX2X_MSG_SP, "Adding registry entry for ["
- BNX2X_MAC_FMT"]\n",
- BNX2X_MAC_PRN_LIST(elem->mac));
+ DP(BNX2X_MSG_SP, "Adding registry entry for [%pM]\n",
+ elem->mac);
list_add_tail(&elem->link,
&o->registry.exact_match.macs);
}
@@ -4246,7 +4242,7 @@ static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_state);
if (o->next_tx_only) /* print num tx-only if any exist */
- DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d",
+ DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d\n",
o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only);
o->state = o->next_state;
@@ -4308,7 +4304,7 @@ static void bnx2x_q_fill_init_general_data(struct bnx2x *bp,
test_bit(BNX2X_Q_FLG_FCOE, flags) ?
LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
- DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d",
+ DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d\n",
gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg);
}
@@ -4461,7 +4457,7 @@ static void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp,
&data->tx,
&cmd_params->params.tx_only.flags);
- DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x",cmd_params->q_obj->cids[0],
+ DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x\n",cmd_params->q_obj->cids[0],
data->tx.tx_bd_page_base.lo, data->tx.tx_bd_page_base.hi);
}
@@ -4508,9 +4504,9 @@ static inline int bnx2x_q_init(struct bnx2x *bp,
/* Set CDU context validation values */
for (cos = 0; cos < o->max_cos; cos++) {
- DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d",
+ DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d\n",
o->cids[cos], cos);
- DP(BNX2X_MSG_SP, "context pointer %p", init->cxts[cos]);
+ DP(BNX2X_MSG_SP, "context pointer %p\n", init->cxts[cos]);
bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]);
}
@@ -4599,7 +4595,7 @@ static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
return -EINVAL;
}
- DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d",
+ DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d\n",
tx_only_params->gen_params.cos,
tx_only_params->gen_params.spcl_id);
@@ -4610,7 +4606,7 @@ static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
bnx2x_q_fill_setup_tx_only(bp, params, rdata);
DP(BNX2X_MSG_SP, "sending tx-only ramrod: cid %d, client-id %d,"
- "sp-client id %d, cos %d",
+ "sp-client id %d, cos %d\n",
o->cids[cid_index],
rdata->general.client_id,
rdata->general.sp_client_id, rdata->general.cos);
@@ -5167,8 +5163,9 @@ static inline int bnx2x_func_state_change_comp(struct bnx2x *bp,
return -EINVAL;
}
- DP(BNX2X_MSG_SP, "Completing command %d for func %d, setting state to "
- "%d\n", cmd, BP_FUNC(bp), o->next_state);
+ DP(BNX2X_MSG_SP,
+ "Completing command %d for func %d, setting state to %d\n",
+ cmd, BP_FUNC(bp), o->next_state);
o->state = o->next_state;
o->next_state = BNX2X_F_STATE_MAX;
diff --git a/drivers/net/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index 9a517c2e9f1b..9a517c2e9f1b 100644
--- a/drivers/net/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
index 9908f2bbcf73..02ac6a771bf9 100644
--- a/drivers/net/bnx2x/bnx2x_stats.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
@@ -14,6 +14,9 @@
* Statistics and Link management by Yitchak Gertner
*
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include "bnx2x_stats.h"
#include "bnx2x_cmn.h"
@@ -1195,14 +1198,13 @@ static void bnx2x_stats_update(struct bnx2x *bp)
struct bnx2x_fastpath *fp = &bp->fp[i];
struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
- printk(KERN_DEBUG "%s: rx usage(%4u) *rx_cons_sb(%u)"
- " rx pkt(%lu) rx calls(%lu %lu)\n",
- fp->name, (le16_to_cpu(*fp->rx_cons_sb) -
- fp->rx_comp_cons),
- le16_to_cpu(*fp->rx_cons_sb),
- bnx2x_hilo(&qstats->
- total_unicast_packets_received_hi),
- fp->rx_calls, fp->rx_pkt);
+ pr_debug("%s: rx usage(%4u) *rx_cons_sb(%u) rx pkt(%lu) rx calls(%lu %lu)\n",
+ fp->name, (le16_to_cpu(*fp->rx_cons_sb) -
+ fp->rx_comp_cons),
+ le16_to_cpu(*fp->rx_cons_sb),
+ bnx2x_hilo(&qstats->
+ total_unicast_packets_received_hi),
+ fp->rx_calls, fp->rx_pkt);
}
for_each_eth_queue(bp, i) {
@@ -1211,27 +1213,25 @@ static void bnx2x_stats_update(struct bnx2x *bp)
struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
struct netdev_queue *txq;
- printk(KERN_DEBUG "%s: tx pkt(%lu) (Xoff events %u)",
- fp->name, bnx2x_hilo(
- &qstats->total_unicast_packets_transmitted_hi),
- qstats->driver_xoff);
+ pr_debug("%s: tx pkt(%lu) (Xoff events %u)",
+ fp->name,
+ bnx2x_hilo(
+ &qstats->total_unicast_packets_transmitted_hi),
+ qstats->driver_xoff);
for_each_cos_in_tx_queue(fp, cos) {
txdata = &fp->txdata[cos];
txq = netdev_get_tx_queue(bp->dev,
FP_COS_TO_TXQ(fp, cos));
- printk(KERN_DEBUG "%d: tx avail(%4u)"
- " *tx_cons_sb(%u)"
- " tx calls (%lu)"
- " %s\n",
- cos,
- bnx2x_tx_avail(bp, txdata),
- le16_to_cpu(*txdata->tx_cons_sb),
- txdata->tx_pkt,
- (netif_tx_queue_stopped(txq) ?
- "Xoff" : "Xon")
- );
+ pr_debug("%d: tx avail(%4u) *tx_cons_sb(%u) tx calls (%lu) %s\n",
+ cos,
+ bnx2x_tx_avail(bp, txdata),
+ le16_to_cpu(*txdata->tx_cons_sb),
+ txdata->tx_pkt,
+ (netif_tx_queue_stopped(txq) ?
+ "Xoff" : "Xon")
+ );
}
}
}
diff --git a/drivers/net/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
index 5d8ce2f6afef..5d8ce2f6afef 100644
--- a/drivers/net/bnx2x/bnx2x_stats.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
diff --git a/drivers/net/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index 94a2e541006d..6f10c6939834 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -45,8 +45,8 @@
#include "bnx2x/bnx2x_reg.h"
#include "bnx2x/bnx2x_fw_defs.h"
#include "bnx2x/bnx2x_hsi.h"
-#include "../scsi/bnx2i/57xx_iscsi_constants.h"
-#include "../scsi/bnx2i/57xx_iscsi_hsi.h"
+#include "../../../scsi/bnx2i/57xx_iscsi_constants.h"
+#include "../../../scsi/bnx2i/57xx_iscsi_hsi.h"
#include "cnic.h"
#include "cnic_defs.h"
@@ -1177,7 +1177,7 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ;
if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
- cp->max_cid_space += BNX2X_FCOE_NUM_CONNECTIONS;
+ cp->max_cid_space += dev->max_fcoe_conn;
cp->fcoe_init_cid = ethdev->fcoe_init_cid;
if (!cp->fcoe_init_cid)
cp->fcoe_init_cid = 0x10;
@@ -1875,12 +1875,12 @@ static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid)
hw_cid, NONE_CONNECTION_TYPE, &l5_data);
if (ret == 0) {
- wait_event(ctx->waitq, ctx->wait_cond);
+ wait_event_timeout(ctx->waitq, ctx->wait_cond, CNIC_RAMROD_TMO);
if (unlikely(test_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags)))
return -EBUSY;
}
- return ret;
+ return 0;
}
static int cnic_bnx2x_iscsi_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
@@ -2280,7 +2280,7 @@ static int cnic_bnx2x_fcoe_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
*work = 4;
l5_cid = req1->fcoe_conn_id;
- if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
+ if (l5_cid >= dev->max_fcoe_conn)
goto err_reply;
l5_cid += BNX2X_FCOE_L5_CID_BASE;
@@ -2384,7 +2384,7 @@ static int cnic_bnx2x_fcoe_disable(struct cnic_dev *dev, struct kwqe *kwqe)
req = (struct fcoe_kwqe_conn_enable_disable *) kwqe;
cid = req->context_id;
l5_cid = req->conn_id;
- if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
+ if (l5_cid >= dev->max_fcoe_conn)
return -EINVAL;
l5_cid += BNX2X_FCOE_L5_CID_BASE;
@@ -2418,7 +2418,7 @@ static int cnic_bnx2x_fcoe_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
req = (struct fcoe_kwqe_conn_destroy *) kwqe;
cid = req->context_id;
l5_cid = req->conn_id;
- if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
+ if (l5_cid >= dev->max_fcoe_conn)
return -EINVAL;
l5_cid += BNX2X_FCOE_L5_CID_BASE;
@@ -2428,17 +2428,20 @@ static int cnic_bnx2x_fcoe_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
init_waitqueue_head(&ctx->waitq);
ctx->wait_cond = 0;
+ memset(&kcqe, 0, sizeof(kcqe));
+ kcqe.completion_status = FCOE_KCQE_COMPLETION_STATUS_ERROR;
memset(&l5_data, 0, sizeof(l5_data));
ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_TERMINATE_CONN, cid,
FCOE_CONNECTION_TYPE, &l5_data);
if (ret == 0) {
- wait_event(ctx->waitq, ctx->wait_cond);
- set_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags);
- queue_delayed_work(cnic_wq, &cp->delete_task,
- msecs_to_jiffies(2000));
+ wait_event_timeout(ctx->waitq, ctx->wait_cond, CNIC_RAMROD_TMO);
+ if (ctx->wait_cond)
+ kcqe.completion_status = 0;
}
- memset(&kcqe, 0, sizeof(kcqe));
+ set_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags);
+ queue_delayed_work(cnic_wq, &cp->delete_task, msecs_to_jiffies(2000));
+
kcqe.op_code = FCOE_KCQE_OPCODE_DESTROY_CONN;
kcqe.fcoe_conn_id = req->conn_id;
kcqe.fcoe_conn_context_id = cid;
@@ -4850,8 +4853,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
return -ENOMEM;
if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
- ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl,
- BNX2X_FCOE_NUM_CONNECTIONS,
+ ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl, dev->max_fcoe_conn,
cp->fcoe_start_cid, 0);
if (ret)
@@ -5292,6 +5294,9 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
!(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE))
cdev->max_fcoe_conn = ethdev->max_fcoe_conn;
+ if (cdev->max_fcoe_conn > BNX2X_FCOE_NUM_CONNECTIONS)
+ cdev->max_fcoe_conn = BNX2X_FCOE_NUM_CONNECTIONS;
+
memcpy(cdev->mac_addr, ethdev->iscsi_mac, 6);
cp->cnic_ops = &cnic_bnx2x_ops;
diff --git a/drivers/net/cnic.h b/drivers/net/ethernet/broadcom/cnic.h
index 7a2928f82d40..30328097f516 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/ethernet/broadcom/cnic.h
@@ -373,7 +373,7 @@ struct bnx2x_bd_chain_next {
#define BNX2X_ISCSI_PBL_NOT_CACHED 0xff
#define BNX2X_ISCSI_PDU_HEADER_NOT_CACHED 0xff
-#define BNX2X_FCOE_NUM_CONNECTIONS 128
+#define BNX2X_FCOE_NUM_CONNECTIONS 1024
#define BNX2X_FCOE_L5_CID_BASE MAX_ISCSI_TBL_SZ
@@ -474,5 +474,7 @@ struct bnx2x_bd_chain_next {
MAX_STAT_COUNTER_ID_E1))
#endif
+#define CNIC_RAMROD_TMO (HZ / 4)
+
#endif
diff --git a/drivers/net/cnic_defs.h b/drivers/net/ethernet/broadcom/cnic_defs.h
index e47d21076767..239de898f071 100644
--- a/drivers/net/cnic_defs.h
+++ b/drivers/net/ethernet/broadcom/cnic_defs.h
@@ -67,6 +67,7 @@
#define FCOE_KWQE_OPCODE_DESTROY (10)
#define FCOE_KWQE_OPCODE_STAT (11)
+#define FCOE_KCQE_COMPLETION_STATUS_ERROR (0x1)
#define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE (0x3)
/* KCQ (kernel completion queue) response op codes */
diff --git a/drivers/net/cnic_if.h b/drivers/net/ethernet/broadcom/cnic_if.h
index 79443e0dbf96..79443e0dbf96 100644
--- a/drivers/net/cnic_if.h
+++ b/drivers/net/ethernet/broadcom/cnic_if.h
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c
index ea65f7ec360a..0a1d7f279fc8 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/ethernet/broadcom/sb1250-mac.c
@@ -2176,7 +2176,7 @@ static const struct net_device_ops sbmac_netdev_ops = {
.ndo_open = sbmac_open,
.ndo_stop = sbmac_close,
.ndo_start_xmit = sbmac_start_tx,
- .ndo_set_multicast_list = sbmac_set_rx_mode,
+ .ndo_set_rx_mode = sbmac_set_rx_mode,
.ndo_tx_timeout = sbmac_tx_timeout,
.ndo_do_ioctl = sbmac_mii_ioctl,
.ndo_change_mtu = sb1250_change_mtu,
diff --git a/drivers/net/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index c11a2b8327f3..161cbbb4814a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -89,12 +89,15 @@ 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 119
+#define TG3_MIN_NUM 120
#define DRV_MODULE_VERSION \
__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE "May 18, 2011"
+#define DRV_MODULE_RELDATE "August 18, 2011"
+
+#define RESET_KIND_SHUTDOWN 0
+#define RESET_KIND_INIT 1
+#define RESET_KIND_SUSPEND 2
-#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
#define TG3_DEF_TX_MODE 0
#define TG3_DEF_MSG_ENABLE \
@@ -188,6 +191,12 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
#define TG3_RX_COPY_THRESH(tp) ((tp)->rx_copy_thresh)
#endif
+#if (NET_IP_ALIGN != 0)
+#define TG3_RX_OFFSET(tp) ((tp)->rx_offset)
+#else
+#define TG3_RX_OFFSET(tp) 0
+#endif
+
/* minimum number of free TX descriptors required to wake up TX process */
#define TG3_TX_WAKEUP_THRESH(tnapi) ((tnapi)->tx_pending / 4)
#define TG3_TX_BD_DMA_MAX 4096
@@ -391,12 +400,14 @@ static const struct {
static const struct {
const char string[ETH_GSTRING_LEN];
} ethtool_test_keys[] = {
- { "nvram test (online) " },
- { "link test (online) " },
- { "register test (offline)" },
- { "memory test (offline)" },
- { "loopback test (offline)" },
- { "interrupt test (offline)" },
+ { "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)" },
};
#define TG3_NUM_TEST ARRAY_SIZE(ethtool_test_keys)
@@ -717,6 +728,103 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
tg3_ape_write32(tp, gnt + 4 * locknum, bit);
}
+static void tg3_ape_send_event(struct tg3 *tp, u32 event)
+{
+ int i;
+ u32 apedata;
+
+ /* NCSI does not support APE events */
+ if (tg3_flag(tp, APE_HAS_NCSI))
+ return;
+
+ apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
+ if (apedata != APE_SEG_SIG_MAGIC)
+ return;
+
+ apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
+ if (!(apedata & APE_FW_STATUS_READY))
+ return;
+
+ /* Wait for up to 1 millisecond for APE to service previous event. */
+ for (i = 0; i < 10; i++) {
+ if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM))
+ return;
+
+ apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
+
+ if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+ tg3_ape_write32(tp, TG3_APE_EVENT_STATUS,
+ event | APE_EVENT_STATUS_EVENT_PENDING);
+
+ tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
+
+ if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+ break;
+
+ udelay(100);
+ }
+
+ if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+ tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
+}
+
+static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
+{
+ u32 event;
+ u32 apedata;
+
+ if (!tg3_flag(tp, ENABLE_APE))
+ return;
+
+ switch (kind) {
+ case RESET_KIND_INIT:
+ tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG,
+ APE_HOST_SEG_SIG_MAGIC);
+ tg3_ape_write32(tp, TG3_APE_HOST_SEG_LEN,
+ APE_HOST_SEG_LEN_MAGIC);
+ apedata = tg3_ape_read32(tp, TG3_APE_HOST_INIT_COUNT);
+ tg3_ape_write32(tp, TG3_APE_HOST_INIT_COUNT, ++apedata);
+ tg3_ape_write32(tp, TG3_APE_HOST_DRIVER_ID,
+ APE_HOST_DRIVER_ID_MAGIC(TG3_MAJ_NUM, TG3_MIN_NUM));
+ tg3_ape_write32(tp, TG3_APE_HOST_BEHAVIOR,
+ APE_HOST_BEHAV_NO_PHYLOCK);
+ tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE,
+ TG3_APE_HOST_DRVR_STATE_START);
+
+ event = APE_EVENT_STATUS_STATE_START;
+ break;
+ case RESET_KIND_SHUTDOWN:
+ /* With the interface we are currently using,
+ * APE does not track driver state. Wiping
+ * out the HOST SEGMENT SIGNATURE forces
+ * the APE to assume OS absent status.
+ */
+ tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);
+
+ if (device_may_wakeup(&tp->pdev->dev) &&
+ tg3_flag(tp, WOL_ENABLE)) {
+ tg3_ape_write32(tp, TG3_APE_HOST_WOL_SPEED,
+ TG3_APE_HOST_WOL_SPEED_AUTO);
+ apedata = TG3_APE_HOST_DRVR_STATE_WOL;
+ } else
+ apedata = TG3_APE_HOST_DRVR_STATE_UNLOAD;
+
+ tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE, apedata);
+
+ event = APE_EVENT_STATUS_STATE_UNLOAD;
+ break;
+ case RESET_KIND_SUSPEND:
+ event = APE_EVENT_STATUS_STATE_SUSPEND;
+ break;
+ default:
+ return;
+ }
+
+ event |= APE_EVENT_STATUS_DRIVER_EVNT | APE_EVENT_STATUS_STATE_CHNGE;
+
+ tg3_ape_send_event(tp, event);
+}
+
static void tg3_disable_ints(struct tg3 *tp)
{
int i;
@@ -1389,6 +1497,149 @@ static void tg3_ump_link_report(struct tg3 *tp)
tg3_generate_fw_event(tp);
}
+/* tp->lock is held. */
+static void tg3_stop_fw(struct tg3 *tp)
+{
+ if (tg3_flag(tp, ENABLE_ASF) && !tg3_flag(tp, ENABLE_APE)) {
+ /* Wait for RX cpu to ACK the previous event. */
+ tg3_wait_for_event_ack(tp);
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
+
+ tg3_generate_fw_event(tp);
+
+ /* Wait for RX cpu to ACK this event. */
+ tg3_wait_for_event_ack(tp);
+ }
+}
+
+/* tp->lock is held. */
+static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
+{
+ tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
+ NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
+
+ if (tg3_flag(tp, ASF_NEW_HANDSHAKE)) {
+ switch (kind) {
+ case RESET_KIND_INIT:
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_START);
+ break;
+
+ case RESET_KIND_SHUTDOWN:
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_UNLOAD);
+ break;
+
+ case RESET_KIND_SUSPEND:
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_SUSPEND);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (kind == RESET_KIND_INIT ||
+ kind == RESET_KIND_SUSPEND)
+ tg3_ape_driver_state_change(tp, kind);
+}
+
+/* tp->lock is held. */
+static void tg3_write_sig_post_reset(struct tg3 *tp, int kind)
+{
+ if (tg3_flag(tp, ASF_NEW_HANDSHAKE)) {
+ switch (kind) {
+ case RESET_KIND_INIT:
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_START_DONE);
+ break;
+
+ case RESET_KIND_SHUTDOWN:
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_UNLOAD_DONE);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (kind == RESET_KIND_SHUTDOWN)
+ tg3_ape_driver_state_change(tp, kind);
+}
+
+/* tp->lock is held. */
+static void tg3_write_sig_legacy(struct tg3 *tp, int kind)
+{
+ if (tg3_flag(tp, ENABLE_ASF)) {
+ switch (kind) {
+ case RESET_KIND_INIT:
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_START);
+ break;
+
+ case RESET_KIND_SHUTDOWN:
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_UNLOAD);
+ break;
+
+ case RESET_KIND_SUSPEND:
+ tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+ DRV_STATE_SUSPEND);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+static int tg3_poll_fw(struct tg3 *tp)
+{
+ int i;
+ u32 val;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ /* Wait up to 20ms for init done. */
+ for (i = 0; i < 200; i++) {
+ if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE)
+ return 0;
+ udelay(100);
+ }
+ return -ENODEV;
+ }
+
+ /* Wait for firmware initialization to complete. */
+ for (i = 0; i < 100000; i++) {
+ tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+ if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+ break;
+ udelay(10);
+ }
+
+ /* Chip might not be fitted with firmware. Some Sun onboard
+ * parts are configured like that. So don't signal the timeout
+ * of the above loop as an error, but do report the lack of
+ * running firmware once.
+ */
+ if (i >= 100000 && !tg3_flag(tp, NO_FWARE_REPORTED)) {
+ tg3_flag_set(tp, NO_FWARE_REPORTED);
+
+ netdev_info(tp->dev, "No firmware running\n");
+ }
+
+ if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
+ /* The 57765 A0 needs a little more
+ * time to do some important work.
+ */
+ mdelay(10);
+ }
+
+ return 0;
+}
+
static void tg3_link_report(struct tg3 *tp)
{
if (!netif_carrier_ok(tp->dev)) {
@@ -1680,6 +1931,36 @@ static void tg3_phy_fini(struct tg3 *tp)
}
}
+static int tg3_phy_set_extloopbk(struct tg3 *tp)
+{
+ int err;
+ u32 val;
+
+ if (tp->phy_flags & TG3_PHYFLG_IS_FET)
+ return 0;
+
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
+ /* Cannot do read-modify-write on 5401 */
+ err = tg3_phy_auxctl_write(tp,
+ MII_TG3_AUXCTL_SHDWSEL_AUXCTL,
+ MII_TG3_AUXCTL_ACTL_EXTLOOPBK |
+ 0x4c20);
+ goto done;
+ }
+
+ err = tg3_phy_auxctl_read(tp,
+ MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val);
+ if (err)
+ return err;
+
+ val |= MII_TG3_AUXCTL_ACTL_EXTLOOPBK;
+ err = tg3_phy_auxctl_write(tp,
+ MII_TG3_AUXCTL_SHDWSEL_AUXCTL, val);
+
+done:
+ return err;
+}
+
static void tg3_phy_fet_toggle_apd(struct tg3 *tp, bool enable)
{
u32 phytest;
@@ -2450,12 +2731,6 @@ static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
}
static int tg3_setup_phy(struct tg3 *, int);
-
-#define RESET_KIND_SHUTDOWN 0
-#define RESET_KIND_INIT 1
-#define RESET_KIND_SUSPEND 2
-
-static void tg3_write_sig_post_reset(struct tg3 *, int);
static int tg3_halt_cpu(struct tg3 *, u32);
static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
@@ -2724,6 +2999,228 @@ static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, __be32 *val)
return res;
}
+#define RX_CPU_SCRATCH_BASE 0x30000
+#define RX_CPU_SCRATCH_SIZE 0x04000
+#define TX_CPU_SCRATCH_BASE 0x34000
+#define TX_CPU_SCRATCH_SIZE 0x04000
+
+/* tp->lock is held. */
+static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
+{
+ int i;
+
+ BUG_ON(offset == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS));
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u32 val = tr32(GRC_VCPU_EXT_CTRL);
+
+ tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU);
+ return 0;
+ }
+ if (offset == RX_CPU_BASE) {
+ for (i = 0; i < 10000; i++) {
+ tw32(offset + CPU_STATE, 0xffffffff);
+ tw32(offset + CPU_MODE, CPU_MODE_HALT);
+ if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
+ break;
+ }
+
+ tw32(offset + CPU_STATE, 0xffffffff);
+ tw32_f(offset + CPU_MODE, CPU_MODE_HALT);
+ udelay(10);
+ } else {
+ for (i = 0; i < 10000; i++) {
+ tw32(offset + CPU_STATE, 0xffffffff);
+ tw32(offset + CPU_MODE, CPU_MODE_HALT);
+ if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
+ break;
+ }
+ }
+
+ if (i >= 10000) {
+ netdev_err(tp->dev, "%s timed out, %s CPU\n",
+ __func__, offset == RX_CPU_BASE ? "RX" : "TX");
+ return -ENODEV;
+ }
+
+ /* Clear firmware's nvram arbitration. */
+ if (tg3_flag(tp, NVRAM))
+ tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
+ return 0;
+}
+
+struct fw_info {
+ unsigned int fw_base;
+ unsigned int fw_len;
+ const __be32 *fw_data;
+};
+
+/* tp->lock is held. */
+static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base,
+ u32 cpu_scratch_base, int cpu_scratch_size,
+ struct fw_info *info)
+{
+ int err, lock_err, i;
+ void (*write_op)(struct tg3 *, u32, u32);
+
+ if (cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)) {
+ netdev_err(tp->dev,
+ "%s: Trying to load TX cpu firmware which is 5705\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (tg3_flag(tp, 5705_PLUS))
+ write_op = tg3_write_mem;
+ else
+ write_op = tg3_write_indirect_reg32;
+
+ /* It is possible that bootcode is still loading at this point.
+ * Get the nvram lock first before halting the cpu.
+ */
+ lock_err = tg3_nvram_lock(tp);
+ err = tg3_halt_cpu(tp, cpu_base);
+ if (!lock_err)
+ tg3_nvram_unlock(tp);
+ if (err)
+ goto out;
+
+ for (i = 0; i < cpu_scratch_size; i += sizeof(u32))
+ write_op(tp, cpu_scratch_base + i, 0);
+ tw32(cpu_base + CPU_STATE, 0xffffffff);
+ tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
+ for (i = 0; i < (info->fw_len / sizeof(u32)); i++)
+ write_op(tp, (cpu_scratch_base +
+ (info->fw_base & 0xffff) +
+ (i * sizeof(u32))),
+ be32_to_cpu(info->fw_data[i]));
+
+ err = 0;
+
+out:
+ return err;
+}
+
+/* tp->lock is held. */
+static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
+{
+ struct fw_info info;
+ const __be32 *fw_data;
+ int err, i;
+
+ fw_data = (void *)tp->fw->data;
+
+ /* Firmware blob starts with version numbers, followed by
+ start address and length. We are setting complete length.
+ length = end_address_of_bss - start_address_of_text.
+ Remainder is the blob to be loaded contiguously
+ from start address. */
+
+ info.fw_base = be32_to_cpu(fw_data[1]);
+ info.fw_len = tp->fw->size - 12;
+ info.fw_data = &fw_data[3];
+
+ err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
+ RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
+ &info);
+ if (err)
+ return err;
+
+ err = tg3_load_firmware_cpu(tp, TX_CPU_BASE,
+ TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE,
+ &info);
+ if (err)
+ return err;
+
+ /* Now startup only the RX cpu. */
+ tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
+ tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
+
+ for (i = 0; i < 5; i++) {
+ if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base)
+ break;
+ tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
+ tw32(RX_CPU_BASE + CPU_MODE, CPU_MODE_HALT);
+ tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
+ udelay(1000);
+ }
+ if (i >= 5) {
+ netdev_err(tp->dev, "%s fails to set RX CPU PC, is %08x "
+ "should be %08x\n", __func__,
+ tr32(RX_CPU_BASE + CPU_PC), info.fw_base);
+ return -ENODEV;
+ }
+ tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
+ tw32_f(RX_CPU_BASE + CPU_MODE, 0x00000000);
+
+ return 0;
+}
+
+/* tp->lock is held. */
+static int tg3_load_tso_firmware(struct tg3 *tp)
+{
+ struct fw_info info;
+ const __be32 *fw_data;
+ unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
+ int err, i;
+
+ if (tg3_flag(tp, HW_TSO_1) ||
+ tg3_flag(tp, HW_TSO_2) ||
+ tg3_flag(tp, HW_TSO_3))
+ return 0;
+
+ fw_data = (void *)tp->fw->data;
+
+ /* Firmware blob starts with version numbers, followed by
+ start address and length. We are setting complete length.
+ length = end_address_of_bss - start_address_of_text.
+ Remainder is the blob to be loaded contiguously
+ from start address. */
+
+ info.fw_base = be32_to_cpu(fw_data[1]);
+ cpu_scratch_size = tp->fw_len;
+ info.fw_len = tp->fw->size - 12;
+ info.fw_data = &fw_data[3];
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+ cpu_base = RX_CPU_BASE;
+ cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705;
+ } else {
+ cpu_base = TX_CPU_BASE;
+ cpu_scratch_base = TX_CPU_SCRATCH_BASE;
+ cpu_scratch_size = TX_CPU_SCRATCH_SIZE;
+ }
+
+ err = tg3_load_firmware_cpu(tp, cpu_base,
+ cpu_scratch_base, cpu_scratch_size,
+ &info);
+ if (err)
+ return err;
+
+ /* Now startup the cpu. */
+ tw32(cpu_base + CPU_STATE, 0xffffffff);
+ tw32_f(cpu_base + CPU_PC, info.fw_base);
+
+ for (i = 0; i < 5; i++) {
+ if (tr32(cpu_base + CPU_PC) == info.fw_base)
+ break;
+ tw32(cpu_base + CPU_STATE, 0xffffffff);
+ tw32(cpu_base + CPU_MODE, CPU_MODE_HALT);
+ tw32_f(cpu_base + CPU_PC, info.fw_base);
+ udelay(1000);
+ }
+ if (i >= 5) {
+ netdev_err(tp->dev,
+ "%s fails to set CPU PC, is %08x should be %08x\n",
+ __func__, tr32(cpu_base + CPU_PC), info.fw_base);
+ return -ENODEV;
+ }
+ tw32(cpu_base + CPU_STATE, 0xffffffff);
+ tw32_f(cpu_base + CPU_MODE, 0x00000000);
+ return 0;
+}
+
+
/* tp->lock is held. */
static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
{
@@ -3303,8 +3800,9 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg))
return 0;
- if ((adv_reg & all_mask) != all_mask)
+ if ((adv_reg & ADVERTISE_ALL) != all_mask)
return 0;
+
if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
u32 tg3_ctrl;
@@ -3317,9 +3815,11 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl))
return 0;
- if ((tg3_ctrl & all_mask) != all_mask)
+ tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
+ if (tg3_ctrl != all_mask)
return 0;
}
+
return 1;
}
@@ -3620,8 +4120,8 @@ relink:
newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
if (newlnkctl != oldlnkctl)
pci_write_config_word(tp->pdev,
- pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
- newlnkctl);
+ pci_pcie_cap(tp->pdev) +
+ PCI_EXP_LNKCTL, newlnkctl);
}
if (current_link_up != netif_carrier_ok(tp->dev)) {
@@ -4856,7 +5356,7 @@ static void tg3_tx(struct tg3_napi *tnapi)
pci_unmap_page(tp->pdev,
dma_unmap_addr(ri, mapping),
- skb_shinfo(skb)->frags[i].size,
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
PCI_DMA_TODEVICE);
while (ri->fragmented) {
@@ -4951,11 +5451,11 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
* Callers depend upon this behavior and assume that
* we leave everything unchanged if we fail.
*/
- skb = netdev_alloc_skb(tp->dev, skb_size + tp->rx_offset);
+ skb = netdev_alloc_skb(tp->dev, skb_size + TG3_RX_OFFSET(tp));
if (skb == NULL)
return -ENOMEM;
- skb_reserve(skb, tp->rx_offset);
+ skb_reserve(skb, TG3_RX_OFFSET(tp));
mapping = pci_map_single(tp->pdev, skb->data, skb_size,
PCI_DMA_FROMDEVICE);
@@ -5673,7 +6173,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id)
* NIC to stop sending us irqs, engaging "in-intr-handler"
* event coalescing.
*/
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+ tw32_mailbox(tnapi->int_mbox, 0x00000001);
if (likely(!tg3_irq_sync(tp)))
napi_schedule(&tnapi->napi);
@@ -6010,14 +6510,14 @@ static void tg3_tx_skb_unmap(struct tg3_napi *tnapi, u32 entry, int last)
}
for (i = 0; i < last; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
entry = NEXT_TX(entry);
txb = &tnapi->tx_buffers[entry];
pci_unmap_page(tnapi->tp->pdev,
dma_unmap_addr(txb, mapping),
- frag->size, PCI_DMA_TODEVICE);
+ skb_frag_size(frag), PCI_DMA_TODEVICE);
while (txb->fragmented) {
txb->fragmented = false;
@@ -6029,12 +6529,12 @@ static void tg3_tx_skb_unmap(struct tg3_napi *tnapi, u32 entry, int last)
/* Workaround 4GB and 40-bit hardware DMA bugs. */
static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
- struct sk_buff *skb,
+ struct sk_buff **pskb,
u32 *entry, u32 *budget,
u32 base_flags, u32 mss, u32 vlan)
{
struct tg3 *tp = tnapi->tp;
- struct sk_buff *new_skb;
+ struct sk_buff *new_skb, *skb = *pskb;
dma_addr_t new_addr = 0;
int ret = 0;
@@ -6076,7 +6576,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
}
dev_kfree_skb(skb);
-
+ *pskb = new_skb;
return ret;
}
@@ -6171,10 +6671,8 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 tcp_opt_len, hdr_len;
if (skb_header_cloned(skb) &&
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
- dev_kfree_skb(skb);
- goto out_unlock;
- }
+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+ goto drop;
iph = ip_hdr(skb);
tcp_opt_len = tcp_optlen(skb);
@@ -6234,22 +6732,21 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
}
+ if (tg3_flag(tp, USE_JUMBO_BDFLAG) &&
+ !mss && skb->len > VLAN_ETH_FRAME_LEN)
+ base_flags |= TXD_FLAG_JMB_PKT;
+
if (vlan_tx_tag_present(skb)) {
base_flags |= TXD_FLAG_VLAN;
vlan = vlan_tx_tag_get(skb);
}
- if (tg3_flag(tp, USE_JUMBO_BDFLAG) &&
- !mss && skb->len > VLAN_ETH_FRAME_LEN)
- base_flags |= TXD_FLAG_JMB_PKT;
-
len = skb_headlen(skb);
mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(tp->pdev, mapping)) {
- dev_kfree_skb(skb);
- goto out_unlock;
- }
+ if (pci_dma_mapping_error(tp->pdev, mapping))
+ goto drop;
+
tnapi->tx_buffers[entry].skb = skb;
dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, mapping);
@@ -6277,16 +6774,14 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
for (i = 0; i <= last; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- len = frag->size;
- mapping = pci_map_page(tp->pdev,
- frag->page,
- frag->page_offset,
- len, PCI_DMA_TODEVICE);
+ len = skb_frag_size(frag);
+ mapping = skb_frag_dma_map(&tp->pdev->dev, frag, 0,
+ len, DMA_TO_DEVICE);
tnapi->tx_buffers[entry].skb = NULL;
dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping,
mapping);
- if (pci_dma_mapping_error(tp->pdev, mapping))
+ if (dma_mapping_error(&tp->pdev->dev, mapping))
goto dma_error;
if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping,
@@ -6305,9 +6800,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
entry = tnapi->tx_prod;
budget = tg3_tx_avail(tnapi);
- if (tigon3_dma_hwbug_workaround(tnapi, skb, &entry, &budget,
+ if (tigon3_dma_hwbug_workaround(tnapi, &skb, &entry, &budget,
base_flags, mss, vlan))
- goto out_unlock;
+ goto drop_nofree;
}
skb_tx_timestamp(skb);
@@ -6329,18 +6824,140 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_tx_wake_queue(txq);
}
-out_unlock:
mmiowb();
-
return NETDEV_TX_OK;
dma_error:
tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i);
- dev_kfree_skb(skb);
tnapi->tx_buffers[tnapi->tx_prod].skb = NULL;
+drop:
+ dev_kfree_skb(skb);
+drop_nofree:
+ tp->tx_dropped++;
return NETDEV_TX_OK;
}
+static void tg3_mac_loopback(struct tg3 *tp, bool enable)
+{
+ if (enable) {
+ tp->mac_mode &= ~(MAC_MODE_HALF_DUPLEX |
+ MAC_MODE_PORT_MODE_MASK);
+
+ tp->mac_mode |= MAC_MODE_PORT_INT_LPBACK;
+
+ if (!tg3_flag(tp, 5705_PLUS))
+ tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+
+ if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+ tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+ else
+ tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+ } else {
+ tp->mac_mode &= ~MAC_MODE_PORT_INT_LPBACK;
+
+ if (tg3_flag(tp, 5705_PLUS) ||
+ (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
+ tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ }
+
+ tw32(MAC_MODE, tp->mac_mode);
+ udelay(40);
+}
+
+static int tg3_phy_lpbk_set(struct tg3 *tp, u32 speed, bool extlpbk)
+{
+ u32 val, bmcr, mac_mode, ptest = 0;
+
+ tg3_phy_toggle_apd(tp, false);
+ tg3_phy_toggle_automdix(tp, 0);
+
+ if (extlpbk && tg3_phy_set_extloopbk(tp))
+ return -EIO;
+
+ bmcr = BMCR_FULLDPLX;
+ switch (speed) {
+ case SPEED_10:
+ break;
+ case SPEED_100:
+ bmcr |= BMCR_SPEED100;
+ break;
+ case SPEED_1000:
+ default:
+ if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+ speed = SPEED_100;
+ bmcr |= BMCR_SPEED100;
+ } else {
+ speed = SPEED_1000;
+ bmcr |= BMCR_SPEED1000;
+ }
+ }
+
+ if (extlpbk) {
+ if (!(tp->phy_flags & TG3_PHYFLG_IS_FET)) {
+ tg3_readphy(tp, MII_CTRL1000, &val);
+ val |= CTL1000_AS_MASTER |
+ CTL1000_ENABLE_MASTER;
+ tg3_writephy(tp, MII_CTRL1000, val);
+ } else {
+ ptest = MII_TG3_FET_PTEST_TRIM_SEL |
+ MII_TG3_FET_PTEST_TRIM_2;
+ tg3_writephy(tp, MII_TG3_FET_PTEST, ptest);
+ }
+ } else
+ bmcr |= BMCR_LOOPBACK;
+
+ tg3_writephy(tp, MII_BMCR, bmcr);
+
+ /* The write needs to be flushed for the FETs */
+ if (tp->phy_flags & TG3_PHYFLG_IS_FET)
+ tg3_readphy(tp, MII_BMCR, &bmcr);
+
+ udelay(40);
+
+ if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ tg3_writephy(tp, MII_TG3_FET_PTEST, ptest |
+ MII_TG3_FET_PTEST_FRC_TX_LINK |
+ MII_TG3_FET_PTEST_FRC_TX_LOCK);
+
+ /* The write needs to be flushed for the AC131 */
+ tg3_readphy(tp, MII_TG3_FET_PTEST, &val);
+ }
+
+ /* Reset to prevent losing 1st rx packet intermittently */
+ if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) &&
+ tg3_flag(tp, 5780_CLASS)) {
+ tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+ udelay(10);
+ tw32_f(MAC_RX_MODE, tp->rx_mode);
+ }
+
+ mac_mode = tp->mac_mode &
+ ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
+ if (speed == SPEED_1000)
+ mac_mode |= MAC_MODE_PORT_MODE_GMII;
+ else
+ mac_mode |= MAC_MODE_PORT_MODE_MII;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
+ u32 masked_phy_id = tp->phy_id & TG3_PHY_ID_MASK;
+
+ if (masked_phy_id == TG3_PHY_ID_BCM5401)
+ mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ else if (masked_phy_id == TG3_PHY_ID_BCM5411)
+ mac_mode |= MAC_MODE_LINK_POLARITY;
+
+ tg3_writephy(tp, MII_TG3_EXT_CTRL,
+ MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+ }
+
+ tw32(MAC_MODE, mac_mode);
+ udelay(40);
+
+ return 0;
+}
+
static void tg3_set_loopback(struct net_device *dev, u32 features)
{
struct tg3 *tp = netdev_priv(dev);
@@ -6349,16 +6966,8 @@ static void tg3_set_loopback(struct net_device *dev, u32 features)
if (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK)
return;
- /*
- * Clear MAC_MODE_HALF_DUPLEX or you won't get packets back in
- * loopback mode if Half-Duplex mode was negotiated earlier.
- */
- tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
-
- /* Enable internal MAC loopback mode */
- tp->mac_mode |= MAC_MODE_PORT_INT_LPBACK;
spin_lock_bh(&tp->lock);
- tw32(MAC_MODE, tp->mac_mode);
+ tg3_mac_loopback(tp, true);
netif_carrier_on(tp->dev);
spin_unlock_bh(&tp->lock);
netdev_info(dev, "Internal MAC loopback mode enabled.\n");
@@ -6366,10 +6975,8 @@ static void tg3_set_loopback(struct net_device *dev, u32 features)
if (!(tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
return;
- /* Disable internal MAC loopback mode */
- tp->mac_mode &= ~MAC_MODE_PORT_INT_LPBACK;
spin_lock_bh(&tp->lock);
- tw32(MAC_MODE, tp->mac_mode);
+ tg3_mac_loopback(tp, false);
/* Force link status check */
tg3_setup_phy(tp, 1);
spin_unlock_bh(&tp->lock);
@@ -6979,230 +7586,6 @@ static int tg3_abort_hw(struct tg3 *tp, int silent)
return err;
}
-static void tg3_ape_send_event(struct tg3 *tp, u32 event)
-{
- int i;
- u32 apedata;
-
- /* NCSI does not support APE events */
- if (tg3_flag(tp, APE_HAS_NCSI))
- return;
-
- apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
- if (apedata != APE_SEG_SIG_MAGIC)
- return;
-
- apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
- if (!(apedata & APE_FW_STATUS_READY))
- return;
-
- /* Wait for up to 1 millisecond for APE to service previous event. */
- for (i = 0; i < 10; i++) {
- if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM))
- return;
-
- apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
-
- if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
- tg3_ape_write32(tp, TG3_APE_EVENT_STATUS,
- event | APE_EVENT_STATUS_EVENT_PENDING);
-
- tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
-
- if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
- break;
-
- udelay(100);
- }
-
- if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
- tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
-}
-
-static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
-{
- u32 event;
- u32 apedata;
-
- if (!tg3_flag(tp, ENABLE_APE))
- return;
-
- switch (kind) {
- case RESET_KIND_INIT:
- tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG,
- APE_HOST_SEG_SIG_MAGIC);
- tg3_ape_write32(tp, TG3_APE_HOST_SEG_LEN,
- APE_HOST_SEG_LEN_MAGIC);
- apedata = tg3_ape_read32(tp, TG3_APE_HOST_INIT_COUNT);
- tg3_ape_write32(tp, TG3_APE_HOST_INIT_COUNT, ++apedata);
- tg3_ape_write32(tp, TG3_APE_HOST_DRIVER_ID,
- APE_HOST_DRIVER_ID_MAGIC(TG3_MAJ_NUM, TG3_MIN_NUM));
- tg3_ape_write32(tp, TG3_APE_HOST_BEHAVIOR,
- APE_HOST_BEHAV_NO_PHYLOCK);
- tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE,
- TG3_APE_HOST_DRVR_STATE_START);
-
- event = APE_EVENT_STATUS_STATE_START;
- break;
- case RESET_KIND_SHUTDOWN:
- /* With the interface we are currently using,
- * APE does not track driver state. Wiping
- * out the HOST SEGMENT SIGNATURE forces
- * the APE to assume OS absent status.
- */
- tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);
-
- if (device_may_wakeup(&tp->pdev->dev) &&
- tg3_flag(tp, WOL_ENABLE)) {
- tg3_ape_write32(tp, TG3_APE_HOST_WOL_SPEED,
- TG3_APE_HOST_WOL_SPEED_AUTO);
- apedata = TG3_APE_HOST_DRVR_STATE_WOL;
- } else
- apedata = TG3_APE_HOST_DRVR_STATE_UNLOAD;
-
- tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE, apedata);
-
- event = APE_EVENT_STATUS_STATE_UNLOAD;
- break;
- case RESET_KIND_SUSPEND:
- event = APE_EVENT_STATUS_STATE_SUSPEND;
- break;
- default:
- return;
- }
-
- event |= APE_EVENT_STATUS_DRIVER_EVNT | APE_EVENT_STATUS_STATE_CHNGE;
-
- tg3_ape_send_event(tp, event);
-}
-
-/* tp->lock is held. */
-static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
-{
- tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
- NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
-
- if (tg3_flag(tp, ASF_NEW_HANDSHAKE)) {
- switch (kind) {
- case RESET_KIND_INIT:
- tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
- DRV_STATE_START);
- break;
-
- case RESET_KIND_SHUTDOWN:
- tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
- DRV_STATE_UNLOAD);
- break;
-
- case RESET_KIND_SUSPEND:
- tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
- DRV_STATE_SUSPEND);
- break;
-
- default:
- break;
- }
- }
-
- if (kind == RESET_KIND_INIT ||
- kind == RESET_KIND_SUSPEND)
- tg3_ape_driver_state_change(tp, kind);
-}
-
-/* tp->lock is held. */
-static void tg3_write_sig_post_reset(struct tg3 *tp, int kind)
-{
- if (tg3_flag(tp, ASF_NEW_HANDSHAKE)) {
- switch (kind) {
- case RESET_KIND_INIT:
- tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
- DRV_STATE_START_DONE);
- break;
-
- case RESET_KIND_SHUTDOWN:
- tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
- DRV_STATE_UNLOAD_DONE);
- break;
-
- default:
- break;
- }
- }
-
- if (kind == RESET_KIND_SHUTDOWN)
- tg3_ape_driver_state_change(tp, kind);
-}
-
-/* tp->lock is held. */
-static void tg3_write_sig_legacy(struct tg3 *tp, int kind)
-{
- if (tg3_flag(tp, ENABLE_ASF)) {
- switch (kind) {
- case RESET_KIND_INIT:
- tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
- DRV_STATE_START);
- break;
-
- case RESET_KIND_SHUTDOWN:
- tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
- DRV_STATE_UNLOAD);
- break;
-
- case RESET_KIND_SUSPEND:
- tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
- DRV_STATE_SUSPEND);
- break;
-
- default:
- break;
- }
- }
-}
-
-static int tg3_poll_fw(struct tg3 *tp)
-{
- int i;
- u32 val;
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- /* Wait up to 20ms for init done. */
- for (i = 0; i < 200; i++) {
- if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE)
- return 0;
- udelay(100);
- }
- return -ENODEV;
- }
-
- /* Wait for firmware initialization to complete. */
- for (i = 0; i < 100000; i++) {
- tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
- if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
- break;
- udelay(10);
- }
-
- /* Chip might not be fitted with firmware. Some Sun onboard
- * parts are configured like that. So don't signal the timeout
- * of the above loop as an error, but do report the lack of
- * running firmware once.
- */
- if (i >= 100000 && !tg3_flag(tp, NO_FWARE_REPORTED)) {
- tg3_flag_set(tp, NO_FWARE_REPORTED);
-
- netdev_info(tp->dev, "No firmware running\n");
- }
-
- if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
- /* The 57765 A0 needs a little more
- * time to do some important work.
- */
- mdelay(10);
- }
-
- return 0;
-}
-
/* Save PCI command register before chip reset */
static void tg3_save_pci_state(struct tg3 *tp)
{
@@ -7274,8 +7657,6 @@ static void tg3_restore_pci_state(struct tg3 *tp)
}
}
-static void tg3_stop_fw(struct tg3 *);
-
/* tp->lock is held. */
static int tg3_chip_reset(struct tg3 *tp)
{
@@ -7523,22 +7904,6 @@ static int tg3_chip_reset(struct tg3 *tp)
}
/* tp->lock is held. */
-static void tg3_stop_fw(struct tg3 *tp)
-{
- if (tg3_flag(tp, ENABLE_ASF) && !tg3_flag(tp, ENABLE_APE)) {
- /* Wait for RX cpu to ACK the previous event. */
- tg3_wait_for_event_ack(tp);
-
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
-
- tg3_generate_fw_event(tp);
-
- /* Wait for RX cpu to ACK this event. */
- tg3_wait_for_event_ack(tp);
- }
-}
-
-/* tp->lock is held. */
static int tg3_halt(struct tg3 *tp, int kind, int silent)
{
int err;
@@ -7561,227 +7926,6 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent)
return 0;
}
-#define RX_CPU_SCRATCH_BASE 0x30000
-#define RX_CPU_SCRATCH_SIZE 0x04000
-#define TX_CPU_SCRATCH_BASE 0x34000
-#define TX_CPU_SCRATCH_SIZE 0x04000
-
-/* tp->lock is held. */
-static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
-{
- int i;
-
- BUG_ON(offset == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS));
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- u32 val = tr32(GRC_VCPU_EXT_CTRL);
-
- tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU);
- return 0;
- }
- if (offset == RX_CPU_BASE) {
- for (i = 0; i < 10000; i++) {
- tw32(offset + CPU_STATE, 0xffffffff);
- tw32(offset + CPU_MODE, CPU_MODE_HALT);
- if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
- break;
- }
-
- tw32(offset + CPU_STATE, 0xffffffff);
- tw32_f(offset + CPU_MODE, CPU_MODE_HALT);
- udelay(10);
- } else {
- for (i = 0; i < 10000; i++) {
- tw32(offset + CPU_STATE, 0xffffffff);
- tw32(offset + CPU_MODE, CPU_MODE_HALT);
- if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
- break;
- }
- }
-
- if (i >= 10000) {
- netdev_err(tp->dev, "%s timed out, %s CPU\n",
- __func__, offset == RX_CPU_BASE ? "RX" : "TX");
- return -ENODEV;
- }
-
- /* Clear firmware's nvram arbitration. */
- if (tg3_flag(tp, NVRAM))
- tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
- return 0;
-}
-
-struct fw_info {
- unsigned int fw_base;
- unsigned int fw_len;
- const __be32 *fw_data;
-};
-
-/* tp->lock is held. */
-static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base,
- int cpu_scratch_size, struct fw_info *info)
-{
- int err, lock_err, i;
- void (*write_op)(struct tg3 *, u32, u32);
-
- if (cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)) {
- netdev_err(tp->dev,
- "%s: Trying to load TX cpu firmware which is 5705\n",
- __func__);
- return -EINVAL;
- }
-
- if (tg3_flag(tp, 5705_PLUS))
- write_op = tg3_write_mem;
- else
- write_op = tg3_write_indirect_reg32;
-
- /* It is possible that bootcode is still loading at this point.
- * Get the nvram lock first before halting the cpu.
- */
- lock_err = tg3_nvram_lock(tp);
- err = tg3_halt_cpu(tp, cpu_base);
- if (!lock_err)
- tg3_nvram_unlock(tp);
- if (err)
- goto out;
-
- for (i = 0; i < cpu_scratch_size; i += sizeof(u32))
- write_op(tp, cpu_scratch_base + i, 0);
- tw32(cpu_base + CPU_STATE, 0xffffffff);
- tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
- for (i = 0; i < (info->fw_len / sizeof(u32)); i++)
- write_op(tp, (cpu_scratch_base +
- (info->fw_base & 0xffff) +
- (i * sizeof(u32))),
- be32_to_cpu(info->fw_data[i]));
-
- err = 0;
-
-out:
- return err;
-}
-
-/* tp->lock is held. */
-static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
-{
- struct fw_info info;
- const __be32 *fw_data;
- int err, i;
-
- fw_data = (void *)tp->fw->data;
-
- /* Firmware blob starts with version numbers, followed by
- start address and length. We are setting complete length.
- length = end_address_of_bss - start_address_of_text.
- Remainder is the blob to be loaded contiguously
- from start address. */
-
- info.fw_base = be32_to_cpu(fw_data[1]);
- info.fw_len = tp->fw->size - 12;
- info.fw_data = &fw_data[3];
-
- err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
- RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
- &info);
- if (err)
- return err;
-
- err = tg3_load_firmware_cpu(tp, TX_CPU_BASE,
- TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE,
- &info);
- if (err)
- return err;
-
- /* Now startup only the RX cpu. */
- tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
- tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
-
- for (i = 0; i < 5; i++) {
- if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base)
- break;
- tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
- tw32(RX_CPU_BASE + CPU_MODE, CPU_MODE_HALT);
- tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
- udelay(1000);
- }
- if (i >= 5) {
- netdev_err(tp->dev, "%s fails to set RX CPU PC, is %08x "
- "should be %08x\n", __func__,
- tr32(RX_CPU_BASE + CPU_PC), info.fw_base);
- return -ENODEV;
- }
- tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
- tw32_f(RX_CPU_BASE + CPU_MODE, 0x00000000);
-
- return 0;
-}
-
-/* tp->lock is held. */
-static int tg3_load_tso_firmware(struct tg3 *tp)
-{
- struct fw_info info;
- const __be32 *fw_data;
- unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
- int err, i;
-
- if (tg3_flag(tp, HW_TSO_1) ||
- tg3_flag(tp, HW_TSO_2) ||
- tg3_flag(tp, HW_TSO_3))
- return 0;
-
- fw_data = (void *)tp->fw->data;
-
- /* Firmware blob starts with version numbers, followed by
- start address and length. We are setting complete length.
- length = end_address_of_bss - start_address_of_text.
- Remainder is the blob to be loaded contiguously
- from start address. */
-
- info.fw_base = be32_to_cpu(fw_data[1]);
- cpu_scratch_size = tp->fw_len;
- info.fw_len = tp->fw->size - 12;
- info.fw_data = &fw_data[3];
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
- cpu_base = RX_CPU_BASE;
- cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705;
- } else {
- cpu_base = TX_CPU_BASE;
- cpu_scratch_base = TX_CPU_SCRATCH_BASE;
- cpu_scratch_size = TX_CPU_SCRATCH_SIZE;
- }
-
- err = tg3_load_firmware_cpu(tp, cpu_base,
- cpu_scratch_base, cpu_scratch_size,
- &info);
- if (err)
- return err;
-
- /* Now startup the cpu. */
- tw32(cpu_base + CPU_STATE, 0xffffffff);
- tw32_f(cpu_base + CPU_PC, info.fw_base);
-
- for (i = 0; i < 5; i++) {
- if (tr32(cpu_base + CPU_PC) == info.fw_base)
- break;
- tw32(cpu_base + CPU_STATE, 0xffffffff);
- tw32(cpu_base + CPU_MODE, CPU_MODE_HALT);
- tw32_f(cpu_base + CPU_PC, info.fw_base);
- udelay(1000);
- }
- if (i >= 5) {
- netdev_err(tp->dev,
- "%s fails to set CPU PC, is %08x should be %08x\n",
- __func__, tr32(cpu_base + CPU_PC), info.fw_base);
- return -ENODEV;
- }
- tw32(cpu_base + CPU_STATE, 0xffffffff);
- tw32_f(cpu_base + CPU_MODE, 0x00000000);
- return 0;
-}
-
-
static int tg3_set_mac_addr(struct net_device *dev, void *p)
{
struct tg3 *tp = netdev_priv(dev);
@@ -7961,7 +8105,7 @@ static void tg3_rings_reset(struct tg3 *tp)
tw32_mailbox(tp->napi[i].prodmbox, 0);
tw32_rx_mbox(tp->napi[i].consmbox, 0);
tw32_mailbox_f(tp->napi[i].int_mbox, 1);
- tp->napi[0].chk_msi_cnt = 0;
+ tp->napi[i].chk_msi_cnt = 0;
tp->napi[i].last_rx_cons = 0;
tp->napi[i].last_tx_cons = 0;
}
@@ -8657,6 +8801,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
if (tg3_flag(tp, USING_MSIX) && tp->irq_cnt > 1) {
val = tr32(MSGINT_MODE);
val |= MSGINT_MODE_MULTIVEC_EN | MSGINT_MODE_ENABLE;
+ if (!tg3_flag(tp, 1SHOT_MSI))
+ val |= MSGINT_MODE_ONE_SHOT_DISABLE;
tw32(MSGINT_MODE, val);
}
@@ -9041,8 +9187,7 @@ static void tg3_chk_missed_msi(struct tg3 *tp)
tnapi->chk_msi_cnt++;
return;
}
- tw32_mailbox(tnapi->int_mbox,
- tnapi->last_tag << 24);
+ tg3_msi(0, tnapi);
}
}
tnapi->chk_msi_cnt = 0;
@@ -9273,7 +9418,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
if (intr_ok) {
/* Reenable MSI one shot mode. */
- if (tg3_flag(tp, 57765_PLUS)) {
+ if (tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, 1SHOT_MSI)) {
val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE;
tw32(MSGINT_MODE, val);
}
@@ -9451,6 +9596,8 @@ static void tg3_ints_init(struct tg3 *tp)
u32 msi_mode = tr32(MSGINT_MODE);
if (tg3_flag(tp, USING_MSIX) && tp->irq_cnt > 1)
msi_mode |= MSGINT_MODE_MULTIVEC_EN;
+ if (!tg3_flag(tp, 1SHOT_MSI))
+ msi_mode |= MSGINT_MODE_ONE_SHOT_DISABLE;
tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
}
defcfg:
@@ -9860,6 +10007,7 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
get_stat64(&hw_stats->rx_discards);
stats->rx_dropped = tp->rx_dropped;
+ stats->tx_dropped = tp->tx_dropped;
return stats;
}
@@ -10365,7 +10513,6 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
struct tg3 *tp = netdev_priv(dev);
ering->rx_max_pending = tp->rx_std_ring_mask;
- ering->rx_mini_max_pending = 0;
if (tg3_flag(tp, JUMBO_RING_ENABLE))
ering->rx_jumbo_max_pending = tp->rx_jmb_ring_mask;
else
@@ -10374,7 +10521,6 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
ering->tx_max_pending = TG3_TX_RING_SIZE - 1;
ering->rx_pending = tp->rx_pending;
- ering->rx_mini_pending = 0;
if (tg3_flag(tp, JUMBO_RING_ENABLE))
ering->rx_jumbo_pending = tp->rx_jumbo_pending;
else
@@ -11217,10 +11363,6 @@ static int tg3_test_memory(struct tg3 *tp)
return err;
}
-#define TG3_MAC_LOOPBACK 0
-#define TG3_PHY_LOOPBACK 1
-#define TG3_TSO_LOOPBACK 2
-
#define TG3_TSO_MSS 500
#define TG3_TSO_IP_HDR_LEN 20
@@ -11244,9 +11386,9 @@ static const u8 tg3_tso_header[] = {
0x11, 0x11, 0x11, 0x11,
};
-static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
+static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback)
{
- u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
+ u32 rx_start_idx, rx_idx, tx_idx, opaque_key;
u32 base_flags = 0, mss = 0, desc_idx, coal_now, data_off, val;
u32 budget;
struct sk_buff *skb, *rx_skb;
@@ -11267,76 +11409,6 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
}
coal_now = tnapi->coal_now | rnapi->coal_now;
- if (loopback_mode == TG3_MAC_LOOPBACK) {
- /* HW errata - mac loopback fails in some cases on 5780.
- * Normal traffic and PHY loopback are not affected by
- * errata. Also, the MAC loopback test is deprecated for
- * all newer ASIC revisions.
- */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
- tg3_flag(tp, CPMU_PRESENT))
- return 0;
-
- mac_mode = tp->mac_mode &
- ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
- mac_mode |= MAC_MODE_PORT_INT_LPBACK;
- if (!tg3_flag(tp, 5705_PLUS))
- mac_mode |= MAC_MODE_LINK_POLARITY;
- if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
- mac_mode |= MAC_MODE_PORT_MODE_MII;
- else
- mac_mode |= MAC_MODE_PORT_MODE_GMII;
- tw32(MAC_MODE, mac_mode);
- } else {
- if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
- tg3_phy_fet_toggle_apd(tp, false);
- val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100;
- } else
- val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000;
-
- tg3_phy_toggle_automdix(tp, 0);
-
- tg3_writephy(tp, MII_BMCR, val);
- udelay(40);
-
- mac_mode = tp->mac_mode &
- ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
- if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
- tg3_writephy(tp, MII_TG3_FET_PTEST,
- MII_TG3_FET_PTEST_FRC_TX_LINK |
- MII_TG3_FET_PTEST_FRC_TX_LOCK);
- /* The write needs to be flushed for the AC131 */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
- tg3_readphy(tp, MII_TG3_FET_PTEST, &val);
- mac_mode |= MAC_MODE_PORT_MODE_MII;
- } else
- mac_mode |= MAC_MODE_PORT_MODE_GMII;
-
- /* reset to prevent losing 1st rx packet intermittently */
- if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
- tw32_f(MAC_RX_MODE, RX_MODE_RESET);
- udelay(10);
- tw32_f(MAC_RX_MODE, tp->rx_mode);
- }
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
- u32 masked_phy_id = tp->phy_id & TG3_PHY_ID_MASK;
- if (masked_phy_id == TG3_PHY_ID_BCM5401)
- mac_mode &= ~MAC_MODE_LINK_POLARITY;
- else if (masked_phy_id == TG3_PHY_ID_BCM5411)
- mac_mode |= MAC_MODE_LINK_POLARITY;
- tg3_writephy(tp, MII_TG3_EXT_CTRL,
- MII_TG3_EXT_CTRL_LNK3_LED_MODE);
- }
- tw32(MAC_MODE, mac_mode);
-
- /* Wait for link */
- for (i = 0; i < 100; i++) {
- if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
- break;
- mdelay(1);
- }
- }
-
err = -EIO;
tx_len = pktsz;
@@ -11350,7 +11422,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
tw32(MAC_RX_MTU_SIZE, tx_len + ETH_FCS_LEN);
- if (loopback_mode == TG3_TSO_LOOPBACK) {
+ if (tso_loopback) {
struct iphdr *iph = (struct iphdr *)&tx_data[ETH_HLEN];
u32 hdr_len = TG3_TSO_IP_HDR_LEN + TG3_TSO_TCP_HDR_LEN +
@@ -11470,7 +11542,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
rx_len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT)
- ETH_FCS_LEN;
- if (loopback_mode != TG3_TSO_LOOPBACK) {
+ if (!tso_loopback) {
if (rx_len != tx_len)
goto out;
@@ -11517,25 +11589,33 @@ out:
#define TG3_STD_LOOPBACK_FAILED 1
#define TG3_JMB_LOOPBACK_FAILED 2
#define TG3_TSO_LOOPBACK_FAILED 4
+#define TG3_LOOPBACK_FAILED \
+ (TG3_STD_LOOPBACK_FAILED | \
+ TG3_JMB_LOOPBACK_FAILED | \
+ TG3_TSO_LOOPBACK_FAILED)
-#define TG3_MAC_LOOPBACK_SHIFT 0
-#define TG3_PHY_LOOPBACK_SHIFT 4
-#define TG3_LOOPBACK_FAILED 0x00000077
-
-static int tg3_test_loopback(struct tg3 *tp)
+static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
{
- int err = 0;
- u32 eee_cap, cpmuctrl = 0;
-
- if (!netif_running(tp->dev))
- return TG3_LOOPBACK_FAILED;
+ int err = -EIO;
+ u32 eee_cap;
eee_cap = tp->phy_flags & TG3_PHYFLG_EEE_CAP;
tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
+ if (!netif_running(tp->dev)) {
+ data[0] = TG3_LOOPBACK_FAILED;
+ data[1] = TG3_LOOPBACK_FAILED;
+ if (do_extlpbk)
+ data[2] = TG3_LOOPBACK_FAILED;
+ goto done;
+ }
+
err = tg3_reset_hw(tp, 1);
if (err) {
- err = TG3_LOOPBACK_FAILED;
+ data[0] = TG3_LOOPBACK_FAILED;
+ data[1] = TG3_LOOPBACK_FAILED;
+ if (do_extlpbk)
+ data[2] = TG3_LOOPBACK_FAILED;
goto done;
}
@@ -11548,68 +11628,72 @@ static int tg3_test_loopback(struct tg3 *tp)
tw32(i, 0x0);
}
- /* Turn off gphy autopowerdown. */
- if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
- tg3_phy_toggle_apd(tp, false);
+ /* HW errata - mac loopback fails in some cases on 5780.
+ * Normal traffic and PHY loopback are not affected by
+ * errata. Also, the MAC loopback test is deprecated for
+ * all newer ASIC revisions.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780 &&
+ !tg3_flag(tp, CPMU_PRESENT)) {
+ tg3_mac_loopback(tp, true);
+
+ if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
+ data[0] |= TG3_STD_LOOPBACK_FAILED;
+
+ if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
+ tg3_run_loopback(tp, 9000 + ETH_HLEN, false))
+ data[0] |= TG3_JMB_LOOPBACK_FAILED;
- if (tg3_flag(tp, CPMU_PRESENT)) {
+ tg3_mac_loopback(tp, false);
+ }
+
+ if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+ !tg3_flag(tp, USE_PHYLIB)) {
int i;
- u32 status;
- tw32(TG3_CPMU_MUTEX_REQ, CPMU_MUTEX_REQ_DRIVER);
+ tg3_phy_lpbk_set(tp, 0, false);
- /* Wait for up to 40 microseconds to acquire lock. */
- for (i = 0; i < 4; i++) {
- status = tr32(TG3_CPMU_MUTEX_GNT);
- if (status == CPMU_MUTEX_GNT_DRIVER)
+ /* Wait for link */
+ for (i = 0; i < 100; i++) {
+ if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
break;
- udelay(10);
- }
-
- if (status != CPMU_MUTEX_GNT_DRIVER) {
- err = TG3_LOOPBACK_FAILED;
- goto done;
+ mdelay(1);
}
- /* Turn off link-based power management. */
- cpmuctrl = tr32(TG3_CPMU_CTRL);
- tw32(TG3_CPMU_CTRL,
- cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE |
- CPMU_CTRL_LINK_AWARE_MODE));
- }
+ if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
+ data[1] |= TG3_STD_LOOPBACK_FAILED;
+ if (tg3_flag(tp, TSO_CAPABLE) &&
+ tg3_run_loopback(tp, ETH_FRAME_LEN, true))
+ data[1] |= TG3_TSO_LOOPBACK_FAILED;
+ if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
+ tg3_run_loopback(tp, 9000 + ETH_HLEN, false))
+ data[1] |= TG3_JMB_LOOPBACK_FAILED;
- if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_MAC_LOOPBACK))
- err |= TG3_STD_LOOPBACK_FAILED << TG3_MAC_LOOPBACK_SHIFT;
+ if (do_extlpbk) {
+ tg3_phy_lpbk_set(tp, 0, true);
- if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
- tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_MAC_LOOPBACK))
- err |= TG3_JMB_LOOPBACK_FAILED << TG3_MAC_LOOPBACK_SHIFT;
+ /* All link indications report up, but the hardware
+ * isn't really ready for about 20 msec. Double it
+ * to be sure.
+ */
+ mdelay(40);
- if (tg3_flag(tp, CPMU_PRESENT)) {
- tw32(TG3_CPMU_CTRL, cpmuctrl);
+ if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
+ data[2] |= TG3_STD_LOOPBACK_FAILED;
+ if (tg3_flag(tp, TSO_CAPABLE) &&
+ tg3_run_loopback(tp, ETH_FRAME_LEN, true))
+ data[2] |= TG3_TSO_LOOPBACK_FAILED;
+ if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
+ tg3_run_loopback(tp, 9000 + ETH_HLEN, false))
+ data[2] |= TG3_JMB_LOOPBACK_FAILED;
+ }
- /* Release the mutex */
- tw32(TG3_CPMU_MUTEX_GNT, CPMU_MUTEX_GNT_DRIVER);
+ /* Re-enable gphy autopowerdown. */
+ if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
+ tg3_phy_toggle_apd(tp, true);
}
- if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
- !tg3_flag(tp, USE_PHYLIB)) {
- if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_PHY_LOOPBACK))
- err |= TG3_STD_LOOPBACK_FAILED <<
- TG3_PHY_LOOPBACK_SHIFT;
- if (tg3_flag(tp, TSO_CAPABLE) &&
- tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_TSO_LOOPBACK))
- err |= TG3_TSO_LOOPBACK_FAILED <<
- TG3_PHY_LOOPBACK_SHIFT;
- if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
- tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_PHY_LOOPBACK))
- err |= TG3_JMB_LOOPBACK_FAILED <<
- TG3_PHY_LOOPBACK_SHIFT;
- }
-
- /* Re-enable gphy autopowerdown. */
- if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
- tg3_phy_toggle_apd(tp, true);
+ err = (data[0] | data[1] | data[2]) ? -EIO : 0;
done:
tp->phy_flags |= eee_cap;
@@ -11621,6 +11705,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
u64 *data)
{
struct tg3 *tp = netdev_priv(dev);
+ bool doextlpbk = etest->flags & ETH_TEST_FL_EXTERNAL_LB;
if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) &&
tg3_power_up(tp)) {
@@ -11635,7 +11720,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
etest->flags |= ETH_TEST_FL_FAILED;
data[0] = 1;
}
- if (tg3_test_link(tp) != 0) {
+ if (!doextlpbk && tg3_test_link(tp)) {
etest->flags |= ETH_TEST_FL_FAILED;
data[1] = 1;
}
@@ -11665,18 +11750,23 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
etest->flags |= ETH_TEST_FL_FAILED;
data[2] = 1;
}
+
if (tg3_test_memory(tp) != 0) {
etest->flags |= ETH_TEST_FL_FAILED;
data[3] = 1;
}
- if ((data[4] = tg3_test_loopback(tp)) != 0)
+
+ if (doextlpbk)
+ etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
+
+ if (tg3_test_loopback(tp, &data[4], doextlpbk))
etest->flags |= ETH_TEST_FL_FAILED;
tg3_full_unlock(tp);
if (tg3_test_interrupt(tp) != 0) {
etest->flags |= ETH_TEST_FL_FAILED;
- data[5] = 1;
+ data[7] = 1;
}
tg3_full_lock(tp, 0);
@@ -13985,7 +14075,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
/* BCM5785 devices are effectively PCIe devices, and should
* follow PCIe codepaths, but do not have a PCIe capabilities
* section.
- */
+ */
tg3_flag_set(tp, PCI_EXPRESS);
} else if (!tg3_flag(tp, 5705_PLUS) ||
tg3_flag(tp, 5780_CLASS)) {
@@ -14366,7 +14456,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tg3_flag(tp, ENABLE_APE))
tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
else
- tp->mac_mode = TG3_DEF_MAC_MODE;
+ tp->mac_mode = 0;
/* these are limited to 10/100 only */
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
@@ -15175,7 +15265,7 @@ static const struct net_device_ops tg3_netdev_ops = {
.ndo_start_xmit = tg3_start_xmit,
.ndo_get_stats64 = tg3_get_stats64,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = tg3_set_rx_mode,
+ .ndo_set_rx_mode = tg3_set_rx_mode,
.ndo_set_mac_address = tg3_set_mac_addr,
.ndo_do_ioctl = tg3_ioctl,
.ndo_tx_timeout = tg3_tx_timeout,
@@ -15445,7 +15535,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tnapi->tx_pending = TG3_DEF_TX_RING_PENDING;
tnapi->int_mbox = intmbx;
- if (i < 4)
+ if (i <= 4)
intmbx += 0x8;
else
intmbx += 0x4;
diff --git a/drivers/net/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index 2ea456dd5880..f32f288134c7 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -2197,6 +2197,7 @@
#define MII_TG3_AUXCTL_ACTL_TX_6DB 0x0400
#define MII_TG3_AUXCTL_ACTL_SMDSP_ENA 0x0800
#define MII_TG3_AUXCTL_ACTL_EXTPKTLEN 0x4000
+#define MII_TG3_AUXCTL_ACTL_EXTLOOPBK 0x8000
#define MII_TG3_AUXCTL_SHDWSEL_PWRCTL 0x0002
#define MII_TG3_AUXCTL_PCTL_WOL_EN 0x0008
@@ -2262,6 +2263,8 @@
/* Fast Ethernet Tranceiver definitions */
#define MII_TG3_FET_PTEST 0x17
+#define MII_TG3_FET_PTEST_TRIM_SEL 0x0010
+#define MII_TG3_FET_PTEST_TRIM_2 0x0002
#define MII_TG3_FET_PTEST_FRC_TX_LINK 0x1000
#define MII_TG3_FET_PTEST_FRC_TX_LOCK 0x0800
@@ -2987,6 +2990,7 @@ struct tg3 {
/* begin "everything else" cacheline(s) section */
unsigned long rx_dropped;
+ unsigned long tx_dropped;
struct rtnl_link_stats64 net_stats_prev;
struct tg3_ethtool_stats estats;
struct tg3_ethtool_stats estats_prev;
diff --git a/drivers/net/ethernet/brocade/Kconfig b/drivers/net/ethernet/brocade/Kconfig
new file mode 100644
index 000000000000..264155778857
--- /dev/null
+++ b/drivers/net/ethernet/brocade/Kconfig
@@ -0,0 +1,23 @@
+#
+# Brocade device configuration
+#
+
+config NET_VENDOR_BROCADE
+ bool "Brocade devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Brocade cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_BROCADE
+
+source "drivers/net/ethernet/brocade/bna/Kconfig"
+
+endif # NET_VENDOR_BROCADE
diff --git a/drivers/net/ethernet/brocade/Makefile b/drivers/net/ethernet/brocade/Makefile
new file mode 100644
index 000000000000..b58238d2df6a
--- /dev/null
+++ b/drivers/net/ethernet/brocade/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Brocade device drivers.
+#
+
+obj-$(CONFIG_BNA) += bna/
diff --git a/drivers/net/ethernet/brocade/bna/Kconfig b/drivers/net/ethernet/brocade/bna/Kconfig
new file mode 100644
index 000000000000..dc2eb526fbf7
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/Kconfig
@@ -0,0 +1,17 @@
+#
+# Brocade network device configuration
+#
+
+config BNA
+ tristate "Brocade 1010/1020 10Gb Ethernet Driver support"
+ depends on PCI
+ ---help---
+ This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet
+ cards.
+ To compile this driver as a module, choose M here: the module
+ will be called bna.
+
+ For general information and support, go to the Brocade support
+ website at:
+
+ <http://support.brocade.com>
diff --git a/drivers/net/bna/Makefile b/drivers/net/ethernet/brocade/bna/Makefile
index a5d604de7fea..74d3abca1960 100644
--- a/drivers/net/bna/Makefile
+++ b/drivers/net/ethernet/brocade/bna/Makefile
@@ -5,7 +5,8 @@
obj-$(CONFIG_BNA) += bna.o
-bna-objs := bnad.o bnad_ethtool.o bna_ctrl.o bna_txrx.o
-bna-objs += bfa_ioc.o bfa_ioc_ct.o bfa_cee.o cna_fwimg.o
+bna-objs := bnad.o bnad_ethtool.o bna_enet.o bna_tx_rx.o
+bna-objs += bfa_msgq.o bfa_ioc.o bfa_ioc_ct.o bfa_cee.o
+bna-objs += cna_fwimg.o
EXTRA_CFLAGS := -Idrivers/net/bna
diff --git a/drivers/net/bna/bfa_cee.c b/drivers/net/ethernet/brocade/bna/bfa_cee.c
index 39e5ab9fde59..8e627186507c 100644
--- a/drivers/net/bna/bfa_cee.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_cee.c
@@ -16,15 +16,10 @@
* www.brocade.com
*/
-#include "bfa_defs_cna.h"
-#include "cna.h"
#include "bfa_cee.h"
#include "bfi_cna.h"
#include "bfa_ioc.h"
-#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
-
static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg);
static void bfa_cee_format_cee_cfg(void *buffer);
diff --git a/drivers/net/bna/bfa_cee.h b/drivers/net/ethernet/brocade/bna/bfa_cee.h
index 58d54e98d595..58d54e98d595 100644
--- a/drivers/net/bna/bfa_cee.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_cee.h
diff --git a/drivers/net/bna/bfa_cs.h b/drivers/net/ethernet/brocade/bna/bfa_cs.h
index 3da1a946ccdd..3da1a946ccdd 100644
--- a/drivers/net/bna/bfa_cs.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_cs.h
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/ethernet/brocade/bna/bfa_defs.h
index b080b3698f48..2f12d68021d5 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_defs.h
@@ -124,6 +124,7 @@ enum bfa_ioc_state {
BFA_IOC_DISABLED = 10, /*!< IOC is disabled */
BFA_IOC_FWMISMATCH = 11, /*!< IOC f/w different from drivers */
BFA_IOC_ENABLING = 12, /*!< IOC is being enabled */
+ BFA_IOC_HWFAIL = 13, /*!< PCI mapping doesn't exist */
};
/**
@@ -179,8 +180,20 @@ struct bfa_ioc_attr {
struct bfa_adapter_attr adapter_attr; /*!< HBA attributes */
struct bfa_ioc_driver_attr driver_attr; /*!< driver attr */
struct bfa_ioc_pci_attr pci_attr;
- u8 port_id; /*!< port number */
- u8 rsvd[7]; /*!< 64bit align */
+ u8 port_id; /*!< port number */
+ u8 port_mode; /*!< enum bfa_mode */
+ u8 cap_bm; /*!< capability */
+ u8 port_mode_cfg; /*!< enum bfa_mode */
+ u8 rsvd[4]; /*!< 64bit align */
+};
+
+/**
+ * Adapter capability mask definition
+ */
+enum {
+ BFA_CM_HBA = 0x01,
+ BFA_CM_CNA = 0x02,
+ BFA_CM_NIC = 0x04,
};
/**
@@ -228,8 +241,18 @@ struct bfa_mfg_block {
mac_t mfg_mac; /*!< mac address */
u8 num_mac; /*!< number of mac addresses */
u8 rsv2;
- u32 mfg_type; /*!< card type */
- u8 rsv3[108];
+ u32 card_type; /*!< card type */
+ char cap_nic; /*!< capability nic */
+ char cap_cna; /*!< capability cna */
+ char cap_hba; /*!< capability hba */
+ char cap_fc16g; /*!< capability fc 16g */
+ char cap_sriov; /*!< capability sriov */
+ char cap_mezz; /*!< capability mezz */
+ u8 rsv3;
+ u8 mfg_nports; /*!< number of ports */
+ char media[8]; /*!< xfi/xaui */
+ char initial_mode[8];/*!< initial mode: hba/cna/nic */
+ u8 rsv4[84];
u8 md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */
};
@@ -239,8 +262,35 @@ struct bfa_mfg_block {
* ---------------------- pci definitions ------------
*/
-#define bfa_asic_id_ct(devid) \
- ((devid) == PCI_DEVICE_ID_BROCADE_CT || \
- (devid) == PCI_DEVICE_ID_BROCADE_CT_FC)
+/*
+ * PCI device ID information
+ */
+enum {
+ BFA_PCI_DEVICE_ID_CT2 = 0x22,
+};
+
+#define bfa_asic_id_ct(device) \
+ ((device) == PCI_DEVICE_ID_BROCADE_CT || \
+ (device) == PCI_DEVICE_ID_BROCADE_CT_FC)
+#define bfa_asic_id_ct2(device) \
+ ((device) == BFA_PCI_DEVICE_ID_CT2)
+#define bfa_asic_id_ctc(device) \
+ (bfa_asic_id_ct(device) || bfa_asic_id_ct2(device))
+
+/**
+ * PCI sub-system device and vendor ID information
+ */
+enum {
+ BFA_PCI_FCOE_SSDEVICE_ID = 0x14,
+ BFA_PCI_CT2_SSID_FCoE = 0x22,
+ BFA_PCI_CT2_SSID_ETH = 0x23,
+ BFA_PCI_CT2_SSID_FC = 0x24,
+};
+
+enum bfa_mode {
+ BFA_MODE_HBA = 1,
+ BFA_MODE_CNA = 2,
+ BFA_MODE_NIC = 3
+};
#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/net/bna/bfa_defs_cna.h b/drivers/net/ethernet/brocade/bna/bfa_defs_cna.h
index 7e0a9187bdd5..8ab33ee2c2bc 100644
--- a/drivers/net/bna/bfa_defs_cna.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_defs_cna.h
@@ -15,7 +15,6 @@
* All rights reserved
* www.brocade.com
*/
-
#ifndef __BFA_DEFS_CNA_H__
#define __BFA_DEFS_CNA_H__
@@ -55,6 +54,9 @@ struct bfa_port_fc_stats {
u64 bad_os_count; /*!< Invalid ordered sets */
u64 err_enc_out; /*!< Encoding err nonframe_8b10b */
u64 err_enc; /*!< Encoding err frame_8b10b */
+ u64 bbsc_frames_lost; /*!< Credit Recovery-Frames Lost */
+ u64 bbsc_credits_lost; /*!< Credit Recovery-Credits Lost */
+ u64 bbsc_link_resets; /*!< Credit Recovery-Link Resets */
};
/**
@@ -100,6 +102,10 @@ struct bfa_port_eth_stats {
u64 rx_fcoe_zero_pause; /*!< Rx FCoE zero pause */
u64 tx_fcoe_pause; /*!< Tx FCoE pause */
u64 tx_fcoe_zero_pause; /*!< Tx FCoE zero pause */
+ u64 rx_iscsi_pause; /*!< Rx iSCSI pause */
+ u64 rx_iscsi_zero_pause; /*!< Rx iSCSI zero pause */
+ u64 tx_iscsi_pause; /*!< Tx iSCSI pause */
+ u64 tx_iscsi_zero_pause; /*!< Tx iSCSI zero pause */
};
/**
diff --git a/drivers/net/bna/bfa_defs_mfg_comm.h b/drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h
index 885ef3afdd4e..6681fe87c1e1 100644
--- a/drivers/net/bna/bfa_defs_mfg_comm.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h
@@ -18,12 +18,12 @@
#ifndef __BFA_DEFS_MFG_COMM_H__
#define __BFA_DEFS_MFG_COMM_H__
-#include "cna.h"
+#include "bfa_defs.h"
/**
* Manufacturing block version
*/
-#define BFA_MFG_VERSION 2
+#define BFA_MFG_VERSION 3
#define BFA_MFG_VERSION_UNINIT 0xFF
/**
@@ -60,20 +60,17 @@ enum {
BFA_MFG_TYPE_ASTRA = 807, /*!< Astra mezz card */
BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*!< Lightning mezz card - old */
BFA_MFG_TYPE_LIGHTNING = 1741, /*!< Lightning mezz card */
+ BFA_MFG_TYPE_PROWLER_F = 1560, /*!< Prowler FC only cards */
+ BFA_MFG_TYPE_PROWLER_N = 1410, /*!< Prowler NIC only cards */
+ BFA_MFG_TYPE_PROWLER_C = 1710, /*!< Prowler CNA only cards */
+ BFA_MFG_TYPE_PROWLER_D = 1860, /*!< Prowler Dual cards */
+ BFA_MFG_TYPE_CHINOOK = 1867, /*!< Chinook cards */
BFA_MFG_TYPE_INVALID = 0, /*!< Invalid card type */
};
#pragma pack(1)
/**
- * Check if 1-port card
- */
-#define bfa_mfg_is_1port(type) (( \
- (type) == BFA_MFG_TYPE_FC8P1 || \
- (type) == BFA_MFG_TYPE_FC4P1 || \
- (type) == BFA_MFG_TYPE_CNA10P1))
-
-/**
* Check if Mezz card
*/
#define bfa_mfg_is_mezz(type) (( \
@@ -81,56 +78,8 @@ enum {
(type) == BFA_MFG_TYPE_WANCHESE || \
(type) == BFA_MFG_TYPE_ASTRA || \
(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
- (type) == BFA_MFG_TYPE_LIGHTNING))
-
-/**
- * Check if card type valid
- */
-#define bfa_mfg_is_card_type_valid(type) (( \
- (type) == BFA_MFG_TYPE_FC8P2 || \
- (type) == BFA_MFG_TYPE_FC8P1 || \
- (type) == BFA_MFG_TYPE_FC4P2 || \
- (type) == BFA_MFG_TYPE_FC4P1 || \
- (type) == BFA_MFG_TYPE_CNA10P2 || \
- (type) == BFA_MFG_TYPE_CNA10P1 || \
- bfa_mfg_is_mezz(type)))
-
-#define bfa_mfg_adapter_prop_init_flash(card_type, prop) \
-do { \
- switch ((card_type)) { \
- case BFA_MFG_TYPE_FC8P2: \
- case BFA_MFG_TYPE_JAYHAWK: \
- case BFA_MFG_TYPE_ASTRA: \
- (prop) = BFI_ADAPTER_SETP(NPORTS, 2) | \
- BFI_ADAPTER_SETP(SPEED, 8); \
- break; \
- case BFA_MFG_TYPE_FC8P1: \
- (prop) = BFI_ADAPTER_SETP(NPORTS, 1) | \
- BFI_ADAPTER_SETP(SPEED, 8); \
- break; \
- case BFA_MFG_TYPE_FC4P2: \
- (prop) = BFI_ADAPTER_SETP(NPORTS, 2) | \
- BFI_ADAPTER_SETP(SPEED, 4); \
- break; \
- case BFA_MFG_TYPE_FC4P1: \
- (prop) = BFI_ADAPTER_SETP(NPORTS, 1) | \
- BFI_ADAPTER_SETP(SPEED, 4); \
- break; \
- case BFA_MFG_TYPE_CNA10P2: \
- case BFA_MFG_TYPE_WANCHESE: \
- case BFA_MFG_TYPE_LIGHTNING_P0: \
- case BFA_MFG_TYPE_LIGHTNING: \
- (prop) = BFI_ADAPTER_SETP(NPORTS, 2); \
- (prop) |= BFI_ADAPTER_SETP(SPEED, 10); \
- break; \
- case BFA_MFG_TYPE_CNA10P1: \
- (prop) = BFI_ADAPTER_SETP(NPORTS, 1); \
- (prop) |= BFI_ADAPTER_SETP(SPEED, 10); \
- break; \
- default: \
- (prop) = BFI_ADAPTER_UNSUPP; \
- } \
-} while (0)
+ (type) == BFA_MFG_TYPE_LIGHTNING || \
+ (type) == BFA_MFG_TYPE_CHINOOK))
enum {
CB_GPIO_TTV = (1), /*!< TTV debug capable cards */
diff --git a/drivers/net/bna/bfa_defs_status.h b/drivers/net/ethernet/brocade/bna/bfa_defs_status.h
index 7c5fe6c2e80e..7c5fe6c2e80e 100644
--- a/drivers/net/bna/bfa_defs_status.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_defs_status.h
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index 126b0aac9f94..b0307a00a109 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -17,9 +17,7 @@
*/
#include "bfa_ioc.h"
-#include "cna.h"
-#include "bfi.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
#include "bfa_defs.h"
/**
@@ -62,6 +60,7 @@ static void bfa_ioc_hw_sem_init(struct bfa_ioc *ioc);
static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
+static void bfa_ioc_poll_fwinit(struct bfa_ioc *ioc);
static void bfa_ioc_send_enable(struct bfa_ioc *ioc);
static void bfa_ioc_send_disable(struct bfa_ioc *ioc);
static void bfa_ioc_send_getattr(struct bfa_ioc *ioc);
@@ -78,8 +77,8 @@ static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);
static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc);
static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);
-static void bfa_ioc_pf_initfailed(struct bfa_ioc *ioc);
static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);
+static void bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc);
static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
u32 boot_param);
@@ -108,11 +107,11 @@ enum ioc_event {
IOC_E_ENABLED = 5, /*!< f/w enabled */
IOC_E_FWRSP_GETATTR = 6, /*!< IOC get attribute response */
IOC_E_DISABLED = 7, /*!< f/w disabled */
- IOC_E_INITFAILED = 8, /*!< failure notice by iocpf sm */
- IOC_E_PFFAILED = 9, /*!< failure notice by iocpf sm */
- IOC_E_HBFAIL = 10, /*!< heartbeat failure */
- IOC_E_HWERROR = 11, /*!< hardware error interrupt */
- IOC_E_TIMEOUT = 12, /*!< timeout */
+ IOC_E_PFFAILED = 8, /*!< failure notice by iocpf sm */
+ IOC_E_HBFAIL = 9, /*!< heartbeat failure */
+ IOC_E_HWERROR = 10, /*!< hardware error interrupt */
+ IOC_E_TIMEOUT = 11, /*!< timeout */
+ IOC_E_HWFAILED = 12, /*!< PCI mapping failure notice */
};
bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
@@ -124,6 +123,7 @@ bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc, enum ioc_event);
static struct bfa_sm_table ioc_sm_table[] = {
{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
@@ -135,12 +135,9 @@ static struct bfa_sm_table ioc_sm_table[] = {
{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
+ {BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
};
-/**
- * IOCPF state machine definitions/declarations
- */
-
/*
* Forward declareations for iocpf state machine
*/
@@ -166,6 +163,7 @@ enum iocpf_event {
IOCPF_E_GETATTRFAIL = 9, /*!< init fail notice by ioc sm */
IOCPF_E_SEMLOCKED = 10, /*!< h/w semaphore is locked */
IOCPF_E_TIMEOUT = 11, /*!< f/w response timeout */
+ IOCPF_E_SEM_ERROR = 12, /*!< h/w sem mapping error */
};
/**
@@ -300,11 +298,16 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
/* !!! fall through !!! */
case IOC_E_HWERROR:
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
if (event != IOC_E_PFFAILED)
bfa_iocpf_initfail(ioc);
break;
+ case IOC_E_HWFAILED:
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+ break;
+
case IOC_E_DISABLE:
bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
break;
@@ -343,6 +346,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
case IOC_E_FWRSP_GETATTR:
del_timer(&ioc->ioc_timer);
bfa_ioc_check_attr_wwns(ioc);
+ bfa_ioc_hb_monitor(ioc);
bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
break;
@@ -352,7 +356,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
/* fall through */
case IOC_E_TIMEOUT:
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
if (event != IOC_E_PFFAILED)
bfa_iocpf_getattrfail(ioc);
break;
@@ -374,7 +378,7 @@ static void
bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
{
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
- bfa_ioc_hb_monitor(ioc);
+ bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
}
static void
@@ -394,12 +398,13 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
bfa_ioc_hb_stop(ioc);
/* !!! fall through !!! */
case IOC_E_HBFAIL:
- bfa_ioc_fail_notify(ioc);
if (ioc->iocpf.auto_recover)
bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
else
bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+ bfa_ioc_fail_notify(ioc);
+
if (event != IOC_E_PFFAILED)
bfa_iocpf_fail(ioc);
break;
@@ -416,7 +421,7 @@ bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
}
/**
- * IOC is being desabled
+ * IOC is being disabled
*/
static void
bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
@@ -435,13 +440,18 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
bfa_iocpf_fail(ioc);
break;
+ case IOC_E_HWFAILED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+ bfa_ioc_disable_comp(ioc);
+ break;
+
default:
bfa_sm_fault(event);
}
}
/**
- * IOC desable completion entry.
+ * IOC disable completion entry.
*/
static void
bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
@@ -493,12 +503,14 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
* Initialization retry failed.
*/
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
if (event != IOC_E_PFFAILED)
bfa_iocpf_initfail(ioc);
break;
- case IOC_E_INITFAILED:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+ case IOC_E_HWFAILED:
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
break;
case IOC_E_ENABLE:
@@ -552,6 +564,36 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
}
}
+static void
+bfa_ioc_sm_hwfail_entry(struct bfa_ioc *ioc)
+{
+}
+
+/**
+ * IOC failure.
+ */
+static void
+bfa_ioc_sm_hwfail(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+
+ case IOC_E_ENABLE:
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ break;
+
+ case IOC_E_DISABLE:
+ ioc->cbfn->disable_cbfn(ioc->bfa);
+ break;
+
+ case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
/**
* IOCPF State Machine
*/
@@ -562,7 +604,7 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
static void
bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf)
{
- iocpf->retry_count = 0;
+ iocpf->fw_mismatch_notified = false;
iocpf->auto_recover = bfa_nw_auto_recover;
}
@@ -607,7 +649,6 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
case IOCPF_E_SEMLOCKED:
if (bfa_ioc_firmware_lock(ioc)) {
if (bfa_ioc_sync_start(ioc)) {
- iocpf->retry_count = 0;
bfa_ioc_sync_join(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
} else {
@@ -622,6 +663,11 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
}
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_ioc_pf_hwfailed(ioc);
+ break;
+
case IOCPF_E_DISABLE:
bfa_ioc_hw_sem_get_cancel(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
@@ -645,10 +691,10 @@ static void
bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf)
{
/* Call only the first time sm enters fwmismatch state. */
- if (iocpf->retry_count == 0)
+ if (iocpf->fw_mismatch_notified == false)
bfa_ioc_pf_fwmismatch(iocpf->ioc);
- iocpf->retry_count++;
+ iocpf->fw_mismatch_notified = true;
mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
msecs_to_jiffies(BFA_IOC_TOV));
}
@@ -711,6 +757,11 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
}
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_ioc_pf_hwfailed(ioc);
+ break;
+
case IOCPF_E_DISABLE:
bfa_ioc_hw_sem_get_cancel(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -724,9 +775,8 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf)
{
- mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
- msecs_to_jiffies(BFA_IOC_TOV));
- bfa_ioc_reset(iocpf->ioc, 0);
+ iocpf->poll_time = 0;
+ bfa_ioc_reset(iocpf->ioc, false);
}
/**
@@ -740,19 +790,11 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_FWREADY:
- del_timer(&ioc->iocpf_timer);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
break;
- case IOCPF_E_INITFAIL:
- del_timer(&ioc->iocpf_timer);
- /*
- * !!! fall through !!!
- */
-
case IOCPF_E_TIMEOUT:
bfa_nw_ioc_hw_sem_release(ioc);
- if (event == IOCPF_E_TIMEOUT)
bfa_ioc_pf_failed(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
break;
@@ -774,6 +816,10 @@ bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf)
{
mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
msecs_to_jiffies(BFA_IOC_TOV));
+ /**
+ * Enable Interrupts before sending fw IOC ENABLE cmd.
+ */
+ iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
bfa_ioc_send_enable(iocpf->ioc);
}
@@ -811,21 +857,11 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
break;
- case IOCPF_E_FWREADY:
- bfa_ioc_send_enable(ioc);
- break;
-
default:
bfa_sm_fault(event);
}
}
-static bool
-bfa_nw_ioc_is_operational(struct bfa_ioc *ioc)
-{
- return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
-}
-
static void
bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)
{
@@ -835,8 +871,6 @@ bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)
static void
bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
{
- struct bfa_ioc *ioc = iocpf->ioc;
-
switch (event) {
case IOCPF_E_DISABLE:
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
@@ -850,14 +884,6 @@ bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
break;
- case IOCPF_E_FWREADY:
- bfa_ioc_pf_failed(ioc);
- if (bfa_nw_ioc_is_operational(ioc))
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
- else
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
- break;
-
default:
bfa_sm_fault(event);
}
@@ -881,7 +907,6 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_FWRSP_DISABLE:
- case IOCPF_E_FWREADY:
del_timer(&ioc->iocpf_timer);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
break;
@@ -926,6 +951,11 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_ioc_pf_hwfailed(ioc);
+ break;
+
case IOCPF_E_FAIL:
break;
@@ -951,7 +981,6 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_ENABLE:
- iocpf->retry_count = 0;
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
break;
@@ -982,20 +1011,15 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_SEMLOCKED:
bfa_ioc_notify_fail(ioc);
- bfa_ioc_sync_ack(ioc);
- iocpf->retry_count++;
- if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) {
- bfa_ioc_sync_leave(ioc);
- bfa_nw_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
- } else {
- if (bfa_ioc_sync_complete(ioc))
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
- else {
- bfa_nw_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
- }
- }
+ bfa_ioc_sync_leave(ioc);
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+ break;
+
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_ioc_pf_hwfailed(ioc);
break;
case IOCPF_E_DISABLE:
@@ -1020,7 +1044,6 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_initfail_entry(struct bfa_iocpf *iocpf)
{
- bfa_ioc_pf_initfailed(iocpf->ioc);
}
/**
@@ -1071,11 +1094,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_SEMLOCKED:
- iocpf->retry_count = 0;
bfa_ioc_sync_ack(ioc);
bfa_ioc_notify_fail(ioc);
if (!iocpf->auto_recover) {
bfa_ioc_sync_leave(ioc);
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
bfa_nw_ioc_hw_sem_release(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
} else {
@@ -1088,6 +1111,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
}
break;
+ case IOCPF_E_SEM_ERROR:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_ioc_pf_hwfailed(ioc);
+ break;
+
case IOCPF_E_DISABLE:
bfa_ioc_hw_sem_get_cancel(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -1158,22 +1186,22 @@ bfa_nw_ioc_sem_get(void __iomem *sem_reg)
r32 = readl(sem_reg);
- while (r32 && (cnt < BFA_SEM_SPINCNT)) {
+ while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {
cnt++;
udelay(2);
r32 = readl(sem_reg);
}
- if (r32 == 0)
+ if (!(r32 & 1))
return true;
- BUG_ON(!(cnt < BFA_SEM_SPINCNT));
return false;
}
void
bfa_nw_ioc_sem_release(void __iomem *sem_reg)
{
+ readl(sem_reg);
writel(1, sem_reg);
}
@@ -1210,7 +1238,11 @@ bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
* will return 1. Semaphore is released by writing 1 to the register
*/
r32 = readl(ioc->ioc_regs.ioc_sem_reg);
- if (r32 == 0) {
+ if (r32 == ~0) {
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);
+ return;
+ }
+ if (!(r32 & 1)) {
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
return;
}
@@ -1331,7 +1363,7 @@ bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
int i;
drv_fwhdr = (struct bfi_ioc_image_hdr *)
- bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+ bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i])
@@ -1352,12 +1384,12 @@ bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env)
bfa_nw_ioc_fwver_get(ioc, &fwhdr);
drv_fwhdr = (struct bfi_ioc_image_hdr *)
- bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+ bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
if (fwhdr.signature != drv_fwhdr->signature)
return false;
- if (swab32(fwhdr.param) != boot_env)
+ if (swab32(fwhdr.bootenv) != boot_env)
return false;
return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr);
@@ -1388,11 +1420,11 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
- boot_env = BFI_BOOT_LOADER_OS;
-
if (force)
ioc_fwstate = BFI_IOC_UNINIT;
+ boot_env = BFI_FWBOOT_ENV_OS;
+
/**
* check if firmware is valid
*/
@@ -1400,7 +1432,8 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
false : bfa_ioc_fwver_valid(ioc, boot_env);
if (!fwvalid) {
- bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
+ bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env);
+ bfa_ioc_poll_fwinit(ioc);
return;
}
@@ -1409,7 +1442,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
* just wait for an initialization completion interrupt.
*/
if (ioc_fwstate == BFI_IOC_INITING) {
- ioc->cbfn->reset_cbfn(ioc->bfa);
+ bfa_ioc_poll_fwinit(ioc);
return;
}
@@ -1423,7 +1456,6 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
* be flushed. Otherwise MSI-X interrupts are not delivered.
*/
bfa_ioc_msgflush(ioc);
- ioc->cbfn->reset_cbfn(ioc->bfa);
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
return;
}
@@ -1431,7 +1463,8 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
/**
* Initialize the h/w for any other states.
*/
- bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
+ bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env);
+ bfa_ioc_poll_fwinit(ioc);
}
void
@@ -1475,7 +1508,7 @@ bfa_ioc_send_enable(struct bfa_ioc *ioc)
bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
bfa_ioc_portid(ioc));
- enable_req.ioc_class = ioc->ioc_mc;
+ enable_req.clscode = htons(ioc->clscode);
do_gettimeofday(&tv);
enable_req.tv_sec = ntohl(tv.tv_sec);
bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req));
@@ -1548,22 +1581,23 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
u32 loff = 0;
u32 chunkno = 0;
u32 i;
+ u32 asicmode;
/**
* Initialize LMEM first before code download
*/
bfa_ioc_lmem_init(ioc);
- fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
+ fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
pgnum = bfa_ioc_smem_pgnum(ioc, loff);
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
- for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
+ for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) {
if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
- fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
+ fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
}
@@ -1590,12 +1624,16 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
ioc->ioc_regs.host_page_num_fn);
/*
- * Set boot type and boot param at the end.
+ * Set boot type, env and device mode at the end.
*/
+ asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
+ ioc->port0_mode, ioc->port1_mode);
+ writel(asicmode, ((ioc->ioc_regs.smem_page_start)
+ + BFI_FWBOOT_DEVMODE_OFF));
writel(boot_type, ((ioc->ioc_regs.smem_page_start)
- + (BFI_BOOT_TYPE_OFF)));
+ + (BFI_FWBOOT_TYPE_OFF)));
writel(boot_env, ((ioc->ioc_regs.smem_page_start)
- + (BFI_BOOT_LOADER_OFF)));
+ + (BFI_FWBOOT_ENV_OFF)));
}
static void
@@ -1605,6 +1643,20 @@ bfa_ioc_reset(struct bfa_ioc *ioc, bool force)
}
/**
+ * BFA ioc enable reply by firmware
+ */
+static void
+bfa_ioc_enable_reply(struct bfa_ioc *ioc, enum bfa_mode port_mode,
+ u8 cap_bm)
+{
+ struct bfa_iocpf *iocpf = &ioc->iocpf;
+
+ ioc->port_mode = ioc->port_mode_cfg = port_mode;
+ ioc->ad_cap_bm = cap_bm;
+ bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
+}
+
+/**
* @brief
* Update BFA configuration from firmware configuration.
*/
@@ -1644,7 +1696,9 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
{
struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
struct bfa_mbox_cmd *cmd;
- u32 stat;
+ bfa_mbox_cmd_cbfn_t cbfn;
+ void *cbarg;
+ u32 stat;
/**
* If no command pending, do nothing
@@ -1664,6 +1718,16 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
*/
bfa_q_deq(&mod->cmd_q, &cmd);
bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+
+ /**
+ * Give a callback to the client, indicating that the command is sent
+ */
+ if (cmd->cbfn) {
+ cbfn = cmd->cbfn;
+ cbarg = cmd->cbarg;
+ cmd->cbfn = NULL;
+ cbfn(cbarg);
+ }
}
/**
@@ -1689,6 +1753,9 @@ bfa_ioc_fail_notify(struct bfa_ioc *ioc)
bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
}
+/**
+ * IOCPF to IOC interface
+ */
static void
bfa_ioc_pf_enabled(struct bfa_ioc *ioc)
{
@@ -1702,15 +1769,15 @@ bfa_ioc_pf_disabled(struct bfa_ioc *ioc)
}
static void
-bfa_ioc_pf_initfailed(struct bfa_ioc *ioc)
+bfa_ioc_pf_failed(struct bfa_ioc *ioc)
{
- bfa_fsm_send_event(ioc, IOC_E_INITFAILED);
+ bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
}
static void
-bfa_ioc_pf_failed(struct bfa_ioc *ioc)
+bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc)
{
- bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+ bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
}
static void
@@ -1749,10 +1816,9 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc)
* as the entry vector.
*/
static void
-bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env)
+bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
+ u32 boot_env)
{
- void __iomem *rb;
-
bfa_ioc_stats(ioc, ioc_boots);
if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
@@ -1761,22 +1827,16 @@ bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env)
/**
* Initialize IOC state of all functions on a chip reset.
*/
- rb = ioc->pcidev.pci_bar_kva;
- if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
- writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
- writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
+ if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
+ writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
} else {
- writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
- writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
+ writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
}
bfa_ioc_msgflush(ioc);
bfa_ioc_download_fw(ioc, boot_type, boot_env);
-
- /**
- * Enable interrupts just before starting LPU
- */
- ioc->cbfn->reset_cbfn(ioc->bfa);
bfa_ioc_lpu_start(ioc);
}
@@ -1789,13 +1849,17 @@ bfa_nw_ioc_auto_recover(bool auto_recover)
bfa_nw_auto_recover = auto_recover;
}
-static void
+static bool
bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
{
u32 *msgp = mbmsg;
u32 r32;
int i;
+ r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
+ if ((r32 & 1) == 0)
+ return false;
+
/**
* read the MBOX msg
*/
@@ -1811,6 +1875,8 @@ bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
*/
writel(1, ioc->ioc_regs.lpu_mbox_cmd);
readl(ioc->ioc_regs.lpu_mbox_cmd);
+
+ return true;
}
static void
@@ -1827,12 +1893,10 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
case BFI_IOC_I2H_HBEAT:
break;
- case BFI_IOC_I2H_READY_EVENT:
- bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
- break;
-
case BFI_IOC_I2H_ENABLE_REPLY:
- bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
+ bfa_ioc_enable_reply(ioc,
+ (enum bfa_mode)msg->fw_event.port_mode,
+ msg->fw_event.cap_bm);
break;
case BFI_IOC_I2H_DISABLE_REPLY:
@@ -1878,6 +1942,9 @@ void
bfa_nw_ioc_detach(struct bfa_ioc *ioc)
{
bfa_fsm_send_event(ioc, IOC_E_DETACH);
+
+ /* Done with detach, empty the notify_q. */
+ INIT_LIST_HEAD(&ioc->notify_q);
}
/**
@@ -1887,14 +1954,63 @@ bfa_nw_ioc_detach(struct bfa_ioc *ioc)
*/
void
bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
- enum bfi_mclass mc)
+ enum bfi_pcifn_class clscode)
{
- ioc->ioc_mc = mc;
+ ioc->clscode = clscode;
ioc->pcidev = *pcidev;
- ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id);
- ioc->cna = ioc->ctdev && !ioc->fcmode;
- bfa_nw_ioc_set_ct_hwif(ioc);
+ /**
+ * Initialize IOC and device personality
+ */
+ ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC;
+ ioc->asic_mode = BFI_ASIC_MODE_FC;
+
+ switch (pcidev->device_id) {
+ case PCI_DEVICE_ID_BROCADE_CT:
+ ioc->asic_gen = BFI_ASIC_GEN_CT;
+ ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
+ ioc->asic_mode = BFI_ASIC_MODE_ETH;
+ ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA;
+ ioc->ad_cap_bm = BFA_CM_CNA;
+ break;
+
+ case BFA_PCI_DEVICE_ID_CT2:
+ ioc->asic_gen = BFI_ASIC_GEN_CT2;
+ if (clscode == BFI_PCIFN_CLASS_FC &&
+ pcidev->ssid == BFA_PCI_CT2_SSID_FC) {
+ ioc->asic_mode = BFI_ASIC_MODE_FC16;
+ ioc->fcmode = true;
+ ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
+ ioc->ad_cap_bm = BFA_CM_HBA;
+ } else {
+ ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
+ ioc->asic_mode = BFI_ASIC_MODE_ETH;
+ if (pcidev->ssid == BFA_PCI_CT2_SSID_FCoE) {
+ ioc->port_mode =
+ ioc->port_mode_cfg = BFA_MODE_CNA;
+ ioc->ad_cap_bm = BFA_CM_CNA;
+ } else {
+ ioc->port_mode =
+ ioc->port_mode_cfg = BFA_MODE_NIC;
+ ioc->ad_cap_bm = BFA_CM_NIC;
+ }
+ }
+ break;
+
+ default:
+ BUG_ON(1);
+ }
+
+ /**
+ * Set asic specific interfaces.
+ */
+ if (ioc->asic_gen == BFI_ASIC_GEN_CT)
+ bfa_nw_ioc_set_ct_hwif(ioc);
+ else {
+ WARN_ON(ioc->asic_gen != BFI_ASIC_GEN_CT2);
+ bfa_nw_ioc_set_ct2_hwif(ioc);
+ bfa_nw_ioc_ct2_poweron(ioc);
+ }
bfa_ioc_map_port(ioc);
bfa_ioc_reg_init(ioc);
@@ -1968,18 +2084,22 @@ bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
* @param[in] ioc IOC instance
* @param[i] cmd Mailbox command
*/
-void
-bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
+bool
+bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd,
+ bfa_mbox_cmd_cbfn_t cbfn, void *cbarg)
{
struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
u32 stat;
+ cmd->cbfn = cbfn;
+ cmd->cbarg = cbarg;
+
/**
* If a previous command is pending, queue new command
*/
if (!list_empty(&mod->cmd_q)) {
list_add_tail(&cmd->qe, &mod->cmd_q);
- return;
+ return true;
}
/**
@@ -1988,7 +2108,7 @@ bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
if (stat) {
list_add_tail(&cmd->qe, &mod->cmd_q);
- return;
+ return true;
}
/**
@@ -1996,7 +2116,7 @@ bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
*/
bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
- return;
+ return false;
}
/**
@@ -2009,21 +2129,28 @@ bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
struct bfi_mbmsg m;
int mc;
- bfa_ioc_msgget(ioc, &m);
+ if (bfa_ioc_msgget(ioc, &m)) {
+ /**
+ * Treat IOC message class as special.
+ */
+ mc = m.mh.msg_class;
+ if (mc == BFI_MC_IOC) {
+ bfa_ioc_isr(ioc, &m);
+ return;
+ }
- /**
- * Treat IOC message class as special.
- */
- mc = m.mh.msg_class;
- if (mc == BFI_MC_IOC) {
- bfa_ioc_isr(ioc, &m);
- return;
+ if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
+ return;
+
+ mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
}
- if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
- return;
+ bfa_ioc_lpu_read_stat(ioc);
- mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
+ /**
+ * Try to send pending mailbox commands
+ */
+ bfa_ioc_mbox_poll(ioc);
}
void
@@ -2095,24 +2222,18 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc,
ad_attr->asic_rev = ioc_attr->asic_rev;
bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
-
- ad_attr->cna_capable = ioc->cna;
- ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
}
static enum bfa_ioc_type
bfa_ioc_get_type(struct bfa_ioc *ioc)
{
- if (!ioc->ctdev || ioc->fcmode)
- return BFA_IOC_TYPE_FC;
- else if (ioc->ioc_mc == BFI_MC_IOCFC)
- return BFA_IOC_TYPE_FCoE;
- else if (ioc->ioc_mc == BFI_MC_LL)
- return BFA_IOC_TYPE_LL;
- else {
- BUG_ON(!(ioc->ioc_mc == BFI_MC_LL));
+ if (ioc->clscode == BFI_PCIFN_CLASS_ETH)
return BFA_IOC_TYPE_LL;
- }
+
+ BUG_ON(!(ioc->clscode == BFI_PCIFN_CLASS_FC));
+
+ return (ioc->attr->port_mode == BFI_PORT_MODE_FC)
+ ? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;
}
static void
@@ -2171,9 +2292,6 @@ bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model)
ioc_attr = ioc->attr;
- /**
- * model name
- */
snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
BFA_MFG_NAME, ioc_attr->card_type);
}
@@ -2224,6 +2342,10 @@ bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)
ioc_attr->state = bfa_ioc_get_state(ioc);
ioc_attr->port_id = ioc->port_id;
+ ioc_attr->port_mode = ioc->port_mode;
+
+ ioc_attr->port_mode_cfg = ioc->port_mode_cfg;
+ ioc_attr->cap_bm = ioc->ad_cap_bm;
ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
@@ -2313,8 +2435,14 @@ void
bfa_nw_iocpf_timeout(void *ioc_arg)
{
struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
+ enum bfa_iocpf_state iocpf_st;
+
+ iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
- bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
+ if (iocpf_st == BFA_IOCPF_HWINIT)
+ bfa_ioc_poll_fwinit(ioc);
+ else
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
}
void
@@ -2324,3 +2452,22 @@ bfa_nw_iocpf_sem_timeout(void *ioc_arg)
bfa_ioc_hw_sem_get(ioc);
}
+
+static void
+bfa_ioc_poll_fwinit(struct bfa_ioc *ioc)
+{
+ u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+ if (fwstate == BFI_IOC_DISABLED) {
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
+ return;
+ }
+
+ if (ioc->iocpf.poll_time >= BFA_IOC_TOV) {
+ bfa_nw_iocpf_timeout(ioc);
+ } else {
+ ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
+ mod_timer(&ioc->iocpf_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_POLL_TOV));
+ }
+}
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/ethernet/brocade/bna/bfa_ioc.h
index bda866ba6e90..ca158d1eaef3 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.h
@@ -26,7 +26,7 @@
#define BFA_IOC_TOV 3000 /* msecs */
#define BFA_IOC_HWSEM_TOV 500 /* msecs */
#define BFA_IOC_HB_TOV 500 /* msecs */
-#define BFA_IOC_HWINIT_MAX 5
+#define BFA_IOC_POLL_TOV 200 /* msecs */
/**
* PCI device information required by IOC
@@ -35,6 +35,7 @@ struct bfa_pcidev {
int pci_slot;
u8 pci_func;
u16 device_id;
+ u16 ssid;
void __iomem *pci_bar_kva;
};
@@ -72,6 +73,7 @@ struct bfa_ioc_regs {
void __iomem *hfn_mbox;
void __iomem *lpu_mbox_cmd;
void __iomem *lpu_mbox;
+ void __iomem *lpu_read_stat;
void __iomem *pss_ctl_reg;
void __iomem *pss_err_status_reg;
void __iomem *app_pll_fast_ctl_reg;
@@ -150,16 +152,7 @@ struct bfa_ioc_notify {
};
/**
- * Heartbeat failure notification queue element.
- */
-struct bfa_ioc_hbfail_notify {
- struct list_head qe;
- bfa_ioc_hbfail_cbfn_t cbfn;
- void *cbarg;
-};
-
-/**
- * Initialize a heartbeat failure notification structure
+ * Initialize a IOC event notification structure
*/
#define bfa_ioc_notify_init(__notify, __cbfn, __cbarg) do { \
(__notify)->cbfn = (__cbfn); \
@@ -169,8 +162,9 @@ struct bfa_ioc_hbfail_notify {
struct bfa_iocpf {
bfa_fsm_t fsm;
struct bfa_ioc *ioc;
- u32 retry_count;
+ bool fw_mismatch_notified;
bool auto_recover;
+ u32 poll_time;
};
struct bfa_ioc {
@@ -186,12 +180,10 @@ struct bfa_ioc {
void *dbg_fwsave;
int dbg_fwsave_len;
bool dbg_fwsave_once;
- enum bfi_mclass ioc_mc;
+ enum bfi_pcifn_class clscode;
struct bfa_ioc_regs ioc_regs;
struct bfa_ioc_drv_stats stats;
bool fcmode;
- bool ctdev;
- bool cna;
bool pllinit;
bool stats_busy; /*!< outstanding stats */
u8 port_id;
@@ -200,12 +192,20 @@ struct bfa_ioc {
struct bfi_ioc_attr *attr;
struct bfa_ioc_cbfn *cbfn;
struct bfa_ioc_mbox_mod mbox_mod;
- struct bfa_ioc_hwif *ioc_hwif;
+ const struct bfa_ioc_hwif *ioc_hwif;
struct bfa_iocpf iocpf;
+ enum bfi_asic_gen asic_gen;
+ enum bfi_asic_mode asic_mode;
+ enum bfi_port_mode port0_mode;
+ enum bfi_port_mode port1_mode;
+ enum bfa_mode port_mode;
+ u8 ad_cap_bm; /*!< adapter cap bit mask */
+ u8 port_mode_cfg; /*!< config port mode */
};
struct bfa_ioc_hwif {
- enum bfa_status (*ioc_pll_init) (void __iomem *rb, bool fcmode);
+ enum bfa_status (*ioc_pll_init) (void __iomem *rb,
+ enum bfi_asic_mode m);
bool (*ioc_firmware_lock) (struct bfa_ioc *ioc);
void (*ioc_firmware_unlock) (struct bfa_ioc *ioc);
void (*ioc_reg_init) (struct bfa_ioc *ioc);
@@ -219,12 +219,14 @@ struct bfa_ioc_hwif {
void (*ioc_sync_leave) (struct bfa_ioc *ioc);
void (*ioc_sync_ack) (struct bfa_ioc *ioc);
bool (*ioc_sync_complete) (struct bfa_ioc *ioc);
+ bool (*ioc_lpu_read_stat) (struct bfa_ioc *ioc);
};
#define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func)
#define bfa_ioc_devid(__ioc) ((__ioc)->pcidev.device_id)
#define bfa_ioc_bar0(__ioc) ((__ioc)->pcidev.pci_bar_kva)
#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
+#define bfa_ioc_asic_gen(__ioc) ((__ioc)->asic_gen)
#define bfa_ioc_fetch_stats(__ioc, __stats) \
(((__stats)->drv_stats) = (__ioc)->stats)
#define bfa_ioc_clr_stats(__ioc) \
@@ -240,12 +242,9 @@ struct bfa_ioc_hwif {
#define bfa_ioc_stats_hb_count(_ioc, _hb_count) \
((_ioc)->stats.hb_count = (_hb_count))
#define BFA_IOC_FWIMG_MINSZ (16 * 1024)
-#define BFA_IOC_FWIMG_TYPE(__ioc) \
- (((__ioc)->ctdev) ? \
- (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) : \
- BFI_IMAGE_CB_FC)
#define BFA_IOC_FW_SMEM_SIZE(__ioc) \
- (((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE)
+ ((bfa_ioc_asic_gen(__ioc) == BFI_ASIC_GEN_CB) \
+ ? BFI_SMEM_CB_SIZE : BFI_SMEM_CT_SIZE)
#define BFA_IOC_FLASH_CHUNK_NO(off) (off / BFI_FLASH_CHUNK_SZ_WORDS)
#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS)
#define BFA_IOC_FLASH_CHUNK_ADDR(chunkno) (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
@@ -253,7 +252,9 @@ struct bfa_ioc_hwif {
/**
* IOC mailbox interface
*/
-void bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd);
+bool bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc,
+ struct bfa_mbox_cmd *cmd,
+ bfa_mbox_cmd_cbfn_t cbfn, void *cbarg);
void bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc);
void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
@@ -264,21 +265,30 @@ void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
#define bfa_ioc_pll_init_asic(__ioc) \
((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
- (__ioc)->fcmode))
+ (__ioc)->asic_mode))
-#define bfa_ioc_isr_mode_set(__ioc, __msix) \
- ((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
+#define bfa_ioc_isr_mode_set(__ioc, __msix) do { \
+ if ((__ioc)->ioc_hwif->ioc_isr_mode_set) \
+ ((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix)); \
+} while (0)
#define bfa_ioc_ownership_reset(__ioc) \
((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
+#define bfa_ioc_lpu_read_stat(__ioc) do { \
+ if ((__ioc)->ioc_hwif->ioc_lpu_read_stat) \
+ ((__ioc)->ioc_hwif->ioc_lpu_read_stat(__ioc)); \
+} while (0)
+
void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc);
+void bfa_nw_ioc_set_ct2_hwif(struct bfa_ioc *ioc);
+void bfa_nw_ioc_ct2_poweron(struct bfa_ioc *ioc);
void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa,
struct bfa_ioc_cbfn *cbfn);
void bfa_nw_ioc_auto_recover(bool auto_recover);
void bfa_nw_ioc_detach(struct bfa_ioc *ioc);
void bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
- enum bfi_mclass mc);
+ enum bfi_pcifn_class clscode);
u32 bfa_nw_ioc_meminfo(void);
void bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa);
void bfa_nw_ioc_enable(struct bfa_ioc *ioc);
@@ -309,7 +319,7 @@ void bfa_nw_iocpf_sem_timeout(void *ioc);
/*
* F/W Image Size & Chunk
*/
-u32 *bfa_cb_image_get_chunk(int type, u32 off);
-u32 bfa_cb_image_get_size(int type);
+u32 *bfa_cb_image_get_chunk(enum bfi_asic_gen asic_gen, u32 off);
+u32 bfa_cb_image_get_size(enum bfi_asic_gen asic_gen);
#endif /* __BFA_IOC_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c b/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c
new file mode 100644
index 000000000000..348479bbfa3a
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c
@@ -0,0 +1,878 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#include "bfa_ioc.h"
+#include "cna.h"
+#include "bfi.h"
+#include "bfi_reg.h"
+#include "bfa_defs.h"
+
+#define bfa_ioc_ct_sync_pos(__ioc) \
+ ((u32) (1 << bfa_ioc_pcifn(__ioc)))
+#define BFA_IOC_SYNC_REQD_SH 16
+#define bfa_ioc_ct_get_sync_ackd(__val) (__val & 0x0000ffff)
+#define bfa_ioc_ct_clear_sync_ackd(__val) (__val & 0xffff0000)
+#define bfa_ioc_ct_get_sync_reqd(__val) (__val >> BFA_IOC_SYNC_REQD_SH)
+#define bfa_ioc_ct_sync_reqd_pos(__ioc) \
+ (bfa_ioc_ct_sync_pos(__ioc) << BFA_IOC_SYNC_REQD_SH)
+
+/*
+ * forward declarations
+ */
+static bool bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc);
+static void bfa_ioc_ct2_reg_init(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
+static void bfa_ioc_ct2_map_port(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
+static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
+static bool bfa_ioc_ct_sync_start(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc);
+static bool bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc);
+static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb,
+ enum bfi_asic_mode asic_mode);
+static enum bfa_status bfa_ioc_ct2_pll_init(void __iomem *rb,
+ enum bfi_asic_mode asic_mode);
+static bool bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc *ioc);
+
+static const struct bfa_ioc_hwif nw_hwif_ct = {
+ .ioc_pll_init = bfa_ioc_ct_pll_init,
+ .ioc_firmware_lock = bfa_ioc_ct_firmware_lock,
+ .ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock,
+ .ioc_reg_init = bfa_ioc_ct_reg_init,
+ .ioc_map_port = bfa_ioc_ct_map_port,
+ .ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set,
+ .ioc_notify_fail = bfa_ioc_ct_notify_fail,
+ .ioc_ownership_reset = bfa_ioc_ct_ownership_reset,
+ .ioc_sync_start = bfa_ioc_ct_sync_start,
+ .ioc_sync_join = bfa_ioc_ct_sync_join,
+ .ioc_sync_leave = bfa_ioc_ct_sync_leave,
+ .ioc_sync_ack = bfa_ioc_ct_sync_ack,
+ .ioc_sync_complete = bfa_ioc_ct_sync_complete,
+};
+
+static const struct bfa_ioc_hwif nw_hwif_ct2 = {
+ .ioc_pll_init = bfa_ioc_ct2_pll_init,
+ .ioc_firmware_lock = bfa_ioc_ct_firmware_lock,
+ .ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock,
+ .ioc_reg_init = bfa_ioc_ct2_reg_init,
+ .ioc_map_port = bfa_ioc_ct2_map_port,
+ .ioc_lpu_read_stat = bfa_ioc_ct2_lpu_read_stat,
+ .ioc_isr_mode_set = NULL,
+ .ioc_notify_fail = bfa_ioc_ct_notify_fail,
+ .ioc_ownership_reset = bfa_ioc_ct_ownership_reset,
+ .ioc_sync_start = bfa_ioc_ct_sync_start,
+ .ioc_sync_join = bfa_ioc_ct_sync_join,
+ .ioc_sync_leave = bfa_ioc_ct_sync_leave,
+ .ioc_sync_ack = bfa_ioc_ct_sync_ack,
+ .ioc_sync_complete = bfa_ioc_ct_sync_complete,
+};
+
+/**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+void
+bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc)
+{
+ ioc->ioc_hwif = &nw_hwif_ct;
+}
+
+void
+bfa_nw_ioc_set_ct2_hwif(struct bfa_ioc *ioc)
+{
+ ioc->ioc_hwif = &nw_hwif_ct2;
+}
+
+/**
+ * Return true if firmware of current driver matches the running firmware.
+ */
+static bool
+bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc)
+{
+ enum bfi_ioc_state ioc_fwstate;
+ u32 usecnt;
+ struct bfi_ioc_image_hdr fwhdr;
+
+ /**
+ * If bios boot (flash based) -- do not increment usage count
+ */
+ if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
+ BFA_IOC_FWIMG_MINSZ)
+ return true;
+
+ bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+ usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
+
+ /**
+ * If usage count is 0, always return TRUE.
+ */
+ if (usecnt == 0) {
+ writel(1, ioc->ioc_regs.ioc_usage_reg);
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(0, ioc->ioc_regs.ioc_fail_sync);
+ return true;
+ }
+
+ ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+ /**
+ * Use count cannot be non-zero and chip in uninitialized state.
+ */
+ BUG_ON(!(ioc_fwstate != BFI_IOC_UNINIT));
+
+ /**
+ * Check if another driver with a different firmware is active
+ */
+ bfa_nw_ioc_fwver_get(ioc, &fwhdr);
+ if (!bfa_nw_ioc_fwver_cmp(ioc, &fwhdr)) {
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ return false;
+ }
+
+ /**
+ * Same firmware version. Increment the reference count.
+ */
+ usecnt++;
+ writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ return true;
+}
+
+static void
+bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc)
+{
+ u32 usecnt;
+
+ /**
+ * If bios boot (flash based) -- do not decrement usage count
+ */
+ if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
+ BFA_IOC_FWIMG_MINSZ)
+ return;
+
+ /**
+ * decrement usage count
+ */
+ bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+ usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
+ BUG_ON(!(usecnt > 0));
+
+ usecnt--;
+ writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
+
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+}
+
+/**
+ * Notify other functions on HB failure.
+ */
+static void
+bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc)
+{
+ writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
+ writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
+ /* Wait for halt to take effect */
+ readl(ioc->ioc_regs.ll_halt);
+ readl(ioc->ioc_regs.alt_ll_halt);
+}
+
+/**
+ * Host to LPU mailbox message addresses
+ */
+static const struct {
+ u32 hfn_mbox;
+ u32 lpu_mbox;
+ u32 hfn_pgn;
+} ct_fnreg[] = {
+ { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
+ { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
+ { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
+ { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 }
+};
+
+/**
+ * Host <-> LPU mailbox command/status registers - port 0
+ */
+static const struct {
+ u32 hfn;
+ u32 lpu;
+} ct_p0reg[] = {
+ { HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
+ { HOSTFN1_LPU0_CMD_STAT, LPU0_HOSTFN1_CMD_STAT },
+ { HOSTFN2_LPU0_CMD_STAT, LPU0_HOSTFN2_CMD_STAT },
+ { HOSTFN3_LPU0_CMD_STAT, LPU0_HOSTFN3_CMD_STAT }
+};
+
+/**
+ * Host <-> LPU mailbox command/status registers - port 1
+ */
+static const struct {
+ u32 hfn;
+ u32 lpu;
+} ct_p1reg[] = {
+ { HOSTFN0_LPU1_CMD_STAT, LPU1_HOSTFN0_CMD_STAT },
+ { HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT },
+ { HOSTFN2_LPU1_CMD_STAT, LPU1_HOSTFN2_CMD_STAT },
+ { HOSTFN3_LPU1_CMD_STAT, LPU1_HOSTFN3_CMD_STAT }
+};
+
+static const struct {
+ u32 hfn_mbox;
+ u32 lpu_mbox;
+ u32 hfn_pgn;
+ u32 hfn;
+ u32 lpu;
+ u32 lpu_read;
+} ct2_reg[] = {
+ { CT2_HOSTFN_LPU0_MBOX0, CT2_LPU0_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM,
+ CT2_HOSTFN_LPU0_CMD_STAT, CT2_LPU0_HOSTFN_CMD_STAT,
+ CT2_HOSTFN_LPU0_READ_STAT},
+ { CT2_HOSTFN_LPU1_MBOX0, CT2_LPU1_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM,
+ CT2_HOSTFN_LPU1_CMD_STAT, CT2_LPU1_HOSTFN_CMD_STAT,
+ CT2_HOSTFN_LPU1_READ_STAT},
+};
+
+static void
+bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
+{
+ void __iomem *rb;
+ int pcifn = bfa_ioc_pcifn(ioc);
+
+ rb = bfa_ioc_bar0(ioc);
+
+ ioc->ioc_regs.hfn_mbox = rb + ct_fnreg[pcifn].hfn_mbox;
+ ioc->ioc_regs.lpu_mbox = rb + ct_fnreg[pcifn].lpu_mbox;
+ ioc->ioc_regs.host_page_num_fn = rb + ct_fnreg[pcifn].hfn_pgn;
+
+ if (ioc->port_id == 0) {
+ ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
+ ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
+ ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
+ ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p0reg[pcifn].hfn;
+ ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p0reg[pcifn].lpu;
+ ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+ ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
+ } else {
+ ioc->ioc_regs.heartbeat = rb + BFA_IOC1_HBEAT_REG;
+ ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC1_STATE_REG;
+ ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG;
+ ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p1reg[pcifn].hfn;
+ ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p1reg[pcifn].lpu;
+ ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+ ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
+ }
+
+ /*
+ * PSS control registers
+ */
+ ioc->ioc_regs.pss_ctl_reg = rb + PSS_CTL_REG;
+ ioc->ioc_regs.pss_err_status_reg = rb + PSS_ERR_STATUS_REG;
+ ioc->ioc_regs.app_pll_fast_ctl_reg = rb + APP_PLL_LCLK_CTL_REG;
+ ioc->ioc_regs.app_pll_slow_ctl_reg = rb + APP_PLL_SCLK_CTL_REG;
+
+ /*
+ * IOC semaphore registers and serialization
+ */
+ ioc->ioc_regs.ioc_sem_reg = rb + HOST_SEM0_REG;
+ ioc->ioc_regs.ioc_usage_sem_reg = rb + HOST_SEM1_REG;
+ ioc->ioc_regs.ioc_init_sem_reg = rb + HOST_SEM2_REG;
+ ioc->ioc_regs.ioc_usage_reg = rb + BFA_FW_USE_COUNT;
+ ioc->ioc_regs.ioc_fail_sync = rb + BFA_IOC_FAIL_SYNC;
+
+ /**
+ * sram memory access
+ */
+ ioc->ioc_regs.smem_page_start = rb + PSS_SMEM_PAGE_START;
+ ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
+
+ /*
+ * err set reg : for notification of hb failure in fcmode
+ */
+ ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
+}
+
+static void
+bfa_ioc_ct2_reg_init(struct bfa_ioc *ioc)
+{
+ void __iomem *rb;
+ int port = bfa_ioc_portid(ioc);
+
+ rb = bfa_ioc_bar0(ioc);
+
+ ioc->ioc_regs.hfn_mbox = rb + ct2_reg[port].hfn_mbox;
+ ioc->ioc_regs.lpu_mbox = rb + ct2_reg[port].lpu_mbox;
+ ioc->ioc_regs.host_page_num_fn = rb + ct2_reg[port].hfn_pgn;
+ ioc->ioc_regs.hfn_mbox_cmd = rb + ct2_reg[port].hfn;
+ ioc->ioc_regs.lpu_mbox_cmd = rb + ct2_reg[port].lpu;
+ ioc->ioc_regs.lpu_read_stat = rb + ct2_reg[port].lpu_read;
+
+ if (port == 0) {
+ ioc->ioc_regs.heartbeat = rb + CT2_BFA_IOC0_HBEAT_REG;
+ ioc->ioc_regs.ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG;
+ ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC1_STATE_REG;
+ ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+ ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
+ } else {
+ ioc->ioc_regs.heartbeat = rb + CT2_BFA_IOC1_HBEAT_REG;
+ ioc->ioc_regs.ioc_fwstate = rb + CT2_BFA_IOC1_STATE_REG;
+ ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG;
+ ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+ ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
+ }
+
+ /*
+ * PSS control registers
+ */
+ ioc->ioc_regs.pss_ctl_reg = rb + PSS_CTL_REG;
+ ioc->ioc_regs.pss_err_status_reg = rb + PSS_ERR_STATUS_REG;
+ ioc->ioc_regs.app_pll_fast_ctl_reg = rb + CT2_APP_PLL_LCLK_CTL_REG;
+ ioc->ioc_regs.app_pll_slow_ctl_reg = rb + CT2_APP_PLL_SCLK_CTL_REG;
+
+ /*
+ * IOC semaphore registers and serialization
+ */
+ ioc->ioc_regs.ioc_sem_reg = rb + CT2_HOST_SEM0_REG;
+ ioc->ioc_regs.ioc_usage_sem_reg = rb + CT2_HOST_SEM1_REG;
+ ioc->ioc_regs.ioc_init_sem_reg = rb + CT2_HOST_SEM2_REG;
+ ioc->ioc_regs.ioc_usage_reg = rb + CT2_BFA_FW_USE_COUNT;
+ ioc->ioc_regs.ioc_fail_sync = rb + CT2_BFA_IOC_FAIL_SYNC;
+
+ /**
+ * sram memory access
+ */
+ ioc->ioc_regs.smem_page_start = rb + PSS_SMEM_PAGE_START;
+ ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
+
+ /*
+ * err set reg : for notification of hb failure in fcmode
+ */
+ ioc->ioc_regs.err_set = rb + ERR_SET_REG;
+}
+
+/**
+ * Initialize IOC to port mapping.
+ */
+
+#define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8)
+static void
+bfa_ioc_ct_map_port(struct bfa_ioc *ioc)
+{
+ void __iomem *rb = ioc->pcidev.pci_bar_kva;
+ u32 r32;
+
+ /**
+ * For catapult, base port id on personality register and IOC type
+ */
+ r32 = readl(rb + FNC_PERS_REG);
+ r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
+ ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
+
+}
+
+static void
+bfa_ioc_ct2_map_port(struct bfa_ioc *ioc)
+{
+ void __iomem *rb = ioc->pcidev.pci_bar_kva;
+ u32 r32;
+
+ r32 = readl(rb + CT2_HOSTFN_PERSONALITY0);
+ ioc->port_id = ((r32 & __FC_LL_PORT_MAP__MK) >> __FC_LL_PORT_MAP__SH);
+}
+
+/**
+ * Set interrupt mode for a function: INTX or MSIX
+ */
+static void
+bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix)
+{
+ void __iomem *rb = ioc->pcidev.pci_bar_kva;
+ u32 r32, mode;
+
+ r32 = readl(rb + FNC_PERS_REG);
+
+ mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
+ __F0_INTX_STATUS;
+
+ /**
+ * If already in desired mode, do not change anything
+ */
+ if ((!msix && mode) || (msix && !mode))
+ return;
+
+ if (msix)
+ mode = __F0_INTX_STATUS_MSIX;
+ else
+ mode = __F0_INTX_STATUS_INTA;
+
+ r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
+ r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
+
+ writel(r32, rb + FNC_PERS_REG);
+}
+
+static bool
+bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc *ioc)
+{
+ u32 r32;
+
+ r32 = readl(ioc->ioc_regs.lpu_read_stat);
+ if (r32) {
+ writel(1, ioc->ioc_regs.lpu_read_stat);
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * MSI-X resource allocation for 1860 with no asic block
+ */
+#define HOSTFN_MSIX_DEFAULT 64
+#define HOSTFN_MSIX_VT_INDEX_MBOX_ERR 0x30138
+#define HOSTFN_MSIX_VT_OFST_NUMVT 0x3013c
+#define __MSIX_VT_NUMVT__MK 0x003ff800
+#define __MSIX_VT_NUMVT__SH 11
+#define __MSIX_VT_NUMVT_(_v) ((_v) << __MSIX_VT_NUMVT__SH)
+#define __MSIX_VT_OFST_ 0x000007ff
+void
+bfa_nw_ioc_ct2_poweron(struct bfa_ioc *ioc)
+{
+ void __iomem *rb = ioc->pcidev.pci_bar_kva;
+ u32 r32;
+
+ r32 = readl(rb + HOSTFN_MSIX_VT_OFST_NUMVT);
+ if (r32 & __MSIX_VT_NUMVT__MK) {
+ writel(r32 & __MSIX_VT_OFST_,
+ rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR);
+ return;
+ }
+
+ writel(__MSIX_VT_NUMVT_(HOSTFN_MSIX_DEFAULT - 1) |
+ HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc),
+ rb + HOSTFN_MSIX_VT_OFST_NUMVT);
+ writel(HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc),
+ rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR);
+}
+
+/**
+ * Cleanup hw semaphore and usecnt registers
+ */
+static void
+bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc)
+{
+ bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(0, ioc->ioc_regs.ioc_usage_reg);
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+
+ /*
+ * Read the hw sem reg to make sure that it is locked
+ * before we clear it. If it is not locked, writing 1
+ * will lock it instead of clearing it.
+ */
+ readl(ioc->ioc_regs.ioc_sem_reg);
+ bfa_nw_ioc_hw_sem_release(ioc);
+}
+
+/**
+ * Synchronized IOC failure processing routines
+ */
+static bool
+bfa_ioc_ct_sync_start(struct bfa_ioc *ioc)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+ u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
+
+ /*
+ * Driver load time. If the sync required bit for this PCI fn
+ * is set, it is due to an unclean exit by the driver for this
+ * PCI fn in the previous incarnation. Whoever comes here first
+ * should clean it up, no matter which PCI fn.
+ */
+
+ if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) {
+ writel(0, ioc->ioc_regs.ioc_fail_sync);
+ writel(1, ioc->ioc_regs.ioc_usage_reg);
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
+ return true;
+ }
+
+ return bfa_ioc_ct_sync_complete(ioc);
+}
+/**
+ * Synchronized IOC failure processing routines
+ */
+static void
+bfa_ioc_ct_sync_join(struct bfa_ioc *ioc)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+ u32 sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc);
+
+ writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static void
+bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+ u32 sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) |
+ bfa_ioc_ct_sync_pos(ioc);
+
+ writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static void
+bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+
+ writel((r32 | bfa_ioc_ct_sync_pos(ioc)), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static bool
+bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+ u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
+ u32 sync_ackd = bfa_ioc_ct_get_sync_ackd(r32);
+ u32 tmp_ackd;
+
+ if (sync_ackd == 0)
+ return true;
+
+ /**
+ * The check below is to see whether any other PCI fn
+ * has reinitialized the ASIC (reset sync_ackd bits)
+ * and failed again while this IOC was waiting for hw
+ * semaphore (in bfa_iocpf_sm_semwait()).
+ */
+ tmp_ackd = sync_ackd;
+ if ((sync_reqd & bfa_ioc_ct_sync_pos(ioc)) &&
+ !(sync_ackd & bfa_ioc_ct_sync_pos(ioc)))
+ sync_ackd |= bfa_ioc_ct_sync_pos(ioc);
+
+ if (sync_reqd == sync_ackd) {
+ writel(bfa_ioc_ct_clear_sync_ackd(r32),
+ ioc->ioc_regs.ioc_fail_sync);
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate);
+ return true;
+ }
+
+ /**
+ * If another PCI fn reinitialized and failed again while
+ * this IOC was waiting for hw sem, the sync_ackd bit for
+ * this IOC need to be set again to allow reinitialization.
+ */
+ if (tmp_ackd != sync_ackd)
+ writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync);
+
+ return false;
+}
+
+static enum bfa_status
+bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode)
+{
+ u32 pll_sclk, pll_fclk, r32;
+ bool fcmode = (asic_mode == BFI_ASIC_MODE_FC);
+
+ pll_sclk = __APP_PLL_SCLK_LRESETN | __APP_PLL_SCLK_ENARST |
+ __APP_PLL_SCLK_RSEL200500 | __APP_PLL_SCLK_P0_1(3U) |
+ __APP_PLL_SCLK_JITLMT0_1(3U) |
+ __APP_PLL_SCLK_CNTLMT0_1(1U);
+ pll_fclk = __APP_PLL_LCLK_LRESETN | __APP_PLL_LCLK_ENARST |
+ __APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) |
+ __APP_PLL_LCLK_JITLMT0_1(3U) |
+ __APP_PLL_LCLK_CNTLMT0_1(1U);
+
+ if (fcmode) {
+ writel(0, (rb + OP_MODE));
+ writel(__APP_EMS_CMLCKSEL |
+ __APP_EMS_REFCKBUFEN2 |
+ __APP_EMS_CHANNEL_SEL,
+ (rb + ETH_MAC_SER_REG));
+ } else {
+ writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE));
+ writel(__APP_EMS_REFCKBUFEN1,
+ (rb + ETH_MAC_SER_REG));
+ }
+ writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
+ writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
+ writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
+ writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
+ writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
+ writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
+ writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
+ writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
+ writel(pll_sclk |
+ __APP_PLL_SCLK_LOGIC_SOFT_RESET,
+ rb + APP_PLL_SCLK_CTL_REG);
+ writel(pll_fclk |
+ __APP_PLL_LCLK_LOGIC_SOFT_RESET,
+ rb + APP_PLL_LCLK_CTL_REG);
+ writel(pll_sclk |
+ __APP_PLL_SCLK_LOGIC_SOFT_RESET | __APP_PLL_SCLK_ENABLE,
+ rb + APP_PLL_SCLK_CTL_REG);
+ writel(pll_fclk |
+ __APP_PLL_LCLK_LOGIC_SOFT_RESET | __APP_PLL_LCLK_ENABLE,
+ rb + APP_PLL_LCLK_CTL_REG);
+ readl(rb + HOSTFN0_INT_MSK);
+ udelay(2000);
+ writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
+ writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
+ writel(pll_sclk |
+ __APP_PLL_SCLK_ENABLE,
+ rb + APP_PLL_SCLK_CTL_REG);
+ writel(pll_fclk |
+ __APP_PLL_LCLK_ENABLE,
+ rb + APP_PLL_LCLK_CTL_REG);
+
+ if (!fcmode) {
+ writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));
+ writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1));
+ }
+ r32 = readl((rb + PSS_CTL_REG));
+ r32 &= ~__PSS_LMEM_RESET;
+ writel(r32, (rb + PSS_CTL_REG));
+ udelay(1000);
+ if (!fcmode) {
+ writel(0, (rb + PMM_1T_RESET_REG_P0));
+ writel(0, (rb + PMM_1T_RESET_REG_P1));
+ }
+
+ writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG));
+ udelay(1000);
+ r32 = readl((rb + MBIST_STAT_REG));
+ writel(0, (rb + MBIST_CTL_REG));
+ return BFA_STATUS_OK;
+}
+
+static void
+bfa_ioc_ct2_sclk_init(void __iomem *rb)
+{
+ u32 r32;
+
+ /*
+ * put s_clk PLL and PLL FSM in reset
+ */
+ r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+ r32 &= ~(__APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN);
+ r32 |= (__APP_PLL_SCLK_ENARST | __APP_PLL_SCLK_BYPASS |
+ __APP_PLL_SCLK_LOGIC_SOFT_RESET);
+ writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+ /*
+ * Ignore mode and program for the max clock (which is FC16)
+ * Firmware/NFC will do the PLL init appropiately
+ */
+ r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+ r32 &= ~(__APP_PLL_SCLK_REFCLK_SEL | __APP_PLL_SCLK_CLK_DIV2);
+ writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+ /*
+ * while doing PLL init dont clock gate ethernet subsystem
+ */
+ r32 = readl((rb + CT2_CHIP_MISC_PRG));
+ writel((r32 | __ETH_CLK_ENABLE_PORT0),
+ (rb + CT2_CHIP_MISC_PRG));
+
+ r32 = readl((rb + CT2_PCIE_MISC_REG));
+ writel((r32 | __ETH_CLK_ENABLE_PORT1),
+ (rb + CT2_PCIE_MISC_REG));
+
+ /*
+ * set sclk value
+ */
+ r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+ r32 &= (__P_SCLK_PLL_LOCK | __APP_PLL_SCLK_REFCLK_SEL |
+ __APP_PLL_SCLK_CLK_DIV2);
+ writel(r32 | 0x1061731b, (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+ /*
+ * poll for s_clk lock or delay 1ms
+ */
+ udelay(1000);
+
+ /*
+ * Dont do clock gating for ethernet subsystem, firmware/NFC will
+ * do this appropriately
+ */
+}
+
+static void
+bfa_ioc_ct2_lclk_init(void __iomem *rb)
+{
+ u32 r32;
+
+ /*
+ * put l_clk PLL and PLL FSM in reset
+ */
+ r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+ r32 &= ~(__APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN);
+ r32 |= (__APP_PLL_LCLK_ENARST | __APP_PLL_LCLK_BYPASS |
+ __APP_PLL_LCLK_LOGIC_SOFT_RESET);
+ writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+ /*
+ * set LPU speed (set for FC16 which will work for other modes)
+ */
+ r32 = readl((rb + CT2_CHIP_MISC_PRG));
+ writel(r32, (rb + CT2_CHIP_MISC_PRG));
+
+ /*
+ * set LPU half speed (set for FC16 which will work for other modes)
+ */
+ r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+ writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+ /*
+ * set lclk for mode (set for FC16)
+ */
+ r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+ r32 &= (__P_LCLK_PLL_LOCK | __APP_LPUCLK_HALFSPEED);
+ r32 |= 0x20c1731b;
+ writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+ /*
+ * poll for s_clk lock or delay 1ms
+ */
+ udelay(1000);
+}
+
+static void
+bfa_ioc_ct2_mem_init(void __iomem *rb)
+{
+ u32 r32;
+
+ r32 = readl((rb + PSS_CTL_REG));
+ r32 &= ~__PSS_LMEM_RESET;
+ writel(r32, (rb + PSS_CTL_REG));
+ udelay(1000);
+
+ writel(__EDRAM_BISTR_START, (rb + CT2_MBIST_CTL_REG));
+ udelay(1000);
+ writel(0, (rb + CT2_MBIST_CTL_REG));
+}
+
+static void
+bfa_ioc_ct2_mac_reset(void __iomem *rb)
+{
+ volatile u32 r32;
+
+ bfa_ioc_ct2_sclk_init(rb);
+ bfa_ioc_ct2_lclk_init(rb);
+
+ /*
+ * release soft reset on s_clk & l_clk
+ */
+ r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+ writel((r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET),
+ (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+ /*
+ * release soft reset on s_clk & l_clk
+ */
+ r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+ writel((r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET),
+ (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+ /* put port0, port1 MAC & AHB in reset */
+ writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET),
+ (rb + CT2_CSI_MAC_CONTROL_REG(0)));
+ writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET),
+ (rb + CT2_CSI_MAC_CONTROL_REG(1)));
+}
+
+#define CT2_NFC_MAX_DELAY 1000
+static enum bfa_status
+bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode)
+{
+ volatile u32 wgn, r32;
+ int i;
+
+ /*
+ * Initialize PLL if not already done by NFC
+ */
+ wgn = readl(rb + CT2_WGN_STATUS);
+ if (!(wgn & __GLBL_PF_VF_CFG_RDY)) {
+ writel(__HALT_NFC_CONTROLLER, (rb + CT2_NFC_CSR_SET_REG));
+ for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
+ r32 = readl(rb + CT2_NFC_CSR_SET_REG);
+ if (r32 & __NFC_CONTROLLER_HALTED)
+ break;
+ udelay(1000);
+ }
+ }
+
+ /*
+ * Mask the interrupts and clear any
+ * pending interrupts left by BIOS/EFI
+ */
+
+ writel(1, (rb + CT2_LPU0_HOSTFN_MBOX0_MSK));
+ writel(1, (rb + CT2_LPU1_HOSTFN_MBOX0_MSK));
+
+ r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
+ if (r32 == 1) {
+ writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT));
+ readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
+ }
+ r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
+ if (r32 == 1) {
+ writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT));
+ readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
+ }
+
+ bfa_ioc_ct2_mac_reset(rb);
+ bfa_ioc_ct2_sclk_init(rb);
+ bfa_ioc_ct2_lclk_init(rb);
+
+ /*
+ * release soft reset on s_clk & l_clk
+ */
+ r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+ writel((r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET),
+ (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+ /*
+ * release soft reset on s_clk & l_clk
+ */
+ r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+ writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
+ (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+ /*
+ * Announce flash device presence, if flash was corrupted.
+ */
+ if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
+ r32 = readl((rb + PSS_GPIO_OUT_REG));
+ writel((r32 & ~1), (rb + PSS_GPIO_OUT_REG));
+ r32 = readl((rb + PSS_GPIO_OE_REG));
+ writel((r32 | 1), (rb + PSS_GPIO_OE_REG));
+ }
+
+ bfa_ioc_ct2_mem_init(rb);
+
+ writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC0_STATE_REG));
+ writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC1_STATE_REG));
+ return BFA_STATUS_OK;
+}
diff --git a/drivers/net/ethernet/brocade/bna/bfa_msgq.c b/drivers/net/ethernet/brocade/bna/bfa_msgq.c
new file mode 100644
index 000000000000..dd36427f4752
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/bfa_msgq.c
@@ -0,0 +1,669 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/**
+ * @file bfa_msgq.c MSGQ module source file.
+ */
+
+#include "bfi.h"
+#include "bfa_msgq.h"
+#include "bfa_ioc.h"
+
+#define call_cmdq_ent_cbfn(_cmdq_ent, _status) \
+{ \
+ bfa_msgq_cmdcbfn_t cbfn; \
+ void *cbarg; \
+ cbfn = (_cmdq_ent)->cbfn; \
+ cbarg = (_cmdq_ent)->cbarg; \
+ (_cmdq_ent)->cbfn = NULL; \
+ (_cmdq_ent)->cbarg = NULL; \
+ if (cbfn) { \
+ cbfn(cbarg, (_status)); \
+ } \
+}
+
+static void bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq);
+static void bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq);
+
+enum cmdq_event {
+ CMDQ_E_START = 1,
+ CMDQ_E_STOP = 2,
+ CMDQ_E_FAIL = 3,
+ CMDQ_E_POST = 4,
+ CMDQ_E_INIT_RESP = 5,
+ CMDQ_E_DB_READY = 6,
+};
+
+bfa_fsm_state_decl(cmdq, stopped, struct bfa_msgq_cmdq, enum cmdq_event);
+bfa_fsm_state_decl(cmdq, init_wait, struct bfa_msgq_cmdq, enum cmdq_event);
+bfa_fsm_state_decl(cmdq, ready, struct bfa_msgq_cmdq, enum cmdq_event);
+bfa_fsm_state_decl(cmdq, dbell_wait, struct bfa_msgq_cmdq,
+ enum cmdq_event);
+
+static void
+cmdq_sm_stopped_entry(struct bfa_msgq_cmdq *cmdq)
+{
+ struct bfa_msgq_cmd_entry *cmdq_ent;
+
+ cmdq->producer_index = 0;
+ cmdq->consumer_index = 0;
+ cmdq->flags = 0;
+ cmdq->token = 0;
+ cmdq->offset = 0;
+ cmdq->bytes_to_copy = 0;
+ while (!list_empty(&cmdq->pending_q)) {
+ bfa_q_deq(&cmdq->pending_q, &cmdq_ent);
+ bfa_q_qe_init(&cmdq_ent->qe);
+ call_cmdq_ent_cbfn(cmdq_ent, BFA_STATUS_FAILED);
+ }
+}
+
+static void
+cmdq_sm_stopped(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
+{
+ switch (event) {
+ case CMDQ_E_START:
+ bfa_fsm_set_state(cmdq, cmdq_sm_init_wait);
+ break;
+
+ case CMDQ_E_STOP:
+ case CMDQ_E_FAIL:
+ /* No-op */
+ break;
+
+ case CMDQ_E_POST:
+ cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+cmdq_sm_init_wait_entry(struct bfa_msgq_cmdq *cmdq)
+{
+ bfa_wc_down(&cmdq->msgq->init_wc);
+}
+
+static void
+cmdq_sm_init_wait(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
+{
+ switch (event) {
+ case CMDQ_E_STOP:
+ case CMDQ_E_FAIL:
+ bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
+ break;
+
+ case CMDQ_E_POST:
+ cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
+ break;
+
+ case CMDQ_E_INIT_RESP:
+ if (cmdq->flags & BFA_MSGQ_CMDQ_F_DB_UPDATE) {
+ cmdq->flags &= ~BFA_MSGQ_CMDQ_F_DB_UPDATE;
+ bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
+ } else
+ bfa_fsm_set_state(cmdq, cmdq_sm_ready);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+cmdq_sm_ready_entry(struct bfa_msgq_cmdq *cmdq)
+{
+}
+
+static void
+cmdq_sm_ready(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
+{
+ switch (event) {
+ case CMDQ_E_STOP:
+ case CMDQ_E_FAIL:
+ bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
+ break;
+
+ case CMDQ_E_POST:
+ bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+cmdq_sm_dbell_wait_entry(struct bfa_msgq_cmdq *cmdq)
+{
+ bfa_msgq_cmdq_dbell(cmdq);
+}
+
+static void
+cmdq_sm_dbell_wait(struct bfa_msgq_cmdq *cmdq, enum cmdq_event event)
+{
+ switch (event) {
+ case CMDQ_E_STOP:
+ case CMDQ_E_FAIL:
+ bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
+ break;
+
+ case CMDQ_E_POST:
+ cmdq->flags |= BFA_MSGQ_CMDQ_F_DB_UPDATE;
+ break;
+
+ case CMDQ_E_DB_READY:
+ if (cmdq->flags & BFA_MSGQ_CMDQ_F_DB_UPDATE) {
+ cmdq->flags &= ~BFA_MSGQ_CMDQ_F_DB_UPDATE;
+ bfa_fsm_set_state(cmdq, cmdq_sm_dbell_wait);
+ } else
+ bfa_fsm_set_state(cmdq, cmdq_sm_ready);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bfa_msgq_cmdq_dbell_ready(void *arg)
+{
+ struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
+ bfa_fsm_send_event(cmdq, CMDQ_E_DB_READY);
+}
+
+static void
+bfa_msgq_cmdq_dbell(struct bfa_msgq_cmdq *cmdq)
+{
+ struct bfi_msgq_h2i_db *dbell =
+ (struct bfi_msgq_h2i_db *)(&cmdq->dbell_mb.msg[0]);
+
+ memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
+ bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_PI, 0);
+ dbell->mh.mtag.i2htok = 0;
+ dbell->idx.cmdq_pi = htons(cmdq->producer_index);
+
+ if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->dbell_mb,
+ bfa_msgq_cmdq_dbell_ready, cmdq)) {
+ bfa_msgq_cmdq_dbell_ready(cmdq);
+ }
+}
+
+static void
+__cmd_copy(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq_cmd_entry *cmd)
+{
+ size_t len = cmd->msg_size;
+ int num_entries = 0;
+ size_t to_copy;
+ u8 *src, *dst;
+
+ src = (u8 *)cmd->msg_hdr;
+ dst = (u8 *)cmdq->addr.kva;
+ dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
+
+ while (len) {
+ to_copy = (len < BFI_MSGQ_CMD_ENTRY_SIZE) ?
+ len : BFI_MSGQ_CMD_ENTRY_SIZE;
+ memcpy(dst, src, to_copy);
+ len -= to_copy;
+ src += BFI_MSGQ_CMD_ENTRY_SIZE;
+ BFA_MSGQ_INDX_ADD(cmdq->producer_index, 1, cmdq->depth);
+ dst = (u8 *)cmdq->addr.kva;
+ dst += (cmdq->producer_index * BFI_MSGQ_CMD_ENTRY_SIZE);
+ num_entries++;
+ }
+
+}
+
+static void
+bfa_msgq_cmdq_ci_update(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
+{
+ struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
+ struct bfa_msgq_cmd_entry *cmd;
+ int posted = 0;
+
+ cmdq->consumer_index = ntohs(dbell->idx.cmdq_ci);
+
+ /* Walk through pending list to see if the command can be posted */
+ while (!list_empty(&cmdq->pending_q)) {
+ cmd =
+ (struct bfa_msgq_cmd_entry *)bfa_q_first(&cmdq->pending_q);
+ if (ntohs(cmd->msg_hdr->num_entries) <=
+ BFA_MSGQ_FREE_CNT(cmdq)) {
+ list_del(&cmd->qe);
+ __cmd_copy(cmdq, cmd);
+ posted = 1;
+ call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
+ } else {
+ break;
+ }
+ }
+
+ if (posted)
+ bfa_fsm_send_event(cmdq, CMDQ_E_POST);
+}
+
+static void
+bfa_msgq_cmdq_copy_next(void *arg)
+{
+ struct bfa_msgq_cmdq *cmdq = (struct bfa_msgq_cmdq *)arg;
+
+ if (cmdq->bytes_to_copy)
+ bfa_msgq_cmdq_copy_rsp(cmdq);
+}
+
+static void
+bfa_msgq_cmdq_copy_req(struct bfa_msgq_cmdq *cmdq, struct bfi_mbmsg *mb)
+{
+ struct bfi_msgq_i2h_cmdq_copy_req *req =
+ (struct bfi_msgq_i2h_cmdq_copy_req *)mb;
+
+ cmdq->token = 0;
+ cmdq->offset = ntohs(req->offset);
+ cmdq->bytes_to_copy = ntohs(req->len);
+ bfa_msgq_cmdq_copy_rsp(cmdq);
+}
+
+static void
+bfa_msgq_cmdq_copy_rsp(struct bfa_msgq_cmdq *cmdq)
+{
+ struct bfi_msgq_h2i_cmdq_copy_rsp *rsp =
+ (struct bfi_msgq_h2i_cmdq_copy_rsp *)&cmdq->copy_mb.msg[0];
+ int copied;
+ u8 *addr = (u8 *)cmdq->addr.kva;
+
+ memset(rsp, 0, sizeof(struct bfi_msgq_h2i_cmdq_copy_rsp));
+ bfi_h2i_set(rsp->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_CMDQ_COPY_RSP, 0);
+ rsp->mh.mtag.i2htok = htons(cmdq->token);
+ copied = (cmdq->bytes_to_copy >= BFI_CMD_COPY_SZ) ? BFI_CMD_COPY_SZ :
+ cmdq->bytes_to_copy;
+ addr += cmdq->offset;
+ memcpy(rsp->data, addr, copied);
+
+ cmdq->token++;
+ cmdq->offset += copied;
+ cmdq->bytes_to_copy -= copied;
+
+ if (!bfa_nw_ioc_mbox_queue(cmdq->msgq->ioc, &cmdq->copy_mb,
+ bfa_msgq_cmdq_copy_next, cmdq)) {
+ bfa_msgq_cmdq_copy_next(cmdq);
+ }
+}
+
+static void
+bfa_msgq_cmdq_attach(struct bfa_msgq_cmdq *cmdq, struct bfa_msgq *msgq)
+{
+ cmdq->depth = BFA_MSGQ_CMDQ_NUM_ENTRY;
+ INIT_LIST_HEAD(&cmdq->pending_q);
+ cmdq->msgq = msgq;
+ bfa_fsm_set_state(cmdq, cmdq_sm_stopped);
+}
+
+static void bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq);
+
+enum rspq_event {
+ RSPQ_E_START = 1,
+ RSPQ_E_STOP = 2,
+ RSPQ_E_FAIL = 3,
+ RSPQ_E_RESP = 4,
+ RSPQ_E_INIT_RESP = 5,
+ RSPQ_E_DB_READY = 6,
+};
+
+bfa_fsm_state_decl(rspq, stopped, struct bfa_msgq_rspq, enum rspq_event);
+bfa_fsm_state_decl(rspq, init_wait, struct bfa_msgq_rspq,
+ enum rspq_event);
+bfa_fsm_state_decl(rspq, ready, struct bfa_msgq_rspq, enum rspq_event);
+bfa_fsm_state_decl(rspq, dbell_wait, struct bfa_msgq_rspq,
+ enum rspq_event);
+
+static void
+rspq_sm_stopped_entry(struct bfa_msgq_rspq *rspq)
+{
+ rspq->producer_index = 0;
+ rspq->consumer_index = 0;
+ rspq->flags = 0;
+}
+
+static void
+rspq_sm_stopped(struct bfa_msgq_rspq *rspq, enum rspq_event event)
+{
+ switch (event) {
+ case RSPQ_E_START:
+ bfa_fsm_set_state(rspq, rspq_sm_init_wait);
+ break;
+
+ case RSPQ_E_STOP:
+ case RSPQ_E_FAIL:
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+rspq_sm_init_wait_entry(struct bfa_msgq_rspq *rspq)
+{
+ bfa_wc_down(&rspq->msgq->init_wc);
+}
+
+static void
+rspq_sm_init_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
+{
+ switch (event) {
+ case RSPQ_E_FAIL:
+ case RSPQ_E_STOP:
+ bfa_fsm_set_state(rspq, rspq_sm_stopped);
+ break;
+
+ case RSPQ_E_INIT_RESP:
+ bfa_fsm_set_state(rspq, rspq_sm_ready);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+rspq_sm_ready_entry(struct bfa_msgq_rspq *rspq)
+{
+}
+
+static void
+rspq_sm_ready(struct bfa_msgq_rspq *rspq, enum rspq_event event)
+{
+ switch (event) {
+ case RSPQ_E_STOP:
+ case RSPQ_E_FAIL:
+ bfa_fsm_set_state(rspq, rspq_sm_stopped);
+ break;
+
+ case RSPQ_E_RESP:
+ bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+rspq_sm_dbell_wait_entry(struct bfa_msgq_rspq *rspq)
+{
+ if (!bfa_nw_ioc_is_disabled(rspq->msgq->ioc))
+ bfa_msgq_rspq_dbell(rspq);
+}
+
+static void
+rspq_sm_dbell_wait(struct bfa_msgq_rspq *rspq, enum rspq_event event)
+{
+ switch (event) {
+ case RSPQ_E_STOP:
+ case RSPQ_E_FAIL:
+ bfa_fsm_set_state(rspq, rspq_sm_stopped);
+ break;
+
+ case RSPQ_E_RESP:
+ rspq->flags |= BFA_MSGQ_RSPQ_F_DB_UPDATE;
+ break;
+
+ case RSPQ_E_DB_READY:
+ if (rspq->flags & BFA_MSGQ_RSPQ_F_DB_UPDATE) {
+ rspq->flags &= ~BFA_MSGQ_RSPQ_F_DB_UPDATE;
+ bfa_fsm_set_state(rspq, rspq_sm_dbell_wait);
+ } else
+ bfa_fsm_set_state(rspq, rspq_sm_ready);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bfa_msgq_rspq_dbell_ready(void *arg)
+{
+ struct bfa_msgq_rspq *rspq = (struct bfa_msgq_rspq *)arg;
+ bfa_fsm_send_event(rspq, RSPQ_E_DB_READY);
+}
+
+static void
+bfa_msgq_rspq_dbell(struct bfa_msgq_rspq *rspq)
+{
+ struct bfi_msgq_h2i_db *dbell =
+ (struct bfi_msgq_h2i_db *)(&rspq->dbell_mb.msg[0]);
+
+ memset(dbell, 0, sizeof(struct bfi_msgq_h2i_db));
+ bfi_h2i_set(dbell->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_DOORBELL_CI, 0);
+ dbell->mh.mtag.i2htok = 0;
+ dbell->idx.rspq_ci = htons(rspq->consumer_index);
+
+ if (!bfa_nw_ioc_mbox_queue(rspq->msgq->ioc, &rspq->dbell_mb,
+ bfa_msgq_rspq_dbell_ready, rspq)) {
+ bfa_msgq_rspq_dbell_ready(rspq);
+ }
+}
+
+static void
+bfa_msgq_rspq_pi_update(struct bfa_msgq_rspq *rspq, struct bfi_mbmsg *mb)
+{
+ struct bfi_msgq_i2h_db *dbell = (struct bfi_msgq_i2h_db *)mb;
+ struct bfi_msgq_mhdr *msghdr;
+ int num_entries;
+ int mc;
+ u8 *rspq_qe;
+
+ rspq->producer_index = ntohs(dbell->idx.rspq_pi);
+
+ while (rspq->consumer_index != rspq->producer_index) {
+ rspq_qe = (u8 *)rspq->addr.kva;
+ rspq_qe += (rspq->consumer_index * BFI_MSGQ_RSP_ENTRY_SIZE);
+ msghdr = (struct bfi_msgq_mhdr *)rspq_qe;
+
+ mc = msghdr->msg_class;
+ num_entries = ntohs(msghdr->num_entries);
+
+ if ((mc >= BFI_MC_MAX) || (rspq->rsphdlr[mc].cbfn == NULL))
+ break;
+
+ (rspq->rsphdlr[mc].cbfn)(rspq->rsphdlr[mc].cbarg, msghdr);
+
+ BFA_MSGQ_INDX_ADD(rspq->consumer_index, num_entries,
+ rspq->depth);
+ }
+
+ bfa_fsm_send_event(rspq, RSPQ_E_RESP);
+}
+
+static void
+bfa_msgq_rspq_attach(struct bfa_msgq_rspq *rspq, struct bfa_msgq *msgq)
+{
+ rspq->depth = BFA_MSGQ_RSPQ_NUM_ENTRY;
+ rspq->msgq = msgq;
+ bfa_fsm_set_state(rspq, rspq_sm_stopped);
+}
+
+static void
+bfa_msgq_init_rsp(struct bfa_msgq *msgq,
+ struct bfi_mbmsg *mb)
+{
+ bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_INIT_RESP);
+ bfa_fsm_send_event(&msgq->rspq, RSPQ_E_INIT_RESP);
+}
+
+static void
+bfa_msgq_init(void *arg)
+{
+ struct bfa_msgq *msgq = (struct bfa_msgq *)arg;
+ struct bfi_msgq_cfg_req *msgq_cfg =
+ (struct bfi_msgq_cfg_req *)&msgq->init_mb.msg[0];
+
+ memset(msgq_cfg, 0, sizeof(struct bfi_msgq_cfg_req));
+ bfi_h2i_set(msgq_cfg->mh, BFI_MC_MSGQ, BFI_MSGQ_H2I_INIT_REQ, 0);
+ msgq_cfg->mh.mtag.i2htok = 0;
+
+ bfa_dma_be_addr_set(msgq_cfg->cmdq.addr, msgq->cmdq.addr.pa);
+ msgq_cfg->cmdq.q_depth = htons(msgq->cmdq.depth);
+ bfa_dma_be_addr_set(msgq_cfg->rspq.addr, msgq->rspq.addr.pa);
+ msgq_cfg->rspq.q_depth = htons(msgq->rspq.depth);
+
+ bfa_nw_ioc_mbox_queue(msgq->ioc, &msgq->init_mb, NULL, NULL);
+}
+
+static void
+bfa_msgq_isr(void *cbarg, struct bfi_mbmsg *msg)
+{
+ struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
+
+ switch (msg->mh.msg_id) {
+ case BFI_MSGQ_I2H_INIT_RSP:
+ bfa_msgq_init_rsp(msgq, msg);
+ break;
+
+ case BFI_MSGQ_I2H_DOORBELL_PI:
+ bfa_msgq_rspq_pi_update(&msgq->rspq, msg);
+ break;
+
+ case BFI_MSGQ_I2H_DOORBELL_CI:
+ bfa_msgq_cmdq_ci_update(&msgq->cmdq, msg);
+ break;
+
+ case BFI_MSGQ_I2H_CMDQ_COPY_REQ:
+ bfa_msgq_cmdq_copy_req(&msgq->cmdq, msg);
+ break;
+
+ default:
+ BUG_ON(1);
+ }
+}
+
+static void
+bfa_msgq_notify(void *cbarg, enum bfa_ioc_event event)
+{
+ struct bfa_msgq *msgq = (struct bfa_msgq *)cbarg;
+
+ switch (event) {
+ case BFA_IOC_E_ENABLED:
+ bfa_wc_init(&msgq->init_wc, bfa_msgq_init, msgq);
+ bfa_wc_up(&msgq->init_wc);
+ bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_START);
+ bfa_wc_up(&msgq->init_wc);
+ bfa_fsm_send_event(&msgq->rspq, RSPQ_E_START);
+ bfa_wc_wait(&msgq->init_wc);
+ break;
+
+ case BFA_IOC_E_DISABLED:
+ bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_STOP);
+ bfa_fsm_send_event(&msgq->rspq, RSPQ_E_STOP);
+ break;
+
+ case BFA_IOC_E_FAILED:
+ bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_FAIL);
+ bfa_fsm_send_event(&msgq->rspq, RSPQ_E_FAIL);
+ break;
+
+ default:
+ break;
+ }
+}
+
+u32
+bfa_msgq_meminfo(void)
+{
+ return roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ) +
+ roundup(BFA_MSGQ_RSPQ_SIZE, BFA_DMA_ALIGN_SZ);
+}
+
+void
+bfa_msgq_memclaim(struct bfa_msgq *msgq, u8 *kva, u64 pa)
+{
+ msgq->cmdq.addr.kva = kva;
+ msgq->cmdq.addr.pa = pa;
+
+ kva += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
+ pa += roundup(BFA_MSGQ_CMDQ_SIZE, BFA_DMA_ALIGN_SZ);
+
+ msgq->rspq.addr.kva = kva;
+ msgq->rspq.addr.pa = pa;
+}
+
+void
+bfa_msgq_attach(struct bfa_msgq *msgq, struct bfa_ioc *ioc)
+{
+ msgq->ioc = ioc;
+
+ bfa_msgq_cmdq_attach(&msgq->cmdq, msgq);
+ bfa_msgq_rspq_attach(&msgq->rspq, msgq);
+
+ bfa_nw_ioc_mbox_regisr(msgq->ioc, BFI_MC_MSGQ, bfa_msgq_isr, msgq);
+ bfa_q_qe_init(&msgq->ioc_notify);
+ bfa_ioc_notify_init(&msgq->ioc_notify, bfa_msgq_notify, msgq);
+ bfa_nw_ioc_notify_register(msgq->ioc, &msgq->ioc_notify);
+}
+
+void
+bfa_msgq_regisr(struct bfa_msgq *msgq, enum bfi_mclass mc,
+ bfa_msgq_mcfunc_t cbfn, void *cbarg)
+{
+ msgq->rspq.rsphdlr[mc].cbfn = cbfn;
+ msgq->rspq.rsphdlr[mc].cbarg = cbarg;
+}
+
+void
+bfa_msgq_cmd_post(struct bfa_msgq *msgq, struct bfa_msgq_cmd_entry *cmd)
+{
+ if (ntohs(cmd->msg_hdr->num_entries) <=
+ BFA_MSGQ_FREE_CNT(&msgq->cmdq)) {
+ __cmd_copy(&msgq->cmdq, cmd);
+ call_cmdq_ent_cbfn(cmd, BFA_STATUS_OK);
+ bfa_fsm_send_event(&msgq->cmdq, CMDQ_E_POST);
+ } else {
+ list_add_tail(&cmd->qe, &msgq->cmdq.pending_q);
+ }
+}
+
+void
+bfa_msgq_rsp_copy(struct bfa_msgq *msgq, u8 *buf, size_t buf_len)
+{
+ struct bfa_msgq_rspq *rspq = &msgq->rspq;
+ size_t len = buf_len;
+ size_t to_copy;
+ int ci;
+ u8 *src, *dst;
+
+ ci = rspq->consumer_index;
+ src = (u8 *)rspq->addr.kva;
+ src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
+ dst = buf;
+
+ while (len) {
+ to_copy = (len < BFI_MSGQ_RSP_ENTRY_SIZE) ?
+ len : BFI_MSGQ_RSP_ENTRY_SIZE;
+ memcpy(dst, src, to_copy);
+ len -= to_copy;
+ dst += BFI_MSGQ_RSP_ENTRY_SIZE;
+ BFA_MSGQ_INDX_ADD(ci, 1, rspq->depth);
+ src = (u8 *)rspq->addr.kva;
+ src += (ci * BFI_MSGQ_RSP_ENTRY_SIZE);
+ }
+}
diff --git a/drivers/net/ethernet/brocade/bna/bfa_msgq.h b/drivers/net/ethernet/brocade/bna/bfa_msgq.h
new file mode 100644
index 000000000000..a6a565a366dc
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/bfa_msgq.h
@@ -0,0 +1,130 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFA_MSGQ_H__
+#define __BFA_MSGQ_H__
+
+#include "bfa_defs.h"
+#include "bfi.h"
+#include "bfa_ioc.h"
+#include "bfa_cs.h"
+
+#define BFA_MSGQ_FREE_CNT(_q) \
+ (((_q)->consumer_index - (_q)->producer_index - 1) & ((_q)->depth - 1))
+
+#define BFA_MSGQ_INDX_ADD(_q_indx, _qe_num, _q_depth) \
+ ((_q_indx) = (((_q_indx) + (_qe_num)) & ((_q_depth) - 1)))
+
+#define BFA_MSGQ_CMDQ_NUM_ENTRY 128
+#define BFA_MSGQ_CMDQ_SIZE \
+ (BFI_MSGQ_CMD_ENTRY_SIZE * BFA_MSGQ_CMDQ_NUM_ENTRY)
+
+#define BFA_MSGQ_RSPQ_NUM_ENTRY 128
+#define BFA_MSGQ_RSPQ_SIZE \
+ (BFI_MSGQ_RSP_ENTRY_SIZE * BFA_MSGQ_RSPQ_NUM_ENTRY)
+
+#define bfa_msgq_cmd_set(_cmd, _cbfn, _cbarg, _msg_size, _msg_hdr) \
+do { \
+ (_cmd)->cbfn = (_cbfn); \
+ (_cmd)->cbarg = (_cbarg); \
+ (_cmd)->msg_size = (_msg_size); \
+ (_cmd)->msg_hdr = (_msg_hdr); \
+} while (0)
+
+struct bfa_msgq;
+
+typedef void (*bfa_msgq_cmdcbfn_t)(void *cbarg, enum bfa_status status);
+
+struct bfa_msgq_cmd_entry {
+ struct list_head qe;
+ bfa_msgq_cmdcbfn_t cbfn;
+ void *cbarg;
+ size_t msg_size;
+ struct bfi_msgq_mhdr *msg_hdr;
+};
+
+enum bfa_msgq_cmdq_flags {
+ BFA_MSGQ_CMDQ_F_DB_UPDATE = 1,
+};
+
+struct bfa_msgq_cmdq {
+ bfa_fsm_t fsm;
+ enum bfa_msgq_cmdq_flags flags;
+
+ u16 producer_index;
+ u16 consumer_index;
+ u16 depth; /* FW Q depth is 16 bits */
+ struct bfa_dma addr;
+ struct bfa_mbox_cmd dbell_mb;
+
+ u16 token;
+ int offset;
+ int bytes_to_copy;
+ struct bfa_mbox_cmd copy_mb;
+
+ struct list_head pending_q; /* pending command queue */
+
+ struct bfa_msgq *msgq;
+};
+
+enum bfa_msgq_rspq_flags {
+ BFA_MSGQ_RSPQ_F_DB_UPDATE = 1,
+};
+
+typedef void (*bfa_msgq_mcfunc_t)(void *cbarg, struct bfi_msgq_mhdr *mhdr);
+
+struct bfa_msgq_rspq {
+ bfa_fsm_t fsm;
+ enum bfa_msgq_rspq_flags flags;
+
+ u16 producer_index;
+ u16 consumer_index;
+ u16 depth; /* FW Q depth is 16 bits */
+ struct bfa_dma addr;
+ struct bfa_mbox_cmd dbell_mb;
+
+ int nmclass;
+ struct {
+ bfa_msgq_mcfunc_t cbfn;
+ void *cbarg;
+ } rsphdlr[BFI_MC_MAX];
+
+ struct bfa_msgq *msgq;
+};
+
+struct bfa_msgq {
+ struct bfa_msgq_cmdq cmdq;
+ struct bfa_msgq_rspq rspq;
+
+ struct bfa_wc init_wc;
+ struct bfa_mbox_cmd init_mb;
+
+ struct bfa_ioc_notify ioc_notify;
+ struct bfa_ioc *ioc;
+};
+
+u32 bfa_msgq_meminfo(void);
+void bfa_msgq_memclaim(struct bfa_msgq *msgq, u8 *kva, u64 pa);
+void bfa_msgq_attach(struct bfa_msgq *msgq, struct bfa_ioc *ioc);
+void bfa_msgq_regisr(struct bfa_msgq *msgq, enum bfi_mclass mc,
+ bfa_msgq_mcfunc_t cbfn, void *cbarg);
+void bfa_msgq_cmd_post(struct bfa_msgq *msgq,
+ struct bfa_msgq_cmd_entry *cmd);
+void bfa_msgq_rsp_copy(struct bfa_msgq *msgq, u8 *buf, size_t buf_len);
+
+#endif
diff --git a/drivers/net/bna/bfi.h b/drivers/net/ethernet/brocade/bna/bfi.h
index 088211c2724f..7a1393aabd43 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/ethernet/brocade/bna/bfi.h
@@ -15,7 +15,6 @@
* All rights reserved
* www.brocade.com
*/
-
#ifndef __BFI_H__
#define __BFI_H__
@@ -28,12 +27,6 @@
*/
#define BFI_FLASH_CHUNK_SZ 256 /*!< Flash chunk size */
#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32))
-enum {
- BFI_IMAGE_CB_FC,
- BFI_IMAGE_CT_FC,
- BFI_IMAGE_CT_CNA,
- BFI_IMAGE_MAX,
-};
/**
* Msg header common to all msgs
@@ -43,17 +36,21 @@ struct bfi_mhdr {
u8 msg_id; /*!< msg opcode with in the class */
union {
struct {
- u8 rsvd;
- u8 lpu_id; /*!< msg destination */
+ u8 qid;
+ u8 fn_lpu; /*!< msg destination */
} h2i;
u16 i2htok; /*!< token in msgs to host */
} mtag;
};
-#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do { \
+#define bfi_fn_lpu(__fn, __lpu) ((__fn) << 1 | (__lpu))
+#define bfi_mhdr_2_fn(_mh) ((_mh)->mtag.h2i.fn_lpu >> 1)
+#define bfi_mhdr_2_qid(_mh) ((_mh)->mtag.h2i.qid)
+
+#define bfi_h2i_set(_mh, _mc, _op, _fn_lpu) do { \
(_mh).msg_class = (_mc); \
(_mh).msg_id = (_op); \
- (_mh).mtag.h2i.lpu_id = (_lpuid); \
+ (_mh).mtag.h2i.fn_lpu = (_fn_lpu); \
} while (0)
#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do { \
@@ -76,20 +73,6 @@ struct bfi_mhdr {
****************************************************************************
*/
-#define BFI_SGE_INLINE 1
-#define BFI_SGE_INLINE_MAX (BFI_SGE_INLINE + 1)
-
-/**
- * SG Flags
- */
-enum {
- BFI_SGE_DATA = 0, /*!< data address, not last */
- BFI_SGE_DATA_CPL = 1, /*!< data addr, last in current page */
- BFI_SGE_DATA_LAST = 3, /*!< data address, last */
- BFI_SGE_LINK = 2, /*!< link address */
- BFI_SGE_PGDLEN = 2, /*!< cumulative data length for page */
-};
-
/**
* DMA addresses
*/
@@ -100,33 +83,6 @@ union bfi_addr_u {
} a32;
};
-/**
- * Scatter Gather Element
- */
-struct bfi_sge {
-#ifdef __BIGENDIAN
- u32 flags:2,
- rsvd:2,
- sg_len:28;
-#else
- u32 sg_len:28,
- rsvd:2,
- flags:2;
-#endif
- union bfi_addr_u sga;
-};
-
-/**
- * Scatter Gather Page
- */
-#define BFI_SGPG_DATA_SGES 7
-#define BFI_SGPG_SGES_MAX (BFI_SGPG_DATA_SGES + 1)
-#define BFI_SGPG_RSVD_WD_LEN 8
-struct bfi_sgpg {
- struct bfi_sge sges[BFI_SGPG_SGES_MAX];
- u32 rsvd[BFI_SGPG_RSVD_WD_LEN];
-};
-
/*
* Large Message structure - 128 Bytes size Msgs
*/
@@ -134,11 +90,6 @@ struct bfi_sgpg {
#define BFI_LMSG_PL_WSZ \
((BFI_LMSG_SZ - sizeof(struct bfi_mhdr)) / 4)
-struct bfi_msg {
- struct bfi_mhdr mhdr;
- u32 pl[BFI_LMSG_PL_WSZ];
-};
-
/**
* Mailbox message structure
*/
@@ -149,6 +100,14 @@ struct bfi_mbmsg {
};
/**
+ * Supported PCI function class codes (personality)
+ */
+enum bfi_pcifn_class {
+ BFI_PCIFN_CLASS_FC = 0x0c04,
+ BFI_PCIFN_CLASS_ETH = 0x0200,
+};
+
+/**
* Message Classes
*/
enum bfi_mclass {
@@ -176,24 +135,21 @@ enum bfi_mclass {
BFI_MC_SFP = 22, /*!< SFP module */
BFI_MC_MSGQ = 23, /*!< MSGQ */
BFI_MC_ENET = 24, /*!< ENET commands/responses */
- BFI_MC_MAX = 32
+ BFI_MC_PHY = 25, /*!< External PHY message class */
+ BFI_MC_NBOOT = 26, /*!< Network Boot */
+ BFI_MC_TIO_READ = 27, /*!< read IO (Target mode) */
+ BFI_MC_TIO_WRITE = 28, /*!< write IO (Target mode) */
+ BFI_MC_TIO_DATA_XFERED = 29, /*!< ds transferred (target mode) */
+ BFI_MC_TIO_IO = 30, /*!< IO (Target mode) */
+ BFI_MC_TIO = 31, /*!< IO (target mode) */
+ BFI_MC_MFG = 32, /*!< MFG/ASIC block commands */
+ BFI_MC_EDMA = 33, /*!< EDMA copy commands */
+ BFI_MC_MAX = 34
};
-#define BFI_IOC_MAX_CQS 4
-#define BFI_IOC_MAX_CQS_ASIC 8
#define BFI_IOC_MSGLEN_MAX 32 /* 32 bytes */
-#define BFI_BOOT_TYPE_OFF 8
-#define BFI_BOOT_LOADER_OFF 12
-
-#define BFI_BOOT_TYPE_NORMAL 0
-#define BFI_BOOT_TYPE_FLASH 1
-#define BFI_BOOT_TYPE_MEMTEST 2
-
-#define BFI_BOOT_LOADER_OS 0
-
-#define BFI_BOOT_MEMTEST_RES_ADDR 0x900
-#define BFI_BOOT_MEMTEST_RES_SIG 0xA0A1A2A3
+#define BFI_FWBOOT_ENV_OS 0
/**
*----------------------------------------------------------------------
@@ -201,6 +157,22 @@ enum bfi_mclass {
*----------------------------------------------------------------------
*/
+/**
+ * Different asic generations
+ */
+enum bfi_asic_gen {
+ BFI_ASIC_GEN_CB = 1,
+ BFI_ASIC_GEN_CT = 2,
+ BFI_ASIC_GEN_CT2 = 3,
+};
+
+enum bfi_asic_mode {
+ BFI_ASIC_MODE_FC = 1, /* FC upto 8G speed */
+ BFI_ASIC_MODE_FC16 = 2, /* FC upto 16G speed */
+ BFI_ASIC_MODE_ETH = 3, /* Ethernet ports */
+ BFI_ASIC_MODE_COMBO = 4, /* FC 16G and Ethernet 10G port */
+};
+
enum bfi_ioc_h2i_msgs {
BFI_IOC_H2I_ENABLE_REQ = 1,
BFI_IOC_H2I_DISABLE_REQ = 2,
@@ -213,8 +185,7 @@ enum bfi_ioc_i2h_msgs {
BFI_IOC_I2H_ENABLE_REPLY = BFA_I2HM(1),
BFI_IOC_I2H_DISABLE_REPLY = BFA_I2HM(2),
BFI_IOC_I2H_GETATTR_REPLY = BFA_I2HM(3),
- BFI_IOC_I2H_READY_EVENT = BFA_I2HM(4),
- BFI_IOC_I2H_HBEAT = BFA_I2HM(5),
+ BFI_IOC_I2H_HBEAT = BFA_I2HM(4),
};
/**
@@ -229,7 +200,8 @@ struct bfi_ioc_attr {
u64 mfg_pwwn; /*!< Mfg port wwn */
u64 mfg_nwwn; /*!< Mfg node wwn */
mac_t mfg_mac; /*!< Mfg mac */
- u16 rsvd_a;
+ u8 port_mode; /* enum bfi_port_mode */
+ u8 rsvd_a;
u64 pwwn;
u64 nwwn;
mac_t mac; /*!< PBC or Mfg mac */
@@ -282,26 +254,34 @@ struct bfi_ioc_getattr_reply {
#define BFI_IOC_MD5SUM_SZ 4
struct bfi_ioc_image_hdr {
u32 signature; /*!< constant signature */
- u32 rsvd_a;
+ u8 asic_gen; /*!< asic generation */
+ u8 asic_mode;
+ u8 port0_mode; /*!< device mode for port 0 */
+ u8 port1_mode; /*!< device mode for port 1 */
u32 exec; /*!< exec vector */
- u32 param; /*!< parameters */
+ u32 bootenv; /*!< firmware boot env */
u32 rsvd_b[4];
u32 md5sum[BFI_IOC_MD5SUM_SZ];
};
+#define BFI_FWBOOT_DEVMODE_OFF 4
+#define BFI_FWBOOT_TYPE_OFF 8
+#define BFI_FWBOOT_ENV_OFF 12
+#define BFI_FWBOOT_DEVMODE(__asic_gen, __asic_mode, __p0_mode, __p1_mode) \
+ (((u32)(__asic_gen)) << 24 | \
+ ((u32)(__asic_mode)) << 16 | \
+ ((u32)(__p0_mode)) << 8 | \
+ ((u32)(__p1_mode)))
+
enum bfi_fwboot_type {
BFI_FWBOOT_TYPE_NORMAL = 0,
BFI_FWBOOT_TYPE_FLASH = 1,
BFI_FWBOOT_TYPE_MEMTEST = 2,
};
-/**
- * BFI_IOC_I2H_READY_EVENT message
- */
-struct bfi_ioc_rdy_event {
- struct bfi_mhdr mh; /*!< common msg header */
- u8 init_status; /*!< init event status */
- u8 rsvd[3];
+enum bfi_port_mode {
+ BFI_PORT_MODE_FC = 1,
+ BFI_PORT_MODE_ETH = 2,
};
struct bfi_ioc_hbeat {
@@ -360,8 +340,8 @@ enum {
*/
struct bfi_ioc_ctrl_req {
struct bfi_mhdr mh;
- u8 ioc_class;
- u8 rsvd[3];
+ u16 clscode;
+ u16 rsvd;
u32 tv_sec;
};
@@ -369,9 +349,11 @@ struct bfi_ioc_ctrl_req {
* BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
*/
struct bfi_ioc_ctrl_reply {
- struct bfi_mhdr mh; /*!< Common msg header */
+ struct bfi_mhdr mh; /*!< Common msg header */
u8 status; /*!< enable/disable status */
- u8 rsvd[3];
+ u8 port_mode; /*!< enum bfa_mode */
+ u8 cap_bm; /*!< capability bit mask */
+ u8 rsvd;
};
#define BFI_IOC_MSGSZ 8
@@ -391,10 +373,109 @@ union bfi_ioc_h2i_msg_u {
*/
union bfi_ioc_i2h_msg_u {
struct bfi_mhdr mh;
- struct bfi_ioc_rdy_event rdy_event;
+ struct bfi_ioc_ctrl_reply fw_event;
u32 mboxmsg[BFI_IOC_MSGSZ];
};
+/**
+ *----------------------------------------------------------------------
+ * MSGQ
+ *----------------------------------------------------------------------
+ */
+
+enum bfi_msgq_h2i_msgs {
+ BFI_MSGQ_H2I_INIT_REQ = 1,
+ BFI_MSGQ_H2I_DOORBELL_PI = 2,
+ BFI_MSGQ_H2I_DOORBELL_CI = 3,
+ BFI_MSGQ_H2I_CMDQ_COPY_RSP = 4,
+};
+
+enum bfi_msgq_i2h_msgs {
+ BFI_MSGQ_I2H_INIT_RSP = BFA_I2HM(BFI_MSGQ_H2I_INIT_REQ),
+ BFI_MSGQ_I2H_DOORBELL_PI = BFA_I2HM(BFI_MSGQ_H2I_DOORBELL_PI),
+ BFI_MSGQ_I2H_DOORBELL_CI = BFA_I2HM(BFI_MSGQ_H2I_DOORBELL_CI),
+ BFI_MSGQ_I2H_CMDQ_COPY_REQ = BFA_I2HM(BFI_MSGQ_H2I_CMDQ_COPY_RSP),
+};
+
+/* Messages(commands/responsed/AENS will have the following header */
+struct bfi_msgq_mhdr {
+ u8 msg_class;
+ u8 msg_id;
+ u16 msg_token;
+ u16 num_entries;
+ u8 enet_id;
+ u8 rsvd[1];
+};
+
+#define bfi_msgq_mhdr_set(_mh, _mc, _mid, _tok, _enet_id) do { \
+ (_mh).msg_class = (_mc); \
+ (_mh).msg_id = (_mid); \
+ (_mh).msg_token = (_tok); \
+ (_mh).enet_id = (_enet_id); \
+} while (0)
+
+/*
+ * Mailbox for messaging interface
+ */
+#define BFI_MSGQ_CMD_ENTRY_SIZE (64) /* TBD */
+#define BFI_MSGQ_RSP_ENTRY_SIZE (64) /* TBD */
+
+#define bfi_msgq_num_cmd_entries(_size) \
+ (((_size) + BFI_MSGQ_CMD_ENTRY_SIZE - 1) / BFI_MSGQ_CMD_ENTRY_SIZE)
+
+struct bfi_msgq {
+ union bfi_addr_u addr;
+ u16 q_depth; /* Total num of entries in the queue */
+ u8 rsvd[2];
+};
+
+/* BFI_ENET_MSGQ_CFG_REQ TBD init or cfg? */
+struct bfi_msgq_cfg_req {
+ struct bfi_mhdr mh;
+ struct bfi_msgq cmdq;
+ struct bfi_msgq rspq;
+};
+
+/* BFI_ENET_MSGQ_CFG_RSP */
+struct bfi_msgq_cfg_rsp {
+ struct bfi_mhdr mh;
+ u8 cmd_status;
+ u8 rsvd[3];
+};
+
+/* BFI_MSGQ_H2I_DOORBELL */
+struct bfi_msgq_h2i_db {
+ struct bfi_mhdr mh;
+ union {
+ u16 cmdq_pi;
+ u16 rspq_ci;
+ } idx;
+};
+
+/* BFI_MSGQ_I2H_DOORBELL */
+struct bfi_msgq_i2h_db {
+ struct bfi_mhdr mh;
+ union {
+ u16 rspq_pi;
+ u16 cmdq_ci;
+ } idx;
+};
+
+#define BFI_CMD_COPY_SZ 28
+
+/* BFI_MSGQ_H2I_CMD_COPY_RSP */
+struct bfi_msgq_h2i_cmdq_copy_rsp {
+ struct bfi_mhdr mh;
+ u8 data[BFI_CMD_COPY_SZ];
+};
+
+/* BFI_MSGQ_I2H_CMD_COPY_REQ */
+struct bfi_msgq_i2h_cmdq_copy_req {
+ struct bfi_mhdr mh;
+ u16 offset;
+ u16 len;
+};
+
#pragma pack()
#endif /* __BFI_H__ */
diff --git a/drivers/net/bna/bfi_cna.h b/drivers/net/ethernet/brocade/bna/bfi_cna.h
index 4eecabea397b..4eecabea397b 100644
--- a/drivers/net/bna/bfi_cna.h
+++ b/drivers/net/ethernet/brocade/bna/bfi_cna.h
diff --git a/drivers/net/ethernet/brocade/bna/bfi_enet.h b/drivers/net/ethernet/brocade/bna/bfi_enet.h
new file mode 100644
index 000000000000..a90f1cf46b41
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/bfi_enet.h
@@ -0,0 +1,901 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/**
+ * @file bfi_enet.h BNA Hardware and Firmware Interface
+ */
+
+/**
+ * Skipping statistics collection to avoid clutter.
+ * Command is no longer needed:
+ * MTU
+ * TxQ Stop
+ * RxQ Stop
+ * RxF Enable/Disable
+ *
+ * HDS-off request is dynamic
+ * keep structures as multiple of 32-bit fields for alignment.
+ * All values must be written in big-endian.
+ */
+#ifndef __BFI_ENET_H__
+#define __BFI_ENET_H__
+
+#include "bfa_defs.h"
+#include "bfi.h"
+
+#pragma pack(1)
+
+#define BFI_ENET_CFG_MAX 32 /* Max resources per PF */
+
+#define BFI_ENET_TXQ_PRIO_MAX 8
+#define BFI_ENET_RX_QSET_MAX 16
+#define BFI_ENET_TXQ_WI_VECT_MAX 4
+
+#define BFI_ENET_VLAN_ID_MAX 4096
+#define BFI_ENET_VLAN_BLOCK_SIZE 512 /* in bits */
+#define BFI_ENET_VLAN_BLOCKS_MAX \
+ (BFI_ENET_VLAN_ID_MAX / BFI_ENET_VLAN_BLOCK_SIZE)
+#define BFI_ENET_VLAN_WORD_SIZE 32 /* in bits */
+#define BFI_ENET_VLAN_WORDS_MAX \
+ (BFI_ENET_VLAN_BLOCK_SIZE / BFI_ENET_VLAN_WORD_SIZE)
+
+#define BFI_ENET_RSS_RIT_MAX 64 /* entries */
+#define BFI_ENET_RSS_KEY_LEN 10 /* 32-bit words */
+
+union bfi_addr_be_u {
+ struct {
+ u32 addr_hi; /* Most Significant 32-bits */
+ u32 addr_lo; /* Least Significant 32-Bits */
+ } a32;
+};
+
+/**
+ * T X Q U E U E D E F I N E S
+ */
+/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */
+/* TxQ Entry Opcodes */
+#define BFI_ENET_TXQ_WI_SEND (0x402) /* Single Frame Transmission */
+#define BFI_ENET_TXQ_WI_SEND_LSO (0x403) /* Multi-Frame Transmission */
+#define BFI_ENET_TXQ_WI_EXTENSION (0x104) /* Extension WI */
+
+/* TxQ Entry Control Flags */
+#define BFI_ENET_TXQ_WI_CF_FCOE_CRC (1 << 8)
+#define BFI_ENET_TXQ_WI_CF_IPID_MODE (1 << 5)
+#define BFI_ENET_TXQ_WI_CF_INS_PRIO (1 << 4)
+#define BFI_ENET_TXQ_WI_CF_INS_VLAN (1 << 3)
+#define BFI_ENET_TXQ_WI_CF_UDP_CKSUM (1 << 2)
+#define BFI_ENET_TXQ_WI_CF_TCP_CKSUM (1 << 1)
+#define BFI_ENET_TXQ_WI_CF_IP_CKSUM (1 << 0)
+
+struct bfi_enet_txq_wi_base {
+ u8 reserved;
+ u8 num_vectors; /* number of vectors present */
+ u16 opcode;
+ /* BFI_ENET_TXQ_WI_SEND or BFI_ENET_TXQ_WI_SEND_LSO */
+ u16 flags; /* OR of all the flags */
+ u16 l4_hdr_size_n_offset;
+ u16 vlan_tag;
+ u16 lso_mss; /* Only 14 LSB are valid */
+ u32 frame_length; /* Only 24 LSB are valid */
+};
+
+struct bfi_enet_txq_wi_ext {
+ u16 reserved;
+ u16 opcode; /* BFI_ENET_TXQ_WI_EXTENSION */
+ u32 reserved2[3];
+};
+
+struct bfi_enet_txq_wi_vector { /* Tx Buffer Descriptor */
+ u16 reserved;
+ u16 length; /* Only 14 LSB are valid */
+ union bfi_addr_be_u addr;
+};
+
+/**
+ * TxQ Entry Structure
+ *
+ */
+struct bfi_enet_txq_entry {
+ union {
+ struct bfi_enet_txq_wi_base base;
+ struct bfi_enet_txq_wi_ext ext;
+ } wi;
+ struct bfi_enet_txq_wi_vector vector[BFI_ENET_TXQ_WI_VECT_MAX];
+};
+
+#define wi_hdr wi.base
+#define wi_ext_hdr wi.ext
+
+#define BFI_ENET_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
+ (((_hdr_size) << 10) | ((_offset) & 0x3FF))
+
+/**
+ * R X Q U E U E D E F I N E S
+ */
+struct bfi_enet_rxq_entry {
+ union bfi_addr_be_u rx_buffer;
+};
+
+/**
+ * R X C O M P L E T I O N Q U E U E D E F I N E S
+ */
+/* CQ Entry Flags */
+#define BFI_ENET_CQ_EF_MAC_ERROR (1 << 0)
+#define BFI_ENET_CQ_EF_FCS_ERROR (1 << 1)
+#define BFI_ENET_CQ_EF_TOO_LONG (1 << 2)
+#define BFI_ENET_CQ_EF_FC_CRC_OK (1 << 3)
+
+#define BFI_ENET_CQ_EF_RSVD1 (1 << 4)
+#define BFI_ENET_CQ_EF_L4_CKSUM_OK (1 << 5)
+#define BFI_ENET_CQ_EF_L3_CKSUM_OK (1 << 6)
+#define BFI_ENET_CQ_EF_HDS_HEADER (1 << 7)
+
+#define BFI_ENET_CQ_EF_UDP (1 << 8)
+#define BFI_ENET_CQ_EF_TCP (1 << 9)
+#define BFI_ENET_CQ_EF_IP_OPTIONS (1 << 10)
+#define BFI_ENET_CQ_EF_IPV6 (1 << 11)
+
+#define BFI_ENET_CQ_EF_IPV4 (1 << 12)
+#define BFI_ENET_CQ_EF_VLAN (1 << 13)
+#define BFI_ENET_CQ_EF_RSS (1 << 14)
+#define BFI_ENET_CQ_EF_RSVD2 (1 << 15)
+
+#define BFI_ENET_CQ_EF_MCAST_MATCH (1 << 16)
+#define BFI_ENET_CQ_EF_MCAST (1 << 17)
+#define BFI_ENET_CQ_EF_BCAST (1 << 18)
+#define BFI_ENET_CQ_EF_REMOTE (1 << 19)
+
+#define BFI_ENET_CQ_EF_LOCAL (1 << 20)
+
+/* CQ Entry Structure */
+struct bfi_enet_cq_entry {
+ u32 flags;
+ u16 vlan_tag;
+ u16 length;
+ u32 rss_hash;
+ u8 valid;
+ u8 reserved1;
+ u8 reserved2;
+ u8 rxq_id;
+};
+
+/**
+ * E N E T C O N T R O L P A T H C O M M A N D S
+ */
+struct bfi_enet_q {
+ union bfi_addr_u pg_tbl;
+ union bfi_addr_u first_entry;
+ u16 pages; /* # of pages */
+ u16 page_sz;
+};
+
+struct bfi_enet_txq {
+ struct bfi_enet_q q;
+ u8 priority;
+ u8 rsvd[3];
+};
+
+struct bfi_enet_rxq {
+ struct bfi_enet_q q;
+ u16 rx_buffer_size;
+ u16 rsvd;
+};
+
+struct bfi_enet_cq {
+ struct bfi_enet_q q;
+};
+
+struct bfi_enet_ib_cfg {
+ u8 int_pkt_dma;
+ u8 int_enabled;
+ u8 int_pkt_enabled;
+ u8 continuous_coalescing;
+ u8 msix;
+ u8 rsvd[3];
+ u32 coalescing_timeout;
+ u32 inter_pkt_timeout;
+ u8 inter_pkt_count;
+ u8 rsvd1[3];
+};
+
+struct bfi_enet_ib {
+ union bfi_addr_u index_addr;
+ union {
+ u16 msix_index;
+ u16 intx_bitmask;
+ } intr;
+ u16 rsvd;
+};
+
+/**
+ * ENET command messages
+ */
+enum bfi_enet_h2i_msgs {
+ /* Rx Commands */
+ BFI_ENET_H2I_RX_CFG_SET_REQ = 1,
+ BFI_ENET_H2I_RX_CFG_CLR_REQ = 2,
+
+ BFI_ENET_H2I_RIT_CFG_REQ = 3,
+ BFI_ENET_H2I_RSS_CFG_REQ = 4,
+ BFI_ENET_H2I_RSS_ENABLE_REQ = 5,
+ BFI_ENET_H2I_RX_PROMISCUOUS_REQ = 6,
+ BFI_ENET_H2I_RX_DEFAULT_REQ = 7,
+
+ BFI_ENET_H2I_MAC_UCAST_SET_REQ = 8,
+ BFI_ENET_H2I_MAC_UCAST_CLR_REQ = 9,
+ BFI_ENET_H2I_MAC_UCAST_ADD_REQ = 10,
+ BFI_ENET_H2I_MAC_UCAST_DEL_REQ = 11,
+
+ BFI_ENET_H2I_MAC_MCAST_ADD_REQ = 12,
+ BFI_ENET_H2I_MAC_MCAST_DEL_REQ = 13,
+ BFI_ENET_H2I_MAC_MCAST_FILTER_REQ = 14,
+
+ BFI_ENET_H2I_RX_VLAN_SET_REQ = 15,
+ BFI_ENET_H2I_RX_VLAN_STRIP_ENABLE_REQ = 16,
+
+ /* Tx Commands */
+ BFI_ENET_H2I_TX_CFG_SET_REQ = 17,
+ BFI_ENET_H2I_TX_CFG_CLR_REQ = 18,
+
+ /* Port Commands */
+ BFI_ENET_H2I_PORT_ADMIN_UP_REQ = 19,
+ BFI_ENET_H2I_SET_PAUSE_REQ = 20,
+ BFI_ENET_H2I_DIAG_LOOPBACK_REQ = 21,
+
+ /* Get Attributes Command */
+ BFI_ENET_H2I_GET_ATTR_REQ = 22,
+
+ /* Statistics Commands */
+ BFI_ENET_H2I_STATS_GET_REQ = 23,
+ BFI_ENET_H2I_STATS_CLR_REQ = 24,
+
+ BFI_ENET_H2I_WOL_MAGIC_REQ = 25,
+ BFI_ENET_H2I_WOL_FRAME_REQ = 26,
+
+ BFI_ENET_H2I_MAX = 27,
+};
+
+enum bfi_enet_i2h_msgs {
+ /* Rx Responses */
+ BFI_ENET_I2H_RX_CFG_SET_RSP =
+ BFA_I2HM(BFI_ENET_H2I_RX_CFG_SET_REQ),
+ BFI_ENET_I2H_RX_CFG_CLR_RSP =
+ BFA_I2HM(BFI_ENET_H2I_RX_CFG_CLR_REQ),
+
+ BFI_ENET_I2H_RIT_CFG_RSP =
+ BFA_I2HM(BFI_ENET_H2I_RIT_CFG_REQ),
+ BFI_ENET_I2H_RSS_CFG_RSP =
+ BFA_I2HM(BFI_ENET_H2I_RSS_CFG_REQ),
+ BFI_ENET_I2H_RSS_ENABLE_RSP =
+ BFA_I2HM(BFI_ENET_H2I_RSS_ENABLE_REQ),
+ BFI_ENET_I2H_RX_PROMISCUOUS_RSP =
+ BFA_I2HM(BFI_ENET_H2I_RX_PROMISCUOUS_REQ),
+ BFI_ENET_I2H_RX_DEFAULT_RSP =
+ BFA_I2HM(BFI_ENET_H2I_RX_DEFAULT_REQ),
+
+ BFI_ENET_I2H_MAC_UCAST_SET_RSP =
+ BFA_I2HM(BFI_ENET_H2I_MAC_UCAST_SET_REQ),
+ BFI_ENET_I2H_MAC_UCAST_CLR_RSP =
+ BFA_I2HM(BFI_ENET_H2I_MAC_UCAST_CLR_REQ),
+ BFI_ENET_I2H_MAC_UCAST_ADD_RSP =
+ BFA_I2HM(BFI_ENET_H2I_MAC_UCAST_ADD_REQ),
+ BFI_ENET_I2H_MAC_UCAST_DEL_RSP =
+ BFA_I2HM(BFI_ENET_H2I_MAC_UCAST_DEL_REQ),
+
+ BFI_ENET_I2H_MAC_MCAST_ADD_RSP =
+ BFA_I2HM(BFI_ENET_H2I_MAC_MCAST_ADD_REQ),
+ BFI_ENET_I2H_MAC_MCAST_DEL_RSP =
+ BFA_I2HM(BFI_ENET_H2I_MAC_MCAST_DEL_REQ),
+ BFI_ENET_I2H_MAC_MCAST_FILTER_RSP =
+ BFA_I2HM(BFI_ENET_H2I_MAC_MCAST_FILTER_REQ),
+
+ BFI_ENET_I2H_RX_VLAN_SET_RSP =
+ BFA_I2HM(BFI_ENET_H2I_RX_VLAN_SET_REQ),
+
+ BFI_ENET_I2H_RX_VLAN_STRIP_ENABLE_RSP =
+ BFA_I2HM(BFI_ENET_H2I_RX_VLAN_STRIP_ENABLE_REQ),
+
+ /* Tx Responses */
+ BFI_ENET_I2H_TX_CFG_SET_RSP =
+ BFA_I2HM(BFI_ENET_H2I_TX_CFG_SET_REQ),
+ BFI_ENET_I2H_TX_CFG_CLR_RSP =
+ BFA_I2HM(BFI_ENET_H2I_TX_CFG_CLR_REQ),
+
+ /* Port Responses */
+ BFI_ENET_I2H_PORT_ADMIN_RSP =
+ BFA_I2HM(BFI_ENET_H2I_PORT_ADMIN_UP_REQ),
+
+ BFI_ENET_I2H_SET_PAUSE_RSP =
+ BFA_I2HM(BFI_ENET_H2I_SET_PAUSE_REQ),
+ BFI_ENET_I2H_DIAG_LOOPBACK_RSP =
+ BFA_I2HM(BFI_ENET_H2I_DIAG_LOOPBACK_REQ),
+
+ /* Attributes Response */
+ BFI_ENET_I2H_GET_ATTR_RSP =
+ BFA_I2HM(BFI_ENET_H2I_GET_ATTR_REQ),
+
+ /* Statistics Responses */
+ BFI_ENET_I2H_STATS_GET_RSP =
+ BFA_I2HM(BFI_ENET_H2I_STATS_GET_REQ),
+ BFI_ENET_I2H_STATS_CLR_RSP =
+ BFA_I2HM(BFI_ENET_H2I_STATS_CLR_REQ),
+
+ BFI_ENET_I2H_WOL_MAGIC_RSP =
+ BFA_I2HM(BFI_ENET_H2I_WOL_MAGIC_REQ),
+ BFI_ENET_I2H_WOL_FRAME_RSP =
+ BFA_I2HM(BFI_ENET_H2I_WOL_FRAME_REQ),
+
+ /* AENs */
+ BFI_ENET_I2H_LINK_DOWN_AEN = BFA_I2HM(BFI_ENET_H2I_MAX),
+ BFI_ENET_I2H_LINK_UP_AEN = BFA_I2HM(BFI_ENET_H2I_MAX + 1),
+
+ BFI_ENET_I2H_PORT_ENABLE_AEN = BFA_I2HM(BFI_ENET_H2I_MAX + 2),
+ BFI_ENET_I2H_PORT_DISABLE_AEN = BFA_I2HM(BFI_ENET_H2I_MAX + 3),
+
+ BFI_ENET_I2H_BW_UPDATE_AEN = BFA_I2HM(BFI_ENET_H2I_MAX + 4),
+};
+
+/**
+ * The following error codes can be returned by the enet commands
+ */
+enum bfi_enet_err {
+ BFI_ENET_CMD_OK = 0,
+ BFI_ENET_CMD_FAIL = 1,
+ BFI_ENET_CMD_DUP_ENTRY = 2, /* !< Duplicate entry in CAM */
+ BFI_ENET_CMD_CAM_FULL = 3, /* !< CAM is full */
+ BFI_ENET_CMD_NOT_OWNER = 4, /* !< Not permitted, b'cos not owner */
+ BFI_ENET_CMD_NOT_EXEC = 5, /* !< Was not sent to f/w at all */
+ BFI_ENET_CMD_WAITING = 6, /* !< Waiting for completion */
+ BFI_ENET_CMD_PORT_DISABLED = 7, /* !< port in disabled state */
+};
+
+/**
+ * Generic Request
+ *
+ * bfi_enet_req is used by:
+ * BFI_ENET_H2I_RX_CFG_CLR_REQ
+ * BFI_ENET_H2I_TX_CFG_CLR_REQ
+ */
+struct bfi_enet_req {
+ struct bfi_msgq_mhdr mh;
+};
+
+/**
+ * Enable/Disable Request
+ *
+ * bfi_enet_enable_req is used by:
+ * BFI_ENET_H2I_RSS_ENABLE_REQ (enet_id must be zero)
+ * BFI_ENET_H2I_RX_PROMISCUOUS_REQ (enet_id must be zero)
+ * BFI_ENET_H2I_RX_DEFAULT_REQ (enet_id must be zero)
+ * BFI_ENET_H2I_RX_MAC_MCAST_FILTER_REQ
+ * BFI_ENET_H2I_PORT_ADMIN_UP_REQ (enet_id must be zero)
+ */
+struct bfi_enet_enable_req {
+ struct bfi_msgq_mhdr mh;
+ u8 enable; /* 1 = enable; 0 = disable */
+ u8 rsvd[3];
+};
+
+/**
+ * Generic Response
+ */
+struct bfi_enet_rsp {
+ struct bfi_msgq_mhdr mh;
+ u8 error; /*!< if error see cmd_offset */
+ u8 rsvd;
+ u16 cmd_offset; /*!< offset to invalid parameter */
+};
+
+/**
+ * GLOBAL CONFIGURATION
+ */
+
+/**
+ * bfi_enet_attr_req is used by:
+ * BFI_ENET_H2I_GET_ATTR_REQ
+ */
+struct bfi_enet_attr_req {
+ struct bfi_msgq_mhdr mh;
+};
+
+/**
+ * bfi_enet_attr_rsp is used by:
+ * BFI_ENET_I2H_GET_ATTR_RSP
+ */
+struct bfi_enet_attr_rsp {
+ struct bfi_msgq_mhdr mh;
+ u8 error; /*!< if error see cmd_offset */
+ u8 rsvd;
+ u16 cmd_offset; /*!< offset to invalid parameter */
+ u32 max_cfg;
+ u32 max_ucmac;
+ u32 rit_size;
+};
+
+/**
+ * Tx Configuration
+ *
+ * bfi_enet_tx_cfg is used by:
+ * BFI_ENET_H2I_TX_CFG_SET_REQ
+ */
+enum bfi_enet_tx_vlan_mode {
+ BFI_ENET_TX_VLAN_NOP = 0,
+ BFI_ENET_TX_VLAN_INS = 1,
+ BFI_ENET_TX_VLAN_WI = 2,
+};
+
+struct bfi_enet_tx_cfg {
+ u8 vlan_mode; /*!< processing mode */
+ u8 rsvd;
+ u16 vlan_id;
+ u8 admit_tagged_frame;
+ u8 apply_vlan_filter;
+ u8 add_to_vswitch;
+ u8 rsvd1[1];
+};
+
+struct bfi_enet_tx_cfg_req {
+ struct bfi_msgq_mhdr mh;
+ u8 num_queues; /* # of Tx Queues */
+ u8 rsvd[3];
+
+ struct {
+ struct bfi_enet_txq q;
+ struct bfi_enet_ib ib;
+ } q_cfg[BFI_ENET_TXQ_PRIO_MAX];
+
+ struct bfi_enet_ib_cfg ib_cfg;
+
+ struct bfi_enet_tx_cfg tx_cfg;
+};
+
+struct bfi_enet_tx_cfg_rsp {
+ struct bfi_msgq_mhdr mh;
+ u8 error;
+ u8 hw_id; /* For debugging */
+ u8 rsvd[2];
+ struct {
+ u32 q_dbell; /* PCI base address offset */
+ u32 i_dbell; /* PCI base address offset */
+ u8 hw_qid; /* For debugging */
+ u8 rsvd[3];
+ } q_handles[BFI_ENET_TXQ_PRIO_MAX];
+};
+
+/**
+ * Rx Configuration
+ *
+ * bfi_enet_rx_cfg is used by:
+ * BFI_ENET_H2I_RX_CFG_SET_REQ
+ */
+enum bfi_enet_rxq_type {
+ BFI_ENET_RXQ_SINGLE = 1,
+ BFI_ENET_RXQ_LARGE_SMALL = 2,
+ BFI_ENET_RXQ_HDS = 3,
+ BFI_ENET_RXQ_HDS_OPT_BASED = 4,
+};
+
+enum bfi_enet_hds_type {
+ BFI_ENET_HDS_FORCED = 0x01,
+ BFI_ENET_HDS_IPV6_UDP = 0x02,
+ BFI_ENET_HDS_IPV6_TCP = 0x04,
+ BFI_ENET_HDS_IPV4_TCP = 0x08,
+ BFI_ENET_HDS_IPV4_UDP = 0x10,
+};
+
+struct bfi_enet_rx_cfg {
+ u8 rxq_type;
+ u8 rsvd[3];
+
+ struct {
+ u8 max_header_size;
+ u8 force_offset;
+ u8 type;
+ u8 rsvd1;
+ } hds;
+
+ u8 multi_buffer;
+ u8 strip_vlan;
+ u8 drop_untagged;
+ u8 rsvd2;
+};
+
+/*
+ * Multicast frames are received on the ql of q-set index zero.
+ * On the completion queue. RxQ ID = even is for large/data buffer queues
+ * and RxQ ID = odd is for small/header buffer queues.
+ */
+struct bfi_enet_rx_cfg_req {
+ struct bfi_msgq_mhdr mh;
+ u8 num_queue_sets; /* # of Rx Queue Sets */
+ u8 rsvd[3];
+
+ struct {
+ struct bfi_enet_rxq ql; /* large/data/single buffers */
+ struct bfi_enet_rxq qs; /* small/header buffers */
+ struct bfi_enet_cq cq;
+ struct bfi_enet_ib ib;
+ } q_cfg[BFI_ENET_RX_QSET_MAX];
+
+ struct bfi_enet_ib_cfg ib_cfg;
+
+ struct bfi_enet_rx_cfg rx_cfg;
+};
+
+struct bfi_enet_rx_cfg_rsp {
+ struct bfi_msgq_mhdr mh;
+ u8 error;
+ u8 hw_id; /* For debugging */
+ u8 rsvd[2];
+ struct {
+ u32 ql_dbell; /* PCI base address offset */
+ u32 qs_dbell; /* PCI base address offset */
+ u32 i_dbell; /* PCI base address offset */
+ u8 hw_lqid; /* For debugging */
+ u8 hw_sqid; /* For debugging */
+ u8 hw_cqid; /* For debugging */
+ u8 rsvd;
+ } q_handles[BFI_ENET_RX_QSET_MAX];
+};
+
+/**
+ * RIT
+ *
+ * bfi_enet_rit_req is used by:
+ * BFI_ENET_H2I_RIT_CFG_REQ
+ */
+struct bfi_enet_rit_req {
+ struct bfi_msgq_mhdr mh;
+ u16 size; /* number of table-entries used */
+ u8 rsvd[2];
+ u8 table[BFI_ENET_RSS_RIT_MAX];
+};
+
+/**
+ * RSS
+ *
+ * bfi_enet_rss_cfg_req is used by:
+ * BFI_ENET_H2I_RSS_CFG_REQ
+ */
+enum bfi_enet_rss_type {
+ BFI_ENET_RSS_IPV6 = 0x01,
+ BFI_ENET_RSS_IPV6_TCP = 0x02,
+ BFI_ENET_RSS_IPV4 = 0x04,
+ BFI_ENET_RSS_IPV4_TCP = 0x08
+};
+
+struct bfi_enet_rss_cfg {
+ u8 type;
+ u8 mask;
+ u8 rsvd[2];
+ u32 key[BFI_ENET_RSS_KEY_LEN];
+};
+
+struct bfi_enet_rss_cfg_req {
+ struct bfi_msgq_mhdr mh;
+ struct bfi_enet_rss_cfg cfg;
+};
+
+/**
+ * MAC Unicast
+ *
+ * bfi_enet_rx_vlan_req is used by:
+ * BFI_ENET_H2I_MAC_UCAST_SET_REQ
+ * BFI_ENET_H2I_MAC_UCAST_CLR_REQ
+ * BFI_ENET_H2I_MAC_UCAST_ADD_REQ
+ * BFI_ENET_H2I_MAC_UCAST_DEL_REQ
+ */
+struct bfi_enet_ucast_req {
+ struct bfi_msgq_mhdr mh;
+ mac_t mac_addr;
+ u8 rsvd[2];
+};
+
+/**
+ * MAC Unicast + VLAN
+ */
+struct bfi_enet_mac_n_vlan_req {
+ struct bfi_msgq_mhdr mh;
+ u16 vlan_id;
+ mac_t mac_addr;
+};
+
+/**
+ * MAC Multicast
+ *
+ * bfi_enet_mac_mfilter_add_req is used by:
+ * BFI_ENET_H2I_MAC_MCAST_ADD_REQ
+ */
+struct bfi_enet_mcast_add_req {
+ struct bfi_msgq_mhdr mh;
+ mac_t mac_addr;
+ u8 rsvd[2];
+};
+
+/**
+ * bfi_enet_mac_mfilter_add_rsp is used by:
+ * BFI_ENET_I2H_MAC_MCAST_ADD_RSP
+ */
+struct bfi_enet_mcast_add_rsp {
+ struct bfi_msgq_mhdr mh;
+ u8 error;
+ u8 rsvd;
+ u16 cmd_offset;
+ u16 handle;
+ u8 rsvd1[2];
+};
+
+/**
+ * bfi_enet_mac_mfilter_del_req is used by:
+ * BFI_ENET_H2I_MAC_MCAST_DEL_REQ
+ */
+struct bfi_enet_mcast_del_req {
+ struct bfi_msgq_mhdr mh;
+ u16 handle;
+ u8 rsvd[2];
+};
+
+/**
+ * VLAN
+ *
+ * bfi_enet_rx_vlan_req is used by:
+ * BFI_ENET_H2I_RX_VLAN_SET_REQ
+ */
+struct bfi_enet_rx_vlan_req {
+ struct bfi_msgq_mhdr mh;
+ u8 block_idx;
+ u8 rsvd[3];
+ u32 bit_mask[BFI_ENET_VLAN_WORDS_MAX];
+};
+
+/**
+ * PAUSE
+ *
+ * bfi_enet_set_pause_req is used by:
+ * BFI_ENET_H2I_SET_PAUSE_REQ
+ */
+struct bfi_enet_set_pause_req {
+ struct bfi_msgq_mhdr mh;
+ u8 rsvd[2];
+ u8 tx_pause; /* 1 = enable; 0 = disable */
+ u8 rx_pause; /* 1 = enable; 0 = disable */
+};
+
+/**
+ * DIAGNOSTICS
+ *
+ * bfi_enet_diag_lb_req is used by:
+ * BFI_ENET_H2I_DIAG_LOOPBACK
+ */
+struct bfi_enet_diag_lb_req {
+ struct bfi_msgq_mhdr mh;
+ u8 rsvd[2];
+ u8 mode; /* cable or Serdes */
+ u8 enable; /* 1 = enable; 0 = disable */
+};
+
+/**
+ * enum for Loopback opmodes
+ */
+enum {
+ BFI_ENET_DIAG_LB_OPMODE_EXT = 0,
+ BFI_ENET_DIAG_LB_OPMODE_CBL = 1,
+};
+
+/**
+ * STATISTICS
+ *
+ * bfi_enet_stats_req is used by:
+ * BFI_ENET_H2I_STATS_GET_REQ
+ * BFI_ENET_I2H_STATS_CLR_REQ
+ */
+struct bfi_enet_stats_req {
+ struct bfi_msgq_mhdr mh;
+ u16 stats_mask;
+ u8 rsvd[2];
+ u32 rx_enet_mask;
+ u32 tx_enet_mask;
+ union bfi_addr_u host_buffer;
+};
+
+/**
+ * defines for "stats_mask" above.
+ */
+#define BFI_ENET_STATS_MAC (1 << 0) /* !< MAC Statistics */
+#define BFI_ENET_STATS_BPC (1 << 1) /* !< Pause Stats from BPC */
+#define BFI_ENET_STATS_RAD (1 << 2) /* !< Rx Admission Statistics */
+#define BFI_ENET_STATS_RX_FC (1 << 3) /* !< Rx FC Stats from RxA */
+#define BFI_ENET_STATS_TX_FC (1 << 4) /* !< Tx FC Stats from TxA */
+
+#define BFI_ENET_STATS_ALL 0x1f
+
+/* TxF Frame Statistics */
+struct bfi_enet_stats_txf {
+ u64 ucast_octets;
+ u64 ucast;
+ u64 ucast_vlan;
+
+ u64 mcast_octets;
+ u64 mcast;
+ u64 mcast_vlan;
+
+ u64 bcast_octets;
+ u64 bcast;
+ u64 bcast_vlan;
+
+ u64 errors;
+ u64 filter_vlan; /* frames filtered due to VLAN */
+ u64 filter_mac_sa; /* frames filtered due to SA check */
+};
+
+/* RxF Frame Statistics */
+struct bfi_enet_stats_rxf {
+ u64 ucast_octets;
+ u64 ucast;
+ u64 ucast_vlan;
+
+ u64 mcast_octets;
+ u64 mcast;
+ u64 mcast_vlan;
+
+ u64 bcast_octets;
+ u64 bcast;
+ u64 bcast_vlan;
+ u64 frame_drops;
+};
+
+/* FC Tx Frame Statistics */
+struct bfi_enet_stats_fc_tx {
+ u64 txf_ucast_octets;
+ u64 txf_ucast;
+ u64 txf_ucast_vlan;
+
+ u64 txf_mcast_octets;
+ u64 txf_mcast;
+ u64 txf_mcast_vlan;
+
+ u64 txf_bcast_octets;
+ u64 txf_bcast;
+ u64 txf_bcast_vlan;
+
+ u64 txf_parity_errors;
+ u64 txf_timeout;
+ u64 txf_fid_parity_errors;
+};
+
+/* FC Rx Frame Statistics */
+struct bfi_enet_stats_fc_rx {
+ u64 rxf_ucast_octets;
+ u64 rxf_ucast;
+ u64 rxf_ucast_vlan;
+
+ u64 rxf_mcast_octets;
+ u64 rxf_mcast;
+ u64 rxf_mcast_vlan;
+
+ u64 rxf_bcast_octets;
+ u64 rxf_bcast;
+ u64 rxf_bcast_vlan;
+};
+
+/* RAD Frame Statistics */
+struct bfi_enet_stats_rad {
+ u64 rx_frames;
+ u64 rx_octets;
+ u64 rx_vlan_frames;
+
+ u64 rx_ucast;
+ u64 rx_ucast_octets;
+ u64 rx_ucast_vlan;
+
+ u64 rx_mcast;
+ u64 rx_mcast_octets;
+ u64 rx_mcast_vlan;
+
+ u64 rx_bcast;
+ u64 rx_bcast_octets;
+ u64 rx_bcast_vlan;
+
+ u64 rx_drops;
+};
+
+/* BPC Tx Registers */
+struct bfi_enet_stats_bpc {
+ /* transmit stats */
+ u64 tx_pause[8];
+ u64 tx_zero_pause[8]; /*!< Pause cancellation */
+ /*!<Pause initiation rather than retention */
+ u64 tx_first_pause[8];
+
+ /* receive stats */
+ u64 rx_pause[8];
+ u64 rx_zero_pause[8]; /*!< Pause cancellation */
+ /*!<Pause initiation rather than retention */
+ u64 rx_first_pause[8];
+};
+
+/* MAC Rx Statistics */
+struct bfi_enet_stats_mac {
+ 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 */
+ u64 frame_256_511; /* both rx and tx counter */
+ u64 frame_512_1023; /* both rx and tx counter */
+ u64 frame_1024_1518; /* both rx and tx counter */
+ u64 frame_1519_1522; /* both rx and tx counter */
+
+ /* receive stats */
+ u64 rx_bytes;
+ u64 rx_packets;
+ u64 rx_fcs_error;
+ u64 rx_multicast;
+ u64 rx_broadcast;
+ u64 rx_control_frames;
+ u64 rx_pause;
+ u64 rx_unknown_opcode;
+ u64 rx_alignment_error;
+ u64 rx_frame_length_error;
+ u64 rx_code_error;
+ u64 rx_carrier_sense_error;
+ u64 rx_undersize;
+ u64 rx_oversize;
+ u64 rx_fragments;
+ u64 rx_jabber;
+ u64 rx_drop;
+
+ /* transmit stats */
+ u64 tx_bytes;
+ u64 tx_packets;
+ u64 tx_multicast;
+ u64 tx_broadcast;
+ u64 tx_pause;
+ u64 tx_deferral;
+ u64 tx_excessive_deferral;
+ u64 tx_single_collision;
+ u64 tx_muliple_collision;
+ u64 tx_late_collision;
+ u64 tx_excessive_collision;
+ u64 tx_total_collision;
+ u64 tx_pause_honored;
+ u64 tx_drop;
+ u64 tx_jabber;
+ u64 tx_fcs_error;
+ u64 tx_control_frame;
+ u64 tx_oversize;
+ u64 tx_undersize;
+ u64 tx_fragments;
+};
+
+/**
+ * Complete statistics, DMAed from fw to host followed by
+ * BFI_ENET_I2H_STATS_GET_RSP
+ */
+struct bfi_enet_stats {
+ struct bfi_enet_stats_mac mac_stats;
+ struct bfi_enet_stats_bpc bpc_stats;
+ struct bfi_enet_stats_rad rad_stats;
+ struct bfi_enet_stats_rad rlb_stats;
+ struct bfi_enet_stats_fc_rx fc_rx_stats;
+ struct bfi_enet_stats_fc_tx fc_tx_stats;
+ struct bfi_enet_stats_rxf rxf_stats[BFI_ENET_CFG_MAX];
+ struct bfi_enet_stats_txf txf_stats[BFI_ENET_CFG_MAX];
+};
+
+#pragma pack()
+
+#endif /* __BFI_ENET_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bfi_reg.h b/drivers/net/ethernet/brocade/bna/bfi_reg.h
new file mode 100644
index 000000000000..efacff3ab51d
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/bfi_reg.h
@@ -0,0 +1,452 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/*
+ * bfi_reg.h ASIC register defines for all Brocade adapter ASICs
+ */
+
+#ifndef __BFI_REG_H__
+#define __BFI_REG_H__
+
+#define HOSTFN0_INT_STATUS 0x00014000 /* cb/ct */
+#define HOSTFN1_INT_STATUS 0x00014100 /* cb/ct */
+#define HOSTFN2_INT_STATUS 0x00014300 /* ct */
+#define HOSTFN3_INT_STATUS 0x00014400 /* ct */
+#define HOSTFN0_INT_MSK 0x00014004 /* cb/ct */
+#define HOSTFN1_INT_MSK 0x00014104 /* cb/ct */
+#define HOSTFN2_INT_MSK 0x00014304 /* ct */
+#define HOSTFN3_INT_MSK 0x00014404 /* ct */
+
+#define HOST_PAGE_NUM_FN0 0x00014008 /* cb/ct */
+#define HOST_PAGE_NUM_FN1 0x00014108 /* cb/ct */
+#define HOST_PAGE_NUM_FN2 0x00014308 /* ct */
+#define HOST_PAGE_NUM_FN3 0x00014408 /* ct */
+
+#define APP_PLL_LCLK_CTL_REG 0x00014204 /* cb/ct */
+#define __P_LCLK_PLL_LOCK 0x80000000
+#define __APP_PLL_LCLK_SRAM_USE_100MHZ 0x00100000
+#define __APP_PLL_LCLK_RESET_TIMER_MK 0x000e0000
+#define __APP_PLL_LCLK_RESET_TIMER_SH 17
+#define __APP_PLL_LCLK_RESET_TIMER(_v) ((_v) << __APP_PLL_LCLK_RESET_TIMER_SH)
+#define __APP_PLL_LCLK_LOGIC_SOFT_RESET 0x00010000
+#define __APP_PLL_LCLK_CNTLMT0_1_MK 0x0000c000
+#define __APP_PLL_LCLK_CNTLMT0_1_SH 14
+#define __APP_PLL_LCLK_CNTLMT0_1(_v) ((_v) << __APP_PLL_LCLK_CNTLMT0_1_SH)
+#define __APP_PLL_LCLK_JITLMT0_1_MK 0x00003000
+#define __APP_PLL_LCLK_JITLMT0_1_SH 12
+#define __APP_PLL_LCLK_JITLMT0_1(_v) ((_v) << __APP_PLL_LCLK_JITLMT0_1_SH)
+#define __APP_PLL_LCLK_HREF 0x00000800
+#define __APP_PLL_LCLK_HDIV 0x00000400
+#define __APP_PLL_LCLK_P0_1_MK 0x00000300
+#define __APP_PLL_LCLK_P0_1_SH 8
+#define __APP_PLL_LCLK_P0_1(_v) ((_v) << __APP_PLL_LCLK_P0_1_SH)
+#define __APP_PLL_LCLK_Z0_2_MK 0x000000e0
+#define __APP_PLL_LCLK_Z0_2_SH 5
+#define __APP_PLL_LCLK_Z0_2(_v) ((_v) << __APP_PLL_LCLK_Z0_2_SH)
+#define __APP_PLL_LCLK_RSEL200500 0x00000010
+#define __APP_PLL_LCLK_ENARST 0x00000008
+#define __APP_PLL_LCLK_BYPASS 0x00000004
+#define __APP_PLL_LCLK_LRESETN 0x00000002
+#define __APP_PLL_LCLK_ENABLE 0x00000001
+#define APP_PLL_SCLK_CTL_REG 0x00014208 /* cb/ct */
+#define __P_SCLK_PLL_LOCK 0x80000000
+#define __APP_PLL_SCLK_RESET_TIMER_MK 0x000e0000
+#define __APP_PLL_SCLK_RESET_TIMER_SH 17
+#define __APP_PLL_SCLK_RESET_TIMER(_v) ((_v) << __APP_PLL_SCLK_RESET_TIMER_SH)
+#define __APP_PLL_SCLK_LOGIC_SOFT_RESET 0x00010000
+#define __APP_PLL_SCLK_CNTLMT0_1_MK 0x0000c000
+#define __APP_PLL_SCLK_CNTLMT0_1_SH 14
+#define __APP_PLL_SCLK_CNTLMT0_1(_v) ((_v) << __APP_PLL_SCLK_CNTLMT0_1_SH)
+#define __APP_PLL_SCLK_JITLMT0_1_MK 0x00003000
+#define __APP_PLL_SCLK_JITLMT0_1_SH 12
+#define __APP_PLL_SCLK_JITLMT0_1(_v) ((_v) << __APP_PLL_SCLK_JITLMT0_1_SH)
+#define __APP_PLL_SCLK_HREF 0x00000800
+#define __APP_PLL_SCLK_HDIV 0x00000400
+#define __APP_PLL_SCLK_P0_1_MK 0x00000300
+#define __APP_PLL_SCLK_P0_1_SH 8
+#define __APP_PLL_SCLK_P0_1(_v) ((_v) << __APP_PLL_SCLK_P0_1_SH)
+#define __APP_PLL_SCLK_Z0_2_MK 0x000000e0
+#define __APP_PLL_SCLK_Z0_2_SH 5
+#define __APP_PLL_SCLK_Z0_2(_v) ((_v) << __APP_PLL_SCLK_Z0_2_SH)
+#define __APP_PLL_SCLK_RSEL200500 0x00000010
+#define __APP_PLL_SCLK_ENARST 0x00000008
+#define __APP_PLL_SCLK_BYPASS 0x00000004
+#define __APP_PLL_SCLK_LRESETN 0x00000002
+#define __APP_PLL_SCLK_ENABLE 0x00000001
+#define __ENABLE_MAC_AHB_1 0x00800000 /* ct */
+#define __ENABLE_MAC_AHB_0 0x00400000 /* ct */
+#define __ENABLE_MAC_1 0x00200000 /* ct */
+#define __ENABLE_MAC_0 0x00100000 /* ct */
+
+#define HOST_SEM0_REG 0x00014230 /* cb/ct */
+#define HOST_SEM1_REG 0x00014234 /* cb/ct */
+#define HOST_SEM2_REG 0x00014238 /* cb/ct */
+#define HOST_SEM3_REG 0x0001423c /* cb/ct */
+#define HOST_SEM4_REG 0x00014610 /* cb/ct */
+#define HOST_SEM5_REG 0x00014614 /* cb/ct */
+#define HOST_SEM6_REG 0x00014618 /* cb/ct */
+#define HOST_SEM7_REG 0x0001461c /* cb/ct */
+#define HOST_SEM0_INFO_REG 0x00014240 /* cb/ct */
+#define HOST_SEM1_INFO_REG 0x00014244 /* cb/ct */
+#define HOST_SEM2_INFO_REG 0x00014248 /* cb/ct */
+#define HOST_SEM3_INFO_REG 0x0001424c /* cb/ct */
+#define HOST_SEM4_INFO_REG 0x00014620 /* cb/ct */
+#define HOST_SEM5_INFO_REG 0x00014624 /* cb/ct */
+#define HOST_SEM6_INFO_REG 0x00014628 /* cb/ct */
+#define HOST_SEM7_INFO_REG 0x0001462c /* cb/ct */
+
+#define HOSTFN0_LPU0_CMD_STAT 0x00019000 /* cb/ct */
+#define HOSTFN0_LPU1_CMD_STAT 0x00019004 /* cb/ct */
+#define HOSTFN1_LPU0_CMD_STAT 0x00019010 /* cb/ct */
+#define HOSTFN1_LPU1_CMD_STAT 0x00019014 /* cb/ct */
+#define HOSTFN2_LPU0_CMD_STAT 0x00019150 /* ct */
+#define HOSTFN2_LPU1_CMD_STAT 0x00019154 /* ct */
+#define HOSTFN3_LPU0_CMD_STAT 0x00019160 /* ct */
+#define HOSTFN3_LPU1_CMD_STAT 0x00019164 /* ct */
+#define LPU0_HOSTFN0_CMD_STAT 0x00019008 /* cb/ct */
+#define LPU1_HOSTFN0_CMD_STAT 0x0001900c /* cb/ct */
+#define LPU0_HOSTFN1_CMD_STAT 0x00019018 /* cb/ct */
+#define LPU1_HOSTFN1_CMD_STAT 0x0001901c /* cb/ct */
+#define LPU0_HOSTFN2_CMD_STAT 0x00019158 /* ct */
+#define LPU1_HOSTFN2_CMD_STAT 0x0001915c /* ct */
+#define LPU0_HOSTFN3_CMD_STAT 0x00019168 /* ct */
+#define LPU1_HOSTFN3_CMD_STAT 0x0001916c /* ct */
+
+#define PSS_CTL_REG 0x00018800 /* cb/ct */
+#define __PSS_I2C_CLK_DIV_MK 0x007f0000
+#define __PSS_I2C_CLK_DIV_SH 16
+#define __PSS_I2C_CLK_DIV(_v) ((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE 0x00001000
+#define __PSS_LMEM_RESET 0x00000200
+#define __PSS_LMEM_INIT_EN 0x00000100
+#define __PSS_LPU1_RESET 0x00000002
+#define __PSS_LPU0_RESET 0x00000001
+#define PSS_ERR_STATUS_REG 0x00018810 /* cb/ct */
+#define ERR_SET_REG 0x00018818 /* cb/ct */
+#define PSS_GPIO_OUT_REG 0x000188c0 /* cb/ct */
+#define __PSS_GPIO_OUT_REG 0x00000fff
+#define PSS_GPIO_OE_REG 0x000188c8 /* cb/ct */
+#define __PSS_GPIO_OE_REG 0x000000ff
+
+#define HOSTFN0_LPU_MBOX0_0 0x00019200 /* cb/ct */
+#define HOSTFN1_LPU_MBOX0_8 0x00019260 /* cb/ct */
+#define LPU_HOSTFN0_MBOX0_0 0x00019280 /* cb/ct */
+#define LPU_HOSTFN1_MBOX0_8 0x000192e0 /* cb/ct */
+#define HOSTFN2_LPU_MBOX0_0 0x00019400 /* ct */
+#define HOSTFN3_LPU_MBOX0_8 0x00019460 /* ct */
+#define LPU_HOSTFN2_MBOX0_0 0x00019480 /* ct */
+#define LPU_HOSTFN3_MBOX0_8 0x000194e0 /* ct */
+
+#define HOST_MSIX_ERR_INDEX_FN0 0x0001400c /* ct */
+#define HOST_MSIX_ERR_INDEX_FN1 0x0001410c /* ct */
+#define HOST_MSIX_ERR_INDEX_FN2 0x0001430c /* ct */
+#define HOST_MSIX_ERR_INDEX_FN3 0x0001440c /* ct */
+
+#define MBIST_CTL_REG 0x00014220 /* ct */
+#define __EDRAM_BISTR_START 0x00000004
+#define MBIST_STAT_REG 0x00014224 /* ct */
+#define ETH_MAC_SER_REG 0x00014288 /* ct */
+#define __APP_EMS_CKBUFAMPIN 0x00000020
+#define __APP_EMS_REFCLKSEL 0x00000010
+#define __APP_EMS_CMLCKSEL 0x00000008
+#define __APP_EMS_REFCKBUFEN2 0x00000004
+#define __APP_EMS_REFCKBUFEN1 0x00000002
+#define __APP_EMS_CHANNEL_SEL 0x00000001
+#define FNC_PERS_REG 0x00014604 /* ct */
+#define __F3_FUNCTION_ACTIVE 0x80000000
+#define __F3_FUNCTION_MODE 0x40000000
+#define __F3_PORT_MAP_MK 0x30000000
+#define __F3_PORT_MAP_SH 28
+#define __F3_PORT_MAP(_v) ((_v) << __F3_PORT_MAP_SH)
+#define __F3_VM_MODE 0x08000000
+#define __F3_INTX_STATUS_MK 0x07000000
+#define __F3_INTX_STATUS_SH 24
+#define __F3_INTX_STATUS(_v) ((_v) << __F3_INTX_STATUS_SH)
+#define __F2_FUNCTION_ACTIVE 0x00800000
+#define __F2_FUNCTION_MODE 0x00400000
+#define __F2_PORT_MAP_MK 0x00300000
+#define __F2_PORT_MAP_SH 20
+#define __F2_PORT_MAP(_v) ((_v) << __F2_PORT_MAP_SH)
+#define __F2_VM_MODE 0x00080000
+#define __F2_INTX_STATUS_MK 0x00070000
+#define __F2_INTX_STATUS_SH 16
+#define __F2_INTX_STATUS(_v) ((_v) << __F2_INTX_STATUS_SH)
+#define __F1_FUNCTION_ACTIVE 0x00008000
+#define __F1_FUNCTION_MODE 0x00004000
+#define __F1_PORT_MAP_MK 0x00003000
+#define __F1_PORT_MAP_SH 12
+#define __F1_PORT_MAP(_v) ((_v) << __F1_PORT_MAP_SH)
+#define __F1_VM_MODE 0x00000800
+#define __F1_INTX_STATUS_MK 0x00000700
+#define __F1_INTX_STATUS_SH 8
+#define __F1_INTX_STATUS(_v) ((_v) << __F1_INTX_STATUS_SH)
+#define __F0_FUNCTION_ACTIVE 0x00000080
+#define __F0_FUNCTION_MODE 0x00000040
+#define __F0_PORT_MAP_MK 0x00000030
+#define __F0_PORT_MAP_SH 4
+#define __F0_PORT_MAP(_v) ((_v) << __F0_PORT_MAP_SH)
+#define __F0_VM_MODE 0x00000008
+#define __F0_INTX_STATUS 0x00000007
+enum {
+ __F0_INTX_STATUS_MSIX = 0x0,
+ __F0_INTX_STATUS_INTA = 0x1,
+ __F0_INTX_STATUS_INTB = 0x2,
+ __F0_INTX_STATUS_INTC = 0x3,
+ __F0_INTX_STATUS_INTD = 0x4,
+};
+
+#define OP_MODE 0x0001460c
+#define __APP_ETH_CLK_LOWSPEED 0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED 0x00000002
+#define __GLOBAL_FCOE_MODE 0x00000001
+#define FW_INIT_HALT_P0 0x000191ac
+#define __FW_INIT_HALT_P 0x00000001
+#define FW_INIT_HALT_P1 0x000191bc
+#define PMM_1T_RESET_REG_P0 0x0002381c
+#define __PMM_1T_RESET_P 0x00000001
+#define PMM_1T_RESET_REG_P1 0x00023c1c
+
+/**
+ * Brocade 1860 Adapter specific defines
+ */
+#define CT2_PCI_CPQ_BASE 0x00030000
+#define CT2_PCI_APP_BASE 0x00030100
+#define CT2_PCI_ETH_BASE 0x00030400
+
+/*
+ * APP block registers
+ */
+#define CT2_HOSTFN_INT_STATUS (CT2_PCI_APP_BASE + 0x00)
+#define CT2_HOSTFN_INTR_MASK (CT2_PCI_APP_BASE + 0x04)
+#define CT2_HOSTFN_PERSONALITY0 (CT2_PCI_APP_BASE + 0x08)
+#define __PME_STATUS_ 0x00200000
+#define __PF_VF_BAR_SIZE_MODE__MK 0x00180000
+#define __PF_VF_BAR_SIZE_MODE__SH 19
+#define __PF_VF_BAR_SIZE_MODE_(_v) ((_v) << __PF_VF_BAR_SIZE_MODE__SH)
+#define __FC_LL_PORT_MAP__MK 0x00060000
+#define __FC_LL_PORT_MAP__SH 17
+#define __FC_LL_PORT_MAP_(_v) ((_v) << __FC_LL_PORT_MAP__SH)
+#define __PF_VF_ACTIVE_ 0x00010000
+#define __PF_VF_CFG_RDY_ 0x00008000
+#define __PF_VF_ENABLE_ 0x00004000
+#define __PF_DRIVER_ACTIVE_ 0x00002000
+#define __PF_PME_SEND_ENABLE_ 0x00001000
+#define __PF_EXROM_OFFSET__MK 0x00000ff0
+#define __PF_EXROM_OFFSET__SH 4
+#define __PF_EXROM_OFFSET_(_v) ((_v) << __PF_EXROM_OFFSET__SH)
+#define __FC_LL_MODE_ 0x00000008
+#define __PF_INTX_PIN_ 0x00000007
+#define CT2_HOSTFN_PERSONALITY1 (CT2_PCI_APP_BASE + 0x0C)
+#define __PF_NUM_QUEUES1__MK 0xff000000
+#define __PF_NUM_QUEUES1__SH 24
+#define __PF_NUM_QUEUES1_(_v) ((_v) << __PF_NUM_QUEUES1__SH)
+#define __PF_VF_QUE_OFFSET1__MK 0x00ff0000
+#define __PF_VF_QUE_OFFSET1__SH 16
+#define __PF_VF_QUE_OFFSET1_(_v) ((_v) << __PF_VF_QUE_OFFSET1__SH)
+#define __PF_VF_NUM_QUEUES__MK 0x0000ff00
+#define __PF_VF_NUM_QUEUES__SH 8
+#define __PF_VF_NUM_QUEUES_(_v) ((_v) << __PF_VF_NUM_QUEUES__SH)
+#define __PF_VF_QUE_OFFSET_ 0x000000ff
+#define CT2_HOSTFN_PAGE_NUM (CT2_PCI_APP_BASE + 0x18)
+#define CT2_HOSTFN_MSIX_VT_INDEX_MBOX_ERR (CT2_PCI_APP_BASE + 0x38)
+
+/*
+ * Brocade 1860 adapter CPQ block registers
+ */
+#define CT2_HOSTFN_LPU0_MBOX0 (CT2_PCI_CPQ_BASE + 0x00)
+#define CT2_HOSTFN_LPU1_MBOX0 (CT2_PCI_CPQ_BASE + 0x20)
+#define CT2_LPU0_HOSTFN_MBOX0 (CT2_PCI_CPQ_BASE + 0x40)
+#define CT2_LPU1_HOSTFN_MBOX0 (CT2_PCI_CPQ_BASE + 0x60)
+#define CT2_HOSTFN_LPU0_CMD_STAT (CT2_PCI_CPQ_BASE + 0x80)
+#define CT2_HOSTFN_LPU1_CMD_STAT (CT2_PCI_CPQ_BASE + 0x84)
+#define CT2_LPU0_HOSTFN_CMD_STAT (CT2_PCI_CPQ_BASE + 0x88)
+#define CT2_LPU1_HOSTFN_CMD_STAT (CT2_PCI_CPQ_BASE + 0x8c)
+#define CT2_HOSTFN_LPU0_READ_STAT (CT2_PCI_CPQ_BASE + 0x90)
+#define CT2_HOSTFN_LPU1_READ_STAT (CT2_PCI_CPQ_BASE + 0x94)
+#define CT2_LPU0_HOSTFN_MBOX0_MSK (CT2_PCI_CPQ_BASE + 0x98)
+#define CT2_LPU1_HOSTFN_MBOX0_MSK (CT2_PCI_CPQ_BASE + 0x9C)
+#define CT2_HOST_SEM0_REG 0x000148f0
+#define CT2_HOST_SEM1_REG 0x000148f4
+#define CT2_HOST_SEM2_REG 0x000148f8
+#define CT2_HOST_SEM3_REG 0x000148fc
+#define CT2_HOST_SEM4_REG 0x00014900
+#define CT2_HOST_SEM5_REG 0x00014904
+#define CT2_HOST_SEM6_REG 0x00014908
+#define CT2_HOST_SEM7_REG 0x0001490c
+#define CT2_HOST_SEM0_INFO_REG 0x000148b0
+#define CT2_HOST_SEM1_INFO_REG 0x000148b4
+#define CT2_HOST_SEM2_INFO_REG 0x000148b8
+#define CT2_HOST_SEM3_INFO_REG 0x000148bc
+#define CT2_HOST_SEM4_INFO_REG 0x000148c0
+#define CT2_HOST_SEM5_INFO_REG 0x000148c4
+#define CT2_HOST_SEM6_INFO_REG 0x000148c8
+#define CT2_HOST_SEM7_INFO_REG 0x000148cc
+
+#define CT2_APP_PLL_LCLK_CTL_REG 0x00014808
+#define __APP_LPUCLK_HALFSPEED 0x40000000
+#define __APP_PLL_LCLK_LOAD 0x20000000
+#define __APP_PLL_LCLK_FBCNT_MK 0x1fe00000
+#define __APP_PLL_LCLK_FBCNT_SH 21
+#define __APP_PLL_LCLK_FBCNT(_v) ((_v) << __APP_PLL_SCLK_FBCNT_SH)
+enum {
+ __APP_PLL_LCLK_FBCNT_425_MHZ = 6,
+ __APP_PLL_LCLK_FBCNT_468_MHZ = 4,
+};
+#define __APP_PLL_LCLK_EXTFB 0x00000800
+#define __APP_PLL_LCLK_ENOUTS 0x00000400
+#define __APP_PLL_LCLK_RATE 0x00000010
+#define CT2_APP_PLL_SCLK_CTL_REG 0x0001480c
+#define __P_SCLK_PLL_LOCK 0x80000000
+#define __APP_PLL_SCLK_REFCLK_SEL 0x40000000
+#define __APP_PLL_SCLK_CLK_DIV2 0x20000000
+#define __APP_PLL_SCLK_LOAD 0x10000000
+#define __APP_PLL_SCLK_FBCNT_MK 0x0ff00000
+#define __APP_PLL_SCLK_FBCNT_SH 20
+#define __APP_PLL_SCLK_FBCNT(_v) ((_v) << __APP_PLL_SCLK_FBCNT_SH)
+enum {
+ __APP_PLL_SCLK_FBCNT_NORM = 6,
+ __APP_PLL_SCLK_FBCNT_10G_FC = 10,
+};
+#define __APP_PLL_SCLK_EXTFB 0x00000800
+#define __APP_PLL_SCLK_ENOUTS 0x00000400
+#define __APP_PLL_SCLK_RATE 0x00000010
+#define CT2_PCIE_MISC_REG 0x00014804
+#define __ETH_CLK_ENABLE_PORT1 0x00000010
+#define CT2_CHIP_MISC_PRG 0x000148a4
+#define __ETH_CLK_ENABLE_PORT0 0x00004000
+#define __APP_LPU_SPEED 0x00000002
+#define CT2_MBIST_STAT_REG 0x00014818
+#define CT2_MBIST_CTL_REG 0x0001481c
+#define CT2_PMM_1T_CONTROL_REG_P0 0x0002381c
+#define __PMM_1T_PNDB_P 0x00000002
+#define CT2_PMM_1T_CONTROL_REG_P1 0x00023c1c
+#define CT2_WGN_STATUS 0x00014990
+#define __A2T_AHB_LOAD 0x00000800
+#define __WGN_READY 0x00000400
+#define __GLBL_PF_VF_CFG_RDY 0x00000200
+#define CT2_NFC_CSR_SET_REG 0x00027424
+#define __HALT_NFC_CONTROLLER 0x00000002
+#define __NFC_CONTROLLER_HALTED 0x00001000
+
+#define CT2_CSI_MAC0_CONTROL_REG 0x000270d0
+#define __CSI_MAC_RESET 0x00000010
+#define __CSI_MAC_AHB_RESET 0x00000008
+#define CT2_CSI_MAC1_CONTROL_REG 0x000270d4
+#define CT2_CSI_MAC_CONTROL_REG(__n) \
+ (CT2_CSI_MAC0_CONTROL_REG + \
+ (__n) * (CT2_CSI_MAC1_CONTROL_REG - CT2_CSI_MAC0_CONTROL_REG))
+
+/*
+ * Name semaphore registers based on usage
+ */
+#define BFA_IOC0_HBEAT_REG HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG
+#define BFA_IOC_FAIL_SYNC HOST_SEM5_INFO_REG
+
+/*
+ * CT2 semaphore register locations changed
+ */
+#define CT2_BFA_IOC0_HBEAT_REG CT2_HOST_SEM0_INFO_REG
+#define CT2_BFA_IOC0_STATE_REG CT2_HOST_SEM1_INFO_REG
+#define CT2_BFA_IOC1_HBEAT_REG CT2_HOST_SEM2_INFO_REG
+#define CT2_BFA_IOC1_STATE_REG CT2_HOST_SEM3_INFO_REG
+#define CT2_BFA_FW_USE_COUNT CT2_HOST_SEM4_INFO_REG
+#define CT2_BFA_IOC_FAIL_SYNC CT2_HOST_SEM5_INFO_REG
+
+#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0 0x00000001U
+#define __HFN_INT_CPE_Q1 0x00000002U
+#define __HFN_INT_CPE_Q2 0x00000004U
+#define __HFN_INT_CPE_Q3 0x00000008U
+#define __HFN_INT_CPE_Q4 0x00000010U
+#define __HFN_INT_CPE_Q5 0x00000020U
+#define __HFN_INT_CPE_Q6 0x00000040U
+#define __HFN_INT_CPE_Q7 0x00000080U
+#define __HFN_INT_RME_Q0 0x00000100U
+#define __HFN_INT_RME_Q1 0x00000200U
+#define __HFN_INT_RME_Q2 0x00000400U
+#define __HFN_INT_RME_Q3 0x00000800U
+#define __HFN_INT_RME_Q4 0x00001000U
+#define __HFN_INT_RME_Q5 0x00002000U
+#define __HFN_INT_RME_Q6 0x00004000U
+#define __HFN_INT_RME_Q7 0x00008000U
+#define __HFN_INT_ERR_EMC 0x00010000U
+#define __HFN_INT_ERR_LPU0 0x00020000U
+#define __HFN_INT_ERR_LPU1 0x00040000U
+#define __HFN_INT_ERR_PSS 0x00080000U
+#define __HFN_INT_MBOX_LPU0 0x00100000U
+#define __HFN_INT_MBOX_LPU1 0x00200000U
+#define __HFN_INT_MBOX1_LPU0 0x00400000U
+#define __HFN_INT_MBOX1_LPU1 0x00800000U
+#define __HFN_INT_LL_HALT 0x01000000U
+#define __HFN_INT_CPE_MASK 0x000000ffU
+#define __HFN_INT_RME_MASK 0x0000ff00U
+#define __HFN_INT_ERR_MASK \
+ (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | __HFN_INT_ERR_LPU1 | \
+ __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT)
+#define __HFN_INT_FN0_MASK \
+ (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | __HFN_INT_CPE_Q2 | \
+ __HFN_INT_CPE_Q3 | __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | \
+ __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | __HFN_INT_MBOX_LPU0)
+#define __HFN_INT_FN1_MASK \
+ (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | __HFN_INT_CPE_Q6 | \
+ __HFN_INT_CPE_Q7 | __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | \
+ __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | __HFN_INT_MBOX_LPU1)
+
+/*
+ * Host interrupt status defines for 1860
+ */
+#define __HFN_INT_MBOX_LPU0_CT2 0x00010000U
+#define __HFN_INT_MBOX_LPU1_CT2 0x00020000U
+#define __HFN_INT_ERR_PSS_CT2 0x00040000U
+#define __HFN_INT_ERR_LPU0_CT2 0x00080000U
+#define __HFN_INT_ERR_LPU1_CT2 0x00100000U
+#define __HFN_INT_CPQ_HALT_CT2 0x00200000U
+#define __HFN_INT_ERR_WGN_CT2 0x00400000U
+#define __HFN_INT_ERR_LEHRX_CT2 0x00800000U
+#define __HFN_INT_ERR_LEHTX_CT2 0x01000000U
+#define __HFN_INT_ERR_MASK_CT2 \
+ (__HFN_INT_ERR_PSS_CT2 | __HFN_INT_ERR_LPU0_CT2 | \
+ __HFN_INT_ERR_LPU1_CT2 | __HFN_INT_CPQ_HALT_CT2 | \
+ __HFN_INT_ERR_WGN_CT2 | __HFN_INT_ERR_LEHRX_CT2 | \
+ __HFN_INT_ERR_LEHTX_CT2)
+#define __HFN_INT_FN0_MASK_CT2 \
+ (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | __HFN_INT_CPE_Q2 | \
+ __HFN_INT_CPE_Q3 | __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | \
+ __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | __HFN_INT_MBOX_LPU0_CT2)
+#define __HFN_INT_FN1_MASK_CT2 \
+ (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | __HFN_INT_CPE_Q6 | \
+ __HFN_INT_CPE_Q7 | __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | \
+ __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | __HFN_INT_MBOX_LPU1_CT2)
+
+/*
+ * asic memory map.
+ */
+#define PSS_SMEM_PAGE_START 0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma) ((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma) ((_ma) & 0x7fff)
+
+#endif /* __BFI_REG_H__ */
diff --git a/drivers/net/bna/bna.h b/drivers/net/ethernet/brocade/bna/bna.h
index 21e9155d6e56..4d7a5de08e12 100644
--- a/drivers/net/bna/bna.h
+++ b/drivers/net/ethernet/brocade/bna/bna.h
@@ -10,13 +10,17 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
+/*
+ * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
#ifndef __BNA_H__
#define __BNA_H__
-#include "bfa_cs.h"
+#include "bfa_defs.h"
#include "bfa_ioc.h"
-#include "cna.h"
-#include "bfi_ll.h"
+#include "bfi_enet.h"
#include "bna_types.h"
extern const u32 bna_napi_dim_vector[][BNA_BIAS_T_MAX];
@@ -32,15 +36,7 @@ extern const u32 bna_napi_dim_vector[][BNA_BIAS_T_MAX];
/* Log string size */
#define BNA_MESSAGE_SIZE 256
-/* MBOX API for PORT, TX, RX */
-#define bna_mbox_qe_fill(_qe, _cmd, _cmd_len, _cbfn, _cbarg) \
-do { \
- memcpy(&((_qe)->cmd.msg[0]), (_cmd), (_cmd_len)); \
- (_qe)->cbfn = (_cbfn); \
- (_qe)->cbarg = (_cbarg); \
-} while (0)
-
-#define bna_is_small_rxq(rcb) ((rcb)->id == 1)
+#define bna_is_small_rxq(_id) ((_id) & 0x1)
#define BNA_MAC_IS_EQUAL(_mac1, _mac2) \
(!memcmp((_mac1), (_mac2), sizeof(mac_t)))
@@ -177,32 +173,6 @@ do { \
#define BNA_Q_IN_USE_COUNT(_q_ptr) \
(BNA_QE_IN_USE_CNT(&(_q_ptr)->q, (_q_ptr)->q.q_depth))
-/* These macros build the data portion of the TxQ/RxQ doorbell */
-#define BNA_DOORBELL_Q_PRD_IDX(_pi) (0x80000000 | (_pi))
-#define BNA_DOORBELL_Q_STOP (0x40000000)
-
-/* These macros build the data portion of the IB doorbell */
-#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
- (0x80000000 | ((_timeout) << 16) | (_events))
-#define BNA_DOORBELL_IB_INT_DISABLE (0x40000000)
-
-/* Set the coalescing timer for the given ib */
-#define bna_ib_coalescing_timer_set(_i_dbell, _cls_timer) \
- ((_i_dbell)->doorbell_ack = BNA_DOORBELL_IB_INT_ACK((_cls_timer), 0));
-
-/* Acks 'events' # of events for a given ib */
-#define bna_ib_ack(_i_dbell, _events) \
- (writel(((_i_dbell)->doorbell_ack | (_events)), \
- (_i_dbell)->doorbell_addr));
-
-#define bna_txq_prod_indx_doorbell(_tcb) \
- (writel(BNA_DOORBELL_Q_PRD_IDX((_tcb)->producer_index), \
- (_tcb)->q_dbell));
-
-#define bna_rxq_prod_indx_doorbell(_rcb) \
- (writel(BNA_DOORBELL_Q_PRD_IDX((_rcb)->producer_index), \
- (_rcb)->q_dbell));
-
#define BNA_LARGE_PKT_SIZE 1000
#define BNA_UPDATE_PKT_CNT(_pkt, _len) \
@@ -214,38 +184,59 @@ do { \
} \
} while (0)
-#define call_rxf_stop_cbfn(rxf, status) \
+#define call_rxf_stop_cbfn(rxf) \
+do { \
if ((rxf)->stop_cbfn) { \
- (*(rxf)->stop_cbfn)((rxf)->stop_cbarg, (status)); \
+ void (*cbfn)(struct bna_rx *); \
+ struct bna_rx *cbarg; \
+ cbfn = (rxf)->stop_cbfn; \
+ cbarg = (rxf)->stop_cbarg; \
(rxf)->stop_cbfn = NULL; \
(rxf)->stop_cbarg = NULL; \
- }
+ cbfn(cbarg); \
+ } \
+} while (0)
-#define call_rxf_start_cbfn(rxf, status) \
+#define call_rxf_start_cbfn(rxf) \
+do { \
if ((rxf)->start_cbfn) { \
- (*(rxf)->start_cbfn)((rxf)->start_cbarg, (status)); \
+ void (*cbfn)(struct bna_rx *); \
+ struct bna_rx *cbarg; \
+ cbfn = (rxf)->start_cbfn; \
+ cbarg = (rxf)->start_cbarg; \
(rxf)->start_cbfn = NULL; \
(rxf)->start_cbarg = NULL; \
- }
+ cbfn(cbarg); \
+ } \
+} while (0)
-#define call_rxf_cam_fltr_cbfn(rxf, status) \
+#define call_rxf_cam_fltr_cbfn(rxf) \
+do { \
if ((rxf)->cam_fltr_cbfn) { \
- (*(rxf)->cam_fltr_cbfn)((rxf)->cam_fltr_cbarg, rxf->rx, \
- (status)); \
+ void (*cbfn)(struct bnad *, struct bna_rx *); \
+ struct bnad *cbarg; \
+ cbfn = (rxf)->cam_fltr_cbfn; \
+ cbarg = (rxf)->cam_fltr_cbarg; \
(rxf)->cam_fltr_cbfn = NULL; \
(rxf)->cam_fltr_cbarg = NULL; \
- }
+ cbfn(cbarg, rxf->rx); \
+ } \
+} while (0)
-#define call_rxf_pause_cbfn(rxf, status) \
+#define call_rxf_pause_cbfn(rxf) \
+do { \
if ((rxf)->oper_state_cbfn) { \
- (*(rxf)->oper_state_cbfn)((rxf)->oper_state_cbarg, rxf->rx,\
- (status)); \
- (rxf)->rxf_flags &= ~BNA_RXF_FL_OPERSTATE_CHANGED; \
+ void (*cbfn)(struct bnad *, struct bna_rx *); \
+ struct bnad *cbarg; \
+ cbfn = (rxf)->oper_state_cbfn; \
+ cbarg = (rxf)->oper_state_cbarg; \
(rxf)->oper_state_cbfn = NULL; \
(rxf)->oper_state_cbarg = NULL; \
- }
+ cbfn(cbarg, rxf->rx); \
+ } \
+} while (0)
-#define call_rxf_resume_cbfn(rxf, status) call_rxf_pause_cbfn(rxf, status)
+#define call_rxf_resume_cbfn(rxf) call_rxf_pause_cbfn(rxf)
#define is_xxx_enable(mode, bitmask, xxx) ((bitmask & xxx) && (mode & xxx))
@@ -331,6 +322,61 @@ do { \
} \
} while (0)
+#define bna_tx_rid_mask(_bna) ((_bna)->tx_mod.rid_mask)
+
+#define bna_rx_rid_mask(_bna) ((_bna)->rx_mod.rid_mask)
+
+#define bna_tx_from_rid(_bna, _rid, _tx) \
+do { \
+ struct bna_tx_mod *__tx_mod = &(_bna)->tx_mod; \
+ struct bna_tx *__tx; \
+ struct list_head *qe; \
+ _tx = NULL; \
+ list_for_each(qe, &__tx_mod->tx_active_q) { \
+ __tx = (struct bna_tx *)qe; \
+ if (__tx->rid == (_rid)) { \
+ (_tx) = __tx; \
+ break; \
+ } \
+ } \
+} while (0)
+
+#define bna_rx_from_rid(_bna, _rid, _rx) \
+do { \
+ struct bna_rx_mod *__rx_mod = &(_bna)->rx_mod; \
+ struct bna_rx *__rx; \
+ struct list_head *qe; \
+ _rx = NULL; \
+ list_for_each(qe, &__rx_mod->rx_active_q) { \
+ __rx = (struct bna_rx *)qe; \
+ if (__rx->rid == (_rid)) { \
+ (_rx) = __rx; \
+ break; \
+ } \
+ } \
+} while (0)
+
+/**
+ *
+ * Inline functions
+ *
+ */
+
+static inline struct bna_mac *bna_mac_find(struct list_head *q, u8 *addr)
+{
+ struct bna_mac *mac = NULL;
+ struct list_head *qe;
+ list_for_each(qe, q) {
+ if (BNA_MAC_IS_EQUAL(((struct bna_mac *)qe)->addr, addr)) {
+ mac = (struct bna_mac *)qe;
+ break;
+ }
+ }
+ return mac;
+}
+
+#define bna_attr(_bna) (&(_bna)->ioceth.attr)
+
/**
*
* Function prototypes
@@ -341,17 +387,20 @@ do { \
* BNA
*/
+/* FW response handlers */
+void bna_bfi_stats_clr_rsp(struct bna *bna, struct bfi_msgq_mhdr *msghdr);
+
/* APIs for BNAD */
void bna_res_req(struct bna_res_info *res_info);
+void bna_mod_res_req(struct bna *bna, struct bna_res_info *res_info);
void bna_init(struct bna *bna, struct bnad *bnad,
struct bfa_pcidev *pcidev,
struct bna_res_info *res_info);
+void bna_mod_init(struct bna *bna, struct bna_res_info *res_info);
void bna_uninit(struct bna *bna);
-void bna_stats_get(struct bna *bna);
-void bna_get_perm_mac(struct bna *bna, u8 *mac);
-
-/* APIs for Rx */
-int bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size);
+int bna_num_txq_set(struct bna *bna, int num_txq);
+int bna_num_rxp_set(struct bna *bna, int num_rxp);
+void bna_hw_stats_get(struct bna *bna);
/* APIs for RxF */
struct bna_mac *bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod);
@@ -360,127 +409,78 @@ void bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod,
struct bna_mac *bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod);
void bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod,
struct bna_mac *mac);
-struct bna_rit_segment *
-bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size);
-void bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod,
- struct bna_rit_segment *seg);
-
-/**
- * DEVICE
- */
-
-/* APIs for BNAD */
-void bna_device_enable(struct bna_device *device);
-void bna_device_disable(struct bna_device *device,
- enum bna_cleanup_type type);
+struct bna_mcam_handle *bna_mcam_mod_handle_get(struct bna_mcam_mod *mod);
+void bna_mcam_mod_handle_put(struct bna_mcam_mod *mcam_mod,
+ struct bna_mcam_handle *handle);
/**
* MBOX
*/
-/* APIs for PORT, TX, RX */
-void bna_mbox_handler(struct bna *bna, u32 intr_status);
-void bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe);
-
-/**
- * PORT
- */
-
-/* API for RX */
-int bna_port_mtu_get(struct bna_port *port);
-void bna_llport_rx_started(struct bna_llport *llport);
-void bna_llport_rx_stopped(struct bna_llport *llport);
-
/* API for BNAD */
-void bna_port_enable(struct bna_port *port);
-void bna_port_disable(struct bna_port *port, enum bna_cleanup_type type,
- void (*cbfn)(void *, enum bna_cb_status));
-void bna_port_pause_config(struct bna_port *port,
- struct bna_pause_config *pause_config,
- void (*cbfn)(struct bnad *, enum bna_cb_status));
-void bna_port_mtu_set(struct bna_port *port, int mtu,
- void (*cbfn)(struct bnad *, enum bna_cb_status));
-void bna_port_mac_get(struct bna_port *port, mac_t *mac);
-
-/* Callbacks for TX, RX */
-void bna_port_cb_tx_stopped(struct bna_port *port,
- enum bna_cb_status status);
-void bna_port_cb_rx_stopped(struct bna_port *port,
- enum bna_cb_status status);
+void bna_mbox_handler(struct bna *bna, u32 intr_status);
/**
- * IB
+ * ETHPORT
*/
-/* APIs for BNA */
-void bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna,
- struct bna_res_info *res_info);
-void bna_ib_mod_uninit(struct bna_ib_mod *ib_mod);
+/* Callbacks for RX */
+void bna_ethport_cb_rx_started(struct bna_ethport *ethport);
+void bna_ethport_cb_rx_stopped(struct bna_ethport *ethport);
/**
* TX MODULE AND TX
*/
+/* FW response handelrs */
+void bna_bfi_tx_enet_start_rsp(struct bna_tx *tx,
+ struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_tx_enet_stop_rsp(struct bna_tx *tx,
+ struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_bw_update_aen(struct bna_tx_mod *tx_mod);
/* APIs for BNA */
void bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
struct bna_res_info *res_info);
void bna_tx_mod_uninit(struct bna_tx_mod *tx_mod);
-int bna_tx_state_get(struct bna_tx *tx);
-/* APIs for PORT */
+/* APIs for ENET */
void bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type);
void bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type);
void bna_tx_mod_fail(struct bna_tx_mod *tx_mod);
-void bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio);
-void bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link);
/* APIs for BNAD */
void bna_tx_res_req(int num_txq, int txq_depth,
struct bna_res_info *res_info);
struct bna_tx *bna_tx_create(struct bna *bna, struct bnad *bnad,
struct bna_tx_config *tx_cfg,
- struct bna_tx_event_cbfn *tx_cbfn,
+ const struct bna_tx_event_cbfn *tx_cbfn,
struct bna_res_info *res_info, void *priv);
void bna_tx_destroy(struct bna_tx *tx);
void bna_tx_enable(struct bna_tx *tx);
void bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
- void (*cbfn)(void *, struct bna_tx *,
- enum bna_cb_status));
+ void (*cbfn)(void *, struct bna_tx *));
+void bna_tx_cleanup_complete(struct bna_tx *tx);
void bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo);
/**
* RX MODULE, RX, RXF
*/
-/* Internal APIs */
-void rxf_cb_cam_fltr_mbox_cmd(void *arg, int status);
-void rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd,
- const struct bna_mac *mac_addr);
-void __rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status);
-void bna_rxf_adv_init(struct bna_rxf *rxf,
- struct bna_rx *rx,
- struct bna_rx_config *q_config);
-int rxf_process_packet_filter_ucast(struct bna_rxf *rxf);
-int rxf_process_packet_filter_promisc(struct bna_rxf *rxf);
-int rxf_process_packet_filter_default(struct bna_rxf *rxf);
-int rxf_process_packet_filter_allmulti(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_ucast(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_promisc(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_default(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_ucast(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_promisc(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_default(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf);
+/* FW response handlers */
+void bna_bfi_rx_enet_start_rsp(struct bna_rx *rx,
+ struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_rx_enet_stop_rsp(struct bna_rx *rx,
+ struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_rxf_cfg_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr);
+void bna_bfi_rxf_mcast_add_rsp(struct bna_rxf *rxf,
+ struct bfi_msgq_mhdr *msghdr);
/* APIs for BNA */
void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
struct bna_res_info *res_info);
void bna_rx_mod_uninit(struct bna_rx_mod *rx_mod);
-int bna_rx_state_get(struct bna_rx *rx);
-int bna_rxf_state_get(struct bna_rxf *rxf);
-/* APIs for PORT */
+/* APIs for ENET */
void bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type);
void bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type);
void bna_rx_mod_fail(struct bna_rx_mod *rx_mod);
@@ -490,59 +490,86 @@ void bna_rx_res_req(struct bna_rx_config *rx_config,
struct bna_res_info *res_info);
struct bna_rx *bna_rx_create(struct bna *bna, struct bnad *bnad,
struct bna_rx_config *rx_cfg,
- struct bna_rx_event_cbfn *rx_cbfn,
+ const struct bna_rx_event_cbfn *rx_cbfn,
struct bna_res_info *res_info, void *priv);
void bna_rx_destroy(struct bna_rx *rx);
void bna_rx_enable(struct bna_rx *rx);
void bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
- void (*cbfn)(void *, struct bna_rx *,
- enum bna_cb_status));
+ void (*cbfn)(void *, struct bna_rx *));
+void bna_rx_cleanup_complete(struct bna_rx *rx);
void bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo);
void bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX]);
void bna_rx_dim_update(struct bna_ccb *ccb);
enum bna_cb_status
bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
- void (*cbfn)(struct bnad *, struct bna_rx *,
- enum bna_cb_status));
+ void (*cbfn)(struct bnad *, struct bna_rx *));
+enum bna_cb_status
+bna_rx_ucast_add(struct bna_rx *rx, u8* ucmac,
+ void (*cbfn)(struct bnad *, struct bna_rx *));
+enum bna_cb_status
+bna_rx_ucast_del(struct bna_rx *rx, u8 *ucmac,
+ void (*cbfn)(struct bnad *, struct bna_rx *));
enum bna_cb_status
bna_rx_mcast_add(struct bna_rx *rx, u8 *mcmac,
- void (*cbfn)(struct bnad *, struct bna_rx *,
- enum bna_cb_status));
+ void (*cbfn)(struct bnad *, struct bna_rx *));
enum bna_cb_status
bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mcmac,
- void (*cbfn)(struct bnad *, struct bna_rx *,
- enum bna_cb_status));
+ void (*cbfn)(struct bnad *, struct bna_rx *));
enum bna_cb_status
bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode rxmode,
enum bna_rxmode bitmask,
- void (*cbfn)(struct bnad *, struct bna_rx *,
- enum bna_cb_status));
+ void (*cbfn)(struct bnad *, struct bna_rx *));
void bna_rx_vlan_add(struct bna_rx *rx, int vlan_id);
void bna_rx_vlan_del(struct bna_rx *rx, int vlan_id);
void bna_rx_vlanfilter_enable(struct bna_rx *rx);
-void bna_rx_hds_enable(struct bna_rx *rx, struct bna_rxf_hds *hds_config,
- void (*cbfn)(struct bnad *, struct bna_rx *,
- enum bna_cb_status));
-void bna_rx_hds_disable(struct bna_rx *rx,
- void (*cbfn)(struct bnad *, struct bna_rx *,
- enum bna_cb_status));
+/**
+ * ENET
+ */
+
+/* API for RX */
+int bna_enet_mtu_get(struct bna_enet *enet);
+
+/* Callbacks for TX, RX */
+void bna_enet_cb_tx_stopped(struct bna_enet *enet);
+void bna_enet_cb_rx_stopped(struct bna_enet *enet);
+
+/* API for BNAD */
+void bna_enet_enable(struct bna_enet *enet);
+void bna_enet_disable(struct bna_enet *enet, enum bna_cleanup_type type,
+ void (*cbfn)(void *));
+void bna_enet_pause_config(struct bna_enet *enet,
+ struct bna_pause_config *pause_config,
+ void (*cbfn)(struct bnad *));
+void bna_enet_mtu_set(struct bna_enet *enet, int mtu,
+ void (*cbfn)(struct bnad *));
+void bna_enet_perm_mac_get(struct bna_enet *enet, mac_t *mac);
+
+/**
+ * IOCETH
+ */
+
+/* APIs for BNAD */
+void bna_ioceth_enable(struct bna_ioceth *ioceth);
+void bna_ioceth_disable(struct bna_ioceth *ioceth,
+ enum bna_cleanup_type type);
/**
* BNAD
*/
+/* Callbacks for ENET */
+void bnad_cb_ethport_link_status(struct bnad *bnad,
+ enum bna_link_status status);
+
+/* Callbacks for IOCETH */
+void bnad_cb_ioceth_ready(struct bnad *bnad);
+void bnad_cb_ioceth_failed(struct bnad *bnad);
+void bnad_cb_ioceth_disabled(struct bnad *bnad);
+void bnad_cb_mbox_intr_enable(struct bnad *bnad);
+void bnad_cb_mbox_intr_disable(struct bnad *bnad);
+
/* Callbacks for BNA */
void bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status,
struct bna_stats *stats);
-/* Callbacks for DEVICE */
-void bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status);
-void bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status);
-void bnad_cb_device_enable_mbox_intr(struct bnad *bnad);
-void bnad_cb_device_disable_mbox_intr(struct bnad *bnad);
-
-/* Callbacks for port */
-void bnad_cb_port_link_status(struct bnad *bnad,
- enum bna_link_status status);
-
#endif /* __BNA_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bna_enet.c b/drivers/net/ethernet/brocade/bna/bna_enet.c
new file mode 100644
index 000000000000..26f5c5abfd1f
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/bna_enet.c
@@ -0,0 +1,2144 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include "bna.h"
+
+static inline int
+ethport_can_be_up(struct bna_ethport *ethport)
+{
+ int ready = 0;
+ if (ethport->bna->enet.type == BNA_ENET_T_REGULAR)
+ ready = ((ethport->flags & BNA_ETHPORT_F_ADMIN_UP) &&
+ (ethport->flags & BNA_ETHPORT_F_RX_STARTED) &&
+ (ethport->flags & BNA_ETHPORT_F_PORT_ENABLED));
+ else
+ ready = ((ethport->flags & BNA_ETHPORT_F_ADMIN_UP) &&
+ (ethport->flags & BNA_ETHPORT_F_RX_STARTED) &&
+ !(ethport->flags & BNA_ETHPORT_F_PORT_ENABLED));
+ return ready;
+}
+
+#define ethport_is_up ethport_can_be_up
+
+enum bna_ethport_event {
+ ETHPORT_E_START = 1,
+ ETHPORT_E_STOP = 2,
+ ETHPORT_E_FAIL = 3,
+ ETHPORT_E_UP = 4,
+ ETHPORT_E_DOWN = 5,
+ ETHPORT_E_FWRESP_UP_OK = 6,
+ ETHPORT_E_FWRESP_DOWN = 7,
+ ETHPORT_E_FWRESP_UP_FAIL = 8,
+};
+
+enum bna_enet_event {
+ ENET_E_START = 1,
+ ENET_E_STOP = 2,
+ ENET_E_FAIL = 3,
+ ENET_E_PAUSE_CFG = 4,
+ ENET_E_MTU_CFG = 5,
+ ENET_E_FWRESP_PAUSE = 6,
+ ENET_E_CHLD_STOPPED = 7,
+};
+
+enum bna_ioceth_event {
+ IOCETH_E_ENABLE = 1,
+ IOCETH_E_DISABLE = 2,
+ IOCETH_E_IOC_RESET = 3,
+ IOCETH_E_IOC_FAILED = 4,
+ IOCETH_E_IOC_READY = 5,
+ IOCETH_E_ENET_ATTR_RESP = 6,
+ IOCETH_E_ENET_STOPPED = 7,
+ IOCETH_E_IOC_DISABLED = 8,
+};
+
+#define bna_stats_copy(_name, _type) \
+do { \
+ count = sizeof(struct bfi_enet_stats_ ## _type) / sizeof(u64); \
+ stats_src = (u64 *)&bna->stats.hw_stats_kva->_name ## _stats; \
+ stats_dst = (u64 *)&bna->stats.hw_stats._name ## _stats; \
+ for (i = 0; i < count; i++) \
+ stats_dst[i] = be64_to_cpu(stats_src[i]); \
+} while (0) \
+
+/*
+ * FW response handlers
+ */
+
+static void
+bna_bfi_ethport_enable_aen(struct bna_ethport *ethport,
+ struct bfi_msgq_mhdr *msghdr)
+{
+ ethport->flags |= BNA_ETHPORT_F_PORT_ENABLED;
+
+ if (ethport_can_be_up(ethport))
+ bfa_fsm_send_event(ethport, ETHPORT_E_UP);
+}
+
+static void
+bna_bfi_ethport_disable_aen(struct bna_ethport *ethport,
+ struct bfi_msgq_mhdr *msghdr)
+{
+ int ethport_up = ethport_is_up(ethport);
+
+ ethport->flags &= ~BNA_ETHPORT_F_PORT_ENABLED;
+
+ if (ethport_up)
+ bfa_fsm_send_event(ethport, ETHPORT_E_DOWN);
+}
+
+static void
+bna_bfi_ethport_admin_rsp(struct bna_ethport *ethport,
+ struct bfi_msgq_mhdr *msghdr)
+{
+ struct bfi_enet_enable_req *admin_req =
+ &ethport->bfi_enet_cmd.admin_req;
+ struct bfi_enet_rsp *rsp = (struct bfi_enet_rsp *)msghdr;
+
+ switch (admin_req->enable) {
+ case BNA_STATUS_T_ENABLED:
+ if (rsp->error == BFI_ENET_CMD_OK)
+ bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_UP_OK);
+ else {
+ ethport->flags &= ~BNA_ETHPORT_F_PORT_ENABLED;
+ bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_UP_FAIL);
+ }
+ break;
+
+ case BNA_STATUS_T_DISABLED:
+ bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_DOWN);
+ ethport->link_status = BNA_LINK_DOWN;
+ ethport->link_cbfn(ethport->bna->bnad, BNA_LINK_DOWN);
+ break;
+ }
+}
+
+static void
+bna_bfi_ethport_lpbk_rsp(struct bna_ethport *ethport,
+ struct bfi_msgq_mhdr *msghdr)
+{
+ struct bfi_enet_diag_lb_req *diag_lb_req =
+ &ethport->bfi_enet_cmd.lpbk_req;
+ struct bfi_enet_rsp *rsp = (struct bfi_enet_rsp *)msghdr;
+
+ switch (diag_lb_req->enable) {
+ case BNA_STATUS_T_ENABLED:
+ if (rsp->error == BFI_ENET_CMD_OK)
+ bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_UP_OK);
+ else {
+ ethport->flags &= ~BNA_ETHPORT_F_ADMIN_UP;
+ bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_UP_FAIL);
+ }
+ break;
+
+ case BNA_STATUS_T_DISABLED:
+ bfa_fsm_send_event(ethport, ETHPORT_E_FWRESP_DOWN);
+ break;
+ }
+}
+
+static void
+bna_bfi_pause_set_rsp(struct bna_enet *enet, struct bfi_msgq_mhdr *msghdr)
+{
+ bfa_fsm_send_event(enet, ENET_E_FWRESP_PAUSE);
+}
+
+static void
+bna_bfi_attr_get_rsp(struct bna_ioceth *ioceth,
+ struct bfi_msgq_mhdr *msghdr)
+{
+ struct bfi_enet_attr_rsp *rsp = (struct bfi_enet_attr_rsp *)msghdr;
+
+ /**
+ * Store only if not set earlier, since BNAD can override the HW
+ * attributes
+ */
+ if (!ioceth->attr.fw_query_complete) {
+ ioceth->attr.num_txq = ntohl(rsp->max_cfg);
+ ioceth->attr.num_rxp = ntohl(rsp->max_cfg);
+ ioceth->attr.num_ucmac = ntohl(rsp->max_ucmac);
+ ioceth->attr.num_mcmac = BFI_ENET_MAX_MCAM;
+ ioceth->attr.max_rit_size = ntohl(rsp->rit_size);
+ ioceth->attr.fw_query_complete = true;
+ }
+
+ bfa_fsm_send_event(ioceth, IOCETH_E_ENET_ATTR_RESP);
+}
+
+static void
+bna_bfi_stats_get_rsp(struct bna *bna, struct bfi_msgq_mhdr *msghdr)
+{
+ struct bfi_enet_stats_req *stats_req = &bna->stats_mod.stats_get;
+ u64 *stats_src;
+ u64 *stats_dst;
+ u32 tx_enet_mask = ntohl(stats_req->tx_enet_mask);
+ u32 rx_enet_mask = ntohl(stats_req->rx_enet_mask);
+ int count;
+ int i;
+
+ bna_stats_copy(mac, mac);
+ bna_stats_copy(bpc, bpc);
+ bna_stats_copy(rad, rad);
+ bna_stats_copy(rlb, rad);
+ bna_stats_copy(fc_rx, fc_rx);
+ bna_stats_copy(fc_tx, fc_tx);
+
+ stats_src = (u64 *)&(bna->stats.hw_stats_kva->rxf_stats[0]);
+
+ /* Copy Rxf stats to SW area, scatter them while copying */
+ for (i = 0; i < BFI_ENET_CFG_MAX; i++) {
+ stats_dst = (u64 *)&(bna->stats.hw_stats.rxf_stats[i]);
+ memset(stats_dst, 0, sizeof(struct bfi_enet_stats_rxf));
+ if (rx_enet_mask & ((u32)(1 << i))) {
+ int k;
+ count = sizeof(struct bfi_enet_stats_rxf) /
+ sizeof(u64);
+ for (k = 0; k < count; k++) {
+ stats_dst[k] = be64_to_cpu(*stats_src);
+ stats_src++;
+ }
+ }
+ }
+
+ /* Copy Txf stats to SW area, scatter them while copying */
+ for (i = 0; i < BFI_ENET_CFG_MAX; i++) {
+ stats_dst = (u64 *)&(bna->stats.hw_stats.txf_stats[i]);
+ memset(stats_dst, 0, sizeof(struct bfi_enet_stats_txf));
+ if (tx_enet_mask & ((u32)(1 << i))) {
+ int k;
+ count = sizeof(struct bfi_enet_stats_txf) /
+ sizeof(u64);
+ for (k = 0; k < count; k++) {
+ stats_dst[k] = be64_to_cpu(*stats_src);
+ stats_src++;
+ }
+ }
+ }
+
+ bna->stats_mod.stats_get_busy = false;
+ bnad_cb_stats_get(bna->bnad, BNA_CB_SUCCESS, &bna->stats);
+}
+
+static void
+bna_bfi_ethport_linkup_aen(struct bna_ethport *ethport,
+ struct bfi_msgq_mhdr *msghdr)
+{
+ ethport->link_status = BNA_LINK_UP;
+
+ /* Dispatch events */
+ ethport->link_cbfn(ethport->bna->bnad, ethport->link_status);
+}
+
+static void
+bna_bfi_ethport_linkdown_aen(struct bna_ethport *ethport,
+ struct bfi_msgq_mhdr *msghdr)
+{
+ ethport->link_status = BNA_LINK_DOWN;
+
+ /* Dispatch events */
+ ethport->link_cbfn(ethport->bna->bnad, BNA_LINK_DOWN);
+}
+
+static void
+bna_err_handler(struct bna *bna, u32 intr_status)
+{
+ if (BNA_IS_HALT_INTR(bna, intr_status))
+ bna_halt_clear(bna);
+
+ bfa_nw_ioc_error_isr(&bna->ioceth.ioc);
+}
+
+void
+bna_mbox_handler(struct bna *bna, u32 intr_status)
+{
+ if (BNA_IS_ERR_INTR(bna, intr_status)) {
+ bna_err_handler(bna, intr_status);
+ return;
+ }
+ if (BNA_IS_MBOX_INTR(bna, intr_status))
+ bfa_nw_ioc_mbox_isr(&bna->ioceth.ioc);
+}
+
+static void
+bna_msgq_rsp_handler(void *arg, struct bfi_msgq_mhdr *msghdr)
+{
+ struct bna *bna = (struct bna *)arg;
+ struct bna_tx *tx;
+ struct bna_rx *rx;
+
+ switch (msghdr->msg_id) {
+ case BFI_ENET_I2H_RX_CFG_SET_RSP:
+ bna_rx_from_rid(bna, msghdr->enet_id, rx);
+ if (rx)
+ bna_bfi_rx_enet_start_rsp(rx, msghdr);
+ break;
+
+ case BFI_ENET_I2H_RX_CFG_CLR_RSP:
+ bna_rx_from_rid(bna, msghdr->enet_id, rx);
+ if (rx)
+ bna_bfi_rx_enet_stop_rsp(rx, msghdr);
+ break;
+
+ case BFI_ENET_I2H_RIT_CFG_RSP:
+ case BFI_ENET_I2H_RSS_CFG_RSP:
+ case BFI_ENET_I2H_RSS_ENABLE_RSP:
+ case BFI_ENET_I2H_RX_PROMISCUOUS_RSP:
+ case BFI_ENET_I2H_RX_DEFAULT_RSP:
+ case BFI_ENET_I2H_MAC_UCAST_SET_RSP:
+ case BFI_ENET_I2H_MAC_UCAST_CLR_RSP:
+ case BFI_ENET_I2H_MAC_UCAST_ADD_RSP:
+ case BFI_ENET_I2H_MAC_UCAST_DEL_RSP:
+ case BFI_ENET_I2H_MAC_MCAST_DEL_RSP:
+ case BFI_ENET_I2H_MAC_MCAST_FILTER_RSP:
+ case BFI_ENET_I2H_RX_VLAN_SET_RSP:
+ case BFI_ENET_I2H_RX_VLAN_STRIP_ENABLE_RSP:
+ bna_rx_from_rid(bna, msghdr->enet_id, rx);
+ if (rx)
+ bna_bfi_rxf_cfg_rsp(&rx->rxf, msghdr);
+ break;
+
+ case BFI_ENET_I2H_MAC_MCAST_ADD_RSP:
+ bna_rx_from_rid(bna, msghdr->enet_id, rx);
+ if (rx)
+ bna_bfi_rxf_mcast_add_rsp(&rx->rxf, msghdr);
+ break;
+
+ case BFI_ENET_I2H_TX_CFG_SET_RSP:
+ bna_tx_from_rid(bna, msghdr->enet_id, tx);
+ if (tx)
+ bna_bfi_tx_enet_start_rsp(tx, msghdr);
+ break;
+
+ case BFI_ENET_I2H_TX_CFG_CLR_RSP:
+ bna_tx_from_rid(bna, msghdr->enet_id, tx);
+ if (tx)
+ bna_bfi_tx_enet_stop_rsp(tx, msghdr);
+ break;
+
+ case BFI_ENET_I2H_PORT_ADMIN_RSP:
+ bna_bfi_ethport_admin_rsp(&bna->ethport, msghdr);
+ break;
+
+ case BFI_ENET_I2H_DIAG_LOOPBACK_RSP:
+ bna_bfi_ethport_lpbk_rsp(&bna->ethport, msghdr);
+ break;
+
+ case BFI_ENET_I2H_SET_PAUSE_RSP:
+ bna_bfi_pause_set_rsp(&bna->enet, msghdr);
+ break;
+
+ case BFI_ENET_I2H_GET_ATTR_RSP:
+ bna_bfi_attr_get_rsp(&bna->ioceth, msghdr);
+ break;
+
+ case BFI_ENET_I2H_STATS_GET_RSP:
+ bna_bfi_stats_get_rsp(bna, msghdr);
+ break;
+
+ case BFI_ENET_I2H_STATS_CLR_RSP:
+ /* No-op */
+ break;
+
+ case BFI_ENET_I2H_LINK_UP_AEN:
+ bna_bfi_ethport_linkup_aen(&bna->ethport, msghdr);
+ break;
+
+ case BFI_ENET_I2H_LINK_DOWN_AEN:
+ bna_bfi_ethport_linkdown_aen(&bna->ethport, msghdr);
+ break;
+
+ case BFI_ENET_I2H_PORT_ENABLE_AEN:
+ bna_bfi_ethport_enable_aen(&bna->ethport, msghdr);
+ break;
+
+ case BFI_ENET_I2H_PORT_DISABLE_AEN:
+ bna_bfi_ethport_disable_aen(&bna->ethport, msghdr);
+ break;
+
+ case BFI_ENET_I2H_BW_UPDATE_AEN:
+ bna_bfi_bw_update_aen(&bna->tx_mod);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * ETHPORT
+ */
+#define call_ethport_stop_cbfn(_ethport) \
+do { \
+ if ((_ethport)->stop_cbfn) { \
+ void (*cbfn)(struct bna_enet *); \
+ cbfn = (_ethport)->stop_cbfn; \
+ (_ethport)->stop_cbfn = NULL; \
+ cbfn(&(_ethport)->bna->enet); \
+ } \
+} while (0)
+
+#define call_ethport_adminup_cbfn(ethport, status) \
+do { \
+ if ((ethport)->adminup_cbfn) { \
+ void (*cbfn)(struct bnad *, enum bna_cb_status); \
+ cbfn = (ethport)->adminup_cbfn; \
+ (ethport)->adminup_cbfn = NULL; \
+ cbfn((ethport)->bna->bnad, status); \
+ } \
+} while (0)
+
+static void
+bna_bfi_ethport_admin_up(struct bna_ethport *ethport)
+{
+ struct bfi_enet_enable_req *admin_up_req =
+ &ethport->bfi_enet_cmd.admin_req;
+
+ bfi_msgq_mhdr_set(admin_up_req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_PORT_ADMIN_UP_REQ, 0, 0);
+ admin_up_req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+ admin_up_req->enable = BNA_STATUS_T_ENABLED;
+
+ bfa_msgq_cmd_set(&ethport->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_enable_req), &admin_up_req->mh);
+ bfa_msgq_cmd_post(&ethport->bna->msgq, &ethport->msgq_cmd);
+}
+
+static void
+bna_bfi_ethport_admin_down(struct bna_ethport *ethport)
+{
+ struct bfi_enet_enable_req *admin_down_req =
+ &ethport->bfi_enet_cmd.admin_req;
+
+ bfi_msgq_mhdr_set(admin_down_req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_PORT_ADMIN_UP_REQ, 0, 0);
+ admin_down_req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+ admin_down_req->enable = BNA_STATUS_T_DISABLED;
+
+ bfa_msgq_cmd_set(&ethport->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_enable_req), &admin_down_req->mh);
+ bfa_msgq_cmd_post(&ethport->bna->msgq, &ethport->msgq_cmd);
+}
+
+static void
+bna_bfi_ethport_lpbk_up(struct bna_ethport *ethport)
+{
+ struct bfi_enet_diag_lb_req *lpbk_up_req =
+ &ethport->bfi_enet_cmd.lpbk_req;
+
+ bfi_msgq_mhdr_set(lpbk_up_req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_DIAG_LOOPBACK_REQ, 0, 0);
+ lpbk_up_req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_diag_lb_req)));
+ lpbk_up_req->mode = (ethport->bna->enet.type ==
+ BNA_ENET_T_LOOPBACK_INTERNAL) ?
+ BFI_ENET_DIAG_LB_OPMODE_EXT :
+ BFI_ENET_DIAG_LB_OPMODE_CBL;
+ lpbk_up_req->enable = BNA_STATUS_T_ENABLED;
+
+ bfa_msgq_cmd_set(&ethport->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_diag_lb_req), &lpbk_up_req->mh);
+ bfa_msgq_cmd_post(&ethport->bna->msgq, &ethport->msgq_cmd);
+}
+
+static void
+bna_bfi_ethport_lpbk_down(struct bna_ethport *ethport)
+{
+ struct bfi_enet_diag_lb_req *lpbk_down_req =
+ &ethport->bfi_enet_cmd.lpbk_req;
+
+ bfi_msgq_mhdr_set(lpbk_down_req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_DIAG_LOOPBACK_REQ, 0, 0);
+ lpbk_down_req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_diag_lb_req)));
+ lpbk_down_req->enable = BNA_STATUS_T_DISABLED;
+
+ bfa_msgq_cmd_set(&ethport->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_diag_lb_req), &lpbk_down_req->mh);
+ bfa_msgq_cmd_post(&ethport->bna->msgq, &ethport->msgq_cmd);
+}
+
+static void
+bna_bfi_ethport_up(struct bna_ethport *ethport)
+{
+ if (ethport->bna->enet.type == BNA_ENET_T_REGULAR)
+ bna_bfi_ethport_admin_up(ethport);
+ else
+ bna_bfi_ethport_lpbk_up(ethport);
+}
+
+static void
+bna_bfi_ethport_down(struct bna_ethport *ethport)
+{
+ if (ethport->bna->enet.type == BNA_ENET_T_REGULAR)
+ bna_bfi_ethport_admin_down(ethport);
+ else
+ bna_bfi_ethport_lpbk_down(ethport);
+}
+
+bfa_fsm_state_decl(bna_ethport, stopped, struct bna_ethport,
+ enum bna_ethport_event);
+bfa_fsm_state_decl(bna_ethport, down, struct bna_ethport,
+ enum bna_ethport_event);
+bfa_fsm_state_decl(bna_ethport, up_resp_wait, struct bna_ethport,
+ enum bna_ethport_event);
+bfa_fsm_state_decl(bna_ethport, down_resp_wait, struct bna_ethport,
+ enum bna_ethport_event);
+bfa_fsm_state_decl(bna_ethport, up, struct bna_ethport,
+ enum bna_ethport_event);
+bfa_fsm_state_decl(bna_ethport, last_resp_wait, struct bna_ethport,
+ enum bna_ethport_event);
+
+static void
+bna_ethport_sm_stopped_entry(struct bna_ethport *ethport)
+{
+ call_ethport_stop_cbfn(ethport);
+}
+
+static void
+bna_ethport_sm_stopped(struct bna_ethport *ethport,
+ enum bna_ethport_event event)
+{
+ switch (event) {
+ case ETHPORT_E_START:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_down);
+ break;
+
+ case ETHPORT_E_STOP:
+ call_ethport_stop_cbfn(ethport);
+ break;
+
+ case ETHPORT_E_FAIL:
+ /* No-op */
+ break;
+
+ case ETHPORT_E_DOWN:
+ /* This event is received due to Rx objects failing */
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ethport_sm_down_entry(struct bna_ethport *ethport)
+{
+}
+
+static void
+bna_ethport_sm_down(struct bna_ethport *ethport,
+ enum bna_ethport_event event)
+{
+ switch (event) {
+ case ETHPORT_E_STOP:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+ break;
+
+ case ETHPORT_E_FAIL:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+ break;
+
+ case ETHPORT_E_UP:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_up_resp_wait);
+ bna_bfi_ethport_up(ethport);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ethport_sm_up_resp_wait_entry(struct bna_ethport *ethport)
+{
+}
+
+static void
+bna_ethport_sm_up_resp_wait(struct bna_ethport *ethport,
+ enum bna_ethport_event event)
+{
+ switch (event) {
+ case ETHPORT_E_STOP:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_last_resp_wait);
+ break;
+
+ case ETHPORT_E_FAIL:
+ call_ethport_adminup_cbfn(ethport, BNA_CB_FAIL);
+ bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+ break;
+
+ case ETHPORT_E_DOWN:
+ call_ethport_adminup_cbfn(ethport, BNA_CB_INTERRUPT);
+ bfa_fsm_set_state(ethport, bna_ethport_sm_down_resp_wait);
+ break;
+
+ case ETHPORT_E_FWRESP_UP_OK:
+ call_ethport_adminup_cbfn(ethport, BNA_CB_SUCCESS);
+ bfa_fsm_set_state(ethport, bna_ethport_sm_up);
+ break;
+
+ case ETHPORT_E_FWRESP_UP_FAIL:
+ call_ethport_adminup_cbfn(ethport, BNA_CB_FAIL);
+ bfa_fsm_set_state(ethport, bna_ethport_sm_down);
+ break;
+
+ case ETHPORT_E_FWRESP_DOWN:
+ /* down_resp_wait -> up_resp_wait transition on ETHPORT_E_UP */
+ bna_bfi_ethport_up(ethport);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ethport_sm_down_resp_wait_entry(struct bna_ethport *ethport)
+{
+ /**
+ * NOTE: Do not call bna_bfi_ethport_down() here. That will over step
+ * mbox due to up_resp_wait -> down_resp_wait transition on event
+ * ETHPORT_E_DOWN
+ */
+}
+
+static void
+bna_ethport_sm_down_resp_wait(struct bna_ethport *ethport,
+ enum bna_ethport_event event)
+{
+ switch (event) {
+ case ETHPORT_E_STOP:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_last_resp_wait);
+ break;
+
+ case ETHPORT_E_FAIL:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+ break;
+
+ case ETHPORT_E_UP:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_up_resp_wait);
+ break;
+
+ case ETHPORT_E_FWRESP_UP_OK:
+ /* up_resp_wait->down_resp_wait transition on ETHPORT_E_DOWN */
+ bna_bfi_ethport_down(ethport);
+ break;
+
+ case ETHPORT_E_FWRESP_UP_FAIL:
+ case ETHPORT_E_FWRESP_DOWN:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_down);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ethport_sm_up_entry(struct bna_ethport *ethport)
+{
+}
+
+static void
+bna_ethport_sm_up(struct bna_ethport *ethport,
+ enum bna_ethport_event event)
+{
+ switch (event) {
+ case ETHPORT_E_STOP:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_last_resp_wait);
+ bna_bfi_ethport_down(ethport);
+ break;
+
+ case ETHPORT_E_FAIL:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+ break;
+
+ case ETHPORT_E_DOWN:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_down_resp_wait);
+ bna_bfi_ethport_down(ethport);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ethport_sm_last_resp_wait_entry(struct bna_ethport *ethport)
+{
+}
+
+static void
+bna_ethport_sm_last_resp_wait(struct bna_ethport *ethport,
+ enum bna_ethport_event event)
+{
+ switch (event) {
+ case ETHPORT_E_FAIL:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+ break;
+
+ case ETHPORT_E_DOWN:
+ /**
+ * This event is received due to Rx objects stopping in
+ * parallel to ethport
+ */
+ /* No-op */
+ break;
+
+ case ETHPORT_E_FWRESP_UP_OK:
+ /* up_resp_wait->last_resp_wait transition on ETHPORT_T_STOP */
+ bna_bfi_ethport_down(ethport);
+ break;
+
+ case ETHPORT_E_FWRESP_UP_FAIL:
+ case ETHPORT_E_FWRESP_DOWN:
+ bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ethport_init(struct bna_ethport *ethport, struct bna *bna)
+{
+ ethport->flags |= (BNA_ETHPORT_F_ADMIN_UP | BNA_ETHPORT_F_PORT_ENABLED);
+ ethport->bna = bna;
+
+ ethport->link_status = BNA_LINK_DOWN;
+ ethport->link_cbfn = bnad_cb_ethport_link_status;
+
+ ethport->rx_started_count = 0;
+
+ ethport->stop_cbfn = NULL;
+ ethport->adminup_cbfn = NULL;
+
+ bfa_fsm_set_state(ethport, bna_ethport_sm_stopped);
+}
+
+static void
+bna_ethport_uninit(struct bna_ethport *ethport)
+{
+ ethport->flags &= ~BNA_ETHPORT_F_ADMIN_UP;
+ ethport->flags &= ~BNA_ETHPORT_F_PORT_ENABLED;
+
+ ethport->bna = NULL;
+}
+
+static void
+bna_ethport_start(struct bna_ethport *ethport)
+{
+ bfa_fsm_send_event(ethport, ETHPORT_E_START);
+}
+
+static void
+bna_enet_cb_ethport_stopped(struct bna_enet *enet)
+{
+ bfa_wc_down(&enet->chld_stop_wc);
+}
+
+static void
+bna_ethport_stop(struct bna_ethport *ethport)
+{
+ ethport->stop_cbfn = bna_enet_cb_ethport_stopped;
+ bfa_fsm_send_event(ethport, ETHPORT_E_STOP);
+}
+
+static void
+bna_ethport_fail(struct bna_ethport *ethport)
+{
+ /* Reset the physical port status to enabled */
+ ethport->flags |= BNA_ETHPORT_F_PORT_ENABLED;
+
+ if (ethport->link_status != BNA_LINK_DOWN) {
+ ethport->link_status = BNA_LINK_DOWN;
+ ethport->link_cbfn(ethport->bna->bnad, BNA_LINK_DOWN);
+ }
+ bfa_fsm_send_event(ethport, ETHPORT_E_FAIL);
+}
+
+/* Should be called only when ethport is disabled */
+void
+bna_ethport_cb_rx_started(struct bna_ethport *ethport)
+{
+ ethport->rx_started_count++;
+
+ if (ethport->rx_started_count == 1) {
+ ethport->flags |= BNA_ETHPORT_F_RX_STARTED;
+
+ if (ethport_can_be_up(ethport))
+ bfa_fsm_send_event(ethport, ETHPORT_E_UP);
+ }
+}
+
+void
+bna_ethport_cb_rx_stopped(struct bna_ethport *ethport)
+{
+ int ethport_up = ethport_is_up(ethport);
+
+ ethport->rx_started_count--;
+
+ if (ethport->rx_started_count == 0) {
+ ethport->flags &= ~BNA_ETHPORT_F_RX_STARTED;
+
+ if (ethport_up)
+ bfa_fsm_send_event(ethport, ETHPORT_E_DOWN);
+ }
+}
+
+/**
+ * ENET
+ */
+#define bna_enet_chld_start(enet) \
+do { \
+ enum bna_tx_type tx_type = \
+ ((enet)->type == BNA_ENET_T_REGULAR) ? \
+ BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK; \
+ enum bna_rx_type rx_type = \
+ ((enet)->type == BNA_ENET_T_REGULAR) ? \
+ BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK; \
+ bna_ethport_start(&(enet)->bna->ethport); \
+ bna_tx_mod_start(&(enet)->bna->tx_mod, tx_type); \
+ bna_rx_mod_start(&(enet)->bna->rx_mod, rx_type); \
+} while (0)
+
+#define bna_enet_chld_stop(enet) \
+do { \
+ enum bna_tx_type tx_type = \
+ ((enet)->type == BNA_ENET_T_REGULAR) ? \
+ BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK; \
+ enum bna_rx_type rx_type = \
+ ((enet)->type == BNA_ENET_T_REGULAR) ? \
+ BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK; \
+ bfa_wc_init(&(enet)->chld_stop_wc, bna_enet_cb_chld_stopped, (enet));\
+ bfa_wc_up(&(enet)->chld_stop_wc); \
+ bna_ethport_stop(&(enet)->bna->ethport); \
+ bfa_wc_up(&(enet)->chld_stop_wc); \
+ bna_tx_mod_stop(&(enet)->bna->tx_mod, tx_type); \
+ bfa_wc_up(&(enet)->chld_stop_wc); \
+ bna_rx_mod_stop(&(enet)->bna->rx_mod, rx_type); \
+ bfa_wc_wait(&(enet)->chld_stop_wc); \
+} while (0)
+
+#define bna_enet_chld_fail(enet) \
+do { \
+ bna_ethport_fail(&(enet)->bna->ethport); \
+ bna_tx_mod_fail(&(enet)->bna->tx_mod); \
+ bna_rx_mod_fail(&(enet)->bna->rx_mod); \
+} while (0)
+
+#define bna_enet_rx_start(enet) \
+do { \
+ enum bna_rx_type rx_type = \
+ ((enet)->type == BNA_ENET_T_REGULAR) ? \
+ BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK; \
+ bna_rx_mod_start(&(enet)->bna->rx_mod, rx_type); \
+} while (0)
+
+#define bna_enet_rx_stop(enet) \
+do { \
+ enum bna_rx_type rx_type = \
+ ((enet)->type == BNA_ENET_T_REGULAR) ? \
+ BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK; \
+ bfa_wc_init(&(enet)->chld_stop_wc, bna_enet_cb_chld_stopped, (enet));\
+ bfa_wc_up(&(enet)->chld_stop_wc); \
+ bna_rx_mod_stop(&(enet)->bna->rx_mod, rx_type); \
+ bfa_wc_wait(&(enet)->chld_stop_wc); \
+} while (0)
+
+#define call_enet_stop_cbfn(enet) \
+do { \
+ if ((enet)->stop_cbfn) { \
+ void (*cbfn)(void *); \
+ void *cbarg; \
+ cbfn = (enet)->stop_cbfn; \
+ cbarg = (enet)->stop_cbarg; \
+ (enet)->stop_cbfn = NULL; \
+ (enet)->stop_cbarg = NULL; \
+ cbfn(cbarg); \
+ } \
+} while (0)
+
+#define call_enet_pause_cbfn(enet) \
+do { \
+ if ((enet)->pause_cbfn) { \
+ void (*cbfn)(struct bnad *); \
+ cbfn = (enet)->pause_cbfn; \
+ (enet)->pause_cbfn = NULL; \
+ cbfn((enet)->bna->bnad); \
+ } \
+} while (0)
+
+#define call_enet_mtu_cbfn(enet) \
+do { \
+ if ((enet)->mtu_cbfn) { \
+ void (*cbfn)(struct bnad *); \
+ cbfn = (enet)->mtu_cbfn; \
+ (enet)->mtu_cbfn = NULL; \
+ cbfn((enet)->bna->bnad); \
+ } \
+} while (0)
+
+static void bna_enet_cb_chld_stopped(void *arg);
+static void bna_bfi_pause_set(struct bna_enet *enet);
+
+bfa_fsm_state_decl(bna_enet, stopped, struct bna_enet,
+ enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, pause_init_wait, struct bna_enet,
+ enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, last_resp_wait, struct bna_enet,
+ enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, started, struct bna_enet,
+ enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, cfg_wait, struct bna_enet,
+ enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, cfg_stop_wait, struct bna_enet,
+ enum bna_enet_event);
+bfa_fsm_state_decl(bna_enet, chld_stop_wait, struct bna_enet,
+ enum bna_enet_event);
+
+static void
+bna_enet_sm_stopped_entry(struct bna_enet *enet)
+{
+ call_enet_pause_cbfn(enet);
+ call_enet_mtu_cbfn(enet);
+ call_enet_stop_cbfn(enet);
+}
+
+static void
+bna_enet_sm_stopped(struct bna_enet *enet, enum bna_enet_event event)
+{
+ switch (event) {
+ case ENET_E_START:
+ bfa_fsm_set_state(enet, bna_enet_sm_pause_init_wait);
+ break;
+
+ case ENET_E_STOP:
+ call_enet_stop_cbfn(enet);
+ break;
+
+ case ENET_E_FAIL:
+ /* No-op */
+ break;
+
+ case ENET_E_PAUSE_CFG:
+ call_enet_pause_cbfn(enet);
+ break;
+
+ case ENET_E_MTU_CFG:
+ call_enet_mtu_cbfn(enet);
+ break;
+
+ case ENET_E_CHLD_STOPPED:
+ /**
+ * This event is received due to Ethport, Tx and Rx objects
+ * failing
+ */
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_enet_sm_pause_init_wait_entry(struct bna_enet *enet)
+{
+ bna_bfi_pause_set(enet);
+}
+
+static void
+bna_enet_sm_pause_init_wait(struct bna_enet *enet,
+ enum bna_enet_event event)
+{
+ switch (event) {
+ case ENET_E_STOP:
+ enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+ bfa_fsm_set_state(enet, bna_enet_sm_last_resp_wait);
+ break;
+
+ case ENET_E_FAIL:
+ enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+ bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+ break;
+
+ case ENET_E_PAUSE_CFG:
+ enet->flags |= BNA_ENET_F_PAUSE_CHANGED;
+ break;
+
+ case ENET_E_MTU_CFG:
+ /* No-op */
+ break;
+
+ case ENET_E_FWRESP_PAUSE:
+ if (enet->flags & BNA_ENET_F_PAUSE_CHANGED) {
+ enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+ bna_bfi_pause_set(enet);
+ } else {
+ bfa_fsm_set_state(enet, bna_enet_sm_started);
+ bna_enet_chld_start(enet);
+ }
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_enet_sm_last_resp_wait_entry(struct bna_enet *enet)
+{
+ enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+}
+
+static void
+bna_enet_sm_last_resp_wait(struct bna_enet *enet,
+ enum bna_enet_event event)
+{
+ switch (event) {
+ case ENET_E_FAIL:
+ case ENET_E_FWRESP_PAUSE:
+ bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_enet_sm_started_entry(struct bna_enet *enet)
+{
+ /**
+ * NOTE: Do not call bna_enet_chld_start() here, since it will be
+ * inadvertently called during cfg_wait->started transition as well
+ */
+ call_enet_pause_cbfn(enet);
+ call_enet_mtu_cbfn(enet);
+}
+
+static void
+bna_enet_sm_started(struct bna_enet *enet,
+ enum bna_enet_event event)
+{
+ switch (event) {
+ case ENET_E_STOP:
+ bfa_fsm_set_state(enet, bna_enet_sm_chld_stop_wait);
+ break;
+
+ case ENET_E_FAIL:
+ bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+ bna_enet_chld_fail(enet);
+ break;
+
+ case ENET_E_PAUSE_CFG:
+ bfa_fsm_set_state(enet, bna_enet_sm_cfg_wait);
+ bna_bfi_pause_set(enet);
+ break;
+
+ case ENET_E_MTU_CFG:
+ bfa_fsm_set_state(enet, bna_enet_sm_cfg_wait);
+ bna_enet_rx_stop(enet);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_enet_sm_cfg_wait_entry(struct bna_enet *enet)
+{
+}
+
+static void
+bna_enet_sm_cfg_wait(struct bna_enet *enet,
+ enum bna_enet_event event)
+{
+ switch (event) {
+ case ENET_E_STOP:
+ enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+ enet->flags &= ~BNA_ENET_F_MTU_CHANGED;
+ bfa_fsm_set_state(enet, bna_enet_sm_cfg_stop_wait);
+ break;
+
+ case ENET_E_FAIL:
+ enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+ enet->flags &= ~BNA_ENET_F_MTU_CHANGED;
+ bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+ bna_enet_chld_fail(enet);
+ break;
+
+ case ENET_E_PAUSE_CFG:
+ enet->flags |= BNA_ENET_F_PAUSE_CHANGED;
+ break;
+
+ case ENET_E_MTU_CFG:
+ enet->flags |= BNA_ENET_F_MTU_CHANGED;
+ break;
+
+ case ENET_E_CHLD_STOPPED:
+ bna_enet_rx_start(enet);
+ /* Fall through */
+ case ENET_E_FWRESP_PAUSE:
+ if (enet->flags & BNA_ENET_F_PAUSE_CHANGED) {
+ enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+ bna_bfi_pause_set(enet);
+ } else if (enet->flags & BNA_ENET_F_MTU_CHANGED) {
+ enet->flags &= ~BNA_ENET_F_MTU_CHANGED;
+ bna_enet_rx_stop(enet);
+ } else {
+ bfa_fsm_set_state(enet, bna_enet_sm_started);
+ }
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_enet_sm_cfg_stop_wait_entry(struct bna_enet *enet)
+{
+ enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED;
+ enet->flags &= ~BNA_ENET_F_MTU_CHANGED;
+}
+
+static void
+bna_enet_sm_cfg_stop_wait(struct bna_enet *enet,
+ enum bna_enet_event event)
+{
+ switch (event) {
+ case ENET_E_FAIL:
+ bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+ bna_enet_chld_fail(enet);
+ break;
+
+ case ENET_E_FWRESP_PAUSE:
+ case ENET_E_CHLD_STOPPED:
+ bfa_fsm_set_state(enet, bna_enet_sm_chld_stop_wait);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_enet_sm_chld_stop_wait_entry(struct bna_enet *enet)
+{
+ bna_enet_chld_stop(enet);
+}
+
+static void
+bna_enet_sm_chld_stop_wait(struct bna_enet *enet,
+ enum bna_enet_event event)
+{
+ switch (event) {
+ case ENET_E_FAIL:
+ bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+ bna_enet_chld_fail(enet);
+ break;
+
+ case ENET_E_CHLD_STOPPED:
+ bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_bfi_pause_set(struct bna_enet *enet)
+{
+ struct bfi_enet_set_pause_req *pause_req = &enet->pause_req;
+
+ bfi_msgq_mhdr_set(pause_req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_SET_PAUSE_REQ, 0, 0);
+ pause_req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_set_pause_req)));
+ pause_req->tx_pause = enet->pause_config.tx_pause;
+ pause_req->rx_pause = enet->pause_config.rx_pause;
+
+ bfa_msgq_cmd_set(&enet->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_set_pause_req), &pause_req->mh);
+ bfa_msgq_cmd_post(&enet->bna->msgq, &enet->msgq_cmd);
+}
+
+static void
+bna_enet_cb_chld_stopped(void *arg)
+{
+ struct bna_enet *enet = (struct bna_enet *)arg;
+
+ bfa_fsm_send_event(enet, ENET_E_CHLD_STOPPED);
+}
+
+static void
+bna_enet_init(struct bna_enet *enet, struct bna *bna)
+{
+ enet->bna = bna;
+ enet->flags = 0;
+ enet->mtu = 0;
+ enet->type = BNA_ENET_T_REGULAR;
+
+ enet->stop_cbfn = NULL;
+ enet->stop_cbarg = NULL;
+
+ enet->pause_cbfn = NULL;
+
+ enet->mtu_cbfn = NULL;
+
+ bfa_fsm_set_state(enet, bna_enet_sm_stopped);
+}
+
+static void
+bna_enet_uninit(struct bna_enet *enet)
+{
+ enet->flags = 0;
+
+ enet->bna = NULL;
+}
+
+static void
+bna_enet_start(struct bna_enet *enet)
+{
+ enet->flags |= BNA_ENET_F_IOCETH_READY;
+ if (enet->flags & BNA_ENET_F_ENABLED)
+ bfa_fsm_send_event(enet, ENET_E_START);
+}
+
+static void
+bna_ioceth_cb_enet_stopped(void *arg)
+{
+ struct bna_ioceth *ioceth = (struct bna_ioceth *)arg;
+
+ bfa_fsm_send_event(ioceth, IOCETH_E_ENET_STOPPED);
+}
+
+static void
+bna_enet_stop(struct bna_enet *enet)
+{
+ enet->stop_cbfn = bna_ioceth_cb_enet_stopped;
+ enet->stop_cbarg = &enet->bna->ioceth;
+
+ enet->flags &= ~BNA_ENET_F_IOCETH_READY;
+ bfa_fsm_send_event(enet, ENET_E_STOP);
+}
+
+static void
+bna_enet_fail(struct bna_enet *enet)
+{
+ enet->flags &= ~BNA_ENET_F_IOCETH_READY;
+ bfa_fsm_send_event(enet, ENET_E_FAIL);
+}
+
+void
+bna_enet_cb_tx_stopped(struct bna_enet *enet)
+{
+ bfa_wc_down(&enet->chld_stop_wc);
+}
+
+void
+bna_enet_cb_rx_stopped(struct bna_enet *enet)
+{
+ bfa_wc_down(&enet->chld_stop_wc);
+}
+
+int
+bna_enet_mtu_get(struct bna_enet *enet)
+{
+ return enet->mtu;
+}
+
+void
+bna_enet_enable(struct bna_enet *enet)
+{
+ if (enet->fsm != (bfa_sm_t)bna_enet_sm_stopped)
+ return;
+
+ enet->flags |= BNA_ENET_F_ENABLED;
+
+ if (enet->flags & BNA_ENET_F_IOCETH_READY)
+ bfa_fsm_send_event(enet, ENET_E_START);
+}
+
+void
+bna_enet_disable(struct bna_enet *enet, enum bna_cleanup_type type,
+ void (*cbfn)(void *))
+{
+ if (type == BNA_SOFT_CLEANUP) {
+ (*cbfn)(enet->bna->bnad);
+ return;
+ }
+
+ enet->stop_cbfn = cbfn;
+ enet->stop_cbarg = enet->bna->bnad;
+
+ enet->flags &= ~BNA_ENET_F_ENABLED;
+
+ bfa_fsm_send_event(enet, ENET_E_STOP);
+}
+
+void
+bna_enet_pause_config(struct bna_enet *enet,
+ struct bna_pause_config *pause_config,
+ void (*cbfn)(struct bnad *))
+{
+ enet->pause_config = *pause_config;
+
+ enet->pause_cbfn = cbfn;
+
+ bfa_fsm_send_event(enet, ENET_E_PAUSE_CFG);
+}
+
+void
+bna_enet_mtu_set(struct bna_enet *enet, int mtu,
+ void (*cbfn)(struct bnad *))
+{
+ enet->mtu = mtu;
+
+ enet->mtu_cbfn = cbfn;
+
+ bfa_fsm_send_event(enet, ENET_E_MTU_CFG);
+}
+
+void
+bna_enet_perm_mac_get(struct bna_enet *enet, mac_t *mac)
+{
+ *mac = bfa_nw_ioc_get_mac(&enet->bna->ioceth.ioc);
+}
+
+/**
+ * IOCETH
+ */
+#define enable_mbox_intr(_ioceth) \
+do { \
+ u32 intr_status; \
+ bna_intr_status_get((_ioceth)->bna, intr_status); \
+ bnad_cb_mbox_intr_enable((_ioceth)->bna->bnad); \
+ bna_mbox_intr_enable((_ioceth)->bna); \
+} while (0)
+
+#define disable_mbox_intr(_ioceth) \
+do { \
+ bna_mbox_intr_disable((_ioceth)->bna); \
+ bnad_cb_mbox_intr_disable((_ioceth)->bna->bnad); \
+} while (0)
+
+#define call_ioceth_stop_cbfn(_ioceth) \
+do { \
+ if ((_ioceth)->stop_cbfn) { \
+ void (*cbfn)(struct bnad *); \
+ struct bnad *cbarg; \
+ cbfn = (_ioceth)->stop_cbfn; \
+ cbarg = (_ioceth)->stop_cbarg; \
+ (_ioceth)->stop_cbfn = NULL; \
+ (_ioceth)->stop_cbarg = NULL; \
+ cbfn(cbarg); \
+ } \
+} while (0)
+
+#define bna_stats_mod_uninit(_stats_mod) \
+do { \
+} while (0)
+
+#define bna_stats_mod_start(_stats_mod) \
+do { \
+ (_stats_mod)->ioc_ready = true; \
+} while (0)
+
+#define bna_stats_mod_stop(_stats_mod) \
+do { \
+ (_stats_mod)->ioc_ready = false; \
+} while (0)
+
+#define bna_stats_mod_fail(_stats_mod) \
+do { \
+ (_stats_mod)->ioc_ready = false; \
+ (_stats_mod)->stats_get_busy = false; \
+ (_stats_mod)->stats_clr_busy = false; \
+} while (0)
+
+static void bna_bfi_attr_get(struct bna_ioceth *ioceth);
+
+bfa_fsm_state_decl(bna_ioceth, stopped, struct bna_ioceth,
+ enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, ioc_ready_wait, struct bna_ioceth,
+ enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, enet_attr_wait, struct bna_ioceth,
+ enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, ready, struct bna_ioceth,
+ enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, last_resp_wait, struct bna_ioceth,
+ enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, enet_stop_wait, struct bna_ioceth,
+ enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, ioc_disable_wait, struct bna_ioceth,
+ enum bna_ioceth_event);
+bfa_fsm_state_decl(bna_ioceth, failed, struct bna_ioceth,
+ enum bna_ioceth_event);
+
+static void
+bna_ioceth_sm_stopped_entry(struct bna_ioceth *ioceth)
+{
+ call_ioceth_stop_cbfn(ioceth);
+}
+
+static void
+bna_ioceth_sm_stopped(struct bna_ioceth *ioceth,
+ enum bna_ioceth_event event)
+{
+ switch (event) {
+ case IOCETH_E_ENABLE:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_ready_wait);
+ bfa_nw_ioc_enable(&ioceth->ioc);
+ break;
+
+ case IOCETH_E_DISABLE:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_stopped);
+ break;
+
+ case IOCETH_E_IOC_RESET:
+ enable_mbox_intr(ioceth);
+ break;
+
+ case IOCETH_E_IOC_FAILED:
+ disable_mbox_intr(ioceth);
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_failed);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ioceth_sm_ioc_ready_wait_entry(struct bna_ioceth *ioceth)
+{
+ /**
+ * Do not call bfa_nw_ioc_enable() here. It must be called in the
+ * previous state due to failed -> ioc_ready_wait transition.
+ */
+}
+
+static void
+bna_ioceth_sm_ioc_ready_wait(struct bna_ioceth *ioceth,
+ enum bna_ioceth_event event)
+{
+ switch (event) {
+ case IOCETH_E_DISABLE:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+ bfa_nw_ioc_disable(&ioceth->ioc);
+ break;
+
+ case IOCETH_E_IOC_RESET:
+ enable_mbox_intr(ioceth);
+ break;
+
+ case IOCETH_E_IOC_FAILED:
+ disable_mbox_intr(ioceth);
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_failed);
+ break;
+
+ case IOCETH_E_IOC_READY:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_enet_attr_wait);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ioceth_sm_enet_attr_wait_entry(struct bna_ioceth *ioceth)
+{
+ bna_bfi_attr_get(ioceth);
+}
+
+static void
+bna_ioceth_sm_enet_attr_wait(struct bna_ioceth *ioceth,
+ enum bna_ioceth_event event)
+{
+ switch (event) {
+ case IOCETH_E_DISABLE:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_last_resp_wait);
+ break;
+
+ case IOCETH_E_IOC_FAILED:
+ disable_mbox_intr(ioceth);
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_failed);
+ break;
+
+ case IOCETH_E_ENET_ATTR_RESP:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_ready);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ioceth_sm_ready_entry(struct bna_ioceth *ioceth)
+{
+ bna_enet_start(&ioceth->bna->enet);
+ bna_stats_mod_start(&ioceth->bna->stats_mod);
+ bnad_cb_ioceth_ready(ioceth->bna->bnad);
+}
+
+static void
+bna_ioceth_sm_ready(struct bna_ioceth *ioceth, enum bna_ioceth_event event)
+{
+ switch (event) {
+ case IOCETH_E_DISABLE:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_enet_stop_wait);
+ break;
+
+ case IOCETH_E_IOC_FAILED:
+ disable_mbox_intr(ioceth);
+ bna_enet_fail(&ioceth->bna->enet);
+ bna_stats_mod_fail(&ioceth->bna->stats_mod);
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_failed);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ioceth_sm_last_resp_wait_entry(struct bna_ioceth *ioceth)
+{
+}
+
+static void
+bna_ioceth_sm_last_resp_wait(struct bna_ioceth *ioceth,
+ enum bna_ioceth_event event)
+{
+ switch (event) {
+ case IOCETH_E_IOC_FAILED:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+ disable_mbox_intr(ioceth);
+ bfa_nw_ioc_disable(&ioceth->ioc);
+ break;
+
+ case IOCETH_E_ENET_ATTR_RESP:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+ bfa_nw_ioc_disable(&ioceth->ioc);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ioceth_sm_enet_stop_wait_entry(struct bna_ioceth *ioceth)
+{
+ bna_stats_mod_stop(&ioceth->bna->stats_mod);
+ bna_enet_stop(&ioceth->bna->enet);
+}
+
+static void
+bna_ioceth_sm_enet_stop_wait(struct bna_ioceth *ioceth,
+ enum bna_ioceth_event event)
+{
+ switch (event) {
+ case IOCETH_E_IOC_FAILED:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+ disable_mbox_intr(ioceth);
+ bna_enet_fail(&ioceth->bna->enet);
+ bna_stats_mod_fail(&ioceth->bna->stats_mod);
+ bfa_nw_ioc_disable(&ioceth->ioc);
+ break;
+
+ case IOCETH_E_ENET_STOPPED:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+ bfa_nw_ioc_disable(&ioceth->ioc);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ioceth_sm_ioc_disable_wait_entry(struct bna_ioceth *ioceth)
+{
+}
+
+static void
+bna_ioceth_sm_ioc_disable_wait(struct bna_ioceth *ioceth,
+ enum bna_ioceth_event event)
+{
+ switch (event) {
+ case IOCETH_E_IOC_DISABLED:
+ disable_mbox_intr(ioceth);
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_stopped);
+ break;
+
+ case IOCETH_E_ENET_STOPPED:
+ /* This event is received due to enet failing */
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_ioceth_sm_failed_entry(struct bna_ioceth *ioceth)
+{
+ bnad_cb_ioceth_failed(ioceth->bna->bnad);
+}
+
+static void
+bna_ioceth_sm_failed(struct bna_ioceth *ioceth,
+ enum bna_ioceth_event event)
+{
+ switch (event) {
+ case IOCETH_E_DISABLE:
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_disable_wait);
+ bfa_nw_ioc_disable(&ioceth->ioc);
+ break;
+
+ case IOCETH_E_IOC_RESET:
+ enable_mbox_intr(ioceth);
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_ioc_ready_wait);
+ break;
+
+ case IOCETH_E_IOC_FAILED:
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_bfi_attr_get(struct bna_ioceth *ioceth)
+{
+ struct bfi_enet_attr_req *attr_req = &ioceth->attr_req;
+
+ bfi_msgq_mhdr_set(attr_req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_GET_ATTR_REQ, 0, 0);
+ attr_req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_attr_req)));
+ bfa_msgq_cmd_set(&ioceth->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_attr_req), &attr_req->mh);
+ bfa_msgq_cmd_post(&ioceth->bna->msgq, &ioceth->msgq_cmd);
+}
+
+/* IOC callback functions */
+
+static void
+bna_cb_ioceth_enable(void *arg, enum bfa_status error)
+{
+ struct bna_ioceth *ioceth = (struct bna_ioceth *)arg;
+
+ if (error)
+ bfa_fsm_send_event(ioceth, IOCETH_E_IOC_FAILED);
+ else
+ bfa_fsm_send_event(ioceth, IOCETH_E_IOC_READY);
+}
+
+static void
+bna_cb_ioceth_disable(void *arg)
+{
+ struct bna_ioceth *ioceth = (struct bna_ioceth *)arg;
+
+ bfa_fsm_send_event(ioceth, IOCETH_E_IOC_DISABLED);
+}
+
+static void
+bna_cb_ioceth_hbfail(void *arg)
+{
+ struct bna_ioceth *ioceth = (struct bna_ioceth *)arg;
+
+ bfa_fsm_send_event(ioceth, IOCETH_E_IOC_FAILED);
+}
+
+static void
+bna_cb_ioceth_reset(void *arg)
+{
+ struct bna_ioceth *ioceth = (struct bna_ioceth *)arg;
+
+ bfa_fsm_send_event(ioceth, IOCETH_E_IOC_RESET);
+}
+
+static struct bfa_ioc_cbfn bna_ioceth_cbfn = {
+ bna_cb_ioceth_enable,
+ bna_cb_ioceth_disable,
+ bna_cb_ioceth_hbfail,
+ bna_cb_ioceth_reset
+};
+
+static void bna_attr_init(struct bna_ioceth *ioceth)
+{
+ ioceth->attr.num_txq = BFI_ENET_DEF_TXQ;
+ ioceth->attr.num_rxp = BFI_ENET_DEF_RXP;
+ ioceth->attr.num_ucmac = BFI_ENET_DEF_UCAM;
+ ioceth->attr.num_mcmac = BFI_ENET_MAX_MCAM;
+ ioceth->attr.max_rit_size = BFI_ENET_DEF_RITSZ;
+ ioceth->attr.fw_query_complete = false;
+}
+
+static void
+bna_ioceth_init(struct bna_ioceth *ioceth, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ u64 dma;
+ u8 *kva;
+
+ ioceth->bna = bna;
+
+ /**
+ * Attach IOC and claim:
+ * 1. DMA memory for IOC attributes
+ * 2. Kernel memory for FW trace
+ */
+ bfa_nw_ioc_attach(&ioceth->ioc, ioceth, &bna_ioceth_cbfn);
+ bfa_nw_ioc_pci_init(&ioceth->ioc, &bna->pcidev, BFI_PCIFN_CLASS_ETH);
+
+ BNA_GET_DMA_ADDR(
+ &res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].dma, dma);
+ kva = res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].kva;
+ bfa_nw_ioc_mem_claim(&ioceth->ioc, kva, dma);
+
+ kva = res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mdl[0].kva;
+
+ /**
+ * Attach common modules (Diag, SFP, CEE, Port) and claim respective
+ * DMA memory.
+ */
+ BNA_GET_DMA_ADDR(
+ &res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].dma, dma);
+ kva = res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].kva;
+ bfa_nw_cee_attach(&bna->cee, &ioceth->ioc, bna);
+ bfa_nw_cee_mem_claim(&bna->cee, kva, dma);
+ kva += bfa_nw_cee_meminfo();
+ dma += bfa_nw_cee_meminfo();
+
+ bfa_msgq_attach(&bna->msgq, &ioceth->ioc);
+ bfa_msgq_memclaim(&bna->msgq, kva, dma);
+ bfa_msgq_regisr(&bna->msgq, BFI_MC_ENET, bna_msgq_rsp_handler, bna);
+ kva += bfa_msgq_meminfo();
+ dma += bfa_msgq_meminfo();
+
+ ioceth->stop_cbfn = NULL;
+ ioceth->stop_cbarg = NULL;
+
+ bna_attr_init(ioceth);
+
+ bfa_fsm_set_state(ioceth, bna_ioceth_sm_stopped);
+}
+
+static void
+bna_ioceth_uninit(struct bna_ioceth *ioceth)
+{
+ bfa_nw_ioc_detach(&ioceth->ioc);
+
+ ioceth->bna = NULL;
+}
+
+void
+bna_ioceth_enable(struct bna_ioceth *ioceth)
+{
+ if (ioceth->fsm == (bfa_fsm_t)bna_ioceth_sm_ready) {
+ bnad_cb_ioceth_ready(ioceth->bna->bnad);
+ return;
+ }
+
+ if (ioceth->fsm == (bfa_fsm_t)bna_ioceth_sm_stopped)
+ bfa_fsm_send_event(ioceth, IOCETH_E_ENABLE);
+}
+
+void
+bna_ioceth_disable(struct bna_ioceth *ioceth, enum bna_cleanup_type type)
+{
+ if (type == BNA_SOFT_CLEANUP) {
+ bnad_cb_ioceth_disabled(ioceth->bna->bnad);
+ return;
+ }
+
+ ioceth->stop_cbfn = bnad_cb_ioceth_disabled;
+ ioceth->stop_cbarg = ioceth->bna->bnad;
+
+ bfa_fsm_send_event(ioceth, IOCETH_E_DISABLE);
+}
+
+static void
+bna_ucam_mod_init(struct bna_ucam_mod *ucam_mod, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ int i;
+
+ ucam_mod->ucmac = (struct bna_mac *)
+ res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
+
+ INIT_LIST_HEAD(&ucam_mod->free_q);
+ for (i = 0; i < bna->ioceth.attr.num_ucmac; i++) {
+ bfa_q_qe_init(&ucam_mod->ucmac[i].qe);
+ list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->free_q);
+ }
+
+ ucam_mod->bna = bna;
+}
+
+static void
+bna_ucam_mod_uninit(struct bna_ucam_mod *ucam_mod)
+{
+ struct list_head *qe;
+ int i = 0;
+
+ list_for_each(qe, &ucam_mod->free_q)
+ i++;
+
+ ucam_mod->bna = NULL;
+}
+
+static void
+bna_mcam_mod_init(struct bna_mcam_mod *mcam_mod, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ int i;
+
+ mcam_mod->mcmac = (struct bna_mac *)
+ res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
+
+ INIT_LIST_HEAD(&mcam_mod->free_q);
+ for (i = 0; i < bna->ioceth.attr.num_mcmac; i++) {
+ bfa_q_qe_init(&mcam_mod->mcmac[i].qe);
+ list_add_tail(&mcam_mod->mcmac[i].qe, &mcam_mod->free_q);
+ }
+
+ mcam_mod->mchandle = (struct bna_mcam_handle *)
+ res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_u.mem_info.mdl[0].kva;
+
+ INIT_LIST_HEAD(&mcam_mod->free_handle_q);
+ for (i = 0; i < bna->ioceth.attr.num_mcmac; i++) {
+ bfa_q_qe_init(&mcam_mod->mchandle[i].qe);
+ list_add_tail(&mcam_mod->mchandle[i].qe,
+ &mcam_mod->free_handle_q);
+ }
+
+ mcam_mod->bna = bna;
+}
+
+static void
+bna_mcam_mod_uninit(struct bna_mcam_mod *mcam_mod)
+{
+ struct list_head *qe;
+ int i;
+
+ i = 0;
+ list_for_each(qe, &mcam_mod->free_q) i++;
+
+ i = 0;
+ list_for_each(qe, &mcam_mod->free_handle_q) i++;
+
+ mcam_mod->bna = NULL;
+}
+
+static void
+bna_bfi_stats_get(struct bna *bna)
+{
+ struct bfi_enet_stats_req *stats_req = &bna->stats_mod.stats_get;
+
+ bna->stats_mod.stats_get_busy = true;
+
+ bfi_msgq_mhdr_set(stats_req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_STATS_GET_REQ, 0, 0);
+ stats_req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_stats_req)));
+ stats_req->stats_mask = htons(BFI_ENET_STATS_ALL);
+ stats_req->tx_enet_mask = htonl(bna->tx_mod.rid_mask);
+ stats_req->rx_enet_mask = htonl(bna->rx_mod.rid_mask);
+ stats_req->host_buffer.a32.addr_hi = bna->stats.hw_stats_dma.msb;
+ stats_req->host_buffer.a32.addr_lo = bna->stats.hw_stats_dma.lsb;
+
+ bfa_msgq_cmd_set(&bna->stats_mod.stats_get_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_stats_req), &stats_req->mh);
+ bfa_msgq_cmd_post(&bna->msgq, &bna->stats_mod.stats_get_cmd);
+}
+
+void
+bna_res_req(struct bna_res_info *res_info)
+{
+ /* DMA memory for COMMON_MODULE */
+ res_info[BNA_RES_MEM_T_COM].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+ res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN(
+ (bfa_nw_cee_meminfo() +
+ bfa_msgq_meminfo()), PAGE_SIZE);
+
+ /* DMA memory for retrieving IOC attributes */
+ res_info[BNA_RES_MEM_T_ATTR].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+ res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.len =
+ ALIGN(bfa_nw_ioc_meminfo(), PAGE_SIZE);
+
+ /* Virtual memory for retreiving fw_trc */
+ res_info[BNA_RES_MEM_T_FWTRC].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.num = 0;
+ res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.len = 0;
+
+ /* DMA memory for retreiving stats */
+ res_info[BNA_RES_MEM_T_STATS].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.len =
+ ALIGN(sizeof(struct bfi_enet_stats),
+ PAGE_SIZE);
+}
+
+void
+bna_mod_res_req(struct bna *bna, struct bna_res_info *res_info)
+{
+ struct bna_attr *attr = &bna->ioceth.attr;
+
+ /* Virtual memory for Tx objects - stored by Tx module */
+ res_info[BNA_MOD_RES_MEM_T_TX_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_MOD_RES_MEM_T_TX_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_MOD_RES_MEM_T_TX_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_MOD_RES_MEM_T_TX_ARRAY].res_u.mem_info.len =
+ attr->num_txq * sizeof(struct bna_tx);
+
+ /* Virtual memory for TxQ - stored by Tx module */
+ res_info[BNA_MOD_RES_MEM_T_TXQ_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_MOD_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_MOD_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_MOD_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.len =
+ attr->num_txq * sizeof(struct bna_txq);
+
+ /* Virtual memory for Rx objects - stored by Rx module */
+ res_info[BNA_MOD_RES_MEM_T_RX_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_MOD_RES_MEM_T_RX_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_MOD_RES_MEM_T_RX_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_MOD_RES_MEM_T_RX_ARRAY].res_u.mem_info.len =
+ attr->num_rxp * sizeof(struct bna_rx);
+
+ /* Virtual memory for RxPath - stored by Rx module */
+ res_info[BNA_MOD_RES_MEM_T_RXP_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_MOD_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_MOD_RES_MEM_T_RXP_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_MOD_RES_MEM_T_RXP_ARRAY].res_u.mem_info.len =
+ attr->num_rxp * sizeof(struct bna_rxp);
+
+ /* Virtual memory for RxQ - stored by Rx module */
+ res_info[BNA_MOD_RES_MEM_T_RXQ_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_MOD_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_MOD_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_MOD_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.len =
+ (attr->num_rxp * 2) * sizeof(struct bna_rxq);
+
+ /* Virtual memory for Unicast MAC address - stored by ucam module */
+ res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.len =
+ attr->num_ucmac * sizeof(struct bna_mac);
+
+ /* Virtual memory for Multicast MAC address - stored by mcam module */
+ res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.len =
+ attr->num_mcmac * sizeof(struct bna_mac);
+
+ /* Virtual memory for Multicast handle - stored by mcam module */
+ res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_u.mem_info.len =
+ attr->num_mcmac * sizeof(struct bna_mcam_handle);
+}
+
+void
+bna_init(struct bna *bna, struct bnad *bnad,
+ struct bfa_pcidev *pcidev, struct bna_res_info *res_info)
+{
+ bna->bnad = bnad;
+ bna->pcidev = *pcidev;
+
+ bna->stats.hw_stats_kva = (struct bfi_enet_stats *)
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].kva;
+ bna->stats.hw_stats_dma.msb =
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.msb;
+ bna->stats.hw_stats_dma.lsb =
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.lsb;
+
+ bna_reg_addr_init(bna, &bna->pcidev);
+
+ /* Also initializes diag, cee, sfp, phy_port, msgq */
+ bna_ioceth_init(&bna->ioceth, bna, res_info);
+
+ bna_enet_init(&bna->enet, bna);
+ bna_ethport_init(&bna->ethport, bna);
+}
+
+void
+bna_mod_init(struct bna *bna, struct bna_res_info *res_info)
+{
+ bna_tx_mod_init(&bna->tx_mod, bna, res_info);
+
+ bna_rx_mod_init(&bna->rx_mod, bna, res_info);
+
+ bna_ucam_mod_init(&bna->ucam_mod, bna, res_info);
+
+ bna_mcam_mod_init(&bna->mcam_mod, bna, res_info);
+
+ bna->default_mode_rid = BFI_INVALID_RID;
+ bna->promisc_rid = BFI_INVALID_RID;
+
+ bna->mod_flags |= BNA_MOD_F_INIT_DONE;
+}
+
+void
+bna_uninit(struct bna *bna)
+{
+ if (bna->mod_flags & BNA_MOD_F_INIT_DONE) {
+ bna_mcam_mod_uninit(&bna->mcam_mod);
+ bna_ucam_mod_uninit(&bna->ucam_mod);
+ bna_rx_mod_uninit(&bna->rx_mod);
+ bna_tx_mod_uninit(&bna->tx_mod);
+ bna->mod_flags &= ~BNA_MOD_F_INIT_DONE;
+ }
+
+ bna_stats_mod_uninit(&bna->stats_mod);
+ bna_ethport_uninit(&bna->ethport);
+ bna_enet_uninit(&bna->enet);
+
+ bna_ioceth_uninit(&bna->ioceth);
+
+ bna->bnad = NULL;
+}
+
+int
+bna_num_txq_set(struct bna *bna, int num_txq)
+{
+ if (bna->ioceth.attr.fw_query_complete &&
+ (num_txq <= bna->ioceth.attr.num_txq)) {
+ bna->ioceth.attr.num_txq = num_txq;
+ return BNA_CB_SUCCESS;
+ }
+
+ return BNA_CB_FAIL;
+}
+
+int
+bna_num_rxp_set(struct bna *bna, int num_rxp)
+{
+ if (bna->ioceth.attr.fw_query_complete &&
+ (num_rxp <= bna->ioceth.attr.num_rxp)) {
+ bna->ioceth.attr.num_rxp = num_rxp;
+ return BNA_CB_SUCCESS;
+ }
+
+ return BNA_CB_FAIL;
+}
+
+struct bna_mac *
+bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod)
+{
+ struct list_head *qe;
+
+ if (list_empty(&ucam_mod->free_q))
+ return NULL;
+
+ bfa_q_deq(&ucam_mod->free_q, &qe);
+
+ return (struct bna_mac *)qe;
+}
+
+void
+bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, struct bna_mac *mac)
+{
+ list_add_tail(&mac->qe, &ucam_mod->free_q);
+}
+
+struct bna_mac *
+bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod)
+{
+ struct list_head *qe;
+
+ if (list_empty(&mcam_mod->free_q))
+ return NULL;
+
+ bfa_q_deq(&mcam_mod->free_q, &qe);
+
+ return (struct bna_mac *)qe;
+}
+
+void
+bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, struct bna_mac *mac)
+{
+ list_add_tail(&mac->qe, &mcam_mod->free_q);
+}
+
+struct bna_mcam_handle *
+bna_mcam_mod_handle_get(struct bna_mcam_mod *mcam_mod)
+{
+ struct list_head *qe;
+
+ if (list_empty(&mcam_mod->free_handle_q))
+ return NULL;
+
+ bfa_q_deq(&mcam_mod->free_handle_q, &qe);
+
+ return (struct bna_mcam_handle *)qe;
+}
+
+void
+bna_mcam_mod_handle_put(struct bna_mcam_mod *mcam_mod,
+ struct bna_mcam_handle *handle)
+{
+ list_add_tail(&handle->qe, &mcam_mod->free_handle_q);
+}
+
+void
+bna_hw_stats_get(struct bna *bna)
+{
+ if (!bna->stats_mod.ioc_ready) {
+ bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
+ return;
+ }
+ if (bna->stats_mod.stats_get_busy) {
+ bnad_cb_stats_get(bna->bnad, BNA_CB_BUSY, &bna->stats);
+ return;
+ }
+
+ bna_bfi_stats_get(bna);
+}
diff --git a/drivers/net/ethernet/brocade/bna/bna_hw_defs.h b/drivers/net/ethernet/brocade/bna/bna_hw_defs.h
new file mode 100644
index 000000000000..4c6aab2a9534
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/bna_hw_defs.h
@@ -0,0 +1,422 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/**
+ * File for interrupt macros and functions
+ */
+
+#ifndef __BNA_HW_DEFS_H__
+#define __BNA_HW_DEFS_H__
+
+#include "bfi_reg.h"
+
+/**
+ *
+ * SW imposed limits
+ *
+ */
+#define BFI_ENET_DEF_TXQ 1
+#define BFI_ENET_DEF_RXP 1
+#define BFI_ENET_DEF_UCAM 1
+#define BFI_ENET_DEF_RITSZ 1
+
+#define BFI_ENET_MAX_MCAM 256
+
+#define BFI_INVALID_RID -1
+
+#define BFI_IBIDX_SIZE 4
+
+#define BFI_VLAN_WORD_SHIFT 5 /* 32 bits */
+#define BFI_VLAN_WORD_MASK 0x1F
+#define BFI_VLAN_BLOCK_SHIFT 9 /* 512 bits */
+#define BFI_VLAN_BMASK_ALL 0xFF
+
+#define BFI_COALESCING_TIMER_UNIT 5 /* 5us */
+#define BFI_MAX_COALESCING_TIMEO 0xFF /* in 5us units */
+#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_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 */
+
+#define BFI_TXQ_WI_SIZE 64 /* bytes */
+#define BFI_RXQ_WI_SIZE 8 /* bytes */
+#define BFI_CQ_WI_SIZE 16 /* bytes */
+#define BFI_TX_MAX_WRR_QUOTA 0xFFF
+
+#define BFI_TX_MAX_VECTORS_PER_WI 4
+#define BFI_TX_MAX_VECTORS_PER_PKT 0xFF
+#define BFI_TX_MAX_DATA_PER_VECTOR 0xFFFF
+#define BFI_TX_MAX_DATA_PER_PKT 0xFFFFFF
+
+/* Small Q buffer size */
+#define BFI_SMALL_RXBUF_SIZE 128
+
+#define BFI_TX_MAX_PRIO 8
+#define BFI_TX_PRIO_MAP_ALL 0xFF
+
+/*
+ *
+ * Register definitions and macros
+ *
+ */
+
+#define BNA_PCI_REG_CT_ADDRSZ (0x40000)
+
+#define ct_reg_addr_init(_bna, _pcidev) \
+{ \
+ struct bna_reg_offset reg_offset[] = \
+ {{HOSTFN0_INT_STATUS, HOSTFN0_INT_MSK}, \
+ {HOSTFN1_INT_STATUS, HOSTFN1_INT_MSK}, \
+ {HOSTFN2_INT_STATUS, HOSTFN2_INT_MSK}, \
+ {HOSTFN3_INT_STATUS, HOSTFN3_INT_MSK} }; \
+ \
+ (_bna)->regs.fn_int_status = (_pcidev)->pci_bar_kva + \
+ reg_offset[(_pcidev)->pci_func].fn_int_status;\
+ (_bna)->regs.fn_int_mask = (_pcidev)->pci_bar_kva + \
+ reg_offset[(_pcidev)->pci_func].fn_int_mask;\
+}
+
+#define ct_bit_defn_init(_bna, _pcidev) \
+{ \
+ (_bna)->bits.mbox_status_bits = (__HFN_INT_MBOX_LPU0 | \
+ __HFN_INT_MBOX_LPU1); \
+ (_bna)->bits.mbox_mask_bits = (__HFN_INT_MBOX_LPU0 | \
+ __HFN_INT_MBOX_LPU1); \
+ (_bna)->bits.error_status_bits = (__HFN_INT_ERR_MASK); \
+ (_bna)->bits.error_mask_bits = (__HFN_INT_ERR_MASK); \
+ (_bna)->bits.halt_status_bits = __HFN_INT_LL_HALT; \
+ (_bna)->bits.halt_mask_bits = __HFN_INT_LL_HALT; \
+}
+
+#define ct2_reg_addr_init(_bna, _pcidev) \
+{ \
+ (_bna)->regs.fn_int_status = (_pcidev)->pci_bar_kva + \
+ CT2_HOSTFN_INT_STATUS; \
+ (_bna)->regs.fn_int_mask = (_pcidev)->pci_bar_kva + \
+ CT2_HOSTFN_INTR_MASK; \
+}
+
+#define ct2_bit_defn_init(_bna, _pcidev) \
+{ \
+ (_bna)->bits.mbox_status_bits = (__HFN_INT_MBOX_LPU0_CT2 | \
+ __HFN_INT_MBOX_LPU1_CT2); \
+ (_bna)->bits.mbox_mask_bits = (__HFN_INT_MBOX_LPU0_CT2 | \
+ __HFN_INT_MBOX_LPU1_CT2); \
+ (_bna)->bits.error_status_bits = (__HFN_INT_ERR_MASK_CT2); \
+ (_bna)->bits.error_mask_bits = (__HFN_INT_ERR_MASK_CT2); \
+ (_bna)->bits.halt_status_bits = __HFN_INT_CPQ_HALT_CT2; \
+ (_bna)->bits.halt_mask_bits = __HFN_INT_CPQ_HALT_CT2; \
+}
+
+#define bna_reg_addr_init(_bna, _pcidev) \
+{ \
+ switch ((_pcidev)->device_id) { \
+ case PCI_DEVICE_ID_BROCADE_CT: \
+ ct_reg_addr_init((_bna), (_pcidev)); \
+ ct_bit_defn_init((_bna), (_pcidev)); \
+ break; \
+ case BFA_PCI_DEVICE_ID_CT2: \
+ ct2_reg_addr_init((_bna), (_pcidev)); \
+ ct2_bit_defn_init((_bna), (_pcidev)); \
+ break; \
+ } \
+}
+
+#define bna_port_id_get(_bna) ((_bna)->ioceth.ioc.port_id)
+/**
+ *
+ * Interrupt related bits, flags and macros
+ *
+ */
+
+#define IB_STATUS_BITS 0x0000ffff
+
+#define BNA_IS_MBOX_INTR(_bna, _intr_status) \
+ ((_intr_status) & (_bna)->bits.mbox_status_bits)
+
+#define BNA_IS_HALT_INTR(_bna, _intr_status) \
+ ((_intr_status) & (_bna)->bits.halt_status_bits)
+
+#define BNA_IS_ERR_INTR(_bna, _intr_status) \
+ ((_intr_status) & (_bna)->bits.error_status_bits)
+
+#define BNA_IS_MBOX_ERR_INTR(_bna, _intr_status) \
+ (BNA_IS_MBOX_INTR(_bna, _intr_status) | \
+ BNA_IS_ERR_INTR(_bna, _intr_status))
+
+#define BNA_IS_INTX_DATA_INTR(_intr_status) \
+ ((_intr_status) & IB_STATUS_BITS)
+
+#define bna_halt_clear(_bna) \
+do { \
+ u32 init_halt; \
+ init_halt = readl((_bna)->ioceth.ioc.ioc_regs.ll_halt); \
+ init_halt &= ~__FW_INIT_HALT_P; \
+ writel(init_halt, (_bna)->ioceth.ioc.ioc_regs.ll_halt); \
+ init_halt = readl((_bna)->ioceth.ioc.ioc_regs.ll_halt); \
+} while (0)
+
+#define bna_intx_disable(_bna, _cur_mask) \
+{ \
+ (_cur_mask) = readl((_bna)->regs.fn_int_mask); \
+ writel(0xffffffff, (_bna)->regs.fn_int_mask); \
+}
+
+#define bna_intx_enable(bna, new_mask) \
+ writel((new_mask), (bna)->regs.fn_int_mask)
+#define bna_mbox_intr_disable(bna) \
+do { \
+ u32 mask; \
+ mask = readl((bna)->regs.fn_int_mask); \
+ writel((mask | (bna)->bits.mbox_mask_bits | \
+ (bna)->bits.error_mask_bits), (bna)->regs.fn_int_mask); \
+ mask = readl((bna)->regs.fn_int_mask); \
+} while (0)
+
+#define bna_mbox_intr_enable(bna) \
+do { \
+ u32 mask; \
+ mask = readl((bna)->regs.fn_int_mask); \
+ writel((mask & ~((bna)->bits.mbox_mask_bits | \
+ (bna)->bits.error_mask_bits)), (bna)->regs.fn_int_mask);\
+ mask = readl((bna)->regs.fn_int_mask); \
+} while (0)
+
+#define bna_intr_status_get(_bna, _status) \
+{ \
+ (_status) = readl((_bna)->regs.fn_int_status); \
+ if (_status) { \
+ writel(((_status) & ~(_bna)->bits.mbox_status_bits), \
+ (_bna)->regs.fn_int_status); \
+ } \
+}
+
+/*
+ * MAX ACK EVENTS : No. of acks that can be accumulated in driver,
+ * before acking to h/w. The no. of bits is 16 in the doorbell register,
+ * however we keep this limited to 15 bits.
+ * This is because around the edge of 64K boundary (16 bits), one
+ * single poll can make the accumulated ACK counter cross the 64K boundary,
+ * causing problems, when we try to ack with a value greater than 64K.
+ * 15 bits (32K) should be large enough to accumulate, anyways, and the max.
+ * acked events to h/w can be (32K + max poll weight) (currently 64).
+ */
+#define BNA_IB_MAX_ACK_EVENTS (1 << 15)
+
+/* These macros build the data portion of the TxQ/RxQ doorbell */
+#define BNA_DOORBELL_Q_PRD_IDX(_pi) (0x80000000 | (_pi))
+#define BNA_DOORBELL_Q_STOP (0x40000000)
+
+/* These macros build the data portion of the IB doorbell */
+#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
+ (0x80000000 | ((_timeout) << 16) | (_events))
+#define BNA_DOORBELL_IB_INT_DISABLE (0x40000000)
+
+/* Set the coalescing timer for the given ib */
+#define bna_ib_coalescing_timer_set(_i_dbell, _cls_timer) \
+ ((_i_dbell)->doorbell_ack = BNA_DOORBELL_IB_INT_ACK((_cls_timer), 0));
+
+/* Acks 'events' # of events for a given ib while disabling interrupts */
+#define bna_ib_ack_disable_irq(_i_dbell, _events) \
+ (writel(BNA_DOORBELL_IB_INT_ACK(0, (_events)), \
+ (_i_dbell)->doorbell_addr));
+
+/* Acks 'events' # of events for a given ib */
+#define bna_ib_ack(_i_dbell, _events) \
+ (writel(((_i_dbell)->doorbell_ack | (_events)), \
+ (_i_dbell)->doorbell_addr));
+
+#define bna_ib_start(_bna, _ib, _is_regular) \
+{ \
+ u32 intx_mask; \
+ struct bna_ib *ib = _ib; \
+ if ((ib->intr_type == BNA_INTR_T_INTX)) { \
+ bna_intx_disable((_bna), intx_mask); \
+ intx_mask &= ~(ib->intr_vector); \
+ bna_intx_enable((_bna), intx_mask); \
+ } \
+ bna_ib_coalescing_timer_set(&ib->door_bell, \
+ ib->coalescing_timeo); \
+ if (_is_regular) \
+ bna_ib_ack(&ib->door_bell, 0); \
+}
+
+#define bna_ib_stop(_bna, _ib) \
+{ \
+ u32 intx_mask; \
+ struct bna_ib *ib = _ib; \
+ writel(BNA_DOORBELL_IB_INT_DISABLE, \
+ ib->door_bell.doorbell_addr); \
+ if (ib->intr_type == BNA_INTR_T_INTX) { \
+ bna_intx_disable((_bna), intx_mask); \
+ intx_mask |= ib->intr_vector; \
+ bna_intx_enable((_bna), intx_mask); \
+ } \
+}
+
+#define bna_txq_prod_indx_doorbell(_tcb) \
+ (writel(BNA_DOORBELL_Q_PRD_IDX((_tcb)->producer_index), \
+ (_tcb)->q_dbell));
+
+#define bna_rxq_prod_indx_doorbell(_rcb) \
+ (writel(BNA_DOORBELL_Q_PRD_IDX((_rcb)->producer_index), \
+ (_rcb)->q_dbell));
+
+/**
+ *
+ * TxQ, RxQ, CQ related bits, offsets, macros
+ *
+ */
+
+/* TxQ Entry Opcodes */
+#define BNA_TXQ_WI_SEND (0x402) /* Single Frame Transmission */
+#define BNA_TXQ_WI_SEND_LSO (0x403) /* Multi-Frame Transmission */
+#define BNA_TXQ_WI_EXTENSION (0x104) /* Extension WI */
+
+/* TxQ Entry Control Flags */
+#define BNA_TXQ_WI_CF_FCOE_CRC (1 << 8)
+#define BNA_TXQ_WI_CF_IPID_MODE (1 << 5)
+#define BNA_TXQ_WI_CF_INS_PRIO (1 << 4)
+#define BNA_TXQ_WI_CF_INS_VLAN (1 << 3)
+#define BNA_TXQ_WI_CF_UDP_CKSUM (1 << 2)
+#define BNA_TXQ_WI_CF_TCP_CKSUM (1 << 1)
+#define BNA_TXQ_WI_CF_IP_CKSUM (1 << 0)
+
+#define BNA_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
+ (((_hdr_size) << 10) | ((_offset) & 0x3FF))
+
+/*
+ * Completion Q defines
+ */
+/* CQ Entry Flags */
+#define BNA_CQ_EF_MAC_ERROR (1 << 0)
+#define BNA_CQ_EF_FCS_ERROR (1 << 1)
+#define BNA_CQ_EF_TOO_LONG (1 << 2)
+#define BNA_CQ_EF_FC_CRC_OK (1 << 3)
+
+#define BNA_CQ_EF_RSVD1 (1 << 4)
+#define BNA_CQ_EF_L4_CKSUM_OK (1 << 5)
+#define BNA_CQ_EF_L3_CKSUM_OK (1 << 6)
+#define BNA_CQ_EF_HDS_HEADER (1 << 7)
+
+#define BNA_CQ_EF_UDP (1 << 8)
+#define BNA_CQ_EF_TCP (1 << 9)
+#define BNA_CQ_EF_IP_OPTIONS (1 << 10)
+#define BNA_CQ_EF_IPV6 (1 << 11)
+
+#define BNA_CQ_EF_IPV4 (1 << 12)
+#define BNA_CQ_EF_VLAN (1 << 13)
+#define BNA_CQ_EF_RSS (1 << 14)
+#define BNA_CQ_EF_RSVD2 (1 << 15)
+
+#define BNA_CQ_EF_MCAST_MATCH (1 << 16)
+#define BNA_CQ_EF_MCAST (1 << 17)
+#define BNA_CQ_EF_BCAST (1 << 18)
+#define BNA_CQ_EF_REMOTE (1 << 19)
+
+#define BNA_CQ_EF_LOCAL (1 << 20)
+
+/**
+ *
+ * Data structures
+ *
+ */
+
+struct bna_reg_offset {
+ u32 fn_int_status;
+ u32 fn_int_mask;
+};
+
+struct bna_bit_defn {
+ u32 mbox_status_bits;
+ u32 mbox_mask_bits;
+ u32 error_status_bits;
+ u32 error_mask_bits;
+ u32 halt_status_bits;
+ u32 halt_mask_bits;
+};
+
+struct bna_reg {
+ void __iomem *fn_int_status;
+ void __iomem *fn_int_mask;
+};
+
+/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */
+struct bna_dma_addr {
+ u32 msb;
+ u32 lsb;
+};
+
+struct bna_txq_wi_vector {
+ u16 reserved;
+ u16 length; /* Only 14 LSB are valid */
+ struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */
+};
+
+/**
+ * TxQ Entry Structure
+ *
+ * BEWARE: Load values into this structure with correct endianess.
+ */
+struct bna_txq_entry {
+ union {
+ struct {
+ u8 reserved;
+ u8 num_vectors; /* number of vectors present */
+ u16 opcode; /* Either */
+ /* BNA_TXQ_WI_SEND or */
+ /* BNA_TXQ_WI_SEND_LSO */
+ u16 flags; /* OR of all the flags */
+ u16 l4_hdr_size_n_offset;
+ u16 vlan_tag;
+ u16 lso_mss; /* Only 14 LSB are valid */
+ u32 frame_length; /* Only 24 LSB are valid */
+ } wi;
+
+ struct {
+ u16 reserved;
+ u16 opcode; /* Must be */
+ /* BNA_TXQ_WI_EXTENSION */
+ u32 reserved2[3]; /* Place holder for */
+ /* removed vector (12 bytes) */
+ } wi_ext;
+ } hdr;
+ struct bna_txq_wi_vector vector[4];
+};
+
+/* RxQ Entry Structure */
+struct bna_rxq_entry { /* Rx-Buffer */
+ struct bna_dma_addr host_addr; /* Rx-Buffer DMA address */
+};
+
+/* CQ Entry Structure */
+struct bna_cq_entry {
+ u32 flags;
+ u16 vlan_tag;
+ u16 length;
+ u32 rss_hash;
+ u8 valid;
+ u8 reserved1;
+ u8 reserved2;
+ u8 rxq_id;
+};
+
+#endif /* __BNA_HW_DEFS_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
new file mode 100644
index 000000000000..276fcb589f4b
--- /dev/null
+++ b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c
@@ -0,0 +1,3798 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include "bna.h"
+#include "bfi.h"
+
+/**
+ * IB
+ */
+static void
+bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo)
+{
+ ib->coalescing_timeo = coalescing_timeo;
+ ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
+ (u32)ib->coalescing_timeo, 0);
+}
+
+/**
+ * RXF
+ */
+
+#define bna_rxf_vlan_cfg_soft_reset(rxf) \
+do { \
+ (rxf)->vlan_pending_bitmask = (u8)BFI_VLAN_BMASK_ALL; \
+ (rxf)->vlan_strip_pending = true; \
+} while (0)
+
+#define bna_rxf_rss_cfg_soft_reset(rxf) \
+do { \
+ if ((rxf)->rss_status == BNA_STATUS_T_ENABLED) \
+ (rxf)->rss_pending = (BNA_RSS_F_RIT_PENDING | \
+ BNA_RSS_F_CFG_PENDING | \
+ BNA_RSS_F_STATUS_PENDING); \
+} while (0)
+
+static int bna_rxf_cfg_apply(struct bna_rxf *rxf);
+static void bna_rxf_cfg_reset(struct bna_rxf *rxf);
+static int bna_rxf_fltr_clear(struct bna_rxf *rxf);
+static int bna_rxf_ucast_cfg_apply(struct bna_rxf *rxf);
+static int bna_rxf_promisc_cfg_apply(struct bna_rxf *rxf);
+static int bna_rxf_allmulti_cfg_apply(struct bna_rxf *rxf);
+static int bna_rxf_vlan_strip_cfg_apply(struct bna_rxf *rxf);
+static int bna_rxf_ucast_cfg_reset(struct bna_rxf *rxf,
+ enum bna_cleanup_type cleanup);
+static int bna_rxf_promisc_cfg_reset(struct bna_rxf *rxf,
+ enum bna_cleanup_type cleanup);
+static int bna_rxf_allmulti_cfg_reset(struct bna_rxf *rxf,
+ enum bna_cleanup_type cleanup);
+
+bfa_fsm_state_decl(bna_rxf, stopped, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, paused, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, cfg_wait, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, started, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, fltr_clr_wait, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, last_resp_wait, struct bna_rxf,
+ enum bna_rxf_event);
+
+static void
+bna_rxf_sm_stopped_entry(struct bna_rxf *rxf)
+{
+ call_rxf_stop_cbfn(rxf);
+}
+
+static void
+bna_rxf_sm_stopped(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_START:
+ if (rxf->flags & BNA_RXF_F_PAUSED) {
+ bfa_fsm_set_state(rxf, bna_rxf_sm_paused);
+ call_rxf_start_cbfn(rxf);
+ } else
+ bfa_fsm_set_state(rxf, bna_rxf_sm_cfg_wait);
+ break;
+
+ case RXF_E_STOP:
+ call_rxf_stop_cbfn(rxf);
+ break;
+
+ case RXF_E_FAIL:
+ /* No-op */
+ break;
+
+ case RXF_E_CONFIG:
+ call_rxf_cam_fltr_cbfn(rxf);
+ break;
+
+ case RXF_E_PAUSE:
+ rxf->flags |= BNA_RXF_F_PAUSED;
+ call_rxf_pause_cbfn(rxf);
+ break;
+
+ case RXF_E_RESUME:
+ rxf->flags &= ~BNA_RXF_F_PAUSED;
+ call_rxf_resume_cbfn(rxf);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_rxf_sm_paused_entry(struct bna_rxf *rxf)
+{
+ call_rxf_pause_cbfn(rxf);
+}
+
+static void
+bna_rxf_sm_paused(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_STOP:
+ case RXF_E_FAIL:
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_CONFIG:
+ call_rxf_cam_fltr_cbfn(rxf);
+ break;
+
+ case RXF_E_RESUME:
+ rxf->flags &= ~BNA_RXF_F_PAUSED;
+ bfa_fsm_set_state(rxf, bna_rxf_sm_cfg_wait);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_rxf_sm_cfg_wait_entry(struct bna_rxf *rxf)
+{
+ if (!bna_rxf_cfg_apply(rxf)) {
+ /* No more pending config updates */
+ bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+ }
+}
+
+static void
+bna_rxf_sm_cfg_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_STOP:
+ bfa_fsm_set_state(rxf, bna_rxf_sm_last_resp_wait);
+ break;
+
+ case RXF_E_FAIL:
+ bna_rxf_cfg_reset(rxf);
+ call_rxf_start_cbfn(rxf);
+ call_rxf_cam_fltr_cbfn(rxf);
+ call_rxf_resume_cbfn(rxf);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_CONFIG:
+ /* No-op */
+ break;
+
+ case RXF_E_PAUSE:
+ rxf->flags |= BNA_RXF_F_PAUSED;
+ call_rxf_start_cbfn(rxf);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_fltr_clr_wait);
+ break;
+
+ case RXF_E_FW_RESP:
+ if (!bna_rxf_cfg_apply(rxf)) {
+ /* No more pending config updates */
+ bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+ }
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_rxf_sm_started_entry(struct bna_rxf *rxf)
+{
+ call_rxf_start_cbfn(rxf);
+ call_rxf_cam_fltr_cbfn(rxf);
+ call_rxf_resume_cbfn(rxf);
+}
+
+static void
+bna_rxf_sm_started(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_STOP:
+ case RXF_E_FAIL:
+ bna_rxf_cfg_reset(rxf);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_CONFIG:
+ bfa_fsm_set_state(rxf, bna_rxf_sm_cfg_wait);
+ break;
+
+ case RXF_E_PAUSE:
+ rxf->flags |= BNA_RXF_F_PAUSED;
+ if (!bna_rxf_fltr_clear(rxf))
+ bfa_fsm_set_state(rxf, bna_rxf_sm_paused);
+ else
+ bfa_fsm_set_state(rxf, bna_rxf_sm_fltr_clr_wait);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_rxf_sm_fltr_clr_wait_entry(struct bna_rxf *rxf)
+{
+}
+
+static void
+bna_rxf_sm_fltr_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_FAIL:
+ bna_rxf_cfg_reset(rxf);
+ call_rxf_pause_cbfn(rxf);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_FW_RESP:
+ if (!bna_rxf_fltr_clear(rxf)) {
+ /* No more pending CAM entries to clear */
+ bfa_fsm_set_state(rxf, bna_rxf_sm_paused);
+ }
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_rxf_sm_last_resp_wait_entry(struct bna_rxf *rxf)
+{
+}
+
+static void
+bna_rxf_sm_last_resp_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_FAIL:
+ case RXF_E_FW_RESP:
+ bna_rxf_cfg_reset(rxf);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_bfi_ucast_req(struct bna_rxf *rxf, struct bna_mac *mac,
+ enum bfi_enet_h2i_msgs req_type)
+{
+ struct bfi_enet_ucast_req *req = &rxf->bfi_enet_cmd.ucast_req;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET, req_type, 0, rxf->rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_ucast_req)));
+ memcpy(&req->mac_addr, &mac->addr, sizeof(mac_t));
+ bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_ucast_req), &req->mh);
+ bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_mcast_add_req(struct bna_rxf *rxf, struct bna_mac *mac)
+{
+ struct bfi_enet_mcast_add_req *req =
+ &rxf->bfi_enet_cmd.mcast_add_req;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET, BFI_ENET_H2I_MAC_MCAST_ADD_REQ,
+ 0, rxf->rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_mcast_add_req)));
+ memcpy(&req->mac_addr, &mac->addr, sizeof(mac_t));
+ bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_mcast_add_req), &req->mh);
+ bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_mcast_del_req(struct bna_rxf *rxf, u16 handle)
+{
+ struct bfi_enet_mcast_del_req *req =
+ &rxf->bfi_enet_cmd.mcast_del_req;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET, BFI_ENET_H2I_MAC_MCAST_DEL_REQ,
+ 0, rxf->rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_mcast_del_req)));
+ req->handle = htons(handle);
+ bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_mcast_del_req), &req->mh);
+ bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_mcast_filter_req(struct bna_rxf *rxf, enum bna_status status)
+{
+ struct bfi_enet_enable_req *req = &rxf->bfi_enet_cmd.req;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_MAC_MCAST_FILTER_REQ, 0, rxf->rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+ req->enable = status;
+ bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_enable_req), &req->mh);
+ bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_rx_promisc_req(struct bna_rxf *rxf, enum bna_status status)
+{
+ struct bfi_enet_enable_req *req = &rxf->bfi_enet_cmd.req;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_RX_PROMISCUOUS_REQ, 0, rxf->rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+ req->enable = status;
+ bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_enable_req), &req->mh);
+ bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_rx_vlan_filter_set(struct bna_rxf *rxf, u8 block_idx)
+{
+ struct bfi_enet_rx_vlan_req *req = &rxf->bfi_enet_cmd.vlan_req;
+ int i;
+ int j;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_RX_VLAN_SET_REQ, 0, rxf->rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_rx_vlan_req)));
+ req->block_idx = block_idx;
+ for (i = 0; i < (BFI_ENET_VLAN_BLOCK_SIZE / 32); i++) {
+ j = (block_idx * (BFI_ENET_VLAN_BLOCK_SIZE / 32)) + i;
+ if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED)
+ req->bit_mask[i] =
+ htonl(rxf->vlan_filter_table[j]);
+ else
+ req->bit_mask[i] = 0xFFFFFFFF;
+ }
+ bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_rx_vlan_req), &req->mh);
+ bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_vlan_strip_enable(struct bna_rxf *rxf)
+{
+ struct bfi_enet_enable_req *req = &rxf->bfi_enet_cmd.req;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_RX_VLAN_STRIP_ENABLE_REQ, 0, rxf->rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+ req->enable = rxf->vlan_strip_status;
+ bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_enable_req), &req->mh);
+ bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_rit_cfg(struct bna_rxf *rxf)
+{
+ struct bfi_enet_rit_req *req = &rxf->bfi_enet_cmd.rit_req;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_RIT_CFG_REQ, 0, rxf->rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_rit_req)));
+ req->size = htons(rxf->rit_size);
+ memcpy(&req->table[0], rxf->rit, rxf->rit_size);
+ bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_rit_req), &req->mh);
+ bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_rss_cfg(struct bna_rxf *rxf)
+{
+ struct bfi_enet_rss_cfg_req *req = &rxf->bfi_enet_cmd.rss_req;
+ int i;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_RSS_CFG_REQ, 0, rxf->rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_rss_cfg_req)));
+ req->cfg.type = rxf->rss_cfg.hash_type;
+ req->cfg.mask = rxf->rss_cfg.hash_mask;
+ for (i = 0; i < BFI_ENET_RSS_KEY_LEN; i++)
+ req->cfg.key[i] =
+ htonl(rxf->rss_cfg.toeplitz_hash_key[i]);
+ bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_rss_cfg_req), &req->mh);
+ bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+static void
+bna_bfi_rss_enable(struct bna_rxf *rxf)
+{
+ struct bfi_enet_enable_req *req = &rxf->bfi_enet_cmd.req;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_RSS_ENABLE_REQ, 0, rxf->rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_enable_req)));
+ req->enable = rxf->rss_status;
+ bfa_msgq_cmd_set(&rxf->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_enable_req), &req->mh);
+ bfa_msgq_cmd_post(&rxf->rx->bna->msgq, &rxf->msgq_cmd);
+}
+
+/* This function gets the multicast MAC that has already been added to CAM */
+static struct bna_mac *
+bna_rxf_mcmac_get(struct bna_rxf *rxf, u8 *mac_addr)
+{
+ struct bna_mac *mac;
+ struct list_head *qe;
+
+ list_for_each(qe, &rxf->mcast_active_q) {
+ mac = (struct bna_mac *)qe;
+ if (BNA_MAC_IS_EQUAL(&mac->addr, mac_addr))
+ return mac;
+ }
+
+ list_for_each(qe, &rxf->mcast_pending_del_q) {
+ mac = (struct bna_mac *)qe;
+ if (BNA_MAC_IS_EQUAL(&mac->addr, mac_addr))
+ return mac;
+ }
+
+ return NULL;
+}
+
+static struct bna_mcam_handle *
+bna_rxf_mchandle_get(struct bna_rxf *rxf, int handle)
+{
+ struct bna_mcam_handle *mchandle;
+ struct list_head *qe;
+
+ list_for_each(qe, &rxf->mcast_handle_q) {
+ mchandle = (struct bna_mcam_handle *)qe;
+ if (mchandle->handle == handle)
+ return mchandle;
+ }
+
+ return NULL;
+}
+
+static void
+bna_rxf_mchandle_attach(struct bna_rxf *rxf, u8 *mac_addr, int handle)
+{
+ struct bna_mac *mcmac;
+ struct bna_mcam_handle *mchandle;
+
+ mcmac = bna_rxf_mcmac_get(rxf, mac_addr);
+ mchandle = bna_rxf_mchandle_get(rxf, handle);
+ if (mchandle == NULL) {
+ mchandle = bna_mcam_mod_handle_get(&rxf->rx->bna->mcam_mod);
+ mchandle->handle = handle;
+ mchandle->refcnt = 0;
+ list_add_tail(&mchandle->qe, &rxf->mcast_handle_q);
+ }
+ mchandle->refcnt++;
+ mcmac->handle = mchandle;
+}
+
+static int
+bna_rxf_mcast_del(struct bna_rxf *rxf, struct bna_mac *mac,
+ enum bna_cleanup_type cleanup)
+{
+ struct bna_mcam_handle *mchandle;
+ int ret = 0;
+
+ mchandle = mac->handle;
+ if (mchandle == NULL)
+ return ret;
+
+ mchandle->refcnt--;
+ if (mchandle->refcnt == 0) {
+ if (cleanup == BNA_HARD_CLEANUP) {
+ bna_bfi_mcast_del_req(rxf, mchandle->handle);
+ ret = 1;
+ }
+ list_del(&mchandle->qe);
+ bfa_q_qe_init(&mchandle->qe);
+ bna_mcam_mod_handle_put(&rxf->rx->bna->mcam_mod, mchandle);
+ }
+ mac->handle = NULL;
+
+ return ret;
+}
+
+static int
+bna_rxf_mcast_cfg_apply(struct bna_rxf *rxf)
+{
+ struct bna_mac *mac = NULL;
+ struct list_head *qe;
+ int ret;
+
+ /* Delete multicast entries previousely added */
+ while (!list_empty(&rxf->mcast_pending_del_q)) {
+ bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ ret = bna_rxf_mcast_del(rxf, mac, BNA_HARD_CLEANUP);
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ if (ret)
+ return ret;
+ }
+
+ /* Add multicast entries */
+ if (!list_empty(&rxf->mcast_pending_add_q)) {
+ bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ list_add_tail(&mac->qe, &rxf->mcast_active_q);
+ bna_bfi_mcast_add_req(rxf, mac);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+bna_rxf_vlan_cfg_apply(struct bna_rxf *rxf)
+{
+ u8 vlan_pending_bitmask;
+ int block_idx = 0;
+
+ if (rxf->vlan_pending_bitmask) {
+ vlan_pending_bitmask = rxf->vlan_pending_bitmask;
+ while (!(vlan_pending_bitmask & 0x1)) {
+ block_idx++;
+ vlan_pending_bitmask >>= 1;
+ }
+ rxf->vlan_pending_bitmask &= ~(1 << block_idx);
+ bna_bfi_rx_vlan_filter_set(rxf, block_idx);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+bna_rxf_mcast_cfg_reset(struct bna_rxf *rxf, enum bna_cleanup_type cleanup)
+{
+ struct list_head *qe;
+ struct bna_mac *mac;
+ int ret;
+
+ /* Throw away delete pending mcast entries */
+ while (!list_empty(&rxf->mcast_pending_del_q)) {
+ bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ ret = bna_rxf_mcast_del(rxf, mac, cleanup);
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ if (ret)
+ return ret;
+ }
+
+ /* Move active mcast entries to pending_add_q */
+ while (!list_empty(&rxf->mcast_active_q)) {
+ bfa_q_deq(&rxf->mcast_active_q, &qe);
+ bfa_q_qe_init(qe);
+ list_add_tail(qe, &rxf->mcast_pending_add_q);
+ mac = (struct bna_mac *)qe;
+ if (bna_rxf_mcast_del(rxf, mac, cleanup))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+bna_rxf_rss_cfg_apply(struct bna_rxf *rxf)
+{
+ if (rxf->rss_pending) {
+ if (rxf->rss_pending & BNA_RSS_F_RIT_PENDING) {
+ rxf->rss_pending &= ~BNA_RSS_F_RIT_PENDING;
+ bna_bfi_rit_cfg(rxf);
+ return 1;
+ }
+
+ if (rxf->rss_pending & BNA_RSS_F_CFG_PENDING) {
+ rxf->rss_pending &= ~BNA_RSS_F_CFG_PENDING;
+ bna_bfi_rss_cfg(rxf);
+ return 1;
+ }
+
+ if (rxf->rss_pending & BNA_RSS_F_STATUS_PENDING) {
+ rxf->rss_pending &= ~BNA_RSS_F_STATUS_PENDING;
+ bna_bfi_rss_enable(rxf);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bna_rxf_cfg_apply(struct bna_rxf *rxf)
+{
+ if (bna_rxf_ucast_cfg_apply(rxf))
+ return 1;
+
+ if (bna_rxf_mcast_cfg_apply(rxf))
+ return 1;
+
+ if (bna_rxf_promisc_cfg_apply(rxf))
+ return 1;
+
+ if (bna_rxf_allmulti_cfg_apply(rxf))
+ return 1;
+
+ if (bna_rxf_vlan_cfg_apply(rxf))
+ return 1;
+
+ if (bna_rxf_vlan_strip_cfg_apply(rxf))
+ return 1;
+
+ if (bna_rxf_rss_cfg_apply(rxf))
+ return 1;
+
+ return 0;
+}
+
+/* Only software reset */
+static int
+bna_rxf_fltr_clear(struct bna_rxf *rxf)
+{
+ if (bna_rxf_ucast_cfg_reset(rxf, BNA_HARD_CLEANUP))
+ return 1;
+
+ if (bna_rxf_mcast_cfg_reset(rxf, BNA_HARD_CLEANUP))
+ return 1;
+
+ if (bna_rxf_promisc_cfg_reset(rxf, BNA_HARD_CLEANUP))
+ return 1;
+
+ if (bna_rxf_allmulti_cfg_reset(rxf, BNA_HARD_CLEANUP))
+ return 1;
+
+ return 0;
+}
+
+static void
+bna_rxf_cfg_reset(struct bna_rxf *rxf)
+{
+ bna_rxf_ucast_cfg_reset(rxf, BNA_SOFT_CLEANUP);
+ bna_rxf_mcast_cfg_reset(rxf, BNA_SOFT_CLEANUP);
+ bna_rxf_promisc_cfg_reset(rxf, BNA_SOFT_CLEANUP);
+ bna_rxf_allmulti_cfg_reset(rxf, BNA_SOFT_CLEANUP);
+ bna_rxf_vlan_cfg_soft_reset(rxf);
+ bna_rxf_rss_cfg_soft_reset(rxf);
+}
+
+static void
+bna_rit_init(struct bna_rxf *rxf, int rit_size)
+{
+ struct bna_rx *rx = rxf->rx;
+ struct bna_rxp *rxp;
+ struct list_head *qe;
+ int offset = 0;
+
+ rxf->rit_size = rit_size;
+ list_for_each(qe, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe;
+ rxf->rit[offset] = rxp->cq.ccb->id;
+ offset++;
+ }
+
+}
+
+void
+bna_bfi_rxf_cfg_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr)
+{
+ bfa_fsm_send_event(rxf, RXF_E_FW_RESP);
+}
+
+void
+bna_bfi_rxf_mcast_add_rsp(struct bna_rxf *rxf,
+ struct bfi_msgq_mhdr *msghdr)
+{
+ struct bfi_enet_mcast_add_req *req =
+ &rxf->bfi_enet_cmd.mcast_add_req;
+ struct bfi_enet_mcast_add_rsp *rsp =
+ (struct bfi_enet_mcast_add_rsp *)msghdr;
+
+ bna_rxf_mchandle_attach(rxf, (u8 *)&req->mac_addr,
+ ntohs(rsp->handle));
+ bfa_fsm_send_event(rxf, RXF_E_FW_RESP);
+}
+
+static void
+bna_rxf_init(struct bna_rxf *rxf,
+ struct bna_rx *rx,
+ struct bna_rx_config *q_config,
+ struct bna_res_info *res_info)
+{
+ rxf->rx = rx;
+
+ INIT_LIST_HEAD(&rxf->ucast_pending_add_q);
+ INIT_LIST_HEAD(&rxf->ucast_pending_del_q);
+ rxf->ucast_pending_set = 0;
+ rxf->ucast_active_set = 0;
+ INIT_LIST_HEAD(&rxf->ucast_active_q);
+ rxf->ucast_pending_mac = NULL;
+
+ INIT_LIST_HEAD(&rxf->mcast_pending_add_q);
+ INIT_LIST_HEAD(&rxf->mcast_pending_del_q);
+ INIT_LIST_HEAD(&rxf->mcast_active_q);
+ INIT_LIST_HEAD(&rxf->mcast_handle_q);
+
+ if (q_config->paused)
+ rxf->flags |= BNA_RXF_F_PAUSED;
+
+ rxf->rit = (u8 *)
+ res_info[BNA_RX_RES_MEM_T_RIT].res_u.mem_info.mdl[0].kva;
+ bna_rit_init(rxf, q_config->num_paths);
+
+ rxf->rss_status = q_config->rss_status;
+ if (rxf->rss_status == BNA_STATUS_T_ENABLED) {
+ rxf->rss_cfg = q_config->rss_config;
+ rxf->rss_pending |= BNA_RSS_F_CFG_PENDING;
+ rxf->rss_pending |= BNA_RSS_F_RIT_PENDING;
+ rxf->rss_pending |= BNA_RSS_F_STATUS_PENDING;
+ }
+
+ rxf->vlan_filter_status = BNA_STATUS_T_DISABLED;
+ memset(rxf->vlan_filter_table, 0,
+ (sizeof(u32) * (BFI_ENET_VLAN_ID_MAX / 32)));
+ rxf->vlan_filter_table[0] |= 1; /* for pure priority tagged frames */
+ rxf->vlan_pending_bitmask = (u8)BFI_VLAN_BMASK_ALL;
+
+ rxf->vlan_strip_status = q_config->vlan_strip_status;
+
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+}
+
+static void
+bna_rxf_uninit(struct bna_rxf *rxf)
+{
+ struct bna_mac *mac;
+
+ rxf->ucast_pending_set = 0;
+ rxf->ucast_active_set = 0;
+
+ while (!list_empty(&rxf->ucast_pending_add_q)) {
+ bfa_q_deq(&rxf->ucast_pending_add_q, &mac);
+ bfa_q_qe_init(&mac->qe);
+ bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+ }
+
+ if (rxf->ucast_pending_mac) {
+ bfa_q_qe_init(&rxf->ucast_pending_mac->qe);
+ bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod,
+ rxf->ucast_pending_mac);
+ rxf->ucast_pending_mac = NULL;
+ }
+
+ while (!list_empty(&rxf->mcast_pending_add_q)) {
+ bfa_q_deq(&rxf->mcast_pending_add_q, &mac);
+ bfa_q_qe_init(&mac->qe);
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ }
+
+ rxf->rxmode_pending = 0;
+ rxf->rxmode_pending_bitmask = 0;
+ if (rxf->rx->bna->promisc_rid == rxf->rx->rid)
+ rxf->rx->bna->promisc_rid = BFI_INVALID_RID;
+ if (rxf->rx->bna->default_mode_rid == rxf->rx->rid)
+ rxf->rx->bna->default_mode_rid = BFI_INVALID_RID;
+
+ rxf->rss_pending = 0;
+ rxf->vlan_strip_pending = false;
+
+ rxf->flags = 0;
+
+ rxf->rx = NULL;
+}
+
+static void
+bna_rx_cb_rxf_started(struct bna_rx *rx)
+{
+ bfa_fsm_send_event(rx, RX_E_RXF_STARTED);
+}
+
+static void
+bna_rxf_start(struct bna_rxf *rxf)
+{
+ rxf->start_cbfn = bna_rx_cb_rxf_started;
+ rxf->start_cbarg = rxf->rx;
+ bfa_fsm_send_event(rxf, RXF_E_START);
+}
+
+static void
+bna_rx_cb_rxf_stopped(struct bna_rx *rx)
+{
+ bfa_fsm_send_event(rx, RX_E_RXF_STOPPED);
+}
+
+static void
+bna_rxf_stop(struct bna_rxf *rxf)
+{
+ rxf->stop_cbfn = bna_rx_cb_rxf_stopped;
+ rxf->stop_cbarg = rxf->rx;
+ bfa_fsm_send_event(rxf, RXF_E_STOP);
+}
+
+static void
+bna_rxf_fail(struct bna_rxf *rxf)
+{
+ bfa_fsm_send_event(rxf, RXF_E_FAIL);
+}
+
+enum bna_cb_status
+bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
+ void (*cbfn)(struct bnad *, struct bna_rx *))
+{
+ struct bna_rxf *rxf = &rx->rxf;
+
+ if (rxf->ucast_pending_mac == NULL) {
+ rxf->ucast_pending_mac =
+ bna_ucam_mod_mac_get(&rxf->rx->bna->ucam_mod);
+ if (rxf->ucast_pending_mac == NULL)
+ return BNA_CB_UCAST_CAM_FULL;
+ bfa_q_qe_init(&rxf->ucast_pending_mac->qe);
+ }
+
+ memcpy(rxf->ucast_pending_mac->addr, ucmac, ETH_ALEN);
+ rxf->ucast_pending_set = 1;
+ rxf->cam_fltr_cbfn = cbfn;
+ rxf->cam_fltr_cbarg = rx->bna->bnad;
+
+ bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+
+ return BNA_CB_SUCCESS;
+}
+
+enum bna_cb_status
+bna_rx_mcast_add(struct bna_rx *rx, u8 *addr,
+ void (*cbfn)(struct bnad *, struct bna_rx *))
+{
+ struct bna_rxf *rxf = &rx->rxf;
+ struct bna_mac *mac;
+
+ /* Check if already added or pending addition */
+ if (bna_mac_find(&rxf->mcast_active_q, addr) ||
+ bna_mac_find(&rxf->mcast_pending_add_q, addr)) {
+ if (cbfn)
+ cbfn(rx->bna->bnad, rx);
+ return BNA_CB_SUCCESS;
+ }
+
+ mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
+ if (mac == NULL)
+ return BNA_CB_MCAST_LIST_FULL;
+ bfa_q_qe_init(&mac->qe);
+ memcpy(mac->addr, addr, ETH_ALEN);
+ list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+
+ rxf->cam_fltr_cbfn = cbfn;
+ rxf->cam_fltr_cbarg = rx->bna->bnad;
+
+ bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+
+ return BNA_CB_SUCCESS;
+}
+
+enum bna_cb_status
+bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
+ void (*cbfn)(struct bnad *, struct bna_rx *))
+{
+ struct bna_rxf *rxf = &rx->rxf;
+ struct list_head list_head;
+ struct list_head *qe;
+ u8 *mcaddr;
+ struct bna_mac *mac;
+ int i;
+
+ /* Allocate nodes */
+ INIT_LIST_HEAD(&list_head);
+ for (i = 0, mcaddr = mclist; i < count; i++) {
+ mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
+ if (mac == NULL)
+ goto err_return;
+ bfa_q_qe_init(&mac->qe);
+ memcpy(mac->addr, mcaddr, ETH_ALEN);
+ list_add_tail(&mac->qe, &list_head);
+
+ mcaddr += ETH_ALEN;
+ }
+
+ /* Purge the pending_add_q */
+ while (!list_empty(&rxf->mcast_pending_add_q)) {
+ bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ }
+
+ /* Schedule active_q entries for deletion */
+ while (!list_empty(&rxf->mcast_active_q)) {
+ bfa_q_deq(&rxf->mcast_active_q, &qe);
+ mac = (struct bna_mac *)qe;
+ bfa_q_qe_init(&mac->qe);
+ list_add_tail(&mac->qe, &rxf->mcast_pending_del_q);
+ }
+
+ /* Add the new entries */
+ while (!list_empty(&list_head)) {
+ bfa_q_deq(&list_head, &qe);
+ mac = (struct bna_mac *)qe;
+ bfa_q_qe_init(&mac->qe);
+ list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+ }
+
+ rxf->cam_fltr_cbfn = cbfn;
+ rxf->cam_fltr_cbarg = rx->bna->bnad;
+ bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+
+ return BNA_CB_SUCCESS;
+
+err_return:
+ while (!list_empty(&list_head)) {
+ bfa_q_deq(&list_head, &qe);
+ mac = (struct bna_mac *)qe;
+ bfa_q_qe_init(&mac->qe);
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ }
+
+ return BNA_CB_MCAST_LIST_FULL;
+}
+
+void
+bna_rx_vlan_add(struct bna_rx *rx, int vlan_id)
+{
+ struct bna_rxf *rxf = &rx->rxf;
+ int index = (vlan_id >> BFI_VLAN_WORD_SHIFT);
+ int bit = (1 << (vlan_id & BFI_VLAN_WORD_MASK));
+ int group_id = (vlan_id >> BFI_VLAN_BLOCK_SHIFT);
+
+ rxf->vlan_filter_table[index] |= bit;
+ if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
+ rxf->vlan_pending_bitmask |= (1 << group_id);
+ bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+ }
+}
+
+void
+bna_rx_vlan_del(struct bna_rx *rx, int vlan_id)
+{
+ struct bna_rxf *rxf = &rx->rxf;
+ int index = (vlan_id >> BFI_VLAN_WORD_SHIFT);
+ int bit = (1 << (vlan_id & BFI_VLAN_WORD_MASK));
+ int group_id = (vlan_id >> BFI_VLAN_BLOCK_SHIFT);
+
+ rxf->vlan_filter_table[index] &= ~bit;
+ if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
+ rxf->vlan_pending_bitmask |= (1 << group_id);
+ bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+ }
+}
+
+static int
+bna_rxf_ucast_cfg_apply(struct bna_rxf *rxf)
+{
+ struct bna_mac *mac = NULL;
+ struct list_head *qe;
+
+ /* Delete MAC addresses previousely added */
+ if (!list_empty(&rxf->ucast_pending_del_q)) {
+ bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ bna_bfi_ucast_req(rxf, mac, BFI_ENET_H2I_MAC_UCAST_DEL_REQ);
+ bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+ return 1;
+ }
+
+ /* Set default unicast MAC */
+ if (rxf->ucast_pending_set) {
+ rxf->ucast_pending_set = 0;
+ memcpy(rxf->ucast_active_mac.addr,
+ rxf->ucast_pending_mac->addr, ETH_ALEN);
+ rxf->ucast_active_set = 1;
+ bna_bfi_ucast_req(rxf, &rxf->ucast_active_mac,
+ BFI_ENET_H2I_MAC_UCAST_SET_REQ);
+ return 1;
+ }
+
+ /* Add additional MAC entries */
+ if (!list_empty(&rxf->ucast_pending_add_q)) {
+ bfa_q_deq(&rxf->ucast_pending_add_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ list_add_tail(&mac->qe, &rxf->ucast_active_q);
+ bna_bfi_ucast_req(rxf, mac, BFI_ENET_H2I_MAC_UCAST_ADD_REQ);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+bna_rxf_ucast_cfg_reset(struct bna_rxf *rxf, enum bna_cleanup_type cleanup)
+{
+ struct list_head *qe;
+ struct bna_mac *mac;
+
+ /* Throw away delete pending ucast entries */
+ while (!list_empty(&rxf->ucast_pending_del_q)) {
+ bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ if (cleanup == BNA_SOFT_CLEANUP)
+ bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+ else {
+ bna_bfi_ucast_req(rxf, mac,
+ BFI_ENET_H2I_MAC_UCAST_DEL_REQ);
+ bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+ return 1;
+ }
+ }
+
+ /* Move active ucast entries to pending_add_q */
+ while (!list_empty(&rxf->ucast_active_q)) {
+ bfa_q_deq(&rxf->ucast_active_q, &qe);
+ bfa_q_qe_init(qe);
+ list_add_tail(qe, &rxf->ucast_pending_add_q);
+ if (cleanup == BNA_HARD_CLEANUP) {
+ mac = (struct bna_mac *)qe;
+ bna_bfi_ucast_req(rxf, mac,
+ BFI_ENET_H2I_MAC_UCAST_DEL_REQ);
+ return 1;
+ }
+ }
+
+ if (rxf->ucast_active_set) {
+ rxf->ucast_pending_set = 1;
+ rxf->ucast_active_set = 0;
+ if (cleanup == BNA_HARD_CLEANUP) {
+ bna_bfi_ucast_req(rxf, &rxf->ucast_active_mac,
+ BFI_ENET_H2I_MAC_UCAST_CLR_REQ);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bna_rxf_promisc_cfg_apply(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+
+ /* Enable/disable promiscuous mode */
+ if (is_promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move promisc configuration from pending -> active */
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active |= BNA_RXMODE_PROMISC;
+ bna_bfi_rx_promisc_req(rxf, BNA_STATUS_T_ENABLED);
+ return 1;
+ } else if (is_promisc_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move promisc configuration from pending -> active */
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+ bna->promisc_rid = BFI_INVALID_RID;
+ bna_bfi_rx_promisc_req(rxf, BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+bna_rxf_promisc_cfg_reset(struct bna_rxf *rxf, enum bna_cleanup_type cleanup)
+{
+ struct bna *bna = rxf->rx->bna;
+
+ /* Clear pending promisc mode disable */
+ if (is_promisc_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+ bna->promisc_rid = BFI_INVALID_RID;
+ if (cleanup == BNA_HARD_CLEANUP) {
+ bna_bfi_rx_promisc_req(rxf, BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+ }
+
+ /* Move promisc mode config from active -> pending */
+ if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
+ promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+ if (cleanup == BNA_HARD_CLEANUP) {
+ bna_bfi_rx_promisc_req(rxf, BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bna_rxf_allmulti_cfg_apply(struct bna_rxf *rxf)
+{
+ /* Enable/disable allmulti mode */
+ if (is_allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move allmulti configuration from pending -> active */
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active |= BNA_RXMODE_ALLMULTI;
+ bna_bfi_mcast_filter_req(rxf, BNA_STATUS_T_DISABLED);
+ return 1;
+ } else if (is_allmulti_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move allmulti configuration from pending -> active */
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+ bna_bfi_mcast_filter_req(rxf, BNA_STATUS_T_ENABLED);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+bna_rxf_allmulti_cfg_reset(struct bna_rxf *rxf, enum bna_cleanup_type cleanup)
+{
+ /* Clear pending allmulti mode disable */
+ if (is_allmulti_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+ if (cleanup == BNA_HARD_CLEANUP) {
+ bna_bfi_mcast_filter_req(rxf, BNA_STATUS_T_ENABLED);
+ return 1;
+ }
+ }
+
+ /* Move allmulti mode config from active -> pending */
+ if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
+ allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+ if (cleanup == BNA_HARD_CLEANUP) {
+ bna_bfi_mcast_filter_req(rxf, BNA_STATUS_T_ENABLED);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bna_rxf_promisc_enable(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+ int ret = 0;
+
+ if (is_promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask) ||
+ (rxf->rxmode_active & BNA_RXMODE_PROMISC)) {
+ /* Do nothing if pending enable or already enabled */
+ } else if (is_promisc_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* Turn off pending disable command */
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ } else {
+ /* Schedule enable */
+ promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ bna->promisc_rid = rxf->rx->rid;
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static int
+bna_rxf_promisc_disable(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+ int ret = 0;
+
+ if (is_promisc_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask) ||
+ (!(rxf->rxmode_active & BNA_RXMODE_PROMISC))) {
+ /* Do nothing if pending disable or already disabled */
+ } else if (is_promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* Turn off pending enable command */
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ bna->promisc_rid = BFI_INVALID_RID;
+ } else if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
+ /* Schedule disable */
+ promisc_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static int
+bna_rxf_allmulti_enable(struct bna_rxf *rxf)
+{
+ int ret = 0;
+
+ if (is_allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask) ||
+ (rxf->rxmode_active & BNA_RXMODE_ALLMULTI)) {
+ /* Do nothing if pending enable or already enabled */
+ } else if (is_allmulti_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* Turn off pending disable command */
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ } else {
+ /* Schedule enable */
+ allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static int
+bna_rxf_allmulti_disable(struct bna_rxf *rxf)
+{
+ int ret = 0;
+
+ if (is_allmulti_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask) ||
+ (!(rxf->rxmode_active & BNA_RXMODE_ALLMULTI))) {
+ /* Do nothing if pending disable or already disabled */
+ } else if (is_allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* Turn off pending enable command */
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ } else if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
+ /* Schedule disable */
+ allmulti_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static int
+bna_rxf_vlan_strip_cfg_apply(struct bna_rxf *rxf)
+{
+ if (rxf->vlan_strip_pending) {
+ rxf->vlan_strip_pending = false;
+ bna_bfi_vlan_strip_enable(rxf);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * RX
+ */
+
+#define BNA_GET_RXQS(qcfg) (((qcfg)->rxp_type == BNA_RXP_SINGLE) ? \
+ (qcfg)->num_paths : ((qcfg)->num_paths * 2))
+
+#define SIZE_TO_PAGES(size) (((size) >> PAGE_SHIFT) + ((((size) &\
+ (PAGE_SIZE - 1)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
+
+#define call_rx_stop_cbfn(rx) \
+do { \
+ if ((rx)->stop_cbfn) { \
+ void (*cbfn)(void *, struct bna_rx *); \
+ void *cbarg; \
+ cbfn = (rx)->stop_cbfn; \
+ cbarg = (rx)->stop_cbarg; \
+ (rx)->stop_cbfn = NULL; \
+ (rx)->stop_cbarg = NULL; \
+ cbfn(cbarg, rx); \
+ } \
+} while (0)
+
+#define call_rx_stall_cbfn(rx) \
+do { \
+ if ((rx)->rx_stall_cbfn) \
+ (rx)->rx_stall_cbfn((rx)->bna->bnad, (rx)); \
+} while (0)
+
+#define bfi_enet_datapath_q_init(bfi_q, bna_qpt) \
+do { \
+ struct bna_dma_addr cur_q_addr = \
+ *((struct bna_dma_addr *)((bna_qpt)->kv_qpt_ptr)); \
+ (bfi_q)->pg_tbl.a32.addr_lo = (bna_qpt)->hw_qpt_ptr.lsb; \
+ (bfi_q)->pg_tbl.a32.addr_hi = (bna_qpt)->hw_qpt_ptr.msb; \
+ (bfi_q)->first_entry.a32.addr_lo = cur_q_addr.lsb; \
+ (bfi_q)->first_entry.a32.addr_hi = cur_q_addr.msb; \
+ (bfi_q)->pages = htons((u16)(bna_qpt)->page_count); \
+ (bfi_q)->page_sz = htons((u16)(bna_qpt)->page_size);\
+} while (0)
+
+static void bna_bfi_rx_enet_start(struct bna_rx *rx);
+static void bna_rx_enet_stop(struct bna_rx *rx);
+static void bna_rx_mod_cb_rx_stopped(void *arg, struct bna_rx *rx);
+
+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, rxf_start_wait,
+ struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, started,
+ struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, rxf_stop_wait,
+ struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, stop_wait,
+ struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, cleanup_wait,
+ struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, failed,
+ struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, quiesce_wait,
+ struct bna_rx, enum bna_rx_event);
+
+static void bna_rx_sm_stopped_entry(struct bna_rx *rx)
+{
+ call_rx_stop_cbfn(rx);
+}
+
+static void bna_rx_sm_stopped(struct bna_rx *rx,
+ enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_START:
+ bfa_fsm_set_state(rx, bna_rx_sm_start_wait);
+ break;
+
+ case RX_E_STOP:
+ call_rx_stop_cbfn(rx);
+ break;
+
+ case RX_E_FAIL:
+ /* no-op */
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ break;
+ }
+}
+
+static void bna_rx_sm_start_wait_entry(struct bna_rx *rx)
+{
+ bna_bfi_rx_enet_start(rx);
+}
+
+void
+bna_rx_sm_stop_wait_entry(struct bna_rx *rx)
+{
+}
+
+static void
+bna_rx_sm_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_cleanup_wait);
+ rx->rx_cleanup_cbfn(rx->bna->bnad, rx);
+ break;
+
+ case RX_E_STARTED:
+ bna_rx_enet_stop(rx);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ break;
+ }
+}
+
+static void bna_rx_sm_start_wait(struct bna_rx *rx,
+ enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_STOP:
+ bfa_fsm_set_state(rx, bna_rx_sm_stop_wait);
+ break;
+
+ case RX_E_FAIL:
+ bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+ break;
+
+ case RX_E_STARTED:
+ bfa_fsm_set_state(rx, bna_rx_sm_rxf_start_wait);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ break;
+ }
+}
+
+static void bna_rx_sm_rxf_start_wait_entry(struct bna_rx *rx)
+{
+ rx->rx_post_cbfn(rx->bna->bnad, rx);
+ bna_rxf_start(&rx->rxf);
+}
+
+void
+bna_rx_sm_rxf_stop_wait_entry(struct bna_rx *rx)
+{
+}
+
+static void
+bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_FAIL:
+ bfa_fsm_set_state(rx, bna_rx_sm_cleanup_wait);
+ bna_rxf_fail(&rx->rxf);
+ call_rx_stall_cbfn(rx);
+ rx->rx_cleanup_cbfn(rx->bna->bnad, rx);
+ break;
+
+ case RX_E_RXF_STARTED:
+ bna_rxf_stop(&rx->rxf);
+ break;
+
+ case RX_E_RXF_STOPPED:
+ bfa_fsm_set_state(rx, bna_rx_sm_stop_wait);
+ call_rx_stall_cbfn(rx);
+ bna_rx_enet_stop(rx);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ break;
+ }
+
+}
+
+void
+bna_rx_sm_started_entry(struct bna_rx *rx)
+{
+ struct bna_rxp *rxp;
+ struct list_head *qe_rxp;
+ int is_regular = (rx->type == BNA_RX_T_REGULAR);
+
+ /* Start IB */
+ list_for_each(qe_rxp, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe_rxp;
+ bna_ib_start(rx->bna, &rxp->cq.ib, is_regular);
+ }
+
+ bna_ethport_cb_rx_started(&rx->bna->ethport);
+}
+
+static void
+bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_STOP:
+ bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
+ bna_ethport_cb_rx_stopped(&rx->bna->ethport);
+ bna_rxf_stop(&rx->rxf);
+ break;
+
+ case RX_E_FAIL:
+ bfa_fsm_set_state(rx, bna_rx_sm_failed);
+ bna_ethport_cb_rx_stopped(&rx->bna->ethport);
+ bna_rxf_fail(&rx->rxf);
+ call_rx_stall_cbfn(rx);
+ rx->rx_cleanup_cbfn(rx->bna->bnad, rx);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ break;
+ }
+}
+
+static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx,
+ enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_STOP:
+ bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
+ break;
+
+ case RX_E_FAIL:
+ bfa_fsm_set_state(rx, bna_rx_sm_failed);
+ bna_rxf_fail(&rx->rxf);
+ call_rx_stall_cbfn(rx);
+ rx->rx_cleanup_cbfn(rx->bna->bnad, rx);
+ break;
+
+ case RX_E_RXF_STARTED:
+ bfa_fsm_set_state(rx, bna_rx_sm_started);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ break;
+ }
+}
+
+void
+bna_rx_sm_cleanup_wait_entry(struct bna_rx *rx)
+{
+}
+
+void
+bna_rx_sm_cleanup_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_FAIL:
+ case RX_E_RXF_STOPPED:
+ /* No-op */
+ break;
+
+ case RX_E_CLEANUP_DONE:
+ bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ break;
+ }
+}
+
+static void
+bna_rx_sm_failed_entry(struct bna_rx *rx)
+{
+}
+
+static void
+bna_rx_sm_failed(struct bna_rx *rx, enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_START:
+ bfa_fsm_set_state(rx, bna_rx_sm_quiesce_wait);
+ break;
+
+ case RX_E_STOP:
+ bfa_fsm_set_state(rx, bna_rx_sm_cleanup_wait);
+ break;
+
+ case RX_E_FAIL:
+ case RX_E_RXF_STARTED:
+ case RX_E_RXF_STOPPED:
+ /* No-op */
+ break;
+
+ case RX_E_CLEANUP_DONE:
+ bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ break;
+} }
+
+static void
+bna_rx_sm_quiesce_wait_entry(struct bna_rx *rx)
+{
+}
+
+static void
+bna_rx_sm_quiesce_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_STOP:
+ bfa_fsm_set_state(rx, bna_rx_sm_cleanup_wait);
+ break;
+
+ case RX_E_FAIL:
+ bfa_fsm_set_state(rx, bna_rx_sm_failed);
+ break;
+
+ case RX_E_CLEANUP_DONE:
+ bfa_fsm_set_state(rx, bna_rx_sm_start_wait);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ break;
+ }
+}
+
+static void
+bna_bfi_rx_enet_start(struct bna_rx *rx)
+{
+ struct bfi_enet_rx_cfg_req *cfg_req = &rx->bfi_enet_cmd.cfg_req;
+ struct bna_rxp *rxp = NULL;
+ struct bna_rxq *q0 = NULL, *q1 = NULL;
+ struct list_head *rxp_qe;
+ int i;
+
+ bfi_msgq_mhdr_set(cfg_req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_RX_CFG_SET_REQ, 0, rx->rid);
+ cfg_req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_rx_cfg_req)));
+
+ cfg_req->num_queue_sets = rx->num_paths;
+ for (i = 0, rxp_qe = bfa_q_first(&rx->rxp_q);
+ i < rx->num_paths;
+ i++, rxp_qe = bfa_q_next(rxp_qe)) {
+ rxp = (struct bna_rxp *)rxp_qe;
+
+ GET_RXQS(rxp, q0, q1);
+ switch (rxp->type) {
+ case BNA_RXP_SLR:
+ case BNA_RXP_HDS:
+ /* Small RxQ */
+ bfi_enet_datapath_q_init(&cfg_req->q_cfg[i].qs.q,
+ &q1->qpt);
+ cfg_req->q_cfg[i].qs.rx_buffer_size =
+ htons((u16)q1->buffer_size);
+ /* Fall through */
+
+ case BNA_RXP_SINGLE:
+ /* Large/Single RxQ */
+ bfi_enet_datapath_q_init(&cfg_req->q_cfg[i].ql.q,
+ &q0->qpt);
+ q0->buffer_size =
+ bna_enet_mtu_get(&rx->bna->enet);
+ cfg_req->q_cfg[i].ql.rx_buffer_size =
+ htons((u16)q0->buffer_size);
+ break;
+
+ default:
+ BUG_ON(1);
+ }
+
+ bfi_enet_datapath_q_init(&cfg_req->q_cfg[i].cq.q,
+ &rxp->cq.qpt);
+
+ cfg_req->q_cfg[i].ib.index_addr.a32.addr_lo =
+ rxp->cq.ib.ib_seg_host_addr.lsb;
+ cfg_req->q_cfg[i].ib.index_addr.a32.addr_hi =
+ rxp->cq.ib.ib_seg_host_addr.msb;
+ cfg_req->q_cfg[i].ib.intr.msix_index =
+ htons((u16)rxp->cq.ib.intr_vector);
+ }
+
+ cfg_req->ib_cfg.int_pkt_dma = BNA_STATUS_T_DISABLED;
+ cfg_req->ib_cfg.int_enabled = BNA_STATUS_T_ENABLED;
+ cfg_req->ib_cfg.int_pkt_enabled = BNA_STATUS_T_DISABLED;
+ cfg_req->ib_cfg.continuous_coalescing = BNA_STATUS_T_DISABLED;
+ cfg_req->ib_cfg.msix = (rxp->cq.ib.intr_type == BNA_INTR_T_MSIX)
+ ? BNA_STATUS_T_ENABLED :
+ BNA_STATUS_T_DISABLED;
+ cfg_req->ib_cfg.coalescing_timeout =
+ htonl((u32)rxp->cq.ib.coalescing_timeo);
+ cfg_req->ib_cfg.inter_pkt_timeout =
+ htonl((u32)rxp->cq.ib.interpkt_timeo);
+ cfg_req->ib_cfg.inter_pkt_count = (u8)rxp->cq.ib.interpkt_count;
+
+ switch (rxp->type) {
+ case BNA_RXP_SLR:
+ cfg_req->rx_cfg.rxq_type = BFI_ENET_RXQ_LARGE_SMALL;
+ break;
+
+ case BNA_RXP_HDS:
+ cfg_req->rx_cfg.rxq_type = BFI_ENET_RXQ_HDS;
+ cfg_req->rx_cfg.hds.type = rx->hds_cfg.hdr_type;
+ cfg_req->rx_cfg.hds.force_offset = rx->hds_cfg.forced_offset;
+ cfg_req->rx_cfg.hds.max_header_size = rx->hds_cfg.forced_offset;
+ break;
+
+ case BNA_RXP_SINGLE:
+ cfg_req->rx_cfg.rxq_type = BFI_ENET_RXQ_SINGLE;
+ break;
+
+ default:
+ BUG_ON(1);
+ }
+ cfg_req->rx_cfg.strip_vlan = rx->rxf.vlan_strip_status;
+
+ bfa_msgq_cmd_set(&rx->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_rx_cfg_req), &cfg_req->mh);
+ bfa_msgq_cmd_post(&rx->bna->msgq, &rx->msgq_cmd);
+}
+
+static void
+bna_bfi_rx_enet_stop(struct bna_rx *rx)
+{
+ struct bfi_enet_req *req = &rx->bfi_enet_cmd.req;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_RX_CFG_CLR_REQ, 0, rx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_req)));
+ bfa_msgq_cmd_set(&rx->msgq_cmd, NULL, NULL, sizeof(struct bfi_enet_req),
+ &req->mh);
+ bfa_msgq_cmd_post(&rx->bna->msgq, &rx->msgq_cmd);
+}
+
+static void
+bna_rx_enet_stop(struct bna_rx *rx)
+{
+ struct bna_rxp *rxp;
+ struct list_head *qe_rxp;
+
+ /* Stop IB */
+ list_for_each(qe_rxp, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe_rxp;
+ bna_ib_stop(rx->bna, &rxp->cq.ib);
+ }
+
+ bna_bfi_rx_enet_stop(rx);
+}
+
+static int
+bna_rx_res_check(struct bna_rx_mod *rx_mod, struct bna_rx_config *rx_cfg)
+{
+ if ((rx_mod->rx_free_count == 0) ||
+ (rx_mod->rxp_free_count == 0) ||
+ (rx_mod->rxq_free_count == 0))
+ return 0;
+
+ if (rx_cfg->rxp_type == BNA_RXP_SINGLE) {
+ if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
+ (rx_mod->rxq_free_count < rx_cfg->num_paths))
+ return 0;
+ } else {
+ if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
+ (rx_mod->rxq_free_count < (2 * rx_cfg->num_paths)))
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct bna_rxq *
+bna_rxq_get(struct bna_rx_mod *rx_mod)
+{
+ struct bna_rxq *rxq = NULL;
+ struct list_head *qe = NULL;
+
+ bfa_q_deq(&rx_mod->rxq_free_q, &qe);
+ rx_mod->rxq_free_count--;
+ rxq = (struct bna_rxq *)qe;
+ bfa_q_qe_init(&rxq->qe);
+
+ return rxq;
+}
+
+static void
+bna_rxq_put(struct bna_rx_mod *rx_mod, struct bna_rxq *rxq)
+{
+ bfa_q_qe_init(&rxq->qe);
+ list_add_tail(&rxq->qe, &rx_mod->rxq_free_q);
+ rx_mod->rxq_free_count++;
+}
+
+static struct bna_rxp *
+bna_rxp_get(struct bna_rx_mod *rx_mod)
+{
+ struct list_head *qe = NULL;
+ struct bna_rxp *rxp = NULL;
+
+ bfa_q_deq(&rx_mod->rxp_free_q, &qe);
+ rx_mod->rxp_free_count--;
+ rxp = (struct bna_rxp *)qe;
+ bfa_q_qe_init(&rxp->qe);
+
+ return rxp;
+}
+
+static void
+bna_rxp_put(struct bna_rx_mod *rx_mod, struct bna_rxp *rxp)
+{
+ bfa_q_qe_init(&rxp->qe);
+ list_add_tail(&rxp->qe, &rx_mod->rxp_free_q);
+ rx_mod->rxp_free_count++;
+}
+
+static struct bna_rx *
+bna_rx_get(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
+{
+ struct list_head *qe = NULL;
+ struct bna_rx *rx = NULL;
+
+ if (type == BNA_RX_T_REGULAR) {
+ bfa_q_deq(&rx_mod->rx_free_q, &qe);
+ } else
+ bfa_q_deq_tail(&rx_mod->rx_free_q, &qe);
+
+ rx_mod->rx_free_count--;
+ rx = (struct bna_rx *)qe;
+ bfa_q_qe_init(&rx->qe);
+ list_add_tail(&rx->qe, &rx_mod->rx_active_q);
+ rx->type = type;
+
+ return rx;
+}
+
+static void
+bna_rx_put(struct bna_rx_mod *rx_mod, struct bna_rx *rx)
+{
+ struct list_head *prev_qe = NULL;
+ struct list_head *qe;
+
+ bfa_q_qe_init(&rx->qe);
+
+ list_for_each(qe, &rx_mod->rx_free_q) {
+ if (((struct bna_rx *)qe)->rid < rx->rid)
+ prev_qe = qe;
+ else
+ break;
+ }
+
+ if (prev_qe == NULL) {
+ /* This is the first entry */
+ bfa_q_enq_head(&rx_mod->rx_free_q, &rx->qe);
+ } else if (bfa_q_next(prev_qe) == &rx_mod->rx_free_q) {
+ /* This is the last entry */
+ list_add_tail(&rx->qe, &rx_mod->rx_free_q);
+ } else {
+ /* Somewhere in the middle */
+ bfa_q_next(&rx->qe) = bfa_q_next(prev_qe);
+ bfa_q_prev(&rx->qe) = prev_qe;
+ bfa_q_next(prev_qe) = &rx->qe;
+ bfa_q_prev(bfa_q_next(&rx->qe)) = &rx->qe;
+ }
+
+ rx_mod->rx_free_count++;
+}
+
+static void
+bna_rxp_add_rxqs(struct bna_rxp *rxp, struct bna_rxq *q0,
+ struct bna_rxq *q1)
+{
+ switch (rxp->type) {
+ case BNA_RXP_SINGLE:
+ rxp->rxq.single.only = q0;
+ rxp->rxq.single.reserved = NULL;
+ break;
+ case BNA_RXP_SLR:
+ rxp->rxq.slr.large = q0;
+ rxp->rxq.slr.small = q1;
+ break;
+ case BNA_RXP_HDS:
+ rxp->rxq.hds.data = q0;
+ rxp->rxq.hds.hdr = q1;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+bna_rxq_qpt_setup(struct bna_rxq *rxq,
+ struct bna_rxp *rxp,
+ u32 page_count,
+ u32 page_size,
+ struct bna_mem_descr *qpt_mem,
+ struct bna_mem_descr *swqpt_mem,
+ struct bna_mem_descr *page_mem)
+{
+ int i;
+
+ rxq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+ rxq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+ rxq->qpt.kv_qpt_ptr = qpt_mem->kva;
+ rxq->qpt.page_count = page_count;
+ rxq->qpt.page_size = page_size;
+
+ rxq->rcb->sw_qpt = (void **) swqpt_mem->kva;
+
+ for (i = 0; i < rxq->qpt.page_count; i++) {
+ rxq->rcb->sw_qpt[i] = page_mem[i].kva;
+ ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].lsb =
+ page_mem[i].dma.lsb;
+ ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].msb =
+ page_mem[i].dma.msb;
+ }
+}
+
+static void
+bna_rxp_cqpt_setup(struct bna_rxp *rxp,
+ u32 page_count,
+ u32 page_size,
+ struct bna_mem_descr *qpt_mem,
+ struct bna_mem_descr *swqpt_mem,
+ struct bna_mem_descr *page_mem)
+{
+ int i;
+
+ rxp->cq.qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+ rxp->cq.qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+ rxp->cq.qpt.kv_qpt_ptr = qpt_mem->kva;
+ rxp->cq.qpt.page_count = page_count;
+ rxp->cq.qpt.page_size = page_size;
+
+ rxp->cq.ccb->sw_qpt = (void **) swqpt_mem->kva;
+
+ for (i = 0; i < rxp->cq.qpt.page_count; i++) {
+ rxp->cq.ccb->sw_qpt[i] = page_mem[i].kva;
+
+ ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].lsb =
+ page_mem[i].dma.lsb;
+ ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].msb =
+ page_mem[i].dma.msb;
+ }
+}
+
+static void
+bna_rx_mod_cb_rx_stopped(void *arg, struct bna_rx *rx)
+{
+ struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
+
+ bfa_wc_down(&rx_mod->rx_stop_wc);
+}
+
+static void
+bna_rx_mod_cb_rx_stopped_all(void *arg)
+{
+ struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
+
+ if (rx_mod->stop_cbfn)
+ rx_mod->stop_cbfn(&rx_mod->bna->enet);
+ rx_mod->stop_cbfn = NULL;
+}
+
+static void
+bna_rx_start(struct bna_rx *rx)
+{
+ rx->rx_flags |= BNA_RX_F_ENET_STARTED;
+ if (rx->rx_flags & BNA_RX_F_ENABLED)
+ bfa_fsm_send_event(rx, RX_E_START);
+}
+
+static void
+bna_rx_stop(struct bna_rx *rx)
+{
+ rx->rx_flags &= ~BNA_RX_F_ENET_STARTED;
+ if (rx->fsm == (bfa_fsm_t) bna_rx_sm_stopped)
+ bna_rx_mod_cb_rx_stopped(&rx->bna->rx_mod, rx);
+ else {
+ rx->stop_cbfn = bna_rx_mod_cb_rx_stopped;
+ rx->stop_cbarg = &rx->bna->rx_mod;
+ bfa_fsm_send_event(rx, RX_E_STOP);
+ }
+}
+
+static void
+bna_rx_fail(struct bna_rx *rx)
+{
+ /* Indicate Enet is not enabled, and failed */
+ rx->rx_flags &= ~BNA_RX_F_ENET_STARTED;
+ bfa_fsm_send_event(rx, RX_E_FAIL);
+}
+
+void
+bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
+{
+ struct bna_rx *rx;
+ struct list_head *qe;
+
+ rx_mod->flags |= BNA_RX_MOD_F_ENET_STARTED;
+ if (type == BNA_RX_T_LOOPBACK)
+ rx_mod->flags |= BNA_RX_MOD_F_ENET_LOOPBACK;
+
+ list_for_each(qe, &rx_mod->rx_active_q) {
+ rx = (struct bna_rx *)qe;
+ if (rx->type == type)
+ bna_rx_start(rx);
+ }
+}
+
+void
+bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
+{
+ struct bna_rx *rx;
+ struct list_head *qe;
+
+ rx_mod->flags &= ~BNA_RX_MOD_F_ENET_STARTED;
+ rx_mod->flags &= ~BNA_RX_MOD_F_ENET_LOOPBACK;
+
+ rx_mod->stop_cbfn = bna_enet_cb_rx_stopped;
+
+ bfa_wc_init(&rx_mod->rx_stop_wc, bna_rx_mod_cb_rx_stopped_all, rx_mod);
+
+ list_for_each(qe, &rx_mod->rx_active_q) {
+ rx = (struct bna_rx *)qe;
+ if (rx->type == type) {
+ bfa_wc_up(&rx_mod->rx_stop_wc);
+ bna_rx_stop(rx);
+ }
+ }
+
+ bfa_wc_wait(&rx_mod->rx_stop_wc);
+}
+
+void
+bna_rx_mod_fail(struct bna_rx_mod *rx_mod)
+{
+ struct bna_rx *rx;
+ struct list_head *qe;
+
+ rx_mod->flags &= ~BNA_RX_MOD_F_ENET_STARTED;
+ rx_mod->flags &= ~BNA_RX_MOD_F_ENET_LOOPBACK;
+
+ list_for_each(qe, &rx_mod->rx_active_q) {
+ rx = (struct bna_rx *)qe;
+ bna_rx_fail(rx);
+ }
+}
+
+void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ int index;
+ struct bna_rx *rx_ptr;
+ struct bna_rxp *rxp_ptr;
+ struct bna_rxq *rxq_ptr;
+
+ rx_mod->bna = bna;
+ rx_mod->flags = 0;
+
+ rx_mod->rx = (struct bna_rx *)
+ res_info[BNA_MOD_RES_MEM_T_RX_ARRAY].res_u.mem_info.mdl[0].kva;
+ rx_mod->rxp = (struct bna_rxp *)
+ res_info[BNA_MOD_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mdl[0].kva;
+ rx_mod->rxq = (struct bna_rxq *)
+ res_info[BNA_MOD_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mdl[0].kva;
+
+ /* Initialize the queues */
+ INIT_LIST_HEAD(&rx_mod->rx_free_q);
+ rx_mod->rx_free_count = 0;
+ INIT_LIST_HEAD(&rx_mod->rxq_free_q);
+ rx_mod->rxq_free_count = 0;
+ INIT_LIST_HEAD(&rx_mod->rxp_free_q);
+ rx_mod->rxp_free_count = 0;
+ INIT_LIST_HEAD(&rx_mod->rx_active_q);
+
+ /* Build RX queues */
+ for (index = 0; index < bna->ioceth.attr.num_rxp; index++) {
+ rx_ptr = &rx_mod->rx[index];
+
+ bfa_q_qe_init(&rx_ptr->qe);
+ INIT_LIST_HEAD(&rx_ptr->rxp_q);
+ rx_ptr->bna = NULL;
+ rx_ptr->rid = index;
+ rx_ptr->stop_cbfn = NULL;
+ rx_ptr->stop_cbarg = NULL;
+
+ list_add_tail(&rx_ptr->qe, &rx_mod->rx_free_q);
+ rx_mod->rx_free_count++;
+ }
+
+ /* build RX-path queue */
+ for (index = 0; index < bna->ioceth.attr.num_rxp; index++) {
+ rxp_ptr = &rx_mod->rxp[index];
+ bfa_q_qe_init(&rxp_ptr->qe);
+ list_add_tail(&rxp_ptr->qe, &rx_mod->rxp_free_q);
+ rx_mod->rxp_free_count++;
+ }
+
+ /* build RXQ queue */
+ for (index = 0; index < (bna->ioceth.attr.num_rxp * 2); index++) {
+ rxq_ptr = &rx_mod->rxq[index];
+ bfa_q_qe_init(&rxq_ptr->qe);
+ list_add_tail(&rxq_ptr->qe, &rx_mod->rxq_free_q);
+ rx_mod->rxq_free_count++;
+ }
+}
+
+void
+bna_rx_mod_uninit(struct bna_rx_mod *rx_mod)
+{
+ struct list_head *qe;
+ int i;
+
+ i = 0;
+ list_for_each(qe, &rx_mod->rx_free_q)
+ i++;
+
+ i = 0;
+ list_for_each(qe, &rx_mod->rxp_free_q)
+ i++;
+
+ i = 0;
+ list_for_each(qe, &rx_mod->rxq_free_q)
+ i++;
+
+ rx_mod->bna = NULL;
+}
+
+void
+bna_bfi_rx_enet_start_rsp(struct bna_rx *rx, struct bfi_msgq_mhdr *msghdr)
+{
+ struct bfi_enet_rx_cfg_rsp *cfg_rsp = &rx->bfi_enet_cmd.cfg_rsp;
+ struct bna_rxp *rxp = NULL;
+ struct bna_rxq *q0 = NULL, *q1 = NULL;
+ struct list_head *rxp_qe;
+ int i;
+
+ bfa_msgq_rsp_copy(&rx->bna->msgq, (u8 *)cfg_rsp,
+ sizeof(struct bfi_enet_rx_cfg_rsp));
+
+ rx->hw_id = cfg_rsp->hw_id;
+
+ for (i = 0, rxp_qe = bfa_q_first(&rx->rxp_q);
+ i < rx->num_paths;
+ i++, rxp_qe = bfa_q_next(rxp_qe)) {
+ rxp = (struct bna_rxp *)rxp_qe;
+ GET_RXQS(rxp, q0, q1);
+
+ /* Setup doorbells */
+ rxp->cq.ccb->i_dbell->doorbell_addr =
+ rx->bna->pcidev.pci_bar_kva
+ + ntohl(cfg_rsp->q_handles[i].i_dbell);
+ rxp->hw_id = cfg_rsp->q_handles[i].hw_cqid;
+ q0->rcb->q_dbell =
+ rx->bna->pcidev.pci_bar_kva
+ + ntohl(cfg_rsp->q_handles[i].ql_dbell);
+ q0->hw_id = cfg_rsp->q_handles[i].hw_lqid;
+ if (q1) {
+ q1->rcb->q_dbell =
+ rx->bna->pcidev.pci_bar_kva
+ + ntohl(cfg_rsp->q_handles[i].qs_dbell);
+ q1->hw_id = cfg_rsp->q_handles[i].hw_sqid;
+ }
+
+ /* Initialize producer/consumer indexes */
+ (*rxp->cq.ccb->hw_producer_index) = 0;
+ rxp->cq.ccb->producer_index = 0;
+ q0->rcb->producer_index = q0->rcb->consumer_index = 0;
+ if (q1)
+ q1->rcb->producer_index = q1->rcb->consumer_index = 0;
+ }
+
+ bfa_fsm_send_event(rx, RX_E_STARTED);
+}
+
+void
+bna_bfi_rx_enet_stop_rsp(struct bna_rx *rx, struct bfi_msgq_mhdr *msghdr)
+{
+ bfa_fsm_send_event(rx, RX_E_STOPPED);
+}
+
+void
+bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info)
+{
+ u32 cq_size, hq_size, dq_size;
+ u32 cpage_count, hpage_count, dpage_count;
+ struct bna_mem_info *mem_info;
+ u32 cq_depth;
+ u32 hq_depth;
+ u32 dq_depth;
+
+ dq_depth = q_cfg->q_depth;
+ hq_depth = ((q_cfg->rxp_type == BNA_RXP_SINGLE) ? 0 : q_cfg->q_depth);
+ cq_depth = dq_depth + hq_depth;
+
+ BNA_TO_POWER_OF_2_HIGH(cq_depth);
+ cq_size = cq_depth * BFI_CQ_WI_SIZE;
+ cq_size = ALIGN(cq_size, PAGE_SIZE);
+ cpage_count = SIZE_TO_PAGES(cq_size);
+
+ BNA_TO_POWER_OF_2_HIGH(dq_depth);
+ dq_size = dq_depth * BFI_RXQ_WI_SIZE;
+ dq_size = ALIGN(dq_size, PAGE_SIZE);
+ dpage_count = SIZE_TO_PAGES(dq_size);
+
+ if (BNA_RXP_SINGLE != q_cfg->rxp_type) {
+ BNA_TO_POWER_OF_2_HIGH(hq_depth);
+ hq_size = hq_depth * BFI_RXQ_WI_SIZE;
+ hq_size = ALIGN(hq_size, PAGE_SIZE);
+ hpage_count = SIZE_TO_PAGES(hq_size);
+ } else
+ hpage_count = 0;
+
+ res_info[BNA_RX_RES_MEM_T_CCB].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = sizeof(struct bna_ccb);
+ mem_info->num = q_cfg->num_paths;
+
+ res_info[BNA_RX_RES_MEM_T_RCB].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = sizeof(struct bna_rcb);
+ mem_info->num = BNA_GET_RXQS(q_cfg);
+
+ res_info[BNA_RX_RES_MEM_T_CQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = cpage_count * sizeof(struct bna_dma_addr);
+ mem_info->num = q_cfg->num_paths;
+
+ res_info[BNA_RX_RES_MEM_T_CSWQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = cpage_count * sizeof(void *);
+ mem_info->num = q_cfg->num_paths;
+
+ 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;
+
+ 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;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = dpage_count * sizeof(struct bna_dma_addr);
+ mem_info->num = q_cfg->num_paths;
+
+ res_info[BNA_RX_RES_MEM_T_DSWQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = dpage_count * sizeof(void *);
+ mem_info->num = q_cfg->num_paths;
+
+ 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;
+
+ 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;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = hpage_count * sizeof(struct bna_dma_addr);
+ mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
+
+ res_info[BNA_RX_RES_MEM_T_HSWQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = hpage_count * sizeof(void *);
+ mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
+
+ 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);
+
+ 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;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = BFI_IBIDX_SIZE;
+ mem_info->num = q_cfg->num_paths;
+
+ res_info[BNA_RX_RES_MEM_T_RIT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_RIT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = BFI_ENET_RSS_RIT_MAX;
+ mem_info->num = 1;
+
+ res_info[BNA_RX_RES_T_INTR].res_type = BNA_RES_T_INTR;
+ res_info[BNA_RX_RES_T_INTR].res_u.intr_info.intr_type = BNA_INTR_T_MSIX;
+ res_info[BNA_RX_RES_T_INTR].res_u.intr_info.num = q_cfg->num_paths;
+}
+
+struct bna_rx *
+bna_rx_create(struct bna *bna, struct bnad *bnad,
+ struct bna_rx_config *rx_cfg,
+ const struct bna_rx_event_cbfn *rx_cbfn,
+ struct bna_res_info *res_info,
+ void *priv)
+{
+ struct bna_rx_mod *rx_mod = &bna->rx_mod;
+ struct bna_rx *rx;
+ struct bna_rxp *rxp;
+ struct bna_rxq *q0;
+ struct bna_rxq *q1;
+ struct bna_intr_info *intr_info;
+ u32 page_count;
+ struct bna_mem_descr *ccb_mem;
+ struct bna_mem_descr *rcb_mem;
+ struct bna_mem_descr *unmapq_mem;
+ struct bna_mem_descr *cqpt_mem;
+ struct bna_mem_descr *cswqpt_mem;
+ struct bna_mem_descr *cpage_mem;
+ struct bna_mem_descr *hqpt_mem;
+ struct bna_mem_descr *dqpt_mem;
+ struct bna_mem_descr *hsqpt_mem;
+ 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 dpage_count, hpage_count, rcb_idx;
+
+ if (!bna_rx_res_check(rx_mod, rx_cfg))
+ return NULL;
+
+ intr_info = &res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
+ ccb_mem = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info.mdl[0];
+ rcb_mem = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info.mdl[0];
+ unmapq_mem = &res_info[BNA_RX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[0];
+ cqpt_mem = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info.mdl[0];
+ cswqpt_mem = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info.mdl[0];
+ cpage_mem = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.mdl[0];
+ hqpt_mem = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info.mdl[0];
+ dqpt_mem = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info.mdl[0];
+ hsqpt_mem = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info.mdl[0];
+ dsqpt_mem = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info.mdl[0];
+ 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;
+
+ dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.num /
+ rx_cfg->num_paths;
+
+ hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.num /
+ rx_cfg->num_paths;
+
+ rx = bna_rx_get(rx_mod, rx_cfg->rx_type);
+ rx->bna = bna;
+ rx->rx_flags = 0;
+ INIT_LIST_HEAD(&rx->rxp_q);
+ rx->stop_cbfn = NULL;
+ rx->stop_cbarg = NULL;
+ rx->priv = priv;
+
+ rx->rcb_setup_cbfn = rx_cbfn->rcb_setup_cbfn;
+ rx->rcb_destroy_cbfn = rx_cbfn->rcb_destroy_cbfn;
+ rx->ccb_setup_cbfn = rx_cbfn->ccb_setup_cbfn;
+ rx->ccb_destroy_cbfn = rx_cbfn->ccb_destroy_cbfn;
+ rx->rx_stall_cbfn = rx_cbfn->rx_stall_cbfn;
+ /* Following callbacks are mandatory */
+ rx->rx_cleanup_cbfn = rx_cbfn->rx_cleanup_cbfn;
+ rx->rx_post_cbfn = rx_cbfn->rx_post_cbfn;
+
+ if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_ENET_STARTED) {
+ switch (rx->type) {
+ case BNA_RX_T_REGULAR:
+ if (!(rx->bna->rx_mod.flags &
+ BNA_RX_MOD_F_ENET_LOOPBACK))
+ rx->rx_flags |= BNA_RX_F_ENET_STARTED;
+ break;
+ case BNA_RX_T_LOOPBACK:
+ if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_ENET_LOOPBACK)
+ rx->rx_flags |= BNA_RX_F_ENET_STARTED;
+ break;
+ }
+ }
+
+ rx->num_paths = rx_cfg->num_paths;
+ for (i = 0, rcb_idx = 0; i < rx->num_paths; i++) {
+ rxp = bna_rxp_get(rx_mod);
+ list_add_tail(&rxp->qe, &rx->rxp_q);
+ rxp->type = rx_cfg->rxp_type;
+ rxp->rx = rx;
+ rxp->cq.rx = rx;
+
+ q0 = bna_rxq_get(rx_mod);
+ if (BNA_RXP_SINGLE == rx_cfg->rxp_type)
+ q1 = NULL;
+ else
+ q1 = bna_rxq_get(rx_mod);
+
+ if (1 == intr_info->num)
+ rxp->vector = intr_info->idl[0].vector;
+ else
+ rxp->vector = intr_info->idl[i].vector;
+
+ /* Setup IB */
+
+ rxp->cq.ib.ib_seg_host_addr.lsb =
+ res_info[BNA_RX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.lsb;
+ rxp->cq.ib.ib_seg_host_addr.msb =
+ res_info[BNA_RX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.msb;
+ rxp->cq.ib.ib_seg_host_addr_kva =
+ res_info[BNA_RX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].kva;
+ rxp->cq.ib.intr_type = intr_info->intr_type;
+ if (intr_info->intr_type == BNA_INTR_T_MSIX)
+ rxp->cq.ib.intr_vector = rxp->vector;
+ else
+ rxp->cq.ib.intr_vector = (1 << rxp->vector);
+ rxp->cq.ib.coalescing_timeo = rx_cfg->coalescing_timeo;
+ rxp->cq.ib.interpkt_count = BFI_RX_INTERPKT_COUNT;
+ rxp->cq.ib.interpkt_timeo = BFI_RX_INTERPKT_TIMEO;
+
+ bna_rxp_add_rxqs(rxp, q0, q1);
+
+ /* Setup large Q */
+
+ q0->rx = rx;
+ q0->rxp = rxp;
+
+ q0->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
+ q0->rcb->unmap_q = (void *)unmapq_mem[rcb_idx].kva;
+ rcb_idx++;
+ q0->rcb->q_depth = rx_cfg->q_depth;
+ q0->rcb->rxq = q0;
+ q0->rcb->bnad = bna->bnad;
+ q0->rcb->id = 0;
+ q0->rx_packets = q0->rx_bytes = 0;
+ 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;
+
+ if (rx->rcb_setup_cbfn)
+ rx->rcb_setup_cbfn(bnad, q0->rcb);
+
+ /* Setup small Q */
+
+ if (q1) {
+ q1->rx = rx;
+ q1->rxp = rxp;
+
+ q1->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
+ q1->rcb->unmap_q = (void *)unmapq_mem[rcb_idx].kva;
+ rcb_idx++;
+ q1->rcb->q_depth = rx_cfg->q_depth;
+ q1->rcb->rxq = q1;
+ q1->rcb->bnad = bna->bnad;
+ q1->rcb->id = 1;
+ q1->buffer_size = (rx_cfg->rxp_type == BNA_RXP_HDS) ?
+ rx_cfg->hds_config.forced_offset
+ : rx_cfg->small_buff_size;
+ q1->rx_packets = q1->rx_bytes = 0;
+ q1->rx_packets_with_error = q1->rxbuf_alloc_failed = 0;
+
+ 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;
+
+ if (rx->rcb_setup_cbfn)
+ rx->rcb_setup_cbfn(bnad, q1->rcb);
+ }
+
+ /* Setup CQ */
+
+ rxp->cq.ccb = (struct bna_ccb *) ccb_mem[i].kva;
+ rxp->cq.ccb->q_depth = rx_cfg->q_depth +
+ ((rx_cfg->rxp_type == BNA_RXP_SINGLE) ?
+ 0 : rx_cfg->q_depth);
+ rxp->cq.ccb->cq = &rxp->cq;
+ rxp->cq.ccb->rcb[0] = q0->rcb;
+ q0->rcb->ccb = rxp->cq.ccb;
+ if (q1) {
+ rxp->cq.ccb->rcb[1] = q1->rcb;
+ q1->rcb->ccb = rxp->cq.ccb;
+ }
+ rxp->cq.ccb->hw_producer_index =
+ (u32 *)rxp->cq.ib.ib_seg_host_addr_kva;
+ rxp->cq.ccb->i_dbell = &rxp->cq.ib.door_bell;
+ rxp->cq.ccb->intr_type = rxp->cq.ib.intr_type;
+ rxp->cq.ccb->intr_vector = rxp->cq.ib.intr_vector;
+ rxp->cq.ccb->rx_coalescing_timeo =
+ rxp->cq.ib.coalescing_timeo;
+ rxp->cq.ccb->pkt_rate.small_pkt_cnt = 0;
+ rxp->cq.ccb->pkt_rate.large_pkt_cnt = 0;
+ rxp->cq.ccb->bnad = bna->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;
+
+ if (rx->ccb_setup_cbfn)
+ rx->ccb_setup_cbfn(bnad, rxp->cq.ccb);
+ }
+
+ rx->hds_cfg = rx_cfg->hds_config;
+
+ bna_rxf_init(&rx->rxf, rx, rx_cfg, res_info);
+
+ bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+
+ rx_mod->rid_mask |= (1 << rx->rid);
+
+ return rx;
+}
+
+void
+bna_rx_destroy(struct bna_rx *rx)
+{
+ struct bna_rx_mod *rx_mod = &rx->bna->rx_mod;
+ struct bna_rxq *q0 = NULL;
+ struct bna_rxq *q1 = NULL;
+ struct bna_rxp *rxp;
+ struct list_head *qe;
+
+ bna_rxf_uninit(&rx->rxf);
+
+ while (!list_empty(&rx->rxp_q)) {
+ bfa_q_deq(&rx->rxp_q, &rxp);
+ GET_RXQS(rxp, q0, q1);
+ if (rx->rcb_destroy_cbfn)
+ rx->rcb_destroy_cbfn(rx->bna->bnad, q0->rcb);
+ q0->rcb = NULL;
+ q0->rxp = NULL;
+ q0->rx = NULL;
+ bna_rxq_put(rx_mod, q0);
+
+ if (q1) {
+ if (rx->rcb_destroy_cbfn)
+ rx->rcb_destroy_cbfn(rx->bna->bnad, q1->rcb);
+ q1->rcb = NULL;
+ q1->rxp = NULL;
+ q1->rx = NULL;
+ bna_rxq_put(rx_mod, q1);
+ }
+ rxp->rxq.slr.large = NULL;
+ rxp->rxq.slr.small = NULL;
+
+ if (rx->ccb_destroy_cbfn)
+ rx->ccb_destroy_cbfn(rx->bna->bnad, rxp->cq.ccb);
+ rxp->cq.ccb = NULL;
+ rxp->rx = NULL;
+ bna_rxp_put(rx_mod, rxp);
+ }
+
+ list_for_each(qe, &rx_mod->rx_active_q) {
+ if (qe == &rx->qe) {
+ list_del(&rx->qe);
+ bfa_q_qe_init(&rx->qe);
+ break;
+ }
+ }
+
+ rx_mod->rid_mask &= ~(1 << rx->rid);
+
+ rx->bna = NULL;
+ rx->priv = NULL;
+ bna_rx_put(rx_mod, rx);
+}
+
+void
+bna_rx_enable(struct bna_rx *rx)
+{
+ if (rx->fsm != (bfa_sm_t)bna_rx_sm_stopped)
+ return;
+
+ rx->rx_flags |= BNA_RX_F_ENABLED;
+ if (rx->rx_flags & BNA_RX_F_ENET_STARTED)
+ bfa_fsm_send_event(rx, RX_E_START);
+}
+
+void
+bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
+ void (*cbfn)(void *, struct bna_rx *))
+{
+ if (type == BNA_SOFT_CLEANUP) {
+ /* h/w should not be accessed. Treat we're stopped */
+ (*cbfn)(rx->bna->bnad, rx);
+ } else {
+ rx->stop_cbfn = cbfn;
+ rx->stop_cbarg = rx->bna->bnad;
+
+ rx->rx_flags &= ~BNA_RX_F_ENABLED;
+
+ bfa_fsm_send_event(rx, RX_E_STOP);
+ }
+}
+
+void
+bna_rx_cleanup_complete(struct bna_rx *rx)
+{
+ bfa_fsm_send_event(rx, RX_E_CLEANUP_DONE);
+}
+
+enum bna_cb_status
+bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode,
+ enum bna_rxmode bitmask,
+ void (*cbfn)(struct bnad *, struct bna_rx *))
+{
+ struct bna_rxf *rxf = &rx->rxf;
+ int need_hw_config = 0;
+
+ /* Error checks */
+
+ if (is_promisc_enable(new_mode, bitmask)) {
+ /* If promisc mode is already enabled elsewhere in the system */
+ if ((rx->bna->promisc_rid != BFI_INVALID_RID) &&
+ (rx->bna->promisc_rid != rxf->rx->rid))
+ goto err_return;
+
+ /* If default mode is already enabled in the system */
+ if (rx->bna->default_mode_rid != BFI_INVALID_RID)
+ goto err_return;
+
+ /* Trying to enable promiscuous and default mode together */
+ if (is_default_enable(new_mode, bitmask))
+ goto err_return;
+ }
+
+ if (is_default_enable(new_mode, bitmask)) {
+ /* If default mode is already enabled elsewhere in the system */
+ if ((rx->bna->default_mode_rid != BFI_INVALID_RID) &&
+ (rx->bna->default_mode_rid != rxf->rx->rid)) {
+ goto err_return;
+ }
+
+ /* If promiscuous mode is already enabled in the system */
+ if (rx->bna->promisc_rid != BFI_INVALID_RID)
+ goto err_return;
+ }
+
+ /* Process the commands */
+
+ if (is_promisc_enable(new_mode, bitmask)) {
+ if (bna_rxf_promisc_enable(rxf))
+ need_hw_config = 1;
+ } else if (is_promisc_disable(new_mode, bitmask)) {
+ if (bna_rxf_promisc_disable(rxf))
+ need_hw_config = 1;
+ }
+
+ if (is_allmulti_enable(new_mode, bitmask)) {
+ if (bna_rxf_allmulti_enable(rxf))
+ need_hw_config = 1;
+ } else if (is_allmulti_disable(new_mode, bitmask)) {
+ if (bna_rxf_allmulti_disable(rxf))
+ need_hw_config = 1;
+ }
+
+ /* Trigger h/w if needed */
+
+ if (need_hw_config) {
+ rxf->cam_fltr_cbfn = cbfn;
+ rxf->cam_fltr_cbarg = rx->bna->bnad;
+ bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+ } else if (cbfn)
+ (*cbfn)(rx->bna->bnad, rx);
+
+ return BNA_CB_SUCCESS;
+
+err_return:
+ return BNA_CB_FAIL;
+}
+
+void
+bna_rx_vlanfilter_enable(struct bna_rx *rx)
+{
+ struct bna_rxf *rxf = &rx->rxf;
+
+ if (rxf->vlan_filter_status == BNA_STATUS_T_DISABLED) {
+ rxf->vlan_filter_status = BNA_STATUS_T_ENABLED;
+ rxf->vlan_pending_bitmask = (u8)BFI_VLAN_BMASK_ALL;
+ bfa_fsm_send_event(rxf, RXF_E_CONFIG);
+ }
+}
+
+void
+bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo)
+{
+ struct bna_rxp *rxp;
+ struct list_head *qe;
+
+ list_for_each(qe, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe;
+ rxp->cq.ccb->rx_coalescing_timeo = coalescing_timeo;
+ bna_ib_coalescing_timeo_set(&rxp->cq.ib, coalescing_timeo);
+ }
+}
+
+void
+bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX])
+{
+ int i, j;
+
+ for (i = 0; i < BNA_LOAD_T_MAX; i++)
+ for (j = 0; j < BNA_BIAS_T_MAX; j++)
+ bna->rx_mod.dim_vector[i][j] = vector[i][j];
+}
+
+void
+bna_rx_dim_update(struct bna_ccb *ccb)
+{
+ struct bna *bna = ccb->cq->rx->bna;
+ u32 load, bias;
+ u32 pkt_rt, small_rt, large_rt;
+ u8 coalescing_timeo;
+
+ if ((ccb->pkt_rate.small_pkt_cnt == 0) &&
+ (ccb->pkt_rate.large_pkt_cnt == 0))
+ return;
+
+ /* Arrive at preconfigured coalescing timeo value based on pkt rate */
+
+ small_rt = ccb->pkt_rate.small_pkt_cnt;
+ large_rt = ccb->pkt_rate.large_pkt_cnt;
+
+ pkt_rt = small_rt + large_rt;
+
+ if (pkt_rt < BNA_PKT_RATE_10K)
+ load = BNA_LOAD_T_LOW_4;
+ else if (pkt_rt < BNA_PKT_RATE_20K)
+ load = BNA_LOAD_T_LOW_3;
+ else if (pkt_rt < BNA_PKT_RATE_30K)
+ load = BNA_LOAD_T_LOW_2;
+ else if (pkt_rt < BNA_PKT_RATE_40K)
+ load = BNA_LOAD_T_LOW_1;
+ else if (pkt_rt < BNA_PKT_RATE_50K)
+ load = BNA_LOAD_T_HIGH_1;
+ else if (pkt_rt < BNA_PKT_RATE_60K)
+ load = BNA_LOAD_T_HIGH_2;
+ else if (pkt_rt < BNA_PKT_RATE_80K)
+ load = BNA_LOAD_T_HIGH_3;
+ else
+ load = BNA_LOAD_T_HIGH_4;
+
+ if (small_rt > (large_rt << 1))
+ bias = 0;
+ else
+ bias = 1;
+
+ ccb->pkt_rate.small_pkt_cnt = 0;
+ ccb->pkt_rate.large_pkt_cnt = 0;
+
+ coalescing_timeo = bna->rx_mod.dim_vector[load][bias];
+ ccb->rx_coalescing_timeo = coalescing_timeo;
+
+ /* Set it to IB */
+ bna_ib_coalescing_timeo_set(&ccb->cq->ib, coalescing_timeo);
+}
+
+const u32 bna_napi_dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX] = {
+ {12, 12},
+ {6, 10},
+ {5, 10},
+ {4, 8},
+ {3, 6},
+ {3, 6},
+ {2, 4},
+ {1, 2},
+};
+
+/**
+ * TX
+ */
+#define call_tx_stop_cbfn(tx) \
+do { \
+ if ((tx)->stop_cbfn) { \
+ void (*cbfn)(void *, struct bna_tx *); \
+ void *cbarg; \
+ cbfn = (tx)->stop_cbfn; \
+ cbarg = (tx)->stop_cbarg; \
+ (tx)->stop_cbfn = NULL; \
+ (tx)->stop_cbarg = NULL; \
+ cbfn(cbarg, (tx)); \
+ } \
+} while (0)
+
+#define call_tx_prio_change_cbfn(tx) \
+do { \
+ if ((tx)->prio_change_cbfn) { \
+ void (*cbfn)(struct bnad *, struct bna_tx *); \
+ cbfn = (tx)->prio_change_cbfn; \
+ (tx)->prio_change_cbfn = NULL; \
+ cbfn((tx)->bna->bnad, (tx)); \
+ } \
+} while (0)
+
+static void bna_tx_mod_cb_tx_stopped(void *tx_mod, struct bna_tx *tx);
+static void bna_bfi_tx_enet_start(struct bna_tx *tx);
+static void bna_tx_enet_stop(struct bna_tx *tx);
+
+enum bna_tx_event {
+ TX_E_START = 1,
+ TX_E_STOP = 2,
+ TX_E_FAIL = 3,
+ TX_E_STARTED = 4,
+ TX_E_STOPPED = 5,
+ TX_E_PRIO_CHANGE = 6,
+ TX_E_CLEANUP_DONE = 7,
+ TX_E_BW_UPDATE = 8,
+};
+
+bfa_fsm_state_decl(bna_tx, stopped, struct bna_tx, enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, start_wait, struct bna_tx, enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, started, struct bna_tx, enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, stop_wait, struct bna_tx, enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, cleanup_wait, struct bna_tx,
+ enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, prio_stop_wait, struct bna_tx,
+ enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, prio_cleanup_wait, struct bna_tx,
+ enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, failed, struct bna_tx, enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, quiesce_wait, struct bna_tx,
+ enum bna_tx_event);
+
+static void
+bna_tx_sm_stopped_entry(struct bna_tx *tx)
+{
+ call_tx_stop_cbfn(tx);
+}
+
+static void
+bna_tx_sm_stopped(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_START:
+ bfa_fsm_set_state(tx, bna_tx_sm_start_wait);
+ break;
+
+ case TX_E_STOP:
+ call_tx_stop_cbfn(tx);
+ break;
+
+ case TX_E_FAIL:
+ /* No-op */
+ break;
+
+ case TX_E_PRIO_CHANGE:
+ call_tx_prio_change_cbfn(tx);
+ break;
+
+ case TX_E_BW_UPDATE:
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_tx_sm_start_wait_entry(struct bna_tx *tx)
+{
+ bna_bfi_tx_enet_start(tx);
+}
+
+static void
+bna_tx_sm_start_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_STOP:
+ tx->flags &= ~(BNA_TX_F_PRIO_CHANGED | BNA_TX_F_BW_UPDATED);
+ bfa_fsm_set_state(tx, bna_tx_sm_stop_wait);
+ break;
+
+ case TX_E_FAIL:
+ tx->flags &= ~(BNA_TX_F_PRIO_CHANGED | BNA_TX_F_BW_UPDATED);
+ bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+ break;
+
+ case TX_E_STARTED:
+ if (tx->flags & (BNA_TX_F_PRIO_CHANGED | BNA_TX_F_BW_UPDATED)) {
+ tx->flags &= ~(BNA_TX_F_PRIO_CHANGED |
+ BNA_TX_F_BW_UPDATED);
+ bfa_fsm_set_state(tx, bna_tx_sm_prio_stop_wait);
+ } else
+ bfa_fsm_set_state(tx, bna_tx_sm_started);
+ break;
+
+ case TX_E_PRIO_CHANGE:
+ tx->flags |= BNA_TX_F_PRIO_CHANGED;
+ break;
+
+ case TX_E_BW_UPDATE:
+ tx->flags |= BNA_TX_F_BW_UPDATED;
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_tx_sm_started_entry(struct bna_tx *tx)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+ int is_regular = (tx->type == BNA_TX_T_REGULAR);
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ txq->tcb->priority = txq->priority;
+ /* Start IB */
+ bna_ib_start(tx->bna, &txq->ib, is_regular);
+ }
+ tx->tx_resume_cbfn(tx->bna->bnad, tx);
+}
+
+static void
+bna_tx_sm_started(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_STOP:
+ bfa_fsm_set_state(tx, bna_tx_sm_stop_wait);
+ tx->tx_stall_cbfn(tx->bna->bnad, tx);
+ bna_tx_enet_stop(tx);
+ break;
+
+ case TX_E_FAIL:
+ bfa_fsm_set_state(tx, bna_tx_sm_failed);
+ tx->tx_stall_cbfn(tx->bna->bnad, tx);
+ tx->tx_cleanup_cbfn(tx->bna->bnad, tx);
+ break;
+
+ case TX_E_PRIO_CHANGE:
+ case TX_E_BW_UPDATE:
+ bfa_fsm_set_state(tx, bna_tx_sm_prio_stop_wait);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_tx_sm_stop_wait_entry(struct bna_tx *tx)
+{
+}
+
+static void
+bna_tx_sm_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_FAIL:
+ case TX_E_STOPPED:
+ bfa_fsm_set_state(tx, bna_tx_sm_cleanup_wait);
+ tx->tx_cleanup_cbfn(tx->bna->bnad, tx);
+ break;
+
+ case TX_E_STARTED:
+ /**
+ * We are here due to start_wait -> stop_wait transition on
+ * TX_E_STOP event
+ */
+ bna_tx_enet_stop(tx);
+ break;
+
+ case TX_E_PRIO_CHANGE:
+ case TX_E_BW_UPDATE:
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_tx_sm_cleanup_wait_entry(struct bna_tx *tx)
+{
+}
+
+static void
+bna_tx_sm_cleanup_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_FAIL:
+ case TX_E_PRIO_CHANGE:
+ case TX_E_BW_UPDATE:
+ /* No-op */
+ break;
+
+ case TX_E_CLEANUP_DONE:
+ bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_tx_sm_prio_stop_wait_entry(struct bna_tx *tx)
+{
+ tx->tx_stall_cbfn(tx->bna->bnad, tx);
+ bna_tx_enet_stop(tx);
+}
+
+static void
+bna_tx_sm_prio_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_STOP:
+ bfa_fsm_set_state(tx, bna_tx_sm_stop_wait);
+ break;
+
+ case TX_E_FAIL:
+ bfa_fsm_set_state(tx, bna_tx_sm_failed);
+ call_tx_prio_change_cbfn(tx);
+ tx->tx_cleanup_cbfn(tx->bna->bnad, tx);
+ break;
+
+ case TX_E_STOPPED:
+ bfa_fsm_set_state(tx, bna_tx_sm_prio_cleanup_wait);
+ break;
+
+ case TX_E_PRIO_CHANGE:
+ case TX_E_BW_UPDATE:
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_tx_sm_prio_cleanup_wait_entry(struct bna_tx *tx)
+{
+ call_tx_prio_change_cbfn(tx);
+ tx->tx_cleanup_cbfn(tx->bna->bnad, tx);
+}
+
+static void
+bna_tx_sm_prio_cleanup_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_STOP:
+ bfa_fsm_set_state(tx, bna_tx_sm_cleanup_wait);
+ break;
+
+ case TX_E_FAIL:
+ bfa_fsm_set_state(tx, bna_tx_sm_failed);
+ break;
+
+ case TX_E_PRIO_CHANGE:
+ case TX_E_BW_UPDATE:
+ /* No-op */
+ break;
+
+ case TX_E_CLEANUP_DONE:
+ bfa_fsm_set_state(tx, bna_tx_sm_start_wait);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_tx_sm_failed_entry(struct bna_tx *tx)
+{
+}
+
+static void
+bna_tx_sm_failed(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_START:
+ bfa_fsm_set_state(tx, bna_tx_sm_quiesce_wait);
+ break;
+
+ case TX_E_STOP:
+ bfa_fsm_set_state(tx, bna_tx_sm_cleanup_wait);
+ break;
+
+ case TX_E_FAIL:
+ /* No-op */
+ break;
+
+ case TX_E_CLEANUP_DONE:
+ bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_tx_sm_quiesce_wait_entry(struct bna_tx *tx)
+{
+}
+
+static void
+bna_tx_sm_quiesce_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_STOP:
+ bfa_fsm_set_state(tx, bna_tx_sm_cleanup_wait);
+ break;
+
+ case TX_E_FAIL:
+ bfa_fsm_set_state(tx, bna_tx_sm_failed);
+ break;
+
+ case TX_E_CLEANUP_DONE:
+ bfa_fsm_set_state(tx, bna_tx_sm_start_wait);
+ break;
+
+ case TX_E_BW_UPDATE:
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(event);
+ }
+}
+
+static void
+bna_bfi_tx_enet_start(struct bna_tx *tx)
+{
+ struct bfi_enet_tx_cfg_req *cfg_req = &tx->bfi_enet_cmd.cfg_req;
+ struct bna_txq *txq = NULL;
+ struct list_head *qe;
+ int i;
+
+ bfi_msgq_mhdr_set(cfg_req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_TX_CFG_SET_REQ, 0, tx->rid);
+ cfg_req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_tx_cfg_req)));
+
+ cfg_req->num_queues = tx->num_txq;
+ for (i = 0, qe = bfa_q_first(&tx->txq_q);
+ i < tx->num_txq;
+ i++, qe = bfa_q_next(qe)) {
+ txq = (struct bna_txq *)qe;
+
+ bfi_enet_datapath_q_init(&cfg_req->q_cfg[i].q.q, &txq->qpt);
+ cfg_req->q_cfg[i].q.priority = txq->priority;
+
+ cfg_req->q_cfg[i].ib.index_addr.a32.addr_lo =
+ txq->ib.ib_seg_host_addr.lsb;
+ cfg_req->q_cfg[i].ib.index_addr.a32.addr_hi =
+ txq->ib.ib_seg_host_addr.msb;
+ cfg_req->q_cfg[i].ib.intr.msix_index =
+ htons((u16)txq->ib.intr_vector);
+ }
+
+ cfg_req->ib_cfg.int_pkt_dma = BNA_STATUS_T_ENABLED;
+ cfg_req->ib_cfg.int_enabled = BNA_STATUS_T_ENABLED;
+ cfg_req->ib_cfg.int_pkt_enabled = BNA_STATUS_T_DISABLED;
+ cfg_req->ib_cfg.continuous_coalescing = BNA_STATUS_T_ENABLED;
+ cfg_req->ib_cfg.msix = (txq->ib.intr_type == BNA_INTR_T_MSIX)
+ ? BNA_STATUS_T_ENABLED : BNA_STATUS_T_DISABLED;
+ cfg_req->ib_cfg.coalescing_timeout =
+ htonl((u32)txq->ib.coalescing_timeo);
+ cfg_req->ib_cfg.inter_pkt_timeout =
+ htonl((u32)txq->ib.interpkt_timeo);
+ cfg_req->ib_cfg.inter_pkt_count = (u8)txq->ib.interpkt_count;
+
+ cfg_req->tx_cfg.vlan_mode = BFI_ENET_TX_VLAN_WI;
+ cfg_req->tx_cfg.vlan_id = htons((u16)tx->txf_vlan_id);
+ cfg_req->tx_cfg.admit_tagged_frame = BNA_STATUS_T_DISABLED;
+ cfg_req->tx_cfg.apply_vlan_filter = BNA_STATUS_T_DISABLED;
+
+ bfa_msgq_cmd_set(&tx->msgq_cmd, NULL, NULL,
+ sizeof(struct bfi_enet_tx_cfg_req), &cfg_req->mh);
+ bfa_msgq_cmd_post(&tx->bna->msgq, &tx->msgq_cmd);
+}
+
+static void
+bna_bfi_tx_enet_stop(struct bna_tx *tx)
+{
+ struct bfi_enet_req *req = &tx->bfi_enet_cmd.req;
+
+ bfi_msgq_mhdr_set(req->mh, BFI_MC_ENET,
+ BFI_ENET_H2I_TX_CFG_CLR_REQ, 0, tx->rid);
+ req->mh.num_entries = htons(
+ bfi_msgq_num_cmd_entries(sizeof(struct bfi_enet_req)));
+ bfa_msgq_cmd_set(&tx->msgq_cmd, NULL, NULL, sizeof(struct bfi_enet_req),
+ &req->mh);
+ bfa_msgq_cmd_post(&tx->bna->msgq, &tx->msgq_cmd);
+}
+
+static void
+bna_tx_enet_stop(struct bna_tx *tx)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ /* Stop IB */
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ bna_ib_stop(tx->bna, &txq->ib);
+ }
+
+ bna_bfi_tx_enet_stop(tx);
+}
+
+static void
+bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size,
+ struct bna_mem_descr *qpt_mem,
+ struct bna_mem_descr *swqpt_mem,
+ struct bna_mem_descr *page_mem)
+{
+ int i;
+
+ txq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+ txq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+ txq->qpt.kv_qpt_ptr = qpt_mem->kva;
+ txq->qpt.page_count = page_count;
+ txq->qpt.page_size = page_size;
+
+ txq->tcb->sw_qpt = (void **) swqpt_mem->kva;
+
+ for (i = 0; i < page_count; i++) {
+ txq->tcb->sw_qpt[i] = page_mem[i].kva;
+
+ ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].lsb =
+ page_mem[i].dma.lsb;
+ ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].msb =
+ page_mem[i].dma.msb;
+ }
+}
+
+static struct bna_tx *
+bna_tx_get(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
+{
+ struct list_head *qe = NULL;
+ struct bna_tx *tx = NULL;
+
+ if (list_empty(&tx_mod->tx_free_q))
+ return NULL;
+ if (type == BNA_TX_T_REGULAR) {
+ bfa_q_deq(&tx_mod->tx_free_q, &qe);
+ } else {
+ bfa_q_deq_tail(&tx_mod->tx_free_q, &qe);
+ }
+ tx = (struct bna_tx *)qe;
+ bfa_q_qe_init(&tx->qe);
+ tx->type = type;
+
+ return tx;
+}
+
+static void
+bna_tx_free(struct bna_tx *tx)
+{
+ struct bna_tx_mod *tx_mod = &tx->bna->tx_mod;
+ struct bna_txq *txq;
+ struct list_head *prev_qe;
+ struct list_head *qe;
+
+ while (!list_empty(&tx->txq_q)) {
+ bfa_q_deq(&tx->txq_q, &txq);
+ bfa_q_qe_init(&txq->qe);
+ txq->tcb = NULL;
+ txq->tx = NULL;
+ list_add_tail(&txq->qe, &tx_mod->txq_free_q);
+ }
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ if (qe == &tx->qe) {
+ list_del(&tx->qe);
+ bfa_q_qe_init(&tx->qe);
+ break;
+ }
+ }
+
+ tx->bna = NULL;
+ tx->priv = NULL;
+
+ prev_qe = NULL;
+ list_for_each(qe, &tx_mod->tx_free_q) {
+ if (((struct bna_tx *)qe)->rid < tx->rid)
+ prev_qe = qe;
+ else {
+ break;
+ }
+ }
+
+ if (prev_qe == NULL) {
+ /* This is the first entry */
+ bfa_q_enq_head(&tx_mod->tx_free_q, &tx->qe);
+ } else if (bfa_q_next(prev_qe) == &tx_mod->tx_free_q) {
+ /* This is the last entry */
+ list_add_tail(&tx->qe, &tx_mod->tx_free_q);
+ } else {
+ /* Somewhere in the middle */
+ bfa_q_next(&tx->qe) = bfa_q_next(prev_qe);
+ bfa_q_prev(&tx->qe) = prev_qe;
+ bfa_q_next(prev_qe) = &tx->qe;
+ bfa_q_prev(bfa_q_next(&tx->qe)) = &tx->qe;
+ }
+}
+
+static void
+bna_tx_start(struct bna_tx *tx)
+{
+ tx->flags |= BNA_TX_F_ENET_STARTED;
+ if (tx->flags & BNA_TX_F_ENABLED)
+ bfa_fsm_send_event(tx, TX_E_START);
+}
+
+static void
+bna_tx_stop(struct bna_tx *tx)
+{
+ tx->stop_cbfn = bna_tx_mod_cb_tx_stopped;
+ tx->stop_cbarg = &tx->bna->tx_mod;
+
+ tx->flags &= ~BNA_TX_F_ENET_STARTED;
+ bfa_fsm_send_event(tx, TX_E_STOP);
+}
+
+static void
+bna_tx_fail(struct bna_tx *tx)
+{
+ tx->flags &= ~BNA_TX_F_ENET_STARTED;
+ bfa_fsm_send_event(tx, TX_E_FAIL);
+}
+
+void
+bna_bfi_tx_enet_start_rsp(struct bna_tx *tx, struct bfi_msgq_mhdr *msghdr)
+{
+ struct bfi_enet_tx_cfg_rsp *cfg_rsp = &tx->bfi_enet_cmd.cfg_rsp;
+ struct bna_txq *txq = NULL;
+ struct list_head *qe;
+ int i;
+
+ bfa_msgq_rsp_copy(&tx->bna->msgq, (u8 *)cfg_rsp,
+ sizeof(struct bfi_enet_tx_cfg_rsp));
+
+ tx->hw_id = cfg_rsp->hw_id;
+
+ for (i = 0, qe = bfa_q_first(&tx->txq_q);
+ i < tx->num_txq; i++, qe = bfa_q_next(qe)) {
+ txq = (struct bna_txq *)qe;
+
+ /* Setup doorbells */
+ txq->tcb->i_dbell->doorbell_addr =
+ tx->bna->pcidev.pci_bar_kva
+ + ntohl(cfg_rsp->q_handles[i].i_dbell);
+ txq->tcb->q_dbell =
+ tx->bna->pcidev.pci_bar_kva
+ + ntohl(cfg_rsp->q_handles[i].q_dbell);
+ txq->hw_id = cfg_rsp->q_handles[i].hw_qid;
+
+ /* Initialize producer/consumer indexes */
+ (*txq->tcb->hw_consumer_index) = 0;
+ txq->tcb->producer_index = txq->tcb->consumer_index = 0;
+ }
+
+ bfa_fsm_send_event(tx, TX_E_STARTED);
+}
+
+void
+bna_bfi_tx_enet_stop_rsp(struct bna_tx *tx, struct bfi_msgq_mhdr *msghdr)
+{
+ bfa_fsm_send_event(tx, TX_E_STOPPED);
+}
+
+void
+bna_bfi_bw_update_aen(struct bna_tx_mod *tx_mod)
+{
+ struct bna_tx *tx;
+ struct list_head *qe;
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ bfa_fsm_send_event(tx, TX_E_BW_UPDATE);
+ }
+}
+
+void
+bna_tx_res_req(int num_txq, int txq_depth, struct bna_res_info *res_info)
+{
+ u32 q_size;
+ u32 page_count;
+ struct bna_mem_info *mem_info;
+
+ res_info[BNA_TX_RES_MEM_T_TCB].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = sizeof(struct bna_tcb);
+ mem_info->num = num_txq;
+
+ q_size = txq_depth * BFI_TXQ_WI_SIZE;
+ q_size = ALIGN(q_size, PAGE_SIZE);
+ page_count = q_size >> PAGE_SHIFT;
+
+ res_info[BNA_TX_RES_MEM_T_QPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = page_count * sizeof(struct bna_dma_addr);
+ mem_info->num = num_txq;
+
+ res_info[BNA_TX_RES_MEM_T_SWQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = page_count * sizeof(void *);
+ mem_info->num = num_txq;
+
+ 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;
+
+ 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;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = BFI_IBIDX_SIZE;
+ mem_info->num = num_txq;
+
+ res_info[BNA_TX_RES_INTR_T_TXCMPL].res_type = BNA_RES_T_INTR;
+ res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.intr_type =
+ BNA_INTR_T_MSIX;
+ res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.num = num_txq;
+}
+
+struct bna_tx *
+bna_tx_create(struct bna *bna, struct bnad *bnad,
+ struct bna_tx_config *tx_cfg,
+ const struct bna_tx_event_cbfn *tx_cbfn,
+ struct bna_res_info *res_info, void *priv)
+{
+ struct bna_intr_info *intr_info;
+ struct bna_tx_mod *tx_mod = &bna->tx_mod;
+ struct bna_tx *tx;
+ 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;
+
+ /**
+ * Get resources
+ */
+
+ if ((intr_info->num != 1) && (intr_info->num != tx_cfg->num_txq))
+ return NULL;
+
+ /* Tx */
+
+ tx = bna_tx_get(tx_mod, tx_cfg->tx_type);
+ if (!tx)
+ return NULL;
+ tx->bna = bna;
+ tx->priv = priv;
+
+ /* TxQs */
+
+ INIT_LIST_HEAD(&tx->txq_q);
+ for (i = 0; i < tx_cfg->num_txq; i++) {
+ if (list_empty(&tx_mod->txq_free_q))
+ goto err_return;
+
+ bfa_q_deq(&tx_mod->txq_free_q, &txq);
+ bfa_q_qe_init(&txq->qe);
+ list_add_tail(&txq->qe, &tx->txq_q);
+ txq->tx = tx;
+ }
+
+ /*
+ * Initialize
+ */
+
+ /* Tx */
+
+ tx->tcb_setup_cbfn = tx_cbfn->tcb_setup_cbfn;
+ tx->tcb_destroy_cbfn = tx_cbfn->tcb_destroy_cbfn;
+ /* Following callbacks are mandatory */
+ tx->tx_stall_cbfn = tx_cbfn->tx_stall_cbfn;
+ tx->tx_resume_cbfn = tx_cbfn->tx_resume_cbfn;
+ tx->tx_cleanup_cbfn = tx_cbfn->tx_cleanup_cbfn;
+
+ list_add_tail(&tx->qe, &tx_mod->tx_active_q);
+
+ tx->num_txq = tx_cfg->num_txq;
+
+ tx->flags = 0;
+ if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_ENET_STARTED) {
+ switch (tx->type) {
+ case BNA_TX_T_REGULAR:
+ if (!(tx->bna->tx_mod.flags &
+ BNA_TX_MOD_F_ENET_LOOPBACK))
+ tx->flags |= BNA_TX_F_ENET_STARTED;
+ break;
+ case BNA_TX_T_LOOPBACK:
+ if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_ENET_LOOPBACK)
+ tx->flags |= BNA_TX_F_ENET_STARTED;
+ break;
+ }
+ }
+
+ /* TxQ */
+
+ i = 0;
+ page_idx = 0;
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ txq->tcb = (struct bna_tcb *)
+ res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info.mdl[i].kva;
+ txq->tx_packets = 0;
+ txq->tx_bytes = 0;
+
+ /* IB */
+ txq->ib.ib_seg_host_addr.lsb =
+ res_info[BNA_TX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.lsb;
+ txq->ib.ib_seg_host_addr.msb =
+ res_info[BNA_TX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.msb;
+ txq->ib.ib_seg_host_addr_kva =
+ res_info[BNA_TX_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].kva;
+ txq->ib.intr_type = intr_info->intr_type;
+ txq->ib.intr_vector = (intr_info->num == 1) ?
+ intr_info->idl[0].vector :
+ intr_info->idl[i].vector;
+ 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_count = BFI_TX_INTERPKT_COUNT;
+
+ /* TCB */
+
+ txq->tcb->q_depth = tx_cfg->txq_depth;
+ txq->tcb->unmap_q = (void *)
+ res_info[BNA_TX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[i].kva;
+ txq->tcb->hw_consumer_index =
+ (u32 *)txq->ib.ib_seg_host_addr_kva;
+ txq->tcb->i_dbell = &txq->ib.door_bell;
+ txq->tcb->intr_type = txq->ib.intr_type;
+ txq->tcb->intr_vector = txq->ib.intr_vector;
+ txq->tcb->txq = txq;
+ txq->tcb->bnad = bnad;
+ txq->tcb->id = i;
+
+ /* QPT, SWQPT, Pages */
+ 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;
+
+ /* Callback to bnad for setting up TCB */
+ if (tx->tcb_setup_cbfn)
+ (tx->tcb_setup_cbfn)(bna->bnad, txq->tcb);
+
+ if (tx_cfg->num_txq == BFI_TX_MAX_PRIO)
+ txq->priority = txq->tcb->id;
+ else
+ txq->priority = tx_mod->default_prio;
+
+ i++;
+ }
+
+ tx->txf_vlan_id = 0;
+
+ bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+
+ tx_mod->rid_mask |= (1 << tx->rid);
+
+ return tx;
+
+err_return:
+ bna_tx_free(tx);
+ return NULL;
+}
+
+void
+bna_tx_destroy(struct bna_tx *tx)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ if (tx->tcb_destroy_cbfn)
+ (tx->tcb_destroy_cbfn)(tx->bna->bnad, txq->tcb);
+ }
+
+ tx->bna->tx_mod.rid_mask &= ~(1 << tx->rid);
+ bna_tx_free(tx);
+}
+
+void
+bna_tx_enable(struct bna_tx *tx)
+{
+ if (tx->fsm != (bfa_sm_t)bna_tx_sm_stopped)
+ return;
+
+ tx->flags |= BNA_TX_F_ENABLED;
+
+ if (tx->flags & BNA_TX_F_ENET_STARTED)
+ bfa_fsm_send_event(tx, TX_E_START);
+}
+
+void
+bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
+ void (*cbfn)(void *, struct bna_tx *))
+{
+ if (type == BNA_SOFT_CLEANUP) {
+ (*cbfn)(tx->bna->bnad, tx);
+ return;
+ }
+
+ tx->stop_cbfn = cbfn;
+ tx->stop_cbarg = tx->bna->bnad;
+
+ tx->flags &= ~BNA_TX_F_ENABLED;
+
+ bfa_fsm_send_event(tx, TX_E_STOP);
+}
+
+void
+bna_tx_cleanup_complete(struct bna_tx *tx)
+{
+ bfa_fsm_send_event(tx, TX_E_CLEANUP_DONE);
+}
+
+static void
+bna_tx_mod_cb_tx_stopped(void *arg, struct bna_tx *tx)
+{
+ struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
+
+ bfa_wc_down(&tx_mod->tx_stop_wc);
+}
+
+static void
+bna_tx_mod_cb_tx_stopped_all(void *arg)
+{
+ struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
+
+ if (tx_mod->stop_cbfn)
+ tx_mod->stop_cbfn(&tx_mod->bna->enet);
+ tx_mod->stop_cbfn = NULL;
+}
+
+void
+bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ int i;
+
+ tx_mod->bna = bna;
+ tx_mod->flags = 0;
+
+ tx_mod->tx = (struct bna_tx *)
+ res_info[BNA_MOD_RES_MEM_T_TX_ARRAY].res_u.mem_info.mdl[0].kva;
+ tx_mod->txq = (struct bna_txq *)
+ res_info[BNA_MOD_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mdl[0].kva;
+
+ INIT_LIST_HEAD(&tx_mod->tx_free_q);
+ INIT_LIST_HEAD(&tx_mod->tx_active_q);
+
+ INIT_LIST_HEAD(&tx_mod->txq_free_q);
+
+ for (i = 0; i < bna->ioceth.attr.num_txq; i++) {
+ tx_mod->tx[i].rid = i;
+ bfa_q_qe_init(&tx_mod->tx[i].qe);
+ list_add_tail(&tx_mod->tx[i].qe, &tx_mod->tx_free_q);
+ bfa_q_qe_init(&tx_mod->txq[i].qe);
+ list_add_tail(&tx_mod->txq[i].qe, &tx_mod->txq_free_q);
+ }
+
+ tx_mod->prio_map = BFI_TX_PRIO_MAP_ALL;
+ tx_mod->default_prio = 0;
+ tx_mod->iscsi_over_cee = BNA_STATUS_T_DISABLED;
+ tx_mod->iscsi_prio = -1;
+}
+
+void
+bna_tx_mod_uninit(struct bna_tx_mod *tx_mod)
+{
+ struct list_head *qe;
+ int i;
+
+ i = 0;
+ list_for_each(qe, &tx_mod->tx_free_q)
+ i++;
+
+ i = 0;
+ list_for_each(qe, &tx_mod->txq_free_q)
+ i++;
+
+ tx_mod->bna = NULL;
+}
+
+void
+bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
+{
+ struct bna_tx *tx;
+ struct list_head *qe;
+
+ tx_mod->flags |= BNA_TX_MOD_F_ENET_STARTED;
+ if (type == BNA_TX_T_LOOPBACK)
+ tx_mod->flags |= BNA_TX_MOD_F_ENET_LOOPBACK;
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ if (tx->type == type)
+ bna_tx_start(tx);
+ }
+}
+
+void
+bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
+{
+ struct bna_tx *tx;
+ struct list_head *qe;
+
+ tx_mod->flags &= ~BNA_TX_MOD_F_ENET_STARTED;
+ tx_mod->flags &= ~BNA_TX_MOD_F_ENET_LOOPBACK;
+
+ tx_mod->stop_cbfn = bna_enet_cb_tx_stopped;
+
+ bfa_wc_init(&tx_mod->tx_stop_wc, bna_tx_mod_cb_tx_stopped_all, tx_mod);
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ if (tx->type == type) {
+ bfa_wc_up(&tx_mod->tx_stop_wc);
+ bna_tx_stop(tx);
+ }
+ }
+
+ bfa_wc_wait(&tx_mod->tx_stop_wc);
+}
+
+void
+bna_tx_mod_fail(struct bna_tx_mod *tx_mod)
+{
+ struct bna_tx *tx;
+ struct list_head *qe;
+
+ tx_mod->flags &= ~BNA_TX_MOD_F_ENET_STARTED;
+ tx_mod->flags &= ~BNA_TX_MOD_F_ENET_LOOPBACK;
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ bna_tx_fail(tx);
+ }
+}
+
+void
+bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ bna_ib_coalescing_timeo_set(&txq->ib, coalescing_timeo);
+ }
+}
diff --git a/drivers/net/bna/bna_types.h b/drivers/net/ethernet/brocade/bna/bna_types.h
index 2f89cb235248..d090fbfb12fa 100644
--- a/drivers/net/bna/bna_types.h
+++ b/drivers/net/ethernet/brocade/bna/bna_types.h
@@ -19,8 +19,9 @@
#define __BNA_TYPES_H__
#include "cna.h"
-#include "bna_hw.h"
+#include "bna_hw_defs.h"
#include "bfa_cee.h"
+#include "bfa_msgq.h"
/**
*
@@ -28,13 +29,14 @@
*
*/
+struct bna_mcam_handle;
struct bna_txq;
struct bna_tx;
struct bna_rxq;
struct bna_cq;
struct bna_rx;
struct bna_rxf;
-struct bna_port;
+struct bna_enet;
struct bna;
struct bnad;
@@ -86,31 +88,29 @@ enum bna_res_req_type {
BNA_RES_MEM_T_ATTR = 1,
BNA_RES_MEM_T_FWTRC = 2,
BNA_RES_MEM_T_STATS = 3,
- BNA_RES_MEM_T_SWSTATS = 4,
- BNA_RES_MEM_T_IBIDX = 5,
- BNA_RES_MEM_T_IB_ARRAY = 6,
- BNA_RES_MEM_T_INTR_ARRAY = 7,
- BNA_RES_MEM_T_IDXSEG_ARRAY = 8,
- BNA_RES_MEM_T_TX_ARRAY = 9,
- BNA_RES_MEM_T_TXQ_ARRAY = 10,
- BNA_RES_MEM_T_RX_ARRAY = 11,
- BNA_RES_MEM_T_RXP_ARRAY = 12,
- BNA_RES_MEM_T_RXQ_ARRAY = 13,
- BNA_RES_MEM_T_UCMAC_ARRAY = 14,
- BNA_RES_MEM_T_MCMAC_ARRAY = 15,
- BNA_RES_MEM_T_RIT_ENTRY = 16,
- BNA_RES_MEM_T_RIT_SEGMENT = 17,
- BNA_RES_INTR_T_MBOX = 18,
BNA_RES_T_MAX
};
+enum bna_mod_res_req_type {
+ BNA_MOD_RES_MEM_T_TX_ARRAY = 0,
+ BNA_MOD_RES_MEM_T_TXQ_ARRAY = 1,
+ BNA_MOD_RES_MEM_T_RX_ARRAY = 2,
+ BNA_MOD_RES_MEM_T_RXP_ARRAY = 3,
+ BNA_MOD_RES_MEM_T_RXQ_ARRAY = 4,
+ BNA_MOD_RES_MEM_T_UCMAC_ARRAY = 5,
+ BNA_MOD_RES_MEM_T_MCMAC_ARRAY = 6,
+ BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY = 7,
+ BNA_MOD_RES_T_MAX
+};
+
enum bna_tx_res_req_type {
BNA_TX_RES_MEM_T_TCB = 0,
BNA_TX_RES_MEM_T_UNMAPQ = 1,
BNA_TX_RES_MEM_T_QPT = 2,
BNA_TX_RES_MEM_T_SWQPT = 3,
BNA_TX_RES_MEM_T_PAGE = 4,
- BNA_TX_RES_INTR_T_TXCMPL = 5,
+ BNA_TX_RES_MEM_T_IBIDX = 5,
+ BNA_TX_RES_INTR_T_TXCMPL = 6,
BNA_TX_RES_T_MAX,
};
@@ -127,13 +127,10 @@ enum bna_rx_mem_type {
BNA_RX_RES_MEM_T_DSWQPT = 9, /* RX s/w QPT */
BNA_RX_RES_MEM_T_DPAGE = 10, /* RX s/w QPT */
BNA_RX_RES_MEM_T_HPAGE = 11, /* RX s/w QPT */
- BNA_RX_RES_T_INTR = 12, /* Rx interrupts */
- BNA_RX_RES_T_MAX = 13
-};
-
-enum bna_mbox_state {
- BNA_MBOX_FREE = 0,
- BNA_MBOX_POSTED = 1
+ BNA_RX_RES_MEM_T_IBIDX = 12,
+ BNA_RX_RES_MEM_T_RIT = 13,
+ BNA_RX_RES_T_INTR = 14, /* Rx interrupts */
+ BNA_RX_RES_T_MAX = 15
};
enum bna_tx_type {
@@ -142,14 +139,15 @@ enum bna_tx_type {
};
enum bna_tx_flags {
- BNA_TX_F_PORT_STARTED = 1,
+ BNA_TX_F_ENET_STARTED = 1,
BNA_TX_F_ENABLED = 2,
- BNA_TX_F_PRIO_LOCK = 4,
+ BNA_TX_F_PRIO_CHANGED = 4,
+ BNA_TX_F_BW_UPDATED = 8,
};
enum bna_tx_mod_flags {
- BNA_TX_MOD_F_PORT_STARTED = 1,
- BNA_TX_MOD_F_PORT_LOOPBACK = 2,
+ BNA_TX_MOD_F_ENET_STARTED = 1,
+ BNA_TX_MOD_F_ENET_LOOPBACK = 2,
};
enum bna_rx_type {
@@ -165,80 +163,49 @@ enum bna_rxp_type {
enum bna_rxmode {
BNA_RXMODE_PROMISC = 1,
- BNA_RXMODE_ALLMULTI = 2
+ BNA_RXMODE_DEFAULT = 2,
+ BNA_RXMODE_ALLMULTI = 4
};
enum bna_rx_event {
RX_E_START = 1,
RX_E_STOP = 2,
RX_E_FAIL = 3,
- RX_E_RXF_STARTED = 4,
- RX_E_RXF_STOPPED = 5,
- RX_E_RXQ_STOPPED = 6,
-};
-
-enum bna_rx_state {
- BNA_RX_STOPPED = 1,
- BNA_RX_RXF_START_WAIT = 2,
- BNA_RX_STARTED = 3,
- BNA_RX_RXF_STOP_WAIT = 4,
- BNA_RX_RXQ_STOP_WAIT = 5,
+ RX_E_STARTED = 4,
+ RX_E_STOPPED = 5,
+ RX_E_RXF_STARTED = 6,
+ RX_E_RXF_STOPPED = 7,
+ RX_E_CLEANUP_DONE = 8,
};
enum bna_rx_flags {
- BNA_RX_F_ENABLE = 0x01, /* bnad enabled rxf */
- BNA_RX_F_PORT_ENABLED = 0x02, /* Port object is enabled */
- BNA_RX_F_PORT_FAILED = 0x04, /* Port in failed state */
+ BNA_RX_F_ENET_STARTED = 1,
+ BNA_RX_F_ENABLED = 2,
};
enum bna_rx_mod_flags {
- BNA_RX_MOD_F_PORT_STARTED = 1,
- BNA_RX_MOD_F_PORT_LOOPBACK = 2,
-};
-
-enum bna_rxf_oper_state {
- BNA_RXF_OPER_STATE_RUNNING = 0x01, /* rxf operational */
- BNA_RXF_OPER_STATE_PAUSED = 0x02, /* rxf in PAUSED state */
+ BNA_RX_MOD_F_ENET_STARTED = 1,
+ BNA_RX_MOD_F_ENET_LOOPBACK = 2,
};
enum bna_rxf_flags {
- BNA_RXF_FL_STOP_PENDING = 0x01,
- BNA_RXF_FL_FAILED = 0x02,
- BNA_RXF_FL_RSS_CONFIG_PENDING = 0x04,
- BNA_RXF_FL_OPERSTATE_CHANGED = 0x08,
- BNA_RXF_FL_RXF_ENABLED = 0x10,
- BNA_RXF_FL_VLAN_CONFIG_PENDING = 0x20,
+ BNA_RXF_F_PAUSED = 1,
};
enum bna_rxf_event {
RXF_E_START = 1,
RXF_E_STOP = 2,
RXF_E_FAIL = 3,
- RXF_E_CAM_FLTR_MOD = 4,
- RXF_E_STARTED = 5,
- RXF_E_STOPPED = 6,
- RXF_E_CAM_FLTR_RESP = 7,
- RXF_E_PAUSE = 8,
- RXF_E_RESUME = 9,
- RXF_E_STAT_CLEARED = 10,
-};
-
-enum bna_rxf_state {
- BNA_RXF_STOPPED = 1,
- BNA_RXF_START_WAIT = 2,
- BNA_RXF_CAM_FLTR_MOD_WAIT = 3,
- BNA_RXF_STARTED = 4,
- BNA_RXF_CAM_FLTR_CLR_WAIT = 5,
- BNA_RXF_STOP_WAIT = 6,
- BNA_RXF_PAUSE_WAIT = 7,
- BNA_RXF_RESUME_WAIT = 8,
- BNA_RXF_STAT_CLR_WAIT = 9,
+ RXF_E_CONFIG = 4,
+ RXF_E_PAUSE = 5,
+ RXF_E_RESUME = 6,
+ RXF_E_FW_RESP = 7,
};
-enum bna_port_type {
- BNA_PORT_T_REGULAR = 0,
- BNA_PORT_T_LOOPBACK_INTERNAL = 1,
- BNA_PORT_T_LOOPBACK_EXTERNAL = 2,
+enum bna_enet_type {
+ BNA_ENET_T_REGULAR = 0,
+ BNA_ENET_T_LOOPBACK_INTERNAL = 1,
+ BNA_ENET_T_LOOPBACK_EXTERNAL = 2,
};
enum bna_link_status {
@@ -247,17 +214,27 @@ enum bna_link_status {
BNA_CEE_UP = 2
};
-enum bna_llport_flags {
- BNA_LLPORT_F_ADMIN_UP = 1,
- BNA_LLPORT_F_PORT_ENABLED = 2,
- BNA_LLPORT_F_RX_STARTED = 4
+enum bna_ethport_flags {
+ BNA_ETHPORT_F_ADMIN_UP = 1,
+ BNA_ETHPORT_F_PORT_ENABLED = 2,
+ BNA_ETHPORT_F_RX_STARTED = 4,
};
-enum bna_port_flags {
- BNA_PORT_F_DEVICE_READY = 1,
- BNA_PORT_F_ENABLED = 2,
- BNA_PORT_F_PAUSE_CHANGED = 4,
- BNA_PORT_F_MTU_CHANGED = 8
+enum bna_enet_flags {
+ BNA_ENET_F_IOCETH_READY = 1,
+ BNA_ENET_F_ENABLED = 2,
+ BNA_ENET_F_PAUSE_CHANGED = 4,
+ BNA_ENET_F_MTU_CHANGED = 8
+};
+
+enum bna_rss_flags {
+ BNA_RSS_F_RIT_PENDING = 1,
+ BNA_RSS_F_CFG_PENDING = 2,
+ BNA_RSS_F_STATUS_PENDING = 4,
+};
+
+enum bna_mod_flags {
+ BNA_MOD_F_INIT_DONE = 1,
};
enum bna_pkt_rates {
@@ -289,10 +266,17 @@ enum bna_dim_bias_types {
BNA_BIAS_T_MAX = 2
};
+#define BNA_MAX_NAME_SIZE 64
+struct bna_ident {
+ int id;
+ char name[BNA_MAX_NAME_SIZE];
+};
+
struct bna_mac {
/* This should be the first one */
struct list_head qe;
u8 addr[ETH_ALEN];
+ struct bna_mcam_handle *handle;
};
struct bna_mem_descr {
@@ -338,23 +322,30 @@ struct bna_qpt {
u32 page_size;
};
+struct bna_attr {
+ bool fw_query_complete;
+ int num_txq;
+ int num_rxp;
+ int num_ucmac;
+ int num_mcmac;
+ int max_rit_size;
+};
+
/**
*
- * Device
+ * IOCEth
*
*/
-struct bna_device {
+struct bna_ioceth {
bfa_fsm_t fsm;
struct bfa_ioc ioc;
- enum bna_intr_type intr_type;
- int vector;
+ struct bna_attr attr;
+ struct bfa_msgq_cmd_entry msgq_cmd;
+ struct bfi_enet_attr_req attr_req;
- void (*ready_cbfn)(struct bnad *bnad, enum bna_cb_status status);
- struct bnad *ready_cbarg;
-
- void (*stop_cbfn)(struct bnad *bnad, enum bna_cb_status status);
+ void (*stop_cbfn)(struct bnad *bnad);
struct bnad *stop_cbarg;
struct bna *bna;
@@ -362,32 +353,7 @@ struct bna_device {
/**
*
- * Mail box
- *
- */
-
-struct bna_mbox_qe {
- /* This should be the first one */
- struct list_head qe;
-
- struct bfa_mbox_cmd cmd;
- u32 cmd_len;
- /* Callback for port, tx, rx, rxf */
- void (*cbfn)(void *arg, int status);
- void *cbarg;
-};
-
-struct bna_mbox_mod {
- enum bna_mbox_state state;
- struct list_head posted_q;
- u32 msg_pending;
- u32 msg_ctr;
- struct bna *bna;
-};
-
-/**
- *
- * Port
+ * Enet
*
*/
@@ -397,50 +363,58 @@ struct bna_pause_config {
enum bna_status rx_pause;
};
-struct bna_llport {
+struct bna_enet {
bfa_fsm_t fsm;
- enum bna_llport_flags flags;
+ enum bna_enet_flags flags;
- enum bna_port_type type;
+ enum bna_enet_type type;
- enum bna_link_status link_status;
+ struct bna_pause_config pause_config;
+ int mtu;
- int rx_started_count;
+ /* Callback for bna_enet_disable(), enet_stop() */
+ void (*stop_cbfn)(void *);
+ void *stop_cbarg;
+
+ /* Callback for bna_enet_pause_config() */
+ void (*pause_cbfn)(struct bnad *);
+
+ /* Callback for bna_enet_mtu_set() */
+ void (*mtu_cbfn)(struct bnad *);
- void (*stop_cbfn)(struct bna_port *, enum bna_cb_status);
+ struct bfa_wc chld_stop_wc;
- struct bna_mbox_qe mbox_qe;
+ struct bfa_msgq_cmd_entry msgq_cmd;
+ struct bfi_enet_set_pause_req pause_req;
struct bna *bna;
};
-struct bna_port {
- bfa_fsm_t fsm;
- enum bna_port_flags flags;
-
- enum bna_port_type type;
+/**
+ *
+ * Ethport
+ *
+ */
- struct bna_llport llport;
+struct bna_ethport {
+ bfa_fsm_t fsm;
+ enum bna_ethport_flags flags;
- struct bna_pause_config pause_config;
- u8 priority;
- int mtu;
+ enum bna_link_status link_status;
- /* Callback for bna_port_disable(), port_stop() */
- void (*stop_cbfn)(void *, enum bna_cb_status);
- void *stop_cbarg;
+ int rx_started_count;
- /* Callback for bna_port_pause_config() */
- void (*pause_cbfn)(struct bnad *, enum bna_cb_status);
+ void (*stop_cbfn)(struct bna_enet *);
- /* Callback for bna_port_mtu_set() */
- void (*mtu_cbfn)(struct bnad *, enum bna_cb_status);
+ void (*adminup_cbfn)(struct bnad *, enum bna_cb_status);
void (*link_cbfn)(struct bnad *, enum bna_link_status);
- struct bfa_wc chld_stop_wc;
-
- struct bna_mbox_qe mbox_qe;
+ struct bfa_msgq_cmd_entry msgq_cmd;
+ union {
+ struct bfi_enet_enable_req admin_req;
+ struct bfi_enet_diag_lb_req lpbk_req;
+ } bfi_enet_cmd;
struct bna *bna;
};
@@ -451,82 +425,26 @@ struct bna_port {
*
*/
-/* IB index segment structure */
-struct bna_ibidx_seg {
- /* This should be the first one */
- struct list_head qe;
-
- u8 ib_seg_size;
- u8 ib_idx_tbl_offset;
-};
-
-/* Interrupt structure */
-struct bna_intr {
- /* This should be the first one */
- struct list_head qe;
- int ref_count;
-
- enum bna_intr_type intr_type;
- int vector;
-
- struct bna_ib *ib;
-};
-
/* Doorbell structure */
struct bna_ib_dbell {
void *__iomem doorbell_addr;
u32 doorbell_ack;
};
-/* Interrupt timer configuration */
-struct bna_ib_config {
- u8 coalescing_timeo; /* Unit is 5usec. */
-
- int interpkt_count;
- int interpkt_timeo;
-
- enum ib_flags ctrl_flags;
-};
-
/* IB structure */
struct bna_ib {
- /* This should be the first one */
- struct list_head qe;
-
- int ib_id;
-
- int ref_count;
- int start_count;
-
struct bna_dma_addr ib_seg_host_addr;
void *ib_seg_host_addr_kva;
- u32 idx_mask; /* Size >= BNA_IBIDX_MAX_SEGSIZE */
-
- struct bna_ibidx_seg *idx_seg;
struct bna_ib_dbell door_bell;
- struct bna_intr *intr;
-
- struct bna_ib_config ib_config;
-
- struct bna *bna;
-};
-
-/* IB module - keeps track of IBs and interrupts */
-struct bna_ib_mod {
- struct bna_ib *ib; /* BFI_MAX_IB entries */
- struct bna_intr *intr; /* BFI_MAX_IB entries */
- struct bna_ibidx_seg *idx_seg; /* BNA_IBIDX_TOTAL_SEGS */
-
- struct list_head ib_free_q;
-
- struct list_head ibidx_seg_pool[BFI_IBIDX_TOTAL_POOLS];
+ enum bna_intr_type intr_type;
+ int intr_vector;
- struct list_head intr_free_q;
- struct list_head intr_active_q;
+ u8 coalescing_timeo; /* Unit is 5usec. */
- struct bna *bna;
+ int interpkt_count;
+ int interpkt_timeo;
};
/**
@@ -552,6 +470,7 @@ struct bna_tcb {
/* Control path */
struct bna_txq *txq;
struct bnad *bnad;
+ void *priv; /* BNAD's cookie */
enum bna_intr_type intr_type;
int intr_vector;
u8 priority; /* Current priority */
@@ -565,68 +484,66 @@ struct bna_txq {
/* This should be the first one */
struct list_head qe;
- int txq_id;
-
u8 priority;
struct bna_qpt qpt;
struct bna_tcb *tcb;
- struct bna_ib *ib;
- int ib_seg_offset;
+ struct bna_ib ib;
struct bna_tx *tx;
+ int hw_id;
+
u64 tx_packets;
u64 tx_bytes;
};
-/* TxF structure (hardware Tx Function) */
-struct bna_txf {
- int txf_id;
- enum txf_flags ctrl_flags;
- u16 vlan;
-};
-
/* Tx object */
struct bna_tx {
/* This should be the first one */
struct list_head qe;
+ int rid;
+ int hw_id;
bfa_fsm_t fsm;
enum bna_tx_flags flags;
enum bna_tx_type type;
+ int num_txq;
struct list_head txq_q;
- struct bna_txf txf;
+ u16 txf_vlan_id;
/* Tx event handlers */
void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *);
void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *);
- void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *);
- void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *);
- void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *);
+ void (*tx_stall_cbfn)(struct bnad *, struct bna_tx *);
+ void (*tx_resume_cbfn)(struct bnad *, struct bna_tx *);
+ void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tx *);
/* callback for bna_tx_disable(), bna_tx_stop() */
- void (*stop_cbfn)(void *arg, struct bna_tx *tx,
- enum bna_cb_status status);
+ void (*stop_cbfn)(void *arg, struct bna_tx *tx);
void *stop_cbarg;
/* callback for bna_tx_prio_set() */
- void (*prio_change_cbfn)(struct bnad *bnad, struct bna_tx *tx,
- enum bna_cb_status status);
-
- struct bfa_wc txq_stop_wc;
+ void (*prio_change_cbfn)(struct bnad *bnad, struct bna_tx *tx);
- struct bna_mbox_qe mbox_qe;
+ struct bfa_msgq_cmd_entry msgq_cmd;
+ union {
+ struct bfi_enet_tx_cfg_req cfg_req;
+ struct bfi_enet_req req;
+ struct bfi_enet_tx_cfg_rsp cfg_rsp;
+ } bfi_enet_cmd;
struct bna *bna;
void *priv; /* bnad's cookie */
};
+/* Tx object configuration used during creation */
struct bna_tx_config {
int num_txq;
int txq_depth;
+ int coalescing_timeo;
enum bna_tx_type tx_type;
};
@@ -635,9 +552,9 @@ struct bna_tx_event_cbfn {
void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *);
void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *);
/* Mandatory */
- void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *);
- void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *);
- void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *);
+ void (*tx_stall_cbfn)(struct bnad *, struct bna_tx *);
+ void (*tx_resume_cbfn)(struct bnad *, struct bna_tx *);
+ void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tx *);
};
/* Tx module - keeps track of free, active tx objects */
@@ -651,57 +568,25 @@ struct bna_tx_mod {
struct list_head txq_free_q;
/* callback for bna_tx_mod_stop() */
- void (*stop_cbfn)(struct bna_port *port,
- enum bna_cb_status status);
+ void (*stop_cbfn)(struct bna_enet *enet);
struct bfa_wc tx_stop_wc;
enum bna_tx_mod_flags flags;
- int priority;
- int cee_link;
+ u8 prio_map;
+ int default_prio;
+ int iscsi_over_cee;
+ int iscsi_prio;
+ int prio_reconfigured;
- u32 txf_bmap[2];
+ u32 rid_mask;
struct bna *bna;
};
/**
*
- * Receive Indirection Table
- *
- */
-
-/* One row of RIT table */
-struct bna_rit_entry {
- u8 large_rxq_id; /* used for either large or data buffers */
- u8 small_rxq_id; /* used for either small or header buffers */
-};
-
-/* RIT segment */
-struct bna_rit_segment {
- struct list_head qe;
-
- u32 rit_offset;
- u32 rit_size;
- /**
- * max_rit_size: Varies per RIT segment depending on how RIT is
- * partitioned
- */
- u32 max_rit_size;
-
- struct bna_rit_entry *rit;
-};
-
-struct bna_rit_mod {
- struct bna_rit_entry *rit;
- struct bna_rit_segment *rit_segment;
-
- struct list_head rit_seg_pool[BFI_RIT_SEG_TOTAL_POOLS];
-};
-
-/**
- *
* Rx object
*
*/
@@ -719,8 +604,9 @@ struct bna_rcb {
int page_count;
/* Control path */
struct bna_rxq *rxq;
- struct bna_cq *cq;
+ struct bna_ccb *ccb;
struct bnad *bnad;
+ void *priv; /* BNAD's cookie */
unsigned long flags;
int id;
};
@@ -728,7 +614,6 @@ struct bna_rcb {
/* RxQ structure - QPT, configuration */
struct bna_rxq {
struct list_head qe;
- int rxq_id;
int buffer_size;
int q_depth;
@@ -739,6 +624,8 @@ struct bna_rxq {
struct bna_rxp *rxp;
struct bna_rx *rx;
+ int hw_id;
+
u64 rx_packets;
u64 rx_bytes;
u64 rx_packets_with_error;
@@ -784,6 +671,7 @@ struct bna_ccb {
/* Control path */
struct bna_cq *cq;
struct bnad *bnad;
+ void *priv; /* BNAD's cookie */
enum bna_intr_type intr_type;
int intr_vector;
u8 rx_coalescing_timeo; /* For NAPI */
@@ -793,46 +681,43 @@ struct bna_ccb {
/* CQ QPT, configuration */
struct bna_cq {
- int cq_id;
-
struct bna_qpt qpt;
struct bna_ccb *ccb;
- struct bna_ib *ib;
- u8 ib_seg_offset;
+ struct bna_ib ib;
struct bna_rx *rx;
};
struct bna_rss_config {
- enum rss_hash_type hash_type;
+ enum bfi_enet_rss_type hash_type;
u8 hash_mask;
- u32 toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN];
+ u32 toeplitz_hash_key[BFI_ENET_RSS_KEY_LEN];
};
struct bna_hds_config {
- enum hds_header_type hdr_type;
- int header_size;
+ enum bfi_enet_hds_type hdr_type;
+ int forced_offset;
};
-/* This structure is used during RX creation */
+/* Rx object configuration used during creation */
struct bna_rx_config {
enum bna_rx_type rx_type;
int num_paths;
enum bna_rxp_type rxp_type;
int paused;
int q_depth;
+ int coalescing_timeo;
/*
* Small/Large (or Header/Data) buffer size to be configured
* for SLR and HDS queue type. Large buffer size comes from
- * port->mtu.
+ * enet->mtu.
*/
int small_buff_size;
enum bna_status rss_status;
struct bna_rss_config rss_config;
- enum bna_status hds_status;
struct bna_hds_config hds_config;
enum bna_status vlan_strip_status;
@@ -851,51 +736,35 @@ struct bna_rxp {
/* MSI-x vector number for configuring RSS */
int vector;
-
- struct bna_mbox_qe mbox_qe;
-};
-
-/* HDS configuration structure */
-struct bna_rxf_hds {
- enum hds_header_type hdr_type;
- int header_size;
-};
-
-/* RSS configuration structure */
-struct bna_rxf_rss {
- enum rss_hash_type hash_type;
- u8 hash_mask;
- u32 toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN];
+ int hw_id;
};
/* RxF structure (hardware Rx Function) */
struct bna_rxf {
bfa_fsm_t fsm;
- int rxf_id;
- enum rxf_flags ctrl_flags;
- u16 default_vlan_tag;
- enum bna_rxf_oper_state rxf_oper_state;
- enum bna_status hds_status;
- struct bna_rxf_hds hds_cfg;
- enum bna_status rss_status;
- struct bna_rxf_rss rss_cfg;
- struct bna_rit_segment *rit_segment;
- struct bna_rx *rx;
- u32 forced_offset;
- struct bna_mbox_qe mbox_qe;
- int mcast_rxq_id;
+ enum bna_rxf_flags flags;
+
+ struct bfa_msgq_cmd_entry msgq_cmd;
+ union {
+ struct bfi_enet_enable_req req;
+ struct bfi_enet_rss_cfg_req rss_req;
+ struct bfi_enet_rit_req rit_req;
+ struct bfi_enet_rx_vlan_req vlan_req;
+ struct bfi_enet_mcast_add_req mcast_add_req;
+ struct bfi_enet_mcast_del_req mcast_del_req;
+ struct bfi_enet_ucast_req ucast_req;
+ } bfi_enet_cmd;
/* callback for bna_rxf_start() */
- void (*start_cbfn) (struct bna_rx *rx, enum bna_cb_status status);
+ void (*start_cbfn) (struct bna_rx *rx);
struct bna_rx *start_cbarg;
/* callback for bna_rxf_stop() */
- void (*stop_cbfn) (struct bna_rx *rx, enum bna_cb_status status);
+ void (*stop_cbfn) (struct bna_rx *rx);
struct bna_rx *stop_cbarg;
- /* callback for bna_rxf_receive_enable() / bna_rxf_receive_disable() */
- void (*oper_state_cbfn) (struct bnad *bnad, struct bna_rx *rx,
- enum bna_cb_status status);
+ /* callback for bna_rx_receive_pause() / bna_rx_receive_resume() */
+ void (*oper_state_cbfn) (struct bnad *bnad, struct bna_rx *rx);
struct bnad *oper_state_cbarg;
/**
@@ -905,25 +774,25 @@ struct bna_rxf {
* bna_rxf_{ucast/mcast}_del(),
* bna_rxf_mode_set()
*/
- void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx,
- enum bna_cb_status status);
+ void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx);
struct bnad *cam_fltr_cbarg;
- enum bna_rxf_flags rxf_flags;
-
/* List of unicast addresses yet to be applied to h/w */
struct list_head ucast_pending_add_q;
struct list_head ucast_pending_del_q;
+ struct bna_mac *ucast_pending_mac;
int ucast_pending_set;
/* ucast addresses applied to the h/w */
struct list_head ucast_active_q;
- struct bna_mac *ucast_active_mac;
+ struct bna_mac ucast_active_mac;
+ int ucast_active_set;
/* List of multicast addresses yet to be applied to h/w */
struct list_head mcast_pending_add_q;
struct list_head mcast_pending_del_q;
/* multicast addresses applied to the h/w */
struct list_head mcast_active_q;
+ struct list_head mcast_handle_q;
/* Rx modes yet to be applied to h/w */
enum bna_rxmode rxmode_pending;
@@ -931,41 +800,59 @@ struct bna_rxf {
/* Rx modes applied to h/w */
enum bna_rxmode rxmode_active;
+ u8 vlan_pending_bitmask;
enum bna_status vlan_filter_status;
- u32 vlan_filter_table[(BFI_MAX_VLAN + 1) / 32];
+ u32 vlan_filter_table[(BFI_ENET_VLAN_ID_MAX) / 32];
+ bool vlan_strip_pending;
+ enum bna_status vlan_strip_status;
+
+ enum bna_rss_flags rss_pending;
+ enum bna_status rss_status;
+ struct bna_rss_config rss_cfg;
+ u8 *rit;
+ int rit_size;
+
+ struct bna_rx *rx;
};
/* Rx object */
struct bna_rx {
/* This should be the first one */
struct list_head qe;
+ int rid;
+ int hw_id;
bfa_fsm_t fsm;
enum bna_rx_type type;
- /* list-head for RX path objects */
+ int num_paths;
struct list_head rxp_q;
+ struct bna_hds_config hds_cfg;
+
struct bna_rxf rxf;
enum bna_rx_flags rx_flags;
- struct bna_mbox_qe mbox_qe;
-
- struct bfa_wc rxq_stop_wc;
+ struct bfa_msgq_cmd_entry msgq_cmd;
+ union {
+ struct bfi_enet_rx_cfg_req cfg_req;
+ struct bfi_enet_req req;
+ struct bfi_enet_rx_cfg_rsp cfg_rsp;
+ } bfi_enet_cmd;
/* Rx event handlers */
void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *);
void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *);
void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *);
void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *);
- void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *);
- void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *);
+ void (*rx_stall_cbfn)(struct bnad *, struct bna_rx *);
+ void (*rx_cleanup_cbfn)(struct bnad *, struct bna_rx *);
+ void (*rx_post_cbfn)(struct bnad *, struct bna_rx *);
/* callback for bna_rx_disable(), bna_rx_stop() */
- void (*stop_cbfn)(void *arg, struct bna_rx *rx,
- enum bna_cb_status status);
+ void (*stop_cbfn)(void *arg, struct bna_rx *rx);
void *stop_cbarg;
struct bna *bna;
@@ -978,9 +865,10 @@ struct bna_rx_event_cbfn {
void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *);
void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *);
void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *);
+ void (*rx_stall_cbfn)(struct bnad *, struct bna_rx *);
/* Mandatory */
- void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *);
- void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *);
+ void (*rx_cleanup_cbfn)(struct bnad *, struct bna_rx *);
+ void (*rx_post_cbfn)(struct bnad *, struct bna_rx *);
};
/* Rx module - keeps track of free, active rx objects */
@@ -1003,12 +891,11 @@ struct bna_rx_mod {
enum bna_rx_mod_flags flags;
/* callback for bna_rx_mod_stop() */
- void (*stop_cbfn)(struct bna_port *port,
- enum bna_cb_status status);
+ void (*stop_cbfn)(struct bna_enet *enet);
struct bfa_wc rx_stop_wc;
u32 dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX];
- u32 rxf_bmap[2];
+ u32 rid_mask;
};
/**
@@ -1024,9 +911,18 @@ struct bna_ucam_mod {
struct bna *bna;
};
+struct bna_mcam_handle {
+ /* This should be the first one */
+ struct list_head qe;
+ int handle;
+ int refcnt;
+};
+
struct bna_mcam_mod {
struct bna_mac *mcmac; /* BFI_MAX_MCMAC entries */
+ struct bna_mcam_handle *mchandle; /* BFI_MAX_MCMAC entries */
struct list_head free_q;
+ struct list_head free_handle_q;
struct bna *bna;
};
@@ -1037,50 +933,20 @@ struct bna_mcam_mod {
*
*/
-struct bna_tx_stats {
- int tx_state;
- int tx_flags;
- int num_txqs;
- u32 txq_bmap[2];
- int txf_id;
-};
-
-struct bna_rx_stats {
- int rx_state;
- int rx_flags;
- int num_rxps;
- int num_rxqs;
- u32 rxq_bmap[2];
- u32 cq_bmap[2];
- int rxf_id;
- int rxf_state;
- int rxf_oper_state;
- int num_active_ucast;
- int num_active_mcast;
- int rxmode_active;
- int vlan_filter_status;
- u32 vlan_filter_table[(BFI_MAX_VLAN + 1) / 32];
- int rss_status;
- int hds_status;
-};
-
-struct bna_sw_stats {
- int device_state;
- int port_state;
- int port_flags;
- int llport_state;
- int priority;
- int num_active_tx;
- int num_active_rx;
- struct bna_tx_stats tx_stats[BFI_MAX_TXQ];
- struct bna_rx_stats rx_stats[BFI_MAX_RXQ];
+struct bna_stats {
+ struct bna_dma_addr hw_stats_dma;
+ struct bfi_enet_stats *hw_stats_kva;
+ struct bfi_enet_stats hw_stats;
};
-struct bna_stats {
- u32 txf_bmap[2];
- u32 rxf_bmap[2];
- struct bfi_ll_stats *hw_stats;
- struct bna_sw_stats *sw_stats;
+struct bna_stats_mod {
+ bool ioc_ready;
+ bool stats_get_busy;
+ bool stats_clr_busy;
+ struct bfa_msgq_cmd_entry stats_get_cmd;
+ struct bfa_msgq_cmd_entry stats_clr_cmd;
+ struct bfi_enet_stats_req stats_get;
+ struct bfi_enet_stats_req stats_clr;
};
/**
@@ -1090,38 +956,32 @@ struct bna_stats {
*/
struct bna {
+ struct bna_ident ident;
struct bfa_pcidev pcidev;
- int port_num;
-
- struct bna_chip_regs regs;
+ struct bna_reg regs;
+ struct bna_bit_defn bits;
- struct bna_dma_addr hw_stats_dma;
struct bna_stats stats;
- struct bna_device device;
+ struct bna_ioceth ioceth;
struct bfa_cee cee;
+ struct bfa_msgq msgq;
- struct bna_mbox_mod mbox_mod;
-
- struct bna_port port;
+ struct bna_ethport ethport;
+ struct bna_enet enet;
+ struct bna_stats_mod stats_mod;
struct bna_tx_mod tx_mod;
-
struct bna_rx_mod rx_mod;
-
- struct bna_ib_mod ib_mod;
-
struct bna_ucam_mod ucam_mod;
struct bna_mcam_mod mcam_mod;
- struct bna_rit_mod rit_mod;
+ enum bna_mod_flags mod_flags;
- int rxf_promisc_id;
-
- struct bna_mbox_qe mbox_qe;
+ int default_mode_rid;
+ int promisc_rid;
struct bnad *bnad;
};
-
#endif /* __BNA_TYPES_H__ */
diff --git a/drivers/net/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 8e35b2596f93..5d7872ecff52 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -102,6 +102,28 @@ bnad_cq_cmpl_init(struct bnad *bnad, struct bna_ccb *ccb)
}
}
+static u32
+bnad_pci_unmap_skb(struct device *pdev, struct bnad_skb_unmap *array,
+ u32 index, u32 depth, struct sk_buff *skb, u32 frag)
+{
+ 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);
+
+ 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);
+ }
+
+ return index;
+}
+
/*
* Frees all pending Tx Bufs
* At this point no activity is expected on the Q,
@@ -115,39 +137,20 @@ bnad_free_all_txbufs(struct bnad *bnad,
struct bnad_unmap_q *unmap_q = tcb->unmap_q;
struct bnad_skb_unmap *unmap_array;
struct sk_buff *skb = NULL;
- int i;
+ int q;
unmap_array = unmap_q->unmap_array;
- unmap_cons = 0;
- while (unmap_cons < unmap_q->q_depth) {
- skb = unmap_array[unmap_cons].skb;
- if (!skb) {
- unmap_cons++;
+ for (q = 0; q < unmap_q->q_depth; q++) {
+ skb = unmap_array[q].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), skb_headlen(skb),
- DMA_TO_DEVICE);
-
- dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
- if (++unmap_cons >= unmap_q->q_depth)
- break;
+ 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);
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- dma_unmap_page(&bnad->pcidev->dev,
- dma_unmap_addr(&unmap_array[unmap_cons],
- dma_addr),
- skb_shinfo(skb)->frags[i].size,
- DMA_TO_DEVICE);
- dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
- 0);
- if (++unmap_cons >= unmap_q->q_depth)
- break;
- }
dev_kfree_skb_any(skb);
}
}
@@ -164,12 +167,11 @@ static u32
bnad_free_txbufs(struct bnad *bnad,
struct bna_tcb *tcb)
{
- u32 sent_packets = 0, sent_bytes = 0;
- u16 wis, unmap_cons, updated_hw_cons;
+ 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;
- int i;
/*
* Just return if TX is stopped. This check is useful
@@ -195,32 +197,14 @@ bnad_free_txbufs(struct bnad *bnad,
while (wis) {
skb = unmap_array[unmap_cons].skb;
- unmap_array[unmap_cons].skb = NULL;
-
sent_packets++;
sent_bytes += skb->len;
wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags);
- dma_unmap_single(&bnad->pcidev->dev,
- dma_unmap_addr(&unmap_array[unmap_cons],
- dma_addr), skb_headlen(skb),
- DMA_TO_DEVICE);
- dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
- BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
-
- prefetch(&unmap_array[unmap_cons + 1]);
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- prefetch(&unmap_array[unmap_cons + 1]);
-
- dma_unmap_page(&bnad->pcidev->dev,
- dma_unmap_addr(&unmap_array[unmap_cons],
- dma_addr),
- skb_shinfo(skb)->frags[i].size,
- DMA_TO_DEVICE);
- dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
- 0);
- BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
- }
+ unmap_cons = bnad_pci_unmap_skb(&bnad->pcidev->dev, unmap_array,
+ unmap_cons, unmap_q->q_depth, skb,
+ skb_shinfo(skb)->nr_frags);
+
dev_kfree_skb_any(skb);
}
@@ -383,14 +367,14 @@ bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent, wi_range);
while (to_alloc--) {
- if (!wi_range) {
+ 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;
@@ -412,7 +396,7 @@ finishing:
unmap_q->producer_index = unmap_prod;
rcb->producer_index = unmap_prod;
smp_mb();
- if (likely(test_bit(BNAD_RXQ_STARTED, &rcb->flags)))
+ if (likely(test_bit(BNAD_RXQ_POST_OK, &rcb->flags)))
bna_rxq_prod_indx_doorbell(rcb);
}
}
@@ -441,11 +425,15 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
struct bnad_skb_unmap *unmap_array;
struct sk_buff *skb;
u32 flags, unmap_cons;
- u32 qid0 = ccb->rcb[0]->rxq->rxq_id;
struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
+ struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
+
+ set_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
- if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))
+ if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)) {
+ clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
return 0;
+ }
prefetch(bnad->netdev);
BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
@@ -455,10 +443,10 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
packets++;
BNA_UPDATE_PKT_CNT(pkt_rt, ntohs(cmpl->length));
- if (qid0 == cmpl->rxq_id)
- rcb = ccb->rcb[0];
- else
+ if (bna_is_small_rxq(cmpl->rxq_id))
rcb = ccb->rcb[1];
+ else
+ rcb = ccb->rcb[0];
unmap_q = rcb->unmap_q;
unmap_array = unmap_q->unmap_array;
@@ -518,12 +506,9 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
if (flags & BNA_CQ_EF_VLAN)
__vlan_hwaccel_put_tag(skb, ntohs(cmpl->vlan_tag));
- if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
- struct bnad_rx_ctrl *rx_ctrl;
-
- rx_ctrl = (struct bnad_rx_ctrl *) ccb->ctrl;
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY)
napi_gro_receive(&rx_ctrl->napi, skb);
- } else {
+ else {
netif_receive_skb(skb);
}
@@ -534,39 +519,16 @@ next:
BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
- if (likely(ccb)) {
- if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
- bna_ib_ack(ccb->i_dbell, packets);
- bnad_refill_rxq(bnad, ccb->rcb[0]);
- if (ccb->rcb[1])
- bnad_refill_rxq(bnad, ccb->rcb[1]);
- } else {
- if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
- bna_ib_ack(ccb->i_dbell, 0);
- }
-
- return packets;
-}
+ if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
+ bna_ib_ack_disable_irq(ccb->i_dbell, packets);
-static void
-bnad_disable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
-{
- if (unlikely(!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
- return;
+ bnad_refill_rxq(bnad, ccb->rcb[0]);
+ if (ccb->rcb[1])
+ bnad_refill_rxq(bnad, ccb->rcb[1]);
- bna_ib_coalescing_timer_set(ccb->i_dbell, 0);
- bna_ib_ack(ccb->i_dbell, 0);
-}
+ clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
-static void
-bnad_enable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
-{
- unsigned long flags;
-
- /* Because of polling context */
- spin_lock_irqsave(&bnad->bna_lock, flags);
- bnad_enable_rx_irq_unsafe(ccb);
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ return packets;
}
static void
@@ -576,10 +538,9 @@ bnad_netif_rx_schedule_poll(struct bnad *bnad, struct bna_ccb *ccb)
struct napi_struct *napi = &rx_ctrl->napi;
if (likely(napi_schedule_prep(napi))) {
- bnad_disable_rx_irq(bnad, ccb);
__napi_schedule(napi);
+ rx_ctrl->rx_schedule++;
}
- BNAD_UPDATE_CTR(bnad, netif_rx_schedule);
}
/* MSIX Rx Path Handler */
@@ -587,9 +548,11 @@ static irqreturn_t
bnad_msix_rx(int irq, void *data)
{
struct bna_ccb *ccb = (struct bna_ccb *)data;
- struct bnad *bnad = ccb->bnad;
- bnad_netif_rx_schedule_poll(bnad, ccb);
+ if (ccb) {
+ ((struct bnad_rx_ctrl *)(ccb->ctrl))->rx_intr_ctr++;
+ bnad_netif_rx_schedule_poll(ccb->bnad, ccb);
+ }
return IRQ_HANDLED;
}
@@ -604,14 +567,15 @@ bnad_msix_mbox_handler(int irq, void *data)
unsigned long flags;
struct bnad *bnad = (struct bnad *)data;
- if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
- return IRQ_HANDLED;
-
spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))) {
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ return IRQ_HANDLED;
+ }
bna_intr_status_get(&bnad->bna, intr_status);
- if (BNA_IS_MBOX_ERR_INTR(intr_status))
+ if (BNA_IS_MBOX_ERR_INTR(&bnad->bna, intr_status))
bna_mbox_handler(&bnad->bna, intr_status);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -628,18 +592,22 @@ bnad_isr(int irq, void *data)
struct bnad *bnad = (struct bnad *)data;
struct bnad_rx_info *rx_info;
struct bnad_rx_ctrl *rx_ctrl;
+ struct bna_tcb *tcb = NULL;
- if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))) {
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
return IRQ_NONE;
+ }
bna_intr_status_get(&bnad->bna, intr_status);
- if (unlikely(!intr_status))
+ if (unlikely(!intr_status)) {
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
return IRQ_NONE;
+ }
- spin_lock_irqsave(&bnad->bna_lock, flags);
-
- if (BNA_IS_MBOX_ERR_INTR(intr_status))
+ if (BNA_IS_MBOX_ERR_INTR(&bnad->bna, intr_status))
bna_mbox_handler(&bnad->bna, intr_status);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -650,8 +618,11 @@ bnad_isr(int irq, void *data)
/* Process data interrupts */
/* Tx processing */
for (i = 0; i < bnad->num_tx; i++) {
- for (j = 0; j < bnad->num_txq_per_tx; j++)
- bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+ for (j = 0; j < bnad->num_txq_per_tx; j++) {
+ tcb = bnad->tx_info[i].tcb[j];
+ if (tcb && test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
+ bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+ }
}
/* Rx processing */
for (i = 0; i < bnad->num_rx; i++) {
@@ -706,43 +677,49 @@ bnad_set_netdev_perm_addr(struct bnad *bnad)
/* Callbacks */
void
-bnad_cb_device_enable_mbox_intr(struct bnad *bnad)
+bnad_cb_mbox_intr_enable(struct bnad *bnad)
{
bnad_enable_mbox_irq(bnad);
}
void
-bnad_cb_device_disable_mbox_intr(struct bnad *bnad)
+bnad_cb_mbox_intr_disable(struct bnad *bnad)
{
bnad_disable_mbox_irq(bnad);
}
void
-bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status)
+bnad_cb_ioceth_ready(struct bnad *bnad)
{
+ bnad->bnad_completions.ioc_comp_status = BNA_CB_SUCCESS;
complete(&bnad->bnad_completions.ioc_comp);
- bnad->bnad_completions.ioc_comp_status = status;
}
void
-bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status)
+bnad_cb_ioceth_failed(struct bnad *bnad)
{
+ bnad->bnad_completions.ioc_comp_status = BNA_CB_FAIL;
+ complete(&bnad->bnad_completions.ioc_comp);
+}
+
+void
+bnad_cb_ioceth_disabled(struct bnad *bnad)
+{
+ bnad->bnad_completions.ioc_comp_status = BNA_CB_SUCCESS;
complete(&bnad->bnad_completions.ioc_comp);
- bnad->bnad_completions.ioc_comp_status = status;
}
static void
-bnad_cb_port_disabled(void *arg, enum bna_cb_status status)
+bnad_cb_enet_disabled(void *arg)
{
struct bnad *bnad = (struct bnad *)arg;
- complete(&bnad->bnad_completions.port_comp);
-
netif_carrier_off(bnad->netdev);
+ complete(&bnad->bnad_completions.enet_comp);
}
void
-bnad_cb_port_link_status(struct bnad *bnad,
+bnad_cb_ethport_link_status(struct bnad *bnad,
enum bna_link_status link_status)
{
bool link_up = 0;
@@ -750,34 +727,60 @@ bnad_cb_port_link_status(struct bnad *bnad,
link_up = (link_status == BNA_LINK_UP) || (link_status == BNA_CEE_UP);
if (link_status == BNA_CEE_UP) {
+ if (!test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags))
+ BNAD_UPDATE_CTR(bnad, cee_toggle);
set_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags);
- BNAD_UPDATE_CTR(bnad, cee_up);
- } else
+ } else {
+ if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags))
+ BNAD_UPDATE_CTR(bnad, cee_toggle);
clear_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags);
+ }
if (link_up) {
if (!netif_carrier_ok(bnad->netdev)) {
- struct bna_tcb *tcb = bnad->tx_info[0].tcb[0];
- if (!tcb)
- return;
- pr_warn("bna: %s link up\n",
+ uint tx_id, tcb_id;
+ printk(KERN_WARNING "bna: %s link up\n",
bnad->netdev->name);
netif_carrier_on(bnad->netdev);
BNAD_UPDATE_CTR(bnad, link_toggle);
- if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
- /* Force an immediate Transmit Schedule */
- pr_info("bna: %s TX_STARTED\n",
- bnad->netdev->name);
- netif_wake_queue(bnad->netdev);
- BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
- } else {
- netif_stop_queue(bnad->netdev);
- BNAD_UPDATE_CTR(bnad, netif_queue_stop);
+ for (tx_id = 0; tx_id < bnad->num_tx; tx_id++) {
+ for (tcb_id = 0; tcb_id < bnad->num_txq_per_tx;
+ tcb_id++) {
+ struct bna_tcb *tcb =
+ bnad->tx_info[tx_id].tcb[tcb_id];
+ u32 txq_id;
+ if (!tcb)
+ continue;
+
+ txq_id = tcb->id;
+
+ if (test_bit(BNAD_TXQ_TX_STARTED,
+ &tcb->flags)) {
+ /*
+ * Force an immediate
+ * Transmit Schedule */
+ printk(KERN_INFO "bna: %s %d "
+ "TXQ_STARTED\n",
+ bnad->netdev->name,
+ txq_id);
+ netif_wake_subqueue(
+ bnad->netdev,
+ txq_id);
+ BNAD_UPDATE_CTR(bnad,
+ netif_queue_wakeup);
+ } else {
+ netif_stop_subqueue(
+ bnad->netdev,
+ txq_id);
+ BNAD_UPDATE_CTR(bnad,
+ netif_queue_stop);
+ }
+ }
}
}
} else {
if (netif_carrier_ok(bnad->netdev)) {
- pr_warn("bna: %s link down\n",
+ printk(KERN_WARNING "bna: %s link down\n",
bnad->netdev->name);
netif_carrier_off(bnad->netdev);
BNAD_UPDATE_CTR(bnad, link_toggle);
@@ -786,8 +789,7 @@ bnad_cb_port_link_status(struct bnad *bnad,
}
static void
-bnad_cb_tx_disabled(void *arg, struct bna_tx *tx,
- enum bna_cb_status status)
+bnad_cb_tx_disabled(void *arg, struct bna_tx *tx)
{
struct bnad *bnad = (struct bnad *)arg;
@@ -864,108 +866,188 @@ bnad_cb_ccb_destroy(struct bnad *bnad, struct bna_ccb *ccb)
}
static void
-bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb)
+bnad_cb_tx_stall(struct bnad *bnad, struct bna_tx *tx)
{
struct bnad_tx_info *tx_info =
- (struct bnad_tx_info *)tcb->txq->tx->priv;
-
- if (tx_info != &bnad->tx_info[0])
- return;
+ (struct bnad_tx_info *)tx->priv;
+ struct bna_tcb *tcb;
+ u32 txq_id;
+ int i;
- clear_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
- netif_stop_queue(bnad->netdev);
- pr_info("bna: %s TX_STOPPED\n", bnad->netdev->name);
+ for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) {
+ tcb = tx_info->tcb[i];
+ if (!tcb)
+ continue;
+ txq_id = tcb->id;
+ clear_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
+ netif_stop_subqueue(bnad->netdev, txq_id);
+ printk(KERN_INFO "bna: %s %d TXQ_STOPPED\n",
+ bnad->netdev->name, txq_id);
+ }
}
static void
-bnad_cb_tx_resume(struct bnad *bnad, struct bna_tcb *tcb)
+bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx)
{
- struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+ struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tx->priv;
+ struct bna_tcb *tcb;
+ struct bnad_unmap_q *unmap_q;
+ u32 txq_id;
+ int i;
- if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
- return;
+ for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) {
+ tcb = tx_info->tcb[i];
+ if (!tcb)
+ continue;
+ txq_id = tcb->id;
- clear_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags);
+ unmap_q = tcb->unmap_q;
- while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
- cpu_relax();
+ if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
+ continue;
- bnad_free_all_txbufs(bnad, tcb);
+ while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+ cpu_relax();
- unmap_q->producer_index = 0;
- unmap_q->consumer_index = 0;
+ bnad_free_all_txbufs(bnad, tcb);
- smp_mb__before_clear_bit();
- clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+ unmap_q->producer_index = 0;
+ unmap_q->consumer_index = 0;
+
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+
+ set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
+
+ if (netif_carrier_ok(bnad->netdev)) {
+ printk(KERN_INFO "bna: %s %d TXQ_STARTED\n",
+ bnad->netdev->name, txq_id);
+ netif_wake_subqueue(bnad->netdev, txq_id);
+ BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+ }
+ }
/*
- * Workaround for first device enable failure & we
+ * Workaround for first ioceth enable failure & we
* get a 0 MAC address. We try to get the MAC address
* again here.
*/
if (is_zero_ether_addr(&bnad->perm_addr.mac[0])) {
- bna_port_mac_get(&bnad->bna.port, &bnad->perm_addr);
+ bna_enet_perm_mac_get(&bnad->bna.enet, &bnad->perm_addr);
bnad_set_netdev_perm_addr(bnad);
}
+}
- set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
+static void
+bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx)
+{
+ struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tx->priv;
+ struct bna_tcb *tcb;
+ int i;
- if (netif_carrier_ok(bnad->netdev)) {
- pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
- netif_wake_queue(bnad->netdev);
- BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+ for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) {
+ tcb = tx_info->tcb[i];
+ if (!tcb)
+ continue;
}
+
+ mdelay(BNAD_TXRX_SYNC_MDELAY);
+ bna_tx_cleanup_complete(tx);
}
static void
-bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
+bnad_cb_rx_stall(struct bnad *bnad, struct bna_rx *rx)
{
- /* Delay only once for the whole Tx Path Shutdown */
- if (!test_and_set_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags))
- mdelay(BNAD_TXRX_SYNC_MDELAY);
+ struct bnad_rx_info *rx_info = (struct bnad_rx_info *)rx->priv;
+ struct bna_ccb *ccb;
+ struct bnad_rx_ctrl *rx_ctrl;
+ int i;
+
+ for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) {
+ rx_ctrl = &rx_info->rx_ctrl[i];
+ ccb = rx_ctrl->ccb;
+ if (!ccb)
+ continue;
+
+ clear_bit(BNAD_RXQ_POST_OK, &ccb->rcb[0]->flags);
+
+ if (ccb->rcb[1])
+ clear_bit(BNAD_RXQ_POST_OK, &ccb->rcb[1]->flags);
+ }
}
static void
-bnad_cb_rx_cleanup(struct bnad *bnad,
- struct bna_ccb *ccb)
+bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx)
{
- clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags);
+ struct bnad_rx_info *rx_info = (struct bnad_rx_info *)rx->priv;
+ struct bna_ccb *ccb;
+ struct bnad_rx_ctrl *rx_ctrl;
+ int i;
- if (ccb->rcb[1])
- clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
+ mdelay(BNAD_TXRX_SYNC_MDELAY);
+
+ for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) {
+ rx_ctrl = &rx_info->rx_ctrl[i];
+ ccb = rx_ctrl->ccb;
+ if (!ccb)
+ continue;
+
+ clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags);
+
+ if (ccb->rcb[1])
+ clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
- if (!test_and_set_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags))
- mdelay(BNAD_TXRX_SYNC_MDELAY);
+ while (test_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags))
+ cpu_relax();
+ }
+
+ bna_rx_cleanup_complete(rx);
}
static void
-bnad_cb_rx_post(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx)
{
- struct bnad_unmap_q *unmap_q = rcb->unmap_q;
-
- clear_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags);
-
- if (rcb == rcb->cq->ccb->rcb[0])
- bnad_cq_cmpl_init(bnad, rcb->cq->ccb);
+ struct bnad_rx_info *rx_info = (struct bnad_rx_info *)rx->priv;
+ struct bna_ccb *ccb;
+ struct bna_rcb *rcb;
+ struct bnad_rx_ctrl *rx_ctrl;
+ struct bnad_unmap_q *unmap_q;
+ int i;
+ int j;
- bnad_free_all_rxbufs(bnad, rcb);
+ for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) {
+ rx_ctrl = &rx_info->rx_ctrl[i];
+ ccb = rx_ctrl->ccb;
+ if (!ccb)
+ continue;
- set_bit(BNAD_RXQ_STARTED, &rcb->flags);
+ bnad_cq_cmpl_init(bnad, ccb);
- /* 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_alloc_n_post_rxbufs(bnad, rcb);
- smp_mb__before_clear_bit();
- clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
+ for (j = 0; j < BNAD_MAX_RXQ_PER_RXP; j++) {
+ rcb = ccb->rcb[j];
+ if (!rcb)
+ continue;
+ bnad_free_all_rxbufs(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_alloc_n_post_rxbufs(bnad, rcb);
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
+ }
+ }
}
}
static void
-bnad_cb_rx_disabled(void *arg, struct bna_rx *rx,
- enum bna_cb_status status)
+bnad_cb_rx_disabled(void *arg, struct bna_rx *rx)
{
struct bnad *bnad = (struct bnad *)arg;
@@ -973,10 +1055,9 @@ bnad_cb_rx_disabled(void *arg, struct bna_rx *rx,
}
static void
-bnad_cb_rx_mcast_add(struct bnad *bnad, struct bna_rx *rx,
- enum bna_cb_status status)
+bnad_cb_rx_mcast_add(struct bnad *bnad, struct bna_rx *rx)
{
- bnad->bnad_completions.mcast_comp_status = status;
+ bnad->bnad_completions.mcast_comp_status = BNA_CB_SUCCESS;
complete(&bnad->bnad_completions.mcast_comp);
}
@@ -995,6 +1076,13 @@ bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status,
jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ));
}
+static void
+bnad_cb_enet_mtu_set(struct bnad *bnad)
+{
+ bnad->bnad_completions.mtu_comp_status = BNA_CB_SUCCESS;
+ complete(&bnad->bnad_completions.mtu_comp);
+}
+
/* Resource allocation, free functions */
static void
@@ -1073,23 +1161,17 @@ err_return:
/* Free IRQ for Mailbox */
static void
-bnad_mbox_irq_free(struct bnad *bnad,
- struct bna_intr_info *intr_info)
+bnad_mbox_irq_free(struct bnad *bnad)
{
int irq;
unsigned long flags;
- if (intr_info->idl == NULL)
- return;
-
spin_lock_irqsave(&bnad->bna_lock, flags);
bnad_disable_mbox_irq(bnad);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
irq = BNAD_GET_MBOX_IRQ(bnad);
free_irq(irq, bnad);
-
- kfree(intr_info->idl);
}
/*
@@ -1098,32 +1180,22 @@ bnad_mbox_irq_free(struct bnad *bnad,
* from bna
*/
static int
-bnad_mbox_irq_alloc(struct bnad *bnad,
- struct bna_intr_info *intr_info)
+bnad_mbox_irq_alloc(struct bnad *bnad)
{
int err = 0;
unsigned long irq_flags, flags;
u32 irq;
irq_handler_t irq_handler;
- /* Mbox should use only 1 vector */
-
- intr_info->idl = kzalloc(sizeof(*(intr_info->idl)), GFP_KERNEL);
- if (!intr_info->idl)
- return -ENOMEM;
-
spin_lock_irqsave(&bnad->bna_lock, flags);
if (bnad->cfg_flags & BNAD_CF_MSIX) {
irq_handler = (irq_handler_t)bnad_msix_mbox_handler;
irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector;
irq_flags = 0;
- intr_info->intr_type = BNA_INTR_T_MSIX;
- intr_info->idl[0].vector = BNAD_MAILBOX_MSIX_INDEX;
} else {
irq_handler = (irq_handler_t)bnad_isr;
irq = bnad->pcidev->irq;
irq_flags = IRQF_SHARED;
- intr_info->intr_type = BNA_INTR_T_INTX;
}
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -1140,11 +1212,6 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
err = request_irq(irq, irq_handler, irq_flags,
bnad->mbox_irq_name, bnad);
- if (err) {
- kfree(intr_info->idl);
- intr_info->idl = NULL;
- }
-
return err;
}
@@ -1158,7 +1225,7 @@ bnad_txrx_irq_free(struct bnad *bnad, struct bna_intr_info *intr_info)
/* Allocates Interrupt Descriptor List for MSIX/INT-X vectors */
static int
bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
- uint txrx_id, struct bna_intr_info *intr_info)
+ u32 txrx_id, struct bna_intr_info *intr_info)
{
int i, vector_start = 0;
u32 cfg_flags;
@@ -1241,7 +1308,7 @@ bnad_tx_msix_unregister(struct bnad *bnad, struct bnad_tx_info *tx_info,
*/
static int
bnad_tx_msix_register(struct bnad *bnad, struct bnad_tx_info *tx_info,
- uint tx_id, int num_txqs)
+ u32 tx_id, int num_txqs)
{
int i;
int err;
@@ -1294,7 +1361,7 @@ bnad_rx_msix_unregister(struct bnad *bnad, struct bnad_rx_info *rx_info,
*/
static int
bnad_rx_msix_register(struct bnad *bnad, struct bnad_rx_info *rx_info,
- uint rx_id, int num_rxps)
+ u32 rx_id, int num_rxps)
{
int i;
int err;
@@ -1338,7 +1405,7 @@ bnad_tx_res_free(struct bnad *bnad, struct bna_res_info *res_info)
/* Allocates memory and interrupt resources for Tx object */
static int
bnad_tx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
- uint tx_id)
+ u32 tx_id)
{
int i, err = 0;
@@ -1407,7 +1474,7 @@ bnad_ioc_timeout(unsigned long data)
unsigned long flags;
spin_lock_irqsave(&bnad->bna_lock, flags);
- bfa_nw_ioc_timeout((void *) &bnad->bna.device.ioc);
+ bfa_nw_ioc_timeout((void *) &bnad->bna.ioceth.ioc);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
@@ -1418,7 +1485,7 @@ bnad_ioc_hb_check(unsigned long data)
unsigned long flags;
spin_lock_irqsave(&bnad->bna_lock, flags);
- bfa_nw_ioc_hb_check((void *) &bnad->bna.device.ioc);
+ bfa_nw_ioc_hb_check((void *) &bnad->bna.ioceth.ioc);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
@@ -1429,7 +1496,7 @@ bnad_iocpf_timeout(unsigned long data)
unsigned long flags;
spin_lock_irqsave(&bnad->bna_lock, flags);
- bfa_nw_iocpf_timeout((void *) &bnad->bna.device.ioc);
+ bfa_nw_iocpf_timeout((void *) &bnad->bna.ioceth.ioc);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
@@ -1440,7 +1507,7 @@ bnad_iocpf_sem_timeout(unsigned long data)
unsigned long flags;
spin_lock_irqsave(&bnad->bna_lock, flags);
- bfa_nw_iocpf_sem_timeout((void *) &bnad->bna.device.ioc);
+ bfa_nw_iocpf_sem_timeout((void *) &bnad->bna.ioceth.ioc);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
@@ -1499,7 +1566,7 @@ bnad_stats_timeout(unsigned long data)
return;
spin_lock_irqsave(&bnad->bna_lock, flags);
- bna_stats_get(&bnad->bna);
+ bna_hw_stats_get(&bnad->bna);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
@@ -1577,32 +1644,32 @@ bnad_napi_poll_rx(struct napi_struct *napi, int budget)
{
struct bnad_rx_ctrl *rx_ctrl =
container_of(napi, struct bnad_rx_ctrl, napi);
- struct bna_ccb *ccb;
- struct bnad *bnad;
+ struct bnad *bnad = rx_ctrl->bnad;
int rcvd = 0;
- ccb = rx_ctrl->ccb;
-
- bnad = ccb->bnad;
+ rx_ctrl->rx_poll_ctr++;
if (!netif_carrier_ok(bnad->netdev))
goto poll_exit;
- rcvd = bnad_poll_cq(bnad, ccb, budget);
- if (rcvd == budget)
+ rcvd = bnad_poll_cq(bnad, rx_ctrl->ccb, budget);
+ if (rcvd >= budget)
return rcvd;
poll_exit:
- napi_complete((napi));
+ napi_complete(napi);
- BNAD_UPDATE_CTR(bnad, netif_rx_complete);
+ rx_ctrl->rx_complete++;
+
+ if (rx_ctrl->ccb)
+ bnad_enable_rx_irq_unsafe(rx_ctrl->ccb);
- bnad_enable_rx_irq(bnad, ccb);
return rcvd;
}
+#define BNAD_NAPI_POLL_QUOTA 64
static void
-bnad_napi_enable(struct bnad *bnad, u32 rx_id)
+bnad_napi_init(struct bnad *bnad, u32 rx_id)
{
struct bnad_rx_ctrl *rx_ctrl;
int i;
@@ -1610,9 +1677,20 @@ bnad_napi_enable(struct bnad *bnad, u32 rx_id)
/* Initialize & enable NAPI */
for (i = 0; i < bnad->num_rxp_per_rx; i++) {
rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i];
-
netif_napi_add(bnad->netdev, &rx_ctrl->napi,
- bnad_napi_poll_rx, 64);
+ bnad_napi_poll_rx, BNAD_NAPI_POLL_QUOTA);
+ }
+}
+
+static void
+bnad_napi_enable(struct bnad *bnad, u32 rx_id)
+{
+ struct bnad_rx_ctrl *rx_ctrl;
+ int i;
+
+ /* Initialize & enable NAPI */
+ for (i = 0; i < bnad->num_rxp_per_rx; i++) {
+ rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i];
napi_enable(&rx_ctrl->napi);
}
@@ -1632,7 +1710,7 @@ bnad_napi_disable(struct bnad *bnad, u32 rx_id)
/* Should be held with conf_lock held */
void
-bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
+bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
{
struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
@@ -1651,21 +1729,22 @@ bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
bnad_tx_msix_unregister(bnad, tx_info,
bnad->num_txq_per_tx);
+ if (0 == tx_id)
+ tasklet_kill(&bnad->tx_free_tasklet);
+
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_tx_destroy(tx_info->tx);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
tx_info->tx = NULL;
-
- if (0 == tx_id)
- tasklet_kill(&bnad->tx_free_tasklet);
+ tx_info->tx_id = 0;
bnad_tx_res_free(bnad, res_info);
}
/* Should be held with conf_lock held */
int
-bnad_setup_tx(struct bnad *bnad, uint tx_id)
+bnad_setup_tx(struct bnad *bnad, u32 tx_id)
{
int err;
struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
@@ -1673,21 +1752,24 @@ bnad_setup_tx(struct bnad *bnad, uint tx_id)
struct bna_intr_info *intr_info =
&res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
struct bna_tx_config *tx_config = &bnad->tx_config[tx_id];
- struct bna_tx_event_cbfn tx_cbfn;
+ static const struct bna_tx_event_cbfn tx_cbfn = {
+ .tcb_setup_cbfn = bnad_cb_tcb_setup,
+ .tcb_destroy_cbfn = bnad_cb_tcb_destroy,
+ .tx_stall_cbfn = bnad_cb_tx_stall,
+ .tx_resume_cbfn = bnad_cb_tx_resume,
+ .tx_cleanup_cbfn = bnad_cb_tx_cleanup,
+ };
+
struct bna_tx *tx;
unsigned long flags;
+ tx_info->tx_id = tx_id;
+
/* Initialize the Tx object configuration */
tx_config->num_txq = bnad->num_txq_per_tx;
tx_config->txq_depth = bnad->txq_depth;
tx_config->tx_type = BNA_TX_T_REGULAR;
-
- /* Initialize the tx event handlers */
- tx_cbfn.tcb_setup_cbfn = bnad_cb_tcb_setup;
- tx_cbfn.tcb_destroy_cbfn = bnad_cb_tcb_destroy;
- tx_cbfn.tx_stall_cbfn = bnad_cb_tx_stall;
- tx_cbfn.tx_resume_cbfn = bnad_cb_tx_resume;
- tx_cbfn.tx_cleanup_cbfn = bnad_cb_tx_cleanup;
+ tx_config->coalescing_timeo = bnad->tx_coalescing_timeo;
/* Get BNA's resource requirement for one tx object */
spin_lock_irqsave(&bnad->bna_lock, flags);
@@ -1741,14 +1823,15 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
{
rx_config->rx_type = BNA_RX_T_REGULAR;
rx_config->num_paths = bnad->num_rxp_per_rx;
+ rx_config->coalescing_timeo = bnad->rx_coalescing_timeo;
if (bnad->num_rxp_per_rx > 1) {
rx_config->rss_status = BNA_STATUS_T_ENABLED;
rx_config->rss_config.hash_type =
- (BFI_RSS_T_V4_TCP |
- BFI_RSS_T_V6_TCP |
- BFI_RSS_T_V4_IP |
- BFI_RSS_T_V6_IP);
+ (BFI_ENET_RSS_IPV6 |
+ BFI_ENET_RSS_IPV6_TCP |
+ BFI_ENET_RSS_IPV4 |
+ BFI_ENET_RSS_IPV4_TCP);
rx_config->rss_config.hash_mask =
bnad->num_rxp_per_rx - 1;
get_random_bytes(rx_config->rss_config.toeplitz_hash_key,
@@ -1766,31 +1849,41 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED;
}
+static void
+bnad_rx_ctrl_init(struct bnad *bnad, u32 rx_id)
+{
+ struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
+ int i;
+
+ for (i = 0; i < bnad->num_rxp_per_rx; i++)
+ rx_info->rx_ctrl[i].bnad = bnad;
+}
+
/* Called with mutex_lock(&bnad->conf_mutex) held */
void
-bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
+bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
{
struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
struct bna_res_info *res_info = &bnad->rx_res_info[rx_id].res_info[0];
unsigned long flags;
- int dim_timer_del = 0;
+ int to_del = 0;
if (!rx_info->rx)
return;
if (0 == rx_id) {
spin_lock_irqsave(&bnad->bna_lock, flags);
- dim_timer_del = bnad_dim_timer_running(bnad);
- if (dim_timer_del)
+ if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED &&
+ test_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags)) {
clear_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags);
+ to_del = 1;
+ }
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- if (dim_timer_del)
+ if (to_del)
del_timer_sync(&bnad->dim_timer);
}
- bnad_napi_disable(bnad, rx_id);
-
init_completion(&bnad->bnad_completions.rx_comp);
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_rx_disable(rx_info->rx, BNA_HARD_CLEANUP, bnad_cb_rx_disabled);
@@ -1800,18 +1893,21 @@ bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
if (rx_info->rx_ctrl[0].ccb->intr_type == BNA_INTR_T_MSIX)
bnad_rx_msix_unregister(bnad, rx_info, rx_config->num_paths);
+ bnad_napi_disable(bnad, rx_id);
+
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_rx_destroy(rx_info->rx);
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
rx_info->rx = NULL;
+ rx_info->rx_id = 0;
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
bnad_rx_res_free(bnad, res_info);
}
/* Called with mutex_lock(&bnad->conf_mutex) held */
int
-bnad_setup_rx(struct bnad *bnad, uint rx_id)
+bnad_setup_rx(struct bnad *bnad, u32 rx_id)
{
int err;
struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
@@ -1819,21 +1915,23 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
struct bna_intr_info *intr_info =
&res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
- struct bna_rx_event_cbfn rx_cbfn;
+ static const struct bna_rx_event_cbfn rx_cbfn = {
+ .rcb_setup_cbfn = bnad_cb_rcb_setup,
+ .rcb_destroy_cbfn = bnad_cb_rcb_destroy,
+ .ccb_setup_cbfn = bnad_cb_ccb_setup,
+ .ccb_destroy_cbfn = bnad_cb_ccb_destroy,
+ .rx_stall_cbfn = bnad_cb_rx_stall,
+ .rx_cleanup_cbfn = bnad_cb_rx_cleanup,
+ .rx_post_cbfn = bnad_cb_rx_post,
+ };
struct bna_rx *rx;
unsigned long flags;
+ rx_info->rx_id = rx_id;
+
/* Initialize the Rx object configuration */
bnad_init_rx_config(bnad, rx_config);
- /* Initialize the Rx event handlers */
- rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup;
- rx_cbfn.rcb_destroy_cbfn = bnad_cb_rcb_destroy;
- rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup;
- rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy;
- rx_cbfn.rx_cleanup_cbfn = bnad_cb_rx_cleanup;
- rx_cbfn.rx_post_cbfn = bnad_cb_rx_post;
-
/* Get BNA's resource requirement for one Rx object */
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_rx_res_req(rx_config, res_info);
@@ -1851,14 +1949,25 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
if (err)
return err;
+ bnad_rx_ctrl_init(bnad, rx_id);
+
/* Ask BNA to create one Rx object, supplying required resources */
spin_lock_irqsave(&bnad->bna_lock, flags);
rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info,
rx_info);
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
- if (!rx)
+ if (!rx) {
+ err = -ENOMEM;
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
goto err_return;
+ }
rx_info->rx = rx;
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ /*
+ * Init NAPI, so that state is set to NAPI_STATE_SCHED,
+ * so that IRQ handler cannot schedule NAPI at this point.
+ */
+ bnad_napi_init(bnad, rx_id);
/* Register ISR for the Rx object */
if (intr_info->intr_type == BNA_INTR_T_MSIX) {
@@ -1868,9 +1977,6 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
goto err_return;
}
- /* Enable NAPI */
- bnad_napi_enable(bnad, rx_id);
-
spin_lock_irqsave(&bnad->bna_lock, flags);
if (0 == rx_id) {
/* Set up Dynamic Interrupt Moderation Vector */
@@ -1887,6 +1993,9 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
bna_rx_enable(rx);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ /* Enable scheduling of NAPI */
+ bnad_napi_enable(bnad, rx_id);
+
return 0;
err_return:
@@ -1926,7 +2035,7 @@ bnad_rx_coalescing_timeo_set(struct bnad *bnad)
/*
* Called with bnad->bna_lock held
*/
-static int
+int
bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr)
{
int ret;
@@ -1946,7 +2055,7 @@ bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr)
}
/* Should be called with conf_lock held */
-static int
+int
bnad_enable_default_bcast(struct bnad *bnad)
{
struct bnad_rx_info *rx_info = &bnad->rx_info[0];
@@ -1971,15 +2080,13 @@ bnad_enable_default_bcast(struct bnad *bnad)
return 0;
}
-/* Called with bnad_conf_lock() held */
-static void
+/* Called with mutex_lock(&bnad->conf_mutex) held */
+void
bnad_restore_vlans(struct bnad *bnad, u32 rx_id)
{
u16 vid;
unsigned long flags;
- BUG_ON(!(VLAN_N_VID == (BFI_MAX_VLAN + 1)));
-
for_each_set_bit(vid, bnad->active_vlans, VLAN_N_VID) {
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_rx_vlan_add(bnad->rx_info[rx_id].rx, vid);
@@ -2031,11 +2138,11 @@ bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
void
bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
{
- struct bfi_ll_stats_mac *mac_stats;
- u64 bmap;
+ struct bfi_enet_stats_mac *mac_stats;
+ u32 bmap;
int i;
- mac_stats = &bnad->stats.bna_stats->hw_stats->mac_stats;
+ mac_stats = &bnad->stats.bna_stats->hw_stats.mac_stats;
stats->rx_errors =
mac_stats->rx_fcs_error + mac_stats->rx_alignment_error +
mac_stats->rx_frame_length_error + mac_stats->rx_code_error +
@@ -2054,13 +2161,12 @@ bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
stats->rx_crc_errors = mac_stats->rx_fcs_error;
stats->rx_frame_errors = mac_stats->rx_alignment_error;
/* recv'r fifo overrun */
- bmap = (u64)bnad->stats.bna_stats->rxf_bmap[0] |
- ((u64)bnad->stats.bna_stats->rxf_bmap[1] << 32);
- for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+ bmap = bna_rx_rid_mask(&bnad->bna);
+ for (i = 0; bmap; i++) {
if (bmap & 1) {
stats->rx_fifo_errors +=
bnad->stats.bna_stats->
- hw_stats->rxf_stats[i].frame_drops;
+ hw_stats.rxf_stats[i].frame_drops;
break;
}
bmap >>= 1;
@@ -2089,9 +2195,6 @@ bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
{
int err;
- /* SKB_GSO_TCPV4 and SKB_GSO_TCPV6 is defined since 2.6.18. */
- BUG_ON(!(skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4 ||
- skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6));
if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err) {
@@ -2118,7 +2221,6 @@ bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
} else {
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
- BUG_ON(!(skb->protocol == htons(ETH_P_IPV6)));
ipv6h->payload_len = 0;
tcp_hdr(skb)->check =
~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 0,
@@ -2140,7 +2242,7 @@ bnad_q_num_init(struct bnad *bnad)
int rxps;
rxps = min((uint)num_online_cpus(),
- (uint)(BNAD_MAX_RXS * BNAD_MAX_RXPS_PER_RX));
+ (uint)(BNAD_MAX_RX * BNAD_MAX_RXP_PER_RX));
if (!(bnad->cfg_flags & BNAD_CF_MSIX))
rxps = 1; /* INTx */
@@ -2158,7 +2260,7 @@ bnad_q_num_init(struct bnad *bnad)
* Called with bnad->bna_lock held b'cos of cfg_flags access
*/
static void
-bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
+bnad_q_num_adjust(struct bnad *bnad, int msix_vectors, int temp)
{
bnad->num_txq_per_tx = 1;
if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx) +
@@ -2171,76 +2273,72 @@ bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
bnad->num_rxp_per_rx = 1;
}
-/* Enable / disable device */
-static void
-bnad_device_disable(struct bnad *bnad)
+/* Enable / disable ioceth */
+static int
+bnad_ioceth_disable(struct bnad *bnad)
{
unsigned long flags;
-
- init_completion(&bnad->bnad_completions.ioc_comp);
+ int err = 0;
spin_lock_irqsave(&bnad->bna_lock, flags);
- bna_device_disable(&bnad->bna.device, BNA_HARD_CLEANUP);
+ init_completion(&bnad->bnad_completions.ioc_comp);
+ bna_ioceth_disable(&bnad->bna.ioceth, BNA_HARD_CLEANUP);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- wait_for_completion(&bnad->bnad_completions.ioc_comp);
+ wait_for_completion_timeout(&bnad->bnad_completions.ioc_comp,
+ msecs_to_jiffies(BNAD_IOCETH_TIMEOUT));
+
+ err = bnad->bnad_completions.ioc_comp_status;
+ return err;
}
static int
-bnad_device_enable(struct bnad *bnad)
+bnad_ioceth_enable(struct bnad *bnad)
{
int err = 0;
unsigned long flags;
- init_completion(&bnad->bnad_completions.ioc_comp);
-
spin_lock_irqsave(&bnad->bna_lock, flags);
- bna_device_enable(&bnad->bna.device);
+ init_completion(&bnad->bnad_completions.ioc_comp);
+ bnad->bnad_completions.ioc_comp_status = BNA_CB_WAITING;
+ bna_ioceth_enable(&bnad->bna.ioceth);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- wait_for_completion(&bnad->bnad_completions.ioc_comp);
+ wait_for_completion_timeout(&bnad->bnad_completions.ioc_comp,
+ msecs_to_jiffies(BNAD_IOCETH_TIMEOUT));
- if (bnad->bnad_completions.ioc_comp_status)
- err = bnad->bnad_completions.ioc_comp_status;
+ err = bnad->bnad_completions.ioc_comp_status;
return err;
}
/* Free BNA resources */
static void
-bnad_res_free(struct bnad *bnad)
+bnad_res_free(struct bnad *bnad, struct bna_res_info *res_info,
+ u32 res_val_max)
{
int i;
- struct bna_res_info *res_info = &bnad->res_info[0];
- for (i = 0; i < BNA_RES_T_MAX; i++) {
- if (res_info[i].res_type == BNA_RES_T_MEM)
- bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
- else
- bnad_mbox_irq_free(bnad, &res_info[i].res_u.intr_info);
- }
+ for (i = 0; i < res_val_max; i++)
+ bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
}
/* Allocates memory and interrupt resources for BNA */
static int
-bnad_res_alloc(struct bnad *bnad)
+bnad_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
+ u32 res_val_max)
{
int i, err;
- struct bna_res_info *res_info = &bnad->res_info[0];
- for (i = 0; i < BNA_RES_T_MAX; i++) {
- if (res_info[i].res_type == BNA_RES_T_MEM)
- err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
- else
- err = bnad_mbox_irq_alloc(bnad,
- &res_info[i].res_u.intr_info);
+ for (i = 0; i < res_val_max; i++) {
+ err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
if (err)
goto err_return;
}
return 0;
err_return:
- bnad_res_free(bnad);
+ bnad_res_free(bnad, res_info, res_val_max);
return err;
}
@@ -2273,17 +2371,21 @@ bnad_enable_msix(struct bnad *bnad)
ret = pci_enable_msix(bnad->pcidev, bnad->msix_table, bnad->msix_num);
if (ret > 0) {
/* Not enough MSI-X vectors. */
+ pr_warn("BNA: %d MSI-X vectors allocated < %d requested\n",
+ ret, bnad->msix_num);
spin_lock_irqsave(&bnad->bna_lock, flags);
/* ret = #of vectors that we got */
- bnad_q_num_adjust(bnad, ret);
+ bnad_q_num_adjust(bnad, (ret - BNAD_MAILBOX_MSIX_VECTORS) / 2,
+ (ret - BNAD_MAILBOX_MSIX_VECTORS) / 2);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx)
- + (bnad->num_rx
- * bnad->num_rxp_per_rx) +
+ bnad->msix_num = BNAD_NUM_TXQ + BNAD_NUM_RXP +
BNAD_MAILBOX_MSIX_VECTORS;
+ if (bnad->msix_num > ret)
+ goto intx_mode;
+
/* Try once more with adjusted numbers */
/* If this fails, fall back to INTx */
ret = pci_enable_msix(bnad->pcidev, bnad->msix_table,
@@ -2293,9 +2395,13 @@ bnad_enable_msix(struct bnad *bnad)
} else if (ret < 0)
goto intx_mode;
+
+ pci_intx(bnad->pcidev, 0);
+
return;
intx_mode:
+ pr_warn("BNA: MSI-X enable failed - operating in INTx mode\n");
kfree(bnad->msix_table);
bnad->msix_table = NULL;
@@ -2351,12 +2457,12 @@ bnad_open(struct net_device *netdev)
pause_config.tx_pause = 0;
pause_config.rx_pause = 0;
- mtu = ETH_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
+ mtu = ETH_HLEN + VLAN_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
spin_lock_irqsave(&bnad->bna_lock, flags);
- bna_port_mtu_set(&bnad->bna.port, mtu, NULL);
- bna_port_pause_config(&bnad->bna.port, &pause_config, NULL);
- bna_port_enable(&bnad->bna.port);
+ bna_enet_mtu_set(&bnad->bna.enet, mtu, NULL);
+ bna_enet_pause_config(&bnad->bna.enet, &pause_config, NULL);
+ bna_enet_enable(&bnad->bna.enet);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
/* Enable broadcast */
@@ -2396,14 +2502,14 @@ bnad_stop(struct net_device *netdev)
/* Stop the stats timer */
bnad_stats_timer_stop(bnad);
- init_completion(&bnad->bnad_completions.port_comp);
+ init_completion(&bnad->bnad_completions.enet_comp);
spin_lock_irqsave(&bnad->bna_lock, flags);
- bna_port_disable(&bnad->bna.port, BNA_HARD_CLEANUP,
- bnad_cb_port_disabled);
+ bna_enet_disable(&bnad->bna.enet, BNA_HARD_CLEANUP,
+ bnad_cb_enet_disabled);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- wait_for_completion(&bnad->bnad_completions.port_comp);
+ wait_for_completion(&bnad->bnad_completions.enet_comp);
bnad_cleanup_tx(bnad, 0);
bnad_cleanup_rx(bnad, 0);
@@ -2425,51 +2531,57 @@ 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 = 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;
- u32 tx_id;
int err;
+ unsigned int len;
+ u32 gso_size;
- struct bnad_tx_info *tx_info;
- struct bna_tcb *tcb;
- struct bnad_unmap_q *unmap_q;
+ struct bnad_unmap_q *unmap_q = tcb->unmap_q;
dma_addr_t dma_addr;
struct bna_txq_entry *txqent;
- bna_txq_wi_ctrl_flag_t flags;
+ u16 flags;
- if (unlikely
- (skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) {
+ 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;
}
-
- tx_id = 0;
-
- tx_info = &bnad->tx_info[tx_id];
- tcb = tx_info->tcb[tx_id];
- unmap_q = tcb->unmap_q;
/*
* Takes care of the Tx that is scheduled between clearing the flag
- * and the netif_stop_queue() call.
+ * 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 (vectors > BFI_TX_MAX_VECTORS_PER_PKT) {
+ 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 (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)) {
@@ -2501,18 +2613,12 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
}
unmap_prod = unmap_q->producer_index;
- wis_used = 1;
- vect_id = 0;
flags = 0;
txq_prod = tcb->producer_index;
BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt, txqent, wi_range);
- BUG_ON(!(wi_range <= tcb->q_depth));
txqent->hdr.wi.reserved = 0;
txqent->hdr.wi.num_vectors = vectors;
- txqent->hdr.wi.opcode =
- htons((skb_is_gso(skb) ? BNA_TXQ_WI_SEND_LSO :
- BNA_TXQ_WI_SEND));
if (vlan_tx_tag_present(skb)) {
vlan_tag = (u16) vlan_tx_tag_get(skb);
@@ -2527,62 +2633,93 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
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);
+ BNAD_UPDATE_CTR(bnad, tx_skb_mss_too_long);
+ return NETDEV_TX_OK;
+ }
+ if (unlikely((gso_size + skb_transport_offset(skb) +
+ tcp_hdrlen(skb)) >= skb->len)) {
+ txqent->hdr.wi.opcode =
+ __constant_htons(BNA_TXQ_WI_SEND);
+ txqent->hdr.wi.lso_mss = 0;
+ BNAD_UPDATE_CTR(bnad, tx_skb_tso_too_short);
+ } else {
+ txqent->hdr.wi.opcode =
+ __constant_htons(BNA_TXQ_WI_SEND_LSO);
+ txqent->hdr.wi.lso_mss = htons(gso_size);
+ }
+
err = bnad_tso_prepare(bnad, skb);
- if (err) {
+ if (unlikely(err)) {
dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, tx_skb_tso_prepare);
return NETDEV_TX_OK;
}
- txqent->hdr.wi.lso_mss = htons(skb_is_gso(skb));
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 if (skb->ip_summed == CHECKSUM_PARTIAL) {
- u8 proto = 0;
-
+ } else {
+ txqent->hdr.wi.opcode = __constant_htons(BNA_TXQ_WI_SEND);
txqent->hdr.wi.lso_mss = 0;
- if (skb->protocol == htons(ETH_P_IP))
- proto = ip_hdr(skb)->protocol;
- else if (skb->protocol == htons(ETH_P_IPV6)) {
- /* nexthdr may not be TCP immediately. */
- proto = ipv6_hdr(skb)->nexthdr;
+ if (unlikely(skb->len > (netdev->mtu + ETH_HLEN))) {
+ dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, tx_skb_non_tso_too_long);
+ return NETDEV_TX_OK;
}
- if (proto == IPPROTO_TCP) {
- flags |= BNA_TXQ_WI_CF_TCP_CKSUM;
- txqent->hdr.wi.l4_hdr_size_n_offset =
- htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
- (0, skb_transport_offset(skb)));
- BNAD_UPDATE_CTR(bnad, tcpcsum_offload);
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ u8 proto = 0;
- BUG_ON(!(skb_headlen(skb) >=
- skb_transport_offset(skb) + tcp_hdrlen(skb)));
-
- } else if (proto == IPPROTO_UDP) {
- flags |= BNA_TXQ_WI_CF_UDP_CKSUM;
- txqent->hdr.wi.l4_hdr_size_n_offset =
- htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
- (0, skb_transport_offset(skb)));
-
- BNAD_UPDATE_CTR(bnad, udpcsum_offload);
+ if (skb->protocol == __constant_htons(ETH_P_IP))
+ proto = ip_hdr(skb)->protocol;
+ else if (skb->protocol ==
+ __constant_htons(ETH_P_IPV6)) {
+ /* nexthdr may not be TCP immediately. */
+ proto = ipv6_hdr(skb)->nexthdr;
+ }
+ if (proto == IPPROTO_TCP) {
+ flags |= BNA_TXQ_WI_CF_TCP_CKSUM;
+ txqent->hdr.wi.l4_hdr_size_n_offset =
+ htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
+ (0, skb_transport_offset(skb)));
+
+ BNAD_UPDATE_CTR(bnad, tcpcsum_offload);
+
+ if (unlikely(skb_headlen(skb) <
+ skb_transport_offset(skb) + tcp_hdrlen(skb))) {
+ dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, tx_skb_tcp_hdr);
+ return NETDEV_TX_OK;
+ }
- BUG_ON(!(skb_headlen(skb) >=
- skb_transport_offset(skb) +
- sizeof(struct udphdr)));
- } else {
- err = skb_checksum_help(skb);
- BNAD_UPDATE_CTR(bnad, csum_help);
- if (err) {
+ } else if (proto == IPPROTO_UDP) {
+ flags |= BNA_TXQ_WI_CF_UDP_CKSUM;
+ txqent->hdr.wi.l4_hdr_size_n_offset =
+ htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
+ (0, skb_transport_offset(skb)));
+
+ BNAD_UPDATE_CTR(bnad, udpcsum_offload);
+ if (unlikely(skb_headlen(skb) <
+ skb_transport_offset(skb) +
+ sizeof(struct udphdr))) {
+ dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, tx_skb_udp_hdr);
+ return NETDEV_TX_OK;
+ }
+ } else {
dev_kfree_skb(skb);
- BNAD_UPDATE_CTR(bnad, csum_help_err);
+ BNAD_UPDATE_CTR(bnad, tx_skb_csum_err);
return NETDEV_TX_OK;
}
+ } else {
+ txqent->hdr.wi.l4_hdr_size_n_offset = 0;
}
- } else {
- txqent->hdr.wi.lso_mss = 0;
- txqent->hdr.wi.l4_hdr_size_n_offset = 0;
}
txqent->hdr.wi.flags = htons(flags);
@@ -2590,19 +2727,36 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
txqent->hdr.wi.frame_length = htonl(skb->len);
unmap_q->unmap_array[unmap_prod].skb = skb;
- BUG_ON(!(skb_headlen(skb) <= BFI_TX_MAX_DATA_PER_VECTOR));
- txqent->vector[vect_id].length = htons(skb_headlen(skb));
+ 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[vect_id].host_addr);
+ BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[0].host_addr);
BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+ vect_id = 0;
+ wis_used = 1;
+
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
- u32 size = frag->size;
+ 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);
+ dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, tx_skb_frag_zero);
+ return NETDEV_TX_OK;
+ }
+
+ len += size;
if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) {
vect_id = 0;
@@ -2614,22 +2768,34 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
wis_used = 0;
BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt,
txqent, wi_range);
- BUG_ON(!(wi_range <= tcb->q_depth));
}
wis_used++;
- txqent->hdr.wi_ext.opcode = htons(BNA_TXQ_WI_EXTENSION);
+ txqent->hdr.wi_ext.opcode =
+ __constant_htons(BNA_TXQ_WI_EXTENSION);
}
BUG_ON(!(size <= BFI_TX_MAX_DATA_PER_VECTOR));
txqent->vector[vect_id].length = htons(size);
- dma_addr = dma_map_page(&bnad->pcidev->dev, frag->page,
- frag->page_offset, size, DMA_TO_DEVICE);
+ 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);
}
+ 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);
+ 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;
@@ -2640,6 +2806,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
bna_txq_prod_indx_doorbell(tcb);
+ smp_mb();
if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index)
tasklet_schedule(&bnad->tx_free_tasklet);
@@ -2667,7 +2834,7 @@ bnad_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
return stats;
}
-static void
+void
bnad_set_rx_mode(struct net_device *netdev)
{
struct bnad *bnad = netdev_priv(netdev);
@@ -2706,6 +2873,9 @@ bnad_set_rx_mode(struct net_device *netdev)
}
}
+ if (bnad->rx_info[0].rx == NULL)
+ goto unlock;
+
bna_rx_mode_set(bnad->rx_info[0].rx, new_mask, valid_mask, NULL);
if (!netdev_mc_empty(netdev)) {
@@ -2760,11 +2930,25 @@ bnad_set_mac_address(struct net_device *netdev, void *mac_addr)
}
static int
-bnad_change_mtu(struct net_device *netdev, int new_mtu)
+bnad_mtu_set(struct bnad *bnad, int mtu)
{
- int mtu, err = 0;
unsigned long flags;
+ init_completion(&bnad->bnad_completions.mtu_comp);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_enet_mtu_set(&bnad->bna.enet, mtu, bnad_cb_enet_mtu_set);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ wait_for_completion(&bnad->bnad_completions.mtu_comp);
+
+ return bnad->bnad_completions.mtu_comp_status;
+}
+
+static int
+bnad_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ int err, mtu = netdev->mtu;
struct bnad *bnad = netdev_priv(netdev);
if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU)
@@ -2774,11 +2958,10 @@ bnad_change_mtu(struct net_device *netdev, int new_mtu)
netdev->mtu = new_mtu;
- mtu = ETH_HLEN + new_mtu + ETH_FCS_LEN;
-
- spin_lock_irqsave(&bnad->bna_lock, flags);
- bna_port_mtu_set(&bnad->bna.port, mtu, NULL);
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ mtu = ETH_HLEN + VLAN_HLEN + new_mtu + ETH_FCS_LEN;
+ err = bnad_mtu_set(bnad, mtu);
+ if (err)
+ err = -EBUSY;
mutex_unlock(&bnad->conf_mutex);
return err;
@@ -2839,18 +3022,21 @@ bnad_netpoll(struct net_device *netdev)
bnad_isr(bnad->pcidev->irq, netdev);
bna_intx_enable(&bnad->bna, curr_mask);
} else {
+ /*
+ * Tx processing may happen in sending context, so no need
+ * to explicitly process completions here
+ */
+
+ /* Rx processing */
for (i = 0; i < bnad->num_rx; i++) {
rx_info = &bnad->rx_info[i];
if (!rx_info->rx)
continue;
for (j = 0; j < bnad->num_rxp_per_rx; j++) {
rx_ctrl = &rx_info->rx_ctrl[j];
- if (rx_ctrl->ccb) {
- bnad_disable_rx_irq(bnad,
- rx_ctrl->ccb);
+ if (rx_ctrl->ccb)
bnad_netif_rx_schedule_poll(bnad,
rx_ctrl->ccb);
- }
}
}
}
@@ -2863,7 +3049,6 @@ static const struct net_device_ops bnad_netdev_ops = {
.ndo_start_xmit = bnad_start_xmit,
.ndo_get_stats64 = bnad_get_stats64,
.ndo_set_rx_mode = bnad_set_rx_mode,
- .ndo_set_multicast_list = bnad_set_rx_mode,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = bnad_set_mac_address,
.ndo_change_mtu = bnad_change_mtu,
@@ -2968,7 +3153,7 @@ bnad_uninit(struct bnad *bnad)
/*
* Initialize locks
- a) Per device mutes used for serializing configuration
+ a) Per ioceth mutes used for serializing configuration
changes from OS interface
b) spin lock used to protect bna state machine
*/
@@ -3033,7 +3218,7 @@ static int __devinit
bnad_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pcidev_id)
{
- bool using_dac = false;
+ bool using_dac;
int err;
struct bnad *bnad;
struct bna *bna;
@@ -3058,12 +3243,15 @@ bnad_pci_probe(struct pci_dev *pdev,
*/
netdev = alloc_etherdev(sizeof(struct bnad));
if (!netdev) {
- dev_err(&pdev->dev, "alloc_etherdev failed\n");
+ dev_err(&pdev->dev, "netdev allocation failed\n");
err = -ENOMEM;
return err;
}
bnad = netdev_priv(netdev);
+ bnad_lock_init(bnad);
+
+ mutex_lock(&bnad->conf_mutex);
/*
* PCI initialization
* Output : using_dac = 1 for 64 bit DMA
@@ -3071,9 +3259,8 @@ bnad_pci_probe(struct pci_dev *pdev,
*/
err = bnad_pci_init(bnad, pdev, &using_dac);
if (err)
- goto free_netdev;
+ goto unlock_mutex;
- bnad_lock_init(bnad);
/*
* Initialize bnad structure
* Setup relation between pci_dev & netdev
@@ -3082,21 +3269,22 @@ bnad_pci_probe(struct pci_dev *pdev,
err = bnad_init(bnad, pdev, netdev);
if (err)
goto pci_uninit;
+
/* Initialize netdev structure, set up ethtool ops */
bnad_netdev_init(bnad, using_dac);
/* Set link to down state */
netif_carrier_off(netdev);
- bnad_enable_msix(bnad);
-
/* Get resource requirement form bna */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
bna_res_req(&bnad->res_info[0]);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
/* Allocate resources from bna */
- err = bnad_res_alloc(bnad);
+ err = bnad_res_alloc(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
if (err)
- goto free_netdev;
+ goto drv_uninit;
bna = &bnad->bna;
@@ -3106,38 +3294,74 @@ bnad_pci_probe(struct pci_dev *pdev,
pcidev_info.device_id = bnad->pcidev->device;
pcidev_info.pci_bar_kva = bnad->bar0;
- mutex_lock(&bnad->conf_mutex);
-
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_init(bna, bnad, &pcidev_info, &bnad->res_info[0]);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
bnad->stats.bna_stats = &bna->stats;
+ bnad_enable_msix(bnad);
+ err = bnad_mbox_irq_alloc(bnad);
+ if (err)
+ goto res_free;
+
+
/* Set up timers */
- setup_timer(&bnad->bna.device.ioc.ioc_timer, bnad_ioc_timeout,
+ setup_timer(&bnad->bna.ioceth.ioc.ioc_timer, bnad_ioc_timeout,
((unsigned long)bnad));
- setup_timer(&bnad->bna.device.ioc.hb_timer, bnad_ioc_hb_check,
+ setup_timer(&bnad->bna.ioceth.ioc.hb_timer, bnad_ioc_hb_check,
((unsigned long)bnad));
- setup_timer(&bnad->bna.device.ioc.iocpf_timer, bnad_iocpf_timeout,
+ setup_timer(&bnad->bna.ioceth.ioc.iocpf_timer, bnad_iocpf_timeout,
((unsigned long)bnad));
- setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_iocpf_sem_timeout,
+ setup_timer(&bnad->bna.ioceth.ioc.sem_timer, bnad_iocpf_sem_timeout,
((unsigned long)bnad));
/* Now start the timer before calling IOC */
- mod_timer(&bnad->bna.device.ioc.iocpf_timer,
+ mod_timer(&bnad->bna.ioceth.ioc.iocpf_timer,
jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ));
/*
* Start the chip
- * Don't care even if err != 0, bna state machine will
- * deal with it
+ * If the call back comes with error, we bail out.
+ * This is a catastrophic error.
*/
- err = bnad_device_enable(bnad);
+ err = bnad_ioceth_enable(bnad);
+ if (err) {
+ pr_err("BNA: Initialization failed err=%d\n",
+ err);
+ goto probe_success;
+ }
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) ||
+ bna_num_rxp_set(bna, BNAD_NUM_RXP + 1)) {
+ bnad_q_num_adjust(bnad, bna_attr(bna)->num_txq - 1,
+ bna_attr(bna)->num_rxp - 1);
+ if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) ||
+ bna_num_rxp_set(bna, BNAD_NUM_RXP + 1))
+ err = -EIO;
+ }
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ if (err)
+ goto disable_ioceth;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_mod_res_req(&bnad->bna, &bnad->mod_res_info[0]);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ err = bnad_res_alloc(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+ if (err) {
+ err = -EIO;
+ goto disable_ioceth;
+ }
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_mod_init(&bnad->bna, &bnad->mod_res_info[0]);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
/* Get the burnt-in mac */
spin_lock_irqsave(&bnad->bna_lock, flags);
- bna_port_mac_get(&bna->port, &bnad->perm_addr);
+ bna_enet_perm_mac_get(&bna->enet, &bnad->perm_addr);
bnad_set_netdev_perm_addr(bnad);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -3147,29 +3371,38 @@ bnad_pci_probe(struct pci_dev *pdev,
err = register_netdev(netdev);
if (err) {
pr_err("BNA : Registering with netdev failed\n");
- goto disable_device;
+ goto probe_uninit;
}
+ set_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags);
return 0;
-disable_device:
+probe_success:
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+
+probe_uninit:
mutex_lock(&bnad->conf_mutex);
- bnad_device_disable(bnad);
- del_timer_sync(&bnad->bna.device.ioc.ioc_timer);
- del_timer_sync(&bnad->bna.device.ioc.sem_timer);
- del_timer_sync(&bnad->bna.device.ioc.hb_timer);
+ bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+disable_ioceth:
+ bnad_ioceth_disable(bnad);
+ del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer);
+ del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer);
+ del_timer_sync(&bnad->bna.ioceth.ioc.hb_timer);
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_uninit(bna);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- mutex_unlock(&bnad->conf_mutex);
-
- bnad_res_free(bnad);
+ bnad_mbox_irq_free(bnad);
bnad_disable_msix(bnad);
+res_free:
+ bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
+drv_uninit:
+ bnad_uninit(bnad);
pci_uninit:
bnad_pci_uninit(pdev);
+unlock_mutex:
+ mutex_unlock(&bnad->conf_mutex);
bnad_lock_uninit(bnad);
- bnad_uninit(bnad);
-free_netdev:
free_netdev(netdev);
return err;
}
@@ -3189,21 +3422,24 @@ bnad_pci_remove(struct pci_dev *pdev)
bnad = netdev_priv(netdev);
bna = &bnad->bna;
- unregister_netdev(netdev);
+ if (test_and_clear_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags))
+ unregister_netdev(netdev);
mutex_lock(&bnad->conf_mutex);
- bnad_device_disable(bnad);
- del_timer_sync(&bnad->bna.device.ioc.ioc_timer);
- del_timer_sync(&bnad->bna.device.ioc.sem_timer);
- del_timer_sync(&bnad->bna.device.ioc.hb_timer);
+ bnad_ioceth_disable(bnad);
+ del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer);
+ del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer);
+ del_timer_sync(&bnad->bna.ioceth.ioc.hb_timer);
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_uninit(bna);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- mutex_unlock(&bnad->conf_mutex);
- bnad_res_free(bnad);
+ bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
+ bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX);
+ bnad_mbox_irq_free(bnad);
bnad_disable_msix(bnad);
bnad_pci_uninit(pdev);
+ mutex_unlock(&bnad->conf_mutex);
bnad_lock_uninit(bnad);
bnad_uninit(bnad);
free_netdev(netdev);
@@ -3215,7 +3451,14 @@ static DEFINE_PCI_DEVICE_TABLE(bnad_pci_id_table) = {
PCI_DEVICE_ID_BROCADE_CT),
.class = PCI_CLASS_NETWORK_ETHERNET << 8,
.class_mask = 0xffff00
- }, {0, }
+ },
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_BROCADE,
+ BFA_PCI_DEVICE_ID_CT2),
+ .class = PCI_CLASS_NETWORK_ETHERNET << 8,
+ .class_mask = 0xffff00
+ },
+ {0, },
};
MODULE_DEVICE_TABLE(pci, bnad_pci_id_table);
@@ -3264,3 +3507,4 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Brocade 10G PCIe Ethernet driver");
MODULE_VERSION(BNAD_VERSION);
MODULE_FIRMWARE(CNA_FW_FILE_CT);
+MODULE_FIRMWARE(CNA_FW_FILE_CT2);
diff --git a/drivers/net/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h
index 458eb30371b5..5487ca42d018 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/ethernet/brocade/bna/bnad.h
@@ -38,12 +38,13 @@
#define BNAD_TXQ_DEPTH 2048
#define BNAD_RXQ_DEPTH 2048
-#define BNAD_MAX_TXS 1
+#define BNAD_MAX_TX 1
#define BNAD_MAX_TXQ_PER_TX 8 /* 8 priority queues */
#define BNAD_TXQ_NUM 1
-#define BNAD_MAX_RXS 1
-#define BNAD_MAX_RXPS_PER_RX 16
+#define BNAD_MAX_RX 1
+#define BNAD_MAX_RXP_PER_RX 16
+#define BNAD_MAX_RXQ_PER_RXP 2
/*
* Control structure pointed to ccb->ctrl, which
@@ -52,21 +53,25 @@
*/
struct bnad_rx_ctrl {
struct bna_ccb *ccb;
+ struct bnad *bnad;
unsigned long flags;
struct napi_struct napi;
+ u64 rx_intr_ctr;
+ u64 rx_poll_ctr;
+ u64 rx_schedule;
+ u64 rx_keep_poll;
+ u64 rx_complete;
};
#define BNAD_RXMODE_PROMISC_DEFAULT BNA_RXMODE_PROMISC
-#define BNAD_GET_TX_ID(_skb) (0)
-
/*
* GLOBAL #defines (CONSTANTS)
*/
#define BNAD_NAME "bna"
#define BNAD_NAME_LEN 64
-#define BNAD_VERSION "2.3.2.3"
+#define BNAD_VERSION "3.0.2.2"
#define BNAD_MAILBOX_MSIX_INDEX 0
#define BNAD_MAILBOX_MSIX_VECTORS 1
@@ -76,9 +81,15 @@ struct bnad_rx_ctrl {
#define BNAD_STATS_TIMER_FREQ 1000 /* in msecs */
#define BNAD_DIM_TIMER_FREQ 1000 /* in msecs */
+#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_JUMBO_MTU 9000
#define BNAD_NETIF_WAKE_THRESHOLD 8
@@ -92,6 +103,11 @@ struct bnad_rx_ctrl {
/* Bit positions for rcb->flags */
#define BNAD_RXQ_REFILL 0
#define BNAD_RXQ_STARTED 1
+#define BNAD_RXQ_POST_OK 2
+
+/* Resource limits */
+#define BNAD_NUM_TXQ (bnad->num_tx * bnad->num_txq_per_tx)
+#define BNAD_NUM_RXP (bnad->num_rx * bnad->num_rxp_per_rx)
/*
* DATA STRUCTURES
@@ -115,7 +131,8 @@ struct bnad_completion {
struct completion tx_comp;
struct completion rx_comp;
struct completion stats_comp;
- struct completion port_comp;
+ struct completion enet_comp;
+ struct completion mtu_comp;
u8 ioc_comp_status;
u8 ucast_comp_status;
@@ -124,6 +141,7 @@ struct bnad_completion {
u8 rx_comp_status;
u8 stats_comp_status;
u8 port_comp_status;
+ u8 mtu_comp_status;
};
/* Tx Rx Control Stats */
@@ -137,15 +155,26 @@ struct bnad_drv_stats {
u64 tcpcsum_offload;
u64 udpcsum_offload;
u64 csum_help;
- u64 csum_help_err;
+ u64 tx_skb_too_short;
+ u64 tx_skb_stopping;
+ u64 tx_skb_max_vectors;
+ u64 tx_skb_mss_too_long;
+ u64 tx_skb_tso_too_short;
+ u64 tx_skb_tso_prepare;
+ u64 tx_skb_non_tso_too_long;
+ u64 tx_skb_tcp_hdr;
+ u64 tx_skb_udp_hdr;
+ u64 tx_skb_csum_err;
+ u64 tx_skb_headlen_too_long;
+ u64 tx_skb_headlen_zero;
+ u64 tx_skb_frag_zero;
+ u64 tx_skb_len_mismatch;
u64 hw_stats_updates;
- u64 netif_rx_schedule;
- u64 netif_rx_complete;
u64 netif_rx_dropped;
u64 link_toggle;
- u64 cee_up;
+ u64 cee_toggle;
u64 rxp_info_alloc_failed;
u64 mbox_intr_disabled;
@@ -174,12 +203,14 @@ struct bnad_rx_res_info {
struct bnad_tx_info {
struct bna_tx *tx; /* 1:1 between tx_info & tx */
struct bna_tcb *tcb[BNAD_MAX_TXQ_PER_TX];
+ u32 tx_id;
} ____cacheline_aligned;
struct bnad_rx_info {
struct bna_rx *rx; /* 1:1 between rx_info & rx */
- struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXPS_PER_RX];
+ struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXP_PER_RX];
+ u32 rx_id;
} ____cacheline_aligned;
/* Unmap queues for Tx / Rx cleanup */
@@ -205,20 +236,25 @@ struct bnad_unmap_q {
/* Defines for run_flags bit-mask */
/* Set, tested & cleared using xxx_bit() functions */
/* Values indicated bit positions */
-#define BNAD_RF_CEE_RUNNING 1
+#define BNAD_RF_CEE_RUNNING 0
+#define BNAD_RF_MTU_SET 1
#define BNAD_RF_MBOX_IRQ_DISABLED 2
-#define BNAD_RF_RX_STARTED 3
+#define BNAD_RF_NETDEV_REGISTERED 3
#define BNAD_RF_DIM_TIMER_RUNNING 4
#define BNAD_RF_STATS_TIMER_RUNNING 5
-#define BNAD_RF_TX_SHUTDOWN_DELAYED 6
-#define BNAD_RF_RX_SHUTDOWN_DELAYED 7
+#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;
/* Data path */
- struct bnad_tx_info tx_info[BNAD_MAX_TXS];
- struct bnad_rx_info rx_info[BNAD_MAX_RXS];
+ struct bnad_tx_info tx_info[BNAD_MAX_TX];
+ struct bnad_rx_info rx_info[BNAD_MAX_RX];
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
/*
@@ -238,8 +274,8 @@ struct bnad {
u8 tx_coalescing_timeo;
u8 rx_coalescing_timeo;
- struct bna_rx_config rx_config[BNAD_MAX_RXS];
- struct bna_tx_config tx_config[BNAD_MAX_TXS];
+ struct bna_rx_config rx_config[BNAD_MAX_RX];
+ struct bna_tx_config tx_config[BNAD_MAX_TX];
void __iomem *bar0; /* BAR0 address */
@@ -265,8 +301,9 @@ struct bnad {
/* Control path resources, memory & irq */
struct bna_res_info res_info[BNA_RES_T_MAX];
- struct bnad_tx_res_info tx_res_info[BNAD_MAX_TXS];
- struct bnad_rx_res_info rx_res_info[BNAD_MAX_RXS];
+ struct bna_res_info mod_res_info[BNA_MOD_RES_T_MAX];
+ struct bnad_tx_res_info tx_res_info[BNAD_MAX_TX];
+ struct bnad_rx_res_info rx_res_info[BNAD_MAX_RX];
struct bnad_completion bnad_completions;
@@ -296,16 +333,22 @@ extern u32 bnad_rxqs_per_cq;
*/
extern u32 *cna_get_firmware_buf(struct pci_dev *pdev);
/* Netdev entry point prototypes */
+extern void bnad_set_rx_mode(struct net_device *netdev);
+extern struct net_device_stats *bnad_get_netdev_stats(
+ struct net_device *netdev);
+extern int bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr);
+extern int bnad_enable_default_bcast(struct bnad *bnad);
+extern void bnad_restore_vlans(struct bnad *bnad, u32 rx_id);
extern void bnad_set_ethtool_ops(struct net_device *netdev);
/* Configuration & setup */
extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad);
extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
-extern int bnad_setup_rx(struct bnad *bnad, uint rx_id);
-extern int bnad_setup_tx(struct bnad *bnad, uint tx_id);
-extern void bnad_cleanup_tx(struct bnad *bnad, uint tx_id);
-extern void bnad_cleanup_rx(struct bnad *bnad, uint rx_id);
+extern int bnad_setup_rx(struct bnad *bnad, u32 rx_id);
+extern int bnad_setup_tx(struct bnad *bnad, u32 tx_id);
+extern void bnad_cleanup_tx(struct bnad *bnad, u32 tx_id);
+extern void bnad_cleanup_rx(struct bnad *bnad, u32 rx_id);
/* Timer start/stop protos */
extern void bnad_dim_timer_start(struct bnad *bnad);
@@ -327,15 +370,11 @@ extern void bnad_netdev_hwstats_fill(struct bnad *bnad,
#define bnad_enable_rx_irq_unsafe(_ccb) \
{ \
- if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))) {\
+ if (likely(test_bit(BNAD_RXQ_STARTED, &(_ccb)->rcb[0]->flags))) {\
bna_ib_coalescing_timer_set((_ccb)->i_dbell, \
(_ccb)->rx_coalescing_timeo); \
bna_ib_ack((_ccb)->i_dbell, 0); \
} \
}
-#define bnad_dim_timer_running(_bnad) \
- (((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED) && \
- (test_bit(BNAD_RF_DIM_TIMER_RUNNING, &((_bnad)->run_flags))))
-
#endif /* __BNAD_H__ */
diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index fea07f19a5db..fd3dcc1e9145 100644
--- a/drivers/net/bna/bnad_ethtool.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -29,14 +29,14 @@
#define BNAD_NUM_TXF_COUNTERS 12
#define BNAD_NUM_RXF_COUNTERS 10
-#define BNAD_NUM_CQ_COUNTERS 3
+#define BNAD_NUM_CQ_COUNTERS (3 + 5)
#define BNAD_NUM_RXQ_COUNTERS 6
#define BNAD_NUM_TXQ_COUNTERS 5
#define BNAD_ETHTOOL_STATS_NUM \
(sizeof(struct rtnl_link_stats64) / sizeof(u64) + \
sizeof(struct bnad_drv_stats) / sizeof(u64) + \
- offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64))
+ offsetof(struct bfi_enet_stats, rxf_stats[0]) / sizeof(u64))
static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
"rx_packets",
@@ -75,14 +75,25 @@ static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
"tcpcsum_offload",
"udpcsum_offload",
"csum_help",
- "csum_help_err",
+ "tx_skb_too_short",
+ "tx_skb_stopping",
+ "tx_skb_max_vectors",
+ "tx_skb_mss_too_long",
+ "tx_skb_tso_too_short",
+ "tx_skb_tso_prepare",
+ "tx_skb_non_tso_too_long",
+ "tx_skb_tcp_hdr",
+ "tx_skb_udp_hdr",
+ "tx_skb_csum_err",
+ "tx_skb_headlen_too_long",
+ "tx_skb_headlen_zero",
+ "tx_skb_frag_zero",
+ "tx_skb_len_mismatch",
"hw_stats_updates",
- "netif_rx_schedule",
- "netif_rx_complete",
"netif_rx_dropped",
"link_toggle",
- "cee_up",
+ "cee_toggle",
"rxp_info_alloc_failed",
"mbox_intr_disabled",
@@ -201,6 +212,20 @@ static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
"rad_rx_bcast_vlan",
"rad_rx_drops",
+ "rlb_rad_rx_frames",
+ "rlb_rad_rx_octets",
+ "rlb_rad_rx_vlan_frames",
+ "rlb_rad_rx_ucast",
+ "rlb_rad_rx_ucast_octets",
+ "rlb_rad_rx_ucast_vlan",
+ "rlb_rad_rx_mcast",
+ "rlb_rad_rx_mcast_octets",
+ "rlb_rad_rx_mcast_vlan",
+ "rlb_rad_rx_bcast",
+ "rlb_rad_rx_bcast_octets",
+ "rlb_rad_rx_bcast_vlan",
+ "rlb_rad_rx_drops",
+
"fc_rx_ucast_octets",
"fc_rx_ucast",
"fc_rx_ucast_vlan",
@@ -277,7 +302,7 @@ bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL);
if (ioc_attr) {
spin_lock_irqsave(&bnad->bna_lock, flags);
- bfa_nw_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr);
+ bfa_nw_ioc_get_attr(&bnad->bna.ioceth.ioc, ioc_attr);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
strncpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver,
@@ -288,323 +313,6 @@ bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
strncpy(drvinfo->bus_info, pci_name(bnad->pcidev), ETHTOOL_BUSINFO_LEN);
}
-static int
-get_regs(struct bnad *bnad, u32 * regs)
-{
- int num = 0, i;
- u32 reg_addr;
- unsigned long flags;
-
-#define BNAD_GET_REG(addr) \
-do { \
- if (regs) \
- regs[num++] = readl(bnad->bar0 + (addr)); \
- else \
- num++; \
-} while (0)
-
- spin_lock_irqsave(&bnad->bna_lock, flags);
-
- /* DMA Block Internal Registers */
- BNAD_GET_REG(DMA_CTRL_REG0);
- BNAD_GET_REG(DMA_CTRL_REG1);
- BNAD_GET_REG(DMA_ERR_INT_STATUS);
- BNAD_GET_REG(DMA_ERR_INT_ENABLE);
- BNAD_GET_REG(DMA_ERR_INT_STATUS_SET);
-
- /* APP Block Register Address Offset from BAR0 */
- BNAD_GET_REG(HOSTFN0_INT_STATUS);
- BNAD_GET_REG(HOSTFN0_INT_MASK);
- BNAD_GET_REG(HOST_PAGE_NUM_FN0);
- BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN0);
- BNAD_GET_REG(FN0_PCIE_ERR_REG);
- BNAD_GET_REG(FN0_ERR_TYPE_STATUS_REG);
- BNAD_GET_REG(FN0_ERR_TYPE_MSK_STATUS_REG);
-
- BNAD_GET_REG(HOSTFN1_INT_STATUS);
- BNAD_GET_REG(HOSTFN1_INT_MASK);
- BNAD_GET_REG(HOST_PAGE_NUM_FN1);
- BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN1);
- BNAD_GET_REG(FN1_PCIE_ERR_REG);
- BNAD_GET_REG(FN1_ERR_TYPE_STATUS_REG);
- BNAD_GET_REG(FN1_ERR_TYPE_MSK_STATUS_REG);
-
- BNAD_GET_REG(PCIE_MISC_REG);
-
- BNAD_GET_REG(HOST_SEM0_INFO_REG);
- BNAD_GET_REG(HOST_SEM1_INFO_REG);
- BNAD_GET_REG(HOST_SEM2_INFO_REG);
- BNAD_GET_REG(HOST_SEM3_INFO_REG);
-
- BNAD_GET_REG(TEMPSENSE_CNTL_REG);
- BNAD_GET_REG(TEMPSENSE_STAT_REG);
-
- BNAD_GET_REG(APP_LOCAL_ERR_STAT);
- BNAD_GET_REG(APP_LOCAL_ERR_MSK);
-
- BNAD_GET_REG(PCIE_LNK_ERR_STAT);
- BNAD_GET_REG(PCIE_LNK_ERR_MSK);
-
- BNAD_GET_REG(FCOE_FIP_ETH_TYPE);
- BNAD_GET_REG(RESV_ETH_TYPE);
-
- BNAD_GET_REG(HOSTFN2_INT_STATUS);
- BNAD_GET_REG(HOSTFN2_INT_MASK);
- BNAD_GET_REG(HOST_PAGE_NUM_FN2);
- BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN2);
- BNAD_GET_REG(FN2_PCIE_ERR_REG);
- BNAD_GET_REG(FN2_ERR_TYPE_STATUS_REG);
- BNAD_GET_REG(FN2_ERR_TYPE_MSK_STATUS_REG);
-
- BNAD_GET_REG(HOSTFN3_INT_STATUS);
- BNAD_GET_REG(HOSTFN3_INT_MASK);
- BNAD_GET_REG(HOST_PAGE_NUM_FN3);
- BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN3);
- BNAD_GET_REG(FN3_PCIE_ERR_REG);
- BNAD_GET_REG(FN3_ERR_TYPE_STATUS_REG);
- BNAD_GET_REG(FN3_ERR_TYPE_MSK_STATUS_REG);
-
- /* Host Command Status Registers */
- reg_addr = HOST_CMDSTS0_CLR_REG;
- for (i = 0; i < 16; i++) {
- BNAD_GET_REG(reg_addr);
- BNAD_GET_REG(reg_addr + 4);
- BNAD_GET_REG(reg_addr + 8);
- reg_addr += 0x10;
- }
-
- /* Function ID register */
- BNAD_GET_REG(FNC_ID_REG);
-
- /* Function personality register */
- BNAD_GET_REG(FNC_PERS_REG);
-
- /* Operation mode register */
- BNAD_GET_REG(OP_MODE);
-
- /* LPU0 Registers */
- BNAD_GET_REG(LPU0_MBOX_CTL_REG);
- BNAD_GET_REG(LPU0_MBOX_CMD_REG);
- BNAD_GET_REG(LPU0_MBOX_LINK_0REG);
- BNAD_GET_REG(LPU1_MBOX_LINK_0REG);
- BNAD_GET_REG(LPU0_MBOX_STATUS_0REG);
- BNAD_GET_REG(LPU1_MBOX_STATUS_0REG);
- BNAD_GET_REG(LPU0_ERR_STATUS_REG);
- BNAD_GET_REG(LPU0_ERR_SET_REG);
-
- /* LPU1 Registers */
- BNAD_GET_REG(LPU1_MBOX_CTL_REG);
- BNAD_GET_REG(LPU1_MBOX_CMD_REG);
- BNAD_GET_REG(LPU0_MBOX_LINK_1REG);
- BNAD_GET_REG(LPU1_MBOX_LINK_1REG);
- BNAD_GET_REG(LPU0_MBOX_STATUS_1REG);
- BNAD_GET_REG(LPU1_MBOX_STATUS_1REG);
- BNAD_GET_REG(LPU1_ERR_STATUS_REG);
- BNAD_GET_REG(LPU1_ERR_SET_REG);
-
- /* PSS Registers */
- BNAD_GET_REG(PSS_CTL_REG);
- BNAD_GET_REG(PSS_ERR_STATUS_REG);
- BNAD_GET_REG(ERR_STATUS_SET);
- BNAD_GET_REG(PSS_RAM_ERR_STATUS_REG);
-
- /* Catapult CPQ Registers */
- BNAD_GET_REG(HOSTFN0_LPU0_MBOX0_CMD_STAT);
- BNAD_GET_REG(HOSTFN0_LPU1_MBOX0_CMD_STAT);
- BNAD_GET_REG(LPU0_HOSTFN0_MBOX0_CMD_STAT);
- BNAD_GET_REG(LPU1_HOSTFN0_MBOX0_CMD_STAT);
-
- BNAD_GET_REG(HOSTFN0_LPU0_MBOX1_CMD_STAT);
- BNAD_GET_REG(HOSTFN0_LPU1_MBOX1_CMD_STAT);
- BNAD_GET_REG(LPU0_HOSTFN0_MBOX1_CMD_STAT);
- BNAD_GET_REG(LPU1_HOSTFN0_MBOX1_CMD_STAT);
-
- BNAD_GET_REG(HOSTFN1_LPU0_MBOX0_CMD_STAT);
- BNAD_GET_REG(HOSTFN1_LPU1_MBOX0_CMD_STAT);
- BNAD_GET_REG(LPU0_HOSTFN1_MBOX0_CMD_STAT);
- BNAD_GET_REG(LPU1_HOSTFN1_MBOX0_CMD_STAT);
-
- BNAD_GET_REG(HOSTFN1_LPU0_MBOX1_CMD_STAT);
- BNAD_GET_REG(HOSTFN1_LPU1_MBOX1_CMD_STAT);
- BNAD_GET_REG(LPU0_HOSTFN1_MBOX1_CMD_STAT);
- BNAD_GET_REG(LPU1_HOSTFN1_MBOX1_CMD_STAT);
-
- BNAD_GET_REG(HOSTFN2_LPU0_MBOX0_CMD_STAT);
- BNAD_GET_REG(HOSTFN2_LPU1_MBOX0_CMD_STAT);
- BNAD_GET_REG(LPU0_HOSTFN2_MBOX0_CMD_STAT);
- BNAD_GET_REG(LPU1_HOSTFN2_MBOX0_CMD_STAT);
-
- BNAD_GET_REG(HOSTFN2_LPU0_MBOX1_CMD_STAT);
- BNAD_GET_REG(HOSTFN2_LPU1_MBOX1_CMD_STAT);
- BNAD_GET_REG(LPU0_HOSTFN2_MBOX1_CMD_STAT);
- BNAD_GET_REG(LPU1_HOSTFN2_MBOX1_CMD_STAT);
-
- BNAD_GET_REG(HOSTFN3_LPU0_MBOX0_CMD_STAT);
- BNAD_GET_REG(HOSTFN3_LPU1_MBOX0_CMD_STAT);
- BNAD_GET_REG(LPU0_HOSTFN3_MBOX0_CMD_STAT);
- BNAD_GET_REG(LPU1_HOSTFN3_MBOX0_CMD_STAT);
-
- BNAD_GET_REG(HOSTFN3_LPU0_MBOX1_CMD_STAT);
- BNAD_GET_REG(HOSTFN3_LPU1_MBOX1_CMD_STAT);
- BNAD_GET_REG(LPU0_HOSTFN3_MBOX1_CMD_STAT);
- BNAD_GET_REG(LPU1_HOSTFN3_MBOX1_CMD_STAT);
-
- /* Host Function Force Parity Error Registers */
- BNAD_GET_REG(HOSTFN0_LPU_FORCE_PERR);
- BNAD_GET_REG(HOSTFN1_LPU_FORCE_PERR);
- BNAD_GET_REG(HOSTFN2_LPU_FORCE_PERR);
- BNAD_GET_REG(HOSTFN3_LPU_FORCE_PERR);
-
- /* LL Port[0|1] Halt Mask Registers */
- BNAD_GET_REG(LL_HALT_MSK_P0);
- BNAD_GET_REG(LL_HALT_MSK_P1);
-
- /* LL Port[0|1] Error Mask Registers */
- BNAD_GET_REG(LL_ERR_MSK_P0);
- BNAD_GET_REG(LL_ERR_MSK_P1);
-
- /* EMC FLI Registers */
- BNAD_GET_REG(FLI_CMD_REG);
- BNAD_GET_REG(FLI_ADDR_REG);
- BNAD_GET_REG(FLI_CTL_REG);
- BNAD_GET_REG(FLI_WRDATA_REG);
- BNAD_GET_REG(FLI_RDDATA_REG);
- BNAD_GET_REG(FLI_DEV_STATUS_REG);
- BNAD_GET_REG(FLI_SIG_WD_REG);
-
- BNAD_GET_REG(FLI_DEV_VENDOR_REG);
- BNAD_GET_REG(FLI_ERR_STATUS_REG);
-
- /* RxAdm 0 Registers */
- BNAD_GET_REG(RAD0_CTL_REG);
- BNAD_GET_REG(RAD0_PE_PARM_REG);
- BNAD_GET_REG(RAD0_BCN_REG);
- BNAD_GET_REG(RAD0_DEFAULT_REG);
- BNAD_GET_REG(RAD0_PROMISC_REG);
- BNAD_GET_REG(RAD0_BCNQ_REG);
- BNAD_GET_REG(RAD0_DEFAULTQ_REG);
-
- BNAD_GET_REG(RAD0_ERR_STS);
- BNAD_GET_REG(RAD0_SET_ERR_STS);
- BNAD_GET_REG(RAD0_ERR_INT_EN);
- BNAD_GET_REG(RAD0_FIRST_ERR);
- BNAD_GET_REG(RAD0_FORCE_ERR);
-
- BNAD_GET_REG(RAD0_MAC_MAN_1H);
- BNAD_GET_REG(RAD0_MAC_MAN_1L);
- BNAD_GET_REG(RAD0_MAC_MAN_2H);
- BNAD_GET_REG(RAD0_MAC_MAN_2L);
- BNAD_GET_REG(RAD0_MAC_MAN_3H);
- BNAD_GET_REG(RAD0_MAC_MAN_3L);
- BNAD_GET_REG(RAD0_MAC_MAN_4H);
- BNAD_GET_REG(RAD0_MAC_MAN_4L);
-
- BNAD_GET_REG(RAD0_LAST4_IP);
-
- /* RxAdm 1 Registers */
- BNAD_GET_REG(RAD1_CTL_REG);
- BNAD_GET_REG(RAD1_PE_PARM_REG);
- BNAD_GET_REG(RAD1_BCN_REG);
- BNAD_GET_REG(RAD1_DEFAULT_REG);
- BNAD_GET_REG(RAD1_PROMISC_REG);
- BNAD_GET_REG(RAD1_BCNQ_REG);
- BNAD_GET_REG(RAD1_DEFAULTQ_REG);
-
- BNAD_GET_REG(RAD1_ERR_STS);
- BNAD_GET_REG(RAD1_SET_ERR_STS);
- BNAD_GET_REG(RAD1_ERR_INT_EN);
-
- /* TxA0 Registers */
- BNAD_GET_REG(TXA0_CTRL_REG);
- /* TxA0 TSO Sequence # Registers (RO) */
- for (i = 0; i < 8; i++) {
- BNAD_GET_REG(TXA0_TSO_TCP_SEQ_REG(i));
- BNAD_GET_REG(TXA0_TSO_IP_INFO_REG(i));
- }
-
- /* TxA1 Registers */
- BNAD_GET_REG(TXA1_CTRL_REG);
- /* TxA1 TSO Sequence # Registers (RO) */
- for (i = 0; i < 8; i++) {
- BNAD_GET_REG(TXA1_TSO_TCP_SEQ_REG(i));
- BNAD_GET_REG(TXA1_TSO_IP_INFO_REG(i));
- }
-
- /* RxA Registers */
- BNAD_GET_REG(RXA0_CTL_REG);
- BNAD_GET_REG(RXA1_CTL_REG);
-
- /* PLB0 Registers */
- BNAD_GET_REG(PLB0_ECM_TIMER_REG);
- BNAD_GET_REG(PLB0_RL_CTL);
- for (i = 0; i < 8; i++)
- BNAD_GET_REG(PLB0_RL_MAX_BC(i));
- BNAD_GET_REG(PLB0_RL_TU_PRIO);
- for (i = 0; i < 8; i++)
- BNAD_GET_REG(PLB0_RL_BYTE_CNT(i));
- BNAD_GET_REG(PLB0_RL_MIN_REG);
- BNAD_GET_REG(PLB0_RL_MAX_REG);
- BNAD_GET_REG(PLB0_EMS_ADD_REG);
-
- /* PLB1 Registers */
- BNAD_GET_REG(PLB1_ECM_TIMER_REG);
- BNAD_GET_REG(PLB1_RL_CTL);
- for (i = 0; i < 8; i++)
- BNAD_GET_REG(PLB1_RL_MAX_BC(i));
- BNAD_GET_REG(PLB1_RL_TU_PRIO);
- for (i = 0; i < 8; i++)
- BNAD_GET_REG(PLB1_RL_BYTE_CNT(i));
- BNAD_GET_REG(PLB1_RL_MIN_REG);
- BNAD_GET_REG(PLB1_RL_MAX_REG);
- BNAD_GET_REG(PLB1_EMS_ADD_REG);
-
- /* HQM Control Register */
- BNAD_GET_REG(HQM0_CTL_REG);
- BNAD_GET_REG(HQM0_RXQ_STOP_SEM);
- BNAD_GET_REG(HQM0_TXQ_STOP_SEM);
- BNAD_GET_REG(HQM1_CTL_REG);
- BNAD_GET_REG(HQM1_RXQ_STOP_SEM);
- BNAD_GET_REG(HQM1_TXQ_STOP_SEM);
-
- /* LUT Registers */
- BNAD_GET_REG(LUT0_ERR_STS);
- BNAD_GET_REG(LUT0_SET_ERR_STS);
- BNAD_GET_REG(LUT1_ERR_STS);
- BNAD_GET_REG(LUT1_SET_ERR_STS);
-
- /* TRC Registers */
- BNAD_GET_REG(TRC_CTL_REG);
- BNAD_GET_REG(TRC_MODS_REG);
- BNAD_GET_REG(TRC_TRGC_REG);
- BNAD_GET_REG(TRC_CNT1_REG);
- BNAD_GET_REG(TRC_CNT2_REG);
- BNAD_GET_REG(TRC_NXTS_REG);
- BNAD_GET_REG(TRC_DIRR_REG);
- for (i = 0; i < 10; i++)
- BNAD_GET_REG(TRC_TRGM_REG(i));
- for (i = 0; i < 10; i++)
- BNAD_GET_REG(TRC_NXTM_REG(i));
- for (i = 0; i < 10; i++)
- BNAD_GET_REG(TRC_STRM_REG(i));
-
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
-#undef BNAD_GET_REG
- return num;
-}
-static int
-bnad_get_regs_len(struct net_device *netdev)
-{
- int ret = get_regs(netdev_priv(netdev), NULL) * sizeof(u32);
- return ret;
-}
-
-static void
-bnad_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
-{
- memset(buf, 0, bnad_get_regs_len(netdev));
- get_regs(netdev_priv(netdev), buf);
-}
-
static void
bnad_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo)
{
@@ -638,7 +346,7 @@ bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
{
struct bnad *bnad = netdev_priv(netdev);
unsigned long flags;
- int dim_timer_del = 0;
+ int to_del = 0;
if (coalesce->rx_coalesce_usecs == 0 ||
coalesce->rx_coalesce_usecs >
@@ -665,14 +373,17 @@ bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
} else {
if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) {
bnad->cfg_flags &= ~BNAD_CF_DIM_ENABLED;
- dim_timer_del = bnad_dim_timer_running(bnad);
- if (dim_timer_del) {
+ if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED &&
+ test_bit(BNAD_RF_DIM_TIMER_RUNNING,
+ &bnad->run_flags)) {
clear_bit(BNAD_RF_DIM_TIMER_RUNNING,
&bnad->run_flags);
- spin_unlock_irqrestore(&bnad->bna_lock, flags);
- del_timer_sync(&bnad->dim_timer);
- spin_lock_irqsave(&bnad->bna_lock, flags);
+ to_del = 1;
}
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ if (to_del)
+ del_timer_sync(&bnad->dim_timer);
+ spin_lock_irqsave(&bnad->bna_lock, flags);
bnad_rx_coalescing_timeo_set(bnad);
}
}
@@ -707,14 +418,10 @@ bnad_get_ringparam(struct net_device *netdev,
{
struct bnad *bnad = netdev_priv(netdev);
- ringparam->rx_max_pending = BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq;
- ringparam->rx_mini_max_pending = 0;
- ringparam->rx_jumbo_max_pending = 0;
- ringparam->tx_max_pending = BNAD_MAX_Q_DEPTH;
+ ringparam->rx_max_pending = BNAD_MAX_RXQ_DEPTH;
+ ringparam->tx_max_pending = BNAD_MAX_TXQ_DEPTH;
ringparam->rx_pending = bnad->rxq_depth;
- ringparam->rx_mini_max_pending = 0;
- ringparam->rx_jumbo_max_pending = 0;
ringparam->tx_pending = bnad->txq_depth;
}
@@ -724,6 +431,7 @@ bnad_set_ringparam(struct net_device *netdev,
{
int i, current_err, err = 0;
struct bnad *bnad = netdev_priv(netdev);
+ unsigned long flags;
mutex_lock(&bnad->conf_mutex);
if (ringparam->rx_pending == bnad->rxq_depth &&
@@ -733,13 +441,13 @@ bnad_set_ringparam(struct net_device *netdev,
}
if (ringparam->rx_pending < BNAD_MIN_Q_DEPTH ||
- ringparam->rx_pending > BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq ||
+ ringparam->rx_pending > BNAD_MAX_RXQ_DEPTH ||
!BNA_POWER_OF_2(ringparam->rx_pending)) {
mutex_unlock(&bnad->conf_mutex);
return -EINVAL;
}
if (ringparam->tx_pending < BNAD_MIN_Q_DEPTH ||
- ringparam->tx_pending > BNAD_MAX_Q_DEPTH ||
+ ringparam->tx_pending > BNAD_MAX_TXQ_DEPTH ||
!BNA_POWER_OF_2(ringparam->tx_pending)) {
mutex_unlock(&bnad->conf_mutex);
return -EINVAL;
@@ -747,6 +455,11 @@ bnad_set_ringparam(struct net_device *netdev,
if (ringparam->rx_pending != bnad->rxq_depth) {
bnad->rxq_depth = ringparam->rx_pending;
+ if (!netif_running(netdev)) {
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+ }
+
for (i = 0; i < bnad->num_rx; i++) {
if (!bnad->rx_info[i].rx)
continue;
@@ -755,9 +468,26 @@ bnad_set_ringparam(struct net_device *netdev,
if (current_err && !err)
err = current_err;
}
+
+ if (!err && bnad->rx_info[0].rx) {
+ /* restore rx configuration */
+ bnad_restore_vlans(bnad, 0);
+ bnad_enable_default_bcast(bnad);
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bnad_mac_addr_set_locked(bnad, netdev->dev_addr);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ bnad->cfg_flags &= ~(BNAD_CF_ALLMULTI |
+ BNAD_CF_PROMISC);
+ bnad_set_rx_mode(netdev);
+ }
}
if (ringparam->tx_pending != bnad->txq_depth) {
bnad->txq_depth = ringparam->tx_pending;
+ if (!netif_running(netdev)) {
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+ }
+
for (i = 0; i < bnad->num_tx; i++) {
if (!bnad->tx_info[i].tx)
continue;
@@ -779,8 +509,8 @@ bnad_get_pauseparam(struct net_device *netdev,
struct bnad *bnad = netdev_priv(netdev);
pauseparam->autoneg = 0;
- pauseparam->rx_pause = bnad->bna.port.pause_config.rx_pause;
- pauseparam->tx_pause = bnad->bna.port.pause_config.tx_pause;
+ pauseparam->rx_pause = bnad->bna.enet.pause_config.rx_pause;
+ pauseparam->tx_pause = bnad->bna.enet.pause_config.tx_pause;
}
static int
@@ -795,12 +525,12 @@ bnad_set_pauseparam(struct net_device *netdev,
return -EINVAL;
mutex_lock(&bnad->conf_mutex);
- if (pauseparam->rx_pause != bnad->bna.port.pause_config.rx_pause ||
- pauseparam->tx_pause != bnad->bna.port.pause_config.tx_pause) {
+ if (pauseparam->rx_pause != bnad->bna.enet.pause_config.rx_pause ||
+ pauseparam->tx_pause != bnad->bna.enet.pause_config.tx_pause) {
pause_config.rx_pause = pauseparam->rx_pause;
pause_config.tx_pause = pauseparam->tx_pause;
spin_lock_irqsave(&bnad->bna_lock, flags);
- bna_port_pause_config(&bnad->bna.port, &pause_config, NULL);
+ bna_enet_pause_config(&bnad->bna.enet, &pause_config, NULL);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
}
mutex_unlock(&bnad->conf_mutex);
@@ -812,7 +542,7 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
{
struct bnad *bnad = netdev_priv(netdev);
int i, j, q_num;
- u64 bmap;
+ u32 bmap;
mutex_lock(&bnad->conf_mutex);
@@ -825,9 +555,8 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
ETH_GSTRING_LEN);
string += ETH_GSTRING_LEN;
}
- bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
- ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
- for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+ bmap = bna_tx_rid_mask(&bnad->bna);
+ for (i = 0; bmap; i++) {
if (bmap & 1) {
sprintf(string, "txf%d_ucast_octets", i);
string += ETH_GSTRING_LEN;
@@ -857,9 +586,8 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
bmap >>= 1;
}
- bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
- ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
- for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+ bmap = bna_rx_rid_mask(&bnad->bna);
+ for (i = 0; bmap; i++) {
if (bmap & 1) {
sprintf(string, "rxf%d_ucast_octets", i);
string += ETH_GSTRING_LEN;
@@ -897,6 +625,16 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
sprintf(string, "cq%d_hw_producer_index",
q_num);
string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_intr", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_poll", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_schedule", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_keep_poll", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_complete", q_num);
+ string += ETH_GSTRING_LEN;
q_num++;
}
}
@@ -979,19 +717,17 @@ static int
bnad_get_stats_count_locked(struct net_device *netdev)
{
struct bnad *bnad = netdev_priv(netdev);
- int i, j, count, rxf_active_num = 0, txf_active_num = 0;
- u64 bmap;
+ int i, j, count = 0, rxf_active_num = 0, txf_active_num = 0;
+ u32 bmap;
- bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
- ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
- for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+ bmap = bna_tx_rid_mask(&bnad->bna);
+ for (i = 0; bmap; i++) {
if (bmap & 1)
txf_active_num++;
bmap >>= 1;
}
- bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
- ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
- for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+ bmap = bna_rx_rid_mask(&bnad->bna);
+ for (i = 0; bmap; i++) {
if (bmap & 1)
rxf_active_num++;
bmap >>= 1;
@@ -1039,6 +775,17 @@ bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi)
buf[bi++] = 0; /* ccb->consumer_index */
buf[bi++] = *(bnad->rx_info[i].rx_ctrl[j].
ccb->hw_producer_index);
+
+ buf[bi++] = bnad->rx_info[i].
+ rx_ctrl[j].rx_intr_ctr;
+ buf[bi++] = bnad->rx_info[i].
+ rx_ctrl[j].rx_poll_ctr;
+ buf[bi++] = bnad->rx_info[i].
+ rx_ctrl[j].rx_schedule;
+ buf[bi++] = bnad->rx_info[i].
+ rx_ctrl[j].rx_keep_poll;
+ buf[bi++] = bnad->rx_info[i].
+ rx_ctrl[j].rx_complete;
}
}
for (i = 0; i < bnad->num_rx; i++) {
@@ -1104,7 +851,7 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
unsigned long flags;
struct rtnl_link_stats64 *net_stats64;
u64 *stats64;
- u64 bmap;
+ u32 bmap;
mutex_lock(&bnad->conf_mutex);
if (bnad_get_stats_count_locked(netdev) != stats->n_stats) {
@@ -1135,20 +882,20 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
buf[bi++] = stats64[i];
/* Fill hardware stats excluding the rxf/txf into ethtool bufs */
- stats64 = (u64 *) bnad->stats.bna_stats->hw_stats;
+ stats64 = (u64 *) &bnad->stats.bna_stats->hw_stats;
for (i = 0;
- i < offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64);
+ i < offsetof(struct bfi_enet_stats, rxf_stats[0]) /
+ sizeof(u64);
i++)
buf[bi++] = stats64[i];
/* Fill txf stats into ethtool buffers */
- bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
- ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
- for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+ bmap = bna_tx_rid_mask(&bnad->bna);
+ for (i = 0; bmap; i++) {
if (bmap & 1) {
stats64 = (u64 *)&bnad->stats.bna_stats->
- hw_stats->txf_stats[i];
- for (j = 0; j < sizeof(struct bfi_ll_stats_txf) /
+ hw_stats.txf_stats[i];
+ for (j = 0; j < sizeof(struct bfi_enet_stats_txf) /
sizeof(u64); j++)
buf[bi++] = stats64[j];
}
@@ -1156,13 +903,12 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
}
/* Fill rxf stats into ethtool buffers */
- bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
- ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
- for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+ bmap = bna_rx_rid_mask(&bnad->bna);
+ for (i = 0; bmap; i++) {
if (bmap & 1) {
stats64 = (u64 *)&bnad->stats.bna_stats->
- hw_stats->rxf_stats[i];
- for (j = 0; j < sizeof(struct bfi_ll_stats_rxf) /
+ hw_stats.rxf_stats[i];
+ for (j = 0; j < sizeof(struct bfi_enet_stats_rxf) /
sizeof(u64); j++)
buf[bi++] = stats64[j];
}
@@ -1192,8 +938,6 @@ static struct ethtool_ops bnad_ethtool_ops = {
.get_settings = bnad_get_settings,
.set_settings = bnad_set_settings,
.get_drvinfo = bnad_get_drvinfo,
- .get_regs_len = bnad_get_regs_len,
- .get_regs = bnad_get_regs,
.get_wol = bnad_get_wol,
.get_link = ethtool_op_get_link,
.get_coalesce = bnad_get_coalesce,
diff --git a/drivers/net/bna/cna.h b/drivers/net/ethernet/brocade/bna/cna.h
index a679e038747b..1b3e90dfbd9a 100644
--- a/drivers/net/bna/cna.h
+++ b/drivers/net/ethernet/brocade/bna/cna.h
@@ -21,26 +21,24 @@
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/bitops.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
+#include <linux/if_vlan.h>
#include <linux/if_ether.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/string.h>
-
-#include <linux/list.h>
#define bfa_sm_fault(__event) do { \
- pr_err("SM Assertion failure: %s: %d: event = %d", __FILE__, __LINE__, \
- __event); \
+ pr_err("SM Assertion failure: %s: %d: event = %d\n", \
+ __FILE__, __LINE__, __event); \
} while (0)
extern char bfa_version[];
-#define CNA_FW_FILE_CT "ctfw_cna.bin"
+#define CNA_FW_FILE_CT "ctfw.bin"
+#define CNA_FW_FILE_CT2 "ct2fw.bin"
#define FC_SYMNAME_MAX 256 /*!< max name server symbolic name size */
#pragma pack(1)
@@ -77,4 +75,33 @@ typedef struct mac { u8 mac[MAC_ADDRLEN]; } mac_t;
} \
}
+/*
+ * bfa_q_deq_tail - dequeue an element from tail of the queue
+ */
+#define bfa_q_deq_tail(_q, _qe) { \
+ if (!list_empty(_q)) { \
+ *((struct list_head **) (_qe)) = bfa_q_prev(_q); \
+ bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = \
+ (struct list_head *) (_q); \
+ bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\
+ bfa_q_qe_init(*((struct list_head **) _qe)); \
+ } else { \
+ *((struct list_head **) (_qe)) = (struct list_head *) NULL; \
+ } \
+}
+
+/*
+ * bfa_add_tail_head - enqueue an element at the head of queue
+ */
+#define bfa_q_enq_head(_q, _qe) { \
+ if (!(bfa_q_next(_qe) == NULL) && (bfa_q_prev(_qe) == NULL)) \
+ pr_err("Assertion failure: %s:%d: %d", \
+ __FILE__, __LINE__, \
+ (bfa_q_next(_qe) == NULL) && (bfa_q_prev(_qe) == NULL));\
+ bfa_q_next(_qe) = bfa_q_next(_q); \
+ bfa_q_prev(_qe) = (struct list_head *) (_q); \
+ bfa_q_prev(bfa_q_next(_q)) = (struct list_head *) (_qe); \
+ bfa_q_next(_q) = (struct list_head *) (_qe); \
+}
+
#endif /* __CNA_H__ */
diff --git a/drivers/net/bna/cna_fwimg.c b/drivers/net/ethernet/brocade/bna/cna_fwimg.c
index e8f4ecd9ebb5..725b9fff337f 100644
--- a/drivers/net/bna/cna_fwimg.c
+++ b/drivers/net/ethernet/brocade/bna/cna_fwimg.c
@@ -16,11 +16,12 @@
* www.brocade.com
*/
#include <linux/firmware.h>
+#include "bfi.h"
#include "cna.h"
const struct firmware *bfi_fw;
-static u32 *bfi_image_ct_cna;
-static u32 bfi_image_ct_cna_size;
+static u32 *bfi_image_ct_cna, *bfi_image_ct2_cna;
+static u32 bfi_image_ct_cna_size, bfi_image_ct2_cna_size;
static u32 *
cna_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
@@ -45,20 +46,47 @@ error:
u32 *
cna_get_firmware_buf(struct pci_dev *pdev)
{
- if (bfi_image_ct_cna_size == 0)
- cna_read_firmware(pdev, &bfi_image_ct_cna,
- &bfi_image_ct_cna_size, CNA_FW_FILE_CT);
- return bfi_image_ct_cna;
+ if (pdev->device == BFA_PCI_DEVICE_ID_CT2) {
+ if (bfi_image_ct2_cna_size == 0)
+ cna_read_firmware(pdev, &bfi_image_ct2_cna,
+ &bfi_image_ct2_cna_size, CNA_FW_FILE_CT2);
+ return bfi_image_ct2_cna;
+ } else if (bfa_asic_id_ct(pdev->device)) {
+ if (bfi_image_ct_cna_size == 0)
+ cna_read_firmware(pdev, &bfi_image_ct_cna,
+ &bfi_image_ct_cna_size, CNA_FW_FILE_CT);
+ return bfi_image_ct_cna;
+ }
+
+ return NULL;
}
u32 *
-bfa_cb_image_get_chunk(int type, u32 off)
+bfa_cb_image_get_chunk(enum bfi_asic_gen asic_gen, u32 off)
{
- return (u32 *)(bfi_image_ct_cna + off);
+ switch (asic_gen) {
+ case BFI_ASIC_GEN_CT:
+ return (u32 *)(bfi_image_ct_cna + off);
+ break;
+ case BFI_ASIC_GEN_CT2:
+ return (u32 *)(bfi_image_ct2_cna + off);
+ break;
+ default:
+ return NULL;
+ }
}
u32
-bfa_cb_image_get_size(int type)
+bfa_cb_image_get_size(enum bfi_asic_gen asic_gen)
{
- return bfi_image_ct_cna_size;
+ switch (asic_gen) {
+ case BFI_ASIC_GEN_CT:
+ return bfi_image_ct_cna_size;
+ break;
+ case BFI_ASIC_GEN_CT2:
+ return bfi_image_ct2_cna_size;
+ break;
+ default:
+ return 0;
+ }
}
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
new file mode 100644
index 000000000000..98849a1fc749
--- /dev/null
+++ b/drivers/net/ethernet/cadence/Kconfig
@@ -0,0 +1,45 @@
+#
+# Atmel device configuration
+#
+
+config HAVE_NET_MACB
+ bool
+
+config NET_ATMEL
+ bool "Atmel devices"
+ 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,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ If unsure, say Y.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the remaining Atmel network card questions. If you say Y, you will be
+ asked for your specific card in the following questions.
+
+if NET_ATMEL
+
+config ARM_AT91_ETHER
+ tristate "AT91RM9200 Ethernet support"
+ depends on ARM && ARCH_AT91RM9200
+ select NET_CORE
+ select MII
+ ---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 "Atmel MACB support"
+ depends on HAVE_NET_MACB
+ select PHYLIB
+ ---help---
+ The Atmel MACB ethernet interface is found on many AT32 and AT91
+ parts. Say Y to include support for the MACB chip.
+
+ To compile this driver as a module, choose M here: the module
+ will be called macb.
+
+endif # NET_ATMEL
diff --git a/drivers/net/ethernet/cadence/Makefile b/drivers/net/ethernet/cadence/Makefile
new file mode 100644
index 000000000000..9068b8331ed1
--- /dev/null
+++ b/drivers/net/ethernet/cadence/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Atmel network device drivers.
+#
+
+obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o
+obj-$(CONFIG_MACB) += macb.o
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 29dc43523cec..56624d303487 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -35,7 +35,7 @@
#include <asm/mach-types.h>
#include <mach/at91rm9200_emac.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <mach/board.h>
#include "at91_ether.h"
@@ -968,7 +968,7 @@ static const struct net_device_ops at91ether_netdev_ops = {
.ndo_stop = at91ether_close,
.ndo_start_xmit = at91ether_start_xmit,
.ndo_get_stats = at91ether_stats,
- .ndo_set_multicast_list = at91ether_set_multicast_list,
+ .ndo_set_rx_mode = at91ether_set_multicast_list,
.ndo_set_mac_address = set_mac_address,
.ndo_do_ioctl = at91ether_ioctl,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/ethernet/cadence/at91_ether.h
index 353f4dab62be..353f4dab62be 100644
--- a/drivers/net/arm/at91_ether.h
+++ b/drivers/net/ethernet/cadence/at91_ether.h
diff --git a/drivers/net/macb.c b/drivers/net/ethernet/cadence/macb.c
index dc4e305a1087..a437b46e5490 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -1106,7 +1106,7 @@ static const struct net_device_ops macb_netdev_ops = {
.ndo_open = macb_open,
.ndo_stop = macb_close,
.ndo_start_xmit = macb_start_xmit,
- .ndo_set_multicast_list = macb_set_rx_mode,
+ .ndo_set_rx_mode = macb_set_rx_mode,
.ndo_get_stats = macb_get_stats,
.ndo_do_ioctl = macb_ioctl,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/macb.h b/drivers/net/ethernet/cadence/macb.h
index d3212f6db703..d3212f6db703 100644
--- a/drivers/net/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig
new file mode 100644
index 000000000000..2de50f95798f
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/Kconfig
@@ -0,0 +1,107 @@
+#
+# Chelsio device configuration
+#
+
+config NET_VENDOR_CHELSIO
+ bool "Chelsio devices"
+ default y
+ depends on PCI || INET
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Chelsio devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_CHELSIO
+
+config CHELSIO_T1
+ tristate "Chelsio 10Gb Ethernet support"
+ depends on PCI
+ select CRC32
+ select MDIO
+ ---help---
+ This driver supports Chelsio gigabit and 10-gigabit
+ Ethernet cards. More information about adapter features and
+ performance tuning is in <file:Documentation/networking/cxgb.txt>.
+
+ For general information about Chelsio and our products, visit
+ our website at <http://www.chelsio.com>.
+
+ For customer support, please visit our customer support page at
+ <http://www.chelsio.com/support.html>.
+
+ Please send feedback to <linux-bugs@chelsio.com>.
+
+ To compile this driver as a module, choose M here: the module
+ will be called cxgb.
+
+config CHELSIO_T1_1G
+ bool "Chelsio gigabit Ethernet support"
+ depends on CHELSIO_T1
+ ---help---
+ Enables support for Chelsio's gigabit Ethernet PCI cards. If you
+ are using only 10G cards say 'N' here.
+
+config CHELSIO_T3
+ tristate "Chelsio Communications T3 10Gb Ethernet support"
+ depends on PCI && INET
+ select FW_LOADER
+ select MDIO
+ ---help---
+ This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
+ adapters.
+
+ For general information about Chelsio and our products, visit
+ our website at <http://www.chelsio.com>.
+
+ For customer support, please visit our customer support page at
+ <http://www.chelsio.com/support.html>.
+
+ Please send feedback to <linux-bugs@chelsio.com>.
+
+ To compile this driver as a module, choose M here: the module
+ will be called cxgb3.
+
+config CHELSIO_T4
+ tristate "Chelsio Communications T4 Ethernet support"
+ depends on PCI
+ select FW_LOADER
+ select MDIO
+ ---help---
+ This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
+ adapters.
+
+ For general information about Chelsio and our products, visit
+ our website at <http://www.chelsio.com>.
+
+ For customer support, please visit our customer support page at
+ <http://www.chelsio.com/support.html>.
+
+ Please send feedback to <linux-bugs@chelsio.com>.
+
+ To compile this driver as a module choose M here; the module
+ will be called cxgb4.
+
+config CHELSIO_T4VF
+ tristate "Chelsio Communications T4 Virtual Function Ethernet support"
+ depends on PCI
+ ---help---
+ This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
+ adapters with PCI-E SR-IOV Virtual Functions.
+
+ For general information about Chelsio and our products, visit
+ our website at <http://www.chelsio.com>.
+
+ For customer support, please visit our customer support page at
+ <http://www.chelsio.com/support.html>.
+
+ Please send feedback to <linux-bugs@chelsio.com>.
+
+ To compile this driver as a module choose M here; the module
+ will be called cxgb4vf.
+
+endif # NET_VENDOR_CHELSIO
diff --git a/drivers/net/ethernet/chelsio/Makefile b/drivers/net/ethernet/chelsio/Makefile
new file mode 100644
index 000000000000..390510b5e90f
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Chelsio network device drivers.
+#
+
+obj-$(CONFIG_CHELSIO_T1) += cxgb/
+obj-$(CONFIG_CHELSIO_T3) += cxgb3/
+obj-$(CONFIG_CHELSIO_T4) += cxgb4/
+obj-$(CONFIG_CHELSIO_T4VF) += cxgb4vf/
diff --git a/drivers/net/chelsio/Makefile b/drivers/net/ethernet/chelsio/cxgb/Makefile
index 57a4b262fd3f..57a4b262fd3f 100644
--- a/drivers/net/chelsio/Makefile
+++ b/drivers/net/ethernet/chelsio/cxgb/Makefile
diff --git a/drivers/net/chelsio/common.h b/drivers/net/ethernet/chelsio/cxgb/common.h
index 5ccbed1784d2..5ccbed1784d2 100644
--- a/drivers/net/chelsio/common.h
+++ b/drivers/net/ethernet/chelsio/cxgb/common.h
diff --git a/drivers/net/chelsio/cphy.h b/drivers/net/ethernet/chelsio/cxgb/cphy.h
index 1f095a9fc739..1f095a9fc739 100644
--- a/drivers/net/chelsio/cphy.h
+++ b/drivers/net/ethernet/chelsio/cxgb/cphy.h
diff --git a/drivers/net/chelsio/cpl5_cmd.h b/drivers/net/ethernet/chelsio/cxgb/cpl5_cmd.h
index e36d45b78cc7..e36d45b78cc7 100644
--- a/drivers/net/chelsio/cpl5_cmd.h
+++ b/drivers/net/ethernet/chelsio/cxgb/cpl5_cmd.h
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 3edbbc4c5112..ca26d97171bd 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -712,12 +712,10 @@ static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
e->rx_max_pending = MAX_RX_BUFFERS;
- e->rx_mini_max_pending = 0;
e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
e->tx_max_pending = MAX_CMDQ_ENTRIES;
e->rx_pending = adapter->params.sge.freelQ_size[!jumbo_fl];
- e->rx_mini_pending = 0;
e->rx_jumbo_pending = adapter->params.sge.freelQ_size[jumbo_fl];
e->tx_pending = adapter->params.sge.cmdQ_size[0];
}
@@ -964,7 +962,7 @@ static const struct net_device_ops cxgb_netdev_ops = {
.ndo_start_xmit = t1_start_xmit,
.ndo_get_stats = t1_get_stats,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = t1_set_rxmode,
+ .ndo_set_rx_mode = t1_set_rxmode,
.ndo_do_ioctl = t1_ioctl,
.ndo_change_mtu = t1_change_mtu,
.ndo_set_mac_address = t1_set_mac_addr,
diff --git a/drivers/net/chelsio/elmer0.h b/drivers/net/ethernet/chelsio/cxgb/elmer0.h
index eef655c827d9..eef655c827d9 100644
--- a/drivers/net/chelsio/elmer0.h
+++ b/drivers/net/ethernet/chelsio/cxgb/elmer0.h
diff --git a/drivers/net/chelsio/espi.c b/drivers/net/ethernet/chelsio/cxgb/espi.c
index 639ff1955739..639ff1955739 100644
--- a/drivers/net/chelsio/espi.c
+++ b/drivers/net/ethernet/chelsio/cxgb/espi.c
diff --git a/drivers/net/chelsio/espi.h b/drivers/net/ethernet/chelsio/cxgb/espi.h
index 5694aad4fbc0..5694aad4fbc0 100644
--- a/drivers/net/chelsio/espi.h
+++ b/drivers/net/ethernet/chelsio/cxgb/espi.h
diff --git a/drivers/net/chelsio/fpga_defs.h b/drivers/net/ethernet/chelsio/cxgb/fpga_defs.h
index ccdb2bc9ae98..ccdb2bc9ae98 100644
--- a/drivers/net/chelsio/fpga_defs.h
+++ b/drivers/net/ethernet/chelsio/cxgb/fpga_defs.h
diff --git a/drivers/net/chelsio/gmac.h b/drivers/net/ethernet/chelsio/cxgb/gmac.h
index d42337457cf7..d42337457cf7 100644
--- a/drivers/net/chelsio/gmac.h
+++ b/drivers/net/ethernet/chelsio/cxgb/gmac.h
diff --git a/drivers/net/chelsio/mv88e1xxx.c b/drivers/net/ethernet/chelsio/cxgb/mv88e1xxx.c
index 71018a4fdf15..71018a4fdf15 100644
--- a/drivers/net/chelsio/mv88e1xxx.c
+++ b/drivers/net/ethernet/chelsio/cxgb/mv88e1xxx.c
diff --git a/drivers/net/chelsio/mv88e1xxx.h b/drivers/net/ethernet/chelsio/cxgb/mv88e1xxx.h
index 967cc4286359..967cc4286359 100644
--- a/drivers/net/chelsio/mv88e1xxx.h
+++ b/drivers/net/ethernet/chelsio/cxgb/mv88e1xxx.h
diff --git a/drivers/net/chelsio/mv88x201x.c b/drivers/net/ethernet/chelsio/cxgb/mv88x201x.c
index f7136b2fd1e5..f7136b2fd1e5 100644
--- a/drivers/net/chelsio/mv88x201x.c
+++ b/drivers/net/ethernet/chelsio/cxgb/mv88x201x.c
diff --git a/drivers/net/chelsio/my3126.c b/drivers/net/ethernet/chelsio/cxgb/my3126.c
index a683fd3bb624..a683fd3bb624 100644
--- a/drivers/net/chelsio/my3126.c
+++ b/drivers/net/ethernet/chelsio/cxgb/my3126.c
diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/ethernet/chelsio/cxgb/pm3393.c
index 40c7b93ababc..40c7b93ababc 100644
--- a/drivers/net/chelsio/pm3393.c
+++ b/drivers/net/ethernet/chelsio/cxgb/pm3393.c
diff --git a/drivers/net/chelsio/regs.h b/drivers/net/ethernet/chelsio/cxgb/regs.h
index c80bf4d6d0a6..c80bf4d6d0a6 100644
--- a/drivers/net/chelsio/regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb/regs.h
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c
index e9a03fffef15..f9b602300040 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -1135,8 +1135,8 @@ static inline unsigned int compute_large_page_tx_descs(struct sk_buff *skb)
len -= SGE_TX_DESC_MAX_PLEN;
}
for (i = 0; nfrags--; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- len = frag->size;
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ len = skb_frag_size(frag);
while (len > SGE_TX_DESC_MAX_PLEN) {
count++;
len -= SGE_TX_DESC_MAX_PLEN;
@@ -1277,11 +1277,10 @@ static inline void write_tx_descs(struct adapter *adapter, struct sk_buff *skb,
ce = q->centries;
}
- mapping = pci_map_page(adapter->pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
+ mapping = skb_frag_dma_map(&adapter->pdev->dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
desc_mapping = mapping;
- desc_len = frag->size;
+ desc_len = skb_frag_size(frag);
pidx = write_large_page_tx_descs(pidx, &e1, &ce, &gen,
&desc_mapping, &desc_len,
@@ -1291,7 +1290,7 @@ static inline void write_tx_descs(struct adapter *adapter, struct sk_buff *skb,
nfrags == 0);
ce->skb = NULL;
dma_unmap_addr_set(ce, dma_addr, mapping);
- dma_unmap_len_set(ce, dma_len, frag->size);
+ dma_unmap_len_set(ce, dma_len, skb_frag_size(frag));
}
ce->skb = skb;
wmb();
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/ethernet/chelsio/cxgb/sge.h
index e03980bcdd65..e03980bcdd65 100644
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.h
diff --git a/drivers/net/chelsio/subr.c b/drivers/net/ethernet/chelsio/cxgb/subr.c
index 8a43c7e19701..8a43c7e19701 100644
--- a/drivers/net/chelsio/subr.c
+++ b/drivers/net/ethernet/chelsio/cxgb/subr.c
diff --git a/drivers/net/chelsio/suni1x10gexp_regs.h b/drivers/net/ethernet/chelsio/cxgb/suni1x10gexp_regs.h
index d0f87d82566a..d0f87d82566a 100644
--- a/drivers/net/chelsio/suni1x10gexp_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb/suni1x10gexp_regs.h
diff --git a/drivers/net/chelsio/tp.c b/drivers/net/ethernet/chelsio/cxgb/tp.c
index 8bed4a59e65f..8bed4a59e65f 100644
--- a/drivers/net/chelsio/tp.c
+++ b/drivers/net/ethernet/chelsio/cxgb/tp.c
diff --git a/drivers/net/chelsio/tp.h b/drivers/net/ethernet/chelsio/cxgb/tp.h
index dfd8ce25106a..dfd8ce25106a 100644
--- a/drivers/net/chelsio/tp.h
+++ b/drivers/net/ethernet/chelsio/cxgb/tp.h
diff --git a/drivers/net/chelsio/vsc7326.c b/drivers/net/ethernet/chelsio/cxgb/vsc7326.c
index b0cb388f5e12..b0cb388f5e12 100644
--- a/drivers/net/chelsio/vsc7326.c
+++ b/drivers/net/ethernet/chelsio/cxgb/vsc7326.c
diff --git a/drivers/net/chelsio/vsc7326_reg.h b/drivers/net/ethernet/chelsio/cxgb/vsc7326_reg.h
index 479edbcabe68..479edbcabe68 100644
--- a/drivers/net/chelsio/vsc7326_reg.h
+++ b/drivers/net/ethernet/chelsio/cxgb/vsc7326_reg.h
diff --git a/drivers/net/cxgb3/Makefile b/drivers/net/ethernet/chelsio/cxgb3/Makefile
index 29aff78c7820..29aff78c7820 100644
--- a/drivers/net/cxgb3/Makefile
+++ b/drivers/net/ethernet/chelsio/cxgb3/Makefile
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/ethernet/chelsio/cxgb3/adapter.h
index 8b395b537330..8b395b537330 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/adapter.h
diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/ethernet/chelsio/cxgb3/ael1002.c
index 2028da95afa1..2028da95afa1 100644
--- a/drivers/net/cxgb3/ael1002.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/ael1002.c
diff --git a/drivers/net/cxgb3/aq100x.c b/drivers/net/ethernet/chelsio/cxgb3/aq100x.c
index 341b7ef1508f..341b7ef1508f 100644
--- a/drivers/net/cxgb3/aq100x.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/aq100x.c
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/ethernet/chelsio/cxgb3/common.h
index df01b6343241..df01b6343241 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/common.h
diff --git a/drivers/net/cxgb3/cxgb3_ctl_defs.h b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_ctl_defs.h
index 369fe711fd7f..369fe711fd7f 100644
--- a/drivers/net/cxgb3/cxgb3_ctl_defs.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_ctl_defs.h
diff --git a/drivers/net/cxgb3/cxgb3_defs.h b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_defs.h
index 920d918ed193..920d918ed193 100644
--- a/drivers/net/cxgb3/cxgb3_defs.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_defs.h
diff --git a/drivers/net/cxgb3/cxgb3_ioctl.h b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_ioctl.h
index b19e4376ba76..b19e4376ba76 100644
--- a/drivers/net/cxgb3/cxgb3_ioctl.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_ioctl.h
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 93b41a7ac175..4d15c8f99c3b 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -1898,7 +1898,6 @@ static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
const struct qset_params *q = &adapter->params.sge.qset[pi->first_qset];
e->rx_max_pending = MAX_RX_BUFFERS;
- e->rx_mini_max_pending = 0;
e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
e->tx_max_pending = MAX_TXQ_ENTRIES;
@@ -3153,7 +3152,7 @@ static const struct net_device_ops cxgb_netdev_ops = {
.ndo_start_xmit = t3_eth_xmit,
.ndo_get_stats = cxgb_get_stats,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = cxgb_set_rxmode,
+ .ndo_set_rx_mode = cxgb_set_rxmode,
.ndo_do_ioctl = cxgb_ioctl,
.ndo_change_mtu = cxgb_change_mtu,
.ndo_set_mac_address = cxgb_set_mac_addr,
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
index da5a5d9b8aff..da5a5d9b8aff 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.h
index 929c298115ca..929c298115ca 100644
--- a/drivers/net/cxgb3/cxgb3_offload.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.h
diff --git a/drivers/net/cxgb3/firmware_exports.h b/drivers/net/ethernet/chelsio/cxgb3/firmware_exports.h
index 0d9b0e6dccff..0d9b0e6dccff 100644
--- a/drivers/net/cxgb3/firmware_exports.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/firmware_exports.h
diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/ethernet/chelsio/cxgb3/l2t.c
index 41540978a173..41540978a173 100644
--- a/drivers/net/cxgb3/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.c
diff --git a/drivers/net/cxgb3/l2t.h b/drivers/net/ethernet/chelsio/cxgb3/l2t.h
index c5f54796e2cb..c5f54796e2cb 100644
--- a/drivers/net/cxgb3/l2t.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.h
diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/ethernet/chelsio/cxgb3/mc5.c
index e13b7fe9d082..e13b7fe9d082 100644
--- a/drivers/net/cxgb3/mc5.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/mc5.c
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/ethernet/chelsio/cxgb3/regs.h
index 6990f6c65221..6990f6c65221 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/regs.h
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c
index d6fa1777a343..cfb60e1f51da 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -254,7 +254,7 @@ static inline void unmap_skb(struct sk_buff *skb, struct sge_txq *q,
while (frag_idx < nfrags && curflit < WR_FLITS) {
pci_unmap_page(pdev, be64_to_cpu(sgp->addr[j]),
- skb_shinfo(skb)->frags[frag_idx].size,
+ skb_frag_size(&skb_shinfo(skb)->frags[frag_idx]),
PCI_DMA_TODEVICE);
j ^= 1;
if (j == 0) {
@@ -977,11 +977,11 @@ static inline unsigned int make_sgl(const struct sk_buff *skb,
nfrags = skb_shinfo(skb)->nr_frags;
for (i = 0; i < nfrags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- mapping = pci_map_page(pdev, frag->page, frag->page_offset,
- frag->size, PCI_DMA_TODEVICE);
- sgp->len[j] = cpu_to_be32(frag->size);
+ mapping = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
+ sgp->len[j] = cpu_to_be32(skb_frag_size(frag));
sgp->addr[j] = cpu_to_be64(mapping);
j ^= 1;
if (j == 0)
@@ -1544,7 +1544,7 @@ static void deferred_unmap_destructor(struct sk_buff *skb)
si = skb_shinfo(skb);
for (i = 0; i < si->nr_frags; i++)
- pci_unmap_page(dui->pdev, *p++, si->frags[i].size,
+ pci_unmap_page(dui->pdev, *p++, skb_frag_size(&si->frags[i]),
PCI_DMA_TODEVICE);
}
@@ -2116,9 +2116,9 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
len -= offset;
rx_frag += nr_frags;
- rx_frag->page = sd->pg_chunk.page;
+ __skb_frag_set_page(rx_frag, sd->pg_chunk.page);
rx_frag->page_offset = sd->pg_chunk.offset + offset;
- rx_frag->size = len;
+ skb_frag_size_set(rx_frag, len);
skb->len += len;
skb->data_len += len;
diff --git a/drivers/net/cxgb3/sge_defs.h b/drivers/net/ethernet/chelsio/cxgb3/sge_defs.h
index 29b6c800b238..29b6c800b238 100644
--- a/drivers/net/cxgb3/sge_defs.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge_defs.h
diff --git a/drivers/net/cxgb3/t3_cpl.h b/drivers/net/ethernet/chelsio/cxgb3/t3_cpl.h
index 852c399a8b0a..852c399a8b0a 100644
--- a/drivers/net/cxgb3/t3_cpl.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/t3_cpl.h
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
index 44ac2f40b644..44ac2f40b644 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/ethernet/chelsio/cxgb3/t3cdev.h
index 705713b56636..705713b56636 100644
--- a/drivers/net/cxgb3/t3cdev.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/t3cdev.h
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/ethernet/chelsio/cxgb3/version.h
index 8bda06e366c8..8bda06e366c8 100644
--- a/drivers/net/cxgb3/version.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/version.h
diff --git a/drivers/net/cxgb3/vsc8211.c b/drivers/net/ethernet/chelsio/cxgb3/vsc8211.c
index 4f9a1c2724f4..4f9a1c2724f4 100644
--- a/drivers/net/cxgb3/vsc8211.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/vsc8211.c
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/ethernet/chelsio/cxgb3/xgmac.c
index 3af19a550372..3af19a550372 100644
--- a/drivers/net/cxgb3/xgmac.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/xgmac.c
diff --git a/drivers/net/cxgb4/Makefile b/drivers/net/ethernet/chelsio/cxgb4/Makefile
index 498667487f52..498667487f52 100644
--- a/drivers/net/cxgb4/Makefile
+++ b/drivers/net/ethernet/chelsio/cxgb4/Makefile
diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 223a7f72343b..0fe18850c838 100644
--- a/drivers/net/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -326,7 +326,7 @@ struct sge_fl { /* SGE free-buffer queue state */
/* A packet gather list */
struct pkt_gl {
- skb_frag_t frags[MAX_SKB_FRAGS];
+ struct page_frag frags[MAX_SKB_FRAGS];
void *va; /* virtual address of first byte */
unsigned int nfrags; /* # of fragments */
unsigned int tot_len; /* total length of fragments */
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index b4efa292fd6f..4c8f42afa3c6 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -41,6 +41,7 @@
#include <linux/err.h>
#include <linux/etherdevice.h>
#include <linux/firmware.h>
+#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/init.h>
#include <linux/log2.h>
@@ -1901,7 +1902,7 @@ static int set_rss_table(struct net_device *dev,
}
static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
- void *rules)
+ u32 *rules)
{
const struct port_info *pi = netdev_priv(dev);
@@ -3639,6 +3640,8 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->features |= netdev->hw_features | highdma;
netdev->vlan_features = netdev->features & VLAN_FEAT;
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
netdev->netdev_ops = &cxgb4_netdev_ops;
SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
}
diff --git a/drivers/net/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index b1d39b8d141a..b1d39b8d141a 100644
--- a/drivers/net/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
diff --git a/drivers/net/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
index a2d323c473f8..a2d323c473f8 100644
--- a/drivers/net/cxgb4/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
diff --git a/drivers/net/cxgb4/l2t.h b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
index 02b31d0c6410..02b31d0c6410 100644
--- a/drivers/net/cxgb4/l2t.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
diff --git a/drivers/net/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 56adf448b9fe..ddc16985d0f6 100644
--- a/drivers/net/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -215,8 +215,8 @@ static int map_skb(struct device *dev, const struct sk_buff *skb,
end = &si->frags[si->nr_frags];
for (fp = si->frags; fp < end; fp++) {
- *++addr = dma_map_page(dev, fp->page, fp->page_offset, fp->size,
- DMA_TO_DEVICE);
+ *++addr = skb_frag_dma_map(dev, fp, 0, skb_frag_size(fp),
+ DMA_TO_DEVICE);
if (dma_mapping_error(dev, *addr))
goto unwind;
}
@@ -224,7 +224,7 @@ static int map_skb(struct device *dev, const struct sk_buff *skb,
unwind:
while (fp-- > si->frags)
- dma_unmap_page(dev, *--addr, fp->size, DMA_TO_DEVICE);
+ dma_unmap_page(dev, *--addr, skb_frag_size(fp), DMA_TO_DEVICE);
dma_unmap_single(dev, addr[-1], skb_headlen(skb), DMA_TO_DEVICE);
out_err:
@@ -243,7 +243,7 @@ static void unmap_skb(struct device *dev, const struct sk_buff *skb,
si = skb_shinfo(skb);
end = &si->frags[si->nr_frags];
for (fp = si->frags; fp < end; fp++)
- dma_unmap_page(dev, *addr++, fp->size, DMA_TO_DEVICE);
+ dma_unmap_page(dev, *addr++, skb_frag_size(fp), DMA_TO_DEVICE);
}
/**
@@ -717,7 +717,7 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q,
sgl->addr0 = cpu_to_be64(addr[0] + start);
nfrags++;
} else {
- sgl->len0 = htonl(si->frags[0].size);
+ sgl->len0 = htonl(skb_frag_size(&si->frags[0]));
sgl->addr0 = cpu_to_be64(addr[1]);
}
@@ -732,13 +732,13 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q,
to = (u8 *)end > (u8 *)q->stat ? buf : sgl->sge;
for (i = (nfrags != si->nr_frags); nfrags >= 2; nfrags -= 2, to++) {
- to->len[0] = cpu_to_be32(si->frags[i].size);
- to->len[1] = cpu_to_be32(si->frags[++i].size);
+ to->len[0] = cpu_to_be32(skb_frag_size(&si->frags[i]));
+ to->len[1] = cpu_to_be32(skb_frag_size(&si->frags[++i]));
to->addr[0] = cpu_to_be64(addr[i]);
to->addr[1] = cpu_to_be64(addr[++i]);
}
if (nfrags) {
- to->len[0] = cpu_to_be32(si->frags[i].size);
+ to->len[0] = cpu_to_be32(skb_frag_size(&si->frags[i]));
to->len[1] = cpu_to_be32(0);
to->addr[0] = cpu_to_be64(addr[i + 1]);
}
@@ -1409,22 +1409,23 @@ int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb)
}
EXPORT_SYMBOL(cxgb4_ofld_send);
-static inline void copy_frags(struct skb_shared_info *ssi,
+static inline void copy_frags(struct sk_buff *skb,
const struct pkt_gl *gl, unsigned int offset)
{
- unsigned int n;
+ int i;
/* usually there's just one frag */
- ssi->frags[0].page = gl->frags[0].page;
- ssi->frags[0].page_offset = gl->frags[0].page_offset + offset;
- ssi->frags[0].size = gl->frags[0].size - offset;
- ssi->nr_frags = gl->nfrags;
- n = gl->nfrags - 1;
- if (n)
- memcpy(&ssi->frags[1], &gl->frags[1], n * sizeof(skb_frag_t));
+ __skb_fill_page_desc(skb, 0, gl->frags[0].page,
+ gl->frags[0].offset + offset,
+ gl->frags[0].size - offset);
+ skb_shinfo(skb)->nr_frags = gl->nfrags;
+ for (i = 1; i < gl->nfrags; i++)
+ __skb_fill_page_desc(skb, i, gl->frags[i].page,
+ gl->frags[i].offset,
+ gl->frags[i].size);
/* get a reference to the last page, we don't own it */
- get_page(gl->frags[n].page);
+ get_page(gl->frags[gl->nfrags - 1].page);
}
/**
@@ -1459,7 +1460,7 @@ struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
__skb_put(skb, pull_len);
skb_copy_to_linear_data(skb, gl->va, pull_len);
- copy_frags(skb_shinfo(skb), gl, pull_len);
+ copy_frags(skb, gl, pull_len);
skb->len = gl->tot_len;
skb->data_len = skb->len - pull_len;
skb->truesize += skb->data_len;
@@ -1478,7 +1479,7 @@ EXPORT_SYMBOL(cxgb4_pktgl_to_skb);
static void t4_pktgl_free(const struct pkt_gl *gl)
{
int n;
- const skb_frag_t *p;
+ const struct page_frag *p;
for (p = gl->frags, n = gl->nfrags - 1; n--; p++)
put_page(p->page);
@@ -1522,7 +1523,7 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
return;
}
- copy_frags(skb_shinfo(skb), gl, RX_PKT_PAD);
+ copy_frags(skb, gl, RX_PKT_PAD);
skb->len = gl->tot_len - RX_PKT_PAD;
skb->data_len = skb->len;
skb->truesize += skb->data_len;
@@ -1698,7 +1699,7 @@ static int process_responses(struct sge_rspq *q, int budget)
rmb();
rsp_type = RSPD_TYPE(rc->type_gen);
if (likely(rsp_type == RSP_TYPE_FLBUF)) {
- skb_frag_t *fp;
+ struct page_frag *fp;
struct pkt_gl si;
const struct rx_sw_desc *rsd;
u32 len = ntohl(rc->pldbuflen_qid), bufsz, frags;
@@ -1717,7 +1718,7 @@ static int process_responses(struct sge_rspq *q, int budget)
rsd = &rxq->fl.sdesc[rxq->fl.cidx];
bufsz = get_buf_size(rsd);
fp->page = rsd->page;
- fp->page_offset = q->offset;
+ fp->offset = q->offset;
fp->size = min(bufsz, len);
len -= fp->size;
if (!len)
@@ -1734,7 +1735,7 @@ static int process_responses(struct sge_rspq *q, int budget)
fp->size, DMA_FROM_DEVICE);
si.va = page_address(si.frags[0].page) +
- si.frags[0].page_offset;
+ si.frags[0].offset;
prefetch(si.va);
si.nfrags = frags + 1;
diff --git a/drivers/net/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index d1ec111aebd8..d1ec111aebd8 100644
--- a/drivers/net/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
diff --git a/drivers/net/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
index c26b455f37de..c26b455f37de 100644
--- a/drivers/net/cxgb4/t4_hw.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
diff --git a/drivers/net/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index eb71b8250b91..eb71b8250b91 100644
--- a/drivers/net/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
diff --git a/drivers/net/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 0adc5bcec7c4..0adc5bcec7c4 100644
--- a/drivers/net/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
diff --git a/drivers/net/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index edcfd7ec7802..edcfd7ec7802 100644
--- a/drivers/net/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
diff --git a/drivers/net/cxgb4vf/Makefile b/drivers/net/ethernet/chelsio/cxgb4vf/Makefile
index d72ee26cb4c7..d72ee26cb4c7 100644
--- a/drivers/net/cxgb4vf/Makefile
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/Makefile
diff --git a/drivers/net/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
index 594334d5c711..611396c4b381 100644
--- a/drivers/net/cxgb4vf/adapter.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
@@ -144,7 +144,7 @@ struct sge_fl {
* An ingress packet gather list.
*/
struct pkt_gl {
- skb_frag_t frags[MAX_SKB_FRAGS];
+ struct page_frag frags[MAX_SKB_FRAGS];
void *va; /* virtual address of first byte */
unsigned int nfrags; /* # of fragments */
unsigned int tot_len; /* total length of fragments */
diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index ec799139dfe2..da9072bfca8b 100644
--- a/drivers/net/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -2625,6 +2625,8 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
netdev->netdev_ops = &cxgb4vf_netdev_ops;
SET_ETHTOOL_OPS(netdev, &cxgb4vf_ethtool_ops);
diff --git a/drivers/net/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
index cffb328c46c3..8d5d55ad102d 100644
--- a/drivers/net/cxgb4vf/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -296,8 +296,8 @@ static int map_skb(struct device *dev, const struct sk_buff *skb,
si = skb_shinfo(skb);
end = &si->frags[si->nr_frags];
for (fp = si->frags; fp < end; fp++) {
- *++addr = dma_map_page(dev, fp->page, fp->page_offset, fp->size,
- DMA_TO_DEVICE);
+ *++addr = skb_frag_dma_map(dev, fp, 0, skb_frag_size(fp),
+ DMA_TO_DEVICE);
if (dma_mapping_error(dev, *addr))
goto unwind;
}
@@ -305,7 +305,7 @@ static int map_skb(struct device *dev, const struct sk_buff *skb,
unwind:
while (fp-- > si->frags)
- dma_unmap_page(dev, *--addr, fp->size, DMA_TO_DEVICE);
+ dma_unmap_page(dev, *--addr, skb_frag_size(fp), DMA_TO_DEVICE);
dma_unmap_single(dev, addr[-1], skb_headlen(skb), DMA_TO_DEVICE);
out_err:
@@ -899,7 +899,7 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *tq,
sgl->addr0 = cpu_to_be64(addr[0] + start);
nfrags++;
} else {
- sgl->len0 = htonl(si->frags[0].size);
+ sgl->len0 = htonl(skb_frag_size(&si->frags[0]));
sgl->addr0 = cpu_to_be64(addr[1]);
}
@@ -915,13 +915,13 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *tq,
to = (u8 *)end > (u8 *)tq->stat ? buf : sgl->sge;
for (i = (nfrags != si->nr_frags); nfrags >= 2; nfrags -= 2, to++) {
- to->len[0] = cpu_to_be32(si->frags[i].size);
- to->len[1] = cpu_to_be32(si->frags[++i].size);
+ to->len[0] = cpu_to_be32(skb_frag_size(&si->frags[i]));
+ to->len[1] = cpu_to_be32(skb_frag_size(&si->frags[++i]));
to->addr[0] = cpu_to_be64(addr[i]);
to->addr[1] = cpu_to_be64(addr[++i]);
}
if (nfrags) {
- to->len[0] = cpu_to_be32(si->frags[i].size);
+ to->len[0] = cpu_to_be32(skb_frag_size(&si->frags[i]));
to->len[1] = cpu_to_be32(0);
to->addr[0] = cpu_to_be64(addr[i + 1]);
}
@@ -1357,6 +1357,35 @@ out_free:
}
/**
+ * copy_frags - copy fragments from gather list into skb_shared_info
+ * @skb: destination skb
+ * @gl: source internal packet gather list
+ * @offset: packet start offset in first page
+ *
+ * Copy an internal packet gather list into a Linux skb_shared_info
+ * structure.
+ */
+static inline void copy_frags(struct sk_buff *skb,
+ const struct pkt_gl *gl,
+ unsigned int offset)
+{
+ int i;
+
+ /* usually there's just one frag */
+ __skb_fill_page_desc(skb, 0, gl->frags[0].page,
+ gl->frags[0].offset + offset,
+ gl->frags[0].size - offset);
+ skb_shinfo(skb)->nr_frags = gl->nfrags;
+ for (i = 1; i < gl->nfrags; i++)
+ __skb_fill_page_desc(skb, i, gl->frags[i].page,
+ gl->frags[i].offset,
+ gl->frags[i].size);
+
+ /* get a reference to the last page, we don't own it */
+ get_page(gl->frags[gl->nfrags - 1].page);
+}
+
+/**
* t4vf_pktgl_to_skb - build an sk_buff from a packet gather list
* @gl: the gather list
* @skb_len: size of sk_buff main body if it carries fragments
@@ -1369,7 +1398,6 @@ struct sk_buff *t4vf_pktgl_to_skb(const struct pkt_gl *gl,
unsigned int skb_len, unsigned int pull_len)
{
struct sk_buff *skb;
- struct skb_shared_info *ssi;
/*
* If the ingress packet is small enough, allocate an skb large enough
@@ -1396,21 +1424,10 @@ struct sk_buff *t4vf_pktgl_to_skb(const struct pkt_gl *gl,
__skb_put(skb, pull_len);
skb_copy_to_linear_data(skb, gl->va, pull_len);
- ssi = skb_shinfo(skb);
- ssi->frags[0].page = gl->frags[0].page;
- ssi->frags[0].page_offset = gl->frags[0].page_offset + pull_len;
- ssi->frags[0].size = gl->frags[0].size - pull_len;
- if (gl->nfrags > 1)
- memcpy(&ssi->frags[1], &gl->frags[1],
- (gl->nfrags-1) * sizeof(skb_frag_t));
- ssi->nr_frags = gl->nfrags;
-
+ copy_frags(skb, gl, pull_len);
skb->len = gl->tot_len;
skb->data_len = skb->len - pull_len;
skb->truesize += skb->data_len;
-
- /* Get a reference for the last page, we don't own it */
- get_page(gl->frags[gl->nfrags - 1].page);
}
out:
@@ -1434,35 +1451,6 @@ void t4vf_pktgl_free(const struct pkt_gl *gl)
}
/**
- * copy_frags - copy fragments from gather list into skb_shared_info
- * @si: destination skb shared info structure
- * @gl: source internal packet gather list
- * @offset: packet start offset in first page
- *
- * Copy an internal packet gather list into a Linux skb_shared_info
- * structure.
- */
-static inline void copy_frags(struct skb_shared_info *si,
- const struct pkt_gl *gl,
- unsigned int offset)
-{
- unsigned int n;
-
- /* usually there's just one frag */
- si->frags[0].page = gl->frags[0].page;
- si->frags[0].page_offset = gl->frags[0].page_offset + offset;
- si->frags[0].size = gl->frags[0].size - offset;
- si->nr_frags = gl->nfrags;
-
- n = gl->nfrags - 1;
- if (n)
- memcpy(&si->frags[1], &gl->frags[1], n * sizeof(skb_frag_t));
-
- /* get a reference to the last page, we don't own it */
- get_page(gl->frags[n].page);
-}
-
-/**
* do_gro - perform Generic Receive Offload ingress packet processing
* @rxq: ingress RX Ethernet Queue
* @gl: gather list for ingress packet
@@ -1484,7 +1472,7 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
return;
}
- copy_frags(skb_shinfo(skb), gl, PKTSHIFT);
+ copy_frags(skb, gl, PKTSHIFT);
skb->len = gl->tot_len - PKTSHIFT;
skb->data_len = skb->len;
skb->truesize += skb->data_len;
@@ -1667,7 +1655,7 @@ int process_responses(struct sge_rspq *rspq, int budget)
rmb();
rsp_type = RSPD_TYPE(rc->type_gen);
if (likely(rsp_type == RSP_TYPE_FLBUF)) {
- skb_frag_t *fp;
+ struct page_frag *fp;
struct pkt_gl gl;
const struct rx_sw_desc *sdesc;
u32 bufsz, frag;
@@ -1701,7 +1689,7 @@ int process_responses(struct sge_rspq *rspq, int budget)
sdesc = &rxq->fl.sdesc[rxq->fl.cidx];
bufsz = get_buf_size(sdesc);
fp->page = sdesc->page;
- fp->page_offset = rspq->offset;
+ fp->offset = rspq->offset;
fp->size = min(bufsz, len);
len -= fp->size;
if (!len)
@@ -1719,7 +1707,7 @@ int process_responses(struct sge_rspq *rspq, int budget)
get_buf_addr(sdesc),
fp->size, DMA_FROM_DEVICE);
gl.va = (page_address(gl.frags[0].page) +
- gl.frags[0].page_offset);
+ gl.frags[0].offset);
prefetch(gl.va);
/*
diff --git a/drivers/net/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
index a65c80aed1f2..a65c80aed1f2 100644
--- a/drivers/net/cxgb4vf/t4vf_common.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
diff --git a/drivers/net/cxgb4vf/t4vf_defs.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_defs.h
index c7b127d93767..c7b127d93767 100644
--- a/drivers/net/cxgb4vf/t4vf_defs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_defs.h
diff --git a/drivers/net/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
index fe3fd3dad6f7..fe3fd3dad6f7 100644
--- a/drivers/net/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig
new file mode 100644
index 000000000000..6cbb81ccc02e
--- /dev/null
+++ b/drivers/net/ethernet/cirrus/Kconfig
@@ -0,0 +1,50 @@
+#
+# Cirrus network device configuration
+#
+
+config NET_VENDOR_CIRRUS
+ bool "Cirrus devices"
+ default y
+ depends on ISA || EISA || MACH_IXDP2351 || ARCH_IXDP2X01 \
+ || MACH_MX31ADS || MACH_QQ2440 || (ARM && ARCH_EP93XX)
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Cirrus cards. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_CIRRUS
+
+config CS89x0
+ tristate "CS89x0 support"
+ depends on (ISA || EISA || MACH_IXDP2351 \
+ || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440)
+ ---help---
+ Support for CS89x0 chipset based Ethernet cards. If you have a
+ network (Ethernet) card of this type, say Y and read the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto> as well as
+ <file:Documentation/networking/cs89x0.txt>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called cs89x0.
+
+config CS89x0_NONISA_IRQ
+ def_bool y
+ depends on CS89x0 != n
+ depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440
+
+config EP93XX_ETH
+ tristate "EP93xx Ethernet support"
+ depends on ARM && ARCH_EP93XX
+ select NET_CORE
+ select MII
+ help
+ This is a driver for the ethernet hardware included in EP93xx CPUs.
+ Say Y if you are building a kernel for EP93xx based devices.
+
+endif # NET_VENDOR_CIRRUS
diff --git a/drivers/net/ethernet/cirrus/Makefile b/drivers/net/ethernet/cirrus/Makefile
new file mode 100644
index 000000000000..14bd77e0cb57
--- /dev/null
+++ b/drivers/net/ethernet/cirrus/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Cirrus network device drivers.
+#
+
+obj-$(CONFIG_CS89x0) += cs89x0.o
+obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o
diff --git a/drivers/net/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index 537a4b2e2020..f328da24c8fa 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -488,7 +488,7 @@ static const struct net_device_ops net_ops = {
.ndo_tx_timeout = net_timeout,
.ndo_start_xmit = net_send_packet,
.ndo_get_stats = net_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_set_mac_address = set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = net_poll_controller,
diff --git a/drivers/net/cs89x0.h b/drivers/net/ethernet/cirrus/cs89x0.h
index 91423b70bb45..91423b70bb45 100644
--- a/drivers/net/cs89x0.h
+++ b/drivers/net/ethernet/cirrus/cs89x0.h
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c
index 4317af8d2f0a..4317af8d2f0a 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c
diff --git a/drivers/net/ethernet/cisco/Kconfig b/drivers/net/ethernet/cisco/Kconfig
new file mode 100644
index 000000000000..94606f7ee13a
--- /dev/null
+++ b/drivers/net/ethernet/cisco/Kconfig
@@ -0,0 +1,23 @@
+#
+# Cisco device configuration
+#
+
+config NET_VENDOR_CISCO
+ bool "Cisco devices"
+ default y
+ depends on PCI && INET
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Cisco cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_CISCO
+
+source "drivers/net/ethernet/cisco/enic/Kconfig"
+
+endif # NET_VENDOR_CISCO
diff --git a/drivers/net/ethernet/cisco/Makefile b/drivers/net/ethernet/cisco/Makefile
new file mode 100644
index 000000000000..6c7437bc4a92
--- /dev/null
+++ b/drivers/net/ethernet/cisco/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Cisco device drivers.
+#
+
+obj-$(CONFIG_ENIC) += enic/
diff --git a/drivers/net/ethernet/cisco/enic/Kconfig b/drivers/net/ethernet/cisco/enic/Kconfig
new file mode 100644
index 000000000000..9cc706a6cffd
--- /dev/null
+++ b/drivers/net/ethernet/cisco/enic/Kconfig
@@ -0,0 +1,9 @@
+#
+# Cisco device configuration
+#
+
+config ENIC
+ tristate "Cisco VIC Ethernet NIC Support"
+ depends on PCI && INET
+ ---help---
+ This enables the support for the Cisco VIC Ethernet card.
diff --git a/drivers/net/enic/Makefile b/drivers/net/ethernet/cisco/enic/Makefile
index 9d4974bba247..9d4974bba247 100644
--- a/drivers/net/enic/Makefile
+++ b/drivers/net/ethernet/cisco/enic/Makefile
diff --git a/drivers/net/enic/cq_desc.h b/drivers/net/ethernet/cisco/enic/cq_desc.h
index d6dd1b4edf6e..d6dd1b4edf6e 100644
--- a/drivers/net/enic/cq_desc.h
+++ b/drivers/net/ethernet/cisco/enic/cq_desc.h
diff --git a/drivers/net/enic/cq_enet_desc.h b/drivers/net/ethernet/cisco/enic/cq_enet_desc.h
index c2c0680a1146..c2c0680a1146 100644
--- a/drivers/net/enic/cq_enet_desc.h
+++ b/drivers/net/ethernet/cisco/enic/cq_enet_desc.h
diff --git a/drivers/net/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index ce76d9a8ca6e..fe0c29acdbe6 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -32,7 +32,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION "2.1.1.24"
+#define DRV_VERSION "2.1.1.28"
#define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
@@ -49,6 +49,10 @@ struct enic_msix_entry {
void *devid;
};
+/* priv_flags */
+#define ENIC_SRIOV_ENABLED (1 << 0)
+
+/* enic port profile set flags */
#define ENIC_PORT_REQUEST_APPLIED (1 << 0)
#define ENIC_SET_REQUEST (1 << 1)
#define ENIC_SET_NAME (1 << 2)
@@ -83,12 +87,16 @@ struct enic {
u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN];
u8 uc_addr[ENIC_UNICAST_PERFECT_FILTERS][ETH_ALEN];
unsigned int flags;
+ unsigned int priv_flags;
unsigned int mc_count;
unsigned int uc_count;
u32 port_mtu;
u32 rx_coalesce_usecs;
u32 tx_coalesce_usecs;
- struct enic_port_profile pp;
+#ifdef CONFIG_PCI_IOV
+ u32 num_vfs;
+#endif
+ struct enic_port_profile *pp;
/* work queue cache line section */
____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX];
@@ -120,5 +128,8 @@ static inline struct device *enic_get_dev(struct enic *enic)
}
void enic_reset_addr_lists(struct enic *enic);
+int enic_sriov_enabled(struct enic *enic);
+int enic_is_valid_vf(struct enic *enic, int vf);
+int enic_is_dynamic(struct enic *enic);
#endif /* _ENIC_H_ */
diff --git a/drivers/net/enic/enic_dev.c b/drivers/net/ethernet/cisco/enic/enic_dev.c
index fd6247b3c0ee..fd6247b3c0ee 100644
--- a/drivers/net/enic/enic_dev.c
+++ b/drivers/net/ethernet/cisco/enic/enic_dev.c
diff --git a/drivers/net/enic/enic_dev.h b/drivers/net/ethernet/cisco/enic/enic_dev.h
index ff8e87fdfc1d..1f83a4747ba0 100644
--- a/drivers/net/enic/enic_dev.h
+++ b/drivers/net/ethernet/cisco/enic/enic_dev.h
@@ -19,6 +19,25 @@
#ifndef _ENIC_DEV_H_
#define _ENIC_DEV_H_
+#include "vnic_dev.h"
+
+/*
+ * Calls the devcmd function given by argument vnicdevcmdfn.
+ * If vf argument is valid, it proxies the devcmd
+ */
+#define ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnicdevcmdfn, ...) \
+ do { \
+ spin_lock(&enic->devcmd_lock); \
+ if (enic_is_valid_vf(enic, vf)) { \
+ vnic_dev_cmd_proxy_by_index_start(enic->vdev, vf); \
+ err = vnicdevcmdfn(enic->vdev, ##__VA_ARGS__); \
+ vnic_dev_cmd_proxy_end(enic->vdev); \
+ } else { \
+ err = vnicdevcmdfn(enic->vdev, ##__VA_ARGS__); \
+ } \
+ spin_unlock(&enic->devcmd_lock); \
+ } while (0)
+
int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info);
int enic_dev_stats_dump(struct enic *enic, struct vnic_stats **vstats);
int enic_dev_add_station_addr(struct enic *enic);
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 67a27cd304dd..c3786fda11db 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -28,6 +28,7 @@
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/ethtool.h>
@@ -121,11 +122,25 @@ static const struct enic_stat enic_rx_stats[] = {
static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats);
static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats);
-static int enic_is_dynamic(struct enic *enic)
+int enic_is_dynamic(struct enic *enic)
{
return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN;
}
+int enic_sriov_enabled(struct enic *enic)
+{
+ return (enic->priv_flags & ENIC_SRIOV_ENABLED) ? 1 : 0;
+}
+
+int enic_is_valid_vf(struct enic *enic, int vf)
+{
+#ifdef CONFIG_PCI_IOV
+ return vf >= 0 && vf < enic->num_vfs;
+#else
+ return 0;
+#endif
+}
+
static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq)
{
return rq;
@@ -584,16 +599,16 @@ static inline void enic_queue_wq_skb_cont(struct enic *enic,
struct vnic_wq *wq, struct sk_buff *skb,
unsigned int len_left, int loopback)
{
- skb_frag_t *frag;
+ const skb_frag_t *frag;
/* Queue additional data fragments */
for (frag = skb_shinfo(skb)->frags; len_left; frag++) {
- len_left -= frag->size;
+ len_left -= skb_frag_size(frag);
enic_queue_wq_desc_cont(wq, skb,
- pci_map_page(enic->pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE),
- frag->size,
+ skb_frag_dma_map(&enic->pdev->dev,
+ frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE),
+ skb_frag_size(frag),
(len_left == 0), /* EOP? */
loopback);
}
@@ -702,16 +717,16 @@ static inline void enic_queue_wq_skb_tso(struct enic *enic,
* for additional data fragments
*/
for (frag = skb_shinfo(skb)->frags; len_left; frag++) {
- len_left -= frag->size;
- frag_len_left = frag->size;
- offset = frag->page_offset;
+ len_left -= skb_frag_size(frag);
+ frag_len_left = skb_frag_size(frag);
+ offset = 0;
while (frag_len_left) {
len = min(frag_len_left,
(unsigned int)WQ_ENET_MAX_DESC_LEN);
- dma_addr = pci_map_page(enic->pdev, frag->page,
- offset, len,
- PCI_DMA_TODEVICE);
+ dma_addr = skb_frag_dma_map(&enic->pdev->dev, frag,
+ offset, len,
+ DMA_TO_DEVICE);
enic_queue_wq_desc_cont(wq, skb,
dma_addr,
len,
@@ -1039,15 +1054,15 @@ static void enic_tx_timeout(struct net_device *netdev)
static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
{
struct enic *enic = netdev_priv(netdev);
+ struct enic_port_profile *pp;
+ int err;
- if (vf != PORT_SELF_VF)
- return -EOPNOTSUPP;
+ ENIC_PP_BY_INDEX(enic, vf, pp, &err);
+ if (err)
+ return err;
- /* Ignore the vf argument for now. We can assume the request
- * is coming on a vf.
- */
if (is_valid_ether_addr(mac)) {
- memcpy(enic->pp.vf_mac, mac, ETH_ALEN);
+ memcpy(pp->vf_mac, mac, ETH_ALEN);
return 0;
} else
return -EINVAL;
@@ -1058,71 +1073,74 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
{
struct enic *enic = netdev_priv(netdev);
struct enic_port_profile prev_pp;
+ struct enic_port_profile *pp;
int err = 0, restore_pp = 1;
- /* don't support VFs, yet */
- if (vf != PORT_SELF_VF)
- return -EOPNOTSUPP;
+ ENIC_PP_BY_INDEX(enic, vf, pp, &err);
+ if (err)
+ return err;
if (!port[IFLA_PORT_REQUEST])
return -EOPNOTSUPP;
- memcpy(&prev_pp, &enic->pp, sizeof(enic->pp));
- memset(&enic->pp, 0, sizeof(enic->pp));
+ memcpy(&prev_pp, pp, sizeof(*enic->pp));
+ memset(pp, 0, sizeof(*enic->pp));
- enic->pp.set |= ENIC_SET_REQUEST;
- enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
+ pp->set |= ENIC_SET_REQUEST;
+ pp->request = nla_get_u8(port[IFLA_PORT_REQUEST]);
if (port[IFLA_PORT_PROFILE]) {
- enic->pp.set |= ENIC_SET_NAME;
- memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]),
+ pp->set |= ENIC_SET_NAME;
+ memcpy(pp->name, nla_data(port[IFLA_PORT_PROFILE]),
PORT_PROFILE_MAX);
}
if (port[IFLA_PORT_INSTANCE_UUID]) {
- enic->pp.set |= ENIC_SET_INSTANCE;
- memcpy(enic->pp.instance_uuid,
+ pp->set |= ENIC_SET_INSTANCE;
+ memcpy(pp->instance_uuid,
nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
}
if (port[IFLA_PORT_HOST_UUID]) {
- enic->pp.set |= ENIC_SET_HOST;
- memcpy(enic->pp.host_uuid,
+ pp->set |= ENIC_SET_HOST;
+ memcpy(pp->host_uuid,
nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
}
/* Special case handling: mac came from IFLA_VF_MAC */
if (!is_zero_ether_addr(prev_pp.vf_mac))
- memcpy(enic->pp.mac_addr, prev_pp.vf_mac, ETH_ALEN);
+ memcpy(pp->mac_addr, prev_pp.vf_mac, ETH_ALEN);
- if (is_zero_ether_addr(netdev->dev_addr))
- random_ether_addr(netdev->dev_addr);
+ if (vf == PORT_SELF_VF && is_zero_ether_addr(netdev->dev_addr))
+ random_ether_addr(netdev->dev_addr);
- err = enic_process_set_pp_request(enic, &prev_pp, &restore_pp);
+ err = enic_process_set_pp_request(enic, vf, &prev_pp, &restore_pp);
if (err) {
if (restore_pp) {
/* Things are still the way they were: Implicit
* DISASSOCIATE failed
*/
- memcpy(&enic->pp, &prev_pp, sizeof(enic->pp));
+ memcpy(pp, &prev_pp, sizeof(*pp));
} else {
- memset(&enic->pp, 0, sizeof(enic->pp));
- memset(netdev->dev_addr, 0, ETH_ALEN);
+ memset(pp, 0, sizeof(*pp));
+ if (vf == PORT_SELF_VF)
+ memset(netdev->dev_addr, 0, ETH_ALEN);
}
} else {
/* Set flag to indicate that the port assoc/disassoc
* request has been sent out to fw
*/
- enic->pp.set |= ENIC_PORT_REQUEST_APPLIED;
+ pp->set |= ENIC_PORT_REQUEST_APPLIED;
/* If DISASSOCIATE, clean up all assigned/saved macaddresses */
- if (enic->pp.request == PORT_REQUEST_DISASSOCIATE) {
- memset(enic->pp.mac_addr, 0, ETH_ALEN);
- memset(netdev->dev_addr, 0, ETH_ALEN);
+ if (pp->request == PORT_REQUEST_DISASSOCIATE) {
+ memset(pp->mac_addr, 0, ETH_ALEN);
+ if (vf == PORT_SELF_VF)
+ memset(netdev->dev_addr, 0, ETH_ALEN);
}
}
- memset(enic->pp.vf_mac, 0, ETH_ALEN);
+ memset(pp->vf_mac, 0, ETH_ALEN);
return err;
}
@@ -1132,26 +1150,31 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
{
struct enic *enic = netdev_priv(netdev);
u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
+ struct enic_port_profile *pp;
int err;
- if (!(enic->pp.set & ENIC_PORT_REQUEST_APPLIED))
+ ENIC_PP_BY_INDEX(enic, vf, pp, &err);
+ if (err)
+ return err;
+
+ if (!(pp->set & ENIC_PORT_REQUEST_APPLIED))
return -ENODATA;
- err = enic_process_get_pp_request(enic, enic->pp.request, &response);
+ err = enic_process_get_pp_request(enic, vf, pp->request, &response);
if (err)
return err;
- NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request);
+ NLA_PUT_U16(skb, IFLA_PORT_REQUEST, pp->request);
NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response);
- if (enic->pp.set & ENIC_SET_NAME)
+ if (pp->set & ENIC_SET_NAME)
NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
- enic->pp.name);
- if (enic->pp.set & ENIC_SET_INSTANCE)
+ pp->name);
+ if (pp->set & ENIC_SET_INSTANCE)
NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
- enic->pp.instance_uuid);
- if (enic->pp.set & ENIC_SET_HOST)
+ pp->instance_uuid);
+ if (pp->set & ENIC_SET_HOST)
NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
- enic->pp.host_uuid);
+ pp->host_uuid);
return 0;
@@ -1585,10 +1608,9 @@ static int enic_open(struct net_device *netdev)
for (i = 0; i < enic->rq_count; i++)
vnic_rq_enable(&enic->rq[i]);
- if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr))
- enic_dev_add_addr(enic, enic->pp.mac_addr);
- else
+ if (!enic_is_dynamic(enic))
enic_dev_add_station_addr(enic);
+
enic_set_rx_mode(netdev);
netif_wake_queue(netdev);
@@ -1636,9 +1658,8 @@ static int enic_stop(struct net_device *netdev)
netif_carrier_off(netdev);
netif_tx_disable(netdev);
- if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr))
- enic_dev_del_addr(enic, enic->pp.mac_addr);
- else
+
+ if (!enic_is_dynamic(enic))
enic_dev_del_station_addr(enic);
for (i = 0; i < enic->wq_count; i++) {
@@ -2103,7 +2124,6 @@ static const struct net_device_ops enic_netdev_dynamic_ops = {
.ndo_get_stats64 = enic_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = enic_set_rx_mode,
- .ndo_set_multicast_list = enic_set_rx_mode,
.ndo_set_mac_address = enic_set_mac_address_dynamic,
.ndo_change_mtu = enic_change_mtu,
.ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid,
@@ -2125,11 +2145,13 @@ static const struct net_device_ops enic_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = enic_set_mac_address,
.ndo_set_rx_mode = enic_set_rx_mode,
- .ndo_set_multicast_list = enic_set_rx_mode,
.ndo_change_mtu = enic_change_mtu,
.ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = enic_vlan_rx_kill_vid,
.ndo_tx_timeout = enic_tx_timeout,
+ .ndo_set_vf_port = enic_set_vf_port,
+ .ndo_get_vf_port = enic_get_vf_port,
+ .ndo_set_vf_mac = enic_set_vf_mac,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = enic_poll_controller,
#endif
@@ -2241,6 +2263,10 @@ static int __devinit enic_probe(struct pci_dev *pdev,
int using_dac = 0;
unsigned int i;
int err;
+ int num_pps = 1;
+#ifdef CONFIG_PCI_IOV
+ int pos = 0;
+#endif
/* Allocate net device structure and initialize. Private
* instance data is initialized to zero.
@@ -2332,13 +2358,41 @@ static int __devinit enic_probe(struct pci_dev *pdev,
goto err_out_iounmap;
}
+#ifdef CONFIG_PCI_IOV
+ /* Get number of subvnics */
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+ if (pos) {
+ pci_read_config_word(pdev, pos + PCI_SRIOV_TOTAL_VF,
+ (u16 *)&enic->num_vfs);
+ if (enic->num_vfs) {
+ err = pci_enable_sriov(pdev, enic->num_vfs);
+ if (err) {
+ dev_err(dev, "SRIOV enable failed, aborting."
+ " pci_enable_sriov() returned %d\n",
+ err);
+ goto err_out_vnic_unregister;
+ }
+ enic->priv_flags |= ENIC_SRIOV_ENABLED;
+ num_pps = enic->num_vfs;
+ }
+ }
+
+#endif
+ /* Allocate structure for port profiles */
+ enic->pp = kzalloc(num_pps * sizeof(*enic->pp), GFP_KERNEL);
+ if (!enic->pp) {
+ pr_err("port profile alloc failed, aborting\n");
+ err = -ENOMEM;
+ goto err_out_disable_sriov;
+ }
+
/* Issue device open to get device in known state
*/
err = enic_dev_open(enic);
if (err) {
dev_err(dev, "vNIC dev open failed, aborting\n");
- goto err_out_vnic_unregister;
+ goto err_out_free_pp;
}
/* Setup devcmd lock
@@ -2405,6 +2459,12 @@ static int __devinit enic_probe(struct pci_dev *pdev,
enic->port_mtu = enic->config.mtu;
(void)enic_change_mtu(netdev, enic->port_mtu);
+#ifdef CONFIG_PCI_IOV
+ if (enic_is_dynamic(enic) && pdev->is_virtfn &&
+ is_zero_ether_addr(enic->mac_addr))
+ random_ether_addr(enic->mac_addr);
+#endif
+
err = enic_set_mac_addr(netdev, enic->mac_addr);
if (err) {
dev_err(dev, "Invalid MAC address, aborting\n");
@@ -2442,6 +2502,8 @@ static int __devinit enic_probe(struct pci_dev *pdev,
if (using_dac)
netdev->features |= NETIF_F_HIGHDMA;
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
err = register_netdev(netdev);
if (err) {
dev_err(dev, "Cannot register net device, aborting\n");
@@ -2454,8 +2516,17 @@ err_out_dev_deinit:
enic_dev_deinit(enic);
err_out_dev_close:
vnic_dev_close(enic->vdev);
+err_out_free_pp:
+ kfree(enic->pp);
+err_out_disable_sriov:
+#ifdef CONFIG_PCI_IOV
+ if (enic_sriov_enabled(enic)) {
+ pci_disable_sriov(pdev);
+ enic->priv_flags &= ~ENIC_SRIOV_ENABLED;
+ }
err_out_vnic_unregister:
vnic_dev_unregister(enic->vdev);
+#endif
err_out_iounmap:
enic_iounmap(enic);
err_out_release_regions:
@@ -2481,6 +2552,13 @@ static void __devexit enic_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
enic_dev_deinit(enic);
vnic_dev_close(enic->vdev);
+#ifdef CONFIG_PCI_IOV
+ if (enic_sriov_enabled(enic)) {
+ pci_disable_sriov(pdev);
+ enic->priv_flags &= ~ENIC_SRIOV_ENABLED;
+ }
+#endif
+ kfree(enic->pp);
vnic_dev_unregister(enic->vdev);
enic_iounmap(enic);
pci_release_regions(pdev);
diff --git a/drivers/net/enic/enic_pp.c b/drivers/net/ethernet/cisco/enic/enic_pp.c
index ffaa75dd1ded..22bf03a1829e 100644
--- a/drivers/net/enic/enic_pp.c
+++ b/drivers/net/ethernet/cisco/enic/enic_pp.c
@@ -29,10 +29,47 @@
#include "enic_res.h"
#include "enic.h"
#include "enic_dev.h"
+#include "enic_pp.h"
-static int enic_set_port_profile(struct enic *enic)
+/*
+ * Checks validity of vf index that came in
+ * port profile request
+ */
+int enic_is_valid_pp_vf(struct enic *enic, int vf, int *err)
+{
+ if (vf != PORT_SELF_VF) {
+#ifdef CONFIG_PCI_IOV
+ if (enic_sriov_enabled(enic)) {
+ if (vf < 0 || vf >= enic->num_vfs) {
+ *err = -EINVAL;
+ goto err_out;
+ }
+ } else {
+ *err = -EOPNOTSUPP;
+ goto err_out;
+ }
+#else
+ *err = -EOPNOTSUPP;
+ goto err_out;
+#endif
+ }
+
+ if (vf == PORT_SELF_VF && !enic_is_dynamic(enic)) {
+ *err = -EOPNOTSUPP;
+ goto err_out;
+ }
+
+ *err = 0;
+ return 1;
+
+err_out:
+ return 0;
+}
+
+static int enic_set_port_profile(struct enic *enic, int vf)
{
struct net_device *netdev = enic->netdev;
+ struct enic_port_profile *pp;
struct vic_provinfo *vp;
const u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
const u16 os_type = htons(VIC_GENERIC_PROV_OS_TYPE_LINUX);
@@ -41,7 +78,11 @@ static int enic_set_port_profile(struct enic *enic)
u8 *client_mac;
int err;
- if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name))
+ ENIC_PP_BY_INDEX(enic, vf, pp, &err);
+ if (err)
+ return err;
+
+ if (!(pp->set & ENIC_SET_NAME) || !strlen(pp->name))
return -EINVAL;
vp = vic_provinfo_alloc(GFP_KERNEL, oui,
@@ -51,12 +92,18 @@ static int enic_set_port_profile(struct enic *enic)
VIC_PROVINFO_ADD_TLV(vp,
VIC_GENERIC_PROV_TLV_PORT_PROFILE_NAME_STR,
- strlen(enic->pp.name) + 1, enic->pp.name);
+ strlen(pp->name) + 1, pp->name);
- if (!is_zero_ether_addr(enic->pp.mac_addr))
- client_mac = enic->pp.mac_addr;
- else
+ if (!is_zero_ether_addr(pp->mac_addr)) {
+ client_mac = pp->mac_addr;
+ } else if (vf == PORT_SELF_VF) {
client_mac = netdev->dev_addr;
+ } else {
+ netdev_err(netdev, "Cannot find pp mac address "
+ "for VF %d\n", vf);
+ err = -EINVAL;
+ goto add_tlv_failure;
+ }
VIC_PROVINFO_ADD_TLV(vp,
VIC_GENERIC_PROV_TLV_CLIENT_MAC_ADDR,
@@ -67,15 +114,15 @@ static int enic_set_port_profile(struct enic *enic)
VIC_GENERIC_PROV_TLV_CLUSTER_PORT_UUID_STR,
sizeof(client_mac_str), client_mac_str);
- if (enic->pp.set & ENIC_SET_INSTANCE) {
- sprintf(uuid_str, "%pUB", enic->pp.instance_uuid);
+ if (pp->set & ENIC_SET_INSTANCE) {
+ sprintf(uuid_str, "%pUB", pp->instance_uuid);
VIC_PROVINFO_ADD_TLV(vp,
VIC_GENERIC_PROV_TLV_CLIENT_UUID_STR,
sizeof(uuid_str), uuid_str);
}
- if (enic->pp.set & ENIC_SET_HOST) {
- sprintf(uuid_str, "%pUB", enic->pp.host_uuid);
+ if (pp->set & ENIC_SET_HOST) {
+ sprintf(uuid_str, "%pUB", pp->host_uuid);
VIC_PROVINFO_ADD_TLV(vp,
VIC_GENERIC_PROV_TLV_HOST_UUID_STR,
sizeof(uuid_str), uuid_str);
@@ -85,7 +132,9 @@ static int enic_set_port_profile(struct enic *enic)
VIC_GENERIC_PROV_TLV_OS_TYPE,
sizeof(os_type), &os_type);
- err = enic_dev_status_to_errno(enic_dev_init_prov2(enic, vp));
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_init_prov2, (u8 *)vp,
+ vic_provinfo_size(vp));
+ err = enic_dev_status_to_errno(err);
add_tlv_failure:
vic_provinfo_free(vp);
@@ -93,15 +142,16 @@ add_tlv_failure:
return err;
}
-static int enic_unset_port_profile(struct enic *enic)
+static int enic_unset_port_profile(struct enic *enic, int vf)
{
int err;
- err = enic_vnic_dev_deinit(enic);
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_deinit);
if (err)
return enic_dev_status_to_errno(err);
- enic_reset_addr_lists(enic);
+ if (vf == PORT_SELF_VF)
+ enic_reset_addr_lists(enic);
return 0;
}
@@ -115,17 +165,18 @@ static int enic_are_pp_different(struct enic_port_profile *pp1,
!!memcmp(pp1->mac_addr, pp2->mac_addr, ETH_ALEN);
}
-static int enic_pp_preassociate(struct enic *enic,
+static int enic_pp_preassociate(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp);
-static int enic_pp_disassociate(struct enic *enic,
+static int enic_pp_disassociate(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp);
-static int enic_pp_preassociate_rr(struct enic *enic,
+static int enic_pp_preassociate_rr(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp);
-static int enic_pp_associate(struct enic *enic,
+static int enic_pp_associate(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp);
-static int (*enic_pp_handlers[])(struct enic *enic,
- struct enic_port_profile *prev_state, int *restore_pp) = {
+static int (*enic_pp_handlers[])(struct enic *enic, int vf,
+ struct enic_port_profile *prev_state,
+ int *restore_pp) = {
[PORT_REQUEST_PREASSOCIATE] = enic_pp_preassociate,
[PORT_REQUEST_PREASSOCIATE_RR] = enic_pp_preassociate_rr,
[PORT_REQUEST_ASSOCIATE] = enic_pp_associate,
@@ -135,28 +186,49 @@ static int (*enic_pp_handlers[])(struct enic *enic,
static const int enic_pp_handlers_count =
sizeof(enic_pp_handlers)/sizeof(*enic_pp_handlers);
-static int enic_pp_preassociate(struct enic *enic,
+static int enic_pp_preassociate(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp)
{
return -EOPNOTSUPP;
}
-static int enic_pp_disassociate(struct enic *enic,
+static int enic_pp_disassociate(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp)
{
- return enic_unset_port_profile(enic);
+ struct net_device *netdev = enic->netdev;
+ struct enic_port_profile *pp;
+ int err;
+
+ ENIC_PP_BY_INDEX(enic, vf, pp, &err);
+ if (err)
+ return err;
+
+ /* Deregister mac addresses */
+ if (!is_zero_ether_addr(pp->mac_addr))
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_del_addr,
+ pp->mac_addr);
+ else if (!is_zero_ether_addr(netdev->dev_addr))
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_del_addr,
+ netdev->dev_addr);
+
+ return enic_unset_port_profile(enic, vf);
}
-static int enic_pp_preassociate_rr(struct enic *enic,
+static int enic_pp_preassociate_rr(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp)
{
+ struct enic_port_profile *pp;
int err;
int active = 0;
- if (enic->pp.request != PORT_REQUEST_ASSOCIATE) {
+ ENIC_PP_BY_INDEX(enic, vf, pp, &err);
+ if (err)
+ return err;
+
+ if (pp->request != PORT_REQUEST_ASSOCIATE) {
/* If pre-associate is not part of an associate.
We always disassociate first */
- err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE](enic,
+ err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE](enic, vf,
prev_pp, restore_pp);
if (err)
return err;
@@ -166,29 +238,39 @@ static int enic_pp_preassociate_rr(struct enic *enic,
*restore_pp = 0;
- err = enic_set_port_profile(enic);
+ err = enic_set_port_profile(enic, vf);
if (err)
return err;
/* If pre-associate is not part of an associate. */
- if (enic->pp.request != PORT_REQUEST_ASSOCIATE)
- err = enic_dev_status_to_errno(enic_dev_enable2(enic, active));
+ if (pp->request != PORT_REQUEST_ASSOCIATE) {
+ /* Enable device as standby */
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_enable2,
+ active);
+ err = enic_dev_status_to_errno(err);
+ }
return err;
}
-static int enic_pp_associate(struct enic *enic,
+static int enic_pp_associate(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp)
{
+ struct net_device *netdev = enic->netdev;
+ struct enic_port_profile *pp;
int err;
int active = 1;
+ ENIC_PP_BY_INDEX(enic, vf, pp, &err);
+ if (err)
+ return err;
+
/* Check if a pre-associate was called before */
if (prev_pp->request != PORT_REQUEST_PREASSOCIATE_RR ||
(prev_pp->request == PORT_REQUEST_PREASSOCIATE_RR &&
- enic_are_pp_different(prev_pp, &enic->pp))) {
+ enic_are_pp_different(prev_pp, pp))) {
err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE](
- enic, prev_pp, restore_pp);
+ enic, vf, prev_pp, restore_pp);
if (err)
return err;
@@ -196,28 +278,48 @@ static int enic_pp_associate(struct enic *enic,
}
err = enic_pp_handlers[PORT_REQUEST_PREASSOCIATE_RR](
- enic, prev_pp, restore_pp);
+ enic, vf, prev_pp, restore_pp);
if (err)
return err;
*restore_pp = 0;
- return enic_dev_status_to_errno(enic_dev_enable2(enic, active));
+ /* Enable device as active */
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_enable2, active);
+ err = enic_dev_status_to_errno(err);
+ if (err)
+ return err;
+
+ /* Register mac address */
+ if (!is_zero_ether_addr(pp->mac_addr))
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_add_addr,
+ pp->mac_addr);
+ else if (!is_zero_ether_addr(netdev->dev_addr))
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_add_addr,
+ netdev->dev_addr);
+
+ return 0;
}
-int enic_process_set_pp_request(struct enic *enic,
+int enic_process_set_pp_request(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp)
{
- if (enic->pp.request < enic_pp_handlers_count
- && enic_pp_handlers[enic->pp.request])
- return enic_pp_handlers[enic->pp.request](enic,
- prev_pp, restore_pp);
- else
+ struct enic_port_profile *pp;
+ int err;
+
+ ENIC_PP_BY_INDEX(enic, vf, pp, &err);
+ if (err)
+ return err;
+
+ if (pp->request >= enic_pp_handlers_count
+ || !enic_pp_handlers[pp->request])
return -EOPNOTSUPP;
+
+ return enic_pp_handlers[pp->request](enic, vf, prev_pp, restore_pp);
}
-int enic_process_get_pp_request(struct enic *enic, int request,
- u16 *response)
+int enic_process_get_pp_request(struct enic *enic, int vf,
+ int request, u16 *response)
{
int err, status = ERR_SUCCESS;
@@ -225,11 +327,13 @@ int enic_process_get_pp_request(struct enic *enic, int request,
case PORT_REQUEST_PREASSOCIATE_RR:
case PORT_REQUEST_ASSOCIATE:
- err = enic_dev_enable2_done(enic, &status);
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic,
+ vnic_dev_enable2_done, &status);
break;
case PORT_REQUEST_DISASSOCIATE:
- err = enic_dev_deinit_done(enic, &status);
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic,
+ vnic_dev_deinit_done, &status);
break;
default:
diff --git a/drivers/net/enic/enic_pp.h b/drivers/net/ethernet/cisco/enic/enic_pp.h
index 699e365a944d..a09ff392c1c6 100644
--- a/drivers/net/enic/enic_pp.h
+++ b/drivers/net/ethernet/cisco/enic/enic_pp.h
@@ -19,9 +19,18 @@
#ifndef _ENIC_PP_H_
#define _ENIC_PP_H_
-int enic_process_set_pp_request(struct enic *enic,
+#define ENIC_PP_BY_INDEX(enic, vf, pp, err) \
+ do { \
+ if (enic_is_valid_pp_vf(enic, vf, err)) \
+ pp = (vf == PORT_SELF_VF) ? enic->pp : enic->pp + vf; \
+ else \
+ pp = NULL; \
+ } while (0)
+
+int enic_process_set_pp_request(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp);
-int enic_process_get_pp_request(struct enic *enic, int request,
- u16 *response);
+int enic_process_get_pp_request(struct enic *enic, int vf,
+ int request, u16 *response);
+int enic_is_valid_pp_vf(struct enic *enic, int vf, int *err);
#endif /* _ENIC_PP_H_ */
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/ethernet/cisco/enic/enic_res.c
index 4a35367de790..4a35367de790 100644
--- a/drivers/net/enic/enic_res.c
+++ b/drivers/net/ethernet/cisco/enic/enic_res.c
diff --git a/drivers/net/enic/enic_res.h b/drivers/net/ethernet/cisco/enic/enic_res.h
index 25be2734c3fe..25be2734c3fe 100644
--- a/drivers/net/enic/enic_res.h
+++ b/drivers/net/ethernet/cisco/enic/enic_res.h
diff --git a/drivers/net/enic/rq_enet_desc.h b/drivers/net/ethernet/cisco/enic/rq_enet_desc.h
index e6dd30988d6f..e6dd30988d6f 100644
--- a/drivers/net/enic/rq_enet_desc.h
+++ b/drivers/net/ethernet/cisco/enic/rq_enet_desc.h
diff --git a/drivers/net/enic/vnic_cq.c b/drivers/net/ethernet/cisco/enic/vnic_cq.c
index 0daa1c7073cb..0daa1c7073cb 100644
--- a/drivers/net/enic/vnic_cq.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_cq.c
diff --git a/drivers/net/enic/vnic_cq.h b/drivers/net/ethernet/cisco/enic/vnic_cq.h
index 579315cbe803..579315cbe803 100644
--- a/drivers/net/enic/vnic_cq.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_cq.h
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c
index 8c4c8cf486f6..31e7f9bc2067 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c
@@ -32,6 +32,7 @@
enum vnic_proxy_type {
PROXY_NONE,
PROXY_BY_BDF,
+ PROXY_BY_INDEX,
};
struct vnic_res {
@@ -328,20 +329,21 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
return -ETIMEDOUT;
}
-static int vnic_dev_cmd_proxy_by_bdf(struct vnic_dev *vdev,
- enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait)
+static int vnic_dev_cmd_proxy(struct vnic_dev *vdev,
+ enum vnic_devcmd_cmd proxy_cmd, enum vnic_devcmd_cmd cmd,
+ u64 *a0, u64 *a1, int wait)
{
u32 status;
int err;
memset(vdev->args, 0, sizeof(vdev->args));
- vdev->args[0] = vdev->proxy_index; /* bdf */
+ vdev->args[0] = vdev->proxy_index;
vdev->args[1] = cmd;
vdev->args[2] = *a0;
vdev->args[3] = *a1;
- err = _vnic_dev_cmd(vdev, CMD_PROXY_BY_BDF, wait);
+ err = _vnic_dev_cmd(vdev, proxy_cmd, wait);
if (err)
return err;
@@ -376,14 +378,30 @@ static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev,
return err;
}
+void vnic_dev_cmd_proxy_by_index_start(struct vnic_dev *vdev, u16 index)
+{
+ vdev->proxy = PROXY_BY_INDEX;
+ vdev->proxy_index = index;
+}
+
+void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev)
+{
+ vdev->proxy = PROXY_NONE;
+ vdev->proxy_index = 0;
+}
+
int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
u64 *a0, u64 *a1, int wait)
{
memset(vdev->args, 0, sizeof(vdev->args));
switch (vdev->proxy) {
+ case PROXY_BY_INDEX:
+ return vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_INDEX, cmd,
+ a0, a1, wait);
case PROXY_BY_BDF:
- return vnic_dev_cmd_proxy_by_bdf(vdev, cmd, a0, a1, wait);
+ return vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_BDF, cmd,
+ a0, a1, wait);
case PROXY_NONE:
default:
return vnic_dev_cmd_no_proxy(vdev, cmd, a0, a1, wait);
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/ethernet/cisco/enic/vnic_dev.h
index 852b698fbe7d..6a138b625d13 100644
--- a/drivers/net/enic/vnic_dev.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.h
@@ -85,6 +85,8 @@ void vnic_dev_free_desc_ring(struct vnic_dev *vdev,
struct vnic_dev_ring *ring);
int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
u64 *a0, u64 *a1, int wait);
+void vnic_dev_cmd_proxy_by_index_start(struct vnic_dev *vdev, u16 index);
+void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev);
int vnic_dev_fw_info(struct vnic_dev *vdev,
struct vnic_devcmd_fw_info **fw_info);
int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
index 8025e8808d61..8025e8808d61 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/ethernet/cisco/enic/vnic_enet.h
index 609542848e02..609542848e02 100644
--- a/drivers/net/enic/vnic_enet.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_enet.h
diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/ethernet/cisco/enic/vnic_intr.c
index 0ca107f7bc8c..0ca107f7bc8c 100644
--- a/drivers/net/enic/vnic_intr.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_intr.c
diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/ethernet/cisco/enic/vnic_intr.h
index 2b1636392294..2b1636392294 100644
--- a/drivers/net/enic/vnic_intr.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_intr.h
diff --git a/drivers/net/enic/vnic_nic.h b/drivers/net/ethernet/cisco/enic/vnic_nic.h
index 995a50dd4c99..995a50dd4c99 100644
--- a/drivers/net/enic/vnic_nic.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_nic.h
diff --git a/drivers/net/enic/vnic_resource.h b/drivers/net/ethernet/cisco/enic/vnic_resource.h
index e0a73f1ca6f4..e0a73f1ca6f4 100644
--- a/drivers/net/enic/vnic_resource.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_resource.h
diff --git a/drivers/net/enic/vnic_rq.c b/drivers/net/ethernet/cisco/enic/vnic_rq.c
index 34105e0951a5..34105e0951a5 100644
--- a/drivers/net/enic/vnic_rq.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_rq.c
diff --git a/drivers/net/enic/vnic_rq.h b/drivers/net/ethernet/cisco/enic/vnic_rq.h
index 2056586f4d4b..2056586f4d4b 100644
--- a/drivers/net/enic/vnic_rq.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_rq.h
diff --git a/drivers/net/enic/vnic_rss.h b/drivers/net/ethernet/cisco/enic/vnic_rss.h
index fa421baf45b8..fa421baf45b8 100644
--- a/drivers/net/enic/vnic_rss.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_rss.h
diff --git a/drivers/net/enic/vnic_stats.h b/drivers/net/ethernet/cisco/enic/vnic_stats.h
index 77750ec93954..77750ec93954 100644
--- a/drivers/net/enic/vnic_stats.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_stats.h
diff --git a/drivers/net/enic/vnic_vic.c b/drivers/net/ethernet/cisco/enic/vnic_vic.c
index 24ef8cd40545..24ef8cd40545 100644
--- a/drivers/net/enic/vnic_vic.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_vic.c
diff --git a/drivers/net/enic/vnic_vic.h b/drivers/net/ethernet/cisco/enic/vnic_vic.h
index 9ef81f148351..9ef81f148351 100644
--- a/drivers/net/enic/vnic_vic.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_vic.h
diff --git a/drivers/net/enic/vnic_wq.c b/drivers/net/ethernet/cisco/enic/vnic_wq.c
index df61bd932ea6..df61bd932ea6 100644
--- a/drivers/net/enic/vnic_wq.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_wq.c
diff --git a/drivers/net/enic/vnic_wq.h b/drivers/net/ethernet/cisco/enic/vnic_wq.h
index 7dd937ac11c2..7dd937ac11c2 100644
--- a/drivers/net/enic/vnic_wq.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_wq.h
diff --git a/drivers/net/enic/wq_enet_desc.h b/drivers/net/ethernet/cisco/enic/wq_enet_desc.h
index c7021e3a631f..c7021e3a631f 100644
--- a/drivers/net/enic/wq_enet_desc.h
+++ b/drivers/net/ethernet/cisco/enic/wq_enet_desc.h
diff --git a/drivers/net/ethernet/davicom/Kconfig b/drivers/net/ethernet/davicom/Kconfig
new file mode 100644
index 000000000000..972b62b31837
--- /dev/null
+++ b/drivers/net/ethernet/davicom/Kconfig
@@ -0,0 +1,24 @@
+#
+# Davicom device configuration
+#
+
+config DM9000
+ tristate "DM9000 support"
+ depends on ARM || BLACKFIN || MIPS
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ Support for DM9000 chipset.
+
+ To compile this driver as a module, choose M here. The module
+ will be called dm9000.
+
+config DM9000_FORCE_SIMPLE_PHY_POLL
+ bool "Force simple NSR based PHY polling"
+ depends on DM9000
+ ---help---
+ This configuration forces the DM9000 to use the NSR's LinkStatus
+ bit to determine if the link is up or down instead of the more
+ costly MII PHY reads. Note, this will not work if the chip is
+ operating with an external PHY.
diff --git a/drivers/net/ethernet/davicom/Makefile b/drivers/net/ethernet/davicom/Makefile
new file mode 100644
index 000000000000..74b31f0ebe18
--- /dev/null
+++ b/drivers/net/ethernet/davicom/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Davicom device drivers.
+#
+
+obj-$(CONFIG_DM9000) += dm9000.o
diff --git a/drivers/net/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 8ef31dc4704d..438f4580bf66 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -56,6 +56,13 @@ static int watchdog = 5000;
module_param(watchdog, int, 0400);
MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+/*
+ * Debug messages level
+ */
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "dm9000 debug level (0-4)");
+
/* DM9000 register address locking.
*
* The DM9000 uses an address register to control where data written
@@ -103,7 +110,6 @@ typedef struct board_info {
unsigned int flags;
unsigned int in_suspend :1;
unsigned int wake_supported :1;
- int debug_level;
enum dm9000_type type;
@@ -138,8 +144,7 @@ typedef struct board_info {
/* debug code */
#define dm9000_dbg(db, lev, msg...) do { \
- if ((lev) < CONFIG_DM9000_DEBUGLEVEL && \
- (lev) < db->debug_level) { \
+ if ((lev) < debug) { \
dev_dbg(db->dev, msg); \
} \
} while (0)
@@ -1339,7 +1344,7 @@ static const struct net_device_ops dm9000_netdev_ops = {
.ndo_stop = dm9000_stop,
.ndo_start_xmit = dm9000_start_xmit,
.ndo_tx_timeout = dm9000_timeout,
- .ndo_set_multicast_list = dm9000_hash_table,
+ .ndo_set_rx_mode = dm9000_hash_table,
.ndo_do_ioctl = dm9000_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_features = dm9000_set_features,
diff --git a/drivers/net/dm9000.h b/drivers/net/ethernet/davicom/dm9000.h
index 55688bd1a3ef..55688bd1a3ef 100644
--- a/drivers/net/dm9000.h
+++ b/drivers/net/ethernet/davicom/dm9000.h
diff --git a/drivers/net/ethernet/dec/Kconfig b/drivers/net/ethernet/dec/Kconfig
new file mode 100644
index 000000000000..37940279ded8
--- /dev/null
+++ b/drivers/net/ethernet/dec/Kconfig
@@ -0,0 +1,37 @@
+#
+# Digital Equipment Inc network device configuration
+#
+
+config NET_VENDOR_DEC
+ bool "Digital Equipment devices"
+ default y
+ depends on PCI || EISA || CARDBUS
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about DEC cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_DEC
+
+config EWRK3
+ tristate "EtherWORKS 3 (DE203, DE204, DE205) support"
+ depends on ISA
+ select CRC32
+ ---help---
+ This driver supports the DE203, DE204 and DE205 network (Ethernet)
+ cards. If this is for you, say Y and read
+ <file:Documentation/networking/ewrk3.txt> in the kernel source as
+ well as the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ewrk3.
+
+source "drivers/net/ethernet/dec/tulip/Kconfig"
+
+endif # NET_VENDOR_DEC
diff --git a/drivers/net/ethernet/dec/Makefile b/drivers/net/ethernet/dec/Makefile
new file mode 100644
index 000000000000..1b01ed8d42c8
--- /dev/null
+++ b/drivers/net/ethernet/dec/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Digital Equipment Inc. network device drivers.
+#
+
+obj-$(CONFIG_EWRK3) += ewrk3.o
+obj-$(CONFIG_NET_TULIP) += tulip/
diff --git a/drivers/net/ewrk3.c b/drivers/net/ethernet/dec/ewrk3.c
index 05a5f71451a7..f9df5e4d0341 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ethernet/dec/ewrk3.c
@@ -393,7 +393,7 @@ static const struct net_device_ops ewrk3_netdev_ops = {
.ndo_open = ewrk3_open,
.ndo_start_xmit = ewrk3_queue_pkt,
.ndo_stop = ewrk3_close,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_do_ioctl = ewrk3_ioctl,
.ndo_tx_timeout = ewrk3_timeout,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/ewrk3.h b/drivers/net/ethernet/dec/ewrk3.h
index 8e0ee906567b..8e0ee906567b 100644
--- a/drivers/net/ewrk3.h
+++ b/drivers/net/ethernet/dec/ewrk3.h
diff --git a/drivers/net/tulip/21142.c b/drivers/net/ethernet/dec/tulip/21142.c
index 092c3faa882a..25b8deedbef8 100644
--- a/drivers/net/tulip/21142.c
+++ b/drivers/net/ethernet/dec/tulip/21142.c
@@ -7,9 +7,6 @@
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
DC21143 manual "21143 PCI/CardBus 10/100Mb/s Ethernet LAN Controller
Hardware Reference Manual" is currently available at :
http://developer.intel.com/design/network/manuals/278074.htm
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/ethernet/dec/tulip/Kconfig
index 1f8d4a8d8ea4..1203be0436e2 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/ethernet/dec/tulip/Kconfig
@@ -2,10 +2,10 @@
# Tulip family network device configuration
#
-menuconfig NET_TULIP
- bool "\"Tulip\" family network device support"
- depends on PCI || EISA || CARDBUS
- help
+config NET_TULIP
+ bool "DEC - Tulip devices"
+ depends on (PCI || EISA || CARDBUS)
+ ---help---
This selects the "Tulip" family of EISA/PCI network cards.
if NET_TULIP
@@ -32,7 +32,7 @@ config DE2104X_DSL
depends on DE2104X
range 0 31
default 0
- help
+ ---help---
Setting this value allows to align ring buffer descriptors into their
own cache lines. Value of 4 corresponds to the typical 32 byte line
(the descriptor is 16 bytes). This is necessary on systems that lack
@@ -59,7 +59,7 @@ config TULIP
config TULIP_MWI
bool "New bus configuration (EXPERIMENTAL)"
depends on TULIP && EXPERIMENTAL
- help
+ ---help---
This configures your Tulip card specifically for the card and
system cache line size type you are using.
@@ -70,7 +70,7 @@ config TULIP_MWI
config TULIP_MMIO
bool "Use PCI shared mem for NIC registers"
depends on TULIP
- help
+ ---help---
Use PCI shared memory for the NIC registers, rather than going through
the Tulip's PIO (programmed I/O ports). Faster, but could produce
obscure bugs if your mainboard has memory controller timing issues.
@@ -79,7 +79,7 @@ config TULIP_MMIO
config TULIP_NAPI
bool "Use RX polling (NAPI)"
depends on TULIP
- help
+ ---help---
NAPI is a new driver API designed to reduce CPU and interrupt load
when the driver is receiving lots of packets from the card. It is
still somewhat experimental and thus not yet enabled by default.
@@ -107,7 +107,7 @@ config TULIP_DM910X
config DE4X5
tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
- depends on PCI || EISA
+ depends on (PCI || EISA)
select CRC32
---help---
This is support for the DIGITAL series of PCI/EISA Ethernet cards.
@@ -125,8 +125,9 @@ config WINBOND_840
tristate "Winbond W89c840 Ethernet support"
depends on PCI
select CRC32
+ select NET_CORE
select MII
- help
+ ---help---
This driver is for the Winbond W89c840 chip. It also works with
the TX9882 chip on the Compex RL100-ATX board.
More specific information and updates are available from
diff --git a/drivers/net/tulip/Makefile b/drivers/net/ethernet/dec/tulip/Makefile
index 5e8be38b45bb..5e8be38b45bb 100644
--- a/drivers/net/tulip/Makefile
+++ b/drivers/net/ethernet/dec/tulip/Makefile
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
index ce90efc6ba3c..1427739d9a51 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -1956,7 +1956,7 @@ bad_srom:
static const struct net_device_ops de_netdev_ops = {
.ndo_open = de_open,
.ndo_stop = de_close,
- .ndo_set_multicast_list = de_set_rx_mode,
+ .ndo_set_rx_mode = de_set_rx_mode,
.ndo_start_xmit = de_start_xmit,
.ndo_get_stats = de_get_stats,
.ndo_tx_timeout = de_tx_timeout,
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c
index 959b41021a65..871bcaa7068d 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/ethernet/dec/tulip/de4x5.c
@@ -1084,7 +1084,7 @@ static const struct net_device_ops de4x5_netdev_ops = {
.ndo_stop = de4x5_close,
.ndo_start_xmit = de4x5_queue_pkt,
.ndo_get_stats = de4x5_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_do_ioctl = de4x5_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address= eth_mac_addr,
diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/ethernet/dec/tulip/de4x5.h
index 9f2877438fb0..ec756eba397b 100644
--- a/drivers/net/tulip/de4x5.h
+++ b/drivers/net/ethernet/dec/tulip/de4x5.h
@@ -991,8 +991,6 @@
*/
#include <linux/sockios.h>
-#define DE4X5IOCTL SIOCDEVPRIVATE
-
struct de4x5_ioctl {
unsigned short cmd; /* Command to run */
unsigned short len; /* Length of the data buffer */
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c
index 9a21ca3873fc..17b11ee1745a 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/ethernet/dec/tulip/dmfe.c
@@ -356,7 +356,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_open = dmfe_open,
.ndo_stop = dmfe_stop,
.ndo_start_xmit = dmfe_start_xmit,
- .ndo_set_multicast_list = dmfe_set_filter_mode,
+ .ndo_set_rx_mode = dmfe_set_filter_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/ethernet/dec/tulip/eeprom.c
index fa5eee925f25..14d5b611783d 100644
--- a/drivers/net/tulip/eeprom.c
+++ b/drivers/net/ethernet/dec/tulip/eeprom.c
@@ -7,8 +7,6 @@
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
Please submit bug reports to http://bugzilla.kernel.org/.
*/
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/ethernet/dec/tulip/interrupt.c
index 5350d753e0ff..4fb8c8c0a420 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/ethernet/dec/tulip/interrupt.c
@@ -7,10 +7,7 @@
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
Please submit bugs to http://bugzilla.kernel.org/ .
-
*/
#include <linux/pci.h>
diff --git a/drivers/net/tulip/media.c b/drivers/net/ethernet/dec/tulip/media.c
index 4bd13922875d..beeb17b52ad4 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/ethernet/dec/tulip/media.c
@@ -7,9 +7,6 @@
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
Please submit bugs to http://bugzilla.kernel.org/ .
*/
diff --git a/drivers/net/tulip/pnic.c b/drivers/net/ethernet/dec/tulip/pnic.c
index 52d898bdbeb4..9c16e4ad02a6 100644
--- a/drivers/net/tulip/pnic.c
+++ b/drivers/net/ethernet/dec/tulip/pnic.c
@@ -7,9 +7,6 @@
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
Please submit bugs to http://bugzilla.kernel.org/ .
*/
diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/ethernet/dec/tulip/pnic2.c
index 93358ee4d830..04a7e477eaff 100644
--- a/drivers/net/tulip/pnic2.c
+++ b/drivers/net/ethernet/dec/tulip/pnic2.c
@@ -8,9 +8,6 @@
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
Please submit bugs to http://bugzilla.kernel.org/ .
*/
diff --git a/drivers/net/tulip/timer.c b/drivers/net/ethernet/dec/tulip/timer.c
index 2017faf2d0e6..19078d28ffb9 100644
--- a/drivers/net/tulip/timer.c
+++ b/drivers/net/ethernet/dec/tulip/timer.c
@@ -7,9 +7,6 @@
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
Please submit bugs to http://bugzilla.kernel.org/ .
*/
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/ethernet/dec/tulip/tulip.h
index 9db528967da9..fb3887c18dc6 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/ethernet/dec/tulip/tulip.h
@@ -7,9 +7,6 @@
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
Please submit bugs to http://bugzilla.kernel.org/ .
*/
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index 1246998a677c..9656dd0647d9 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -6,9 +6,6 @@
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
- for more information on this driver.
-
Please submit bugs to http://bugzilla.kernel.org/ .
*/
@@ -1291,7 +1288,7 @@ static const struct net_device_ops tulip_netdev_ops = {
.ndo_stop = tulip_close,
.ndo_get_stats = tulip_get_stats,
.ndo_do_ioctl = private_ioctl,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c
index 9e63f406f72d..7a44a7a6adc8 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/ethernet/dec/tulip/uli526x.c
@@ -259,7 +259,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_open = uli526x_open,
.ndo_stop = uli526x_stop,
.ndo_start_xmit = uli526x_start_xmit,
- .ndo_set_multicast_list = uli526x_set_filter_mode,
+ .ndo_set_rx_mode = uli526x_set_filter_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c
index 862eadf07191..4d01219ba22f 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/ethernet/dec/tulip/winbond-840.c
@@ -350,7 +350,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_stop = netdev_close,
.ndo_start_xmit = start_tx,
.ndo_get_stats = get_stats,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = netdev_ioctl,
.ndo_tx_timeout = tx_timeout,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c
index 988b8eb24d37..988b8eb24d37 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c
diff --git a/drivers/net/ethernet/dlink/Kconfig b/drivers/net/ethernet/dlink/Kconfig
new file mode 100644
index 000000000000..b5afe218c31b
--- /dev/null
+++ b/drivers/net/ethernet/dlink/Kconfig
@@ -0,0 +1,86 @@
+#
+# D-Link device configuration
+#
+
+config NET_VENDOR_DLINK
+ bool "D-Link devices"
+ default y
+ depends on PCI || PARPORT
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about D-Link devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_DLINK
+
+config DE600
+ tristate "D-Link DE600 pocket adapter support"
+ depends on PARPORT
+ ---help---
+ This is a network (Ethernet) device which attaches to your parallel
+ port. Read <file:Documentation/networking/DLINK.txt> as well as the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, if you want to use
+ this. It is possible to have several devices share a single parallel
+ port and it is safe to compile the corresponding drivers into the
+ kernel.
+
+ To compile this driver as a module, choose M here: the module
+ will be called de600.
+
+config DE620
+ tristate "D-Link DE620 pocket adapter support"
+ depends on PARPORT
+ ---help---
+ This is a network (Ethernet) device which attaches to your parallel
+ port. Read <file:Documentation/networking/DLINK.txt> as well as the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, if you want to use
+ this. It is possible to have several devices share a single parallel
+ port and it is safe to compile the corresponding drivers into the
+ kernel.
+
+ To compile this driver as a module, choose M here: the module
+ will be called de620.
+
+config DL2K
+ tristate "DL2000/TC902x-based Gigabit Ethernet support"
+ depends on PCI
+ select CRC32
+ ---help---
+ This driver supports DL2000/TC902x-based Gigabit ethernet cards,
+ which includes
+ D-Link DGE-550T Gigabit Ethernet Adapter.
+ D-Link DL2000-based Gigabit Ethernet Adapter.
+ Sundance/Tamarack TC902x Gigabit Ethernet Adapter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called dl2k.
+
+config SUNDANCE
+ tristate "Sundance Alta support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This driver is for the Sundance "Alta" chip.
+ More specific information and updates are available from
+ <http://www.scyld.com/network/sundance.html>.
+
+config SUNDANCE_MMIO
+ bool "Use MMIO instead of PIO"
+ depends on SUNDANCE
+ ---help---
+ Enable memory-mapped I/O for interaction with Sundance NIC registers.
+ Do NOT enable this by default, PIO (enabled when MMIO is disabled)
+ is known to solve bugs on certain chips.
+
+ If unsure, say N.
+
+endif # NET_VENDOR_DLINK
diff --git a/drivers/net/ethernet/dlink/Makefile b/drivers/net/ethernet/dlink/Makefile
new file mode 100644
index 000000000000..c705eaa4f5b2
--- /dev/null
+++ b/drivers/net/ethernet/dlink/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the D-Link network device drivers.
+#
+
+obj-$(CONFIG_DE600) += de600.o
+obj-$(CONFIG_DE620) += de620.o
+obj-$(CONFIG_DL2K) += dl2k.o
+obj-$(CONFIG_SUNDANCE) += sundance.o
diff --git a/drivers/net/de600.c b/drivers/net/ethernet/dlink/de600.c
index 23a65398d011..23a65398d011 100644
--- a/drivers/net/de600.c
+++ b/drivers/net/ethernet/dlink/de600.c
diff --git a/drivers/net/de600.h b/drivers/net/ethernet/dlink/de600.h
index e80ecbabcf4e..e80ecbabcf4e 100644
--- a/drivers/net/de600.h
+++ b/drivers/net/ethernet/dlink/de600.h
diff --git a/drivers/net/de620.c b/drivers/net/ethernet/dlink/de620.c
index 1c51a7576119..3b934ab784d3 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/ethernet/dlink/de620.c
@@ -767,7 +767,7 @@ static const struct net_device_ops de620_netdev_ops = {
.ndo_stop = de620_close,
.ndo_start_xmit = de620_start_xmit,
.ndo_tx_timeout = de620_timeout,
- .ndo_set_multicast_list = de620_set_multicast_list,
+ .ndo_set_rx_mode = de620_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/de620.h b/drivers/net/ethernet/dlink/de620.h
index e8d9a88f4cb5..e8d9a88f4cb5 100644
--- a/drivers/net/de620.h
+++ b/drivers/net/ethernet/dlink/de620.h
diff --git a/drivers/net/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
index ed73e4a93508..b2dc2c81a147 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -92,7 +92,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_get_stats = get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
- .ndo_set_multicast_list = set_multicast,
+ .ndo_set_rx_mode = set_multicast,
.ndo_do_ioctl = rio_ioctl,
.ndo_tx_timeout = rio_tx_timeout,
.ndo_change_mtu = change_mtu,
@@ -1428,7 +1428,7 @@ mii_wait_link (struct net_device *dev, int wait)
do {
bmsr = mii_read (dev, phy_addr, MII_BMSR);
- if (bmsr & MII_BMSR_LINK_STATUS)
+ if (bmsr & BMSR_LSTATUS)
return 0;
mdelay (1);
} while (--wait > 0);
@@ -1449,60 +1449,60 @@ mii_get_media (struct net_device *dev)
bmsr = mii_read (dev, phy_addr, MII_BMSR);
if (np->an_enable) {
- if (!(bmsr & MII_BMSR_AN_COMPLETE)) {
+ if (!(bmsr & BMSR_ANEGCOMPLETE)) {
/* Auto-Negotiation not completed */
return -1;
}
- negotiate = mii_read (dev, phy_addr, MII_ANAR) &
- mii_read (dev, phy_addr, MII_ANLPAR);
- mscr = mii_read (dev, phy_addr, MII_MSCR);
- mssr = mii_read (dev, phy_addr, MII_MSSR);
- if (mscr & MII_MSCR_1000BT_FD && mssr & MII_MSSR_LP_1000BT_FD) {
+ negotiate = mii_read (dev, phy_addr, MII_ADVERTISE) &
+ mii_read (dev, phy_addr, MII_LPA);
+ mscr = mii_read (dev, phy_addr, MII_CTRL1000);
+ mssr = mii_read (dev, phy_addr, MII_STAT1000);
+ if (mscr & ADVERTISE_1000FULL && mssr & LPA_1000FULL) {
np->speed = 1000;
np->full_duplex = 1;
printk (KERN_INFO "Auto 1000 Mbps, Full duplex\n");
- } else if (mscr & MII_MSCR_1000BT_HD && mssr & MII_MSSR_LP_1000BT_HD) {
+ } else if (mscr & ADVERTISE_1000HALF && mssr & LPA_1000HALF) {
np->speed = 1000;
np->full_duplex = 0;
printk (KERN_INFO "Auto 1000 Mbps, Half duplex\n");
- } else if (negotiate & MII_ANAR_100BX_FD) {
+ } else if (negotiate & ADVERTISE_100FULL) {
np->speed = 100;
np->full_duplex = 1;
printk (KERN_INFO "Auto 100 Mbps, Full duplex\n");
- } else if (negotiate & MII_ANAR_100BX_HD) {
+ } else if (negotiate & ADVERTISE_100HALF) {
np->speed = 100;
np->full_duplex = 0;
printk (KERN_INFO "Auto 100 Mbps, Half duplex\n");
- } else if (negotiate & MII_ANAR_10BT_FD) {
+ } else if (negotiate & ADVERTISE_10FULL) {
np->speed = 10;
np->full_duplex = 1;
printk (KERN_INFO "Auto 10 Mbps, Full duplex\n");
- } else if (negotiate & MII_ANAR_10BT_HD) {
+ } else if (negotiate & ADVERTISE_10HALF) {
np->speed = 10;
np->full_duplex = 0;
printk (KERN_INFO "Auto 10 Mbps, Half duplex\n");
}
- if (negotiate & MII_ANAR_PAUSE) {
+ if (negotiate & ADVERTISE_PAUSE_CAP) {
np->tx_flow &= 1;
np->rx_flow &= 1;
- } else if (negotiate & MII_ANAR_ASYMMETRIC) {
+ } else if (negotiate & ADVERTISE_PAUSE_ASYM) {
np->tx_flow = 0;
np->rx_flow &= 1;
}
/* else tx_flow, rx_flow = user select */
} else {
__u16 bmcr = mii_read (dev, phy_addr, MII_BMCR);
- switch (bmcr & (MII_BMCR_SPEED_100 | MII_BMCR_SPEED_1000)) {
- case MII_BMCR_SPEED_1000:
+ switch (bmcr & (BMCR_SPEED100 | BMCR_SPEED1000)) {
+ case BMCR_SPEED1000:
printk (KERN_INFO "Operating at 1000 Mbps, ");
break;
- case MII_BMCR_SPEED_100:
+ case BMCR_SPEED100:
printk (KERN_INFO "Operating at 100 Mbps, ");
break;
case 0:
printk (KERN_INFO "Operating at 10 Mbps, ");
}
- if (bmcr & MII_BMCR_DUPLEX_MODE) {
+ if (bmcr & BMCR_FULLDPLX) {
printk (KERN_CONT "Full duplex\n");
} else {
printk (KERN_CONT "Half duplex\n");
@@ -1536,24 +1536,22 @@ mii_set_media (struct net_device *dev)
if (np->an_enable) {
/* Advertise capabilities */
bmsr = mii_read (dev, phy_addr, MII_BMSR);
- anar = mii_read (dev, phy_addr, MII_ANAR) &
- ~MII_ANAR_100BX_FD &
- ~MII_ANAR_100BX_HD &
- ~MII_ANAR_100BT4 &
- ~MII_ANAR_10BT_FD &
- ~MII_ANAR_10BT_HD;
- if (bmsr & MII_BMSR_100BX_FD)
- anar |= MII_ANAR_100BX_FD;
- if (bmsr & MII_BMSR_100BX_HD)
- anar |= MII_ANAR_100BX_HD;
- if (bmsr & MII_BMSR_100BT4)
- anar |= MII_ANAR_100BT4;
- if (bmsr & MII_BMSR_10BT_FD)
- anar |= MII_ANAR_10BT_FD;
- if (bmsr & MII_BMSR_10BT_HD)
- anar |= MII_ANAR_10BT_HD;
- anar |= MII_ANAR_PAUSE | MII_ANAR_ASYMMETRIC;
- mii_write (dev, phy_addr, MII_ANAR, anar);
+ anar = mii_read (dev, phy_addr, MII_ADVERTISE) &
+ ~(ADVERTISE_100FULL | ADVERTISE_10FULL |
+ ADVERTISE_100HALF | ADVERTISE_10HALF |
+ ADVERTISE_100BASE4);
+ if (bmsr & BMSR_100FULL)
+ anar |= ADVERTISE_100FULL;
+ if (bmsr & BMSR_100HALF)
+ anar |= ADVERTISE_100HALF;
+ if (bmsr & BMSR_100BASE4)
+ anar |= ADVERTISE_100BASE4;
+ if (bmsr & BMSR_10FULL)
+ anar |= ADVERTISE_10FULL;
+ if (bmsr & BMSR_10HALF)
+ anar |= ADVERTISE_10HALF;
+ anar |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ mii_write (dev, phy_addr, MII_ADVERTISE, anar);
/* Enable Auto crossover */
pscr = mii_read (dev, phy_addr, MII_PHY_SCR);
@@ -1561,8 +1559,8 @@ mii_set_media (struct net_device *dev)
mii_write (dev, phy_addr, MII_PHY_SCR, pscr);
/* Soft reset PHY */
- mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
- bmcr = MII_BMCR_AN_ENABLE | MII_BMCR_RESTART_AN | MII_BMCR_RESET;
+ mii_write (dev, phy_addr, MII_BMCR, BMCR_RESET);
+ bmcr = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET;
mii_write (dev, phy_addr, MII_BMCR, bmcr);
mdelay(1);
} else {
@@ -1574,7 +1572,7 @@ mii_set_media (struct net_device *dev)
/* 2) PHY Reset */
bmcr = mii_read (dev, phy_addr, MII_BMCR);
- bmcr |= MII_BMCR_RESET;
+ bmcr |= BMCR_RESET;
mii_write (dev, phy_addr, MII_BMCR, bmcr);
/* 3) Power Down */
@@ -1583,25 +1581,25 @@ mii_set_media (struct net_device *dev)
mdelay (100); /* wait a certain time */
/* 4) Advertise nothing */
- mii_write (dev, phy_addr, MII_ANAR, 0);
+ mii_write (dev, phy_addr, MII_ADVERTISE, 0);
/* 5) Set media and Power Up */
- bmcr = MII_BMCR_POWER_DOWN;
+ bmcr = BMCR_PDOWN;
if (np->speed == 100) {
- bmcr |= MII_BMCR_SPEED_100;
+ bmcr |= BMCR_SPEED100;
printk (KERN_INFO "Manual 100 Mbps, ");
} else if (np->speed == 10) {
printk (KERN_INFO "Manual 10 Mbps, ");
}
if (np->full_duplex) {
- bmcr |= MII_BMCR_DUPLEX_MODE;
+ bmcr |= BMCR_FULLDPLX;
printk (KERN_CONT "Full duplex\n");
} else {
printk (KERN_CONT "Half duplex\n");
}
#if 0
/* Set 1000BaseT Master/Slave setting */
- mscr = mii_read (dev, phy_addr, MII_MSCR);
+ mscr = mii_read (dev, phy_addr, MII_CTRL1000);
mscr |= MII_MSCR_CFG_ENABLE;
mscr &= ~MII_MSCR_CFG_VALUE = 0;
#endif
@@ -1624,7 +1622,7 @@ mii_get_media_pcs (struct net_device *dev)
bmsr = mii_read (dev, phy_addr, PCS_BMSR);
if (np->an_enable) {
- if (!(bmsr & MII_BMSR_AN_COMPLETE)) {
+ if (!(bmsr & BMSR_ANEGCOMPLETE)) {
/* Auto-Negotiation not completed */
return -1;
}
@@ -1649,7 +1647,7 @@ mii_get_media_pcs (struct net_device *dev)
} else {
__u16 bmcr = mii_read (dev, phy_addr, PCS_BMCR);
printk (KERN_INFO "Operating at 1000 Mbps, ");
- if (bmcr & MII_BMCR_DUPLEX_MODE) {
+ if (bmcr & BMCR_FULLDPLX) {
printk (KERN_CONT "Full duplex\n");
} else {
printk (KERN_CONT "Half duplex\n");
@@ -1682,7 +1680,7 @@ mii_set_media_pcs (struct net_device *dev)
if (np->an_enable) {
/* Advertise capabilities */
esr = mii_read (dev, phy_addr, PCS_ESR);
- anar = mii_read (dev, phy_addr, MII_ANAR) &
+ anar = mii_read (dev, phy_addr, MII_ADVERTISE) &
~PCS_ANAR_HALF_DUPLEX &
~PCS_ANAR_FULL_DUPLEX;
if (esr & (MII_ESR_1000BT_HD | MII_ESR_1000BX_HD))
@@ -1690,22 +1688,21 @@ mii_set_media_pcs (struct net_device *dev)
if (esr & (MII_ESR_1000BT_FD | MII_ESR_1000BX_FD))
anar |= PCS_ANAR_FULL_DUPLEX;
anar |= PCS_ANAR_PAUSE | PCS_ANAR_ASYMMETRIC;
- mii_write (dev, phy_addr, MII_ANAR, anar);
+ mii_write (dev, phy_addr, MII_ADVERTISE, anar);
/* Soft reset PHY */
- mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
- bmcr = MII_BMCR_AN_ENABLE | MII_BMCR_RESTART_AN |
- MII_BMCR_RESET;
+ mii_write (dev, phy_addr, MII_BMCR, BMCR_RESET);
+ bmcr = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET;
mii_write (dev, phy_addr, MII_BMCR, bmcr);
mdelay(1);
} else {
/* Force speed setting */
/* PHY Reset */
- bmcr = MII_BMCR_RESET;
+ bmcr = BMCR_RESET;
mii_write (dev, phy_addr, MII_BMCR, bmcr);
mdelay(10);
if (np->full_duplex) {
- bmcr = MII_BMCR_DUPLEX_MODE;
+ bmcr = BMCR_FULLDPLX;
printk (KERN_INFO "Manual full duplex\n");
} else {
bmcr = 0;
@@ -1715,7 +1712,7 @@ mii_set_media_pcs (struct net_device *dev)
mdelay(10);
/* Advertise nothing */
- mii_write (dev, phy_addr, MII_ANAR, 0);
+ mii_write (dev, phy_addr, MII_ADVERTISE, 0);
}
return 0;
}
diff --git a/drivers/net/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h
index 7caab3d26a9e..ba0adcafa55a 100644
--- a/drivers/net/dl2k.h
+++ b/drivers/net/ethernet/dlink/dl2k.h
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/crc32.h>
#include <linux/ethtool.h>
+#include <linux/mii.h>
#include <linux/bitops.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/io.h>
@@ -271,20 +272,9 @@ enum RFS_bits {
#define MII_RESET_TIME_OUT 10000
/* MII register */
enum _mii_reg {
- MII_BMCR = 0,
- MII_BMSR = 1,
- MII_PHY_ID1 = 2,
- MII_PHY_ID2 = 3,
- MII_ANAR = 4,
- MII_ANLPAR = 5,
- MII_ANER = 6,
- MII_ANNPT = 7,
- MII_ANLPRNP = 8,
- MII_MSCR = 9,
- MII_MSSR = 10,
- MII_ESR = 15,
MII_PHY_SCR = 16,
};
+
/* PCS register */
enum _pcs_reg {
PCS_BMCR = 0,
@@ -297,102 +287,6 @@ enum _pcs_reg {
PCS_ESR = 15,
};
-/* Basic Mode Control Register */
-enum _mii_bmcr {
- MII_BMCR_RESET = 0x8000,
- MII_BMCR_LOOP_BACK = 0x4000,
- MII_BMCR_SPEED_LSB = 0x2000,
- MII_BMCR_AN_ENABLE = 0x1000,
- MII_BMCR_POWER_DOWN = 0x0800,
- MII_BMCR_ISOLATE = 0x0400,
- MII_BMCR_RESTART_AN = 0x0200,
- MII_BMCR_DUPLEX_MODE = 0x0100,
- MII_BMCR_COL_TEST = 0x0080,
- MII_BMCR_SPEED_MSB = 0x0040,
- MII_BMCR_SPEED_RESERVED = 0x003f,
- MII_BMCR_SPEED_10 = 0,
- MII_BMCR_SPEED_100 = MII_BMCR_SPEED_LSB,
- MII_BMCR_SPEED_1000 = MII_BMCR_SPEED_MSB,
-};
-
-/* Basic Mode Status Register */
-enum _mii_bmsr {
- MII_BMSR_100BT4 = 0x8000,
- MII_BMSR_100BX_FD = 0x4000,
- MII_BMSR_100BX_HD = 0x2000,
- MII_BMSR_10BT_FD = 0x1000,
- MII_BMSR_10BT_HD = 0x0800,
- MII_BMSR_100BT2_FD = 0x0400,
- MII_BMSR_100BT2_HD = 0x0200,
- MII_BMSR_EXT_STATUS = 0x0100,
- MII_BMSR_PREAMBLE_SUPP = 0x0040,
- MII_BMSR_AN_COMPLETE = 0x0020,
- MII_BMSR_REMOTE_FAULT = 0x0010,
- MII_BMSR_AN_ABILITY = 0x0008,
- MII_BMSR_LINK_STATUS = 0x0004,
- MII_BMSR_JABBER_DETECT = 0x0002,
- MII_BMSR_EXT_CAP = 0x0001,
-};
-
-/* ANAR */
-enum _mii_anar {
- MII_ANAR_NEXT_PAGE = 0x8000,
- MII_ANAR_REMOTE_FAULT = 0x4000,
- MII_ANAR_ASYMMETRIC = 0x0800,
- MII_ANAR_PAUSE = 0x0400,
- MII_ANAR_100BT4 = 0x0200,
- MII_ANAR_100BX_FD = 0x0100,
- MII_ANAR_100BX_HD = 0x0080,
- MII_ANAR_10BT_FD = 0x0020,
- MII_ANAR_10BT_HD = 0x0010,
- MII_ANAR_SELECTOR = 0x001f,
- MII_IEEE8023_CSMACD = 0x0001,
-};
-
-/* ANLPAR */
-enum _mii_anlpar {
- MII_ANLPAR_NEXT_PAGE = MII_ANAR_NEXT_PAGE,
- MII_ANLPAR_REMOTE_FAULT = MII_ANAR_REMOTE_FAULT,
- MII_ANLPAR_ASYMMETRIC = MII_ANAR_ASYMMETRIC,
- MII_ANLPAR_PAUSE = MII_ANAR_PAUSE,
- MII_ANLPAR_100BT4 = MII_ANAR_100BT4,
- MII_ANLPAR_100BX_FD = MII_ANAR_100BX_FD,
- MII_ANLPAR_100BX_HD = MII_ANAR_100BX_HD,
- MII_ANLPAR_10BT_FD = MII_ANAR_10BT_FD,
- MII_ANLPAR_10BT_HD = MII_ANAR_10BT_HD,
- MII_ANLPAR_SELECTOR = MII_ANAR_SELECTOR,
-};
-
-/* Auto-Negotiation Expansion Register */
-enum _mii_aner {
- MII_ANER_PAR_DETECT_FAULT = 0x0010,
- MII_ANER_LP_NEXTPAGABLE = 0x0008,
- MII_ANER_NETXTPAGABLE = 0x0004,
- MII_ANER_PAGE_RECEIVED = 0x0002,
- MII_ANER_LP_NEGOTIABLE = 0x0001,
-};
-
-/* MASTER-SLAVE Control Register */
-enum _mii_mscr {
- MII_MSCR_TEST_MODE = 0xe000,
- MII_MSCR_CFG_ENABLE = 0x1000,
- MII_MSCR_CFG_VALUE = 0x0800,
- MII_MSCR_PORT_VALUE = 0x0400,
- MII_MSCR_1000BT_FD = 0x0200,
- MII_MSCR_1000BT_HD = 0X0100,
-};
-
-/* MASTER-SLAVE Status Register */
-enum _mii_mssr {
- MII_MSSR_CFG_FAULT = 0x8000,
- MII_MSSR_CFG_RES = 0x4000,
- MII_MSSR_LOCAL_RCV_STATUS = 0x2000,
- MII_MSSR_REMOTE_RCVR = 0x1000,
- MII_MSSR_LP_1000BT_FD = 0x0800,
- MII_MSSR_LP_1000BT_HD = 0x0400,
- MII_MSSR_IDLE_ERR_COUNT = 0x00ff,
-};
-
/* IEEE Extened Status Register */
enum _mii_esr {
MII_ESR_1000BX_FD = 0x8000,
diff --git a/drivers/net/sundance.c b/drivers/net/ethernet/dlink/sundance.c
index 4793df843c24..dcd7f7a71ad4 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/ethernet/dlink/sundance.c
@@ -464,7 +464,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_stop = netdev_close,
.ndo_start_xmit = start_tx,
.ndo_get_stats = get_stats,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = netdev_ioctl,
.ndo_tx_timeout = tx_timeout,
.ndo_change_mtu = change_mtu,
diff --git a/drivers/net/dnet.c b/drivers/net/ethernet/dnet.c
index c1063d1540c2..c1063d1540c2 100644
--- a/drivers/net/dnet.c
+++ b/drivers/net/ethernet/dnet.c
diff --git a/drivers/net/dnet.h b/drivers/net/ethernet/dnet.h
index 37f5b30fa78b..37f5b30fa78b 100644
--- a/drivers/net/dnet.h
+++ b/drivers/net/ethernet/dnet.h
diff --git a/drivers/net/ethernet/emulex/Kconfig b/drivers/net/ethernet/emulex/Kconfig
new file mode 100644
index 000000000000..7a28a6433944
--- /dev/null
+++ b/drivers/net/ethernet/emulex/Kconfig
@@ -0,0 +1,23 @@
+#
+# Emulex driver configuration
+#
+
+config NET_VENDOR_EMULEX
+ bool "Emulex devices"
+ default y
+ depends on PCI && INET
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Emulex cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_EMULEX
+
+source "drivers/net/ethernet/emulex/benet/Kconfig"
+
+endif # NET_VENDOR_EMULEX
diff --git a/drivers/net/ethernet/emulex/Makefile b/drivers/net/ethernet/emulex/Makefile
new file mode 100644
index 000000000000..ea8ec574d45a
--- /dev/null
+++ b/drivers/net/ethernet/emulex/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Emulex device drivers.
+#
+
+obj-$(CONFIG_BE2NET) += benet/
diff --git a/drivers/net/ethernet/emulex/benet/Kconfig b/drivers/net/ethernet/emulex/benet/Kconfig
new file mode 100644
index 000000000000..804db04a2bd0
--- /dev/null
+++ b/drivers/net/ethernet/emulex/benet/Kconfig
@@ -0,0 +1,6 @@
+config BE2NET
+ tristate "ServerEngines' 10Gbps NIC - BladeEngine"
+ depends on PCI && INET
+ ---help---
+ This driver implements the NIC functionality for ServerEngines'
+ 10Gbps network adapter - BladeEngine.
diff --git a/drivers/net/benet/Makefile b/drivers/net/ethernet/emulex/benet/Makefile
index a60cd8051135..a60cd8051135 100644
--- a/drivers/net/benet/Makefile
+++ b/drivers/net/ethernet/emulex/benet/Makefile
diff --git a/drivers/net/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index c85768cd1b18..644e8fed8364 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -29,6 +29,7 @@
#include <linux/interrupt.h>
#include <linux/firmware.h>
#include <linux/slab.h>
+#include <linux/u64_stats_sync.h>
#include "be_hw.h"
@@ -136,6 +137,11 @@ static inline void *queue_tail_node(struct be_queue_info *q)
return q->dma_mem.va + q->tail * q->entry_size;
}
+static inline void *queue_index_node(struct be_queue_info *q, u16 index)
+{
+ return q->dma_mem.va + index * q->entry_size;
+}
+
static inline void queue_head_inc(struct be_queue_info *q)
{
index_inc(&q->head, q->len);
@@ -167,15 +173,15 @@ struct be_mcc_obj {
};
struct be_tx_stats {
- u32 be_tx_reqs; /* number of TX requests initiated */
- u32 be_tx_stops; /* number of times TX Q was stopped */
- u32 be_tx_wrbs; /* number of tx WRBs used */
- u32 be_tx_compl; /* number of tx completion entries processed */
- ulong be_tx_jiffies;
- u64 be_tx_bytes;
- u64 be_tx_bytes_prev;
- u64 be_tx_pkts;
- u32 be_tx_rate;
+ u64 tx_bytes;
+ u64 tx_pkts;
+ u64 tx_reqs;
+ u64 tx_wrbs;
+ u64 tx_compl;
+ ulong tx_jiffies;
+ u32 tx_stops;
+ struct u64_stats_sync sync;
+ struct u64_stats_sync sync_compl;
};
struct be_tx_obj {
@@ -195,22 +201,20 @@ struct be_rx_page_info {
};
struct be_rx_stats {
- u32 rx_post_fail;/* number of ethrx buffer alloc failures */
- u32 rx_polls; /* number of times NAPI called poll function */
- u32 rx_events; /* number of ucast rx completion events */
- u32 rx_compl; /* number of rx completion entries processed */
- ulong rx_dropped; /* number of skb allocation errors */
- ulong rx_jiffies;
u64 rx_bytes;
- u64 rx_bytes_prev;
u64 rx_pkts;
- u32 rx_rate;
+ u64 rx_pkts_prev;
+ ulong rx_jiffies;
+ u32 rx_drops_no_skbs; /* skb allocation errors */
+ u32 rx_drops_no_frags; /* HW has no fetched frags */
+ u32 rx_post_fail; /* page post alloc failures */
+ u32 rx_polls; /* NAPI calls */
+ u32 rx_events;
+ u32 rx_compl;
u32 rx_mcast_pkts;
- u32 rxcp_err; /* Num rx completion entries w/ err set. */
- ulong rx_fps_jiffies; /* jiffies at last FPS calc */
- u32 rx_frags;
- u32 prev_rx_frags;
- u32 rx_fps; /* Rx frags per second */
+ u32 rx_compl_err; /* completions with err set */
+ u32 rx_pps; /* pkts per second */
+ struct u64_stats_sync sync;
};
struct be_rx_compl_info {
@@ -218,7 +222,7 @@ struct be_rx_compl_info {
u16 vlan_tag;
u16 pkt_size;
u16 rxq_idx;
- u16 mac_id;
+ u16 port;
u8 vlanf;
u8 num_rcvd;
u8 err;
@@ -246,44 +250,41 @@ struct be_rx_obj {
};
struct be_drv_stats {
- u8 be_on_die_temperature;
- u64 be_tx_events;
- u64 eth_red_drops;
- u64 rx_drops_no_pbuf;
- u64 rx_drops_no_txpb;
- u64 rx_drops_no_erx_descr;
- u64 rx_drops_no_tpre_descr;
- u64 rx_drops_too_many_frags;
- u64 rx_drops_invalid_ring;
- u64 forwarded_packets;
- u64 rx_drops_mtu;
- u64 rx_crc_errors;
- u64 rx_alignment_symbol_errors;
- u64 rx_pause_frames;
- u64 rx_priority_pause_frames;
- u64 rx_control_frames;
- u64 rx_in_range_errors;
- u64 rx_out_range_errors;
- u64 rx_frame_too_long;
- u64 rx_address_match_errors;
- u64 rx_dropped_too_small;
- u64 rx_dropped_too_short;
- u64 rx_dropped_header_too_small;
- u64 rx_dropped_tcp_length;
- u64 rx_dropped_runt;
- u64 rx_ip_checksum_errs;
- u64 rx_tcp_checksum_errs;
- u64 rx_udp_checksum_errs;
- u64 rx_switched_unicast_packets;
- u64 rx_switched_multicast_packets;
- u64 rx_switched_broadcast_packets;
- u64 tx_pauseframes;
- u64 tx_priority_pauseframes;
- u64 tx_controlframes;
- u64 rxpp_fifo_overflow_drop;
- u64 rx_input_fifo_overflow_drop;
- u64 pmem_fifo_overflow_drop;
- u64 jabber_events;
+ u32 be_on_die_temperature;
+ u32 tx_events;
+ u32 eth_red_drops;
+ u32 rx_drops_no_pbuf;
+ u32 rx_drops_no_txpb;
+ u32 rx_drops_no_erx_descr;
+ u32 rx_drops_no_tpre_descr;
+ u32 rx_drops_too_many_frags;
+ u32 rx_drops_invalid_ring;
+ u32 forwarded_packets;
+ u32 rx_drops_mtu;
+ u32 rx_crc_errors;
+ u32 rx_alignment_symbol_errors;
+ u32 rx_pause_frames;
+ u32 rx_priority_pause_frames;
+ u32 rx_control_frames;
+ u32 rx_in_range_errors;
+ u32 rx_out_range_errors;
+ u32 rx_frame_too_long;
+ u32 rx_address_match_errors;
+ u32 rx_dropped_too_small;
+ u32 rx_dropped_too_short;
+ u32 rx_dropped_header_too_small;
+ u32 rx_dropped_tcp_length;
+ u32 rx_dropped_runt;
+ u32 rx_ip_checksum_errs;
+ u32 rx_tcp_checksum_errs;
+ u32 rx_udp_checksum_errs;
+ u32 tx_pauseframes;
+ u32 tx_priority_pauseframes;
+ u32 tx_controlframes;
+ u32 rxpp_fifo_overflow_drop;
+ u32 rx_input_fifo_overflow_drop;
+ u32 pmem_fifo_overflow_drop;
+ u32 jabber_events;
};
struct be_vf_cfg {
@@ -302,7 +303,6 @@ struct be_adapter {
u8 __iomem *csr;
u8 __iomem *db; /* Door Bell */
- u8 __iomem *pcicfg; /* PCI config space */
struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
struct be_dma_mem mbox_mem;
@@ -338,7 +338,7 @@ struct be_adapter {
u8 vlan_tag[VLAN_N_VID];
u8 vlan_prio_bmap; /* Available Priority BitMap */
u16 recommended_prio; /* Recommended Priority */
- struct be_dma_mem mc_cmd_mem;
+ struct be_dma_mem rx_filter; /* Cmd DMA mem for rx-filter */
struct be_dma_mem stats_cmd;
/* Work queue used to perform periodic tasks like getting statistics */
@@ -352,7 +352,6 @@ struct be_adapter {
u32 beacon_state; /* for set_phys_id */
bool eeh_err;
- bool link_up;
u32 port_num;
bool promiscuous;
bool wol;
@@ -385,6 +384,8 @@ struct be_adapter {
#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))
@@ -525,8 +526,7 @@ static inline bool be_multi_rxq(const struct be_adapter *adapter)
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, bool link_up);
-extern void netdev_stats_update(struct be_adapter *adapter);
+extern void be_link_status_update(struct be_adapter *adapter, u32 link_status);
extern void be_parse_stats(struct be_adapter *adapter);
extern int be_load_fw(struct be_adapter *adapter, u8 *func);
#endif /* BE_H */
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 054fa67bc4e3..824b8e6021f6 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -19,7 +19,12 @@
#include "be_cmds.h"
/* Must be a power of 2 or else MODULO will BUG_ON */
-static int be_get_temp_freq = 32;
+static int be_get_temp_freq = 64;
+
+static inline void *embedded_payload(struct be_mcc_wrb *wrb)
+{
+ return wrb->payload.embedded_payload;
+}
static void be_mcc_notify(struct be_adapter *adapter)
{
@@ -82,31 +87,23 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) ||
(compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) &&
(compl->tag1 == CMD_SUBSYSTEM_ETH)) {
- if (adapter->generation == BE_GEN3) {
- if (lancer_chip(adapter)) {
- struct lancer_cmd_resp_pport_stats
- *resp = adapter->stats_cmd.va;
- be_dws_le_to_cpu(&resp->pport_stats,
- sizeof(resp->pport_stats));
- } else {
- struct be_cmd_resp_get_stats_v1 *resp =
- adapter->stats_cmd.va;
-
- be_dws_le_to_cpu(&resp->hw_stats,
- sizeof(resp->hw_stats));
- }
- } else {
- struct be_cmd_resp_get_stats_v0 *resp =
- adapter->stats_cmd.va;
-
- be_dws_le_to_cpu(&resp->hw_stats,
- sizeof(resp->hw_stats));
- }
be_parse_stats(adapter);
- netdev_stats_update(adapter);
adapter->stats_cmd_sent = false;
}
+ if (compl->tag0 ==
+ OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) {
+ struct be_mcc_wrb *mcc_wrb =
+ queue_index_node(&adapter->mcc_obj.q,
+ compl->tag1);
+ struct be_cmd_resp_get_cntl_addnl_attribs *resp =
+ embedded_payload(mcc_wrb);
+ adapter->drv_stats.be_on_die_temperature =
+ resp->on_die_temperature;
+ }
} else {
+ if (compl->tag0 == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
+ be_get_temp_freq = 0;
+
if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
compl_status == MCC_STATUS_ILLEGAL_REQUEST)
goto done;
@@ -131,8 +128,7 @@ done:
static void be_async_link_state_process(struct be_adapter *adapter,
struct be_async_event_link_state *evt)
{
- be_link_status_update(adapter,
- evt->port_link_status == ASYNC_EVENT_LINK_UP);
+ be_link_status_update(adapter, evt->port_link_status);
}
/* Grp5 CoS Priority evt */
@@ -162,7 +158,7 @@ static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
struct be_async_event_grp5_pvid_state *evt)
{
if (evt->enabled)
- adapter->pvid = le16_to_cpu(evt->tag);
+ adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
else
adapter->pvid = 0;
}
@@ -420,44 +416,45 @@ int be_cmd_POST(struct be_adapter *adapter)
} else {
return 0;
}
- } while (timeout < 40);
+ } while (timeout < 60);
dev_err(dev, "POST timeout; stage=0x%x\n", stage);
return -1;
}
-static inline void *embedded_payload(struct be_mcc_wrb *wrb)
-{
- return wrb->payload.embedded_payload;
-}
static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
{
return &wrb->payload.sgl[0];
}
-/* Don't touch the hdr after it's prepared */
-static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
- bool embedded, u8 sge_cnt, u32 opcode)
-{
- if (embedded)
- wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
- else
- wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) <<
- MCC_WRB_SGE_CNT_SHIFT;
- wrb->payload_length = payload_len;
- wrb->tag0 = opcode;
- be_dws_cpu_to_le(wrb, 8);
-}
/* Don't touch the hdr after it's prepared */
-static void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
- u8 subsystem, u8 opcode, int cmd_len)
+/* mem will be NULL for embedded commands */
+static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
+ u8 subsystem, u8 opcode, int cmd_len,
+ struct be_mcc_wrb *wrb, struct be_dma_mem *mem)
{
+ struct be_sge *sge;
+
req_hdr->opcode = opcode;
req_hdr->subsystem = subsystem;
req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
req_hdr->version = 0;
+
+ wrb->tag0 = opcode;
+ wrb->tag1 = subsystem;
+ wrb->payload_length = cmd_len;
+ if (mem) {
+ wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
+ MCC_WRB_SGE_CNT_SHIFT;
+ sge = nonembedded_sgl(wrb);
+ sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
+ sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
+ sge->len = cpu_to_le32(mem->size);
+ } else
+ wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
+ be_dws_cpu_to_le(wrb, 8);
}
static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
@@ -594,10 +591,8 @@ int be_cmd_eq_create(struct be_adapter *adapter,
wrb = wrb_from_mbox(adapter);
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_COMMON_EQ_CREATE);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_EQ_CREATE, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_EQ_CREATE, sizeof(*req), wrb, NULL);
req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
@@ -623,7 +618,7 @@ int be_cmd_eq_create(struct be_adapter *adapter,
return status;
}
-/* Uses mbox */
+/* Use MCC */
int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
u8 type, bool permanent, u32 if_handle)
{
@@ -631,18 +626,17 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
struct be_cmd_req_mac_query *req;
int status;
- if (mutex_lock_interruptible(&adapter->mbox_lock))
- return -1;
+ spin_lock_bh(&adapter->mcc_lock);
- wrb = wrb_from_mbox(adapter);
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_NTWK_MAC_QUERY);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req));
-
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb, NULL);
req->type = type;
if (permanent) {
req->permanent = 1;
@@ -651,13 +645,14 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
req->permanent = 0;
}
- status = be_mbox_notify_wait(adapter);
+ status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
}
- mutex_unlock(&adapter->mbox_lock);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -678,11 +673,8 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_NTWK_PMAC_ADD);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req), wrb, NULL);
req->hdr.domain = domain;
req->if_id = cpu_to_le32(if_id);
@@ -696,6 +688,10 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
err:
spin_unlock_bh(&adapter->mcc_lock);
+
+ if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
+ status = -EPERM;
+
return status;
}
@@ -715,11 +711,8 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id, u32 dom)
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_NTWK_PMAC_DEL);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req), wrb, NULL);
req->hdr.domain = dom;
req->if_id = cpu_to_le32(if_id);
@@ -750,11 +743,8 @@ int be_cmd_cq_create(struct be_adapter *adapter,
req = embedded_payload(wrb);
ctxt = &req->context;
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_CQ_CREATE);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_CQ_CREATE, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_CQ_CREATE, sizeof(*req), wrb, NULL);
req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
if (lancer_chip(adapter)) {
@@ -826,11 +816,8 @@ int be_cmd_mccq_ext_create(struct be_adapter *adapter,
req = embedded_payload(wrb);
ctxt = &req->context;
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_MCC_CREATE_EXT);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req), wrb, NULL);
req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
if (lancer_chip(adapter)) {
@@ -886,11 +873,8 @@ int be_cmd_mccq_org_create(struct be_adapter *adapter,
req = embedded_payload(wrb);
ctxt = &req->context;
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_MCC_CREATE);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_MCC_CREATE, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_MCC_CREATE, sizeof(*req), wrb, NULL);
req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
@@ -947,11 +931,8 @@ int be_cmd_txq_create(struct be_adapter *adapter,
req = embedded_payload(wrb);
ctxt = &req->context;
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_ETH_TX_CREATE);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_TX_CREATE,
- sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
+ OPCODE_ETH_TX_CREATE, sizeof(*req), wrb, NULL);
if (lancer_chip(adapter)) {
req->hdr.version = 1;
@@ -1003,11 +984,8 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_ETH_RX_CREATE);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_CREATE,
- sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
+ OPCODE_ETH_RX_CREATE, sizeof(*req), wrb, NULL);
req->cq_id = cpu_to_le16(cq_id);
req->frag_size = fls(frag_size) - 1;
@@ -1075,9 +1053,8 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
BUG();
}
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, opcode);
-
- be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req), wrb,
+ NULL);
req->id = cpu_to_le16(q->id);
status = be_mbox_notify_wait(adapter);
@@ -1104,9 +1081,8 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_RX_DESTROY);
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_DESTROY,
- sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
+ OPCODE_ETH_RX_DESTROY, sizeof(*req), wrb, NULL);
req->id = cpu_to_le16(q->id);
status = be_mcc_notify_wait(adapter);
@@ -1119,48 +1095,48 @@ err:
}
/* Create an rx filtering policy configuration on an i/f
- * Uses mbox
+ * Uses MCCQ
*/
int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
- u8 *mac, bool pmac_invalid, u32 *if_handle, u32 *pmac_id,
- u32 domain)
+ u8 *mac, u32 *if_handle, u32 *pmac_id, u32 domain)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_if_create *req;
int status;
- if (mutex_lock_interruptible(&adapter->mbox_lock))
- return -1;
+ spin_lock_bh(&adapter->mcc_lock);
- wrb = wrb_from_mbox(adapter);
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_NTWK_INTERFACE_CREATE);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req));
-
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req), wrb, NULL);
req->hdr.domain = domain;
req->capability_flags = cpu_to_le32(cap_flags);
req->enable_flags = cpu_to_le32(en_flags);
- req->pmac_invalid = pmac_invalid;
- if (!pmac_invalid)
+ if (mac)
memcpy(req->mac_addr, mac, ETH_ALEN);
+ else
+ req->pmac_invalid = true;
- status = be_mbox_notify_wait(adapter);
+ status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_if_create *resp = embedded_payload(wrb);
*if_handle = le32_to_cpu(resp->interface_id);
- if (!pmac_invalid)
+ if (mac)
*pmac_id = le32_to_cpu(resp->pmac_id);
}
- mutex_unlock(&adapter->mbox_lock);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
return status;
}
-/* Uses mbox */
+/* Uses MCCQ */
int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain)
{
struct be_mcc_wrb *wrb;
@@ -1170,25 +1146,26 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain)
if (adapter->eeh_err)
return -EIO;
- if (mutex_lock_interruptible(&adapter->mbox_lock))
- return -1;
-
- wrb = wrb_from_mbox(adapter);
- req = embedded_payload(wrb);
+ if (!interface_id)
+ return 0;
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_NTWK_INTERFACE_DESTROY);
+ spin_lock_bh(&adapter->mcc_lock);
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req));
+ 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_NTWK_INTERFACE_DESTROY, sizeof(*req), wrb, NULL);
req->hdr.domain = domain;
req->interface_id = cpu_to_le32(interface_id);
- status = be_mbox_notify_wait(adapter);
-
- mutex_unlock(&adapter->mbox_lock);
-
+ status = be_mcc_notify_wait(adapter);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1200,7 +1177,6 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_hdr *hdr;
- struct be_sge *sge;
int status = 0;
if (MODULO(adapter->work_counter, be_get_temp_freq) == 0)
@@ -1214,22 +1190,13 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
goto err;
}
hdr = nonemb_cmd->va;
- sge = nonembedded_sgl(wrb);
-
- be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1,
- OPCODE_ETH_GET_STATISTICS);
- be_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
- OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size);
+ be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
+ OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, nonemb_cmd);
if (adapter->generation == BE_GEN3)
hdr->version = 1;
- wrb->tag1 = CMD_SUBSYSTEM_ETH;
- sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
- sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(nonemb_cmd->size);
-
be_mcc_notify(adapter);
adapter->stats_cmd_sent = true;
@@ -1245,7 +1212,6 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
struct be_mcc_wrb *wrb;
struct lancer_cmd_req_pport_stats *req;
- struct be_sge *sge;
int status = 0;
spin_lock_bh(&adapter->mcc_lock);
@@ -1256,23 +1222,14 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
goto err;
}
req = nonemb_cmd->va;
- sge = nonembedded_sgl(wrb);
-
- be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1,
- OPCODE_ETH_GET_PPORT_STATS);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
- OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
+ OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size, wrb,
+ nonemb_cmd);
req->cmd_params.params.pport_num = cpu_to_le16(adapter->port_num);
req->cmd_params.params.reset_stats = 0;
- wrb->tag1 = CMD_SUBSYSTEM_ETH;
- sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
- sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(nonemb_cmd->size);
-
be_mcc_notify(adapter);
adapter->stats_cmd_sent = true;
@@ -1282,8 +1239,8 @@ err:
}
/* Uses synchronous mcc */
-int be_cmd_link_status_query(struct be_adapter *adapter,
- bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom)
+int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
+ u16 *link_speed, u32 dom)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_link_status *req;
@@ -1298,21 +1255,16 @@ int be_cmd_link_status_query(struct be_adapter *adapter,
}
req = embedded_payload(wrb);
- *link_up = false;
-
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_NTWK_LINK_STATUS_QUERY);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL);
status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
if (resp->mac_speed != PHY_LINK_SPEED_ZERO) {
- *link_up = true;
*link_speed = le16_to_cpu(resp->link_speed);
- *mac_speed = resp->mac_speed;
+ if (mac_speed)
+ *mac_speed = resp->mac_speed;
}
}
@@ -1326,10 +1278,13 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_cntl_addnl_attribs *req;
+ u16 mccq_index;
int status;
spin_lock_bh(&adapter->mcc_lock);
+ mccq_index = adapter->mcc_obj.q.head;
+
wrb = wrb_from_mccq(adapter);
if (!wrb) {
status = -EBUSY;
@@ -1337,22 +1292,13 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req),
+ wrb, NULL);
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req));
+ wrb->tag1 = mccq_index;
- status = be_mcc_notify_wait(adapter);
- if (!status) {
- struct be_cmd_resp_get_cntl_addnl_attribs *resp =
- embedded_payload(wrb);
- adapter->drv_stats.be_on_die_temperature =
- resp->on_die_temperature;
- }
- /* If IOCTL fails once, do not bother issuing it again */
- else
- be_get_temp_freq = 0;
+ be_mcc_notify(adapter);
err:
spin_unlock_bh(&adapter->mcc_lock);
@@ -1375,11 +1321,8 @@ int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size)
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_MANAGE_FAT);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_MANAGE_FAT, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_MANAGE_FAT, sizeof(*req), wrb, NULL);
req->fat_operation = cpu_to_le32(QUERY_FAT);
status = be_mcc_notify_wait(adapter);
if (!status) {
@@ -1398,7 +1341,6 @@ void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf)
struct be_dma_mem get_fat_cmd;
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_fat *req;
- struct be_sge *sge;
u32 offset = 0, total_size, buf_size,
log_offset = sizeof(u32), payload_len;
int status;
@@ -1431,18 +1373,11 @@ void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf)
goto err;
}
req = get_fat_cmd.va;
- sge = nonembedded_sgl(wrb);
payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size;
- be_wrb_hdr_prepare(wrb, payload_len, false, 1,
- OPCODE_COMMON_MANAGE_FAT);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_MANAGE_FAT, payload_len);
-
- sge->pa_hi = cpu_to_le32(upper_32_bits(get_fat_cmd.dma));
- sge->pa_lo = cpu_to_le32(get_fat_cmd.dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(get_fat_cmd.size);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_MANAGE_FAT, payload_len, wrb,
+ &get_fat_cmd);
req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
req->read_log_offset = cpu_to_le32(log_offset);
@@ -1454,7 +1389,7 @@ void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf)
struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
memcpy(buf + offset,
resp->data_buffer,
- resp->read_log_length);
+ le32_to_cpu(resp->read_log_length));
} else {
dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
goto err;
@@ -1469,32 +1404,35 @@ err:
spin_unlock_bh(&adapter->mcc_lock);
}
-/* Uses Mbox */
-int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
+/* Uses synchronous mcc */
+int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
+ char *fw_on_flash)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_fw_version *req;
int status;
- if (mutex_lock_interruptible(&adapter->mbox_lock))
- return -1;
-
- wrb = wrb_from_mbox(adapter);
- req = embedded_payload(wrb);
+ spin_lock_bh(&adapter->mcc_lock);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_GET_FW_VERSION);
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_FW_VERSION, sizeof(*req));
+ req = embedded_payload(wrb);
- status = be_mbox_notify_wait(adapter);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_FW_VERSION, sizeof(*req), wrb, NULL);
+ status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
- strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN);
+ strcpy(fw_ver, resp->firmware_version_string);
+ if (fw_on_flash)
+ strcpy(fw_on_flash, resp->fw_on_flash_version_string);
}
-
- mutex_unlock(&adapter->mbox_lock);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
return status;
}
@@ -1516,11 +1454,8 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd)
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_MODIFY_EQ_DELAY);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req), wrb, NULL);
req->num_eq = cpu_to_le32(1);
req->delay[0].eq_id = cpu_to_le32(eq_id);
@@ -1551,11 +1486,8 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_NTWK_VLAN_CONFIG);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req), wrb, NULL);
req->interface_id = if_id;
req->promiscuous = promiscuous;
@@ -1573,27 +1505,13 @@ err:
return status;
}
-/* Uses MCC for this command as it may be called in BH context
- * Uses synchronous mcc
- */
-int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en)
+int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
{
struct be_mcc_wrb *wrb;
- struct be_cmd_req_rx_filter *req;
- struct be_dma_mem promiscous_cmd;
- struct be_sge *sge;
+ struct be_dma_mem *mem = &adapter->rx_filter;
+ struct be_cmd_req_rx_filter *req = mem->va;
int status;
- memset(&promiscous_cmd, 0, sizeof(struct be_dma_mem));
- promiscous_cmd.size = sizeof(struct be_cmd_req_rx_filter);
- promiscous_cmd.va = pci_alloc_consistent(adapter->pdev,
- promiscous_cmd.size, &promiscous_cmd.dma);
- if (!promiscous_cmd.va) {
- dev_err(&adapter->pdev->dev,
- "Memory allocation failure\n");
- return -ENOMEM;
- }
-
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
@@ -1601,80 +1519,33 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en)
status = -EBUSY;
goto err;
}
-
- req = promiscous_cmd.va;
- sge = nonembedded_sgl(wrb);
-
- be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
- OPCODE_COMMON_NTWK_RX_FILTER);
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req));
-
- req->if_id = cpu_to_le32(adapter->if_handle);
- req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS);
- if (en)
- req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS);
-
- sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma));
- sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(promiscous_cmd.size);
-
- status = be_mcc_notify_wait(adapter);
-
-err:
- spin_unlock_bh(&adapter->mcc_lock);
- pci_free_consistent(adapter->pdev, promiscous_cmd.size,
- promiscous_cmd.va, promiscous_cmd.dma);
- return status;
-}
-
-/*
- * Uses MCC for this command as it may be called in BH context
- * (mc == NULL) => multicast promiscuous
- */
-int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
- struct net_device *netdev, struct be_dma_mem *mem)
-{
- struct be_mcc_wrb *wrb;
- struct be_cmd_req_mcast_mac_config *req = mem->va;
- struct be_sge *sge;
- int status;
-
- spin_lock_bh(&adapter->mcc_lock);
-
- wrb = wrb_from_mccq(adapter);
- if (!wrb) {
- status = -EBUSY;
- goto err;
- }
- sge = nonembedded_sgl(wrb);
memset(req, 0, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req),
+ wrb, mem);
- be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
- OPCODE_COMMON_NTWK_MULTICAST_SET);
- sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
- sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(mem->size);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req));
-
- req->interface_id = if_id;
- if (netdev) {
- int i;
+ req->if_id = cpu_to_le32(adapter->if_handle);
+ if (flags & IFF_PROMISC) {
+ req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS |
+ BE_IF_FLAGS_VLAN_PROMISCUOUS);
+ if (value == ON)
+ req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS |
+ BE_IF_FLAGS_VLAN_PROMISCUOUS);
+ } else if (flags & IFF_ALLMULTI) {
+ req->if_flags_mask = req->if_flags =
+ cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
+ } else {
struct netdev_hw_addr *ha;
+ int i = 0;
- req->num_mac = cpu_to_le16(netdev_mc_count(netdev));
-
- i = 0;
- netdev_for_each_mc_addr(ha, netdev)
- memcpy(req->mac[i++].byte, ha->addr, ETH_ALEN);
- } else {
- req->promiscuous = 1;
+ req->if_flags_mask = req->if_flags =
+ cpu_to_le32(BE_IF_FLAGS_MULTICAST);
+ req->mcast_num = cpu_to_le16(netdev_mc_count(adapter->netdev));
+ netdev_for_each_mc_addr(ha, adapter->netdev)
+ memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN);
}
status = be_mcc_notify_wait(adapter);
-
err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
@@ -1696,11 +1567,8 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_SET_FLOW_CONTROL);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req), wrb, NULL);
req->tx_flow_control = cpu_to_le16((u16)tx_fc);
req->rx_flow_control = cpu_to_le16((u16)rx_fc);
@@ -1728,11 +1596,8 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_GET_FLOW_CONTROL);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req), wrb, NULL);
status = be_mcc_notify_wait(adapter);
if (!status) {
@@ -1761,11 +1626,8 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
wrb = wrb_from_mbox(adapter);
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_QUERY_FIRMWARE_CONFIG);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req), wrb, NULL);
status = be_mbox_notify_wait(adapter);
if (!status) {
@@ -1792,11 +1654,8 @@ int be_cmd_reset_function(struct be_adapter *adapter)
wrb = wrb_from_mbox(adapter);
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_FUNCTION_RESET);
-
- be_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_FUNCTION_RESET, sizeof(*req), wrb, NULL);
status = be_mbox_notify_wait(adapter);
@@ -1818,11 +1677,8 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
wrb = wrb_from_mbox(adapter);
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_ETH_RSS_CONFIG);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
- OPCODE_ETH_RSS_CONFIG, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
+ OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL);
req->if_id = cpu_to_le32(adapter->if_handle);
req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4);
@@ -1854,11 +1710,8 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_ENABLE_DISABLE_BEACON);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_ENABLE_DISABLE_BEACON, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_ENABLE_DISABLE_BEACON, sizeof(*req), wrb, NULL);
req->port_num = port_num;
req->beacon_state = state;
@@ -1888,11 +1741,8 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_GET_BEACON_STATE);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req), wrb, NULL);
req->port_num = port_num;
@@ -1929,13 +1779,10 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(struct lancer_cmd_req_write_object),
- true, 1, OPCODE_COMMON_WRITE_OBJECT);
- wrb->tag1 = CMD_SUBSYSTEM_COMMON;
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_WRITE_OBJECT,
- sizeof(struct lancer_cmd_req_write_object));
+ sizeof(struct lancer_cmd_req_write_object), wrb,
+ NULL);
ctxt = &req->context;
AMAP_SET_BITS(struct amap_lancer_write_obj_context,
@@ -1988,7 +1835,6 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
{
struct be_mcc_wrb *wrb;
struct be_cmd_write_flashrom *req;
- struct be_sge *sge;
int status;
spin_lock_bh(&adapter->mcc_lock);
@@ -2000,17 +1846,9 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
goto err_unlock;
}
req = cmd->va;
- sge = nonembedded_sgl(wrb);
- be_wrb_hdr_prepare(wrb, cmd->size, false, 1,
- OPCODE_COMMON_WRITE_FLASHROM);
- wrb->tag1 = CMD_SUBSYSTEM_COMMON;
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_WRITE_FLASHROM, cmd->size);
- sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
- sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(cmd->size);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_WRITE_FLASHROM, cmd->size, wrb, cmd);
req->params.op_type = cpu_to_le32(flash_type);
req->params.op_code = cpu_to_le32(flash_opcode);
@@ -2020,7 +1858,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
spin_unlock_bh(&adapter->mcc_lock);
if (!wait_for_completion_timeout(&adapter->flash_compl,
- msecs_to_jiffies(12000)))
+ msecs_to_jiffies(40000)))
status = -1;
else
status = adapter->flash_status;
@@ -2048,11 +1886,8 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
}
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req)+4, true, 0,
- OPCODE_COMMON_READ_FLASHROM);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL);
req->params.op_type = cpu_to_le32(IMG_TYPE_REDBOOT);
req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
@@ -2073,7 +1908,6 @@ int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_acpi_wol_magic_config *req;
- struct be_sge *sge;
int status;
spin_lock_bh(&adapter->mcc_lock);
@@ -2084,19 +1918,12 @@ int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
goto err;
}
req = nonemb_cmd->va;
- sge = nonembedded_sgl(wrb);
-
- be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
- OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG);
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
- OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
+ OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req), wrb,
+ nonemb_cmd);
memcpy(req->magic_mac, mac, ETH_ALEN);
- sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
- sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(nonemb_cmd->size);
-
status = be_mcc_notify_wait(adapter);
err:
@@ -2121,12 +1948,9 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_LOWLEVEL_SET_LOOPBACK_MODE);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
- OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
- sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
+ OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, sizeof(*req), wrb,
+ NULL);
req->src_port = port_num;
req->dest_port = port_num;
@@ -2156,11 +1980,8 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_LOWLEVEL_LOOPBACK_TEST);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
- OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
+ OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb, NULL);
req->hdr.timeout = cpu_to_le32(4);
req->pattern = cpu_to_le64(pattern);
@@ -2186,7 +2007,6 @@ int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_ddrdma_test *req;
- struct be_sge *sge;
int status;
int i, j = 0;
@@ -2198,15 +2018,8 @@ int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
goto err;
}
req = cmd->va;
- sge = nonembedded_sgl(wrb);
- be_wrb_hdr_prepare(wrb, cmd->size, false, 1,
- OPCODE_LOWLEVEL_HOST_DDR_DMA);
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
- OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size);
-
- sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
- sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(cmd->size);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
+ OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size, wrb, cmd);
req->pattern = cpu_to_le64(pattern);
req->byte_count = cpu_to_le32(byte_cnt);
@@ -2251,15 +2064,9 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter,
req = nonemb_cmd->va;
sge = nonembedded_sgl(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
- OPCODE_COMMON_SEEPROM_READ);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_SEEPROM_READ, sizeof(*req));
-
- sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
- sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(nonemb_cmd->size);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_SEEPROM_READ, sizeof(*req), wrb,
+ nonemb_cmd);
status = be_mcc_notify_wait(adapter);
@@ -2268,11 +2075,12 @@ err:
return status;
}
-int be_cmd_get_phy_info(struct be_adapter *adapter, struct be_dma_mem *cmd)
+int be_cmd_get_phy_info(struct be_adapter *adapter,
+ struct be_phy_info *phy_info)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_phy_info *req;
- struct be_sge *sge;
+ struct be_dma_mem cmd;
int status;
spin_lock_bh(&adapter->mcc_lock);
@@ -2282,22 +2090,31 @@ int be_cmd_get_phy_info(struct be_adapter *adapter, struct be_dma_mem *cmd)
status = -EBUSY;
goto err;
}
+ cmd.size = sizeof(struct be_cmd_req_get_phy_info);
+ cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+ &cmd.dma);
+ if (!cmd.va) {
+ dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+ status = -ENOMEM;
+ goto err;
+ }
- req = cmd->va;
- sge = nonembedded_sgl(wrb);
-
- be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
- OPCODE_COMMON_GET_PHY_DETAILS);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_PHY_DETAILS,
- sizeof(*req));
+ req = cmd.va;
- sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
- sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(cmd->size);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_PHY_DETAILS, sizeof(*req),
+ wrb, &cmd);
status = be_mcc_notify_wait(adapter);
+ if (!status) {
+ struct be_phy_info *resp_phy_info =
+ cmd.va + sizeof(struct be_cmd_req_hdr);
+ phy_info->phy_type = le16_to_cpu(resp_phy_info->phy_type);
+ phy_info->interface_type =
+ le16_to_cpu(resp_phy_info->interface_type);
+ }
+ pci_free_consistent(adapter->pdev, cmd.size,
+ cmd.va, cmd.dma);
err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
@@ -2319,11 +2136,8 @@ int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain)
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_SET_QOS);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_SET_QOS, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_SET_QOS, sizeof(*req), wrb, NULL);
req->hdr.domain = domain;
req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC);
@@ -2341,7 +2155,6 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
struct be_mcc_wrb *wrb;
struct be_cmd_req_cntl_attribs *req;
struct be_cmd_resp_cntl_attribs *resp;
- struct be_sge *sge;
int status;
int payload_len = max(sizeof(*req), sizeof(*resp));
struct mgmt_controller_attrib *attribs;
@@ -2366,15 +2179,10 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
goto err;
}
req = attribs_cmd.va;
- sge = nonembedded_sgl(wrb);
- be_wrb_hdr_prepare(wrb, payload_len, false, 1,
- OPCODE_COMMON_GET_CNTL_ATTRIBUTES);
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len);
- sge->pa_hi = cpu_to_le32(upper_32_bits(attribs_cmd.dma));
- sge->pa_lo = cpu_to_le32(attribs_cmd.dma & 0xFFFFFFFF);
- sge->len = cpu_to_le32(attribs_cmd.size);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len, wrb,
+ &attribs_cmd);
status = be_mbox_notify_wait(adapter);
if (!status) {
@@ -2407,11 +2215,8 @@ int be_cmd_req_native_mode(struct be_adapter *adapter)
req = embedded_payload(wrb);
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP);
-
- be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP, sizeof(*req));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP, sizeof(*req), wrb, NULL);
req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS |
CAPABILITY_BE3_NATIVE_ERX_API);
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 8e4d48824fe9..a35cd03fac4e 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -89,9 +89,10 @@ struct be_async_event_trailer {
};
enum {
- ASYNC_EVENT_LINK_DOWN = 0x0,
- ASYNC_EVENT_LINK_UP = 0x1
+ LINK_DOWN = 0x0,
+ LINK_UP = 0x1
};
+#define LINK_STATUS_MASK 0x1
/* When the event code of an async trailer is link-state, the mcc_compl
* must be interpreted as follows
@@ -693,8 +694,7 @@ struct be_cmd_resp_get_stats_v0 {
struct be_hw_stats_v0 hw_stats;
};
-#define make_64bit_val(hi_32, lo_32) (((u64)hi_32<<32) | lo_32)
-struct lancer_cmd_pport_stats {
+struct lancer_pport_stats {
u32 tx_packets_lo;
u32 tx_packets_hi;
u32 tx_unicast_packets_lo;
@@ -871,16 +871,16 @@ struct lancer_cmd_req_pport_stats {
struct be_cmd_req_hdr hdr;
union {
struct pport_stats_params params;
- u8 rsvd[sizeof(struct lancer_cmd_pport_stats)];
+ u8 rsvd[sizeof(struct lancer_pport_stats)];
} cmd_params;
};
struct lancer_cmd_resp_pport_stats {
struct be_cmd_resp_hdr hdr;
- struct lancer_cmd_pport_stats pport_stats;
+ struct lancer_pport_stats pport_stats;
};
-static inline struct lancer_cmd_pport_stats*
+static inline struct lancer_pport_stats*
pport_stats_from_cmd(struct be_adapter *adapter)
{
struct lancer_cmd_resp_pport_stats *cmd = adapter->stats_cmd.va;
@@ -910,21 +910,12 @@ struct be_cmd_req_vlan_config {
u16 normal_vlan[64];
} __packed;
-/******************** Multicast MAC Config *******************/
+/******************* RX FILTER ******************************/
#define BE_MAX_MC 64 /* set mcast promisc if > 64 */
struct macaddr {
u8 byte[ETH_ALEN];
};
-struct be_cmd_req_mcast_mac_config {
- struct be_cmd_req_hdr hdr;
- u16 num_mac;
- u8 promiscuous;
- u8 interface_id;
- struct macaddr mac[BE_MAX_MC];
-} __packed;
-
-/******************* RX FILTER ******************************/
struct be_cmd_req_rx_filter {
struct be_cmd_req_hdr hdr;
u32 global_flags_mask;
@@ -932,11 +923,10 @@ struct be_cmd_req_rx_filter {
u32 if_flags_mask;
u32 if_flags;
u32 if_id;
- u32 multicast_num;
- struct macaddr mac[BE_MAX_MC];
+ u32 mcast_num;
+ struct macaddr mcast_mac[BE_MAX_MC];
};
-
/******************** Link Status Query *******************/
struct be_cmd_req_link_status {
struct be_cmd_req_hdr hdr;
@@ -1056,6 +1046,12 @@ struct be_cmd_resp_modify_eq_delay {
/******************** Get FW Config *******************/
#define BE_FUNCTION_CAPS_RSS 0x2
+/* The HW can come up in either of the following multi-channel modes
+ * based on the skew/IPL.
+ */
+#define FLEX10_MODE 0x400
+#define VNIC_MODE 0x20000
+#define UMC_ENABLED 0x1000000
struct be_cmd_req_query_fw_cfg {
struct be_cmd_req_hdr hdr;
u32 rsvd[31];
@@ -1254,14 +1250,19 @@ struct be_cmd_req_get_phy_info {
struct be_cmd_req_hdr hdr;
u8 rsvd0[24];
};
-struct be_cmd_resp_get_phy_info {
- struct be_cmd_req_hdr hdr;
+
+struct be_phy_info {
u16 phy_type;
u16 interface_type;
u32 misc_params;
u32 future_use[4];
};
+struct be_cmd_resp_get_phy_info {
+ struct be_cmd_req_hdr hdr;
+ struct be_phy_info phy_info;
+};
+
/*********************** Set QOS ***********************/
#define BE_QOS_BITS_NIC 1
@@ -1383,8 +1384,7 @@ 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)
+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;
@@ -1397,34 +1397,6 @@ hw_stats_from_cmd(struct be_adapter *adapter)
}
}
-static inline void *be_port_rxf_stats_from_cmd(struct be_adapter *adapter)
-{
- if (adapter->generation == BE_GEN3) {
- struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
- struct be_rxf_stats_v1 *rxf_stats = &hw_stats->rxf;
-
- return &rxf_stats->port[adapter->port_num];
- } else {
- struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
- struct be_rxf_stats_v0 *rxf_stats = &hw_stats->rxf;
-
- return &rxf_stats->port[adapter->port_num];
- }
-}
-
-static inline void *be_rxf_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->rxf;
- } else {
- struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-
- return &hw_stats->rxf;
- }
-}
-
static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
{
if (adapter->generation == BE_GEN3) {
@@ -1438,19 +1410,6 @@ static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
}
}
-static inline void *be_pmem_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->pmem;
- } else {
- struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-
- return &hw_stats->pmem;
- }
-}
-
extern int be_pci_fnum_get(struct be_adapter *adapter);
extern int be_cmd_POST(struct be_adapter *adapter);
extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
@@ -1460,8 +1419,8 @@ extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id,
u32 pmac_id, u32 domain);
extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags,
- u32 en_flags, u8 *mac, bool pmac_invalid,
- u32 *if_handle, u32 *pmac_id, u32 domain);
+ u32 en_flags, u8 *mac, u32 *if_handle, u32 *pmac_id,
+ u32 domain);
extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle,
u32 domain);
extern int be_cmd_eq_create(struct be_adapter *adapter,
@@ -1485,21 +1444,20 @@ extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
struct be_queue_info *q);
extern int be_cmd_link_status_query(struct be_adapter *adapter,
- bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom);
+ u8 *mac_speed, u16 *link_speed, u32 dom);
extern int be_cmd_reset(struct be_adapter *adapter);
extern int be_cmd_get_stats(struct be_adapter *adapter,
struct be_dma_mem *nonemb_cmd);
extern int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
struct be_dma_mem *nonemb_cmd);
-extern int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver);
+extern int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
+ char *fw_on_flash);
extern int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd);
extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id,
u16 *vtag_array, u32 num, bool untagged,
bool promiscuous);
-extern int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en);
-extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
- struct net_device *netdev, struct be_dma_mem *mem);
+extern int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status);
extern int be_cmd_set_flow_control(struct be_adapter *adapter,
u32 tx_fc, u32 rx_fc);
extern int be_cmd_get_flow_control(struct be_adapter *adapter,
@@ -1540,7 +1498,7 @@ extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
u8 loopback_type, u8 enable);
extern int be_cmd_get_phy_info(struct be_adapter *adapter,
- struct be_dma_mem *cmd);
+ struct be_phy_info *phy_info);
extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
extern void be_detect_dump_ue(struct be_adapter *adapter);
extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 7fd8130d86ea..bf8153ea4ed8 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -26,33 +26,18 @@ struct be_ethtool_stat {
int offset;
};
-enum {NETSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT,
- DRVSTAT};
+enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT};
#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
offsetof(_struct, field)
-#define NETSTAT_INFO(field) #field, NETSTAT,\
- FIELDINFO(struct net_device_stats,\
- field)
#define DRVSTAT_TX_INFO(field) #field, DRVSTAT_TX,\
FIELDINFO(struct be_tx_stats, field)
#define DRVSTAT_RX_INFO(field) #field, DRVSTAT_RX,\
FIELDINFO(struct be_rx_stats, field)
-#define ERXSTAT_INFO(field) #field, ERXSTAT,\
- FIELDINFO(struct be_erx_stats_v1, field)
#define DRVSTAT_INFO(field) #field, DRVSTAT,\
- FIELDINFO(struct be_drv_stats, \
- field)
+ FIELDINFO(struct be_drv_stats, field)
static const struct be_ethtool_stat et_stats[] = {
- {NETSTAT_INFO(rx_packets)},
- {NETSTAT_INFO(tx_packets)},
- {NETSTAT_INFO(rx_bytes)},
- {NETSTAT_INFO(tx_bytes)},
- {NETSTAT_INFO(rx_errors)},
- {NETSTAT_INFO(tx_errors)},
- {NETSTAT_INFO(rx_dropped)},
- {NETSTAT_INFO(tx_dropped)},
- {DRVSTAT_INFO(be_tx_events)},
+ {DRVSTAT_INFO(tx_events)},
{DRVSTAT_INFO(rx_crc_errors)},
{DRVSTAT_INFO(rx_alignment_symbol_errors)},
{DRVSTAT_INFO(rx_pause_frames)},
@@ -71,9 +56,6 @@ static const struct be_ethtool_stat et_stats[] = {
{DRVSTAT_INFO(rx_ip_checksum_errs)},
{DRVSTAT_INFO(rx_tcp_checksum_errs)},
{DRVSTAT_INFO(rx_udp_checksum_errs)},
- {DRVSTAT_INFO(rx_switched_unicast_packets)},
- {DRVSTAT_INFO(rx_switched_multicast_packets)},
- {DRVSTAT_INFO(rx_switched_broadcast_packets)},
{DRVSTAT_INFO(tx_pauseframes)},
{DRVSTAT_INFO(tx_controlframes)},
{DRVSTAT_INFO(rx_priority_pause_frames)},
@@ -92,28 +74,33 @@ static const struct be_ethtool_stat et_stats[] = {
};
#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
-/* Stats related to multi RX queues */
+/* Stats related to multi RX queues: get_stats routine assumes bytes, pkts
+ * are first and second members respectively.
+ */
static const struct be_ethtool_stat et_rx_stats[] = {
- {DRVSTAT_RX_INFO(rx_bytes)},
- {DRVSTAT_RX_INFO(rx_pkts)},
- {DRVSTAT_RX_INFO(rx_rate)},
+ {DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */
+ {DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */
{DRVSTAT_RX_INFO(rx_polls)},
{DRVSTAT_RX_INFO(rx_events)},
{DRVSTAT_RX_INFO(rx_compl)},
{DRVSTAT_RX_INFO(rx_mcast_pkts)},
{DRVSTAT_RX_INFO(rx_post_fail)},
- {DRVSTAT_RX_INFO(rx_dropped)},
- {ERXSTAT_INFO(rx_drops_no_fragments)}
+ {DRVSTAT_RX_INFO(rx_drops_no_skbs)},
+ {DRVSTAT_RX_INFO(rx_drops_no_frags)}
};
#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
-/* Stats related to multi TX queues */
+/* Stats related to multi TX queues: get_stats routine assumes compl is the
+ * first member
+ */
static const struct be_ethtool_stat et_tx_stats[] = {
- {DRVSTAT_TX_INFO(be_tx_rate)},
- {DRVSTAT_TX_INFO(be_tx_reqs)},
- {DRVSTAT_TX_INFO(be_tx_wrbs)},
- {DRVSTAT_TX_INFO(be_tx_stops)},
- {DRVSTAT_TX_INFO(be_tx_compl)}
+ {DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */
+ {DRVSTAT_TX_INFO(tx_bytes)},
+ {DRVSTAT_TX_INFO(tx_pkts)},
+ {DRVSTAT_TX_INFO(tx_reqs)},
+ {DRVSTAT_TX_INFO(tx_wrbs)},
+ {DRVSTAT_TX_INFO(tx_compl)},
+ {DRVSTAT_TX_INFO(tx_stops)}
};
#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats))
@@ -131,14 +118,24 @@ static const char et_self_tests[][ETH_GSTRING_LEN] = {
#define BE_ONE_PORT_EXT_LOOPBACK 0x2
#define BE_NO_LOOPBACK 0xff
-static void
-be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+static void be_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
{
struct be_adapter *adapter = netdev_priv(netdev);
+ char fw_on_flash[FW_VER_LEN];
+
+ memset(fw_on_flash, 0 , sizeof(fw_on_flash));
+ be_cmd_get_fw_ver(adapter, adapter->fw_ver, fw_on_flash);
strcpy(drvinfo->driver, DRV_NAME);
strcpy(drvinfo->version, DRV_VER);
strncpy(drvinfo->fw_version, adapter->fw_ver, FW_VER_LEN);
+ if (memcmp(adapter->fw_ver, fw_on_flash, FW_VER_LEN) != 0) {
+ strcat(drvinfo->fw_version, " [");
+ strcat(drvinfo->fw_version, fw_on_flash);
+ strcat(drvinfo->fw_version, "]");
+ }
+
strcpy(drvinfo->bus_info, pci_name(adapter->pdev));
drvinfo->testinfo_len = 0;
drvinfo->regdump_len = 0;
@@ -260,50 +257,49 @@ be_get_ethtool_stats(struct net_device *netdev,
struct be_adapter *adapter = netdev_priv(netdev);
struct be_rx_obj *rxo;
struct be_tx_obj *txo;
- void *p = NULL;
- int i, j, base;
+ void *p;
+ unsigned int i, j, base = 0, start;
for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
- switch (et_stats[i].type) {
- case NETSTAT:
- p = &netdev->stats;
- break;
- case DRVSTAT:
- p = &adapter->drv_stats;
- break;
- }
-
- p = (u8 *)p + et_stats[i].offset;
- data[i] = (et_stats[i].size == sizeof(u64)) ?
- *(u64 *)p: *(u32 *)p;
+ p = (u8 *)&adapter->drv_stats + et_stats[i].offset;
+ data[i] = *(u32 *)p;
}
+ base += ETHTOOL_STATS_NUM;
- base = ETHTOOL_STATS_NUM;
for_all_rx_queues(adapter, rxo, j) {
- for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) {
- switch (et_rx_stats[i].type) {
- case DRVSTAT_RX:
- p = (u8 *)&rxo->stats + et_rx_stats[i].offset;
- break;
- case ERXSTAT:
- p = (u32 *)be_erx_stats_from_cmd(adapter) +
- rxo->q.id;
- break;
- }
- data[base + j * ETHTOOL_RXSTATS_NUM + i] =
- (et_rx_stats[i].size == sizeof(u64)) ?
- *(u64 *)p: *(u32 *)p;
+ struct be_rx_stats *stats = rx_stats(rxo);
+
+ do {
+ start = u64_stats_fetch_begin_bh(&stats->sync);
+ data[base] = stats->rx_bytes;
+ data[base + 1] = stats->rx_pkts;
+ } while (u64_stats_fetch_retry_bh(&stats->sync, start));
+
+ for (i = 2; i < ETHTOOL_RXSTATS_NUM; i++) {
+ p = (u8 *)stats + et_rx_stats[i].offset;
+ data[base + i] = *(u32 *)p;
}
+ base += ETHTOOL_RXSTATS_NUM;
}
- base = ETHTOOL_STATS_NUM + adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
for_all_tx_queues(adapter, txo, j) {
- for (i = 0; i < ETHTOOL_TXSTATS_NUM; i++) {
- p = (u8 *)&txo->stats + et_tx_stats[i].offset;
- data[base + j * ETHTOOL_TXSTATS_NUM + i] =
- (et_tx_stats[i].size == sizeof(u64)) ?
- *(u64 *)p: *(u32 *)p;
- }
+ struct be_tx_stats *stats = tx_stats(txo);
+
+ do {
+ start = u64_stats_fetch_begin_bh(&stats->sync_compl);
+ data[base] = stats->tx_compl;
+ } while (u64_stats_fetch_retry_bh(&stats->sync_compl, start));
+
+ do {
+ start = u64_stats_fetch_begin_bh(&stats->sync);
+ for (i = 1; i < ETHTOOL_TXSTATS_NUM; i++) {
+ p = (u8 *)stats + et_tx_stats[i].offset;
+ data[base + i] =
+ (et_tx_stats[i].size == sizeof(u64)) ?
+ *(u64 *)p : *(u32 *)p;
+ }
+ } while (u64_stats_fetch_retry_bh(&stats->sync, start));
+ base += ETHTOOL_TXSTATS_NUM;
}
}
@@ -363,19 +359,15 @@ static int be_get_sset_count(struct net_device *netdev, int stringset)
static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_dma_mem phy_cmd;
- struct be_cmd_resp_get_phy_info *resp;
+ struct be_phy_info phy_info;
u8 mac_speed = 0;
u16 link_speed = 0;
- bool link_up = false;
int status;
- u16 intf_type;
if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
- status = be_cmd_link_status_query(adapter, &link_up,
- &mac_speed, &link_speed, 0);
+ status = be_cmd_link_status_query(adapter, &mac_speed,
+ &link_speed, 0);
- be_link_status_update(adapter, link_up);
/* link_speed is in units of 10 Mbps */
if (link_speed) {
ethtool_cmd_speed_set(ecmd, link_speed*10);
@@ -399,20 +391,9 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
}
}
- phy_cmd.size = sizeof(struct be_cmd_req_get_phy_info);
- phy_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
- phy_cmd.size, &phy_cmd.dma,
- GFP_KERNEL);
- if (!phy_cmd.va) {
- dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
- return -ENOMEM;
- }
- status = be_cmd_get_phy_info(adapter, &phy_cmd);
+ status = be_cmd_get_phy_info(adapter, &phy_info);
if (!status) {
- resp = phy_cmd.va;
- intf_type = le16_to_cpu(resp->interface_type);
-
- switch (intf_type) {
+ switch (phy_info.interface_type) {
case PHY_TYPE_XFP_10GB:
case PHY_TYPE_SFP_1GB:
case PHY_TYPE_SFP_PLUS_10GB:
@@ -423,7 +404,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
break;
}
- switch (intf_type) {
+ switch (phy_info.interface_type) {
case PHY_TYPE_KR_10GB:
case PHY_TYPE_KX4_10GB:
ecmd->autoneg = AUTONEG_ENABLE;
@@ -441,8 +422,6 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
adapter->port_type = ecmd->port;
adapter->transceiver = ecmd->transceiver;
adapter->autoneg = ecmd->autoneg;
- dma_free_coherent(&adapter->pdev->dev, phy_cmd.size, phy_cmd.va,
- phy_cmd.dma);
} else {
ethtool_cmd_speed_set(ecmd, adapter->link_speed);
ecmd->port = adapter->port_type;
@@ -631,7 +610,6 @@ static void
be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
{
struct be_adapter *adapter = netdev_priv(netdev);
- bool link_up;
u8 mac_speed = 0;
u16 qos_link_speed = 0;
@@ -657,7 +635,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
test->flags |= ETH_TEST_FL_FAILED;
}
- if (be_cmd_link_status_query(adapter, &link_up, &mac_speed,
+ if (be_cmd_link_status_query(adapter, &mac_speed,
&qos_link_speed, 0) != 0) {
test->flags |= ETH_TEST_FL_FAILED;
data[4] = -1;
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index 53d658afea2a..fbc8a915519e 100644
--- a/drivers/net/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -175,18 +175,24 @@
#define IMG_TYPE_FCOE_FW_ACTIVE 10
#define IMG_TYPE_FCOE_FW_BACKUP 11
#define IMG_TYPE_NCSI_FW 13
+#define IMG_TYPE_PHY_FW 99
+#define TN_8022 13
+#define ILLEGAL_IOCTL_REQ 2
+#define FLASHROM_OPER_PHY_FLASH 9
+#define FLASHROM_OPER_PHY_SAVE 10
#define FLASHROM_OPER_FLASH 1
#define FLASHROM_OPER_SAVE 2
#define FLASHROM_OPER_REPORT 4
-#define FLASH_IMAGE_MAX_SIZE_g2 (1310720) /* Max firmware image sz */
-#define FLASH_BIOS_IMAGE_MAX_SIZE_g2 (262144) /* Max OPTION ROM img sz */
-#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g2 (262144) /* Max Redboot image sz */
-#define FLASH_IMAGE_MAX_SIZE_g3 (2097152) /* Max fw image size */
-#define FLASH_BIOS_IMAGE_MAX_SIZE_g3 (524288) /* Max OPTION ROM img sz */
-#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g3 (1048576) /* Max Redboot image sz */
-#define FLASH_NCSI_IMAGE_MAX_SIZE_g3 (262144) /* Max NSCI image sz */
+#define FLASH_IMAGE_MAX_SIZE_g2 (1310720) /* Max firmware image size */
+#define FLASH_BIOS_IMAGE_MAX_SIZE_g2 (262144) /* Max OPTION ROM image sz */
+#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g2 (262144) /* Max Redboot image sz */
+#define FLASH_IMAGE_MAX_SIZE_g3 (2097152) /* Max firmware image size */
+#define FLASH_BIOS_IMAGE_MAX_SIZE_g3 (524288) /* Max OPTION ROM image sz */
+#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g3 (1048576) /* Max Redboot image sz */
+#define FLASH_NCSI_IMAGE_MAX_SIZE_g3 (262144)
+#define FLASH_PHY_FW_IMAGE_MAX_SIZE_g3 262144
#define FLASH_NCSI_MAGIC (0x16032009)
#define FLASH_NCSI_DISABLED (0)
@@ -213,6 +219,7 @@
#define FLASH_PXE_BIOS_START_g3 (13107200)
#define FLASH_FCoE_BIOS_START_g3 (13631488)
#define FLASH_REDBOOT_START_g3 (262144)
+#define FLASH_PHY_FW_START_g3 1310720
/************* Rx Packet Type Encoding **************/
#define BE_UNICAST_PACKET 0
diff --git a/drivers/net/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index c411bb1845fd..21804972fa2f 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -114,6 +114,13 @@ static const char * const ue_status_hi_desc[] = {
"Unknown"
};
+/* Is BE in a multi-channel mode */
+static inline bool be_is_mc(struct be_adapter *adapter) {
+ return (adapter->function_mode & FLEX10_MODE ||
+ adapter->function_mode & VNIC_MODE ||
+ adapter->function_mode & UMC_ENABLED);
+}
+
static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q)
{
struct be_dma_mem *mem = &q->dma_mem;
@@ -141,13 +148,15 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
static void be_intr_set(struct be_adapter *adapter, bool enable)
{
- u8 __iomem *addr = adapter->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
- u32 reg = ioread32(addr);
- u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
+ u32 reg, enabled;
if (adapter->eeh_err)
return;
+ pci_read_config_dword(adapter->pdev, PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET,
+ &reg);
+ enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
+
if (!enabled && enable)
reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
else if (enabled && !enable)
@@ -155,7 +164,8 @@ static void be_intr_set(struct be_adapter *adapter, bool enable)
else
return;
- iowrite32(reg, addr);
+ pci_write_config_dword(adapter->pdev,
+ PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, reg);
}
static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted)
@@ -219,40 +229,42 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
struct be_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
int status = 0;
+ u8 current_mac[ETH_ALEN];
+ u32 pmac_id = adapter->pmac_id;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- /* MAC addr configuration will be done in hardware for VFs
- * by their corresponding PFs. Just copy to netdev addr here
- */
- if (!be_physfn(adapter))
- goto netdev_addr;
-
- status = be_cmd_pmac_del(adapter, adapter->if_handle,
- adapter->pmac_id, 0);
+ status = be_cmd_mac_addr_query(adapter, current_mac,
+ MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle);
if (status)
- return status;
+ goto err;
- status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
+ 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);
-netdev_addr:
- if (!status)
- memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ if (status)
+ goto err;
+ be_cmd_pmac_del(adapter, adapter->if_handle, pmac_id, 0);
+ }
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ return 0;
+err:
+ dev_err(&adapter->pdev->dev, "MAC %pM set Failed\n", addr->sa_data);
return status;
}
static void populate_be2_stats(struct be_adapter *adapter)
{
-
- struct be_drv_stats *drvs = &adapter->drv_stats;
- struct be_pmem_stats *pmem_sts = be_pmem_stats_from_cmd(adapter);
+ struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
+ struct be_pmem_stats *pmem_sts = &hw_stats->pmem;
+ struct be_rxf_stats_v0 *rxf_stats = &hw_stats->rxf;
struct be_port_rxf_stats_v0 *port_stats =
- be_port_rxf_stats_from_cmd(adapter);
- struct be_rxf_stats_v0 *rxf_stats =
- be_rxf_stats_from_cmd(adapter);
+ &rxf_stats->port[adapter->port_num];
+ struct be_drv_stats *drvs = &adapter->drv_stats;
+ be_dws_le_to_cpu(hw_stats, sizeof(*hw_stats));
drvs->rx_pause_frames = port_stats->rx_pause_frames;
drvs->rx_crc_errors = port_stats->rx_crc_errors;
drvs->rx_control_frames = port_stats->rx_control_frames;
@@ -267,12 +279,10 @@ static void populate_be2_stats(struct be_adapter *adapter)
drvs->rx_dropped_too_small = port_stats->rx_dropped_too_small;
drvs->rx_dropped_too_short = port_stats->rx_dropped_too_short;
drvs->rx_out_range_errors = port_stats->rx_out_range_errors;
- drvs->rx_input_fifo_overflow_drop =
- port_stats->rx_input_fifo_overflow;
+ drvs->rx_input_fifo_overflow_drop = port_stats->rx_input_fifo_overflow;
drvs->rx_dropped_header_too_small =
port_stats->rx_dropped_header_too_small;
- drvs->rx_address_match_errors =
- port_stats->rx_address_match_errors;
+ drvs->rx_address_match_errors = port_stats->rx_address_match_errors;
drvs->rx_alignment_symbol_errors =
port_stats->rx_alignment_symbol_errors;
@@ -280,36 +290,30 @@ static void populate_be2_stats(struct be_adapter *adapter)
drvs->tx_controlframes = port_stats->tx_controlframes;
if (adapter->port_num)
- drvs->jabber_events =
- rxf_stats->port1_jabber_events;
+ drvs->jabber_events = rxf_stats->port1_jabber_events;
else
- drvs->jabber_events =
- rxf_stats->port0_jabber_events;
+ drvs->jabber_events = rxf_stats->port0_jabber_events;
drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf;
drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb;
drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr;
drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring;
drvs->forwarded_packets = rxf_stats->forwarded_packets;
drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu;
- drvs->rx_drops_no_tpre_descr =
- rxf_stats->rx_drops_no_tpre_descr;
- drvs->rx_drops_too_many_frags =
- rxf_stats->rx_drops_too_many_frags;
+ drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr;
+ drvs->rx_drops_too_many_frags = rxf_stats->rx_drops_too_many_frags;
adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops;
}
static void populate_be3_stats(struct be_adapter *adapter)
{
- struct be_drv_stats *drvs = &adapter->drv_stats;
- struct be_pmem_stats *pmem_sts = be_pmem_stats_from_cmd(adapter);
-
- struct be_rxf_stats_v1 *rxf_stats =
- be_rxf_stats_from_cmd(adapter);
+ struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
+ struct be_pmem_stats *pmem_sts = &hw_stats->pmem;
+ struct be_rxf_stats_v1 *rxf_stats = &hw_stats->rxf;
struct be_port_rxf_stats_v1 *port_stats =
- be_port_rxf_stats_from_cmd(adapter);
+ &rxf_stats->port[adapter->port_num];
+ struct be_drv_stats *drvs = &adapter->drv_stats;
- drvs->rx_priority_pause_frames = 0;
- drvs->pmem_fifo_overflow_drop = 0;
+ be_dws_le_to_cpu(hw_stats, sizeof(*hw_stats));
drvs->rx_pause_frames = port_stats->rx_pause_frames;
drvs->rx_crc_errors = port_stats->rx_crc_errors;
drvs->rx_control_frames = port_stats->rx_control_frames;
@@ -327,12 +331,10 @@ static void populate_be3_stats(struct be_adapter *adapter)
port_stats->rx_dropped_header_too_small;
drvs->rx_input_fifo_overflow_drop =
port_stats->rx_input_fifo_overflow_drop;
- drvs->rx_address_match_errors =
- port_stats->rx_address_match_errors;
+ drvs->rx_address_match_errors = port_stats->rx_address_match_errors;
drvs->rx_alignment_symbol_errors =
port_stats->rx_alignment_symbol_errors;
- drvs->rxpp_fifo_overflow_drop =
- port_stats->rxpp_fifo_overflow_drop;
+ drvs->rxpp_fifo_overflow_drop = port_stats->rxpp_fifo_overflow_drop;
drvs->tx_pauseframes = port_stats->tx_pauseframes;
drvs->tx_controlframes = port_stats->tx_controlframes;
drvs->jabber_events = port_stats->jabber_events;
@@ -342,10 +344,8 @@ static void populate_be3_stats(struct be_adapter *adapter)
drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring;
drvs->forwarded_packets = rxf_stats->forwarded_packets;
drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu;
- drvs->rx_drops_no_tpre_descr =
- rxf_stats->rx_drops_no_tpre_descr;
- drvs->rx_drops_too_many_frags =
- rxf_stats->rx_drops_too_many_frags;
+ drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr;
+ drvs->rx_drops_too_many_frags = rxf_stats->rx_drops_too_many_frags;
adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops;
}
@@ -353,22 +353,15 @@ static void populate_lancer_stats(struct be_adapter *adapter)
{
struct be_drv_stats *drvs = &adapter->drv_stats;
- struct lancer_cmd_pport_stats *pport_stats = pport_stats_from_cmd
- (adapter);
- drvs->rx_priority_pause_frames = 0;
- drvs->pmem_fifo_overflow_drop = 0;
- drvs->rx_pause_frames =
- make_64bit_val(pport_stats->rx_pause_frames_hi,
- pport_stats->rx_pause_frames_lo);
- drvs->rx_crc_errors = make_64bit_val(pport_stats->rx_crc_errors_hi,
- pport_stats->rx_crc_errors_lo);
- drvs->rx_control_frames =
- make_64bit_val(pport_stats->rx_control_frames_hi,
- pport_stats->rx_control_frames_lo);
+ struct lancer_pport_stats *pport_stats =
+ pport_stats_from_cmd(adapter);
+
+ be_dws_le_to_cpu(pport_stats, sizeof(*pport_stats));
+ drvs->rx_pause_frames = pport_stats->rx_pause_frames_lo;
+ drvs->rx_crc_errors = pport_stats->rx_crc_errors_lo;
+ drvs->rx_control_frames = pport_stats->rx_control_frames_lo;
drvs->rx_in_range_errors = pport_stats->rx_in_range_errors;
- drvs->rx_frame_too_long =
- make_64bit_val(pport_stats->rx_internal_mac_errors_hi,
- pport_stats->rx_frames_too_long_lo);
+ drvs->rx_frame_too_long = pport_stats->rx_frames_too_long_lo;
drvs->rx_dropped_runt = pport_stats->rx_dropped_runt;
drvs->rx_ip_checksum_errs = pport_stats->rx_ip_checksum_errors;
drvs->rx_tcp_checksum_errs = pport_stats->rx_tcp_checksum_errors;
@@ -382,32 +375,36 @@ static void populate_lancer_stats(struct be_adapter *adapter)
pport_stats->rx_dropped_header_too_small;
drvs->rx_input_fifo_overflow_drop = pport_stats->rx_fifo_overflow;
drvs->rx_address_match_errors = pport_stats->rx_address_match_errors;
- drvs->rx_alignment_symbol_errors =
- make_64bit_val(pport_stats->rx_symbol_errors_hi,
- pport_stats->rx_symbol_errors_lo);
+ drvs->rx_alignment_symbol_errors = pport_stats->rx_symbol_errors_lo;
drvs->rxpp_fifo_overflow_drop = pport_stats->rx_fifo_overflow;
- drvs->tx_pauseframes = make_64bit_val(pport_stats->tx_pause_frames_hi,
- pport_stats->tx_pause_frames_lo);
- drvs->tx_controlframes =
- make_64bit_val(pport_stats->tx_control_frames_hi,
- pport_stats->tx_control_frames_lo);
+ drvs->tx_pauseframes = pport_stats->tx_pause_frames_lo;
+ drvs->tx_controlframes = pport_stats->tx_control_frames_lo;
drvs->jabber_events = pport_stats->rx_jabbers;
- drvs->rx_drops_no_pbuf = 0;
- drvs->rx_drops_no_txpb = 0;
- drvs->rx_drops_no_erx_descr = 0;
drvs->rx_drops_invalid_ring = pport_stats->rx_drops_invalid_queue;
- drvs->forwarded_packets = make_64bit_val(pport_stats->num_forwards_hi,
- pport_stats->num_forwards_lo);
- drvs->rx_drops_mtu = make_64bit_val(pport_stats->rx_drops_mtu_hi,
- pport_stats->rx_drops_mtu_lo);
- drvs->rx_drops_no_tpre_descr = 0;
+ drvs->forwarded_packets = pport_stats->num_forwards_lo;
+ drvs->rx_drops_mtu = pport_stats->rx_drops_mtu_lo;
drvs->rx_drops_too_many_frags =
- make_64bit_val(pport_stats->rx_drops_too_many_frags_hi,
- pport_stats->rx_drops_too_many_frags_lo);
+ pport_stats->rx_drops_too_many_frags_lo;
+}
+
+static void accumulate_16bit_val(u32 *acc, u16 val)
+{
+#define lo(x) (x & 0xFFFF)
+#define hi(x) (x & 0xFFFF0000)
+ bool wrapped = val < lo(*acc);
+ u32 newacc = hi(*acc) + val;
+
+ if (wrapped)
+ newacc += 65536;
+ ACCESS_ONCE(*acc) = newacc;
}
void be_parse_stats(struct be_adapter *adapter)
{
+ struct be_erx_stats_v1 *erx = be_erx_stats_from_cmd(adapter);
+ struct be_rx_obj *rxo;
+ int i;
+
if (adapter->generation == BE_GEN3) {
if (lancer_chip(adapter))
populate_lancer_stats(adapter);
@@ -416,50 +413,55 @@ void be_parse_stats(struct be_adapter *adapter)
} else {
populate_be2_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]);
+ }
}
-void netdev_stats_update(struct be_adapter *adapter)
+static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
{
+ struct be_adapter *adapter = netdev_priv(netdev);
struct be_drv_stats *drvs = &adapter->drv_stats;
- struct net_device_stats *dev_stats = &adapter->netdev->stats;
struct be_rx_obj *rxo;
struct be_tx_obj *txo;
- unsigned long pkts = 0, bytes = 0, mcast = 0, drops = 0;
+ u64 pkts, bytes;
+ unsigned int start;
int i;
for_all_rx_queues(adapter, rxo, i) {
- pkts += rx_stats(rxo)->rx_pkts;
- bytes += rx_stats(rxo)->rx_bytes;
- mcast += rx_stats(rxo)->rx_mcast_pkts;
- drops += rx_stats(rxo)->rx_dropped;
- /* no space in linux buffers: best possible approximation */
- if (adapter->generation == BE_GEN3) {
- if (!(lancer_chip(adapter))) {
- struct be_erx_stats_v1 *erx =
- be_erx_stats_from_cmd(adapter);
- drops += erx->rx_drops_no_fragments[rxo->q.id];
- }
- } else {
- struct be_erx_stats_v0 *erx =
- be_erx_stats_from_cmd(adapter);
- drops += erx->rx_drops_no_fragments[rxo->q.id];
- }
+ const struct be_rx_stats *rx_stats = rx_stats(rxo);
+ do {
+ start = u64_stats_fetch_begin_bh(&rx_stats->sync);
+ pkts = rx_stats(rxo)->rx_pkts;
+ bytes = rx_stats(rxo)->rx_bytes;
+ } while (u64_stats_fetch_retry_bh(&rx_stats->sync, start));
+ stats->rx_packets += pkts;
+ stats->rx_bytes += bytes;
+ stats->multicast += rx_stats(rxo)->rx_mcast_pkts;
+ stats->rx_dropped += rx_stats(rxo)->rx_drops_no_skbs +
+ rx_stats(rxo)->rx_drops_no_frags;
}
- dev_stats->rx_packets = pkts;
- dev_stats->rx_bytes = bytes;
- dev_stats->multicast = mcast;
- dev_stats->rx_dropped = drops;
- pkts = bytes = 0;
for_all_tx_queues(adapter, txo, i) {
- pkts += tx_stats(txo)->be_tx_pkts;
- bytes += tx_stats(txo)->be_tx_bytes;
+ const struct be_tx_stats *tx_stats = tx_stats(txo);
+ do {
+ start = u64_stats_fetch_begin_bh(&tx_stats->sync);
+ pkts = tx_stats(txo)->tx_pkts;
+ bytes = tx_stats(txo)->tx_bytes;
+ } while (u64_stats_fetch_retry_bh(&tx_stats->sync, start));
+ stats->tx_packets += pkts;
+ stats->tx_bytes += bytes;
}
- dev_stats->tx_packets = pkts;
- dev_stats->tx_bytes = bytes;
/* bad pkts received */
- dev_stats->rx_errors = drvs->rx_crc_errors +
+ stats->rx_errors = drvs->rx_crc_errors +
drvs->rx_alignment_symbol_errors +
drvs->rx_in_range_errors +
drvs->rx_out_range_errors +
@@ -468,115 +470,38 @@ void netdev_stats_update(struct be_adapter *adapter)
drvs->rx_dropped_too_short +
drvs->rx_dropped_header_too_small +
drvs->rx_dropped_tcp_length +
- drvs->rx_dropped_runt +
- drvs->rx_tcp_checksum_errs +
- drvs->rx_ip_checksum_errs +
- drvs->rx_udp_checksum_errs;
+ drvs->rx_dropped_runt;
/* detailed rx errors */
- dev_stats->rx_length_errors = drvs->rx_in_range_errors +
+ stats->rx_length_errors = drvs->rx_in_range_errors +
drvs->rx_out_range_errors +
drvs->rx_frame_too_long;
- dev_stats->rx_crc_errors = drvs->rx_crc_errors;
+ stats->rx_crc_errors = drvs->rx_crc_errors;
/* frame alignment errors */
- dev_stats->rx_frame_errors = drvs->rx_alignment_symbol_errors;
+ stats->rx_frame_errors = drvs->rx_alignment_symbol_errors;
/* receiver fifo overrun */
/* drops_no_pbuf is no per i/f, it's per BE card */
- dev_stats->rx_fifo_errors = drvs->rxpp_fifo_overflow_drop +
+ stats->rx_fifo_errors = drvs->rxpp_fifo_overflow_drop +
drvs->rx_input_fifo_overflow_drop +
drvs->rx_drops_no_pbuf;
+ return stats;
}
-void be_link_status_update(struct be_adapter *adapter, bool link_up)
+void be_link_status_update(struct be_adapter *adapter, u32 link_status)
{
struct net_device *netdev = adapter->netdev;
- /* If link came up or went down */
- if (adapter->link_up != link_up) {
- adapter->link_speed = -1;
- if (link_up) {
- netif_carrier_on(netdev);
- printk(KERN_INFO "%s: Link up\n", netdev->name);
- } else {
- netif_carrier_off(netdev);
- printk(KERN_INFO "%s: Link down\n", netdev->name);
- }
- adapter->link_up = link_up;
- }
-}
-
-/* Update the EQ delay n BE based on the RX frags consumed / sec */
-static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo)
-{
- struct be_eq_obj *rx_eq = &rxo->rx_eq;
- struct be_rx_stats *stats = &rxo->stats;
- ulong now = jiffies;
- u32 eqd;
-
- if (!rx_eq->enable_aic)
- return;
-
- /* Wrapped around */
- if (time_before(now, stats->rx_fps_jiffies)) {
- stats->rx_fps_jiffies = now;
- return;
- }
-
- /* Update once a second */
- if ((now - stats->rx_fps_jiffies) < HZ)
- return;
-
- stats->rx_fps = (stats->rx_frags - stats->prev_rx_frags) /
- ((now - stats->rx_fps_jiffies) / HZ);
-
- stats->rx_fps_jiffies = now;
- stats->prev_rx_frags = stats->rx_frags;
- eqd = stats->rx_fps / 110000;
- eqd = eqd << 3;
- if (eqd > rx_eq->max_eqd)
- eqd = rx_eq->max_eqd;
- if (eqd < rx_eq->min_eqd)
- eqd = rx_eq->min_eqd;
- if (eqd < 10)
- eqd = 0;
- if (eqd != rx_eq->cur_eqd)
- be_cmd_modify_eqd(adapter, rx_eq->q.id, eqd);
-
- rx_eq->cur_eqd = eqd;
-}
-
-static u32 be_calc_rate(u64 bytes, unsigned long ticks)
-{
- u64 rate = bytes;
-
- do_div(rate, ticks / HZ);
- rate <<= 3; /* bytes/sec -> bits/sec */
- do_div(rate, 1000000ul); /* MB/Sec */
-
- return rate;
-}
-
-static void be_tx_rate_update(struct be_tx_obj *txo)
-{
- struct be_tx_stats *stats = tx_stats(txo);
- ulong now = jiffies;
-
- /* Wrapped around? */
- if (time_before(now, stats->be_tx_jiffies)) {
- stats->be_tx_jiffies = now;
- return;
- }
-
- /* Update tx rate once in two seconds */
- if ((now - stats->be_tx_jiffies) > 2 * HZ) {
- stats->be_tx_rate = be_calc_rate(stats->be_tx_bytes
- - stats->be_tx_bytes_prev,
- now - stats->be_tx_jiffies);
- stats->be_tx_jiffies = now;
- stats->be_tx_bytes_prev = stats->be_tx_bytes;
+ /* when link status changes, link speed must be re-queried from card */
+ adapter->link_speed = -1;
+ if ((link_status & LINK_STATUS_MASK) == LINK_UP) {
+ netif_carrier_on(netdev);
+ dev_info(&adapter->pdev->dev, "%s: Link up\n", netdev->name);
+ } else {
+ netif_carrier_off(netdev);
+ dev_info(&adapter->pdev->dev, "%s: Link down\n", netdev->name);
}
}
@@ -585,12 +510,14 @@ static void be_tx_stats_update(struct be_tx_obj *txo,
{
struct be_tx_stats *stats = tx_stats(txo);
- stats->be_tx_reqs++;
- stats->be_tx_wrbs += wrb_cnt;
- stats->be_tx_bytes += copied;
- stats->be_tx_pkts += (gso_segs ? gso_segs : 1);
+ u64_stats_update_begin(&stats->sync);
+ stats->tx_reqs++;
+ stats->tx_wrbs += wrb_cnt;
+ stats->tx_bytes += copied;
+ stats->tx_pkts += (gso_segs ? gso_segs : 1);
if (stopped)
- stats->be_tx_stops++;
+ stats->tx_stops++;
+ u64_stats_update_end(&stats->sync);
}
/* Determine number of WRB entries needed to xmit data in an skb */
@@ -718,17 +645,17 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq,
}
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- struct skb_frag_struct *frag =
+ const struct skb_frag_struct *frag =
&skb_shinfo(skb)->frags[i];
- busaddr = dma_map_page(dev, frag->page, frag->page_offset,
- frag->size, DMA_TO_DEVICE);
+ busaddr = skb_frag_dma_map(dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
if (dma_mapping_error(dev, busaddr))
goto dma_err;
wrb = queue_head_node(txq);
- wrb_fill(wrb, busaddr, frag->size);
+ wrb_fill(wrb, busaddr, skb_frag_size(frag));
be_dws_cpu_to_le(wrb, sizeof(*wrb));
queue_head_inc(txq);
- copied += frag->size;
+ copied += skb_frag_size(frag);
}
if (dummy_wrb) {
@@ -829,6 +756,10 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0);
}
+ /* No need to further configure vids if in promiscuous mode */
+ if (adapter->promiscuous)
+ return 0;
+
if (adapter->vlans_added <= adapter->max_vlans) {
/* Construct VLAN Table to give to HW */
for (i = 0; i < VLAN_N_VID; i++) {
@@ -874,12 +805,12 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
be_vid_config(adapter, false, 0);
}
-static void be_set_multicast_list(struct net_device *netdev)
+static void be_set_rx_mode(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
if (netdev->flags & IFF_PROMISC) {
- be_cmd_promiscuous_config(adapter, true);
+ be_cmd_rx_filter(adapter, IFF_PROMISC, ON);
adapter->promiscuous = true;
goto done;
}
@@ -887,19 +818,20 @@ static void be_set_multicast_list(struct net_device *netdev)
/* BE was previously in promiscuous mode; disable it */
if (adapter->promiscuous) {
adapter->promiscuous = false;
- be_cmd_promiscuous_config(adapter, false);
+ be_cmd_rx_filter(adapter, IFF_PROMISC, OFF);
+
+ if (adapter->vlans_added)
+ be_vid_config(adapter, false, 0);
}
/* Enable multicast promisc if num configured exceeds what we support */
if (netdev->flags & IFF_ALLMULTI ||
- netdev_mc_count(netdev) > BE_MAX_MC) {
- be_cmd_multicast_set(adapter, adapter->if_handle, NULL,
- &adapter->mc_cmd_mem);
+ netdev_mc_count(netdev) > BE_MAX_MC) {
+ be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
goto done;
}
- be_cmd_multicast_set(adapter, adapter->if_handle, netdev,
- &adapter->mc_cmd_mem);
+ be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
done:
return;
}
@@ -1005,10 +937,17 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
return status;
}
-static void be_rx_rate_update(struct be_rx_obj *rxo)
+static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo)
{
- struct be_rx_stats *stats = &rxo->stats;
+ struct be_eq_obj *rx_eq = &rxo->rx_eq;
+ struct be_rx_stats *stats = rx_stats(rxo);
ulong now = jiffies;
+ ulong delta = now - stats->rx_jiffies;
+ u64 pkts;
+ unsigned int start, eqd;
+
+ if (!rx_eq->enable_aic)
+ return;
/* Wrapped around */
if (time_before(now, stats->rx_jiffies)) {
@@ -1016,29 +955,46 @@ static void be_rx_rate_update(struct be_rx_obj *rxo)
return;
}
- /* Update the rate once in two seconds */
- if ((now - stats->rx_jiffies) < 2 * HZ)
+ /* Update once a second */
+ if (delta < HZ)
return;
- stats->rx_rate = be_calc_rate(stats->rx_bytes - stats->rx_bytes_prev,
- now - stats->rx_jiffies);
+ do {
+ start = u64_stats_fetch_begin_bh(&stats->sync);
+ pkts = stats->rx_pkts;
+ } while (u64_stats_fetch_retry_bh(&stats->sync, start));
+
+ stats->rx_pps = (unsigned long)(pkts - stats->rx_pkts_prev) / (delta / HZ);
+ stats->rx_pkts_prev = pkts;
stats->rx_jiffies = now;
- stats->rx_bytes_prev = stats->rx_bytes;
+ eqd = stats->rx_pps / 110000;
+ eqd = eqd << 3;
+ if (eqd > rx_eq->max_eqd)
+ eqd = rx_eq->max_eqd;
+ if (eqd < rx_eq->min_eqd)
+ eqd = rx_eq->min_eqd;
+ if (eqd < 10)
+ eqd = 0;
+ if (eqd != rx_eq->cur_eqd) {
+ be_cmd_modify_eqd(adapter, rx_eq->q.id, eqd);
+ rx_eq->cur_eqd = eqd;
+ }
}
static void be_rx_stats_update(struct be_rx_obj *rxo,
struct be_rx_compl_info *rxcp)
{
- struct be_rx_stats *stats = &rxo->stats;
+ struct be_rx_stats *stats = rx_stats(rxo);
+ u64_stats_update_begin(&stats->sync);
stats->rx_compl++;
- stats->rx_frags += rxcp->num_rcvd;
stats->rx_bytes += rxcp->pkt_size;
stats->rx_pkts++;
if (rxcp->pkt_type == BE_MULTICAST_PACKET)
stats->rx_mcast_pkts++;
if (rxcp->err)
- stats->rxcp_err++;
+ stats->rx_compl_err++;
+ u64_stats_update_end(&stats->sync);
}
static inline bool csum_passed(struct be_rx_compl_info *rxcp)
@@ -1119,11 +1075,12 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
skb->tail += curr_frag_len;
} else {
skb_shinfo(skb)->nr_frags = 1;
- skb_shinfo(skb)->frags[0].page = page_info->page;
+ skb_frag_set_page(skb, 0, page_info->page);
skb_shinfo(skb)->frags[0].page_offset =
page_info->page_offset + hdr_len;
- skb_shinfo(skb)->frags[0].size = curr_frag_len - hdr_len;
+ skb_frag_size_set(&skb_shinfo(skb)->frags[0], curr_frag_len - hdr_len);
skb->data_len = curr_frag_len - hdr_len;
+ skb->truesize += rx_frag_size;
skb->tail += hdr_len;
}
page_info->page = NULL;
@@ -1144,19 +1101,19 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
if (page_info->page_offset == 0) {
/* Fresh page */
j++;
- skb_shinfo(skb)->frags[j].page = page_info->page;
+ skb_frag_set_page(skb, j, page_info->page);
skb_shinfo(skb)->frags[j].page_offset =
page_info->page_offset;
- skb_shinfo(skb)->frags[j].size = 0;
+ skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0);
skb_shinfo(skb)->nr_frags++;
} else {
put_page(page_info->page);
}
- skb_shinfo(skb)->frags[j].size += curr_frag_len;
+ skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len);
skb->len += curr_frag_len;
skb->data_len += curr_frag_len;
-
+ skb->truesize += rx_frag_size;
remaining -= curr_frag_len;
index_inc(&rxcp->rxq_idx, rxq->len);
page_info->page = NULL;
@@ -1174,7 +1131,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN);
if (unlikely(!skb)) {
- rxo->stats.rx_dropped++;
+ rx_stats(rxo)->rx_drops_no_skbs++;
be_rx_compl_discard(adapter, rxo, rxcp);
return;
}
@@ -1186,13 +1143,12 @@ static void be_rx_compl_process(struct be_adapter *adapter,
else
skb_checksum_none_assert(skb);
- skb->truesize = skb->len + sizeof(struct sk_buff);
skb->protocol = eth_type_trans(skb, netdev);
if (adapter->netdev->features & NETIF_F_RXHASH)
skb->rxhash = rxcp->rss_hash;
- if (unlikely(rxcp->vlanf))
+ if (rxcp->vlanf)
__vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
netif_receive_skb(skb);
@@ -1226,15 +1182,15 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
if (i == 0 || page_info->page_offset == 0) {
/* First frag or Fresh page */
j++;
- skb_shinfo(skb)->frags[j].page = page_info->page;
+ skb_frag_set_page(skb, j, page_info->page);
skb_shinfo(skb)->frags[j].page_offset =
page_info->page_offset;
- skb_shinfo(skb)->frags[j].size = 0;
+ skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0);
} else {
put_page(page_info->page);
}
- skb_shinfo(skb)->frags[j].size += curr_frag_len;
-
+ skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len);
+ skb->truesize += rx_frag_size;
remaining -= curr_frag_len;
index_inc(&rxcp->rxq_idx, rxq->len);
memset(page_info, 0, sizeof(*page_info));
@@ -1244,12 +1200,11 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
skb_shinfo(skb)->nr_frags = j + 1;
skb->len = rxcp->pkt_size;
skb->data_len = rxcp->pkt_size;
- skb->truesize += rxcp->pkt_size;
skb->ip_summed = CHECKSUM_UNNECESSARY;
if (adapter->netdev->features & NETIF_F_RXHASH)
skb->rxhash = rxcp->rss_hash;
- if (unlikely(rxcp->vlanf))
+ if (rxcp->vlanf)
__vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
napi_gro_frags(&eq_obj->napi);
@@ -1285,6 +1240,7 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter,
rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag,
compl);
}
+ rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, port, compl);
}
static void be_parse_rx_compl_v0(struct be_adapter *adapter,
@@ -1317,6 +1273,7 @@ static void be_parse_rx_compl_v0(struct be_adapter *adapter,
rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag,
compl);
}
+ rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, port, compl);
}
static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
@@ -1341,14 +1298,13 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
if (rxcp->vlanf) {
/* vlanf could be wrongly set in some cards.
* ignore if vtm is not set */
- if ((adapter->function_mode & 0x400) && !rxcp->vtm)
+ if ((adapter->function_mode & FLEX10_MODE) && !rxcp->vtm)
rxcp->vlanf = 0;
if (!lancer_chip(adapter))
rxcp->vlan_tag = swab16(rxcp->vlan_tag);
- if (((adapter->pvid & VLAN_VID_MASK) ==
- (rxcp->vlan_tag & VLAN_VID_MASK)) &&
+ if (adapter->pvid == (rxcp->vlan_tag & VLAN_VID_MASK) &&
!adapter->vlan_tag[rxcp->vlan_tag])
rxcp->vlanf = 0;
}
@@ -1389,7 +1345,7 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
if (!pagep) {
pagep = be_alloc_pages(adapter->big_page_size, gfp);
if (unlikely(!pagep)) {
- rxo->stats.rx_post_fail++;
+ rx_stats(rxo)->rx_post_fail++;
break;
}
page_dmaaddr = dma_map_page(&adapter->pdev->dev, pagep,
@@ -1686,6 +1642,17 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
be_queue_free(adapter, q);
}
+static int be_num_txqs_want(struct be_adapter *adapter)
+{
+ if ((num_vfs && adapter->sriov_enabled) ||
+ be_is_mc(adapter) ||
+ lancer_chip(adapter) || !be_physfn(adapter) ||
+ adapter->generation == BE_GEN2)
+ return 1;
+ else
+ return MAX_TX_QS;
+}
+
/* One TX event queue is shared by all TX compl qs */
static int be_tx_queues_create(struct be_adapter *adapter)
{
@@ -1693,6 +1660,11 @@ static int be_tx_queues_create(struct be_adapter *adapter)
struct be_tx_obj *txo;
u8 i;
+ adapter->num_tx_qs = be_num_txqs_want(adapter);
+ if (adapter->num_tx_qs != MAX_TX_QS)
+ netif_set_real_num_tx_queues(adapter->netdev,
+ adapter->num_tx_qs);
+
adapter->tx_eq.max_eqd = 0;
adapter->tx_eq.min_eqd = 0;
adapter->tx_eq.cur_eqd = 96;
@@ -1755,7 +1727,8 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
static u32 be_num_rxqs_want(struct be_adapter *adapter)
{
if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
- !adapter->sriov_enabled && !(adapter->function_mode & 0x400)) {
+ !adapter->sriov_enabled && be_physfn(adapter) &&
+ !be_is_mc(adapter)) {
return 1 + MAX_RSS_QS; /* one default non-RSS queue */
} else {
dev_warn(&adapter->pdev->dev,
@@ -1899,27 +1872,41 @@ static int be_poll_rx(struct napi_struct *napi, int budget)
struct be_rx_compl_info *rxcp;
u32 work_done;
- rxo->stats.rx_polls++;
+ rx_stats(rxo)->rx_polls++;
for (work_done = 0; work_done < budget; work_done++) {
rxcp = be_rx_compl_get(rxo);
if (!rxcp)
break;
- /* Ignore flush completions */
- if (rxcp->num_rcvd && rxcp->pkt_size) {
- if (do_gro(rxcp))
- be_rx_compl_process_gro(adapter, rxo, rxcp);
- else
- be_rx_compl_process(adapter, rxo, rxcp);
- } else if (rxcp->pkt_size == 0) {
+ /* Is it a flush compl that has no data */
+ if (unlikely(rxcp->num_rcvd == 0))
+ goto loop_continue;
+
+ /* Discard compl with partial DMA Lancer B0 */
+ if (unlikely(!rxcp->pkt_size)) {
be_rx_compl_discard(adapter, rxo, rxcp);
+ goto loop_continue;
}
+ /* On BE drop pkts that arrive due to imperfect filtering in
+ * promiscuous mode on some skews
+ */
+ if (unlikely(rxcp->port != adapter->port_num &&
+ !lancer_chip(adapter))) {
+ be_rx_compl_discard(adapter, rxo, rxcp);
+ goto loop_continue;
+ }
+
+ if (do_gro(rxcp))
+ be_rx_compl_process_gro(adapter, rxo, rxcp);
+ else
+ be_rx_compl_process(adapter, rxo, rxcp);
+loop_continue:
be_rx_stats_update(rxo, rxcp);
}
/* Refill the queue */
- if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM)
+ if (work_done && atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM)
be_post_rx_frags(rxo, GFP_ATOMIC);
/* All consumed */
@@ -1968,8 +1955,9 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
netif_wake_subqueue(adapter->netdev, i);
}
- adapter->drv_stats.be_tx_events++;
- txo->stats.be_tx_compl += tx_compl;
+ u64_stats_update_begin(&tx_stats(txo)->sync_compl);
+ tx_stats(txo)->tx_compl += tx_compl;
+ u64_stats_update_end(&tx_stats(txo)->sync_compl);
}
}
@@ -1983,6 +1971,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
napi_complete(napi);
be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
+ adapter->drv_stats.tx_events++;
return 1;
}
@@ -2031,7 +2020,6 @@ static void be_worker(struct work_struct *work)
struct be_adapter *adapter =
container_of(work, struct be_adapter, work.work);
struct be_rx_obj *rxo;
- struct be_tx_obj *txo;
int i;
if (!adapter->ue_detected && !lancer_chip(adapter))
@@ -2060,11 +2048,7 @@ static void be_worker(struct work_struct *work)
be_cmd_get_stats(adapter, &adapter->stats_cmd);
}
- for_all_tx_queues(adapter, txo, i)
- be_tx_rate_update(txo);
-
for_all_rx_queues(adapter, rxo, i) {
- be_rx_rate_update(rxo);
be_rx_eqd_update(adapter, rxo);
if (rxo->rx_post_starved) {
@@ -2111,7 +2095,7 @@ done:
return;
}
-static void be_sriov_enable(struct be_adapter *adapter)
+static int be_sriov_enable(struct be_adapter *adapter)
{
be_check_sriov_fn_type(adapter);
#ifdef CONFIG_PCI_IOV
@@ -2133,8 +2117,17 @@ static void be_sriov_enable(struct be_adapter *adapter)
status = pci_enable_sriov(adapter->pdev, num_vfs);
adapter->sriov_enabled = status ? false : true;
+
+ if (adapter->sriov_enabled) {
+ adapter->vf_cfg = kcalloc(num_vfs,
+ sizeof(struct be_vf_cfg),
+ GFP_KERNEL);
+ if (!adapter->vf_cfg)
+ return -ENOMEM;
+ }
}
#endif
+ return 0;
}
static void be_sriov_disable(struct be_adapter *adapter)
@@ -2142,6 +2135,7 @@ static void be_sriov_disable(struct be_adapter *adapter)
#ifdef CONFIG_PCI_IOV
if (adapter->sriov_enabled) {
pci_disable_sriov(adapter->pdev);
+ kfree(adapter->vf_cfg);
adapter->sriov_enabled = false;
}
#endif
@@ -2294,9 +2288,6 @@ static int be_close(struct net_device *netdev)
be_async_mcc_disable(adapter);
- netif_carrier_off(netdev);
- adapter->link_up = false;
-
if (!lancer_chip(adapter))
be_intr_set(adapter, false);
@@ -2374,10 +2365,7 @@ static int be_open(struct net_device *netdev)
struct be_adapter *adapter = netdev_priv(netdev);
struct be_eq_obj *tx_eq = &adapter->tx_eq;
struct be_rx_obj *rxo;
- bool link_up;
int status, i;
- u8 mac_speed;
- u16 link_speed;
status = be_rx_queues_setup(adapter);
if (status)
@@ -2400,23 +2388,6 @@ static int be_open(struct net_device *netdev)
/* Now that interrupts are on we can process async mcc */
be_async_mcc_enable(adapter);
- status = be_cmd_link_status_query(adapter, &link_up, &mac_speed,
- &link_speed, 0);
- if (status)
- goto err;
- be_link_status_update(adapter, link_up);
-
- if (be_physfn(adapter)) {
- status = be_vid_config(adapter, false, 0);
- if (status)
- goto err;
-
- status = be_cmd_set_flow_control(adapter,
- adapter->tx_fc, adapter->rx_fc);
- if (status)
- goto err;
- }
-
return 0;
err:
be_close(adapter->netdev);
@@ -2470,7 +2441,7 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
*/
static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
{
- u32 vf = 0;
+ u32 vf;
int status = 0;
u8 mac[ETH_ALEN];
@@ -2492,7 +2463,7 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
return status;
}
-static inline void be_vf_eth_addr_rem(struct be_adapter *adapter)
+static void be_vf_clear(struct be_adapter *adapter)
{
u32 vf;
@@ -2502,132 +2473,159 @@ static inline void be_vf_eth_addr_rem(struct be_adapter *adapter)
adapter->vf_cfg[vf].vf_if_handle,
adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
}
+
+ for (vf = 0; vf < num_vfs; vf++)
+ if (adapter->vf_cfg[vf].vf_if_handle)
+ be_cmd_if_destroy(adapter,
+ adapter->vf_cfg[vf].vf_if_handle, vf + 1);
}
-static int be_setup(struct be_adapter *adapter)
+static int be_clear(struct be_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
- u32 cap_flags, en_flags, vf = 0;
- int status;
- u8 mac[ETH_ALEN];
+ if (be_physfn(adapter) && adapter->sriov_enabled)
+ be_vf_clear(adapter);
- be_cmd_req_native_mode(adapter);
+ be_cmd_if_destroy(adapter, adapter->if_handle, 0);
- cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED |
- BE_IF_FLAGS_BROADCAST |
- BE_IF_FLAGS_MULTICAST;
+ be_mcc_queues_destroy(adapter);
+ be_rx_queues_destroy(adapter);
+ be_tx_queues_destroy(adapter);
+ adapter->eq_next_idx = 0;
- if (be_physfn(adapter)) {
- cap_flags |= BE_IF_FLAGS_MCAST_PROMISCUOUS |
- BE_IF_FLAGS_PROMISCUOUS |
- BE_IF_FLAGS_PASS_L3L4_ERRORS;
- en_flags |= BE_IF_FLAGS_PASS_L3L4_ERRORS;
-
- if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) {
- cap_flags |= BE_IF_FLAGS_RSS;
- en_flags |= BE_IF_FLAGS_RSS;
- }
- }
+ adapter->be3_native = false;
+ adapter->promiscuous = false;
- status = be_cmd_if_create(adapter, cap_flags, en_flags,
- netdev->dev_addr, false/* pmac_invalid */,
- &adapter->if_handle, &adapter->pmac_id, 0);
- if (status != 0)
- goto do_none;
+ /* tell fw we're done with firing cmds */
+ be_cmd_fw_clean(adapter);
+ return 0;
+}
- if (be_physfn(adapter)) {
- if (adapter->sriov_enabled) {
- while (vf < num_vfs) {
- cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED |
- BE_IF_FLAGS_BROADCAST;
- status = be_cmd_if_create(adapter, cap_flags,
- en_flags, mac, true,
+static int be_vf_setup(struct be_adapter *adapter)
+{
+ u32 cap_flags, en_flags, vf;
+ u16 lnk_speed;
+ int status;
+
+ cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST;
+ for (vf = 0; vf < num_vfs; vf++) {
+ status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL,
&adapter->vf_cfg[vf].vf_if_handle,
NULL, vf+1);
- if (status) {
- dev_err(&adapter->pdev->dev,
- "Interface Create failed for VF %d\n",
- vf);
- goto if_destroy;
- }
- adapter->vf_cfg[vf].vf_pmac_id =
- BE_INVALID_PMAC_ID;
- vf++;
- }
- }
- } else {
- status = be_cmd_mac_addr_query(adapter, mac,
- MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle);
- if (!status) {
- memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
- memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
- }
+ if (status)
+ goto err;
+ adapter->vf_cfg[vf].vf_pmac_id = BE_INVALID_PMAC_ID;
+ }
+
+ if (!lancer_chip(adapter)) {
+ status = be_vf_eth_addr_config(adapter);
+ if (status)
+ goto err;
+ }
+
+ for (vf = 0; vf < num_vfs; vf++) {
+ status = be_cmd_link_status_query(adapter, NULL, &lnk_speed,
+ vf + 1);
+ if (status)
+ goto err;
+ adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10;
}
+ return 0;
+err:
+ return status;
+}
+
+static int be_setup(struct be_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ u32 cap_flags, en_flags;
+ u32 tx_fc, rx_fc;
+ int status;
+ u8 mac[ETH_ALEN];
+
+ /* Allow all priorities by default. A GRP5 evt may modify this */
+ adapter->vlan_prio_bmap = 0xff;
+ adapter->link_speed = -1;
+
+ be_cmd_req_native_mode(adapter);
status = be_tx_queues_create(adapter);
if (status != 0)
- goto if_destroy;
+ goto err;
status = be_rx_queues_create(adapter);
if (status != 0)
- goto tx_qs_destroy;
-
- /* Allow all priorities by default. A GRP5 evt may modify this */
- adapter->vlan_prio_bmap = 0xff;
+ goto err;
status = be_mcc_queues_create(adapter);
if (status != 0)
- goto rx_qs_destroy;
+ goto err;
- adapter->link_speed = -1;
+ memset(mac, 0, ETH_ALEN);
+ status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK,
+ true /*permanent */, 0);
+ if (status)
+ return status;
+ memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
+ memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
- return 0;
+ 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_PROMISCUOUS;
+ if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) {
+ cap_flags |= BE_IF_FLAGS_RSS;
+ en_flags |= BE_IF_FLAGS_RSS;
+ }
+ status = be_cmd_if_create(adapter, cap_flags, en_flags,
+ netdev->dev_addr, &adapter->if_handle,
+ &adapter->pmac_id, 0);
+ if (status != 0)
+ goto err;
-rx_qs_destroy:
- be_rx_queues_destroy(adapter);
-tx_qs_destroy:
- be_tx_queues_destroy(adapter);
-if_destroy:
- if (be_physfn(adapter) && adapter->sriov_enabled)
- for (vf = 0; vf < num_vfs; vf++)
- if (adapter->vf_cfg[vf].vf_if_handle)
- be_cmd_if_destroy(adapter,
- adapter->vf_cfg[vf].vf_if_handle,
- vf + 1);
- be_cmd_if_destroy(adapter, adapter->if_handle, 0);
-do_none:
- return status;
-}
+ /* For BEx, the VF's permanent mac queried from card is incorrect.
+ * Query the mac configued by the PF using if_handle
+ */
+ if (!be_physfn(adapter) && !lancer_chip(adapter)) {
+ status = be_cmd_mac_addr_query(adapter, mac,
+ MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle);
+ if (!status) {
+ memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
+ memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
+ }
+ }
-static int be_clear(struct be_adapter *adapter)
-{
- int vf;
+ be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL);
- if (be_physfn(adapter) && adapter->sriov_enabled)
- be_vf_eth_addr_rem(adapter);
+ status = be_vid_config(adapter, false, 0);
+ if (status)
+ goto err;
- be_mcc_queues_destroy(adapter);
- be_rx_queues_destroy(adapter);
- be_tx_queues_destroy(adapter);
- adapter->eq_next_idx = 0;
+ be_set_rx_mode(adapter->netdev);
- if (be_physfn(adapter) && adapter->sriov_enabled)
- for (vf = 0; vf < num_vfs; vf++)
- if (adapter->vf_cfg[vf].vf_if_handle)
- be_cmd_if_destroy(adapter,
- adapter->vf_cfg[vf].vf_if_handle,
- vf + 1);
+ status = be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc);
+ if (status)
+ goto err;
+ if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) {
+ status = be_cmd_set_flow_control(adapter, adapter->tx_fc,
+ adapter->rx_fc);
+ if (status)
+ goto err;
+ }
- be_cmd_if_destroy(adapter, adapter->if_handle, 0);
+ pcie_set_readrq(adapter->pdev, 4096);
- adapter->be3_native = 0;
+ if (be_physfn(adapter) && adapter->sriov_enabled) {
+ status = be_vf_setup(adapter);
+ if (status)
+ goto err;
+ }
- /* tell fw we're done with firing cmds */
- be_cmd_fw_clean(adapter);
return 0;
+err:
+ be_clear(adapter);
+ return status;
}
-
#define FW_FILE_HDR_SIGN "ServerEngines Corp. "
static bool be_flash_redboot(struct be_adapter *adapter,
const u8 *p, u32 img_start, int image_size,
@@ -2656,6 +2654,21 @@ static bool be_flash_redboot(struct be_adapter *adapter,
return true;
}
+static bool phy_flashing_required(struct be_adapter *adapter)
+{
+ int status = 0;
+ struct be_phy_info phy_info;
+
+ status = be_cmd_get_phy_info(adapter, &phy_info);
+ if (status)
+ return false;
+ if ((phy_info.phy_type == TN_8022) &&
+ (phy_info.interface_type == PHY_TYPE_BASET_10GB)) {
+ return true;
+ }
+ return false;
+}
+
static int be_flash_data(struct be_adapter *adapter,
const struct firmware *fw,
struct be_dma_mem *flash_cmd, int num_of_images)
@@ -2669,7 +2682,7 @@ static int be_flash_data(struct be_adapter *adapter,
const struct flash_comp *pflashcomp;
int num_comp;
- static const struct flash_comp gen3_flash_types[9] = {
+ static const struct flash_comp gen3_flash_types[10] = {
{ FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE,
FLASH_IMAGE_MAX_SIZE_g3},
{ FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT,
@@ -2687,7 +2700,9 @@ static int be_flash_data(struct be_adapter *adapter,
{ FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP,
FLASH_IMAGE_MAX_SIZE_g3},
{ FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW,
- FLASH_NCSI_IMAGE_MAX_SIZE_g3}
+ FLASH_NCSI_IMAGE_MAX_SIZE_g3},
+ { FLASH_PHY_FW_START_g3, IMG_TYPE_PHY_FW,
+ FLASH_PHY_FW_IMAGE_MAX_SIZE_g3}
};
static const struct flash_comp gen2_flash_types[8] = {
{ FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE,
@@ -2721,6 +2736,10 @@ static int be_flash_data(struct be_adapter *adapter,
if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) &&
memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
continue;
+ if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) {
+ if (!phy_flashing_required(adapter))
+ continue;
+ }
if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) &&
(!be_flash_redboot(adapter, fw->data,
pflashcomp[i].offset, pflashcomp[i].size, filehdr_size +
@@ -2729,25 +2748,35 @@ static int be_flash_data(struct be_adapter *adapter,
p = fw->data;
p += filehdr_size + pflashcomp[i].offset
+ (num_of_images * sizeof(struct image_hdr));
- if (p + pflashcomp[i].size > fw->data + fw->size)
- return -1;
- total_bytes = pflashcomp[i].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)
- flash_op = FLASHROM_OPER_FLASH;
- else
- flash_op = FLASHROM_OPER_SAVE;
+ if (!total_bytes) {
+ if (pflashcomp[i].optype == IMG_TYPE_PHY_FW)
+ flash_op = FLASHROM_OPER_PHY_FLASH;
+ else
+ flash_op = FLASHROM_OPER_FLASH;
+ } else {
+ if (pflashcomp[i].optype == IMG_TYPE_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 ==
+ IMG_TYPE_PHY_FW))
+ break;
dev_err(&adapter->pdev->dev,
"cmd to write to flash rom failed.\n");
return -1;
@@ -2935,9 +2964,10 @@ static struct net_device_ops be_netdev_ops = {
.ndo_open = be_open,
.ndo_stop = be_close,
.ndo_start_xmit = be_xmit,
- .ndo_set_rx_mode = be_set_multicast_list,
+ .ndo_set_rx_mode = be_set_rx_mode,
.ndo_set_mac_address = be_mac_addr_set,
.ndo_change_mtu = be_change_mtu,
+ .ndo_get_stats64 = be_get_stats64,
.ndo_validate_addr = eth_validate_addr,
.ndo_vlan_rx_add_vid = be_vlan_add_vid,
.ndo_vlan_rx_kill_vid = be_vlan_rem_vid,
@@ -2967,10 +2997,6 @@ static void be_netdev_init(struct net_device *netdev)
netdev->flags |= IFF_MULTICAST;
- /* Default settings for Rx and Tx flow control */
- adapter->rx_fc = true;
- adapter->tx_fc = true;
-
netif_set_gso_max_size(netdev, 65535);
BE_SET_NETDEV_OPS(netdev, &be_netdev_ops);
@@ -2991,14 +3017,12 @@ static void be_unmap_pci_bars(struct be_adapter *adapter)
iounmap(adapter->csr);
if (adapter->db)
iounmap(adapter->db);
- if (adapter->pcicfg && be_physfn(adapter))
- iounmap(adapter->pcicfg);
}
static int be_map_pci_bars(struct be_adapter *adapter)
{
u8 __iomem *addr;
- int pcicfg_reg, db_reg;
+ int db_reg;
if (lancer_chip(adapter)) {
addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0),
@@ -3018,10 +3042,8 @@ static int be_map_pci_bars(struct be_adapter *adapter)
}
if (adapter->generation == BE_GEN2) {
- pcicfg_reg = 1;
db_reg = 4;
} else {
- pcicfg_reg = 0;
if (be_physfn(adapter))
db_reg = 4;
else
@@ -3033,16 +3055,6 @@ static int be_map_pci_bars(struct be_adapter *adapter)
goto pci_map_err;
adapter->db = addr;
- if (be_physfn(adapter)) {
- addr = ioremap_nocache(
- pci_resource_start(adapter->pdev, pcicfg_reg),
- pci_resource_len(adapter->pdev, pcicfg_reg));
- if (addr == NULL)
- goto pci_map_err;
- adapter->pcicfg = addr;
- } else
- adapter->pcicfg = adapter->db + SRIOV_VF_PCICFG_OFFSET;
-
return 0;
pci_map_err:
be_unmap_pci_bars(adapter);
@@ -3060,7 +3072,7 @@ static void be_ctrl_cleanup(struct be_adapter *adapter)
dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
mem->dma);
- mem = &adapter->mc_cmd_mem;
+ mem = &adapter->rx_filter;
if (mem->va)
dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
mem->dma);
@@ -3070,7 +3082,7 @@ 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 *mc_cmd_mem = &adapter->mc_cmd_mem;
+ struct be_dma_mem *rx_filter = &adapter->rx_filter;
int status;
status = be_map_pci_bars(adapter);
@@ -3086,21 +3098,19 @@ static int be_ctrl_init(struct be_adapter *adapter)
status = -ENOMEM;
goto unmap_pci_bars;
}
-
mbox_mem_align->size = sizeof(struct be_mcc_mailbox);
mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
- mc_cmd_mem->size = sizeof(struct be_cmd_req_mcast_mac_config);
- mc_cmd_mem->va = dma_alloc_coherent(&adapter->pdev->dev,
- mc_cmd_mem->size, &mc_cmd_mem->dma,
- GFP_KERNEL);
- if (mc_cmd_mem->va == NULL) {
+ rx_filter->size = sizeof(struct be_cmd_req_rx_filter);
+ rx_filter->va = dma_alloc_coherent(&adapter->pdev->dev, rx_filter->size,
+ &rx_filter->dma, GFP_KERNEL);
+ if (rx_filter->va == NULL) {
status = -ENOMEM;
goto free_mbox;
}
- memset(mc_cmd_mem->va, 0, mc_cmd_mem->size);
+ memset(rx_filter->va, 0, rx_filter->size);
mutex_init(&adapter->mbox_lock);
spin_lock_init(&adapter->mcc_lock);
@@ -3167,7 +3177,6 @@ static void __devexit be_remove(struct pci_dev *pdev)
be_ctrl_cleanup(adapter);
- kfree(adapter->vf_cfg);
be_sriov_disable(adapter);
be_msix_disable(adapter);
@@ -3182,35 +3191,13 @@ static void __devexit be_remove(struct pci_dev *pdev)
static int be_get_config(struct be_adapter *adapter)
{
int status;
- u8 mac[ETH_ALEN];
-
- status = be_cmd_get_fw_ver(adapter, adapter->fw_ver);
- if (status)
- return status;
status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
&adapter->function_mode, &adapter->function_caps);
if (status)
return status;
- memset(mac, 0, ETH_ALEN);
-
- /* A default permanent address is given to each VF for Lancer*/
- if (be_physfn(adapter) || lancer_chip(adapter)) {
- status = be_cmd_mac_addr_query(adapter, mac,
- MAC_ADDRESS_TYPE_NETWORK, true /*permanent */, 0);
-
- if (status)
- return status;
-
- if (!is_valid_ether_addr(mac))
- return -EADDRNOTAVAIL;
-
- memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
- memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
- }
-
- if (adapter->function_mode & 0x400)
+ if (adapter->function_mode & FLEX10_MODE)
adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4;
else
adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
@@ -3219,16 +3206,6 @@ static int be_get_config(struct be_adapter *adapter)
if (status)
return status;
- if ((num_vfs && adapter->sriov_enabled) ||
- (adapter->function_mode & 0x400) ||
- lancer_chip(adapter) || !be_physfn(adapter)) {
- adapter->num_tx_qs = 1;
- netif_set_real_num_tx_queues(adapter->netdev,
- adapter->num_tx_qs);
- } else {
- adapter->num_tx_qs = MAX_TX_QS;
- }
-
return 0;
}
@@ -3358,18 +3335,13 @@ static int __devinit be_probe(struct pci_dev *pdev,
}
}
- be_sriov_enable(adapter);
- if (adapter->sriov_enabled) {
- adapter->vf_cfg = kcalloc(num_vfs,
- sizeof(struct be_vf_cfg), GFP_KERNEL);
-
- if (!adapter->vf_cfg)
- goto free_netdev;
- }
+ status = be_sriov_enable(adapter);
+ if (status)
+ goto free_netdev;
status = be_ctrl_init(adapter);
if (status)
- goto free_vf_cfg;
+ goto disable_sriov;
if (lancer_chip(adapter)) {
status = lancer_test_and_set_rdy_state(adapter);
@@ -3412,6 +3384,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
be_msix_enable(adapter);
INIT_DELAYED_WORK(&adapter->work, be_worker);
+ adapter->rx_fc = adapter->tx_fc = true;
status = be_setup(adapter);
if (status)
@@ -3421,36 +3394,12 @@ static int __devinit be_probe(struct pci_dev *pdev,
status = register_netdev(netdev);
if (status != 0)
goto unsetup;
- netif_carrier_off(netdev);
-
- if (be_physfn(adapter) && adapter->sriov_enabled) {
- u8 mac_speed;
- bool link_up;
- u16 vf, lnk_speed;
-
- if (!lancer_chip(adapter)) {
- status = be_vf_eth_addr_config(adapter);
- if (status)
- goto unreg_netdev;
- }
-
- for (vf = 0; vf < num_vfs; vf++) {
- status = be_cmd_link_status_query(adapter, &link_up,
- &mac_speed, &lnk_speed, vf + 1);
- if (!status)
- adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10;
- else
- goto unreg_netdev;
- }
- }
dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
return 0;
-unreg_netdev:
- unregister_netdev(netdev);
unsetup:
be_clear(adapter);
msix_disable:
@@ -3459,10 +3408,9 @@ stats_clean:
be_stats_cleanup(adapter);
ctrl_clean:
be_ctrl_cleanup(adapter);
-free_vf_cfg:
- kfree(adapter->vf_cfg);
-free_netdev:
+disable_sriov:
be_sriov_disable(adapter);
+free_netdev:
free_netdev(netdev);
pci_set_drvdata(pdev, NULL);
rel_reg:
@@ -3489,7 +3437,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
be_close(netdev);
rtnl_unlock();
}
- be_cmd_get_flow_control(adapter, &adapter->tx_fc, &adapter->rx_fc);
be_clear(adapter);
be_msix_disable(adapter);
diff --git a/drivers/net/ethoc.c b/drivers/net/ethernet/ethoc.c
index 8abbe1d82826..bdb348a5ccf6 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -888,7 +888,7 @@ static const struct net_device_ops ethoc_netdev_ops = {
.ndo_do_ioctl = ethoc_ioctl,
.ndo_set_config = ethoc_config,
.ndo_set_mac_address = ethoc_set_mac_address,
- .ndo_set_multicast_list = ethoc_set_multicast_list,
+ .ndo_set_rx_mode = ethoc_set_multicast_list,
.ndo_change_mtu = ethoc_change_mtu,
.ndo_tx_timeout = ethoc_tx_timeout,
.ndo_start_xmit = ethoc_start_xmit,
diff --git a/drivers/net/ethernet/faraday/Kconfig b/drivers/net/ethernet/faraday/Kconfig
new file mode 100644
index 000000000000..b8974b9e3b47
--- /dev/null
+++ b/drivers/net/ethernet/faraday/Kconfig
@@ -0,0 +1,40 @@
+#
+# Faraday device configuration
+#
+
+config NET_VENDOR_FARADAY
+ bool "Faraday devices"
+ default y
+ depends on ARM
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Faraday cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_FARADAY
+
+config FTMAC100
+ tristate "Faraday FTMAC100 10/100 Ethernet support"
+ depends on ARM
+ select NET_CORE
+ select MII
+ ---help---
+ This driver supports the FTMAC100 10/100 Ethernet controller
+ from Faraday. It is used on Faraday A320, Andes AG101 and some
+ other ARM/NDS32 SoC's.
+
+config FTGMAC100
+ tristate "Faraday FTGMAC100 Gigabit Ethernet support"
+ depends on ARM
+ select PHYLIB
+ ---help---
+ This driver supports the FTGMAC100 Gigabit Ethernet controller
+ from Faraday. It is used on Faraday A369, Andes AG102 and some
+ other ARM/NDS32 SoC's.
+
+endif # NET_VENDOR_FARADAY
diff --git a/drivers/net/ethernet/faraday/Makefile b/drivers/net/ethernet/faraday/Makefile
new file mode 100644
index 000000000000..408b53980d53
--- /dev/null
+++ b/drivers/net/ethernet/faraday/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Faraday device drivers.
+#
+
+obj-$(CONFIG_FTGMAC100) += ftgmac100.o
+obj-$(CONFIG_FTMAC100) += ftmac100.o
diff --git a/drivers/net/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 54709af917e9..fb5579a3b19d 100644
--- a/drivers/net/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -467,7 +467,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
skb->len += size;
skb->data_len += size;
- skb->truesize += size;
+ skb->truesize += PAGE_SIZE;
if (ftgmac100_rxdes_last_segment(rxdes))
done = true;
@@ -478,6 +478,8 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
rxdes = ftgmac100_current_rxdes(priv);
} while (!done);
+ if (skb->len <= 64)
+ skb->truesize -= PAGE_SIZE;
__pskb_pull_tail(skb, min(skb->len, 64U));
skb->protocol = eth_type_trans(skb, netdev);
diff --git a/drivers/net/ftgmac100.h b/drivers/net/ethernet/faraday/ftgmac100.h
index 13408d448b05..13408d448b05 100644
--- a/drivers/net/ftgmac100.h
+++ b/drivers/net/ethernet/faraday/ftgmac100.h
diff --git a/drivers/net/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c
index 9bd7746cbfcf..a127cb2476c7 100644
--- a/drivers/net/ftmac100.c
+++ b/drivers/net/ethernet/faraday/ftmac100.c
@@ -439,7 +439,10 @@ static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed)
skb_fill_page_desc(skb, 0, page, 0, length);
skb->len += length;
skb->data_len += length;
- skb->truesize += length;
+
+ /* page might be freed in __pskb_pull_tail() */
+ if (length > 64)
+ skb->truesize += PAGE_SIZE;
__pskb_pull_tail(skb, min(length, 64));
ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
diff --git a/drivers/net/ftmac100.h b/drivers/net/ethernet/faraday/ftmac100.h
index 46a0c47b1ee1..46a0c47b1ee1 100644
--- a/drivers/net/ftmac100.h
+++ b/drivers/net/ethernet/faraday/ftmac100.h
diff --git a/drivers/net/fealnx.c b/drivers/net/ethernet/fealnx.c
index fa8677c32384..61d2bddec1fa 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/ethernet/fealnx.c
@@ -469,7 +469,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_stop = netdev_close,
.ndo_start_xmit = start_tx,
.ndo_get_stats = get_stats,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = mii_ioctl,
.ndo_tx_timeout = fealnx_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
new file mode 100644
index 000000000000..1cf671643d1f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -0,0 +1,88 @@
+#
+# Freescale device configuration
+#
+
+config NET_VENDOR_FREESCALE
+ bool "Freescale devices"
+ default y
+ depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \
+ M523x || M527x || M5272 || M528x || M520x || M532x || \
+ ARCH_MXC || ARCH_MXS || \
+ (PPC_MPC52xx && PPC_BESTCOMM)
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Freescale devices. If you say Y, you will be
+ asked for your specific card in the following questions.
+
+if NET_VENDOR_FREESCALE
+
+config FEC
+ bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
+ depends on (M523x || M527x || M5272 || M528x || M520x || M532x || \
+ ARCH_MXC || ARCH_MXS)
+ select PHYLIB
+ ---help---
+ Say Y here if you want to use the built-in 10/100 Fast ethernet
+ controller on some Motorola ColdFire and Freescale i.MX processors.
+
+config FEC_MPC52xx
+ tristate "FEC MPC52xx driver"
+ depends on PPC_MPC52xx && PPC_BESTCOMM
+ select CRC32
+ select PHYLIB
+ select PPC_BESTCOMM_FEC
+ ---help---
+ This option enables support for the MPC5200's on-chip
+ Fast Ethernet Controller
+ If compiled as module, it will be called fec_mpc52xx.
+
+config FEC_MPC52xx_MDIO
+ bool "FEC MPC52xx MDIO bus driver"
+ depends on FEC_MPC52xx
+ default y
+ ---help---
+ The MPC5200's FEC can connect to the Ethernet either with
+ an external MII PHY chip or 10 Mbps 7-wire interface
+ (Motorola? industry standard).
+ If your board uses an external PHY connected to FEC, enable this.
+ If not sure, enable.
+ If compiled as module, it will be called fec_mpc52xx_phy.
+
+source "drivers/net/ethernet/freescale/fs_enet/Kconfig"
+
+config FSL_PQ_MDIO
+ tristate "Freescale PQ MDIO"
+ depends on FSL_SOC
+ select PHYLIB
+ ---help---
+ This driver supports the MDIO bus used by the gianfar and UCC drivers.
+
+config UCC_GETH
+ tristate "Freescale QE Gigabit Ethernet"
+ depends on QUICC_ENGINE
+ select FSL_PQ_MDIO
+ select PHYLIB
+ ---help---
+ This driver supports the Gigabit Ethernet mode of the QUICC Engine,
+ which is available on some Freescale SOCs.
+
+config UGETH_TX_ON_DEMAND
+ bool "Transmit on Demand support"
+ depends on UCC_GETH
+
+config GIANFAR
+ tristate "Gianfar Ethernet"
+ depends on FSL_SOC
+ select FSL_PQ_MDIO
+ select PHYLIB
+ select CRC32
+ ---help---
+ This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
+ and MPC86xx family of chips, and the FEC on the 8540.
+
+endif # NET_VENDOR_FREESCALE
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
new file mode 100644
index 000000000000..1752488c9ee5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Freescale network device drivers.
+#
+
+obj-$(CONFIG_FEC) += fec.o
+obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
+ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
+ obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
+endif
+obj-$(CONFIG_FS_ENET) += fs_enet/
+obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o
+obj-$(CONFIG_GIANFAR) += gianfar_driver.o
+obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
+gianfar_driver-objs := gianfar.o \
+ gianfar_ethtool.o \
+ gianfar_sysfs.o
+obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
+ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
diff --git a/drivers/net/fec.c b/drivers/net/ethernet/freescale/fec.c
index e8266ccf818a..1124ce0a1594 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -18,7 +18,7 @@
* Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
* Copyright (c) 2004-2006 Macq Electronique SA.
*
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
*/
#include <linux/module.h>
@@ -72,6 +72,8 @@
#define FEC_QUIRK_SWAP_FRAME (1 << 1)
/* Controller uses gasket */
#define FEC_QUIRK_USE_GASKET (1 << 2)
+/* Controller has GBIT support */
+#define FEC_QUIRK_HAS_GBIT (1 << 3)
static struct platform_device_id fec_devtype[] = {
{
@@ -88,6 +90,9 @@ static struct platform_device_id fec_devtype[] = {
.name = "imx28-fec",
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
}, {
+ .name = "imx6q-fec",
+ .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT,
+ }, {
/* sentinel */
}
};
@@ -97,12 +102,14 @@ enum imx_fec_type {
IMX25_FEC = 1, /* runs on i.mx25/50/53 */
IMX27_FEC, /* runs on i.mx27/35/51 */
IMX28_FEC,
+ IMX6Q_FEC,
};
static const struct of_device_id fec_dt_ids[] = {
{ .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], },
{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
+ { .compatible = "fsl,imx6q-fec", .data = &fec_devtype[IMX6Q_FEC], },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fec_dt_ids);
@@ -170,6 +177,8 @@ 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
@@ -233,6 +242,7 @@ struct fec_enet_private {
int link;
int full_duplex;
struct completion mdio_done;
+ int irq[FEC_IRQ_NUM];
};
/* FEC MII MMFR bits definition */
@@ -373,6 +383,7 @@ fec_restart(struct net_device *ndev, int duplex)
int i;
u32 temp_mac[2];
u32 rcntl = OPT_FRAME_SIZE | 0x04;
+ u32 ecntl = 0x2; /* ETHEREN */
/* Whack a reset. We should wait for this. */
writel(1, fep->hwp + FEC_ECNTRL);
@@ -442,18 +453,23 @@ fec_restart(struct net_device *ndev, int duplex)
/* Enable flow control and length check */
rcntl |= 0x40000000 | 0x00000020;
- /* MII or RMII */
- if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
+ /* RGMII, RMII or MII */
+ if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII)
+ rcntl |= (1 << 6);
+ else if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
rcntl |= (1 << 8);
else
rcntl &= ~(1 << 8);
- /* 10M or 100M */
- if (fep->phy_dev && fep->phy_dev->speed == SPEED_100)
- rcntl &= ~(1 << 9);
- else
- rcntl |= (1 << 9);
-
+ /* 1G, 100M or 10M */
+ if (fep->phy_dev) {
+ if (fep->phy_dev->speed == SPEED_1000)
+ ecntl |= (1 << 5);
+ else if (fep->phy_dev->speed == SPEED_100)
+ rcntl &= ~(1 << 9);
+ else
+ rcntl |= (1 << 9);
+ }
} else {
#ifdef FEC_MIIGSK_ENR
if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) {
@@ -478,8 +494,15 @@ fec_restart(struct net_device *ndev, int duplex)
}
writel(rcntl, fep->hwp + FEC_R_CNTRL);
+ if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+ /* enable ENET endian swap */
+ ecntl |= (1 << 8);
+ /* enable ENET store and forward mode */
+ writel(1 << 8, fep->hwp + FEC_X_WMRK);
+ }
+
/* And last, enable the transmit and receive processing */
- writel(2, fep->hwp + FEC_ECNTRL);
+ writel(ecntl, fep->hwp + FEC_ECNTRL);
writel(0, fep->hwp + FEC_R_DES_ACTIVE);
/* Enable interrupts we wish to service */
@@ -490,6 +513,8 @@ static void
fec_stop(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
+ const struct platform_device_id *id_entry =
+ platform_get_device_id(fep->pdev);
/* We cannot expect a graceful transmit stop without link !!! */
if (fep->link) {
@@ -504,6 +529,10 @@ fec_stop(struct net_device *ndev)
udelay(10);
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+
+ /* We have to keep ENET enabled to have MII interrupt stay working */
+ if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
+ writel(2, fep->hwp + FEC_ECNTRL);
}
@@ -918,6 +947,8 @@ static int fec_enet_mdio_reset(struct mii_bus *bus)
static int fec_enet_mii_probe(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
+ const struct platform_device_id *id_entry =
+ platform_get_device_id(fep->pdev);
struct phy_device *phy_dev = NULL;
char mdio_bus_id[MII_BUS_ID_SIZE];
char phy_name[MII_BUS_ID_SIZE + 3];
@@ -949,14 +980,18 @@ static int fec_enet_mii_probe(struct net_device *ndev)
snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
+ fep->phy_interface);
if (IS_ERR(phy_dev)) {
printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name);
return PTR_ERR(phy_dev);
}
/* mask with MAC supported features */
- phy_dev->supported &= PHY_BASIC_FEATURES;
+ if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT)
+ phy_dev->supported &= PHY_GBIT_FEATURES;
+ else
+ phy_dev->supported &= PHY_BASIC_FEATURES;
+
phy_dev->advertising = phy_dev->supported;
fep->phy_dev = phy_dev;
@@ -996,7 +1031,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
* mdio interface in board design, and need to be configured by
* fec0 mii_bus.
*/
- if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && pdev->id) {
+ if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && pdev->id > 0) {
/* fec1 uses fec0 mii_bus */
fep->mii_bus = fec0_mii_bus;
return 0;
@@ -1006,8 +1041,16 @@ static int fec_enet_mii_init(struct platform_device *pdev)
/*
* Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed)
+ *
+ * The formula for FEC MDC is 'ref_freq / (MII_SPEED x 2)' while
+ * for ENET-MAC is 'ref_freq / ((MII_SPEED + 1) x 2)'. The i.MX28
+ * Reference Manual has an error on this, and gets fixed on i.MX6Q
+ * document.
*/
- fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000) << 1;
+ fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000);
+ if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
+ fep->phy_speed--;
+ fep->phy_speed <<= 1;
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
fep->mii_bus = mdiobus_alloc();
@@ -1321,16 +1364,42 @@ fec_set_mac_address(struct net_device *ndev, void *p)
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * fec_poll_controller: FEC Poll controller function
+ * @dev: The FEC network adapter
+ *
+ * Polled functionality used by netconsole and others in non interrupt mode
+ *
+ */
+void fec_poll_controller(struct net_device *dev)
+{
+ int i;
+ struct fec_enet_private *fep = netdev_priv(dev);
+
+ for (i = 0; i < FEC_IRQ_NUM; i++) {
+ if (fep->irq[i] > 0) {
+ disable_irq(fep->irq[i]);
+ fec_enet_interrupt(fep->irq[i], dev);
+ enable_irq(fep->irq[i]);
+ }
+ }
+}
+#endif
+
static const struct net_device_ops fec_netdev_ops = {
.ndo_open = fec_enet_open,
.ndo_stop = fec_enet_close,
.ndo_start_xmit = fec_enet_start_xmit,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = fec_timeout,
.ndo_set_mac_address = fec_set_mac_address,
.ndo_do_ioctl = fec_enet_ioctl,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = fec_poll_controller,
+#endif
};
/*
@@ -1411,24 +1480,22 @@ static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
return -ENODEV;
}
-static int __devinit fec_reset_phy(struct platform_device *pdev)
+static void __devinit fec_reset_phy(struct platform_device *pdev)
{
int err, phy_reset;
struct device_node *np = pdev->dev.of_node;
if (!np)
- return -ENODEV;
+ return;
phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
err = gpio_request_one(phy_reset, GPIOF_OUT_INIT_LOW, "phy-reset");
if (err) {
- pr_warn("FEC: failed to get gpio phy-reset: %d\n", err);
- return err;
+ pr_debug("FEC: failed to get gpio phy-reset: %d\n", err);
+ return;
}
msleep(1);
gpio_set_value(phy_reset, 1);
-
- return 0;
}
#else /* CONFIG_OF */
static inline int fec_get_phy_mode_dt(struct platform_device *pdev)
@@ -1436,13 +1503,12 @@ static inline int fec_get_phy_mode_dt(struct platform_device *pdev)
return -ENODEV;
}
-static inline int fec_reset_phy(struct platform_device *pdev)
+static inline void fec_reset_phy(struct platform_device *pdev)
{
/*
* In case of platform probe, the reset has been done
* by machine code.
*/
- return 0;
}
#endif /* CONFIG_OF */
@@ -1503,8 +1569,7 @@ fec_probe(struct platform_device *pdev)
fec_reset_phy(pdev);
- /* This device has up to three irqs on some platforms */
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < FEC_IRQ_NUM; i++) {
irq = platform_get_irq(pdev, i);
if (i && irq < 0)
break;
@@ -1549,7 +1614,7 @@ failed_init:
clk_disable(fep->clk);
clk_put(fep->clk);
failed_clk:
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < FEC_IRQ_NUM; i++) {
irq = platform_get_irq(pdev, i);
if (irq > 0)
free_irq(irq, ndev);
diff --git a/drivers/net/fec.h b/drivers/net/ethernet/freescale/fec.h
index 8b2c6d797e6d..8b2c6d797e6d 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index cb4416e591f1..30745b56fe5d 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -828,7 +828,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = {
.ndo_open = mpc52xx_fec_open,
.ndo_stop = mpc52xx_fec_close,
.ndo_start_xmit = mpc52xx_fec_start_xmit,
- .ndo_set_multicast_list = mpc52xx_fec_set_multicast_list,
+ .ndo_set_rx_mode = mpc52xx_fec_set_multicast_list,
.ndo_set_mac_address = mpc52xx_fec_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = mpc52xx_fec_ioctl,
diff --git a/drivers/net/fec_mpc52xx.h b/drivers/net/ethernet/freescale/fec_mpc52xx.h
index 41d2dffde55b..41d2dffde55b 100644
--- a/drivers/net/fec_mpc52xx.h
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.h
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c
index 360a578c2bb7..360a578c2bb7 100644
--- a/drivers/net/fec_mpc52xx_phy.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/ethernet/freescale/fs_enet/Kconfig
index fc073b5a38c7..268414d9f2cb 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/ethernet/freescale/fs_enet/Kconfig
@@ -1,6 +1,7 @@
config FS_ENET
tristate "Freescale Ethernet Driver"
- depends on CPM1 || CPM2 || PPC_MPC512x
+ depends on NET_VENDOR_FREESCALE && (CPM1 || CPM2 || PPC_MPC512x)
+ select NET_CORE
select MII
select PHYLIB
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/ethernet/freescale/fs_enet/Makefile
index d4a305ee3455..d4a305ee3455 100644
--- a/drivers/net/fs_enet/Makefile
+++ b/drivers/net/ethernet/freescale/fs_enet/Makefile
diff --git a/drivers/net/fs_enet/fec.h b/drivers/net/ethernet/freescale/fs_enet/fec.h
index e980527e2b99..e980527e2b99 100644
--- a/drivers/net/fs_enet/fec.h
+++ b/drivers/net/ethernet/freescale/fs_enet/fec.h
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 329ef231a096..5bf5471f06ff 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -988,7 +988,7 @@ static const struct net_device_ops fs_enet_netdev_ops = {
.ndo_get_stats = fs_enet_get_stats,
.ndo_start_xmit = fs_enet_start_xmit,
.ndo_tx_timeout = fs_timeout,
- .ndo_set_multicast_list = fs_set_multicast_list,
+ .ndo_set_rx_mode = fs_set_multicast_list,
.ndo_do_ioctl = fs_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h
index 1ece4b1a689e..1ece4b1a689e 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
index 7583a9572bcc..7583a9572bcc 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
index b9fbc83d64a7..b9fbc83d64a7 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
index 22a02a767069..22a02a767069 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
index b09270b5d0a5..b09270b5d0a5 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
index e0e9d6c35d83..e0e9d6c35d83 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
index 52f4e8ad48e7..52f4e8ad48e7 100644
--- a/drivers/net/fsl_pq_mdio.c
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
diff --git a/drivers/net/fsl_pq_mdio.h b/drivers/net/ethernet/freescale/fsl_pq_mdio.h
index bd17a2a0139b..bd17a2a0139b 100644
--- a/drivers/net/fsl_pq_mdio.h
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.h
diff --git a/drivers/net/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 31d5c574e5a9..83199fd0d62b 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -458,7 +458,7 @@ static const struct net_device_ops gfar_netdev_ops = {
.ndo_stop = gfar_close,
.ndo_change_mtu = gfar_change_mtu,
.ndo_set_features = gfar_set_features,
- .ndo_set_multicast_list = gfar_set_multi,
+ .ndo_set_rx_mode = gfar_set_multi,
.ndo_tx_timeout = gfar_timeout,
.ndo_do_ioctl = gfar_ioctl,
.ndo_get_stats = gfar_get_stats,
@@ -2140,11 +2140,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (i == nr_frags - 1)
lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
- bufaddr = dma_map_page(&priv->ofdev->dev,
- skb_shinfo(skb)->frags[i].page,
- skb_shinfo(skb)->frags[i].page_offset,
- length,
- DMA_TO_DEVICE);
+ bufaddr = skb_frag_dma_map(&priv->ofdev->dev,
+ &skb_shinfo(skb)->frags[i],
+ 0,
+ length,
+ DMA_TO_DEVICE);
/* set the TxBD length and buffer pointer */
txbdp->bufPtr = bufaddr;
diff --git a/drivers/net/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 9aa43773e8e3..9aa43773e8e3 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 0caf3c323ec0..212736bab6bb 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -1676,6 +1676,7 @@ static int gfar_get_cls_all(struct gfar_private *priv,
}
cmd->data = MAX_FILER_IDX;
+ cmd->rule_cnt = i;
return 0;
}
@@ -1712,7 +1713,7 @@ static int gfar_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
}
static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
- void *rule_locs)
+ u32 *rule_locs)
{
struct gfar_private *priv = netdev_priv(dev);
int ret = 0;
@@ -1728,7 +1729,7 @@ static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
ret = gfar_get_cls(priv, cmd);
break;
case ETHTOOL_GRXCLSRLALL:
- ret = gfar_get_cls_all(priv, cmd, (u32 *) rule_locs);
+ ret = gfar_get_cls_all(priv, cmd, rule_locs);
break;
default:
ret = -EINVAL;
diff --git a/drivers/net/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c
index f67b8aebc89c..f67b8aebc89c 100644
--- a/drivers/net/gianfar_ptp.c
+++ b/drivers/net/ethernet/freescale/gianfar_ptp.c
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/ethernet/freescale/gianfar_sysfs.c
index 64f4094ac7f1..64f4094ac7f1 100644
--- a/drivers/net/gianfar_sysfs.c
+++ b/drivers/net/ethernet/freescale/gianfar_sysfs.c
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index d3465ab50e56..46d690a92c0b 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -1761,10 +1761,12 @@ static int init_phy(struct net_device *dev)
if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
uec_configure_serdes(dev);
- phydev->supported &= (ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full);
+ phydev->supported &= (SUPPORTED_MII |
+ SUPPORTED_Autoneg |
+ ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full);
if (priv->max_speed == SPEED_1000)
phydev->supported |= ADVERTISED_1000baseT_Full;
@@ -3729,7 +3731,7 @@ static const struct net_device_ops ucc_geth_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ucc_geth_set_mac_addr,
.ndo_change_mtu = eth_change_mtu,
- .ndo_set_multicast_list = ucc_geth_set_multi,
+ .ndo_set_rx_mode = ucc_geth_set_multi,
.ndo_tx_timeout = ucc_geth_timeout,
.ndo_do_ioctl = ucc_geth_ioctl,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ethernet/freescale/ucc_geth.h
index d12fcad145e9..d12fcad145e9 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ethernet/freescale/ucc_geth.h
diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
index a97257f91a3d..a97257f91a3d 100644
--- a/drivers/net/ucc_geth_ethtool.c
+++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
diff --git a/drivers/net/ethernet/fujitsu/Kconfig b/drivers/net/ethernet/fujitsu/Kconfig
new file mode 100644
index 000000000000..dffee9d44fd5
--- /dev/null
+++ b/drivers/net/ethernet/fujitsu/Kconfig
@@ -0,0 +1,54 @@
+#
+# Fujitsu Network device configuration
+#
+
+config NET_VENDOR_FUJITSU
+ bool "Fujitsu devices"
+ default y
+ depends on ISA || PCMCIA || ((ISA || MCA_LEGACY) && EXPERIMENTAL)
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ the questions about Fujitsu cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_FUJITSU
+
+config AT1700
+ tristate "AT1700/1720 support (EXPERIMENTAL)"
+ depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
+ select CRC32
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called at1700.
+
+config PCMCIA_FMVJ18X
+ tristate "Fujitsu FMV-J18x PCMCIA support"
+ depends on PCMCIA
+ select CRC32
+ ---help---
+ Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible
+ PCMCIA (PC-card) Ethernet card to your computer.
+
+ To compile this driver as a module, choose M here: the module will be
+ called fmvj18x_cs. If unsure, say N.
+
+config ETH16I
+ tristate "ICL EtherTeam 16i/32 support"
+ depends on ISA
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called eth16i.
+
+endif # NET_VENDOR_FUJITSU
diff --git a/drivers/net/ethernet/fujitsu/Makefile b/drivers/net/ethernet/fujitsu/Makefile
new file mode 100644
index 000000000000..2730ae67d3aa
--- /dev/null
+++ b/drivers/net/ethernet/fujitsu/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Fujitsu network device drivers.
+#
+
+obj-$(CONFIG_AT1700) += at1700.o
+obj-$(CONFIG_ETH16I) += eth16i.o
+obj-$(CONFIG_PCMCIA_FMVJ18X) += fmvj18x_cs.o
diff --git a/drivers/net/at1700.c b/drivers/net/ethernet/fujitsu/at1700.c
index 65a78f965dd2..7c6c908bdf02 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/ethernet/fujitsu/at1700.c
@@ -253,7 +253,7 @@ static const struct net_device_ops at1700_netdev_ops = {
.ndo_open = net_open,
.ndo_stop = net_close,
.ndo_start_xmit = net_send_packet,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_tx_timeout = net_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/eth16i.c b/drivers/net/ethernet/fujitsu/eth16i.c
index 12d28e9d0cb7..b0e2313af3d1 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/ethernet/fujitsu/eth16i.c
@@ -478,7 +478,7 @@ static const struct net_device_ops eth16i_netdev_ops = {
.ndo_open = eth16i_open,
.ndo_stop = eth16i_close,
.ndo_start_xmit = eth16i_tx,
- .ndo_set_multicast_list = eth16i_multicast,
+ .ndo_set_rx_mode = eth16i_multicast,
.ndo_tx_timeout = eth16i_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
index 723815e7a997..15416752c13e 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
@@ -226,7 +226,7 @@ static const struct net_device_ops fjn_netdev_ops = {
.ndo_start_xmit = fjn_start_xmit,
.ndo_tx_timeout = fjn_tx_timeout,
.ndo_set_config = fjn_config,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/ethernet/hp/Kconfig b/drivers/net/ethernet/hp/Kconfig
new file mode 100644
index 000000000000..a0b8ece1e3bc
--- /dev/null
+++ b/drivers/net/ethernet/hp/Kconfig
@@ -0,0 +1,32 @@
+#
+# HP network device configuration
+#
+
+config NET_VENDOR_HP
+ bool "HP devices"
+ default y
+ depends on ISA || EISA || PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about HP cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_HP
+
+config HP100
+ tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
+ depends on (ISA || EISA || PCI)
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called hp100.
+
+endif # NET_VENDOR_HP
diff --git a/drivers/net/ethernet/hp/Makefile b/drivers/net/ethernet/hp/Makefile
new file mode 100644
index 000000000000..20b6918b52bd
--- /dev/null
+++ b/drivers/net/ethernet/hp/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the HP network device drivers.
+#
+
+obj-$(CONFIG_HP100) += hp100.o
diff --git a/drivers/net/hp100.c b/drivers/net/ethernet/hp/hp100.c
index b6519c1ba7e1..6a5ee0776b28 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/ethernet/hp/hp100.c
@@ -430,7 +430,7 @@ static const struct net_device_ops hp100_bm_netdev_ops = {
.ndo_stop = hp100_close,
.ndo_start_xmit = hp100_start_xmit_bm,
.ndo_get_stats = hp100_get_stats,
- .ndo_set_multicast_list = hp100_set_multicast_list,
+ .ndo_set_rx_mode = hp100_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
@@ -441,7 +441,7 @@ static const struct net_device_ops hp100_netdev_ops = {
.ndo_stop = hp100_close,
.ndo_start_xmit = hp100_start_xmit,
.ndo_get_stats = hp100_get_stats,
- .ndo_set_multicast_list = hp100_set_multicast_list,
+ .ndo_set_rx_mode = hp100_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/hp100.h b/drivers/net/ethernet/hp/hp100.h
index b60e96fe38b4..b60e96fe38b4 100644
--- a/drivers/net/hp100.h
+++ b/drivers/net/ethernet/hp/hp100.h
diff --git a/drivers/net/3c505.c b/drivers/net/ethernet/i825xx/3c505.c
index 88d766ee0e1b..40e1a175fceb 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/ethernet/i825xx/3c505.c
@@ -1363,7 +1363,7 @@ static const struct net_device_ops elp_netdev_ops = {
.ndo_get_stats = elp_get_stats,
.ndo_start_xmit = elp_start_xmit,
.ndo_tx_timeout = elp_timeout,
- .ndo_set_multicast_list = elp_set_mc_list,
+ .ndo_set_rx_mode = elp_set_mc_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/3c505.h b/drivers/net/ethernet/i825xx/3c505.h
index 04df2a9002b6..04df2a9002b6 100644
--- a/drivers/net/3c505.h
+++ b/drivers/net/ethernet/i825xx/3c505.h
diff --git a/drivers/net/3c507.c b/drivers/net/ethernet/i825xx/3c507.c
index 1e945551c144..1e945551c144 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/ethernet/i825xx/3c507.c
diff --git a/drivers/net/3c523.c b/drivers/net/ethernet/i825xx/3c523.c
index bc0d1a1c2e28..d70d3df4c985 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/ethernet/i825xx/3c523.c
@@ -409,7 +409,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_start_xmit = elmc_send_packet,
.ndo_tx_timeout = elmc_timeout,
#ifdef ELMC_MULTICAST
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
#endif
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/3c523.h b/drivers/net/ethernet/i825xx/3c523.h
index 6956441687b9..6956441687b9 100644
--- a/drivers/net/3c523.h
+++ b/drivers/net/ethernet/i825xx/3c523.h
diff --git a/drivers/net/3c527.c b/drivers/net/ethernet/i825xx/3c527.c
index d9d056d207f3..474b5e71a53a 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/ethernet/i825xx/3c527.c
@@ -292,7 +292,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_stop = mc32_close,
.ndo_start_xmit = mc32_send_packet,
.ndo_get_stats = mc32_get_stats,
- .ndo_set_multicast_list = mc32_set_multicast_list,
+ .ndo_set_rx_mode = mc32_set_multicast_list,
.ndo_tx_timeout = mc32_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/3c527.h b/drivers/net/ethernet/i825xx/3c527.h
index d693b8d15cde..d693b8d15cde 100644
--- a/drivers/net/3c527.h
+++ b/drivers/net/ethernet/i825xx/3c527.h
diff --git a/drivers/net/82596.c b/drivers/net/ethernet/i825xx/82596.c
index be1f1970c842..f2408a4d5d9c 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/ethernet/i825xx/82596.c
@@ -1145,7 +1145,7 @@ static const struct net_device_ops i596_netdev_ops = {
.ndo_open = i596_open,
.ndo_stop = i596_close,
.ndo_start_xmit = i596_start_xmit,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = i596_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ethernet/i825xx/Kconfig b/drivers/net/ethernet/i825xx/Kconfig
new file mode 100644
index 000000000000..ca1ae985c6df
--- /dev/null
+++ b/drivers/net/ethernet/i825xx/Kconfig
@@ -0,0 +1,183 @@
+#
+# Intel 82596/82593/82596 network device configuration
+#
+
+config NET_VENDOR_I825XX
+ bool "Intel (82586/82593/82596) devices"
+ default y
+ depends on NET_VENDOR_INTEL && (ISA || ISA_DMA_API || ARM || \
+ ARCH_ACORN || MCA || MCA_LEGACY || SNI_RM || SUN3 || \
+ GSC || BVME6000 || MVME16x || EXPERIMENTAL)
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question does not directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about these devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_I825XX
+
+config ELPLUS
+ tristate "3c505 \"EtherLink Plus\" support"
+ depends on ISA && ISA_DMA_API
+ ---help---
+ Information about this network (Ethernet) card can be found in
+ <file:Documentation/networking/3c505.txt>. If you have a card of
+ this type, say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called 3c505.
+
+config EL16
+ tristate "3c507 \"EtherLink 16\" support (EXPERIMENTAL)"
+ depends on ISA && EXPERIMENTAL
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called 3c507.
+
+config ELMC
+ tristate "3c523 \"EtherLink/MC\" support"
+ depends on MCA_LEGACY
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called 3c523.
+
+config ELMC_II
+ tristate "3c527 \"EtherLink/MC 32\" support (EXPERIMENTAL)"
+ depends on MCA && MCA_LEGACY
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called 3c527.
+
+config ARM_ETHER1
+ tristate "Acorn Ether1 support"
+ depends on ARM && ARCH_ACORN
+ ---help---
+ If you have an Acorn system with one of these (AKA25) network cards,
+ you should say Y to this option if you wish to use it with Linux.
+
+config APRICOT
+ tristate "Apricot Xen-II on board Ethernet"
+ depends on ISA
+ ---help---
+ If you have a network (Ethernet) controller of this type, say Y and
+ read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called apricot.
+
+config BVME6000_NET
+ tristate "BVME6000 Ethernet support"
+ depends on BVME6000
+ ---help---
+ This is the driver for the Ethernet interface on BVME4000 and
+ BVME6000 VME boards. Say Y here to include the driver for this chip
+ in your kernel.
+ To compile this driver as a module, choose M here.
+
+config EEXPRESS
+ tristate "EtherExpress 16 support"
+ depends on ISA
+ ---help---
+ If you have an EtherExpress16 network (Ethernet) card, say Y and
+ read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Note that the Intel
+ EtherExpress16 card used to be regarded as a very poor choice
+ because the driver was very unreliable. We now have a new driver
+ that should do better.
+
+ To compile this driver as a module, choose M here. The module
+ will be called eexpress.
+
+config EEXPRESS_PRO
+ tristate "EtherExpressPro support/EtherExpress 10 (i82595) support"
+ depends on ISA
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y. This
+ driver supports Intel i82595{FX,TX} based boards. Note however
+ that the EtherExpress PRO/100 Ethernet card has its own separate
+ driver. Please read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called eepro.
+
+config LASI_82596
+ tristate "Lasi ethernet"
+ depends on GSC
+ ---help---
+ Say Y here to support the builtin Intel 82596 ethernet controller
+ found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
+
+config LP486E
+ tristate "LP486E on board Ethernet"
+ depends on ISA
+ ---help---
+ Say Y here to support the 82596-based on-board Ethernet controller
+ for the Panther motherboard, which is one of the two shipped in the
+ Intel Professional Workstation.
+
+config MVME16x_NET
+ tristate "MVME16x Ethernet support"
+ depends on MVME16x
+ ---help---
+ This is the driver for the Ethernet interface on the Motorola
+ MVME162, 166, 167, 172 and 177 boards. Say Y here to include the
+ driver for this chip in your kernel.
+ To compile this driver as a module, choose M here.
+
+config NI52
+ tristate "NI5210 support"
+ depends on ISA
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ni52.
+
+config SNI_82596
+ tristate "SNI RM ethernet"
+ depends on SNI_RM
+ ---help---
+ Say Y here to support the on-board Intel 82596 ethernet controller
+ built into SNI RM machines.
+
+config SUN3_82586
+ bool "Sun3 on-board Intel 82586 support"
+ depends on SUN3
+ ---help---
+ This driver enables support for the on-board Intel 82586 based
+ Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note
+ that this driver does not support 82586-based adapters on additional
+ VME boards.
+
+config ZNET
+ tristate "Zenith Z-Note support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && ISA_DMA_API
+ ---help---
+ The Zenith Z-Note notebook computer has a built-in network
+ (Ethernet) card, and this is the Linux driver for it. Note that the
+ IBM Thinkpad 300 is compatible with the Z-Note and is also supported
+ by this driver. Read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+endif # NET_VENDOR_I825XX
diff --git a/drivers/net/ethernet/i825xx/Makefile b/drivers/net/ethernet/i825xx/Makefile
new file mode 100644
index 000000000000..f68a3694968a
--- /dev/null
+++ b/drivers/net/ethernet/i825xx/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for the Intel 82586/82593/82596 chipset device drivers.
+#
+
+obj-$(CONFIG_ARM_ETHER1) += ether1.o
+obj-$(CONFIG_EEXPRESS) += eexpress.o
+obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
+obj-$(CONFIG_ELPLUS) += 3c505.o
+obj-$(CONFIG_EL16) += 3c507.o
+obj-$(CONFIG_ELMC) += 3c523.o
+obj-$(CONFIG_ELMC_II) += 3c527.o
+obj-$(CONFIG_LP486E) += lp486e.o
+obj-$(CONFIG_NI52) += ni52.o
+obj-$(CONFIG_SUN3_82586) += sun3_82586.o
+obj-$(CONFIG_ZNET) += znet.o
+obj-$(CONFIG_APRICOT) += 82596.o
+obj-$(CONFIG_LASI_82596) += lasi_82596.o
+obj-$(CONFIG_SNI_82596) += sni_82596.o
+obj-$(CONFIG_MVME16x_NET) += 82596.o
+obj-$(CONFIG_BVME6000_NET) += 82596.o
diff --git a/drivers/net/eepro.c b/drivers/net/ethernet/i825xx/eepro.c
index dfeb006035df..067c46069a11 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/ethernet/i825xx/eepro.c
@@ -743,7 +743,7 @@ static const struct net_device_ops eepro_netdev_ops = {
.ndo_open = eepro_open,
.ndo_stop = eepro_close,
.ndo_start_xmit = eepro_send_packet,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = eepro_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/eexpress.c b/drivers/net/ethernet/i825xx/eexpress.c
index a19228563efd..3a9580f3d4dd 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/ethernet/i825xx/eexpress.c
@@ -1047,7 +1047,7 @@ static const struct net_device_ops eexp_netdev_ops = {
.ndo_open = eexp_open,
.ndo_stop = eexp_close,
.ndo_start_xmit = eexp_xmit,
- .ndo_set_multicast_list = eexp_set_multicast,
+ .ndo_set_rx_mode = eexp_set_multicast,
.ndo_tx_timeout = eexp_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/eexpress.h b/drivers/net/ethernet/i825xx/eexpress.h
index dc9c6ea289e9..dc9c6ea289e9 100644
--- a/drivers/net/eexpress.h
+++ b/drivers/net/ethernet/i825xx/eexpress.h
diff --git a/drivers/net/arm/ether1.c b/drivers/net/ethernet/i825xx/ether1.c
index b00781c02d5d..42e90a97c7a5 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/ethernet/i825xx/ether1.c
@@ -985,7 +985,7 @@ static const struct net_device_ops ether1_netdev_ops = {
.ndo_open = ether1_open,
.ndo_stop = ether1_close,
.ndo_start_xmit = ether1_sendpacket,
- .ndo_set_multicast_list = ether1_setmulticastlist,
+ .ndo_set_rx_mode = ether1_setmulticastlist,
.ndo_tx_timeout = ether1_timeout,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/arm/ether1.h b/drivers/net/ethernet/i825xx/ether1.h
index 3a5830ab3dc7..3a5830ab3dc7 100644
--- a/drivers/net/arm/ether1.h
+++ b/drivers/net/ethernet/i825xx/ether1.h
diff --git a/drivers/net/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c
index 6eba352c52e0..6eba352c52e0 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/ethernet/i825xx/lasi_82596.c
diff --git a/drivers/net/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c
index 9e042894479b..3efbd8dbb63d 100644
--- a/drivers/net/lib82596.c
+++ b/drivers/net/ethernet/i825xx/lib82596.c
@@ -1038,7 +1038,7 @@ static const struct net_device_ops i596_netdev_ops = {
.ndo_open = i596_open,
.ndo_stop = i596_close,
.ndo_start_xmit = i596_start_xmit,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = i596_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/lp486e.c b/drivers/net/ethernet/i825xx/lp486e.c
index 385a95311cd2..414044b3cb11 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/ethernet/i825xx/lp486e.c
@@ -954,7 +954,7 @@ static const struct net_device_ops i596_netdev_ops = {
.ndo_open = i596_open,
.ndo_stop = i596_close,
.ndo_start_xmit = i596_start_xmit,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = i596_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ni52.c b/drivers/net/ethernet/i825xx/ni52.c
index d973fc6c6b88..c0893715ef47 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ethernet/i825xx/ni52.c
@@ -445,7 +445,7 @@ static const struct net_device_ops ni52_netdev_ops = {
.ndo_get_stats = ni52_get_stats,
.ndo_tx_timeout = ni52_timeout,
.ndo_start_xmit = ni52_send_packet,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/ni52.h b/drivers/net/ethernet/i825xx/ni52.h
index 0a03b2883327..0a03b2883327 100644
--- a/drivers/net/ni52.h
+++ b/drivers/net/ethernet/i825xx/ni52.h
diff --git a/drivers/net/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c
index 6b2a88817473..6b2a88817473 100644
--- a/drivers/net/sni_82596.c
+++ b/drivers/net/ethernet/i825xx/sni_82596.c
diff --git a/drivers/net/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c
index b6ae53bada75..6ef5e11d1c84 100644
--- a/drivers/net/sun3_82586.c
+++ b/drivers/net/ethernet/i825xx/sun3_82586.c
@@ -333,7 +333,7 @@ static const struct net_device_ops sun3_82586_netdev_ops = {
.ndo_open = sun3_82586_open,
.ndo_stop = sun3_82586_close,
.ndo_start_xmit = sun3_82586_send_packet,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_tx_timeout = sun3_82586_timeout,
.ndo_get_stats = sun3_82586_get_stats,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/sun3_82586.h b/drivers/net/ethernet/i825xx/sun3_82586.h
index 93346f00486b..93346f00486b 100644
--- a/drivers/net/sun3_82586.h
+++ b/drivers/net/ethernet/i825xx/sun3_82586.h
diff --git a/drivers/net/znet.c b/drivers/net/ethernet/i825xx/znet.c
index 8b8881718f5e..962b4c421f3f 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/ethernet/i825xx/znet.c
@@ -356,7 +356,7 @@ static const struct net_device_ops znet_netdev_ops = {
.ndo_open = znet_open,
.ndo_stop = znet_close,
.ndo_start_xmit = znet_send_packet,
- .ndo_set_multicast_list = znet_set_multicast_list,
+ .ndo_set_rx_mode = znet_set_multicast_list,
.ndo_tx_timeout = znet_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ethernet/ibm/Kconfig b/drivers/net/ethernet/ibm/Kconfig
new file mode 100644
index 000000000000..9e16f3fa97b2
--- /dev/null
+++ b/drivers/net/ethernet/ibm/Kconfig
@@ -0,0 +1,48 @@
+#
+# IBM device configuration.
+#
+
+config NET_VENDOR_IBM
+ bool "IBM devices"
+ default y
+ depends on MCA || PPC_PSERIES || PPC_PSERIES || PPC_DCR || \
+ (IBMEBUS && INET && SPARSEMEM)
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about IBM devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_IBM
+
+config IBMVETH
+ tristate "IBM LAN Virtual Ethernet support"
+ depends on PPC_PSERIES
+ ---help---
+ This driver supports virtual ethernet adapters on newer IBM iSeries
+ and pSeries systems.
+
+ To compile this driver as a module, choose M here. The module will
+ be called ibmveth.
+
+config ISERIES_VETH
+ tristate "iSeries Virtual Ethernet driver support"
+ depends on PPC_ISERIES
+
+source "drivers/net/ethernet/ibm/emac/Kconfig"
+
+config EHEA
+ tristate "eHEA Ethernet support"
+ depends on IBMEBUS && INET && SPARSEMEM
+ select INET_LRO
+ ---help---
+ This driver supports the IBM pSeries eHEA ethernet adapter.
+
+ To compile the driver as a module, choose M here. The module
+ will be called ehea.
+
+endif # NET_VENDOR_IBM
diff --git a/drivers/net/ethernet/ibm/Makefile b/drivers/net/ethernet/ibm/Makefile
new file mode 100644
index 000000000000..5a7d4e9ac803
--- /dev/null
+++ b/drivers/net/ethernet/ibm/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for th IBM network device drivers.
+#
+
+obj-$(CONFIG_IBMVETH) += ibmveth.o
+obj-$(CONFIG_ISERIES_VETH) += iseries_veth.o
+obj-$(CONFIG_IBM_EMAC) += emac/
+obj-$(CONFIG_EHEA) += ehea/
diff --git a/drivers/net/ehea/Makefile b/drivers/net/ethernet/ibm/ehea/Makefile
index 775d9969b5c2..775d9969b5c2 100644
--- a/drivers/net/ehea/Makefile
+++ b/drivers/net/ethernet/ibm/ehea/Makefile
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ethernet/ibm/ehea/ehea.h
index 7dd5e6a0d998..410d6a1984ed 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ethernet/ibm/ehea/ehea.h
@@ -33,7 +33,6 @@
#include <linux/ethtool.h>
#include <linux/vmalloc.h>
#include <linux/if_vlan.h>
-#include <linux/inet_lro.h>
#include <asm/ibmebus.h>
#include <asm/abs_addr.h>
@@ -58,8 +57,6 @@
#define EHEA_MIN_ENTRIES_QP 127
#define EHEA_SMALL_QUEUES
-#define EHEA_NUM_TX_QP 1
-#define EHEA_LRO_MAX_AGGR 64
#ifdef EHEA_SMALL_QUEUES
#define EHEA_MAX_CQE_COUNT 1023
@@ -83,18 +80,16 @@
#define EHEA_SG_RQ3 0
#define EHEA_MAX_PACKET_SIZE 9022 /* for jumbo frames */
-#define EHEA_RQ2_PKT_SIZE 1522
+#define EHEA_RQ2_PKT_SIZE 2048
#define EHEA_L_PKT_SIZE 256 /* low latency */
-#define MAX_LRO_DESCRIPTORS 8
-
/* Send completion signaling */
/* Protection Domain Identifier */
#define EHEA_PD_ID 0xaabcdeff
#define EHEA_RQ2_THRESHOLD 1
-#define EHEA_RQ3_THRESHOLD 9 /* use RQ3 threshold of 1522 bytes */
+#define EHEA_RQ3_THRESHOLD 4 /* use RQ3 threshold of 2048 bytes */
#define EHEA_SPEED_10G 10000
#define EHEA_SPEED_1G 1000
@@ -363,7 +358,6 @@ struct ehea_port_res {
struct port_stats p_stats;
struct ehea_mr send_mr; /* send memory region */
struct ehea_mr recv_mr; /* receive memory region */
- spinlock_t xmit_lock;
struct ehea_port *port;
char int_recv_name[EHEA_IRQ_NAME_SIZE];
char int_send_name[EHEA_IRQ_NAME_SIZE];
@@ -376,8 +370,6 @@ struct ehea_port_res {
struct ehea_q_skb_arr rq3_skba;
struct ehea_q_skb_arr sq_skba;
int sq_skba_size;
- spinlock_t netif_queue;
- int queue_stopped;
int swqe_refill_th;
atomic_t swqe_avail;
int swqe_ll_count;
@@ -386,9 +378,6 @@ struct ehea_port_res {
u64 tx_bytes;
u64 rx_packets;
u64 rx_bytes;
- u32 poll_counter;
- struct net_lro_mgr lro_mgr;
- struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS];
int sq_restart_flag;
};
@@ -453,18 +442,17 @@ struct ehea_bcmc_reg_array {
struct ehea_port {
struct ehea_adapter *adapter; /* adapter that owns this port */
struct net_device *netdev;
- struct net_device_stats stats;
+ struct rtnl_link_stats64 stats;
struct ehea_port_res port_res[EHEA_MAX_PORT_RES];
struct platform_device ofdev; /* Open Firmware Device */
struct ehea_mc_list *mc_list; /* Multicast MAC addresses */
struct ehea_eq *qp_eq;
struct work_struct reset_task;
+ struct delayed_work stats_work;
struct mutex port_lock;
char int_aff_name[EHEA_IRQ_NAME_SIZE];
int allmulti; /* Indicates IFF_ALLMULTI state */
int promisc; /* Indicates IFF_PROMISC state */
- int num_tx_qps;
- int num_add_tx_qps;
int num_mcs;
int resets;
unsigned long flags;
@@ -474,7 +462,6 @@ struct ehea_port {
u32 msg_enable;
u32 sig_comp_iv;
u32 state;
- u32 lro_max_aggr;
u8 phy_link;
u8 full_duplex;
u8 autoneg;
diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
index 7f642aef5e82..05b7359bde8d 100644
--- a/drivers/net/ehea/ehea_ethtool.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
@@ -180,7 +180,7 @@ static void ehea_set_msglevel(struct net_device *dev, u32 value)
port->msg_enable = value;
}
-static char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = {
+static const char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = {
{"sig_comp_iv"},
{"swqe_refill_th"},
{"port resets"},
@@ -189,7 +189,6 @@ static char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = {
{"IP cksum errors"},
{"Frame cksum errors"},
{"num SQ stopped"},
- {"SQ stopped"},
{"PR0 free_swqes"},
{"PR1 free_swqes"},
{"PR2 free_swqes"},
@@ -198,9 +197,14 @@ static char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = {
{"PR5 free_swqes"},
{"PR6 free_swqes"},
{"PR7 free_swqes"},
- {"LRO aggregated"},
- {"LRO flushed"},
- {"LRO no_desc"},
+ {"PR8 free_swqes"},
+ {"PR9 free_swqes"},
+ {"PR10 free_swqes"},
+ {"PR11 free_swqes"},
+ {"PR12 free_swqes"},
+ {"PR13 free_swqes"},
+ {"PR14 free_swqes"},
+ {"PR15 free_swqes"},
};
static void ehea_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -255,25 +259,8 @@ static void ehea_get_ethtool_stats(struct net_device *dev,
tmp += port->port_res[k].p_stats.queue_stopped;
data[i++] = tmp;
- for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
- tmp |= port->port_res[k].queue_stopped;
- data[i++] = tmp;
-
- for (k = 0; k < 8; k++)
+ for (k = 0; k < 16; k++)
data[i++] = atomic_read(&port->port_res[k].swqe_avail);
-
- for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
- tmp |= port->port_res[k].lro_mgr.stats.aggregated;
- data[i++] = tmp;
-
- for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
- tmp |= port->port_res[k].lro_mgr.stats.flushed;
- data[i++] = tmp;
-
- for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
- tmp |= port->port_res[k].lro_mgr.stats.no_desc;
- data[i++] = tmp;
-
}
const struct ethtool_ops ehea_ethtool_ops = {
diff --git a/drivers/net/ehea/ehea_hw.h b/drivers/net/ethernet/ibm/ehea/ehea_hw.h
index 567981b4b2cc..1a2fe4dc3eb3 100644
--- a/drivers/net/ehea/ehea_hw.h
+++ b/drivers/net/ethernet/ibm/ehea/ehea_hw.h
@@ -210,36 +210,11 @@ static inline void epa_store_acc(struct h_epa epa, u32 offset, u64 value)
__raw_writeq(value, (void __iomem *)(epa.addr + offset));
}
-#define epa_store_eq(epa, offset, value)\
- epa_store(epa, EQTEMM_OFFSET(offset), value)
-#define epa_load_eq(epa, offset)\
- epa_load(epa, EQTEMM_OFFSET(offset))
-
#define epa_store_cq(epa, offset, value)\
epa_store(epa, CQTEMM_OFFSET(offset), value)
#define epa_load_cq(epa, offset)\
epa_load(epa, CQTEMM_OFFSET(offset))
-#define epa_store_qp(epa, offset, value)\
- epa_store(epa, QPTEMM_OFFSET(offset), value)
-#define epa_load_qp(epa, offset)\
- epa_load(epa, QPTEMM_OFFSET(offset))
-
-#define epa_store_qped(epa, offset, value)\
- epa_store(epa, QPEDMM_OFFSET(offset), value)
-#define epa_load_qped(epa, offset)\
- epa_load(epa, QPEDMM_OFFSET(offset))
-
-#define epa_store_mrmw(epa, offset, value)\
- epa_store(epa, MRMWMM_OFFSET(offset), value)
-#define epa_load_mrmw(epa, offset)\
- epa_load(epa, MRMWMM_OFFSET(offset))
-
-#define epa_store_base(epa, offset, value)\
- epa_store(epa, HCAGR_OFFSET(offset), value)
-#define epa_load_base(epa, offset)\
- epa_load(epa, HCAGR_OFFSET(offset))
-
static inline void ehea_update_sqa(struct ehea_qp *qp, u16 nr_wqes)
{
struct h_epa epa = qp->epas.kernel;
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index be2cb4ab8b4f..37b70f7052b6 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -61,10 +61,7 @@ static int rq1_entries = EHEA_DEF_ENTRIES_RQ1;
static int rq2_entries = EHEA_DEF_ENTRIES_RQ2;
static int rq3_entries = EHEA_DEF_ENTRIES_RQ3;
static int sq_entries = EHEA_DEF_ENTRIES_SQ;
-static int use_mcs;
-static int use_lro;
-static int lro_max_aggr = EHEA_LRO_MAX_AGGR;
-static int num_tx_qps = EHEA_NUM_TX_QP;
+static int use_mcs = 1;
static int prop_carrier_state;
module_param(msg_level, int, 0);
@@ -74,11 +71,7 @@ module_param(rq3_entries, int, 0);
module_param(sq_entries, int, 0);
module_param(prop_carrier_state, int, 0);
module_param(use_mcs, int, 0);
-module_param(use_lro, int, 0);
-module_param(lro_max_aggr, int, 0);
-module_param(num_tx_qps, int, 0);
-MODULE_PARM_DESC(num_tx_qps, "Number of TX-QPS");
MODULE_PARM_DESC(msg_level, "msg_level");
MODULE_PARM_DESC(prop_carrier_state, "Propagate carrier state of physical "
"port to stack. 1:yes, 0:no. Default = 0 ");
@@ -94,12 +87,8 @@ MODULE_PARM_DESC(rq1_entries, "Number of entries for Receive Queue 1 "
MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue "
"[2^x - 1], x = [6..14]. Default = "
__MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")");
-MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0 ");
-
-MODULE_PARM_DESC(lro_max_aggr, " LRO: Max packets to be aggregated. Default = "
- __MODULE_STRING(EHEA_LRO_MAX_AGGR));
-MODULE_PARM_DESC(use_lro, " Large Receive Offload, 1: enable, 0: disable, "
- "Default = 0");
+MODULE_PARM_DESC(use_mcs, " Multiple receive queues, 1: enable, 0: disable, "
+ "Default = 1");
static int port_name_cnt;
static LIST_HEAD(adapter_list);
@@ -173,7 +162,7 @@ static void ehea_update_firmware_handles(void)
continue;
num_ports++;
- num_portres += port->num_def_qps + port->num_add_tx_qps;
+ num_portres += port->num_def_qps;
}
}
@@ -199,9 +188,7 @@ static void ehea_update_firmware_handles(void)
(num_ports == 0))
continue;
- for (l = 0;
- l < port->num_def_qps + port->num_add_tx_qps;
- l++) {
+ for (l = 0; l < port->num_def_qps; l++) {
struct ehea_port_res *pr = &port->port_res[l];
arr[i].adh = adapter->handle;
@@ -327,20 +314,44 @@ out:
spin_unlock_irqrestore(&ehea_bcmc_regs.lock, flags);
}
-static struct net_device_stats *ehea_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *ehea_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
{
struct ehea_port *port = netdev_priv(dev);
- struct net_device_stats *stats = &port->stats;
- struct hcp_ehea_port_cb2 *cb2;
- u64 hret, rx_packets, tx_packets, rx_bytes = 0, tx_bytes = 0;
+ u64 rx_packets = 0, tx_packets = 0, rx_bytes = 0, tx_bytes = 0;
int i;
- memset(stats, 0, sizeof(*stats));
+ for (i = 0; i < port->num_def_qps; i++) {
+ rx_packets += port->port_res[i].rx_packets;
+ rx_bytes += port->port_res[i].rx_bytes;
+ }
+
+ for (i = 0; i < port->num_def_qps; i++) {
+ tx_packets += port->port_res[i].tx_packets;
+ tx_bytes += port->port_res[i].tx_bytes;
+ }
+
+ stats->tx_packets = tx_packets;
+ stats->rx_bytes = rx_bytes;
+ stats->tx_bytes = tx_bytes;
+ stats->rx_packets = rx_packets;
+
+ return &port->stats;
+}
+
+static void ehea_update_stats(struct work_struct *work)
+{
+ struct ehea_port *port =
+ container_of(work, struct ehea_port, stats_work.work);
+ struct net_device *dev = port->netdev;
+ struct rtnl_link_stats64 *stats = &port->stats;
+ struct hcp_ehea_port_cb2 *cb2;
+ u64 hret;
cb2 = (void *)get_zeroed_page(GFP_KERNEL);
if (!cb2) {
- netdev_err(dev, "no mem for cb2\n");
- goto out;
+ netdev_err(dev, "No mem for cb2. Some interface statistics were not updated\n");
+ goto resched;
}
hret = ehea_h_query_ehea_port(port->adapter->handle,
@@ -354,29 +365,13 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev)
if (netif_msg_hw(port))
ehea_dump(cb2, sizeof(*cb2), "net_device_stats");
- rx_packets = 0;
- for (i = 0; i < port->num_def_qps; i++) {
- rx_packets += port->port_res[i].rx_packets;
- rx_bytes += port->port_res[i].rx_bytes;
- }
-
- tx_packets = 0;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
- tx_packets += port->port_res[i].tx_packets;
- tx_bytes += port->port_res[i].tx_bytes;
- }
-
- stats->tx_packets = tx_packets;
stats->multicast = cb2->rxmcp;
stats->rx_errors = cb2->rxuerr;
- stats->rx_bytes = rx_bytes;
- stats->tx_bytes = tx_bytes;
- stats->rx_packets = rx_packets;
out_herr:
free_page((unsigned long)cb2);
-out:
- return stats;
+resched:
+ schedule_delayed_work(&port->stats_work, msecs_to_jiffies(1000));
}
static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
@@ -543,7 +538,8 @@ static inline int ehea_check_cqe(struct ehea_cqe *cqe, int *rq_num)
}
static inline void ehea_fill_skb(struct net_device *dev,
- struct sk_buff *skb, struct ehea_cqe *cqe)
+ struct sk_buff *skb, struct ehea_cqe *cqe,
+ struct ehea_port_res *pr)
{
int length = cqe->num_bytes_transfered - 4; /*remove CRC */
@@ -557,6 +553,8 @@ static inline void ehea_fill_skb(struct net_device *dev,
skb->csum = csum_unfold(~cqe->inet_checksum_value);
} else
skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ skb_record_rx_queue(skb, pr - &pr->port->port_res[0]);
}
static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
@@ -649,49 +647,6 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
return 0;
}
-static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
- void **tcph, u64 *hdr_flags, void *priv)
-{
- struct ehea_cqe *cqe = priv;
- unsigned int ip_len;
- struct iphdr *iph;
-
- /* non tcp/udp packets */
- if (!cqe->header_length)
- return -1;
-
- /* non tcp packet */
- skb_reset_network_header(skb);
- iph = ip_hdr(skb);
- if (iph->protocol != IPPROTO_TCP)
- return -1;
-
- ip_len = ip_hdrlen(skb);
- skb_set_transport_header(skb, ip_len);
- *tcph = tcp_hdr(skb);
-
- /* check if ip header and tcp header are complete */
- if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb))
- return -1;
-
- *hdr_flags = LRO_IPV4 | LRO_TCP;
- *iphdr = iph;
-
- return 0;
-}
-
-static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe,
- struct sk_buff *skb)
-{
- if (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
- __vlan_hwaccel_put_tag(skb, cqe->vlan_tag);
-
- if (skb->dev->features & NETIF_F_LRO)
- lro_receive_skb(&pr->lro_mgr, skb, cqe);
- else
- netif_receive_skb(skb);
-}
-
static int ehea_proc_rwqes(struct net_device *dev,
struct ehea_port_res *pr,
int budget)
@@ -742,7 +697,7 @@ static int ehea_proc_rwqes(struct net_device *dev,
}
skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
cqe->num_bytes_transfered - 4);
- ehea_fill_skb(dev, skb, cqe);
+ ehea_fill_skb(dev, skb, cqe, pr);
} else if (rq == 2) {
/* RQ2 */
skb = get_skb_by_index(skb_arr_rq2,
@@ -752,7 +707,7 @@ static int ehea_proc_rwqes(struct net_device *dev,
"rq2: skb=NULL\n");
break;
}
- ehea_fill_skb(dev, skb, cqe);
+ ehea_fill_skb(dev, skb, cqe, pr);
processed_rq2++;
} else {
/* RQ3 */
@@ -763,12 +718,16 @@ static int ehea_proc_rwqes(struct net_device *dev,
"rq3: skb=NULL\n");
break;
}
- ehea_fill_skb(dev, skb, cqe);
+ ehea_fill_skb(dev, skb, cqe, pr);
processed_rq3++;
}
processed_bytes += skb->len;
- ehea_proc_skb(pr, cqe, skb);
+
+ if (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
+ __vlan_hwaccel_put_tag(skb, cqe->vlan_tag);
+
+ napi_gro_receive(&pr->napi, skb);
} else {
pr->p_stats.poll_receive_errors++;
port_reset = ehea_treat_poll_error(pr, rq, cqe,
@@ -779,8 +738,6 @@ static int ehea_proc_rwqes(struct net_device *dev,
}
cqe = ehea_poll_rq1(qp, &wqe_index);
}
- if (dev->features & NETIF_F_LRO)
- lro_flush_all(&pr->lro_mgr);
pr->rx_packets += processed;
pr->rx_bytes += processed_bytes;
@@ -798,7 +755,7 @@ static void reset_sq_restart_flag(struct ehea_port *port)
{
int i;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
struct ehea_port_res *pr = &port->port_res[i];
pr->sq_restart_flag = 0;
}
@@ -811,7 +768,7 @@ static void check_sqs(struct ehea_port *port)
int swqe_index;
int i, k;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
struct ehea_port_res *pr = &port->port_res[i];
int ret;
k = 0;
@@ -849,7 +806,8 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
int cqe_counter = 0;
int swqe_av = 0;
int index;
- unsigned long flags;
+ struct netdev_queue *txq = netdev_get_tx_queue(pr->port->netdev,
+ pr - &pr->port->port_res[0]);
cqe = ehea_poll_cq(send_cq);
while (cqe && (quota > 0)) {
@@ -899,20 +857,20 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
ehea_update_feca(send_cq, cqe_counter);
atomic_add(swqe_av, &pr->swqe_avail);
- spin_lock_irqsave(&pr->netif_queue, flags);
-
- if (pr->queue_stopped && (atomic_read(&pr->swqe_avail)
- >= pr->swqe_refill_th)) {
- netif_wake_queue(pr->port->netdev);
- pr->queue_stopped = 0;
+ if (unlikely(netif_tx_queue_stopped(txq) &&
+ (atomic_read(&pr->swqe_avail) >= pr->swqe_refill_th))) {
+ __netif_tx_lock(txq, smp_processor_id());
+ if (netif_tx_queue_stopped(txq) &&
+ (atomic_read(&pr->swqe_avail) >= pr->swqe_refill_th))
+ netif_tx_wake_queue(txq);
+ __netif_tx_unlock(txq);
}
- spin_unlock_irqrestore(&pr->netif_queue, flags);
+
wake_up(&pr->port->swqe_avail_wq);
return cqe;
}
-#define EHEA_NAPI_POLL_NUM_BEFORE_IRQ 16
#define EHEA_POLL_MAX_CQES 65535
static int ehea_poll(struct napi_struct *napi, int budget)
@@ -922,18 +880,13 @@ static int ehea_poll(struct napi_struct *napi, int budget)
struct net_device *dev = pr->port->netdev;
struct ehea_cqe *cqe;
struct ehea_cqe *cqe_skb = NULL;
- int force_irq, wqe_index;
+ int wqe_index;
int rx = 0;
- force_irq = (pr->poll_counter > EHEA_NAPI_POLL_NUM_BEFORE_IRQ);
cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
+ rx += ehea_proc_rwqes(dev, pr, budget - rx);
- if (!force_irq)
- rx += ehea_proc_rwqes(dev, pr, budget - rx);
-
- while ((rx != budget) || force_irq) {
- pr->poll_counter = 0;
- force_irq = 0;
+ while (rx != budget) {
napi_complete(napi);
ehea_reset_cq_ep(pr->recv_cq);
ehea_reset_cq_ep(pr->send_cq);
@@ -953,7 +906,6 @@ static int ehea_poll(struct napi_struct *napi, int budget)
rx += ehea_proc_rwqes(dev, pr, budget - rx);
}
- pr->poll_counter++;
return rx;
}
@@ -1105,13 +1057,6 @@ int ehea_sense_port_attr(struct ehea_port *port)
goto out_free;
}
- port->num_tx_qps = num_tx_qps;
-
- if (port->num_def_qps >= port->num_tx_qps)
- port->num_add_tx_qps = 0;
- else
- port->num_add_tx_qps = port->num_tx_qps - port->num_def_qps;
-
ret = 0;
out_free:
if (ret || netif_msg_probe(port))
@@ -1243,7 +1188,7 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe)
netif_info(port, link, dev,
"Logical port down\n");
netif_carrier_off(dev);
- netif_stop_queue(dev);
+ netif_tx_disable(dev);
}
if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PORT_UP, eqe)) {
@@ -1274,7 +1219,7 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe)
case EHEA_EC_PORT_MALFUNC:
netdev_info(dev, "Port malfunction\n");
netif_carrier_off(dev);
- netif_stop_queue(dev);
+ netif_tx_disable(dev);
break;
default:
netdev_err(dev, "unknown event code %x, eqe=0x%llX\n", ec, eqe);
@@ -1352,7 +1297,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
port->qp_eq->attr.ist1);
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
pr = &port->port_res[i];
snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1,
"%s-queue%d", dev->name, i);
@@ -1395,7 +1340,7 @@ static void ehea_free_interrupts(struct net_device *dev)
/* send */
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
pr = &port->port_res[i];
ibmebus_free_irq(pr->eq->attr.ist1, pr);
netif_info(port, intr, dev,
@@ -1526,8 +1471,6 @@ static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr,
pr->rx_packets = rx_packets;
pr->port = port;
- spin_lock_init(&pr->xmit_lock);
- spin_lock_init(&pr->netif_queue);
pr->eq = ehea_create_eq(adapter, eq_type, EHEA_MAX_ENTRIES_EQ, 0);
if (!pr->eq) {
@@ -1618,15 +1561,6 @@ static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr,
netif_napi_add(pr->port->netdev, &pr->napi, ehea_poll, 64);
- pr->lro_mgr.max_aggr = pr->port->lro_max_aggr;
- pr->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
- pr->lro_mgr.lro_arr = pr->lro_desc;
- pr->lro_mgr.get_skb_header = get_skb_hdr;
- pr->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
- pr->lro_mgr.dev = port->netdev;
- pr->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
- pr->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
-
ret = 0;
goto out;
@@ -1683,96 +1617,35 @@ static int ehea_clean_portres(struct ehea_port *port, struct ehea_port_res *pr)
return ret;
}
-/*
- * The write_* functions store information in swqe which is used by
- * the hardware to calculate the ip/tcp/udp checksum
- */
-
-static inline void write_ip_start_end(struct ehea_swqe *swqe,
- const struct sk_buff *skb)
-{
- swqe->ip_start = skb_network_offset(skb);
- swqe->ip_end = (u8)(swqe->ip_start + ip_hdrlen(skb) - 1);
-}
-
-static inline void write_tcp_offset_end(struct ehea_swqe *swqe,
- const struct sk_buff *skb)
-{
- swqe->tcp_offset =
- (u8)(swqe->ip_end + 1 + offsetof(struct tcphdr, check));
-
- swqe->tcp_end = (u16)skb->len - 1;
-}
-
-static inline void write_udp_offset_end(struct ehea_swqe *swqe,
- const struct sk_buff *skb)
-{
- swqe->tcp_offset =
- (u8)(swqe->ip_end + 1 + offsetof(struct udphdr, check));
-
- swqe->tcp_end = (u16)skb->len - 1;
-}
-
-
-static void write_swqe2_TSO(struct sk_buff *skb,
- struct ehea_swqe *swqe, u32 lkey)
-{
- struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
- u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
- int skb_data_size = skb_headlen(skb);
- int headersize;
-
- /* Packet is TCP with TSO enabled */
- swqe->tx_control |= EHEA_SWQE_TSO;
- swqe->mss = skb_shinfo(skb)->gso_size;
- /* copy only eth/ip/tcp headers to immediate data and
- * the rest of skb->data to sg1entry
- */
- headersize = ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
-
- skb_data_size = skb_headlen(skb);
-
- if (skb_data_size >= headersize) {
- /* copy immediate data */
- skb_copy_from_linear_data(skb, imm_data, headersize);
- swqe->immediate_data_length = headersize;
-
- if (skb_data_size > headersize) {
- /* set sg1entry data */
- sg1entry->l_key = lkey;
- sg1entry->len = skb_data_size - headersize;
- sg1entry->vaddr =
- ehea_map_vaddr(skb->data + headersize);
- swqe->descriptors++;
- }
- } else
- pr_err("cannot handle fragmented headers\n");
-}
-
-static void write_swqe2_nonTSO(struct sk_buff *skb,
- struct ehea_swqe *swqe, u32 lkey)
+static void write_swqe2_immediate(struct sk_buff *skb, struct ehea_swqe *swqe,
+ u32 lkey)
{
int skb_data_size = skb_headlen(skb);
u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
+ unsigned int immediate_len = SWQE2_MAX_IMM;
- /* Packet is any nonTSO type
- *
- * Copy as much as possible skb->data to immediate data and
- * the rest to sg1entry
- */
- if (skb_data_size >= SWQE2_MAX_IMM) {
- /* copy immediate data */
- skb_copy_from_linear_data(skb, imm_data, SWQE2_MAX_IMM);
+ swqe->descriptors = 0;
- swqe->immediate_data_length = SWQE2_MAX_IMM;
+ if (skb_is_gso(skb)) {
+ swqe->tx_control |= EHEA_SWQE_TSO;
+ swqe->mss = skb_shinfo(skb)->gso_size;
+ /*
+ * For TSO packets we only copy the headers into the
+ * immediate area.
+ */
+ immediate_len = ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
+ }
- if (skb_data_size > SWQE2_MAX_IMM) {
- /* copy sg1entry data */
+ if (skb_is_gso(skb) || skb_data_size >= SWQE2_MAX_IMM) {
+ skb_copy_from_linear_data(skb, imm_data, immediate_len);
+ swqe->immediate_data_length = immediate_len;
+
+ if (skb_data_size > immediate_len) {
sg1entry->l_key = lkey;
- sg1entry->len = skb_data_size - SWQE2_MAX_IMM;
+ sg1entry->len = skb_data_size - immediate_len;
sg1entry->vaddr =
- ehea_map_vaddr(skb->data + SWQE2_MAX_IMM);
+ ehea_map_vaddr(skb->data + immediate_len);
swqe->descriptors++;
}
} else {
@@ -1791,13 +1664,9 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
nfrags = skb_shinfo(skb)->nr_frags;
sg1entry = &swqe->u.immdata_desc.sg_entry;
sg_list = (struct ehea_vsgentry *)&swqe->u.immdata_desc.sg_list;
- swqe->descriptors = 0;
sg1entry_contains_frag_data = 0;
- if ((dev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size)
- write_swqe2_TSO(skb, swqe, lkey);
- else
- write_swqe2_nonTSO(skb, swqe, lkey);
+ write_swqe2_immediate(skb, swqe, lkey);
/* write descriptors */
if (nfrags > 0) {
@@ -1807,10 +1676,9 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
/* copy sg1entry data */
sg1entry->l_key = lkey;
- sg1entry->len = frag->size;
+ sg1entry->len = skb_frag_size(frag);
sg1entry->vaddr =
- ehea_map_vaddr(page_address(frag->page)
- + frag->page_offset);
+ ehea_map_vaddr(skb_frag_address(frag));
swqe->descriptors++;
sg1entry_contains_frag_data = 1;
}
@@ -1821,10 +1689,8 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
sgentry = &sg_list[i - sg1entry_contains_frag_data];
sgentry->l_key = lkey;
- sgentry->len = frag->size;
- sgentry->vaddr =
- ehea_map_vaddr(page_address(frag->page)
- + frag->page_offset);
+ sgentry->len = skb_frag_size(frag);
+ sgentry->vaddr = ehea_map_vaddr(skb_frag_address(frag));
swqe->descriptors++;
}
}
@@ -2115,41 +1981,44 @@ static int ehea_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
- struct ehea_swqe *swqe, u32 lkey)
+static void xmit_common(struct sk_buff *skb, struct ehea_swqe *swqe)
{
- if (skb->protocol == htons(ETH_P_IP)) {
- const struct iphdr *iph = ip_hdr(skb);
+ swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT | EHEA_SWQE_CRC;
+
+ if (skb->protocol != htons(ETH_P_IP))
+ return;
- /* IPv4 */
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IP_CHECKSUM
- | EHEA_SWQE_TCP_CHECKSUM
- | EHEA_SWQE_IMM_DATA_PRESENT
- | EHEA_SWQE_DESCRIPTORS_PRESENT;
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ swqe->tx_control |= EHEA_SWQE_IP_CHECKSUM;
- write_ip_start_end(swqe, skb);
+ swqe->ip_start = skb_network_offset(skb);
+ swqe->ip_end = swqe->ip_start + ip_hdrlen(skb) - 1;
- if (iph->protocol == IPPROTO_UDP) {
- if ((iph->frag_off & IP_MF) ||
- (iph->frag_off & IP_OFFSET))
- /* IP fragment, so don't change cs */
- swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
- else
- write_udp_offset_end(swqe, skb);
- } else if (iph->protocol == IPPROTO_TCP) {
- write_tcp_offset_end(swqe, skb);
- }
+ switch (ip_hdr(skb)->protocol) {
+ case IPPROTO_UDP:
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ swqe->tx_control |= EHEA_SWQE_TCP_CHECKSUM;
+
+ swqe->tcp_offset = swqe->ip_end + 1 +
+ offsetof(struct udphdr, check);
+ break;
- /* icmp (big data) and ip segmentation packets (all other ip
- packets) do not require any special handling */
+ case IPPROTO_TCP:
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ swqe->tx_control |= EHEA_SWQE_TCP_CHECKSUM;
- } else {
- /* Other Ethernet Protocol */
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IMM_DATA_PRESENT
- | EHEA_SWQE_DESCRIPTORS_PRESENT;
+ swqe->tcp_offset = swqe->ip_end + 1 +
+ offsetof(struct tcphdr, check);
+ break;
}
+}
+
+static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
+ struct ehea_swqe *swqe, u32 lkey)
+{
+ swqe->tx_control |= EHEA_SWQE_DESCRIPTORS_PRESENT;
+
+ xmit_common(skb, swqe);
write_swqe2_data(skb, dev, swqe, lkey);
}
@@ -2157,107 +2026,30 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
struct ehea_swqe *swqe)
{
- int nfrags = skb_shinfo(skb)->nr_frags;
u8 *imm_data = &swqe->u.immdata_nodesc.immediate_data[0];
- skb_frag_t *frag;
- int i;
-
- if (skb->protocol == htons(ETH_P_IP)) {
- const struct iphdr *iph = ip_hdr(skb);
-
- /* IPv4 */
- write_ip_start_end(swqe, skb);
-
- if (iph->protocol == IPPROTO_TCP) {
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IP_CHECKSUM
- | EHEA_SWQE_TCP_CHECKSUM
- | EHEA_SWQE_IMM_DATA_PRESENT;
-
- write_tcp_offset_end(swqe, skb);
- } else if (iph->protocol == IPPROTO_UDP) {
- if ((iph->frag_off & IP_MF) ||
- (iph->frag_off & IP_OFFSET))
- /* IP fragment, so don't change cs */
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IMM_DATA_PRESENT;
- else {
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IP_CHECKSUM
- | EHEA_SWQE_TCP_CHECKSUM
- | EHEA_SWQE_IMM_DATA_PRESENT;
+ xmit_common(skb, swqe);
- write_udp_offset_end(swqe, skb);
- }
- } else {
- /* icmp (big data) and
- ip segmentation packets (all other ip packets) */
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IP_CHECKSUM
- | EHEA_SWQE_IMM_DATA_PRESENT;
- }
- } else {
- /* Other Ethernet Protocol */
- swqe->tx_control |= EHEA_SWQE_CRC | EHEA_SWQE_IMM_DATA_PRESENT;
- }
- /* copy (immediate) data */
- if (nfrags == 0) {
- /* data is in a single piece */
+ if (!skb->data_len)
skb_copy_from_linear_data(skb, imm_data, skb->len);
- } else {
- /* first copy data from the skb->data buffer ... */
- skb_copy_from_linear_data(skb, imm_data,
- skb_headlen(skb));
- imm_data += skb_headlen(skb);
+ else
+ skb_copy_bits(skb, 0, imm_data, skb->len);
- /* ... then copy data from the fragments */
- for (i = 0; i < nfrags; i++) {
- frag = &skb_shinfo(skb)->frags[i];
- memcpy(imm_data,
- page_address(frag->page) + frag->page_offset,
- frag->size);
- imm_data += frag->size;
- }
- }
swqe->immediate_data_length = skb->len;
dev_kfree_skb(skb);
}
-static inline int ehea_hash_skb(struct sk_buff *skb, int num_qps)
-{
- struct tcphdr *tcp;
- u32 tmp;
-
- if ((skb->protocol == htons(ETH_P_IP)) &&
- (ip_hdr(skb)->protocol == IPPROTO_TCP)) {
- tcp = (struct tcphdr *)(skb_network_header(skb) +
- (ip_hdr(skb)->ihl * 4));
- tmp = (tcp->source + (tcp->dest << 16)) % 31;
- tmp += ip_hdr(skb)->daddr % 31;
- return tmp % num_qps;
- } else
- return 0;
-}
-
static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ehea_port *port = netdev_priv(dev);
struct ehea_swqe *swqe;
- unsigned long flags;
u32 lkey;
int swqe_index;
struct ehea_port_res *pr;
+ struct netdev_queue *txq;
- pr = &port->port_res[ehea_hash_skb(skb, port->num_tx_qps)];
-
- if (!spin_trylock(&pr->xmit_lock))
- return NETDEV_TX_BUSY;
-
- if (pr->queue_stopped) {
- spin_unlock(&pr->xmit_lock);
- return NETDEV_TX_BUSY;
- }
+ pr = &port->port_res[skb_get_queue_mapping(skb)];
+ txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
swqe = ehea_get_swqe(pr->qp, &swqe_index);
memset(swqe, 0, SWQE_HEADER_SIZE);
@@ -2307,23 +2099,16 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
ehea_dump(swqe, 512, "swqe");
if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
- netif_stop_queue(dev);
+ netif_tx_stop_queue(txq);
swqe->tx_control |= EHEA_SWQE_PURGE;
}
ehea_post_swqe(pr->qp, swqe);
if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
- spin_lock_irqsave(&pr->netif_queue, flags);
- if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
- pr->p_stats.queue_stopped++;
- netif_stop_queue(dev);
- pr->queue_stopped = 1;
- }
- spin_unlock_irqrestore(&pr->netif_queue, flags);
+ pr->p_stats.queue_stopped++;
+ netif_tx_stop_queue(txq);
}
- dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
- spin_unlock(&pr->xmit_lock);
return NETDEV_TX_OK;
}
@@ -2468,8 +2253,7 @@ out:
return ret;
}
-static int ehea_port_res_setup(struct ehea_port *port, int def_qps,
- int add_tx_qps)
+static int ehea_port_res_setup(struct ehea_port *port, int def_qps)
{
int ret, i;
struct port_res_cfg pr_cfg, pr_cfg_small_rx;
@@ -2502,7 +2286,7 @@ static int ehea_port_res_setup(struct ehea_port *port, int def_qps,
if (ret)
goto out_clean_pr;
}
- for (i = def_qps; i < def_qps + add_tx_qps; i++) {
+ for (i = def_qps; i < def_qps; i++) {
ret = ehea_init_port_res(port, &port->port_res[i],
&pr_cfg_small_rx, i);
if (ret)
@@ -2525,7 +2309,7 @@ static int ehea_clean_all_portres(struct ehea_port *port)
int ret = 0;
int i;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
+ for (i = 0; i < port->num_def_qps; i++)
ret |= ehea_clean_portres(port, &port->port_res[i]);
ret |= ehea_destroy_eq(port->qp_eq);
@@ -2557,8 +2341,7 @@ static int ehea_up(struct net_device *dev)
if (port->state == EHEA_PORT_UP)
return 0;
- ret = ehea_port_res_setup(port, port->num_def_qps,
- port->num_add_tx_qps);
+ ret = ehea_port_res_setup(port, port->num_def_qps);
if (ret) {
netdev_err(dev, "port_res_failed\n");
goto out;
@@ -2577,7 +2360,7 @@ static int ehea_up(struct net_device *dev)
goto out_clean_pr;
}
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
ret = ehea_activate_qp(port->adapter, port->port_res[i].qp);
if (ret) {
netdev_err(dev, "activate_qp failed\n");
@@ -2623,7 +2406,7 @@ static void port_napi_disable(struct ehea_port *port)
{
int i;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
+ for (i = 0; i < port->num_def_qps; i++)
napi_disable(&port->port_res[i].napi);
}
@@ -2631,7 +2414,7 @@ static void port_napi_enable(struct ehea_port *port)
{
int i;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
+ for (i = 0; i < port->num_def_qps; i++)
napi_enable(&port->port_res[i].napi);
}
@@ -2647,10 +2430,11 @@ static int ehea_open(struct net_device *dev)
ret = ehea_up(dev);
if (!ret) {
port_napi_enable(port);
- netif_start_queue(dev);
+ netif_tx_start_all_queues(dev);
}
mutex_unlock(&port->port_lock);
+ schedule_delayed_work(&port->stats_work, msecs_to_jiffies(1000));
return ret;
}
@@ -2690,8 +2474,9 @@ static int ehea_stop(struct net_device *dev)
set_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
cancel_work_sync(&port->reset_task);
+ cancel_delayed_work_sync(&port->stats_work);
mutex_lock(&port->port_lock);
- netif_stop_queue(dev);
+ netif_tx_stop_all_queues(dev);
port_napi_disable(port);
ret = ehea_down(dev);
mutex_unlock(&port->port_lock);
@@ -2717,7 +2502,7 @@ static void ehea_flush_sq(struct ehea_port *port)
{
int i;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
struct ehea_port_res *pr = &port->port_res[i];
int swqe_max = pr->sq_skba_size - 2 - pr->swqe_ll_count;
int ret;
@@ -2751,7 +2536,7 @@ int ehea_stop_qps(struct net_device *dev)
goto out;
}
- for (i = 0; i < (port->num_def_qps + port->num_add_tx_qps); i++) {
+ for (i = 0; i < (port->num_def_qps); i++) {
struct ehea_port_res *pr = &port->port_res[i];
struct ehea_qp *qp = pr->qp;
@@ -2853,7 +2638,7 @@ int ehea_restart_qps(struct net_device *dev)
goto out;
}
- for (i = 0; i < (port->num_def_qps + port->num_add_tx_qps); i++) {
+ for (i = 0; i < (port->num_def_qps); i++) {
struct ehea_port_res *pr = &port->port_res[i];
struct ehea_qp *qp = pr->qp;
@@ -2915,7 +2700,7 @@ static void ehea_reset_port(struct work_struct *work)
mutex_lock(&dlpar_mem_lock);
port->resets++;
mutex_lock(&port->port_lock);
- netif_stop_queue(dev);
+ netif_tx_disable(dev);
port_napi_disable(port);
@@ -2931,7 +2716,7 @@ static void ehea_reset_port(struct work_struct *work)
port_napi_enable(port);
- netif_wake_queue(dev);
+ netif_tx_wake_all_queues(dev);
out:
mutex_unlock(&port->port_lock);
mutex_unlock(&dlpar_mem_lock);
@@ -2958,7 +2743,7 @@ static void ehea_rereg_mrs(void)
if (dev->flags & IFF_UP) {
mutex_lock(&port->port_lock);
- netif_stop_queue(dev);
+ netif_tx_disable(dev);
ehea_flush_sq(port);
ret = ehea_stop_qps(dev);
if (ret) {
@@ -3003,7 +2788,7 @@ static void ehea_rereg_mrs(void)
if (!ret) {
check_sqs(port);
port_napi_enable(port);
- netif_wake_queue(dev);
+ netif_tx_wake_all_queues(dev);
} else {
netdev_err(dev, "Unable to restart QPS\n");
}
@@ -3158,10 +2943,10 @@ static const struct net_device_ops ehea_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ehea_netpoll,
#endif
- .ndo_get_stats = ehea_get_stats,
+ .ndo_get_stats64 = ehea_get_stats64,
.ndo_set_mac_address = ehea_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = ehea_set_multicast_list,
+ .ndo_set_rx_mode = ehea_set_multicast_list,
.ndo_change_mtu = ehea_change_mtu,
.ndo_vlan_rx_add_vid = ehea_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ehea_vlan_rx_kill_vid,
@@ -3179,7 +2964,7 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
int jumbo;
/* allocate memory for the port structures */
- dev = alloc_etherdev(sizeof(struct ehea_port));
+ dev = alloc_etherdev_mq(sizeof(struct ehea_port), EHEA_MAX_PORT_RES);
if (!dev) {
pr_err("no mem for net_device\n");
@@ -3211,6 +2996,9 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
if (ret)
goto out_free_mc_list;
+ netif_set_real_num_rx_queues(dev, port->num_def_qps);
+ netif_set_real_num_tx_queues(dev, port->num_def_qps);
+
port_dev = ehea_register_port(port, dn);
if (!port_dev)
goto out_free_mc_list;
@@ -3223,30 +3011,29 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
dev->netdev_ops = &ehea_netdev_ops;
ehea_set_ethtool_ops(dev);
- dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
+ dev->hw_features = NETIF_F_SG | NETIF_F_TSO
| NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO;
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
- | NETIF_F_LLTX | NETIF_F_RXCSUM;
+ | NETIF_F_RXCSUM;
+ dev->vlan_features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_HIGHDMA |
+ NETIF_F_IP_CSUM;
dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
- if (use_lro)
- dev->features |= NETIF_F_LRO;
-
INIT_WORK(&port->reset_task, ehea_reset_port);
+ INIT_DELAYED_WORK(&port->stats_work, ehea_update_stats);
init_waitqueue_head(&port->swqe_avail_wq);
init_waitqueue_head(&port->restart_wq);
+ memset(&port->stats, 0, sizeof(struct net_device_stats));
ret = register_netdev(dev);
if (ret) {
pr_err("register_netdev failed. ret=%d\n", ret);
goto out_unreg_port;
}
- port->lro_max_aggr = lro_max_aggr;
-
ret = ehea_get_jumboframe_status(port, &jumbo);
if (ret)
netdev_err(dev, "failed determining jumbo frame status\n");
@@ -3278,6 +3065,7 @@ static void ehea_shutdown_single_port(struct ehea_port *port)
struct ehea_adapter *adapter = port->adapter;
cancel_work_sync(&port->reset_task);
+ cancel_delayed_work_sync(&port->stats_work);
unregister_netdev(port->netdev);
ehea_unregister_port(port);
kfree(port->mc_list);
diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ethernet/ibm/ehea/ehea_phyp.c
index 0506967b9044..0506967b9044 100644
--- a/drivers/net/ehea/ehea_phyp.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_phyp.c
diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
index 2f8174c248bc..2f8174c248bc 100644
--- a/drivers/net/ehea/ehea_phyp.h
+++ b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ethernet/ibm/ehea/ehea_qmr.c
index 95b9f4fa811e..95b9f4fa811e 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_qmr.c
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ethernet/ibm/ehea/ehea_qmr.h
index fddff8ec8cfd..337a47ecf4aa 100644
--- a/drivers/net/ehea/ehea_qmr.h
+++ b/drivers/net/ethernet/ibm/ehea/ehea_qmr.h
@@ -107,7 +107,7 @@ struct ehea_swqe {
u8 immediate_data_length;
u8 tcp_offset;
u8 reserved2;
- u16 tcp_end;
+ u16 reserved2b;
u8 wrap_tag;
u8 descriptors; /* number of valid descriptors in WQE */
u16 reserved3;
diff --git a/drivers/net/ibm_newemac/Kconfig b/drivers/net/ethernet/ibm/emac/Kconfig
index 78a1628c9892..3f44a30e0615 100644
--- a/drivers/net/ibm_newemac/Kconfig
+++ b/drivers/net/ethernet/ibm/emac/Kconfig
@@ -1,4 +1,4 @@
-config IBM_NEW_EMAC
+config IBM_EMAC
tristate "IBM EMAC Ethernet support"
depends on PPC_DCR
select CRC32
@@ -7,29 +7,29 @@ config IBM_NEW_EMAC
typically found on 4xx embedded PowerPC chips, but also on the
Axon southbridge for Cell.
-config IBM_NEW_EMAC_RXB
+config IBM_EMAC_RXB
int "Number of receive buffers"
- depends on IBM_NEW_EMAC
+ depends on IBM_EMAC
default "128"
-config IBM_NEW_EMAC_TXB
+config IBM_EMAC_TXB
int "Number of transmit buffers"
- depends on IBM_NEW_EMAC
+ depends on IBM_EMAC
default "64"
-config IBM_NEW_EMAC_POLL_WEIGHT
+config IBM_EMAC_POLL_WEIGHT
int "MAL NAPI polling weight"
- depends on IBM_NEW_EMAC
+ depends on IBM_EMAC
default "32"
-config IBM_NEW_EMAC_RX_COPY_THRESHOLD
+config IBM_EMAC_RX_COPY_THRESHOLD
int "RX skb copy threshold (bytes)"
- depends on IBM_NEW_EMAC
+ depends on IBM_EMAC
default "256"
-config IBM_NEW_EMAC_RX_SKB_HEADROOM
+config IBM_EMAC_RX_SKB_HEADROOM
int "Additional RX skb headroom (bytes)"
- depends on IBM_NEW_EMAC
+ depends on IBM_EMAC
default "0"
help
Additional receive skb headroom. Note, that driver
@@ -39,38 +39,38 @@ config IBM_NEW_EMAC_RX_SKB_HEADROOM
If unsure, set to 0.
-config IBM_NEW_EMAC_DEBUG
+config IBM_EMAC_DEBUG
bool "Debugging"
- depends on IBM_NEW_EMAC
+ depends on IBM_EMAC
default n
# The options below has to be select'ed by the respective
# processor types or platforms
-config IBM_NEW_EMAC_ZMII
+config IBM_EMAC_ZMII
bool
default n
-config IBM_NEW_EMAC_RGMII
+config IBM_EMAC_RGMII
bool
default n
-config IBM_NEW_EMAC_TAH
+config IBM_EMAC_TAH
bool
default n
-config IBM_NEW_EMAC_EMAC4
+config IBM_EMAC_EMAC4
bool
default n
-config IBM_NEW_EMAC_NO_FLOW_CTRL
+config IBM_EMAC_NO_FLOW_CTRL
bool
default n
-config IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
+config IBM_EMAC_MAL_CLR_ICINTSTAT
bool
default n
-config IBM_NEW_EMAC_MAL_COMMON_ERR
+config IBM_EMAC_MAL_COMMON_ERR
bool
default n
diff --git a/drivers/net/ethernet/ibm/emac/Makefile b/drivers/net/ethernet/ibm/emac/Makefile
new file mode 100644
index 000000000000..eba21835d90d
--- /dev/null
+++ b/drivers/net/ethernet/ibm/emac/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the PowerPC 4xx on-chip ethernet driver
+#
+
+obj-$(CONFIG_IBM_EMAC) += ibm_emac.o
+
+ibm_emac-y := mal.o core.o phy.o
+ibm_emac-$(CONFIG_IBM_EMAC_ZMII) += zmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_RGMII) += rgmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_TAH) += tah.o
+ibm_emac-$(CONFIG_IBM_EMAC_DEBUG) += debug.o
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 70cb7d8a3b53..ed79b2d3ad3e 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -90,7 +90,7 @@ MODULE_LICENSE("GPL");
/* If packet size is less than this number, we allocate small skb and copy packet
* contents into it instead of just sending original big skb up
*/
-#define EMAC_RX_COPY_THRESH CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD
+#define EMAC_RX_COPY_THRESH CONFIG_IBM_EMAC_RX_COPY_THRESHOLD
/* Since multiple EMACs share MDIO lines in various ways, we need
* to avoid re-using the same PHY ID in cases where the arch didn't
@@ -1453,13 +1453,13 @@ static int emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev)
/* skb fragments */
for (i = 0; i < nr_frags; ++i) {
struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
- len = frag->size;
+ len = skb_frag_size(frag);
if (unlikely(dev->tx_cnt + mal_tx_chunks(len) >= NUM_TX_BUFF))
goto undo_frame;
- pd = dma_map_page(&dev->ofdev->dev, frag->page, frag->page_offset, len,
- DMA_TO_DEVICE);
+ pd = skb_frag_dma_map(&dev->ofdev->dev, frag, 0, len,
+ DMA_TO_DEVICE);
slot = emac_xmit_split(dev, slot, pd, len, i == nr_frags - 1,
ctrl);
@@ -1618,7 +1618,7 @@ static void emac_parse_rx_error(struct emac_instance *dev, u16 ctrl)
static inline void emac_rx_csum(struct emac_instance *dev,
struct sk_buff *skb, u16 ctrl)
{
-#ifdef CONFIG_IBM_NEW_EMAC_TAH
+#ifdef CONFIG_IBM_EMAC_TAH
if (!ctrl && dev->tah_dev) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
++dev->stats.rx_packets_csum;
@@ -2577,7 +2577,7 @@ static int __devinit emac_init_config(struct emac_instance *dev)
of_device_is_compatible(np, "ibm,emac-440gr"))
dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
if (of_device_is_compatible(np, "ibm,emac-405ez")) {
-#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
+#ifdef CONFIG_IBM_EMAC_NO_FLOW_CTRL
dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x;
#else
printk(KERN_ERR "%s: Flow control not disabled!\n",
@@ -2601,7 +2601,7 @@ static int __devinit emac_init_config(struct emac_instance *dev)
/* Enable TAH/ZMII/RGMII features as found */
if (dev->tah_ph != 0) {
-#ifdef CONFIG_IBM_NEW_EMAC_TAH
+#ifdef CONFIG_IBM_EMAC_TAH
dev->features |= EMAC_FTR_HAS_TAH;
#else
printk(KERN_ERR "%s: TAH support not enabled !\n",
@@ -2611,7 +2611,7 @@ static int __devinit emac_init_config(struct emac_instance *dev)
}
if (dev->zmii_ph != 0) {
-#ifdef CONFIG_IBM_NEW_EMAC_ZMII
+#ifdef CONFIG_IBM_EMAC_ZMII
dev->features |= EMAC_FTR_HAS_ZMII;
#else
printk(KERN_ERR "%s: ZMII support not enabled !\n",
@@ -2621,7 +2621,7 @@ static int __devinit emac_init_config(struct emac_instance *dev)
}
if (dev->rgmii_ph != 0) {
-#ifdef CONFIG_IBM_NEW_EMAC_RGMII
+#ifdef CONFIG_IBM_EMAC_RGMII
dev->features |= EMAC_FTR_HAS_RGMII;
#else
printk(KERN_ERR "%s: RGMII support not enabled !\n",
@@ -2661,7 +2661,7 @@ static const struct net_device_ops emac_netdev_ops = {
.ndo_open = emac_open,
.ndo_stop = emac_close,
.ndo_get_stats = emac_stats,
- .ndo_set_multicast_list = emac_set_multicast_list,
+ .ndo_set_rx_mode = emac_set_multicast_list,
.ndo_do_ioctl = emac_ioctl,
.ndo_tx_timeout = emac_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
@@ -2674,7 +2674,7 @@ static const struct net_device_ops emac_gige_netdev_ops = {
.ndo_open = emac_open,
.ndo_stop = emac_close,
.ndo_get_stats = emac_stats,
- .ndo_set_multicast_list = emac_set_multicast_list,
+ .ndo_set_rx_mode = emac_set_multicast_list,
.ndo_do_ioctl = emac_ioctl,
.ndo_tx_timeout = emac_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ethernet/ibm/emac/core.h
index 4fec0844d59d..fa3ec57935fa 100644
--- a/drivers/net/ibm_newemac/core.h
+++ b/drivers/net/ethernet/ibm/emac/core.h
@@ -47,8 +47,8 @@
#include "tah.h"
#include "debug.h"
-#define NUM_TX_BUFF CONFIG_IBM_NEW_EMAC_TXB
-#define NUM_RX_BUFF CONFIG_IBM_NEW_EMAC_RXB
+#define NUM_TX_BUFF CONFIG_IBM_EMAC_TXB
+#define NUM_RX_BUFF CONFIG_IBM_EMAC_RXB
/* Simple sanity check */
#if NUM_TX_BUFF > 256 || NUM_RX_BUFF > 256
@@ -72,7 +72,7 @@ static inline int emac_rx_size(int mtu)
#define EMAC_DMA_ALIGN(x) ALIGN((x), dma_get_cache_alignment())
#define EMAC_RX_SKB_HEADROOM \
- EMAC_DMA_ALIGN(CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM)
+ EMAC_DMA_ALIGN(CONFIG_IBM_EMAC_RX_SKB_HEADROOM)
/* Size of RX skb for the given MTU */
static inline int emac_rx_skb_size(int mtu)
@@ -335,21 +335,21 @@ enum {
EMAC_FTRS_ALWAYS = 0,
EMAC_FTRS_POSSIBLE =
-#ifdef CONFIG_IBM_NEW_EMAC_EMAC4
+#ifdef CONFIG_IBM_EMAC_EMAC4
EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC |
EMAC_FTR_HAS_NEW_STACR |
EMAC_FTR_STACR_OC_INVERT | EMAC_FTR_440GX_PHY_CLK_FIX |
#endif
-#ifdef CONFIG_IBM_NEW_EMAC_TAH
+#ifdef CONFIG_IBM_EMAC_TAH
EMAC_FTR_HAS_TAH |
#endif
-#ifdef CONFIG_IBM_NEW_EMAC_ZMII
+#ifdef CONFIG_IBM_EMAC_ZMII
EMAC_FTR_HAS_ZMII |
#endif
-#ifdef CONFIG_IBM_NEW_EMAC_RGMII
+#ifdef CONFIG_IBM_EMAC_RGMII
EMAC_FTR_HAS_RGMII |
#endif
-#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
+#ifdef CONFIG_IBM_EMAC_NO_FLOW_CTRL
EMAC_FTR_NO_FLOW_CONTROL_40x |
#endif
EMAC_FTR_460EX_PHY_CLK_FIX |
diff --git a/drivers/net/ibm_newemac/debug.c b/drivers/net/ethernet/ibm/emac/debug.c
index 8c6c1e2a8750..8c6c1e2a8750 100644
--- a/drivers/net/ibm_newemac/debug.c
+++ b/drivers/net/ethernet/ibm/emac/debug.c
diff --git a/drivers/net/ibm_newemac/debug.h b/drivers/net/ethernet/ibm/emac/debug.h
index e596c77ccdf7..90477fe69d0c 100644
--- a/drivers/net/ibm_newemac/debug.h
+++ b/drivers/net/ethernet/ibm/emac/debug.h
@@ -24,7 +24,7 @@
#include "core.h"
-#if defined(CONFIG_IBM_NEW_EMAC_DEBUG)
+#if defined(CONFIG_IBM_EMAC_DEBUG)
struct emac_instance;
struct mal_instance;
diff --git a/drivers/net/ibm_newemac/emac.h b/drivers/net/ethernet/ibm/emac/emac.h
index 1568278d759a..1568278d759a 100644
--- a/drivers/net/ibm_newemac/emac.h
+++ b/drivers/net/ethernet/ibm/emac/emac.h
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index d268f404b7b0..f3c50b97ec61 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -577,8 +577,8 @@ static int __devinit mal_probe(struct platform_device *ofdev)
}
if (of_device_is_compatible(ofdev->dev.of_node, "ibm,mcmal-405ez")) {
-#if defined(CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT) && \
- defined(CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR)
+#if defined(CONFIG_IBM_EMAC_MAL_CLR_ICINTSTAT) && \
+ defined(CONFIG_IBM_EMAC_MAL_COMMON_ERR)
mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
MAL_FTR_COMMON_ERR_INT);
#else
@@ -616,7 +616,7 @@ static int __devinit mal_probe(struct platform_device *ofdev)
init_dummy_netdev(&mal->dummy_dev);
netif_napi_add(&mal->dummy_dev, &mal->napi, mal_poll,
- CONFIG_IBM_NEW_EMAC_POLL_WEIGHT);
+ CONFIG_IBM_EMAC_POLL_WEIGHT);
/* Load power-on reset defaults */
mal_reset(mal);
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ethernet/ibm/emac/mal.h
index 66084214bf45..d06f985bda32 100644
--- a/drivers/net/ibm_newemac/mal.h
+++ b/drivers/net/ethernet/ibm/emac/mal.h
@@ -245,10 +245,10 @@ enum {
MAL_FTRS_ALWAYS = 0,
MAL_FTRS_POSSIBLE =
-#ifdef CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
+#ifdef CONFIG_IBM_EMAC_MAL_CLR_ICINTSTAT
MAL_FTR_CLEAR_ICINTSTAT |
#endif
-#ifdef CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR
+#ifdef CONFIG_IBM_EMAC_MAL_COMMON_ERR
MAL_FTR_COMMON_ERR_INT |
#endif
0,
diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ethernet/ibm/emac/phy.c
index ab4e5969fe65..ab4e5969fe65 100644
--- a/drivers/net/ibm_newemac/phy.c
+++ b/drivers/net/ethernet/ibm/emac/phy.c
diff --git a/drivers/net/ibm_newemac/phy.h b/drivers/net/ethernet/ibm/emac/phy.h
index 5d2bf4cbe50b..5d2bf4cbe50b 100644
--- a/drivers/net/ibm_newemac/phy.h
+++ b/drivers/net/ethernet/ibm/emac/phy.h
diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c
index 4fa53f3def64..4fa53f3def64 100644
--- a/drivers/net/ibm_newemac/rgmii.c
+++ b/drivers/net/ethernet/ibm/emac/rgmii.c
diff --git a/drivers/net/ibm_newemac/rgmii.h b/drivers/net/ethernet/ibm/emac/rgmii.h
index d69799049865..9296b6c5f920 100644
--- a/drivers/net/ibm_newemac/rgmii.h
+++ b/drivers/net/ethernet/ibm/emac/rgmii.h
@@ -54,7 +54,7 @@ struct rgmii_instance {
struct platform_device *ofdev;
};
-#ifdef CONFIG_IBM_NEW_EMAC_RGMII
+#ifdef CONFIG_IBM_EMAC_RGMII
extern int rgmii_init(void);
extern void rgmii_exit(void);
@@ -77,6 +77,6 @@ extern void *rgmii_dump_regs(struct platform_device *ofdev, void *buf);
# define rgmii_set_speed(x,y,z) do { } while(0)
# define rgmii_get_regs_len(x) 0
# define rgmii_dump_regs(x,buf) (buf)
-#endif /* !CONFIG_IBM_NEW_EMAC_RGMII */
+#endif /* !CONFIG_IBM_EMAC_RGMII */
#endif /* __IBM_NEWEMAC_RGMII_H */
diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c
index 5f51bf7c9dc5..5f51bf7c9dc5 100644
--- a/drivers/net/ibm_newemac/tah.c
+++ b/drivers/net/ethernet/ibm/emac/tah.c
diff --git a/drivers/net/ibm_newemac/tah.h b/drivers/net/ethernet/ibm/emac/tah.h
index 61dbeca006d1..3437ab4964c7 100644
--- a/drivers/net/ibm_newemac/tah.h
+++ b/drivers/net/ethernet/ibm/emac/tah.h
@@ -70,7 +70,7 @@ struct tah_instance {
#define TAH_MR_DTFP 0x00100000
#define TAH_MR_DIG 0x00080000
-#ifdef CONFIG_IBM_NEW_EMAC_TAH
+#ifdef CONFIG_IBM_EMAC_TAH
extern int tah_init(void);
extern void tah_exit(void);
@@ -90,6 +90,6 @@ extern void *tah_dump_regs(struct platform_device *ofdev, void *buf);
# define tah_get_regs_len(x) 0
# define tah_dump_regs(x,buf) (buf)
-#endif /* !CONFIG_IBM_NEW_EMAC_TAH */
+#endif /* !CONFIG_IBM_EMAC_TAH */
#endif /* __IBM_NEWEMAC_TAH_H */
diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c
index 97449e786d61..97449e786d61 100644
--- a/drivers/net/ibm_newemac/zmii.c
+++ b/drivers/net/ethernet/ibm/emac/zmii.c
diff --git a/drivers/net/ibm_newemac/zmii.h b/drivers/net/ethernet/ibm/emac/zmii.h
index 1333fa2b2781..ceaed823a83c 100644
--- a/drivers/net/ibm_newemac/zmii.h
+++ b/drivers/net/ethernet/ibm/emac/zmii.h
@@ -51,7 +51,7 @@ struct zmii_instance {
struct platform_device *ofdev;
};
-#ifdef CONFIG_IBM_NEW_EMAC_ZMII
+#ifdef CONFIG_IBM_EMAC_ZMII
extern int zmii_init(void);
extern void zmii_exit(void);
@@ -73,6 +73,6 @@ extern void *zmii_dump_regs(struct platform_device *ofdev, void *buf);
# define zmii_set_speed(x,y,z) do { } while(0)
# define zmii_get_regs_len(x) 0
# define zmii_dump_regs(x,buf) (buf)
-#endif /* !CONFIG_IBM_NEW_EMAC_ZMII */
+#endif /* !CONFIG_IBM_EMAC_ZMII */
#endif /* __IBM_NEWEMAC_ZMII_H */
diff --git a/drivers/net/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index d393f1e764ed..b1cd41b9c61c 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1014,16 +1014,15 @@ retry_bounce:
/* Map the frags */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- dma_addr = dma_map_page(&adapter->vdev->dev, frag->page,
- frag->page_offset, frag->size,
- DMA_TO_DEVICE);
+ dma_addr = skb_frag_dma_map(&adapter->vdev->dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
if (dma_mapping_error(&adapter->vdev->dev, dma_addr))
goto map_failed_frags;
- descs[i+1].fields.flags_len = desc_flags | frag->size;
+ descs[i+1].fields.flags_len = desc_flags | skb_frag_size(frag);
descs[i+1].fields.address = dma_addr;
}
@@ -1319,7 +1318,7 @@ static const struct net_device_ops ibmveth_netdev_ops = {
.ndo_open = ibmveth_open,
.ndo_stop = ibmveth_close,
.ndo_start_xmit = ibmveth_start_xmit,
- .ndo_set_multicast_list = ibmveth_set_multicast_list,
+ .ndo_set_rx_mode = ibmveth_set_multicast_list,
.ndo_do_ioctl = ibmveth_ioctl,
.ndo_change_mtu = ibmveth_change_mtu,
.ndo_fix_features = ibmveth_fix_features,
diff --git a/drivers/net/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h
index 43a794fab9ff..43a794fab9ff 100644
--- a/drivers/net/ibmveth.h
+++ b/drivers/net/ethernet/ibm/ibmveth.h
diff --git a/drivers/net/iseries_veth.c b/drivers/net/ethernet/ibm/iseries_veth.c
index 53dd39e9130e..4326681df382 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/ethernet/ibm/iseries_veth.c
@@ -1009,7 +1009,7 @@ static const struct net_device_ops veth_netdev_ops = {
.ndo_stop = veth_close,
.ndo_start_xmit = veth_start_xmit,
.ndo_change_mtu = veth_change_mtu,
- .ndo_set_multicast_list = veth_set_multicast_list,
+ .ndo_set_rx_mode = veth_set_multicast_list,
.ndo_set_mac_address = NULL,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/ethernet/icplus/Kconfig b/drivers/net/ethernet/icplus/Kconfig
new file mode 100644
index 000000000000..3aff81d7989f
--- /dev/null
+++ b/drivers/net/ethernet/icplus/Kconfig
@@ -0,0 +1,14 @@
+#
+# IC Plus device configuration
+#
+
+config IP1000
+ tristate "IP1000 Gigabit Ethernet support"
+ depends on PCI && EXPERIMENTAL
+ select NET_CORE
+ select MII
+ ---help---
+ This driver supports IP1000 gigabit Ethernet cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ipg. This is recommended.
diff --git a/drivers/net/ethernet/icplus/Makefile b/drivers/net/ethernet/icplus/Makefile
new file mode 100644
index 000000000000..5bc87c1f36aa
--- /dev/null
+++ b/drivers/net/ethernet/icplus/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the IC Plus device drivers
+#
+
+obj-$(CONFIG_IP1000) += ipg.o
diff --git a/drivers/net/ipg.c b/drivers/net/ethernet/icplus/ipg.c
index d4aa40adf1e9..8fd80a00b898 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ethernet/icplus/ipg.c
@@ -20,6 +20,9 @@
* http://www.icplus.com.tw
* jesse@icplus.com.tw
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/crc32.h>
#include <linux/ethtool.h>
#include <linux/interrupt.h>
@@ -67,7 +70,7 @@ MODULE_LICENSE("GPL");
* Variable record -- index by leading revision/length
* Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN
*/
-static unsigned short DefaultPhyParam[] = {
+static const unsigned short DefaultPhyParam[] = {
/* 11/12/03 IP1000A v1-3 rev=0x40 */
/*--------------------------------------------------------------------------
(0x4000|(15*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 22, 0x85bd, 24, 0xfff2,
@@ -85,7 +88,7 @@ static unsigned short DefaultPhyParam[] = {
0x0000
};
-static const char *ipg_brand_name[] = {
+static const char * const ipg_brand_name[] = {
"IC PLUS IP1000 1000/100/10 based NIC",
"Sundance Technology ST2021 based NIC",
"Tamarack Microelectronics TC9020/9021 based NIC",
@@ -118,23 +121,23 @@ static void ipg_dump_rfdlist(struct net_device *dev)
IPG_DEBUG_MSG("_dump_rfdlist\n");
- printk(KERN_INFO "rx_current = %2.2x\n", sp->rx_current);
- printk(KERN_INFO "rx_dirty = %2.2x\n", sp->rx_dirty);
- printk(KERN_INFO "RFDList start address = %16.16lx\n",
- (unsigned long) sp->rxd_map);
- printk(KERN_INFO "RFDListPtr register = %8.8x%8.8x\n",
- ipg_r32(IPG_RFDLISTPTR1), ipg_r32(IPG_RFDLISTPTR0));
+ netdev_info(dev, "rx_current = %02x\n", sp->rx_current);
+ netdev_info(dev, "rx_dirty = %02x\n", sp->rx_dirty);
+ netdev_info(dev, "RFDList start address = %016lx\n",
+ (unsigned long)sp->rxd_map);
+ netdev_info(dev, "RFDListPtr register = %08x%08x\n",
+ ipg_r32(IPG_RFDLISTPTR1), ipg_r32(IPG_RFDLISTPTR0));
for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
offset = (u32) &sp->rxd[i].next_desc - (u32) sp->rxd;
- printk(KERN_INFO "%2.2x %4.4x RFDNextPtr = %16.16lx\n", i,
- offset, (unsigned long) sp->rxd[i].next_desc);
+ netdev_info(dev, "%02x %04x RFDNextPtr = %016lx\n",
+ i, offset, (unsigned long)sp->rxd[i].next_desc);
offset = (u32) &sp->rxd[i].rfs - (u32) sp->rxd;
- printk(KERN_INFO "%2.2x %4.4x RFS = %16.16lx\n", i,
- offset, (unsigned long) sp->rxd[i].rfs);
+ netdev_info(dev, "%02x %04x RFS = %016lx\n",
+ i, offset, (unsigned long)sp->rxd[i].rfs);
offset = (u32) &sp->rxd[i].frag_info - (u32) sp->rxd;
- printk(KERN_INFO "%2.2x %4.4x frag_info = %16.16lx\n", i,
- offset, (unsigned long) sp->rxd[i].frag_info);
+ netdev_info(dev, "%02x %04x frag_info = %016lx\n",
+ i, offset, (unsigned long)sp->rxd[i].frag_info);
}
}
@@ -147,24 +150,24 @@ static void ipg_dump_tfdlist(struct net_device *dev)
IPG_DEBUG_MSG("_dump_tfdlist\n");
- printk(KERN_INFO "tx_current = %2.2x\n", sp->tx_current);
- printk(KERN_INFO "tx_dirty = %2.2x\n", sp->tx_dirty);
- printk(KERN_INFO "TFDList start address = %16.16lx\n",
- (unsigned long) sp->txd_map);
- printk(KERN_INFO "TFDListPtr register = %8.8x%8.8x\n",
- ipg_r32(IPG_TFDLISTPTR1), ipg_r32(IPG_TFDLISTPTR0));
+ netdev_info(dev, "tx_current = %02x\n", sp->tx_current);
+ netdev_info(dev, "tx_dirty = %02x\n", sp->tx_dirty);
+ netdev_info(dev, "TFDList start address = %016lx\n",
+ (unsigned long) sp->txd_map);
+ netdev_info(dev, "TFDListPtr register = %08x%08x\n",
+ ipg_r32(IPG_TFDLISTPTR1), ipg_r32(IPG_TFDLISTPTR0));
for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
offset = (u32) &sp->txd[i].next_desc - (u32) sp->txd;
- printk(KERN_INFO "%2.2x %4.4x TFDNextPtr = %16.16lx\n", i,
- offset, (unsigned long) sp->txd[i].next_desc);
+ netdev_info(dev, "%02x %04x TFDNextPtr = %016lx\n",
+ i, offset, (unsigned long)sp->txd[i].next_desc);
offset = (u32) &sp->txd[i].tfc - (u32) sp->txd;
- printk(KERN_INFO "%2.2x %4.4x TFC = %16.16lx\n", i,
- offset, (unsigned long) sp->txd[i].tfc);
+ netdev_info(dev, "%02x %04x TFC = %016lx\n",
+ i, offset, (unsigned long) sp->txd[i].tfc);
offset = (u32) &sp->txd[i].frag_info - (u32) sp->txd;
- printk(KERN_INFO "%2.2x %4.4x frag_info = %16.16lx\n", i,
- offset, (unsigned long) sp->txd[i].frag_info);
+ netdev_info(dev, "%02x %04x frag_info = %016lx\n",
+ i, offset, (unsigned long) sp->txd[i].frag_info);
}
}
#endif
@@ -480,6 +483,10 @@ static int ipg_config_autoneg(struct net_device *dev)
u32 mac_ctrl_val;
u32 asicctrl;
u8 phyctrl;
+ const char *speed;
+ const char *duplex;
+ const char *tx_desc;
+ const char *rx_desc;
IPG_DEBUG_MSG("_config_autoneg\n");
@@ -499,27 +506,27 @@ static int ipg_config_autoneg(struct net_device *dev)
*/
sp->tenmbpsmode = 0;
- printk(KERN_INFO "%s: Link speed = ", dev->name);
-
/* Determine actual speed of operation. */
switch (phyctrl & IPG_PC_LINK_SPEED) {
case IPG_PC_LINK_SPEED_10MBPS:
- printk("10Mbps.\n");
- printk(KERN_INFO "%s: 10Mbps operational mode enabled.\n",
- dev->name);
+ speed = "10Mbps";
sp->tenmbpsmode = 1;
break;
case IPG_PC_LINK_SPEED_100MBPS:
- printk("100Mbps.\n");
+ speed = "100Mbps";
break;
case IPG_PC_LINK_SPEED_1000MBPS:
- printk("1000Mbps.\n");
+ speed = "1000Mbps";
break;
default:
- printk("undefined!\n");
+ speed = "undefined!";
return 0;
}
+ netdev_info(dev, "Link speed = %s\n", speed);
+ if (sp->tenmbpsmode == 1)
+ netdev_info(dev, "10Mbps operational mode enabled\n");
+
if (phyctrl & IPG_PC_DUPLEX_STATUS) {
fullduplex = 1;
txflowcontrol = 1;
@@ -528,38 +535,41 @@ static int ipg_config_autoneg(struct net_device *dev)
/* Configure full duplex, and flow control. */
if (fullduplex == 1) {
+
/* Configure IPG for full duplex operation. */
- printk(KERN_INFO "%s: setting full duplex, ", dev->name);
+
+ duplex = "full";
mac_ctrl_val |= IPG_MC_DUPLEX_SELECT_FD;
if (txflowcontrol == 1) {
- printk("TX flow control");
+ tx_desc = "";
mac_ctrl_val |= IPG_MC_TX_FLOW_CONTROL_ENABLE;
} else {
- printk("no TX flow control");
+ tx_desc = "no ";
mac_ctrl_val &= ~IPG_MC_TX_FLOW_CONTROL_ENABLE;
}
if (rxflowcontrol == 1) {
- printk(", RX flow control.");
+ rx_desc = "";
mac_ctrl_val |= IPG_MC_RX_FLOW_CONTROL_ENABLE;
} else {
- printk(", no RX flow control.");
+ rx_desc = "no ";
mac_ctrl_val &= ~IPG_MC_RX_FLOW_CONTROL_ENABLE;
}
-
- printk("\n");
} else {
- /* Configure IPG for half duplex operation. */
- printk(KERN_INFO "%s: setting half duplex, "
- "no TX flow control, no RX flow control.\n", dev->name);
-
- mac_ctrl_val &= ~IPG_MC_DUPLEX_SELECT_FD &
- ~IPG_MC_TX_FLOW_CONTROL_ENABLE &
- ~IPG_MC_RX_FLOW_CONTROL_ENABLE;
+ duplex = "half";
+ tx_desc = "no ";
+ rx_desc = "no ";
+ mac_ctrl_val &= (~IPG_MC_DUPLEX_SELECT_FD &
+ ~IPG_MC_TX_FLOW_CONTROL_ENABLE &
+ ~IPG_MC_RX_FLOW_CONTROL_ENABLE);
}
+
+ netdev_info(dev, "setting %s duplex, %sTX, %sRX flow control\n",
+ duplex, tx_desc, rx_desc);
ipg_w32(mac_ctrl_val, MAC_CTRL);
+
return 0;
}
@@ -784,14 +794,13 @@ static int init_rfdlist(struct net_device *dev)
* A receive buffer was not ready, break the
* RFD list here.
*/
- IPG_DEBUG_MSG("Cannot allocate Rx buffer.\n");
+ IPG_DEBUG_MSG("Cannot allocate Rx buffer\n");
/* Just in case we cannot allocate a single RFD.
* Should not occur.
*/
if (i == 0) {
- printk(KERN_ERR "%s: No memory available"
- " for RFD list.\n", dev->name);
+ netdev_err(dev, "No memory available for RFD list\n");
return -ENOMEM;
}
}
@@ -838,7 +847,7 @@ static void init_tfdlist(struct net_device *dev)
sp->tx_dirty = 0;
/* Write the location of the TFDList to the IPG. */
- IPG_DDEBUG_MSG("Starting TFDListPtr = %8.8x\n",
+ IPG_DDEBUG_MSG("Starting TFDListPtr = %08x\n",
(u32) sp->txd_map);
ipg_w32((u32) sp->txd_map, TFD_LIST_PTR_0);
ipg_w32(0x00000000, TFD_LIST_PTR_1);
@@ -864,7 +873,7 @@ static void ipg_nic_txfree(struct net_device *dev)
struct sk_buff *skb = sp->tx_buff[dirty];
struct ipg_tx *txfd = sp->txd + dirty;
- IPG_DEBUG_MSG("TFC = %16.16lx\n", (unsigned long) txfd->tfc);
+ IPG_DEBUG_MSG("TFC = %016lx\n", (unsigned long) txfd->tfc);
/* Look at each TFD's TFC field beginning
* at the last freed TFD up to the current TFD.
@@ -906,10 +915,8 @@ static void ipg_tx_timeout(struct net_device *dev)
spin_lock_irq(&sp->lock);
/* Re-configure after DMA reset. */
- if (ipg_io_config(dev) < 0) {
- printk(KERN_INFO "%s: Error during re-configuration.\n",
- dev->name);
- }
+ if (ipg_io_config(dev) < 0)
+ netdev_info(dev, "Error during re-configuration\n");
init_tfdlist(dev);
@@ -938,7 +945,7 @@ static void ipg_nic_txcleanup(struct net_device *dev)
*/
u32 txstatusdword = ipg_r32(TX_STATUS);
- IPG_DEBUG_MSG("TxStatus = %8.8x\n", txstatusdword);
+ IPG_DEBUG_MSG("TxStatus = %08x\n", txstatusdword);
/* Check for Transmit errors. Error bits only valid if
* TX_COMPLETE bit in the TXSTATUS register is a 1.
@@ -953,20 +960,20 @@ static void ipg_nic_txcleanup(struct net_device *dev)
/* Transmit error, increment stat counters. */
if (txstatusdword & IPG_TS_TX_ERROR) {
- IPG_DEBUG_MSG("Transmit error.\n");
+ IPG_DEBUG_MSG("Transmit error\n");
sp->stats.tx_errors++;
}
/* Late collision, re-enable transmitter. */
if (txstatusdword & IPG_TS_LATE_COLLISION) {
- IPG_DEBUG_MSG("Late collision on transmit.\n");
+ IPG_DEBUG_MSG("Late collision on transmit\n");
ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) &
IPG_MC_RSVD_MASK, MAC_CTRL);
}
/* Maximum collisions, re-enable transmitter. */
if (txstatusdword & IPG_TS_TX_MAX_COLL) {
- IPG_DEBUG_MSG("Maximum collisions on transmit.\n");
+ IPG_DEBUG_MSG("Maximum collisions on transmit\n");
ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) &
IPG_MC_RSVD_MASK, MAC_CTRL);
}
@@ -975,16 +982,14 @@ static void ipg_nic_txcleanup(struct net_device *dev)
* transmitter.
*/
if (txstatusdword & IPG_TS_TX_UNDERRUN) {
- IPG_DEBUG_MSG("Transmitter underrun.\n");
+ IPG_DEBUG_MSG("Transmitter underrun\n");
sp->stats.tx_fifo_errors++;
ipg_reset(dev, IPG_AC_TX_RESET | IPG_AC_DMA |
IPG_AC_NETWORK | IPG_AC_FIFO);
/* Re-configure after DMA reset. */
if (ipg_io_config(dev) < 0) {
- printk(KERN_INFO
- "%s: Error during re-configuration.\n",
- dev->name);
+ netdev_info(dev, "Error during re-configuration\n");
}
init_tfdlist(dev);
@@ -1063,7 +1068,7 @@ static int ipg_nic_rxrestore(struct net_device *dev)
* Linux system).
*/
if (ipg_get_rxbuff(dev, entry) < 0) {
- IPG_DEBUG_MSG("Cannot allocate new Rx buffer.\n");
+ IPG_DEBUG_MSG("Cannot allocate new Rx buffer\n");
break;
}
@@ -1134,7 +1139,7 @@ static int ipg_nic_rx_check_error(struct net_device *dev)
(IPG_RFS_RXFIFOOVERRUN | IPG_RFS_RXRUNTFRAME |
IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR |
IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR))) {
- IPG_DEBUG_MSG("Rx error, RFS = %16.16lx\n",
+ IPG_DEBUG_MSG("Rx error, RFS = %016lx\n",
(unsigned long) rxfd->rfs);
/* Increment general receive error statistic. */
@@ -1142,13 +1147,13 @@ static int ipg_nic_rx_check_error(struct net_device *dev)
/* Increment detailed receive error statistics. */
if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) {
- IPG_DEBUG_MSG("RX FIFO overrun occurred.\n");
+ IPG_DEBUG_MSG("RX FIFO overrun occurred\n");
sp->stats.rx_fifo_errors++;
}
if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) {
- IPG_DEBUG_MSG("RX runt occurred.\n");
+ IPG_DEBUG_MSG("RX runt occurred\n");
sp->stats.rx_length_errors++;
}
@@ -1157,7 +1162,7 @@ static int ipg_nic_rx_check_error(struct net_device *dev)
*/
if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) {
- IPG_DEBUG_MSG("RX alignment error occurred.\n");
+ IPG_DEBUG_MSG("RX alignment error occurred\n");
sp->stats.rx_frame_errors++;
}
@@ -1404,7 +1409,7 @@ static int ipg_nic_rx(struct net_device *dev)
*/
if (framelen > sp->rxfrag_size) {
IPG_DEBUG_MSG
- ("RFS FrameLen > allocated fragment size.\n");
+ ("RFS FrameLen > allocated fragment size\n");
framelen = sp->rxfrag_size;
}
@@ -1414,7 +1419,7 @@ static int ipg_nic_rx(struct net_device *dev)
IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR |
IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR)))) {
- IPG_DEBUG_MSG("Rx error, RFS = %16.16lx\n",
+ IPG_DEBUG_MSG("Rx error, RFS = %016lx\n",
(unsigned long int) rxfd->rfs);
/* Increment general receive error statistic. */
@@ -1422,12 +1427,12 @@ static int ipg_nic_rx(struct net_device *dev)
/* Increment detailed receive error statistics. */
if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) {
- IPG_DEBUG_MSG("RX FIFO overrun occurred.\n");
+ IPG_DEBUG_MSG("RX FIFO overrun occurred\n");
sp->stats.rx_fifo_errors++;
}
if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) {
- IPG_DEBUG_MSG("RX runt occurred.\n");
+ IPG_DEBUG_MSG("RX runt occurred\n");
sp->stats.rx_length_errors++;
}
@@ -1437,7 +1442,7 @@ static int ipg_nic_rx(struct net_device *dev)
*/
if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) {
- IPG_DEBUG_MSG("RX alignment error occurred.\n");
+ IPG_DEBUG_MSG("RX alignment error occurred\n");
sp->stats.rx_frame_errors++;
}
@@ -1508,7 +1513,7 @@ static int ipg_nic_rx(struct net_device *dev)
rxfd = sp->rxd + entry;
- IPG_DEBUG_MSG("Frame requires multiple RFDs.\n");
+ IPG_DEBUG_MSG("Frame requires multiple RFDs\n");
/* An unexpected event, additional code needed to handle
* properly. So for the time being, just disregard the
@@ -1557,8 +1562,7 @@ static void ipg_reset_after_host_error(struct work_struct *work)
init_tfdlist(dev);
if (ipg_io_config(dev) < 0) {
- printk(KERN_INFO "%s: Cannot recover from PCI error.\n",
- dev->name);
+ netdev_info(dev, "Cannot recover from PCI error\n");
schedule_delayed_work(&sp->task, HZ);
}
}
@@ -1586,7 +1590,7 @@ static irqreturn_t ipg_interrupt_handler(int irq, void *dev_inst)
*/
status = ipg_r16(INT_STATUS_ACK);
- IPG_DEBUG_MSG("IntStatusAck = %4.4x\n", status);
+ IPG_DEBUG_MSG("IntStatusAck = %04x\n", status);
/* Shared IRQ of remove event. */
if (!(status & IPG_IS_RSVD_MASK))
@@ -1599,7 +1603,7 @@ static irqreturn_t ipg_interrupt_handler(int irq, void *dev_inst)
/* If RFDListEnd interrupt, restore all used RFDs. */
if (status & IPG_IS_RFD_LIST_END) {
- IPG_DEBUG_MSG("RFDListEnd Interrupt.\n");
+ IPG_DEBUG_MSG("RFDListEnd Interrupt\n");
/* The RFD list end indicates an RFD was encountered
* with a 0 NextPtr, or with an RFDDone bit set to 1
@@ -1661,21 +1665,20 @@ static irqreturn_t ipg_interrupt_handler(int irq, void *dev_inst)
/* If LinkEvent interrupt, resolve autonegotiation. */
if (status & IPG_IS_LINK_EVENT) {
if (ipg_config_autoneg(dev) < 0)
- printk(KERN_INFO "%s: Auto-negotiation error.\n",
- dev->name);
+ netdev_info(dev, "Auto-negotiation error\n");
}
/* If MACCtrlFrame interrupt, do nothing. */
if (status & IPG_IS_MAC_CTRL_FRAME)
- IPG_DEBUG_MSG("MACCtrlFrame interrupt.\n");
+ IPG_DEBUG_MSG("MACCtrlFrame interrupt\n");
/* If RxComplete interrupt, do nothing. */
if (status & IPG_IS_RX_COMPLETE)
- IPG_DEBUG_MSG("RxComplete interrupt.\n");
+ IPG_DEBUG_MSG("RxComplete interrupt\n");
/* If RxEarly interrupt, do nothing. */
if (status & IPG_IS_RX_EARLY)
- IPG_DEBUG_MSG("RxEarly interrupt.\n");
+ IPG_DEBUG_MSG("RxEarly interrupt\n");
out_enable:
/* Re-enable IPG interrupts. */
@@ -1749,8 +1752,7 @@ static int ipg_nic_open(struct net_device *dev)
rc = request_irq(pdev->irq, ipg_interrupt_handler, IRQF_SHARED,
dev->name, dev);
if (rc < 0) {
- printk(KERN_INFO "%s: Error when requesting interrupt.\n",
- dev->name);
+ netdev_info(dev, "Error when requesting interrupt\n");
goto out;
}
@@ -1770,8 +1772,7 @@ static int ipg_nic_open(struct net_device *dev)
rc = init_rfdlist(dev);
if (rc < 0) {
- printk(KERN_INFO "%s: Error during configuration.\n",
- dev->name);
+ netdev_info(dev, "Error during configuration\n");
goto err_free_tx_2;
}
@@ -1779,14 +1780,13 @@ static int ipg_nic_open(struct net_device *dev)
rc = ipg_io_config(dev);
if (rc < 0) {
- printk(KERN_INFO "%s: Error during configuration.\n",
- dev->name);
+ netdev_info(dev, "Error during configuration\n");
goto err_release_tfdlist_3;
}
/* Resolve autonegotiation. */
if (ipg_config_autoneg(dev) < 0)
- printk(KERN_INFO "%s: Auto-negotiation error.\n", dev->name);
+ netdev_info(dev, "Auto-negotiation error\n");
/* initialize JUMBO Frame control variable */
sp->jumbo.found_start = 0;
@@ -1961,7 +1961,7 @@ static void ipg_set_phy_default_param(unsigned char rev,
{
unsigned short length;
unsigned char revision;
- unsigned short *phy_param;
+ const unsigned short *phy_param;
unsigned short address, value;
phy_param = &DefaultPhyParam[0];
@@ -2201,7 +2201,7 @@ static const struct net_device_ops ipg_netdev_ops = {
.ndo_stop = ipg_nic_stop,
.ndo_start_xmit = ipg_nic_hard_start_xmit,
.ndo_get_stats = ipg_nic_get_stats,
- .ndo_set_multicast_list = ipg_nic_set_multicast_list,
+ .ndo_set_rx_mode = ipg_nic_set_multicast_list,
.ndo_do_ioctl = ipg_ioctl,
.ndo_tx_timeout = ipg_tx_timeout,
.ndo_change_mtu = ipg_nic_change_mtu,
@@ -2222,7 +2222,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
if (rc < 0)
goto out;
- printk(KERN_INFO "%s: %s\n", pci_name(pdev), ipg_brand_name[i]);
+ pr_info("%s: %s\n", pci_name(pdev), ipg_brand_name[i]);
pci_set_master(pdev);
@@ -2230,8 +2230,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
if (rc < 0) {
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc < 0) {
- printk(KERN_ERR "%s: DMA config failed.\n",
- pci_name(pdev));
+ pr_err("%s: DMA config failed\n", pci_name(pdev));
goto err_disable_0;
}
}
@@ -2241,7 +2240,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
*/
dev = alloc_etherdev(sizeof(struct ipg_nic_private));
if (!dev) {
- printk(KERN_ERR "%s: alloc_etherdev failed\n", pci_name(pdev));
+ pr_err("%s: alloc_etherdev failed\n", pci_name(pdev));
rc = -ENOMEM;
goto err_disable_0;
}
@@ -2267,7 +2266,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
ioaddr = pci_iomap(pdev, 1, pci_resource_len(pdev, 1));
if (!ioaddr) {
- printk(KERN_ERR "%s cannot map MMIO\n", pci_name(pdev));
+ pr_err("%s: cannot map MMIO\n", pci_name(pdev));
rc = -EIO;
goto err_release_regions_2;
}
@@ -2289,7 +2288,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
if (rc < 0)
goto err_unmap_3;
- printk(KERN_INFO "Ethernet device registered as: %s\n", dev->name);
+ netdev_info(dev, "Ethernet device registered\n");
out:
return rc;
diff --git a/drivers/net/ipg.h b/drivers/net/ethernet/icplus/ipg.h
index 6ce027355fcf..6ce027355fcf 100644
--- a/drivers/net/ipg.h
+++ b/drivers/net/ethernet/icplus/ipg.h
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
new file mode 100644
index 000000000000..61029dc7fa6f
--- /dev/null
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -0,0 +1,222 @@
+#
+# Intel network device configuration
+#
+
+config NET_VENDOR_INTEL
+ bool "Intel devices"
+ default y
+ depends on PCI || PCI_MSI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Intel cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_INTEL
+
+config E100
+ tristate "Intel(R) PRO/100+ support"
+ depends on PCI
+ select NET_CORE
+ select MII
+ ---help---
+ This driver supports Intel(R) PRO/100 family of adapters.
+ To verify that your adapter is supported, find the board ID number
+ on the adapter. Look for a label that has a barcode and a number
+ in the format 123456-001 (six digits hyphen three digits).
+
+ Use the above information and the Adapter & Driver ID Guide at:
+
+ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+ to identify the adapter.
+
+ For the latest Intel PRO/100 network driver for Linux, see:
+
+ <http://www.intel.com/p/en_US/support/highlights/network/pro100plus>
+
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/e100.txt>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called e100.
+
+config E1000
+ tristate "Intel(R) PRO/1000 Gigabit Ethernet support"
+ depends on PCI
+ ---help---
+ This driver supports Intel(R) PRO/1000 gigabit ethernet family of
+ adapters. For more information on how to identify your adapter, go
+ to the Adapter & Driver ID Guide at:
+
+ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+ For general information and support, go to the Intel support
+ website at:
+
+ <http://support.intel.com>
+
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/e1000.txt>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called e1000.
+
+config E1000E
+ tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
+ depends on PCI && (!SPARC32 || BROKEN)
+ select CRC32
+ ---help---
+ This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
+ ethernet family of adapters. For PCI or PCI-X e1000 adapters,
+ use the regular e1000 driver For more information on how to
+ identify your adapter, go to the Adapter & Driver ID Guide at:
+
+ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+ For general information and support, go to the Intel support
+ website at:
+
+ <http://support.intel.com>
+
+ To compile this driver as a module, choose M here. The module
+ will be called e1000e.
+
+config IGB
+ tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
+ depends on PCI
+ ---help---
+ This driver supports Intel(R) 82575/82576 gigabit ethernet family of
+ adapters. For more information on how to identify your adapter, go
+ to the Adapter & Driver ID Guide at:
+
+ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+ For general information and support, go to the Intel support
+ website at:
+
+ <http://support.intel.com>
+
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/e1000.txt>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called igb.
+
+config IGB_DCA
+ bool "Direct Cache Access (DCA) Support"
+ default y
+ depends on IGB && DCA && !(IGB=y && DCA=m)
+ ---help---
+ Say Y here if you want to use Direct Cache Access (DCA) in the
+ 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 IGBVF
+ tristate "Intel(R) 82576 Virtual Function Ethernet support"
+ depends on PCI
+ ---help---
+ This driver supports Intel(R) 82576 virtual functions. For more
+ information on how to identify your adapter, go to the Adapter &
+ Driver ID Guide at:
+
+ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+ For general information and support, go to the Intel support
+ website at:
+
+ <http://support.intel.com>
+
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/e1000.txt>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called igbvf.
+
+config IXGB
+ tristate "Intel(R) PRO/10GbE support"
+ depends on PCI
+ ---help---
+ This driver supports Intel(R) PRO/10GbE family of adapters for
+ PCI-X type cards. For PCI-E type cards, use the "ixgbe" driver
+ instead. For more information on how to identify your adapter, go
+ to the Adapter & Driver ID Guide at:
+
+ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+ For general information and support, go to the Intel support
+ website at:
+
+ <http://support.intel.com>
+
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/ixgb.txt>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ixgb.
+
+config IXGBE
+ tristate "Intel(R) 10GbE PCI Express adapters support"
+ depends on PCI && INET
+ select MDIO
+ ---help---
+ This driver supports Intel(R) 10GbE PCI Express family of
+ adapters. For more information on how to identify your adapter, go
+ to the Adapter & Driver ID Guide at:
+
+ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+ For general information and support, go to the Intel support
+ website at:
+
+ <http://support.intel.com>
+
+ To compile this driver as a module, choose M here. The module
+ will be called ixgbe.
+
+config IXGBE_DCA
+ bool "Direct Cache Access (DCA) Support"
+ default y
+ depends on IXGBE && DCA && !(IXGBE=y && DCA=m)
+ ---help---
+ Say Y here if you want to use Direct Cache Access (DCA) in the
+ 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 IXGBE_DCB
+ bool "Data Center Bridging (DCB) Support"
+ default n
+ depends on IXGBE && DCB
+ ---help---
+ Say Y here if you want to use Data Center Bridging (DCB) in the
+ driver.
+
+ If unsure, say N.
+
+config IXGBEVF
+ tristate "Intel(R) 82599 Virtual Function Ethernet support"
+ depends on PCI_MSI
+ ---help---
+ This driver supports Intel(R) 82599 virtual functions. For more
+ information on how to identify your adapter, go to the Adapter &
+ Driver ID Guide at:
+
+ <http://support.intel.com/support/network/sb/CS-008441.htm>
+
+ For general information and support, go to the Intel support
+ website at:
+
+ <http://support.intel.com>
+
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/ixgbevf.txt>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ixgbevf. MSI-X interrupt support is required
+ for this driver to work correctly.
+
+endif # NET_VENDOR_INTEL
diff --git a/drivers/net/ethernet/intel/Makefile b/drivers/net/ethernet/intel/Makefile
new file mode 100644
index 000000000000..c8210e688669
--- /dev/null
+++ b/drivers/net/ethernet/intel/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the Intel network device drivers.
+#
+
+obj-$(CONFIG_E100) += e100.o
+obj-$(CONFIG_E1000) += e1000/
+obj-$(CONFIG_E1000E) += e1000e/
+obj-$(CONFIG_IGB) += igb/
+obj-$(CONFIG_IGBVF) += igbvf/
+obj-$(CONFIG_IXGBE) += ixgbe/
+obj-$(CONFIG_IXGBEVF) += ixgbevf/
+obj-$(CONFIG_IXGB) += ixgb/
diff --git a/drivers/net/e100.c b/drivers/net/ethernet/intel/e100.c
index c1352c60c299..ae17cd1a907f 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -2502,12 +2502,8 @@ static void e100_get_ringparam(struct net_device *netdev,
ring->rx_max_pending = rfds->max;
ring->tx_max_pending = cbs->max;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = rfds->count;
ring->tx_pending = cbs->count;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
static int e100_set_ringparam(struct net_device *netdev,
@@ -2738,7 +2734,7 @@ static const struct net_device_ops e100_netdev_ops = {
.ndo_stop = e100_close,
.ndo_start_xmit = e100_xmit_frame,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = e100_set_multicast_list,
+ .ndo_set_rx_mode = e100_set_multicast_list,
.ndo_set_mac_address = e100_set_mac_address,
.ndo_change_mtu = e100_change_mtu,
.ndo_do_ioctl = e100_do_ioctl,
diff --git a/drivers/net/e1000/Makefile b/drivers/net/ethernet/intel/e1000/Makefile
index 4a6ab1522451..4a6ab1522451 100644
--- a/drivers/net/e1000/Makefile
+++ b/drivers/net/ethernet/intel/e1000/Makefile
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h
index 24f41da8c4be..1e1596990b5c 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/ethernet/intel/e1000/e1000.h
@@ -150,6 +150,8 @@ struct e1000_buffer {
unsigned long time_stamp;
u16 length;
u16 next_to_watch;
+ unsigned int segs;
+ unsigned int bytecount;
u16 mapped_as_page;
};
@@ -212,9 +214,6 @@ struct e1000_rx_ring {
/* board specific private data structure */
struct e1000_adapter {
- struct timer_list tx_fifo_stall_timer;
- struct timer_list watchdog_timer;
- struct timer_list phy_info_timer;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u16 mng_vlan_id;
u32 bd_number;
@@ -235,7 +234,6 @@ struct e1000_adapter {
u16 tx_itr;
u16 rx_itr;
- struct work_struct reset_task;
u8 fc_autoneg;
/* TX */
@@ -308,8 +306,12 @@ struct e1000_adapter {
bool discarding;
- struct work_struct fifo_stall_task;
- struct work_struct phy_info_task;
+ struct work_struct reset_task;
+ struct delayed_work watchdog_task;
+ struct delayed_work fifo_stall_task;
+ struct delayed_work phy_info_task;
+
+ struct mutex mutex;
};
enum e1000_state_t {
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index 5548d464261a..2b223ac99c42 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -540,12 +540,8 @@ static void e1000_get_ringparam(struct net_device *netdev,
E1000_MAX_82544_RXD;
ring->tx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_TXD :
E1000_MAX_82544_TXD;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = rxdr->count;
ring->tx_pending = txdr->count;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
static int e1000_set_ringparam(struct net_device *netdev,
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/ethernet/intel/e1000/e1000_hw.c
index a5a89ecb6f36..36ee76bf4cba 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c
@@ -5385,7 +5385,7 @@ static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
if (ret_val)
return ret_val;
- mdelay(20);
+ msleep(20);
ret_val = e1000_write_phy_reg(hw, 0x0000,
IGP01E1000_IEEE_FORCE_GIGA);
@@ -5413,7 +5413,7 @@ static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
if (ret_val)
return ret_val;
- mdelay(20);
+ msleep(20);
/* Now enable the transmitter */
ret_val =
@@ -5440,7 +5440,7 @@ static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
if (ret_val)
return ret_val;
- mdelay(20);
+ msleep(20);
ret_val = e1000_write_phy_reg(hw, 0x0000,
IGP01E1000_IEEE_FORCE_GIGA);
@@ -5457,7 +5457,7 @@ static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
if (ret_val)
return ret_val;
- mdelay(20);
+ msleep(20);
/* Now enable the transmitter */
ret_val =
@@ -5750,26 +5750,26 @@ static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0)
break;
- mdelay(100);
+ msleep(100);
}
/* Recommended delay time after link has been lost */
- mdelay(1000);
+ msleep(1000);
/* Now we will re-enable th transmitter on the PHY */
ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
if (ret_val)
return ret_val;
- mdelay(50);
+ msleep(50);
ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
if (ret_val)
return ret_val;
- mdelay(50);
+ msleep(50);
ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
if (ret_val)
return ret_val;
- mdelay(50);
+ msleep(50);
ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
if (ret_val)
return ret_val;
@@ -5794,7 +5794,7 @@ static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
if (mii_status_reg & MII_SR_LINK_STATUS)
break;
- mdelay(100);
+ msleep(100);
}
return E1000_SUCCESS;
}
@@ -5825,6 +5825,6 @@ static s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
{
e_dbg("e1000_get_phy_cfg_done");
- mdelay(10);
+ msleep(10);
return E1000_SUCCESS;
}
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/ethernet/intel/e1000/e1000_hw.h
index 5c9a8403668b..5c9a8403668b 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/ethernet/intel/e1000/e1000_hw.h
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index f97afda941d7..cf480b554622 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -131,10 +131,8 @@ static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring);
static void e1000_set_rx_mode(struct net_device *netdev);
-static void e1000_update_phy_info(unsigned long data);
static void e1000_update_phy_info_task(struct work_struct *work);
-static void e1000_watchdog(unsigned long data);
-static void e1000_82547_tx_fifo_stall(unsigned long data);
+static void e1000_watchdog(struct work_struct *work);
static void e1000_82547_tx_fifo_stall_task(struct work_struct *work);
static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
struct net_device *netdev);
@@ -487,12 +485,21 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter)
e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
- mdelay(1);
+ msleep(1);
}
out:
return;
}
+static void e1000_down_and_stop(struct e1000_adapter *adapter)
+{
+ set_bit(__E1000_DOWN, &adapter->flags);
+ cancel_work_sync(&adapter->reset_task);
+ cancel_delayed_work_sync(&adapter->watchdog_task);
+ cancel_delayed_work_sync(&adapter->phy_info_task);
+ cancel_delayed_work_sync(&adapter->fifo_stall_task);
+}
+
void e1000_down(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
@@ -522,13 +529,9 @@ void e1000_down(struct e1000_adapter *adapter)
/*
* Setting DOWN must be after irq_disable to prevent
* a screaming interrupt. Setting DOWN also prevents
- * timers and tasks from rescheduling.
+ * tasks from rescheduling.
*/
- set_bit(__E1000_DOWN, &adapter->flags);
-
- del_timer_sync(&adapter->tx_fifo_stall_timer);
- del_timer_sync(&adapter->watchdog_timer);
- del_timer_sync(&adapter->phy_info_timer);
+ e1000_down_and_stop(adapter);
adapter->link_speed = 0;
adapter->link_duplex = 0;
@@ -543,10 +546,10 @@ static void e1000_reinit_safe(struct e1000_adapter *adapter)
{
while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
msleep(1);
- rtnl_lock();
+ mutex_lock(&adapter->mutex);
e1000_down(adapter);
e1000_up(adapter);
- rtnl_unlock();
+ mutex_unlock(&adapter->mutex);
clear_bit(__E1000_RESETTING, &adapter->flags);
}
@@ -1080,6 +1083,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
netdev->vlan_features |= NETIF_F_HW_CSUM;
netdev->vlan_features |= NETIF_F_SG;
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
/* initialize eeprom parameters */
@@ -1118,21 +1123,12 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (!is_valid_ether_addr(netdev->perm_addr))
e_err(probe, "Invalid MAC Address\n");
- init_timer(&adapter->tx_fifo_stall_timer);
- adapter->tx_fifo_stall_timer.function = e1000_82547_tx_fifo_stall;
- adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
-
- init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = e1000_watchdog;
- adapter->watchdog_timer.data = (unsigned long) adapter;
- init_timer(&adapter->phy_info_timer);
- adapter->phy_info_timer.function = e1000_update_phy_info;
- adapter->phy_info_timer.data = (unsigned long)adapter;
-
- INIT_WORK(&adapter->fifo_stall_task, e1000_82547_tx_fifo_stall_task);
+ INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog);
+ INIT_DELAYED_WORK(&adapter->fifo_stall_task,
+ e1000_82547_tx_fifo_stall_task);
+ INIT_DELAYED_WORK(&adapter->phy_info_task, e1000_update_phy_info_task);
INIT_WORK(&adapter->reset_task, e1000_reset_task);
- INIT_WORK(&adapter->phy_info_task, e1000_update_phy_info_task);
e1000_check_options(adapter);
@@ -1277,13 +1273,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- set_bit(__E1000_DOWN, &adapter->flags);
- del_timer_sync(&adapter->tx_fifo_stall_timer);
- del_timer_sync(&adapter->watchdog_timer);
- del_timer_sync(&adapter->phy_info_timer);
-
- cancel_work_sync(&adapter->reset_task);
-
+ e1000_down_and_stop(adapter);
e1000_release_manageability(adapter);
unregister_netdev(netdev);
@@ -1327,6 +1317,7 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
e1000_irq_disable(adapter);
spin_lock_init(&adapter->stats_lock);
+ mutex_init(&adapter->mutex);
set_bit(__E1000_DOWN, &adapter->flags);
@@ -1367,7 +1358,7 @@ static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
* The open entry point is called when a network interface is made
* active by the system (IFF_UP). At this point all resources needed
* for transmit and receive operations are allocated, the interrupt
- * handler is registered with the OS, the watchdog timer is started,
+ * handler is registered with the OS, the watchdog task is started,
* and the stack is notified that the interface is ready.
**/
@@ -1812,8 +1803,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
- rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
- E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+ rctl |= E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
+ E1000_RCTL_RDMTS_HALF |
(hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
if (hw->tbi_compatibility_on == 1)
@@ -1915,7 +1906,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
}
/* Enable Receives */
- ew32(RCTL, rctl);
+ ew32(RCTL, rctl | E1000_RCTL_EN);
}
/**
@@ -2329,35 +2320,23 @@ static void e1000_set_rx_mode(struct net_device *netdev)
kfree(mcarray);
}
-/* 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;
- schedule_work(&adapter->phy_info_task);
-}
-
+/**
+ * e1000_update_phy_info_task - get phy info
+ * @work: work struct contained inside adapter struct
+ *
+ * Need to wait a few seconds after link up to get diagnostic information from
+ * the phy
+ */
static void e1000_update_phy_info_task(struct work_struct *work)
{
struct e1000_adapter *adapter = container_of(work,
- struct e1000_adapter,
- phy_info_task);
- struct e1000_hw *hw = &adapter->hw;
-
- rtnl_lock();
- e1000_phy_get_info(hw, &adapter->phy_info);
- rtnl_unlock();
-}
-
-/**
- * e1000_82547_tx_fifo_stall - Timer Call-back
- * @data: pointer to adapter cast into an unsigned long
- **/
-static void e1000_82547_tx_fifo_stall(unsigned long data)
-{
- struct e1000_adapter *adapter = (struct e1000_adapter *)data;
- schedule_work(&adapter->fifo_stall_task);
+ struct e1000_adapter,
+ phy_info_task.work);
+ if (test_bit(__E1000_DOWN, &adapter->flags))
+ return;
+ mutex_lock(&adapter->mutex);
+ e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+ mutex_unlock(&adapter->mutex);
}
/**
@@ -2367,13 +2346,15 @@ static void e1000_82547_tx_fifo_stall(unsigned long data)
static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
{
struct e1000_adapter *adapter = container_of(work,
- struct e1000_adapter,
- fifo_stall_task);
+ struct e1000_adapter,
+ fifo_stall_task.work);
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
u32 tctl;
- rtnl_lock();
+ if (test_bit(__E1000_DOWN, &adapter->flags))
+ return;
+ mutex_lock(&adapter->mutex);
if (atomic_read(&adapter->tx_fifo_stall)) {
if ((er32(TDT) == er32(TDH)) &&
(er32(TDFT) == er32(TDFH)) &&
@@ -2391,10 +2372,10 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
atomic_set(&adapter->tx_fifo_stall, 0);
netif_wake_queue(netdev);
} else if (!test_bit(__E1000_DOWN, &adapter->flags)) {
- mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
+ schedule_delayed_work(&adapter->fifo_stall_task, 1);
}
}
- rtnl_unlock();
+ mutex_unlock(&adapter->mutex);
}
bool e1000_has_link(struct e1000_adapter *adapter)
@@ -2435,17 +2416,23 @@ bool e1000_has_link(struct e1000_adapter *adapter)
}
/**
- * e1000_watchdog - Timer Call-back
- * @data: pointer to adapter cast into an unsigned long
+ * e1000_watchdog - work function
+ * @work: work struct contained inside adapter struct
**/
-static void e1000_watchdog(unsigned long data)
+static void e1000_watchdog(struct work_struct *work)
{
- struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+ struct e1000_adapter *adapter = container_of(work,
+ struct e1000_adapter,
+ watchdog_task.work);
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct e1000_tx_ring *txdr = adapter->tx_ring;
u32 link, tctl;
+ if (test_bit(__E1000_DOWN, &adapter->flags))
+ return;
+
+ mutex_lock(&adapter->mutex);
link = e1000_has_link(adapter);
if ((netif_carrier_ok(netdev)) && link)
goto link_up;
@@ -2491,8 +2478,8 @@ static void e1000_watchdog(unsigned long data)
netif_carrier_on(netdev);
if (!test_bit(__E1000_DOWN, &adapter->flags))
- mod_timer(&adapter->phy_info_timer,
- round_jiffies(jiffies + 2 * HZ));
+ schedule_delayed_work(&adapter->phy_info_task,
+ 2 * HZ);
adapter->smartspeed = 0;
}
} else {
@@ -2504,8 +2491,8 @@ static void e1000_watchdog(unsigned long data)
netif_carrier_off(netdev);
if (!test_bit(__E1000_DOWN, &adapter->flags))
- mod_timer(&adapter->phy_info_timer,
- round_jiffies(jiffies + 2 * HZ));
+ schedule_delayed_work(&adapter->phy_info_task,
+ 2 * HZ);
}
e1000_smartspeed(adapter);
@@ -2534,8 +2521,8 @@ link_up:
* (Do the reset outside of interrupt context). */
adapter->tx_timeout_count++;
schedule_work(&adapter->reset_task);
- /* return immediately since reset is imminent */
- return;
+ /* exit immediately since reset is imminent */
+ goto unlock;
}
}
@@ -2561,10 +2548,12 @@ link_up:
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = true;
- /* Reset the timer */
+ /* Reschedule the task */
if (!test_bit(__E1000_DOWN, &adapter->flags))
- mod_timer(&adapter->watchdog_timer,
- round_jiffies(jiffies + 2 * HZ));
+ schedule_delayed_work(&adapter->watchdog_task, 2 * HZ);
+
+unlock:
+ mutex_unlock(&adapter->mutex);
}
enum latency_range {
@@ -2846,7 +2835,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info;
unsigned int len = skb_headlen(skb);
unsigned int offset = 0, size, count = 0, i;
- unsigned int f;
+ unsigned int f, bytecount, segs;
i = tx_ring->next_to_use;
@@ -2905,13 +2894,14 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
}
for (f = 0; f < nr_frags; f++) {
- struct skb_frag_struct *frag;
+ const struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[f];
- len = frag->size;
- offset = frag->page_offset;
+ len = skb_frag_size(frag);
+ offset = 0;
while (len) {
+ unsigned long bufend;
i++;
if (unlikely(i == tx_ring->count))
i = 0;
@@ -2925,18 +2915,19 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
/* Workaround for potential 82544 hang in PCI-X.
* Avoid terminating buffers within evenly-aligned
* dwords. */
+ bufend = (unsigned long)
+ page_to_phys(skb_frag_page(frag));
+ bufend += offset + size - 1;
if (unlikely(adapter->pcix_82544 &&
- !((unsigned long)(page_to_phys(frag->page) + offset
- + size - 1) & 4) &&
- size > 4))
+ !(bufend & 4) &&
+ size > 4))
size -= 4;
buffer_info->length = size;
buffer_info->time_stamp = jiffies;
buffer_info->mapped_as_page = true;
- buffer_info->dma = dma_map_page(&pdev->dev, frag->page,
- offset, size,
- DMA_TO_DEVICE);
+ buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag,
+ offset, size, DMA_TO_DEVICE);
if (dma_mapping_error(&pdev->dev, buffer_info->dma))
goto dma_error;
buffer_info->next_to_watch = i;
@@ -2947,7 +2938,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
}
}
+ segs = skb_shinfo(skb)->gso_segs ?: 1;
+ /* multiply data chunks by size of headers */
+ bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len;
+
tx_ring->buffer_info[i].skb = skb;
+ tx_ring->buffer_info[i].segs = segs;
+ tx_ring->buffer_info[i].bytecount = bytecount;
tx_ring->buffer_info[first].next_to_watch = i;
return count;
@@ -3186,7 +3183,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
nr_frags = skb_shinfo(skb)->nr_frags;
for (f = 0; f < nr_frags; f++)
- count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
+ count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]),
max_txd_pwr);
if (adapter->pcix_82544)
count += nr_frags;
@@ -3196,14 +3193,12 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2)))
return NETDEV_TX_BUSY;
- if (unlikely(hw->mac_type == e1000_82547)) {
- if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
- netif_stop_queue(netdev);
- if (!test_bit(__E1000_DOWN, &adapter->flags))
- mod_timer(&adapter->tx_fifo_stall_timer,
- jiffies + 1);
- return NETDEV_TX_BUSY;
- }
+ if (unlikely((hw->mac_type == e1000_82547) &&
+ (e1000_82547_fifo_workaround(adapter, skb)))) {
+ netif_stop_queue(netdev);
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ schedule_delayed_work(&adapter->fifo_stall_task, 1);
+ return NETDEV_TX_BUSY;
}
if (vlan_tx_tag_present(skb)) {
@@ -3265,6 +3260,8 @@ static void e1000_reset_task(struct work_struct *work)
struct e1000_adapter *adapter =
container_of(work, struct e1000_adapter, reset_task);
+ if (test_bit(__E1000_DOWN, &adapter->flags))
+ return;
e1000_reinit_safe(adapter);
}
@@ -3273,7 +3270,7 @@ static void e1000_reset_task(struct work_struct *work)
* @netdev: network interface device structure
*
* Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
+ * The statistics are actually updated from the watchdog.
**/
static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
@@ -3541,7 +3538,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
hw->get_link_status = 1;
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->flags))
- mod_timer(&adapter->watchdog_timer, jiffies + 1);
+ schedule_delayed_work(&adapter->watchdog_task, 1);
}
/* disable interrupts, without the synchronize_irq bit */
@@ -3621,14 +3618,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
cleaned = (i == eop);
if (cleaned) {
- struct sk_buff *skb = buffer_info->skb;
- unsigned int segs, bytecount;
- segs = skb_shinfo(skb)->gso_segs ?: 1;
- /* multiply data chunks by size of headers */
- bytecount = ((segs - 1) * skb_headlen(skb)) +
- skb->len;
- total_tx_packets += segs;
- total_tx_bytes += bytecount;
+ total_tx_packets += buffer_info->segs;
+ total_tx_bytes += buffer_info->bytecount;
}
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
tx_desc->upper.data = 0;
@@ -3746,7 +3737,7 @@ static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
bi->page = NULL;
skb->len += length;
skb->data_len += length;
- skb->truesize += length;
+ skb->truesize += PAGE_SIZE;
}
/**
@@ -4725,6 +4716,8 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
netif_device_detach(netdev);
+ mutex_lock(&adapter->mutex);
+
if (netif_running(netdev)) {
WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
e1000_down(adapter);
@@ -4732,8 +4725,10 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
#ifdef CONFIG_PM
retval = pci_save_state(pdev);
- if (retval)
+ if (retval) {
+ mutex_unlock(&adapter->mutex);
return retval;
+ }
#endif
status = er32(STATUS);
@@ -4788,6 +4783,8 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
if (netif_running(netdev))
e1000_free_irq(adapter);
+ mutex_unlock(&adapter->mutex);
+
pci_disable_device(pdev);
return 0;
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/ethernet/intel/e1000/e1000_osdep.h
index 33e7c45a4fe4..33e7c45a4fe4 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/ethernet/intel/e1000/e1000_osdep.h
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/ethernet/intel/e1000/e1000_param.c
index 1301eba8b57a..1301eba8b57a 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_param.c
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
index e4f42257c24c..e1159e54334a 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
@@ -1441,7 +1441,7 @@ static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw)
er32(ICRXDMTC);
}
-static struct e1000_mac_operations es2_mac_ops = {
+static const struct e1000_mac_operations es2_mac_ops = {
.read_mac_addr = e1000_read_mac_addr_80003es2lan,
.id_led_init = e1000e_id_led_init,
.blink_led = e1000e_blink_led_generic,
@@ -1464,7 +1464,7 @@ static struct e1000_mac_operations es2_mac_ops = {
.setup_led = e1000e_setup_led_generic,
};
-static struct e1000_phy_operations es2_phy_ops = {
+static const struct e1000_phy_operations es2_phy_ops = {
.acquire = e1000_acquire_phy_80003es2lan,
.check_polarity = e1000_check_polarity_m88,
.check_reset_block = e1000e_check_reset_block_generic,
@@ -1482,7 +1482,7 @@ static struct e1000_phy_operations es2_phy_ops = {
.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan,
};
-static struct e1000_nvm_operations es2_nvm_ops = {
+static const struct e1000_nvm_operations es2_nvm_ops = {
.acquire = e1000_acquire_nvm_80003es2lan,
.read = e1000e_read_nvm_eerd,
.release = e1000_release_nvm_80003es2lan,
@@ -1492,13 +1492,12 @@ static struct e1000_nvm_operations es2_nvm_ops = {
.write = e1000_write_nvm_80003es2lan,
};
-struct e1000_info e1000_es2_info = {
+const struct e1000_info e1000_es2_info = {
.mac = e1000_80003es2lan,
.flags = FLAG_HAS_HW_VLAN_FILTER
| FLAG_HAS_JUMBO_FRAMES
| FLAG_HAS_WOL
| FLAG_APME_IN_CTRL3
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_RX_NEEDS_RESTART /* errata */
| FLAG_TARC_SET_BIT_ZERO /* errata */
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c
index 536b3a55c45f..a3e65fd26e09 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/ethernet/intel/e1000e/82571.c
@@ -1927,7 +1927,7 @@ static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw)
er32(ICRXDMTC);
}
-static struct e1000_mac_operations e82571_mac_ops = {
+static const struct e1000_mac_operations e82571_mac_ops = {
/* .check_mng_mode: mac type dependent */
/* .check_for_link: media type dependent */
.id_led_init = e1000e_id_led_init,
@@ -1949,7 +1949,7 @@ static struct e1000_mac_operations e82571_mac_ops = {
.read_mac_addr = e1000_read_mac_addr_82571,
};
-static struct e1000_phy_operations e82_phy_ops_igp = {
+static const struct e1000_phy_operations e82_phy_ops_igp = {
.acquire = e1000_get_hw_semaphore_82571,
.check_polarity = e1000_check_polarity_igp,
.check_reset_block = e1000e_check_reset_block_generic,
@@ -1967,7 +1967,7 @@ static struct e1000_phy_operations e82_phy_ops_igp = {
.cfg_on_link_up = NULL,
};
-static struct e1000_phy_operations e82_phy_ops_m88 = {
+static const struct e1000_phy_operations e82_phy_ops_m88 = {
.acquire = e1000_get_hw_semaphore_82571,
.check_polarity = e1000_check_polarity_m88,
.check_reset_block = e1000e_check_reset_block_generic,
@@ -1985,7 +1985,7 @@ static struct e1000_phy_operations e82_phy_ops_m88 = {
.cfg_on_link_up = NULL,
};
-static struct e1000_phy_operations e82_phy_ops_bm = {
+static const struct e1000_phy_operations e82_phy_ops_bm = {
.acquire = e1000_get_hw_semaphore_82571,
.check_polarity = e1000_check_polarity_m88,
.check_reset_block = e1000e_check_reset_block_generic,
@@ -2003,7 +2003,7 @@ static struct e1000_phy_operations e82_phy_ops_bm = {
.cfg_on_link_up = NULL,
};
-static struct e1000_nvm_operations e82571_nvm_ops = {
+static const struct e1000_nvm_operations e82571_nvm_ops = {
.acquire = e1000_acquire_nvm_82571,
.read = e1000e_read_nvm_eerd,
.release = e1000_release_nvm_82571,
@@ -2013,13 +2013,12 @@ static struct e1000_nvm_operations e82571_nvm_ops = {
.write = e1000_write_nvm_82571,
};
-struct e1000_info e1000_82571_info = {
+const struct e1000_info e1000_82571_info = {
.mac = e1000_82571,
.flags = FLAG_HAS_HW_VLAN_FILTER
| FLAG_HAS_JUMBO_FRAMES
| FLAG_HAS_WOL
| FLAG_APME_IN_CTRL3
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_SMART_POWER_DOWN
| FLAG_RESET_OVERWRITES_LAA /* errata */
@@ -2035,13 +2034,12 @@ struct e1000_info e1000_82571_info = {
.nvm_ops = &e82571_nvm_ops,
};
-struct e1000_info e1000_82572_info = {
+const struct e1000_info e1000_82572_info = {
.mac = e1000_82572,
.flags = FLAG_HAS_HW_VLAN_FILTER
| FLAG_HAS_JUMBO_FRAMES
| FLAG_HAS_WOL
| FLAG_APME_IN_CTRL3
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_TARC_SPEED_MODE_BIT, /* errata */
.flags2 = FLAG2_DISABLE_ASPM_L1 /* errata 13 */
@@ -2054,12 +2052,11 @@ struct e1000_info e1000_82572_info = {
.nvm_ops = &e82571_nvm_ops,
};
-struct e1000_info e1000_82573_info = {
+const struct e1000_info e1000_82573_info = {
.mac = e1000_82573,
.flags = FLAG_HAS_HW_VLAN_FILTER
| FLAG_HAS_WOL
| FLAG_APME_IN_CTRL3
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_SMART_POWER_DOWN
| FLAG_HAS_AMT
| FLAG_HAS_SWSM_ON_LOAD,
@@ -2073,14 +2070,13 @@ struct e1000_info e1000_82573_info = {
.nvm_ops = &e82571_nvm_ops,
};
-struct e1000_info e1000_82574_info = {
+const struct e1000_info e1000_82574_info = {
.mac = e1000_82574,
.flags = FLAG_HAS_HW_VLAN_FILTER
| FLAG_HAS_MSIX
| FLAG_HAS_JUMBO_FRAMES
| FLAG_HAS_WOL
| FLAG_APME_IN_CTRL3
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_SMART_POWER_DOWN
| FLAG_HAS_AMT
| FLAG_HAS_CTRLEXT_ON_LOAD,
@@ -2095,12 +2091,11 @@ struct e1000_info e1000_82574_info = {
.nvm_ops = &e82571_nvm_ops,
};
-struct e1000_info e1000_82583_info = {
+const struct e1000_info e1000_82583_info = {
.mac = e1000_82583,
.flags = FLAG_HAS_HW_VLAN_FILTER
| FLAG_HAS_WOL
| FLAG_APME_IN_CTRL3
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_SMART_POWER_DOWN
| FLAG_HAS_AMT
| FLAG_HAS_JUMBO_FRAMES
diff --git a/drivers/net/e1000e/Makefile b/drivers/net/ethernet/intel/e1000e/Makefile
index 28519acacd2d..948c05db5d68 100644
--- a/drivers/net/e1000e/Makefile
+++ b/drivers/net/ethernet/intel/e1000e/Makefile
@@ -32,6 +32,6 @@
obj-$(CONFIG_E1000E) += e1000e.o
-e1000e-objs := 82571.o ich8lan.o es2lan.o \
+e1000e-objs := 82571.o ich8lan.o 80003es2lan.o \
lib.o phy.o param.o ethtool.o netdev.o
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h
index c516a7440bec..c516a7440bec 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index 8533ad7f3559..9fe18d1d53d8 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -406,9 +406,9 @@ struct e1000_info {
u32 pba;
u32 max_hw_frame_size;
s32 (*get_variants)(struct e1000_adapter *);
- struct e1000_mac_operations *mac_ops;
- struct e1000_phy_operations *phy_ops;
- struct e1000_nvm_operations *nvm_ops;
+ const struct e1000_mac_operations *mac_ops;
+ const struct e1000_phy_operations *phy_ops;
+ const struct e1000_nvm_operations *nvm_ops;
};
/* hardware capability, feature, and workaround flags */
@@ -440,12 +440,11 @@ struct e1000_info {
#define FLAG_LSC_GIG_SPEED_DROP (1 << 25)
#define FLAG_SMART_POWER_DOWN (1 << 26)
#define FLAG_MSI_ENABLED (1 << 27)
-#define FLAG_RX_CSUM_ENABLED (1 << 28)
+/* reserved (1 << 28) */
#define FLAG_TSO_FORCE (1 << 29)
#define FLAG_RX_RESTART_NOW (1 << 30)
#define FLAG_MSI_TEST_FAILED (1 << 31)
-/* CRC Stripping defines */
#define FLAG2_CRC_STRIPPING (1 << 0)
#define FLAG2_HAS_PHY_WAKEUP (1 << 1)
#define FLAG2_IS_DISCARDING (1 << 2)
@@ -461,14 +460,16 @@ struct e1000_info {
#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
+#define E1000_RX_DESC_EXT(R, i) \
+ (&(((union e1000_rx_desc_extended *)((R).desc))[i]))
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
-#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
enum e1000_state_t {
__E1000_TESTING,
__E1000_RESETTING,
+ __E1000_ACCESS_SHARED_RESOURCE,
__E1000_DOWN
};
@@ -506,17 +507,17 @@ extern unsigned int copybreak;
extern char *e1000e_get_hw_dev_name(struct e1000_hw *hw);
-extern struct e1000_info e1000_82571_info;
-extern struct e1000_info e1000_82572_info;
-extern struct e1000_info e1000_82573_info;
-extern struct e1000_info e1000_82574_info;
-extern struct e1000_info e1000_82583_info;
-extern struct e1000_info e1000_ich8_info;
-extern struct e1000_info e1000_ich9_info;
-extern struct e1000_info e1000_ich10_info;
-extern struct e1000_info e1000_pch_info;
-extern struct e1000_info e1000_pch2_info;
-extern struct e1000_info e1000_es2_info;
+extern const struct e1000_info e1000_82571_info;
+extern const struct e1000_info e1000_82572_info;
+extern const struct e1000_info e1000_82573_info;
+extern const struct e1000_info e1000_82574_info;
+extern const struct e1000_info e1000_82583_info;
+extern const struct e1000_info e1000_ich8_info;
+extern const struct e1000_info e1000_ich9_info;
+extern const struct e1000_info e1000_ich10_info;
+extern const struct e1000_info e1000_pch_info;
+extern const struct e1000_info e1000_pch2_info;
+extern const struct e1000_info e1000_es2_info;
extern s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
u32 pba_num_size);
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index 6a0526a59a8a..69c9d2199140 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -367,59 +367,6 @@ out:
return retval;
}
-static u32 e1000_get_rx_csum(struct net_device *netdev)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- return adapter->flags & FLAG_RX_CSUM_ENABLED;
-}
-
-static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
-
- if (data)
- adapter->flags |= FLAG_RX_CSUM_ENABLED;
- else
- adapter->flags &= ~FLAG_RX_CSUM_ENABLED;
-
- if (netif_running(netdev))
- e1000e_reinit_locked(adapter);
- else
- e1000e_reset(adapter);
- return 0;
-}
-
-static u32 e1000_get_tx_csum(struct net_device *netdev)
-{
- return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
-{
- if (data)
- netdev->features |= NETIF_F_HW_CSUM;
- else
- netdev->features &= ~NETIF_F_HW_CSUM;
-
- return 0;
-}
-
-static int e1000_set_tso(struct net_device *netdev, u32 data)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
-
- if (data) {
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
- } else {
- netdev->features &= ~NETIF_F_TSO;
- netdev->features &= ~NETIF_F_TSO6;
- }
-
- adapter->flags |= FLAG_TSO_FORCE;
- return 0;
-}
-
static u32 e1000_get_msglevel(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -665,12 +612,8 @@ static void e1000_get_ringparam(struct net_device *netdev,
ring->rx_max_pending = E1000_MAX_RXD;
ring->tx_max_pending = E1000_MAX_TXD;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = rx_ring->count;
ring->tx_pending = tx_ring->count;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
static int e1000_set_ringparam(struct net_device *netdev,
@@ -1195,7 +1138,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
goto err_nomem;
}
- rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc);
+ rx_ring->size = rx_ring->count * sizeof(union e1000_rx_desc_extended);
rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
&rx_ring->dma, GFP_KERNEL);
if (!rx_ring->desc) {
@@ -1221,7 +1164,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
ew32(RCTL, rctl);
for (i = 0; i < rx_ring->count; i++) {
- struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i);
+ union e1000_rx_desc_extended *rx_desc;
struct sk_buff *skb;
skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL);
@@ -1239,8 +1182,9 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
ret_val = 8;
goto err_nomem;
}
- rx_desc->buffer_addr =
- cpu_to_le64(rx_ring->buffer_info[i].dma);
+ rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+ rx_desc->read.buffer_addr =
+ cpu_to_le64(rx_ring->buffer_info[i].dma);
memset(skb->data, 0x00, skb->len);
}
@@ -2013,31 +1957,6 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset,
}
}
-static int e1000e_set_flags(struct net_device *netdev, u32 data)
-{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- bool need_reset = false;
- int rc;
-
- need_reset = (data & ETH_FLAG_RXVLAN) !=
- (netdev->features & NETIF_F_HW_VLAN_RX);
-
- rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_RXVLAN |
- ETH_FLAG_TXVLAN);
-
- if (rc)
- return rc;
-
- if (need_reset) {
- if (netif_running(netdev))
- e1000e_reinit_locked(adapter);
- else
- e1000e_reset(adapter);
- }
-
- return 0;
-}
-
static const struct ethtool_ops e1000_ethtool_ops = {
.get_settings = e1000_get_settings,
.set_settings = e1000_set_settings,
@@ -2057,14 +1976,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.set_ringparam = e1000_set_ringparam,
.get_pauseparam = e1000_get_pauseparam,
.set_pauseparam = e1000_set_pauseparam,
- .get_rx_csum = e1000_get_rx_csum,
- .set_rx_csum = e1000_set_rx_csum,
- .get_tx_csum = e1000_get_tx_csum,
- .set_tx_csum = e1000_set_tx_csum,
- .get_sg = ethtool_op_get_sg,
- .set_sg = ethtool_op_set_sg,
- .get_tso = ethtool_op_get_tso,
- .set_tso = e1000_set_tso,
.self_test = e1000_diag_test,
.get_strings = e1000_get_strings,
.set_phys_id = e1000_set_phys_id,
@@ -2072,8 +1983,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.get_sset_count = e1000e_get_sset_count,
.get_coalesce = e1000_get_coalesce,
.set_coalesce = e1000_set_coalesce,
- .get_flags = ethtool_op_get_flags,
- .set_flags = e1000e_set_flags,
};
void e1000e_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index 29670397079b..29670397079b 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 54add27c8f76..6a17c62cb86f 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -811,7 +811,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
}
if ((adapter->hw.mac.type == e1000_ich8lan) &&
- (adapter->hw.phy.type == e1000_phy_igp_3))
+ (adapter->hw.phy.type != e1000_phy_ife))
adapter->flags |= FLAG_LSC_GIG_SPEED_DROP;
/* Enable workaround for 82579 w/ ME enabled */
@@ -852,8 +852,6 @@ static void e1000_release_nvm_ich8lan(struct e1000_hw *hw)
mutex_unlock(&nvm_mutex);
}
-static DEFINE_MUTEX(swflag_mutex);
-
/**
* e1000_acquire_swflag_ich8lan - Acquire software control flag
* @hw: pointer to the HW structure
@@ -866,7 +864,12 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT;
s32 ret_val = 0;
- mutex_lock(&swflag_mutex);
+ if (test_and_set_bit(__E1000_ACCESS_SHARED_RESOURCE,
+ &hw->adapter->state)) {
+ WARN(1, "e1000e: %s: contention for Phy access\n",
+ hw->adapter->netdev->name);
+ return -E1000_ERR_PHY;
+ }
while (timeout) {
extcnf_ctrl = er32(EXTCNF_CTRL);
@@ -878,7 +881,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
}
if (!timeout) {
- e_dbg("SW/FW/HW has locked the resource for too long.\n");
+ e_dbg("SW has already locked the resource.\n");
ret_val = -E1000_ERR_CONFIG;
goto out;
}
@@ -898,7 +901,9 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
}
if (!timeout) {
- e_dbg("Failed to acquire the semaphore.\n");
+ e_dbg("Failed to acquire the semaphore, FW or HW has it: "
+ "FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n",
+ er32(FWSM), extcnf_ctrl);
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
ret_val = -E1000_ERR_CONFIG;
@@ -907,7 +912,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
out:
if (ret_val)
- mutex_unlock(&swflag_mutex);
+ clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state);
return ret_val;
}
@@ -932,7 +937,7 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
e_dbg("Semaphore unexpectedly released by sw/fw/hw\n");
}
- mutex_unlock(&swflag_mutex);
+ clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state);
}
/**
@@ -1319,16 +1324,20 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
oem_reg |= HV_OEM_BITS_LPLU;
+
+ /* Set Restart auto-neg to activate the bits */
+ if (!e1000_check_reset_block(hw))
+ oem_reg |= HV_OEM_BITS_RESTART_AN;
} else {
- if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE)
+ if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE |
+ E1000_PHY_CTRL_NOND0A_GBE_DISABLE))
oem_reg |= HV_OEM_BITS_GBE_DIS;
- if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU)
+ if (mac_reg & (E1000_PHY_CTRL_D0A_LPLU |
+ E1000_PHY_CTRL_NOND0A_LPLU))
oem_reg |= HV_OEM_BITS_LPLU;
}
- /* Restart auto-neg to activate the bits */
- if (!e1000_check_reset_block(hw))
- oem_reg |= HV_OEM_BITS_RESTART_AN;
+
ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg);
out:
@@ -1574,7 +1583,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
if (ret_val)
goto out;
- ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xFE00);
+ ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xF100);
if (ret_val)
goto out;
e1e_rphy(hw, HV_PM_CTRL, &data);
@@ -3135,7 +3144,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
msleep(20);
if (!ret_val)
- mutex_unlock(&swflag_mutex);
+ clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state);
if (ctrl & E1000_CTRL_PHY_RST) {
ret_val = hw->phy.ops.get_cfg_done(hw);
@@ -3638,15 +3647,14 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
* LPLU, Gig disable, MDIC PHY reset):
* 1) Set Kumeran Near-end loopback
* 2) Clear Kumeran Near-end loopback
- * Should only be called for ICH8[m] devices with IGP_3 Phy.
+ * Should only be called for ICH8[m] devices with any 1G Phy.
**/
void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
{
s32 ret_val;
u16 reg_data;
- if ((hw->mac.type != e1000_ich8lan) ||
- (hw->phy.type != e1000_phy_igp_3))
+ if ((hw->mac.type != e1000_ich8lan) || (hw->phy.type == e1000_phy_ife))
return;
ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
@@ -3682,8 +3690,12 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE;
ew32(PHY_CTRL, phy_ctrl);
+ if (hw->mac.type == e1000_ich8lan)
+ e1000e_gig_downshift_workaround_ich8lan(hw);
+
if (hw->mac.type >= e1000_pchlan) {
e1000_oem_bits_config_ich8lan(hw, false);
+ e1000_phy_hw_reset_ich8lan(hw);
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return;
@@ -4011,7 +4023,7 @@ release:
}
}
-static struct e1000_mac_operations ich8_mac_ops = {
+static const struct e1000_mac_operations ich8_mac_ops = {
.id_led_init = e1000e_id_led_init,
/* check_mng_mode dependent on mac type */
.check_for_link = e1000_check_for_copper_link_ich8lan,
@@ -4030,7 +4042,7 @@ static struct e1000_mac_operations ich8_mac_ops = {
/* id_led_init dependent on mac type */
};
-static struct e1000_phy_operations ich8_phy_ops = {
+static const struct e1000_phy_operations ich8_phy_ops = {
.acquire = e1000_acquire_swflag_ich8lan,
.check_reset_block = e1000_check_reset_block_ich8lan,
.commit = NULL,
@@ -4044,7 +4056,7 @@ static struct e1000_phy_operations ich8_phy_ops = {
.write_reg = e1000e_write_phy_reg_igp,
};
-static struct e1000_nvm_operations ich8_nvm_ops = {
+static const struct e1000_nvm_operations ich8_nvm_ops = {
.acquire = e1000_acquire_nvm_ich8lan,
.read = e1000_read_nvm_ich8lan,
.release = e1000_release_nvm_ich8lan,
@@ -4054,11 +4066,10 @@ static struct e1000_nvm_operations ich8_nvm_ops = {
.write = e1000_write_nvm_ich8lan,
};
-struct e1000_info e1000_ich8_info = {
+const struct e1000_info e1000_ich8_info = {
.mac = e1000_ich8lan,
.flags = FLAG_HAS_WOL
| FLAG_IS_ICH
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_AMT
| FLAG_HAS_FLASH
@@ -4071,12 +4082,11 @@ struct e1000_info e1000_ich8_info = {
.nvm_ops = &ich8_nvm_ops,
};
-struct e1000_info e1000_ich9_info = {
+const struct e1000_info e1000_ich9_info = {
.mac = e1000_ich9lan,
.flags = FLAG_HAS_JUMBO_FRAMES
| FLAG_IS_ICH
| FLAG_HAS_WOL
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_AMT
| FLAG_HAS_ERT
@@ -4090,12 +4100,11 @@ struct e1000_info e1000_ich9_info = {
.nvm_ops = &ich8_nvm_ops,
};
-struct e1000_info e1000_ich10_info = {
+const struct e1000_info e1000_ich10_info = {
.mac = e1000_ich10lan,
.flags = FLAG_HAS_JUMBO_FRAMES
| FLAG_IS_ICH
| FLAG_HAS_WOL
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_AMT
| FLAG_HAS_ERT
@@ -4109,11 +4118,10 @@ struct e1000_info e1000_ich10_info = {
.nvm_ops = &ich8_nvm_ops,
};
-struct e1000_info e1000_pch_info = {
+const struct e1000_info e1000_pch_info = {
.mac = e1000_pchlan,
.flags = FLAG_IS_ICH
| FLAG_HAS_WOL
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_AMT
| FLAG_HAS_FLASH
@@ -4129,11 +4137,10 @@ struct e1000_info e1000_pch_info = {
.nvm_ops = &ich8_nvm_ops,
};
-struct e1000_info e1000_pch2_info = {
+const struct e1000_info e1000_pch2_info = {
.mac = e1000_pch2lan,
.flags = FLAG_IS_ICH
| FLAG_HAS_WOL
- | FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_AMT
| FLAG_HAS_FLASH
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/ethernet/intel/e1000e/lib.c
index 0893ab107adf..0893ab107adf 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/ethernet/intel/e1000e/lib.c
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 2198e615f241..a855db1ad249 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -47,7 +47,7 @@
#include <linux/if_vlan.h>
#include <linux/cpu.h>
#include <linux/smp.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
#include <linux/pm_runtime.h>
#include <linux/aer.h>
#include <linux/prefetch.h>
@@ -56,7 +56,7 @@
#define DRV_EXTRAVERSION "-k"
-#define DRV_VERSION "1.4.4" DRV_EXTRAVERSION
+#define DRV_VERSION "1.5.1" DRV_EXTRAVERSION
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
@@ -192,7 +192,7 @@ static void e1000e_dump(struct e1000_adapter *adapter)
struct e1000_buffer *buffer_info;
struct e1000_ring *rx_ring = adapter->rx_ring;
union e1000_rx_desc_packet_split *rx_desc_ps;
- struct e1000_rx_desc *rx_desc;
+ union e1000_rx_desc_extended *rx_desc;
struct my_u1 {
u64 a;
u64 b;
@@ -399,41 +399,70 @@ rx_ring_summary:
break;
default:
case 0:
- /* Legacy Receive Descriptor Format
+ /* Extended Receive Descriptor (Read) Format
*
- * +-----------------------------------------------------+
- * | Buffer Address [63:0] |
- * +-----------------------------------------------------+
- * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
- * +-----------------------------------------------------+
- * 63 48 47 40 39 32 31 16 15 0
+ * +-----------------------------------------------------+
+ * 0 | Buffer Address [63:0] |
+ * +-----------------------------------------------------+
+ * 8 | Reserved |
+ * +-----------------------------------------------------+
*/
- printk(KERN_INFO "Rl[desc] [address 63:0 ] "
- "[vl er S cks ln] [bi->dma ] [bi->skb] "
- "<-- Legacy format\n");
- for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
- rx_desc = E1000_RX_DESC(*rx_ring, i);
+ printk(KERN_INFO "R [desc] [buf addr 63:0 ] "
+ "[reserved 63:0 ] [bi->dma ] "
+ "[bi->skb] <-- Ext (Read) format\n");
+ /* Extended Receive Descriptor (Write-Back) Format
+ *
+ * 63 48 47 32 31 24 23 4 3 0
+ * +------------------------------------------------------+
+ * | RSS Hash | | | |
+ * 0 +-------------------+ Rsvd | Reserved | MRQ RSS |
+ * | Packet | IP | | | Type |
+ * | Checksum | Ident | | | |
+ * +------------------------------------------------------+
+ * 8 | VLAN Tag | Length | Extended Error | Extended Status |
+ * +------------------------------------------------------+
+ * 63 48 47 32 31 20 19 0
+ */
+ printk(KERN_INFO "RWB[desc] [cs ipid mrq] "
+ "[vt ln xe xs] "
+ "[bi->skb] <-- Ext (Write-Back) format\n");
+
+ for (i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
- u0 = (struct my_u0 *)rx_desc;
- printk(KERN_INFO "Rl[0x%03X] %016llX %016llX "
- "%016llX %p", i,
- (unsigned long long)le64_to_cpu(u0->a),
- (unsigned long long)le64_to_cpu(u0->b),
- (unsigned long long)buffer_info->dma,
- buffer_info->skb);
+ rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+ u1 = (struct my_u1 *)rx_desc;
+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+ if (staterr & E1000_RXD_STAT_DD) {
+ /* Descriptor Done */
+ printk(KERN_INFO "RWB[0x%03X] %016llX "
+ "%016llX ---------------- %p", i,
+ (unsigned long long)le64_to_cpu(u1->a),
+ (unsigned long long)le64_to_cpu(u1->b),
+ buffer_info->skb);
+ } else {
+ printk(KERN_INFO "R [0x%03X] %016llX "
+ "%016llX %016llX %p", i,
+ (unsigned long long)le64_to_cpu(u1->a),
+ (unsigned long long)le64_to_cpu(u1->b),
+ (unsigned long long)buffer_info->dma,
+ buffer_info->skb);
+
+ if (netif_msg_pktdata(adapter))
+ print_hex_dump(KERN_INFO, "",
+ DUMP_PREFIX_ADDRESS, 16,
+ 1,
+ phys_to_virt
+ (buffer_info->dma),
+ adapter->rx_buffer_len,
+ true);
+ }
+
if (i == rx_ring->next_to_use)
printk(KERN_CONT " NTU\n");
else if (i == rx_ring->next_to_clean)
printk(KERN_CONT " NTC\n");
else
printk(KERN_CONT "\n");
-
- if (netif_msg_pktdata(adapter))
- print_hex_dump(KERN_INFO, "",
- DUMP_PREFIX_ADDRESS,
- 16, 1,
- phys_to_virt(buffer_info->dma),
- adapter->rx_buffer_len, true);
}
}
@@ -576,7 +605,7 @@ static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i)
}
/**
- * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
+ * e1000_alloc_rx_buffers - Replace used receive buffers
* @adapter: address of board private structure
**/
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
@@ -585,7 +614,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_ring *rx_ring = adapter->rx_ring;
- struct e1000_rx_desc *rx_desc;
+ union e1000_rx_desc_extended *rx_desc;
struct e1000_buffer *buffer_info;
struct sk_buff *skb;
unsigned int i;
@@ -619,8 +648,8 @@ map_skb:
break;
}
- rx_desc = E1000_RX_DESC(*rx_ring, i);
- rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+ rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+ rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) {
/*
@@ -761,7 +790,7 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_rx_desc *rx_desc;
+ union e1000_rx_desc_extended *rx_desc;
struct e1000_ring *rx_ring = adapter->rx_ring;
struct e1000_buffer *buffer_info;
struct sk_buff *skb;
@@ -802,8 +831,8 @@ check_page:
PAGE_SIZE,
DMA_FROM_DEVICE);
- rx_desc = E1000_RX_DESC(*rx_ring, i);
- rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+ rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+ rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
if (unlikely(++i == rx_ring->count))
i = 0;
@@ -841,28 +870,27 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
struct pci_dev *pdev = adapter->pdev;
struct e1000_hw *hw = &adapter->hw;
struct e1000_ring *rx_ring = adapter->rx_ring;
- struct e1000_rx_desc *rx_desc, *next_rxd;
+ union e1000_rx_desc_extended *rx_desc, *next_rxd;
struct e1000_buffer *buffer_info, *next_buffer;
- u32 length;
+ u32 length, staterr;
unsigned int i;
int cleaned_count = 0;
bool cleaned = 0;
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
i = rx_ring->next_to_clean;
- rx_desc = E1000_RX_DESC(*rx_ring, i);
+ rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
buffer_info = &rx_ring->buffer_info[i];
- while (rx_desc->status & E1000_RXD_STAT_DD) {
+ while (staterr & E1000_RXD_STAT_DD) {
struct sk_buff *skb;
- u8 status;
if (*work_done >= work_to_do)
break;
(*work_done)++;
rmb(); /* read descriptor and rx_buffer_info after status DD */
- status = rx_desc->status;
skb = buffer_info->skb;
buffer_info->skb = NULL;
@@ -871,7 +899,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
i++;
if (i == rx_ring->count)
i = 0;
- next_rxd = E1000_RX_DESC(*rx_ring, i);
+ next_rxd = E1000_RX_DESC_EXT(*rx_ring, i);
prefetch(next_rxd);
next_buffer = &rx_ring->buffer_info[i];
@@ -884,7 +912,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
DMA_FROM_DEVICE);
buffer_info->dma = 0;
- length = le16_to_cpu(rx_desc->length);
+ length = le16_to_cpu(rx_desc->wb.upper.length);
/*
* !EOP means multiple descriptors were used to store a single
@@ -893,7 +921,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
* next frame that _does_ have the EOP bit set, as it is by
* definition only a frame fragment
*/
- if (unlikely(!(status & E1000_RXD_STAT_EOP)))
+ if (unlikely(!(staterr & E1000_RXD_STAT_EOP)))
adapter->flags2 |= FLAG2_IS_DISCARDING;
if (adapter->flags2 & FLAG2_IS_DISCARDING) {
@@ -901,12 +929,12 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
e_dbg("Receive packet consumed multiple buffers\n");
/* recycle */
buffer_info->skb = skb;
- if (status & E1000_RXD_STAT_EOP)
+ if (staterr & E1000_RXD_STAT_EOP)
adapter->flags2 &= ~FLAG2_IS_DISCARDING;
goto next_desc;
}
- if (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
+ if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
/* recycle */
buffer_info->skb = skb;
goto next_desc;
@@ -944,15 +972,15 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
skb_put(skb, length);
/* Receive Checksum Offload */
- e1000_rx_checksum(adapter,
- (u32)(status) |
- ((u32)(rx_desc->errors) << 24),
- le16_to_cpu(rx_desc->csum), skb);
+ e1000_rx_checksum(adapter, staterr,
+ le16_to_cpu(rx_desc->wb.lower.hi_dword.
+ csum_ip.csum), skb);
- e1000_receive_skb(adapter, netdev, skb,status,rx_desc->special);
+ e1000_receive_skb(adapter, netdev, skb, staterr,
+ rx_desc->wb.upper.vlan);
next_desc:
- rx_desc->status = 0;
+ rx_desc->wb.upper.status_error &= cpu_to_le32(~0xFF);
/* return some buffers to hardware, one at a time is too slow */
if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
@@ -964,6 +992,8 @@ next_desc:
/* use prefetched values */
rx_desc = next_rxd;
buffer_info = next_buffer;
+
+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
}
rx_ring->next_to_clean = i;
@@ -1270,7 +1300,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
ps_page->page = NULL;
skb->len += length;
skb->data_len += length;
- skb->truesize += length;
+ skb->truesize += PAGE_SIZE;
}
/* strip the ethernet crc, problem is we're using pages now so
@@ -1330,7 +1360,7 @@ static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
bi->page = NULL;
skb->len += length;
skb->data_len += length;
- skb->truesize += length;
+ skb->truesize += PAGE_SIZE;
}
/**
@@ -1347,35 +1377,34 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_ring *rx_ring = adapter->rx_ring;
- struct e1000_rx_desc *rx_desc, *next_rxd;
+ union e1000_rx_desc_extended *rx_desc, *next_rxd;
struct e1000_buffer *buffer_info, *next_buffer;
- u32 length;
+ u32 length, staterr;
unsigned int i;
int cleaned_count = 0;
bool cleaned = false;
unsigned int total_rx_bytes=0, total_rx_packets=0;
i = rx_ring->next_to_clean;
- rx_desc = E1000_RX_DESC(*rx_ring, i);
+ rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
buffer_info = &rx_ring->buffer_info[i];
- while (rx_desc->status & E1000_RXD_STAT_DD) {
+ while (staterr & E1000_RXD_STAT_DD) {
struct sk_buff *skb;
- u8 status;
if (*work_done >= work_to_do)
break;
(*work_done)++;
rmb(); /* read descriptor and rx_buffer_info after status DD */
- status = rx_desc->status;
skb = buffer_info->skb;
buffer_info->skb = NULL;
++i;
if (i == rx_ring->count)
i = 0;
- next_rxd = E1000_RX_DESC(*rx_ring, i);
+ next_rxd = E1000_RX_DESC_EXT(*rx_ring, i);
prefetch(next_rxd);
next_buffer = &rx_ring->buffer_info[i];
@@ -1386,23 +1415,22 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
DMA_FROM_DEVICE);
buffer_info->dma = 0;
- length = le16_to_cpu(rx_desc->length);
+ length = le16_to_cpu(rx_desc->wb.upper.length);
/* errors is only valid for DD + EOP descriptors */
- if (unlikely((status & E1000_RXD_STAT_EOP) &&
- (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
- /* recycle both page and skb */
- buffer_info->skb = skb;
- /* an error means any chain goes out the window
- * too */
- if (rx_ring->rx_skb_top)
- dev_kfree_skb_irq(rx_ring->rx_skb_top);
- rx_ring->rx_skb_top = NULL;
- goto next_desc;
+ if (unlikely((staterr & E1000_RXD_STAT_EOP) &&
+ (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK))) {
+ /* recycle both page and skb */
+ buffer_info->skb = skb;
+ /* an error means any chain goes out the window too */
+ if (rx_ring->rx_skb_top)
+ dev_kfree_skb_irq(rx_ring->rx_skb_top);
+ rx_ring->rx_skb_top = NULL;
+ goto next_desc;
}
#define rxtop (rx_ring->rx_skb_top)
- if (!(status & E1000_RXD_STAT_EOP)) {
+ if (!(staterr & E1000_RXD_STAT_EOP)) {
/* this descriptor is only the beginning (or middle) */
if (!rxtop) {
/* this is the beginning of a chain */
@@ -1457,10 +1485,9 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
}
/* Receive Checksum Offload XXX recompute due to CRC strip? */
- e1000_rx_checksum(adapter,
- (u32)(status) |
- ((u32)(rx_desc->errors) << 24),
- le16_to_cpu(rx_desc->csum), skb);
+ e1000_rx_checksum(adapter, staterr,
+ le16_to_cpu(rx_desc->wb.lower.hi_dword.
+ csum_ip.csum), skb);
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
@@ -1473,11 +1500,11 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
goto next_desc;
}
- e1000_receive_skb(adapter, netdev, skb, status,
- rx_desc->special);
+ e1000_receive_skb(adapter, netdev, skb, staterr,
+ rx_desc->wb.upper.vlan);
next_desc:
- rx_desc->status = 0;
+ rx_desc->wb.upper.status_error &= cpu_to_le32(~0xFF);
/* return some buffers to hardware, one at a time is too slow */
if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
@@ -1489,6 +1516,8 @@ next_desc:
/* use prefetched values */
rx_desc = next_rxd;
buffer_info = next_buffer;
+
+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
}
rx_ring->next_to_clean = i;
@@ -2887,6 +2916,10 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
break;
}
+ /* Enable Extended Status in all Receive Descriptors */
+ rfctl = er32(RFCTL);
+ rfctl |= E1000_RFCTL_EXTEN;
+
/*
* 82571 and greater support packet-split where the protocol
* header is placed in skb->data and the packet data is
@@ -2912,9 +2945,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
if (adapter->rx_ps_pages) {
u32 psrctl = 0;
- /* Configure extra packet-split registers */
- rfctl = er32(RFCTL);
- rfctl |= E1000_RFCTL_EXTEN;
/*
* disable packet split support for IPv6 extension headers,
* because some malformed IPv6 headers can hang the Rx
@@ -2922,8 +2952,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
E1000_RFCTL_NEW_IPV6_EXT_DIS);
- ew32(RFCTL, rfctl);
-
/* Enable Packet split descriptors */
rctl |= E1000_RCTL_DTYP_PS;
@@ -2946,6 +2974,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
ew32(PSRCTL, psrctl);
}
+ ew32(RFCTL, rfctl);
ew32(RCTL, rctl);
/* just started the receive unit, no need to restart */
adapter->flags &= ~FLAG_RX_RESTART_NOW;
@@ -2971,11 +3000,11 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
adapter->clean_rx = e1000_clean_rx_irq_ps;
adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
} else if (adapter->netdev->mtu > ETH_FRAME_LEN + ETH_FCS_LEN) {
- rdlen = rx_ring->count * sizeof(struct e1000_rx_desc);
+ rdlen = rx_ring->count * sizeof(union e1000_rx_desc_extended);
adapter->clean_rx = e1000_clean_jumbo_rx_irq;
adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers;
} else {
- rdlen = rx_ring->count * sizeof(struct e1000_rx_desc);
+ rdlen = rx_ring->count * sizeof(union e1000_rx_desc_extended);
adapter->clean_rx = e1000_clean_rx_irq;
adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
}
@@ -3040,7 +3069,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
/* Enable Receive Checksum Offload for TCP and UDP */
rxcsum = er32(RXCSUM);
- if (adapter->flags & FLAG_RX_CSUM_ENABLED) {
+ if (adapter->netdev->features & NETIF_F_RXCSUM) {
rxcsum |= E1000_RXCSUM_TUOFL;
/*
@@ -4644,11 +4673,11 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
}
for (f = 0; f < nr_frags; f++) {
- struct skb_frag_struct *frag;
+ const struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[f];
- len = frag->size;
- offset = frag->page_offset;
+ len = skb_frag_size(frag);
+ offset = 0;
while (len) {
i++;
@@ -4661,9 +4690,8 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
buffer_info->length = size;
buffer_info->time_stamp = jiffies;
buffer_info->next_to_watch = i;
- buffer_info->dma = dma_map_page(&pdev->dev, frag->page,
- offset, size,
- DMA_TO_DEVICE);
+ buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag,
+ offset, size, DMA_TO_DEVICE);
buffer_info->mapped_as_page = true;
if (dma_mapping_error(&pdev->dev, buffer_info->dma))
goto dma_error;
@@ -4915,7 +4943,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
nr_frags = skb_shinfo(skb)->nr_frags;
for (f = 0; f < nr_frags; f++)
- count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
+ count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]),
max_txd_pwr);
if (adapter->hw.mac.tx_pkt_filtering)
@@ -5831,12 +5859,32 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
}
}
+static int e1000_set_features(struct net_device *netdev, u32 features)
+{
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ u32 changed = features ^ netdev->features;
+
+ if (changed & (NETIF_F_TSO | NETIF_F_TSO6))
+ adapter->flags |= FLAG_TSO_FORCE;
+
+ if (!(changed & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX |
+ NETIF_F_RXCSUM)))
+ return 0;
+
+ if (netif_running(netdev))
+ e1000e_reinit_locked(adapter);
+ else
+ e1000e_reset(adapter);
+
+ return 0;
+}
+
static const struct net_device_ops e1000e_netdev_ops = {
.ndo_open = e1000_open,
.ndo_stop = e1000_close,
.ndo_start_xmit = e1000_xmit_frame,
.ndo_get_stats64 = e1000e_get_stats64,
- .ndo_set_multicast_list = e1000_set_multi,
+ .ndo_set_rx_mode = e1000_set_multi,
.ndo_set_mac_address = e1000_set_mac,
.ndo_change_mtu = e1000_change_mtu,
.ndo_do_ioctl = e1000_ioctl,
@@ -5848,6 +5896,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = e1000_netpoll,
#endif
+ .ndo_set_features = e1000_set_features,
};
/**
@@ -6007,21 +6056,25 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (e1000_check_reset_block(&adapter->hw))
e_info("PHY reset is blocked due to SOL/IDER session.\n");
- netdev->features = NETIF_F_SG |
- NETIF_F_HW_CSUM |
- NETIF_F_HW_VLAN_TX |
- NETIF_F_HW_VLAN_RX;
+ /* Set initial default active device features */
+ netdev->features = (NETIF_F_SG |
+ NETIF_F_HW_VLAN_RX |
+ NETIF_F_HW_VLAN_TX |
+ NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_RXCSUM |
+ NETIF_F_HW_CSUM);
+
+ /* Set user-changeable features (subset of all device features) */
+ netdev->hw_features = netdev->features;
if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER)
netdev->features |= NETIF_F_HW_VLAN_FILTER;
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
-
- netdev->vlan_features |= NETIF_F_TSO;
- netdev->vlan_features |= NETIF_F_TSO6;
- netdev->vlan_features |= NETIF_F_HW_CSUM;
- netdev->vlan_features |= NETIF_F_SG;
+ netdev->vlan_features |= (NETIF_F_SG |
+ NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_HW_CSUM);
if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c
index 4dd9b63273f6..4dd9b63273f6 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/ethernet/intel/e1000e/param.c
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
index 8666476cb9be..8666476cb9be 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/ethernet/intel/e1000e/phy.c
diff --git a/drivers/net/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile
index c6e4621b6262..c6e4621b6262 100644
--- a/drivers/net/igb/Makefile
+++ b/drivers/net/ethernet/intel/igb/Makefile
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index c0857bdfb03a..7881fb95a25b 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -66,10 +66,6 @@ static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw);
static s32 igb_reset_mdicnfg_82580(struct e1000_hw *hw);
static s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw);
static s32 igb_update_nvm_checksum_82580(struct e1000_hw *hw);
-static s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw,
- u16 offset);
-static s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
- u16 offset);
static s32 igb_validate_nvm_checksum_i350(struct e1000_hw *hw);
static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw);
static const u16 e1000_82580_rxpbs_table[] =
@@ -1055,7 +1051,10 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw)
/* Disabling VLAN filtering */
hw_dbg("Initializing the IEEE VLAN\n");
- igb_clear_vfta(hw);
+ if (hw->mac.type == e1000_i350)
+ igb_clear_vfta_i350(hw);
+ else
+ igb_clear_vfta(hw);
/* Setup the receive address */
igb_init_rx_addrs(hw, rar_count);
@@ -1584,14 +1583,31 @@ void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
**/
void igb_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
{
- u32 dtxswc = rd32(E1000_DTXSWC);
+ u32 dtxswc;
+
+ switch (hw->mac.type) {
+ case e1000_82576:
+ dtxswc = rd32(E1000_DTXSWC);
+ if (enable)
+ dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+ else
+ dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+ wr32(E1000_DTXSWC, dtxswc);
+ break;
+ case e1000_i350:
+ dtxswc = rd32(E1000_TXSWC);
+ if (enable)
+ dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+ else
+ dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+ wr32(E1000_TXSWC, dtxswc);
+ break;
+ default:
+ /* Currently no other hardware supports loopback */
+ break;
+ }
- if (enable)
- dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
- else
- dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
- wr32(E1000_DTXSWC, dtxswc);
}
/**
@@ -1820,7 +1836,8 @@ u16 igb_rxpbs_adjust_82580(u32 data)
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
**/
-s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+static s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
+ u16 offset)
{
s32 ret_val = 0;
u16 checksum = 0;
@@ -1855,7 +1872,7 @@ out:
* up to the checksum. Then calculates the EEPROM checksum and writes the
* value to the EEPROM.
**/
-s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+static s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
{
s32 ret_val;
u16 checksum = 0;
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h
index 786e110011a3..08a757eb6608 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.h
@@ -130,7 +130,9 @@ union e1000_adv_tx_desc {
#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
+#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index 7b8ddd830f19..f5fc5725ea94 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -85,6 +85,7 @@
#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
#define E1000_RXD_STAT_TS 0x10000 /* Pkt was time stamped */
+#define E1000_RXDEXT_STATERR_LB 0x00040000
#define E1000_RXDEXT_STATERR_CE 0x01000000
#define E1000_RXDEXT_STATERR_SE 0x02000000
#define E1000_RXDEXT_STATERR_SEQ 0x04000000
@@ -409,6 +410,9 @@
#define E1000_ICS_DRSTA E1000_ICR_DRSTA /* Device Reset Aserted */
/* Extended Interrupt Cause Set */
+/* E1000_EITR_CNT_IGNR is only for 82576 and newer */
+#define E1000_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */
+
/* Transmit Descriptor Control */
/* Enable the counting of descriptors still to be processed. */
diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h
index 4519a1367170..4519a1367170 100644
--- a/drivers/net/igb/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c
index 2b5ef761d2ab..73aac082c44d 100644
--- a/drivers/net/igb/e1000_mac.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.c
@@ -117,6 +117,50 @@ static void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
wrfl();
}
+/* Due to a hw errata, if the host tries to configure the VFTA register
+ * while performing queries from the BMC or DMA, then the VFTA in some
+ * cases won't be written.
+ */
+
+/**
+ * igb_clear_vfta_i350 - Clear VLAN filter table
+ * @hw: pointer to the HW structure
+ *
+ * Clears the register array which contains the VLAN filter table by
+ * setting all the values to 0.
+ **/
+void igb_clear_vfta_i350(struct e1000_hw *hw)
+{
+ u32 offset;
+ int i;
+
+ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+ for (i = 0; i < 10; i++)
+ array_wr32(E1000_VFTA, offset, 0);
+
+ wrfl();
+ }
+}
+
+/**
+ * igb_write_vfta_i350 - Write value to VLAN filter table
+ * @hw: pointer to the HW structure
+ * @offset: register offset in VLAN filter table
+ * @value: register value written to VLAN filter table
+ *
+ * Writes value at the given offset in the register array which stores
+ * the VLAN filter table.
+ **/
+void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
+{
+ int i;
+
+ for (i = 0; i < 10; i++)
+ array_wr32(E1000_VFTA, offset, value);
+
+ wrfl();
+}
+
/**
* igb_init_rx_addrs - Initialize receive address's
* @hw: pointer to the HW structure
@@ -155,9 +199,12 @@ s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add)
{
u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK;
u32 mask = 1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
- u32 vfta = array_rd32(E1000_VFTA, index);
+ u32 vfta;
+ struct igb_adapter *adapter = hw->back;
s32 ret_val = 0;
+ vfta = adapter->shadow_vfta[index];
+
/* bit was set/cleared before we started */
if ((!!(vfta & mask)) == add) {
ret_val = -E1000_ERR_CONFIG;
@@ -167,8 +214,11 @@ s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add)
else
vfta &= ~mask;
}
-
- igb_write_vfta(hw, index, vfta);
+ if (hw->mac.type == e1000_i350)
+ igb_write_vfta_i350(hw, index, vfta);
+ else
+ igb_write_vfta(hw, index, vfta);
+ adapter->shadow_vfta[index] = vfta;
return ret_val;
}
@@ -191,6 +241,13 @@ s32 igb_check_alt_mac_addr(struct e1000_hw *hw)
u16 offset, nvm_alt_mac_addr_offset, nvm_data;
u8 alt_mac_addr[ETH_ALEN];
+ /*
+ * Alternate MAC address is handled by the option ROM for 82580
+ * and newer. SW support not required.
+ */
+ if (hw->mac.type >= e1000_82580)
+ goto out;
+
ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1,
&nvm_alt_mac_addr_offset);
if (ret_val) {
@@ -198,13 +255,18 @@ s32 igb_check_alt_mac_addr(struct e1000_hw *hw)
goto out;
}
- if (nvm_alt_mac_addr_offset == 0xFFFF) {
+ if ((nvm_alt_mac_addr_offset == 0xFFFF) ||
+ (nvm_alt_mac_addr_offset == 0x0000))
/* There is no Alternate MAC Address */
goto out;
- }
if (hw->bus.func == E1000_FUNC_1)
nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
+ if (hw->bus.func == E1000_FUNC_2)
+ nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN2;
+
+ if (hw->bus.func == E1000_FUNC_3)
+ nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN3;
for (i = 0; i < ETH_ALEN; i += 2) {
offset = nvm_alt_mac_addr_offset + (i >> 1);
ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h
index 4927f61fbbc8..e45996b4ea34 100644
--- a/drivers/net/igb/e1000_mac.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.h
@@ -60,6 +60,7 @@ s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg,
void igb_clear_hw_cntrs_base(struct e1000_hw *hw);
void igb_clear_vfta(struct e1000_hw *hw);
+void igb_clear_vfta_i350(struct e1000_hw *hw);
s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add);
void igb_config_collision_dist(struct e1000_hw *hw);
void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
diff --git a/drivers/net/igb/e1000_mbx.c b/drivers/net/ethernet/intel/igb/e1000_mbx.c
index 74f2f11ac290..469d95eaa154 100644
--- a/drivers/net/igb/e1000_mbx.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mbx.c
@@ -34,7 +34,7 @@
* @size: Length of buffer
* @mbx_id: id of mailbox to read
*
- * returns SUCCESS if it successfuly read message from buffer
+ * returns SUCCESS if it successfully read message from buffer
**/
s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
{
diff --git a/drivers/net/igb/e1000_mbx.h b/drivers/net/ethernet/intel/igb/e1000_mbx.h
index eddb0f83dcea..eddb0f83dcea 100644
--- a/drivers/net/igb/e1000_mbx.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mbx.h
diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/ethernet/intel/igb/e1000_nvm.c
index 40407124e722..40407124e722 100644
--- a/drivers/net/igb/e1000_nvm.c
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.c
diff --git a/drivers/net/igb/e1000_nvm.h b/drivers/net/ethernet/intel/igb/e1000_nvm.h
index a2a7ca9fa733..a2a7ca9fa733 100644
--- a/drivers/net/igb/e1000_nvm.h
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.h
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
index e662554c62d6..7edf31efe756 100644
--- a/drivers/net/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -306,6 +306,12 @@ s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
u32 i, i2ccmd = 0;
u16 phy_data_swapped;
+ /* Prevent overwritting SFP I2C EEPROM which is at A0 address.*/
+ if ((hw->phy.addr == 0) || (hw->phy.addr > 7)) {
+ hw_dbg("PHY I2C Address %d is out of range.\n",
+ hw->phy.addr);
+ return -E1000_ERR_CONFIG;
+ }
/* Swap the data bytes for the I2C interface */
phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h
index 8510797b9d81..8510797b9d81 100644
--- a/drivers/net/igb/e1000_phy.h
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.h
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h
index 0990f6d860c7..0a860bc1198e 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igb/e1000_regs.h
@@ -318,6 +318,7 @@
#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */
#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
+#define E1000_TXSWC 0x05ACC /* Tx Switch Control */
/* These act per VF so an array friendly macro is used */
#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n)))
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
diff --git a/drivers/net/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 265e151b66c4..c69feebf2653 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -42,11 +42,15 @@
struct igb_adapter;
-/* ((1000000000ns / (6000ints/s * 1024ns)) << 2 = 648 */
-#define IGB_START_ITR 648
+/* Interrupt defines */
+#define IGB_START_ITR 648 /* ~6000 ints/sec */
+#define IGB_4K_ITR 980
+#define IGB_20K_ITR 196
+#define IGB_70K_ITR 56
/* TX/RX descriptor defines */
#define IGB_DEFAULT_TXD 256
+#define IGB_DEFAULT_TX_WORK 128
#define IGB_MIN_TXD 80
#define IGB_MAX_TXD 4096
@@ -63,12 +67,13 @@ struct igb_adapter;
/* Transmit and receive queues */
#define IGB_MAX_RX_QUEUES (adapter->vfs_allocated_count ? 2 : \
(hw->mac.type > e1000_82575 ? 8 : 4))
-#define IGB_ABS_MAX_TX_QUEUES 8
-#define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES
+#define IGB_MAX_TX_QUEUES 16
#define IGB_MAX_VF_MC_ENTRIES 30
#define IGB_MAX_VF_FUNCTIONS 8
#define IGB_MAX_VFTA_ENTRIES 128
+#define IGB_82576_VF_DEV_ID 0x10CA
+#define IGB_I350_VF_DEV_ID 0x1520
struct vf_data_storage {
unsigned char vf_mac_addresses[ETH_ALEN];
@@ -80,6 +85,7 @@ struct vf_data_storage {
u16 pf_vlan; /* When set, guest VLAN config not allowed. */
u16 pf_qos;
u16 tx_rate;
+ struct pci_dev *vfdev;
};
#define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */
@@ -100,23 +106,20 @@ struct vf_data_storage {
*/
#define IGB_RX_PTHRESH 8
#define IGB_RX_HTHRESH 8
-#define IGB_RX_WTHRESH 1
#define IGB_TX_PTHRESH 8
#define IGB_TX_HTHRESH 1
+#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \
+ adapter->msix_entries) ? 1 : 4)
#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \
- adapter->msix_entries) ? 1 : 16)
+ adapter->msix_entries) ? 1 : 16)
/* this is the size past which hardware will drop packets when setting LPE=0 */
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
/* Supported Rx Buffer Sizes */
-#define IGB_RXBUFFER_64 64 /* Used for packet split */
-#define IGB_RXBUFFER_128 128 /* Used for packet split */
-#define IGB_RXBUFFER_1024 1024
-#define IGB_RXBUFFER_2048 2048
+#define IGB_RXBUFFER_512 512
#define IGB_RXBUFFER_16384 16384
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
+#define IGB_RX_HDR_LEN IGB_RXBUFFER_512
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
#define IGB_TX_QUEUE_WAKE 16
@@ -133,29 +136,34 @@ 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
+#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000
+#define IGB_TX_FLAGS_VLAN_SHIFT 16
+
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
-struct igb_buffer {
+struct igb_tx_buffer {
+ union e1000_adv_tx_desc *next_to_watch;
+ unsigned long time_stamp;
struct sk_buff *skb;
+ unsigned int bytecount;
+ u16 gso_segs;
+ __be16 protocol;
dma_addr_t dma;
- union {
- /* TX */
- struct {
- unsigned long time_stamp;
- u16 length;
- u16 next_to_watch;
- unsigned int bytecount;
- u16 gso_segs;
- u8 tx_flags;
- u8 mapped_as_page;
- };
- /* RX */
- struct {
- struct page *page;
- dma_addr_t page_dma;
- u16 page_offset;
- };
- };
+ u32 length;
+ u32 tx_flags;
+};
+
+struct igb_rx_buffer {
+ struct sk_buff *skb;
+ dma_addr_t dma;
+ struct page *page;
+ dma_addr_t page_dma;
+ u32 page_offset;
};
struct igb_tx_queue_stats {
@@ -173,14 +181,24 @@ struct igb_rx_queue_stats {
u64 alloc_failed;
};
+struct igb_ring_container {
+ struct igb_ring *ring; /* pointer to linked list of rings */
+ unsigned int total_bytes; /* total bytes processed this int */
+ unsigned int total_packets; /* total packets processed this int */
+ u16 work_limit; /* total work allowed per interrupt */
+ u8 count; /* total number of rings in vector */
+ u8 itr; /* current ITR setting for ring */
+};
+
struct igb_q_vector {
- struct igb_adapter *adapter; /* backlink */
- struct igb_ring *rx_ring;
- struct igb_ring *tx_ring;
- struct napi_struct napi;
+ struct igb_adapter *adapter; /* backlink */
+ int cpu; /* CPU for DCA */
+ u32 eims_value; /* EIMS mask value */
- u32 eims_value;
- u16 cpu;
+ struct igb_ring_container rx, tx;
+
+ struct napi_struct napi;
+ int numa_node;
u16 itr_val;
u8 set_itr;
@@ -190,25 +208,25 @@ struct igb_q_vector {
};
struct igb_ring {
- struct igb_q_vector *q_vector; /* backlink to q_vector */
- struct net_device *netdev; /* back pointer to net_device */
- struct device *dev; /* device pointer for dma mapping */
- dma_addr_t dma; /* phys address of the ring */
- void *desc; /* descriptor ring memory */
- unsigned int size; /* length of desc. ring in bytes */
- u16 count; /* number of desc. in the ring */
- u16 next_to_use;
- u16 next_to_clean;
- u8 queue_index;
- u8 reg_idx;
- void __iomem *head;
- void __iomem *tail;
- struct igb_buffer *buffer_info; /* array of buffer info structs */
+ struct igb_q_vector *q_vector; /* backlink to q_vector */
+ struct net_device *netdev; /* back pointer to net_device */
+ struct device *dev; /* device pointer for dma mapping */
+ union { /* array of buffer info structs */
+ struct igb_tx_buffer *tx_buffer_info;
+ struct igb_rx_buffer *rx_buffer_info;
+ };
+ void *desc; /* descriptor ring memory */
+ unsigned long flags; /* ring specific flags */
+ void __iomem *tail; /* pointer to ring tail register */
- unsigned int total_bytes;
- unsigned int total_packets;
+ 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 */
- u32 flags;
+ /* everything past this point are written often */
+ u16 next_to_clean ____cacheline_aligned_in_smp;
+ u16 next_to_use;
union {
/* TX */
@@ -216,30 +234,40 @@ struct igb_ring {
struct igb_tx_queue_stats tx_stats;
struct u64_stats_sync tx_syncp;
struct u64_stats_sync tx_syncp2;
- bool detect_tx_hung;
};
/* RX */
struct {
struct igb_rx_queue_stats rx_stats;
struct u64_stats_sync rx_syncp;
- u32 rx_buffer_len;
};
};
+ /* Items past this point are only used during ring alloc / free */
+ dma_addr_t dma; /* phys address of the ring */
+ int numa_node; /* node to alloc ring memory on */
};
-#define IGB_RING_FLAG_RX_CSUM 0x00000001 /* RX CSUM enabled */
-#define IGB_RING_FLAG_RX_SCTP_CSUM 0x00000002 /* SCTP CSUM offload enabled */
+enum e1000_ring_flags_t {
+ IGB_RING_FLAG_RX_SCTP_CSUM,
+ IGB_RING_FLAG_RX_LB_VLAN_BSWAP,
+ IGB_RING_FLAG_TX_CTX_IDX,
+ IGB_RING_FLAG_TX_DETECT_HANG
+};
-#define IGB_RING_FLAG_TX_CTX_IDX 0x00000001 /* HW requires context index */
+#define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS)
-#define IGB_ADVTXD_DCMD (E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS)
+#define IGB_RX_DESC(R, i) \
+ (&(((union e1000_adv_rx_desc *)((R)->desc))[i]))
+#define IGB_TX_DESC(R, i) \
+ (&(((union e1000_adv_tx_desc *)((R)->desc))[i]))
+#define IGB_TX_CTXTDESC(R, i) \
+ (&(((struct e1000_adv_tx_context_desc *)((R)->desc))[i]))
-#define E1000_RX_DESC_ADV(R, i) \
- (&(((union e1000_adv_rx_desc *)((R).desc))[i]))
-#define E1000_TX_DESC_ADV(R, i) \
- (&(((union e1000_adv_tx_desc *)((R).desc))[i]))
-#define E1000_TX_CTXTDESC_ADV(R, i) \
- (&(((struct e1000_adv_tx_context_desc *)((R).desc))[i]))
+/* igb_test_staterr - tests bits within Rx descriptor status and error fields */
+static inline __le32 igb_test_staterr(union e1000_adv_rx_desc *rx_desc,
+ const u32 stat_err_bits)
+{
+ return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
+}
/* igb_desc_unused - calculate if we have unused descriptors */
static inline int igb_desc_unused(struct igb_ring *ring)
@@ -252,15 +280,15 @@ static inline int igb_desc_unused(struct igb_ring *ring)
/* board specific private data structure */
struct igb_adapter {
- struct timer_list watchdog_timer;
- struct timer_list phy_info_timer;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
- u16 mng_vlan_id;
- u32 bd_number;
- u32 wol;
- u32 en_mng_pt;
- u16 link_speed;
- u16 link_duplex;
+
+ struct net_device *netdev;
+
+ unsigned long state;
+ unsigned int flags;
+
+ unsigned int num_q_vectors;
+ struct msix_entry *msix_entries;
/* Interrupt Throttle Rate */
u32 rx_itr_setting;
@@ -268,27 +296,37 @@ struct igb_adapter {
u16 tx_itr;
u16 rx_itr;
- struct work_struct reset_task;
- struct work_struct watchdog_task;
- bool fc_autoneg;
- u8 tx_timeout_factor;
- struct timer_list blink_timer;
- unsigned long led_status;
-
/* TX */
- struct igb_ring *tx_ring[16];
+ u16 tx_work_limit;
u32 tx_timeout_count;
+ int num_tx_queues;
+ struct igb_ring *tx_ring[16];
/* RX */
- struct igb_ring *rx_ring[16];
- int num_tx_queues;
int num_rx_queues;
+ struct igb_ring *rx_ring[16];
u32 max_frame_size;
u32 min_frame_size;
+ struct timer_list watchdog_timer;
+ struct timer_list phy_info_timer;
+
+ u16 mng_vlan_id;
+ u32 bd_number;
+ u32 wol;
+ u32 en_mng_pt;
+ u16 link_speed;
+ u16 link_duplex;
+
+ struct work_struct reset_task;
+ struct work_struct watchdog_task;
+ bool fc_autoneg;
+ u8 tx_timeout_factor;
+ struct timer_list blink_timer;
+ unsigned long led_status;
+
/* OS defined structs */
- struct net_device *netdev;
struct pci_dev *pdev;
struct cyclecounter cycles;
struct timecounter clock;
@@ -310,18 +348,13 @@ struct igb_adapter {
int msg_enable;
- unsigned int num_q_vectors;
struct igb_q_vector *q_vector[MAX_Q_VECTORS];
- struct msix_entry *msix_entries;
u32 eims_enable_mask;
u32 eims_other;
/* to not mess up cache alignment, always add to the bottom */
- unsigned long state;
- unsigned int flags;
u32 eeprom_wol;
- struct igb_ring *multi_tx_table[IGB_ABS_MAX_TX_QUEUES];
u16 tx_ring_count;
u16 rx_ring_count;
unsigned int vfs_allocated_count;
@@ -329,6 +362,8 @@ struct igb_adapter {
int vf_rate_link_speed;
u32 rss_queues;
u32 wvbr;
+ int node;
+ u32 *shadow_vfta;
};
#define IGB_FLAG_HAS_MSI (1 << 0)
@@ -371,10 +406,10 @@ extern void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *);
extern void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *);
extern void igb_setup_tctl(struct igb_adapter *);
extern void igb_setup_rctl(struct igb_adapter *);
-extern netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *, struct igb_ring *);
+extern netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *);
extern void igb_unmap_and_free_tx_resource(struct igb_ring *,
- struct igb_buffer *);
-extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
+ struct igb_tx_buffer *);
+extern void igb_alloc_rx_buffers(struct igb_ring *, u16);
extern void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *);
extern bool igb_has_link(struct igb_adapter *adapter);
extern void igb_set_ethtool_ops(struct net_device *);
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 414b0225be89..43873eba2f63 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -705,12 +705,8 @@ static void igb_get_ringparam(struct net_device *netdev,
ring->rx_max_pending = IGB_MAX_RXD;
ring->tx_max_pending = IGB_MAX_TXD;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = adapter->rx_ring_count;
ring->tx_pending = adapter->tx_ring_count;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
static int igb_set_ringparam(struct net_device *netdev,
@@ -1368,7 +1364,6 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter)
rx_ring->count = IGB_DEFAULT_RXD;
rx_ring->dev = &adapter->pdev->dev;
rx_ring->netdev = adapter->netdev;
- rx_ring->rx_buffer_len = IGB_RXBUFFER_2048;
rx_ring->reg_idx = adapter->vfs_allocated_count;
if (igb_setup_rx_resources(rx_ring)) {
@@ -1383,7 +1378,7 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter)
igb_setup_rctl(adapter);
igb_configure_rx_ring(adapter, rx_ring);
- igb_alloc_rx_buffers_adv(rx_ring, igb_desc_unused(rx_ring));
+ igb_alloc_rx_buffers(rx_ring, igb_desc_unused(rx_ring));
return 0;
@@ -1580,34 +1575,33 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
unsigned int size)
{
union e1000_adv_rx_desc *rx_desc;
- struct igb_buffer *buffer_info;
- int rx_ntc, tx_ntc, count = 0;
- u32 staterr;
+ struct igb_rx_buffer *rx_buffer_info;
+ struct igb_tx_buffer *tx_buffer_info;
+ u16 rx_ntc, tx_ntc, count = 0;
/* initialize next to clean and descriptor values */
rx_ntc = rx_ring->next_to_clean;
tx_ntc = tx_ring->next_to_clean;
- rx_desc = E1000_RX_DESC_ADV(*rx_ring, rx_ntc);
- staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+ rx_desc = IGB_RX_DESC(rx_ring, rx_ntc);
- while (staterr & E1000_RXD_STAT_DD) {
+ while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) {
/* check rx buffer */
- buffer_info = &rx_ring->buffer_info[rx_ntc];
+ 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,
- buffer_info->dma,
- rx_ring->rx_buffer_len,
+ rx_buffer_info->dma,
+ IGB_RX_HDR_LEN,
DMA_FROM_DEVICE);
- buffer_info->dma = 0;
+ rx_buffer_info->dma = 0;
/* verify contents of skb */
- if (!igb_check_lbtest_frame(buffer_info->skb, size))
+ if (!igb_check_lbtest_frame(rx_buffer_info->skb, size))
count++;
/* unmap buffer on tx side */
- buffer_info = &tx_ring->buffer_info[tx_ntc];
- igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
+ tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc];
+ igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
/* increment rx/tx next to clean counters */
rx_ntc++;
@@ -1618,12 +1612,11 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
tx_ntc = 0;
/* fetch next descriptor */
- rx_desc = E1000_RX_DESC_ADV(*rx_ring, rx_ntc);
- staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+ rx_desc = IGB_RX_DESC(rx_ring, rx_ntc);
}
/* re-map buffers to ring, store next to clean values */
- igb_alloc_rx_buffers_adv(rx_ring, count);
+ igb_alloc_rx_buffers(rx_ring, count);
rx_ring->next_to_clean = rx_ntc;
tx_ring->next_to_clean = tx_ntc;
@@ -1634,8 +1627,9 @@ static int igb_run_loopback_test(struct igb_adapter *adapter)
{
struct igb_ring *tx_ring = &adapter->test_tx_ring;
struct igb_ring *rx_ring = &adapter->test_rx_ring;
- int i, j, lc, good_cnt, ret_val = 0;
- unsigned int size = 1024;
+ u16 i, j, lc, good_cnt;
+ int ret_val = 0;
+ unsigned int size = IGB_RX_HDR_LEN;
netdev_tx_t tx_ret_val;
struct sk_buff *skb;
@@ -1666,7 +1660,7 @@ static int igb_run_loopback_test(struct igb_adapter *adapter)
/* place 64 packets on the transmit queue*/
for (i = 0; i < 64; i++) {
skb_get(skb);
- tx_ret_val = igb_xmit_frame_ring_adv(skb, tx_ring);
+ tx_ret_val = igb_xmit_frame_ring(skb, tx_ring);
if (tx_ret_val == NETDEV_TX_OK)
good_cnt++;
}
@@ -2012,7 +2006,8 @@ static int igb_set_coalesce(struct net_device *netdev,
for (i = 0; i < adapter->num_q_vectors; i++) {
struct igb_q_vector *q_vector = adapter->q_vector[i];
- if (q_vector->rx_ring)
+ q_vector->tx.work_limit = adapter->tx_work_limit;
+ if (q_vector->rx.ring)
q_vector->itr_val = adapter->rx_itr_setting;
else
q_vector->itr_val = adapter->tx_itr_setting;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 40d4c405fd7e..ced544499f1b 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -39,11 +39,15 @@
#include <linux/net_tstamp.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
+#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/pci.h>
#include <linux/pci-aspm.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/sctp.h>
#include <linux/if_ether.h>
#include <linux/aer.h>
#include <linux/prefetch.h>
@@ -53,8 +57,8 @@
#include "igb.h"
#define MAJ 3
-#define MIN 0
-#define BUILD 6
+#define MIN 2
+#define BUILD 10
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
char igb_driver_name[] = "igb";
@@ -121,7 +125,7 @@ static void igb_set_rx_mode(struct net_device *);
static void igb_update_phy_info(unsigned long);
static void igb_watchdog(unsigned long);
static void igb_watchdog_task(struct work_struct *);
-static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *);
+static netdev_tx_t igb_xmit_frame(struct sk_buff *skb, struct net_device *);
static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *stats);
static int igb_change_mtu(struct net_device *, int);
@@ -135,9 +139,9 @@ static irqreturn_t igb_msix_ring(int irq, void *);
static void igb_update_dca(struct igb_q_vector *);
static void igb_setup_dca(struct igb_adapter *);
#endif /* CONFIG_IGB_DCA */
-static bool igb_clean_tx_irq(struct igb_q_vector *);
static int igb_poll(struct napi_struct *, int);
-static bool igb_clean_rx_irq_adv(struct igb_q_vector *, int *, int);
+static bool igb_clean_tx_irq(struct igb_q_vector *);
+static bool igb_clean_rx_irq(struct igb_q_vector *, int);
static int igb_ioctl(struct net_device *, struct ifreq *, int cmd);
static void igb_tx_timeout(struct net_device *);
static void igb_reset_task(struct work_struct *);
@@ -159,6 +163,12 @@ static int igb_ndo_get_vf_config(struct net_device *netdev, int vf,
struct ifla_vf_info *ivi);
static void igb_check_vf_rate_limit(struct igb_adapter *);
+#ifdef CONFIG_PCI_IOV
+static int igb_vf_configure(struct igb_adapter *adapter, int vf);
+static int igb_find_enabled_vfs(struct igb_adapter *adapter);
+static int igb_check_vf_assignment(struct igb_adapter *adapter);
+#endif
+
#ifdef CONFIG_PM
static int igb_suspend(struct pci_dev *, pm_message_t);
static int igb_resume(struct pci_dev *);
@@ -194,6 +204,7 @@ static struct pci_error_handlers igb_err_handler = {
.resume = igb_io_resume,
};
+static void igb_init_dmac(struct igb_adapter *adapter, u32 pba);
static struct pci_driver igb_driver = {
.name = igb_driver_name,
@@ -334,15 +345,13 @@ static void igb_dump(struct igb_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct e1000_hw *hw = &adapter->hw;
struct igb_reg_info *reginfo;
- int n = 0;
struct igb_ring *tx_ring;
union e1000_adv_tx_desc *tx_desc;
struct my_u0 { u64 a; u64 b; } *u0;
- struct igb_buffer *buffer_info;
struct igb_ring *rx_ring;
union e1000_adv_rx_desc *rx_desc;
u32 staterr;
- int i = 0;
+ u16 i, n;
if (!netif_msg_hw(adapter))
return;
@@ -375,9 +384,10 @@ static void igb_dump(struct igb_adapter *adapter)
printk(KERN_INFO "Queue [NTU] [NTC] [bi(ntc)->dma ]"
" leng ntw timestamp\n");
for (n = 0; n < adapter->num_tx_queues; n++) {
+ struct igb_tx_buffer *buffer_info;
tx_ring = adapter->tx_ring[n];
- buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean];
- printk(KERN_INFO " %5d %5X %5X %016llX %04X %3X %016llX\n",
+ buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
+ printk(KERN_INFO " %5d %5X %5X %016llX %04X %p %016llX\n",
n, tx_ring->next_to_use, tx_ring->next_to_clean,
(u64)buffer_info->dma,
buffer_info->length,
@@ -412,11 +422,12 @@ static void igb_dump(struct igb_adapter *adapter)
"leng ntw timestamp bi->skb\n");
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
- tx_desc = E1000_TX_DESC_ADV(*tx_ring, i);
- buffer_info = &tx_ring->buffer_info[i];
+ struct igb_tx_buffer *buffer_info;
+ tx_desc = IGB_TX_DESC(tx_ring, i);
+ buffer_info = &tx_ring->tx_buffer_info[i];
u0 = (struct my_u0 *)tx_desc;
printk(KERN_INFO "T [0x%03X] %016llX %016llX %016llX"
- " %04X %3X %016llX %p", i,
+ " %04X %p %016llX %p", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
(u64)buffer_info->dma,
@@ -492,8 +503,9 @@ rx_ring_summary:
"<-- Adv Rx Write-Back format\n");
for (i = 0; i < rx_ring->count; i++) {
- buffer_info = &rx_ring->buffer_info[i];
- rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
+ struct igb_rx_buffer *buffer_info;
+ buffer_info = &rx_ring->rx_buffer_info[i];
+ rx_desc = IGB_RX_DESC(rx_ring, i);
u0 = (struct my_u0 *)rx_desc;
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
if (staterr & E1000_RXD_STAT_DD) {
@@ -516,16 +528,14 @@ rx_ring_summary:
DUMP_PREFIX_ADDRESS,
16, 1,
phys_to_virt(buffer_info->dma),
- rx_ring->rx_buffer_len, true);
- if (rx_ring->rx_buffer_len
- < IGB_RXBUFFER_1024)
- print_hex_dump(KERN_INFO, "",
- DUMP_PREFIX_ADDRESS,
- 16, 1,
- phys_to_virt(
- buffer_info->page_dma +
- buffer_info->page_offset),
- PAGE_SIZE/2, true);
+ IGB_RX_HDR_LEN, true);
+ print_hex_dump(KERN_INFO, "",
+ DUMP_PREFIX_ADDRESS,
+ 16, 1,
+ phys_to_virt(
+ buffer_info->page_dma +
+ buffer_info->page_offset),
+ PAGE_SIZE/2, true);
}
}
@@ -560,7 +570,7 @@ static cycle_t igb_read_clock(const struct cyclecounter *tc)
* the lowest register is SYSTIMR instead of SYSTIML. However we never
* adjusted TIMINCA so SYSTIMR will just read as all 0s so ignore it.
*/
- if (hw->mac.type == e1000_82580) {
+ if (hw->mac.type >= e1000_82580) {
stamp = rd32(E1000_SYSTIMR) >> 8;
shift = IGB_82580_TSYNC_SHIFT;
}
@@ -683,61 +693,116 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
{
struct igb_ring *ring;
int i;
+ int orig_node = adapter->node;
for (i = 0; i < adapter->num_tx_queues; i++) {
- ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL);
+ if (orig_node == -1) {
+ int cur_node = next_online_node(adapter->node);
+ if (cur_node == MAX_NUMNODES)
+ cur_node = first_online_node;
+ adapter->node = cur_node;
+ }
+ ring = kzalloc_node(sizeof(struct igb_ring), GFP_KERNEL,
+ adapter->node);
+ if (!ring)
+ 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;
+ ring->numa_node = adapter->node;
/* For 82575, context index must be unique per ring. */
if (adapter->hw.mac.type == e1000_82575)
- ring->flags = IGB_RING_FLAG_TX_CTX_IDX;
+ set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags);
adapter->tx_ring[i] = ring;
}
+ /* Restore the adapter's original node */
+ adapter->node = orig_node;
for (i = 0; i < adapter->num_rx_queues; i++) {
- ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL);
+ if (orig_node == -1) {
+ int cur_node = next_online_node(adapter->node);
+ if (cur_node == MAX_NUMNODES)
+ cur_node = first_online_node;
+ adapter->node = cur_node;
+ }
+ ring = kzalloc_node(sizeof(struct igb_ring), GFP_KERNEL,
+ adapter->node);
+ if (!ring)
+ 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;
- ring->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
- ring->flags = IGB_RING_FLAG_RX_CSUM; /* enable rx checksum */
+ ring->numa_node = adapter->node;
/* set flag indicating ring supports SCTP checksum offload */
if (adapter->hw.mac.type >= e1000_82576)
- ring->flags |= IGB_RING_FLAG_RX_SCTP_CSUM;
+ set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags);
+
+ /* On i350, 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;
}
+ /* Restore the adapter's original node */
+ adapter->node = orig_node;
igb_cache_ring_register(adapter);
return 0;
err:
+ /* Restore the adapter's original node */
+ adapter->node = orig_node;
igb_free_queues(adapter);
return -ENOMEM;
}
+/**
+ * igb_write_ivar - configure ivar for given MSI-X vector
+ * @hw: pointer to the HW structure
+ * @msix_vector: vector number we are allocating to a given ring
+ * @index: row index of IVAR register to write within IVAR table
+ * @offset: column offset of in IVAR, should be multiple of 8
+ *
+ * This function is intended to handle the writing of the IVAR register
+ * for adapters 82576 and newer. The IVAR table consists of 2 columns,
+ * each containing an cause allocation for an Rx and Tx ring, and a
+ * variable number of rows depending on the number of queues supported.
+ **/
+static void igb_write_ivar(struct e1000_hw *hw, int msix_vector,
+ int index, int offset)
+{
+ u32 ivar = array_rd32(E1000_IVAR0, index);
+
+ /* clear any bits that are currently set */
+ ivar &= ~((u32)0xFF << offset);
+
+ /* write vector and valid bit */
+ ivar |= (msix_vector | E1000_IVAR_VALID) << offset;
+
+ array_wr32(E1000_IVAR0, index, ivar);
+}
+
#define IGB_N0_QUEUE -1
static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector)
{
- u32 msixbm = 0;
struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw;
- u32 ivar, index;
int rx_queue = IGB_N0_QUEUE;
int tx_queue = IGB_N0_QUEUE;
+ u32 msixbm = 0;
- if (q_vector->rx_ring)
- rx_queue = q_vector->rx_ring->reg_idx;
- if (q_vector->tx_ring)
- tx_queue = q_vector->tx_ring->reg_idx;
+ if (q_vector->rx.ring)
+ rx_queue = q_vector->rx.ring->reg_idx;
+ if (q_vector->tx.ring)
+ tx_queue = q_vector->tx.ring->reg_idx;
switch (hw->mac.type) {
case e1000_82575:
@@ -755,72 +820,39 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector)
q_vector->eims_value = msixbm;
break;
case e1000_82576:
- /* 82576 uses a table-based method for assigning vectors.
- Each queue has a single entry in the table to which we write
- a vector number along with a "valid" bit. Sadly, the layout
- of the table is somewhat counterintuitive. */
- if (rx_queue > IGB_N0_QUEUE) {
- index = (rx_queue & 0x7);
- ivar = array_rd32(E1000_IVAR0, index);
- if (rx_queue < 8) {
- /* vector goes into low byte of register */
- ivar = ivar & 0xFFFFFF00;
- ivar |= msix_vector | E1000_IVAR_VALID;
- } else {
- /* vector goes into third byte of register */
- ivar = ivar & 0xFF00FFFF;
- ivar |= (msix_vector | E1000_IVAR_VALID) << 16;
- }
- array_wr32(E1000_IVAR0, index, ivar);
- }
- if (tx_queue > IGB_N0_QUEUE) {
- index = (tx_queue & 0x7);
- ivar = array_rd32(E1000_IVAR0, index);
- if (tx_queue < 8) {
- /* vector goes into second byte of register */
- ivar = ivar & 0xFFFF00FF;
- ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
- } else {
- /* vector goes into high byte of register */
- ivar = ivar & 0x00FFFFFF;
- ivar |= (msix_vector | E1000_IVAR_VALID) << 24;
- }
- array_wr32(E1000_IVAR0, index, ivar);
- }
+ /*
+ * 82576 uses a table that essentially consists of 2 columns
+ * with 8 rows. The ordering is column-major so we use the
+ * lower 3 bits as the row index, and the 4th bit as the
+ * column offset.
+ */
+ if (rx_queue > IGB_N0_QUEUE)
+ igb_write_ivar(hw, msix_vector,
+ rx_queue & 0x7,
+ (rx_queue & 0x8) << 1);
+ if (tx_queue > IGB_N0_QUEUE)
+ igb_write_ivar(hw, msix_vector,
+ tx_queue & 0x7,
+ ((tx_queue & 0x8) << 1) + 8);
q_vector->eims_value = 1 << msix_vector;
break;
case e1000_82580:
case e1000_i350:
- /* 82580 uses the same table-based approach as 82576 but has fewer
- entries as a result we carry over for queues greater than 4. */
- if (rx_queue > IGB_N0_QUEUE) {
- index = (rx_queue >> 1);
- ivar = array_rd32(E1000_IVAR0, index);
- if (rx_queue & 0x1) {
- /* vector goes into third byte of register */
- ivar = ivar & 0xFF00FFFF;
- ivar |= (msix_vector | E1000_IVAR_VALID) << 16;
- } else {
- /* vector goes into low byte of register */
- ivar = ivar & 0xFFFFFF00;
- ivar |= msix_vector | E1000_IVAR_VALID;
- }
- array_wr32(E1000_IVAR0, index, ivar);
- }
- if (tx_queue > IGB_N0_QUEUE) {
- index = (tx_queue >> 1);
- ivar = array_rd32(E1000_IVAR0, index);
- if (tx_queue & 0x1) {
- /* vector goes into high byte of register */
- ivar = ivar & 0x00FFFFFF;
- ivar |= (msix_vector | E1000_IVAR_VALID) << 24;
- } else {
- /* vector goes into second byte of register */
- ivar = ivar & 0xFFFF00FF;
- ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
- }
- array_wr32(E1000_IVAR0, index, ivar);
- }
+ /*
+ * On 82580 and newer adapters the scheme is similar to 82576
+ * however instead of ordering column-major we have things
+ * ordered row-major. So we traverse the table by using
+ * bit 0 as the column offset, and the remaining bits as the
+ * row index.
+ */
+ if (rx_queue > IGB_N0_QUEUE)
+ igb_write_ivar(hw, msix_vector,
+ rx_queue >> 1,
+ (rx_queue & 0x1) << 4);
+ if (tx_queue > IGB_N0_QUEUE)
+ igb_write_ivar(hw, msix_vector,
+ tx_queue >> 1,
+ ((tx_queue & 0x1) << 4) + 8);
q_vector->eims_value = 1 << msix_vector;
break;
default:
@@ -920,15 +952,15 @@ static int igb_request_msix(struct igb_adapter *adapter)
q_vector->itr_register = hw->hw_addr + E1000_EITR(vector);
- if (q_vector->rx_ring && q_vector->tx_ring)
+ if (q_vector->rx.ring && q_vector->tx.ring)
sprintf(q_vector->name, "%s-TxRx-%u", netdev->name,
- q_vector->rx_ring->queue_index);
- else if (q_vector->tx_ring)
+ q_vector->rx.ring->queue_index);
+ else if (q_vector->tx.ring)
sprintf(q_vector->name, "%s-tx-%u", netdev->name,
- q_vector->tx_ring->queue_index);
- else if (q_vector->rx_ring)
+ q_vector->tx.ring->queue_index);
+ else if (q_vector->rx.ring)
sprintf(q_vector->name, "%s-rx-%u", netdev->name,
- q_vector->rx_ring->queue_index);
+ q_vector->rx.ring->queue_index);
else
sprintf(q_vector->name, "%s-unused", netdev->name);
@@ -1084,9 +1116,24 @@ static int igb_alloc_q_vectors(struct igb_adapter *adapter)
struct igb_q_vector *q_vector;
struct e1000_hw *hw = &adapter->hw;
int v_idx;
+ int orig_node = adapter->node;
for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
- q_vector = kzalloc(sizeof(struct igb_q_vector), GFP_KERNEL);
+ if ((adapter->num_q_vectors == (adapter->num_rx_queues +
+ adapter->num_tx_queues)) &&
+ (adapter->num_rx_queues == v_idx))
+ adapter->node = orig_node;
+ if (orig_node == -1) {
+ int cur_node = next_online_node(adapter->node);
+ if (cur_node == MAX_NUMNODES)
+ cur_node = first_online_node;
+ adapter->node = cur_node;
+ }
+ q_vector = kzalloc_node(sizeof(struct igb_q_vector), GFP_KERNEL,
+ adapter->node);
+ if (!q_vector)
+ q_vector = kzalloc(sizeof(struct igb_q_vector),
+ GFP_KERNEL);
if (!q_vector)
goto err_out;
q_vector->adapter = adapter;
@@ -1095,9 +1142,14 @@ static int igb_alloc_q_vectors(struct igb_adapter *adapter)
netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64);
adapter->q_vector[v_idx] = q_vector;
}
+ /* Restore the adapter's original node */
+ adapter->node = orig_node;
+
return 0;
err_out:
+ /* Restore the adapter's original node */
+ adapter->node = orig_node;
igb_free_q_vectors(adapter);
return -ENOMEM;
}
@@ -1107,8 +1159,9 @@ static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter,
{
struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
- q_vector->rx_ring = adapter->rx_ring[ring_idx];
- q_vector->rx_ring->q_vector = q_vector;
+ 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;
@@ -1119,9 +1172,11 @@ static void igb_map_tx_ring_to_vector(struct igb_adapter *adapter,
{
struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
- q_vector->tx_ring = adapter->tx_ring[ring_idx];
- q_vector->tx_ring->q_vector = q_vector;
+ 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;
}
@@ -1219,7 +1274,7 @@ static int igb_request_irq(struct igb_adapter *adapter)
goto request_done;
/* fall back to MSI */
igb_clear_interrupt_scheme(adapter);
- if (!pci_enable_msi(adapter->pdev))
+ if (!pci_enable_msi(pdev))
adapter->flags |= IGB_FLAG_HAS_MSI;
igb_free_all_tx_resources(adapter);
igb_free_all_rx_resources(adapter);
@@ -1241,12 +1296,12 @@ static int igb_request_irq(struct igb_adapter *adapter)
}
igb_setup_all_tx_resources(adapter);
igb_setup_all_rx_resources(adapter);
- } else {
- igb_assign_vector(adapter->q_vector[0], 0);
}
+ igb_assign_vector(adapter->q_vector[0], 0);
+
if (adapter->flags & IGB_FLAG_HAS_MSI) {
- err = request_irq(adapter->pdev->irq, igb_intr_msi, 0,
+ err = request_irq(pdev->irq, igb_intr_msi, 0,
netdev->name, adapter);
if (!err)
goto request_done;
@@ -1256,11 +1311,11 @@ static int igb_request_irq(struct igb_adapter *adapter)
adapter->flags &= ~IGB_FLAG_HAS_MSI;
}
- err = request_irq(adapter->pdev->irq, igb_intr, IRQF_SHARED,
+ err = request_irq(pdev->irq, igb_intr, IRQF_SHARED,
netdev->name, adapter);
if (err)
- dev_err(&adapter->pdev->dev, "Error %d getting interrupt\n",
+ dev_err(&pdev->dev, "Error %d getting interrupt\n",
err);
request_done:
@@ -1274,11 +1329,9 @@ static void igb_free_irq(struct igb_adapter *adapter)
free_irq(adapter->msix_entries[vector++].vector, adapter);
- for (i = 0; i < adapter->num_q_vectors; i++) {
- struct igb_q_vector *q_vector = adapter->q_vector[i];
+ for (i = 0; i < adapter->num_q_vectors; i++)
free_irq(adapter->msix_entries[vector++].vector,
- q_vector);
- }
+ adapter->q_vector[i]);
} else {
free_irq(adapter->pdev->irq, adapter);
}
@@ -1326,7 +1379,7 @@ static void igb_irq_enable(struct igb_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
if (adapter->msix_entries) {
- u32 ims = E1000_IMS_LSC | E1000_IMS_DOUTSYNC;
+ u32 ims = E1000_IMS_LSC | E1000_IMS_DOUTSYNC | E1000_IMS_DRSTA;
u32 regval = rd32(E1000_EIAC);
wr32(E1000_EIAC, regval | adapter->eims_enable_mask);
regval = rd32(E1000_EIAM);
@@ -1336,9 +1389,6 @@ static void igb_irq_enable(struct igb_adapter *adapter)
wr32(E1000_MBVFIMR, 0xFF);
ims |= E1000_IMS_VMMB;
}
- if (adapter->hw.mac.type == e1000_82580)
- ims |= E1000_IMS_DRSTA;
-
wr32(E1000_IMS, ims);
} else {
wr32(E1000_IMS, IMS_ENABLE_MASK |
@@ -1438,7 +1488,7 @@ static void igb_configure(struct igb_adapter *adapter)
* next_to_use != next_to_clean */
for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *ring = adapter->rx_ring[i];
- igb_alloc_rx_buffers_adv(ring, igb_desc_unused(ring));
+ igb_alloc_rx_buffers(ring, igb_desc_unused(ring));
}
}
@@ -1480,10 +1530,9 @@ int igb_up(struct igb_adapter *adapter)
clear_bit(__IGB_DOWN, &adapter->state);
- for (i = 0; i < adapter->num_q_vectors; i++) {
- struct igb_q_vector *q_vector = adapter->q_vector[i];
- napi_enable(&q_vector->napi);
- }
+ for (i = 0; i < adapter->num_q_vectors; i++)
+ napi_enable(&(adapter->q_vector[i]->napi));
+
if (adapter->msix_entries)
igb_configure_msix(adapter);
else
@@ -1535,10 +1584,8 @@ void igb_down(struct igb_adapter *adapter)
wrfl();
msleep(10);
- for (i = 0; i < adapter->num_q_vectors; i++) {
- struct igb_q_vector *q_vector = adapter->q_vector[i];
- napi_disable(&q_vector->napi);
- }
+ for (i = 0; i < adapter->num_q_vectors; i++)
+ napi_disable(&(adapter->q_vector[i]->napi));
igb_irq_disable(adapter);
@@ -1682,63 +1729,8 @@ void igb_reset(struct igb_adapter *adapter)
if (hw->mac.ops.init_hw(hw))
dev_err(&pdev->dev, "Hardware Error\n");
- if (hw->mac.type > e1000_82580) {
- if (adapter->flags & IGB_FLAG_DMAC) {
- u32 reg;
-
- /*
- * DMA Coalescing high water mark needs to be higher
- * than * the * Rx threshold. The Rx threshold is
- * currently * pba - 6, so we * should use a high water
- * mark of pba * - 4. */
- hwm = (pba - 4) << 10;
- reg = (((pba-6) << E1000_DMACR_DMACTHR_SHIFT)
- & E1000_DMACR_DMACTHR_MASK);
-
- /* transition to L0x or L1 if available..*/
- reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK);
-
- /* watchdog timer= +-1000 usec in 32usec intervals */
- reg |= (1000 >> 5);
- wr32(E1000_DMACR, reg);
-
- /* no lower threshold to disable coalescing(smart fifb)
- * -UTRESH=0*/
- wr32(E1000_DMCRTRH, 0);
-
- /* set hwm to PBA - 2 * max frame size */
- wr32(E1000_FCRTC, hwm);
-
- /*
- * This sets the time to wait before requesting tran-
- * sition to * low power state to number of usecs needed
- * to receive 1 512 * byte frame at gigabit line rate
- */
- reg = rd32(E1000_DMCTLX);
- reg |= IGB_DMCTLX_DCFLUSH_DIS;
-
- /* Delay 255 usec before entering Lx state. */
- reg |= 0xFF;
- wr32(E1000_DMCTLX, reg);
-
- /* free space in Tx packet buffer to wake from DMAC */
- wr32(E1000_DMCTXTH,
- (IGB_MIN_TXPBSIZE -
- (IGB_TX_BUF_4096 + adapter->max_frame_size))
- >> 6);
-
- /* make low power state decision controlled by DMAC */
- reg = rd32(E1000_PCIEMISC);
- reg |= E1000_PCIEMISC_LX_DECISION;
- wr32(E1000_PCIEMISC, reg);
- } /* end if IGB_FLAG_DMAC set */
- }
- if (hw->mac.type == e1000_82580) {
- u32 reg = rd32(E1000_PCIEMISC);
- wr32(E1000_PCIEMISC,
- reg & ~E1000_PCIEMISC_LX_DECISION);
- }
+ igb_init_dmac(adapter, pba);
if (!netif_running(adapter->netdev))
igb_power_down_link(adapter);
@@ -1766,17 +1758,8 @@ static u32 igb_fix_features(struct net_device *netdev, u32 features)
static int igb_set_features(struct net_device *netdev, u32 features)
{
- struct igb_adapter *adapter = netdev_priv(netdev);
- int i;
u32 changed = netdev->features ^ features;
- for (i = 0; i < adapter->num_rx_queues; i++) {
- if (features & NETIF_F_RXCSUM)
- adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM;
- else
- adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM;
- }
-
if (changed & NETIF_F_HW_VLAN_RX)
igb_vlan_mode(netdev, features);
@@ -1786,10 +1769,9 @@ static int igb_set_features(struct net_device *netdev, u32 features)
static const struct net_device_ops igb_netdev_ops = {
.ndo_open = igb_open,
.ndo_stop = igb_close,
- .ndo_start_xmit = igb_xmit_frame_adv,
+ .ndo_start_xmit = igb_xmit_frame,
.ndo_get_stats64 = igb_get_stats64,
.ndo_set_rx_mode = igb_set_rx_mode,
- .ndo_set_multicast_list = igb_set_rx_mode,
.ndo_set_mac_address = igb_set_mac,
.ndo_change_mtu = igb_change_mtu,
.ndo_do_ioctl = igb_ioctl,
@@ -1878,7 +1860,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
err = -ENOMEM;
netdev = alloc_etherdev_mq(sizeof(struct igb_adapter),
- IGB_ABS_MAX_TX_QUEUES);
+ IGB_MAX_TX_QUEUES);
if (!netdev)
goto err_alloc_etherdev;
@@ -1945,23 +1927,32 @@ static int __devinit igb_probe(struct pci_dev *pdev,
dev_info(&pdev->dev,
"PHY reset is blocked due to SOL/IDER session.\n");
- netdev->hw_features = NETIF_F_SG |
- NETIF_F_IP_CSUM |
- NETIF_F_IPV6_CSUM |
- NETIF_F_TSO |
- NETIF_F_TSO6 |
- NETIF_F_RXCSUM |
- NETIF_F_HW_VLAN_RX;
-
- netdev->features = netdev->hw_features |
- NETIF_F_HW_VLAN_TX |
- NETIF_F_HW_VLAN_FILTER;
-
- netdev->vlan_features |= NETIF_F_TSO;
- netdev->vlan_features |= NETIF_F_TSO6;
- netdev->vlan_features |= NETIF_F_IP_CSUM;
- netdev->vlan_features |= NETIF_F_IPV6_CSUM;
- netdev->vlan_features |= NETIF_F_SG;
+ /*
+ * features is initialized to 0 in allocation, it might have bits
+ * set by igb_sw_init so we should use an or instead of an
+ * assignment.
+ */
+ netdev->features |= NETIF_F_SG |
+ NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM |
+ NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_RXHASH |
+ NETIF_F_RXCSUM |
+ NETIF_F_HW_VLAN_RX |
+ NETIF_F_HW_VLAN_TX;
+
+ /* copy netdev features into list of user selectable features */
+ netdev->hw_features |= netdev->features;
+
+ /* set this bit last since it cannot be part of hw_features */
+ netdev->features |= NETIF_F_HW_VLAN_FILTER;
+
+ netdev->vlan_features |= NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM |
+ NETIF_F_SG;
if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
@@ -1973,6 +1964,8 @@ static int __devinit igb_probe(struct pci_dev *pdev,
netdev->features |= NETIF_F_SCTP_CSUM;
}
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);
/* before reading the NVM, reset the controller to put the device in a
@@ -2077,8 +2070,6 @@ static int __devinit igb_probe(struct pci_dev *pdev,
if (err)
goto err_register;
- igb_vlan_mode(netdev, netdev->features);
-
/* carrier off reporting is important to ethtool even BEFORE open */
netif_carrier_off(netdev);
@@ -2193,8 +2184,12 @@ static void __devexit igb_remove(struct pci_dev *pdev)
/* reclaim resources allocated to VFs */
if (adapter->vf_data) {
/* disable iov and allow time for transactions to clear */
- pci_disable_sriov(pdev);
- msleep(500);
+ if (!igb_check_vf_assignment(adapter)) {
+ pci_disable_sriov(pdev);
+ msleep(500);
+ } else {
+ dev_info(&pdev->dev, "VF(s) assigned to guests!\n");
+ }
kfree(adapter->vf_data);
adapter->vf_data = NULL;
@@ -2211,6 +2206,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
pci_release_selected_regions(pdev,
pci_select_bars(pdev, IORESOURCE_MEM));
+ kfree(adapter->shadow_vfta);
free_netdev(netdev);
pci_disable_pcie_error_reporting(pdev);
@@ -2231,42 +2227,49 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
{
#ifdef CONFIG_PCI_IOV
struct pci_dev *pdev = adapter->pdev;
+ int old_vfs = igb_find_enabled_vfs(adapter);
+ int i;
- if (adapter->vfs_allocated_count) {
- adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
- sizeof(struct vf_data_storage),
- GFP_KERNEL);
- /* if allocation failed then we do not support SR-IOV */
- if (!adapter->vf_data) {
- adapter->vfs_allocated_count = 0;
- dev_err(&pdev->dev, "Unable to allocate memory for VF "
- "Data Storage\n");
- }
+ if (old_vfs) {
+ dev_info(&pdev->dev, "%d pre-allocated VFs found - override "
+ "max_vfs setting of %d\n", old_vfs, max_vfs);
+ adapter->vfs_allocated_count = old_vfs;
}
- if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) {
- kfree(adapter->vf_data);
- adapter->vf_data = NULL;
-#endif /* CONFIG_PCI_IOV */
+ if (!adapter->vfs_allocated_count)
+ return;
+
+ adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
+ sizeof(struct vf_data_storage), GFP_KERNEL);
+ /* if allocation failed then we do not support SR-IOV */
+ if (!adapter->vf_data) {
adapter->vfs_allocated_count = 0;
-#ifdef CONFIG_PCI_IOV
- } else {
- unsigned char mac_addr[ETH_ALEN];
- int i;
- dev_info(&pdev->dev, "%d vfs allocated\n",
- adapter->vfs_allocated_count);
- for (i = 0; i < adapter->vfs_allocated_count; i++) {
- random_ether_addr(mac_addr);
- igb_set_vf_mac(adapter, i, mac_addr);
- }
- /* DMA Coalescing is not supported in IOV mode. */
- if (adapter->flags & IGB_FLAG_DMAC)
- adapter->flags &= ~IGB_FLAG_DMAC;
+ dev_err(&pdev->dev, "Unable to allocate memory for VF "
+ "Data Storage\n");
+ goto out;
+ }
+
+ if (!old_vfs) {
+ if (pci_enable_sriov(pdev, adapter->vfs_allocated_count))
+ goto err_out;
}
+ dev_info(&pdev->dev, "%d VFs allocated\n",
+ adapter->vfs_allocated_count);
+ for (i = 0; i < adapter->vfs_allocated_count; i++)
+ igb_vf_configure(adapter, i);
+
+ /* DMA Coalescing is not supported in IOV mode. */
+ adapter->flags &= ~IGB_FLAG_DMAC;
+ goto out;
+err_out:
+ kfree(adapter->vf_data);
+ adapter->vf_data = NULL;
+ adapter->vfs_allocated_count = 0;
+out:
+ return;
#endif /* CONFIG_PCI_IOV */
}
-
/**
* igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp
* @adapter: board private structure to initialize
@@ -2389,14 +2392,23 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word);
+ /* set default ring sizes */
adapter->tx_ring_count = IGB_DEFAULT_TXD;
adapter->rx_ring_count = IGB_DEFAULT_RXD;
+
+ /* set default ITR values */
adapter->rx_itr_setting = IGB_DEFAULT_ITR;
adapter->tx_itr_setting = IGB_DEFAULT_ITR;
- adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+ /* set default work limits */
+ adapter->tx_work_limit = IGB_DEFAULT_TX_WORK;
+
+ adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN +
+ VLAN_HLEN;
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+ adapter->node = -1;
+
spin_lock_init(&adapter->stats64_lock);
#ifdef CONFIG_PCI_IOV
switch (hw->mac.type) {
@@ -2427,6 +2439,11 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
((adapter->rss_queues > 1) && (adapter->vfs_allocated_count > 6)))
adapter->flags |= IGB_FLAG_QUEUE_PAIRS;
+ /* Setup and initialize a copy of the hw vlan table array */
+ adapter->shadow_vfta = kzalloc(sizeof(u32) *
+ E1000_VLAN_FILTER_TBL_SIZE,
+ GFP_ATOMIC);
+
/* This call may decrease the number of queues */
if (igb_init_interrupt_scheme(adapter)) {
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
@@ -2495,10 +2512,8 @@ static int igb_open(struct net_device *netdev)
/* From here on the code is the same as igb_up() */
clear_bit(__IGB_DOWN, &adapter->state);
- for (i = 0; i < adapter->num_q_vectors; i++) {
- struct igb_q_vector *q_vector = adapter->q_vector[i];
- napi_enable(&q_vector->napi);
- }
+ for (i = 0; i < adapter->num_q_vectors; i++)
+ napi_enable(&(adapter->q_vector[i]->napi));
/* Clear any pending interrupts. */
rd32(E1000_ICR);
@@ -2567,31 +2582,42 @@ static int igb_close(struct net_device *netdev)
int igb_setup_tx_resources(struct igb_ring *tx_ring)
{
struct device *dev = tx_ring->dev;
+ int orig_node = dev_to_node(dev);
int size;
- size = sizeof(struct igb_buffer) * tx_ring->count;
- tx_ring->buffer_info = vzalloc(size);
- if (!tx_ring->buffer_info)
+ size = sizeof(struct igb_tx_buffer) * tx_ring->count;
+ tx_ring->tx_buffer_info = vzalloc_node(size, tx_ring->numa_node);
+ if (!tx_ring->tx_buffer_info)
+ tx_ring->tx_buffer_info = vzalloc(size);
+ if (!tx_ring->tx_buffer_info)
goto err;
/* round up to nearest 4K */
tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
tx_ring->size = ALIGN(tx_ring->size, 4096);
+ set_dev_node(dev, tx_ring->numa_node);
tx_ring->desc = dma_alloc_coherent(dev,
tx_ring->size,
&tx_ring->dma,
GFP_KERNEL);
+ set_dev_node(dev, orig_node);
+ if (!tx_ring->desc)
+ tx_ring->desc = dma_alloc_coherent(dev,
+ tx_ring->size,
+ &tx_ring->dma,
+ GFP_KERNEL);
if (!tx_ring->desc)
goto err;
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
+
return 0;
err:
- vfree(tx_ring->buffer_info);
+ vfree(tx_ring->tx_buffer_info);
dev_err(dev,
"Unable to allocate memory for the transmit descriptor ring\n");
return -ENOMEM;
@@ -2620,10 +2646,6 @@ static int igb_setup_all_tx_resources(struct igb_adapter *adapter)
}
}
- for (i = 0; i < IGB_ABS_MAX_TX_QUEUES; i++) {
- int r_idx = i % adapter->num_tx_queues;
- adapter->multi_tx_table[i] = adapter->tx_ring[r_idx];
- }
return err;
}
@@ -2664,14 +2686,12 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
struct igb_ring *ring)
{
struct e1000_hw *hw = &adapter->hw;
- u32 txdctl;
+ u32 txdctl = 0;
u64 tdba = ring->dma;
int reg_idx = ring->reg_idx;
/* disable the queue */
- txdctl = rd32(E1000_TXDCTL(reg_idx));
- wr32(E1000_TXDCTL(reg_idx),
- txdctl & ~E1000_TXDCTL_QUEUE_ENABLE);
+ wr32(E1000_TXDCTL(reg_idx), 0);
wrfl();
mdelay(10);
@@ -2681,9 +2701,8 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
tdba & 0x00000000ffffffffULL);
wr32(E1000_TDBAH(reg_idx), tdba >> 32);
- ring->head = hw->hw_addr + E1000_TDH(reg_idx);
ring->tail = hw->hw_addr + E1000_TDT(reg_idx);
- writel(0, ring->head);
+ wr32(E1000_TDH(reg_idx), 0);
writel(0, ring->tail);
txdctl |= IGB_TX_PTHRESH;
@@ -2717,11 +2736,14 @@ static void igb_configure_tx(struct igb_adapter *adapter)
int igb_setup_rx_resources(struct igb_ring *rx_ring)
{
struct device *dev = rx_ring->dev;
+ int orig_node = dev_to_node(dev);
int size, desc_len;
- size = sizeof(struct igb_buffer) * rx_ring->count;
- rx_ring->buffer_info = vzalloc(size);
- if (!rx_ring->buffer_info)
+ size = sizeof(struct igb_rx_buffer) * rx_ring->count;
+ rx_ring->rx_buffer_info = vzalloc_node(size, rx_ring->numa_node);
+ if (!rx_ring->rx_buffer_info)
+ rx_ring->rx_buffer_info = vzalloc(size);
+ if (!rx_ring->rx_buffer_info)
goto err;
desc_len = sizeof(union e1000_adv_rx_desc);
@@ -2730,10 +2752,17 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
rx_ring->size = rx_ring->count * desc_len;
rx_ring->size = ALIGN(rx_ring->size, 4096);
+ set_dev_node(dev, rx_ring->numa_node);
rx_ring->desc = dma_alloc_coherent(dev,
rx_ring->size,
&rx_ring->dma,
GFP_KERNEL);
+ set_dev_node(dev, orig_node);
+ if (!rx_ring->desc)
+ rx_ring->desc = dma_alloc_coherent(dev,
+ rx_ring->size,
+ &rx_ring->dma,
+ GFP_KERNEL);
if (!rx_ring->desc)
goto err;
@@ -2744,8 +2773,8 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
return 0;
err:
- vfree(rx_ring->buffer_info);
- rx_ring->buffer_info = NULL;
+ vfree(rx_ring->rx_buffer_info);
+ rx_ring->rx_buffer_info = NULL;
dev_err(dev, "Unable to allocate memory for the receive descriptor"
" ring\n");
return -ENOMEM;
@@ -2962,16 +2991,19 @@ static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
**/
static void igb_rlpml_set(struct igb_adapter *adapter)
{
- u32 max_frame_size;
+ u32 max_frame_size = adapter->max_frame_size;
struct e1000_hw *hw = &adapter->hw;
u16 pf_id = adapter->vfs_allocated_count;
- max_frame_size = adapter->max_frame_size + VLAN_TAG_SIZE;
-
- /* if vfs are enabled we set RLPML to the largest possible request
- * size and set the VMOLR RLPML to the size we need */
if (pf_id) {
igb_set_vf_rlpml(adapter, max_frame_size, pf_id);
+ /*
+ * If we're in VMDQ or SR-IOV mode, then set global RLPML
+ * to our max jumbo frame size, in case we need to enable
+ * jumbo frames on one of the rings later.
+ * This will not pass over-length frames into the default
+ * queue because it's gated by the VMOLR.RLPML.
+ */
max_frame_size = MAX_JUMBO_FRAME_SIZE;
}
@@ -3026,12 +3058,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
struct e1000_hw *hw = &adapter->hw;
u64 rdba = ring->dma;
int reg_idx = ring->reg_idx;
- u32 srrctl, rxdctl;
+ u32 srrctl = 0, rxdctl = 0;
/* disable the queue */
- rxdctl = rd32(E1000_RXDCTL(reg_idx));
- wr32(E1000_RXDCTL(reg_idx),
- rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE);
+ wr32(E1000_RXDCTL(reg_idx), 0);
/* Set DMA base address registers */
wr32(E1000_RDBAL(reg_idx),
@@ -3041,29 +3071,19 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
ring->count * sizeof(union e1000_adv_rx_desc));
/* initialize head and tail */
- ring->head = hw->hw_addr + E1000_RDH(reg_idx);
ring->tail = hw->hw_addr + E1000_RDT(reg_idx);
- writel(0, ring->head);
+ wr32(E1000_RDH(reg_idx), 0);
writel(0, ring->tail);
/* set descriptor configuration */
- if (ring->rx_buffer_len < IGB_RXBUFFER_1024) {
- srrctl = ALIGN(ring->rx_buffer_len, 64) <<
- E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
+ srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
- srrctl |= IGB_RXBUFFER_16384 >>
- E1000_SRRCTL_BSIZEPKT_SHIFT;
+ srrctl |= IGB_RXBUFFER_16384 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
#else
- srrctl |= (PAGE_SIZE / 2) >>
- E1000_SRRCTL_BSIZEPKT_SHIFT;
+ srrctl |= (PAGE_SIZE / 2) >> E1000_SRRCTL_BSIZEPKT_SHIFT;
#endif
- srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
- } else {
- srrctl = ALIGN(ring->rx_buffer_len, 1024) >>
- E1000_SRRCTL_BSIZEPKT_SHIFT;
- srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
- }
- if (hw->mac.type == e1000_82580)
+ srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
+ if (hw->mac.type >= e1000_82580)
srrctl |= E1000_SRRCTL_TIMESTAMP;
/* Only set Drop Enable if we are supporting multiple queues */
if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1)
@@ -3074,13 +3094,12 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
/* set filtering for VMDQ pools */
igb_set_vmolr(adapter, reg_idx & 0x7, true);
- /* enable receive descriptor fetching */
- rxdctl = rd32(E1000_RXDCTL(reg_idx));
- rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
- rxdctl &= 0xFFF00000;
rxdctl |= IGB_RX_PTHRESH;
rxdctl |= IGB_RX_HTHRESH << 8;
rxdctl |= IGB_RX_WTHRESH << 16;
+
+ /* enable receive descriptor fetching */
+ rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
wr32(E1000_RXDCTL(reg_idx), rxdctl);
}
@@ -3117,8 +3136,8 @@ void igb_free_tx_resources(struct igb_ring *tx_ring)
{
igb_clean_tx_ring(tx_ring);
- vfree(tx_ring->buffer_info);
- tx_ring->buffer_info = NULL;
+ vfree(tx_ring->tx_buffer_info);
+ tx_ring->tx_buffer_info = NULL;
/* if not set, then don't free */
if (!tx_ring->desc)
@@ -3144,30 +3163,26 @@ static void igb_free_all_tx_resources(struct igb_adapter *adapter)
igb_free_tx_resources(adapter->tx_ring[i]);
}
-void igb_unmap_and_free_tx_resource(struct igb_ring *tx_ring,
- struct igb_buffer *buffer_info)
+void igb_unmap_and_free_tx_resource(struct igb_ring *ring,
+ struct igb_tx_buffer *tx_buffer)
{
- if (buffer_info->dma) {
- if (buffer_info->mapped_as_page)
- dma_unmap_page(tx_ring->dev,
- buffer_info->dma,
- buffer_info->length,
- DMA_TO_DEVICE);
- else
- dma_unmap_single(tx_ring->dev,
- buffer_info->dma,
- buffer_info->length,
- DMA_TO_DEVICE);
- buffer_info->dma = 0;
- }
- if (buffer_info->skb) {
- dev_kfree_skb_any(buffer_info->skb);
- buffer_info->skb = NULL;
+ if (tx_buffer->skb) {
+ dev_kfree_skb_any(tx_buffer->skb);
+ if (tx_buffer->dma)
+ dma_unmap_single(ring->dev,
+ tx_buffer->dma,
+ tx_buffer->length,
+ DMA_TO_DEVICE);
+ } else if (tx_buffer->dma) {
+ dma_unmap_page(ring->dev,
+ tx_buffer->dma,
+ tx_buffer->length,
+ DMA_TO_DEVICE);
}
- buffer_info->time_stamp = 0;
- buffer_info->length = 0;
- buffer_info->next_to_watch = 0;
- buffer_info->mapped_as_page = false;
+ tx_buffer->next_to_watch = NULL;
+ tx_buffer->skb = NULL;
+ tx_buffer->dma = 0;
+ /* buffer_info must be completely set up in the transmit path */
}
/**
@@ -3176,21 +3191,21 @@ void igb_unmap_and_free_tx_resource(struct igb_ring *tx_ring,
**/
static void igb_clean_tx_ring(struct igb_ring *tx_ring)
{
- struct igb_buffer *buffer_info;
+ struct igb_tx_buffer *buffer_info;
unsigned long size;
- unsigned int i;
+ u16 i;
- if (!tx_ring->buffer_info)
+ if (!tx_ring->tx_buffer_info)
return;
/* Free all the Tx ring sk_buffs */
for (i = 0; i < tx_ring->count; i++) {
- buffer_info = &tx_ring->buffer_info[i];
+ buffer_info = &tx_ring->tx_buffer_info[i];
igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
}
- size = sizeof(struct igb_buffer) * tx_ring->count;
- memset(tx_ring->buffer_info, 0, size);
+ size = sizeof(struct igb_tx_buffer) * tx_ring->count;
+ memset(tx_ring->tx_buffer_info, 0, size);
/* Zero out the descriptor ring */
memset(tx_ring->desc, 0, tx_ring->size);
@@ -3221,8 +3236,8 @@ void igb_free_rx_resources(struct igb_ring *rx_ring)
{
igb_clean_rx_ring(rx_ring);
- vfree(rx_ring->buffer_info);
- rx_ring->buffer_info = NULL;
+ vfree(rx_ring->rx_buffer_info);
+ rx_ring->rx_buffer_info = NULL;
/* if not set, then don't free */
if (!rx_ring->desc)
@@ -3254,20 +3269,19 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter)
**/
static void igb_clean_rx_ring(struct igb_ring *rx_ring)
{
- struct igb_buffer *buffer_info;
unsigned long size;
- unsigned int i;
+ u16 i;
- if (!rx_ring->buffer_info)
+ if (!rx_ring->rx_buffer_info)
return;
/* Free all the Rx ring sk_buffs */
for (i = 0; i < rx_ring->count; i++) {
- buffer_info = &rx_ring->buffer_info[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,
- rx_ring->rx_buffer_len,
+ IGB_RX_HDR_LEN,
DMA_FROM_DEVICE);
buffer_info->dma = 0;
}
@@ -3290,8 +3304,8 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
}
}
- size = sizeof(struct igb_buffer) * rx_ring->count;
- memset(rx_ring->buffer_info, 0, size);
+ size = sizeof(struct igb_rx_buffer) * rx_ring->count;
+ memset(rx_ring->rx_buffer_info, 0, size);
/* Zero out the descriptor ring */
memset(rx_ring->desc, 0, rx_ring->size);
@@ -3713,16 +3727,14 @@ static void igb_watchdog_task(struct work_struct *work)
}
/* Force detection of hung controller every watchdog period */
- tx_ring->detect_tx_hung = true;
+ set_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags);
}
/* Cause software interrupt to ensure rx ring is cleaned */
if (adapter->msix_entries) {
u32 eics = 0;
- for (i = 0; i < adapter->num_q_vectors; i++) {
- struct igb_q_vector *q_vector = adapter->q_vector[i];
- eics |= q_vector->eims_value;
- }
+ for (i = 0; i < adapter->num_q_vectors; i++)
+ eics |= adapter->q_vector[i]->eims_value;
wr32(E1000_EICS, eics);
} else {
wr32(E1000_ICS, E1000_ICS_RXDMT0);
@@ -3764,33 +3776,24 @@ static void igb_update_ring_itr(struct igb_q_vector *q_vector)
int new_val = q_vector->itr_val;
int avg_wire_size = 0;
struct igb_adapter *adapter = q_vector->adapter;
- struct igb_ring *ring;
unsigned int packets;
/* For non-gigabit speeds, just fix the interrupt rate at 4000
* ints/sec - ITR timer value of 120 ticks.
*/
if (adapter->link_speed != SPEED_1000) {
- new_val = 976;
+ new_val = IGB_4K_ITR;
goto set_itr_val;
}
- ring = q_vector->rx_ring;
- if (ring) {
- packets = ACCESS_ONCE(ring->total_packets);
-
- if (packets)
- avg_wire_size = ring->total_bytes / packets;
- }
-
- ring = q_vector->tx_ring;
- if (ring) {
- packets = ACCESS_ONCE(ring->total_packets);
+ packets = q_vector->rx.total_packets;
+ if (packets)
+ avg_wire_size = q_vector->rx.total_bytes / packets;
- if (packets)
- avg_wire_size = max_t(u32, avg_wire_size,
- ring->total_bytes / packets);
- }
+ packets = q_vector->tx.total_packets;
+ if (packets)
+ avg_wire_size = max_t(u32, avg_wire_size,
+ q_vector->tx.total_bytes / packets);
/* if avg_wire_size isn't set no work was done */
if (!avg_wire_size)
@@ -3808,9 +3811,11 @@ static void igb_update_ring_itr(struct igb_q_vector *q_vector)
else
new_val = avg_wire_size / 2;
- /* when in itr mode 3 do not exceed 20K ints/sec */
- if (adapter->rx_itr_setting == 3 && new_val < 196)
- new_val = 196;
+ /* conservative mode (itr 3) eliminates the lowest_latency setting */
+ if (new_val < IGB_20K_ITR &&
+ ((q_vector->rx.ring && adapter->rx_itr_setting == 3) ||
+ (!q_vector->rx.ring && adapter->tx_itr_setting == 3)))
+ new_val = IGB_20K_ITR;
set_itr_val:
if (new_val != q_vector->itr_val) {
@@ -3818,14 +3823,10 @@ set_itr_val:
q_vector->set_itr = 1;
}
clear_counts:
- if (q_vector->rx_ring) {
- q_vector->rx_ring->total_bytes = 0;
- q_vector->rx_ring->total_packets = 0;
- }
- if (q_vector->tx_ring) {
- q_vector->tx_ring->total_bytes = 0;
- q_vector->tx_ring->total_packets = 0;
- }
+ q_vector->rx.total_bytes = 0;
+ q_vector->rx.total_packets = 0;
+ q_vector->tx.total_bytes = 0;
+ q_vector->tx.total_packets = 0;
}
/**
@@ -3841,106 +3842,102 @@ clear_counts:
* parameter (see igb_param.c)
* NOTE: These calculations are only valid when operating in a single-
* queue environment.
- * @adapter: pointer to adapter
- * @itr_setting: current q_vector->itr_val
- * @packets: the number of packets during this measurement interval
- * @bytes: the number of bytes during this measurement interval
+ * @q_vector: pointer to q_vector
+ * @ring_container: ring info to update the itr for
**/
-static unsigned int igb_update_itr(struct igb_adapter *adapter, u16 itr_setting,
- int packets, int bytes)
+static void igb_update_itr(struct igb_q_vector *q_vector,
+ struct igb_ring_container *ring_container)
{
- unsigned int retval = itr_setting;
+ unsigned int packets = ring_container->total_packets;
+ unsigned int bytes = ring_container->total_bytes;
+ u8 itrval = ring_container->itr;
+ /* no packets, exit with status unchanged */
if (packets == 0)
- goto update_itr_done;
+ return;
- switch (itr_setting) {
+ switch (itrval) {
case lowest_latency:
/* handle TSO and jumbo frames */
if (bytes/packets > 8000)
- retval = bulk_latency;
+ itrval = bulk_latency;
else if ((packets < 5) && (bytes > 512))
- retval = low_latency;
+ itrval = low_latency;
break;
case low_latency: /* 50 usec aka 20000 ints/s */
if (bytes > 10000) {
/* this if handles the TSO accounting */
if (bytes/packets > 8000) {
- retval = bulk_latency;
+ itrval = bulk_latency;
} else if ((packets < 10) || ((bytes/packets) > 1200)) {
- retval = bulk_latency;
+ itrval = bulk_latency;
} else if ((packets > 35)) {
- retval = lowest_latency;
+ itrval = lowest_latency;
}
} else if (bytes/packets > 2000) {
- retval = bulk_latency;
+ itrval = bulk_latency;
} else if (packets <= 2 && bytes < 512) {
- retval = lowest_latency;
+ itrval = lowest_latency;
}
break;
case bulk_latency: /* 250 usec aka 4000 ints/s */
if (bytes > 25000) {
if (packets > 35)
- retval = low_latency;
+ itrval = low_latency;
} else if (bytes < 1500) {
- retval = low_latency;
+ itrval = low_latency;
}
break;
}
-update_itr_done:
- return retval;
+ /* clear work counters since we have the values we need */
+ ring_container->total_bytes = 0;
+ ring_container->total_packets = 0;
+
+ /* write updated itr to ring container */
+ ring_container->itr = itrval;
}
-static void igb_set_itr(struct igb_adapter *adapter)
+static void igb_set_itr(struct igb_q_vector *q_vector)
{
- struct igb_q_vector *q_vector = adapter->q_vector[0];
- u16 current_itr;
+ struct igb_adapter *adapter = q_vector->adapter;
u32 new_itr = q_vector->itr_val;
+ u8 current_itr = 0;
/* for non-gigabit speeds, just fix the interrupt rate at 4000 */
if (adapter->link_speed != SPEED_1000) {
current_itr = 0;
- new_itr = 4000;
+ new_itr = IGB_4K_ITR;
goto set_itr_now;
}
- adapter->rx_itr = igb_update_itr(adapter,
- adapter->rx_itr,
- q_vector->rx_ring->total_packets,
- q_vector->rx_ring->total_bytes);
+ igb_update_itr(q_vector, &q_vector->tx);
+ igb_update_itr(q_vector, &q_vector->rx);
- adapter->tx_itr = igb_update_itr(adapter,
- adapter->tx_itr,
- q_vector->tx_ring->total_packets,
- q_vector->tx_ring->total_bytes);
- current_itr = max(adapter->rx_itr, adapter->tx_itr);
+ current_itr = max(q_vector->rx.itr, q_vector->tx.itr);
/* conservative mode (itr 3) eliminates the lowest_latency setting */
- if (adapter->rx_itr_setting == 3 && current_itr == lowest_latency)
+ if (current_itr == lowest_latency &&
+ ((q_vector->rx.ring && adapter->rx_itr_setting == 3) ||
+ (!q_vector->rx.ring && adapter->tx_itr_setting == 3)))
current_itr = low_latency;
switch (current_itr) {
/* counts and packets in update_itr are dependent on these numbers */
case lowest_latency:
- new_itr = 56; /* aka 70,000 ints/sec */
+ new_itr = IGB_70K_ITR; /* 70,000 ints/sec */
break;
case low_latency:
- new_itr = 196; /* aka 20,000 ints/sec */
+ new_itr = IGB_20K_ITR; /* 20,000 ints/sec */
break;
case bulk_latency:
- new_itr = 980; /* aka 4,000 ints/sec */
+ new_itr = IGB_4K_ITR; /* 4,000 ints/sec */
break;
default:
break;
}
set_itr_now:
- q_vector->rx_ring->total_bytes = 0;
- q_vector->rx_ring->total_packets = 0;
- q_vector->tx_ring->total_bytes = 0;
- q_vector->tx_ring->total_packets = 0;
-
if (new_itr != q_vector->itr_val) {
/* this attempts to bias the interrupt rate towards Bulk
* by adding intermediate steps when interrupt rate is
@@ -3948,7 +3945,7 @@ set_itr_now:
new_itr = new_itr > q_vector->itr_val ?
max((new_itr * q_vector->itr_val) /
(new_itr + (q_vector->itr_val >> 2)),
- new_itr) :
+ new_itr) :
new_itr;
/* Don't write the value here; it resets the adapter's
* internal timer, and causes us to delay far longer than
@@ -3961,35 +3958,51 @@ set_itr_now:
}
}
-#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
-#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000
-#define IGB_TX_FLAGS_VLAN_SHIFT 16
-
-static inline int igb_tso_adv(struct igb_ring *tx_ring,
- struct sk_buff *skb, u32 tx_flags, u8 *hdr_len)
+void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens,
+ u32 type_tucmd, u32 mss_l4len_idx)
{
struct e1000_adv_tx_context_desc *context_desc;
- unsigned int i;
- int err;
- struct igb_buffer *buffer_info;
- u32 info = 0, tu_cmd = 0;
- u32 mss_l4len_idx;
- u8 l4len;
+ u16 i = tx_ring->next_to_use;
+
+ context_desc = IGB_TX_CTXTDESC(tx_ring, i);
+
+ i++;
+ tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
+
+ /* set bits to identify this as an advanced context descriptor */
+ type_tucmd |= E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT;
+
+ /* For 82575, context index must be unique per ring. */
+ if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
+ mss_l4len_idx |= tx_ring->reg_idx << 4;
+
+ context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
+ context_desc->seqnum_seed = 0;
+ context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
+ context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
+}
+
+static int igb_tso(struct igb_ring *tx_ring,
+ struct igb_tx_buffer *first,
+ u8 *hdr_len)
+{
+ struct sk_buff *skb = first->skb;
+ u32 vlan_macip_lens, type_tucmd;
+ u32 mss_l4len_idx, l4len;
+
+ if (!skb_is_gso(skb))
+ return 0;
if (skb_header_cloned(skb)) {
- err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ int err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err)
return err;
}
- l4len = tcp_hdrlen(skb);
- *hdr_len += l4len;
+ /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
+ type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP;
- if (skb->protocol == htons(ETH_P_IP)) {
+ if (first->protocol == __constant_htons(ETH_P_IP)) {
struct iphdr *iph = ip_hdr(skb);
iph->tot_len = 0;
iph->check = 0;
@@ -3997,290 +4010,289 @@ static inline int igb_tso_adv(struct igb_ring *tx_ring,
iph->daddr, 0,
IPPROTO_TCP,
0);
+ type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;
+ first->tx_flags |= IGB_TX_FLAGS_TSO |
+ IGB_TX_FLAGS_CSUM |
+ IGB_TX_FLAGS_IPV4;
} else if (skb_is_gso_v6(skb)) {
ipv6_hdr(skb)->payload_len = 0;
tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr,
0, IPPROTO_TCP, 0);
+ first->tx_flags |= IGB_TX_FLAGS_TSO |
+ IGB_TX_FLAGS_CSUM;
}
- i = tx_ring->next_to_use;
-
- buffer_info = &tx_ring->buffer_info[i];
- context_desc = E1000_TX_CTXTDESC_ADV(*tx_ring, i);
- /* VLAN MACLEN IPLEN */
- if (tx_flags & IGB_TX_FLAGS_VLAN)
- info |= (tx_flags & IGB_TX_FLAGS_VLAN_MASK);
- info |= (skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT);
- *hdr_len += skb_network_offset(skb);
- info |= skb_network_header_len(skb);
- *hdr_len += skb_network_header_len(skb);
- context_desc->vlan_macip_lens = cpu_to_le32(info);
-
- /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
- tu_cmd |= (E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT);
-
- if (skb->protocol == htons(ETH_P_IP))
- tu_cmd |= E1000_ADVTXD_TUCMD_IPV4;
- tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
+ /* compute header lengths */
+ l4len = tcp_hdrlen(skb);
+ *hdr_len = skb_transport_offset(skb) + l4len;
- context_desc->type_tucmd_mlhl = cpu_to_le32(tu_cmd);
+ /* update gso size and bytecount with header size */
+ first->gso_segs = skb_shinfo(skb)->gso_segs;
+ first->bytecount += (first->gso_segs - 1) * *hdr_len;
/* MSS L4LEN IDX */
- mss_l4len_idx = (skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT);
- mss_l4len_idx |= (l4len << E1000_ADVTXD_L4LEN_SHIFT);
+ mss_l4len_idx = l4len << E1000_ADVTXD_L4LEN_SHIFT;
+ mss_l4len_idx |= skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT;
- /* For 82575, context index must be unique per ring. */
- if (tx_ring->flags & IGB_RING_FLAG_TX_CTX_IDX)
- mss_l4len_idx |= tx_ring->reg_idx << 4;
-
- context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
- context_desc->seqnum_seed = 0;
-
- buffer_info->time_stamp = jiffies;
- buffer_info->next_to_watch = i;
- buffer_info->dma = 0;
- i++;
- if (i == tx_ring->count)
- i = 0;
+ /* VLAN MACLEN IPLEN */
+ vlan_macip_lens = skb_network_header_len(skb);
+ vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK;
- tx_ring->next_to_use = i;
+ igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
- return true;
+ return 1;
}
-static inline bool igb_tx_csum_adv(struct igb_ring *tx_ring,
- struct sk_buff *skb, u32 tx_flags)
+static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first)
{
- struct e1000_adv_tx_context_desc *context_desc;
- struct device *dev = tx_ring->dev;
- struct igb_buffer *buffer_info;
- u32 info = 0, tu_cmd = 0;
- unsigned int i;
+ struct sk_buff *skb = first->skb;
+ u32 vlan_macip_lens = 0;
+ u32 mss_l4len_idx = 0;
+ u32 type_tucmd = 0;
- if ((skb->ip_summed == CHECKSUM_PARTIAL) ||
- (tx_flags & IGB_TX_FLAGS_VLAN)) {
- i = tx_ring->next_to_use;
- buffer_info = &tx_ring->buffer_info[i];
- context_desc = E1000_TX_CTXTDESC_ADV(*tx_ring, i);
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
+ if (!(first->tx_flags & IGB_TX_FLAGS_VLAN))
+ return;
+ } else {
+ u8 l4_hdr = 0;
+ switch (first->protocol) {
+ case __constant_htons(ETH_P_IP):
+ vlan_macip_lens |= skb_network_header_len(skb);
+ type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;
+ l4_hdr = ip_hdr(skb)->protocol;
+ break;
+ case __constant_htons(ETH_P_IPV6):
+ vlan_macip_lens |= skb_network_header_len(skb);
+ l4_hdr = ipv6_hdr(skb)->nexthdr;
+ break;
+ default:
+ if (unlikely(net_ratelimit())) {
+ dev_warn(tx_ring->dev,
+ "partial checksum but proto=%x!\n",
+ first->protocol);
+ }
+ break;
+ }
- if (tx_flags & IGB_TX_FLAGS_VLAN)
- info |= (tx_flags & IGB_TX_FLAGS_VLAN_MASK);
+ switch (l4_hdr) {
+ case IPPROTO_TCP:
+ type_tucmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
+ mss_l4len_idx = tcp_hdrlen(skb) <<
+ E1000_ADVTXD_L4LEN_SHIFT;
+ break;
+ case IPPROTO_SCTP:
+ type_tucmd |= E1000_ADVTXD_TUCMD_L4T_SCTP;
+ mss_l4len_idx = sizeof(struct sctphdr) <<
+ E1000_ADVTXD_L4LEN_SHIFT;
+ break;
+ case IPPROTO_UDP:
+ mss_l4len_idx = sizeof(struct udphdr) <<
+ E1000_ADVTXD_L4LEN_SHIFT;
+ break;
+ default:
+ if (unlikely(net_ratelimit())) {
+ dev_warn(tx_ring->dev,
+ "partial checksum but l4 proto=%x!\n",
+ l4_hdr);
+ }
+ break;
+ }
- info |= (skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT);
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- info |= skb_network_header_len(skb);
+ /* update TX checksum flag */
+ first->tx_flags |= IGB_TX_FLAGS_CSUM;
+ }
- context_desc->vlan_macip_lens = cpu_to_le32(info);
+ vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT;
+ vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK;
- tu_cmd |= (E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT);
+ igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
+}
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- __be16 protocol;
+static __le32 igb_tx_cmd_type(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);
- if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) {
- const struct vlan_ethhdr *vhdr =
- (const struct vlan_ethhdr*)skb->data;
+ /* set HW vlan bit if vlan is present */
+ if (tx_flags & IGB_TX_FLAGS_VLAN)
+ cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_VLE);
- protocol = vhdr->h_vlan_encapsulated_proto;
- } else {
- protocol = skb->protocol;
- }
+ /* set timestamp bit if present */
+ if (tx_flags & IGB_TX_FLAGS_TSTAMP)
+ cmd_type |= cpu_to_le32(E1000_ADVTXD_MAC_TSTAMP);
- switch (protocol) {
- case cpu_to_be16(ETH_P_IP):
- tu_cmd |= E1000_ADVTXD_TUCMD_IPV4;
- if (ip_hdr(skb)->protocol == IPPROTO_TCP)
- tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
- else if (ip_hdr(skb)->protocol == IPPROTO_SCTP)
- tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP;
- break;
- case cpu_to_be16(ETH_P_IPV6):
- /* XXX what about other V6 headers?? */
- if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
- tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
- else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP)
- tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP;
- break;
- default:
- if (unlikely(net_ratelimit()))
- dev_warn(dev,
- "partial checksum but proto=%x!\n",
- skb->protocol);
- break;
- }
- }
+ /* set segmentation bits for TSO */
+ if (tx_flags & IGB_TX_FLAGS_TSO)
+ cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_TSE);
- context_desc->type_tucmd_mlhl = cpu_to_le32(tu_cmd);
- context_desc->seqnum_seed = 0;
- if (tx_ring->flags & IGB_RING_FLAG_TX_CTX_IDX)
- context_desc->mss_l4len_idx =
- cpu_to_le32(tx_ring->reg_idx << 4);
+ return cmd_type;
+}
- buffer_info->time_stamp = jiffies;
- buffer_info->next_to_watch = i;
- buffer_info->dma = 0;
+static void igb_tx_olinfo_status(struct igb_ring *tx_ring,
+ union e1000_adv_tx_desc *tx_desc,
+ u32 tx_flags, unsigned int paylen)
+{
+ u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT;
- i++;
- if (i == tx_ring->count)
- i = 0;
- tx_ring->next_to_use = i;
+ /* 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))
+ olinfo_status |= tx_ring->reg_idx << 4;
- return true;
+ /* insert L4 checksum */
+ if (tx_flags & IGB_TX_FLAGS_CSUM) {
+ olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
+
+ /* insert IPv4 checksum */
+ if (tx_flags & IGB_TX_FLAGS_IPV4)
+ olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
}
- return false;
+
+ tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
}
-#define IGB_MAX_TXD_PWR 16
+/*
+ * The largest size we can write to the descriptor is 65535. In order to
+ * maintain a power of two alignment we have to limit ourselves to 32K.
+ */
+#define IGB_MAX_TXD_PWR 15
#define IGB_MAX_DATA_PER_TXD (1<<IGB_MAX_TXD_PWR)
-static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb,
- unsigned int first)
+static void igb_tx_map(struct igb_ring *tx_ring,
+ struct igb_tx_buffer *first,
+ const u8 hdr_len)
{
- struct igb_buffer *buffer_info;
- struct device *dev = tx_ring->dev;
- unsigned int hlen = skb_headlen(skb);
- unsigned int count = 0, i;
- unsigned int f;
- u16 gso_segs = skb_shinfo(skb)->gso_segs ?: 1;
-
- i = tx_ring->next_to_use;
-
- buffer_info = &tx_ring->buffer_info[i];
- BUG_ON(hlen >= IGB_MAX_DATA_PER_TXD);
- buffer_info->length = hlen;
- /* set time_stamp *before* dma to help avoid a possible race */
- buffer_info->time_stamp = jiffies;
- buffer_info->next_to_watch = i;
- buffer_info->dma = dma_map_single(dev, skb->data, hlen,
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, buffer_info->dma))
+ struct sk_buff *skb = first->skb;
+ struct igb_tx_buffer *tx_buffer_info;
+ union e1000_adv_tx_desc *tx_desc;
+ 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;
+ u32 tx_flags = first->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);
+
+ dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);
+ if (dma_mapping_error(tx_ring->dev, dma))
goto dma_error;
- for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
- struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[f];
- unsigned int len = frag->size;
+ /* record length, and DMA address */
+ first->length = size;
+ first->dma = dma;
+ tx_desc->read.buffer_addr = cpu_to_le64(dma);
- count++;
- i++;
- if (i == tx_ring->count)
- i = 0;
+ 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);
- buffer_info = &tx_ring->buffer_info[i];
- BUG_ON(len >= IGB_MAX_DATA_PER_TXD);
- buffer_info->length = len;
- buffer_info->time_stamp = jiffies;
- buffer_info->next_to_watch = i;
- buffer_info->mapped_as_page = true;
- buffer_info->dma = dma_map_page(dev,
- frag->page,
- frag->page_offset,
- len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(dev, buffer_info->dma))
- goto dma_error;
-
- }
-
- tx_ring->buffer_info[i].skb = skb;
- tx_ring->buffer_info[i].tx_flags = skb_shinfo(skb)->tx_flags;
- /* multiply data chunks by size of headers */
- tx_ring->buffer_info[i].bytecount = ((gso_segs - 1) * hlen) + skb->len;
- tx_ring->buffer_info[i].gso_segs = gso_segs;
- tx_ring->buffer_info[first].next_to_watch = i;
-
- return ++count;
-
-dma_error:
- dev_err(dev, "TX DMA map failed\n");
+ i++;
+ tx_desc++;
+ if (i == tx_ring->count) {
+ tx_desc = IGB_TX_DESC(tx_ring, 0);
+ i = 0;
+ }
- /* clear timestamp and dma mappings for failed buffer_info mapping */
- buffer_info->dma = 0;
- buffer_info->time_stamp = 0;
- buffer_info->length = 0;
- buffer_info->next_to_watch = 0;
- buffer_info->mapped_as_page = false;
+ dma += IGB_MAX_DATA_PER_TXD;
+ size -= IGB_MAX_DATA_PER_TXD;
- /* clear timestamp and dma mappings for remaining portion of packet */
- while (count--) {
- if (i == 0)
- i = tx_ring->count;
- i--;
- buffer_info = &tx_ring->buffer_info[i];
- igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
- }
-
- return 0;
-}
+ tx_desc->read.olinfo_status = 0;
+ tx_desc->read.buffer_addr = cpu_to_le64(dma);
+ }
-static inline void igb_tx_queue_adv(struct igb_ring *tx_ring,
- u32 tx_flags, int count, u32 paylen,
- u8 hdr_len)
-{
- union e1000_adv_tx_desc *tx_desc;
- struct igb_buffer *buffer_info;
- u32 olinfo_status = 0, cmd_type_len;
- unsigned int i = tx_ring->next_to_use;
+ if (likely(!data_len))
+ break;
- cmd_type_len = (E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_IFCS |
- E1000_ADVTXD_DCMD_DEXT);
+ tx_desc->read.cmd_type_len = cmd_type | cpu_to_le32(size);
- if (tx_flags & IGB_TX_FLAGS_VLAN)
- cmd_type_len |= E1000_ADVTXD_DCMD_VLE;
+ i++;
+ tx_desc++;
+ if (i == tx_ring->count) {
+ tx_desc = IGB_TX_DESC(tx_ring, 0);
+ i = 0;
+ }
- if (tx_flags & IGB_TX_FLAGS_TSTAMP)
- cmd_type_len |= E1000_ADVTXD_MAC_TSTAMP;
+ size = skb_frag_size(frag);
+ data_len -= size;
- if (tx_flags & IGB_TX_FLAGS_TSO) {
- cmd_type_len |= E1000_ADVTXD_DCMD_TSE;
+ 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;
- /* insert tcp checksum */
- olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
+ tx_buffer_info = &tx_ring->tx_buffer_info[i];
+ tx_buffer_info->length = size;
+ tx_buffer_info->dma = dma;
- /* insert ip checksum */
- if (tx_flags & IGB_TX_FLAGS_IPV4)
- olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
+ tx_desc->read.olinfo_status = 0;
+ tx_desc->read.buffer_addr = cpu_to_le64(dma);
- } else if (tx_flags & IGB_TX_FLAGS_CSUM) {
- olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
+ frag++;
}
- if ((tx_ring->flags & IGB_RING_FLAG_TX_CTX_IDX) &&
- (tx_flags & (IGB_TX_FLAGS_CSUM |
- IGB_TX_FLAGS_TSO |
- IGB_TX_FLAGS_VLAN)))
- olinfo_status |= tx_ring->reg_idx << 4;
+ /* write last descriptor with RS and EOP bits */
+ cmd_type |= cpu_to_le32(size) | cpu_to_le32(IGB_TXD_DCMD);
+ tx_desc->read.cmd_type_len = cmd_type;
- olinfo_status |= ((paylen - hdr_len) << E1000_ADVTXD_PAYLEN_SHIFT);
+ /* set the timestamp */
+ first->time_stamp = jiffies;
- do {
- buffer_info = &tx_ring->buffer_info[i];
- tx_desc = E1000_TX_DESC_ADV(*tx_ring, i);
- tx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
- tx_desc->read.cmd_type_len =
- cpu_to_le32(cmd_type_len | buffer_info->length);
- tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
- count--;
- i++;
- if (i == tx_ring->count)
- i = 0;
- } while (count > 0);
-
- tx_desc->read.cmd_type_len |= cpu_to_le32(IGB_ADVTXD_DCMD);
- /* 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). */
+ /*
+ * 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).
+ *
+ * We also need this memory barrier to make certain all of the
+ * status bits have been updated before next_to_watch is written.
+ */
wmb();
+ /* set next_to_watch value indicating a packet is present */
+ first->next_to_watch = tx_desc;
+
+ i++;
+ if (i == tx_ring->count)
+ i = 0;
+
tx_ring->next_to_use = i;
+
writel(i, tx_ring->tail);
+
/* we need this if more than one processor can write to our tail
* at a time, it syncronizes IO on IA64/Altix systems */
mmiowb();
+
+ return;
+
+dma_error:
+ dev_err(tx_ring->dev, "TX DMA map failed\n");
+
+ /* clear dma mappings for failed tx_buffer_info map */
+ for (;;) {
+ tx_buffer_info = &tx_ring->tx_buffer_info[i];
+ igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
+ if (tx_buffer_info == first)
+ break;
+ if (i == 0)
+ i = tx_ring->count;
+ i--;
+ }
+
+ tx_ring->next_to_use = i;
}
-static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, int size)
+static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
{
struct net_device *netdev = tx_ring->netdev;
@@ -4306,19 +4318,20 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, int size)
return 0;
}
-static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, int size)
+static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
{
if (igb_desc_unused(tx_ring) >= size)
return 0;
return __igb_maybe_stop_tx(tx_ring, size);
}
-netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
- struct igb_ring *tx_ring)
+netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
+ struct igb_ring *tx_ring)
{
- int tso = 0, count;
+ struct igb_tx_buffer *first;
+ int tso;
u32 tx_flags = 0;
- u16 first;
+ __be16 protocol = vlan_get_protocol(skb);
u8 hdr_len = 0;
/* need: 1 descriptor per page,
@@ -4331,6 +4344,12 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
+ /* record the location of the first descriptor for this packet */
+ first = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
+ first->skb = skb;
+ first->bytecount = skb->len;
+ first->gso_segs = 1;
+
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
tx_flags |= IGB_TX_FLAGS_TSTAMP;
@@ -4341,51 +4360,44 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT);
}
- if (skb->protocol == htons(ETH_P_IP))
- tx_flags |= IGB_TX_FLAGS_IPV4;
-
- first = tx_ring->next_to_use;
- if (skb_is_gso(skb)) {
- tso = igb_tso_adv(tx_ring, skb, tx_flags, &hdr_len);
-
- if (tso < 0) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
- }
-
- if (tso)
- tx_flags |= IGB_TX_FLAGS_TSO;
- else if (igb_tx_csum_adv(tx_ring, skb, tx_flags) &&
- (skb->ip_summed == CHECKSUM_PARTIAL))
- tx_flags |= IGB_TX_FLAGS_CSUM;
+ /* record initial flags and protocol */
+ first->tx_flags = tx_flags;
+ first->protocol = protocol;
- /*
- * count reflects descriptors mapped, if 0 or less then mapping error
- * has occurred and we need to rewind the descriptor queue
- */
- count = igb_tx_map_adv(tx_ring, skb, first);
- if (!count) {
- dev_kfree_skb_any(skb);
- tx_ring->buffer_info[first].time_stamp = 0;
- tx_ring->next_to_use = first;
- return NETDEV_TX_OK;
- }
+ tso = igb_tso(tx_ring, first, &hdr_len);
+ if (tso < 0)
+ goto out_drop;
+ else if (!tso)
+ igb_tx_csum(tx_ring, first);
- igb_tx_queue_adv(tx_ring, tx_flags, count, skb->len, hdr_len);
+ igb_tx_map(tx_ring, first, hdr_len);
/* Make sure there is space in the ring for the next send. */
igb_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 4);
return NETDEV_TX_OK;
+
+out_drop:
+ igb_unmap_and_free_tx_resource(tx_ring, first);
+
+ return NETDEV_TX_OK;
}
-static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb,
- struct net_device *netdev)
+static inline struct igb_ring *igb_tx_queue_mapping(struct igb_adapter *adapter,
+ struct sk_buff *skb)
+{
+ unsigned int r_idx = skb->queue_mapping;
+
+ if (r_idx >= adapter->num_tx_queues)
+ r_idx = r_idx % adapter->num_tx_queues;
+
+ return adapter->tx_ring[r_idx];
+}
+
+static netdev_tx_t igb_xmit_frame(struct sk_buff *skb,
+ struct net_device *netdev)
{
struct igb_adapter *adapter = netdev_priv(netdev);
- struct igb_ring *tx_ring;
- int r_idx = 0;
if (test_bit(__IGB_DOWN, &adapter->state)) {
dev_kfree_skb_any(skb);
@@ -4397,14 +4409,17 @@ static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb,
return NETDEV_TX_OK;
}
- r_idx = skb->queue_mapping & (IGB_ABS_MAX_TX_QUEUES - 1);
- tx_ring = adapter->multi_tx_table[r_idx];
+ /*
+ * 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))
+ return NETDEV_TX_OK;
+ skb->len = 17;
+ }
- /* This goes back to the question of how to logically map a tx queue
- * to a flow. Right now, performance is impacted slightly negatively
- * if using multiple tx queues. If the stack breaks away from a
- * single qdisc implementation, we can look at this again. */
- return igb_xmit_frame_ring_adv(skb, tx_ring);
+ return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb));
}
/**
@@ -4419,7 +4434,7 @@ static void igb_tx_timeout(struct net_device *netdev)
/* Do the reset outside of interrupt context */
adapter->tx_timeout_count++;
- if (hw->mac.type == e1000_82580)
+ if (hw->mac.type >= e1000_82580)
hw->dev_spec._82575.global_device_reset = true;
schedule_work(&adapter->reset_task);
@@ -4467,14 +4482,14 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
{
struct igb_adapter *adapter = netdev_priv(netdev);
struct pci_dev *pdev = adapter->pdev;
- int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
- u32 rx_buffer_len, i;
+ int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) {
dev_err(&pdev->dev, "Invalid MTU setting\n");
return -EINVAL;
}
+#define MAX_STD_JUMBO_FRAME_SIZE 9238
if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
dev_err(&pdev->dev, "MTU > 9216 not supported.\n");
return -EINVAL;
@@ -4486,30 +4501,6 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
/* igb_down has a dependency on max_frame_size */
adapter->max_frame_size = max_frame;
- /* 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
- */
-
- if (adapter->hw.mac.type == e1000_82580)
- max_frame += IGB_TS_HDR_LEN;
-
- if (max_frame <= IGB_RXBUFFER_1024)
- rx_buffer_len = IGB_RXBUFFER_1024;
- else if (max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE)
- rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
- else
- rx_buffer_len = IGB_RXBUFFER_128;
-
- if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN + IGB_TS_HDR_LEN) ||
- (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE + IGB_TS_HDR_LEN))
- rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE + IGB_TS_HDR_LEN;
-
- if ((adapter->hw.mac.type == e1000_82580) &&
- (rx_buffer_len == IGB_RXBUFFER_128))
- rx_buffer_len += IGB_RXBUFFER_64;
-
if (netif_running(netdev))
igb_down(adapter);
@@ -4517,9 +4508,6 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
netdev->mtu, new_mtu);
netdev->mtu = new_mtu;
- for (i = 0; i < adapter->num_rx_queues; i++)
- adapter->rx_ring[i]->rx_buffer_len = rx_buffer_len;
-
if (netif_running(netdev))
igb_up(adapter);
else
@@ -4752,12 +4740,6 @@ static irqreturn_t igb_msix_other(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
- if (adapter->vfs_allocated_count)
- wr32(E1000_IMS, E1000_IMS_LSC |
- E1000_IMS_VMMB |
- E1000_IMS_DOUTSYNC);
- else
- wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC);
wr32(E1000_EIMS, adapter->eims_other);
return IRQ_HANDLED;
@@ -4777,7 +4759,7 @@ static void igb_write_itr(struct igb_q_vector *q_vector)
if (adapter->hw.mac.type == e1000_82575)
itr_val |= itr_val << 16;
else
- itr_val |= 0x8000000;
+ itr_val |= E1000_EITR_CNT_IGNR;
writel(itr_val, q_vector->itr_register);
q_vector->set_itr = 0;
@@ -4805,8 +4787,8 @@ static void igb_update_dca(struct igb_q_vector *q_vector)
if (q_vector->cpu == cpu)
goto out_no_update;
- if (q_vector->tx_ring) {
- int q = q_vector->tx_ring->reg_idx;
+ 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;
@@ -4819,8 +4801,8 @@ static void igb_update_dca(struct igb_q_vector *q_vector)
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;
+ 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;
@@ -4904,6 +4886,109 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event,
}
#endif /* CONFIG_IGB_DCA */
+#ifdef CONFIG_PCI_IOV
+static int igb_vf_configure(struct igb_adapter *adapter, int vf)
+{
+ unsigned char mac_addr[ETH_ALEN];
+ struct pci_dev *pdev = adapter->pdev;
+ struct e1000_hw *hw = &adapter->hw;
+ struct pci_dev *pvfdev;
+ unsigned int device_id;
+ u16 thisvf_devfn;
+
+ random_ether_addr(mac_addr);
+ igb_set_vf_mac(adapter, vf, mac_addr);
+
+ switch (adapter->hw.mac.type) {
+ case e1000_82576:
+ device_id = IGB_82576_VF_DEV_ID;
+ /* VF Stride for 82576 is 2 */
+ thisvf_devfn = (pdev->devfn + 0x80 + (vf << 1)) |
+ (pdev->devfn & 1);
+ break;
+ case e1000_i350:
+ device_id = IGB_I350_VF_DEV_ID;
+ /* VF Stride for I350 is 4 */
+ thisvf_devfn = (pdev->devfn + 0x80 + (vf << 2)) |
+ (pdev->devfn & 3);
+ break;
+ default:
+ device_id = 0;
+ thisvf_devfn = 0;
+ break;
+ }
+
+ pvfdev = pci_get_device(hw->vendor_id, device_id, NULL);
+ while (pvfdev) {
+ if (pvfdev->devfn == thisvf_devfn)
+ break;
+ pvfdev = pci_get_device(hw->vendor_id,
+ device_id, pvfdev);
+ }
+
+ if (pvfdev)
+ adapter->vf_data[vf].vfdev = pvfdev;
+ else
+ dev_err(&pdev->dev,
+ "Couldn't find pci dev ptr for VF %4.4x\n",
+ thisvf_devfn);
+ return pvfdev != NULL;
+}
+
+static int igb_find_enabled_vfs(struct igb_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
+ struct pci_dev *pvfdev;
+ u16 vf_devfn = 0;
+ u16 vf_stride;
+ unsigned int device_id;
+ int vfs_found = 0;
+
+ switch (adapter->hw.mac.type) {
+ case e1000_82576:
+ device_id = IGB_82576_VF_DEV_ID;
+ /* VF Stride for 82576 is 2 */
+ vf_stride = 2;
+ break;
+ case e1000_i350:
+ device_id = IGB_I350_VF_DEV_ID;
+ /* VF Stride for I350 is 4 */
+ vf_stride = 4;
+ break;
+ default:
+ device_id = 0;
+ vf_stride = 0;
+ break;
+ }
+
+ vf_devfn = pdev->devfn + 0x80;
+ pvfdev = pci_get_device(hw->vendor_id, device_id, NULL);
+ while (pvfdev) {
+ if (pvfdev->devfn == vf_devfn)
+ vfs_found++;
+ vf_devfn += vf_stride;
+ pvfdev = pci_get_device(hw->vendor_id,
+ device_id, pvfdev);
+ }
+
+ return vfs_found;
+}
+
+static int igb_check_vf_assignment(struct igb_adapter *adapter)
+{
+ int i;
+ for (i = 0; i < adapter->vfs_allocated_count; i++) {
+ if (adapter->vf_data[i].vfdev) {
+ if (adapter->vf_data[i].vfdev->dev_flags &
+ PCI_DEV_FLAGS_ASSIGNED)
+ return true;
+ }
+ }
+ return false;
+}
+
+#endif
static void igb_ping_all_vfs(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
@@ -5101,7 +5186,6 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf)
}
adapter->vf_data[vf].vlans_enabled++;
- return 0;
}
} else {
if (i < E1000_VLVF_ARRAY_SIZE) {
@@ -5464,16 +5548,14 @@ static irqreturn_t igb_intr(int irq, void *data)
/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No
* need for the IMC write */
u32 icr = rd32(E1000_ICR);
- if (!icr)
- return IRQ_NONE; /* Not our interrupt */
-
- igb_write_itr(q_vector);
/* 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;
+ igb_write_itr(q_vector);
+
if (icr & E1000_ICR_DRSTA)
schedule_work(&adapter->reset_task);
@@ -5494,15 +5576,15 @@ static irqreturn_t igb_intr(int irq, void *data)
return IRQ_HANDLED;
}
-static inline void igb_ring_irq_enable(struct igb_q_vector *q_vector)
+void igb_ring_irq_enable(struct igb_q_vector *q_vector)
{
struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw;
- if ((q_vector->rx_ring && (adapter->rx_itr_setting & 3)) ||
- (!q_vector->rx_ring && (adapter->tx_itr_setting & 3))) {
- if (!adapter->msix_entries)
- igb_set_itr(adapter);
+ if ((q_vector->rx.ring && (adapter->rx_itr_setting & 3)) ||
+ (!q_vector->rx.ring && (adapter->tx_itr_setting & 3))) {
+ if ((adapter->num_q_vectors == 1) && !adapter->vf_data)
+ igb_set_itr(q_vector);
else
igb_update_ring_itr(q_vector);
}
@@ -5525,28 +5607,27 @@ static int igb_poll(struct napi_struct *napi, int budget)
struct igb_q_vector *q_vector = container_of(napi,
struct igb_q_vector,
napi);
- int tx_clean_complete = 1, work_done = 0;
+ bool clean_complete = true;
#ifdef CONFIG_IGB_DCA
if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
igb_update_dca(q_vector);
#endif
- if (q_vector->tx_ring)
- tx_clean_complete = igb_clean_tx_irq(q_vector);
+ if (q_vector->tx.ring)
+ clean_complete = igb_clean_tx_irq(q_vector);
- if (q_vector->rx_ring)
- igb_clean_rx_irq_adv(q_vector, &work_done, budget);
+ if (q_vector->rx.ring)
+ clean_complete &= igb_clean_rx_irq(q_vector, budget);
- if (!tx_clean_complete)
- work_done = budget;
+ /* If all work not completed, return budget and keep polling */
+ if (!clean_complete)
+ return budget;
/* If not enough Rx work done, exit the polling mode */
- if (work_done < budget) {
- napi_complete(napi);
- igb_ring_irq_enable(q_vector);
- }
+ napi_complete(napi);
+ igb_ring_irq_enable(q_vector);
- return work_done;
+ return 0;
}
/**
@@ -5568,7 +5649,7 @@ static void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
* The 82580 starts with 1ns at bit 0 in RX/TXSTMPL, shift this up to
* 24 to match clock shift we setup earlier.
*/
- if (adapter->hw.mac.type == e1000_82580)
+ if (adapter->hw.mac.type >= e1000_82580)
regval <<= IGB_82580_TSYNC_SHIFT;
ns = timecounter_cyc2time(&adapter->clock, regval);
@@ -5581,13 +5662,14 @@ static void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
/**
* igb_tx_hwtstamp - utility function which checks for TX time stamp
* @q_vector: pointer to q_vector containing needed info
- * @buffer: pointer to igb_buffer structure
+ * @buffer: pointer to igb_tx_buffer structure
*
* If we were asked to do hardware stamping and such a time stamp is
* available, then it must have been for this skb here because we only
* allow only one such packet into the queue.
*/
-static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct igb_buffer *buffer_info)
+static void igb_tx_hwtstamp(struct igb_q_vector *q_vector,
+ struct igb_tx_buffer *buffer_info)
{
struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw;
@@ -5595,7 +5677,7 @@ static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct igb_buffer *bu
u64 regval;
/* if skb does not support hw timestamp or TX stamp not valid exit */
- if (likely(!(buffer_info->tx_flags & SKBTX_HW_TSTAMP)) ||
+ if (likely(!(buffer_info->tx_flags & IGB_TX_FLAGS_TSTAMP)) ||
!(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID))
return;
@@ -5614,70 +5696,109 @@ static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct igb_buffer *bu
static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
{
struct igb_adapter *adapter = q_vector->adapter;
- struct igb_ring *tx_ring = q_vector->tx_ring;
- struct net_device *netdev = tx_ring->netdev;
- struct e1000_hw *hw = &adapter->hw;
- struct igb_buffer *buffer_info;
+ struct igb_ring *tx_ring = q_vector->tx.ring;
+ struct igb_tx_buffer *tx_buffer;
union e1000_adv_tx_desc *tx_desc, *eop_desc;
unsigned int total_bytes = 0, total_packets = 0;
- unsigned int i, eop, count = 0;
- bool cleaned = false;
-
- i = tx_ring->next_to_clean;
- eop = tx_ring->buffer_info[i].next_to_watch;
- eop_desc = E1000_TX_DESC_ADV(*tx_ring, eop);
-
- while ((eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)) &&
- (count < tx_ring->count)) {
- rmb(); /* read buffer_info after eop_desc status */
- for (cleaned = false; !cleaned; count++) {
- tx_desc = E1000_TX_DESC_ADV(*tx_ring, i);
- buffer_info = &tx_ring->buffer_info[i];
- cleaned = (i == eop);
-
- if (buffer_info->skb) {
- total_bytes += buffer_info->bytecount;
- /* gso_segs is currently only valid for tcp */
- total_packets += buffer_info->gso_segs;
- igb_tx_hwtstamp(q_vector, buffer_info);
- }
+ unsigned int budget = q_vector->tx.work_limit;
+ unsigned int i = tx_ring->next_to_clean;
+
+ if (test_bit(__IGB_DOWN, &adapter->state))
+ return true;
+
+ tx_buffer = &tx_ring->tx_buffer_info[i];
+ tx_desc = IGB_TX_DESC(tx_ring, i);
+ i -= tx_ring->count;
- igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
- tx_desc->wb.status = 0;
+ for (; budget; budget--) {
+ eop_desc = tx_buffer->next_to_watch;
+ /* prevent any other reads prior to eop_desc */
+ rmb();
+
+ /* if next_to_watch is not set then there is no work pending */
+ if (!eop_desc)
+ break;
+
+ /* if DD is not set pending work has not been completed */
+ if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)))
+ break;
+
+ /* clear next_to_watch to prevent false hangs */
+ tx_buffer->next_to_watch = NULL;
+
+ /* update the statistics for this packet */
+ total_bytes += tx_buffer->bytecount;
+ total_packets += tx_buffer->gso_segs;
+
+ /* retrieve hardware timestamp */
+ igb_tx_hwtstamp(q_vector, tx_buffer);
+
+ /* free the skb */
+ dev_kfree_skb_any(tx_buffer->skb);
+ tx_buffer->skb = NULL;
+
+ /* unmap skb header data */
+ dma_unmap_single(tx_ring->dev,
+ tx_buffer->dma,
+ tx_buffer->length,
+ DMA_TO_DEVICE);
+
+ /* clear last DMA location and unmap remaining buffers */
+ while (tx_desc != eop_desc) {
+ tx_buffer->dma = 0;
+
+ tx_buffer++;
+ tx_desc++;
i++;
- if (i == tx_ring->count)
- i = 0;
+ if (unlikely(!i)) {
+ i -= tx_ring->count;
+ tx_buffer = tx_ring->tx_buffer_info;
+ tx_desc = IGB_TX_DESC(tx_ring, 0);
+ }
+
+ /* unmap any remaining paged data */
+ if (tx_buffer->dma) {
+ dma_unmap_page(tx_ring->dev,
+ tx_buffer->dma,
+ tx_buffer->length,
+ DMA_TO_DEVICE);
+ }
+ }
+
+ /* clear last DMA location */
+ tx_buffer->dma = 0;
+
+ /* move us one more past the eop_desc for start of next pkt */
+ tx_buffer++;
+ tx_desc++;
+ i++;
+ if (unlikely(!i)) {
+ i -= tx_ring->count;
+ tx_buffer = tx_ring->tx_buffer_info;
+ tx_desc = IGB_TX_DESC(tx_ring, 0);
}
- eop = tx_ring->buffer_info[i].next_to_watch;
- eop_desc = E1000_TX_DESC_ADV(*tx_ring, eop);
}
+ i += tx_ring->count;
tx_ring->next_to_clean = i;
+ u64_stats_update_begin(&tx_ring->tx_syncp);
+ tx_ring->tx_stats.bytes += total_bytes;
+ tx_ring->tx_stats.packets += total_packets;
+ u64_stats_update_end(&tx_ring->tx_syncp);
+ q_vector->tx.total_bytes += total_bytes;
+ q_vector->tx.total_packets += total_packets;
- if (unlikely(count &&
- netif_carrier_ok(netdev) &&
- igb_desc_unused(tx_ring) >= IGB_TX_QUEUE_WAKE)) {
- /* Make sure that anybody stopping the queue after this
- * sees the new next_to_clean.
- */
- smp_mb();
- if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
- !(test_bit(__IGB_DOWN, &adapter->state))) {
- netif_wake_subqueue(netdev, tx_ring->queue_index);
+ if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) {
+ struct e1000_hw *hw = &adapter->hw;
- u64_stats_update_begin(&tx_ring->tx_syncp);
- tx_ring->tx_stats.restart_queue++;
- u64_stats_update_end(&tx_ring->tx_syncp);
- }
- }
+ eop_desc = tx_buffer->next_to_watch;
- if (tx_ring->detect_tx_hung) {
/* Detect a transmit hang in hardware, this serializes the
* check with the clearing of time_stamp and movement of i */
- tx_ring->detect_tx_hung = false;
- if (tx_ring->buffer_info[i].time_stamp &&
- time_after(jiffies, tx_ring->buffer_info[i].time_stamp +
+ clear_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags);
+ if (eop_desc &&
+ time_after(jiffies, tx_buffer->time_stamp +
(adapter->tx_timeout_factor * HZ)) &&
!(rd32(E1000_STATUS) & E1000_STATUS_TXOFF)) {
@@ -5691,50 +5812,73 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
" next_to_clean <%x>\n"
"buffer_info[next_to_clean]\n"
" time_stamp <%lx>\n"
- " next_to_watch <%x>\n"
+ " next_to_watch <%p>\n"
" jiffies <%lx>\n"
" desc.status <%x>\n",
tx_ring->queue_index,
- readl(tx_ring->head),
+ rd32(E1000_TDH(tx_ring->reg_idx)),
readl(tx_ring->tail),
tx_ring->next_to_use,
tx_ring->next_to_clean,
- tx_ring->buffer_info[eop].time_stamp,
- eop,
+ tx_buffer->time_stamp,
+ eop_desc,
jiffies,
eop_desc->wb.status);
- netif_stop_subqueue(netdev, tx_ring->queue_index);
+ netif_stop_subqueue(tx_ring->netdev,
+ tx_ring->queue_index);
+
+ /* we are about to reset, no point in enabling stuff */
+ return true;
}
}
- tx_ring->total_bytes += total_bytes;
- tx_ring->total_packets += total_packets;
- u64_stats_update_begin(&tx_ring->tx_syncp);
- tx_ring->tx_stats.bytes += total_bytes;
- tx_ring->tx_stats.packets += total_packets;
- u64_stats_update_end(&tx_ring->tx_syncp);
- return count < tx_ring->count;
+
+ if (unlikely(total_packets &&
+ netif_carrier_ok(tx_ring->netdev) &&
+ igb_desc_unused(tx_ring) >= IGB_TX_QUEUE_WAKE)) {
+ /* Make sure that anybody stopping the queue after this
+ * sees the new next_to_clean.
+ */
+ smp_mb();
+ if (__netif_subqueue_stopped(tx_ring->netdev,
+ tx_ring->queue_index) &&
+ !(test_bit(__IGB_DOWN, &adapter->state))) {
+ netif_wake_subqueue(tx_ring->netdev,
+ tx_ring->queue_index);
+
+ u64_stats_update_begin(&tx_ring->tx_syncp);
+ tx_ring->tx_stats.restart_queue++;
+ u64_stats_update_end(&tx_ring->tx_syncp);
+ }
+ }
+
+ return !!budget;
}
-static inline void igb_rx_checksum_adv(struct igb_ring *ring,
- u32 status_err, struct sk_buff *skb)
+static inline void igb_rx_checksum(struct igb_ring *ring,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
{
skb_checksum_none_assert(skb);
- /* Ignore Checksum bit is set or checksum is disabled through ethtool */
- if (!(ring->flags & IGB_RING_FLAG_RX_CSUM) ||
- (status_err & E1000_RXD_STAT_IXSM))
+ /* Ignore Checksum bit is set */
+ if (igb_test_staterr(rx_desc, E1000_RXD_STAT_IXSM))
+ return;
+
+ /* Rx checksum disabled via ethtool */
+ if (!(ring->netdev->features & NETIF_F_RXCSUM))
return;
/* TCP/UDP checksum error bit is set */
- if (status_err &
- (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) {
+ if (igb_test_staterr(rx_desc,
+ E1000_RXDEXT_STATERR_TCPE |
+ E1000_RXDEXT_STATERR_IPE)) {
/*
* work around errata with sctp packets where the TCPE aka
* L4E bit is set incorrectly on 64 byte (60 byte w/o crc)
* packets, (aka let the stack check the crc32c)
*/
- if ((skb->len == 60) &&
- (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM)) {
+ if (!((skb->len == 60) &&
+ test_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags))) {
u64_stats_update_begin(&ring->rx_syncp);
ring->rx_stats.csum_err++;
u64_stats_update_end(&ring->rx_syncp);
@@ -5743,19 +5887,34 @@ static inline void igb_rx_checksum_adv(struct igb_ring *ring,
return;
}
/* It must be a TCP or UDP packet with a valid checksum */
- if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))
+ if (igb_test_staterr(rx_desc, E1000_RXD_STAT_TCPCS |
+ E1000_RXD_STAT_UDPCS))
skb->ip_summed = CHECKSUM_UNNECESSARY;
- dev_dbg(ring->dev, "cksum success: bits %08X\n", status_err);
+ dev_dbg(ring->dev, "cksum success: bits %08X\n",
+ le32_to_cpu(rx_desc->wb.upper.status_error));
+}
+
+static inline void igb_rx_hash(struct igb_ring *ring,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ if (ring->netdev->features & NETIF_F_RXHASH)
+ skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
}
-static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
- struct sk_buff *skb)
+static void igb_rx_hwtstamp(struct igb_q_vector *q_vector,
+ union e1000_adv_rx_desc *rx_desc,
+ 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
@@ -5767,7 +5926,7 @@ static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
* If nothing went wrong, then it should have a shared tx_flags that we
* can turn into a skb_shared_hwtstamps.
*/
- if (staterr & E1000_RXDADV_STAT_TSIP) {
+ 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;
@@ -5782,8 +5941,24 @@ static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
igb_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
}
-static inline u16 igb_get_hlen(struct igb_ring *rx_ring,
- union e1000_adv_rx_desc *rx_desc)
+
+static void igb_rx_vlan(struct igb_ring *ring,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ 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);
+
+ __vlan_hwaccel_put_tag(skb, vid);
+ }
+}
+
+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
@@ -5791,247 +5966,244 @@ static inline u16 igb_get_hlen(struct igb_ring *rx_ring,
*/
u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
- if (hlen > rx_ring->rx_buffer_len)
- hlen = rx_ring->rx_buffer_len;
+ if (hlen > IGB_RX_HDR_LEN)
+ hlen = IGB_RX_HDR_LEN;
return hlen;
}
-static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
- int *work_done, int budget)
+static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
{
- struct igb_ring *rx_ring = q_vector->rx_ring;
- struct net_device *netdev = rx_ring->netdev;
- struct device *dev = rx_ring->dev;
- union e1000_adv_rx_desc *rx_desc , *next_rxd;
- struct igb_buffer *buffer_info , *next_buffer;
- struct sk_buff *skb;
- bool cleaned = false;
- int cleaned_count = 0;
- int current_node = numa_node_id();
+ 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;
- unsigned int i;
- u32 staterr;
- u16 length;
+ u16 cleaned_count = igb_desc_unused(rx_ring);
+ u16 i = rx_ring->next_to_clean;
- i = rx_ring->next_to_clean;
- buffer_info = &rx_ring->buffer_info[i];
- rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
- staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+ rx_desc = IGB_RX_DESC(rx_ring, i);
- while (staterr & E1000_RXD_STAT_DD) {
- if (*work_done >= budget)
- break;
- (*work_done)++;
- rmb(); /* read descriptor and rx_buffer_info after status DD */
+ 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;
- skb = buffer_info->skb;
- prefetch(skb->data - NET_IP_ALIGN);
buffer_info->skb = NULL;
+ prefetch(skb->data);
i++;
if (i == rx_ring->count)
i = 0;
- next_rxd = E1000_RX_DESC_ADV(*rx_ring, i);
+ next_rxd = IGB_RX_DESC(rx_ring, i);
prefetch(next_rxd);
- next_buffer = &rx_ring->buffer_info[i];
- length = le16_to_cpu(rx_desc->wb.upper.length);
- cleaned = true;
- cleaned_count++;
+ /*
+ * 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();
- if (buffer_info->dma) {
- dma_unmap_single(dev, buffer_info->dma,
- rx_ring->rx_buffer_len,
+ 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;
- if (rx_ring->rx_buffer_len >= IGB_RXBUFFER_1024) {
- skb_put(skb, length);
- goto send_up;
- }
- skb_put(skb, igb_get_hlen(rx_ring, rx_desc));
}
- if (length) {
- dma_unmap_page(dev, buffer_info->page_dma,
- PAGE_SIZE / 2, DMA_FROM_DEVICE);
- buffer_info->page_dma = 0;
+ if (rx_desc->wb.upper.length) {
+ u16 length = le16_to_cpu(rx_desc->wb.upper.length);
skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
buffer_info->page,
buffer_info->page_offset,
length);
+ skb->len += length;
+ skb->data_len += length;
+ skb->truesize += PAGE_SIZE / 2;
+
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);
- skb->len += length;
- skb->data_len += length;
- skb->truesize += length;
+ dma_unmap_page(rx_ring->dev, buffer_info->page_dma,
+ PAGE_SIZE / 2, DMA_FROM_DEVICE);
+ buffer_info->page_dma = 0;
}
- if (!(staterr & E1000_RXD_STAT_EOP)) {
+ 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;
}
-send_up:
- if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
- dev_kfree_skb_irq(skb);
+
+ if (igb_test_staterr(rx_desc,
+ E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
+ dev_kfree_skb_any(skb);
goto next_desc;
}
- if (staterr & (E1000_RXDADV_STAT_TSIP | E1000_RXDADV_STAT_TS))
- igb_rx_hwtstamp(q_vector, staterr, skb);
+ igb_rx_hwtstamp(q_vector, rx_desc, skb);
+ igb_rx_hash(rx_ring, rx_desc, skb);
+ igb_rx_checksum(rx_ring, rx_desc, skb);
+ igb_rx_vlan(rx_ring, rx_desc, skb);
+
total_bytes += skb->len;
total_packets++;
- igb_rx_checksum_adv(rx_ring, staterr, skb);
-
- skb->protocol = eth_type_trans(skb, netdev);
- skb_record_rx_queue(skb, rx_ring->queue_index);
-
- if (staterr & E1000_RXD_STAT_VP) {
- u16 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);
+ budget--;
next_desc:
- rx_desc->wb.upper.status_error = 0;
+ if (!budget)
+ break;
+ 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_adv(rx_ring, cleaned_count);
+ igb_alloc_rx_buffers(rx_ring, cleaned_count);
cleaned_count = 0;
}
/* use prefetched values */
rx_desc = next_rxd;
- buffer_info = next_buffer;
- staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
}
rx_ring->next_to_clean = i;
- cleaned_count = igb_desc_unused(rx_ring);
-
- if (cleaned_count)
- igb_alloc_rx_buffers_adv(rx_ring, cleaned_count);
-
- rx_ring->total_packets += total_packets;
- rx_ring->total_bytes += total_bytes;
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);
- return cleaned;
+ 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 !!budget;
+}
+
+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;
+
+ if (dma)
+ return true;
+
+ 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;
+ }
+
+ /* initialize skb for ring */
+ skb_record_rx_queue(skb, rx_ring->queue_index);
+ }
+
+ dma = dma_map_single(rx_ring->dev, skb->data,
+ IGB_RX_HDR_LEN, DMA_FROM_DEVICE);
+
+ if (dma_mapping_error(rx_ring->dev, dma)) {
+ rx_ring->rx_stats.alloc_failed++;
+ return false;
+ }
+
+ bi->dma = dma;
+ return true;
+}
+
+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);
+
+ if (page_dma)
+ return true;
+
+ if (!page) {
+ page = netdev_alloc_page(rx_ring->netdev);
+ bi->page = page;
+ 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);
+
+ 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;
+ return true;
}
/**
- * igb_alloc_rx_buffers_adv - Replace used receive buffers; packet split
+ * igb_alloc_rx_buffers - Replace used receive buffers; packet split
* @adapter: address of board private structure
**/
-void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count)
+void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
{
- struct net_device *netdev = rx_ring->netdev;
union e1000_adv_rx_desc *rx_desc;
- struct igb_buffer *buffer_info;
- struct sk_buff *skb;
- unsigned int i;
- int bufsz;
+ struct igb_rx_buffer *bi;
+ u16 i = rx_ring->next_to_use;
- i = rx_ring->next_to_use;
- buffer_info = &rx_ring->buffer_info[i];
-
- bufsz = rx_ring->rx_buffer_len;
+ rx_desc = IGB_RX_DESC(rx_ring, i);
+ bi = &rx_ring->rx_buffer_info[i];
+ i -= rx_ring->count;
while (cleaned_count--) {
- rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
-
- if ((bufsz < IGB_RXBUFFER_1024) && !buffer_info->page_dma) {
- if (!buffer_info->page) {
- buffer_info->page = netdev_alloc_page(netdev);
- if (unlikely(!buffer_info->page)) {
- u64_stats_update_begin(&rx_ring->rx_syncp);
- rx_ring->rx_stats.alloc_failed++;
- u64_stats_update_end(&rx_ring->rx_syncp);
- goto no_buffers;
- }
- buffer_info->page_offset = 0;
- } else {
- buffer_info->page_offset ^= PAGE_SIZE / 2;
- }
- buffer_info->page_dma =
- dma_map_page(rx_ring->dev, buffer_info->page,
- buffer_info->page_offset,
- PAGE_SIZE / 2,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(rx_ring->dev,
- buffer_info->page_dma)) {
- buffer_info->page_dma = 0;
- u64_stats_update_begin(&rx_ring->rx_syncp);
- rx_ring->rx_stats.alloc_failed++;
- u64_stats_update_end(&rx_ring->rx_syncp);
- goto no_buffers;
- }
- }
+ if (!igb_alloc_mapped_skb(rx_ring, bi))
+ break;
- skb = buffer_info->skb;
- if (!skb) {
- skb = netdev_alloc_skb_ip_align(netdev, bufsz);
- if (unlikely(!skb)) {
- u64_stats_update_begin(&rx_ring->rx_syncp);
- rx_ring->rx_stats.alloc_failed++;
- u64_stats_update_end(&rx_ring->rx_syncp);
- goto no_buffers;
- }
+ /* 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);
- buffer_info->skb = skb;
- }
- if (!buffer_info->dma) {
- buffer_info->dma = dma_map_single(rx_ring->dev,
- skb->data,
- bufsz,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(rx_ring->dev,
- buffer_info->dma)) {
- buffer_info->dma = 0;
- u64_stats_update_begin(&rx_ring->rx_syncp);
- rx_ring->rx_stats.alloc_failed++;
- u64_stats_update_end(&rx_ring->rx_syncp);
- goto no_buffers;
- }
- }
- /* Refresh the desc even if buffer_addrs didn't change because
- * each write-back erases this info. */
- if (bufsz < IGB_RXBUFFER_1024) {
- rx_desc->read.pkt_addr =
- cpu_to_le64(buffer_info->page_dma);
- rx_desc->read.hdr_addr = cpu_to_le64(buffer_info->dma);
- } else {
- rx_desc->read.pkt_addr = cpu_to_le64(buffer_info->dma);
- rx_desc->read.hdr_addr = 0;
- }
+ if (!igb_alloc_mapped_page(rx_ring, bi))
+ break;
+
+ rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
+ rx_desc++;
+ bi++;
i++;
- if (i == rx_ring->count)
- i = 0;
- buffer_info = &rx_ring->buffer_info[i];
+ if (unlikely(!i)) {
+ rx_desc = IGB_RX_DESC(rx_ring, 0);
+ bi = rx_ring->rx_buffer_info;
+ i -= rx_ring->count;
+ }
+
+ /* clear the hdr_addr for the next_to_use descriptor */
+ rx_desc->read.hdr_addr = 0;
}
-no_buffers:
+ i += rx_ring->count;
+
if (rx_ring->next_to_use != i) {
rx_ring->next_to_use = i;
- if (i == 0)
- i = (rx_ring->count - 1);
- else
- i--;
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
@@ -6168,6 +6340,7 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,
tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2;
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
is_l2 = true;
+ is_l4 = true;
break;
default:
return -ERANGE;
@@ -6184,7 +6357,7 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,
* timestamped, so enable timestamping in all packets as
* long as one rx filter was configured.
*/
- if ((hw->mac.type == e1000_82580) && tsync_rx_ctl) {
+ if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) {
tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED;
tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
}
@@ -6299,10 +6472,9 @@ static void igb_vlan_mode(struct net_device *netdev, u32 features)
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
u32 ctrl, rctl;
+ bool enable = !!(features & NETIF_F_HW_VLAN_RX);
- igb_irq_disable(adapter);
-
- if (features & NETIF_F_HW_VLAN_RX) {
+ if (enable) {
/* enable VLAN tag insert/strip */
ctrl = rd32(E1000_CTRL);
ctrl |= E1000_CTRL_VME;
@@ -6320,9 +6492,6 @@ static void igb_vlan_mode(struct net_device *netdev, u32 features)
}
igb_rlpml_set(adapter);
-
- if (!test_bit(__IGB_DOWN, &adapter->state))
- igb_irq_enable(adapter);
}
static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
@@ -6347,11 +6516,6 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
int pf_id = adapter->vfs_allocated_count;
s32 err;
- igb_irq_disable(adapter);
-
- if (!test_bit(__IGB_DOWN, &adapter->state))
- igb_irq_enable(adapter);
-
/* remove vlan from VLVF table array */
err = igb_vlvf_set(adapter, vid, false, pf_id);
@@ -6366,6 +6530,8 @@ static void igb_restore_vlan(struct igb_adapter *adapter)
{
u16 vid;
+ igb_vlan_mode(adapter->netdev, adapter->netdev->features);
+
for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
igb_vlan_rx_add_vid(adapter->netdev, vid);
}
@@ -6577,18 +6743,15 @@ static void igb_netpoll(struct net_device *netdev)
{
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
+ struct igb_q_vector *q_vector;
int i;
- if (!adapter->msix_entries) {
- struct igb_q_vector *q_vector = adapter->q_vector[0];
- igb_irq_disable(adapter);
- napi_schedule(&q_vector->napi);
- return;
- }
-
for (i = 0; i < adapter->num_q_vectors; i++) {
- struct igb_q_vector *q_vector = adapter->q_vector[i];
- wr32(E1000_EIMC, q_vector->eims_value);
+ q_vector = adapter->q_vector[i];
+ if (adapter->msix_entries)
+ wr32(E1000_EIMC, q_vector->eims_value);
+ else
+ igb_irq_disable(adapter);
napi_schedule(&q_vector->napi);
}
}
@@ -6887,4 +7050,70 @@ static void igb_vmm_control(struct igb_adapter *adapter)
}
}
+static void igb_init_dmac(struct igb_adapter *adapter, u32 pba)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 dmac_thr;
+ u16 hwm;
+
+ if (hw->mac.type > e1000_82580) {
+ if (adapter->flags & IGB_FLAG_DMAC) {
+ u32 reg;
+
+ /* force threshold to 0. */
+ wr32(E1000_DMCTXTH, 0);
+
+ /*
+ * DMA Coalescing high water mark needs to be higher
+ * than the RX threshold. set hwm to PBA - 2 * max
+ * frame size
+ */
+ hwm = pba - (2 * adapter->max_frame_size);
+ reg = rd32(E1000_DMACR);
+ reg &= ~E1000_DMACR_DMACTHR_MASK;
+ dmac_thr = pba - 4;
+
+ reg |= ((dmac_thr << E1000_DMACR_DMACTHR_SHIFT)
+ & E1000_DMACR_DMACTHR_MASK);
+
+ /* transition to L0x or L1 if available..*/
+ reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK);
+
+ /* watchdog timer= +-1000 usec in 32usec intervals */
+ reg |= (1000 >> 5);
+ wr32(E1000_DMACR, reg);
+
+ /*
+ * no lower threshold to disable
+ * coalescing(smart fifb)-UTRESH=0
+ */
+ wr32(E1000_DMCRTRH, 0);
+ wr32(E1000_FCRTC, hwm);
+
+ reg = (IGB_DMCTLX_DCFLUSH_DIS | 0x4);
+
+ wr32(E1000_DMCTLX, reg);
+
+ /*
+ * free space in tx packet buffer to wake from
+ * DMA coal
+ */
+ wr32(E1000_DMCTXTH, (IGB_MIN_TXPBSIZE -
+ (IGB_TX_BUF_4096 + adapter->max_frame_size)) >> 6);
+
+ /*
+ * make low power state decision controlled
+ * by DMA coal
+ */
+ reg = rd32(E1000_PCIEMISC);
+ reg &= ~E1000_PCIEMISC_LX_DECISION;
+ wr32(E1000_PCIEMISC, reg);
+ } /* endif adapter->dmac is not disabled */
+ } else if (hw->mac.type == e1000_82580) {
+ u32 reg = rd32(E1000_PCIEMISC);
+ wr32(E1000_PCIEMISC, reg & ~E1000_PCIEMISC_LX_DECISION);
+ wr32(E1000_DMACR, 0);
+ }
+}
+
/* igb_main.c */
diff --git a/drivers/net/igbvf/Makefile b/drivers/net/ethernet/intel/igbvf/Makefile
index 0fa3db3dd8b6..0fa3db3dd8b6 100644
--- a/drivers/net/igbvf/Makefile
+++ b/drivers/net/ethernet/intel/igbvf/Makefile
diff --git a/drivers/net/igbvf/defines.h b/drivers/net/ethernet/intel/igbvf/defines.h
index 79f2604673fe..79f2604673fe 100644
--- a/drivers/net/igbvf/defines.h
+++ b/drivers/net/ethernet/intel/igbvf/defines.h
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c
index b0b14d63dfbf..2c25858cc0ff 100644
--- a/drivers/net/igbvf/ethtool.c
+++ b/drivers/net/ethernet/intel/igbvf/ethtool.c
@@ -128,55 +128,6 @@ static int igbvf_set_pauseparam(struct net_device *netdev,
return -EOPNOTSUPP;
}
-static u32 igbvf_get_rx_csum(struct net_device *netdev)
-{
- struct igbvf_adapter *adapter = netdev_priv(netdev);
- return !(adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED);
-}
-
-static int igbvf_set_rx_csum(struct net_device *netdev, u32 data)
-{
- struct igbvf_adapter *adapter = netdev_priv(netdev);
-
- if (data)
- adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
- else
- adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
-
- return 0;
-}
-
-static u32 igbvf_get_tx_csum(struct net_device *netdev)
-{
- return (netdev->features & NETIF_F_IP_CSUM) != 0;
-}
-
-static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
-{
- if (data)
- netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
- else
- netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
- return 0;
-}
-
-static int igbvf_set_tso(struct net_device *netdev, u32 data)
-{
- struct igbvf_adapter *adapter = netdev_priv(netdev);
-
- if (data) {
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
- } else {
- netdev->features &= ~NETIF_F_TSO;
- netdev->features &= ~NETIF_F_TSO6;
- }
-
- dev_info(&adapter->pdev->dev, "TSO is %s\n",
- data ? "Enabled" : "Disabled");
- return 0;
-}
-
static u32 igbvf_get_msglevel(struct net_device *netdev)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
@@ -259,12 +210,8 @@ static void igbvf_get_ringparam(struct net_device *netdev,
ring->rx_max_pending = IGBVF_MAX_RXD;
ring->tx_max_pending = IGBVF_MAX_TXD;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = rx_ring->count;
ring->tx_pending = tx_ring->count;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
static int igbvf_set_ringparam(struct net_device *netdev,
@@ -511,14 +458,6 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
.set_ringparam = igbvf_set_ringparam,
.get_pauseparam = igbvf_get_pauseparam,
.set_pauseparam = igbvf_set_pauseparam,
- .get_rx_csum = igbvf_get_rx_csum,
- .set_rx_csum = igbvf_set_rx_csum,
- .get_tx_csum = igbvf_get_tx_csum,
- .set_tx_csum = igbvf_set_tx_csum,
- .get_sg = ethtool_op_get_sg,
- .set_sg = ethtool_op_set_sg,
- .get_tso = ethtool_op_get_tso,
- .set_tso = igbvf_set_tso,
.self_test = igbvf_diag_test,
.get_sset_count = igbvf_get_sset_count,
.get_strings = igbvf_get_strings,
diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h
index fd4a7b780fdd..fd4a7b780fdd 100644
--- a/drivers/net/igbvf/igbvf.h
+++ b/drivers/net/ethernet/intel/igbvf/igbvf.h
diff --git a/drivers/net/igbvf/mbx.c b/drivers/net/ethernet/intel/igbvf/mbx.c
index 3d6f4cc3998a..048aae248d06 100644
--- a/drivers/net/igbvf/mbx.c
+++ b/drivers/net/ethernet/intel/igbvf/mbx.c
@@ -288,7 +288,7 @@ out_no_write:
* @msg: The message buffer
* @size: Length of buffer
*
- * returns SUCCESS if it successfuly read message from buffer
+ * returns SUCCESS if it successfully read message from buffer
**/
static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
{
diff --git a/drivers/net/igbvf/mbx.h b/drivers/net/ethernet/intel/igbvf/mbx.h
index c2883c45d477..c2883c45d477 100644
--- a/drivers/net/igbvf/mbx.h
+++ b/drivers/net/ethernet/intel/igbvf/mbx.h
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 40ed066e3ef4..cca78124be31 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -45,13 +45,13 @@
#include "igbvf.h"
-#define DRV_VERSION "2.0.0-k"
+#define DRV_VERSION "2.0.1-k"
char igbvf_driver_name[] = "igbvf";
const char igbvf_driver_version[] = DRV_VERSION;
static const char igbvf_driver_string[] =
- "Intel(R) Virtual Function Network Driver";
+ "Intel(R) Gigabit Virtual Function Network Driver";
static const char igbvf_copyright[] =
- "Copyright (c) 2009 - 2010 Intel Corporation.";
+ "Copyright (c) 2009 - 2011 Intel Corporation.";
static int igbvf_poll(struct napi_struct *napi, int budget);
static void igbvf_reset(struct igbvf_adapter *);
@@ -102,8 +102,8 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
{
if (status & E1000_RXD_STAT_VP) {
u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
-
- __vlan_hwaccel_put_tag(skb, vid);
+ if (test_bit(vid, adapter->active_vlans))
+ __vlan_hwaccel_put_tag(skb, vid);
}
netif_receive_skb(skb);
}
@@ -312,7 +312,7 @@ static bool igbvf_clean_rx_irq(struct igbvf_adapter *adapter,
skb->len += length;
skb->data_len += length;
- skb->truesize += length;
+ skb->truesize += PAGE_SIZE / 2;
}
send_up:
i++;
@@ -2045,7 +2045,7 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter,
for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
- struct skb_frag_struct *frag;
+ const struct skb_frag_struct *frag;
count++;
i++;
@@ -2053,7 +2053,7 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter,
i = 0;
frag = &skb_shinfo(skb)->frags[f];
- len = frag->size;
+ len = skb_frag_size(frag);
buffer_info = &tx_ring->buffer_info[i];
BUG_ON(len >= IGBVF_MAX_DATA_PER_TXD);
@@ -2061,10 +2061,7 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter,
buffer_info->time_stamp = jiffies;
buffer_info->next_to_watch = i;
buffer_info->mapped_as_page = true;
- buffer_info->dma = dma_map_page(&pdev->dev,
- frag->page,
- frag->page_offset,
- len,
+ buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag, 0, len,
DMA_TO_DEVICE);
if (dma_mapping_error(&pdev->dev, buffer_info->dma))
goto dma_error;
@@ -2528,9 +2525,23 @@ static void igbvf_print_device_info(struct igbvf_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- dev_info(&pdev->dev, "Intel(R) 82576 Virtual Function\n");
+ if (hw->mac.type == e1000_vfadapt_i350)
+ dev_info(&pdev->dev, "Intel(R) I350 Virtual Function\n");
+ else
+ dev_info(&pdev->dev, "Intel(R) 82576 Virtual Function\n");
dev_info(&pdev->dev, "Address: %pM\n", netdev->dev_addr);
- dev_info(&pdev->dev, "MAC: %d\n", hw->mac.type);
+}
+
+static int igbvf_set_features(struct net_device *netdev, u32 features)
+{
+ struct igbvf_adapter *adapter = netdev_priv(netdev);
+
+ if (features & NETIF_F_RXCSUM)
+ adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
+ else
+ adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
+
+ return 0;
}
static const struct net_device_ops igbvf_netdev_ops = {
@@ -2538,7 +2549,7 @@ static const struct net_device_ops igbvf_netdev_ops = {
.ndo_stop = igbvf_close,
.ndo_start_xmit = igbvf_xmit_frame,
.ndo_get_stats = igbvf_get_stats,
- .ndo_set_multicast_list = igbvf_set_multi,
+ .ndo_set_rx_mode = igbvf_set_multi,
.ndo_set_mac_address = igbvf_set_mac,
.ndo_change_mtu = igbvf_change_mtu,
.ndo_do_ioctl = igbvf_ioctl,
@@ -2548,6 +2559,7 @@ static const struct net_device_ops igbvf_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = igbvf_netpoll,
#endif
+ .ndo_set_features = igbvf_set_features,
};
/**
@@ -2655,16 +2667,18 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
adapter->bd_number = cards_found++;
- netdev->features = NETIF_F_SG |
+ netdev->hw_features = NETIF_F_SG |
NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM |
+ NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_RXCSUM;
+
+ netdev->features = netdev->hw_features |
NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
- netdev->features |= NETIF_F_IPV6_CSUM;
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
-
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
@@ -2852,7 +2866,7 @@ module_exit(igbvf_exit_module);
MODULE_AUTHOR("Intel Corporation, <e1000-devel@lists.sourceforge.net>");
-MODULE_DESCRIPTION("Intel(R) 82576 Virtual Function Network Driver");
+MODULE_DESCRIPTION("Intel(R) Gigabit Virtual Function Network Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/net/igbvf/regs.h b/drivers/net/ethernet/intel/igbvf/regs.h
index 77e18d3d6b15..77e18d3d6b15 100644
--- a/drivers/net/igbvf/regs.h
+++ b/drivers/net/ethernet/intel/igbvf/regs.h
diff --git a/drivers/net/igbvf/vf.c b/drivers/net/ethernet/intel/igbvf/vf.c
index af3822f9ea9a..af3822f9ea9a 100644
--- a/drivers/net/igbvf/vf.c
+++ b/drivers/net/ethernet/intel/igbvf/vf.c
diff --git a/drivers/net/igbvf/vf.h b/drivers/net/ethernet/intel/igbvf/vf.h
index d7ed58fcd9bb..d7ed58fcd9bb 100644
--- a/drivers/net/igbvf/vf.h
+++ b/drivers/net/ethernet/intel/igbvf/vf.h
diff --git a/drivers/net/ixgb/Makefile b/drivers/net/ethernet/intel/ixgb/Makefile
index 0b20c5e62ffe..0b20c5e62ffe 100644
--- a/drivers/net/ixgb/Makefile
+++ b/drivers/net/ethernet/intel/ixgb/Makefile
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ethernet/intel/ixgb/ixgb.h
index 49e8408f05fc..cb23448fe2fa 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ethernet/intel/ixgb/ixgb.h
@@ -204,6 +204,8 @@ extern void ixgb_set_ethtool_ops(struct net_device *netdev);
extern char ixgb_driver_name[];
extern const char ixgb_driver_version[];
+extern void ixgb_set_speed_duplex(struct net_device *netdev);
+
extern int ixgb_up(struct ixgb_adapter *adapter);
extern void ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog);
extern void ixgb_reset(struct ixgb_adapter *adapter);
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ethernet/intel/ixgb/ixgb_ee.c
index 38b362b67857..2ed925f38811 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_ee.c
@@ -559,7 +559,7 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
ENTER();
if (ixgb_check_and_get_eeprom_data(hw) == true) {
- for (i = 0; i < IXGB_ETH_LENGTH_OF_ADDRESS; i++) {
+ for (i = 0; i < ETH_ALEN; i++) {
mac_addr[i] = ee_map->mac_addr[i];
}
pr_debug("eeprom mac address = %pM\n", mac_addr);
diff --git a/drivers/net/ixgb/ixgb_ee.h b/drivers/net/ethernet/intel/ixgb/ixgb_ee.h
index 7ea12652f471..5680f64314b8 100644
--- a/drivers/net/ixgb/ixgb_ee.h
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_ee.h
@@ -31,8 +31,6 @@
#define IXGB_EEPROM_SIZE 64 /* Size in words */
-#define IXGB_ETH_LENGTH_OF_ADDRESS 6
-
/* EEPROM Commands */
#define EEPROM_READ_OPCODE 0x6 /* EEPROM read opcode */
#define EEPROM_WRITE_OPCODE 0x5 /* EEPROM write opcode */
@@ -75,7 +73,7 @@
/* EEPROM structure */
struct ixgb_ee_map_type {
- u8 mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];
+ u8 mac_addr[ETH_ALEN];
__le16 compatibility;
__le16 reserved1[4];
__le32 pba_number;
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
index 6da890b9534c..9dfce7dff79b 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
@@ -115,7 +115,7 @@ ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
return 0;
}
-static void ixgb_set_speed_duplex(struct net_device *netdev)
+void ixgb_set_speed_duplex(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev_priv(netdev);
/* be optimistic about our link, since we were up before */
@@ -195,57 +195,6 @@ ixgb_set_pauseparam(struct net_device *netdev,
}
static u32
-ixgb_get_rx_csum(struct net_device *netdev)
-{
- struct ixgb_adapter *adapter = netdev_priv(netdev);
-
- return adapter->rx_csum;
-}
-
-static int
-ixgb_set_rx_csum(struct net_device *netdev, u32 data)
-{
- struct ixgb_adapter *adapter = netdev_priv(netdev);
-
- adapter->rx_csum = data;
-
- if (netif_running(netdev)) {
- ixgb_down(adapter, true);
- ixgb_up(adapter);
- ixgb_set_speed_duplex(netdev);
- } else
- ixgb_reset(adapter);
- return 0;
-}
-
-static u32
-ixgb_get_tx_csum(struct net_device *netdev)
-{
- return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int
-ixgb_set_tx_csum(struct net_device *netdev, u32 data)
-{
- if (data)
- netdev->features |= NETIF_F_HW_CSUM;
- else
- netdev->features &= ~NETIF_F_HW_CSUM;
-
- return 0;
-}
-
-static int
-ixgb_set_tso(struct net_device *netdev, u32 data)
-{
- if (data)
- netdev->features |= NETIF_F_TSO;
- else
- netdev->features &= ~NETIF_F_TSO;
- return 0;
-}
-
-static u32
ixgb_get_msglevel(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev_priv(netdev);
@@ -543,12 +492,8 @@ ixgb_get_ringparam(struct net_device *netdev,
ring->rx_max_pending = MAX_RXD;
ring->tx_max_pending = MAX_TXD;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = rxdr->count;
ring->tx_pending = txdr->count;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
static int
@@ -685,43 +630,6 @@ ixgb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
}
}
-static int ixgb_set_flags(struct net_device *netdev, u32 data)
-{
- struct ixgb_adapter *adapter = netdev_priv(netdev);
- bool need_reset;
- int rc;
-
- /*
- * Tx VLAN insertion does not work per HW design when Rx stripping is
- * disabled. Disable txvlan when rxvlan is turned off, and enable
- * rxvlan when txvlan is turned on.
- */
- if (!(data & ETH_FLAG_RXVLAN) &&
- (netdev->features & NETIF_F_HW_VLAN_TX))
- data &= ~ETH_FLAG_TXVLAN;
- else if (data & ETH_FLAG_TXVLAN)
- data |= ETH_FLAG_RXVLAN;
-
- need_reset = (data & ETH_FLAG_RXVLAN) !=
- (netdev->features & NETIF_F_HW_VLAN_RX);
-
- rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_RXVLAN |
- ETH_FLAG_TXVLAN);
- if (rc)
- return rc;
-
- if (need_reset) {
- if (netif_running(netdev)) {
- ixgb_down(adapter, true);
- ixgb_up(adapter);
- ixgb_set_speed_duplex(netdev);
- } else
- ixgb_reset(adapter);
- }
-
- return 0;
-}
-
static const struct ethtool_ops ixgb_ethtool_ops = {
.get_settings = ixgb_get_settings,
.set_settings = ixgb_set_settings,
@@ -736,20 +644,12 @@ static const struct ethtool_ops ixgb_ethtool_ops = {
.set_ringparam = ixgb_set_ringparam,
.get_pauseparam = ixgb_get_pauseparam,
.set_pauseparam = ixgb_set_pauseparam,
- .get_rx_csum = ixgb_get_rx_csum,
- .set_rx_csum = ixgb_set_rx_csum,
- .get_tx_csum = ixgb_get_tx_csum,
- .set_tx_csum = ixgb_set_tx_csum,
- .set_sg = ethtool_op_set_sg,
.get_msglevel = ixgb_get_msglevel,
.set_msglevel = ixgb_set_msglevel,
- .set_tso = ixgb_set_tso,
.get_strings = ixgb_get_strings,
.set_phys_id = ixgb_set_phys_id,
.get_sset_count = ixgb_get_sset_count,
.get_ethtool_stats = ixgb_get_ethtool_stats,
- .get_flags = ethtool_op_get_flags,
- .set_flags = ixgb_set_flags,
};
void ixgb_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ethernet/intel/ixgb/ixgb_hw.c
index 3d61a9e4faf7..99b69adb4a0f 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_hw.c
@@ -478,7 +478,7 @@ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
ixgb_mta_set(hw, hash_value);
}
- mca += IXGB_ETH_LENGTH_OF_ADDRESS + pad;
+ mca += ETH_ALEN + pad;
}
pr_debug("MC Update Complete\n");
diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ethernet/intel/ixgb/ixgb_hw.h
index 873d32b89fba..2a99a35c33aa 100644
--- a/drivers/net/ixgb/ixgb_hw.h
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_hw.h
@@ -97,8 +97,6 @@ typedef enum {
ixgb_bus_width_64
} ixgb_bus_width;
-#define IXGB_ETH_LENGTH_OF_ADDRESS 6
-
#define IXGB_EEPROM_SIZE 64 /* Size in words */
#define SPEED_10000 10000
@@ -674,7 +672,7 @@ struct ixgb_hw {
u32 max_frame_size; /* Maximum frame size supported */
u32 mc_filter_type; /* Multicast filter hash type */
u32 num_mc_addrs; /* Number of current Multicast addrs */
- u8 curr_mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS]; /* Individual address currently programmed in MAC */
+ u8 curr_mac_addr[ETH_ALEN]; /* Individual address currently programmed in MAC */
u32 num_tx_desc; /* Number of Transmit descriptors */
u32 num_rx_desc; /* Number of Receive descriptors */
u32 rx_buffer_size; /* Size of Receive buffer */
diff --git a/drivers/net/ixgb/ixgb_ids.h b/drivers/net/ethernet/intel/ixgb/ixgb_ids.h
index 2a58847f46e8..2a58847f46e8 100644
--- a/drivers/net/ixgb/ixgb_ids.h
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_ids.h
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 6a130eb51cfa..e21148f8b160 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -325,12 +325,47 @@ ixgb_reset(struct ixgb_adapter *adapter)
}
}
+static u32
+ixgb_fix_features(struct net_device *netdev, u32 features)
+{
+ /*
+ * Tx VLAN insertion does not work per HW design when Rx stripping is
+ * disabled.
+ */
+ if (!(features & NETIF_F_HW_VLAN_RX))
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+static int
+ixgb_set_features(struct net_device *netdev, u32 features)
+{
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ u32 changed = features ^ netdev->features;
+
+ if (!(changed & (NETIF_F_RXCSUM|NETIF_F_HW_VLAN_RX)))
+ return 0;
+
+ adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
+
+ if (netif_running(netdev)) {
+ ixgb_down(adapter, true);
+ ixgb_up(adapter);
+ ixgb_set_speed_duplex(netdev);
+ } else
+ ixgb_reset(adapter);
+
+ return 0;
+}
+
+
static const struct net_device_ops ixgb_netdev_ops = {
.ndo_open = ixgb_open,
.ndo_stop = ixgb_close,
.ndo_start_xmit = ixgb_xmit_frame,
.ndo_get_stats = ixgb_get_stats,
- .ndo_set_multicast_list = ixgb_set_multi,
+ .ndo_set_rx_mode = ixgb_set_multi,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ixgb_set_mac,
.ndo_change_mtu = ixgb_change_mtu,
@@ -340,6 +375,8 @@ static const struct net_device_ops ixgb_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ixgb_netpoll,
#endif
+ .ndo_fix_features = ixgb_fix_features,
+ .ndo_set_features = ixgb_set_features,
};
/**
@@ -439,12 +476,14 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_sw_init;
- netdev->features = NETIF_F_SG |
+ netdev->hw_features = NETIF_F_SG |
+ NETIF_F_TSO |
NETIF_F_HW_CSUM |
NETIF_F_HW_VLAN_TX |
- NETIF_F_HW_VLAN_RX |
+ NETIF_F_HW_VLAN_RX;
+ netdev->features = netdev->hw_features |
NETIF_F_HW_VLAN_FILTER;
- netdev->features |= NETIF_F_TSO;
+ netdev->hw_features |= NETIF_F_RXCSUM;
if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
@@ -1068,7 +1107,6 @@ ixgb_set_multi(struct net_device *netdev)
struct ixgb_hw *hw = &adapter->hw;
struct netdev_hw_addr *ha;
u32 rctl;
- int i;
/* Check for Promiscuous and All Multicast modes */
@@ -1095,19 +1133,27 @@ ixgb_set_multi(struct net_device *netdev)
rctl |= IXGB_RCTL_MPE;
IXGB_WRITE_REG(hw, RCTL, rctl);
} else {
- u8 mta[IXGB_MAX_NUM_MULTICAST_ADDRESSES *
- IXGB_ETH_LENGTH_OF_ADDRESS];
+ u8 *mta = kmalloc(IXGB_MAX_NUM_MULTICAST_ADDRESSES *
+ ETH_ALEN, GFP_ATOMIC);
+ u8 *addr;
+ if (!mta) {
+ pr_err("allocation of multicast memory failed\n");
+ goto alloc_failed;
+ }
IXGB_WRITE_REG(hw, RCTL, rctl);
- i = 0;
- netdev_for_each_mc_addr(ha, netdev)
- memcpy(&mta[i++ * IXGB_ETH_LENGTH_OF_ADDRESS],
- ha->addr, IXGB_ETH_LENGTH_OF_ADDRESS);
+ addr = mta;
+ netdev_for_each_mc_addr(ha, netdev) {
+ memcpy(addr, ha->addr, ETH_ALEN);
+ addr += ETH_ALEN;
+ }
ixgb_mc_addr_list_update(hw, mta, netdev_mc_count(netdev), 0);
+ kfree(mta);
}
+alloc_failed:
if (netdev->features & NETIF_F_HW_VLAN_RX)
ixgb_vlan_strip_enable(adapter);
else
@@ -1337,11 +1383,11 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
}
for (f = 0; f < nr_frags; f++) {
- struct skb_frag_struct *frag;
+ const struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[f];
- len = frag->size;
- offset = frag->page_offset;
+ len = skb_frag_size(frag);
+ offset = 0;
while (len) {
i++;
@@ -1361,8 +1407,8 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
buffer_info->time_stamp = jiffies;
buffer_info->mapped_as_page = true;
buffer_info->dma =
- dma_map_page(&pdev->dev, frag->page,
- offset, size, DMA_TO_DEVICE);
+ skb_frag_dma_map(&pdev->dev, frag, offset, size,
+ DMA_TO_DEVICE);
if (dma_mapping_error(&pdev->dev, buffer_info->dma))
goto dma_error;
buffer_info->next_to_watch = 0;
diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ethernet/intel/ixgb/ixgb_osdep.h
index e361185920ef..8fc905192231 100644
--- a/drivers/net/ixgb/ixgb_osdep.h
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_osdep.h
@@ -38,6 +38,7 @@
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
+#include <linux/if_ether.h>
#undef ASSERT
#define ASSERT(x) BUG_ON(!(x))
diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ethernet/intel/ixgb/ixgb_param.c
index dd7fbeb1f7d1..07d83ab46e21 100644
--- a/drivers/net/ixgb/ixgb_param.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_param.c
@@ -267,7 +267,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
}
{ /* Transmit Descriptor Count */
- const struct ixgb_option opt = {
+ static const struct ixgb_option opt = {
.type = range_option,
.name = "Transmit Descriptors",
.err = "using default of " __MODULE_STRING(DEFAULT_TXD),
@@ -286,7 +286,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
tx_ring->count = ALIGN(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
}
{ /* Receive Descriptor Count */
- const struct ixgb_option opt = {
+ static const struct ixgb_option opt = {
.type = range_option,
.name = "Receive Descriptors",
.err = "using default of " __MODULE_STRING(DEFAULT_RXD),
@@ -305,7 +305,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
rx_ring->count = ALIGN(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
}
{ /* Receive Checksum Offload Enable */
- const struct ixgb_option opt = {
+ static const struct ixgb_option opt = {
.type = enable_option,
.name = "Receive Checksum Offload",
.err = "defaulting to Enabled",
@@ -348,7 +348,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
}
}
{ /* Receive Flow Control High Threshold */
- const struct ixgb_option opt = {
+ static const struct ixgb_option opt = {
.type = range_option,
.name = "Rx Flow Control High Threshold",
.err = "using default of " __MODULE_STRING(DEFAULT_FCRTH),
@@ -367,7 +367,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
pr_info("Ignoring RxFCHighThresh when no RxFC\n");
}
{ /* Receive Flow Control Low Threshold */
- const struct ixgb_option opt = {
+ static const struct ixgb_option opt = {
.type = range_option,
.name = "Rx Flow Control Low Threshold",
.err = "using default of " __MODULE_STRING(DEFAULT_FCRTL),
@@ -386,7 +386,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
pr_info("Ignoring RxFCLowThresh when no RxFC\n");
}
{ /* Flow Control Pause Time Request*/
- const struct ixgb_option opt = {
+ static const struct ixgb_option opt = {
.type = range_option,
.name = "Flow Control Pause Time Request",
.err = "using default of "__MODULE_STRING(DEFAULT_FCPAUSE),
@@ -416,7 +416,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
}
}
{ /* Receive Interrupt Delay */
- const struct ixgb_option opt = {
+ static const struct ixgb_option opt = {
.type = range_option,
.name = "Receive Interrupt Delay",
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
@@ -433,7 +433,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
}
}
{ /* Transmit Interrupt Delay */
- const struct ixgb_option opt = {
+ static const struct ixgb_option opt = {
.type = range_option,
.name = "Transmit Interrupt Delay",
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
@@ -451,7 +451,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
}
{ /* Transmit Interrupt Delay Enable */
- const struct ixgb_option opt = {
+ static const struct ixgb_option opt = {
.type = enable_option,
.name = "Tx Interrupt Delay Enable",
.err = "defaulting to Enabled",
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile
index 7d7387fbdecd..7d7387fbdecd 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ethernet/intel/ixgbe/Makefile
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index e04a8e49e6dc..a8368d5cf686 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -53,6 +53,7 @@
/* TX/RX descriptor defines */
#define IXGBE_DEFAULT_TXD 512
+#define IXGBE_DEFAULT_TX_WORK 256
#define IXGBE_MAX_TXD 4096
#define IXGBE_MIN_TXD 64
@@ -71,10 +72,13 @@
/* Supported Rx Buffer Sizes */
#define IXGBE_RXBUFFER_512 512 /* Used for packet split */
-#define IXGBE_RXBUFFER_2048 2048
-#define IXGBE_RXBUFFER_4096 4096
-#define IXGBE_RXBUFFER_8192 8192
-#define IXGBE_MAX_RXBUFFER 16384 /* largest size for a single descriptor */
+#define IXGBE_RXBUFFER_2K 2048
+#define IXGBE_RXBUFFER_3K 3072
+#define IXGBE_RXBUFFER_4K 4096
+#define IXGBE_RXBUFFER_7K 7168
+#define IXGBE_RXBUFFER_8K 8192
+#define IXGBE_RXBUFFER_15K 15360
+#define IXGBE_MAX_RXBUFFER 16384 /* largest size for a single descriptor */
/*
* NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN mans we
@@ -91,13 +95,17 @@
#define IXGBE_RX_BUFFER_WRITE 16 /* Must be power of 2 */
#define IXGBE_TX_FLAGS_CSUM (u32)(1)
-#define IXGBE_TX_FLAGS_VLAN (u32)(1 << 1)
-#define IXGBE_TX_FLAGS_TSO (u32)(1 << 2)
-#define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3)
-#define IXGBE_TX_FLAGS_FCOE (u32)(1 << 4)
-#define IXGBE_TX_FLAGS_FSO (u32)(1 << 5)
+#define IXGBE_TX_FLAGS_HW_VLAN (u32)(1 << 1)
+#define IXGBE_TX_FLAGS_SW_VLAN (u32)(1 << 2)
+#define IXGBE_TX_FLAGS_TSO (u32)(1 << 3)
+#define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 4)
+#define IXGBE_TX_FLAGS_FCOE (u32)(1 << 5)
+#define IXGBE_TX_FLAGS_FSO (u32)(1 << 6)
+#define IXGBE_TX_FLAGS_TXSW (u32)(1 << 7)
+#define IXGBE_TX_FLAGS_MAPPED_AS_PAGE (u32)(1 << 8)
#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000
-#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000
+#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000
+#define IXGBE_TX_FLAGS_VLAN_PRIO_SHIFT 29
#define IXGBE_TX_FLAGS_VLAN_SHIFT 16
#define IXGBE_MAX_RSC_INT_RATE 162760
@@ -108,6 +116,8 @@
#define MAX_EMULATION_MAC_ADDRS 16
#define IXGBE_MAX_PF_MACVLANS 15
#define VMDQ_P(p) ((p) + adapter->num_vfs)
+#define IXGBE_82599_VF_DEVICE_ID 0x10ED
+#define IXGBE_X540_VF_DEVICE_ID 0x1515
struct vf_data_storage {
unsigned char vf_mac_addresses[ETH_ALEN];
@@ -120,6 +130,9 @@ struct vf_data_storage {
u16 pf_vlan; /* When set, guest VLAN config not allowed. */
u16 pf_qos;
u16 tx_rate;
+ u16 vlan_count;
+ u8 spoofchk_enabled;
+ struct pci_dev *vfdev;
};
struct vf_macvlans {
@@ -141,14 +154,14 @@ struct vf_macvlans {
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
struct ixgbe_tx_buffer {
- struct sk_buff *skb;
- dma_addr_t dma;
+ union ixgbe_adv_tx_desc *next_to_watch;
unsigned long time_stamp;
- u16 length;
- u16 next_to_watch;
- unsigned int bytecount;
+ dma_addr_t dma;
+ u32 length;
+ u32 tx_flags;
+ struct sk_buff *skb;
+ u32 bytecount;
u16 gso_segs;
- u8 mapped_as_page;
};
struct ixgbe_rx_buffer {
@@ -206,6 +219,7 @@ enum ixbge_ring_state_t {
#define clear_ring_rsc_enabled(ring) \
clear_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
struct ixgbe_ring {
+ struct ixgbe_ring *next; /* pointer to next ring in q_vector */
void *desc; /* descriptor ring memory */
struct device *dev; /* device for DMA mapping */
struct net_device *netdev; /* netdev ring belongs to */
@@ -274,11 +288,7 @@ struct ixgbe_ring_feature {
} ____cacheline_internodealigned_in_smp;
struct ixgbe_ring_container {
-#if MAX_RX_QUEUES > MAX_TX_QUEUES
- DECLARE_BITMAP(idx, MAX_RX_QUEUES);
-#else
- DECLARE_BITMAP(idx, MAX_TX_QUEUES);
-#endif
+ struct ixgbe_ring *ring; /* pointer to linked list of rings */
unsigned int total_bytes; /* total bytes processed this int */
unsigned int total_packets; /* total packets processed this int */
u16 work_limit; /* total work allowed per interrupt */
@@ -295,26 +305,29 @@ struct ixgbe_ring_container {
*/
struct ixgbe_q_vector {
struct ixgbe_adapter *adapter;
- unsigned int v_idx; /* index of q_vector within array, also used for
- * finding the bit in EICR and friends that
- * represents the vector for this ring */
#ifdef CONFIG_IXGBE_DCA
int cpu; /* CPU for DCA */
#endif
- struct napi_struct napi;
+ u16 v_idx; /* index of q_vector within array, also used for
+ * finding the bit in EICR and friends that
+ * represents the vector for this ring */
+ u16 itr; /* Interrupt throttle rate written to EITR */
struct ixgbe_ring_container rx, tx;
- u32 eitr;
+
+ struct napi_struct napi;
cpumask_var_t affinity_mask;
char name[IFNAMSIZ + 9];
};
-/* Helper macros to switch between ints/sec and what the register uses.
- * And yes, it's the same math going both ways. The lowest value
- * supported by all of the ixgbe hardware is 8.
+/*
+ * microsecond values for various ITR rates shifted by 2 to fit itr register
+ * with the first 3 bits reserved 0
*/
-#define EITR_INTS_PER_SEC_TO_REG(_eitr) \
- ((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8)
-#define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG
+#define IXGBE_MIN_RSC_ITR 24
+#define IXGBE_100K_ITR 40
+#define IXGBE_20K_ITR 200
+#define IXGBE_10K_ITR 400
+#define IXGBE_8K_ITR 500
static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring)
{
@@ -484,12 +497,13 @@ struct ixgbe_adapter {
u64 rsc_total_count;
u64 rsc_total_flush;
u32 wol;
- u16 eeprom_version;
+ u16 eeprom_verh;
+ u16 eeprom_verl;
+ u16 eeprom_cap;
int node;
u32 led_reg;
u32 interrupt_event;
- char lsc_int_name[IFNAMSIZ + 9];
/* SR-IOV */
DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
@@ -498,11 +512,12 @@ struct ixgbe_adapter {
int vf_rate_link_speed;
struct vf_macvlans vf_mvs;
struct vf_macvlans *mv_list;
- bool antispoofing_enabled;
struct hlist_head fdir_filter_list;
union ixgbe_atr_input fdir_mask;
int fdir_filter_count;
+ u32 timer_event_accumulator;
+ u32 vferr_refcount;
};
struct ixgbe_fdir_filter {
@@ -546,7 +561,7 @@ extern int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
extern char ixgbe_driver_name[];
extern const char ixgbe_driver_version[];
-extern int ixgbe_up(struct ixgbe_adapter *adapter);
+extern void ixgbe_up(struct ixgbe_adapter *adapter);
extern void ixgbe_down(struct ixgbe_adapter *adapter);
extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter);
extern void ixgbe_reset(struct ixgbe_adapter *adapter);
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index 0d4e38264492..ef2afefb0cd4 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -307,7 +307,6 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
switch (hw->phy.type) {
case ixgbe_phy_cu_unknown:
case ixgbe_phy_tn:
- case ixgbe_phy_aq:
media_type = ixgbe_media_type_copper;
goto out;
default:
@@ -358,7 +357,6 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
u32 fctrl_reg;
u32 rmcs_reg;
u32 reg;
- u32 rx_pba_size;
u32 link_speed = 0;
bool link_up;
@@ -461,16 +459,13 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
/* Set up and enable Rx high/low water mark thresholds, enable XON. */
if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
- rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
- rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
-
- reg = (rx_pba_size - hw->fc.low_water) << 6;
+ reg = hw->fc.low_water << 6;
if (hw->fc.send_xon)
reg |= IXGBE_FCRTL_XONE;
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg);
- reg = (rx_pba_size - hw->fc.high_water) << 6;
+ reg = hw->fc.high_water[packetbuf_num] << 6;
reg |= IXGBE_FCRTH_FCEN;
IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg);
@@ -654,11 +649,6 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
(ixgbe_validate_link_ready(hw) != 0))
*link_up = false;
- /* if link is down, zero out the current_mode */
- if (*link_up == false) {
- hw->fc.current_mode = ixgbe_fc_none;
- hw->fc.fc_was_autonegged = false;
- }
out:
return 0;
}
@@ -759,7 +749,9 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
u8 analog_val;
/* Call adapter stop to disable tx/rx and clear interrupts */
- hw->mac.ops.stop_adapter(hw);
+ status = hw->mac.ops.stop_adapter(hw);
+ if (status != 0)
+ goto reset_hw_out;
/*
* Power up the Atlas Tx lanes if they are currently powered down.
@@ -802,26 +794,19 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
phy_status = hw->phy.ops.init(hw);
if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
goto reset_hw_out;
- else if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
- goto no_phy_reset;
+ if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
+ goto mac_reset_top;
hw->phy.ops.reset(hw);
}
-no_phy_reset:
- /*
- * Prevent the PCI-E bus from from hanging by disabling PCI-E master
- * access and verify no pending requests before reset
- */
- ixgbe_disable_pcie_master(hw);
-
mac_reset_top:
/*
* Issue global reset to the MAC. This needs to be a SW reset.
* If link reset is used, it might reset the MAC when mng is using it
*/
- ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
- IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST));
+ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL) | IXGBE_CTRL_RST;
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
IXGBE_WRITE_FLUSH(hw);
/* Poll for reset bit to self-clear indicating reset is complete */
@@ -836,21 +821,18 @@ mac_reset_top:
hw_dbg(hw, "Reset polling failed to complete.\n");
}
+ msleep(50);
+
/*
* Double resets are required for recovery from certain error
* conditions. Between resets, it is necessary to stall to allow time
- * for any pending HW events to complete. We use 1usec since that is
- * what is needed for ixgbe_disable_pcie_master(). The second reset
- * then clears out any effects of those events.
+ * for any pending HW events to complete.
*/
if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
- udelay(1);
goto mac_reset_top;
}
- msleep(50);
-
gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR);
gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6));
IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr);
@@ -1129,7 +1111,6 @@ static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
* physical layer because 10GBase-T PHYs use LMS = KX4/KX */
switch (hw->phy.type) {
case ixgbe_phy_tn:
- case ixgbe_phy_aq:
case ixgbe_phy_cu_unknown:
hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE,
MDIO_MMD_PMAPMD, &ext_ability);
@@ -1324,6 +1305,8 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
.init_params = &ixgbe_init_eeprom_params_generic,
.read = &ixgbe_read_eerd_generic,
+ .write = &ixgbe_write_eeprom_generic,
+ .write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic,
.read_buffer = &ixgbe_read_eerd_buffer_generic,
.calc_checksum = &ixgbe_calc_eeprom_checksum_generic,
.validate_checksum = &ixgbe_validate_eeprom_checksum_generic,
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 34f30ec79c2e..4ae26a748da0 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -217,10 +217,6 @@ static s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
phy->ops.get_firmware_version =
&ixgbe_get_phy_firmware_version_tnx;
break;
- case ixgbe_phy_aq:
- phy->ops.get_firmware_version =
- &ixgbe_get_phy_firmware_version_generic;
- break;
default:
break;
}
@@ -340,7 +336,6 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
switch (hw->phy.type) {
case ixgbe_phy_cu_unknown:
case ixgbe_phy_tn:
- case ixgbe_phy_aq:
media_type = ixgbe_media_type_copper;
goto out;
default:
@@ -361,6 +356,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82599_SFP_FCOE:
case IXGBE_DEV_ID_82599_SFP_EM:
case IXGBE_DEV_ID_82599_SFP_SF2:
+ case IXGBE_DEV_ID_82599EN_SFP:
media_type = ixgbe_media_type_fiber;
break;
case IXGBE_DEV_ID_82599_CX4:
@@ -904,14 +900,18 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
**/
static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
{
- s32 status = 0;
- u32 ctrl;
- u32 i;
- u32 autoc;
- u32 autoc2;
+ ixgbe_link_speed link_speed;
+ s32 status;
+ u32 ctrl, i, autoc, autoc2;
+ bool link_up = false;
/* Call adapter stop to disable tx/rx and clear interrupts */
- hw->mac.ops.stop_adapter(hw);
+ status = hw->mac.ops.stop_adapter(hw);
+ if (status != 0)
+ goto reset_hw_out;
+
+ /* flush pending Tx transactions */
+ ixgbe_clear_tx_pending(hw);
/* PHY ops must be identified and initialized prior to reset */
@@ -934,48 +934,49 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
hw->phy.ops.reset(hw);
- /*
- * Prevent the PCI-E bus from from hanging by disabling PCI-E master
- * access and verify no pending requests before reset
- */
- ixgbe_disable_pcie_master(hw);
-
mac_reset_top:
/*
- * Issue global reset to the MAC. This needs to be a SW reset.
- * If link reset is used, it might reset the MAC when mng is using it
+ * Issue global reset to the MAC. Needs to be SW reset if link is up.
+ * If link reset is used when link is up, it might reset the PHY when
+ * mng is using it. If link is down or the flag to force full link
+ * reset is set, then perform link reset.
*/
- ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
- IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST));
+ ctrl = IXGBE_CTRL_LNK_RST;
+ if (!hw->force_full_reset) {
+ hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
+ if (link_up)
+ ctrl = IXGBE_CTRL_RST;
+ }
+
+ ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
IXGBE_WRITE_FLUSH(hw);
/* Poll for reset bit to self-clear indicating reset is complete */
for (i = 0; i < 10; i++) {
udelay(1);
ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
- if (!(ctrl & IXGBE_CTRL_RST))
+ if (!(ctrl & IXGBE_CTRL_RST_MASK))
break;
}
- if (ctrl & IXGBE_CTRL_RST) {
+
+ if (ctrl & IXGBE_CTRL_RST_MASK) {
status = IXGBE_ERR_RESET_FAILED;
hw_dbg(hw, "Reset polling failed to complete.\n");
}
+ msleep(50);
+
/*
* Double resets are required for recovery from certain error
* conditions. Between resets, it is necessary to stall to allow time
- * for any pending HW events to complete. We use 1usec since that is
- * what is needed for ixgbe_disable_pcie_master(). The second reset
- * then clears out any effects of those events.
+ * for any pending HW events to complete.
*/
if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
- udelay(1);
goto mac_reset_top;
}
- msleep(50);
-
/*
* Store the original AUTOC/AUTOC2 values if they have not been
* stored off yet. Otherwise restore the stored original
@@ -1108,79 +1109,6 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
}
/**
- * ixgbe_set_fdir_rxpba_82599 - Initialize Flow Director Rx packet buffer
- * @hw: pointer to hardware structure
- * @pballoc: which mode to allocate filters with
- **/
-static s32 ixgbe_set_fdir_rxpba_82599(struct ixgbe_hw *hw, const u32 pballoc)
-{
- u32 fdir_pbsize = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT;
- u32 current_rxpbsize = 0;
- int i;
-
- /* reserve space for Flow Director filters */
- switch (pballoc) {
- case IXGBE_FDIR_PBALLOC_256K:
- fdir_pbsize -= 256 << IXGBE_RXPBSIZE_SHIFT;
- break;
- case IXGBE_FDIR_PBALLOC_128K:
- fdir_pbsize -= 128 << IXGBE_RXPBSIZE_SHIFT;
- break;
- case IXGBE_FDIR_PBALLOC_64K:
- fdir_pbsize -= 64 << IXGBE_RXPBSIZE_SHIFT;
- break;
- case IXGBE_FDIR_PBALLOC_NONE:
- default:
- return IXGBE_ERR_PARAM;
- }
-
- /* determine current RX packet buffer size */
- for (i = 0; i < 8; i++)
- current_rxpbsize += IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
-
- /* if there is already room for the filters do nothing */
- if (current_rxpbsize <= fdir_pbsize)
- return 0;
-
- if (current_rxpbsize > hw->mac.rx_pb_size) {
- /*
- * if rxpbsize is greater than max then HW max the Rx buffer
- * sizes are unconfigured or misconfigured since HW default is
- * to give the full buffer to each traffic class resulting in
- * the total size being buffer size 8x actual size
- *
- * This assumes no DCB since the RXPBSIZE registers appear to
- * be unconfigured.
- */
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), fdir_pbsize);
- for (i = 1; i < 8; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
- } else {
- /*
- * Since the Rx packet buffer appears to have already been
- * configured we need to shrink each packet buffer by enough
- * to make room for the filters. As such we take each rxpbsize
- * value and multiply it by a fraction representing the size
- * needed over the size we currently have.
- *
- * We need to reduce fdir_pbsize and current_rxpbsize to
- * 1/1024 of their original values in order to avoid
- * overflowing the u32 being used to store rxpbsize.
- */
- fdir_pbsize >>= IXGBE_RXPBSIZE_SHIFT;
- current_rxpbsize >>= IXGBE_RXPBSIZE_SHIFT;
- for (i = 0; i < 8; i++) {
- u32 rxpbsize = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
- rxpbsize *= fdir_pbsize;
- rxpbsize /= current_rxpbsize;
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpbsize);
- }
- }
-
- return 0;
-}
-
-/**
* ixgbe_fdir_enable_82599 - Initialize Flow Director control registers
* @hw: pointer to hardware structure
* @fdirctrl: value to write to flow director control register
@@ -1227,13 +1155,6 @@ static void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl)
**/
s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
{
- s32 err;
-
- /* Before enabling Flow Director, verify the Rx Packet Buffer size */
- err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
- if (err)
- return err;
-
/*
* Continue setup of fdirctrl register bits:
* Move the flexible bytes to use the ethertype - shift 6 words
@@ -1258,13 +1179,6 @@ s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
**/
s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl)
{
- s32 err;
-
- /* Before enabling Flow Director, verify the Rx Packet Buffer size */
- err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
- if (err)
- return err;
-
/*
* Continue setup of fdirctrl register bits:
* Turn perfect match filtering on
@@ -1886,7 +1800,6 @@ static u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
switch (hw->phy.type) {
case ixgbe_phy_tn:
- case ixgbe_phy_aq:
case ixgbe_phy_cu_unknown:
hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
&ext_ability);
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index fc1375f26fe5..834f044be4c3 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -61,6 +61,7 @@ static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data);
static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
u16 offset);
+static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
/**
* ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
@@ -225,8 +226,9 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
IXGBE_READ_REG(hw, IXGBE_GORCH);
IXGBE_READ_REG(hw, IXGBE_GOTCL);
IXGBE_READ_REG(hw, IXGBE_GOTCH);
- for (i = 0; i < 8; i++)
- IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ for (i = 0; i < 8; i++)
+ IXGBE_READ_REG(hw, IXGBE_RNBC(i));
IXGBE_READ_REG(hw, IXGBE_RUC);
IXGBE_READ_REG(hw, IXGBE_RFC);
IXGBE_READ_REG(hw, IXGBE_ROC);
@@ -495,7 +497,6 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
**/
s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
{
- u32 number_of_queues;
u32 reg_val;
u16 i;
@@ -506,35 +507,35 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
hw->adapter_stopped = true;
/* Disable the receive unit */
- reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
- reg_val &= ~(IXGBE_RXCTRL_RXEN);
- IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val);
- IXGBE_WRITE_FLUSH(hw);
- usleep_range(2000, 4000);
+ IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, 0);
- /* Clear interrupt mask to stop from interrupts being generated */
+ /* Clear interrupt mask to stop interrupts from being generated */
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
- /* Clear any pending interrupts */
+ /* Clear any pending interrupts, flush previous writes */
IXGBE_READ_REG(hw, IXGBE_EICR);
/* Disable the transmit unit. Each queue must be disabled. */
- number_of_queues = hw->mac.max_tx_queues;
- for (i = 0; i < number_of_queues; i++) {
- reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
- if (reg_val & IXGBE_TXDCTL_ENABLE) {
- reg_val &= ~IXGBE_TXDCTL_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), reg_val);
- }
+ for (i = 0; i < hw->mac.max_tx_queues; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH);
+
+ /* Disable the receive unit by stopping each queue */
+ for (i = 0; i < hw->mac.max_rx_queues; i++) {
+ reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
+ reg_val &= ~IXGBE_RXDCTL_ENABLE;
+ reg_val |= IXGBE_RXDCTL_SWFLSH;
+ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val);
}
+ /* flush all queues disables */
+ IXGBE_WRITE_FLUSH(hw);
+ usleep_range(1000, 2000);
+
/*
* Prevent the PCI-E bus from from hanging by disabling PCI-E master
* access and verify no pending requests
*/
- ixgbe_disable_pcie_master(hw);
-
- return 0;
+ return ixgbe_disable_pcie_master(hw);
}
/**
@@ -1931,7 +1932,6 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
s32 ret_val = 0;
u32 mflcn_reg, fccfg_reg;
u32 reg;
- u32 rx_pba_size;
u32 fcrtl, fcrth;
#ifdef CONFIG_DCB
@@ -2011,11 +2011,8 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
- rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
- rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
-
- fcrth = (rx_pba_size - hw->fc.high_water) << 10;
- fcrtl = (rx_pba_size - hw->fc.low_water) << 10;
+ fcrth = hw->fc.high_water[packetbuf_num] << 10;
+ fcrtl = hw->fc.low_water << 10;
if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
fcrth |= IXGBE_FCRTH_FCEN;
@@ -2121,8 +2118,8 @@ static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
*/
linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
- if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
- ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+ if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+ (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
goto out;
}
@@ -2292,7 +2289,9 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
* Validate the water mark configuration. Zero water marks are invalid
* because it causes the controller to just blast out fc packets.
*/
- if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
+ if (!hw->fc.low_water ||
+ !hw->fc.high_water[packetbuf_num] ||
+ !hw->fc.pause_time) {
hw_dbg(hw, "Invalid water mark configuration\n");
ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
goto out;
@@ -2457,75 +2456,57 @@ out:
* bit hasn't caused the master requests to be disabled, else 0
* is returned signifying master requests disabled.
**/
-s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
+static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
{
struct ixgbe_adapter *adapter = hw->back;
- u32 i;
- u32 reg_val;
- u32 number_of_queues;
s32 status = 0;
- u16 dev_status = 0;
+ u32 i;
+ u16 value;
- /* Just jump out if bus mastering is already disabled */
+ /* Always set this bit to ensure any future transactions are blocked */
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS);
+
+ /* Exit if master requests are blocked */
if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
goto out;
- /* Disable the receive unit by stopping each queue */
- number_of_queues = hw->mac.max_rx_queues;
- for (i = 0; i < number_of_queues; i++) {
- reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
- if (reg_val & IXGBE_RXDCTL_ENABLE) {
- reg_val &= ~IXGBE_RXDCTL_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val);
- }
- }
-
- reg_val = IXGBE_READ_REG(hw, IXGBE_CTRL);
- reg_val |= IXGBE_CTRL_GIO_DIS;
- IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val);
-
+ /* Poll for master request bit to clear */
for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
- if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
- goto check_device_status;
udelay(100);
+ if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+ goto out;
}
+ /*
+ * Two consecutive resets are required via CTRL.RST per datasheet
+ * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine
+ * of this need. The first reset prevents new master requests from
+ * being issued by our device. We then must wait 1usec or more for any
+ * remaining completions from the PCIe bus to trickle in, and then reset
+ * again to clear out any effects they may have had on our device.
+ */
hw_dbg(hw, "GIO Master Disable bit didn't clear - requesting resets\n");
- status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+ hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
/*
* Before proceeding, make sure that the PCIe block does not have
* transactions pending.
*/
-check_device_status:
for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
- pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_STATUS,
- &dev_status);
- if (!(dev_status & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
- break;
udelay(100);
+ pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_STATUS,
+ &value);
+ if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
+ goto out;
}
- if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT)
- hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n");
- else
- goto out;
-
- /*
- * Two consecutive resets are required via CTRL.RST per datasheet
- * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine
- * of this need. The first reset prevents new master requests from
- * being issued by our device. We then must wait 1usec for any
- * remaining completions from the PCIe bus to trickle in, and then reset
- * again to clear out any effects they may have had on our device.
- */
- hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+ hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n");
+ status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
out:
return status;
}
-
/**
* ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
* @hw: pointer to hardware structure
@@ -3114,12 +3095,6 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
else
*speed = IXGBE_LINK_SPEED_UNKNOWN;
- /* if link is down, zero out the current_mode */
- if (*link_up == false) {
- hw->fc.current_mode = ixgbe_fc_none;
- hw->fc.fc_was_autonegged = false;
- }
-
return 0;
}
@@ -3366,7 +3341,7 @@ static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
* Communicates with the manageability block. On success return 0
* else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
**/
-static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
+static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
u32 length)
{
u32 hicr, i;
@@ -3399,7 +3374,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
*/
for (i = 0; i < dword_len; i++)
IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG,
- i, *((u32 *)buffer + i));
+ i, cpu_to_le32(buffer[i]));
/* Setting this bit tells the ARC that a new command is pending. */
IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C);
@@ -3423,9 +3398,10 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
dword_len = hdr_size >> 2;
/* first pull in the header so we know the buffer length */
- for (i = 0; i < dword_len; i++)
- *((u32 *)buffer + i) =
- IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
+ for (i = 0; i < dword_len; i++) {
+ buffer[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
+ le32_to_cpus(&buffer[i]);
+ }
/* If there is any thing in data position pull it in */
buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
@@ -3443,8 +3419,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
/* Pull in the rest of the buffer (i is where we left off)*/
for (; i < buf_len; i++)
- *((u32 *)buffer + i) =
- IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
+ buffer[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
out:
return ret_val;
@@ -3490,7 +3465,7 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
fw_cmd.pad2 = 0;
for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
- ret_val = ixgbe_host_interface_command(hw, (u8 *)&fw_cmd,
+ ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
sizeof(fw_cmd));
if (ret_val != 0)
continue;
@@ -3508,3 +3483,44 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
out:
return ret_val;
}
+
+/**
+ * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo
+ * @hw: pointer to the hardware structure
+ *
+ * The 82599 and x540 MACs can experience issues if TX work is still pending
+ * when a reset occurs. This function prevents this by flushing the PCIe
+ * buffers on the system.
+ **/
+void ixgbe_clear_tx_pending(struct ixgbe_hw *hw)
+{
+ u32 gcr_ext, hlreg0;
+
+ /*
+ * If double reset is not requested then all transactions should
+ * already be clear and as such there is no work to do
+ */
+ if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED))
+ return;
+
+ /*
+ * Set loopback enable to prevent any transmits from being sent
+ * should the link come up. This assumes that the RXCTRL.RXEN bit
+ * has already been cleared.
+ */
+ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+ IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK);
+
+ /* initiate cleaning flow for buffers in the PCIe transaction layer */
+ gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
+ IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT,
+ gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR);
+
+ /* Flush all writes and allow 20usec for all transactions to clear */
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(20);
+
+ /* restore previous register values */
+ IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
+ IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
+}
diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index f24fd64a4c46..863f9c1f145b 100644
--- a/drivers/net/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -81,7 +81,6 @@ s32 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_disable_pcie_master(struct ixgbe_hw *hw);
s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr);
s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
@@ -101,6 +100,7 @@ void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf);
s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps);
s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
u8 build, u8 ver);
+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);
diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
index 9d88c31487bc..318caf4bf623 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
@@ -40,7 +40,8 @@
* hardware. The IEEE 802.1Qaz specification do not use bandwidth
* groups so this is much simplified from the CEE case.
*/
-s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill, __u16 *max, int max_frame)
+static s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill,
+ __u16 *max, int max_frame)
{
int min_percent = 100;
int min_credit, multiplier;
@@ -183,7 +184,7 @@ void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en)
*pfc_en = 0;
for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
- *pfc_en |= (cfg->tc_config[i].dcb_pfc & 0xF) << i;
+ *pfc_en |= !!(cfg->tc_config[i].dcb_pfc & 0xF) << i;
}
void ixgbe_dcb_unpack_refill(struct ixgbe_dcb_config *cfg, int direction,
@@ -230,6 +231,18 @@ void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *cfg, int direction,
}
}
+void ixgbe_dcb_unpack_map(struct ixgbe_dcb_config *cfg, int direction, u8 *map)
+{
+ int i, up;
+ unsigned long bitmap;
+
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ bitmap = cfg->tc_config[i].path[direction].up_to_tc_bitmap;
+ for_each_set_bit(up, &bitmap, MAX_USER_PRIORITY)
+ map[up] = i;
+ }
+}
+
/**
* ixgbe_dcb_hw_config - Config and enable DCB
* @hw: pointer to hardware structure
@@ -244,10 +257,9 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
u8 pfc_en;
u8 ptype[MAX_TRAFFIC_CLASS];
u8 bwgid[MAX_TRAFFIC_CLASS];
+ u8 prio_tc[MAX_TRAFFIC_CLASS];
u16 refill[MAX_TRAFFIC_CLASS];
u16 max[MAX_TRAFFIC_CLASS];
- /* CEE does not define a priority to tc mapping so map 1:1 */
- u8 prio_tc[MAX_TRAFFIC_CLASS] = {0, 1, 2, 3, 4, 5, 6, 7};
/* Unpack CEE standard containers */
ixgbe_dcb_unpack_pfc(dcb_config, &pfc_en);
@@ -255,6 +267,7 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
ixgbe_dcb_unpack_max(dcb_config, max);
ixgbe_dcb_unpack_bwgid(dcb_config, DCB_TX_CONFIG, bwgid);
ixgbe_dcb_unpack_prio(dcb_config, DCB_TX_CONFIG, ptype);
+ ixgbe_dcb_unpack_map(dcb_config, DCB_TX_CONFIG, prio_tc);
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
@@ -273,7 +286,7 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
}
/* Helper routines to abstract HW specifics from DCB netlink ops */
-s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en)
+s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
{
int ret = -EINVAL;
@@ -283,7 +296,7 @@ s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en)
break;
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
- ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en);
+ ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, prio_tc);
break;
default:
break;
@@ -291,6 +304,39 @@ s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en)
return ret;
}
+s32 ixgbe_dcb_hw_ets(struct ixgbe_hw *hw, struct ieee_ets *ets, int max_frame)
+{
+ __u16 refill[IEEE_8021QAZ_MAX_TCS], max[IEEE_8021QAZ_MAX_TCS];
+ __u8 prio_type[IEEE_8021QAZ_MAX_TCS];
+ int i;
+
+ /* naively give each TC a bwg to map onto CEE hardware */
+ __u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+ /* Map TSA onto CEE prio type */
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+ switch (ets->tc_tsa[i]) {
+ case IEEE_8021QAZ_TSA_STRICT:
+ prio_type[i] = 2;
+ break;
+ case IEEE_8021QAZ_TSA_ETS:
+ prio_type[i] = 0;
+ break;
+ default:
+ /* Hardware only supports priority strict or
+ * ETS transmission selection algorithms if
+ * we receive some other value from dcbnl
+ * throw an error
+ */
+ return -EINVAL;
+ }
+ }
+
+ ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame);
+ return ixgbe_dcb_hw_ets_config(hw, refill, max,
+ bwg_id, prio_type, ets->prio_tc);
+}
+
s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw,
u16 *refill, u16 *max, u8 *bwg_id,
u8 *prio_type, u8 *prio_tc)
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h
index e85826ae0320..e162775064da 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h
@@ -29,13 +29,13 @@
#ifndef _DCB_CONFIG_H_
#define _DCB_CONFIG_H_
+#include <linux/dcbnl.h>
#include "ixgbe_type.h"
/* DCB data structures */
#define IXGBE_MAX_PACKET_BUFFERS 8
#define MAX_USER_PRIORITY 8
-#define MAX_TRAFFIC_CLASS 8
#define MAX_BW_GROUP 8
#define BW_PERCENT 100
@@ -145,16 +145,17 @@ void ixgbe_dcb_unpack_refill(struct ixgbe_dcb_config *, int, u16 *);
void ixgbe_dcb_unpack_max(struct ixgbe_dcb_config *, u16 *);
void ixgbe_dcb_unpack_bwgid(struct ixgbe_dcb_config *, int, u8 *);
void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *, int, u8 *);
+void ixgbe_dcb_unpack_map(struct ixgbe_dcb_config *, int, u8 *);
/* DCB credits calculation */
-s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill, __u16 *max, int max_frame);
s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *,
struct ixgbe_dcb_config *, int, u8);
/* DCB hw initialization */
+s32 ixgbe_dcb_hw_ets(struct ixgbe_hw *hw, struct ieee_ets *ets, int max);
s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw, u16 *refill, u16 *max,
u8 *bwg_id, u8 *prio_type, u8 *tc_prio);
-s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en);
+s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en, u8 *tc_prio);
s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *);
/* DCB definitions for credit calculation */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
index 2288c3cac010..fcd0e479721f 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
@@ -191,7 +191,7 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
*/
s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en)
{
- u32 reg, rx_pba_size;
+ u32 reg;
u8 i;
if (pfc_en) {
@@ -222,9 +222,8 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en)
*/
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
int enabled = pfc_en & (1 << i);
- rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
- rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
- reg = (rx_pba_size - hw->fc.low_water) << 10;
+
+ reg = hw->fc.low_water << 10;
if (enabled == pfc_enabled_tx ||
enabled == pfc_enabled_full)
@@ -232,7 +231,7 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en)
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), reg);
- reg = (rx_pba_size - hw->fc.high_water) << 10;
+ reg = hw->fc.high_water[i] << 10;
if (enabled == pfc_enabled_tx ||
enabled == pfc_enabled_full)
reg |= IXGBE_FCRTH_FCEN;
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h
index 2f318935561a..2f318935561a 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
index ade98200288c..32cd97bc794d 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
@@ -59,9 +59,9 @@ s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
reg = IXGBE_RTRPCS_RRM | IXGBE_RTRPCS_RAC | IXGBE_RTRPCS_ARBDIS;
IXGBE_WRITE_REG(hw, IXGBE_RTRPCS, reg);
- /* Map all traffic classes to their UP, 1 to 1 */
+ /* Map all traffic classes to their UP */
reg = 0;
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
+ for (i = 0; i < MAX_USER_PRIORITY; i++)
reg |= (prio_tc[i] << (i * IXGBE_RTRUP2TC_UP_SHIFT));
IXGBE_WRITE_REG(hw, IXGBE_RTRUP2TC, reg);
@@ -169,9 +169,9 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
IXGBE_RTTPCS_ARBDIS;
IXGBE_WRITE_REG(hw, IXGBE_RTTPCS, reg);
- /* Map all traffic classes to their UP, 1 to 1 */
+ /* Map all traffic classes to their UP */
reg = 0;
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
+ for (i = 0; i < MAX_USER_PRIORITY; i++)
reg |= (prio_tc[i] << (i * IXGBE_RTTUP2TC_UP_SHIFT));
IXGBE_WRITE_REG(hw, IXGBE_RTTUP2TC, reg);
@@ -205,26 +205,44 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
* ixgbe_dcb_config_pfc_82599 - Configure priority flow control
* @hw: pointer to hardware structure
* @pfc_en: enabled pfc bitmask
+ * @prio_tc: priority to tc assignments indexed by priority
*
* Configure Priority Flow Control (PFC) for each traffic class.
*/
-s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en)
+s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
{
- u32 i, reg, rx_pba_size;
+ u32 i, j, reg;
+ u8 max_tc = 0;
+
+ for (i = 0; i < MAX_USER_PRIORITY; i++)
+ if (prio_tc[i] > max_tc)
+ max_tc = prio_tc[i];
/* Configure PFC Tx thresholds per TC */
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
- int enabled = pfc_en & (1 << i);
- rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
- rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
+ int enabled = 0;
+
+ if (i > max_tc) {
+ reg = 0;
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg);
+ continue;
+ }
+
+ for (j = 0; j < MAX_USER_PRIORITY; j++) {
+ if ((prio_tc[j] == i) && (pfc_en & (1 << j))) {
+ enabled = 1;
+ break;
+ }
+ }
- reg = (rx_pba_size - hw->fc.low_water) << 10;
+ reg = hw->fc.low_water << 10;
if (enabled)
reg |= IXGBE_FCRTL_XONE;
IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg);
- reg = (rx_pba_size - hw->fc.high_water) << 10;
+ reg = hw->fc.high_water[i] << 10;
if (enabled)
reg |= IXGBE_FCRTH_FCEN;
IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg);
@@ -252,12 +270,24 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en)
reg &= ~IXGBE_MFLCN_RFCE;
reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF;
- if (hw->mac.type == ixgbe_mac_X540)
+ if (hw->mac.type == ixgbe_mac_X540) {
+ reg &= ~IXGBE_MFLCN_RPFCE_MASK;
reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT;
+ }
IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
} else {
+ /* X540 devices have a RX bit that should be cleared
+ * if PFC is disabled on all TCs but PFC features is
+ * enabled.
+ */
+ if (hw->mac.type == ixgbe_mac_X540) {
+ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
+ reg &= ~IXGBE_MFLCN_RPFCE_MASK;
+ IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
+ }
+
for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
hw->mac.ops.fc_enable(hw, i);
}
@@ -338,7 +368,7 @@ s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
bwg_id, prio_type);
ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max,
bwg_id, prio_type, prio_tc);
- ixgbe_dcb_config_pfc_82599(hw, pfc_en);
+ ixgbe_dcb_config_pfc_82599(hw, pfc_en, prio_tc);
ixgbe_dcb_config_tc_stats_82599(hw);
return 0;
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h
index 08d1749862a3..a59d5dc59d04 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h
@@ -93,7 +93,7 @@
/* DCB hardware-specific driver APIs */
/* DCB PFC functions */
-s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en);
+s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc);
/* DCB hw initialization */
s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
index 0ace6ce1d0b4..3631d639d86a 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
@@ -114,53 +114,19 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
u8 err = 0;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ /* Fail command if not in CEE mode */
+ if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
+ return 1;
+
/* verify there is something to do, if not then exit */
if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
return err;
- if (state > 0) {
- /* Turn on DCB */
- if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
- e_err(drv, "Enable failed, needs MSI-X\n");
- err = 1;
- goto out;
- }
-
- adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
-
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82598EB:
- adapter->last_lfc_mode = adapter->hw.fc.current_mode;
- adapter->hw.fc.requested_mode = ixgbe_fc_none;
- break;
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- break;
- default:
- break;
- }
-
- ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
- } else {
- /* Turn off DCB */
- adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
- adapter->temp_dcb_cfg.pfc_mode_enable = false;
- adapter->dcb_cfg.pfc_mode_enable = false;
- adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
- adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
- break;
- default:
- break;
- }
- ixgbe_setup_tc(netdev, 0);
- }
+ if (state > 0)
+ err = ixgbe_setup_tc(netdev, adapter->dcb_cfg.num_tcs.pg_tcs);
+ else
+ err = ixgbe_setup_tc(netdev, 0);
-out:
return err;
}
@@ -192,6 +158,10 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ /* Abort a bad configuration */
+ if (ffs(up_map) > adapter->dcb_cfg.num_tcs.pg_tcs)
+ return;
+
if (prio != DCB_ATTR_VALUE_UNDEFINED)
adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type = prio;
if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
@@ -212,6 +182,10 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
(adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap))
adapter->dcb_set_bitmap |= BIT_PG_TX;
+
+ if (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
+ adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)
+ adapter->dcb_set_bitmap |= BIT_PFC;
}
static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
@@ -232,6 +206,10 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ /* Abort bad configurations */
+ if (ffs(up_map) > adapter->dcb_cfg.num_tcs.pg_tcs)
+ return;
+
if (prio != DCB_ATTR_VALUE_UNDEFINED)
adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type = prio;
if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
@@ -252,6 +230,10 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
(adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap))
adapter->dcb_set_bitmap |= BIT_PG_RX;
+
+ if (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
+ adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)
+ adapter->dcb_set_bitmap |= BIT_PFC;
}
static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
@@ -330,22 +312,34 @@ static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- int ret;
+ int ret, i;
#ifdef IXGBE_FCOE
struct dcb_app app = {
.selector = DCB_APP_IDTYPE_ETHTYPE,
.protocol = ETH_P_FCOE,
};
- u8 up = dcb_getapp(netdev, &app);
+ u8 up;
+
+ /* In IEEE mode, use the IEEE Ethertype selector value */
+ if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) {
+ app.selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE;
+ up = dcb_ieee_getapp_mask(netdev, &app);
+ } else {
+ up = dcb_getapp(netdev, &app);
+ }
#endif
+ /* Fail command if not in CEE mode */
+ if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
+ return 1;
+
ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
MAX_TRAFFIC_CLASS);
if (ret)
return DCB_NO_HW_CHG;
#ifdef IXGBE_FCOE
- if (up && (up != (1 << adapter->fcoe.up)))
+ if (up && !(up & (1 << adapter->fcoe.up)))
adapter->dcb_set_bitmap |= BIT_APP_UPCHG;
/*
@@ -400,21 +394,14 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
}
#endif
- if (adapter->dcb_set_bitmap & BIT_PFC) {
- u8 pfc_en;
- ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en);
- ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en);
- ret = DCB_HW_CHG;
- }
-
if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) {
u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS];
u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS];
/* Priority to TC mapping in CEE case default to 1:1 */
- u8 prio_tc[MAX_TRAFFIC_CLASS] = {0, 1, 2, 3, 4, 5, 6, 7};
+ u8 prio_tc[MAX_USER_PRIORITY];
int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
-#ifdef CONFIG_FCOE
+#ifdef IXGBE_FCOE
if (adapter->netdev->features & NETIF_F_FCOE_MTU)
max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
#endif
@@ -431,9 +418,25 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
DCB_TX_CONFIG, bwg_id);
ixgbe_dcb_unpack_prio(&adapter->dcb_cfg,
DCB_TX_CONFIG, prio_type);
+ ixgbe_dcb_unpack_map(&adapter->dcb_cfg,
+ DCB_TX_CONFIG, prio_tc);
ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max,
bwg_id, prio_type, prio_tc);
+
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
+ netdev_set_prio_tc_map(netdev, i, prio_tc[i]);
+ }
+
+ if (adapter->dcb_set_bitmap & BIT_PFC) {
+ u8 pfc_en;
+ u8 prio_tc[MAX_USER_PRIORITY];
+
+ ixgbe_dcb_unpack_map(&adapter->dcb_cfg,
+ DCB_TX_CONFIG, prio_tc);
+ ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en);
+ ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en, prio_tc);
+ ret = DCB_HW_CHG;
}
if (adapter->dcb_cfg.pfc_mode_enable)
@@ -490,10 +493,10 @@ static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
switch (tcid) {
case DCB_NUMTCS_ATTR_PG:
- *num = MAX_TRAFFIC_CLASS;
+ *num = adapter->dcb_cfg.num_tcs.pg_tcs;
break;
case DCB_NUMTCS_ATTR_PFC:
- *num = MAX_TRAFFIC_CLASS;
+ *num = adapter->dcb_cfg.num_tcs.pfc_tcs;
break;
default:
rval = -EINVAL;
@@ -562,7 +565,7 @@ static int ixgbe_dcbnl_ieee_getets(struct net_device *dev,
if (!my_ets)
return -EINVAL;
- ets->ets_cap = MAX_TRAFFIC_CLASS;
+ ets->ets_cap = adapter->dcb_cfg.num_tcs.pg_tcs;
ets->cbs = my_ets->cbs;
memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
@@ -575,13 +578,9 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
struct ieee_ets *ets)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
- __u16 refill[IEEE_8021QAZ_MAX_TCS], max[IEEE_8021QAZ_MAX_TCS];
- __u8 prio_type[IEEE_8021QAZ_MAX_TCS];
int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
- int i, err;
- __u64 *p = (__u64 *) ets->prio_tc;
- /* naively give each TC a bwg to map onto CEE hardware */
- __u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7};
+ int i;
+ __u8 max_tc = 0;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
return -EINVAL;
@@ -595,34 +594,24 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets));
- /* Map TSA onto CEE prio type */
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
- switch (ets->tc_tsa[i]) {
- case IEEE_8021QAZ_TSA_STRICT:
- prio_type[i] = 2;
- break;
- case IEEE_8021QAZ_TSA_ETS:
- prio_type[i] = 0;
- break;
- default:
- /* Hardware only supports priority strict or
- * ETS transmission selection algorithms if
- * we receive some other value from dcbnl
- * throw an error
- */
- return -EINVAL;
- }
+ if (ets->prio_tc[i] > max_tc)
+ max_tc = ets->prio_tc[i];
}
- if (*p)
- ixgbe_dcbnl_set_state(dev, 1);
- else
- ixgbe_dcbnl_set_state(dev, 0);
+ if (max_tc)
+ max_tc++;
- ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame);
- err = ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max,
- bwg_id, prio_type, ets->prio_tc);
- return err;
+ if (max_tc > adapter->dcb_cfg.num_tcs.pg_tcs)
+ return -EINVAL;
+
+ if (max_tc != netdev_get_num_tc(dev))
+ ixgbe_setup_tc(dev, max_tc);
+
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
+ netdev_set_prio_tc_map(dev, i, ets->prio_tc[i]);
+
+ return ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame);
}
static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
@@ -636,7 +625,7 @@ static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
if (!my_pfc)
return -EINVAL;
- pfc->pfc_cap = MAX_TRAFFIC_CLASS;
+ pfc->pfc_cap = adapter->dcb_cfg.num_tcs.pfc_tcs;
pfc->pfc_en = my_pfc->pfc_en;
pfc->mbc = my_pfc->mbc;
pfc->delay = my_pfc->delay;
@@ -653,7 +642,7 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
struct ieee_pfc *pfc)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
- int err;
+ u8 *prio_tc;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
return -EINVAL;
@@ -665,9 +654,9 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
return -ENOMEM;
}
+ prio_tc = adapter->ixgbe_ieee_ets->prio_tc;
memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc));
- err = ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en);
- return err;
+ return ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en, prio_tc);
}
#ifdef IXGBE_FCOE
@@ -778,7 +767,7 @@ static u8 ixgbe_dcbnl_setdcbx(struct net_device *dev, u8 mode)
*/
ixgbe_dcbnl_ieee_setets(dev, &ets);
ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
- ixgbe_dcbnl_set_state(dev, 0);
+ ixgbe_setup_tc(dev, 0);
}
return 0;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 82d4244c6e10..70d58c3849b0 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -113,6 +113,8 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
{"rx_fcoe_dropped", IXGBE_STAT(stats.fcoerpdc)},
{"rx_fcoe_packets", IXGBE_STAT(stats.fcoeprc)},
{"rx_fcoe_dwords", IXGBE_STAT(stats.fcoedwrc)},
+ {"fcoe_noddp", IXGBE_STAT(stats.fcoe_noddp)},
+ {"fcoe_noddp_ext_buff", IXGBE_STAT(stats.fcoe_noddp_ext_buff)},
{"tx_fcoe_packets", IXGBE_STAT(stats.fcoeptc)},
{"tx_fcoe_dwords", IXGBE_STAT(stats.fcoedwtc)},
#endif /* IXGBE_FCOE */
@@ -324,12 +326,16 @@ static int ixgbe_set_settings(struct net_device *netdev,
if ((hw->phy.media_type == ixgbe_media_type_copper) ||
(hw->phy.multispeed_fiber)) {
- /* 10000/copper and 1000/copper must autoneg
- * this function does not support any duplex forcing, but can
- * limit the advertising of the adapter to only 10000 or 1000 */
+ /*
+ * this function does not support duplex forcing, but can
+ * limit the advertising of the adapter to the specified speed
+ */
if (ecmd->autoneg == AUTONEG_DISABLE)
return -EINVAL;
+ if (ecmd->advertising & ~ecmd->supported)
+ return -EINVAL;
+
old = hw->phy.autoneg_advertised;
advertised = 0;
if (ecmd->advertising & ADVERTISED_10000baseT_Full)
@@ -368,13 +374,7 @@ static void ixgbe_get_pauseparam(struct net_device *netdev,
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
- /*
- * Flow Control Autoneg isn't on if
- * - we didn't ask for it OR
- * - it failed, we know this by tx & rx being off
- */
- if (hw->fc.disable_fc_autoneg ||
- (hw->fc.current_mode == ixgbe_fc_none))
+ if (hw->fc.disable_fc_autoneg)
pause->autoneg = 0;
else
pause->autoneg = 1;
@@ -456,7 +456,7 @@ static void ixgbe_set_msglevel(struct net_device *netdev, u32 data)
static int ixgbe_get_regs_len(struct net_device *netdev)
{
-#define IXGBE_REGS_LEN 1128
+#define IXGBE_REGS_LEN 1129
return IXGBE_REGS_LEN * sizeof(u32);
}
@@ -525,6 +525,7 @@ static void ixgbe_get_regs(struct net_device *netdev,
regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH(i));
break;
case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL_82599(i));
regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i));
break;
@@ -766,6 +767,9 @@ static void ixgbe_get_regs(struct net_device *netdev,
regs_buff[1125] = IXGBE_READ_REG(hw, IXGBE_PCIEECCCTL);
regs_buff[1126] = IXGBE_READ_REG(hw, IXGBE_PBTXECC);
regs_buff[1127] = IXGBE_READ_REG(hw, IXGBE_PBRXECC);
+
+ /* 82599 X540 specific registers */
+ regs_buff[1128] = IXGBE_READ_REG(hw, IXGBE_MFLCN);
}
static int ixgbe_get_eeprom_len(struct net_device *netdev)
@@ -810,26 +814,97 @@ static int ixgbe_get_eeprom(struct net_device *netdev,
return ret_val;
}
+static int ixgbe_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_hw *hw = &adapter->hw;
+ u16 *eeprom_buff;
+ void *ptr;
+ int max_len, first_word, last_word, ret_val = 0;
+ u16 i;
+
+ if (eeprom->len == 0)
+ return -EINVAL;
+
+ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+ return -EINVAL;
+
+ max_len = hw->eeprom.word_size * 2;
+
+ first_word = eeprom->offset >> 1;
+ last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+ eeprom_buff = kmalloc(max_len, GFP_KERNEL);
+ if (!eeprom_buff)
+ return -ENOMEM;
+
+ ptr = eeprom_buff;
+
+ if (eeprom->offset & 1) {
+ /*
+ * need read/modify/write of first changed EEPROM word
+ * only the second byte of the word is being modified
+ */
+ ret_val = hw->eeprom.ops.read(hw, first_word, &eeprom_buff[0]);
+ if (ret_val)
+ goto err;
+
+ ptr++;
+ }
+ if ((eeprom->offset + eeprom->len) & 1) {
+ /*
+ * need read/modify/write of last changed EEPROM word
+ * only the first byte of the word is being modified
+ */
+ ret_val = hw->eeprom.ops.read(hw, last_word,
+ &eeprom_buff[last_word - first_word]);
+ if (ret_val)
+ goto err;
+ }
+
+ /* Device's eeprom is always little-endian, word addressable */
+ for (i = 0; i < last_word - first_word + 1; i++)
+ le16_to_cpus(&eeprom_buff[i]);
+
+ memcpy(ptr, bytes, eeprom->len);
+
+ for (i = 0; i < last_word - first_word + 1; i++)
+ cpu_to_le16s(&eeprom_buff[i]);
+
+ ret_val = hw->eeprom.ops.write_buffer(hw, first_word,
+ last_word - first_word + 1,
+ eeprom_buff);
+
+ /* Update the checksum */
+ if (ret_val == 0)
+ hw->eeprom.ops.update_checksum(hw);
+
+err:
+ kfree(eeprom_buff);
+ return ret_val;
+}
+
static void ixgbe_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
char firmware_version[32];
+ u32 nvm_track_id;
strncpy(drvinfo->driver, ixgbe_driver_name,
sizeof(drvinfo->driver) - 1);
strncpy(drvinfo->version, ixgbe_driver_version,
sizeof(drvinfo->version) - 1);
- snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d",
- (adapter->eeprom_version & 0xF000) >> 12,
- (adapter->eeprom_version & 0x0FF0) >> 4,
- adapter->eeprom_version & 0x000F);
+ nvm_track_id = (adapter->eeprom_verh << 16) |
+ adapter->eeprom_verl;
+ snprintf(firmware_version, sizeof(firmware_version), "0x%08x",
+ nvm_track_id);
strncpy(drvinfo->fw_version, firmware_version,
- sizeof(drvinfo->fw_version));
+ sizeof(drvinfo->fw_version) - 1);
strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
- sizeof(drvinfo->bus_info));
+ sizeof(drvinfo->bus_info) - 1);
drvinfo->n_stats = IXGBE_STATS_LEN;
drvinfo->testinfo_len = IXGBE_TEST_LEN;
drvinfo->regdump_len = ixgbe_get_regs_len(netdev);
@@ -844,12 +919,8 @@ static void ixgbe_get_ringparam(struct net_device *netdev,
ring->rx_max_pending = IXGBE_MAX_RXD;
ring->tx_max_pending = IXGBE_MAX_TXD;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = rx_ring->count;
ring->tx_pending = tx_ring->count;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
static int ixgbe_set_ringparam(struct net_device *netdev,
@@ -1535,7 +1606,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
rx_ring->dev = &adapter->pdev->dev;
rx_ring->netdev = adapter->netdev;
rx_ring->reg_idx = adapter->rx_ring[0]->reg_idx;
- rx_ring->rx_buf_len = IXGBE_RXBUFFER_2048;
+ rx_ring->rx_buf_len = IXGBE_RXBUFFER_2K;
rx_ring->numa_node = adapter->node;
err = ixgbe_setup_rx_resources(rx_ring);
@@ -1566,26 +1637,26 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter)
/* X540 needs to set the MACC.FLU bit to force link up */
if (adapter->hw.mac.type == ixgbe_mac_X540) {
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_MACC);
+ reg_data = IXGBE_READ_REG(hw, IXGBE_MACC);
reg_data |= IXGBE_MACC_FLU;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_MACC, reg_data);
+ IXGBE_WRITE_REG(hw, IXGBE_MACC, reg_data);
}
/* right now we only support MAC loopback in the driver */
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
+ reg_data = IXGBE_READ_REG(hw, IXGBE_HLREG0);
/* Setup MAC loopback */
reg_data |= IXGBE_HLREG0_LPBK;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
+ IXGBE_WRITE_REG(hw, IXGBE_HLREG0, reg_data);
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
+ reg_data = IXGBE_READ_REG(hw, IXGBE_FCTRL);
reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data);
+ IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg_data);
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_AUTOC);
+ reg_data = IXGBE_READ_REG(hw, IXGBE_AUTOC);
reg_data &= ~IXGBE_AUTOC_LMS_MASK;
reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_AUTOC, reg_data);
- IXGBE_WRITE_FLUSH(&adapter->hw);
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_data);
+ IXGBE_WRITE_FLUSH(hw);
usleep_range(10000, 20000);
/* Disable Atlas Tx lanes; re-enabled in reset path */
@@ -1883,6 +1954,7 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter,
{
struct ixgbe_hw *hw = &adapter->hw;
int retval = 1;
+ u16 wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK;
/* WOL not supported except for the following */
switch(hw->device_id) {
@@ -1906,6 +1978,18 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter,
case IXGBE_DEV_ID_82599_KX4:
retval = 0;
break;
+ case IXGBE_DEV_ID_X540T:
+ /* check eeprom to see if enabled wol */
+ if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
+ ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
+ (hw->bus.func == 0))) {
+ retval = 0;
+ break;
+ }
+
+ /* All others not supported */
+ wol->supported = 0;
+ break;
default:
wol->supported = 0;
}
@@ -2008,39 +2092,20 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
ec->tx_max_coalesced_frames_irq = adapter->tx_work_limit;
/* only valid if in constant ITR mode */
- switch (adapter->rx_itr_setting) {
- case 0:
- /* throttling disabled */
- ec->rx_coalesce_usecs = 0;
- break;
- case 1:
- /* dynamic ITR mode */
- ec->rx_coalesce_usecs = 1;
- break;
- default:
- /* fixed interrupt rate mode */
- ec->rx_coalesce_usecs = 1000000/adapter->rx_eitr_param;
- break;
- }
+ if (adapter->rx_itr_setting <= 1)
+ ec->rx_coalesce_usecs = adapter->rx_itr_setting;
+ else
+ ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2;
/* if in mixed tx/rx queues per vector mode, report only rx settings */
if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count)
return 0;
/* only valid if in constant ITR mode */
- switch (adapter->tx_itr_setting) {
- case 0:
- /* throttling disabled */
- ec->tx_coalesce_usecs = 0;
- break;
- case 1:
- /* dynamic ITR mode */
- ec->tx_coalesce_usecs = 1;
- break;
- default:
- ec->tx_coalesce_usecs = 1000000/adapter->tx_eitr_param;
- break;
- }
+ if (adapter->tx_itr_setting <= 1)
+ ec->tx_coalesce_usecs = adapter->tx_itr_setting;
+ else
+ ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2;
return 0;
}
@@ -2059,10 +2124,9 @@ static bool ixgbe_update_rsc(struct ixgbe_adapter *adapter,
/* if interrupt rate is too high then disable RSC */
if (ec->rx_coalesce_usecs != 1 &&
- ec->rx_coalesce_usecs <= 1000000/IXGBE_MAX_RSC_INT_RATE) {
+ ec->rx_coalesce_usecs <= (IXGBE_MIN_RSC_ITR >> 2)) {
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
- e_info(probe, "rx-usecs set too low, "
- "disabling RSC\n");
+ e_info(probe, "rx-usecs set too low, disabling RSC\n");
adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
return true;
}
@@ -2070,8 +2134,7 @@ static bool ixgbe_update_rsc(struct ixgbe_adapter *adapter,
/* check the feature flag value and enable RSC if necessary */
if ((netdev->features & NETIF_F_LRO) &&
!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) {
- e_info(probe, "rx-usecs set to %d, "
- "re-enabling RSC\n",
+ e_info(probe, "rx-usecs set to %d, re-enabling RSC\n",
ec->rx_coalesce_usecs);
adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
return true;
@@ -2086,97 +2149,59 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_q_vector *q_vector;
int i;
+ int num_vectors;
+ u16 tx_itr_param, rx_itr_param;
bool need_reset = false;
/* don't accept tx specific changes if we've got mixed RxTx vectors */
if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count
- && ec->tx_coalesce_usecs)
+ && ec->tx_coalesce_usecs)
return -EINVAL;
if (ec->tx_max_coalesced_frames_irq)
adapter->tx_work_limit = ec->tx_max_coalesced_frames_irq;
- if (ec->rx_coalesce_usecs > 1) {
- /* check the limits */
- if ((1000000/ec->rx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
- (1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
- return -EINVAL;
-
- /* check the old value and enable RSC if necessary */
- need_reset = ixgbe_update_rsc(adapter, ec);
-
- /* store the value in ints/second */
- adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
+ if ((ec->rx_coalesce_usecs > (IXGBE_MAX_EITR >> 2)) ||
+ (ec->tx_coalesce_usecs > (IXGBE_MAX_EITR >> 2)))
+ return -EINVAL;
- /* static value of interrupt rate */
- adapter->rx_itr_setting = adapter->rx_eitr_param;
- /* clear the lower bit as its used for dynamic state */
- adapter->rx_itr_setting &= ~1;
- } else if (ec->rx_coalesce_usecs == 1) {
- /* check the old value and enable RSC if necessary */
- need_reset = ixgbe_update_rsc(adapter, ec);
+ /* check the old value and enable RSC if necessary */
+ need_reset = ixgbe_update_rsc(adapter, ec);
- /* 1 means dynamic mode */
- adapter->rx_eitr_param = 20000;
- adapter->rx_itr_setting = 1;
- } else {
- /* check the old value and enable RSC if necessary */
- need_reset = ixgbe_update_rsc(adapter, ec);
- /*
- * any other value means disable eitr, which is best
- * served by setting the interrupt rate very high
- */
- adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
- adapter->rx_itr_setting = 0;
- }
+ if (ec->rx_coalesce_usecs > 1)
+ adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2;
+ else
+ adapter->rx_itr_setting = ec->rx_coalesce_usecs;
- if (ec->tx_coalesce_usecs > 1) {
- /*
- * don't have to worry about max_int as above because
- * tx vectors don't do hardware RSC (an rx function)
- */
- /* check the limits */
- if ((1000000/ec->tx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
- (1000000/ec->tx_coalesce_usecs < IXGBE_MIN_INT_RATE))
- return -EINVAL;
+ if (adapter->rx_itr_setting == 1)
+ rx_itr_param = IXGBE_20K_ITR;
+ else
+ rx_itr_param = adapter->rx_itr_setting;
- /* store the value in ints/second */
- adapter->tx_eitr_param = 1000000/ec->tx_coalesce_usecs;
+ if (ec->tx_coalesce_usecs > 1)
+ adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2;
+ else
+ adapter->tx_itr_setting = ec->tx_coalesce_usecs;
- /* static value of interrupt rate */
- adapter->tx_itr_setting = adapter->tx_eitr_param;
+ if (adapter->tx_itr_setting == 1)
+ tx_itr_param = IXGBE_10K_ITR;
+ else
+ tx_itr_param = adapter->tx_itr_setting;
- /* clear the lower bit as its used for dynamic state */
- adapter->tx_itr_setting &= ~1;
- } else if (ec->tx_coalesce_usecs == 1) {
- /* 1 means dynamic mode */
- adapter->tx_eitr_param = 10000;
- adapter->tx_itr_setting = 1;
- } else {
- adapter->tx_eitr_param = IXGBE_MAX_INT_RATE;
- adapter->tx_itr_setting = 0;
- }
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
+ num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+ else
+ num_vectors = 1;
- /* MSI/MSIx Interrupt Mode */
- if (adapter->flags &
- (IXGBE_FLAG_MSIX_ENABLED | IXGBE_FLAG_MSI_ENABLED)) {
- int num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
- for (i = 0; i < num_vectors; i++) {
- q_vector = adapter->q_vector[i];
- if (q_vector->tx.count && !q_vector->rx.count)
- /* tx only */
- q_vector->eitr = adapter->tx_eitr_param;
- else
- /* rx only or mixed */
- q_vector->eitr = adapter->rx_eitr_param;
- q_vector->tx.work_limit = adapter->tx_work_limit;
- ixgbe_write_eitr(q_vector);
- }
- /* Legacy Interrupt Mode */
- } else {
- q_vector = adapter->q_vector[0];
- q_vector->eitr = adapter->rx_eitr_param;
+ for (i = 0; i < num_vectors; i++) {
+ q_vector = adapter->q_vector[i];
q_vector->tx.work_limit = adapter->tx_work_limit;
+ if (q_vector->tx.count && !q_vector->rx.count)
+ /* tx only */
+ q_vector->itr = tx_itr_param;
+ else
+ /* rx only or mixed */
+ q_vector->itr = rx_itr_param;
ixgbe_write_eitr(q_vector);
}
@@ -2279,11 +2304,13 @@ static int ixgbe_get_ethtool_fdir_all(struct ixgbe_adapter *adapter,
cnt++;
}
+ cmd->rule_cnt = cnt;
+
return 0;
}
static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
- void *rule_locs)
+ u32 *rule_locs)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
int ret = -EOPNOTSUPP;
@@ -2301,8 +2328,7 @@ static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
ret = ixgbe_get_ethtool_fdir_entry(adapter, cmd);
break;
case ETHTOOL_GRXCLSRLALL:
- ret = ixgbe_get_ethtool_fdir_all(adapter, cmd,
- (u32 *)rule_locs);
+ ret = ixgbe_get_ethtool_fdir_all(adapter, cmd, rule_locs);
break;
default:
break;
@@ -2569,6 +2595,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_eeprom_len = ixgbe_get_eeprom_len,
.get_eeprom = ixgbe_get_eeprom,
+ .set_eeprom = ixgbe_set_eeprom,
.get_ringparam = ixgbe_get_ringparam,
.set_ringparam = ixgbe_set_ringparam,
.get_pauseparam = ixgbe_get_pauseparam,
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index 824edae77865..df3b1be69d83 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -145,6 +145,7 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
u32 fcbuff, fcdmarw, fcfltrw, fcrxctl;
dma_addr_t addr = 0;
struct pci_pool *pool;
+ unsigned int cpu;
if (!netdev || !sgl)
return 0;
@@ -182,7 +183,8 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
}
/* alloc the udl from per cpu ddp pool */
- pool = *per_cpu_ptr(fcoe->pool, get_cpu());
+ cpu = get_cpu();
+ pool = *per_cpu_ptr(fcoe->pool, cpu);
ddp->udl = pci_pool_alloc(pool, GFP_ATOMIC, &ddp->udp);
if (!ddp->udl) {
e_err(drv, "failed allocated ddp context\n");
@@ -199,9 +201,7 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
while (len) {
/* max number of buffers allowed in one DDP context */
if (j >= IXGBE_BUFFCNT_MAX) {
- e_err(drv, "xid=%x:%d,%d,%d:addr=%llx "
- "not enough descriptors\n",
- xid, i, j, dmacount, (u64)addr);
+ *per_cpu_ptr(fcoe->pcpu_noddp, cpu) += 1;
goto out_noddp_free;
}
@@ -241,10 +241,7 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
*/
if (lastsize == bufflen) {
if (j >= IXGBE_BUFFCNT_MAX) {
- e_err(drv, "xid=%x:%d,%d,%d:addr=%llx "
- "not enough user buffers. We need an extra "
- "buffer because lastsize is bufflen.\n",
- xid, i, j, dmacount, (u64)addr);
+ *per_cpu_ptr(fcoe->pcpu_noddp_ext_buff, cpu) += 1;
goto out_noddp_free;
}
@@ -438,7 +435,6 @@ ddp_out:
/**
* ixgbe_fso - ixgbe FCoE Sequence Offload (FSO)
- * @adapter: ixgbe adapter
* @tx_ring: tx desc ring
* @skb: associated skb
* @tx_flags: tx flags
@@ -599,6 +595,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_fcoe *fcoe = &adapter->fcoe;
struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE];
+ unsigned int cpu;
if (!fcoe->pool) {
spin_lock_init(&fcoe->lock);
@@ -626,6 +623,24 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
e_err(drv, "failed to map extra DDP buffer\n");
goto out_extra_ddp_buffer;
}
+
+ /* Alloc per cpu mem to count the ddp alloc failure number */
+ fcoe->pcpu_noddp = alloc_percpu(u64);
+ if (!fcoe->pcpu_noddp) {
+ e_err(drv, "failed to alloc noddp counter\n");
+ goto out_pcpu_noddp_alloc_fail;
+ }
+
+ fcoe->pcpu_noddp_ext_buff = alloc_percpu(u64);
+ if (!fcoe->pcpu_noddp_ext_buff) {
+ e_err(drv, "failed to alloc noddp extra buff cnt\n");
+ goto out_pcpu_noddp_extra_buff_alloc_fail;
+ }
+
+ for_each_possible_cpu(cpu) {
+ *per_cpu_ptr(fcoe->pcpu_noddp, cpu) = 0;
+ *per_cpu_ptr(fcoe->pcpu_noddp_ext_buff, cpu) = 0;
+ }
}
/* Enable L2 eth type filter for FCoE */
@@ -660,12 +675,16 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
IXGBE_ETQS_QUEUE_EN |
(fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT));
- IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL,
- IXGBE_FCRXCTRL_FCOELLI |
- IXGBE_FCRXCTRL_FCCRCBO |
+ IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL, IXGBE_FCRXCTRL_FCCRCBO |
(FC_FCOE_VER << IXGBE_FCRXCTRL_FCOEVER_SHIFT));
return;
-
+out_pcpu_noddp_extra_buff_alloc_fail:
+ free_percpu(fcoe->pcpu_noddp);
+out_pcpu_noddp_alloc_fail:
+ dma_unmap_single(&adapter->pdev->dev,
+ fcoe->extra_ddp_buffer_dma,
+ IXGBE_FCBUFF_MIN,
+ DMA_FROM_DEVICE);
out_extra_ddp_buffer:
kfree(fcoe->extra_ddp_buffer);
out_ddp_pools:
@@ -694,6 +713,8 @@ void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter)
fcoe->extra_ddp_buffer_dma,
IXGBE_FCBUFF_MIN,
DMA_FROM_DEVICE);
+ free_percpu(fcoe->pcpu_noddp);
+ free_percpu(fcoe->pcpu_noddp_ext_buff);
kfree(fcoe->extra_ddp_buffer);
ixgbe_fcoe_ddp_pools_free(fcoe);
}
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h
index 99de145e290d..261fd62dda18 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h
@@ -73,6 +73,8 @@ struct ixgbe_fcoe {
unsigned char *extra_ddp_buffer;
dma_addr_t extra_ddp_buffer_dma;
unsigned long mode;
+ u64 __percpu *pcpu_noddp;
+ u64 __percpu *pcpu_noddp_ext_buff;
#ifdef CONFIG_IXGBE_DCB
u8 up;
#endif
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index e1fcc9589278..09b8e88b2999 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -42,6 +42,7 @@
#include <net/checksum.h>
#include <net/ip6_checksum.h>
#include <linux/ethtool.h>
+#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/prefetch.h>
#include <scsi/fc/fc_fcoe.h>
@@ -55,8 +56,8 @@ char ixgbe_driver_name[] = "ixgbe";
static const char ixgbe_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Network Driver";
#define MAJ 3
-#define MIN 4
-#define BUILD 8
+#define MIN 6
+#define BUILD 7
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
const char ixgbe_driver_version[] = DRV_VERSION;
@@ -78,59 +79,33 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = {
* Class, Class Mask, private data (not used) }
*/
static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT2),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_DA_DUAL_PORT),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_XF_LR),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_BX),
- board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_XAUI_LOM),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KR),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_EM),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4_MEZZ),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_BACKPLANE_FCOE),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_FCOE),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_T3_LOM),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T),
- board_X540 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF2),
- board_82599 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS),
- board_82599 },
-
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT2), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_DA_DUAL_PORT), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_XF_LR), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_BX), board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_XAUI_LOM), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KR), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_EM), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4_MEZZ), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_BACKPLANE_FCOE), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_FCOE), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_T3_LOM), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T), board_X540 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF2), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP), board_82599 },
/* required last entry */
{0, }
};
@@ -160,42 +135,6 @@ MODULE_VERSION(DRV_VERSION);
#define DEFAULT_DEBUG_LEVEL_SHIFT 3
-static inline void ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- u32 gcr;
- u32 gpie;
- u32 vmdctl;
-
-#ifdef CONFIG_PCI_IOV
- /* disable iov and allow time for transactions to clear */
- pci_disable_sriov(adapter->pdev);
-#endif
-
- /* turn off device IOV mode */
- gcr = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
- gcr &= ~(IXGBE_GCR_EXT_SRIOV);
- IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr);
- gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
- gpie &= ~IXGBE_GPIE_VTMODE_MASK;
- IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
-
- /* set default pool back to 0 */
- vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
- vmdctl &= ~IXGBE_VT_CTL_POOL_MASK;
- IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl);
- IXGBE_WRITE_FLUSH(hw);
-
- /* take a breather then clean up driver data */
- msleep(100);
-
- kfree(adapter->vfinfo);
- adapter->vfinfo = NULL;
-
- adapter->num_vfs = 0;
- adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
-}
-
static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
{
if (!test_bit(__IXGBE_DOWN, &adapter->state) &&
@@ -384,7 +323,7 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
tx_ring = adapter->tx_ring[n];
tx_buffer_info =
&tx_ring->tx_buffer_info[tx_ring->next_to_clean];
- pr_info(" %5d %5X %5X %016llX %04X %3X %016llX\n",
+ pr_info(" %5d %5X %5X %016llX %04X %p %016llX\n",
n, tx_ring->next_to_use, tx_ring->next_to_clean,
(u64)tx_buffer_info->dma,
tx_buffer_info->length,
@@ -423,7 +362,7 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
tx_buffer_info = &tx_ring->tx_buffer_info[i];
u0 = (struct my_u0 *)tx_desc;
pr_info("T [0x%03X] %016llX %016llX %016llX"
- " %04X %3X %016llX %p", i,
+ " %04X %p %016llX %p", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
(u64)tx_buffer_info->dma,
@@ -525,7 +464,7 @@ rx_ring_summary:
rx_ring->rx_buf_len, true);
if (rx_ring->rx_buf_len
- < IXGBE_RXBUFFER_2048)
+ < IXGBE_RXBUFFER_2K)
print_hex_dump(KERN_INFO, "",
DUMP_PREFIX_ADDRESS, 16, 1,
phys_to_virt(
@@ -642,27 +581,31 @@ static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter,
}
}
-void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *tx_ring,
- struct ixgbe_tx_buffer *tx_buffer_info)
+static inline void ixgbe_unmap_tx_resource(struct ixgbe_ring *ring,
+ struct ixgbe_tx_buffer *tx_buffer)
{
- if (tx_buffer_info->dma) {
- if (tx_buffer_info->mapped_as_page)
- dma_unmap_page(tx_ring->dev,
- tx_buffer_info->dma,
- tx_buffer_info->length,
- DMA_TO_DEVICE);
+ if (tx_buffer->dma) {
+ if (tx_buffer->tx_flags & IXGBE_TX_FLAGS_MAPPED_AS_PAGE)
+ dma_unmap_page(ring->dev,
+ tx_buffer->dma,
+ tx_buffer->length,
+ DMA_TO_DEVICE);
else
- dma_unmap_single(tx_ring->dev,
- tx_buffer_info->dma,
- tx_buffer_info->length,
- DMA_TO_DEVICE);
- tx_buffer_info->dma = 0;
+ dma_unmap_single(ring->dev,
+ tx_buffer->dma,
+ tx_buffer->length,
+ DMA_TO_DEVICE);
}
- if (tx_buffer_info->skb) {
+ tx_buffer->dma = 0;
+}
+
+void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *tx_ring,
+ struct ixgbe_tx_buffer *tx_buffer_info)
+{
+ ixgbe_unmap_tx_resource(tx_ring, tx_buffer_info);
+ if (tx_buffer_info->skb)
dev_kfree_skb_any(tx_buffer_info->skb);
- tx_buffer_info->skb = NULL;
- }
- tx_buffer_info->time_stamp = 0;
+ tx_buffer_info->skb = NULL;
/* tx_buffer_info must be completely set up in the transmit path */
}
@@ -796,56 +739,72 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
struct ixgbe_ring *tx_ring)
{
struct ixgbe_adapter *adapter = q_vector->adapter;
- union ixgbe_adv_tx_desc *tx_desc, *eop_desc;
- struct ixgbe_tx_buffer *tx_buffer_info;
+ struct ixgbe_tx_buffer *tx_buffer;
+ union ixgbe_adv_tx_desc *tx_desc;
unsigned int total_bytes = 0, total_packets = 0;
- u16 i, eop, count = 0;
+ unsigned int budget = q_vector->tx.work_limit;
+ u16 i = tx_ring->next_to_clean;
- i = tx_ring->next_to_clean;
- eop = tx_ring->tx_buffer_info[i].next_to_watch;
- eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
+ tx_buffer = &tx_ring->tx_buffer_info[i];
+ tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
- while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) &&
- (count < q_vector->tx.work_limit)) {
- bool cleaned = false;
- rmb(); /* read buffer_info after eop_desc */
- for ( ; !cleaned; count++) {
- tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
+ for (; budget; budget--) {
+ union ixgbe_adv_tx_desc *eop_desc = tx_buffer->next_to_watch;
+
+ /* if next_to_watch is not set then there is no work pending */
+ if (!eop_desc)
+ break;
+
+ /* if DD is not set pending work has not been completed */
+ if (!(eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)))
+ break;
+
+ /* count the packet as being completed */
+ tx_ring->tx_stats.completed++;
+
+ /* clear next_to_watch to prevent false hangs */
+ tx_buffer->next_to_watch = NULL;
+ /* prevent any other reads prior to eop_desc being verified */
+ rmb();
+
+ do {
+ ixgbe_unmap_tx_resource(tx_ring, tx_buffer);
tx_desc->wb.status = 0;
- cleaned = (i == eop);
+ if (likely(tx_desc == eop_desc)) {
+ eop_desc = NULL;
+ dev_kfree_skb_any(tx_buffer->skb);
+ tx_buffer->skb = NULL;
+ total_bytes += tx_buffer->bytecount;
+ total_packets += tx_buffer->gso_segs;
+ }
+
+ tx_buffer++;
+ tx_desc++;
i++;
- if (i == tx_ring->count)
+ if (unlikely(i == tx_ring->count)) {
i = 0;
- if (cleaned && tx_buffer_info->skb) {
- total_bytes += tx_buffer_info->bytecount;
- total_packets += tx_buffer_info->gso_segs;
+ tx_buffer = tx_ring->tx_buffer_info;
+ tx_desc = IXGBE_TX_DESC_ADV(tx_ring, 0);
}
- ixgbe_unmap_and_free_tx_resource(tx_ring,
- tx_buffer_info);
- }
-
- tx_ring->tx_stats.completed++;
- eop = tx_ring->tx_buffer_info[i].next_to_watch;
- eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
+ } while (eop_desc);
}
tx_ring->next_to_clean = i;
+ u64_stats_update_begin(&tx_ring->syncp);
tx_ring->stats.bytes += total_bytes;
tx_ring->stats.packets += total_packets;
- u64_stats_update_begin(&tx_ring->syncp);
+ u64_stats_update_end(&tx_ring->syncp);
q_vector->tx.total_bytes += total_bytes;
q_vector->tx.total_packets += total_packets;
- u64_stats_update_end(&tx_ring->syncp);
if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) {
/* schedule immediate reset if we believe we hung */
struct ixgbe_hw *hw = &adapter->hw;
- tx_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
+ tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
e_err(drv, "Detected Tx Unit Hang\n"
" Tx Queue <%d>\n"
" TDH, TDT <%x>, <%x>\n"
@@ -857,8 +816,8 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
tx_ring->queue_index,
IXGBE_READ_REG(hw, IXGBE_TDH(tx_ring->reg_idx)),
IXGBE_READ_REG(hw, IXGBE_TDT(tx_ring->reg_idx)),
- tx_ring->next_to_use, eop,
- tx_ring->tx_buffer_info[eop].time_stamp, jiffies);
+ tx_ring->next_to_use, i,
+ tx_ring->tx_buffer_info[i].time_stamp, jiffies);
netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
@@ -874,7 +833,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
}
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
- if (unlikely(count && netif_carrier_ok(tx_ring->netdev) &&
+ if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) &&
(ixgbe_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) {
/* Make sure that anybody stopping the queue after this
* sees the new next_to_clean.
@@ -887,7 +846,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
}
}
- return count < q_vector->tx.work_limit;
+ return !!budget;
}
#ifdef CONFIG_IXGBE_DCA
@@ -903,12 +862,12 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK;
- rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
+ rxctrl |= dca3_get_tag(rx_ring->dev, cpu);
break;
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK_82599;
- rxctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) <<
+ rxctrl |= (dca3_get_tag(rx_ring->dev, cpu) <<
IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599);
break;
default:
@@ -932,7 +891,7 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
case ixgbe_mac_82598EB:
txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(reg_idx));
txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK;
- txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
+ txctrl |= dca3_get_tag(tx_ring->dev, cpu);
txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(reg_idx), txctrl);
break;
@@ -940,7 +899,7 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
case ixgbe_mac_X540:
txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx));
txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599;
- txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) <<
+ txctrl |= (dca3_get_tag(tx_ring->dev, cpu) <<
IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599);
txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx), txctrl);
@@ -953,26 +912,17 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
static void ixgbe_update_dca(struct ixgbe_q_vector *q_vector)
{
struct ixgbe_adapter *adapter = q_vector->adapter;
+ struct ixgbe_ring *ring;
int cpu = get_cpu();
- long r_idx;
- int i;
if (q_vector->cpu == cpu)
goto out_no_update;
- r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
- for (i = 0; i < q_vector->tx.count; i++) {
- ixgbe_update_tx_dca(adapter, adapter->tx_ring[r_idx], cpu);
- r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
- r_idx + 1);
- }
+ for (ring = q_vector->tx.ring; ring != NULL; ring = ring->next)
+ ixgbe_update_tx_dca(adapter, ring, cpu);
- r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
- for (i = 0; i < q_vector->rx.count; i++) {
- ixgbe_update_rx_dca(adapter, adapter->rx_ring[r_idx], cpu);
- r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
- r_idx + 1);
- }
+ for (ring = q_vector->rx.ring; ring != NULL; ring = ring->next)
+ ixgbe_update_rx_dca(adapter, ring, cpu);
q_vector->cpu = cpu;
out_no_update:
@@ -1285,9 +1235,9 @@ static inline bool ixgbe_get_rsc_state(union ixgbe_adv_rx_desc *rx_desc)
IXGBE_RXDADV_RSCCNT_MASK);
}
-static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
+static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
struct ixgbe_ring *rx_ring,
- int *work_done, int work_to_do)
+ int budget)
{
struct ixgbe_adapter *adapter = q_vector->adapter;
union ixgbe_adv_rx_desc *rx_desc, *next_rxd;
@@ -1376,7 +1326,7 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
skb->len += upper_len;
skb->data_len += upper_len;
- skb->truesize += upper_len;
+ skb->truesize += PAGE_SIZE / 2;
}
i++;
@@ -1467,11 +1417,11 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
#endif /* IXGBE_FCOE */
ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc);
+ budget--;
next_desc:
rx_desc->wb.upper.status_error = 0;
- (*work_done)++;
- if (*work_done >= work_to_do)
+ if (!budget)
break;
/* return some buffers to hardware, one at a time is too slow */
@@ -1512,9 +1462,10 @@ next_desc:
u64_stats_update_end(&rx_ring->syncp);
q_vector->rx.total_packets += total_rx_packets;
q_vector->rx.total_bytes += total_rx_bytes;
+
+ return !!budget;
}
-static int ixgbe_clean_rxonly(struct napi_struct *, int);
/**
* ixgbe_configure_msix - Configure MSI-X hardware
* @adapter: board private structure
@@ -1525,61 +1476,46 @@ static int ixgbe_clean_rxonly(struct napi_struct *, int);
static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
{
struct ixgbe_q_vector *q_vector;
- int i, q_vectors, v_idx, r_idx;
+ int q_vectors, v_idx;
u32 mask;
q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+ /* Populate MSIX to EITR Select */
+ if (adapter->num_vfs > 32) {
+ u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, eitrsel);
+ }
+
/*
* Populate the IVAR table and set the ITR values to the
* corresponding register.
*/
for (v_idx = 0; v_idx < q_vectors; v_idx++) {
+ struct ixgbe_ring *ring;
q_vector = adapter->q_vector[v_idx];
- /* XXX for_each_set_bit(...) */
- r_idx = find_first_bit(q_vector->rx.idx,
- adapter->num_rx_queues);
-
- for (i = 0; i < q_vector->rx.count; i++) {
- u8 reg_idx = adapter->rx_ring[r_idx]->reg_idx;
- ixgbe_set_ivar(adapter, 0, reg_idx, v_idx);
- r_idx = find_next_bit(q_vector->rx.idx,
- adapter->num_rx_queues,
- r_idx + 1);
- }
- r_idx = find_first_bit(q_vector->tx.idx,
- adapter->num_tx_queues);
-
- for (i = 0; i < q_vector->tx.count; i++) {
- u8 reg_idx = adapter->tx_ring[r_idx]->reg_idx;
- ixgbe_set_ivar(adapter, 1, reg_idx, v_idx);
- r_idx = find_next_bit(q_vector->tx.idx,
- adapter->num_tx_queues,
- r_idx + 1);
- }
- if (q_vector->tx.count && !q_vector->rx.count)
- /* tx only */
- q_vector->eitr = adapter->tx_eitr_param;
- else if (q_vector->rx.count)
- /* rx or mixed */
- q_vector->eitr = adapter->rx_eitr_param;
+ for (ring = q_vector->rx.ring; ring != NULL; ring = ring->next)
+ ixgbe_set_ivar(adapter, 0, ring->reg_idx, v_idx);
- ixgbe_write_eitr(q_vector);
- /* If ATR is enabled, set interrupt affinity */
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
- /*
- * Allocate the affinity_hint cpumask, assign the mask
- * for this vector, and set our affinity_hint for
- * this irq.
- */
- if (!alloc_cpumask_var(&q_vector->affinity_mask,
- GFP_KERNEL))
- return;
- cpumask_set_cpu(v_idx, q_vector->affinity_mask);
- irq_set_affinity_hint(adapter->msix_entries[v_idx].vector,
- q_vector->affinity_mask);
+ for (ring = q_vector->tx.ring; ring != NULL; ring = ring->next)
+ 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);
}
switch (adapter->hw.mac.type) {
@@ -1591,7 +1527,6 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
case ixgbe_mac_X540:
ixgbe_set_ivar(adapter, -1, 1, v_idx);
break;
-
default:
break;
}
@@ -1599,12 +1534,10 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
/* set up to autoclear timer, and the vectors */
mask = IXGBE_EIMS_ENABLE_MASK;
- if (adapter->num_vfs)
- mask &= ~(IXGBE_EIMS_OTHER |
- IXGBE_EIMS_MAILBOX |
- IXGBE_EIMS_LSC);
- else
- mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC);
+ mask &= ~(IXGBE_EIMS_OTHER |
+ IXGBE_EIMS_MAILBOX |
+ IXGBE_EIMS_LSC);
+
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, mask);
}
@@ -1649,7 +1582,7 @@ static void ixgbe_update_itr(struct ixgbe_q_vector *q_vector,
* 100-1249MB/s bulk (8000 ints/s)
*/
/* what was last interrupt timeslice? */
- timepassed_us = 1000000/q_vector->eitr;
+ timepassed_us = q_vector->itr >> 2;
bytes_perint = bytes / timepassed_us; /* bytes/usec */
switch (itr_setting) {
@@ -1690,7 +1623,7 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector)
struct ixgbe_adapter *adapter = q_vector->adapter;
struct ixgbe_hw *hw = &adapter->hw;
int v_idx = q_vector->v_idx;
- u32 itr_reg = EITR_INTS_PER_SEC_TO_REG(q_vector->eitr);
+ u32 itr_reg = q_vector->itr;
switch (adapter->hw.mac.type) {
case ixgbe_mac_82598EB:
@@ -1700,15 +1633,6 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector)
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
/*
- * 82599 and X540 can support a value of zero, so allow it for
- * max interrupt rate, but there is an errata where it can
- * not be zero with RSC
- */
- if (itr_reg == 8 &&
- !(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))
- itr_reg = 0;
-
- /*
* set the WDIS bit to not clear the timer bits and cause an
* immediate assertion of the interrupt
*/
@@ -1722,7 +1646,7 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector)
static void ixgbe_set_itr(struct ixgbe_q_vector *q_vector)
{
- u32 new_itr = q_vector->eitr;
+ u32 new_itr = q_vector->itr;
u8 current_itr;
ixgbe_update_itr(q_vector, &q_vector->tx);
@@ -1733,24 +1657,25 @@ static void ixgbe_set_itr(struct ixgbe_q_vector *q_vector)
switch (current_itr) {
/* counts and packets in update_itr are dependent on these numbers */
case lowest_latency:
- new_itr = 100000;
+ new_itr = IXGBE_100K_ITR;
break;
case low_latency:
- new_itr = 20000; /* aka hwitr = ~200 */
+ new_itr = IXGBE_20K_ITR;
break;
case bulk_latency:
- new_itr = 8000;
+ new_itr = IXGBE_8K_ITR;
break;
default:
break;
}
- if (new_itr != q_vector->eitr) {
+ if (new_itr != q_vector->itr) {
/* do an exponential smoothing */
- new_itr = ((q_vector->eitr * 9) + new_itr)/10;
+ new_itr = (10 * new_itr * q_vector->itr) /
+ ((9 * new_itr) + q_vector->itr);
/* save the algorithm value here */
- q_vector->eitr = new_itr;
+ q_vector->itr = new_itr & IXGBE_MAX_EITR;
ixgbe_write_eitr(q_vector);
}
@@ -1827,6 +1752,39 @@ static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr)
}
}
+static void ixgbe_check_overtemp_event(struct ixgbe_adapter *adapter, u32 eicr)
+{
+ if (!(adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE))
+ return;
+
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ /*
+ * Need to check link state so complete overtemp check
+ * on service task
+ */
+ if (((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC)) &&
+ (!test_bit(__IXGBE_DOWN, &adapter->state))) {
+ adapter->interrupt_event = eicr;
+ adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_EVENT;
+ ixgbe_service_event_schedule(adapter);
+ return;
+ }
+ return;
+ case ixgbe_mac_X540:
+ if (!(eicr & IXGBE_EICR_TS))
+ return;
+ break;
+ default:
+ return;
+ }
+
+ e_crit(drv,
+ "Network adapter has been stopped because it has over heated. "
+ "Restart the computer. If the problem persists, "
+ "power off the system and replace the adapter\n");
+}
+
static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr)
{
struct ixgbe_hw *hw = &adapter->hw;
@@ -1864,72 +1822,6 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
}
}
-static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
-{
- struct ixgbe_adapter *adapter = data;
- struct ixgbe_hw *hw = &adapter->hw;
- u32 eicr;
-
- /*
- * Workaround for Silicon errata. Use clear-by-write instead
- * of clear-by-read. Reading with EICS will return the
- * interrupt causes without clearing, which later be done
- * with the write to EICR.
- */
- eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
- IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr);
-
- if (eicr & IXGBE_EICR_LSC)
- ixgbe_check_lsc(adapter);
-
- if (eicr & IXGBE_EICR_MAILBOX)
- ixgbe_msg_task(adapter);
-
- switch (hw->mac.type) {
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- /* Handle Flow Director Full threshold interrupt */
- if (eicr & IXGBE_EICR_FLOW_DIR) {
- int reinit_count = 0;
- int i;
- for (i = 0; i < adapter->num_tx_queues; i++) {
- struct ixgbe_ring *ring = adapter->tx_ring[i];
- if (test_and_clear_bit(__IXGBE_TX_FDIR_INIT_DONE,
- &ring->state))
- reinit_count++;
- }
- if (reinit_count) {
- /* no more flow director interrupts until after init */
- IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR);
- eicr &= ~IXGBE_EICR_FLOW_DIR;
- adapter->flags2 |= IXGBE_FLAG2_FDIR_REQUIRES_REINIT;
- ixgbe_service_event_schedule(adapter);
- }
- }
- ixgbe_check_sfp_event(adapter, eicr);
- if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
- ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) {
- if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
- adapter->interrupt_event = eicr;
- adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_EVENT;
- ixgbe_service_event_schedule(adapter);
- }
- }
- break;
- default:
- break;
- }
-
- ixgbe_check_fan_failure(adapter, eicr);
-
- /* re-enable the original interrupt state, no lsc, no queues */
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, eicr &
- ~(IXGBE_EIMS_LSC | IXGBE_EIMS_RTX_QUEUE));
-
- return IRQ_HANDLED;
-}
-
static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
u64 qmask)
{
@@ -1982,232 +1874,124 @@ static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
/* skip the flush */
}
-static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
-{
- struct ixgbe_q_vector *q_vector = data;
- struct ixgbe_adapter *adapter = q_vector->adapter;
- struct ixgbe_ring *tx_ring;
- int i, r_idx;
-
- if (!q_vector->tx.count)
- return IRQ_HANDLED;
-
- r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
- for (i = 0; i < q_vector->tx.count; i++) {
- tx_ring = adapter->tx_ring[r_idx];
- r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
- r_idx + 1);
- }
-
- /* EIAM disabled interrupts (on this vector) for us */
- napi_schedule(&q_vector->napi);
-
- return IRQ_HANDLED;
-}
-
/**
- * ixgbe_msix_clean_rx - single unshared vector rx clean (all queues)
- * @irq: unused
- * @data: pointer to our q_vector struct for this interrupt vector
+ * ixgbe_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
**/
-static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
-{
- struct ixgbe_q_vector *q_vector = data;
- struct ixgbe_adapter *adapter = q_vector->adapter;
- struct ixgbe_ring *rx_ring;
- int r_idx;
- int i;
-
-#ifdef CONFIG_IXGBE_DCA
- if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
- ixgbe_update_dca(q_vector);
-#endif
-
- r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
- for (i = 0; i < q_vector->rx.count; i++) {
- rx_ring = adapter->rx_ring[r_idx];
- r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
- r_idx + 1);
- }
-
- if (!q_vector->rx.count)
- return IRQ_HANDLED;
-
- /* EIAM disabled interrupts (on this vector) for us */
- napi_schedule(&q_vector->napi);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
+static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
+ bool flush)
{
- struct ixgbe_q_vector *q_vector = data;
- struct ixgbe_adapter *adapter = q_vector->adapter;
- struct ixgbe_ring *ring;
- int r_idx;
- int i;
-
- if (!q_vector->tx.count && !q_vector->rx.count)
- return IRQ_HANDLED;
+ u32 mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
- r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
- for (i = 0; i < q_vector->tx.count; i++) {
- ring = adapter->tx_ring[r_idx];
- r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
- r_idx + 1);
- }
+ /* don't reenable LSC while waiting for link */
+ if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)
+ mask &= ~IXGBE_EIMS_LSC;
- r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
- for (i = 0; i < q_vector->rx.count; i++) {
- ring = adapter->rx_ring[r_idx];
- r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
- r_idx + 1);
+ if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ mask |= IXGBE_EIMS_GPI_SDP0;
+ break;
+ case ixgbe_mac_X540:
+ mask |= IXGBE_EIMS_TS;
+ break;
+ default:
+ break;
+ }
+ if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
+ mask |= IXGBE_EIMS_GPI_SDP1;
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ mask |= IXGBE_EIMS_GPI_SDP1;
+ mask |= IXGBE_EIMS_GPI_SDP2;
+ case ixgbe_mac_X540:
+ mask |= IXGBE_EIMS_ECC;
+ mask |= IXGBE_EIMS_MAILBOX;
+ break;
+ default:
+ break;
}
+ if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
+ !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT))
+ mask |= IXGBE_EIMS_FLOW_DIR;
- /* EIAM disabled interrupts (on this vector) for us */
- napi_schedule(&q_vector->napi);
-
- return IRQ_HANDLED;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
+ if (queues)
+ ixgbe_irq_enable_queues(adapter, ~0);
+ if (flush)
+ IXGBE_WRITE_FLUSH(&adapter->hw);
}
-/**
- * ixgbe_clean_rxonly - msix (aka one shot) rx clean routine
- * @napi: napi struct with our devices info in it
- * @budget: amount of work driver is allowed to do this pass, in packets
- *
- * This function is optimized for cleaning one queue only on a single
- * q_vector!!!
- **/
-static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
+static irqreturn_t ixgbe_msix_other(int irq, void *data)
{
- struct ixgbe_q_vector *q_vector =
- container_of(napi, struct ixgbe_q_vector, napi);
- struct ixgbe_adapter *adapter = q_vector->adapter;
- struct ixgbe_ring *rx_ring = NULL;
- int work_done = 0;
- long r_idx;
+ struct ixgbe_adapter *adapter = data;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 eicr;
-#ifdef CONFIG_IXGBE_DCA
- if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
- ixgbe_update_dca(q_vector);
-#endif
+ /*
+ * Workaround for Silicon errata. Use clear-by-write instead
+ * of clear-by-read. Reading with EICS will return the
+ * interrupt causes without clearing, which later be done
+ * with the write to EICR.
+ */
+ eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr);
- r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
- rx_ring = adapter->rx_ring[r_idx];
+ if (eicr & IXGBE_EICR_LSC)
+ ixgbe_check_lsc(adapter);
- ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget);
+ if (eicr & IXGBE_EICR_MAILBOX)
+ ixgbe_msg_task(adapter);
- /* If all Rx work done, exit the polling mode */
- if (work_done < budget) {
- napi_complete(napi);
- if (adapter->rx_itr_setting & 1)
- ixgbe_set_itr(q_vector);
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_enable_queues(adapter,
- ((u64)1 << q_vector->v_idx));
+ switch (hw->mac.type) {
+ case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
+ if (eicr & IXGBE_EICR_ECC)
+ e_info(link, "Received unrecoverable ECC Err, please "
+ "reboot\n");
+ /* Handle Flow Director Full threshold interrupt */
+ if (eicr & IXGBE_EICR_FLOW_DIR) {
+ int reinit_count = 0;
+ int i;
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct ixgbe_ring *ring = adapter->tx_ring[i];
+ if (test_and_clear_bit(__IXGBE_TX_FDIR_INIT_DONE,
+ &ring->state))
+ reinit_count++;
+ }
+ if (reinit_count) {
+ /* no more flow director interrupts until after init */
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR);
+ adapter->flags2 |= IXGBE_FLAG2_FDIR_REQUIRES_REINIT;
+ ixgbe_service_event_schedule(adapter);
+ }
+ }
+ ixgbe_check_sfp_event(adapter, eicr);
+ ixgbe_check_overtemp_event(adapter, eicr);
+ break;
+ default:
+ break;
}
- return work_done;
-}
-
-/**
- * ixgbe_clean_rxtx_many - msix (aka one shot) rx clean routine
- * @napi: napi struct with our devices info in it
- * @budget: amount of work driver is allowed to do this pass, in packets
- *
- * This function will clean more than one rx queue associated with a
- * q_vector.
- **/
-static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
-{
- struct ixgbe_q_vector *q_vector =
- container_of(napi, struct ixgbe_q_vector, napi);
- struct ixgbe_adapter *adapter = q_vector->adapter;
- struct ixgbe_ring *ring = NULL;
- int work_done = 0, i;
- long r_idx;
- bool tx_clean_complete = true;
-
-#ifdef CONFIG_IXGBE_DCA
- if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
- ixgbe_update_dca(q_vector);
-#endif
-
- r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
- for (i = 0; i < q_vector->tx.count; i++) {
- ring = adapter->tx_ring[r_idx];
- tx_clean_complete &= ixgbe_clean_tx_irq(q_vector, ring);
- r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
- r_idx + 1);
- }
+ ixgbe_check_fan_failure(adapter, eicr);
- /* attempt to distribute budget to each queue fairly, but don't allow
- * the budget to go below 1 because we'll exit polling */
- budget /= (q_vector->rx.count ?: 1);
- budget = max(budget, 1);
- r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
- for (i = 0; i < q_vector->rx.count; i++) {
- ring = adapter->rx_ring[r_idx];
- ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget);
- r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
- r_idx + 1);
- }
-
- r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
- ring = adapter->rx_ring[r_idx];
- /* If all Rx work done, exit the polling mode */
- if (work_done < budget) {
- napi_complete(napi);
- if (adapter->rx_itr_setting & 1)
- ixgbe_set_itr(q_vector);
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_enable_queues(adapter,
- ((u64)1 << q_vector->v_idx));
- return 0;
- }
+ /* re-enable the original interrupt state, no lsc, no queues */
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ ixgbe_irq_enable(adapter, false, false);
- return work_done;
+ return IRQ_HANDLED;
}
-/**
- * ixgbe_clean_txonly - msix (aka one shot) tx clean routine
- * @napi: napi struct with our devices info in it
- * @budget: amount of work driver is allowed to do this pass, in packets
- *
- * This function is optimized for cleaning one queue only on a single
- * q_vector!!!
- **/
-static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
+static irqreturn_t ixgbe_msix_clean_rings(int irq, void *data)
{
- struct ixgbe_q_vector *q_vector =
- container_of(napi, struct ixgbe_q_vector, napi);
- struct ixgbe_adapter *adapter = q_vector->adapter;
- struct ixgbe_ring *tx_ring = NULL;
- int work_done = 0;
- long r_idx;
-
-#ifdef CONFIG_IXGBE_DCA
- if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
- ixgbe_update_dca(q_vector);
-#endif
-
- r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
- tx_ring = adapter->tx_ring[r_idx];
+ struct ixgbe_q_vector *q_vector = data;
- if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
- work_done = budget;
+ /* EIAM disabled interrupts (on this vector) for us */
- /* If all Tx work done, exit the polling mode */
- if (work_done < budget) {
- napi_complete(napi);
- if (adapter->tx_itr_setting & 1)
- ixgbe_set_itr(q_vector);
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_enable_queues(adapter,
- ((u64)1 << q_vector->v_idx));
- }
+ if (q_vector->rx.ring || q_vector->tx.ring)
+ napi_schedule(&q_vector->napi);
- return work_done;
+ return IRQ_HANDLED;
}
static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
@@ -2216,9 +2000,10 @@ static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
struct ixgbe_ring *rx_ring = a->rx_ring[r_idx];
- set_bit(r_idx, q_vector->rx.idx);
- q_vector->rx.count++;
rx_ring->q_vector = q_vector;
+ rx_ring->next = q_vector->rx.ring;
+ q_vector->rx.ring = rx_ring;
+ q_vector->rx.count++;
}
static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
@@ -2227,9 +2012,10 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
struct ixgbe_ring *tx_ring = a->tx_ring[t_idx];
- set_bit(t_idx, q_vector->tx.idx);
- q_vector->tx.count++;
tx_ring->q_vector = q_vector;
+ tx_ring->next = q_vector->tx.ring;
+ q_vector->tx.ring = tx_ring;
+ q_vector->tx.count++;
q_vector->tx.work_limit = a->tx_work_limit;
}
@@ -2243,59 +2029,41 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
* group the rings as "efficiently" as possible. You would add new
* mapping configurations in here.
**/
-static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter)
+static void ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter)
{
- int q_vectors;
+ int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+ int rxr_remaining = adapter->num_rx_queues, rxr_idx = 0;
+ int txr_remaining = adapter->num_tx_queues, txr_idx = 0;
int v_start = 0;
- int rxr_idx = 0, txr_idx = 0;
- int rxr_remaining = adapter->num_rx_queues;
- int txr_remaining = adapter->num_tx_queues;
- int i, j;
- int rqpv, tqpv;
- int err = 0;
- /* No mapping required if MSI-X is disabled. */
+ /* only one q_vector if MSI-X is disabled. */
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
- goto out;
-
- q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+ q_vectors = 1;
/*
- * The ideal configuration...
- * We have enough vectors to map one per queue.
+ * If we don't have enough vectors for a 1-to-1 mapping, we'll have to
+ * group them so there are multiple queues per vector.
+ *
+ * Re-adjusting *qpv takes care of the remainder.
*/
- if (q_vectors == adapter->num_rx_queues + adapter->num_tx_queues) {
- for (; rxr_idx < rxr_remaining; v_start++, rxr_idx++)
+ for (; v_start < q_vectors && rxr_remaining; v_start++) {
+ int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_start);
+ for (; rqpv; rqpv--, rxr_idx++, rxr_remaining--)
map_vector_to_rxq(adapter, v_start, rxr_idx);
-
- for (; txr_idx < txr_remaining; v_start++, txr_idx++)
- map_vector_to_txq(adapter, v_start, txr_idx);
-
- goto out;
}
/*
- * If we don't have enough vectors for a 1-to-1
- * mapping, we'll have to group them so there are
- * multiple queues per vector.
+ * If there are not enough q_vectors for each ring to have it's own
+ * vector then we must pair up Rx/Tx on a each vector
*/
- /* Re-adjusting *qpv takes care of the remainder. */
- for (i = v_start; i < q_vectors; i++) {
- rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - i);
- for (j = 0; j < rqpv; j++) {
- map_vector_to_rxq(adapter, i, rxr_idx);
- rxr_idx++;
- rxr_remaining--;
- }
- tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - i);
- for (j = 0; j < tqpv; j++) {
- map_vector_to_txq(adapter, i, txr_idx);
- txr_idx++;
- txr_remaining--;
- }
+ if ((v_start + txr_remaining) > q_vectors)
+ v_start = 0;
+
+ for (; v_start < q_vectors && txr_remaining; v_start++) {
+ int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_start);
+ for (; tqpv; tqpv--, txr_idx++, txr_remaining--)
+ map_vector_to_txq(adapter, v_start, txr_idx);
}
-out:
- return err;
}
/**
@@ -2308,53 +2076,45 @@ out:
static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- irqreturn_t (*handler)(int, void *);
- int i, vector, q_vectors, err;
+ int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+ int vector, err;
int ri = 0, ti = 0;
- /* Decrement for Other and TCP Timer vectors */
- q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
-
- err = ixgbe_map_rings_to_vectors(adapter);
- if (err)
- return err;
-
-#define SET_HANDLER(_v) (((_v)->rx.count && (_v)->tx.count) \
- ? &ixgbe_msix_clean_many : \
- (_v)->rx.count ? &ixgbe_msix_clean_rx : \
- (_v)->tx.count ? &ixgbe_msix_clean_tx : \
- NULL)
for (vector = 0; vector < q_vectors; vector++) {
struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
- handler = SET_HANDLER(q_vector);
+ struct msix_entry *entry = &adapter->msix_entries[vector];
- if (handler == &ixgbe_msix_clean_rx) {
+ if (q_vector->tx.ring && q_vector->rx.ring) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
- "%s-%s-%d", netdev->name, "rx", ri++);
- } else if (handler == &ixgbe_msix_clean_tx) {
+ "%s-%s-%d", netdev->name, "TxRx", ri++);
+ ti++;
+ } else if (q_vector->rx.ring) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
- "%s-%s-%d", netdev->name, "tx", ti++);
- } else if (handler == &ixgbe_msix_clean_many) {
+ "%s-%s-%d", netdev->name, "rx", ri++);
+ } else if (q_vector->tx.ring) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
- "%s-%s-%d", netdev->name, "TxRx", ri++);
- ti++;
+ "%s-%s-%d", netdev->name, "tx", ti++);
} else {
/* skip this unused q_vector */
continue;
}
- err = request_irq(adapter->msix_entries[vector].vector,
- handler, 0, q_vector->name,
- q_vector);
+ err = request_irq(entry->vector, &ixgbe_msix_clean_rings, 0,
+ q_vector->name, q_vector);
if (err) {
e_err(probe, "request_irq failed for MSIX interrupt "
"Error: %d\n", err);
goto free_queue_irqs;
}
+ /* If Flow Director is enabled, set interrupt affinity */
+ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
+ /* assign the mask for this irq */
+ irq_set_affinity_hint(entry->vector,
+ q_vector->affinity_mask);
+ }
}
- sprintf(adapter->lsc_int_name, "%s:lsc", netdev->name);
err = request_irq(adapter->msix_entries[vector].vector,
- ixgbe_msix_lsc, 0, adapter->lsc_int_name, adapter);
+ ixgbe_msix_other, 0, netdev->name, adapter);
if (err) {
e_err(probe, "request_irq for msix_lsc failed: %d\n", err);
goto free_queue_irqs;
@@ -2363,9 +2123,13 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
return 0;
free_queue_irqs:
- for (i = vector - 1; i >= 0; i--)
- free_irq(adapter->msix_entries[--vector].vector,
- adapter->q_vector[i]);
+ while (vector) {
+ vector--;
+ irq_set_affinity_hint(adapter->msix_entries[vector].vector,
+ NULL);
+ free_irq(adapter->msix_entries[vector].vector,
+ adapter->q_vector[vector]);
+ }
adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries);
@@ -2374,47 +2138,6 @@ free_queue_irqs:
}
/**
- * ixgbe_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
-static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
- bool flush)
-{
- u32 mask;
-
- mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
- if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
- mask |= IXGBE_EIMS_GPI_SDP0;
- if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
- mask |= IXGBE_EIMS_GPI_SDP1;
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- mask |= IXGBE_EIMS_ECC;
- mask |= IXGBE_EIMS_GPI_SDP1;
- mask |= IXGBE_EIMS_GPI_SDP2;
- if (adapter->num_vfs)
- mask |= IXGBE_EIMS_MAILBOX;
- break;
- default:
- break;
- }
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
- mask |= IXGBE_EIMS_FLOW_DIR;
-
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
- if (queues)
- ixgbe_irq_enable_queues(adapter, ~0);
- if (flush)
- IXGBE_WRITE_FLUSH(&adapter->hw);
-
- if (adapter->num_vfs > 32) {
- u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, eitrsel);
- }
-}
-
-/**
* ixgbe_intr - legacy mode Interrupt Handler
* @irq: interrupt number
* @data: pointer to a network interface device structure
@@ -2454,14 +2177,12 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
switch (hw->mac.type) {
case ixgbe_mac_82599EB:
ixgbe_check_sfp_event(adapter, eicr);
- if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
- ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) {
- if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
- adapter->interrupt_event = eicr;
- adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_EVENT;
- ixgbe_service_event_schedule(adapter);
- }
- }
+ /* Fall through */
+ case ixgbe_mac_X540:
+ if (eicr & IXGBE_EICR_ECC)
+ e_info(link, "Received unrecoverable ECC err, please "
+ "reboot\n");
+ ixgbe_check_overtemp_event(adapter, eicr);
break;
default:
break;
@@ -2487,14 +2208,26 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter)
{
- int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+ int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+ int i;
+
+ /* legacy and MSI only use one vector */
+ if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
+ q_vectors = 1;
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ adapter->rx_ring[i]->q_vector = NULL;
+ adapter->rx_ring[i]->next = NULL;
+ }
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ adapter->tx_ring[i]->q_vector = NULL;
+ adapter->tx_ring[i]->next = NULL;
+ }
for (i = 0; i < q_vectors; i++) {
struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
- bitmap_zero(q_vector->rx.idx, MAX_RX_QUEUES);
- bitmap_zero(q_vector->tx.idx, MAX_TX_QUEUES);
- q_vector->rx.count = 0;
- q_vector->tx.count = 0;
+ memset(&q_vector->rx, 0, sizeof(struct ixgbe_ring_container));
+ memset(&q_vector->tx, 0, sizeof(struct ixgbe_ring_container));
}
}
@@ -2510,19 +2243,25 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
struct net_device *netdev = adapter->netdev;
int err;
- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+ /* map all of the rings to the q_vectors */
+ ixgbe_map_rings_to_vectors(adapter);
+
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
err = ixgbe_request_msix_irqs(adapter);
- } else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
+ else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED)
err = request_irq(adapter->pdev->irq, ixgbe_intr, 0,
netdev->name, adapter);
- } else {
+ else
err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED,
netdev->name, adapter);
- }
- if (err)
+ if (err) {
e_err(probe, "request_irq failed, Error %d\n", err);
+ /* place q_vectors and rings back into a known good state */
+ ixgbe_reset_q_vectors(adapter);
+ }
+
return err;
}
@@ -2532,25 +2271,29 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
int i, q_vectors;
q_vectors = adapter->num_msix_vectors;
-
i = q_vectors - 1;
free_irq(adapter->msix_entries[i].vector, adapter);
-
i--;
+
for (; i >= 0; i--) {
/* free only the irqs that were actually requested */
- if (!adapter->q_vector[i]->rx.count &&
- !adapter->q_vector[i]->tx.count)
+ if (!adapter->q_vector[i]->rx.ring &&
+ !adapter->q_vector[i]->tx.ring)
continue;
+ /* clear the affinity_mask in the IRQ descriptor */
+ irq_set_affinity_hint(adapter->msix_entries[i].vector,
+ NULL);
+
free_irq(adapter->msix_entries[i].vector,
adapter->q_vector[i]);
}
-
- ixgbe_reset_q_vectors(adapter);
} else {
free_irq(adapter->pdev->irq, adapter);
}
+
+ /* clear q_vector state information */
+ ixgbe_reset_q_vectors(adapter);
}
/**
@@ -2568,8 +2311,6 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
- if (adapter->num_vfs > 32)
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, 0);
break;
default:
break;
@@ -2590,17 +2331,19 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
**/
static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
{
- struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
- IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
- EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param));
+ /* 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);
ixgbe_set_ivar(adapter, 1, 0, 0);
- map_vector_to_rxq(adapter, 0, 0);
- map_vector_to_txq(adapter, 0, 0);
-
e_info(hw, "Legacy interrupt IVAR setup done\n");
}
@@ -2617,13 +2360,11 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
struct ixgbe_hw *hw = &adapter->hw;
u64 tdba = ring->dma;
int wait_loop = 10;
- u32 txdctl;
+ u32 txdctl = IXGBE_TXDCTL_ENABLE;
u8 reg_idx = ring->reg_idx;
/* disable queue to avoid issues while updating state */
- txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
- IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx),
- txdctl & ~IXGBE_TXDCTL_ENABLE);
+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), 0);
IXGBE_WRITE_FLUSH(hw);
IXGBE_WRITE_REG(hw, IXGBE_TDBAL(reg_idx),
@@ -2635,18 +2376,22 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
IXGBE_WRITE_REG(hw, IXGBE_TDT(reg_idx), 0);
ring->tail = hw->hw_addr + IXGBE_TDT(reg_idx);
- /* configure fetching thresholds */
- if (adapter->rx_itr_setting == 0) {
- /* cannot set wthresh when itr==0 */
- txdctl &= ~0x007F0000;
- } else {
- /* enable WTHRESH=8 descriptors, to encourage burst writeback */
- txdctl |= (8 << 16);
- }
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- /* PThresh workaround for Tx hang with DFP enabled. */
- txdctl |= 32;
- }
+ /*
+ * set WTHRESH to encourage burst writeback, it should not be set
+ * higher than 1 when ITR is 0 as it could cause false TX hangs
+ *
+ * In order to avoid issues WTHRESH + PTHRESH should always be equal
+ * to or less than the number of on chip descriptors, which is
+ * currently 40.
+ */
+ if (!adapter->tx_itr_setting || !adapter->rx_itr_setting)
+ txdctl |= (1 << 16); /* WTHRESH = 1 */
+ else
+ txdctl |= (8 << 16); /* WTHRESH = 8 */
+
+ /* PTHRESH=32 is needed to avoid a Tx hang with DFP enabled. */
+ txdctl |= (1 << 8) | /* HTHRESH = 1 */
+ 32; /* PTHRESH = 32 */
/* reinitialize flowdirector state */
if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
@@ -2661,7 +2406,6 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
clear_bit(__IXGBE_HANG_CHECK_ARMED, &ring->state);
/* enable queue */
- txdctl |= IXGBE_TXDCTL_ENABLE;
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), txdctl);
/* TXDCTL.EN will return 0 on 82598 if link is down, so skip it */
@@ -2899,9 +2643,9 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
#endif
} else {
- if (rx_buf_len < IXGBE_RXBUFFER_4096)
+ if (rx_buf_len < IXGBE_RXBUFFER_4K)
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
- else if (rx_buf_len < IXGBE_RXBUFFER_8192)
+ else if (rx_buf_len < IXGBE_RXBUFFER_8K)
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
else
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
@@ -3072,6 +2816,7 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
u32 vt_reg_bits;
u32 reg_offset, vf_shift;
u32 vmdctl;
+ int i;
if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
return;
@@ -3107,9 +2852,13 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
/* Enable MAC Anti-Spoofing */
hw->mac.ops.set_mac_anti_spoofing(hw,
- (adapter->antispoofing_enabled =
- (adapter->num_vfs != 0)),
+ (adapter->num_vfs != 0),
adapter->num_vfs);
+ /* For VFs that have spoof checking turned off */
+ for (i = 0; i < adapter->num_vfs; i++) {
+ if (!adapter->vfinfo[i].spoofchk_enabled)
+ ixgbe_ndo_set_vf_spoofchk(adapter->netdev, i, false);
+ }
}
static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
@@ -3134,17 +2883,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
if (hw->mac.type == ixgbe_mac_82599EB)
adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
- /* Set the RX buffer length according to the mode */
- if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
- rx_buf_len = IXGBE_RX_HDR_SIZE;
- } else {
- if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
- (netdev->mtu <= ETH_DATA_LEN))
- rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
- else
- rx_buf_len = ALIGN(max_frame + VLAN_HLEN, 1024);
- }
-
#ifdef IXGBE_FCOE
/* adjust max frame to be able to do baby jumbo for FCoE */
if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
@@ -3160,6 +2898,30 @@ 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;
+
+ /* Set the RX buffer length according to the mode */
+ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+ rx_buf_len = IXGBE_RX_HDR_SIZE;
+ } else {
+ if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
+ (netdev->mtu <= ETH_DATA_LEN))
+ rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
+ /*
+ * Make best use of allocation by using all but 1K of a
+ * power of 2 allocation that will be used for skb->head.
+ */
+ else if (max_frame <= IXGBE_RXBUFFER_3K)
+ rx_buf_len = IXGBE_RXBUFFER_3K;
+ else if (max_frame <= IXGBE_RXBUFFER_7K)
+ rx_buf_len = IXGBE_RXBUFFER_7K;
+ else if (max_frame <= IXGBE_RXBUFFER_15K)
+ rx_buf_len = IXGBE_RXBUFFER_15K;
+ else
+ rx_buf_len = IXGBE_MAX_RXBUFFER;
+ }
+
hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
/* set jumbo enable since MHADD.MFS is keeping size locked at max_frame */
hlreg0 |= IXGBE_HLREG0_JUMBOEN;
@@ -3533,19 +3295,8 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
q_vectors = 1;
for (q_idx = 0; q_idx < q_vectors; q_idx++) {
- struct napi_struct *napi;
q_vector = adapter->q_vector[q_idx];
- napi = &q_vector->napi;
- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
- if (!q_vector->rx.count || !q_vector->tx.count) {
- if (q_vector->tx.count == 1)
- napi->poll = &ixgbe_clean_txonly;
- else if (q_vector->rx.count == 1)
- napi->poll = &ixgbe_clean_rxonly;
- }
- }
-
- napi_enable(napi);
+ napi_enable(&q_vector->napi);
}
}
@@ -3596,7 +3347,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
/* reconfigure the hardware */
if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE) {
-#ifdef CONFIG_FCOE
+#ifdef IXGBE_FCOE
if (adapter->netdev->features & NETIF_F_FCOE_MTU)
max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
#endif
@@ -3608,12 +3359,20 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
} else {
struct net_device *dev = adapter->netdev;
- if (adapter->ixgbe_ieee_ets)
- dev->dcbnl_ops->ieee_setets(dev,
- adapter->ixgbe_ieee_ets);
- if (adapter->ixgbe_ieee_pfc)
- dev->dcbnl_ops->ieee_setpfc(dev,
- adapter->ixgbe_ieee_pfc);
+ if (adapter->ixgbe_ieee_ets) {
+ struct ieee_ets *ets = adapter->ixgbe_ieee_ets;
+ int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
+
+ ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame);
+ }
+
+ if (adapter->ixgbe_ieee_pfc) {
+ struct ieee_pfc *pfc = adapter->ixgbe_ieee_pfc;
+ u8 *prio_tc = adapter->ixgbe_ieee_ets->prio_tc;
+
+ ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en,
+ prio_tc);
+ }
}
/* Enable RSS Hash per TC */
@@ -3633,20 +3392,142 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_RQTC, reg);
}
}
+#endif
+
+/* Additional bittime to account for IXGBE framing */
+#define IXGBE_ETH_FRAMING 20
+
+/*
+ * ixgbe_hpbthresh - calculate high water mark for flow control
+ *
+ * @adapter: board private structure to calculate for
+ * @pb - packet buffer to calculate
+ */
+static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct net_device *dev = adapter->netdev;
+ int link, tc, kb, marker;
+ u32 dv_id, rx_pba;
+
+ /* Calculate max LAN frame size */
+ tc = link = dev->mtu + ETH_HLEN + ETH_FCS_LEN + IXGBE_ETH_FRAMING;
+
+#ifdef IXGBE_FCOE
+ /* FCoE traffic class uses FCOE jumbo frames */
+ if (dev->features & NETIF_F_FCOE_MTU) {
+ int fcoe_pb = 0;
+
+#ifdef CONFIG_IXGBE_DCB
+ fcoe_pb = netdev_get_prio_tc_map(dev, adapter->fcoe.up);
#endif
+ if (fcoe_pb == pb && tc < IXGBE_FCOE_JUMBO_FRAME_SIZE)
+ tc = IXGBE_FCOE_JUMBO_FRAME_SIZE;
+ }
+#endif
-static void ixgbe_configure_pb(struct ixgbe_adapter *adapter)
+ /* Calculate delay value for device */
+ switch (hw->mac.type) {
+ case ixgbe_mac_X540:
+ dv_id = IXGBE_DV_X540(link, tc);
+ break;
+ default:
+ dv_id = IXGBE_DV(link, tc);
+ break;
+ }
+
+ /* Loopback switch introduces additional latency */
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+ dv_id += IXGBE_B2BT(tc);
+
+ /* Delay value is calculated in bit times convert to KB */
+ kb = IXGBE_BT2KB(dv_id);
+ rx_pba = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(pb)) >> 10;
+
+ marker = rx_pba - kb;
+
+ /* It is possible that the packet buffer is not large enough
+ * to provide required headroom. In this case throw an error
+ * to user and a do the best we can.
+ */
+ if (marker < 0) {
+ e_warn(drv, "Packet Buffer(%i) can not provide enough"
+ "headroom to support flow control."
+ "Decrease MTU or number of traffic classes\n", pb);
+ marker = tc + 1;
+ }
+
+ return marker;
+}
+
+/*
+ * ixgbe_lpbthresh - calculate low water mark for for flow control
+ *
+ * @adapter: board private structure to calculate for
+ * @pb - packet buffer to calculate
+ */
+static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct net_device *dev = adapter->netdev;
+ int tc;
+ u32 dv_id;
+
+ /* Calculate max LAN frame size */
+ tc = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
+
+ /* Calculate delay value for device */
+ switch (hw->mac.type) {
+ case ixgbe_mac_X540:
+ dv_id = IXGBE_LOW_DV_X540(tc);
+ break;
+ default:
+ dv_id = IXGBE_LOW_DV(tc);
+ break;
+ }
+
+ /* Delay value is calculated in bit times convert to KB */
+ return IXGBE_BT2KB(dv_id);
+}
+
+/*
+ * ixgbe_pbthresh_setup - calculate and setup high low water marks
+ */
+static void ixgbe_pbthresh_setup(struct ixgbe_adapter *adapter)
{
- int hdrm = 0;
+ struct ixgbe_hw *hw = &adapter->hw;
int num_tc = netdev_get_num_tc(adapter->netdev);
+ int i;
+
+ if (!num_tc)
+ num_tc = 1;
+
+ hw->fc.low_water = ixgbe_lpbthresh(adapter);
+
+ for (i = 0; i < num_tc; i++) {
+ hw->fc.high_water[i] = ixgbe_hpbthresh(adapter, i);
+
+ /* Low water marks must not be larger than high water marks */
+ if (hw->fc.low_water > hw->fc.high_water[i])
+ hw->fc.low_water = 0;
+ }
+}
+
+static void ixgbe_configure_pb(struct ixgbe_adapter *adapter)
+{
struct ixgbe_hw *hw = &adapter->hw;
+ int hdrm;
+ u8 tc = netdev_get_num_tc(adapter->netdev);
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
- hdrm = 64 << adapter->fdir_pballoc;
+ hdrm = 32 << adapter->fdir_pballoc;
+ else
+ hdrm = 0;
- hw->mac.ops.set_rxpba(&adapter->hw, num_tc, hdrm, PBA_STRATEGY_EQUAL);
+ hw->mac.ops.set_rxpba(hw, tc, hdrm, PBA_STRATEGY_EQUAL);
+ ixgbe_pbthresh_setup(adapter);
}
static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter)
@@ -3675,16 +3556,12 @@ static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter)
static void ixgbe_configure(struct ixgbe_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
- struct ixgbe_hw *hw = &adapter->hw;
- int i;
-
ixgbe_configure_pb(adapter);
#ifdef CONFIG_IXGBE_DCB
ixgbe_configure_dcb(adapter);
#endif
- ixgbe_set_rx_mode(netdev);
+ ixgbe_set_rx_mode(adapter->netdev);
ixgbe_restore_vlan(adapter);
#ifdef IXGBE_FCOE
@@ -3693,15 +3570,14 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
#endif /* IXGBE_FCOE */
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
- for (i = 0; i < adapter->num_tx_queues; i++)
- adapter->tx_ring[i]->atr_sample_rate =
- adapter->atr_sample_rate;
- ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
+ ixgbe_init_fdir_signature_82599(&adapter->hw,
+ adapter->fdir_pballoc);
} else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
ixgbe_init_fdir_perfect_82599(&adapter->hw,
adapter->fdir_pballoc);
ixgbe_fdir_filter_restore(adapter);
}
+
ixgbe_configure_virtualization(adapter);
ixgbe_configure_tx(adapter);
@@ -3720,6 +3596,9 @@ static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw)
case ixgbe_phy_sfp_active_unknown:
case ixgbe_phy_sfp_ftl_active:
return true;
+ case ixgbe_phy_nl:
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ return true;
default:
return false;
}
@@ -3812,6 +3691,20 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
gpie |= IXGBE_GPIE_VTMODE_64;
}
+ /* Enable Thermal over heat sensor interrupt */
+ if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) {
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ gpie |= IXGBE_SDP0_GPIEN;
+ break;
+ case ixgbe_mac_X540:
+ gpie |= IXGBE_EIMS_TS;
+ break;
+ default:
+ break;
+ }
+ }
+
/* Enable fan failure interrupt */
if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
gpie |= IXGBE_SDP1_GPIEN;
@@ -3824,7 +3717,7 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
}
-static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
+static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
int err;
@@ -3883,8 +3776,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
-
- return 0;
}
void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)
@@ -3908,12 +3799,12 @@ void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)
clear_bit(__IXGBE_RESETTING, &adapter->state);
}
-int ixgbe_up(struct ixgbe_adapter *adapter)
+void ixgbe_up(struct ixgbe_adapter *adapter)
{
/* hardware has been reset, we need to reload some things */
ixgbe_configure(adapter);
- return ixgbe_up_complete(adapter);
+ ixgbe_up_complete(adapter);
}
void ixgbe_reset(struct ixgbe_adapter *adapter)
@@ -4100,7 +3991,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
u32 rxctrl;
int i;
- int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
/* signal that we are down to the interrupt handler */
set_bit(__IXGBE_DOWN, &adapter->state);
@@ -4132,26 +4022,19 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
del_timer_sync(&adapter->service_timer);
- /* disable receive for all VFs and wait one second */
if (adapter->num_vfs) {
- /* ping all the active vfs to let them know we are going down */
- ixgbe_ping_all_vfs(adapter);
-
- /* Disable all VFTE/VFRE TX/RX */
- ixgbe_disable_tx_rx(adapter);
+ /* Clear EITR Select mapping */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, 0);
/* Mark all the VFs as inactive */
for (i = 0 ; i < adapter->num_vfs; i++)
adapter->vfinfo[i].clear_to_send = 0;
- }
- /* Cleanup the affinity_hint CPU mask memory and callback */
- for (i = 0; i < num_q_vectors; i++) {
- struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
- /* clear the affinity_mask in the IRQ descriptor */
- irq_set_affinity_hint(adapter->msix_entries[i]. vector, NULL);
- /* release the CPU mask memory */
- free_cpumask_var(q_vector->affinity_mask);
+ /* ping all the active vfs to let them know we are going down */
+ ixgbe_ping_all_vfs(adapter);
+
+ /* Disable all VFTE/VFRE TX/RX */
+ ixgbe_disable_tx_rx(adapter);
}
/* disable transmits in the hardware now that interrupts are off */
@@ -4203,28 +4086,41 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
struct ixgbe_q_vector *q_vector =
container_of(napi, struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter;
- int tx_clean_complete, work_done = 0;
+ struct ixgbe_ring *ring;
+ int per_ring_budget;
+ bool clean_complete = true;
#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
ixgbe_update_dca(q_vector);
#endif
- tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring[0]);
- ixgbe_clean_rx_irq(q_vector, adapter->rx_ring[0], &work_done, budget);
+ for (ring = q_vector->tx.ring; ring != NULL; ring = ring->next)
+ clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring);
- if (!tx_clean_complete)
- work_done = budget;
+ /* attempt to distribute budget to each queue fairly, but don't allow
+ * the budget to go below 1 because we'll exit polling */
+ if (q_vector->rx.count > 1)
+ per_ring_budget = max(budget/q_vector->rx.count, 1);
+ else
+ per_ring_budget = budget;
- /* If budget not fully consumed, exit the polling mode */
- if (work_done < budget) {
- napi_complete(napi);
- if (adapter->rx_itr_setting & 1)
- ixgbe_set_itr(q_vector);
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
- }
- return work_done;
+ for (ring = q_vector->rx.ring; ring != NULL; ring = ring->next)
+ clean_complete &= ixgbe_clean_rx_irq(q_vector, ring,
+ per_ring_budget);
+
+ /* If all work not completed, return budget and keep polling */
+ if (!clean_complete)
+ return budget;
+
+ /* all work done, exit the polling mode */
+ napi_complete(napi);
+ if (adapter->rx_itr_setting & 1)
+ ixgbe_set_itr(q_vector);
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
+
+ return 0;
}
/**
@@ -4352,7 +4248,6 @@ static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter)
q = min((int)num_online_cpus(), per_tc_q);
for (i = 0; i < tcs; i++) {
- netdev_set_prio_tc_map(dev, i, i);
netdev_set_tc_queue(dev, i, q, offset);
offset += q;
}
@@ -4536,7 +4431,7 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
break;
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
- if (num_tcs == 8) {
+ if (num_tcs > 4) {
if (tc < 3) {
*tx = tc << 5;
*rx = tc << 4;
@@ -4547,7 +4442,7 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
*tx = ((tc + 8) << 3);
*rx = tc << 4;
}
- } else if (num_tcs == 4) {
+ } else {
*rx = tc << 5;
switch (tc) {
case 0:
@@ -4865,19 +4760,15 @@ out:
**/
static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
{
- int q_idx, num_q_vectors;
+ int v_idx, num_q_vectors;
struct ixgbe_q_vector *q_vector;
- int (*poll)(struct napi_struct *, int);
- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
- poll = &ixgbe_clean_rxtx_many;
- } else {
+ else
num_q_vectors = 1;
- poll = &ixgbe_poll;
- }
- for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
+ for (v_idx = 0; v_idx < num_q_vectors; v_idx++) {
q_vector = kzalloc_node(sizeof(struct ixgbe_q_vector),
GFP_KERNEL, adapter->node);
if (!q_vector)
@@ -4885,25 +4776,29 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
GFP_KERNEL);
if (!q_vector)
goto err_out;
+
q_vector->adapter = adapter;
- if (q_vector->tx.count && !q_vector->rx.count)
- q_vector->eitr = adapter->tx_eitr_param;
- else
- q_vector->eitr = adapter->rx_eitr_param;
- q_vector->v_idx = q_idx;
- netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
- adapter->q_vector[q_idx] = q_vector;
+ q_vector->v_idx = v_idx;
+
+ /* Allocate the affinity_hint cpumask, configure the mask */
+ if (!alloc_cpumask_var(&q_vector->affinity_mask, GFP_KERNEL))
+ goto err_out;
+ cpumask_set_cpu(v_idx, q_vector->affinity_mask);
+ netif_napi_add(adapter->netdev, &q_vector->napi,
+ ixgbe_poll, 64);
+ adapter->q_vector[v_idx] = q_vector;
}
return 0;
err_out:
- while (q_idx) {
- q_idx--;
- q_vector = adapter->q_vector[q_idx];
+ while (v_idx) {
+ v_idx--;
+ q_vector = adapter->q_vector[v_idx];
netif_napi_del(&q_vector->napi);
+ free_cpumask_var(q_vector->affinity_mask);
kfree(q_vector);
- adapter->q_vector[q_idx] = NULL;
+ adapter->q_vector[v_idx] = NULL;
}
return -ENOMEM;
}
@@ -4918,17 +4813,18 @@ err_out:
**/
static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter)
{
- int q_idx, num_q_vectors;
+ int v_idx, num_q_vectors;
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
else
num_q_vectors = 1;
- for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
- struct ixgbe_q_vector *q_vector = adapter->q_vector[q_idx];
- adapter->q_vector[q_idx] = NULL;
+ for (v_idx = 0; v_idx < num_q_vectors; v_idx++) {
+ struct ixgbe_q_vector *q_vector = adapter->q_vector[v_idx];
+ adapter->q_vector[v_idx] = NULL;
netif_napi_del(&q_vector->napi);
+ free_cpumask_var(q_vector->affinity_mask);
kfree(q_vector);
}
}
@@ -5043,13 +4939,11 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
- struct net_device *dev = adapter->netdev;
unsigned int rss;
#ifdef CONFIG_IXGBE_DCB
int j;
struct tc_configuration *tc;
#endif
- int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
/* PCI config space info */
@@ -5069,8 +4963,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE;
adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598;
break;
- case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
+ adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
+ case ixgbe_mac_82599EB:
adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599;
adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
@@ -5100,6 +4995,17 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
spin_lock_init(&adapter->fdir_perfect_lock);
#ifdef CONFIG_IXGBE_DCB
+ switch (hw->mac.type) {
+ case ixgbe_mac_X540:
+ adapter->dcb_cfg.num_tcs.pg_tcs = X540_TRAFFIC_CLASS;
+ adapter->dcb_cfg.num_tcs.pfc_tcs = X540_TRAFFIC_CLASS;
+ break;
+ default:
+ adapter->dcb_cfg.num_tcs.pg_tcs = MAX_TRAFFIC_CLASS;
+ adapter->dcb_cfg.num_tcs.pfc_tcs = MAX_TRAFFIC_CLASS;
+ break;
+ }
+
/* Configure DCB traffic classes */
for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
tc = &adapter->dcb_cfg.tc_config[j];
@@ -5109,6 +5015,12 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
tc->path[DCB_RX_CONFIG].bwg_percent = 12 + (j & 1);
tc->dcb_pfc = pfc_disabled;
}
+
+ /* Initialize default user to priority mapping, UPx->TC0 */
+ tc = &adapter->dcb_cfg.tc_config[0];
+ tc->path[DCB_TX_CONFIG].up_to_tc_bitmap = 0xFF;
+ tc->path[DCB_RX_CONFIG].up_to_tc_bitmap = 0xFF;
+
adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
adapter->dcb_cfg.pfc_mode_enable = false;
@@ -5125,17 +5037,14 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
#ifdef CONFIG_DCB
adapter->last_lfc_mode = hw->fc.current_mode;
#endif
- hw->fc.high_water = FC_HIGH_WATER(max_frame);
- hw->fc.low_water = FC_LOW_WATER(max_frame);
+ ixgbe_pbthresh_setup(adapter);
hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
hw->fc.send_xon = true;
hw->fc.disable_fc_autoneg = false;
/* enable itr by default in dynamic mode */
adapter->rx_itr_setting = 1;
- adapter->rx_eitr_param = 20000;
adapter->tx_itr_setting = 1;
- adapter->tx_eitr_param = 10000;
/* set defaults for eitr in MegaBytes */
adapter->eitr_low = 10;
@@ -5146,7 +5055,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->rx_ring_count = IXGBE_DEFAULT_RXD;
/* set default work limits */
- adapter->tx_work_limit = adapter->tx_ring_count;
+ adapter->tx_work_limit = IXGBE_DEFAULT_TX_WORK;
/* initialize eeprom parameters */
if (ixgbe_init_eeprom_params_generic(hw)) {
@@ -5395,9 +5304,6 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
/* must set new MTU before calling down or up */
netdev->mtu = new_mtu;
- hw->fc.high_water = FC_HIGH_WATER(max_frame);
- hw->fc.low_water = FC_LOW_WATER(max_frame);
-
if (netif_running(netdev))
ixgbe_reinit_locked(adapter);
@@ -5443,17 +5349,10 @@ static int ixgbe_open(struct net_device *netdev)
if (err)
goto err_req_irq;
- err = ixgbe_up_complete(adapter);
- if (err)
- goto err_up;
-
- netif_tx_start_all_queues(netdev);
+ ixgbe_up_complete(adapter);
return 0;
-err_up:
- ixgbe_release_hw_control(adapter);
- ixgbe_free_irq(adapter);
err_req_irq:
err_setup_rx:
ixgbe_free_all_rx_resources(adapter);
@@ -5658,6 +5557,11 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
u64 non_eop_descs = 0, restart_queue = 0, tx_busy = 0;
u64 alloc_rx_page_failed = 0, alloc_rx_buff_failed = 0;
u64 bytes = 0, packets = 0;
+#ifdef IXGBE_FCOE
+ struct ixgbe_fcoe *fcoe = &adapter->fcoe;
+ unsigned int cpu;
+ u64 fcoe_noddp_counts_sum = 0, fcoe_noddp_ext_buff_counts_sum = 0;
+#endif /* IXGBE_FCOE */
if (test_bit(__IXGBE_DOWN, &adapter->state) ||
test_bit(__IXGBE_RESETTING, &adapter->state))
@@ -5707,20 +5611,21 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
netdev->stats.tx_packets = packets;
hwstats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
+
+ /* 8 register reads */
for (i = 0; i < 8; i++) {
/* for packet buffers not used, the register should read 0 */
mpc = IXGBE_READ_REG(hw, IXGBE_MPC(i));
missed_rx += mpc;
hwstats->mpc[i] += mpc;
total_mpc += hwstats->mpc[i];
- if (hw->mac.type == ixgbe_mac_82598EB)
- hwstats->rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
- hwstats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
- hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
- hwstats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
- hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
+ hwstats->pxontxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
+ hwstats->pxofftxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
+ hwstats->rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+ hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+ hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
hwstats->pxonrxc[i] +=
IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
break;
@@ -5732,9 +5637,21 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
default:
break;
}
- hwstats->pxontxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
- hwstats->pxofftxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
}
+
+ /*16 register reads */
+ for (i = 0; i < 16; i++) {
+ hwstats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
+ hwstats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
+ if ((hw->mac.type == ixgbe_mac_82599EB) ||
+ (hw->mac.type == ixgbe_mac_X540)) {
+ hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
+ IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); /* to clear */
+ hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
+ IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); /* to clear */
+ }
+ }
+
hwstats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
/* work around hardware counting issue */
hwstats->gprc -= missed_rx;
@@ -5772,6 +5689,18 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
hwstats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
hwstats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
hwstats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
+ /* Add up per cpu counters for total ddp aloc fail */
+ if (fcoe->pcpu_noddp && fcoe->pcpu_noddp_ext_buff) {
+ for_each_possible_cpu(cpu) {
+ fcoe_noddp_counts_sum +=
+ *per_cpu_ptr(fcoe->pcpu_noddp, cpu);
+ fcoe_noddp_ext_buff_counts_sum +=
+ *per_cpu_ptr(fcoe->
+ pcpu_noddp_ext_buff, cpu);
+ }
+ }
+ hwstats->fcoe_noddp = fcoe_noddp_counts_sum;
+ hwstats->fcoe_noddp_ext_buff = fcoe_noddp_ext_buff_counts_sum;
#endif /* IXGBE_FCOE */
break;
default:
@@ -5794,7 +5723,6 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
hwstats->lxontxc += lxon;
lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
hwstats->lxofftxc += lxoff;
- hwstats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
hwstats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
hwstats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
/*
@@ -5902,7 +5830,7 @@ static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter)
/* get one bit for every active tx/rx interrupt vector */
for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
struct ixgbe_q_vector *qv = adapter->q_vector[i];
- if (qv->rx.count || qv->tx.count)
+ if (qv->rx.ring || qv->tx.ring)
eics |= ((u64)1 << i);
}
}
@@ -6091,7 +6019,8 @@ static void ixgbe_spoof_check(struct ixgbe_adapter *adapter)
static void ixgbe_watchdog_subtask(struct ixgbe_adapter *adapter)
{
/* if interface is down do nothing */
- if (test_bit(__IXGBE_DOWN, &adapter->state))
+ if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+ test_bit(__IXGBE_RESETTING, &adapter->state))
return;
ixgbe_watchdog_update_link(adapter);
@@ -6205,6 +6134,51 @@ static void ixgbe_sfp_link_config_subtask(struct ixgbe_adapter *adapter)
clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state);
}
+#ifdef CONFIG_PCI_IOV
+static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
+{
+ int vf;
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ u32 gpc;
+ u32 ciaa, ciad;
+
+ gpc = IXGBE_READ_REG(hw, IXGBE_TXDGPC);
+ if (gpc) /* If incrementing then no need for the check below */
+ return;
+ /*
+ * Check to see if a bad DMA write target from an errant or
+ * malicious VF has caused a PCIe error. If so then we can
+ * issue a VFLR to the offending VF(s) and then resume without
+ * requesting a full slot reset.
+ */
+
+ for (vf = 0; vf < adapter->num_vfs; vf++) {
+ ciaa = (vf << 16) | 0x80000000;
+ /* 32 bit read so align, we really want status at offset 6 */
+ ciaa |= PCI_COMMAND;
+ IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
+ ciad = IXGBE_READ_REG(hw, IXGBE_CIAD_82599);
+ ciaa &= 0x7FFFFFFF;
+ /* disable debug mode asap after reading data */
+ IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
+ /* Get the upper 16 bits which will be the PCI status reg */
+ ciad >>= 16;
+ if (ciad & PCI_STATUS_REC_MASTER_ABORT) {
+ netdev_err(netdev, "VF %d Hung DMA\n", vf);
+ /* Issue VFLR */
+ ciaa = (vf << 16) | 0x80000000;
+ ciaa |= 0xA8;
+ IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
+ ciad = 0x00008000; /* VFLR */
+ IXGBE_WRITE_REG(hw, IXGBE_CIAD_82599, ciad);
+ ciaa &= 0x7FFFFFFF;
+ IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa);
+ }
+ }
+}
+
+#endif
/**
* ixgbe_service_timer - Timer Call-back
* @data: pointer to adapter cast into an unsigned long
@@ -6213,17 +6187,49 @@ static void ixgbe_service_timer(unsigned long data)
{
struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
unsigned long next_event_offset;
+ bool ready = true;
+
+#ifdef CONFIG_PCI_IOV
+ ready = false;
+
+ /*
+ * don't bother with SR-IOV VF DMA hang check if there are
+ * no VFs or the link is down
+ */
+ if (!adapter->num_vfs ||
+ (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)) {
+ ready = true;
+ goto normal_timer_service;
+ }
+
+ /* If we have VFs allocated then we must check for DMA hangs */
+ ixgbe_check_for_bad_vf(adapter);
+ next_event_offset = HZ / 50;
+ adapter->timer_event_accumulator++;
+
+ if (adapter->timer_event_accumulator >= 100) {
+ ready = true;
+ adapter->timer_event_accumulator = 0;
+ }
+ goto schedule_event;
+
+normal_timer_service:
+#endif
/* poll faster when waiting for link */
if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)
next_event_offset = HZ / 10;
else
next_event_offset = HZ * 2;
+#ifdef CONFIG_PCI_IOV
+schedule_event:
+#endif
/* Reset the timer */
mod_timer(&adapter->service_timer, next_event_offset + jiffies);
- ixgbe_service_event_schedule(adapter);
+ if (ready)
+ ixgbe_service_event_schedule(adapter);
}
static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter)
@@ -6350,7 +6356,8 @@ static bool ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
u32 type_tucmd = 0;
if (skb->ip_summed != CHECKSUM_PARTIAL) {
- if (!(tx_flags & IXGBE_TX_FLAGS_VLAN))
+ if (!(tx_flags & IXGBE_TX_FLAGS_HW_VLAN) &&
+ !(tx_flags & IXGBE_TX_FLAGS_TXSW))
return false;
} else {
u8 l4_hdr = 0;
@@ -6407,185 +6414,185 @@ static bool ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
return (skb->ip_summed == CHECKSUM_PARTIAL);
}
-static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
- struct sk_buff *skb, u32 tx_flags,
- unsigned int first, const u8 hdr_len)
+static __le32 ixgbe_tx_cmd_type(u32 tx_flags)
{
- struct device *dev = tx_ring->dev;
- struct ixgbe_tx_buffer *tx_buffer_info;
- unsigned int len;
- unsigned int total = skb->len;
- unsigned int offset = 0, size, count = 0;
- unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
- unsigned int f;
- unsigned int bytecount = skb->len;
- u16 gso_segs = 1;
- u16 i;
+ /* set type for advanced descriptor with frame checksum insertion */
+ __le32 cmd_type = cpu_to_le32(IXGBE_ADVTXD_DTYP_DATA |
+ IXGBE_ADVTXD_DCMD_IFCS |
+ IXGBE_ADVTXD_DCMD_DEXT);
- i = tx_ring->next_to_use;
+ /* set HW vlan bit if vlan is present */
+ if (tx_flags & IXGBE_TX_FLAGS_HW_VLAN)
+ cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_VLE);
- if (tx_flags & IXGBE_TX_FLAGS_FCOE)
- /* excluding fcoe_crc_eof for FCoE */
- total -= sizeof(struct fcoe_crc_eof);
+ /* set segmentation enable bits for TSO/FSO */
+#ifdef IXGBE_FCOE
+ if ((tx_flags & IXGBE_TX_FLAGS_TSO) || (tx_flags & IXGBE_TX_FLAGS_FSO))
+#else
+ if (tx_flags & IXGBE_TX_FLAGS_TSO)
+#endif
+ cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_TSE);
- len = min(skb_headlen(skb), total);
- while (len) {
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
- size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);
-
- tx_buffer_info->length = size;
- tx_buffer_info->mapped_as_page = false;
- tx_buffer_info->dma = dma_map_single(dev,
- skb->data + offset,
- size, DMA_TO_DEVICE);
- if (dma_mapping_error(dev, tx_buffer_info->dma))
- goto dma_error;
- tx_buffer_info->time_stamp = jiffies;
- tx_buffer_info->next_to_watch = i;
+ return cmd_type;
+}
- len -= size;
- total -= size;
- offset += size;
- count++;
+static __le32 ixgbe_tx_olinfo_status(u32 tx_flags, unsigned int paylen)
+{
+ __le32 olinfo_status =
+ cpu_to_le32(paylen << IXGBE_ADVTXD_PAYLEN_SHIFT);
- if (len) {
- i++;
- if (i == tx_ring->count)
- i = 0;
- }
+ if (tx_flags & IXGBE_TX_FLAGS_TSO) {
+ olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_TXSM |
+ (1 << IXGBE_ADVTXD_IDX_SHIFT));
+ /* enble IPv4 checksum for TSO */
+ if (tx_flags & IXGBE_TX_FLAGS_IPV4)
+ olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_IXSM);
}
- for (f = 0; f < nr_frags; f++) {
- struct skb_frag_struct *frag;
-
- frag = &skb_shinfo(skb)->frags[f];
- len = min((unsigned int)frag->size, total);
- offset = frag->page_offset;
-
- while (len) {
- i++;
- if (i == tx_ring->count)
- i = 0;
-
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
- size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);
-
- tx_buffer_info->length = size;
- tx_buffer_info->dma = dma_map_page(dev,
- frag->page,
- offset, size,
- DMA_TO_DEVICE);
- tx_buffer_info->mapped_as_page = true;
- if (dma_mapping_error(dev, tx_buffer_info->dma))
- goto dma_error;
- tx_buffer_info->time_stamp = jiffies;
- tx_buffer_info->next_to_watch = i;
-
- len -= size;
- total -= size;
- offset += size;
- count++;
- }
- if (total == 0)
- break;
- }
+ /* enable L4 checksum for TSO and TX checksum offload */
+ if (tx_flags & IXGBE_TX_FLAGS_CSUM)
+ olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_TXSM);
- if (tx_flags & IXGBE_TX_FLAGS_TSO)
- gso_segs = skb_shinfo(skb)->gso_segs;
#ifdef IXGBE_FCOE
- /* adjust for FCoE Sequence Offload */
- else if (tx_flags & IXGBE_TX_FLAGS_FSO)
- gso_segs = DIV_ROUND_UP(skb->len - hdr_len,
- skb_shinfo(skb)->gso_size);
-#endif /* IXGBE_FCOE */
- bytecount += (gso_segs - 1) * hdr_len;
+ /* use index 1 context for FCOE/FSO */
+ if (tx_flags & IXGBE_TX_FLAGS_FCOE)
+ olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_CC |
+ (1 << IXGBE_ADVTXD_IDX_SHIFT));
- /* multiply data chunks by size of headers */
- tx_ring->tx_buffer_info[i].bytecount = bytecount;
- tx_ring->tx_buffer_info[i].gso_segs = gso_segs;
- tx_ring->tx_buffer_info[i].skb = skb;
- tx_ring->tx_buffer_info[first].next_to_watch = i;
+#endif
+ /*
+ * Check Context must be set if Tx switch is enabled, which it
+ * always is for case where virtual functions are running
+ */
+ if (tx_flags & IXGBE_TX_FLAGS_TXSW)
+ olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_CC);
- return count;
+ return olinfo_status;
+}
-dma_error:
- e_dev_err("TX DMA map failed\n");
+#define IXGBE_TXD_CMD (IXGBE_TXD_CMD_EOP | \
+ IXGBE_TXD_CMD_RS)
- /* clear timestamp and dma mappings for failed tx_buffer_info map */
- tx_buffer_info->dma = 0;
- tx_buffer_info->time_stamp = 0;
- tx_buffer_info->next_to_watch = 0;
- if (count)
- count--;
+static void ixgbe_tx_map(struct ixgbe_ring *tx_ring,
+ struct sk_buff *skb,
+ struct ixgbe_tx_buffer *first,
+ u32 tx_flags,
+ const u8 hdr_len)
+{
+ struct device *dev = tx_ring->dev;
+ struct ixgbe_tx_buffer *tx_buffer_info;
+ union ixgbe_adv_tx_desc *tx_desc;
+ dma_addr_t dma;
+ __le32 cmd_type, olinfo_status;
+ struct skb_frag_struct *frag;
+ unsigned int f = 0;
+ unsigned int data_len = skb->data_len;
+ unsigned int size = skb_headlen(skb);
+ u32 offset = 0;
+ u32 paylen = skb->len - hdr_len;
+ u16 i = tx_ring->next_to_use;
+ u16 gso_segs;
- /* clear timestamp and dma mappings for remaining portion of packet */
- while (count--) {
- if (i == 0)
- i += tx_ring->count;
- i--;
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
- ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
+#ifdef IXGBE_FCOE
+ if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
+ if (data_len >= sizeof(struct fcoe_crc_eof)) {
+ data_len -= sizeof(struct fcoe_crc_eof);
+ } else {
+ size -= sizeof(struct fcoe_crc_eof) - data_len;
+ data_len = 0;
+ }
}
- return 0;
-}
+#endif
+ dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, dma))
+ goto dma_error;
-static void ixgbe_tx_queue(struct ixgbe_ring *tx_ring,
- int tx_flags, int count, u32 paylen, u8 hdr_len)
-{
- union ixgbe_adv_tx_desc *tx_desc = NULL;
- struct ixgbe_tx_buffer *tx_buffer_info;
- u32 olinfo_status = 0, cmd_type_len = 0;
- unsigned int i;
- u32 txd_cmd = IXGBE_TXD_CMD_EOP | IXGBE_TXD_CMD_RS | IXGBE_TXD_CMD_IFCS;
+ cmd_type = ixgbe_tx_cmd_type(tx_flags);
+ olinfo_status = ixgbe_tx_olinfo_status(tx_flags, paylen);
- cmd_type_len |= IXGBE_ADVTXD_DTYP_DATA;
+ tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
- cmd_type_len |= IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT;
+ for (;;) {
+ while (size > IXGBE_MAX_DATA_PER_TXD) {
+ tx_desc->read.buffer_addr = cpu_to_le64(dma + offset);
+ tx_desc->read.cmd_type_len =
+ cmd_type | cpu_to_le32(IXGBE_MAX_DATA_PER_TXD);
+ tx_desc->read.olinfo_status = olinfo_status;
- if (tx_flags & IXGBE_TX_FLAGS_VLAN)
- cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE;
+ offset += IXGBE_MAX_DATA_PER_TXD;
+ size -= IXGBE_MAX_DATA_PER_TXD;
- if (tx_flags & IXGBE_TX_FLAGS_TSO) {
- cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
+ tx_desc++;
+ i++;
+ if (i == tx_ring->count) {
+ tx_desc = IXGBE_TX_DESC_ADV(tx_ring, 0);
+ i = 0;
+ }
+ }
- olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
- IXGBE_ADVTXD_POPTS_SHIFT;
+ tx_buffer_info = &tx_ring->tx_buffer_info[i];
+ tx_buffer_info->length = offset + size;
+ tx_buffer_info->tx_flags = tx_flags;
+ tx_buffer_info->dma = dma;
- /* use index 1 context for tso */
- olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
- if (tx_flags & IXGBE_TX_FLAGS_IPV4)
- olinfo_status |= IXGBE_TXD_POPTS_IXSM <<
- IXGBE_ADVTXD_POPTS_SHIFT;
+ tx_desc->read.buffer_addr = cpu_to_le64(dma + offset);
+ tx_desc->read.cmd_type_len = cmd_type | cpu_to_le32(size);
+ tx_desc->read.olinfo_status = olinfo_status;
- } else if (tx_flags & IXGBE_TX_FLAGS_CSUM)
- olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
- IXGBE_ADVTXD_POPTS_SHIFT;
+ if (!data_len)
+ break;
- if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
- olinfo_status |= IXGBE_ADVTXD_CC;
- olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
- if (tx_flags & IXGBE_TX_FLAGS_FSO)
- cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
- }
+ frag = &skb_shinfo(skb)->frags[f];
+#ifdef IXGBE_FCOE
+ size = min_t(unsigned int, data_len, skb_frag_size(frag));
+#else
+ size = skb_frag_size(frag);
+#endif
+ data_len -= size;
+ f++;
- olinfo_status |= ((paylen - hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT);
+ offset = 0;
+ tx_flags |= IXGBE_TX_FLAGS_MAPPED_AS_PAGE;
- i = tx_ring->next_to_use;
- while (count--) {
- tx_buffer_info = &tx_ring->tx_buffer_info[i];
- tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
- tx_desc->read.buffer_addr = cpu_to_le64(tx_buffer_info->dma);
- tx_desc->read.cmd_type_len =
- cpu_to_le32(cmd_type_len | tx_buffer_info->length);
- tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
+ dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, dma))
+ goto dma_error;
+
+ tx_desc++;
i++;
- if (i == tx_ring->count)
+ if (i == tx_ring->count) {
+ tx_desc = IXGBE_TX_DESC_ADV(tx_ring, 0);
i = 0;
+ }
}
- tx_desc->read.cmd_type_len |= cpu_to_le32(txd_cmd);
+ tx_desc->read.cmd_type_len |= cpu_to_le32(IXGBE_TXD_CMD);
+
+ i++;
+ if (i == tx_ring->count)
+ i = 0;
+
+ tx_ring->next_to_use = i;
+
+ if (tx_flags & IXGBE_TX_FLAGS_TSO)
+ gso_segs = skb_shinfo(skb)->gso_segs;
+#ifdef IXGBE_FCOE
+ /* adjust for FCoE Sequence Offload */
+ else if (tx_flags & IXGBE_TX_FLAGS_FSO)
+ gso_segs = DIV_ROUND_UP(skb->len - hdr_len,
+ skb_shinfo(skb)->gso_size);
+#endif /* IXGBE_FCOE */
+ else
+ gso_segs = 1;
+
+ /* multiply data chunks by size of headers */
+ tx_buffer_info->bytecount = paylen + (gso_segs * hdr_len);
+ tx_buffer_info->gso_segs = gso_segs;
+ tx_buffer_info->skb = skb;
+
+ /* set the timestamp */
+ first->time_stamp = jiffies;
/*
* Force memory writes to complete before letting h/w
@@ -6595,8 +6602,30 @@ static void ixgbe_tx_queue(struct ixgbe_ring *tx_ring,
*/
wmb();
- tx_ring->next_to_use = i;
+ /* set next_to_watch value indicating a packet is present */
+ first->next_to_watch = tx_desc;
+
+ /* notify HW of packet */
writel(i, tx_ring->tail);
+
+ return;
+dma_error:
+ dev_err(dev, "TX DMA map failed\n");
+
+ /* clear dma mappings for failed tx_buffer_info map */
+ for (;;) {
+ tx_buffer_info = &tx_ring->tx_buffer_info[i];
+ ixgbe_unmap_tx_resource(tx_ring, tx_buffer_info);
+ if (tx_buffer_info == first)
+ break;
+ if (i == 0)
+ i = tx_ring->count;
+ i--;
+ }
+
+ dev_kfree_skb_any(skb);
+
+ tx_ring->next_to_use = i;
}
static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
@@ -6635,8 +6664,8 @@ static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
th = tcp_hdr(skb);
- /* skip this packet since the socket is closing */
- if (th->fin)
+ /* skip this packet since it is invalid or the socket is closing */
+ if (!th || th->fin)
return;
/* sample on all syn packets or once every atr sample count */
@@ -6661,7 +6690,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
* since src port and flex bytes occupy the same word XOR them together
* and write the value to source port portion of compressed dword
*/
- if (vlan_id)
+ if (tx_flags & (IXGBE_TX_FLAGS_SW_VLAN | IXGBE_TX_FLAGS_HW_VLAN))
common.port.src ^= th->dest ^ __constant_htons(ETH_P_8021Q);
else
common.port.src ^= th->dest ^ protocol;
@@ -6743,14 +6772,14 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
struct ixgbe_adapter *adapter,
struct ixgbe_ring *tx_ring)
{
+ struct ixgbe_tx_buffer *first;
int tso;
- u32 tx_flags = 0;
+ u32 tx_flags = 0;
#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
unsigned short f;
#endif
- u16 first;
u16 count = TXD_USE_COUNT(skb_headlen(skb));
- __be16 protocol;
+ __be16 protocol = skb->protocol;
u8 hdr_len = 0;
/*
@@ -6771,68 +6800,89 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
- protocol = vlan_get_protocol(skb);
+#ifdef CONFIG_PCI_IOV
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+ tx_flags |= IXGBE_TX_FLAGS_TXSW;
+#endif
+ /* if we have a HW VLAN tag being added default to the HW one */
if (vlan_tx_tag_present(skb)) {
- tx_flags |= vlan_tx_tag_get(skb);
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
- tx_flags |= tx_ring->dcb_tc << 13;
+ tx_flags |= vlan_tx_tag_get(skb) << IXGBE_TX_FLAGS_VLAN_SHIFT;
+ tx_flags |= IXGBE_TX_FLAGS_HW_VLAN;
+ /* else if it is a SW VLAN check the next protocol and store the tag */
+ } else if (protocol == __constant_htons(ETH_P_8021Q)) {
+ struct vlan_hdr *vhdr, _vhdr;
+ vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr);
+ if (!vhdr)
+ goto out_drop;
+
+ protocol = vhdr->h_vlan_encapsulated_proto;
+ tx_flags |= ntohs(vhdr->h_vlan_TCI) << IXGBE_TX_FLAGS_VLAN_SHIFT;
+ tx_flags |= IXGBE_TX_FLAGS_SW_VLAN;
+ }
+
+ /* DCB maps skb priorities 0-7 onto 3 bit PCP of VLAN tag. */
+ if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
+ ((tx_flags & (IXGBE_TX_FLAGS_HW_VLAN | IXGBE_TX_FLAGS_SW_VLAN)) ||
+ (skb->priority != TC_PRIO_CONTROL))) {
+ tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
+ tx_flags |= (skb->priority & 0x7) <<
+ IXGBE_TX_FLAGS_VLAN_PRIO_SHIFT;
+ if (tx_flags & IXGBE_TX_FLAGS_SW_VLAN) {
+ struct vlan_ethhdr *vhdr;
+ if (skb_header_cloned(skb) &&
+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+ goto out_drop;
+ vhdr = (struct vlan_ethhdr *)skb->data;
+ vhdr->h_vlan_TCI = htons(tx_flags >>
+ IXGBE_TX_FLAGS_VLAN_SHIFT);
+ } else {
+ tx_flags |= IXGBE_TX_FLAGS_HW_VLAN;
}
- tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
- tx_flags |= IXGBE_TX_FLAGS_VLAN;
- } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED &&
- skb->priority != TC_PRIO_CONTROL) {
- tx_flags |= tx_ring->dcb_tc << 13;
- tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
- tx_flags |= IXGBE_TX_FLAGS_VLAN;
}
-#ifdef IXGBE_FCOE
- /* for FCoE with DCB, we force the priority to what
- * was specified by the switch */
- if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED &&
- (protocol == htons(ETH_P_FCOE)))
- tx_flags |= IXGBE_TX_FLAGS_FCOE;
-
-#endif
/* record the location of the first descriptor for this packet */
- first = tx_ring->next_to_use;
+ first = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
- if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
#ifdef IXGBE_FCOE
- /* setup tx offload for FCoE */
+ /* setup tx offload for FCoE */
+ if ((protocol == __constant_htons(ETH_P_FCOE)) &&
+ (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) {
tso = ixgbe_fso(tx_ring, skb, tx_flags, &hdr_len);
if (tso < 0)
goto out_drop;
else if (tso)
- tx_flags |= IXGBE_TX_FLAGS_FSO;
-#endif /* IXGBE_FCOE */
- } else {
- if (protocol == htons(ETH_P_IP))
- tx_flags |= IXGBE_TX_FLAGS_IPV4;
- tso = ixgbe_tso(tx_ring, skb, tx_flags, protocol, &hdr_len);
- if (tso < 0)
- goto out_drop;
- else if (tso)
- tx_flags |= IXGBE_TX_FLAGS_TSO;
- else if (ixgbe_tx_csum(tx_ring, skb, tx_flags, protocol))
- tx_flags |= IXGBE_TX_FLAGS_CSUM;
+ tx_flags |= IXGBE_TX_FLAGS_FSO |
+ IXGBE_TX_FLAGS_FCOE;
+ else
+ tx_flags |= IXGBE_TX_FLAGS_FCOE;
+
+ goto xmit_fcoe;
}
- count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first, hdr_len);
- if (count) {
- /* add the ATR filter if ATR is on */
- if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state))
- ixgbe_atr(tx_ring, skb, tx_flags, protocol);
- ixgbe_tx_queue(tx_ring, tx_flags, count, skb->len, hdr_len);
- ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
+#endif /* IXGBE_FCOE */
+ /* setup IPv4/IPv6 offloads */
+ if (protocol == __constant_htons(ETH_P_IP))
+ tx_flags |= IXGBE_TX_FLAGS_IPV4;
- } else {
- tx_ring->tx_buffer_info[first].time_stamp = 0;
- tx_ring->next_to_use = first;
+ tso = ixgbe_tso(tx_ring, skb, tx_flags, protocol, &hdr_len);
+ if (tso < 0)
goto out_drop;
- }
+ else if (tso)
+ tx_flags |= IXGBE_TX_FLAGS_TSO;
+ else if (ixgbe_tx_csum(tx_ring, skb, tx_flags, protocol))
+ tx_flags |= IXGBE_TX_FLAGS_CSUM;
+
+ /* add the ATR filter if ATR is on */
+ if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state))
+ ixgbe_atr(tx_ring, skb, tx_flags, protocol);
+
+#ifdef IXGBE_FCOE
+xmit_fcoe:
+#endif /* IXGBE_FCOE */
+ ixgbe_tx_map(tx_ring, skb, first, tx_flags, hdr_len);
+
+ ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
return NETDEV_TX_OK;
@@ -6971,7 +7021,7 @@ static void ixgbe_netpoll(struct net_device *netdev)
int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
for (i = 0; i < num_q_vectors; i++) {
struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
- ixgbe_msix_clean_many(0, q_vector);
+ ixgbe_msix_clean_rings(0, q_vector);
}
} else {
ixgbe_intr(adapter->pdev->irq, netdev);
@@ -7076,14 +7126,14 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_hw *hw = &adapter->hw;
- /* If DCB is anabled do not remove traffic classes, multiple
- * traffic classes are required to implement DCB
- */
- if (!tc && (adapter->flags & IXGBE_FLAG_DCB_ENABLED))
- return 0;
+ /* Multiple traffic classes requires multiple queues */
+ if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
+ e_err(drv, "Enable failed, needs MSI-X\n");
+ return -EINVAL;
+ }
/* Hardware supports up to 8 traffic classes */
- if (tc > MAX_TRAFFIC_CLASS ||
+ if (tc > adapter->dcb_cfg.num_tcs.pg_tcs ||
(hw->mac.type == ixgbe_mac_82598EB && tc < MAX_TRAFFIC_CLASS))
return -EINVAL;
@@ -7095,11 +7145,27 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
ixgbe_close(dev);
ixgbe_clear_interrupt_scheme(adapter);
- if (tc)
+ if (tc) {
netdev_set_num_tc(dev, tc);
- else
+ adapter->last_lfc_mode = adapter->hw.fc.current_mode;
+
+ adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
+ adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ adapter->hw.fc.requested_mode = ixgbe_fc_none;
+ } else {
netdev_reset_tc(dev);
+ adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
+
+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
+ adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+
+ adapter->temp_dcb_cfg.pfc_mode_enable = false;
+ adapter->dcb_cfg.pfc_mode_enable = false;
+ }
+
ixgbe_init_interrupt_scheme(adapter);
ixgbe_validate_rtr(adapter, tc);
if (netif_running(dev))
@@ -7206,7 +7272,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_start_xmit = ixgbe_xmit_frame,
.ndo_select_queue = ixgbe_select_queue,
.ndo_set_rx_mode = ixgbe_set_rx_mode,
- .ndo_set_multicast_list = ixgbe_set_rx_mode,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ixgbe_set_mac,
.ndo_change_mtu = ixgbe_change_mtu,
@@ -7217,6 +7282,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_set_vf_mac = ixgbe_ndo_set_vf_mac,
.ndo_set_vf_vlan = ixgbe_ndo_set_vf_vlan,
.ndo_set_vf_tx_rate = ixgbe_ndo_set_vf_bw,
+ .ndo_set_vf_spoofchk = ixgbe_ndo_set_vf_spoofchk,
.ndo_get_vf_config = ixgbe_ndo_get_vf_config,
.ndo_get_stats64 = ixgbe_get_stats64,
.ndo_setup_tc = ixgbe_setup_tc,
@@ -7240,11 +7306,8 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
{
#ifdef CONFIG_PCI_IOV
struct ixgbe_hw *hw = &adapter->hw;
- int err;
- int num_vf_macvlans, i;
- struct vf_macvlans *mv_list;
- if (hw->mac.type == ixgbe_mac_82598EB || !max_vfs)
+ if (hw->mac.type == ixgbe_mac_82598EB)
return;
/* The 82599 supports up to 64 VFs per physical function
@@ -7253,60 +7316,7 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
* physical function
*/
adapter->num_vfs = (max_vfs > 63) ? 63 : max_vfs;
- adapter->flags |= IXGBE_FLAG_SRIOV_ENABLED;
- err = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
- if (err) {
- e_err(probe, "Failed to enable PCI sriov: %d\n", err);
- goto err_novfs;
- }
-
- num_vf_macvlans = hw->mac.num_rar_entries -
- (IXGBE_MAX_PF_MACVLANS + 1 + adapter->num_vfs);
-
- adapter->mv_list = mv_list = kcalloc(num_vf_macvlans,
- sizeof(struct vf_macvlans),
- GFP_KERNEL);
- if (mv_list) {
- /* Initialize list of VF macvlans */
- INIT_LIST_HEAD(&adapter->vf_mvs.l);
- for (i = 0; i < num_vf_macvlans; i++) {
- mv_list->vf = -1;
- mv_list->free = true;
- mv_list->rar_entry = hw->mac.num_rar_entries -
- (i + adapter->num_vfs + 1);
- list_add(&mv_list->l, &adapter->vf_mvs.l);
- mv_list++;
- }
- }
-
- /* If call to enable VFs succeeded then allocate memory
- * for per VF control structures.
- */
- adapter->vfinfo =
- kcalloc(adapter->num_vfs,
- sizeof(struct vf_data_storage), GFP_KERNEL);
- if (adapter->vfinfo) {
- /* Now that we're sure SR-IOV is enabled
- * and memory allocated set up the mailbox parameters
- */
- ixgbe_init_mbx_params_pf(hw);
- memcpy(&hw->mbx.ops, ii->mbx_ops,
- sizeof(hw->mbx.ops));
-
- /* Disable RSC when in SR-IOV mode */
- adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE |
- IXGBE_FLAG2_RSC_ENABLED);
- return;
- }
-
- /* Oh oh */
- e_err(probe, "Unable to allocate memory for VF Data Storage - "
- "SRIOV disabled\n");
- pci_disable_sriov(adapter->pdev);
-
-err_novfs:
- adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
- adapter->num_vfs = 0;
+ ixgbe_enable_sriov(adapter, ii);
#endif /* CONFIG_PCI_IOV */
}
@@ -7336,6 +7346,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
u16 device_caps;
#endif
u32 eec;
+ u16 wol_cap;
/* Catch broken hardware that put the wrong VF device ID in
* the PCIe SR-IOV capability.
@@ -7506,7 +7517,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
NETIF_F_HW_VLAN_FILTER |
NETIF_F_TSO |
NETIF_F_TSO6 |
- NETIF_F_GRO |
NETIF_F_RXHASH |
NETIF_F_RXCSUM;
@@ -7529,6 +7539,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
netdev->vlan_features |= NETIF_F_IPV6_CSUM;
netdev->vlan_features |= NETIF_F_SG;
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
adapter->flags &= ~(IXGBE_FLAG_RSS_ENABLED |
IXGBE_FLAG_DCB_ENABLED);
@@ -7599,6 +7611,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
netdev->features &= ~NETIF_F_RXHASH;
}
+ /* WOL not supported for all but the following */
+ adapter->wol = 0;
switch (pdev->device) {
case IXGBE_DEV_ID_82599_SFP:
/* Only this subdevice supports WOL */
@@ -7613,12 +7627,23 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
case IXGBE_DEV_ID_82599_KX4:
adapter->wol = IXGBE_WUFC_MAG;
break;
- default:
- adapter->wol = 0;
+ case IXGBE_DEV_ID_X540T:
+ /* Check eeprom to see if it is enabled */
+ hw->eeprom.ops.read(hw, 0x2c, &adapter->eeprom_cap);
+ wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK;
+
+ if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
+ ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
+ (hw->bus.func == 0)))
+ adapter->wol = IXGBE_WUFC_MAG;
break;
}
device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+ /* save off EEPROM version number */
+ hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh);
+ hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl);
+
/* pick up the PCI bus settings for reporting later */
hw->mac.ops.get_bus_info(hw);
@@ -7651,9 +7676,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
"is required.\n");
}
- /* save off EEPROM version number */
- hw->eeprom.ops.read(hw, 0x29, &adapter->eeprom_version);
-
/* reset the hardware with the new settings */
err = hw->mac.ops.start_hw(hw);
@@ -7686,10 +7708,12 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
ixgbe_vf_configuration(pdev, (i | 0x10000000));
}
- /* Inform firmware of driver version */
+ /* firmware requires driver version to be 0xFFFFFFFF
+ * since os does not support feature
+ */
if (hw->mac.ops.set_fw_drv_ver)
- hw->mac.ops.set_fw_drv_ver(hw, MAJ, MIN, BUILD,
- FW_CEM_UNUSED_VER);
+ hw->mac.ops.set_fw_drv_ver(hw, 0xFF, 0xFF, 0xFF,
+ 0xFF);
/* add san mac addr to netdev */
ixgbe_add_sanmac_netdev(netdev);
@@ -7755,8 +7779,13 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdev(netdev);
- if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
- ixgbe_disable_sriov(adapter);
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+ if (!(ixgbe_check_vf_assignment(adapter)))
+ ixgbe_disable_sriov(adapter);
+ else
+ e_dev_warn("Unloading driver while VFs are assigned "
+ "- VFs will not be deallocated\n");
+ }
ixgbe_clear_interrupt_scheme(adapter);
@@ -7789,6 +7818,91 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev;
+#ifdef CONFIG_PCI_IOV
+ struct pci_dev *bdev, *vfdev;
+ u32 dw0, dw1, dw2, dw3;
+ int vf, pos;
+ u16 req_id, pf_func;
+
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB ||
+ adapter->num_vfs == 0)
+ goto skip_bad_vf_detection;
+
+ bdev = pdev->bus->self;
+ while (bdev && (bdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT))
+ bdev = bdev->bus->self;
+
+ if (!bdev)
+ goto skip_bad_vf_detection;
+
+ pos = pci_find_ext_capability(bdev, PCI_EXT_CAP_ID_ERR);
+ if (!pos)
+ goto skip_bad_vf_detection;
+
+ pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG, &dw0);
+ pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 4, &dw1);
+ pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 8, &dw2);
+ pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 12, &dw3);
+
+ req_id = dw1 >> 16;
+ /* On the 82599 if bit 7 of the requestor ID is set then it's a VF */
+ if (!(req_id & 0x0080))
+ goto skip_bad_vf_detection;
+
+ pf_func = req_id & 0x01;
+ if ((pf_func & 1) == (pdev->devfn & 1)) {
+ unsigned int device_id;
+
+ vf = (req_id & 0x7F) >> 1;
+ e_dev_err("VF %d has caused a PCIe error\n", vf);
+ e_dev_err("TLP: dw0: %8.8x\tdw1: %8.8x\tdw2: "
+ "%8.8x\tdw3: %8.8x\n",
+ dw0, dw1, dw2, dw3);
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ device_id = IXGBE_82599_VF_DEVICE_ID;
+ break;
+ case ixgbe_mac_X540:
+ device_id = IXGBE_X540_VF_DEVICE_ID;
+ break;
+ default:
+ device_id = 0;
+ break;
+ }
+
+ /* Find the pci device of the offending VF */
+ vfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID, device_id, NULL);
+ while (vfdev) {
+ if (vfdev->devfn == (req_id & 0xFF))
+ break;
+ vfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID,
+ device_id, vfdev);
+ }
+ /*
+ * There's a slim chance the VF could have been hot plugged,
+ * so if it is no longer present we don't need to issue the
+ * VFLR. Just clean up the AER in that case.
+ */
+ if (vfdev) {
+ e_dev_err("Issuing VFLR to VF %d\n", vf);
+ pci_write_config_dword(vfdev, 0xA8, 0x00008000);
+ }
+
+ pci_cleanup_aer_uncorrect_error_status(pdev);
+ }
+
+ /*
+ * Even though the error may have occurred on the other port
+ * we still need to increment the vf error reference count for
+ * both ports because the I/O resume function will be called
+ * for both of them.
+ */
+ adapter->vferr_refcount++;
+
+ return PCI_ERS_RESULT_RECOVERED;
+
+skip_bad_vf_detection:
+#endif /* CONFIG_PCI_IOV */
netif_device_detach(netdev);
if (state == pci_channel_io_perm_failure)
@@ -7851,13 +7965,17 @@ static void ixgbe_io_resume(struct pci_dev *pdev)
struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev;
- if (netif_running(netdev)) {
- if (ixgbe_up(adapter)) {
- e_info(probe, "ixgbe_up failed after reset\n");
- return;
- }
+#ifdef CONFIG_PCI_IOV
+ if (adapter->vferr_refcount) {
+ e_info(drv, "Resuming after VF err\n");
+ adapter->vferr_refcount--;
+ return;
}
+#endif
+ if (netif_running(netdev))
+ ixgbe_up(adapter);
+
netif_device_attach(netdev);
}
diff --git a/drivers/net/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
index 1ff0eefcfd0a..3f725d48336d 100644
--- a/drivers/net/ixgbe/ixgbe_mbx.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
@@ -38,7 +38,7 @@
* @size: Length of buffer
* @mbx_id: id of mailbox to read
*
- * returns SUCCESS if it successfuly read message from buffer
+ * returns SUCCESS if it successfully read message from buffer
**/
s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
{
diff --git a/drivers/net/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
index b239bdac38da..b239bdac38da 100644
--- a/drivers/net/ixgbe/ixgbe_mbx.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index f7ca3511b9fe..9a56fd74e673 100644
--- a/drivers/net/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -39,7 +39,7 @@ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data);
static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw);
static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data);
static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data);
-static s32 ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl);
+static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl);
static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl);
static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data);
static bool ixgbe_get_i2c_data(u32 *i2cctl);
@@ -1205,7 +1205,7 @@ s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
* @data: value read
*
* Performs byte read operation to SFP module's EEPROM over I2C interface at
- * a specified deivce address.
+ * a specified device address.
**/
s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data)
@@ -1215,6 +1215,7 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
u32 retry = 0;
u16 swfw_mask = 0;
bool nack = 1;
+ *data = 0;
if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
swfw_mask = IXGBE_GSSR_PHY1_SM;
@@ -1419,19 +1420,15 @@ static void ixgbe_i2c_stop(struct ixgbe_hw *hw)
**/
static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data)
{
- s32 status = 0;
s32 i;
bool bit = 0;
for (i = 7; i >= 0; i--) {
- status = ixgbe_clock_in_i2c_bit(hw, &bit);
+ ixgbe_clock_in_i2c_bit(hw, &bit);
*data |= bit << i;
-
- if (status != 0)
- break;
}
- return status;
+ return 0;
}
/**
@@ -1472,16 +1469,14 @@ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data)
**/
static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw)
{
- s32 status;
+ s32 status = 0;
u32 i = 0;
u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
u32 timeout = 10;
bool ack = 1;
- status = ixgbe_raise_i2c_clk(hw, &i2cctl);
+ ixgbe_raise_i2c_clk(hw, &i2cctl);
- if (status != 0)
- goto out;
/* Minimum high period of clock is 4us */
udelay(IXGBE_I2C_T_HIGH);
@@ -1507,7 +1502,6 @@ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw)
/* Minimum low period of clock is 4.7 us */
udelay(IXGBE_I2C_T_LOW);
-out:
return status;
}
@@ -1520,10 +1514,9 @@ out:
**/
static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data)
{
- s32 status;
u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
- status = ixgbe_raise_i2c_clk(hw, &i2cctl);
+ ixgbe_raise_i2c_clk(hw, &i2cctl);
/* Minimum high period of clock is 4us */
udelay(IXGBE_I2C_T_HIGH);
@@ -1536,7 +1529,7 @@ static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data)
/* Minimum low period of clock is 4.7 us */
udelay(IXGBE_I2C_T_LOW);
- return status;
+ return 0;
}
/**
@@ -1553,7 +1546,7 @@ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data)
status = ixgbe_set_i2c_data(hw, &i2cctl, data);
if (status == 0) {
- status = ixgbe_raise_i2c_clk(hw, &i2cctl);
+ ixgbe_raise_i2c_clk(hw, &i2cctl);
/* Minimum high period of clock is 4us */
udelay(IXGBE_I2C_T_HIGH);
@@ -1578,10 +1571,8 @@ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data)
*
* Raises the I2C clock line '0'->'1'
**/
-static s32 ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
+static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
{
- s32 status = 0;
-
*i2cctl |= IXGBE_I2C_CLK_OUT;
IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
@@ -1589,8 +1580,6 @@ static s32 ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
/* SCL rise time (1000ns) */
udelay(IXGBE_I2C_T_RISE);
-
- return status;
}
/**
diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
index 197bdd13106a..197bdd13106a 100644
--- a/drivers/net/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index d99d01e21326..db95731863d7 100644
--- a/drivers/net/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -40,9 +40,176 @@
#endif
#include "ixgbe.h"
-
+#include "ixgbe_type.h"
#include "ixgbe_sriov.h"
+#ifdef CONFIG_PCI_IOV
+static int ixgbe_find_enabled_vfs(struct ixgbe_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct pci_dev *pvfdev;
+ u16 vf_devfn = 0;
+ int device_id;
+ int vfs_found = 0;
+
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ device_id = IXGBE_DEV_ID_82599_VF;
+ break;
+ case ixgbe_mac_X540:
+ device_id = IXGBE_DEV_ID_X540_VF;
+ break;
+ default:
+ device_id = 0;
+ break;
+ }
+
+ vf_devfn = pdev->devfn + 0x80;
+ pvfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID, device_id, NULL);
+ while (pvfdev) {
+ if (pvfdev->devfn == vf_devfn)
+ vfs_found++;
+ vf_devfn += 2;
+ pvfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID,
+ device_id, pvfdev);
+ }
+
+ return vfs_found;
+}
+
+void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
+ const struct ixgbe_info *ii)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ int err = 0;
+ int num_vf_macvlans, i;
+ struct vf_macvlans *mv_list;
+ int pre_existing_vfs = 0;
+
+ pre_existing_vfs = ixgbe_find_enabled_vfs(adapter);
+ if (!pre_existing_vfs && !adapter->num_vfs)
+ return;
+
+ /* If there are pre-existing VFs then we have to force
+ * use of that many because they were not deleted the last
+ * time someone removed the PF driver. That would have
+ * been because they were allocated to guest VMs and can't
+ * be removed. Go ahead and just re-enable the old amount.
+ * If the user wants to change the number of VFs they can
+ * use ethtool while making sure no VFs are allocated to
+ * guest VMs... i.e. the right way.
+ */
+ if (pre_existing_vfs) {
+ adapter->num_vfs = pre_existing_vfs;
+ dev_warn(&adapter->pdev->dev, "Virtual Functions already "
+ "enabled for this device - Please reload all "
+ "VF drivers to avoid spoofed packet errors\n");
+ } else {
+ err = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
+ }
+ if (err) {
+ e_err(probe, "Failed to enable PCI sriov: %d\n", err);
+ goto err_novfs;
+ }
+ adapter->flags |= IXGBE_FLAG_SRIOV_ENABLED;
+
+ e_info(probe, "SR-IOV enabled with %d VFs\n", adapter->num_vfs);
+
+ num_vf_macvlans = hw->mac.num_rar_entries -
+ (IXGBE_MAX_PF_MACVLANS + 1 + adapter->num_vfs);
+
+ adapter->mv_list = mv_list = kcalloc(num_vf_macvlans,
+ sizeof(struct vf_macvlans),
+ GFP_KERNEL);
+ if (mv_list) {
+ /* Initialize list of VF macvlans */
+ INIT_LIST_HEAD(&adapter->vf_mvs.l);
+ for (i = 0; i < num_vf_macvlans; i++) {
+ mv_list->vf = -1;
+ mv_list->free = true;
+ mv_list->rar_entry = hw->mac.num_rar_entries -
+ (i + adapter->num_vfs + 1);
+ list_add(&mv_list->l, &adapter->vf_mvs.l);
+ mv_list++;
+ }
+ }
+
+ /* If call to enable VFs succeeded then allocate memory
+ * for per VF control structures.
+ */
+ adapter->vfinfo =
+ kcalloc(adapter->num_vfs,
+ sizeof(struct vf_data_storage), GFP_KERNEL);
+ if (adapter->vfinfo) {
+ /* Now that we're sure SR-IOV is enabled
+ * and memory allocated set up the mailbox parameters
+ */
+ ixgbe_init_mbx_params_pf(hw);
+ memcpy(&hw->mbx.ops, ii->mbx_ops,
+ sizeof(hw->mbx.ops));
+
+ /* Disable RSC when in SR-IOV mode */
+ adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE |
+ IXGBE_FLAG2_RSC_ENABLED);
+ for (i = 0; i < adapter->num_vfs; i++)
+ adapter->vfinfo[i].spoofchk_enabled = true;
+ return;
+ }
+
+ /* Oh oh */
+ e_err(probe, "Unable to allocate memory for VF Data Storage - "
+ "SRIOV disabled\n");
+ pci_disable_sriov(adapter->pdev);
+
+err_novfs:
+ adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
+ adapter->num_vfs = 0;
+}
+#endif /* #ifdef CONFIG_PCI_IOV */
+
+void ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 gcr;
+ u32 gpie;
+ u32 vmdctl;
+ int i;
+
+#ifdef CONFIG_PCI_IOV
+ /* disable iov and allow time for transactions to clear */
+ pci_disable_sriov(adapter->pdev);
+#endif
+
+ /* turn off device IOV mode */
+ gcr = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
+ gcr &= ~(IXGBE_GCR_EXT_SRIOV);
+ IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr);
+ gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
+ gpie &= ~IXGBE_GPIE_VTMODE_MASK;
+ IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+
+ /* set default pool back to 0 */
+ vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+ vmdctl &= ~IXGBE_VT_CTL_POOL_MASK;
+ IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl);
+ IXGBE_WRITE_FLUSH(hw);
+
+ /* take a breather then clean up driver data */
+ msleep(100);
+
+ /* Release reference to VF devices */
+ for (i = 0; i < adapter->num_vfs; i++) {
+ if (adapter->vfinfo[i].vfdev)
+ pci_dev_put(adapter->vfinfo[i].vfdev);
+ }
+ kfree(adapter->vfinfo);
+ kfree(adapter->mv_list);
+ adapter->vfinfo = NULL;
+
+ adapter->num_vfs = 0;
+ adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
+}
+
static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
int entries, u16 *hash_list, u32 vf)
{
@@ -273,11 +440,26 @@ static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter,
return 0;
}
+int ixgbe_check_vf_assignment(struct ixgbe_adapter *adapter)
+{
+ int i;
+ for (i = 0; i < adapter->num_vfs; i++) {
+ if (adapter->vfinfo[i].vfdev->dev_flags &
+ PCI_DEV_FLAGS_ASSIGNED)
+ return true;
+ }
+ return false;
+}
+
int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
{
unsigned char vf_mac_addr[6];
struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
unsigned int vfn = (event_mask & 0x3f);
+ struct pci_dev *pvfdev;
+ unsigned int device_id;
+ u16 thisvf_devfn = (pdev->devfn + 0x80 + (vfn << 1)) |
+ (pdev->devfn & 1);
bool enable = ((event_mask & 0x10000000U) != 0);
@@ -290,6 +472,31 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
* for it later.
*/
memcpy(adapter->vfinfo[vfn].vf_mac_addresses, vf_mac_addr, 6);
+
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_82599EB:
+ device_id = IXGBE_DEV_ID_82599_VF;
+ break;
+ case ixgbe_mac_X540:
+ device_id = IXGBE_DEV_ID_X540_VF;
+ break;
+ default:
+ device_id = 0;
+ break;
+ }
+
+ pvfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID, device_id, NULL);
+ while (pvfdev) {
+ if (pvfdev->devfn == thisvf_devfn)
+ break;
+ pvfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID,
+ device_id, pvfdev);
+ }
+ if (pvfdev)
+ adapter->vfinfo[vfn].vfdev = pvfdev;
+ else
+ e_err(drv, "Couldn't find pci dev ptr for VF %4.4x\n",
+ thisvf_devfn);
}
return 0;
@@ -415,7 +622,13 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
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);
}
break;
case IXGBE_VF_SET_MACVLAN:
@@ -427,12 +640,8 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
* greater than 0 will indicate the VF is setting a
* macvlan MAC filter.
*/
- if (index > 0 && adapter->antispoofing_enabled) {
- hw->mac.ops.set_mac_anti_spoofing(hw, false,
- adapter->num_vfs);
- hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf);
- adapter->antispoofing_enabled = false;
- }
+ 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]));
break;
@@ -543,8 +752,9 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
goto out;
ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf);
ixgbe_set_vmolr(hw, vf, false);
- if (adapter->antispoofing_enabled)
+ if (adapter->vfinfo[vf].spoofchk_enabled)
hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
+ adapter->vfinfo[vf].vlan_count++;
adapter->vfinfo[vf].pf_vlan = vlan;
adapter->vfinfo[vf].pf_qos = qos;
dev_info(&adapter->pdev->dev,
@@ -563,6 +773,8 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
ixgbe_set_vmvir(adapter, vlan, vf);
ixgbe_set_vmolr(hw, vf, true);
hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf);
+ if (adapter->vfinfo[vf].vlan_count)
+ adapter->vfinfo[vf].vlan_count--;
adapter->vfinfo[vf].pf_vlan = 0;
adapter->vfinfo[vf].pf_qos = 0;
}
@@ -672,6 +884,32 @@ int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate)
return 0;
}
+int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ int vf_target_reg = vf >> 3;
+ int vf_target_shift = vf % 8;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 regval;
+
+ adapter->vfinfo[vf].spoofchk_enabled = setting;
+
+ regval = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
+ regval &= ~(1 << vf_target_shift);
+ regval |= (setting << vf_target_shift);
+ IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), regval);
+
+ if (adapter->vfinfo[vf].vlan_count) {
+ vf_target_shift += IXGBE_SPOOF_VLANAS_SHIFT;
+ regval = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
+ regval &= ~(1 << vf_target_shift);
+ regval |= (setting << vf_target_shift);
+ IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), regval);
+ }
+
+ return 0;
+}
+
int ixgbe_ndo_get_vf_config(struct net_device *netdev,
int vf, struct ifla_vf_info *ivi)
{
@@ -683,5 +921,6 @@ int ixgbe_ndo_get_vf_config(struct net_device *netdev,
ivi->tx_rate = adapter->vfinfo[vf].tx_rate;
ivi->vlan = adapter->vfinfo[vf].pf_vlan;
ivi->qos = adapter->vfinfo[vf].pf_qos;
+ ivi->spoofchk = adapter->vfinfo[vf].spoofchk_enabled;
return 0;
}
diff --git a/drivers/net/ixgbe/ixgbe_sriov.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
index 34175564bb78..5a7e1eb33599 100644
--- a/drivers/net/ixgbe/ixgbe_sriov.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
@@ -38,9 +38,15 @@ int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int queue, u8 *mac);
int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int queue, u16 vlan,
u8 qos);
int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate);
+int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
int ixgbe_ndo_get_vf_config(struct net_device *netdev,
int vf, struct ifla_vf_info *ivi);
void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter);
+void ixgbe_disable_sriov(struct ixgbe_adapter *adapter);
+void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
+ const struct ixgbe_info *ii);
+int ixgbe_check_vf_assignment(struct ixgbe_adapter *adapter);
+
#endif /* _IXGBE_SRIOV_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index e0d970ebab7a..6c5cca808bd7 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -59,12 +59,17 @@
#define IXGBE_SUBDEV_ID_82599_SFP 0x11A9
#define IXGBE_DEV_ID_82599_SFP_EM 0x1507
#define IXGBE_DEV_ID_82599_SFP_SF2 0x154D
+#define IXGBE_DEV_ID_82599EN_SFP 0x1557
#define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC
#define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8
#define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C
#define IXGBE_DEV_ID_82599_LS 0x154F
#define IXGBE_DEV_ID_X540T 0x1528
+/* VF Device IDs */
+#define IXGBE_DEV_ID_82599_VF 0x10ED
+#define IXGBE_DEV_ID_X540_VF 0x1515
+
/* General Registers */
#define IXGBE_CTRL 0x00000
#define IXGBE_STATUS 0x00008
@@ -400,6 +405,8 @@
#define IXGBE_WUPL_LENGTH_MASK 0xFFFF
/* DCB registers */
+#define MAX_TRAFFIC_CLASS 8
+#define X540_TRAFFIC_CLASS 4
#define IXGBE_RMCS 0x03D00
#define IXGBE_DPMCS 0x07F40
#define IXGBE_PDPMCS 0x0CD00
@@ -766,6 +773,7 @@
#define IXGBE_GCR_CAP_VER2 0x00040000
#define IXGBE_GCR_EXT_MSIX_EN 0x80000000
+#define IXGBE_GCR_EXT_BUFFERS_CLEAR 0x40000000
#define IXGBE_GCR_EXT_VT_MODE_16 0x00000001
#define IXGBE_GCR_EXT_VT_MODE_32 0x00000002
#define IXGBE_GCR_EXT_VT_MODE_64 0x00000003
@@ -982,6 +990,7 @@
#define IXGBE_CTRL_GIO_DIS 0x00000004 /* Global IO Master Disable bit */
#define IXGBE_CTRL_LNK_RST 0x00000008 /* Link Reset. Resets everything. */
#define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */
+#define IXGBE_CTRL_RST_MASK (IXGBE_CTRL_LNK_RST | IXGBE_CTRL_RST)
/* FACTPS */
#define IXGBE_FACTPS_LFS 0x40000000 /* LAN Function Select */
@@ -1273,6 +1282,7 @@ enum {
#define IXGBE_EICR_LSC 0x00100000 /* Link Status Change */
#define IXGBE_EICR_LINKSEC 0x00200000 /* PN Threshold */
#define IXGBE_EICR_MNG 0x00400000 /* Manageability Event Interrupt */
+#define IXGBE_EICR_TS 0x00800000 /* Thermal Sensor Event */
#define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */
#define IXGBE_EICR_GPI_SDP1 0x02000000 /* Gen Purpose Interrupt on SDP1 */
#define IXGBE_EICR_GPI_SDP2 0x04000000 /* Gen Purpose Interrupt on SDP2 */
@@ -1307,6 +1317,7 @@ enum {
#define IXGBE_EIMS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */
#define IXGBE_EIMS_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EIMS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
+#define IXGBE_EIMS_TS IXGBE_EICR_TS /* Thermel Sensor Event */
#define IXGBE_EIMS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */
#define IXGBE_EIMS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */
#define IXGBE_EIMS_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */
@@ -1748,6 +1759,10 @@ enum {
#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_SANMAC 0x0 /* Alt. SAN MAC exists */
#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN 0x1 /* Alt. WWN base exists */
+#define IXGBE_DEVICE_CAPS_WOL_PORT0_1 0x4 /* WoL supported on ports 0 & 1 */
+#define IXGBE_DEVICE_CAPS_WOL_PORT0 0x8 /* WoL supported on port 0 */
+#define IXGBE_DEVICE_CAPS_WOL_MASK 0xC /* Mask for WoL capabilities */
+
/* PCI Bus Info */
#define IXGBE_PCI_DEVICE_STATUS 0xAA
#define IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING 0x0020
@@ -1817,6 +1832,7 @@ enum {
#define IXGBE_RXCTRL_RXEN 0x00000001 /* Enable Receiver */
#define IXGBE_RXCTRL_DMBYPS 0x00000002 /* Descriptor Monitor Bypass */
#define IXGBE_RXDCTL_ENABLE 0x02000000 /* Enable specific Rx Queue */
+#define IXGBE_RXDCTL_SWFLSH 0x04000000 /* Rx Desc. write-back flushing */
#define IXGBE_RXDCTL_RLPMLMASK 0x00003FFF /* Only supported on the X540 */
#define IXGBE_RXDCTL_RLPML_EN 0x00008000
#define IXGBE_RXDCTL_VME 0x40000000 /* VLAN mode enable */
@@ -1834,6 +1850,7 @@ enum {
#define IXGBE_MFLCN_DPF 0x00000002 /* Discard Pause Frame */
#define IXGBE_MFLCN_RPFCE 0x00000004 /* Receive Priority FC Enable */
#define IXGBE_MFLCN_RFCE 0x00000008 /* Receive FC Enable */
+#define IXGBE_MFLCN_RPFCE_MASK 0x00000FF0 /* Receive FC Mask */
#define IXGBE_MFLCN_RPFCE_SHIFT 4
@@ -2311,13 +2328,60 @@ typedef u32 ixgbe_physical_layer;
#define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000
#define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x2000
-/* Flow Control Macros */
-#define PAUSE_RTT 8
-#define PAUSE_MTU(MTU) ((MTU + 1024 - 1) / 1024)
+/* Flow Control Data Sheet defined values
+ * Calculation and defines taken from 802.1bb Annex O
+ */
+
+/* BitTimes (BT) conversion */
+#define IXGBE_BT2KB(BT) ((BT + 1023) / (8 * 1024))
+#define IXGBE_B2BT(BT) (BT * 8)
+
+/* Calculate Delay to respond to PFC */
+#define IXGBE_PFC_D 672
+
+/* Calculate Cable Delay */
+#define IXGBE_CABLE_DC 5556 /* Delay Copper */
+#define IXGBE_CABLE_DO 5000 /* Delay Optical */
+
+/* Calculate Interface Delay X540 */
+#define IXGBE_PHY_DC 25600 /* Delay 10G BASET */
+#define IXGBE_MAC_DC 8192 /* Delay Copper XAUI interface */
+#define IXGBE_XAUI_DC (2 * 2048) /* Delay Copper Phy */
+
+#define IXGBE_ID_X540 (IXGBE_MAC_DC + IXGBE_XAUI_DC + IXGBE_PHY_DC)
+
+/* Calculate Interface Delay 82598, 82599 */
+#define IXGBE_PHY_D 12800
+#define IXGBE_MAC_D 4096
+#define IXGBE_XAUI_D (2 * 1024)
+
+#define IXGBE_ID (IXGBE_MAC_D + IXGBE_XAUI_D + IXGBE_PHY_D)
+
+/* Calculate Delay incurred from higher layer */
+#define IXGBE_HD 6144
+
+/* Calculate PCI Bus delay for low thresholds */
+#define IXGBE_PCI_DELAY 10000
+
+/* Calculate X540 delay value in bit times */
+#define IXGBE_FILL_RATE (36 / 25)
+
+#define IXGBE_DV_X540(LINK, TC) (IXGBE_FILL_RATE * \
+ (IXGBE_B2BT(LINK) + IXGBE_PFC_D + \
+ (2 * IXGBE_CABLE_DC) + \
+ (2 * IXGBE_ID_X540) + \
+ IXGBE_HD + IXGBE_B2BT(TC)))
+
+/* Calculate 82599, 82598 delay value in bit times */
+#define IXGBE_DV(LINK, TC) (IXGBE_FILL_RATE * \
+ (IXGBE_B2BT(LINK) + IXGBE_PFC_D + \
+ (2 * IXGBE_CABLE_DC) + (2 * IXGBE_ID) + \
+ IXGBE_HD + IXGBE_B2BT(TC)))
-#define FC_HIGH_WATER(MTU) ((((PAUSE_RTT + PAUSE_MTU(MTU)) * 144) + 99) / 100 +\
- PAUSE_MTU(MTU))
-#define FC_LOW_WATER(MTU) (2 * (2 * PAUSE_MTU(MTU) + PAUSE_RTT))
+/* Calculate low threshold delay values */
+#define IXGBE_LOW_DV_X540(TC) (2 * IXGBE_B2BT(TC) + \
+ (IXGBE_FILL_RATE * IXGBE_PCI_DELAY))
+#define IXGBE_LOW_DV(TC) (2 * IXGBE_LOW_DV_X540(TC))
/* Software ATR hash keys */
#define IXGBE_ATR_BUCKET_HASH_KEY 0x3DAD14E2
@@ -2536,7 +2600,7 @@ struct ixgbe_bus_info {
/* Flow control parameters */
struct ixgbe_fc_info {
- u32 high_water; /* Flow Control High-water */
+ u32 high_water[MAX_TRAFFIC_CLASS]; /* Flow Control High-water */
u32 low_water; /* Flow Control Low-water */
u16 pause_time; /* Flow Control Pause timer */
bool send_xon; /* Flow control send XON */
@@ -2618,6 +2682,8 @@ struct ixgbe_hw_stats {
u64 fcoeptc;
u64 fcoedwrc;
u64 fcoedwtc;
+ u64 fcoe_noddp;
+ u64 fcoe_noddp_ext_buff;
u64 b2ospc;
u64 b2ogprc;
u64 o2bgptc;
diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index 2696c78e9f46..e5101e91b6b5 100644
--- a/drivers/net/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -93,79 +93,47 @@ static s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw,
**/
static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
{
- ixgbe_link_speed link_speed;
- s32 status = 0;
- u32 ctrl;
- u32 ctrl_ext;
- u32 reset_bit;
- u32 i;
- u32 autoc;
- u32 autoc2;
- bool link_up = false;
+ s32 status;
+ u32 ctrl, i;
/* Call adapter stop to disable tx/rx and clear interrupts */
- hw->mac.ops.stop_adapter(hw);
+ status = hw->mac.ops.stop_adapter(hw);
+ if (status != 0)
+ goto reset_hw_out;
- /*
- * Prevent the PCI-E bus from from hanging by disabling PCI-E master
- * access and verify no pending requests before reset
- */
- ixgbe_disable_pcie_master(hw);
+ /* flush pending Tx transactions */
+ ixgbe_clear_tx_pending(hw);
mac_reset_top:
- /*
- * Issue global reset to the MAC. Needs to be SW reset if link is up.
- * If link reset is used when link is up, it might reset the PHY when
- * mng is using it. If link is down or the flag to force full link
- * reset is set, then perform link reset.
- */
- if (hw->force_full_reset) {
- reset_bit = IXGBE_CTRL_LNK_RST;
- } else {
- hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
- if (!link_up)
- reset_bit = IXGBE_CTRL_LNK_RST;
- else
- reset_bit = IXGBE_CTRL_RST;
- }
-
- ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
- IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | reset_bit));
+ ctrl = IXGBE_CTRL_RST;
+ ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
IXGBE_WRITE_FLUSH(hw);
/* Poll for reset bit to self-clear indicating reset is complete */
for (i = 0; i < 10; i++) {
udelay(1);
ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
- if (!(ctrl & reset_bit))
+ if (!(ctrl & IXGBE_CTRL_RST_MASK))
break;
}
- if (ctrl & reset_bit) {
+
+ if (ctrl & IXGBE_CTRL_RST_MASK) {
status = IXGBE_ERR_RESET_FAILED;
hw_dbg(hw, "Reset polling failed to complete.\n");
}
+ msleep(100);
/*
* Double resets are required for recovery from certain error
* conditions. Between resets, it is necessary to stall to allow time
- * for any pending HW events to complete. We use 1usec since that is
- * what is needed for ixgbe_disable_pcie_master(). The second reset
- * then clears out any effects of those events.
+ * for any pending HW events to complete.
*/
if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
- udelay(1);
goto mac_reset_top;
}
- /* Clear PF Reset Done bit so PF/VF Mail Ops can work */
- ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
- ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
- IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
- IXGBE_WRITE_FLUSH(hw);
-
- msleep(50);
-
/* Set the Rx packet buffer size. */
IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT);
@@ -173,31 +141,6 @@ mac_reset_top:
hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
/*
- * Store the original AUTOC/AUTOC2 values if they have not been
- * stored off yet. Otherwise restore the stored original
- * values since the reset operation sets back to defaults.
- */
- autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
- autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
- if (hw->mac.orig_link_settings_stored == false) {
- hw->mac.orig_autoc = autoc;
- 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 ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
- (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
- autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK;
- autoc2 |= (hw->mac.orig_autoc2 &
- IXGBE_AUTOC2_UPPER_MASK);
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
- }
- }
-
- /*
* Store MAC address from RAR0, clear receive address registers, and
* clear the multicast table. Also reset num_rar_entries to 128,
* since we modify this value when programming the SAN MAC address.
@@ -205,9 +148,6 @@ mac_reset_top:
hw->mac.num_rar_entries = IXGBE_X540_MAX_TX_QUEUES;
hw->mac.ops.init_rx_addrs(hw);
- /* Store the permanent mac address */
- hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
-
/* Store the permanent SAN mac address */
hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
@@ -224,6 +164,7 @@ mac_reset_top:
hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
&hw->mac.wwpn_prefix);
+reset_hw_out:
return status;
}
@@ -929,6 +870,7 @@ static struct ixgbe_phy_operations phy_ops_X540 = {
.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic,
.write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic,
.check_overtemp = &ixgbe_tn_check_overtemp,
+ .get_firmware_version = &ixgbe_get_phy_firmware_version_generic,
};
struct ixgbe_info ixgbe_X540_info = {
diff --git a/drivers/net/ixgbevf/Makefile b/drivers/net/ethernet/intel/ixgbevf/Makefile
index 1f35d229e71a..1f35d229e71a 100644
--- a/drivers/net/ixgbevf/Makefile
+++ b/drivers/net/ethernet/intel/ixgbevf/Makefile
diff --git a/drivers/net/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h
index 78abb6f1a866..78abb6f1a866 100644
--- a/drivers/net/ixgbevf/defines.h
+++ b/drivers/net/ethernet/intel/ixgbevf/defines.h
diff --git a/drivers/net/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
index deee3754b1f7..e29ba4506b74 100644
--- a/drivers/net/ixgbevf/ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
@@ -117,44 +117,6 @@ static int ixgbevf_get_settings(struct net_device *netdev,
return 0;
}
-static u32 ixgbevf_get_rx_csum(struct net_device *netdev)
-{
- struct ixgbevf_adapter *adapter = netdev_priv(netdev);
- return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED;
-}
-
-static int ixgbevf_set_rx_csum(struct net_device *netdev, u32 data)
-{
- struct ixgbevf_adapter *adapter = netdev_priv(netdev);
- if (data)
- adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
- else
- adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
-
- if (netif_running(netdev)) {
- if (!adapter->dev_closed)
- ixgbevf_reinit_locked(adapter);
- } else {
- ixgbevf_reset(adapter);
- }
-
- return 0;
-}
-
-static int ixgbevf_set_tso(struct net_device *netdev, u32 data)
-{
- if (data) {
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
- } else {
- netif_tx_stop_all_queues(netdev);
- netdev->features &= ~NETIF_F_TSO;
- netdev->features &= ~NETIF_F_TSO6;
- netif_tx_start_all_queues(netdev);
- }
- return 0;
-}
-
static u32 ixgbevf_get_msglevel(struct net_device *netdev)
{
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
@@ -319,12 +281,8 @@ static void ixgbevf_get_ringparam(struct net_device *netdev,
ring->rx_max_pending = IXGBEVF_MAX_RXD;
ring->tx_max_pending = IXGBEVF_MAX_TXD;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = rx_ring->count;
ring->tx_pending = tx_ring->count;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
static int ixgbevf_set_ringparam(struct net_device *netdev,
@@ -720,16 +678,8 @@ static struct ethtool_ops ixgbevf_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_ringparam = ixgbevf_get_ringparam,
.set_ringparam = ixgbevf_set_ringparam,
- .get_rx_csum = ixgbevf_get_rx_csum,
- .set_rx_csum = ixgbevf_set_rx_csum,
- .get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = ethtool_op_set_tx_ipv6_csum,
- .get_sg = ethtool_op_get_sg,
- .set_sg = ethtool_op_set_sg,
.get_msglevel = ixgbevf_get_msglevel,
.set_msglevel = ixgbevf_set_msglevel,
- .get_tso = ethtool_op_get_tso,
- .set_tso = ixgbevf_set_tso,
.self_test = ixgbevf_diag_test,
.get_sset_count = ixgbevf_get_sset_count,
.get_strings = ixgbevf_get_strings,
diff --git a/drivers/net/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 8857df4dd3b9..e6c9d1a927a9 100644
--- a/drivers/net/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -34,6 +34,7 @@
#include <linux/io.h>
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
+#include <linux/u64_stats_sync.h>
#include "vf.h"
@@ -71,12 +72,13 @@ struct ixgbevf_ring {
struct ixgbevf_rx_buffer *rx_buffer_info;
};
+ u64 total_bytes;
+ u64 total_packets;
+ struct u64_stats_sync syncp;
+
u16 head;
u16 tail;
- unsigned int total_bytes;
- unsigned int total_packets;
-
u16 reg_idx; /* holds the special value that gets the hardware register
* offset associated with this ring, which is different
* for DCB and RSS modes */
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 3b880a27f8d1..5e92cc2079bd 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -44,6 +44,7 @@
#include <net/checksum.h>
#include <net/ip6_checksum.h>
#include <linux/ethtool.h>
+#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/prefetch.h>
@@ -202,6 +203,9 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter,
(count < tx_ring->work_limit)) {
bool cleaned = false;
rmb(); /* read buffer_info after eop_desc */
+ /* eop could change between read and DD-check */
+ if (unlikely(eop != tx_ring->tx_buffer_info[i].next_to_watch))
+ goto cont_loop;
for ( ; !cleaned; count++) {
struct sk_buff *skb;
tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
@@ -231,6 +235,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter,
i = 0;
}
+cont_loop:
eop = tx_ring->tx_buffer_info[i].next_to_watch;
eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
}
@@ -265,11 +270,10 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter,
IXGBE_WRITE_REG(hw, IXGBE_VTEICS, tx_ring->v_idx);
}
+ u64_stats_update_begin(&tx_ring->syncp);
tx_ring->total_bytes += total_bytes;
tx_ring->total_packets += total_packets;
-
- netdev->stats.tx_bytes += total_bytes;
- netdev->stats.tx_packets += total_packets;
+ u64_stats_update_end(&tx_ring->syncp);
return count < tx_ring->work_limit;
}
@@ -289,12 +293,10 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector,
{
struct ixgbevf_adapter *adapter = q_vector->adapter;
bool is_vlan = (status & IXGBE_RXD_STAT_VP);
+ u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
- if (is_vlan) {
- u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
-
+ if (is_vlan && test_bit(tag, adapter->active_vlans))
__vlan_hwaccel_put_tag(skb, tag);
- }
if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
napi_gro_receive(&q_vector->napi, skb);
@@ -592,10 +594,10 @@ next_desc:
if (cleaned_count)
ixgbevf_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
+ u64_stats_update_begin(&rx_ring->syncp);
rx_ring->total_packets += total_rx_packets;
rx_ring->total_bytes += total_rx_bytes;
- adapter->netdev->stats.rx_bytes += total_rx_bytes;
- adapter->netdev->stats.rx_packets += total_rx_packets;
+ u64_stats_update_end(&rx_ring->syncp);
return cleaned;
}
@@ -2255,10 +2257,6 @@ void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
adapter->stats.vfgotc);
UPDATE_VF_COUNTER_32bit(IXGBE_VFMPRC, adapter->stats.last_vfmprc,
adapter->stats.vfmprc);
-
- /* Fill out the OS statistics structure */
- adapter->netdev->stats.multicast = adapter->stats.vfmprc -
- adapter->stats.base_vfmprc;
}
/**
@@ -2914,22 +2912,20 @@ static int ixgbevf_tx_map(struct ixgbevf_adapter *adapter,
}
for (f = 0; f < nr_frags; f++) {
- struct skb_frag_struct *frag;
+ const struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[f];
- len = min((unsigned int)frag->size, total);
- offset = frag->page_offset;
+ len = min((unsigned int)skb_frag_size(frag), total);
+ offset = 0;
while (len) {
tx_buffer_info = &tx_ring->tx_buffer_info[i];
size = min(len, (unsigned int)IXGBE_MAX_DATA_PER_TXD);
tx_buffer_info->length = size;
- tx_buffer_info->dma = dma_map_page(&adapter->pdev->dev,
- frag->page,
- offset,
- size,
- DMA_TO_DEVICE);
+ tx_buffer_info->dma =
+ skb_frag_dma_map(&adapter->pdev->dev, frag,
+ offset, size, DMA_TO_DEVICE);
tx_buffer_info->mapped_as_page = true;
if (dma_mapping_error(&pdev->dev, tx_buffer_info->dma))
goto dma_error;
@@ -3100,7 +3096,7 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
count += TXD_USE_COUNT(skb_headlen(skb));
for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
- count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
+ count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]));
if (ixgbevf_maybe_stop_tx(netdev, tx_ring, count)) {
adapter->tx_busy++;
@@ -3215,18 +3211,69 @@ static void ixgbevf_shutdown(struct pci_dev *pdev)
pci_disable_device(pdev);
}
+static struct rtnl_link_stats64 *ixgbevf_get_stats(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct ixgbevf_adapter *adapter = netdev_priv(netdev);
+ unsigned int start;
+ u64 bytes, packets;
+ const struct ixgbevf_ring *ring;
+ int i;
+
+ ixgbevf_update_stats(adapter);
+
+ stats->multicast = adapter->stats.vfmprc - adapter->stats.base_vfmprc;
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ ring = &adapter->rx_ring[i];
+ do {
+ start = u64_stats_fetch_begin_bh(&ring->syncp);
+ bytes = ring->total_bytes;
+ packets = ring->total_packets;
+ } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+ stats->rx_bytes += bytes;
+ stats->rx_packets += packets;
+ }
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ ring = &adapter->tx_ring[i];
+ do {
+ start = u64_stats_fetch_begin_bh(&ring->syncp);
+ bytes = ring->total_bytes;
+ packets = ring->total_packets;
+ } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+ stats->tx_bytes += bytes;
+ stats->tx_packets += packets;
+ }
+
+ return stats;
+}
+
+static int ixgbevf_set_features(struct net_device *netdev, u32 features)
+{
+ struct ixgbevf_adapter *adapter = netdev_priv(netdev);
+
+ if (features & NETIF_F_RXCSUM)
+ adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
+ else
+ adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
+
+ return 0;
+}
+
static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbevf_open,
.ndo_stop = ixgbevf_close,
.ndo_start_xmit = ixgbevf_xmit_frame,
.ndo_set_rx_mode = ixgbevf_set_rx_mode,
- .ndo_set_multicast_list = ixgbevf_set_rx_mode,
+ .ndo_get_stats64 = ixgbevf_get_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ixgbevf_set_mac,
.ndo_change_mtu = ixgbevf_change_mtu,
.ndo_tx_timeout = ixgbevf_tx_timeout,
.ndo_vlan_rx_add_vid = ixgbevf_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ixgbevf_vlan_rx_kill_vid,
+ .ndo_set_features = ixgbevf_set_features,
};
static void ixgbevf_assign_netdev_ops(struct net_device *dev)
@@ -3339,16 +3386,18 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
/* setup the private structure */
err = ixgbevf_sw_init(adapter);
- netdev->features = NETIF_F_SG |
+ netdev->hw_features = NETIF_F_SG |
NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM |
+ NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_RXCSUM;
+
+ netdev->features = netdev->hw_features |
NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
- netdev->features |= NETIF_F_IPV6_CSUM;
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
- netdev->features |= NETIF_F_GRO;
netdev->vlan_features |= NETIF_F_TSO;
netdev->vlan_features |= NETIF_F_TSO6;
netdev->vlan_features |= NETIF_F_IP_CSUM;
@@ -3358,6 +3407,8 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
/* The HW MAC address was set and/or determined in sw_init */
memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
diff --git a/drivers/net/ixgbevf/mbx.c b/drivers/net/ethernet/intel/ixgbevf/mbx.c
index 7a8833125770..930fa83f2568 100644
--- a/drivers/net/ixgbevf/mbx.c
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c
@@ -276,7 +276,7 @@ out_no_write:
* @msg: The message buffer
* @size: Length of buffer
*
- * returns 0 if it successfuly read message from buffer
+ * returns 0 if it successfully read message from buffer
**/
static s32 ixgbevf_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size)
{
diff --git a/drivers/net/ixgbevf/mbx.h b/drivers/net/ethernet/intel/ixgbevf/mbx.h
index ea393eb03f3a..ea393eb03f3a 100644
--- a/drivers/net/ixgbevf/mbx.h
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.h
diff --git a/drivers/net/ixgbevf/regs.h b/drivers/net/ethernet/intel/ixgbevf/regs.h
index 189200eeca26..189200eeca26 100644
--- a/drivers/net/ixgbevf/regs.h
+++ b/drivers/net/ethernet/intel/ixgbevf/regs.h
diff --git a/drivers/net/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index aa3682e8c473..aa3682e8c473 100644
--- a/drivers/net/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
diff --git a/drivers/net/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h
index 10306b492ee6..10306b492ee6 100644
--- a/drivers/net/ixgbevf/vf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.h
diff --git a/drivers/net/jme.c b/drivers/net/ethernet/jme.c
index 3ac262f55633..7becff1f387d 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -1920,7 +1920,7 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx)
u8 hidma = jme->dev->features & NETIF_F_HIGHDMA;
int i, nr_frags = skb_shinfo(skb)->nr_frags;
int mask = jme->tx_ring_mask;
- struct skb_frag_struct *frag;
+ const struct skb_frag_struct *frag;
u32 len;
for (i = 0 ; i < nr_frags ; ++i) {
@@ -1928,8 +1928,9 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx)
ctxdesc = txdesc + ((idx + i + 2) & (mask));
ctxbi = txbi + ((idx + i + 2) & (mask));
- jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, frag->page,
- frag->page_offset, frag->size, hidma);
+ jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi,
+ skb_frag_page(frag),
+ frag->page_offset, skb_frag_size(frag), hidma);
}
len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len;
@@ -2839,7 +2840,7 @@ static const struct net_device_ops jme_netdev_ops = {
.ndo_do_ioctl = jme_ioctl,
.ndo_start_xmit = jme_start_xmit,
.ndo_set_mac_address = jme_set_macaddr,
- .ndo_set_multicast_list = jme_set_multi,
+ .ndo_set_rx_mode = jme_set_multi,
.ndo_change_mtu = jme_change_mtu,
.ndo_tx_timeout = jme_tx_timeout,
.ndo_fix_features = jme_fix_features,
@@ -3131,6 +3132,9 @@ jme_suspend(struct device *dev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct jme_adapter *jme = netdev_priv(netdev);
+ if (!netif_running(netdev))
+ return 0;
+
atomic_dec(&jme->link_changing);
netif_device_detach(netdev);
@@ -3171,6 +3175,9 @@ jme_resume(struct device *dev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct jme_adapter *jme = netdev_priv(netdev);
+ if (!netif_running(netdev))
+ return 0;
+
jme_clear_pm(jme);
jme_phy_on(jme);
if (test_bit(JME_FLAG_SSET, &jme->flags))
diff --git a/drivers/net/jme.h b/drivers/net/ethernet/jme.h
index c1f8b893e2ea..02ea27c1dcb5 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/ethernet/jme.h
@@ -102,7 +102,6 @@ enum jme_spi_op_bits {
};
#define HALF_US 500 /* 500 ns */
-#define JMESPIIOCTL SIOCDEVPRIVATE
#define PCI_PRIV_PE1 0xE4
diff --git a/drivers/net/korina.c b/drivers/net/ethernet/korina.c
index 763844c587fd..d8430f487b84 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -58,7 +58,6 @@
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/pgtable.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/dma.h>
@@ -1089,7 +1088,7 @@ static const struct net_device_ops korina_netdev_ops = {
.ndo_open = korina_open,
.ndo_stop = korina_close,
.ndo_start_xmit = korina_send_packet,
- .ndo_set_multicast_list = korina_multicast_list,
+ .ndo_set_rx_mode = korina_multicast_list,
.ndo_tx_timeout = korina_tx_timeout,
.ndo_do_ioctl = korina_ioctl,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 45f252b7da30..6bb2b9506cad 100644
--- a/drivers/net/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -687,7 +687,7 @@ static const struct net_device_ops ltq_eth_netdev_ops = {
.ndo_do_ioctl = ltq_etop_ioctl,
.ndo_set_mac_address = ltq_etop_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = ltq_etop_set_multicast_list,
+ .ndo_set_rx_mode = ltq_etop_set_multicast_list,
.ndo_select_queue = ltq_etop_select_queue,
.ndo_init = ltq_etop_init,
.ndo_tx_timeout = ltq_etop_tx_timeout,
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
new file mode 100644
index 000000000000..0029934748bc
--- /dev/null
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -0,0 +1,111 @@
+#
+# Marvell device configuration
+#
+
+config NET_VENDOR_MARVELL
+ bool "Marvell devices"
+ default y
+ depends on PCI || CPU_PXA168 || MV64X60 || PPC32 || PLAT_ORION || INET
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Marvell devices. If you say Y, you will be
+ asked for your specific card in the following questions.
+
+if NET_VENDOR_MARVELL
+
+config MV643XX_ETH
+ tristate "Marvell Discovery (643XX) and Orion ethernet support"
+ depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
+ select INET_LRO
+ select PHYLIB
+ ---help---
+ This driver supports the gigabit ethernet MACs in the
+ Marvell Discovery PPC/MIPS chipset family (MV643XX) and
+ in the Marvell Orion ARM SoC family.
+
+ Some boards that use the Discovery chipset are the Momenco
+ Ocelot C and Jaguar ATX and Pegasos II.
+
+config PXA168_ETH
+ tristate "Marvell pxa168 ethernet support"
+ depends on CPU_PXA168
+ select PHYLIB
+ ---help---
+ This driver supports the pxa168 Ethernet ports.
+
+ To compile this driver as a module, choose M here. The module
+ will be called pxa168_eth.
+
+config SKGE
+ tristate "Marvell Yukon Gigabit Ethernet support"
+ depends on PCI
+ select CRC32
+ ---help---
+ This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
+ and related Gigabit Ethernet adapters. It is a new smaller driver
+ with better performance and more complete ethtool support.
+
+ It does not support the link failover and network management
+ features that "portable" vendor supplied sk98lin driver does.
+
+ This driver supports adapters based on the original Yukon chipset:
+ Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
+ Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872.
+
+ It does not support the newer Yukon2 chipset: a separate driver,
+ sky2, is provided for these adapters.
+
+ To compile this driver as a module, choose M here: the module
+ will be called skge. This is recommended.
+
+config SKGE_DEBUG
+ bool "Debugging interface"
+ depends on SKGE && DEBUG_FS
+ ---help---
+ This option adds the ability to dump driver state for debugging.
+ The file /sys/kernel/debug/skge/ethX displays the state of the internal
+ transmit and receive rings.
+
+ If unsure, say N.
+
+config SKGE_GENESIS
+ bool "Support for older SysKonnect Genesis boards"
+ depends on SKGE
+ ---help---
+ This enables support for the older and uncommon SysKonnect Genesis
+ chips, which support MII via an external transceiver, instead of
+ an internal one. Disabling this option will save some memory
+ by making code smaller. If unsure say Y.
+
+config SKY2
+ tristate "Marvell Yukon 2 support"
+ depends on PCI
+ select CRC32
+ ---help---
+ This driver supports Gigabit Ethernet adapters based on the
+ Marvell Yukon 2 chipset:
+ Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/
+ 88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21
+
+ There is companion driver for the older Marvell Yukon and
+ SysKonnect Genesis based adapters: skge.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sky2. This is recommended.
+
+config SKY2_DEBUG
+ bool "Debugging interface"
+ depends on SKY2 && DEBUG_FS
+ ---help---
+ This option adds the ability to dump driver state for debugging.
+ The file /sys/kernel/debug/sky2/ethX displays the state of the internal
+ transmit and receive rings.
+
+ If unsure, say N.
+
+endif # NET_VENDOR_MARVELL
diff --git a/drivers/net/ethernet/marvell/Makefile b/drivers/net/ethernet/marvell/Makefile
new file mode 100644
index 000000000000..57e3234a37ba
--- /dev/null
+++ b/drivers/net/ethernet/marvell/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Marvell device drivers.
+#
+
+obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
+obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
+obj-$(CONFIG_SKGE) += skge.o
+obj-$(CONFIG_SKY2) += sky2.o
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 259699983ca5..194a03113802 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -713,8 +713,9 @@ static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)
int frag;
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
- skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag];
- if (fragp->size <= 8 && fragp->page_offset & 7)
+ const skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag];
+
+ if (skb_frag_size(fragp) <= 8 && fragp->page_offset & 7)
return 1;
}
@@ -751,11 +752,11 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
}
desc->l4i_chk = 0;
- desc->byte_cnt = this_frag->size;
- desc->buf_ptr = dma_map_page(mp->dev->dev.parent,
- this_frag->page,
- this_frag->page_offset,
- this_frag->size, DMA_TO_DEVICE);
+ desc->byte_cnt = skb_frag_size(this_frag);
+ desc->buf_ptr = skb_frag_dma_map(mp->dev->dev.parent,
+ this_frag, 0,
+ skb_frag_size(this_frag),
+ DMA_TO_DEVICE);
}
}
@@ -1547,13 +1548,9 @@ mv643xx_eth_get_ringparam(struct net_device *dev, struct ethtool_ringparam *er)
er->rx_max_pending = 4096;
er->tx_max_pending = 4096;
- er->rx_mini_max_pending = 0;
- er->rx_jumbo_max_pending = 0;
er->rx_pending = mp->rx_ring_size;
er->tx_pending = mp->tx_ring_size;
- er->rx_mini_pending = 0;
- er->rx_jumbo_pending = 0;
}
static int
@@ -2923,6 +2920,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM;
+ dev->priv_flags |= IFF_UNICAST_FLT;
+
SET_NETDEV_DEV(dev, &pdev->dev);
if (mp->shared->win_protect)
diff --git a/drivers/net/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index d17d0624c5e6..d17d0624c5e6 100644
--- a/drivers/net/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
diff --git a/drivers/net/skge.c b/drivers/net/ethernet/marvell/skge.c
index 98ec614c5690..c7b60839ac99 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -113,6 +113,7 @@ static void yukon_init(struct skge_hw *hw, int port);
static void genesis_mac_init(struct skge_hw *hw, int port);
static void genesis_link_up(struct skge_port *skge);
static void skge_set_multicast(struct net_device *dev);
+static irqreturn_t skge_intr(int irq, void *dev_id);
/* Avoid conditionals by using array */
static const int txqaddr[] = { Q_XA1, Q_XA2 };
@@ -496,13 +497,9 @@ static void skge_get_ring_param(struct net_device *dev,
p->rx_max_pending = MAX_RX_RING_SIZE;
p->tx_max_pending = MAX_TX_RING_SIZE;
- p->rx_mini_max_pending = 0;
- p->rx_jumbo_max_pending = 0;
p->rx_pending = skge->rx_ring.count;
p->tx_pending = skge->tx_ring.count;
- p->rx_mini_pending = 0;
- p->rx_jumbo_pending = 0;
}
static int skge_set_ring_param(struct net_device *dev,
@@ -2568,6 +2565,16 @@ static int skge_up(struct net_device *dev)
if (err)
goto free_rx_ring;
+ if (hw->ports == 1) {
+ err = request_irq(hw->pdev->irq, skge_intr, IRQF_SHARED,
+ dev->name, hw);
+ if (err) {
+ netdev_err(dev, "Unable to allocate interrupt %d error: %d\n",
+ hw->pdev->irq, err);
+ goto free_tx_ring;
+ }
+ }
+
/* Initialize MAC */
spin_lock_bh(&hw->phy_lock);
if (is_genesis(hw))
@@ -2595,11 +2602,14 @@ static int skge_up(struct net_device *dev)
spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= portmask[port];
skge_write32(hw, B0_IMSK, hw->intr_mask);
+ skge_read32(hw, B0_IMSK);
spin_unlock_irq(&hw->hw_lock);
napi_enable(&skge->napi);
return 0;
+ free_tx_ring:
+ kfree(skge->tx_ring.start);
free_rx_ring:
skge_rx_clean(skge);
kfree(skge->rx_ring.start);
@@ -2640,9 +2650,13 @@ static int skge_down(struct net_device *dev)
spin_lock_irq(&hw->hw_lock);
hw->intr_mask &= ~portmask[port];
- skge_write32(hw, B0_IMSK, hw->intr_mask);
+ skge_write32(hw, B0_IMSK, (hw->ports == 1) ? 0 : hw->intr_mask);
+ skge_read32(hw, B0_IMSK);
spin_unlock_irq(&hw->hw_lock);
+ if (hw->ports == 1)
+ free_irq(hw->pdev->irq, hw);
+
skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
if (is_genesis(hw))
genesis_stop(skge);
@@ -2756,10 +2770,10 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
control |= BMU_STFWD;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- map = pci_map_page(hw->pdev, frag->page, frag->page_offset,
- frag->size, PCI_DMA_TODEVICE);
+ map = skb_frag_dma_map(&hw->pdev->dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
e = e->next;
e->skb = skb;
@@ -2769,9 +2783,9 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
tf->dma_lo = map;
tf->dma_hi = (u64) map >> 32;
dma_unmap_addr_set(e, mapaddr, map);
- dma_unmap_len_set(e, maplen, frag->size);
+ dma_unmap_len_set(e, maplen, skb_frag_size(frag));
- tf->control = BMU_OWN | BMU_SW | control | frag->size;
+ tf->control = BMU_OWN | BMU_SW | control | skb_frag_size(frag);
}
tf->control |= BMU_EOF | BMU_IRQ_EOF;
}
@@ -3603,7 +3617,8 @@ static int skge_reset(struct skge_hw *hw)
skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
skge_write32(hw, B2_IRQM_CTRL, TIM_START);
- skge_write32(hw, B0_IMSK, hw->intr_mask);
+ /* Leave irq disabled until first port is brought up. */
+ skge_write32(hw, B0_IMSK, 0);
for (i = 0; i < hw->ports; i++) {
if (is_genesis(hw))
@@ -3762,7 +3777,7 @@ static const struct net_device_ops skge_netdev_ops = {
.ndo_tx_timeout = skge_tx_timeout,
.ndo_change_mtu = skge_change_mtu,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = skge_set_multicast,
+ .ndo_set_rx_mode = skge_set_multicast,
.ndo_set_mac_address = skge_set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = skge_netpoll,
@@ -3930,31 +3945,39 @@ static int __devinit skge_probe(struct pci_dev *pdev,
goto err_out_free_netdev;
}
- err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, hw->irq_name, hw);
- if (err) {
- dev_err(&pdev->dev, "%s: cannot assign irq %d\n",
- dev->name, pdev->irq);
- goto err_out_unregister;
- }
skge_show_addr(dev);
if (hw->ports > 1) {
dev1 = skge_devinit(hw, 1, using_dac);
- if (dev1 && register_netdev(dev1) == 0)
- skge_show_addr(dev1);
- else {
- /* Failure to register second port need not be fatal */
- dev_warn(&pdev->dev, "register of second port failed\n");
- hw->dev[1] = NULL;
- hw->ports = 1;
- if (dev1)
- free_netdev(dev1);
+ if (!dev1) {
+ err = -ENOMEM;
+ goto err_out_unregister;
}
+
+ err = register_netdev(dev1);
+ if (err) {
+ dev_err(&pdev->dev, "cannot register second net device\n");
+ goto err_out_free_dev1;
+ }
+
+ err = request_irq(pdev->irq, skge_intr, IRQF_SHARED,
+ hw->irq_name, hw);
+ if (err) {
+ dev_err(&pdev->dev, "cannot assign irq %d\n",
+ pdev->irq);
+ goto err_out_unregister_dev1;
+ }
+
+ skge_show_addr(dev1);
}
pci_set_drvdata(pdev, hw);
return 0;
+err_out_unregister_dev1:
+ unregister_netdev(dev1);
+err_out_free_dev1:
+ free_netdev(dev1);
err_out_unregister:
unregister_netdev(dev);
err_out_free_netdev:
@@ -3992,14 +4015,19 @@ static void __devexit skge_remove(struct pci_dev *pdev)
spin_lock_irq(&hw->hw_lock);
hw->intr_mask = 0;
- skge_write32(hw, B0_IMSK, 0);
- skge_read32(hw, B0_IMSK);
+
+ if (hw->ports > 1) {
+ skge_write32(hw, B0_IMSK, 0);
+ skge_read32(hw, B0_IMSK);
+ free_irq(pdev->irq, hw);
+ }
spin_unlock_irq(&hw->hw_lock);
skge_write16(hw, B0_LED, LED_STAT_OFF);
skge_write8(hw, B0_CTST, CS_RST_SET);
- free_irq(pdev->irq, hw);
+ if (hw->ports > 1)
+ free_irq(pdev->irq, hw);
pci_release_regions(pdev);
pci_disable_device(pdev);
if (dev1)
diff --git a/drivers/net/skge.h b/drivers/net/ethernet/marvell/skge.h
index a2eb34115844..a2eb34115844 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/ethernet/marvell/skge.h
diff --git a/drivers/net/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 57339da76326..cbd026f3bc57 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -148,6 +148,7 @@ static const unsigned rxqaddr[] = { Q_R1, Q_R2 };
static const u32 portirq_msk[] = { Y2_IS_PORT_1, Y2_IS_PORT_2 };
static void sky2_set_multicast(struct net_device *dev);
+static irqreturn_t sky2_intr(int irq, void *dev_id);
/* Access to PHY via serial interconnect */
static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val)
@@ -1224,14 +1225,13 @@ static int sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re,
dma_unmap_len_set(re, data_size, size);
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- re->frag_addr[i] = pci_map_page(pdev, frag->page,
- frag->page_offset,
- frag->size,
- PCI_DMA_FROMDEVICE);
+ re->frag_addr[i] = skb_frag_dma_map(&pdev->dev, frag, 0,
+ skb_frag_size(frag),
+ DMA_FROM_DEVICE);
- if (pci_dma_mapping_error(pdev, re->frag_addr[i]))
+ if (dma_mapping_error(&pdev->dev, re->frag_addr[i]))
goto map_page_error;
}
return 0;
@@ -1239,7 +1239,7 @@ static int sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re,
map_page_error:
while (--i >= 0) {
pci_unmap_page(pdev, re->frag_addr[i],
- skb_shinfo(skb)->frags[i].size,
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
PCI_DMA_FROMDEVICE);
}
@@ -1263,7 +1263,7 @@ static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re)
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
pci_unmap_page(pdev, re->frag_addr[i],
- skb_shinfo(skb)->frags[i].size,
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
PCI_DMA_FROMDEVICE);
}
@@ -1716,6 +1716,27 @@ static void sky2_hw_up(struct sky2_port *sky2)
sky2_rx_start(sky2);
}
+/* Setup device IRQ and enable napi to process */
+static int sky2_setup_irq(struct sky2_hw *hw, const char *name)
+{
+ struct pci_dev *pdev = hw->pdev;
+ int err;
+
+ err = request_irq(pdev->irq, sky2_intr,
+ (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
+ name, hw);
+ if (err)
+ dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
+ else {
+ napi_enable(&hw->napi);
+ sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+ sky2_read32(hw, B0_IMSK);
+ }
+
+ return err;
+}
+
+
/* Bring up network interface. */
static int sky2_up(struct net_device *dev)
{
@@ -1731,6 +1752,10 @@ static int sky2_up(struct net_device *dev)
if (err)
goto err_out;
+ /* With single port, IRQ is setup when device is brought up */
+ if (hw->ports == 1 && (err = sky2_setup_irq(hw, dev->name)))
+ goto err_out;
+
sky2_hw_up(sky2);
/* Enable interrupts from phy/mac for port */
@@ -1910,10 +1935,10 @@ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb,
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
- frag->size, PCI_DMA_TODEVICE);
+ mapping = skb_frag_dma_map(&hw->pdev->dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
- if (pci_dma_mapping_error(hw->pdev, mapping))
+ if (dma_mapping_error(&hw->pdev->dev, mapping))
goto mapping_unwind;
upper = upper_32_bits(mapping);
@@ -1927,11 +1952,11 @@ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb,
re = sky2->tx_ring + slot;
re->flags = TX_MAP_PAGE;
dma_unmap_addr_set(re, mapaddr, mapping);
- dma_unmap_len_set(re, maplen, frag->size);
+ dma_unmap_len_set(re, maplen, skb_frag_size(frag));
le = get_tx_le(sky2, &slot);
le->addr = cpu_to_le32(lower_32_bits(mapping));
- le->length = cpu_to_le16(frag->size);
+ le->length = cpu_to_le16(skb_frag_size(frag));
le->ctrl = ctrl;
le->opcode = OP_BUFFER | HW_OWNER;
}
@@ -2057,7 +2082,7 @@ static void sky2_hw_down(struct sky2_port *sky2)
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
- /* Force any delayed status interrrupt and NAPI */
+ /* Force any delayed status interrupt and NAPI */
sky2_write32(hw, STAT_LEV_TIMER_CNT, 0);
sky2_write32(hw, STAT_TX_TIMER_CNT, 0);
sky2_write32(hw, STAT_ISR_TIMER_CNT, 0);
@@ -2092,8 +2117,13 @@ static int sky2_down(struct net_device *dev)
sky2_read32(hw, B0_IMSK) & ~portirq_msk[sky2->port]);
sky2_read32(hw, B0_IMSK);
- synchronize_irq(hw->pdev->irq);
- napi_synchronize(&hw->napi);
+ if (hw->ports == 1) {
+ napi_disable(&hw->napi);
+ free_irq(hw->pdev->irq, hw);
+ } else {
+ synchronize_irq(hw->pdev->irq);
+ napi_synchronize(&hw->napi);
+ }
sky2_hw_down(sky2);
@@ -2449,14 +2479,14 @@ static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
if (length == 0) {
/* don't need this page */
- __free_page(frag->page);
+ __skb_frag_unref(frag);
--skb_shinfo(skb)->nr_frags;
} else {
size = min(length, (unsigned) PAGE_SIZE);
- frag->size = size;
+ skb_frag_size_set(frag, size);
skb->data_len += size;
- skb->truesize += size;
+ skb->truesize += PAGE_SIZE;
skb->len += size;
length -= size;
}
@@ -4058,13 +4088,9 @@ static void sky2_get_ringparam(struct net_device *dev,
struct sky2_port *sky2 = netdev_priv(dev);
ering->rx_max_pending = RX_MAX_PENDING;
- ering->rx_mini_max_pending = 0;
- ering->rx_jumbo_max_pending = 0;
ering->tx_max_pending = TX_MAX_PENDING;
ering->rx_pending = sky2->rx_pending;
- ering->rx_mini_pending = 0;
- ering->rx_jumbo_pending = 0;
ering->tx_pending = sky2->tx_pending;
}
@@ -4612,7 +4638,7 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
.ndo_do_ioctl = sky2_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = sky2_set_mac_address,
- .ndo_set_multicast_list = sky2_set_multicast,
+ .ndo_set_rx_mode = sky2_set_multicast,
.ndo_change_mtu = sky2_change_mtu,
.ndo_fix_features = sky2_fix_features,
.ndo_set_features = sky2_set_features,
@@ -4629,7 +4655,7 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
.ndo_do_ioctl = sky2_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = sky2_set_mac_address,
- .ndo_set_multicast_list = sky2_set_multicast,
+ .ndo_set_rx_mode = sky2_set_multicast,
.ndo_change_mtu = sky2_change_mtu,
.ndo_fix_features = sky2_fix_features,
.ndo_set_features = sky2_set_features,
@@ -4799,7 +4825,7 @@ static const char *sky2_name(u8 chipid, char *buf, int sz)
static int __devinit sky2_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- struct net_device *dev;
+ struct net_device *dev, *dev1;
struct sky2_hw *hw;
int err, using_dac = 0, wol_default;
u32 reg;
@@ -4925,33 +4951,26 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
- err = request_irq(pdev->irq, sky2_intr,
- (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
- hw->irq_name, hw);
- if (err) {
- dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
- goto err_out_unregister;
- }
- sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
- napi_enable(&hw->napi);
-
sky2_show_addr(dev);
if (hw->ports > 1) {
- struct net_device *dev1;
-
- err = -ENOMEM;
dev1 = sky2_init_netdev(hw, 1, using_dac, wol_default);
- if (dev1 && (err = register_netdev(dev1)) == 0)
- sky2_show_addr(dev1);
- else {
- dev_warn(&pdev->dev,
- "register of second port failed (%d)\n", err);
- hw->dev[1] = NULL;
- hw->ports = 1;
- if (dev1)
- free_netdev(dev1);
+ if (!dev1) {
+ err = -ENOMEM;
+ goto err_out_unregister;
}
+
+ err = register_netdev(dev1);
+ if (err) {
+ dev_err(&pdev->dev, "cannot register second net device\n");
+ goto err_out_free_dev1;
+ }
+
+ err = sky2_setup_irq(hw, hw->irq_name);
+ if (err)
+ goto err_out_unregister_dev1;
+
+ sky2_show_addr(dev1);
}
setup_timer(&hw->watchdog_timer, sky2_watchdog, (unsigned long) hw);
@@ -4962,6 +4981,10 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
return 0;
+err_out_unregister_dev1:
+ unregister_netdev(dev1);
+err_out_free_dev1:
+ free_netdev(dev1);
err_out_unregister:
if (hw->flags & SKY2_HW_USE_MSI)
pci_disable_msi(pdev);
@@ -5001,13 +5024,18 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
unregister_netdev(hw->dev[i]);
sky2_write32(hw, B0_IMSK, 0);
+ sky2_read32(hw, B0_IMSK);
sky2_power_aux(hw);
sky2_write8(hw, B0_CTST, CS_RST_SET);
sky2_read8(hw, B0_CTST);
- free_irq(pdev->irq, hw);
+ if (hw->ports > 1) {
+ napi_disable(&hw->napi);
+ free_irq(pdev->irq, hw);
+ }
+
if (hw->flags & SKY2_HW_USE_MSI)
pci_disable_msi(pdev);
pci_free_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le),
diff --git a/drivers/net/sky2.h b/drivers/net/ethernet/marvell/sky2.h
index 0af31b8b5f10..0af31b8b5f10 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/ethernet/marvell/sky2.h
diff --git a/drivers/net/ethernet/mellanox/Kconfig b/drivers/net/ethernet/mellanox/Kconfig
new file mode 100644
index 000000000000..d8099a7903d3
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/Kconfig
@@ -0,0 +1,23 @@
+#
+# Mellanox driver configuration
+#
+
+config NET_VENDOR_MELLANOX
+ bool "Mellanox devices"
+ default y
+ depends on PCI && INET
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Mellanox cards. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_MELLANOX
+
+source "drivers/net/ethernet/mellanox/mlx4/Kconfig"
+
+endif # NET_VENDOR_MELLANOX
diff --git a/drivers/net/ethernet/mellanox/Makefile b/drivers/net/ethernet/mellanox/Makefile
new file mode 100644
index 000000000000..37afb9683372
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Mellanox device drivers.
+#
+
+obj-$(CONFIG_MLX4_CORE) += mlx4/
diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig
new file mode 100644
index 000000000000..1bb93531f1ba
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig
@@ -0,0 +1,27 @@
+#
+# Mellanox driver configuration
+#
+
+config MLX4_EN
+ tristate "Mellanox Technologies 10Gbit Ethernet support"
+ depends on PCI && INET
+ select MLX4_CORE
+ select INET_LRO
+ ---help---
+ This driver supports Mellanox Technologies ConnectX Ethernet
+ devices.
+
+config MLX4_CORE
+ tristate
+ depends on PCI
+ default n
+
+config MLX4_DEBUG
+ bool "Verbose debugging output" if (MLX4_CORE && EXPERT)
+ depends on MLX4_CORE
+ default y
+ ---help---
+ This option causes debugging code to be compiled into the
+ mlx4_core driver. The output can be turned on via the
+ debug_level module parameter (which can also be set after
+ the driver is loaded through sysfs).
diff --git a/drivers/net/mlx4/Makefile b/drivers/net/ethernet/mellanox/mlx4/Makefile
index d1aa45a15854..d1aa45a15854 100644
--- a/drivers/net/mlx4/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx4/Makefile
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c
index 116cae334dad..116cae334dad 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c
diff --git a/drivers/net/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c
index 32f947154c33..32f947154c33 100644
--- a/drivers/net/mlx4/catas.c
+++ b/drivers/net/ethernet/mellanox/mlx4/catas.c
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 23cee7b6af91..23cee7b6af91 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
diff --git a/drivers/net/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c
index bd8ef9f2fa71..bd8ef9f2fa71 100644
--- a/drivers/net/mlx4/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cq.c
diff --git a/drivers/net/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
index ec4b6d047fe0..227997d775e8 100644
--- a/drivers/net/mlx4/en_cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
@@ -74,7 +74,8 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
return err;
}
-int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
+ int cq_idx)
{
struct mlx4_en_dev *mdev = priv->mdev;
int err = 0;
@@ -90,13 +91,15 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
if (cq->is_tx == RX) {
if (mdev->dev->caps.comp_pool) {
if (!cq->vector) {
- sprintf(name , "%s-rx-%d", priv->dev->name, cq->ring);
+ sprintf(name, "%s-%d", priv->dev->name,
+ cq->ring);
+ /* Set IRQ for specific name (per ring) */
if (mlx4_assign_eq(mdev->dev, name, &cq->vector)) {
- cq->vector = (cq->ring + 1 + priv->port) %
- mdev->dev->caps.num_comp_vectors;
+ cq->vector = (cq->ring + 1 + priv->port)
+ % mdev->dev->caps.num_comp_vectors;
mlx4_warn(mdev, "Failed Assigning an EQ to "
- "%s_rx-%d ,Falling back to legacy EQ's\n",
- priv->dev->name, cq->ring);
+ "%s ,Falling back to legacy EQ's\n",
+ name);
}
}
} else {
@@ -104,10 +107,13 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
mdev->dev->caps.num_comp_vectors;
}
} else {
- if (!cq->vector || !mdev->dev->caps.comp_pool) {
- /*Fallback to legacy pool in case of error*/
- cq->vector = 0;
- }
+ /* For TX we use the same irq per
+ ring we assigned for the RX */
+ struct mlx4_en_cq *rx_cq;
+
+ cq_idx = cq_idx % priv->rx_ring_num;
+ rx_cq = &priv->rx_cq[cq_idx];
+ cq->vector = rx_cq->vector;
}
if (!cq->is_tx)
@@ -133,14 +139,13 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
return 0;
}
-void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
- bool reserve_vectors)
+void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
{
struct mlx4_en_dev *mdev = priv->mdev;
mlx4_en_unmap_buffer(&cq->wqres.buf);
mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
- if (priv->mdev->dev->caps.comp_pool && cq->vector && !reserve_vectors)
+ if (priv->mdev->dev->caps.comp_pool && cq->vector)
mlx4_release_eq(priv->mdev->dev, cq->vector);
cq->buf_size = 0;
cq->buf = NULL;
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index eb096253d781..74e2a2a8a02b 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -342,13 +342,13 @@ 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;
- priv->last_moder_time = MLX4_EN_AUTO_CONF;
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;
@@ -394,6 +394,7 @@ 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;
@@ -416,7 +417,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
mlx4_en_stop_port(dev);
}
- mlx4_en_free_resources(priv, true);
+ mlx4_en_free_resources(priv);
priv->prof->tx_ring_size = tx_size;
priv->prof->rx_ring_size = rx_size;
@@ -432,6 +433,15 @@ 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;
+ }
+
out:
mutex_unlock(&mdev->state_lock);
return err;
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index 6bfea233a9f2..a06096fcc0b8 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -176,6 +176,7 @@ static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr)
flush_workqueue(mdev->workqueue);
destroy_workqueue(mdev->workqueue);
mlx4_mr_free(dev, &mdev->mr);
+ iounmap(mdev->uar_map);
mlx4_uar_free(dev, &mdev->priv_uar);
mlx4_pd_free(dev, mdev->priv_pdn);
kfree(mdev);
@@ -223,7 +224,7 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
MLX4_PERM_LOCAL_WRITE | MLX4_PERM_LOCAL_READ,
0, 0, &mdev->mr)) {
mlx4_err(mdev, "Failed allocating memory region\n");
- goto err_uar;
+ goto err_map;
}
if (mlx4_mr_enable(mdev->dev, &mdev->mr)) {
mlx4_err(mdev, "Failed enabling memory region\n");
@@ -282,6 +283,9 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
err_mr:
mlx4_mr_free(dev, &mdev->mr);
+err_map:
+ if (!mdev->uar_map)
+ iounmap(mdev->uar_map);
err_uar:
mlx4_uar_free(dev, &mdev->priv_uar);
err_pd:
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 4b0f32e568f8..78d776bc355c 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -415,6 +415,9 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
cq = &priv->rx_cq[i];
cq->moder_cnt = priv->rx_frames;
cq->moder_time = priv->rx_usecs;
+ priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
+ priv->last_moder_packets[i] = 0;
+ priv->last_moder_bytes[i] = 0;
}
for (i = 0; i < priv->tx_ring_num; i++) {
@@ -430,11 +433,8 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
priv->rx_usecs_high = MLX4_EN_RX_COAL_TIME_HIGH;
priv->sample_interval = MLX4_EN_SAMPLE_INTERVAL;
priv->adaptive_rx_coal = 1;
- priv->last_moder_time = MLX4_EN_AUTO_CONF;
priv->last_moder_jiffies = 0;
- priv->last_moder_packets = 0;
priv->last_moder_tx_packets = 0;
- priv->last_moder_bytes = 0;
}
static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
@@ -446,43 +446,30 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
unsigned long avg_pkt_size;
unsigned long rx_packets;
unsigned long rx_bytes;
- unsigned long tx_packets;
- unsigned long tx_pkt_diff;
unsigned long rx_pkt_diff;
int moder_time;
- int i, err;
+ int ring, err;
if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ)
return;
- spin_lock_bh(&priv->stats_lock);
- rx_packets = priv->stats.rx_packets;
- rx_bytes = priv->stats.rx_bytes;
- tx_packets = priv->stats.tx_packets;
- spin_unlock_bh(&priv->stats_lock);
-
- if (!priv->last_moder_jiffies || !period)
- goto out;
-
- tx_pkt_diff = ((unsigned long) (tx_packets -
- priv->last_moder_tx_packets));
- rx_pkt_diff = ((unsigned long) (rx_packets -
- priv->last_moder_packets));
- packets = max(tx_pkt_diff, rx_pkt_diff);
- rate = packets * HZ / period;
- avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
- priv->last_moder_bytes)) / packets : 0;
-
- /* Apply auto-moderation only when packet rate exceeds a rate that
- * it matters */
- if (rate > MLX4_EN_RX_RATE_THRESH && avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
- /* If tx and rx packet rates are not balanced, assume that
- * traffic is mainly BW bound and apply maximum moderation.
- * Otherwise, moderate according to packet rate */
- if (2 * tx_pkt_diff > 3 * rx_pkt_diff ||
- 2 * rx_pkt_diff > 3 * tx_pkt_diff) {
- moder_time = priv->rx_usecs_high;
- } else {
+ for (ring = 0; ring < priv->rx_ring_num; ring++) {
+ spin_lock_bh(&priv->stats_lock);
+ rx_packets = priv->rx_ring[ring].packets;
+ rx_bytes = priv->rx_ring[ring].bytes;
+ spin_unlock_bh(&priv->stats_lock);
+
+ rx_pkt_diff = ((unsigned long) (rx_packets -
+ priv->last_moder_packets[ring]));
+ packets = rx_pkt_diff;
+ rate = packets * HZ / period;
+ avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
+ priv->last_moder_bytes[ring])) / packets : 0;
+
+ /* Apply auto-moderation only when packet rate
+ * exceeds a rate that it matters */
+ if (rate > (MLX4_EN_RX_RATE_THRESH / priv->rx_ring_num) &&
+ avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
if (rate < priv->pkt_rate_low)
moder_time = priv->rx_usecs_low;
else if (rate > priv->pkt_rate_high)
@@ -492,36 +479,23 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
(priv->rx_usecs_high - priv->rx_usecs_low) /
(priv->pkt_rate_high - priv->pkt_rate_low) +
priv->rx_usecs_low;
+ } else {
+ moder_time = priv->rx_usecs_low;
}
- } else {
- moder_time = priv->rx_usecs_low;
- }
-
- en_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n",
- tx_pkt_diff * HZ / period, rx_pkt_diff * HZ / period);
- en_dbg(INTR, priv, "Rx moder_time changed from:%d to %d period:%lu "
- "[jiff] packets:%lu avg_pkt_size:%lu rate:%lu [p/s])\n",
- priv->last_moder_time, moder_time, period, packets,
- avg_pkt_size, rate);
-
- if (moder_time != priv->last_moder_time) {
- priv->last_moder_time = moder_time;
- for (i = 0; i < priv->rx_ring_num; i++) {
- cq = &priv->rx_cq[i];
+ if (moder_time != priv->last_moder_time[ring]) {
+ priv->last_moder_time[ring] = moder_time;
+ cq = &priv->rx_cq[ring];
cq->moder_time = moder_time;
err = mlx4_en_set_cq_moder(priv, cq);
- if (err) {
- en_err(priv, "Failed modifying moderation for cq:%d\n", i);
- break;
- }
+ if (err)
+ en_err(priv, "Failed modifying moderation "
+ "for cq:%d\n", ring);
}
+ priv->last_moder_packets[ring] = rx_packets;
+ priv->last_moder_bytes[ring] = rx_bytes;
}
-out:
- priv->last_moder_packets = rx_packets;
- priv->last_moder_tx_packets = tx_packets;
- priv->last_moder_bytes = rx_bytes;
priv->last_moder_jiffies = jiffies;
}
@@ -587,7 +561,6 @@ int mlx4_en_start_port(struct net_device *dev)
int i;
int j;
u8 mc_list[16] = {0};
- char name[32];
if (priv->port_up) {
en_dbg(DRV, priv, "start port called while port already up\n");
@@ -608,7 +581,7 @@ int mlx4_en_start_port(struct net_device *dev)
for (i = 0; i < priv->rx_ring_num; i++) {
cq = &priv->rx_cq[i];
- err = mlx4_en_activate_cq(priv, cq);
+ err = mlx4_en_activate_cq(priv, cq, i);
if (err) {
en_err(priv, "Failed activating Rx CQ\n");
goto cq_err;
@@ -642,20 +615,11 @@ int mlx4_en_start_port(struct net_device *dev)
goto mac_err;
}
- if (mdev->dev->caps.comp_pool && !priv->tx_vector) {
- sprintf(name , "%s-tx", priv->dev->name);
- if (mlx4_assign_eq(mdev->dev , name, &priv->tx_vector)) {
- mlx4_warn(mdev, "Failed Assigning an EQ to "
- "%s_tx ,Falling back to legacy "
- "EQ's\n", priv->dev->name);
- }
- }
/* Configure tx cq's and rings */
for (i = 0; i < priv->tx_ring_num; i++) {
/* Configure cq */
cq = &priv->tx_cq[i];
- cq->vector = priv->tx_vector;
- err = mlx4_en_activate_cq(priv, cq);
+ err = mlx4_en_activate_cq(priv, cq, i);
if (err) {
en_err(priv, "Failed allocating Tx CQ\n");
goto tx_err;
@@ -886,7 +850,7 @@ static int mlx4_en_close(struct net_device *dev)
return 0;
}
-void mlx4_en_free_resources(struct mlx4_en_priv *priv, bool reserve_vectors)
+void mlx4_en_free_resources(struct mlx4_en_priv *priv)
{
int i;
@@ -894,14 +858,14 @@ void mlx4_en_free_resources(struct mlx4_en_priv *priv, bool reserve_vectors)
if (priv->tx_ring[i].tx_info)
mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
if (priv->tx_cq[i].buf)
- mlx4_en_destroy_cq(priv, &priv->tx_cq[i], reserve_vectors);
+ mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
}
for (i = 0; i < priv->rx_ring_num; i++) {
if (priv->rx_ring[i].rx_info)
mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]);
if (priv->rx_cq[i].buf)
- mlx4_en_destroy_cq(priv, &priv->rx_cq[i], reserve_vectors);
+ mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
}
}
@@ -971,7 +935,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
mdev->pndev[priv->port] = NULL;
mutex_unlock(&mdev->state_lock);
- mlx4_en_free_resources(priv, false);
+ mlx4_en_free_resources(priv);
free_netdev(dev);
}
@@ -1016,7 +980,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
.ndo_start_xmit = mlx4_en_xmit,
.ndo_select_queue = mlx4_en_select_queue,
.ndo_get_stats = mlx4_en_get_stats,
- .ndo_set_multicast_list = mlx4_en_set_multicast,
+ .ndo_set_rx_mode = mlx4_en_set_multicast,
.ndo_set_mac_address = mlx4_en_set_mac,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = mlx4_en_change_mtu,
@@ -1120,7 +1084,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
dev->vlan_features = dev->hw_features;
- dev->hw_features |= NETIF_F_RXCSUM;
+ dev->hw_features |= NETIF_F_RXCSUM | NETIF_F_RXHASH;
dev->features = dev->hw_features | NETIF_F_HIGHDMA |
NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
@@ -1133,6 +1097,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
en_err(priv, "Netdev registration failed for port %d\n", port);
goto out;
}
+ priv->registered = 1;
en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
@@ -1154,7 +1119,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
en_err(priv, "Failed Initializing port\n");
goto out;
}
- priv->registered = 1;
mlx4_en_set_default_moderation(priv);
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
return 0;
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/ethernet/mellanox/mlx4/en_port.c
index 5ada5b469112..03c84cd78cde 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_port.c
@@ -128,7 +128,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
memset(context, 0, sizeof *context);
context->base_qpn = cpu_to_be32(base_qpn);
- context->n_mac = 0x2;
+ context->n_mac = dev->caps.log_num_macs;
context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT |
base_qpn);
context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT |
@@ -167,11 +167,21 @@ int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
/* This command is always accessed from Ethtool context
* already synchronized, no need in locking */
state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK);
- if ((qport_context->link_speed & MLX4_EN_SPEED_MASK) ==
- MLX4_EN_1G_SPEED)
+ switch (qport_context->link_speed & MLX4_EN_SPEED_MASK) {
+ case MLX4_EN_1G_SPEED:
state->link_speed = 1000;
- else
+ break;
+ case MLX4_EN_10G_SPEED_XAUI:
+ case MLX4_EN_10G_SPEED_XFI:
state->link_speed = 10000;
+ break;
+ case MLX4_EN_40G_SPEED:
+ state->link_speed = 40000;
+ break;
+ default:
+ state->link_speed = -1;
+ break;
+ }
state->transciver = qport_context->transceiver;
out:
@@ -204,15 +214,21 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
stats->rx_packets = 0;
stats->rx_bytes = 0;
+ priv->port_stats.rx_chksum_good = 0;
+ priv->port_stats.rx_chksum_none = 0;
for (i = 0; i < priv->rx_ring_num; i++) {
stats->rx_packets += priv->rx_ring[i].packets;
stats->rx_bytes += priv->rx_ring[i].bytes;
+ priv->port_stats.rx_chksum_good += priv->rx_ring[i].csum_ok;
+ priv->port_stats.rx_chksum_none += priv->rx_ring[i].csum_none;
}
stats->tx_packets = 0;
stats->tx_bytes = 0;
+ priv->port_stats.tx_chksum_offload = 0;
for (i = 0; i < priv->tx_ring_num; i++) {
stats->tx_packets += priv->tx_ring[i].packets;
stats->tx_bytes += priv->tx_ring[i].bytes;
+ priv->port_stats.tx_chksum_offload += priv->tx_ring[i].tx_csum;
}
stats->rx_errors = be64_to_cpu(mlx4_en_stats->PCS) +
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/ethernet/mellanox/mlx4/en_port.h
index e3d73e41c567..19eb244f5165 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/ethernet/mellanox/mlx4/en_port.h
@@ -94,6 +94,14 @@ enum {
MLX4_MCAST_ENABLE = 2,
};
+enum {
+ MLX4_EN_1G_SPEED = 0x02,
+ MLX4_EN_10G_SPEED_XFI = 0x01,
+ MLX4_EN_10G_SPEED_XAUI = 0x00,
+ MLX4_EN_40G_SPEED = 0x40,
+ MLX4_EN_OTHER_SPEED = 0x0f,
+};
+
struct mlx4_en_query_port_context {
u8 link_up;
#define MLX4_EN_LINK_UP_MASK 0x80
@@ -101,8 +109,7 @@ struct mlx4_en_query_port_context {
__be16 mtu;
u8 reserved2;
u8 link_speed;
-#define MLX4_EN_SPEED_MASK 0x3
-#define MLX4_EN_1G_SPEED 0x2
+#define MLX4_EN_SPEED_MASK 0x43
u16 reserved3[5];
__be64 mac;
u8 transceiver;
diff --git a/drivers/net/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
index 0dfb4ec8a9dd..0dfb4ec8a9dd 100644
--- a/drivers/net/mlx4/en_resources.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 37cc9e5c56be..b89c36dbf5b3 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -44,7 +44,7 @@
static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
struct mlx4_en_rx_desc *rx_desc,
- struct skb_frag_struct *skb_frags,
+ struct page_frag *skb_frags,
struct mlx4_en_rx_alloc *ring_alloc,
int i)
{
@@ -61,7 +61,7 @@ static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
return -ENOMEM;
skb_frags[i].page = page_alloc->page;
- skb_frags[i].page_offset = page_alloc->offset;
+ skb_frags[i].offset = page_alloc->offset;
page_alloc->page = page;
page_alloc->offset = frag_info->frag_align;
} else {
@@ -69,11 +69,11 @@ static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
get_page(page);
skb_frags[i].page = page;
- skb_frags[i].page_offset = page_alloc->offset;
+ skb_frags[i].offset = page_alloc->offset;
page_alloc->offset += frag_info->frag_stride;
}
dma = pci_map_single(mdev->pdev, page_address(skb_frags[i].page) +
- skb_frags[i].page_offset, frag_info->frag_size,
+ skb_frags[i].offset, frag_info->frag_size,
PCI_DMA_FROMDEVICE);
rx_desc->data[i].addr = cpu_to_be64(dma);
return 0;
@@ -135,7 +135,7 @@ static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv,
/* Set size and memtype fields */
for (i = 0; i < priv->num_frags; i++) {
- skb_frags[i].size = priv->frag_info[i].frag_size;
+ skb_frag_size_set(&skb_frags[i], priv->frag_info[i].frag_size);
rx_desc->data[i].byte_count =
cpu_to_be32(priv->frag_info[i].frag_size);
rx_desc->data[i].lkey = cpu_to_be32(priv->mdev->mr.key);
@@ -157,8 +157,8 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring *ring, int index)
{
struct mlx4_en_rx_desc *rx_desc = ring->buf + (index * ring->stride);
- struct skb_frag_struct *skb_frags = ring->rx_info +
- (index << priv->log_rx_info);
+ struct page_frag *skb_frags = ring->rx_info +
+ (index << priv->log_rx_info);
int i;
for (i = 0; i < priv->num_frags; i++)
@@ -183,7 +183,7 @@ static void mlx4_en_free_rx_desc(struct mlx4_en_priv *priv,
int index)
{
struct mlx4_en_dev *mdev = priv->mdev;
- struct skb_frag_struct *skb_frags;
+ struct page_frag *skb_frags;
struct mlx4_en_rx_desc *rx_desc = ring->buf + (index << ring->log_stride);
dma_addr_t dma;
int nr;
@@ -403,11 +403,12 @@ void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
/* Unmap a completed descriptor and free unused pages */
static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
struct mlx4_en_rx_desc *rx_desc,
- struct skb_frag_struct *skb_frags,
- struct skb_frag_struct *skb_frags_rx,
+ struct page_frag *skb_frags,
+ struct sk_buff *skb,
struct mlx4_en_rx_alloc *page_alloc,
int length)
{
+ struct skb_frag_struct *skb_frags_rx = skb_shinfo(skb)->frags;
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_en_frag_info *frag_info;
int nr;
@@ -420,9 +421,10 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
break;
/* Save page reference in skb */
- skb_frags_rx[nr].page = skb_frags[nr].page;
- skb_frags_rx[nr].size = skb_frags[nr].size;
- skb_frags_rx[nr].page_offset = skb_frags[nr].page_offset;
+ __skb_frag_set_page(&skb_frags_rx[nr], skb_frags[nr].page);
+ skb_frag_size_set(&skb_frags_rx[nr], skb_frags[nr].size);
+ skb_frags_rx[nr].page_offset = skb_frags[nr].offset;
+ skb->truesize += frag_info->frag_stride;
dma = be64_to_cpu(rx_desc->data[nr].addr);
/* Allocate a replacement page */
@@ -430,13 +432,13 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
goto fail;
/* Unmap buffer */
- pci_unmap_single(mdev->pdev, dma, skb_frags_rx[nr].size,
+ pci_unmap_single(mdev->pdev, dma, skb_frag_size(&skb_frags_rx[nr]),
PCI_DMA_FROMDEVICE);
}
/* Adjust size of last fragment to match actual length */
if (nr > 0)
- skb_frags_rx[nr - 1].size = length -
- priv->frag_info[nr - 1].frag_prefix_size;
+ skb_frag_size_set(&skb_frags_rx[nr - 1],
+ length - priv->frag_info[nr - 1].frag_prefix_size);
return nr;
fail:
@@ -444,7 +446,7 @@ fail:
* the descriptor) of this packet; remaining fragments are reused... */
while (nr > 0) {
nr--;
- put_page(skb_frags_rx[nr].page);
+ __skb_frag_unref(&skb_frags_rx[nr]);
}
return 0;
}
@@ -452,7 +454,7 @@ fail:
static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
struct mlx4_en_rx_desc *rx_desc,
- struct skb_frag_struct *skb_frags,
+ struct page_frag *skb_frags,
struct mlx4_en_rx_alloc *page_alloc,
unsigned int length)
{
@@ -470,11 +472,10 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
skb->dev = priv->dev;
skb_reserve(skb, NET_IP_ALIGN);
skb->len = length;
- skb->truesize = length + sizeof(struct sk_buff);
/* Get pointer to first fragment so we could copy the headers into the
* (linear part of the) skb */
- va = page_address(skb_frags[0].page) + skb_frags[0].page_offset;
+ va = page_address(skb_frags[0].page) + skb_frags[0].offset;
if (length <= SMALL_PACKET_SIZE) {
/* We are copying all relevant data to the skb - temporarily
@@ -490,8 +491,7 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
/* Move relevant fragments to skb */
used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags,
- skb_shinfo(skb)->frags,
- page_alloc, length);
+ skb, page_alloc, length);
if (unlikely(!used_frags)) {
kfree_skb(skb);
return NULL;
@@ -506,7 +506,7 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
skb_shinfo(skb)->frags[0].page_offset += HEADER_COPY_SIZE;
/* Adjust size of first fragment */
- skb_shinfo(skb)->frags[0].size -= HEADER_COPY_SIZE;
+ skb_frag_size_sub(&skb_shinfo(skb)->frags[0], HEADER_COPY_SIZE);
skb->data_len = length - HEADER_COPY_SIZE;
}
return skb;
@@ -533,7 +533,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_cqe *cqe;
struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
- struct skb_frag_struct *skb_frags;
+ struct page_frag *skb_frags;
struct mlx4_en_rx_desc *rx_desc;
struct sk_buff *skb;
int index;
@@ -587,7 +587,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
if (likely(dev->features & NETIF_F_RXCSUM)) {
if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
(cqe->checksum == cpu_to_be16(0xffff))) {
- priv->port_stats.rx_chksum_good++;
+ ring->csum_ok++;
/* This packet is eligible for LRO if it is:
* - DIX Ethernet (type interpretation)
* - TCP/IP (v4)
@@ -600,7 +600,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
nr = mlx4_en_complete_rx_desc(
priv, rx_desc,
- skb_frags, skb_shinfo(gro_skb)->frags,
+ skb_frags, gro_skb,
ring->page_alloc, length);
if (!nr)
goto next;
@@ -608,7 +608,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
skb_shinfo(gro_skb)->nr_frags = nr;
gro_skb->len = length;
gro_skb->data_len = length;
- gro_skb->truesize += length;
gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
if (cqe->vlan_my_qpn &
@@ -618,6 +617,10 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
__vlan_hwaccel_put_tag(gro_skb, vid);
}
+ if (dev->features & NETIF_F_RXHASH)
+ gro_skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid);
+
+ skb_record_rx_queue(gro_skb, cq->ring);
napi_gro_frags(&cq->napi);
goto next;
@@ -627,11 +630,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
ip_summed = CHECKSUM_UNNECESSARY;
} else {
ip_summed = CHECKSUM_NONE;
- priv->port_stats.rx_chksum_none++;
+ ring->csum_none++;
}
} else {
ip_summed = CHECKSUM_NONE;
- priv->port_stats.rx_chksum_none++;
+ ring->csum_none++;
}
skb = mlx4_en_rx_skb(priv, rx_desc, skb_frags,
@@ -650,6 +653,9 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
skb->protocol = eth_type_trans(skb, dev);
skb_record_rx_queue(skb, cq->ring);
+ if (dev->features & NETIF_F_RXHASH)
+ skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid);
+
if (be32_to_cpu(cqe->vlan_my_qpn) &
MLX4_CQE_VLAN_PRESENT_MASK)
__vlan_hwaccel_put_tag(skb, be16_to_cpu(cqe->sl_vid));
@@ -806,6 +812,10 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
qpn, ring->cqn, context);
context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
+ /* Cancel FCS removal if FW allows */
+ if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP)
+ context->param3 |= cpu_to_be32(1 << 29);
+
err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, context, qp, state);
if (err) {
mlx4_qp_remove(mdev->dev, qp);
@@ -829,6 +839,9 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
int i, qpn;
int err = 0;
int good_qps = 0;
+ static const u32 rsskey[10] = { 0xD181C62C, 0xF7F4DB5B, 0x1983A2FC,
+ 0x943E1ADB, 0xD9389E6B, 0xD1039C2C, 0xA74499AD,
+ 0x593D56D9, 0xF3253C06, 0x2ADC1FFC};
en_dbg(DRV, priv, "Configuring rss steering\n");
err = mlx4_qp_reserve_range(mdev->dev, priv->rx_ring_num,
@@ -866,6 +879,9 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
(rss_map->base_qpn));
rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
rss_context->flags = rss_mask;
+ rss_context->hash_fn = 1;
+ for (i = 0; i < 10; i++)
+ rss_context->rss_key[i] = rsskey[i];
if (priv->mdev->profile.udp_rss)
rss_context->base_qpn_udp = rss_context->default_qpn;
diff --git a/drivers/net/mlx4/en_selftest.c b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
index 9fdbcecd499d..9fdbcecd499d 100644
--- a/drivers/net/mlx4/en_selftest.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index f76ab6bf3096..90f2cd24faac 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -226,7 +226,7 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
frag = &skb_shinfo(skb)->frags[i];
pci_unmap_page(mdev->pdev,
(dma_addr_t) be64_to_cpu(data[i].addr),
- frag->size, PCI_DMA_TODEVICE);
+ skb_frag_size(frag), PCI_DMA_TODEVICE);
}
}
/* Stamp the freed descriptor */
@@ -256,7 +256,7 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
frag = &skb_shinfo(skb)->frags[i];
pci_unmap_page(mdev->pdev,
(dma_addr_t) be64_to_cpu(data->addr),
- frag->size, PCI_DMA_TODEVICE);
+ skb_frag_size(frag), PCI_DMA_TODEVICE);
++data;
}
}
@@ -460,26 +460,13 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
}
}
-static void *get_frag_ptr(struct sk_buff *skb)
-{
- struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
- struct page *page = frag->page;
- void *ptr;
-
- ptr = page_address(page);
- if (unlikely(!ptr))
- return NULL;
-
- return ptr + frag->page_offset;
-}
-
static int is_inline(struct sk_buff *skb, void **pfrag)
{
void *ptr;
if (inline_thold && !skb_is_gso(skb) && skb->len <= inline_thold) {
if (skb_shinfo(skb)->nr_frags == 1) {
- ptr = get_frag_ptr(skb);
+ ptr = skb_frag_address_safe(&skb_shinfo(skb)->frags[0]);
if (unlikely(!ptr))
return 0;
@@ -550,7 +537,7 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
skb_copy_from_linear_data(skb, inl + 1, skb_headlen(skb));
if (skb_shinfo(skb)->nr_frags)
memcpy(((void *)(inl + 1)) + skb_headlen(skb), fragptr,
- skb_shinfo(skb)->frags[0].size);
+ skb_frag_size(&skb_shinfo(skb)->frags[0]));
} else {
inl->byte_count = cpu_to_be32(1 << 31 | spc);
@@ -570,7 +557,7 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
skb_headlen(skb) - spc);
if (skb_shinfo(skb)->nr_frags)
memcpy(((void *)(inl + 1)) + skb_headlen(skb) - spc,
- fragptr, skb_shinfo(skb)->frags[0].size);
+ fragptr, skb_frag_size(&skb_shinfo(skb)->frags[0]));
}
wmb();
@@ -695,7 +682,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM |
MLX4_WQE_CTRL_TCP_UDP_CSUM);
- priv->port_stats.tx_chksum_offload++;
+ ring->tx_csum++;
}
if (unlikely(priv->validate_loopback)) {
@@ -756,12 +743,13 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
/* Map fragments */
for (i = skb_shinfo(skb)->nr_frags - 1; i >= 0; i--) {
frag = &skb_shinfo(skb)->frags[i];
- dma = pci_map_page(mdev->dev->pdev, frag->page, frag->page_offset,
- frag->size, PCI_DMA_TODEVICE);
+ dma = skb_frag_dma_map(&mdev->dev->pdev->dev, frag,
+ 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
data->addr = cpu_to_be64(dma);
data->lkey = cpu_to_be32(mdev->mr.key);
wmb();
- data->byte_count = cpu_to_be32(frag->size);
+ data->byte_count = cpu_to_be32(skb_frag_size(frag));
--data;
}
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 1ad1f6029af8..869a2c220a7b 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -484,7 +484,7 @@ static void mlx4_free_eq(struct mlx4_dev *dev,
mlx4_mtt_cleanup(dev, &eq->mtt);
for (i = 0; i < npages; ++i)
- pci_free_consistent(dev->pdev, PAGE_SIZE,
+ dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
eq->page_list[i].buf,
eq->page_list[i].map);
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 7eb8ba822e97..abdfbacab4a6 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -101,6 +101,7 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
[25] = "Router support",
[30] = "IBoE support",
[32] = "Unicast loopback support",
+ [34] = "FCS header control",
[38] = "Wake On LAN support",
[40] = "UDP RSS support",
[41] = "Unicast VEP steering support",
@@ -204,6 +205,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_MCG_OFFSET 0x63
#define QUERY_DEV_CAP_RSVD_PD_OFFSET 0x64
#define QUERY_DEV_CAP_MAX_PD_OFFSET 0x65
+#define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66
+#define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67
#define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82
@@ -318,6 +321,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->reserved_pds = field >> 4;
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET);
dev_cap->max_pds = 1 << (field & 0x3f);
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_XRC_OFFSET);
+ dev_cap->reserved_xrcds = field >> 4;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET);
+ dev_cap->max_xrcds = 1 << (field & 0x1f);
MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET);
dev_cap->rdmarc_entry_sz = size;
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h
index 1e8ecc3708e2..bf5ec2286528 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.h
@@ -93,6 +93,8 @@ struct mlx4_dev_cap {
int max_mcgs;
int reserved_pds;
int max_pds;
+ int reserved_xrcds;
+ int max_xrcds;
int qpc_entry_sz;
int rdmarc_entry_sz;
int altc_entry_sz;
diff --git a/drivers/net/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c
index 02393fdf44c1..02393fdf44c1 100644
--- a/drivers/net/mlx4/icm.c
+++ b/drivers/net/ethernet/mellanox/mlx4/icm.c
diff --git a/drivers/net/mlx4/icm.h b/drivers/net/ethernet/mellanox/mlx4/icm.h
index b10c07a1dc1a..b10c07a1dc1a 100644
--- a/drivers/net/mlx4/icm.h
+++ b/drivers/net/ethernet/mellanox/mlx4/icm.h
diff --git a/drivers/net/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c
index 73c94fcdfddf..73c94fcdfddf 100644
--- a/drivers/net/mlx4/intf.c
+++ b/drivers/net/ethernet/mellanox/mlx4/intf.c
diff --git a/drivers/net/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index f0ee35df4dd7..94bbc85a532d 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -96,6 +96,8 @@ MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)");
static int log_num_vlan;
module_param_named(log_num_vlan, log_num_vlan, int, 0444);
MODULE_PARM_DESC(log_num_vlan, "Log2 max number of VLANs per ETH port (0-7)");
+/* Log2 max number of VLANs per ETH port (0-7) */
+#define MLX4_LOG_NUM_VLANS 7
static int use_prio;
module_param_named(use_prio, use_prio, bool, 0444);
@@ -220,6 +222,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.reserved_mrws = dev_cap->reserved_mrws;
dev->caps.reserved_uars = dev_cap->reserved_uars;
dev->caps.reserved_pds = dev_cap->reserved_pds;
+ dev->caps.reserved_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
+ dev_cap->reserved_xrcds : 0;
+ dev->caps.max_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
+ dev_cap->max_xrcds : 0;
dev->caps.mtt_entry_sz = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz;
dev->caps.max_msg_sz = dev_cap->max_msg_sz;
dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1);
@@ -230,7 +236,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
dev->caps.log_num_macs = log_num_mac;
- dev->caps.log_num_vlans = log_num_vlan;
+ dev->caps.log_num_vlans = MLX4_LOG_NUM_VLANS;
dev->caps.log_num_prios = use_prio ? 3 : 0;
for (i = 1; i <= dev->caps.num_ports; ++i) {
@@ -912,11 +918,18 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
goto err_kar_unmap;
}
+ err = mlx4_init_xrcd_table(dev);
+ if (err) {
+ mlx4_err(dev, "Failed to initialize "
+ "reliable connection domain table, aborting.\n");
+ goto err_pd_table_free;
+ }
+
err = mlx4_init_mr_table(dev);
if (err) {
mlx4_err(dev, "Failed to initialize "
"memory region table, aborting.\n");
- goto err_pd_table_free;
+ goto err_xrcd_table_free;
}
err = mlx4_init_eq_table(dev);
@@ -998,6 +1011,13 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
"ib capabilities (%d). Continuing with "
"caps = 0\n", port, err);
dev->caps.ib_port_def_cap[port] = ib_port_default_caps;
+
+ err = mlx4_check_ext_port_caps(dev, port);
+ if (err)
+ mlx4_warn(dev, "failed to get port %d extended "
+ "port capabilities support info (%d)."
+ " Assuming not supported\n", port, err);
+
err = mlx4_SET_PORT(dev, port);
if (err) {
mlx4_err(dev, "Failed to set port %d, aborting\n",
@@ -1033,6 +1053,9 @@ err_eq_table_free:
err_mr_table_free:
mlx4_cleanup_mr_table(dev);
+err_xrcd_table_free:
+ mlx4_cleanup_xrcd_table(dev);
+
err_pd_table_free:
mlx4_cleanup_pd_table(dev);
@@ -1355,6 +1378,7 @@ err_port:
mlx4_cmd_use_polling(dev);
mlx4_cleanup_eq_table(dev);
mlx4_cleanup_mr_table(dev);
+ mlx4_cleanup_xrcd_table(dev);
mlx4_cleanup_pd_table(dev);
mlx4_cleanup_uar_table(dev);
@@ -1416,6 +1440,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
mlx4_cmd_use_polling(dev);
mlx4_cleanup_eq_table(dev);
mlx4_cleanup_mr_table(dev);
+ mlx4_cleanup_xrcd_table(dev);
mlx4_cleanup_pd_table(dev);
iounmap(priv->kar);
@@ -1489,10 +1514,9 @@ static int __init mlx4_verify_params(void)
return -1;
}
- if ((log_num_vlan < 0) || (log_num_vlan > 7)) {
- pr_warning("mlx4_core: bad num_vlan: %d\n", log_num_vlan);
- return -1;
- }
+ if (log_num_vlan != 0)
+ pr_warning("mlx4_core: log_num_vlan - obsolete module param, using %d\n",
+ MLX4_LOG_NUM_VLANS);
if ((log_mtts_per_seg < 1) || (log_mtts_per_seg > 7)) {
pr_warning("mlx4_core: bad log_mtts_per_seg: %d\n", log_mtts_per_seg);
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index cd1784593a3c..cd1784593a3c 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index a2fcd8402d37..5dfa68ffc11c 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -335,6 +335,7 @@ struct mlx4_priv {
struct mlx4_cmd cmd;
struct mlx4_bitmap pd_bitmap;
+ struct mlx4_bitmap xrcd_bitmap;
struct mlx4_uar_table uar_table;
struct mlx4_mr_table mr_table;
struct mlx4_cq_table cq_table;
@@ -384,6 +385,7 @@ int mlx4_alloc_eq_table(struct mlx4_dev *dev);
void mlx4_free_eq_table(struct mlx4_dev *dev);
int mlx4_init_pd_table(struct mlx4_dev *dev);
+int mlx4_init_xrcd_table(struct mlx4_dev *dev);
int mlx4_init_uar_table(struct mlx4_dev *dev);
int mlx4_init_mr_table(struct mlx4_dev *dev);
int mlx4_init_eq_table(struct mlx4_dev *dev);
@@ -393,6 +395,7 @@ int mlx4_init_srq_table(struct mlx4_dev *dev);
int mlx4_init_mcg_table(struct mlx4_dev *dev);
void mlx4_cleanup_pd_table(struct mlx4_dev *dev);
+void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev);
void mlx4_cleanup_uar_table(struct mlx4_dev *dev);
void mlx4_cleanup_mr_table(struct mlx4_dev *dev);
void mlx4_cleanup_eq_table(struct mlx4_dev *dev);
@@ -450,6 +453,7 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port);
int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps);
+int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port);
int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
enum mlx4_protocol prot, enum mlx4_steer_type steer);
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index ed84811766e6..8fda331c65df 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -51,8 +51,8 @@
#include "en_port.h"
#define DRV_NAME "mlx4_en"
-#define DRV_VERSION "1.5.4.1"
-#define DRV_RELDATE "March 2011"
+#define DRV_VERSION "1.5.4.2"
+#define DRV_RELDATE "October 2011"
#define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
@@ -249,6 +249,7 @@ struct mlx4_en_tx_ring {
struct mlx4_srq dummy;
unsigned long bytes;
unsigned long packets;
+ unsigned long tx_csum;
spinlock_t comp_lock;
struct mlx4_bf bf;
bool bf_enabled;
@@ -275,6 +276,8 @@ struct mlx4_en_rx_ring {
void *rx_info;
unsigned long bytes;
unsigned long packets;
+ unsigned long csum_ok;
+ unsigned long csum_none;
};
@@ -426,11 +429,11 @@ struct mlx4_en_priv {
struct mlx4_en_port_state port_state;
spinlock_t stats_lock;
- unsigned long last_moder_packets;
+ unsigned long last_moder_packets[MAX_RX_RINGS];
unsigned long last_moder_tx_packets;
- unsigned long last_moder_bytes;
+ unsigned long last_moder_bytes[MAX_RX_RINGS];
unsigned long last_moder_jiffies;
- int last_moder_time;
+ int last_moder_time[MAX_RX_RINGS];
u16 rx_usecs;
u16 rx_frames;
u16 tx_usecs;
@@ -470,7 +473,6 @@ struct mlx4_en_priv {
u16 log_rx_info;
struct mlx4_en_tx_ring tx_ring[MAX_TX_RINGS];
- int tx_vector;
struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS];
struct mlx4_en_cq tx_cq[MAX_TX_RINGS];
struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
@@ -503,14 +505,14 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
int mlx4_en_start_port(struct net_device *dev);
void mlx4_en_stop_port(struct net_device *dev);
-void mlx4_en_free_resources(struct mlx4_en_priv *priv, bool reserve_vectors);
+void mlx4_en_free_resources(struct mlx4_en_priv *priv);
int mlx4_en_alloc_resources(struct mlx4_en_priv *priv);
int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
int entries, int ring, enum cq_type mode);
-void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
- bool reserve_vectors);
-int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
+void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
+int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
+ int cq_idx);
void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
@@ -579,8 +581,9 @@ extern const struct ethtool_ops mlx4_en_ethtool_ops;
* printk / logging functions
*/
+__printf(3, 4)
int en_print(const char *level, const struct mlx4_en_priv *priv,
- const char *format, ...) __attribute__ ((format (printf, 3, 4)));
+ const char *format, ...);
#define en_dbg(mlevel, priv, format, arg...) \
do { \
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c
index 9c188bdd7f4f..ab639cfef78e 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mr.c
@@ -139,7 +139,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
GFP_KERNEL);
- buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+ buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free,
GFP_KERNEL);
if (!buddy->bits || !buddy->num_free)
goto err_out;
diff --git a/drivers/net/mlx4/pd.c b/drivers/net/ethernet/mellanox/mlx4/pd.c
index 1286b886dcea..3736163e30e9 100644
--- a/drivers/net/mlx4/pd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/pd.c
@@ -61,6 +61,24 @@ void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn)
}
EXPORT_SYMBOL_GPL(mlx4_pd_free);
+int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ *xrcdn = mlx4_bitmap_alloc(&priv->xrcd_bitmap);
+ if (*xrcdn == -1)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc);
+
+void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
+{
+ mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn);
+}
+EXPORT_SYMBOL_GPL(mlx4_xrcd_free);
+
int mlx4_init_pd_table(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -74,6 +92,18 @@ void mlx4_cleanup_pd_table(struct mlx4_dev *dev)
mlx4_bitmap_cleanup(&mlx4_priv(dev)->pd_bitmap);
}
+int mlx4_init_xrcd_table(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ return mlx4_bitmap_init(&priv->xrcd_bitmap, (1 << 16),
+ (1 << 16) - 1, dev->caps.reserved_xrcds + 1, 0);
+}
+
+void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev)
+{
+ mlx4_bitmap_cleanup(&mlx4_priv(dev)->xrcd_bitmap);
+}
int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar)
{
diff --git a/drivers/net/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index 609e0ec14cee..a44f080fdfe5 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -65,7 +65,7 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
table->entries[i] = 0;
table->refs[i] = 0;
}
- table->max = 1 << dev->caps.log_num_vlans;
+ table->max = (1 << dev->caps.log_num_vlans) - MLX4_VLAN_REGULAR;
table->total = 0;
}
@@ -148,22 +148,26 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap)
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
err = mlx4_uc_steer_add(dev, port, mac, qpn, 1);
- if (!err) {
- entry = kmalloc(sizeof *entry, GFP_KERNEL);
- if (!entry) {
- mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
- return -ENOMEM;
- }
- entry->mac = mac;
- err = radix_tree_insert(&info->mac_tree, *qpn, entry);
- if (err) {
- mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
- return err;
- }
- } else
+ if (err)
return err;
+
+ entry = kmalloc(sizeof *entry, GFP_KERNEL);
+ if (!entry) {
+ mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
+ return -ENOMEM;
+ }
+
+ entry->mac = mac;
+ err = radix_tree_insert(&info->mac_tree, *qpn, entry);
+ if (err) {
+ kfree(entry);
+ mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
+ return err;
+ }
}
+
mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
+
mutex_lock(&table->mutex);
for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) {
if (free < 0 && !table->refs[i]) {
@@ -354,6 +358,13 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
int free = -1;
mutex_lock(&table->mutex);
+
+ if (table->total == table->max) {
+ /* No free vlan entries */
+ err = -ENOSPC;
+ goto out;
+ }
+
for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) {
if (free < 0 && (table->refs[i] == 0)) {
free = i;
@@ -375,12 +386,6 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
goto out;
}
- if (table->total == table->max) {
- /* No free vlan entries */
- err = -ENOSPC;
- goto out;
- }
-
/* Register new MAC */
table->refs[free] = 1;
table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID);
@@ -464,6 +469,48 @@ int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps)
return err;
}
+int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port)
+{
+ struct mlx4_cmd_mailbox *inmailbox, *outmailbox;
+ u8 *inbuf, *outbuf;
+ int err, packet_error;
+
+ inmailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(inmailbox))
+ return PTR_ERR(inmailbox);
+
+ outmailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(outmailbox)) {
+ mlx4_free_cmd_mailbox(dev, inmailbox);
+ return PTR_ERR(outmailbox);
+ }
+
+ inbuf = inmailbox->buf;
+ outbuf = outmailbox->buf;
+ memset(inbuf, 0, 256);
+ memset(outbuf, 0, 256);
+ inbuf[0] = 1;
+ inbuf[1] = 1;
+ inbuf[2] = 1;
+ inbuf[3] = 1;
+
+ *(__be16 *) (&inbuf[16]) = MLX4_ATTR_EXTENDED_PORT_INFO;
+ *(__be32 *) (&inbuf[20]) = cpu_to_be32(port);
+
+ err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3,
+ MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C);
+
+ packet_error = be16_to_cpu(*(__be16 *) (outbuf + 4));
+
+ dev->caps.ext_port_cap[port] = (!err && !packet_error) ?
+ MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO
+ : 0;
+
+ mlx4_free_cmd_mailbox(dev, inmailbox);
+ mlx4_free_cmd_mailbox(dev, outmailbox);
+ return err;
+}
+
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
{
struct mlx4_cmd_mailbox *mailbox;
diff --git a/drivers/net/mlx4/profile.c b/drivers/net/ethernet/mellanox/mlx4/profile.c
index b967647d0c76..b967647d0c76 100644
--- a/drivers/net/mlx4/profile.c
+++ b/drivers/net/ethernet/mellanox/mlx4/profile.c
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index ec9350e5f21a..51c53898c35f 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -280,6 +280,9 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
* We reserve 2 extra QPs per port for the special QPs. The
* block of special QPs must be aligned to a multiple of 8, so
* round up.
+ *
+ * We also reserve the MSB of the 24-bit QP number to indicate
+ * that a QP is an XRC QP.
*/
dev->caps.sqp_start =
ALIGN(dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], 8);
diff --git a/drivers/net/mlx4/reset.c b/drivers/net/ethernet/mellanox/mlx4/reset.c
index 11e7c1cb99bf..11e7c1cb99bf 100644
--- a/drivers/net/mlx4/reset.c
+++ b/drivers/net/ethernet/mellanox/mlx4/reset.c
diff --git a/drivers/net/mlx4/sense.c b/drivers/net/ethernet/mellanox/mlx4/sense.c
index e2337a7411d9..e2337a7411d9 100644
--- a/drivers/net/mlx4/sense.c
+++ b/drivers/net/ethernet/mellanox/mlx4/sense.c
diff --git a/drivers/net/mlx4/srq.c b/drivers/net/ethernet/mellanox/mlx4/srq.c
index 3b07b80a0456..a20b141dbb5c 100644
--- a/drivers/net/mlx4/srq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/srq.c
@@ -40,20 +40,20 @@
struct mlx4_srq_context {
__be32 state_logsize_srqn;
u8 logstride;
- u8 reserved1[3];
- u8 pg_offset;
- u8 reserved2[3];
- u32 reserved3;
+ u8 reserved1;
+ __be16 xrcd;
+ __be32 pg_offset_cqn;
+ u32 reserved2;
u8 log_page_size;
- u8 reserved4[2];
+ u8 reserved3[2];
u8 mtt_base_addr_h;
__be32 mtt_base_addr_l;
__be32 pd;
__be16 limit_watermark;
__be16 wqe_cnt;
- u16 reserved5;
+ u16 reserved4;
__be16 wqe_counter;
- u32 reserved6;
+ u32 reserved5;
__be64 db_rec_addr;
};
@@ -109,8 +109,8 @@ static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
MLX4_CMD_TIME_CLASS_A);
}
-int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
- u64 db_rec, struct mlx4_srq *srq)
+int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
+ struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq)
{
struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
struct mlx4_cmd_mailbox *mailbox;
@@ -148,6 +148,8 @@ int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
srq_context->state_logsize_srqn = cpu_to_be32((ilog2(srq->max) << 24) |
srq->srqn);
srq_context->logstride = srq->wqe_shift - 4;
+ srq_context->xrcd = cpu_to_be16(xrcd);
+ srq_context->pg_offset_cqn = cpu_to_be32(cqn & 0xffffff);
srq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
mtt_addr = mlx4_mtt_addr(dev, mtt);
diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig
new file mode 100644
index 000000000000..d10c2e15f4ed
--- /dev/null
+++ b/drivers/net/ethernet/micrel/Kconfig
@@ -0,0 +1,69 @@
+#
+# Micrel device configuration
+#
+
+config NET_VENDOR_MICREL
+ bool "Micrel devices"
+ default y
+ depends on (HAS_IOMEM && DMA_ENGINE) || SPI || PCI || HAS_IOMEM || \
+ (ARM && ARCH_KS8695)
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Micrel devices. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_MICREL
+
+config ARM_KS8695_ETHER
+ tristate "KS8695 Ethernet support"
+ depends on ARM && ARCH_KS8695
+ select NET_CORE
+ select MII
+ ---help---
+ If you wish to compile a kernel for the KS8695 and want to
+ use the internal ethernet then you should answer Y to this.
+
+config KS8842
+ tristate "Micrel KSZ8841/42 with generic bus interface"
+ depends on HAS_IOMEM && DMA_ENGINE
+ ---help---
+ This platform driver is for KSZ8841(1-port) / KS8842(2-port)
+ ethernet switch chip (managed, VLAN, QoS) from Micrel or
+ Timberdale(FPGA).
+
+config KS8851
+ tristate "Micrel KS8851 SPI"
+ depends on SPI
+ select NET_CORE
+ select MII
+ select CRC32
+ ---help---
+ SPI driver for Micrel KS8851 SPI attached network chip.
+
+config KS8851_MLL
+ tristate "Micrel KS8851 MLL"
+ depends on HAS_IOMEM
+ select NET_CORE
+ select MII
+ ---help---
+ This platform driver is for Micrel KS8851 Address/data bus
+ multiplexed network chip.
+
+config KSZ884X_PCI
+ tristate "Micrel KSZ8841/2 PCI"
+ depends on PCI
+ select NET_CORE
+ select MII
+ select CRC32
+ ---help---
+ This PCI driver is for Micrel KSZ8841/KSZ8842 PCI Ethernet chip.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ksz884x.
+
+endif # NET_VENDOR_MICREL
diff --git a/drivers/net/ethernet/micrel/Makefile b/drivers/net/ethernet/micrel/Makefile
new file mode 100644
index 000000000000..c83e4bc50c73
--- /dev/null
+++ b/drivers/net/ethernet/micrel/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the Micrel network device drivers.
+#
+
+obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
+obj-$(CONFIG_KS8842) += ks8842.o
+obj-$(CONFIG_KS8851) += ks8851.o
+obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
+obj-$(CONFIG_KSZ884X_PCI) += ksz884x.o
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
index c827a6097d02..ab81c0dc96e2 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/ethernet/micrel/ks8695net.c
@@ -414,7 +414,7 @@ ks8695_tx_irq(int irq, void *dev_id)
* Interrupt Status Register (Offset 0xF208)
* Bit29: WAN MAC Receive Status
* Bit16: LAN MAC Receive Status
- * So, this Rx interrrupt enable/status bit number is equal
+ * So, this Rx interrupt enable/status bit number is equal
* as Rx IRQ number.
*/
static inline u32 ks8695_get_rx_enable_bit(struct ks8695_priv *ksp)
@@ -1333,7 +1333,7 @@ static const struct net_device_ops ks8695_netdev_ops = {
.ndo_tx_timeout = ks8695_timeout,
.ndo_set_mac_address = ks8695_set_mac,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = ks8695_set_multicast,
+ .ndo_set_rx_mode = ks8695_set_multicast,
};
/**
diff --git a/drivers/net/arm/ks8695net.h b/drivers/net/ethernet/micrel/ks8695net.h
index 80eff6ea5163..80eff6ea5163 100644
--- a/drivers/net/arm/ks8695net.h
+++ b/drivers/net/ethernet/micrel/ks8695net.h
diff --git a/drivers/net/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index 4a6ae057e3b1..4a6ae057e3b1 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
diff --git a/drivers/net/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index f56743a28fc0..f56743a28fc0 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
diff --git a/drivers/net/ks8851.h b/drivers/net/ethernet/micrel/ks8851.h
index 537fb06e5932..537fb06e5932 100644
--- a/drivers/net/ks8851.h
+++ b/drivers/net/ethernet/micrel/ks8851.h
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
index d19c849059d8..d19c849059d8 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ethernet/micrel/ks8851_mll.c
diff --git a/drivers/net/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 27418d31a09f..7ece990381c8 100644
--- a/drivers/net/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -4700,12 +4700,11 @@ static void send_packet(struct sk_buff *skb, struct net_device *dev)
++hw->tx_int_cnt;
dma_buf = DMA_BUFFER(desc);
- dma_buf->len = this_frag->size;
+ dma_buf->len = skb_frag_size(this_frag);
dma_buf->dma = pci_map_single(
hw_priv->pdev,
- page_address(this_frag->page) +
- this_frag->page_offset,
+ skb_frag_address(this_frag),
dma_buf->len,
PCI_DMA_TODEVICE);
set_tx_buf(desc, dma_buf->dma);
diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig
new file mode 100644
index 000000000000..8163fd0f453f
--- /dev/null
+++ b/drivers/net/ethernet/microchip/Kconfig
@@ -0,0 +1,38 @@
+#
+# Microchip network device configuration
+#
+
+config NET_VENDOR_MICROCHIP
+ bool "Microchip devices"
+ default y
+ depends on SPI && EXPERIMENTAL
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Microchip cards. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_MICROCHIP
+
+config ENC28J60
+ tristate "ENC28J60 support"
+ depends on SPI && EXPERIMENTAL
+ select CRC32
+ ---help---
+ Support for the Microchip EN28J60 ethernet chip.
+
+ To compile this driver as a module, choose M here. The module will be
+ called enc28j60.
+
+config ENC28J60_WRITEVERIFY
+ bool "Enable write verify"
+ depends on ENC28J60
+ ---help---
+ Enable the verify after the buffer write useful for debugging purpose.
+ If unsure, say N.
+
+endif # NET_VENDOR_MICROCHIP
diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile
new file mode 100644
index 000000000000..573d4292b9ea
--- /dev/null
+++ b/drivers/net/ethernet/microchip/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Microchip network device drivers.
+#
+
+obj-$(CONFIG_ENC28J60) += enc28j60.o
diff --git a/drivers/net/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index 2837ce209cd7..50055e0282ed 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -1534,7 +1534,7 @@ static const struct net_device_ops enc28j60_netdev_ops = {
.ndo_open = enc28j60_net_open,
.ndo_stop = enc28j60_net_close,
.ndo_start_xmit = enc28j60_send_packet,
- .ndo_set_multicast_list = enc28j60_set_multicast_list,
+ .ndo_set_rx_mode = enc28j60_set_multicast_list,
.ndo_set_mac_address = enc28j60_set_mac_address,
.ndo_tx_timeout = enc28j60_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/enc28j60_hw.h b/drivers/net/ethernet/microchip/enc28j60_hw.h
index 25b41de49f0e..25b41de49f0e 100644
--- a/drivers/net/enc28j60_hw.h
+++ b/drivers/net/ethernet/microchip/enc28j60_hw.h
diff --git a/drivers/net/mipsnet.c b/drivers/net/ethernet/mipsnet.c
index 004e64ab1f95..d05b0c9e1e9c 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/ethernet/mipsnet.c
@@ -242,7 +242,7 @@ static const struct net_device_ops mipsnet_netdev_ops = {
.ndo_open = mipsnet_open,
.ndo_stop = mipsnet_close,
.ndo_start_xmit = mipsnet_xmit,
- .ndo_set_multicast_list = mipsnet_set_mclist,
+ .ndo_set_rx_mode = mipsnet_set_mclist,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ethernet/myricom/Kconfig b/drivers/net/ethernet/myricom/Kconfig
new file mode 100644
index 000000000000..540f0c6fc160
--- /dev/null
+++ b/drivers/net/ethernet/myricom/Kconfig
@@ -0,0 +1,47 @@
+#
+# Myricom device configuration
+#
+
+config NET_VENDOR_MYRI
+ bool "Myricom devices"
+ default y
+ depends on PCI && INET
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say
+ Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Myricom cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_MYRI
+
+config MYRI10GE
+ tristate "Myricom Myri-10G Ethernet support"
+ 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,
+ you will need a newer firmware image.
+ You may get this image or more information, at:
+
+ <http://www.myri.com/scs/download-Myri10GE.html>
+
+ To compile this driver as a module, choose M here. The module
+ will be called myri10ge.
+
+config MYRI10GE_DCA
+ bool "Direct Cache Access (DCA) Support"
+ default y
+ depends on MYRI10GE && DCA && !(MYRI10GE=y && DCA=m)
+ ---help---
+ Say Y here if you want to use Direct Cache Access (DCA) in the
+ driver. DCA is a method for warming the CPU cache before data
+ is used, with the intent of lessening the impact of cache misses.
+
+endif # NET_VENDOR_MYRI
diff --git a/drivers/net/ethernet/myricom/Makefile b/drivers/net/ethernet/myricom/Makefile
new file mode 100644
index 000000000000..296c0a10056b
--- /dev/null
+++ b/drivers/net/ethernet/myricom/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Myricom network device drivers.
+#
+
+obj-$(CONFIG_MYRI10GE) += myri10ge/
diff --git a/drivers/net/myri10ge/Makefile b/drivers/net/ethernet/myricom/myri10ge/Makefile
index 5df891647aee..5df891647aee 100644
--- a/drivers/net/myri10ge/Makefile
+++ b/drivers/net/ethernet/myricom/myri10ge/Makefile
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 1d2247554a35..0778edcf7b9a 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -1210,13 +1210,12 @@ myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va,
struct skb_frag_struct *skb_frags;
skb->len = skb->data_len = len;
- skb->truesize = len + sizeof(struct sk_buff);
/* attach the page(s) */
skb_frags = skb_shinfo(skb)->frags;
while (len > 0) {
memcpy(skb_frags, rx_frags, sizeof(*skb_frags));
- len -= rx_frags->size;
+ len -= skb_frag_size(rx_frags);
skb_frags++;
rx_frags++;
skb_shinfo(skb)->nr_frags++;
@@ -1228,7 +1227,7 @@ myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va,
* manually */
skb_copy_to_linear_data(skb, va, hlen);
skb_shinfo(skb)->frags[0].page_offset += hlen;
- skb_shinfo(skb)->frags[0].size -= hlen;
+ skb_frag_size_sub(&skb_shinfo(skb)->frags[0], hlen);
skb->data_len -= hlen;
skb->tail += hlen;
skb_pull(skb, MXGEFW_PAD);
@@ -1342,12 +1341,12 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
/* 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);
- rx_frags[i].page = rx->info[idx].page;
+ __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)
- rx_frags[i].size = remainder;
+ skb_frag_size_set(&rx_frags[i], remainder);
else
- rx_frags[i].size = MYRI10GE_ALLOC_SIZE;
+ skb_frag_size_set(&rx_frags[i], MYRI10GE_ALLOC_SIZE);
rx->cnt++;
idx = rx->cnt & rx->mask;
remainder -= MYRI10GE_ALLOC_SIZE;
@@ -1355,7 +1354,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
if (lro_enabled) {
rx_frags[0].page_offset += MXGEFW_PAD;
- rx_frags[0].size -= 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 */
@@ -1375,16 +1374,18 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
ss->stats.rx_dropped++;
do {
i--;
- put_page(rx_frags[i].page);
+ __skb_frag_unref(&rx_frags[i]);
} while (i != 0);
return 0;
}
/* Attach the pages to the skb, and trim off any padding */
myri10ge_rx_skb_build(skb, va, rx_frags, len, hlen);
- if (skb_shinfo(skb)->frags[0].size <= 0) {
- put_page(skb_shinfo(skb)->frags[0].page);
+ 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->protocol = eth_type_trans(skb, dev);
skb_record_rx_queue(skb, ss - &mgp->ss[0]);
@@ -2284,7 +2285,7 @@ myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
struct ethhdr *eh;
struct vlan_ethhdr *veh;
struct iphdr *iph;
- u8 *va = page_address(frag->page) + frag->page_offset;
+ u8 *va = skb_frag_address(frag);
unsigned long ll_hlen;
/* passed opaque through lro_receive_frags() */
__wsum csum = (__force __wsum) (unsigned long)priv;
@@ -2926,9 +2927,9 @@ again:
idx = (count + tx->req) & tx->mask;
frag = &skb_shinfo(skb)->frags[frag_idx];
frag_idx++;
- len = frag->size;
- bus = pci_map_page(mgp->pdev, frag->page, frag->page_offset,
- len, PCI_DMA_TODEVICE);
+ len = skb_frag_size(frag);
+ bus = skb_frag_dma_map(&mgp->pdev->dev, frag, 0, len,
+ DMA_TO_DEVICE);
dma_unmap_addr_set(&tx->info[idx], bus, bus);
dma_unmap_len_set(&tx->info[idx], len, len);
}
@@ -3892,7 +3893,7 @@ static const struct net_device_ops myri10ge_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = myri10ge_change_mtu,
.ndo_fix_features = myri10ge_fix_features,
- .ndo_set_multicast_list = myri10ge_set_multicast_list,
+ .ndo_set_rx_mode = myri10ge_set_multicast_list,
.ndo_set_mac_address = myri10ge_set_mac_address,
};
diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp.h
index 11be150e4d67..11be150e4d67 100644
--- a/drivers/net/myri10ge/myri10ge_mcp.h
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp.h
diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h
index 7ec4b864a550..7ec4b864a550 100644
--- a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h
diff --git a/drivers/net/ethernet/natsemi/Kconfig b/drivers/net/ethernet/natsemi/Kconfig
new file mode 100644
index 000000000000..4a6b9fd073b6
--- /dev/null
+++ b/drivers/net/ethernet/natsemi/Kconfig
@@ -0,0 +1,83 @@
+#
+# National Semi-conductor device configuration
+#
+
+config NET_VENDOR_NATSEMI
+ bool "National Semi-conductor devices"
+ default y
+ depends on MCA || MAC || MACH_JAZZ || PCI || XTENSA_PLATFORM_XT2000
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about National Semi-conductor devices. If you say Y,
+ you will be asked for your specific card in the following questions.
+
+if NET_VENDOR_NATSEMI
+
+config IBMLANA
+ tristate "IBM LAN Adapter/A support"
+ depends on MCA
+ ---help---
+ This is a Micro Channel Ethernet adapter. You need to set
+ CONFIG_MCA to use this driver. It is both available as an in-kernel
+ driver and as a module.
+
+ To compile this driver as a module, choose M here. The only
+ currently supported card is the IBM LAN Adapter/A for Ethernet. It
+ will both support 16K and 32K memory windows, however a 32K window
+ gives a better security against packet losses. Usage of multiple
+ boards with this driver should be possible, but has not been tested
+ up to now due to lack of hardware.
+
+config MACSONIC
+ tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
+ depends on MAC
+ ---help---
+ Support for NatSemi SONIC based Ethernet devices. This includes
+ the onboard Ethernet in many Quadras as well as some LC-PDS,
+ a few Nubus and all known Comm Slot Ethernet cards. If you have
+ one of these say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. This module will
+ be called macsonic.
+
+config MIPS_JAZZ_SONIC
+ tristate "MIPS JAZZ onboard SONIC Ethernet support"
+ depends on MACH_JAZZ
+ ---help---
+ This is the driver for the onboard card of MIPS Magnum 4000,
+ Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
+
+config NATSEMI
+ tristate "National Semiconductor DP8381x series PCI Ethernet support"
+ depends on PCI
+ select CRC32
+ ---help---
+ This driver is for the National Semiconductor DP83810 series,
+ which is used in cards from PureData, NetGear, Linksys
+ and others, including the 83815 chip.
+ More specific information and updates are available from
+ <http://www.scyld.com/network/natsemi.html>.
+
+config NS83820
+ tristate "National Semiconductor DP83820 support"
+ depends on PCI
+ ---help---
+ This is a driver for the National Semiconductor DP83820 series
+ of gigabit ethernet MACs. Cards using this chipset include
+ the D-Link DGE-500T, PureData's PDP8023Z-TG, SMC's SMC9462TX,
+ SOHO-GA2000T, SOHO-GA2500T. The driver supports the use of
+ zero copy.
+
+config XTENSA_XT2000_SONIC
+ tristate "Xtensa XT2000 onboard SONIC Ethernet support"
+ depends on XTENSA_PLATFORM_XT2000
+ ---help---
+ This is the driver for the onboard card of the Xtensa XT2000 board.
+
+endif # NET_VENDOR_NATSEMI
diff --git a/drivers/net/ethernet/natsemi/Makefile b/drivers/net/ethernet/natsemi/Makefile
new file mode 100644
index 000000000000..9aa5dea52b3e
--- /dev/null
+++ b/drivers/net/ethernet/natsemi/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the National Semi-conductor Sonic devices.
+#
+
+obj-$(CONFIG_IBMLANA) += ibmlana.o
+obj-$(CONFIG_MACSONIC) += macsonic.o
+obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
+obj-$(CONFIG_NATSEMI) += natsemi.o
+obj-$(CONFIG_NS83820) += ns83820.o
+obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
diff --git a/drivers/net/ibmlana.c b/drivers/net/ethernet/natsemi/ibmlana.c
index a7d6cad32953..999407f7ebdf 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ethernet/natsemi/ibmlana.c
@@ -910,7 +910,7 @@ static const struct net_device_ops ibmlana_netdev_ops = {
.ndo_open = ibmlana_open,
.ndo_stop = ibmlana_close,
.ndo_start_xmit = ibmlana_tx,
- .ndo_set_multicast_list = ibmlana_set_multicast_list,
+ .ndo_set_rx_mode = ibmlana_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/ibmlana.h b/drivers/net/ethernet/natsemi/ibmlana.h
index accd5efc9c8a..accd5efc9c8a 100644
--- a/drivers/net/ibmlana.h
+++ b/drivers/net/ethernet/natsemi/ibmlana.h
diff --git a/drivers/net/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c
index 949c1f933644..fc7c6a932ad9 100644
--- a/drivers/net/jazzsonic.c
+++ b/drivers/net/ethernet/natsemi/jazzsonic.c
@@ -111,7 +111,7 @@ static const struct net_device_ops sonic_netdev_ops = {
.ndo_stop = jazzsonic_close,
.ndo_start_xmit = sonic_send_packet,
.ndo_get_stats = sonic_get_stats,
- .ndo_set_multicast_list = sonic_multicast_list,
+ .ndo_set_rx_mode = sonic_multicast_list,
.ndo_tx_timeout = sonic_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index c93679ee6994..a2eacbfb4252 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -190,7 +190,7 @@ static const struct net_device_ops macsonic_netdev_ops = {
.ndo_open = macsonic_open,
.ndo_stop = macsonic_close,
.ndo_start_xmit = sonic_send_packet,
- .ndo_set_multicast_list = sonic_multicast_list,
+ .ndo_set_rx_mode = sonic_multicast_list,
.ndo_tx_timeout = sonic_tx_timeout,
.ndo_get_stats = sonic_get_stats,
.ndo_validate_addr = eth_validate_addr,
@@ -313,22 +313,13 @@ static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
{
- /* Bwahahaha */
- static int once_is_more_than_enough;
struct sonic_local* lp = netdev_priv(dev);
int sr;
int commslot = 0;
- if (once_is_more_than_enough)
- return -ENODEV;
- once_is_more_than_enough = 1;
-
if (!MACH_IS_MAC)
return -ENODEV;
- if (macintosh_config->ether_type != MAC_ETHER_SONIC)
- return -ENODEV;
-
printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
/* Bogus probing, on the models which may or may not have
diff --git a/drivers/net/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
index 2962cc695ce3..6ca047aab793 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -783,7 +783,7 @@ static const struct net_device_ops natsemi_netdev_ops = {
.ndo_stop = netdev_close,
.ndo_start_xmit = start_tx,
.ndo_get_stats = get_stats,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_change_mtu = natsemi_change_mtu,
.ndo_do_ioctl = netdev_ioctl,
.ndo_tx_timeout = ns_tx_timeout,
diff --git a/drivers/net/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index e736aec588fc..2b8f64ddfb55 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -1160,13 +1160,12 @@ again:
if (!nr_frags)
break;
- buf = pci_map_page(dev->pci_dev, frag->page,
- frag->page_offset,
- frag->size, PCI_DMA_TODEVICE);
+ buf = skb_frag_dma_map(&dev->pci_dev->dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
dprintk("frag: buf=%08Lx page=%08lx offset=%08lx\n",
(long long)buf, (long) page_to_pfn(frag->page),
frag->page_offset);
- len = frag->size;
+ len = skb_frag_size(frag);
frag++;
nr_frags--;
}
@@ -1937,7 +1936,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_start_xmit = ns83820_hard_start_xmit,
.ndo_get_stats = ns83820_get_stats,
.ndo_change_mtu = ns83820_change_mtu,
- .ndo_set_multicast_list = ns83820_set_multicast,
+ .ndo_set_rx_mode = ns83820_set_multicast,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = ns83820_tx_timeout,
diff --git a/drivers/net/sonic.c b/drivers/net/ethernet/natsemi/sonic.c
index 26e25d7f5829..26e25d7f5829 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
diff --git a/drivers/net/sonic.h b/drivers/net/ethernet/natsemi/sonic.h
index 07091dd27e5d..07091dd27e5d 100644
--- a/drivers/net/sonic.h
+++ b/drivers/net/ethernet/natsemi/sonic.h
diff --git a/drivers/net/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c
index 9f12026d98e7..ccf61b9da8d1 100644
--- a/drivers/net/xtsonic.c
+++ b/drivers/net/ethernet/natsemi/xtsonic.c
@@ -122,7 +122,7 @@ static const struct net_device_ops xtsonic_netdev_ops = {
.ndo_stop = xtsonic_close,
.ndo_start_xmit = sonic_send_packet,
.ndo_get_stats = sonic_get_stats,
- .ndo_set_multicast_list = sonic_multicast_list,
+ .ndo_set_rx_mode = sonic_multicast_list,
.ndo_tx_timeout = sonic_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/ethernet/neterion/Kconfig b/drivers/net/ethernet/neterion/Kconfig
new file mode 100644
index 000000000000..ff26b54bd3fb
--- /dev/null
+++ b/drivers/net/ethernet/neterion/Kconfig
@@ -0,0 +1,55 @@
+#
+# Exar device configuration
+#
+
+config NET_VENDOR_EXAR
+ bool "Exar devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say
+ Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Exar cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_EXAR
+
+config S2IO
+ tristate "Exar Xframe 10Gb Ethernet Adapter"
+ depends on PCI
+ ---help---
+ This driver supports Exar Corp's Xframe Series 10Gb Ethernet Adapters.
+
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/s2io.txt>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called s2io.
+
+config VXGE
+ tristate "Exar X3100 Series 10GbE PCIe Server Adapter"
+ depends on PCI && INET
+ ---help---
+ This driver supports Exar Corp's X3100 Series 10 GbE PCIe
+ I/O Virtualized Server Adapter.
+
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/vxge.txt>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called vxge.
+
+config VXGE_DEBUG_TRACE_ALL
+ bool "Enabling All Debug trace statements in driver"
+ default n
+ depends on VXGE
+ ---help---
+ Say Y here if you want to enabling all the debug trace statements in
+ the vxge driver. By default only few debug trace statements are
+ enabled.
+
+endif # NET_VENDOR_EXAR
diff --git a/drivers/net/ethernet/neterion/Makefile b/drivers/net/ethernet/neterion/Makefile
new file mode 100644
index 000000000000..70c8058a601a
--- /dev/null
+++ b/drivers/net/ethernet/neterion/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Exar network device drivers.
+#
+
+obj-$(CONFIG_S2IO) += s2io.o
+obj-$(CONFIG_VXGE) += vxge/
diff --git a/drivers/net/s2io-regs.h b/drivers/net/ethernet/neterion/s2io-regs.h
index 3688325c11f5..3688325c11f5 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/ethernet/neterion/s2io-regs.h
diff --git a/drivers/net/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 277d48b0800a..c27fb3dda9f4 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -2350,12 +2350,12 @@ static struct sk_buff *s2io_txdl_getskb(struct fifo_info *fifo_data,
if (frg_cnt) {
txds++;
for (j = 0; j < frg_cnt; j++, txds++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[j];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[j];
if (!txds->Buffer_Pointer)
break;
pci_unmap_page(nic->pdev,
(dma_addr_t)txds->Buffer_Pointer,
- frag->size, PCI_DMA_TODEVICE);
+ skb_frag_size(frag), PCI_DMA_TODEVICE);
}
}
memset(txdlp, 0, (sizeof(struct TxD) * fifo_data->max_txds));
@@ -4185,16 +4185,16 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev)
frg_cnt = skb_shinfo(skb)->nr_frags;
/* For fragmented SKB. */
for (i = 0; i < frg_cnt; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
/* A '0' length fragment will be ignored */
- if (!frag->size)
+ if (!skb_frag_size(frag))
continue;
txdp++;
- txdp->Buffer_Pointer = (u64)pci_map_page(sp->pdev, frag->page,
- frag->page_offset,
- frag->size,
- PCI_DMA_TODEVICE);
- txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
+ txdp->Buffer_Pointer = (u64)skb_frag_dma_map(&sp->pdev->dev,
+ frag, 0,
+ skb_frag_size(frag),
+ DMA_TO_DEVICE);
+ txdp->Control_1 = TXD_BUFFER0_SIZE(skb_frag_size(frag));
if (offload_type == SKB_GSO_UDP)
txdp->Control_1 |= TXD_UFO_EN;
}
@@ -5522,14 +5522,12 @@ static void s2io_ethtool_gringparam(struct net_device *dev,
ering->rx_jumbo_max_pending = MAX_RX_DESC_2;
}
- ering->rx_mini_max_pending = 0;
ering->tx_max_pending = MAX_TX_DESC;
for (i = 0; i < sp->config.rx_ring_num; i++)
rx_desc_count += sp->config.rx_cfg[i].num_rxd;
ering->rx_pending = rx_desc_count;
ering->rx_jumbo_pending = rx_desc_count;
- ering->rx_mini_pending = 0;
for (i = 0; i < sp->config.tx_fifo_num; i++)
tx_desc_count += sp->config.tx_cfg[i].fifo_len;
@@ -7682,7 +7680,7 @@ static const struct net_device_ops s2io_netdev_ops = {
.ndo_get_stats = s2io_get_stats,
.ndo_start_xmit = s2io_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = s2io_set_multicast,
+ .ndo_set_rx_mode = s2io_set_multicast,
.ndo_do_ioctl = s2io_ioctl,
.ndo_set_mac_address = s2io_set_mac_addr,
.ndo_change_mtu = s2io_change_mtu,
diff --git a/drivers/net/s2io.h b/drivers/net/ethernet/neterion/s2io.h
index d5596926a1ef..d5596926a1ef 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/ethernet/neterion/s2io.h
diff --git a/drivers/net/vxge/Makefile b/drivers/net/ethernet/neterion/vxge/Makefile
index b625e2c503f5..b625e2c503f5 100644
--- a/drivers/net/vxge/Makefile
+++ b/drivers/net/ethernet/neterion/vxge/Makefile
diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c
index 1520c574cb20..98e2c10ae08b 100644
--- a/drivers/net/vxge/vxge-config.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c
@@ -1342,9 +1342,7 @@ vxge_hw_device_initialize(
hldev->bar0 = attr->bar0;
hldev->pdev = attr->pdev;
- hldev->uld_callbacks.link_up = attr->uld_callbacks.link_up;
- hldev->uld_callbacks.link_down = attr->uld_callbacks.link_down;
- hldev->uld_callbacks.crit_err = attr->uld_callbacks.crit_err;
+ hldev->uld_callbacks = attr->uld_callbacks;
__vxge_hw_device_pci_e_init(hldev);
@@ -2633,7 +2631,7 @@ __vxge_hw_mempool_create(struct __vxge_hw_device *devh,
u32 items_priv_size,
u32 items_initial,
u32 items_max,
- struct vxge_hw_mempool_cbs *mp_callback,
+ const struct vxge_hw_mempool_cbs *mp_callback,
void *userdata)
{
enum vxge_hw_status status = VXGE_HW_OK;
@@ -2817,7 +2815,9 @@ __vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp,
struct vxge_hw_ring_config *config;
struct __vxge_hw_device *hldev;
u32 vp_id;
- struct vxge_hw_mempool_cbs ring_mp_callback;
+ static const struct vxge_hw_mempool_cbs ring_mp_callback = {
+ .item_func_alloc = __vxge_hw_ring_mempool_item_alloc,
+ };
if ((vp == NULL) || (attr == NULL)) {
status = VXGE_HW_FAIL;
@@ -2872,7 +2872,6 @@ __vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp,
/* calculate actual RxD block private size */
ring->rxdblock_priv_size = ring->rxd_priv_size * ring->rxds_per_block;
- ring_mp_callback.item_func_alloc = __vxge_hw_ring_mempool_item_alloc;
ring->mempool = __vxge_hw_mempool_create(hldev,
VXGE_HW_BLOCK_SIZE,
VXGE_HW_BLOCK_SIZE,
diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/ethernet/neterion/vxge/vxge-config.h
index dd362584f5ca..5046a64f0fe8 100644
--- a/drivers/net/vxge/vxge-config.h
+++ b/drivers/net/ethernet/neterion/vxge/vxge-config.h
@@ -740,7 +740,7 @@ struct __vxge_hw_device {
struct vxge_hw_device_config config;
enum vxge_hw_device_link_state link_state;
- struct vxge_hw_uld_cbs uld_callbacks;
+ const struct vxge_hw_uld_cbs *uld_callbacks;
u32 host_type;
u32 func_id;
@@ -840,7 +840,7 @@ struct vxge_hw_device_hw_info {
struct vxge_hw_device_attr {
void __iomem *bar0;
struct pci_dev *pdev;
- struct vxge_hw_uld_cbs uld_callbacks;
+ const struct vxge_hw_uld_cbs *uld_callbacks;
};
#define VXGE_HW_DEVICE_LINK_STATE_SET(hldev, ls) (hldev->link_state = ls)
diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
index 92dd72d3f9de..92dd72d3f9de 100644
--- a/drivers/net/vxge/vxge-ethtool.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c
diff --git a/drivers/net/vxge/vxge-ethtool.h b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.h
index 6cf3044d7f43..6cf3044d7f43 100644
--- a/drivers/net/vxge/vxge-ethtool.h
+++ b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.h
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index 178348a258d2..671e166b5af1 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -585,7 +585,7 @@ vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
for (j = 0; j < frg_cnt; j++) {
pci_unmap_page(fifo->pdev,
txd_priv->dma_buffers[i++],
- frag->size, PCI_DMA_TODEVICE);
+ skb_frag_size(frag), PCI_DMA_TODEVICE);
frag += 1;
}
@@ -920,14 +920,14 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
frag = &skb_shinfo(skb)->frags[0];
for (i = 0; i < frg_cnt; i++) {
/* ignore 0 length fragment */
- if (!frag->size)
+ if (!skb_frag_size(frag))
continue;
- dma_pointer = (u64) pci_map_page(fifo->pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
+ dma_pointer = (u64)skb_frag_dma_map(&fifo->pdev->dev, frag,
+ 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
- if (unlikely(pci_dma_mapping_error(fifo->pdev, dma_pointer)))
+ if (unlikely(dma_mapping_error(&fifo->pdev->dev, dma_pointer)))
goto _exit2;
vxge_debug_tx(VXGE_TRACE,
"%s: %s:%d frag = %d dma_pointer = 0x%llx",
@@ -936,7 +936,7 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
txdl_priv->dma_buffers[j] = dma_pointer;
vxge_hw_fifo_txdl_buffer_set(fifo_hw, dtr, j++, dma_pointer,
- frag->size);
+ skb_frag_size(frag));
frag += 1;
}
@@ -979,7 +979,7 @@ _exit1:
for (; j < i; j++) {
pci_unmap_page(fifo->pdev, txdl_priv->dma_buffers[j],
- frag->size, PCI_DMA_TODEVICE);
+ skb_frag_size(frag), PCI_DMA_TODEVICE);
frag += 1;
}
@@ -1050,7 +1050,7 @@ vxge_tx_term(void *dtrh, enum vxge_hw_txdl_state state, void *userdata)
for (j = 0; j < frg_cnt; j++) {
pci_unmap_page(fifo->pdev, txd_priv->dma_buffers[i++],
- frag->size, PCI_DMA_TODEVICE);
+ skb_frag_size(frag), PCI_DMA_TODEVICE);
frag += 1;
}
@@ -3354,7 +3354,7 @@ static const struct net_device_ops vxge_netdev_ops = {
.ndo_get_stats64 = vxge_get_stats64,
.ndo_start_xmit = vxge_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = vxge_set_multicast,
+ .ndo_set_rx_mode = vxge_set_multicast,
.ndo_do_ioctl = vxge_ioctl,
.ndo_set_mac_address = vxge_set_mac_addr,
.ndo_change_mtu = vxge_change_mtu,
@@ -4284,6 +4284,12 @@ static int __devinit is_sriov_initialized(struct pci_dev *pdev)
return 0;
}
+static const struct vxge_hw_uld_cbs vxge_callbacks = {
+ .link_up = vxge_callback_link_up,
+ .link_down = vxge_callback_link_down,
+ .crit_err = vxge_callback_crit_err,
+};
+
/**
* vxge_probe
* @pdev : structure containing the PCI related information of the device.
@@ -4494,9 +4500,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
}
/* Setting driver callbacks */
- attr.uld_callbacks.link_up = vxge_callback_link_up;
- attr.uld_callbacks.link_down = vxge_callback_link_down;
- attr.uld_callbacks.crit_err = vxge_callback_crit_err;
+ attr.uld_callbacks = &vxge_callbacks;
status = vxge_hw_device_initialize(&hldev, &attr, device_config);
if (status != VXGE_HW_OK) {
diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/ethernet/neterion/vxge/vxge-main.h
index f52a42d1dbb7..f52a42d1dbb7 100644
--- a/drivers/net/vxge/vxge-main.h
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.h
diff --git a/drivers/net/vxge/vxge-reg.h b/drivers/net/ethernet/neterion/vxge/vxge-reg.h
index 3e658b175947..3e658b175947 100644
--- a/drivers/net/vxge/vxge-reg.h
+++ b/drivers/net/ethernet/neterion/vxge/vxge-reg.h
diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/ethernet/neterion/vxge/vxge-traffic.c
index ad64ce0afe3f..5954fa264da1 100644
--- a/drivers/net/vxge/vxge-traffic.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-traffic.c
@@ -532,8 +532,8 @@ __vxge_hw_device_handle_error(struct __vxge_hw_device *hldev, u32 vp_id,
}
/* notify driver */
- if (hldev->uld_callbacks.crit_err)
- hldev->uld_callbacks.crit_err(
+ if (hldev->uld_callbacks->crit_err)
+ hldev->uld_callbacks->crit_err(
(struct __vxge_hw_device *)hldev,
type, vp_id);
out:
@@ -560,8 +560,8 @@ __vxge_hw_device_handle_link_down_ind(struct __vxge_hw_device *hldev)
hldev->link_state = VXGE_HW_LINK_DOWN;
/* notify driver */
- if (hldev->uld_callbacks.link_down)
- hldev->uld_callbacks.link_down(hldev);
+ if (hldev->uld_callbacks->link_down)
+ hldev->uld_callbacks->link_down(hldev);
exit:
return VXGE_HW_OK;
}
@@ -585,8 +585,8 @@ __vxge_hw_device_handle_link_up_ind(struct __vxge_hw_device *hldev)
hldev->link_state = VXGE_HW_LINK_UP;
/* notify driver */
- if (hldev->uld_callbacks.link_up)
- hldev->uld_callbacks.link_up(hldev);
+ if (hldev->uld_callbacks->link_up)
+ hldev->uld_callbacks->link_up(hldev);
exit:
return VXGE_HW_OK;
}
diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/ethernet/neterion/vxge/vxge-traffic.h
index 4a518a3b131c..4a518a3b131c 100644
--- a/drivers/net/vxge/vxge-traffic.h
+++ b/drivers/net/ethernet/neterion/vxge/vxge-traffic.h
diff --git a/drivers/net/vxge/vxge-version.h b/drivers/net/ethernet/neterion/vxge/vxge-version.h
index b9efa28bab3e..b9efa28bab3e 100644
--- a/drivers/net/vxge/vxge-version.h
+++ b/drivers/net/ethernet/neterion/vxge/vxge-version.h
diff --git a/drivers/net/netx-eth.c b/drivers/net/ethernet/netx-eth.c
index 2dfee892d200..8d288af16fc9 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/ethernet/netx-eth.c
@@ -306,7 +306,7 @@ static const struct net_device_ops netx_eth_netdev_ops = {
.ndo_stop = netx_eth_close,
.ndo_start_xmit = netx_eth_hard_start_xmit,
.ndo_tx_timeout = netx_eth_timeout,
- .ndo_set_multicast_list = netx_eth_set_multicast_list,
+ .ndo_set_rx_mode = netx_eth_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ethernet/nuvoton/Kconfig b/drivers/net/ethernet/nuvoton/Kconfig
new file mode 100644
index 000000000000..334c17183095
--- /dev/null
+++ b/drivers/net/ethernet/nuvoton/Kconfig
@@ -0,0 +1,31 @@
+#
+# Nuvoton network device configuration
+#
+
+config NET_VENDOR_NUVOTON
+ bool "Nuvoton devices"
+ default y
+ depends on ARM && ARCH_W90X900
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Nuvoton cards. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_NUVOTON
+
+config W90P910_ETH
+ tristate "Nuvoton w90p910 Ethernet support"
+ depends on ARM && ARCH_W90X900
+ select PHYLIB
+ select NET_CORE
+ select MII
+ ---help---
+ Say Y here if you want to use built-in Ethernet ports
+ on w90p910 processor.
+
+endif # NET_VENDOR_NUVOTON
diff --git a/drivers/net/ethernet/nuvoton/Makefile b/drivers/net/ethernet/nuvoton/Makefile
new file mode 100644
index 000000000000..171aa044bd3b
--- /dev/null
+++ b/drivers/net/ethernet/nuvoton/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Nuvoton network device drivers.
+#
+
+obj-$(CONFIG_W90P910_ETH) += w90p910_ether.o
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
index bfea499a3513..f1bfb8f8fcf0 100644
--- a/drivers/net/arm/w90p910_ether.c
+++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
@@ -919,7 +919,7 @@ static const struct net_device_ops w90p910_ether_netdev_ops = {
.ndo_stop = w90p910_ether_close,
.ndo_start_xmit = w90p910_ether_start_xmit,
.ndo_get_stats = w90p910_ether_stats,
- .ndo_set_multicast_list = w90p910_ether_set_multicast_list,
+ .ndo_set_rx_mode = w90p910_ether_set_multicast_list,
.ndo_set_mac_address = w90p910_set_mac_address,
.ndo_do_ioctl = w90p910_ether_ioctl,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/ethernet/nvidia/Kconfig b/drivers/net/ethernet/nvidia/Kconfig
new file mode 100644
index 000000000000..ace19e7f6d13
--- /dev/null
+++ b/drivers/net/ethernet/nvidia/Kconfig
@@ -0,0 +1,32 @@
+#
+# NVIDIA network device configuration
+#
+
+config NET_VENDOR_NVIDIA
+ bool "NVIDIA devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about NVIDIA cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_NVIDIA
+
+config FORCEDETH
+ tristate "nForce Ethernet support"
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) controller of this type, say Y and
+ read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called forcedeth.
+
+endif # NET_VENDOR_NVIDIA
diff --git a/drivers/net/ethernet/nvidia/Makefile b/drivers/net/ethernet/nvidia/Makefile
new file mode 100644
index 000000000000..e079ae5771d5
--- /dev/null
+++ b/drivers/net/ethernet/nvidia/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the NVIDIA network device drivers.
+#
+
+obj-$(CONFIG_FORCEDETH) += forcedeth.o
diff --git a/drivers/net/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 6d5fbd4d4256..1e37eb98c4e2 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -2099,8 +2099,10 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* add fragments to entries count */
for (i = 0; i < fragments; i++) {
- entries += (skb_shinfo(skb)->frags[i].size >> NV_TX2_TSO_MAX_SHIFT) +
- ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
+ u32 size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+
+ entries += (size >> NV_TX2_TSO_MAX_SHIFT) +
+ ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
}
spin_lock_irqsave(&np->lock, flags);
@@ -2138,16 +2140,19 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* setup the fragments */
for (i = 0; i < fragments; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- u32 size = frag->size;
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ u32 size = skb_frag_size(frag);
offset = 0;
do {
prev_tx = put_tx;
prev_tx_ctx = np->put_tx_ctx;
bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
- np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
- PCI_DMA_TODEVICE);
+ np->put_tx_ctx->dma = skb_frag_dma_map(
+ &np->pci_dev->dev,
+ frag, offset,
+ bcnt,
+ DMA_TO_DEVICE);
np->put_tx_ctx->dma_len = bcnt;
np->put_tx_ctx->dma_single = 0;
put_tx->buf = cpu_to_le32(np->put_tx_ctx->dma);
@@ -2208,8 +2213,10 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
/* add fragments to entries count */
for (i = 0; i < fragments; i++) {
- entries += (skb_shinfo(skb)->frags[i].size >> NV_TX2_TSO_MAX_SHIFT) +
- ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
+ u32 size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+
+ entries += (size >> NV_TX2_TSO_MAX_SHIFT) +
+ ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
}
spin_lock_irqsave(&np->lock, flags);
@@ -2250,15 +2257,18 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
/* setup the fragments */
for (i = 0; i < fragments; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- u32 size = frag->size;
+ u32 size = skb_frag_size(frag);
offset = 0;
do {
prev_tx = put_tx;
prev_tx_ctx = np->put_tx_ctx;
bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
- np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
- PCI_DMA_TODEVICE);
+ np->put_tx_ctx->dma = skb_frag_dma_map(
+ &np->pci_dev->dev,
+ frag, offset,
+ bcnt,
+ DMA_TO_DEVICE);
np->put_tx_ctx->dma_len = bcnt;
np->put_tx_ctx->dma_single = 0;
put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma));
@@ -4274,13 +4284,9 @@ static void nv_get_ringparam(struct net_device *dev, struct ethtool_ringparam* r
struct fe_priv *np = netdev_priv(dev);
ring->rx_max_pending = (np->desc_ver == DESC_VER_1) ? RING_MAX_DESC_VER_1 : RING_MAX_DESC_VER_2_3;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->tx_max_pending = (np->desc_ver == DESC_VER_1) ? RING_MAX_DESC_VER_1 : RING_MAX_DESC_VER_2_3;
ring->rx_pending = np->rx_ring_size;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
ring->tx_pending = np->tx_ring_size;
}
@@ -5208,7 +5214,7 @@ static const struct net_device_ops nv_netdev_ops = {
.ndo_set_features = nv_set_features,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = nv_set_mac_address,
- .ndo_set_multicast_list = nv_set_multicast,
+ .ndo_set_rx_mode = nv_set_multicast,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = nv_poll_controller,
#endif
@@ -5225,7 +5231,7 @@ static const struct net_device_ops nv_netdev_ops_optimized = {
.ndo_set_features = nv_set_features,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = nv_set_mac_address,
- .ndo_set_multicast_list = nv_set_multicast,
+ .ndo_set_rx_mode = nv_set_multicast,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = nv_poll_controller,
#endif
diff --git a/drivers/net/octeon/Kconfig b/drivers/net/ethernet/octeon/Kconfig
index 1e56bbf3f5c0..3de52ffd2872 100644
--- a/drivers/net/octeon/Kconfig
+++ b/drivers/net/ethernet/octeon/Kconfig
@@ -1,10 +1,14 @@
+#
+# Cavium network device configuration
+#
+
config OCTEON_MGMT_ETHERNET
tristate "Octeon Management port ethernet driver (CN5XXX, CN6XXX)"
depends on CPU_CAVIUM_OCTEON
select PHYLIB
select MDIO_OCTEON
default y
- help
+ ---help---
This option enables the ethernet driver for the management
port on Cavium Networks' Octeon CN57XX, CN56XX, CN55XX,
CN54XX, CN52XX, and CN6XXX chips.
diff --git a/drivers/net/ethernet/octeon/Makefile b/drivers/net/ethernet/octeon/Makefile
new file mode 100644
index 000000000000..efa41c1d91c5
--- /dev/null
+++ b/drivers/net/ethernet/octeon/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Cavium network device drivers.
+#
+
+obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon_mgmt.o
diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index 429e08c84e9b..bc1d946b7971 100644
--- a/drivers/net/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/slab.h>
#include <linux/phy.h>
@@ -1059,7 +1060,6 @@ static const struct net_device_ops octeon_mgmt_ops = {
.ndo_stop = octeon_mgmt_stop,
.ndo_start_xmit = octeon_mgmt_xmit,
.ndo_set_rx_mode = octeon_mgmt_set_rx_filtering,
- .ndo_set_multicast_list = octeon_mgmt_set_rx_filtering,
.ndo_set_mac_address = octeon_mgmt_set_mac_address,
.ndo_do_ioctl = octeon_mgmt_ioctl,
.ndo_change_mtu = octeon_mgmt_change_mtu,
@@ -1102,6 +1102,8 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
tasklet_init(&p->tx_clean_tasklet,
octeon_mgmt_clean_tx_tasklet, (unsigned long)p);
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
netdev->netdev_ops = &octeon_mgmt_ops;
netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
diff --git a/drivers/net/ethernet/oki-semi/Kconfig b/drivers/net/ethernet/oki-semi/Kconfig
new file mode 100644
index 000000000000..ecd45f9ea9d9
--- /dev/null
+++ b/drivers/net/ethernet/oki-semi/Kconfig
@@ -0,0 +1,23 @@
+#
+# OKI Semiconductor device configuration
+#
+
+config NET_VENDOR_OKI
+ bool "OKI Semiconductor devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about OKI Semiconductor cards. If you say Y, you will
+ be asked for your specific card in the following questions.
+
+if NET_VENDOR_OKI
+
+source "drivers/net/ethernet/oki-semi/pch_gbe/Kconfig"
+
+endif # NET_VENDOR_OKI
diff --git a/drivers/net/ethernet/oki-semi/Makefile b/drivers/net/ethernet/oki-semi/Makefile
new file mode 100644
index 000000000000..b6780c877c19
--- /dev/null
+++ b/drivers/net/ethernet/oki-semi/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the OKI Semiconductor device drivers.
+#
+
+obj-$(CONFIG_PCH_GBE) += pch_gbe/
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
new file mode 100644
index 000000000000..00bc4fc968c7
--- /dev/null
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
@@ -0,0 +1,22 @@
+#
+# OKI Semiconductor device configuration
+#
+
+config PCH_GBE
+ tristate "OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE"
+ depends on PCI
+ select NET_CORE
+ select MII
+ ---help---
+ This is a gigabit ethernet driver for EG20T PCH.
+ EG20T PCH is the platform controller hub that is used in Intel's
+ general embedded platform. EG20T PCH has Gigabit Ethernet interface.
+ Using this interface, it is able to access system devices connected
+ to Gigabit Ethernet. This driver enables Gigabit Ethernet function.
+
+ This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
+ Output Hub), ML7223/ML7831.
+ ML7223 IOH is for MP(Media Phone) use. ML7831 IOH is for general
+ purpose use.
+ ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+ ML7223/ML7831 is completely compatible for Intel EG20T PCH.
diff --git a/drivers/net/pch_gbe/Makefile b/drivers/net/ethernet/oki-semi/pch_gbe/Makefile
index 31288d4ad248..31288d4ad248 100644
--- a/drivers/net/pch_gbe/Makefile
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/Makefile
diff --git a/drivers/net/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
index a09a07197eb5..a09a07197eb5 100644
--- a/drivers/net/pch_gbe/pch_gbe.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
diff --git a/drivers/net/pch_gbe/pch_gbe_api.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c
index e48f084ad226..e48f084ad226 100644
--- a/drivers/net/pch_gbe/pch_gbe_api.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c
diff --git a/drivers/net/pch_gbe/pch_gbe_api.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h
index 94aaac5b057b..94aaac5b057b 100644
--- a/drivers/net/pch_gbe/pch_gbe_api.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h
diff --git a/drivers/net/pch_gbe/pch_gbe_ethtool.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
index ea2d8e41887a..8c8027176bef 100644
--- a/drivers/net/pch_gbe/pch_gbe_ethtool.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
@@ -273,12 +273,8 @@ static void pch_gbe_get_ringparam(struct net_device *netdev,
ring->rx_max_pending = PCH_GBE_MAX_RXD;
ring->tx_max_pending = PCH_GBE_MAX_TXD;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = rxdr->count;
ring->tx_pending = txdr->count;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
/**
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index b8b4ba27b0e7..b89f3a684aec 100644
--- a/drivers/net/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -698,7 +698,6 @@ static void pch_gbe_configure_tx(struct pch_gbe_adapter *adapter)
*/
static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
struct pch_gbe_hw *hw = &adapter->hw;
u32 rx_mode, tcpip;
@@ -2233,7 +2232,7 @@ static const struct net_device_ops pch_gbe_netdev_ops = {
.ndo_change_mtu = pch_gbe_change_mtu,
.ndo_set_features = pch_gbe_set_features,
.ndo_do_ioctl = pch_gbe_ioctl,
- .ndo_set_multicast_list = &pch_gbe_set_multi,
+ .ndo_set_rx_mode = pch_gbe_set_multi,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = pch_gbe_netpoll,
#endif
diff --git a/drivers/net/pch_gbe/pch_gbe_param.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
index 5b5d90a47e29..5b5d90a47e29 100644
--- a/drivers/net/pch_gbe/pch_gbe_param.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
diff --git a/drivers/net/pch_gbe/pch_gbe_phy.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
index 28bb9603d736..28bb9603d736 100644
--- a/drivers/net/pch_gbe/pch_gbe_phy.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
diff --git a/drivers/net/pch_gbe/pch_gbe_phy.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
index 03264dc7b5ec..03264dc7b5ec 100644
--- a/drivers/net/pch_gbe/pch_gbe_phy.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
diff --git a/drivers/net/ethernet/packetengines/Kconfig b/drivers/net/ethernet/packetengines/Kconfig
new file mode 100644
index 000000000000..b97132d9dff0
--- /dev/null
+++ b/drivers/net/ethernet/packetengines/Kconfig
@@ -0,0 +1,47 @@
+#
+# Packet engine device configuration
+#
+
+config NET_PACKET_ENGINE
+ bool "Packet Engine devices"
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about packet engine devices. If you say Y, you will
+ be asked for your specific card in the following questions.
+
+if NET_PACKET_ENGINE
+
+config HAMACHI
+ tristate "Packet Engines Hamachi GNIC-II support"
+ depends on PCI
+ select NET_CORE
+ select MII
+ ---help---
+ If you have a Gigabit Ethernet card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module will be
+ called hamachi.
+
+config YELLOWFIN
+ tristate "Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+ select CRC32
+ ---help---
+ Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet
+ adapter or the SYM53C885 Ethernet controller. The Gigabit adapter is
+ used by the Beowulf Linux cluster project. See
+ <http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html> for more
+ information about this driver in particular and Beowulf in general.
+
+ To compile this driver as a module, choose M here: the module
+ will be called yellowfin. This is recommended.
+
+endif # NET_PACKET_ENGINE
diff --git a/drivers/net/ethernet/packetengines/Makefile b/drivers/net/ethernet/packetengines/Makefile
new file mode 100644
index 000000000000..995ccd077d0c
--- /dev/null
+++ b/drivers/net/ethernet/packetengines/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Packet Engine network device drivers.
+#
+
+obj-$(CONFIG_HAMACHI) += hamachi.o
+obj-$(CONFIG_YELLOWFIN) += yellowfin.o
diff --git a/drivers/net/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
index c274b3d77eb5..3458df3780b8 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/ethernet/packetengines/hamachi.c
@@ -567,7 +567,7 @@ static const struct net_device_ops hamachi_netdev_ops = {
.ndo_stop = hamachi_close,
.ndo_start_xmit = hamachi_start_xmit,
.ndo_get_stats = hamachi_get_stats,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
index 3e5ac60b89ac..db44e9af03c3 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/ethernet/packetengines/yellowfin.c
@@ -359,7 +359,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_open = yellowfin_open,
.ndo_stop = yellowfin_close,
.ndo_start_xmit = yellowfin_start_xmit,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ethernet/pasemi/Kconfig b/drivers/net/ethernet/pasemi/Kconfig
new file mode 100644
index 000000000000..01e6c329d78c
--- /dev/null
+++ b/drivers/net/ethernet/pasemi/Kconfig
@@ -0,0 +1,30 @@
+#
+# PA Semi network device configuration
+#
+
+config NET_VENDOR_PASEMI
+ bool "PA Semi devices"
+ default y
+ depends on PPC_PASEMI && PCI && INET
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about PA Semi cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_PASEMI
+
+config PASEMI_MAC
+ tristate "PA Semi 1/10Gbit MAC"
+ depends on PPC_PASEMI && PCI && INET
+ select PHYLIB
+ select INET_LRO
+ ---help---
+ This driver supports the on-chip 1/10Gbit Ethernet controller on
+ PA Semi's PWRficient line of chips.
+
+endif # NET_VENDOR_PASEMI
diff --git a/drivers/net/ethernet/pasemi/Makefile b/drivers/net/ethernet/pasemi/Makefile
new file mode 100644
index 000000000000..05db5434bafc
--- /dev/null
+++ b/drivers/net/ethernet/pasemi/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the A Semi network device drivers.
+#
+
+obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o pasemi_mac_ethtool.o
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index 9ec112ca62e4..49b549ff2c78 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -300,9 +300,9 @@ static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
pci_unmap_single(pdev, dmas[0], skb_headlen(skb), PCI_DMA_TODEVICE);
for (f = 0; f < nfrags; f++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
- pci_unmap_page(pdev, dmas[f+1], frag->size, PCI_DMA_TODEVICE);
+ pci_unmap_page(pdev, dmas[f+1], skb_frag_size(frag), PCI_DMA_TODEVICE);
}
dev_kfree_skb_irq(skb);
@@ -1505,11 +1505,10 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
for (i = 0; i < nfrags; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- map[i+1] = pci_map_page(mac->dma_pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
- map_size[i+1] = frag->size;
- if (pci_dma_mapping_error(mac->dma_pdev, map[i+1])) {
+ map[i + 1] = skb_frag_dma_map(&mac->dma_pdev->dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
+ map_size[i+1] = skb_frag_size(frag);
+ if (dma_mapping_error(&mac->dma_pdev->dev, map[i + 1])) {
nfrags = i;
goto out_err_nolock;
}
@@ -1719,7 +1718,7 @@ static const struct net_device_ops pasemi_netdev_ops = {
.ndo_open = pasemi_mac_open,
.ndo_stop = pasemi_mac_close,
.ndo_start_xmit = pasemi_mac_start_tx,
- .ndo_set_multicast_list = pasemi_mac_set_rx_mode,
+ .ndo_set_rx_mode = pasemi_mac_set_rx_mode,
.ndo_set_mac_address = pasemi_mac_set_mac_addr,
.ndo_change_mtu = pasemi_mac_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/ethernet/pasemi/pasemi_mac.h
index e2f4efa8ad46..e2f4efa8ad46 100644
--- a/drivers/net/pasemi_mac.h
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.h
diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/ethernet/pasemi/pasemi_mac_ethtool.c
index 4825959a0efe..4825959a0efe 100644
--- a/drivers/net/pasemi_mac_ethtool.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac_ethtool.c
diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig
new file mode 100644
index 000000000000..a8669adecc97
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/Kconfig
@@ -0,0 +1,54 @@
+#
+# QLogic network device configuration
+#
+
+config NET_VENDOR_QLOGIC
+ bool "QLogic devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about QLogic cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_QLOGIC
+
+config QLA3XXX
+ tristate "QLogic QLA3XXX Network Driver Support"
+ depends on PCI
+ ---help---
+ This driver supports QLogic ISP3XXX gigabit Ethernet cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called qla3xxx.
+
+config QLCNIC
+ tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
+ depends on PCI
+ select FW_LOADER
+ ---help---
+ This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
+ devices.
+
+config QLGE
+ tristate "QLogic QLGE 10Gb Ethernet Driver Support"
+ depends on PCI
+ ---help---
+ This driver supports QLogic ISP8XXX 10Gb Ethernet cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called qlge.
+
+config NETXEN_NIC
+ tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
+ depends on PCI
+ select FW_LOADER
+ ---help---
+ This enables the support for NetXen's Gigabit Ethernet card.
+
+endif # NET_VENDOR_QLOGIC
diff --git a/drivers/net/ethernet/qlogic/Makefile b/drivers/net/ethernet/qlogic/Makefile
new file mode 100644
index 000000000000..b2a283d9ae60
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the QLogic network device drivers.
+#
+
+obj-$(CONFIG_QLA3XXX) += qla3xxx.o
+obj-$(CONFIG_QLCNIC) += qlcnic/
+obj-$(CONFIG_QLGE) += qlge/
+obj-$(CONFIG_NETXEN_NIC) += netxen/
diff --git a/drivers/net/netxen/Makefile b/drivers/net/ethernet/qlogic/netxen/Makefile
index 861a0590b1f4..861a0590b1f4 100644
--- a/drivers/net/netxen/Makefile
+++ b/drivers/net/ethernet/qlogic/netxen/Makefile
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
index f744d291218a..a876dffd7101 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
@@ -53,8 +53,8 @@
#define _NETXEN_NIC_LINUX_MAJOR 4
#define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 76
-#define NETXEN_NIC_LINUX_VERSIONID "4.0.76"
+#define _NETXEN_NIC_LINUX_SUBVERSION 77
+#define NETXEN_NIC_LINUX_VERSIONID "4.0.77"
#define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c))
#define _major(v) (((v) >> 24) & 0xff)
@@ -940,6 +940,11 @@ typedef struct nx_mac_list_s {
uint8_t mac_addr[ETH_ALEN+2];
} nx_mac_list_t;
+struct nx_vlan_ip_list {
+ struct list_head list;
+ u32 ip_addr;
+};
+
/*
* Interrupt coalescing defaults. The defaults are for 1500 MTU. It is
* adjusted based on configured MTU.
@@ -1165,6 +1170,7 @@ struct netxen_adapter {
struct net_device *netdev;
struct pci_dev *pdev;
struct list_head mac_list;
+ struct list_head vlan_ip_list;
spinlock_t tx_clean_lock;
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
index a925392abd6f..a925392abd6f 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
index b34fb74d07e3..e09ea83b8c47 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
@@ -413,9 +413,6 @@ netxen_nic_get_ringparam(struct net_device *dev,
}
ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
-
- ring->rx_mini_max_pending = 0;
- ring->rx_mini_pending = 0;
}
static u32
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
index dc1967c1f312..dc1967c1f312 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
index 3f89e57cae50..3f89e57cae50 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.h
index e2c5b6f2df03..e2c5b6f2df03 100644
--- a/drivers/net/netxen/netxen_nic_hw.h
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.h
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
index e8993a76a080..a8259cc19a63 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
@@ -26,6 +26,7 @@
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/if_vlan.h>
#include "netxen_nic.h"
#include "netxen_nic_hw.h"
@@ -1619,6 +1620,7 @@ netxen_process_lro(struct netxen_adapter *adapter,
int index;
u16 lro_length, length, data_offset;
u32 seq_number;
+ u8 vhdr_len = 0;
if (unlikely(ring > adapter->max_rds_rings))
return NULL;
@@ -1652,8 +1654,10 @@ netxen_process_lro(struct netxen_adapter *adapter,
skb_pull(skb, l2_hdr_offset);
skb->protocol = eth_type_trans(skb, netdev);
- iph = (struct iphdr *)skb->data;
- th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+ if (skb->protocol == htons(ETH_P_8021Q))
+ vhdr_len = VLAN_HLEN;
+ iph = (struct iphdr *)(skb->data + vhdr_len);
+ th = (struct tcphdr *)((skb->data + vhdr_len) + (iph->ihl << 2));
length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
iph->tot_len = htons(length);
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index f574edff7fcb..8cf3173ba488 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -91,7 +91,8 @@ static irqreturn_t netxen_intr(int irq, void *data);
static irqreturn_t netxen_msi_intr(int irq, void *data);
static irqreturn_t netxen_msix_intr(int irq, void *data);
-static void netxen_config_indev_addr(struct net_device *dev, unsigned long);
+static void netxen_free_vlan_ip_list(struct netxen_adapter *);
+static void netxen_restore_indev_addr(struct net_device *dev, unsigned long);
static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *dev,
struct rtnl_link_stats64 *stats);
static int netxen_nic_set_mac(struct net_device *netdev, void *p);
@@ -399,6 +400,63 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter)
}
}
+#define PCI_CAP_ID_GEN 0x10
+
+static void netxen_pcie_strap_init(struct netxen_adapter *adapter)
+{
+ u32 pdevfuncsave;
+ u32 c8c9value = 0;
+ u32 chicken = 0;
+ u32 control = 0;
+ int i, pos;
+ struct pci_dev *pdev;
+
+ pdev = adapter->pdev;
+
+ chicken = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_CHICKEN3));
+ /* clear chicken3.25:24 */
+ chicken &= 0xFCFFFFFF;
+ /*
+ * if gen1 and B0, set F1020 - if gen 2, do nothing
+ * if gen2 set to F1000
+ */
+ pos = pci_find_capability(pdev, PCI_CAP_ID_GEN);
+ if (pos == 0xC0) {
+ pci_read_config_dword(pdev, pos + 0x10, &control);
+ if ((control & 0x000F0000) != 0x00020000) {
+ /* set chicken3.24 if gen1 */
+ chicken |= 0x01000000;
+ }
+ dev_info(&adapter->pdev->dev, "Gen2 strapping detected\n");
+ c8c9value = 0xF1000;
+ } else {
+ /* set chicken3.24 if gen1 */
+ chicken |= 0x01000000;
+ dev_info(&adapter->pdev->dev, "Gen1 strapping detected\n");
+ if (adapter->ahw.revision_id == NX_P3_B0)
+ c8c9value = 0xF1020;
+ else
+ c8c9value = 0;
+ }
+
+ NXWR32(adapter, NETXEN_PCIE_REG(PCIE_CHICKEN3), chicken);
+
+ if (!c8c9value)
+ return;
+
+ pdevfuncsave = pdev->devfn;
+ if (pdevfuncsave & 0x07)
+ return;
+
+ for (i = 0; i < 8; i++) {
+ pci_read_config_dword(pdev, pos + 8, &control);
+ pci_read_config_dword(pdev, pos + 8, &control);
+ pci_write_config_dword(pdev, pos + 8, c8c9value);
+ pdev->devfn++;
+ }
+ pdev->devfn = pdevfuncsave;
+}
+
static void netxen_set_msix_bit(struct pci_dev *pdev, int enable)
{
u32 control;
@@ -523,7 +581,7 @@ static const struct net_device_ops netxen_netdev_ops = {
.ndo_start_xmit = netxen_nic_xmit_frame,
.ndo_get_stats64 = netxen_nic_get_stats,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = netxen_set_multicast_list,
+ .ndo_set_rx_mode = netxen_set_multicast_list,
.ndo_set_mac_address = netxen_nic_set_mac,
.ndo_change_mtu = netxen_nic_change_mtu,
.ndo_tx_timeout = netxen_tx_timeout,
@@ -866,7 +924,7 @@ netxen_start_firmware(struct netxen_adapter *adapter)
if (err < 0)
goto err_out;
if (err == 0)
- goto wait_init;
+ goto pcie_strap_init;
if (first_boot != 0x55555555) {
NXWR32(adapter, CRB_CMDPEG_STATE, 0);
@@ -909,6 +967,10 @@ netxen_start_firmware(struct netxen_adapter *adapter)
| (_NETXEN_NIC_LINUX_SUBVERSION);
NXWR32(adapter, CRB_DRIVER_VERSION, val);
+pcie_strap_init:
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_pcie_strap_init(adapter);
+
wait_init:
/* Handshake with the card before we register the devices. */
err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
@@ -1359,6 +1421,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
spin_lock_init(&adapter->tx_clean_lock);
INIT_LIST_HEAD(&adapter->mac_list);
+ INIT_LIST_HEAD(&adapter->vlan_ip_list);
err = netxen_setup_pci_map(adapter);
if (err)
@@ -1481,6 +1544,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
cancel_work_sync(&adapter->tx_timeout_task);
+ netxen_free_vlan_ip_list(adapter);
netxen_nic_detach(adapter);
nx_decr_dev_ref_cnt(adapter);
@@ -1563,7 +1627,7 @@ static int netxen_nic_attach_func(struct pci_dev *pdev)
if (err)
goto err_out_detach;
- netxen_config_indev_addr(netdev, NETDEV_UP);
+ netxen_restore_indev_addr(netdev, NETDEV_UP);
}
netif_device_attach(netdev);
@@ -1841,13 +1905,13 @@ netxen_map_tx_skb(struct pci_dev *pdev,
frag = &skb_shinfo(skb)->frags[i];
nf = &pbuf->frag_array[i+1];
- map = pci_map_page(pdev, frag->page, frag->page_offset,
- frag->size, PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(pdev, map))
+ 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 = frag->size;
+ nf->length = skb_frag_size(frag);
}
return 0;
@@ -1898,7 +1962,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
for (i = 0; i < (frag_count - NETXEN_MAX_FRAGS_PER_TX); i++) {
frag = &skb_shinfo(skb)->frags[i];
- delta += frag->size;
+ delta += skb_frag_size(frag);
}
if (!__pskb_pull_tail(skb, delta))
@@ -2374,7 +2438,7 @@ netxen_attach_work(struct work_struct *work)
goto done;
}
- netxen_config_indev_addr(netdev, NETDEV_UP);
+ netxen_restore_indev_addr(netdev, NETDEV_UP);
}
netif_device_attach(netdev);
@@ -2848,10 +2912,70 @@ netxen_destip_supported(struct netxen_adapter *adapter)
}
static void
-netxen_config_indev_addr(struct net_device *dev, unsigned long event)
+netxen_free_vlan_ip_list(struct netxen_adapter *adapter)
+{
+ struct nx_vlan_ip_list *cur;
+ struct list_head *head = &adapter->vlan_ip_list;
+
+ while (!list_empty(head)) {
+ cur = list_entry(head->next, struct nx_vlan_ip_list, list);
+ netxen_config_ipaddr(adapter, cur->ip_addr, NX_IP_DOWN);
+ list_del(&cur->list);
+ kfree(cur);
+ }
+
+}
+static void
+netxen_list_config_vlan_ip(struct netxen_adapter *adapter,
+ struct in_ifaddr *ifa, unsigned long event)
+{
+ struct net_device *dev;
+ struct nx_vlan_ip_list *cur, *tmp_cur;
+ struct list_head *head;
+
+ dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
+
+ if (dev == NULL)
+ return;
+
+ if (!is_vlan_dev(dev))
+ return;
+
+ switch (event) {
+ case NX_IP_UP:
+ list_for_each(head, &adapter->vlan_ip_list) {
+ cur = list_entry(head, struct nx_vlan_ip_list, list);
+
+ if (cur->ip_addr == ifa->ifa_address)
+ return;
+ }
+
+ cur = kzalloc(sizeof(struct nx_vlan_ip_list), GFP_ATOMIC);
+ if (cur == NULL) {
+ printk(KERN_ERR "%s: failed to add vlan ip to list\n",
+ adapter->netdev->name);
+ return;
+ }
+
+ cur->ip_addr = ifa->ifa_address;
+ list_add_tail(&cur->list, &adapter->vlan_ip_list);
+ break;
+ case NX_IP_DOWN:
+ list_for_each_entry_safe(cur, tmp_cur,
+ &adapter->vlan_ip_list, list) {
+ if (cur->ip_addr == ifa->ifa_address) {
+ list_del(&cur->list);
+ kfree(cur);
+ break;
+ }
+ }
+ }
+}
+static void
+netxen_config_indev_addr(struct netxen_adapter *adapter,
+ struct net_device *dev, unsigned long event)
{
struct in_device *indev;
- struct netxen_adapter *adapter = netdev_priv(dev);
if (!netxen_destip_supported(adapter))
return;
@@ -2865,10 +2989,12 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event)
case NETDEV_UP:
netxen_config_ipaddr(adapter,
ifa->ifa_address, NX_IP_UP);
+ netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP);
break;
case NETDEV_DOWN:
netxen_config_ipaddr(adapter,
ifa->ifa_address, NX_IP_DOWN);
+ netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN);
break;
default:
break;
@@ -2878,11 +3004,28 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event)
in_dev_put(indev);
}
+static void
+netxen_restore_indev_addr(struct net_device *netdev, unsigned long event)
+
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ struct nx_vlan_ip_list *pos, *tmp_pos;
+ unsigned long ip_event;
+
+ ip_event = (event == NETDEV_UP) ? NX_IP_UP : NX_IP_DOWN;
+ netxen_config_indev_addr(adapter, netdev, event);
+
+ list_for_each_entry_safe(pos, tmp_pos, &adapter->vlan_ip_list, list) {
+ netxen_config_ipaddr(adapter, pos->ip_addr, ip_event);
+ }
+}
+
static int netxen_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct netxen_adapter *adapter;
struct net_device *dev = (struct net_device *)ptr;
+ struct net_device *orig_dev = dev;
recheck:
if (dev == NULL)
@@ -2904,7 +3047,7 @@ recheck:
if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
goto done;
- netxen_config_indev_addr(dev, event);
+ netxen_config_indev_addr(adapter, orig_dev, event);
done:
return NOTIFY_DONE;
}
@@ -2921,7 +3064,7 @@ netxen_inetaddr_event(struct notifier_block *this,
dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
recheck:
- if (dev == NULL || !netif_running(dev))
+ if (dev == NULL)
goto done;
if (dev->priv_flags & IFF_802_1Q_VLAN) {
@@ -2943,9 +3086,11 @@ recheck:
switch (event) {
case NETDEV_UP:
netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP);
+ netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP);
break;
case NETDEV_DOWN:
netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN);
+ netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN);
break;
default:
break;
@@ -2964,7 +3109,10 @@ static struct notifier_block netxen_inetaddr_cb = {
};
#else
static void
-netxen_config_indev_addr(struct net_device *dev, unsigned long event)
+netxen_restore_indev_addr(struct net_device *dev, unsigned long event)
+{ }
+static void
+netxen_free_vlan_ip_list(struct netxen_adapter *adapter)
{ }
#endif
diff --git a/drivers/net/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 2f6914025efc..a4bdff438a5e 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -1650,7 +1650,7 @@ static int ql_mii_setup(struct ql3_adapter *qdev)
SUPPORTED_1000baseT_Half | \
SUPPORTED_1000baseT_Full | \
SUPPORTED_Autoneg | \
- SUPPORTED_TP); \
+ SUPPORTED_TP) \
static u32 ql_supported_modes(struct ql3_adapter *qdev)
{
@@ -2388,11 +2388,10 @@ static int ql_send_map(struct ql3_adapter *qdev,
seg++;
}
- map = pci_map_page(qdev->pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
+ map = skb_frag_dma_map(&qdev->pdev->dev, frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
- err = pci_dma_mapping_error(qdev->pdev, map);
+ err = dma_mapping_error(&qdev->pdev->dev, map);
if (err) {
netdev_err(qdev->ndev,
"PCI mapping frags failed with error: %d\n",
@@ -2402,9 +2401,9 @@ static int ql_send_map(struct ql3_adapter *qdev,
oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
- oal_entry->len = cpu_to_le32(frag->size);
+ oal_entry->len = cpu_to_le32(skb_frag_size(frag));
dma_unmap_addr_set(&tx_cb->map[seg], mapaddr, map);
- dma_unmap_len_set(&tx_cb->map[seg], maplen, frag->size);
+ dma_unmap_len_set(&tx_cb->map[seg], maplen, skb_frag_size(frag));
}
/* Terminate the last segment. */
oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
@@ -3762,7 +3761,6 @@ static const struct net_device_ops ql3xxx_netdev_ops = {
.ndo_open = ql3xxx_open,
.ndo_start_xmit = ql3xxx_send,
.ndo_stop = ql3xxx_close,
- .ndo_set_multicast_list = NULL, /* not allowed on NIC side */
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ql3xxx_set_mac_address,
diff --git a/drivers/net/qla3xxx.h b/drivers/net/ethernet/qlogic/qla3xxx.h
index 73e234366a82..73e234366a82 100644
--- a/drivers/net/qla3xxx.h
+++ b/drivers/net/ethernet/qlogic/qla3xxx.h
diff --git a/drivers/net/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index ddba83ef3f44..ddba83ef3f44 100644
--- a/drivers/net/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index baf646d98fa0..7ed53dbb8646 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -36,8 +36,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 21
-#define QLCNIC_LINUX_VERSIONID "5.0.21"
+#define _QLCNIC_LINUX_SUBVERSION 25
+#define QLCNIC_LINUX_VERSIONID "5.0.25"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -73,6 +73,7 @@
(sizeof(struct cmd_desc_type0) * tx_ring->num_desc)
#define QLCNIC_P3P_A0 0x50
+#define QLCNIC_P3P_C0 0x58
#define QLCNIC_IS_REVISION_P3P(REVISION) (REVISION >= QLCNIC_P3P_A0)
@@ -291,7 +292,8 @@ struct uni_data_desc{
/* Flash Defines and Structures */
#define QLCNIC_FLT_LOCATION 0x3F1000
-#define QLCNIC_FW_IMAGE_REGION 0x74
+#define QLCNIC_B0_FW_IMAGE_REGION 0x74
+#define QLCNIC_C0_FW_IMAGE_REGION 0x97
#define QLCNIC_BOOTLD_REGION 0X72
struct qlcnic_flt_header {
u16 version;
@@ -455,6 +457,8 @@ struct qlcnic_hardware_context {
u16 port_type;
u16 board_type;
+ u8 beacon_state;
+
struct qlcnic_nic_intr_coalesce coal;
struct qlcnic_fw_dump fw_dump;
};
@@ -579,6 +583,7 @@ struct qlcnic_recv_context {
#define QLCNIC_CDRP_CMD_DESTROY_RX_CTX 0x00000008
#define QLCNIC_CDRP_CMD_CREATE_TX_CTX 0x00000009
#define QLCNIC_CDRP_CMD_DESTROY_TX_CTX 0x0000000a
+#define QLCNIC_CDRP_CMD_INTRPT_TEST 0x00000011
#define QLCNIC_CDRP_CMD_SET_MTU 0x00000012
#define QLCNIC_CDRP_CMD_READ_PHY 0x00000013
#define QLCNIC_CDRP_CMD_WRITE_PHY 0x00000014
@@ -911,6 +916,7 @@ struct qlcnic_ipaddr {
#define QLCNIC_PROMISC_DISABLED 0x800
#define QLCNIC_NEED_FLR 0x1000
#define QLCNIC_FW_RESET_OWNER 0x2000
+#define QLCNIC_FW_HANG 0x4000
#define QLCNIC_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
@@ -928,6 +934,7 @@ struct qlcnic_ipaddr {
#define __QLCNIC_START_FW 4
#define __QLCNIC_AER 5
#define __QLCNIC_DIAG_RES_ALLOC 6
+#define __QLCNIC_LED_ENABLE 7
#define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2
@@ -1344,6 +1351,7 @@ enum op_codes {
#define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed
#define QLCNIC_ENABLE_FW_DUMP 0xaddfeed
#define QLCNIC_DISABLE_FW_DUMP 0xbadfeed
+#define QLCNIC_FORCE_FW_RESET 0xdeaddead
struct qlcnic_dump_operations {
enum op_codes opcode;
@@ -1351,6 +1359,18 @@ struct qlcnic_dump_operations {
struct qlcnic_dump_entry *, u32 *);
};
+struct _cdrp_cmd {
+ u32 cmd;
+ u32 arg1;
+ u32 arg2;
+ u32 arg3;
+};
+
+struct qlcnic_cmd_args {
+ struct _cdrp_cmd req;
+ struct _cdrp_cmd rsp;
+};
+
int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config);
@@ -1393,6 +1413,9 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
#define crb_win_unlock(a) \
qlcnic_pcie_sem_unlock((a), 7)
+#define __QLCNIC_MAX_LED_RATE 0xf
+#define __QLCNIC_MAX_LED_STATE 0x2
+
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);
@@ -1460,8 +1483,7 @@ int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]);
/* Functions from qlcnic_main.c */
int qlcnic_reset_context(struct qlcnic_adapter *);
-u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
- u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd);
+void qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *);
void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings);
int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index b0d32ddd2ccb..569a837d2ac4 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -26,42 +26,54 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
return rsp;
}
-u32
-qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
- u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
+void
+qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
{
u32 rsp;
u32 signature;
- u32 rcode = QLCNIC_RCODE_SUCCESS;
struct pci_dev *pdev = adapter->pdev;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
- signature = QLCNIC_CDRP_SIGNATURE_MAKE(pci_fn, version);
+ signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw->pci_func,
+ adapter->fw_hal_version);
/* Acquire semaphore before accessing CRB */
- if (qlcnic_api_lock(adapter))
- return QLCNIC_RCODE_TIMEOUT;
+ if (qlcnic_api_lock(adapter)) {
+ cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT;
+ return;
+ }
QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature);
- QLCWR32(adapter, QLCNIC_ARG1_CRB_OFFSET, arg1);
- QLCWR32(adapter, QLCNIC_ARG2_CRB_OFFSET, arg2);
- QLCWR32(adapter, QLCNIC_ARG3_CRB_OFFSET, arg3);
- QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET, QLCNIC_CDRP_FORM_CMD(cmd));
+ QLCWR32(adapter, QLCNIC_ARG1_CRB_OFFSET, cmd->req.arg1);
+ QLCWR32(adapter, QLCNIC_ARG2_CRB_OFFSET, cmd->req.arg2);
+ QLCWR32(adapter, QLCNIC_ARG3_CRB_OFFSET, cmd->req.arg3);
+ QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET,
+ QLCNIC_CDRP_FORM_CMD(cmd->req.cmd));
rsp = qlcnic_poll_rsp(adapter);
if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
dev_err(&pdev->dev, "card response timeout.\n");
- rcode = QLCNIC_RCODE_TIMEOUT;
+ cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT;
} else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
- rcode = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
+ cmd->rsp.cmd = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
dev_err(&pdev->dev, "failed card response code:0x%x\n",
- rcode);
+ cmd->rsp.cmd);
+ } else if (rsp == QLCNIC_CDRP_RSP_OK) {
+ cmd->rsp.cmd = QLCNIC_RCODE_SUCCESS;
+ if (cmd->rsp.arg2)
+ cmd->rsp.arg2 = QLCRD32(adapter,
+ QLCNIC_ARG2_CRB_OFFSET);
+ if (cmd->rsp.arg3)
+ cmd->rsp.arg3 = QLCRD32(adapter,
+ QLCNIC_ARG3_CRB_OFFSET);
}
+ if (cmd->rsp.arg1)
+ cmd->rsp.arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
/* Release semaphore */
qlcnic_api_unlock(adapter);
- return rcode;
}
static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size)
@@ -81,27 +93,24 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
u16 temp_size;
void *tmp_addr;
u32 version, csum, *template, *tmp_buf;
+ struct qlcnic_cmd_args cmd;
struct qlcnic_hardware_context *ahw;
struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl;
dma_addr_t tmp_addr_t = 0;
ahw = adapter->ahw;
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- 0,
- 0,
- 0,
- QLCNIC_CDRP_CMD_TEMP_SIZE);
- if (err != QLCNIC_RCODE_SUCCESS) {
- err = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_TEMP_SIZE;
+ memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd));
+ qlcnic_issue_cmd(adapter, &cmd);
+ if (cmd.rsp.cmd != QLCNIC_RCODE_SUCCESS) {
dev_info(&adapter->pdev->dev,
- "Can't get template size %d\n", err);
+ "Can't get template size %d\n", cmd.rsp.cmd);
err = -EIO;
return err;
}
- version = QLCRD32(adapter, QLCNIC_ARG3_CRB_OFFSET);
- temp_size = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
+ temp_size = cmd.rsp.arg2;
+ version = cmd.rsp.arg3;
if (!temp_size)
return -EIO;
@@ -112,14 +121,14 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
"Can't get memory for FW dump template\n");
return -ENOMEM;
}
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- LSD(tmp_addr_t),
- MSD(tmp_addr_t),
- temp_size,
- QLCNIC_CDRP_CMD_GET_TEMP_HDR);
-
+ memset(&cmd.rsp, 0, sizeof(struct _cdrp_cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_GET_TEMP_HDR;
+ cmd.req.arg1 = LSD(tmp_addr_t);
+ cmd.req.arg2 = MSD(tmp_addr_t);
+ cmd.req.arg3 = temp_size;
+ qlcnic_issue_cmd(adapter, &cmd);
+
+ err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
"Failed to get mini dump template header %d\n", err);
@@ -155,17 +164,17 @@ error:
int
qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
{
+ struct qlcnic_cmd_args cmd;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_SET_MTU;
+ cmd.req.arg1 = recv_ctx->context_id;
+ cmd.req.arg2 = mtu;
+ cmd.req.arg3 = 0;
if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) {
- if (qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- recv_ctx->context_id,
- mtu,
- 0,
- QLCNIC_CDRP_CMD_SET_MTU)) {
-
+ qlcnic_issue_cmd(adapter, &cmd);
+ if (cmd.rsp.cmd) {
dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
return -EIO;
}
@@ -186,6 +195,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
struct qlcnic_cardrsp_sds_ring *prsp_sds;
struct qlcnic_host_rds_ring *rds_ring;
struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_cmd_args cmd;
dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
u64 phys_addr;
@@ -274,13 +284,13 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
}
phys_addr = hostrq_phys_addr;
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- (u32)(phys_addr >> 32),
- (u32)(phys_addr & 0xffffffff),
- rq_size,
- QLCNIC_CDRP_CMD_CREATE_RX_CTX);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = (u32) (phys_addr >> 32);
+ cmd.req.arg2 = (u32) (phys_addr & 0xffffffff);
+ cmd.req.arg3 = rq_size;
+ cmd.req.cmd = QLCNIC_CDRP_CMD_CREATE_RX_CTX;
+ qlcnic_issue_cmd(adapter, &cmd);
+ err = cmd.rsp.cmd;
if (err) {
dev_err(&adapter->pdev->dev,
"Failed to create rx ctx in firmware%d\n", err);
@@ -326,19 +336,18 @@ out_free_rq:
static void
qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter)
{
+ struct qlcnic_cmd_args cmd;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
- if (qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- recv_ctx->context_id,
- QLCNIC_DESTROY_CTX_RESET,
- 0,
- QLCNIC_CDRP_CMD_DESTROY_RX_CTX)) {
-
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = recv_ctx->context_id;
+ cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET;
+ cmd.req.arg3 = 0;
+ cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_RX_CTX;
+ qlcnic_issue_cmd(adapter, &cmd);
+ if (cmd.rsp.cmd)
dev_err(&adapter->pdev->dev,
"Failed to destroy rx ctx in firmware\n");
- }
recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED;
}
@@ -352,6 +361,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
void *rq_addr, *rsp_addr;
size_t rq_size, rsp_size;
u32 temp;
+ struct qlcnic_cmd_args cmd;
int err;
u64 phys_addr;
dma_addr_t rq_phys_addr, rsp_phys_addr;
@@ -401,13 +411,13 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
phys_addr = rq_phys_addr;
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- (u32)(phys_addr >> 32),
- ((u32)phys_addr & 0xffffffff),
- rq_size,
- QLCNIC_CDRP_CMD_CREATE_TX_CTX);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = (u32)(phys_addr >> 32);
+ cmd.req.arg2 = ((u32)phys_addr & 0xffffffff);
+ cmd.req.arg3 = rq_size;
+ cmd.req.cmd = QLCNIC_CDRP_CMD_CREATE_TX_CTX;
+ qlcnic_issue_cmd(adapter, &cmd);
+ err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS) {
temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
@@ -433,29 +443,30 @@ out_free_rq:
static void
qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter)
{
- if (qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- adapter->tx_context_id,
- QLCNIC_DESTROY_CTX_RESET,
- 0,
- QLCNIC_CDRP_CMD_DESTROY_TX_CTX)) {
-
+ struct qlcnic_cmd_args cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = adapter->tx_context_id;
+ cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET;
+ cmd.req.arg3 = 0;
+ cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_TX_CTX;
+ qlcnic_issue_cmd(adapter, &cmd);
+ if (cmd.rsp.cmd)
dev_err(&adapter->pdev->dev,
"Failed to destroy tx ctx in firmware\n");
- }
}
int
qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config)
{
- return qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- config,
- 0,
- 0,
- QLCNIC_CDRP_CMD_CONFIG_PORT);
+ struct qlcnic_cmd_args cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = config;
+ cmd.req.cmd = QLCNIC_CDRP_CMD_CONFIG_PORT;
+ qlcnic_issue_cmd(adapter, &cmd);
+
+ return cmd.rsp.cmd;
}
int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
@@ -620,20 +631,17 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
{
int err;
- u32 arg1;
+ struct qlcnic_cmd_args cmd;
- arg1 = adapter->ahw->pci_func | BIT_8;
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- arg1,
- 0,
- 0,
- QLCNIC_CDRP_CMD_MAC_ADDRESS);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = adapter->ahw->pci_func | BIT_8;
+ cmd.req.cmd = QLCNIC_CDRP_CMD_MAC_ADDRESS;
+ cmd.rsp.arg1 = cmd.rsp.arg2 = 1;
+ qlcnic_issue_cmd(adapter, &cmd);
+ err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS)
- qlcnic_fetch_mac(adapter, QLCNIC_ARG1_CRB_OFFSET,
- QLCNIC_ARG2_CRB_OFFSET, 0, mac);
+ qlcnic_fetch_mac(adapter, cmd.rsp.arg1, cmd.rsp.arg2, 0, mac);
else {
dev_err(&adapter->pdev->dev,
"Failed to get mac address%d\n", err);
@@ -651,6 +659,7 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
dma_addr_t nic_dma_t;
struct qlcnic_info *nic_info;
void *nic_info_addr;
+ struct qlcnic_cmd_args cmd;
size_t nic_size = sizeof(struct qlcnic_info);
nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
@@ -660,13 +669,13 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
memset(nic_info_addr, 0, nic_size);
nic_info = nic_info_addr;
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- MSD(nic_dma_t),
- LSD(nic_dma_t),
- (func_id << 16 | nic_size),
- QLCNIC_CDRP_CMD_GET_NIC_INFO);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_GET_NIC_INFO;
+ cmd.req.arg1 = MSD(nic_dma_t);
+ cmd.req.arg2 = LSD(nic_dma_t);
+ cmd.req.arg3 = (func_id << 16 | nic_size);
+ qlcnic_issue_cmd(adapter, &cmd);
+ err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS) {
npar_info->pci_func = le16_to_cpu(nic_info->pci_func);
@@ -705,6 +714,7 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
int err = -EIO;
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);
@@ -730,13 +740,13 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw);
nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw);
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- MSD(nic_dma_t),
- LSD(nic_dma_t),
- ((nic->pci_func << 16) | nic_size),
- QLCNIC_CDRP_CMD_SET_NIC_INFO);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_SET_NIC_INFO;
+ cmd.req.arg1 = MSD(nic_dma_t);
+ cmd.req.arg2 = LSD(nic_dma_t);
+ cmd.req.arg3 = ((nic->pci_func << 16) | nic_size);
+ qlcnic_issue_cmd(adapter, &cmd);
+ err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
@@ -754,6 +764,7 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
struct qlcnic_pci_info *pci_info)
{
int err = 0, i;
+ struct qlcnic_cmd_args cmd;
dma_addr_t pci_info_dma_t;
struct qlcnic_pci_info *npar;
void *pci_info_addr;
@@ -767,13 +778,13 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
memset(pci_info_addr, 0, pci_size);
npar = pci_info_addr;
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- MSD(pci_info_dma_t),
- LSD(pci_info_dma_t),
- pci_size,
- QLCNIC_CDRP_CMD_GET_PCI_INFO);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_GET_PCI_INFO;
+ cmd.req.arg1 = MSD(pci_info_dma_t);
+ cmd.req.arg2 = LSD(pci_info_dma_t);
+ cmd.req.arg3 = pci_size;
+ qlcnic_issue_cmd(adapter, &cmd);
+ err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS) {
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
@@ -805,6 +816,7 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
{
int err = -EIO;
u32 arg1;
+ struct qlcnic_cmd_args cmd;
if (adapter->op_mode != QLCNIC_MGMT_FUNC ||
!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
@@ -813,13 +825,11 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
arg1 = id | (enable_mirroring ? BIT_4 : 0);
arg1 |= pci_func << 8;
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- arg1,
- 0,
- 0,
- QLCNIC_CDRP_CMD_SET_PORTMIRRORING);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_SET_PORTMIRRORING;
+ cmd.req.arg1 = arg1;
+ qlcnic_issue_cmd(adapter, &cmd);
+ err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
@@ -842,6 +852,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
dma_addr_t stats_dma_t;
void *stats_addr;
u32 arg1;
+ struct qlcnic_cmd_args cmd;
int err;
if (esw_stats == NULL)
@@ -865,13 +876,13 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
arg1 |= rx_tx << 15 | stats_size << 16;
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- arg1,
- MSD(stats_dma_t),
- LSD(stats_dma_t),
- QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_STATS;
+ cmd.req.arg1 = arg1;
+ cmd.req.arg2 = MSD(stats_dma_t);
+ cmd.req.arg3 = LSD(stats_dma_t);
+ qlcnic_issue_cmd(adapter, &cmd);
+ err = cmd.rsp.cmd;
if (!err) {
stats = stats_addr;
@@ -952,6 +963,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)
return -EIO;
@@ -972,13 +984,11 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
arg1 |= BIT_14 | rx_tx << 15;
- return qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- arg1,
- 0,
- 0,
- QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_STATS;
+ cmd.req.arg1 = arg1;
+ qlcnic_issue_cmd(adapter, &cmd);
+ return cmd.rsp.cmd;
err_ret:
dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d"
@@ -991,19 +1001,19 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
u32 *arg1, u32 *arg2)
{
int err = -EIO;
+ struct qlcnic_cmd_args cmd;
u8 pci_func;
pci_func = (*arg1 >> 8);
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- *arg1,
- 0,
- 0,
- QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG);
+
+ cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG;
+ cmd.req.arg1 = *arg1;
+ cmd.rsp.arg1 = cmd.rsp.arg2 = 1;
+ qlcnic_issue_cmd(adapter, &cmd);
+ *arg1 = cmd.rsp.arg1;
+ *arg2 = cmd.rsp.arg2;
+ err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS) {
- *arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
- *arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
dev_info(&adapter->pdev->dev,
"eSwitch port config for pci func %d\n", pci_func);
} else {
@@ -1025,6 +1035,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
{
int err = -EIO;
u32 arg1, arg2 = 0;
+ struct qlcnic_cmd_args cmd;
u8 pci_func;
if (adapter->op_mode != QLCNIC_MGMT_FUNC)
@@ -1071,14 +1082,13 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
return err;
}
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw->pci_func,
- adapter->fw_hal_version,
- arg1,
- arg2,
- 0,
- QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH;
+ cmd.req.arg1 = arg1;
+ cmd.req.arg2 = arg2;
+ qlcnic_issue_cmd(adapter, &cmd);
+ err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
"Failed to configure eswitch pci func %d\n", pci_func);
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 72a723d5c988..8aa1c6e8667b 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -418,9 +418,6 @@ qlcnic_get_ringparam(struct net_device *dev,
ring->rx_max_pending = adapter->max_rxd;
ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
-
- ring->rx_mini_max_pending = 0;
- ring->rx_mini_pending = 0;
}
static u32
@@ -659,6 +656,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int max_sds_rings = adapter->max_sds_rings;
int ret;
+ struct qlcnic_cmd_args cmd;
if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
return -EIO;
@@ -668,9 +666,12 @@ static int qlcnic_irq_test(struct net_device *netdev)
goto clear_it;
adapter->diag_cnt = 0;
- ret = qlcnic_issue_cmd(adapter, adapter->ahw->pci_func,
- adapter->fw_hal_version, adapter->ahw->pci_func,
- 0, 0, 0x00000011);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST;
+ cmd.req.arg1 = adapter->ahw->pci_func;
+ qlcnic_issue_cmd(adapter, &cmd);
+ ret = cmd.rsp.cmd;
+
if (ret)
goto done;
@@ -710,7 +711,7 @@ int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
}
-static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter)
+static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
{
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
@@ -736,13 +737,18 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter)
dev_kfree_skb_any(skb);
if (!adapter->diag_cnt)
- dev_warn(&adapter->pdev->dev, "LB Test: %dth packet"
- " not recevied\n", i + 1);
+ QLCDB(adapter, DRV,
+ "LB Test: packet #%d was not received\n", i + 1);
else
cnt++;
}
if (cnt != i) {
dev_warn(&adapter->pdev->dev, "LB Test failed\n");
+ if (mode != QLCNIC_ILB_MODE) {
+ dev_warn(&adapter->pdev->dev,
+ "WARNING: Please make sure external"
+ "loopback connector is plugged in\n");
+ }
return -1;
}
return 0;
@@ -761,7 +767,7 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
return -EOPNOTSUPP;
}
- netdev_info(netdev, "%s loopback test in progress\n",
+ QLCDB(adapter, DRV, "%s loopback test in progress\n",
mode == QLCNIC_ILB_MODE ? "internal" : "external");
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
netdev_warn(netdev, "Loopback test not supported for non "
@@ -797,7 +803,7 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
}
} while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
- ret = qlcnic_do_lb_test(adapter);
+ ret = qlcnic_do_lb_test(adapter, mode);
qlcnic_clear_lb_mode(adapter);
@@ -832,7 +838,6 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
if (data[3])
eth_test->flags |= ETH_TEST_FL_FAILED;
-
if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
if (data[4])
@@ -930,28 +935,49 @@ static int qlcnic_set_led(struct net_device *dev,
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
int max_sds_rings = adapter->max_sds_rings;
+ int err = -EIO, active = 1;
+
+ if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+ netdev_warn(dev, "LED test not supported for non "
+ "privilege function\n");
+ return -EOPNOTSUPP;
+ }
switch (state) {
case ETHTOOL_ID_ACTIVE:
- if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
- if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
- return -EIO;
+ if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
+ return -EBUSY;
+
+ if (test_bit(__QLCNIC_RESETTING, &adapter->state))
+ break;
- if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) {
- clear_bit(__QLCNIC_RESETTING, &adapter->state);
- return -EIO;
- }
+ if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+ if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
+ break;
set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
}
- if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0)
- return 0;
+ if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) {
+ err = 0;
+ break;
+ }
dev_err(&adapter->pdev->dev,
"Failed to set LED blink state.\n");
break;
case ETHTOOL_ID_INACTIVE:
+ active = 0;
+
+ if (test_bit(__QLCNIC_RESETTING, &adapter->state))
+ break;
+
+ if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+ if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
+ break;
+ set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
+ }
+
if (adapter->nic_ops->config_led(adapter, 0, 0xf))
dev_err(&adapter->pdev->dev,
"Failed to reset LED blink state.\n");
@@ -962,12 +988,13 @@ static int qlcnic_set_led(struct net_device *dev,
return -EINVAL;
}
- if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) {
+ if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
qlcnic_diag_free_res(dev, max_sds_rings);
- clear_bit(__QLCNIC_RESETTING, &adapter->state);
- }
- return -EIO;
+ if (!active || err)
+ clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
+
+ return err;
}
static void
@@ -1105,7 +1132,10 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
- dump->len = fw_dump->tmpl_hdr->size + fw_dump->size;
+ if (fw_dump->clr)
+ dump->len = fw_dump->tmpl_hdr->size + fw_dump->size;
+ else
+ dump->len = 0;
dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
dump->version = adapter->fw_version;
return 0;
@@ -1152,7 +1182,8 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
- if (val->flag == QLCNIC_FORCE_FW_DUMP_KEY) {
+ switch (val->flag) {
+ case QLCNIC_FORCE_FW_DUMP_KEY:
if (!fw_dump->enable) {
netdev_info(netdev, "FW dump not enabled\n");
return ret;
@@ -1164,17 +1195,25 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
}
netdev_info(netdev, "Forcing a FW dump\n");
qlcnic_dev_request_reset(adapter);
- } else if (val->flag == QLCNIC_DISABLE_FW_DUMP) {
+ break;
+ case QLCNIC_DISABLE_FW_DUMP:
if (fw_dump->enable) {
netdev_info(netdev, "Disabling FW dump\n");
fw_dump->enable = 0;
}
- } else if (val->flag == QLCNIC_ENABLE_FW_DUMP) {
+ break;
+ case QLCNIC_ENABLE_FW_DUMP:
if (!fw_dump->enable && fw_dump->tmpl_hdr) {
netdev_info(netdev, "Enabling FW dump\n");
fw_dump->enable = 1;
}
- } else {
+ break;
+ case QLCNIC_FORCE_FW_RESET:
+ netdev_info(netdev, "Forcing a FW reset\n");
+ qlcnic_dev_request_reset(adapter);
+ adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
+ break;
+ default:
if (val->flag > QLCNIC_DUMP_MASK_MAX ||
val->flag < QLCNIC_DUMP_MASK_MIN) {
netdev_info(netdev,
diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index d14506f764e0..a52819303d1b 100644
--- a/drivers/net/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -407,7 +407,9 @@ enum {
#define QLCNIC_CRB_SRE QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_SRE)
#define QLCNIC_CRB_ROMUSB \
QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_ROMUSB)
+#define QLCNIC_CRB_EPG QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_EG)
#define QLCNIC_CRB_I2Q QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_I2Q)
+#define QLCNIC_CRB_TIMER QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_TIMR)
#define QLCNIC_CRB_I2C0 QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_I2C0)
#define QLCNIC_CRB_SMB QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_SMB)
#define QLCNIC_CRB_MAX QLCNIC_PCI_CRB_WINDOW(64)
@@ -609,6 +611,7 @@ enum {
QLCNIC_TEMP_PANIC /* Fatal error, hardware has shut down. */
};
+
/* Lock IDs for PHY lock */
#define PHY_LOCK_DRIVER 0x44524956
@@ -723,7 +726,8 @@ enum {
#define QLCNIC_RCODE_DRIVER_CAN_RELOAD BIT_30
#define QLCNIC_RCODE_FATAL_ERROR BIT_31
#define QLCNIC_FWERROR_PEGNUM(code) ((code) & 0xff)
-#define QLCNIC_FWERROR_CODE(code) ((code >> 8) & 0xfffff)
+#define QLCNIC_FWERROR_CODE(code) ((code >> 8) & 0x1fffff)
+#define QLCNIC_FWERROR_FAN_FAILURE 0x16
#define FW_POLL_DELAY (1 * HZ)
#define FW_FAIL_THRESH 2
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 4055c218ef2a..bcb81e47543a 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -566,7 +566,7 @@ int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
return -EIO;
if (qlcnic_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL)) {
- qlcnic_set_fw_loopback(adapter, mode);
+ qlcnic_set_fw_loopback(adapter, 0);
return -EIO;
}
@@ -1773,8 +1773,8 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
goto error;
} else {
fw_dump->clr = 1;
- snprintf(mesg, sizeof(mesg), "FW dump for device: %d\n",
- adapter->pdev->devfn);
+ 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 */
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index ee8a3982395e..38669583840c 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -422,9 +422,53 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
QLCWR32(adapter, CRB_CMDPEG_STATE, 0);
QLCWR32(adapter, CRB_RCVPEG_STATE, 0);
- qlcnic_rom_lock(adapter);
- QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff);
+ /* Halt all the indiviual PEGs and other blocks */
+ /* disable all I2Q */
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x10, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x14, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x18, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x1c, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x20, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x24, 0x0);
+
+ /* disable all niu interrupts */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0x40, 0xff);
+ /* disable xge rx/tx */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0x70000, 0x00);
+ /* disable xg1 rx/tx */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0x80000, 0x00);
+ /* disable sideband mac */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0x90000, 0x00);
+ /* disable ap0 mac */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0xa0000, 0x00);
+ /* disable ap1 mac */
+ QLCWR32(adapter, QLCNIC_CRB_NIU + 0xb0000, 0x00);
+
+ /* halt sre */
+ val = QLCRD32(adapter, QLCNIC_CRB_SRE + 0x1000);
+ QLCWR32(adapter, QLCNIC_CRB_SRE + 0x1000, val & (~(0x1)));
+
+ /* halt epg */
+ QLCWR32(adapter, QLCNIC_CRB_EPG + 0x1300, 0x1);
+
+ /* halt timers */
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x0, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x8, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x10, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x18, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x100, 0x0);
+ QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x200, 0x0);
+ /* halt pegs */
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c, 1);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c, 1);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c, 1);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c, 1);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c, 1);
+ msleep(20);
+
qlcnic_rom_unlock(adapter);
+ /* big hammer don't reset CAM block on reset */
+ QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff);
/* Init HW CRB block */
if (qlcnic_rom_fast_read(adapter, 0, &n) != 0 || (n != 0xcafecafe) ||
@@ -522,8 +566,10 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x8, 0);
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0xc, 0);
msleep(1);
+
QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
+
return 0;
}
@@ -686,7 +732,13 @@ qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter)
u32 ver = -1, min_ver;
int ret;
- ret = qlcnic_get_flt_entry(adapter, QLCNIC_FW_IMAGE_REGION, &fw_entry);
+ if (adapter->ahw->revision_id == QLCNIC_P3P_C0)
+ ret = qlcnic_get_flt_entry(adapter, QLCNIC_C0_FW_IMAGE_REGION,
+ &fw_entry);
+ else
+ ret = qlcnic_get_flt_entry(adapter, QLCNIC_B0_FW_IMAGE_REGION,
+ &fw_entry);
+
if (!ret)
/* 0-4:-signature, 4-8:-fw version */
qlcnic_rom_fast_read(adapter, fw_entry.start_addr + 4,
@@ -1056,7 +1108,8 @@ qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter)
int
qlcnic_need_fw_reset(struct qlcnic_adapter *adapter)
{
- if (qlcnic_check_fw_hearbeat(adapter)) {
+ if ((adapter->flags & QLCNIC_FW_HANG) ||
+ qlcnic_check_fw_hearbeat(adapter)) {
qlcnic_rom_lock_recovery(adapter);
return 1;
}
@@ -1778,14 +1831,14 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
spin_unlock(&rds_ring->lock);
}
-static void dump_skb(struct sk_buff *skb)
+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++) {
- printk(KERN_INFO "%02x ", data[i]);
+ QLCDB(adapter, DRV, "%02x ", data[i]);
if ((i & 0x0f) == 8)
printk(KERN_INFO "\n");
}
@@ -1828,7 +1881,7 @@ void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
adapter->diag_cnt++;
else
- dump_skb(skb);
+ dump_skb(skb, adapter);
dev_kfree_skb_any(skb);
adapter->stats.rx_pkts++;
@@ -1882,8 +1935,8 @@ qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
u32 mac_low, mac_high;
int i;
- mac_low = QLCRD32(adapter, off1);
- mac_high = QLCRD32(adapter, off2);
+ mac_low = off1;
+ mac_high = off2;
if (alt_mac) {
mac_low |= (mac_low >> 16) | (mac_high << 16);
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 5ca1b562443c..0bd163828e33 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -325,7 +325,7 @@ static const struct net_device_ops qlcnic_netdev_ops = {
.ndo_start_xmit = qlcnic_xmit_frame,
.ndo_get_stats = qlcnic_get_stats,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = qlcnic_set_multi,
+ .ndo_set_rx_mode = qlcnic_set_multi,
.ndo_set_mac_address = qlcnic_set_mac,
.ndo_change_mtu = qlcnic_change_mtu,
.ndo_fix_features = qlcnic_fix_features,
@@ -643,8 +643,11 @@ static void get_brd_name(struct qlcnic_adapter *adapter, char *name)
static void
qlcnic_check_options(struct qlcnic_adapter *adapter)
{
- u32 fw_major, fw_minor, fw_build;
+ u32 fw_major, fw_minor, fw_build, prev_fw_version;
struct pci_dev *pdev = adapter->pdev;
+ struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+
+ prev_fw_version = adapter->fw_version;
fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
@@ -652,6 +655,17 @@ 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 (fw_dump->tmpl_hdr == NULL ||
+ adapter->fw_version > prev_fw_version) {
+ if (fw_dump->tmpl_hdr)
+ vfree(fw_dump->tmpl_hdr);
+ if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
+ dev_info(&pdev->dev,
+ "Supports FW dump capability\n");
+ }
+ }
+
dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
fw_major, fw_minor, fw_build);
if (adapter->ahw->port_type == QLCNIC_XGBE) {
@@ -1610,12 +1624,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_decr_ref;
}
- /* Get FW dump template and store it */
- if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC)
- if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
- dev_info(&pdev->dev,
- "Supports FW dump capability\n");
-
if (qlcnic_read_mac_addr(adapter))
dev_warn(&pdev->dev, "failed to read mac addr\n");
@@ -2127,13 +2135,13 @@ qlcnic_map_tx_skb(struct pci_dev *pdev,
frag = &skb_shinfo(skb)->frags[i];
nf = &pbuf->frag_array[i+1];
- map = pci_map_page(pdev, frag->page, frag->page_offset,
- frag->size, PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(pdev, map))
+ 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 = frag->size;
+ nf->length = skb_frag_size(frag);
}
return 0;
@@ -2213,7 +2221,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
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_shinfo(skb)->frags[i].size;
+ delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
if (!__pskb_pull_tail(skb, delta))
goto drop_packet;
@@ -2682,6 +2690,7 @@ qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
qlcnic_api_unlock(adapter);
err:
adapter->fw_fail_cnt = 0;
+ adapter->flags &= ~QLCNIC_FW_HANG;
clear_bit(__QLCNIC_START_FW, &adapter->state);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
}
@@ -2831,8 +2840,15 @@ qlcnic_fwinit_work(struct work_struct *work)
goto wait_npar;
}
+ if (dev_state == QLCNIC_DEV_INITIALIZING ||
+ dev_state == QLCNIC_DEV_READY) {
+ dev_info(&adapter->pdev->dev, "Detected state change from "
+ "DEV_NEED_RESET, skipping ack check\n");
+ goto skip_ack_check;
+ }
+
if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
- dev_err(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
+ dev_info(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
adapter->reset_ack_timeo);
goto skip_ack_check;
}
@@ -2859,6 +2875,7 @@ skip_ack_check:
(adapter->flags & QLCNIC_FW_RESET_OWNER)) {
QLCDB(adapter, DRV, "Take FW dump\n");
qlcnic_dump_fw(adapter);
+ adapter->flags |= QLCNIC_FW_HANG;
}
rtnl_unlock();
@@ -2918,15 +2935,36 @@ qlcnic_detach_work(struct work_struct *work)
status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
- if (status & QLCNIC_RCODE_FATAL_ERROR)
+ if (status & QLCNIC_RCODE_FATAL_ERROR) {
+ dev_err(&adapter->pdev->dev,
+ "Detaching the device: peg halt status1=0x%x\n",
+ status);
+
+ if (QLCNIC_FWERROR_CODE(status) == QLCNIC_FWERROR_FAN_FAILURE) {
+ dev_err(&adapter->pdev->dev,
+ "On board active cooling fan failed. "
+ "Device has been halted.\n");
+ dev_err(&adapter->pdev->dev,
+ "Replace the adapter.\n");
+ }
+
goto err_ret;
+ }
- if (adapter->temp == QLCNIC_TEMP_PANIC)
+ if (adapter->temp == QLCNIC_TEMP_PANIC) {
+ dev_err(&adapter->pdev->dev, "Detaching the device: temp=%d\n",
+ adapter->temp);
goto err_ret;
+ }
+
/* Dont ack if this instance is the reset owner */
if (!(adapter->flags & QLCNIC_FW_RESET_OWNER)) {
- if (qlcnic_set_drv_state(adapter, adapter->dev_state))
+ if (qlcnic_set_drv_state(adapter, adapter->dev_state)) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to set driver state,"
+ "detaching the device.\n");
goto err_ret;
+ }
}
adapter->fw_wait_cnt = 0;
@@ -2936,8 +2974,6 @@ qlcnic_detach_work(struct work_struct *work)
return;
err_ret:
- dev_err(&adapter->pdev->dev, "detach failed; status=%d temp=%d\n",
- status, adapter->temp);
netif_device_attach(netdev);
qlcnic_clr_all_drv_state(adapter, 1);
}
@@ -3046,6 +3082,7 @@ attach:
done:
netif_device_attach(netdev);
adapter->fw_fail_cnt = 0;
+ adapter->flags &= ~QLCNIC_FW_HANG;
clear_bit(__QLCNIC_RESETTING, &adapter->state);
if (!qlcnic_clr_drv_state(adapter))
@@ -3057,7 +3094,7 @@ static int
qlcnic_check_health(struct qlcnic_adapter *adapter)
{
u32 state = 0, heartbeat;
- struct net_device *netdev = adapter->netdev;
+ u32 peg_status;
if (qlcnic_check_temp(adapter))
goto detach;
@@ -3090,13 +3127,31 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
if (++adapter->fw_fail_cnt < FW_FAIL_THRESH)
return 0;
+ adapter->flags |= QLCNIC_FW_HANG;
+
qlcnic_dev_request_reset(adapter);
if (auto_fw_reset)
clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
- dev_info(&netdev->dev, "firmware hang detected\n");
-
+ dev_err(&adapter->pdev->dev, "firmware hang detected\n");
+ dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n"
+ "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"
+ "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"
+ "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"
+ "PEG_NET_4_PC: 0x%x\n",
+ QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1),
+ QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS2),
+ QLCRD32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c),
+ QLCRD32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c),
+ QLCRD32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c),
+ QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c),
+ QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c));
+ peg_status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
+ if (LSW(MSB(peg_status)) == 0x67)
+ dev_err(&adapter->pdev->dev,
+ "Firmware aborted with error code 0x00006700. "
+ "Device is being reset.\n");
detach:
adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
QLCNIC_DEV_NEED_RESET;
@@ -3423,6 +3478,107 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
}
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)
{
@@ -4119,6 +4275,8 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
return;
if (device_create_file(dev, &dev_attr_diag_mode))
dev_info(dev, "failed to create diag_mode sysfs entry\n");
+ if (device_create_file(dev, &dev_attr_beacon))
+ dev_info(dev, "failed to create beacon sysfs entry");
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))
@@ -4149,6 +4307,7 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
device_remove_file(dev, &dev_attr_diag_mode);
+ device_remove_file(dev, &dev_attr_beacon);
device_remove_bin_file(dev, &bin_attr_crb);
device_remove_bin_file(dev, &bin_attr_mem);
device_remove_bin_file(dev, &bin_attr_pci_config);
diff --git a/drivers/net/qlge/Makefile b/drivers/net/ethernet/qlogic/qlge/Makefile
index 8a197658d76f..8a197658d76f 100644
--- a/drivers/net/qlge/Makefile
+++ b/drivers/net/ethernet/qlogic/qlge/Makefile
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h
index 8731f79c9efc..8731f79c9efc 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/ethernet/qlogic/qlge/qlge.h
diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
index fca804f36d61..fca804f36d61 100644
--- a/drivers/net/qlge/qlge_dbg.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
index 9b67bfea035f..9b67bfea035f 100644
--- a/drivers/net/qlge/qlge_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index f07e96ec8843..c92afcd912e2 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -1431,12 +1431,10 @@ static int ql_map_send(struct ql_adapter *qdev,
map_idx++;
}
- map =
- pci_map_page(qdev->pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
+ map = skb_frag_dma_map(&qdev->pdev->dev, frag, 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
- err = pci_dma_mapping_error(qdev->pdev, map);
+ err = dma_mapping_error(&qdev->pdev->dev, map);
if (err) {
netif_err(qdev, tx_queued, qdev->ndev,
"PCI mapping frags failed with error: %d.\n",
@@ -1445,10 +1443,10 @@ static int ql_map_send(struct ql_adapter *qdev,
}
tbd->addr = cpu_to_le64(map);
- tbd->len = cpu_to_le32(frag->size);
+ tbd->len = cpu_to_le32(skb_frag_size(frag));
dma_unmap_addr_set(&tx_ring_desc->map[map_idx], mapaddr, map);
dma_unmap_len_set(&tx_ring_desc->map[map_idx], maplen,
- frag->size);
+ skb_frag_size(frag));
}
/* Save the number of segments we've mapped. */
@@ -1477,8 +1475,6 @@ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev,
{
struct sk_buff *skb;
struct bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring);
- struct skb_frag_struct *rx_frag;
- int nr_frags;
struct napi_struct *napi = &rx_ring->napi;
napi->dev = qdev->ndev;
@@ -1492,12 +1488,10 @@ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev,
return;
}
prefetch(lbq_desc->p.pg_chunk.va);
- rx_frag = skb_shinfo(skb)->frags;
- nr_frags = skb_shinfo(skb)->nr_frags;
- rx_frag += nr_frags;
- rx_frag->page = lbq_desc->p.pg_chunk.page;
- rx_frag->page_offset = lbq_desc->p.pg_chunk.offset;
- rx_frag->size = length;
+ __skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+ lbq_desc->p.pg_chunk.page,
+ lbq_desc->p.pg_chunk.offset,
+ length);
skb->len += length;
skb->data_len += length;
@@ -4676,7 +4670,7 @@ static const struct net_device_ops qlge_netdev_ops = {
.ndo_start_xmit = qlge_send,
.ndo_change_mtu = qlge_change_mtu,
.ndo_get_stats = qlge_get_stats,
- .ndo_set_multicast_list = qlge_set_multicast_list,
+ .ndo_set_rx_mode = qlge_set_multicast_list,
.ndo_set_mac_address = qlge_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = qlge_tx_timeout,
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/ethernet/qlogic/qlge/qlge_mpi.c
index ff2bf8a4e247..ff2bf8a4e247 100644
--- a/drivers/net/qlge/qlge_mpi.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_mpi.c
diff --git a/drivers/net/ethernet/racal/Kconfig b/drivers/net/ethernet/racal/Kconfig
new file mode 100644
index 000000000000..01969e0a9c68
--- /dev/null
+++ b/drivers/net/ethernet/racal/Kconfig
@@ -0,0 +1,33 @@
+#
+# Racal-Interlan device configuration
+#
+
+config NET_VENDOR_RACAL
+ bool "Racal-Interlan (Micom) NI devices"
+ default y
+ depends on ISA
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, such
+ as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about NI cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_RACAL
+
+config NI5010
+ tristate "NI5010 support (EXPERIMENTAL)"
+ depends on ISA && EXPERIMENTAL && BROKEN_ON_SMP
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Note that this is still
+ experimental code.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ni5010.
+
+endif # NET_VENDOR_RACAL
diff --git a/drivers/net/ethernet/racal/Makefile b/drivers/net/ethernet/racal/Makefile
new file mode 100644
index 000000000000..1e210ca1d78b
--- /dev/null
+++ b/drivers/net/ethernet/racal/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Racal-Interlan network device drivers.
+#
+
+obj-$(CONFIG_NI5010) += ni5010.o
diff --git a/drivers/net/ni5010.c b/drivers/net/ethernet/racal/ni5010.c
index 4d3f2e2b28bd..072810da9a37 100644
--- a/drivers/net/ni5010.c
+++ b/drivers/net/ethernet/racal/ni5010.c
@@ -192,7 +192,7 @@ static const struct net_device_ops ni5010_netdev_ops = {
.ndo_open = ni5010_open,
.ndo_stop = ni5010_close,
.ndo_start_xmit = ni5010_send_packet,
- .ndo_set_multicast_list = ni5010_set_multicast_list,
+ .ndo_set_rx_mode = ni5010_set_multicast_list,
.ndo_tx_timeout = ni5010_timeout,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ni5010.h b/drivers/net/ethernet/racal/ni5010.h
index e10e717fcd76..e10e717fcd76 100644
--- a/drivers/net/ni5010.h
+++ b/drivers/net/ethernet/racal/ni5010.h
diff --git a/drivers/net/ethernet/rdc/Kconfig b/drivers/net/ethernet/rdc/Kconfig
new file mode 100644
index 000000000000..c8ba4b3494c1
--- /dev/null
+++ b/drivers/net/ethernet/rdc/Kconfig
@@ -0,0 +1,35 @@
+#
+# RDC network device configuration
+#
+
+config NET_VENDOR_RDC
+ bool "RDC devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about RDC cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_RDC
+
+config R6040
+ tristate "RDC R6040 Fast Ethernet Adapter support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ select PHYLIB
+ ---help---
+ This is a driver for the R6040 Fast Ethernet MACs found in the
+ the RDC R-321x System-on-chips.
+
+ To compile this driver as a module, choose M here: the module
+ will be called r6040. This is recommended.
+
+endif # NET_VENDOR_RDC
diff --git a/drivers/net/ethernet/rdc/Makefile b/drivers/net/ethernet/rdc/Makefile
new file mode 100644
index 000000000000..8d51fd2d07fc
--- /dev/null
+++ b/drivers/net/ethernet/rdc/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the RDC network device drivers.
+#
+
+obj-$(CONFIG_R6040) += r6040.o
diff --git a/drivers/net/r6040.c b/drivers/net/ethernet/rdc/r6040.c
index b64fcee483aa..1fc01ca72b46 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/ethernet/rdc/r6040.c
@@ -49,8 +49,8 @@
#include <asm/processor.h>
#define DRV_NAME "r6040"
-#define DRV_VERSION "0.27"
-#define DRV_RELDATE "23Feb2011"
+#define DRV_VERSION "0.28"
+#define DRV_RELDATE "07Oct2011"
/* PHY CHIP Address */
#define PHY1_ADDR 1 /* For MAC1 */
@@ -470,6 +470,8 @@ static void r6040_down(struct net_device *dev)
iowrite16(adrp[0], ioaddr + MID_0L);
iowrite16(adrp[1], ioaddr + MID_0M);
iowrite16(adrp[2], ioaddr + MID_0H);
+
+ phy_stop(lp->phydev);
}
static int r6040_close(struct net_device *dev)
@@ -727,6 +729,8 @@ static int r6040_up(struct net_device *dev)
/* Initialize all MAC registers */
r6040_init_mac_regs(dev);
+ phy_start(lp->phydev);
+
return 0;
}
@@ -982,7 +986,7 @@ static const struct net_device_ops r6040_netdev_ops = {
.ndo_stop = r6040_close,
.ndo_start_xmit = r6040_start_xmit,
.ndo_get_stats = r6040_get_stats,
- .ndo_set_multicast_list = r6040_multicast_list,
+ .ndo_set_rx_mode = r6040_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index cc4c210a91f8..ee5da9293ce0 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -777,15 +777,14 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
entry = NEXT_TX(entry);
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
- skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
+ const skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
u32 len;
u32 ctrl;
dma_addr_t mapping;
- len = this_frag->size;
+ len = skb_frag_size(this_frag);
mapping = dma_map_single(&cp->pdev->dev,
- ((void *) page_address(this_frag->page) +
- this_frag->page_offset),
+ skb_frag_address(this_frag),
len, PCI_DMA_TODEVICE);
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
@@ -1325,6 +1324,15 @@ static void cp_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info
strcpy (info->bus_info, pci_name(cp->pdev));
}
+static void cp_get_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ring)
+{
+ ring->rx_max_pending = CP_RX_RING_SIZE;
+ ring->tx_max_pending = CP_TX_RING_SIZE;
+ ring->rx_pending = CP_RX_RING_SIZE;
+ ring->tx_pending = CP_TX_RING_SIZE;
+}
+
static int cp_get_regs_len(struct net_device *dev)
{
return CP_REGS_SIZE;
@@ -1526,6 +1534,7 @@ static const struct ethtool_ops cp_ethtool_ops = {
.get_eeprom_len = cp_get_eeprom_len,
.get_eeprom = cp_get_eeprom,
.set_eeprom = cp_set_eeprom,
+ .get_ringparam = cp_get_ringparam,
};
static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1785,7 +1794,7 @@ static const struct net_device_ops cp_netdev_ops = {
.ndo_stop = cp_close,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = cp_set_mac_address,
- .ndo_set_multicast_list = cp_set_rx_mode,
+ .ndo_set_rx_mode = cp_set_rx_mode,
.ndo_get_stats = cp_get_stats,
.ndo_do_ioctl = cp_ioctl,
.ndo_start_xmit = cp_start_xmit,
diff --git a/drivers/net/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index c2672c692d6f..4d6b254fc6c1 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -916,7 +916,7 @@ static const struct net_device_ops rtl8139_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = rtl8139_set_mac_address,
.ndo_start_xmit = rtl8139_start_xmit,
- .ndo_set_multicast_list = rtl8139_set_rx_mode,
+ .ndo_set_rx_mode = rtl8139_set_rx_mode,
.ndo_do_ioctl = netdev_ioctl,
.ndo_tx_timeout = rtl8139_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig
new file mode 100644
index 000000000000..84083ec6e612
--- /dev/null
+++ b/drivers/net/ethernet/realtek/Kconfig
@@ -0,0 +1,130 @@
+#
+# Realtek device configuration
+#
+
+config NET_VENDOR_REALTEK
+ bool "Realtek devices"
+ default y
+ depends on PCI || (PARPORT && X86)
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Realtek devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_REALTEK
+
+config ATP
+ tristate "AT-LAN-TEC/RealTek pocket adapter support"
+ depends on PARPORT && X86
+ select CRC32
+ ---help---
+ This is a network (Ethernet) device which attaches to your parallel
+ port. Read <file:drivers/net/atp.c> as well as the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>, if you
+ want to use this. If you intend to use this driver, you should have
+ said N to the "Parallel printer support", because the two drivers
+ don't like each other.
+
+ To compile this driver as a module, choose M here: the module
+ will be called atp.
+
+config 8139CP
+ tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This is a driver for the Fast Ethernet PCI network cards based on
+ the RTL8139C+ chips. If you have one of those, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8139cp. This is recommended.
+
+config 8139TOO
+ tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This is a driver for the Fast Ethernet PCI network cards based on
+ the RTL 8129/8130/8139 chips. If you have one of those, say Y and
+ read the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8139too. This is recommended.
+
+config 8139TOO_PIO
+ bool "Use PIO instead of MMIO"
+ default y
+ depends on 8139TOO
+ ---help---
+ This instructs the driver to use programmed I/O ports (PIO) instead
+ of PCI shared memory (MMIO). This can possibly solve some problems
+ in case your mainboard has memory consistency issues. If unsure,
+ say N.
+
+config 8139TOO_TUNE_TWISTER
+ bool "Support for uncommon RTL-8139 rev. K (automatic channel equalization)"
+ depends on 8139TOO
+ ---help---
+ This implements a function which might come in handy in case you
+ are using low quality on long cabling. It is required for RealTek
+ RTL-8139 revision K boards, and totally unused otherwise. It tries
+ to match the transceiver to the cable characteristics. This is
+ experimental since hardly documented by the manufacturer.
+ If unsure, say Y.
+
+config 8139TOO_8129
+ bool "Support for older RTL-8129/8130 boards"
+ depends on 8139TOO
+ ---help---
+ This enables support for the older and uncommon RTL-8129 and
+ RTL-8130 chips, which support MII via an external transceiver,
+ instead of an internal one. Disabling this option will save some
+ memory by making the code size smaller. If unsure, say Y.
+
+config 8139_OLD_RX_RESET
+ bool "Use older RX-reset method"
+ depends on 8139TOO
+ ---help---
+ The 8139too driver was recently updated to contain a more rapid
+ reset sequence, in the face of severe receive errors. This "new"
+ RX-reset method should be adequate for all boards. But if you
+ experience problems, you can enable this option to restore the
+ old RX-reset behavior. If unsure, say N.
+
+config R8169
+ tristate "Realtek 8169 gigabit ethernet support"
+ depends on PCI
+ select FW_LOADER
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter.
+
+ To compile this driver as a module, choose M here: the module
+ will be called r8169. This is recommended.
+
+config SC92031
+ tristate "Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+ select CRC32
+ ---help---
+ This is a driver for the Fast Ethernet PCI network cards based on
+ the Silan SC92031 chip (sometimes also called Rsltek 8139D). If you
+ have one of these, say Y here.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sc92031. This is recommended.
+
+endif # NET_VENDOR_REALTEK
diff --git a/drivers/net/ethernet/realtek/Makefile b/drivers/net/ethernet/realtek/Makefile
new file mode 100644
index 000000000000..e48cfb6ac42d
--- /dev/null
+++ b/drivers/net/ethernet/realtek/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the Realtek network device drivers.
+#
+
+obj-$(CONFIG_8139CP) += 8139cp.o
+obj-$(CONFIG_8139TOO) += 8139too.o
+obj-$(CONFIG_ATP) += atp.o
+obj-$(CONFIG_R8169) += r8169.o
+obj-$(CONFIG_SC92031) += sc92031.o
diff --git a/drivers/net/atp.c b/drivers/net/ethernet/realtek/atp.c
index f3459798b0e9..e3f57fdbf0ea 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/ethernet/realtek/atp.c
@@ -245,7 +245,7 @@ static const struct net_device_ops atp_netdev_ops = {
.ndo_open = net_open,
.ndo_stop = net_close,
.ndo_start_xmit = atp_send_packet,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_tx_timeout = tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/atp.h b/drivers/net/ethernet/realtek/atp.h
index 0edc642c2c2f..0edc642c2c2f 100644
--- a/drivers/net/atp.h
+++ b/drivers/net/ethernet/realtek/atp.h
diff --git a/drivers/net/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 6d657cabb951..92b45f08858f 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -42,6 +42,8 @@
#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw"
#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw"
#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw"
+#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw"
+#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw"
#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw"
#ifdef RTL8169_DEBUG
@@ -133,6 +135,8 @@ enum mac_version {
RTL_GIGA_MAC_VER_32,
RTL_GIGA_MAC_VER_33,
RTL_GIGA_MAC_VER_34,
+ RTL_GIGA_MAC_VER_35,
+ RTL_GIGA_MAC_VER_36,
RTL_GIGA_MAC_NONE = 0xff,
};
@@ -141,84 +145,110 @@ enum rtl_tx_desc_version {
RTL_TD_1 = 1,
};
-#define _R(NAME,TD,FW) \
- { .name = NAME, .txd_version = TD, .fw_name = FW }
+#define JUMBO_1K ETH_DATA_LEN
+#define JUMBO_4K (4*1024 - ETH_HLEN - 2)
+#define JUMBO_6K (6*1024 - ETH_HLEN - 2)
+#define JUMBO_7K (7*1024 - ETH_HLEN - 2)
+#define JUMBO_9K (9*1024 - ETH_HLEN - 2)
+
+#define _R(NAME,TD,FW,SZ,B) { \
+ .name = NAME, \
+ .txd_version = TD, \
+ .fw_name = FW, \
+ .jumbo_max = SZ, \
+ .jumbo_tx_csum = B \
+}
static const struct {
const char *name;
enum rtl_tx_desc_version txd_version;
const char *fw_name;
+ u16 jumbo_max;
+ bool jumbo_tx_csum;
} rtl_chip_infos[] = {
/* PCI devices. */
[RTL_GIGA_MAC_VER_01] =
- _R("RTL8169", RTL_TD_0, NULL),
+ _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true),
[RTL_GIGA_MAC_VER_02] =
- _R("RTL8169s", RTL_TD_0, NULL),
+ _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true),
[RTL_GIGA_MAC_VER_03] =
- _R("RTL8110s", RTL_TD_0, NULL),
+ _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true),
[RTL_GIGA_MAC_VER_04] =
- _R("RTL8169sb/8110sb", RTL_TD_0, NULL),
+ _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true),
[RTL_GIGA_MAC_VER_05] =
- _R("RTL8169sc/8110sc", RTL_TD_0, NULL),
+ _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
[RTL_GIGA_MAC_VER_06] =
- _R("RTL8169sc/8110sc", RTL_TD_0, NULL),
+ _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
/* PCI-E devices. */
[RTL_GIGA_MAC_VER_07] =
- _R("RTL8102e", RTL_TD_1, NULL),
+ _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_08] =
- _R("RTL8102e", RTL_TD_1, NULL),
+ _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_09] =
- _R("RTL8102e", RTL_TD_1, NULL),
+ _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_10] =
- _R("RTL8101e", RTL_TD_0, NULL),
+ _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_11] =
- _R("RTL8168b/8111b", RTL_TD_0, NULL),
+ _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
[RTL_GIGA_MAC_VER_12] =
- _R("RTL8168b/8111b", RTL_TD_0, NULL),
+ _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
[RTL_GIGA_MAC_VER_13] =
- _R("RTL8101e", RTL_TD_0, NULL),
+ _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_14] =
- _R("RTL8100e", RTL_TD_0, NULL),
+ _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_15] =
- _R("RTL8100e", RTL_TD_0, NULL),
+ _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_16] =
- _R("RTL8101e", RTL_TD_0, NULL),
+ _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_17] =
- _R("RTL8168b/8111b", RTL_TD_0, NULL),
+ _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false),
[RTL_GIGA_MAC_VER_18] =
- _R("RTL8168cp/8111cp", RTL_TD_1, NULL),
+ _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_19] =
- _R("RTL8168c/8111c", RTL_TD_1, NULL),
+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_20] =
- _R("RTL8168c/8111c", RTL_TD_1, NULL),
+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_21] =
- _R("RTL8168c/8111c", RTL_TD_1, NULL),
+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_22] =
- _R("RTL8168c/8111c", RTL_TD_1, NULL),
+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_23] =
- _R("RTL8168cp/8111cp", RTL_TD_1, NULL),
+ _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_24] =
- _R("RTL8168cp/8111cp", RTL_TD_1, NULL),
+ _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_25] =
- _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1),
+ _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1,
+ JUMBO_9K, false),
[RTL_GIGA_MAC_VER_26] =
- _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2),
+ _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2,
+ JUMBO_9K, false),
[RTL_GIGA_MAC_VER_27] =
- _R("RTL8168dp/8111dp", RTL_TD_1, NULL),
+ _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
[RTL_GIGA_MAC_VER_28] =
- _R("RTL8168dp/8111dp", RTL_TD_1, NULL),
+ _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
[RTL_GIGA_MAC_VER_29] =
- _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1),
+ _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
+ JUMBO_1K, true),
[RTL_GIGA_MAC_VER_30] =
- _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1),
+ _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
+ JUMBO_1K, true),
[RTL_GIGA_MAC_VER_31] =
- _R("RTL8168dp/8111dp", RTL_TD_1, NULL),
+ _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
[RTL_GIGA_MAC_VER_32] =
- _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1),
+ _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1,
+ JUMBO_9K, false),
[RTL_GIGA_MAC_VER_33] =
- _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2),
+ _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2,
+ JUMBO_9K, false),
[RTL_GIGA_MAC_VER_34] =
- _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3)
+ _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3,
+ JUMBO_9K, false),
+ [RTL_GIGA_MAC_VER_35] =
+ _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1,
+ JUMBO_9K, false),
+ [RTL_GIGA_MAC_VER_36] =
+ _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2,
+ JUMBO_9K, false),
};
#undef _R
@@ -311,6 +341,7 @@ enum rtl_registers {
MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */
#define TxPacketMax (8064 >> 7)
+#define EarlySize 0x27
FuncEvent = 0xf0,
FuncEventMask = 0xf4,
@@ -460,8 +491,12 @@ enum rtl_register_content {
/* Config3 register p.25 */
MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
+ Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
+ /* Config4 register */
+ Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */
+
/* Config5 register p.27 */
BWF = (1 << 6), /* Accept Broadcast wakeup frame */
MWF = (1 << 5), /* Accept Multicast wakeup frame */
@@ -670,6 +705,11 @@ struct rtl8169_private {
void (*up)(struct rtl8169_private *);
} pll_power_ops;
+ struct jumbo_ops {
+ void (*enable)(struct rtl8169_private *);
+ void (*disable)(struct rtl8169_private *);
+ } jumbo_ops;
+
int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
int (*get_settings)(struct net_device *, struct ethtool_cmd *);
void (*phy_reset_enable)(struct rtl8169_private *tp);
@@ -714,6 +754,8 @@ MODULE_FIRMWARE(FIRMWARE_8168E_1);
MODULE_FIRMWARE(FIRMWARE_8168E_2);
MODULE_FIRMWARE(FIRMWARE_8168E_3);
MODULE_FIRMWARE(FIRMWARE_8105E_1);
+MODULE_FIRMWARE(FIRMWARE_8168F_1);
+MODULE_FIRMWARE(FIRMWARE_8168F_2);
static int rtl8169_open(struct net_device *dev);
static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
@@ -732,6 +774,19 @@ static void rtl8169_down(struct net_device *dev);
static void rtl8169_rx_clear(struct rtl8169_private *tp);
static int rtl8169_poll(struct napi_struct *napi, int budget);
+static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
+{
+ int cap = pci_pcie_cap(pdev);
+
+ if (cap) {
+ u16 ctl;
+
+ pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+ ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
+ pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
+ }
+}
+
static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
{
void __iomem *ioaddr = tp->mmio_addr;
@@ -1202,6 +1257,19 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)
ERIAR_EXGMAC);
rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
ERIAR_EXGMAC);
+ } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_36) {
+ if (RTL_R8(PHYstatus) & _1000bpsF) {
+ rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
+ 0x00000011, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111,
+ 0x00000005, ERIAR_EXGMAC);
+ } else {
+ rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
+ 0x0000001f, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111,
+ 0x0000003f, ERIAR_EXGMAC);
+ }
}
}
@@ -1487,9 +1555,15 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static u32 rtl8169_fix_features(struct net_device *dev, u32 features)
{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
if (dev->mtu > TD_MSS_MAX)
features &= ~NETIF_F_ALL_TSO;
+ if (dev->mtu > JUMBO_1K &&
+ !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
+ features &= ~NETIF_F_IP_CSUM;
+
return features;
}
@@ -1741,6 +1815,10 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
u32 val;
int mac_version;
} mac_info[] = {
+ /* 8168F family. */
+ { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
+ { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
+
/* 8168E family. */
{ 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
{ 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
@@ -2875,6 +2953,97 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x1f, 0x0000);
}
+static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
+{
+ static const struct phy_reg phy_reg_init[] = {
+ /* Channel estimation fine tune */
+ { 0x1f, 0x0003 },
+ { 0x09, 0xa20f },
+ { 0x1f, 0x0000 },
+
+ /* Modify green table for giga & fnet */
+ { 0x1f, 0x0005 },
+ { 0x05, 0x8b55 },
+ { 0x06, 0x0000 },
+ { 0x05, 0x8b5e },
+ { 0x06, 0x0000 },
+ { 0x05, 0x8b67 },
+ { 0x06, 0x0000 },
+ { 0x05, 0x8b70 },
+ { 0x06, 0x0000 },
+ { 0x1f, 0x0000 },
+ { 0x1f, 0x0007 },
+ { 0x1e, 0x0078 },
+ { 0x17, 0x0000 },
+ { 0x19, 0x00fb },
+ { 0x1f, 0x0000 },
+
+ /* Modify green table for 10M */
+ { 0x1f, 0x0005 },
+ { 0x05, 0x8b79 },
+ { 0x06, 0xaa00 },
+ { 0x1f, 0x0000 },
+
+ /* Disable hiimpedance detection (RTCT) */
+ { 0x1f, 0x0003 },
+ { 0x01, 0x328a },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_apply_firmware(tp);
+
+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ /* For 4-corner performance improve */
+ rtl_writephy(tp, 0x1f, 0x0005);
+ rtl_writephy(tp, 0x05, 0x8b80);
+ rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* PHY auto speed down */
+ rtl_writephy(tp, 0x1f, 0x0007);
+ rtl_writephy(tp, 0x1e, 0x002d);
+ rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+ rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
+
+ /* Improve 10M EEE waveform */
+ rtl_writephy(tp, 0x1f, 0x0005);
+ rtl_writephy(tp, 0x05, 0x8b86);
+ rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* Improve 2-pair detection performance */
+ rtl_writephy(tp, 0x1f, 0x0005);
+ rtl_writephy(tp, 0x05, 0x8b85);
+ rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+}
+
+static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
+{
+ rtl_apply_firmware(tp);
+
+ /* For 4-corner performance improve */
+ rtl_writephy(tp, 0x1f, 0x0005);
+ rtl_writephy(tp, 0x05, 0x8b80);
+ rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* PHY auto speed down */
+ rtl_writephy(tp, 0x1f, 0x0007);
+ rtl_writephy(tp, 0x1e, 0x002d);
+ rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+ rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
+
+ /* Improve 10M EEE waveform */
+ rtl_writephy(tp, 0x1f, 0x0005);
+ rtl_writephy(tp, 0x05, 0x8b86);
+ rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+}
+
static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
{
static const struct phy_reg phy_reg_init[] = {
@@ -2999,6 +3168,12 @@ static void rtl_hw_phy_config(struct net_device *dev)
case RTL_GIGA_MAC_VER_34:
rtl8168e_2_hw_phy_config(tp);
break;
+ case RTL_GIGA_MAC_VER_35:
+ rtl8168f_1_hw_phy_config(tp);
+ break;
+ case RTL_GIGA_MAC_VER_36:
+ rtl8168f_2_hw_phy_config(tp);
+ break;
default:
break;
@@ -3288,7 +3463,7 @@ static const struct net_device_ops rtl8169_netdev_ops = {
.ndo_set_features = rtl8169_set_features,
.ndo_set_mac_address = rtl_set_mac_address,
.ndo_do_ioctl = rtl8169_ioctl,
- .ndo_set_multicast_list = rtl_set_rx_mode,
+ .ndo_set_rx_mode = rtl_set_rx_mode,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = rtl8169_netpoll,
#endif
@@ -3495,8 +3670,8 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
r8168_phy_power_up(tp);
}
-static void rtl_pll_power_op(struct rtl8169_private *tp,
- void (*op)(struct rtl8169_private *))
+static void rtl_generic_op(struct rtl8169_private *tp,
+ void (*op)(struct rtl8169_private *))
{
if (op)
op(tp);
@@ -3504,12 +3679,12 @@ static void rtl_pll_power_op(struct rtl8169_private *tp,
static void rtl_pll_power_down(struct rtl8169_private *tp)
{
- rtl_pll_power_op(tp, tp->pll_power_ops.down);
+ rtl_generic_op(tp, tp->pll_power_ops.down);
}
static void rtl_pll_power_up(struct rtl8169_private *tp)
{
- rtl_pll_power_op(tp, tp->pll_power_ops.up);
+ rtl_generic_op(tp, tp->pll_power_ops.up);
}
static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
@@ -3546,6 +3721,8 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_32:
case RTL_GIGA_MAC_VER_33:
case RTL_GIGA_MAC_VER_34:
+ case RTL_GIGA_MAC_VER_35:
+ case RTL_GIGA_MAC_VER_36:
ops->down = r8168_pll_power_down;
ops->up = r8168_pll_power_up;
break;
@@ -3598,6 +3775,150 @@ static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
}
+static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ rtl_generic_op(tp, tp->jumbo_ops.enable);
+}
+
+static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ rtl_generic_op(tp, tp->jumbo_ops.disable);
+}
+
+static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+ RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
+ rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
+}
+
+static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+ RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
+ rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
+}
+
+static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+}
+
+static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+}
+
+static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ RTL_W8(MaxTxPacketSize, 0x3f);
+ RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+ RTL_W8(Config4, RTL_R8(Config4) | 0x01);
+ pci_write_config_byte(pdev, 0x79, 0x20);
+}
+
+static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ RTL_W8(MaxTxPacketSize, 0x0c);
+ RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+ RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
+ pci_write_config_byte(pdev, 0x79, 0x50);
+}
+
+static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ rtl_tx_performance_tweak(tp->pci_dev,
+ (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+}
+
+static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ rtl_tx_performance_tweak(tp->pci_dev,
+ (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+}
+
+static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ r8168b_0_hw_jumbo_enable(tp);
+
+ RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
+}
+
+static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ r8168b_0_hw_jumbo_disable(tp);
+
+ RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
+}
+
+static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp)
+{
+ struct jumbo_ops *ops = &tp->jumbo_ops;
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_11:
+ ops->disable = r8168b_0_hw_jumbo_disable;
+ ops->enable = r8168b_0_hw_jumbo_enable;
+ break;
+ case RTL_GIGA_MAC_VER_12:
+ case RTL_GIGA_MAC_VER_17:
+ ops->disable = r8168b_1_hw_jumbo_disable;
+ ops->enable = r8168b_1_hw_jumbo_enable;
+ break;
+ case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
+ case RTL_GIGA_MAC_VER_19:
+ case RTL_GIGA_MAC_VER_20:
+ case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
+ case RTL_GIGA_MAC_VER_22:
+ case RTL_GIGA_MAC_VER_23:
+ case RTL_GIGA_MAC_VER_24:
+ case RTL_GIGA_MAC_VER_25:
+ case RTL_GIGA_MAC_VER_26:
+ ops->disable = r8168c_hw_jumbo_disable;
+ ops->enable = r8168c_hw_jumbo_enable;
+ break;
+ case RTL_GIGA_MAC_VER_27:
+ case RTL_GIGA_MAC_VER_28:
+ ops->disable = r8168dp_hw_jumbo_disable;
+ ops->enable = r8168dp_hw_jumbo_enable;
+ break;
+ case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
+ case RTL_GIGA_MAC_VER_32:
+ case RTL_GIGA_MAC_VER_33:
+ case RTL_GIGA_MAC_VER_34:
+ ops->disable = r8168e_hw_jumbo_disable;
+ ops->enable = r8168e_hw_jumbo_enable;
+ break;
+
+ /*
+ * No action needed for jumbo frames with 8169.
+ * No jumbo for 810x at all.
+ */
+ default:
+ ops->disable = NULL;
+ ops->enable = NULL;
+ break;
+ }
+}
+
static void rtl_hw_reset(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
@@ -3742,6 +4063,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rtl_init_mdio_ops(tp);
rtl_init_pll_power_ops(tp);
+ rtl_init_jumbo_ops(tp);
rtl8169_print_mac_version(tp);
@@ -3825,6 +4147,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n",
rtl_chip_infos[chipset].name, dev->base_addr, dev->dev_addr,
(u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq);
+ if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
+ netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
+ "tx checksumming: %s]\n",
+ rtl_chip_infos[chipset].jumbo_max,
+ rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
+ }
if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
tp->mac_version == RTL_GIGA_MAC_VER_28 ||
@@ -4020,7 +4348,9 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
tp->mac_version == RTL_GIGA_MAC_VER_31) {
while (RTL_R8(TxPoll) & NPQ)
udelay(20);
- } else if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
+ } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_35 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_36) {
RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
while (!(RTL_R32(TxConfig) & TXCFG_EMPTY))
udelay(100);
@@ -4179,19 +4509,6 @@ static void rtl_hw_start_8169(struct net_device *dev)
RTL_W16(IntrMask, tp->intr_event);
}
-static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
-{
- int cap = pci_pcie_cap(pdev);
-
- if (cap) {
- u16 ctl;
-
- pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
- ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
- pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
- }
-}
-
static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits)
{
u32 csi;
@@ -4491,7 +4808,50 @@ static void rtl_hw_start_8168e_2(void __iomem *ioaddr, struct pci_dev *pdev)
rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00,
ERIAR_EXGMAC);
- RTL_W8(MaxTxPacketSize, 0x27);
+ 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);
+
+ /* Adjust EEE LED frequency */
+ RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
+
+ RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
+ RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
+ RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+}
+
+static void rtl_hw_start_8168f_1(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+ static const struct ephy_info e_info_8168f_1[] = {
+ { 0x06, 0x00c0, 0x0020 },
+ { 0x08, 0x0001, 0x0002 },
+ { 0x09, 0x0000, 0x0080 },
+ { 0x19, 0x0000, 0x0224 }
+ };
+
+ rtl_csi_access_enable_1(ioaddr);
+
+ rtl_ephy_init(ioaddr, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ rtl_eri_write(ioaddr, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00,
+ ERIAR_EXGMAC);
+
+ RTL_W8(MaxTxPacketSize, EarlySize);
rtl_disable_clock_request(pdev);
@@ -4600,6 +4960,11 @@ static void rtl_hw_start_8168(struct net_device *dev)
rtl_hw_start_8168e_2(ioaddr, pdev);
break;
+ case RTL_GIGA_MAC_VER_35:
+ case RTL_GIGA_MAC_VER_36:
+ rtl_hw_start_8168f_1(ioaddr, pdev);
+ break;
+
default:
printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
dev->name, tp->mac_version);
@@ -4771,9 +5136,17 @@ static void rtl_hw_start_8101(struct net_device *dev)
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu)
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (new_mtu < ETH_ZLEN ||
+ new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
return -EINVAL;
+ if (new_mtu > ETH_DATA_LEN)
+ rtl_hw_jumbo_enable(tp);
+ else
+ rtl_hw_jumbo_disable(tp);
+
dev->mtu = new_mtu;
netdev_update_features(dev);
@@ -5052,7 +5425,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
entry = tp->cur_tx;
for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
- skb_frag_t *frag = info->frags + cur_frag;
+ const skb_frag_t *frag = info->frags + cur_frag;
dma_addr_t mapping;
u32 status, len;
void *addr;
@@ -5060,8 +5433,8 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
entry = (entry + 1) % NUM_TX_DESC;
txd = tp->TxDescArray + entry;
- len = frag->size;
- addr = ((void *) page_address(frag->page)) + frag->page_offset;
+ len = skb_frag_size(frag);
+ addr = skb_frag_address(frag);
mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(d, mapping))) {
if (net_ratelimit())
@@ -5368,7 +5741,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
} else {
struct sk_buff *skb;
dma_addr_t addr = le64_to_cpu(desc->addr);
- int pkt_size = (status & 0x00001FFF) - 4;
+ int pkt_size = (status & 0x00003fff) - 4;
/*
* The driver does not support incoming fragmented
diff --git a/drivers/net/sc92031.c b/drivers/net/ethernet/realtek/sc92031.c
index 9da47337b7c3..a284d6440538 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/ethernet/realtek/sc92031.c
@@ -31,6 +31,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/mii.h>
#include <linux/crc32.h>
#include <asm/irq.h>
@@ -116,16 +117,9 @@ enum silan_registers {
TestD8 = 0xD8,
};
-#define MII_BMCR 0 // Basic mode control register
-#define MII_BMSR 1 // Basic mode status register
#define MII_JAB 16
#define MII_OutputStatus 24
-#define BMCR_FULLDPLX 0x0100 // Full duplex
-#define BMCR_ANRESTART 0x0200 // Auto negotiation restart
-#define BMCR_ANENABLE 0x1000 // Enable auto negotiation
-#define BMCR_SPEED100 0x2000 // Select 100Mbps
-#define BMSR_LSTATUS 0x0004 // Link status
#define PHY_16_JAB_ENB 0x1000
#define PHY_16_PORT_ENB 0x1
@@ -1390,7 +1384,7 @@ static const struct net_device_ops sc92031_netdev_ops = {
.ndo_start_xmit = sc92031_start_xmit,
.ndo_open = sc92031_open,
.ndo_stop = sc92031_stop,
- .ndo_set_multicast_list = sc92031_set_multicast_list,
+ .ndo_set_rx_mode = sc92031_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
new file mode 100644
index 000000000000..9755b49bbefb
--- /dev/null
+++ b/drivers/net/ethernet/renesas/Kconfig
@@ -0,0 +1,19 @@
+#
+# Renesas device configuration
+#
+
+config SH_ETH
+ tristate "Renesas SuperH Ethernet support"
+ depends on SUPERH && \
+ (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
+ CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
+ CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7757)
+ select CRC32
+ select NET_CORE
+ select MII
+ select MDIO_BITBANG
+ select PHYLIB
+ ---help---
+ Renesas SuperH Ethernet device driver.
+ This driver supporting CPUs are:
+ - SH7710, SH7712, SH7763, SH7619, SH7724, and SH7757.
diff --git a/drivers/net/ethernet/renesas/Makefile b/drivers/net/ethernet/renesas/Makefile
new file mode 100644
index 000000000000..1c278a8e066a
--- /dev/null
+++ b/drivers/net/ethernet/renesas/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Renesas device drivers.
+#
+
+obj-$(CONFIG_SH_ETH) += sh_eth.o
diff --git a/drivers/net/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 1c1666e99106..9b230740c6ab 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -21,6 +21,9 @@
*/
#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
@@ -35,6 +38,7 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/ethtool.h>
+#include <linux/sh_eth.h>
#include "sh_eth.h"
@@ -155,18 +159,18 @@ static void sh_eth_chip_reset_giga(struct net_device *ndev)
/* save MAHR and MALR */
for (i = 0; i < 2; i++) {
- malr[i] = readl(GIGA_MALR(i));
- mahr[i] = readl(GIGA_MAHR(i));
+ malr[i] = ioread32((void *)GIGA_MALR(i));
+ mahr[i] = ioread32((void *)GIGA_MAHR(i));
}
/* reset device */
- writel(ARSTR_ARSTR, SH_GIGA_ETH_BASE + 0x1800);
+ iowrite32(ARSTR_ARSTR, (void *)(SH_GIGA_ETH_BASE + 0x1800));
mdelay(1);
/* restore MAHR and MALR */
for (i = 0; i < 2; i++) {
- writel(malr[i], GIGA_MALR(i));
- writel(mahr[i], GIGA_MAHR(i));
+ iowrite32(malr[i], (void *)GIGA_MALR(i));
+ iowrite32(mahr[i], (void *)GIGA_MAHR(i));
}
}
@@ -515,9 +519,9 @@ static unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp)
}
struct bb_info {
- void (*set_gate)(unsigned long addr);
+ void (*set_gate)(void *addr);
struct mdiobb_ctrl ctrl;
- u32 addr;
+ void *addr;
u32 mmd_msk;/* MMD */
u32 mdo_msk;
u32 mdi_msk;
@@ -525,21 +529,21 @@ struct bb_info {
};
/* PHY bit set */
-static void bb_set(u32 addr, u32 msk)
+static void bb_set(void *addr, u32 msk)
{
- writel(readl(addr) | msk, addr);
+ iowrite32(ioread32(addr) | msk, addr);
}
/* PHY bit clear */
-static void bb_clr(u32 addr, u32 msk)
+static void bb_clr(void *addr, u32 msk)
{
- writel((readl(addr) & ~msk), addr);
+ iowrite32((ioread32(addr) & ~msk), addr);
}
/* PHY bit read */
-static int bb_read(u32 addr, u32 msk)
+static int bb_read(void *addr, u32 msk)
{
- return (readl(addr) & msk) != 0;
+ return (ioread32(addr) & msk) != 0;
}
/* Data I/O pin control */
@@ -1680,7 +1684,7 @@ static int sh_mdio_init(struct net_device *ndev, int id,
}
/* bitbang init */
- bitbang->addr = ndev->base_addr + mdp->reg_offset[PIR];
+ bitbang->addr = mdp->addr + mdp->reg_offset[PIR];
bitbang->set_gate = pd->set_mdio_gate;
bitbang->mdi_msk = 0x08;
bitbang->mdo_msk = 0x04;
@@ -1760,7 +1764,7 @@ static const struct net_device_ops sh_eth_netdev_ops = {
.ndo_start_xmit = sh_eth_start_xmit,
.ndo_get_stats = sh_eth_get_stats,
#if defined(SH_ETH_HAS_TSU)
- .ndo_set_multicast_list = sh_eth_set_multicast_list,
+ .ndo_set_rx_mode = sh_eth_set_multicast_list,
#endif
.ndo_tx_timeout = sh_eth_tx_timeout,
.ndo_do_ioctl = sh_eth_do_ioctl,
@@ -1812,6 +1816,13 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
ether_setup(ndev);
mdp = netdev_priv(ndev);
+ mdp->addr = ioremap(res->start, resource_size(res));
+ if (mdp->addr == NULL) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "ioremap failed.\n");
+ goto out_release;
+ }
+
spin_lock_init(&mdp->lock);
mdp->pdev = pdev;
pm_runtime_enable(&pdev->dev);
@@ -1892,6 +1903,8 @@ out_unregister:
out_release:
/* net_dev free */
+ if (mdp && mdp->addr)
+ iounmap(mdp->addr);
if (mdp && mdp->tsu_addr)
iounmap(mdp->tsu_addr);
if (ndev)
@@ -1910,6 +1923,7 @@ static int sh_eth_drv_remove(struct platform_device *pdev)
sh_mdio_release(ndev);
unregister_netdev(ndev);
pm_runtime_disable(&pdev->dev);
+ iounmap(mdp->addr);
free_netdev(ndev);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index c3048a6ba676..47877b13ffad 100644
--- a/drivers/net/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -23,14 +23,6 @@
#ifndef __SH_ETH_H__
#define __SH_ETH_H__
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/netdevice.h>
-#include <linux/phy.h>
-
-#include <asm/sh_eth.h>
-
#define CARDNAME "sh-eth"
#define TX_TIMEOUT (5*HZ)
#define TX_RING_SIZE 64 /* Tx ring size */
@@ -762,6 +754,7 @@ struct sh_eth_private {
struct platform_device *pdev;
struct sh_eth_cpu_data *cd;
const u16 *reg_offset;
+ void __iomem *addr;
void __iomem *tsu_addr;
dma_addr_t rx_desc_dma;
dma_addr_t tx_desc_dma;
@@ -811,7 +804,7 @@ static inline void sh_eth_write(struct net_device *ndev, unsigned long data,
{
struct sh_eth_private *mdp = netdev_priv(ndev);
- writel(data, ndev->base_addr + mdp->reg_offset[enum_index]);
+ iowrite32(data, mdp->addr + mdp->reg_offset[enum_index]);
}
static inline unsigned long sh_eth_read(struct net_device *ndev,
@@ -819,19 +812,19 @@ static inline unsigned long sh_eth_read(struct net_device *ndev,
{
struct sh_eth_private *mdp = netdev_priv(ndev);
- return readl(ndev->base_addr + mdp->reg_offset[enum_index]);
+ return ioread32(mdp->addr + mdp->reg_offset[enum_index]);
}
static inline void sh_eth_tsu_write(struct sh_eth_private *mdp,
unsigned long data, int enum_index)
{
- writel(data, mdp->tsu_addr + mdp->reg_offset[enum_index]);
+ iowrite32(data, mdp->tsu_addr + mdp->reg_offset[enum_index]);
}
static inline unsigned long sh_eth_tsu_read(struct sh_eth_private *mdp,
int enum_index)
{
- return readl(mdp->tsu_addr + mdp->reg_offset[enum_index]);
+ return ioread32(mdp->tsu_addr + mdp->reg_offset[enum_index]);
}
#endif /* #ifndef __SH_ETH_H__ */
diff --git a/drivers/net/s6gmac.c b/drivers/net/ethernet/s6gmac.c
index a7ff8ea342b4..a7ff8ea342b4 100644
--- a/drivers/net/s6gmac.c
+++ b/drivers/net/ethernet/s6gmac.c
diff --git a/drivers/net/ethernet/seeq/Kconfig b/drivers/net/ethernet/seeq/Kconfig
new file mode 100644
index 000000000000..29f18533fdc7
--- /dev/null
+++ b/drivers/net/ethernet/seeq/Kconfig
@@ -0,0 +1,47 @@
+#
+# SEEQ device configuration
+#
+
+config NET_VENDOR_SEEQ
+ bool "SEEQ devices"
+ default y
+ depends on HAS_IOMEM
+ depends on (ARM && ARCH_ACORN) || SGI_HAS_SEEQ || EXPERIMENTAL
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about SEEQ devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_SEEQ
+
+config ARM_ETHER3
+ tristate "Acorn/ANT Ether3 support"
+ depends on ARM && ARCH_ACORN
+ ---help---
+ If you have an Acorn system with one of these network cards, you
+ should say Y to this option if you wish to use it with Linux.
+
+config SEEQ8005
+ tristate "SEEQ8005 support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ ---help---
+ This is a driver for the SEEQ 8005 network (Ethernet) card. If this
+ is for you, read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called seeq8005.
+
+config SGISEEQ
+ tristate "SGI Seeq ethernet controller support"
+ depends on SGI_HAS_SEEQ
+ ---help---
+ Say Y here if you have an Seeq based Ethernet network card. This is
+ used in many Silicon Graphics machines.
+
+endif # NET_VENDOR_SEEQ
diff --git a/drivers/net/ethernet/seeq/Makefile b/drivers/net/ethernet/seeq/Makefile
new file mode 100644
index 000000000000..3e258a580c05
--- /dev/null
+++ b/drivers/net/ethernet/seeq/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the SEEQ network device drivers
+#
+
+obj-$(CONFIG_ARM_ETHER3) += ether3.o
+obj-$(CONFIG_SEEQ8005) += seeq8005.o
+obj-$(CONFIG_SGISEEQ) += sgiseeq.o
diff --git a/drivers/net/arm/ether3.c b/drivers/net/ethernet/seeq/ether3.c
index 44a8746f4014..893c880dadf0 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/ethernet/seeq/ether3.c
@@ -761,7 +761,7 @@ static const struct net_device_ops ether3_netdev_ops = {
.ndo_open = ether3_open,
.ndo_stop = ether3_close,
.ndo_start_xmit = ether3_sendpacket,
- .ndo_set_multicast_list = ether3_setmulticastlist,
+ .ndo_set_rx_mode = ether3_setmulticastlist,
.ndo_tx_timeout = ether3_timeout,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/arm/ether3.h b/drivers/net/ethernet/seeq/ether3.h
index 2db63b08bdf3..2db63b08bdf3 100644
--- a/drivers/net/arm/ether3.h
+++ b/drivers/net/ethernet/seeq/ether3.h
diff --git a/drivers/net/seeq8005.c b/drivers/net/ethernet/seeq/seeq8005.c
index d2fce98f557f..60561451789b 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/ethernet/seeq/seeq8005.c
@@ -148,7 +148,7 @@ static const struct net_device_ops seeq8005_netdev_ops = {
.ndo_stop = seeq8005_close,
.ndo_start_xmit = seeq8005_send_packet,
.ndo_tx_timeout = seeq8005_timeout,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/seeq8005.h b/drivers/net/ethernet/seeq/seeq8005.h
index 5dfb0098c6ca..5dfb0098c6ca 100644
--- a/drivers/net/seeq8005.h
+++ b/drivers/net/ethernet/seeq/seeq8005.h
diff --git a/drivers/net/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c
index 52fb7ed9f365..c3673f151a41 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/ethernet/seeq/sgiseeq.c
@@ -715,7 +715,7 @@ static const struct net_device_ops sgiseeq_netdev_ops = {
.ndo_stop = sgiseeq_close,
.ndo_start_xmit = sgiseeq_start_xmit,
.ndo_tx_timeout = timeout,
- .ndo_set_multicast_list = sgiseeq_set_multicast,
+ .ndo_set_rx_mode = sgiseeq_set_multicast,
.ndo_set_mac_address = sgiseeq_set_mac_address,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/sgiseeq.h b/drivers/net/ethernet/seeq/sgiseeq.h
index 2211e2987a8d..2211e2987a8d 100644
--- a/drivers/net/sgiseeq.h
+++ b/drivers/net/ethernet/seeq/sgiseeq.h
diff --git a/drivers/net/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index a3d5bb9e39dc..5d18841f0f3d 100644
--- a/drivers/net/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -5,7 +5,7 @@ config SFC
select CRC32
select I2C
select I2C_ALGOBIT
- help
+ ---help---
This driver supports 10-gigabit Ethernet cards based on
the Solarflare SFC4000 and SFC9000-family controllers.
@@ -15,7 +15,7 @@ config SFC_MTD
bool "Solarflare SFC4000/SFC9000-family MTD support"
depends on SFC && MTD && !(SFC=y && MTD=m)
default y
- help
+ ---help---
This exposes the on-board flash memory as MTD devices (e.g.
/dev/mtd1). This makes it possible to upload new firmware
to the NIC.
diff --git a/drivers/net/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index ab31c7124db1..ab31c7124db1 100644
--- a/drivers/net/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
diff --git a/drivers/net/sfc/bitfield.h b/drivers/net/ethernet/sfc/bitfield.h
index 098ac2ad757d..098ac2ad757d 100644
--- a/drivers/net/sfc/bitfield.h
+++ b/drivers/net/ethernet/sfc/bitfield.h
diff --git a/drivers/net/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index b59abc706d93..d5731f1fe6d6 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1343,7 +1343,8 @@ static int efx_probe_nic(struct efx_nic *efx)
netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels);
/* Initialise the interrupt moderation settings */
- efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true);
+ efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true,
+ true);
return 0;
@@ -1542,18 +1543,19 @@ static void efx_remove_all(struct efx_nic *efx)
*
**************************************************************************/
-static unsigned irq_mod_ticks(int usecs, int resolution)
+static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int resolution)
{
- if (usecs <= 0)
- return 0; /* cannot receive interrupts ahead of time :-) */
+ if (usecs == 0)
+ return 0;
if (usecs < resolution)
return 1; /* never round down to 0 */
return usecs / resolution;
}
/* Set interrupt moderation parameters */
-void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
- bool rx_adaptive)
+int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
+ unsigned int rx_usecs, bool rx_adaptive,
+ bool rx_may_override_tx)
{
struct efx_channel *channel;
unsigned tx_ticks = irq_mod_ticks(tx_usecs, EFX_IRQ_MOD_RESOLUTION);
@@ -1561,6 +1563,16 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
EFX_ASSERT_RESET_SERIALISED(efx);
+ if (tx_ticks > EFX_IRQ_MOD_MAX || rx_ticks > EFX_IRQ_MOD_MAX)
+ return -EINVAL;
+
+ if (tx_ticks != rx_ticks && efx->tx_channel_offset == 0 &&
+ !rx_may_override_tx) {
+ netif_err(efx, drv, efx->net_dev, "Channels are shared. "
+ "RX and TX IRQ moderation must be equal\n");
+ return -EINVAL;
+ }
+
efx->irq_rx_adaptive = rx_adaptive;
efx->irq_rx_moderation = rx_ticks;
efx_for_each_channel(channel, efx) {
@@ -1569,6 +1581,26 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
else if (efx_channel_has_tx_queues(channel))
channel->irq_moderation = tx_ticks;
}
+
+ return 0;
+}
+
+void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
+ unsigned int *rx_usecs, bool *rx_adaptive)
+{
+ *rx_adaptive = efx->irq_rx_adaptive;
+ *rx_usecs = efx->irq_rx_moderation * EFX_IRQ_MOD_RESOLUTION;
+
+ /* If channels are shared between RX and TX, so is IRQ
+ * moderation. Otherwise, IRQ moderation is the same for all
+ * TX channels and is not adaptive.
+ */
+ if (efx->tx_channel_offset == 0)
+ *tx_usecs = *rx_usecs;
+ else
+ *tx_usecs =
+ efx->channel[efx->tx_channel_offset]->irq_moderation *
+ EFX_IRQ_MOD_RESOLUTION;
}
/**************************************************************************
@@ -1889,7 +1921,7 @@ static const struct net_device_ops efx_netdev_ops = {
.ndo_do_ioctl = efx_ioctl,
.ndo_change_mtu = efx_change_mtu,
.ndo_set_mac_address = efx_set_mac_address,
- .ndo_set_multicast_list = efx_set_multicast_list,
+ .ndo_set_rx_mode = efx_set_multicast_list,
.ndo_set_features = efx_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = efx_netpoll,
@@ -2197,13 +2229,15 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
/* PCI device ID table */
static DEFINE_PCI_DEVICE_TABLE(efx_pci_table) = {
- {PCI_DEVICE(EFX_VENDID_SFC, FALCON_A_P_DEVID),
+ {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0),
.driver_data = (unsigned long) &falcon_a1_nic_type},
- {PCI_DEVICE(EFX_VENDID_SFC, FALCON_B_P_DEVID),
+ {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000B),
.driver_data = (unsigned long) &falcon_b0_nic_type},
- {PCI_DEVICE(EFX_VENDID_SFC, BETHPAGE_A_P_DEVID),
+ {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, BETHPAGE_A_P_DEVID),
.driver_data = (unsigned long) &siena_a0_nic_type},
- {PCI_DEVICE(EFX_VENDID_SFC, SIENA_A_P_DEVID),
+ {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, SIENA_A_P_DEVID),
.driver_data = (unsigned long) &siena_a0_nic_type},
{0} /* end of list */
};
diff --git a/drivers/net/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index b0d1209ea18d..4764793ed234 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -15,10 +15,6 @@
#include "filter.h"
/* PCI IDs */
-#define EFX_VENDID_SFC 0x1924
-#define FALCON_A_P_DEVID 0x0703
-#define FALCON_A_S_DEVID 0x6703
-#define FALCON_B_P_DEVID 0x0710
#define BETHPAGE_A_P_DEVID 0x0803
#define SIENA_A_P_DEVID 0x0813
@@ -111,8 +107,11 @@ extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok);
/* Global */
extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
-extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs,
- int rx_usecs, bool rx_adaptive);
+extern int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
+ unsigned int rx_usecs, bool rx_adaptive,
+ bool rx_may_override_tx);
+extern void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
+ unsigned int *rx_usecs, bool *rx_adaptive);
/* Dummy PHY ops for PHY drivers */
extern int efx_port_dummy_op_int(struct efx_nic *efx);
diff --git a/drivers/net/sfc/enum.h b/drivers/net/ethernet/sfc/enum.h
index d725a8fbe1a6..d725a8fbe1a6 100644
--- a/drivers/net/sfc/enum.h
+++ b/drivers/net/ethernet/sfc/enum.h
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index bc4643af6dd1..f3cd96dfa398 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -586,72 +586,89 @@ static int efx_ethtool_nway_reset(struct net_device *net_dev)
return mdio45_nway_restart(&efx->mdio);
}
+/*
+ * Each channel has a single IRQ and moderation timer, started by any
+ * completion (or other event). Unless the module parameter
+ * separate_tx_channels is set, IRQs and moderation are therefore
+ * shared between RX and TX completions. In this case, when RX IRQ
+ * moderation is explicitly changed then TX IRQ moderation is
+ * automatically changed too, but otherwise we fail if the two values
+ * are requested to be different.
+ *
+ * The hardware does not support a limit on the number of completions
+ * before an IRQ, so we do not use the max_frames fields. We should
+ * report and require that max_frames == (usecs != 0), but this would
+ * invalidate existing user documentation.
+ *
+ * The hardware does not have distinct settings for interrupt
+ * moderation while the previous IRQ is being handled, so we should
+ * not use the 'irq' fields. However, an earlier developer
+ * misunderstood the meaning of the 'irq' fields and the driver did
+ * not support the standard fields. To avoid invalidating existing
+ * user documentation, we report and accept changes through either the
+ * standard or 'irq' fields. If both are changed at the same time, we
+ * prefer the standard field.
+ *
+ * We implement adaptive IRQ moderation, but use a different algorithm
+ * from that assumed in the definition of struct ethtool_coalesce.
+ * Therefore we do not use any of the adaptive moderation parameters
+ * in it.
+ */
+
static int efx_ethtool_get_coalesce(struct net_device *net_dev,
struct ethtool_coalesce *coalesce)
{
struct efx_nic *efx = netdev_priv(net_dev);
- struct efx_channel *channel;
-
- memset(coalesce, 0, sizeof(*coalesce));
-
- /* Find lowest IRQ moderation across all used TX queues */
- coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
- efx_for_each_channel(channel, efx) {
- if (!efx_channel_has_tx_queues(channel))
- continue;
- if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
- if (channel->channel < efx->n_rx_channels)
- coalesce->tx_coalesce_usecs_irq =
- channel->irq_moderation;
- else
- coalesce->tx_coalesce_usecs_irq = 0;
- }
- }
+ unsigned int tx_usecs, rx_usecs;
+ bool rx_adaptive;
- coalesce->use_adaptive_rx_coalesce = efx->irq_rx_adaptive;
- coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation;
+ efx_get_irq_moderation(efx, &tx_usecs, &rx_usecs, &rx_adaptive);
- coalesce->tx_coalesce_usecs_irq *= EFX_IRQ_MOD_RESOLUTION;
- coalesce->rx_coalesce_usecs_irq *= EFX_IRQ_MOD_RESOLUTION;
+ coalesce->tx_coalesce_usecs = tx_usecs;
+ coalesce->tx_coalesce_usecs_irq = tx_usecs;
+ coalesce->rx_coalesce_usecs = rx_usecs;
+ coalesce->rx_coalesce_usecs_irq = rx_usecs;
+ coalesce->use_adaptive_rx_coalesce = rx_adaptive;
return 0;
}
-/* Set coalescing parameters
- * The difficulties occur for shared channels
- */
static int efx_ethtool_set_coalesce(struct net_device *net_dev,
struct ethtool_coalesce *coalesce)
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_channel *channel;
- unsigned tx_usecs, rx_usecs, adaptive;
+ unsigned int tx_usecs, rx_usecs;
+ bool adaptive, rx_may_override_tx;
+ int rc;
if (coalesce->use_adaptive_tx_coalesce)
- return -EOPNOTSUPP;
+ return -EINVAL;
- if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) {
- netif_err(efx, drv, efx->net_dev, "invalid coalescing setting. "
- "Only rx/tx_coalesce_usecs_irq are supported\n");
- return -EOPNOTSUPP;
- }
+ efx_get_irq_moderation(efx, &tx_usecs, &rx_usecs, &adaptive);
+
+ if (coalesce->rx_coalesce_usecs != rx_usecs)
+ rx_usecs = coalesce->rx_coalesce_usecs;
+ else
+ rx_usecs = coalesce->rx_coalesce_usecs_irq;
- rx_usecs = coalesce->rx_coalesce_usecs_irq;
- tx_usecs = coalesce->tx_coalesce_usecs_irq;
adaptive = coalesce->use_adaptive_rx_coalesce;
- /* If the channel is shared only allow RX parameters to be set */
- efx_for_each_channel(channel, efx) {
- if (efx_channel_has_rx_queue(channel) &&
- efx_channel_has_tx_queues(channel) &&
- tx_usecs) {
- netif_err(efx, drv, efx->net_dev, "Channel is shared. "
- "Only RX coalescing may be set\n");
- return -EOPNOTSUPP;
- }
- }
+ /* If channels are shared, TX IRQ moderation can be quietly
+ * overridden unless it is changed from its old value.
+ */
+ rx_may_override_tx = (coalesce->tx_coalesce_usecs == tx_usecs &&
+ coalesce->tx_coalesce_usecs_irq == tx_usecs);
+ if (coalesce->tx_coalesce_usecs != tx_usecs)
+ tx_usecs = coalesce->tx_coalesce_usecs;
+ else
+ tx_usecs = coalesce->tx_coalesce_usecs_irq;
+
+ rc = efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive,
+ rx_may_override_tx);
+ if (rc != 0)
+ return rc;
- efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive);
efx_for_each_channel(channel, efx)
efx->type->push_irq_moderation(channel);
@@ -665,12 +682,8 @@ static void efx_ethtool_get_ringparam(struct net_device *net_dev,
ring->rx_max_pending = EFX_MAX_DMAQ_SIZE;
ring->tx_max_pending = EFX_MAX_DMAQ_SIZE;
- ring->rx_mini_max_pending = 0;
- ring->rx_jumbo_max_pending = 0;
ring->rx_pending = efx->rxq_entries;
ring->tx_pending = efx->txq_entries;
- ring->rx_mini_pending = 0;
- ring->rx_jumbo_pending = 0;
}
static int efx_ethtool_set_ringparam(struct net_device *net_dev,
@@ -807,7 +820,7 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
static int
efx_ethtool_get_rxnfc(struct net_device *net_dev,
- struct ethtool_rxnfc *info, void *rules __always_unused)
+ struct ethtool_rxnfc *info, u32 *rules __always_unused)
{
struct efx_nic *efx = netdev_priv(net_dev);
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 94bf4aaf984d..97b606b92e88 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -104,6 +104,8 @@ static void falcon_push_irq_moderation(struct efx_channel *channel)
efx_dword_t timer_cmd;
struct efx_nic *efx = channel->efx;
+ BUILD_BUG_ON(EFX_IRQ_MOD_MAX > (1 << FRF_AB_TC_TIMER_VAL_WIDTH));
+
/* Set timer register */
if (channel->irq_moderation) {
EFX_POPULATE_DWORD_2(timer_cmd,
@@ -1424,7 +1426,8 @@ static int falcon_probe_nic(struct efx_nic *efx)
}
dev = pci_dev_get(efx->pci_dev);
- while ((dev = pci_get_device(EFX_VENDID_SFC, FALCON_A_S_DEVID,
+ while ((dev = pci_get_device(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000A_1,
dev))) {
if (dev->bus == efx->pci_dev->bus &&
dev->devfn == efx->pci_dev->devfn + 1) {
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/ethernet/sfc/falcon_boards.c
index b9cc846811d6..6cc16b8cc6f4 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/ethernet/sfc/falcon_boards.c
@@ -764,7 +764,8 @@ int falcon_probe_board(struct efx_nic *efx, u16 revision_info)
if (board->type) {
netif_info(efx, probe, efx->net_dev, "board is %s rev %c%d\n",
- (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)
+ (efx->pci_dev->subsystem_vendor ==
+ PCI_VENDOR_ID_SOLARFLARE)
? board->type->ref_model : board->type->gen_type,
'A' + board->major, board->minor);
return 0;
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/ethernet/sfc/falcon_xmac.c
index 9516452c079c..9516452c079c 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/ethernet/sfc/falcon_xmac.c
diff --git a/drivers/net/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c
index 2b9636f96e05..2b9636f96e05 100644
--- a/drivers/net/sfc/filter.c
+++ b/drivers/net/ethernet/sfc/filter.c
diff --git a/drivers/net/sfc/filter.h b/drivers/net/ethernet/sfc/filter.h
index 872f2132a496..872f2132a496 100644
--- a/drivers/net/sfc/filter.h
+++ b/drivers/net/ethernet/sfc/filter.h
diff --git a/drivers/net/sfc/io.h b/drivers/net/ethernet/sfc/io.h
index 751d1ec112cc..751d1ec112cc 100644
--- a/drivers/net/sfc/io.h
+++ b/drivers/net/ethernet/sfc/io.h
diff --git a/drivers/net/sfc/mac.h b/drivers/net/ethernet/sfc/mac.h
index d6a255d0856b..d6a255d0856b 100644
--- a/drivers/net/sfc/mac.h
+++ b/drivers/net/ethernet/sfc/mac.h
diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 81a425397468..81a425397468 100644
--- a/drivers/net/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
diff --git a/drivers/net/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index aced2a7856fc..aced2a7856fc 100644
--- a/drivers/net/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
diff --git a/drivers/net/sfc/mcdi_mac.c b/drivers/net/ethernet/sfc/mcdi_mac.c
index 50c20777a564..50c20777a564 100644
--- a/drivers/net/sfc/mcdi_mac.c
+++ b/drivers/net/ethernet/sfc/mcdi_mac.c
diff --git a/drivers/net/sfc/mcdi_pcol.h b/drivers/net/ethernet/sfc/mcdi_pcol.h
index 41fe06fa0600..41fe06fa0600 100644
--- a/drivers/net/sfc/mcdi_pcol.h
+++ b/drivers/net/ethernet/sfc/mcdi_pcol.h
diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/ethernet/sfc/mcdi_phy.c
index 6c63ab0710af..6c63ab0710af 100644
--- a/drivers/net/sfc/mcdi_phy.c
+++ b/drivers/net/ethernet/sfc/mcdi_phy.c
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/ethernet/sfc/mdio_10g.c
index 7ab385c8136d..7ab385c8136d 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/ethernet/sfc/mdio_10g.c
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/ethernet/sfc/mdio_10g.h
index a97dbbd2de99..a97dbbd2de99 100644
--- a/drivers/net/sfc/mdio_10g.h
+++ b/drivers/net/ethernet/sfc/mdio_10g.h
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/ethernet/sfc/mtd.c
index b6304486f244..b6304486f244 100644
--- a/drivers/net/sfc/mtd.c
+++ b/drivers/net/ethernet/sfc/mtd.c
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index b8e251a1ee48..b8e251a1ee48 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
diff --git a/drivers/net/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 3edfbaf5f022..3edfbaf5f022 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
diff --git a/drivers/net/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 7443f99c977f..5fb24d3aa3ca 100644
--- a/drivers/net/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -202,7 +202,8 @@ extern irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx);
extern irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id);
extern void falcon_irq_ack_a1(struct efx_nic *efx);
-#define EFX_IRQ_MOD_RESOLUTION 5
+#define EFX_IRQ_MOD_RESOLUTION 5
+#define EFX_IRQ_MOD_MAX 0x1000
/* Global Resources */
extern int efx_nic_flush_queues(struct efx_nic *efx);
diff --git a/drivers/net/sfc/phy.h b/drivers/net/ethernet/sfc/phy.h
index 11d148cd8441..11d148cd8441 100644
--- a/drivers/net/sfc/phy.h
+++ b/drivers/net/ethernet/sfc/phy.h
diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/ethernet/sfc/qt202x_phy.c
index 7ad97e397406..7ad97e397406 100644
--- a/drivers/net/sfc/qt202x_phy.c
+++ b/drivers/net/ethernet/sfc/qt202x_phy.c
diff --git a/drivers/net/sfc/regs.h b/drivers/net/ethernet/sfc/regs.h
index cc2c86b76a7b..cc2c86b76a7b 100644
--- a/drivers/net/sfc/regs.h
+++ b/drivers/net/ethernet/sfc/regs.h
diff --git a/drivers/net/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 62e43649466e..adbda182f159 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -478,10 +478,10 @@ static void efx_rx_packet_gro(struct efx_channel *channel,
if (efx->net_dev->features & NETIF_F_RXHASH)
skb->rxhash = efx_rx_buf_hash(eh);
- skb_shinfo(skb)->frags[0].page = page;
+ skb_frag_set_page(skb, 0, page);
skb_shinfo(skb)->frags[0].page_offset =
efx_rx_buf_offset(efx, rx_buf);
- skb_shinfo(skb)->frags[0].size = rx_buf->len;
+ skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx_buf->len);
skb_shinfo(skb)->nr_frags = 1;
skb->len = rx_buf->len;
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index 822f6c2a6a7c..822f6c2a6a7c 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
diff --git a/drivers/net/sfc/selftest.h b/drivers/net/ethernet/sfc/selftest.h
index dba5456e70f3..dba5456e70f3 100644
--- a/drivers/net/sfc/selftest.h
+++ b/drivers/net/ethernet/sfc/selftest.h
diff --git a/drivers/net/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 2c3bd93fab54..cc2549cb7076 100644
--- a/drivers/net/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -36,6 +36,8 @@ static void siena_push_irq_moderation(struct efx_channel *channel)
{
efx_dword_t timer_cmd;
+ BUILD_BUG_ON(EFX_IRQ_MOD_MAX > (1 << FRF_CZ_TC_TIMER_VAL_WIDTH));
+
if (channel->irq_moderation)
EFX_POPULATE_DWORD_2(timer_cmd,
FRF_CZ_TC_TIMER_MODE,
diff --git a/drivers/net/sfc/spi.h b/drivers/net/ethernet/sfc/spi.h
index 71f2e3ebe1c7..71f2e3ebe1c7 100644
--- a/drivers/net/sfc/spi.h
+++ b/drivers/net/ethernet/sfc/spi.h
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/ethernet/sfc/tenxpress.c
index 7b0fd89e7b85..7b0fd89e7b85 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/ethernet/sfc/tenxpress.c
diff --git a/drivers/net/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 84eb99e0f8d2..df88c5430f95 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -137,8 +137,6 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
struct pci_dev *pci_dev = efx->pci_dev;
struct efx_tx_buffer *buffer;
skb_frag_t *fragment;
- struct page *page;
- int page_offset;
unsigned int len, unmap_len = 0, fill_level, insert_ptr;
dma_addr_t dma_addr, unmap_addr = 0;
unsigned int dma_len;
@@ -240,14 +238,12 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
if (i >= skb_shinfo(skb)->nr_frags)
break;
fragment = &skb_shinfo(skb)->frags[i];
- len = fragment->size;
- page = fragment->page;
- page_offset = fragment->page_offset;
+ len = skb_frag_size(fragment);
i++;
/* Map for DMA */
unmap_single = false;
- dma_addr = pci_map_page(pci_dev, page, page_offset, len,
- PCI_DMA_TODEVICE);
+ dma_addr = skb_frag_dma_map(&pci_dev->dev, fragment, 0, len,
+ DMA_TO_DEVICE);
}
/* Transfer ownership of the skb to the final buffer */
@@ -929,13 +925,12 @@ static void tso_start(struct tso_state *st, const struct sk_buff *skb)
static int tso_get_fragment(struct tso_state *st, struct efx_nic *efx,
skb_frag_t *frag)
{
- st->unmap_addr = pci_map_page(efx->pci_dev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
- if (likely(!pci_dma_mapping_error(efx->pci_dev, st->unmap_addr))) {
+ st->unmap_addr = skb_frag_dma_map(&efx->pci_dev->dev, frag, 0,
+ skb_frag_size(frag), DMA_TO_DEVICE);
+ if (likely(!dma_mapping_error(&efx->pci_dev->dev, st->unmap_addr))) {
st->unmap_single = false;
- st->unmap_len = frag->size;
- st->in_len = frag->size;
+ st->unmap_len = skb_frag_size(frag);
+ st->in_len = skb_frag_size(frag);
st->dma_addr = st->unmap_addr;
return 0;
}
diff --git a/drivers/net/sfc/txc43128_phy.c b/drivers/net/ethernet/sfc/txc43128_phy.c
index 7c21b334a75b..7c21b334a75b 100644
--- a/drivers/net/sfc/txc43128_phy.c
+++ b/drivers/net/ethernet/sfc/txc43128_phy.c
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/ethernet/sfc/workarounds.h
index e4dd3a7f304b..e4dd3a7f304b 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/ethernet/sfc/workarounds.h
diff --git a/drivers/net/ethernet/sgi/Kconfig b/drivers/net/ethernet/sgi/Kconfig
new file mode 100644
index 000000000000..c1c4bb868a3b
--- /dev/null
+++ b/drivers/net/ethernet/sgi/Kconfig
@@ -0,0 +1,36 @@
+#
+# SGI device configuration
+#
+
+config NET_VENDOR_SGI
+ bool "SGI devices"
+ default y
+ depends on (PCI && SGI_IP27) || SGI_IP32
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about SGI devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_SGI
+
+config SGI_IOC3_ETH
+ bool "SGI IOC3 Ethernet"
+ depends on PCI && SGI_IP27
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+config SGI_O2MACE_ETH
+ tristate "SGI O2 MACE Fast Ethernet support"
+ depends on SGI_IP32=y
+
+endif # NET_VENDOR_SGI
diff --git a/drivers/net/ethernet/sgi/Makefile b/drivers/net/ethernet/sgi/Makefile
new file mode 100644
index 000000000000..e5bedd271e29
--- /dev/null
+++ b/drivers/net/ethernet/sgi/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the SGI device drivers.
+#
+
+obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o
+obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
index a234e4504522..ac149d99f78f 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -1220,7 +1220,7 @@ static const struct net_device_ops ioc3_netdev_ops = {
.ndo_start_xmit = ioc3_start_xmit,
.ndo_tx_timeout = ioc3_timeout,
.ndo_get_stats = ioc3_get_stats,
- .ndo_set_multicast_list = ioc3_set_multicast_list,
+ .ndo_set_rx_mode = ioc3_set_multicast_list,
.ndo_do_ioctl = ioc3_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ioc3_set_mac_address,
diff --git a/drivers/net/meth.c b/drivers/net/ethernet/sgi/meth.c
index 60135aa55802..60135aa55802 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/ethernet/sgi/meth.c
diff --git a/drivers/net/meth.h b/drivers/net/ethernet/sgi/meth.h
index 5b145c6bad60..5b145c6bad60 100644
--- a/drivers/net/meth.h
+++ b/drivers/net/ethernet/sgi/meth.h
diff --git a/drivers/net/ethernet/sis/Kconfig b/drivers/net/ethernet/sis/Kconfig
new file mode 100644
index 000000000000..f1135cc1bd48
--- /dev/null
+++ b/drivers/net/ethernet/sis/Kconfig
@@ -0,0 +1,53 @@
+#
+# Silicon Integrated Systems (SiS) device configuration
+#
+
+config NET_VENDOR_SIS
+ bool "Silicon Integrated Systems (SiS) devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about SiS devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_SIS
+
+config SIS900
+ tristate "SiS 900/7016 PCI Fast Ethernet Adapter support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This is a driver for the Fast Ethernet PCI network cards based on
+ the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in
+ SiS 630 and SiS 540 chipsets.
+
+ This driver also supports AMD 79C901 HomePNA so that you can use
+ your phone line as a network cable.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sis900. This is recommended.
+
+config SIS190
+ tristate "SiS190/SiS191 gigabit ethernet support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or
+ a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to
+ appear in lan on motherboard designs which are based on SiS 965
+ and SiS 966 south bridge.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sis190. This is recommended.
+
+endif # NET_VENDOR_SIS
diff --git a/drivers/net/ethernet/sis/Makefile b/drivers/net/ethernet/sis/Makefile
new file mode 100644
index 000000000000..58d3ac1985df
--- /dev/null
+++ b/drivers/net/ethernet/sis/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Silicon Integrated Systems (SiS) network device drivers.
+#
+
+obj-$(CONFIG_SIS190) += sis190.o
+obj-$(CONFIG_SIS900) += sis900.o
diff --git a/drivers/net/sis190.c b/drivers/net/ethernet/sis/sis190.c
index 3c0f1312b391..1b4658c99391 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/ethernet/sis/sis190.c
@@ -1841,7 +1841,7 @@ static const struct net_device_ops sis190_netdev_ops = {
.ndo_do_ioctl = sis190_ioctl,
.ndo_start_xmit = sis190_start_xmit,
.ndo_tx_timeout = sis190_tx_timeout,
- .ndo_set_multicast_list = sis190_set_rx_mode,
+ .ndo_set_rx_mode = sis190_set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = sis190_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/sis900.c b/drivers/net/ethernet/sis/sis900.c
index 658a1928fe79..a184abc5ef11 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -403,7 +403,7 @@ static const struct net_device_ops sis900_netdev_ops = {
.ndo_stop = sis900_close,
.ndo_start_xmit = sis900_start_xmit,
.ndo_set_config = sis900_set_config,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/sis900.h b/drivers/net/ethernet/sis/sis900.h
index 150511a922ef..150511a922ef 100644
--- a/drivers/net/sis900.h
+++ b/drivers/net/ethernet/sis/sis900.h
diff --git a/drivers/net/ethernet/smsc/Kconfig b/drivers/net/ethernet/smsc/Kconfig
new file mode 100644
index 000000000000..5a689af516e9
--- /dev/null
+++ b/drivers/net/ethernet/smsc/Kconfig
@@ -0,0 +1,136 @@
+#
+# Western Digital/SMC network device configuration
+#
+
+config NET_VENDOR_SMSC
+ bool "SMC (SMSC)/Western Digital devices"
+ default y
+ depends on ARM || ISA || MAC || ARM || MIPS || M32R || SUPERH || \
+ BLACKFIN || MN10300 || COLDFIRE || PCI || PCMCIA
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about SMC/Western Digital cards. If you say Y, you will
+ be asked for your specific card in the following questions.
+
+if NET_VENDOR_SMSC
+
+config SMC9194
+ tristate "SMC 9194 support"
+ depends on (ISA || MAC && BROKEN)
+ select CRC32
+ ---help---
+ This is support for the SMC9xxx based Ethernet cards. Choose this
+ option if you have a DELL laptop with the docking station, or
+ another SMC9192/9194 based chipset. Say Y if you want it compiled
+ into the kernel, and read the file
+ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here. The module
+ will be called smc9194.
+
+config SMC91X
+ tristate "SMC 91C9x/91C1xxx support"
+ select CRC32
+ select NET_CORE
+ select MII
+ depends on (ARM || M32R || SUPERH || MIPS || BLACKFIN || \
+ MN10300 || COLDFIRE)
+ ---help---
+ This is a driver for SMC's 91x series of Ethernet chipsets,
+ including the SMC91C94 and the SMC91C111. Say Y if you want it
+ compiled into the kernel, and read the file
+ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called smc91x. If you want to compile it as a
+ module, say M here and read <file:Documentation/kbuild/modules.txt>.
+
+config PCMCIA_SMC91C92
+ tristate "SMC 91Cxx PCMCIA support"
+ depends on PCMCIA
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA
+ (PC-card) Ethernet or Fast Ethernet card to your computer.
+
+ To compile this driver as a module, choose M here: the module will be
+ called smc91c92_cs. If unsure, say N.
+
+config EPIC100
+ tristate "SMC EtherPower II"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC,
+ which is based on the SMC83c17x (EPIC/100).
+ More specific information and updates are available from
+ <http://www.scyld.com/network/epic100.html>.
+
+config SMC911X
+ tristate "SMSC LAN911[5678] support"
+ select CRC32
+ select NET_CORE
+ select MII
+ depends on (ARM || SUPERH || MN10300)
+ ---help---
+ This is a driver for SMSC's LAN911x series of Ethernet chipsets
+ including the new LAN9115, LAN9116, LAN9117, and LAN9118.
+ Say Y if you want it compiled into the kernel,
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module. The module will be
+ called smc911x. If you want to compile it as a module, say M
+ here and read <file:Documentation/kbuild/modules.txt>
+
+config SMSC911X
+ tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
+ depends on (ARM || SUPERH || BLACKFIN || MIPS || MN10300)
+ select CRC32
+ select NET_CORE
+ select MII
+ select PHYLIB
+ ---help---
+ Say Y here if you want support for SMSC LAN911x and LAN921x families
+ of ethernet controllers.
+
+ To compile this driver as a module, choose M here. The module
+ will be called smsc911x.
+
+config SMSC911X_ARCH_HOOKS
+ def_bool n
+ depends on SMSC911X
+ ---help---
+ If the arch enables this, it allows the arch to implement various
+ hooks for more comprehensive interrupt control and also to override
+ the source of the MAC address.
+
+config SMSC9420
+ tristate "SMSC LAN9420 PCI ethernet adapter support"
+ depends on PCI
+ select CRC32
+ select PHYLIB
+ select SMSC_PHY
+ ---help---
+ This is a driver for SMSC's LAN9420 PCI ethernet adapter.
+ Say Y if you want it compiled into the kernel,
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module. The module will be
+ called smsc9420. If you want to compile it as a module, say M
+ here and read <file:Documentation/kbuild/modules.txt>
+
+endif # NET_VENDOR_SMSC
diff --git a/drivers/net/ethernet/smsc/Makefile b/drivers/net/ethernet/smsc/Makefile
new file mode 100644
index 000000000000..f3438dec9d90
--- /dev/null
+++ b/drivers/net/ethernet/smsc/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the SMSC network device drivers.
+#
+
+obj-$(CONFIG_SMC9194) += smc9194.o
+obj-$(CONFIG_SMC91X) += smc91x.o
+obj-$(CONFIG_PCMCIA_SMC91C92) += smc91c92_cs.o
+obj-$(CONFIG_EPIC100) += epic100.o
+obj-$(CONFIG_SMSC9420) += smsc9420.o
+obj-$(CONFIG_SMC911X) += smc911x.o
+obj-$(CONFIG_SMSC911X) += smsc911x.o
diff --git a/drivers/net/epic100.c b/drivers/net/ethernet/smsc/epic100.c
index 814c187d5f95..0a5dfb814157 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/ethernet/smsc/epic100.c
@@ -314,7 +314,7 @@ static const struct net_device_ops epic_netdev_ops = {
.ndo_start_xmit = epic_start_xmit,
.ndo_tx_timeout = epic_tx_timeout,
.ndo_get_stats = epic_get_stats,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = netdev_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index a91fe1723020..8f61fe9db1d0 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -1768,7 +1768,7 @@ static const struct net_device_ops smc911x_netdev_ops = {
.ndo_stop = smc911x_close,
.ndo_start_xmit = smc911x_hard_start_xmit,
.ndo_tx_timeout = smc911x_timeout,
- .ndo_set_multicast_list = smc911x_set_multicast_list,
+ .ndo_set_rx_mode = smc911x_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/smc911x.h b/drivers/net/ethernet/smsc/smc911x.h
index 3269292efecc..3269292efecc 100644
--- a/drivers/net/smc911x.h
+++ b/drivers/net/ethernet/smsc/smc911x.h
diff --git a/drivers/net/smc9194.c b/drivers/net/ethernet/smsc/smc9194.c
index 5b65ac4b3cef..4e45094efb18 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/ethernet/smsc/smc9194.c
@@ -827,7 +827,7 @@ static const struct net_device_ops smc_netdev_ops = {
.ndo_stop = smc_close,
.ndo_start_xmit = smc_wait_to_send_packet,
.ndo_tx_timeout = smc_timeout,
- .ndo_set_multicast_list = smc_set_multicast_list,
+ .ndo_set_rx_mode = smc_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/smc9194.h b/drivers/net/ethernet/smsc/smc9194.h
index cf69d0a5a1cb..cf69d0a5a1cb 100644
--- a/drivers/net/smc9194.h
+++ b/drivers/net/ethernet/smsc/smc9194.h
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c
index cffbc0373fa9..cbfa98187131 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/ethernet/smsc/smc91c92_cs.c
@@ -294,7 +294,7 @@ static const struct net_device_ops smc_netdev_ops = {
.ndo_start_xmit = smc_start_xmit,
.ndo_tx_timeout = smc_tx_timeout,
.ndo_set_config = s9k_config,
- .ndo_set_multicast_list = set_rx_mode,
+ .ndo_set_rx_mode = set_rx_mode,
.ndo_do_ioctl = smc_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 2b1d254d59af..f47f81e25322 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -1768,7 +1768,7 @@ static const struct net_device_ops smc_netdev_ops = {
.ndo_stop = smc_close,
.ndo_start_xmit = smc_hard_start_xmit,
.ndo_tx_timeout = smc_timeout,
- .ndo_set_multicast_list = smc_set_multicast_list,
+ .ndo_set_rx_mode = smc_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index 5f53fbbf67be..5f53fbbf67be 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
diff --git a/drivers/net/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index c90ddb61cc56..d2be42aafbef 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -54,6 +54,10 @@
#include <linux/phy.h>
#include <linux/smsc911x.h>
#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_net.h>
#include "smsc911x.h"
#define SMSC_CHIPNAME "smsc911x"
@@ -1903,7 +1907,7 @@ static const struct net_device_ops smsc911x_netdev_ops = {
.ndo_stop = smsc911x_stop,
.ndo_start_xmit = smsc911x_hard_start_xmit,
.ndo_get_stats = smsc911x_get_stats,
- .ndo_set_multicast_list = smsc911x_set_multicast_list,
+ .ndo_set_rx_mode = smsc911x_set_multicast_list,
.ndo_do_ioctl = smsc911x_do_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
@@ -2097,8 +2101,60 @@ static const struct smsc911x_ops shifted_smsc911x_ops = {
.tx_writefifo = smsc911x_tx_writefifo_shift,
};
+#ifdef CONFIG_OF
+static int __devinit smsc911x_probe_config_dt(
+ struct smsc911x_platform_config *config,
+ struct device_node *np)
+{
+ const char *mac;
+ u32 width = 0;
+
+ if (!np)
+ return -ENODEV;
+
+ config->phy_interface = of_get_phy_mode(np);
+
+ mac = of_get_mac_address(np);
+ if (mac)
+ memcpy(config->mac, mac, ETH_ALEN);
+
+ of_property_read_u32(np, "reg-shift", &config->shift);
+
+ of_property_read_u32(np, "reg-io-width", &width);
+ if (width == 4)
+ config->flags |= SMSC911X_USE_32BIT;
+ else
+ config->flags |= SMSC911X_USE_16BIT;
+
+ if (of_get_property(np, "smsc,irq-active-high", NULL))
+ config->irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH;
+
+ if (of_get_property(np, "smsc,irq-push-pull", NULL))
+ config->irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL;
+
+ if (of_get_property(np, "smsc,force-internal-phy", NULL))
+ config->flags |= SMSC911X_FORCE_INTERNAL_PHY;
+
+ if (of_get_property(np, "smsc,force-external-phy", NULL))
+ config->flags |= SMSC911X_FORCE_EXTERNAL_PHY;
+
+ if (of_get_property(np, "smsc,save-mac-address", NULL))
+ config->flags |= SMSC911X_SAVE_MAC_ADDRESS;
+
+ return 0;
+}
+#else
+static inline int smsc911x_probe_config_dt(
+ struct smsc911x_platform_config *config,
+ struct device_node *np)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_OF */
+
static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct net_device *dev;
struct smsc911x_data *pdata;
struct smsc911x_platform_config *config = pdev->dev.platform_data;
@@ -2109,13 +2165,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
pr_info("Driver version %s\n", SMSC_DRV_VERSION);
- /* platform data specifies irq & dynamic bus configuration */
- if (!pdev->dev.platform_data) {
- pr_warn("platform_data not provided\n");
- retval = -ENODEV;
- goto out_0;
- }
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"smsc911x-memory");
if (!res)
@@ -2154,9 +2203,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
irq_flags = irq_res->flags & IRQF_TRIGGER_MASK;
pdata->ioaddr = ioremap_nocache(res->start, res_size);
- /* copy config parameters across to pdata */
- memcpy(&pdata->config, config, sizeof(pdata->config));
-
pdata->dev = dev;
pdata->msg_enable = ((1 << debug) - 1);
@@ -2166,10 +2212,22 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
goto out_free_netdev_2;
}
+ retval = smsc911x_probe_config_dt(&pdata->config, np);
+ if (retval && config) {
+ /* copy config parameters across to pdata */
+ memcpy(&pdata->config, config, sizeof(pdata->config));
+ retval = 0;
+ }
+
+ if (retval) {
+ SMSC_WARN(pdata, probe, "Error smsc911x config not found");
+ goto out_unmap_io_3;
+ }
+
/* assume standard, non-shifted, access to HW registers */
pdata->ops = &standard_smsc911x_ops;
/* apply the right access if shifting is needed */
- if (config->shift)
+ if (pdata->config.shift)
pdata->ops = &shifted_smsc911x_ops;
retval = smsc911x_init(dev);
@@ -2316,6 +2374,12 @@ static const struct dev_pm_ops smsc911x_pm_ops = {
#define SMSC911X_PM_OPS NULL
#endif
+static const struct of_device_id smsc911x_dt_ids[] = {
+ { .compatible = "smsc,lan9115", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, smsc911x_dt_ids);
+
static struct platform_driver smsc911x_driver = {
.probe = smsc911x_drv_probe,
.remove = __devexit_p(smsc911x_drv_remove),
@@ -2323,6 +2387,7 @@ static struct platform_driver smsc911x_driver = {
.name = SMSC_CHIPNAME,
.owner = THIS_MODULE,
.pm = SMSC911X_PM_OPS,
+ .of_match_table = smsc911x_dt_ids,
},
};
diff --git a/drivers/net/smsc911x.h b/drivers/net/ethernet/smsc/smsc911x.h
index 8d67aacf8867..8d67aacf8867 100644
--- a/drivers/net/smsc911x.h
+++ b/drivers/net/ethernet/smsc/smsc911x.h
diff --git a/drivers/net/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
index 459726f54754..4f15680849ff 100644
--- a/drivers/net/smsc9420.c
+++ b/drivers/net/ethernet/smsc/smsc9420.c
@@ -1566,7 +1566,7 @@ static const struct net_device_ops smsc9420_netdev_ops = {
.ndo_stop = smsc9420_stop,
.ndo_start_xmit = smsc9420_hard_start_xmit,
.ndo_get_stats = smsc9420_get_stats,
- .ndo_set_multicast_list = smsc9420_set_multicast_list,
+ .ndo_set_rx_mode = smsc9420_set_multicast_list,
.ndo_do_ioctl = smsc9420_do_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/smsc9420.h b/drivers/net/ethernet/smsc/smsc9420.h
index e441402f77a2..e441402f77a2 100644
--- a/drivers/net/smsc9420.h
+++ b/drivers/net/ethernet/smsc/smsc9420.h
diff --git a/drivers/net/ethernet/stmicro/Kconfig b/drivers/net/ethernet/stmicro/Kconfig
new file mode 100644
index 000000000000..f4a80da00650
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/Kconfig
@@ -0,0 +1,23 @@
+#
+# STMicroelectronics device configuration
+#
+
+config NET_VENDOR_STMICRO
+ bool "STMicroelectronics devices"
+ default y
+ depends on HAS_IOMEM
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about STMicroelectronics cards. If you say Y, you will
+ be asked for your specific card in the following questions.
+
+if NET_VENDOR_STMICRO
+
+source "drivers/net/ethernet/stmicro/stmmac/Kconfig"
+
+endif # NET_VENDOR_STMICRO
diff --git a/drivers/net/ethernet/stmicro/Makefile b/drivers/net/ethernet/stmicro/Makefile
new file mode 100644
index 000000000000..9b3bfddda7dd
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the STMicroelectronics device drivers.
+#
+
+obj-$(CONFIG_STMMAC_ETH) += stmmac/
diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 7df7df4e79c5..ac6f190743dd 100644
--- a/drivers/net/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -1,20 +1,29 @@
config STMMAC_ETH
tristate "STMicroelectronics 10/100/1000 Ethernet driver"
+ depends on HAS_IOMEM
+ select NET_CORE
select MII
select PHYLIB
select CRC32
- depends on NETDEVICES && HAS_IOMEM
- help
+ ---help---
This is the driver for the Ethernet IPs are built around a
Synopsys IP Core and only tested on the STMicroelectronics
platforms.
if STMMAC_ETH
+config STMMAC_DEBUG_FS
+ bool "Enable monitoring via sysFS "
+ default n
+ depends on STMMAC_ETH && DEBUG_FS
+ -- help
+ The stmmac entry in /sys reports DMA TX/RX rings
+ or (if supported) the HW cap register.
+
config STMMAC_DA
bool "STMMAC DMA arbitration scheme"
default n
- help
+ ---help---
Selecting this option, rx has priority over Tx (only for Giga
Ethernet device).
By default, the DMA arbitration scheme is based on Round-robin
@@ -24,7 +33,7 @@ config STMMAC_DUAL_MAC
bool "STMMAC: dual mac support (EXPERIMENTAL)"
default n
depends on EXPERIMENTAL && STMMAC_ETH && !STMMAC_TIMER
- help
+ ---help---
Some ST SoCs (for example the stx7141 and stx7200c2) have two
Ethernet Controllers. This option turns on the second Ethernet
device on this kind of platforms.
@@ -33,7 +42,7 @@ config STMMAC_TIMER
bool "STMMAC Timer optimisation"
default n
depends on RTC_HCTOSYS_DEVICE
- help
+ ---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.
@@ -45,13 +54,31 @@ choice
config STMMAC_TMU_TIMER
bool "TMU channel 2"
depends on CPU_SH4
- help
+ ---help---
config STMMAC_RTC_TIMER
bool "Real time clock"
depends on RTC_CLASS
- help
+ ---help---
endchoice
+choice
+ prompt "Select the DMA TX/RX descriptor operating modes"
+ depends on STMMAC_ETH
+ ---help---
+ This driver supports DMA descriptor to operate both in dual buffer
+ (RING) and linked-list(CHAINED) mode. In RING mode each descriptor
+ points to two data buffer pointers whereas in CHAINED mode they
+ points to only one data buffer pointer.
+
+config STMMAC_RING
+ bool "Enable Descriptor Ring Mode"
+
+config STMMAC_CHAINED
+ bool "Enable Descriptor Chained Mode"
+
+endchoice
+
+
endif
diff --git a/drivers/net/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 9691733ddb8e..d7c45164ea79 100644
--- a/drivers/net/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,5 +1,8 @@
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-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \
dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
- dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o $(stmmac-y)
+ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
+ mmc_core.o $(stmmac-y)
diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
new file mode 100644
index 000000000000..0668659803ed
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ Specialised functions for managing Chained mode
+
+ Copyright(C) 2011 STMicroelectronics Ltd
+
+ It defines all the functions used to handle the normal/enhanced
+ descriptors in case of the DMA is configured to work in chained or
+ in ring mode.
+
+ 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 "stmmac.h"
+
+unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
+{
+ struct stmmac_priv *priv = (struct stmmac_priv *) p;
+ unsigned int txsize = priv->dma_tx_size;
+ unsigned int entry = priv->cur_tx % txsize;
+ struct dma_desc *desc = priv->dma_tx + entry;
+ unsigned int nopaged_len = skb_headlen(skb);
+ unsigned int bmax;
+ unsigned int i = 1, len;
+
+ if (priv->plat->enh_desc)
+ bmax = BUF_SIZE_8KiB;
+ else
+ bmax = BUF_SIZE_2KiB;
+
+ len = nopaged_len - bmax;
+
+ desc->des2 = dma_map_single(priv->device, skb->data,
+ bmax, DMA_TO_DEVICE);
+ priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum);
+
+ while (len != 0) {
+ entry = (++priv->cur_tx) % txsize;
+ desc = priv->dma_tx + entry;
+
+ if (len > bmax) {
+ desc->des2 = dma_map_single(priv->device,
+ (skb->data + bmax * i),
+ bmax, DMA_TO_DEVICE);
+ priv->hw->desc->prepare_tx_desc(desc, 0, bmax,
+ csum);
+ priv->hw->desc->set_tx_owner(desc);
+ priv->tx_skbuff[entry] = NULL;
+ len -= bmax;
+ i++;
+ } else {
+ desc->des2 = dma_map_single(priv->device,
+ (skb->data + bmax * i), len,
+ DMA_TO_DEVICE);
+ priv->hw->desc->prepare_tx_desc(desc, 0, len,
+ csum);
+ priv->hw->desc->set_tx_owner(desc);
+ priv->tx_skbuff[entry] = NULL;
+ len = 0;
+ }
+ }
+ return entry;
+}
+
+static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
+{
+ unsigned int ret = 0;
+
+ if ((enh_desc && (len > BUF_SIZE_8KiB)) ||
+ (!enh_desc && (len > BUF_SIZE_2KiB))) {
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
+{
+}
+
+static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
+{
+}
+
+static void stmmac_clean_desc3(struct dma_desc *p)
+{
+}
+
+static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
+ unsigned int size)
+{
+ /*
+ * In chained mode the des3 points to the next element in the ring.
+ * The latest element has to point to the head.
+ */
+ int i;
+ struct dma_desc *p = des;
+ dma_addr_t dma_phy = phy_addr;
+
+ for (i = 0; i < (size - 1); i++) {
+ dma_phy += sizeof(struct dma_desc);
+ p->des3 = (unsigned int)dma_phy;
+ p++;
+ }
+ p->des3 = (unsigned int)phy_addr;
+}
+
+static int stmmac_set_16kib_bfsize(int mtu)
+{
+ /* Not supported */
+ return 0;
+}
+
+const struct stmmac_ring_mode_ops ring_mode_ops = {
+ .is_jumbo_frm = stmmac_is_jumbo_frm,
+ .jumbo_frm = stmmac_jumbo_frm,
+ .refill_desc3 = stmmac_refill_desc3,
+ .init_desc3 = stmmac_init_desc3,
+ .init_dma_chain = stmmac_init_dma_chain,
+ .clean_desc3 = stmmac_clean_desc3,
+ .set_16kib_bfsize = stmmac_set_16kib_bfsize,
+};
diff --git a/drivers/net/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 375ea193e139..2cc119295821 100644
--- a/drivers/net/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -29,6 +29,7 @@
#endif
#include "descs.h"
+#include "mmc.h"
#undef CHIP_DEBUG_PRINT
/* Turn-on extra printk debug for MAC core, dma and descriptors */
@@ -48,7 +49,7 @@ struct stmmac_extra_stats {
unsigned long tx_underflow ____cacheline_aligned;
unsigned long tx_carrier;
unsigned long tx_losscarrier;
- unsigned long tx_heartbeat;
+ unsigned long vlan_tag;
unsigned long tx_deferred;
unsigned long tx_vlan;
unsigned long tx_jabber;
@@ -57,9 +58,9 @@ struct stmmac_extra_stats {
unsigned long tx_ip_header_error;
/* Receive errors */
unsigned long rx_desc;
- unsigned long rx_partial;
- unsigned long rx_runt;
- unsigned long rx_toolong;
+ unsigned long sa_filter_fail;
+ unsigned long overflow_error;
+ unsigned long ipc_csum_error;
unsigned long rx_collision;
unsigned long rx_crc;
unsigned long rx_length;
@@ -102,6 +103,36 @@ struct stmmac_extra_stats {
#define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */
+/* DAM HW feature register fields */
+#define DMA_HW_FEAT_MIISEL 0x00000001 /* 10/100 Mbps Support */
+#define DMA_HW_FEAT_GMIISEL 0x00000002 /* 1000 Mbps Support */
+#define DMA_HW_FEAT_HDSEL 0x00000004 /* Half-Duplex Support */
+#define DMA_HW_FEAT_EXTHASHEN 0x00000008 /* Expanded DA Hash Filter */
+#define DMA_HW_FEAT_HASHSEL 0x00000010 /* HASH Filter */
+#define DMA_HW_FEAT_ADDMACADRSEL 0x00000020 /* Multiple MAC Addr Reg */
+#define DMA_HW_FEAT_PCSSEL 0x00000040 /* PCS registers */
+#define DMA_HW_FEAT_L3L4FLTREN 0x00000080 /* Layer 3 & Layer 4 Feature */
+#define DMA_HW_FEAT_SMASEL 0x00000100 /* SMA(MDIO) Interface */
+#define DMA_HW_FEAT_RWKSEL 0x00000200 /* PMT Remote Wakeup */
+#define DMA_HW_FEAT_MGKSEL 0x00000400 /* PMT Magic Packet */
+#define DMA_HW_FEAT_MMCSEL 0x00000800 /* RMON Module */
+#define DMA_HW_FEAT_TSVER1SEL 0x00001000 /* Only IEEE 1588-2002 Timestamp */
+#define DMA_HW_FEAT_TSVER2SEL 0x00002000 /* IEEE 1588-2008 Adv Timestamp */
+#define DMA_HW_FEAT_EEESEL 0x00004000 /* Energy Efficient Ethernet */
+#define DMA_HW_FEAT_AVSEL 0x00008000 /* AV Feature */
+#define DMA_HW_FEAT_TXCOESEL 0x00010000 /* Checksum Offload in Tx */
+#define DMA_HW_FEAT_RXTYP1COE 0x00020000 /* IP csum Offload(Type 1) in Rx */
+#define DMA_HW_FEAT_RXTYP2COE 0x00040000 /* IP csum Offload(Type 2) in Rx */
+#define DMA_HW_FEAT_RXFIFOSIZE 0x00080000 /* Rx FIFO > 2048 Bytes */
+#define DMA_HW_FEAT_RXCHCNT 0x00300000 /* No. of additional Rx Channels */
+#define DMA_HW_FEAT_TXCHCNT 0x00c00000 /* No. of additional Tx Channels */
+#define DMA_HW_FEAT_ENHDESSEL 0x01000000 /* Alternate (Enhanced Descriptor) */
+#define DMA_HW_FEAT_INTTSEN 0x02000000 /* Timestamping with Internal
+ System Time */
+#define DMA_HW_FEAT_FLEXIPPSEN 0x04000000 /* Flexible PPS Output */
+#define DMA_HW_FEAT_SAVLANINS 0x08000000 /* Source Addr or VLAN Insertion */
+#define DMA_HW_FEAT_ACTPHYIF 0x70000000 /* Active/selected PHY interface */
+
enum rx_frame_status { /* IPC status */
good_frame = 0,
discard_frame = 1,
@@ -115,6 +146,37 @@ enum tx_dma_irq_status {
handle_tx_rx = 3,
};
+/* DMA HW capabilities */
+struct dma_features {
+ unsigned int mbps_10_100;
+ unsigned int mbps_1000;
+ unsigned int half_duplex;
+ unsigned int hash_filter;
+ unsigned int multi_addr;
+ unsigned int pcs;
+ unsigned int sma_mdio;
+ unsigned int pmt_remote_wake_up;
+ unsigned int pmt_magic_frame;
+ unsigned int rmon;
+ /* IEEE 1588-2002*/
+ unsigned int time_stamp;
+ /* IEEE 1588-2008*/
+ unsigned int atime_stamp;
+ /* 802.3az - Energy-Efficient Ethernet (EEE) */
+ unsigned int eee;
+ unsigned int av;
+ /* TX and RX csum */
+ unsigned int tx_coe;
+ unsigned int rx_coe_type1;
+ unsigned int rx_coe_type2;
+ unsigned int rxfifo_over_2048;
+ /* TX and RX number of channels */
+ unsigned int number_rx_channel;
+ unsigned int number_tx_channel;
+ /* Alternate (enhanced) DESC mode*/
+ unsigned int enh_desc;
+};
+
/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
#define BUF_SIZE_16KiB 16384
#define BUF_SIZE_8KiB 8192
@@ -130,17 +192,6 @@ enum tx_dma_irq_status {
#define MAC_ENABLE_TX 0x00000008 /* Transmitter Enable */
#define MAC_RNABLE_RX 0x00000004 /* Receiver Enable */
-/* MAC Management Counters register */
-#define MMC_CONTROL 0x00000100 /* MMC Control */
-#define MMC_HIGH_INTR 0x00000104 /* MMC High Interrupt */
-#define MMC_LOW_INTR 0x00000108 /* MMC Low Interrupt */
-#define MMC_HIGH_INTR_MASK 0x0000010c /* MMC High Interrupt Mask */
-#define MMC_LOW_INTR_MASK 0x00000110 /* MMC Low Interrupt Mask */
-
-#define MMC_CONTROL_MAX_FRM_MASK 0x0003ff8 /* Maximum Frame Size */
-#define MMC_CONTROL_MAX_FRM_SHIFT 3
-#define MMC_CONTROL_MAX_FRAME 0x7FF
-
struct stmmac_desc_ops {
/* DMA RX descriptor ring initialization */
void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size,
@@ -198,6 +249,8 @@ struct stmmac_dma_ops {
void (*stop_rx) (void __iomem *ioaddr);
int (*dma_interrupt) (void __iomem *ioaddr,
struct stmmac_extra_stats *x);
+ /* If supported then get the optional core features */
+ unsigned int (*get_hw_feature) (void __iomem *ioaddr);
};
struct stmmac_ops {
@@ -234,12 +287,25 @@ struct mii_regs {
unsigned int data; /* MII Data */
};
+struct stmmac_ring_mode_ops {
+ unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
+ unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
+ void (*refill_desc3) (int bfsize, struct dma_desc *p);
+ void (*init_desc3) (int des3_as_data_buf, struct dma_desc *p);
+ void (*init_dma_chain) (struct dma_desc *des, dma_addr_t phy_addr,
+ unsigned int size);
+ void (*clean_desc3) (struct dma_desc *p);
+ int (*set_16kib_bfsize) (int mtu);
+};
+
struct mac_device_info {
const struct stmmac_ops *mac;
const struct stmmac_desc_ops *desc;
const struct stmmac_dma_ops *dma;
+ const struct stmmac_ring_mode_ops *ring;
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
+ unsigned int synopsys_uid;
};
struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr);
@@ -250,3 +316,4 @@ extern void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
extern void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int high, unsigned int low);
extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
+extern const struct stmmac_ring_mode_ops ring_mode_ops;
diff --git a/drivers/net/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h
index 63a03e264694..9820ec842cc0 100644
--- a/drivers/net/stmmac/descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h
@@ -25,33 +25,34 @@ struct dma_desc {
union {
struct {
/* RDES0 */
- u32 reserved1:1;
+ u32 payload_csum_error:1;
u32 crc_error:1;
u32 dribbling:1;
u32 mii_error:1;
u32 receive_watchdog:1;
u32 frame_type:1;
u32 collision:1;
- u32 frame_too_long:1;
+ u32 ipc_csum_error:1;
u32 last_descriptor:1;
u32 first_descriptor:1;
- u32 multicast_frame:1;
- u32 run_frame:1;
+ u32 vlan_tag:1;
+ u32 overflow_error:1;
u32 length_error:1;
- u32 partial_frame_error:1;
+ u32 sa_filter_fail:1;
u32 descriptor_error:1;
u32 error_summary:1;
u32 frame_length:14;
- u32 filtering_fail:1;
+ u32 da_filter_fail:1;
u32 own:1;
/* RDES1 */
u32 buffer1_size:11;
u32 buffer2_size:11;
- u32 reserved2:2;
+ u32 reserved1:2;
u32 second_address_chained:1;
u32 end_ring:1;
- u32 reserved3:5;
+ u32 reserved2:5;
u32 disable_ic:1;
+
} rx;
struct {
/* RDES0 */
@@ -91,24 +92,28 @@ struct dma_desc {
u32 underflow_error:1;
u32 excessive_deferral:1;
u32 collision_count:4;
- u32 heartbeat_fail:1;
+ u32 vlan_frame:1;
u32 excessive_collisions:1;
u32 late_collision:1;
u32 no_carrier:1;
u32 loss_carrier:1;
- u32 reserved1:3;
+ u32 payload_error:1;
+ u32 frame_flushed:1;
+ u32 jabber_timeout:1;
u32 error_summary:1;
- u32 reserved2:15;
+ u32 ip_header_error:1;
+ u32 time_stamp_status:1;
+ u32 reserved1:13;
u32 own:1;
/* TDES1 */
u32 buffer1_size:11;
u32 buffer2_size:11;
- u32 reserved3:1;
+ u32 time_stamp_enable:1;
u32 disable_padding:1;
u32 second_address_chained:1;
u32 end_ring:1;
u32 crc_disable:1;
- u32 reserved4:2;
+ u32 checksum_insertion:2;
u32 first_segment:1;
u32 last_segment:1;
u32 interrupt:1;
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
new file mode 100644
index 000000000000..dd8d6e19dff6
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ Header File to describe Normal/enhanced descriptor functions used for RING
+ and CHAINED modes.
+
+ Copyright(C) 2011 STMicroelectronics Ltd
+
+ It defines all the functions used to handle the normal/enhanced
+ descriptors in case of the DMA is configured to work in chained or
+ in ring mode.
+
+ 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>
+*******************************************************************************/
+
+#if defined(CONFIG_STMMAC_RING)
+static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1;
+ if (end)
+ p->des01.erx.end_ring = 1;
+}
+
+static inline void ehn_desc_tx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ if (end)
+ p->des01.etx.end_ring = 1;
+}
+
+static inline void enh_desc_end_tx_desc(struct dma_desc *p, int ter)
+{
+ p->des01.etx.end_ring = ter;
+}
+
+static inline void enh_set_tx_desc_len(struct dma_desc *p, int len)
+{
+ if (unlikely(len > BUF_SIZE_4KiB)) {
+ p->des01.etx.buffer1_size = BUF_SIZE_4KiB;
+ p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB;
+ } else
+ p->des01.etx.buffer1_size = len;
+}
+
+static inline void ndesc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ p->des01.rx.buffer2_size = BUF_SIZE_2KiB - 1;
+ if (end)
+ p->des01.rx.end_ring = 1;
+}
+
+static inline void ndesc_tx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ if (end)
+ p->des01.tx.end_ring = 1;
+}
+
+static inline void ndesc_end_tx_desc(struct dma_desc *p, int ter)
+{
+ p->des01.tx.end_ring = ter;
+}
+
+static inline void norm_set_tx_desc_len(struct dma_desc *p, int len)
+{
+ if (unlikely(len > BUF_SIZE_2KiB)) {
+ p->des01.etx.buffer1_size = BUF_SIZE_2KiB - 1;
+ p->des01.etx.buffer2_size = len - p->des01.etx.buffer1_size;
+ } else
+ p->des01.tx.buffer1_size = len;
+}
+
+#else
+
+static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ p->des01.erx.second_address_chained = 1;
+}
+
+static inline void ehn_desc_tx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ p->des01.etx.second_address_chained = 1;
+}
+
+static inline void enh_desc_end_tx_desc(struct dma_desc *p, int ter)
+{
+ p->des01.etx.second_address_chained = 1;
+}
+
+static inline void enh_set_tx_desc_len(struct dma_desc *p, int len)
+{
+ p->des01.etx.buffer1_size = len;
+}
+
+static inline void ndesc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ p->des01.rx.second_address_chained = 1;
+}
+
+static inline void ndesc_tx_set_on_ring_chain(struct dma_desc *p, int ring_size)
+{
+ p->des01.tx.second_address_chained = 1;
+}
+
+static inline void ndesc_end_tx_desc(struct dma_desc *p, int ter)
+{
+ p->des01.tx.second_address_chained = 1;
+}
+
+static inline void norm_set_tx_desc_len(struct dma_desc *p, int len)
+{
+ p->des01.tx.buffer1_size = len;
+}
+#endif
diff --git a/drivers/net/stmmac/dwmac100.h b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h
index 7c6d857a9cc7..7c6d857a9cc7 100644
--- a/drivers/net/stmmac/dwmac100.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h
diff --git a/drivers/net/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index cfcef0ea0fa5..cfcef0ea0fa5 100644
--- a/drivers/net/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 0f63b3c83c19..b1c48b975945 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -37,11 +37,6 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
value |= GMAC_CORE_INIT;
writel(value, ioaddr + GMAC_CONTROL);
- /* STBus Bridge Configuration */
- /*writel(0xc5608, ioaddr + 0x00007000);*/
-
- /* Freeze MMC counters */
- writel(0x8, ioaddr + GMAC_MMC_CTRL);
/* Mask GMAC interrupts */
writel(0x207, ioaddr + GMAC_INT_MASK);
@@ -229,10 +224,7 @@ static const struct stmmac_ops dwmac1000_ops = {
struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
{
struct mac_device_info *mac;
- u32 uid = readl(ioaddr + GMAC_VERSION);
-
- pr_info("\tDWMAC1000 - user ID: 0x%x, Synopsys ID: 0x%x\n",
- ((uid & 0x0000ff00) >> 8), (uid & 0x000000ff));
+ u32 hwid = readl(ioaddr + GMAC_VERSION);
mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
if (!mac)
@@ -246,6 +238,7 @@ struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
mac->link.speed = GMAC_CONTROL_FES;
mac->mii.addr = GMAC_MII_ADDR;
mac->mii.data = GMAC_MII_DATA;
+ mac->synopsys_uid = hwid;
return mac;
}
diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 3dbeea619085..da66ac511c4c 100644
--- a/drivers/net/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -118,13 +118,6 @@ static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode,
writel(csr6, ioaddr + DMA_CONTROL);
}
-/* Not yet implemented --- no RMON module */
-static void dwmac1000_dma_diagnostic_fr(void *data,
- struct stmmac_extra_stats *x, void __iomem *ioaddr)
-{
- return;
-}
-
static void dwmac1000_dump_dma_regs(void __iomem *ioaddr)
{
int i;
@@ -139,11 +132,15 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr)
}
}
+static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr)
+{
+ return readl(ioaddr + DMA_HW_FEATURE);
+}
+
const struct stmmac_dma_ops dwmac1000_dma_ops = {
.init = dwmac1000_dma_init,
.dump_regs = dwmac1000_dump_dma_regs,
.dma_mode = dwmac1000_dma_operation_mode,
- .dma_diagnostic_fr = dwmac1000_dma_diagnostic_fr,
.enable_dma_transmission = dwmac_enable_dma_transmission,
.enable_dma_irq = dwmac_enable_dma_irq,
.disable_dma_irq = dwmac_disable_dma_irq,
@@ -152,4 +149,5 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
.start_rx = dwmac_dma_start_rx,
.stop_rx = dwmac_dma_stop_rx,
.dma_interrupt = dwmac_dma_interrupt,
+ .get_hw_feature = dwmac1000_get_hw_feature,
};
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 743a58017637..138fb8dd1e87 100644
--- a/drivers/net/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -70,17 +70,6 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
readl(ioaddr + MAC_VLAN1));
pr_info("\tVLAN2 tag (offset 0x%x): 0x%08x\n", MAC_VLAN2,
readl(ioaddr + MAC_VLAN2));
- pr_info("\n\tMAC management counter registers\n");
- pr_info("\t MMC crtl (offset 0x%x): 0x%08x\n",
- MMC_CONTROL, readl(ioaddr + MMC_CONTROL));
- pr_info("\t MMC High Interrupt (offset 0x%x): 0x%08x\n",
- MMC_HIGH_INTR, readl(ioaddr + MMC_HIGH_INTR));
- pr_info("\t MMC Low Interrupt (offset 0x%x): 0x%08x\n",
- MMC_LOW_INTR, readl(ioaddr + MMC_LOW_INTR));
- pr_info("\t MMC High Interrupt Mask (offset 0x%x): 0x%08x\n",
- MMC_HIGH_INTR_MASK, readl(ioaddr + MMC_HIGH_INTR_MASK));
- pr_info("\t MMC Low Interrupt Mask (offset 0x%x): 0x%08x\n",
- MMC_LOW_INTR_MASK, readl(ioaddr + MMC_LOW_INTR_MASK));
}
static void dwmac100_irq_status(void __iomem *ioaddr)
@@ -199,6 +188,7 @@ struct mac_device_info *dwmac100_setup(void __iomem *ioaddr)
mac->link.speed = 0;
mac->mii.addr = MAC_MII_ADDR;
mac->mii.data = MAC_MII_DATA;
+ mac->synopsys_uid = 0;
return mac;
}
diff --git a/drivers/net/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
index 627f656b0f3c..627f656b0f3c 100644
--- a/drivers/net/stmmac/dwmac100_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
diff --git a/drivers/net/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index da3f5ccf83d3..437edacd602e 100644
--- a/drivers/net/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -34,6 +34,7 @@
#define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */
#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 */
/* DMA Control register defines */
#define DMA_CONTROL_ST 0x00002000 /* Start/Stop Transmission */
diff --git a/drivers/net/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index e25093510b0c..e25093510b0c 100644
--- a/drivers/net/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
diff --git a/drivers/net/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index e5dfb6a30182..d87976364ec5 100644
--- a/drivers/net/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -23,6 +23,7 @@
*******************************************************************************/
#include "common.h"
+#include "descs_com.h"
static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
struct dma_desc *p, void __iomem *ioaddr)
@@ -233,10 +234,9 @@ static void enh_desc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
for (i = 0; i < ring_size; i++) {
p->des01.erx.own = 1;
p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
- /* To support jumbo frames */
- p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1;
- if (i == ring_size - 1)
- p->des01.erx.end_ring = 1;
+
+ ehn_desc_rx_set_on_ring_chain(p, (i == ring_size - 1));
+
if (disable_rx_ic)
p->des01.erx.disable_ic = 1;
p++;
@@ -249,8 +249,7 @@ static void enh_desc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
for (i = 0; i < ring_size; i++) {
p->des01.etx.own = 0;
- if (i == ring_size - 1)
- p->des01.etx.end_ring = 1;
+ ehn_desc_tx_set_on_ring_chain(p, (i == ring_size - 1));
p++;
}
}
@@ -285,19 +284,16 @@ static void enh_desc_release_tx_desc(struct dma_desc *p)
int ter = p->des01.etx.end_ring;
memset(p, 0, offsetof(struct dma_desc, des2));
- p->des01.etx.end_ring = ter;
+ enh_desc_end_tx_desc(p, ter);
}
static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
int csum_flag)
{
p->des01.etx.first_segment = is_fs;
- if (unlikely(len > BUF_SIZE_4KiB)) {
- p->des01.etx.buffer1_size = BUF_SIZE_4KiB;
- p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB;
- } else {
- p->des01.etx.buffer1_size = len;
- }
+
+ enh_set_tx_desc_len(p, len);
+
if (likely(csum_flag))
p->des01.etx.checksum_insertion = cic_full;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc.h b/drivers/net/ethernet/stmicro/stmmac/mmc.h
new file mode 100644
index 000000000000..a38352024cb8
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ MMC Header file
+
+ Copyright (C) 2011 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>
+*******************************************************************************/
+
+/* MMC control register */
+/* When set, all counter are reset */
+#define MMC_CNTRL_COUNTER_RESET 0x1
+/* When set, do not roll over zero
+ * after reaching the max value*/
+#define MMC_CNTRL_COUNTER_STOP_ROLLOVER 0x2
+#define MMC_CNTRL_RESET_ON_READ 0x4 /* Reset after reading */
+#define MMC_CNTRL_COUNTER_FREEZER 0x8 /* Freeze counter values to the
+ * current value.*/
+#define MMC_CNTRL_PRESET 0x10
+#define MMC_CNTRL_FULL_HALF_PRESET 0x20
+struct stmmac_counters {
+ unsigned int mmc_tx_octetcount_gb;
+ unsigned int mmc_tx_framecount_gb;
+ unsigned int mmc_tx_broadcastframe_g;
+ unsigned int mmc_tx_multicastframe_g;
+ unsigned int mmc_tx_64_octets_gb;
+ unsigned int mmc_tx_65_to_127_octets_gb;
+ unsigned int mmc_tx_128_to_255_octets_gb;
+ unsigned int mmc_tx_256_to_511_octets_gb;
+ unsigned int mmc_tx_512_to_1023_octets_gb;
+ unsigned int mmc_tx_1024_to_max_octets_gb;
+ unsigned int mmc_tx_unicast_gb;
+ unsigned int mmc_tx_multicast_gb;
+ unsigned int mmc_tx_broadcast_gb;
+ unsigned int mmc_tx_underflow_error;
+ unsigned int mmc_tx_singlecol_g;
+ unsigned int mmc_tx_multicol_g;
+ unsigned int mmc_tx_deferred;
+ unsigned int mmc_tx_latecol;
+ unsigned int mmc_tx_exesscol;
+ unsigned int mmc_tx_carrier_error;
+ unsigned int mmc_tx_octetcount_g;
+ unsigned int mmc_tx_framecount_g;
+ unsigned int mmc_tx_excessdef;
+ unsigned int mmc_tx_pause_frame;
+ unsigned int mmc_tx_vlan_frame_g;
+
+ /* MMC RX counter registers */
+ unsigned int mmc_rx_framecount_gb;
+ unsigned int mmc_rx_octetcount_gb;
+ unsigned int mmc_rx_octetcount_g;
+ unsigned int mmc_rx_broadcastframe_g;
+ unsigned int mmc_rx_multicastframe_g;
+ unsigned int mmc_rx_crc_errror;
+ unsigned int mmc_rx_align_error;
+ unsigned int mmc_rx_run_error;
+ unsigned int mmc_rx_jabber_error;
+ unsigned int mmc_rx_undersize_g;
+ unsigned int mmc_rx_oversize_g;
+ unsigned int mmc_rx_64_octets_gb;
+ unsigned int mmc_rx_65_to_127_octets_gb;
+ unsigned int mmc_rx_128_to_255_octets_gb;
+ unsigned int mmc_rx_256_to_511_octets_gb;
+ unsigned int mmc_rx_512_to_1023_octets_gb;
+ unsigned int mmc_rx_1024_to_max_octets_gb;
+ unsigned int mmc_rx_unicast_g;
+ unsigned int mmc_rx_length_error;
+ unsigned int mmc_rx_autofrangetype;
+ unsigned int mmc_rx_pause_frames;
+ unsigned int mmc_rx_fifo_overflow;
+ unsigned int mmc_rx_vlan_frames_gb;
+ unsigned int mmc_rx_watchdog_error;
+ /* IPC */
+ unsigned int mmc_rx_ipc_intr_mask;
+ unsigned int mmc_rx_ipc_intr;
+ /* IPv4 */
+ unsigned int mmc_rx_ipv4_gd;
+ unsigned int mmc_rx_ipv4_hderr;
+ unsigned int mmc_rx_ipv4_nopay;
+ unsigned int mmc_rx_ipv4_frag;
+ unsigned int mmc_rx_ipv4_udsbl;
+
+ unsigned int mmc_rx_ipv4_gd_octets;
+ unsigned int mmc_rx_ipv4_hderr_octets;
+ unsigned int mmc_rx_ipv4_nopay_octets;
+ unsigned int mmc_rx_ipv4_frag_octets;
+ unsigned int mmc_rx_ipv4_udsbl_octets;
+
+ /* IPV6 */
+ unsigned int mmc_rx_ipv6_gd_octets;
+ unsigned int mmc_rx_ipv6_hderr_octets;
+ unsigned int mmc_rx_ipv6_nopay_octets;
+
+ unsigned int mmc_rx_ipv6_gd;
+ unsigned int mmc_rx_ipv6_hderr;
+ unsigned int mmc_rx_ipv6_nopay;
+
+ /* Protocols */
+ unsigned int mmc_rx_udp_gd;
+ unsigned int mmc_rx_udp_err;
+ unsigned int mmc_rx_tcp_gd;
+ unsigned int mmc_rx_tcp_err;
+ unsigned int mmc_rx_icmp_gd;
+ unsigned int mmc_rx_icmp_err;
+
+ unsigned int mmc_rx_udp_gd_octets;
+ unsigned int mmc_rx_udp_err_octets;
+ unsigned int mmc_rx_tcp_gd_octets;
+ unsigned int mmc_rx_tcp_err_octets;
+ unsigned int mmc_rx_icmp_gd_octets;
+ unsigned int mmc_rx_icmp_err_octets;
+};
+
+extern void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode);
+extern void dwmac_mmc_intr_all_mask(void __iomem *ioaddr);
+extern void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc);
diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
new file mode 100644
index 000000000000..41e6b33e1b08
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
@@ -0,0 +1,265 @@
+/*******************************************************************************
+ DWMAC Management Counters
+
+ Copyright (C) 2011 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/io.h>
+#include "mmc.h"
+
+/* MAC Management Counters register offset */
+
+#define MMC_CNTRL 0x00000100 /* MMC Control */
+#define MMC_RX_INTR 0x00000104 /* MMC RX Interrupt */
+#define MMC_TX_INTR 0x00000108 /* MMC TX Interrupt */
+#define MMC_RX_INTR_MASK 0x0000010c /* MMC Interrupt Mask */
+#define MMC_TX_INTR_MASK 0x00000110 /* MMC Interrupt Mask */
+#define MMC_DEFAUL_MASK 0xffffffff
+
+/* MMC TX counter registers */
+
+/* Note:
+ * _GB register stands for good and bad frames
+ * _G is for good only.
+ */
+#define MMC_TX_OCTETCOUNT_GB 0x00000114
+#define MMC_TX_FRAMECOUNT_GB 0x00000118
+#define MMC_TX_BROADCASTFRAME_G 0x0000011c
+#define MMC_TX_MULTICASTFRAME_G 0x00000120
+#define MMC_TX_64_OCTETS_GB 0x00000124
+#define MMC_TX_65_TO_127_OCTETS_GB 0x00000128
+#define MMC_TX_128_TO_255_OCTETS_GB 0x0000012c
+#define MMC_TX_256_TO_511_OCTETS_GB 0x00000130
+#define MMC_TX_512_TO_1023_OCTETS_GB 0x00000134
+#define MMC_TX_1024_TO_MAX_OCTETS_GB 0x00000138
+#define MMC_TX_UNICAST_GB 0x0000013c
+#define MMC_TX_MULTICAST_GB 0x00000140
+#define MMC_TX_BROADCAST_GB 0x00000144
+#define MMC_TX_UNDERFLOW_ERROR 0x00000148
+#define MMC_TX_SINGLECOL_G 0x0000014c
+#define MMC_TX_MULTICOL_G 0x00000150
+#define MMC_TX_DEFERRED 0x00000154
+#define MMC_TX_LATECOL 0x00000158
+#define MMC_TX_EXESSCOL 0x0000015c
+#define MMC_TX_CARRIER_ERROR 0x00000160
+#define MMC_TX_OCTETCOUNT_G 0x00000164
+#define MMC_TX_FRAMECOUNT_G 0x00000168
+#define MMC_TX_EXCESSDEF 0x0000016c
+#define MMC_TX_PAUSE_FRAME 0x00000170
+#define MMC_TX_VLAN_FRAME_G 0x00000174
+
+/* MMC RX counter registers */
+#define MMC_RX_FRAMECOUNT_GB 0x00000180
+#define MMC_RX_OCTETCOUNT_GB 0x00000184
+#define MMC_RX_OCTETCOUNT_G 0x00000188
+#define MMC_RX_BROADCASTFRAME_G 0x0000018c
+#define MMC_RX_MULTICASTFRAME_G 0x00000190
+#define MMC_RX_CRC_ERRROR 0x00000194
+#define MMC_RX_ALIGN_ERROR 0x00000198
+#define MMC_RX_RUN_ERROR 0x0000019C
+#define MMC_RX_JABBER_ERROR 0x000001A0
+#define MMC_RX_UNDERSIZE_G 0x000001A4
+#define MMC_RX_OVERSIZE_G 0x000001A8
+#define MMC_RX_64_OCTETS_GB 0x000001AC
+#define MMC_RX_65_TO_127_OCTETS_GB 0x000001b0
+#define MMC_RX_128_TO_255_OCTETS_GB 0x000001b4
+#define MMC_RX_256_TO_511_OCTETS_GB 0x000001b8
+#define MMC_RX_512_TO_1023_OCTETS_GB 0x000001bc
+#define MMC_RX_1024_TO_MAX_OCTETS_GB 0x000001c0
+#define MMC_RX_UNICAST_G 0x000001c4
+#define MMC_RX_LENGTH_ERROR 0x000001c8
+#define MMC_RX_AUTOFRANGETYPE 0x000001cc
+#define MMC_RX_PAUSE_FRAMES 0x000001d0
+#define MMC_RX_FIFO_OVERFLOW 0x000001d4
+#define MMC_RX_VLAN_FRAMES_GB 0x000001d8
+#define MMC_RX_WATCHDOG_ERROR 0x000001dc
+/* IPC*/
+#define MMC_RX_IPC_INTR_MASK 0x00000200
+#define MMC_RX_IPC_INTR 0x00000208
+/* IPv4*/
+#define MMC_RX_IPV4_GD 0x00000210
+#define MMC_RX_IPV4_HDERR 0x00000214
+#define MMC_RX_IPV4_NOPAY 0x00000218
+#define MMC_RX_IPV4_FRAG 0x0000021C
+#define MMC_RX_IPV4_UDSBL 0x00000220
+
+#define MMC_RX_IPV4_GD_OCTETS 0x00000250
+#define MMC_RX_IPV4_HDERR_OCTETS 0x00000254
+#define MMC_RX_IPV4_NOPAY_OCTETS 0x00000258
+#define MMC_RX_IPV4_FRAG_OCTETS 0x0000025c
+#define MMC_RX_IPV4_UDSBL_OCTETS 0x00000260
+
+/* IPV6*/
+#define MMC_RX_IPV6_GD_OCTETS 0x00000264
+#define MMC_RX_IPV6_HDERR_OCTETS 0x00000268
+#define MMC_RX_IPV6_NOPAY_OCTETS 0x0000026c
+
+#define MMC_RX_IPV6_GD 0x00000224
+#define MMC_RX_IPV6_HDERR 0x00000228
+#define MMC_RX_IPV6_NOPAY 0x0000022c
+
+/* Protocols*/
+#define MMC_RX_UDP_GD 0x00000230
+#define MMC_RX_UDP_ERR 0x00000234
+#define MMC_RX_TCP_GD 0x00000238
+#define MMC_RX_TCP_ERR 0x0000023c
+#define MMC_RX_ICMP_GD 0x00000240
+#define MMC_RX_ICMP_ERR 0x00000244
+
+#define MMC_RX_UDP_GD_OCTETS 0x00000270
+#define MMC_RX_UDP_ERR_OCTETS 0x00000274
+#define MMC_RX_TCP_GD_OCTETS 0x00000278
+#define MMC_RX_TCP_ERR_OCTETS 0x0000027c
+#define MMC_RX_ICMP_GD_OCTETS 0x00000280
+#define MMC_RX_ICMP_ERR_OCTETS 0x00000284
+
+void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode)
+{
+ u32 value = readl(ioaddr + MMC_CNTRL);
+
+ value |= (mode & 0x3F);
+
+ writel(value, ioaddr + MMC_CNTRL);
+
+ pr_debug("stmmac: MMC ctrl register (offset 0x%x): 0x%08x\n",
+ MMC_CNTRL, value);
+}
+
+/* To mask all all interrupts.*/
+void dwmac_mmc_intr_all_mask(void __iomem *ioaddr)
+{
+ writel(MMC_DEFAUL_MASK, ioaddr + MMC_RX_INTR_MASK);
+ writel(MMC_DEFAUL_MASK, ioaddr + MMC_TX_INTR_MASK);
+}
+
+/* This reads the MAC core counters (if actaully supported).
+ * by default the MMC core is programmed to reset each
+ * counter after a read. So all the field of the mmc struct
+ * have to be incremented.
+ */
+void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc)
+{
+ mmc->mmc_tx_octetcount_gb += readl(ioaddr + MMC_TX_OCTETCOUNT_GB);
+ mmc->mmc_tx_framecount_gb += readl(ioaddr + MMC_TX_FRAMECOUNT_GB);
+ mmc->mmc_tx_broadcastframe_g += readl(ioaddr + MMC_TX_BROADCASTFRAME_G);
+ mmc->mmc_tx_multicastframe_g += readl(ioaddr + MMC_TX_MULTICASTFRAME_G);
+ mmc->mmc_tx_64_octets_gb += readl(ioaddr + MMC_TX_64_OCTETS_GB);
+ mmc->mmc_tx_65_to_127_octets_gb +=
+ readl(ioaddr + MMC_TX_65_TO_127_OCTETS_GB);
+ mmc->mmc_tx_128_to_255_octets_gb +=
+ readl(ioaddr + MMC_TX_128_TO_255_OCTETS_GB);
+ mmc->mmc_tx_256_to_511_octets_gb +=
+ readl(ioaddr + MMC_TX_256_TO_511_OCTETS_GB);
+ mmc->mmc_tx_512_to_1023_octets_gb +=
+ readl(ioaddr + MMC_TX_512_TO_1023_OCTETS_GB);
+ mmc->mmc_tx_1024_to_max_octets_gb +=
+ readl(ioaddr + MMC_TX_1024_TO_MAX_OCTETS_GB);
+ mmc->mmc_tx_unicast_gb += readl(ioaddr + MMC_TX_UNICAST_GB);
+ mmc->mmc_tx_multicast_gb += readl(ioaddr + MMC_TX_MULTICAST_GB);
+ mmc->mmc_tx_broadcast_gb += readl(ioaddr + MMC_TX_BROADCAST_GB);
+ mmc->mmc_tx_underflow_error += readl(ioaddr + MMC_TX_UNDERFLOW_ERROR);
+ mmc->mmc_tx_singlecol_g += readl(ioaddr + MMC_TX_SINGLECOL_G);
+ mmc->mmc_tx_multicol_g += readl(ioaddr + MMC_TX_MULTICOL_G);
+ mmc->mmc_tx_deferred += readl(ioaddr + MMC_TX_DEFERRED);
+ mmc->mmc_tx_latecol += readl(ioaddr + MMC_TX_LATECOL);
+ mmc->mmc_tx_exesscol += readl(ioaddr + MMC_TX_EXESSCOL);
+ mmc->mmc_tx_carrier_error += readl(ioaddr + MMC_TX_CARRIER_ERROR);
+ mmc->mmc_tx_octetcount_g += readl(ioaddr + MMC_TX_OCTETCOUNT_G);
+ mmc->mmc_tx_framecount_g += readl(ioaddr + MMC_TX_FRAMECOUNT_G);
+ mmc->mmc_tx_excessdef += readl(ioaddr + MMC_TX_EXCESSDEF);
+ mmc->mmc_tx_pause_frame += readl(ioaddr + MMC_TX_PAUSE_FRAME);
+ mmc->mmc_tx_vlan_frame_g += readl(ioaddr + MMC_TX_VLAN_FRAME_G);
+
+ /* MMC RX counter registers */
+ mmc->mmc_rx_framecount_gb += readl(ioaddr + MMC_RX_FRAMECOUNT_GB);
+ mmc->mmc_rx_octetcount_gb += readl(ioaddr + MMC_RX_OCTETCOUNT_GB);
+ mmc->mmc_rx_octetcount_g += readl(ioaddr + MMC_RX_OCTETCOUNT_G);
+ mmc->mmc_rx_broadcastframe_g += readl(ioaddr + MMC_RX_BROADCASTFRAME_G);
+ mmc->mmc_rx_multicastframe_g += readl(ioaddr + MMC_RX_MULTICASTFRAME_G);
+ mmc->mmc_rx_crc_errror += readl(ioaddr + MMC_RX_CRC_ERRROR);
+ mmc->mmc_rx_align_error += readl(ioaddr + MMC_RX_ALIGN_ERROR);
+ mmc->mmc_rx_run_error += readl(ioaddr + MMC_RX_RUN_ERROR);
+ mmc->mmc_rx_jabber_error += readl(ioaddr + MMC_RX_JABBER_ERROR);
+ mmc->mmc_rx_undersize_g += readl(ioaddr + MMC_RX_UNDERSIZE_G);
+ mmc->mmc_rx_oversize_g += readl(ioaddr + MMC_RX_OVERSIZE_G);
+ mmc->mmc_rx_64_octets_gb += readl(ioaddr + MMC_RX_64_OCTETS_GB);
+ mmc->mmc_rx_65_to_127_octets_gb +=
+ readl(ioaddr + MMC_RX_65_TO_127_OCTETS_GB);
+ mmc->mmc_rx_128_to_255_octets_gb +=
+ readl(ioaddr + MMC_RX_128_TO_255_OCTETS_GB);
+ mmc->mmc_rx_256_to_511_octets_gb +=
+ readl(ioaddr + MMC_RX_256_TO_511_OCTETS_GB);
+ mmc->mmc_rx_512_to_1023_octets_gb +=
+ readl(ioaddr + MMC_RX_512_TO_1023_OCTETS_GB);
+ mmc->mmc_rx_1024_to_max_octets_gb +=
+ readl(ioaddr + MMC_RX_1024_TO_MAX_OCTETS_GB);
+ mmc->mmc_rx_unicast_g += readl(ioaddr + MMC_RX_UNICAST_G);
+ mmc->mmc_rx_length_error += readl(ioaddr + MMC_RX_LENGTH_ERROR);
+ mmc->mmc_rx_autofrangetype += readl(ioaddr + MMC_RX_AUTOFRANGETYPE);
+ mmc->mmc_rx_pause_frames += readl(ioaddr + MMC_RX_PAUSE_FRAMES);
+ mmc->mmc_rx_fifo_overflow += readl(ioaddr + MMC_RX_FIFO_OVERFLOW);
+ mmc->mmc_rx_vlan_frames_gb += readl(ioaddr + MMC_RX_VLAN_FRAMES_GB);
+ mmc->mmc_rx_watchdog_error += readl(ioaddr + MMC_RX_WATCHDOG_ERROR);
+ /* IPC */
+ mmc->mmc_rx_ipc_intr_mask += readl(ioaddr + MMC_RX_IPC_INTR_MASK);
+ mmc->mmc_rx_ipc_intr += readl(ioaddr + MMC_RX_IPC_INTR);
+ /* IPv4 */
+ mmc->mmc_rx_ipv4_gd += readl(ioaddr + MMC_RX_IPV4_GD);
+ mmc->mmc_rx_ipv4_hderr += readl(ioaddr + MMC_RX_IPV4_HDERR);
+ mmc->mmc_rx_ipv4_nopay += readl(ioaddr + MMC_RX_IPV4_NOPAY);
+ mmc->mmc_rx_ipv4_frag += readl(ioaddr + MMC_RX_IPV4_FRAG);
+ mmc->mmc_rx_ipv4_udsbl += readl(ioaddr + MMC_RX_IPV4_UDSBL);
+
+ mmc->mmc_rx_ipv4_gd_octets += readl(ioaddr + MMC_RX_IPV4_GD_OCTETS);
+ mmc->mmc_rx_ipv4_hderr_octets +=
+ readl(ioaddr + MMC_RX_IPV4_HDERR_OCTETS);
+ mmc->mmc_rx_ipv4_nopay_octets +=
+ readl(ioaddr + MMC_RX_IPV4_NOPAY_OCTETS);
+ mmc->mmc_rx_ipv4_frag_octets += readl(ioaddr + MMC_RX_IPV4_FRAG_OCTETS);
+ mmc->mmc_rx_ipv4_udsbl_octets +=
+ readl(ioaddr + MMC_RX_IPV4_UDSBL_OCTETS);
+
+ /* IPV6 */
+ mmc->mmc_rx_ipv6_gd_octets += readl(ioaddr + MMC_RX_IPV6_GD_OCTETS);
+ mmc->mmc_rx_ipv6_hderr_octets +=
+ readl(ioaddr + MMC_RX_IPV6_HDERR_OCTETS);
+ mmc->mmc_rx_ipv6_nopay_octets +=
+ readl(ioaddr + MMC_RX_IPV6_NOPAY_OCTETS);
+
+ mmc->mmc_rx_ipv6_gd += readl(ioaddr + MMC_RX_IPV6_GD);
+ mmc->mmc_rx_ipv6_hderr += readl(ioaddr + MMC_RX_IPV6_HDERR);
+ mmc->mmc_rx_ipv6_nopay += readl(ioaddr + MMC_RX_IPV6_NOPAY);
+
+ /* Protocols */
+ mmc->mmc_rx_udp_gd += readl(ioaddr + MMC_RX_UDP_GD);
+ mmc->mmc_rx_udp_err += readl(ioaddr + MMC_RX_UDP_ERR);
+ mmc->mmc_rx_tcp_gd += readl(ioaddr + MMC_RX_TCP_GD);
+ mmc->mmc_rx_tcp_err += readl(ioaddr + MMC_RX_TCP_ERR);
+ mmc->mmc_rx_icmp_gd += readl(ioaddr + MMC_RX_ICMP_GD);
+ mmc->mmc_rx_icmp_err += readl(ioaddr + MMC_RX_ICMP_ERR);
+
+ mmc->mmc_rx_udp_gd_octets += readl(ioaddr + MMC_RX_UDP_GD_OCTETS);
+ mmc->mmc_rx_udp_err_octets += readl(ioaddr + MMC_RX_UDP_ERR_OCTETS);
+ mmc->mmc_rx_tcp_gd_octets += readl(ioaddr + MMC_RX_TCP_GD_OCTETS);
+ mmc->mmc_rx_tcp_err_octets += readl(ioaddr + MMC_RX_TCP_ERR_OCTETS);
+ mmc->mmc_rx_icmp_gd_octets += readl(ioaddr + MMC_RX_ICMP_GD_OCTETS);
+ mmc->mmc_rx_icmp_err_octets += readl(ioaddr + MMC_RX_ICMP_ERR_OCTETS);
+}
diff --git a/drivers/net/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 029c2a2cf524..fda5d2b31d3a 100644
--- a/drivers/net/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -23,6 +23,7 @@
*******************************************************************************/
#include "common.h"
+#include "descs_com.h"
static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
struct dma_desc *p, void __iomem *ioaddr)
@@ -49,11 +50,12 @@ static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
stats->collisions += p->des01.tx.collision_count;
ret = -1;
}
- if (unlikely(p->des01.tx.heartbeat_fail)) {
- x->tx_heartbeat++;
- stats->tx_heartbeat_errors++;
- ret = -1;
+
+ if (p->des01.etx.vlan_frame) {
+ CHIP_DBG(KERN_INFO "GMAC TX status: VLAN frame\n");
+ x->tx_vlan++;
}
+
if (unlikely(p->des01.tx.deferred))
x->tx_deferred++;
@@ -67,12 +69,12 @@ static int ndesc_get_tx_len(struct dma_desc *p)
/* This function verifies if each incoming frame has some errors
* and, if required, updates the multicast statistics.
- * In case of success, it returns csum_none because the device
- * is not able to compute the csum in HW. */
+ * In case of success, it returns good_frame because the GMAC device
+ * is supposed to be able to compute the csum in HW. */
static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
struct dma_desc *p)
{
- int ret = csum_none;
+ int ret = good_frame;
struct net_device_stats *stats = (struct net_device_stats *)data;
if (unlikely(p->des01.rx.last_descriptor == 0)) {
@@ -85,12 +87,12 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
if (unlikely(p->des01.rx.error_summary)) {
if (unlikely(p->des01.rx.descriptor_error))
x->rx_desc++;
- if (unlikely(p->des01.rx.partial_frame_error))
- x->rx_partial++;
- if (unlikely(p->des01.rx.run_frame))
- x->rx_runt++;
- if (unlikely(p->des01.rx.frame_too_long))
- x->rx_toolong++;
+ if (unlikely(p->des01.rx.sa_filter_fail))
+ x->sa_filter_fail++;
+ if (unlikely(p->des01.rx.overflow_error))
+ x->overflow_error++;
+ if (unlikely(p->des01.rx.ipc_csum_error))
+ x->ipc_csum_error++;
if (unlikely(p->des01.rx.collision)) {
x->rx_collision++;
stats->collisions++;
@@ -112,10 +114,10 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
x->rx_mii++;
ret = discard_frame;
}
- if (p->des01.rx.multicast_frame) {
- x->rx_multicast++;
- stats->multicast++;
- }
+#ifdef STMMAC_VLAN_TAG_USED
+ if (p->des01.rx.vlan_tag)
+ x->vlan_tag++;
+#endif
return ret;
}
@@ -126,8 +128,9 @@ static void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
for (i = 0; i < ring_size; i++) {
p->des01.rx.own = 1;
p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
- if (i == ring_size - 1)
- p->des01.rx.end_ring = 1;
+
+ ndesc_rx_set_on_ring_chain(p, (i == ring_size - 1));
+
if (disable_rx_ic)
p->des01.rx.disable_ic = 1;
p++;
@@ -139,8 +142,7 @@ static void ndesc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
int i;
for (i = 0; i < ring_size; i++) {
p->des01.tx.own = 0;
- if (i == ring_size - 1)
- p->des01.tx.end_ring = 1;
+ ndesc_tx_set_on_ring_chain(p, (i == (ring_size - 1)));
p++;
}
}
@@ -175,15 +177,17 @@ static void ndesc_release_tx_desc(struct dma_desc *p)
int ter = p->des01.tx.end_ring;
memset(p, 0, offsetof(struct dma_desc, des2));
- /* set termination field */
- p->des01.tx.end_ring = ter;
+ ndesc_end_tx_desc(p, ter);
}
static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
int csum_flag)
{
p->des01.tx.first_segment = is_fs;
- p->des01.tx.buffer1_size = len;
+ norm_set_tx_desc_len(p, len);
+
+ if (likely(csum_flag))
+ p->des01.tx.checksum_insertion = cic_full;
}
static void ndesc_clear_tx_ic(struct dma_desc *p)
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
new file mode 100644
index 000000000000..fb8377da1687
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ Specialised functions for managing Ring mode
+
+ Copyright(C) 2011 STMicroelectronics Ltd
+
+ It defines all the functions used to handle the normal/enhanced
+ descriptors in case of the DMA is configured to work in chained or
+ in ring mode.
+
+ 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 "stmmac.h"
+
+static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
+{
+ struct stmmac_priv *priv = (struct stmmac_priv *) p;
+ unsigned int txsize = priv->dma_tx_size;
+ unsigned int entry = priv->cur_tx % txsize;
+ struct dma_desc *desc = priv->dma_tx + entry;
+ unsigned int nopaged_len = skb_headlen(skb);
+ unsigned int bmax, len;
+
+ if (priv->plat->enh_desc)
+ bmax = BUF_SIZE_8KiB;
+ else
+ bmax = BUF_SIZE_2KiB;
+
+ len = nopaged_len - bmax;
+
+ if (nopaged_len > BUF_SIZE_8KiB) {
+
+ desc->des2 = dma_map_single(priv->device, skb->data,
+ bmax, DMA_TO_DEVICE);
+ desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ priv->hw->desc->prepare_tx_desc(desc, 1, bmax,
+ csum);
+
+ entry = (++priv->cur_tx) % txsize;
+ desc = priv->dma_tx + entry;
+
+ desc->des2 = dma_map_single(priv->device, skb->data + bmax,
+ len, DMA_TO_DEVICE);
+ desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ priv->hw->desc->prepare_tx_desc(desc, 0, len, csum);
+ priv->hw->desc->set_tx_owner(desc);
+ priv->tx_skbuff[entry] = NULL;
+ } else {
+ desc->des2 = dma_map_single(priv->device, skb->data,
+ nopaged_len, DMA_TO_DEVICE);
+ desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum);
+ }
+
+ return entry;
+}
+
+static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
+{
+ unsigned int ret = 0;
+
+ if (len >= BUF_SIZE_4KiB)
+ ret = 1;
+
+ return ret;
+}
+
+static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
+{
+ /* Fill DES3 in case of RING mode */
+ if (bfsize >= BUF_SIZE_8KiB)
+ p->des3 = p->des2 + BUF_SIZE_8KiB;
+}
+
+/* In ring mode we need to fill the desc3 because it is used
+ * as buffer */
+static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
+{
+ if (unlikely(des3_as_data_buf))
+ p->des3 = p->des2 + BUF_SIZE_8KiB;
+}
+
+static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
+ unsigned int size)
+{
+}
+
+static void stmmac_clean_desc3(struct dma_desc *p)
+{
+ if (unlikely(p->des3))
+ p->des3 = 0;
+}
+
+static int stmmac_set_16kib_bfsize(int mtu)
+{
+ int ret = 0;
+ if (unlikely(mtu >= BUF_SIZE_8KiB))
+ ret = BUF_SIZE_16KiB;
+ return ret;
+}
+
+const struct stmmac_ring_mode_ops ring_mode_ops = {
+ .is_jumbo_frm = stmmac_is_jumbo_frm,
+ .jumbo_frm = stmmac_jumbo_frm,
+ .refill_desc3 = stmmac_refill_desc3,
+ .init_desc3 = stmmac_init_desc3,
+ .init_dma_chain = stmmac_init_dma_chain,
+ .clean_desc3 = stmmac_clean_desc3,
+ .set_16kib_bfsize = stmmac_set_16kib_bfsize,
+};
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index de1929b2641b..9bafa6cf9e8b 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -20,9 +20,9 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
-#define DRV_MODULE_VERSION "July_2011"
+#define DRV_MODULE_VERSION "Oct_2011"
#include <linux/stmmac.h>
-
+#include <linux/phy.h>
#include "common.h"
#ifdef CONFIG_STMMAC_TIMER
#include "stmmac_timer.h"
@@ -70,12 +70,16 @@ struct stmmac_priv {
u32 msg_enable;
spinlock_t lock;
+ spinlock_t tx_lock;
int wolopts;
int wolenabled;
+ 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;
};
extern int stmmac_mdio_unregister(struct net_device *ndev);
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 7ed8fb6c2117..e8eff09bbbd7 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -46,11 +46,11 @@ struct stmmac_stats {
{ #m, FIELD_SIZEOF(struct stmmac_extra_stats, m), \
offsetof(struct stmmac_priv, xstats.m)}
-static const struct stmmac_stats stmmac_gstrings_stats[] = {
+static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(tx_underflow),
STMMAC_STAT(tx_carrier),
STMMAC_STAT(tx_losscarrier),
- STMMAC_STAT(tx_heartbeat),
+ STMMAC_STAT(vlan_tag),
STMMAC_STAT(tx_deferred),
STMMAC_STAT(tx_vlan),
STMMAC_STAT(rx_vlan),
@@ -59,9 +59,9 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(tx_payload_error),
STMMAC_STAT(tx_ip_header_error),
STMMAC_STAT(rx_desc),
- STMMAC_STAT(rx_partial),
- STMMAC_STAT(rx_runt),
- STMMAC_STAT(rx_toolong),
+ STMMAC_STAT(sa_filter_fail),
+ STMMAC_STAT(overflow_error),
+ STMMAC_STAT(ipc_csum_error),
STMMAC_STAT(rx_collision),
STMMAC_STAT(rx_crc),
STMMAC_STAT(rx_length),
@@ -91,19 +91,106 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
};
#define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
+/* HW MAC Management counters (if supported) */
+#define STMMAC_MMC_STAT(m) \
+ { #m, FIELD_SIZEOF(struct stmmac_counters, m), \
+ offsetof(struct stmmac_priv, mmc.m)}
+
+static const struct stmmac_stats stmmac_mmc[] = {
+ STMMAC_MMC_STAT(mmc_tx_octetcount_gb),
+ STMMAC_MMC_STAT(mmc_tx_framecount_gb),
+ STMMAC_MMC_STAT(mmc_tx_broadcastframe_g),
+ STMMAC_MMC_STAT(mmc_tx_multicastframe_g),
+ STMMAC_MMC_STAT(mmc_tx_64_octets_gb),
+ STMMAC_MMC_STAT(mmc_tx_65_to_127_octets_gb),
+ STMMAC_MMC_STAT(mmc_tx_128_to_255_octets_gb),
+ STMMAC_MMC_STAT(mmc_tx_256_to_511_octets_gb),
+ STMMAC_MMC_STAT(mmc_tx_512_to_1023_octets_gb),
+ STMMAC_MMC_STAT(mmc_tx_1024_to_max_octets_gb),
+ STMMAC_MMC_STAT(mmc_tx_unicast_gb),
+ STMMAC_MMC_STAT(mmc_tx_multicast_gb),
+ STMMAC_MMC_STAT(mmc_tx_broadcast_gb),
+ STMMAC_MMC_STAT(mmc_tx_underflow_error),
+ STMMAC_MMC_STAT(mmc_tx_singlecol_g),
+ STMMAC_MMC_STAT(mmc_tx_multicol_g),
+ STMMAC_MMC_STAT(mmc_tx_deferred),
+ STMMAC_MMC_STAT(mmc_tx_latecol),
+ STMMAC_MMC_STAT(mmc_tx_exesscol),
+ STMMAC_MMC_STAT(mmc_tx_carrier_error),
+ STMMAC_MMC_STAT(mmc_tx_octetcount_g),
+ STMMAC_MMC_STAT(mmc_tx_framecount_g),
+ STMMAC_MMC_STAT(mmc_tx_excessdef),
+ STMMAC_MMC_STAT(mmc_tx_pause_frame),
+ STMMAC_MMC_STAT(mmc_tx_vlan_frame_g),
+ STMMAC_MMC_STAT(mmc_rx_framecount_gb),
+ STMMAC_MMC_STAT(mmc_rx_octetcount_gb),
+ STMMAC_MMC_STAT(mmc_rx_octetcount_g),
+ STMMAC_MMC_STAT(mmc_rx_broadcastframe_g),
+ STMMAC_MMC_STAT(mmc_rx_multicastframe_g),
+ STMMAC_MMC_STAT(mmc_rx_crc_errror),
+ STMMAC_MMC_STAT(mmc_rx_align_error),
+ STMMAC_MMC_STAT(mmc_rx_run_error),
+ STMMAC_MMC_STAT(mmc_rx_jabber_error),
+ STMMAC_MMC_STAT(mmc_rx_undersize_g),
+ STMMAC_MMC_STAT(mmc_rx_oversize_g),
+ STMMAC_MMC_STAT(mmc_rx_64_octets_gb),
+ STMMAC_MMC_STAT(mmc_rx_65_to_127_octets_gb),
+ STMMAC_MMC_STAT(mmc_rx_128_to_255_octets_gb),
+ STMMAC_MMC_STAT(mmc_rx_256_to_511_octets_gb),
+ STMMAC_MMC_STAT(mmc_rx_512_to_1023_octets_gb),
+ STMMAC_MMC_STAT(mmc_rx_1024_to_max_octets_gb),
+ STMMAC_MMC_STAT(mmc_rx_unicast_g),
+ STMMAC_MMC_STAT(mmc_rx_length_error),
+ STMMAC_MMC_STAT(mmc_rx_autofrangetype),
+ STMMAC_MMC_STAT(mmc_rx_pause_frames),
+ STMMAC_MMC_STAT(mmc_rx_fifo_overflow),
+ STMMAC_MMC_STAT(mmc_rx_vlan_frames_gb),
+ STMMAC_MMC_STAT(mmc_rx_watchdog_error),
+ STMMAC_MMC_STAT(mmc_rx_ipc_intr_mask),
+ STMMAC_MMC_STAT(mmc_rx_ipc_intr),
+ STMMAC_MMC_STAT(mmc_rx_ipv4_gd),
+ STMMAC_MMC_STAT(mmc_rx_ipv4_hderr),
+ STMMAC_MMC_STAT(mmc_rx_ipv4_nopay),
+ STMMAC_MMC_STAT(mmc_rx_ipv4_frag),
+ STMMAC_MMC_STAT(mmc_rx_ipv4_udsbl),
+ STMMAC_MMC_STAT(mmc_rx_ipv4_gd_octets),
+ STMMAC_MMC_STAT(mmc_rx_ipv4_hderr_octets),
+ STMMAC_MMC_STAT(mmc_rx_ipv4_nopay_octets),
+ STMMAC_MMC_STAT(mmc_rx_ipv4_frag_octets),
+ STMMAC_MMC_STAT(mmc_rx_ipv4_udsbl_octets),
+ STMMAC_MMC_STAT(mmc_rx_ipv6_gd_octets),
+ STMMAC_MMC_STAT(mmc_rx_ipv6_hderr_octets),
+ STMMAC_MMC_STAT(mmc_rx_ipv6_nopay_octets),
+ STMMAC_MMC_STAT(mmc_rx_ipv6_gd),
+ STMMAC_MMC_STAT(mmc_rx_ipv6_hderr),
+ STMMAC_MMC_STAT(mmc_rx_ipv6_nopay),
+ STMMAC_MMC_STAT(mmc_rx_udp_gd),
+ STMMAC_MMC_STAT(mmc_rx_udp_err),
+ STMMAC_MMC_STAT(mmc_rx_tcp_gd),
+ STMMAC_MMC_STAT(mmc_rx_tcp_err),
+ STMMAC_MMC_STAT(mmc_rx_icmp_gd),
+ STMMAC_MMC_STAT(mmc_rx_icmp_err),
+ STMMAC_MMC_STAT(mmc_rx_udp_gd_octets),
+ STMMAC_MMC_STAT(mmc_rx_udp_err_octets),
+ STMMAC_MMC_STAT(mmc_rx_tcp_gd_octets),
+ STMMAC_MMC_STAT(mmc_rx_tcp_err_octets),
+ STMMAC_MMC_STAT(mmc_rx_icmp_gd_octets),
+ STMMAC_MMC_STAT(mmc_rx_icmp_err_octets),
+};
+#define STMMAC_MMC_STATS_LEN ARRAY_SIZE(stmmac_mmc)
+
static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
struct stmmac_priv *priv = netdev_priv(dev);
- if (!priv->plat->has_gmac)
- strcpy(info->driver, MAC100_ETHTOOL_NAME);
- else
+ if (priv->plat->has_gmac)
strcpy(info->driver, GMAC_ETHTOOL_NAME);
+ else
+ strcpy(info->driver, MAC100_ETHTOOL_NAME);
strcpy(info->version, DRV_MODULE_VERSION);
info->fw_version[0] = '\0';
- info->n_stats = STMMAC_STATS_LEN;
}
static int stmmac_ethtool_getsettings(struct net_device *dev,
@@ -252,24 +339,48 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *dummy, u64 *data)
{
struct stmmac_priv *priv = netdev_priv(dev);
- int i;
-
- /* Update HW stats if supported */
- priv->hw->dma->dma_diagnostic_fr(&dev->stats, (void *) &priv->xstats,
- priv->ioaddr);
+ int i, j = 0;
+ /* Update the DMA HW counters for dwmac10/100 */
+ if (!priv->plat->has_gmac)
+ priv->hw->dma->dma_diagnostic_fr(&dev->stats,
+ (void *) &priv->xstats,
+ priv->ioaddr);
+ else {
+ /* If supported, for new GMAC chips expose the MMC counters */
+ if (priv->dma_cap.rmon) {
+ dwmac_mmc_read(priv->ioaddr, &priv->mmc);
+
+ for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
+ char *p;
+ p = (char *)priv + stmmac_mmc[i].stat_offset;
+
+ data[j++] = (stmmac_mmc[i].sizeof_stat ==
+ sizeof(u64)) ? (*(u64 *)p) :
+ (*(u32 *)p);
+ }
+ }
+ }
for (i = 0; i < STMMAC_STATS_LEN; i++) {
char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
- data[i] = (stmmac_gstrings_stats[i].sizeof_stat ==
- sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
+ data[j++] = (stmmac_gstrings_stats[i].sizeof_stat ==
+ sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
}
}
static int stmmac_get_sset_count(struct net_device *netdev, int sset)
{
+ struct stmmac_priv *priv = netdev_priv(netdev);
+ int len;
+
switch (sset) {
case ETH_SS_STATS:
- return STMMAC_STATS_LEN;
+ len = STMMAC_STATS_LEN;
+
+ if (priv->dma_cap.rmon)
+ len += STMMAC_MMC_STATS_LEN;
+
+ return len;
default:
return -EOPNOTSUPP;
}
@@ -279,9 +390,16 @@ static void stmmac_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
int i;
u8 *p = data;
+ struct stmmac_priv *priv = netdev_priv(dev);
switch (stringset) {
case ETH_SS_STATS:
+ if (priv->dma_cap.rmon)
+ for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
+ memcpy(p, stmmac_mmc[i].stat_string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
for (i = 0; i < STMMAC_STATS_LEN; i++) {
memcpy(p, stmmac_gstrings_stats[i].stat_string,
ETH_GSTRING_LEN);
@@ -321,10 +439,10 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
if (wol->wolopts) {
pr_info("stmmac: wakeup enable\n");
device_set_wakeup_enable(priv->device, 1);
- enable_irq_wake(dev->irq);
+ enable_irq_wake(priv->wol_irq);
} else {
device_set_wakeup_enable(priv->device, 0);
- disable_irq_wake(dev->irq);
+ disable_irq_wake(priv->wol_irq);
}
spin_lock_irq(&priv->lock);
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c6e567e04eff..20546bbbb8db 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2,7 +2,7 @@
This is the driver for the ST MAC 10/100/1000 on-chip Ethernet controllers.
ST Ethernet IPs are built around a Synopsys IP Core.
- Copyright (C) 2007-2009 STMicroelectronics Ltd
+ Copyright(C) 2007-2011 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,
@@ -41,11 +41,15 @@
#include <linux/if_ether.h>
#include <linux/crc32.h>
#include <linux/mii.h>
-#include <linux/phy.h>
+#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/prefetch.h>
+#ifdef CONFIG_STMMAC_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#endif
#include "stmmac.h"
#define STMMAC_RESOURCE_NAME "stmmaceth"
@@ -299,7 +303,7 @@ static int stmmac_init_phy(struct net_device *dev)
struct phy_device *phydev;
char phy_id[MII_BUS_ID_SIZE + 3];
char bus_id[MII_BUS_ID_SIZE];
-
+ int interface = priv->plat->interface;
priv->oldlink = 0;
priv->speed = 0;
priv->oldduplex = -1;
@@ -309,14 +313,21 @@ static int stmmac_init_phy(struct net_device *dev)
priv->plat->phy_addr);
pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id);
- phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0,
- priv->plat->interface);
+ phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0, interface);
if (IS_ERR(phydev)) {
pr_err("%s: Could not attach to PHY\n", dev->name);
return PTR_ERR(phydev);
}
+ /* Stop Advertising 1000BASE Capability if interface is not GMII */
+ if ((interface) && ((interface == PHY_INTERFACE_MODE_MII) ||
+ (interface == PHY_INTERFACE_MODE_RMII))) {
+ phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ phydev->advertising = phydev->supported;
+ }
+
/*
* Broken HW is sometimes missing the pull-up resistor on the
* MDIO line, which results in reads to non-existent devices returning
@@ -376,11 +387,28 @@ static void display_ring(struct dma_desc *p, int size)
}
}
+static int stmmac_set_bfsize(int mtu, int bufsize)
+{
+ int ret = bufsize;
+
+ if (mtu >= BUF_SIZE_4KiB)
+ ret = BUF_SIZE_8KiB;
+ else if (mtu >= BUF_SIZE_2KiB)
+ ret = BUF_SIZE_4KiB;
+ else if (mtu >= DMA_BUFFER_SIZE)
+ ret = BUF_SIZE_2KiB;
+ else
+ ret = DMA_BUFFER_SIZE;
+
+ return ret;
+}
+
/**
* init_dma_desc_rings - init the RX/TX descriptor rings
* @dev: net device structure
* Description: this function initializes the DMA RX/TX descriptors
- * and allocates the socket buffers.
+ * and allocates the socket buffers. It suppors the chained and ring
+ * modes.
*/
static void init_dma_desc_rings(struct net_device *dev)
{
@@ -389,31 +417,24 @@ static void init_dma_desc_rings(struct net_device *dev)
struct sk_buff *skb;
unsigned int txsize = priv->dma_tx_size;
unsigned int rxsize = priv->dma_rx_size;
- unsigned int bfsize = priv->dma_buf_sz;
- int buff2_needed = 0, dis_ic = 0;
+ unsigned int bfsize;
+ int dis_ic = 0;
+ int des3_as_data_buf = 0;
- /* Set the Buffer size according to the MTU;
- * indeed, in case of jumbo we need to bump-up the buffer sizes.
- */
- if (unlikely(dev->mtu >= BUF_SIZE_8KiB))
- bfsize = BUF_SIZE_16KiB;
- else if (unlikely(dev->mtu >= BUF_SIZE_4KiB))
- bfsize = BUF_SIZE_8KiB;
- else if (unlikely(dev->mtu >= BUF_SIZE_2KiB))
- bfsize = BUF_SIZE_4KiB;
- else if (unlikely(dev->mtu >= DMA_BUFFER_SIZE))
- bfsize = BUF_SIZE_2KiB;
+ /* Set the max buffer size according to the DESC mode
+ * and the MTU. Note that RING mode allows 16KiB bsize. */
+ bfsize = priv->hw->ring->set_16kib_bfsize(dev->mtu);
+
+ if (bfsize == BUF_SIZE_16KiB)
+ des3_as_data_buf = 1;
else
- bfsize = DMA_BUFFER_SIZE;
+ 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
- /* If the MTU exceeds 8k so use the second buffer in the chain */
- if (bfsize >= BUF_SIZE_8KiB)
- buff2_needed = 1;
DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n",
txsize, rxsize, bfsize);
@@ -441,7 +462,7 @@ static void init_dma_desc_rings(struct net_device *dev)
return;
}
- DBG(probe, INFO, "stmmac (%s) DMA desc rings: virt addr (Rx %p, "
+ DBG(probe, INFO, "stmmac (%s) DMA desc: virt addr (Rx %p, "
"Tx %p)\n\tDMA phy addr (Rx 0x%08x, Tx 0x%08x)\n",
dev->name, priv->dma_rx, priv->dma_tx,
(unsigned int)priv->dma_rx_phy, (unsigned int)priv->dma_tx_phy);
@@ -453,18 +474,21 @@ static void init_dma_desc_rings(struct net_device *dev)
for (i = 0; i < rxsize; i++) {
struct dma_desc *p = priv->dma_rx + i;
- skb = netdev_alloc_skb_ip_align(dev, bfsize);
+ skb = __netdev_alloc_skb(dev, bfsize + NET_IP_ALIGN,
+ GFP_KERNEL);
if (unlikely(skb == NULL)) {
pr_err("%s: Rx init fails; skb is NULL\n", __func__);
break;
}
+ skb_reserve(skb, NET_IP_ALIGN);
priv->rx_skbuff[i] = skb;
priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
bfsize, DMA_FROM_DEVICE);
p->des2 = priv->rx_skbuff_dma[i];
- if (unlikely(buff2_needed))
- p->des3 = p->des2 + BUF_SIZE_8KiB;
+
+ priv->hw->ring->init_desc3(des3_as_data_buf, p);
+
DBG(probe, INFO, "[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
priv->rx_skbuff[i]->data, priv->rx_skbuff_dma[i]);
}
@@ -478,6 +502,12 @@ static void init_dma_desc_rings(struct net_device *dev)
priv->tx_skbuff[i] = NULL;
priv->dma_tx[i].des2 = 0;
}
+
+ /* In case of Chained mode this sets the des3 to the next
+ * element in the chain */
+ priv->hw->ring->init_dma_chain(priv->dma_rx, priv->dma_rx_phy, rxsize);
+ priv->hw->ring->init_dma_chain(priv->dma_tx, priv->dma_tx_phy, txsize);
+
priv->dirty_tx = 0;
priv->cur_tx = 0;
@@ -576,6 +606,8 @@ static void stmmac_tx(struct stmmac_priv *priv)
{
unsigned int txsize = priv->dma_tx_size;
+ spin_lock(&priv->tx_lock);
+
while (priv->dirty_tx != priv->cur_tx) {
int last;
unsigned int entry = priv->dirty_tx % txsize;
@@ -606,8 +638,7 @@ static void stmmac_tx(struct stmmac_priv *priv)
dma_unmap_single(priv->device, p->des2,
priv->hw->desc->get_tx_len(p),
DMA_TO_DEVICE);
- if (unlikely(p->des3))
- p->des3 = 0;
+ priv->hw->ring->clean_desc3(p);
if (likely(skb != NULL)) {
/*
@@ -639,6 +670,7 @@ static void stmmac_tx(struct stmmac_priv *priv)
}
netif_tx_unlock(priv->dev);
}
+ spin_unlock(&priv->tx_lock);
}
static inline void stmmac_enable_irq(struct stmmac_priv *priv)
@@ -713,7 +745,6 @@ static void stmmac_no_timer_stopped(void)
*/
static void stmmac_tx_err(struct stmmac_priv *priv)
{
-
netif_stop_queue(priv->dev);
priv->hw->dma->stop_tx(priv->ioaddr);
@@ -747,6 +778,91 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
stmmac_tx_err(priv);
}
+static void stmmac_mmc_setup(struct stmmac_priv *priv)
+{
+ unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
+ MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
+
+ /* Do not manage MMC IRQ (FIXME) */
+ dwmac_mmc_intr_all_mask(priv->ioaddr);
+ dwmac_mmc_ctrl(priv->ioaddr, mode);
+ memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
+}
+
+static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
+{
+ u32 hwid = priv->hw->synopsys_uid;
+
+ /* Only check valid Synopsys Id because old MAC chips
+ * have no HW registers where get the ID */
+ if (likely(hwid)) {
+ u32 uid = ((hwid & 0x0000ff00) >> 8);
+ u32 synid = (hwid & 0x000000ff);
+
+ pr_info("STMMAC - user ID: 0x%x, Synopsys ID: 0x%x\n",
+ uid, synid);
+
+ return synid;
+ }
+ return 0;
+}
+
+/* New GMAC chips support a new register to indicate the
+ * presence of the optional feature/functions.
+ */
+static int stmmac_get_hw_features(struct stmmac_priv *priv)
+{
+ u32 hw_cap = 0;
+
+ if (priv->hw->dma->get_hw_feature) {
+ hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
+
+ priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
+ priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
+ priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
+ priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
+ priv->dma_cap.multi_addr =
+ (hw_cap & DMA_HW_FEAT_ADDMACADRSEL) >> 5;
+ priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
+ priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
+ priv->dma_cap.pmt_remote_wake_up =
+ (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
+ priv->dma_cap.pmt_magic_frame =
+ (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
+ /*MMC*/
+ priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
+ /* IEEE 1588-2002*/
+ priv->dma_cap.time_stamp =
+ (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
+ /* IEEE 1588-2008*/
+ priv->dma_cap.atime_stamp =
+ (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
+ /* 802.3az - Energy-Efficient Ethernet (EEE) */
+ priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
+ priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
+ /* TX and RX csum */
+ priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
+ priv->dma_cap.rx_coe_type1 =
+ (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
+ priv->dma_cap.rx_coe_type2 =
+ (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
+ priv->dma_cap.rxfifo_over_2048 =
+ (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
+ /* TX and RX number of channels */
+ priv->dma_cap.number_rx_channel =
+ (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
+ priv->dma_cap.number_tx_channel =
+ (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
+ /* Alternate (enhanced) DESC mode*/
+ priv->dma_cap.enh_desc =
+ (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
+
+ } else
+ pr_debug("\tNo HW DMA feature register supported");
+
+ return hw_cap;
+}
+
/**
* stmmac_open - open entry point of the driver
* @dev : pointer to the device structure.
@@ -819,6 +935,10 @@ static int stmmac_open(struct net_device *dev)
/* Initialize the MAC Core */
priv->hw->mac->core_init(priv->ioaddr);
+ stmmac_get_synopsys_id(priv);
+
+ stmmac_get_hw_features(priv);
+
priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
if (priv->rx_coe)
pr_info("stmmac: Rx Checksum Offload Engine supported\n");
@@ -826,10 +946,6 @@ static int stmmac_open(struct net_device *dev)
pr_info("\tTX Checksum insertion supported\n");
netdev_update_features(dev);
- /* Initialise the MMC (if present) to disable all interrupts. */
- writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
- writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
-
/* Request the IRQ lines */
ret = request_irq(dev->irq, stmmac_interrupt,
IRQF_SHARED, dev->name, dev);
@@ -849,6 +965,9 @@ static int stmmac_open(struct net_device *dev)
memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
priv->xstats.threshold = tc;
+ if (priv->dma_cap.rmon)
+ stmmac_mmc_setup(priv);
+
/* Start the ball rolling... */
DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
priv->hw->dma->start_tx(priv->ioaddr);
@@ -928,47 +1047,6 @@ static int stmmac_release(struct net_device *dev)
return 0;
}
-static unsigned int stmmac_handle_jumbo_frames(struct sk_buff *skb,
- struct net_device *dev,
- int csum_insertion)
-{
- struct stmmac_priv *priv = netdev_priv(dev);
- unsigned int nopaged_len = skb_headlen(skb);
- unsigned int txsize = priv->dma_tx_size;
- unsigned int entry = priv->cur_tx % txsize;
- struct dma_desc *desc = priv->dma_tx + entry;
-
- if (nopaged_len > BUF_SIZE_8KiB) {
-
- int buf2_size = nopaged_len - BUF_SIZE_8KiB;
-
- desc->des2 = dma_map_single(priv->device, skb->data,
- BUF_SIZE_8KiB, DMA_TO_DEVICE);
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
- priv->hw->desc->prepare_tx_desc(desc, 1, BUF_SIZE_8KiB,
- csum_insertion);
-
- entry = (++priv->cur_tx) % txsize;
- desc = priv->dma_tx + entry;
-
- desc->des2 = dma_map_single(priv->device,
- skb->data + BUF_SIZE_8KiB,
- buf2_size, DMA_TO_DEVICE);
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
- priv->hw->desc->prepare_tx_desc(desc, 0, buf2_size,
- csum_insertion);
- priv->hw->desc->set_tx_owner(desc);
- priv->tx_skbuff[entry] = NULL;
- } else {
- desc->des2 = dma_map_single(priv->device, skb->data,
- nopaged_len, DMA_TO_DEVICE);
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
- priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
- csum_insertion);
- }
- return entry;
-}
-
/**
* stmmac_xmit:
* @skb : the socket buffer
@@ -983,6 +1061,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
int i, csum_insertion = 0;
int nfrags = skb_shinfo(skb)->nr_frags;
struct dma_desc *desc, *first;
+ unsigned int nopaged_len = skb_headlen(skb);
if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
if (!netif_queue_stopped(dev)) {
@@ -994,6 +1073,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
+ spin_lock(&priv->tx_lock);
+
entry = priv->cur_tx % txsize;
#ifdef STMMAC_XMIT_DEBUG
@@ -1001,7 +1082,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
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, skb_headlen(skb), nfrags, skb->ip_summed,
+ skb, skb->len, nopaged_len, nfrags, skb->ip_summed,
!skb_is_gso(skb) ? "isn't" : "is");
#endif
@@ -1014,14 +1095,14 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
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, skb_headlen(skb), nfrags, skb->ip_summed);
+ skb->len, nopaged_len, nfrags, skb->ip_summed);
#endif
priv->tx_skbuff[entry] = skb;
- if (unlikely(skb->len >= BUF_SIZE_4KiB)) {
- entry = stmmac_handle_jumbo_frames(skb, dev, csum_insertion);
+
+ if (priv->hw->ring->is_jumbo_frm(skb->len, priv->plat->enh_desc)) {
+ entry = priv->hw->ring->jumbo_frm(priv, skb, csum_insertion);
desc = priv->dma_tx + entry;
} else {
- unsigned int nopaged_len = skb_headlen(skb);
desc->des2 = dma_map_single(priv->device, skb->data,
nopaged_len, DMA_TO_DEVICE);
priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
@@ -1029,16 +1110,15 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
}
for (i = 0; i < nfrags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- int len = frag->size;
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ int len = skb_frag_size(frag);
entry = (++priv->cur_tx) % txsize;
desc = priv->dma_tx + entry;
TX_DBG("\t[entry %d] segment len: %d\n", entry, len);
- desc->des2 = dma_map_page(priv->device, frag->page,
- frag->page_offset,
- len, DMA_TO_DEVICE);
+ desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
+ DMA_TO_DEVICE);
priv->tx_skbuff[entry] = NULL;
priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion);
wmb();
@@ -1083,6 +1163,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
priv->hw->dma->enable_dma_transmission(priv->ioaddr);
+ spin_unlock(&priv->tx_lock);
+
return NETDEV_TX_OK;
}
@@ -1111,11 +1193,10 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
DMA_FROM_DEVICE);
(p + entry)->des2 = priv->rx_skbuff_dma[entry];
- if (unlikely(priv->plat->has_gmac)) {
- if (bfsize >= BUF_SIZE_8KiB)
- (p + entry)->des3 =
- (p + entry)->des2 + BUF_SIZE_8KiB;
- }
+
+ if (unlikely(priv->plat->has_gmac))
+ priv->hw->ring->refill_desc3(bfsize, p + entry);
+
RX_DBG(KERN_INFO "\trefill entry #%d\n", entry);
}
wmb();
@@ -1196,8 +1277,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
#endif
skb->protocol = eth_type_trans(skb, priv->dev);
- if (unlikely(status == csum_none)) {
- /* always for the old mac 10/100 */
+ if (unlikely(!priv->rx_coe)) {
+ /* No RX COE for old mac10/100 devices */
skb_checksum_none_assert(skb);
netif_receive_skb(skb);
} else {
@@ -1284,7 +1365,7 @@ static int stmmac_config(struct net_device *dev, struct ifmap *map)
}
/**
- * stmmac_multicast_list - entry point for multicast addressing
+ * stmmac_set_rx_mode - entry point for multicast addressing
* @dev : pointer to the device structure
* Description:
* This function is a driver entry point which gets called by the kernel
@@ -1292,7 +1373,7 @@ static int stmmac_config(struct net_device *dev, struct ifmap *map)
* Return value:
* void.
*/
-static void stmmac_multicast_list(struct net_device *dev)
+static void stmmac_set_rx_mode(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
@@ -1322,10 +1403,10 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
return -EBUSY;
}
- if (priv->plat->has_gmac)
+ if (priv->plat->enh_desc)
max_mtu = JUMBO_LEN;
else
- max_mtu = ETH_DATA_LEN;
+ max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
if ((new_mtu < 46) || (new_mtu > max_mtu)) {
pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
@@ -1415,13 +1496,189 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return ret;
}
+#ifdef CONFIG_STMMAC_DEBUG_FS
+static struct dentry *stmmac_fs_dir;
+static struct dentry *stmmac_rings_status;
+static struct dentry *stmmac_dma_cap;
+
+static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
+{
+ struct tmp_s {
+ u64 a;
+ unsigned int b;
+ unsigned int c;
+ };
+ int i;
+ struct net_device *dev = seq->private;
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+ seq_printf(seq, "=======================\n");
+ seq_printf(seq, " RX descriptor ring\n");
+ seq_printf(seq, "=======================\n");
+
+ for (i = 0; i < priv->dma_rx_size; i++) {
+ struct tmp_s *x = (struct tmp_s *)(priv->dma_rx + i);
+ seq_printf(seq, "[%d] DES0=0x%x DES1=0x%x BUF1=0x%x BUF2=0x%x",
+ i, (unsigned int)(x->a),
+ (unsigned int)((x->a) >> 32), x->b, x->c);
+ seq_printf(seq, "\n");
+ }
+
+ seq_printf(seq, "\n");
+ seq_printf(seq, "=======================\n");
+ seq_printf(seq, " TX descriptor ring\n");
+ seq_printf(seq, "=======================\n");
+
+ for (i = 0; i < priv->dma_tx_size; i++) {
+ struct tmp_s *x = (struct tmp_s *)(priv->dma_tx + i);
+ seq_printf(seq, "[%d] DES0=0x%x DES1=0x%x BUF1=0x%x BUF2=0x%x",
+ i, (unsigned int)(x->a),
+ (unsigned int)((x->a) >> 32), x->b, x->c);
+ seq_printf(seq, "\n");
+ }
+
+ return 0;
+}
+
+static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
+}
+
+static const struct file_operations stmmac_rings_status_fops = {
+ .owner = THIS_MODULE,
+ .open = stmmac_sysfs_ring_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
+{
+ struct net_device *dev = seq->private;
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+ if (!stmmac_get_hw_features(priv)) {
+ seq_printf(seq, "DMA HW features not supported\n");
+ return 0;
+ }
+
+ seq_printf(seq, "==============================\n");
+ seq_printf(seq, "\tDMA HW features\n");
+ seq_printf(seq, "==============================\n");
+
+ seq_printf(seq, "\t10/100 Mbps %s\n",
+ (priv->dma_cap.mbps_10_100) ? "Y" : "N");
+ seq_printf(seq, "\t1000 Mbps %s\n",
+ (priv->dma_cap.mbps_1000) ? "Y" : "N");
+ seq_printf(seq, "\tHalf duple %s\n",
+ (priv->dma_cap.half_duplex) ? "Y" : "N");
+ seq_printf(seq, "\tHash Filter: %s\n",
+ (priv->dma_cap.hash_filter) ? "Y" : "N");
+ seq_printf(seq, "\tMultiple MAC address registers: %s\n",
+ (priv->dma_cap.multi_addr) ? "Y" : "N");
+ seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
+ (priv->dma_cap.pcs) ? "Y" : "N");
+ seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
+ (priv->dma_cap.sma_mdio) ? "Y" : "N");
+ seq_printf(seq, "\tPMT Remote wake up: %s\n",
+ (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
+ seq_printf(seq, "\tPMT Magic Frame: %s\n",
+ (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
+ seq_printf(seq, "\tRMON module: %s\n",
+ (priv->dma_cap.rmon) ? "Y" : "N");
+ seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
+ (priv->dma_cap.time_stamp) ? "Y" : "N");
+ seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
+ (priv->dma_cap.atime_stamp) ? "Y" : "N");
+ seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
+ (priv->dma_cap.eee) ? "Y" : "N");
+ seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
+ seq_printf(seq, "\tChecksum Offload in TX: %s\n",
+ (priv->dma_cap.tx_coe) ? "Y" : "N");
+ seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
+ (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
+ seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
+ (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
+ seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
+ (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
+ seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
+ priv->dma_cap.number_rx_channel);
+ seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
+ priv->dma_cap.number_tx_channel);
+ seq_printf(seq, "\tEnhanced descriptors: %s\n",
+ (priv->dma_cap.enh_desc) ? "Y" : "N");
+
+ return 0;
+}
+
+static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
+}
+
+static const struct file_operations stmmac_dma_cap_fops = {
+ .owner = THIS_MODULE,
+ .open = stmmac_sysfs_dma_cap_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int stmmac_init_fs(struct net_device *dev)
+{
+ /* Create debugfs entries */
+ stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
+
+ if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
+ pr_err("ERROR %s, debugfs create directory failed\n",
+ STMMAC_RESOURCE_NAME);
+
+ return -ENOMEM;
+ }
+
+ /* Entry to report DMA RX/TX rings */
+ stmmac_rings_status = debugfs_create_file("descriptors_status",
+ S_IRUGO, stmmac_fs_dir, dev,
+ &stmmac_rings_status_fops);
+
+ if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
+ pr_info("ERROR creating stmmac ring debugfs file\n");
+ debugfs_remove(stmmac_fs_dir);
+
+ return -ENOMEM;
+ }
+
+ /* Entry to report the DMA HW features */
+ stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
+ dev, &stmmac_dma_cap_fops);
+
+ if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
+ pr_info("ERROR creating stmmac MMC debugfs file\n");
+ debugfs_remove(stmmac_rings_status);
+ debugfs_remove(stmmac_fs_dir);
+
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void stmmac_exit_fs(void)
+{
+ debugfs_remove(stmmac_rings_status);
+ debugfs_remove(stmmac_dma_cap);
+ debugfs_remove(stmmac_fs_dir);
+}
+#endif /* CONFIG_STMMAC_DEBUG_FS */
+
static const struct net_device_ops stmmac_netdev_ops = {
.ndo_open = stmmac_open,
.ndo_start_xmit = stmmac_xmit,
.ndo_stop = stmmac_release,
.ndo_change_mtu = stmmac_change_mtu,
.ndo_fix_features = stmmac_fix_features,
- .ndo_set_multicast_list = stmmac_multicast_list,
+ .ndo_set_rx_mode = stmmac_set_rx_mode,
.ndo_tx_timeout = stmmac_tx_timeout,
.ndo_do_ioctl = stmmac_ioctl,
.ndo_set_config = stmmac_config,
@@ -1472,6 +1729,7 @@ static int stmmac_probe(struct net_device *dev)
"please, use ifconfig or nwhwconfig!\n");
spin_lock_init(&priv->lock);
+ spin_lock_init(&priv->tx_lock);
ret = register_netdev(dev);
if (ret) {
@@ -1498,10 +1756,12 @@ static int stmmac_mac_device_setup(struct net_device *dev)
struct mac_device_info *device;
- if (priv->plat->has_gmac)
+ if (priv->plat->has_gmac) {
+ dev->priv_flags |= IFF_UNICAST_FLT;
device = dwmac1000_setup(priv->ioaddr);
- else
+ } else {
device = dwmac100_setup(priv->ioaddr);
+ }
if (!device)
return -ENOMEM;
@@ -1513,10 +1773,11 @@ static int stmmac_mac_device_setup(struct net_device *dev)
device->desc = &ndesc_ops;
priv->hw = device;
+ priv->hw->ring = &ring_mode_ops;
if (device_can_wakeup(priv->device)) {
priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
- enable_irq_wake(dev->irq);
+ enable_irq_wake(priv->wol_irq);
}
return 0;
@@ -1589,6 +1850,18 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
pr_info("\tPMT module supported\n");
device_set_wakeup_capable(&pdev->dev, 1);
}
+ /*
+ * On some platforms e.g. SPEAr the wake up irq differs from the mac irq
+ * The external wake up irq can be passed through the platform code
+ * named as "eth_wake_irq"
+ *
+ * In case the wake up interrupt is not passed from the platform
+ * so the driver will continue to use the mac irq (ndev->irq)
+ */
+ priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
+ if (priv->wol_irq == -ENXIO)
+ priv->wol_irq = ndev->irq;
+
platform_set_drvdata(pdev, ndev);
@@ -1627,6 +1900,13 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
if (ret < 0)
goto out_unregister;
pr_debug("registered!\n");
+
+#ifdef CONFIG_STMMAC_DEBUG_FS
+ ret = stmmac_init_fs(ndev);
+ if (ret < 0)
+ pr_warning("\tFailed debugFS registration");
+#endif
+
return 0;
out_unregister:
@@ -1679,6 +1959,10 @@ static int stmmac_dvr_remove(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
+#ifdef CONFIG_STMMAC_DEBUG_FS
+ stmmac_exit_fs();
+#endif
+
free_netdev(ndev);
return 0;
diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 9c3b9d5c3411..9c3b9d5c3411 100644
--- a/drivers/net/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
diff --git a/drivers/net/stmmac/stmmac_timer.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
index 2a0e1abde7e7..2a0e1abde7e7 100644
--- a/drivers/net/stmmac/stmmac_timer.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
diff --git a/drivers/net/stmmac/stmmac_timer.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
index 6863590d184b..6863590d184b 100644
--- a/drivers/net/stmmac/stmmac_timer.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
diff --git a/drivers/net/ethernet/sun/Kconfig b/drivers/net/ethernet/sun/Kconfig
new file mode 100644
index 000000000000..57bfd8599679
--- /dev/null
+++ b/drivers/net/ethernet/sun/Kconfig
@@ -0,0 +1,88 @@
+#
+# Sun network device configuration
+#
+
+config NET_VENDOR_SUN
+ bool "Sun devices"
+ default y
+ depends on SUN3 || SBUS || PCI || SUN_LDOMS
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say
+ Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Sun network interfaces. If you say Y, you will be
+ asked for your specific card in the following questions.
+
+if NET_VENDOR_SUN
+
+config HAPPYMEAL
+ tristate "Sun Happy Meal 10/100baseT support"
+ depends on (SBUS || PCI)
+ select CRC32
+ ---help---
+ This driver supports the "hme" interface present on most Ultra
+ systems and as an option on older Sbus systems. This driver supports
+ both PCI and Sbus devices. This driver also supports the "qfe" quad
+ 100baseT device available in both PCI and Sbus configurations.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sunhme.
+
+config SUNBMAC
+ tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
+ depends on SBUS && EXPERIMENTAL
+ select CRC32
+ ---help---
+ This driver supports the "be" interface available as an Sbus option.
+ This is Sun's older 100baseT Ethernet device.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sunbmac.
+
+config SUNQE
+ tristate "Sun QuadEthernet support"
+ depends on SBUS
+ select CRC32
+ ---help---
+ This driver supports the "qe" 10baseT Ethernet device, available as
+ an Sbus option. Note that this is not the same as Quad FastEthernet
+ "qfe" which is supported by the Happy Meal driver instead.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sunqe.
+
+config SUNGEM
+ tristate "Sun GEM support"
+ depends on PCI
+ select CRC32
+ select SUNGEM_PHY
+ ---help---
+ Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also
+ <http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>.
+
+config CASSINI
+ tristate "Sun Cassini support"
+ depends on PCI
+ select CRC32
+ ---help---
+ Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
+ <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
+
+config SUNVNET
+ tristate "Sun Virtual Network support"
+ depends on SUN_LDOMS
+ ---help---
+ Support for virtual network devices under Sun Logical Domains.
+
+config NIU
+ tristate "Sun Neptune 10Gbit Ethernet support"
+ depends on PCI
+ select CRC32
+ ---help---
+ This enables support for cards based upon Sun's
+ Neptune chipset.
+
+endif # NET_VENDOR_SUN
diff --git a/drivers/net/ethernet/sun/Makefile b/drivers/net/ethernet/sun/Makefile
new file mode 100644
index 000000000000..1e620ff88eba
--- /dev/null
+++ b/drivers/net/ethernet/sun/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the Sun network device drivers.
+#
+
+obj-$(CONFIG_HAPPYMEAL) += sunhme.o
+obj-$(CONFIG_SUNQE) += sunqe.o
+obj-$(CONFIG_SUNBMAC) += sunbmac.o
+obj-$(CONFIG_SUNGEM) += sungem.o
+obj-$(CONFIG_CASSINI) += cassini.o
+obj-$(CONFIG_SUNVNET) += sunvnet.o
+obj-$(CONFIG_NIU) += niu.o
diff --git a/drivers/net/cassini.c b/drivers/net/ethernet/sun/cassini.c
index fdb7a1756409..fd40988c19a6 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -2048,10 +2048,10 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
skb->truesize += hlen - swivel;
skb->len += hlen - swivel;
- get_page(page->buffer);
- frag->page = page->buffer;
+ __skb_frag_set_page(frag, page->buffer);
+ __skb_frag_ref(frag);
frag->page_offset = off;
- frag->size = hlen - swivel;
+ skb_frag_size_set(frag, hlen - swivel);
/* any more data? */
if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) {
@@ -2072,10 +2072,10 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
skb->len += hlen;
frag++;
- get_page(page->buffer);
- frag->page = page->buffer;
+ __skb_frag_set_page(frag, page->buffer);
+ __skb_frag_ref(frag);
frag->page_offset = 0;
- frag->size = hlen;
+ skb_frag_size_set(frag, hlen);
RX_USED_ADD(page, hlen + cp->crc_size);
}
@@ -2826,12 +2826,11 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring,
entry = TX_DESC_NEXT(ring, entry);
for (frag = 0; frag < nr_frags; frag++) {
- skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag];
+ const skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag];
- len = fragp->size;
- mapping = pci_map_page(cp->pdev, fragp->page,
- fragp->page_offset, len,
- PCI_DMA_TODEVICE);
+ len = skb_frag_size(fragp);
+ mapping = skb_frag_dma_map(&cp->pdev->dev, fragp, 0, len,
+ DMA_TO_DEVICE);
tabort = cas_calc_tabort(cp, fragp->page_offset, len);
if (unlikely(tabort)) {
@@ -2842,7 +2841,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring,
ctrl, 0);
entry = TX_DESC_NEXT(ring, entry);
- addr = cas_page_map(fragp->page);
+ addr = cas_page_map(skb_frag_page(fragp));
memcpy(tx_tiny_buf(cp, ring, entry),
addr + fragp->page_offset + len - tabort,
tabort);
@@ -4909,7 +4908,7 @@ static const struct net_device_ops cas_netdev_ops = {
.ndo_stop = cas_close,
.ndo_start_xmit = cas_start_xmit,
.ndo_get_stats = cas_get_stats,
- .ndo_set_multicast_list = cas_set_multicast,
+ .ndo_set_rx_mode = cas_set_multicast,
.ndo_do_ioctl = cas_ioctl,
.ndo_tx_timeout = cas_tx_timeout,
.ndo_change_mtu = cas_change_mtu,
diff --git a/drivers/net/cassini.h b/drivers/net/ethernet/sun/cassini.h
index b361424d5f57..b361424d5f57 100644
--- a/drivers/net/cassini.h
+++ b/drivers/net/ethernet/sun/cassini.h
diff --git a/drivers/net/niu.c b/drivers/net/ethernet/sun/niu.c
index ed47585a6862..73c708107a37 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/bitops.h>
#include <linux/mii.h>
+#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
@@ -3286,20 +3287,13 @@ static u16 tcam_get_valid_entry_cnt(struct niu *np)
}
static void niu_rx_skb_append(struct sk_buff *skb, struct page *page,
- u32 offset, u32 size)
+ u32 offset, u32 size, u32 truesize)
{
- int i = skb_shinfo(skb)->nr_frags;
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
- frag->page = page;
- frag->page_offset = offset;
- frag->size = size;
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, offset, size);
skb->len += size;
skb->data_len += size;
- skb->truesize += size;
-
- skb_shinfo(skb)->nr_frags = i + 1;
+ skb->truesize += truesize;
}
static unsigned int niu_hash_rxaddr(struct rx_ring_info *rp, u64 a)
@@ -3482,7 +3476,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
} else if (!(val & RCR_ENTRY_MULTI))
append_size = len - skb->len;
- niu_rx_skb_append(skb, page, off, append_size);
+ niu_rx_skb_append(skb, page, off, append_size, rcr_size);
if ((page->index + rp->rbr_block_size) - rcr_size == addr) {
*link = (struct page *) page->mapping;
np->ops->unmap_page(np->device, page->index,
@@ -3600,7 +3594,7 @@ static int release_tx_packet(struct niu *np, struct tx_ring_info *rp, int idx)
tb = &rp->tx_buffs[idx];
BUG_ON(tb->skb != NULL);
np->ops->unmap_page(np->device, tb->mapping,
- skb_shinfo(skb)->frags[i].size,
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
DMA_TO_DEVICE);
idx = NEXT_TX(rp, idx);
}
@@ -6733,10 +6727,10 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb,
}
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- len = frag->size;
- mapping = np->ops->map_page(np->device, frag->page,
+ len = skb_frag_size(frag);
+ mapping = np->ops->map_page(np->device, skb_frag_page(frag),
frag->page_offset, len,
DMA_TO_DEVICE);
@@ -7301,11 +7295,13 @@ static int niu_get_ethtool_tcam_all(struct niu *np,
}
niu_unlock_parent(np, flags);
+ nfc->rule_cnt = cnt;
+
return ret;
}
static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
- void *rule_locs)
+ u32 *rule_locs)
{
struct niu *np = netdev_priv(dev);
int ret = 0;
@@ -7324,7 +7320,7 @@ static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
ret = niu_get_ethtool_tcam_entry(np, cmd);
break;
case ETHTOOL_GRXCLSRLALL:
- ret = niu_get_ethtool_tcam_all(np, cmd, (u32 *)rule_locs);
+ ret = niu_get_ethtool_tcam_all(np, cmd, rule_locs);
break;
default:
ret = -EINVAL;
@@ -9716,7 +9712,7 @@ static const struct net_device_ops niu_netdev_ops = {
.ndo_stop = niu_close,
.ndo_start_xmit = niu_start_xmit,
.ndo_get_stats64 = niu_get_stats,
- .ndo_set_multicast_list = niu_set_rx_mode,
+ .ndo_set_rx_mode = niu_set_rx_mode,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = niu_set_mac_addr,
.ndo_do_ioctl = niu_ioctl,
@@ -9852,6 +9848,8 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
niu_set_basic_features(dev);
+ dev->priv_flags |= IFF_UNICAST_FLT;
+
np->regs = pci_ioremap_bar(pdev, 0);
if (!np->regs) {
dev_err(&pdev->dev, "Cannot map device registers, aborting\n");
diff --git a/drivers/net/niu.h b/drivers/net/ethernet/sun/niu.h
index 51e177e1860d..51e177e1860d 100644
--- a/drivers/net/niu.h
+++ b/drivers/net/ethernet/sun/niu.h
diff --git a/drivers/net/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c
index 297a4242106b..0d8cfd9ea053 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/ethernet/sun/sunbmac.c
@@ -17,6 +17,7 @@
#include <linux/crc32.h>
#include <linux/errno.h>
#include <linux/ethtool.h>
+#include <linux/mii.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
@@ -500,13 +501,13 @@ static int try_next_permutation(struct bigmac *bp, void __iomem *tregs)
/* Reset the PHY. */
bp->sw_bmcr = (BMCR_ISOLATE | BMCR_PDOWN | BMCR_LOOPBACK);
- bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+ bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
bp->sw_bmcr = (BMCR_RESET);
- bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+ bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
timeout = 64;
while (--timeout) {
- bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+ bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
if ((bp->sw_bmcr & BMCR_RESET) == 0)
break;
udelay(20);
@@ -514,11 +515,11 @@ static int try_next_permutation(struct bigmac *bp, void __iomem *tregs)
if (timeout == 0)
printk(KERN_ERR "%s: PHY reset failed.\n", bp->dev->name);
- bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+ bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
/* Now we try 10baseT. */
bp->sw_bmcr &= ~(BMCR_SPEED100);
- bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+ bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
return 0;
}
@@ -534,8 +535,8 @@ static void bigmac_timer(unsigned long data)
bp->timer_ticks++;
if (bp->timer_state == ltrywait) {
- bp->sw_bmsr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMSR);
- bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+ bp->sw_bmsr = bigmac_tcvr_read(bp, tregs, MII_BMSR);
+ bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
if (bp->sw_bmsr & BMSR_LSTATUS) {
printk(KERN_INFO "%s: Link is now up at %s.\n",
bp->dev->name,
@@ -588,18 +589,18 @@ static void bigmac_begin_auto_negotiation(struct bigmac *bp)
int timeout;
/* Grab new software copies of PHY registers. */
- bp->sw_bmsr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMSR);
- bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+ bp->sw_bmsr = bigmac_tcvr_read(bp, tregs, MII_BMSR);
+ bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
/* Reset the PHY. */
bp->sw_bmcr = (BMCR_ISOLATE | BMCR_PDOWN | BMCR_LOOPBACK);
- bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+ bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
bp->sw_bmcr = (BMCR_RESET);
- bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+ bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
timeout = 64;
while (--timeout) {
- bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+ bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
if ((bp->sw_bmcr & BMCR_RESET) == 0)
break;
udelay(20);
@@ -607,11 +608,11 @@ static void bigmac_begin_auto_negotiation(struct bigmac *bp)
if (timeout == 0)
printk(KERN_ERR "%s: PHY reset failed.\n", bp->dev->name);
- bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
+ bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, MII_BMCR);
/* First we try 100baseT. */
bp->sw_bmcr |= BMCR_SPEED100;
- bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
+ bigmac_tcvr_write(bp, tregs, MII_BMCR, bp->sw_bmcr);
bp->timer_state = ltrywait;
bp->timer_ticks = 0;
@@ -1054,7 +1055,7 @@ static u32 bigmac_get_link(struct net_device *dev)
struct bigmac *bp = netdev_priv(dev);
spin_lock_irq(&bp->lock);
- bp->sw_bmsr = bigmac_tcvr_read(bp, bp->tregs, BIGMAC_BMSR);
+ bp->sw_bmsr = bigmac_tcvr_read(bp, bp->tregs, MII_BMSR);
spin_unlock_irq(&bp->lock);
return (bp->sw_bmsr & BMSR_LSTATUS);
@@ -1070,7 +1071,7 @@ static const struct net_device_ops bigmac_ops = {
.ndo_stop = bigmac_close,
.ndo_start_xmit = bigmac_start_xmit,
.ndo_get_stats = bigmac_get_stats,
- .ndo_set_multicast_list = bigmac_set_multicast,
+ .ndo_set_rx_mode = bigmac_set_multicast,
.ndo_tx_timeout = bigmac_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/sunbmac.h b/drivers/net/ethernet/sun/sunbmac.h
index 4943e975a731..06dd21707353 100644
--- a/drivers/net/sunbmac.h
+++ b/drivers/net/ethernet/sun/sunbmac.h
@@ -223,23 +223,6 @@
#define BIGMAC_PHY_EXTERNAL 0 /* External transceiver */
#define BIGMAC_PHY_INTERNAL 1 /* Internal transceiver */
-/* PHY registers */
-#define BIGMAC_BMCR 0x00 /* Basic mode control register */
-#define BIGMAC_BMSR 0x01 /* Basic mode status register */
-
-/* BMCR bits */
-#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
-#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
-#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
-#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
-#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
-#define BMCR_RESET 0x8000 /* Reset the DP83840 */
-
-/* BMSR bits */
-#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
-#define BMSR_JCD 0x0002 /* Jabber detected */
-#define BMSR_LSTATUS 0x0004 /* Link status */
-
/* Ring descriptors and such, same as Quad Ethernet. */
struct be_rxd {
u32 rx_flags;
diff --git a/drivers/net/sungem.c b/drivers/net/ethernet/sun/sungem.c
index ade35dde5b51..ceab215bb4a3 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -59,7 +59,7 @@
#include <asm/pmac_feature.h>
#endif
-#include "sungem_phy.h"
+#include <linux/sungem_phy.h>
#include "sungem.h"
/* Stripping FCS is causing problems, disabled for now */
@@ -1065,16 +1065,14 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
entry = NEXT_TX(entry);
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
- skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
+ const skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
u32 len;
dma_addr_t mapping;
u64 this_ctrl;
- len = this_frag->size;
- mapping = pci_map_page(gp->pdev,
- this_frag->page,
- this_frag->page_offset,
- len, PCI_DMA_TODEVICE);
+ len = skb_frag_size(this_frag);
+ mapping = skb_frag_dma_map(&gp->pdev->dev, this_frag,
+ 0, len, DMA_TO_DEVICE);
this_ctrl = ctrl;
if (frag == skb_shinfo(skb)->nr_frags - 1)
this_ctrl |= TXDCTRL_EOF;
@@ -1721,7 +1719,7 @@ static void gem_init_phy(struct gem *gp)
if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1) {
/* Reset and detect MII PHY */
- mii_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
+ sungem_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
/* Init PHY */
if (gp->phy_mii.def && gp->phy_mii.def->ops->init)
@@ -2820,7 +2818,7 @@ static const struct net_device_ops gem_netdev_ops = {
.ndo_stop = gem_close,
.ndo_start_xmit = gem_start_xmit,
.ndo_get_stats = gem_get_stats,
- .ndo_set_multicast_list = gem_set_multicast,
+ .ndo_set_rx_mode = gem_set_multicast,
.ndo_do_ioctl = gem_ioctl,
.ndo_tx_timeout = gem_tx_timeout,
.ndo_change_mtu = gem_change_mtu,
diff --git a/drivers/net/sungem.h b/drivers/net/ethernet/sun/sungem.h
index 835ce1b3cb9f..835ce1b3cb9f 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/ethernet/sun/sungem.h
diff --git a/drivers/net/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index 856e05b9fba3..c517dac02ae1 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2305,13 +2305,12 @@ static netdev_tx_t happy_meal_start_xmit(struct sk_buff *skb,
entry = NEXT_TX(entry);
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
- skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
+ const skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
u32 len, mapping, this_txflags;
- len = this_frag->size;
- mapping = dma_map_page(hp->dma_dev, this_frag->page,
- this_frag->page_offset, len,
- DMA_TO_DEVICE);
+ len = skb_frag_size(this_frag);
+ mapping = skb_frag_dma_map(hp->dma_dev, this_frag,
+ 0, len, DMA_TO_DEVICE);
this_txflags = tx_flags;
if (frag == skb_shinfo(skb)->nr_frags - 1)
this_txflags |= TXFLAG_EOP;
@@ -2619,7 +2618,7 @@ static const struct net_device_ops hme_netdev_ops = {
.ndo_start_xmit = happy_meal_start_xmit,
.ndo_tx_timeout = happy_meal_tx_timeout,
.ndo_get_stats = happy_meal_get_stats,
- .ndo_set_multicast_list = happy_meal_set_multicast,
+ .ndo_set_rx_mode = happy_meal_set_multicast,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/sunhme.h b/drivers/net/ethernet/sun/sunhme.h
index 64f278360d89..64f278360d89 100644
--- a/drivers/net/sunhme.h
+++ b/drivers/net/ethernet/sun/sunhme.h
diff --git a/drivers/net/sunqe.c b/drivers/net/ethernet/sun/sunqe.c
index 209c7f8df003..b28f74367ebe 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/ethernet/sun/sunqe.c
@@ -824,7 +824,7 @@ static const struct net_device_ops qec_ops = {
.ndo_open = qe_open,
.ndo_stop = qe_close,
.ndo_start_xmit = qe_start_xmit,
- .ndo_set_multicast_list = qe_set_multicast,
+ .ndo_set_rx_mode = qe_set_multicast,
.ndo_tx_timeout = qe_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/sunqe.h b/drivers/net/ethernet/sun/sunqe.h
index 581781b6b2fa..581781b6b2fa 100644
--- a/drivers/net/sunqe.h
+++ b/drivers/net/ethernet/sun/sunqe.h
diff --git a/drivers/net/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index bf3c762de620..8c6c059f3489 100644
--- a/drivers/net/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -1012,7 +1012,7 @@ static DEFINE_MUTEX(vnet_list_mutex);
static const struct net_device_ops vnet_ops = {
.ndo_open = vnet_open,
.ndo_stop = vnet_close,
- .ndo_set_multicast_list = vnet_set_rx_mode,
+ .ndo_set_rx_mode = vnet_set_rx_mode,
.ndo_set_mac_address = vnet_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = vnet_tx_timeout,
diff --git a/drivers/net/sunvnet.h b/drivers/net/ethernet/sun/sunvnet.h
index d347a5bf24b0..d347a5bf24b0 100644
--- a/drivers/net/sunvnet.h
+++ b/drivers/net/ethernet/sun/sunvnet.h
diff --git a/drivers/net/ethernet/tehuti/Kconfig b/drivers/net/ethernet/tehuti/Kconfig
new file mode 100644
index 000000000000..1fc027eda33e
--- /dev/null
+++ b/drivers/net/ethernet/tehuti/Kconfig
@@ -0,0 +1,27 @@
+#
+# Tehuti network device configuration
+#
+
+config NET_VENDOR_TEHUTI
+ bool "Tehuti devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Tehuti cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_TEHUTI
+
+config TEHUTI
+ tristate "Tehuti Networks 10G Ethernet"
+ depends on PCI
+ ---help---
+ Tehuti Networks 10G Ethernet NIC
+
+endif # NET_VENDOR_TEHUTI
diff --git a/drivers/net/ethernet/tehuti/Makefile b/drivers/net/ethernet/tehuti/Makefile
new file mode 100644
index 000000000000..f995421ddbc8
--- /dev/null
+++ b/drivers/net/ethernet/tehuti/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Tehuti network device drivers.
+#
+
+obj-$(CONFIG_TEHUTI) += tehuti.o
diff --git a/drivers/net/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index 749bbf18dc6a..3a90af6d111c 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -67,10 +67,10 @@
#include "tehuti.h"
static DEFINE_PCI_DEVICE_TABLE(bdx_pci_tbl) = {
- {0x1FC9, 0x3009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x1FC9, 0x3010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x1FC9, 0x3014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0}
+ { PCI_VDEVICE(TEHUTI, 0x3009), },
+ { PCI_VDEVICE(TEHUTI, 0x3010), },
+ { PCI_VDEVICE(TEHUTI, 0x3014), },
+ { 0 }
};
MODULE_DEVICE_TABLE(pci, bdx_pci_tbl);
@@ -1493,13 +1493,13 @@ bdx_tx_map_skb(struct bdx_priv *priv, struct sk_buff *skb,
bdx_tx_db_inc_wptr(db);
for (i = 0; i < nr_frags; i++) {
- struct skb_frag_struct *frag;
+ const struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[i];
- db->wptr->len = frag->size;
- db->wptr->addr.dma =
- pci_map_page(priv->pdev, frag->page, frag->page_offset,
- frag->size, PCI_DMA_TODEVICE);
+ db->wptr->len = skb_frag_size(frag);
+ db->wptr->addr.dma = skb_frag_dma_map(&priv->pdev->dev, frag,
+ 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
pbl++;
pbl->len = CPU_CHIP_SWAP32(db->wptr->len);
@@ -1860,7 +1860,7 @@ static const struct net_device_ops bdx_netdev_ops = {
.ndo_start_xmit = bdx_tx_transmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = bdx_ioctl,
- .ndo_set_multicast_list = bdx_setmulti,
+ .ndo_set_rx_mode = bdx_setmulti,
.ndo_change_mtu = bdx_change_mtu,
.ndo_set_mac_address = bdx_set_mac,
.ndo_vlan_rx_add_vid = bdx_vlan_rx_add_vid,
diff --git a/drivers/net/tehuti.h b/drivers/net/ethernet/tehuti/tehuti.h
index 709ebd6e28b4..709ebd6e28b4 100644
--- a/drivers/net/tehuti.h
+++ b/drivers/net/ethernet/tehuti/tehuti.h
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
new file mode 100644
index 000000000000..de76c70ec8fb
--- /dev/null
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -0,0 +1,77 @@
+#
+# TI device configuration
+#
+
+config NET_VENDOR_TI
+ bool "Texas Instruments (TI) devices"
+ default y
+ depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3))
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about TI devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_TI
+
+config TI_DAVINCI_EMAC
+ tristate "TI DaVinci EMAC Support"
+ depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+ select TI_DAVINCI_MDIO
+ select TI_DAVINCI_CPDMA
+ select PHYLIB
+ ---help---
+ This driver supports TI's DaVinci Ethernet .
+
+ To compile this driver as a module, choose M here: the module
+ will be called davinci_emac_driver. This is recommended.
+
+config TI_DAVINCI_MDIO
+ tristate "TI DaVinci MDIO Support"
+ depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+ select PHYLIB
+ ---help---
+ This driver supports TI's DaVinci MDIO module.
+
+ To compile this driver as a module, choose M here: the module
+ will be called davinci_mdio. This is recommended.
+
+config TI_DAVINCI_CPDMA
+ tristate "TI DaVinci CPDMA Support"
+ depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+ ---help---
+ This driver supports TI's DaVinci CPDMA dma engine.
+
+ To compile this driver as a module, choose M here: the module
+ will be called davinci_cpdma. This is recommended.
+
+config TLAN
+ tristate "TI ThunderLAN support"
+ depends on (PCI || EISA)
+ ---help---
+ If you have a PCI Ethernet network card based on the ThunderLAN chip
+ which is supported by this driver, say Y and read the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Devices currently supported by this driver are Compaq Netelligent,
+ Compaq NetFlex and Olicom cards. Please read the file
+ <file:Documentation/networking/tlan.txt> for more details.
+
+ To compile this driver as a module, choose M here. The module
+ will be called tlan.
+
+ Please email feedback to <torben.mathiasen@compaq.com>.
+
+config CPMAC
+ tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && AR7
+ select PHYLIB
+ ---help---
+ TI AR7 CPMAC Ethernet support
+
+endif # NET_VENDOR_TI
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
new file mode 100644
index 000000000000..aedb3af74e5a
--- /dev/null
+++ b/drivers/net/ethernet/ti/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the TI network device drivers.
+#
+
+obj-$(CONFIG_TLAN) += tlan.o
+obj-$(CONFIG_CPMAC) += cpmac.o
+obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
+obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
+obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
diff --git a/drivers/net/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index e0638cb4b07c..aaac0c7ad111 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -1100,7 +1100,7 @@ static const struct net_device_ops cpmac_netdev_ops = {
.ndo_stop = cpmac_stop,
.ndo_start_xmit = cpmac_start_xmit,
.ndo_tx_timeout = cpmac_tx_timeout,
- .ndo_set_multicast_list = cpmac_set_multicast_list,
+ .ndo_set_rx_mode = cpmac_set_multicast_list,
.ndo_do_ioctl = cpmac_ioctl,
.ndo_set_config = cpmac_config,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index dca9d3369cdd..dca9d3369cdd 100644
--- a/drivers/net/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/ethernet/ti/davinci_cpdma.h
index afa19a0c0d81..afa19a0c0d81 100644
--- a/drivers/net/davinci_cpdma.h
+++ b/drivers/net/ethernet/ti/davinci_cpdma.h
diff --git a/drivers/net/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 3f451e4d8361..815c7970261b 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1741,7 +1741,7 @@ static const struct net_device_ops emac_netdev_ops = {
.ndo_open = emac_dev_open,
.ndo_stop = emac_dev_stop,
.ndo_start_xmit = emac_dev_xmit,
- .ndo_set_multicast_list = emac_dev_mcast_set,
+ .ndo_set_rx_mode = emac_dev_mcast_set,
.ndo_set_mac_address = emac_dev_setmac_addr,
.ndo_do_ioctl = emac_devioctl,
.ndo_tx_timeout = emac_dev_tx_timeout,
diff --git a/drivers/net/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 7615040df756..7615040df756 100644
--- a/drivers/net/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
diff --git a/drivers/net/tlan.c b/drivers/net/ethernet/ti/tlan.c
index 145871b3130b..9c0dd6b8d6c9 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/ethernet/ti/tlan.c
@@ -774,7 +774,7 @@ static const struct net_device_ops tlan_netdev_ops = {
.ndo_start_xmit = tlan_start_tx,
.ndo_tx_timeout = tlan_tx_timeout,
.ndo_get_stats = tlan_get_stats,
- .ndo_set_multicast_list = tlan_set_multicast_list,
+ .ndo_set_rx_mode = tlan_set_multicast_list,
.ndo_do_ioctl = tlan_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/tlan.h b/drivers/net/ethernet/ti/tlan.h
index 5fc98a8e4889..5fc98a8e4889 100644
--- a/drivers/net/tlan.h
+++ b/drivers/net/ethernet/ti/tlan.h
diff --git a/drivers/net/ethernet/tile/Kconfig b/drivers/net/ethernet/tile/Kconfig
new file mode 100644
index 000000000000..2d9218f86bca
--- /dev/null
+++ b/drivers/net/ethernet/tile/Kconfig
@@ -0,0 +1,15 @@
+#
+# Tilera network device configuration
+#
+
+config TILE_NET
+ tristate "Tilera GBE/XGBE network driver support"
+ depends on TILE
+ default y
+ select CRC32
+ ---help---
+ This is a standard Linux network device driver for the
+ on-chip Tilera Gigabit Ethernet and XAUI interfaces.
+
+ To compile this driver as a module, choose M here: the module
+ will be called tile_net.
diff --git a/drivers/net/tile/Makefile b/drivers/net/ethernet/tile/Makefile
index f634f142cab4..f634f142cab4 100644
--- a/drivers/net/tile/Makefile
+++ b/drivers/net/ethernet/tile/Makefile
diff --git a/drivers/net/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c
index 1e2af96fc29c..10826d8a2a2d 100644
--- a/drivers/net/tile/tilepro.c
+++ b/drivers/net/ethernet/tile/tilepro.c
@@ -177,7 +177,7 @@ struct tile_net_cpu {
struct tile_net_stats_t stats;
/* True iff NAPI is enabled. */
bool napi_enabled;
- /* True if this tile has succcessfully registered with the IPP. */
+ /* True if this tile has successfully registered with the IPP. */
bool registered;
/* True if the link was down last time we tried to register. */
bool link_down;
@@ -1713,7 +1713,7 @@ static unsigned int tile_net_tx_frags(lepp_frag_t *frags,
cpa = ((phys_addr_t)pfn << PAGE_SHIFT) + f->page_offset;
frags[n].cpa_lo = cpa;
frags[n].cpa_hi = cpa >> 32;
- frags[n].length = f->size;
+ frags[n].length = skb_frag_size(f);
frags[n].hash_for_home = hash_for_home;
n++;
}
diff --git a/drivers/net/ethernet/toshiba/Kconfig b/drivers/net/ethernet/toshiba/Kconfig
new file mode 100644
index 000000000000..051764704559
--- /dev/null
+++ b/drivers/net/ethernet/toshiba/Kconfig
@@ -0,0 +1,57 @@
+#
+# Toshiba network device configuration
+#
+
+config NET_VENDOR_TOSHIBA
+ bool "Toshiba devices"
+ default y
+ depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB) || PPC_PS3
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Toshiba cards. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_TOSHIBA
+
+config GELIC_NET
+ tristate "PS3 Gigabit Ethernet driver"
+ depends on PPC_PS3
+ select PS3_SYS_MANAGER
+ ---help---
+ This driver supports the network device on the PS3 game
+ console. This driver has built-in support for Ethernet.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ps3_gelic.
+
+config GELIC_WIRELESS
+ bool "PS3 Wireless support"
+ depends on GELIC_NET && WLAN
+ select WIRELESS_EXT
+ ---help---
+ This option adds the support for the wireless feature of PS3.
+ If you have the wireless-less model of PS3 or have no plan to
+ use wireless feature, disabling this option saves memory. As
+ the driver automatically distinguishes the models, you can
+ safely enable this option even if you have a wireless-less model.
+
+config SPIDER_NET
+ tristate "Spider Gigabit Ethernet driver"
+ depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB)
+ select FW_LOADER
+ select SUNGEM_PHY
+ ---help---
+ This driver supports the Gigabit Ethernet chips present on the
+ Cell Processor-Based Blades from IBM.
+
+config TC35815
+ tristate "TOSHIBA TC35815 Ethernet support"
+ depends on PCI && MIPS
+ select PHYLIB
+
+endif # NET_VENDOR_TOSHIBA
diff --git a/drivers/net/ethernet/toshiba/Makefile b/drivers/net/ethernet/toshiba/Makefile
new file mode 100644
index 000000000000..a5069008435b
--- /dev/null
+++ b/drivers/net/ethernet/toshiba/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the Toshiba network device drivers.
+#
+
+obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
+gelic_wireless-$(CONFIG_GELIC_WIRELESS) += ps3_gelic_wireless.o
+ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y)
+spidernet-y += spider_net.o spider_net_ethtool.o
+obj-$(CONFIG_SPIDER_NET) += spidernet.o
+obj-$(CONFIG_TC35815) += tc35815.o
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index d82a82d9870c..ddb33cfd3543 100644
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -1452,7 +1452,7 @@ static const struct net_device_ops gelic_netdevice_ops = {
.ndo_open = gelic_net_open,
.ndo_stop = gelic_net_stop,
.ndo_start_xmit = gelic_net_xmit,
- .ndo_set_multicast_list = gelic_net_set_multi,
+ .ndo_set_rx_mode = gelic_net_set_multi,
.ndo_change_mtu = gelic_net_change_mtu,
.ndo_tx_timeout = gelic_net_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ethernet/toshiba/ps3_gelic_net.h
index d3fadfbc3bcc..d3fadfbc3bcc 100644
--- a/drivers/net/ps3_gelic_net.h
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.h
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
index 2e62938c0f82..fd4ed7f8cfa1 100644
--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
@@ -2568,7 +2568,7 @@ static const struct net_device_ops gelic_wl_netdevice_ops = {
.ndo_open = gelic_wl_open,
.ndo_stop = gelic_wl_stop,
.ndo_start_xmit = gelic_net_xmit,
- .ndo_set_multicast_list = gelic_net_set_multi,
+ .ndo_set_rx_mode = gelic_net_set_multi,
.ndo_change_mtu = gelic_net_change_mtu,
.ndo_tx_timeout = gelic_net_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/ps3_gelic_wireless.h b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h
index f7e51b7d7049..f7e51b7d7049 100644
--- a/drivers/net/ps3_gelic_wireless.h
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h
diff --git a/drivers/net/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index 1ff3491c8240..6199f6b387b6 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -196,7 +196,7 @@ spider_net_setup_aneg(struct spider_net_card *card)
if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_THALF))
advertise |= SUPPORTED_1000baseT_Half;
- mii_phy_probe(phy, phy->mii_id);
+ sungem_phy_probe(phy, phy->mii_id);
phy->def->ops->setup_aneg(phy, advertise);
}
@@ -2120,7 +2120,7 @@ spider_net_setup_phy(struct spider_net_card *card)
unsigned short id;
id = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR);
if (id != 0x0000 && id != 0xffff) {
- if (!mii_phy_probe(phy, phy->mii_id)) {
+ if (!sungem_phy_probe(phy, phy->mii_id)) {
pr_info("Found %s.\n", phy->def->name);
break;
}
@@ -2259,7 +2259,7 @@ static const struct net_device_ops spider_net_ops = {
.ndo_open = spider_net_open,
.ndo_stop = spider_net_stop,
.ndo_start_xmit = spider_net_xmit,
- .ndo_set_multicast_list = spider_net_set_multi,
+ .ndo_set_rx_mode = spider_net_set_multi,
.ndo_set_mac_address = spider_net_set_mac,
.ndo_change_mtu = spider_net_change_mtu,
.ndo_do_ioctl = spider_net_do_ioctl,
diff --git a/drivers/net/spider_net.h b/drivers/net/ethernet/toshiba/spider_net.h
index 020f64a8fcf7..4ba2135474d1 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/ethernet/toshiba/spider_net.h
@@ -27,7 +27,7 @@
#define VERSION "2.0 B"
-#include "sungem_phy.h"
+#include <linux/sungem_phy.h>
extern int spider_net_stop(struct net_device *netdev);
extern int spider_net_open(struct net_device *netdev);
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/ethernet/toshiba/spider_net_ethtool.c
index 9c288cd7d171..9c288cd7d171 100644
--- a/drivers/net/spider_net_ethtool.c
+++ b/drivers/net/ethernet/toshiba/spider_net_ethtool.c
diff --git a/drivers/net/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
index 4a55a162dfe6..71b785cd7563 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/ethernet/toshiba/tc35815.c
@@ -774,7 +774,7 @@ static const struct net_device_ops tc35815_netdev_ops = {
.ndo_stop = tc35815_close,
.ndo_start_xmit = tc35815_send_packet,
.ndo_get_stats = tc35815_get_stats,
- .ndo_set_multicast_list = tc35815_set_multicast_list,
+ .ndo_set_rx_mode = tc35815_set_multicast_list,
.ndo_tx_timeout = tc35815_tx_timeout,
.ndo_do_ioctl = tc35815_ioctl,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/ethernet/tundra/Kconfig b/drivers/net/ethernet/tundra/Kconfig
new file mode 100644
index 000000000000..cf7d69b62c42
--- /dev/null
+++ b/drivers/net/ethernet/tundra/Kconfig
@@ -0,0 +1,29 @@
+#
+# Tundra network device configuration
+#
+
+config NET_VENDOR_TUNDRA
+ bool "Tundra devices"
+ default y
+ depends on TSI108_BRIDGE
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Tundra cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_TUNDRA
+
+config TSI108_ETH
+ tristate "Tundra TSI108 gigabit Ethernet support"
+ depends on TSI108_BRIDGE
+ ---help---
+ This driver supports Tundra TSI108 gigabit Ethernet ports.
+ To compile this driver as a module, choose M here: the module
+ will be called tsi108_eth.
+
+endif # NET_VENDOR_TUNDRA
diff --git a/drivers/net/ethernet/tundra/Makefile b/drivers/net/ethernet/tundra/Makefile
new file mode 100644
index 000000000000..439f6930235b
--- /dev/null
+++ b/drivers/net/ethernet/tundra/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Tundra network device drivers.
+#
+
+obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index 64cb9ac19ed9..a8df7eca0956 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -709,12 +709,13 @@ static int tsi108_send_packet(struct sk_buff * skb, struct net_device *dev)
data->txring[tx].len = skb_headlen(skb);
misc |= TSI108_TX_SOF;
} else {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
- data->txring[tx].buf0 =
- dma_map_page(NULL, frag->page, frag->page_offset,
- frag->size, DMA_TO_DEVICE);
- data->txring[tx].len = frag->size;
+ data->txring[tx].buf0 = skb_frag_dma_map(NULL, frag,
+ 0,
+ skb_frag_size(frag),
+ DMA_TO_DEVICE);
+ data->txring[tx].len = skb_frag_size(frag);
}
if (i == frags - 1)
@@ -1554,7 +1555,7 @@ static const struct net_device_ops tsi108_netdev_ops = {
.ndo_open = tsi108_open,
.ndo_stop = tsi108_close,
.ndo_start_xmit = tsi108_send_packet,
- .ndo_set_multicast_list = tsi108_set_rx_mode,
+ .ndo_set_rx_mode = tsi108_set_rx_mode,
.ndo_get_stats = tsi108_get_stats,
.ndo_do_ioctl = tsi108_do_ioctl,
.ndo_set_mac_address = tsi108_set_mac,
diff --git a/drivers/net/tsi108_eth.h b/drivers/net/ethernet/tundra/tsi108_eth.h
index 5fee7d78dc6d..5fee7d78dc6d 100644
--- a/drivers/net/tsi108_eth.h
+++ b/drivers/net/ethernet/tundra/tsi108_eth.h
diff --git a/drivers/net/ethernet/via/Kconfig b/drivers/net/ethernet/via/Kconfig
new file mode 100644
index 000000000000..68a9ba66feba
--- /dev/null
+++ b/drivers/net/ethernet/via/Kconfig
@@ -0,0 +1,59 @@
+#
+# VIA device configuration
+#
+
+config NET_VENDOR_VIA
+ bool "VIA devices"
+ default y
+ depends on PCI
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about VIA devices. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_VIA
+
+config VIA_RHINE
+ tristate "VIA Rhine support"
+ depends on PCI
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A),
+ Rhine-II (VT6102), or Rhine-III (VT6105)), say Y here. Rhine-type
+ Ethernet functions can also be found integrated on South Bridges
+ (e.g. VT8235).
+
+ To compile this driver as a module, choose M here. The module
+ will be called via-rhine.
+
+config VIA_RHINE_MMIO
+ bool "Use MMIO instead of PIO"
+ depends on VIA_RHINE
+ ---help---
+ This instructs the driver to use PCI shared memory (MMIO) instead of
+ programmed I/O ports (PIO). Enabling this gives an improvement in
+ processing time in parts of the driver.
+
+ If unsure, say Y.
+
+config VIA_VELOCITY
+ tristate "VIA Velocity support"
+ depends on PCI
+ select CRC32
+ select CRC_CCITT
+ select NET_CORE
+ select MII
+ ---help---
+ If you have a VIA "Velocity" based network card say Y here.
+
+ To compile this driver as a module, choose M here. The module
+ will be called via-velocity.
+
+endif # NET_VENDOR_VIA
diff --git a/drivers/net/ethernet/via/Makefile b/drivers/net/ethernet/via/Makefile
new file mode 100644
index 000000000000..46c5d4a3d8f1
--- /dev/null
+++ b/drivers/net/ethernet/via/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the VIA device drivers.
+#
+
+obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
diff --git a/drivers/net/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 7f23ab913fd9..f34dd99fe579 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -697,7 +697,7 @@ static const struct net_device_ops rhine_netdev_ops = {
.ndo_stop = rhine_close,
.ndo_start_xmit = rhine_start_tx,
.ndo_get_stats = rhine_get_stats,
- .ndo_set_multicast_list = rhine_set_rx_mode,
+ .ndo_set_rx_mode = rhine_set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index 7c5336c5c37f..4535d7cc848e 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -42,7 +42,6 @@
*
*/
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/bitops.h>
@@ -112,7 +111,6 @@ static void mac_get_cam_mask(struct mac_regs __iomem *regs, u8 *mask)
BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
}
-
/**
* mac_set_cam_mask - Set a CAM mask
* @regs: register block for this velocity
@@ -696,7 +694,6 @@ static int velocity_mii_read(struct mac_regs __iomem *regs, u8 index, u16 *data)
return 0;
}
-
/**
* mii_check_media_mode - check media state
* @regs: velocity registers
@@ -862,8 +859,6 @@ static u32 check_connection_type(struct mac_regs __iomem *regs)
return status;
}
-
-
/**
* velocity_set_media_mode - set media mode
* @mii_status: old MII link state
@@ -1258,6 +1253,7 @@ static void setup_queue_timers(struct velocity_info *vptr)
writeb(rxqueue_timer, &vptr->mac_regs->RQETMR);
}
}
+
/**
* setup_adaptive_interrupts - Setup interrupt suppression
*
@@ -1597,8 +1593,6 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
vptr->rx.info = NULL;
}
-
-
/**
* velocity_init_rd_ring - set up receive ring
* @vptr: velocity to configure
@@ -1672,7 +1666,6 @@ static void velocity_free_dma_rings(struct velocity_info *vptr)
pci_free_consistent(vptr->pdev, size, vptr->rx.ring, vptr->rx.pool_dma);
}
-
static int velocity_init_rings(struct velocity_info *vptr, int mtu)
{
int ret;
@@ -1735,7 +1728,6 @@ static void velocity_free_tx_buf(struct velocity_info *vptr,
tdinfo->skb = NULL;
}
-
/*
* FIXME: could we merge this with velocity_free_tx_buf ?
*/
@@ -1783,7 +1775,6 @@ static void velocity_free_td_ring(struct velocity_info *vptr)
}
}
-
static void velocity_free_rings(struct velocity_info *vptr)
{
velocity_free_td_ring(vptr);
@@ -2021,7 +2012,6 @@ static inline void velocity_iph_realign(struct velocity_info *vptr,
}
}
-
/**
* velocity_receive_frame - received packet processor
* @vptr: velocity we are handling
@@ -2088,11 +2078,11 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
netif_rx(skb);
stats->rx_bytes += pkt_len;
+ stats->rx_packets++;
return 0;
}
-
/**
* velocity_rx_srv - service RX interrupt
* @vptr: velocity
@@ -2400,7 +2390,6 @@ static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd
return 0;
}
-
/**
* velocity_ioctl - ioctl entry point
* @dev: network device
@@ -2565,15 +2554,16 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
/* Handle fragments */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- tdinfo->skb_dma[i + 1] = pci_map_page(vptr->pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
+ tdinfo->skb_dma[i + 1] = skb_frag_dma_map(&vptr->pdev->dev,
+ frag, 0,
+ skb_frag_size(frag),
+ DMA_TO_DEVICE);
td_ptr->td_buf[i + 1].pa_low = cpu_to_le32(tdinfo->skb_dma[i + 1]);
td_ptr->td_buf[i + 1].pa_high = 0;
- td_ptr->td_buf[i + 1].size = cpu_to_le16(frag->size);
+ td_ptr->td_buf[i + 1].size = cpu_to_le16(skb_frag_size(frag));
}
tdinfo->nskb_dma = i + 1;
@@ -2615,15 +2605,14 @@ out:
return NETDEV_TX_OK;
}
-
static const struct net_device_ops velocity_netdev_ops = {
.ndo_open = velocity_open,
.ndo_stop = velocity_close,
.ndo_start_xmit = velocity_xmit,
.ndo_get_stats = velocity_get_stats,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_set_multicast_list = velocity_set_multi,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_rx_mode = velocity_set_multi,
.ndo_change_mtu = velocity_change_mtu,
.ndo_do_ioctl = velocity_ioctl,
.ndo_vlan_rx_add_vid = velocity_vlan_rx_add_vid,
@@ -2713,7 +2702,6 @@ static u32 velocity_get_link(struct net_device *dev)
return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 1 : 0;
}
-
/**
* velocity_found1 - set up discovered velocity card
* @pdev: PCI device
@@ -2860,7 +2848,6 @@ err_free_dev:
goto out;
}
-
#ifdef CONFIG_PM
/**
* wol_calc_crc - WOL CRC
@@ -3031,7 +3018,7 @@ static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
spin_lock_irqsave(&vptr->lock, flags);
pci_save_state(pdev);
-#ifdef ETHTOOL_GWOL
+
if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
velocity_get_ip(vptr);
velocity_save_context(vptr, &vptr->context);
@@ -3045,9 +3032,7 @@ static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
}
-#else
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
-#endif
+
spin_unlock_irqrestore(&vptr->lock, flags);
return 0;
}
@@ -3128,13 +3113,13 @@ static int velocity_resume(struct pci_dev *pdev)
* uses this to handle all our card discover and plugging
*/
static struct pci_driver velocity_driver = {
- .name = VELOCITY_NAME,
- .id_table = velocity_id_table,
- .probe = velocity_found1,
- .remove = __devexit_p(velocity_remove1),
+ .name = VELOCITY_NAME,
+ .id_table = velocity_id_table,
+ .probe = velocity_found1,
+ .remove = __devexit_p(velocity_remove1),
#ifdef CONFIG_PM
- .suspend = velocity_suspend,
- .resume = velocity_resume,
+ .suspend = velocity_suspend,
+ .resume = velocity_resume,
#endif
};
@@ -3444,26 +3429,99 @@ static int velocity_set_coalesce(struct net_device *dev,
return 0;
}
+static const char velocity_gstrings[][ETH_GSTRING_LEN] = {
+ "rx_all",
+ "rx_ok",
+ "tx_ok",
+ "rx_error",
+ "rx_runt_ok",
+ "rx_runt_err",
+ "rx_64",
+ "tx_64",
+ "rx_65_to_127",
+ "tx_65_to_127",
+ "rx_128_to_255",
+ "tx_128_to_255",
+ "rx_256_to_511",
+ "tx_256_to_511",
+ "rx_512_to_1023",
+ "tx_512_to_1023",
+ "rx_1024_to_1518",
+ "tx_1024_to_1518",
+ "tx_ether_collisions",
+ "rx_crc_errors",
+ "rx_jumbo",
+ "tx_jumbo",
+ "rx_mac_control_frames",
+ "tx_mac_control_frames",
+ "rx_frame_alignement_errors",
+ "rx_long_ok",
+ "rx_long_err",
+ "tx_sqe_errors",
+ "rx_no_buf",
+ "rx_symbol_errors",
+ "in_range_length_errors",
+ "late_collisions"
+};
+
+static void velocity_get_strings(struct net_device *dev, u32 sset, u8 *data)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ memcpy(data, *velocity_gstrings, sizeof(velocity_gstrings));
+ break;
+ }
+}
+
+static int velocity_get_sset_count(struct net_device *dev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return ARRAY_SIZE(velocity_gstrings);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void velocity_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ if (netif_running(dev)) {
+ struct velocity_info *vptr = netdev_priv(dev);
+ u32 *p = vptr->mib_counter;
+ int i;
+
+ spin_lock_irq(&vptr->lock);
+ velocity_update_hw_mibs(vptr);
+ spin_unlock_irq(&vptr->lock);
+
+ for (i = 0; i < ARRAY_SIZE(velocity_gstrings); i++)
+ *data++ = *p++;
+ }
+}
+
static const struct ethtool_ops velocity_ethtool_ops = {
- .get_settings = velocity_get_settings,
- .set_settings = velocity_set_settings,
- .get_drvinfo = velocity_get_drvinfo,
- .get_wol = velocity_ethtool_get_wol,
- .set_wol = velocity_ethtool_set_wol,
- .get_msglevel = velocity_get_msglevel,
- .set_msglevel = velocity_set_msglevel,
- .get_link = velocity_get_link,
- .get_coalesce = velocity_get_coalesce,
- .set_coalesce = velocity_set_coalesce,
- .begin = velocity_ethtool_up,
- .complete = velocity_ethtool_down
+ .get_settings = velocity_get_settings,
+ .set_settings = velocity_set_settings,
+ .get_drvinfo = velocity_get_drvinfo,
+ .get_wol = velocity_ethtool_get_wol,
+ .set_wol = velocity_ethtool_set_wol,
+ .get_msglevel = velocity_get_msglevel,
+ .set_msglevel = velocity_set_msglevel,
+ .get_link = velocity_get_link,
+ .get_strings = velocity_get_strings,
+ .get_sset_count = velocity_get_sset_count,
+ .get_ethtool_stats = velocity_get_ethtool_stats,
+ .get_coalesce = velocity_get_coalesce,
+ .set_coalesce = velocity_set_coalesce,
+ .begin = velocity_ethtool_up,
+ .complete = velocity_ethtool_down
};
-#ifdef CONFIG_PM
-#ifdef CONFIG_INET
+#if defined(CONFIG_PM) && defined(CONFIG_INET)
static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
{
- struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
+ struct in_ifaddr *ifa = ptr;
struct net_device *dev = ifa->ifa_dev->dev;
if (dev_net(dev) == &init_net &&
@@ -3472,12 +3530,9 @@ static int velocity_netdev_event(struct notifier_block *nb, unsigned long notifi
return NOTIFY_DONE;
}
-#endif /* CONFIG_INET */
-#endif /* CONFIG_PM */
-#if defined(CONFIG_PM) && defined(CONFIG_INET)
static struct notifier_block velocity_inetaddr_notifier = {
- .notifier_call = velocity_netdev_event,
+ .notifier_call = velocity_netdev_event,
};
static void velocity_register_notifier(void)
diff --git a/drivers/net/via-velocity.h b/drivers/net/ethernet/via/via-velocity.h
index 4cb9f13485e9..4cb9f13485e9 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/ethernet/via/via-velocity.h
diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig
new file mode 100644
index 000000000000..d5a826063a82
--- /dev/null
+++ b/drivers/net/ethernet/xilinx/Kconfig
@@ -0,0 +1,36 @@
+#
+# Xilink device configuration
+#
+
+config NET_VENDOR_XILINX
+ bool "Xilinx devices"
+ default y
+ depends on PPC || PPC32 || MICROBLAZE
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Xilinx devices. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_XILINX
+
+config XILINX_EMACLITE
+ tristate "Xilinx 10/100 Ethernet Lite support"
+ depends on (PPC32 || MICROBLAZE)
+ select PHYLIB
+ ---help---
+ This driver supports the 10/100 Ethernet Lite from Xilinx.
+
+config XILINX_LL_TEMAC
+ tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
+ depends on (PPC || MICROBLAZE)
+ select PHYLIB
+ ---help---
+ This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
+ core used in Xilinx Spartan and Virtex FPGAs
+
+endif # NET_VENDOR_XILINX
diff --git a/drivers/net/ethernet/xilinx/Makefile b/drivers/net/ethernet/xilinx/Makefile
new file mode 100644
index 000000000000..5feac734ea45
--- /dev/null
+++ b/drivers/net/ethernet/xilinx/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Xilink network device drivers.
+#
+
+ll_temac-objs := ll_temac_main.o ll_temac_mdio.o
+obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o
+obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
diff --git a/drivers/net/ll_temac.h b/drivers/net/ethernet/xilinx/ll_temac.h
index 522abe2ff25a..522abe2ff25a 100644
--- a/drivers/net/ll_temac.h
+++ b/drivers/net/ethernet/xilinx/ll_temac.h
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 728fe414147a..4d1658e78dee 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -715,10 +715,9 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
cur_p->phys = dma_map_single(ndev->dev.parent,
- (void *)page_address(frag->page) +
- frag->page_offset,
- frag->size, DMA_TO_DEVICE);
- cur_p->len = frag->size;
+ skb_frag_address(frag),
+ frag_size(frag), DMA_TO_DEVICE);
+ cur_p->len = frag_size(frag);
cur_p->app0 = 0;
frag++;
}
@@ -922,7 +921,6 @@ static const struct net_device_ops temac_netdev_ops = {
.ndo_start_xmit = temac_start_xmit,
.ndo_set_mac_address = netdev_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
- //.ndo_set_multicast_list = temac_set_multicast_list,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = temac_poll_controller,
#endif
@@ -957,6 +955,32 @@ static const struct attribute_group temac_attr_group = {
.attrs = temac_device_attrs,
};
+/* ethtool support */
+static int temac_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+ struct temac_local *lp = netdev_priv(ndev);
+ return phy_ethtool_gset(lp->phy_dev, cmd);
+}
+
+static int temac_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+ struct temac_local *lp = netdev_priv(ndev);
+ return phy_ethtool_sset(lp->phy_dev, cmd);
+}
+
+static int temac_nway_reset(struct net_device *ndev)
+{
+ struct temac_local *lp = netdev_priv(ndev);
+ return phy_start_aneg(lp->phy_dev);
+}
+
+static const struct ethtool_ops temac_ethtool_ops = {
+ .get_settings = temac_get_settings,
+ .set_settings = temac_set_settings,
+ .nway_reset = temac_nway_reset,
+ .get_link = ethtool_op_get_link,
+};
+
static int __devinit temac_of_probe(struct platform_device *op)
{
struct device_node *np;
@@ -978,6 +1002,7 @@ static int __devinit temac_of_probe(struct platform_device *op)
ndev->flags &= ~IFF_MULTICAST; /* clear multicast */
ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
ndev->netdev_ops = &temac_netdev_ops;
+ ndev->ethtool_ops = &temac_ethtool_ops;
#if 0
ndev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4. */
ndev->features |= NETIF_F_HW_CSUM; /* Can checksum all the packets. */
diff --git a/drivers/net/ll_temac_mdio.c b/drivers/net/ethernet/xilinx/ll_temac_mdio.c
index 8cf9d4f56bb2..8cf9d4f56bb2 100644
--- a/drivers/net/ll_temac_mdio.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_mdio.c
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 8018d7d045b0..8018d7d045b0 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
diff --git a/drivers/net/ethernet/xircom/Kconfig b/drivers/net/ethernet/xircom/Kconfig
new file mode 100644
index 000000000000..69f56a6de821
--- /dev/null
+++ b/drivers/net/ethernet/xircom/Kconfig
@@ -0,0 +1,31 @@
+#
+# Xircom network device configuration
+#
+
+config NET_VENDOR_XIRCOM
+ bool "Xircom devices"
+ default y
+ depends on PCMCIA
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Xircom cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_XIRCOM
+
+config PCMCIA_XIRC2PS
+ tristate "Xircom 16-bit PCMCIA support"
+ depends on PCMCIA
+ ---help---
+ Say Y here if you intend to attach a Xircom 16-bit PCMCIA (PC-card)
+ Ethernet or Fast Ethernet card to your computer.
+
+ To compile this driver as a module, choose M here: the module will be
+ called xirc2ps_cs. If unsure, say N.
+
+endif # NET_VENDOR_XIRCOM
diff --git a/drivers/net/ethernet/xircom/Makefile b/drivers/net/ethernet/xircom/Makefile
new file mode 100644
index 000000000000..3b7aebd8b849
--- /dev/null
+++ b/drivers/net/ethernet/xircom/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Xircom network device drivers.
+#
+
+obj-$(CONFIG_PCMCIA_XIRC2PS) += xirc2ps_cs.o
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c
index e33b190d716f..bbe8b7dbf3f3 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c
@@ -467,7 +467,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_tx_timeout = xirc_tx_timeout,
.ndo_set_config = do_config,
.ndo_do_ioctl = do_ioctl,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/ethernet/xscale/Kconfig b/drivers/net/ethernet/xscale/Kconfig
new file mode 100644
index 000000000000..cf67352cea14
--- /dev/null
+++ b/drivers/net/ethernet/xscale/Kconfig
@@ -0,0 +1,32 @@
+#
+# Intel XScale IXP device configuration
+#
+
+config NET_VENDOR_XSCALE
+ bool "Intel XScale IXP devices"
+ default y
+ depends on NET_VENDOR_INTEL && ((ARM && ARCH_IXP4XX && \
+ IXP4XX_NPE && IXP4XX_QMGR) || ARCH_ENP2611)
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question does not directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about XSacle IXP devices. If you say Y, you will be
+ asked for your specific card in the following questions.
+
+if NET_VENDOR_XSCALE
+
+config IXP4XX_ETH
+ tristate "Intel IXP4xx Ethernet support"
+ depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR
+ select PHYLIB
+ ---help---
+ Say Y here if you want to use built-in Ethernet ports
+ on IXP4xx processor.
+
+source "drivers/net/ethernet/xscale/ixp2000/Kconfig"
+
+endif # NET_VENDOR_XSCALE
diff --git a/drivers/net/ethernet/xscale/Makefile b/drivers/net/ethernet/xscale/Makefile
new file mode 100644
index 000000000000..b195b9d7fe81
--- /dev/null
+++ b/drivers/net/ethernet/xscale/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Intel XScale IXP device drivers.
+#
+
+obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
+obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o
diff --git a/drivers/net/ixp2000/Kconfig b/drivers/net/ethernet/xscale/ixp2000/Kconfig
index 2fec2415651f..58dbc5b876bc 100644
--- a/drivers/net/ixp2000/Kconfig
+++ b/drivers/net/ethernet/xscale/ixp2000/Kconfig
@@ -1,6 +1,6 @@
config ENP2611_MSF_NET
tristate "Radisys ENP2611 MSF network interface support"
depends on ARCH_ENP2611
- help
+ ---help---
This is a driver for the MSF network interface unit in
the IXP2400 on the Radisys ENP2611 platform.
diff --git a/drivers/net/ixp2000/Makefile b/drivers/net/ethernet/xscale/ixp2000/Makefile
index fd38351ceaa7..fd38351ceaa7 100644
--- a/drivers/net/ixp2000/Makefile
+++ b/drivers/net/ethernet/xscale/ixp2000/Makefile
diff --git a/drivers/net/ixp2000/caleb.c b/drivers/net/ethernet/xscale/ixp2000/caleb.c
index 7dea5b95012c..7dea5b95012c 100644
--- a/drivers/net/ixp2000/caleb.c
+++ b/drivers/net/ethernet/xscale/ixp2000/caleb.c
diff --git a/drivers/net/ixp2000/caleb.h b/drivers/net/ethernet/xscale/ixp2000/caleb.h
index e93a1ef5b8a3..e93a1ef5b8a3 100644
--- a/drivers/net/ixp2000/caleb.h
+++ b/drivers/net/ethernet/xscale/ixp2000/caleb.h
diff --git a/drivers/net/ixp2000/enp2611.c b/drivers/net/ethernet/xscale/ixp2000/enp2611.c
index 34a6cfd17930..34a6cfd17930 100644
--- a/drivers/net/ixp2000/enp2611.c
+++ b/drivers/net/ethernet/xscale/ixp2000/enp2611.c
diff --git a/drivers/net/ixp2000/ixp2400-msf.c b/drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.c
index f5ffd7e05d26..f5ffd7e05d26 100644
--- a/drivers/net/ixp2000/ixp2400-msf.c
+++ b/drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.c
diff --git a/drivers/net/ixp2000/ixp2400-msf.h b/drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.h
index 3ac1af2771da..3ac1af2771da 100644
--- a/drivers/net/ixp2000/ixp2400-msf.h
+++ b/drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.h
diff --git a/drivers/net/ixp2000/ixp2400_rx.uc b/drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.uc
index 42a73e357afa..42a73e357afa 100644
--- a/drivers/net/ixp2000/ixp2400_rx.uc
+++ b/drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.uc
diff --git a/drivers/net/ixp2000/ixp2400_rx.ucode b/drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.ucode
index e8aee2f81aad..e8aee2f81aad 100644
--- a/drivers/net/ixp2000/ixp2400_rx.ucode
+++ b/drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.ucode
diff --git a/drivers/net/ixp2000/ixp2400_tx.uc b/drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.uc
index d090d1884fb7..d090d1884fb7 100644
--- a/drivers/net/ixp2000/ixp2400_tx.uc
+++ b/drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.uc
diff --git a/drivers/net/ixp2000/ixp2400_tx.ucode b/drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.ucode
index a433e24b0a51..a433e24b0a51 100644
--- a/drivers/net/ixp2000/ixp2400_tx.ucode
+++ b/drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.ucode
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ethernet/xscale/ixp2000/ixpdev.c
index e122493ab70e..e122493ab70e 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ethernet/xscale/ixp2000/ixpdev.c
diff --git a/drivers/net/ixp2000/ixpdev.h b/drivers/net/ethernet/xscale/ixp2000/ixpdev.h
index 391ece623243..391ece623243 100644
--- a/drivers/net/ixp2000/ixpdev.h
+++ b/drivers/net/ethernet/xscale/ixp2000/ixpdev.h
diff --git a/drivers/net/ixp2000/ixpdev_priv.h b/drivers/net/ethernet/xscale/ixp2000/ixpdev_priv.h
index 86aa08ea0c33..86aa08ea0c33 100644
--- a/drivers/net/ixp2000/ixpdev_priv.h
+++ b/drivers/net/ethernet/xscale/ixp2000/ixpdev_priv.h
diff --git a/drivers/net/ixp2000/pm3386.c b/drivers/net/ethernet/xscale/ixp2000/pm3386.c
index e08d3f9863b8..e08d3f9863b8 100644
--- a/drivers/net/ixp2000/pm3386.c
+++ b/drivers/net/ethernet/xscale/ixp2000/pm3386.c
diff --git a/drivers/net/ixp2000/pm3386.h b/drivers/net/ethernet/xscale/ixp2000/pm3386.h
index cc4183dca911..cc4183dca911 100644
--- a/drivers/net/ixp2000/pm3386.h
+++ b/drivers/net/ethernet/xscale/ixp2000/pm3386.h
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index de51e8453c13..ec96d910e9a3 100644
--- a/drivers/net/arm/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -1339,7 +1339,7 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
.ndo_open = eth_open,
.ndo_stop = eth_close,
.ndo_start_xmit = eth_xmit,
- .ndo_set_multicast_list = eth_set_mcast_list,
+ .ndo_set_rx_mode = eth_set_mcast_list,
.ndo_do_ioctl = eth_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/fddi/Kconfig b/drivers/net/fddi/Kconfig
new file mode 100644
index 000000000000..3a424c864f4d
--- /dev/null
+++ b/drivers/net/fddi/Kconfig
@@ -0,0 +1,77 @@
+#
+# FDDI network device configuration
+#
+
+config FDDI
+ tristate "FDDI driver support"
+ depends on PCI || EISA || TC
+ ---help---
+ Fiber Distributed Data Interface is a high speed local area network
+ design; essentially a replacement for high speed Ethernet. FDDI can
+ run over copper or fiber. If you are connected to such a network and
+ want a driver for the FDDI card in your computer, say Y here (and
+ then also Y to the driver for your FDDI card, below). Most people
+ will say N.
+
+if FDDI
+
+config DEFXX
+ tristate "Digital DEFTA/DEFEA/DEFPA adapter support"
+ depends on FDDI && (PCI || EISA || TC)
+ ---help---
+ This is support for the DIGITAL series of TURBOchannel (DEFTA),
+ EISA (DEFEA) and PCI (DEFPA) controllers which can connect you
+ to a local FDDI network.
+
+ To compile this driver as a module, choose M here: the module
+ will be called defxx. If unsure, say N.
+
+config DEFXX_MMIO
+ bool
+ prompt "Use MMIO instead of PIO" if PCI || EISA
+ depends on DEFXX
+ default n if PCI || EISA
+ default y
+ ---help---
+ This instructs the driver to use EISA or PCI memory-mapped I/O
+ (MMIO) as appropriate instead of programmed I/O ports (PIO).
+ Enabling this gives an improvement in processing time in parts
+ of the driver, but it may cause problems with EISA (DEFEA)
+ adapters. TURBOchannel does not have the concept of I/O ports,
+ so MMIO is always used for these (DEFTA) adapters.
+
+ If unsure, say N.
+
+config SKFP
+ tristate "SysKonnect FDDI PCI support"
+ depends on FDDI && PCI
+ select BITREVERSE
+ ---help---
+ Say Y here if you have a SysKonnect FDDI PCI adapter.
+ The following adapters are supported by this driver:
+ - SK-5521 (SK-NET FDDI-UP)
+ - SK-5522 (SK-NET FDDI-UP DAS)
+ - SK-5541 (SK-NET FDDI-FP)
+ - SK-5543 (SK-NET FDDI-LP)
+ - SK-5544 (SK-NET FDDI-LP DAS)
+ - SK-5821 (SK-NET FDDI-UP64)
+ - SK-5822 (SK-NET FDDI-UP64 DAS)
+ - SK-5841 (SK-NET FDDI-FP64)
+ - SK-5843 (SK-NET FDDI-LP64)
+ - SK-5844 (SK-NET FDDI-LP64 DAS)
+ - Netelligent 100 FDDI DAS Fibre SC
+ - Netelligent 100 FDDI SAS Fibre SC
+ - Netelligent 100 FDDI DAS UTP
+ - Netelligent 100 FDDI SAS UTP
+ - Netelligent 100 FDDI SAS Fibre MIC
+
+ Read <file:Documentation/networking/skfp.txt> for information about
+ the driver.
+
+ Questions concerning this driver can be addressed to:
+ <linux@syskonnect.de>
+
+ To compile this driver as a module, choose M here: the module
+ will be called skfp. This is recommended.
+
+endif # FDDI
diff --git a/drivers/net/fddi/Makefile b/drivers/net/fddi/Makefile
new file mode 100644
index 000000000000..36da19c9a8aa
--- /dev/null
+++ b/drivers/net/fddi/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Linux FDDI network device drivers.
+#
+
+obj-$(CONFIG_DEFXX) += defxx.o
+obj-$(CONFIG_SKFP) += skfp/
diff --git a/drivers/net/defxx.c b/drivers/net/fddi/defxx.c
index 417e14385623..4ad80f771099 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/fddi/defxx.c
@@ -483,7 +483,7 @@ static const struct net_device_ops dfx_netdev_ops = {
.ndo_stop = dfx_close,
.ndo_start_xmit = dfx_xmt_queue_pkt,
.ndo_get_stats = dfx_ctl_get_stats,
- .ndo_set_multicast_list = dfx_ctl_set_multicast_list,
+ .ndo_set_rx_mode = dfx_ctl_set_multicast_list,
.ndo_set_mac_address = dfx_ctl_set_mac_address,
};
diff --git a/drivers/net/defxx.h b/drivers/net/fddi/defxx.h
index 19a6f64df198..19a6f64df198 100644
--- a/drivers/net/defxx.h
+++ b/drivers/net/fddi/defxx.h
diff --git a/drivers/net/skfp/Makefile b/drivers/net/fddi/skfp/Makefile
index b0be0234abf6..b0be0234abf6 100644
--- a/drivers/net/skfp/Makefile
+++ b/drivers/net/fddi/skfp/Makefile
diff --git a/drivers/net/skfp/cfm.c b/drivers/net/fddi/skfp/cfm.c
index e395ace3120b..e395ace3120b 100644
--- a/drivers/net/skfp/cfm.c
+++ b/drivers/net/fddi/skfp/cfm.c
diff --git a/drivers/net/skfp/drvfbi.c b/drivers/net/fddi/skfp/drvfbi.c
index 07da97c303d6..07da97c303d6 100644
--- a/drivers/net/skfp/drvfbi.c
+++ b/drivers/net/fddi/skfp/drvfbi.c
diff --git a/drivers/net/skfp/ecm.c b/drivers/net/fddi/skfp/ecm.c
index 47d922cb3c08..47d922cb3c08 100644
--- a/drivers/net/skfp/ecm.c
+++ b/drivers/net/fddi/skfp/ecm.c
diff --git a/drivers/net/skfp/ess.c b/drivers/net/fddi/skfp/ess.c
index 2fc5987b41dc..2fc5987b41dc 100644
--- a/drivers/net/skfp/ess.c
+++ b/drivers/net/fddi/skfp/ess.c
diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/fddi/skfp/fplustm.c
index a20ed1a98099..a20ed1a98099 100644
--- a/drivers/net/skfp/fplustm.c
+++ b/drivers/net/fddi/skfp/fplustm.c
diff --git a/drivers/net/skfp/h/cmtdef.h b/drivers/net/fddi/skfp/h/cmtdef.h
index 5a6c6122ccb0..f5bc90ff2a2a 100644
--- a/drivers/net/skfp/h/cmtdef.h
+++ b/drivers/net/fddi/skfp/h/cmtdef.h
@@ -477,8 +477,8 @@ struct s_plc {
/*
* function prototypes
*/
-#include "h/mbuf.h" /* Type definitions for MBUFs */
-#include "h/smtstate.h" /* struct smt_state */
+#include "mbuf.h" /* Type definitions for MBUFs */
+#include "smtstate.h" /* struct smt_state */
void hwt_restart(struct s_smc *smc); /* hwt.c */
SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
diff --git a/drivers/net/skfp/h/fddi.h b/drivers/net/fddi/skfp/h/fddi.h
index c9a28a8a383b..c9a28a8a383b 100644
--- a/drivers/net/skfp/h/fddi.h
+++ b/drivers/net/fddi/skfp/h/fddi.h
diff --git a/drivers/net/skfp/h/fddimib.h b/drivers/net/fddi/skfp/h/fddimib.h
index d1acdc773950..d1acdc773950 100644
--- a/drivers/net/skfp/h/fddimib.h
+++ b/drivers/net/fddi/skfp/h/fddimib.h
diff --git a/drivers/net/skfp/h/fplustm.h b/drivers/net/fddi/skfp/h/fplustm.h
index d43191ed938b..d43191ed938b 100644
--- a/drivers/net/skfp/h/fplustm.h
+++ b/drivers/net/fddi/skfp/h/fplustm.h
diff --git a/drivers/net/skfp/h/hwmtm.h b/drivers/net/fddi/skfp/h/hwmtm.h
index e1a7e5f683dc..5924d4219e9e 100644
--- a/drivers/net/skfp/h/hwmtm.h
+++ b/drivers/net/fddi/skfp/h/hwmtm.h
@@ -15,7 +15,7 @@
#ifndef _HWM_
#define _HWM_
-#include "h/mbuf.h"
+#include "mbuf.h"
/*
* MACRO for DMA synchronization:
diff --git a/drivers/net/skfp/h/mbuf.h b/drivers/net/fddi/skfp/h/mbuf.h
index f2aadcda9e7f..f2aadcda9e7f 100644
--- a/drivers/net/skfp/h/mbuf.h
+++ b/drivers/net/fddi/skfp/h/mbuf.h
diff --git a/drivers/net/skfp/h/osdef1st.h b/drivers/net/fddi/skfp/h/osdef1st.h
index 763ca18cbea8..763ca18cbea8 100644
--- a/drivers/net/skfp/h/osdef1st.h
+++ b/drivers/net/fddi/skfp/h/osdef1st.h
diff --git a/drivers/net/skfp/h/sba.h b/drivers/net/fddi/skfp/h/sba.h
index 638cf0283bc4..35ddb44a1120 100644
--- a/drivers/net/skfp/h/sba.h
+++ b/drivers/net/fddi/skfp/h/sba.h
@@ -19,8 +19,8 @@
#ifndef _SBA_
#define _SBA_
-#include "h/mbuf.h"
-#include "h/sba_def.h"
+#include "mbuf.h"
+#include "sba_def.h"
#ifdef SBA
diff --git a/drivers/net/skfp/h/sba_def.h b/drivers/net/fddi/skfp/h/sba_def.h
index 0459a095d0cd..0459a095d0cd 100644
--- a/drivers/net/skfp/h/sba_def.h
+++ b/drivers/net/fddi/skfp/h/sba_def.h
diff --git a/drivers/net/skfp/h/skfbi.h b/drivers/net/fddi/skfp/h/skfbi.h
index c1ba26c06d73..c1ba26c06d73 100644
--- a/drivers/net/skfp/h/skfbi.h
+++ b/drivers/net/fddi/skfp/h/skfbi.h
diff --git a/drivers/net/skfp/h/skfbiinc.h b/drivers/net/fddi/skfp/h/skfbiinc.h
index ac2d7192f1ca..ce72557c354c 100644
--- a/drivers/net/skfp/h/skfbiinc.h
+++ b/drivers/net/fddi/skfp/h/skfbiinc.h
@@ -15,7 +15,7 @@
#ifndef _SKFBIINC_
#define _SKFBIINC_
-#include "h/supern_2.h"
+#include "supern_2.h"
/*
* special defines for use into .asm files
diff --git a/drivers/net/skfp/h/smc.h b/drivers/net/fddi/skfp/h/smc.h
index c774a95902f5..3ca308b28214 100644
--- a/drivers/net/skfp/h/smc.h
+++ b/drivers/net/fddi/skfp/h/smc.h
@@ -38,18 +38,18 @@
* fddi.h
*/
#ifdef OSDEF
-#include "h/osdef1st.h"
+#include "osdef1st.h"
#endif /* OSDEF */
#ifdef OEM_CONCEPT
#include "oemdef.h"
#endif /* OEM_CONCEPT */
-#include "h/smt.h"
-#include "h/cmtdef.h"
-#include "h/fddimib.h"
-#include "h/targethw.h" /* all target hw dependencies */
-#include "h/targetos.h" /* all target os dependencies */
+#include "smt.h"
+#include "cmtdef.h"
+#include "fddimib.h"
+#include "targethw.h" /* all target hw dependencies */
+#include "targetos.h" /* all target os dependencies */
#ifdef ESS
-#include "h/sba.h"
+#include "sba.h"
#endif
/*
diff --git a/drivers/net/skfp/h/smt.h b/drivers/net/fddi/skfp/h/smt.h
index 2030f9cbb24b..2030f9cbb24b 100644
--- a/drivers/net/skfp/h/smt.h
+++ b/drivers/net/fddi/skfp/h/smt.h
diff --git a/drivers/net/skfp/h/smt_p.h b/drivers/net/fddi/skfp/h/smt_p.h
index 99f9be9552bb..99f9be9552bb 100644
--- a/drivers/net/skfp/h/smt_p.h
+++ b/drivers/net/fddi/skfp/h/smt_p.h
diff --git a/drivers/net/skfp/h/smtstate.h b/drivers/net/fddi/skfp/h/smtstate.h
index 62fe695077a9..62fe695077a9 100644
--- a/drivers/net/skfp/h/smtstate.h
+++ b/drivers/net/fddi/skfp/h/smtstate.h
diff --git a/drivers/net/skfp/h/supern_2.h b/drivers/net/fddi/skfp/h/supern_2.h
index 0b73690280f6..0b73690280f6 100644
--- a/drivers/net/skfp/h/supern_2.h
+++ b/drivers/net/fddi/skfp/h/supern_2.h
diff --git a/drivers/net/skfp/h/targethw.h b/drivers/net/fddi/skfp/h/targethw.h
index 626dc7263591..842a690446f3 100644
--- a/drivers/net/skfp/h/targethw.h
+++ b/drivers/net/fddi/skfp/h/targethw.h
@@ -25,11 +25,11 @@
#define SK_ML_ID_2 0x30
#endif
-#include "h/skfbi.h"
+#include "skfbi.h"
#ifndef TAG_MODE
-#include "h/fplus.h"
+#include "fplus.h"
#else
-#include "h/fplustm.h"
+#include "fplustm.h"
#endif
#ifndef HW_PTR
diff --git a/drivers/net/skfp/h/targetos.h b/drivers/net/fddi/skfp/h/targetos.h
index 5d940e7b8ea0..53bacc107160 100644
--- a/drivers/net/skfp/h/targetos.h
+++ b/drivers/net/fddi/skfp/h/targetos.h
@@ -58,7 +58,7 @@
#define ADDR(a) (((a)>>7) ? (outp(smc->hw.iop+B0_RAP,(a)>>7), (smc->hw.iop+( ((a)&0x7F) | ((a)>>7 ? 0x80:0)) )) : (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
#endif
-#include "h/hwmtm.h"
+#include "hwmtm.h"
#define TRUE 1
#define FALSE 0
diff --git a/drivers/net/skfp/h/types.h b/drivers/net/fddi/skfp/h/types.h
index 5a3bf8378f9e..5a3bf8378f9e 100644
--- a/drivers/net/skfp/h/types.h
+++ b/drivers/net/fddi/skfp/h/types.h
diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/fddi/skfp/hwmtm.c
index e26398b5a7dc..e26398b5a7dc 100644
--- a/drivers/net/skfp/hwmtm.c
+++ b/drivers/net/fddi/skfp/hwmtm.c
diff --git a/drivers/net/skfp/hwt.c b/drivers/net/fddi/skfp/hwt.c
index c0798fd2ca69..c0798fd2ca69 100644
--- a/drivers/net/skfp/hwt.c
+++ b/drivers/net/fddi/skfp/hwt.c
diff --git a/drivers/net/skfp/pcmplc.c b/drivers/net/fddi/skfp/pcmplc.c
index 88d02d0a42c4..88d02d0a42c4 100644
--- a/drivers/net/skfp/pcmplc.c
+++ b/drivers/net/fddi/skfp/pcmplc.c
diff --git a/drivers/net/skfp/pmf.c b/drivers/net/fddi/skfp/pmf.c
index 9ac4665d7411..9ac4665d7411 100644
--- a/drivers/net/skfp/pmf.c
+++ b/drivers/net/fddi/skfp/pmf.c
diff --git a/drivers/net/skfp/queue.c b/drivers/net/fddi/skfp/queue.c
index c1a0df455a59..c1a0df455a59 100644
--- a/drivers/net/skfp/queue.c
+++ b/drivers/net/fddi/skfp/queue.c
diff --git a/drivers/net/skfp/rmt.c b/drivers/net/fddi/skfp/rmt.c
index ef8d5672d9e8..ef8d5672d9e8 100644
--- a/drivers/net/skfp/rmt.c
+++ b/drivers/net/fddi/skfp/rmt.c
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c
index 16c62659cdd9..3d9a4596a423 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/fddi/skfp/skfddi.c
@@ -167,7 +167,7 @@ static const struct net_device_ops skfp_netdev_ops = {
.ndo_start_xmit = skfp_send_pkt,
.ndo_get_stats = skfp_ctl_get_stats,
.ndo_change_mtu = fddi_change_mtu,
- .ndo_set_multicast_list = skfp_ctl_set_multicast_list,
+ .ndo_set_rx_mode = skfp_ctl_set_multicast_list,
.ndo_set_mac_address = skfp_ctl_set_mac_address,
.ndo_do_ioctl = skfp_ioctl,
};
diff --git a/drivers/net/skfp/smt.c b/drivers/net/fddi/skfp/smt.c
index 08d94329c12f..08d94329c12f 100644
--- a/drivers/net/skfp/smt.c
+++ b/drivers/net/fddi/skfp/smt.c
diff --git a/drivers/net/skfp/smtdef.c b/drivers/net/fddi/skfp/smtdef.c
index 1acab0b368e3..1acab0b368e3 100644
--- a/drivers/net/skfp/smtdef.c
+++ b/drivers/net/fddi/skfp/smtdef.c
diff --git a/drivers/net/skfp/smtinit.c b/drivers/net/fddi/skfp/smtinit.c
index e3a0c0bc2233..e3a0c0bc2233 100644
--- a/drivers/net/skfp/smtinit.c
+++ b/drivers/net/fddi/skfp/smtinit.c
diff --git a/drivers/net/skfp/smttimer.c b/drivers/net/fddi/skfp/smttimer.c
index 531795e98c30..531795e98c30 100644
--- a/drivers/net/skfp/smttimer.c
+++ b/drivers/net/fddi/skfp/smttimer.c
diff --git a/drivers/net/skfp/srf.c b/drivers/net/fddi/skfp/srf.c
index f6f7baf9f27a..f6f7baf9f27a 100644
--- a/drivers/net/skfp/srf.c
+++ b/drivers/net/fddi/skfp/srf.c
diff --git a/drivers/net/hippi/Kconfig b/drivers/net/hippi/Kconfig
new file mode 100644
index 000000000000..7393eb732ee6
--- /dev/null
+++ b/drivers/net/hippi/Kconfig
@@ -0,0 +1,39 @@
+#
+# HIPPI network device configuration
+#
+
+config HIPPI
+ bool "HIPPI driver support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && INET && PCI
+ ---help---
+ HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
+ 1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
+ can run over copper (25m) or fiber (300m on multi-mode or 10km on
+ single-mode). HIPPI networks are commonly used for clusters and to
+ connect to super computers. If you are connected to a HIPPI network
+ and have a HIPPI network card in your computer that you want to use
+ under Linux, say Y here (you must also remember to enable the driver
+ for your HIPPI card below). Most people will say N here.
+
+if HIPPI
+
+config ROADRUNNER
+ tristate "Essential RoadRunner HIPPI PCI adapter support (EXPERIMENTAL)"
+ depends on PCI
+ ---help---
+ Say Y here if this is your PCI HIPPI network card.
+
+ To compile this driver as a module, choose M here: the module
+ will be called rrunner. If unsure, say N.
+
+config ROADRUNNER_LARGE_RINGS
+ bool "Use large TX/RX rings (EXPERIMENTAL)"
+ depends on ROADRUNNER
+ ---help---
+ If you say Y here, the RoadRunner driver will preallocate up to 2 MB
+ of additional memory to allow for fastest operation, both for
+ transmitting and receiving. This memory cannot be used by any other
+ kernel code or by user space programs. Say Y here only if you have
+ the memory.
+
+endif /* HIPPI */
diff --git a/drivers/net/hippi/Makefile b/drivers/net/hippi/Makefile
new file mode 100644
index 000000000000..b95d629baee5
--- /dev/null
+++ b/drivers/net/hippi/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the HIPPI network device drivers.
+#
+
+obj-$(CONFIG_ROADRUNNER) += rrunner.o
diff --git a/drivers/net/rrunner.c b/drivers/net/hippi/rrunner.c
index e68c941926f1..e68c941926f1 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/hippi/rrunner.c
diff --git a/drivers/net/rrunner.h b/drivers/net/hippi/rrunner.h
index 28169043ae49..28169043ae49 100644
--- a/drivers/net/rrunner.h
+++ b/drivers/net/hippi/rrunner.h
diff --git a/drivers/net/ibm_newemac/Makefile b/drivers/net/ibm_newemac/Makefile
deleted file mode 100644
index 0b5c99512762..000000000000
--- a/drivers/net/ibm_newemac/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the PowerPC 4xx on-chip ethernet driver
-#
-
-obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac.o
-
-ibm_newemac-y := mal.o core.o phy.o
-ibm_newemac-$(CONFIG_IBM_NEW_EMAC_ZMII) += zmii.o
-ibm_newemac-$(CONFIG_IBM_NEW_EMAC_RGMII) += rgmii.o
-ibm_newemac-$(CONFIG_IBM_NEW_EMAC_TAH) += tah.o
-ibm_newemac-$(CONFIG_IBM_NEW_EMAC_DEBUG) += debug.o
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 25bb2a015e18..a40fab44b9ae 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -183,7 +183,7 @@ config OLD_BELKIN_DONGLE
Say Y here if you want to build support for the Adaptec Airport 1000
and 2000 dongles. If you want to compile it as a module, choose
M here. Some information is contained in the comments
- at the top of <file:drivers/net/irda/old_belkin.c>.
+ at the top of <file:drivers/net/irda/old_belkin-sir.c>.
config ACT200L_DONGLE
tristate "ACTiSYS IR-200L dongle"
diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c
index 82660672dcd9..d275e276e742 100644
--- a/drivers/net/irda/sh_irda.c
+++ b/drivers/net/irda/sh_irda.c
@@ -2,7 +2,7 @@
* SuperH IrDA Driver
*
* Copyright (C) 2010 Renesas Solutions Corp.
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* Based on sh_sir.c
* Copyright (C) 2009 Renesas Solutions Corp.
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
@@ -144,8 +145,8 @@ struct sh_irda_xir_func {
struct sh_irda_self {
void __iomem *membase;
- unsigned int irq;
- struct clk *clk;
+ unsigned int irq;
+ struct platform_device *pdev;
struct net_device *ndev;
@@ -264,7 +265,7 @@ static int sh_irda_set_baudrate(struct sh_irda_self *self, int baudrate)
return 0;
}
-static int xir_get_rcv_length(struct sh_irda_self *self)
+static int sh_irda_get_rcv_length(struct sh_irda_self *self)
{
return RFL_MASK & sh_irda_read(self, IRRFLR);
}
@@ -274,47 +275,47 @@ static int xir_get_rcv_length(struct sh_irda_self *self)
* NONE MODE
*
*=====================================*/
-static int xir_fre(struct sh_irda_self *self)
+static int sh_irda_xir_fre(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
dev_err(dev, "none mode: frame recv\n");
return 0;
}
-static int xir_trov(struct sh_irda_self *self)
+static int sh_irda_xir_trov(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
dev_err(dev, "none mode: buffer ram over\n");
return 0;
}
-static int xir_9(struct sh_irda_self *self)
+static int sh_irda_xir_9(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
dev_err(dev, "none mode: time over\n");
return 0;
}
-static int xir_8(struct sh_irda_self *self)
+static int sh_irda_xir_8(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
dev_err(dev, "none mode: framing error\n");
return 0;
}
-static int xir_fte(struct sh_irda_self *self)
+static int sh_irda_xir_fte(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
dev_err(dev, "none mode: frame transmit end\n");
return 0;
}
-static struct sh_irda_xir_func xir_func = {
- .xir_fre = xir_fre,
- .xir_trov = xir_trov,
- .xir_9 = xir_9,
- .xir_8 = xir_8,
- .xir_fte = xir_fte,
+static struct sh_irda_xir_func sh_irda_xir_func = {
+ .xir_fre = sh_irda_xir_fre,
+ .xir_trov = sh_irda_xir_trov,
+ .xir_9 = sh_irda_xir_9,
+ .xir_8 = sh_irda_xir_8,
+ .xir_fte = sh_irda_xir_fte,
};
/*=====================================
@@ -323,12 +324,12 @@ static struct sh_irda_xir_func xir_func = {
*
* MIR/FIR are not supported now
*=====================================*/
-static struct sh_irda_xir_func mfir_func = {
- .xir_fre = xir_fre,
- .xir_trov = xir_trov,
- .xir_9 = xir_9,
- .xir_8 = xir_8,
- .xir_fte = xir_fte,
+static struct sh_irda_xir_func sh_irda_mfir_func = {
+ .xir_fre = sh_irda_xir_fre,
+ .xir_trov = sh_irda_xir_trov,
+ .xir_9 = sh_irda_xir_9,
+ .xir_8 = sh_irda_xir_8,
+ .xir_fte = sh_irda_xir_fte,
};
/*=====================================
@@ -336,12 +337,12 @@ static struct sh_irda_xir_func mfir_func = {
* SIR MODE
*
*=====================================*/
-static int sir_fre(struct sh_irda_self *self)
+static int sh_irda_sir_fre(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
u16 data16;
u8 *data = (u8 *)&data16;
- int len = xir_get_rcv_length(self);
+ int len = sh_irda_get_rcv_length(self);
int i, j;
if (len > IRDARAM_LEN)
@@ -364,7 +365,7 @@ static int sir_fre(struct sh_irda_self *self)
return 0;
}
-static int sir_trov(struct sh_irda_self *self)
+static int sh_irda_sir_trov(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
@@ -373,7 +374,7 @@ static int sir_trov(struct sh_irda_self *self)
return 0;
}
-static int sir_tot(struct sh_irda_self *self)
+static int sh_irda_sir_tot(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
@@ -383,7 +384,7 @@ static int sir_tot(struct sh_irda_self *self)
return 0;
}
-static int sir_fer(struct sh_irda_self *self)
+static int sh_irda_sir_fer(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
@@ -392,7 +393,7 @@ static int sir_fer(struct sh_irda_self *self)
return 0;
}
-static int sir_fte(struct sh_irda_self *self)
+static int sh_irda_sir_fte(struct sh_irda_self *self)
{
struct device *dev = &self->ndev->dev;
@@ -402,12 +403,12 @@ static int sir_fte(struct sh_irda_self *self)
return 0;
}
-static struct sh_irda_xir_func sir_func = {
- .xir_fre = sir_fre,
- .xir_trov = sir_trov,
- .xir_9 = sir_tot,
- .xir_8 = sir_fer,
- .xir_fte = sir_fte,
+static struct sh_irda_xir_func sh_irda_sir_func = {
+ .xir_fre = sh_irda_sir_fre,
+ .xir_trov = sh_irda_sir_trov,
+ .xir_9 = sh_irda_sir_tot,
+ .xir_8 = sh_irda_sir_fer,
+ .xir_fte = sh_irda_sir_fte,
};
static void sh_irda_set_mode(struct sh_irda_self *self, enum sh_irda_mode mode)
@@ -421,22 +422,22 @@ static void sh_irda_set_mode(struct sh_irda_self *self, enum sh_irda_mode mode)
case SH_IRDA_SIR:
name = "SIR";
data = TMD_SIR;
- func = &sir_func;
+ func = &sh_irda_sir_func;
break;
case SH_IRDA_MIR:
name = "MIR";
data = TMD_MIR;
- func = &mfir_func;
+ func = &sh_irda_mfir_func;
break;
case SH_IRDA_FIR:
name = "FIR";
data = TMD_FIR;
- func = &mfir_func;
+ func = &sh_irda_mfir_func;
break;
default:
- name = "NONE";
- data = 0;
- func = &xir_func;
+ name = "NONE";
+ data = 0;
+ func = &sh_irda_xir_func;
break;
}
@@ -694,7 +695,7 @@ static int sh_irda_open(struct net_device *ndev)
struct sh_irda_self *self = netdev_priv(ndev);
int err;
- clk_enable(self->clk);
+ pm_runtime_get_sync(&self->pdev->dev);
err = sh_irda_crc_init(self);
if (err)
goto open_err;
@@ -718,7 +719,7 @@ static int sh_irda_open(struct net_device *ndev)
return 0;
open_err:
- clk_disable(self->clk);
+ pm_runtime_put_sync(&self->pdev->dev);
return err;
}
@@ -734,6 +735,7 @@ static int sh_irda_stop(struct net_device *ndev)
}
netif_stop_queue(ndev);
+ pm_runtime_put_sync(&self->pdev->dev);
dev_info(&ndev->dev, "stoped\n");
@@ -786,11 +788,8 @@ static int __devinit sh_irda_probe(struct platform_device *pdev)
if (err)
goto err_mem_2;
- self->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(self->clk)) {
- dev_err(&pdev->dev, "cannot get irda clock\n");
- goto err_mem_3;
- }
+ self->pdev = pdev;
+ pm_runtime_enable(&pdev->dev);
irda_init_max_qos_capabilies(&self->qos);
@@ -820,8 +819,7 @@ static int __devinit sh_irda_probe(struct platform_device *pdev)
goto exit;
err_mem_4:
- clk_put(self->clk);
-err_mem_3:
+ pm_runtime_disable(&pdev->dev);
sh_irda_remove_iobuf(self);
err_mem_2:
iounmap(self->membase);
@@ -840,7 +838,7 @@ static int __devexit sh_irda_remove(struct platform_device *pdev)
return 0;
unregister_netdev(ndev);
- clk_put(self->clk);
+ pm_runtime_disable(&pdev->dev);
sh_irda_remove_iobuf(self);
iounmap(self->membase);
free_netdev(ndev);
@@ -849,11 +847,29 @@ static int __devexit sh_irda_remove(struct platform_device *pdev)
return 0;
}
+static int sh_irda_runtime_nop(struct device *dev)
+{
+ /* Runtime PM callback shared between ->runtime_suspend()
+ * and ->runtime_resume(). Simply returns success.
+ *
+ * This driver re-initializes all registers after
+ * pm_runtime_get_sync() anyway so there is no need
+ * to save and restore registers here.
+ */
+ return 0;
+}
+
+static const struct dev_pm_ops sh_irda_pm_ops = {
+ .runtime_suspend = sh_irda_runtime_nop,
+ .runtime_resume = sh_irda_runtime_nop,
+};
+
static struct platform_driver sh_irda_driver = {
- .probe = sh_irda_probe,
- .remove = __devexit_p(sh_irda_remove),
- .driver = {
- .name = DRIVER_NAME,
+ .probe = sh_irda_probe,
+ .remove = __devexit_p(sh_irda_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .pm = &sh_irda_pm_ops,
},
};
@@ -870,6 +886,6 @@ static void __exit sh_irda_exit(void)
module_init(sh_irda_init);
module_exit(sh_irda_exit);
-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
MODULE_DESCRIPTION("SuperH IrDA driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 376e3e94bae0..a3ce3d4561ed 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -169,6 +169,9 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
port = macvlan_port_get_rcu(skb->dev);
if (is_multicast_ether_addr(eth->h_dest)) {
+ skb = ip_check_defrag(skb, IP_DEFRAG_MACVLAN);
+ if (!skb)
+ return RX_HANDLER_CONSUMED;
src = macvlan_hash_lookup(port, eth->h_source);
if (!src)
/* frame comes from an external address */
@@ -543,7 +546,8 @@ static int macvlan_ethtool_get_settings(struct net_device *dev,
struct ethtool_cmd *cmd)
{
const struct macvlan_dev *vlan = netdev_priv(dev);
- return dev_ethtool_get_settings(vlan->lowerdev, cmd);
+
+ return __ethtool_get_settings(vlan->lowerdev, cmd);
}
static const struct ethtool_ops macvlan_ethtool_ops = {
@@ -561,7 +565,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_change_mtu = macvlan_change_mtu,
.ndo_change_rx_flags = macvlan_change_rx_flags,
.ndo_set_mac_address = macvlan_set_mac_address,
- .ndo_set_multicast_list = macvlan_set_multicast_list,
+ .ndo_set_rx_mode = macvlan_set_multicast_list,
.ndo_get_stats64 = macvlan_dev_get_stats64,
.ndo_validate_addr = eth_validate_addr,
.ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid,
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index ab96c319a240..1b7082d08f33 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -51,15 +51,13 @@ static struct proto macvtap_proto = {
};
/*
- * Minor number matches netdev->ifindex, so need a potentially
- * large value. This also makes it possible to split the
- * tap functionality out again in the future by offering it
- * from other drivers besides macvtap. As long as every device
- * only has one tap, the interface numbers assure that the
- * device nodes are unique.
+ * Variables for dealing with macvtaps device numbers.
*/
static dev_t macvtap_major;
-#define MACVTAP_NUM_DEVS 65536
+#define MACVTAP_NUM_DEVS (1U << MINORBITS)
+static DEFINE_MUTEX(minor_lock);
+static DEFINE_IDR(minor_idr);
+
#define GOODCOPY_LEN 128
static struct class *macvtap_class;
static struct cdev macvtap_cdev;
@@ -231,6 +229,8 @@ static void macvtap_del_queues(struct net_device *dev)
}
}
BUG_ON(vlan->numvtaps != 0);
+ /* guarantee that any future macvtap_set_queue will fail */
+ vlan->numvtaps = MAX_MACVTAP_QUEUES;
spin_unlock(&macvtap_lock);
synchronize_rcu();
@@ -273,39 +273,73 @@ static int macvtap_receive(struct sk_buff *skb)
return macvtap_forward(skb->dev, skb);
}
-static int macvtap_newlink(struct net *src_net,
- struct net_device *dev,
- struct nlattr *tb[],
- struct nlattr *data[])
+static int macvtap_get_minor(struct macvlan_dev *vlan)
{
- struct device *classdev;
- dev_t devt;
- int err;
+ int retval = -ENOMEM;
+ int id;
+
+ mutex_lock(&minor_lock);
+ if (idr_pre_get(&minor_idr, GFP_KERNEL) == 0)
+ goto exit;
+
+ retval = idr_get_new_above(&minor_idr, vlan, 1, &id);
+ if (retval < 0) {
+ if (retval == -EAGAIN)
+ retval = -ENOMEM;
+ goto exit;
+ }
+ if (id < MACVTAP_NUM_DEVS) {
+ vlan->minor = id;
+ } else {
+ printk(KERN_ERR "too many macvtap devices\n");
+ retval = -EINVAL;
+ idr_remove(&minor_idr, id);
+ }
+exit:
+ mutex_unlock(&minor_lock);
+ return retval;
+}
- err = macvlan_common_newlink(src_net, dev, tb, data,
- macvtap_receive, macvtap_forward);
- if (err)
- goto out;
+static void macvtap_free_minor(struct macvlan_dev *vlan)
+{
+ mutex_lock(&minor_lock);
+ if (vlan->minor) {
+ idr_remove(&minor_idr, vlan->minor);
+ vlan->minor = 0;
+ }
+ mutex_unlock(&minor_lock);
+}
- devt = MKDEV(MAJOR(macvtap_major), dev->ifindex);
+static struct net_device *dev_get_by_macvtap_minor(int minor)
+{
+ struct net_device *dev = NULL;
+ struct macvlan_dev *vlan;
- classdev = device_create(macvtap_class, &dev->dev, devt,
- dev, "tap%d", dev->ifindex);
- if (IS_ERR(classdev)) {
- err = PTR_ERR(classdev);
- macvtap_del_queues(dev);
+ mutex_lock(&minor_lock);
+ vlan = idr_find(&minor_idr, minor);
+ if (vlan) {
+ dev = vlan->dev;
+ dev_hold(dev);
}
+ mutex_unlock(&minor_lock);
+ return dev;
+}
-out:
- return err;
+static int macvtap_newlink(struct net *src_net,
+ struct net_device *dev,
+ struct nlattr *tb[],
+ struct nlattr *data[])
+{
+ /* Don't put anything that may fail after macvlan_common_newlink
+ * because we can't undo what it does.
+ */
+ return macvlan_common_newlink(src_net, dev, tb, data,
+ macvtap_receive, macvtap_forward);
}
static void macvtap_dellink(struct net_device *dev,
struct list_head *head)
{
- device_destroy(macvtap_class,
- MKDEV(MAJOR(macvtap_major), dev->ifindex));
-
macvtap_del_queues(dev);
macvlan_dellink(dev, head);
}
@@ -337,11 +371,15 @@ static void macvtap_sock_write_space(struct sock *sk)
wake_up_interruptible_poll(wqueue, POLLOUT | POLLWRNORM | POLLWRBAND);
}
+static void macvtap_sock_destruct(struct sock *sk)
+{
+ skb_queue_purge(&sk->sk_receive_queue);
+}
+
static int macvtap_open(struct inode *inode, struct file *file)
{
struct net *net = current->nsproxy->net_ns;
- struct net_device *dev = dev_get_by_index(net, iminor(inode));
- struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *dev = dev_get_by_macvtap_minor(iminor(inode));
struct macvtap_queue *q;
int err;
@@ -349,11 +387,6 @@ static int macvtap_open(struct inode *inode, struct file *file)
if (!dev)
goto out;
- /* check if this is a macvtap device */
- err = -EINVAL;
- if (dev->rtnl_link_ops != &macvtap_link_ops)
- goto out;
-
err = -ENOMEM;
q = (struct macvtap_queue *)sk_alloc(net, AF_UNSPEC, GFP_KERNEL,
&macvtap_proto);
@@ -368,18 +401,19 @@ static int macvtap_open(struct inode *inode, struct file *file)
q->sock.ops = &macvtap_socket_ops;
sock_init_data(&q->sock, &q->sk);
q->sk.sk_write_space = macvtap_sock_write_space;
+ q->sk.sk_destruct = macvtap_sock_destruct;
q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
q->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
/*
* so far only KVM virtio_net uses macvtap, enable zero copy between
* guest kernel and host kernel when lower device supports zerocopy
+ *
+ * The macvlan supports zerocopy iff the lower device supports zero
+ * copy so we don't have to look at the lower device directly.
*/
- if (vlan) {
- if ((vlan->lowerdev->features & NETIF_F_HIGHDMA) &&
- (vlan->lowerdev->features & NETIF_F_SG))
- sock_set_flag(&q->sk, SOCK_ZEROCOPY);
- }
+ if ((dev->features & NETIF_F_HIGHDMA) && (dev->features & NETIF_F_SG))
+ sock_set_flag(&q->sk, SOCK_ZEROCOPY);
err = macvtap_set_queue(dev, file, q);
if (err)
@@ -453,7 +487,6 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
int copy = skb_headlen(skb);
int size, offset1 = 0;
int i = 0;
- skb_frag_t *f;
/* Skip over from offset */
while (count && (offset >= from->iov_len)) {
@@ -503,14 +536,13 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
skb->truesize += len;
atomic_add(len, &skb->sk->sk_wmem_alloc);
while (len) {
- f = &skb_shinfo(skb)->frags[i];
- f->page = page[i];
- f->page_offset = base & ~PAGE_MASK;
- f->size = min_t(int, len, PAGE_SIZE - f->page_offset);
+ int off = base & ~PAGE_MASK;
+ int size = min_t(int, len, PAGE_SIZE - off);
+ __skb_fill_page_desc(skb, i, page[i], off, size);
skb_shinfo(skb)->nr_frags++;
/* increase sk_wmem_alloc */
- base += f->size;
- len -= f->size;
+ base += size;
+ len -= size;
i++;
}
offset1 = 0;
@@ -970,6 +1002,52 @@ struct socket *macvtap_get_socket(struct file *file)
}
EXPORT_SYMBOL_GPL(macvtap_get_socket);
+static int macvtap_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct macvlan_dev *vlan;
+ struct device *classdev;
+ dev_t devt;
+ int err;
+
+ if (dev->rtnl_link_ops != &macvtap_link_ops)
+ return NOTIFY_DONE;
+
+ vlan = netdev_priv(dev);
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ /* Create the device node here after the network device has
+ * been registered but before register_netdevice has
+ * finished running.
+ */
+ err = macvtap_get_minor(vlan);
+ if (err)
+ return notifier_from_errno(err);
+
+ devt = MKDEV(MAJOR(macvtap_major), vlan->minor);
+ classdev = device_create(macvtap_class, &dev->dev, devt,
+ dev, "tap%d", dev->ifindex);
+ if (IS_ERR(classdev)) {
+ macvtap_free_minor(vlan);
+ return notifier_from_errno(PTR_ERR(classdev));
+ }
+ break;
+ case NETDEV_UNREGISTER:
+ devt = MKDEV(MAJOR(macvtap_major), vlan->minor);
+ device_destroy(macvtap_class, devt);
+ macvtap_free_minor(vlan);
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block macvtap_notifier_block __read_mostly = {
+ .notifier_call = macvtap_device_event,
+};
+
static int macvtap_init(void)
{
int err;
@@ -990,12 +1068,18 @@ static int macvtap_init(void)
goto out3;
}
- err = macvlan_link_register(&macvtap_link_ops);
+ err = register_netdevice_notifier(&macvtap_notifier_block);
if (err)
goto out4;
+ err = macvlan_link_register(&macvtap_link_ops);
+ if (err)
+ goto out5;
+
return 0;
+out5:
+ unregister_netdevice_notifier(&macvtap_notifier_block);
out4:
class_unregister(macvtap_class);
out3:
@@ -1010,6 +1094,7 @@ module_init(macvtap_init);
static void macvtap_exit(void)
{
rtnl_link_unregister(&macvtap_link_ops);
+ unregister_netdevice_notifier(&macvtap_notifier_block);
class_unregister(macvtap_class);
cdev_del(&macvtap_cdev);
unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
diff --git a/drivers/net/octeon/Makefile b/drivers/net/octeon/Makefile
deleted file mode 100644
index 906edecacfd3..000000000000
--- a/drivers/net/octeon/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-
-obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon_mgmt.o
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
deleted file mode 100644
index c0f23376a462..000000000000
--- a/drivers/net/pci-skeleton.c
+++ /dev/null
@@ -1,1923 +0,0 @@
-/*
-
- drivers/net/pci-skeleton.c
-
- Maintained by Jeff Garzik <jgarzik@pobox.com>
-
- Original code came from 8139too.c, which in turns was based
- originally on Donald Becker's rtl8139.c driver, versions 1.11
- and older. This driver was originally based on rtl8139.c
- version 1.07. Header of rtl8139.c version 1.11:
-
- -----<snip>-----
-
- Written 1997-2000 by Donald Becker.
- This software may be used and distributed according to the
- terms of the GNU General Public License (GPL), incorporated
- herein by reference. Drivers based on or derived from this
- code fall under the GPL and must retain the authorship,
- copyright and license notice. This file is not a complete
- program and may only be used when the entire operating
- system is licensed under the GPL.
-
- This driver is for boards based on the RTL8129 and RTL8139
- PCI ethernet chips.
-
- The author may be reached as becker@scyld.com, or C/O Scyld
- Computing Corporation 410 Severn Ave., Suite 210 Annapolis
- MD 21403
-
- Support and updates available at
- http://www.scyld.com/network/rtl8139.html
-
- Twister-tuning table provided by Kinston
- <shangh@realtek.com.tw>.
-
- -----<snip>-----
-
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
-
------------------------------------------------------------------------------
-
- Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the RealTek RTL8139 series, the RealTek
-Fast Ethernet controllers for PCI and CardBus. This chip is used on many
-low-end boards, sometimes with its markings changed.
-
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board. The system BIOS will assign the
-PCI INTA signal to a (preferably otherwise unused) system IRQ line.
-
-III. Driver operation
-
-IIIa. Rx Ring buffers
-
-The receive unit uses a single linear ring buffer rather than the more
-common (and more efficient) descriptor-based architecture. Incoming frames
-are sequentially stored into the Rx region, and the host copies them into
-skbuffs.
-
-Comment: While it is theoretically possible to process many frames in place,
-any delay in Rx processing would cause us to drop frames. More importantly,
-the Linux protocol stack is not designed to operate in this manner.
-
-IIIb. Tx operation
-
-The RTL8139 uses a fixed set of four Tx descriptors in register space.
-In a stunningly bad design choice, Tx frames must be 32 bit aligned. Linux
-aligns the IP header on word boundaries, and 14 byte ethernet header means
-that almost all frames will need to be copied to an alignment buffer.
-
-IVb. References
-
-http://www.realtek.com.tw/
-http://www.scyld.com/expert/NWay.html
-
-IVc. Errata
-
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/crc32.h>
-#include <linux/io.h>
-
-#define NETDRV_VERSION "1.0.1"
-#define MODNAME "netdrv"
-#define NETDRV_DRIVER_LOAD_MSG "MyVendor Fast Ethernet driver " NETDRV_VERSION " loaded"
-
-static char version[] __devinitdata =
- KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n"
- " Support available from http://foo.com/bar/baz.html\n";
-
-/* define to 1 to enable PIO instead of MMIO */
-#undef USE_IO_OPS
-
-/* define to 1 to enable copious debugging info */
-#undef NETDRV_DEBUG
-
-/* define to 1 to disable lightweight runtime debugging checks */
-#undef NETDRV_NDEBUG
-
-
-#ifdef NETDRV_DEBUG
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...) \
- printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
-#else
-#define DPRINTK(fmt, args...) \
-do { \
- if (0) \
- printk(KERN_DEBUG fmt, ##args); \
-} while (0)
-#endif
-
-#ifdef NETDRV_NDEBUG
-#define assert(expr) do {} while (0)
-#else
-#define assert(expr) \
- if (!(expr)) { \
- printk("Assertion failed! %s,%s,%s,line=%d\n", \
- #expr, __FILE__, __func__, __LINE__); \
- }
-#endif
-
-
-/* A few user-configurable values. */
-/* media options */
-static int media[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
-
-/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
- The RTL chips use a 64 element hash table based on the Ethernet CRC. */
-static int multicast_filter_limit = 32;
-
-/* Size of the in-memory receive ring. */
-#define RX_BUF_LEN_IDX 2 /* 0==8K, 1==16K, 2==32K, 3==64K */
-#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
-#define RX_BUF_PAD 16
-#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
-#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
-
-/* Number of Tx descriptor registers. */
-#define NUM_TX_DESC 4
-
-/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/
-#define MAX_ETH_FRAME_SIZE 1536
-
-/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
-#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE
-#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC)
-
-/* PCI Tuning Parameters
- Threshold is bytes transferred to chip before transmission starts. */
-#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */
-
-/* The following settings are log_2(bytes)-4:
- 0==16 bytes 1==32 2==64 3==128 4==256 5==512 6==1024 7==end of packet.
-*/
-#define RX_FIFO_THRESH 6 /* Rx buffer level before first PCI xfer. */
-#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
-#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
-
-
-/* Operational parameters that usually are not changed. */
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (6 * HZ)
-
-enum {
- HAS_CHIP_XCVR = 0x020000,
- HAS_LNK_CHNG = 0x040000,
-};
-
-#define NETDRV_MIN_IO_SIZE 0x80
-#define RTL8139B_IO_SIZE 256
-
-#define NETDRV_CAPS (HAS_CHIP_XCVR | HAS_LNK_CHNG)
-
-typedef enum {
- RTL8139 = 0,
- NETDRV_CB,
- SMC1211TX,
- /*MPX5030,*/
- DELTA8139,
- ADDTRON8139,
-} board_t;
-
-
-/* indexed by board_t, above */
-static struct {
- const char *name;
-} board_info[] __devinitdata = {
- { "RealTek RTL8139 Fast Ethernet" },
- { "RealTek RTL8139B PCI/CardBus" },
- { "SMC1211TX EZCard 10/100 (RealTek RTL8139)" },
-/* { MPX5030, "Accton MPX5030 (RealTek RTL8139)" },*/
- { "Delta Electronics 8139 10/100BaseTX" },
- { "Addtron Technology 8139 10/100BaseTX" },
-};
-
-
-static DEFINE_PCI_DEVICE_TABLE(netdrv_pci_tbl) = {
- {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
- {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NETDRV_CB },
- {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX },
-/* {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },*/
- {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DELTA8139 },
- {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 },
- {0,}
-};
-MODULE_DEVICE_TABLE(pci, netdrv_pci_tbl);
-
-
-/* The rest of these values should never change. */
-
-/* Symbolic offsets to registers. */
-enum NETDRV_registers {
- MAC0 = 0, /* Ethernet hardware address. */
- MAR0 = 8, /* Multicast filter. */
- TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */
- TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */
- RxBuf = 0x30,
- RxEarlyCnt = 0x34,
- RxEarlyStatus = 0x36,
- ChipCmd = 0x37,
- RxBufPtr = 0x38,
- RxBufAddr = 0x3A,
- IntrMask = 0x3C,
- IntrStatus = 0x3E,
- TxConfig = 0x40,
- ChipVersion = 0x43,
- RxConfig = 0x44,
- Timer = 0x48, /* A general-purpose counter. */
- RxMissed = 0x4C, /* 24 bits valid, write clears. */
- Cfg9346 = 0x50,
- Config0 = 0x51,
- Config1 = 0x52,
- FlashReg = 0x54,
- MediaStatus = 0x58,
- Config3 = 0x59,
- Config4 = 0x5A, /* absent on RTL-8139A */
- HltClk = 0x5B,
- MultiIntr = 0x5C,
- TxSummary = 0x60,
- BasicModeCtrl = 0x62,
- BasicModeStatus = 0x64,
- NWayAdvert = 0x66,
- NWayLPAR = 0x68,
- NWayExpansion = 0x6A,
- /* Undocumented registers, but required for proper operation. */
- FIFOTMS = 0x70, /* FIFO Control and test. */
- CSCR = 0x74, /* Chip Status and Configuration Register. */
- PARA78 = 0x78,
- PARA7c = 0x7c, /* Magic transceiver parameter register. */
- Config5 = 0xD8, /* absent on RTL-8139A */
-};
-
-enum ClearBitMasks {
- MultiIntrClear = 0xF000,
- ChipCmdClear = 0xE2,
- Config1Clear = (1 << 7) | (1 << 6) | (1 << 3) | (1 << 2) | (1 << 1),
-};
-
-enum ChipCmdBits {
- CmdReset = 0x10,
- CmdRxEnb = 0x08,
- CmdTxEnb = 0x04,
- RxBufEmpty = 0x01,
-};
-
-/* Interrupt register bits, using my own meaningful names. */
-enum IntrStatusBits {
- PCIErr = 0x8000,
- PCSTimeout = 0x4000,
- RxFIFOOver = 0x40,
- RxUnderrun = 0x20,
- RxOverflow = 0x10,
- TxErr = 0x08,
- TxOK = 0x04,
- RxErr = 0x02,
- RxOK = 0x01,
-};
-enum TxStatusBits {
- TxHostOwns = 0x2000,
- TxUnderrun = 0x4000,
- TxStatOK = 0x8000,
- TxOutOfWindow = 0x20000000,
- TxAborted = 0x40000000,
- TxCarrierLost = 0x80000000,
-};
-enum RxStatusBits {
- RxMulticast = 0x8000,
- RxPhysical = 0x4000,
- RxBroadcast = 0x2000,
- RxBadSymbol = 0x0020,
- RxRunt = 0x0010,
- RxTooLong = 0x0008,
- RxCRCErr = 0x0004,
- RxBadAlign = 0x0002,
- RxStatusOK = 0x0001,
-};
-
-/* Bits in RxConfig. */
-enum rx_mode_bits {
- AcceptErr = 0x20,
- AcceptRunt = 0x10,
- AcceptBroadcast = 0x08,
- AcceptMulticast = 0x04,
- AcceptMyPhys = 0x02,
- AcceptAllPhys = 0x01,
-};
-
-/* Bits in TxConfig. */
-enum tx_config_bits {
- TxIFG1 = (1 << 25), /* Interframe Gap Time */
- TxIFG0 = (1 << 24), /* Enabling these bits violates IEEE 802.3 */
- TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
- TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */
- TxClearAbt = (1 << 0), /* Clear abort (WO) */
- TxDMAShift = 8, /* DMA burst value(0-7) is shift this many bits */
-
- TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
-};
-
-/* Bits in Config1 */
-enum Config1Bits {
- Cfg1_PM_Enable = 0x01,
- Cfg1_VPD_Enable = 0x02,
- Cfg1_PIO = 0x04,
- Cfg1_MMIO = 0x08,
- Cfg1_LWAKE = 0x10,
- Cfg1_Driver_Load = 0x20,
- Cfg1_LED0 = 0x40,
- Cfg1_LED1 = 0x80,
-};
-
-enum RxConfigBits {
- /* Early Rx threshold, none or X/16 */
- RxCfgEarlyRxNone = 0,
- RxCfgEarlyRxShift = 24,
-
- /* rx fifo threshold */
- RxCfgFIFOShift = 13,
- RxCfgFIFONone = (7 << RxCfgFIFOShift),
-
- /* Max DMA burst */
- RxCfgDMAShift = 8,
- RxCfgDMAUnlimited = (7 << RxCfgDMAShift),
-
- /* rx ring buffer length */
- RxCfgRcv8K = 0,
- RxCfgRcv16K = (1 << 11),
- RxCfgRcv32K = (1 << 12),
- RxCfgRcv64K = (1 << 11) | (1 << 12),
-
- /* Disable packet wrap at end of Rx buffer */
- RxNoWrap = (1 << 7),
-};
-
-
-/* Twister tuning parameters from RealTek.
- Completely undocumented, but required to tune bad links. */
-enum CSCRBits {
- CSCR_LinkOKBit = 0x0400,
- CSCR_LinkChangeBit = 0x0800,
- CSCR_LinkStatusBits = 0x0f000,
- CSCR_LinkDownOffCmd = 0x003c0,
- CSCR_LinkDownCmd = 0x0f3c0,
-};
-
-
-enum Cfg9346Bits {
- Cfg9346_Lock = 0x00,
- Cfg9346_Unlock = 0xC0,
-};
-
-
-#define PARA78_default 0x78fa8388
-#define PARA7c_default 0xcb38de43 /* param[0][3] */
-#define PARA7c_xxx 0xcb38de43
-static const unsigned long param[4][4] = {
- {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43},
- {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
- {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
- {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}
-};
-
-struct ring_info {
- struct sk_buff *skb;
- dma_addr_t mapping;
-};
-
-
-typedef enum {
- CH_8139 = 0,
- CH_8139_K,
- CH_8139A,
- CH_8139B,
- CH_8130,
- CH_8139C,
-} chip_t;
-
-
-/* directly indexed by chip_t, above */
-static const struct {
- const char *name;
- u8 version; /* from RTL8139C docs */
- u32 RxConfigMask; /* should clear the bits supported by this chip */
-} rtl_chip_info[] = {
- { "RTL-8139",
- 0x40,
- 0xf0fe0040, /* XXX copied from RTL8139A, verify */
- },
-
- { "RTL-8139 rev K",
- 0x60,
- 0xf0fe0040,
- },
-
- { "RTL-8139A",
- 0x70,
- 0xf0fe0040,
- },
-
- { "RTL-8139B",
- 0x78,
- 0xf0fc0040
- },
-
- { "RTL-8130",
- 0x7C,
- 0xf0fe0040, /* XXX copied from RTL8139A, verify */
- },
-
- { "RTL-8139C",
- 0x74,
- 0xf0fc0040, /* XXX copied from RTL8139B, verify */
- },
-
-};
-
-
-struct netdrv_private {
- board_t board;
- void *mmio_addr;
- int drv_flags;
- struct pci_dev *pci_dev;
- struct timer_list timer; /* Media selection timer. */
- unsigned char *rx_ring;
- unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */
- unsigned int tx_flag;
- atomic_t cur_tx;
- atomic_t dirty_tx;
- /* The saved address of a sent-in-place packet/buffer, for skfree(). */
- struct ring_info tx_info[NUM_TX_DESC];
- unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */
- unsigned char *tx_bufs; /* Tx bounce buffer region. */
- dma_addr_t rx_ring_dma;
- dma_addr_t tx_bufs_dma;
- char phys[4]; /* MII device addresses. */
- char twistie, twist_row, twist_col; /* Twister tune state. */
- unsigned int full_duplex:1; /* Full-duplex operation requested. */
- unsigned int duplex_lock:1;
- unsigned int default_port:4; /* Last dev->if_port value. */
- unsigned int media2:4; /* Secondary monitored media port. */
- unsigned int medialock:1; /* Don't sense media type. */
- unsigned int mediasense:1; /* Media sensing in progress. */
- spinlock_t lock;
- chip_t chipset;
-};
-
-MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
-MODULE_DESCRIPTION("Skeleton for a PCI Fast Ethernet driver");
-MODULE_LICENSE("GPL");
-module_param(multicast_filter_limit, int, 0);
-module_param(max_interrupt_work, int, 0);
-module_param_array(media, int, NULL, 0);
-MODULE_PARM_DESC(multicast_filter_limit,
- MODNAME " maximum number of filtered multicast addresses");
-MODULE_PARM_DESC(max_interrupt_work,
- MODNAME " maximum events handled per interrupt");
-MODULE_PARM_DESC(media,
- MODNAME " Bits 0-3: media type, bit 17: full duplex");
-
-static int read_eeprom(void *ioaddr, int location, int addr_len);
-static int netdrv_open(struct net_device *dev);
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int location,
- int val);
-static void netdrv_timer(unsigned long data);
-static void netdrv_tx_timeout(struct net_device *dev);
-static void netdrv_init_ring(struct net_device *dev);
-static int netdrv_start_xmit(struct sk_buff *skb,
- struct net_device *dev);
-static irqreturn_t netdrv_interrupt(int irq, void *dev_instance);
-static int netdrv_close(struct net_device *dev);
-static int netdrv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void netdrv_set_rx_mode(struct net_device *dev);
-static void netdrv_hw_start(struct net_device *dev);
-
-
-#ifdef USE_IO_OPS
-
-#define NETDRV_R8(reg) inb(((unsigned long)ioaddr) + (reg))
-#define NETDRV_R16(reg) inw(((unsigned long)ioaddr) + (reg))
-#define NETDRV_R32(reg) ((unsigned long)inl(((unsigned long)ioaddr) + (reg)))
-#define NETDRV_W8(reg, val8) outb((val8), ((unsigned long)ioaddr) + (reg))
-#define NETDRV_W16(reg, val16) outw((val16), ((unsigned long)ioaddr) + (reg))
-#define NETDRV_W32(reg, val32) outl((val32), ((unsigned long)ioaddr) + (reg))
-#define NETDRV_W8_F NETDRV_W8
-#define NETDRV_W16_F NETDRV_W16
-#define NETDRV_W32_F NETDRV_W32
-#undef readb
-#undef readw
-#undef readl
-#undef writeb
-#undef writew
-#undef writel
-#define readb(addr) inb((unsigned long)(addr))
-#define readw(addr) inw((unsigned long)(addr))
-#define readl(addr) inl((unsigned long)(addr))
-#define writeb(val, addr) outb((val), (unsigned long)(addr))
-#define writew(val, addr) outw((val), (unsigned long)(addr))
-#define writel(val, addr) outl((val), (unsigned long)(addr))
-
-#else
-
-/* write MMIO register, with flush */
-/* Flush avoids rtl8139 bug w/ posted MMIO writes */
-#define NETDRV_W8_F(reg, val8) \
-do { \
- writeb((val8), ioaddr + (reg)); \
- readb(ioaddr + (reg)); \
-} while (0)
-#define NETDRV_W16_F(reg, val16) \
-do { \
- writew((val16), ioaddr + (reg)); \
- readw(ioaddr + (reg)); \
-} while (0)
-#define NETDRV_W32_F(reg, val32) \
-do { \
- writel((val32), ioaddr + (reg)); \
- readl(ioaddr + (reg)); \
-} while (0)
-
-
-#ifdef MMIO_FLUSH_AUDIT_COMPLETE
-
-/* write MMIO register */
-#define NETDRV_W8(reg, val8) writeb((val8), ioaddr + (reg))
-#define NETDRV_W16(reg, val16) writew((val16), ioaddr + (reg))
-#define NETDRV_W32(reg, val32) writel((val32), ioaddr + (reg))
-
-#else
-
-/* write MMIO register, then flush */
-#define NETDRV_W8 NETDRV_W8_F
-#define NETDRV_W16 NETDRV_W16_F
-#define NETDRV_W32 NETDRV_W32_F
-
-#endif /* MMIO_FLUSH_AUDIT_COMPLETE */
-
-/* read MMIO register */
-#define NETDRV_R8(reg) readb(ioaddr + (reg))
-#define NETDRV_R16(reg) readw(ioaddr + (reg))
-#define NETDRV_R32(reg) ((unsigned long) readl(ioaddr + (reg)))
-
-#endif /* USE_IO_OPS */
-
-
-static const u16 netdrv_intr_mask =
- PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
- TxErr | TxOK | RxErr | RxOK;
-
-static const unsigned int netdrv_rx_config =
- RxCfgEarlyRxNone | RxCfgRcv32K | RxNoWrap |
- (RX_FIFO_THRESH << RxCfgFIFOShift) |
- (RX_DMA_BURST << RxCfgDMAShift);
-
-
-static int __devinit netdrv_init_board(struct pci_dev *pdev,
- struct net_device **dev_out,
- void **ioaddr_out)
-{
- void *ioaddr = NULL;
- struct net_device *dev;
- struct netdrv_private *tp;
- int rc, i;
- u32 pio_start, pio_end, pio_flags, pio_len;
- unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
- u32 tmp;
-
- DPRINTK("ENTER\n");
-
- assert(pdev != NULL);
- assert(ioaddr_out != NULL);
-
- *ioaddr_out = NULL;
- *dev_out = NULL;
-
- /* dev zeroed in alloc_etherdev */
- dev = alloc_etherdev(sizeof(*tp));
- if (dev == NULL) {
- dev_err(&pdev->dev, "unable to alloc new ethernet\n");
- DPRINTK("EXIT, returning -ENOMEM\n");
- return -ENOMEM;
- }
- SET_NETDEV_DEV(dev, &pdev->dev);
- tp = netdev_priv(dev);
-
- /* enable device(incl. PCI PM wakeup), and bus-mastering */
- rc = pci_enable_device(pdev);
- if (rc)
- goto err_out;
-
- pio_start = pci_resource_start(pdev, 0);
- pio_end = pci_resource_end(pdev, 0);
- pio_flags = pci_resource_flags(pdev, 0);
- pio_len = pci_resource_len(pdev, 0);
-
- mmio_start = pci_resource_start(pdev, 1);
- mmio_end = pci_resource_end(pdev, 1);
- mmio_flags = pci_resource_flags(pdev, 1);
- mmio_len = pci_resource_len(pdev, 1);
-
- /* set this immediately, we need to know before
- * we talk to the chip directly */
- DPRINTK("PIO region size == %#02X\n", pio_len);
- DPRINTK("MMIO region size == %#02lX\n", mmio_len);
-
- /* make sure PCI base addr 0 is PIO */
- if (!(pio_flags & IORESOURCE_IO)) {
- dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
-
- /* make sure PCI base addr 1 is MMIO */
- if (!(mmio_flags & IORESOURCE_MEM)) {
- dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
-
- /* check for weird/broken PCI region reporting */
- if ((pio_len < NETDRV_MIN_IO_SIZE) ||
- (mmio_len < NETDRV_MIN_IO_SIZE)) {
- dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
-
- rc = pci_request_regions(pdev, MODNAME);
- if (rc)
- goto err_out;
-
- pci_set_master(pdev);
-
-#ifdef USE_IO_OPS
- ioaddr = (void *)pio_start;
-#else
- /* ioremap MMIO region */
- ioaddr = ioremap(mmio_start, mmio_len);
- if (ioaddr == NULL) {
- dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
- rc = -EIO;
- goto err_out_free_res;
- }
-#endif /* USE_IO_OPS */
-
- /* Soft reset the chip. */
- NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) | CmdReset);
-
- /* Check that the chip has finished the reset. */
- for (i = 1000; i > 0; i--)
- if ((NETDRV_R8(ChipCmd) & CmdReset) == 0)
- break;
- else
- udelay(10);
-
- /* Bring the chip out of low-power mode. */
- /* <insert device-specific code here> */
-
-#ifndef USE_IO_OPS
- /* sanity checks -- ensure PIO and MMIO registers agree */
- assert(inb(pio_start+Config0) == readb(ioaddr+Config0));
- assert(inb(pio_start+Config1) == readb(ioaddr+Config1));
- assert(inb(pio_start+TxConfig) == readb(ioaddr+TxConfig));
- assert(inb(pio_start+RxConfig) == readb(ioaddr+RxConfig));
-#endif /* !USE_IO_OPS */
-
- /* identify chip attached to board */
- tmp = NETDRV_R8(ChipVersion);
- for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--)
- if (tmp == rtl_chip_info[i].version) {
- tp->chipset = i;
- goto match;
- }
-
- /* if unknown chip, assume array element #0, original RTL-8139 in this case */
- dev_printk(KERN_DEBUG, &pdev->dev,
- "unknown chip version, assuming RTL-8139\n");
- dev_printk(KERN_DEBUG, &pdev->dev, "TxConfig = %#lx\n",
- NETDRV_R32(TxConfig));
- tp->chipset = 0;
-
-match:
- DPRINTK("chipset id(%d) == index %d, '%s'\n",
- tmp, tp->chipset, rtl_chip_info[tp->chipset].name);
-
- rc = register_netdev(dev);
- if (rc)
- goto err_out_unmap;
-
- DPRINTK("EXIT, returning 0\n");
- *ioaddr_out = ioaddr;
- *dev_out = dev;
- return 0;
-
-err_out_unmap:
-#ifndef USE_IO_OPS
- iounmap(ioaddr);
-err_out_free_res:
-#endif
- pci_release_regions(pdev);
-err_out:
- free_netdev(dev);
- DPRINTK("EXIT, returning %d\n", rc);
- return rc;
-}
-
-static const struct net_device_ops netdrv_netdev_ops = {
- .ndo_open = netdrv_open,
- .ndo_stop = netdrv_close,
- .ndo_start_xmit = netdrv_start_xmit,
- .ndo_set_multicast_list = netdrv_set_rx_mode,
- .ndo_do_ioctl = netdrv_ioctl,
- .ndo_tx_timeout = netdrv_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
-};
-
-static int __devinit netdrv_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct net_device *dev = NULL;
- struct netdrv_private *tp;
- int i, addr_len, option;
- void *ioaddr = NULL;
- static int board_idx = -1;
-
-/* when built into the kernel, we only print version if device is found */
-#ifndef MODULE
- static int printed_version;
- if (!printed_version++)
- printk(version);
-#endif
-
- DPRINTK("ENTER\n");
-
- assert(pdev != NULL);
- assert(ent != NULL);
-
- board_idx++;
-
- i = netdrv_init_board(pdev, &dev, &ioaddr);
- if (i < 0) {
- DPRINTK("EXIT, returning %d\n", i);
- return i;
- }
-
- tp = netdev_priv(dev);
-
- assert(ioaddr != NULL);
- assert(dev != NULL);
- assert(tp != NULL);
-
- addr_len = read_eeprom(ioaddr, 0, 8) == 0x8129 ? 8 : 6;
- for (i = 0; i < 3; i++)
- ((u16 *)(dev->dev_addr))[i] =
- le16_to_cpu(read_eeprom(ioaddr, i + 7, addr_len));
-
- dev->netdev_ops = &netdrv_netdev_ops;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- dev->irq = pdev->irq;
- dev->base_addr = (unsigned long) ioaddr;
-
- /* netdev_priv()/tp zeroed and aligned in alloc_etherdev */
- tp = netdev_priv(dev);
-
- /* note: tp->chipset set in netdrv_init_board */
- tp->drv_flags = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER | NETDRV_CAPS;
- tp->pci_dev = pdev;
- tp->board = ent->driver_data;
- tp->mmio_addr = ioaddr;
- spin_lock_init(&tp->lock);
-
- pci_set_drvdata(pdev, dev);
-
- tp->phys[0] = 32;
-
- netdev_info(dev, "%s at %#lx, %pM IRQ %d\n",
- board_info[ent->driver_data].name,
- dev->base_addr, dev->dev_addr, dev->irq);
-
- netdev_printk(KERN_DEBUG, dev, "Identified 8139 chip type '%s'\n",
- rtl_chip_info[tp->chipset].name);
-
- /* Put the chip into low-power mode. */
- NETDRV_W8_F(Cfg9346, Cfg9346_Unlock);
-
- /* The lower four bits are the media type. */
- option = (board_idx > 7) ? 0 : media[board_idx];
- if (option > 0) {
- tp->full_duplex = (option & 0x200) ? 1 : 0;
- tp->default_port = option & 15;
- if (tp->default_port)
- tp->medialock = 1;
- }
-
- if (tp->full_duplex) {
- netdev_info(dev, "Media type forced to Full Duplex\n");
- mdio_write(dev, tp->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
- tp->duplex_lock = 1;
- }
-
- DPRINTK("EXIT - returning 0\n");
- return 0;
-}
-
-
-static void __devexit netdrv_remove_one(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct netdrv_private *np;
-
- DPRINTK("ENTER\n");
-
- assert(dev != NULL);
-
- np = netdev_priv(dev);
- assert(np != NULL);
-
- unregister_netdev(dev);
-
-#ifndef USE_IO_OPS
- iounmap(np->mmio_addr);
-#endif /* !USE_IO_OPS */
-
- pci_release_regions(pdev);
-
- free_netdev(dev);
-
- pci_set_drvdata(pdev, NULL);
-
- pci_disable_device(pdev);
-
- DPRINTK("EXIT\n");
-}
-
-
-/* Serial EEPROM section. */
-
-/* EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */
-#define EE_CS 0x08 /* EEPROM chip select. */
-#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */
-#define EE_WRITE_0 0x00
-#define EE_WRITE_1 0x02
-#define EE_DATA_READ 0x01 /* EEPROM chip data out. */
-#define EE_ENB (0x80 | EE_CS)
-
-/* Delay between EEPROM clock transitions.
- No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
-*/
-
-#define eeprom_delay() readl(ee_addr)
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD (5)
-#define EE_READ_CMD (6)
-#define EE_ERASE_CMD (7)
-
-static int __devinit read_eeprom(void *ioaddr, int location, int addr_len)
-{
- int i;
- unsigned retval = 0;
- void *ee_addr = ioaddr + Cfg9346;
- int read_cmd = location | (EE_READ_CMD << addr_len);
-
- DPRINTK("ENTER\n");
-
- writeb(EE_ENB & ~EE_CS, ee_addr);
- writeb(EE_ENB, ee_addr);
- eeprom_delay();
-
- /* Shift the read command bits out. */
- for (i = 4 + addr_len; i >= 0; i--) {
- int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
- writeb(EE_ENB | dataval, ee_addr);
- eeprom_delay();
- writeb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
- eeprom_delay();
- }
- writeb(EE_ENB, ee_addr);
- eeprom_delay();
-
- for (i = 16; i > 0; i--) {
- writeb(EE_ENB | EE_SHIFT_CLK, ee_addr);
- eeprom_delay();
- retval =
- (retval << 1) | ((readb(ee_addr) & EE_DATA_READ) ? 1 :
- 0);
- writeb(EE_ENB, ee_addr);
- eeprom_delay();
- }
-
- /* Terminate the EEPROM access. */
- writeb(~EE_CS, ee_addr);
- eeprom_delay();
-
- DPRINTK("EXIT - returning %d\n", retval);
- return retval;
-}
-
-/* MII serial management: mostly bogus for now. */
-/* Read and write the MII management registers using software-generated
- serial MDIO protocol.
- The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
- met by back-to-back PCI I/O cycles, but we insert a delay to avoid
- "overclocking" issues. */
-#define MDIO_DIR 0x80
-#define MDIO_DATA_OUT 0x04
-#define MDIO_DATA_IN 0x02
-#define MDIO_CLK 0x01
-#define MDIO_WRITE0 (MDIO_DIR)
-#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
-
-#define mdio_delay() readb(mdio_addr)
-
-
-static char mii_2_8139_map[8] = {
- BasicModeCtrl,
- BasicModeStatus,
- 0,
- 0,
- NWayAdvert,
- NWayLPAR,
- NWayExpansion,
- 0
-};
-
-
-/* Syncronize the MII management interface by shifting 32 one bits out. */
-static void mdio_sync(void *mdio_addr)
-{
- int i;
-
- DPRINTK("ENTER\n");
-
- for (i = 32; i >= 0; i--) {
- writeb(MDIO_WRITE1, mdio_addr);
- mdio_delay();
- writeb(MDIO_WRITE1 | MDIO_CLK, mdio_addr);
- mdio_delay();
- }
-
- DPRINTK("EXIT\n");
-}
-
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
- struct netdrv_private *tp = netdev_priv(dev);
- void *mdio_addr = tp->mmio_addr + Config4;
- int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
- int retval = 0;
- int i;
-
- DPRINTK("ENTER\n");
-
- if (phy_id > 31) { /* Really a 8139. Use internal registers. */
- DPRINTK("EXIT after directly using 8139 internal regs\n");
- return location < 8 && mii_2_8139_map[location] ?
- readw(tp->mmio_addr + mii_2_8139_map[location]) : 0;
- }
- mdio_sync(mdio_addr);
- /* Shift the read command bits out. */
- for (i = 15; i >= 0; i--) {
- int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
-
- writeb(MDIO_DIR | dataval, mdio_addr);
- mdio_delay();
- writeb(MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
- mdio_delay();
- }
-
- /* Read the two transition, 16 data, and wire-idle bits. */
- for (i = 19; i > 0; i--) {
- writeb(0, mdio_addr);
- mdio_delay();
- retval = ((retval << 1) | ((readb(mdio_addr) & MDIO_DATA_IN))
- ? 1 : 0);
- writeb(MDIO_CLK, mdio_addr);
- mdio_delay();
- }
-
- DPRINTK("EXIT, returning %d\n", (retval >> 1) & 0xffff);
- return (retval >> 1) & 0xffff;
-}
-
-
-static void mdio_write(struct net_device *dev, int phy_id, int location,
- int value)
-{
- struct netdrv_private *tp = netdev_priv(dev);
- void *mdio_addr = tp->mmio_addr + Config4;
- int mii_cmd =
- (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
- int i;
-
- DPRINTK("ENTER\n");
-
- if (phy_id > 31) { /* Really a 8139. Use internal registers. */
- if (location < 8 && mii_2_8139_map[location]) {
- writew(value,
- tp->mmio_addr + mii_2_8139_map[location]);
- readw(tp->mmio_addr + mii_2_8139_map[location]);
- }
- DPRINTK("EXIT after directly using 8139 internal regs\n");
- return;
- }
- mdio_sync(mdio_addr);
-
- /* Shift the command bits out. */
- for (i = 31; i >= 0; i--) {
- int dataval =
- (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
- writeb(dataval, mdio_addr);
- mdio_delay();
- writeb(dataval | MDIO_CLK, mdio_addr);
- mdio_delay();
- }
-
- /* Clear out extra bits. */
- for (i = 2; i > 0; i--) {
- writeb(0, mdio_addr);
- mdio_delay();
- writeb(MDIO_CLK, mdio_addr);
- mdio_delay();
- }
-
- DPRINTK("EXIT\n");
-}
-
-
-static int netdrv_open(struct net_device *dev)
-{
- struct netdrv_private *tp = netdev_priv(dev);
- int retval;
- void *ioaddr = tp->mmio_addr;
-
- DPRINTK("ENTER\n");
-
- retval = request_irq(dev->irq, netdrv_interrupt, IRQF_SHARED, dev->name, dev);
- if (retval) {
- DPRINTK("EXIT, returning %d\n", retval);
- return retval;
- }
-
- tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
- &tp->tx_bufs_dma);
- tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
- &tp->rx_ring_dma);
- if (tp->tx_bufs == NULL || tp->rx_ring == NULL) {
- free_irq(dev->irq, dev);
-
- if (tp->tx_bufs)
- pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
- tp->tx_bufs, tp->tx_bufs_dma);
- if (tp->rx_ring)
- pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
- tp->rx_ring, tp->rx_ring_dma);
-
- DPRINTK("EXIT, returning -ENOMEM\n");
- return -ENOMEM;
-
- }
-
- tp->full_duplex = tp->duplex_lock;
- tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
-
- netdrv_init_ring(dev);
- netdrv_hw_start(dev);
-
- netdev_dbg(dev, "ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n",
- (unsigned long long)pci_resource_start(tp->pci_dev, 1),
- dev->irq, NETDRV_R8(MediaStatus),
- tp->full_duplex ? "full" : "half");
-
- /* Set the timer to switch to check for link beat and perhaps switch
- to an alternate media type. */
- init_timer(&tp->timer);
- tp->timer.expires = jiffies + 3 * HZ;
- tp->timer.data = (unsigned long) dev;
- tp->timer.function = netdrv_timer;
- add_timer(&tp->timer);
-
- DPRINTK("EXIT, returning 0\n");
- return 0;
-}
-
-
-/* Start the hardware at open or resume. */
-static void netdrv_hw_start(struct net_device *dev)
-{
- struct netdrv_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
- u32 i;
-
- DPRINTK("ENTER\n");
-
- /* Soft reset the chip. */
- NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) | CmdReset);
- udelay(100);
-
- /* Check that the chip has finished the reset. */
- for (i = 1000; i > 0; i--)
- if ((NETDRV_R8(ChipCmd) & CmdReset) == 0)
- break;
-
- /* Restore our idea of the MAC address. */
- NETDRV_W32_F(MAC0 + 0, cpu_to_le32(*(u32 *)(dev->dev_addr + 0)));
- NETDRV_W32_F(MAC0 + 4, cpu_to_le32(*(u32 *)(dev->dev_addr + 4)));
-
- /* Must enable Tx/Rx before setting transfer thresholds! */
- NETDRV_W8_F(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) |
- CmdRxEnb | CmdTxEnb);
-
- i = netdrv_rx_config |
- (NETDRV_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
- NETDRV_W32_F(RxConfig, i);
-
- /* Check this value: the documentation for IFG contradicts ifself. */
- NETDRV_W32(TxConfig, (TX_DMA_BURST << TxDMAShift));
-
- /* unlock Config[01234] and BMCR register writes */
- NETDRV_W8_F(Cfg9346, Cfg9346_Unlock);
- udelay(10);
-
- tp->cur_rx = 0;
-
- /* Lock Config[01234] and BMCR register writes */
- NETDRV_W8_F(Cfg9346, Cfg9346_Lock);
- udelay(10);
-
- /* init Rx ring buffer DMA address */
- NETDRV_W32_F(RxBuf, tp->rx_ring_dma);
-
- /* init Tx buffer DMA addresses */
- for (i = 0; i < NUM_TX_DESC; i++)
- NETDRV_W32_F(TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs));
-
- NETDRV_W32_F(RxMissed, 0);
-
- netdrv_set_rx_mode(dev);
-
- /* no early-rx interrupts */
- NETDRV_W16(MultiIntr, NETDRV_R16(MultiIntr) & MultiIntrClear);
-
- /* make sure RxTx has started */
- NETDRV_W8_F(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) |
- CmdRxEnb | CmdTxEnb);
-
- /* Enable all known interrupts by setting the interrupt mask. */
- NETDRV_W16_F(IntrMask, netdrv_intr_mask);
-
- netif_start_queue(dev);
-
- DPRINTK("EXIT\n");
-}
-
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void netdrv_init_ring(struct net_device *dev)
-{
- struct netdrv_private *tp = netdev_priv(dev);
- int i;
-
- DPRINTK("ENTER\n");
-
- tp->cur_rx = 0;
- atomic_set(&tp->cur_tx, 0);
- atomic_set(&tp->dirty_tx, 0);
-
- for (i = 0; i < NUM_TX_DESC; i++) {
- tp->tx_info[i].skb = NULL;
- tp->tx_info[i].mapping = 0;
- tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
- }
-
- DPRINTK("EXIT\n");
-}
-
-
-static void netdrv_timer(unsigned long data)
-{
- struct net_device *dev = (struct net_device *) data;
- struct netdrv_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
- int next_tick = 60 * HZ;
- int mii_lpa;
-
- mii_lpa = mdio_read(dev, tp->phys[0], MII_LPA);
-
- if (!tp->duplex_lock && mii_lpa != 0xffff) {
- int duplex = ((mii_lpa & LPA_100FULL) ||
- (mii_lpa & 0x01C0) == 0x0040);
- if (tp->full_duplex != duplex) {
- tp->full_duplex = duplex;
- netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n",
- tp->full_duplex ? "full" : "half",
- tp->phys[0], mii_lpa);
- NETDRV_W8(Cfg9346, Cfg9346_Unlock);
- NETDRV_W8(Config1, tp->full_duplex ? 0x60 : 0x20);
- NETDRV_W8(Cfg9346, Cfg9346_Lock);
- }
- }
-
- netdev_dbg(dev, "Media selection tick, Link partner %04x\n",
- NETDRV_R16(NWayLPAR));
- netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x RxStatus %04lx\n",
- NETDRV_R16(IntrMask),
- NETDRV_R16(IntrStatus),
- NETDRV_R32(RxEarlyStatus));
- netdev_dbg(dev, "Chip config %02x %02x\n",
- NETDRV_R8(Config0), NETDRV_R8(Config1));
-
- tp->timer.expires = jiffies + next_tick;
- add_timer(&tp->timer);
-}
-
-
-static void netdrv_tx_clear(struct net_device *dev)
-{
- int i;
- struct netdrv_private *tp = netdev_priv(dev);
-
- atomic_set(&tp->cur_tx, 0);
- atomic_set(&tp->dirty_tx, 0);
-
- /* Dump the unsent Tx packets. */
- for (i = 0; i < NUM_TX_DESC; i++) {
- struct ring_info *rp = &tp->tx_info[i];
- if (rp->mapping != 0) {
- pci_unmap_single(tp->pci_dev, rp->mapping,
- rp->skb->len, PCI_DMA_TODEVICE);
- rp->mapping = 0;
- }
- if (rp->skb) {
- dev_kfree_skb(rp->skb);
- rp->skb = NULL;
- dev->stats.tx_dropped++;
- }
- }
-}
-
-
-static void netdrv_tx_timeout(struct net_device *dev)
-{
- struct netdrv_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
- int i;
- u8 tmp8;
- unsigned long flags;
-
- netdev_dbg(dev, "Transmit timeout, status %02x %04x media %02x\n",
- NETDRV_R8(ChipCmd),
- NETDRV_R16(IntrStatus),
- NETDRV_R8(MediaStatus));
-
- /* disable Tx ASAP, if not already */
- tmp8 = NETDRV_R8(ChipCmd);
- if (tmp8 & CmdTxEnb)
- NETDRV_W8(ChipCmd, tmp8 & ~CmdTxEnb);
-
- /* Disable interrupts by clearing the interrupt mask. */
- NETDRV_W16(IntrMask, 0x0000);
-
- /* Emit info to figure out what went wrong. */
- netdev_dbg(dev, "Tx queue start entry %d dirty entry %d\n",
- atomic_read(&tp->cur_tx),
- atomic_read(&tp->dirty_tx));
- for (i = 0; i < NUM_TX_DESC; i++)
- netdev_dbg(dev, "Tx descriptor %d is %08lx%s\n",
- i, NETDRV_R32(TxStatus0 + (i * 4)),
- i == atomic_read(&tp->dirty_tx) % NUM_TX_DESC ?
- "(queue head)" : "");
-
- /* Stop a shared interrupt from scavenging while we are. */
- spin_lock_irqsave(&tp->lock, flags);
-
- netdrv_tx_clear(dev);
-
- spin_unlock_irqrestore(&tp->lock, flags);
-
- /* ...and finally, reset everything */
- netdrv_hw_start(dev);
-
- netif_wake_queue(dev);
-}
-
-
-
-static int netdrv_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct netdrv_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
- int entry;
-
- /* Calculate the next Tx descriptor entry. */
- entry = atomic_read(&tp->cur_tx) % NUM_TX_DESC;
-
- assert(tp->tx_info[entry].skb == NULL);
- assert(tp->tx_info[entry].mapping == 0);
-
- tp->tx_info[entry].skb = skb;
- /* tp->tx_info[entry].mapping = 0; */
- skb_copy_from_linear_data(skb, tp->tx_buf[entry], skb->len);
-
- /* Note: the chip doesn't have auto-pad! */
- NETDRV_W32(TxStatus0 + (entry * sizeof(u32)),
- tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
-
- atomic_inc(&tp->cur_tx);
- if ((atomic_read(&tp->cur_tx) - atomic_read(&tp->dirty_tx)) >= NUM_TX_DESC)
- netif_stop_queue(dev);
-
- netdev_dbg(dev, "Queued Tx packet at %p size %u to slot %d\n",
- skb->data, skb->len, entry);
-
- return NETDEV_TX_OK;
-}
-
-
-static void netdrv_tx_interrupt(struct net_device *dev,
- struct netdrv_private *tp,
- void *ioaddr)
-{
- int cur_tx, dirty_tx, tx_left;
-
- assert(dev != NULL);
- assert(tp != NULL);
- assert(ioaddr != NULL);
-
- dirty_tx = atomic_read(&tp->dirty_tx);
-
- cur_tx = atomic_read(&tp->cur_tx);
- tx_left = cur_tx - dirty_tx;
- while (tx_left > 0) {
- int entry = dirty_tx % NUM_TX_DESC;
- int txstatus;
-
- txstatus = NETDRV_R32(TxStatus0 + (entry * sizeof(u32)));
-
- if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted)))
- break; /* It still hasn't been Txed */
-
- /* Note: TxCarrierLost is always asserted at 100mbps. */
- if (txstatus & (TxOutOfWindow | TxAborted)) {
- /* There was an major error, log it. */
- netdev_dbg(dev, "Transmit error, Tx status %#08x\n",
- txstatus);
- dev->stats.tx_errors++;
- if (txstatus & TxAborted) {
- dev->stats.tx_aborted_errors++;
- NETDRV_W32(TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift));
- }
- if (txstatus & TxCarrierLost)
- dev->stats.tx_carrier_errors++;
- if (txstatus & TxOutOfWindow)
- dev->stats.tx_window_errors++;
- } else {
- if (txstatus & TxUnderrun) {
- /* Add 64 to the Tx FIFO threshold. */
- if (tp->tx_flag < 0x00300000)
- tp->tx_flag += 0x00020000;
- dev->stats.tx_fifo_errors++;
- }
- dev->stats.collisions += (txstatus >> 24) & 15;
- dev->stats.tx_bytes += txstatus & 0x7ff;
- dev->stats.tx_packets++;
- }
-
- /* Free the original skb. */
- if (tp->tx_info[entry].mapping != 0) {
- pci_unmap_single(tp->pci_dev,
- tp->tx_info[entry].mapping,
- tp->tx_info[entry].skb->len,
- PCI_DMA_TODEVICE);
- tp->tx_info[entry].mapping = 0;
- }
- dev_kfree_skb_irq(tp->tx_info[entry].skb);
- tp->tx_info[entry].skb = NULL;
- dirty_tx++;
- if (dirty_tx < 0) { /* handle signed int overflow */
- atomic_sub(cur_tx, &tp->cur_tx); /* XXX racy? */
- dirty_tx = cur_tx - tx_left + 1;
- }
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
-
- cur_tx = atomic_read(&tp->cur_tx);
- tx_left = cur_tx - dirty_tx;
-
- }
-
-#ifndef NETDRV_NDEBUG
- if (atomic_read(&tp->cur_tx) - dirty_tx > NUM_TX_DESC) {
- netdev_err(dev, "Out-of-sync dirty pointer, %d vs. %d\n",
- dirty_tx, atomic_read(&tp->cur_tx));
- dirty_tx += NUM_TX_DESC;
- }
-#endif /* NETDRV_NDEBUG */
-
- atomic_set(&tp->dirty_tx, dirty_tx);
-}
-
-
-/* TODO: clean this up! Rx reset need not be this intensive */
-static void netdrv_rx_err(u32 rx_status, struct net_device *dev,
- struct netdrv_private *tp, void *ioaddr)
-{
- u8 tmp8;
- int tmp_work = 1000;
-
- netdev_dbg(dev, "Ethernet frame had errors, status %08x\n", rx_status);
- if (rx_status & RxTooLong)
- netdev_dbg(dev, "Oversized Ethernet frame, status %04x!\n",
- rx_status);
- /* A.C.: The chip hangs here. */
- dev->stats.rx_errors++;
- if (rx_status & (RxBadSymbol | RxBadAlign))
- dev->stats.rx_frame_errors++;
- if (rx_status & (RxRunt | RxTooLong))
- dev->stats.rx_length_errors++;
- if (rx_status & RxCRCErr)
- dev->stats.rx_crc_errors++;
- /* Reset the receiver, based on RealTek recommendation.(Bug?) */
- tp->cur_rx = 0;
-
- /* disable receive */
- tmp8 = NETDRV_R8(ChipCmd) & ChipCmdClear;
- NETDRV_W8_F(ChipCmd, tmp8 | CmdTxEnb);
-
- /* A.C.: Reset the multicast list. */
- netdrv_set_rx_mode(dev);
-
- /* XXX potentially temporary hack to
- * restart hung receiver */
- while (--tmp_work > 0) {
- tmp8 = NETDRV_R8(ChipCmd);
- if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))
- break;
- NETDRV_W8_F(ChipCmd,
- (tmp8 & ChipCmdClear) | CmdRxEnb | CmdTxEnb);
- }
-
- /* G.S.: Re-enable receiver */
- /* XXX temporary hack to work around receiver hang */
- netdrv_set_rx_mode(dev);
-
- if (tmp_work <= 0)
- netdev_warn(dev, "tx/rx enable wait too long\n");
-}
-
-
-/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the
- field alignments and semantics. */
-static void netdrv_rx_interrupt(struct net_device *dev,
- struct netdrv_private *tp, void *ioaddr)
-{
- unsigned char *rx_ring;
- u16 cur_rx;
-
- assert(dev != NULL);
- assert(tp != NULL);
- assert(ioaddr != NULL);
-
- rx_ring = tp->rx_ring;
- cur_rx = tp->cur_rx;
-
- netdev_dbg(dev, "In netdrv_rx(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n",
- cur_rx, NETDRV_R16(RxBufAddr),
- NETDRV_R16(RxBufPtr), NETDRV_R8(ChipCmd));
-
- while ((NETDRV_R8(ChipCmd) & RxBufEmpty) == 0) {
- int ring_offset = cur_rx % RX_BUF_LEN;
- u32 rx_status;
- unsigned int rx_size;
- unsigned int pkt_size;
- struct sk_buff *skb;
-
- /* read size+status of next frame from DMA ring buffer */
- rx_status = le32_to_cpu(*(u32 *)(rx_ring + ring_offset));
- rx_size = rx_status >> 16;
- pkt_size = rx_size - 4;
-
- netdev_dbg(dev, "netdrv_rx() status %04x, size %04x, cur %04x\n",
- rx_status, rx_size, cur_rx);
-#if defined(NETDRV_DEBUG) && (NETDRV_DEBUG > 2)
- print_hex_dump_bytes("Frame contents: ", HEX_DUMP_OFFSET,
- &rx_ring[ring_offset], 70);
-#endif
-
- /* If Rx err or invalid rx_size/rx_status received
- *(which happens if we get lost in the ring),
- * Rx process gets reset, so we abort any further
- * Rx processing.
- */
- if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
- (!(rx_status & RxStatusOK))) {
- netdrv_rx_err(rx_status, dev, tp, ioaddr);
- return;
- }
-
- /* Malloc up new buffer, compatible with net-2e. */
- /* Omit the four octet CRC from the length. */
-
- /* TODO: consider allocating skb's outside of
- * interrupt context, both to speed interrupt processing,
- * and also to reduce the chances of having to
- * drop packets here under memory pressure.
- */
-
- skb = dev_alloc_skb(pkt_size + 2);
- if (skb) {
- skb_reserve(skb, 2); /* 16 byte align the IP fields. */
-
- skb_copy_to_linear_data(skb, &rx_ring[ring_offset + 4], pkt_size);
- skb_put(skb, pkt_size);
-
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->stats.rx_bytes += pkt_size;
- dev->stats.rx_packets++;
- } else {
- netdev_warn(dev, "Memory squeeze, dropping packet\n");
- dev->stats.rx_dropped++;
- }
-
- cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
- NETDRV_W16_F(RxBufPtr, cur_rx - 16);
- }
-
- netdev_dbg(dev, "Done netdrv_rx(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n",
- cur_rx, NETDRV_R16(RxBufAddr),
- NETDRV_R16(RxBufPtr), NETDRV_R8(ChipCmd));
-
- tp->cur_rx = cur_rx;
-}
-
-
-static void netdrv_weird_interrupt(struct net_device *dev,
- struct netdrv_private *tp,
- void *ioaddr,
- int status, int link_changed)
-{
- netdev_printk(KERN_DEBUG, dev, "Abnormal interrupt, status %08x\n",
- status);
-
- assert(dev != NULL);
- assert(tp != NULL);
- assert(ioaddr != NULL);
-
- /* Update the error count. */
- dev->stats.rx_missed_errors += NETDRV_R32(RxMissed);
- NETDRV_W32(RxMissed, 0);
-
- if ((status & RxUnderrun) && link_changed &&
- (tp->drv_flags & HAS_LNK_CHNG)) {
- /* Really link-change on new chips. */
- int lpar = NETDRV_R16(NWayLPAR);
- int duplex = ((lpar & 0x0100) || (lpar & 0x01C0) == 0x0040 ||
- tp->duplex_lock);
- if (tp->full_duplex != duplex) {
- tp->full_duplex = duplex;
- NETDRV_W8(Cfg9346, Cfg9346_Unlock);
- NETDRV_W8(Config1, tp->full_duplex ? 0x60 : 0x20);
- NETDRV_W8(Cfg9346, Cfg9346_Lock);
- }
- status &= ~RxUnderrun;
- }
-
- /* XXX along with netdrv_rx_err, are we double-counting errors? */
- if (status & (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
- dev->stats.rx_errors++;
-
- if (status & (PCSTimeout))
- dev->stats.rx_length_errors++;
- if (status & (RxUnderrun | RxFIFOOver))
- dev->stats.rx_fifo_errors++;
- if (status & RxOverflow) {
- dev->stats.rx_over_errors++;
- tp->cur_rx = NETDRV_R16(RxBufAddr) % RX_BUF_LEN;
- NETDRV_W16_F(RxBufPtr, tp->cur_rx - 16);
- }
- if (status & PCIErr) {
- u16 pci_cmd_status;
- pci_read_config_word(tp->pci_dev, PCI_STATUS, &pci_cmd_status);
-
- netdev_err(dev, "PCI Bus error %04x\n", pci_cmd_status);
- }
-}
-
-
-/* The interrupt handler does all of the Rx thread work and cleans up
- after the Tx thread. */
-static irqreturn_t netdrv_interrupt(int irq, void *dev_instance)
-{
- struct net_device *dev = (struct net_device *) dev_instance;
- struct netdrv_private *tp = netdev_priv(dev);
- int boguscnt = max_interrupt_work;
- void *ioaddr = tp->mmio_addr;
- int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */
- int handled = 0;
-
- spin_lock(&tp->lock);
-
- do {
- status = NETDRV_R16(IntrStatus);
-
- /* h/w no longer present(hotplug?) or major error, bail */
- if (status == 0xFFFF)
- break;
-
- handled = 1;
- /* Acknowledge all of the current interrupt sources ASAP */
- NETDRV_W16_F(IntrStatus, status);
-
- netdev_dbg(dev, "interrupt status=%#04x new intstat=%#04x\n",
- status, NETDRV_R16(IntrStatus));
-
- if ((status &
- (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
- RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0)
- break;
-
- /* Check uncommon events with one test. */
- if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
- RxFIFOOver | TxErr | RxErr))
- netdrv_weird_interrupt(dev, tp, ioaddr,
- status, link_changed);
-
- if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) /* Rx interrupt */
- netdrv_rx_interrupt(dev, tp, ioaddr);
-
- if (status & (TxOK | TxErr))
- netdrv_tx_interrupt(dev, tp, ioaddr);
-
- boguscnt--;
- } while (boguscnt > 0);
-
- if (boguscnt <= 0) {
- netdev_warn(dev, "Too much work at interrupt, IntrStatus=%#04x\n",
- status);
-
- /* Clear all interrupt sources. */
- NETDRV_W16(IntrStatus, 0xffff);
- }
-
- spin_unlock(&tp->lock);
-
- netdev_dbg(dev, "exiting interrupt, intr_status=%#04x\n",
- NETDRV_R16(IntrStatus));
- return IRQ_RETVAL(handled);
-}
-
-
-static int netdrv_close(struct net_device *dev)
-{
- struct netdrv_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
- unsigned long flags;
-
- DPRINTK("ENTER\n");
-
- netif_stop_queue(dev);
-
- netdev_dbg(dev, "Shutting down ethercard, status was %#04x\n",
- NETDRV_R16(IntrStatus));
-
- del_timer_sync(&tp->timer);
-
- spin_lock_irqsave(&tp->lock, flags);
-
- /* Stop the chip's Tx and Rx DMA processes. */
- NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear));
-
- /* Disable interrupts by clearing the interrupt mask. */
- NETDRV_W16(IntrMask, 0x0000);
-
- /* Update the error counts. */
- dev->stats.rx_missed_errors += NETDRV_R32(RxMissed);
- NETDRV_W32(RxMissed, 0);
-
- spin_unlock_irqrestore(&tp->lock, flags);
-
- free_irq(dev->irq, dev);
-
- netdrv_tx_clear(dev);
-
- pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
- tp->rx_ring, tp->rx_ring_dma);
- pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
- tp->tx_bufs, tp->tx_bufs_dma);
- tp->rx_ring = NULL;
- tp->tx_bufs = NULL;
-
- /* Green! Put the chip in low-power mode. */
- NETDRV_W8(Cfg9346, Cfg9346_Unlock);
- NETDRV_W8(Config1, 0x03);
- NETDRV_W8(Cfg9346, Cfg9346_Lock);
-
- DPRINTK("EXIT\n");
- return 0;
-}
-
-
-static int netdrv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct netdrv_private *tp = netdev_priv(dev);
- struct mii_ioctl_data *data = if_mii(rq);
- unsigned long flags;
- int rc = 0;
-
- DPRINTK("ENTER\n");
-
- switch (cmd) {
- case SIOCGMIIPHY: /* Get address of MII PHY in use. */
- data->phy_id = tp->phys[0] & 0x3f;
- /* Fall Through */
-
- case SIOCGMIIREG: /* Read MII PHY register. */
- spin_lock_irqsave(&tp->lock, flags);
- data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
- spin_unlock_irqrestore(&tp->lock, flags);
- break;
-
- case SIOCSMIIREG: /* Write MII PHY register. */
- spin_lock_irqsave(&tp->lock, flags);
- mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
- spin_unlock_irqrestore(&tp->lock, flags);
- break;
-
- default:
- rc = -EOPNOTSUPP;
- break;
- }
-
- DPRINTK("EXIT, returning %d\n", rc);
- return rc;
-}
-
-/* Set or clear the multicast filter for this adaptor.
- This routine is not state sensitive and need not be SMP locked. */
-
-static void netdrv_set_rx_mode(struct net_device *dev)
-{
- struct netdrv_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
- u32 mc_filter[2]; /* Multicast hash filter */
- int rx_mode;
- u32 tmp;
-
- DPRINTK("ENTER\n");
-
- netdev_dbg(dev, "%s(%04x) done -- Rx config %08lx\n",
- __func__, dev->flags, NETDRV_R32(RxConfig));
-
- /* Note: do not reorder, GCC is clever about common statements. */
- if (dev->flags & IFF_PROMISC) {
- rx_mode =
- AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
- AcceptAllPhys;
- mc_filter[1] = mc_filter[0] = 0xffffffff;
- } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
- (dev->flags & IFF_ALLMULTI)) {
- /* Too many to filter perfectly -- accept all multicasts. */
- rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
- mc_filter[1] = mc_filter[0] = 0xffffffff;
- } else {
- struct netdev_hw_addr *ha;
-
- rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
- mc_filter[1] = mc_filter[0] = 0;
- netdev_for_each_mc_addr(ha, dev) {
- int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
-
- mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
- }
- }
-
- /* if called from irq handler, lock already acquired */
- if (!in_irq())
- spin_lock_irq(&tp->lock);
-
- /* We can safely update without stopping the chip. */
- tmp = netdrv_rx_config | rx_mode |
- (NETDRV_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
- NETDRV_W32_F(RxConfig, tmp);
- NETDRV_W32_F(MAR0 + 0, mc_filter[0]);
- NETDRV_W32_F(MAR0 + 4, mc_filter[1]);
-
- if (!in_irq())
- spin_unlock_irq(&tp->lock);
-
- DPRINTK("EXIT\n");
-}
-
-
-#ifdef CONFIG_PM
-
-static int netdrv_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct netdrv_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
- unsigned long flags;
-
- if (!netif_running(dev))
- return 0;
- netif_device_detach(dev);
-
- spin_lock_irqsave(&tp->lock, flags);
-
- /* Disable interrupts, stop Tx and Rx. */
- NETDRV_W16(IntrMask, 0x0000);
- NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear));
-
- /* Update the error counts. */
- dev->stats.rx_missed_errors += NETDRV_R32(RxMissed);
- NETDRV_W32(RxMissed, 0);
-
- spin_unlock_irqrestore(&tp->lock, flags);
-
- pci_save_state(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
-
- return 0;
-}
-
-
-static int netdrv_resume(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- /*struct netdrv_private *tp = netdev_priv(dev);*/
-
- if (!netif_running(dev))
- return 0;
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- netif_device_attach(dev);
- netdrv_hw_start(dev);
-
- return 0;
-}
-
-#endif /* CONFIG_PM */
-
-
-static struct pci_driver netdrv_pci_driver = {
- .name = MODNAME,
- .id_table = netdrv_pci_tbl,
- .probe = netdrv_init_one,
- .remove = __devexit_p(netdrv_remove_one),
-#ifdef CONFIG_PM
- .suspend = netdrv_suspend,
- .resume = netdrv_resume,
-#endif /* CONFIG_PM */
-};
-
-
-static int __init netdrv_init_module(void)
-{
-/* when a module, this is printed whether or not devices are found in probe */
-#ifdef MODULE
- printk(version);
-#endif
- return pci_register_driver(&netdrv_pci_driver);
-}
-
-
-static void __exit netdrv_cleanup_module(void)
-{
- pci_unregister_driver(&netdrv_pci_driver);
-}
-
-
-module_init(netdrv_init_module);
-module_exit(netdrv_cleanup_module);
diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig
deleted file mode 100644
index 9b8f793b1cc8..000000000000
--- a/drivers/net/pcmcia/Kconfig
+++ /dev/null
@@ -1,123 +0,0 @@
-#
-# PCMCIA Network device configuration
-#
-
-menuconfig NET_PCMCIA
- bool "PCMCIA network device support"
- depends on PCMCIA
- ---help---
- Say Y if you would like to include support for any PCMCIA or CardBus
- network adapters, then say Y to the driver for your particular card
- below. PCMCIA- or PC-cards are credit-card size devices often used
- with laptops computers; CardBus is the newer and faster version of
- PCMCIA.
-
- To use your PC-cards, you will need supporting software from David
- Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
- for location). You also want to check out the PCMCIA-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- If unsure, say N.
-
-if NET_PCMCIA && PCMCIA
-
-config PCMCIA_3C589
- tristate "3Com 3c589 PCMCIA support"
- help
- Say Y here if you intend to attach a 3Com 3c589 or compatible PCMCIA
- (PC-card) Ethernet card to your computer.
-
- To compile this driver as a module, choose M here: the module will be
- called 3c589_cs. If unsure, say N.
-
-config PCMCIA_3C574
- tristate "3Com 3c574 PCMCIA support"
- help
- Say Y here if you intend to attach a 3Com 3c574 or compatible PCMCIA
- (PC-card) Fast Ethernet card to your computer.
-
- To compile this driver as a module, choose M here: the module will be
- called 3c574_cs. If unsure, say N.
-
-config PCMCIA_FMVJ18X
- tristate "Fujitsu FMV-J18x PCMCIA support"
- select CRC32
- help
- Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible
- PCMCIA (PC-card) Ethernet card to your computer.
-
- To compile this driver as a module, choose M here: the module will be
- called fmvj18x_cs. If unsure, say N.
-
-config PCMCIA_PCNET
- tristate "NE2000 compatible PCMCIA support"
- select CRC32
- help
- Say Y here if you intend to attach an NE2000 compatible PCMCIA
- (PC-card) Ethernet or Fast Ethernet card to your computer.
-
- To compile this driver as a module, choose M here: the module will be
- called pcnet_cs. If unsure, say N.
-
-config PCMCIA_NMCLAN
- tristate "New Media PCMCIA support"
- help
- Say Y here if you intend to attach a New Media Ethernet or LiveWire
- PCMCIA (PC-card) Ethernet card to your computer.
-
- To compile this driver as a module, choose M here: the module will be
- called nmclan_cs. If unsure, say N.
-
-config PCMCIA_SMC91C92
- tristate "SMC 91Cxx PCMCIA support"
- select CRC32
- select MII
- help
- Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA
- (PC-card) Ethernet or Fast Ethernet card to your computer.
-
- To compile this driver as a module, choose M here: the module will be
- called smc91c92_cs. If unsure, say N.
-
-config PCMCIA_XIRC2PS
- tristate "Xircom 16-bit PCMCIA support"
- help
- Say Y here if you intend to attach a Xircom 16-bit PCMCIA (PC-card)
- Ethernet or Fast Ethernet card to your computer.
-
- To compile this driver as a module, choose M here: the module will be
- called xirc2ps_cs. If unsure, say N.
-
-config PCMCIA_AXNET
- tristate "Asix AX88190 PCMCIA support"
- ---help---
- Say Y here if you intend to attach an Asix AX88190-based PCMCIA
- (PC-card) Fast Ethernet card to your computer. These cards are
- nearly NE2000 compatible but need a separate driver due to a few
- misfeatures.
-
- To compile this driver as a module, choose M here: the module will be
- called axnet_cs. If unsure, say N.
-
-config ARCNET_COM20020_CS
- tristate "COM20020 ARCnet PCMCIA support"
- depends on ARCNET_COM20020
- help
- Say Y here if you intend to attach this type of ARCnet PCMCIA card
- to your computer.
-
- To compile this driver as a module, choose M here: the module will be
- called com20020_cs. If unsure, say N.
-
-config PCMCIA_IBMTR
- tristate "IBM PCMCIA tokenring adapter support"
- depends on IBMTR!=y && TR
- help
- Say Y here if you intend to attach this type of Token Ring PCMCIA
- card to your computer. You then also need to say Y to "Token Ring
- driver support".
-
- To compile this driver as a module, choose M here: the module will be
- called ibmtr_cs.
-
-endif # NET_PCMCIA
diff --git a/drivers/net/pcmcia/Makefile b/drivers/net/pcmcia/Makefile
deleted file mode 100644
index 87d2d99f4c14..000000000000
--- a/drivers/net/pcmcia/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# Makefile for the Linux PCMCIA network device drivers.
-#
-
-# 16-bit client drivers
-obj-$(CONFIG_PCMCIA_3C589) += 3c589_cs.o
-obj-$(CONFIG_PCMCIA_3C574) += 3c574_cs.o
-obj-$(CONFIG_PCMCIA_FMVJ18X) += fmvj18x_cs.o
-obj-$(CONFIG_PCMCIA_NMCLAN) += nmclan_cs.o
-obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o
-obj-$(CONFIG_PCMCIA_SMC91C92) += smc91c92_cs.o
-obj-$(CONFIG_PCMCIA_XIRC2PS) += xirc2ps_cs.o
-obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o
-obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o
-
-obj-$(CONFIG_PCMCIA_IBMTR) += ibmtr_cs.o
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index a70244306c94..bb88e12101c7 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -3,7 +3,7 @@
#
menuconfig PHYLIB
- tristate "PHY Device support and infrastructure"
+ bool "PHY Device support and infrastructure"
depends on !S390
depends on NETDEVICES
help
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index d84c4224dd12..e8be47d6d7d0 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -553,7 +553,7 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
/*
* There is no BCM5481 specification available, so down
* here is everything we know about "register 0x18". This
- * at least helps BCM5481 to successfuly receive packets
+ * at least helps BCM5481 to successfully receive packets
* on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
* says: "This sets delay between the RXD and RXC signals
* instead of using trace lengths to achieve timing".
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index edd7304773eb..9663e0ba6003 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -35,16 +35,15 @@
#define LAYER4 0x02
#define LAYER2 0x01
#define MAX_RXTS 64
-#define N_EXT_TS 1
+#define N_EXT_TS 6
#define PSF_PTPVER 2
#define PSF_EVNT 0x4000
#define PSF_RX 0x2000
#define PSF_TX 0x1000
#define EXT_EVENT 1
-#define EXT_GPIO 1
-#define CAL_EVENT 2
-#define CAL_GPIO 9
-#define CAL_TRIGGER 2
+#define CAL_EVENT 7
+#define CAL_TRIGGER 7
+#define PER_TRIGGER 6
/* phyter seems to miss the mark by 16 ns */
#define ADJTIME_FIX 16
@@ -131,16 +130,30 @@ struct dp83640_clock {
/* globals */
+enum {
+ CALIBRATE_GPIO,
+ PEROUT_GPIO,
+ EXTTS0_GPIO,
+ EXTTS1_GPIO,
+ EXTTS2_GPIO,
+ EXTTS3_GPIO,
+ EXTTS4_GPIO,
+ EXTTS5_GPIO,
+ GPIO_TABLE_SIZE
+};
+
static int chosen_phy = -1;
-static ushort cal_gpio = 4;
+static ushort gpio_tab[GPIO_TABLE_SIZE] = {
+ 1, 2, 3, 4, 8, 9, 10, 11
+};
module_param(chosen_phy, int, 0444);
-module_param(cal_gpio, ushort, 0444);
+module_param_array(gpio_tab, ushort, NULL, 0444);
MODULE_PARM_DESC(chosen_phy, \
"The address of the PHY to use for the ancillary clock features");
-MODULE_PARM_DESC(cal_gpio, \
- "Which GPIO line to use for synchronizing multiple PHYs");
+MODULE_PARM_DESC(gpio_tab, \
+ "Which GPIO line to use for which purpose: cal,perout,extts1,...,extts6");
/* a list of clocks and a mutex to protect it */
static LIST_HEAD(phyter_clocks);
@@ -235,6 +248,61 @@ static u64 phy2txts(struct phy_txts *p)
return ns;
}
+static void periodic_output(struct dp83640_clock *clock,
+ struct ptp_clock_request *clkreq, bool on)
+{
+ struct dp83640_private *dp83640 = clock->chosen;
+ struct phy_device *phydev = dp83640->phydev;
+ u32 sec, nsec, period;
+ u16 gpio, ptp_trig, trigger, val;
+
+ gpio = on ? gpio_tab[PEROUT_GPIO] : 0;
+ trigger = PER_TRIGGER;
+
+ ptp_trig = TRIG_WR |
+ (trigger & TRIG_CSEL_MASK) << TRIG_CSEL_SHIFT |
+ (gpio & TRIG_GPIO_MASK) << TRIG_GPIO_SHIFT |
+ TRIG_PER |
+ TRIG_PULSE;
+
+ val = (trigger & TRIG_SEL_MASK) << TRIG_SEL_SHIFT;
+
+ if (!on) {
+ val |= TRIG_DIS;
+ mutex_lock(&clock->extreg_lock);
+ ext_write(0, phydev, PAGE5, PTP_TRIG, ptp_trig);
+ ext_write(0, phydev, PAGE4, PTP_CTL, val);
+ mutex_unlock(&clock->extreg_lock);
+ return;
+ }
+
+ sec = clkreq->perout.start.sec;
+ nsec = clkreq->perout.start.nsec;
+ period = clkreq->perout.period.sec * 1000000000UL;
+ period += clkreq->perout.period.nsec;
+
+ mutex_lock(&clock->extreg_lock);
+
+ ext_write(0, phydev, PAGE5, PTP_TRIG, ptp_trig);
+
+ /*load trigger*/
+ val |= TRIG_LOAD;
+ ext_write(0, phydev, PAGE4, PTP_CTL, val);
+ ext_write(0, phydev, PAGE4, PTP_TDR, nsec & 0xffff); /* ns[15:0] */
+ ext_write(0, phydev, PAGE4, PTP_TDR, nsec >> 16); /* ns[31:16] */
+ ext_write(0, phydev, PAGE4, PTP_TDR, sec & 0xffff); /* sec[15:0] */
+ ext_write(0, phydev, PAGE4, PTP_TDR, sec >> 16); /* sec[31:16] */
+ ext_write(0, phydev, PAGE4, PTP_TDR, period & 0xffff); /* ns[15:0] */
+ ext_write(0, phydev, PAGE4, PTP_TDR, period >> 16); /* ns[31:16] */
+
+ /*enable trigger*/
+ val &= ~TRIG_LOAD;
+ val |= TRIG_EN;
+ ext_write(0, phydev, PAGE4, PTP_CTL, val);
+
+ mutex_unlock(&clock->extreg_lock);
+}
+
/* ptp clock methods */
static int ptp_dp83640_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
@@ -338,19 +406,30 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
struct dp83640_clock *clock =
container_of(ptp, struct dp83640_clock, caps);
struct phy_device *phydev = clock->chosen->phydev;
- u16 evnt;
+ int index;
+ u16 evnt, event_num, gpio_num;
switch (rq->type) {
case PTP_CLK_REQ_EXTTS:
- if (rq->extts.index != 0)
+ index = rq->extts.index;
+ if (index < 0 || index >= N_EXT_TS)
return -EINVAL;
- evnt = EVNT_WR | (EXT_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
+ event_num = EXT_EVENT + index;
+ evnt = EVNT_WR | (event_num & EVNT_SEL_MASK) << EVNT_SEL_SHIFT;
if (on) {
- evnt |= (EXT_GPIO & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
+ gpio_num = gpio_tab[EXTTS0_GPIO + index];
+ evnt |= (gpio_num & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
evnt |= EVNT_RISE;
}
ext_write(0, phydev, PAGE5, PTP_EVNT, evnt);
return 0;
+
+ case PTP_CLK_REQ_PEROUT:
+ if (rq->perout.index != 0)
+ return -EINVAL;
+ periodic_output(clock, rq, on);
+ return 0;
+
default:
break;
}
@@ -441,9 +520,10 @@ static void recalibrate(struct dp83640_clock *clock)
struct list_head *this;
struct dp83640_private *tmp;
struct phy_device *master = clock->chosen->phydev;
- u16 cfg0, evnt, ptp_trig, trigger, val;
+ u16 cal_gpio, cfg0, evnt, ptp_trig, trigger, val;
trigger = CAL_TRIGGER;
+ cal_gpio = gpio_tab[CALIBRATE_GPIO];
mutex_lock(&clock->extreg_lock);
@@ -542,11 +622,17 @@ static void recalibrate(struct dp83640_clock *clock)
/* time stamping methods */
+static inline u16 exts_chan_to_edata(int ch)
+{
+ return 1 << ((ch + EXT_EVENT) * 2);
+}
+
static int decode_evnt(struct dp83640_private *dp83640,
void *data, u16 ests)
{
struct phy_txts *phy_txts;
struct ptp_clock_event event;
+ int i, parsed;
int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK;
u16 ext_status = 0;
@@ -568,14 +654,25 @@ static int decode_evnt(struct dp83640_private *dp83640,
dp83640->edata.ns_lo = phy_txts->ns_lo;
}
+ if (ext_status) {
+ parsed = words + 2;
+ } else {
+ parsed = words + 1;
+ i = ((ests >> EVNT_NUM_SHIFT) & EVNT_NUM_MASK) - EXT_EVENT;
+ ext_status = exts_chan_to_edata(i);
+ }
+
event.type = PTP_CLOCK_EXTTS;
- event.index = 0;
event.timestamp = phy2txts(&dp83640->edata);
- ptp_clock_event(dp83640->clock->ptp_clock, &event);
+ for (i = 0; i < N_EXT_TS; i++) {
+ if (ext_status & exts_chan_to_edata(i)) {
+ event.index = i;
+ ptp_clock_event(dp83640->clock->ptp_clock, &event);
+ }
+ }
- words = ext_status ? words + 2 : words + 1;
- return words * sizeof(u16);
+ return parsed * sizeof(u16);
}
static void decode_rxts(struct dp83640_private *dp83640,
@@ -664,6 +761,41 @@ static void decode_status_frame(struct dp83640_private *dp83640,
}
}
+static int is_sync(struct sk_buff *skb, int type)
+{
+ u8 *data = skb->data, *msgtype;
+ unsigned int offset = 0;
+
+ switch (type) {
+ 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 (type & PTP_CLASS_V1)
+ offset += OFF_PTP_CONTROL;
+
+ if (skb->len < offset + 1)
+ return 0;
+
+ msgtype = data + offset;
+
+ return (*msgtype & 0xf) == 0;
+}
+
static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
{
u16 *seqid;
@@ -740,7 +872,7 @@ static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus)
clock->caps.max_adj = 1953124;
clock->caps.n_alarm = 0;
clock->caps.n_ext_ts = N_EXT_TS;
- clock->caps.n_per_out = 0;
+ clock->caps.n_per_out = 1;
clock->caps.pps = 0;
clock->caps.adjfreq = ptp_dp83640_adjfreq;
clock->caps.adjtime = ptp_dp83640_adjtime;
@@ -875,6 +1007,7 @@ static void dp83640_remove(struct phy_device *phydev)
struct dp83640_clock *clock;
struct list_head *this, *next;
struct dp83640_private *tmp, *dp83640 = phydev->priv;
+ struct sk_buff *skb;
if (phydev->addr == BROADCAST_ADDR)
return;
@@ -882,6 +1015,12 @@ static void dp83640_remove(struct phy_device *phydev)
enable_status_frames(phydev, false);
cancel_work_sync(&dp83640->ts_work);
+ while ((skb = skb_dequeue(&dp83640->rx_queue)) != NULL)
+ kfree_skb(skb);
+
+ while ((skb = skb_dequeue(&dp83640->tx_queue)) != NULL)
+ skb_complete_tx_timestamp(skb, NULL);
+
clock = dp83640_clock_get(dp83640->clock);
if (dp83640 == clock->chosen) {
@@ -913,16 +1052,10 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
if (cfg.flags) /* reserved for future extensions */
return -EINVAL;
- switch (cfg.tx_type) {
- case HWTSTAMP_TX_OFF:
- dp83640->hwts_tx_en = 0;
- break;
- case HWTSTAMP_TX_ON:
- dp83640->hwts_tx_en = 1;
- break;
- default:
+ if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ONESTEP_SYNC)
return -ERANGE;
- }
+
+ dp83640->hwts_tx_en = cfg.tx_type;
switch (cfg.rx_filter) {
case HWTSTAMP_FILTER_NONE:
@@ -977,6 +1110,9 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
if (dp83640->hwts_tx_en)
txcfg0 |= TX_TS_EN;
+ if (dp83640->hwts_tx_en == HWTSTAMP_TX_ONESTEP_SYNC)
+ txcfg0 |= SYNC_1STEP | CHK_1STEP;
+
if (dp83640->hwts_rx_en)
rxcfg0 |= RX_TS_EN;
@@ -1059,12 +1195,24 @@ static void dp83640_txtstamp(struct phy_device *phydev,
{
struct dp83640_private *dp83640 = phydev->priv;
- if (!dp83640->hwts_tx_en) {
- kfree_skb(skb);
- return;
+ switch (dp83640->hwts_tx_en) {
+
+ case HWTSTAMP_TX_ONESTEP_SYNC:
+ if (is_sync(skb, type)) {
+ skb_complete_tx_timestamp(skb, NULL);
+ return;
+ }
+ /* fall through */
+ case HWTSTAMP_TX_ON:
+ skb_queue_tail(&dp83640->tx_queue, skb);
+ schedule_work(&dp83640->ts_work);
+ break;
+
+ case HWTSTAMP_TX_OFF:
+ default:
+ skb_complete_tx_timestamp(skb, NULL);
+ break;
}
- skb_queue_tail(&dp83640->tx_queue, skb);
- schedule_work(&dp83640->ts_work);
}
static struct phy_driver dp83640_driver = {
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index d4cbc2922b23..c81f136ae670 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -30,10 +30,17 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
-MODULE_DESCRIPTION("ICPlus IP175C/IC1001 PHY drivers");
+MODULE_DESCRIPTION("ICPlus IP175C/IP101A/IC1001 PHY drivers");
MODULE_AUTHOR("Michael Barkowski");
MODULE_LICENSE("GPL");
+/* IP101A/IP1001 */
+#define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */
+#define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */
+#define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */
+#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
+#define IP101A_APS_ON 2 /* IP101A APS Mode bit */
+
static int ip175c_config_init(struct phy_device *phydev)
{
int err, i;
@@ -42,36 +49,36 @@ static int ip175c_config_init(struct phy_device *phydev)
if (full_reset_performed == 0) {
/* master reset */
- err = phydev->bus->write(phydev->bus, 30, 0, 0x175c);
+ err = mdiobus_write(phydev->bus, 30, 0, 0x175c);
if (err < 0)
return err;
/* ensure no bus delays overlap reset period */
- err = phydev->bus->read(phydev->bus, 30, 0);
+ err = mdiobus_read(phydev->bus, 30, 0);
/* data sheet specifies reset period is 2 msec */
mdelay(2);
/* enable IP175C mode */
- err = phydev->bus->write(phydev->bus, 29, 31, 0x175c);
+ err = mdiobus_write(phydev->bus, 29, 31, 0x175c);
if (err < 0)
return err;
/* Set MII0 speed and duplex (in PHY mode) */
- err = phydev->bus->write(phydev->bus, 29, 22, 0x420);
+ err = mdiobus_write(phydev->bus, 29, 22, 0x420);
if (err < 0)
return err;
/* reset switch ports */
for (i = 0; i < 5; i++) {
- err = phydev->bus->write(phydev->bus, i,
- MII_BMCR, BMCR_RESET);
+ err = mdiobus_write(phydev->bus, i,
+ MII_BMCR, BMCR_RESET);
if (err < 0)
return err;
}
for (i = 0; i < 5; i++)
- err = phydev->bus->read(phydev->bus, i, MII_BMCR);
+ err = mdiobus_read(phydev->bus, i, MII_BMCR);
mdelay(2);
@@ -89,27 +96,61 @@ static int ip175c_config_init(struct phy_device *phydev)
return 0;
}
-static int ip1001_config_init(struct phy_device *phydev)
+static int ip1xx_reset(struct phy_device *phydev)
{
- int err, value;
+ int err, bmcr;
/* Software Reset PHY */
- value = phy_read(phydev, MII_BMCR);
- value |= BMCR_RESET;
- err = phy_write(phydev, MII_BMCR, value);
+ bmcr = phy_read(phydev, MII_BMCR);
+ bmcr |= BMCR_RESET;
+ err = phy_write(phydev, MII_BMCR, bmcr);
if (err < 0)
return err;
do {
- value = phy_read(phydev, MII_BMCR);
- } while (value & BMCR_RESET);
+ bmcr = phy_read(phydev, MII_BMCR);
+ } while (bmcr & BMCR_RESET);
+
+ return err;
+}
+
+static int ip1001_config_init(struct phy_device *phydev)
+{
+ int c;
+
+ c = ip1xx_reset(phydev);
+ if (c < 0)
+ return c;
+
+ /* Enable Auto Power Saving mode */
+ c = phy_read(phydev, IP1001_SPEC_CTRL_STATUS_2);
+ c |= IP1001_APS_ON;
+ if (c < 0)
+ return c;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
+ /* Additional delay (2ns) used to adjust RX clock phase
+ * at RGMII interface */
+ c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
+ c |= IP1001_PHASE_SEL_MASK;
+ c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
+ }
+
+ return c;
+}
+
+static int ip101a_config_init(struct phy_device *phydev)
+{
+ int c;
- /* Additional delay (2ns) used to adjust RX clock phase
- * at GMII/ RGMII interface */
- value = phy_read(phydev, 16);
- value |= 0x3;
+ c = ip1xx_reset(phydev);
+ if (c < 0)
+ return c;
- return phy_write(phydev, 16, value);
+ /* Enable Auto Power Saving mode */
+ c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
+ c |= IP101A_APS_ON;
+ return c;
}
static int ip175c_read_status(struct phy_device *phydev)
@@ -158,6 +199,20 @@ static struct phy_driver ip1001_driver = {
.driver = { .owner = THIS_MODULE,},
};
+static struct phy_driver ip101a_driver = {
+ .phy_id = 0x02430c54,
+ .name = "ICPlus IP101A",
+ .phy_id_mask = 0x0ffffff0,
+ .features = PHY_BASIC_FEATURES | SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause,
+ .config_init = &ip101a_config_init,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .driver = { .owner = THIS_MODULE,},
+};
+
static int __init icplus_init(void)
{
int ret = 0;
@@ -166,12 +221,17 @@ static int __init icplus_init(void)
if (ret < 0)
return -ENODEV;
+ ret = phy_driver_register(&ip101a_driver);
+ if (ret < 0)
+ return -ENODEV;
+
return phy_driver_register(&ip175c_driver);
}
static void __exit icplus_exit(void)
{
phy_driver_unregister(&ip1001_driver);
+ phy_driver_unregister(&ip101a_driver);
phy_driver_unregister(&ip175c_driver);
}
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 47c8339a0359..2843c90f712f 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -241,7 +241,7 @@ MODULE_DEVICE_TABLE(of, mdio_ofgpio_match);
static struct platform_driver mdio_ofgpio_driver = {
.driver = {
- .name = "mdio-gpio",
+ .name = "mdio-ofgpio",
.owner = THIS_MODULE,
.of_match_table = mdio_ofgpio_match,
},
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index ff109fe5af6b..83a5a5afec67 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -213,7 +213,7 @@ int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
/* Grab the bits from PHYIR1, and put them
* in the upper half */
- phy_reg = bus->read(bus, addr, MII_PHYSID1);
+ phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);
if (phy_reg < 0)
return -EIO;
@@ -221,7 +221,7 @@ int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
*phy_id = (phy_reg & 0xffff) << 16;
/* Grab the bits from PHYIR2, and put them in the lower half */
- phy_reg = bus->read(bus, addr, MII_PHYSID2);
+ phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
if (phy_reg < 0)
return -EIO;
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 5d8f6e17bd55..0ec8e09cc2ac 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -3,7 +3,7 @@
*
* Author: Kriston Carson
*
- * Copyright (c) 2005 Freescale Semiconductor, Inc.
+ * Copyright (c) 2005, 2009 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -61,32 +61,42 @@ MODULE_DESCRIPTION("Vitesse PHY driver");
MODULE_AUTHOR("Kriston Carson");
MODULE_LICENSE("GPL");
-static int vsc824x_config_init(struct phy_device *phydev)
+int vsc824x_add_skew(struct phy_device *phydev)
{
- int extcon;
int err;
-
- err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT,
- MII_VSC8244_AUXCONSTAT_INIT);
- if (err < 0)
- return err;
+ int extcon;
extcon = phy_read(phydev, MII_VSC8244_EXT_CON1);
if (extcon < 0)
- return err;
+ return extcon;
extcon &= ~(MII_VSC8244_EXTCON1_TX_SKEW_MASK |
MII_VSC8244_EXTCON1_RX_SKEW_MASK);
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- extcon |= (MII_VSC8244_EXTCON1_TX_SKEW |
- MII_VSC8244_EXTCON1_RX_SKEW);
+ extcon |= (MII_VSC8244_EXTCON1_TX_SKEW |
+ MII_VSC8244_EXTCON1_RX_SKEW);
err = phy_write(phydev, MII_VSC8244_EXT_CON1, extcon);
return err;
}
+EXPORT_SYMBOL(vsc824x_add_skew);
+
+static int vsc824x_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT,
+ MII_VSC8244_AUXCONSTAT_INIT);
+ if (err < 0)
+ return err;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+ err = vsc824x_add_skew(phydev);
+
+ return err;
+}
static int vsc824x_ack_interrupt(struct phy_device *phydev)
{
diff --git a/drivers/net/plip/Kconfig b/drivers/net/plip/Kconfig
new file mode 100644
index 000000000000..80c4a3373e51
--- /dev/null
+++ b/drivers/net/plip/Kconfig
@@ -0,0 +1,38 @@
+#
+# Parallel Line Internet Protocol (PLIP) network device configuration
+#
+
+config PLIP
+ tristate "PLIP (parallel port) support"
+ depends on PARPORT
+ ---help---
+ PLIP (Parallel Line Internet Protocol) is used to create a
+ reasonably fast mini network consisting of two (or, rarely, more)
+ local machines. A PLIP link from a Linux box is a popular means to
+ install a Linux distribution on a machine which doesn't have a
+ CD-ROM drive (a minimal system has to be transferred with floppies
+ first). The kernels on both machines need to have this PLIP option
+ enabled for this to work.
+
+ The PLIP driver has two modes, mode 0 and mode 1. The parallel
+ ports (the connectors at the computers with 25 holes) are connected
+ with "null printer" or "Turbo Laplink" cables which can transmit 4
+ bits at a time (mode 0) or with special PLIP cables, to be used on
+ bidirectional parallel ports only, which can transmit 8 bits at a
+ time (mode 1); you can find the wiring of these cables in
+ <file:Documentation/networking/PLIP.txt>. The cables can be up to
+ 15m long. Mode 0 works also if one of the machines runs DOS/Windows
+ and has some PLIP software installed, e.g. the Crynwr PLIP packet
+ driver (<http://oak.oakland.edu/simtel.net/msdos/pktdrvr-pre.html>)
+ and winsock or NCSA's telnet.
+
+ If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well
+ as the NET-3-HOWTO, both available from
+ <http://www.tldp.org/docs.html#howto>. Note that the PLIP
+ protocol has been changed and this PLIP driver won't work together
+ with the PLIP support in Linux versions 1.0.x. This option enlarges
+ your kernel by about 8 KB.
+
+ To compile this driver as a module, choose M here. The module
+ will be called plip. If unsure, say Y or M, in case you buy
+ a laptop later.
diff --git a/drivers/net/plip/Makefile b/drivers/net/plip/Makefile
new file mode 100644
index 000000000000..ed958796dc64
--- /dev/null
+++ b/drivers/net/plip/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the PLIP network device drivers.
+#
+
+obj-$(CONFIG_PLIP) += plip.o
diff --git a/drivers/net/plip.c b/drivers/net/plip/plip.c
index a9e9ca8a86ed..a9e9ca8a86ed 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip/plip.c
diff --git a/drivers/net/ppp/Kconfig b/drivers/net/ppp/Kconfig
new file mode 100644
index 000000000000..872df3ef07a6
--- /dev/null
+++ b/drivers/net/ppp/Kconfig
@@ -0,0 +1,175 @@
+#
+# PPP network device configuration
+#
+
+config PPP
+ tristate "PPP (point-to-point protocol) support"
+ select SLHC
+ ---help---
+ PPP (Point to Point Protocol) is a newer and better SLIP. It serves
+ the same purpose: sending Internet traffic over telephone (and other
+ serial) lines. Ask your access provider if they support it, because
+ otherwise you can't use it; most Internet access providers these
+ days support PPP rather than SLIP.
+
+ To use PPP, you need an additional program called pppd as described
+ in the PPP-HOWTO, available at
+ <http://www.tldp.org/docs.html#howto>. Make sure that you have
+ the version of pppd recommended in <file:Documentation/Changes>.
+ The PPP option enlarges your kernel by about 16 KB.
+
+ There are actually two versions of PPP: the traditional PPP for
+ asynchronous lines, such as regular analog phone lines, and
+ synchronous PPP which can be used over digital ISDN lines for
+ example. If you want to use PPP over phone lines or other
+ asynchronous serial lines, you need to say Y (or M) here and also to
+ the next option, "PPP support for async serial ports". For PPP over
+ synchronous lines, you should say Y (or M) here and to "Support
+ synchronous PPP", below.
+
+ If you said Y to "Version information on all symbols" above, then
+ you cannot compile the PPP driver into the kernel; you can then only
+ compile it as a module. To compile this driver as a module, choose M
+ here. The module will be called ppp_generic.
+
+if PPP
+
+config PPP_BSDCOMP
+ tristate "PPP BSD-Compress compression"
+ depends on PPP
+ ---help---
+ Support for the BSD-Compress compression method for PPP, which uses
+ the LZW compression method to compress each PPP packet before it is
+ sent over the wire. The machine at the other end of the PPP link
+ (usually your ISP) has to support the BSD-Compress compression
+ method as well for this to be useful. Even if they don't support it,
+ it is safe to say Y here.
+
+ The PPP Deflate compression method ("PPP Deflate compression",
+ above) is preferable to BSD-Compress, because it compresses better
+ and is patent-free.
+
+ Note that the BSD compression code will always be compiled as a
+ module; it is called bsd_comp and will show up in the directory
+ modules once you have said "make modules". If unsure, say N.
+
+config PPP_DEFLATE
+ tristate "PPP Deflate compression"
+ depends on PPP
+ select ZLIB_INFLATE
+ select ZLIB_DEFLATE
+ ---help---
+ Support for the Deflate compression method for PPP, which uses the
+ Deflate algorithm (the same algorithm that gzip uses) to compress
+ each PPP packet before it is sent over the wire. The machine at the
+ other end of the PPP link (usually your ISP) has to support the
+ Deflate compression method as well for this to be useful. Even if
+ they don't support it, it is safe to say Y here.
+
+ To compile this driver as a module, choose M here.
+
+config PPP_FILTER
+ bool "PPP filtering"
+ depends on PPP
+ ---help---
+ Say Y here if you want to be able to filter the packets passing over
+ PPP interfaces. This allows you to control which packets count as
+ activity (i.e. which packets will reset the idle timer or bring up
+ a demand-dialed link) and which packets are to be dropped entirely.
+ You need to say Y here if you wish to use the pass-filter and
+ active-filter options to pppd.
+
+ If unsure, say N.
+
+config PPP_MPPE
+ tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)"
+ depends on PPP && EXPERIMENTAL
+ select CRYPTO
+ select CRYPTO_SHA1
+ select CRYPTO_ARC4
+ select CRYPTO_ECB
+ ---help---
+ Support for the MPPE Encryption protocol, as employed by the
+ Microsoft Point-to-Point Tunneling Protocol.
+
+ See http://pptpclient.sourceforge.net/ for information on
+ configuring PPTP clients and servers to utilize this method.
+
+config PPP_MULTILINK
+ bool "PPP multilink support (EXPERIMENTAL)"
+ depends on PPP && EXPERIMENTAL
+ ---help---
+ PPP multilink is a protocol (defined in RFC 1990) which allows you
+ to combine several (logical or physical) lines into one logical PPP
+ connection, so that you can utilize your full bandwidth.
+
+ This has to be supported at the other end as well and you need a
+ version of the pppd daemon which understands the multilink protocol.
+
+ If unsure, say N.
+
+config PPPOATM
+ tristate "PPP over ATM"
+ depends on ATM && PPP
+ ---help---
+ Support PPP (Point to Point Protocol) encapsulated in ATM frames.
+ This implementation does not yet comply with section 8 of RFC2364,
+ which can lead to bad results if the ATM peer loses state and
+ changes its encapsulation unilaterally.
+
+config PPPOE
+ tristate "PPP over Ethernet (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && PPP
+ ---help---
+ Support for PPP over Ethernet.
+
+ This driver requires the latest version of pppd from the CVS
+ repository at cvs.samba.org. Alternatively, see the
+ RoaringPenguin package (<http://www.roaringpenguin.com/pppoe>)
+ which contains instruction on how to use this driver (under
+ the heading "Kernel mode PPPoE").
+
+config PPTP
+ tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
+ ---help---
+ Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
+
+ This driver requires pppd plugin to work in client mode or
+ modified pptpd (poptop) to work in server mode.
+ See http://accel-pptp.sourceforge.net/ for information how to
+ utilize this module.
+
+config PPPOL2TP
+ tristate "PPP over L2TP (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && L2TP && PPP
+ ---help---
+ Support for PPP-over-L2TP socket family. L2TP is a protocol
+ used by ISPs and enterprises to tunnel PPP traffic over UDP
+ tunnels. L2TP is replacing PPTP for VPN uses.
+
+config PPP_ASYNC
+ tristate "PPP support for async serial ports"
+ depends on PPP
+ select CRC_CCITT
+ ---help---
+ Say Y (or M) here if you want to be able to use PPP over standard
+ asynchronous serial ports, such as COM1 or COM2 on a PC. If you use
+ a modem (not a synchronous or ISDN modem) to contact your ISP, you
+ need this option.
+
+ To compile this driver as a module, choose M here.
+
+ If unsure, say Y.
+
+config PPP_SYNC_TTY
+ tristate "PPP support for sync tty ports"
+ depends on PPP
+ ---help---
+ Say Y (or M) here if you want to be able to use PPP over synchronous
+ (HDLC) tty devices, such as the SyncLink adapter. These devices
+ are often used for high-speed leased lines like T1/E1.
+
+ To compile this driver as a module, choose M here.
+
+endif # PPP
diff --git a/drivers/net/ppp/Makefile b/drivers/net/ppp/Makefile
new file mode 100644
index 000000000000..a6b6297b0066
--- /dev/null
+++ b/drivers/net/ppp/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the Linux PPP network device drivers.
+#
+
+obj-$(CONFIG_PPP) += ppp_generic.o
+obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
+obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
+obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
+obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
+obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
+obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
+obj-$(CONFIG_PPPOL2TP) += pppox.o
+obj-$(CONFIG_PPTP) += pppox.o pptp.o
diff --git a/drivers/net/bsd_comp.c b/drivers/net/ppp/bsd_comp.c
index a9b759add187..a9b759add187 100644
--- a/drivers/net/bsd_comp.c
+++ b/drivers/net/ppp/bsd_comp.c
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp/ppp_async.c
index c6ba64380829..c6ba64380829 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp/ppp_async.c
diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp/ppp_deflate.c
index 1dbdf82a6dfd..1dbdf82a6dfd 100644
--- a/drivers/net/ppp_deflate.c
+++ b/drivers/net/ppp/ppp_deflate.c
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index edfa15d2e795..edfa15d2e795 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp/ppp_mppe.c
index 9a1849a83e2a..9a1849a83e2a 100644
--- a/drivers/net/ppp_mppe.c
+++ b/drivers/net/ppp/ppp_mppe.c
diff --git a/drivers/net/ppp_mppe.h b/drivers/net/ppp/ppp_mppe.h
index 7a14e058c668..7a14e058c668 100644
--- a/drivers/net/ppp_mppe.h
+++ b/drivers/net/ppp/ppp_mppe.h
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
index 736a39ee05bb..736a39ee05bb 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp/ppp_synctty.c
diff --git a/drivers/net/pppoe.c b/drivers/net/ppp/pppoe.c
index bc9a4bb31980..bc9a4bb31980 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
diff --git a/drivers/net/pppox.c b/drivers/net/ppp/pppox.c
index 8c0d170dabcd..8c0d170dabcd 100644
--- a/drivers/net/pppox.c
+++ b/drivers/net/ppp/pppox.c
diff --git a/drivers/net/pptp.c b/drivers/net/ppp/pptp.c
index 89f829f5f725..89f829f5f725 100644
--- a/drivers/net/pptp.c
+++ b/drivers/net/ppp/pptp.c
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 3bb131137033..7145714a5ec9 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -88,8 +88,8 @@ static struct rio_dev **rionet_active;
#define dev_rionet_capable(dev) \
is_rionet_capable(dev->src_ops, dev->dst_ops)
-#define RIONET_MAC_MATCH(x) (*(u32 *)x == 0x00010001)
-#define RIONET_GET_DESTID(x) (*(u16 *)(x + 4))
+#define RIONET_MAC_MATCH(x) (!memcmp((x), "\00\01\00\01", 4))
+#define RIONET_GET_DESTID(x) ((*((u8 *)x + 4) << 8) | *((u8 *)x + 5))
static int rionet_rx_clean(struct net_device *ndev)
{
diff --git a/drivers/net/slip/Kconfig b/drivers/net/slip/Kconfig
new file mode 100644
index 000000000000..211b160e4e9c
--- /dev/null
+++ b/drivers/net/slip/Kconfig
@@ -0,0 +1,79 @@
+#
+# SLIP network device configuration
+#
+
+config SLIP
+ tristate "SLIP (serial line) support"
+ ---help---
+ Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
+ connect to your Internet service provider or to connect to some
+ other local Unix box or if you want to configure your Linux box as a
+ Slip/CSlip server for other people to dial in. SLIP (Serial Line
+ Internet Protocol) is a protocol used to send Internet traffic over
+ serial connections such as telephone lines or null modem cables;
+ nowadays, the protocol PPP is more commonly used for this same
+ purpose.
+
+ Normally, your access provider has to support SLIP in order for you
+ to be able to use it, but there is now a SLIP emulator called SLiRP
+ around (available from
+ <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
+ allows you to use SLIP over a regular dial up shell connection. If
+ you plan to use SLiRP, make sure to say Y to CSLIP, below. The
+ NET-3-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, explains how to
+ configure SLIP. Note that you don't need this option if you just
+ want to run term (term is a program which gives you almost full
+ Internet connectivity if you have a regular dial up shell account on
+ some Internet connected Unix computer. Read
+ <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
+ support will enlarge your kernel by about 4 KB. If unsure, say N.
+
+ To compile this driver as a module, choose M here. The module
+ will be called slip.
+
+config SLHC
+ tristate
+ ---help---
+ This option enables Van Jacobsen serial line header compression
+ routines.
+
+if SLIP
+
+config SLIP_COMPRESSED
+ bool "CSLIP compressed headers"
+ depends on SLIP
+ select SLHC
+ ---help---
+ This protocol is faster than SLIP because it uses compression on the
+ TCP/IP headers (not on the data itself), but it has to be supported
+ on both ends. Ask your access provider if you are not sure and
+ answer Y, just in case. You will still be able to use plain SLIP. If
+ you plan to use SLiRP, the SLIP emulator (available from
+ <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
+ allows you to use SLIP over a regular dial up shell connection, you
+ definitely want to say Y here. The NET-3-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, explains how to configure
+ CSLIP. This won't enlarge your kernel.
+
+config SLIP_SMART
+ bool "Keepalive and linefill"
+ depends on SLIP
+ ---help---
+ Adds additional capabilities to the SLIP driver to support the
+ RELCOM line fill and keepalive monitoring. Ideal on poor quality
+ analogue lines.
+
+config SLIP_MODE_SLIP6
+ bool "Six bit SLIP encapsulation"
+ depends on SLIP
+ ---help---
+ Just occasionally you may need to run IP over hostile serial
+ networks that don't pass all control characters or are only seven
+ bit. Saying Y here adds an extra mode you can use with SLIP:
+ "slip6". In this mode, SLIP will only send normal ASCII symbols over
+ the serial device. Naturally, this has to be supported at the other
+ end of the link as well. It's good enough, for example, to run IP
+ over the async ports of a Camtec JNT Pad. If unsure, say N.
+
+endif # SLIP
diff --git a/drivers/net/slip/Makefile b/drivers/net/slip/Makefile
new file mode 100644
index 000000000000..e3ebc59e6fb9
--- /dev/null
+++ b/drivers/net/slip/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the SLIP network device drivers.
+#
+
+obj-$(CONFIG_SLIP) += slip.o
+obj-$(CONFIG_SLHC) += slhc.o
diff --git a/drivers/net/slhc.c b/drivers/net/slip/slhc.c
index 0a0a6643cf3a..0a0a6643cf3a 100644
--- a/drivers/net/slhc.c
+++ b/drivers/net/slip/slhc.c
diff --git a/drivers/net/slip.c b/drivers/net/slip/slip.c
index 4c617534f937..ba08341fb92c 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip/slip.c
@@ -562,34 +562,33 @@ static struct rtnl_link_stats64 *
sl_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
{
struct net_device_stats *devstats = &dev->stats;
- unsigned long c_rx_dropped = 0;
#ifdef SL_INCLUDE_CSLIP
- unsigned long c_rx_fifo_errors = 0;
- unsigned long c_tx_fifo_errors = 0;
- unsigned long c_collisions = 0;
struct slip *sl = netdev_priv(dev);
struct slcompress *comp = sl->slcomp;
-
- if (comp) {
- c_rx_fifo_errors = comp->sls_i_compressed;
- c_rx_dropped = comp->sls_i_tossed;
- c_tx_fifo_errors = comp->sls_o_compressed;
- c_collisions = comp->sls_o_misses;
- }
- stats->rx_fifo_errors = sl->rx_compressed + c_rx_fifo_errors;
- stats->tx_fifo_errors = sl->tx_compressed + c_tx_fifo_errors;
- stats->collisions = sl->tx_misses + c_collisions;
#endif
stats->rx_packets = devstats->rx_packets;
stats->tx_packets = devstats->tx_packets;
stats->rx_bytes = devstats->rx_bytes;
stats->tx_bytes = devstats->tx_bytes;
- stats->rx_dropped = devstats->rx_dropped + c_rx_dropped;
+ stats->rx_dropped = devstats->rx_dropped;
stats->tx_dropped = devstats->tx_dropped;
stats->tx_errors = devstats->tx_errors;
stats->rx_errors = devstats->rx_errors;
stats->rx_over_errors = devstats->rx_over_errors;
+#ifdef SL_INCLUDE_CSLIP
+ if (comp) {
+ /* Generic compressed statistics */
+ stats->rx_compressed = comp->sls_i_compressed;
+ stats->tx_compressed = comp->sls_o_compressed;
+
+ /* Are we really still needs this? */
+ stats->rx_fifo_errors += comp->sls_i_compressed;
+ stats->rx_dropped += comp->sls_i_tossed;
+ stats->tx_fifo_errors += comp->sls_o_compressed;
+ stats->collisions += comp->sls_o_misses;
+ }
+#endif
return stats;
}
diff --git a/drivers/net/slip.h b/drivers/net/slip/slip.h
index aa0764ce2342..67673cf1266b 100644
--- a/drivers/net/slip.h
+++ b/drivers/net/slip/slip.h
@@ -65,15 +65,6 @@ struct slip {
unsigned char *xbuff; /* transmitter buffer */
unsigned char *xhead; /* pointer to next byte to XMIT */
int xleft; /* bytes left in XMIT queue */
-
- /* SLIP interface statistics. */
-#ifdef SL_INCLUDE_CSLIP
- unsigned long tx_compressed;
- unsigned long rx_compressed;
- unsigned long tx_misses;
-#endif
- /* Detailed SLIP statistics. */
-
int mtu; /* Our mtu (to spot changes!) */
int buffsize; /* Max buffers sizes */
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index d16880d7099b..58f13adaa549 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -33,7 +33,7 @@
#include <asm/prom.h>
#endif
-#include "sungem_phy.h"
+#include <linux/sungem_phy.h>
/* Link modes of the BCM5400 PHY */
static const int phy_BCM5400_link_table[8][3] = {
@@ -1156,7 +1156,7 @@ static struct mii_phy_def* mii_phy_table[] = {
NULL
};
-int mii_phy_probe(struct mii_phy *phy, int mii_id)
+int sungem_phy_probe(struct mii_phy *phy, int mii_id)
{
int rc;
u32 id;
@@ -1195,6 +1195,5 @@ fail:
return -ENODEV;
}
-EXPORT_SYMBOL(mii_phy_probe);
+EXPORT_SYMBOL(sungem_phy_probe);
MODULE_LICENSE("GPL");
-
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index b6162fe2348e..ef9fdf3652f6 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -282,7 +282,7 @@ static const struct net_device_ops xl_netdev_ops = {
.ndo_stop = xl_close,
.ndo_start_xmit = xl_xmit,
.ndo_change_mtu = xl_change_mtu,
- .ndo_set_multicast_list = xl_set_rx_mode,
+ .ndo_set_rx_mode = xl_set_rx_mode,
.ndo_set_mac_address = xl_set_mac_address,
};
diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
index c4137b0f808e..c7e0149d1514 100644
--- a/drivers/net/tokenring/Kconfig
+++ b/drivers/net/tokenring/Kconfig
@@ -4,9 +4,9 @@
# So far, we only have PCI, ISA, and MCA token ring devices
menuconfig TR
- tristate "Token Ring driver support"
+ bool "Token Ring driver support"
depends on NETDEVICES && !UML
- depends on (PCI || ISA || MCA || CCW)
+ depends on (PCI || ISA || MCA || CCW || PCMCIA)
select LLC
help
Token Ring is IBM's way of communication on a local network; the
@@ -20,6 +20,17 @@ menuconfig TR
if TR
+config PCMCIA_IBMTR
+ tristate "IBM PCMCIA tokenring adapter support"
+ depends on IBMTR!=y && PCMCIA
+ ---help---
+ Say Y here if you intend to attach this type of Token Ring PCMCIA
+ card to your computer. You then also need to say Y to "Token Ring
+ driver support".
+
+ To compile this driver as a module, choose M here: the module will be
+ called ibmtr_cs.
+
config IBMTR
tristate "IBM Tropic chipset based adapter support"
depends on ISA || MCA
diff --git a/drivers/net/tokenring/Makefile b/drivers/net/tokenring/Makefile
index c88b0a5e5380..f1be8d97b7a8 100644
--- a/drivers/net/tokenring/Makefile
+++ b/drivers/net/tokenring/Makefile
@@ -2,14 +2,15 @@
# Makefile for drivers/net/tokenring
#
-obj-$(CONFIG_IBMTR) += ibmtr.o
-obj-$(CONFIG_IBMOL) += olympic.o
-obj-$(CONFIG_IBMLS) += lanstreamer.o
-obj-$(CONFIG_TMS380TR) += tms380tr.o
-obj-$(CONFIG_ABYSS) += abyss.o
-obj-$(CONFIG_MADGEMC) += madgemc.o
-obj-$(CONFIG_PROTEON) += proteon.o
-obj-$(CONFIG_TMSPCI) += tmspci.o
-obj-$(CONFIG_SKISA) += skisa.o
-obj-$(CONFIG_SMCTR) += smctr.o
+obj-$(CONFIG_PCMCIA_IBMTR) += ibmtr_cs.o
+obj-$(CONFIG_IBMTR) += ibmtr.o
+obj-$(CONFIG_IBMOL) += olympic.o
+obj-$(CONFIG_IBMLS) += lanstreamer.o
+obj-$(CONFIG_TMS380TR) += tms380tr.o
+obj-$(CONFIG_ABYSS) += abyss.o
+obj-$(CONFIG_MADGEMC) += madgemc.o
+obj-$(CONFIG_PROTEON) += proteon.o
+obj-$(CONFIG_TMSPCI) += tmspci.o
+obj-$(CONFIG_SKISA) += skisa.o
+obj-$(CONFIG_SMCTR) += smctr.o
obj-$(CONFIG_3C359) += 3c359.o
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index e257a00fe14b..b5c8c18f5046 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -823,7 +823,7 @@ static const struct net_device_ops trdev_netdev_ops = {
.ndo_open = tok_open,
.ndo_stop = tok_close,
.ndo_start_xmit = tok_send_packet,
- .ndo_set_multicast_list = tok_set_multicast_list,
+ .ndo_set_rx_mode = tok_set_multicast_list,
.ndo_change_mtu = ibmtr_change_mtu,
};
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/tokenring/ibmtr_cs.c
index 6006d5488fbe..91b684630fc5 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/tokenring/ibmtr_cs.c
@@ -66,7 +66,7 @@
#include <asm/system.h>
#define PCMCIA
-#include "../tokenring/ibmtr.c"
+#include "ibmtr.c"
/*====================================================================*/
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index 9354ca9da576..8d71e0d29062 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -231,7 +231,7 @@ static const struct net_device_ops streamer_netdev_ops = {
#if STREAMER_IOCTL
.ndo_do_ioctl = streamer_ioctl,
#endif
- .ndo_set_multicast_list = streamer_set_rx_mode,
+ .ndo_set_rx_mode = streamer_set_rx_mode,
.ndo_set_mac_address = streamer_set_mac_address,
};
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index e3855aeb13d4..fd8dce90c957 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -201,7 +201,7 @@ static const struct net_device_ops olympic_netdev_ops = {
.ndo_stop = olympic_close,
.ndo_start_xmit = olympic_xmit,
.ndo_change_mtu = olympic_change_mtu,
- .ndo_set_multicast_list = olympic_set_rx_mode,
+ .ndo_set_rx_mode = olympic_set_rx_mode,
.ndo_set_mac_address = olympic_set_mac_address,
};
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index d9044aba7afa..029846a98636 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -3623,7 +3623,7 @@ static const struct net_device_ops smctr_netdev_ops = {
.ndo_start_xmit = smctr_send_packet,
.ndo_tx_timeout = smctr_timeout,
.ndo_get_stats = smctr_get_stats,
- .ndo_set_multicast_list = smctr_set_multicast_list,
+ .ndo_set_rx_mode = smctr_set_multicast_list,
};
static int __init smctr_probe1(struct net_device *dev, int ioaddr)
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index 793020347e54..65e9cf3a71fe 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -2289,7 +2289,7 @@ const struct net_device_ops tms380tr_netdev_ops = {
.ndo_start_xmit = tms380tr_send_packet,
.ndo_tx_timeout = tms380tr_timeout,
.ndo_get_stats = tms380tr_get_stats,
- .ndo_set_multicast_list = tms380tr_set_multicast_list,
+ .ndo_set_rx_mode = tms380tr_set_multicast_list,
.ndo_set_mac_address = tms380tr_set_mac_address,
};
EXPORT_SYMBOL(tms380tr_netdev_ops);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 71f3d1a35b74..7bea9c65119e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -496,7 +496,7 @@ static const struct net_device_ops tap_netdev_ops = {
.ndo_start_xmit = tun_net_xmit,
.ndo_change_mtu = tun_net_change_mtu,
.ndo_fix_features = tun_net_fix_features,
- .ndo_set_multicast_list = tun_net_mclist,
+ .ndo_set_rx_mode = tun_net_mclist,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 84d4608153c9..233576127934 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -68,6 +68,7 @@ config USB_KAWETH
config USB_PEGASUS
tristate "USB Pegasus/Pegasus-II based ethernet device support"
+ select NET_CORE
select MII
---help---
Say Y here if you know you have Pegasus or Pegasus-II based adapter.
@@ -84,6 +85,7 @@ config USB_PEGASUS
config USB_RTL8150
tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)"
depends on EXPERIMENTAL
+ select NET_CORE
select MII
help
Say Y here if you have RTL8150 based usb-ethernet adapter.
@@ -95,6 +97,7 @@ config USB_RTL8150
config USB_USBNET
tristate "Multi-purpose USB Networking Framework"
+ select NET_CORE
select MII
---help---
This driver supports several kinds of network links over USB,
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index c5c4b4def7fb..e81e22e3d1d2 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -36,8 +36,8 @@
#include <linux/usb/usbnet.h>
#include <linux/slab.h>
-#define DRIVER_VERSION "14-Jun-2006"
-static const char driver_name [] = "asix";
+#define DRIVER_VERSION "26-Sep-2011"
+#define DRIVER_NAME "asix"
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
@@ -115,28 +115,27 @@ static const char driver_name [] = "asix";
#define AX88178_MEDIUM_DEFAULT \
(AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
- AX_MEDIUM_RE )
+ AX_MEDIUM_RE)
#define AX88772_MEDIUM_DEFAULT \
(AX_MEDIUM_FD | AX_MEDIUM_RFC | \
AX_MEDIUM_TFC | AX_MEDIUM_PS | \
- AX_MEDIUM_AC | AX_MEDIUM_RE )
+ AX_MEDIUM_AC | AX_MEDIUM_RE)
/* AX88772 & AX88178 RX_CTL values */
-#define AX_RX_CTL_SO 0x0080
-#define AX_RX_CTL_AP 0x0020
-#define AX_RX_CTL_AM 0x0010
-#define AX_RX_CTL_AB 0x0008
-#define AX_RX_CTL_SEP 0x0004
-#define AX_RX_CTL_AMALL 0x0002
-#define AX_RX_CTL_PRO 0x0001
-#define AX_RX_CTL_MFB_2048 0x0000
-#define AX_RX_CTL_MFB_4096 0x0100
-#define AX_RX_CTL_MFB_8192 0x0200
-#define AX_RX_CTL_MFB_16384 0x0300
-
-#define AX_DEFAULT_RX_CTL \
- (AX_RX_CTL_SO | AX_RX_CTL_AB )
+#define AX_RX_CTL_SO 0x0080
+#define AX_RX_CTL_AP 0x0020
+#define AX_RX_CTL_AM 0x0010
+#define AX_RX_CTL_AB 0x0008
+#define AX_RX_CTL_SEP 0x0004
+#define AX_RX_CTL_AMALL 0x0002
+#define AX_RX_CTL_PRO 0x0001
+#define AX_RX_CTL_MFB_2048 0x0000
+#define AX_RX_CTL_MFB_4096 0x0100
+#define AX_RX_CTL_MFB_8192 0x0200
+#define AX_RX_CTL_MFB_16384 0x0300
+
+#define AX_DEFAULT_RX_CTL (AX_RX_CTL_SO | AX_RX_CTL_AB)
/* GPIO 0 .. 2 toggles */
#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */
@@ -164,6 +163,8 @@ static const char driver_name [] = "asix";
#define MARVELL_CTRL_TXDELAY 0x0002
#define MARVELL_CTRL_RXDELAY 0x0080
+#define PHY_MODE_RTL8211CL 0x0004
+
/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
struct asix_data {
u8 multi_filter[AX_MCAST_FILTER_SIZE];
@@ -268,12 +269,15 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
cmd, value, index, size);
- if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n");
return;
}
- if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
+ 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;
@@ -290,7 +294,8 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
(void *)req, data, size,
asix_async_cmd_callback, req);
- if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ 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);
@@ -531,11 +536,11 @@ static u16 asix_read_medium_status(struct usbnet *dev)
if (ret < 0) {
netdev_err(dev->net, "Error reading Medium Status register: %02x\n",
ret);
- goto out;
+ return ret; /* TODO: callers not checking for error ret */
}
- ret = le16_to_cpu(v);
-out:
- return ret;
+
+ return le16_to_cpu(v);
+
}
static int asix_write_medium_mode(struct usbnet *dev, u16 mode)
@@ -676,12 +681,6 @@ asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
}
wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
wolinfo->wolopts = 0;
- if (opt & AX_MONITOR_MODE) {
- if (opt & AX_MONITOR_LINK)
- wolinfo->wolopts |= WAKE_PHY;
- if (opt & AX_MONITOR_MAGIC)
- wolinfo->wolopts |= WAKE_MAGIC;
- }
}
static int
@@ -694,8 +693,6 @@ asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
opt |= AX_MONITOR_LINK;
if (wolinfo->wolopts & WAKE_MAGIC)
opt |= AX_MONITOR_MAGIC;
- if (opt != 0)
- opt |= AX_MONITOR_MODE;
if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
opt, 0, 0, NULL) < 0)
@@ -744,7 +741,7 @@ static void asix_get_drvinfo (struct net_device *net,
/* Inherit standard device info */
usbnet_get_drvinfo(net, info);
- strncpy (info->driver, driver_name, sizeof info->driver);
+ strncpy (info->driver, DRIVER_NAME, sizeof info->driver);
strncpy (info->version, DRIVER_VERSION, sizeof info->version);
info->eedump_len = data->eeprom_len;
}
@@ -872,7 +869,7 @@ static const struct net_device_ops ax88172_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = asix_ioctl,
- .ndo_set_multicast_list = ax88172_set_multicast,
+ .ndo_set_rx_mode = ax88172_set_multicast,
};
static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -889,19 +886,20 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
/* Toggle the GPIOs in a manufacturer/model specific way */
for (i = 2; i >= 0; i--) {
- if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
- (gpio_bits >> (i * 8)) & 0xff, 0, 0,
- NULL)) < 0)
+ ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ (gpio_bits >> (i * 8)) & 0xff, 0, 0, NULL);
+ if (ret < 0)
goto out;
msleep(5);
}
- if ((ret = asix_write_rx_ctl(dev, 0x80)) < 0)
+ ret = asix_write_rx_ctl(dev, 0x80);
+ if (ret < 0)
goto out;
/* Get the MAC address */
- if ((ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID,
- 0, 0, ETH_ALEN, buf)) < 0) {
+ ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf);
+ if (ret < 0) {
dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
goto out;
}
@@ -966,117 +964,88 @@ static int ax88772_link_reset(struct usbnet *dev)
return 0;
}
-static const struct net_device_ops ax88772_netdev_ops = {
- .ndo_open = usbnet_open,
- .ndo_stop = usbnet_stop,
- .ndo_start_xmit = usbnet_start_xmit,
- .ndo_tx_timeout = usbnet_tx_timeout,
- .ndo_change_mtu = usbnet_change_mtu,
- .ndo_set_mac_address = asix_set_mac_address,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_do_ioctl = asix_ioctl,
- .ndo_set_multicast_list = asix_set_multicast,
-};
-
-static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
+static int ax88772_reset(struct usbnet *dev)
{
int ret, embd_phy;
u16 rx_ctl;
- struct asix_data *data = (struct asix_data *)&dev->data;
- u8 buf[ETH_ALEN];
- u32 phyid;
- data->eeprom_len = AX88772_EEPROM_LEN;
-
- usbnet_get_endpoints(dev,intf);
-
- if ((ret = asix_write_gpio(dev,
- AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0)
+ ret = asix_write_gpio(dev,
+ AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5);
+ if (ret < 0)
goto out;
- /* 0x10 is the phy id of the embedded 10/100 ethernet phy */
embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
- if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
- embd_phy, 0, 0, NULL)) < 0) {
+
+ ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
+ if (ret < 0) {
dbg("Select PHY #1 failed: %d", ret);
goto out;
}
- if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL)) < 0)
+ ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL);
+ if (ret < 0)
goto out;
msleep(150);
- if ((ret = asix_sw_reset(dev, AX_SWRESET_CLEAR)) < 0)
+
+ ret = asix_sw_reset(dev, AX_SWRESET_CLEAR);
+ if (ret < 0)
goto out;
msleep(150);
+
if (embd_phy) {
- if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0)
+ ret = asix_sw_reset(dev, AX_SWRESET_IPRL);
+ if (ret < 0)
goto out;
- }
- else {
- if ((ret = asix_sw_reset(dev, AX_SWRESET_PRTE)) < 0)
+ } else {
+ ret = asix_sw_reset(dev, AX_SWRESET_PRTE);
+ if (ret < 0)
goto out;
}
msleep(150);
rx_ctl = asix_read_rx_ctl(dev);
dbg("RX_CTL is 0x%04x after software reset", rx_ctl);
- if ((ret = asix_write_rx_ctl(dev, 0x0000)) < 0)
+ ret = asix_write_rx_ctl(dev, 0x0000);
+ if (ret < 0)
goto out;
rx_ctl = asix_read_rx_ctl(dev);
dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl);
- /* Get the MAC address */
- if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
- 0, 0, ETH_ALEN, buf)) < 0) {
- dbg("Failed to read MAC address: %d", ret);
- goto out;
- }
- memcpy(dev->net->dev_addr, buf, ETH_ALEN);
-
- /* Initialize MII structure */
- dev->mii.dev = dev->net;
- dev->mii.mdio_read = asix_mdio_read;
- dev->mii.mdio_write = asix_mdio_write;
- dev->mii.phy_id_mask = 0x1f;
- dev->mii.reg_num_mask = 0x1f;
- dev->mii.phy_id = asix_get_phy_addr(dev);
-
- phyid = asix_get_phyid(dev);
- dbg("PHYID=0x%08x", phyid);
-
- if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0)
+ ret = asix_sw_reset(dev, AX_SWRESET_PRL);
+ if (ret < 0)
goto out;
msleep(150);
- if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0)
+ ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL);
+ if (ret < 0)
goto out;
msleep(150);
- dev->net->netdev_ops = &ax88772_netdev_ops;
- dev->net->ethtool_ops = &ax88772_ethtool_ops;
-
asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_CSMA);
mii_nway_restart(&dev->mii);
- if ((ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT)) < 0)
+ ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT);
+ if (ret < 0)
goto out;
- if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
+ ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
- AX88772_IPG2_DEFAULT, 0, NULL)) < 0) {
+ AX88772_IPG2_DEFAULT, 0, NULL);
+ if (ret < 0) {
dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
goto out;
}
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
- if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0)
+ ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL);
+ if (ret < 0)
goto out;
rx_ctl = asix_read_rx_ctl(dev);
@@ -1085,16 +1054,70 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
rx_ctl = asix_read_medium_status(dev);
dbg("Medium Status is 0x%04x after all initializations", rx_ctl);
+ return 0;
+
+out:
+ return ret;
+
+}
+
+static const struct net_device_ops ax88772_netdev_ops = {
+ .ndo_open = usbnet_open,
+ .ndo_stop = usbnet_stop,
+ .ndo_start_xmit = usbnet_start_xmit,
+ .ndo_tx_timeout = usbnet_tx_timeout,
+ .ndo_change_mtu = usbnet_change_mtu,
+ .ndo_set_mac_address = asix_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = asix_ioctl,
+ .ndo_set_rx_mode = asix_set_multicast,
+};
+
+static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int ret;
+ struct asix_data *data = (struct asix_data *)&dev->data;
+ u8 buf[ETH_ALEN];
+ u32 phyid;
+
+ data->eeprom_len = AX88772_EEPROM_LEN;
+
+ usbnet_get_endpoints(dev,intf);
+
+ /* Get the MAC address */
+ ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf);
+ if (ret < 0) {
+ dbg("Failed to read MAC address: %d", ret);
+ return ret;
+ }
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+ /* Initialize MII structure */
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = asix_mdio_read;
+ dev->mii.mdio_write = asix_mdio_write;
+ dev->mii.phy_id_mask = 0x1f;
+ dev->mii.reg_num_mask = 0x1f;
+ dev->mii.phy_id = asix_get_phy_addr(dev);
+
+ phyid = asix_get_phyid(dev);
+ dbg("PHYID=0x%08x", phyid);
+
+ dev->net->netdev_ops = &ax88772_netdev_ops;
+ dev->net->ethtool_ops = &ax88772_ethtool_ops;
+
+ ret = ax88772_reset(dev);
+ if (ret < 0)
+ return ret;
+
/* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
if (dev->driver_info->flags & FLAG_FRAMING_AX) {
/* hard_mtu is still the default - the device does not support
jumbo eth frames */
dev->rx_urb_size = 2048;
}
- return 0;
-out:
- return ret;
+ return 0;
}
static struct ethtool_ops ax88178_ethtool_ops = {
@@ -1143,6 +1166,27 @@ static int marvell_phy_init(struct usbnet *dev)
return 0;
}
+static int rtl8211cl_phy_init(struct usbnet *dev)
+{
+ struct asix_data *data = (struct asix_data *)&dev->data;
+
+ netdev_dbg(dev->net, "rtl8211cl_phy_init()\n");
+
+ asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0x0005);
+ asix_mdio_write (dev->net, dev->mii.phy_id, 0x0c, 0);
+ asix_mdio_write (dev->net, dev->mii.phy_id, 0x01,
+ asix_mdio_read (dev->net, dev->mii.phy_id, 0x01) | 0x0080);
+ asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0);
+
+ if (data->ledmode == 12) {
+ asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0x0002);
+ asix_mdio_write (dev->net, dev->mii.phy_id, 0x1a, 0x00cb);
+ asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0);
+ }
+
+ return 0;
+}
+
static int marvell_led_status(struct usbnet *dev, u16 speed)
{
u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL);
@@ -1169,6 +1213,79 @@ static int marvell_led_status(struct usbnet *dev, u16 speed)
return 0;
}
+static int ax88178_reset(struct usbnet *dev)
+{
+ struct asix_data *data = (struct asix_data *)&dev->data;
+ int ret;
+ __le16 eeprom;
+ u8 status;
+ int gpio0 = 0;
+
+ asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status);
+ dbg("GPIO Status: 0x%04x", status);
+
+ asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL);
+ asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom);
+ asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL);
+
+ dbg("EEPROM index 0x17 is 0x%04x", eeprom);
+
+ if (eeprom == cpu_to_le16(0xffff)) {
+ data->phymode = PHY_MODE_MARVELL;
+ data->ledmode = 0;
+ gpio0 = 1;
+ } else {
+ data->phymode = le16_to_cpu(eeprom) & 7;
+ data->ledmode = le16_to_cpu(eeprom) >> 8;
+ gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1;
+ }
+ dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode);
+
+ asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40);
+ if ((le16_to_cpu(eeprom) >> 8) != 1) {
+ asix_write_gpio(dev, 0x003c, 30);
+ asix_write_gpio(dev, 0x001c, 300);
+ asix_write_gpio(dev, 0x003c, 30);
+ } else {
+ dbg("gpio phymode == 1 path");
+ asix_write_gpio(dev, AX_GPIO_GPO1EN, 30);
+ asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30);
+ }
+
+ asix_sw_reset(dev, 0);
+ msleep(150);
+
+ asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD);
+ msleep(150);
+
+ asix_write_rx_ctl(dev, 0);
+
+ if (data->phymode == PHY_MODE_MARVELL) {
+ marvell_phy_init(dev);
+ msleep(60);
+ } else if (data->phymode == PHY_MODE_RTL8211CL)
+ rtl8211cl_phy_init(dev);
+
+ asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
+ BMCR_RESET | BMCR_ANENABLE);
+ asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+ asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
+ ADVERTISE_1000FULL);
+
+ mii_nway_restart(&dev->mii);
+
+ ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT);
+ if (ret < 0)
+ return ret;
+
+ ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int ax88178_link_reset(struct usbnet *dev)
{
u16 mode;
@@ -1270,67 +1387,27 @@ static const struct net_device_ops ax88178_netdev_ops = {
.ndo_tx_timeout = usbnet_tx_timeout,
.ndo_set_mac_address = asix_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = asix_set_multicast,
+ .ndo_set_rx_mode = asix_set_multicast,
.ndo_do_ioctl = asix_ioctl,
.ndo_change_mtu = ax88178_change_mtu,
};
static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
{
- struct asix_data *data = (struct asix_data *)&dev->data;
int ret;
u8 buf[ETH_ALEN];
- __le16 eeprom;
- u8 status;
- int gpio0 = 0;
u32 phyid;
+ struct asix_data *data = (struct asix_data *)&dev->data;
- usbnet_get_endpoints(dev,intf);
-
- asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status);
- dbg("GPIO Status: 0x%04x", status);
-
- asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL);
- asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom);
- asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL);
-
- dbg("EEPROM index 0x17 is 0x%04x", eeprom);
-
- if (eeprom == cpu_to_le16(0xffff)) {
- data->phymode = PHY_MODE_MARVELL;
- data->ledmode = 0;
- gpio0 = 1;
- } else {
- data->phymode = le16_to_cpu(eeprom) & 7;
- data->ledmode = le16_to_cpu(eeprom) >> 8;
- gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1;
- }
- dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode);
-
- asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40);
- if ((le16_to_cpu(eeprom) >> 8) != 1) {
- asix_write_gpio(dev, 0x003c, 30);
- asix_write_gpio(dev, 0x001c, 300);
- asix_write_gpio(dev, 0x003c, 30);
- } else {
- dbg("gpio phymode == 1 path");
- asix_write_gpio(dev, AX_GPIO_GPO1EN, 30);
- asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30);
- }
-
- asix_sw_reset(dev, 0);
- msleep(150);
-
- asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD);
- msleep(150);
+ data->eeprom_len = AX88772_EEPROM_LEN;
- asix_write_rx_ctl(dev, 0);
+ usbnet_get_endpoints(dev,intf);
/* Get the MAC address */
- if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
- 0, 0, ETH_ALEN, buf)) < 0) {
+ ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf);
+ if (ret < 0) {
dbg("Failed to read MAC address: %d", ret);
- goto out;
+ return ret;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
@@ -1349,25 +1426,9 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
phyid = asix_get_phyid(dev);
dbg("PHYID=0x%08x", phyid);
- if (data->phymode == PHY_MODE_MARVELL) {
- marvell_phy_init(dev);
- msleep(60);
- }
-
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
- BMCR_RESET | BMCR_ANENABLE);
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
- ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
- ADVERTISE_1000FULL);
-
- mii_nway_restart(&dev->mii);
-
- if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0)
- goto out;
-
- if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0)
- goto out;
+ ret = ax88178_reset(dev);
+ if (ret < 0)
+ return ret;
/* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
if (dev->driver_info->flags & FLAG_FRAMING_AX) {
@@ -1375,10 +1436,8 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
jumbo eth frames */
dev->rx_urb_size = 2048;
}
- return 0;
-out:
- return ret;
+ return 0;
}
static const struct driver_info ax8817x_info = {
@@ -1426,7 +1485,7 @@ static const struct driver_info ax88772_info = {
.bind = ax88772_bind,
.status = asix_status,
.link_reset = ax88772_link_reset,
- .reset = ax88772_link_reset,
+ .reset = ax88772_reset,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
.rx_fixup = asix_rx_fixup,
.tx_fixup = asix_tx_fixup,
@@ -1437,7 +1496,7 @@ static const struct driver_info ax88178_info = {
.bind = ax88178_bind,
.status = asix_status,
.link_reset = ax88178_link_reset,
- .reset = ax88178_link_reset,
+ .reset = ax88178_reset,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
.rx_fixup = asix_rx_fixup,
.tx_fixup = asix_tx_fixup,
@@ -1566,7 +1625,7 @@ static const struct usb_device_id products [] = {
MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver asix_driver = {
- .name = "asix",
+ .name = DRIVER_NAME,
.id_table = products,
.probe = usbnet_probe,
.suspend = usbnet_suspend,
@@ -1588,6 +1647,7 @@ static void __exit asix_exit(void)
module_exit(asix_exit);
MODULE_AUTHOR("David Hollis");
+MODULE_VERSION(DRIVER_VERSION);
MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 8056f8a27c6a..a68272c93381 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -749,7 +749,7 @@ static const struct net_device_ops catc_netdev_ops = {
.ndo_start_xmit = catc_start_xmit,
.ndo_tx_timeout = catc_tx_timeout,
- .ndo_set_multicast_list = catc_set_multicast_list,
+ .ndo_set_rx_mode = catc_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index 1d93133e9b74..fbc0e4def767 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -428,7 +428,7 @@ static const struct net_device_ops dm9601_netdev_ops = {
.ndo_change_mtu = usbnet_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = dm9601_ioctl,
- .ndo_set_multicast_list = dm9601_set_multicast,
+ .ndo_set_rx_mode = dm9601_set_multicast,
.ndo_set_mac_address = dm9601_set_mac_address,
};
diff --git a/drivers/net/usb/int51x1.c b/drivers/net/usb/int51x1.c
index be02a25da71a..131ac6c172f6 100644
--- a/drivers/net/usb/int51x1.c
+++ b/drivers/net/usb/int51x1.c
@@ -193,7 +193,7 @@ static const struct net_device_ops int51x1_netdev_ops = {
.ndo_change_mtu = usbnet_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = int51x1_set_multicast,
+ .ndo_set_rx_mode = int51x1_set_multicast,
};
static int int51x1_bind(struct usbnet *dev, struct usb_interface *intf)
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index ad0298f9b5f9..582ca2dfa5f9 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -985,7 +985,7 @@ static const struct net_device_ops kaweth_netdev_ops = {
.ndo_stop = kaweth_close,
.ndo_start_xmit = kaweth_start_xmit,
.ndo_tx_timeout = kaweth_tx_timeout,
- .ndo_set_multicast_list = kaweth_set_rx_mode,
+ .ndo_set_rx_mode = kaweth_set_rx_mode,
.ndo_get_stats = kaweth_netdev_stats,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/usb/lg-vl600.c b/drivers/net/usb/lg-vl600.c
index 1d83ccfd7277..1e7221951056 100644
--- a/drivers/net/usb/lg-vl600.c
+++ b/drivers/net/usb/lg-vl600.c
@@ -89,6 +89,8 @@ static int vl600_bind(struct usbnet *dev, struct usb_interface *intf)
* addresses have no meaning, the destination and the source of every
* packet depend only on whether it is on the IN or OUT endpoint. */
dev->net->flags |= IFF_NOARP;
+ /* IPv6 NDP relies on multicast. Enable it by default. */
+ dev->net->flags |= IFF_MULTICAST;
return ret;
}
@@ -200,6 +202,14 @@ static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
} else {
memset(ethhdr->h_source, 0, ETH_ALEN);
memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN);
+
+ /* Inbound IPv6 packets have an IPv4 ethertype (0x800)
+ * for some reason. Peek at the L3 header to check
+ * for IPv6 packets, and set the ethertype to IPv6
+ * (0x86dd) so Linux can understand it.
+ */
+ if ((buf->data[sizeof(*ethhdr)] & 0xf0) == 0x60)
+ ethhdr->h_proto = __constant_htons(ETH_P_IPV6);
}
if (count) {
@@ -297,6 +307,15 @@ encapsulate:
if (skb->len < full_len) /* Pad */
skb_put(skb, full_len - skb->len);
+ /* The VL600 wants IPv6 packets to have an IPv4 ethertype
+ * Check if this is an IPv6 packet, and set the ethertype
+ * to 0x800
+ */
+ if ((skb->data[sizeof(struct vl600_pkt_hdr *) + 0x22] & 0xf0) == 0x60) {
+ skb->data[sizeof(struct vl600_pkt_hdr *) + 0x20] = 0x08;
+ skb->data[sizeof(struct vl600_pkt_hdr *) + 0x21] = 0;
+ }
+
return skb;
}
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index 2b791392e788..db2cb74bf854 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -553,7 +553,7 @@ static const struct net_device_ops mcs7830_netdev_ops = {
.ndo_change_mtu = usbnet_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = mcs7830_ioctl,
- .ndo_set_multicast_list = mcs7830_set_multicast,
+ .ndo_set_rx_mode = mcs7830_set_multicast,
.ndo_set_mac_address = mcs7830_set_mac_address,
};
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index ef3667690b12..769f5090bda1 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -1476,7 +1476,7 @@ static const struct net_device_ops pegasus_netdev_ops = {
.ndo_stop = pegasus_close,
.ndo_do_ioctl = pegasus_ioctl,
.ndo_start_xmit = pegasus_start_xmit,
- .ndo_set_multicast_list = pegasus_set_multicast,
+ .ndo_set_rx_mode = pegasus_set_multicast,
.ndo_get_stats = pegasus_netdev_stats,
.ndo_tx_timeout = pegasus_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index ef3b236b5145..bf8c84d0adf2 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -169,26 +169,8 @@ struct rtl8150 {
typedef struct rtl8150 rtl8150_t;
-static void fill_skb_pool(rtl8150_t *);
-static void free_skb_pool(rtl8150_t *);
-static inline struct sk_buff *pull_skb(rtl8150_t *);
-static void rtl8150_disconnect(struct usb_interface *intf);
-static int rtl8150_probe(struct usb_interface *intf,
- const struct usb_device_id *id);
-static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message);
-static int rtl8150_resume(struct usb_interface *intf);
-
static const char driver_name [] = "rtl8150";
-static struct usb_driver rtl8150_driver = {
- .name = driver_name,
- .probe = rtl8150_probe,
- .disconnect = rtl8150_disconnect,
- .id_table = rtl8150_table,
- .suspend = rtl8150_suspend,
- .resume = rtl8150_resume
-};
-
/*
**
** device related part of the code
@@ -333,7 +315,7 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p)
/* Write the MAC address into eeprom. Eeprom writes must be word-sized,
so we need to split them up. */
for (i = 0; i * 2 < netdev->addr_len; i++) {
- set_registers(dev, IDR_EEPROM + (i * 2), 2,
+ set_registers(dev, IDR_EEPROM + (i * 2), 2,
netdev->dev_addr + (i * 2));
}
/* Clear the WEPROM bit (preventing accidental eeprom writes). */
@@ -490,44 +472,6 @@ resched:
tasklet_schedule(&dev->tl);
}
-static void rx_fixup(unsigned long data)
-{
- rtl8150_t *dev;
- struct sk_buff *skb;
- int status;
-
- dev = (rtl8150_t *)data;
-
- spin_lock_irq(&dev->rx_pool_lock);
- fill_skb_pool(dev);
- spin_unlock_irq(&dev->rx_pool_lock);
- if (test_bit(RX_URB_FAIL, &dev->flags))
- if (dev->rx_skb)
- goto try_again;
- spin_lock_irq(&dev->rx_pool_lock);
- skb = pull_skb(dev);
- spin_unlock_irq(&dev->rx_pool_lock);
- if (skb == NULL)
- goto tlsched;
- dev->rx_skb = skb;
- usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
- dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
-try_again:
- status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
- if (status == -ENODEV) {
- netif_device_detach(dev->netdev);
- } else if (status) {
- set_bit(RX_URB_FAIL, &dev->flags);
- goto tlsched;
- } else {
- clear_bit(RX_URB_FAIL, &dev->flags);
- }
-
- return;
-tlsched:
- tasklet_schedule(&dev->tl);
-}
-
static void write_bulk_callback(struct urb *urb)
{
rtl8150_t *dev;
@@ -665,6 +609,42 @@ static void free_skb_pool(rtl8150_t *dev)
dev_kfree_skb(dev->rx_skb_pool[i]);
}
+static void rx_fixup(unsigned long data)
+{
+ struct rtl8150 *dev = (struct rtl8150 *)data;
+ struct sk_buff *skb;
+ int status;
+
+ spin_lock_irq(&dev->rx_pool_lock);
+ fill_skb_pool(dev);
+ spin_unlock_irq(&dev->rx_pool_lock);
+ if (test_bit(RX_URB_FAIL, &dev->flags))
+ if (dev->rx_skb)
+ goto try_again;
+ spin_lock_irq(&dev->rx_pool_lock);
+ skb = pull_skb(dev);
+ spin_unlock_irq(&dev->rx_pool_lock);
+ if (skb == NULL)
+ goto tlsched;
+ dev->rx_skb = skb;
+ usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
+ dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
+try_again:
+ status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
+ if (status == -ENODEV) {
+ netif_device_detach(dev->netdev);
+ } else if (status) {
+ set_bit(RX_URB_FAIL, &dev->flags);
+ goto tlsched;
+ } else {
+ clear_bit(RX_URB_FAIL, &dev->flags);
+ }
+
+ return;
+tlsched:
+ tasklet_schedule(&dev->tl);
+}
+
static int enable_net_traffic(rtl8150_t * dev)
{
u8 cr, tcr, rcr, msr;
@@ -778,7 +758,7 @@ static int rtl8150_open(struct net_device *netdev)
return -ENOMEM;
set_registers(dev, IDR, 6, netdev->dev_addr);
-
+
usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) {
@@ -898,8 +878,8 @@ static const struct net_device_ops rtl8150_netdev_ops = {
.ndo_stop = rtl8150_close,
.ndo_do_ioctl = rtl8150_ioctl,
.ndo_start_xmit = rtl8150_start_xmit,
- .ndo_tx_timeout = rtl8150_tx_timeout,
- .ndo_set_multicast_list = rtl8150_set_multicast,
+ .ndo_tx_timeout = rtl8150_tx_timeout,
+ .ndo_set_rx_mode = rtl8150_set_multicast,
.ndo_set_mac_address = rtl8150_set_mac_address,
.ndo_change_mtu = eth_change_mtu,
@@ -929,7 +909,7 @@ static int rtl8150_probe(struct usb_interface *intf,
tasklet_init(&dev->tl, rx_fixup, (unsigned long)dev);
spin_lock_init(&dev->rx_pool_lock);
-
+
dev->udev = udev;
dev->netdev = netdev;
netdev->netdev_ops = &rtl8150_netdev_ops;
@@ -947,7 +927,7 @@ static int rtl8150_probe(struct usb_interface *intf,
}
fill_skb_pool(dev);
set_ethernet_addr(dev);
-
+
usb_set_intfdata(intf, dev);
SET_NETDEV_DEV(netdev, &intf->dev);
if (register_netdev(netdev) != 0) {
@@ -989,6 +969,15 @@ static void rtl8150_disconnect(struct usb_interface *intf)
}
}
+static struct usb_driver rtl8150_driver = {
+ .name = driver_name,
+ .probe = rtl8150_probe,
+ .disconnect = rtl8150_disconnect,
+ .id_table = rtl8150_table,
+ .suspend = rtl8150_suspend,
+ .resume = rtl8150_resume
+};
+
static int __init usb_rtl8150_init(void)
{
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 15b3d6888ae9..22a7cf951e72 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1000,7 +1000,7 @@ static const struct net_device_ops smsc75xx_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = smsc75xx_ioctl,
- .ndo_set_multicast_list = smsc75xx_set_multicast,
+ .ndo_set_rx_mode = smsc75xx_set_multicast,
.ndo_set_features = smsc75xx_set_features,
};
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index f74f3ce71526..eff67678c5a6 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -972,7 +972,7 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = smsc95xx_ioctl,
- .ndo_set_multicast_list = smsc95xx_set_multicast,
+ .ndo_set_rx_mode = smsc95xx_set_multicast,
.ndo_set_features = smsc95xx_set_features,
};
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index ce395fe5de26..7d6082160bcc 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -238,6 +238,10 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n",
skb->len + sizeof (struct ethhdr), skb->protocol);
memset (skb->cb, 0, sizeof (struct skb_data));
+
+ if (skb_defer_rx_timestamp(skb))
+ return;
+
status = netif_rx (skb);
if (status != NET_RX_SUCCESS)
netif_dbg(dev, rx_err, dev->net,
@@ -1053,6 +1057,8 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
unsigned long flags;
int retval;
+ skb_tx_timestamp(skb);
+
// some devices want funky USB-level framing, for
// win32 driver (usually) and/or hardware quirks
if (info->tx_fixup) {
@@ -1470,7 +1476,7 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
if (!dev->suspend_count++) {
spin_lock_irq(&dev->txq.lock);
/* don't autosuspend while transmitting */
- if (dev->txq.qlen && (message.event & PM_EVENT_AUTO)) {
+ if (dev->txq.qlen && PMSG_IS_AUTO(message)) {
spin_unlock_irq(&dev->txq.lock);
return -EBUSY;
} else {
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 0c7321c35ad4..6ee8410443c4 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -143,18 +143,16 @@ static void skb_xmit_done(struct virtqueue *svq)
static void set_skb_frag(struct sk_buff *skb, struct page *page,
unsigned int offset, unsigned int *len)
{
+ int size = min((unsigned)PAGE_SIZE - offset, *len);
int i = skb_shinfo(skb)->nr_frags;
- skb_frag_t *f;
- f = &skb_shinfo(skb)->frags[i];
- f->size = min((unsigned)PAGE_SIZE - offset, *len);
- f->page_offset = offset;
- f->page = page;
+ __skb_fill_page_desc(skb, i, page, offset, size);
- skb->data_len += f->size;
- skb->len += f->size;
+ skb->data_len += size;
+ skb->len += size;
+ skb->truesize += PAGE_SIZE;
skb_shinfo(skb)->nr_frags++;
- *len -= f->size;
+ *len -= size;
}
static struct sk_buff *page_to_skb(struct virtnet_info *vi,
@@ -195,6 +193,19 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
len -= copy;
offset += copy;
+ /*
+ * Verify that we can indeed put this data into a skb.
+ * This is here to handle cases when the device erroneously
+ * tries to receive more than is possible. This is usually
+ * 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);
+ dev_kfree_skb(skb);
+ return NULL;
+ }
+
while (len) {
set_skb_frag(skb, page, offset, &len);
page = (struct page *)page->private;
@@ -277,7 +288,6 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
}
hdr = skb_vnet_hdr(skb);
- skb->truesize += skb->data_len;
u64_stats_update_begin(&stats->syncp);
stats->rx_bytes += skb->len;
@@ -867,8 +877,21 @@ static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid);
}
+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_pending = ring->rx_max_pending;
+ ring->tx_pending = ring->tx_max_pending;
+
+}
+
static const struct ethtool_ops virtnet_ethtool_ops = {
.get_link = ethtool_op_get_link,
+ .get_ringparam = virtnet_get_ringparam,
};
#define MIN_MTU 68
@@ -902,12 +925,10 @@ static void virtnet_update_status(struct virtnet_info *vi)
{
u16 v;
- if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS))
- return;
-
- vi->vdev->config->get(vi->vdev,
+ if (virtio_config_val(vi->vdev, VIRTIO_NET_F_STATUS,
offsetof(struct virtio_net_config, status),
- &v, sizeof(v));
+ &v) < 0)
+ return;
/* Ignore unknown (future) status bits */
v &= VIRTIO_NET_S_LINK_UP;
@@ -949,6 +970,7 @@ static int virtnet_probe(struct virtio_device *vdev)
return -ENOMEM;
/* Set up network device as normal. */
+ dev->priv_flags |= IFF_UNICAST_FLT;
dev->netdev_ops = &virtnet_netdev;
dev->features = NETIF_F_HIGHDMA;
@@ -982,11 +1004,9 @@ static int virtnet_probe(struct virtio_device *vdev)
}
/* Configuration may specify what MAC to use. Otherwise random. */
- if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) {
- vdev->config->get(vdev,
+ if (virtio_config_val_len(vdev, VIRTIO_NET_F_MAC,
offsetof(struct virtio_net_config, mac),
- dev->dev_addr, dev->addr_len);
- } else
+ dev->dev_addr, dev->addr_len) < 0)
random_ether_addr(dev->dev_addr);
/* Set up our device-specific information */
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 0959583feb27..b771ebac0f01 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -654,10 +654,11 @@ vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd,
BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS);
- frag->page = rbi->page;
+ __skb_frag_set_page(frag, rbi->page);
frag->page_offset = 0;
- frag->size = rcd->len;
- skb->data_len += frag->size;
+ skb_frag_size_set(frag, rcd->len);
+ skb->data_len += rcd->len;
+ skb->truesize += PAGE_SIZE;
skb_shinfo(skb)->nr_frags++;
}
@@ -744,21 +745,21 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
}
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+ const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
tbi = tq->buf_info + tq->tx_ring.next2fill;
tbi->map_type = VMXNET3_MAP_PAGE;
- tbi->dma_addr = pci_map_page(adapter->pdev, frag->page,
- frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
+ tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
+ 0, skb_frag_size(frag),
+ DMA_TO_DEVICE);
- tbi->len = frag->size;
+ tbi->len = skb_frag_size(frag);
gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
- gdesc->dword[2] = cpu_to_le32(dw2 | frag->size);
+ gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
gdesc->dword[3] = 0;
dev_dbg(&adapter->netdev->dev,
@@ -1277,7 +1278,6 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
skb = ctx->skb;
if (rcd->eop) {
skb->len += skb->data_len;
- skb->truesize += skb->data_len;
vmxnet3_rx_csum(adapter, skb,
(union Vmxnet3_GenericDesc *)rcd);
@@ -2876,7 +2876,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
.ndo_set_features = vmxnet3_set_features,
.ndo_get_stats64 = vmxnet3_get_stats64,
.ndo_tx_timeout = vmxnet3_tx_timeout,
- .ndo_set_multicast_list = vmxnet3_set_mc,
+ .ndo_set_rx_mode = vmxnet3_set_mc,
.ndo_vlan_rx_add_vid = vmxnet3_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 27400edeef55..e662cbc8bfbd 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -558,7 +558,7 @@ out:
static int
vmxnet3_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info,
- void *rules)
+ u32 *rules)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
switch (info->cmd) {
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index 055a918067e6..0d7645581f91 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -515,37 +515,37 @@ static int ppp_rx(struct sk_buff *skb)
switch (cp->code) {
case CP_CONF_REQ:
ppp_cp_parse_cr(dev, pid, cp->id, len, skb->data);
- goto out;
+ break;
case CP_CONF_ACK:
if (cp->id == proto->cr_id)
ppp_cp_event(dev, pid, RCA, 0, 0, 0, NULL);
- goto out;
+ break;
case CP_CONF_REJ:
case CP_CONF_NAK:
if (cp->id == proto->cr_id)
ppp_cp_event(dev, pid, RCN, 0, 0, 0, NULL);
- goto out;
+ break;
case CP_TERM_REQ:
ppp_cp_event(dev, pid, RTR, 0, cp->id, 0, NULL);
- goto out;
+ break;
case CP_TERM_ACK:
ppp_cp_event(dev, pid, RTA, 0, 0, 0, NULL);
- goto out;
+ break;
case CP_CODE_REJ:
ppp_cp_event(dev, pid, RXJ_BAD, 0, 0, 0, NULL);
- goto out;
+ break;
default:
len += sizeof(struct cp_header);
if (len > dev->mtu)
len = dev->mtu;
ppp_cp_event(dev, pid, RUC, 0, 0, len, cp);
- goto out;
+ break;
}
goto out;
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
index 56aeb011cb3d..a49aec5efd20 100644
--- a/drivers/net/wan/hdlc_x25.c
+++ b/drivers/net/wan/hdlc_x25.c
@@ -134,15 +134,15 @@ static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
static int x25_open(struct net_device *dev)
{
- struct lapb_register_struct cb;
int result;
-
- cb.connect_confirmation = x25_connected;
- cb.connect_indication = x25_connected;
- cb.disconnect_confirmation = x25_disconnected;
- cb.disconnect_indication = x25_disconnected;
- cb.data_indication = x25_data_indication;
- cb.data_transmit = x25_data_transmit;
+ static const struct lapb_register_struct cb = {
+ .connect_confirmation = x25_connected,
+ .connect_indication = x25_connected,
+ .disconnect_confirmation = x25_disconnected,
+ .disconnect_indication = x25_disconnected,
+ .data_indication = x25_data_indication,
+ .data_transmit = x25_data_transmit,
+ };
result = lapb_register(dev, &cb);
if (result != LAPB_OK)
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index a817081737a0..7beeb9b88a3b 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -259,14 +259,13 @@ static int lapbeth_set_mac_address(struct net_device *dev, void *addr)
}
-static struct lapb_register_struct lapbeth_callbacks = {
+static const struct lapb_register_struct lapbeth_callbacks = {
.connect_confirmation = lapbeth_connected,
.connect_indication = lapbeth_connected,
.disconnect_confirmation = lapbeth_disconnected,
.disconnect_indication = lapbeth_disconnected,
.data_indication = lapbeth_data_indication,
.data_transmit = lapbeth_data_transmit,
-
};
/*
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 86127bcc9f7a..783168cce077 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -212,7 +212,7 @@ static const struct net_device_ops sbni_netdev_ops = {
.ndo_open = sbni_open,
.ndo_stop = sbni_close,
.ndo_start_xmit = sbni_start_xmit,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_do_ioctl = sbni_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 46ceb3ae9073..8a10bb730d5a 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -434,14 +434,13 @@ static void x25_asy_disconnected(struct net_device *dev, int reason)
netif_rx(skb);
}
-static struct lapb_register_struct x25_asy_callbacks = {
+static const struct lapb_register_struct x25_asy_callbacks = {
.connect_confirmation = x25_asy_connected,
.connect_indication = x25_asy_connected,
.disconnect_confirmation = x25_asy_disconnected,
.disconnect_indication = x25_asy_disconnected,
.data_indication = x25_asy_data_indication,
.data_transmit = x25_asy_data_transmit,
-
};
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index 298f2b0b6311..9a644d052f1e 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -599,7 +599,7 @@ void i2400mu_disconnect(struct usb_interface *iface)
*
* As well, the device might refuse going to sleep for whichever
* reason. In this case we just fail. For system suspend/hibernate,
- * we *can't* fail. We check PM_EVENT_AUTO to see if the
+ * we *can't* fail. We check PMSG_IS_AUTO to see if the
* suspend call comes from the USB stack or from the system and act
* in consequence.
*
@@ -615,7 +615,7 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)
struct i2400m *i2400m = &i2400mu->i2400m;
#ifdef CONFIG_PM
- if (pm_msg.event & PM_EVENT_AUTO)
+ if (PMSG_IS_AUTO(pm_msg))
is_autosuspend = 1;
#endif
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index f354bd4e121e..abd3b71cd4ab 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -271,6 +271,7 @@ config MWL8K
source "drivers/net/wireless/ath/Kconfig"
source "drivers/net/wireless/b43/Kconfig"
source "drivers/net/wireless/b43legacy/Kconfig"
+source "drivers/net/wireless/brcm80211/Kconfig"
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/ipw2x00/Kconfig"
source "drivers/net/wireless/iwlwifi/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 7bba6a82b875..0a304b060b6c 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -41,7 +41,7 @@ obj-$(CONFIG_ADM8211) += adm8211.o
obj-$(CONFIG_MWL8K) += mwl8k.o
-obj-$(CONFIG_IWLAGN) += iwlwifi/
+obj-$(CONFIG_IWLWIFI) += iwlwifi/
obj-$(CONFIG_IWLWIFI_LEGACY) += iwlegacy/
obj-$(CONFIG_RT2X00) += rt2x00/
@@ -58,3 +58,6 @@ obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/
obj-$(CONFIG_IWM) += iwmc3200wifi/
obj-$(CONFIG_MWIFIEX) += mwifiex/
+obj-$(CONFIG_BRCMFMAC) += brcm80211/
+obj-$(CONFIG_BRCMUMAC) += brcm80211/
+obj-$(CONFIG_BRCMSMAC) += brcm80211/
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 43ebc44fc82c..3b752d9fb3cd 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1249,7 +1249,8 @@ static int adm8211_hw_reset(struct ieee80211_hw *dev)
return 0;
}
-static u64 adm8211_get_tsft(struct ieee80211_hw *dev)
+static u64 adm8211_get_tsft(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif)
{
struct adm8211_priv *priv = dev->priv;
u32 tsftl;
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index e1b3e3c134fd..ac1176a4f465 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -2754,7 +2754,7 @@ static const struct net_device_ops airo_netdev_ops = {
.ndo_stop = airo_close,
.ndo_start_xmit = airo_start_xmit,
.ndo_get_stats = airo_get_stats,
- .ndo_set_multicast_list = airo_set_multicast_list,
+ .ndo_set_rx_mode = airo_set_multicast_list,
.ndo_set_mac_address = airo_set_mac_address,
.ndo_do_ioctl = airo_ioctl,
.ndo_change_mtu = airo_change_mtu,
@@ -2766,7 +2766,7 @@ static const struct net_device_ops mpi_netdev_ops = {
.ndo_stop = airo_close,
.ndo_start_xmit = mpi_start_xmit,
.ndo_get_stats = airo_get_stats,
- .ndo_set_multicast_list = airo_set_multicast_list,
+ .ndo_set_rx_mode = airo_set_multicast_list,
.ndo_set_mac_address = airo_set_mac_address,
.ndo_do_ioctl = airo_ioctl,
.ndo_change_mtu = airo_change_mtu,
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 298601436ee2..4045e5ab0555 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -500,10 +500,9 @@ exit:
#define HEX2STR_BUFFERS 4
#define HEX2STR_MAX_LEN 64
-#define BIN2HEX(x) ((x) < 10 ? '0' + (x) : (x) + 'A' - 10)
/* Convert binary data into hex string */
-static char *hex2str(void *buf, int len)
+static char *hex2str(void *buf, size_t len)
{
static atomic_t a = ATOMIC_INIT(0);
static char bufs[HEX2STR_BUFFERS][3 * HEX2STR_MAX_LEN + 1];
@@ -514,18 +513,17 @@ static char *hex2str(void *buf, int len)
if (len > HEX2STR_MAX_LEN)
len = HEX2STR_MAX_LEN;
- if (len <= 0) {
- ret[0] = '\0';
- return ret;
- }
+ if (len == 0)
+ goto exit;
while (len--) {
- *obuf++ = BIN2HEX(*ibuf >> 4);
- *obuf++ = BIN2HEX(*ibuf & 0xf);
+ obuf = hex_byte_pack(obuf, *ibuf++);
*obuf++ = '-';
- ibuf++;
}
- *(--obuf) = '\0';
+ obuf--;
+
+exit:
+ *obuf = '\0';
return ret;
}
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index d1b23067619f..09602241901b 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -1,6 +1,6 @@
menuconfig ATH_COMMON
tristate "Atheros Wireless Cards"
- depends on CFG80211
+ depends on CFG80211 && (!UML || BROKEN)
---help---
This will enable the support for the Atheros wireless drivers.
ath5k, ath9k, ath9k_htc and ar9170 drivers share some common code, this option
@@ -25,5 +25,6 @@ config ATH_DEBUG
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"
endif
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index 0e8f528c81c0..d1214696a35b 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_ATH5K) += ath5k/
obj-$(CONFIG_ATH9K_HW) += ath9k/
obj-$(CONFIG_CARL9170) += carl9170/
+obj-$(CONFIG_ATH6KL) += ath6kl/
obj-$(CONFIG_ATH_COMMON) += ath.o
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 17c4b56c3874..0f9ee46cfc97 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -71,9 +71,7 @@ struct ath_regulatory {
char alpha2[2];
u16 country_code;
u16 max_power_level;
- u32 tp_scale;
u16 current_rd;
- u16 current_rd_ext;
int16_t power_limit;
struct reg_dmn_pair_mapping *regpair;
};
@@ -140,9 +138,6 @@ struct ath_common {
u8 curbssid[ETH_ALEN];
u8 bssidmask[ETH_ALEN];
- u8 tx_chainmask;
- u8 rx_chainmask;
-
u32 rx_bufsize;
u32 keymax;
@@ -178,23 +173,28 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry);
void ath_hw_cycle_counters_update(struct ath_common *common);
int32_t ath_hw_get_listen_time(struct ath_common *common);
-extern __attribute__ ((format (printf, 3, 4))) int
-ath_printk(const char *level, struct ath_common *common, const char *fmt, ...);
+extern __printf(2, 3) void ath_printk(const char *level, const char *fmt, ...);
+
+#define _ath_printk(level, common, fmt, ...) \
+do { \
+ __always_unused struct ath_common *unused = common; \
+ ath_printk(level, fmt, ##__VA_ARGS__); \
+} while (0)
#define ath_emerg(common, fmt, ...) \
- ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__)
+ _ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__)
#define ath_alert(common, fmt, ...) \
- ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__)
+ _ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__)
#define ath_crit(common, fmt, ...) \
- ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__)
+ _ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__)
#define ath_err(common, fmt, ...) \
- ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__)
+ _ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__)
#define ath_warn(common, fmt, ...) \
- ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__)
+ _ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__)
#define ath_notice(common, fmt, ...) \
- ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__)
+ _ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__)
#define ath_info(common, fmt, ...) \
- ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__)
+ _ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__)
/**
* enum ath_debug_level - atheros wireless debug level
@@ -246,27 +246,21 @@ enum ATH_DEBUG {
#ifdef CONFIG_ATH_DEBUG
-#define ath_dbg(common, dbg_mask, fmt, ...) \
-({ \
- int rtn; \
- if ((common)->debug_mask & dbg_mask) \
- rtn = ath_printk(KERN_DEBUG, common, fmt, \
- ##__VA_ARGS__); \
- else \
- rtn = 0; \
- \
- rtn; \
-})
+#define ath_dbg(common, dbg_mask, fmt, ...) \
+do { \
+ if ((common)->debug_mask & dbg_mask) \
+ _ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \
+} while (0)
+
#define ATH_DBG_WARN(foo, arg...) WARN(foo, arg)
#define ATH_DBG_WARN_ON_ONCE(foo) WARN_ON_ONCE(foo)
#else
-static inline __attribute__ ((format (printf, 3, 4))) int
-ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask,
- const char *fmt, ...)
+static inline __attribute__ ((format (printf, 3, 4)))
+void ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask,
+ const char *fmt, ...)
{
- return 0;
}
#define ATH_DBG_WARN(foo, arg...) do {} while (0)
#define ATH_DBG_WARN_ON_ONCE(foo) ({ \
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index a2a167363dbf..e5be7e701816 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -169,7 +169,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
__set_bit(ATH_STAT_2G_DISABLED, ah->status);
}
- ret = ath5k_init_softc(ah, &ath_ahb_bus_ops);
+ ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
if (ret != 0) {
dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
ret = -ENODEV;
@@ -214,7 +214,7 @@ static int ath_ahb_remove(struct platform_device *pdev)
__raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
}
- ath5k_deinit_softc(ah);
+ ath5k_deinit_ah(ah);
platform_set_drvdata(pdev, NULL);
ieee80211_free_hw(hw);
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
index 603ae15f139b..bea90e6be70e 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -15,7 +15,6 @@
*/
#include "ath5k.h"
-#include "base.h"
#include "reg.h"
#include "debug.h"
#include "ani.h"
diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h
index 034015397093..7358b6c83c6c 100644
--- a/drivers/net/wireless/ath/ath5k/ani.h
+++ b/drivers/net/wireless/ath/ath5k/ani.h
@@ -16,6 +16,10 @@
#ifndef ANI_H
#define ANI_H
+#include "../ath.h"
+
+enum ath5k_phy_error_code;
+
/* these thresholds are relative to the ATH5K_ANI_LISTEN_PERIOD */
#define ATH5K_ANI_LISTEN_PERIOD 100
#define ATH5K_ANI_OFDM_TRIG_HIGH 500
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 277d5cbe0068..fecbcd9a4259 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -131,13 +131,6 @@
#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \
ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
-/* Access to PHY registers */
-#define AR5K_PHY_READ(ah, _reg) \
- ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
-
-#define AR5K_PHY_WRITE(ah, _reg, _val) \
- ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
-
/* Access QCU registers per queue */
#define AR5K_REG_READ_Q(ah, _reg, _queue) \
(ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \
@@ -166,7 +159,6 @@
#define AR5K_TUNE_DMA_BEACON_RESP 2
#define AR5K_TUNE_SW_BEACON_RESP 10
#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0
-#define AR5K_TUNE_RADAR_ALERT false
#define AR5K_TUNE_MIN_TX_FIFO_THRES 1
#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_FRAME_LEN / 64) + 1)
#define AR5K_TUNE_REGISTER_TIMEOUT 20000
@@ -295,17 +287,6 @@ enum ath5k_radio {
* Common silicon revision/version values
*/
-enum ath5k_srev_type {
- AR5K_VERSION_MAC,
- AR5K_VERSION_RAD,
-};
-
-struct ath5k_srev_name {
- const char *sr_name;
- enum ath5k_srev_type sr_type;
- u_int sr_val;
-};
-
#define AR5K_SREV_UNKNOWN 0xffff
#define AR5K_SREV_AR5210 0x00 /* Crete */
@@ -424,7 +405,6 @@ enum ath5k_driver_mode {
AR5K_MODE_11A = 0,
AR5K_MODE_11B = 1,
AR5K_MODE_11G = 2,
- AR5K_MODE_XR = 0,
AR5K_MODE_MAX = 3
};
@@ -694,33 +674,6 @@ struct ath5k_gain {
#define AR5K_SLOT_TIME_20 880
#define AR5K_SLOT_TIME_MAX 0xffff
-/* channel_flags */
-#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */
-#define CHANNEL_CCK 0x0020 /* CCK channel */
-#define CHANNEL_OFDM 0x0040 /* OFDM channel */
-#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */
-#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */
-#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */
-#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */
-#define CHANNEL_XR 0x0800 /* XR channel */
-
-#define CHANNEL_A (CHANNEL_5GHZ | CHANNEL_OFDM)
-#define CHANNEL_B (CHANNEL_2GHZ | CHANNEL_CCK)
-#define CHANNEL_G (CHANNEL_2GHZ | CHANNEL_OFDM)
-#define CHANNEL_X (CHANNEL_5GHZ | CHANNEL_OFDM | CHANNEL_XR)
-
-#define CHANNEL_ALL (CHANNEL_OFDM | CHANNEL_CCK | \
- CHANNEL_2GHZ | CHANNEL_5GHZ)
-
-#define CHANNEL_MODES CHANNEL_ALL
-
-/*
- * Used internally for ath5k_hw_reset_tx_queue().
- * Also see struct struct ieee80211_channel.
- */
-#define IS_CHAN_XR(_c) ((_c->hw_value & CHANNEL_XR) != 0)
-#define IS_CHAN_B(_c) ((_c->hw_value & CHANNEL_B) != 0)
-
/*
* The following structure is used to map 2GHz channels to
* 5GHz Atheros channels.
@@ -977,7 +930,7 @@ enum ath5k_power_mode {
struct ath5k_capabilities {
/*
* Supported PHY modes
- * (ie. CHANNEL_A, CHANNEL_B, ...)
+ * (ie. AR5K_MODE_11A, AR5K_MODE_11B, ...)
*/
DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);
@@ -1013,16 +966,6 @@ struct ath5k_nfcal_hist {
s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */
};
-/**
- * struct avg_val - Helper structure for average calculation
- * @avg: contains the actual average value
- * @avg_weight: is used internally during calculation to prevent rounding errors
- */
-struct ath5k_avg_val {
- int avg;
- int avg_weight;
-};
-
#define ATH5K_LED_MAX_NAME_LEN 31
/*
@@ -1148,7 +1091,6 @@ struct ath5k_hw {
bool rx_pending; /* rx tasklet pending */
bool tx_pending; /* tx tasklet pending */
- u8 lladdr[ETH_ALEN];
u8 bssidmask[ETH_ALEN];
unsigned int led_pin, /* GPIO pin for driving LED */
@@ -1156,7 +1098,6 @@ struct ath5k_hw {
struct work_struct reset_work; /* deferred chip reset */
- unsigned int rxbufsize; /* rx size based on mtu */
struct list_head rxbuf; /* receive buffer */
spinlock_t rxbuflock;
u32 *rxlink; /* link ptr in last RX desc */
@@ -1208,10 +1149,8 @@ struct ath5k_hw {
enum ath5k_version ah_version;
enum ath5k_radio ah_radio;
- u32 ah_phy;
u32 ah_mac_srev;
u16 ah_mac_version;
- u16 ah_mac_revision;
u16 ah_phy_revision;
u16 ah_radio_5ghz_revision;
u16 ah_radio_2ghz_revision;
@@ -1279,12 +1218,6 @@ struct ath5k_hw {
bool txp_setup;
} ah_txpower;
- struct {
- bool r_enabled;
- int r_last_alert;
- struct ieee80211_channel r_last_channel;
- } ah_radar;
-
struct ath5k_nfcal_hist ah_nfcal_hist;
/* average beacon RSSI in our BSS (used by ANI) */
@@ -1327,36 +1260,13 @@ struct ath_bus_ops {
extern const struct ieee80211_ops ath5k_hw_ops;
/* Initialization and detach functions */
-int ath5k_init_softc(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops);
-void ath5k_deinit_softc(struct ath5k_hw *ah);
int ath5k_hw_init(struct ath5k_hw *ah);
void ath5k_hw_deinit(struct ath5k_hw *ah);
int ath5k_sysfs_register(struct ath5k_hw *ah);
void ath5k_sysfs_unregister(struct ath5k_hw *ah);
-/* base.c */
-struct ath5k_buf;
-struct ath5k_txq;
-
-void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable);
-bool ath5k_any_vif_assoc(struct ath5k_hw *ah);
-void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ath5k_txq *txq);
-int ath5k_start(struct ieee80211_hw *hw);
-void ath5k_stop(struct ieee80211_hw *hw);
-void ath5k_mode_setup(struct ath5k_hw *ah, struct ieee80211_vif *vif);
-void ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
- struct ieee80211_vif *vif);
-int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan);
-void ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf);
-int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-void ath5k_beacon_config(struct ath5k_hw *ah);
-void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
-void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
-
/*Chip id helper functions */
-const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
int ath5k_hw_read_srev(struct ath5k_hw *ah);
/* LED functions */
@@ -1367,7 +1277,7 @@ void ath5k_unregister_leds(struct ath5k_hw *ah);
/* Reset Functions */
-int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
+int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel);
int ath5k_hw_on_hold(struct ath5k_hw *ah);
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
struct ieee80211_channel *channel, bool fast, bool skip_pcu);
@@ -1487,13 +1397,13 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
/* PHY functions */
/* Misc PHY functions */
-u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band);
int ath5k_hw_phy_disable(struct ath5k_hw *ah);
/* Gain_F optimization */
enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
/* PHY/RF channel functions */
-bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
+bool ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel);
/* PHY calibration */
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index f8a6b380d96d..91627dd2c26a 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -25,7 +25,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/**
* ath5k_hw_post - Power On Self Test helper function
@@ -95,7 +94,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
/**
* ath5k_hw_init - Check if hw is supported and init the needed structs
*
- * @ah: The &struct ath5k_hw we got from the driver's init_softc function
+ * @ah: The &struct ath5k_hw associated with the device
*
* Check if the device is supported, perform a POST and initialize the needed
* structs. Returns -ENOMEM if we don't have memory for the needed structs,
@@ -114,7 +113,6 @@ int ath5k_hw_init(struct ath5k_hw *ah)
/*
* HW information
*/
- ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
ah->ah_bwmode = AR5K_BWMODE_DEFAULT;
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
ah->ah_imr = 0;
@@ -137,9 +135,8 @@ int ath5k_hw_init(struct ath5k_hw *ah)
else
ah->ah_version = AR5K_AR5212;
- /* Get the MAC revision */
+ /* Get the MAC version */
ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
- ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
/* Fill the ath5k_hw struct with the needed functions */
ret = ath5k_hw_init_desc_functions(ah);
@@ -147,7 +144,7 @@ int ath5k_hw_init(struct ath5k_hw *ah)
goto err;
/* Bring device out of sleep and reset its units */
- ret = ath5k_hw_nic_wakeup(ah, 0, true);
+ ret = ath5k_hw_nic_wakeup(ah, NULL);
if (ret)
goto err;
@@ -155,8 +152,7 @@ int ath5k_hw_init(struct ath5k_hw *ah)
ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
0xffffffff;
ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
- CHANNEL_5GHZ);
- ah->ah_phy = AR5K_PHY(0);
+ IEEE80211_BAND_5GHZ);
/* Try to identify radio chip based on its srev */
switch (ah->ah_radio_5ghz_revision & 0xf0) {
@@ -164,14 +160,14 @@ int ath5k_hw_init(struct ath5k_hw *ah)
ah->ah_radio = AR5K_RF5111;
ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
- CHANNEL_2GHZ);
+ IEEE80211_BAND_2GHZ);
break;
case AR5K_SREV_RAD_5112:
case AR5K_SREV_RAD_2112:
ah->ah_radio = AR5K_RF5112;
ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
- CHANNEL_2GHZ);
+ IEEE80211_BAND_2GHZ);
break;
case AR5K_SREV_RAD_2413:
ah->ah_radio = AR5K_RF2413;
@@ -208,7 +204,7 @@ int ath5k_hw_init(struct ath5k_hw *ah)
ah->ah_radio = AR5K_RF5111;
ah->ah_single_chip = false;
ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
- CHANNEL_2GHZ);
+ IEEE80211_BAND_2GHZ);
} else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index c3119a6caace..b346d0492001 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -52,6 +52,7 @@
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/etherdevice.h>
+#include <linux/nl80211.h>
#include <net/ieee80211_radiotap.h>
@@ -61,6 +62,8 @@
#include "reg.h"
#include "debug.h"
#include "ani.h"
+#include "ath5k.h"
+#include "../regd.h"
#define CREATE_TRACE_POINTS
#include "trace.h"
@@ -272,20 +275,18 @@ static unsigned int
ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
unsigned int mode, unsigned int max)
{
- unsigned int count, size, chfreq, freq, ch;
+ unsigned int count, size, freq, ch;
enum ieee80211_band band;
switch (mode) {
case AR5K_MODE_11A:
/* 1..220, but 2GHz frequencies are filtered by check_channel */
size = 220;
- chfreq = CHANNEL_5GHZ;
band = IEEE80211_BAND_5GHZ;
break;
case AR5K_MODE_11B:
case AR5K_MODE_11G:
size = 26;
- chfreq = CHANNEL_2GHZ;
band = IEEE80211_BAND_2GHZ;
break;
default:
@@ -300,26 +301,19 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
if (freq == 0) /* mapping failed - not a standard channel */
continue;
+ /* Write channel info, needed for ath5k_channel_ok() */
+ channels[count].center_freq = freq;
+ channels[count].band = band;
+ channels[count].hw_value = mode;
+
/* Check if channel is supported by the chipset */
- if (!ath5k_channel_ok(ah, freq, chfreq))
+ if (!ath5k_channel_ok(ah, &channels[count]))
continue;
if (!modparam_all_channels &&
!ath5k_is_standard_channel(ch, band))
continue;
- /* Write channel info and increment counter */
- channels[count].center_freq = freq;
- channels[count].band = band;
- switch (mode) {
- case AR5K_MODE_11A:
- case AR5K_MODE_11G:
- channels[count].hw_value = chfreq | CHANNEL_OFDM;
- break;
- case AR5K_MODE_11B:
- channels[count].hw_value = CHANNEL_B;
- }
-
count++;
}
@@ -927,12 +921,6 @@ ath5k_txq_setup(struct ath5k_hw *ah,
*/
return ERR_PTR(qnum);
}
- if (qnum >= ARRAY_SIZE(ah->txqs)) {
- ATH5K_ERR(ah, "hw qnum %u out of range, max %tu!\n",
- qnum, ARRAY_SIZE(ah->txqs));
- ath5k_hw_release_tx_queue(ah, qnum);
- return ERR_PTR(-EINVAL);
- }
txq = &ah->txqs[qnum];
if (!txq->setup) {
txq->qnum = qnum;
@@ -2349,7 +2337,7 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
\*************************/
int __devinit
-ath5k_init_softc(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
+ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
{
struct ieee80211_hw *hw = ah->hw;
struct ath_common *common;
@@ -2867,7 +2855,6 @@ ath5k_init(struct ieee80211_hw *hw)
}
SET_IEEE80211_PERM_ADDR(hw, mac);
- memcpy(&ah->lladdr, mac, ETH_ALEN);
/* All MAC address bits matter for ACKs */
ath5k_update_bssid_mask_and_opmode(ah, NULL);
@@ -2903,7 +2890,7 @@ err:
}
void
-ath5k_deinit_softc(struct ath5k_hw *ah)
+ath5k_deinit_ah(struct ath5k_hw *ah)
{
struct ieee80211_hw *hw = ah->hw;
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index a81f28d5bddc..6c94c7ff2350 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -38,19 +38,27 @@
/*
* Definitions for the Atheros Wireless LAN controller driver.
*/
-#ifndef _DEV_ATH_ATHVAR_H
-#define _DEV_ATH_ATHVAR_H
+#ifndef _DEV_ATH5K_BASE_H
+#define _DEV_ATH5K_BASE_H
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/wireless.h>
-#include <linux/if_ether.h>
-#include <linux/rfkill.h>
-#include <linux/workqueue.h>
+struct ieee80211_vif;
+struct ieee80211_hw;
+struct ath5k_hw;
+struct ath5k_txq;
+struct ieee80211_channel;
+struct ath_bus_ops;
+enum nl80211_iftype;
-#include "ath5k.h"
-#include "../regd.h"
-#include "../ath.h"
+enum ath5k_srev_type {
+ AR5K_VERSION_MAC,
+ AR5K_VERSION_RAD,
+};
+
+struct ath5k_srev_name {
+ const char *sr_name;
+ enum ath5k_srev_type sr_type;
+ u_int sr_val;
+};
struct ath5k_buf {
struct list_head list;
@@ -65,7 +73,6 @@ struct ath5k_vif {
enum nl80211_iftype opmode;
int bslot;
struct ath5k_buf *bbuf; /* beacon buffer */
- u8 lladdr[ETH_ALEN];
};
struct ath5k_vif_iter_data {
@@ -78,8 +85,30 @@ struct ath5k_vif_iter_data {
enum nl80211_iftype opmode;
int n_stas;
};
+
void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif);
+bool ath5k_any_vif_assoc(struct ath5k_hw *ah);
+
+int ath5k_start(struct ieee80211_hw *hw);
+void ath5k_stop(struct ieee80211_hw *hw);
+
+void ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf);
+int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void ath5k_beacon_config(struct ath5k_hw *ah);
+void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable);
+
+void ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
+ struct ieee80211_vif *vif);
+int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan);
+void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
+void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
+void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ath5k_txq *txq);
+
+const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
+int ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops);
+void ath5k_deinit_ah(struct ath5k_hw *ah);
/* Check whether BSSID mask is supported */
#define ath5k_hw_hasbssidmask(_ah) (ah->ah_version == AR5K_AR5212)
@@ -87,4 +116,4 @@ void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif);
/* Check whether virtual EOL is supported */
#define ath5k_hw_hasveol(_ah) (ah->ah_version != AR5K_AR5210)
-#endif
+#endif /* _DEV_ATH5K_BASE_H */
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c
index eefe670e28a7..810fba96702b 100644
--- a/drivers/net/wireless/ath/ath5k/caps.c
+++ b/drivers/net/wireless/ath/ath5k/caps.c
@@ -24,7 +24,7 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
+#include "../regd.h"
/*
* Fill the capabilities struct
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index ccca724de173..fce8c904eea9 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -58,19 +58,18 @@
* THE POSSIBILITY OF SUCH DAMAGES.
*/
-#include "base.h"
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/list.h>
#include "debug.h"
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
static unsigned int ath5k_debug;
module_param_named(debug, ath5k_debug, uint, 0);
-#ifdef CONFIG_ATH5K_DEBUG
-
-#include <linux/seq_file.h>
-#include "reg.h"
-#include "ani.h"
-
static int ath5k_debugfs_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
@@ -1031,5 +1030,3 @@ ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf)
td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
}
-
-#endif /* ifdef CONFIG_ATH5K_DEBUG */
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 7f37df3125fd..0a3f916a1ef3 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -141,10 +141,10 @@ ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf);
#include <linux/compiler.h>
-static inline void __attribute__ ((format (printf, 3, 4)))
+static inline __printf(3, 4) void
ATH5K_DBG(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...) {}
-static inline void __attribute__ ((format (printf, 3, 4)))
+static inline __printf(3, 4) void
ATH5K_DBG_UNLIMIT(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...)
{}
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c
index 846535f59efc..7e88dda82221 100644
--- a/drivers/net/wireless/ath/ath5k/desc.c
+++ b/drivers/net/wireless/ath/ath5k/desc.c
@@ -24,7 +24,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/************************\
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index 0d5d4033f12a..2481f9c7f4b6 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -35,7 +35,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/*********\
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 9068b9165265..cd708c15b774 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -26,7 +26,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/******************\
@@ -1780,13 +1779,12 @@ ath5k_eeprom_detach(struct ath5k_hw *ah)
int
ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel)
{
- switch (channel->hw_value & CHANNEL_MODES) {
- case CHANNEL_A:
- case CHANNEL_XR:
+ switch (channel->hw_value) {
+ case AR5K_MODE_11A:
return AR5K_EEPROM_MODE_11A;
- case CHANNEL_G:
+ case AR5K_MODE_11G:
return AR5K_EEPROM_MODE_11G;
- case CHANNEL_B:
+ case AR5K_MODE_11B:
return AR5K_EEPROM_MODE_11B;
default:
return -1;
diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c
index bc90503f4b7a..859297811914 100644
--- a/drivers/net/wireless/ath/ath5k/gpio.c
+++ b/drivers/net/wireless/ath/ath5k/gpio.c
@@ -23,7 +23,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/*
* Set led state
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c
index 5ab607f40e0e..1ffecc0fd3ed 100644
--- a/drivers/net/wireless/ath/ath5k/initvals.c
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
@@ -22,7 +22,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/*
* Mode-independent initial register writes
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 8c17a00f7dad..c1151c723711 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -41,7 +41,6 @@
#include <linux/pci.h>
#include "ath5k.h"
-#include "base.h"
#define ATH_SDEVICE(subv, subd) \
.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 2a715ca0c5e4..6ed4c0717e3e 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -41,8 +41,10 @@
*
*/
+#include <net/mac80211.h>
#include <asm/unaligned.h>
+#include "ath5k.h"
#include "base.h"
#include "reg.h"
@@ -137,11 +139,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
/* Any MAC address is fine, all others are included through the
* filter.
*/
- memcpy(&ah->lladdr, vif->addr, ETH_ALEN);
ath5k_hw_set_lladdr(ah, vif->addr);
- memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
-
ath5k_update_bssid_mask_and_opmode(ah, vif);
ret = 0;
end:
@@ -564,7 +563,7 @@ ath5k_get_stats(struct ieee80211_hw *hw,
static int
-ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
+ath5k_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct ath5k_hw *ah = hw->priv;
@@ -603,7 +602,7 @@ ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
static u64
-ath5k_get_tsf(struct ieee80211_hw *hw)
+ath5k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct ath5k_hw *ah = hw->priv;
@@ -612,7 +611,7 @@ ath5k_get_tsf(struct ieee80211_hw *hw)
static void
-ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+ath5k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 tsf)
{
struct ath5k_hw *ah = hw->priv;
@@ -621,7 +620,7 @@ ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
static void
-ath5k_reset_tsf(struct ieee80211_hw *hw)
+ath5k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct ath5k_hw *ah = hw->priv;
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index eaf79b49341e..c1dff2ced044 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -261,7 +261,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
ah->iobase = mem; /* So we can unmap it on detach */
/* Initialize */
- ret = ath5k_init_softc(ah, &ath_pci_bus_ops);
+ ret = ath5k_init_ah(ah, &ath_pci_bus_ops);
if (ret)
goto err_free;
@@ -287,7 +287,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath5k_hw *ah = hw->priv;
- ath5k_deinit_softc(ah);
+ ath5k_deinit_ah(ah);
pci_iounmap(pdev, ah->iobase);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 067313845060..a7eafa3edc21 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -29,7 +29,6 @@
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/*
* AR5212+ can use higher rates for ack transmission
@@ -152,7 +151,7 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
case AR5K_BWMODE_DEFAULT:
default:
slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
- if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot)
+ if ((channel->hw_value == AR5K_MODE_11B) && !ah->ah_short_slot)
slot_time = AR5K_INIT_SLOT_TIME_B;
break;
}
@@ -183,7 +182,7 @@ unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
case AR5K_BWMODE_DEFAULT:
sifs = AR5K_INIT_SIFS_DEFAULT_BG;
default:
- if (channel->hw_value & CHANNEL_5GHZ)
+ if (channel->band == IEEE80211_BAND_5GHZ)
sifs = AR5K_INIT_SIFS_DEFAULT_A;
break;
}
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 81e465e70175..01cb72de44cb 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -26,9 +26,9 @@
#include "ath5k.h"
#include "reg.h"
-#include "base.h"
#include "rfbuffer.h"
#include "rfgain.h"
+#include "../regd.h"
/******************\
@@ -38,7 +38,7 @@
/*
* Get the PHY Chip revision
*/
-u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band)
{
unsigned int i;
u32 srev;
@@ -47,11 +47,11 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
/*
* Set the radio chip access register
*/
- switch (chan) {
- case CHANNEL_2GHZ:
+ switch (band) {
+ case IEEE80211_BAND_2GHZ:
ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
break;
- case CHANNEL_5GHZ:
+ case IEEE80211_BAND_5GHZ:
ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
break;
default:
@@ -84,14 +84,16 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
/*
* Check if a channel is supported
*/
-bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
+bool ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel)
{
+ u16 freq = channel->center_freq;
+
/* Check if the channel is in our supported range */
- if (flags & CHANNEL_2GHZ) {
+ if (channel->band == IEEE80211_BAND_2GHZ) {
if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
(freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
return true;
- } else if (flags & CHANNEL_5GHZ)
+ } else if (channel->band == IEEE80211_BAND_5GHZ)
if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
(freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
return true;
@@ -224,7 +226,7 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
ds_coef_exp, ds_coef_man, clock;
BUG_ON(!(ah->ah_version == AR5K_AR5212) ||
- !(channel->hw_value & CHANNEL_OFDM));
+ (channel->hw_value == AR5K_MODE_11B));
/* Get coefficient
* ALGO: coef = (5 * clock / carrier_freq) / 2
@@ -298,7 +300,7 @@ static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah,
u32 delay;
delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
AR5K_PHY_RX_DELAY_M;
- delay = (channel->hw_value & CHANNEL_CCK) ?
+ delay = (channel->hw_value == AR5K_MODE_11B) ?
((delay << 2) / 22) : (delay / 10);
if (ah->ah_bwmode == AR5K_BWMODE_10MHZ)
delay = delay << 1;
@@ -798,9 +800,9 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
}
/* Set Output and Driver bias current (OB/DB) */
- if (channel->hw_value & CHANNEL_2GHZ) {
+ if (channel->band == IEEE80211_BAND_2GHZ) {
- if (channel->hw_value & CHANNEL_CCK)
+ if (channel->hw_value == AR5K_MODE_11B)
ee_mode = AR5K_EEPROM_MODE_11B;
else
ee_mode = AR5K_EEPROM_MODE_11G;
@@ -825,7 +827,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
AR5K_RF_DB_2GHZ, true);
/* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */
- } else if ((channel->hw_value & CHANNEL_5GHZ) ||
+ } else if ((channel->band == IEEE80211_BAND_5GHZ) ||
(ah->ah_radio == AR5K_RF5111)) {
/* For 11a, Turbo and XR we need to choose
@@ -857,7 +859,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
if (ah->ah_radio == AR5K_RF5111) {
/* Set gain_F settings according to current step */
- if (channel->hw_value & CHANNEL_OFDM) {
+ if (channel->hw_value != AR5K_MODE_11B) {
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
AR5K_PHY_FRAME_CTL_TX_CLIP,
@@ -914,7 +916,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
if (ah->ah_radio == AR5K_RF5112) {
/* Set gain_F settings according to current step */
- if (channel->hw_value & CHANNEL_OFDM) {
+ if (channel->hw_value != AR5K_MODE_11B) {
ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0],
AR5K_RF_MIXGAIN_OVR, true);
@@ -1026,7 +1028,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
}
if (ah->ah_radio == AR5K_RF5413 &&
- channel->hw_value & CHANNEL_2GHZ) {
+ channel->band == IEEE80211_BAND_2GHZ) {
ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE,
true);
@@ -1138,7 +1140,7 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
*/
data0 = data1 = 0;
- if (channel->hw_value & CHANNEL_2GHZ) {
+ if (channel->band == IEEE80211_BAND_2GHZ) {
/* Map 2GHz channel to 5GHz Atheros channel ID */
ret = ath5k_hw_rf5111_chan2athchan(
ieee80211_frequency_to_channel(channel->center_freq),
@@ -1265,10 +1267,9 @@ static int ath5k_hw_channel(struct ath5k_hw *ah,
int ret;
/*
* Check bounds supported by the PHY (we don't care about regulatory
- * restrictions at this point). Note: hw_value already has the band
- * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
- * of the band by that */
- if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
+ * restrictions at this point).
+ */
+ if (!ath5k_channel_ok(ah, channel)) {
ATH5K_ERR(ah,
"channel frequency (%u MHz) out of supported "
"band range\n",
@@ -1614,7 +1615,7 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
ret = ath5k_hw_rf511x_iq_calibrate(ah);
if ((ah->ah_radio == AR5K_RF5111 || ah->ah_radio == AR5K_RF5112) &&
- (channel->hw_value & CHANNEL_OFDM))
+ (channel->hw_value != AR5K_MODE_11B))
ath5k_hw_request_rfgain_probe(ah);
return ret;
@@ -1641,7 +1642,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
/* Convert current frequency to fbin value (the same way channels
* are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale
* up by 2 so we can compare it later */
- if (channel->hw_value & CHANNEL_2GHZ) {
+ if (channel->band == IEEE80211_BAND_2GHZ) {
chan_fbin = (channel->center_freq - 2300) * 10;
freq_band = AR5K_EEPROM_BAND_2GHZ;
} else {
@@ -1703,7 +1704,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
spur_freq_sigma_delta = (spur_delta_phase >> 10);
symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4;
default:
- if (channel->hw_value == CHANNEL_A) {
+ if (channel->band == IEEE80211_BAND_5GHZ) {
/* Both sample_freq and chip_freq are 40MHz */
spur_delta_phase = (spur_offset << 17) / 25;
spur_freq_sigma_delta =
@@ -2226,15 +2227,20 @@ ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah,
idx_l = 0;
idx_r = 0;
- if (!(channel->hw_value & CHANNEL_OFDM)) {
+ switch (channel->hw_value) {
+ case AR5K_EEPROM_MODE_11A:
+ pcinfo = ee->ee_pwr_cal_a;
+ mode = AR5K_EEPROM_MODE_11A;
+ break;
+ case AR5K_EEPROM_MODE_11B:
pcinfo = ee->ee_pwr_cal_b;
mode = AR5K_EEPROM_MODE_11B;
- } else if (channel->hw_value & CHANNEL_2GHZ) {
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ default:
pcinfo = ee->ee_pwr_cal_g;
mode = AR5K_EEPROM_MODE_11G;
- } else {
- pcinfo = ee->ee_pwr_cal_a;
- mode = AR5K_EEPROM_MODE_11A;
+ break;
}
max = ee->ee_n_piers[mode] - 1;
@@ -2303,15 +2309,20 @@ ath5k_get_rate_pcal_data(struct ath5k_hw *ah,
idx_l = 0;
idx_r = 0;
- if (!(channel->hw_value & CHANNEL_OFDM)) {
+ switch (channel->hw_value) {
+ case AR5K_MODE_11A:
+ rpinfo = ee->ee_rate_tpwr_a;
+ mode = AR5K_EEPROM_MODE_11A;
+ break;
+ case AR5K_MODE_11B:
rpinfo = ee->ee_rate_tpwr_b;
mode = AR5K_EEPROM_MODE_11B;
- } else if (channel->hw_value & CHANNEL_2GHZ) {
+ break;
+ case AR5K_MODE_11G:
+ default:
rpinfo = ee->ee_rate_tpwr_g;
mode = AR5K_EEPROM_MODE_11G;
- } else {
- rpinfo = ee->ee_rate_tpwr_a;
- mode = AR5K_EEPROM_MODE_11A;
+ break;
}
max = ee->ee_rate_target_pwr_num[mode] - 1;
@@ -2392,24 +2403,22 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,
ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band);
- switch (channel->hw_value & CHANNEL_MODES) {
- case CHANNEL_A:
+ switch (channel->hw_value) {
+ case AR5K_MODE_11A:
if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
ctl_mode |= AR5K_CTL_TURBO;
else
ctl_mode |= AR5K_CTL_11A;
break;
- case CHANNEL_G:
+ case AR5K_MODE_11G:
if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
ctl_mode |= AR5K_CTL_TURBOG;
else
ctl_mode |= AR5K_CTL_11G;
break;
- case CHANNEL_B:
+ case AR5K_MODE_11B:
ctl_mode |= AR5K_CTL_11B;
break;
- case CHANNEL_XR:
- /* Fall through */
default:
return;
}
@@ -3292,7 +3301,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
/* Write OFDM timings on 5212*/
if (ah->ah_version == AR5K_AR5212 &&
- channel->hw_value & CHANNEL_OFDM) {
+ channel->hw_value != AR5K_MODE_11B) {
ret = ath5k_hw_write_ofdm_timings(ah, channel);
if (ret)
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 65f10398999e..776654228eaa 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -23,7 +23,6 @@ Queue Control Unit, DFS Control Unit Functions
#include "ath5k.h"
#include "reg.h"
#include "debug.h"
-#include "base.h"
/******************\
@@ -185,13 +184,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
case AR5K_TX_QUEUE_CAB:
queue = AR5K_TX_QUEUE_ID_CAB;
break;
- case AR5K_TX_QUEUE_XR_DATA:
- if (ah->ah_version != AR5K_AR5212)
- ATH5K_ERR(ah,
- "XR data queues only supported in"
- " 5212!\n");
- queue = AR5K_TX_QUEUE_ID_XR_DATA;
- break;
default:
return -EINVAL;
}
@@ -544,7 +536,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
*
* Also we have different lowest rate for 802.11a
*/
- if (channel->hw_value & CHANNEL_5GHZ)
+ if (channel->band == IEEE80211_BAND_5GHZ)
rate = &ah->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
else
rate = &ah->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 0686c5d8d56e..2abac257b4b4 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -30,7 +30,6 @@
#include <linux/platform_device.h>
#include "ath5k.h"
#include "reg.h"
-#include "base.h"
#include "debug.h"
@@ -102,12 +101,18 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
/*
* Set core clock frequency
*/
- if (channel->hw_value & CHANNEL_5GHZ)
- clock = 40; /* 802.11a */
- else if (channel->hw_value & CHANNEL_CCK)
- clock = 22; /* 802.11b */
- else
- clock = 44; /* 802.11g */
+ switch (channel->hw_value) {
+ case AR5K_MODE_11A:
+ clock = 40;
+ break;
+ case AR5K_MODE_11B:
+ clock = 22;
+ break;
+ case AR5K_MODE_11G:
+ default:
+ clock = 44;
+ break;
+ }
/* Use clock multiplier for non-default
* bwmode */
@@ -581,8 +586,9 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
/*
* Bring up MAC + PHY Chips and program PLL
+ * Channel is NULL for the initial wakeup.
*/
-int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
+int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
{
struct pci_dev *pdev = ah->pdev;
u32 turbo, mode, clock, bus_flags;
@@ -592,7 +598,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
mode = 0;
clock = 0;
- if ((ath5k_get_bus_type(ah) != ATH_AHB) || !initial) {
+ if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) {
/* Wakeup the device */
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {
@@ -652,7 +658,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
/* On initialization skip PLL programming since we don't have
* a channel / mode set yet */
- if (initial)
+ if (!channel)
return 0;
if (ah->ah_version != AR5K_AR5210) {
@@ -668,13 +674,13 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
clock = AR5K_PHY_PLL_RF5111; /*Zero*/
}
- if (flags & CHANNEL_2GHZ) {
+ if (channel->band == IEEE80211_BAND_2GHZ) {
mode |= AR5K_PHY_MODE_FREQ_2GHZ;
clock |= AR5K_PHY_PLL_44MHZ;
- if (flags & CHANNEL_CCK) {
+ if (channel->hw_value == AR5K_MODE_11B) {
mode |= AR5K_PHY_MODE_MOD_CCK;
- } else if (flags & CHANNEL_OFDM) {
+ } else {
/* XXX Dynamic OFDM/CCK is not supported by the
* AR5211 so we set MOD_OFDM for plain g (no
* CCK headers) operation. We need to test
@@ -686,27 +692,16 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
mode |= AR5K_PHY_MODE_MOD_OFDM;
else
mode |= AR5K_PHY_MODE_MOD_DYN;
- } else {
- ATH5K_ERR(ah,
- "invalid radio modulation mode\n");
- return -EINVAL;
}
- } else if (flags & CHANNEL_5GHZ) {
- mode |= AR5K_PHY_MODE_FREQ_5GHZ;
+ } else if (channel->band == IEEE80211_BAND_5GHZ) {
+ mode |= (AR5K_PHY_MODE_FREQ_5GHZ |
+ AR5K_PHY_MODE_MOD_OFDM);
/* Different PLL setting for 5413 */
if (ah->ah_radio == AR5K_RF5413)
clock = AR5K_PHY_PLL_40MHZ_5413;
else
clock |= AR5K_PHY_PLL_40MHZ;
-
- if (flags & CHANNEL_OFDM)
- mode |= AR5K_PHY_MODE_MOD_OFDM;
- else {
- ATH5K_ERR(ah,
- "invalid radio modulation mode\n");
- return -EINVAL;
- }
} else {
ATH5K_ERR(ah, "invalid radio frequency mode\n");
return -EINVAL;
@@ -822,7 +817,7 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
u32 data;
ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
AR5K_PHY_CCKTXCTL);
- if (channel->hw_value & CHANNEL_5GHZ)
+ if (channel->band == IEEE80211_BAND_5GHZ)
data = 0xffb81020;
else
data = 0xffb80d20;
@@ -905,7 +900,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
/* Set CCK to OFDM power delta on tx power
* adjustment register */
if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
- if (channel->hw_value == CHANNEL_G)
+ if (channel->hw_value == AR5K_MODE_11G)
ath5k_hw_reg_write(ah,
AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
@@ -1084,37 +1079,23 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ret = 0;
}
- switch (channel->hw_value & CHANNEL_MODES) {
- case CHANNEL_A:
- mode = AR5K_MODE_11A;
+ mode = channel->hw_value;
+ switch (mode) {
+ case AR5K_MODE_11A:
break;
- case CHANNEL_G:
-
+ case AR5K_MODE_11G:
if (ah->ah_version <= AR5K_AR5211) {
ATH5K_ERR(ah,
"G mode not available on 5210/5211");
return -EINVAL;
}
-
- mode = AR5K_MODE_11G;
break;
- case CHANNEL_B:
-
+ case AR5K_MODE_11B:
if (ah->ah_version < AR5K_AR5211) {
ATH5K_ERR(ah,
"B mode not available on 5210");
return -EINVAL;
}
-
- mode = AR5K_MODE_11B;
- break;
- case CHANNEL_XR:
- if (ah->ah_version == AR5K_AR5211) {
- ATH5K_ERR(ah,
- "XR mode not available on 5211");
- return -EINVAL;
- }
- mode = AR5K_MODE_XR;
break;
default:
ATH5K_ERR(ah,
@@ -1200,7 +1181,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
}
/* Wakeup the device */
- ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
+ ret = ath5k_hw_nic_wakeup(ah, channel);
if (ret)
return ret;
diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c
index 945fc9f21e76..270a319f3aeb 100644
--- a/drivers/net/wireless/ath/ath5k/rfkill.c
+++ b/drivers/net/wireless/ath/ath5k/rfkill.c
@@ -33,7 +33,7 @@
* THE POSSIBILITY OF SUCH DAMAGES.
*/
-#include "base.h"
+#include "ath5k.h"
static inline void ath5k_rfkill_disable(struct ath5k_hw *ah)
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c
index 0244a36ba958..9364da7bd131 100644
--- a/drivers/net/wireless/ath/ath5k/sysfs.c
+++ b/drivers/net/wireless/ath/ath5k/sysfs.c
@@ -1,7 +1,6 @@
#include <linux/device.h>
#include <linux/pci.h>
-#include "base.h"
#include "ath5k.h"
#include "reg.h"
diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h
index c741c871f4e9..39f002ed4a88 100644
--- a/drivers/net/wireless/ath/ath5k/trace.h
+++ b/drivers/net/wireless/ath/ath5k/trace.h
@@ -2,7 +2,6 @@
#define __TRACE_ATH5K_H
#include <linux/tracepoint.h>
-#include "base.h"
#ifndef CONFIG_ATH5K_TRACER
#undef TRACE_EVENT
@@ -11,6 +10,8 @@ static inline void trace_ ## name(proto) {}
#endif
struct sk_buff;
+struct ath5k_txq;
+struct ath5k_tx_status;
#undef TRACE_SYSTEM
#define TRACE_SYSTEM ath5k
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig
new file mode 100644
index 000000000000..3d5f8be20eac
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/Kconfig
@@ -0,0 +1,15 @@
+config ATH6KL
+ tristate "Atheros ath6kl support"
+ depends on MMC
+ depends on CFG80211
+ ---help---
+ This module adds support for wireless adapters based on
+ Atheros AR6003 chipset running over SDIO. If you choose to
+ build it as a module, it will be called ath6kl. Pls note
+ that AR6002 and AR6001 are not supported by this driver.
+
+config ATH6KL_DEBUG
+ bool "Atheros ath6kl debugging"
+ depends on ATH6KL
+ ---help---
+ Enables debug support
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
new file mode 100644
index 000000000000..8f7a0d1c290c
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -0,0 +1,37 @@
+#------------------------------------------------------------------------------
+# Copyright (c) 2004-2010 Atheros Communications Inc.
+# All rights reserved.
+#
+#
+#
+# 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.
+#
+#
+#
+# Author(s): ="Atheros"
+#------------------------------------------------------------------------------
+
+obj-$(CONFIG_ATH6KL) := ath6kl.o
+ath6kl-y += debug.o
+ath6kl-y += htc_hif.o
+ath6kl-y += htc.o
+ath6kl-y += bmi.o
+ath6kl-y += cfg80211.o
+ath6kl-y += init.o
+ath6kl-y += main.o
+ath6kl-y += txrx.o
+ath6kl-y += wmi.o
+ath6kl-y += sdio.o
+ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c
new file mode 100644
index 000000000000..c5d11cc536e0
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/bmi.c
@@ -0,0 +1,689 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications 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 "hif-ops.h"
+#include "target.h"
+#include "debug.h"
+
+static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar)
+{
+ u32 addr;
+ unsigned long timeout;
+ int ret;
+
+ ar->bmi.cmd_credits = 0;
+
+ /* Read the counter register to get the command credits */
+ addr = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
+
+ timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
+ while (time_before(jiffies, timeout) && !ar->bmi.cmd_credits) {
+
+ /*
+ * Hit the credit counter with a 4-byte access, the first byte
+ * read will hit the counter and cause a decrement, while the
+ * remaining 3 bytes has no effect. The rationale behind this
+ * is to make all HIF accesses 4-byte aligned.
+ */
+ ret = hif_read_write_sync(ar, addr,
+ (u8 *)&ar->bmi.cmd_credits, 4,
+ HIF_RD_SYNC_BYTE_INC);
+ if (ret) {
+ ath6kl_err("Unable to decrement the command credit count register: %d\n",
+ ret);
+ return ret;
+ }
+
+ /* The counter is only 8 bits.
+ * Ignore anything in the upper 3 bytes
+ */
+ ar->bmi.cmd_credits &= 0xFF;
+ }
+
+ if (!ar->bmi.cmd_credits) {
+ ath6kl_err("bmi communication timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar)
+{
+ unsigned long timeout;
+ u32 rx_word = 0;
+ int ret = 0;
+
+ timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
+ while (time_before(jiffies, timeout) && !rx_word) {
+ ret = hif_read_write_sync(ar, RX_LOOKAHEAD_VALID_ADDRESS,
+ (u8 *)&rx_word, sizeof(rx_word),
+ HIF_RD_SYNC_BYTE_INC);
+ if (ret) {
+ ath6kl_err("unable to read RX_LOOKAHEAD_VALID\n");
+ return ret;
+ }
+
+ /* all we really want is one bit */
+ rx_word &= (1 << ENDPOINT1);
+ }
+
+ if (!rx_word) {
+ ath6kl_err("bmi_recv_buf FIFO empty\n");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len)
+{
+ int ret;
+ u32 addr;
+
+ ret = ath6kl_get_bmi_cmd_credits(ar);
+ if (ret)
+ return ret;
+
+ addr = ar->mbox_info.htc_addr;
+
+ ret = hif_read_write_sync(ar, addr, buf, len,
+ HIF_WR_SYNC_BYTE_INC);
+ if (ret)
+ ath6kl_err("unable to send the bmi data to the device\n");
+
+ return ret;
+}
+
+static int ath6kl_bmi_recv_buf(struct ath6kl *ar, u8 *buf, u32 len)
+{
+ int ret;
+ u32 addr;
+
+ /*
+ * During normal bootup, small reads may be required.
+ * Rather than issue an HIF Read and then wait as the Target
+ * adds successive bytes to the FIFO, we wait here until
+ * we know that response data is available.
+ *
+ * This allows us to cleanly timeout on an unexpected
+ * Target failure rather than risk problems at the HIF level.
+ * In particular, this avoids SDIO timeouts and possibly garbage
+ * data on some host controllers. And on an interconnect
+ * such as Compact Flash (as well as some SDIO masters) which
+ * does not provide any indication on data timeout, it avoids
+ * a potential hang or garbage response.
+ *
+ * Synchronization is more difficult for reads larger than the
+ * size of the MBOX FIFO (128B), because the Target is unable
+ * to push the 129th byte of data until AFTER the Host posts an
+ * HIF Read and removes some FIFO data. So for large reads the
+ * Host proceeds to post an HIF Read BEFORE all the data is
+ * actually available to read. Fortunately, large BMI reads do
+ * not occur in practice -- they're supported for debug/development.
+ *
+ * So Host/Target BMI synchronization is divided into these cases:
+ * CASE 1: length < 4
+ * Should not happen
+ *
+ * CASE 2: 4 <= length <= 128
+ * Wait for first 4 bytes to be in FIFO
+ * If CONSERVATIVE_BMI_READ is enabled, also wait for
+ * a BMI command credit, which indicates that the ENTIRE
+ * response is available in the the FIFO
+ *
+ * CASE 3: length > 128
+ * Wait for the first 4 bytes to be in FIFO
+ *
+ * For most uses, a small timeout should be sufficient and we will
+ * usually see a response quickly; but there may be some unusual
+ * (debug) cases of BMI_EXECUTE where we want an larger timeout.
+ * For now, we use an unbounded busy loop while waiting for
+ * BMI_EXECUTE.
+ *
+ * If BMI_EXECUTE ever needs to support longer-latency execution,
+ * especially in production, this code needs to be enhanced to sleep
+ * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently
+ * a function of Host processor speed.
+ */
+ if (len >= 4) { /* NB: Currently, always true */
+ ret = ath6kl_bmi_get_rx_lkahd(ar);
+ if (ret)
+ return ret;
+ }
+
+ addr = ar->mbox_info.htc_addr;
+ ret = hif_read_write_sync(ar, addr, buf, len,
+ HIF_RD_SYNC_BYTE_INC);
+ if (ret) {
+ ath6kl_err("Unable to read the bmi data from the device: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int ath6kl_bmi_done(struct ath6kl *ar)
+{
+ int ret;
+ u32 cid = BMI_DONE;
+
+ if (ar->bmi.done_sent) {
+ ath6kl_dbg(ATH6KL_DBG_BMI, "bmi done skipped\n");
+ return 0;
+ }
+
+ ar->bmi.done_sent = true;
+
+ ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid));
+ if (ret) {
+ ath6kl_err("Unable to send bmi done: %d\n", ret);
+ return ret;
+ }
+
+ ath6kl_bmi_cleanup(ar);
+
+ return 0;
+}
+
+int ath6kl_bmi_get_target_info(struct ath6kl *ar,
+ struct ath6kl_bmi_target_info *targ_info)
+{
+ int ret;
+ u32 cid = BMI_GET_TARGET_INFO;
+
+ if (ar->bmi.done_sent) {
+ ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
+ return -EACCES;
+ }
+
+ ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid));
+ if (ret) {
+ ath6kl_err("Unable to send get target info: %d\n", ret);
+ return ret;
+ }
+
+ ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->version,
+ sizeof(targ_info->version));
+ if (ret) {
+ ath6kl_err("Unable to recv target info: %d\n", ret);
+ return ret;
+ }
+
+ if (le32_to_cpu(targ_info->version) == TARGET_VERSION_SENTINAL) {
+ /* Determine how many bytes are in the Target's targ_info */
+ ret = ath6kl_bmi_recv_buf(ar,
+ (u8 *)&targ_info->byte_count,
+ sizeof(targ_info->byte_count));
+ if (ret) {
+ ath6kl_err("unable to read target info byte count: %d\n",
+ ret);
+ return ret;
+ }
+
+ /*
+ * The target's targ_info doesn't match the host's targ_info.
+ * We need to do some backwards compatibility to make this work.
+ */
+ if (le32_to_cpu(targ_info->byte_count) != sizeof(*targ_info)) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ /* Read the remainder of the targ_info */
+ ret = ath6kl_bmi_recv_buf(ar,
+ ((u8 *)targ_info) +
+ sizeof(targ_info->byte_count),
+ sizeof(*targ_info) -
+ sizeof(targ_info->byte_count));
+
+ if (ret) {
+ ath6kl_err("Unable to read target info (%d bytes): %d\n",
+ targ_info->byte_count, ret);
+ return ret;
+ }
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_BMI, "target info (ver: 0x%x type: 0x%x)\n",
+ targ_info->version, targ_info->type);
+
+ return 0;
+}
+
+int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
+{
+ u32 cid = BMI_READ_MEMORY;
+ int ret;
+ u32 offset;
+ u32 len_remain, rx_len;
+ u16 size;
+
+ if (ar->bmi.done_sent) {
+ ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
+ return -EACCES;
+ }
+
+ size = BMI_DATASZ_MAX + sizeof(cid) + sizeof(addr) + sizeof(len);
+ if (size > MAX_BMI_CMDBUF_SZ) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ memset(ar->bmi.cmd_buf, 0, size);
+
+ ath6kl_dbg(ATH6KL_DBG_BMI,
+ "bmi read memory: device: addr: 0x%x, len: %d\n",
+ addr, len);
+
+ len_remain = len;
+
+ while (len_remain) {
+ rx_len = (len_remain < BMI_DATASZ_MAX) ?
+ len_remain : BMI_DATASZ_MAX;
+ offset = 0;
+ memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
+ offset += sizeof(addr);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &rx_len, sizeof(rx_len));
+ offset += sizeof(len);
+
+ ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+ if (ret) {
+ ath6kl_err("Unable to write to the device: %d\n",
+ ret);
+ return ret;
+ }
+ ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len);
+ if (ret) {
+ ath6kl_err("Unable to read from the device: %d\n",
+ ret);
+ return ret;
+ }
+ memcpy(&buf[len - len_remain], ar->bmi.cmd_buf, rx_len);
+ len_remain -= rx_len; addr += rx_len;
+ }
+
+ return 0;
+}
+
+int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
+{
+ u32 cid = BMI_WRITE_MEMORY;
+ int ret;
+ u32 offset;
+ u32 len_remain, tx_len;
+ const u32 header = sizeof(cid) + sizeof(addr) + sizeof(len);
+ u8 aligned_buf[BMI_DATASZ_MAX];
+ u8 *src;
+
+ if (ar->bmi.done_sent) {
+ ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
+ return -EACCES;
+ }
+
+ if ((BMI_DATASZ_MAX + header) > MAX_BMI_CMDBUF_SZ) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ memset(ar->bmi.cmd_buf, 0, BMI_DATASZ_MAX + header);
+
+ ath6kl_dbg(ATH6KL_DBG_BMI,
+ "bmi write memory: addr: 0x%x, len: %d\n", addr, len);
+
+ len_remain = len;
+ while (len_remain) {
+ src = &buf[len - len_remain];
+
+ if (len_remain < (BMI_DATASZ_MAX - header)) {
+ if (len_remain & 3) {
+ /* align it with 4 bytes */
+ len_remain = len_remain +
+ (4 - (len_remain & 3));
+ memcpy(aligned_buf, src, len_remain);
+ src = aligned_buf;
+ }
+ tx_len = len_remain;
+ } else {
+ tx_len = (BMI_DATASZ_MAX - header);
+ }
+
+ offset = 0;
+ memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
+ offset += sizeof(addr);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len));
+ offset += sizeof(tx_len);
+ memcpy(&(ar->bmi.cmd_buf[offset]), src, tx_len);
+ offset += tx_len;
+
+ ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+ if (ret) {
+ ath6kl_err("Unable to write to the device: %d\n",
+ ret);
+ return ret;
+ }
+ len_remain -= tx_len; addr += tx_len;
+ }
+
+ return 0;
+}
+
+int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
+{
+ u32 cid = BMI_EXECUTE;
+ int ret;
+ u32 offset;
+ u16 size;
+
+ if (ar->bmi.done_sent) {
+ ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
+ return -EACCES;
+ }
+
+ size = sizeof(cid) + sizeof(addr) + sizeof(param);
+ if (size > MAX_BMI_CMDBUF_SZ) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ memset(ar->bmi.cmd_buf, 0, size);
+
+ ath6kl_dbg(ATH6KL_DBG_BMI, "bmi execute: addr: 0x%x, param: %d)\n",
+ addr, *param);
+
+ offset = 0;
+ memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
+ offset += sizeof(addr);
+ memcpy(&(ar->bmi.cmd_buf[offset]), param, sizeof(*param));
+ offset += sizeof(*param);
+
+ ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+ if (ret) {
+ ath6kl_err("Unable to write to the device: %d\n", ret);
+ return ret;
+ }
+
+ ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param));
+ if (ret) {
+ ath6kl_err("Unable to read from the device: %d\n", ret);
+ return ret;
+ }
+
+ memcpy(param, ar->bmi.cmd_buf, sizeof(*param));
+
+ return 0;
+}
+
+int ath6kl_bmi_set_app_start(struct ath6kl *ar, u32 addr)
+{
+ u32 cid = BMI_SET_APP_START;
+ int ret;
+ u32 offset;
+ u16 size;
+
+ if (ar->bmi.done_sent) {
+ ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
+ return -EACCES;
+ }
+
+ size = sizeof(cid) + sizeof(addr);
+ if (size > MAX_BMI_CMDBUF_SZ) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ memset(ar->bmi.cmd_buf, 0, size);
+
+ ath6kl_dbg(ATH6KL_DBG_BMI, "bmi set app start: addr: 0x%x\n", addr);
+
+ offset = 0;
+ memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
+ offset += sizeof(addr);
+
+ ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+ if (ret) {
+ ath6kl_err("Unable to write to the device: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param)
+{
+ u32 cid = BMI_READ_SOC_REGISTER;
+ int ret;
+ u32 offset;
+ u16 size;
+
+ if (ar->bmi.done_sent) {
+ ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
+ return -EACCES;
+ }
+
+ size = sizeof(cid) + sizeof(addr);
+ if (size > MAX_BMI_CMDBUF_SZ) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ memset(ar->bmi.cmd_buf, 0, size);
+
+ ath6kl_dbg(ATH6KL_DBG_BMI, "bmi read SOC reg: addr: 0x%x\n", addr);
+
+ offset = 0;
+ memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
+ offset += sizeof(addr);
+
+ ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+ if (ret) {
+ ath6kl_err("Unable to write to the device: %d\n", ret);
+ return ret;
+ }
+
+ ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param));
+ if (ret) {
+ ath6kl_err("Unable to read from the device: %d\n", ret);
+ return ret;
+ }
+ memcpy(param, ar->bmi.cmd_buf, sizeof(*param));
+
+ return 0;
+}
+
+int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param)
+{
+ u32 cid = BMI_WRITE_SOC_REGISTER;
+ int ret;
+ u32 offset;
+ u16 size;
+
+ if (ar->bmi.done_sent) {
+ ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
+ return -EACCES;
+ }
+
+ size = sizeof(cid) + sizeof(addr) + sizeof(param);
+ if (size > MAX_BMI_CMDBUF_SZ) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ memset(ar->bmi.cmd_buf, 0, size);
+
+ ath6kl_dbg(ATH6KL_DBG_BMI,
+ "bmi write SOC reg: addr: 0x%x, param: %d\n",
+ addr, param);
+
+ offset = 0;
+ memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
+ offset += sizeof(addr);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &param, sizeof(param));
+ offset += sizeof(param);
+
+ ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+ if (ret) {
+ ath6kl_err("Unable to write to the device: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
+{
+ u32 cid = BMI_LZ_DATA;
+ int ret;
+ u32 offset;
+ u32 len_remain, tx_len;
+ const u32 header = sizeof(cid) + sizeof(len);
+ u16 size;
+
+ if (ar->bmi.done_sent) {
+ ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
+ return -EACCES;
+ }
+
+ size = BMI_DATASZ_MAX + header;
+ if (size > MAX_BMI_CMDBUF_SZ) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ memset(ar->bmi.cmd_buf, 0, size);
+
+ ath6kl_dbg(ATH6KL_DBG_BMI, "bmi send LZ data: len: %d)\n",
+ len);
+
+ len_remain = len;
+ while (len_remain) {
+ tx_len = (len_remain < (BMI_DATASZ_MAX - header)) ?
+ len_remain : (BMI_DATASZ_MAX - header);
+
+ offset = 0;
+ memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len));
+ offset += sizeof(tx_len);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &buf[len - len_remain],
+ tx_len);
+ offset += tx_len;
+
+ ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+ if (ret) {
+ ath6kl_err("Unable to write to the device: %d\n",
+ ret);
+ return ret;
+ }
+
+ len_remain -= tx_len;
+ }
+
+ return 0;
+}
+
+int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, u32 addr)
+{
+ u32 cid = BMI_LZ_STREAM_START;
+ int ret;
+ u32 offset;
+ u16 size;
+
+ if (ar->bmi.done_sent) {
+ ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
+ return -EACCES;
+ }
+
+ size = sizeof(cid) + sizeof(addr);
+ if (size > MAX_BMI_CMDBUF_SZ) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ memset(ar->bmi.cmd_buf, 0, size);
+
+ ath6kl_dbg(ATH6KL_DBG_BMI,
+ "bmi LZ stream start: addr: 0x%x)\n",
+ addr);
+
+ offset = 0;
+ memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
+ offset += sizeof(addr);
+
+ ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+ if (ret) {
+ ath6kl_err("Unable to start LZ stream to the device: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int ath6kl_bmi_fast_download(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
+{
+ int ret;
+ u32 last_word = 0;
+ u32 last_word_offset = len & ~0x3;
+ u32 unaligned_bytes = len & 0x3;
+
+ ret = ath6kl_bmi_lz_stream_start(ar, addr);
+ if (ret)
+ return ret;
+
+ if (unaligned_bytes) {
+ /* copy the last word into a zero padded buffer */
+ memcpy(&last_word, &buf[last_word_offset], unaligned_bytes);
+ }
+
+ ret = ath6kl_bmi_lz_data(ar, buf, last_word_offset);
+ if (ret)
+ return ret;
+
+ if (unaligned_bytes)
+ ret = ath6kl_bmi_lz_data(ar, (u8 *)&last_word, 4);
+
+ if (!ret) {
+ /* Close compressed stream and open a new (fake) one.
+ * This serves mainly to flush Target caches. */
+ ret = ath6kl_bmi_lz_stream_start(ar, 0x00);
+ }
+ return ret;
+}
+
+int ath6kl_bmi_init(struct ath6kl *ar)
+{
+ ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC);
+
+ if (!ar->bmi.cmd_buf)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void ath6kl_bmi_cleanup(struct ath6kl *ar)
+{
+ kfree(ar->bmi.cmd_buf);
+ ar->bmi.cmd_buf = NULL;
+}
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h
new file mode 100644
index 000000000000..96851d5df24b
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/bmi.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef BMI_H
+#define BMI_H
+
+/*
+ * Bootloader Messaging Interface (BMI)
+ *
+ * BMI is a very simple messaging interface used during initialization
+ * to read memory, write memory, execute code, and to define an
+ * application entry PC.
+ *
+ * It is used to download an application to ATH6KL, to provide
+ * patches to code that is already resident on ATH6KL, and generally
+ * to examine and modify state. The Host has an opportunity to use
+ * BMI only once during bootup. Once the Host issues a BMI_DONE
+ * command, this opportunity ends.
+ *
+ * The Host writes BMI requests to mailbox0, and reads BMI responses
+ * from mailbox0. BMI requests all begin with a command
+ * (see below for specific commands), and are followed by
+ * command-specific data.
+ *
+ * Flow control:
+ * The Host can only issue a command once the Target gives it a
+ * "BMI Command Credit", using ATH6KL Counter #4. As soon as the
+ * Target has completed a command, it issues another BMI Command
+ * Credit (so the Host can issue the next command).
+ *
+ * BMI handles all required Target-side cache flushing.
+ */
+
+#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
+ (sizeof(u32) * 3 /* cmd + addr + len */))
+
+/* Maximum data size used for BMI transfers */
+#define BMI_DATASZ_MAX 256
+
+/* BMI Commands */
+
+#define BMI_NO_COMMAND 0
+
+#define BMI_DONE 1
+/*
+ * Semantics: Host is done using BMI
+ * Request format:
+ * u32 command (BMI_DONE)
+ * Response format: none
+ */
+
+#define BMI_READ_MEMORY 2
+/*
+ * Semantics: Host reads ATH6KL memory
+ * Request format:
+ * u32 command (BMI_READ_MEMORY)
+ * u32 address
+ * u32 length, at most BMI_DATASZ_MAX
+ * Response format:
+ * u8 data[length]
+ */
+
+#define BMI_WRITE_MEMORY 3
+/*
+ * Semantics: Host writes ATH6KL memory
+ * Request format:
+ * u32 command (BMI_WRITE_MEMORY)
+ * u32 address
+ * u32 length, at most BMI_DATASZ_MAX
+ * u8 data[length]
+ * Response format: none
+ */
+
+#define BMI_EXECUTE 4
+/*
+ * Semantics: Causes ATH6KL to execute code
+ * Request format:
+ * u32 command (BMI_EXECUTE)
+ * u32 address
+ * u32 parameter
+ * Response format:
+ * u32 return value
+ */
+
+#define BMI_SET_APP_START 5
+/*
+ * Semantics: Set Target application starting address
+ * Request format:
+ * u32 command (BMI_SET_APP_START)
+ * u32 address
+ * Response format: none
+ */
+
+#define BMI_READ_SOC_REGISTER 6
+/*
+ * Semantics: Read a 32-bit Target SOC register.
+ * Request format:
+ * u32 command (BMI_READ_REGISTER)
+ * u32 address
+ * Response format:
+ * u32 value
+ */
+
+#define BMI_WRITE_SOC_REGISTER 7
+/*
+ * Semantics: Write a 32-bit Target SOC register.
+ * Request format:
+ * u32 command (BMI_WRITE_REGISTER)
+ * u32 address
+ * u32 value
+ *
+ * Response format: none
+ */
+
+#define BMI_GET_TARGET_ID 8
+#define BMI_GET_TARGET_INFO 8
+/*
+ * Semantics: Fetch the 4-byte Target information
+ * Request format:
+ * u32 command (BMI_GET_TARGET_ID/INFO)
+ * Response format1 (old firmware):
+ * u32 TargetVersionID
+ * Response format2 (newer firmware):
+ * u32 TARGET_VERSION_SENTINAL
+ * struct bmi_target_info;
+ */
+
+#define TARGET_VERSION_SENTINAL 0xffffffff
+#define TARGET_TYPE_AR6003 3
+#define TARGET_TYPE_AR6004 5
+#define BMI_ROMPATCH_INSTALL 9
+/*
+ * Semantics: Install a ROM Patch.
+ * Request format:
+ * u32 command (BMI_ROMPATCH_INSTALL)
+ * u32 Target ROM Address
+ * u32 Target RAM Address or Value (depending on Target Type)
+ * u32 Size, in bytes
+ * u32 Activate? 1-->activate;
+ * 0-->install but do not activate
+ * Response format:
+ * u32 PatchID
+ */
+
+#define BMI_ROMPATCH_UNINSTALL 10
+/*
+ * Semantics: Uninstall a previously-installed ROM Patch,
+ * automatically deactivating, if necessary.
+ * Request format:
+ * u32 command (BMI_ROMPATCH_UNINSTALL)
+ * u32 PatchID
+ *
+ * Response format: none
+ */
+
+#define BMI_ROMPATCH_ACTIVATE 11
+/*
+ * Semantics: Activate a list of previously-installed ROM Patches.
+ * Request format:
+ * u32 command (BMI_ROMPATCH_ACTIVATE)
+ * u32 rompatch_count
+ * u32 PatchID[rompatch_count]
+ *
+ * Response format: none
+ */
+
+#define BMI_ROMPATCH_DEACTIVATE 12
+/*
+ * Semantics: Deactivate a list of active ROM Patches.
+ * Request format:
+ * u32 command (BMI_ROMPATCH_DEACTIVATE)
+ * u32 rompatch_count
+ * u32 PatchID[rompatch_count]
+ *
+ * Response format: none
+ */
+
+
+#define BMI_LZ_STREAM_START 13
+/*
+ * Semantics: Begin an LZ-compressed stream of input
+ * which is to be uncompressed by the Target to an
+ * output buffer at address. The output buffer must
+ * be sufficiently large to hold the uncompressed
+ * output from the compressed input stream. This BMI
+ * command should be followed by a series of 1 or more
+ * BMI_LZ_DATA commands.
+ * u32 command (BMI_LZ_STREAM_START)
+ * u32 address
+ * Note: Not supported on all versions of ROM firmware.
+ */
+
+#define BMI_LZ_DATA 14
+/*
+ * Semantics: Host writes ATH6KL memory with LZ-compressed
+ * data which is uncompressed by the Target. This command
+ * must be preceded by a BMI_LZ_STREAM_START command. A series
+ * of BMI_LZ_DATA commands are considered part of a single
+ * input stream until another BMI_LZ_STREAM_START is issued.
+ * Request format:
+ * u32 command (BMI_LZ_DATA)
+ * u32 length (of compressed data),
+ * at most BMI_DATASZ_MAX
+ * u8 CompressedData[length]
+ * Response format: none
+ * Note: Not supported on all versions of ROM firmware.
+ */
+
+#define BMI_COMMUNICATION_TIMEOUT 1000 /* in msec */
+
+struct ath6kl;
+struct ath6kl_bmi_target_info {
+ __le32 byte_count; /* size of this structure */
+ __le32 version; /* target version id */
+ __le32 type; /* target type */
+} __packed;
+
+int ath6kl_bmi_init(struct ath6kl *ar);
+void ath6kl_bmi_cleanup(struct ath6kl *ar);
+int ath6kl_bmi_done(struct ath6kl *ar);
+int ath6kl_bmi_get_target_info(struct ath6kl *ar,
+ struct ath6kl_bmi_target_info *targ_info);
+int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len);
+int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len);
+int ath6kl_bmi_execute(struct ath6kl *ar,
+ u32 addr, u32 *param);
+int ath6kl_bmi_set_app_start(struct ath6kl *ar,
+ u32 addr);
+int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param);
+int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param);
+int ath6kl_bmi_lz_data(struct ath6kl *ar,
+ u8 *buf, u32 len);
+int ath6kl_bmi_lz_stream_start(struct ath6kl *ar,
+ u32 addr);
+int ath6kl_bmi_fast_download(struct ath6kl *ar,
+ u32 addr, u8 *buf, u32 len);
+#endif
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
new file mode 100644
index 000000000000..3aff36bad5d3
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -0,0 +1,1914 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications 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"
+#include "hif-ops.h"
+#include "testmode.h"
+
+static unsigned int ath6kl_p2p;
+
+module_param(ath6kl_p2p, uint, 0644);
+
+#define RATETAB_ENT(_rate, _rateid, _flags) { \
+ .bitrate = (_rate), \
+ .flags = (_flags), \
+ .hw_value = (_rateid), \
+}
+
+#define CHAN2G(_channel, _freq, _flags) { \
+ .band = IEEE80211_BAND_2GHZ, \
+ .hw_value = (_channel), \
+ .center_freq = (_freq), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+#define CHAN5G(_channel, _flags) { \
+ .band = IEEE80211_BAND_5GHZ, \
+ .hw_value = (_channel), \
+ .center_freq = 5000 + (5 * (_channel)), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+static struct ieee80211_rate ath6kl_rates[] = {
+ RATETAB_ENT(10, 0x1, 0),
+ RATETAB_ENT(20, 0x2, 0),
+ RATETAB_ENT(55, 0x4, 0),
+ RATETAB_ENT(110, 0x8, 0),
+ RATETAB_ENT(60, 0x10, 0),
+ RATETAB_ENT(90, 0x20, 0),
+ RATETAB_ENT(120, 0x40, 0),
+ RATETAB_ENT(180, 0x80, 0),
+ RATETAB_ENT(240, 0x100, 0),
+ RATETAB_ENT(360, 0x200, 0),
+ RATETAB_ENT(480, 0x400, 0),
+ RATETAB_ENT(540, 0x800, 0),
+};
+
+#define ath6kl_a_rates (ath6kl_rates + 4)
+#define ath6kl_a_rates_size 8
+#define ath6kl_g_rates (ath6kl_rates + 0)
+#define ath6kl_g_rates_size 12
+
+static struct ieee80211_channel ath6kl_2ghz_channels[] = {
+ CHAN2G(1, 2412, 0),
+ CHAN2G(2, 2417, 0),
+ CHAN2G(3, 2422, 0),
+ CHAN2G(4, 2427, 0),
+ CHAN2G(5, 2432, 0),
+ CHAN2G(6, 2437, 0),
+ CHAN2G(7, 2442, 0),
+ CHAN2G(8, 2447, 0),
+ CHAN2G(9, 2452, 0),
+ CHAN2G(10, 2457, 0),
+ CHAN2G(11, 2462, 0),
+ CHAN2G(12, 2467, 0),
+ CHAN2G(13, 2472, 0),
+ CHAN2G(14, 2484, 0),
+};
+
+static struct ieee80211_channel ath6kl_5ghz_a_channels[] = {
+ CHAN5G(34, 0), CHAN5G(36, 0),
+ CHAN5G(38, 0), CHAN5G(40, 0),
+ CHAN5G(42, 0), CHAN5G(44, 0),
+ CHAN5G(46, 0), CHAN5G(48, 0),
+ CHAN5G(52, 0), CHAN5G(56, 0),
+ CHAN5G(60, 0), CHAN5G(64, 0),
+ CHAN5G(100, 0), CHAN5G(104, 0),
+ CHAN5G(108, 0), CHAN5G(112, 0),
+ CHAN5G(116, 0), CHAN5G(120, 0),
+ CHAN5G(124, 0), CHAN5G(128, 0),
+ CHAN5G(132, 0), CHAN5G(136, 0),
+ CHAN5G(140, 0), CHAN5G(149, 0),
+ CHAN5G(153, 0), CHAN5G(157, 0),
+ CHAN5G(161, 0), CHAN5G(165, 0),
+ CHAN5G(184, 0), CHAN5G(188, 0),
+ CHAN5G(192, 0), CHAN5G(196, 0),
+ CHAN5G(200, 0), CHAN5G(204, 0),
+ CHAN5G(208, 0), CHAN5G(212, 0),
+ CHAN5G(216, 0),
+};
+
+static struct ieee80211_supported_band ath6kl_band_2ghz = {
+ .n_channels = ARRAY_SIZE(ath6kl_2ghz_channels),
+ .channels = ath6kl_2ghz_channels,
+ .n_bitrates = ath6kl_g_rates_size,
+ .bitrates = ath6kl_g_rates,
+};
+
+static struct ieee80211_supported_band ath6kl_band_5ghz = {
+ .n_channels = ARRAY_SIZE(ath6kl_5ghz_a_channels),
+ .channels = ath6kl_5ghz_a_channels,
+ .n_bitrates = ath6kl_a_rates_size,
+ .bitrates = ath6kl_a_rates,
+};
+
+static int ath6kl_set_wpa_version(struct ath6kl *ar,
+ enum nl80211_wpa_versions wpa_version)
+{
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: %u\n", __func__, wpa_version);
+
+ if (!wpa_version) {
+ ar->auth_mode = NONE_AUTH;
+ } else if (wpa_version & NL80211_WPA_VERSION_2) {
+ ar->auth_mode = WPA2_AUTH;
+ } else if (wpa_version & NL80211_WPA_VERSION_1) {
+ ar->auth_mode = WPA_AUTH;
+ } else {
+ ath6kl_err("%s: %u not supported\n", __func__, wpa_version);
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int ath6kl_set_auth_type(struct ath6kl *ar,
+ enum nl80211_auth_type auth_type)
+{
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, auth_type);
+
+ switch (auth_type) {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ ar->dot11_auth_mode = OPEN_AUTH;
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ ar->dot11_auth_mode = SHARED_AUTH;
+ break;
+ case NL80211_AUTHTYPE_NETWORK_EAP:
+ ar->dot11_auth_mode = LEAP_AUTH;
+ break;
+
+ case NL80211_AUTHTYPE_AUTOMATIC:
+ ar->dot11_auth_mode = OPEN_AUTH | SHARED_AUTH;
+ break;
+
+ default:
+ ath6kl_err("%s: 0x%x not spported\n", __func__, auth_type);
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int ath6kl_set_cipher(struct ath6kl *ar, u32 cipher, bool ucast)
+{
+ u8 *ar_cipher = ucast ? &ar->prwise_crypto : &ar->grp_crypto;
+ u8 *ar_cipher_len = ucast ? &ar->prwise_crypto_len :
+ &ar->grp_crypto_len;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n",
+ __func__, cipher, ucast);
+
+ switch (cipher) {
+ case 0:
+ /* our own hack to use value 0 as no crypto used */
+ *ar_cipher = NONE_CRYPT;
+ *ar_cipher_len = 0;
+ break;
+ case WLAN_CIPHER_SUITE_WEP40:
+ *ar_cipher = WEP_CRYPT;
+ *ar_cipher_len = 5;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ *ar_cipher = WEP_CRYPT;
+ *ar_cipher_len = 13;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ *ar_cipher = TKIP_CRYPT;
+ *ar_cipher_len = 0;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ *ar_cipher = AES_CRYPT;
+ *ar_cipher_len = 0;
+ break;
+ default:
+ ath6kl_err("cipher 0x%x not supported\n", cipher);
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static void ath6kl_set_key_mgmt(struct ath6kl *ar, u32 key_mgmt)
+{
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, key_mgmt);
+
+ if (key_mgmt == WLAN_AKM_SUITE_PSK) {
+ if (ar->auth_mode == WPA_AUTH)
+ ar->auth_mode = WPA_PSK_AUTH;
+ else if (ar->auth_mode == WPA2_AUTH)
+ ar->auth_mode = WPA2_PSK_AUTH;
+ } else if (key_mgmt != WLAN_AKM_SUITE_8021X) {
+ ar->auth_mode = NONE_AUTH;
+ }
+}
+
+static bool ath6kl_cfg80211_ready(struct ath6kl *ar)
+{
+ if (!test_bit(WMI_READY, &ar->flag)) {
+ ath6kl_err("wmi is not ready\n");
+ return false;
+ }
+
+ if (!test_bit(WLAN_ENABLED, &ar->flag)) {
+ ath6kl_err("wlan disabled\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ int status;
+
+ ar->sme_state = SME_CONNECTING;
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
+ ath6kl_err("destroy in progress\n");
+ return -EBUSY;
+ }
+
+ if (test_bit(SKIP_SCAN, &ar->flag) &&
+ ((sme->channel && sme->channel->center_freq == 0) ||
+ (sme->bssid && is_zero_ether_addr(sme->bssid)))) {
+ ath6kl_err("SkipScan: channel or bssid invalid\n");
+ return -EINVAL;
+ }
+
+ if (down_interruptible(&ar->sem)) {
+ ath6kl_err("busy, couldn't get access\n");
+ return -ERESTARTSYS;
+ }
+
+ if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
+ ath6kl_err("busy, destroy in progress\n");
+ up(&ar->sem);
+ return -EBUSY;
+ }
+
+ if (ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)]) {
+ /*
+ * sleep until the command queue drains
+ */
+ wait_event_interruptible_timeout(ar->event_wq,
+ ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0,
+ WMI_TIMEOUT);
+ if (signal_pending(current)) {
+ ath6kl_err("cmd queue drain timeout\n");
+ up(&ar->sem);
+ return -EINTR;
+ }
+ }
+
+ if (test_bit(CONNECTED, &ar->flag) &&
+ ar->ssid_len == sme->ssid_len &&
+ !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
+ ar->reconnect_flag = true;
+ status = ath6kl_wmi_reconnect_cmd(ar->wmi, ar->req_bssid,
+ ar->ch_hint);
+
+ up(&ar->sem);
+ if (status) {
+ ath6kl_err("wmi_reconnect_cmd failed\n");
+ return -EIO;
+ }
+ return 0;
+ } else if (ar->ssid_len == sme->ssid_len &&
+ !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
+ ath6kl_disconnect(ar);
+ }
+
+ memset(ar->ssid, 0, sizeof(ar->ssid));
+ ar->ssid_len = sme->ssid_len;
+ memcpy(ar->ssid, sme->ssid, sme->ssid_len);
+
+ if (sme->channel)
+ ar->ch_hint = sme->channel->center_freq;
+
+ memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
+ if (sme->bssid && !is_broadcast_ether_addr(sme->bssid))
+ memcpy(ar->req_bssid, sme->bssid, sizeof(ar->req_bssid));
+
+ ath6kl_set_wpa_version(ar, sme->crypto.wpa_versions);
+
+ status = ath6kl_set_auth_type(ar, sme->auth_type);
+ if (status) {
+ up(&ar->sem);
+ return status;
+ }
+
+ if (sme->crypto.n_ciphers_pairwise)
+ ath6kl_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true);
+ else
+ ath6kl_set_cipher(ar, 0, true);
+
+ ath6kl_set_cipher(ar, sme->crypto.cipher_group, false);
+
+ if (sme->crypto.n_akm_suites)
+ ath6kl_set_key_mgmt(ar, sme->crypto.akm_suites[0]);
+
+ if ((sme->key_len) &&
+ (ar->auth_mode == NONE_AUTH) && (ar->prwise_crypto == WEP_CRYPT)) {
+ struct ath6kl_key *key = NULL;
+
+ if (sme->key_idx < WMI_MIN_KEY_INDEX ||
+ sme->key_idx > WMI_MAX_KEY_INDEX) {
+ ath6kl_err("key index %d out of bounds\n",
+ sme->key_idx);
+ up(&ar->sem);
+ return -ENOENT;
+ }
+
+ key = &ar->keys[sme->key_idx];
+ key->key_len = sme->key_len;
+ memcpy(key->key, sme->key, key->key_len);
+ key->cipher = ar->prwise_crypto;
+ ar->def_txkey_index = sme->key_idx;
+
+ ath6kl_wmi_addkey_cmd(ar->wmi, sme->key_idx,
+ ar->prwise_crypto,
+ GROUP_USAGE | TX_USAGE,
+ key->key_len,
+ NULL,
+ key->key, KEY_OP_INIT_VAL, NULL,
+ NO_SYNC_WMIFLAG);
+ }
+
+ if (!ar->usr_bss_filter) {
+ clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
+ if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) {
+ ath6kl_err("couldn't set bss filtering\n");
+ up(&ar->sem);
+ return -EIO;
+ }
+ }
+
+ ar->nw_type = ar->next_mode;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: connect called with authmode %d dot11 auth %d"
+ " PW crypto %d PW crypto len %d GRP crypto %d"
+ " GRP crypto len %d channel hint %u\n",
+ __func__,
+ ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto,
+ ar->prwise_crypto_len, ar->grp_crypto,
+ ar->grp_crypto_len, ar->ch_hint);
+
+ ar->reconnect_flag = 0;
+ status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type,
+ ar->dot11_auth_mode, ar->auth_mode,
+ ar->prwise_crypto,
+ ar->prwise_crypto_len,
+ ar->grp_crypto, ar->grp_crypto_len,
+ ar->ssid_len, ar->ssid,
+ ar->req_bssid, ar->ch_hint,
+ ar->connect_ctrl_flags);
+
+ up(&ar->sem);
+
+ if (status == -EINVAL) {
+ memset(ar->ssid, 0, sizeof(ar->ssid));
+ ar->ssid_len = 0;
+ ath6kl_err("invalid request\n");
+ return -ENOENT;
+ } else if (status) {
+ ath6kl_err("ath6kl_wmi_connect_cmd failed\n");
+ return -EIO;
+ }
+
+ if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
+ ((ar->auth_mode == WPA_PSK_AUTH)
+ || (ar->auth_mode == WPA2_PSK_AUTH))) {
+ mod_timer(&ar->disconnect_timer,
+ jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
+ }
+
+ ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD;
+ set_bit(CONNECT_PEND, &ar->flag);
+
+ return 0;
+}
+
+static int ath6kl_add_bss_if_needed(struct ath6kl *ar, const u8 *bssid,
+ struct ieee80211_channel *chan,
+ const u8 *beacon_ie, size_t beacon_ie_len)
+{
+ struct cfg80211_bss *bss;
+ u8 *ie;
+
+ bss = cfg80211_get_bss(ar->wdev->wiphy, chan, bssid,
+ ar->ssid, ar->ssid_len, WLAN_CAPABILITY_ESS,
+ WLAN_CAPABILITY_ESS);
+ if (bss == NULL) {
+ /*
+ * Since cfg80211 may not yet know about the BSS,
+ * generate a partial entry until the first BSS info
+ * event becomes available.
+ *
+ * Prepend SSID element since it is not included in the Beacon
+ * IEs from the target.
+ */
+ ie = kmalloc(2 + ar->ssid_len + beacon_ie_len, GFP_KERNEL);
+ if (ie == NULL)
+ return -ENOMEM;
+ ie[0] = WLAN_EID_SSID;
+ ie[1] = ar->ssid_len;
+ memcpy(ie + 2, ar->ssid, ar->ssid_len);
+ memcpy(ie + 2 + ar->ssid_len, beacon_ie, beacon_ie_len);
+ bss = cfg80211_inform_bss(ar->wdev->wiphy, chan,
+ bssid, 0, WLAN_CAPABILITY_ESS, 100,
+ ie, 2 + ar->ssid_len + beacon_ie_len,
+ 0, GFP_KERNEL);
+ if (bss)
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added dummy bss for "
+ "%pM prior to indicating connect/roamed "
+ "event\n", bssid);
+ kfree(ie);
+ } else
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss "
+ "entry\n");
+
+ if (bss == NULL)
+ return -ENOMEM;
+
+ cfg80211_put_bss(bss);
+
+ return 0;
+}
+
+void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
+ u8 *bssid, u16 listen_intvl,
+ u16 beacon_intvl,
+ enum network_type nw_type,
+ u8 beacon_ie_len, u8 assoc_req_len,
+ u8 assoc_resp_len, u8 *assoc_info)
+{
+ struct ieee80211_channel *chan;
+
+ /* capinfo + listen interval */
+ u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16);
+
+ /* capinfo + status code + associd */
+ u8 assoc_resp_ie_offset = sizeof(u16) + sizeof(u16) + sizeof(u16);
+
+ u8 *assoc_req_ie = assoc_info + beacon_ie_len + assoc_req_ie_offset;
+ u8 *assoc_resp_ie = assoc_info + beacon_ie_len + assoc_req_len +
+ assoc_resp_ie_offset;
+
+ assoc_req_len -= assoc_req_ie_offset;
+ assoc_resp_len -= assoc_resp_ie_offset;
+
+ /*
+ * Store Beacon interval here; DTIM period will be available only once
+ * a Beacon frame from the AP is seen.
+ */
+ ar->assoc_bss_beacon_int = beacon_intvl;
+ clear_bit(DTIM_PERIOD_AVAIL, &ar->flag);
+
+ if (nw_type & ADHOC_NETWORK) {
+ if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: ath6k not in ibss mode\n", __func__);
+ return;
+ }
+ }
+
+ if (nw_type & INFRA_NETWORK) {
+ if (ar->wdev->iftype != NL80211_IFTYPE_STATION &&
+ ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: ath6k not in station mode\n", __func__);
+ return;
+ }
+ }
+
+ chan = ieee80211_get_channel(ar->wdev->wiphy, (int) channel);
+
+
+ if (nw_type & ADHOC_NETWORK) {
+ cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL);
+ return;
+ }
+
+ if (ath6kl_add_bss_if_needed(ar, bssid, chan, assoc_info,
+ beacon_ie_len) < 0) {
+ ath6kl_err("could not add cfg80211 bss entry for "
+ "connect/roamed notification\n");
+ return;
+ }
+
+ if (ar->sme_state == SME_CONNECTING) {
+ /* inform connect result to cfg80211 */
+ ar->sme_state = SME_CONNECTED;
+ cfg80211_connect_result(ar->net_dev, bssid,
+ assoc_req_ie, assoc_req_len,
+ assoc_resp_ie, assoc_resp_len,
+ WLAN_STATUS_SUCCESS, GFP_KERNEL);
+ } else if (ar->sme_state == SME_CONNECTED) {
+ /* inform roam event to cfg80211 */
+ cfg80211_roamed(ar->net_dev, chan, bssid,
+ assoc_req_ie, assoc_req_len,
+ assoc_resp_ie, assoc_resp_len, GFP_KERNEL);
+ }
+}
+
+static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
+ struct net_device *dev, u16 reason_code)
+{
+ struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev);
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__,
+ reason_code);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
+ ath6kl_err("busy, destroy in progress\n");
+ return -EBUSY;
+ }
+
+ if (down_interruptible(&ar->sem)) {
+ ath6kl_err("busy, couldn't get access\n");
+ return -ERESTARTSYS;
+ }
+
+ ar->reconnect_flag = 0;
+ ath6kl_disconnect(ar);
+ memset(ar->ssid, 0, sizeof(ar->ssid));
+ ar->ssid_len = 0;
+
+ if (!test_bit(SKIP_SCAN, &ar->flag))
+ memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
+
+ up(&ar->sem);
+
+ ar->sme_state = SME_DISCONNECTED;
+
+ return 0;
+}
+
+void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
+ u8 *bssid, u8 assoc_resp_len,
+ u8 *assoc_info, u16 proto_reason)
+{
+ if (ar->scan_req) {
+ cfg80211_scan_done(ar->scan_req, true);
+ ar->scan_req = NULL;
+ }
+
+ if (ar->nw_type & ADHOC_NETWORK) {
+ if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: ath6k not in ibss mode\n", __func__);
+ return;
+ }
+ memset(bssid, 0, ETH_ALEN);
+ cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL);
+ return;
+ }
+
+ if (ar->nw_type & INFRA_NETWORK) {
+ if (ar->wdev->iftype != NL80211_IFTYPE_STATION &&
+ ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: ath6k not in station mode\n", __func__);
+ return;
+ }
+ }
+
+ /*
+ * Send a disconnect command to target when a disconnect event is
+ * received with reason code other than 3 (DISCONNECT_CMD - disconnect
+ * request from host) to make the firmware stop trying to connect even
+ * after giving disconnect event. There will be one more disconnect
+ * event for this disconnect command with reason code DISCONNECT_CMD
+ * which will be notified to cfg80211.
+ */
+
+ if (reason != DISCONNECT_CMD) {
+ ath6kl_wmi_disconnect_cmd(ar->wmi);
+ return;
+ }
+
+ clear_bit(CONNECT_PEND, &ar->flag);
+
+ if (ar->sme_state == SME_CONNECTING) {
+ cfg80211_connect_result(ar->net_dev,
+ bssid, NULL, 0,
+ NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
+ } else if (ar->sme_state == SME_CONNECTED) {
+ cfg80211_disconnected(ar->net_dev, reason,
+ NULL, 0, GFP_KERNEL);
+ }
+
+ ar->sme_state = SME_DISCONNECTED;
+}
+
+static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_scan_request *request)
+{
+ struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+ s8 n_channels = 0;
+ u16 *channels = NULL;
+ int ret = 0;
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (!ar->usr_bss_filter) {
+ clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
+ ret = ath6kl_wmi_bssfilter_cmd(
+ ar->wmi,
+ (test_bit(CONNECTED, &ar->flag) ?
+ ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0);
+ if (ret) {
+ ath6kl_err("couldn't set bss filtering\n");
+ return ret;
+ }
+ }
+
+ if (request->n_ssids && request->ssids[0].ssid_len) {
+ u8 i;
+
+ if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
+ request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
+
+ for (i = 0; i < request->n_ssids; i++)
+ ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1,
+ SPECIFIC_SSID_FLAG,
+ request->ssids[i].ssid_len,
+ request->ssids[i].ssid);
+ }
+
+ if (request->ie) {
+ ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_REQ,
+ request->ie, request->ie_len);
+ if (ret) {
+ ath6kl_err("failed to set Probe Request appie for "
+ "scan");
+ return ret;
+ }
+ }
+
+ /*
+ * Scan only the requested channels if the request specifies a set of
+ * channels. If the list is longer than the target supports, do not
+ * configure the list and instead, scan all available channels.
+ */
+ if (request->n_channels > 0 &&
+ request->n_channels <= WMI_MAX_CHANNELS) {
+ u8 i;
+
+ n_channels = request->n_channels;
+
+ channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);
+ if (channels == NULL) {
+ ath6kl_warn("failed to set scan channels, "
+ "scan all channels");
+ n_channels = 0;
+ }
+
+ for (i = 0; i < n_channels; i++)
+ channels[i] = request->channels[i]->center_freq;
+ }
+
+ ret = ath6kl_wmi_startscan_cmd(ar->wmi, WMI_LONG_SCAN, 0,
+ false, 0, 0, n_channels, channels);
+ if (ret)
+ ath6kl_err("wmi_startscan_cmd failed\n");
+ else
+ ar->scan_req = request;
+
+ kfree(channels);
+
+ return ret;
+}
+
+void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status)
+{
+ int i;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status %d\n", __func__, status);
+
+ if (!ar->scan_req)
+ return;
+
+ if ((status == -ECANCELED) || (status == -EBUSY)) {
+ cfg80211_scan_done(ar->scan_req, true);
+ goto out;
+ }
+
+ cfg80211_scan_done(ar->scan_req, false);
+
+ if (ar->scan_req->n_ssids && ar->scan_req->ssids[0].ssid_len) {
+ for (i = 0; i < ar->scan_req->n_ssids; i++) {
+ ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1,
+ DISABLE_SSID_FLAG,
+ 0, NULL);
+ }
+ }
+
+out:
+ ar->scan_req = NULL;
+}
+
+static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
+ u8 key_index, bool pairwise,
+ const u8 *mac_addr,
+ struct key_params *params)
+{
+ struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+ struct ath6kl_key *key = NULL;
+ u8 key_usage;
+ u8 key_type;
+ int status = 0;
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: key index %d out of bounds\n", __func__,
+ key_index);
+ return -ENOENT;
+ }
+
+ key = &ar->keys[key_index];
+ memset(key, 0, sizeof(struct ath6kl_key));
+
+ if (pairwise)
+ key_usage = PAIRWISE_USAGE;
+ else
+ key_usage = GROUP_USAGE;
+
+ if (params) {
+ if (params->key_len > WLAN_MAX_KEY_LEN ||
+ params->seq_len > sizeof(key->seq))
+ return -EINVAL;
+
+ key->key_len = params->key_len;
+ memcpy(key->key, params->key, key->key_len);
+ key->seq_len = params->seq_len;
+ memcpy(key->seq, params->seq, key->seq_len);
+ key->cipher = params->cipher;
+ }
+
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ key_type = WEP_CRYPT;
+ break;
+
+ case WLAN_CIPHER_SUITE_TKIP:
+ key_type = TKIP_CRYPT;
+ break;
+
+ case WLAN_CIPHER_SUITE_CCMP:
+ key_type = AES_CRYPT;
+ break;
+
+ default:
+ return -ENOTSUPP;
+ }
+
+ if (((ar->auth_mode == WPA_PSK_AUTH)
+ || (ar->auth_mode == WPA2_PSK_AUTH))
+ && (key_usage & GROUP_USAGE))
+ del_timer(&ar->disconnect_timer);
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n",
+ __func__, key_index, key->key_len, key_type,
+ key_usage, key->seq_len);
+
+ ar->def_txkey_index = key_index;
+
+ if (ar->nw_type == AP_NETWORK && !pairwise &&
+ (key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) {
+ ar->ap_mode_bkey.valid = true;
+ ar->ap_mode_bkey.key_index = key_index;
+ ar->ap_mode_bkey.key_type = key_type;
+ ar->ap_mode_bkey.key_len = key->key_len;
+ memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
+ if (!test_bit(CONNECTED, &ar->flag)) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
+ "key configuration until AP mode has been "
+ "started\n");
+ /*
+ * The key will be set in ath6kl_connect_ap_mode() once
+ * the connected event is received from the target.
+ */
+ return 0;
+ }
+ }
+
+ if (ar->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
+ !test_bit(CONNECTED, &ar->flag)) {
+ /*
+ * Store the key locally so that it can be re-configured after
+ * the AP mode has properly started
+ * (ath6kl_install_statioc_wep_keys).
+ */
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
+ "until AP mode has been started\n");
+ ar->wep_key_list[key_index].key_len = key->key_len;
+ memcpy(ar->wep_key_list[key_index].key, key->key, key->key_len);
+ return 0;
+ }
+
+ status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
+ key_type, key_usage, key->key_len,
+ key->seq, key->key, KEY_OP_INIT_VAL,
+ (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
+
+ if (status)
+ return -EIO;
+
+ return 0;
+}
+
+static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
+ u8 key_index, bool pairwise,
+ const u8 *mac_addr)
+{
+ struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: key index %d out of bounds\n", __func__,
+ key_index);
+ return -ENOENT;
+ }
+
+ if (!ar->keys[key_index].key_len) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: index %d is empty\n", __func__, key_index);
+ return 0;
+ }
+
+ ar->keys[key_index].key_len = 0;
+
+ return ath6kl_wmi_deletekey_cmd(ar->wmi, key_index);
+}
+
+static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
+ u8 key_index, bool pairwise,
+ const u8 *mac_addr, void *cookie,
+ void (*callback) (void *cookie,
+ struct key_params *))
+{
+ struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+ struct ath6kl_key *key = NULL;
+ struct key_params params;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: key index %d out of bounds\n", __func__,
+ key_index);
+ return -ENOENT;
+ }
+
+ key = &ar->keys[key_index];
+ memset(&params, 0, sizeof(params));
+ params.cipher = key->cipher;
+ params.key_len = key->key_len;
+ params.seq_len = key->seq_len;
+ params.seq = key->seq;
+ params.key = key->key;
+
+ callback(cookie, &params);
+
+ return key->key_len ? 0 : -ENOENT;
+}
+
+static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
+ struct net_device *ndev,
+ u8 key_index, bool unicast,
+ bool multicast)
+{
+ struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+ struct ath6kl_key *key = NULL;
+ int status = 0;
+ u8 key_usage;
+ enum crypto_type key_type = NONE_CRYPT;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: key index %d out of bounds\n",
+ __func__, key_index);
+ return -ENOENT;
+ }
+
+ if (!ar->keys[key_index].key_len) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
+ __func__, key_index);
+ return -EINVAL;
+ }
+
+ ar->def_txkey_index = key_index;
+ key = &ar->keys[ar->def_txkey_index];
+ key_usage = GROUP_USAGE;
+ if (ar->prwise_crypto == WEP_CRYPT)
+ key_usage |= TX_USAGE;
+ if (unicast)
+ key_type = ar->prwise_crypto;
+ if (multicast)
+ key_type = ar->grp_crypto;
+
+ if (ar->next_mode == AP_NETWORK && !test_bit(CONNECTED, &ar->flag))
+ return 0; /* Delay until AP mode has been started */
+
+ status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
+ key_type, key_usage,
+ key->key_len, key->seq, key->key,
+ KEY_OP_INIT_VAL, NULL,
+ SYNC_BOTH_WMIFLAG);
+ if (status)
+ return -EIO;
+
+ return 0;
+}
+
+void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid,
+ bool ismcast)
+{
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast);
+
+ cfg80211_michael_mic_failure(ar->net_dev, ar->bssid,
+ (ismcast ? NL80211_KEYTYPE_GROUP :
+ NL80211_KEYTYPE_PAIRWISE), keyid, NULL,
+ GFP_KERNEL);
+}
+
+static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+ struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
+ int ret;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
+ changed);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
+ ret = ath6kl_wmi_set_rts_cmd(ar->wmi, wiphy->rts_threshold);
+ if (ret != 0) {
+ ath6kl_err("ath6kl_wmi_set_rts_cmd failed\n");
+ return -EIO;
+ }
+ }
+
+ 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,
+ enum nl80211_tx_power_setting type,
+ int dbm)
+{
+ struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
+ u8 ath6kl_dbm;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
+ type, dbm);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ switch (type) {
+ case NL80211_TX_POWER_AUTOMATIC:
+ return 0;
+ case NL80211_TX_POWER_LIMITED:
+ ar->tx_pwr = ath6kl_dbm = dbm;
+ break;
+ default:
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
+ __func__, type);
+ return -EOPNOTSUPP;
+ }
+
+ ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, ath6kl_dbm);
+
+ return 0;
+}
+
+static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
+{
+ struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (test_bit(CONNECTED, &ar->flag)) {
+ ar->tx_pwr = 0;
+
+ if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi) != 0) {
+ ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
+ return -EIO;
+ }
+
+ wait_event_interruptible_timeout(ar->event_wq, ar->tx_pwr != 0,
+ 5 * HZ);
+
+ if (signal_pending(current)) {
+ ath6kl_err("target did not respond\n");
+ return -EINTR;
+ }
+ }
+
+ *dbm = ar->tx_pwr;
+ return 0;
+}
+
+static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+ struct net_device *dev,
+ bool pmgmt, int timeout)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ struct wmi_power_mode_cmd mode;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
+ __func__, pmgmt, timeout);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (pmgmt) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
+ mode.pwr_mode = REC_POWER;
+ } else {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
+ mode.pwr_mode = MAX_PERF_POWER;
+ }
+
+ if (ath6kl_wmi_powermode_cmd(ar->wmi, mode.pwr_mode) != 0) {
+ ath6kl_err("wmi_powermode_cmd failed\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
+ struct net_device *ndev,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+{
+ struct ath6kl *ar = ath6kl_priv(ndev);
+ struct wireless_dev *wdev = ar->wdev;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ switch (type) {
+ case NL80211_IFTYPE_STATION:
+ ar->next_mode = INFRA_NETWORK;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ ar->next_mode = ADHOC_NETWORK;
+ break;
+ case NL80211_IFTYPE_AP:
+ ar->next_mode = AP_NETWORK;
+ break;
+ case NL80211_IFTYPE_P2P_CLIENT:
+ ar->next_mode = INFRA_NETWORK;
+ break;
+ case NL80211_IFTYPE_P2P_GO:
+ ar->next_mode = AP_NETWORK;
+ break;
+ default:
+ ath6kl_err("invalid interface type %u\n", type);
+ return -EOPNOTSUPP;
+ }
+
+ wdev->iftype = type;
+
+ return 0;
+}
+
+static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_ibss_params *ibss_param)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ int status;
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ ar->ssid_len = ibss_param->ssid_len;
+ memcpy(ar->ssid, ibss_param->ssid, ar->ssid_len);
+
+ if (ibss_param->channel)
+ ar->ch_hint = ibss_param->channel->center_freq;
+
+ if (ibss_param->channel_fixed) {
+ /*
+ * TODO: channel_fixed: The channel should be fixed, do not
+ * search for IBSSs to join on other channels. Target
+ * firmware does not support this feature, needs to be
+ * updated.
+ */
+ return -EOPNOTSUPP;
+ }
+
+ memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
+ if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid))
+ memcpy(ar->req_bssid, ibss_param->bssid, sizeof(ar->req_bssid));
+
+ ath6kl_set_wpa_version(ar, 0);
+
+ status = ath6kl_set_auth_type(ar, NL80211_AUTHTYPE_OPEN_SYSTEM);
+ if (status)
+ return status;
+
+ if (ibss_param->privacy) {
+ ath6kl_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, true);
+ ath6kl_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, false);
+ } else {
+ ath6kl_set_cipher(ar, 0, true);
+ ath6kl_set_cipher(ar, 0, false);
+ }
+
+ ar->nw_type = ar->next_mode;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "%s: connect called with authmode %d dot11 auth %d"
+ " PW crypto %d PW crypto len %d GRP crypto %d"
+ " GRP crypto len %d channel hint %u\n",
+ __func__,
+ ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto,
+ ar->prwise_crypto_len, ar->grp_crypto,
+ ar->grp_crypto_len, ar->ch_hint);
+
+ status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type,
+ ar->dot11_auth_mode, ar->auth_mode,
+ ar->prwise_crypto,
+ ar->prwise_crypto_len,
+ ar->grp_crypto, ar->grp_crypto_len,
+ ar->ssid_len, ar->ssid,
+ ar->req_bssid, ar->ch_hint,
+ ar->connect_ctrl_flags);
+ set_bit(CONNECT_PEND, &ar->flag);
+
+ return 0;
+}
+
+static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
+ struct net_device *dev)
+{
+ struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ ath6kl_disconnect(ar);
+ memset(ar->ssid, 0, sizeof(ar->ssid));
+ ar->ssid_len = 0;
+
+ return 0;
+}
+
+static const u32 cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+};
+
+static bool is_rate_legacy(s32 rate)
+{
+ static const s32 legacy[] = { 1000, 2000, 5500, 11000,
+ 6000, 9000, 12000, 18000, 24000,
+ 36000, 48000, 54000
+ };
+ u8 i;
+
+ for (i = 0; i < ARRAY_SIZE(legacy); i++)
+ if (rate == legacy[i])
+ return true;
+
+ return false;
+}
+
+static bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
+{
+ static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
+ 52000, 58500, 65000, 72200
+ };
+ u8 i;
+
+ for (i = 0; i < ARRAY_SIZE(ht20); i++) {
+ if (rate == ht20[i]) {
+ if (i == ARRAY_SIZE(ht20) - 1)
+ /* last rate uses sgi */
+ *sgi = true;
+ else
+ *sgi = false;
+
+ *mcs = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
+{
+ static const s32 ht40[] = { 13500, 27000, 40500, 54000,
+ 81000, 108000, 121500, 135000,
+ 150000
+ };
+ u8 i;
+
+ for (i = 0; i < ARRAY_SIZE(ht40); i++) {
+ if (rate == ht40[i]) {
+ if (i == ARRAY_SIZE(ht40) - 1)
+ /* last rate uses sgi */
+ *sgi = true;
+ else
+ *sgi = false;
+
+ *mcs = i;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_info *sinfo)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ long left;
+ bool sgi;
+ s32 rate;
+ int ret;
+ u8 mcs;
+
+ if (memcmp(mac, ar->bssid, ETH_ALEN) != 0)
+ return -ENOENT;
+
+ if (down_interruptible(&ar->sem))
+ return -EBUSY;
+
+ set_bit(STATS_UPDATE_PEND, &ar->flag);
+
+ ret = ath6kl_wmi_get_stats_cmd(ar->wmi);
+
+ if (ret != 0) {
+ up(&ar->sem);
+ return -EIO;
+ }
+
+ left = wait_event_interruptible_timeout(ar->event_wq,
+ !test_bit(STATS_UPDATE_PEND,
+ &ar->flag),
+ WMI_TIMEOUT);
+
+ up(&ar->sem);
+
+ if (left == 0)
+ return -ETIMEDOUT;
+ else if (left < 0)
+ return left;
+
+ if (ar->target_stats.rx_byte) {
+ sinfo->rx_bytes = ar->target_stats.rx_byte;
+ sinfo->filled |= STATION_INFO_RX_BYTES;
+ sinfo->rx_packets = ar->target_stats.rx_pkt;
+ sinfo->filled |= STATION_INFO_RX_PACKETS;
+ }
+
+ if (ar->target_stats.tx_byte) {
+ sinfo->tx_bytes = ar->target_stats.tx_byte;
+ sinfo->filled |= STATION_INFO_TX_BYTES;
+ sinfo->tx_packets = ar->target_stats.tx_pkt;
+ sinfo->filled |= STATION_INFO_TX_PACKETS;
+ }
+
+ sinfo->signal = ar->target_stats.cs_rssi;
+ sinfo->filled |= STATION_INFO_SIGNAL;
+
+ rate = ar->target_stats.tx_ucast_rate;
+
+ if (is_rate_legacy(rate)) {
+ sinfo->txrate.legacy = rate / 100;
+ } else if (is_rate_ht20(rate, &mcs, &sgi)) {
+ if (sgi) {
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ sinfo->txrate.mcs = mcs - 1;
+ } else {
+ sinfo->txrate.mcs = mcs;
+ }
+
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+ } else if (is_rate_ht40(rate, &mcs, &sgi)) {
+ if (sgi) {
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ sinfo->txrate.mcs = mcs - 1;
+ } else {
+ sinfo->txrate.mcs = mcs;
+ }
+
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+ } else {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+ "invalid rate from stats: %d\n", rate);
+ ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE);
+ return 0;
+ }
+
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+
+ if (test_bit(CONNECTED, &ar->flag) &&
+ test_bit(DTIM_PERIOD_AVAIL, &ar->flag) &&
+ ar->nw_type == INFRA_NETWORK) {
+ sinfo->filled |= STATION_INFO_BSS_PARAM;
+ sinfo->bss_param.flags = 0;
+ sinfo->bss_param.dtim_period = ar->assoc_bss_dtim_period;
+ sinfo->bss_param.beacon_interval = ar->assoc_bss_beacon_int;
+ }
+
+ return 0;
+}
+
+static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa)
+{
+ struct ath6kl *ar = ath6kl_priv(netdev);
+ return ath6kl_wmi_setpmkid_cmd(ar->wmi, pmksa->bssid,
+ pmksa->pmkid, true);
+}
+
+static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_pmksa *pmksa)
+{
+ struct ath6kl *ar = ath6kl_priv(netdev);
+ return ath6kl_wmi_setpmkid_cmd(ar->wmi, pmksa->bssid,
+ pmksa->pmkid, false);
+}
+
+static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
+{
+ struct ath6kl *ar = ath6kl_priv(netdev);
+ if (test_bit(CONNECTED, &ar->flag))
+ return ath6kl_wmi_setpmkid_cmd(ar->wmi, ar->bssid, NULL, false);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int ar6k_cfg80211_suspend(struct wiphy *wiphy,
+ struct cfg80211_wowlan *wow)
+{
+ struct ath6kl *ar = wiphy_priv(wiphy);
+
+ return ath6kl_hif_suspend(ar);
+}
+#endif
+
+static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
+ __func__, chan->center_freq, chan->hw_value);
+ ar->next_chan = chan->center_freq;
+
+ return 0;
+}
+
+static bool ath6kl_is_p2p_ie(const u8 *pos)
+{
+ return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
+ pos[2] == 0x50 && pos[3] == 0x6f &&
+ pos[4] == 0x9a && pos[5] == 0x09;
+}
+
+static int ath6kl_set_ap_probe_resp_ies(struct ath6kl *ar, const u8 *ies,
+ size_t ies_len)
+{
+ const u8 *pos;
+ u8 *buf = NULL;
+ size_t len = 0;
+ int ret;
+
+ /*
+ * Filter out P2P IE(s) since they will be included depending on
+ * the Probe Request frame in ath6kl_send_go_probe_resp().
+ */
+
+ if (ies && ies_len) {
+ buf = kmalloc(ies_len, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+ pos = ies;
+ while (pos + 1 < ies + ies_len) {
+ if (pos + 2 + pos[1] > ies + ies_len)
+ break;
+ if (!ath6kl_is_p2p_ie(pos)) {
+ memcpy(buf + len, pos, 2 + pos[1]);
+ len += 2 + pos[1];
+ }
+ pos += 2 + pos[1];
+ }
+ }
+
+ ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_RESP,
+ buf, len);
+ kfree(buf);
+ return ret;
+}
+
+static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
+ struct beacon_parameters *info, bool add)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ struct ieee80211_mgmt *mgmt;
+ u8 *ies;
+ int ies_len;
+ struct wmi_connect_cmd p;
+ int res;
+ int i;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add);
+
+ if (!ath6kl_cfg80211_ready(ar))
+ return -EIO;
+
+ if (ar->next_mode != AP_NETWORK)
+ return -EOPNOTSUPP;
+
+ if (info->beacon_ies) {
+ res = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_BEACON,
+ info->beacon_ies,
+ info->beacon_ies_len);
+ if (res)
+ return res;
+ }
+ if (info->proberesp_ies) {
+ res = ath6kl_set_ap_probe_resp_ies(ar, info->proberesp_ies,
+ info->proberesp_ies_len);
+ if (res)
+ return res;
+ }
+ if (info->assocresp_ies) {
+ res = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_ASSOC_RESP,
+ info->assocresp_ies,
+ info->assocresp_ies_len);
+ if (res)
+ return res;
+ }
+
+ if (!add)
+ return 0;
+
+ ar->ap_mode_bkey.valid = false;
+
+ /* TODO:
+ * info->interval
+ * info->dtim_period
+ */
+
+ if (info->head == NULL)
+ return -EINVAL;
+ mgmt = (struct ieee80211_mgmt *) info->head;
+ ies = mgmt->u.beacon.variable;
+ if (ies > info->head + info->head_len)
+ return -EINVAL;
+ ies_len = info->head + info->head_len - ies;
+
+ if (info->ssid == NULL)
+ return -EINVAL;
+ memcpy(ar->ssid, info->ssid, info->ssid_len);
+ ar->ssid_len = info->ssid_len;
+ if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
+ return -EOPNOTSUPP; /* TODO */
+
+ ar->dot11_auth_mode = OPEN_AUTH;
+
+ memset(&p, 0, sizeof(p));
+
+ for (i = 0; i < info->crypto.n_akm_suites; i++) {
+ switch (info->crypto.akm_suites[i]) {
+ case WLAN_AKM_SUITE_8021X:
+ if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+ p.auth_mode |= WPA_AUTH;
+ if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+ p.auth_mode |= WPA2_AUTH;
+ break;
+ case WLAN_AKM_SUITE_PSK:
+ if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+ p.auth_mode |= WPA_PSK_AUTH;
+ if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+ p.auth_mode |= WPA2_PSK_AUTH;
+ break;
+ }
+ }
+ if (p.auth_mode == 0)
+ p.auth_mode = NONE_AUTH;
+ ar->auth_mode = p.auth_mode;
+
+ for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) {
+ switch (info->crypto.ciphers_pairwise[i]) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ p.prwise_crypto_type |= WEP_CRYPT;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ p.prwise_crypto_type |= TKIP_CRYPT;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ p.prwise_crypto_type |= AES_CRYPT;
+ break;
+ }
+ }
+ if (p.prwise_crypto_type == 0) {
+ p.prwise_crypto_type = NONE_CRYPT;
+ ath6kl_set_cipher(ar, 0, true);
+ } else if (info->crypto.n_ciphers_pairwise == 1)
+ ath6kl_set_cipher(ar, info->crypto.ciphers_pairwise[0], true);
+
+ switch (info->crypto.cipher_group) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ p.grp_crypto_type = WEP_CRYPT;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ p.grp_crypto_type = TKIP_CRYPT;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ p.grp_crypto_type = AES_CRYPT;
+ break;
+ default:
+ p.grp_crypto_type = NONE_CRYPT;
+ break;
+ }
+ ath6kl_set_cipher(ar, info->crypto.cipher_group, false);
+
+ p.nw_type = AP_NETWORK;
+ ar->nw_type = ar->next_mode;
+
+ p.ssid_len = ar->ssid_len;
+ memcpy(p.ssid, ar->ssid, ar->ssid_len);
+ p.dot11_auth_mode = ar->dot11_auth_mode;
+ p.ch = cpu_to_le16(ar->next_chan);
+
+ res = ath6kl_wmi_ap_profile_commit(ar->wmi, &p);
+ if (res < 0)
+ return res;
+
+ return 0;
+}
+
+static int ath6kl_add_beacon(struct wiphy *wiphy, struct net_device *dev,
+ struct beacon_parameters *info)
+{
+ return ath6kl_ap_beacon(wiphy, dev, info, true);
+}
+
+static int ath6kl_set_beacon(struct wiphy *wiphy, struct net_device *dev,
+ struct beacon_parameters *info)
+{
+ return ath6kl_ap_beacon(wiphy, dev, info, false);
+}
+
+static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+
+ if (ar->nw_type != AP_NETWORK)
+ return -EOPNOTSUPP;
+ if (!test_bit(CONNECTED, &ar->flag))
+ return -ENOTCONN;
+
+ ath6kl_wmi_disconnect_cmd(ar->wmi);
+ clear_bit(CONNECTED, &ar->flag);
+
+ return 0;
+}
+
+static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_parameters *params)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+
+ if (ar->nw_type != AP_NETWORK)
+ return -EOPNOTSUPP;
+
+ /* Use this only for authorizing/unauthorizing a station */
+ if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
+ return -EOPNOTSUPP;
+
+ if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
+ return ath6kl_wmi_ap_set_mlme(ar->wmi, WMI_AP_MLME_AUTHORIZE,
+ mac, 0);
+ return ath6kl_wmi_ap_set_mlme(ar->wmi, WMI_AP_MLME_UNAUTHORIZE, mac,
+ 0);
+}
+
+static int ath6kl_remain_on_channel(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
+ unsigned int duration,
+ u64 *cookie)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+
+ /* TODO: if already pending or ongoing remain-on-channel,
+ * return -EBUSY */
+ *cookie = 1; /* only a single pending request is supported */
+
+ return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, chan->center_freq,
+ duration);
+}
+
+static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
+ struct net_device *dev,
+ u64 cookie)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+
+ if (cookie != 1)
+ return -ENOENT;
+
+ return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi);
+}
+
+static int ath6kl_send_go_probe_resp(struct ath6kl *ar, const u8 *buf,
+ size_t len, unsigned int freq)
+{
+ const u8 *pos;
+ u8 *p2p;
+ int p2p_len;
+ int ret;
+ const struct ieee80211_mgmt *mgmt;
+
+ mgmt = (const struct ieee80211_mgmt *) buf;
+
+ /* Include P2P IE(s) from the frame generated in user space. */
+
+ p2p = kmalloc(len, GFP_KERNEL);
+ if (p2p == NULL)
+ return -ENOMEM;
+ p2p_len = 0;
+
+ pos = mgmt->u.probe_resp.variable;
+ while (pos + 1 < buf + len) {
+ if (pos + 2 + pos[1] > buf + len)
+ break;
+ if (ath6kl_is_p2p_ie(pos)) {
+ memcpy(p2p + p2p_len, pos, 2 + pos[1]);
+ p2p_len += 2 + pos[1];
+ }
+ pos += 2 + pos[1];
+ }
+
+ ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, freq, mgmt->da,
+ p2p, p2p_len);
+ kfree(p2p);
+ return ret;
+}
+
+static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
+ 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, u64 *cookie)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ u32 id;
+ const struct ieee80211_mgmt *mgmt;
+
+ mgmt = (const struct ieee80211_mgmt *) buf;
+ if (buf + len >= mgmt->u.probe_resp.variable &&
+ ar->nw_type == AP_NETWORK && test_bit(CONNECTED, &ar->flag) &&
+ ieee80211_is_probe_resp(mgmt->frame_control)) {
+ /*
+ * Send Probe Response frame in AP mode using a separate WMI
+ * command to allow the target to fill in the generic IEs.
+ */
+ *cookie = 0; /* TX status not supported */
+ return ath6kl_send_go_probe_resp(ar, buf, len,
+ chan->center_freq);
+ }
+
+ id = ar->send_action_id++;
+ if (id == 0) {
+ /*
+ * 0 is a reserved value in the WMI command and shall not be
+ * used for the command.
+ */
+ id = ar->send_action_id++;
+ }
+
+ *cookie = id;
+ return ath6kl_wmi_send_action_cmd(ar->wmi, id, chan->center_freq, wait,
+ buf, len);
+}
+
+static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
+ struct net_device *dev,
+ u16 frame_type, bool reg)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
+ __func__, frame_type, reg);
+ if (frame_type == IEEE80211_STYPE_PROBE_REQ) {
+ /*
+ * Note: This notification callback is not allowed to sleep, so
+ * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
+ * hardcode target to report Probe Request frames all the time.
+ */
+ ar->probe_req_report = reg;
+ }
+}
+
+static const struct ieee80211_txrx_stypes
+ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+ [NL80211_IFTYPE_STATION] = {
+ .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_P2P_CLIENT] = {
+ .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_P2P_GO] = {
+ .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+};
+
+static struct cfg80211_ops ath6kl_cfg80211_ops = {
+ .change_virtual_intf = ath6kl_cfg80211_change_iface,
+ .scan = ath6kl_cfg80211_scan,
+ .connect = ath6kl_cfg80211_connect,
+ .disconnect = ath6kl_cfg80211_disconnect,
+ .add_key = ath6kl_cfg80211_add_key,
+ .get_key = ath6kl_cfg80211_get_key,
+ .del_key = ath6kl_cfg80211_del_key,
+ .set_default_key = ath6kl_cfg80211_set_default_key,
+ .set_wiphy_params = ath6kl_cfg80211_set_wiphy_params,
+ .set_tx_power = ath6kl_cfg80211_set_txpower,
+ .get_tx_power = ath6kl_cfg80211_get_txpower,
+ .set_power_mgmt = ath6kl_cfg80211_set_power_mgmt,
+ .join_ibss = ath6kl_cfg80211_join_ibss,
+ .leave_ibss = ath6kl_cfg80211_leave_ibss,
+ .get_station = ath6kl_get_station,
+ .set_pmksa = ath6kl_set_pmksa,
+ .del_pmksa = ath6kl_del_pmksa,
+ .flush_pmksa = ath6kl_flush_pmksa,
+ CFG80211_TESTMODE_CMD(ath6kl_tm_cmd)
+#ifdef CONFIG_PM
+ .suspend = ar6k_cfg80211_suspend,
+#endif
+ .set_channel = ath6kl_set_channel,
+ .add_beacon = ath6kl_add_beacon,
+ .set_beacon = ath6kl_set_beacon,
+ .del_beacon = ath6kl_del_beacon,
+ .change_station = ath6kl_change_station,
+ .remain_on_channel = ath6kl_remain_on_channel,
+ .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
+ .mgmt_tx = ath6kl_mgmt_tx,
+ .mgmt_frame_register = ath6kl_mgmt_frame_register,
+};
+
+struct wireless_dev *ath6kl_cfg80211_init(struct device *dev)
+{
+ int ret = 0;
+ struct wireless_dev *wdev;
+ struct ath6kl *ar;
+
+ wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+ if (!wdev) {
+ ath6kl_err("couldn't allocate wireless device\n");
+ return NULL;
+ }
+
+ /* create a new wiphy for use with cfg80211 */
+ wdev->wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
+ if (!wdev->wiphy) {
+ ath6kl_err("couldn't allocate wiphy device\n");
+ kfree(wdev);
+ return NULL;
+ }
+
+ ar = wiphy_priv(wdev->wiphy);
+ ar->p2p = !!ath6kl_p2p;
+
+ wdev->wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
+
+ wdev->wiphy->max_remain_on_channel_duration = 5000;
+
+ /* set device pointer for wiphy */
+ set_wiphy_dev(wdev->wiphy, dev);
+
+ wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
+ if (ar->p2p) {
+ wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT);
+ }
+ /* max num of ssids that can be probed during scanning */
+ wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
+ wdev->wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
+ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
+ wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
+ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+ wdev->wiphy->cipher_suites = cipher_suites;
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+
+ ret = wiphy_register(wdev->wiphy);
+ if (ret < 0) {
+ ath6kl_err("couldn't register wiphy device\n");
+ wiphy_free(wdev->wiphy);
+ kfree(wdev);
+ return NULL;
+ }
+
+ return wdev;
+}
+
+void ath6kl_cfg80211_deinit(struct ath6kl *ar)
+{
+ struct wireless_dev *wdev = ar->wdev;
+
+ if (ar->scan_req) {
+ cfg80211_scan_done(ar->scan_req, true);
+ ar->scan_req = NULL;
+ }
+
+ if (!wdev)
+ return;
+
+ wiphy_unregister(wdev->wiphy);
+ wiphy_free(wdev->wiphy);
+ kfree(wdev);
+}
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
new file mode 100644
index 000000000000..a84adc249c61
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH6KL_CFG80211_H
+#define ATH6KL_CFG80211_H
+
+struct wireless_dev *ath6kl_cfg80211_init(struct device *dev);
+void ath6kl_cfg80211_deinit(struct ath6kl *ar);
+
+void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status);
+
+void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
+ u8 *bssid, u16 listen_intvl,
+ u16 beacon_intvl,
+ enum network_type nw_type,
+ u8 beacon_ie_len, u8 assoc_req_len,
+ u8 assoc_resp_len, u8 *assoc_info);
+
+void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
+ u8 *bssid, u8 assoc_resp_len,
+ u8 *assoc_info, u16 proto_reason);
+
+void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid,
+ bool ismcast);
+
+#endif /* ATH6KL_CFG80211_H */
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h
new file mode 100644
index 000000000000..b92f0e5d2336
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/common.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <linux/netdevice.h>
+
+#define ATH6KL_MAX_IE 256
+
+extern int ath6kl_printk(const char *level, const char *fmt, ...);
+
+#define A_CACHE_LINE_PAD 128
+
+/*
+ * Reflects the version of binary interface exposed by ATH6KL target
+ * firmware. Needs to be incremented by 1 for any change in the firmware
+ * that requires upgrade of the driver on the host side for the change to
+ * work correctly
+ */
+#define ATH6KL_ABI_VERSION 1
+
+#define SIGNAL_QUALITY_METRICS_NUM_MAX 2
+
+enum {
+ SIGNAL_QUALITY_METRICS_SNR = 0,
+ SIGNAL_QUALITY_METRICS_RSSI,
+ SIGNAL_QUALITY_METRICS_ALL,
+};
+
+/*
+ * Data Path
+ */
+
+#define WMI_MAX_TX_DATA_FRAME_LENGTH \
+ (1500 + sizeof(struct wmi_data_hdr) + \
+ sizeof(struct ethhdr) + \
+ sizeof(struct ath6kl_llc_snap_hdr))
+
+/* An AMSDU frame */ /* The MAX AMSDU length of AR6003 is 3839 */
+#define WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH \
+ (3840 + sizeof(struct wmi_data_hdr) + \
+ sizeof(struct ethhdr) + \
+ sizeof(struct ath6kl_llc_snap_hdr))
+
+#define EPPING_ALIGNMENT_PAD \
+ (((sizeof(struct htc_frame_hdr) + 3) & (~0x3)) \
+ - sizeof(struct htc_frame_hdr))
+
+struct ath6kl_llc_snap_hdr {
+ u8 dsap;
+ u8 ssap;
+ u8 cntl;
+ u8 org_code[3];
+ __be16 eth_type;
+} __packed;
+
+enum crypto_type {
+ NONE_CRYPT = 0x01,
+ WEP_CRYPT = 0x02,
+ TKIP_CRYPT = 0x04,
+ AES_CRYPT = 0x08,
+};
+
+struct htc_endpoint_credit_dist;
+struct ath6kl;
+enum htc_credit_dist_reason;
+struct htc_credit_state_info;
+
+int ath6k_setup_credit_dist(void *htc_handle,
+ struct htc_credit_state_info *cred_info);
+void ath6k_credit_distribute(struct htc_credit_state_info *cred_inf,
+ struct list_head *epdist_list,
+ enum htc_credit_dist_reason reason);
+void ath6k_credit_init(struct htc_credit_state_info *cred_inf,
+ struct list_head *ep_list,
+ int tot_credits);
+void ath6k_seek_credits(struct htc_credit_state_info *cred_inf,
+ struct htc_endpoint_credit_dist *ep_dist);
+struct ath6kl *ath6kl_core_alloc(struct device *sdev);
+int ath6kl_core_init(struct ath6kl *ar);
+int ath6kl_unavail_ev(struct ath6kl *ar);
+struct sk_buff *ath6kl_buf_alloc(int size);
+#endif /* COMMON_H */
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
new file mode 100644
index 000000000000..6d8a4845baaf
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -0,0 +1,637 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef CORE_H
+#define CORE_H
+
+#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/firmware.h>
+#include <linux/sched.h>
+#include <linux/circ_buf.h>
+#include <net/cfg80211.h>
+#include "htc.h"
+#include "wmi.h"
+#include "bmi.h"
+#include "target.h"
+
+#define MAX_ATH6KL 1
+#define ATH6KL_MAX_RX_BUFFERS 16
+#define ATH6KL_BUFFER_SIZE 1664
+#define ATH6KL_MAX_AMSDU_RX_BUFFERS 4
+#define ATH6KL_AMSDU_REFILL_THRESHOLD 3
+#define ATH6KL_AMSDU_BUFFER_SIZE (WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH + 128)
+#define MAX_MSDU_SUBFRAME_PAYLOAD_LEN 1508
+#define MIN_MSDU_SUBFRAME_PAYLOAD_LEN 46
+
+#define USER_SAVEDKEYS_STAT_INIT 0
+#define USER_SAVEDKEYS_STAT_RUN 1
+
+#define ATH6KL_TX_TIMEOUT 10
+#define ATH6KL_MAX_ENDPOINTS 4
+#define MAX_NODE_NUM 15
+
+/* Extra bytes for htc header alignment */
+#define ATH6KL_HTC_ALIGN_BYTES 3
+
+/* MAX_HI_COOKIE_NUM are reserved for high priority traffic */
+#define MAX_DEF_COOKIE_NUM 180
+#define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */
+#define MAX_COOKIE_NUM (MAX_DEF_COOKIE_NUM + MAX_HI_COOKIE_NUM)
+
+#define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC)
+
+#define DISCON_TIMER_INTVAL 10000 /* in msec */
+#define A_DEFAULT_LISTEN_INTERVAL 100
+#define A_MAX_WOW_LISTEN_INTERVAL 1000
+
+/* includes also the null byte */
+#define ATH6KL_FIRMWARE_MAGIC "QCA-ATH6KL"
+
+enum ath6kl_fw_ie_type {
+ ATH6KL_FW_IE_FW_VERSION = 0,
+ ATH6KL_FW_IE_TIMESTAMP = 1,
+ ATH6KL_FW_IE_OTP_IMAGE = 2,
+ ATH6KL_FW_IE_FW_IMAGE = 3,
+ ATH6KL_FW_IE_PATCH_IMAGE = 4,
+ ATH6KL_FW_IE_RESERVED_RAM_SIZE = 5,
+ ATH6KL_FW_IE_CAPABILITIES = 6,
+ ATH6KL_FW_IE_PATCH_ADDR = 7,
+};
+
+enum ath6kl_fw_capability {
+ ATH6KL_FW_CAPABILITY_HOST_P2P = 0,
+
+ /* this needs to be last */
+ ATH6KL_FW_CAPABILITY_MAX,
+};
+
+#define ATH6KL_CAPABILITY_LEN (ALIGN(ATH6KL_FW_CAPABILITY_MAX, 32) / 32)
+
+struct ath6kl_fw_ie {
+ __le32 id;
+ __le32 len;
+ u8 data[0];
+};
+
+/* AR6003 1.0 definitions */
+#define AR6003_REV1_VERSION 0x300002ba
+
+/* AR6003 2.0 definitions */
+#define AR6003_REV2_VERSION 0x30000384
+#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910
+#define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77"
+#define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77"
+#define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin"
+#define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin"
+#define AR6003_REV2_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin"
+#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin"
+#define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin"
+
+/* AR6003 3.0 definitions */
+#define AR6003_REV3_VERSION 0x30000582
+#define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin"
+#define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin"
+#define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin"
+#define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin"
+#define AR6003_REV3_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin"
+#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin"
+#define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \
+ "ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
+
+/* AR6004 1.0 definitions */
+#define AR6004_REV1_VERSION 0x30000623
+#define AR6004_REV1_FIRMWARE_FILE "ath6k/AR6004/hw6.1/fw.ram.bin"
+#define AR6004_REV1_FIRMWARE_2_FILE "ath6k/AR6004/hw6.1/fw-2.bin"
+#define AR6004_REV1_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.bin"
+#define AR6004_REV1_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.DB132.bin"
+#define AR6004_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6004/hw6.1/endpointping.bin"
+
+/* Per STA data, used in AP mode */
+#define STA_PS_AWAKE BIT(0)
+#define STA_PS_SLEEP BIT(1)
+#define STA_PS_POLLED BIT(2)
+
+/* HTC TX packet tagging definitions */
+#define ATH6KL_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED
+#define ATH6KL_DATA_PKT_TAG (ATH6KL_CONTROL_PKT_TAG + 1)
+
+#define AR6003_CUST_DATA_SIZE 16
+
+#define AGGR_WIN_IDX(x, y) ((x) % (y))
+#define AGGR_INCR_IDX(x, y) AGGR_WIN_IDX(((x) + 1), (y))
+#define AGGR_DCRM_IDX(x, y) AGGR_WIN_IDX(((x) - 1), (y))
+#define ATH6KL_MAX_SEQ_NO 0xFFF
+#define ATH6KL_NEXT_SEQ_NO(x) (((x) + 1) & ATH6KL_MAX_SEQ_NO)
+
+#define NUM_OF_TIDS 8
+#define AGGR_SZ_DEFAULT 8
+
+#define AGGR_WIN_SZ_MIN 2
+#define AGGR_WIN_SZ_MAX 8
+
+#define TID_WINDOW_SZ(_x) ((_x) << 1)
+
+#define AGGR_NUM_OF_FREE_NETBUFS 16
+
+#define AGGR_RX_TIMEOUT 400 /* in ms */
+
+#define WMI_TIMEOUT (2 * HZ)
+
+#define MBOX_YIELD_LIMIT 99
+
+/* configuration lags */
+/*
+ * ATH6KL_CONF_IGNORE_ERP_BARKER: Ignore the barker premable in
+ * ERP IE of beacon to determine the short premable support when
+ * sending (Re)Assoc req.
+ * ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN: Don't send the power
+ * module state transition failure events which happen during
+ * scan, to the host.
+ */
+#define ATH6KL_CONF_IGNORE_ERP_BARKER BIT(0)
+#define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN BIT(1)
+#define ATH6KL_CONF_ENABLE_11N BIT(2)
+#define ATH6KL_CONF_ENABLE_TX_BURST BIT(3)
+
+enum wlan_low_pwr_state {
+ WLAN_POWER_STATE_ON,
+ WLAN_POWER_STATE_CUT_PWR,
+ WLAN_POWER_STATE_DEEP_SLEEP,
+ WLAN_POWER_STATE_WOW
+};
+
+enum sme_state {
+ SME_DISCONNECTED,
+ SME_CONNECTING,
+ SME_CONNECTED
+};
+
+struct skb_hold_q {
+ struct sk_buff *skb;
+ bool is_amsdu;
+ u16 seq_no;
+};
+
+struct rxtid {
+ bool aggr;
+ bool progress;
+ bool timer_mon;
+ u16 win_sz;
+ u16 seq_next;
+ u32 hold_q_sz;
+ struct skb_hold_q *hold_q;
+ struct sk_buff_head q;
+ spinlock_t lock;
+};
+
+struct rxtid_stats {
+ u32 num_into_aggr;
+ u32 num_dups;
+ u32 num_oow;
+ u32 num_mpdu;
+ u32 num_amsdu;
+ u32 num_delivered;
+ u32 num_timeouts;
+ u32 num_hole;
+ u32 num_bar;
+};
+
+struct aggr_info {
+ u8 aggr_sz;
+ u8 timer_scheduled;
+ struct timer_list timer;
+ struct net_device *dev;
+ struct rxtid rx_tid[NUM_OF_TIDS];
+ struct sk_buff_head free_q;
+ struct rxtid_stats stat[NUM_OF_TIDS];
+};
+
+struct ath6kl_wep_key {
+ u8 key_index;
+ u8 key_len;
+ u8 key[64];
+};
+
+#define ATH6KL_KEY_SEQ_LEN 8
+
+struct ath6kl_key {
+ u8 key[WLAN_MAX_KEY_LEN];
+ u8 key_len;
+ u8 seq[ATH6KL_KEY_SEQ_LEN];
+ u8 seq_len;
+ u32 cipher;
+};
+
+struct ath6kl_node_mapping {
+ u8 mac_addr[ETH_ALEN];
+ u8 ep_id;
+ u8 tx_pend;
+};
+
+struct ath6kl_cookie {
+ struct sk_buff *skb;
+ u32 map_no;
+ struct htc_packet htc_pkt;
+ struct ath6kl_cookie *arc_list_next;
+};
+
+struct ath6kl_sta {
+ u16 sta_flags;
+ u8 mac[ETH_ALEN];
+ u8 aid;
+ u8 keymgmt;
+ u8 ucipher;
+ u8 auth;
+ u8 wpa_ie[ATH6KL_MAX_IE];
+ struct sk_buff_head psq;
+ spinlock_t psq_lock;
+};
+
+struct ath6kl_version {
+ u32 target_ver;
+ u32 wlan_ver;
+ u32 abi_ver;
+};
+
+struct ath6kl_bmi {
+ u32 cmd_credits;
+ bool done_sent;
+ u8 *cmd_buf;
+};
+
+struct target_stats {
+ u64 tx_pkt;
+ u64 tx_byte;
+ u64 tx_ucast_pkt;
+ u64 tx_ucast_byte;
+ u64 tx_mcast_pkt;
+ u64 tx_mcast_byte;
+ u64 tx_bcast_pkt;
+ u64 tx_bcast_byte;
+ u64 tx_rts_success_cnt;
+ u64 tx_pkt_per_ac[4];
+
+ u64 tx_err;
+ u64 tx_fail_cnt;
+ u64 tx_retry_cnt;
+ u64 tx_mult_retry_cnt;
+ u64 tx_rts_fail_cnt;
+
+ u64 rx_pkt;
+ u64 rx_byte;
+ u64 rx_ucast_pkt;
+ u64 rx_ucast_byte;
+ u64 rx_mcast_pkt;
+ u64 rx_mcast_byte;
+ u64 rx_bcast_pkt;
+ u64 rx_bcast_byte;
+ u64 rx_frgment_pkt;
+
+ u64 rx_err;
+ u64 rx_crc_err;
+ u64 rx_key_cache_miss;
+ u64 rx_decrypt_err;
+ u64 rx_dupl_frame;
+
+ u64 tkip_local_mic_fail;
+ u64 tkip_cnter_measures_invoked;
+ u64 tkip_replays;
+ u64 tkip_fmt_err;
+ u64 ccmp_fmt_err;
+ u64 ccmp_replays;
+
+ u64 pwr_save_fail_cnt;
+
+ u64 cs_bmiss_cnt;
+ u64 cs_low_rssi_cnt;
+ u64 cs_connect_cnt;
+ u64 cs_discon_cnt;
+
+ s32 tx_ucast_rate;
+ s32 rx_ucast_rate;
+
+ u32 lq_val;
+
+ u32 wow_pkt_dropped;
+ u16 wow_evt_discarded;
+
+ s16 noise_floor_calib;
+ s16 cs_rssi;
+ s16 cs_ave_beacon_rssi;
+ u8 cs_ave_beacon_snr;
+ u8 cs_last_roam_msec;
+ u8 cs_snr;
+
+ u8 wow_host_pkt_wakeups;
+ u8 wow_host_evt_wakeups;
+
+ u32 arp_received;
+ u32 arp_matched;
+ u32 arp_replied;
+};
+
+struct ath6kl_mbox_info {
+ u32 htc_addr;
+ u32 htc_ext_addr;
+ u32 htc_ext_sz;
+
+ u32 block_size;
+
+ u32 gmbox_addr;
+
+ u32 gmbox_sz;
+};
+
+/*
+ * 802.11i defines an extended IV for use with non-WEP ciphers.
+ * When the EXTIV bit is set in the key id byte an additional
+ * 4 bytes immediately follow the IV for TKIP. For CCMP the
+ * EXTIV bit is likewise set but the 8 bytes represent the
+ * CCMP header rather than IV+extended-IV.
+ */
+
+#define ATH6KL_KEYBUF_SIZE 16
+#define ATH6KL_MICBUF_SIZE (8+8) /* space for both tx and rx */
+
+#define ATH6KL_KEY_XMIT 0x01
+#define ATH6KL_KEY_RECV 0x02
+#define ATH6KL_KEY_DEFAULT 0x80 /* default xmit key */
+
+/* Initial group key for AP mode */
+struct ath6kl_req_key {
+ bool valid;
+ u8 key_index;
+ int key_type;
+ u8 key[WLAN_MAX_KEY_LEN];
+ u8 key_len;
+};
+
+/* Flag info */
+#define WMI_ENABLED 0
+#define WMI_READY 1
+#define CONNECTED 2
+#define STATS_UPDATE_PEND 3
+#define CONNECT_PEND 4
+#define WMM_ENABLED 5
+#define NETQ_STOPPED 6
+#define WMI_CTRL_EP_FULL 7
+#define DTIM_EXPIRED 8
+#define DESTROY_IN_PROGRESS 9
+#define NETDEV_REGISTERED 10
+#define SKIP_SCAN 11
+#define WLAN_ENABLED 12
+#define TESTMODE 13
+#define CLEAR_BSSFILTER_ON_BEACON 14
+#define DTIM_PERIOD_AVAIL 15
+
+struct ath6kl {
+ struct device *dev;
+ struct net_device *net_dev;
+ struct ath6kl_bmi bmi;
+ const struct ath6kl_hif_ops *hif_ops;
+ struct wmi *wmi;
+ int tx_pending[ENDPOINT_MAX];
+ int total_tx_data_pend;
+ struct htc_target *htc_target;
+ void *hif_priv;
+ spinlock_t lock;
+ struct semaphore sem;
+ int ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 next_mode;
+ u8 nw_type;
+ u8 dot11_auth_mode;
+ u8 auth_mode;
+ u8 prwise_crypto;
+ u8 prwise_crypto_len;
+ u8 grp_crypto;
+ u8 grp_crypto_len;
+ u8 def_txkey_index;
+ struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
+ u8 bssid[ETH_ALEN];
+ u8 req_bssid[ETH_ALEN];
+ u16 ch_hint;
+ u16 bss_ch;
+ u16 listen_intvl_b;
+ u16 listen_intvl_t;
+ u8 lrssi_roam_threshold;
+ struct ath6kl_version version;
+ u32 target_type;
+ u8 tx_pwr;
+ struct net_device_stats net_stats;
+ struct target_stats target_stats;
+ struct ath6kl_node_mapping node_map[MAX_NODE_NUM];
+ u8 ibss_ps_enable;
+ u8 node_num;
+ u8 next_ep_id;
+ struct ath6kl_cookie *cookie_list;
+ u32 cookie_count;
+ enum htc_endpoint_id ac2ep_map[WMM_NUM_AC];
+ bool ac_stream_active[WMM_NUM_AC];
+ u8 ac_stream_pri_map[WMM_NUM_AC];
+ u8 hiac_stream_active_pri;
+ u8 ep2ac_map[ENDPOINT_MAX];
+ enum htc_endpoint_id ctrl_ep;
+ struct htc_credit_state_info credit_state_info;
+ u32 connect_ctrl_flags;
+ u32 user_key_ctrl;
+ u8 usr_bss_filter;
+ struct ath6kl_sta sta_list[AP_MAX_NUM_STA];
+ u8 sta_list_index;
+ struct ath6kl_req_key ap_mode_bkey;
+ struct sk_buff_head mcastpsq;
+ spinlock_t mcastpsq_lock;
+ u8 intra_bss;
+ struct aggr_info *aggr_cntxt;
+ struct wmi_ap_mode_stat ap_stats;
+ u8 ap_country_code[3];
+ struct list_head amsdu_rx_buffer_queue;
+ struct timer_list disconnect_timer;
+ u8 rx_meta_ver;
+ struct wireless_dev *wdev;
+ struct cfg80211_scan_request *scan_req;
+ struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
+ enum sme_state sme_state;
+ enum wlan_low_pwr_state wlan_pwr_state;
+ struct wmi_scan_params_cmd sc_params;
+#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4
+ struct {
+ void *rx_report;
+ size_t rx_report_len;
+ } tm;
+
+ struct {
+ u32 dataset_patch_addr;
+ u32 app_load_addr;
+ u32 app_start_override_addr;
+ u32 board_ext_data_addr;
+ u32 reserved_ram_size;
+ } hw;
+
+ u16 conf_flags;
+ wait_queue_head_t event_wq;
+ struct ath6kl_mbox_info mbox_info;
+
+ struct ath6kl_cookie cookie_mem[MAX_COOKIE_NUM];
+ int reconnect_flag;
+ unsigned long flag;
+
+ u8 *fw_board;
+ size_t fw_board_len;
+
+ u8 *fw_otp;
+ size_t fw_otp_len;
+
+ u8 *fw;
+ size_t fw_len;
+
+ u8 *fw_patch;
+ size_t fw_patch_len;
+
+ unsigned long fw_capabilities[ATH6KL_CAPABILITY_LEN];
+
+ struct workqueue_struct *ath6kl_wq;
+
+ struct dentry *debugfs_phy;
+
+ u32 send_action_id;
+ bool probe_req_report;
+ u16 next_chan;
+
+ bool p2p;
+ u16 assoc_bss_beacon_int;
+ u8 assoc_bss_dtim_period;
+
+#ifdef CONFIG_ATH6KL_DEBUG
+ struct {
+ struct circ_buf fwlog_buf;
+ spinlock_t fwlog_lock;
+ void *fwlog_tmp;
+ u32 fwlog_mask;
+ unsigned int dbgfs_diag_reg;
+ u32 diag_reg_addr_wr;
+ u32 diag_reg_val_wr;
+
+ struct {
+ unsigned int invalid_rate;
+ } war_stats;
+ } debug;
+#endif /* CONFIG_ATH6KL_DEBUG */
+};
+
+static inline void *ath6kl_priv(struct net_device *dev)
+{
+ return wdev_priv(dev->ieee80211_ptr);
+}
+
+static inline void ath6kl_deposit_credit_to_ep(struct htc_credit_state_info
+ *cred_info,
+ struct htc_endpoint_credit_dist
+ *ep_dist, int credits)
+{
+ ep_dist->credits += credits;
+ ep_dist->cred_assngd += credits;
+ cred_info->cur_free_credits -= credits;
+}
+
+static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar,
+ u32 item_offset)
+{
+ u32 addr = 0;
+
+ if (ar->target_type == TARGET_TYPE_AR6003)
+ addr = ATH6KL_AR6003_HI_START_ADDR + item_offset;
+ else if (ar->target_type == TARGET_TYPE_AR6004)
+ addr = ATH6KL_AR6004_HI_START_ADDR + item_offset;
+
+ return addr;
+}
+
+void ath6kl_destroy(struct net_device *dev, unsigned int unregister);
+int ath6kl_configure_target(struct ath6kl *ar);
+void ath6kl_detect_error(unsigned long ptr);
+void disconnect_timer_handler(unsigned long ptr);
+void init_netdev(struct net_device *dev);
+void ath6kl_cookie_init(struct ath6kl *ar);
+void ath6kl_cookie_cleanup(struct ath6kl *ar);
+void ath6kl_rx(struct htc_target *target, struct htc_packet *packet);
+void ath6kl_tx_complete(void *context, struct list_head *packet_queue);
+enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
+ struct htc_packet *packet);
+void ath6kl_stop_txrx(struct ath6kl *ar);
+void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar);
+int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value);
+int ath6kl_diag_write(struct ath6kl *ar, u32 address, void *data, u32 length);
+int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value);
+int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length);
+int ath6kl_read_fwlogs(struct ath6kl *ar);
+void ath6kl_init_profile_info(struct ath6kl *ar);
+void ath6kl_tx_data_cleanup(struct ath6kl *ar);
+void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile,
+ bool get_dbglogs);
+
+struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar);
+void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie);
+int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev);
+
+struct aggr_info *aggr_init(struct net_device *dev);
+void ath6kl_rx_refill(struct htc_target *target,
+ enum htc_endpoint_id endpoint);
+void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count);
+struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target,
+ enum htc_endpoint_id endpoint,
+ int len);
+void aggr_module_destroy(struct aggr_info *aggr_info);
+void aggr_reset_state(struct aggr_info *aggr_info);
+
+struct ath6kl_sta *ath6kl_find_sta(struct ath6kl *ar, u8 * node_addr);
+struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid);
+
+void ath6kl_ready_event(void *devt, u8 * datap, u32 sw_ver, u32 abi_ver);
+int ath6kl_control_tx(void *devt, struct sk_buff *skb,
+ enum htc_endpoint_id eid);
+void ath6kl_connect_event(struct ath6kl *ar, u16 channel,
+ u8 *bssid, u16 listen_int,
+ u16 beacon_int, enum network_type net_type,
+ u8 beacon_ie_len, u8 assoc_req_len,
+ u8 assoc_resp_len, u8 *assoc_info);
+void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel);
+void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
+ u8 keymgmt, u8 ucipher, u8 auth,
+ u8 assoc_req_len, u8 *assoc_info);
+void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason,
+ u8 *bssid, u8 assoc_resp_len,
+ u8 *assoc_info, u16 prot_reason_status);
+void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast);
+void ath6kl_txpwr_rx_evt(void *devt, u8 tx_pwr);
+void ath6kl_scan_complete_evt(struct ath6kl *ar, int status);
+void ath6kl_tgt_stats_event(struct ath6kl *ar, u8 *ptr, u32 len);
+void ath6kl_indicate_tx_activity(void *devt, u8 traffic_class, bool active);
+enum htc_endpoint_id ath6kl_ac2_endpoint_id(void *devt, u8 ac);
+
+void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid);
+
+void ath6kl_dtimexpiry_event(struct ath6kl *ar);
+void ath6kl_disconnect(struct ath6kl *ar);
+void ath6kl_deep_sleep_enable(struct ath6kl *ar);
+void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid);
+void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no,
+ u8 win_sz);
+void ath6kl_wakeup_event(void *dev);
+void ath6kl_target_failure(struct ath6kl *ar);
+
+#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
new file mode 100644
index 000000000000..ba3f23d71150
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -0,0 +1,934 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications 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 <linux/circ_buf.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+
+#include "debug.h"
+#include "target.h"
+
+struct ath6kl_fwlog_slot {
+ __le32 timestamp;
+ __le32 length;
+
+ /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */
+ u8 payload[0];
+};
+
+#define ATH6KL_FWLOG_SIZE 32768
+#define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \
+ ATH6KL_FWLOG_PAYLOAD_SIZE)
+#define ATH6KL_FWLOG_VALID_MASK 0x1ffff
+
+int ath6kl_printk(const char *level, const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ int rtn;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ rtn = printk("%sath6kl: %pV", level, &vaf);
+
+ va_end(args);
+
+ return rtn;
+}
+
+#ifdef CONFIG_ATH6KL_DEBUG
+
+#define REG_OUTPUT_LEN_PER_LINE 25
+#define REGTYPE_STR_LEN 100
+
+struct ath6kl_diag_reg_info {
+ u32 reg_start;
+ u32 reg_end;
+ const char *reg_info;
+};
+
+static const struct ath6kl_diag_reg_info diag_reg[] = {
+ { 0x20000, 0x200fc, "General DMA and Rx registers" },
+ { 0x28000, 0x28900, "MAC PCU register & keycache" },
+ { 0x20800, 0x20a40, "QCU" },
+ { 0x21000, 0x212f0, "DCU" },
+ { 0x4000, 0x42e4, "RTC" },
+ { 0x540000, 0x540000 + (256 * 1024), "RAM" },
+ { 0x29800, 0x2B210, "Base Band" },
+ { 0x1C000, 0x1C748, "Analog" },
+};
+
+void ath6kl_dump_registers(struct ath6kl_device *dev,
+ struct ath6kl_irq_proc_registers *irq_proc_reg,
+ struct ath6kl_irq_enable_reg *irq_enable_reg)
+{
+
+ ath6kl_dbg(ATH6KL_DBG_ANY, ("<------- Register Table -------->\n"));
+
+ if (irq_proc_reg != NULL) {
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "Host Int status: 0x%x\n",
+ irq_proc_reg->host_int_status);
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "CPU Int status: 0x%x\n",
+ irq_proc_reg->cpu_int_status);
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "Error Int status: 0x%x\n",
+ irq_proc_reg->error_int_status);
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "Counter Int status: 0x%x\n",
+ irq_proc_reg->counter_int_status);
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "Mbox Frame: 0x%x\n",
+ irq_proc_reg->mbox_frame);
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "Rx Lookahead Valid: 0x%x\n",
+ irq_proc_reg->rx_lkahd_valid);
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "Rx Lookahead 0: 0x%x\n",
+ irq_proc_reg->rx_lkahd[0]);
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "Rx Lookahead 1: 0x%x\n",
+ irq_proc_reg->rx_lkahd[1]);
+
+ if (dev->ar->mbox_info.gmbox_addr != 0) {
+ /*
+ * If the target supports GMBOX hardware, dump some
+ * additional state.
+ */
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "GMBOX Host Int status 2: 0x%x\n",
+ irq_proc_reg->host_int_status2);
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "GMBOX RX Avail: 0x%x\n",
+ irq_proc_reg->gmbox_rx_avail);
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "GMBOX lookahead alias 0: 0x%x\n",
+ irq_proc_reg->rx_gmbox_lkahd_alias[0]);
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "GMBOX lookahead alias 1: 0x%x\n",
+ irq_proc_reg->rx_gmbox_lkahd_alias[1]);
+ }
+
+ }
+
+ if (irq_enable_reg != NULL) {
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "Int status Enable: 0x%x\n",
+ irq_enable_reg->int_status_en);
+ ath6kl_dbg(ATH6KL_DBG_ANY, "Counter Int status Enable: 0x%x\n",
+ irq_enable_reg->cntr_int_status_en);
+ }
+ ath6kl_dbg(ATH6KL_DBG_ANY, "<------------------------------->\n");
+}
+
+static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist)
+{
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "--- endpoint: %d svc_id: 0x%X ---\n",
+ ep_dist->endpoint, ep_dist->svc_id);
+ ath6kl_dbg(ATH6KL_DBG_ANY, " dist_flags : 0x%X\n",
+ ep_dist->dist_flags);
+ ath6kl_dbg(ATH6KL_DBG_ANY, " cred_norm : %d\n",
+ ep_dist->cred_norm);
+ ath6kl_dbg(ATH6KL_DBG_ANY, " cred_min : %d\n",
+ ep_dist->cred_min);
+ ath6kl_dbg(ATH6KL_DBG_ANY, " credits : %d\n",
+ ep_dist->credits);
+ ath6kl_dbg(ATH6KL_DBG_ANY, " cred_assngd : %d\n",
+ ep_dist->cred_assngd);
+ ath6kl_dbg(ATH6KL_DBG_ANY, " seek_cred : %d\n",
+ ep_dist->seek_cred);
+ ath6kl_dbg(ATH6KL_DBG_ANY, " cred_sz : %d\n",
+ ep_dist->cred_sz);
+ ath6kl_dbg(ATH6KL_DBG_ANY, " cred_per_msg : %d\n",
+ ep_dist->cred_per_msg);
+ ath6kl_dbg(ATH6KL_DBG_ANY, " cred_to_dist : %d\n",
+ ep_dist->cred_to_dist);
+ ath6kl_dbg(ATH6KL_DBG_ANY, " txq_depth : %d\n",
+ get_queue_depth(&((struct htc_endpoint *)
+ ep_dist->htc_rsvd)->txq));
+ ath6kl_dbg(ATH6KL_DBG_ANY,
+ "----------------------------------\n");
+}
+
+void dump_cred_dist_stats(struct htc_target *target)
+{
+ struct htc_endpoint_credit_dist *ep_list;
+
+ if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_TRC))
+ return;
+
+ list_for_each_entry(ep_list, &target->cred_dist_list, list)
+ dump_cred_dist(ep_list);
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:%p dist:%p\n",
+ target->cred_dist_cntxt, NULL);
+ ath6kl_dbg(ATH6KL_DBG_TRC, "credit distribution, total : %d, free : %d\n",
+ target->cred_dist_cntxt->total_avail_credits,
+ target->cred_dist_cntxt->cur_free_credits);
+}
+
+static int ath6kl_debugfs_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
+{
+ switch (war) {
+ case ATH6KL_WAR_INVALID_RATE:
+ ar->debug.war_stats.invalid_rate++;
+ break;
+ }
+}
+
+static ssize_t read_file_war_stats(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ char *buf;
+ unsigned int len = 0, buf_len = 1500;
+ ssize_t ret_cnt;
+
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%25s\n",
+ "Workaround stats");
+ len += scnprintf(buf + len, buf_len - len, "%25s\n\n",
+ "=================");
+ len += scnprintf(buf + len, buf_len - len, "%20s %10u\n",
+ "Invalid rates", ar->debug.war_stats.invalid_rate);
+
+ if (WARN_ON(len > buf_len))
+ len = buf_len;
+
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+ kfree(buf);
+ return ret_cnt;
+}
+
+static const struct file_operations fops_war_stats = {
+ .read = read_file_war_stats,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf,
+ size_t buf_len)
+{
+ struct circ_buf *fwlog = &ar->debug.fwlog_buf;
+ size_t space;
+ int i;
+
+ /* entries must all be equal size */
+ if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE))
+ return;
+
+ space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE);
+ if (space < buf_len)
+ /* discard oldest slot */
+ fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) &
+ (ATH6KL_FWLOG_SIZE - 1);
+
+ for (i = 0; i < buf_len; i += space) {
+ space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail,
+ ATH6KL_FWLOG_SIZE);
+
+ if ((size_t) space > buf_len - i)
+ space = buf_len - i;
+
+ memcpy(&fwlog->buf[fwlog->head], buf, space);
+ fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1);
+ }
+
+}
+
+void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
+{
+ struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp;
+ size_t slot_len;
+
+ if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
+ return;
+
+ spin_lock_bh(&ar->debug.fwlog_lock);
+
+ slot->timestamp = cpu_to_le32(jiffies);
+ slot->length = cpu_to_le32(len);
+ memcpy(slot->payload, buf, len);
+
+ slot_len = sizeof(*slot) + len;
+
+ if (slot_len < ATH6KL_FWLOG_SLOT_SIZE)
+ memset(slot->payload + len, 0,
+ ATH6KL_FWLOG_SLOT_SIZE - slot_len);
+
+ ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE);
+
+ spin_unlock_bh(&ar->debug.fwlog_lock);
+}
+
+static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar)
+{
+ return CIRC_CNT(ar->debug.fwlog_buf.head,
+ ar->debug.fwlog_buf.tail,
+ ATH6KL_FWLOG_SLOT_SIZE) == 0;
+}
+
+static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ struct circ_buf *fwlog = &ar->debug.fwlog_buf;
+ size_t len = 0, buf_len = count;
+ ssize_t ret_cnt;
+ char *buf;
+ int ccnt;
+
+ buf = vmalloc(buf_len);
+ if (!buf)
+ return -ENOMEM;
+
+ /* read undelivered logs from firmware */
+ ath6kl_read_fwlogs(ar);
+
+ spin_lock_bh(&ar->debug.fwlog_lock);
+
+ while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) {
+ ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail,
+ ATH6KL_FWLOG_SIZE);
+
+ if ((size_t) ccnt > buf_len - len)
+ ccnt = buf_len - len;
+
+ memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt);
+ len += ccnt;
+
+ fwlog->tail = (fwlog->tail + ccnt) &
+ (ATH6KL_FWLOG_SIZE - 1);
+ }
+
+ spin_unlock_bh(&ar->debug.fwlog_lock);
+
+ if (WARN_ON(len > buf_len))
+ len = buf_len;
+
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+ vfree(buf);
+
+ return ret_cnt;
+}
+
+static const struct file_operations fops_fwlog = {
+ .open = ath6kl_debugfs_open,
+ .read = ath6kl_fwlog_read,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ char buf[16];
+ int len;
+
+ len = snprintf(buf, sizeof(buf), "0x%x\n", ar->debug.fwlog_mask);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath6kl_fwlog_mask_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ int ret;
+
+ ret = kstrtou32_from_user(user_buf, count, 0, &ar->debug.fwlog_mask);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_wmi_config_debug_module_cmd(ar->wmi,
+ ATH6KL_FWLOG_VALID_MASK,
+ ar->debug.fwlog_mask);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_fwlog_mask = {
+ .open = ath6kl_debugfs_open,
+ .read = ath6kl_fwlog_mask_read,
+ .write = ath6kl_fwlog_mask_write,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ struct target_stats *tgt_stats = &ar->target_stats;
+ char *buf;
+ unsigned int len = 0, buf_len = 1500;
+ int i;
+ long left;
+ ssize_t ret_cnt;
+
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (down_interruptible(&ar->sem)) {
+ kfree(buf);
+ return -EBUSY;
+ }
+
+ set_bit(STATS_UPDATE_PEND, &ar->flag);
+
+ if (ath6kl_wmi_get_stats_cmd(ar->wmi)) {
+ up(&ar->sem);
+ kfree(buf);
+ return -EIO;
+ }
+
+ left = wait_event_interruptible_timeout(ar->event_wq,
+ !test_bit(STATS_UPDATE_PEND,
+ &ar->flag), WMI_TIMEOUT);
+
+ up(&ar->sem);
+
+ if (left <= 0) {
+ kfree(buf);
+ return -ETIMEDOUT;
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%25s\n",
+ "Target Tx stats");
+ len += scnprintf(buf + len, buf_len - len, "%25s\n\n",
+ "=================");
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Ucast packets", tgt_stats->tx_ucast_pkt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Bcast packets", tgt_stats->tx_bcast_pkt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Ucast byte", tgt_stats->tx_ucast_byte);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Bcast byte", tgt_stats->tx_bcast_byte);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Rts success cnt", tgt_stats->tx_rts_success_cnt);
+ for (i = 0; i < 4; i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%18s %d %10llu\n", "PER on ac",
+ i, tgt_stats->tx_pkt_per_ac[i]);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Error", tgt_stats->tx_err);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Fail count", tgt_stats->tx_fail_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Retry count", tgt_stats->tx_retry_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Multi retry cnt", tgt_stats->tx_mult_retry_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Rts fail cnt", tgt_stats->tx_rts_fail_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n",
+ "TKIP counter measure used",
+ tgt_stats->tkip_cnter_measures_invoked);
+
+ len += scnprintf(buf + len, buf_len - len, "%25s\n",
+ "Target Rx stats");
+ len += scnprintf(buf + len, buf_len - len, "%25s\n",
+ "=================");
+
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Ucast packets", tgt_stats->rx_ucast_pkt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
+ "Ucast Rate", tgt_stats->rx_ucast_rate);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Bcast packets", tgt_stats->rx_bcast_pkt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Ucast byte", tgt_stats->rx_ucast_byte);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Bcast byte", tgt_stats->rx_bcast_byte);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Fragmented pkt", tgt_stats->rx_frgment_pkt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Error", tgt_stats->rx_err);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "CRC Err", tgt_stats->rx_crc_err);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Key chache miss", tgt_stats->rx_key_cache_miss);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Decrypt Err", tgt_stats->rx_decrypt_err);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Duplicate frame", tgt_stats->rx_dupl_frame);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Tkip Mic failure", tgt_stats->tkip_local_mic_fail);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "TKIP format err", tgt_stats->tkip_fmt_err);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "CCMP format Err", tgt_stats->ccmp_fmt_err);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
+ "CCMP Replay Err", tgt_stats->ccmp_replays);
+
+ len += scnprintf(buf + len, buf_len - len, "%25s\n",
+ "Misc Target stats");
+ len += scnprintf(buf + len, buf_len - len, "%25s\n",
+ "=================");
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Beacon Miss count", tgt_stats->cs_bmiss_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Num Connects", tgt_stats->cs_connect_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
+ "Num disconnects", tgt_stats->cs_discon_cnt);
+ len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
+ "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi);
+
+ if (len > buf_len)
+ len = buf_len;
+
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+ kfree(buf);
+ return ret_cnt;
+}
+
+static const struct file_operations fops_tgt_stats = {
+ .read = read_file_tgt_stats,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+#define print_credit_info(fmt_str, ep_list_field) \
+ (len += scnprintf(buf + len, buf_len - len, fmt_str, \
+ ep_list->ep_list_field))
+#define CREDIT_INFO_DISPLAY_STRING_LEN 200
+#define CREDIT_INFO_LEN 128
+
+static ssize_t read_file_credit_dist_stats(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ struct htc_target *target = ar->htc_target;
+ struct htc_endpoint_credit_dist *ep_list;
+ char *buf;
+ unsigned int buf_len, len = 0;
+ ssize_t ret_cnt;
+
+ buf_len = CREDIT_INFO_DISPLAY_STRING_LEN +
+ get_queue_depth(&target->cred_dist_list) * CREDIT_INFO_LEN;
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
+ "Total Avail Credits: ",
+ target->cred_dist_cntxt->total_avail_credits);
+ len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
+ "Free credits :",
+ target->cred_dist_cntxt->cur_free_credits);
+
+ len += scnprintf(buf + len, buf_len - len,
+ " Epid Flags Cred_norm Cred_min Credits Cred_assngd"
+ " Seek_cred Cred_sz Cred_per_msg Cred_to_dist"
+ " qdepth\n");
+
+ list_for_each_entry(ep_list, &target->cred_dist_list, list) {
+ print_credit_info(" %2d", endpoint);
+ print_credit_info("%10x", dist_flags);
+ print_credit_info("%8d", cred_norm);
+ print_credit_info("%9d", cred_min);
+ print_credit_info("%9d", credits);
+ print_credit_info("%10d", cred_assngd);
+ print_credit_info("%13d", seek_cred);
+ print_credit_info("%12d", cred_sz);
+ print_credit_info("%9d", cred_per_msg);
+ print_credit_info("%14d", cred_to_dist);
+ len += scnprintf(buf + len, buf_len - len, "%12d\n",
+ get_queue_depth(&((struct htc_endpoint *)
+ ep_list->htc_rsvd)->txq));
+ }
+
+ if (len > buf_len)
+ len = buf_len;
+
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+ return ret_cnt;
+}
+
+static const struct file_operations fops_credit_dist_stats = {
+ .read = read_file_credit_dist_stats,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static unsigned long ath6kl_get_num_reg(void)
+{
+ int i;
+ unsigned long n_reg = 0;
+
+ for (i = 0; i < ARRAY_SIZE(diag_reg); i++)
+ n_reg = n_reg +
+ (diag_reg[i].reg_end - diag_reg[i].reg_start) / 4 + 1;
+
+ return n_reg;
+}
+
+static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(diag_reg); i++) {
+ if (reg_addr >= diag_reg[i].reg_start &&
+ reg_addr <= diag_reg[i].reg_end)
+ return true;
+ }
+
+ return false;
+}
+
+static ssize_t ath6kl_regread_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ u8 buf[50];
+ unsigned int len = 0;
+
+ if (ar->debug.dbgfs_diag_reg)
+ len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n",
+ ar->debug.dbgfs_diag_reg);
+ else
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "All diag registers\n");
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath6kl_regread_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ u8 buf[50];
+ unsigned int len;
+ unsigned long reg_addr;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+
+ if (strict_strtoul(buf, 0, &reg_addr))
+ return -EINVAL;
+
+ if ((reg_addr % 4) != 0)
+ return -EINVAL;
+
+ if (reg_addr && !ath6kl_dbg_is_diag_reg_valid(reg_addr))
+ return -EINVAL;
+
+ ar->debug.dbgfs_diag_reg = reg_addr;
+
+ return count;
+}
+
+static const struct file_operations fops_diag_reg_read = {
+ .read = ath6kl_regread_read,
+ .write = ath6kl_regread_write,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static int ath6kl_regdump_open(struct inode *inode, struct file *file)
+{
+ struct ath6kl *ar = inode->i_private;
+ u8 *buf;
+ unsigned long int reg_len;
+ unsigned int len = 0, n_reg;
+ u32 addr;
+ __le32 reg_val;
+ int i, status;
+
+ /* Dump all the registers if no register is specified */
+ if (!ar->debug.dbgfs_diag_reg)
+ n_reg = ath6kl_get_num_reg();
+ else
+ n_reg = 1;
+
+ reg_len = n_reg * REG_OUTPUT_LEN_PER_LINE;
+ if (n_reg > 1)
+ reg_len += REGTYPE_STR_LEN;
+
+ buf = vmalloc(reg_len);
+ if (!buf)
+ return -ENOMEM;
+
+ if (n_reg == 1) {
+ addr = ar->debug.dbgfs_diag_reg;
+
+ status = ath6kl_diag_read32(ar,
+ TARG_VTOP(ar->target_type, addr),
+ (u32 *)&reg_val);
+ if (status)
+ goto fail_reg_read;
+
+ len += scnprintf(buf + len, reg_len - len,
+ "0x%06x 0x%08x\n", addr, le32_to_cpu(reg_val));
+ goto done;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(diag_reg); i++) {
+ len += scnprintf(buf + len, reg_len - len,
+ "%s\n", diag_reg[i].reg_info);
+ for (addr = diag_reg[i].reg_start;
+ addr <= diag_reg[i].reg_end; addr += 4) {
+ status = ath6kl_diag_read32(ar,
+ TARG_VTOP(ar->target_type, addr),
+ (u32 *)&reg_val);
+ if (status)
+ goto fail_reg_read;
+
+ len += scnprintf(buf + len, reg_len - len,
+ "0x%06x 0x%08x\n",
+ addr, le32_to_cpu(reg_val));
+ }
+ }
+
+done:
+ file->private_data = buf;
+ return 0;
+
+fail_reg_read:
+ ath6kl_warn("Unable to read memory:%u\n", addr);
+ vfree(buf);
+ return -EIO;
+}
+
+static ssize_t ath6kl_regdump_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ u8 *buf = file->private_data;
+ return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
+}
+
+static int ath6kl_regdump_release(struct inode *inode, struct file *file)
+{
+ vfree(file->private_data);
+ return 0;
+}
+
+static const struct file_operations fops_reg_dump = {
+ .open = ath6kl_regdump_open,
+ .read = ath6kl_regdump_read,
+ .release = ath6kl_regdump_release,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_lrssi_roam_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ unsigned long lrssi_roam_threshold;
+ char buf[32];
+ ssize_t len;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ if (strict_strtoul(buf, 0, &lrssi_roam_threshold))
+ return -EINVAL;
+
+ ar->lrssi_roam_threshold = lrssi_roam_threshold;
+
+ ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold);
+
+ return count;
+}
+
+static ssize_t ath6kl_lrssi_roam_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ char buf[32];
+ unsigned int len;
+
+ len = snprintf(buf, sizeof(buf), "%u\n", ar->lrssi_roam_threshold);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_lrssi_roam_threshold = {
+ .read = ath6kl_lrssi_roam_read,
+ .write = ath6kl_lrssi_roam_write,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_regwrite_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ u8 buf[32];
+ unsigned int len = 0;
+
+ len = scnprintf(buf, sizeof(buf), "Addr: 0x%x Val: 0x%x\n",
+ ar->debug.diag_reg_addr_wr, ar->debug.diag_reg_val_wr);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath6kl_regwrite_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath6kl *ar = file->private_data;
+ char buf[32];
+ char *sptr, *token;
+ unsigned int len = 0;
+ u32 reg_addr, reg_val;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ sptr = buf;
+
+ token = strsep(&sptr, "=");
+ if (!token)
+ return -EINVAL;
+
+ if (kstrtou32(token, 0, &reg_addr))
+ return -EINVAL;
+
+ if (!ath6kl_dbg_is_diag_reg_valid(reg_addr))
+ return -EINVAL;
+
+ if (kstrtou32(sptr, 0, &reg_val))
+ return -EINVAL;
+
+ ar->debug.diag_reg_addr_wr = reg_addr;
+ ar->debug.diag_reg_val_wr = reg_val;
+
+ if (ath6kl_diag_write32(ar, ar->debug.diag_reg_addr_wr,
+ cpu_to_le32(ar->debug.diag_reg_val_wr)))
+ return -EIO;
+
+ return count;
+}
+
+static const struct file_operations fops_diag_reg_write = {
+ .read = ath6kl_regwrite_read,
+ .write = ath6kl_regwrite_write,
+ .open = ath6kl_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+int ath6kl_debug_init(struct ath6kl *ar)
+{
+ ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
+ if (ar->debug.fwlog_buf.buf == NULL)
+ return -ENOMEM;
+
+ ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL);
+ if (ar->debug.fwlog_tmp == NULL) {
+ vfree(ar->debug.fwlog_buf.buf);
+ return -ENOMEM;
+ }
+
+ spin_lock_init(&ar->debug.fwlog_lock);
+
+ /*
+ * Actually we are lying here but don't know how to read the mask
+ * value from the firmware.
+ */
+ ar->debug.fwlog_mask = 0;
+
+ ar->debugfs_phy = debugfs_create_dir("ath6kl",
+ ar->wdev->wiphy->debugfsdir);
+ if (!ar->debugfs_phy) {
+ vfree(ar->debug.fwlog_buf.buf);
+ kfree(ar->debug.fwlog_tmp);
+ return -ENOMEM;
+ }
+
+ debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,
+ &fops_tgt_stats);
+
+ debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
+ &fops_credit_dist_stats);
+
+ debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
+ &fops_fwlog);
+
+ debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy,
+ ar, &fops_fwlog_mask);
+
+ debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar,
+ &fops_diag_reg_read);
+
+ debugfs_create_file("reg_dump", S_IRUSR, ar->debugfs_phy, ar,
+ &fops_reg_dump);
+
+ debugfs_create_file("lrssi_roam_threshold", S_IRUSR | S_IWUSR,
+ ar->debugfs_phy, ar, &fops_lrssi_roam_threshold);
+
+ debugfs_create_file("reg_write", S_IRUSR | S_IWUSR,
+ ar->debugfs_phy, ar, &fops_diag_reg_write);
+
+ debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar,
+ &fops_war_stats);
+
+ return 0;
+}
+
+void ath6kl_debug_cleanup(struct ath6kl *ar)
+{
+ vfree(ar->debug.fwlog_buf.buf);
+ kfree(ar->debug.fwlog_tmp);
+}
+
+#endif
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
new file mode 100644
index 000000000000..7b7675f70a10
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include "htc_hif.h"
+
+enum ATH6K_DEBUG_MASK {
+ ATH6KL_DBG_WLAN_CONNECT = BIT(0), /* wlan connect */
+ ATH6KL_DBG_WLAN_SCAN = BIT(1), /* wlan scan */
+ ATH6KL_DBG_WLAN_TX = BIT(2), /* wlan tx */
+ ATH6KL_DBG_WLAN_RX = BIT(3), /* wlan rx */
+ ATH6KL_DBG_BMI = BIT(4), /* bmi tracing */
+ ATH6KL_DBG_HTC_SEND = BIT(5), /* htc send */
+ ATH6KL_DBG_HTC_RECV = BIT(6), /* htc recv */
+ ATH6KL_DBG_IRQ = BIT(7), /* interrupt processing */
+ ATH6KL_DBG_PM = BIT(8), /* power management */
+ ATH6KL_DBG_WLAN_NODE = BIT(9), /* general wlan node tracing */
+ ATH6KL_DBG_WMI = BIT(10), /* wmi tracing */
+ ATH6KL_DBG_TRC = BIT(11), /* generic func tracing */
+ ATH6KL_DBG_SCATTER = BIT(12), /* hif scatter tracing */
+ ATH6KL_DBG_WLAN_CFG = BIT(13), /* cfg80211 i/f file tracing */
+ ATH6KL_DBG_RAW_BYTES = BIT(14), /* dump tx/rx frames */
+ ATH6KL_DBG_AGGR = BIT(15), /* aggregation */
+ ATH6KL_DBG_SDIO = BIT(16),
+ ATH6KL_DBG_SDIO_DUMP = BIT(17),
+ ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */
+ ATH6KL_DBG_WMI_DUMP = BIT(19),
+ ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */
+};
+
+extern unsigned int debug_mask;
+extern __printf(2, 3)
+int ath6kl_printk(const char *level, const char *fmt, ...);
+
+#define ath6kl_info(fmt, ...) \
+ ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__)
+#define ath6kl_err(fmt, ...) \
+ ath6kl_printk(KERN_ERR, fmt, ##__VA_ARGS__)
+#define ath6kl_warn(fmt, ...) \
+ ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__)
+
+#define AR_DBG_LVL_CHECK(mask) (debug_mask & mask)
+
+enum ath6kl_war {
+ ATH6KL_WAR_INVALID_RATE,
+};
+
+#ifdef CONFIG_ATH6KL_DEBUG
+#define ath6kl_dbg(mask, fmt, ...) \
+ ({ \
+ int rtn; \
+ if (debug_mask & mask) \
+ rtn = ath6kl_printk(KERN_DEBUG, fmt, ##__VA_ARGS__); \
+ else \
+ rtn = 0; \
+ \
+ rtn; \
+ })
+
+static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
+ const char *msg, const char *prefix,
+ const void *buf, size_t len)
+{
+ if (debug_mask & mask) {
+ if (msg)
+ ath6kl_dbg(mask, "%s\n", msg);
+
+ print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
+ }
+}
+
+void ath6kl_dump_registers(struct ath6kl_device *dev,
+ struct ath6kl_irq_proc_registers *irq_proc_reg,
+ struct ath6kl_irq_enable_reg *irq_en_reg);
+void dump_cred_dist_stats(struct htc_target *target);
+void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len);
+void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war);
+int ath6kl_debug_init(struct ath6kl *ar);
+void ath6kl_debug_cleanup(struct ath6kl *ar);
+
+#else
+static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
+ const char *fmt, ...)
+{
+ return 0;
+}
+
+static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
+ const char *msg, const char *prefix,
+ const void *buf, size_t len)
+{
+}
+
+static inline void ath6kl_dump_registers(struct ath6kl_device *dev,
+ struct ath6kl_irq_proc_registers *irq_proc_reg,
+ struct ath6kl_irq_enable_reg *irq_en_reg)
+{
+
+}
+static inline void dump_cred_dist_stats(struct htc_target *target)
+{
+}
+
+static inline void ath6kl_debug_fwlog_event(struct ath6kl *ar,
+ const void *buf, size_t len)
+{
+}
+
+static inline void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
+{
+}
+
+static inline int ath6kl_debug_init(struct ath6kl *ar)
+{
+ return 0;
+}
+
+static inline void ath6kl_debug_cleanup(struct ath6kl *ar)
+{
+}
+
+#endif
+#endif
diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h
new file mode 100644
index 000000000000..d6c898f3d0b3
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HIF_OPS_H
+#define HIF_OPS_H
+
+#include "hif.h"
+
+static inline int hif_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
+ u32 len, u32 request)
+{
+ return ar->hif_ops->read_write_sync(ar, addr, buf, len, request);
+}
+
+static inline int hif_write_async(struct ath6kl *ar, u32 address, u8 *buffer,
+ u32 length, u32 request,
+ struct htc_packet *packet)
+{
+ return ar->hif_ops->write_async(ar, address, buffer, length,
+ request, packet);
+}
+static inline void ath6kl_hif_irq_enable(struct ath6kl *ar)
+{
+ return ar->hif_ops->irq_enable(ar);
+}
+
+static inline void ath6kl_hif_irq_disable(struct ath6kl *ar)
+{
+ return ar->hif_ops->irq_disable(ar);
+}
+
+static inline struct hif_scatter_req *hif_scatter_req_get(struct ath6kl *ar)
+{
+ return ar->hif_ops->scatter_req_get(ar);
+}
+
+static inline void hif_scatter_req_add(struct ath6kl *ar,
+ struct hif_scatter_req *s_req)
+{
+ return ar->hif_ops->scatter_req_add(ar, s_req);
+}
+
+static inline int ath6kl_hif_enable_scatter(struct ath6kl *ar)
+{
+ return ar->hif_ops->enable_scatter(ar);
+}
+
+static inline int ath6kl_hif_scat_req_rw(struct ath6kl *ar,
+ struct hif_scatter_req *scat_req)
+{
+ return ar->hif_ops->scat_req_rw(ar, scat_req);
+}
+
+static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar)
+{
+ return ar->hif_ops->cleanup_scatter(ar);
+}
+
+static inline int ath6kl_hif_suspend(struct ath6kl *ar)
+{
+ return ar->hif_ops->suspend(ar);
+}
+
+#endif
diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h
new file mode 100644
index 000000000000..797e2d1d9bf9
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/hif.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HIF_H
+#define HIF_H
+
+#include "common.h"
+#include "core.h"
+
+#include <linux/scatterlist.h>
+
+#define BUS_REQUEST_MAX_NUM 64
+#define HIF_MBOX_BLOCK_SIZE 128
+#define HIF_MBOX0_BLOCK_SIZE 1
+
+#define HIF_DMA_BUFFER_SIZE (32 * 1024)
+#define CMD53_FIXED_ADDRESS 1
+#define CMD53_INCR_ADDRESS 2
+
+#define MAX_SCATTER_REQUESTS 4
+#define MAX_SCATTER_ENTRIES_PER_REQ 16
+#define MAX_SCATTER_REQ_TRANSFER_SIZE (32 * 1024)
+
+#define MANUFACTURER_ID_AR6003_BASE 0x300
+ /* SDIO manufacturer ID and Codes */
+#define MANUFACTURER_ID_ATH6KL_BASE_MASK 0xFF00
+#define MANUFACTURER_CODE 0x271 /* Atheros */
+
+/* Mailbox address in SDIO address space */
+#define HIF_MBOX_BASE_ADDR 0x800
+#define HIF_MBOX_WIDTH 0x800
+
+#define HIF_MBOX_END_ADDR (HTC_MAILBOX_NUM_MAX * HIF_MBOX_WIDTH - 1)
+
+/* version 1 of the chip has only a 12K extended mbox range */
+#define HIF_MBOX0_EXT_BASE_ADDR 0x4000
+#define HIF_MBOX0_EXT_WIDTH (12*1024)
+
+/* GMBOX addresses */
+#define HIF_GMBOX_BASE_ADDR 0x7000
+#define HIF_GMBOX_WIDTH 0x4000
+
+/* interrupt mode register */
+#define CCCR_SDIO_IRQ_MODE_REG 0xF0
+
+/* mode to enable special 4-bit interrupt assertion without clock */
+#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ (1 << 0)
+
+struct bus_request {
+ struct list_head list;
+
+ /* request data */
+ u32 address;
+
+ u8 *buffer;
+ u32 length;
+ u32 request;
+ struct htc_packet *packet;
+ int status;
+
+ /* this is a scatter request */
+ struct hif_scatter_req *scat_req;
+};
+
+/* direction of transfer (read/write) */
+#define HIF_READ 0x00000001
+#define HIF_WRITE 0x00000002
+#define HIF_DIR_MASK (HIF_READ | HIF_WRITE)
+
+/*
+ * emode - This indicates the whether the command is to be executed in a
+ * blocking or non-blocking fashion (HIF_SYNCHRONOUS/
+ * HIF_ASYNCHRONOUS). The read/write data paths in HTC have been
+ * implemented using the asynchronous mode allowing the the bus
+ * driver to indicate the completion of operation through the
+ * registered callback routine. The requirement primarily comes
+ * from the contexts these operations get called from (a driver's
+ * transmit context or the ISR context in case of receive).
+ * Support for both of these modes is essential.
+ */
+#define HIF_SYNCHRONOUS 0x00000010
+#define HIF_ASYNCHRONOUS 0x00000020
+#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS)
+
+/*
+ * dmode - An interface may support different kinds of commands based on
+ * the tradeoff between the amount of data it can carry and the
+ * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/
+ * HIF_BLOCK_BASIS). In case of latter, the data is rounded off
+ * to the nearest block size by padding. The size of the block is
+ * configurable at compile time using the HIF_BLOCK_SIZE and is
+ * negotiated with the target during initialization after the
+ * ATH6KL interrupts are enabled.
+ */
+#define HIF_BYTE_BASIS 0x00000040
+#define HIF_BLOCK_BASIS 0x00000080
+#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS)
+
+/*
+ * amode - This indicates if the address has to be incremented on ATH6KL
+ * after every read/write operation (HIF?FIXED_ADDRESS/
+ * HIF_INCREMENTAL_ADDRESS).
+ */
+#define HIF_FIXED_ADDRESS 0x00000100
+#define HIF_INCREMENTAL_ADDRESS 0x00000200
+#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS)
+
+#define HIF_WR_ASYNC_BYTE_INC \
+ (HIF_WRITE | HIF_ASYNCHRONOUS | \
+ HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
+
+#define HIF_WR_ASYNC_BLOCK_INC \
+ (HIF_WRITE | HIF_ASYNCHRONOUS | \
+ HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
+
+#define HIF_WR_SYNC_BYTE_FIX \
+ (HIF_WRITE | HIF_SYNCHRONOUS | \
+ HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
+
+#define HIF_WR_SYNC_BYTE_INC \
+ (HIF_WRITE | HIF_SYNCHRONOUS | \
+ HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
+
+#define HIF_WR_SYNC_BLOCK_INC \
+ (HIF_WRITE | HIF_SYNCHRONOUS | \
+ HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
+
+#define HIF_RD_SYNC_BYTE_INC \
+ (HIF_READ | HIF_SYNCHRONOUS | \
+ HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
+
+#define HIF_RD_SYNC_BYTE_FIX \
+ (HIF_READ | HIF_SYNCHRONOUS | \
+ HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
+
+#define HIF_RD_ASYNC_BLOCK_FIX \
+ (HIF_READ | HIF_ASYNCHRONOUS | \
+ HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
+
+#define HIF_RD_SYNC_BLOCK_FIX \
+ (HIF_READ | HIF_SYNCHRONOUS | \
+ HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
+
+struct hif_scatter_item {
+ u8 *buf;
+ int len;
+ struct htc_packet *packet;
+};
+
+struct hif_scatter_req {
+ struct list_head list;
+ /* address for the read/write operation */
+ u32 addr;
+
+ /* request flags */
+ u32 req;
+
+ /* total length of entire transfer */
+ u32 len;
+
+ bool virt_scat;
+
+ void (*complete) (struct htc_target *, struct hif_scatter_req *);
+ int status;
+ int scat_entries;
+
+ struct bus_request *busrequest;
+ struct scatterlist *sgentries;
+
+ /* bounce buffer for upper layers to copy to/from */
+ u8 *virt_dma_buf;
+
+ struct hif_scatter_item scat_list[1];
+};
+
+struct ath6kl_hif_ops {
+ int (*read_write_sync)(struct ath6kl *ar, u32 addr, u8 *buf,
+ u32 len, u32 request);
+ int (*write_async)(struct ath6kl *ar, u32 address, u8 *buffer,
+ u32 length, u32 request, struct htc_packet *packet);
+
+ void (*irq_enable)(struct ath6kl *ar);
+ void (*irq_disable)(struct ath6kl *ar);
+
+ struct hif_scatter_req *(*scatter_req_get)(struct ath6kl *ar);
+ void (*scatter_req_add)(struct ath6kl *ar,
+ struct hif_scatter_req *s_req);
+ int (*enable_scatter)(struct ath6kl *ar);
+ int (*scat_req_rw) (struct ath6kl *ar,
+ struct hif_scatter_req *scat_req);
+ void (*cleanup_scatter)(struct ath6kl *ar);
+ int (*suspend)(struct ath6kl *ar);
+};
+
+#endif
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c
new file mode 100644
index 000000000000..f88a7c9e4148
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/htc.c
@@ -0,0 +1,2478 @@
+/*
+ * Copyright (c) 2007-2011 Atheros Communications 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 "htc_hif.h"
+#include "debug.h"
+#include "hif-ops.h"
+#include <asm/unaligned.h>
+
+#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask))
+
+static void ath6kl_htc_tx_buf_align(u8 **buf, unsigned long len)
+{
+ u8 *align_addr;
+
+ if (!IS_ALIGNED((unsigned long) *buf, 4)) {
+ align_addr = PTR_ALIGN(*buf - 4, 4);
+ memmove(align_addr, *buf, len);
+ *buf = align_addr;
+ }
+}
+
+static void ath6kl_htc_tx_prep_pkt(struct htc_packet *packet, u8 flags,
+ int ctrl0, int ctrl1)
+{
+ struct htc_frame_hdr *hdr;
+
+ packet->buf -= HTC_HDR_LENGTH;
+ hdr = (struct htc_frame_hdr *)packet->buf;
+
+ /* Endianess? */
+ put_unaligned((u16)packet->act_len, &hdr->payld_len);
+ hdr->flags = flags;
+ hdr->eid = packet->endpoint;
+ hdr->ctrl[0] = ctrl0;
+ hdr->ctrl[1] = ctrl1;
+}
+
+static void htc_reclaim_txctrl_buf(struct htc_target *target,
+ struct htc_packet *pkt)
+{
+ spin_lock_bh(&target->htc_lock);
+ list_add_tail(&pkt->list, &target->free_ctrl_txbuf);
+ spin_unlock_bh(&target->htc_lock);
+}
+
+static struct htc_packet *htc_get_control_buf(struct htc_target *target,
+ bool tx)
+{
+ struct htc_packet *packet = NULL;
+ struct list_head *buf_list;
+
+ buf_list = tx ? &target->free_ctrl_txbuf : &target->free_ctrl_rxbuf;
+
+ spin_lock_bh(&target->htc_lock);
+
+ if (list_empty(buf_list)) {
+ spin_unlock_bh(&target->htc_lock);
+ return NULL;
+ }
+
+ packet = list_first_entry(buf_list, struct htc_packet, list);
+ list_del(&packet->list);
+ spin_unlock_bh(&target->htc_lock);
+
+ if (tx)
+ packet->buf = packet->buf_start + HTC_HDR_LENGTH;
+
+ return packet;
+}
+
+static void htc_tx_comp_update(struct htc_target *target,
+ struct htc_endpoint *endpoint,
+ struct htc_packet *packet)
+{
+ packet->completion = NULL;
+ packet->buf += HTC_HDR_LENGTH;
+
+ if (!packet->status)
+ return;
+
+ ath6kl_err("req failed (status:%d, ep:%d, len:%d creds:%d)\n",
+ packet->status, packet->endpoint, packet->act_len,
+ packet->info.tx.cred_used);
+
+ /* on failure to submit, reclaim credits for this packet */
+ spin_lock_bh(&target->tx_lock);
+ endpoint->cred_dist.cred_to_dist +=
+ packet->info.tx.cred_used;
+ endpoint->cred_dist.txq_depth = get_queue_depth(&endpoint->txq);
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
+ target->cred_dist_cntxt, &target->cred_dist_list);
+
+ ath6k_credit_distribute(target->cred_dist_cntxt,
+ &target->cred_dist_list,
+ HTC_CREDIT_DIST_SEND_COMPLETE);
+
+ spin_unlock_bh(&target->tx_lock);
+}
+
+static void htc_tx_complete(struct htc_endpoint *endpoint,
+ struct list_head *txq)
+{
+ if (list_empty(txq))
+ return;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "send complete ep %d, (%d pkts)\n",
+ endpoint->eid, get_queue_depth(txq));
+
+ ath6kl_tx_complete(endpoint->target->dev->ar, txq);
+}
+
+static void htc_tx_comp_handler(struct htc_target *target,
+ struct htc_packet *packet)
+{
+ struct htc_endpoint *endpoint = &target->endpoint[packet->endpoint];
+ struct list_head container;
+
+ htc_tx_comp_update(target, endpoint, packet);
+ INIT_LIST_HEAD(&container);
+ list_add_tail(&packet->list, &container);
+ /* do completion */
+ htc_tx_complete(endpoint, &container);
+}
+
+static void htc_async_tx_scat_complete(struct htc_target *target,
+ struct hif_scatter_req *scat_req)
+{
+ struct htc_endpoint *endpoint;
+ struct htc_packet *packet;
+ struct list_head tx_compq;
+ int i;
+
+ INIT_LIST_HEAD(&tx_compq);
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "htc_async_tx_scat_complete total len: %d entries: %d\n",
+ scat_req->len, scat_req->scat_entries);
+
+ if (scat_req->status)
+ ath6kl_err("send scatter req failed: %d\n", scat_req->status);
+
+ packet = scat_req->scat_list[0].packet;
+ endpoint = &target->endpoint[packet->endpoint];
+
+ /* walk through the scatter list and process */
+ for (i = 0; i < scat_req->scat_entries; i++) {
+ packet = scat_req->scat_list[i].packet;
+ if (!packet) {
+ WARN_ON(1);
+ return;
+ }
+
+ packet->status = scat_req->status;
+ htc_tx_comp_update(target, endpoint, packet);
+ list_add_tail(&packet->list, &tx_compq);
+ }
+
+ /* free scatter request */
+ hif_scatter_req_add(target->dev->ar, scat_req);
+
+ /* complete all packets */
+ htc_tx_complete(endpoint, &tx_compq);
+}
+
+static int ath6kl_htc_tx_issue(struct htc_target *target,
+ struct htc_packet *packet)
+{
+ int status;
+ bool sync = false;
+ u32 padded_len, send_len;
+
+ if (!packet->completion)
+ sync = true;
+
+ send_len = packet->act_len + HTC_HDR_LENGTH;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "%s: transmit len : %d (%s)\n",
+ __func__, send_len, sync ? "sync" : "async");
+
+ padded_len = CALC_TXRX_PADDED_LEN(target, send_len);
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "DevSendPacket, padded len: %d mbox:0x%X (mode:%s)\n",
+ padded_len,
+ target->dev->ar->mbox_info.htc_addr,
+ sync ? "sync" : "async");
+
+ if (sync) {
+ status = hif_read_write_sync(target->dev->ar,
+ target->dev->ar->mbox_info.htc_addr,
+ packet->buf, padded_len,
+ HIF_WR_SYNC_BLOCK_INC);
+
+ packet->status = status;
+ packet->buf += HTC_HDR_LENGTH;
+ } else
+ status = hif_write_async(target->dev->ar,
+ target->dev->ar->mbox_info.htc_addr,
+ packet->buf, padded_len,
+ HIF_WR_ASYNC_BLOCK_INC, packet);
+
+ return status;
+}
+
+static int htc_check_credits(struct htc_target *target,
+ struct htc_endpoint *ep, u8 *flags,
+ enum htc_endpoint_id eid, unsigned int len,
+ int *req_cred)
+{
+
+ *req_cred = (len > target->tgt_cred_sz) ?
+ DIV_ROUND_UP(len, target->tgt_cred_sz) : 1;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "creds required:%d got:%d\n",
+ *req_cred, ep->cred_dist.credits);
+
+ if (ep->cred_dist.credits < *req_cred) {
+ if (eid == ENDPOINT_0)
+ return -EINVAL;
+
+ /* Seek more credits */
+ ep->cred_dist.seek_cred = *req_cred - ep->cred_dist.credits;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
+ target->cred_dist_cntxt, &ep->cred_dist);
+
+ ath6k_seek_credits(target->cred_dist_cntxt, &ep->cred_dist);
+
+ ep->cred_dist.seek_cred = 0;
+
+ if (ep->cred_dist.credits < *req_cred) {
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "not enough credits for ep %d - leaving packet in queue\n",
+ eid);
+ return -EINVAL;
+ }
+ }
+
+ ep->cred_dist.credits -= *req_cred;
+ ep->ep_st.cred_cosumd += *req_cred;
+
+ /* When we are getting low on credits, ask for more */
+ if (ep->cred_dist.credits < ep->cred_dist.cred_per_msg) {
+ ep->cred_dist.seek_cred =
+ ep->cred_dist.cred_per_msg - ep->cred_dist.credits;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
+ target->cred_dist_cntxt, &ep->cred_dist);
+
+ ath6k_seek_credits(target->cred_dist_cntxt, &ep->cred_dist);
+
+ /* see if we were successful in getting more */
+ if (ep->cred_dist.credits < ep->cred_dist.cred_per_msg) {
+ /* tell the target we need credits ASAP! */
+ *flags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
+ ep->ep_st.cred_low_indicate += 1;
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "host needs credits\n");
+ }
+ }
+
+ return 0;
+}
+
+static void ath6kl_htc_tx_pkts_get(struct htc_target *target,
+ struct htc_endpoint *endpoint,
+ struct list_head *queue)
+{
+ int req_cred;
+ u8 flags;
+ struct htc_packet *packet;
+ unsigned int len;
+
+ while (true) {
+
+ flags = 0;
+
+ if (list_empty(&endpoint->txq))
+ break;
+ packet = list_first_entry(&endpoint->txq, struct htc_packet,
+ list);
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "got head pkt:0x%p , queue depth: %d\n",
+ packet, get_queue_depth(&endpoint->txq));
+
+ len = CALC_TXRX_PADDED_LEN(target,
+ packet->act_len + HTC_HDR_LENGTH);
+
+ if (htc_check_credits(target, endpoint, &flags,
+ packet->endpoint, len, &req_cred))
+ break;
+
+ /* now we can fully move onto caller's queue */
+ packet = list_first_entry(&endpoint->txq, struct htc_packet,
+ list);
+ list_move_tail(&packet->list, queue);
+
+ /* save the number of credits this packet consumed */
+ packet->info.tx.cred_used = req_cred;
+
+ /* all TX packets are handled asynchronously */
+ packet->completion = htc_tx_comp_handler;
+ packet->context = target;
+ endpoint->ep_st.tx_issued += 1;
+
+ /* save send flags */
+ packet->info.tx.flags = flags;
+ packet->info.tx.seqno = endpoint->seqno;
+ endpoint->seqno++;
+ }
+}
+
+/* See if the padded tx length falls on a credit boundary */
+static int htc_get_credit_padding(unsigned int cred_sz, int *len,
+ struct htc_endpoint *ep)
+{
+ int rem_cred, cred_pad;
+
+ rem_cred = *len % cred_sz;
+
+ /* No padding needed */
+ if (!rem_cred)
+ return 0;
+
+ if (!(ep->conn_flags & HTC_FLGS_TX_BNDL_PAD_EN))
+ return -1;
+
+ /*
+ * The transfer consumes a "partial" credit, this
+ * packet cannot be bundled unless we add
+ * additional "dummy" padding (max 255 bytes) to
+ * consume the entire credit.
+ */
+ cred_pad = *len < cred_sz ? (cred_sz - *len) : rem_cred;
+
+ if ((cred_pad > 0) && (cred_pad <= 255))
+ *len += cred_pad;
+ else
+ /* The amount of padding is too large, send as non-bundled */
+ return -1;
+
+ return cred_pad;
+}
+
+static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target,
+ struct htc_endpoint *endpoint,
+ struct hif_scatter_req *scat_req,
+ int n_scat,
+ struct list_head *queue)
+{
+ struct htc_packet *packet;
+ int i, len, rem_scat, cred_pad;
+ int status = 0;
+
+ rem_scat = target->max_tx_bndl_sz;
+
+ for (i = 0; i < n_scat; i++) {
+ scat_req->scat_list[i].packet = NULL;
+
+ if (list_empty(queue))
+ break;
+
+ packet = list_first_entry(queue, struct htc_packet, list);
+ len = CALC_TXRX_PADDED_LEN(target,
+ packet->act_len + HTC_HDR_LENGTH);
+
+ cred_pad = htc_get_credit_padding(target->tgt_cred_sz,
+ &len, endpoint);
+ if (cred_pad < 0 || rem_scat < len) {
+ status = -ENOSPC;
+ break;
+ }
+
+ rem_scat -= len;
+ /* now remove it from the queue */
+ list_del(&packet->list);
+
+ scat_req->scat_list[i].packet = packet;
+ /* prepare packet and flag message as part of a send bundle */
+ ath6kl_htc_tx_prep_pkt(packet,
+ packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE,
+ cred_pad, packet->info.tx.seqno);
+ /* Make sure the buffer is 4-byte aligned */
+ ath6kl_htc_tx_buf_align(&packet->buf,
+ packet->act_len + HTC_HDR_LENGTH);
+ scat_req->scat_list[i].buf = packet->buf;
+ scat_req->scat_list[i].len = len;
+
+ scat_req->len += len;
+ scat_req->scat_entries++;
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "%d, adding pkt : 0x%p len:%d (remaining space:%d)\n",
+ i, packet, len, rem_scat);
+ }
+
+ /* Roll back scatter setup in case of any failure */
+ if (scat_req->scat_entries < HTC_MIN_HTC_MSGS_TO_BUNDLE) {
+ for (i = scat_req->scat_entries - 1; i >= 0; i--) {
+ packet = scat_req->scat_list[i].packet;
+ if (packet) {
+ packet->buf += HTC_HDR_LENGTH;
+ list_add(&packet->list, queue);
+ }
+ }
+ return -EAGAIN;
+ }
+
+ return status;
+}
+
+/*
+ * Drain a queue and send as bundles this function may return without fully
+ * draining the queue when
+ *
+ * 1. scatter resources are exhausted
+ * 2. a message that will consume a partial credit will stop the
+ * bundling process early
+ * 3. we drop below the minimum number of messages for a bundle
+ */
+static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
+ struct list_head *queue,
+ int *sent_bundle, int *n_bundle_pkts)
+{
+ struct htc_target *target = endpoint->target;
+ struct hif_scatter_req *scat_req = NULL;
+ int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0;
+ int status;
+
+ while (true) {
+ status = 0;
+ n_scat = get_queue_depth(queue);
+ n_scat = min(n_scat, target->msg_per_bndl_max);
+
+ if (n_scat < HTC_MIN_HTC_MSGS_TO_BUNDLE)
+ /* not enough to bundle */
+ break;
+
+ scat_req = hif_scatter_req_get(target->dev->ar);
+
+ if (!scat_req) {
+ /* no scatter resources */
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "no more scatter resources\n");
+ break;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "pkts to scatter: %d\n",
+ n_scat);
+
+ scat_req->len = 0;
+ scat_req->scat_entries = 0;
+
+ status = ath6kl_htc_tx_setup_scat_list(target, endpoint,
+ scat_req, n_scat,
+ queue);
+ if (status == -EAGAIN) {
+ hif_scatter_req_add(target->dev->ar, scat_req);
+ break;
+ }
+
+ /* send path is always asynchronous */
+ scat_req->complete = htc_async_tx_scat_complete;
+ n_sent_bundle++;
+ tot_pkts_bundle += scat_req->scat_entries;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "send scatter total bytes: %d , entries: %d\n",
+ scat_req->len, scat_req->scat_entries);
+ ath6kldev_submit_scat_req(target->dev, scat_req, false);
+
+ if (status)
+ break;
+ }
+
+ *sent_bundle = n_sent_bundle;
+ *n_bundle_pkts = tot_pkts_bundle;
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "%s (sent:%d)\n",
+ __func__, n_sent_bundle);
+
+ return;
+}
+
+static void ath6kl_htc_tx_from_queue(struct htc_target *target,
+ struct htc_endpoint *endpoint)
+{
+ struct list_head txq;
+ struct htc_packet *packet;
+ int bundle_sent;
+ int n_pkts_bundle;
+
+ spin_lock_bh(&target->tx_lock);
+
+ endpoint->tx_proc_cnt++;
+ if (endpoint->tx_proc_cnt > 1) {
+ endpoint->tx_proc_cnt--;
+ spin_unlock_bh(&target->tx_lock);
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "htc_try_send (busy)\n");
+ return;
+ }
+
+ /*
+ * drain the endpoint TX queue for transmission as long
+ * as we have enough credits.
+ */
+ INIT_LIST_HEAD(&txq);
+
+ while (true) {
+
+ if (list_empty(&endpoint->txq))
+ break;
+
+ ath6kl_htc_tx_pkts_get(target, endpoint, &txq);
+
+ if (list_empty(&txq))
+ break;
+
+ spin_unlock_bh(&target->tx_lock);
+
+ bundle_sent = 0;
+ n_pkts_bundle = 0;
+
+ while (true) {
+ /* try to send a bundle on each pass */
+ if ((target->tx_bndl_enable) &&
+ (get_queue_depth(&txq) >=
+ HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
+ int temp1 = 0, temp2 = 0;
+
+ ath6kl_htc_tx_bundle(endpoint, &txq,
+ &temp1, &temp2);
+ bundle_sent += temp1;
+ n_pkts_bundle += temp2;
+ }
+
+ if (list_empty(&txq))
+ break;
+
+ packet = list_first_entry(&txq, struct htc_packet,
+ list);
+ list_del(&packet->list);
+
+ ath6kl_htc_tx_prep_pkt(packet, packet->info.tx.flags,
+ 0, packet->info.tx.seqno);
+ ath6kl_htc_tx_issue(target, packet);
+ }
+
+ spin_lock_bh(&target->tx_lock);
+
+ endpoint->ep_st.tx_bundles += bundle_sent;
+ endpoint->ep_st.tx_pkt_bundled += n_pkts_bundle;
+ }
+
+ endpoint->tx_proc_cnt = 0;
+ spin_unlock_bh(&target->tx_lock);
+}
+
+static bool ath6kl_htc_tx_try(struct htc_target *target,
+ struct htc_endpoint *endpoint,
+ struct htc_packet *tx_pkt)
+{
+ struct htc_ep_callbacks ep_cb;
+ int txq_depth;
+ bool overflow = false;
+
+ ep_cb = endpoint->ep_cb;
+
+ spin_lock_bh(&target->tx_lock);
+ txq_depth = get_queue_depth(&endpoint->txq);
+ spin_unlock_bh(&target->tx_lock);
+
+ if (txq_depth >= endpoint->max_txq_depth)
+ overflow = true;
+
+ if (overflow)
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "ep %d, tx queue will overflow :%d , tx depth:%d, max:%d\n",
+ endpoint->eid, overflow, txq_depth,
+ endpoint->max_txq_depth);
+
+ if (overflow && ep_cb.tx_full) {
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "indicating overflowed tx packet: 0x%p\n", tx_pkt);
+
+ if (ep_cb.tx_full(endpoint->target, tx_pkt) ==
+ HTC_SEND_FULL_DROP) {
+ endpoint->ep_st.tx_dropped += 1;
+ return false;
+ }
+ }
+
+ spin_lock_bh(&target->tx_lock);
+ list_add_tail(&tx_pkt->list, &endpoint->txq);
+ spin_unlock_bh(&target->tx_lock);
+
+ ath6kl_htc_tx_from_queue(target, endpoint);
+
+ return true;
+}
+
+static void htc_chk_ep_txq(struct htc_target *target)
+{
+ struct htc_endpoint *endpoint;
+ struct htc_endpoint_credit_dist *cred_dist;
+
+ /*
+ * Run through the credit distribution list to see if there are
+ * packets queued. NOTE: no locks need to be taken since the
+ * distribution list is not dynamic (cannot be re-ordered) and we
+ * are not modifying any state.
+ */
+ list_for_each_entry(cred_dist, &target->cred_dist_list, list) {
+ endpoint = (struct htc_endpoint *)cred_dist->htc_rsvd;
+
+ spin_lock_bh(&target->tx_lock);
+ if (!list_empty(&endpoint->txq)) {
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "ep %d has %d credits and %d packets in tx queue\n",
+ cred_dist->endpoint,
+ endpoint->cred_dist.credits,
+ get_queue_depth(&endpoint->txq));
+ spin_unlock_bh(&target->tx_lock);
+ /*
+ * Try to start the stalled queue, this list is
+ * ordered by priority. If there are credits
+ * available the highest priority queue will get a
+ * chance to reclaim credits from lower priority
+ * ones.
+ */
+ ath6kl_htc_tx_from_queue(target, endpoint);
+ spin_lock_bh(&target->tx_lock);
+ }
+ spin_unlock_bh(&target->tx_lock);
+ }
+}
+
+static int htc_setup_tx_complete(struct htc_target *target)
+{
+ struct htc_packet *send_pkt = NULL;
+ int status;
+
+ send_pkt = htc_get_control_buf(target, true);
+
+ if (!send_pkt)
+ return -ENOMEM;
+
+ if (target->htc_tgt_ver >= HTC_VERSION_2P1) {
+ struct htc_setup_comp_ext_msg *setup_comp_ext;
+ u32 flags = 0;
+
+ setup_comp_ext =
+ (struct htc_setup_comp_ext_msg *)send_pkt->buf;
+ memset(setup_comp_ext, 0, sizeof(*setup_comp_ext));
+ setup_comp_ext->msg_id =
+ cpu_to_le16(HTC_MSG_SETUP_COMPLETE_EX_ID);
+
+ if (target->msg_per_bndl_max > 0) {
+ /* Indicate HTC bundling to the target */
+ flags |= HTC_SETUP_COMP_FLG_RX_BNDL_EN;
+ setup_comp_ext->msg_per_rxbndl =
+ target->msg_per_bndl_max;
+ }
+
+ memcpy(&setup_comp_ext->flags, &flags,
+ sizeof(setup_comp_ext->flags));
+ set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp_ext,
+ sizeof(struct htc_setup_comp_ext_msg),
+ ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
+
+ } else {
+ struct htc_setup_comp_msg *setup_comp;
+ setup_comp = (struct htc_setup_comp_msg *)send_pkt->buf;
+ memset(setup_comp, 0, sizeof(struct htc_setup_comp_msg));
+ setup_comp->msg_id = cpu_to_le16(HTC_MSG_SETUP_COMPLETE_ID);
+ set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp,
+ sizeof(struct htc_setup_comp_msg),
+ ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
+ }
+
+ /* we want synchronous operation */
+ send_pkt->completion = NULL;
+ ath6kl_htc_tx_prep_pkt(send_pkt, 0, 0, 0);
+ status = ath6kl_htc_tx_issue(target, send_pkt);
+
+ if (send_pkt != NULL)
+ htc_reclaim_txctrl_buf(target, send_pkt);
+
+ return status;
+}
+
+void ath6kl_htc_set_credit_dist(struct htc_target *target,
+ struct htc_credit_state_info *cred_dist_cntxt,
+ u16 srvc_pri_order[], int list_len)
+{
+ struct htc_endpoint *endpoint;
+ int i, ep;
+
+ target->cred_dist_cntxt = cred_dist_cntxt;
+
+ list_add_tail(&target->endpoint[ENDPOINT_0].cred_dist.list,
+ &target->cred_dist_list);
+
+ for (i = 0; i < list_len; i++) {
+ for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) {
+ endpoint = &target->endpoint[ep];
+ if (endpoint->svc_id == srvc_pri_order[i]) {
+ list_add_tail(&endpoint->cred_dist.list,
+ &target->cred_dist_list);
+ break;
+ }
+ }
+ if (ep >= ENDPOINT_MAX) {
+ WARN_ON(1);
+ return;
+ }
+ }
+}
+
+int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet)
+{
+ struct htc_endpoint *endpoint;
+ struct list_head queue;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "htc_tx: ep id: %d, buf: 0x%p, len: %d\n",
+ packet->endpoint, packet->buf, packet->act_len);
+
+ if (packet->endpoint >= ENDPOINT_MAX) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ endpoint = &target->endpoint[packet->endpoint];
+
+ if (!ath6kl_htc_tx_try(target, endpoint, packet)) {
+ packet->status = (target->htc_flags & HTC_OP_STATE_STOPPING) ?
+ -ECANCELED : -ENOSPC;
+ INIT_LIST_HEAD(&queue);
+ list_add(&packet->list, &queue);
+ htc_tx_complete(endpoint, &queue);
+ }
+
+ return 0;
+}
+
+/* flush endpoint TX queue */
+void ath6kl_htc_flush_txep(struct htc_target *target,
+ enum htc_endpoint_id eid, u16 tag)
+{
+ struct htc_packet *packet, *tmp_pkt;
+ struct list_head discard_q, container;
+ struct htc_endpoint *endpoint = &target->endpoint[eid];
+
+ if (!endpoint->svc_id) {
+ WARN_ON(1);
+ return;
+ }
+
+ /* initialize the discard queue */
+ INIT_LIST_HEAD(&discard_q);
+
+ spin_lock_bh(&target->tx_lock);
+
+ list_for_each_entry_safe(packet, tmp_pkt, &endpoint->txq, list) {
+ if ((tag == HTC_TX_PACKET_TAG_ALL) ||
+ (tag == packet->info.tx.tag))
+ list_move_tail(&packet->list, &discard_q);
+ }
+
+ spin_unlock_bh(&target->tx_lock);
+
+ list_for_each_entry_safe(packet, tmp_pkt, &discard_q, list) {
+ packet->status = -ECANCELED;
+ list_del(&packet->list);
+ ath6kl_dbg(ATH6KL_DBG_TRC,
+ "flushing tx pkt:0x%p, len:%d, ep:%d tag:0x%X\n",
+ packet, packet->act_len,
+ packet->endpoint, packet->info.tx.tag);
+
+ INIT_LIST_HEAD(&container);
+ list_add_tail(&packet->list, &container);
+ htc_tx_complete(endpoint, &container);
+ }
+
+}
+
+static void ath6kl_htc_flush_txep_all(struct htc_target *target)
+{
+ struct htc_endpoint *endpoint;
+ int i;
+
+ dump_cred_dist_stats(target);
+
+ for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
+ endpoint = &target->endpoint[i];
+ if (endpoint->svc_id == 0)
+ /* not in use.. */
+ continue;
+ ath6kl_htc_flush_txep(target, i, HTC_TX_PACKET_TAG_ALL);
+ }
+}
+
+void ath6kl_htc_indicate_activity_change(struct htc_target *target,
+ enum htc_endpoint_id eid, bool active)
+{
+ struct htc_endpoint *endpoint = &target->endpoint[eid];
+ bool dist = false;
+
+ if (endpoint->svc_id == 0) {
+ WARN_ON(1);
+ return;
+ }
+
+ spin_lock_bh(&target->tx_lock);
+
+ if (active) {
+ if (!(endpoint->cred_dist.dist_flags & HTC_EP_ACTIVE)) {
+ endpoint->cred_dist.dist_flags |= HTC_EP_ACTIVE;
+ dist = true;
+ }
+ } else {
+ if (endpoint->cred_dist.dist_flags & HTC_EP_ACTIVE) {
+ endpoint->cred_dist.dist_flags &= ~HTC_EP_ACTIVE;
+ dist = true;
+ }
+ }
+
+ if (dist) {
+ endpoint->cred_dist.txq_depth =
+ get_queue_depth(&endpoint->txq);
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
+ target->cred_dist_cntxt, &target->cred_dist_list);
+
+ ath6k_credit_distribute(target->cred_dist_cntxt,
+ &target->cred_dist_list,
+ HTC_CREDIT_DIST_ACTIVITY_CHANGE);
+ }
+
+ spin_unlock_bh(&target->tx_lock);
+
+ if (dist && !active)
+ htc_chk_ep_txq(target);
+}
+
+/* HTC Rx */
+
+static inline void ath6kl_htc_rx_update_stats(struct htc_endpoint *endpoint,
+ int n_look_ahds)
+{
+ endpoint->ep_st.rx_pkts++;
+ if (n_look_ahds == 1)
+ endpoint->ep_st.rx_lkahds++;
+ else if (n_look_ahds > 1)
+ endpoint->ep_st.rx_bundle_lkahd++;
+}
+
+static inline bool htc_valid_rx_frame_len(struct htc_target *target,
+ enum htc_endpoint_id eid, int len)
+{
+ return (eid == target->dev->ar->ctrl_ep) ?
+ len <= ATH6KL_BUFFER_SIZE : len <= ATH6KL_AMSDU_BUFFER_SIZE;
+}
+
+static int htc_add_rxbuf(struct htc_target *target, struct htc_packet *packet)
+{
+ struct list_head queue;
+
+ INIT_LIST_HEAD(&queue);
+ list_add_tail(&packet->list, &queue);
+ return ath6kl_htc_add_rxbuf_multiple(target, &queue);
+}
+
+static void htc_reclaim_rxbuf(struct htc_target *target,
+ struct htc_packet *packet,
+ struct htc_endpoint *ep)
+{
+ if (packet->info.rx.rx_flags & HTC_RX_PKT_NO_RECYCLE) {
+ htc_rxpkt_reset(packet);
+ packet->status = -ECANCELED;
+ ep->ep_cb.rx(ep->target, packet);
+ } else {
+ htc_rxpkt_reset(packet);
+ htc_add_rxbuf((void *)(target), packet);
+ }
+}
+
+static void reclaim_rx_ctrl_buf(struct htc_target *target,
+ struct htc_packet *packet)
+{
+ spin_lock_bh(&target->htc_lock);
+ list_add_tail(&packet->list, &target->free_ctrl_rxbuf);
+ spin_unlock_bh(&target->htc_lock);
+}
+
+static int ath6kl_htc_rx_packet(struct htc_target *target,
+ struct htc_packet *packet,
+ u32 rx_len)
+{
+ struct ath6kl_device *dev = target->dev;
+ u32 padded_len;
+ int status;
+
+ padded_len = CALC_TXRX_PADDED_LEN(target, rx_len);
+
+ if (padded_len > packet->buf_len) {
+ ath6kl_err("not enough receive space for packet - padlen:%d recvlen:%d bufferlen:%d\n",
+ padded_len, rx_len, packet->buf_len);
+ return -ENOMEM;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "dev_rx_pkt (0x%p : hdr:0x%X) padded len: %d mbox:0x%X (mode:%s)\n",
+ packet, packet->info.rx.exp_hdr,
+ padded_len, dev->ar->mbox_info.htc_addr, "sync");
+
+ status = hif_read_write_sync(dev->ar,
+ dev->ar->mbox_info.htc_addr,
+ packet->buf, padded_len,
+ HIF_RD_SYNC_BLOCK_FIX);
+
+ packet->status = status;
+
+ return status;
+}
+
+/*
+ * optimization for recv packets, we can indicate a
+ * "hint" that there are more single-packets to fetch
+ * on this endpoint.
+ */
+static void ath6kl_htc_rx_set_indicate(u32 lk_ahd,
+ struct htc_endpoint *endpoint,
+ struct htc_packet *packet)
+{
+ struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)&lk_ahd;
+
+ if (htc_hdr->eid == packet->endpoint) {
+ if (!list_empty(&endpoint->rx_bufq))
+ packet->info.rx.indicat_flags |=
+ HTC_RX_FLAGS_INDICATE_MORE_PKTS;
+ }
+}
+
+static void ath6kl_htc_rx_chk_water_mark(struct htc_endpoint *endpoint)
+{
+ struct htc_ep_callbacks ep_cb = endpoint->ep_cb;
+
+ if (ep_cb.rx_refill_thresh > 0) {
+ spin_lock_bh(&endpoint->target->rx_lock);
+ if (get_queue_depth(&endpoint->rx_bufq)
+ < ep_cb.rx_refill_thresh) {
+ spin_unlock_bh(&endpoint->target->rx_lock);
+ ep_cb.rx_refill(endpoint->target, endpoint->eid);
+ return;
+ }
+ spin_unlock_bh(&endpoint->target->rx_lock);
+ }
+}
+
+/* This function is called with rx_lock held */
+static int ath6kl_htc_rx_setup(struct htc_target *target,
+ struct htc_endpoint *ep,
+ u32 *lk_ahds, struct list_head *queue, int n_msg)
+{
+ struct htc_packet *packet;
+ /* FIXME: type of lk_ahds can't be right */
+ struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)lk_ahds;
+ struct htc_ep_callbacks ep_cb;
+ int status = 0, j, full_len;
+ bool no_recycle;
+
+ full_len = CALC_TXRX_PADDED_LEN(target,
+ le16_to_cpu(htc_hdr->payld_len) +
+ sizeof(*htc_hdr));
+
+ if (!htc_valid_rx_frame_len(target, ep->eid, full_len)) {
+ ath6kl_warn("Rx buffer requested with invalid length\n");
+ return -EINVAL;
+ }
+
+ ep_cb = ep->ep_cb;
+ for (j = 0; j < n_msg; j++) {
+
+ /*
+ * Reset flag, any packets allocated using the
+ * rx_alloc() API cannot be recycled on
+ * cleanup,they must be explicitly returned.
+ */
+ no_recycle = false;
+
+ if (ep_cb.rx_allocthresh &&
+ (full_len > ep_cb.rx_alloc_thresh)) {
+ ep->ep_st.rx_alloc_thresh_hit += 1;
+ ep->ep_st.rxalloc_thresh_byte +=
+ le16_to_cpu(htc_hdr->payld_len);
+
+ spin_unlock_bh(&target->rx_lock);
+ no_recycle = true;
+
+ packet = ep_cb.rx_allocthresh(ep->target, ep->eid,
+ full_len);
+ spin_lock_bh(&target->rx_lock);
+ } else {
+ /* refill handler is being used */
+ if (list_empty(&ep->rx_bufq)) {
+ if (ep_cb.rx_refill) {
+ spin_unlock_bh(&target->rx_lock);
+ ep_cb.rx_refill(ep->target, ep->eid);
+ spin_lock_bh(&target->rx_lock);
+ }
+ }
+
+ if (list_empty(&ep->rx_bufq))
+ packet = NULL;
+ else {
+ packet = list_first_entry(&ep->rx_bufq,
+ struct htc_packet, list);
+ list_del(&packet->list);
+ }
+ }
+
+ if (!packet) {
+ target->rx_st_flags |= HTC_RECV_WAIT_BUFFERS;
+ target->ep_waiting = ep->eid;
+ return -ENOSPC;
+ }
+
+ /* clear flags */
+ packet->info.rx.rx_flags = 0;
+ packet->info.rx.indicat_flags = 0;
+ packet->status = 0;
+
+ if (no_recycle)
+ /*
+ * flag that these packets cannot be
+ * recycled, they have to be returned to
+ * the user
+ */
+ packet->info.rx.rx_flags |= HTC_RX_PKT_NO_RECYCLE;
+
+ /* Caller needs to free this upon any failure */
+ list_add_tail(&packet->list, queue);
+
+ if (target->htc_flags & HTC_OP_STATE_STOPPING) {
+ status = -ECANCELED;
+ break;
+ }
+
+ if (j) {
+ packet->info.rx.rx_flags |= HTC_RX_PKT_REFRESH_HDR;
+ packet->info.rx.exp_hdr = 0xFFFFFFFF;
+ } else
+ /* set expected look ahead */
+ packet->info.rx.exp_hdr = *lk_ahds;
+
+ packet->act_len = le16_to_cpu(htc_hdr->payld_len) +
+ HTC_HDR_LENGTH;
+ }
+
+ return status;
+}
+
+static int ath6kl_htc_rx_alloc(struct htc_target *target,
+ u32 lk_ahds[], int msg,
+ struct htc_endpoint *endpoint,
+ struct list_head *queue)
+{
+ int status = 0;
+ struct htc_packet *packet, *tmp_pkt;
+ struct htc_frame_hdr *htc_hdr;
+ int i, n_msg;
+
+ spin_lock_bh(&target->rx_lock);
+
+ for (i = 0; i < msg; i++) {
+
+ htc_hdr = (struct htc_frame_hdr *)&lk_ahds[i];
+
+ if (htc_hdr->eid >= ENDPOINT_MAX) {
+ ath6kl_err("invalid ep in look-ahead: %d\n",
+ htc_hdr->eid);
+ status = -ENOMEM;
+ break;
+ }
+
+ if (htc_hdr->eid != endpoint->eid) {
+ ath6kl_err("invalid ep in look-ahead: %d should be : %d (index:%d)\n",
+ htc_hdr->eid, endpoint->eid, i);
+ status = -ENOMEM;
+ break;
+ }
+
+ if (le16_to_cpu(htc_hdr->payld_len) > HTC_MAX_PAYLOAD_LENGTH) {
+ ath6kl_err("payload len %d exceeds max htc : %d !\n",
+ htc_hdr->payld_len,
+ (u32) HTC_MAX_PAYLOAD_LENGTH);
+ status = -ENOMEM;
+ break;
+ }
+
+ if (endpoint->svc_id == 0) {
+ ath6kl_err("ep %d is not connected !\n", htc_hdr->eid);
+ status = -ENOMEM;
+ break;
+ }
+
+ if (htc_hdr->flags & HTC_FLG_RX_BNDL_CNT) {
+ /*
+ * HTC header indicates that every packet to follow
+ * has the same padded length so that it can be
+ * optimally fetched as a full bundle.
+ */
+ n_msg = (htc_hdr->flags & HTC_FLG_RX_BNDL_CNT) >>
+ HTC_FLG_RX_BNDL_CNT_S;
+
+ /* the count doesn't include the starter frame */
+ n_msg++;
+ if (n_msg > target->msg_per_bndl_max) {
+ status = -ENOMEM;
+ break;
+ }
+
+ endpoint->ep_st.rx_bundle_from_hdr += 1;
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "htc hdr indicates :%d msg can be fetched as a bundle\n",
+ n_msg);
+ } else
+ /* HTC header only indicates 1 message to fetch */
+ n_msg = 1;
+
+ /* Setup packet buffers for each message */
+ status = ath6kl_htc_rx_setup(target, endpoint, &lk_ahds[i],
+ queue, n_msg);
+
+ /*
+ * This is due to unavailabilty of buffers to rx entire data.
+ * Return no error so that free buffers from queue can be used
+ * to receive partial data.
+ */
+ if (status == -ENOSPC) {
+ spin_unlock_bh(&target->rx_lock);
+ return 0;
+ }
+
+ if (status)
+ break;
+ }
+
+ spin_unlock_bh(&target->rx_lock);
+
+ if (status) {
+ list_for_each_entry_safe(packet, tmp_pkt, queue, list) {
+ list_del(&packet->list);
+ htc_reclaim_rxbuf(target, packet,
+ &target->endpoint[packet->endpoint]);
+ }
+ }
+
+ return status;
+}
+
+static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets)
+{
+ if (packets->endpoint != ENDPOINT_0) {
+ WARN_ON(1);
+ return;
+ }
+
+ if (packets->status == -ECANCELED) {
+ reclaim_rx_ctrl_buf(context, packets);
+ return;
+ }
+
+ if (packets->act_len > 0) {
+ ath6kl_err("htc_ctrl_rx, got message with len:%zu\n",
+ packets->act_len + HTC_HDR_LENGTH);
+
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES,
+ "Unexpected ENDPOINT 0 Message", "",
+ packets->buf - HTC_HDR_LENGTH,
+ packets->act_len + HTC_HDR_LENGTH);
+ }
+
+ htc_reclaim_rxbuf(context, packets, &context->endpoint[0]);
+}
+
+static void htc_proc_cred_rpt(struct htc_target *target,
+ struct htc_credit_report *rpt,
+ int n_entries,
+ enum htc_endpoint_id from_ep)
+{
+ struct htc_endpoint *endpoint;
+ int tot_credits = 0, i;
+ bool dist = false;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "htc_proc_cred_rpt, credit report entries:%d\n", n_entries);
+
+ spin_lock_bh(&target->tx_lock);
+
+ for (i = 0; i < n_entries; i++, rpt++) {
+ if (rpt->eid >= ENDPOINT_MAX) {
+ WARN_ON(1);
+ spin_unlock_bh(&target->tx_lock);
+ return;
+ }
+
+ endpoint = &target->endpoint[rpt->eid];
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, " ep %d got %d credits\n",
+ rpt->eid, rpt->credits);
+
+ endpoint->ep_st.tx_cred_rpt += 1;
+ endpoint->ep_st.cred_retnd += rpt->credits;
+
+ if (from_ep == rpt->eid) {
+ /*
+ * This credit report arrived on the same endpoint
+ * indicating it arrived in an RX packet.
+ */
+ endpoint->ep_st.cred_from_rx += rpt->credits;
+ endpoint->ep_st.cred_rpt_from_rx += 1;
+ } else if (from_ep == ENDPOINT_0) {
+ /* credit arrived on endpoint 0 as a NULL message */
+ endpoint->ep_st.cred_from_ep0 += rpt->credits;
+ endpoint->ep_st.cred_rpt_ep0 += 1;
+ } else {
+ endpoint->ep_st.cred_from_other += rpt->credits;
+ endpoint->ep_st.cred_rpt_from_other += 1;
+ }
+
+ if (rpt->eid == ENDPOINT_0)
+ /* always give endpoint 0 credits back */
+ endpoint->cred_dist.credits += rpt->credits;
+ else {
+ endpoint->cred_dist.cred_to_dist += rpt->credits;
+ dist = true;
+ }
+
+ /*
+ * Refresh tx depth for distribution function that will
+ * recover these credits NOTE: this is only valid when
+ * there are credits to recover!
+ */
+ endpoint->cred_dist.txq_depth =
+ get_queue_depth(&endpoint->txq);
+
+ tot_credits += rpt->credits;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
+ "report indicated %d credits to distribute\n",
+ tot_credits);
+
+ if (dist) {
+ /*
+ * This was a credit return based on a completed send
+ * operations note, this is done with the lock held
+ */
+ ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
+ target->cred_dist_cntxt, &target->cred_dist_list);
+
+ ath6k_credit_distribute(target->cred_dist_cntxt,
+ &target->cred_dist_list,
+ HTC_CREDIT_DIST_SEND_COMPLETE);
+ }
+
+ spin_unlock_bh(&target->tx_lock);
+
+ if (tot_credits)
+ htc_chk_ep_txq(target);
+}
+
+static int htc_parse_trailer(struct htc_target *target,
+ struct htc_record_hdr *record,
+ u8 *record_buf, u32 *next_lk_ahds,
+ enum htc_endpoint_id endpoint,
+ int *n_lk_ahds)
+{
+ struct htc_bundle_lkahd_rpt *bundle_lkahd_rpt;
+ struct htc_lookahead_report *lk_ahd;
+ int len;
+
+ switch (record->rec_id) {
+ case HTC_RECORD_CREDITS:
+ len = record->len / sizeof(struct htc_credit_report);
+ if (!len) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ htc_proc_cred_rpt(target,
+ (struct htc_credit_report *) record_buf,
+ len, endpoint);
+ break;
+ case HTC_RECORD_LOOKAHEAD:
+ len = record->len / sizeof(*lk_ahd);
+ if (!len) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ lk_ahd = (struct htc_lookahead_report *) record_buf;
+ if ((lk_ahd->pre_valid == ((~lk_ahd->post_valid) & 0xFF))
+ && next_lk_ahds) {
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "lk_ahd report found (pre valid:0x%X, post valid:0x%X)\n",
+ lk_ahd->pre_valid, lk_ahd->post_valid);
+
+ /* look ahead bytes are valid, copy them over */
+ memcpy((u8 *)&next_lk_ahds[0], lk_ahd->lk_ahd, 4);
+
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Next Look Ahead",
+ "", next_lk_ahds, 4);
+
+ *n_lk_ahds = 1;
+ }
+ break;
+ case HTC_RECORD_LOOKAHEAD_BUNDLE:
+ len = record->len / sizeof(*bundle_lkahd_rpt);
+ if (!len || (len > HTC_HOST_MAX_MSG_PER_BUNDLE)) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ if (next_lk_ahds) {
+ int i;
+
+ bundle_lkahd_rpt =
+ (struct htc_bundle_lkahd_rpt *) record_buf;
+
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Bundle lk_ahd",
+ "", record_buf, record->len);
+
+ for (i = 0; i < len; i++) {
+ memcpy((u8 *)&next_lk_ahds[i],
+ bundle_lkahd_rpt->lk_ahd, 4);
+ bundle_lkahd_rpt++;
+ }
+
+ *n_lk_ahds = i;
+ }
+ break;
+ default:
+ ath6kl_err("unhandled record: id:%d len:%d\n",
+ record->rec_id, record->len);
+ break;
+ }
+
+ return 0;
+
+}
+
+static int htc_proc_trailer(struct htc_target *target,
+ u8 *buf, int len, u32 *next_lk_ahds,
+ int *n_lk_ahds, enum htc_endpoint_id endpoint)
+{
+ struct htc_record_hdr *record;
+ int orig_len;
+ int status;
+ u8 *record_buf;
+ u8 *orig_buf;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "+htc_proc_trailer (len:%d)\n", len);
+
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Recv Trailer", "",
+ buf, len);
+
+ orig_buf = buf;
+ orig_len = len;
+ status = 0;
+
+ while (len > 0) {
+
+ if (len < sizeof(struct htc_record_hdr)) {
+ status = -ENOMEM;
+ break;
+ }
+ /* these are byte aligned structs */
+ record = (struct htc_record_hdr *) buf;
+ len -= sizeof(struct htc_record_hdr);
+ buf += sizeof(struct htc_record_hdr);
+
+ if (record->len > len) {
+ ath6kl_err("invalid record len: %d (id:%d) buf has: %d bytes left\n",
+ record->len, record->rec_id, len);
+ status = -ENOMEM;
+ break;
+ }
+ record_buf = buf;
+
+ status = htc_parse_trailer(target, record, record_buf,
+ next_lk_ahds, endpoint, n_lk_ahds);
+
+ if (status)
+ break;
+
+ /* advance buffer past this record for next time around */
+ buf += record->len;
+ len -= record->len;
+ }
+
+ if (status)
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD Recv Trailer",
+ "", orig_buf, orig_len);
+
+ return status;
+}
+
+static int ath6kl_htc_rx_process_hdr(struct htc_target *target,
+ struct htc_packet *packet,
+ u32 *next_lkahds, int *n_lkahds)
+{
+ int status = 0;
+ u16 payload_len;
+ u32 lk_ahd;
+ struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)packet->buf;
+
+ if (n_lkahds != NULL)
+ *n_lkahds = 0;
+
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "HTC Recv PKT", "htc ",
+ packet->buf, packet->act_len);
+
+ /*
+ * NOTE: we cannot assume the alignment of buf, so we use the safe
+ * macros to retrieve 16 bit fields.
+ */
+ payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len));
+
+ memcpy((u8 *)&lk_ahd, packet->buf, sizeof(lk_ahd));
+
+ if (packet->info.rx.rx_flags & HTC_RX_PKT_REFRESH_HDR) {
+ /*
+ * Refresh the expected header and the actual length as it
+ * was unknown when this packet was grabbed as part of the
+ * bundle.
+ */
+ packet->info.rx.exp_hdr = lk_ahd;
+ packet->act_len = payload_len + HTC_HDR_LENGTH;
+
+ /* validate the actual header that was refreshed */
+ if (packet->act_len > packet->buf_len) {
+ ath6kl_err("refreshed hdr payload len (%d) in bundled recv is invalid (hdr: 0x%X)\n",
+ payload_len, lk_ahd);
+ /*
+ * Limit this to max buffer just to print out some
+ * of the buffer.
+ */
+ packet->act_len = min(packet->act_len, packet->buf_len);
+ status = -ENOMEM;
+ goto fail_rx;
+ }
+
+ if (packet->endpoint != htc_hdr->eid) {
+ ath6kl_err("refreshed hdr ep (%d) does not match expected ep (%d)\n",
+ htc_hdr->eid, packet->endpoint);
+ status = -ENOMEM;
+ goto fail_rx;
+ }
+ }
+
+ if (lk_ahd != packet->info.rx.exp_hdr) {
+ ath6kl_err("%s(): lk_ahd mismatch! (pPkt:0x%p flags:0x%X)\n",
+ __func__, packet, packet->info.rx.rx_flags);
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Expected Message lk_ahd",
+ "", &packet->info.rx.exp_hdr, 4);
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Current Frame Header",
+ "", (u8 *)&lk_ahd, sizeof(lk_ahd));
+ status = -ENOMEM;
+ goto fail_rx;
+ }
+
+ if (htc_hdr->flags & HTC_FLG_RX_TRAILER) {
+ if (htc_hdr->ctrl[0] < sizeof(struct htc_record_hdr) ||
+ htc_hdr->ctrl[0] > payload_len) {
+ ath6kl_err("%s(): invalid hdr (payload len should be :%d, CB[0] is:%d)\n",
+ __func__, payload_len, htc_hdr->ctrl[0]);
+ status = -ENOMEM;
+ goto fail_rx;
+ }
+
+ if (packet->info.rx.rx_flags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
+ next_lkahds = NULL;
+ n_lkahds = NULL;
+ }
+
+ status = htc_proc_trailer(target, packet->buf + HTC_HDR_LENGTH
+ + payload_len - htc_hdr->ctrl[0],
+ htc_hdr->ctrl[0], next_lkahds,
+ n_lkahds, packet->endpoint);
+
+ if (status)
+ goto fail_rx;
+
+ packet->act_len -= htc_hdr->ctrl[0];
+ }
+
+ packet->buf += HTC_HDR_LENGTH;
+ packet->act_len -= HTC_HDR_LENGTH;
+
+fail_rx:
+ if (status)
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD HTC Recv PKT",
+ "", packet->buf,
+ packet->act_len < 256 ? packet->act_len : 256);
+ else {
+ if (packet->act_len > 0)
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES,
+ "HTC - Application Msg", "",
+ packet->buf, packet->act_len);
+ }
+
+ return status;
+}
+
+static void ath6kl_htc_rx_complete(struct htc_endpoint *endpoint,
+ struct htc_packet *packet)
+{
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "htc calling ep %d recv callback on packet 0x%p\n",
+ endpoint->eid, packet);
+ endpoint->ep_cb.rx(endpoint->target, packet);
+}
+
+static int ath6kl_htc_rx_bundle(struct htc_target *target,
+ struct list_head *rxq,
+ struct list_head *sync_compq,
+ int *n_pkt_fetched, bool part_bundle)
+{
+ struct hif_scatter_req *scat_req;
+ struct htc_packet *packet;
+ int rem_space = target->max_rx_bndl_sz;
+ int n_scat_pkt, status = 0, i, len;
+
+ n_scat_pkt = get_queue_depth(rxq);
+ n_scat_pkt = min(n_scat_pkt, target->msg_per_bndl_max);
+
+ if ((get_queue_depth(rxq) - n_scat_pkt) > 0) {
+ /*
+ * We were forced to split this bundle receive operation
+ * all packets in this partial bundle must have their
+ * lookaheads ignored.
+ */
+ part_bundle = true;
+
+ /*
+ * This would only happen if the target ignored our max
+ * bundle limit.
+ */
+ ath6kl_warn("%s(): partial bundle detected num:%d , %d\n",
+ __func__, get_queue_depth(rxq), n_scat_pkt);
+ }
+
+ len = 0;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "%s(): (numpackets: %d , actual : %d)\n",
+ __func__, get_queue_depth(rxq), n_scat_pkt);
+
+ scat_req = hif_scatter_req_get(target->dev->ar);
+
+ if (scat_req == NULL)
+ goto fail_rx_pkt;
+
+ for (i = 0; i < n_scat_pkt; i++) {
+ int pad_len;
+
+ packet = list_first_entry(rxq, struct htc_packet, list);
+ list_del(&packet->list);
+
+ pad_len = CALC_TXRX_PADDED_LEN(target,
+ packet->act_len);
+
+ if ((rem_space - pad_len) < 0) {
+ list_add(&packet->list, rxq);
+ break;
+ }
+
+ rem_space -= pad_len;
+
+ if (part_bundle || (i < (n_scat_pkt - 1)))
+ /*
+ * Packet 0..n-1 cannot be checked for look-aheads
+ * since we are fetching a bundle the last packet
+ * however can have it's lookahead used
+ */
+ packet->info.rx.rx_flags |=
+ HTC_RX_PKT_IGNORE_LOOKAHEAD;
+
+ /* NOTE: 1 HTC packet per scatter entry */
+ scat_req->scat_list[i].buf = packet->buf;
+ scat_req->scat_list[i].len = pad_len;
+
+ packet->info.rx.rx_flags |= HTC_RX_PKT_PART_OF_BUNDLE;
+
+ list_add_tail(&packet->list, sync_compq);
+
+ WARN_ON(!scat_req->scat_list[i].len);
+ len += scat_req->scat_list[i].len;
+ }
+
+ scat_req->len = len;
+ scat_req->scat_entries = i;
+
+ status = ath6kldev_submit_scat_req(target->dev, scat_req, true);
+
+ if (!status)
+ *n_pkt_fetched = i;
+
+ /* free scatter request */
+ hif_scatter_req_add(target->dev->ar, scat_req);
+
+fail_rx_pkt:
+
+ return status;
+}
+
+static int ath6kl_htc_rx_process_packets(struct htc_target *target,
+ struct list_head *comp_pktq,
+ u32 lk_ahds[],
+ int *n_lk_ahd)
+{
+ struct htc_packet *packet, *tmp_pkt;
+ struct htc_endpoint *ep;
+ int status = 0;
+
+ list_for_each_entry_safe(packet, tmp_pkt, comp_pktq, list) {
+ list_del(&packet->list);
+ ep = &target->endpoint[packet->endpoint];
+
+ /* process header for each of the recv packet */
+ status = ath6kl_htc_rx_process_hdr(target, packet, lk_ahds,
+ n_lk_ahd);
+ if (status)
+ return status;
+
+ if (list_empty(comp_pktq)) {
+ /*
+ * Last packet's more packet flag is set
+ * based on the lookahead.
+ */
+ if (*n_lk_ahd > 0)
+ ath6kl_htc_rx_set_indicate(lk_ahds[0],
+ ep, packet);
+ } else
+ /*
+ * Packets in a bundle automatically have
+ * this flag set.
+ */
+ packet->info.rx.indicat_flags |=
+ HTC_RX_FLAGS_INDICATE_MORE_PKTS;
+
+ ath6kl_htc_rx_update_stats(ep, *n_lk_ahd);
+
+ if (packet->info.rx.rx_flags & HTC_RX_PKT_PART_OF_BUNDLE)
+ ep->ep_st.rx_bundl += 1;
+
+ ath6kl_htc_rx_complete(ep, packet);
+ }
+
+ return status;
+}
+
+static int ath6kl_htc_rx_fetch(struct htc_target *target,
+ struct list_head *rx_pktq,
+ struct list_head *comp_pktq)
+{
+ int fetched_pkts;
+ bool part_bundle = false;
+ int status = 0;
+
+ /* now go fetch the list of HTC packets */
+ while (!list_empty(rx_pktq)) {
+ fetched_pkts = 0;
+
+ if (target->rx_bndl_enable && (get_queue_depth(rx_pktq) > 1)) {
+ /*
+ * There are enough packets to attempt a
+ * bundle transfer and recv bundling is
+ * allowed.
+ */
+ status = ath6kl_htc_rx_bundle(target, rx_pktq,
+ comp_pktq,
+ &fetched_pkts,
+ part_bundle);
+ if (status)
+ return status;
+
+ if (!list_empty(rx_pktq))
+ part_bundle = true;
+ }
+
+ if (!fetched_pkts) {
+ struct htc_packet *packet;
+
+ packet = list_first_entry(rx_pktq, struct htc_packet,
+ list);
+
+ list_del(&packet->list);
+
+ /* fully synchronous */
+ packet->completion = NULL;
+
+ if (!list_empty(rx_pktq))
+ /*
+ * look_aheads in all packet
+ * except the last one in the
+ * bundle must be ignored
+ */
+ packet->info.rx.rx_flags |=
+ HTC_RX_PKT_IGNORE_LOOKAHEAD;
+
+ /* go fetch the packet */
+ status = ath6kl_htc_rx_packet(target, packet,
+ packet->act_len);
+ if (status)
+ return status;
+
+ list_add_tail(&packet->list, comp_pktq);
+ }
+ }
+
+ return status;
+}
+
+int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
+ u32 msg_look_ahead[], int *num_pkts)
+{
+ struct htc_packet *packets, *tmp_pkt;
+ struct htc_endpoint *endpoint;
+ struct list_head rx_pktq, comp_pktq;
+ int status = 0;
+ u32 look_aheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
+ int num_look_ahead = 1;
+ enum htc_endpoint_id id;
+ int n_fetched = 0;
+
+ *num_pkts = 0;
+
+ /*
+ * On first entry copy the look_aheads into our temp array for
+ * processing
+ */
+ memcpy(look_aheads, msg_look_ahead, sizeof(look_aheads));
+
+ while (true) {
+
+ /*
+ * First lookahead sets the expected endpoint IDs for all
+ * packets in a bundle.
+ */
+ id = ((struct htc_frame_hdr *)&look_aheads[0])->eid;
+ endpoint = &target->endpoint[id];
+
+ if (id >= ENDPOINT_MAX) {
+ ath6kl_err("MsgPend, invalid endpoint in look-ahead: %d\n",
+ id);
+ status = -ENOMEM;
+ break;
+ }
+
+ INIT_LIST_HEAD(&rx_pktq);
+ INIT_LIST_HEAD(&comp_pktq);
+
+ /*
+ * Try to allocate as many HTC RX packets indicated by the
+ * look_aheads.
+ */
+ status = ath6kl_htc_rx_alloc(target, look_aheads,
+ num_look_ahead, endpoint,
+ &rx_pktq);
+ if (status)
+ break;
+
+ if (get_queue_depth(&rx_pktq) >= 2)
+ /*
+ * A recv bundle was detected, force IRQ status
+ * re-check again
+ */
+ target->chk_irq_status_cnt = 1;
+
+ n_fetched += get_queue_depth(&rx_pktq);
+
+ num_look_ahead = 0;
+
+ status = ath6kl_htc_rx_fetch(target, &rx_pktq, &comp_pktq);
+
+ if (!status)
+ ath6kl_htc_rx_chk_water_mark(endpoint);
+
+ /* Process fetched packets */
+ status = ath6kl_htc_rx_process_packets(target, &comp_pktq,
+ look_aheads,
+ &num_look_ahead);
+
+ if (!num_look_ahead || status)
+ break;
+
+ /*
+ * For SYNCH processing, if we get here, we are running
+ * through the loop again due to a detected lookahead. Set
+ * flag that we should re-check IRQ status registers again
+ * before leaving IRQ processing, this can net better
+ * performance in high throughput situations.
+ */
+ target->chk_irq_status_cnt = 1;
+ }
+
+ if (status) {
+ ath6kl_err("failed to get pending recv messages: %d\n",
+ status);
+ /*
+ * Cleanup any packets we allocated but didn't use to
+ * actually fetch any packets.
+ */
+ list_for_each_entry_safe(packets, tmp_pkt, &rx_pktq, list) {
+ list_del(&packets->list);
+ htc_reclaim_rxbuf(target, packets,
+ &target->endpoint[packets->endpoint]);
+ }
+
+ /* cleanup any packets in sync completion queue */
+ list_for_each_entry_safe(packets, tmp_pkt, &comp_pktq, list) {
+ list_del(&packets->list);
+ htc_reclaim_rxbuf(target, packets,
+ &target->endpoint[packets->endpoint]);
+ }
+
+ if (target->htc_flags & HTC_OP_STATE_STOPPING) {
+ ath6kl_warn("host is going to stop blocking receiver for htc_stop\n");
+ ath6kldev_rx_control(target->dev, false);
+ }
+ }
+
+ /*
+ * Before leaving, check to see if host ran out of buffers and
+ * needs to stop the receiver.
+ */
+ if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) {
+ ath6kl_warn("host has no rx buffers blocking receiver to prevent overrun\n");
+ ath6kldev_rx_control(target->dev, false);
+ }
+ *num_pkts = n_fetched;
+
+ return status;
+}
+
+/*
+ * Synchronously wait for a control message from the target,
+ * This function is used at initialization time ONLY. At init messages
+ * on ENDPOINT 0 are expected.
+ */
+static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
+{
+ struct htc_packet *packet = NULL;
+ struct htc_frame_hdr *htc_hdr;
+ u32 look_ahead;
+
+ if (ath6kldev_poll_mboxmsg_rx(target->dev, &look_ahead,
+ HTC_TARGET_RESPONSE_TIMEOUT))
+ return NULL;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "htc_wait_for_ctrl_msg: look_ahead : 0x%X\n", look_ahead);
+
+ htc_hdr = (struct htc_frame_hdr *)&look_ahead;
+
+ if (htc_hdr->eid != ENDPOINT_0)
+ return NULL;
+
+ packet = htc_get_control_buf(target, false);
+
+ if (!packet)
+ return NULL;
+
+ packet->info.rx.rx_flags = 0;
+ packet->info.rx.exp_hdr = look_ahead;
+ packet->act_len = le16_to_cpu(htc_hdr->payld_len) + HTC_HDR_LENGTH;
+
+ if (packet->act_len > packet->buf_len)
+ goto fail_ctrl_rx;
+
+ /* we want synchronous operation */
+ packet->completion = NULL;
+
+ /* get the message from the device, this will block */
+ if (ath6kl_htc_rx_packet(target, packet, packet->act_len))
+ goto fail_ctrl_rx;
+
+ /* process receive header */
+ packet->status = ath6kl_htc_rx_process_hdr(target, packet, NULL, NULL);
+
+ if (packet->status) {
+ ath6kl_err("htc_wait_for_ctrl_msg, ath6kl_htc_rx_process_hdr failed (status = %d)\n",
+ packet->status);
+ goto fail_ctrl_rx;
+ }
+
+ return packet;
+
+fail_ctrl_rx:
+ if (packet != NULL) {
+ htc_rxpkt_reset(packet);
+ reclaim_rx_ctrl_buf(target, packet);
+ }
+
+ return NULL;
+}
+
+int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
+ struct list_head *pkt_queue)
+{
+ struct htc_endpoint *endpoint;
+ struct htc_packet *first_pkt;
+ bool rx_unblock = false;
+ int status = 0, depth;
+
+ if (list_empty(pkt_queue))
+ return -ENOMEM;
+
+ first_pkt = list_first_entry(pkt_queue, struct htc_packet, list);
+
+ if (first_pkt->endpoint >= ENDPOINT_MAX)
+ return status;
+
+ depth = get_queue_depth(pkt_queue);
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "htc_add_rxbuf_multiple: ep id: %d, cnt:%d, len: %d\n",
+ first_pkt->endpoint, depth, first_pkt->buf_len);
+
+ endpoint = &target->endpoint[first_pkt->endpoint];
+
+ if (target->htc_flags & HTC_OP_STATE_STOPPING) {
+ struct htc_packet *packet, *tmp_pkt;
+
+ /* walk through queue and mark each one canceled */
+ list_for_each_entry_safe(packet, tmp_pkt, pkt_queue, list) {
+ packet->status = -ECANCELED;
+ list_del(&packet->list);
+ ath6kl_htc_rx_complete(endpoint, packet);
+ }
+
+ return status;
+ }
+
+ spin_lock_bh(&target->rx_lock);
+
+ list_splice_tail_init(pkt_queue, &endpoint->rx_bufq);
+
+ /* check if we are blocked waiting for a new buffer */
+ if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) {
+ if (target->ep_waiting == first_pkt->endpoint) {
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "receiver was blocked on ep:%d, unblocking.\n",
+ target->ep_waiting);
+ target->rx_st_flags &= ~HTC_RECV_WAIT_BUFFERS;
+ target->ep_waiting = ENDPOINT_MAX;
+ rx_unblock = true;
+ }
+ }
+
+ spin_unlock_bh(&target->rx_lock);
+
+ if (rx_unblock && !(target->htc_flags & HTC_OP_STATE_STOPPING))
+ /* TODO : implement a buffer threshold count? */
+ ath6kldev_rx_control(target->dev, true);
+
+ return status;
+}
+
+void ath6kl_htc_flush_rx_buf(struct htc_target *target)
+{
+ struct htc_endpoint *endpoint;
+ struct htc_packet *packet, *tmp_pkt;
+ int i;
+
+ for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
+ endpoint = &target->endpoint[i];
+ if (!endpoint->svc_id)
+ /* not in use.. */
+ continue;
+
+ spin_lock_bh(&target->rx_lock);
+ list_for_each_entry_safe(packet, tmp_pkt,
+ &endpoint->rx_bufq, list) {
+ list_del(&packet->list);
+ spin_unlock_bh(&target->rx_lock);
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "flushing rx pkt:0x%p, len:%d, ep:%d\n",
+ packet, packet->buf_len,
+ packet->endpoint);
+ dev_kfree_skb(packet->pkt_cntxt);
+ spin_lock_bh(&target->rx_lock);
+ }
+ spin_unlock_bh(&target->rx_lock);
+ }
+}
+
+int ath6kl_htc_conn_service(struct htc_target *target,
+ struct htc_service_connect_req *conn_req,
+ struct htc_service_connect_resp *conn_resp)
+{
+ struct htc_packet *rx_pkt = NULL;
+ struct htc_packet *tx_pkt = NULL;
+ struct htc_conn_service_resp *resp_msg;
+ struct htc_conn_service_msg *conn_msg;
+ struct htc_endpoint *endpoint;
+ enum htc_endpoint_id assigned_ep = ENDPOINT_MAX;
+ unsigned int max_msg_sz = 0;
+ int status = 0;
+
+ ath6kl_dbg(ATH6KL_DBG_TRC,
+ "htc_conn_service, target:0x%p service id:0x%X\n",
+ target, conn_req->svc_id);
+
+ if (conn_req->svc_id == HTC_CTRL_RSVD_SVC) {
+ /* special case for pseudo control service */
+ assigned_ep = ENDPOINT_0;
+ max_msg_sz = HTC_MAX_CTRL_MSG_LEN;
+ } else {
+ /* allocate a packet to send to the target */
+ tx_pkt = htc_get_control_buf(target, true);
+
+ if (!tx_pkt)
+ return -ENOMEM;
+
+ conn_msg = (struct htc_conn_service_msg *)tx_pkt->buf;
+ memset(conn_msg, 0, sizeof(*conn_msg));
+ conn_msg->msg_id = cpu_to_le16(HTC_MSG_CONN_SVC_ID);
+ conn_msg->svc_id = cpu_to_le16(conn_req->svc_id);
+ conn_msg->conn_flags = cpu_to_le16(conn_req->conn_flags);
+
+ set_htc_pkt_info(tx_pkt, NULL, (u8 *) conn_msg,
+ sizeof(*conn_msg) + conn_msg->svc_meta_len,
+ ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
+
+ /* we want synchronous operation */
+ tx_pkt->completion = NULL;
+ ath6kl_htc_tx_prep_pkt(tx_pkt, 0, 0, 0);
+ status = ath6kl_htc_tx_issue(target, tx_pkt);
+
+ if (status)
+ goto fail_tx;
+
+ /* wait for response */
+ rx_pkt = htc_wait_for_ctrl_msg(target);
+
+ if (!rx_pkt) {
+ status = -ENOMEM;
+ goto fail_tx;
+ }
+
+ resp_msg = (struct htc_conn_service_resp *)rx_pkt->buf;
+
+ if ((le16_to_cpu(resp_msg->msg_id) != HTC_MSG_CONN_SVC_RESP_ID)
+ || (rx_pkt->act_len < sizeof(*resp_msg))) {
+ status = -ENOMEM;
+ goto fail_tx;
+ }
+
+ conn_resp->resp_code = resp_msg->status;
+ /* check response status */
+ if (resp_msg->status != HTC_SERVICE_SUCCESS) {
+ ath6kl_err("target failed service 0x%X connect request (status:%d)\n",
+ resp_msg->svc_id, resp_msg->status);
+ status = -ENOMEM;
+ goto fail_tx;
+ }
+
+ assigned_ep = (enum htc_endpoint_id)resp_msg->eid;
+ max_msg_sz = le16_to_cpu(resp_msg->max_msg_sz);
+ }
+
+ if (assigned_ep >= ENDPOINT_MAX || !max_msg_sz) {
+ status = -ENOMEM;
+ goto fail_tx;
+ }
+
+ endpoint = &target->endpoint[assigned_ep];
+ endpoint->eid = assigned_ep;
+ if (endpoint->svc_id) {
+ status = -ENOMEM;
+ goto fail_tx;
+ }
+
+ /* return assigned endpoint to caller */
+ conn_resp->endpoint = assigned_ep;
+ conn_resp->len_max = max_msg_sz;
+
+ /* setup the endpoint */
+
+ /* this marks the endpoint in use */
+ endpoint->svc_id = conn_req->svc_id;
+
+ endpoint->max_txq_depth = conn_req->max_txq_depth;
+ endpoint->len_max = max_msg_sz;
+ endpoint->ep_cb = conn_req->ep_cb;
+ endpoint->cred_dist.svc_id = conn_req->svc_id;
+ endpoint->cred_dist.htc_rsvd = endpoint;
+ endpoint->cred_dist.endpoint = assigned_ep;
+ endpoint->cred_dist.cred_sz = target->tgt_cred_sz;
+
+ if (conn_req->max_rxmsg_sz) {
+ /*
+ * Override cred_per_msg calculation, this optimizes
+ * the credit-low indications since the host will actually
+ * issue smaller messages in the Send path.
+ */
+ if (conn_req->max_rxmsg_sz > max_msg_sz) {
+ status = -ENOMEM;
+ goto fail_tx;
+ }
+ endpoint->cred_dist.cred_per_msg =
+ conn_req->max_rxmsg_sz / target->tgt_cred_sz;
+ } else
+ endpoint->cred_dist.cred_per_msg =
+ max_msg_sz / target->tgt_cred_sz;
+
+ if (!endpoint->cred_dist.cred_per_msg)
+ endpoint->cred_dist.cred_per_msg = 1;
+
+ /* save local connection flags */
+ endpoint->conn_flags = conn_req->flags;
+
+fail_tx:
+ if (tx_pkt)
+ htc_reclaim_txctrl_buf(target, tx_pkt);
+
+ if (rx_pkt) {
+ htc_rxpkt_reset(rx_pkt);
+ reclaim_rx_ctrl_buf(target, rx_pkt);
+ }
+
+ return status;
+}
+
+static void reset_ep_state(struct htc_target *target)
+{
+ struct htc_endpoint *endpoint;
+ int i;
+
+ for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
+ endpoint = &target->endpoint[i];
+ memset(&endpoint->cred_dist, 0, sizeof(endpoint->cred_dist));
+ endpoint->svc_id = 0;
+ endpoint->len_max = 0;
+ endpoint->max_txq_depth = 0;
+ memset(&endpoint->ep_st, 0,
+ sizeof(endpoint->ep_st));
+ INIT_LIST_HEAD(&endpoint->rx_bufq);
+ INIT_LIST_HEAD(&endpoint->txq);
+ endpoint->target = target;
+ }
+
+ /* reset distribution list */
+ INIT_LIST_HEAD(&target->cred_dist_list);
+}
+
+int ath6kl_htc_get_rxbuf_num(struct htc_target *target,
+ enum htc_endpoint_id endpoint)
+{
+ int num;
+
+ spin_lock_bh(&target->rx_lock);
+ num = get_queue_depth(&(target->endpoint[endpoint].rx_bufq));
+ spin_unlock_bh(&target->rx_lock);
+ return num;
+}
+
+static void htc_setup_msg_bndl(struct htc_target *target)
+{
+ /* limit what HTC can handle */
+ target->msg_per_bndl_max = min(HTC_HOST_MAX_MSG_PER_BUNDLE,
+ target->msg_per_bndl_max);
+
+ if (ath6kl_hif_enable_scatter(target->dev->ar)) {
+ target->msg_per_bndl_max = 0;
+ return;
+ }
+
+ /* limit bundle what the device layer can handle */
+ target->msg_per_bndl_max = min(target->max_scat_entries,
+ target->msg_per_bndl_max);
+
+ ath6kl_dbg(ATH6KL_DBG_TRC,
+ "htc bundling allowed. max msg per htc bundle: %d\n",
+ target->msg_per_bndl_max);
+
+ /* Max rx bundle size is limited by the max tx bundle size */
+ target->max_rx_bndl_sz = target->max_xfer_szper_scatreq;
+ /* Max tx bundle size if limited by the extended mbox address range */
+ target->max_tx_bndl_sz = min(HIF_MBOX0_EXT_WIDTH,
+ target->max_xfer_szper_scatreq);
+
+ ath6kl_dbg(ATH6KL_DBG_ANY, "max recv: %d max send: %d\n",
+ target->max_rx_bndl_sz, target->max_tx_bndl_sz);
+
+ if (target->max_tx_bndl_sz)
+ target->tx_bndl_enable = true;
+
+ if (target->max_rx_bndl_sz)
+ target->rx_bndl_enable = true;
+
+ if ((target->tgt_cred_sz % target->block_sz) != 0) {
+ ath6kl_warn("credit size: %d is not block aligned! Disabling send bundling\n",
+ target->tgt_cred_sz);
+
+ /*
+ * Disallow send bundling since the credit size is
+ * not aligned to a block size the I/O block
+ * padding will spill into the next credit buffer
+ * which is fatal.
+ */
+ target->tx_bndl_enable = false;
+ }
+}
+
+int ath6kl_htc_wait_target(struct htc_target *target)
+{
+ struct htc_packet *packet = NULL;
+ struct htc_ready_ext_msg *rdy_msg;
+ struct htc_service_connect_req connect;
+ struct htc_service_connect_resp resp;
+ int status;
+
+ /* we should be getting 1 control message that the target is ready */
+ packet = htc_wait_for_ctrl_msg(target);
+
+ if (!packet)
+ return -ENOMEM;
+
+ /* we controlled the buffer creation so it's properly aligned */
+ rdy_msg = (struct htc_ready_ext_msg *)packet->buf;
+
+ if ((le16_to_cpu(rdy_msg->ver2_0_info.msg_id) != HTC_MSG_READY_ID) ||
+ (packet->act_len < sizeof(struct htc_ready_msg))) {
+ status = -ENOMEM;
+ goto fail_wait_target;
+ }
+
+ if (!rdy_msg->ver2_0_info.cred_cnt || !rdy_msg->ver2_0_info.cred_sz) {
+ status = -ENOMEM;
+ goto fail_wait_target;
+ }
+
+ target->tgt_creds = le16_to_cpu(rdy_msg->ver2_0_info.cred_cnt);
+ target->tgt_cred_sz = le16_to_cpu(rdy_msg->ver2_0_info.cred_sz);
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "target ready: credits: %d credit size: %d\n",
+ target->tgt_creds, target->tgt_cred_sz);
+
+ /* check if this is an extended ready message */
+ if (packet->act_len >= sizeof(struct htc_ready_ext_msg)) {
+ /* this is an extended message */
+ target->htc_tgt_ver = rdy_msg->htc_ver;
+ target->msg_per_bndl_max = rdy_msg->msg_per_htc_bndl;
+ } else {
+ /* legacy */
+ target->htc_tgt_ver = HTC_VERSION_2P0;
+ target->msg_per_bndl_max = 0;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "using htc protocol version : %s (%d)\n",
+ (target->htc_tgt_ver == HTC_VERSION_2P0) ? "2.0" : ">= 2.1",
+ target->htc_tgt_ver);
+
+ if (target->msg_per_bndl_max > 0)
+ htc_setup_msg_bndl(target);
+
+ /* setup our pseudo HTC control endpoint connection */
+ memset(&connect, 0, sizeof(connect));
+ memset(&resp, 0, sizeof(resp));
+ connect.ep_cb.rx = htc_ctrl_rx;
+ connect.ep_cb.rx_refill = NULL;
+ connect.ep_cb.tx_full = NULL;
+ connect.max_txq_depth = NUM_CONTROL_BUFFERS;
+ connect.svc_id = HTC_CTRL_RSVD_SVC;
+
+ /* connect fake service */
+ status = ath6kl_htc_conn_service((void *)target, &connect, &resp);
+
+ if (status)
+ ath6kl_hif_cleanup_scatter(target->dev->ar);
+
+fail_wait_target:
+ if (packet) {
+ htc_rxpkt_reset(packet);
+ reclaim_rx_ctrl_buf(target, packet);
+ }
+
+ return status;
+}
+
+/*
+ * Start HTC, enable interrupts and let the target know
+ * host has finished setup.
+ */
+int ath6kl_htc_start(struct htc_target *target)
+{
+ struct htc_packet *packet;
+ int status;
+
+ /* Disable interrupts at the chip level */
+ ath6kldev_disable_intrs(target->dev);
+
+ target->htc_flags = 0;
+ target->rx_st_flags = 0;
+
+ /* Push control receive buffers into htc control endpoint */
+ while ((packet = htc_get_control_buf(target, false)) != NULL) {
+ status = htc_add_rxbuf(target, packet);
+ if (status)
+ return status;
+ }
+
+ /* NOTE: the first entry in the distribution list is ENDPOINT_0 */
+ ath6k_credit_init(target->cred_dist_cntxt, &target->cred_dist_list,
+ target->tgt_creds);
+
+ dump_cred_dist_stats(target);
+
+ /* Indicate to the target of the setup completion */
+ status = htc_setup_tx_complete(target);
+
+ if (status)
+ return status;
+
+ /* unmask interrupts */
+ status = ath6kldev_unmask_intrs(target->dev);
+
+ if (status)
+ ath6kl_htc_stop(target);
+
+ return status;
+}
+
+/* htc_stop: stop interrupt reception, and flush all queued buffers */
+void ath6kl_htc_stop(struct htc_target *target)
+{
+ spin_lock_bh(&target->htc_lock);
+ target->htc_flags |= HTC_OP_STATE_STOPPING;
+ spin_unlock_bh(&target->htc_lock);
+
+ /*
+ * Masking interrupts is a synchronous operation, when this
+ * function returns all pending HIF I/O has completed, we can
+ * safely flush the queues.
+ */
+ ath6kldev_mask_intrs(target->dev);
+
+ ath6kl_htc_flush_txep_all(target);
+
+ ath6kl_htc_flush_rx_buf(target);
+
+ reset_ep_state(target);
+}
+
+void *ath6kl_htc_create(struct ath6kl *ar)
+{
+ struct htc_target *target = NULL;
+ struct htc_packet *packet;
+ int status = 0, i = 0;
+ u32 block_size, ctrl_bufsz;
+
+ target = kzalloc(sizeof(*target), GFP_KERNEL);
+ if (!target) {
+ ath6kl_err("unable to allocate memory\n");
+ return NULL;
+ }
+
+ target->dev = kzalloc(sizeof(*target->dev), GFP_KERNEL);
+ if (!target->dev) {
+ ath6kl_err("unable to allocate memory\n");
+ status = -ENOMEM;
+ goto fail_create_htc;
+ }
+
+ spin_lock_init(&target->htc_lock);
+ spin_lock_init(&target->rx_lock);
+ spin_lock_init(&target->tx_lock);
+
+ INIT_LIST_HEAD(&target->free_ctrl_txbuf);
+ INIT_LIST_HEAD(&target->free_ctrl_rxbuf);
+ INIT_LIST_HEAD(&target->cred_dist_list);
+
+ target->dev->ar = ar;
+ target->dev->htc_cnxt = target;
+ target->ep_waiting = ENDPOINT_MAX;
+
+ reset_ep_state(target);
+
+ status = ath6kldev_setup(target->dev);
+
+ if (status)
+ goto fail_create_htc;
+
+ block_size = ar->mbox_info.block_size;
+
+ ctrl_bufsz = (block_size > HTC_MAX_CTRL_MSG_LEN) ?
+ (block_size + HTC_HDR_LENGTH) :
+ (HTC_MAX_CTRL_MSG_LEN + HTC_HDR_LENGTH);
+
+ for (i = 0; i < NUM_CONTROL_BUFFERS; i++) {
+ packet = kzalloc(sizeof(*packet), GFP_KERNEL);
+ if (!packet)
+ break;
+
+ packet->buf_start = kzalloc(ctrl_bufsz, GFP_KERNEL);
+ if (!packet->buf_start) {
+ kfree(packet);
+ break;
+ }
+
+ packet->buf_len = ctrl_bufsz;
+ if (i < NUM_CONTROL_RX_BUFFERS) {
+ packet->act_len = 0;
+ packet->buf = packet->buf_start;
+ packet->endpoint = ENDPOINT_0;
+ list_add_tail(&packet->list, &target->free_ctrl_rxbuf);
+ } else
+ list_add_tail(&packet->list, &target->free_ctrl_txbuf);
+ }
+
+fail_create_htc:
+ if (i != NUM_CONTROL_BUFFERS || status) {
+ if (target) {
+ ath6kl_htc_cleanup(target);
+ target = NULL;
+ }
+ }
+
+ return target;
+}
+
+/* cleanup the HTC instance */
+void ath6kl_htc_cleanup(struct htc_target *target)
+{
+ struct htc_packet *packet, *tmp_packet;
+
+ ath6kl_hif_cleanup_scatter(target->dev->ar);
+
+ list_for_each_entry_safe(packet, tmp_packet,
+ &target->free_ctrl_txbuf, list) {
+ list_del(&packet->list);
+ kfree(packet->buf_start);
+ kfree(packet);
+ }
+
+ list_for_each_entry_safe(packet, tmp_packet,
+ &target->free_ctrl_rxbuf, list) {
+ list_del(&packet->list);
+ kfree(packet->buf_start);
+ kfree(packet);
+ }
+
+ kfree(target->dev);
+ kfree(target);
+}
diff --git a/drivers/net/wireless/ath/ath6kl/htc.h b/drivers/net/wireless/ath/ath6kl/htc.h
new file mode 100644
index 000000000000..8ce0c2c07ded
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/htc.h
@@ -0,0 +1,607 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HTC_H
+#define HTC_H
+
+#include "common.h"
+
+/* frame header flags */
+
+/* send direction */
+#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0)
+#define HTC_FLAGS_SEND_BUNDLE (1 << 1)
+
+/* receive direction */
+#define HTC_FLG_RX_UNUSED (1 << 0)
+#define HTC_FLG_RX_TRAILER (1 << 1)
+/* Bundle count maske and shift */
+#define HTC_FLG_RX_BNDL_CNT (0xF0)
+#define HTC_FLG_RX_BNDL_CNT_S 4
+
+#define HTC_HDR_LENGTH (sizeof(struct htc_frame_hdr))
+#define HTC_MAX_PAYLOAD_LENGTH (4096 - sizeof(struct htc_frame_hdr))
+
+/* HTC control message IDs */
+
+#define HTC_MSG_READY_ID 1
+#define HTC_MSG_CONN_SVC_ID 2
+#define HTC_MSG_CONN_SVC_RESP_ID 3
+#define HTC_MSG_SETUP_COMPLETE_ID 4
+#define HTC_MSG_SETUP_COMPLETE_EX_ID 5
+
+#define HTC_MAX_CTRL_MSG_LEN 256
+
+#define HTC_VERSION_2P0 0x00
+#define HTC_VERSION_2P1 0x01
+
+#define HTC_SERVICE_META_DATA_MAX_LENGTH 128
+
+#define HTC_CONN_FLGS_THRESH_LVL_QUAT 0x0
+#define HTC_CONN_FLGS_THRESH_LVL_HALF 0x1
+#define HTC_CONN_FLGS_THRESH_LVL_THREE_QUAT 0x2
+#define HTC_CONN_FLGS_REDUCE_CRED_DRIB 0x4
+#define HTC_CONN_FLGS_THRESH_MASK 0x3
+
+/* connect response status codes */
+#define HTC_SERVICE_SUCCESS 0
+#define HTC_SERVICE_NOT_FOUND 1
+#define HTC_SERVICE_FAILED 2
+
+/* no resources (i.e. no more endpoints) */
+#define HTC_SERVICE_NO_RESOURCES 3
+
+/* specific service is not allowing any more endpoints */
+#define HTC_SERVICE_NO_MORE_EP 4
+
+/* report record IDs */
+#define HTC_RECORD_NULL 0
+#define HTC_RECORD_CREDITS 1
+#define HTC_RECORD_LOOKAHEAD 2
+#define HTC_RECORD_LOOKAHEAD_BUNDLE 3
+
+#define HTC_SETUP_COMP_FLG_RX_BNDL_EN (1 << 0)
+
+#define MAKE_SERVICE_ID(group, index) \
+ (int)(((int)group << 8) | (int)(index))
+
+/* NOTE: service ID of 0x0000 is reserved and should never be used */
+#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 1)
+#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 0)
+#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 1)
+#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 2)
+#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 3)
+#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4)
+#define WMI_MAX_SERVICES 5
+
+/* reserved and used to flush ALL packets */
+#define HTC_TX_PACKET_TAG_ALL 0
+#define HTC_SERVICE_TX_PACKET_TAG 1
+#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_SERVICE_TX_PACKET_TAG + 9)
+
+/* more packets on this endpoint are being fetched */
+#define HTC_RX_FLAGS_INDICATE_MORE_PKTS (1 << 0)
+
+/* TODO.. for BMI */
+#define ENDPOINT1 0
+/* TODO -remove me, but we have to fix BMI first */
+#define HTC_MAILBOX_NUM_MAX 4
+
+/* enable send bundle padding for this endpoint */
+#define HTC_FLGS_TX_BNDL_PAD_EN (1 << 0)
+#define HTC_EP_ACTIVE ((u32) (1u << 31))
+
+/* HTC operational parameters */
+#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */
+#define HTC_TARGET_DEBUG_INTR_MASK 0x01
+#define HTC_TARGET_CREDIT_INTR_MASK 0xF0
+
+#define HTC_HOST_MAX_MSG_PER_BUNDLE 8
+#define HTC_MIN_HTC_MSGS_TO_BUNDLE 2
+
+/* packet flags */
+
+#define HTC_RX_PKT_IGNORE_LOOKAHEAD (1 << 0)
+#define HTC_RX_PKT_REFRESH_HDR (1 << 1)
+#define HTC_RX_PKT_PART_OF_BUNDLE (1 << 2)
+#define HTC_RX_PKT_NO_RECYCLE (1 << 3)
+
+#define NUM_CONTROL_BUFFERS 8
+#define NUM_CONTROL_TX_BUFFERS 2
+#define NUM_CONTROL_RX_BUFFERS (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS)
+
+#define HTC_RECV_WAIT_BUFFERS (1 << 0)
+#define HTC_OP_STATE_STOPPING (1 << 0)
+
+/*
+ * The frame header length and message formats defined herein were selected
+ * to accommodate optimal alignment for target processing. This reduces
+ * code size and improves performance. Any changes to the header length may
+ * alter the alignment and cause exceptions on the target. When adding to
+ * the messagestructures insure that fields are properly aligned.
+ */
+
+/* HTC frame header
+ *
+ * NOTE: do not remove or re-arrange the fields, these are minimally
+ * required to take advantage of 4-byte lookaheads in some hardware
+ * implementations.
+ */
+struct htc_frame_hdr {
+ u8 eid;
+ u8 flags;
+
+ /* length of data (including trailer) that follows the header */
+ __le16 payld_len;
+
+ /* end of 4-byte lookahead */
+
+ u8 ctrl[2];
+} __packed;
+
+/* HTC ready message */
+struct htc_ready_msg {
+ __le16 msg_id;
+ __le16 cred_cnt;
+ __le16 cred_sz;
+ u8 max_ep;
+ u8 pad;
+} __packed;
+
+/* extended HTC ready message */
+struct htc_ready_ext_msg {
+ struct htc_ready_msg ver2_0_info;
+ u8 htc_ver;
+ u8 msg_per_htc_bndl;
+} __packed;
+
+/* connect service */
+struct htc_conn_service_msg {
+ __le16 msg_id;
+ __le16 svc_id;
+ __le16 conn_flags;
+ u8 svc_meta_len;
+ u8 pad;
+} __packed;
+
+/* connect response */
+struct htc_conn_service_resp {
+ __le16 msg_id;
+ __le16 svc_id;
+ u8 status;
+ u8 eid;
+ __le16 max_msg_sz;
+ u8 svc_meta_len;
+ u8 pad;
+} __packed;
+
+struct htc_setup_comp_msg {
+ __le16 msg_id;
+} __packed;
+
+/* extended setup completion message */
+struct htc_setup_comp_ext_msg {
+ __le16 msg_id;
+ __le32 flags;
+ u8 msg_per_rxbndl;
+ u8 Rsvd[3];
+} __packed;
+
+struct htc_record_hdr {
+ u8 rec_id;
+ u8 len;
+} __packed;
+
+struct htc_credit_report {
+ u8 eid;
+ u8 credits;
+} __packed;
+
+/*
+ * NOTE: The lk_ahd array is guarded by a pre_valid
+ * and Post Valid guard bytes. The pre_valid bytes must
+ * equal the inverse of the post_valid byte.
+ */
+struct htc_lookahead_report {
+ u8 pre_valid;
+ u8 lk_ahd[4];
+ u8 post_valid;
+} __packed;
+
+struct htc_bundle_lkahd_rpt {
+ u8 lk_ahd[4];
+} __packed;
+
+/* Current service IDs */
+
+enum htc_service_grp_ids {
+ RSVD_SERVICE_GROUP = 0,
+ WMI_SERVICE_GROUP = 1,
+
+ HTC_TEST_GROUP = 254,
+ HTC_SERVICE_GROUP_LAST = 255
+};
+
+/* ------ endpoint IDS ------ */
+
+enum htc_endpoint_id {
+ ENDPOINT_UNUSED = -1,
+ ENDPOINT_0 = 0,
+ ENDPOINT_1 = 1,
+ ENDPOINT_2 = 2,
+ ENDPOINT_3,
+ ENDPOINT_4,
+ ENDPOINT_5,
+ ENDPOINT_6,
+ ENDPOINT_7,
+ ENDPOINT_8,
+ ENDPOINT_MAX,
+};
+
+struct htc_tx_packet_info {
+ u16 tag;
+ int cred_used;
+ u8 flags;
+ int seqno;
+};
+
+struct htc_rx_packet_info {
+ u32 exp_hdr;
+ u32 rx_flags;
+ u32 indicat_flags;
+};
+
+struct htc_target;
+
+/* wrapper around endpoint-specific packets */
+struct htc_packet {
+ struct list_head list;
+
+ /* caller's per packet specific context */
+ void *pkt_cntxt;
+
+ /*
+ * the true buffer start , the caller can store the real
+ * buffer start here. In receive callbacks, the HTC layer
+ * sets buf to the start of the payload past the header.
+ * This field allows the caller to reset buf when it recycles
+ * receive packets back to HTC.
+ */
+ u8 *buf_start;
+
+ /*
+ * Pointer to the start of the buffer. In the transmit
+ * direction this points to the start of the payload. In the
+ * receive direction, however, the buffer when queued up
+ * points to the start of the HTC header but when returned
+ * to the caller points to the start of the payload
+ */
+ u8 *buf;
+ u32 buf_len;
+
+ /* actual length of payload */
+ u32 act_len;
+
+ /* endpoint that this packet was sent/recv'd from */
+ enum htc_endpoint_id endpoint;
+
+ /* completion status */
+
+ int status;
+ union {
+ struct htc_tx_packet_info tx;
+ struct htc_rx_packet_info rx;
+ } info;
+
+ void (*completion) (struct htc_target *, struct htc_packet *);
+ struct htc_target *context;
+};
+
+enum htc_send_full_action {
+ HTC_SEND_FULL_KEEP = 0,
+ HTC_SEND_FULL_DROP = 1,
+};
+
+struct htc_ep_callbacks {
+ void (*rx) (struct htc_target *, struct htc_packet *);
+ void (*rx_refill) (struct htc_target *, enum htc_endpoint_id endpoint);
+ enum htc_send_full_action (*tx_full) (struct htc_target *,
+ struct htc_packet *);
+ struct htc_packet *(*rx_allocthresh) (struct htc_target *,
+ enum htc_endpoint_id, int);
+ int rx_alloc_thresh;
+ int rx_refill_thresh;
+};
+
+/* service connection information */
+struct htc_service_connect_req {
+ u16 svc_id;
+ u16 conn_flags;
+ struct htc_ep_callbacks ep_cb;
+ int max_txq_depth;
+ u32 flags;
+ unsigned int max_rxmsg_sz;
+};
+
+/* service connection response information */
+struct htc_service_connect_resp {
+ u8 buf_len;
+ u8 act_len;
+ enum htc_endpoint_id endpoint;
+ unsigned int len_max;
+ u8 resp_code;
+};
+
+/* endpoint distributionstructure */
+struct htc_endpoint_credit_dist {
+ struct list_head list;
+
+ /* Service ID (set by HTC) */
+ u16 svc_id;
+
+ /* endpoint for this distributionstruct (set by HTC) */
+ enum htc_endpoint_id endpoint;
+
+ u32 dist_flags;
+
+ /*
+ * credits for normal operation, anything above this
+ * indicates the endpoint is over-subscribed.
+ */
+ int cred_norm;
+
+ /* floor for credit distribution */
+ int cred_min;
+
+ int cred_assngd;
+
+ /* current credits available */
+ int credits;
+
+ /*
+ * pending credits to distribute on this endpoint, this
+ * is set by HTC when credit reports arrive. The credit
+ * distribution functions sets this to zero when it distributes
+ * the credits.
+ */
+ int cred_to_dist;
+
+ /*
+ * the number of credits that the current pending TX packet needs
+ * to transmit. This is set by HTC when endpoint needs credits in
+ * order to transmit.
+ */
+ int seek_cred;
+
+ /* size in bytes of each credit */
+ int cred_sz;
+
+ /* credits required for a maximum sized messages */
+ int cred_per_msg;
+
+ /* reserved for HTC use */
+ void *htc_rsvd;
+
+ /*
+ * current depth of TX queue , i.e. messages waiting for credits
+ * This field is valid only when HTC_CREDIT_DIST_ACTIVITY_CHANGE
+ * or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint
+ * that has non-zero credits to recover.
+ */
+ int txq_depth;
+};
+
+/*
+ * credit distibution code that is passed into the distrbution function,
+ * there are mandatory and optional codes that must be handled
+ */
+enum htc_credit_dist_reason {
+ HTC_CREDIT_DIST_SEND_COMPLETE = 0,
+ HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1,
+ HTC_CREDIT_DIST_SEEK_CREDITS,
+};
+
+struct htc_credit_state_info {
+ int total_avail_credits;
+ int cur_free_credits;
+ struct list_head lowestpri_ep_dist;
+};
+
+/* endpoint statistics */
+struct htc_endpoint_stats {
+ /*
+ * number of times the host set the credit-low flag in a send
+ * message on this endpoint
+ */
+ u32 cred_low_indicate;
+
+ u32 tx_issued;
+ u32 tx_pkt_bundled;
+ u32 tx_bundles;
+ u32 tx_dropped;
+
+ /* running count of total credit reports received for this endpoint */
+ u32 tx_cred_rpt;
+
+ /* credit reports received from this endpoint's RX packets */
+ u32 cred_rpt_from_rx;
+
+ /* credit reports received from RX packets of other endpoints */
+ u32 cred_rpt_from_other;
+
+ /* credit reports received from endpoint 0 RX packets */
+ u32 cred_rpt_ep0;
+
+ /* count of credits received via Rx packets on this endpoint */
+ u32 cred_from_rx;
+
+ /* count of credits received via another endpoint */
+ u32 cred_from_other;
+
+ /* count of credits received via another endpoint */
+ u32 cred_from_ep0;
+
+ /* count of consummed credits */
+ u32 cred_cosumd;
+
+ /* count of credits returned */
+ u32 cred_retnd;
+
+ u32 rx_pkts;
+
+ /* count of lookahead records found in Rx msg */
+ u32 rx_lkahds;
+
+ /* count of recv packets received in a bundle */
+ u32 rx_bundl;
+
+ /* count of number of bundled lookaheads */
+ u32 rx_bundle_lkahd;
+
+ /* count of the number of bundle indications from the HTC header */
+ u32 rx_bundle_from_hdr;
+
+ /* the number of times the recv allocation threshold was hit */
+ u32 rx_alloc_thresh_hit;
+
+ /* total number of bytes */
+ u32 rxalloc_thresh_byte;
+};
+
+struct htc_endpoint {
+ enum htc_endpoint_id eid;
+ u16 svc_id;
+ struct list_head txq;
+ struct list_head rx_bufq;
+ struct htc_endpoint_credit_dist cred_dist;
+ struct htc_ep_callbacks ep_cb;
+ int max_txq_depth;
+ int len_max;
+ int tx_proc_cnt;
+ int rx_proc_cnt;
+ struct htc_target *target;
+ u8 seqno;
+ u32 conn_flags;
+ struct htc_endpoint_stats ep_st;
+};
+
+struct htc_control_buffer {
+ struct htc_packet packet;
+ u8 *buf;
+};
+
+struct ath6kl_device;
+
+/* our HTC target state */
+struct htc_target {
+ struct htc_endpoint endpoint[ENDPOINT_MAX];
+ struct list_head cred_dist_list;
+ struct list_head free_ctrl_txbuf;
+ struct list_head free_ctrl_rxbuf;
+ struct htc_credit_state_info *cred_dist_cntxt;
+ int tgt_creds;
+ unsigned int tgt_cred_sz;
+ spinlock_t htc_lock;
+ spinlock_t rx_lock;
+ spinlock_t tx_lock;
+ struct ath6kl_device *dev;
+ u32 htc_flags;
+ u32 rx_st_flags;
+ enum htc_endpoint_id ep_waiting;
+ u8 htc_tgt_ver;
+
+ /* max messages per bundle for HTC */
+ int msg_per_bndl_max;
+
+ bool tx_bndl_enable;
+ int rx_bndl_enable;
+ int max_rx_bndl_sz;
+ int max_tx_bndl_sz;
+
+ u32 block_sz;
+ u32 block_mask;
+
+ int max_scat_entries;
+ int max_xfer_szper_scatreq;
+
+ int chk_irq_status_cnt;
+};
+
+void *ath6kl_htc_create(struct ath6kl *ar);
+void ath6kl_htc_set_credit_dist(struct htc_target *target,
+ struct htc_credit_state_info *cred_info,
+ u16 svc_pri_order[], int len);
+int ath6kl_htc_wait_target(struct htc_target *target);
+int ath6kl_htc_start(struct htc_target *target);
+int ath6kl_htc_conn_service(struct htc_target *target,
+ struct htc_service_connect_req *req,
+ struct htc_service_connect_resp *resp);
+int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet);
+void ath6kl_htc_stop(struct htc_target *target);
+void ath6kl_htc_cleanup(struct htc_target *target);
+void ath6kl_htc_flush_txep(struct htc_target *target,
+ enum htc_endpoint_id endpoint, u16 tag);
+void ath6kl_htc_flush_rx_buf(struct htc_target *target);
+void ath6kl_htc_indicate_activity_change(struct htc_target *target,
+ enum htc_endpoint_id endpoint,
+ bool active);
+int ath6kl_htc_get_rxbuf_num(struct htc_target *target,
+ enum htc_endpoint_id endpoint);
+int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
+ struct list_head *pktq);
+int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
+ u32 msg_look_ahead[], int *n_pkts);
+
+static inline void set_htc_pkt_info(struct htc_packet *packet, void *context,
+ u8 *buf, unsigned int len,
+ enum htc_endpoint_id eid, u16 tag)
+{
+ packet->pkt_cntxt = context;
+ packet->buf = buf;
+ packet->act_len = len;
+ packet->endpoint = eid;
+ packet->info.tx.tag = tag;
+}
+
+static inline void htc_rxpkt_reset(struct htc_packet *packet)
+{
+ packet->buf = packet->buf_start;
+ packet->act_len = 0;
+}
+
+static inline void set_htc_rxpkt_info(struct htc_packet *packet, void *context,
+ u8 *buf, unsigned long len,
+ enum htc_endpoint_id eid)
+{
+ packet->pkt_cntxt = context;
+ packet->buf = buf;
+ packet->buf_start = buf;
+ packet->buf_len = len;
+ packet->endpoint = eid;
+}
+
+static inline int get_queue_depth(struct list_head *queue)
+{
+ struct list_head *tmp_list;
+ int depth = 0;
+
+ list_for_each(tmp_list, queue)
+ depth++;
+
+ return depth;
+}
+
+#endif
diff --git a/drivers/net/wireless/ath/ath6kl/htc_hif.c b/drivers/net/wireless/ath/ath6kl/htc_hif.c
new file mode 100644
index 000000000000..86b1cc7409c2
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/htc_hif.c
@@ -0,0 +1,641 @@
+/*
+ * Copyright (c) 2007-2011 Atheros Communications 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 "target.h"
+#include "hif-ops.h"
+#include "htc_hif.h"
+#include "debug.h"
+
+#define MAILBOX_FOR_BLOCK_SIZE 1
+
+#define ATH6KL_TIME_QUANTUM 10 /* in ms */
+
+static int ath6kldev_cp_scat_dma_buf(struct hif_scatter_req *req, bool from_dma)
+{
+ u8 *buf;
+ int i;
+
+ buf = req->virt_dma_buf;
+
+ for (i = 0; i < req->scat_entries; i++) {
+
+ if (from_dma)
+ memcpy(req->scat_list[i].buf, buf,
+ req->scat_list[i].len);
+ else
+ memcpy(buf, req->scat_list[i].buf,
+ req->scat_list[i].len);
+
+ buf += req->scat_list[i].len;
+ }
+
+ return 0;
+}
+
+int ath6kldev_rw_comp_handler(void *context, int status)
+{
+ struct htc_packet *packet = context;
+
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
+ "ath6kldev_rw_comp_handler (pkt:0x%p , status: %d\n",
+ packet, status);
+
+ packet->status = status;
+ packet->completion(packet->context, packet);
+
+ return 0;
+}
+
+static int ath6kldev_proc_dbg_intr(struct ath6kl_device *dev)
+{
+ u32 dummy;
+ int status;
+
+ ath6kl_err("target debug interrupt\n");
+
+ ath6kl_target_failure(dev->ar);
+
+ /*
+ * read counter to clear the interrupt, the debug error interrupt is
+ * counter 0.
+ */
+ status = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS,
+ (u8 *)&dummy, 4, HIF_RD_SYNC_BYTE_INC);
+ if (status)
+ WARN_ON(1);
+
+ return status;
+}
+
+/* mailbox recv message polling */
+int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
+ int timeout)
+{
+ struct ath6kl_irq_proc_registers *rg;
+ int status = 0, i;
+ u8 htc_mbox = 1 << HTC_MAILBOX;
+
+ for (i = timeout / ATH6KL_TIME_QUANTUM; i > 0; i--) {
+ /* this is the standard HIF way, load the reg table */
+ status = hif_read_write_sync(dev->ar, HOST_INT_STATUS_ADDRESS,
+ (u8 *) &dev->irq_proc_reg,
+ sizeof(dev->irq_proc_reg),
+ HIF_RD_SYNC_BYTE_INC);
+
+ if (status) {
+ ath6kl_err("failed to read reg table\n");
+ return status;
+ }
+
+ /* check for MBOX data and valid lookahead */
+ if (dev->irq_proc_reg.host_int_status & htc_mbox) {
+ if (dev->irq_proc_reg.rx_lkahd_valid &
+ htc_mbox) {
+ /*
+ * Mailbox has a message and the look ahead
+ * is valid.
+ */
+ rg = &dev->irq_proc_reg;
+ *lk_ahd =
+ le32_to_cpu(rg->rx_lkahd[HTC_MAILBOX]);
+ break;
+ }
+ }
+
+ /* delay a little */
+ mdelay(ATH6KL_TIME_QUANTUM);
+ ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "retry mbox poll : %d\n", i);
+ }
+
+ if (i == 0) {
+ ath6kl_err("timeout waiting for recv message\n");
+ status = -ETIME;
+ /* check if the target asserted */
+ if (dev->irq_proc_reg.counter_int_status &
+ ATH6KL_TARGET_DEBUG_INTR_MASK)
+ /*
+ * Target failure handler will be called in case of
+ * an assert.
+ */
+ ath6kldev_proc_dbg_intr(dev);
+ }
+
+ return status;
+}
+
+/*
+ * Disable packet reception (used in case the host runs out of buffers)
+ * using the interrupt enable registers through the host I/F
+ */
+int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx)
+{
+ struct ath6kl_irq_enable_reg regs;
+ int status = 0;
+
+ /* take the lock to protect interrupt enable shadows */
+ spin_lock_bh(&dev->lock);
+
+ if (enable_rx)
+ dev->irq_en_reg.int_status_en |=
+ SM(INT_STATUS_ENABLE_MBOX_DATA, 0x01);
+ else
+ dev->irq_en_reg.int_status_en &=
+ ~SM(INT_STATUS_ENABLE_MBOX_DATA, 0x01);
+
+ memcpy(&regs, &dev->irq_en_reg, sizeof(regs));
+
+ spin_unlock_bh(&dev->lock);
+
+ status = hif_read_write_sync(dev->ar, INT_STATUS_ENABLE_ADDRESS,
+ &regs.int_status_en,
+ sizeof(struct ath6kl_irq_enable_reg),
+ HIF_WR_SYNC_BYTE_INC);
+
+ return status;
+}
+
+int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
+ struct hif_scatter_req *scat_req, bool read)
+{
+ int status = 0;
+
+ if (read) {
+ scat_req->req = HIF_RD_SYNC_BLOCK_FIX;
+ scat_req->addr = dev->ar->mbox_info.htc_addr;
+ } else {
+ scat_req->req = HIF_WR_ASYNC_BLOCK_INC;
+
+ scat_req->addr =
+ (scat_req->len > HIF_MBOX_WIDTH) ?
+ dev->ar->mbox_info.htc_ext_addr :
+ dev->ar->mbox_info.htc_addr;
+ }
+
+ ath6kl_dbg((ATH6KL_DBG_HTC_RECV | ATH6KL_DBG_HTC_SEND),
+ "ath6kldev_submit_scat_req, entries: %d, total len: %d mbox:0x%X (mode: %s : %s)\n",
+ scat_req->scat_entries, scat_req->len,
+ scat_req->addr, !read ? "async" : "sync",
+ (read) ? "rd" : "wr");
+
+ if (!read && scat_req->virt_scat) {
+ status = ath6kldev_cp_scat_dma_buf(scat_req, false);
+ if (status) {
+ scat_req->status = status;
+ scat_req->complete(dev->ar->htc_target, scat_req);
+ return 0;
+ }
+ }
+
+ status = ath6kl_hif_scat_req_rw(dev->ar, scat_req);
+
+ if (read) {
+ /* in sync mode, we can touch the scatter request */
+ scat_req->status = status;
+ if (!status && scat_req->virt_scat)
+ scat_req->status =
+ ath6kldev_cp_scat_dma_buf(scat_req, true);
+ }
+
+ return status;
+}
+
+static int ath6kldev_proc_counter_intr(struct ath6kl_device *dev)
+{
+ u8 counter_int_status;
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ, "counter interrupt\n");
+
+ counter_int_status = dev->irq_proc_reg.counter_int_status &
+ dev->irq_en_reg.cntr_int_status_en;
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ,
+ "valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n",
+ counter_int_status);
+
+ /*
+ * NOTE: other modules like GMBOX may use the counter interrupt for
+ * credit flow control on other counters, we only need to check for
+ * the debug assertion counter interrupt.
+ */
+ if (counter_int_status & ATH6KL_TARGET_DEBUG_INTR_MASK)
+ return ath6kldev_proc_dbg_intr(dev);
+
+ return 0;
+}
+
+static int ath6kldev_proc_err_intr(struct ath6kl_device *dev)
+{
+ int status;
+ u8 error_int_status;
+ u8 reg_buf[4];
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ, "error interrupt\n");
+
+ error_int_status = dev->irq_proc_reg.error_int_status & 0x0F;
+ if (!error_int_status) {
+ WARN_ON(1);
+ return -EIO;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ,
+ "valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n",
+ error_int_status);
+
+ if (MS(ERROR_INT_STATUS_WAKEUP, error_int_status))
+ ath6kl_dbg(ATH6KL_DBG_IRQ, "error : wakeup\n");
+
+ if (MS(ERROR_INT_STATUS_RX_UNDERFLOW, error_int_status))
+ ath6kl_err("rx underflow\n");
+
+ if (MS(ERROR_INT_STATUS_TX_OVERFLOW, error_int_status))
+ ath6kl_err("tx overflow\n");
+
+ /* Clear the interrupt */
+ dev->irq_proc_reg.error_int_status &= ~error_int_status;
+
+ /* set W1C value to clear the interrupt, this hits the register first */
+ reg_buf[0] = error_int_status;
+ reg_buf[1] = 0;
+ reg_buf[2] = 0;
+ reg_buf[3] = 0;
+
+ status = hif_read_write_sync(dev->ar, ERROR_INT_STATUS_ADDRESS,
+ reg_buf, 4, HIF_WR_SYNC_BYTE_FIX);
+
+ if (status)
+ WARN_ON(1);
+
+ return status;
+}
+
+static int ath6kldev_proc_cpu_intr(struct ath6kl_device *dev)
+{
+ int status;
+ u8 cpu_int_status;
+ u8 reg_buf[4];
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ, "cpu interrupt\n");
+
+ cpu_int_status = dev->irq_proc_reg.cpu_int_status &
+ dev->irq_en_reg.cpu_int_status_en;
+ if (!cpu_int_status) {
+ WARN_ON(1);
+ return -EIO;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ,
+ "valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n",
+ cpu_int_status);
+
+ /* Clear the interrupt */
+ dev->irq_proc_reg.cpu_int_status &= ~cpu_int_status;
+
+ /*
+ * Set up the register transfer buffer to hit the register 4 times ,
+ * this is done to make the access 4-byte aligned to mitigate issues
+ * with host bus interconnects that restrict bus transfer lengths to
+ * be a multiple of 4-bytes.
+ */
+
+ /* set W1C value to clear the interrupt, this hits the register first */
+ reg_buf[0] = cpu_int_status;
+ /* the remaining are set to zero which have no-effect */
+ reg_buf[1] = 0;
+ reg_buf[2] = 0;
+ reg_buf[3] = 0;
+
+ status = hif_read_write_sync(dev->ar, CPU_INT_STATUS_ADDRESS,
+ reg_buf, 4, HIF_WR_SYNC_BYTE_FIX);
+
+ if (status)
+ WARN_ON(1);
+
+ return status;
+}
+
+/* process pending interrupts synchronously */
+static int proc_pending_irqs(struct ath6kl_device *dev, bool *done)
+{
+ struct ath6kl_irq_proc_registers *rg;
+ int status = 0;
+ u8 host_int_status = 0;
+ u32 lk_ahd = 0;
+ u8 htc_mbox = 1 << HTC_MAILBOX;
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ, "proc_pending_irqs: (dev: 0x%p)\n", dev);
+
+ /*
+ * NOTE: HIF implementation guarantees that the context of this
+ * call allows us to perform SYNCHRONOUS I/O, that is we can block,
+ * sleep or call any API that can block or switch thread/task
+ * contexts. This is a fully schedulable context.
+ */
+
+ /*
+ * Process pending intr only when int_status_en is clear, it may
+ * result in unnecessary bus transaction otherwise. Target may be
+ * unresponsive at the time.
+ */
+ if (dev->irq_en_reg.int_status_en) {
+ /*
+ * Read the first 28 bytes of the HTC register table. This
+ * will yield us the value of different int status
+ * registers and the lookahead registers.
+ *
+ * length = sizeof(int_status) + sizeof(cpu_int_status)
+ * + sizeof(error_int_status) +
+ * sizeof(counter_int_status) +
+ * sizeof(mbox_frame) + sizeof(rx_lkahd_valid)
+ * + sizeof(hole) + sizeof(rx_lkahd) +
+ * sizeof(int_status_en) +
+ * sizeof(cpu_int_status_en) +
+ * sizeof(err_int_status_en) +
+ * sizeof(cntr_int_status_en);
+ */
+ status = hif_read_write_sync(dev->ar, HOST_INT_STATUS_ADDRESS,
+ (u8 *) &dev->irq_proc_reg,
+ sizeof(dev->irq_proc_reg),
+ HIF_RD_SYNC_BYTE_INC);
+ if (status)
+ goto out;
+
+ if (AR_DBG_LVL_CHECK(ATH6KL_DBG_IRQ))
+ ath6kl_dump_registers(dev, &dev->irq_proc_reg,
+ &dev->irq_en_reg);
+
+ /* Update only those registers that are enabled */
+ host_int_status = dev->irq_proc_reg.host_int_status &
+ dev->irq_en_reg.int_status_en;
+
+ /* Look at mbox status */
+ if (host_int_status & htc_mbox) {
+ /*
+ * Mask out pending mbox value, we use "lookAhead as
+ * the real flag for mbox processing.
+ */
+ host_int_status &= ~htc_mbox;
+ if (dev->irq_proc_reg.rx_lkahd_valid &
+ htc_mbox) {
+ rg = &dev->irq_proc_reg;
+ lk_ahd = le32_to_cpu(rg->rx_lkahd[HTC_MAILBOX]);
+ if (!lk_ahd)
+ ath6kl_err("lookAhead is zero!\n");
+ }
+ }
+ }
+
+ if (!host_int_status && !lk_ahd) {
+ *done = true;
+ goto out;
+ }
+
+ if (lk_ahd) {
+ int fetched = 0;
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ,
+ "pending mailbox msg, lk_ahd: 0x%X\n", lk_ahd);
+ /*
+ * Mailbox Interrupt, the HTC layer may issue async
+ * requests to empty the mailbox. When emptying the recv
+ * mailbox we use the async handler above called from the
+ * completion routine of the callers read request. This can
+ * improve performance by reducing context switching when
+ * we rapidly pull packets.
+ */
+ status = ath6kl_htc_rxmsg_pending_handler(dev->htc_cnxt,
+ &lk_ahd, &fetched);
+ if (status)
+ goto out;
+
+ if (!fetched)
+ /*
+ * HTC could not pull any messages out due to lack
+ * of resources.
+ */
+ dev->htc_cnxt->chk_irq_status_cnt = 0;
+ }
+
+ /* now handle the rest of them */
+ ath6kl_dbg(ATH6KL_DBG_IRQ,
+ "valid interrupt source(s) for other interrupts: 0x%x\n",
+ host_int_status);
+
+ if (MS(HOST_INT_STATUS_CPU, host_int_status)) {
+ /* CPU Interrupt */
+ status = ath6kldev_proc_cpu_intr(dev);
+ if (status)
+ goto out;
+ }
+
+ if (MS(HOST_INT_STATUS_ERROR, host_int_status)) {
+ /* Error Interrupt */
+ status = ath6kldev_proc_err_intr(dev);
+ if (status)
+ goto out;
+ }
+
+ if (MS(HOST_INT_STATUS_COUNTER, host_int_status))
+ /* Counter Interrupt */
+ status = ath6kldev_proc_counter_intr(dev);
+
+out:
+ /*
+ * An optimization to bypass reading the IRQ status registers
+ * unecessarily which can re-wake the target, if upper layers
+ * determine that we are in a low-throughput mode, we can rely on
+ * taking another interrupt rather than re-checking the status
+ * registers which can re-wake the target.
+ *
+ * NOTE : for host interfaces that makes use of detecting pending
+ * mbox messages at hif can not use this optimization due to
+ * possible side effects, SPI requires the host to drain all
+ * messages from the mailbox before exiting the ISR routine.
+ */
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ,
+ "bypassing irq status re-check, forcing done\n");
+
+ if (!dev->htc_cnxt->chk_irq_status_cnt)
+ *done = true;
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ,
+ "proc_pending_irqs: (done:%d, status=%d\n", *done, status);
+
+ return status;
+}
+
+/* interrupt handler, kicks off all interrupt processing */
+int ath6kldev_intr_bh_handler(struct ath6kl *ar)
+{
+ struct ath6kl_device *dev = ar->htc_target->dev;
+ int status = 0;
+ bool done = false;
+
+ /*
+ * Reset counter used to flag a re-scan of IRQ status registers on
+ * the target.
+ */
+ dev->htc_cnxt->chk_irq_status_cnt = 0;
+
+ /*
+ * IRQ processing is synchronous, interrupt status registers can be
+ * re-read.
+ */
+ while (!done) {
+ status = proc_pending_irqs(dev, &done);
+ if (status)
+ break;
+ }
+
+ return status;
+}
+
+static int ath6kldev_enable_intrs(struct ath6kl_device *dev)
+{
+ struct ath6kl_irq_enable_reg regs;
+ int status;
+
+ spin_lock_bh(&dev->lock);
+
+ /* Enable all but ATH6KL CPU interrupts */
+ dev->irq_en_reg.int_status_en =
+ SM(INT_STATUS_ENABLE_ERROR, 0x01) |
+ SM(INT_STATUS_ENABLE_CPU, 0x01) |
+ SM(INT_STATUS_ENABLE_COUNTER, 0x01);
+
+ /*
+ * NOTE: There are some cases where HIF can do detection of
+ * pending mbox messages which is disabled now.
+ */
+ dev->irq_en_reg.int_status_en |= SM(INT_STATUS_ENABLE_MBOX_DATA, 0x01);
+
+ /* Set up the CPU Interrupt status Register */
+ dev->irq_en_reg.cpu_int_status_en = 0;
+
+ /* Set up the Error Interrupt status Register */
+ dev->irq_en_reg.err_int_status_en =
+ SM(ERROR_STATUS_ENABLE_RX_UNDERFLOW, 0x01) |
+ SM(ERROR_STATUS_ENABLE_TX_OVERFLOW, 0x1);
+
+ /*
+ * Enable Counter interrupt status register to get fatal errors for
+ * debugging.
+ */
+ dev->irq_en_reg.cntr_int_status_en = SM(COUNTER_INT_STATUS_ENABLE_BIT,
+ ATH6KL_TARGET_DEBUG_INTR_MASK);
+ memcpy(&regs, &dev->irq_en_reg, sizeof(regs));
+
+ spin_unlock_bh(&dev->lock);
+
+ status = hif_read_write_sync(dev->ar, INT_STATUS_ENABLE_ADDRESS,
+ &regs.int_status_en, sizeof(regs),
+ HIF_WR_SYNC_BYTE_INC);
+
+ if (status)
+ ath6kl_err("failed to update interrupt ctl reg err: %d\n",
+ status);
+
+ return status;
+}
+
+int ath6kldev_disable_intrs(struct ath6kl_device *dev)
+{
+ struct ath6kl_irq_enable_reg regs;
+
+ spin_lock_bh(&dev->lock);
+ /* Disable all interrupts */
+ dev->irq_en_reg.int_status_en = 0;
+ dev->irq_en_reg.cpu_int_status_en = 0;
+ dev->irq_en_reg.err_int_status_en = 0;
+ dev->irq_en_reg.cntr_int_status_en = 0;
+ memcpy(&regs, &dev->irq_en_reg, sizeof(regs));
+ spin_unlock_bh(&dev->lock);
+
+ return hif_read_write_sync(dev->ar, INT_STATUS_ENABLE_ADDRESS,
+ &regs.int_status_en, sizeof(regs),
+ HIF_WR_SYNC_BYTE_INC);
+}
+
+/* enable device interrupts */
+int ath6kldev_unmask_intrs(struct ath6kl_device *dev)
+{
+ int status = 0;
+
+ /*
+ * Make sure interrupt are disabled before unmasking at the HIF
+ * layer. The rationale here is that between device insertion
+ * (where we clear the interrupts the first time) and when HTC
+ * is finally ready to handle interrupts, other software can perform
+ * target "soft" resets. The ATH6KL interrupt enables reset back to an
+ * "enabled" state when this happens.
+ */
+ ath6kldev_disable_intrs(dev);
+
+ /* unmask the host controller interrupts */
+ ath6kl_hif_irq_enable(dev->ar);
+ status = ath6kldev_enable_intrs(dev);
+
+ return status;
+}
+
+/* disable all device interrupts */
+int ath6kldev_mask_intrs(struct ath6kl_device *dev)
+{
+ /*
+ * Mask the interrupt at the HIF layer to avoid any stray interrupt
+ * taken while we zero out our shadow registers in
+ * ath6kldev_disable_intrs().
+ */
+ ath6kl_hif_irq_disable(dev->ar);
+
+ return ath6kldev_disable_intrs(dev);
+}
+
+int ath6kldev_setup(struct ath6kl_device *dev)
+{
+ int status = 0;
+
+ spin_lock_init(&dev->lock);
+
+ /*
+ * NOTE: we actually get the block size of a mailbox other than 0,
+ * for SDIO the block size on mailbox 0 is artificially set to 1.
+ * So we use the block size that is set for the other 3 mailboxes.
+ */
+ dev->htc_cnxt->block_sz = dev->ar->mbox_info.block_size;
+
+ /* must be a power of 2 */
+ if ((dev->htc_cnxt->block_sz & (dev->htc_cnxt->block_sz - 1)) != 0) {
+ WARN_ON(1);
+ goto fail_setup;
+ }
+
+ /* assemble mask, used for padding to a block */
+ dev->htc_cnxt->block_mask = dev->htc_cnxt->block_sz - 1;
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "block size: %d, mbox addr:0x%X\n",
+ dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr);
+
+ ath6kl_dbg(ATH6KL_DBG_TRC,
+ "hif interrupt processing is sync only\n");
+
+ status = ath6kldev_disable_intrs(dev);
+
+fail_setup:
+ return status;
+
+}
diff --git a/drivers/net/wireless/ath/ath6kl/htc_hif.h b/drivers/net/wireless/ath/ath6kl/htc_hif.h
new file mode 100644
index 000000000000..171ad63d89b0
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/htc_hif.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2007-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HTC_HIF_H
+#define HTC_HIF_H
+
+#include "htc.h"
+#include "hif.h"
+
+#define ATH6KL_MAILBOXES 4
+
+/* HTC runs over mailbox 0 */
+#define HTC_MAILBOX 0
+
+#define ATH6KL_TARGET_DEBUG_INTR_MASK 0x01
+
+#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \
+ INT_STATUS_ENABLE_CPU_MASK | \
+ INT_STATUS_ENABLE_COUNTER_MASK)
+
+#define ATH6KL_REG_IO_BUFFER_SIZE 32
+#define ATH6KL_MAX_REG_IO_BUFFERS 8
+#define ATH6KL_SCATTER_ENTRIES_PER_REQ 16
+#define ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER (16 * 1024)
+#define ATH6KL_SCATTER_REQS 4
+
+#ifndef A_CACHE_LINE_PAD
+#define A_CACHE_LINE_PAD 128
+#endif
+#define ATH6KL_MIN_SCATTER_ENTRIES_PER_REQ 2
+#define ATH6KL_MIN_TRANSFER_SIZE_PER_SCATTER (4 * 1024)
+
+struct ath6kl_irq_proc_registers {
+ u8 host_int_status;
+ u8 cpu_int_status;
+ u8 error_int_status;
+ u8 counter_int_status;
+ u8 mbox_frame;
+ u8 rx_lkahd_valid;
+ u8 host_int_status2;
+ u8 gmbox_rx_avail;
+ __le32 rx_lkahd[2];
+ __le32 rx_gmbox_lkahd_alias[2];
+} __packed;
+
+struct ath6kl_irq_enable_reg {
+ u8 int_status_en;
+ u8 cpu_int_status_en;
+ u8 err_int_status_en;
+ u8 cntr_int_status_en;
+} __packed;
+
+struct ath6kl_device {
+ spinlock_t lock;
+ u8 pad1[A_CACHE_LINE_PAD];
+ struct ath6kl_irq_proc_registers irq_proc_reg;
+ u8 pad2[A_CACHE_LINE_PAD];
+ struct ath6kl_irq_enable_reg irq_en_reg;
+ u8 pad3[A_CACHE_LINE_PAD];
+ struct htc_target *htc_cnxt;
+ struct ath6kl *ar;
+};
+
+int ath6kldev_setup(struct ath6kl_device *dev);
+int ath6kldev_unmask_intrs(struct ath6kl_device *dev);
+int ath6kldev_mask_intrs(struct ath6kl_device *dev);
+int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev,
+ u32 *lk_ahd, int timeout);
+int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx);
+int ath6kldev_disable_intrs(struct ath6kl_device *dev);
+
+int ath6kldev_rw_comp_handler(void *context, int status);
+int ath6kldev_intr_bh_handler(struct ath6kl *ar);
+
+/* Scatter Function and Definitions */
+int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
+ struct hif_scatter_req *scat_req, bool read);
+
+#endif /*ATH6KL_H_ */
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
new file mode 100644
index 000000000000..c1d2366704b5
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -0,0 +1,1727 @@
+
+/*
+ * Copyright (c) 2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/of.h>
+#include <linux/mmc/sdio_func.h>
+#include "core.h"
+#include "cfg80211.h"
+#include "target.h"
+#include "debug.h"
+#include "hif-ops.h"
+
+unsigned int debug_mask;
+static unsigned int testmode;
+
+module_param(debug_mask, uint, 0644);
+module_param(testmode, uint, 0644);
+
+/*
+ * Include definitions here that can be used to tune the WLAN module
+ * behavior. Different customers can tune the behavior as per their needs,
+ * here.
+ */
+
+/*
+ * This configuration item enable/disable keepalive support.
+ * Keepalive support: In the absence of any data traffic to AP, null
+ * frames will be sent to the AP at periodic interval, to keep the association
+ * active. This configuration item defines the periodic interval.
+ * Use value of zero to disable keepalive support
+ * Default: 60 seconds
+ */
+#define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60
+
+/*
+ * This configuration item sets the value of disconnect timeout
+ * Firmware delays sending the disconnec event to the host for this
+ * timeout after is gets disconnected from the current AP.
+ * If the firmware successly roams within the disconnect timeout
+ * it sends a new connect event
+ */
+#define WLAN_CONFIG_DISCONNECT_TIMEOUT 10
+
+#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
+
+#define ATH6KL_DATA_OFFSET 64
+struct sk_buff *ath6kl_buf_alloc(int size)
+{
+ struct sk_buff *skb;
+ u16 reserved;
+
+ /* Add chacheline space at front and back of buffer */
+ reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET +
+ sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES;
+ skb = dev_alloc_skb(size + reserved);
+
+ if (skb)
+ skb_reserve(skb, reserved - L1_CACHE_BYTES);
+ return skb;
+}
+
+void ath6kl_init_profile_info(struct ath6kl *ar)
+{
+ ar->ssid_len = 0;
+ memset(ar->ssid, 0, sizeof(ar->ssid));
+
+ ar->dot11_auth_mode = OPEN_AUTH;
+ ar->auth_mode = NONE_AUTH;
+ ar->prwise_crypto = NONE_CRYPT;
+ ar->prwise_crypto_len = 0;
+ ar->grp_crypto = NONE_CRYPT;
+ ar->grp_crypto_len = 0;
+ memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
+ memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
+ memset(ar->bssid, 0, sizeof(ar->bssid));
+ ar->bss_ch = 0;
+ ar->nw_type = ar->next_mode = INFRA_NETWORK;
+}
+
+static u8 ath6kl_get_fw_iftype(struct ath6kl *ar)
+{
+ switch (ar->nw_type) {
+ case INFRA_NETWORK:
+ return HI_OPTION_FW_MODE_BSS_STA;
+ case ADHOC_NETWORK:
+ return HI_OPTION_FW_MODE_IBSS;
+ case AP_NETWORK:
+ return HI_OPTION_FW_MODE_AP;
+ default:
+ ath6kl_err("Unsupported interface type :%d\n", ar->nw_type);
+ return 0xff;
+ }
+}
+
+static int ath6kl_set_host_app_area(struct ath6kl *ar)
+{
+ u32 address, data;
+ struct host_app_area host_app_area;
+
+ /* Fetch the address of the host_app_area_s
+ * instance in the host interest area */
+ address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest));
+ address = TARG_VTOP(ar->target_type, address);
+
+ if (ath6kl_diag_read32(ar, address, &data))
+ return -EIO;
+
+ address = TARG_VTOP(ar->target_type, data);
+ host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
+ if (ath6kl_diag_write(ar, address, (u8 *) &host_app_area,
+ sizeof(struct host_app_area)))
+ return -EIO;
+
+ return 0;
+}
+
+static inline void set_ac2_ep_map(struct ath6kl *ar,
+ u8 ac,
+ enum htc_endpoint_id ep)
+{
+ ar->ac2ep_map[ac] = ep;
+ ar->ep2ac_map[ep] = ac;
+}
+
+/* connect to a service */
+static int ath6kl_connectservice(struct ath6kl *ar,
+ struct htc_service_connect_req *con_req,
+ char *desc)
+{
+ int status;
+ struct htc_service_connect_resp response;
+
+ memset(&response, 0, sizeof(response));
+
+ status = ath6kl_htc_conn_service(ar->htc_target, con_req, &response);
+ if (status) {
+ ath6kl_err("failed to connect to %s service status:%d\n",
+ desc, status);
+ return status;
+ }
+
+ switch (con_req->svc_id) {
+ case WMI_CONTROL_SVC:
+ if (test_bit(WMI_ENABLED, &ar->flag))
+ ath6kl_wmi_set_control_ep(ar->wmi, response.endpoint);
+ ar->ctrl_ep = response.endpoint;
+ break;
+ case WMI_DATA_BE_SVC:
+ set_ac2_ep_map(ar, WMM_AC_BE, response.endpoint);
+ break;
+ case WMI_DATA_BK_SVC:
+ set_ac2_ep_map(ar, WMM_AC_BK, response.endpoint);
+ break;
+ case WMI_DATA_VI_SVC:
+ set_ac2_ep_map(ar, WMM_AC_VI, response.endpoint);
+ break;
+ case WMI_DATA_VO_SVC:
+ set_ac2_ep_map(ar, WMM_AC_VO, response.endpoint);
+ break;
+ default:
+ ath6kl_err("service id is not mapped %d\n", con_req->svc_id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ath6kl_init_service_ep(struct ath6kl *ar)
+{
+ struct htc_service_connect_req connect;
+
+ memset(&connect, 0, sizeof(connect));
+
+ /* these fields are the same for all service endpoints */
+ connect.ep_cb.rx = ath6kl_rx;
+ connect.ep_cb.rx_refill = ath6kl_rx_refill;
+ connect.ep_cb.tx_full = ath6kl_tx_queue_full;
+
+ /*
+ * Set the max queue depth so that our ath6kl_tx_queue_full handler
+ * gets called.
+ */
+ connect.max_txq_depth = MAX_DEFAULT_SEND_QUEUE_DEPTH;
+ connect.ep_cb.rx_refill_thresh = ATH6KL_MAX_RX_BUFFERS / 4;
+ if (!connect.ep_cb.rx_refill_thresh)
+ connect.ep_cb.rx_refill_thresh++;
+
+ /* connect to control service */
+ connect.svc_id = WMI_CONTROL_SVC;
+ if (ath6kl_connectservice(ar, &connect, "WMI CONTROL"))
+ return -EIO;
+
+ connect.flags |= HTC_FLGS_TX_BNDL_PAD_EN;
+
+ /*
+ * Limit the HTC message size on the send path, although e can
+ * receive A-MSDU frames of 4K, we will only send ethernet-sized
+ * (802.3) frames on the send path.
+ */
+ connect.max_rxmsg_sz = WMI_MAX_TX_DATA_FRAME_LENGTH;
+
+ /*
+ * To reduce the amount of committed memory for larger A_MSDU
+ * frames, use the recv-alloc threshold mechanism for larger
+ * packets.
+ */
+ connect.ep_cb.rx_alloc_thresh = ATH6KL_BUFFER_SIZE;
+ connect.ep_cb.rx_allocthresh = ath6kl_alloc_amsdu_rxbuf;
+
+ /*
+ * For the remaining data services set the connection flag to
+ * reduce dribbling, if configured to do so.
+ */
+ connect.conn_flags |= HTC_CONN_FLGS_REDUCE_CRED_DRIB;
+ connect.conn_flags &= ~HTC_CONN_FLGS_THRESH_MASK;
+ connect.conn_flags |= HTC_CONN_FLGS_THRESH_LVL_HALF;
+
+ connect.svc_id = WMI_DATA_BE_SVC;
+
+ if (ath6kl_connectservice(ar, &connect, "WMI DATA BE"))
+ return -EIO;
+
+ /* connect to back-ground map this to WMI LOW_PRI */
+ connect.svc_id = WMI_DATA_BK_SVC;
+ if (ath6kl_connectservice(ar, &connect, "WMI DATA BK"))
+ return -EIO;
+
+ /* connect to Video service, map this to to HI PRI */
+ connect.svc_id = WMI_DATA_VI_SVC;
+ if (ath6kl_connectservice(ar, &connect, "WMI DATA VI"))
+ return -EIO;
+
+ /*
+ * Connect to VO service, this is currently not mapped to a WMI
+ * priority stream due to historical reasons. WMI originally
+ * defined 3 priorities over 3 mailboxes We can change this when
+ * WMI is reworked so that priorities are not dependent on
+ * mailboxes.
+ */
+ connect.svc_id = WMI_DATA_VO_SVC;
+ if (ath6kl_connectservice(ar, &connect, "WMI DATA VO"))
+ return -EIO;
+
+ return 0;
+}
+
+static void ath6kl_init_control_info(struct ath6kl *ar)
+{
+ u8 ctr;
+
+ clear_bit(WMI_ENABLED, &ar->flag);
+ ath6kl_init_profile_info(ar);
+ ar->def_txkey_index = 0;
+ memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
+ ar->ch_hint = 0;
+ ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL;
+ ar->listen_intvl_b = 0;
+ ar->tx_pwr = 0;
+ clear_bit(SKIP_SCAN, &ar->flag);
+ set_bit(WMM_ENABLED, &ar->flag);
+ ar->intra_bss = 1;
+ memset(&ar->sc_params, 0, sizeof(ar->sc_params));
+ ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT;
+ ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS;
+ ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
+
+ memset((u8 *)ar->sta_list, 0,
+ AP_MAX_NUM_STA * sizeof(struct ath6kl_sta));
+
+ spin_lock_init(&ar->mcastpsq_lock);
+
+ /* Init the PS queues */
+ for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
+ spin_lock_init(&ar->sta_list[ctr].psq_lock);
+ skb_queue_head_init(&ar->sta_list[ctr].psq);
+ }
+
+ skb_queue_head_init(&ar->mcastpsq);
+
+ memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
+}
+
+/*
+ * Set HTC/Mbox operational parameters, this can only be called when the
+ * target is in the BMI phase.
+ */
+static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
+ u8 htc_ctrl_buf)
+{
+ int status;
+ u32 blk_size;
+
+ blk_size = ar->mbox_info.block_size;
+
+ if (htc_ctrl_buf)
+ blk_size |= ((u32)htc_ctrl_buf) << 16;
+
+ /* set the host interest area for the block size */
+ status = ath6kl_bmi_write(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_mbox_io_block_sz)),
+ (u8 *)&blk_size,
+ 4);
+ if (status) {
+ ath6kl_err("bmi_write_memory for IO block size failed\n");
+ goto out;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "block size set: %d (target addr:0x%X)\n",
+ blk_size,
+ ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_mbox_io_block_sz)));
+
+ if (mbox_isr_yield_val) {
+ /* set the host interest area for the mbox ISR yield limit */
+ status = ath6kl_bmi_write(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_mbox_isr_yield_limit)),
+ (u8 *)&mbox_isr_yield_val,
+ 4);
+ if (status) {
+ ath6kl_err("bmi_write_memory for yield limit failed\n");
+ goto out;
+ }
+ }
+
+out:
+ return status;
+}
+
+#define REG_DUMP_COUNT_AR6003 60
+#define REGISTER_DUMP_LEN_MAX 60
+
+static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
+{
+ u32 address;
+ u32 regdump_loc = 0;
+ int status;
+ u32 regdump_val[REGISTER_DUMP_LEN_MAX];
+ u32 i;
+
+ if (ar->target_type != TARGET_TYPE_AR6003)
+ return;
+
+ /* the reg dump pointer is copied to the host interest area */
+ address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
+ address = TARG_VTOP(ar->target_type, address);
+
+ /* read RAM location through diagnostic window */
+ status = ath6kl_diag_read32(ar, address, &regdump_loc);
+
+ if (status || !regdump_loc) {
+ ath6kl_err("failed to get ptr to register dump area\n");
+ return;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n",
+ regdump_loc);
+ regdump_loc = TARG_VTOP(ar->target_type, regdump_loc);
+
+ /* fetch register dump data */
+ status = ath6kl_diag_read(ar, regdump_loc, (u8 *)&regdump_val[0],
+ REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
+
+ if (status) {
+ ath6kl_err("failed to get register dump\n");
+ return;
+ }
+ ath6kl_dbg(ATH6KL_DBG_TRC, "Register Dump:\n");
+
+ for (i = 0; i < REG_DUMP_COUNT_AR6003; i++)
+ ath6kl_dbg(ATH6KL_DBG_TRC, " %d : 0x%8.8X\n",
+ i, regdump_val[i]);
+
+}
+
+void ath6kl_target_failure(struct ath6kl *ar)
+{
+ ath6kl_err("target asserted\n");
+
+ /* try dumping target assertion information (if any) */
+ ath6kl_dump_target_assert_info(ar);
+
+}
+
+static int ath6kl_target_config_wlan_params(struct ath6kl *ar)
+{
+ int status = 0;
+ int ret;
+
+ /*
+ * Configure the device for rx dot11 header rules. "0,0" are the
+ * default values. Required if checksum offload is needed. Set
+ * RxMetaVersion to 2.
+ */
+ if (ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi,
+ ar->rx_meta_ver, 0, 0)) {
+ ath6kl_err("unable to set the rx frame format\n");
+ status = -EIO;
+ }
+
+ if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN)
+ if ((ath6kl_wmi_pmparams_cmd(ar->wmi, 0, 1, 0, 0, 1,
+ IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) {
+ ath6kl_err("unable to set power save fail event policy\n");
+ status = -EIO;
+ }
+
+ if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER))
+ if ((ath6kl_wmi_set_lpreamble_cmd(ar->wmi, 0,
+ WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) {
+ ath6kl_err("unable to set barker preamble policy\n");
+ status = -EIO;
+ }
+
+ if (ath6kl_wmi_set_keepalive_cmd(ar->wmi,
+ WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) {
+ ath6kl_err("unable to set keep alive interval\n");
+ status = -EIO;
+ }
+
+ if (ath6kl_wmi_disctimeout_cmd(ar->wmi,
+ WLAN_CONFIG_DISCONNECT_TIMEOUT)) {
+ ath6kl_err("unable to set disconnect timeout\n");
+ status = -EIO;
+ }
+
+ if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST))
+ if (ath6kl_wmi_set_wmm_txop(ar->wmi, WMI_TXOP_DISABLED)) {
+ ath6kl_err("unable to set txop bursting\n");
+ status = -EIO;
+ }
+
+ if (ar->p2p) {
+ ret = ath6kl_wmi_info_req_cmd(ar->wmi,
+ P2P_FLAG_CAPABILITIES_REQ |
+ P2P_FLAG_MACADDR_REQ |
+ P2P_FLAG_HMODEL_REQ);
+ if (ret) {
+ ath6kl_dbg(ATH6KL_DBG_TRC, "failed to request P2P "
+ "capabilities (%d) - assuming P2P not "
+ "supported\n", ret);
+ ar->p2p = 0;
+ }
+ }
+
+ if (ar->p2p) {
+ /* Enable Probe Request reporting for P2P */
+ ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, true);
+ if (ret) {
+ ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe "
+ "Request reporting (%d)\n", ret);
+ }
+ }
+
+ return status;
+}
+
+int ath6kl_configure_target(struct ath6kl *ar)
+{
+ u32 param, ram_reserved_size;
+ u8 fw_iftype;
+
+ fw_iftype = ath6kl_get_fw_iftype(ar);
+ if (fw_iftype == 0xff)
+ return -EINVAL;
+
+ /* Tell target which HTC version it is used*/
+ param = HTC_PROTOCOL_VERSION;
+ if (ath6kl_bmi_write(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_app_host_interest)),
+ (u8 *)&param, 4) != 0) {
+ ath6kl_err("bmi_write_memory for htc version failed\n");
+ return -EIO;
+ }
+
+ /* set the firmware mode to STA/IBSS/AP */
+ param = 0;
+
+ if (ath6kl_bmi_read(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_option_flag)),
+ (u8 *)&param, 4) != 0) {
+ ath6kl_err("bmi_read_memory for setting fwmode failed\n");
+ return -EIO;
+ }
+
+ param |= (1 << HI_OPTION_NUM_DEV_SHIFT);
+ param |= (fw_iftype << HI_OPTION_FW_MODE_SHIFT);
+ if (ar->p2p && fw_iftype == HI_OPTION_FW_MODE_BSS_STA) {
+ param |= HI_OPTION_FW_SUBMODE_P2PDEV <<
+ HI_OPTION_FW_SUBMODE_SHIFT;
+ }
+ param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
+ param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
+
+ if (ath6kl_bmi_write(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_option_flag)),
+ (u8 *)&param,
+ 4) != 0) {
+ ath6kl_err("bmi_write_memory for setting fwmode failed\n");
+ return -EIO;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "firmware mode set\n");
+
+ /*
+ * Hardcode the address use for the extended board data
+ * Ideally this should be pre-allocate by the OS at boot time
+ * But since it is a new feature and board data is loaded
+ * at init time, we have to workaround this from host.
+ * It is difficult to patch the firmware boot code,
+ * but possible in theory.
+ */
+
+ param = ar->hw.board_ext_data_addr;
+ ram_reserved_size = ar->hw.reserved_ram_size;
+
+ if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_board_ext_data)),
+ (u8 *)&param, 4) != 0) {
+ ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n");
+ return -EIO;
+ }
+
+ if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_end_ram_reserve_sz)),
+ (u8 *)&ram_reserved_size, 4) != 0) {
+ ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n");
+ return -EIO;
+ }
+
+ /* set the block size for the target */
+ if (ath6kl_set_htc_params(ar, MBOX_YIELD_LIMIT, 0))
+ /* use default number of control buffers */
+ return -EIO;
+
+ return 0;
+}
+
+struct ath6kl *ath6kl_core_alloc(struct device *sdev)
+{
+ struct net_device *dev;
+ struct ath6kl *ar;
+ struct wireless_dev *wdev;
+
+ wdev = ath6kl_cfg80211_init(sdev);
+ if (!wdev) {
+ ath6kl_err("ath6kl_cfg80211_init failed\n");
+ return NULL;
+ }
+
+ ar = wdev_priv(wdev);
+ ar->dev = sdev;
+ ar->wdev = wdev;
+ wdev->iftype = NL80211_IFTYPE_STATION;
+
+ if (ath6kl_debug_init(ar)) {
+ ath6kl_err("Failed to initialize debugfs\n");
+ ath6kl_cfg80211_deinit(ar);
+ return NULL;
+ }
+
+ dev = alloc_netdev(0, "wlan%d", ether_setup);
+ if (!dev) {
+ ath6kl_err("no memory for network device instance\n");
+ ath6kl_cfg80211_deinit(ar);
+ return NULL;
+ }
+
+ dev->ieee80211_ptr = wdev;
+ SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
+ wdev->netdev = dev;
+ ar->sme_state = SME_DISCONNECTED;
+
+ init_netdev(dev);
+
+ ar->net_dev = dev;
+ set_bit(WLAN_ENABLED, &ar->flag);
+
+ ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
+
+ spin_lock_init(&ar->lock);
+
+ ath6kl_init_control_info(ar);
+ init_waitqueue_head(&ar->event_wq);
+ sema_init(&ar->sem, 1);
+ clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
+
+ INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);
+
+ setup_timer(&ar->disconnect_timer, disconnect_timer_handler,
+ (unsigned long) dev);
+
+ return ar;
+}
+
+int ath6kl_unavail_ev(struct ath6kl *ar)
+{
+ ath6kl_destroy(ar->net_dev, 1);
+
+ return 0;
+}
+
+/* firmware upload */
+static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
+ u8 **fw, size_t *fw_len)
+{
+ const struct firmware *fw_entry;
+ int ret;
+
+ ret = request_firmware(&fw_entry, filename, ar->dev);
+ if (ret)
+ return ret;
+
+ *fw_len = fw_entry->size;
+ *fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+
+ if (*fw == NULL)
+ ret = -ENOMEM;
+
+ release_firmware(fw_entry);
+
+ return ret;
+}
+
+#ifdef CONFIG_OF
+static const char *get_target_ver_dir(const struct ath6kl *ar)
+{
+ switch (ar->version.target_ver) {
+ case AR6003_REV1_VERSION:
+ return "ath6k/AR6003/hw1.0";
+ case AR6003_REV2_VERSION:
+ return "ath6k/AR6003/hw2.0";
+ case AR6003_REV3_VERSION:
+ return "ath6k/AR6003/hw2.1.1";
+ }
+ ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__,
+ ar->version.target_ver);
+ return NULL;
+}
+
+/*
+ * Check the device tree for a board-id and use it to construct
+ * the pathname to the firmware file. Used (for now) to find a
+ * fallback to the "bdata.bin" file--typically a symlink to the
+ * appropriate board-specific file.
+ */
+static bool check_device_tree(struct ath6kl *ar)
+{
+ static const char *board_id_prop = "atheros,board-id";
+ struct device_node *node;
+ char board_filename[64];
+ const char *board_id;
+ int ret;
+
+ for_each_compatible_node(node, NULL, "atheros,ath6kl") {
+ board_id = of_get_property(node, board_id_prop, NULL);
+ if (board_id == NULL) {
+ ath6kl_warn("No \"%s\" property on %s node.\n",
+ board_id_prop, node->name);
+ continue;
+ }
+ snprintf(board_filename, sizeof(board_filename),
+ "%s/bdata.%s.bin", get_target_ver_dir(ar), board_id);
+
+ ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board,
+ &ar->fw_board_len);
+ if (ret) {
+ ath6kl_err("Failed to get DT board file %s: %d\n",
+ board_filename, ret);
+ continue;
+ }
+ return true;
+ }
+ return false;
+}
+#else
+static bool check_device_tree(struct ath6kl *ar)
+{
+ return false;
+}
+#endif /* CONFIG_OF */
+
+static int ath6kl_fetch_board_file(struct ath6kl *ar)
+{
+ const char *filename;
+ int ret;
+
+ if (ar->fw_board != NULL)
+ return 0;
+
+ switch (ar->version.target_ver) {
+ case AR6003_REV2_VERSION:
+ filename = AR6003_REV2_BOARD_DATA_FILE;
+ break;
+ case AR6004_REV1_VERSION:
+ filename = AR6004_REV1_BOARD_DATA_FILE;
+ break;
+ default:
+ filename = AR6003_REV3_BOARD_DATA_FILE;
+ break;
+ }
+
+ ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
+ &ar->fw_board_len);
+ if (ret == 0) {
+ /* managed to get proper board file */
+ return 0;
+ }
+
+ if (check_device_tree(ar)) {
+ /* got board file from device tree */
+ return 0;
+ }
+
+ /* there was no proper board file, try to use default instead */
+ ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n",
+ filename, ret);
+
+ switch (ar->version.target_ver) {
+ case AR6003_REV2_VERSION:
+ filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE;
+ break;
+ case AR6004_REV1_VERSION:
+ filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE;
+ break;
+ default:
+ filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE;
+ break;
+ }
+
+ ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
+ &ar->fw_board_len);
+ if (ret) {
+ ath6kl_err("Failed to get default board file %s: %d\n",
+ filename, ret);
+ return ret;
+ }
+
+ ath6kl_warn("WARNING! No proper board file was not found, instead using a default board file.\n");
+ ath6kl_warn("Most likely your hardware won't work as specified. Install correct board file!\n");
+
+ return 0;
+}
+
+static int ath6kl_fetch_otp_file(struct ath6kl *ar)
+{
+ const char *filename;
+ int ret;
+
+ if (ar->fw_otp != NULL)
+ return 0;
+
+ switch (ar->version.target_ver) {
+ case AR6003_REV2_VERSION:
+ filename = AR6003_REV2_OTP_FILE;
+ break;
+ case AR6004_REV1_VERSION:
+ ath6kl_dbg(ATH6KL_DBG_TRC, "AR6004 doesn't need OTP file\n");
+ return 0;
+ break;
+ default:
+ filename = AR6003_REV3_OTP_FILE;
+ break;
+ }
+
+ ret = ath6kl_get_fw(ar, filename, &ar->fw_otp,
+ &ar->fw_otp_len);
+ if (ret) {
+ ath6kl_err("Failed to get OTP file %s: %d\n",
+ filename, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ath6kl_fetch_fw_file(struct ath6kl *ar)
+{
+ const char *filename;
+ int ret;
+
+ if (ar->fw != NULL)
+ return 0;
+
+ if (testmode) {
+ switch (ar->version.target_ver) {
+ case AR6003_REV2_VERSION:
+ filename = AR6003_REV2_TCMD_FIRMWARE_FILE;
+ break;
+ case AR6003_REV3_VERSION:
+ filename = AR6003_REV3_TCMD_FIRMWARE_FILE;
+ break;
+ case AR6004_REV1_VERSION:
+ ath6kl_warn("testmode not supported with ar6004\n");
+ return -EOPNOTSUPP;
+ default:
+ ath6kl_warn("unknown target version: 0x%x\n",
+ ar->version.target_ver);
+ return -EINVAL;
+ }
+
+ set_bit(TESTMODE, &ar->flag);
+
+ goto get_fw;
+ }
+
+ switch (ar->version.target_ver) {
+ case AR6003_REV2_VERSION:
+ filename = AR6003_REV2_FIRMWARE_FILE;
+ break;
+ case AR6004_REV1_VERSION:
+ filename = AR6004_REV1_FIRMWARE_FILE;
+ break;
+ default:
+ filename = AR6003_REV3_FIRMWARE_FILE;
+ break;
+ }
+
+get_fw:
+ ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len);
+ if (ret) {
+ ath6kl_err("Failed to get firmware file %s: %d\n",
+ filename, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ath6kl_fetch_patch_file(struct ath6kl *ar)
+{
+ const char *filename;
+ int ret;
+
+ switch (ar->version.target_ver) {
+ case AR6003_REV2_VERSION:
+ filename = AR6003_REV2_PATCH_FILE;
+ break;
+ case AR6004_REV1_VERSION:
+ /* FIXME: implement for AR6004 */
+ return 0;
+ break;
+ default:
+ filename = AR6003_REV3_PATCH_FILE;
+ break;
+ }
+
+ if (ar->fw_patch == NULL) {
+ ret = ath6kl_get_fw(ar, filename, &ar->fw_patch,
+ &ar->fw_patch_len);
+ if (ret) {
+ ath6kl_err("Failed to get patch file %s: %d\n",
+ filename, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int ath6kl_fetch_fw_api1(struct ath6kl *ar)
+{
+ int ret;
+
+ ret = ath6kl_fetch_otp_file(ar);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_fetch_fw_file(ar);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_fetch_patch_file(ar);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
+{
+ size_t magic_len, len, ie_len;
+ const struct firmware *fw;
+ struct ath6kl_fw_ie *hdr;
+ const char *filename;
+ const u8 *data;
+ int ret, ie_id, i, index, bit;
+ __le32 *val;
+
+ switch (ar->version.target_ver) {
+ case AR6003_REV2_VERSION:
+ filename = AR6003_REV2_FIRMWARE_2_FILE;
+ break;
+ case AR6003_REV3_VERSION:
+ filename = AR6003_REV3_FIRMWARE_2_FILE;
+ break;
+ case AR6004_REV1_VERSION:
+ filename = AR6004_REV1_FIRMWARE_2_FILE;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ ret = request_firmware(&fw, filename, ar->dev);
+ if (ret)
+ return ret;
+
+ data = fw->data;
+ len = fw->size;
+
+ /* magic also includes the null byte, check that as well */
+ magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1;
+
+ if (len < magic_len) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ len -= magic_len;
+ data += magic_len;
+
+ /* loop elements */
+ while (len > sizeof(struct ath6kl_fw_ie)) {
+ /* hdr is unaligned! */
+ hdr = (struct ath6kl_fw_ie *) data;
+
+ ie_id = le32_to_cpup(&hdr->id);
+ ie_len = le32_to_cpup(&hdr->len);
+
+ len -= sizeof(*hdr);
+ data += sizeof(*hdr);
+
+ if (len < ie_len) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ switch (ie_id) {
+ case ATH6KL_FW_IE_OTP_IMAGE:
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
+ ie_len);
+
+ ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL);
+
+ if (ar->fw_otp == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ar->fw_otp_len = ie_len;
+ break;
+ case ATH6KL_FW_IE_FW_IMAGE:
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n",
+ ie_len);
+
+ ar->fw = kmemdup(data, ie_len, GFP_KERNEL);
+
+ if (ar->fw == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ar->fw_len = ie_len;
+ break;
+ case ATH6KL_FW_IE_PATCH_IMAGE:
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "found patch image ie (%zd B)\n",
+ ie_len);
+
+ ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL);
+
+ if (ar->fw_patch == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ar->fw_patch_len = ie_len;
+ break;
+ case ATH6KL_FW_IE_RESERVED_RAM_SIZE:
+ val = (__le32 *) data;
+ ar->hw.reserved_ram_size = le32_to_cpup(val);
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT,
+ "found reserved ram size ie 0x%d\n",
+ ar->hw.reserved_ram_size);
+ break;
+ case ATH6KL_FW_IE_CAPABILITIES:
+ ath6kl_dbg(ATH6KL_DBG_BOOT,
+ "found firmware capabilities ie (%zd B)\n",
+ ie_len);
+
+ for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) {
+ index = ALIGN(i, 8) / 8;
+ bit = i % 8;
+
+ if (data[index] & (1 << bit))
+ __set_bit(i, ar->fw_capabilities);
+ }
+
+ ath6kl_dbg_dump(ATH6KL_DBG_BOOT, "capabilities", "",
+ ar->fw_capabilities,
+ sizeof(ar->fw_capabilities));
+ break;
+ case ATH6KL_FW_IE_PATCH_ADDR:
+ if (ie_len != sizeof(*val))
+ break;
+
+ val = (__le32 *) data;
+ ar->hw.dataset_patch_addr = le32_to_cpup(val);
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT,
+ "found patch address ie 0x%d\n",
+ ar->hw.dataset_patch_addr);
+ break;
+ default:
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n",
+ le32_to_cpup(&hdr->id));
+ break;
+ }
+
+ len -= ie_len;
+ data += ie_len;
+ };
+
+ ret = 0;
+out:
+ release_firmware(fw);
+
+ return ret;
+}
+
+static int ath6kl_fetch_firmwares(struct ath6kl *ar)
+{
+ int ret;
+
+ ret = ath6kl_fetch_board_file(ar);
+ if (ret)
+ return ret;
+
+ ret = ath6kl_fetch_fw_api2(ar);
+ if (ret == 0) {
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 2\n");
+ return 0;
+ }
+
+ ret = ath6kl_fetch_fw_api1(ar);
+ if (ret)
+ return ret;
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 1\n");
+
+ return 0;
+}
+
+static int ath6kl_upload_board_file(struct ath6kl *ar)
+{
+ u32 board_address, board_ext_address, param;
+ u32 board_data_size, board_ext_data_size;
+ int ret;
+
+ if (WARN_ON(ar->fw_board == NULL))
+ return -ENOENT;
+
+ /*
+ * Determine where in Target RAM to write Board Data.
+ * For AR6004, host determine Target RAM address for
+ * writing board data.
+ */
+ if (ar->target_type == TARGET_TYPE_AR6004) {
+ board_address = AR6004_REV1_BOARD_DATA_ADDRESS;
+ ath6kl_bmi_write(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_board_data)),
+ (u8 *) &board_address, 4);
+ } else {
+ ath6kl_bmi_read(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_board_data)),
+ (u8 *) &board_address, 4);
+ }
+
+ /* determine where in target ram to write extended board data */
+ ath6kl_bmi_read(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_board_ext_data)),
+ (u8 *) &board_ext_address, 4);
+
+ if (board_ext_address == 0) {
+ ath6kl_err("Failed to get board file target address.\n");
+ return -EINVAL;
+ }
+
+ switch (ar->target_type) {
+ case TARGET_TYPE_AR6003:
+ board_data_size = AR6003_BOARD_DATA_SZ;
+ board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
+ break;
+ case TARGET_TYPE_AR6004:
+ board_data_size = AR6004_BOARD_DATA_SZ;
+ board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ break;
+ }
+
+ if (ar->fw_board_len == (board_data_size +
+ board_ext_data_size)) {
+
+ /* write extended board data */
+ ath6kl_dbg(ATH6KL_DBG_BOOT,
+ "writing extended board data to 0x%x (%d B)\n",
+ board_ext_address, board_ext_data_size);
+
+ ret = ath6kl_bmi_write(ar, board_ext_address,
+ ar->fw_board + board_data_size,
+ board_ext_data_size);
+ if (ret) {
+ ath6kl_err("Failed to write extended board data: %d\n",
+ ret);
+ return ret;
+ }
+
+ /* record that extended board data is initialized */
+ param = (board_ext_data_size << 16) | 1;
+
+ ath6kl_bmi_write(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_board_ext_data_config)),
+ (unsigned char *) &param, 4);
+ }
+
+ if (ar->fw_board_len < board_data_size) {
+ ath6kl_err("Too small board file: %zu\n", ar->fw_board_len);
+ ret = -EINVAL;
+ return ret;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "writing board file to 0x%x (%d B)\n",
+ board_address, board_data_size);
+
+ ret = ath6kl_bmi_write(ar, board_address, ar->fw_board,
+ board_data_size);
+
+ if (ret) {
+ ath6kl_err("Board file bmi write failed: %d\n", ret);
+ return ret;
+ }
+
+ /* record the fact that Board Data IS initialized */
+ param = 1;
+ ath6kl_bmi_write(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_board_data_initialized)),
+ (u8 *)&param, 4);
+
+ return ret;
+}
+
+static int ath6kl_upload_otp(struct ath6kl *ar)
+{
+ u32 address, param;
+ int ret;
+
+ if (WARN_ON(ar->fw_otp == NULL))
+ return -ENOENT;
+
+ address = ar->hw.app_load_addr;
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "writing otp to 0x%x (%zd B)\n", address,
+ ar->fw_otp_len);
+
+ ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp,
+ ar->fw_otp_len);
+ if (ret) {
+ ath6kl_err("Failed to upload OTP file: %d\n", ret);
+ return ret;
+ }
+
+ /* read firmware start address */
+ ret = ath6kl_bmi_read(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_app_start)),
+ (u8 *) &address, sizeof(address));
+
+ if (ret) {
+ ath6kl_err("Failed to read hi_app_start: %d\n", ret);
+ return ret;
+ }
+
+ ar->hw.app_start_override_addr = address;
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "app_start_override_addr 0x%x\n",
+ ar->hw.app_start_override_addr);
+
+ /* execute the OTP code */
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "executing OTP at 0x%x\n", address);
+ param = 0;
+ ath6kl_bmi_execute(ar, address, &param);
+
+ return ret;
+}
+
+static int ath6kl_upload_firmware(struct ath6kl *ar)
+{
+ u32 address;
+ int ret;
+
+ if (WARN_ON(ar->fw == NULL))
+ return -ENOENT;
+
+ address = ar->hw.app_load_addr;
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "writing firmware to 0x%x (%zd B)\n",
+ address, ar->fw_len);
+
+ ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len);
+
+ if (ret) {
+ ath6kl_err("Failed to write firmware: %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * Set starting address for firmware
+ * Don't need to setup app_start override addr on AR6004
+ */
+ if (ar->target_type != TARGET_TYPE_AR6004) {
+ address = ar->hw.app_start_override_addr;
+ ath6kl_bmi_set_app_start(ar, address);
+ }
+ return ret;
+}
+
+static int ath6kl_upload_patch(struct ath6kl *ar)
+{
+ u32 address, param;
+ int ret;
+
+ if (WARN_ON(ar->fw_patch == NULL))
+ return -ENOENT;
+
+ address = ar->hw.dataset_patch_addr;
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "writing patch to 0x%x (%zd B)\n",
+ address, ar->fw_patch_len);
+
+ ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len);
+ if (ret) {
+ ath6kl_err("Failed to write patch file: %d\n", ret);
+ return ret;
+ }
+
+ param = address;
+ ath6kl_bmi_write(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_dset_list_head)),
+ (unsigned char *) &param, 4);
+
+ return 0;
+}
+
+static int ath6kl_init_upload(struct ath6kl *ar)
+{
+ u32 param, options, sleep, address;
+ int status = 0;
+
+ if (ar->target_type != TARGET_TYPE_AR6003 &&
+ ar->target_type != TARGET_TYPE_AR6004)
+ return -EINVAL;
+
+ /* temporarily disable system sleep */
+ address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
+ status = ath6kl_bmi_reg_read(ar, address, &param);
+ if (status)
+ return status;
+
+ options = param;
+
+ param |= ATH6KL_OPTION_SLEEP_DISABLE;
+ status = ath6kl_bmi_reg_write(ar, address, param);
+ if (status)
+ return status;
+
+ address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
+ status = ath6kl_bmi_reg_read(ar, address, &param);
+ if (status)
+ return status;
+
+ sleep = param;
+
+ param |= SM(SYSTEM_SLEEP_DISABLE, 1);
+ status = ath6kl_bmi_reg_write(ar, address, param);
+ if (status)
+ return status;
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n",
+ options, sleep);
+
+ /* program analog PLL register */
+ /* no need to control 40/44MHz clock on AR6004 */
+ if (ar->target_type != TARGET_TYPE_AR6004) {
+ status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER,
+ 0xF9104001);
+
+ if (status)
+ return status;
+
+ /* Run at 80/88MHz by default */
+ param = SM(CPU_CLOCK_STANDARD, 1);
+
+ address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
+ status = ath6kl_bmi_reg_write(ar, address, param);
+ if (status)
+ return status;
+ }
+
+ param = 0;
+ address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
+ param = SM(LPO_CAL_ENABLE, 1);
+ status = ath6kl_bmi_reg_write(ar, address, param);
+ if (status)
+ return status;
+
+ /* WAR to avoid SDIO CRC err */
+ if (ar->version.target_ver == AR6003_REV2_VERSION) {
+ ath6kl_err("temporary war to avoid sdio crc error\n");
+
+ param = 0x20;
+
+ address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
+ status = ath6kl_bmi_reg_write(ar, address, param);
+ if (status)
+ return status;
+
+ address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
+ status = ath6kl_bmi_reg_write(ar, address, param);
+ if (status)
+ return status;
+
+ address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
+ status = ath6kl_bmi_reg_write(ar, address, param);
+ if (status)
+ return status;
+
+ address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
+ status = ath6kl_bmi_reg_write(ar, address, param);
+ if (status)
+ return status;
+ }
+
+ /* write EEPROM data to Target RAM */
+ status = ath6kl_upload_board_file(ar);
+ if (status)
+ return status;
+
+ /* transfer One time Programmable data */
+ status = ath6kl_upload_otp(ar);
+ if (status)
+ return status;
+
+ /* Download Target firmware */
+ status = ath6kl_upload_firmware(ar);
+ if (status)
+ return status;
+
+ status = ath6kl_upload_patch(ar);
+ if (status)
+ return status;
+
+ /* Restore system sleep */
+ address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
+ status = ath6kl_bmi_reg_write(ar, address, sleep);
+ if (status)
+ return status;
+
+ address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
+ param = options | 0x20;
+ status = ath6kl_bmi_reg_write(ar, address, param);
+ if (status)
+ return status;
+
+ /* Configure GPIO AR6003 UART */
+ param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
+ status = ath6kl_bmi_write(ar,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_dbg_uart_txpin)),
+ (u8 *)&param, 4);
+
+ return status;
+}
+
+static int ath6kl_init_hw_params(struct ath6kl *ar)
+{
+ switch (ar->version.target_ver) {
+ case AR6003_REV2_VERSION:
+ ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
+ ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS;
+ ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS;
+ ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE;
+ break;
+ case AR6003_REV3_VERSION:
+ ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS;
+ ar->hw.app_load_addr = 0x1234;
+ ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS;
+ ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE;
+ break;
+ case AR6004_REV1_VERSION:
+ ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
+ ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS;
+ ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS;
+ ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE;
+ break;
+ default:
+ ath6kl_err("Unsupported hardware version: 0x%x\n",
+ ar->version.target_ver);
+ return -EINVAL;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT,
+ "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n",
+ ar->version.target_ver, ar->target_type,
+ ar->hw.dataset_patch_addr, ar->hw.app_load_addr);
+ ath6kl_dbg(ATH6KL_DBG_BOOT,
+ "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x",
+ ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr,
+ ar->hw.reserved_ram_size);
+
+ return 0;
+}
+
+static int ath6kl_init(struct net_device *dev)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ int status = 0;
+ s32 timeleft;
+
+ if (!ar)
+ return -EIO;
+
+ /* Do we need to finish the BMI phase */
+ if (ath6kl_bmi_done(ar)) {
+ status = -EIO;
+ goto ath6kl_init_done;
+ }
+
+ /* Indicate that WMI is enabled (although not ready yet) */
+ set_bit(WMI_ENABLED, &ar->flag);
+ ar->wmi = ath6kl_wmi_init(ar);
+ if (!ar->wmi) {
+ ath6kl_err("failed to initialize wmi\n");
+ status = -EIO;
+ goto ath6kl_init_done;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
+
+ /*
+ * The reason we have to wait for the target here is that the
+ * driver layer has to init BMI in order to set the host block
+ * size.
+ */
+ if (ath6kl_htc_wait_target(ar->htc_target)) {
+ status = -EIO;
+ goto err_node_cleanup;
+ }
+
+ if (ath6kl_init_service_ep(ar)) {
+ status = -EIO;
+ goto err_cleanup_scatter;
+ }
+
+ /* setup access class priority mappings */
+ ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */
+ ar->ac_stream_pri_map[WMM_AC_BE] = 1;
+ ar->ac_stream_pri_map[WMM_AC_VI] = 2;
+ ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
+
+ /* give our connected endpoints some buffers */
+ ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
+ ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
+
+ /* allocate some buffers that handle larger AMSDU frames */
+ ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
+
+ /* setup credit distribution */
+ ath6k_setup_credit_dist(ar->htc_target, &ar->credit_state_info);
+
+ ath6kl_cookie_init(ar);
+
+ /* start HTC */
+ status = ath6kl_htc_start(ar->htc_target);
+
+ if (status) {
+ ath6kl_cookie_cleanup(ar);
+ goto err_rxbuf_cleanup;
+ }
+
+ /* Wait for Wmi event to be ready */
+ timeleft = wait_event_interruptible_timeout(ar->event_wq,
+ test_bit(WMI_READY,
+ &ar->flag),
+ WMI_TIMEOUT);
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n");
+
+ if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
+ ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
+ ATH6KL_ABI_VERSION, ar->version.abi_ver);
+ status = -EIO;
+ goto err_htc_stop;
+ }
+
+ if (!timeleft || signal_pending(current)) {
+ ath6kl_err("wmi is not ready or wait was interrupted\n");
+ status = -EIO;
+ goto err_htc_stop;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__);
+
+ /* communicate the wmi protocol verision to the target */
+ if ((ath6kl_set_host_app_area(ar)) != 0)
+ ath6kl_err("unable to set the host app area\n");
+
+ ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
+ ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
+
+ ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+
+ status = ath6kl_target_config_wlan_params(ar);
+ if (!status)
+ goto ath6kl_init_done;
+
+err_htc_stop:
+ ath6kl_htc_stop(ar->htc_target);
+err_rxbuf_cleanup:
+ ath6kl_htc_flush_rx_buf(ar->htc_target);
+ ath6kl_cleanup_amsdu_rxbufs(ar);
+err_cleanup_scatter:
+ ath6kl_hif_cleanup_scatter(ar);
+err_node_cleanup:
+ ath6kl_wmi_shutdown(ar->wmi);
+ clear_bit(WMI_ENABLED, &ar->flag);
+ ar->wmi = NULL;
+
+ath6kl_init_done:
+ return status;
+}
+
+int ath6kl_core_init(struct ath6kl *ar)
+{
+ int ret = 0;
+ struct ath6kl_bmi_target_info targ_info;
+
+ ar->ath6kl_wq = create_singlethread_workqueue("ath6kl");
+ if (!ar->ath6kl_wq)
+ return -ENOMEM;
+
+ ret = ath6kl_bmi_init(ar);
+ if (ret)
+ goto err_wq;
+
+ ret = ath6kl_bmi_get_target_info(ar, &targ_info);
+ if (ret)
+ goto err_bmi_cleanup;
+
+ ar->version.target_ver = le32_to_cpu(targ_info.version);
+ ar->target_type = le32_to_cpu(targ_info.type);
+ ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version);
+
+ ret = ath6kl_init_hw_params(ar);
+ if (ret)
+ goto err_bmi_cleanup;
+
+ ret = ath6kl_configure_target(ar);
+ if (ret)
+ goto err_bmi_cleanup;
+
+ ar->htc_target = ath6kl_htc_create(ar);
+
+ if (!ar->htc_target) {
+ ret = -ENOMEM;
+ goto err_bmi_cleanup;
+ }
+
+ ar->aggr_cntxt = aggr_init(ar->net_dev);
+ if (!ar->aggr_cntxt) {
+ ath6kl_err("failed to initialize aggr\n");
+ ret = -ENOMEM;
+ goto err_htc_cleanup;
+ }
+
+ ret = ath6kl_fetch_firmwares(ar);
+ if (ret)
+ goto err_htc_cleanup;
+
+ ret = ath6kl_init_upload(ar);
+ if (ret)
+ goto err_htc_cleanup;
+
+ ret = ath6kl_init(ar->net_dev);
+ if (ret)
+ goto err_htc_cleanup;
+
+ /* This runs the init function if registered */
+ ret = register_netdev(ar->net_dev);
+ if (ret) {
+ ath6kl_err("register_netdev failed\n");
+ ath6kl_destroy(ar->net_dev, 0);
+ return ret;
+ }
+
+ set_bit(NETDEV_REGISTERED, &ar->flag);
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
+ __func__, ar->net_dev->name, ar->net_dev, ar);
+
+ return ret;
+
+err_htc_cleanup:
+ ath6kl_htc_cleanup(ar->htc_target);
+err_bmi_cleanup:
+ ath6kl_bmi_cleanup(ar);
+err_wq:
+ destroy_workqueue(ar->ath6kl_wq);
+ return ret;
+}
+
+void ath6kl_stop_txrx(struct ath6kl *ar)
+{
+ struct net_device *ndev = ar->net_dev;
+
+ if (!ndev)
+ return;
+
+ set_bit(DESTROY_IN_PROGRESS, &ar->flag);
+
+ if (down_interruptible(&ar->sem)) {
+ ath6kl_err("down_interruptible failed\n");
+ return;
+ }
+
+ if (ar->wlan_pwr_state != WLAN_POWER_STATE_CUT_PWR)
+ ath6kl_stop_endpoint(ndev, false, true);
+
+ clear_bit(WLAN_ENABLED, &ar->flag);
+}
+
+/*
+ * We need to differentiate between the surprise and planned removal of the
+ * device because of the following consideration:
+ *
+ * - In case of surprise removal, the hcd already frees up the pending
+ * for the device and hence there is no need to unregister the function
+ * driver inorder to get these requests. For planned removal, the function
+ * driver has to explicitly unregister itself to have the hcd return all the
+ * pending requests before the data structures for the devices are freed up.
+ * Note that as per the current implementation, the function driver will
+ * end up releasing all the devices since there is no API to selectively
+ * release a particular device.
+ *
+ * - Certain commands issued to the target can be skipped for surprise
+ * removal since they will anyway not go through.
+ */
+void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
+{
+ struct ath6kl *ar;
+
+ if (!dev || !ath6kl_priv(dev)) {
+ ath6kl_err("failed to get device structure\n");
+ return;
+ }
+
+ ar = ath6kl_priv(dev);
+
+ destroy_workqueue(ar->ath6kl_wq);
+
+ if (ar->htc_target)
+ ath6kl_htc_cleanup(ar->htc_target);
+
+ aggr_module_destroy(ar->aggr_cntxt);
+
+ ath6kl_cookie_cleanup(ar);
+
+ ath6kl_cleanup_amsdu_rxbufs(ar);
+
+ ath6kl_bmi_cleanup(ar);
+
+ ath6kl_debug_cleanup(ar);
+
+ if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) {
+ unregister_netdev(dev);
+ clear_bit(NETDEV_REGISTERED, &ar->flag);
+ }
+
+ free_netdev(dev);
+
+ kfree(ar->fw_board);
+ kfree(ar->fw_otp);
+ kfree(ar->fw);
+ kfree(ar->fw_patch);
+
+ ath6kl_cfg80211_deinit(ar);
+}
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
new file mode 100644
index 000000000000..30b5a53db9ed
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -0,0 +1,1477 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications 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 "hif-ops.h"
+#include "cfg80211.h"
+#include "target.h"
+#include "debug.h"
+
+struct ath6kl_sta *ath6kl_find_sta(struct ath6kl *ar, u8 *node_addr)
+{
+ struct ath6kl_sta *conn = NULL;
+ u8 i, max_conn;
+
+ max_conn = (ar->nw_type == AP_NETWORK) ? AP_MAX_NUM_STA : 0;
+
+ for (i = 0; i < max_conn; i++) {
+ if (memcmp(node_addr, ar->sta_list[i].mac, ETH_ALEN) == 0) {
+ conn = &ar->sta_list[i];
+ break;
+ }
+ }
+
+ return conn;
+}
+
+struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid)
+{
+ struct ath6kl_sta *conn = NULL;
+ u8 ctr;
+
+ for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
+ if (ar->sta_list[ctr].aid == aid) {
+ conn = &ar->sta_list[ctr];
+ break;
+ }
+ }
+ return conn;
+}
+
+static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie,
+ u8 ielen, u8 keymgmt, u8 ucipher, u8 auth)
+{
+ struct ath6kl_sta *sta;
+ u8 free_slot;
+
+ free_slot = aid - 1;
+
+ sta = &ar->sta_list[free_slot];
+ memcpy(sta->mac, mac, ETH_ALEN);
+ if (ielen <= ATH6KL_MAX_IE)
+ memcpy(sta->wpa_ie, wpaie, ielen);
+ sta->aid = aid;
+ sta->keymgmt = keymgmt;
+ sta->ucipher = ucipher;
+ sta->auth = auth;
+
+ ar->sta_list_index = ar->sta_list_index | (1 << free_slot);
+ ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid);
+}
+
+static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
+{
+ struct ath6kl_sta *sta = &ar->sta_list[i];
+
+ /* empty the queued pkts in the PS queue if any */
+ spin_lock_bh(&sta->psq_lock);
+ skb_queue_purge(&sta->psq);
+ spin_unlock_bh(&sta->psq_lock);
+
+ memset(&ar->ap_stats.sta[sta->aid - 1], 0,
+ sizeof(struct wmi_per_sta_stat));
+ memset(sta->mac, 0, ETH_ALEN);
+ memset(sta->wpa_ie, 0, ATH6KL_MAX_IE);
+ sta->aid = 0;
+ sta->sta_flags = 0;
+
+ ar->sta_list_index = ar->sta_list_index & ~(1 << i);
+
+}
+
+static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason)
+{
+ u8 i, removed = 0;
+
+ if (is_zero_ether_addr(mac))
+ return removed;
+
+ if (is_broadcast_ether_addr(mac)) {
+ ath6kl_dbg(ATH6KL_DBG_TRC, "deleting all station\n");
+
+ for (i = 0; i < AP_MAX_NUM_STA; i++) {
+ if (!is_zero_ether_addr(ar->sta_list[i].mac)) {
+ ath6kl_sta_cleanup(ar, i);
+ removed = 1;
+ }
+ }
+ } else {
+ for (i = 0; i < AP_MAX_NUM_STA; i++) {
+ if (memcmp(ar->sta_list[i].mac, mac, ETH_ALEN) == 0) {
+ ath6kl_dbg(ATH6KL_DBG_TRC,
+ "deleting station %pM aid=%d reason=%d\n",
+ mac, ar->sta_list[i].aid, reason);
+ ath6kl_sta_cleanup(ar, i);
+ removed = 1;
+ break;
+ }
+ }
+ }
+
+ return removed;
+}
+
+enum htc_endpoint_id ath6kl_ac2_endpoint_id(void *devt, u8 ac)
+{
+ struct ath6kl *ar = devt;
+ return ar->ac2ep_map[ac];
+}
+
+struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar)
+{
+ struct ath6kl_cookie *cookie;
+
+ cookie = ar->cookie_list;
+ if (cookie != NULL) {
+ ar->cookie_list = cookie->arc_list_next;
+ ar->cookie_count--;
+ }
+
+ return cookie;
+}
+
+void ath6kl_cookie_init(struct ath6kl *ar)
+{
+ u32 i;
+
+ ar->cookie_list = NULL;
+ ar->cookie_count = 0;
+
+ memset(ar->cookie_mem, 0, sizeof(ar->cookie_mem));
+
+ for (i = 0; i < MAX_COOKIE_NUM; i++)
+ ath6kl_free_cookie(ar, &ar->cookie_mem[i]);
+}
+
+void ath6kl_cookie_cleanup(struct ath6kl *ar)
+{
+ ar->cookie_list = NULL;
+ ar->cookie_count = 0;
+}
+
+void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie)
+{
+ /* Insert first */
+
+ if (!ar || !cookie)
+ return;
+
+ cookie->arc_list_next = ar->cookie_list;
+ ar->cookie_list = cookie;
+ ar->cookie_count++;
+}
+
+/* set the window address register (using 4-byte register access ). */
+static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
+{
+ int status;
+ s32 i;
+ __le32 addr_val;
+
+ /*
+ * Write bytes 1,2,3 of the register to set the upper address bytes,
+ * the LSB is written last to initiate the access cycle
+ */
+
+ for (i = 1; i <= 3; i++) {
+ /*
+ * Fill the buffer with the address byte value we want to
+ * hit 4 times. No need to worry about endianness as the
+ * same byte is copied to all four bytes of addr_val at
+ * any time.
+ */
+ memset((u8 *)&addr_val, ((u8 *)&addr)[i], 4);
+
+ /*
+ * Hit each byte of the register address with a 4-byte
+ * write operation to the same address, this is a harmless
+ * operation.
+ */
+ status = hif_read_write_sync(ar, reg_addr + i, (u8 *)&addr_val,
+ 4, HIF_WR_SYNC_BYTE_FIX);
+ if (status)
+ break;
+ }
+
+ if (status) {
+ ath6kl_err("failed to write initial bytes of 0x%x to window reg: 0x%X\n",
+ addr, reg_addr);
+ return status;
+ }
+
+ /*
+ * Write the address register again, this time write the whole
+ * 4-byte value. The effect here is that the LSB write causes the
+ * cycle to start, the extra 3 byte write to bytes 1,2,3 has no
+ * effect since we are writing the same values again
+ */
+ addr_val = cpu_to_le32(addr);
+ status = hif_read_write_sync(ar, reg_addr,
+ (u8 *)&(addr_val),
+ 4, HIF_WR_SYNC_BYTE_INC);
+
+ if (status) {
+ ath6kl_err("failed to write 0x%x to window reg: 0x%X\n",
+ addr, reg_addr);
+ return status;
+ }
+
+ return 0;
+}
+
+/*
+ * Read from the hardware through its diagnostic window. No cooperation
+ * from the firmware is required for this.
+ */
+int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value)
+{
+ int ret;
+
+ /* set window register to start read cycle */
+ ret = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, address);
+ if (ret)
+ return ret;
+
+ /* read the data */
+ ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) value,
+ sizeof(*value), HIF_RD_SYNC_BYTE_INC);
+ if (ret) {
+ ath6kl_warn("failed to read32 through diagnose window: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Write to the ATH6KL through its diagnostic window. No cooperation from
+ * the Target is required for this.
+ */
+int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value)
+{
+ int ret;
+
+ /* set write data */
+ ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) &value,
+ sizeof(value), HIF_WR_SYNC_BYTE_INC);
+ if (ret) {
+ ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n",
+ address, value);
+ return ret;
+ }
+
+ /* set window register, which starts the write cycle */
+ return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS,
+ address);
+}
+
+int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length)
+{
+ u32 count, *buf = data;
+ int ret;
+
+ if (WARN_ON(length % 4))
+ return -EINVAL;
+
+ for (count = 0; count < length / 4; count++, address += 4) {
+ ret = ath6kl_diag_read32(ar, address, &buf[count]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int ath6kl_diag_write(struct ath6kl *ar, u32 address, void *data, u32 length)
+{
+ u32 count;
+ __le32 *buf = data;
+ int ret;
+
+ if (WARN_ON(length % 4))
+ return -EINVAL;
+
+ for (count = 0; count < length / 4; count++, address += 4) {
+ ret = ath6kl_diag_write32(ar, address, buf[count]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int ath6kl_read_fwlogs(struct ath6kl *ar)
+{
+ struct ath6kl_dbglog_hdr debug_hdr;
+ struct ath6kl_dbglog_buf debug_buf;
+ u32 address, length, dropped, firstbuf, debug_hdr_addr;
+ int ret = 0, loop;
+ u8 *buf;
+
+ buf = kmalloc(ATH6KL_FWLOG_PAYLOAD_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ address = TARG_VTOP(ar->target_type,
+ ath6kl_get_hi_item_addr(ar,
+ HI_ITEM(hi_dbglog_hdr)));
+
+ ret = ath6kl_diag_read32(ar, address, &debug_hdr_addr);
+ if (ret)
+ goto out;
+
+ /* Get the contents of the ring buffer */
+ if (debug_hdr_addr == 0) {
+ ath6kl_warn("Invalid address for debug_hdr_addr\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ address = TARG_VTOP(ar->target_type, debug_hdr_addr);
+ ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr));
+
+ 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));
+
+ loop = 100;
+
+ do {
+ address = TARG_VTOP(ar->target_type,
+ le32_to_cpu(debug_buf.buffer_addr));
+ length = le32_to_cpu(debug_buf.length);
+
+ if (length != 0 && (le32_to_cpu(debug_buf.length) <=
+ le32_to_cpu(debug_buf.bufsize))) {
+ length = ALIGN(length, 4);
+
+ ret = ath6kl_diag_read(ar, address,
+ buf, length);
+ if (ret)
+ goto out;
+
+ ath6kl_debug_fwlog_event(ar, buf, length);
+ }
+
+ address = TARG_VTOP(ar->target_type,
+ le32_to_cpu(debug_buf.next));
+ ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
+ if (ret)
+ goto out;
+
+ loop--;
+
+ if (WARN_ON(loop == 0)) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ } while (address != firstbuf);
+
+out:
+ kfree(buf);
+
+ return ret;
+}
+
+/* FIXME: move to a better place, target.h? */
+#define AR6003_RESET_CONTROL_ADDRESS 0x00004000
+#define AR6004_RESET_CONTROL_ADDRESS 0x00004000
+
+static void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
+ bool wait_fot_compltn, bool cold_reset)
+{
+ int status = 0;
+ u32 address;
+ __le32 data;
+
+ if (target_type != TARGET_TYPE_AR6003 &&
+ target_type != TARGET_TYPE_AR6004)
+ return;
+
+ data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) :
+ cpu_to_le32(RESET_CONTROL_MBOX_RST);
+
+ switch (target_type) {
+ case TARGET_TYPE_AR6003:
+ address = AR6003_RESET_CONTROL_ADDRESS;
+ break;
+ case TARGET_TYPE_AR6004:
+ address = AR6004_RESET_CONTROL_ADDRESS;
+ break;
+ default:
+ address = AR6003_RESET_CONTROL_ADDRESS;
+ break;
+ }
+
+ status = ath6kl_diag_write32(ar, address, data);
+
+ if (status)
+ ath6kl_err("failed to reset target\n");
+}
+
+void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile,
+ bool get_dbglogs)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ bool discon_issued;
+
+ netif_stop_queue(dev);
+
+ /* disable the target and the interrupts associated with it */
+ if (test_bit(WMI_READY, &ar->flag)) {
+ discon_issued = (test_bit(CONNECTED, &ar->flag) ||
+ test_bit(CONNECT_PEND, &ar->flag));
+ ath6kl_disconnect(ar);
+ if (!keep_profile)
+ ath6kl_init_profile_info(ar);
+
+ del_timer(&ar->disconnect_timer);
+
+ clear_bit(WMI_READY, &ar->flag);
+ ath6kl_wmi_shutdown(ar->wmi);
+ clear_bit(WMI_ENABLED, &ar->flag);
+ ar->wmi = NULL;
+
+ /*
+ * After wmi_shudown all WMI events will be dropped. We
+ * need to cleanup the buffers allocated in AP mode and
+ * give disconnect notification to stack, which usually
+ * happens in the disconnect_event. Simulate the disconnect
+ * event by calling the function directly. Sometimes
+ * disconnect_event will be received when the debug logs
+ * are collected.
+ */
+ if (discon_issued)
+ ath6kl_disconnect_event(ar, DISCONNECT_CMD,
+ (ar->nw_type & AP_NETWORK) ?
+ bcast_mac : ar->bssid,
+ 0, NULL, 0);
+
+ ar->user_key_ctrl = 0;
+
+ } else {
+ ath6kl_dbg(ATH6KL_DBG_TRC,
+ "%s: wmi is not ready 0x%p 0x%p\n",
+ __func__, ar, ar->wmi);
+
+ /* Shut down WMI if we have started it */
+ if (test_bit(WMI_ENABLED, &ar->flag)) {
+ ath6kl_dbg(ATH6KL_DBG_TRC,
+ "%s: shut down wmi\n", __func__);
+ ath6kl_wmi_shutdown(ar->wmi);
+ clear_bit(WMI_ENABLED, &ar->flag);
+ ar->wmi = NULL;
+ }
+ }
+
+ if (ar->htc_target) {
+ ath6kl_dbg(ATH6KL_DBG_TRC, "%s: shut down htc\n", __func__);
+ ath6kl_htc_stop(ar->htc_target);
+ }
+
+ /*
+ * Try to reset the device if we can. The driver may have been
+ * configure NOT to reset the target during a debug session.
+ */
+ ath6kl_dbg(ATH6KL_DBG_TRC,
+ "attempting to reset target on instance destroy\n");
+ ath6kl_reset_device(ar, ar->target_type, true, true);
+}
+
+static void ath6kl_install_static_wep_keys(struct ath6kl *ar)
+{
+ u8 index;
+ u8 keyusage;
+
+ for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
+ if (ar->wep_key_list[index].key_len) {
+ keyusage = GROUP_USAGE;
+ if (index == ar->def_txkey_index)
+ keyusage |= TX_USAGE;
+
+ ath6kl_wmi_addkey_cmd(ar->wmi,
+ index,
+ WEP_CRYPT,
+ keyusage,
+ ar->wep_key_list[index].key_len,
+ NULL,
+ ar->wep_key_list[index].key,
+ KEY_OP_INIT_VAL, NULL,
+ NO_SYNC_WMIFLAG);
+ }
+ }
+}
+
+void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel)
+{
+ struct ath6kl_req_key *ik;
+ int res;
+ u8 key_rsc[ATH6KL_KEY_SEQ_LEN];
+
+ ik = &ar->ap_mode_bkey;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", channel);
+
+ switch (ar->auth_mode) {
+ case NONE_AUTH:
+ if (ar->prwise_crypto == WEP_CRYPT)
+ ath6kl_install_static_wep_keys(ar);
+ break;
+ case WPA_PSK_AUTH:
+ case WPA2_PSK_AUTH:
+ case (WPA_PSK_AUTH | WPA2_PSK_AUTH):
+ if (!ik->valid)
+ break;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for "
+ "the initial group key for AP mode\n");
+ memset(key_rsc, 0, sizeof(key_rsc));
+ res = ath6kl_wmi_addkey_cmd(
+ ar->wmi, ik->key_index, ik->key_type,
+ GROUP_USAGE, ik->key_len, key_rsc, ik->key,
+ KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);
+ if (res) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed "
+ "addkey failed: %d\n", res);
+ }
+ break;
+ }
+
+ ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
+ set_bit(CONNECTED, &ar->flag);
+ netif_carrier_on(ar->net_dev);
+}
+
+void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
+ u8 keymgmt, u8 ucipher, u8 auth,
+ u8 assoc_req_len, u8 *assoc_info)
+{
+ u8 *ies = NULL, *wpa_ie = NULL, *pos;
+ size_t ies_len = 0;
+ struct station_info sinfo;
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", mac_addr, aid);
+
+ if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) {
+ struct ieee80211_mgmt *mgmt =
+ (struct ieee80211_mgmt *) assoc_info;
+ if (ieee80211_is_assoc_req(mgmt->frame_control) &&
+ assoc_req_len >= sizeof(struct ieee80211_hdr_3addr) +
+ sizeof(mgmt->u.assoc_req)) {
+ ies = mgmt->u.assoc_req.variable;
+ ies_len = assoc_info + assoc_req_len - ies;
+ } else if (ieee80211_is_reassoc_req(mgmt->frame_control) &&
+ assoc_req_len >= sizeof(struct ieee80211_hdr_3addr)
+ + sizeof(mgmt->u.reassoc_req)) {
+ ies = mgmt->u.reassoc_req.variable;
+ ies_len = assoc_info + assoc_req_len - ies;
+ }
+ }
+
+ pos = ies;
+ while (pos && pos + 1 < ies + ies_len) {
+ if (pos + 2 + pos[1] > ies + ies_len)
+ break;
+ if (pos[0] == WLAN_EID_RSN)
+ wpa_ie = pos; /* RSN IE */
+ else if (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
+ pos[1] >= 4 &&
+ pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xf2) {
+ if (pos[5] == 0x01)
+ wpa_ie = pos; /* WPA IE */
+ else if (pos[5] == 0x04) {
+ wpa_ie = pos; /* WPS IE */
+ break; /* overrides WPA/RSN IE */
+ }
+ }
+ pos += 2 + pos[1];
+ }
+
+ ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie,
+ wpa_ie ? 2 + wpa_ie[1] : 0,
+ keymgmt, ucipher, auth);
+
+ /* send event to application */
+ memset(&sinfo, 0, sizeof(sinfo));
+
+ /* TODO: sinfo.generation */
+
+ sinfo.assoc_req_ies = ies;
+ sinfo.assoc_req_ies_len = ies_len;
+ sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
+
+ cfg80211_new_sta(ar->net_dev, mac_addr, &sinfo, GFP_KERNEL);
+
+ netif_wake_queue(ar->net_dev);
+}
+
+/* Functions for Tx credit handling */
+void ath6k_credit_init(struct htc_credit_state_info *cred_info,
+ struct list_head *ep_list,
+ int tot_credits)
+{
+ struct htc_endpoint_credit_dist *cur_ep_dist;
+ int count;
+
+ cred_info->cur_free_credits = tot_credits;
+ cred_info->total_avail_credits = tot_credits;
+
+ list_for_each_entry(cur_ep_dist, ep_list, list) {
+ if (cur_ep_dist->endpoint == ENDPOINT_0)
+ continue;
+
+ cur_ep_dist->cred_min = cur_ep_dist->cred_per_msg;
+
+ if (tot_credits > 4)
+ if ((cur_ep_dist->svc_id == WMI_DATA_BK_SVC) ||
+ (cur_ep_dist->svc_id == WMI_DATA_BE_SVC)) {
+ ath6kl_deposit_credit_to_ep(cred_info,
+ cur_ep_dist,
+ cur_ep_dist->cred_min);
+ cur_ep_dist->dist_flags |= HTC_EP_ACTIVE;
+ }
+
+ if (cur_ep_dist->svc_id == WMI_CONTROL_SVC) {
+ ath6kl_deposit_credit_to_ep(cred_info, cur_ep_dist,
+ cur_ep_dist->cred_min);
+ /*
+ * Control service is always marked active, it
+ * never goes inactive EVER.
+ */
+ cur_ep_dist->dist_flags |= HTC_EP_ACTIVE;
+ } else if (cur_ep_dist->svc_id == WMI_DATA_BK_SVC)
+ /* this is the lowest priority data endpoint */
+ cred_info->lowestpri_ep_dist = cur_ep_dist->list;
+
+ /*
+ * Streams have to be created (explicit | implicit) for all
+ * kinds of traffic. BE endpoints are also inactive in the
+ * beginning. When BE traffic starts it creates implicit
+ * streams that redistributes credits.
+ *
+ * Note: all other endpoints have minimums set but are
+ * initially given NO credits. credits will be distributed
+ * as traffic activity demands
+ */
+ }
+
+ WARN_ON(cred_info->cur_free_credits <= 0);
+
+ list_for_each_entry(cur_ep_dist, ep_list, list) {
+ if (cur_ep_dist->endpoint == ENDPOINT_0)
+ continue;
+
+ if (cur_ep_dist->svc_id == WMI_CONTROL_SVC)
+ cur_ep_dist->cred_norm = cur_ep_dist->cred_per_msg;
+ else {
+ /*
+ * For the remaining data endpoints, we assume that
+ * each cred_per_msg are the same. We use a simple
+ * calculation here, we take the remaining credits
+ * and determine how many max messages this can
+ * cover and then set each endpoint's normal value
+ * equal to 3/4 this amount.
+ */
+ count = (cred_info->cur_free_credits /
+ cur_ep_dist->cred_per_msg)
+ * cur_ep_dist->cred_per_msg;
+ count = (count * 3) >> 2;
+ count = max(count, cur_ep_dist->cred_per_msg);
+ cur_ep_dist->cred_norm = count;
+
+ }
+ }
+}
+
+/* initialize and setup credit distribution */
+int ath6k_setup_credit_dist(void *htc_handle,
+ struct htc_credit_state_info *cred_info)
+{
+ u16 servicepriority[5];
+
+ memset(cred_info, 0, sizeof(struct htc_credit_state_info));
+
+ servicepriority[0] = WMI_CONTROL_SVC; /* highest */
+ servicepriority[1] = WMI_DATA_VO_SVC;
+ servicepriority[2] = WMI_DATA_VI_SVC;
+ servicepriority[3] = WMI_DATA_BE_SVC;
+ servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */
+
+ /* set priority list */
+ ath6kl_htc_set_credit_dist(htc_handle, cred_info, servicepriority, 5);
+
+ return 0;
+}
+
+/* reduce an ep's credits back to a set limit */
+static void ath6k_reduce_credits(struct htc_credit_state_info *cred_info,
+ struct htc_endpoint_credit_dist *ep_dist,
+ int limit)
+{
+ int credits;
+
+ ep_dist->cred_assngd = limit;
+
+ if (ep_dist->credits <= limit)
+ return;
+
+ credits = ep_dist->credits - limit;
+ ep_dist->credits -= credits;
+ cred_info->cur_free_credits += credits;
+}
+
+static void ath6k_credit_update(struct htc_credit_state_info *cred_info,
+ struct list_head *epdist_list)
+{
+ struct htc_endpoint_credit_dist *cur_dist_list;
+
+ list_for_each_entry(cur_dist_list, epdist_list, list) {
+ if (cur_dist_list->endpoint == ENDPOINT_0)
+ continue;
+
+ if (cur_dist_list->cred_to_dist > 0) {
+ cur_dist_list->credits +=
+ cur_dist_list->cred_to_dist;
+ cur_dist_list->cred_to_dist = 0;
+ if (cur_dist_list->credits >
+ cur_dist_list->cred_assngd)
+ ath6k_reduce_credits(cred_info,
+ cur_dist_list,
+ cur_dist_list->cred_assngd);
+
+ if (cur_dist_list->credits >
+ cur_dist_list->cred_norm)
+ ath6k_reduce_credits(cred_info, cur_dist_list,
+ cur_dist_list->cred_norm);
+
+ if (!(cur_dist_list->dist_flags & HTC_EP_ACTIVE)) {
+ if (cur_dist_list->txq_depth == 0)
+ ath6k_reduce_credits(cred_info,
+ cur_dist_list, 0);
+ }
+ }
+ }
+}
+
+/*
+ * HTC has an endpoint that needs credits, ep_dist is the endpoint in
+ * question.
+ */
+void ath6k_seek_credits(struct htc_credit_state_info *cred_info,
+ struct htc_endpoint_credit_dist *ep_dist)
+{
+ struct htc_endpoint_credit_dist *curdist_list;
+ int credits = 0;
+ int need;
+
+ if (ep_dist->svc_id == WMI_CONTROL_SVC)
+ goto out;
+
+ if ((ep_dist->svc_id == WMI_DATA_VI_SVC) ||
+ (ep_dist->svc_id == WMI_DATA_VO_SVC))
+ if ((ep_dist->cred_assngd >= ep_dist->cred_norm))
+ goto out;
+
+ /*
+ * For all other services, we follow a simple algorithm of:
+ *
+ * 1. checking the free pool for credits
+ * 2. checking lower priority endpoints for credits to take
+ */
+
+ credits = min(cred_info->cur_free_credits, ep_dist->seek_cred);
+
+ if (credits >= ep_dist->seek_cred)
+ goto out;
+
+ /*
+ * We don't have enough in the free pool, try taking away from
+ * lower priority services The rule for taking away credits:
+ *
+ * 1. Only take from lower priority endpoints
+ * 2. Only take what is allocated above the minimum (never
+ * starve an endpoint completely)
+ * 3. Only take what you need.
+ */
+
+ list_for_each_entry_reverse(curdist_list,
+ &cred_info->lowestpri_ep_dist,
+ list) {
+ if (curdist_list == ep_dist)
+ break;
+
+ need = ep_dist->seek_cred - cred_info->cur_free_credits;
+
+ if ((curdist_list->cred_assngd - need) >=
+ curdist_list->cred_min) {
+ /*
+ * The current one has been allocated more than
+ * it's minimum and it has enough credits assigned
+ * above it's minimum to fulfill our need try to
+ * take away just enough to fulfill our need.
+ */
+ ath6k_reduce_credits(cred_info, curdist_list,
+ curdist_list->cred_assngd - need);
+
+ if (cred_info->cur_free_credits >=
+ ep_dist->seek_cred)
+ break;
+ }
+
+ if (curdist_list->endpoint == ENDPOINT_0)
+ break;
+ }
+
+ credits = min(cred_info->cur_free_credits, ep_dist->seek_cred);
+
+out:
+ /* did we find some credits? */
+ if (credits)
+ ath6kl_deposit_credit_to_ep(cred_info, ep_dist, credits);
+
+ ep_dist->seek_cred = 0;
+}
+
+/* redistribute credits based on activity change */
+static void ath6k_redistribute_credits(struct htc_credit_state_info *info,
+ struct list_head *ep_dist_list)
+{
+ struct htc_endpoint_credit_dist *curdist_list;
+
+ list_for_each_entry(curdist_list, ep_dist_list, list) {
+ if (curdist_list->endpoint == ENDPOINT_0)
+ continue;
+
+ if ((curdist_list->svc_id == WMI_DATA_BK_SVC) ||
+ (curdist_list->svc_id == WMI_DATA_BE_SVC))
+ curdist_list->dist_flags |= HTC_EP_ACTIVE;
+
+ if ((curdist_list->svc_id != WMI_CONTROL_SVC) &&
+ !(curdist_list->dist_flags & HTC_EP_ACTIVE)) {
+ if (curdist_list->txq_depth == 0)
+ ath6k_reduce_credits(info,
+ curdist_list, 0);
+ else
+ ath6k_reduce_credits(info,
+ curdist_list,
+ curdist_list->cred_min);
+ }
+ }
+}
+
+/*
+ *
+ * This function is invoked whenever endpoints require credit
+ * distributions. A lock is held while this function is invoked, this
+ * function shall NOT block. The ep_dist_list is a list of distribution
+ * structures in prioritized order as defined by the call to the
+ * htc_set_credit_dist() api.
+ */
+void ath6k_credit_distribute(struct htc_credit_state_info *cred_info,
+ struct list_head *ep_dist_list,
+ enum htc_credit_dist_reason reason)
+{
+ switch (reason) {
+ case HTC_CREDIT_DIST_SEND_COMPLETE:
+ ath6k_credit_update(cred_info, ep_dist_list);
+ break;
+ case HTC_CREDIT_DIST_ACTIVITY_CHANGE:
+ ath6k_redistribute_credits(cred_info, ep_dist_list);
+ break;
+ default:
+ break;
+ }
+
+ WARN_ON(cred_info->cur_free_credits > cred_info->total_avail_credits);
+ WARN_ON(cred_info->cur_free_credits < 0);
+}
+
+void disconnect_timer_handler(unsigned long ptr)
+{
+ struct net_device *dev = (struct net_device *)ptr;
+ struct ath6kl *ar = ath6kl_priv(dev);
+
+ ath6kl_init_profile_info(ar);
+ ath6kl_disconnect(ar);
+}
+
+void ath6kl_disconnect(struct ath6kl *ar)
+{
+ if (test_bit(CONNECTED, &ar->flag) ||
+ test_bit(CONNECT_PEND, &ar->flag)) {
+ ath6kl_wmi_disconnect_cmd(ar->wmi);
+ /*
+ * Disconnect command is issued, clear the connect pending
+ * flag. The connected flag will be cleared in
+ * disconnect event notification.
+ */
+ clear_bit(CONNECT_PEND, &ar->flag);
+ }
+}
+
+void ath6kl_deep_sleep_enable(struct ath6kl *ar)
+{
+ switch (ar->sme_state) {
+ case SME_CONNECTING:
+ cfg80211_connect_result(ar->net_dev, ar->bssid, NULL, 0,
+ NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
+ break;
+ case SME_CONNECTED:
+ default:
+ /*
+ * FIXME: oddly enough smeState is in DISCONNECTED during
+ * suspend, why? Need to send disconnected event in that
+ * state.
+ */
+ cfg80211_disconnected(ar->net_dev, 0, NULL, 0, GFP_KERNEL);
+ break;
+ }
+
+ if (test_bit(CONNECTED, &ar->flag) ||
+ test_bit(CONNECT_PEND, &ar->flag))
+ ath6kl_wmi_disconnect_cmd(ar->wmi);
+
+ ar->sme_state = SME_DISCONNECTED;
+
+ /* disable scanning */
+ if (ath6kl_wmi_scanparams_cmd(ar->wmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0) != 0)
+ printk(KERN_WARNING "ath6kl: failed to disable scan "
+ "during suspend\n");
+
+ ath6kl_cfg80211_scan_complete_event(ar, -ECANCELED);
+}
+
+/* WMI Event handlers */
+
+static const char *get_hw_id_string(u32 id)
+{
+ switch (id) {
+ case AR6003_REV1_VERSION:
+ return "1.0";
+ case AR6003_REV2_VERSION:
+ return "2.0";
+ case AR6003_REV3_VERSION:
+ return "2.1.1";
+ default:
+ return "unknown";
+ }
+}
+
+void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
+{
+ struct ath6kl *ar = devt;
+ struct net_device *dev = ar->net_dev;
+
+ memcpy(dev->dev_addr, datap, ETH_ALEN);
+ ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n",
+ __func__, dev->dev_addr);
+
+ ar->version.wlan_ver = sw_ver;
+ ar->version.abi_ver = abi_ver;
+
+ snprintf(ar->wdev->wiphy->fw_version,
+ sizeof(ar->wdev->wiphy->fw_version),
+ "%u.%u.%u.%u",
+ (ar->version.wlan_ver & 0xf0000000) >> 28,
+ (ar->version.wlan_ver & 0x0f000000) >> 24,
+ (ar->version.wlan_ver & 0x00ff0000) >> 16,
+ (ar->version.wlan_ver & 0x0000ffff));
+
+ /* indicate to the waiting thread that the ready event was received */
+ set_bit(WMI_READY, &ar->flag);
+ wake_up(&ar->event_wq);
+
+ ath6kl_info("hw %s fw %s%s\n",
+ get_hw_id_string(ar->wdev->wiphy->hw_version),
+ ar->wdev->wiphy->fw_version,
+ test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
+}
+
+void ath6kl_scan_complete_evt(struct ath6kl *ar, int status)
+{
+ ath6kl_cfg80211_scan_complete_event(ar, status);
+
+ if (!ar->usr_bss_filter) {
+ clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
+ ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_SCAN, "scan complete: %d\n", status);
+}
+
+void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
+ u16 listen_int, u16 beacon_int,
+ enum network_type net_type, u8 beacon_ie_len,
+ u8 assoc_req_len, u8 assoc_resp_len,
+ u8 *assoc_info)
+{
+ unsigned long flags;
+
+ ath6kl_cfg80211_connect_event(ar, channel, bssid,
+ listen_int, beacon_int,
+ net_type, beacon_ie_len,
+ assoc_req_len, assoc_resp_len,
+ assoc_info);
+
+ memcpy(ar->bssid, bssid, sizeof(ar->bssid));
+ ar->bss_ch = channel;
+
+ if ((ar->nw_type == INFRA_NETWORK))
+ ath6kl_wmi_listeninterval_cmd(ar->wmi, ar->listen_intvl_t,
+ ar->listen_intvl_b);
+
+ netif_wake_queue(ar->net_dev);
+
+ /* Update connect & link status atomically */
+ spin_lock_irqsave(&ar->lock, flags);
+ set_bit(CONNECTED, &ar->flag);
+ clear_bit(CONNECT_PEND, &ar->flag);
+ netif_carrier_on(ar->net_dev);
+ spin_unlock_irqrestore(&ar->lock, flags);
+
+ aggr_reset_state(ar->aggr_cntxt);
+ ar->reconnect_flag = 0;
+
+ if ((ar->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) {
+ memset(ar->node_map, 0, sizeof(ar->node_map));
+ ar->node_num = 0;
+ ar->next_ep_id = ENDPOINT_2;
+ }
+
+ if (!ar->usr_bss_filter) {
+ set_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
+ ath6kl_wmi_bssfilter_cmd(ar->wmi, CURRENT_BSS_FILTER, 0);
+ }
+}
+
+void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast)
+{
+ struct ath6kl_sta *sta;
+ u8 tsc[6];
+ /*
+ * For AP case, keyid will have aid of STA which sent pkt with
+ * MIC error. Use this aid to get MAC & send it to hostapd.
+ */
+ if (ar->nw_type == AP_NETWORK) {
+ sta = ath6kl_find_sta_by_aid(ar, (keyid >> 2));
+ if (!sta)
+ return;
+
+ ath6kl_dbg(ATH6KL_DBG_TRC,
+ "ap tkip mic error received from aid=%d\n", keyid);
+
+ memset(tsc, 0, sizeof(tsc)); /* FIX: get correct TSC */
+ cfg80211_michael_mic_failure(ar->net_dev, sta->mac,
+ NL80211_KEYTYPE_PAIRWISE, keyid,
+ tsc, GFP_KERNEL);
+ } else
+ ath6kl_cfg80211_tkip_micerr_event(ar, keyid, ismcast);
+
+}
+
+static void ath6kl_update_target_stats(struct ath6kl *ar, u8 *ptr, u32 len)
+{
+ struct wmi_target_stats *tgt_stats =
+ (struct wmi_target_stats *) ptr;
+ struct target_stats *stats = &ar->target_stats;
+ struct tkip_ccmp_stats *ccmp_stats;
+ u8 ac;
+
+ if (len < sizeof(*tgt_stats))
+ return;
+
+ ath6kl_dbg(ATH6KL_DBG_TRC, "updating target stats\n");
+
+ stats->tx_pkt += le32_to_cpu(tgt_stats->stats.tx.pkt);
+ stats->tx_byte += le32_to_cpu(tgt_stats->stats.tx.byte);
+ stats->tx_ucast_pkt += le32_to_cpu(tgt_stats->stats.tx.ucast_pkt);
+ stats->tx_ucast_byte += le32_to_cpu(tgt_stats->stats.tx.ucast_byte);
+ stats->tx_mcast_pkt += le32_to_cpu(tgt_stats->stats.tx.mcast_pkt);
+ stats->tx_mcast_byte += le32_to_cpu(tgt_stats->stats.tx.mcast_byte);
+ stats->tx_bcast_pkt += le32_to_cpu(tgt_stats->stats.tx.bcast_pkt);
+ stats->tx_bcast_byte += le32_to_cpu(tgt_stats->stats.tx.bcast_byte);
+ stats->tx_rts_success_cnt +=
+ le32_to_cpu(tgt_stats->stats.tx.rts_success_cnt);
+
+ for (ac = 0; ac < WMM_NUM_AC; ac++)
+ stats->tx_pkt_per_ac[ac] +=
+ le32_to_cpu(tgt_stats->stats.tx.pkt_per_ac[ac]);
+
+ stats->tx_err += le32_to_cpu(tgt_stats->stats.tx.err);
+ stats->tx_fail_cnt += le32_to_cpu(tgt_stats->stats.tx.fail_cnt);
+ stats->tx_retry_cnt += le32_to_cpu(tgt_stats->stats.tx.retry_cnt);
+ stats->tx_mult_retry_cnt +=
+ le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt);
+ stats->tx_rts_fail_cnt +=
+ le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt);
+ stats->tx_ucast_rate =
+ ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate));
+
+ stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt);
+ stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte);
+ stats->rx_ucast_pkt += le32_to_cpu(tgt_stats->stats.rx.ucast_pkt);
+ stats->rx_ucast_byte += le32_to_cpu(tgt_stats->stats.rx.ucast_byte);
+ stats->rx_mcast_pkt += le32_to_cpu(tgt_stats->stats.rx.mcast_pkt);
+ stats->rx_mcast_byte += le32_to_cpu(tgt_stats->stats.rx.mcast_byte);
+ stats->rx_bcast_pkt += le32_to_cpu(tgt_stats->stats.rx.bcast_pkt);
+ stats->rx_bcast_byte += le32_to_cpu(tgt_stats->stats.rx.bcast_byte);
+ stats->rx_frgment_pkt += le32_to_cpu(tgt_stats->stats.rx.frgment_pkt);
+ stats->rx_err += le32_to_cpu(tgt_stats->stats.rx.err);
+ stats->rx_crc_err += le32_to_cpu(tgt_stats->stats.rx.crc_err);
+ stats->rx_key_cache_miss +=
+ le32_to_cpu(tgt_stats->stats.rx.key_cache_miss);
+ stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err);
+ stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame);
+ stats->rx_ucast_rate =
+ ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate));
+
+ ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats;
+
+ stats->tkip_local_mic_fail +=
+ le32_to_cpu(ccmp_stats->tkip_local_mic_fail);
+ stats->tkip_cnter_measures_invoked +=
+ le32_to_cpu(ccmp_stats->tkip_cnter_measures_invoked);
+ stats->tkip_fmt_err += le32_to_cpu(ccmp_stats->tkip_fmt_err);
+
+ stats->ccmp_fmt_err += le32_to_cpu(ccmp_stats->ccmp_fmt_err);
+ stats->ccmp_replays += le32_to_cpu(ccmp_stats->ccmp_replays);
+
+ stats->pwr_save_fail_cnt +=
+ le32_to_cpu(tgt_stats->pm_stats.pwr_save_failure_cnt);
+ stats->noise_floor_calib =
+ a_sle32_to_cpu(tgt_stats->noise_floor_calib);
+
+ stats->cs_bmiss_cnt +=
+ le32_to_cpu(tgt_stats->cserv_stats.cs_bmiss_cnt);
+ stats->cs_low_rssi_cnt +=
+ le32_to_cpu(tgt_stats->cserv_stats.cs_low_rssi_cnt);
+ stats->cs_connect_cnt +=
+ le16_to_cpu(tgt_stats->cserv_stats.cs_connect_cnt);
+ stats->cs_discon_cnt +=
+ le16_to_cpu(tgt_stats->cserv_stats.cs_discon_cnt);
+
+ stats->cs_ave_beacon_rssi =
+ a_sle16_to_cpu(tgt_stats->cserv_stats.cs_ave_beacon_rssi);
+
+ stats->cs_last_roam_msec =
+ tgt_stats->cserv_stats.cs_last_roam_msec;
+ stats->cs_snr = tgt_stats->cserv_stats.cs_snr;
+ stats->cs_rssi = a_sle16_to_cpu(tgt_stats->cserv_stats.cs_rssi);
+
+ stats->lq_val = le32_to_cpu(tgt_stats->lq_val);
+
+ stats->wow_pkt_dropped +=
+ le32_to_cpu(tgt_stats->wow_stats.wow_pkt_dropped);
+ stats->wow_host_pkt_wakeups +=
+ tgt_stats->wow_stats.wow_host_pkt_wakeups;
+ stats->wow_host_evt_wakeups +=
+ tgt_stats->wow_stats.wow_host_evt_wakeups;
+ stats->wow_evt_discarded +=
+ le16_to_cpu(tgt_stats->wow_stats.wow_evt_discarded);
+
+ if (test_bit(STATS_UPDATE_PEND, &ar->flag)) {
+ clear_bit(STATS_UPDATE_PEND, &ar->flag);
+ wake_up(&ar->event_wq);
+ }
+}
+
+static void ath6kl_add_le32(__le32 *var, __le32 val)
+{
+ *var = cpu_to_le32(le32_to_cpu(*var) + le32_to_cpu(val));
+}
+
+void ath6kl_tgt_stats_event(struct ath6kl *ar, u8 *ptr, u32 len)
+{
+ struct wmi_ap_mode_stat *p = (struct wmi_ap_mode_stat *) ptr;
+ struct wmi_ap_mode_stat *ap = &ar->ap_stats;
+ struct wmi_per_sta_stat *st_ap, *st_p;
+ u8 ac;
+
+ if (ar->nw_type == AP_NETWORK) {
+ if (len < sizeof(*p))
+ return;
+
+ for (ac = 0; ac < AP_MAX_NUM_STA; ac++) {
+ st_ap = &ap->sta[ac];
+ st_p = &p->sta[ac];
+
+ ath6kl_add_le32(&st_ap->tx_bytes, st_p->tx_bytes);
+ ath6kl_add_le32(&st_ap->tx_pkts, st_p->tx_pkts);
+ ath6kl_add_le32(&st_ap->tx_error, st_p->tx_error);
+ ath6kl_add_le32(&st_ap->tx_discard, st_p->tx_discard);
+ ath6kl_add_le32(&st_ap->rx_bytes, st_p->rx_bytes);
+ ath6kl_add_le32(&st_ap->rx_pkts, st_p->rx_pkts);
+ ath6kl_add_le32(&st_ap->rx_error, st_p->rx_error);
+ ath6kl_add_le32(&st_ap->rx_discard, st_p->rx_discard);
+ }
+
+ } else {
+ ath6kl_update_target_stats(ar, ptr, len);
+ }
+}
+
+void ath6kl_wakeup_event(void *dev)
+{
+ struct ath6kl *ar = (struct ath6kl *) dev;
+
+ wake_up(&ar->event_wq);
+}
+
+void ath6kl_txpwr_rx_evt(void *devt, u8 tx_pwr)
+{
+ struct ath6kl *ar = (struct ath6kl *) devt;
+
+ ar->tx_pwr = tx_pwr;
+ wake_up(&ar->event_wq);
+}
+
+void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid)
+{
+ struct ath6kl_sta *conn;
+ struct sk_buff *skb;
+ bool psq_empty = false;
+
+ conn = ath6kl_find_sta_by_aid(ar, aid);
+
+ if (!conn)
+ return;
+ /*
+ * Send out a packet queued on ps queue. When the ps queue
+ * becomes empty update the PVB for this station.
+ */
+ spin_lock_bh(&conn->psq_lock);
+ psq_empty = skb_queue_empty(&conn->psq);
+ spin_unlock_bh(&conn->psq_lock);
+
+ if (psq_empty)
+ /* TODO: Send out a NULL data frame */
+ return;
+
+ spin_lock_bh(&conn->psq_lock);
+ skb = skb_dequeue(&conn->psq);
+ spin_unlock_bh(&conn->psq_lock);
+
+ conn->sta_flags |= STA_PS_POLLED;
+ ath6kl_data_tx(skb, ar->net_dev);
+ conn->sta_flags &= ~STA_PS_POLLED;
+
+ spin_lock_bh(&conn->psq_lock);
+ psq_empty = skb_queue_empty(&conn->psq);
+ spin_unlock_bh(&conn->psq_lock);
+
+ if (psq_empty)
+ ath6kl_wmi_set_pvb_cmd(ar->wmi, conn->aid, 0);
+}
+
+void ath6kl_dtimexpiry_event(struct ath6kl *ar)
+{
+ bool mcastq_empty = false;
+ struct sk_buff *skb;
+
+ /*
+ * If there are no associated STAs, ignore the DTIM expiry event.
+ * There can be potential race conditions where the last associated
+ * STA may disconnect & before the host could clear the 'Indicate
+ * DTIM' request to the firmware, the firmware would have just
+ * indicated a DTIM expiry event. The race is between 'clear DTIM
+ * expiry cmd' going from the host to the firmware & the DTIM
+ * expiry event happening from the firmware to the host.
+ */
+ if (!ar->sta_list_index)
+ return;
+
+ spin_lock_bh(&ar->mcastpsq_lock);
+ mcastq_empty = skb_queue_empty(&ar->mcastpsq);
+ spin_unlock_bh(&ar->mcastpsq_lock);
+
+ if (mcastq_empty)
+ return;
+
+ /* set the STA flag to dtim_expired for the frame to go out */
+ set_bit(DTIM_EXPIRED, &ar->flag);
+
+ spin_lock_bh(&ar->mcastpsq_lock);
+ while ((skb = skb_dequeue(&ar->mcastpsq)) != NULL) {
+ spin_unlock_bh(&ar->mcastpsq_lock);
+
+ ath6kl_data_tx(skb, ar->net_dev);
+
+ spin_lock_bh(&ar->mcastpsq_lock);
+ }
+ spin_unlock_bh(&ar->mcastpsq_lock);
+
+ clear_bit(DTIM_EXPIRED, &ar->flag);
+
+ /* clear the LSB of the BitMapCtl field of the TIM IE */
+ ath6kl_wmi_set_pvb_cmd(ar->wmi, MCAST_AID, 0);
+}
+
+void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
+ u8 assoc_resp_len, u8 *assoc_info,
+ u16 prot_reason_status)
+{
+ unsigned long flags;
+
+ if (ar->nw_type == AP_NETWORK) {
+ if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))
+ return;
+
+ /* if no more associated STAs, empty the mcast PS q */
+ if (ar->sta_list_index == 0) {
+ spin_lock_bh(&ar->mcastpsq_lock);
+ skb_queue_purge(&ar->mcastpsq);
+ spin_unlock_bh(&ar->mcastpsq_lock);
+
+ /* clear the LSB of the TIM IE's BitMapCtl field */
+ if (test_bit(WMI_READY, &ar->flag))
+ ath6kl_wmi_set_pvb_cmd(ar->wmi, MCAST_AID, 0);
+ }
+
+ if (!is_broadcast_ether_addr(bssid)) {
+ /* send event to application */
+ cfg80211_del_sta(ar->net_dev, bssid, GFP_KERNEL);
+ }
+
+ if (memcmp(ar->net_dev->dev_addr, bssid, ETH_ALEN) == 0) {
+ memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
+ clear_bit(CONNECTED, &ar->flag);
+ }
+ return;
+ }
+
+ ath6kl_cfg80211_disconnect_event(ar, reason, bssid,
+ assoc_resp_len, assoc_info,
+ prot_reason_status);
+
+ aggr_reset_state(ar->aggr_cntxt);
+
+ del_timer(&ar->disconnect_timer);
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_CONNECT,
+ "disconnect reason is %d\n", reason);
+
+ /*
+ * If the event is due to disconnect cmd from the host, only they
+ * the target would stop trying to connect. Under any other
+ * condition, target would keep trying to connect.
+ */
+ if (reason == DISCONNECT_CMD) {
+ if (!ar->usr_bss_filter && test_bit(WMI_READY, &ar->flag))
+ ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
+ } else {
+ set_bit(CONNECT_PEND, &ar->flag);
+ if (((reason == ASSOC_FAILED) &&
+ (prot_reason_status == 0x11)) ||
+ ((reason == ASSOC_FAILED) && (prot_reason_status == 0x0)
+ && (ar->reconnect_flag == 1))) {
+ set_bit(CONNECTED, &ar->flag);
+ return;
+ }
+ }
+
+ /* update connect & link status atomically */
+ spin_lock_irqsave(&ar->lock, flags);
+ clear_bit(CONNECTED, &ar->flag);
+ netif_carrier_off(ar->net_dev);
+ spin_unlock_irqrestore(&ar->lock, flags);
+
+ if ((reason != CSERV_DISCONNECT) || (ar->reconnect_flag != 1))
+ ar->reconnect_flag = 0;
+
+ if (reason != CSERV_DISCONNECT)
+ ar->user_key_ctrl = 0;
+
+ netif_stop_queue(ar->net_dev);
+ memset(ar->bssid, 0, sizeof(ar->bssid));
+ ar->bss_ch = 0;
+
+ ath6kl_tx_data_cleanup(ar);
+}
+
+static int ath6kl_open(struct net_device *dev)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ar->lock, flags);
+
+ set_bit(WLAN_ENABLED, &ar->flag);
+
+ if (test_bit(CONNECTED, &ar->flag)) {
+ netif_carrier_on(dev);
+ netif_wake_queue(dev);
+ } else
+ netif_carrier_off(dev);
+
+ spin_unlock_irqrestore(&ar->lock, flags);
+
+ return 0;
+}
+
+static int ath6kl_close(struct net_device *dev)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+
+ netif_stop_queue(dev);
+
+ ath6kl_disconnect(ar);
+
+ if (test_bit(WMI_READY, &ar->flag)) {
+ if (ath6kl_wmi_scanparams_cmd(ar->wmi, 0xFFFF, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0))
+ return -EIO;
+
+ clear_bit(WLAN_ENABLED, &ar->flag);
+ }
+
+ ath6kl_cfg80211_scan_complete_event(ar, -ECANCELED);
+
+ return 0;
+}
+
+static struct net_device_stats *ath6kl_get_stats(struct net_device *dev)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+
+ return &ar->net_stats;
+}
+
+static struct net_device_ops ath6kl_netdev_ops = {
+ .ndo_open = ath6kl_open,
+ .ndo_stop = ath6kl_close,
+ .ndo_start_xmit = ath6kl_data_tx,
+ .ndo_get_stats = ath6kl_get_stats,
+};
+
+void init_netdev(struct net_device *dev)
+{
+ dev->netdev_ops = &ath6kl_netdev_ops;
+ dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
+
+ dev->needed_headroom = ETH_HLEN;
+ dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) +
+ sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH
+ + WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES;
+
+ return;
+}
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
new file mode 100644
index 000000000000..f1dc311ee0c7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -0,0 +1,949 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sd.h>
+#include "htc_hif.h"
+#include "hif-ops.h"
+#include "target.h"
+#include "debug.h"
+#include "cfg80211.h"
+
+struct ath6kl_sdio {
+ struct sdio_func *func;
+
+ spinlock_t lock;
+
+ /* free list */
+ struct list_head bus_req_freeq;
+
+ /* available bus requests */
+ struct bus_request bus_req[BUS_REQUEST_MAX_NUM];
+
+ struct ath6kl *ar;
+ u8 *dma_buffer;
+
+ /* scatter request list head */
+ struct list_head scat_req;
+
+ spinlock_t scat_lock;
+ bool is_disabled;
+ atomic_t irq_handling;
+ const struct sdio_device_id *id;
+ struct work_struct wr_async_work;
+ struct list_head wr_asyncq;
+ spinlock_t wr_async_lock;
+};
+
+#define CMD53_ARG_READ 0
+#define CMD53_ARG_WRITE 1
+#define CMD53_ARG_BLOCK_BASIS 1
+#define CMD53_ARG_FIXED_ADDRESS 0
+#define CMD53_ARG_INCR_ADDRESS 1
+
+static inline struct ath6kl_sdio *ath6kl_sdio_priv(struct ath6kl *ar)
+{
+ return ar->hif_priv;
+}
+
+/*
+ * Macro to check if DMA buffer is WORD-aligned and DMA-able.
+ * Most host controllers assume the buffer is DMA'able and will
+ * bug-check otherwise (i.e. buffers on the stack). virt_addr_valid
+ * check fails on stack memory.
+ */
+static inline bool buf_needs_bounce(u8 *buf)
+{
+ return ((unsigned long) buf & 0x3) || !virt_addr_valid(buf);
+}
+
+static void ath6kl_sdio_set_mbox_info(struct ath6kl *ar)
+{
+ struct ath6kl_mbox_info *mbox_info = &ar->mbox_info;
+
+ /* EP1 has an extended range */
+ mbox_info->htc_addr = HIF_MBOX_BASE_ADDR;
+ mbox_info->htc_ext_addr = HIF_MBOX0_EXT_BASE_ADDR;
+ mbox_info->htc_ext_sz = HIF_MBOX0_EXT_WIDTH;
+ mbox_info->block_size = HIF_MBOX_BLOCK_SIZE;
+ mbox_info->gmbox_addr = HIF_GMBOX_BASE_ADDR;
+ mbox_info->gmbox_sz = HIF_GMBOX_WIDTH;
+}
+
+static inline void ath6kl_sdio_set_cmd53_arg(u32 *arg, u8 rw, u8 func,
+ u8 mode, u8 opcode, u32 addr,
+ u16 blksz)
+{
+ *arg = (((rw & 1) << 31) |
+ ((func & 0x7) << 28) |
+ ((mode & 1) << 27) |
+ ((opcode & 1) << 26) |
+ ((addr & 0x1FFFF) << 9) |
+ (blksz & 0x1FF));
+}
+
+static inline void ath6kl_sdio_set_cmd52_arg(u32 *arg, u8 write, u8 raw,
+ unsigned int address,
+ unsigned char val)
+{
+ const u8 func = 0;
+
+ *arg = ((write & 1) << 31) |
+ ((func & 0x7) << 28) |
+ ((raw & 1) << 27) |
+ (1 << 26) |
+ ((address & 0x1FFFF) << 9) |
+ (1 << 8) |
+ (val & 0xFF);
+}
+
+static int ath6kl_sdio_func0_cmd52_wr_byte(struct mmc_card *card,
+ unsigned int address,
+ unsigned char byte)
+{
+ struct mmc_command io_cmd;
+
+ memset(&io_cmd, 0, sizeof(io_cmd));
+ ath6kl_sdio_set_cmd52_arg(&io_cmd.arg, 1, 0, address, byte);
+ io_cmd.opcode = SD_IO_RW_DIRECT;
+ io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+
+ return mmc_wait_for_cmd(card->host, &io_cmd, 0);
+}
+
+static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
+ u8 *buf, u32 len)
+{
+ int ret = 0;
+
+ if (request & HIF_WRITE) {
+ /* FIXME: looks like ugly workaround for something */
+ if (addr >= HIF_MBOX_BASE_ADDR &&
+ addr <= HIF_MBOX_END_ADDR)
+ addr += (HIF_MBOX_WIDTH - len);
+
+ /* FIXME: this also looks like ugly workaround */
+ if (addr == HIF_MBOX0_EXT_BASE_ADDR)
+ addr += HIF_MBOX0_EXT_WIDTH - len;
+
+ if (request & HIF_FIXED_ADDRESS)
+ ret = sdio_writesb(func, addr, buf, len);
+ else
+ ret = sdio_memcpy_toio(func, addr, buf, len);
+ } else {
+ if (request & HIF_FIXED_ADDRESS)
+ ret = sdio_readsb(func, buf, addr, len);
+ else
+ ret = sdio_memcpy_fromio(func, buf, addr, len);
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_SDIO, "%s addr 0x%x%s buf 0x%p len %d\n",
+ request & HIF_WRITE ? "wr" : "rd", addr,
+ request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len);
+ ath6kl_dbg_dump(ATH6KL_DBG_SDIO_DUMP, NULL, "sdio ", buf, len);
+
+ return ret;
+}
+
+static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio)
+{
+ struct bus_request *bus_req;
+ unsigned long flag;
+
+ spin_lock_irqsave(&ar_sdio->lock, flag);
+
+ if (list_empty(&ar_sdio->bus_req_freeq)) {
+ spin_unlock_irqrestore(&ar_sdio->lock, flag);
+ return NULL;
+ }
+
+ bus_req = list_first_entry(&ar_sdio->bus_req_freeq,
+ struct bus_request, list);
+ list_del(&bus_req->list);
+
+ spin_unlock_irqrestore(&ar_sdio->lock, flag);
+ ath6kl_dbg(ATH6KL_DBG_SCATTER, "%s: bus request 0x%p\n",
+ __func__, bus_req);
+
+ return bus_req;
+}
+
+static void ath6kl_sdio_free_bus_req(struct ath6kl_sdio *ar_sdio,
+ struct bus_request *bus_req)
+{
+ unsigned long flag;
+
+ ath6kl_dbg(ATH6KL_DBG_SCATTER, "%s: bus request 0x%p\n",
+ __func__, bus_req);
+
+ spin_lock_irqsave(&ar_sdio->lock, flag);
+ list_add_tail(&bus_req->list, &ar_sdio->bus_req_freeq);
+ spin_unlock_irqrestore(&ar_sdio->lock, flag);
+}
+
+static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req,
+ struct mmc_data *data)
+{
+ struct scatterlist *sg;
+ int i;
+
+ data->blksz = HIF_MBOX_BLOCK_SIZE;
+ data->blocks = scat_req->len / HIF_MBOX_BLOCK_SIZE;
+
+ ath6kl_dbg(ATH6KL_DBG_SCATTER,
+ "hif-scatter: (%s) addr: 0x%X, (block len: %d, block count: %d) , (tot:%d,sg:%d)\n",
+ (scat_req->req & HIF_WRITE) ? "WR" : "RD", scat_req->addr,
+ data->blksz, data->blocks, scat_req->len,
+ scat_req->scat_entries);
+
+ data->flags = (scat_req->req & HIF_WRITE) ? MMC_DATA_WRITE :
+ MMC_DATA_READ;
+
+ /* fill SG entries */
+ sg = scat_req->sgentries;
+ sg_init_table(sg, scat_req->scat_entries);
+
+ /* assemble SG list */
+ for (i = 0; i < scat_req->scat_entries; i++, sg++) {
+ ath6kl_dbg(ATH6KL_DBG_SCATTER, "%d: addr:0x%p, len:%d\n",
+ i, scat_req->scat_list[i].buf,
+ scat_req->scat_list[i].len);
+
+ sg_set_buf(sg, scat_req->scat_list[i].buf,
+ scat_req->scat_list[i].len);
+ }
+
+ /* set scatter-gather table for request */
+ data->sg = scat_req->sgentries;
+ data->sg_len = scat_req->scat_entries;
+}
+
+static int ath6kl_sdio_scat_rw(struct ath6kl_sdio *ar_sdio,
+ struct bus_request *req)
+{
+ struct mmc_request mmc_req;
+ struct mmc_command cmd;
+ struct mmc_data data;
+ struct hif_scatter_req *scat_req;
+ u8 opcode, rw;
+ int status, len;
+
+ scat_req = req->scat_req;
+
+ if (scat_req->virt_scat) {
+ len = scat_req->len;
+ if (scat_req->req & HIF_BLOCK_BASIS)
+ len = round_down(len, HIF_MBOX_BLOCK_SIZE);
+
+ status = ath6kl_sdio_io(ar_sdio->func, scat_req->req,
+ scat_req->addr, scat_req->virt_dma_buf,
+ len);
+ goto scat_complete;
+ }
+
+ memset(&mmc_req, 0, sizeof(struct mmc_request));
+ memset(&cmd, 0, sizeof(struct mmc_command));
+ memset(&data, 0, sizeof(struct mmc_data));
+
+ ath6kl_sdio_setup_scat_data(scat_req, &data);
+
+ opcode = (scat_req->req & HIF_FIXED_ADDRESS) ?
+ CMD53_ARG_FIXED_ADDRESS : CMD53_ARG_INCR_ADDRESS;
+
+ rw = (scat_req->req & HIF_WRITE) ? CMD53_ARG_WRITE : CMD53_ARG_READ;
+
+ /* Fixup the address so that the last byte will fall on MBOX EOM */
+ if (scat_req->req & HIF_WRITE) {
+ if (scat_req->addr == HIF_MBOX_BASE_ADDR)
+ scat_req->addr += HIF_MBOX_WIDTH - scat_req->len;
+ else
+ /* Uses extended address range */
+ scat_req->addr += HIF_MBOX0_EXT_WIDTH - scat_req->len;
+ }
+
+ /* set command argument */
+ ath6kl_sdio_set_cmd53_arg(&cmd.arg, rw, ar_sdio->func->num,
+ CMD53_ARG_BLOCK_BASIS, opcode, scat_req->addr,
+ data.blocks);
+
+ cmd.opcode = SD_IO_RW_EXTENDED;
+ cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
+
+ mmc_req.cmd = &cmd;
+ mmc_req.data = &data;
+
+ mmc_set_data_timeout(&data, ar_sdio->func->card);
+ /* synchronous call to process request */
+ mmc_wait_for_req(ar_sdio->func->card->host, &mmc_req);
+
+ status = cmd.error ? cmd.error : data.error;
+
+scat_complete:
+ scat_req->status = status;
+
+ if (scat_req->status)
+ ath6kl_err("Scatter write request failed:%d\n",
+ scat_req->status);
+
+ if (scat_req->req & HIF_ASYNCHRONOUS)
+ scat_req->complete(ar_sdio->ar->htc_target, scat_req);
+
+ return status;
+}
+
+static int ath6kl_sdio_alloc_prep_scat_req(struct ath6kl_sdio *ar_sdio,
+ int n_scat_entry, int n_scat_req,
+ bool virt_scat)
+{
+ struct hif_scatter_req *s_req;
+ struct bus_request *bus_req;
+ int i, scat_req_sz, scat_list_sz, sg_sz, buf_sz;
+ u8 *virt_buf;
+
+ scat_list_sz = (n_scat_entry - 1) * sizeof(struct hif_scatter_item);
+ scat_req_sz = sizeof(*s_req) + scat_list_sz;
+
+ if (!virt_scat)
+ sg_sz = sizeof(struct scatterlist) * n_scat_entry;
+ else
+ buf_sz = 2 * L1_CACHE_BYTES +
+ ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER;
+
+ for (i = 0; i < n_scat_req; i++) {
+ /* allocate the scatter request */
+ s_req = kzalloc(scat_req_sz, GFP_KERNEL);
+ if (!s_req)
+ return -ENOMEM;
+
+ if (virt_scat) {
+ virt_buf = kzalloc(buf_sz, GFP_KERNEL);
+ if (!virt_buf) {
+ kfree(s_req);
+ return -ENOMEM;
+ }
+
+ s_req->virt_dma_buf =
+ (u8 *)L1_CACHE_ALIGN((unsigned long)virt_buf);
+ } else {
+ /* allocate sglist */
+ s_req->sgentries = kzalloc(sg_sz, GFP_KERNEL);
+
+ if (!s_req->sgentries) {
+ kfree(s_req);
+ return -ENOMEM;
+ }
+ }
+
+ /* allocate a bus request for this scatter request */
+ bus_req = ath6kl_sdio_alloc_busreq(ar_sdio);
+ if (!bus_req) {
+ kfree(s_req->sgentries);
+ kfree(s_req->virt_dma_buf);
+ kfree(s_req);
+ return -ENOMEM;
+ }
+
+ /* assign the scatter request to this bus request */
+ bus_req->scat_req = s_req;
+ s_req->busrequest = bus_req;
+
+ s_req->virt_scat = virt_scat;
+
+ /* add it to the scatter pool */
+ hif_scatter_req_add(ar_sdio->ar, s_req);
+ }
+
+ return 0;
+}
+
+static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
+ u32 len, u32 request)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ u8 *tbuf = NULL;
+ int ret;
+ bool bounced = false;
+
+ if (request & HIF_BLOCK_BASIS)
+ len = round_down(len, HIF_MBOX_BLOCK_SIZE);
+
+ if (buf_needs_bounce(buf)) {
+ if (!ar_sdio->dma_buffer)
+ return -ENOMEM;
+ tbuf = ar_sdio->dma_buffer;
+ memcpy(tbuf, buf, len);
+ bounced = true;
+ } else
+ tbuf = buf;
+
+ sdio_claim_host(ar_sdio->func);
+ ret = ath6kl_sdio_io(ar_sdio->func, request, addr, tbuf, len);
+ if ((request & HIF_READ) && bounced)
+ memcpy(buf, tbuf, len);
+ sdio_release_host(ar_sdio->func);
+
+ return ret;
+}
+
+static void __ath6kl_sdio_write_async(struct ath6kl_sdio *ar_sdio,
+ struct bus_request *req)
+{
+ if (req->scat_req)
+ ath6kl_sdio_scat_rw(ar_sdio, req);
+ else {
+ void *context;
+ int status;
+
+ status = ath6kl_sdio_read_write_sync(ar_sdio->ar, req->address,
+ req->buffer, req->length,
+ req->request);
+ context = req->packet;
+ ath6kl_sdio_free_bus_req(ar_sdio, req);
+ ath6kldev_rw_comp_handler(context, status);
+ }
+}
+
+static void ath6kl_sdio_write_async_work(struct work_struct *work)
+{
+ struct ath6kl_sdio *ar_sdio;
+ unsigned long flags;
+ struct bus_request *req, *tmp_req;
+
+ ar_sdio = container_of(work, struct ath6kl_sdio, wr_async_work);
+ sdio_claim_host(ar_sdio->func);
+
+ spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
+ list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) {
+ list_del(&req->list);
+ spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
+ __ath6kl_sdio_write_async(ar_sdio, req);
+ spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
+ }
+ spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
+
+ sdio_release_host(ar_sdio->func);
+}
+
+static void ath6kl_sdio_irq_handler(struct sdio_func *func)
+{
+ int status;
+ struct ath6kl_sdio *ar_sdio;
+
+ ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n");
+
+ ar_sdio = sdio_get_drvdata(func);
+ atomic_set(&ar_sdio->irq_handling, 1);
+
+ /*
+ * Release the host during interrups so we can pick it back up when
+ * we process commands.
+ */
+ sdio_release_host(ar_sdio->func);
+
+ status = ath6kldev_intr_bh_handler(ar_sdio->ar);
+ sdio_claim_host(ar_sdio->func);
+ atomic_set(&ar_sdio->irq_handling, 0);
+ WARN_ON(status && status != -ECANCELED);
+}
+
+static int ath6kl_sdio_power_on(struct ath6kl_sdio *ar_sdio)
+{
+ struct sdio_func *func = ar_sdio->func;
+ int ret = 0;
+
+ if (!ar_sdio->is_disabled)
+ return 0;
+
+ sdio_claim_host(func);
+
+ ret = sdio_enable_func(func);
+ if (ret) {
+ ath6kl_err("Unable to enable sdio func: %d)\n", ret);
+ sdio_release_host(func);
+ return ret;
+ }
+
+ sdio_release_host(func);
+
+ /*
+ * Wait for hardware to initialise. It should take a lot less than
+ * 10 ms but let's be conservative here.
+ */
+ msleep(10);
+
+ ar_sdio->is_disabled = false;
+
+ return ret;
+}
+
+static int ath6kl_sdio_power_off(struct ath6kl_sdio *ar_sdio)
+{
+ int ret;
+
+ if (ar_sdio->is_disabled)
+ return 0;
+
+ /* Disable the card */
+ sdio_claim_host(ar_sdio->func);
+ ret = sdio_disable_func(ar_sdio->func);
+ sdio_release_host(ar_sdio->func);
+
+ if (ret)
+ return ret;
+
+ ar_sdio->is_disabled = true;
+
+ return ret;
+}
+
+static int ath6kl_sdio_write_async(struct ath6kl *ar, u32 address, u8 *buffer,
+ u32 length, u32 request,
+ struct htc_packet *packet)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ struct bus_request *bus_req;
+ unsigned long flags;
+
+ bus_req = ath6kl_sdio_alloc_busreq(ar_sdio);
+
+ if (!bus_req)
+ return -ENOMEM;
+
+ bus_req->address = address;
+ bus_req->buffer = buffer;
+ bus_req->length = length;
+ bus_req->request = request;
+ bus_req->packet = packet;
+
+ spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
+ list_add_tail(&bus_req->list, &ar_sdio->wr_asyncq);
+ spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
+ queue_work(ar->ath6kl_wq, &ar_sdio->wr_async_work);
+
+ return 0;
+}
+
+static void ath6kl_sdio_irq_enable(struct ath6kl *ar)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ int ret;
+
+ sdio_claim_host(ar_sdio->func);
+
+ /* Register the isr */
+ ret = sdio_claim_irq(ar_sdio->func, ath6kl_sdio_irq_handler);
+ if (ret)
+ ath6kl_err("Failed to claim sdio irq: %d\n", ret);
+
+ sdio_release_host(ar_sdio->func);
+}
+
+static void ath6kl_sdio_irq_disable(struct ath6kl *ar)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ int ret;
+
+ sdio_claim_host(ar_sdio->func);
+
+ /* Mask our function IRQ */
+ while (atomic_read(&ar_sdio->irq_handling)) {
+ sdio_release_host(ar_sdio->func);
+ schedule_timeout(HZ / 10);
+ sdio_claim_host(ar_sdio->func);
+ }
+
+ ret = sdio_release_irq(ar_sdio->func);
+ if (ret)
+ ath6kl_err("Failed to release sdio irq: %d\n", ret);
+
+ sdio_release_host(ar_sdio->func);
+}
+
+static struct hif_scatter_req *ath6kl_sdio_scatter_req_get(struct ath6kl *ar)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ struct hif_scatter_req *node = NULL;
+ unsigned long flag;
+
+ spin_lock_irqsave(&ar_sdio->scat_lock, flag);
+
+ if (!list_empty(&ar_sdio->scat_req)) {
+ node = list_first_entry(&ar_sdio->scat_req,
+ struct hif_scatter_req, list);
+ list_del(&node->list);
+ }
+
+ spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
+
+ return node;
+}
+
+static void ath6kl_sdio_scatter_req_add(struct ath6kl *ar,
+ struct hif_scatter_req *s_req)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ unsigned long flag;
+
+ spin_lock_irqsave(&ar_sdio->scat_lock, flag);
+
+ list_add_tail(&s_req->list, &ar_sdio->scat_req);
+
+ spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
+
+}
+
+/* scatter gather read write request */
+static int ath6kl_sdio_async_rw_scatter(struct ath6kl *ar,
+ struct hif_scatter_req *scat_req)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ u32 request = scat_req->req;
+ int status = 0;
+ unsigned long flags;
+
+ if (!scat_req->len)
+ return -EINVAL;
+
+ ath6kl_dbg(ATH6KL_DBG_SCATTER,
+ "hif-scatter: total len: %d scatter entries: %d\n",
+ scat_req->len, scat_req->scat_entries);
+
+ if (request & HIF_SYNCHRONOUS) {
+ sdio_claim_host(ar_sdio->func);
+ status = ath6kl_sdio_scat_rw(ar_sdio, scat_req->busrequest);
+ sdio_release_host(ar_sdio->func);
+ } else {
+ spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
+ list_add_tail(&scat_req->busrequest->list, &ar_sdio->wr_asyncq);
+ spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
+ queue_work(ar->ath6kl_wq, &ar_sdio->wr_async_work);
+ }
+
+ return status;
+}
+
+/* clean up scatter support */
+static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ struct hif_scatter_req *s_req, *tmp_req;
+ unsigned long flag;
+
+ /* empty the free list */
+ spin_lock_irqsave(&ar_sdio->scat_lock, flag);
+ list_for_each_entry_safe(s_req, tmp_req, &ar_sdio->scat_req, list) {
+ list_del(&s_req->list);
+ spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
+
+ if (s_req->busrequest)
+ ath6kl_sdio_free_bus_req(ar_sdio, s_req->busrequest);
+ kfree(s_req->virt_dma_buf);
+ kfree(s_req->sgentries);
+ kfree(s_req);
+
+ spin_lock_irqsave(&ar_sdio->scat_lock, flag);
+ }
+ spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
+}
+
+/* setup of HIF scatter resources */
+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;
+ bool virt_scat = false;
+
+ /* check if host supports scatter and it meets our requirements */
+ if (ar_sdio->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) {
+ ath6kl_err("host only supports scatter of :%d entries, need: %d\n",
+ ar_sdio->func->card->host->max_segs,
+ MAX_SCATTER_ENTRIES_PER_REQ);
+ virt_scat = true;
+ }
+
+ if (!virt_scat) {
+ ret = ath6kl_sdio_alloc_prep_scat_req(ar_sdio,
+ MAX_SCATTER_ENTRIES_PER_REQ,
+ MAX_SCATTER_REQUESTS, virt_scat);
+
+ if (!ret) {
+ ath6kl_dbg(ATH6KL_DBG_SCATTER,
+ "hif-scatter enabled: max scatter req : %d entries: %d\n",
+ MAX_SCATTER_REQUESTS,
+ MAX_SCATTER_ENTRIES_PER_REQ);
+
+ target->max_scat_entries = MAX_SCATTER_ENTRIES_PER_REQ;
+ target->max_xfer_szper_scatreq =
+ MAX_SCATTER_REQ_TRANSFER_SIZE;
+ } else {
+ ath6kl_sdio_cleanup_scatter(ar);
+ ath6kl_warn("hif scatter resource setup failed, trying virtual scatter method\n");
+ }
+ }
+
+ if (virt_scat || ret) {
+ ret = ath6kl_sdio_alloc_prep_scat_req(ar_sdio,
+ ATH6KL_SCATTER_ENTRIES_PER_REQ,
+ ATH6KL_SCATTER_REQS, virt_scat);
+
+ if (ret) {
+ ath6kl_err("failed to alloc virtual scatter resources !\n");
+ ath6kl_sdio_cleanup_scatter(ar);
+ return ret;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_SCATTER,
+ "Vitual scatter enabled, max_scat_req:%d, entries:%d\n",
+ ATH6KL_SCATTER_REQS, ATH6KL_SCATTER_ENTRIES_PER_REQ);
+
+ target->max_scat_entries = ATH6KL_SCATTER_ENTRIES_PER_REQ;
+ target->max_xfer_szper_scatreq =
+ ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER;
+ }
+
+ return 0;
+}
+
+static int ath6kl_sdio_suspend(struct ath6kl *ar)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ struct sdio_func *func = ar_sdio->func;
+ mmc_pm_flag_t flags;
+ int ret;
+
+ flags = sdio_get_host_pm_caps(func);
+
+ if (!(flags & MMC_PM_KEEP_POWER))
+ /* as host doesn't support keep power we need to bail out */
+ ath6kl_dbg(ATH6KL_DBG_SDIO,
+ "func %d doesn't support MMC_PM_KEEP_POWER\n",
+ func->num);
+ return -EINVAL;
+
+ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+ if (ret) {
+ printk(KERN_ERR "ath6kl: set sdio pm flags failed: %d\n",
+ ret);
+ return ret;
+ }
+
+ ath6kl_deep_sleep_enable(ar);
+
+ return 0;
+}
+
+static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
+ .read_write_sync = ath6kl_sdio_read_write_sync,
+ .write_async = ath6kl_sdio_write_async,
+ .irq_enable = ath6kl_sdio_irq_enable,
+ .irq_disable = ath6kl_sdio_irq_disable,
+ .scatter_req_get = ath6kl_sdio_scatter_req_get,
+ .scatter_req_add = ath6kl_sdio_scatter_req_add,
+ .enable_scatter = ath6kl_sdio_enable_scatter,
+ .scat_req_rw = ath6kl_sdio_async_rw_scatter,
+ .cleanup_scatter = ath6kl_sdio_cleanup_scatter,
+ .suspend = ath6kl_sdio_suspend,
+};
+
+static int ath6kl_sdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ int ret;
+ struct ath6kl_sdio *ar_sdio;
+ struct ath6kl *ar;
+ int count;
+
+ ath6kl_dbg(ATH6KL_DBG_SDIO,
+ "new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n",
+ func->num, func->vendor, func->device,
+ func->max_blksize, func->cur_blksize);
+
+ ar_sdio = kzalloc(sizeof(struct ath6kl_sdio), GFP_KERNEL);
+ if (!ar_sdio)
+ return -ENOMEM;
+
+ ar_sdio->dma_buffer = kzalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL);
+ if (!ar_sdio->dma_buffer) {
+ ret = -ENOMEM;
+ goto err_hif;
+ }
+
+ ar_sdio->func = func;
+ sdio_set_drvdata(func, ar_sdio);
+
+ ar_sdio->id = id;
+ ar_sdio->is_disabled = true;
+
+ spin_lock_init(&ar_sdio->lock);
+ spin_lock_init(&ar_sdio->scat_lock);
+ spin_lock_init(&ar_sdio->wr_async_lock);
+
+ INIT_LIST_HEAD(&ar_sdio->scat_req);
+ INIT_LIST_HEAD(&ar_sdio->bus_req_freeq);
+ INIT_LIST_HEAD(&ar_sdio->wr_asyncq);
+
+ INIT_WORK(&ar_sdio->wr_async_work, ath6kl_sdio_write_async_work);
+
+ for (count = 0; count < BUS_REQUEST_MAX_NUM; count++)
+ ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]);
+
+ ar = ath6kl_core_alloc(&ar_sdio->func->dev);
+ if (!ar) {
+ ath6kl_err("Failed to alloc ath6kl core\n");
+ ret = -ENOMEM;
+ goto err_dma;
+ }
+
+ ar_sdio->ar = ar;
+ ar->hif_priv = ar_sdio;
+ ar->hif_ops = &ath6kl_sdio_ops;
+
+ ath6kl_sdio_set_mbox_info(ar);
+
+ sdio_claim_host(func);
+
+ if ((ar_sdio->id->device & MANUFACTURER_ID_ATH6KL_BASE_MASK) >=
+ MANUFACTURER_ID_AR6003_BASE) {
+ /* enable 4-bit ASYNC interrupt on AR6003 or later */
+ ret = ath6kl_sdio_func0_cmd52_wr_byte(func->card,
+ CCCR_SDIO_IRQ_MODE_REG,
+ SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
+ if (ret) {
+ ath6kl_err("Failed to enable 4-bit async irq mode %d\n",
+ ret);
+ sdio_release_host(func);
+ goto err_cfg80211;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_SDIO, "4-bit async irq mode enabled\n");
+ }
+
+ /* give us some time to enable, in ms */
+ func->enable_timeout = 100;
+
+ sdio_release_host(func);
+
+ ret = ath6kl_sdio_power_on(ar_sdio);
+ if (ret)
+ goto err_cfg80211;
+
+ sdio_claim_host(func);
+
+ ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
+ if (ret) {
+ ath6kl_err("Set sdio block size %d failed: %d)\n",
+ HIF_MBOX_BLOCK_SIZE, ret);
+ sdio_release_host(func);
+ goto err_off;
+ }
+
+ sdio_release_host(func);
+
+ ret = ath6kl_core_init(ar);
+ if (ret) {
+ ath6kl_err("Failed to init ath6kl core\n");
+ goto err_off;
+ }
+
+ return ret;
+
+err_off:
+ ath6kl_sdio_power_off(ar_sdio);
+err_cfg80211:
+ ath6kl_cfg80211_deinit(ar_sdio->ar);
+err_dma:
+ kfree(ar_sdio->dma_buffer);
+err_hif:
+ kfree(ar_sdio);
+
+ return ret;
+}
+
+static void ath6kl_sdio_remove(struct sdio_func *func)
+{
+ struct ath6kl_sdio *ar_sdio;
+
+ ath6kl_dbg(ATH6KL_DBG_SDIO,
+ "removed func %d vendor 0x%x device 0x%x\n",
+ func->num, func->vendor, func->device);
+
+ ar_sdio = sdio_get_drvdata(func);
+
+ ath6kl_stop_txrx(ar_sdio->ar);
+ cancel_work_sync(&ar_sdio->wr_async_work);
+
+ ath6kl_unavail_ev(ar_sdio->ar);
+
+ ath6kl_sdio_power_off(ar_sdio);
+
+ kfree(ar_sdio->dma_buffer);
+ kfree(ar_sdio);
+}
+
+static const struct sdio_device_id ath6kl_sdio_devices[] = {
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0))},
+ {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1))},
+ {},
+};
+
+MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices);
+
+static struct sdio_driver ath6kl_sdio_driver = {
+ .name = "ath6kl_sdio",
+ .id_table = ath6kl_sdio_devices,
+ .probe = ath6kl_sdio_probe,
+ .remove = ath6kl_sdio_remove,
+};
+
+static int __init ath6kl_sdio_init(void)
+{
+ int ret;
+
+ ret = sdio_register_driver(&ath6kl_sdio_driver);
+ if (ret)
+ ath6kl_err("sdio driver registration failed: %d\n", ret);
+
+ return ret;
+}
+
+static void __exit ath6kl_sdio_exit(void)
+{
+ sdio_unregister_driver(&ath6kl_sdio_driver);
+}
+
+module_init(ath6kl_sdio_init);
+module_exit(ath6kl_sdio_exit);
+
+MODULE_AUTHOR("Atheros Communications, Inc.");
+MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices");
+MODULE_LICENSE("Dual BSD/GPL");
+
+MODULE_FIRMWARE(AR6003_REV2_OTP_FILE);
+MODULE_FIRMWARE(AR6003_REV2_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6003_REV2_PATCH_FILE);
+MODULE_FIRMWARE(AR6003_REV2_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6003_REV2_DEFAULT_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6003_REV3_OTP_FILE);
+MODULE_FIRMWARE(AR6003_REV3_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6003_REV3_PATCH_FILE);
+MODULE_FIRMWARE(AR6003_REV3_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6003_REV3_DEFAULT_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h
new file mode 100644
index 000000000000..c9a76051f042
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/target.h
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2004-2010 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef TARGET_H
+#define TARGET_H
+
+#define AR6003_BOARD_DATA_SZ 1024
+#define AR6003_BOARD_EXT_DATA_SZ 768
+
+#define AR6004_BOARD_DATA_SZ 7168
+#define AR6004_BOARD_EXT_DATA_SZ 0
+
+#define RESET_CONTROL_ADDRESS 0x00000000
+#define RESET_CONTROL_COLD_RST 0x00000100
+#define RESET_CONTROL_MBOX_RST 0x00000004
+
+#define CPU_CLOCK_STANDARD_S 0
+#define CPU_CLOCK_STANDARD 0x00000003
+#define CPU_CLOCK_ADDRESS 0x00000020
+
+#define CLOCK_CONTROL_ADDRESS 0x00000028
+#define CLOCK_CONTROL_LF_CLK32_S 2
+#define CLOCK_CONTROL_LF_CLK32 0x00000004
+
+#define SYSTEM_SLEEP_ADDRESS 0x000000c4
+#define SYSTEM_SLEEP_DISABLE_S 0
+#define SYSTEM_SLEEP_DISABLE 0x00000001
+
+#define LPO_CAL_ADDRESS 0x000000e0
+#define LPO_CAL_ENABLE_S 20
+#define LPO_CAL_ENABLE 0x00100000
+
+#define GPIO_PIN10_ADDRESS 0x00000050
+#define GPIO_PIN11_ADDRESS 0x00000054
+#define GPIO_PIN12_ADDRESS 0x00000058
+#define GPIO_PIN13_ADDRESS 0x0000005c
+
+#define HOST_INT_STATUS_ADDRESS 0x00000400
+#define HOST_INT_STATUS_ERROR_S 7
+#define HOST_INT_STATUS_ERROR 0x00000080
+
+#define HOST_INT_STATUS_CPU_S 6
+#define HOST_INT_STATUS_CPU 0x00000040
+
+#define HOST_INT_STATUS_COUNTER_S 4
+#define HOST_INT_STATUS_COUNTER 0x00000010
+
+#define CPU_INT_STATUS_ADDRESS 0x00000401
+
+#define ERROR_INT_STATUS_ADDRESS 0x00000402
+#define ERROR_INT_STATUS_WAKEUP_S 2
+#define ERROR_INT_STATUS_WAKEUP 0x00000004
+
+#define ERROR_INT_STATUS_RX_UNDERFLOW_S 1
+#define ERROR_INT_STATUS_RX_UNDERFLOW 0x00000002
+
+#define ERROR_INT_STATUS_TX_OVERFLOW_S 0
+#define ERROR_INT_STATUS_TX_OVERFLOW 0x00000001
+
+#define COUNTER_INT_STATUS_ADDRESS 0x00000403
+#define COUNTER_INT_STATUS_COUNTER_S 0
+#define COUNTER_INT_STATUS_COUNTER 0x000000ff
+
+#define RX_LOOKAHEAD_VALID_ADDRESS 0x00000405
+
+#define INT_STATUS_ENABLE_ADDRESS 0x00000418
+#define INT_STATUS_ENABLE_ERROR_S 7
+#define INT_STATUS_ENABLE_ERROR 0x00000080
+
+#define INT_STATUS_ENABLE_CPU_S 6
+#define INT_STATUS_ENABLE_CPU 0x00000040
+
+#define INT_STATUS_ENABLE_INT_S 5
+#define INT_STATUS_ENABLE_INT 0x00000020
+#define INT_STATUS_ENABLE_COUNTER_S 4
+#define INT_STATUS_ENABLE_COUNTER 0x00000010
+
+#define INT_STATUS_ENABLE_MBOX_DATA_S 0
+#define INT_STATUS_ENABLE_MBOX_DATA 0x0000000f
+
+#define CPU_INT_STATUS_ENABLE_ADDRESS 0x00000419
+#define CPU_INT_STATUS_ENABLE_BIT_S 0
+#define CPU_INT_STATUS_ENABLE_BIT 0x000000ff
+
+#define ERROR_STATUS_ENABLE_ADDRESS 0x0000041a
+#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_S 1
+#define ERROR_STATUS_ENABLE_RX_UNDERFLOW 0x00000002
+
+#define ERROR_STATUS_ENABLE_TX_OVERFLOW_S 0
+#define ERROR_STATUS_ENABLE_TX_OVERFLOW 0x00000001
+
+#define COUNTER_INT_STATUS_ENABLE_ADDRESS 0x0000041b
+#define COUNTER_INT_STATUS_ENABLE_BIT_S 0
+#define COUNTER_INT_STATUS_ENABLE_BIT 0x000000ff
+
+#define COUNT_ADDRESS 0x00000420
+
+#define COUNT_DEC_ADDRESS 0x00000440
+
+#define WINDOW_DATA_ADDRESS 0x00000474
+#define WINDOW_WRITE_ADDR_ADDRESS 0x00000478
+#define WINDOW_READ_ADDR_ADDRESS 0x0000047c
+#define CPU_DBG_SEL_ADDRESS 0x00000483
+#define CPU_DBG_ADDRESS 0x00000484
+
+#define LOCAL_SCRATCH_ADDRESS 0x000000c0
+#define ATH6KL_OPTION_SLEEP_DISABLE 0x08
+
+#define RTC_BASE_ADDRESS 0x00004000
+#define GPIO_BASE_ADDRESS 0x00014000
+#define MBOX_BASE_ADDRESS 0x00018000
+#define ANALOG_INTF_BASE_ADDRESS 0x0001c000
+
+/* real name of the register is unknown */
+#define ATH6KL_ANALOG_PLL_REGISTER (ANALOG_INTF_BASE_ADDRESS + 0x284)
+
+#define SM(f, v) (((v) << f##_S) & f)
+#define MS(f, v) (((v) & f) >> f##_S)
+
+/*
+ * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the
+ * host_interest structure.
+ *
+ * Host Interest is shared between Host and Target in order to coordinate
+ * between the two, and is intended to remain constant (with additions only
+ * at the end).
+ */
+#define ATH6KL_AR6003_HI_START_ADDR 0x00540600
+#define ATH6KL_AR6004_HI_START_ADDR 0x00400800
+
+/*
+ * These are items that the Host may need to access
+ * via BMI or via the Diagnostic Window. The position
+ * of items in this structure must remain constant.
+ * across firmware revisions!
+ *
+ * Types for each item must be fixed size across target and host platforms.
+ * The structure is used only to calculate offset for each register with
+ * HI_ITEM() macro, no values are stored to it.
+ *
+ * More items may be added at the end.
+ */
+struct host_interest {
+ /*
+ * Pointer to application-defined area, if any.
+ * Set by Target application during startup.
+ */
+ u32 hi_app_host_interest; /* 0x00 */
+
+ /* Pointer to register dump area, valid after Target crash. */
+ u32 hi_failure_state; /* 0x04 */
+
+ /* Pointer to debug logging header */
+ u32 hi_dbglog_hdr; /* 0x08 */
+
+ u32 hi_unused1; /* 0x0c */
+
+ /*
+ * General-purpose flag bits, similar to ATH6KL_OPTION_* flags.
+ * Can be used by application rather than by OS.
+ */
+ u32 hi_option_flag; /* 0x10 */
+
+ /*
+ * Boolean that determines whether or not to
+ * display messages on the serial port.
+ */
+ u32 hi_serial_enable; /* 0x14 */
+
+ /* Start address of DataSet index, if any */
+ u32 hi_dset_list_head; /* 0x18 */
+
+ /* Override Target application start address */
+ u32 hi_app_start; /* 0x1c */
+
+ /* Clock and voltage tuning */
+ u32 hi_skip_clock_init; /* 0x20 */
+ u32 hi_core_clock_setting; /* 0x24 */
+ u32 hi_cpu_clock_setting; /* 0x28 */
+ u32 hi_system_sleep_setting; /* 0x2c */
+ u32 hi_xtal_control_setting; /* 0x30 */
+ u32 hi_pll_ctrl_setting_24ghz; /* 0x34 */
+ u32 hi_pll_ctrl_setting_5ghz; /* 0x38 */
+ u32 hi_ref_voltage_trim_setting; /* 0x3c */
+ u32 hi_clock_info; /* 0x40 */
+
+ /*
+ * Flash configuration overrides, used only
+ * when firmware is not executing from flash.
+ * (When using flash, modify the global variables
+ * with equivalent names.)
+ */
+ u32 hi_bank0_addr_value; /* 0x44 */
+ u32 hi_bank0_read_value; /* 0x48 */
+ u32 hi_bank0_write_value; /* 0x4c */
+ u32 hi_bank0_config_value; /* 0x50 */
+
+ /* Pointer to Board Data */
+ u32 hi_board_data; /* 0x54 */
+ u32 hi_board_data_initialized; /* 0x58 */
+
+ u32 hi_dset_ram_index_tbl; /* 0x5c */
+
+ u32 hi_desired_baud_rate; /* 0x60 */
+ u32 hi_dbglog_config; /* 0x64 */
+ u32 hi_end_ram_reserve_sz; /* 0x68 */
+ u32 hi_mbox_io_block_sz; /* 0x6c */
+
+ u32 hi_num_bpatch_streams; /* 0x70 -- unused */
+ u32 hi_mbox_isr_yield_limit; /* 0x74 */
+
+ u32 hi_refclk_hz; /* 0x78 */
+ u32 hi_ext_clk_detected; /* 0x7c */
+ u32 hi_dbg_uart_txpin; /* 0x80 */
+ u32 hi_dbg_uart_rxpin; /* 0x84 */
+ u32 hi_hci_uart_baud; /* 0x88 */
+ u32 hi_hci_uart_pin_assignments; /* 0x8C */
+ /*
+ * NOTE: byte [0] = tx pin, [1] = rx pin, [2] = rts pin, [3] = cts
+ * pin
+ */
+ u32 hi_hci_uart_baud_scale_val; /* 0x90 */
+ u32 hi_hci_uart_baud_step_val; /* 0x94 */
+
+ u32 hi_allocram_start; /* 0x98 */
+ u32 hi_allocram_sz; /* 0x9c */
+ u32 hi_hci_bridge_flags; /* 0xa0 */
+ u32 hi_hci_uart_support_pins; /* 0xa4 */
+ /*
+ * NOTE: byte [0] = RESET pin (bit 7 is polarity),
+ * bytes[1]..bytes[3] are for future use
+ */
+ u32 hi_hci_uart_pwr_mgmt_params; /* 0xa8 */
+ /*
+ * 0xa8 - [1]: 0 = UART FC active low, 1 = UART FC active high
+ * [31:16]: wakeup timeout in ms
+ */
+
+ /* Pointer to extended board data */
+ u32 hi_board_ext_data; /* 0xac */
+ u32 hi_board_ext_data_config; /* 0xb0 */
+
+ /*
+ * Bit [0] : valid
+ * Bit[31:16: size
+ */
+ /*
+ * hi_reset_flag is used to do some stuff when target reset.
+ * such as restore app_start after warm reset or
+ * preserve host Interest area, or preserve ROM data, literals etc.
+ */
+ u32 hi_reset_flag; /* 0xb4 */
+ /* indicate hi_reset_flag is valid */
+ u32 hi_reset_flag_valid; /* 0xb8 */
+ u32 hi_hci_uart_pwr_mgmt_params_ext; /* 0xbc */
+ /*
+ * 0xbc - [31:0]: idle timeout in ms
+ */
+ /* ACS flags */
+ u32 hi_acs_flags; /* 0xc0 */
+ u32 hi_console_flags; /* 0xc4 */
+ u32 hi_nvram_state; /* 0xc8 */
+ u32 hi_option_flag2; /* 0xcc */
+
+ /* If non-zero, override values sent to Host in WMI_READY event. */
+ u32 hi_sw_version_override; /* 0xd0 */
+ u32 hi_abi_version_override; /* 0xd4 */
+
+ /*
+ * Percentage of high priority RX traffic to total expected RX traffic -
+ * applicable only to ar6004
+ */
+ u32 hi_hp_rx_traffic_ratio; /* 0xd8 */
+
+ /* test applications flags */
+ u32 hi_test_apps_related ; /* 0xdc */
+ /* location of test script */
+ u32 hi_ota_testscript; /* 0xe0 */
+ /* location of CAL data */
+ u32 hi_cal_data; /* 0xe4 */
+ /* Number of packet log buffers */
+ u32 hi_pktlog_num_buffers; /* 0xe8 */
+
+} __packed;
+
+#define HI_ITEM(item) offsetof(struct host_interest, item)
+
+#define HI_OPTION_MAC_ADDR_METHOD_SHIFT 3
+
+#define HI_OPTION_FW_MODE_IBSS 0x0
+#define HI_OPTION_FW_MODE_BSS_STA 0x1
+#define HI_OPTION_FW_MODE_AP 0x2
+
+#define HI_OPTION_FW_SUBMODE_NONE 0x0
+#define HI_OPTION_FW_SUBMODE_P2PDEV 0x1
+#define HI_OPTION_FW_SUBMODE_P2PCLIENT 0x2
+#define HI_OPTION_FW_SUBMODE_P2PGO 0x3
+
+#define HI_OPTION_NUM_DEV_SHIFT 0x9
+
+#define HI_OPTION_FW_BRIDGE_SHIFT 0x04
+
+/* Fw Mode/SubMode Mask
+|------------------------------------------------------------------------------|
+| SUB | SUB | SUB | SUB | | | |
+| MODE[3] | MODE[2] | MODE[1] | MODE[0] | MODE[3] | MODE[2] | MODE[1] | MODE[0|
+| (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2)
+|------------------------------------------------------------------------------|
+*/
+#define HI_OPTION_FW_MODE_SHIFT 0xC
+#define HI_OPTION_FW_SUBMODE_SHIFT 0x14
+
+/* Convert a Target virtual address into a Target physical address */
+#define AR6003_VTOP(vaddr) ((vaddr) & 0x001fffff)
+#define AR6004_VTOP(vaddr) (vaddr)
+
+#define TARG_VTOP(target_type, vaddr) \
+ (((target_type) == TARGET_TYPE_AR6003) ? AR6003_VTOP(vaddr) : \
+ (((target_type) == TARGET_TYPE_AR6004) ? AR6004_VTOP(vaddr) : 0))
+
+#define AR6003_REV2_APP_LOAD_ADDRESS 0x543180
+#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500
+#define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884
+#define AR6003_REV2_RAM_RESERVE_SIZE 6912
+
+#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000
+#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330
+#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74
+#define AR6003_REV3_RAM_RESERVE_SIZE 512
+
+#define AR6004_REV1_BOARD_DATA_ADDRESS 0x435400
+#define AR6004_REV1_BOARD_EXT_DATA_ADDRESS 0x437000
+#define AR6004_REV1_RAM_RESERVE_SIZE 11264
+
+#define ATH6KL_FWLOG_PAYLOAD_SIZE 1500
+
+struct ath6kl_dbglog_buf {
+ __le32 next;
+ __le32 buffer_addr;
+ __le32 bufsize;
+ __le32 length;
+ __le32 count;
+ __le32 free;
+} __packed;
+
+struct ath6kl_dbglog_hdr {
+ __le32 dbuf_addr;
+ __le32 dropped;
+} __packed;
+
+#endif
diff --git a/drivers/net/wireless/ath/ath6kl/testmode.c b/drivers/net/wireless/ath/ath6kl/testmode.c
new file mode 100644
index 000000000000..381eb66a605f
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/testmode.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications 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 "testmode.h"
+
+#include <net/netlink.h>
+
+enum ath6kl_tm_attr {
+ __ATH6KL_TM_ATTR_INVALID = 0,
+ ATH6KL_TM_ATTR_CMD = 1,
+ ATH6KL_TM_ATTR_DATA = 2,
+
+ /* keep last */
+ __ATH6KL_TM_ATTR_AFTER_LAST,
+ ATH6KL_TM_ATTR_MAX = __ATH6KL_TM_ATTR_AFTER_LAST - 1,
+};
+
+enum ath6kl_tm_cmd {
+ ATH6KL_TM_CMD_TCMD = 0,
+ ATH6KL_TM_CMD_RX_REPORT = 1,
+};
+
+#define ATH6KL_TM_DATA_MAX_LEN 5000
+
+static const struct nla_policy ath6kl_tm_policy[ATH6KL_TM_ATTR_MAX + 1] = {
+ [ATH6KL_TM_ATTR_CMD] = { .type = NLA_U32 },
+ [ATH6KL_TM_ATTR_DATA] = { .type = NLA_BINARY,
+ .len = ATH6KL_TM_DATA_MAX_LEN },
+};
+
+void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len)
+{
+ if (down_interruptible(&ar->sem))
+ return;
+
+ kfree(ar->tm.rx_report);
+
+ ar->tm.rx_report = kmemdup(buf, buf_len, GFP_KERNEL);
+ ar->tm.rx_report_len = buf_len;
+
+ up(&ar->sem);
+
+ wake_up(&ar->event_wq);
+}
+
+static int ath6kl_tm_rx_report(struct ath6kl *ar, void *buf, size_t buf_len,
+ struct sk_buff *skb)
+{
+ int ret = 0;
+ long left;
+
+ if (down_interruptible(&ar->sem))
+ return -ERESTARTSYS;
+
+ if (!test_bit(WMI_READY, &ar->flag)) {
+ ret = -EIO;
+ goto out;
+ }
+
+ if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len) < 0) {
+ up(&ar->sem);
+ return -EIO;
+ }
+
+ left = wait_event_interruptible_timeout(ar->event_wq,
+ ar->tm.rx_report != NULL,
+ WMI_TIMEOUT);
+
+ if (left == 0) {
+ ret = -ETIMEDOUT;
+ goto out;
+ } else if (left < 0) {
+ ret = left;
+ goto out;
+ }
+
+ if (ar->tm.rx_report == NULL || ar->tm.rx_report_len == 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, ar->tm.rx_report_len,
+ ar->tm.rx_report);
+
+ kfree(ar->tm.rx_report);
+ ar->tm.rx_report = NULL;
+
+out:
+ up(&ar->sem);
+
+ return ret;
+
+nla_put_failure:
+ ret = -ENOBUFS;
+ goto out;
+}
+
+int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len)
+{
+ struct ath6kl *ar = wiphy_priv(wiphy);
+ struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1];
+ int err, buf_len, reply_len;
+ struct sk_buff *skb;
+ void *buf;
+
+ err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len,
+ ath6kl_tm_policy);
+ if (err)
+ return err;
+
+ if (!tb[ATH6KL_TM_ATTR_CMD])
+ return -EINVAL;
+
+ switch (nla_get_u32(tb[ATH6KL_TM_ATTR_CMD])) {
+ case ATH6KL_TM_CMD_TCMD:
+ if (!tb[ATH6KL_TM_ATTR_DATA])
+ return -EINVAL;
+
+ buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]);
+ buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]);
+
+ ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len);
+
+ return 0;
+
+ break;
+ case ATH6KL_TM_CMD_RX_REPORT:
+ if (!tb[ATH6KL_TM_ATTR_DATA])
+ return -EINVAL;
+
+ buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]);
+ buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]);
+
+ reply_len = nla_total_size(ATH6KL_TM_DATA_MAX_LEN);
+ skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len);
+ if (!skb)
+ return -ENOMEM;
+
+ err = ath6kl_tm_rx_report(ar, buf, buf_len, skb);
+ if (err < 0) {
+ kfree_skb(skb);
+ return err;
+ }
+
+ return cfg80211_testmode_reply(skb);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
diff --git a/drivers/net/wireless/ath/ath6kl/testmode.h b/drivers/net/wireless/ath/ath6kl/testmode.h
new file mode 100644
index 000000000000..43dffcc11fb1
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/testmode.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications 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"
+
+#ifdef CONFIG_NL80211_TESTMODE
+
+void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len);
+int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len);
+
+#else
+
+static inline void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf,
+ size_t buf_len)
+{
+}
+
+static inline int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len)
+{
+ return 0;
+}
+
+#endif
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
new file mode 100644
index 000000000000..a7117074f81c
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -0,0 +1,1478 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications 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 "debug.h"
+
+static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev,
+ u32 *map_no)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ struct ethhdr *eth_hdr;
+ u32 i, ep_map = -1;
+ u8 *datap;
+
+ *map_no = 0;
+ datap = skb->data;
+ eth_hdr = (struct ethhdr *) (datap + sizeof(struct wmi_data_hdr));
+
+ if (is_multicast_ether_addr(eth_hdr->h_dest))
+ return ENDPOINT_2;
+
+ for (i = 0; i < ar->node_num; i++) {
+ if (memcmp(eth_hdr->h_dest, ar->node_map[i].mac_addr,
+ ETH_ALEN) == 0) {
+ *map_no = i + 1;
+ ar->node_map[i].tx_pend++;
+ return ar->node_map[i].ep_id;
+ }
+
+ if ((ep_map == -1) && !ar->node_map[i].tx_pend)
+ ep_map = i;
+ }
+
+ if (ep_map == -1) {
+ ep_map = ar->node_num;
+ ar->node_num++;
+ if (ar->node_num > MAX_NODE_NUM)
+ return ENDPOINT_UNUSED;
+ }
+
+ memcpy(ar->node_map[ep_map].mac_addr, eth_hdr->h_dest, ETH_ALEN);
+
+ for (i = ENDPOINT_2; i <= ENDPOINT_5; i++) {
+ if (!ar->tx_pending[i]) {
+ ar->node_map[ep_map].ep_id = i;
+ break;
+ }
+
+ /*
+ * No free endpoint is available, start redistribution on
+ * the inuse endpoints.
+ */
+ if (i == ENDPOINT_5) {
+ ar->node_map[ep_map].ep_id = ar->next_ep_id;
+ ar->next_ep_id++;
+ if (ar->next_ep_id > ENDPOINT_5)
+ ar->next_ep_id = ENDPOINT_2;
+ }
+ }
+
+ *map_no = ep_map + 1;
+ ar->node_map[ep_map].tx_pend++;
+
+ return ar->node_map[ep_map].ep_id;
+}
+
+static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
+ bool *more_data)
+{
+ struct ethhdr *datap = (struct ethhdr *) skb->data;
+ struct ath6kl_sta *conn = NULL;
+ bool ps_queued = false, is_psq_empty = false;
+
+ if (is_multicast_ether_addr(datap->h_dest)) {
+ u8 ctr = 0;
+ bool q_mcast = false;
+
+ for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
+ if (ar->sta_list[ctr].sta_flags & STA_PS_SLEEP) {
+ q_mcast = true;
+ break;
+ }
+ }
+
+ if (q_mcast) {
+ /*
+ * If this transmit is not because of a Dtim Expiry
+ * q it.
+ */
+ if (!test_bit(DTIM_EXPIRED, &ar->flag)) {
+ bool is_mcastq_empty = false;
+
+ spin_lock_bh(&ar->mcastpsq_lock);
+ is_mcastq_empty =
+ skb_queue_empty(&ar->mcastpsq);
+ skb_queue_tail(&ar->mcastpsq, skb);
+ spin_unlock_bh(&ar->mcastpsq_lock);
+
+ /*
+ * If this is the first Mcast pkt getting
+ * queued indicate to the target to set the
+ * BitmapControl LSB of the TIM IE.
+ */
+ if (is_mcastq_empty)
+ ath6kl_wmi_set_pvb_cmd(ar->wmi,
+ MCAST_AID, 1);
+
+ ps_queued = true;
+ } else {
+ /*
+ * This transmit is because of Dtim expiry.
+ * Determine if MoreData bit has to be set.
+ */
+ spin_lock_bh(&ar->mcastpsq_lock);
+ if (!skb_queue_empty(&ar->mcastpsq))
+ *more_data = true;
+ spin_unlock_bh(&ar->mcastpsq_lock);
+ }
+ }
+ } else {
+ conn = ath6kl_find_sta(ar, datap->h_dest);
+ if (!conn) {
+ dev_kfree_skb(skb);
+
+ /* Inform the caller that the skb is consumed */
+ return true;
+ }
+
+ if (conn->sta_flags & STA_PS_SLEEP) {
+ if (!(conn->sta_flags & STA_PS_POLLED)) {
+ /* Queue the frames if the STA is sleeping */
+ spin_lock_bh(&conn->psq_lock);
+ is_psq_empty = skb_queue_empty(&conn->psq);
+ skb_queue_tail(&conn->psq, skb);
+ spin_unlock_bh(&conn->psq_lock);
+
+ /*
+ * If this is the first pkt getting queued
+ * for this STA, update the PVB for this
+ * STA.
+ */
+ if (is_psq_empty)
+ ath6kl_wmi_set_pvb_cmd(ar->wmi,
+ conn->aid, 1);
+
+ ps_queued = true;
+ } else {
+ /*
+ * This tx is because of a PsPoll.
+ * Determine if MoreData bit has to be set.
+ */
+ spin_lock_bh(&conn->psq_lock);
+ if (!skb_queue_empty(&conn->psq))
+ *more_data = true;
+ spin_unlock_bh(&conn->psq_lock);
+ }
+ }
+ }
+
+ return ps_queued;
+}
+
+/* Tx functions */
+
+int ath6kl_control_tx(void *devt, struct sk_buff *skb,
+ enum htc_endpoint_id eid)
+{
+ struct ath6kl *ar = devt;
+ int status = 0;
+ struct ath6kl_cookie *cookie = NULL;
+
+ spin_lock_bh(&ar->lock);
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
+ "%s: skb=0x%p, len=0x%x eid =%d\n", __func__,
+ skb, skb->len, eid);
+
+ if (test_bit(WMI_CTRL_EP_FULL, &ar->flag) && (eid == ar->ctrl_ep)) {
+ /*
+ * Control endpoint is full, don't allocate resources, we
+ * are just going to drop this packet.
+ */
+ cookie = NULL;
+ ath6kl_err("wmi ctrl ep full, dropping pkt : 0x%p, len:%d\n",
+ skb, skb->len);
+ } else
+ cookie = ath6kl_alloc_cookie(ar);
+
+ if (cookie == NULL) {
+ spin_unlock_bh(&ar->lock);
+ status = -ENOMEM;
+ goto fail_ctrl_tx;
+ }
+
+ ar->tx_pending[eid]++;
+
+ if (eid != ar->ctrl_ep)
+ ar->total_tx_data_pend++;
+
+ spin_unlock_bh(&ar->lock);
+
+ cookie->skb = skb;
+ cookie->map_no = 0;
+ set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len,
+ eid, ATH6KL_CONTROL_PKT_TAG);
+
+ /*
+ * This interface is asynchronous, if there is an error, cleanup
+ * will happen in the TX completion callback.
+ */
+ ath6kl_htc_tx(ar->htc_target, &cookie->htc_pkt);
+
+ return 0;
+
+fail_ctrl_tx:
+ dev_kfree_skb(skb);
+ return status;
+}
+
+int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ath6kl *ar = ath6kl_priv(dev);
+ struct ath6kl_cookie *cookie = NULL;
+ enum htc_endpoint_id eid = ENDPOINT_UNUSED;
+ u32 map_no = 0;
+ u16 htc_tag = ATH6KL_DATA_PKT_TAG;
+ u8 ac = 99 ; /* initialize to unmapped ac */
+ bool chk_adhoc_ps_mapping = false, more_data = false;
+ int ret;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
+ "%s: skb=0x%p, data=0x%p, len=0x%x\n", __func__,
+ skb, skb->data, skb->len);
+
+ /* If target is not associated */
+ if (!test_bit(CONNECTED, &ar->flag)) {
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ if (!test_bit(WMI_READY, &ar->flag))
+ goto fail_tx;
+
+ /* AP mode Power saving processing */
+ if (ar->nw_type == AP_NETWORK) {
+ if (ath6kl_powersave_ap(ar, skb, &more_data))
+ return 0;
+ }
+
+ if (test_bit(WMI_ENABLED, &ar->flag)) {
+ if (skb_headroom(skb) < dev->needed_headroom) {
+ WARN_ON(1);
+ goto fail_tx;
+ }
+
+ if (ath6kl_wmi_dix_2_dot3(ar->wmi, skb)) {
+ ath6kl_err("ath6kl_wmi_dix_2_dot3 failed\n");
+ goto fail_tx;
+ }
+
+ if (ath6kl_wmi_data_hdr_add(ar->wmi, skb, DATA_MSGTYPE,
+ more_data, 0, 0, NULL)) {
+ ath6kl_err("wmi_data_hdr_add failed\n");
+ goto fail_tx;
+ }
+
+ if ((ar->nw_type == ADHOC_NETWORK) &&
+ ar->ibss_ps_enable && test_bit(CONNECTED, &ar->flag))
+ chk_adhoc_ps_mapping = true;
+ else {
+ /* get the stream mapping */
+ ret = ath6kl_wmi_implicit_create_pstream(ar->wmi, skb,
+ 0, test_bit(WMM_ENABLED, &ar->flag), &ac);
+ if (ret)
+ goto fail_tx;
+ }
+ } else
+ goto fail_tx;
+
+ spin_lock_bh(&ar->lock);
+
+ if (chk_adhoc_ps_mapping)
+ eid = ath6kl_ibss_map_epid(skb, dev, &map_no);
+ else
+ eid = ar->ac2ep_map[ac];
+
+ if (eid == 0 || eid == ENDPOINT_UNUSED) {
+ ath6kl_err("eid %d is not mapped!\n", eid);
+ spin_unlock_bh(&ar->lock);
+ goto fail_tx;
+ }
+
+ /* allocate resource for this packet */
+ cookie = ath6kl_alloc_cookie(ar);
+
+ if (!cookie) {
+ spin_unlock_bh(&ar->lock);
+ goto fail_tx;
+ }
+
+ /* update counts while the lock is held */
+ ar->tx_pending[eid]++;
+ ar->total_tx_data_pend++;
+
+ spin_unlock_bh(&ar->lock);
+
+ if (!IS_ALIGNED((unsigned long) skb->data - HTC_HDR_LENGTH, 4) &&
+ skb_cloned(skb)) {
+ /*
+ * We will touch (move the buffer data to align it. Since the
+ * skb buffer is cloned and not only the header is changed, we
+ * have to copy it to allow the changes. Since we are copying
+ * the data here, we may as well align it by reserving suitable
+ * headroom to avoid the memmove in ath6kl_htc_tx_buf_align().
+ */
+ struct sk_buff *nskb;
+
+ nskb = skb_copy_expand(skb, HTC_HDR_LENGTH, 0, GFP_ATOMIC);
+ if (nskb == NULL)
+ goto fail_tx;
+ kfree_skb(skb);
+ skb = nskb;
+ }
+
+ cookie->skb = skb;
+ cookie->map_no = map_no;
+ set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len,
+ eid, htc_tag);
+
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "tx ",
+ skb->data, skb->len);
+
+ /*
+ * HTC interface is asynchronous, if this fails, cleanup will
+ * happen in the ath6kl_tx_complete callback.
+ */
+ ath6kl_htc_tx(ar->htc_target, &cookie->htc_pkt);
+
+ return 0;
+
+fail_tx:
+ dev_kfree_skb(skb);
+
+ ar->net_stats.tx_dropped++;
+ ar->net_stats.tx_aborted_errors++;
+
+ return 0;
+}
+
+/* indicate tx activity or inactivity on a WMI stream */
+void ath6kl_indicate_tx_activity(void *devt, u8 traffic_class, bool active)
+{
+ struct ath6kl *ar = devt;
+ enum htc_endpoint_id eid;
+ int i;
+
+ eid = ar->ac2ep_map[traffic_class];
+
+ if (!test_bit(WMI_ENABLED, &ar->flag))
+ goto notify_htc;
+
+ spin_lock_bh(&ar->lock);
+
+ ar->ac_stream_active[traffic_class] = active;
+
+ if (active) {
+ /*
+ * Keep track of the active stream with the highest
+ * priority.
+ */
+ if (ar->ac_stream_pri_map[traffic_class] >
+ ar->hiac_stream_active_pri)
+ /* set the new highest active priority */
+ ar->hiac_stream_active_pri =
+ ar->ac_stream_pri_map[traffic_class];
+
+ } else {
+ /*
+ * We may have to search for the next active stream
+ * that is the highest priority.
+ */
+ if (ar->hiac_stream_active_pri ==
+ ar->ac_stream_pri_map[traffic_class]) {
+ /*
+ * The highest priority stream just went inactive
+ * reset and search for the "next" highest "active"
+ * priority stream.
+ */
+ ar->hiac_stream_active_pri = 0;
+
+ for (i = 0; i < WMM_NUM_AC; i++) {
+ if (ar->ac_stream_active[i] &&
+ (ar->ac_stream_pri_map[i] >
+ ar->hiac_stream_active_pri))
+ /*
+ * Set the new highest active
+ * priority.
+ */
+ ar->hiac_stream_active_pri =
+ ar->ac_stream_pri_map[i];
+ }
+ }
+ }
+
+ spin_unlock_bh(&ar->lock);
+
+notify_htc:
+ /* notify HTC, this may cause credit distribution changes */
+ ath6kl_htc_indicate_activity_change(ar->htc_target, eid, active);
+}
+
+enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
+ struct htc_packet *packet)
+{
+ struct ath6kl *ar = target->dev->ar;
+ enum htc_endpoint_id endpoint = packet->endpoint;
+
+ if (endpoint == ar->ctrl_ep) {
+ /*
+ * Under normal WMI if this is getting full, then something
+ * is running rampant the host should not be exhausting the
+ * WMI queue with too many commands the only exception to
+ * this is during testing using endpointping.
+ */
+ spin_lock_bh(&ar->lock);
+ set_bit(WMI_CTRL_EP_FULL, &ar->flag);
+ spin_unlock_bh(&ar->lock);
+ ath6kl_err("wmi ctrl ep is full\n");
+ return HTC_SEND_FULL_KEEP;
+ }
+
+ if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG)
+ return HTC_SEND_FULL_KEEP;
+
+ if (ar->nw_type == ADHOC_NETWORK)
+ /*
+ * In adhoc mode, we cannot differentiate traffic
+ * priorities so there is no need to continue, however we
+ * should stop the network.
+ */
+ goto stop_net_queues;
+
+ /*
+ * The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for
+ * the highest active stream.
+ */
+ if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] <
+ ar->hiac_stream_active_pri &&
+ ar->cookie_count <= MAX_HI_COOKIE_NUM)
+ /*
+ * Give preference to the highest priority stream by
+ * dropping the packets which overflowed.
+ */
+ return HTC_SEND_FULL_DROP;
+
+stop_net_queues:
+ spin_lock_bh(&ar->lock);
+ set_bit(NETQ_STOPPED, &ar->flag);
+ spin_unlock_bh(&ar->lock);
+ netif_stop_queue(ar->net_dev);
+
+ return HTC_SEND_FULL_KEEP;
+}
+
+/* TODO this needs to be looked at */
+static void ath6kl_tx_clear_node_map(struct ath6kl *ar,
+ enum htc_endpoint_id eid, u32 map_no)
+{
+ u32 i;
+
+ if (ar->nw_type != ADHOC_NETWORK)
+ return;
+
+ if (!ar->ibss_ps_enable)
+ return;
+
+ if (eid == ar->ctrl_ep)
+ return;
+
+ if (map_no == 0)
+ return;
+
+ map_no--;
+ ar->node_map[map_no].tx_pend--;
+
+ if (ar->node_map[map_no].tx_pend)
+ return;
+
+ if (map_no != (ar->node_num - 1))
+ return;
+
+ for (i = ar->node_num; i > 0; i--) {
+ if (ar->node_map[i - 1].tx_pend)
+ break;
+
+ memset(&ar->node_map[i - 1], 0,
+ sizeof(struct ath6kl_node_mapping));
+ ar->node_num--;
+ }
+}
+
+void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
+{
+ struct ath6kl *ar = context;
+ struct sk_buff_head skb_queue;
+ struct htc_packet *packet;
+ struct sk_buff *skb;
+ struct ath6kl_cookie *ath6kl_cookie;
+ u32 map_no = 0;
+ int status;
+ enum htc_endpoint_id eid;
+ bool wake_event = false;
+ bool flushing = false;
+
+ skb_queue_head_init(&skb_queue);
+
+ /* lock the driver as we update internal state */
+ spin_lock_bh(&ar->lock);
+
+ /* reap completed packets */
+ while (!list_empty(packet_queue)) {
+
+ packet = list_first_entry(packet_queue, struct htc_packet,
+ list);
+ list_del(&packet->list);
+
+ ath6kl_cookie = (struct ath6kl_cookie *)packet->pkt_cntxt;
+ if (!ath6kl_cookie)
+ goto fatal;
+
+ status = packet->status;
+ skb = ath6kl_cookie->skb;
+ eid = packet->endpoint;
+ map_no = ath6kl_cookie->map_no;
+
+ if (!skb || !skb->data)
+ goto fatal;
+
+ packet->buf = skb->data;
+
+ __skb_queue_tail(&skb_queue, skb);
+
+ if (!status && (packet->act_len != skb->len))
+ goto fatal;
+
+ ar->tx_pending[eid]--;
+
+ if (eid != ar->ctrl_ep)
+ ar->total_tx_data_pend--;
+
+ if (eid == ar->ctrl_ep) {
+ if (test_bit(WMI_CTRL_EP_FULL, &ar->flag))
+ clear_bit(WMI_CTRL_EP_FULL, &ar->flag);
+
+ if (ar->tx_pending[eid] == 0)
+ wake_event = true;
+ }
+
+ if (status) {
+ if (status == -ECANCELED)
+ /* a packet was flushed */
+ flushing = true;
+
+ ar->net_stats.tx_errors++;
+
+ if (status != -ENOSPC)
+ ath6kl_err("tx error, status: 0x%x\n", status);
+ ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
+ "%s: skb=0x%p data=0x%p len=0x%x eid=%d %s\n",
+ __func__, skb, packet->buf, packet->act_len,
+ eid, "error!");
+ } else {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
+ "%s: skb=0x%p data=0x%p len=0x%x eid=%d %s\n",
+ __func__, skb, packet->buf, packet->act_len,
+ eid, "OK");
+
+ flushing = false;
+ ar->net_stats.tx_packets++;
+ ar->net_stats.tx_bytes += skb->len;
+ }
+
+ ath6kl_tx_clear_node_map(ar, eid, map_no);
+
+ ath6kl_free_cookie(ar, ath6kl_cookie);
+
+ if (test_bit(NETQ_STOPPED, &ar->flag))
+ clear_bit(NETQ_STOPPED, &ar->flag);
+ }
+
+ spin_unlock_bh(&ar->lock);
+
+ __skb_queue_purge(&skb_queue);
+
+ if (test_bit(CONNECTED, &ar->flag)) {
+ if (!flushing)
+ netif_wake_queue(ar->net_dev);
+ }
+
+ if (wake_event)
+ wake_up(&ar->event_wq);
+
+ return;
+
+fatal:
+ WARN_ON(1);
+ spin_unlock_bh(&ar->lock);
+ return;
+}
+
+void ath6kl_tx_data_cleanup(struct ath6kl *ar)
+{
+ int i;
+
+ /* flush all the data (non-control) streams */
+ for (i = 0; i < WMM_NUM_AC; i++)
+ ath6kl_htc_flush_txep(ar->htc_target, ar->ac2ep_map[i],
+ ATH6KL_DATA_PKT_TAG);
+}
+
+/* Rx functions */
+
+static void ath6kl_deliver_frames_to_nw_stack(struct net_device *dev,
+ struct sk_buff *skb)
+{
+ if (!skb)
+ return;
+
+ skb->dev = dev;
+
+ if (!(skb->dev->flags & IFF_UP)) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ skb->protocol = eth_type_trans(skb, skb->dev);
+
+ netif_rx_ni(skb);
+}
+
+static void ath6kl_alloc_netbufs(struct sk_buff_head *q, u16 num)
+{
+ struct sk_buff *skb;
+
+ while (num) {
+ skb = ath6kl_buf_alloc(ATH6KL_BUFFER_SIZE);
+ if (!skb) {
+ ath6kl_err("netbuf allocation failed\n");
+ return;
+ }
+ skb_queue_tail(q, skb);
+ num--;
+ }
+}
+
+static struct sk_buff *aggr_get_free_skb(struct aggr_info *p_aggr)
+{
+ struct sk_buff *skb = NULL;
+
+ if (skb_queue_len(&p_aggr->free_q) < (AGGR_NUM_OF_FREE_NETBUFS >> 2))
+ ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS);
+
+ skb = skb_dequeue(&p_aggr->free_q);
+
+ return skb;
+}
+
+void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
+{
+ struct ath6kl *ar = target->dev->ar;
+ struct sk_buff *skb;
+ int rx_buf;
+ int n_buf_refill;
+ struct htc_packet *packet;
+ struct list_head queue;
+
+ n_buf_refill = ATH6KL_MAX_RX_BUFFERS -
+ ath6kl_htc_get_rxbuf_num(ar->htc_target, endpoint);
+
+ if (n_buf_refill <= 0)
+ return;
+
+ INIT_LIST_HEAD(&queue);
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_RX,
+ "%s: providing htc with %d buffers at eid=%d\n",
+ __func__, n_buf_refill, endpoint);
+
+ for (rx_buf = 0; rx_buf < n_buf_refill; rx_buf++) {
+ skb = ath6kl_buf_alloc(ATH6KL_BUFFER_SIZE);
+ if (!skb)
+ break;
+
+ packet = (struct htc_packet *) skb->head;
+ if (!IS_ALIGNED((unsigned long) skb->data, 4))
+ skb->data = PTR_ALIGN(skb->data - 4, 4);
+ set_htc_rxpkt_info(packet, skb, skb->data,
+ ATH6KL_BUFFER_SIZE, endpoint);
+ list_add_tail(&packet->list, &queue);
+ }
+
+ if (!list_empty(&queue))
+ ath6kl_htc_add_rxbuf_multiple(ar->htc_target, &queue);
+}
+
+void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count)
+{
+ struct htc_packet *packet;
+ struct sk_buff *skb;
+
+ while (count) {
+ skb = ath6kl_buf_alloc(ATH6KL_AMSDU_BUFFER_SIZE);
+ if (!skb)
+ return;
+
+ packet = (struct htc_packet *) skb->head;
+ if (!IS_ALIGNED((unsigned long) skb->data, 4))
+ skb->data = PTR_ALIGN(skb->data - 4, 4);
+ set_htc_rxpkt_info(packet, skb, skb->data,
+ ATH6KL_AMSDU_BUFFER_SIZE, 0);
+ spin_lock_bh(&ar->lock);
+ list_add_tail(&packet->list, &ar->amsdu_rx_buffer_queue);
+ spin_unlock_bh(&ar->lock);
+ count--;
+ }
+}
+
+/*
+ * Callback to allocate a receive buffer for a pending packet. We use a
+ * pre-allocated list of buffers of maximum AMSDU size (4K).
+ */
+struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target,
+ enum htc_endpoint_id endpoint,
+ int len)
+{
+ struct ath6kl *ar = target->dev->ar;
+ struct htc_packet *packet = NULL;
+ struct list_head *pkt_pos;
+ int refill_cnt = 0, depth = 0;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: eid=%d, len:%d\n",
+ __func__, endpoint, len);
+
+ if ((len <= ATH6KL_BUFFER_SIZE) ||
+ (len > ATH6KL_AMSDU_BUFFER_SIZE))
+ return NULL;
+
+ spin_lock_bh(&ar->lock);
+
+ if (list_empty(&ar->amsdu_rx_buffer_queue)) {
+ spin_unlock_bh(&ar->lock);
+ refill_cnt = ATH6KL_MAX_AMSDU_RX_BUFFERS;
+ goto refill_buf;
+ }
+
+ packet = list_first_entry(&ar->amsdu_rx_buffer_queue,
+ struct htc_packet, list);
+ list_del(&packet->list);
+ list_for_each(pkt_pos, &ar->amsdu_rx_buffer_queue)
+ depth++;
+
+ refill_cnt = ATH6KL_MAX_AMSDU_RX_BUFFERS - depth;
+ spin_unlock_bh(&ar->lock);
+
+ /* set actual endpoint ID */
+ packet->endpoint = endpoint;
+
+refill_buf:
+ if (refill_cnt >= ATH6KL_AMSDU_REFILL_THRESHOLD)
+ ath6kl_refill_amsdu_rxbufs(ar, refill_cnt);
+
+ return packet;
+}
+
+static void aggr_slice_amsdu(struct aggr_info *p_aggr,
+ struct rxtid *rxtid, struct sk_buff *skb)
+{
+ struct sk_buff *new_skb;
+ struct ethhdr *hdr;
+ u16 frame_8023_len, payload_8023_len, mac_hdr_len, amsdu_len;
+ u8 *framep;
+
+ mac_hdr_len = sizeof(struct ethhdr);
+ framep = skb->data + mac_hdr_len;
+ amsdu_len = skb->len - mac_hdr_len;
+
+ while (amsdu_len > mac_hdr_len) {
+ hdr = (struct ethhdr *) framep;
+ payload_8023_len = ntohs(hdr->h_proto);
+
+ if (payload_8023_len < MIN_MSDU_SUBFRAME_PAYLOAD_LEN ||
+ payload_8023_len > MAX_MSDU_SUBFRAME_PAYLOAD_LEN) {
+ ath6kl_err("802.3 AMSDU frame bound check failed. len %d\n",
+ payload_8023_len);
+ break;
+ }
+
+ frame_8023_len = payload_8023_len + mac_hdr_len;
+ new_skb = aggr_get_free_skb(p_aggr);
+ if (!new_skb) {
+ ath6kl_err("no buffer available\n");
+ break;
+ }
+
+ memcpy(new_skb->data, framep, frame_8023_len);
+ skb_put(new_skb, frame_8023_len);
+ if (ath6kl_wmi_dot3_2_dix(new_skb)) {
+ ath6kl_err("dot3_2_dix error\n");
+ dev_kfree_skb(new_skb);
+ break;
+ }
+
+ skb_queue_tail(&rxtid->q, new_skb);
+
+ /* Is this the last subframe within this aggregate ? */
+ if ((amsdu_len - frame_8023_len) == 0)
+ break;
+
+ /* Add the length of A-MSDU subframe padding bytes -
+ * Round to nearest word.
+ */
+ frame_8023_len = ALIGN(frame_8023_len, 4);
+
+ framep += frame_8023_len;
+ amsdu_len -= frame_8023_len;
+ }
+
+ dev_kfree_skb(skb);
+}
+
+static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid,
+ u16 seq_no, u8 order)
+{
+ struct sk_buff *skb;
+ struct rxtid *rxtid;
+ struct skb_hold_q *node;
+ u16 idx, idx_end, seq_end;
+ struct rxtid_stats *stats;
+
+ if (!p_aggr)
+ return;
+
+ rxtid = &p_aggr->rx_tid[tid];
+ stats = &p_aggr->stat[tid];
+
+ idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
+
+ /*
+ * idx_end is typically the last possible frame in the window,
+ * but changes to 'the' seq_no, when BAR comes. If seq_no
+ * is non-zero, we will go up to that and stop.
+ * Note: last seq no in current window will occupy the same
+ * index position as index that is just previous to start.
+ * An imp point : if win_sz is 7, for seq_no space of 4095,
+ * then, there would be holes when sequence wrap around occurs.
+ * Target should judiciously choose the win_sz, based on
+ * this condition. For 4095, (TID_WINDOW_SZ = 2 x win_sz
+ * 2, 4, 8, 16 win_sz works fine).
+ * We must deque from "idx" to "idx_end", including both.
+ */
+ seq_end = seq_no ? seq_no : rxtid->seq_next;
+ idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz);
+
+ spin_lock_bh(&rxtid->lock);
+
+ do {
+ node = &rxtid->hold_q[idx];
+ if ((order == 1) && (!node->skb))
+ break;
+
+ if (node->skb) {
+ if (node->is_amsdu)
+ aggr_slice_amsdu(p_aggr, rxtid, node->skb);
+ else
+ skb_queue_tail(&rxtid->q, node->skb);
+ node->skb = NULL;
+ } else
+ stats->num_hole++;
+
+ rxtid->seq_next = ATH6KL_NEXT_SEQ_NO(rxtid->seq_next);
+ idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
+ } while (idx != idx_end);
+
+ spin_unlock_bh(&rxtid->lock);
+
+ stats->num_delivered += skb_queue_len(&rxtid->q);
+
+ while ((skb = skb_dequeue(&rxtid->q)))
+ ath6kl_deliver_frames_to_nw_stack(p_aggr->dev, skb);
+}
+
+static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid,
+ u16 seq_no,
+ bool is_amsdu, struct sk_buff *frame)
+{
+ struct rxtid *rxtid;
+ struct rxtid_stats *stats;
+ struct sk_buff *skb;
+ struct skb_hold_q *node;
+ u16 idx, st, cur, end;
+ bool is_queued = false;
+ u16 extended_end;
+
+ rxtid = &agg_info->rx_tid[tid];
+ stats = &agg_info->stat[tid];
+
+ stats->num_into_aggr++;
+
+ if (!rxtid->aggr) {
+ if (is_amsdu) {
+ aggr_slice_amsdu(agg_info, rxtid, frame);
+ is_queued = true;
+ stats->num_amsdu++;
+ while ((skb = skb_dequeue(&rxtid->q)))
+ ath6kl_deliver_frames_to_nw_stack(agg_info->dev,
+ skb);
+ }
+ return is_queued;
+ }
+
+ /* Check the incoming sequence no, if it's in the window */
+ st = rxtid->seq_next;
+ cur = seq_no;
+ end = (st + rxtid->hold_q_sz-1) & ATH6KL_MAX_SEQ_NO;
+
+ if (((st < end) && (cur < st || cur > end)) ||
+ ((st > end) && (cur > end) && (cur < st))) {
+ extended_end = (end + rxtid->hold_q_sz - 1) &
+ ATH6KL_MAX_SEQ_NO;
+
+ if (((end < extended_end) &&
+ (cur < end || cur > extended_end)) ||
+ ((end > extended_end) && (cur > extended_end) &&
+ (cur < end))) {
+ aggr_deque_frms(agg_info, tid, 0, 0);
+ if (cur >= rxtid->hold_q_sz - 1)
+ rxtid->seq_next = cur - (rxtid->hold_q_sz - 1);
+ else
+ rxtid->seq_next = ATH6KL_MAX_SEQ_NO -
+ (rxtid->hold_q_sz - 2 - cur);
+ } else {
+ /*
+ * Dequeue only those frames that are outside the
+ * new shifted window.
+ */
+ if (cur >= rxtid->hold_q_sz - 1)
+ st = cur - (rxtid->hold_q_sz - 1);
+ else
+ st = ATH6KL_MAX_SEQ_NO -
+ (rxtid->hold_q_sz - 2 - cur);
+
+ aggr_deque_frms(agg_info, tid, st, 0);
+ }
+
+ stats->num_oow++;
+ }
+
+ idx = AGGR_WIN_IDX(seq_no, rxtid->hold_q_sz);
+
+ node = &rxtid->hold_q[idx];
+
+ spin_lock_bh(&rxtid->lock);
+
+ /*
+ * Is the cur frame duplicate or something beyond our window(hold_q
+ * -> which is 2x, already)?
+ *
+ * 1. Duplicate is easy - drop incoming frame.
+ * 2. Not falling in current sliding window.
+ * 2a. is the frame_seq_no preceding current tid_seq_no?
+ * -> drop the frame. perhaps sender did not get our ACK.
+ * this is taken care of above.
+ * 2b. is the frame_seq_no beyond window(st, TID_WINDOW_SZ);
+ * -> Taken care of it above, by moving window forward.
+ */
+ dev_kfree_skb(node->skb);
+ stats->num_dups++;
+
+ node->skb = frame;
+ is_queued = true;
+ node->is_amsdu = is_amsdu;
+ node->seq_no = seq_no;
+
+ if (node->is_amsdu)
+ stats->num_amsdu++;
+ else
+ stats->num_mpdu++;
+
+ spin_unlock_bh(&rxtid->lock);
+
+ aggr_deque_frms(agg_info, tid, 0, 1);
+
+ if (agg_info->timer_scheduled)
+ rxtid->progress = true;
+ else
+ for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
+ if (rxtid->hold_q[idx].skb) {
+ /*
+ * There is a frame in the queue and no
+ * timer so start a timer to ensure that
+ * the frame doesn't remain stuck
+ * forever.
+ */
+ agg_info->timer_scheduled = true;
+ mod_timer(&agg_info->timer,
+ (jiffies +
+ HZ * (AGGR_RX_TIMEOUT) / 1000));
+ rxtid->progress = false;
+ rxtid->timer_mon = true;
+ break;
+ }
+ }
+
+ return is_queued;
+}
+
+void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
+{
+ struct ath6kl *ar = target->dev->ar;
+ struct sk_buff *skb = packet->pkt_cntxt;
+ struct wmi_rx_meta_v2 *meta;
+ struct wmi_data_hdr *dhdr;
+ int min_hdr_len;
+ u8 meta_type, dot11_hdr = 0;
+ int status = packet->status;
+ enum htc_endpoint_id ept = packet->endpoint;
+ bool is_amsdu, prev_ps, ps_state = false;
+ struct ath6kl_sta *conn = NULL;
+ struct sk_buff *skb1 = NULL;
+ struct ethhdr *datap = NULL;
+ u16 seq_no, offset;
+ u8 tid;
+
+ ath6kl_dbg(ATH6KL_DBG_WLAN_RX,
+ "%s: ar=0x%p eid=%d, skb=0x%p, data=0x%p, len=0x%x status:%d",
+ __func__, ar, ept, skb, packet->buf,
+ packet->act_len, status);
+
+ if (status || !(skb->data + HTC_HDR_LENGTH)) {
+ ar->net_stats.rx_errors++;
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ /*
+ * Take lock to protect buffer counts and adaptive power throughput
+ * state.
+ */
+ spin_lock_bh(&ar->lock);
+
+ ar->net_stats.rx_packets++;
+ ar->net_stats.rx_bytes += packet->act_len;
+
+ spin_unlock_bh(&ar->lock);
+
+ skb_put(skb, packet->act_len + HTC_HDR_LENGTH);
+ skb_pull(skb, HTC_HDR_LENGTH);
+
+ ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ",
+ skb->data, skb->len);
+
+ skb->dev = ar->net_dev;
+
+ if (!test_bit(WMI_ENABLED, &ar->flag)) {
+ if (EPPING_ALIGNMENT_PAD > 0)
+ skb_pull(skb, EPPING_ALIGNMENT_PAD);
+ ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb);
+ return;
+ }
+
+ if (ept == ar->ctrl_ep) {
+ ath6kl_wmi_control_rx(ar->wmi, skb);
+ return;
+ }
+
+ min_hdr_len = sizeof(struct ethhdr) + sizeof(struct wmi_data_hdr) +
+ sizeof(struct ath6kl_llc_snap_hdr);
+
+ dhdr = (struct wmi_data_hdr *) skb->data;
+
+ /*
+ * In the case of AP mode we may receive NULL data frames
+ * that do not have LLC hdr. They are 16 bytes in size.
+ * Allow these frames in the AP mode.
+ */
+ if (ar->nw_type != AP_NETWORK &&
+ ((packet->act_len < min_hdr_len) ||
+ (packet->act_len > WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH))) {
+ ath6kl_info("frame len is too short or too long\n");
+ ar->net_stats.rx_errors++;
+ ar->net_stats.rx_length_errors++;
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ /* Get the Power save state of the STA */
+ if (ar->nw_type == AP_NETWORK) {
+ meta_type = wmi_data_hdr_get_meta(dhdr);
+
+ ps_state = !!((dhdr->info >> WMI_DATA_HDR_PS_SHIFT) &
+ WMI_DATA_HDR_PS_MASK);
+
+ offset = sizeof(struct wmi_data_hdr);
+
+ switch (meta_type) {
+ case 0:
+ break;
+ case WMI_META_VERSION_1:
+ offset += sizeof(struct wmi_rx_meta_v1);
+ break;
+ case WMI_META_VERSION_2:
+ offset += sizeof(struct wmi_rx_meta_v2);
+ break;
+ default:
+ break;
+ }
+
+ datap = (struct ethhdr *) (skb->data + offset);
+ conn = ath6kl_find_sta(ar, datap->h_source);
+
+ if (!conn) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ /*
+ * If there is a change in PS state of the STA,
+ * take appropriate steps:
+ *
+ * 1. If Sleep-->Awake, flush the psq for the STA
+ * Clear the PVB for the STA.
+ * 2. If Awake-->Sleep, Starting queueing frames
+ * the STA.
+ */
+ prev_ps = !!(conn->sta_flags & STA_PS_SLEEP);
+
+ if (ps_state)
+ conn->sta_flags |= STA_PS_SLEEP;
+ else
+ conn->sta_flags &= ~STA_PS_SLEEP;
+
+ if (prev_ps ^ !!(conn->sta_flags & STA_PS_SLEEP)) {
+ if (!(conn->sta_flags & STA_PS_SLEEP)) {
+ struct sk_buff *skbuff = NULL;
+
+ spin_lock_bh(&conn->psq_lock);
+ while ((skbuff = skb_dequeue(&conn->psq))
+ != NULL) {
+ spin_unlock_bh(&conn->psq_lock);
+ ath6kl_data_tx(skbuff, ar->net_dev);
+ spin_lock_bh(&conn->psq_lock);
+ }
+ spin_unlock_bh(&conn->psq_lock);
+ /* Clear the PVB for this STA */
+ ath6kl_wmi_set_pvb_cmd(ar->wmi, conn->aid, 0);
+ }
+ }
+
+ /* drop NULL data frames here */
+ if ((packet->act_len < min_hdr_len) ||
+ (packet->act_len >
+ WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH)) {
+ dev_kfree_skb(skb);
+ return;
+ }
+ }
+
+ is_amsdu = wmi_data_hdr_is_amsdu(dhdr) ? true : false;
+ tid = wmi_data_hdr_get_up(dhdr);
+ seq_no = wmi_data_hdr_get_seqno(dhdr);
+ meta_type = wmi_data_hdr_get_meta(dhdr);
+ dot11_hdr = wmi_data_hdr_get_dot11(dhdr);
+ skb_pull(skb, sizeof(struct wmi_data_hdr));
+
+ switch (meta_type) {
+ case WMI_META_VERSION_1:
+ skb_pull(skb, sizeof(struct wmi_rx_meta_v1));
+ break;
+ case WMI_META_VERSION_2:
+ meta = (struct wmi_rx_meta_v2 *) skb->data;
+ if (meta->csum_flags & 0x1) {
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb->csum = (__force __wsum) meta->csum;
+ }
+ skb_pull(skb, sizeof(struct wmi_rx_meta_v2));
+ break;
+ default:
+ break;
+ }
+
+ if (dot11_hdr)
+ status = ath6kl_wmi_dot11_hdr_remove(ar->wmi, skb);
+ else if (!is_amsdu)
+ status = ath6kl_wmi_dot3_2_dix(skb);
+
+ if (status) {
+ /*
+ * Drop frames that could not be processed (lack of
+ * memory, etc.)
+ */
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ if (!(ar->net_dev->flags & IFF_UP)) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ if (ar->nw_type == AP_NETWORK) {
+ datap = (struct ethhdr *) skb->data;
+ if (is_multicast_ether_addr(datap->h_dest))
+ /*
+ * Bcast/Mcast frames should be sent to the
+ * OS stack as well as on the air.
+ */
+ skb1 = skb_copy(skb, GFP_ATOMIC);
+ else {
+ /*
+ * Search for a connected STA with dstMac
+ * as the Mac address. If found send the
+ * frame to it on the air else send the
+ * frame up the stack.
+ */
+ struct ath6kl_sta *conn = NULL;
+ conn = ath6kl_find_sta(ar, datap->h_dest);
+
+ if (conn && ar->intra_bss) {
+ skb1 = skb;
+ skb = NULL;
+ } else if (conn && !ar->intra_bss) {
+ dev_kfree_skb(skb);
+ skb = NULL;
+ }
+ }
+ if (skb1)
+ ath6kl_data_tx(skb1, ar->net_dev);
+ }
+
+ datap = (struct ethhdr *) skb->data;
+
+ if (is_unicast_ether_addr(datap->h_dest) &&
+ aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no,
+ is_amsdu, skb))
+ /* aggregation code will handle the skb */
+ return;
+
+ ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb);
+}
+
+static void aggr_timeout(unsigned long arg)
+{
+ u8 i, j;
+ struct aggr_info *p_aggr = (struct aggr_info *) arg;
+ struct rxtid *rxtid;
+ struct rxtid_stats *stats;
+
+ for (i = 0; i < NUM_OF_TIDS; i++) {
+ rxtid = &p_aggr->rx_tid[i];
+ stats = &p_aggr->stat[i];
+
+ if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress)
+ continue;
+
+ stats->num_timeouts++;
+ ath6kl_dbg(ATH6KL_DBG_AGGR,
+ "aggr timeout (st %d end %d)\n",
+ rxtid->seq_next,
+ ((rxtid->seq_next + rxtid->hold_q_sz-1) &
+ ATH6KL_MAX_SEQ_NO));
+ aggr_deque_frms(p_aggr, i, 0, 0);
+ }
+
+ p_aggr->timer_scheduled = false;
+
+ for (i = 0; i < NUM_OF_TIDS; i++) {
+ rxtid = &p_aggr->rx_tid[i];
+
+ if (rxtid->aggr && rxtid->hold_q) {
+ for (j = 0; j < rxtid->hold_q_sz; j++) {
+ if (rxtid->hold_q[j].skb) {
+ p_aggr->timer_scheduled = true;
+ rxtid->timer_mon = true;
+ rxtid->progress = false;
+ break;
+ }
+ }
+
+ if (j >= rxtid->hold_q_sz)
+ rxtid->timer_mon = false;
+ }
+ }
+
+ if (p_aggr->timer_scheduled)
+ mod_timer(&p_aggr->timer,
+ jiffies + msecs_to_jiffies(AGGR_RX_TIMEOUT));
+}
+
+static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid)
+{
+ struct rxtid *rxtid;
+ struct rxtid_stats *stats;
+
+ if (!p_aggr || tid >= NUM_OF_TIDS)
+ return;
+
+ rxtid = &p_aggr->rx_tid[tid];
+ stats = &p_aggr->stat[tid];
+
+ if (rxtid->aggr)
+ aggr_deque_frms(p_aggr, tid, 0, 0);
+
+ rxtid->aggr = false;
+ rxtid->progress = false;
+ rxtid->timer_mon = false;
+ rxtid->win_sz = 0;
+ rxtid->seq_next = 0;
+ rxtid->hold_q_sz = 0;
+
+ kfree(rxtid->hold_q);
+ rxtid->hold_q = NULL;
+
+ memset(stats, 0, sizeof(struct rxtid_stats));
+}
+
+void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, u8 win_sz)
+{
+ struct aggr_info *p_aggr = ar->aggr_cntxt;
+ struct rxtid *rxtid;
+ struct rxtid_stats *stats;
+ u16 hold_q_size;
+
+ if (!p_aggr)
+ return;
+
+ rxtid = &p_aggr->rx_tid[tid];
+ stats = &p_aggr->stat[tid];
+
+ if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX)
+ ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n",
+ __func__, win_sz, tid);
+
+ if (rxtid->aggr)
+ aggr_delete_tid_state(p_aggr, tid);
+
+ rxtid->seq_next = seq_no;
+ hold_q_size = TID_WINDOW_SZ(win_sz) * sizeof(struct skb_hold_q);
+ rxtid->hold_q = kzalloc(hold_q_size, GFP_KERNEL);
+ if (!rxtid->hold_q)
+ return;
+
+ rxtid->win_sz = win_sz;
+ rxtid->hold_q_sz = TID_WINDOW_SZ(win_sz);
+ if (!skb_queue_empty(&rxtid->q))
+ return;
+
+ rxtid->aggr = true;
+}
+
+struct aggr_info *aggr_init(struct net_device *dev)
+{
+ struct aggr_info *p_aggr = NULL;
+ struct rxtid *rxtid;
+ u8 i;
+
+ p_aggr = kzalloc(sizeof(struct aggr_info), GFP_KERNEL);
+ if (!p_aggr) {
+ ath6kl_err("failed to alloc memory for aggr_node\n");
+ return NULL;
+ }
+
+ p_aggr->aggr_sz = AGGR_SZ_DEFAULT;
+ p_aggr->dev = dev;
+ init_timer(&p_aggr->timer);
+ p_aggr->timer.function = aggr_timeout;
+ p_aggr->timer.data = (unsigned long) p_aggr;
+
+ p_aggr->timer_scheduled = false;
+ skb_queue_head_init(&p_aggr->free_q);
+
+ ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS);
+
+ for (i = 0; i < NUM_OF_TIDS; i++) {
+ rxtid = &p_aggr->rx_tid[i];
+ rxtid->aggr = false;
+ rxtid->progress = false;
+ rxtid->timer_mon = false;
+ skb_queue_head_init(&rxtid->q);
+ spin_lock_init(&rxtid->lock);
+ }
+
+ return p_aggr;
+}
+
+void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid)
+{
+ struct aggr_info *p_aggr = ar->aggr_cntxt;
+ struct rxtid *rxtid;
+
+ if (!p_aggr)
+ return;
+
+ rxtid = &p_aggr->rx_tid[tid];
+
+ if (rxtid->aggr)
+ aggr_delete_tid_state(p_aggr, tid);
+}
+
+void aggr_reset_state(struct aggr_info *aggr_info)
+{
+ u8 tid;
+
+ for (tid = 0; tid < NUM_OF_TIDS; tid++)
+ aggr_delete_tid_state(aggr_info, tid);
+}
+
+/* clean up our amsdu buffer list */
+void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar)
+{
+ struct htc_packet *packet, *tmp_pkt;
+
+ spin_lock_bh(&ar->lock);
+ if (list_empty(&ar->amsdu_rx_buffer_queue)) {
+ spin_unlock_bh(&ar->lock);
+ return;
+ }
+
+ list_for_each_entry_safe(packet, tmp_pkt, &ar->amsdu_rx_buffer_queue,
+ list) {
+ list_del(&packet->list);
+ spin_unlock_bh(&ar->lock);
+ dev_kfree_skb(packet->pkt_cntxt);
+ spin_lock_bh(&ar->lock);
+ }
+
+ spin_unlock_bh(&ar->lock);
+}
+
+void aggr_module_destroy(struct aggr_info *aggr_info)
+{
+ struct rxtid *rxtid;
+ u8 i, k;
+
+ if (!aggr_info)
+ return;
+
+ if (aggr_info->timer_scheduled) {
+ del_timer(&aggr_info->timer);
+ aggr_info->timer_scheduled = false;
+ }
+
+ for (i = 0; i < NUM_OF_TIDS; i++) {
+ rxtid = &aggr_info->rx_tid[i];
+ if (rxtid->hold_q) {
+ for (k = 0; k < rxtid->hold_q_sz; k++)
+ dev_kfree_skb(rxtid->hold_q[k].skb);
+ kfree(rxtid->hold_q);
+ }
+
+ skb_queue_purge(&rxtid->q);
+ }
+
+ skb_queue_purge(&aggr_info->free_q);
+ kfree(aggr_info);
+}
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
new file mode 100644
index 000000000000..a7de23cbd2c7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -0,0 +1,3127 @@
+/*
+ * Copyright (c) 2004-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/ip.h>
+#include "core.h"
+#include "debug.h"
+#include "testmode.h"
+#include "../regd.h"
+#include "../regd_common.h"
+
+static int ath6kl_wmi_sync_point(struct wmi *wmi);
+
+static const s32 wmi_rate_tbl[][2] = {
+ /* {W/O SGI, with SGI} */
+ {1000, 1000},
+ {2000, 2000},
+ {5500, 5500},
+ {11000, 11000},
+ {6000, 6000},
+ {9000, 9000},
+ {12000, 12000},
+ {18000, 18000},
+ {24000, 24000},
+ {36000, 36000},
+ {48000, 48000},
+ {54000, 54000},
+ {6500, 7200},
+ {13000, 14400},
+ {19500, 21700},
+ {26000, 28900},
+ {39000, 43300},
+ {52000, 57800},
+ {58500, 65000},
+ {65000, 72200},
+ {13500, 15000},
+ {27000, 30000},
+ {40500, 45000},
+ {54000, 60000},
+ {81000, 90000},
+ {108000, 120000},
+ {121500, 135000},
+ {135000, 150000},
+ {0, 0}
+};
+
+/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
+static const u8 up_to_ac[] = {
+ WMM_AC_BE,
+ WMM_AC_BK,
+ WMM_AC_BK,
+ WMM_AC_BE,
+ WMM_AC_VI,
+ WMM_AC_VI,
+ WMM_AC_VO,
+ WMM_AC_VO,
+};
+
+void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id)
+{
+ if (WARN_ON(ep_id == ENDPOINT_UNUSED || ep_id >= ENDPOINT_MAX))
+ return;
+
+ wmi->ep_id = ep_id;
+}
+
+enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi)
+{
+ return wmi->ep_id;
+}
+
+/* Performs DIX to 802.3 encapsulation for transmit packets.
+ * Assumes the entire DIX header is contigous and that there is
+ * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
+ */
+int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb)
+{
+ struct ath6kl_llc_snap_hdr *llc_hdr;
+ struct ethhdr *eth_hdr;
+ size_t new_len;
+ __be16 type;
+ u8 *datap;
+ u16 size;
+
+ if (WARN_ON(skb == NULL))
+ return -EINVAL;
+
+ size = sizeof(struct ath6kl_llc_snap_hdr) + sizeof(struct wmi_data_hdr);
+ if (skb_headroom(skb) < size)
+ return -ENOMEM;
+
+ eth_hdr = (struct ethhdr *) skb->data;
+ type = eth_hdr->h_proto;
+
+ if (!is_ethertype(be16_to_cpu(type))) {
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "%s: pkt is already in 802.3 format\n", __func__);
+ return 0;
+ }
+
+ new_len = skb->len - sizeof(*eth_hdr) + sizeof(*llc_hdr);
+
+ skb_push(skb, sizeof(struct ath6kl_llc_snap_hdr));
+ datap = skb->data;
+
+ eth_hdr->h_proto = cpu_to_be16(new_len);
+
+ memcpy(datap, eth_hdr, sizeof(*eth_hdr));
+
+ llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap + sizeof(*eth_hdr));
+ llc_hdr->dsap = 0xAA;
+ llc_hdr->ssap = 0xAA;
+ llc_hdr->cntl = 0x03;
+ llc_hdr->org_code[0] = 0x0;
+ llc_hdr->org_code[1] = 0x0;
+ llc_hdr->org_code[2] = 0x0;
+ llc_hdr->eth_type = type;
+
+ return 0;
+}
+
+static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb,
+ u8 *version, void *tx_meta_info)
+{
+ struct wmi_tx_meta_v1 *v1;
+ struct wmi_tx_meta_v2 *v2;
+
+ if (WARN_ON(skb == NULL || version == NULL))
+ return -EINVAL;
+
+ switch (*version) {
+ case WMI_META_VERSION_1:
+ skb_push(skb, WMI_MAX_TX_META_SZ);
+ v1 = (struct wmi_tx_meta_v1 *) skb->data;
+ v1->pkt_id = 0;
+ v1->rate_plcy_id = 0;
+ *version = WMI_META_VERSION_1;
+ break;
+ case WMI_META_VERSION_2:
+ skb_push(skb, WMI_MAX_TX_META_SZ);
+ v2 = (struct wmi_tx_meta_v2 *) skb->data;
+ memcpy(v2, (struct wmi_tx_meta_v2 *) tx_meta_info,
+ sizeof(struct wmi_tx_meta_v2));
+ break;
+ }
+
+ return 0;
+}
+
+int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
+ u8 msg_type, bool more_data,
+ enum wmi_data_hdr_data_type data_type,
+ u8 meta_ver, void *tx_meta_info)
+{
+ struct wmi_data_hdr *data_hdr;
+ int ret;
+
+ if (WARN_ON(skb == NULL))
+ return -EINVAL;
+
+ if (tx_meta_info) {
+ ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info);
+ if (ret)
+ return ret;
+ }
+
+ skb_push(skb, sizeof(struct wmi_data_hdr));
+
+ data_hdr = (struct wmi_data_hdr *)skb->data;
+ memset(data_hdr, 0, sizeof(struct wmi_data_hdr));
+
+ data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT;
+ data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT;
+
+ if (more_data)
+ data_hdr->info |=
+ WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT;
+
+ data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT);
+ data_hdr->info3 = 0;
+
+ return 0;
+}
+
+static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri)
+{
+ struct iphdr *ip_hdr = (struct iphdr *) pkt;
+ u8 ip_pri;
+
+ /*
+ * Determine IPTOS priority
+ *
+ * IP-TOS - 8bits
+ * : DSCP(6-bits) ECN(2-bits)
+ * : DSCP - P2 P1 P0 X X X
+ * where (P2 P1 P0) form 802.1D
+ */
+ ip_pri = ip_hdr->tos >> 5;
+ ip_pri &= 0x7;
+
+ if ((layer2_pri & 0x7) > ip_pri)
+ return (u8) layer2_pri & 0x7;
+ else
+ return ip_pri;
+}
+
+int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb,
+ u32 layer2_priority, bool wmm_enabled,
+ u8 *ac)
+{
+ struct wmi_data_hdr *data_hdr;
+ struct ath6kl_llc_snap_hdr *llc_hdr;
+ struct wmi_create_pstream_cmd cmd;
+ u32 meta_size, hdr_size;
+ u16 ip_type = IP_ETHERTYPE;
+ u8 stream_exist, usr_pri;
+ u8 traffic_class = WMM_AC_BE;
+ u8 *datap;
+
+ if (WARN_ON(skb == NULL))
+ return -EINVAL;
+
+ datap = skb->data;
+ data_hdr = (struct wmi_data_hdr *) datap;
+
+ meta_size = ((le16_to_cpu(data_hdr->info2) >> WMI_DATA_HDR_META_SHIFT) &
+ WMI_DATA_HDR_META_MASK) ? WMI_MAX_TX_META_SZ : 0;
+
+ if (!wmm_enabled) {
+ /* If WMM is disabled all traffic goes as BE traffic */
+ usr_pri = 0;
+ } else {
+ hdr_size = sizeof(struct ethhdr);
+
+ llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap +
+ sizeof(struct
+ wmi_data_hdr) +
+ meta_size + hdr_size);
+
+ if (llc_hdr->eth_type == htons(ip_type)) {
+ /*
+ * Extract the endpoint info from the TOS field
+ * in the IP header.
+ */
+ usr_pri =
+ ath6kl_wmi_determine_user_priority(((u8 *) llc_hdr) +
+ sizeof(struct ath6kl_llc_snap_hdr),
+ layer2_priority);
+ } else
+ usr_pri = layer2_priority & 0x7;
+ }
+
+ /* workaround for WMM S5 */
+ if ((wmi->traffic_class == WMM_AC_VI) &&
+ ((usr_pri == 5) || (usr_pri == 4)))
+ usr_pri = 1;
+
+ /* Convert user priority to traffic class */
+ traffic_class = up_to_ac[usr_pri & 0x7];
+
+ wmi_data_hdr_set_up(data_hdr, usr_pri);
+
+ spin_lock_bh(&wmi->lock);
+ stream_exist = wmi->fat_pipe_exist;
+ spin_unlock_bh(&wmi->lock);
+
+ if (!(stream_exist & (1 << traffic_class))) {
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.traffic_class = traffic_class;
+ cmd.user_pri = usr_pri;
+ cmd.inactivity_int =
+ cpu_to_le32(WMI_IMPLICIT_PSTREAM_INACTIVITY_INT);
+ /* Implicit streams are created with TSID 0xFF */
+ cmd.tsid = WMI_IMPLICIT_PSTREAM;
+ ath6kl_wmi_create_pstream_cmd(wmi, &cmd);
+ }
+
+ *ac = traffic_class;
+
+ return 0;
+}
+
+int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb)
+{
+ struct ieee80211_hdr_3addr *pwh, wh;
+ struct ath6kl_llc_snap_hdr *llc_hdr;
+ struct ethhdr eth_hdr;
+ u32 hdr_size;
+ u8 *datap;
+ __le16 sub_type;
+
+ if (WARN_ON(skb == NULL))
+ return -EINVAL;
+
+ datap = skb->data;
+ pwh = (struct ieee80211_hdr_3addr *) datap;
+
+ sub_type = pwh->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE);
+
+ memcpy((u8 *) &wh, datap, sizeof(struct ieee80211_hdr_3addr));
+
+ /* Strip off the 802.11 header */
+ if (sub_type == cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
+ hdr_size = roundup(sizeof(struct ieee80211_qos_hdr),
+ sizeof(u32));
+ skb_pull(skb, hdr_size);
+ } else if (sub_type == cpu_to_le16(IEEE80211_STYPE_DATA))
+ skb_pull(skb, sizeof(struct ieee80211_hdr_3addr));
+
+ datap = skb->data;
+ llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap);
+
+ memset(&eth_hdr, 0, sizeof(eth_hdr));
+ eth_hdr.h_proto = llc_hdr->eth_type;
+
+ switch ((le16_to_cpu(wh.frame_control)) &
+ (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
+ case 0:
+ memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
+ memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_TODS:
+ memcpy(eth_hdr.h_dest, wh.addr3, ETH_ALEN);
+ memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_FROMDS:
+ memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
+ memcpy(eth_hdr.h_source, wh.addr3, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
+ break;
+ }
+
+ skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr));
+ skb_push(skb, sizeof(eth_hdr));
+
+ datap = skb->data;
+
+ memcpy(datap, &eth_hdr, sizeof(eth_hdr));
+
+ return 0;
+}
+
+/*
+ * Performs 802.3 to DIX encapsulation for received packets.
+ * Assumes the entire 802.3 header is contigous.
+ */
+int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb)
+{
+ struct ath6kl_llc_snap_hdr *llc_hdr;
+ struct ethhdr eth_hdr;
+ u8 *datap;
+
+ if (WARN_ON(skb == NULL))
+ return -EINVAL;
+
+ datap = skb->data;
+
+ memcpy(&eth_hdr, datap, sizeof(eth_hdr));
+
+ llc_hdr = (struct ath6kl_llc_snap_hdr *) (datap + sizeof(eth_hdr));
+ eth_hdr.h_proto = llc_hdr->eth_type;
+
+ skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr));
+ datap = skb->data;
+
+ memcpy(datap, &eth_hdr, sizeof(eth_hdr));
+
+ return 0;
+}
+
+static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len)
+{
+ struct tx_complete_msg_v1 *msg_v1;
+ struct wmi_tx_complete_event *evt;
+ int index;
+ u16 size;
+
+ evt = (struct wmi_tx_complete_event *) datap;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n",
+ evt->num_msg, evt->msg_len, evt->msg_type);
+
+ if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_WMI))
+ return 0;
+
+ for (index = 0; index < evt->num_msg; index++) {
+ size = sizeof(struct wmi_tx_complete_event) +
+ (index * sizeof(struct tx_complete_msg_v1));
+ msg_v1 = (struct tx_complete_msg_v1 *)(datap + size);
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "msg: %d %d %d %d\n",
+ msg_v1->status, msg_v1->pkt_id,
+ msg_v1->rate_idx, msg_v1->ack_failures);
+ }
+
+ return 0;
+}
+
+static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
+ int len)
+{
+ struct wmi_remain_on_chnl_event *ev;
+ u32 freq;
+ u32 dur;
+ struct ieee80211_channel *chan;
+ struct ath6kl *ar = wmi->parent_dev;
+
+ if (len < sizeof(*ev))
+ return -EINVAL;
+
+ ev = (struct wmi_remain_on_chnl_event *) datap;
+ freq = le32_to_cpu(ev->freq);
+ dur = le32_to_cpu(ev->duration);
+ ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: freq=%u dur=%u\n",
+ freq, dur);
+ chan = ieee80211_get_channel(ar->wdev->wiphy, freq);
+ if (!chan) {
+ ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: Unknown channel "
+ "(freq=%u)\n", freq);
+ return -EINVAL;
+ }
+ cfg80211_ready_on_channel(ar->net_dev, 1, chan, NL80211_CHAN_NO_HT,
+ dur, GFP_ATOMIC);
+
+ return 0;
+}
+
+static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
+ u8 *datap, int len)
+{
+ struct wmi_cancel_remain_on_chnl_event *ev;
+ u32 freq;
+ u32 dur;
+ struct ieee80211_channel *chan;
+ struct ath6kl *ar = wmi->parent_dev;
+
+ if (len < sizeof(*ev))
+ return -EINVAL;
+
+ ev = (struct wmi_cancel_remain_on_chnl_event *) datap;
+ freq = le32_to_cpu(ev->freq);
+ dur = le32_to_cpu(ev->duration);
+ ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: freq=%u dur=%u "
+ "status=%u\n", freq, dur, ev->status);
+ chan = ieee80211_get_channel(ar->wdev->wiphy, freq);
+ if (!chan) {
+ ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: Unknown "
+ "channel (freq=%u)\n", freq);
+ return -EINVAL;
+ }
+ cfg80211_remain_on_channel_expired(ar->net_dev, 1, chan,
+ NL80211_CHAN_NO_HT, GFP_ATOMIC);
+
+ return 0;
+}
+
+static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_tx_status_event *ev;
+ u32 id;
+ struct ath6kl *ar = wmi->parent_dev;
+
+ if (len < sizeof(*ev))
+ return -EINVAL;
+
+ ev = (struct wmi_tx_status_event *) datap;
+ id = le32_to_cpu(ev->id);
+ ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n",
+ id, ev->ack_status);
+ if (wmi->last_mgmt_tx_frame) {
+ cfg80211_mgmt_tx_status(ar->net_dev, id,
+ wmi->last_mgmt_tx_frame,
+ wmi->last_mgmt_tx_frame_len,
+ !!ev->ack_status, GFP_ATOMIC);
+ kfree(wmi->last_mgmt_tx_frame);
+ wmi->last_mgmt_tx_frame = NULL;
+ wmi->last_mgmt_tx_frame_len = 0;
+ }
+
+ return 0;
+}
+
+static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_p2p_rx_probe_req_event *ev;
+ u32 freq;
+ u16 dlen;
+ struct ath6kl *ar = wmi->parent_dev;
+
+ if (len < sizeof(*ev))
+ return -EINVAL;
+
+ ev = (struct wmi_p2p_rx_probe_req_event *) datap;
+ freq = le32_to_cpu(ev->freq);
+ dlen = le16_to_cpu(ev->len);
+ if (datap + len < ev->data + dlen) {
+ ath6kl_err("invalid wmi_p2p_rx_probe_req_event: "
+ "len=%d dlen=%u\n", len, dlen);
+ return -EINVAL;
+ }
+ ath6kl_dbg(ATH6KL_DBG_WMI, "rx_probe_req: len=%u freq=%u "
+ "probe_req_report=%d\n",
+ dlen, freq, ar->probe_req_report);
+
+ if (ar->probe_req_report || ar->nw_type == AP_NETWORK)
+ cfg80211_rx_mgmt(ar->net_dev, freq, ev->data, dlen, GFP_ATOMIC);
+
+ return 0;
+}
+
+static int ath6kl_wmi_p2p_capabilities_event_rx(u8 *datap, int len)
+{
+ struct wmi_p2p_capabilities_event *ev;
+ u16 dlen;
+
+ if (len < sizeof(*ev))
+ return -EINVAL;
+
+ ev = (struct wmi_p2p_capabilities_event *) datap;
+ dlen = le16_to_cpu(ev->len);
+ ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_capab: len=%u\n", dlen);
+
+ return 0;
+}
+
+static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_rx_action_event *ev;
+ u32 freq;
+ u16 dlen;
+ struct ath6kl *ar = wmi->parent_dev;
+
+ if (len < sizeof(*ev))
+ return -EINVAL;
+
+ ev = (struct wmi_rx_action_event *) datap;
+ freq = le32_to_cpu(ev->freq);
+ dlen = le16_to_cpu(ev->len);
+ if (datap + len < ev->data + dlen) {
+ ath6kl_err("invalid wmi_rx_action_event: "
+ "len=%d dlen=%u\n", len, dlen);
+ return -EINVAL;
+ }
+ ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
+ cfg80211_rx_mgmt(ar->net_dev, freq, ev->data, dlen, GFP_ATOMIC);
+
+ return 0;
+}
+
+static int ath6kl_wmi_p2p_info_event_rx(u8 *datap, int len)
+{
+ struct wmi_p2p_info_event *ev;
+ u32 flags;
+ u16 dlen;
+
+ if (len < sizeof(*ev))
+ return -EINVAL;
+
+ ev = (struct wmi_p2p_info_event *) datap;
+ flags = le32_to_cpu(ev->info_req_flags);
+ dlen = le16_to_cpu(ev->len);
+ ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: flags=%x len=%d\n", flags, dlen);
+
+ if (flags & P2P_FLAG_CAPABILITIES_REQ) {
+ struct wmi_p2p_capabilities *cap;
+ if (dlen < sizeof(*cap))
+ return -EINVAL;
+ cap = (struct wmi_p2p_capabilities *) ev->data;
+ ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: GO Power Save = %d\n",
+ cap->go_power_save);
+ }
+
+ if (flags & P2P_FLAG_MACADDR_REQ) {
+ struct wmi_p2p_macaddr *mac;
+ if (dlen < sizeof(*mac))
+ return -EINVAL;
+ mac = (struct wmi_p2p_macaddr *) ev->data;
+ ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: MAC Address = %pM\n",
+ mac->mac_addr);
+ }
+
+ if (flags & P2P_FLAG_HMODEL_REQ) {
+ struct wmi_p2p_hmodel *mod;
+ if (dlen < sizeof(*mod))
+ return -EINVAL;
+ mod = (struct wmi_p2p_hmodel *) ev->data;
+ ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: P2P Model = %d (%s)\n",
+ mod->p2p_model,
+ mod->p2p_model ? "host" : "firmware");
+ }
+ return 0;
+}
+
+static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size)
+{
+ struct sk_buff *skb;
+
+ skb = ath6kl_buf_alloc(size);
+ if (!skb)
+ return NULL;
+
+ skb_put(skb, size);
+ if (size)
+ memset(skb->data, 0, size);
+
+ return skb;
+}
+
+/* Send a "simple" wmi command -- one with no arguments */
+static int ath6kl_wmi_simple_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id)
+{
+ struct sk_buff *skb;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(0);
+ if (!skb)
+ return -ENOMEM;
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, cmd_id, NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_ready_event_2 *ev = (struct wmi_ready_event_2 *) datap;
+
+ if (len < sizeof(struct wmi_ready_event_2))
+ return -EINVAL;
+
+ wmi->ready = true;
+ ath6kl_ready_event(wmi->parent_dev, ev->mac_addr,
+ le32_to_cpu(ev->sw_version),
+ le32_to_cpu(ev->abi_version));
+
+ return 0;
+}
+
+/*
+ * Mechanism to modify the roaming behavior in the firmware. The lower rssi
+ * at which the station has to roam can be passed with
+ * WMI_SET_LRSSI_SCAN_PARAMS. Subtract 96 from RSSI to get the signal level
+ * in dBm.
+ */
+int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi)
+{
+ struct sk_buff *skb;
+ struct roam_ctrl_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct roam_ctrl_cmd *) skb->data;
+
+ cmd->info.params.lrssi_scan_period = cpu_to_le16(DEF_LRSSI_SCAN_PERIOD);
+ cmd->info.params.lrssi_scan_threshold = a_cpu_to_sle16(lrssi +
+ DEF_SCAN_FOR_ROAM_INTVL);
+ cmd->info.params.lrssi_roam_threshold = a_cpu_to_sle16(lrssi);
+ cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR;
+ cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS;
+
+ ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_ROAM_CTRL_CMDID, NO_SYNC_WMIFLAG);
+
+ return 0;
+}
+
+static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_connect_event *ev;
+ u8 *pie, *peie;
+ struct ath6kl *ar = wmi->parent_dev;
+
+ if (len < sizeof(struct wmi_connect_event))
+ return -EINVAL;
+
+ ev = (struct wmi_connect_event *) datap;
+
+ if (ar->nw_type == AP_NETWORK) {
+ /* AP mode start/STA connected event */
+ struct net_device *dev = ar->net_dev;
+ if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) {
+ ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM "
+ "(AP started)\n",
+ __func__, le16_to_cpu(ev->u.ap_bss.ch),
+ ev->u.ap_bss.bssid);
+ ath6kl_connect_ap_mode_bss(
+ ar, le16_to_cpu(ev->u.ap_bss.ch));
+ } else {
+ ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM "
+ "auth=%u keymgmt=%u cipher=%u apsd_info=%u "
+ "(STA connected)\n",
+ __func__, ev->u.ap_sta.aid,
+ ev->u.ap_sta.mac_addr,
+ ev->u.ap_sta.auth,
+ ev->u.ap_sta.keymgmt,
+ le16_to_cpu(ev->u.ap_sta.cipher),
+ ev->u.ap_sta.apsd_info);
+ ath6kl_connect_ap_mode_sta(
+ ar, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr,
+ ev->u.ap_sta.keymgmt,
+ le16_to_cpu(ev->u.ap_sta.cipher),
+ ev->u.ap_sta.auth, ev->assoc_req_len,
+ ev->assoc_info + ev->beacon_ie_len);
+ }
+ return 0;
+ }
+
+ /* STA/IBSS mode connection event */
+
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "wmi event connect freq %d bssid %pM listen_intvl %d beacon_intvl %d type %d\n",
+ le16_to_cpu(ev->u.sta.ch), ev->u.sta.bssid,
+ le16_to_cpu(ev->u.sta.listen_intvl),
+ le16_to_cpu(ev->u.sta.beacon_intvl),
+ le32_to_cpu(ev->u.sta.nw_type));
+
+ /* Start of assoc rsp IEs */
+ pie = ev->assoc_info + ev->beacon_ie_len +
+ ev->assoc_req_len + (sizeof(u16) * 3); /* capinfo, status, aid */
+
+ /* End of assoc rsp IEs */
+ peie = ev->assoc_info + ev->beacon_ie_len + ev->assoc_req_len +
+ ev->assoc_resp_len;
+
+ while (pie < peie) {
+ switch (*pie) {
+ case WLAN_EID_VENDOR_SPECIFIC:
+ if (pie[1] > 3 && pie[2] == 0x00 && pie[3] == 0x50 &&
+ pie[4] == 0xf2 && pie[5] == WMM_OUI_TYPE) {
+ /* WMM OUT (00:50:F2) */
+ if (pie[1] > 5
+ && pie[6] == WMM_PARAM_OUI_SUBTYPE)
+ wmi->is_wmm_enabled = true;
+ }
+ break;
+ }
+
+ if (wmi->is_wmm_enabled)
+ break;
+
+ pie += pie[1] + 2;
+ }
+
+ ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->u.sta.ch),
+ ev->u.sta.bssid,
+ le16_to_cpu(ev->u.sta.listen_intvl),
+ le16_to_cpu(ev->u.sta.beacon_intvl),
+ le32_to_cpu(ev->u.sta.nw_type),
+ ev->beacon_ie_len, ev->assoc_req_len,
+ ev->assoc_resp_len, ev->assoc_info);
+
+ return 0;
+}
+
+static struct country_code_to_enum_rd *
+ath6kl_regd_find_country(u16 countryCode)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+ if (allCountries[i].countryCode == countryCode)
+ return &allCountries[i];
+ }
+
+ return NULL;
+}
+
+static struct reg_dmn_pair_mapping *
+ath6kl_get_regpair(u16 regdmn)
+{
+ int i;
+
+ if (regdmn == NO_ENUMRD)
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
+ if (regDomainPairs[i].regDmnEnum == regdmn)
+ return &regDomainPairs[i];
+ }
+
+ return NULL;
+}
+
+static struct country_code_to_enum_rd *
+ath6kl_regd_find_country_by_rd(u16 regdmn)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+ if (allCountries[i].regDmnEnum == regdmn)
+ return &allCountries[i];
+ }
+
+ return NULL;
+}
+
+static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
+{
+
+ struct ath6kl_wmi_regdomain *ev;
+ struct country_code_to_enum_rd *country = NULL;
+ struct reg_dmn_pair_mapping *regpair = NULL;
+ char alpha2[2];
+ u32 reg_code;
+
+ ev = (struct ath6kl_wmi_regdomain *) datap;
+ reg_code = le32_to_cpu(ev->reg_code);
+
+ if ((reg_code >> ATH6KL_COUNTRY_RD_SHIFT) & COUNTRY_ERD_FLAG)
+ country = ath6kl_regd_find_country((u16) reg_code);
+ else if (!(((u16) reg_code & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)) {
+
+ 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 (country) {
+ alpha2[0] = country->isoName[0];
+ alpha2[1] = country->isoName[1];
+
+ regulatory_hint(wmi->parent_dev->wdev->wiphy, alpha2);
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "Country alpha2 being used: %c%c\n",
+ alpha2[0], alpha2[1]);
+ }
+}
+
+static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_disconnect_event *ev;
+ wmi->traffic_class = 100;
+
+ if (len < sizeof(struct wmi_disconnect_event))
+ return -EINVAL;
+
+ ev = (struct wmi_disconnect_event *) datap;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "wmi event disconnect proto_reason %d bssid %pM wmi_reason %d assoc_resp_len %d\n",
+ le16_to_cpu(ev->proto_reason_status), ev->bssid,
+ ev->disconn_reason, ev->assoc_resp_len);
+
+ wmi->is_wmm_enabled = false;
+ wmi->pair_crypto_type = NONE_CRYPT;
+ wmi->grp_crypto_type = NONE_CRYPT;
+
+ ath6kl_disconnect_event(wmi->parent_dev, ev->disconn_reason,
+ ev->bssid, ev->assoc_resp_len, ev->assoc_info,
+ le16_to_cpu(ev->proto_reason_status));
+
+ return 0;
+}
+
+static int ath6kl_wmi_peer_node_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_peer_node_event *ev;
+
+ if (len < sizeof(struct wmi_peer_node_event))
+ return -EINVAL;
+
+ ev = (struct wmi_peer_node_event *) datap;
+
+ if (ev->event_code == PEER_NODE_JOIN_EVENT)
+ ath6kl_dbg(ATH6KL_DBG_WMI, "joined node with mac addr: %pM\n",
+ ev->peer_mac_addr);
+ else if (ev->event_code == PEER_NODE_LEAVE_EVENT)
+ ath6kl_dbg(ATH6KL_DBG_WMI, "left node with mac addr: %pM\n",
+ ev->peer_mac_addr);
+
+ return 0;
+}
+
+static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_tkip_micerr_event *ev;
+
+ if (len < sizeof(struct wmi_tkip_micerr_event))
+ return -EINVAL;
+
+ ev = (struct wmi_tkip_micerr_event *) datap;
+
+ ath6kl_tkip_micerr_event(wmi->parent_dev, ev->key_id, ev->is_mcast);
+
+ return 0;
+}
+
+static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_bss_info_hdr2 *bih;
+ u8 *buf;
+ struct ieee80211_channel *channel;
+ struct ath6kl *ar = wmi->parent_dev;
+ struct ieee80211_mgmt *mgmt;
+ struct cfg80211_bss *bss;
+
+ if (len <= sizeof(struct wmi_bss_info_hdr2))
+ return -EINVAL;
+
+ bih = (struct wmi_bss_info_hdr2 *) datap;
+ buf = datap + sizeof(struct wmi_bss_info_hdr2);
+ len -= sizeof(struct wmi_bss_info_hdr2);
+
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "bss info evt - ch %u, snr %d, rssi %d, bssid \"%pM\" "
+ "frame_type=%d\n",
+ bih->ch, bih->snr, bih->snr - 95, bih->bssid,
+ bih->frame_type);
+
+ if (bih->frame_type != BEACON_FTYPE &&
+ bih->frame_type != PROBERESP_FTYPE)
+ return 0; /* Only update BSS table for now */
+
+ if (bih->frame_type == BEACON_FTYPE &&
+ test_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag)) {
+ clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
+ ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
+ }
+
+ channel = ieee80211_get_channel(ar->wdev->wiphy, le16_to_cpu(bih->ch));
+ if (channel == NULL)
+ return -EINVAL;
+
+ if (len < 8 + 2 + 2)
+ return -EINVAL;
+
+ if (bih->frame_type == BEACON_FTYPE && test_bit(CONNECTED, &ar->flag) &&
+ memcmp(bih->bssid, ar->bssid, ETH_ALEN) == 0) {
+ const u8 *tim;
+ tim = cfg80211_find_ie(WLAN_EID_TIM, buf + 8 + 2 + 2,
+ len - 8 - 2 - 2);
+ if (tim && tim[1] >= 2) {
+ ar->assoc_bss_dtim_period = tim[3];
+ set_bit(DTIM_PERIOD_AVAIL, &ar->flag);
+ }
+ }
+
+ /*
+ * In theory, use of cfg80211_inform_bss() would be more natural here
+ * since we do not have the full frame. However, at least for now,
+ * cfg80211 can only distinguish Beacon and Probe Response frames from
+ * each other when using cfg80211_inform_bss_frame(), so let's build a
+ * fake IEEE 802.11 header to be able to take benefit of this.
+ */
+ mgmt = kmalloc(24 + len, GFP_ATOMIC);
+ if (mgmt == NULL)
+ return -EINVAL;
+
+ if (bih->frame_type == BEACON_FTYPE) {
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_BEACON);
+ memset(mgmt->da, 0xff, ETH_ALEN);
+ } else {
+ struct net_device *dev = ar->net_dev;
+
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_PROBE_RESP);
+ memcpy(mgmt->da, dev->dev_addr, ETH_ALEN);
+ }
+ mgmt->duration = cpu_to_le16(0);
+ memcpy(mgmt->sa, bih->bssid, ETH_ALEN);
+ memcpy(mgmt->bssid, bih->bssid, ETH_ALEN);
+ mgmt->seq_ctrl = cpu_to_le16(0);
+
+ memcpy(&mgmt->u.beacon, buf, len);
+
+ bss = cfg80211_inform_bss_frame(ar->wdev->wiphy, channel, mgmt,
+ 24 + len, (bih->snr - 95) * 100,
+ GFP_ATOMIC);
+ kfree(mgmt);
+ if (bss == NULL)
+ return -ENOMEM;
+ cfg80211_put_bss(bss);
+
+ return 0;
+}
+
+/* Inactivity timeout of a fatpipe(pstream) at the target */
+static int ath6kl_wmi_pstream_timeout_event_rx(struct wmi *wmi, u8 *datap,
+ int len)
+{
+ struct wmi_pstream_timeout_event *ev;
+
+ if (len < sizeof(struct wmi_pstream_timeout_event))
+ return -EINVAL;
+
+ ev = (struct wmi_pstream_timeout_event *) datap;
+
+ /*
+ * When the pstream (fat pipe == AC) timesout, it means there were
+ * no thinStreams within this pstream & it got implicitly created
+ * due to data flow on this AC. We start the inactivity timer only
+ * for implicitly created pstream. Just reset the host state.
+ */
+ spin_lock_bh(&wmi->lock);
+ wmi->stream_exist_for_ac[ev->traffic_class] = 0;
+ wmi->fat_pipe_exist &= ~(1 << ev->traffic_class);
+ spin_unlock_bh(&wmi->lock);
+
+ /* Indicate inactivity to driver layer for this fatpipe (pstream) */
+ ath6kl_indicate_tx_activity(wmi->parent_dev, ev->traffic_class, false);
+
+ return 0;
+}
+
+static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_bit_rate_reply *reply;
+ s32 rate;
+ u32 sgi, index;
+
+ if (len < sizeof(struct wmi_bit_rate_reply))
+ return -EINVAL;
+
+ reply = (struct wmi_bit_rate_reply *) datap;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "rateindex %d\n", reply->rate_index);
+
+ if (reply->rate_index == (s8) RATE_AUTO) {
+ rate = RATE_AUTO;
+ } else {
+ index = reply->rate_index & 0x7f;
+ sgi = (reply->rate_index & 0x80) ? 1 : 0;
+ rate = wmi_rate_tbl[index][sgi];
+ }
+
+ ath6kl_wakeup_event(wmi->parent_dev);
+
+ return 0;
+}
+
+static int ath6kl_wmi_tcmd_test_report_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ ath6kl_tm_rx_report_event(wmi->parent_dev, datap, len);
+
+ return 0;
+}
+
+static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ if (len < sizeof(struct wmi_fix_rates_reply))
+ return -EINVAL;
+
+ ath6kl_wakeup_event(wmi->parent_dev);
+
+ return 0;
+}
+
+static int ath6kl_wmi_ch_list_reply_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ if (len < sizeof(struct wmi_channel_list_reply))
+ return -EINVAL;
+
+ ath6kl_wakeup_event(wmi->parent_dev);
+
+ return 0;
+}
+
+static int ath6kl_wmi_tx_pwr_reply_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_tx_pwr_reply *reply;
+
+ if (len < sizeof(struct wmi_tx_pwr_reply))
+ return -EINVAL;
+
+ reply = (struct wmi_tx_pwr_reply *) datap;
+ ath6kl_txpwr_rx_evt(wmi->parent_dev, reply->dbM);
+
+ return 0;
+}
+
+static int ath6kl_wmi_keepalive_reply_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ if (len < sizeof(struct wmi_get_keepalive_cmd))
+ return -EINVAL;
+
+ ath6kl_wakeup_event(wmi->parent_dev);
+
+ return 0;
+}
+
+static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_scan_complete_event *ev;
+
+ ev = (struct wmi_scan_complete_event *) datap;
+
+ ath6kl_scan_complete_evt(wmi->parent_dev, a_sle32_to_cpu(ev->status));
+ wmi->is_probe_ssid = false;
+
+ return 0;
+}
+
+static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap,
+ int len)
+{
+ struct wmi_neighbor_report_event *ev;
+ u8 i;
+
+ if (len < sizeof(*ev))
+ return -EINVAL;
+ ev = (struct wmi_neighbor_report_event *) datap;
+ if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info)
+ > len) {
+ ath6kl_dbg(ATH6KL_DBG_WMI, "truncated neighbor event "
+ "(num=%d len=%d)\n", ev->num_neighbors, len);
+ return -EINVAL;
+ }
+ for (i = 0; i < ev->num_neighbors; i++) {
+ ath6kl_dbg(ATH6KL_DBG_WMI, "neighbor %d/%d - %pM 0x%x\n",
+ i + 1, ev->num_neighbors, ev->neighbor[i].bssid,
+ ev->neighbor[i].bss_flags);
+ cfg80211_pmksa_candidate_notify(wmi->parent_dev->net_dev, i,
+ ev->neighbor[i].bssid,
+ !!(ev->neighbor[i].bss_flags &
+ WMI_PREAUTH_CAPABLE_BSS),
+ GFP_ATOMIC);
+ }
+
+ return 0;
+}
+
+/*
+ * Target is reporting a programming error. This is for
+ * developer aid only. Target only checks a few common violations
+ * and it is responsibility of host to do all error checking.
+ * Behavior of target after wmi error event is undefined.
+ * A reset is recommended.
+ */
+static int ath6kl_wmi_error_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ const char *type = "unknown error";
+ struct wmi_cmd_error_event *ev;
+ ev = (struct wmi_cmd_error_event *) datap;
+
+ switch (ev->err_code) {
+ case INVALID_PARAM:
+ type = "invalid parameter";
+ break;
+ case ILLEGAL_STATE:
+ type = "invalid state";
+ break;
+ case INTERNAL_ERROR:
+ type = "internal error";
+ break;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "programming error, cmd=%d %s\n",
+ ev->cmd_id, type);
+
+ return 0;
+}
+
+static int ath6kl_wmi_stats_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ ath6kl_tgt_stats_event(wmi->parent_dev, datap, len);
+
+ return 0;
+}
+
+static u8 ath6kl_wmi_get_upper_threshold(s16 rssi,
+ struct sq_threshold_params *sq_thresh,
+ u32 size)
+{
+ u32 index;
+ u8 threshold = (u8) sq_thresh->upper_threshold[size - 1];
+
+ /* The list is already in sorted order. Get the next lower value */
+ for (index = 0; index < size; index++) {
+ if (rssi < sq_thresh->upper_threshold[index]) {
+ threshold = (u8) sq_thresh->upper_threshold[index];
+ break;
+ }
+ }
+
+ return threshold;
+}
+
+static u8 ath6kl_wmi_get_lower_threshold(s16 rssi,
+ struct sq_threshold_params *sq_thresh,
+ u32 size)
+{
+ u32 index;
+ u8 threshold = (u8) sq_thresh->lower_threshold[size - 1];
+
+ /* The list is already in sorted order. Get the next lower value */
+ for (index = 0; index < size; index++) {
+ if (rssi > sq_thresh->lower_threshold[index]) {
+ threshold = (u8) sq_thresh->lower_threshold[index];
+ break;
+ }
+ }
+
+ return threshold;
+}
+
+static int ath6kl_wmi_send_rssi_threshold_params(struct wmi *wmi,
+ struct wmi_rssi_threshold_params_cmd *rssi_cmd)
+{
+ struct sk_buff *skb;
+ struct wmi_rssi_threshold_params_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_rssi_threshold_params_cmd *) skb->data;
+ memcpy(cmd, rssi_cmd, sizeof(struct wmi_rssi_threshold_params_cmd));
+
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap,
+ int len)
+{
+ struct wmi_rssi_threshold_event *reply;
+ struct wmi_rssi_threshold_params_cmd cmd;
+ struct sq_threshold_params *sq_thresh;
+ enum wmi_rssi_threshold_val new_threshold;
+ u8 upper_rssi_threshold, lower_rssi_threshold;
+ s16 rssi;
+ int ret;
+
+ if (len < sizeof(struct wmi_rssi_threshold_event))
+ return -EINVAL;
+
+ reply = (struct wmi_rssi_threshold_event *) datap;
+ new_threshold = (enum wmi_rssi_threshold_val) reply->range;
+ rssi = a_sle16_to_cpu(reply->rssi);
+
+ sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_RSSI];
+
+ /*
+ * Identify the threshold breached and communicate that to the app.
+ * After that install a new set of thresholds based on the signal
+ * quality reported by the target
+ */
+ if (new_threshold) {
+ /* Upper threshold breached */
+ if (rssi < sq_thresh->upper_threshold[0]) {
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "spurious upper rssi threshold event: %d\n",
+ rssi);
+ } else if ((rssi < sq_thresh->upper_threshold[1]) &&
+ (rssi >= sq_thresh->upper_threshold[0])) {
+ new_threshold = WMI_RSSI_THRESHOLD1_ABOVE;
+ } else if ((rssi < sq_thresh->upper_threshold[2]) &&
+ (rssi >= sq_thresh->upper_threshold[1])) {
+ new_threshold = WMI_RSSI_THRESHOLD2_ABOVE;
+ } else if ((rssi < sq_thresh->upper_threshold[3]) &&
+ (rssi >= sq_thresh->upper_threshold[2])) {
+ new_threshold = WMI_RSSI_THRESHOLD3_ABOVE;
+ } else if ((rssi < sq_thresh->upper_threshold[4]) &&
+ (rssi >= sq_thresh->upper_threshold[3])) {
+ new_threshold = WMI_RSSI_THRESHOLD4_ABOVE;
+ } else if ((rssi < sq_thresh->upper_threshold[5]) &&
+ (rssi >= sq_thresh->upper_threshold[4])) {
+ new_threshold = WMI_RSSI_THRESHOLD5_ABOVE;
+ } else if (rssi >= sq_thresh->upper_threshold[5]) {
+ new_threshold = WMI_RSSI_THRESHOLD6_ABOVE;
+ }
+ } else {
+ /* Lower threshold breached */
+ if (rssi > sq_thresh->lower_threshold[0]) {
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "spurious lower rssi threshold event: %d %d\n",
+ rssi, sq_thresh->lower_threshold[0]);
+ } else if ((rssi > sq_thresh->lower_threshold[1]) &&
+ (rssi <= sq_thresh->lower_threshold[0])) {
+ new_threshold = WMI_RSSI_THRESHOLD6_BELOW;
+ } else if ((rssi > sq_thresh->lower_threshold[2]) &&
+ (rssi <= sq_thresh->lower_threshold[1])) {
+ new_threshold = WMI_RSSI_THRESHOLD5_BELOW;
+ } else if ((rssi > sq_thresh->lower_threshold[3]) &&
+ (rssi <= sq_thresh->lower_threshold[2])) {
+ new_threshold = WMI_RSSI_THRESHOLD4_BELOW;
+ } else if ((rssi > sq_thresh->lower_threshold[4]) &&
+ (rssi <= sq_thresh->lower_threshold[3])) {
+ new_threshold = WMI_RSSI_THRESHOLD3_BELOW;
+ } else if ((rssi > sq_thresh->lower_threshold[5]) &&
+ (rssi <= sq_thresh->lower_threshold[4])) {
+ new_threshold = WMI_RSSI_THRESHOLD2_BELOW;
+ } else if (rssi <= sq_thresh->lower_threshold[5]) {
+ new_threshold = WMI_RSSI_THRESHOLD1_BELOW;
+ }
+ }
+
+ /* Calculate and install the next set of thresholds */
+ lower_rssi_threshold = ath6kl_wmi_get_lower_threshold(rssi, sq_thresh,
+ sq_thresh->lower_threshold_valid_count);
+ upper_rssi_threshold = ath6kl_wmi_get_upper_threshold(rssi, sq_thresh,
+ sq_thresh->upper_threshold_valid_count);
+
+ /* Issue a wmi command to install the thresholds */
+ cmd.thresh_above1_val = a_cpu_to_sle16(upper_rssi_threshold);
+ cmd.thresh_below1_val = a_cpu_to_sle16(lower_rssi_threshold);
+ cmd.weight = sq_thresh->weight;
+ cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval);
+
+ ret = ath6kl_wmi_send_rssi_threshold_params(wmi, &cmd);
+ if (ret) {
+ ath6kl_err("unable to configure rssi thresholds\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_cac_event *reply;
+ struct ieee80211_tspec_ie *ts;
+ u16 active_tsids, tsinfo;
+ u8 tsid, index;
+ u8 ts_id;
+
+ if (len < sizeof(struct wmi_cac_event))
+ return -EINVAL;
+
+ reply = (struct wmi_cac_event *) datap;
+
+ if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&
+ (reply->status_code != IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED)) {
+
+ ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion);
+ tsinfo = le16_to_cpu(ts->tsinfo);
+ tsid = (tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
+ IEEE80211_WMM_IE_TSPEC_TID_MASK;
+
+ ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, tsid);
+ } else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
+ /*
+ * Following assumes that there is only one outstanding
+ * ADDTS request when this event is received
+ */
+ spin_lock_bh(&wmi->lock);
+ active_tsids = wmi->stream_exist_for_ac[reply->ac];
+ spin_unlock_bh(&wmi->lock);
+
+ for (index = 0; index < sizeof(active_tsids) * 8; index++) {
+ if ((active_tsids >> index) & 1)
+ break;
+ }
+ if (index < (sizeof(active_tsids) * 8))
+ ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, index);
+ }
+
+ /*
+ * Clear active tsids and Add missing handling
+ * for delete qos stream from AP
+ */
+ else if (reply->cac_indication == CAC_INDICATION_DELETE) {
+
+ ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion);
+ tsinfo = le16_to_cpu(ts->tsinfo);
+ ts_id = ((tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
+ IEEE80211_WMM_IE_TSPEC_TID_MASK);
+
+ spin_lock_bh(&wmi->lock);
+ wmi->stream_exist_for_ac[reply->ac] &= ~(1 << ts_id);
+ active_tsids = wmi->stream_exist_for_ac[reply->ac];
+ spin_unlock_bh(&wmi->lock);
+
+ /* Indicate stream inactivity to driver layer only if all tsids
+ * within this AC are deleted.
+ */
+ if (!active_tsids) {
+ ath6kl_indicate_tx_activity(wmi->parent_dev, reply->ac,
+ false);
+ wmi->fat_pipe_exist &= ~(1 << reply->ac);
+ }
+ }
+
+ return 0;
+}
+
+static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi,
+ struct wmi_snr_threshold_params_cmd *snr_cmd)
+{
+ struct sk_buff *skb;
+ struct wmi_snr_threshold_params_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_snr_threshold_params_cmd *) skb->data;
+ memcpy(cmd, snr_cmd, sizeof(struct wmi_snr_threshold_params_cmd));
+
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_SNR_THRESHOLD_PARAMS_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap,
+ int len)
+{
+ struct wmi_snr_threshold_event *reply;
+ struct sq_threshold_params *sq_thresh;
+ struct wmi_snr_threshold_params_cmd cmd;
+ enum wmi_snr_threshold_val new_threshold;
+ u8 upper_snr_threshold, lower_snr_threshold;
+ s16 snr;
+ int ret;
+
+ if (len < sizeof(struct wmi_snr_threshold_event))
+ return -EINVAL;
+
+ reply = (struct wmi_snr_threshold_event *) datap;
+
+ new_threshold = (enum wmi_snr_threshold_val) reply->range;
+ snr = reply->snr;
+
+ sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_SNR];
+
+ /*
+ * Identify the threshold breached and communicate that to the app.
+ * After that install a new set of thresholds based on the signal
+ * quality reported by the target.
+ */
+ if (new_threshold) {
+ /* Upper threshold breached */
+ if (snr < sq_thresh->upper_threshold[0]) {
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "spurious upper snr threshold event: %d\n",
+ snr);
+ } else if ((snr < sq_thresh->upper_threshold[1]) &&
+ (snr >= sq_thresh->upper_threshold[0])) {
+ new_threshold = WMI_SNR_THRESHOLD1_ABOVE;
+ } else if ((snr < sq_thresh->upper_threshold[2]) &&
+ (snr >= sq_thresh->upper_threshold[1])) {
+ new_threshold = WMI_SNR_THRESHOLD2_ABOVE;
+ } else if ((snr < sq_thresh->upper_threshold[3]) &&
+ (snr >= sq_thresh->upper_threshold[2])) {
+ new_threshold = WMI_SNR_THRESHOLD3_ABOVE;
+ } else if (snr >= sq_thresh->upper_threshold[3]) {
+ new_threshold = WMI_SNR_THRESHOLD4_ABOVE;
+ }
+ } else {
+ /* Lower threshold breached */
+ if (snr > sq_thresh->lower_threshold[0]) {
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "spurious lower snr threshold event: %d\n",
+ sq_thresh->lower_threshold[0]);
+ } else if ((snr > sq_thresh->lower_threshold[1]) &&
+ (snr <= sq_thresh->lower_threshold[0])) {
+ new_threshold = WMI_SNR_THRESHOLD4_BELOW;
+ } else if ((snr > sq_thresh->lower_threshold[2]) &&
+ (snr <= sq_thresh->lower_threshold[1])) {
+ new_threshold = WMI_SNR_THRESHOLD3_BELOW;
+ } else if ((snr > sq_thresh->lower_threshold[3]) &&
+ (snr <= sq_thresh->lower_threshold[2])) {
+ new_threshold = WMI_SNR_THRESHOLD2_BELOW;
+ } else if (snr <= sq_thresh->lower_threshold[3]) {
+ new_threshold = WMI_SNR_THRESHOLD1_BELOW;
+ }
+ }
+
+ /* Calculate and install the next set of thresholds */
+ lower_snr_threshold = ath6kl_wmi_get_lower_threshold(snr, sq_thresh,
+ sq_thresh->lower_threshold_valid_count);
+ upper_snr_threshold = ath6kl_wmi_get_upper_threshold(snr, sq_thresh,
+ sq_thresh->upper_threshold_valid_count);
+
+ /* Issue a wmi command to install the thresholds */
+ cmd.thresh_above1_val = upper_snr_threshold;
+ cmd.thresh_below1_val = lower_snr_threshold;
+ cmd.weight = sq_thresh->weight;
+ cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval);
+
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "snr: %d, threshold: %d, lower: %d, upper: %d\n",
+ snr, new_threshold,
+ lower_snr_threshold, upper_snr_threshold);
+
+ ret = ath6kl_wmi_send_snr_threshold_params(wmi, &cmd);
+ if (ret) {
+ ath6kl_err("unable to configure snr threshold\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ath6kl_wmi_aplist_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ u16 ap_info_entry_size;
+ struct wmi_aplist_event *ev = (struct wmi_aplist_event *) datap;
+ struct wmi_ap_info_v1 *ap_info_v1;
+ u8 index;
+
+ if (len < sizeof(struct wmi_aplist_event) ||
+ ev->ap_list_ver != APLIST_VER1)
+ return -EINVAL;
+
+ ap_info_entry_size = sizeof(struct wmi_ap_info_v1);
+ ap_info_v1 = (struct wmi_ap_info_v1 *) ev->ap_list;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "number of APs in aplist event: %d\n", ev->num_ap);
+
+ if (len < (int) (sizeof(struct wmi_aplist_event) +
+ (ev->num_ap - 1) * ap_info_entry_size))
+ return -EINVAL;
+
+ /* AP list version 1 contents */
+ for (index = 0; index < ev->num_ap; index++) {
+ ath6kl_dbg(ATH6KL_DBG_WMI, "AP#%d BSSID %pM Channel %d\n",
+ index, ap_info_v1->bssid, ap_info_v1->channel);
+ ap_info_v1++;
+ }
+
+ return 0;
+}
+
+int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
+ enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag)
+{
+ struct wmi_cmd_hdr *cmd_hdr;
+ enum htc_endpoint_id ep_id = wmi->ep_id;
+ int ret;
+
+ if (WARN_ON(skb == NULL))
+ return -EINVAL;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n",
+ cmd_id, skb->len, sync_flag);
+ ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi tx ",
+ skb->data, skb->len);
+
+ if (sync_flag >= END_WMIFLAG) {
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ if ((sync_flag == SYNC_BEFORE_WMIFLAG) ||
+ (sync_flag == SYNC_BOTH_WMIFLAG)) {
+ /*
+ * Make sure all data currently queued is transmitted before
+ * the cmd execution. Establish a new sync point.
+ */
+ ath6kl_wmi_sync_point(wmi);
+ }
+
+ skb_push(skb, sizeof(struct wmi_cmd_hdr));
+
+ cmd_hdr = (struct wmi_cmd_hdr *) skb->data;
+ cmd_hdr->cmd_id = cpu_to_le16(cmd_id);
+ cmd_hdr->info1 = 0; /* added for virtual interface */
+
+ /* Only for OPT_TX_CMD, use BE endpoint. */
+ if (cmd_id == WMI_OPT_TX_FRAME_CMDID) {
+ ret = ath6kl_wmi_data_hdr_add(wmi, skb, OPT_MSGTYPE,
+ false, false, 0, NULL);
+ if (ret) {
+ dev_kfree_skb(skb);
+ return ret;
+ }
+ ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev, WMM_AC_BE);
+ }
+
+ ath6kl_control_tx(wmi->parent_dev, skb, ep_id);
+
+ if ((sync_flag == SYNC_AFTER_WMIFLAG) ||
+ (sync_flag == SYNC_BOTH_WMIFLAG)) {
+ /*
+ * Make sure all new data queued waits for the command to
+ * execute. Establish a new sync point.
+ */
+ ath6kl_wmi_sync_point(wmi);
+ }
+
+ return 0;
+}
+
+int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
+ enum dot11_auth_mode dot11_auth_mode,
+ enum auth_mode auth_mode,
+ enum crypto_type pairwise_crypto,
+ u8 pairwise_crypto_len,
+ enum crypto_type group_crypto,
+ u8 group_crypto_len, int ssid_len, u8 *ssid,
+ u8 *bssid, u16 channel, u32 ctrl_flags)
+{
+ struct sk_buff *skb;
+ struct wmi_connect_cmd *cc;
+ int ret;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "wmi connect bssid %pM freq %d flags 0x%x ssid_len %d "
+ "type %d dot11_auth %d auth %d pairwise %d group %d\n",
+ bssid, channel, ctrl_flags, ssid_len, nw_type,
+ dot11_auth_mode, auth_mode, pairwise_crypto, group_crypto);
+ ath6kl_dbg_dump(ATH6KL_DBG_WMI, NULL, "ssid ", ssid, ssid_len);
+
+ wmi->traffic_class = 100;
+
+ if ((pairwise_crypto == NONE_CRYPT) && (group_crypto != NONE_CRYPT))
+ return -EINVAL;
+
+ if ((pairwise_crypto != NONE_CRYPT) && (group_crypto == NONE_CRYPT))
+ return -EINVAL;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_connect_cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cc = (struct wmi_connect_cmd *) skb->data;
+
+ if (ssid_len)
+ memcpy(cc->ssid, ssid, ssid_len);
+
+ cc->ssid_len = ssid_len;
+ cc->nw_type = nw_type;
+ cc->dot11_auth_mode = dot11_auth_mode;
+ cc->auth_mode = auth_mode;
+ cc->prwise_crypto_type = pairwise_crypto;
+ cc->prwise_crypto_len = pairwise_crypto_len;
+ cc->grp_crypto_type = group_crypto;
+ cc->grp_crypto_len = group_crypto_len;
+ cc->ch = cpu_to_le16(channel);
+ cc->ctrl_flags = cpu_to_le32(ctrl_flags);
+
+ if (bssid != NULL)
+ memcpy(cc->bssid, bssid, ETH_ALEN);
+
+ wmi->pair_crypto_type = pairwise_crypto;
+ wmi->grp_crypto_type = group_crypto;
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel)
+{
+ struct sk_buff *skb;
+ struct wmi_reconnect_cmd *cc;
+ int ret;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "wmi reconnect bssid %pM freq %d\n",
+ bssid, channel);
+
+ wmi->traffic_class = 100;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_reconnect_cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cc = (struct wmi_reconnect_cmd *) skb->data;
+ cc->channel = cpu_to_le16(channel);
+
+ if (bssid != NULL)
+ memcpy(cc->bssid, bssid, ETH_ALEN);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RECONNECT_CMDID,
+ NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+int ath6kl_wmi_disconnect_cmd(struct wmi *wmi)
+{
+ int ret;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "wmi disconnect\n");
+
+ wmi->traffic_class = 100;
+
+ /* Disconnect command does not need to do a SYNC before. */
+ ret = ath6kl_wmi_simple_cmd(wmi, WMI_DISCONNECT_CMDID);
+
+ return ret;
+}
+
+int ath6kl_wmi_startscan_cmd(struct wmi *wmi, 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, skb, WMI_START_SCAN_CMDID,
+ NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec,
+ u16 fg_end_sec, u16 bg_sec,
+ u16 minact_chdw_msec, u16 maxact_chdw_msec,
+ u16 pas_chdw_msec, u8 short_scan_ratio,
+ u8 scan_ctrl_flag, u32 max_dfsch_act_time,
+ u16 maxact_scan_per_ssid)
+{
+ struct sk_buff *skb;
+ struct wmi_scan_params_cmd *sc;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*sc));
+ if (!skb)
+ return -ENOMEM;
+
+ sc = (struct wmi_scan_params_cmd *) skb->data;
+ sc->fg_start_period = cpu_to_le16(fg_start_sec);
+ sc->fg_end_period = cpu_to_le16(fg_end_sec);
+ sc->bg_period = cpu_to_le16(bg_sec);
+ sc->minact_chdwell_time = cpu_to_le16(minact_chdw_msec);
+ sc->maxact_chdwell_time = cpu_to_le16(maxact_chdw_msec);
+ sc->pas_chdwell_time = cpu_to_le16(pas_chdw_msec);
+ sc->short_scan_ratio = short_scan_ratio;
+ sc->scan_ctrl_flags = scan_ctrl_flag;
+ sc->max_dfsch_act_time = cpu_to_le32(max_dfsch_act_time);
+ sc->maxact_scan_per_ssid = cpu_to_le16(maxact_scan_per_ssid);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_SCAN_PARAMS_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask)
+{
+ struct sk_buff *skb;
+ struct wmi_bss_filter_cmd *cmd;
+ int ret;
+
+ if (filter >= LAST_BSS_FILTER)
+ return -EINVAL;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_bss_filter_cmd *) skb->data;
+ cmd->bss_filter = filter;
+ cmd->ie_mask = cpu_to_le32(ie_mask);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_BSS_FILTER_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag,
+ u8 ssid_len, u8 *ssid)
+{
+ struct sk_buff *skb;
+ struct wmi_probed_ssid_cmd *cmd;
+ int ret;
+
+ if (index > MAX_PROBED_SSID_INDEX)
+ return -EINVAL;
+
+ if (ssid_len > sizeof(cmd->ssid))
+ return -EINVAL;
+
+ if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssid_len > 0))
+ return -EINVAL;
+
+ if ((flag & SPECIFIC_SSID_FLAG) && !ssid_len)
+ return -EINVAL;
+
+ if (flag & SPECIFIC_SSID_FLAG)
+ wmi->is_probe_ssid = true;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_probed_ssid_cmd *) skb->data;
+ cmd->entry_index = index;
+ cmd->flag = flag;
+ cmd->ssid_len = ssid_len;
+ memcpy(cmd->ssid, ssid, ssid_len);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PROBED_SSID_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval,
+ u16 listen_beacons)
+{
+ struct sk_buff *skb;
+ struct wmi_listen_int_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_listen_int_cmd *) skb->data;
+ cmd->listen_intvl = cpu_to_le16(listen_interval);
+ cmd->num_beacons = cpu_to_le16(listen_beacons);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LISTEN_INT_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode)
+{
+ struct sk_buff *skb;
+ struct wmi_power_mode_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_power_mode_cmd *) skb->data;
+ cmd->pwr_mode = pwr_mode;
+ wmi->pwr_mode = pwr_mode;
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_MODE_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period,
+ u16 ps_poll_num, u16 dtim_policy,
+ u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
+ u16 ps_fail_event_policy)
+{
+ struct sk_buff *skb;
+ struct wmi_power_params_cmd *pm;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*pm));
+ if (!skb)
+ return -ENOMEM;
+
+ pm = (struct wmi_power_params_cmd *)skb->data;
+ pm->idle_period = cpu_to_le16(idle_period);
+ pm->pspoll_number = cpu_to_le16(ps_poll_num);
+ pm->dtim_policy = cpu_to_le16(dtim_policy);
+ pm->tx_wakeup_policy = cpu_to_le16(tx_wakeup_policy);
+ pm->num_tx_to_wakeup = cpu_to_le16(num_tx_to_wakeup);
+ pm->ps_fail_event_policy = cpu_to_le16(ps_fail_event_policy);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_PARAMS_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout)
+{
+ struct sk_buff *skb;
+ struct wmi_disc_timeout_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_disc_timeout_cmd *) skb->data;
+ cmd->discon_timeout = timeout;
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_DISC_TIMEOUT_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
+ enum crypto_type key_type,
+ u8 key_usage, u8 key_len,
+ u8 *key_rsc, u8 *key_material,
+ u8 key_op_ctrl, u8 *mac_addr,
+ enum wmi_sync_flag sync_flag)
+{
+ struct sk_buff *skb;
+ struct wmi_add_cipher_key_cmd *cmd;
+ int ret;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d "
+ "key_usage=%d key_len=%d key_op_ctrl=%d\n",
+ key_index, key_type, key_usage, key_len, key_op_ctrl);
+
+ if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) ||
+ (key_material == NULL))
+ return -EINVAL;
+
+ if ((WEP_CRYPT != key_type) && (NULL == key_rsc))
+ return -EINVAL;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_add_cipher_key_cmd *) skb->data;
+ cmd->key_index = key_index;
+ cmd->key_type = key_type;
+ cmd->key_usage = key_usage;
+ cmd->key_len = key_len;
+ memcpy(cmd->key, key_material, key_len);
+
+ if (key_rsc != NULL)
+ memcpy(cmd->key_rsc, key_rsc, sizeof(cmd->key_rsc));
+
+ cmd->key_op_ctrl = key_op_ctrl;
+
+ if (mac_addr)
+ memcpy(cmd->key_mac_addr, mac_addr, ETH_ALEN);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_CIPHER_KEY_CMDID,
+ sync_flag);
+
+ return ret;
+}
+
+int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk)
+{
+ struct sk_buff *skb;
+ struct wmi_add_krk_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_add_krk_cmd *) skb->data;
+ memcpy(cmd->krk, krk, WMI_KRK_LEN);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index)
+{
+ struct sk_buff *skb;
+ struct wmi_delete_cipher_key_cmd *cmd;
+ int ret;
+
+ if (key_index > WMI_MAX_KEY_INDEX)
+ return -EINVAL;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_delete_cipher_key_cmd *) skb->data;
+ cmd->key_index = key_index;
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_CIPHER_KEY_CMDID,
+ NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid,
+ const u8 *pmkid, bool set)
+{
+ struct sk_buff *skb;
+ struct wmi_setpmkid_cmd *cmd;
+ int ret;
+
+ if (bssid == NULL)
+ return -EINVAL;
+
+ if (set && pmkid == NULL)
+ return -EINVAL;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_setpmkid_cmd *) skb->data;
+ memcpy(cmd->bssid, bssid, ETH_ALEN);
+ if (set) {
+ memcpy(cmd->pmkid, pmkid, sizeof(cmd->pmkid));
+ cmd->enable = PMKID_ENABLE;
+ } else {
+ memset(cmd->pmkid, 0, sizeof(cmd->pmkid));
+ cmd->enable = PMKID_DISABLE;
+ }
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PMKID_CMDID,
+ NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
+ enum htc_endpoint_id ep_id)
+{
+ struct wmi_data_hdr *data_hdr;
+ int ret;
+
+ if (WARN_ON(skb == NULL || ep_id == wmi->ep_id))
+ return -EINVAL;
+
+ skb_push(skb, sizeof(struct wmi_data_hdr));
+
+ data_hdr = (struct wmi_data_hdr *) skb->data;
+ data_hdr->info = SYNC_MSGTYPE << WMI_DATA_HDR_MSG_TYPE_SHIFT;
+ data_hdr->info3 = 0;
+
+ ret = ath6kl_control_tx(wmi->parent_dev, skb, ep_id);
+
+ return ret;
+}
+
+static int ath6kl_wmi_sync_point(struct wmi *wmi)
+{
+ struct sk_buff *skb;
+ struct wmi_sync_cmd *cmd;
+ struct wmi_data_sync_bufs data_sync_bufs[WMM_NUM_AC];
+ enum htc_endpoint_id ep_id;
+ u8 index, num_pri_streams = 0;
+ int ret = 0;
+
+ memset(data_sync_bufs, 0, sizeof(data_sync_bufs));
+
+ spin_lock_bh(&wmi->lock);
+
+ for (index = 0; index < WMM_NUM_AC; index++) {
+ if (wmi->fat_pipe_exist & (1 << index)) {
+ num_pri_streams++;
+ data_sync_bufs[num_pri_streams - 1].traffic_class =
+ index;
+ }
+ }
+
+ spin_unlock_bh(&wmi->lock);
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb) {
+ ret = -ENOMEM;
+ goto free_skb;
+ }
+
+ cmd = (struct wmi_sync_cmd *) skb->data;
+
+ /*
+ * In the SYNC cmd sent on the control Ep, send a bitmap
+ * of the data eps on which the Data Sync will be sent
+ */
+ cmd->data_sync_map = wmi->fat_pipe_exist;
+
+ for (index = 0; index < num_pri_streams; index++) {
+ data_sync_bufs[index].skb = ath6kl_buf_alloc(0);
+ if (data_sync_bufs[index].skb == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+ }
+
+ /*
+ * If buffer allocation for any of the dataSync fails,
+ * then do not send the Synchronize cmd on the control ep
+ */
+ if (ret)
+ goto free_skb;
+
+ /*
+ * Send sync cmd followed by sync data messages on all
+ * endpoints being used
+ */
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SYNCHRONIZE_CMDID,
+ NO_SYNC_WMIFLAG);
+
+ if (ret)
+ goto free_skb;
+
+ /* cmd buffer sent, we no longer own it */
+ skb = NULL;
+
+ for (index = 0; index < num_pri_streams; index++) {
+
+ if (WARN_ON(!data_sync_bufs[index].skb))
+ break;
+
+ ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev,
+ data_sync_bufs[index].
+ traffic_class);
+ ret =
+ ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb,
+ ep_id);
+
+ if (ret)
+ break;
+
+ data_sync_bufs[index].skb = NULL;
+ }
+
+free_skb:
+ /* free up any resources left over (possibly due to an error) */
+ if (skb)
+ dev_kfree_skb(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].
+ skb);
+ }
+ }
+
+ return ret;
+}
+
+int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi,
+ struct wmi_create_pstream_cmd *params)
+{
+ struct sk_buff *skb;
+ struct wmi_create_pstream_cmd *cmd;
+ u8 fatpipe_exist_for_ac = 0;
+ s32 min_phy = 0;
+ s32 nominal_phy = 0;
+ int ret;
+
+ if (!((params->user_pri < 8) &&
+ (params->user_pri <= 0x7) &&
+ (up_to_ac[params->user_pri & 0x7] == params->traffic_class) &&
+ (params->traffic_direc == UPLINK_TRAFFIC ||
+ params->traffic_direc == DNLINK_TRAFFIC ||
+ params->traffic_direc == BIDIR_TRAFFIC) &&
+ (params->traffic_type == TRAFFIC_TYPE_APERIODIC ||
+ params->traffic_type == TRAFFIC_TYPE_PERIODIC) &&
+ (params->voice_psc_cap == DISABLE_FOR_THIS_AC ||
+ params->voice_psc_cap == ENABLE_FOR_THIS_AC ||
+ params->voice_psc_cap == ENABLE_FOR_ALL_AC) &&
+ (params->tsid == WMI_IMPLICIT_PSTREAM ||
+ params->tsid <= WMI_MAX_THINSTREAM))) {
+ return -EINVAL;
+ }
+
+ /*
+ * Check nominal PHY rate is >= minimalPHY,
+ * so that DUT can allow TSRS IE
+ */
+
+ /* Get the physical rate (units of bps) */
+ min_phy = ((le32_to_cpu(params->min_phy_rate) / 1000) / 1000);
+
+ /* Check minimal phy < nominal phy rate */
+ if (params->nominal_phy >= min_phy) {
+ /* unit of 500 kbps */
+ nominal_phy = (params->nominal_phy * 1000) / 500;
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "TSRS IE enabled::MinPhy %x->NominalPhy ===> %x\n",
+ min_phy, nominal_phy);
+
+ params->nominal_phy = nominal_phy;
+ } else {
+ params->nominal_phy = 0;
+ }
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "sending create_pstream_cmd: ac=%d tsid:%d\n",
+ params->traffic_class, params->tsid);
+
+ cmd = (struct wmi_create_pstream_cmd *) skb->data;
+ memcpy(cmd, params, sizeof(*cmd));
+
+ /* This is an implicitly created Fat pipe */
+ if ((u32) params->tsid == (u32) WMI_IMPLICIT_PSTREAM) {
+ spin_lock_bh(&wmi->lock);
+ fatpipe_exist_for_ac = (wmi->fat_pipe_exist &
+ (1 << params->traffic_class));
+ wmi->fat_pipe_exist |= (1 << params->traffic_class);
+ spin_unlock_bh(&wmi->lock);
+ } else {
+ /* explicitly created thin stream within a fat pipe */
+ spin_lock_bh(&wmi->lock);
+ fatpipe_exist_for_ac = (wmi->fat_pipe_exist &
+ (1 << params->traffic_class));
+ wmi->stream_exist_for_ac[params->traffic_class] |=
+ (1 << params->tsid);
+ /*
+ * If a thinstream becomes active, the fat pipe automatically
+ * becomes active
+ */
+ wmi->fat_pipe_exist |= (1 << params->traffic_class);
+ spin_unlock_bh(&wmi->lock);
+ }
+
+ /*
+ * Indicate activty change to driver layer only if this is the
+ * first TSID to get created in this AC explicitly or an implicit
+ * fat pipe is getting created.
+ */
+ if (!fatpipe_exist_for_ac)
+ ath6kl_indicate_tx_activity(wmi->parent_dev,
+ params->traffic_class, true);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CREATE_PSTREAM_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid)
+{
+ struct sk_buff *skb;
+ struct wmi_delete_pstream_cmd *cmd;
+ u16 active_tsids = 0;
+ int ret;
+
+ if (traffic_class > 3) {
+ ath6kl_err("invalid traffic class: %d\n", traffic_class);
+ return -EINVAL;
+ }
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_delete_pstream_cmd *) skb->data;
+ cmd->traffic_class = traffic_class;
+ cmd->tsid = tsid;
+
+ spin_lock_bh(&wmi->lock);
+ active_tsids = wmi->stream_exist_for_ac[traffic_class];
+ spin_unlock_bh(&wmi->lock);
+
+ if (!(active_tsids & (1 << tsid))) {
+ dev_kfree_skb(skb);
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "TSID %d doesn't exist for traffic class: %d\n",
+ tsid, traffic_class);
+ return -ENODATA;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "sending delete_pstream_cmd: traffic class: %d tsid=%d\n",
+ traffic_class, tsid);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_PSTREAM_CMDID,
+ SYNC_BEFORE_WMIFLAG);
+
+ spin_lock_bh(&wmi->lock);
+ wmi->stream_exist_for_ac[traffic_class] &= ~(1 << tsid);
+ active_tsids = wmi->stream_exist_for_ac[traffic_class];
+ spin_unlock_bh(&wmi->lock);
+
+ /*
+ * Indicate stream inactivity to driver layer only if all tsids
+ * within this AC are deleted.
+ */
+ if (!active_tsids) {
+ ath6kl_indicate_tx_activity(wmi->parent_dev,
+ traffic_class, false);
+ wmi->fat_pipe_exist &= ~(1 << traffic_class);
+ }
+
+ return ret;
+}
+
+int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd)
+{
+ struct sk_buff *skb;
+ struct wmi_set_ip_cmd *cmd;
+ int ret;
+
+ /* Multicast address are not valid */
+ if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) ||
+ (*((u8 *) &ip_cmd->ips[1]) >= 0xE0))
+ return -EINVAL;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_ip_cmd *) skb->data;
+ memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd));
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_IP_CMDID, NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+static int ath6kl_wmi_get_wow_list_event_rx(struct wmi *wmi, u8 * datap,
+ int len)
+{
+ if (len < sizeof(struct wmi_get_wow_list_reply))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int ath6kl_wmi_cmd_send_xtnd(struct wmi *wmi, struct sk_buff *skb,
+ enum wmix_command_id cmd_id,
+ enum wmi_sync_flag sync_flag)
+{
+ struct wmix_cmd_hdr *cmd_hdr;
+ int ret;
+
+ skb_push(skb, sizeof(struct wmix_cmd_hdr));
+
+ cmd_hdr = (struct wmix_cmd_hdr *) skb->data;
+ cmd_hdr->cmd_id = cpu_to_le32(cmd_id);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_EXTENSION_CMDID, sync_flag);
+
+ return ret;
+}
+
+int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source)
+{
+ struct sk_buff *skb;
+ struct wmix_hb_challenge_resp_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmix_hb_challenge_resp_cmd *) skb->data;
+ cmd->cookie = cpu_to_le32(cookie);
+ cmd->source = cpu_to_le32(source);
+
+ ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_HB_CHALLENGE_RESP_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config)
+{
+ struct ath6kl_wmix_dbglog_cfg_module_cmd *cmd;
+ struct sk_buff *skb;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct ath6kl_wmix_dbglog_cfg_module_cmd *) skb->data;
+ cmd->valid = cpu_to_le32(valid);
+ cmd->config = cpu_to_le32(config);
+
+ ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_DBGLOG_CFG_MODULE_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_get_stats_cmd(struct wmi *wmi)
+{
+ return ath6kl_wmi_simple_cmd(wmi, WMI_GET_STATISTICS_CMDID);
+}
+
+int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM)
+{
+ struct sk_buff *skb;
+ struct wmi_set_tx_pwr_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_tx_pwr_cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_tx_pwr_cmd *) skb->data;
+ cmd->dbM = dbM;
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_TX_PWR_CMDID,
+ NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi)
+{
+ return ath6kl_wmi_simple_cmd(wmi, WMI_GET_TX_PWR_CMDID);
+}
+
+int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, u8 preamble_policy)
+{
+ struct sk_buff *skb;
+ struct wmi_set_lpreamble_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_lpreamble_cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_lpreamble_cmd *) skb->data;
+ cmd->status = status;
+ cmd->preamble_policy = preamble_policy;
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LPREAMBLE_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold)
+{
+ struct sk_buff *skb;
+ struct wmi_set_rts_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_rts_cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_rts_cmd *) skb->data;
+ cmd->threshold = cpu_to_le16(threshold);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_RTS_CMDID, NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg)
+{
+ struct sk_buff *skb;
+ struct wmi_set_wmm_txop_cmd *cmd;
+ int ret;
+
+ if (!((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)))
+ return -EINVAL;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_wmm_txop_cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_wmm_txop_cmd *) skb->data;
+ cmd->txop_enable = cfg;
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_WMM_TXOP_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl)
+{
+ struct sk_buff *skb;
+ struct wmi_set_keepalive_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_keepalive_cmd *) skb->data;
+ cmd->keep_alive_intvl = keep_alive_intvl;
+ wmi->keep_alive_intvl = keep_alive_intvl;
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_KEEPALIVE_CMDID,
+ NO_SYNC_WMIFLAG);
+ return ret;
+}
+
+int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len)
+{
+ struct sk_buff *skb;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(len);
+ if (!skb)
+ return -ENOMEM;
+
+ memcpy(skb->data, buf, len);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_TEST_CMDID, NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+
+s32 ath6kl_wmi_get_rate(s8 rate_index)
+{
+ if (rate_index == RATE_AUTO)
+ return 0;
+
+ return wmi_rate_tbl[(u32) rate_index][0];
+}
+
+static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
+ u32 len)
+{
+ struct wmi_pmkid_list_reply *reply;
+ u32 expected_len;
+
+ if (len < sizeof(struct wmi_pmkid_list_reply))
+ return -EINVAL;
+
+ reply = (struct wmi_pmkid_list_reply *)datap;
+ expected_len = sizeof(reply->num_pmkid) +
+ le32_to_cpu(reply->num_pmkid) * WMI_PMKID_LEN;
+
+ if (len < expected_len)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap;
+
+ aggr_recv_addba_req_evt(wmi->parent_dev, cmd->tid,
+ le16_to_cpu(cmd->st_seq_no), cmd->win_sz);
+
+ return 0;
+}
+
+static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_delba_event *cmd = (struct wmi_delba_event *) datap;
+
+ aggr_recv_delba_req_evt(wmi->parent_dev, cmd->tid);
+
+ return 0;
+}
+
+/* AP mode functions */
+
+int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p)
+{
+ struct sk_buff *skb;
+ struct wmi_connect_cmd *cm;
+ int res;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cm));
+ if (!skb)
+ return -ENOMEM;
+
+ cm = (struct wmi_connect_cmd *) skb->data;
+ memcpy(cm, p, sizeof(*cm));
+
+ res = ath6kl_wmi_cmd_send(wmip, skb, WMI_AP_CONFIG_COMMIT_CMDID,
+ NO_SYNC_WMIFLAG);
+ ath6kl_dbg(ATH6KL_DBG_WMI, "%s: nw_type=%u auth_mode=%u ch=%u "
+ "ctrl_flags=0x%x-> res=%d\n",
+ __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch),
+ le32_to_cpu(p->ctrl_flags), res);
+ return res;
+}
+
+int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason)
+{
+ struct sk_buff *skb;
+ struct wmi_ap_set_mlme_cmd *cm;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cm));
+ if (!skb)
+ return -ENOMEM;
+
+ cm = (struct wmi_ap_set_mlme_cmd *) skb->data;
+ memcpy(cm->mac, mac, ETH_ALEN);
+ cm->reason = cpu_to_le16(reason);
+ cm->cmd = cmd;
+
+ return ath6kl_wmi_cmd_send(wmip, skb, WMI_AP_SET_MLME_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ struct wmi_pspoll_event *ev;
+
+ if (len < sizeof(struct wmi_pspoll_event))
+ return -EINVAL;
+
+ ev = (struct wmi_pspoll_event *) datap;
+
+ ath6kl_pspoll_event(wmi->parent_dev, le16_to_cpu(ev->aid));
+
+ return 0;
+}
+
+static int ath6kl_wmi_dtimexpiry_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+ ath6kl_dtimexpiry_event(wmi->parent_dev);
+
+ return 0;
+}
+
+int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag)
+{
+ struct sk_buff *skb;
+ struct wmi_ap_set_pvb_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_ap_set_pvb_cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_ap_set_pvb_cmd *) skb->data;
+ cmd->aid = cpu_to_le16(aid);
+ cmd->rsvd = cpu_to_le16(0);
+ cmd->flag = cpu_to_le32(flag);
+
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_AP_SET_PVB_CMDID,
+ NO_SYNC_WMIFLAG);
+
+ return 0;
+}
+
+int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver,
+ bool rx_dot11_hdr, bool defrag_on_host)
+{
+ struct sk_buff *skb;
+ struct wmi_rx_frame_format_cmd *cmd;
+ int ret;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_rx_frame_format_cmd *) skb->data;
+ cmd->dot11_hdr = rx_dot11_hdr ? 1 : 0;
+ cmd->defrag_on_host = defrag_on_host ? 1 : 0;
+ cmd->meta_ver = rx_meta_ver;
+
+ /* Delete the local aggr state, on host */
+ ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RX_FRAME_FORMAT_CMDID,
+ NO_SYNC_WMIFLAG);
+
+ return ret;
+}
+
+int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie,
+ u8 ie_len)
+{
+ struct sk_buff *skb;
+ struct wmi_set_appie_cmd *p;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*p) + ie_len);
+ if (!skb)
+ return -ENOMEM;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "set_appie_cmd: mgmt_frm_type=%u "
+ "ie_len=%u\n", mgmt_frm_type, ie_len);
+ p = (struct wmi_set_appie_cmd *) skb->data;
+ p->mgmt_frm_type = mgmt_frm_type;
+ p->ie_len = ie_len;
+ memcpy(p->ie_info, ie, ie_len);
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_APPIE_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable)
+{
+ struct sk_buff *skb;
+ struct wmi_disable_11b_rates_cmd *cmd;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "disable_11b_rates_cmd: disable=%u\n",
+ disable);
+ cmd = (struct wmi_disable_11b_rates_cmd *) skb->data;
+ cmd->disable = disable ? 1 : 0;
+
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_DISABLE_11B_RATES_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur)
+{
+ struct sk_buff *skb;
+ struct wmi_remain_on_chnl_cmd *p;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*p));
+ if (!skb)
+ return -ENOMEM;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl_cmd: freq=%u dur=%u\n",
+ freq, dur);
+ p = (struct wmi_remain_on_chnl_cmd *) skb->data;
+ p->freq = cpu_to_le32(freq);
+ p->duration = cpu_to_le32(dur);
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_REMAIN_ON_CHNL_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait,
+ const u8 *data, u16 data_len)
+{
+ struct sk_buff *skb;
+ struct wmi_send_action_cmd *p;
+ u8 *buf;
+
+ if (wait)
+ return -EINVAL; /* Offload for wait not supported */
+
+ buf = kmalloc(data_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len);
+ if (!skb) {
+ kfree(buf);
+ return -ENOMEM;
+ }
+
+ kfree(wmi->last_mgmt_tx_frame);
+ wmi->last_mgmt_tx_frame = buf;
+ wmi->last_mgmt_tx_frame_len = data_len;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u "
+ "len=%u\n", id, freq, wait, data_len);
+ p = (struct wmi_send_action_cmd *) skb->data;
+ p->id = cpu_to_le32(id);
+ p->freq = cpu_to_le32(freq);
+ p->wait = cpu_to_le32(wait);
+ p->len = cpu_to_le16(data_len);
+ memcpy(p->data, data, data_len);
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_SEND_ACTION_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq,
+ const u8 *dst,
+ const u8 *data, u16 data_len)
+{
+ struct sk_buff *skb;
+ struct wmi_p2p_probe_response_cmd *p;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len);
+ if (!skb)
+ return -ENOMEM;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "send_probe_response_cmd: freq=%u dst=%pM "
+ "len=%u\n", freq, dst, data_len);
+ p = (struct wmi_p2p_probe_response_cmd *) skb->data;
+ p->freq = cpu_to_le32(freq);
+ memcpy(p->destination_addr, dst, ETH_ALEN);
+ p->len = cpu_to_le16(data_len);
+ memcpy(p->data, data, data_len);
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_SEND_PROBE_RESPONSE_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable)
+{
+ struct sk_buff *skb;
+ struct wmi_probe_req_report_cmd *p;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*p));
+ if (!skb)
+ return -ENOMEM;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "probe_report_req_cmd: enable=%u\n",
+ enable);
+ p = (struct wmi_probe_req_report_cmd *) skb->data;
+ p->enable = enable ? 1 : 0;
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_PROBE_REQ_REPORT_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags)
+{
+ struct sk_buff *skb;
+ struct wmi_get_p2p_info *p;
+
+ skb = ath6kl_wmi_get_new_buf(sizeof(*p));
+ if (!skb)
+ return -ENOMEM;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "info_req_cmd: flags=%x\n",
+ info_req_flags);
+ p = (struct wmi_get_p2p_info *) skb->data;
+ p->info_req_flags = cpu_to_le32(info_req_flags);
+ return ath6kl_wmi_cmd_send(wmi, skb, WMI_GET_P2P_INFO_CMDID,
+ NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi)
+{
+ ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl_cmd\n");
+ return ath6kl_wmi_simple_cmd(wmi, WMI_CANCEL_REMAIN_ON_CHNL_CMDID);
+}
+
+static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
+{
+ struct wmix_cmd_hdr *cmd;
+ u32 len;
+ u16 id;
+ u8 *datap;
+ int ret = 0;
+
+ if (skb->len < sizeof(struct wmix_cmd_hdr)) {
+ ath6kl_err("bad packet 1\n");
+ wmi->stat.cmd_len_err++;
+ return -EINVAL;
+ }
+
+ cmd = (struct wmix_cmd_hdr *) skb->data;
+ id = le32_to_cpu(cmd->cmd_id);
+
+ skb_pull(skb, sizeof(struct wmix_cmd_hdr));
+
+ datap = skb->data;
+ len = skb->len;
+
+ switch (id) {
+ case WMIX_HB_CHALLENGE_RESP_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n");
+ break;
+ case WMIX_DBGLOG_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len);
+ ath6kl_debug_fwlog_event(wmi->parent_dev, datap, len);
+ break;
+ default:
+ ath6kl_warn("unknown cmd id 0x%x\n", id);
+ wmi->stat.cmd_id_err++;
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/* Control Path */
+int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
+{
+ struct wmi_cmd_hdr *cmd;
+ u32 len;
+ u16 id;
+ u8 *datap;
+ int ret = 0;
+
+ if (WARN_ON(skb == NULL))
+ return -EINVAL;
+
+ if (skb->len < sizeof(struct wmi_cmd_hdr)) {
+ ath6kl_err("bad packet 1\n");
+ dev_kfree_skb(skb);
+ wmi->stat.cmd_len_err++;
+ return -EINVAL;
+ }
+
+ cmd = (struct wmi_cmd_hdr *) skb->data;
+ id = le16_to_cpu(cmd->cmd_id);
+
+ skb_pull(skb, sizeof(struct wmi_cmd_hdr));
+
+ datap = skb->data;
+ len = skb->len;
+
+ ath6kl_dbg(ATH6KL_DBG_WMI, "wmi rx id %d len %d\n", id, len);
+ ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi rx ",
+ datap, len);
+
+ switch (id) {
+ case WMI_GET_BITRATE_CMDID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n");
+ ret = ath6kl_wmi_bitrate_reply_rx(wmi, datap, len);
+ break;
+ case WMI_GET_CHANNEL_LIST_CMDID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_CHANNEL_LIST_CMDID\n");
+ ret = ath6kl_wmi_ch_list_reply_rx(wmi, datap, len);
+ break;
+ case WMI_GET_TX_PWR_CMDID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_TX_PWR_CMDID\n");
+ ret = ath6kl_wmi_tx_pwr_reply_rx(wmi, datap, len);
+ break;
+ case WMI_READY_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_READY_EVENTID\n");
+ ret = ath6kl_wmi_ready_event_rx(wmi, datap, len);
+ break;
+ case WMI_CONNECT_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n");
+ ret = ath6kl_wmi_connect_event_rx(wmi, datap, len);
+ break;
+ case WMI_DISCONNECT_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n");
+ ret = ath6kl_wmi_disconnect_event_rx(wmi, datap, len);
+ break;
+ case WMI_PEER_NODE_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n");
+ ret = ath6kl_wmi_peer_node_event_rx(wmi, datap, len);
+ break;
+ case WMI_TKIP_MICERR_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n");
+ ret = ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len);
+ break;
+ case WMI_BSSINFO_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n");
+ ret = ath6kl_wmi_bssinfo_event_rx(wmi, datap, len);
+ break;
+ case WMI_REGDOMAIN_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n");
+ ath6kl_wmi_regdomain_event(wmi, datap, len);
+ break;
+ case WMI_PSTREAM_TIMEOUT_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n");
+ ret = ath6kl_wmi_pstream_timeout_event_rx(wmi, datap, len);
+ break;
+ case WMI_NEIGHBOR_REPORT_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n");
+ ret = ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len);
+ break;
+ case WMI_SCAN_COMPLETE_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n");
+ ret = ath6kl_wmi_scan_complete_rx(wmi, datap, len);
+ break;
+ case WMI_CMDERROR_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n");
+ ret = ath6kl_wmi_error_event_rx(wmi, datap, len);
+ break;
+ case WMI_REPORT_STATISTICS_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n");
+ ret = ath6kl_wmi_stats_event_rx(wmi, datap, len);
+ break;
+ case WMI_RSSI_THRESHOLD_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n");
+ ret = ath6kl_wmi_rssi_threshold_event_rx(wmi, datap, len);
+ break;
+ case WMI_ERROR_REPORT_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ERROR_REPORT_EVENTID\n");
+ break;
+ case WMI_OPT_RX_FRAME_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_OPT_RX_FRAME_EVENTID\n");
+ /* this event has been deprecated */
+ break;
+ case WMI_REPORT_ROAM_TBL_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n");
+ break;
+ case WMI_EXTENSION_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n");
+ ret = ath6kl_wmi_control_rx_xtnd(wmi, skb);
+ break;
+ case WMI_CAC_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n");
+ ret = ath6kl_wmi_cac_event_rx(wmi, datap, len);
+ break;
+ case WMI_CHANNEL_CHANGE_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n");
+ break;
+ case WMI_REPORT_ROAM_DATA_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_DATA_EVENTID\n");
+ break;
+ case WMI_TEST_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n");
+ ret = ath6kl_wmi_tcmd_test_report_rx(wmi, datap, len);
+ break;
+ case WMI_GET_FIXRATES_CMDID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n");
+ ret = ath6kl_wmi_ratemask_reply_rx(wmi, datap, len);
+ break;
+ case WMI_TX_RETRY_ERR_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_RETRY_ERR_EVENTID\n");
+ break;
+ case WMI_SNR_THRESHOLD_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SNR_THRESHOLD_EVENTID\n");
+ ret = ath6kl_wmi_snr_threshold_event_rx(wmi, datap, len);
+ break;
+ case WMI_LQ_THRESHOLD_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_LQ_THRESHOLD_EVENTID\n");
+ break;
+ case WMI_APLIST_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_APLIST_EVENTID\n");
+ ret = ath6kl_wmi_aplist_event_rx(wmi, datap, len);
+ break;
+ case WMI_GET_KEEPALIVE_CMDID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_KEEPALIVE_CMDID\n");
+ ret = ath6kl_wmi_keepalive_reply_rx(wmi, datap, len);
+ break;
+ case WMI_GET_WOW_LIST_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_WOW_LIST_EVENTID\n");
+ ret = ath6kl_wmi_get_wow_list_event_rx(wmi, datap, len);
+ break;
+ case WMI_GET_PMKID_LIST_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n");
+ ret = ath6kl_wmi_get_pmkid_list_event_rx(wmi, datap, len);
+ break;
+ case WMI_PSPOLL_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n");
+ ret = ath6kl_wmi_pspoll_event_rx(wmi, datap, len);
+ break;
+ case WMI_DTIMEXPIRY_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n");
+ ret = ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len);
+ break;
+ case WMI_SET_PARAMS_REPLY_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n");
+ break;
+ case WMI_ADDBA_REQ_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n");
+ ret = ath6kl_wmi_addba_req_event_rx(wmi, datap, len);
+ break;
+ case WMI_ADDBA_RESP_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n");
+ break;
+ case WMI_DELBA_REQ_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n");
+ ret = ath6kl_wmi_delba_req_event_rx(wmi, datap, len);
+ break;
+ case WMI_REPORT_BTCOEX_CONFIG_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "WMI_REPORT_BTCOEX_CONFIG_EVENTID\n");
+ break;
+ case WMI_REPORT_BTCOEX_STATS_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "WMI_REPORT_BTCOEX_STATS_EVENTID\n");
+ break;
+ case WMI_TX_COMPLETE_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n");
+ ret = ath6kl_wmi_tx_complete_event_rx(datap, len);
+ break;
+ case WMI_REMAIN_ON_CHNL_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n");
+ ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len);
+ break;
+ case WMI_CANCEL_REMAIN_ON_CHNL_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n");
+ ret = ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap,
+ len);
+ break;
+ case WMI_TX_STATUS_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n");
+ ret = ath6kl_wmi_tx_status_event_rx(wmi, datap, len);
+ break;
+ case WMI_RX_PROBE_REQ_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n");
+ ret = ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len);
+ break;
+ case WMI_P2P_CAPABILITIES_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_CAPABILITIES_EVENTID\n");
+ ret = ath6kl_wmi_p2p_capabilities_event_rx(datap, len);
+ break;
+ case WMI_RX_ACTION_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
+ ret = ath6kl_wmi_rx_action_event_rx(wmi, datap, len);
+ break;
+ case WMI_P2P_INFO_EVENTID:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_INFO_EVENTID\n");
+ ret = ath6kl_wmi_p2p_info_event_rx(datap, len);
+ break;
+ default:
+ ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id);
+ wmi->stat.cmd_id_err++;
+ ret = -EINVAL;
+ break;
+ }
+
+ dev_kfree_skb(skb);
+
+ return ret;
+}
+
+static void ath6kl_wmi_qos_state_init(struct wmi *wmi)
+{
+ if (!wmi)
+ return;
+
+ spin_lock_bh(&wmi->lock);
+
+ wmi->fat_pipe_exist = 0;
+ memset(wmi->stream_exist_for_ac, 0, sizeof(wmi->stream_exist_for_ac));
+
+ spin_unlock_bh(&wmi->lock);
+}
+
+void *ath6kl_wmi_init(struct ath6kl *dev)
+{
+ struct wmi *wmi;
+
+ wmi = kzalloc(sizeof(struct wmi), GFP_KERNEL);
+ if (!wmi)
+ return NULL;
+
+ spin_lock_init(&wmi->lock);
+
+ wmi->parent_dev = dev;
+
+ ath6kl_wmi_qos_state_init(wmi);
+
+ wmi->pwr_mode = REC_POWER;
+ wmi->phy_mode = WMI_11G_MODE;
+
+ wmi->pair_crypto_type = NONE_CRYPT;
+ wmi->grp_crypto_type = NONE_CRYPT;
+
+ wmi->ht_allowed[A_BAND_24GHZ] = 1;
+ wmi->ht_allowed[A_BAND_5GHZ] = 1;
+
+ return wmi;
+}
+
+void ath6kl_wmi_shutdown(struct wmi *wmi)
+{
+ if (!wmi)
+ return;
+
+ kfree(wmi->last_mgmt_tx_frame);
+ kfree(wmi);
+}
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
new file mode 100644
index 000000000000..f8e644d54aa7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -0,0 +1,2282 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications 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.
+ */
+
+/*
+ * This file contains the definitions of the WMI protocol specified in the
+ * Wireless Module Interface (WMI). It includes definitions of all the
+ * commands and events. Commands are messages from the host to the WM.
+ * Events and Replies are messages from the WM to the host.
+ */
+
+#ifndef WMI_H
+#define WMI_H
+
+#include <linux/ieee80211.h>
+
+#include "htc.h"
+
+#define HTC_PROTOCOL_VERSION 0x0002
+#define WMI_PROTOCOL_VERSION 0x0002
+#define WMI_CONTROL_MSG_MAX_LEN 256
+#define is_ethertype(type_or_len) ((type_or_len) >= 0x0600)
+
+#define IP_ETHERTYPE 0x0800
+
+#define WMI_IMPLICIT_PSTREAM 0xFF
+#define WMI_MAX_THINSTREAM 15
+
+#define SSID_IE_LEN_INDEX 13
+
+/* Host side link management data structures */
+#define SIG_QUALITY_THRESH_LVLS 6
+#define SIG_QUALITY_UPPER_THRESH_LVLS SIG_QUALITY_THRESH_LVLS
+#define SIG_QUALITY_LOWER_THRESH_LVLS SIG_QUALITY_THRESH_LVLS
+
+#define A_BAND_24GHZ 0
+#define A_BAND_5GHZ 1
+#define A_NUM_BANDS 2
+
+/* in ms */
+#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000
+
+/*
+ * There are no signed versions of __le16 and __le32, so for a temporary
+ * solution come up with our own version. The idea is from fs/ntfs/types.h.
+ *
+ * Use a_ prefix so that it doesn't conflict if we get proper support to
+ * linux/types.h.
+ */
+typedef __s16 __bitwise a_sle16;
+typedef __s32 __bitwise a_sle32;
+
+static inline a_sle32 a_cpu_to_sle32(s32 val)
+{
+ return (__force a_sle32) cpu_to_le32(val);
+}
+
+static inline s32 a_sle32_to_cpu(a_sle32 val)
+{
+ return le32_to_cpu((__force __le32) val);
+}
+
+static inline a_sle16 a_cpu_to_sle16(s16 val)
+{
+ return (__force a_sle16) cpu_to_le16(val);
+}
+
+static inline s16 a_sle16_to_cpu(a_sle16 val)
+{
+ return le16_to_cpu((__force __le16) val);
+}
+
+struct sq_threshold_params {
+ s16 upper_threshold[SIG_QUALITY_UPPER_THRESH_LVLS];
+ s16 lower_threshold[SIG_QUALITY_LOWER_THRESH_LVLS];
+ u32 upper_threshold_valid_count;
+ u32 lower_threshold_valid_count;
+ u32 polling_interval;
+ u8 weight;
+ u8 last_rssi;
+ u8 last_rssi_poll_event;
+};
+
+struct wmi_stats {
+ u32 cmd_len_err;
+ u32 cmd_id_err;
+};
+
+struct wmi_data_sync_bufs {
+ u8 traffic_class;
+ struct sk_buff *skb;
+};
+
+/* WMM stream classes */
+#define WMM_NUM_AC 4
+#define WMM_AC_BE 0 /* best effort */
+#define WMM_AC_BK 1 /* background */
+#define WMM_AC_VI 2 /* video */
+#define WMM_AC_VO 3 /* voice */
+
+struct wmi {
+ bool ready;
+ u16 stream_exist_for_ac[WMM_NUM_AC];
+ u8 fat_pipe_exist;
+ struct ath6kl *parent_dev;
+ struct wmi_stats stat;
+ u8 pwr_mode;
+ u8 phy_mode;
+ u8 keep_alive_intvl;
+ spinlock_t lock;
+ enum htc_endpoint_id ep_id;
+ struct sq_threshold_params
+ sq_threshld[SIGNAL_QUALITY_METRICS_NUM_MAX];
+ enum crypto_type pair_crypto_type;
+ enum crypto_type grp_crypto_type;
+ bool is_wmm_enabled;
+ u8 ht_allowed[A_NUM_BANDS];
+ u8 traffic_class;
+ bool is_probe_ssid;
+
+ u8 *last_mgmt_tx_frame;
+ size_t last_mgmt_tx_frame_len;
+};
+
+struct host_app_area {
+ u32 wmi_protocol_ver;
+};
+
+enum wmi_msg_type {
+ DATA_MSGTYPE = 0x0,
+ CNTL_MSGTYPE,
+ SYNC_MSGTYPE,
+ OPT_MSGTYPE,
+};
+
+/*
+ * Macros for operating on WMI_DATA_HDR (info) field
+ */
+
+#define WMI_DATA_HDR_MSG_TYPE_MASK 0x03
+#define WMI_DATA_HDR_MSG_TYPE_SHIFT 0
+#define WMI_DATA_HDR_UP_MASK 0x07
+#define WMI_DATA_HDR_UP_SHIFT 2
+
+/* In AP mode, the same bit (b5) is used to indicate Power save state in
+ * the Rx dir and More data bit state in the tx direction.
+ */
+#define WMI_DATA_HDR_PS_MASK 0x1
+#define WMI_DATA_HDR_PS_SHIFT 5
+
+#define WMI_DATA_HDR_MORE_MASK 0x1
+#define WMI_DATA_HDR_MORE_SHIFT 5
+
+enum wmi_data_hdr_data_type {
+ WMI_DATA_HDR_DATA_TYPE_802_3 = 0,
+ WMI_DATA_HDR_DATA_TYPE_802_11,
+
+ /* used to be used for the PAL */
+ WMI_DATA_HDR_DATA_TYPE_ACL,
+};
+
+#define WMI_DATA_HDR_DATA_TYPE_MASK 0x3
+#define WMI_DATA_HDR_DATA_TYPE_SHIFT 6
+
+/* Macros for operating on WMI_DATA_HDR (info2) field */
+#define WMI_DATA_HDR_SEQNO_MASK 0xFFF
+#define WMI_DATA_HDR_SEQNO_SHIFT 0
+
+#define WMI_DATA_HDR_AMSDU_MASK 0x1
+#define WMI_DATA_HDR_AMSDU_SHIFT 12
+
+#define WMI_DATA_HDR_META_MASK 0x7
+#define WMI_DATA_HDR_META_SHIFT 13
+
+struct wmi_data_hdr {
+ s8 rssi;
+
+ /*
+ * usage of 'info' field(8-bit):
+ *
+ * b1:b0 - WMI_MSG_TYPE
+ * b4:b3:b2 - UP(tid)
+ * b5 - Used in AP mode.
+ * More-data in tx dir, PS in rx.
+ * b7:b6 - Dot3 header(0),
+ * Dot11 Header(1),
+ * ACL data(2)
+ */
+ u8 info;
+
+ /*
+ * usage of 'info2' field(16-bit):
+ *
+ * b11:b0 - seq_no
+ * b12 - A-MSDU?
+ * b15:b13 - META_DATA_VERSION 0 - 7
+ */
+ __le16 info2;
+ __le16 info3;
+} __packed;
+
+static inline u8 wmi_data_hdr_get_up(struct wmi_data_hdr *dhdr)
+{
+ return (dhdr->info >> WMI_DATA_HDR_UP_SHIFT) & WMI_DATA_HDR_UP_MASK;
+}
+
+static inline void wmi_data_hdr_set_up(struct wmi_data_hdr *dhdr,
+ u8 usr_pri)
+{
+ dhdr->info &= ~(WMI_DATA_HDR_UP_MASK << WMI_DATA_HDR_UP_SHIFT);
+ dhdr->info |= usr_pri << WMI_DATA_HDR_UP_SHIFT;
+}
+
+static inline u8 wmi_data_hdr_get_dot11(struct wmi_data_hdr *dhdr)
+{
+ u8 data_type;
+
+ data_type = (dhdr->info >> WMI_DATA_HDR_DATA_TYPE_SHIFT) &
+ WMI_DATA_HDR_DATA_TYPE_MASK;
+ return (data_type == WMI_DATA_HDR_DATA_TYPE_802_11);
+}
+
+static inline u16 wmi_data_hdr_get_seqno(struct wmi_data_hdr *dhdr)
+{
+ return (le16_to_cpu(dhdr->info2) >> WMI_DATA_HDR_SEQNO_SHIFT) &
+ WMI_DATA_HDR_SEQNO_MASK;
+}
+
+static inline u8 wmi_data_hdr_is_amsdu(struct wmi_data_hdr *dhdr)
+{
+ return (le16_to_cpu(dhdr->info2) >> WMI_DATA_HDR_AMSDU_SHIFT) &
+ WMI_DATA_HDR_AMSDU_MASK;
+}
+
+static inline u8 wmi_data_hdr_get_meta(struct wmi_data_hdr *dhdr)
+{
+ return (le16_to_cpu(dhdr->info2) >> WMI_DATA_HDR_META_SHIFT) &
+ WMI_DATA_HDR_META_MASK;
+}
+
+/* Tx meta version definitions */
+#define WMI_MAX_TX_META_SZ 12
+#define WMI_META_VERSION_1 0x01
+#define WMI_META_VERSION_2 0x02
+
+struct wmi_tx_meta_v1 {
+ /* packet ID to identify the tx request */
+ u8 pkt_id;
+
+ /* rate policy to be used for the tx of this frame */
+ u8 rate_plcy_id;
+} __packed;
+
+struct wmi_tx_meta_v2 {
+ /*
+ * Offset from start of the WMI header for csum calculation to
+ * begin.
+ */
+ u8 csum_start;
+
+ /* offset from start of WMI header where final csum goes */
+ u8 csum_dest;
+
+ /* no of bytes over which csum is calculated */
+ u8 csum_flags;
+} __packed;
+
+struct wmi_rx_meta_v1 {
+ u8 status;
+
+ /* rate index mapped to rate at which this packet was received. */
+ u8 rix;
+
+ /* rssi of packet */
+ u8 rssi;
+
+ /* rf channel during packet reception */
+ u8 channel;
+
+ __le16 flags;
+} __packed;
+
+struct wmi_rx_meta_v2 {
+ __le16 csum;
+
+ /* bit 0 set -partial csum valid bit 1 set -test mode */
+ u8 csum_flags;
+} __packed;
+
+/* Control Path */
+struct wmi_cmd_hdr {
+ __le16 cmd_id;
+
+ /* info1 - 16 bits
+ * b03:b00 - id
+ * b15:b04 - unused */
+ __le16 info1;
+
+ /* for alignment */
+ __le16 reserved;
+} __packed;
+
+/* List of WMI commands */
+enum wmi_cmd_id {
+ WMI_CONNECT_CMDID = 0x0001,
+ WMI_RECONNECT_CMDID,
+ WMI_DISCONNECT_CMDID,
+ WMI_SYNCHRONIZE_CMDID,
+ WMI_CREATE_PSTREAM_CMDID,
+ WMI_DELETE_PSTREAM_CMDID,
+ WMI_START_SCAN_CMDID,
+ WMI_SET_SCAN_PARAMS_CMDID,
+ WMI_SET_BSS_FILTER_CMDID,
+ WMI_SET_PROBED_SSID_CMDID, /* 10 */
+ WMI_SET_LISTEN_INT_CMDID,
+ WMI_SET_BMISS_TIME_CMDID,
+ WMI_SET_DISC_TIMEOUT_CMDID,
+ WMI_GET_CHANNEL_LIST_CMDID,
+ WMI_SET_BEACON_INT_CMDID,
+ WMI_GET_STATISTICS_CMDID,
+ WMI_SET_CHANNEL_PARAMS_CMDID,
+ WMI_SET_POWER_MODE_CMDID,
+ WMI_SET_IBSS_PM_CAPS_CMDID,
+ WMI_SET_POWER_PARAMS_CMDID, /* 20 */
+ WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
+ WMI_ADD_CIPHER_KEY_CMDID,
+ WMI_DELETE_CIPHER_KEY_CMDID,
+ WMI_ADD_KRK_CMDID,
+ WMI_DELETE_KRK_CMDID,
+ WMI_SET_PMKID_CMDID,
+ WMI_SET_TX_PWR_CMDID,
+ WMI_GET_TX_PWR_CMDID,
+ WMI_SET_ASSOC_INFO_CMDID,
+ WMI_ADD_BAD_AP_CMDID, /* 30 */
+ WMI_DELETE_BAD_AP_CMDID,
+ WMI_SET_TKIP_COUNTERMEASURES_CMDID,
+ WMI_RSSI_THRESHOLD_PARAMS_CMDID,
+ WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
+ WMI_SET_ACCESS_PARAMS_CMDID,
+ WMI_SET_RETRY_LIMITS_CMDID,
+ WMI_SET_OPT_MODE_CMDID,
+ WMI_OPT_TX_FRAME_CMDID,
+ WMI_SET_VOICE_PKT_SIZE_CMDID,
+ WMI_SET_MAX_SP_LEN_CMDID, /* 40 */
+ WMI_SET_ROAM_CTRL_CMDID,
+ WMI_GET_ROAM_TBL_CMDID,
+ WMI_GET_ROAM_DATA_CMDID,
+ WMI_ENABLE_RM_CMDID,
+ WMI_SET_MAX_OFFHOME_DURATION_CMDID,
+ WMI_EXTENSION_CMDID, /* Non-wireless extensions */
+ WMI_SNR_THRESHOLD_PARAMS_CMDID,
+ WMI_LQ_THRESHOLD_PARAMS_CMDID,
+ WMI_SET_LPREAMBLE_CMDID,
+ WMI_SET_RTS_CMDID, /* 50 */
+ WMI_CLR_RSSI_SNR_CMDID,
+ WMI_SET_FIXRATES_CMDID,
+ WMI_GET_FIXRATES_CMDID,
+ WMI_SET_AUTH_MODE_CMDID,
+ WMI_SET_REASSOC_MODE_CMDID,
+ WMI_SET_WMM_CMDID,
+ WMI_SET_WMM_TXOP_CMDID,
+ WMI_TEST_CMDID,
+
+ /* COEX AR6002 only */
+ WMI_SET_BT_STATUS_CMDID,
+ WMI_SET_BT_PARAMS_CMDID, /* 60 */
+
+ WMI_SET_KEEPALIVE_CMDID,
+ WMI_GET_KEEPALIVE_CMDID,
+ WMI_SET_APPIE_CMDID,
+ WMI_GET_APPIE_CMDID,
+ WMI_SET_WSC_STATUS_CMDID,
+
+ /* Wake on Wireless */
+ WMI_SET_HOST_SLEEP_MODE_CMDID,
+ WMI_SET_WOW_MODE_CMDID,
+ WMI_GET_WOW_LIST_CMDID,
+ WMI_ADD_WOW_PATTERN_CMDID,
+ WMI_DEL_WOW_PATTERN_CMDID, /* 70 */
+
+ WMI_SET_FRAMERATES_CMDID,
+ WMI_SET_AP_PS_CMDID,
+ WMI_SET_QOS_SUPP_CMDID,
+
+ /* WMI_THIN_RESERVED_... mark the start and end
+ * values for WMI_THIN_RESERVED command IDs. These
+ * command IDs can be found in wmi_thin.h */
+ WMI_THIN_RESERVED_START = 0x8000,
+ WMI_THIN_RESERVED_END = 0x8fff,
+
+ /* Developer commands starts at 0xF000 */
+ WMI_SET_BITRATE_CMDID = 0xF000,
+ WMI_GET_BITRATE_CMDID,
+ WMI_SET_WHALPARAM_CMDID,
+ WMI_SET_MAC_ADDRESS_CMDID,
+ WMI_SET_AKMP_PARAMS_CMDID,
+ WMI_SET_PMKID_LIST_CMDID,
+ WMI_GET_PMKID_LIST_CMDID,
+ WMI_ABORT_SCAN_CMDID,
+ WMI_SET_TARGET_EVENT_REPORT_CMDID,
+
+ /* Unused */
+ WMI_UNUSED1,
+ WMI_UNUSED2,
+
+ /* AP mode commands */
+ WMI_AP_HIDDEN_SSID_CMDID,
+ WMI_AP_SET_NUM_STA_CMDID,
+ WMI_AP_ACL_POLICY_CMDID,
+ WMI_AP_ACL_MAC_LIST_CMDID,
+ WMI_AP_CONFIG_COMMIT_CMDID,
+ WMI_AP_SET_MLME_CMDID,
+ WMI_AP_SET_PVB_CMDID,
+ WMI_AP_CONN_INACT_CMDID,
+ WMI_AP_PROT_SCAN_TIME_CMDID,
+ WMI_AP_SET_COUNTRY_CMDID,
+ WMI_AP_SET_DTIM_CMDID,
+ WMI_AP_MODE_STAT_CMDID,
+
+ WMI_SET_IP_CMDID,
+ WMI_SET_PARAMS_CMDID,
+ WMI_SET_MCAST_FILTER_CMDID,
+ WMI_DEL_MCAST_FILTER_CMDID,
+
+ WMI_ALLOW_AGGR_CMDID,
+ WMI_ADDBA_REQ_CMDID,
+ WMI_DELBA_REQ_CMDID,
+ WMI_SET_HT_CAP_CMDID,
+ WMI_SET_HT_OP_CMDID,
+ WMI_SET_TX_SELECT_RATES_CMDID,
+ WMI_SET_TX_SGI_PARAM_CMDID,
+ WMI_SET_RATE_POLICY_CMDID,
+
+ WMI_HCI_CMD_CMDID,
+ WMI_RX_FRAME_FORMAT_CMDID,
+ WMI_SET_THIN_MODE_CMDID,
+ WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID,
+
+ WMI_AP_SET_11BG_RATESET_CMDID,
+ WMI_SET_PMK_CMDID,
+ WMI_MCAST_FILTER_CMDID,
+
+ /* COEX CMDID AR6003 */
+ WMI_SET_BTCOEX_FE_ANT_CMDID,
+ WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
+ WMI_SET_BTCOEX_SCO_CONFIG_CMDID,
+ WMI_SET_BTCOEX_A2DP_CONFIG_CMDID,
+ WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID,
+ WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
+ WMI_SET_BTCOEX_DEBUG_CMDID,
+ WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID,
+ WMI_GET_BTCOEX_STATS_CMDID,
+ WMI_GET_BTCOEX_CONFIG_CMDID,
+
+ WMI_SET_DFS_ENABLE_CMDID, /* F034 */
+ WMI_SET_DFS_MINRSSITHRESH_CMDID,
+ WMI_SET_DFS_MAXPULSEDUR_CMDID,
+ WMI_DFS_RADAR_DETECTED_CMDID,
+
+ /* P2P commands */
+ WMI_P2P_SET_CONFIG_CMDID, /* F038 */
+ WMI_WPS_SET_CONFIG_CMDID,
+ WMI_SET_REQ_DEV_ATTR_CMDID,
+ WMI_P2P_FIND_CMDID,
+ WMI_P2P_STOP_FIND_CMDID,
+ WMI_P2P_GO_NEG_START_CMDID,
+ WMI_P2P_LISTEN_CMDID,
+
+ WMI_CONFIG_TX_MAC_RULES_CMDID, /* F040 */
+ WMI_SET_PROMISCUOUS_MODE_CMDID,
+ WMI_RX_FRAME_FILTER_CMDID,
+ WMI_SET_CHANNEL_CMDID,
+
+ /* WAC commands */
+ WMI_ENABLE_WAC_CMDID,
+ WMI_WAC_SCAN_REPLY_CMDID,
+ WMI_WAC_CTRL_REQ_CMDID,
+ WMI_SET_DIV_PARAMS_CMDID,
+
+ WMI_GET_PMK_CMDID,
+ WMI_SET_PASSPHRASE_CMDID,
+ WMI_SEND_ASSOC_RES_CMDID,
+ WMI_SET_ASSOC_REQ_RELAY_CMDID,
+
+ /* ACS command, consists of sub-commands */
+ WMI_ACS_CTRL_CMDID,
+ WMI_SET_EXCESS_TX_RETRY_THRES_CMDID,
+ WMI_SET_TBD_TIME_CMDID, /*added for wmiconfig command for TBD */
+
+ /* Pktlog cmds */
+ WMI_PKTLOG_ENABLE_CMDID,
+ WMI_PKTLOG_DISABLE_CMDID,
+
+ /* More P2P Cmds */
+ WMI_P2P_GO_NEG_REQ_RSP_CMDID,
+ WMI_P2P_GRP_INIT_CMDID,
+ WMI_P2P_GRP_FORMATION_DONE_CMDID,
+ WMI_P2P_INVITE_CMDID,
+ WMI_P2P_INVITE_REQ_RSP_CMDID,
+ WMI_P2P_PROV_DISC_REQ_CMDID,
+ WMI_P2P_SET_CMDID,
+
+ WMI_GET_RFKILL_MODE_CMDID,
+ WMI_SET_RFKILL_MODE_CMDID,
+ WMI_AP_SET_APSD_CMDID,
+ WMI_AP_APSD_BUFFERED_TRAFFIC_CMDID,
+
+ WMI_P2P_SDPD_TX_CMDID, /* F05C */
+ WMI_P2P_STOP_SDPD_CMDID,
+ WMI_P2P_CANCEL_CMDID,
+ /* Ultra low power store / recall commands */
+ WMI_STORERECALL_CONFIGURE_CMDID,
+ WMI_STORERECALL_RECALL_CMDID,
+ WMI_STORERECALL_HOST_READY_CMDID,
+ WMI_FORCE_TARGET_ASSERT_CMDID,
+
+ WMI_SET_PROBED_SSID_EX_CMDID,
+ WMI_SET_NETWORK_LIST_OFFLOAD_CMDID,
+ WMI_SET_ARP_NS_OFFLOAD_CMDID,
+ WMI_ADD_WOW_EXT_PATTERN_CMDID,
+ WMI_GTK_OFFLOAD_OP_CMDID,
+ WMI_REMAIN_ON_CHNL_CMDID,
+ WMI_CANCEL_REMAIN_ON_CHNL_CMDID,
+ WMI_SEND_ACTION_CMDID,
+ WMI_PROBE_REQ_REPORT_CMDID,
+ WMI_DISABLE_11B_RATES_CMDID,
+ WMI_SEND_PROBE_RESPONSE_CMDID,
+ WMI_GET_P2P_INFO_CMDID,
+ WMI_AP_JOIN_BSS_CMDID,
+};
+
+enum wmi_mgmt_frame_type {
+ WMI_FRAME_BEACON = 0,
+ WMI_FRAME_PROBE_REQ,
+ WMI_FRAME_PROBE_RESP,
+ WMI_FRAME_ASSOC_REQ,
+ WMI_FRAME_ASSOC_RESP,
+ WMI_NUM_MGMT_FRAME
+};
+
+/* WMI_CONNECT_CMDID */
+enum network_type {
+ INFRA_NETWORK = 0x01,
+ ADHOC_NETWORK = 0x02,
+ ADHOC_CREATOR = 0x04,
+ AP_NETWORK = 0x10,
+};
+
+enum dot11_auth_mode {
+ OPEN_AUTH = 0x01,
+ SHARED_AUTH = 0x02,
+
+ /* different from IEEE_AUTH_MODE definitions */
+ LEAP_AUTH = 0x04,
+};
+
+enum auth_mode {
+ NONE_AUTH = 0x01,
+ WPA_AUTH = 0x02,
+ WPA2_AUTH = 0x04,
+ WPA_PSK_AUTH = 0x08,
+ WPA2_PSK_AUTH = 0x10,
+ WPA_AUTH_CCKM = 0x20,
+ WPA2_AUTH_CCKM = 0x40,
+};
+
+#define WMI_MIN_CRYPTO_TYPE NONE_CRYPT
+#define WMI_MAX_CRYPTO_TYPE (AES_CRYPT + 1)
+
+#define WMI_MIN_KEY_INDEX 0
+#define WMI_MAX_KEY_INDEX 3
+
+#define WMI_MAX_KEY_LEN 32
+
+/*
+ * NB: these values are ordered carefully; there are lots of
+ * of implications in any reordering. In particular beware
+ * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY.
+ */
+#define ATH6KL_CIPHER_WEP 0
+#define ATH6KL_CIPHER_TKIP 1
+#define ATH6KL_CIPHER_AES_OCB 2
+#define ATH6KL_CIPHER_AES_CCM 3
+#define ATH6KL_CIPHER_CKIP 5
+#define ATH6KL_CIPHER_CCKM_KRK 6
+#define ATH6KL_CIPHER_NONE 7 /* pseudo value */
+
+/*
+ * 802.11 rate set.
+ */
+#define ATH6KL_RATE_MAXSIZE 15 /* max rates we'll handle */
+
+#define ATH_OUI_TYPE 0x01
+#define WPA_OUI_TYPE 0x01
+#define WMM_PARAM_OUI_SUBTYPE 0x01
+#define WMM_OUI_TYPE 0x02
+#define WSC_OUT_TYPE 0x04
+
+enum wmi_connect_ctrl_flags_bits {
+ CONNECT_ASSOC_POLICY_USER = 0x0001,
+ CONNECT_SEND_REASSOC = 0x0002,
+ CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004,
+ CONNECT_PROFILE_MATCH_DONE = 0x0008,
+ CONNECT_IGNORE_AAC_BEACON = 0x0010,
+ CONNECT_CSA_FOLLOW_BSS = 0x0020,
+ CONNECT_DO_WPA_OFFLOAD = 0x0040,
+ CONNECT_DO_NOT_DEAUTH = 0x0080,
+};
+
+struct wmi_connect_cmd {
+ u8 nw_type;
+ u8 dot11_auth_mode;
+ u8 auth_mode;
+ u8 prwise_crypto_type;
+ u8 prwise_crypto_len;
+ u8 grp_crypto_type;
+ u8 grp_crypto_len;
+ u8 ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ __le16 ch;
+ u8 bssid[ETH_ALEN];
+ __le32 ctrl_flags;
+} __packed;
+
+/* WMI_RECONNECT_CMDID */
+struct wmi_reconnect_cmd {
+ /* channel hint */
+ __le16 channel;
+
+ /* mandatory if set */
+ u8 bssid[ETH_ALEN];
+} __packed;
+
+/* WMI_ADD_CIPHER_KEY_CMDID */
+enum key_usage {
+ PAIRWISE_USAGE = 0x00,
+ GROUP_USAGE = 0x01,
+
+ /* default Tx Key - static WEP only */
+ TX_USAGE = 0x02,
+};
+
+/*
+ * Bit Flag
+ * Bit 0 - Initialise TSC - default is Initialize
+ */
+#define KEY_OP_INIT_TSC 0x01
+#define KEY_OP_INIT_RSC 0x02
+
+/* default initialise the TSC & RSC */
+#define KEY_OP_INIT_VAL 0x03
+#define KEY_OP_VALID_MASK 0x03
+
+struct wmi_add_cipher_key_cmd {
+ u8 key_index;
+ u8 key_type;
+
+ /* enum key_usage */
+ u8 key_usage;
+
+ u8 key_len;
+
+ /* key replay sequence counter */
+ u8 key_rsc[8];
+
+ u8 key[WLAN_MAX_KEY_LEN];
+
+ /* additional key control info */
+ u8 key_op_ctrl;
+
+ u8 key_mac_addr[ETH_ALEN];
+} __packed;
+
+/* WMI_DELETE_CIPHER_KEY_CMDID */
+struct wmi_delete_cipher_key_cmd {
+ u8 key_index;
+} __packed;
+
+#define WMI_KRK_LEN 16
+
+/* WMI_ADD_KRK_CMDID */
+struct wmi_add_krk_cmd {
+ u8 krk[WMI_KRK_LEN];
+} __packed;
+
+/* WMI_SETPMKID_CMDID */
+
+#define WMI_PMKID_LEN 16
+
+enum pmkid_enable_flg {
+ PMKID_DISABLE = 0,
+ PMKID_ENABLE = 1,
+};
+
+struct wmi_setpmkid_cmd {
+ u8 bssid[ETH_ALEN];
+
+ /* enum pmkid_enable_flg */
+ u8 enable;
+
+ u8 pmkid[WMI_PMKID_LEN];
+} __packed;
+
+/* WMI_START_SCAN_CMD */
+enum wmi_scan_type {
+ WMI_LONG_SCAN = 0,
+ WMI_SHORT_SCAN = 1,
+};
+
+struct wmi_start_scan_cmd {
+ __le32 force_fg_scan;
+
+ /* for legacy cisco AP compatibility */
+ __le32 is_legacy;
+
+ /* max duration in the home channel(msec) */
+ __le32 home_dwell_time;
+
+ /* time interval between scans (msec) */
+ __le32 force_scan_intvl;
+
+ /* enum wmi_scan_type */
+ u8 scan_type;
+
+ /* how many channels follow */
+ u8 num_ch;
+
+ /* channels in Mhz */
+ __le16 ch_list[1];
+} __packed;
+
+/* WMI_SET_SCAN_PARAMS_CMDID */
+#define WMI_SHORTSCANRATIO_DEFAULT 3
+
+/*
+ * Warning: scan control flag value of 0xFF is used to disable
+ * all flags in WMI_SCAN_PARAMS_CMD. Do not add any more
+ * flags here
+ */
+enum wmi_scan_ctrl_flags_bits {
+
+ /* set if can scan in the connect cmd */
+ CONNECT_SCAN_CTRL_FLAGS = 0x01,
+
+ /* set if scan for the SSID it is already connected to */
+ SCAN_CONNECTED_CTRL_FLAGS = 0x02,
+
+ /* set if enable active scan */
+ ACTIVE_SCAN_CTRL_FLAGS = 0x04,
+
+ /* set if enable roam scan when bmiss and lowrssi */
+ ROAM_SCAN_CTRL_FLAGS = 0x08,
+
+ /* set if follows customer BSSINFO reporting rule */
+ REPORT_BSSINFO_CTRL_FLAGS = 0x10,
+
+ /* if disabled, target doesn't scan after a disconnect event */
+ ENABLE_AUTO_CTRL_FLAGS = 0x20,
+
+ /*
+ * Scan complete event with canceled status will be generated when
+ * a scan is prempted before it gets completed.
+ */
+ ENABLE_SCAN_ABORT_EVENT = 0x40
+};
+
+#define DEFAULT_SCAN_CTRL_FLAGS \
+ (CONNECT_SCAN_CTRL_FLAGS | \
+ SCAN_CONNECTED_CTRL_FLAGS | \
+ ACTIVE_SCAN_CTRL_FLAGS | \
+ ROAM_SCAN_CTRL_FLAGS | \
+ ENABLE_AUTO_CTRL_FLAGS)
+
+struct wmi_scan_params_cmd {
+ /* sec */
+ __le16 fg_start_period;
+
+ /* sec */
+ __le16 fg_end_period;
+
+ /* sec */
+ __le16 bg_period;
+
+ /* msec */
+ __le16 maxact_chdwell_time;
+
+ /* msec */
+ __le16 pas_chdwell_time;
+
+ /* how many shorts scan for one long */
+ u8 short_scan_ratio;
+
+ u8 scan_ctrl_flags;
+
+ /* msec */
+ __le16 minact_chdwell_time;
+
+ /* max active scans per ssid */
+ __le16 maxact_scan_per_ssid;
+
+ /* msecs */
+ __le32 max_dfsch_act_time;
+} __packed;
+
+/* WMI_SET_BSS_FILTER_CMDID */
+enum wmi_bss_filter {
+ /* no beacons forwarded */
+ NONE_BSS_FILTER = 0x0,
+
+ /* all beacons forwarded */
+ ALL_BSS_FILTER,
+
+ /* only beacons matching profile */
+ PROFILE_FILTER,
+
+ /* all but beacons matching profile */
+ ALL_BUT_PROFILE_FILTER,
+
+ /* only beacons matching current BSS */
+ CURRENT_BSS_FILTER,
+
+ /* all but beacons matching BSS */
+ ALL_BUT_BSS_FILTER,
+
+ /* beacons matching probed ssid */
+ PROBED_SSID_FILTER,
+
+ /* marker only */
+ LAST_BSS_FILTER,
+};
+
+struct wmi_bss_filter_cmd {
+ /* see, enum wmi_bss_filter */
+ u8 bss_filter;
+
+ /* for alignment */
+ u8 reserved1;
+
+ /* for alignment */
+ __le16 reserved2;
+
+ __le32 ie_mask;
+} __packed;
+
+/* WMI_SET_PROBED_SSID_CMDID */
+#define MAX_PROBED_SSID_INDEX 9
+
+enum wmi_ssid_flag {
+ /* disables entry */
+ DISABLE_SSID_FLAG = 0,
+
+ /* probes specified ssid */
+ SPECIFIC_SSID_FLAG = 0x01,
+
+ /* probes for any ssid */
+ ANY_SSID_FLAG = 0x02,
+};
+
+struct wmi_probed_ssid_cmd {
+ /* 0 to MAX_PROBED_SSID_INDEX */
+ u8 entry_index;
+
+ /* see, enum wmi_ssid_flg */
+ u8 flag;
+
+ u8 ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+} __packed;
+
+/*
+ * WMI_SET_LISTEN_INT_CMDID
+ * The Listen interval is between 15 and 3000 TUs
+ */
+struct wmi_listen_int_cmd {
+ __le16 listen_intvl;
+ __le16 num_beacons;
+} __packed;
+
+/* WMI_SET_POWER_MODE_CMDID */
+enum wmi_power_mode {
+ REC_POWER = 0x01,
+ MAX_PERF_POWER,
+};
+
+struct wmi_power_mode_cmd {
+ /* see, enum wmi_power_mode */
+ u8 pwr_mode;
+} __packed;
+
+/*
+ * Policy to determnine whether power save failure event should be sent to
+ * host during scanning
+ */
+enum power_save_fail_event_policy {
+ SEND_POWER_SAVE_FAIL_EVENT_ALWAYS = 1,
+ IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN = 2,
+};
+
+struct wmi_power_params_cmd {
+ /* msec */
+ __le16 idle_period;
+
+ __le16 pspoll_number;
+ __le16 dtim_policy;
+ __le16 tx_wakeup_policy;
+ __le16 num_tx_to_wakeup;
+ __le16 ps_fail_event_policy;
+} __packed;
+
+/* WMI_SET_DISC_TIMEOUT_CMDID */
+struct wmi_disc_timeout_cmd {
+ /* seconds */
+ u8 discon_timeout;
+} __packed;
+
+enum dir_type {
+ UPLINK_TRAFFIC = 0,
+ DNLINK_TRAFFIC = 1,
+ BIDIR_TRAFFIC = 2,
+};
+
+enum voiceps_cap_type {
+ DISABLE_FOR_THIS_AC = 0,
+ ENABLE_FOR_THIS_AC = 1,
+ ENABLE_FOR_ALL_AC = 2,
+};
+
+enum traffic_type {
+ TRAFFIC_TYPE_APERIODIC = 0,
+ TRAFFIC_TYPE_PERIODIC = 1,
+};
+
+/* WMI_SYNCHRONIZE_CMDID */
+struct wmi_sync_cmd {
+ u8 data_sync_map;
+} __packed;
+
+/* WMI_CREATE_PSTREAM_CMDID */
+struct wmi_create_pstream_cmd {
+ /* msec */
+ __le32 min_service_int;
+
+ /* msec */
+ __le32 max_service_int;
+
+ /* msec */
+ __le32 inactivity_int;
+
+ /* msec */
+ __le32 suspension_int;
+
+ __le32 service_start_time;
+
+ /* in bps */
+ __le32 min_data_rate;
+
+ /* in bps */
+ __le32 mean_data_rate;
+
+ /* in bps */
+ __le32 peak_data_rate;
+
+ __le32 max_burst_size;
+ __le32 delay_bound;
+
+ /* in bps */
+ __le32 min_phy_rate;
+
+ __le32 sba;
+ __le32 medium_time;
+
+ /* in octects */
+ __le16 nominal_msdu;
+
+ /* in octects */
+ __le16 max_msdu;
+
+ u8 traffic_class;
+
+ /* see, enum dir_type */
+ u8 traffic_direc;
+
+ u8 rx_queue_num;
+
+ /* see, enum traffic_type */
+ u8 traffic_type;
+
+ /* see, enum voiceps_cap_type */
+ u8 voice_psc_cap;
+ u8 tsid;
+
+ /* 802.1D user priority */
+ u8 user_pri;
+
+ /* nominal phy rate */
+ u8 nominal_phy;
+} __packed;
+
+/* WMI_DELETE_PSTREAM_CMDID */
+struct wmi_delete_pstream_cmd {
+ u8 tx_queue_num;
+ u8 rx_queue_num;
+ u8 traffic_direc;
+ u8 traffic_class;
+ u8 tsid;
+} __packed;
+
+/* WMI_SET_CHANNEL_PARAMS_CMDID */
+enum wmi_phy_mode {
+ WMI_11A_MODE = 0x1,
+ WMI_11G_MODE = 0x2,
+ WMI_11AG_MODE = 0x3,
+ WMI_11B_MODE = 0x4,
+ WMI_11GONLY_MODE = 0x5,
+};
+
+#define WMI_MAX_CHANNELS 32
+
+/*
+ * WMI_RSSI_THRESHOLD_PARAMS_CMDID
+ * Setting the polltime to 0 would disable polling. Threshold values are
+ * in the ascending order, and should agree to:
+ * (lowThreshold_lowerVal < lowThreshold_upperVal < highThreshold_lowerVal
+ * < highThreshold_upperVal)
+ */
+
+struct wmi_rssi_threshold_params_cmd {
+ /* polling time as a factor of LI */
+ __le32 poll_time;
+
+ /* lowest of upper */
+ a_sle16 thresh_above1_val;
+
+ a_sle16 thresh_above2_val;
+ a_sle16 thresh_above3_val;
+ a_sle16 thresh_above4_val;
+ a_sle16 thresh_above5_val;
+
+ /* highest of upper */
+ a_sle16 thresh_above6_val;
+
+ /* lowest of bellow */
+ a_sle16 thresh_below1_val;
+
+ a_sle16 thresh_below2_val;
+ a_sle16 thresh_below3_val;
+ a_sle16 thresh_below4_val;
+ a_sle16 thresh_below5_val;
+
+ /* highest of bellow */
+ a_sle16 thresh_below6_val;
+
+ /* "alpha" */
+ u8 weight;
+
+ u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_SNR_THRESHOLD_PARAMS_CMDID
+ * Setting the polltime to 0 would disable polling.
+ */
+
+struct wmi_snr_threshold_params_cmd {
+ /* polling time as a factor of LI */
+ __le32 poll_time;
+
+ /* "alpha" */
+ u8 weight;
+
+ /* lowest of uppper */
+ u8 thresh_above1_val;
+
+ u8 thresh_above2_val;
+ u8 thresh_above3_val;
+
+ /* highest of upper */
+ u8 thresh_above4_val;
+
+ /* lowest of bellow */
+ u8 thresh_below1_val;
+
+ u8 thresh_below2_val;
+ u8 thresh_below3_val;
+
+ /* highest of bellow */
+ u8 thresh_below4_val;
+
+ u8 reserved[3];
+} __packed;
+
+enum wmi_preamble_policy {
+ WMI_IGNORE_BARKER_IN_ERP = 0,
+ WMI_DONOT_IGNORE_BARKER_IN_ERP
+};
+
+struct wmi_set_lpreamble_cmd {
+ u8 status;
+ u8 preamble_policy;
+} __packed;
+
+struct wmi_set_rts_cmd {
+ __le16 threshold;
+} __packed;
+
+/* WMI_SET_TX_PWR_CMDID */
+struct wmi_set_tx_pwr_cmd {
+ /* in dbM units */
+ u8 dbM;
+} __packed;
+
+struct wmi_tx_pwr_reply {
+ /* in dbM units */
+ u8 dbM;
+} __packed;
+
+struct wmi_report_sleep_state_event {
+ __le32 sleep_state;
+};
+
+enum wmi_report_sleep_status {
+ WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP = 0,
+ WMI_REPORT_SLEEP_STATUS_IS_AWAKE
+};
+enum target_event_report_config {
+ /* default */
+ DISCONN_EVT_IN_RECONN = 0,
+
+ NO_DISCONN_EVT_IN_RECONN
+};
+
+/* Command Replies */
+
+/* WMI_GET_CHANNEL_LIST_CMDID reply */
+struct wmi_channel_list_reply {
+ u8 reserved;
+
+ /* number of channels in reply */
+ u8 num_ch;
+
+ /* channel in Mhz */
+ __le16 ch_list[1];
+} __packed;
+
+/* List of Events (target to host) */
+enum wmi_event_id {
+ WMI_READY_EVENTID = 0x1001,
+ WMI_CONNECT_EVENTID,
+ WMI_DISCONNECT_EVENTID,
+ WMI_BSSINFO_EVENTID,
+ WMI_CMDERROR_EVENTID,
+ WMI_REGDOMAIN_EVENTID,
+ WMI_PSTREAM_TIMEOUT_EVENTID,
+ WMI_NEIGHBOR_REPORT_EVENTID,
+ WMI_TKIP_MICERR_EVENTID,
+ WMI_SCAN_COMPLETE_EVENTID, /* 0x100a */
+ WMI_REPORT_STATISTICS_EVENTID,
+ WMI_RSSI_THRESHOLD_EVENTID,
+ WMI_ERROR_REPORT_EVENTID,
+ WMI_OPT_RX_FRAME_EVENTID,
+ WMI_REPORT_ROAM_TBL_EVENTID,
+ WMI_EXTENSION_EVENTID,
+ WMI_CAC_EVENTID,
+ WMI_SNR_THRESHOLD_EVENTID,
+ WMI_LQ_THRESHOLD_EVENTID,
+ WMI_TX_RETRY_ERR_EVENTID, /* 0x1014 */
+ WMI_REPORT_ROAM_DATA_EVENTID,
+ WMI_TEST_EVENTID,
+ WMI_APLIST_EVENTID,
+ WMI_GET_WOW_LIST_EVENTID,
+ WMI_GET_PMKID_LIST_EVENTID,
+ WMI_CHANNEL_CHANGE_EVENTID,
+ WMI_PEER_NODE_EVENTID,
+ WMI_PSPOLL_EVENTID,
+ WMI_DTIMEXPIRY_EVENTID,
+ WMI_WLAN_VERSION_EVENTID,
+ WMI_SET_PARAMS_REPLY_EVENTID,
+ WMI_ADDBA_REQ_EVENTID, /*0x1020 */
+ WMI_ADDBA_RESP_EVENTID,
+ WMI_DELBA_REQ_EVENTID,
+ WMI_TX_COMPLETE_EVENTID,
+ WMI_HCI_EVENT_EVENTID,
+ WMI_ACL_DATA_EVENTID,
+ WMI_REPORT_SLEEP_STATE_EVENTID,
+ WMI_REPORT_BTCOEX_STATS_EVENTID,
+ WMI_REPORT_BTCOEX_CONFIG_EVENTID,
+ WMI_GET_PMK_EVENTID,
+
+ /* DFS Events */
+ WMI_DFS_HOST_ATTACH_EVENTID,
+ WMI_DFS_HOST_INIT_EVENTID,
+ WMI_DFS_RESET_DELAYLINES_EVENTID,
+ WMI_DFS_RESET_RADARQ_EVENTID,
+ WMI_DFS_RESET_AR_EVENTID,
+ WMI_DFS_RESET_ARQ_EVENTID,
+ WMI_DFS_SET_DUR_MULTIPLIER_EVENTID,
+ WMI_DFS_SET_BANGRADAR_EVENTID,
+ WMI_DFS_SET_DEBUGLEVEL_EVENTID,
+ WMI_DFS_PHYERR_EVENTID,
+
+ /* CCX Evants */
+ WMI_CCX_RM_STATUS_EVENTID,
+
+ /* P2P Events */
+ WMI_P2P_GO_NEG_RESULT_EVENTID,
+
+ WMI_WAC_SCAN_DONE_EVENTID,
+ WMI_WAC_REPORT_BSS_EVENTID,
+ WMI_WAC_START_WPS_EVENTID,
+ WMI_WAC_CTRL_REQ_REPLY_EVENTID,
+
+ WMI_REPORT_WMM_PARAMS_EVENTID,
+ WMI_WAC_REJECT_WPS_EVENTID,
+
+ /* More P2P Events */
+ WMI_P2P_GO_NEG_REQ_EVENTID,
+ WMI_P2P_INVITE_REQ_EVENTID,
+ WMI_P2P_INVITE_RCVD_RESULT_EVENTID,
+ WMI_P2P_INVITE_SENT_RESULT_EVENTID,
+ WMI_P2P_PROV_DISC_RESP_EVENTID,
+ WMI_P2P_PROV_DISC_REQ_EVENTID,
+
+ /* RFKILL Events */
+ WMI_RFKILL_STATE_CHANGE_EVENTID,
+ WMI_RFKILL_GET_MODE_CMD_EVENTID,
+
+ WMI_P2P_START_SDPD_EVENTID,
+ WMI_P2P_SDPD_RX_EVENTID,
+
+ WMI_THIN_RESERVED_START_EVENTID = 0x8000,
+ /* Events in this range are reserved for thinmode */
+ WMI_THIN_RESERVED_END_EVENTID = 0x8fff,
+
+ WMI_SET_CHANNEL_EVENTID,
+ WMI_ASSOC_REQ_EVENTID,
+
+ /* Generic ACS event */
+ WMI_ACS_EVENTID,
+ WMI_STORERECALL_STORE_EVENTID,
+ WMI_WOW_EXT_WAKE_EVENTID,
+ WMI_GTK_OFFLOAD_STATUS_EVENTID,
+ WMI_NETWORK_LIST_OFFLOAD_EVENTID,
+ WMI_REMAIN_ON_CHNL_EVENTID,
+ WMI_CANCEL_REMAIN_ON_CHNL_EVENTID,
+ WMI_TX_STATUS_EVENTID,
+ WMI_RX_PROBE_REQ_EVENTID,
+ WMI_P2P_CAPABILITIES_EVENTID,
+ WMI_RX_ACTION_EVENTID,
+ WMI_P2P_INFO_EVENTID,
+};
+
+struct wmi_ready_event_2 {
+ __le32 sw_version;
+ __le32 abi_version;
+ u8 mac_addr[ETH_ALEN];
+ u8 phy_cap;
+} __packed;
+
+/* Connect Event */
+struct wmi_connect_event {
+ union {
+ struct {
+ __le16 ch;
+ u8 bssid[ETH_ALEN];
+ __le16 listen_intvl;
+ __le16 beacon_intvl;
+ __le32 nw_type;
+ } sta;
+ struct {
+ u8 phymode;
+ u8 aid;
+ u8 mac_addr[ETH_ALEN];
+ u8 auth;
+ u8 keymgmt;
+ __le16 cipher;
+ u8 apsd_info;
+ u8 unused[3];
+ } ap_sta;
+ struct {
+ __le16 ch;
+ u8 bssid[ETH_ALEN];
+ u8 unused[8];
+ } ap_bss;
+ } u;
+ u8 beacon_ie_len;
+ u8 assoc_req_len;
+ u8 assoc_resp_len;
+ u8 assoc_info[1];
+} __packed;
+
+/* Disconnect Event */
+enum wmi_disconnect_reason {
+ NO_NETWORK_AVAIL = 0x01,
+
+ /* bmiss */
+ LOST_LINK = 0x02,
+
+ DISCONNECT_CMD = 0x03,
+ BSS_DISCONNECTED = 0x04,
+ AUTH_FAILED = 0x05,
+ ASSOC_FAILED = 0x06,
+ NO_RESOURCES_AVAIL = 0x07,
+ CSERV_DISCONNECT = 0x08,
+ INVALID_PROFILE = 0x0a,
+ DOT11H_CHANNEL_SWITCH = 0x0b,
+ PROFILE_MISMATCH = 0x0c,
+ CONNECTION_EVICTED = 0x0d,
+ IBSS_MERGE = 0xe,
+};
+
+#define ATH6KL_COUNTRY_RD_SHIFT 16
+
+struct ath6kl_wmi_regdomain {
+ __le32 reg_code;
+};
+
+struct wmi_disconnect_event {
+ /* reason code, see 802.11 spec. */
+ __le16 proto_reason_status;
+
+ /* set if known */
+ u8 bssid[ETH_ALEN];
+
+ /* see WMI_DISCONNECT_REASON */
+ u8 disconn_reason;
+
+ u8 assoc_resp_len;
+ u8 assoc_info[1];
+} __packed;
+
+/*
+ * BSS Info Event.
+ * Mechanism used to inform host of the presence and characteristic of
+ * wireless networks present. Consists of bss info header followed by
+ * the beacon or probe-response frame body. The 802.11 header is no included.
+ */
+enum wmi_bi_ftype {
+ BEACON_FTYPE = 0x1,
+ PROBERESP_FTYPE,
+ ACTION_MGMT_FTYPE,
+ PROBEREQ_FTYPE,
+};
+
+#define DEF_LRSSI_SCAN_PERIOD 5
+#define DEF_LRSSI_ROAM_THRESHOLD 20
+#define DEF_LRSSI_ROAM_FLOOR 60
+#define DEF_SCAN_FOR_ROAM_INTVL 2
+
+enum wmi_roam_ctrl {
+ WMI_FORCE_ROAM = 1,
+ WMI_SET_ROAM_MODE,
+ WMI_SET_HOST_BIAS,
+ WMI_SET_LRSSI_SCAN_PARAMS,
+};
+
+struct bss_bias {
+ u8 bssid[ETH_ALEN];
+ u8 bias;
+} __packed;
+
+struct bss_bias_info {
+ u8 num_bss;
+ struct bss_bias bss_bias[1];
+} __packed;
+
+struct low_rssi_scan_params {
+ __le16 lrssi_scan_period;
+ a_sle16 lrssi_scan_threshold;
+ a_sle16 lrssi_roam_threshold;
+ u8 roam_rssi_floor;
+ u8 reserved[1];
+} __packed;
+
+struct roam_ctrl_cmd {
+ union {
+ u8 bssid[ETH_ALEN];
+ u8 roam_mode;
+ struct bss_bias_info bss;
+ struct low_rssi_scan_params params;
+ } __packed info;
+ u8 roam_ctrl;
+} __packed;
+
+/* BSS INFO HDR version 2.0 */
+struct wmi_bss_info_hdr2 {
+ __le16 ch; /* frequency in MHz */
+
+ /* see, enum wmi_bi_ftype */
+ u8 frame_type;
+
+ u8 snr; /* note: rssi = snr - 95 dBm */
+ u8 bssid[ETH_ALEN];
+ __le16 ie_mask;
+} __packed;
+
+/* Command Error Event */
+enum wmi_error_code {
+ INVALID_PARAM = 0x01,
+ ILLEGAL_STATE = 0x02,
+ INTERNAL_ERROR = 0x03,
+};
+
+struct wmi_cmd_error_event {
+ __le16 cmd_id;
+ u8 err_code;
+} __packed;
+
+struct wmi_pstream_timeout_event {
+ u8 tx_queue_num;
+ u8 rx_queue_num;
+ u8 traffic_direc;
+ u8 traffic_class;
+} __packed;
+
+/*
+ * The WMI_NEIGHBOR_REPORT Event is generated by the target to inform
+ * the host of BSS's it has found that matches the current profile.
+ * It can be used by the host to cache PMKs and/to initiate pre-authentication
+ * if the BSS supports it. The first bssid is always the current associated
+ * BSS.
+ * The bssid and bssFlags information repeats according to the number
+ * or APs reported.
+ */
+enum wmi_bss_flags {
+ WMI_DEFAULT_BSS_FLAGS = 0x00,
+ WMI_PREAUTH_CAPABLE_BSS = 0x01,
+ WMI_PMKID_VALID_BSS = 0x02,
+};
+
+struct wmi_neighbor_info {
+ u8 bssid[ETH_ALEN];
+ u8 bss_flags; /* enum wmi_bss_flags */
+} __packed;
+
+struct wmi_neighbor_report_event {
+ u8 num_neighbors;
+ struct wmi_neighbor_info neighbor[0];
+} __packed;
+
+/* TKIP MIC Error Event */
+struct wmi_tkip_micerr_event {
+ u8 key_id;
+ u8 is_mcast;
+} __packed;
+
+/* WMI_SCAN_COMPLETE_EVENTID */
+struct wmi_scan_complete_event {
+ a_sle32 status;
+} __packed;
+
+#define MAX_OPT_DATA_LEN 1400
+
+/*
+ * Special frame receive Event.
+ * Mechanism used to inform host of the receiption of the special frames.
+ * Consists of special frame info header followed by special frame body.
+ * The 802.11 header is not included.
+ */
+struct wmi_opt_rx_info_hdr {
+ __le16 ch;
+ u8 frame_type;
+ s8 snr;
+ u8 src_addr[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+} __packed;
+
+/* Reporting statistic */
+struct tx_stats {
+ __le32 pkt;
+ __le32 byte;
+ __le32 ucast_pkt;
+ __le32 ucast_byte;
+ __le32 mcast_pkt;
+ __le32 mcast_byte;
+ __le32 bcast_pkt;
+ __le32 bcast_byte;
+ __le32 rts_success_cnt;
+ __le32 pkt_per_ac[4];
+ __le32 err_per_ac[4];
+
+ __le32 err;
+ __le32 fail_cnt;
+ __le32 retry_cnt;
+ __le32 mult_retry_cnt;
+ __le32 rts_fail_cnt;
+ a_sle32 ucast_rate;
+} __packed;
+
+struct rx_stats {
+ __le32 pkt;
+ __le32 byte;
+ __le32 ucast_pkt;
+ __le32 ucast_byte;
+ __le32 mcast_pkt;
+ __le32 mcast_byte;
+ __le32 bcast_pkt;
+ __le32 bcast_byte;
+ __le32 frgment_pkt;
+
+ __le32 err;
+ __le32 crc_err;
+ __le32 key_cache_miss;
+ __le32 decrypt_err;
+ __le32 dupl_frame;
+ a_sle32 ucast_rate;
+} __packed;
+
+struct tkip_ccmp_stats {
+ __le32 tkip_local_mic_fail;
+ __le32 tkip_cnter_measures_invoked;
+ __le32 tkip_replays;
+ __le32 tkip_fmt_err;
+ __le32 ccmp_fmt_err;
+ __le32 ccmp_replays;
+} __packed;
+
+struct pm_stats {
+ __le32 pwr_save_failure_cnt;
+ __le16 stop_tx_failure_cnt;
+ __le16 atim_tx_failure_cnt;
+ __le16 atim_rx_failure_cnt;
+ __le16 bcn_rx_failure_cnt;
+} __packed;
+
+struct cserv_stats {
+ __le32 cs_bmiss_cnt;
+ __le32 cs_low_rssi_cnt;
+ __le16 cs_connect_cnt;
+ __le16 cs_discon_cnt;
+ a_sle16 cs_ave_beacon_rssi;
+ __le16 cs_roam_count;
+ a_sle16 cs_rssi;
+ u8 cs_snr;
+ u8 cs_ave_beacon_snr;
+ u8 cs_last_roam_msec;
+} __packed;
+
+struct wlan_net_stats {
+ struct tx_stats tx;
+ struct rx_stats rx;
+ struct tkip_ccmp_stats tkip_ccmp_stats;
+} __packed;
+
+struct arp_stats {
+ __le32 arp_received;
+ __le32 arp_matched;
+ __le32 arp_replied;
+} __packed;
+
+struct wlan_wow_stats {
+ __le32 wow_pkt_dropped;
+ __le16 wow_evt_discarded;
+ u8 wow_host_pkt_wakeups;
+ u8 wow_host_evt_wakeups;
+} __packed;
+
+struct wmi_target_stats {
+ __le32 lq_val;
+ a_sle32 noise_floor_calib;
+ struct pm_stats pm_stats;
+ struct wlan_net_stats stats;
+ struct wlan_wow_stats wow_stats;
+ struct arp_stats arp_stats;
+ struct cserv_stats cserv_stats;
+} __packed;
+
+/*
+ * WMI_RSSI_THRESHOLD_EVENTID.
+ * Indicate the RSSI events to host. Events are indicated when we breach a
+ * thresold value.
+ */
+enum wmi_rssi_threshold_val {
+ WMI_RSSI_THRESHOLD1_ABOVE = 0,
+ WMI_RSSI_THRESHOLD2_ABOVE,
+ WMI_RSSI_THRESHOLD3_ABOVE,
+ WMI_RSSI_THRESHOLD4_ABOVE,
+ WMI_RSSI_THRESHOLD5_ABOVE,
+ WMI_RSSI_THRESHOLD6_ABOVE,
+ WMI_RSSI_THRESHOLD1_BELOW,
+ WMI_RSSI_THRESHOLD2_BELOW,
+ WMI_RSSI_THRESHOLD3_BELOW,
+ WMI_RSSI_THRESHOLD4_BELOW,
+ WMI_RSSI_THRESHOLD5_BELOW,
+ WMI_RSSI_THRESHOLD6_BELOW
+};
+
+struct wmi_rssi_threshold_event {
+ a_sle16 rssi;
+ u8 range;
+} __packed;
+
+enum wmi_snr_threshold_val {
+ WMI_SNR_THRESHOLD1_ABOVE = 1,
+ WMI_SNR_THRESHOLD1_BELOW,
+ WMI_SNR_THRESHOLD2_ABOVE,
+ WMI_SNR_THRESHOLD2_BELOW,
+ WMI_SNR_THRESHOLD3_ABOVE,
+ WMI_SNR_THRESHOLD3_BELOW,
+ WMI_SNR_THRESHOLD4_ABOVE,
+ WMI_SNR_THRESHOLD4_BELOW
+};
+
+struct wmi_snr_threshold_event {
+ /* see, enum wmi_snr_threshold_val */
+ u8 range;
+
+ u8 snr;
+} __packed;
+
+/* WMI_REPORT_ROAM_TBL_EVENTID */
+#define MAX_ROAM_TBL_CAND 5
+
+struct wmi_bss_roam_info {
+ a_sle32 roam_util;
+ u8 bssid[ETH_ALEN];
+ s8 rssi;
+ s8 rssidt;
+ s8 last_rssi;
+ s8 util;
+ s8 bias;
+
+ /* for alignment */
+ u8 reserved;
+} __packed;
+
+/* WMI_CAC_EVENTID */
+enum cac_indication {
+ CAC_INDICATION_ADMISSION = 0x00,
+ CAC_INDICATION_ADMISSION_RESP = 0x01,
+ CAC_INDICATION_DELETE = 0x02,
+ CAC_INDICATION_NO_RESP = 0x03,
+};
+
+#define WMM_TSPEC_IE_LEN 63
+
+struct wmi_cac_event {
+ u8 ac;
+ u8 cac_indication;
+ u8 status_code;
+ u8 tspec_suggestion[WMM_TSPEC_IE_LEN];
+} __packed;
+
+/* WMI_APLIST_EVENTID */
+
+enum aplist_ver {
+ APLIST_VER1 = 1,
+};
+
+struct wmi_ap_info_v1 {
+ u8 bssid[ETH_ALEN];
+ __le16 channel;
+} __packed;
+
+union wmi_ap_info {
+ struct wmi_ap_info_v1 ap_info_v1;
+} __packed;
+
+struct wmi_aplist_event {
+ u8 ap_list_ver;
+ u8 num_ap;
+ union wmi_ap_info ap_list[1];
+} __packed;
+
+/* Developer Commands */
+
+/*
+ * WMI_SET_BITRATE_CMDID
+ *
+ * Get bit rate cmd uses same definition as set bit rate cmd
+ */
+enum wmi_bit_rate {
+ RATE_AUTO = -1,
+ RATE_1Mb = 0,
+ RATE_2Mb = 1,
+ RATE_5_5Mb = 2,
+ RATE_11Mb = 3,
+ RATE_6Mb = 4,
+ RATE_9Mb = 5,
+ RATE_12Mb = 6,
+ RATE_18Mb = 7,
+ RATE_24Mb = 8,
+ RATE_36Mb = 9,
+ RATE_48Mb = 10,
+ RATE_54Mb = 11,
+ RATE_MCS_0_20 = 12,
+ RATE_MCS_1_20 = 13,
+ RATE_MCS_2_20 = 14,
+ RATE_MCS_3_20 = 15,
+ RATE_MCS_4_20 = 16,
+ RATE_MCS_5_20 = 17,
+ RATE_MCS_6_20 = 18,
+ RATE_MCS_7_20 = 19,
+ RATE_MCS_0_40 = 20,
+ RATE_MCS_1_40 = 21,
+ RATE_MCS_2_40 = 22,
+ RATE_MCS_3_40 = 23,
+ RATE_MCS_4_40 = 24,
+ RATE_MCS_5_40 = 25,
+ RATE_MCS_6_40 = 26,
+ RATE_MCS_7_40 = 27,
+};
+
+struct wmi_bit_rate_reply {
+ /* see, enum wmi_bit_rate */
+ s8 rate_index;
+} __packed;
+
+/*
+ * WMI_SET_FIXRATES_CMDID
+ *
+ * Get fix rates cmd uses same definition as set fix rates cmd
+ */
+struct wmi_fix_rates_reply {
+ /* see wmi_bit_rate */
+ __le32 fix_rate_mask;
+} __packed;
+
+enum roam_data_type {
+ /* get the roam time data */
+ ROAM_DATA_TIME = 1,
+};
+
+struct wmi_target_roam_time {
+ __le32 disassoc_time;
+ __le32 no_txrx_time;
+ __le32 assoc_time;
+ __le32 allow_txrx_time;
+ u8 disassoc_bssid[ETH_ALEN];
+ s8 disassoc_bss_rssi;
+ u8 assoc_bssid[ETH_ALEN];
+ s8 assoc_bss_rssi;
+} __packed;
+
+enum wmi_txop_cfg {
+ WMI_TXOP_DISABLED = 0,
+ WMI_TXOP_ENABLED
+};
+
+struct wmi_set_wmm_txop_cmd {
+ u8 txop_enable;
+} __packed;
+
+struct wmi_set_keepalive_cmd {
+ u8 keep_alive_intvl;
+} __packed;
+
+struct wmi_get_keepalive_cmd {
+ __le32 configured;
+ u8 keep_alive_intvl;
+} __packed;
+
+struct wmi_set_appie_cmd {
+ u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */
+ u8 ie_len;
+ u8 ie_info[0];
+} __packed;
+
+/* Notify the WSC registration status to the target */
+#define WSC_REG_ACTIVE 1
+#define WSC_REG_INACTIVE 0
+
+#define WOW_MAX_FILTER_LISTS 1
+#define WOW_MAX_FILTERS_PER_LIST 4
+#define WOW_PATTERN_SIZE 64
+#define WOW_MASK_SIZE 64
+
+#define MAC_MAX_FILTERS_PER_LIST 4
+
+struct wow_filter {
+ u8 wow_valid_filter;
+ u8 wow_filter_id;
+ u8 wow_filter_size;
+ u8 wow_filter_offset;
+ u8 wow_filter_mask[WOW_MASK_SIZE];
+ u8 wow_filter_pattern[WOW_PATTERN_SIZE];
+} __packed;
+
+#define MAX_IP_ADDRS 2
+
+struct wmi_set_ip_cmd {
+ /* IP in network byte order */
+ __le32 ips[MAX_IP_ADDRS];
+} __packed;
+
+/* WMI_GET_WOW_LIST_CMD reply */
+struct wmi_get_wow_list_reply {
+ /* number of patterns in reply */
+ u8 num_filters;
+
+ /* this is filter # x of total num_filters */
+ u8 this_filter_num;
+
+ u8 wow_mode;
+ u8 host_mode;
+ struct wow_filter wow_filters[1];
+} __packed;
+
+/* WMI_SET_AKMP_PARAMS_CMD */
+
+struct wmi_pmkid {
+ u8 pmkid[WMI_PMKID_LEN];
+} __packed;
+
+/* WMI_GET_PMKID_LIST_CMD Reply */
+struct wmi_pmkid_list_reply {
+ __le32 num_pmkid;
+ u8 bssid_list[ETH_ALEN][1];
+ struct wmi_pmkid pmkid_list[1];
+} __packed;
+
+/* WMI_ADDBA_REQ_EVENTID */
+struct wmi_addba_req_event {
+ u8 tid;
+ u8 win_sz;
+ __le16 st_seq_no;
+
+ /* f/w response for ADDBA Req; OK (0) or failure (!=0) */
+ u8 status;
+} __packed;
+
+/* WMI_ADDBA_RESP_EVENTID */
+struct wmi_addba_resp_event {
+ u8 tid;
+
+ /* OK (0), failure (!=0) */
+ u8 status;
+
+ /* three values: not supported(0), 3839, 8k */
+ __le16 amsdu_sz;
+} __packed;
+
+/* WMI_DELBA_EVENTID
+ * f/w received a DELBA for peer and processed it.
+ * Host is notified of this
+ */
+struct wmi_delba_event {
+ u8 tid;
+ u8 is_peer_initiator;
+ __le16 reason_code;
+} __packed;
+
+#define PEER_NODE_JOIN_EVENT 0x00
+#define PEER_NODE_LEAVE_EVENT 0x01
+#define PEER_FIRST_NODE_JOIN_EVENT 0x10
+#define PEER_LAST_NODE_LEAVE_EVENT 0x11
+
+struct wmi_peer_node_event {
+ u8 event_code;
+ u8 peer_mac_addr[ETH_ALEN];
+} __packed;
+
+/* Transmit complete event data structure(s) */
+
+/* version 1 of tx complete msg */
+struct tx_complete_msg_v1 {
+#define TX_COMPLETE_STATUS_SUCCESS 0
+#define TX_COMPLETE_STATUS_RETRIES 1
+#define TX_COMPLETE_STATUS_NOLINK 2
+#define TX_COMPLETE_STATUS_TIMEOUT 3
+#define TX_COMPLETE_STATUS_OTHER 4
+
+ u8 status;
+
+ /* packet ID to identify parent packet */
+ u8 pkt_id;
+
+ /* rate index on successful transmission */
+ u8 rate_idx;
+
+ /* number of ACK failures in tx attempt */
+ u8 ack_failures;
+} __packed;
+
+struct wmi_tx_complete_event {
+ /* no of tx comp msgs following this struct */
+ u8 num_msg;
+
+ /* length in bytes for each individual msg following this struct */
+ u8 msg_len;
+
+ /* version of tx complete msg data following this struct */
+ u8 msg_type;
+
+ /* individual messages follow this header */
+ u8 reserved;
+} __packed;
+
+/*
+ * ------- AP Mode definitions --------------
+ */
+
+/*
+ * !!! Warning !!!
+ * -Changing the following values needs compilation of both driver and firmware
+ */
+#define AP_MAX_NUM_STA 8
+
+/* Spl. AID used to set DTIM flag in the beacons */
+#define MCAST_AID 0xFF
+
+#define DEF_AP_COUNTRY_CODE "US "
+
+/* Used with WMI_AP_SET_NUM_STA_CMDID */
+
+/*
+ * Used with WMI_AP_SET_MLME_CMDID
+ */
+
+/* MLME Commands */
+#define WMI_AP_MLME_ASSOC 1 /* associate station */
+#define WMI_AP_DISASSOC 2 /* disassociate station */
+#define WMI_AP_DEAUTH 3 /* deauthenticate station */
+#define WMI_AP_MLME_AUTHORIZE 4 /* authorize station */
+#define WMI_AP_MLME_UNAUTHORIZE 5 /* unauthorize station */
+
+struct wmi_ap_set_mlme_cmd {
+ u8 mac[ETH_ALEN];
+ __le16 reason; /* 802.11 reason code */
+ u8 cmd; /* operation to perform (WMI_AP_*) */
+} __packed;
+
+struct wmi_ap_set_pvb_cmd {
+ __le32 flag;
+ __le16 rsvd;
+ __le16 aid;
+} __packed;
+
+struct wmi_rx_frame_format_cmd {
+ /* version of meta data for rx packets <0 = default> (0-7 = valid) */
+ u8 meta_ver;
+
+ /*
+ * 1 == leave .11 header intact,
+ * 0 == replace .11 header with .3 <default>
+ */
+ u8 dot11_hdr;
+
+ /*
+ * 1 == defragmentation is performed by host,
+ * 0 == performed by target <default>
+ */
+ u8 defrag_on_host;
+
+ /* for alignment */
+ u8 reserved[1];
+} __packed;
+
+/* AP mode events */
+
+/* WMI_PS_POLL_EVENT */
+struct wmi_pspoll_event {
+ __le16 aid;
+} __packed;
+
+struct wmi_per_sta_stat {
+ __le32 tx_bytes;
+ __le32 tx_pkts;
+ __le32 tx_error;
+ __le32 tx_discard;
+ __le32 rx_bytes;
+ __le32 rx_pkts;
+ __le32 rx_error;
+ __le32 rx_discard;
+ __le32 aid;
+} __packed;
+
+struct wmi_ap_mode_stat {
+ __le32 action;
+ struct wmi_per_sta_stat sta[AP_MAX_NUM_STA + 1];
+} __packed;
+
+/* End of AP mode definitions */
+
+struct wmi_remain_on_chnl_cmd {
+ __le32 freq;
+ __le32 duration;
+} __packed;
+
+struct wmi_send_action_cmd {
+ __le32 id;
+ __le32 freq;
+ __le32 wait;
+ __le16 len;
+ u8 data[0];
+} __packed;
+
+struct wmi_tx_status_event {
+ __le32 id;
+ u8 ack_status;
+} __packed;
+
+struct wmi_probe_req_report_cmd {
+ u8 enable;
+} __packed;
+
+struct wmi_disable_11b_rates_cmd {
+ u8 disable;
+} __packed;
+
+struct wmi_set_appie_extended_cmd {
+ u8 role_id;
+ u8 mgmt_frm_type;
+ u8 ie_len;
+ u8 ie_info[0];
+} __packed;
+
+struct wmi_remain_on_chnl_event {
+ __le32 freq;
+ __le32 duration;
+} __packed;
+
+struct wmi_cancel_remain_on_chnl_event {
+ __le32 freq;
+ __le32 duration;
+ u8 status;
+} __packed;
+
+struct wmi_rx_action_event {
+ __le32 freq;
+ __le16 len;
+ u8 data[0];
+} __packed;
+
+struct wmi_p2p_capabilities_event {
+ __le16 len;
+ u8 data[0];
+} __packed;
+
+struct wmi_p2p_rx_probe_req_event {
+ __le32 freq;
+ __le16 len;
+ u8 data[0];
+} __packed;
+
+#define P2P_FLAG_CAPABILITIES_REQ (0x00000001)
+#define P2P_FLAG_MACADDR_REQ (0x00000002)
+#define P2P_FLAG_HMODEL_REQ (0x00000002)
+
+struct wmi_get_p2p_info {
+ __le32 info_req_flags;
+} __packed;
+
+struct wmi_p2p_info_event {
+ __le32 info_req_flags;
+ __le16 len;
+ u8 data[0];
+} __packed;
+
+struct wmi_p2p_capabilities {
+ u8 go_power_save;
+} __packed;
+
+struct wmi_p2p_macaddr {
+ u8 mac_addr[ETH_ALEN];
+} __packed;
+
+struct wmi_p2p_hmodel {
+ u8 p2p_model;
+} __packed;
+
+struct wmi_p2p_probe_response_cmd {
+ __le32 freq;
+ u8 destination_addr[ETH_ALEN];
+ __le16 len;
+ u8 data[0];
+} __packed;
+
+/* Extended WMI (WMIX)
+ *
+ * Extended WMIX commands are encapsulated in a WMI message with
+ * cmd=WMI_EXTENSION_CMD.
+ *
+ * Extended WMI commands are those that are needed during wireless
+ * operation, but which are not really wireless commands. This allows,
+ * for instance, platform-specific commands. Extended WMI commands are
+ * embedded in a WMI command message with WMI_COMMAND_ID=WMI_EXTENSION_CMDID.
+ * Extended WMI events are similarly embedded in a WMI event message with
+ * WMI_EVENT_ID=WMI_EXTENSION_EVENTID.
+ */
+struct wmix_cmd_hdr {
+ __le32 cmd_id;
+} __packed;
+
+enum wmix_command_id {
+ WMIX_DSETOPEN_REPLY_CMDID = 0x2001,
+ WMIX_DSETDATA_REPLY_CMDID,
+ WMIX_GPIO_OUTPUT_SET_CMDID,
+ WMIX_GPIO_INPUT_GET_CMDID,
+ WMIX_GPIO_REGISTER_SET_CMDID,
+ WMIX_GPIO_REGISTER_GET_CMDID,
+ WMIX_GPIO_INTR_ACK_CMDID,
+ WMIX_HB_CHALLENGE_RESP_CMDID,
+ WMIX_DBGLOG_CFG_MODULE_CMDID,
+ WMIX_PROF_CFG_CMDID, /* 0x200a */
+ WMIX_PROF_ADDR_SET_CMDID,
+ WMIX_PROF_START_CMDID,
+ WMIX_PROF_STOP_CMDID,
+ WMIX_PROF_COUNT_GET_CMDID,
+};
+
+enum wmix_event_id {
+ WMIX_DSETOPENREQ_EVENTID = 0x3001,
+ WMIX_DSETCLOSE_EVENTID,
+ WMIX_DSETDATAREQ_EVENTID,
+ WMIX_GPIO_INTR_EVENTID,
+ WMIX_GPIO_DATA_EVENTID,
+ WMIX_GPIO_ACK_EVENTID,
+ WMIX_HB_CHALLENGE_RESP_EVENTID,
+ WMIX_DBGLOG_EVENTID,
+ WMIX_PROF_COUNT_EVENTID,
+};
+
+/*
+ * ------Error Detection support-------
+ */
+
+/*
+ * WMIX_HB_CHALLENGE_RESP_CMDID
+ * Heartbeat Challenge Response command
+ */
+struct wmix_hb_challenge_resp_cmd {
+ __le32 cookie;
+ __le32 source;
+} __packed;
+
+struct ath6kl_wmix_dbglog_cfg_module_cmd {
+ __le32 valid;
+ __le32 config;
+} __packed;
+
+/* End of Extended WMI (WMIX) */
+
+enum wmi_sync_flag {
+ NO_SYNC_WMIFLAG = 0,
+
+ /* transmit all queued data before cmd */
+ SYNC_BEFORE_WMIFLAG,
+
+ /* any new data waits until cmd execs */
+ SYNC_AFTER_WMIFLAG,
+
+ SYNC_BOTH_WMIFLAG,
+
+ /* end marker */
+ END_WMIFLAG
+};
+
+enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi);
+void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id);
+int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb);
+int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
+ u8 msg_type, bool more_data,
+ enum wmi_data_hdr_data_type data_type,
+ u8 meta_ver, void *tx_meta_info);
+
+int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb);
+int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb);
+int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb,
+ u32 layer2_priority, bool wmm_enabled,
+ u8 *ac);
+
+int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb);
+
+int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
+ enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag);
+
+int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
+ enum dot11_auth_mode dot11_auth_mode,
+ enum auth_mode auth_mode,
+ enum crypto_type pairwise_crypto,
+ u8 pairwise_crypto_len,
+ enum crypto_type group_crypto,
+ u8 group_crypto_len, int ssid_len, u8 *ssid,
+ u8 *bssid, u16 channel, u32 ctrl_flags);
+
+int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel);
+int ath6kl_wmi_disconnect_cmd(struct wmi *wmi);
+int ath6kl_wmi_startscan_cmd(struct wmi *wmi, 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_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec,
+ u16 fg_end_sec, u16 bg_sec,
+ u16 minact_chdw_msec, u16 maxact_chdw_msec,
+ u16 pas_chdw_msec, u8 short_scan_ratio,
+ u8 scan_ctrl_flag, u32 max_dfsch_act_time,
+ u16 maxact_scan_per_ssid);
+int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask);
+int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag,
+ u8 ssid_len, u8 *ssid);
+int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval,
+ u16 listen_beacons);
+int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode);
+int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period,
+ u16 ps_poll_num, u16 dtim_policy,
+ u16 tx_wakup_policy, u16 num_tx_to_wakeup,
+ u16 ps_fail_event_policy);
+int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout);
+int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi,
+ struct wmi_create_pstream_cmd *pstream);
+int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid);
+
+int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold);
+int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status,
+ u8 preamble_policy);
+
+int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source);
+int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config);
+
+int ath6kl_wmi_get_stats_cmd(struct wmi *wmi);
+int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
+ enum crypto_type key_type,
+ u8 key_usage, u8 key_len,
+ u8 *key_rsc, u8 *key_material,
+ u8 key_op_ctrl, u8 *mac_addr,
+ enum wmi_sync_flag sync_flag);
+int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk);
+int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index);
+int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid,
+ const u8 *pmkid, bool set);
+int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM);
+int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi);
+
+int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg);
+int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl);
+int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
+
+s32 ath6kl_wmi_get_rate(s8 rate_index);
+
+int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd);
+int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
+
+/* AP mode */
+int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p);
+
+int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason);
+
+int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag);
+
+int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_version,
+ bool rx_dot11_hdr, bool defrag_on_host);
+
+int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie,
+ u8 ie_len);
+
+/* P2P */
+int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable);
+
+int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur);
+
+int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait,
+ const u8 *data, u16 data_len);
+
+int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq,
+ const u8 *dst,
+ const u8 *data, u16 data_len);
+
+int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable);
+
+int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags);
+
+int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi);
+
+int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie,
+ u8 ie_len);
+
+void *ath6kl_wmi_init(struct ath6kl *devt);
+void ath6kl_wmi_shutdown(struct wmi *wmi);
+
+#endif /* WMI_H */
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 05a6fade7b1c..36ed3c46fec6 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -21,6 +21,7 @@ ath9k_hw-y:= \
ar5008_phy.o \
ar9002_calib.o \
ar9003_calib.o \
+ ar9003_rtt.o \
calib.o \
eeprom.o \
eeprom_def.o \
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 0b36fcf8a280..85a54cd2b083 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -133,7 +133,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
goto err_free_hw;
}
- ret = ath9k_init_device(id->driver_data, sc, 0x0, &ath_ahb_bus_ops);
+ ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
if (ret) {
dev_err(&pdev->dev, "failed to initialize device\n");
goto err_irq;
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index bfb6481f01f9..2776c3c1f506 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -273,7 +273,8 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
immunityLevel, aniState->noiseFloor,
aniState->rssiThrLow, aniState->rssiThrHigh);
- aniState->ofdmNoiseImmunityLevel = immunityLevel;
+ if (aniState->update_ani)
+ aniState->ofdmNoiseImmunityLevel = immunityLevel;
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
@@ -346,7 +347,8 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
- aniState->cckNoiseImmunityLevel = immunityLevel;
+ if (aniState->update_ani)
+ aniState->cckNoiseImmunityLevel = immunityLevel;
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
@@ -502,9 +504,6 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
ATH9K_ANI_CCK_WEAK_SIG_THR);
- ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
- ATH9K_RX_FILTER_PHYERR);
-
ath9k_ani_restart(ah);
return;
}
@@ -525,8 +524,6 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
aniState->firstepLevel);
- ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
- ~ATH9K_RX_FILTER_PHYERR);
ath9k_ani_restart(ah);
ENABLE_REGWRITE_BUFFER(ah);
@@ -593,6 +590,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
aniState->ofdmNoiseImmunityLevel,
aniState->cckNoiseImmunityLevel);
+ aniState->update_ani = false;
ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
}
@@ -609,6 +607,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
aniState->ofdmNoiseImmunityLevel,
aniState->cckNoiseImmunityLevel);
+ aniState->update_ani = true;
ath9k_hw_set_ofdm_nil(ah,
aniState->ofdmNoiseImmunityLevel);
ath9k_hw_set_cck_nil(ah,
@@ -643,7 +642,7 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
listenTime = ath_hw_get_listen_time(common);
if (listenTime <= 0) {
- ah->stats.ast_ani_lneg++;
+ ah->stats.ast_ani_lneg_or_lzero++;
ath9k_ani_restart(ah);
return false;
}
@@ -892,6 +891,8 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
ani->ofdmWeakSigDetectOff =
!ATH9K_ANI_USE_OFDM_WEAK_SIG;
ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+ ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
+ ani->update_ani = false;
}
/*
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index dbab5b9ce494..83029d6c7b22 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -122,6 +122,7 @@ struct ar5416AniState {
u8 firstepLevel;
u8 ofdmWeakSigDetectOff;
u8 cckWeakSigThreshold;
+ bool update_ani;
u32 listenTime;
int32_t rssiThrLow;
int32_t rssiThrHigh;
@@ -148,8 +149,7 @@ struct ar5416Stats {
u32 ast_ani_ofdmerrs;
u32 ast_ani_cckerrs;
u32 ast_ani_reset;
- u32 ast_ani_lzero;
- u32 ast_ani_lneg;
+ u32 ast_ani_lneg_or_lzero;
u32 avgbrssi;
struct ath9k_mib_stats ast_mibstats;
};
@@ -159,7 +159,5 @@ void ath9k_enable_mib_counters(struct ath_hw *ah);
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
void ath9k_hw_ani_setup(struct ath_hw *ah);
void ath9k_hw_ani_init(struct ath_hw *ah);
-int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
- struct ath9k_channel *chan);
#endif /* ANI_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h
index 234617c948a1..f81e7fc60a36 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h
@@ -14,70 +14,71 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-static const u32 ar5416Modes[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0},
- {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de},
- {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
- {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
- {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
- {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
- {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134},
- {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
- {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
- {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
- {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
- {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
- {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120},
- {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
- {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
- {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
- {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
- {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
- {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
- {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
- {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
- {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
- {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
- {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
- {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
- {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
- {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
- {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
- {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
- {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
- {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
- {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
- {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar5416Modes[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0},
+ {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de},
+ {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
+ {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
+ {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134},
+ {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
+ {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+ {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+ {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+ {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+ {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120},
+ {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
+ {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+ {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+ {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+ {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+ {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+ {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+ {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+ {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+ {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+ {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+ {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+ {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+ {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+ {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+ {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+ {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
static const u32 ar5416Common[][2] = {
@@ -668,6 +669,6 @@ static const u32 ar5416Addac[][2] = {
{0x0000989c, 0x00000000},
{0x0000989c, 0x00000000},
{0x0000989c, 0x00000000},
- {0x000098cc, 0x00000000},
+ {0x000098c4, 0x00000000},
};
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index fac2c6da6ca4..f199e9e25149 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -704,8 +704,10 @@ static void ar5008_hw_override_ini(struct ath_hw *ah,
REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
}
- if (!AR_SREV_5416_20_OR_LATER(ah) ||
- AR_SREV_9280_20_OR_LATER(ah))
+ REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+ if (AR_SREV_9280_20_OR_LATER(ah))
return;
/*
* Disable BB clock gating
@@ -761,10 +763,8 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah,
static int ar5008_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
int i, regWrites = 0;
- struct ieee80211_channel *channel = chan->chan;
u32 modesIndex, freqIndex;
switch (chan->chanmode) {
@@ -802,7 +802,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
/* Write ADDAC shifts */
REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
- ah->eep_ops->set_addac(ah, chan);
+ if (ah->eep_ops->set_addac)
+ ah->eep_ops->set_addac(ah, chan);
if (AR_SREV_5416_22_OR_LATER(ah)) {
REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
@@ -900,14 +901,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
ar5008_hw_set_channel_regs(ah, chan);
ar5008_hw_init_chain_masks(ah);
ath9k_olc_init(ah);
-
- /* Set TX power */
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- channel->max_antenna_gain * 2,
- channel->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit), false);
+ ath9k_hw_apply_txpower(ah, chan);
/* Write analog registers */
if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
@@ -1007,24 +1001,6 @@ static void ar5008_restore_chainmask(struct ath_hw *ah)
}
}
-static void ar5008_set_diversity(struct ath_hw *ah, bool value)
-{
- u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
- if (value)
- v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
- else
- v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
- REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
-}
-
-static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- if (chan && IS_CHAN_5GHZ(chan))
- return 0x1450;
- return 0x1458;
-}
-
static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
@@ -1654,7 +1630,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->rfbus_req = ar5008_hw_rfbus_req;
priv_ops->rfbus_done = ar5008_hw_rfbus_done;
priv_ops->restore_chainmask = ar5008_restore_chainmask;
- priv_ops->set_diversity = ar5008_set_diversity;
priv_ops->do_getnf = ar5008_hw_do_getnf;
priv_ops->set_radar_params = ar5008_hw_set_radar_params;
@@ -1664,9 +1639,7 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
} else
priv_ops->ani_control = ar5008_hw_ani_control_old;
- if (AR_SREV_9100(ah))
- priv_ops->compute_pll_control = ar9100_hw_compute_pll_control;
- else if (AR_SREV_9160_10_OR_LATER(ah))
+ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
else
priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
diff --git a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h
index 6d2e2f3303f9..e8bdc75405f1 100644
--- a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h
@@ -14,73 +14,74 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-static const u32 ar5416Modes_9100[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
- {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2},
- {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
- {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
- {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
- {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
- {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
- {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204},
- {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
- {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e},
- {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff},
- {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
- {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
- {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
- {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
- {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00},
- {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
- {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
- {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
- {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
- {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
- {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
- {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
- {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
- {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
- {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
- {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
- {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
- {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
- {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
- {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
- {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
- {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
- {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
- {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar5416Modes_9100[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+ {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
+ {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+ {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+ {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204},
+ {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
+ {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e},
+ {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff},
+ {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+ {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+ {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+ {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+ {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00},
+ {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+ {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+ {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+ {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+ {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+ {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+ {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+ {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+ {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+ {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+ {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+ {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+ {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+ {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
static const u32 ar5416Common_9100[][2] = {
@@ -666,71 +667,72 @@ static const u32 ar5416Addac_9100[][2] = {
{0x000098cc, 0x00000000},
};
-static const u32 ar5416Modes_9160[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
- {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
- {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2},
- {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
- {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
- {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
- {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
- {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
- {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
- {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
- {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
- {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
- {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
- {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce},
- {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00},
- {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
- {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
- {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
- {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
- {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
- {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
- {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
- {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
- {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
- {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
- {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
- {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
- {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
- {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
- {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
- {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
- {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
- {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
- {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar5416Modes_9160[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+ {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+ {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
+ {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+ {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+ {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+ {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+ {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+ {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+ {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+ {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00},
+ {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+ {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+ {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+ {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+ {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+ {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+ {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+ {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+ {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+ {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+ {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+ {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+ {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+ {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
static const u32 ar5416Common_9160[][2] = {
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 2d394af82171..e0ab0657cc3a 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -869,6 +869,7 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
ar9002_hw_pa_cal(ah, true);
/* Do NF Calibration after DC offset and other calibrations */
+ ath9k_hw_loadnf(ah, chan);
ath9k_hw_start_nfcal(ah, true);
if (ah->caldata)
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index 44d9d8d56490..626d547d2f06 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -30,7 +30,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
{
if (AR_SREV_9271(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
- ARRAY_SIZE(ar9271Modes_9271), 6);
+ ARRAY_SIZE(ar9271Modes_9271), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
ARRAY_SIZE(ar9271Common_9271), 2);
INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
@@ -41,21 +41,21 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2);
INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
ar9271Modes_9271_1_0_only,
- ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6);
+ ARRAY_SIZE(ar9271Modes_9271_1_0_only), 5);
INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
- ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6);
+ ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5);
INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
ar9271Modes_high_power_tx_gain_9271,
- ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6);
+ ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
ar9271Modes_normal_power_tx_gain_9271,
- ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6);
+ ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
return;
}
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
- ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
+ ARRAY_SIZE(ar9287Modes_9287_1_1), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
ARRAY_SIZE(ar9287Common_9287_1_1), 2);
if (ah->config.pcie_clock_req)
@@ -71,7 +71,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
- ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
+ ARRAY_SIZE(ar9285Modes_9285_1_2), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
ARRAY_SIZE(ar9285Common_9285_1_2), 2);
@@ -87,7 +87,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
}
} else if (AR_SREV_9280_20_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
- ARRAY_SIZE(ar9280Modes_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_9280_2), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
ARRAY_SIZE(ar9280Common_9280_2), 2);
@@ -105,7 +105,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
} else if (AR_SREV_9160_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
- ARRAY_SIZE(ar5416Modes_9160), 6);
+ ARRAY_SIZE(ar5416Modes_9160), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
ARRAY_SIZE(ar5416Common_9160), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
@@ -134,7 +134,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
}
} else if (AR_SREV_9100_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
- ARRAY_SIZE(ar5416Modes_9100), 6);
+ ARRAY_SIZE(ar5416Modes_9100), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
ARRAY_SIZE(ar5416Common_9100), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
@@ -157,7 +157,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar5416Addac_9100), 2);
} else {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
- ARRAY_SIZE(ar5416Modes), 6);
+ ARRAY_SIZE(ar5416Modes), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
ARRAY_SIZE(ar5416Common), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
@@ -207,19 +207,19 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_backoff_13db_rxgain_9280_2,
- ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 5);
else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_backoff_23db_rxgain_9280_2,
- ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 5);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_original_rxgain_9280_2,
- ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
} else {
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_original_rxgain_9280_2,
- ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
}
}
@@ -234,15 +234,15 @@ static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_high_power_tx_gain_9280_2,
- ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_original_tx_gain_9280_2,
- ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_original_tx_gain_9280_2,
- ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+ ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
}
}
@@ -251,14 +251,14 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
if (AR_SREV_9287_11_OR_LATER(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_1,
- ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
+ ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 5);
else if (AR_SREV_9280_20(ah))
ar9280_20_hw_init_rxgain_ini(ah);
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_1,
- ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
+ ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5);
} else if (AR_SREV_9280_20(ah)) {
ar9280_20_hw_init_txgain_ini(ah);
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
@@ -270,24 +270,24 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_high_power,
ARRAY_SIZE(
- ar9285Modes_XE2_0_high_power), 6);
+ ar9285Modes_XE2_0_high_power), 5);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_high_power_tx_gain_9285_1_2,
ARRAY_SIZE(
- ar9285Modes_high_power_tx_gain_9285_1_2), 6);
+ ar9285Modes_high_power_tx_gain_9285_1_2), 5);
}
} else {
if (AR_SREV_9285E_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_normal_power,
ARRAY_SIZE(
- ar9285Modes_XE2_0_normal_power), 6);
+ ar9285Modes_XE2_0_normal_power), 5);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_original_tx_gain_9285_1_2,
ARRAY_SIZE(
- ar9285Modes_original_tx_gain_9285_1_2), 6);
+ ar9285Modes_original_tx_gain_9285_1_2), 5);
}
}
}
@@ -303,17 +303,13 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
* register as the other analog registers. Hence the 9 writes.
*/
static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
- int restore,
- int power_off)
+ bool power_off)
{
u8 i;
u32 val;
- if (ah->is_pciexpress != true || ah->aspm_enabled != true)
- return;
-
/* Nothing to do on restore for 11N */
- if (!restore) {
+ if (!power_off /* !restore */) {
if (AR_SREV_9280_20_OR_LATER(ah)) {
/*
* AR9280 2.0 or later chips use SerDes values from the
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
index 7573257731b6..863db321070d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
@@ -14,53 +14,54 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-static const u32 ar9280Modes_9280_2[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e},
- {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
- {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2},
- {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
- {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
- {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
- {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010},
- {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
- {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
- {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210},
- {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce},
- {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c},
- {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
- {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444},
- {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019},
- {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000},
- {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000},
- {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
- {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000},
- {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000},
+static const u32 ar9280Modes_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+ {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+ {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+ {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b},
+ {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010},
+ {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+ {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+ {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210},
+ {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c},
+ {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444},
+ {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019},
+ {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000},
+ {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
+ {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000},
+ {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000},
};
static const u32 ar9280Common_9280_2[][2] = {
@@ -424,471 +425,476 @@ static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
{0x00009918, 0x0000000b, 0x00000016},
};
-static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
- {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290},
- {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300},
- {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304},
- {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308},
- {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c},
- {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
- {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
- {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
- {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
- {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
- {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
- {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
- {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
- {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
- {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
- {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
- {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
- {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
- {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
- {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
- {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
- {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
- {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
- {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
- {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
- {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
- {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
- {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
- {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
- {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
- {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
- {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
- {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
- {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
- {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
- {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
- {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
- {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
- {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
- {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
- {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
- {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
- {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
- {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
- {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
- {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
- {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
- {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10},
- {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80, 0x00008b80},
- {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84, 0x00008b84},
- {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88, 0x00008b88},
- {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c, 0x00008b8c},
- {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90, 0x00008b90},
- {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94, 0x00008b94},
- {0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98, 0x00008b98},
- {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4, 0x00008ba4},
- {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8, 0x00008ba8},
- {0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac, 0x00008bac},
- {0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0, 0x00008bb0},
- {0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4, 0x00008bb4},
- {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1, 0x00008ba1},
- {0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5, 0x00008ba5},
- {0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9, 0x00008ba9},
- {0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad, 0x00008bad},
- {0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1, 0x00008bb1},
- {0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5, 0x00008bb5},
- {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2, 0x00008ba2},
- {0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6, 0x00008ba6},
- {0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa, 0x00008baa},
- {0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae, 0x00008bae},
- {0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2, 0x00008bb2},
- {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6, 0x00008bb6},
- {0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3, 0x00008ba3},
- {0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7, 0x00008ba7},
- {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab, 0x00008bab},
- {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf, 0x00008baf},
- {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3, 0x00008bb3},
- {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7, 0x00008bb7},
- {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3, 0x00008bc3},
- {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7, 0x00008bc7},
- {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb, 0x00008bcb},
- {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf, 0x00008bcf},
- {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3, 0x00008bd3},
- {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7, 0x00008bd7},
- {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
- {0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055},
- {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055},
+static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290},
+ {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300},
+ {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304},
+ {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308},
+ {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c},
+ {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+ {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+ {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+ {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+ {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+ {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+ {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+ {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+ {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+ {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+ {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+ {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+ {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+ {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+ {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+ {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+ {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+ {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+ {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+ {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+ {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+ {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+ {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+ {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+ {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+ {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+ {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+ {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+ {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+ {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+ {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+ {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+ {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+ {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+ {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+ {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+ {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+ {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+ {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+ {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+ {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+ {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+ {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+ {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10},
+ {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80},
+ {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84},
+ {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88},
+ {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c},
+ {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90},
+ {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94},
+ {0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98},
+ {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4},
+ {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8},
+ {0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac},
+ {0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0},
+ {0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4},
+ {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1},
+ {0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5},
+ {0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9},
+ {0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad},
+ {0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1},
+ {0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5},
+ {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2},
+ {0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6},
+ {0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa},
+ {0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae},
+ {0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2},
+ {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6},
+ {0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3},
+ {0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7},
+ {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab},
+ {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf},
+ {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3},
+ {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7},
+ {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3},
+ {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7},
+ {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb},
+ {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf},
+ {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3},
+ {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7},
+ {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb},
+ {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb},
+ {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb},
+ {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb},
+ {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb},
+ {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb},
+ {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb},
+ {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb},
+ {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb},
+ {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb},
+ {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb},
+ {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb},
+ {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb},
+ {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb},
+ {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb},
+ {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb},
+ {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb},
+ {0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055},
};
-static const u32 ar9280Modes_original_rxgain_9280_2[][6] = {
- {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
- {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
- {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
- {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
- {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
- {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
- {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
- {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
- {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
- {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
- {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
- {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
- {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
- {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
- {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
- {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
- {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
- {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
- {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
- {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
- {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
- {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
- {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
- {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
- {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
- {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
- {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
- {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
- {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
- {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
- {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
- {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
- {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
- {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
- {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
- {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
- {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
- {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
- {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
- {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
- {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
- {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
- {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80},
- {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84},
- {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88},
- {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c},
- {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90},
- {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80},
- {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84},
- {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88},
- {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c},
- {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90},
- {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c},
- {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310},
- {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384},
- {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388},
- {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324},
- {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704},
- {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4},
- {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8},
- {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710},
- {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714},
- {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720},
- {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724},
- {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728},
- {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c},
- {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0},
- {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4},
- {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8},
- {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0},
- {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4},
- {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8},
- {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5},
- {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9},
- {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad},
- {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1},
- {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5},
- {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9},
- {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5},
- {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9},
- {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1},
- {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5},
- {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9},
- {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6},
- {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca},
- {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce},
- {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2},
- {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6},
- {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3},
- {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7},
- {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb},
- {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf},
- {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7},
- {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db},
- {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db},
- {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db},
- {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
- {0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063},
- {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063},
+static const u32 ar9280Modes_original_rxgain_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000},
+ {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000},
+ {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000},
+ {0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000},
+ {0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000},
+ {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+ {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+ {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+ {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+ {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+ {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+ {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+ {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+ {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+ {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+ {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+ {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+ {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+ {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+ {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+ {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+ {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+ {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+ {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+ {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+ {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+ {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+ {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+ {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+ {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+ {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+ {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+ {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+ {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+ {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+ {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+ {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+ {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+ {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+ {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+ {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+ {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+ {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+ {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+ {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+ {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+ {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+ {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+ {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80},
+ {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84},
+ {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88},
+ {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c},
+ {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90},
+ {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80},
+ {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84},
+ {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88},
+ {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c},
+ {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90},
+ {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c},
+ {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310},
+ {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384},
+ {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388},
+ {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324},
+ {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704},
+ {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4},
+ {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8},
+ {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710},
+ {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714},
+ {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720},
+ {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724},
+ {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728},
+ {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c},
+ {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0},
+ {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4},
+ {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8},
+ {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0},
+ {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4},
+ {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8},
+ {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5},
+ {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9},
+ {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad},
+ {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1},
+ {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5},
+ {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9},
+ {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5},
+ {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9},
+ {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1},
+ {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5},
+ {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9},
+ {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6},
+ {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca},
+ {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce},
+ {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2},
+ {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6},
+ {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3},
+ {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7},
+ {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb},
+ {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf},
+ {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7},
+ {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db},
+ {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db},
+ {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db},
+ {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063},
};
-static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
- {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290},
- {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300},
- {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304},
- {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308},
- {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c},
- {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
- {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
- {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
- {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
- {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
- {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
- {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
- {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
- {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
- {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
- {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
- {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
- {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
- {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
- {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
- {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
- {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
- {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
- {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
- {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
- {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
- {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
- {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
- {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
- {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
- {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
- {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
- {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
- {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
- {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
- {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
- {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
- {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
- {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
- {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
- {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
- {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
- {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
- {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
- {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
- {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
- {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
- {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
- {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80},
- {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84},
- {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88},
- {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c},
- {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90},
- {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80},
- {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84},
- {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88},
- {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c},
- {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90},
- {0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310},
- {0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314},
- {0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320},
- {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324},
- {0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328},
- {0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c},
- {0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330},
- {0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334},
- {0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321},
- {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325},
- {0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329},
- {0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d},
- {0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331},
- {0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335},
- {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322},
- {0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326},
- {0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a},
- {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e},
- {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332},
- {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336},
- {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323},
- {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327},
- {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b},
- {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f},
- {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333},
- {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337},
- {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343},
- {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347},
- {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b},
- {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f},
- {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353},
- {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357},
- {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
- {0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a},
- {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a},
+static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290},
+ {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300},
+ {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304},
+ {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308},
+ {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c},
+ {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+ {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+ {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+ {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+ {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+ {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+ {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+ {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+ {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+ {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+ {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+ {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+ {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+ {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+ {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+ {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+ {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+ {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+ {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+ {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+ {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+ {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+ {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+ {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+ {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+ {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+ {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+ {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+ {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+ {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+ {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+ {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+ {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+ {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+ {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+ {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+ {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+ {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+ {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+ {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+ {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+ {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+ {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+ {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80},
+ {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84},
+ {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88},
+ {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c},
+ {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90},
+ {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80},
+ {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84},
+ {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88},
+ {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c},
+ {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90},
+ {0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310},
+ {0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314},
+ {0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320},
+ {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324},
+ {0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328},
+ {0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c},
+ {0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330},
+ {0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334},
+ {0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321},
+ {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325},
+ {0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329},
+ {0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d},
+ {0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331},
+ {0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335},
+ {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322},
+ {0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326},
+ {0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a},
+ {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e},
+ {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332},
+ {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336},
+ {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323},
+ {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327},
+ {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b},
+ {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f},
+ {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333},
+ {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337},
+ {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343},
+ {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347},
+ {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b},
+ {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f},
+ {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353},
+ {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357},
+ {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b},
+ {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b},
+ {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b},
+ {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b},
+ {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b},
+ {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b},
+ {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b},
+ {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b},
+ {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b},
+ {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b},
+ {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b},
+ {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b},
+ {0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+ {0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a},
+ {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a},
};
-static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
- {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652},
- {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce},
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002},
- {0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008},
- {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010},
- {0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012},
- {0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014},
- {0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a},
- {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211},
- {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213},
- {0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411},
- {0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413},
- {0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811},
- {0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813},
- {0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14},
- {0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50},
- {0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c},
- {0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a},
- {0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92},
- {0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2},
- {0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5},
- {0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54},
- {0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5},
- {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
- {0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
- {0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
- {0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
- {0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
- {0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
- {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
+static const u32 ar9280Modes_high_power_tx_gain_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652},
+ {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce},
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002},
+ {0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008},
+ {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010},
+ {0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012},
+ {0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014},
+ {0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a},
+ {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211},
+ {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213},
+ {0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411},
+ {0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413},
+ {0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811},
+ {0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813},
+ {0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14},
+ {0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50},
+ {0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c},
+ {0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a},
+ {0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92},
+ {0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2},
+ {0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5},
+ {0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54},
+ {0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5},
+ {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
+ {0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
+ {0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
+ {0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
+ {0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
+ {0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
+ {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
};
-static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
- {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652},
- {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce},
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002},
- {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009},
- {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b},
- {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012},
- {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048},
- {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a},
- {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211},
- {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213},
- {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b},
- {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412},
- {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414},
- {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a},
- {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649},
- {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b},
- {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49},
- {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48},
- {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a},
- {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88},
- {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a},
- {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9},
- {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42},
- {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
- {0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
- {0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
- {0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
- {0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
- {0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
- {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
+static const u32 ar9280Modes_original_tx_gain_9280_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652},
+ {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce},
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002},
+ {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009},
+ {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b},
+ {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012},
+ {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048},
+ {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a},
+ {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211},
+ {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213},
+ {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b},
+ {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412},
+ {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414},
+ {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a},
+ {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649},
+ {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b},
+ {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49},
+ {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48},
+ {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a},
+ {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88},
+ {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a},
+ {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9},
+ {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42},
+ {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
+ {0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
+ {0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
+ {0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
+ {0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
+ {0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
+ {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
};
static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
@@ -947,309 +953,310 @@ static const u32 ar9285PciePhy_clkreq_off_L1_9285[][2] = {
{0x00004044, 0x00000000},
};
-static const u32 ar9285Modes_9285_1_2[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
- {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0},
- {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
- {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
- {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
- {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
- {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18},
- {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
- {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010},
- {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
- {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
- {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
- {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
- {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
- {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
- {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
- {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
- {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
- {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
- {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
- {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
- {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
- {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
- {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
- {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
- {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
- {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
- {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
- {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
- {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
- {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
- {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
- {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
- {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
- {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
- {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
- {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
- {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
- {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
- {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
- {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
- {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
- {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
- {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
- {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
- {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
- {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
- {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
- {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
- {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
- {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
- {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
- {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
- {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
- {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
- {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
- {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
- {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
- {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
- {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
- {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
- {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
- {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
- {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
- {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
- {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
- {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
- {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
- {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
- {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
- {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
- {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
- {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
- {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
- {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
- {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
- {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
- {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
- {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
- {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
- {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
- {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
- {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
- {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
- {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
- {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
- {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
- {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
- {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
- {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
- {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
- {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
- {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
- {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
- {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
- {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
- {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
- {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
- {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
- {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
- {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
- {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
- {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
- {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
- {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
- {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
- {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
- {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
- {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
- {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
- {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
- {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
- {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
- {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
- {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
- {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
- {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
- {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
- {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
- {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
- {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
- {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
- {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
- {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
- {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
- {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
- {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
- {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
- {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
- {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
- {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
- {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
- {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
- {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
- {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
- {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
- {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
- {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
- {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
- {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
- {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
- {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
- {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
- {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
- {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
- {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
- {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
- {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
- {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
- {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
- {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
- {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
- {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
- {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
- {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
- {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
- {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
- {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
- {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
- {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
- {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
- {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
- {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
- {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
- {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
- {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
- {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
- {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
- {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
- {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
- {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
- {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
- {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
- {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
- {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
- {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
- {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
- {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
- {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
- {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
- {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
- {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
- {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
- {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
- {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
- {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
- {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
- {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
- {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
- {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
- {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
- {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
- {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
- {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
- {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
- {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000},
- {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+static const u32 ar9285Modes_9285_1_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+ {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+ {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+ {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20},
+ {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+ {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020},
+ {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
+ {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+ {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+ {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+ {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+ {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+ {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+ {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+ {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+ {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+ {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+ {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+ {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+ {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+ {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+ {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+ {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+ {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+ {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+ {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+ {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+ {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+ {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+ {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+ {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+ {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+ {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+ {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+ {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+ {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+ {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+ {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+ {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+ {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+ {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+ {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+ {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+ {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+ {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+ {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+ {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+ {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+ {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+ {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+ {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+ {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+ {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+ {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+ {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+ {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+ {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+ {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+ {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+ {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+ {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+ {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+ {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+ {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+ {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+ {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+ {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+ {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+ {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+ {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+ {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+ {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+ {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+ {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+ {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+ {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+ {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+ {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+ {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+ {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+ {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+ {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+ {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+ {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+ {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+ {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+ {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+ {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+ {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+ {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+ {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+ {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+ {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+ {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+ {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+ {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+ {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+ {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+ {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+ {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+ {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+ {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+ {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+ {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+ {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+ {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+ {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+ {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+ {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+ {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+ {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+ {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+ {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+ {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+ {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+ {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+ {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+ {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+ {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+ {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+ {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+ {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+ {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+ {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+ {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+ {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+ {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+ {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+ {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+ {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+ {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+ {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+ {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+ {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+ {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+ {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+ {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+ {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+ {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+ {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+ {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+ {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+ {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+ {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+ {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+ {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+ {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+ {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+ {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+ {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+ {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+ {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+ {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+ {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+ {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+ {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+ {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+ {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+ {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+ {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+ {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+ {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+ {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+ {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+ {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+ {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+ {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+ {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+ {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+ {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+ {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+ {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+ {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+ {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+ {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+ {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+ {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+ {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+ {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+ {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+ {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+ {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+ {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+ {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+ {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+ {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
+ {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+ {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
};
static const u32 ar9285Common_9285_1_2[][2] = {
@@ -1572,164 +1579,168 @@ static const u32 ar9285Common_9285_1_2[][2] = {
{0x00007870, 0x10142c00},
};
-static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
- {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
- {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
- {0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803},
- {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
- {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
- {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
- {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652},
- {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
- {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
- {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805},
+ {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
+ {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
+ {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
+ {0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803},
+ {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
+ {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
+ {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
+ {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652},
+ {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
+ {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+ {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
};
-static const u32 ar9285Modes_original_tx_gain_9285_1_2[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
- {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
- {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
- {0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801},
- {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
- {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
- {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
- {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
- {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652},
- {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
- {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
- {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+static const u32 ar9285Modes_original_tx_gain_9285_1_2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+ {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718},
+ {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a},
+ {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f},
+ {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
+ {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
+ {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
+ {0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801},
+ {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
+ {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
+ {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+ {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+ {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652},
+ {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
+ {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+ {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
};
-static const u32 ar9285Modes_XE2_0_normal_power[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
- {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b},
- {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae},
- {0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441},
- {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
- {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
- {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
- {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
- {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652},
- {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
- {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
- {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
- {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+static const u32 ar9285Modes_XE2_0_normal_power[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+ {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718},
+ {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a},
+ {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f},
+ {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
+ {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b},
+ {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
+ {0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441},
+ {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
+ {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
+ {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+ {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+ {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652},
+ {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
+ {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+ {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+ {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
};
-static const u32 ar9285Modes_XE2_0_high_power[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000},
- {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
- {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b},
- {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
- {0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443},
- {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
- {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
- {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
- {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652},
- {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
- {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
- {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+static const u32 ar9285Modes_XE2_0_high_power[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805},
+ {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
+ {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b},
+ {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
+ {0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443},
+ {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
+ {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
+ {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
+ {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652},
+ {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
+ {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+ {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
};
static const u32 ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {
@@ -1760,50 +1771,51 @@ static const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
{0x00004044, 0x00000000},
};
-static const u32 ar9287Modes_9287_1_1[][6] = {
- {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
- {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a},
- {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880},
- {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e},
- {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001},
- {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007},
- {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e},
- {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0},
- {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2},
- {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e},
- {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18},
- {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881},
- {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
- {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010},
- {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010},
- {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010},
- {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210},
- {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce},
- {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c},
- {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
- {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444},
- {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000},
- {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
- {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar9287Modes_9287_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440},
+ {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300},
+ {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200},
+ {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001},
+ {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0},
+ {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2},
+ {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e},
+ {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20},
+ {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881},
+ {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898},
+ {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b},
+ {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d},
+ {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010},
+ {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+ {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+ {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210},
+ {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce},
+ {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c},
+ {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4},
+ {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444},
+ {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
+ {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
static const u32 ar9287Common_9287_1_1[][2] = {
@@ -2189,313 +2201,315 @@ static const u32 ar9287Common_japan_2484_cck_fir_coeff_9287_1_1[][2] = {
{0x0000a1fc, 0xca9228ee},
};
-static const u32 ar9287Modes_tx_gain_9287_1_1[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002},
- {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004},
- {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a},
- {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c},
- {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b},
- {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a},
- {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a},
- {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a},
- {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a},
- {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a},
- {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a},
- {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a},
- {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c},
- {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc},
- {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4},
- {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc},
- {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede},
- {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e},
- {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e},
- {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e},
- {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062},
- {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064},
- {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4},
- {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa},
- {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac},
- {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4},
- {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4},
- {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134},
- {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174},
- {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c},
- {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e},
- {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be},
- {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
- {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000},
+static const u32 ar9287Modes_tx_gain_9287_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b},
+ {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a},
+ {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a},
+ {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a},
+ {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c},
+ {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc},
+ {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4},
+ {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc},
+ {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede},
+ {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e},
+ {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e},
+ {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e},
+ {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062},
+ {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064},
+ {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4},
+ {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa},
+ {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac},
+ {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4},
+ {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4},
+ {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134},
+ {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174},
+ {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c},
+ {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e},
+ {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be},
+ {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+ {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000},
};
-static const u32 ar9287Modes_rx_gain_9287_1_1[][6] = {
- {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120},
- {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124},
- {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128},
- {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c},
- {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130},
- {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194},
- {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198},
- {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c},
- {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210},
- {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284},
- {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288},
- {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c},
- {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290},
- {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294},
- {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0},
- {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4},
- {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8},
- {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac},
- {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0},
- {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4},
- {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8},
- {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4},
- {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708},
- {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c},
- {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710},
- {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04},
- {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08},
- {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c},
- {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10},
- {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14},
- {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18},
- {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c},
- {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90},
- {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94},
- {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98},
- {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4},
- {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8},
- {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04},
- {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08},
- {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c},
- {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10},
- {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14},
- {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18},
- {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c},
- {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90},
- {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18},
- {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24},
- {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28},
- {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314},
- {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318},
- {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c},
- {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390},
- {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394},
- {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398},
- {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4},
- {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8},
- {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac},
- {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0},
- {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380},
- {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384},
- {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388},
- {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710},
- {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714},
- {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718},
- {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10},
- {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14},
- {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18},
- {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c},
- {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90},
- {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94},
- {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c},
- {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90},
- {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94},
- {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0},
- {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4},
- {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8},
- {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac},
- {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0},
- {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4},
- {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1},
- {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5},
- {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9},
- {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad},
- {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1},
- {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5},
- {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9},
- {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5},
- {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9},
- {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd},
- {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1},
- {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5},
- {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2},
- {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6},
- {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca},
- {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce},
- {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2},
- {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6},
- {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda},
- {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7},
- {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb},
- {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf},
- {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3},
- {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7},
- {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120},
- {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124},
- {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128},
- {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c},
- {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130},
- {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194},
- {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198},
- {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c},
- {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210},
- {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284},
- {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288},
- {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c},
- {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290},
- {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294},
- {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0},
- {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4},
- {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8},
- {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac},
- {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0},
- {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4},
- {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8},
- {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4},
- {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708},
- {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c},
- {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710},
- {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04},
- {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08},
- {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c},
- {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10},
- {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14},
- {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18},
- {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c},
- {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90},
- {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94},
- {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98},
- {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4},
- {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8},
- {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04},
- {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08},
- {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c},
- {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10},
- {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14},
- {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18},
- {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c},
- {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90},
- {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18},
- {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24},
- {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28},
- {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314},
- {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318},
- {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c},
- {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390},
- {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394},
- {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398},
- {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4},
- {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8},
- {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac},
- {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0},
- {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380},
- {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384},
- {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388},
- {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710},
- {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714},
- {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718},
- {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10},
- {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14},
- {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18},
- {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c},
- {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90},
- {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94},
- {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c},
- {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90},
- {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94},
- {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0},
- {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4},
- {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8},
- {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac},
- {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0},
- {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4},
- {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1},
- {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5},
- {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9},
- {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad},
- {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1},
- {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5},
- {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9},
- {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5},
- {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9},
- {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd},
- {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1},
- {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5},
- {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2},
- {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6},
- {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca},
- {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce},
- {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2},
- {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6},
- {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda},
- {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7},
- {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb},
- {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf},
- {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3},
- {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7},
- {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
- {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067},
- {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067},
+static const u32 ar9287Modes_rx_gain_9287_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120},
+ {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124},
+ {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128},
+ {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c},
+ {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130},
+ {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194},
+ {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198},
+ {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c},
+ {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210},
+ {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284},
+ {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288},
+ {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c},
+ {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290},
+ {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294},
+ {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0},
+ {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4},
+ {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8},
+ {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac},
+ {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0},
+ {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4},
+ {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8},
+ {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4},
+ {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708},
+ {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c},
+ {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710},
+ {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04},
+ {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08},
+ {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c},
+ {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10},
+ {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14},
+ {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18},
+ {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c},
+ {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90},
+ {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94},
+ {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98},
+ {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4},
+ {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8},
+ {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04},
+ {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08},
+ {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c},
+ {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10},
+ {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14},
+ {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18},
+ {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c},
+ {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90},
+ {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18},
+ {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24},
+ {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28},
+ {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314},
+ {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318},
+ {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c},
+ {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390},
+ {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394},
+ {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398},
+ {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4},
+ {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8},
+ {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac},
+ {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0},
+ {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380},
+ {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384},
+ {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388},
+ {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710},
+ {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714},
+ {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718},
+ {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10},
+ {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14},
+ {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18},
+ {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c},
+ {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90},
+ {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94},
+ {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c},
+ {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90},
+ {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94},
+ {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0},
+ {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4},
+ {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8},
+ {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac},
+ {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0},
+ {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4},
+ {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1},
+ {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5},
+ {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9},
+ {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad},
+ {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1},
+ {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5},
+ {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9},
+ {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5},
+ {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9},
+ {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd},
+ {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1},
+ {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5},
+ {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2},
+ {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6},
+ {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca},
+ {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce},
+ {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2},
+ {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6},
+ {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda},
+ {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7},
+ {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb},
+ {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf},
+ {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3},
+ {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7},
+ {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120},
+ {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124},
+ {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128},
+ {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c},
+ {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130},
+ {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194},
+ {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198},
+ {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c},
+ {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210},
+ {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284},
+ {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288},
+ {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c},
+ {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290},
+ {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294},
+ {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0},
+ {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4},
+ {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8},
+ {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac},
+ {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0},
+ {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4},
+ {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8},
+ {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4},
+ {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708},
+ {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c},
+ {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710},
+ {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04},
+ {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08},
+ {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c},
+ {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10},
+ {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14},
+ {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18},
+ {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c},
+ {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90},
+ {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94},
+ {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98},
+ {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4},
+ {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8},
+ {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04},
+ {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08},
+ {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c},
+ {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10},
+ {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14},
+ {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18},
+ {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c},
+ {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90},
+ {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18},
+ {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24},
+ {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28},
+ {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314},
+ {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318},
+ {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c},
+ {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390},
+ {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394},
+ {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398},
+ {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4},
+ {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8},
+ {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac},
+ {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0},
+ {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380},
+ {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384},
+ {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388},
+ {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710},
+ {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714},
+ {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718},
+ {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10},
+ {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14},
+ {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18},
+ {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c},
+ {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90},
+ {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94},
+ {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c},
+ {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90},
+ {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94},
+ {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0},
+ {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4},
+ {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8},
+ {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac},
+ {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0},
+ {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4},
+ {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1},
+ {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5},
+ {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9},
+ {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad},
+ {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1},
+ {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5},
+ {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9},
+ {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5},
+ {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9},
+ {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd},
+ {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1},
+ {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5},
+ {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2},
+ {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6},
+ {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca},
+ {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce},
+ {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2},
+ {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6},
+ {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda},
+ {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7},
+ {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb},
+ {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf},
+ {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3},
+ {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7},
+ {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+ {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067},
+ {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067},
};
static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = {
@@ -2526,310 +2540,311 @@ static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = {
{0x00004044, 0x00000000},
};
-static const u32 ar9271Modes_9271[][6] = {
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
- {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
- {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
- {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
- {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
- {0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001},
- {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
- {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
- {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0},
- {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
- {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
- {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
- {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
- {0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
- {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
- {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
- {0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310, 0x30002310},
- {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
- {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
- {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
- {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010},
- {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
- {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
- {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
- {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
- {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
- {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
- {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
- {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
- {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
- {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
- {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
- {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
- {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
- {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
- {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
- {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
- {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
- {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
- {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
- {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
- {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
- {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
- {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
- {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
- {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
- {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
- {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
- {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
- {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
- {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
- {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
- {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
- {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
- {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
- {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
- {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
- {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
- {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
- {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
- {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
- {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
- {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
- {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
- {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
- {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
- {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
- {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
- {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
- {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
- {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
- {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
- {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
- {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
- {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
- {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
- {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
- {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
- {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
- {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
- {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
- {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
- {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
- {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
- {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
- {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
- {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
- {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
- {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
- {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
- {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
- {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
- {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
- {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
- {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
- {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
- {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
- {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
- {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
- {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
- {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
- {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
- {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
- {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
- {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
- {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
- {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
- {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
- {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
- {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
- {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
- {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
- {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
- {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
- {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
- {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
- {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
- {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
- {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
- {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
- {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
- {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
- {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
- {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
- {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
- {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
- {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
- {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
- {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
- {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
- {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
- {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
- {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
- {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
- {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
- {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
- {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
- {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
- {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
- {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
- {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
- {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
- {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
- {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
- {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
- {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
- {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
- {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
- {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
- {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
- {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
- {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
- {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
- {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
- {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
- {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
- {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
- {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
- {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
- {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
- {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
- {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
- {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
- {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
- {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
- {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
- {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
- {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
- {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
- {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
- {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
- {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
- {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
- {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
- {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
- {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
- {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
- {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
- {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
- {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
- {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
- {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
- {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
- {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
- {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
- {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
- {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
- {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
- {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
- {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
- {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
- {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
- {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
- {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
- {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
- {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
- {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
- {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
- {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
- {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
- {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
- {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
- {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
- {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
- {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
- {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
- {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
- {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
- {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
- {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
- {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
- {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000},
- {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+static const u32 ar9271Modes_9271[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+ {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+ {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001},
+ {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+ {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
+ {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620},
+ {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+ {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+ {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+ {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+ {0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
+ {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310},
+ {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+ {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020},
+ {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
+ {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+ {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
+ {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+ {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+ {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+ {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+ {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+ {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+ {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+ {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+ {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+ {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+ {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+ {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+ {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+ {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+ {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+ {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+ {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+ {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+ {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+ {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+ {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+ {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+ {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+ {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+ {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+ {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+ {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+ {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+ {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+ {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+ {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+ {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+ {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+ {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+ {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+ {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+ {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+ {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+ {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+ {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+ {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+ {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+ {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+ {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+ {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+ {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+ {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+ {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+ {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+ {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+ {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+ {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+ {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+ {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+ {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+ {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+ {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+ {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+ {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+ {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+ {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+ {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+ {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+ {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+ {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+ {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+ {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+ {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+ {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+ {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+ {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+ {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+ {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+ {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+ {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+ {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+ {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+ {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+ {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+ {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+ {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+ {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+ {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+ {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+ {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+ {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+ {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+ {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+ {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+ {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+ {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+ {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+ {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+ {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+ {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+ {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+ {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+ {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+ {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+ {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+ {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+ {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+ {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+ {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+ {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+ {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+ {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+ {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+ {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+ {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+ {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+ {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+ {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+ {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+ {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+ {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+ {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+ {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+ {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+ {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+ {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+ {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+ {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+ {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+ {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+ {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+ {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+ {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+ {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+ {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+ {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+ {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+ {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+ {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+ {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+ {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+ {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+ {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+ {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+ {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+ {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+ {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+ {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+ {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+ {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+ {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+ {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+ {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+ {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+ {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+ {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+ {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+ {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+ {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+ {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+ {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+ {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+ {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+ {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+ {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+ {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+ {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+ {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+ {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+ {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+ {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+ {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+ {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+ {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+ {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+ {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+ {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+ {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+ {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+ {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+ {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+ {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+ {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+ {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+ {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+ {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+ {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
+ {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+ {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+ {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+ {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000},
+ {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
};
static const u32 ar9271Common_9271[][2] = {
@@ -3175,91 +3190,95 @@ static const u32 ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = {
{0x0000a1fc, 0xca9228ee},
};
-static const u32 ar9271Modes_9271_1_0_only[][6] = {
- {0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311},
- {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+static const u32 ar9271Modes_9271_1_0_only[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311},
+ {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
};
-static const u32 ar9271Modes_9271_ANI_reg[][6] = {
- {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
- {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
- {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881, 0x06903881},
- {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8},
- {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
- {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+static const u32 ar9271Modes_9271_ANI_reg[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+ {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+ {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881},
+ {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8},
+ {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+ {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
};
-static const u32 ar9271Modes_normal_power_tx_gain_9271[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000},
- {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029, 0x00000029},
- {0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff},
- {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
- {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
- {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652},
- {0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
- {0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd},
- {0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
- {0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
- {0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
- {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
+static const u32 ar9271Modes_normal_power_tx_gain_9271[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610},
+ {0x0000a314, 0x00000000, 0x00000000, 0x00024650, 0x00024650},
+ {0x0000a318, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x000316d2, 0x000316d2},
+ {0x0000a320, 0x00000000, 0x00000000, 0x00039758, 0x00039758},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759},
+ {0x0000a328, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e},
+ {0x0000a334, 0x000368de, 0x000368de, 0x0004979f, 0x0004979f},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0004d7df, 0x0004d7df},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029},
+ {0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff},
+ {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+ {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+ {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21c652, 0x0a21c652},
+ {0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+ {0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd},
+ {0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+ {0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
+ {0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+ {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
};
-static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = {
- {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000},
- {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000},
- {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000},
- {0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240, 0x00000000},
- {0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241, 0x00000000},
- {0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600, 0x00000000},
- {0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800, 0x00000000},
- {0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802, 0x00000000},
- {0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805, 0x00000000},
- {0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41, 0x00000000},
- {0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00, 0x00000000},
- {0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40, 0x00000000},
- {0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80, 0x00000000},
- {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000},
- {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
- {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
- {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
- {0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b},
- {0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff},
- {0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6},
- {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
- {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652, 0x0a22a652},
- {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
- {0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063},
- {0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
- {0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
- {0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
- {0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
+static const u32 ar9271Modes_high_power_tx_gain_9271[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000},
+ {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200},
+ {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201},
+ {0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240},
+ {0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241},
+ {0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600},
+ {0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800},
+ {0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802},
+ {0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805},
+ {0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41},
+ {0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00},
+ {0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40},
+ {0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80},
+ {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de},
+ {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+ {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+ {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+ {0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b},
+ {0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff},
+ {0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba},
+ {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+ {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652},
+ {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+ {0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063},
+ {0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
+ {0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
+ {0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
+ {0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
};
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 45b262fe2c25..f7d8e516a2a9 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -170,33 +170,104 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
return true;
}
-static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
- bool is_firstseg, bool is_lastseg,
- const void *ds0, dma_addr_t buf_addr,
- unsigned int qcu)
+static void
+ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
{
struct ar5416_desc *ads = AR5416DESC(ds);
+ u32 ctl1, ctl6;
- ads->ds_data = buf_addr;
-
- if (is_firstseg) {
- ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore);
- } else if (is_lastseg) {
- ads->ds_ctl0 = 0;
- ads->ds_ctl1 = seglen;
- ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
- ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
- } else {
- ads->ds_ctl0 = 0;
- ads->ds_ctl1 = seglen | AR_TxMore;
- ads->ds_ctl2 = 0;
- ads->ds_ctl3 = 0;
- }
ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+
+ ACCESS_ONCE(ads->ds_link) = i->link;
+ ACCESS_ONCE(ads->ds_data) = i->buf_addr[0];
+
+ ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore);
+ ctl6 = SM(i->keytype, AR_EncrType);
+
+ if (AR_SREV_9285(ah)) {
+ ads->ds_ctl8 = 0;
+ ads->ds_ctl9 = 0;
+ ads->ds_ctl10 = 0;
+ ads->ds_ctl11 = 0;
+ }
+
+ if ((i->is_first || i->is_last) &&
+ i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) {
+ ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0)
+ | set11nTries(i->rates, 1)
+ | set11nTries(i->rates, 2)
+ | set11nTries(i->rates, 3)
+ | (i->dur_update ? AR_DurUpdateEna : 0)
+ | SM(0, AR_BurstDur);
+
+ ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0)
+ | set11nRate(i->rates, 1)
+ | set11nRate(i->rates, 2)
+ | set11nRate(i->rates, 3);
+ } else {
+ ACCESS_ONCE(ads->ds_ctl2) = 0;
+ ACCESS_ONCE(ads->ds_ctl3) = 0;
+ }
+
+ if (!i->is_first) {
+ ACCESS_ONCE(ads->ds_ctl0) = 0;
+ ACCESS_ONCE(ads->ds_ctl1) = ctl1;
+ ACCESS_ONCE(ads->ds_ctl6) = ctl6;
+ return;
+ }
+
+ ctl1 |= (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0)
+ | SM(i->type, AR_FrameType)
+ | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+ | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+ | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+ switch (i->aggr) {
+ case AGGR_BUF_FIRST:
+ ctl6 |= SM(i->aggr_len, AR_AggrLen);
+ /* fall through */
+ case AGGR_BUF_MIDDLE:
+ ctl1 |= AR_IsAggr | AR_MoreAggr;
+ ctl6 |= SM(i->ndelim, AR_PadDelim);
+ break;
+ case AGGR_BUF_LAST:
+ ctl1 |= AR_IsAggr;
+ break;
+ case AGGR_BUF_NONE:
+ break;
+ }
+
+ ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
+ | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+ | SM(i->txpower, AR_XmitPower)
+ | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+ | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+ | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+ | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+ | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
+ (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
+
+ ACCESS_ONCE(ads->ds_ctl1) = ctl1;
+ ACCESS_ONCE(ads->ds_ctl6) = ctl6;
+
+ if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST)
+ return;
+
+ ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0)
+ | set11nPktDurRTSCTS(i->rates, 1);
+
+ ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2)
+ | set11nPktDurRTSCTS(i->rates, 3);
+
+ ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0)
+ | set11nRateFlags(i->rates, 1)
+ | set11nRateFlags(i->rates, 2)
+ | set11nRateFlags(i->rates, 3)
+ | SM(i->rtscts_rate, AR_RTSCTSRate);
}
static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
@@ -271,145 +342,6 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
return 0;
}
-static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
- u32 pktLen, enum ath9k_pkt_type type,
- u32 txPower, u32 keyIx,
- enum ath9k_key_type keyType, u32 flags)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- if (txPower > 63)
- txPower = 63;
-
- ads->ds_ctl0 = (pktLen & AR_FrameLen)
- | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- | SM(txPower, AR_XmitPower)
- | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
- | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
- | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
-
- ads->ds_ctl1 =
- (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
- | SM(type, AR_FrameType)
- | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
- | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
- | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
-
- ads->ds_ctl6 = SM(keyType, AR_EncrType);
-
- if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
- ads->ds_ctl8 = 0;
- ads->ds_ctl9 = 0;
- ads->ds_ctl10 = 0;
- ads->ds_ctl11 = 0;
- }
-}
-
-static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- if (val)
- ads->ds_ctl0 |= AR_ClrDestMask;
- else
- ads->ds_ctl0 &= ~AR_ClrDestMask;
-}
-
-static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
- void *lastds,
- u32 durUpdateEn, u32 rtsctsRate,
- u32 rtsctsDuration,
- struct ath9k_11n_rate_series series[],
- u32 nseries, u32 flags)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
- struct ar5416_desc *last_ads = AR5416DESC(lastds);
- u32 ds_ctl0;
-
- if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
- ds_ctl0 = ads->ds_ctl0;
-
- if (flags & ATH9K_TXDESC_RTSENA) {
- ds_ctl0 &= ~AR_CTSEnable;
- ds_ctl0 |= AR_RTSEnable;
- } else {
- ds_ctl0 &= ~AR_RTSEnable;
- ds_ctl0 |= AR_CTSEnable;
- }
-
- ads->ds_ctl0 = ds_ctl0;
- } else {
- ads->ds_ctl0 =
- (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
- }
-
- ads->ds_ctl2 = set11nTries(series, 0)
- | set11nTries(series, 1)
- | set11nTries(series, 2)
- | set11nTries(series, 3)
- | (durUpdateEn ? AR_DurUpdateEna : 0)
- | SM(0, AR_BurstDur);
-
- ads->ds_ctl3 = set11nRate(series, 0)
- | set11nRate(series, 1)
- | set11nRate(series, 2)
- | set11nRate(series, 3);
-
- ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
- | set11nPktDurRTSCTS(series, 1);
-
- ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
- | set11nPktDurRTSCTS(series, 3);
-
- ads->ds_ctl7 = set11nRateFlags(series, 0)
- | set11nRateFlags(series, 1)
- | set11nRateFlags(series, 2)
- | set11nRateFlags(series, 3)
- | SM(rtsctsRate, AR_RTSCTSRate);
- last_ads->ds_ctl2 = ads->ds_ctl2;
- last_ads->ds_ctl3 = ads->ds_ctl3;
-}
-
-static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
- u32 aggrLen)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
- ads->ds_ctl6 &= ~AR_AggrLen;
- ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
-}
-
-static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
- u32 numDelims)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
- unsigned int ctl6;
-
- ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
-
- ctl6 = ads->ds_ctl6;
- ctl6 &= ~AR_PadDelim;
- ctl6 |= SM(numDelims, AR_PadDelim);
- ads->ds_ctl6 = ctl6;
-}
-
-static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- ads->ds_ctl1 |= AR_IsAggr;
- ads->ds_ctl1 &= ~AR_MoreAggr;
- ads->ds_ctl6 &= ~AR_PadDelim;
-}
-
-static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
-}
-
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags)
{
@@ -433,13 +365,6 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
ops->rx_enable = ar9002_hw_rx_enable;
ops->set_desc_link = ar9002_hw_set_desc_link;
ops->get_isr = ar9002_hw_get_isr;
- ops->fill_txdesc = ar9002_hw_fill_txdesc;
+ ops->set_txdesc = ar9002_set_txdesc;
ops->proc_txdesc = ar9002_hw_proc_txdesc;
- ops->set11n_txdesc = ar9002_hw_set11n_txdesc;
- ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario;
- ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first;
- ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle;
- ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
- ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
- ops->set_clrdmask = ar9002_hw_set_clrdmask;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
index 3e69c631ebb4..026f9de15d15 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
@@ -24,11 +24,11 @@ static const u32 ar9300_2p2_radio_postamble[][5] = {
{0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31},
{0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
{0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
- {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0001610c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
{0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
- {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0001650c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
{0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
- {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0001690c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
{0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
};
@@ -190,7 +190,7 @@ static const u32 ar9300_2p2_radio_core[][2] = {
{0x00016288, 0x05a20408},
{0x0001628c, 0x00038c07},
{0x00016290, 0x00000004},
- {0x00016294, 0x458aa14f},
+ {0x00016294, 0x458a214f},
{0x00016380, 0x00000000},
{0x00016384, 0x00000000},
{0x00016388, 0x00800700},
@@ -636,7 +636,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
- {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0},
+ {0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0},
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
{0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f},
{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
@@ -835,108 +835,108 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
- {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
- {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
- {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
- {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
- {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
- {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
- {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
- {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
- {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
- {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
- {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
- {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
- {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
- {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
- {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
- {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
- {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
- {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
- {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
- {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
- {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
- {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
- {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
- {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
- {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
- {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
- {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
- {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
- {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
- {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
- {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
- {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
- {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
- {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
- {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
- {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
- {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
- {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
- {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
- {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
- {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
- {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
- {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
- {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
- {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
- {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
- {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
- {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
- {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
- {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
- {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
- {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
+ {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
+ {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
+ {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
+ {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
+ {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
+ {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
+ {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
+ {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
+ {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
+ {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
+ {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
+ {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
+ {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
+ {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
+ {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
+ {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
+ {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
+ {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
+ {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
+ {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
+ {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
+ {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
+ {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
+ {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
+ {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83},
+ {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84},
+ {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
+ {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
+ {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
+ {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
+ {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+ {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+ {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
- {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
- {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
- {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
- {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
- {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
- {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
- {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
- {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
- {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
- {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+ {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
+ {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+ {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+ {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+ {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
- {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
- {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+ {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+ {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
- {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
- {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
- {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
- {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
- {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
- {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
- {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
- {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+ {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+ {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
};
static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index f48051c50092..16851cb109a6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -17,8 +17,9 @@
#include "hw.h"
#include "hw-ops.h"
#include "ar9003_phy.h"
+#include "ar9003_rtt.h"
-#define MAX_MEASUREMENT 8
+#define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
#define MAX_MAG_DELTA 11
#define MAX_PHS_DELTA 10
@@ -615,11 +616,10 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
{
int mp_max = -64, max_idx = 0;
int mp_min = 63, min_idx = 0;
- int mp_avg = 0, i, outlier_idx = 0;
+ int mp_avg = 0, i, outlier_idx = 0, mp_count = 0;
/* find min/max mismatch across all calibrated gains */
for (i = 0; i < nmeasurement; i++) {
- mp_avg += mp_coeff[i];
if (mp_coeff[i] > mp_max) {
mp_max = mp_coeff[i];
max_idx = i;
@@ -632,10 +632,20 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
/* find average (exclude max abs value) */
for (i = 0; i < nmeasurement; i++) {
if ((abs(mp_coeff[i]) < abs(mp_max)) ||
- (abs(mp_coeff[i]) < abs(mp_min)))
+ (abs(mp_coeff[i]) < abs(mp_min))) {
mp_avg += mp_coeff[i];
+ mp_count++;
+ }
}
- mp_avg /= (nmeasurement - 1);
+
+ /*
+ * finding mean magnitude/phase if possible, otherwise
+ * just use the last value as the mean
+ */
+ if (mp_count)
+ mp_avg /= mp_count;
+ else
+ mp_avg = mp_coeff[nmeasurement - 1];
/* detect outlier */
if (abs(mp_max - mp_min) > max_delta) {
@@ -643,16 +653,19 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
outlier_idx = max_idx;
else
outlier_idx = min_idx;
+
+ mp_coeff[outlier_idx] = mp_avg;
}
- mp_coeff[outlier_idx] = mp_avg;
}
static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
u8 num_chains,
- struct coeff *coeff)
+ struct coeff *coeff,
+ bool is_reusable)
{
int i, im, nmeasurement;
u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
@@ -702,7 +715,13 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
coeff->iqc_coeff[0]);
+
+ if (caldata)
+ caldata->tx_corr_coeff[im][i] =
+ coeff->iqc_coeff[0];
}
+ if (caldata)
+ caldata->num_measures[i] = nmeasurement;
}
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
@@ -710,8 +729,10 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
- return;
+ if (caldata)
+ caldata->done_txiqcal_once = is_reusable;
+ return;
}
static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
@@ -738,7 +759,7 @@ static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
return true;
}
-static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
{
struct ath_common *common = ath9k_hw_common(ah);
const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
@@ -827,7 +848,8 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
coeff.phs_coeff[i][im] -= 128;
}
}
- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
+ ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains,
+ &coeff, is_reusable);
return;
@@ -835,23 +857,129 @@ tx_iqcal_fail:
ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
return;
}
+
+static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
+{
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+ u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
+ int i, im;
+
+ memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
+ for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
+ tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
+ AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
+ if (!AR_SREV_9485(ah)) {
+ tx_corr_coeff[i * 2][1] =
+ tx_corr_coeff[(i * 2) + 1][1] =
+ AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
+
+ tx_corr_coeff[i * 2][2] =
+ tx_corr_coeff[(i * 2) + 1][2] =
+ AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
+ }
+ }
+
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->txchainmask & (1 << i)))
+ continue;
+
+ for (im = 0; im < caldata->num_measures[i]; im++) {
+ if ((im % 2) == 0)
+ REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+ AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
+ caldata->tx_corr_coeff[im][i]);
+ else
+ REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+ AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
+ caldata->tx_corr_coeff[im][i]);
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
+ AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
+ AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
+}
+
+static bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ struct ath9k_rtt_hist *hist;
+ u32 *table;
+ int i;
+ bool restore;
+
+ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT) || !ah->caldata)
+ return false;
+
+ hist = &ah->caldata->rtt_hist;
+ ar9003_hw_rtt_enable(ah);
+ ar9003_hw_rtt_set_mask(ah, 0x10);
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->rxchainmask & (1 << i)))
+ continue;
+ table = &hist->table[i][hist->num_readings][0];
+ ar9003_hw_rtt_load_hist(ah, i, table);
+ }
+ restore = ar9003_hw_rtt_force_restore(ah);
+ ar9003_hw_rtt_disable(ah);
+
+ return restore;
+}
+
static bool ar9003_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_hw_capabilities *pCap = &ah->caps;
- int val;
- bool txiqcal_done = false;
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+ bool txiqcal_done = false, txclcal_done = false;
+ bool is_reusable = true, status = true;
+ bool run_rtt_cal = false, run_agc_cal;
+ bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT);
+ u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL |
+ AR_PHY_AGC_CONTROL_FLTR_CAL |
+ AR_PHY_AGC_CONTROL_PKDET_CAL;
+ int i, j;
+ u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0,
+ AR_PHY_CL_TAB_1,
+ AR_PHY_CL_TAB_2 };
+
+ if (rtt) {
+ if (!ar9003_hw_rtt_restore(ah, chan))
+ run_rtt_cal = true;
+
+ ath_dbg(common, ATH_DBG_CALIBRATE, "RTT restore %s\n",
+ run_rtt_cal ? "failed" : "succeed");
+ }
+ run_agc_cal = run_rtt_cal;
- val = REG_READ(ah, AR_ENT_OTP);
- ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
+ if (run_rtt_cal) {
+ ar9003_hw_rtt_enable(ah);
+ ar9003_hw_rtt_set_mask(ah, 0x00);
+ ar9003_hw_rtt_clear_hist(ah);
+ }
- /* Configure rx/tx chains before running AGC/TxiQ cals */
- if (val & AR_ENT_OTP_CHAIN2_DISABLE)
- ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
- else
- ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
- pCap->tx_chainmask);
+ if (rtt && !run_rtt_cal) {
+ agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL);
+ agc_supp_cals &= agc_ctrl;
+ agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL |
+ AR_PHY_AGC_CONTROL_FLTR_CAL |
+ AR_PHY_AGC_CONTROL_PKDET_CAL);
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
+ }
+
+ if (ah->enabled_cals & TX_CL_CAL) {
+ if (caldata && caldata->done_txclcal_once)
+ REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
+ AR_PHY_CL_CAL_ENABLE);
+ else {
+ REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL,
+ AR_PHY_CL_CAL_ENABLE);
+ run_agc_cal = true;
+ }
+ }
+
+ if (!(ah->enabled_cals & TX_IQ_CAL))
+ goto skip_tx_iqcal;
/* Do Tx IQ Calibration */
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
@@ -862,34 +990,98 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
* For AR9485 or later chips, TxIQ cal runs as part of
* AGC calibration
*/
- if (AR_SREV_9485_OR_LATER(ah))
- txiqcal_done = true;
- else {
- txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
- udelay(5);
- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
- }
-
- /* Calibrate the AGC */
- REG_WRITE(ah, AR_PHY_AGC_CONTROL,
- REG_READ(ah, AR_PHY_AGC_CONTROL) |
- AR_PHY_AGC_CONTROL_CAL);
-
- /* Poll for offset calibration complete */
- if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
- 0, AH_WAIT_TIMEOUT)) {
+ if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
+ if (caldata && !caldata->done_txiqcal_once)
+ REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
+ else
+ REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
+ txiqcal_done = run_agc_cal = true;
+ goto skip_tx_iqcal;
+ } else if (caldata && !caldata->done_txiqcal_once)
+ run_agc_cal = true;
+
+ txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+ udelay(5);
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+skip_tx_iqcal:
+ if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
+ /* Calibrate the AGC */
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+ REG_READ(ah, AR_PHY_AGC_CONTROL) |
+ AR_PHY_AGC_CONTROL_CAL);
+
+ /* Poll for offset calibration complete */
+ status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_CAL,
+ 0, AH_WAIT_TIMEOUT);
+ }
+ if (rtt && !run_rtt_cal) {
+ agc_ctrl |= agc_supp_cals;
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
+ }
+
+ if (!status) {
+ if (run_rtt_cal)
+ ar9003_hw_rtt_disable(ah);
+
ath_dbg(common, ATH_DBG_CALIBRATE,
- "offset calibration failed to complete in 1ms; noisy environment?\n");
+ "offset calibration failed to complete in 1ms;"
+ "noisy environment?\n");
return false;
}
if (txiqcal_done)
- ar9003_hw_tx_iq_cal_post_proc(ah);
+ ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
+ else if (caldata && caldata->done_txiqcal_once)
+ ar9003_hw_tx_iq_cal_reload(ah);
+
+#define CL_TAB_ENTRY(reg_base) (reg_base + (4 * j))
+ if (caldata && (ah->enabled_cals & TX_CL_CAL)) {
+ txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) &
+ AR_PHY_AGC_CONTROL_CLC_SUCCESS);
+ if (caldata->done_txclcal_once) {
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->txchainmask & (1 << i)))
+ continue;
+ for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
+ REG_WRITE(ah, CL_TAB_ENTRY(cl_idx[i]),
+ caldata->tx_clcal[i][j]);
+ }
+ } else if (is_reusable && txclcal_done) {
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->txchainmask & (1 << i)))
+ continue;
+ for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
+ caldata->tx_clcal[i][j] =
+ REG_READ(ah,
+ CL_TAB_ENTRY(cl_idx[i]));
+ }
+ caldata->done_txclcal_once = true;
+ }
+ }
+#undef CL_TAB_ENTRY
+
+ if (run_rtt_cal && caldata) {
+ struct ath9k_rtt_hist *hist = &caldata->rtt_hist;
+ if (is_reusable && (hist->num_readings < RTT_HIST_MAX)) {
+ u32 *table;
+
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->rxchainmask & (1 << i)))
+ continue;
+ table = &hist->table[i][hist->num_readings][0];
+ ar9003_hw_rtt_fill_hist(ah, i, table);
+ }
+ }
- /* Revert chainmasks to their original values before NF cal */
- ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+ ar9003_hw_rtt_disable(ah);
+ }
+ ath9k_hw_loadnf(ah, chan);
ath9k_hw_start_nfcal(ah, true);
/* Initialize list pointers */
@@ -916,8 +1108,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
if (ah->cal_list_curr)
ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
- if (ah->caldata)
- ah->caldata->CalValid = 0;
+ if (caldata)
+ caldata->CalValid = 0;
return true;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 1b9400371eaf..3b262ba6b172 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -22,25 +22,6 @@
#define COMP_HDR_LEN 4
#define COMP_CKSUM_LEN 2
-#define AR_CH0_TOP (0x00016288)
-#define AR_CH0_TOP_XPABIASLVL (0x300)
-#define AR_CH0_TOP_XPABIASLVL_S (8)
-
-#define AR_CH0_THERM (0x00016290)
-#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
-#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
-#define AR_CH0_THERM_XPASHORT2GND 0x4
-#define AR_CH0_THERM_XPASHORT2GND_S 2
-
-#define AR_SWITCH_TABLE_COM_ALL (0xffff)
-#define AR_SWITCH_TABLE_COM_ALL_S (0)
-
-#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
-#define AR_SWITCH_TABLE_COM2_ALL_S (0)
-
-#define AR_SWITCH_TABLE_ALL (0xfff)
-#define AR_SWITCH_TABLE_ALL_S (0)
-
#define LE16(x) __constant_cpu_to_le16(x)
#define LE32(x) __constant_cpu_to_le32(x)
@@ -158,7 +139,7 @@ static const struct ar9300_eeprom ar9300_default = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@@ -360,7 +341,7 @@ static const struct ar9300_eeprom ar9300_default = {
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@@ -735,7 +716,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@@ -937,7 +918,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@@ -1313,7 +1294,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.papdRateMaskHt20 = LE32(0x80c080),
.papdRateMaskHt40 = LE32(0x80c080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@@ -1515,7 +1496,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@@ -1891,7 +1872,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@@ -2093,7 +2074,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@@ -2468,7 +2449,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.papdRateMaskHt20 = LE32(0x0c80C080),
.papdRateMaskHt40 = LE32(0x0080C080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@@ -2670,7 +2651,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@@ -3014,8 +2995,6 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
return get_unaligned_be16(eep->macAddr + 4);
case EEP_REG_0:
return le16_to_cpu(pBase->regDmn[0]);
- case EEP_REG_1:
- return le16_to_cpu(pBase->regDmn[1]);
case EEP_OP_CAP:
return pBase->deviceCap;
case EEP_OP_MODE:
@@ -3040,6 +3019,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
return (pBase->miscConfiguration >> 0x3) & 0x1;
case EEP_ANT_DIV_CTL1:
return eep->base_ext1.ant_div_control;
+ case EEP_ANTENNA_GAIN_5G:
+ return eep->modalHeader5G.antennaGain;
+ case EEP_ANTENNA_GAIN_2G:
+ return eep->modalHeader2G.antennaGain;
default:
return 0;
}
@@ -3318,7 +3301,7 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
word = kzalloc(2048, GFP_KERNEL);
if (!word)
- return -1;
+ return -ENOMEM;
memcpy(mptr, &ar9300_default, mdata_size);
@@ -3418,6 +3401,133 @@ static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
return true;
}
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ar9003_dump_modal_eeprom(char *buf, u32 len, u32 size,
+ struct ar9300_modal_eep_header *modal_hdr)
+{
+ PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
+ PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
+ PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2]));
+ PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
+ PR_EEP("Ant. Common Control2", le32_to_cpu(modal_hdr->antCtrlCommon2));
+ PR_EEP("Ant. Gain", modal_hdr->antennaGain);
+ PR_EEP("Switch Settle", modal_hdr->switchSettling);
+ PR_EEP("Chain0 xatten1DB", modal_hdr->xatten1DB[0]);
+ PR_EEP("Chain1 xatten1DB", modal_hdr->xatten1DB[1]);
+ PR_EEP("Chain2 xatten1DB", modal_hdr->xatten1DB[2]);
+ PR_EEP("Chain0 xatten1Margin", modal_hdr->xatten1Margin[0]);
+ PR_EEP("Chain1 xatten1Margin", modal_hdr->xatten1Margin[1]);
+ PR_EEP("Chain2 xatten1Margin", modal_hdr->xatten1Margin[2]);
+ PR_EEP("Temp Slope", modal_hdr->tempSlope);
+ PR_EEP("Volt Slope", modal_hdr->voltSlope);
+ PR_EEP("spur Channels0", modal_hdr->spurChans[0]);
+ PR_EEP("spur Channels1", modal_hdr->spurChans[1]);
+ PR_EEP("spur Channels2", modal_hdr->spurChans[2]);
+ PR_EEP("spur Channels3", modal_hdr->spurChans[3]);
+ PR_EEP("spur Channels4", modal_hdr->spurChans[4]);
+ PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+ PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
+ PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);
+ PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+ PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+ PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+ PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+ PR_EEP("txClip", modal_hdr->txClip);
+ PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+ PR_EEP("Chain0 ob", modal_hdr->ob[0]);
+ PR_EEP("Chain1 ob", modal_hdr->ob[1]);
+ PR_EEP("Chain2 ob", modal_hdr->ob[2]);
+
+ PR_EEP("Chain0 db_stage2", modal_hdr->db_stage2[0]);
+ PR_EEP("Chain1 db_stage2", modal_hdr->db_stage2[1]);
+ PR_EEP("Chain2 db_stage2", modal_hdr->db_stage2[2]);
+ PR_EEP("Chain0 db_stage3", modal_hdr->db_stage3[0]);
+ PR_EEP("Chain1 db_stage3", modal_hdr->db_stage3[1]);
+ PR_EEP("Chain2 db_stage3", modal_hdr->db_stage3[2]);
+ PR_EEP("Chain0 db_stage4", modal_hdr->db_stage4[0]);
+ PR_EEP("Chain1 db_stage4", modal_hdr->db_stage4[1]);
+ PR_EEP("Chain2 db_stage4", modal_hdr->db_stage4[2]);
+
+ return len;
+}
+
+static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ struct ar9300_base_eep_hdr *pBase;
+
+ if (!dump_base_hdr) {
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
+ len += ar9003_dump_modal_eeprom(buf, len, size,
+ &eep->modalHeader2G);
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "5GHz modal Header");
+ len += ar9003_dump_modal_eeprom(buf, len, size,
+ &eep->modalHeader5G);
+ goto out;
+ }
+
+ pBase = &eep->baseEepHeader;
+
+ PR_EEP("EEPROM Version", ah->eeprom.ar9300_eep.eepromVersion);
+ PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
+ PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
+ PR_EEP("TX Mask", (pBase->txrxMask >> 4));
+ PR_EEP("RX Mask", (pBase->txrxMask & 0x0f));
+ PR_EEP("Allow 5GHz", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_11A));
+ PR_EEP("Allow 2GHz", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_11G));
+ PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_N_2G_HT20));
+ PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_N_2G_HT40));
+ PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_N_5G_HT20));
+ PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags.opFlags &
+ AR5416_OPFLAGS_N_5G_HT40));
+ PR_EEP("Big Endian", !!(pBase->opCapFlags.eepMisc & 0x01));
+ PR_EEP("RF Silent", pBase->rfSilent);
+ PR_EEP("BT option", pBase->blueToothOptions);
+ PR_EEP("Device Cap", pBase->deviceCap);
+ PR_EEP("Device Type", pBase->deviceType);
+ PR_EEP("Power Table Offset", pBase->pwrTableOffset);
+ PR_EEP("Tuning Caps1", pBase->params_for_tuning_caps[0]);
+ PR_EEP("Tuning Caps2", pBase->params_for_tuning_caps[1]);
+ PR_EEP("Enable Tx Temp Comp", !!(pBase->featureEnable & BIT(0)));
+ PR_EEP("Enable Tx Volt Comp", !!(pBase->featureEnable & BIT(1)));
+ PR_EEP("Enable fast clock", !!(pBase->featureEnable & BIT(2)));
+ PR_EEP("Enable doubling", !!(pBase->featureEnable & BIT(3)));
+ PR_EEP("Internal regulator", !!(pBase->featureEnable & BIT(4)));
+ PR_EEP("Enable Paprd", !!(pBase->featureEnable & BIT(5)));
+ PR_EEP("Driver Strength", !!(pBase->miscConfiguration & BIT(0)));
+ PR_EEP("Chain mask Reduce", (pBase->miscConfiguration >> 0x3) & 0x1);
+ PR_EEP("Write enable Gpio", pBase->eepromWriteEnableGpio);
+ PR_EEP("WLAN Disable Gpio", pBase->wlanDisableGpio);
+ PR_EEP("WLAN LED Gpio", pBase->wlanLedGpio);
+ PR_EEP("Rx Band Select Gpio", pBase->rxBandSelectGpio);
+ PR_EEP("Tx Gain", pBase->txrxgain >> 4);
+ PR_EEP("Rx Gain", pBase->txrxgain & 0xf);
+ PR_EEP("SW Reg", le32_to_cpu(pBase->swreg));
+
+ len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ ah->eeprom.ar9300_eep.macAddr);
+out:
+ if (len > size)
+ len = size;
+
+ return len;
+}
+#else
+static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ return 0;
+}
+#endif
+
/* XXX: review hardware docs */
static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
{
@@ -3446,6 +3556,8 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
+ else if (AR_SREV_9462(ah))
+ REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
else {
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
REG_RMW_FIELD(ah, AR_CH0_THERM,
@@ -3456,6 +3568,19 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
}
}
+static u16 ar9003_switch_com_spdt_get(struct ath_hw *ah, bool is_2ghz)
+{
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ __le32 val;
+
+ if (is_2ghz)
+ val = eep->modalHeader2G.switchcomspdt;
+ else
+ val = eep->modalHeader5G.switchcomspdt;
+ return le32_to_cpu(val);
+}
+
+
static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
@@ -3510,7 +3635,36 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
- REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
+ if (AR_SREV_9462(ah)) {
+ if (AR_SREV_9462_10(ah)) {
+ value &= ~AR_SWITCH_TABLE_COM_SPDT;
+ value |= 0x00100000;
+ }
+ REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_AR9462_ALL, value);
+ } else
+ REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_ALL, value);
+
+
+ /*
+ * AR9462 defines new switch table for BT/WLAN,
+ * here's new field name in XXX.ref for both 2G and 5G.
+ * Register: [GLB_CONTROL] GLB_CONTROL (@0x20044)
+ * 15:12 R/W SWITCH_TABLE_COM_SPDT_WLAN_RX
+ * SWITCH_TABLE_COM_SPDT_WLAN_RX
+ *
+ * 11:8 R/W SWITCH_TABLE_COM_SPDT_WLAN_TX
+ * SWITCH_TABLE_COM_SPDT_WLAN_TX
+ *
+ * 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE
+ * SWITCH_TABLE_COM_SPDT_WLAN_IDLE
+ */
+ if (AR_SREV_9462_20_OR_LATER(ah)) {
+ value = ar9003_switch_com_spdt_get(ah, is2ghz);
+ REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
+ AR_SWITCH_TABLE_COM_SPDT_ALL, value);
+ }
value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
@@ -3710,6 +3864,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
{
int internal_regulator =
ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
+ u32 reg_val;
if (internal_regulator) {
if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
@@ -3754,13 +3909,16 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
return;
+ } else if (AR_SREV_9462(ah)) {
+ reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+ REG_WRITE(ah, AR_PHY_PMU1, reg_val);
} else {
/* Internal regulator is ON. Write swreg register. */
- int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+ reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
REG_WRITE(ah, AR_RTC_REG_CONTROL1,
REG_READ(ah, AR_RTC_REG_CONTROL1) &
(~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
- REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
+ REG_WRITE(ah, AR_RTC_REG_CONTROL0, reg_val);
/* Set REG_CONTROL1.SWREG_PROGRAM */
REG_WRITE(ah, AR_RTC_REG_CONTROL1,
REG_READ(ah,
@@ -3771,22 +3929,24 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
while (REG_READ_FIELD(ah, AR_PHY_PMU2,
- AR_PHY_PMU2_PGM))
+ AR_PHY_PMU2_PGM))
udelay(10);
REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
while (!REG_READ_FIELD(ah, AR_PHY_PMU1,
- AR_PHY_PMU1_PWD))
+ AR_PHY_PMU1_PWD))
udelay(10);
REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1);
while (!REG_READ_FIELD(ah, AR_PHY_PMU2,
- AR_PHY_PMU2_PGM))
+ AR_PHY_PMU2_PGM))
udelay(10);
- } else
- REG_WRITE(ah, AR_RTC_SLEEP_CLK,
- (REG_READ(ah,
- AR_RTC_SLEEP_CLK) |
- AR_RTC_FORCE_SWREG_PRD));
+ } else if (AR_SREV_9462(ah))
+ REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
+ else {
+ reg_val = REG_READ(ah, AR_RTC_SLEEP_CLK) |
+ AR_RTC_FORCE_SWREG_PRD;
+ REG_WRITE(ah, AR_RTC_SLEEP_CLK, reg_val);
+ }
}
}
@@ -4061,7 +4221,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
/* Write the power for duplicated frames - HT40 */
/* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */
- REG_WRITE(ah, 0xa3e0,
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE(8),
POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
@@ -4366,6 +4526,12 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah,
tempSlope = eep->modalHeader5G.tempSlope;
REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
+
+ if (AR_SREV_9462_20(ah))
+ REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1,
+ AR_PHY_TPC_19_B1_ALPHA_THERM, tempSlope);
+
+
REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
temperature[0]);
@@ -4600,20 +4766,14 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 *pPwrArray, u16 cfgCtl,
- u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
+ u8 antenna_reduction,
u16 powerLimit)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
- static const u16 tpScaleReductionTable[5] = {
- 0, 3, 6, 9, MAX_RATE_POWER
- };
int i;
- int16_t twiceLargestAntenna;
- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 scaledPower = 0, minCtlPower;
static const u16 ctlModesFor11a[] = {
CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
};
@@ -4631,28 +4791,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
bool is2ghz = IS_CHAN_2GHZ(chan);
ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- /* Compute TxPower reduction due to Antenna Gain */
- if (is2ghz)
- twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
- else
- twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
-
- twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
- twiceLargestAntenna, 0);
-
- /*
- * scaledPower is the minimum of the user input power level
- * and the regulatory allowed power level
- */
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
- maxRegAllowedPower -=
- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
- }
-
- scaledPower = min(powerLimit, maxRegAllowedPower);
+ scaledPower = powerLimit - antenna_reduction;
/*
* Reduce scaled Power by number of chains active to get
@@ -4839,7 +4978,6 @@ static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx)
static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -4892,7 +5030,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
ar9003_hw_set_power_per_rate_table(ah, chan,
targetPowerValT2, cfgCtl,
twiceAntennaReduction,
- twiceMaxRegulatoryPower,
powerLimit);
if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
@@ -4922,25 +5059,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
"TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
}
- /*
- * This is the TX power we send back to driver core,
- * and it can use to pass to userspace to display our
- * currently configured TX power setting.
- *
- * Since power is rate dependent, use one of the indices
- * from the AR9300_Rates enum to select an entry from
- * targetPowerValT2[] to report. Currently returns the
- * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
- * as CCK power is less interesting (?).
- */
- i = ALL_TARGET_LEGACY_6_24; /* legacy */
- if (IS_CHAN_HT40(chan))
- i = ALL_TARGET_HT40_0_8_16; /* ht40 */
- else if (IS_CHAN_HT20(chan))
- i = ALL_TARGET_HT20_0_8_16; /* ht20 */
-
- ah->txpower_limit = targetPowerValT2[i];
- regulatory->max_power_level = targetPowerValT2[i];
+ ah->txpower_limit = regulatory->max_power_level;
/* Write target power array to registers */
ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
@@ -5015,6 +5134,7 @@ const struct eeprom_ops eep_ar9300_ops = {
.check_eeprom = ath9k_hw_ar9300_check_eeprom,
.get_eeprom = ath9k_hw_ar9300_get_eeprom,
.fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
+ .dump_eeprom = ath9k_hw_ar9003_dump_eeprom,
.get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
.set_board_values = ath9k_hw_ar9300_set_board_values,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
index ab21a4915981..6335a867527e 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
@@ -233,7 +233,8 @@ struct ar9300_modal_eep_header {
u8 thresh62;
__le32 papdRateMaskHt20;
__le32 papdRateMaskHt40;
- u8 futureModal[10];
+ __le16 switchcomspdt;
+ u8 futureModal[8];
} __packed;
struct ar9300_cal_data_per_freq_op_loop {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index ad2bb2bf4e8a..fb937ba93e0c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -21,6 +21,9 @@
#include "ar9340_initvals.h"
#include "ar9330_1p1_initvals.h"
#include "ar9330_1p2_initvals.h"
+#include "ar9580_1p0_initvals.h"
+#include "ar9462_1p0_initvals.h"
+#include "ar9462_2p0_initvals.h"
/* General hardware code for the AR9003 hadware family */
@@ -31,6 +34,14 @@
*/
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{
+#define PCIE_PLL_ON_CREQ_DIS_L1_2P0 \
+ ar9462_pciephy_pll_on_clkreq_disable_L1_2p0
+
+#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_PRE], NULL, 0, 0);
@@ -253,6 +264,182 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
ar9485_1_1_pcie_phy_clkreq_disable_L1,
ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
2);
+ } else if (AR_SREV_9462_10(ah)) {
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_1p0_mac_core,
+ ARRAY_SIZE(ar9462_1p0_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9462_1p0_mac_postamble,
+ ARRAY_SIZE(ar9462_1p0_mac_postamble),
+ 5);
+
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9462_1p0_baseband_core,
+ ARRAY_SIZE(ar9462_1p0_baseband_core),
+ 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9462_1p0_baseband_postamble,
+ ARRAY_SIZE(ar9462_1p0_baseband_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9462_1p0_radio_core,
+ ARRAY_SIZE(ar9462_1p0_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+ ar9462_1p0_radio_postamble,
+ ARRAY_SIZE(ar9462_1p0_radio_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9462_1p0_soc_preamble,
+ ARRAY_SIZE(ar9462_1p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9462_1p0_soc_postamble,
+ ARRAY_SIZE(ar9462_1p0_soc_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_common_rx_gain_table_1p0), 2);
+
+ /* Awake -> Sleep Setting */
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ ar9462_pcie_phy_clkreq_disable_L1_1p0,
+ ARRAY_SIZE(ar9462_pcie_phy_clkreq_disable_L1_1p0),
+ 2);
+
+ /* Sleep -> Awake Setting */
+ INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+ ar9462_pcie_phy_clkreq_disable_L1_1p0,
+ ARRAY_SIZE(ar9462_pcie_phy_clkreq_disable_L1_1p0),
+ 2);
+
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9462_modes_fast_clock_1p0,
+ ARRAY_SIZE(ar9462_modes_fast_clock_1p0), 3);
+ INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+ AR9462_BB_CTX_COEFJ(1p0),
+ ARRAY_SIZE(AR9462_BB_CTX_COEFJ(1p0)), 2);
+
+ } else if (AR_SREV_9462_20(ah)) {
+
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core,
+ ARRAY_SIZE(ar9462_2p0_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9462_2p0_mac_postamble,
+ ARRAY_SIZE(ar9462_2p0_mac_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9462_2p0_baseband_core,
+ ARRAY_SIZE(ar9462_2p0_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9462_2p0_baseband_postamble,
+ ARRAY_SIZE(ar9462_2p0_baseband_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9462_2p0_radio_core,
+ ARRAY_SIZE(ar9462_2p0_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+ ar9462_2p0_radio_postamble,
+ ARRAY_SIZE(ar9462_2p0_radio_postamble), 5);
+ INIT_INI_ARRAY(&ah->ini_radio_post_sys2ant,
+ ar9462_2p0_radio_postamble_sys2ant,
+ ARRAY_SIZE(ar9462_2p0_radio_postamble_sys2ant),
+ 5);
+
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9462_2p0_soc_preamble,
+ ARRAY_SIZE(ar9462_2p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9462_2p0_soc_postamble,
+ ARRAY_SIZE(ar9462_2p0_soc_postamble), 5);
+
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_rx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_common_rx_gain_table_2p0), 2);
+
+ INIT_INI_ARRAY(&ah->ini_BTCOEX_MAX_TXPWR,
+ ar9462_2p0_BTCOEX_MAX_TXPWR_table,
+ ARRAY_SIZE(ar9462_2p0_BTCOEX_MAX_TXPWR_table),
+ 2);
+
+ /* Awake -> Sleep Setting */
+ INIT_INI_ARRAY(&ah->iniPcieSerdes,
+ PCIE_PLL_ON_CREQ_DIS_L1_2P0,
+ ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
+ 2);
+ /* Sleep -> Awake Setting */
+ INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+ PCIE_PLL_ON_CREQ_DIS_L1_2P0,
+ ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
+ 2);
+
+ /* Fast clock modal settings */
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9462_modes_fast_clock_2p0,
+ ARRAY_SIZE(ar9462_modes_fast_clock_2p0), 3);
+
+ INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+ AR9462_BB_CTX_COEFJ(2p0),
+ ARRAY_SIZE(AR9462_BB_CTX_COEFJ(2p0)), 2);
+
+ INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ,
+ ARRAY_SIZE(AR9462_BBC_TXIFR_COEFFJ), 2);
+
+ } else if (AR_SREV_9580(ah)) {
+ /* mac */
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+ ar9580_1p0_mac_core,
+ ARRAY_SIZE(ar9580_1p0_mac_core), 2);
+ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+ ar9580_1p0_mac_postamble,
+ ARRAY_SIZE(ar9580_1p0_mac_postamble), 5);
+
+ /* bb */
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ ar9580_1p0_baseband_core,
+ ARRAY_SIZE(ar9580_1p0_baseband_core), 2);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ ar9580_1p0_baseband_postamble,
+ ARRAY_SIZE(ar9580_1p0_baseband_postamble), 5);
+
+ /* radio */
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+ ar9580_1p0_radio_core,
+ ARRAY_SIZE(ar9580_1p0_radio_core), 2);
+ INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+ ar9580_1p0_radio_postamble,
+ ARRAY_SIZE(ar9580_1p0_radio_postamble), 5);
+
+ /* soc */
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+ ar9580_1p0_soc_preamble,
+ ARRAY_SIZE(ar9580_1p0_soc_preamble), 2);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+ ar9580_1p0_soc_postamble,
+ ARRAY_SIZE(ar9580_1p0_soc_postamble), 5);
+
+ /* rx/tx gain */
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9580_1p0_rx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_rx_gain_table), 2);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_low_ob_db_tx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
+ 5);
+
+ INIT_INI_ARRAY(&ah->iniModesAdditional,
+ ar9580_1p0_modes_fast_clock,
+ ARRAY_SIZE(ar9580_1p0_modes_fast_clock),
+ 3);
} else {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@@ -323,178 +510,293 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
}
}
+static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_lowest_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485_modes_lowest_ob_db_tx_gain_1_1,
+ ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+ 5);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_lowest_ob_db_tx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table),
+ 5);
+ else if (AR_SREV_9462_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9462_modes_low_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_modes_low_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9462_20(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9462_modes_low_ob_db_tx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_modes_low_ob_db_tx_gain_table_2p0),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+ 5);
+}
+
+static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485Modes_high_ob_db_tx_gain_1_1,
+ ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
+ 5);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_high_ob_db_tx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
+ 5);
+ else if (AR_SREV_9462_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9462_modes_high_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_modes_high_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9462_20(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9462_modes_high_ob_db_tx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_modes_high_ob_db_tx_gain_table_2p0),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_high_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
+ 5);
+}
+
+static void ar9003_tx_gain_table_mode2(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_low_ob_db_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_low_ob_db_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485Modes_low_ob_db_tx_gain_1_1,
+ ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
+ 5);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_low_ob_db_tx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_low_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
+ 5);
+}
+
+static void ar9003_tx_gain_table_mode3(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_power_tx_gain_1p2,
+ ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
+ 5);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9331_modes_high_power_tx_gain_1p1,
+ ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
+ 5);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+ 5);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485Modes_high_power_tx_gain_1_1,
+ ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
+ 5);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_high_power_tx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table),
+ 5);
+ else
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_high_power_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
+ 5);
+}
+
static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
{
switch (ar9003_hw_get_tx_gain_idx(ah)) {
case 0:
default:
- if (AR_SREV_9330_12(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9331_modes_lowest_ob_db_tx_gain_1p2,
- ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
- 5);
- else if (AR_SREV_9330_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9331_modes_lowest_ob_db_tx_gain_1p1,
- ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
- 5);
- else if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
- ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
- 5);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9485_modes_lowest_ob_db_tx_gain_1_1,
- ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
- 5);
+ ar9003_tx_gain_table_mode0(ah);
break;
case 1:
- if (AR_SREV_9330_12(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9331_modes_high_ob_db_tx_gain_1p2,
- ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
- 5);
- else if (AR_SREV_9330_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9331_modes_high_ob_db_tx_gain_1p1,
- ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
- 5);
- else if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
- ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
- 5);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9485Modes_high_ob_db_tx_gain_1_1,
- ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_high_ob_db_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
- 5);
+ ar9003_tx_gain_table_mode1(ah);
break;
case 2:
- if (AR_SREV_9330_12(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9331_modes_low_ob_db_tx_gain_1p2,
- ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
- 5);
- else if (AR_SREV_9330_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9331_modes_low_ob_db_tx_gain_1p1,
- ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
- 5);
- else if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
- ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
- 5);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9485Modes_low_ob_db_tx_gain_1_1,
- ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_low_ob_db_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
- 5);
+ ar9003_tx_gain_table_mode2(ah);
break;
case 3:
- if (AR_SREV_9330_12(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9331_modes_high_power_tx_gain_1p2,
- ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
- 5);
- else if (AR_SREV_9330_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9331_modes_high_power_tx_gain_1p1,
- ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
- 5);
- else if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
- ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
- 5);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9485Modes_high_power_tx_gain_1_1,
- ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_high_power_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
- 5);
+ ar9003_tx_gain_table_mode3(ah);
break;
}
}
+static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p2,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p2),
+ 2);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_rx_gain_1p1,
+ ARRAY_SIZE(ar9331_common_rx_gain_1p1),
+ 2);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9340Common_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
+ 2);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9485Common_wo_xlna_rx_gain_1_1,
+ ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+ 2);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9580_1p0_rx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_rx_gain_table),
+ 2);
+ else if (AR_SREV_9462_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_common_rx_gain_table_1p0),
+ 2);
+ else if (AR_SREV_9462_20(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_rx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_common_rx_gain_table_2p0),
+ 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9300Common_rx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
+ 2);
+}
+
+static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
+{
+ if (AR_SREV_9330_12(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_wo_xlna_rx_gain_1p2,
+ ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
+ 2);
+ else if (AR_SREV_9330_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9331_common_wo_xlna_rx_gain_1p1,
+ ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
+ 2);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9340Common_wo_xlna_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
+ 2);
+ else if (AR_SREV_9485_11(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9485Common_wo_xlna_rx_gain_1_1,
+ ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+ 2);
+ else if (AR_SREV_9462_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_wo_xlna_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_common_wo_xlna_rx_gain_table_1p0),
+ 2);
+ else if (AR_SREV_9462_20(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_wo_xlna_rx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_common_wo_xlna_rx_gain_table_2p0),
+ 2);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9580_1p0_wo_xlna_rx_gain_table,
+ ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
+ 2);
+ else
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9300Common_wo_xlna_rx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
+ 2);
+}
+
+static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
+{
+ if (AR_SREV_9462_10(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_mixed_rx_gain_table_1p0,
+ ARRAY_SIZE(ar9462_common_mixed_rx_gain_table_1p0), 2);
+ else if (AR_SREV_9462_20(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9462_common_mixed_rx_gain_table_2p0,
+ ARRAY_SIZE(ar9462_common_mixed_rx_gain_table_2p0), 2);
+}
+
static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
{
switch (ar9003_hw_get_rx_gain_idx(ah)) {
case 0:
default:
- if (AR_SREV_9330_12(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9331_common_rx_gain_1p2,
- ARRAY_SIZE(ar9331_common_rx_gain_1p2),
- 2);
- else if (AR_SREV_9330_11(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9331_common_rx_gain_1p1,
- ARRAY_SIZE(ar9331_common_rx_gain_1p1),
- 2);
- else if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9340Common_rx_gain_table_1p0,
- ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
- 2);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9485Common_wo_xlna_rx_gain_1_1,
- ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
- 2);
- else
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9300Common_rx_gain_table_2p2,
- ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
- 2);
+ ar9003_rx_gain_table_mode0(ah);
break;
case 1:
- if (AR_SREV_9330_12(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9331_common_wo_xlna_rx_gain_1p2,
- ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
- 2);
- else if (AR_SREV_9330_11(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9331_common_wo_xlna_rx_gain_1p1,
- ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
- 2);
- else if (AR_SREV_9340(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9340Common_wo_xlna_rx_gain_table_1p0,
- ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
- 2);
- else if (AR_SREV_9485_11(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9485Common_wo_xlna_rx_gain_1_1,
- ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
- 2);
- else
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9300Common_wo_xlna_rx_gain_table_2p2,
- ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
- 2);
+ ar9003_rx_gain_table_mode1(ah);
+ break;
+ case 2:
+ ar9003_rx_gain_table_mode2(ah);
break;
}
}
@@ -516,14 +818,10 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
* register as the other analog registers. Hence the 9 writes.
*/
static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
- int restore,
- int power_off)
+ bool power_off)
{
- if (ah->is_pciexpress != true || ah->aspm_enabled != true)
- return;
-
/* Nothing to do on restore for 11N */
- if (!restore) {
+ if (!power_off /* !restore */) {
/* set bit 19 to allow forcing of pcie core into L1 state */
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 8ff0b88a29b9..b363cc06cfd9 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -21,6 +21,132 @@ static void ar9003_hw_rx_enable(struct ath_hw *hw)
REG_WRITE(hw, AR_CR, 0);
}
+static void
+ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
+{
+ struct ar9003_txc *ads = ds;
+ int checksum = 0;
+ u32 val, ctl12, ctl17;
+
+ val = (ATHEROS_VENDOR_ID << AR_DescId_S) |
+ (1 << AR_TxRxDesc_S) |
+ (1 << AR_CtrlStat_S) |
+ (i->qcu << AR_TxQcuNum_S) | 0x17;
+
+ checksum += val;
+ ACCESS_ONCE(ads->info) = val;
+
+ checksum += i->link;
+ ACCESS_ONCE(ads->link) = i->link;
+
+ checksum += i->buf_addr[0];
+ ACCESS_ONCE(ads->data0) = i->buf_addr[0];
+ checksum += i->buf_addr[1];
+ ACCESS_ONCE(ads->data1) = i->buf_addr[1];
+ checksum += i->buf_addr[2];
+ ACCESS_ONCE(ads->data2) = i->buf_addr[2];
+ checksum += i->buf_addr[3];
+ ACCESS_ONCE(ads->data3) = i->buf_addr[3];
+
+ checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen);
+ ACCESS_ONCE(ads->ctl3) = val;
+ checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen);
+ ACCESS_ONCE(ads->ctl5) = val;
+ checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen);
+ ACCESS_ONCE(ads->ctl7) = val;
+ checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen);
+ ACCESS_ONCE(ads->ctl9) = val;
+
+ checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff);
+ ACCESS_ONCE(ads->ctl10) = checksum;
+
+ if (i->is_first || i->is_last) {
+ ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0)
+ | set11nTries(i->rates, 1)
+ | set11nTries(i->rates, 2)
+ | set11nTries(i->rates, 3)
+ | (i->dur_update ? AR_DurUpdateEna : 0)
+ | SM(0, AR_BurstDur);
+
+ ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0)
+ | set11nRate(i->rates, 1)
+ | set11nRate(i->rates, 2)
+ | set11nRate(i->rates, 3);
+ } else {
+ ACCESS_ONCE(ads->ctl13) = 0;
+ ACCESS_ONCE(ads->ctl14) = 0;
+ }
+
+ ads->ctl20 = 0;
+ ads->ctl21 = 0;
+ ads->ctl22 = 0;
+
+ ctl17 = SM(i->keytype, AR_EncrType);
+ if (!i->is_first) {
+ ACCESS_ONCE(ads->ctl11) = 0;
+ ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore;
+ ACCESS_ONCE(ads->ctl15) = 0;
+ ACCESS_ONCE(ads->ctl16) = 0;
+ ACCESS_ONCE(ads->ctl17) = ctl17;
+ ACCESS_ONCE(ads->ctl18) = 0;
+ ACCESS_ONCE(ads->ctl19) = 0;
+ return;
+ }
+
+ ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
+ | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+ | SM(i->txpower, AR_XmitPower)
+ | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+ | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+ | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
+ | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+ | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
+ (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
+
+ ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ?
+ SM(i->keyix, AR_DestIdx) : 0)
+ | SM(i->type, AR_FrameType)
+ | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+ | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+ | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+ ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
+ switch (i->aggr) {
+ case AGGR_BUF_FIRST:
+ ctl17 |= SM(i->aggr_len, AR_AggrLen);
+ /* fall through */
+ case AGGR_BUF_MIDDLE:
+ ctl12 |= AR_IsAggr | AR_MoreAggr;
+ ctl17 |= SM(i->ndelim, AR_PadDelim);
+ break;
+ case AGGR_BUF_LAST:
+ ctl12 |= AR_IsAggr;
+ break;
+ case AGGR_BUF_NONE:
+ break;
+ }
+
+ val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S;
+ ctl12 |= SM(val, AR_PAPRDChainMask);
+
+ ACCESS_ONCE(ads->ctl12) = ctl12;
+ ACCESS_ONCE(ads->ctl17) = ctl17;
+
+ ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0)
+ | set11nPktDurRTSCTS(i->rates, 1);
+
+ ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2)
+ | set11nPktDurRTSCTS(i->rates, 3);
+
+ ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0)
+ | set11nRateFlags(i->rates, 1)
+ | set11nRateFlags(i->rates, 2)
+ | set11nRateFlags(i->rates, 3)
+ | SM(i->rtscts_rate, AR_RTSCTSRate);
+
+ ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
+}
+
static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
{
int checksum;
@@ -185,47 +311,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
return true;
}
-static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
- bool is_firstseg, bool is_lastseg,
- const void *ds0, dma_addr_t buf_addr,
- unsigned int qcu)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
- unsigned int descid = 0;
-
- ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) |
- (1 << AR_TxRxDesc_S) |
- (1 << AR_CtrlStat_S) |
- (qcu << AR_TxQcuNum_S) | 0x17;
-
- ads->data0 = buf_addr;
- ads->data1 = 0;
- ads->data2 = 0;
- ads->data3 = 0;
-
- ads->ctl3 = (seglen << AR_BufLen_S);
- ads->ctl3 &= AR_BufLen;
-
- /* Fill in pointer checksum and descriptor id */
- ads->ctl10 = ar9003_calc_ptr_chksum(ads);
- ads->ctl10 |= (descid << AR_TxDescId_S);
-
- if (is_firstseg) {
- ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore);
- } else if (is_lastseg) {
- ads->ctl11 = 0;
- ads->ctl12 = 0;
- ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13;
- ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14;
- } else {
- /* XXX Intermediate descriptor in a multi-descriptor frame.*/
- ads->ctl11 = 0;
- ads->ctl12 = AR_TxMore;
- ads->ctl13 = 0;
- ads->ctl14 = 0;
- }
-}
-
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
@@ -253,8 +338,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
return -EIO;
}
- if (status & AR_TxOpExceeded)
- ts->ts_status |= ATH9K_TXERR_XTXOP;
ts->ts_rateindex = MS(status, AR_FinalTxIdx);
ts->ts_seqnum = MS(status, AR_SeqNum);
ts->tid = MS(status, AR_TxTid);
@@ -264,6 +347,8 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
ts->ts_status = 0;
ts->ts_flags = 0;
+ if (status & AR_TxOpExceeded)
+ ts->ts_status |= ATH9K_TXERR_XTXOP;
status = ACCESS_ONCE(ads->status2);
ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
@@ -310,185 +395,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
return 0;
}
-static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
- u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
- u32 keyIx, enum ath9k_key_type keyType, u32 flags)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
- if (txpower > ah->txpower_limit)
- txpower = ah->txpower_limit;
-
- if (txpower > 63)
- txpower = 63;
-
- ads->ctl11 = (pktlen & AR_FrameLen)
- | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- | SM(txpower, AR_XmitPower)
- | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
- | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
- | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
-
- ads->ctl12 =
- (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
- | SM(type, AR_FrameType)
- | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
- | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
- | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
-
- ads->ctl17 = SM(keyType, AR_EncrType) |
- (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
- ads->ctl18 = 0;
- ads->ctl19 = AR_Not_Sounding;
-
- ads->ctl20 = 0;
- ads->ctl21 = 0;
- ads->ctl22 = 0;
-}
-
-static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
- if (val)
- ads->ctl11 |= AR_ClrDestMask;
- else
- ads->ctl11 &= ~AR_ClrDestMask;
-}
-
-static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
- void *lastds,
- u32 durUpdateEn, u32 rtsctsRate,
- u32 rtsctsDuration,
- struct ath9k_11n_rate_series series[],
- u32 nseries, u32 flags)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
- struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds;
- u_int32_t ctl11;
-
- if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
- ctl11 = ads->ctl11;
-
- if (flags & ATH9K_TXDESC_RTSENA) {
- ctl11 &= ~AR_CTSEnable;
- ctl11 |= AR_RTSEnable;
- } else {
- ctl11 &= ~AR_RTSEnable;
- ctl11 |= AR_CTSEnable;
- }
-
- ads->ctl11 = ctl11;
- } else {
- ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable));
- }
-
- ads->ctl13 = set11nTries(series, 0)
- | set11nTries(series, 1)
- | set11nTries(series, 2)
- | set11nTries(series, 3)
- | (durUpdateEn ? AR_DurUpdateEna : 0)
- | SM(0, AR_BurstDur);
-
- ads->ctl14 = set11nRate(series, 0)
- | set11nRate(series, 1)
- | set11nRate(series, 2)
- | set11nRate(series, 3);
-
- ads->ctl15 = set11nPktDurRTSCTS(series, 0)
- | set11nPktDurRTSCTS(series, 1);
-
- ads->ctl16 = set11nPktDurRTSCTS(series, 2)
- | set11nPktDurRTSCTS(series, 3);
-
- ads->ctl18 = set11nRateFlags(series, 0)
- | set11nRateFlags(series, 1)
- | set11nRateFlags(series, 2)
- | set11nRateFlags(series, 3)
- | SM(rtsctsRate, AR_RTSCTSRate);
- ads->ctl19 = AR_Not_Sounding;
-
- last_ads->ctl13 = ads->ctl13;
- last_ads->ctl14 = ads->ctl14;
-}
-
-static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
- u32 aggrLen)
-{
-#define FIRST_DESC_NDELIMS 60
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
- ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
-
- if (ah->ent_mode & AR_ENT_OTP_MPSD) {
- u32 ctl17, ndelim;
- /*
- * Add delimiter when using RTS/CTS with aggregation
- * and non enterprise AR9003 card
- */
- ctl17 = ads->ctl17;
- ndelim = MS(ctl17, AR_PadDelim);
-
- if (ndelim < FIRST_DESC_NDELIMS) {
- aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4;
- ndelim = FIRST_DESC_NDELIMS;
- }
-
- ctl17 &= ~AR_AggrLen;
- ctl17 |= SM(aggrLen, AR_AggrLen);
-
- ctl17 &= ~AR_PadDelim;
- ctl17 |= SM(ndelim, AR_PadDelim);
-
- ads->ctl17 = ctl17;
- } else {
- ads->ctl17 &= ~AR_AggrLen;
- ads->ctl17 |= SM(aggrLen, AR_AggrLen);
- }
-}
-
-static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
- u32 numDelims)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
- unsigned int ctl17;
-
- ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
-
- /*
- * We use a stack variable to manipulate ctl6 to reduce uncached
- * read modify, modfiy, write.
- */
- ctl17 = ads->ctl17;
- ctl17 &= ~AR_PadDelim;
- ctl17 |= SM(numDelims, AR_PadDelim);
- ads->ctl17 = ctl17;
-}
-
-static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
- ads->ctl12 |= AR_IsAggr;
- ads->ctl12 &= ~AR_MoreAggr;
- ads->ctl17 &= ~AR_PadDelim;
-}
-
-static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
-{
- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
- ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr);
-}
-
-void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains)
-{
- struct ar9003_txc *ads = ds;
-
- ads->ctl12 |= SM(chains, AR_PAPRDChainMask);
-}
-EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc);
-
void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
{
struct ath_hw_ops *ops = ath9k_hw_ops(hw);
@@ -496,15 +402,8 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
ops->rx_enable = ar9003_hw_rx_enable;
ops->set_desc_link = ar9003_hw_set_desc_link;
ops->get_isr = ar9003_hw_get_isr;
- ops->fill_txdesc = ar9003_hw_fill_txdesc;
+ ops->set_txdesc = ar9003_set_txdesc;
ops->proc_txdesc = ar9003_hw_proc_txdesc;
- ops->set11n_txdesc = ar9003_hw_set11n_txdesc;
- ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario;
- ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first;
- ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle;
- ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
- ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
- ops->set_clrdmask = ar9003_hw_set_clrdmask;
}
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
@@ -531,17 +430,18 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
/* TODO: byte swap on big endian for ar9300_10 */
- if ((rxsp->status11 & AR_RxDone) == 0)
- return -EINPROGRESS;
+ if (!rxs) {
+ if ((rxsp->status11 & AR_RxDone) == 0)
+ return -EINPROGRESS;
- if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
- return -EINVAL;
+ if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
+ return -EINVAL;
- if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
- return -EINPROGRESS;
+ if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
+ return -EINPROGRESS;
- if (!rxs)
return 0;
+ }
rxs->rs_status = 0;
rxs->rs_flags = 0;
@@ -625,8 +525,8 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (rxsp->status11 & AR_MichaelErr)
rxs->rs_status |= ATH9K_RXERR_MIC;
- else if (rxsp->status11 & AR_KeyMiss)
- rxs->rs_status |= ATH9K_RXERR_DECRYPT;
+ if (rxsp->status11 & AR_KeyMiss)
+ rxs->rs_status |= ATH9K_RXERR_KEYMISS;
}
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index f80d1d633980..0c462c904cbe 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -19,7 +19,6 @@
void ar9003_paprd_enable(struct ath_hw *ah, bool val)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath9k_channel *chan = ah->curchan;
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
@@ -54,13 +53,7 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val)
if (val) {
ah->paprd_table_write_done = true;
-
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- chan->chan->max_antenna_gain * 2,
- chan->chan->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit), false);
+ ath9k_hw_apply_txpower(ah, chan);
}
REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
@@ -113,7 +106,7 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
if (delta > scale)
return -1;
- switch (get_streams(common->tx_chainmask)) {
+ switch (get_streams(ah->txchainmask)) {
case 1:
delta = 6;
break;
@@ -126,7 +119,7 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
default:
delta = 0;
ath_dbg(common, ATH_DBG_CALIBRATE,
- "Invalid tx-chainmask: %u\n", common->tx_chainmask);
+ "Invalid tx-chainmask: %u\n", ah->txchainmask);
}
power += delta;
@@ -147,7 +140,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_CTRL1_B2
};
int training_power;
- int i;
+ int i, val;
if (IS_CHAN_2GHZ(ah->curchan))
training_power = ar9003_get_training_power_2g(ah);
@@ -207,8 +200,9 @@ 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;
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2,
- AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147);
+ AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, val);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
@@ -217,7 +211,7 @@ 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))
+ if (AR_SREV_9485(ah) || AR_SREV_9462(ah))
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
-3);
@@ -225,9 +219,10 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
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;
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE,
- -15);
+ val);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4,
@@ -757,6 +752,7 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah,
training_power);
if (ah->caps.tx_chainmask & BIT(2))
+ /* val AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL correct? */
REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2,
AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
training_power);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index fcafec0605f4..fe96997921d3 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -370,7 +370,7 @@ static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
else
spur_subchannel_sd = 0;
- spur_freq_sd = ((freq_offset + 10) << 9) / 11;
+ spur_freq_sd = (freq_offset << 9) / 11;
} else {
if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
@@ -379,7 +379,7 @@ static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
else
spur_subchannel_sd = 1;
- spur_freq_sd = ((freq_offset - 10) << 9) / 11;
+ spur_freq_sd = (freq_offset << 9) / 11;
}
@@ -482,7 +482,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah,
(REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO);
/* Enable 11n HT, 20 MHz */
- phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH |
+ phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 |
AR_PHY_GC_SHORT_GI_40 | enableDacFifo;
/* Configure baseband for dynamic 20/40 operation */
@@ -540,7 +540,7 @@ static void ar9003_hw_init_bb(struct ath_hw *ah,
udelay(synthDelay + BASE_ACTIVATE_DELAY);
}
-void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
+static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
{
switch (rx) {
case 0x5:
@@ -559,6 +559,9 @@ void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
+ else if (AR_SREV_9462(ah))
+ /* xxx only when MCI support is enabled */
+ REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
else
REG_WRITE(ah, AR_SELFGEN_MASK, tx);
@@ -592,6 +595,9 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
REG_WRITE(ah, AR_PCU_MISC_MODE2,
val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
+
+ REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
}
static void ar9003_hw_prog_ini(struct ath_hw *ah,
@@ -625,9 +631,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah,
static int ar9003_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
unsigned int regWrites = 0, i;
- struct ieee80211_channel *channel = chan->chan;
u32 modesIndex;
switch (chan->chanmode) {
@@ -658,6 +662,10 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex);
+ if (i == ATH_INI_POST && AR_SREV_9462_20(ah))
+ ar9003_hw_prog_ini(ah,
+ &ah->ini_radio_post_sys2ant,
+ modesIndex);
}
REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
@@ -677,17 +685,27 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
+ if (AR_SREV_9462(ah))
+ ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1);
+
+ ah->modes_index = modesIndex;
ar9003_hw_override_ini(ah);
ar9003_hw_set_channel_regs(ah, chan);
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+ ath9k_hw_apply_txpower(ah, chan);
+
+ if (AR_SREV_9462(ah)) {
+ if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
+ ah->enabled_cals |= TX_IQ_CAL;
+ else
+ ah->enabled_cals &= ~TX_IQ_CAL;
- /* Set TX power */
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- channel->max_antenna_gain * 2,
- channel->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit), false);
+ if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
+ ah->enabled_cals |= TX_CL_CAL;
+ else
+ ah->enabled_cals &= ~TX_CL_CAL;
+ }
return 0;
}
@@ -785,16 +803,6 @@ static void ar9003_hw_rfbus_done(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
}
-static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
-{
- u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
- if (value)
- v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
- else
- v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
- REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
-}
-
static bool ar9003_hw_ani_control(struct ath_hw *ah,
enum ath9k_ani_cmd cmd, int param)
{
@@ -1253,6 +1261,73 @@ static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
}
+static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 *ini_reloaded)
+{
+ unsigned int regWrites = 0;
+ u32 modesIndex;
+
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ modesIndex = 1;
+ break;
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ modesIndex = 2;
+ break;
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_B:
+ modesIndex = 4;
+ break;
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ modesIndex = 3;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (modesIndex == ah->modes_index) {
+ *ini_reloaded = false;
+ goto set_rfmode;
+ }
+
+ ar9003_hw_prog_ini(ah, &ah->iniSOC[ATH_INI_POST], modesIndex);
+ ar9003_hw_prog_ini(ah, &ah->iniMac[ATH_INI_POST], modesIndex);
+ ar9003_hw_prog_ini(ah, &ah->iniBB[ATH_INI_POST], modesIndex);
+ ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex);
+ if (AR_SREV_9462_20(ah))
+ ar9003_hw_prog_ini(ah,
+ &ah->ini_radio_post_sys2ant,
+ modesIndex);
+
+ REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+
+ /*
+ * For 5GHz channels requiring Fast Clock, apply
+ * different modal values.
+ */
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites);
+
+ if (AR_SREV_9330(ah))
+ REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
+
+ if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
+ REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
+
+ ah->modes_index = modesIndex;
+ *ini_reloaded = true;
+
+set_rfmode:
+ ar9003_hw_set_rfmode(ah, chan);
+ return 0;
+}
+
void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -1277,11 +1352,11 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
priv_ops->rfbus_req = ar9003_hw_rfbus_req;
priv_ops->rfbus_done = ar9003_hw_rfbus_done;
- priv_ops->set_diversity = ar9003_hw_set_diversity;
priv_ops->ani_control = ar9003_hw_ani_control;
priv_ops->do_getnf = ar9003_hw_do_getnf;
priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
priv_ops->set_radar_params = ar9003_hw_set_radar_params;
+ priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 5c590429f120..2f4023e66081 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -325,10 +325,10 @@
#define AR_PHY_RX_OCGAIN (AR_AGC_BASE + 0x200)
-#define AR_PHY_CCA_NOM_VAL_9300_2GHZ -110
-#define AR_PHY_CCA_NOM_VAL_9300_5GHZ -115
-#define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ -125
-#define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ -125
+#define AR_PHY_CCA_NOM_VAL_9300_2GHZ (AR_SREV_9462(ah) ? -127 : -110)
+#define AR_PHY_CCA_NOM_VAL_9300_5GHZ (AR_SREV_9462(ah) ? -127 : -115)
+#define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ (AR_SREV_9462(ah) ? -127 : -125)
+#define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ (AR_SREV_9462(ah) ? -127 : -125)
#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ -95
#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ -100
@@ -572,6 +572,8 @@
#define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300)
+#define AR_PHY_TX_IQCAL_CONTROL_0 (AR_SM_BASE + AR_SREV_9485(ah) ? \
+ 0x3c4 : 0x444)
#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \
0x3c8 : 0x448)
#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \
@@ -581,6 +583,7 @@
#define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \
(AR_SREV_9485(ah) ? \
0x3d0 : 0x450) + ((_i) << 2))
+#define AR_PHY_RTT_CTRL (AR_SM_BASE + 0x380)
#define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0)
#define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4)
@@ -600,6 +603,17 @@
#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE 0x0000ff00
#define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S 8
+/* AIC Registers */
+#define AR_PHY_AIC_CTRL_0_B0 (AR_SM_BASE + 0x4b0)
+#define AR_PHY_AIC_CTRL_1_B0 (AR_SM_BASE + 0x4b4)
+#define AR_PHY_AIC_CTRL_2_B0 (AR_SM_BASE + 0x4b8)
+#define AR_PHY_AIC_CTRL_3_B0 (AR_SM_BASE + 0x4bc)
+#define AR_PHY_AIC_STAT_0_B0 (AR_SM_BASE + (AR_SREV_9462_10(ah) ? \
+ 0x4c0 : 0x4c4))
+#define AR_PHY_AIC_STAT_1_B0 (AR_SM_BASE + (AR_SREV_9462_10(ah) ? \
+ 0x4c4 : 0x4c8))
+#define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0)
+#define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc)
#define AR_PHY_65NM_CH0_SYNTH4 0x1608c
#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002
@@ -609,7 +623,35 @@
#define AR_PHY_65NM_CH0_BIAS2 0x160c4
#define AR_PHY_65NM_CH0_BIAS4 0x160cc
#define AR_PHY_65NM_CH0_RXTX4 0x1610c
-#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : 0x1628c)
+
+#define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \
+ ((AR_SREV_9462(ah) ? 0x1628c : 0x16280)))
+#define AR_CH0_TOP_XPABIASLVL (0x300)
+#define AR_CH0_TOP_XPABIASLVL_S (8)
+
+#define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : \
+ ((AR_SREV_9485(ah) ? 0x1628c : 0x16294)))
+#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
+#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
+#define AR_CH0_THERM_XPASHORT2GND 0x4
+#define AR_CH0_THERM_XPASHORT2GND_S 2
+
+#define AR_SWITCH_TABLE_COM_ALL (0xffff)
+#define AR_SWITCH_TABLE_COM_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_AR9462_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM_AR9462_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000)
+#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0)
+#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4)
+
+#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM2_ALL_S (0)
+
+#define AR_SWITCH_TABLE_ALL (0xfff)
+#define AR_SWITCH_TABLE_ALL_S (0)
+
+#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 :\
+ (AR_SREV_9485(ah) ? 0x1628c : 0x16294))
#define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000
#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
@@ -625,21 +667,23 @@
#define AR_PHY_65NM_CH2_RXTX1 0x16900
#define AR_PHY_65NM_CH2_RXTX2 0x16904
-#define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : 0x16284)
+#define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \
+ (AR_SREV_9485(ah) ? 0x16284 : 0x16290))
#define AR_CH0_TOP2_XPABIASLVL 0xf000
#define AR_CH0_TOP2_XPABIASLVL_S 12
-#define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : 0x16290)
+#define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : \
+ (AR_SREV_9485(ah) ? 0x16290 : 0x16298))
#define AR_CH0_XTAL_CAPINDAC 0x7f000000
#define AR_CH0_XTAL_CAPINDAC_S 24
#define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000
#define AR_CH0_XTAL_CAPOUTDAC_S 17
-#define AR_PHY_PMU1 0x16c40
+#define AR_PHY_PMU1 (AR_SREV_9462(ah) ? 0x16340 : 0x16c40)
#define AR_PHY_PMU1_PWD 0x1
#define AR_PHY_PMU1_PWD_S 0
-#define AR_PHY_PMU2 0x16c44
+#define AR_PHY_PMU2 (AR_SREV_9462(ah) ? 0x16344 : 0x16c44)
#define AR_PHY_PMU2_PGM 0x00200000
#define AR_PHY_PMU2_PGM_S 21
@@ -779,6 +823,22 @@
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24
#define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004
+#define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION 0x00000001
+#define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION_S 0
+#define AR_PHY_RTT_CTRL_RESTORE_MASK 0x0000007E
+#define AR_PHY_RTT_CTRL_RESTORE_MASK_S 1
+#define AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE 0x00000080
+#define AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE_S 7
+#define AR_PHY_RTT_SW_RTT_TABLE_ACCESS 0x00000001
+#define AR_PHY_RTT_SW_RTT_TABLE_ACCESS_S 0
+#define AR_PHY_RTT_SW_RTT_TABLE_WRITE 0x00000002
+#define AR_PHY_RTT_SW_RTT_TABLE_WRITE_S 1
+#define AR_PHY_RTT_SW_RTT_TABLE_ADDR 0x0000001C
+#define AR_PHY_RTT_SW_RTT_TABLE_ADDR_S 2
+#define AR_PHY_RTT_SW_RTT_TABLE_DATA 0xFFFFFFF0
+#define AR_PHY_RTT_SW_RTT_TABLE_DATA_S 4
+#define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL 0x80000000
+#define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL_S 31
#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000
#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18
#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001
@@ -839,19 +899,42 @@
*/
#define AR_SM1_BASE 0xb200
-#define AR_PHY_SWITCH_CHAIN_1 (AR_SM1_BASE + 0x84)
-#define AR_PHY_FCAL_2_1 (AR_SM1_BASE + 0xd0)
-#define AR_PHY_DFT_TONE_CTL_1 (AR_SM1_BASE + 0xd4)
-#define AR_PHY_CL_TAB_1 (AR_SM1_BASE + 0x100)
-#define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180)
-#define AR_PHY_TPC_4_B1 (AR_SM1_BASE + 0x204)
-#define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208)
-#define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c)
-#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220)
-#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240)
+#define AR_PHY_SWITCH_CHAIN_1 (AR_SM1_BASE + 0x84)
+#define AR_PHY_FCAL_2_1 (AR_SM1_BASE + 0xd0)
+#define AR_PHY_DFT_TONE_CTL_1 (AR_SM1_BASE + 0xd4)
+#define AR_PHY_CL_TAB_1 (AR_SM1_BASE + 0x100)
+#define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180)
+#define AR_PHY_TPC_4_B1 (AR_SM1_BASE + 0x204)
+#define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208)
+#define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c)
+#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220)
+#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + (AR_SREV_AR9300(ah) ? \
+ 0x240 : 0x280))
+#define AR_PHY_TPC_19_B1 (AR_SM1_BASE + 0x240)
+#define AR_PHY_TPC_19_B1_ALPHA_THERM 0xff
+#define AR_PHY_TPC_19_B1_ALPHA_THERM_S 0
#define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c)
#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM1_BASE + 0x450 + ((_i) << 2))
+/* SM 1 AIC Registers */
+
+#define AR_PHY_AIC_CTRL_0_B1 (AR_SM1_BASE + 0x4b0)
+#define AR_PHY_AIC_CTRL_1_B1 (AR_SM1_BASE + 0x4b4)
+#define AR_PHY_AIC_CTRL_2_B1 (AR_SM1_BASE + 0x4b8)
+#define AR_PHY_AIC_STAT_0_B1 (AR_SM1_BASE + (AR_SREV_9462_10(ah) ? \
+ 0x4c0 : 0x4c4))
+#define AR_PHY_AIC_STAT_1_B1 (AR_SM1_BASE + (AR_SREV_9462_10(ah) ? \
+ 0x4c4 : 0x4c8))
+#define AR_PHY_AIC_CTRL_4_B1 (AR_SM1_BASE + 0x4c0)
+#define AR_PHY_AIC_STAT_2_B1 (AR_SM1_BASE + 0x4cc)
+
+#define AR_PHY_AIC_SRAM_ADDR_B1 (AR_SM1_BASE + 0x5f0)
+#define AR_PHY_AIC_SRAM_DATA_B1 (AR_SM1_BASE + 0x5f4)
+
+#define AR_PHY_RTT_TABLE_SW_INTF_B(i) (0x384 + (i) ? \
+ AR_SM1_BASE : AR_SM_BASE)
+#define AR_PHY_RTT_TABLE_SW_INTF_1_B(i) (0x388 + (i) ? \
+ AR_SM1_BASE : AR_SM_BASE)
/*
* Channel 2 Register Map
*/
@@ -914,6 +997,13 @@
#define AR_PHY_RSSI_3 (AR_AGC3_BASE + 0x180)
+/* GLB Registers */
+#define AR_GLB_BASE 0x20000
+#define AR_PHY_GLB_CONTROL (AR_GLB_BASE + 0x44)
+#define AR_GLB_SCRATCH(_ah) (AR_GLB_BASE + \
+ (AR_SREV_9462_20(_ah) ? 0x4c : 0x50))
+#define AR_GLB_STATUS (AR_GLB_BASE + 0x48)
+
/*
* Misc helper defines
*/
@@ -1124,6 +1214,4 @@
#define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f
#define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0
-void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
-
#endif /* AR9003_PHY_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c
new file mode 100644
index 000000000000..48803ee9c0d6
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications 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 "hw.h"
+#include "ar9003_phy.h"
+
+#define RTT_RESTORE_TIMEOUT 1000
+#define RTT_ACCESS_TIMEOUT 100
+#define RTT_BAD_VALUE 0x0bad0bad
+
+/*
+ * RTT (Radio Retention Table) hardware implementation information
+ *
+ * There is an internal table (i.e. the rtt) for each chain (or bank).
+ * Each table contains 6 entries and each entry is corresponding to
+ * a specific calibration parameter as depicted below.
+ * 0~2 - DC offset DAC calibration: loop, low, high (offsetI/Q_...)
+ * 3 - Filter cal (filterfc)
+ * 4 - RX gain settings
+ * 5 - Peak detector offset calibration (agc_caldac)
+ */
+
+void ar9003_hw_rtt_enable(struct ath_hw *ah)
+{
+ REG_WRITE(ah, AR_PHY_RTT_CTRL, 1);
+}
+
+void ar9003_hw_rtt_disable(struct ath_hw *ah)
+{
+ REG_WRITE(ah, AR_PHY_RTT_CTRL, 0);
+}
+
+void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask)
+{
+ REG_RMW_FIELD(ah, AR_PHY_RTT_CTRL,
+ AR_PHY_RTT_CTRL_RESTORE_MASK, rtt_mask);
+}
+
+bool ar9003_hw_rtt_force_restore(struct ath_hw *ah)
+{
+ if (!ath9k_hw_wait(ah, AR_PHY_RTT_CTRL,
+ AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE,
+ 0, RTT_RESTORE_TIMEOUT))
+ return false;
+
+ REG_RMW_FIELD(ah, AR_PHY_RTT_CTRL,
+ AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE, 1);
+
+ if (!ath9k_hw_wait(ah, AR_PHY_RTT_CTRL,
+ AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE,
+ 0, RTT_RESTORE_TIMEOUT))
+ return false;
+
+ return true;
+}
+
+static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain,
+ u32 index, u32 data28)
+{
+ u32 val;
+
+ val = SM(data28, AR_PHY_RTT_SW_RTT_TABLE_DATA);
+ REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain), val);
+
+ val = SM(0, AR_PHY_RTT_SW_RTT_TABLE_ACCESS) |
+ SM(1, AR_PHY_RTT_SW_RTT_TABLE_WRITE) |
+ SM(index, AR_PHY_RTT_SW_RTT_TABLE_ADDR);
+ REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val);
+ udelay(1);
+
+ val |= SM(1, AR_PHY_RTT_SW_RTT_TABLE_ACCESS);
+ REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val);
+ udelay(1);
+
+ if (!ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain),
+ AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0,
+ RTT_ACCESS_TIMEOUT))
+ return;
+
+ val &= ~SM(1, AR_PHY_RTT_SW_RTT_TABLE_WRITE);
+ REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val);
+ udelay(1);
+
+ ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain),
+ AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0,
+ RTT_ACCESS_TIMEOUT);
+}
+
+void ar9003_hw_rtt_load_hist(struct ath_hw *ah, u8 chain, u32 *table)
+{
+ int i;
+
+ for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++)
+ ar9003_hw_rtt_load_hist_entry(ah, chain, i, table[i]);
+}
+
+static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index)
+{
+ u32 val;
+
+ val = SM(0, AR_PHY_RTT_SW_RTT_TABLE_ACCESS) |
+ SM(0, AR_PHY_RTT_SW_RTT_TABLE_WRITE) |
+ SM(index, AR_PHY_RTT_SW_RTT_TABLE_ADDR);
+
+ REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val);
+ udelay(1);
+
+ val |= SM(1, AR_PHY_RTT_SW_RTT_TABLE_ACCESS);
+ REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val);
+ udelay(1);
+
+ if (!ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain),
+ AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0,
+ RTT_ACCESS_TIMEOUT))
+ return RTT_BAD_VALUE;
+
+ val = REG_READ(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain));
+
+ return val;
+}
+
+void ar9003_hw_rtt_fill_hist(struct ath_hw *ah, u8 chain, u32 *table)
+{
+ int i;
+
+ for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++)
+ table[i] = ar9003_hw_rtt_fill_hist_entry(ah, chain, i);
+}
+
+void ar9003_hw_rtt_clear_hist(struct ath_hw *ah)
+{
+ int i, j;
+
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->rxchainmask & (1 << i)))
+ continue;
+ for (j = 0; j < MAX_RTT_TABLE_ENTRY; j++)
+ ar9003_hw_rtt_load_hist_entry(ah, i, j, 0);
+ }
+}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
new file mode 100644
index 000000000000..030758d087d6
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef AR9003_RTT_H
+#define AR9003_RTT_H
+
+void ar9003_hw_rtt_enable(struct ath_hw *ah);
+void ar9003_hw_rtt_disable(struct ath_hw *ah);
+void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask);
+bool ar9003_hw_rtt_force_restore(struct ath_hw *ah);
+void ar9003_hw_rtt_load_hist(struct ath_hw *ah, u8 chain, u32 *table);
+void ar9003_hw_rtt_fill_hist(struct ath_hw *ah, u8 chain, u32 *table);
+void ar9003_hw_rtt_clear_hist(struct ath_hw *ah);
+
+#endif
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_1p0_initvals.h
new file mode 100644
index 000000000000..5c55ae389adb
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9462_1p0_initvals.h
@@ -0,0 +1,1833 @@
+/*
+ * Copyright (c) 2010 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9462_1P0_H
+#define INITVALS_9462_1P0_H
+
+/* AR9462 1.0 */
+
+static const u32 ar9462_1p0_mac_core[][2] = {
+ /* Addr allmodes */
+ {0x00000008, 0x00000000},
+ {0x00000030, 0x00060085},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000000},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x000010f0, 0x00000100},
+ {0x00001270, 0x00000000},
+ {0x000012b0, 0x00000000},
+ {0x000012f0, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00001810, 0x0f000003},
+ {0x00008000, 0x00000000},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000000},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00080000},
+ {0x00008040, 0x00000000},
+ {0x00008044, 0x00000000},
+ {0x00008048, 0x00000000},
+ {0x0000804c, 0xffffffff},
+ {0x00008050, 0xffffffff},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000310},
+ {0x00008074, 0x00000020},
+ {0x00008078, 0x00000000},
+ {0x0000809c, 0x0000000f},
+ {0x000080a0, 0x00000000},
+ {0x000080a4, 0x02ff0000},
+ {0x000080a8, 0x0e070605},
+ {0x000080ac, 0x0000000d},
+ {0x000080b0, 0x00000000},
+ {0x000080b4, 0x00000000},
+ {0x000080b8, 0x00000000},
+ {0x000080bc, 0x00000000},
+ {0x000080c0, 0x2a800000},
+ {0x000080c4, 0x06900168},
+ {0x000080c8, 0x13881c20},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00252500},
+ {0x000080d4, 0x00a00005},
+ {0x000080d8, 0x00400002},
+ {0x000080dc, 0x00000000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x3f3f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00000000},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000000},
+ {0x00008114, 0x000007ff},
+ {0x00008118, 0x000000aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x0000ffff},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x18486e00},
+ {0x00008174, 0x33332210},
+ {0x00008178, 0x00000000},
+ {0x0000817c, 0x00020000},
+ {0x000081c4, 0x33332210},
+ {0x000081c8, 0x00000000},
+ {0x000081cc, 0x00000000},
+ {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000800},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x40000000},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x99c00010},
+ {0x00008268, 0xffffffff},
+ {0x0000826c, 0x0000ffff},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000004},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x000000ff},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000140},
+ {0x00008314, 0x00000000},
+ {0x0000831c, 0x0000010d},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x0000001f},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000700},
+ {0x00008338, 0xffff0000},
+ {0x0000833c, 0x02400000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0xaa48105b},
+ {0x00008348, 0x008f0000},
+ {0x0000835c, 0x00000000},
+ {0x00008360, 0xffffffff},
+ {0x00008364, 0xffffffff},
+ {0x00008368, 0x00000000},
+ {0x00008370, 0x00000000},
+ {0x00008374, 0x000000ff},
+ {0x00008378, 0x00000000},
+ {0x0000837c, 0x00000000},
+ {0x00008380, 0xffffffff},
+ {0x00008384, 0xffffffff},
+ {0x00008390, 0xffffffff},
+ {0x00008394, 0xffffffff},
+ {0x00008398, 0x00000000},
+ {0x0000839c, 0x00000000},
+ {0x000083a4, 0x0000fa14},
+ {0x000083a8, 0x000f0c00},
+ {0x000083ac, 0x33332210},
+ {0x000083b0, 0x33332210},
+ {0x000083b4, 0x33332210},
+ {0x000083b8, 0x33332210},
+ {0x000083bc, 0x00000000},
+ {0x000083c0, 0x00000000},
+ {0x000083c4, 0x00000000},
+ {0x000083c8, 0x00000000},
+ {0x000083cc, 0x00000200},
+ {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9462_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9462_1p0_sys3ant[][2] = {
+ /* Addr allmodes */
+ {0x00063280, 0x00040807},
+ {0x00063284, 0x104ccccc},
+};
+
+static const u32 ar9462_pcie_phy_clkreq_enable_L1_1p0[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x10053e5e},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0000580c},
+};
+
+static const u32 ar9462_1p0_mac_core_emulation[][2] = {
+ /* Addr allmodes */
+ {0x00000030, 0x00060085},
+ {0x00000044, 0x00000008},
+ {0x0000805c, 0xffffc7ff},
+ {0x00008344, 0xaa4a105b},
+};
+
+static const u32 ar9462_common_rx_gain_table_ar9280_2p0_1p0[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x02000101},
+ {0x0000a004, 0x02000102},
+ {0x0000a008, 0x02000103},
+ {0x0000a00c, 0x02000104},
+ {0x0000a010, 0x02000200},
+ {0x0000a014, 0x02000201},
+ {0x0000a018, 0x02000202},
+ {0x0000a01c, 0x02000203},
+ {0x0000a020, 0x02000204},
+ {0x0000a024, 0x02000205},
+ {0x0000a028, 0x02000208},
+ {0x0000a02c, 0x02000302},
+ {0x0000a030, 0x02000303},
+ {0x0000a034, 0x02000304},
+ {0x0000a038, 0x02000400},
+ {0x0000a03c, 0x02010300},
+ {0x0000a040, 0x02010301},
+ {0x0000a044, 0x02010302},
+ {0x0000a048, 0x02000500},
+ {0x0000a04c, 0x02010400},
+ {0x0000a050, 0x02020300},
+ {0x0000a054, 0x02020301},
+ {0x0000a058, 0x02020302},
+ {0x0000a05c, 0x02020303},
+ {0x0000a060, 0x02020400},
+ {0x0000a064, 0x02030300},
+ {0x0000a068, 0x02030301},
+ {0x0000a06c, 0x02030302},
+ {0x0000a070, 0x02030303},
+ {0x0000a074, 0x02030400},
+ {0x0000a078, 0x02040300},
+ {0x0000a07c, 0x02040301},
+ {0x0000a080, 0x02040302},
+ {0x0000a084, 0x02040303},
+ {0x0000a088, 0x02030500},
+ {0x0000a08c, 0x02040400},
+ {0x0000a090, 0x02050203},
+ {0x0000a094, 0x02050204},
+ {0x0000a098, 0x02050205},
+ {0x0000a09c, 0x02040500},
+ {0x0000a0a0, 0x02050301},
+ {0x0000a0a4, 0x02050302},
+ {0x0000a0a8, 0x02050303},
+ {0x0000a0ac, 0x02050400},
+ {0x0000a0b0, 0x02050401},
+ {0x0000a0b4, 0x02050402},
+ {0x0000a0b8, 0x02050403},
+ {0x0000a0bc, 0x02050500},
+ {0x0000a0c0, 0x02050501},
+ {0x0000a0c4, 0x02050502},
+ {0x0000a0c8, 0x02050503},
+ {0x0000a0cc, 0x02050504},
+ {0x0000a0d0, 0x02050600},
+ {0x0000a0d4, 0x02050601},
+ {0x0000a0d8, 0x02050602},
+ {0x0000a0dc, 0x02050603},
+ {0x0000a0e0, 0x02050604},
+ {0x0000a0e4, 0x02050700},
+ {0x0000a0e8, 0x02050701},
+ {0x0000a0ec, 0x02050702},
+ {0x0000a0f0, 0x02050703},
+ {0x0000a0f4, 0x02050704},
+ {0x0000a0f8, 0x02050705},
+ {0x0000a0fc, 0x02050708},
+ {0x0000a100, 0x02050709},
+ {0x0000a104, 0x0205070a},
+ {0x0000a108, 0x0205070b},
+ {0x0000a10c, 0x0205070c},
+ {0x0000a110, 0x0205070d},
+ {0x0000a114, 0x02050710},
+ {0x0000a118, 0x02050711},
+ {0x0000a11c, 0x02050712},
+ {0x0000a120, 0x02050713},
+ {0x0000a124, 0x02050714},
+ {0x0000a128, 0x02050715},
+ {0x0000a12c, 0x02050730},
+ {0x0000a130, 0x02050731},
+ {0x0000a134, 0x02050732},
+ {0x0000a138, 0x02050733},
+ {0x0000a13c, 0x02050734},
+ {0x0000a140, 0x02050735},
+ {0x0000a144, 0x02050750},
+ {0x0000a148, 0x02050751},
+ {0x0000a14c, 0x02050752},
+ {0x0000a150, 0x02050753},
+ {0x0000a154, 0x02050754},
+ {0x0000a158, 0x02050755},
+ {0x0000a15c, 0x02050770},
+ {0x0000a160, 0x02050771},
+ {0x0000a164, 0x02050772},
+ {0x0000a168, 0x02050773},
+ {0x0000a16c, 0x02050774},
+ {0x0000a170, 0x02050775},
+ {0x0000a174, 0x00000776},
+ {0x0000a178, 0x00000776},
+ {0x0000a17c, 0x00000776},
+ {0x0000a180, 0x00000776},
+ {0x0000a184, 0x00000776},
+ {0x0000a188, 0x00000776},
+ {0x0000a18c, 0x00000776},
+ {0x0000a190, 0x00000776},
+ {0x0000a194, 0x00000776},
+ {0x0000a198, 0x00000776},
+ {0x0000a19c, 0x00000776},
+ {0x0000a1a0, 0x00000776},
+ {0x0000a1a4, 0x00000776},
+ {0x0000a1a8, 0x00000776},
+ {0x0000a1ac, 0x00000776},
+ {0x0000a1b0, 0x00000776},
+ {0x0000a1b4, 0x00000776},
+ {0x0000a1b8, 0x00000776},
+ {0x0000a1bc, 0x00000776},
+ {0x0000a1c0, 0x00000776},
+ {0x0000a1c4, 0x00000776},
+ {0x0000a1c8, 0x00000776},
+ {0x0000a1cc, 0x00000776},
+ {0x0000a1d0, 0x00000776},
+ {0x0000a1d4, 0x00000776},
+ {0x0000a1d8, 0x00000776},
+ {0x0000a1dc, 0x00000776},
+ {0x0000a1e0, 0x00000776},
+ {0x0000a1e4, 0x00000776},
+ {0x0000a1e8, 0x00000776},
+ {0x0000a1ec, 0x00000776},
+ {0x0000a1f0, 0x00000776},
+ {0x0000a1f4, 0x00000776},
+ {0x0000a1f8, 0x00000776},
+ {0x0000a1fc, 0x00000776},
+ {0x0000b000, 0x02000101},
+ {0x0000b004, 0x02000102},
+ {0x0000b008, 0x02000103},
+ {0x0000b00c, 0x02000104},
+ {0x0000b010, 0x02000200},
+ {0x0000b014, 0x02000201},
+ {0x0000b018, 0x02000202},
+ {0x0000b01c, 0x02000203},
+ {0x0000b020, 0x02000204},
+ {0x0000b024, 0x02000205},
+ {0x0000b028, 0x02000208},
+ {0x0000b02c, 0x02000302},
+ {0x0000b030, 0x02000303},
+ {0x0000b034, 0x02000304},
+ {0x0000b038, 0x02000400},
+ {0x0000b03c, 0x02010300},
+ {0x0000b040, 0x02010301},
+ {0x0000b044, 0x02010302},
+ {0x0000b048, 0x02000500},
+ {0x0000b04c, 0x02010400},
+ {0x0000b050, 0x02020300},
+ {0x0000b054, 0x02020301},
+ {0x0000b058, 0x02020302},
+ {0x0000b05c, 0x02020303},
+ {0x0000b060, 0x02020400},
+ {0x0000b064, 0x02030300},
+ {0x0000b068, 0x02030301},
+ {0x0000b06c, 0x02030302},
+ {0x0000b070, 0x02030303},
+ {0x0000b074, 0x02030400},
+ {0x0000b078, 0x02040300},
+ {0x0000b07c, 0x02040301},
+ {0x0000b080, 0x02040302},
+ {0x0000b084, 0x02040303},
+ {0x0000b088, 0x02030500},
+ {0x0000b08c, 0x02040400},
+ {0x0000b090, 0x02050203},
+ {0x0000b094, 0x02050204},
+ {0x0000b098, 0x02050205},
+ {0x0000b09c, 0x02040500},
+ {0x0000b0a0, 0x02050301},
+ {0x0000b0a4, 0x02050302},
+ {0x0000b0a8, 0x02050303},
+ {0x0000b0ac, 0x02050400},
+ {0x0000b0b0, 0x02050401},
+ {0x0000b0b4, 0x02050402},
+ {0x0000b0b8, 0x02050403},
+ {0x0000b0bc, 0x02050500},
+ {0x0000b0c0, 0x02050501},
+ {0x0000b0c4, 0x02050502},
+ {0x0000b0c8, 0x02050503},
+ {0x0000b0cc, 0x02050504},
+ {0x0000b0d0, 0x02050600},
+ {0x0000b0d4, 0x02050601},
+ {0x0000b0d8, 0x02050602},
+ {0x0000b0dc, 0x02050603},
+ {0x0000b0e0, 0x02050604},
+ {0x0000b0e4, 0x02050700},
+ {0x0000b0e8, 0x02050701},
+ {0x0000b0ec, 0x02050702},
+ {0x0000b0f0, 0x02050703},
+ {0x0000b0f4, 0x02050704},
+ {0x0000b0f8, 0x02050705},
+ {0x0000b0fc, 0x02050708},
+ {0x0000b100, 0x02050709},
+ {0x0000b104, 0x0205070a},
+ {0x0000b108, 0x0205070b},
+ {0x0000b10c, 0x0205070c},
+ {0x0000b110, 0x0205070d},
+ {0x0000b114, 0x02050710},
+ {0x0000b118, 0x02050711},
+ {0x0000b11c, 0x02050712},
+ {0x0000b120, 0x02050713},
+ {0x0000b124, 0x02050714},
+ {0x0000b128, 0x02050715},
+ {0x0000b12c, 0x02050730},
+ {0x0000b130, 0x02050731},
+ {0x0000b134, 0x02050732},
+ {0x0000b138, 0x02050733},
+ {0x0000b13c, 0x02050734},
+ {0x0000b140, 0x02050735},
+ {0x0000b144, 0x02050750},
+ {0x0000b148, 0x02050751},
+ {0x0000b14c, 0x02050752},
+ {0x0000b150, 0x02050753},
+ {0x0000b154, 0x02050754},
+ {0x0000b158, 0x02050755},
+ {0x0000b15c, 0x02050770},
+ {0x0000b160, 0x02050771},
+ {0x0000b164, 0x02050772},
+ {0x0000b168, 0x02050773},
+ {0x0000b16c, 0x02050774},
+ {0x0000b170, 0x02050775},
+ {0x0000b174, 0x00000776},
+ {0x0000b178, 0x00000776},
+ {0x0000b17c, 0x00000776},
+ {0x0000b180, 0x00000776},
+ {0x0000b184, 0x00000776},
+ {0x0000b188, 0x00000776},
+ {0x0000b18c, 0x00000776},
+ {0x0000b190, 0x00000776},
+ {0x0000b194, 0x00000776},
+ {0x0000b198, 0x00000776},
+ {0x0000b19c, 0x00000776},
+ {0x0000b1a0, 0x00000776},
+ {0x0000b1a4, 0x00000776},
+ {0x0000b1a8, 0x00000776},
+ {0x0000b1ac, 0x00000776},
+ {0x0000b1b0, 0x00000776},
+ {0x0000b1b4, 0x00000776},
+ {0x0000b1b8, 0x00000776},
+ {0x0000b1bc, 0x00000776},
+ {0x0000b1c0, 0x00000776},
+ {0x0000b1c4, 0x00000776},
+ {0x0000b1c8, 0x00000776},
+ {0x0000b1cc, 0x00000776},
+ {0x0000b1d0, 0x00000776},
+ {0x0000b1d4, 0x00000776},
+ {0x0000b1d8, 0x00000776},
+ {0x0000b1dc, 0x00000776},
+ {0x0000b1e0, 0x00000776},
+ {0x0000b1e4, 0x00000776},
+ {0x0000b1e8, 0x00000776},
+ {0x0000b1ec, 0x00000776},
+ {0x0000b1f0, 0x00000776},
+ {0x0000b1f4, 0x00000776},
+ {0x0000b1f8, 0x00000776},
+ {0x0000b1fc, 0x00000776},
+};
+
+static const u32 ar9200_ar9280_2p0_radio_core_1p0[][2] = {
+ /* Addr allmodes */
+ {0x00007800, 0x00040000},
+ {0x00007804, 0xdb005012},
+ {0x00007808, 0x04924914},
+ {0x0000780c, 0x21084210},
+ {0x00007810, 0x6d801300},
+ {0x00007814, 0x0019beff},
+ {0x00007818, 0x07e41000},
+ {0x0000781c, 0x00392000},
+ {0x00007820, 0x92592480},
+ {0x00007824, 0x00040000},
+ {0x00007828, 0xdb005012},
+ {0x0000782c, 0x04924914},
+ {0x00007830, 0x21084210},
+ {0x00007834, 0x6d801300},
+ {0x00007838, 0x0019beff},
+ {0x0000783c, 0x07e40000},
+ {0x00007840, 0x00392000},
+ {0x00007844, 0x92592480},
+ {0x00007848, 0x00100000},
+ {0x0000784c, 0x773f0567},
+ {0x00007850, 0x54214514},
+ {0x00007854, 0x12035828},
+ {0x00007858, 0x92592692},
+ {0x0000785c, 0x00000000},
+ {0x00007860, 0x56400000},
+ {0x00007864, 0x0a8e370e},
+ {0x00007868, 0xc0102850},
+ {0x0000786c, 0x812d4000},
+ {0x00007870, 0x807ec400},
+ {0x00007874, 0x001b6db0},
+ {0x00007878, 0x00376b63},
+ {0x0000787c, 0x06db6db6},
+ {0x00007880, 0x006d8000},
+ {0x00007884, 0xffeffffe},
+ {0x00007888, 0xffeffffe},
+ {0x0000788c, 0x00010000},
+ {0x00007890, 0x02060aeb},
+ {0x00007894, 0x5a108000},
+};
+
+static const u32 ar9462_1p0_baseband_postamble_emulation[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e3c, 0xcf946221, 0xcf946221, 0xcf946221, 0xcf946221},
+ {0x00009e44, 0x005c0000, 0x005c0000, 0x005c0000, 0x005c0000},
+ {0x0000a258, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x0000a25c, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a28c, 0x00011111, 0x00011111, 0x00011111, 0x00011111},
+ {0x0000a2c4, 0x00148d18, 0x00148d18, 0x00148d20, 0x00148d20},
+ {0x0000a2d8, 0xf999a800, 0xf999a800, 0xf999a80c, 0xf999a80c},
+ {0x0000a50c, 0x0000c00a, 0x0000c00a, 0x0000c00a, 0x0000c00a},
+ {0x0000a538, 0x00038e8c, 0x00038e8c, 0x00038e8c, 0x00038e8c},
+ {0x0000a53c, 0x0003cecc, 0x0003cecc, 0x0003cecc, 0x0003cecc},
+ {0x0000a540, 0x00040ed4, 0x00040ed4, 0x00040ed4, 0x00040ed4},
+ {0x0000a544, 0x00044edc, 0x00044edc, 0x00044edc, 0x00044edc},
+ {0x0000a548, 0x00048ede, 0x00048ede, 0x00048ede, 0x00048ede},
+ {0x0000a54c, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e},
+ {0x0000a550, 0x00050f5e, 0x00050f5e, 0x00050f5e, 0x00050f5e},
+ {0x0000a554, 0x00054f9e, 0x00054f9e, 0x00054f9e, 0x00054f9e},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9462_pcie_phy_pll_on_clkreq_disable_L1_1p0[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x10012e5e},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0000580c},
+};
+
+static const u32 ar9462_common_rx_gain_table_1p0[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x01910190},
+ {0x0000a030, 0x01930192},
+ {0x0000a034, 0x01950194},
+ {0x0000a038, 0x038a0196},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x22222229},
+ {0x0000a084, 0x1d1d1d1d},
+ {0x0000a088, 0x1d1d1d1d},
+ {0x0000a08c, 0x1d1d1d1d},
+ {0x0000a090, 0x171d1d1d},
+ {0x0000a094, 0x11111717},
+ {0x0000a098, 0x00030311},
+ {0x0000a09c, 0x00000000},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x2a2d2f32},
+ {0x0000b084, 0x21232328},
+ {0x0000b088, 0x19191c1e},
+ {0x0000b08c, 0x12141417},
+ {0x0000b090, 0x07070e0e},
+ {0x0000b094, 0x03030305},
+ {0x0000b098, 0x00000003},
+ {0x0000b09c, 0x00000000},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9462_modes_high_ob_db_tx_gain_table_1p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
+ {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
+ {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
+ {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+ {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060},
+ {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+ {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000},
+};
+
+static const u32 ar9462_common_wo_xlna_rx_gain_table_1p0[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x03820190},
+ {0x0000a030, 0x03840383},
+ {0x0000a034, 0x03880385},
+ {0x0000a038, 0x038a0389},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x29292929},
+ {0x0000a084, 0x29292929},
+ {0x0000a088, 0x29292929},
+ {0x0000a08c, 0x29292929},
+ {0x0000a090, 0x22292929},
+ {0x0000a094, 0x1d1d2222},
+ {0x0000a098, 0x0c111117},
+ {0x0000a09c, 0x00030303},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x32323232},
+ {0x0000b084, 0x2f2f3232},
+ {0x0000b088, 0x23282a2d},
+ {0x0000b08c, 0x1c1e2123},
+ {0x0000b090, 0x14171919},
+ {0x0000b094, 0x0e0e1214},
+ {0x0000b098, 0x03050707},
+ {0x0000b09c, 0x00030303},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9462_1p0_mac_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9462_1p0_mac_postamble_emulation[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00008014, 0x10f810f8, 0x10f810f8, 0x10f810f8, 0x10f810f8},
+ {0x0000801c, 0x0e8d8017, 0x0e8d8017, 0x0e8d8017, 0x0e8d8017},
+};
+
+static const u32 ar9462_1p0_tx_gain_table_baseband_postamble_emulation[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000000d5, 0x000000d5, 0x000000d5, 0x000000d5},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x00004002, 0x00004002, 0x00004002, 0x00004002},
+ {0x0000a508, 0x00008004, 0x00008004, 0x00008004, 0x00008004},
+ {0x0000a510, 0x0001000c, 0x0001000c, 0x0001000c, 0x0001000c},
+ {0x0000a514, 0x0001420b, 0x0001420b, 0x0001420b, 0x0001420b},
+ {0x0000a518, 0x0001824a, 0x0001824a, 0x0001824a, 0x0001824a},
+ {0x0000a51c, 0x0001c44a, 0x0001c44a, 0x0001c44a, 0x0001c44a},
+ {0x0000a520, 0x0002064a, 0x0002064a, 0x0002064a, 0x0002064a},
+ {0x0000a524, 0x0002484a, 0x0002484a, 0x0002484a, 0x0002484a},
+ {0x0000a528, 0x00028a4a, 0x00028a4a, 0x00028a4a, 0x00028a4a},
+ {0x0000a52c, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a},
+ {0x0000a530, 0x00030e4a, 0x00030e4a, 0x00030e4a, 0x00030e4a},
+ {0x0000a534, 0x00034e8a, 0x00034e8a, 0x00034e8a, 0x00034e8a},
+};
+
+static const u32 ar9462_1p0_radio_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524},
+ {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24646c08, 0x24646c08},
+ {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70},
+ {0x0001610c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
+ {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+ {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
+ {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+};
+
+static const u32 ar9462_1p0_soc_postamble_emulation[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00001133, 0x00001133, 0x00001133, 0x00001133},
+};
+
+static const u32 ar9462_1p0_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a9f6b},
+ {0x0000980c, 0x04900000},
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x6400a290},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x0d000600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x32840bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098e4, 0x01ffffff},
+ {0x000098e8, 0x01ffffff},
+ {0x000098ec, 0x01ffffff},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0xff55ff55},
+ {0x00009c08, 0x0320ff55},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x9883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c0040b},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038230c},
+ {0x00009e24, 0x990bb514},
+ {0x00009e28, 0x0c6f0000},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009e54, 0x64c355c7},
+ {0x00009e58, 0xfd897735},
+ {0x00009e5c, 0xe9198724},
+ {0x00009fc0, 0x803e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x00009fd0, 0x01193b93},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0xaaaaaaaa},
+ {0x0000a3ac, 0x3c466478},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000006},
+ {0x0000a3f8, 0x0c9bd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce739ce},
+ {0x0000a418, 0x2d001dce},
+ {0x0000a41c, 0x1ce739ce},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce739ce},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00100000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x05000080},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+ {0x0000a644, 0xbfad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x00000838},
+ {0x0000a6b0, 0x0000000a},
+ {0x0000a6b4, 0x28f12c01},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000001},
+ {0x0000a8d0, 0x004b6a8e},
+ {0x0000a8d4, 0x00000820},
+ {0x0000a8dc, 0x00000000},
+ {0x0000a8f0, 0x00000000},
+ {0x0000a8f4, 0x00000000},
+ {0x0000b2d0, 0x00000080},
+ {0x0000b2d4, 0x00000000},
+ {0x0000b2ec, 0x00000000},
+ {0x0000b2f0, 0x00000000},
+ {0x0000b2f4, 0x00000000},
+ {0x0000b2f8, 0x00000000},
+ {0x0000b408, 0x0e79e5c0},
+ {0x0000b40c, 0x00820820},
+ {0x0000b420, 0x00000000},
+ {0x0000b6b0, 0x0000000a},
+ {0x0000b6b4, 0x00c00001},
+};
+
+static const u32 ar9462_1p0_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+ {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+ {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+ {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+ {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+ {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c782},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x0131b7c0, 0x0131b7c4, 0x0131b7c4, 0x0131b7c0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f},
+ {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+ {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+ {0x0000a288, 0x00000110, 0x00000110, 0x00100110, 0x00100110},
+ {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+ {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
+};
+
+static const u32 ar9462_modes_fast_clock_1p0[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00001030, 0x00000268, 0x000004d0},
+ {0x00001070, 0x0000018c, 0x00000318},
+ {0x000010b0, 0x00000fd0, 0x00001fa0},
+ {0x00008014, 0x044c044c, 0x08980898},
+ {0x0000801c, 0x148ec02b, 0x148ec057},
+ {0x00008318, 0x000044c0, 0x00008980},
+ {0x00009e00, 0x0372131c, 0x0372131c},
+ {0x0000a230, 0x0000400b, 0x00004016},
+ {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9462_modes_low_ob_db_tx_gain_table_1p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+ {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
+ {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+ {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+ {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+ {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+ {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+ {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+ {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060},
+ {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+ {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000},
+};
+
+static const u32 ar9462_1p0_soc_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00002233, 0x00002233, 0x00002233, 0x00002233},
+};
+
+static const u32 ar9462_common_mixed_rx_gain_table_1p0[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x03820190},
+ {0x0000a030, 0x03840383},
+ {0x0000a034, 0x03880385},
+ {0x0000a038, 0x038a0389},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x29292929},
+ {0x0000a084, 0x29292929},
+ {0x0000a088, 0x29292929},
+ {0x0000a08c, 0x29292929},
+ {0x0000a090, 0x22292929},
+ {0x0000a094, 0x1d1d2222},
+ {0x0000a098, 0x0c111117},
+ {0x0000a09c, 0x00030303},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x2a2d2f32},
+ {0x0000b084, 0x21232328},
+ {0x0000b088, 0x19191c1e},
+ {0x0000b08c, 0x12141417},
+ {0x0000b090, 0x07070e0e},
+ {0x0000b094, 0x03030305},
+ {0x0000b098, 0x00000003},
+ {0x0000b09c, 0x00000000},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9462_pcie_phy_clkreq_disable_L1_1p0[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x10013e5e},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0000580c},
+};
+
+static const u32 ar9462_1p0_baseband_core_emulation[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafa68e30},
+ {0x00009884, 0x00002842},
+ {0x00009c04, 0xff55ff55},
+ {0x00009c08, 0x0320ff55},
+ {0x00009e50, 0x00000000},
+ {0x00009fcc, 0x00000014},
+ {0x0000a344, 0x00000010},
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x71733d01},
+ {0x0000a3a0, 0xd0ad5c12},
+ {0x0000a3c0, 0x22222220},
+ {0x0000a3c4, 0x22222222},
+ {0x0000a404, 0x00418a11},
+ {0x0000a418, 0x050001ce},
+ {0x0000a438, 0x00001800},
+ {0x0000a458, 0x01444452},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a690, 0x00000038},
+};
+
+static const u32 ar9462_1p0_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73f00000},
+ {0x0001600c, 0x00000000},
+ {0x00016010, 0x6d820001},
+ {0x00016040, 0x7f80fff8},
+ {0x0001604c, 0x2699e04f},
+ {0x00016050, 0x6db6db6c},
+ {0x00016054, 0x6db60000},
+ {0x00016058, 0x6c200000},
+ {0x00016080, 0x00040000},
+ {0x00016084, 0x9a68048c},
+ {0x00016088, 0x54214514},
+ {0x0001608c, 0x12030409},
+ {0x00016090, 0x24926490},
+ {0x00016098, 0xd2888888},
+ {0x000160a0, 0x0a108ffe},
+ {0x000160a4, 0x812fc490},
+ {0x000160a8, 0x423c8000},
+ {0x000160b4, 0x92000000},
+ {0x000160b8, 0x0285dddc},
+ {0x000160bc, 0x02908888},
+ {0x000160c0, 0x00adb6d0},
+ {0x000160c4, 0x6db6db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x0de6c1b0},
+ {0x00016100, 0x3fffbe04},
+ {0x00016104, 0xfff80000},
+ {0x00016108, 0x00200400},
+ {0x00016110, 0x00000000},
+ {0x00016144, 0x02084080},
+ {0x00016148, 0x000080c0},
+ {0x00016280, 0x050a0001},
+ {0x00016284, 0x3d841400},
+ {0x00016288, 0x00000000},
+ {0x0001628c, 0xe3000000},
+ {0x00016290, 0xa1005080},
+ {0x00016294, 0x00000020},
+ {0x00016298, 0x50a02900},
+ {0x00016340, 0x121e4276},
+ {0x00016344, 0x00300000},
+ {0x00016400, 0x36db6db6},
+ {0x00016404, 0x6db6db40},
+ {0x00016408, 0x73f00000},
+ {0x0001640c, 0x00000000},
+ {0x00016410, 0x6c800001},
+ {0x00016440, 0x7f80fff8},
+ {0x0001644c, 0x4699e04f},
+ {0x00016450, 0x6db6db6c},
+ {0x00016454, 0x6db60000},
+ {0x00016500, 0x3fffbe04},
+ {0x00016504, 0xfff80000},
+ {0x00016508, 0x00200400},
+ {0x00016510, 0x00000000},
+ {0x00016544, 0x02084080},
+ {0x00016548, 0x000080c0},
+};
+
+static const u32 ar9462_1p0_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+};
+
+static const u32 ar9462_1p0_sys2ant[][2] = {
+ /* Addr allmodes */
+ {0x00063120, 0x00801980},
+};
+
+#endif /* INITVALS_9462_1P0_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
new file mode 100644
index 000000000000..9c51b395b4ff
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
@@ -0,0 +1,1928 @@
+/*
+ * Copyright (c) 2010 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9462_2P0_H
+#define INITVALS_9462_2P0_H
+
+/* AR9462 2.0 */
+
+static const u32 ar9462_modes_fast_clock_2p0[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00001030, 0x00000268, 0x000004d0},
+ {0x00001070, 0x0000018c, 0x00000318},
+ {0x000010b0, 0x00000fd0, 0x00001fa0},
+ {0x00008014, 0x044c044c, 0x08980898},
+ {0x0000801c, 0x148ec02b, 0x148ec057},
+ {0x00008318, 0x000044c0, 0x00008980},
+ {0x00009e00, 0x0372131c, 0x0372131c},
+ {0x0000a230, 0x0000400b, 0x00004016},
+ {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x18253ede},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0003580c},
+};
+
+static const u32 ar9462_2p0_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+ {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+ {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+ {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+ {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3039605e, 0x33795d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+ {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c782},
+ {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f},
+ {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+ {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+ {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+ {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+ {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
+};
+
+static const u32 ar9462_2p0_mac_core_emulation[][2] = {
+ /* Addr allmodes */
+ {0x00000030, 0x000e0085},
+ {0x00000044, 0x00000008},
+ {0x0000805c, 0xffffc7ff},
+ {0x00008344, 0xaa4a105b},
+};
+
+static const u32 ar9462_common_rx_gain_table_2p0[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x01910190},
+ {0x0000a030, 0x01930192},
+ {0x0000a034, 0x01950194},
+ {0x0000a038, 0x038a0196},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x22222229},
+ {0x0000a084, 0x1d1d1d1d},
+ {0x0000a088, 0x1d1d1d1d},
+ {0x0000a08c, 0x1d1d1d1d},
+ {0x0000a090, 0x171d1d1d},
+ {0x0000a094, 0x11111717},
+ {0x0000a098, 0x00030311},
+ {0x0000a09c, 0x00000000},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x2a2d2f32},
+ {0x0000b084, 0x21232328},
+ {0x0000b088, 0x19191c1e},
+ {0x0000b08c, 0x12141417},
+ {0x0000b090, 0x07070e0e},
+ {0x0000b094, 0x03030305},
+ {0x0000b098, 0x00000003},
+ {0x0000b09c, 0x00000000},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x18213ede},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0003580c},
+};
+
+static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = {
+ /* Addr allmodes */
+ {0x00018c00, 0x18212ede},
+ {0x00018c04, 0x000801d8},
+ {0x00018c08, 0x0003580c},
+};
+
+static const u32 ar9462_2p0_sys3ant[][2] = {
+ /* Addr allmodes */
+ {0x00063280, 0x00040807},
+ {0x00063284, 0x104ccccc},
+};
+
+static const u32 ar9462_common_rx_gain_table_ar9280_2p0[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x02000101},
+ {0x0000a004, 0x02000102},
+ {0x0000a008, 0x02000103},
+ {0x0000a00c, 0x02000104},
+ {0x0000a010, 0x02000200},
+ {0x0000a014, 0x02000201},
+ {0x0000a018, 0x02000202},
+ {0x0000a01c, 0x02000203},
+ {0x0000a020, 0x02000204},
+ {0x0000a024, 0x02000205},
+ {0x0000a028, 0x02000208},
+ {0x0000a02c, 0x02000302},
+ {0x0000a030, 0x02000303},
+ {0x0000a034, 0x02000304},
+ {0x0000a038, 0x02000400},
+ {0x0000a03c, 0x02010300},
+ {0x0000a040, 0x02010301},
+ {0x0000a044, 0x02010302},
+ {0x0000a048, 0x02000500},
+ {0x0000a04c, 0x02010400},
+ {0x0000a050, 0x02020300},
+ {0x0000a054, 0x02020301},
+ {0x0000a058, 0x02020302},
+ {0x0000a05c, 0x02020303},
+ {0x0000a060, 0x02020400},
+ {0x0000a064, 0x02030300},
+ {0x0000a068, 0x02030301},
+ {0x0000a06c, 0x02030302},
+ {0x0000a070, 0x02030303},
+ {0x0000a074, 0x02030400},
+ {0x0000a078, 0x02040300},
+ {0x0000a07c, 0x02040301},
+ {0x0000a080, 0x02040302},
+ {0x0000a084, 0x02040303},
+ {0x0000a088, 0x02030500},
+ {0x0000a08c, 0x02040400},
+ {0x0000a090, 0x02050203},
+ {0x0000a094, 0x02050204},
+ {0x0000a098, 0x02050205},
+ {0x0000a09c, 0x02040500},
+ {0x0000a0a0, 0x02050301},
+ {0x0000a0a4, 0x02050302},
+ {0x0000a0a8, 0x02050303},
+ {0x0000a0ac, 0x02050400},
+ {0x0000a0b0, 0x02050401},
+ {0x0000a0b4, 0x02050402},
+ {0x0000a0b8, 0x02050403},
+ {0x0000a0bc, 0x02050500},
+ {0x0000a0c0, 0x02050501},
+ {0x0000a0c4, 0x02050502},
+ {0x0000a0c8, 0x02050503},
+ {0x0000a0cc, 0x02050504},
+ {0x0000a0d0, 0x02050600},
+ {0x0000a0d4, 0x02050601},
+ {0x0000a0d8, 0x02050602},
+ {0x0000a0dc, 0x02050603},
+ {0x0000a0e0, 0x02050604},
+ {0x0000a0e4, 0x02050700},
+ {0x0000a0e8, 0x02050701},
+ {0x0000a0ec, 0x02050702},
+ {0x0000a0f0, 0x02050703},
+ {0x0000a0f4, 0x02050704},
+ {0x0000a0f8, 0x02050705},
+ {0x0000a0fc, 0x02050708},
+ {0x0000a100, 0x02050709},
+ {0x0000a104, 0x0205070a},
+ {0x0000a108, 0x0205070b},
+ {0x0000a10c, 0x0205070c},
+ {0x0000a110, 0x0205070d},
+ {0x0000a114, 0x02050710},
+ {0x0000a118, 0x02050711},
+ {0x0000a11c, 0x02050712},
+ {0x0000a120, 0x02050713},
+ {0x0000a124, 0x02050714},
+ {0x0000a128, 0x02050715},
+ {0x0000a12c, 0x02050730},
+ {0x0000a130, 0x02050731},
+ {0x0000a134, 0x02050732},
+ {0x0000a138, 0x02050733},
+ {0x0000a13c, 0x02050734},
+ {0x0000a140, 0x02050735},
+ {0x0000a144, 0x02050750},
+ {0x0000a148, 0x02050751},
+ {0x0000a14c, 0x02050752},
+ {0x0000a150, 0x02050753},
+ {0x0000a154, 0x02050754},
+ {0x0000a158, 0x02050755},
+ {0x0000a15c, 0x02050770},
+ {0x0000a160, 0x02050771},
+ {0x0000a164, 0x02050772},
+ {0x0000a168, 0x02050773},
+ {0x0000a16c, 0x02050774},
+ {0x0000a170, 0x02050775},
+ {0x0000a174, 0x00000776},
+ {0x0000a178, 0x00000776},
+ {0x0000a17c, 0x00000776},
+ {0x0000a180, 0x00000776},
+ {0x0000a184, 0x00000776},
+ {0x0000a188, 0x00000776},
+ {0x0000a18c, 0x00000776},
+ {0x0000a190, 0x00000776},
+ {0x0000a194, 0x00000776},
+ {0x0000a198, 0x00000776},
+ {0x0000a19c, 0x00000776},
+ {0x0000a1a0, 0x00000776},
+ {0x0000a1a4, 0x00000776},
+ {0x0000a1a8, 0x00000776},
+ {0x0000a1ac, 0x00000776},
+ {0x0000a1b0, 0x00000776},
+ {0x0000a1b4, 0x00000776},
+ {0x0000a1b8, 0x00000776},
+ {0x0000a1bc, 0x00000776},
+ {0x0000a1c0, 0x00000776},
+ {0x0000a1c4, 0x00000776},
+ {0x0000a1c8, 0x00000776},
+ {0x0000a1cc, 0x00000776},
+ {0x0000a1d0, 0x00000776},
+ {0x0000a1d4, 0x00000776},
+ {0x0000a1d8, 0x00000776},
+ {0x0000a1dc, 0x00000776},
+ {0x0000a1e0, 0x00000776},
+ {0x0000a1e4, 0x00000776},
+ {0x0000a1e8, 0x00000776},
+ {0x0000a1ec, 0x00000776},
+ {0x0000a1f0, 0x00000776},
+ {0x0000a1f4, 0x00000776},
+ {0x0000a1f8, 0x00000776},
+ {0x0000a1fc, 0x00000776},
+ {0x0000b000, 0x02000101},
+ {0x0000b004, 0x02000102},
+ {0x0000b008, 0x02000103},
+ {0x0000b00c, 0x02000104},
+ {0x0000b010, 0x02000200},
+ {0x0000b014, 0x02000201},
+ {0x0000b018, 0x02000202},
+ {0x0000b01c, 0x02000203},
+ {0x0000b020, 0x02000204},
+ {0x0000b024, 0x02000205},
+ {0x0000b028, 0x02000208},
+ {0x0000b02c, 0x02000302},
+ {0x0000b030, 0x02000303},
+ {0x0000b034, 0x02000304},
+ {0x0000b038, 0x02000400},
+ {0x0000b03c, 0x02010300},
+ {0x0000b040, 0x02010301},
+ {0x0000b044, 0x02010302},
+ {0x0000b048, 0x02000500},
+ {0x0000b04c, 0x02010400},
+ {0x0000b050, 0x02020300},
+ {0x0000b054, 0x02020301},
+ {0x0000b058, 0x02020302},
+ {0x0000b05c, 0x02020303},
+ {0x0000b060, 0x02020400},
+ {0x0000b064, 0x02030300},
+ {0x0000b068, 0x02030301},
+ {0x0000b06c, 0x02030302},
+ {0x0000b070, 0x02030303},
+ {0x0000b074, 0x02030400},
+ {0x0000b078, 0x02040300},
+ {0x0000b07c, 0x02040301},
+ {0x0000b080, 0x02040302},
+ {0x0000b084, 0x02040303},
+ {0x0000b088, 0x02030500},
+ {0x0000b08c, 0x02040400},
+ {0x0000b090, 0x02050203},
+ {0x0000b094, 0x02050204},
+ {0x0000b098, 0x02050205},
+ {0x0000b09c, 0x02040500},
+ {0x0000b0a0, 0x02050301},
+ {0x0000b0a4, 0x02050302},
+ {0x0000b0a8, 0x02050303},
+ {0x0000b0ac, 0x02050400},
+ {0x0000b0b0, 0x02050401},
+ {0x0000b0b4, 0x02050402},
+ {0x0000b0b8, 0x02050403},
+ {0x0000b0bc, 0x02050500},
+ {0x0000b0c0, 0x02050501},
+ {0x0000b0c4, 0x02050502},
+ {0x0000b0c8, 0x02050503},
+ {0x0000b0cc, 0x02050504},
+ {0x0000b0d0, 0x02050600},
+ {0x0000b0d4, 0x02050601},
+ {0x0000b0d8, 0x02050602},
+ {0x0000b0dc, 0x02050603},
+ {0x0000b0e0, 0x02050604},
+ {0x0000b0e4, 0x02050700},
+ {0x0000b0e8, 0x02050701},
+ {0x0000b0ec, 0x02050702},
+ {0x0000b0f0, 0x02050703},
+ {0x0000b0f4, 0x02050704},
+ {0x0000b0f8, 0x02050705},
+ {0x0000b0fc, 0x02050708},
+ {0x0000b100, 0x02050709},
+ {0x0000b104, 0x0205070a},
+ {0x0000b108, 0x0205070b},
+ {0x0000b10c, 0x0205070c},
+ {0x0000b110, 0x0205070d},
+ {0x0000b114, 0x02050710},
+ {0x0000b118, 0x02050711},
+ {0x0000b11c, 0x02050712},
+ {0x0000b120, 0x02050713},
+ {0x0000b124, 0x02050714},
+ {0x0000b128, 0x02050715},
+ {0x0000b12c, 0x02050730},
+ {0x0000b130, 0x02050731},
+ {0x0000b134, 0x02050732},
+ {0x0000b138, 0x02050733},
+ {0x0000b13c, 0x02050734},
+ {0x0000b140, 0x02050735},
+ {0x0000b144, 0x02050750},
+ {0x0000b148, 0x02050751},
+ {0x0000b14c, 0x02050752},
+ {0x0000b150, 0x02050753},
+ {0x0000b154, 0x02050754},
+ {0x0000b158, 0x02050755},
+ {0x0000b15c, 0x02050770},
+ {0x0000b160, 0x02050771},
+ {0x0000b164, 0x02050772},
+ {0x0000b168, 0x02050773},
+ {0x0000b16c, 0x02050774},
+ {0x0000b170, 0x02050775},
+ {0x0000b174, 0x00000776},
+ {0x0000b178, 0x00000776},
+ {0x0000b17c, 0x00000776},
+ {0x0000b180, 0x00000776},
+ {0x0000b184, 0x00000776},
+ {0x0000b188, 0x00000776},
+ {0x0000b18c, 0x00000776},
+ {0x0000b190, 0x00000776},
+ {0x0000b194, 0x00000776},
+ {0x0000b198, 0x00000776},
+ {0x0000b19c, 0x00000776},
+ {0x0000b1a0, 0x00000776},
+ {0x0000b1a4, 0x00000776},
+ {0x0000b1a8, 0x00000776},
+ {0x0000b1ac, 0x00000776},
+ {0x0000b1b0, 0x00000776},
+ {0x0000b1b4, 0x00000776},
+ {0x0000b1b8, 0x00000776},
+ {0x0000b1bc, 0x00000776},
+ {0x0000b1c0, 0x00000776},
+ {0x0000b1c4, 0x00000776},
+ {0x0000b1c8, 0x00000776},
+ {0x0000b1cc, 0x00000776},
+ {0x0000b1d0, 0x00000776},
+ {0x0000b1d4, 0x00000776},
+ {0x0000b1d8, 0x00000776},
+ {0x0000b1dc, 0x00000776},
+ {0x0000b1e0, 0x00000776},
+ {0x0000b1e4, 0x00000776},
+ {0x0000b1e8, 0x00000776},
+ {0x0000b1ec, 0x00000776},
+ {0x0000b1f0, 0x00000776},
+ {0x0000b1f4, 0x00000776},
+ {0x0000b1f8, 0x00000776},
+ {0x0000b1fc, 0x00000776},
+};
+
+static const u32 ar9200_ar9280_2p0_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00007800, 0x00040000},
+ {0x00007804, 0xdb005012},
+ {0x00007808, 0x04924914},
+ {0x0000780c, 0x21084210},
+ {0x00007810, 0x6d801300},
+ {0x00007814, 0x0019beff},
+ {0x00007818, 0x07e41000},
+ {0x0000781c, 0x00392000},
+ {0x00007820, 0x92592480},
+ {0x00007824, 0x00040000},
+ {0x00007828, 0xdb005012},
+ {0x0000782c, 0x04924914},
+ {0x00007830, 0x21084210},
+ {0x00007834, 0x6d801300},
+ {0x00007838, 0x0019beff},
+ {0x0000783c, 0x07e40000},
+ {0x00007840, 0x00392000},
+ {0x00007844, 0x92592480},
+ {0x00007848, 0x00100000},
+ {0x0000784c, 0x773f0567},
+ {0x00007850, 0x54214514},
+ {0x00007854, 0x12035828},
+ {0x00007858, 0x92592692},
+ {0x0000785c, 0x00000000},
+ {0x00007860, 0x56400000},
+ {0x00007864, 0x0a8e370e},
+ {0x00007868, 0xc0102850},
+ {0x0000786c, 0x812d4000},
+ {0x00007870, 0x807ec400},
+ {0x00007874, 0x001b6db0},
+ {0x00007878, 0x00376b63},
+ {0x0000787c, 0x06db6db6},
+ {0x00007880, 0x006d8000},
+ {0x00007884, 0xffeffffe},
+ {0x00007888, 0xffeffffe},
+ {0x0000788c, 0x00010000},
+ {0x00007890, 0x02060aeb},
+ {0x00007894, 0x5a108000},
+};
+
+static const u32 ar9462_2p0_mac_postamble_emulation[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00008014, 0x10f810f8, 0x10f810f8, 0x10f810f8, 0x10f810f8},
+ {0x0000801c, 0x0e8d8017, 0x0e8d8017, 0x0e8d8017, 0x0e8d8017},
+};
+
+static const u32 ar9462_2p0_radio_postamble_sys3ant[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
+ {0x00016140, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
+ {0x00016540, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
+};
+
+static const u32 ar9462_2p0_baseband_postamble_emulation[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e3c, 0xcf946221, 0xcf946221, 0xcf946221, 0xcf946221},
+ {0x00009e44, 0xfc5c0000, 0xfc5c0000, 0xfc5c0000, 0xfc5c0000},
+ {0x0000a258, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+ {0x0000a25c, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a28c, 0x00011111, 0x00011111, 0x00011111, 0x00011111},
+ {0x0000a2c4, 0x00148d18, 0x00148d18, 0x00148d20, 0x00148d20},
+ {0x0000a2d8, 0xf999a800, 0xf999a800, 0xf999a80c, 0xf999a80c},
+ {0x0000a50c, 0x0000c00a, 0x0000c00a, 0x0000c00a, 0x0000c00a},
+ {0x0000a538, 0x00038e8c, 0x00038e8c, 0x00038e8c, 0x00038e8c},
+ {0x0000a53c, 0x0003cecc, 0x0003cecc, 0x0003cecc, 0x0003cecc},
+ {0x0000a540, 0x00040ed4, 0x00040ed4, 0x00040ed4, 0x00040ed4},
+ {0x0000a544, 0x00044edc, 0x00044edc, 0x00044edc, 0x00044edc},
+ {0x0000a548, 0x00048ede, 0x00048ede, 0x00048ede, 0x00048ede},
+ {0x0000a54c, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e},
+ {0x0000a550, 0x00050f5e, 0x00050f5e, 0x00050f5e, 0x00050f5e},
+ {0x0000a554, 0x00054f9e, 0x00054f9e, 0x00054f9e, 0x00054f9e},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
+ {0x00016140, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
+ {0x00016540, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
+};
+
+static const u32 ar9462_common_wo_xlna_rx_gain_table_2p0[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x03820190},
+ {0x0000a030, 0x03840383},
+ {0x0000a034, 0x03880385},
+ {0x0000a038, 0x038a0389},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x29292929},
+ {0x0000a084, 0x29292929},
+ {0x0000a088, 0x29292929},
+ {0x0000a08c, 0x29292929},
+ {0x0000a090, 0x22292929},
+ {0x0000a094, 0x1d1d2222},
+ {0x0000a098, 0x0c111117},
+ {0x0000a09c, 0x00030303},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x32323232},
+ {0x0000b084, 0x2f2f3232},
+ {0x0000b088, 0x23282a2d},
+ {0x0000b08c, 0x1c1e2123},
+ {0x0000b090, 0x14171919},
+ {0x0000b094, 0x0e0e1214},
+ {0x0000b098, 0x03050707},
+ {0x0000b09c, 0x00030303},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9462_2p0_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9462_modes_low_ob_db_tx_gain_table_2p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+ {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
+ {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+ {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+ {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+ {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+ {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+ {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+ {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060},
+ {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+ {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+ {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000},
+ {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+};
+
+static const u32 ar9462_2p0_soc_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00002233, 0x00002233, 0x00002233, 0x00002233},
+};
+
+static const u32 ar9462_2p0_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a9f6b},
+ {0x0000980c, 0x04900000},
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x6400a290},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x0d000600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x32440bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098e4, 0x01ffffff},
+ {0x000098e8, 0x01ffffff},
+ {0x000098ec, 0x01ffffff},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009bf0, 0x80000000},
+ {0x00009c04, 0xff55ff55},
+ {0x00009c08, 0x0320ff55},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x9883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c0040b},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038230c},
+ {0x00009e24, 0x990bb515},
+ {0x00009e28, 0x0c6f0000},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009e54, 0xe4c355c7},
+ {0x00009e58, 0xfd897735},
+ {0x00009e5c, 0xe9198724},
+ {0x00009fc0, 0x803e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x00009fd0, 0x01193b93},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0xaaaaaaaa},
+ {0x0000a3ac, 0x3c466478},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000006},
+ {0x0000a3f8, 0x0c9bd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce739ce},
+ {0x0000a418, 0x2d001dce},
+ {0x0000a41c, 0x1ce739ce},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce739ce},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00100000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x05000080},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a454, 0x07000000},
+ {0x0000a644, 0xbfad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00002037},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x00000838},
+ {0x0000a6b0, 0x0000000a},
+ {0x0000a6b4, 0x00512c01},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000001},
+ {0x0000a7f0, 0x80000000},
+ {0x0000a8d0, 0x004b6a8e},
+ {0x0000a8d4, 0x00000820},
+ {0x0000a8dc, 0x00000000},
+ {0x0000a8f0, 0x00000000},
+ {0x0000a8f4, 0x00000000},
+ {0x0000abf0, 0x80000000},
+ {0x0000b2d0, 0x00000080},
+ {0x0000b2d4, 0x00000000},
+ {0x0000b2ec, 0x00000000},
+ {0x0000b2f0, 0x00000000},
+ {0x0000b2f4, 0x00000000},
+ {0x0000b2f8, 0x00000000},
+ {0x0000b408, 0x0e79e5c0},
+ {0x0000b40c, 0x00820820},
+ {0x0000b420, 0x00000000},
+ {0x0000b6b0, 0x0000000a},
+ {0x0000b6b4, 0x00000001},
+};
+
+static const u32 ar9462_2p0_radio_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524},
+ {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70},
+ {0x0001610c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
+ {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
+};
+
+static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+ {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
+ {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
+ {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
+ {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+ {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060},
+ {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+ {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+ {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000},
+ {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+};
+
+static const u32 ar9462_2p0_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73f00000},
+ {0x0001600c, 0x00000000},
+ {0x00016010, 0x6d820001},
+ {0x00016040, 0x7f80fff8},
+ {0x0001604c, 0x2699e04f},
+ {0x00016050, 0x6db6db6c},
+ {0x00016058, 0x6c200000},
+ {0x00016080, 0x00040000},
+ {0x00016084, 0x9a68048c},
+ {0x00016088, 0x54214514},
+ {0x0001608c, 0x1203040b},
+ {0x00016090, 0x24926490},
+ {0x00016098, 0xd2888888},
+ {0x000160a0, 0x0a108ffe},
+ {0x000160a4, 0x812fc491},
+ {0x000160a8, 0x423c8000},
+ {0x000160b4, 0x92000000},
+ {0x000160b8, 0x0285dddc},
+ {0x000160bc, 0x02908888},
+ {0x000160c0, 0x00adb6d0},
+ {0x000160c4, 0x6db6db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x0de6c1b0},
+ {0x00016100, 0x3fffbe04},
+ {0x00016104, 0xfff80000},
+ {0x00016108, 0x00200400},
+ {0x00016110, 0x00000000},
+ {0x00016144, 0x02084080},
+ {0x00016148, 0x000080c0},
+ {0x00016280, 0x050a0001},
+ {0x00016284, 0x3d841400},
+ {0x00016288, 0x00000000},
+ {0x0001628c, 0xe3000000},
+ {0x00016290, 0xa1005080},
+ {0x00016294, 0x00000020},
+ {0x00016298, 0x54a82900},
+ {0x00016340, 0x121e4276},
+ {0x00016344, 0x00300000},
+ {0x00016400, 0x36db6db6},
+ {0x00016404, 0x6db6db40},
+ {0x00016408, 0x73f00000},
+ {0x0001640c, 0x00000000},
+ {0x00016410, 0x6c800001},
+ {0x00016440, 0x7f80fff8},
+ {0x0001644c, 0x4699e04f},
+ {0x00016450, 0x6db6db6c},
+ {0x00016500, 0x3fffbe04},
+ {0x00016504, 0xfff80000},
+ {0x00016508, 0x00200400},
+ {0x00016510, 0x00000000},
+ {0x00016544, 0x02084080},
+ {0x00016548, 0x000080c0},
+};
+
+static const u32 ar9462_2p0_tx_gain_table_baseband_postamble_emulation[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a410, 0x000000d5, 0x000000d5, 0x000000d5, 0x000000d5},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x00004002, 0x00004002, 0x00004002, 0x00004002},
+ {0x0000a508, 0x00008004, 0x00008004, 0x00008004, 0x00008004},
+ {0x0000a510, 0x0001000c, 0x0001000c, 0x0001000c, 0x0001000c},
+ {0x0000a514, 0x0001420b, 0x0001420b, 0x0001420b, 0x0001420b},
+ {0x0000a518, 0x0001824a, 0x0001824a, 0x0001824a, 0x0001824a},
+ {0x0000a51c, 0x0001c44a, 0x0001c44a, 0x0001c44a, 0x0001c44a},
+ {0x0000a520, 0x0002064a, 0x0002064a, 0x0002064a, 0x0002064a},
+ {0x0000a524, 0x0002484a, 0x0002484a, 0x0002484a, 0x0002484a},
+ {0x0000a528, 0x00028a4a, 0x00028a4a, 0x00028a4a, 0x00028a4a},
+ {0x0000a52c, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a},
+ {0x0000a530, 0x00030e4a, 0x00030e4a, 0x00030e4a, 0x00030e4a},
+ {0x0000a534, 0x00034e8a, 0x00034e8a, 0x00034e8a, 0x00034e8a},
+};
+
+static const u32 ar9462_2p0_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+};
+
+static const u32 ar9462_2p0_sys2ant[][2] = {
+ /* Addr allmodes */
+ {0x00063120, 0x00801980},
+};
+
+static const u32 ar9462_2p0_mac_core[][2] = {
+ /* Addr allmodes */
+ {0x00000008, 0x00000000},
+ {0x00000030, 0x000e0085},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000000},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x000010f0, 0x00000100},
+ {0x00001270, 0x00000000},
+ {0x000012b0, 0x00000000},
+ {0x000012f0, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00001810, 0x0f000003},
+ {0x00008000, 0x00000000},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000000},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00080000},
+ {0x00008040, 0x00000000},
+ {0x00008044, 0x00000000},
+ {0x00008048, 0x00000000},
+ {0x0000804c, 0xffffffff},
+ {0x00008050, 0xffffffff},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000310},
+ {0x00008074, 0x00000020},
+ {0x00008078, 0x00000000},
+ {0x0000809c, 0x0000000f},
+ {0x000080a0, 0x00000000},
+ {0x000080a4, 0x02ff0000},
+ {0x000080a8, 0x0e070605},
+ {0x000080ac, 0x0000000d},
+ {0x000080b0, 0x00000000},
+ {0x000080b4, 0x00000000},
+ {0x000080b8, 0x00000000},
+ {0x000080bc, 0x00000000},
+ {0x000080c0, 0x2a800000},
+ {0x000080c4, 0x06900168},
+ {0x000080c8, 0x13881c20},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00252500},
+ {0x000080d4, 0x00b00005},
+ {0x000080d8, 0x00400002},
+ {0x000080dc, 0x00000000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x3f3f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00000000},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000000},
+ {0x00008114, 0x000007ff},
+ {0x00008118, 0x000000aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x0000ffff},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x00008170, 0x18486e00},
+ {0x00008174, 0x33332210},
+ {0x00008178, 0x00000000},
+ {0x0000817c, 0x00020000},
+ {0x000081c4, 0x33332210},
+ {0x000081c8, 0x00000000},
+ {0x000081cc, 0x00000000},
+ {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000800},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x40000000},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x99c00010},
+ {0x00008268, 0xffffffff},
+ {0x0000826c, 0x0000ffff},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000004},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x000000ff},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000140},
+ {0x00008314, 0x00000000},
+ {0x0000831c, 0x0000010d},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x0000001f},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000700},
+ {0x00008338, 0xffff0000},
+ {0x0000833c, 0x02400000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0xaa48105b},
+ {0x00008348, 0x008f0000},
+ {0x0000835c, 0x00000000},
+ {0x00008360, 0xffffffff},
+ {0x00008364, 0xffffffff},
+ {0x00008368, 0x00000000},
+ {0x00008370, 0x00000000},
+ {0x00008374, 0x000000ff},
+ {0x00008378, 0x00000000},
+ {0x0000837c, 0x00000000},
+ {0x00008380, 0xffffffff},
+ {0x00008384, 0xffffffff},
+ {0x00008390, 0xffffffff},
+ {0x00008394, 0xffffffff},
+ {0x00008398, 0x00000000},
+ {0x0000839c, 0x00000000},
+ {0x000083a4, 0x0000fa14},
+ {0x000083a8, 0x000f0c00},
+ {0x000083ac, 0x33332210},
+ {0x000083b0, 0x33332210},
+ {0x000083b4, 0x33332210},
+ {0x000083b8, 0x33332210},
+ {0x000083bc, 0x00000000},
+ {0x000083c0, 0x00000000},
+ {0x000083c4, 0x00000000},
+ {0x000083c8, 0x00000000},
+ {0x000083cc, 0x00000200},
+ {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9462_2p0_mac_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9462_common_mixed_rx_gain_table_2p0[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x03820190},
+ {0x0000a030, 0x03840383},
+ {0x0000a034, 0x03880385},
+ {0x0000a038, 0x038a0389},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x29292929},
+ {0x0000a084, 0x29292929},
+ {0x0000a088, 0x29292929},
+ {0x0000a08c, 0x29292929},
+ {0x0000a090, 0x22292929},
+ {0x0000a094, 0x1d1d2222},
+ {0x0000a098, 0x0c111117},
+ {0x0000a09c, 0x00030303},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x2a2d2f32},
+ {0x0000b084, 0x21232328},
+ {0x0000b088, 0x19191c1e},
+ {0x0000b08c, 0x12141417},
+ {0x0000b090, 0x07070e0e},
+ {0x0000b094, 0x03030305},
+ {0x0000b098, 0x00000003},
+ {0x0000b09c, 0x00000000},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9462_modes_green_ob_db_tx_gain_table_2p0[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
+ {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
+ {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
+ {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
+ {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+ {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060},
+ {0x00016054, 0x6db60180, 0x6db60180, 0x6db60180, 0x6db60180},
+ {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+ {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000},
+ {0x00016454, 0x6db60180, 0x6db60180, 0x6db60180, 0x6db60180},
+};
+
+static const u32 ar9462_2p0_BTCOEX_MAX_TXPWR_table[][2] = {
+ /* Addr allmodes */
+ {0x000018c0, 0x10101010},
+ {0x000018c4, 0x10101010},
+ {0x000018c8, 0x10101010},
+ {0x000018cc, 0x10101010},
+ {0x000018d0, 0x10101010},
+ {0x000018d4, 0x10101010},
+ {0x000018d8, 0x10101010},
+ {0x000018dc, 0x10101010},
+};
+
+static const u32 ar9462_2p0_baseband_core_emulation[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafa68e30},
+ {0x00009884, 0x00002842},
+ {0x00009c04, 0xff55ff55},
+ {0x00009c08, 0x0320ff55},
+ {0x00009e50, 0x00000000},
+ {0x00009fcc, 0x00000014},
+ {0x0000a344, 0x00000010},
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x71733d01},
+ {0x0000a3a0, 0xd0ad5c12},
+ {0x0000a3c0, 0x22222220},
+ {0x0000a3c4, 0x22222222},
+ {0x0000a404, 0x00418a11},
+ {0x0000a418, 0x050001ce},
+ {0x0000a438, 0x00001800},
+ {0x0000a458, 0x01444452},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a690, 0x00000038},
+};
+
+#endif /* INITVALS_9462_2P0_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
new file mode 100644
index 000000000000..06b3f0df9fad
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
@@ -0,0 +1,1673 @@
+/*
+ * Copyright (c) 2010 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9580_1P0_H
+#define INITVALS_9580_1P0_H
+
+/* AR9580 1.0 */
+
+static const u32 ar9580_1p0_modes_fast_clock[][3] = {
+ /* Addr 5G_HT20 5G_HT40 */
+ {0x00001030, 0x00000268, 0x000004d0},
+ {0x00001070, 0x0000018c, 0x00000318},
+ {0x000010b0, 0x00000fd0, 0x00001fa0},
+ {0x00008014, 0x044c044c, 0x08980898},
+ {0x0000801c, 0x148ec02b, 0x148ec057},
+ {0x00008318, 0x000044c0, 0x00008980},
+ {0x00009e00, 0x0372131c, 0x0372131c},
+ {0x0000a230, 0x0000000b, 0x00000016},
+ {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9580_1p0_radio_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31},
+ {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
+ {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
+ {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+ {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+ {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+};
+
+static const u32 ar9580_1p0_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a9f6b},
+ {0x0000980c, 0x04900000},
+ {0x00009814, 0x3280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x6400a290},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x0d000600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x32840bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0xff55ff55},
+ {0x00009c08, 0x0320ff55},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x9883800a},
+ {0x00009d10, 0x01834061},
+ {0x00009d14, 0x00c0040b},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038230c},
+ {0x00009e24, 0x990bb515},
+ {0x00009e28, 0x0c6f0000},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009e54, 0x00000000},
+ {0x00009fc0, 0x803e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x00009fd0, 0x01193b93},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+ {0x0000a2c0, 0x00000001},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {0x0000a3a4, 0x00000000},
+ {0x0000a3a8, 0xaaaaaaaa},
+ {0x0000a3ac, 0x3c466478},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000000},
+ {0x0000a3f8, 0x0c9bd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce739ce},
+ {0x0000a418, 0x2d001dce},
+ {0x0000a41c, 0x1ce739ce},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce739ce},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00100000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x05000080},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+ {0x0000a640, 0x00000000},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x00000838},
+ {0x0000a7c0, 0x00000000},
+ {0x0000a7c4, 0xfffffffc},
+ {0x0000a7c8, 0x00000000},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000000},
+ {0x0000a8d0, 0x004b6a8e},
+ {0x0000a8d4, 0x00000820},
+ {0x0000a8dc, 0x00000000},
+ {0x0000a8f0, 0x00000000},
+ {0x0000a8f4, 0x00000000},
+ {0x0000b2d0, 0x00000080},
+ {0x0000b2d4, 0x00000000},
+ {0x0000b2ec, 0x00000000},
+ {0x0000b2f0, 0x00000000},
+ {0x0000b2f4, 0x00000000},
+ {0x0000b2f8, 0x00000000},
+ {0x0000b408, 0x0e79e5c0},
+ {0x0000b40c, 0x00820820},
+ {0x0000b420, 0x00000000},
+ {0x0000b8d0, 0x004b6a8e},
+ {0x0000b8d4, 0x00000820},
+ {0x0000b8dc, 0x00000000},
+ {0x0000b8f0, 0x00000000},
+ {0x0000b8f4, 0x00000000},
+ {0x0000c2d0, 0x00000080},
+ {0x0000c2d4, 0x00000000},
+ {0x0000c2ec, 0x00000000},
+ {0x0000c2f0, 0x00000000},
+ {0x0000c2f4, 0x00000000},
+ {0x0000c2f8, 0x00000000},
+ {0x0000c408, 0x0e79e5c0},
+ {0x0000c40c, 0x00820820},
+ {0x0000c420, 0x00000000},
+};
+
+static const u32 ar9580_1p0_mac_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 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, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x7702b08c, 0x7702b08c, 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, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
+ {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
+ {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
+ {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
+ {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
+ {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
+ {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
+ {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
+ {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9580_1p0_high_power_tx_gain_table[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 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, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x7702b08c, 0x7702b08c, 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, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
+ {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
+ {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
+ {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
+ {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
+ {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
+ {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
+ {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
+ {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 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, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+ {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+ {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
+ {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
+ {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
+ {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
+ {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
+ {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+ {0x0000a57c, 0x7702b08c, 0x7702b08c, 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, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
+ {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
+ {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
+ {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
+ {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
+ {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
+ {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
+ {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
+ {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {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, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+ {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+ {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9580_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9580_1p0_mac_core[][2] = {
+ /* Addr allmodes */
+ {0x00000008, 0x00000000},
+ {0x00000030, 0x00020085},
+ {0x00000034, 0x00000005},
+ {0x00000040, 0x00000000},
+ {0x00000044, 0x00000000},
+ {0x00000048, 0x00000008},
+ {0x0000004c, 0x00000010},
+ {0x00000050, 0x00000000},
+ {0x00001040, 0x002ffc0f},
+ {0x00001044, 0x002ffc0f},
+ {0x00001048, 0x002ffc0f},
+ {0x0000104c, 0x002ffc0f},
+ {0x00001050, 0x002ffc0f},
+ {0x00001054, 0x002ffc0f},
+ {0x00001058, 0x002ffc0f},
+ {0x0000105c, 0x002ffc0f},
+ {0x00001060, 0x002ffc0f},
+ {0x00001064, 0x002ffc0f},
+ {0x000010f0, 0x00000100},
+ {0x00001270, 0x00000000},
+ {0x000012b0, 0x00000000},
+ {0x000012f0, 0x00000000},
+ {0x0000143c, 0x00000000},
+ {0x0000147c, 0x00000000},
+ {0x00008000, 0x00000000},
+ {0x00008004, 0x00000000},
+ {0x00008008, 0x00000000},
+ {0x0000800c, 0x00000000},
+ {0x00008018, 0x00000000},
+ {0x00008020, 0x00000000},
+ {0x00008038, 0x00000000},
+ {0x0000803c, 0x00000000},
+ {0x00008040, 0x00000000},
+ {0x00008044, 0x00000000},
+ {0x00008048, 0x00000000},
+ {0x0000804c, 0xffffffff},
+ {0x00008054, 0x00000000},
+ {0x00008058, 0x00000000},
+ {0x0000805c, 0x000fc78f},
+ {0x00008060, 0x0000000f},
+ {0x00008064, 0x00000000},
+ {0x00008070, 0x00000310},
+ {0x00008074, 0x00000020},
+ {0x00008078, 0x00000000},
+ {0x0000809c, 0x0000000f},
+ {0x000080a0, 0x00000000},
+ {0x000080a4, 0x02ff0000},
+ {0x000080a8, 0x0e070605},
+ {0x000080ac, 0x0000000d},
+ {0x000080b0, 0x00000000},
+ {0x000080b4, 0x00000000},
+ {0x000080b8, 0x00000000},
+ {0x000080bc, 0x00000000},
+ {0x000080c0, 0x2a800000},
+ {0x000080c4, 0x06900168},
+ {0x000080c8, 0x13881c22},
+ {0x000080cc, 0x01f40000},
+ {0x000080d0, 0x00252500},
+ {0x000080d4, 0x00a00000},
+ {0x000080d8, 0x00400000},
+ {0x000080dc, 0x00000000},
+ {0x000080e0, 0xffffffff},
+ {0x000080e4, 0x0000ffff},
+ {0x000080e8, 0x3f3f3f3f},
+ {0x000080ec, 0x00000000},
+ {0x000080f0, 0x00000000},
+ {0x000080f4, 0x00000000},
+ {0x000080fc, 0x00020000},
+ {0x00008100, 0x00000000},
+ {0x00008108, 0x00000052},
+ {0x0000810c, 0x00000000},
+ {0x00008110, 0x00000000},
+ {0x00008114, 0x000007ff},
+ {0x00008118, 0x000000aa},
+ {0x0000811c, 0x00003210},
+ {0x00008124, 0x00000000},
+ {0x00008128, 0x00000000},
+ {0x0000812c, 0x00000000},
+ {0x00008130, 0x00000000},
+ {0x00008134, 0x00000000},
+ {0x00008138, 0x00000000},
+ {0x0000813c, 0x0000ffff},
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
+ {0x000081f8, 0x00000000},
+ {0x000081fc, 0x00000000},
+ {0x00008240, 0x00100000},
+ {0x00008244, 0x0010f400},
+ {0x00008248, 0x00000800},
+ {0x0000824c, 0x0001e800},
+ {0x00008250, 0x00000000},
+ {0x00008254, 0x00000000},
+ {0x00008258, 0x00000000},
+ {0x0000825c, 0x40000000},
+ {0x00008260, 0x00080922},
+ {0x00008264, 0x9bc00010},
+ {0x00008268, 0xffffffff},
+ {0x0000826c, 0x0000ffff},
+ {0x00008270, 0x00000000},
+ {0x00008274, 0x40000000},
+ {0x00008278, 0x003e4180},
+ {0x0000827c, 0x00000004},
+ {0x00008284, 0x0000002c},
+ {0x00008288, 0x0000002c},
+ {0x0000828c, 0x000000ff},
+ {0x00008294, 0x00000000},
+ {0x00008298, 0x00000000},
+ {0x0000829c, 0x00000000},
+ {0x00008300, 0x00000140},
+ {0x00008314, 0x00000000},
+ {0x0000831c, 0x0000010d},
+ {0x00008328, 0x00000000},
+ {0x0000832c, 0x00000007},
+ {0x00008330, 0x00000302},
+ {0x00008334, 0x00000700},
+ {0x00008338, 0x00ff0000},
+ {0x0000833c, 0x02400000},
+ {0x00008340, 0x000107ff},
+ {0x00008344, 0xaa48105b},
+ {0x00008348, 0x008f0000},
+ {0x0000835c, 0x00000000},
+ {0x00008360, 0xffffffff},
+ {0x00008364, 0xffffffff},
+ {0x00008368, 0x00000000},
+ {0x00008370, 0x00000000},
+ {0x00008374, 0x000000ff},
+ {0x00008378, 0x00000000},
+ {0x0000837c, 0x00000000},
+ {0x00008380, 0xffffffff},
+ {0x00008384, 0xffffffff},
+ {0x00008390, 0xffffffff},
+ {0x00008394, 0xffffffff},
+ {0x00008398, 0x00000000},
+ {0x0000839c, 0x00000000},
+ {0x000083a0, 0x00000000},
+ {0x000083a4, 0x0000fa14},
+ {0x000083a8, 0x000f0c00},
+ {0x000083ac, 0x33332210},
+ {0x000083b0, 0x33332210},
+ {0x000083b4, 0x33332210},
+ {0x000083b8, 0x33332210},
+ {0x000083bc, 0x00000000},
+ {0x000083c0, 0x00000000},
+ {0x000083c4, 0x00000000},
+ {0x000083c8, 0x00000000},
+ {0x000083cc, 0x00000200},
+ {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400},
+ {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640},
+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660},
+ {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400},
+ {0x0000a598, 0x21802220, 0x21802220, 0x15800402, 0x15800402},
+ {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603},
+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02},
+ {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04},
+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20},
+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20},
+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22},
+ {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24},
+ {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640},
+ {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660},
+ {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861},
+ {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81},
+ {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x42801a83, 0x42801a83},
+ {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x44801c84, 0x44801c84},
+ {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x48801ce3, 0x48801ce3},
+ {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x4c801ce5, 0x4c801ce5},
+ {0x0000a5dc, 0x7082708c, 0x7082708c, 0x50801ce9, 0x50801ce9},
+ {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x54801ceb, 0x54801ceb},
+ {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+ {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+ {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+ {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+ {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4},
+ {0x00016048, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016444, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4},
+ {0x00016448, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001},
+ {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016844, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4},
+ {0x00016848, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001},
+ {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9580_1p0_wo_xlna_rx_gain_table[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x03820190},
+ {0x0000a030, 0x03840383},
+ {0x0000a034, 0x03880385},
+ {0x0000a038, 0x038a0389},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x29292929},
+ {0x0000a084, 0x29292929},
+ {0x0000a088, 0x29292929},
+ {0x0000a08c, 0x29292929},
+ {0x0000a090, 0x22292929},
+ {0x0000a094, 0x1d1d2222},
+ {0x0000a098, 0x0c111117},
+ {0x0000a09c, 0x00030303},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x32323232},
+ {0x0000b084, 0x2f2f3232},
+ {0x0000b088, 0x23282a2d},
+ {0x0000b08c, 0x1c1e2123},
+ {0x0000b090, 0x14171919},
+ {0x0000b094, 0x0e0e1214},
+ {0x0000b098, 0x03050707},
+ {0x0000b09c, 0x00030303},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9580_1p0_soc_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
+};
+
+static const u32 ar9580_1p0_high_ob_db_tx_gain_table[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+ {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+ {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+ {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+ {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+ {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+ {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+ {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+ {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+ {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+ {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+static const u32 ar9580_1p0_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x000040a4, 0x00a0c1c9},
+ {0x00007008, 0x00000000},
+ {0x00007020, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+ {0x00007048, 0x00000008},
+};
+
+static const u32 ar9580_1p0_rx_gain_table[][2] = {
+ /* Addr allmodes */
+ {0x0000a000, 0x00010000},
+ {0x0000a004, 0x00030002},
+ {0x0000a008, 0x00050004},
+ {0x0000a00c, 0x00810080},
+ {0x0000a010, 0x00830082},
+ {0x0000a014, 0x01810180},
+ {0x0000a018, 0x01830182},
+ {0x0000a01c, 0x01850184},
+ {0x0000a020, 0x01890188},
+ {0x0000a024, 0x018b018a},
+ {0x0000a028, 0x018d018c},
+ {0x0000a02c, 0x01910190},
+ {0x0000a030, 0x01930192},
+ {0x0000a034, 0x01950194},
+ {0x0000a038, 0x038a0196},
+ {0x0000a03c, 0x038c038b},
+ {0x0000a040, 0x0390038d},
+ {0x0000a044, 0x03920391},
+ {0x0000a048, 0x03940393},
+ {0x0000a04c, 0x03960395},
+ {0x0000a050, 0x00000000},
+ {0x0000a054, 0x00000000},
+ {0x0000a058, 0x00000000},
+ {0x0000a05c, 0x00000000},
+ {0x0000a060, 0x00000000},
+ {0x0000a064, 0x00000000},
+ {0x0000a068, 0x00000000},
+ {0x0000a06c, 0x00000000},
+ {0x0000a070, 0x00000000},
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+ {0x0000a080, 0x22222229},
+ {0x0000a084, 0x1d1d1d1d},
+ {0x0000a088, 0x1d1d1d1d},
+ {0x0000a08c, 0x1d1d1d1d},
+ {0x0000a090, 0x171d1d1d},
+ {0x0000a094, 0x11111717},
+ {0x0000a098, 0x00030311},
+ {0x0000a09c, 0x00000000},
+ {0x0000a0a0, 0x00000000},
+ {0x0000a0a4, 0x00000000},
+ {0x0000a0a8, 0x00000000},
+ {0x0000a0ac, 0x00000000},
+ {0x0000a0b0, 0x00000000},
+ {0x0000a0b4, 0x00000000},
+ {0x0000a0b8, 0x00000000},
+ {0x0000a0bc, 0x00000000},
+ {0x0000a0c0, 0x001f0000},
+ {0x0000a0c4, 0x01000101},
+ {0x0000a0c8, 0x011e011f},
+ {0x0000a0cc, 0x011c011d},
+ {0x0000a0d0, 0x02030204},
+ {0x0000a0d4, 0x02010202},
+ {0x0000a0d8, 0x021f0200},
+ {0x0000a0dc, 0x0302021e},
+ {0x0000a0e0, 0x03000301},
+ {0x0000a0e4, 0x031e031f},
+ {0x0000a0e8, 0x0402031d},
+ {0x0000a0ec, 0x04000401},
+ {0x0000a0f0, 0x041e041f},
+ {0x0000a0f4, 0x0502041d},
+ {0x0000a0f8, 0x05000501},
+ {0x0000a0fc, 0x051e051f},
+ {0x0000a100, 0x06010602},
+ {0x0000a104, 0x061f0600},
+ {0x0000a108, 0x061d061e},
+ {0x0000a10c, 0x07020703},
+ {0x0000a110, 0x07000701},
+ {0x0000a114, 0x00000000},
+ {0x0000a118, 0x00000000},
+ {0x0000a11c, 0x00000000},
+ {0x0000a120, 0x00000000},
+ {0x0000a124, 0x00000000},
+ {0x0000a128, 0x00000000},
+ {0x0000a12c, 0x00000000},
+ {0x0000a130, 0x00000000},
+ {0x0000a134, 0x00000000},
+ {0x0000a138, 0x00000000},
+ {0x0000a13c, 0x00000000},
+ {0x0000a140, 0x001f0000},
+ {0x0000a144, 0x01000101},
+ {0x0000a148, 0x011e011f},
+ {0x0000a14c, 0x011c011d},
+ {0x0000a150, 0x02030204},
+ {0x0000a154, 0x02010202},
+ {0x0000a158, 0x021f0200},
+ {0x0000a15c, 0x0302021e},
+ {0x0000a160, 0x03000301},
+ {0x0000a164, 0x031e031f},
+ {0x0000a168, 0x0402031d},
+ {0x0000a16c, 0x04000401},
+ {0x0000a170, 0x041e041f},
+ {0x0000a174, 0x0502041d},
+ {0x0000a178, 0x05000501},
+ {0x0000a17c, 0x051e051f},
+ {0x0000a180, 0x06010602},
+ {0x0000a184, 0x061f0600},
+ {0x0000a188, 0x061d061e},
+ {0x0000a18c, 0x07020703},
+ {0x0000a190, 0x07000701},
+ {0x0000a194, 0x00000000},
+ {0x0000a198, 0x00000000},
+ {0x0000a19c, 0x00000000},
+ {0x0000a1a0, 0x00000000},
+ {0x0000a1a4, 0x00000000},
+ {0x0000a1a8, 0x00000000},
+ {0x0000a1ac, 0x00000000},
+ {0x0000a1b0, 0x00000000},
+ {0x0000a1b4, 0x00000000},
+ {0x0000a1b8, 0x00000000},
+ {0x0000a1bc, 0x00000000},
+ {0x0000a1c0, 0x00000000},
+ {0x0000a1c4, 0x00000000},
+ {0x0000a1c8, 0x00000000},
+ {0x0000a1cc, 0x00000000},
+ {0x0000a1d0, 0x00000000},
+ {0x0000a1d4, 0x00000000},
+ {0x0000a1d8, 0x00000000},
+ {0x0000a1dc, 0x00000000},
+ {0x0000a1e0, 0x00000000},
+ {0x0000a1e4, 0x00000000},
+ {0x0000a1e8, 0x00000000},
+ {0x0000a1ec, 0x00000000},
+ {0x0000a1f0, 0x00000396},
+ {0x0000a1f4, 0x00000396},
+ {0x0000a1f8, 0x00000396},
+ {0x0000a1fc, 0x00000196},
+ {0x0000b000, 0x00010000},
+ {0x0000b004, 0x00030002},
+ {0x0000b008, 0x00050004},
+ {0x0000b00c, 0x00810080},
+ {0x0000b010, 0x00830082},
+ {0x0000b014, 0x01810180},
+ {0x0000b018, 0x01830182},
+ {0x0000b01c, 0x01850184},
+ {0x0000b020, 0x02810280},
+ {0x0000b024, 0x02830282},
+ {0x0000b028, 0x02850284},
+ {0x0000b02c, 0x02890288},
+ {0x0000b030, 0x028b028a},
+ {0x0000b034, 0x0388028c},
+ {0x0000b038, 0x038a0389},
+ {0x0000b03c, 0x038c038b},
+ {0x0000b040, 0x0390038d},
+ {0x0000b044, 0x03920391},
+ {0x0000b048, 0x03940393},
+ {0x0000b04c, 0x03960395},
+ {0x0000b050, 0x00000000},
+ {0x0000b054, 0x00000000},
+ {0x0000b058, 0x00000000},
+ {0x0000b05c, 0x00000000},
+ {0x0000b060, 0x00000000},
+ {0x0000b064, 0x00000000},
+ {0x0000b068, 0x00000000},
+ {0x0000b06c, 0x00000000},
+ {0x0000b070, 0x00000000},
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+ {0x0000b080, 0x2a2d2f32},
+ {0x0000b084, 0x21232328},
+ {0x0000b088, 0x19191c1e},
+ {0x0000b08c, 0x12141417},
+ {0x0000b090, 0x07070e0e},
+ {0x0000b094, 0x03030305},
+ {0x0000b098, 0x00000003},
+ {0x0000b09c, 0x00000000},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+ {0x0000b0ac, 0x00000000},
+ {0x0000b0b0, 0x00000000},
+ {0x0000b0b4, 0x00000000},
+ {0x0000b0b8, 0x00000000},
+ {0x0000b0bc, 0x00000000},
+ {0x0000b0c0, 0x003f0020},
+ {0x0000b0c4, 0x00400041},
+ {0x0000b0c8, 0x0140005f},
+ {0x0000b0cc, 0x0160015f},
+ {0x0000b0d0, 0x017e017f},
+ {0x0000b0d4, 0x02410242},
+ {0x0000b0d8, 0x025f0240},
+ {0x0000b0dc, 0x027f0260},
+ {0x0000b0e0, 0x0341027e},
+ {0x0000b0e4, 0x035f0340},
+ {0x0000b0e8, 0x037f0360},
+ {0x0000b0ec, 0x04400441},
+ {0x0000b0f0, 0x0460045f},
+ {0x0000b0f4, 0x0541047f},
+ {0x0000b0f8, 0x055f0540},
+ {0x0000b0fc, 0x057f0560},
+ {0x0000b100, 0x06400641},
+ {0x0000b104, 0x0660065f},
+ {0x0000b108, 0x067e067f},
+ {0x0000b10c, 0x07410742},
+ {0x0000b110, 0x075f0740},
+ {0x0000b114, 0x077f0760},
+ {0x0000b118, 0x07800781},
+ {0x0000b11c, 0x07a0079f},
+ {0x0000b120, 0x07c107bf},
+ {0x0000b124, 0x000007c0},
+ {0x0000b128, 0x00000000},
+ {0x0000b12c, 0x00000000},
+ {0x0000b130, 0x00000000},
+ {0x0000b134, 0x00000000},
+ {0x0000b138, 0x00000000},
+ {0x0000b13c, 0x00000000},
+ {0x0000b140, 0x003f0020},
+ {0x0000b144, 0x00400041},
+ {0x0000b148, 0x0140005f},
+ {0x0000b14c, 0x0160015f},
+ {0x0000b150, 0x017e017f},
+ {0x0000b154, 0x02410242},
+ {0x0000b158, 0x025f0240},
+ {0x0000b15c, 0x027f0260},
+ {0x0000b160, 0x0341027e},
+ {0x0000b164, 0x035f0340},
+ {0x0000b168, 0x037f0360},
+ {0x0000b16c, 0x04400441},
+ {0x0000b170, 0x0460045f},
+ {0x0000b174, 0x0541047f},
+ {0x0000b178, 0x055f0540},
+ {0x0000b17c, 0x057f0560},
+ {0x0000b180, 0x06400641},
+ {0x0000b184, 0x0660065f},
+ {0x0000b188, 0x067e067f},
+ {0x0000b18c, 0x07410742},
+ {0x0000b190, 0x075f0740},
+ {0x0000b194, 0x077f0760},
+ {0x0000b198, 0x07800781},
+ {0x0000b19c, 0x07a0079f},
+ {0x0000b1a0, 0x07c107bf},
+ {0x0000b1a4, 0x000007c0},
+ {0x0000b1a8, 0x00000000},
+ {0x0000b1ac, 0x00000000},
+ {0x0000b1b0, 0x00000000},
+ {0x0000b1b4, 0x00000000},
+ {0x0000b1b8, 0x00000000},
+ {0x0000b1bc, 0x00000000},
+ {0x0000b1c0, 0x00000000},
+ {0x0000b1c4, 0x00000000},
+ {0x0000b1c8, 0x00000000},
+ {0x0000b1cc, 0x00000000},
+ {0x0000b1d0, 0x00000000},
+ {0x0000b1d4, 0x00000000},
+ {0x0000b1d8, 0x00000000},
+ {0x0000b1dc, 0x00000000},
+ {0x0000b1e0, 0x00000000},
+ {0x0000b1e4, 0x00000000},
+ {0x0000b1e8, 0x00000000},
+ {0x0000b1ec, 0x00000000},
+ {0x0000b1f0, 0x00000396},
+ {0x0000b1f4, 0x00000396},
+ {0x0000b1f8, 0x00000396},
+ {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9580_1p0_radio_core[][2] = {
+ /* Addr allmodes */
+ {0x00016000, 0x36db6db6},
+ {0x00016004, 0x6db6db40},
+ {0x00016008, 0x73f00000},
+ {0x0001600c, 0x00000000},
+ {0x00016040, 0x7f80fff8},
+ {0x0001604c, 0x76d005b5},
+ {0x00016050, 0x556cf031},
+ {0x00016054, 0x13449440},
+ {0x00016058, 0x0c51c92c},
+ {0x0001605c, 0x3db7fffc},
+ {0x00016060, 0xfffffffc},
+ {0x00016064, 0x000f0278},
+ {0x0001606c, 0x6db60000},
+ {0x00016080, 0x00000000},
+ {0x00016084, 0x0e48048c},
+ {0x00016088, 0x54214514},
+ {0x0001608c, 0x119f481e},
+ {0x00016090, 0x24926490},
+ {0x00016098, 0xd2888888},
+ {0x000160a0, 0x0a108ffe},
+ {0x000160a4, 0x812fc370},
+ {0x000160a8, 0x423c8000},
+ {0x000160b4, 0x92480080},
+ {0x000160c0, 0x00adb6d0},
+ {0x000160c4, 0x6db6db60},
+ {0x000160c8, 0x6db6db6c},
+ {0x000160cc, 0x01e6c000},
+ {0x00016100, 0x3fffbe01},
+ {0x00016104, 0xfff80000},
+ {0x00016108, 0x00080010},
+ {0x00016144, 0x02084080},
+ {0x00016148, 0x00000000},
+ {0x00016280, 0x058a0001},
+ {0x00016284, 0x3d840208},
+ {0x00016288, 0x05a20408},
+ {0x0001628c, 0x00038c07},
+ {0x00016290, 0x00000004},
+ {0x00016294, 0x458aa14f},
+ {0x00016380, 0x00000000},
+ {0x00016384, 0x00000000},
+ {0x00016388, 0x00800700},
+ {0x0001638c, 0x00800700},
+ {0x00016390, 0x00800700},
+ {0x00016394, 0x00000000},
+ {0x00016398, 0x00000000},
+ {0x0001639c, 0x00000000},
+ {0x000163a0, 0x00000001},
+ {0x000163a4, 0x00000001},
+ {0x000163a8, 0x00000000},
+ {0x000163ac, 0x00000000},
+ {0x000163b0, 0x00000000},
+ {0x000163b4, 0x00000000},
+ {0x000163b8, 0x00000000},
+ {0x000163bc, 0x00000000},
+ {0x000163c0, 0x000000a0},
+ {0x000163c4, 0x000c0000},
+ {0x000163c8, 0x14021402},
+ {0x000163cc, 0x00001402},
+ {0x000163d0, 0x00000000},
+ {0x000163d4, 0x00000000},
+ {0x00016400, 0x36db6db6},
+ {0x00016404, 0x6db6db40},
+ {0x00016408, 0x73f00000},
+ {0x0001640c, 0x00000000},
+ {0x00016440, 0x7f80fff8},
+ {0x0001644c, 0x76d005b5},
+ {0x00016450, 0x556cf031},
+ {0x00016454, 0x13449440},
+ {0x00016458, 0x0c51c92c},
+ {0x0001645c, 0x3db7fffc},
+ {0x00016460, 0xfffffffc},
+ {0x00016464, 0x000f0278},
+ {0x0001646c, 0x6db60000},
+ {0x00016500, 0x3fffbe01},
+ {0x00016504, 0xfff80000},
+ {0x00016508, 0x00080010},
+ {0x00016544, 0x02084080},
+ {0x00016548, 0x00000000},
+ {0x00016780, 0x00000000},
+ {0x00016784, 0x00000000},
+ {0x00016788, 0x00800700},
+ {0x0001678c, 0x00800700},
+ {0x00016790, 0x00800700},
+ {0x00016794, 0x00000000},
+ {0x00016798, 0x00000000},
+ {0x0001679c, 0x00000000},
+ {0x000167a0, 0x00000001},
+ {0x000167a4, 0x00000001},
+ {0x000167a8, 0x00000000},
+ {0x000167ac, 0x00000000},
+ {0x000167b0, 0x00000000},
+ {0x000167b4, 0x00000000},
+ {0x000167b8, 0x00000000},
+ {0x000167bc, 0x00000000},
+ {0x000167c0, 0x000000a0},
+ {0x000167c4, 0x000c0000},
+ {0x000167c8, 0x14021402},
+ {0x000167cc, 0x00001402},
+ {0x000167d0, 0x00000000},
+ {0x000167d4, 0x00000000},
+ {0x00016800, 0x36db6db6},
+ {0x00016804, 0x6db6db40},
+ {0x00016808, 0x73f00000},
+ {0x0001680c, 0x00000000},
+ {0x00016840, 0x7f80fff8},
+ {0x0001684c, 0x76d005b5},
+ {0x00016850, 0x556cf031},
+ {0x00016854, 0x13449440},
+ {0x00016858, 0x0c51c92c},
+ {0x0001685c, 0x3db7fffc},
+ {0x00016860, 0xfffffffc},
+ {0x00016864, 0x000f0278},
+ {0x0001686c, 0x6db60000},
+ {0x00016900, 0x3fffbe01},
+ {0x00016904, 0xfff80000},
+ {0x00016908, 0x00080010},
+ {0x00016944, 0x02084080},
+ {0x00016948, 0x00000000},
+ {0x00016b80, 0x00000000},
+ {0x00016b84, 0x00000000},
+ {0x00016b88, 0x00800700},
+ {0x00016b8c, 0x00800700},
+ {0x00016b90, 0x00800700},
+ {0x00016b94, 0x00000000},
+ {0x00016b98, 0x00000000},
+ {0x00016b9c, 0x00000000},
+ {0x00016ba0, 0x00000001},
+ {0x00016ba4, 0x00000001},
+ {0x00016ba8, 0x00000000},
+ {0x00016bac, 0x00000000},
+ {0x00016bb0, 0x00000000},
+ {0x00016bb4, 0x00000000},
+ {0x00016bb8, 0x00000000},
+ {0x00016bbc, 0x00000000},
+ {0x00016bc0, 0x000000a0},
+ {0x00016bc4, 0x000c0000},
+ {0x00016bc8, 0x14021402},
+ {0x00016bcc, 0x00001402},
+ {0x00016bd0, 0x00000000},
+ {0x00016bd4, 0x00000000},
+};
+
+static const u32 ar9580_1p0_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+ {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+ {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+ {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+ {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+ {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f},
+ {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+ {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+ {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+ {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+ {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+ {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+};
+
+static const u32 ar9580_1p0_pcie_phy_clkreq_enable_L1[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x0835365e},
+ {0x00004040, 0x0008003b},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9580_1p0_pcie_phy_clkreq_disable_L1[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x0831365e},
+ {0x00004040, 0x0008003b},
+ {0x00004044, 0x00000000},
+};
+
+static const u32 ar9580_1p0_pcie_phy_pll_on_clkreq[][2] = {
+ /* Addr allmodes */
+ {0x00004040, 0x0831265e},
+ {0x00004040, 0x0008003b},
+ {0x00004044, 0x00000000},
+};
+
+#endif /* INITVALS_9580_1P0_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 46393f90f16c..1c269f50822b 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -87,17 +87,14 @@ struct ath_config {
* @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
* @BUF_AGGR: Indicates whether the buffer can be aggregated
* (used in aggregation scheduling)
- * @BUF_XRETRY: To denote excessive retries of the buffer
*/
enum buffer_type {
BUF_AMPDU = BIT(0),
BUF_AGGR = BIT(1),
- BUF_XRETRY = BIT(2),
};
#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
-#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
#define ATH_TXSTATUS_RING_SIZE 64
@@ -206,18 +203,19 @@ struct ath_atx_ac {
};
struct ath_frame_info {
+ struct ath_buf *bf;
int framelen;
- u32 keyix;
enum ath9k_key_type keytype;
+ u8 keyix;
u8 retries;
- u16 seqno;
};
struct ath_buf_state {
u8 bf_type;
u8 bfs_paprd;
+ u8 ndelim;
+ u16 seqno;
unsigned long bfs_paprd_timestamp;
- enum ath9k_internal_frame_type bfs_ftype;
};
struct ath_buf {
@@ -230,13 +228,12 @@ struct ath_buf {
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
bool bf_stale;
- u16 bf_flags;
struct ath_buf_state bf_state;
};
struct ath_atx_tid {
struct list_head list;
- struct list_head buf_q;
+ struct sk_buff_head buf_q;
struct ath_node *an;
struct ath_atx_ac *ac;
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
@@ -273,14 +270,11 @@ struct ath_node {
struct ath_tx_control {
struct ath_txq *txq;
struct ath_node *an;
- int if_id;
- enum ath9k_internal_frame_type frame_type;
u8 paprd;
};
#define ATH_TX_ERROR 0x01
-#define ATH_TX_XRETRY 0x02
-#define ATH_TX_BAR 0x04
+#define ATH_TX_BAR 0x02
/**
* @txq_map: Index is mac80211 queue number. This is
@@ -346,7 +340,8 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
-bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an);
+void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
+ struct ath_node *an);
/********/
/* VIFs */
@@ -427,6 +422,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
+void ath_reset_work(struct work_struct *work);
void ath_hw_check(struct work_struct *work);
void ath_hw_pll_work(struct work_struct *work);
void ath_paprd_calibrate(struct work_struct *work);
@@ -462,6 +458,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc);
#define ATH_LED_PIN_9287 8
#define ATH_LED_PIN_9300 10
#define ATH_LED_PIN_9485 6
+#define ATH_LED_PIN_9462 0
#ifdef CONFIG_MAC80211_LEDS
void ath_init_leds(struct ath_softc *sc);
@@ -561,8 +558,7 @@ struct ath_ant_comb {
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
#define SC_OP_ANI_RUN BIT(14)
-#define SC_OP_ENABLE_APM BIT(15)
-#define SC_OP_PRIM_STA_VIF BIT(16)
+#define SC_OP_PRIM_STA_VIF BIT(15)
/* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0)
@@ -570,7 +566,6 @@ struct ath_ant_comb {
#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
#define PS_WAIT_FOR_TX_ACK BIT(3)
#define PS_BEACON_SYNC BIT(4)
-#define PS_TSFOOR_SYNC BIT(5)
struct ath_rate_table;
@@ -608,6 +603,7 @@ struct ath_softc {
struct mutex mutex;
struct work_struct paprd_work;
struct work_struct hw_check_work;
+ struct work_struct hw_reset_work;
struct completion paprd_complete;
unsigned int hw_busy_count;
@@ -651,10 +647,10 @@ struct ath_softc {
struct ath_descdma txsdma;
struct ath_ant_comb ant_comb;
+ u8 ant_tx, ant_rx;
};
void ath9k_tasklet(unsigned long data);
-int ath_reset(struct ath_softc *sc, bool retry_tx);
int ath_cabq_update(struct ath_softc *);
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
@@ -668,11 +664,11 @@ extern int led_blink;
extern bool is_ath9k_unloaded;
irqreturn_t ath_isr(int irq, void *dev);
-void ath9k_init_crypto(struct ath_softc *sc);
-int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
+int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops);
void ath9k_deinit_device(struct ath_softc *sc);
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
+void ath9k_reload_chainmask_settings(struct ath_softc *sc);
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
bool ath9k_uses_beacons(int type);
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 0d13ff74a68b..a13cabb95435 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -73,44 +73,39 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
struct sk_buff *skb = bf->bf_mpdu;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ath_desc *ds;
- struct ath9k_11n_rate_series series[4];
- int flags, ctsrate = 0, ctsduration = 0;
+ struct ath_tx_info info;
struct ieee80211_supported_band *sband;
+ u8 chainmask = ah->txchainmask;
u8 rate = 0;
ath9k_reset_beacon_status(sc);
- ds = bf->bf_desc;
- flags = ATH9K_TXDESC_NOACK;
-
- ds->ds_link = 0;
-
sband = &sc->sbands[common->hw->conf.channel->band];
rate = sband->bitrates[rateidx].hw_value;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
rate |= sband->bitrates[rateidx].hw_value_short;
- ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
- ATH9K_PKT_TYPE_BEACON,
- MAX_RATE_POWER,
- ATH9K_TXKEYIX_INVALID,
- ATH9K_KEY_TYPE_CLEAR,
- flags);
-
- /* NB: beacon's BufLen must be a multiple of 4 bytes */
- ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
- true, true, ds, bf->bf_buf_addr,
- sc->beacon.beaconq);
-
- memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
- series[0].Tries = 1;
- series[0].Rate = rate;
- series[0].ChSel = ath_txchainmask_reduction(sc,
- common->tx_chainmask, series[0].Rate);
- series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
- ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
- series, 4, 0);
+ memset(&info, 0, sizeof(info));
+ info.pkt_len = skb->len + FCS_LEN;
+ info.type = ATH9K_PKT_TYPE_BEACON;
+ info.txpower = MAX_RATE_POWER;
+ info.keyix = ATH9K_TXKEYIX_INVALID;
+ info.keytype = ATH9K_KEY_TYPE_CLEAR;
+ info.flags = ATH9K_TXDESC_NOACK;
+
+ info.buf_addr[0] = bf->bf_buf_addr;
+ info.buf_len[0] = roundup(skb->len, 4);
+
+ info.is_first = true;
+ info.is_last = true;
+
+ info.qcu = sc->beacon.beaconq;
+
+ info.rates[0].Tries = 1;
+ info.rates[0].Rate = rate;
+ info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate);
+
+ ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
}
static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
@@ -386,9 +381,7 @@ void ath_beacon_tasklet(unsigned long data)
ath_dbg(common, ATH_DBG_BSTUCK,
"beacon is officially stuck\n");
sc->sc_flags |= SC_OP_TSF_RESET;
- spin_lock(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock(&sc->sc_pcu_lock);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
return;
@@ -519,9 +512,11 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
/* Set the computed AP beacon timers */
ath9k_hw_disable_interrupts(ah);
+ sc->sc_flags |= SC_OP_TSF_RESET;
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
}
/*
@@ -648,12 +643,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
ath9k_hw_set_sta_beacon_timers(ah, &bs);
ah->imask |= ATH9K_INT_BMISS;
- /*
- * If the beacon config is called beacause of TSFOOR,
- * Interrupts will be enabled back at the end of ath9k_tasklet
- */
- if (!(sc->ps_flags & PS_TSFOOR_SYNC))
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
}
static void ath_beacon_config_adhoc(struct ath_softc *sc,
@@ -687,12 +678,9 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
ath9k_hw_disable_interrupts(ah);
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
- /*
- * If the beacon config is called beacause of TSFOOR,
- * Interrupts will be enabled back at the end of ath9k_tasklet
- */
- if (!(sc->ps_flags & PS_TSFOOR_SYNC))
- ath9k_hw_set_interrupts(ah, ah->imask);
+
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
}
static bool ath9k_allow_beacon_config(struct ath_softc *sc,
@@ -833,11 +821,11 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
if (status) {
/* Re-enable beaconing */
ah->imask |= ATH9K_INT_SWBA;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
} else {
/* Disable SWBA interrupt */
ah->imask &= ~ATH9K_INT_SWBA;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
tasklet_kill(&sc->bcon_tasklet);
ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
}
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index a1250c586e40..ebaf304f464b 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -63,13 +63,25 @@ static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
return ath9k_hw_get_nf_limits(ah, chan)->nominal;
}
+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ s8 noise = ATH_DEFAULT_NOISE_FLOOR;
+
+ if (chan && chan->noisefloor) {
+ s8 delta = chan->noisefloor -
+ ath9k_hw_get_default_nf(ah, chan);
+ if (delta > 0)
+ noise += delta;
+ }
+ return noise;
+}
+EXPORT_SYMBOL(ath9k_hw_getchan_noise);
static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
struct ath9k_hw_cal_data *cal,
int16_t *nfarray)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_conf *conf = &common->hw->conf;
struct ath_nf_limits *limit;
struct ath9k_nfcal_hist *h;
bool high_nf_mid = false;
@@ -81,7 +93,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
for (i = 0; i < NUM_NF_READINGS; i++) {
if (!(chainmask & (1 << i)) ||
- ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+ ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan)))
continue;
h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
@@ -378,6 +390,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
if (!caldata) {
chan->noisefloor = nf;
+ ah->noise = ath9k_hw_getchan_noise(ah, chan);
return false;
}
@@ -385,6 +398,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
caldata->nfcal_pending = false;
ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
chan->noisefloor = h[0].privNF;
+ ah->noise = ath9k_hw_getchan_noise(ah, chan);
return true;
}
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 1bef41d1b1ff..05b9dbf81850 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -108,6 +108,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
void ath9k_hw_bstuck_nfcal(struct ath_hw *ah);
void ath9k_hw_reset_calibration(struct ath_hw *ah,
struct ath9k_cal_list *currCal);
+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
#endif /* CALIB_H */
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index fa6bd2d189e5..905f1b313961 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -161,14 +161,42 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams);
void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
u16 new_txpow, u16 *txpower)
{
- if (cur_txpow != new_txpow) {
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+
+ if (reg->power_limit != new_txpow) {
ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
/* read back in case value is clamped */
- *txpower = ath9k_hw_regulatory(ah)->power_limit;
+ *txpower = reg->max_power_level;
}
}
EXPORT_SYMBOL(ath9k_cmn_update_txpow);
+void ath9k_cmn_init_crypto(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ int i = 0;
+
+ /* Get the hardware key cache size. */
+ common->keymax = AR_KEYTABLE_SIZE;
+
+ /*
+ * Check whether the separate key cache entries
+ * are required to handle both tx+rx MIC keys.
+ * With split mic keys the number of stations is limited
+ * to 27 otherwise 59.
+ */
+ if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
+ common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
+
+ /*
+ * Reset the key cache since some parts do not
+ * reset the contents on initial power up.
+ */
+ for (i = 0; i < common->keymax; i++)
+ ath_hw_keyreset(common, (u16) i);
+}
+EXPORT_SYMBOL(ath9k_cmn_init_crypto);
+
static int __init ath9k_cmn_init(void)
{
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 77ec288b5a70..ad14fecc76c6 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -62,3 +62,4 @@ void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
enum ath_stomp_type stomp_type);
void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
u16 new_txpow, u16 *txpower);
+void ath9k_cmn_init_crypto(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index d1eb89611ff7..327aa28f6030 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -95,11 +95,11 @@ static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
char buf[32];
unsigned int len;
- len = sprintf(buf, "0x%08x\n", common->tx_chainmask);
+ len = sprintf(buf, "0x%08x\n", ah->txchainmask);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -107,7 +107,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
unsigned long mask;
char buf[32];
ssize_t len;
@@ -120,8 +120,8 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
if (strict_strtoul(buf, 0, &mask))
return -EINVAL;
- common->tx_chainmask = mask;
- sc->sc_ah->caps.tx_chainmask = mask;
+ ah->txchainmask = mask;
+ ah->caps.tx_chainmask = mask;
return count;
}
@@ -138,11 +138,11 @@ static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
char buf[32];
unsigned int len;
- len = sprintf(buf, "0x%08x\n", common->rx_chainmask);
+ len = sprintf(buf, "0x%08x\n", ah->rxchainmask);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -150,7 +150,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
unsigned long mask;
char buf[32];
ssize_t len;
@@ -163,8 +163,8 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
if (strict_strtoul(buf, 0, &mask))
return -EINVAL;
- common->rx_chainmask = mask;
- sc->sc_ah->caps.rx_chainmask = mask;
+ ah->rxchainmask = mask;
+ ah->caps.rx_chainmask = mask;
return count;
}
@@ -523,9 +523,22 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
if (tmp & ATH9K_RX_FILTER_PHYRADAR)
len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
if (tmp & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
- len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL\n");
- else
- len += snprintf(buf + len, sizeof(buf) - len, "\n");
+ len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL");
+
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "\n\nReset causes:\n"
+ " baseband hang: %d\n"
+ " baseband watchdog: %d\n"
+ " fatal hardware error interrupt: %d\n"
+ " tx hardware error: %d\n"
+ " tx path hang: %d\n"
+ " pll rx hang: %d\n",
+ sc->debug.stats.reset[RESET_TYPE_BB_HANG],
+ sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG],
+ sc->debug.stats.reset[RESET_TYPE_FATAL_INT],
+ sc->debug.stats.reset[RESET_TYPE_TX_ERROR],
+ sc->debug.stats.reset[RESET_TYPE_TX_HANG],
+ sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
if (len > sizeof(buf))
len = sizeof(buf);
@@ -711,7 +724,7 @@ static ssize_t read_file_stations(struct file *file, char __user *user_buf,
" tid: %p %s %s %i %p %p\n",
tid, tid->sched ? "sched" : "idle",
tid->paused ? "paused" : "running",
- list_empty(&tid->buf_q),
+ skb_queue_empty(&tid->buf_q),
tid->an, tid->ac);
if (len >= size)
goto done;
@@ -826,20 +839,23 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
}
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_tx_status *ts, struct ath_txq *txq)
+ struct ath_tx_status *ts, struct ath_txq *txq,
+ unsigned int flags)
{
+#define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\
+ [sc->debug.tsidx].c)
int qnum = txq->axq_qnum;
TX_STAT_INC(qnum, tx_pkts_all);
sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
if (bf_isampdu(bf)) {
- if (bf_isxretried(bf))
+ if (flags & ATH_TX_BAR)
TX_STAT_INC(qnum, a_xretries);
else
TX_STAT_INC(qnum, a_completed);
} else {
- if (bf_isxretried(bf))
+ if (ts->ts_status & ATH9K_TXERR_XRETRY)
TX_STAT_INC(qnum, xretries);
else
TX_STAT_INC(qnum, completed);
@@ -857,6 +873,35 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
TX_STAT_INC(qnum, data_underrun);
if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
TX_STAT_INC(qnum, delim_underrun);
+
+ spin_lock(&sc->debug.samp_lock);
+ TX_SAMP_DBG(jiffies) = jiffies;
+ TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0;
+ TX_SAMP_DBG(rssi_ctl1) = ts->ts_rssi_ctl1;
+ TX_SAMP_DBG(rssi_ctl2) = ts->ts_rssi_ctl2;
+ TX_SAMP_DBG(rssi_ext0) = ts->ts_rssi_ext0;
+ TX_SAMP_DBG(rssi_ext1) = ts->ts_rssi_ext1;
+ TX_SAMP_DBG(rssi_ext2) = ts->ts_rssi_ext2;
+ TX_SAMP_DBG(rateindex) = ts->ts_rateindex;
+ TX_SAMP_DBG(isok) = !!(ts->ts_status & ATH9K_TXERR_MASK);
+ TX_SAMP_DBG(rts_fail_cnt) = ts->ts_shortretry;
+ TX_SAMP_DBG(data_fail_cnt) = ts->ts_longretry;
+ TX_SAMP_DBG(rssi) = ts->ts_rssi;
+ TX_SAMP_DBG(tid) = ts->tid;
+ TX_SAMP_DBG(qid) = ts->qid;
+
+ if (ts->ts_flags & ATH9K_TX_BA) {
+ TX_SAMP_DBG(ba_low) = ts->ba_low;
+ TX_SAMP_DBG(ba_high) = ts->ba_high;
+ } else {
+ TX_SAMP_DBG(ba_low) = 0;
+ TX_SAMP_DBG(ba_high) = 0;
+ }
+
+ sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES;
+ spin_unlock(&sc->debug.samp_lock);
+
+#undef TX_SAMP_DBG
}
static const struct file_operations fops_xmit = {
@@ -995,6 +1040,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
{
#define RX_STAT_INC(c) sc->debug.stats.rxstats.c++
#define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
+#define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\
+ [sc->debug.rsidx].c)
u32 phyerr;
@@ -1030,8 +1077,25 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna;
+ spin_lock(&sc->debug.samp_lock);
+ RX_SAMP_DBG(jiffies) = jiffies;
+ RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
+ RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1;
+ RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2;
+ RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0;
+ RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1;
+ RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2;
+ RX_SAMP_DBG(antenna) = rs->rs_antenna;
+ RX_SAMP_DBG(rssi) = rs->rs_rssi;
+ RX_SAMP_DBG(rate) = rs->rs_rate;
+ RX_SAMP_DBG(is_mybeacon) = rs->is_mybeacon;
+
+ sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES;
+ spin_unlock(&sc->debug.samp_lock);
+
#undef RX_STAT_INC
#undef RX_PHY_ERR_INC
+#undef RX_SAMP_DBG
}
static const struct file_operations fops_recv = {
@@ -1163,6 +1227,389 @@ static const struct file_operations fops_regdump = {
.llseek = default_llseek,/* read accesses f_pos */
};
+static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_conf *conf = &common->hw->conf;
+ u32 len = 0, size = 1500;
+ u32 i, j;
+ ssize_t retval = 0;
+ char *buf;
+ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+ u8 nread;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len += snprintf(buf + len, size - len,
+ "Channel Noise Floor : %d\n", ah->noise);
+ len += snprintf(buf + len, size - len,
+ "Chain | privNF | # Readings | NF Readings\n");
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (!(chainmask & (1 << i)) ||
+ ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+ continue;
+
+ nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount;
+ len += snprintf(buf + len, size - len, " %d\t %d\t %d\t\t",
+ i, h[i].privNF, nread);
+ for (j = 0; j < nread; j++)
+ len += snprintf(buf + len, size - len,
+ " %d", h[i].nfCalBuffer[j]);
+ len += snprintf(buf + len, size - len, "\n");
+ }
+
+ if (len > size)
+ len = size;
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_dump_nfcal = {
+ .read = read_file_dump_nfcal,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_hw *ah = sc->sc_ah;
+ u32 len = 0, size = 1500;
+ ssize_t retval = 0;
+ char *buf;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size);
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_base_eeprom = {
+ .read = read_file_base_eeprom,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_hw *ah = sc->sc_ah;
+ u32 len = 0, size = 6000;
+ char *buf;
+ size_t retval;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size);
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_modal_eeprom = {
+ .read = read_file_modal_eeprom,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
+{
+#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c)
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ unsigned long flags;
+ int i;
+
+ ath9k_ps_wakeup(sc);
+
+ spin_lock_bh(&sc->debug.samp_lock);
+
+ spin_lock_irqsave(&common->cc_lock, flags);
+ ath_hw_cycle_counters_update(common);
+
+ ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles;
+ ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy;
+ ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame;
+ ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame;
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+
+ ATH_SAMP_DBG(noise) = ah->noise;
+
+ REG_WRITE_D(ah, AR_MACMISC,
+ ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+ (AR_MACMISC_MISC_OBS_BUS_1 <<
+ AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
+ for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+ ATH_SAMP_DBG(dma_dbg_reg_vals[i]) = REG_READ_D(ah,
+ AR_DMADBG_0 + (i * sizeof(u32)));
+
+ ATH_SAMP_DBG(pcu_obs) = REG_READ_D(ah, AR_OBS_BUS_1);
+ ATH_SAMP_DBG(pcu_cr) = REG_READ_D(ah, AR_CR);
+
+ memcpy(ATH_SAMP_DBG(nfCalHist), sc->caldata.nfCalHist,
+ sizeof(ATH_SAMP_DBG(nfCalHist)));
+
+ sc->debug.sampidx = (sc->debug.sampidx + 1) % ATH_DBG_MAX_SAMPLES;
+ spin_unlock_bh(&sc->debug.samp_lock);
+ ath9k_ps_restore(sc);
+
+#undef ATH_SAMP_DBG
+}
+
+static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
+{
+#define ATH_SAMP_DBG(c) bb_mac_samp[sampidx].c
+ struct ath_softc *sc = inode->i_private;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_conf *conf = &common->hw->conf;
+ struct ath_dbg_bb_mac_samp *bb_mac_samp;
+ struct ath9k_nfcal_hist *h;
+ int i, j, qcuOffset = 0, dcuOffset = 0;
+ u32 *qcuBase, *dcuBase, size = 30000, len = 0;
+ u32 sampidx = 0;
+ u8 *buf;
+ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+ u8 nread;
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return -EAGAIN;
+
+ buf = vmalloc(size);
+ if (!buf)
+ return -ENOMEM;
+ bb_mac_samp = vmalloc(sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
+ if (!bb_mac_samp) {
+ vfree(buf);
+ return -ENOMEM;
+ }
+ /* Account the current state too */
+ ath9k_debug_samp_bb_mac(sc);
+
+ spin_lock_bh(&sc->debug.samp_lock);
+ memcpy(bb_mac_samp, sc->debug.bb_mac_samp,
+ sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
+ len += snprintf(buf + len, size - len,
+ "Current Sample Index: %d\n", sc->debug.sampidx);
+ spin_unlock_bh(&sc->debug.samp_lock);
+
+ len += snprintf(buf + len, size - len,
+ "Raw DMA Debug Dump:\n");
+ len += snprintf(buf + len, size - len, "Sample |\t");
+ for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+ len += snprintf(buf + len, size - len, " DMA Reg%d |\t", i);
+ len += snprintf(buf + len, size - len, "\n");
+
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ len += snprintf(buf + len, size - len, "%d\t", sampidx);
+
+ for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+ len += snprintf(buf + len, size - len, " %08x\t",
+ ATH_SAMP_DBG(dma_dbg_reg_vals[i]));
+ len += snprintf(buf + len, size - len, "\n");
+ }
+ len += snprintf(buf + len, size - len, "\n");
+
+ len += snprintf(buf + len, size - len,
+ "Sample Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]);
+ dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]);
+
+ for (i = 0; i < ATH9K_NUM_QUEUES; i++,
+ qcuOffset += 4, dcuOffset += 5) {
+ if (i == 8) {
+ qcuOffset = 0;
+ qcuBase++;
+ }
+
+ if (i == 6) {
+ dcuOffset = 0;
+ dcuBase++;
+ }
+ if (!sc->debug.stats.txstats[i].queued)
+ continue;
+
+ len += snprintf(buf + len, size - len,
+ "%4d %7d %2x %1x %2x %2x\n",
+ sampidx, i,
+ (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+ (*qcuBase & (0x8 << qcuOffset)) >>
+ (qcuOffset + 3),
+ ATH_SAMP_DBG(dma_dbg_reg_vals[2]) &
+ (0x7 << (i * 3)) >> (i * 3),
+ (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+ }
+ len += snprintf(buf + len, size - len, "\n");
+ }
+ len += snprintf(buf + len, size - len,
+ "samp qcu_sh qcu_fh qcu_comp dcu_comp dcu_arb dcu_fp "
+ "ch_idle_dur ch_idle_dur_val txfifo_val0 txfifo_val1 "
+ "txfifo_dcu0 txfifo_dcu1 pcu_obs AR_CR\n");
+
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]);
+ dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]);
+
+ len += snprintf(buf + len, size - len, "%4d %5x %5x ", sampidx,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x003c0000) >> 18,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x03c00000) >> 22);
+ len += snprintf(buf + len, size - len, "%7x %8x ",
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x1c000000) >> 26,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x3));
+ len += snprintf(buf + len, size - len, "%7x %7x ",
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x06000000) >> 25,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x38000000) >> 27);
+ len += snprintf(buf + len, size - len, "%7d %12d ",
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x000003fc) >> 2,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000400) >> 10);
+ len += snprintf(buf + len, size - len, "%12d %12d ",
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000800) >> 11,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00001000) >> 12);
+ len += snprintf(buf + len, size - len, "%12d %12d ",
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x0001e000) >> 13,
+ (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x001e0000) >> 17);
+ len += snprintf(buf + len, size - len, "0x%07x 0x%07x\n",
+ ATH_SAMP_DBG(pcu_obs), ATH_SAMP_DBG(pcu_cr));
+ }
+
+ len += snprintf(buf + len, size - len,
+ "Sample ChNoise Chain privNF #Reading Readings\n");
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ h = ATH_SAMP_DBG(nfCalHist);
+ if (!ATH_SAMP_DBG(noise))
+ continue;
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (!(chainmask & (1 << i)) ||
+ ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
+ continue;
+
+ nread = AR_PHY_CCA_FILTERWINDOW_LENGTH -
+ h[i].invalidNFcount;
+ len += snprintf(buf + len, size - len,
+ "%4d %5d %4d\t %d\t %d\t",
+ sampidx, ATH_SAMP_DBG(noise),
+ i, h[i].privNF, nread);
+ for (j = 0; j < nread; j++)
+ len += snprintf(buf + len, size - len,
+ " %d", h[i].nfCalBuffer[j]);
+ len += snprintf(buf + len, size - len, "\n");
+ }
+ }
+ len += snprintf(buf + len, size - len, "\nCycle counters:\n"
+ "Sample Total Rxbusy Rxframes Txframes\n");
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ if (!ATH_SAMP_DBG(cc.cycles))
+ continue;
+ len += snprintf(buf + len, size - len,
+ "%4d %08x %08x %08x %08x\n",
+ sampidx, ATH_SAMP_DBG(cc.cycles),
+ ATH_SAMP_DBG(cc.rx_busy),
+ ATH_SAMP_DBG(cc.rx_frame),
+ ATH_SAMP_DBG(cc.tx_frame));
+ }
+
+ len += snprintf(buf + len, size - len, "Tx status Dump :\n");
+ len += snprintf(buf + len, size - len,
+ "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb "
+ "isok rts_fail data_fail rate tid qid "
+ "ba_low ba_high tx_before(ms)\n");
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
+ if (!ATH_SAMP_DBG(ts[i].jiffies))
+ continue;
+ len += snprintf(buf + len, size - len, "%-14d"
+ "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-8d "
+ "%-9d %-4d %-3d %-3d %08x %08x %-11d\n",
+ sampidx,
+ ATH_SAMP_DBG(ts[i].rssi_ctl0),
+ ATH_SAMP_DBG(ts[i].rssi_ctl1),
+ ATH_SAMP_DBG(ts[i].rssi_ctl2),
+ ATH_SAMP_DBG(ts[i].rssi_ext0),
+ ATH_SAMP_DBG(ts[i].rssi_ext1),
+ ATH_SAMP_DBG(ts[i].rssi_ext2),
+ ATH_SAMP_DBG(ts[i].rssi),
+ ATH_SAMP_DBG(ts[i].isok),
+ ATH_SAMP_DBG(ts[i].rts_fail_cnt),
+ ATH_SAMP_DBG(ts[i].data_fail_cnt),
+ ATH_SAMP_DBG(ts[i].rateindex),
+ ATH_SAMP_DBG(ts[i].tid),
+ ATH_SAMP_DBG(ts[i].qid),
+ ATH_SAMP_DBG(ts[i].ba_low),
+ ATH_SAMP_DBG(ts[i].ba_high),
+ jiffies_to_msecs(jiffies -
+ ATH_SAMP_DBG(ts[i].jiffies)));
+ }
+ }
+
+ len += snprintf(buf + len, size - len, "Rx status Dump :\n");
+ len += snprintf(buf + len, size - len, "Sample rssi:- ctl0 ctl1 ctl2 "
+ "ext0 ext1 ext2 comb beacon ant rate rx_before(ms)\n");
+ for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
+ for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
+ if (!ATH_SAMP_DBG(rs[i].jiffies))
+ continue;
+ len += snprintf(buf + len, size - len, "%-14d"
+ "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-9s %-2d %02x %-13d\n",
+ sampidx,
+ ATH_SAMP_DBG(rs[i].rssi_ctl0),
+ ATH_SAMP_DBG(rs[i].rssi_ctl1),
+ ATH_SAMP_DBG(rs[i].rssi_ctl2),
+ ATH_SAMP_DBG(rs[i].rssi_ext0),
+ ATH_SAMP_DBG(rs[i].rssi_ext1),
+ ATH_SAMP_DBG(rs[i].rssi_ext2),
+ ATH_SAMP_DBG(rs[i].rssi),
+ ATH_SAMP_DBG(rs[i].is_mybeacon) ?
+ "True" : "False",
+ ATH_SAMP_DBG(rs[i].antenna),
+ ATH_SAMP_DBG(rs[i].rate),
+ jiffies_to_msecs(jiffies -
+ ATH_SAMP_DBG(rs[i].jiffies)));
+ }
+ }
+
+ vfree(bb_mac_samp);
+ file->private_data = buf;
+
+ return 0;
+#undef ATH_SAMP_DBG
+}
+
+static const struct file_operations fops_samps = {
+ .open = open_file_bb_mac_samps,
+ .read = ath9k_debugfs_read_buf,
+ .release = ath9k_debugfs_release_buf,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
@@ -1206,6 +1653,14 @@ int ath9k_init_debug(struct ath_hw *ah)
&ah->config.cwm_ignore_extcca);
debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_regdump);
+ debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_dump_nfcal);
+ debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_base_eeprom);
+ debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_modal_eeprom);
+ debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_samps);
debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
@@ -1214,5 +1669,9 @@ int ath9k_init_debug(struct ath_hw *ah)
sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
sc->debug.regidx = 0;
+ memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp));
+ sc->debug.sampidx = 0;
+ sc->debug.tsidx = 0;
+ sc->debug.rsidx = 0;
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 4a04510e1111..356352ac2d6e 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -25,8 +25,10 @@ struct ath_buf;
#ifdef CONFIG_ATH9K_DEBUGFS
#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
+#define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++
#else
#define TX_STAT_INC(q, c) do { } while (0)
+#define RESET_STAT_INC(sc, type) do { } while (0)
#endif
#ifdef CONFIG_ATH9K_DEBUGFS
@@ -171,23 +173,80 @@ struct ath_rx_stats {
u8 rs_antenna;
};
+enum ath_reset_type {
+ RESET_TYPE_BB_HANG,
+ RESET_TYPE_BB_WATCHDOG,
+ RESET_TYPE_FATAL_INT,
+ RESET_TYPE_TX_ERROR,
+ RESET_TYPE_TX_HANG,
+ RESET_TYPE_PLL_HANG,
+ __RESET_TYPE_MAX
+};
+
struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
struct ath_rx_stats rxstats;
+ u32 reset[__RESET_TYPE_MAX];
+};
+
+#define ATH_DBG_MAX_SAMPLES 10
+struct ath_dbg_bb_mac_samp {
+ u32 dma_dbg_reg_vals[ATH9K_NUM_DMA_DEBUG_REGS];
+ u32 pcu_obs, pcu_cr, noise;
+ struct {
+ u64 jiffies;
+ int8_t rssi_ctl0;
+ int8_t rssi_ctl1;
+ int8_t rssi_ctl2;
+ int8_t rssi_ext0;
+ int8_t rssi_ext1;
+ int8_t rssi_ext2;
+ int8_t rssi;
+ bool isok;
+ u8 rts_fail_cnt;
+ u8 data_fail_cnt;
+ u8 rateindex;
+ u8 qid;
+ u8 tid;
+ u32 ba_low;
+ u32 ba_high;
+ } ts[ATH_DBG_MAX_SAMPLES];
+ struct {
+ u64 jiffies;
+ int8_t rssi_ctl0;
+ int8_t rssi_ctl1;
+ int8_t rssi_ctl2;
+ int8_t rssi_ext0;
+ int8_t rssi_ext1;
+ int8_t rssi_ext2;
+ int8_t rssi;
+ bool is_mybeacon;
+ u8 antenna;
+ u8 rate;
+ } rs[ATH_DBG_MAX_SAMPLES];
+ struct ath_cycle_counters cc;
+ struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
};
struct ath9k_debug {
struct dentry *debugfs_phy;
u32 regidx;
struct ath_stats stats;
+ spinlock_t samp_lock;
+ struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES];
+ u8 sampidx;
+ u8 tsidx;
+ u8 rsidx;
};
int ath9k_init_debug(struct ath_hw *ah);
+void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_tx_status *ts, struct ath_txq *txq);
+ 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);
#else
@@ -197,6 +256,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
return 0;
}
+static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
+{
+}
+
static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
enum ath9k_int status)
{
@@ -205,7 +268,8 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
static inline void ath_debug_stat_tx(struct ath_softc *sc,
struct ath_buf *bf,
struct ath_tx_status *ts,
- struct ath_txq *txq)
+ struct ath_txq *txq,
+ unsigned int flags)
{
}
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index e61404dda8c5..e46f751ab508 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -456,12 +456,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
pPdGainBoundaries[i] =
min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
- if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
- minDelta = pPdGainBoundaries[0] - 23;
- pPdGainBoundaries[0] = 23;
- } else {
- minDelta = 0;
- }
+ minDelta = 0;
if (i == 0) {
if (AR_SREV_9280_20_OR_LATER(ah))
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index de99c0da52e4..49abd34be741 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -104,16 +104,11 @@
#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
-#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
-#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2
-#define AR_EEPROM_RFSILENT_POLARITY 0x0002
-#define AR_EEPROM_RFSILENT_POLARITY_S 1
-
#define EEP_RFSILENT_ENABLED 0x0001
#define EEP_RFSILENT_ENABLED_S 0
#define EEP_RFSILENT_POLARITY 0x0002
#define EEP_RFSILENT_POLARITY_S 1
-#define EEP_RFSILENT_GPIO_SEL 0x001c
+#define EEP_RFSILENT_GPIO_SEL (AR_SREV_9462(ah) ? 0x00fc : 0x001c)
#define EEP_RFSILENT_GPIO_SEL_S 2
#define AR5416_OPFLAGS_11A 0x01
@@ -225,7 +220,6 @@ enum eeprom_param {
EEP_MAC_MID,
EEP_MAC_LSW,
EEP_REG_0,
- EEP_REG_1,
EEP_OP_CAP,
EEP_OP_MODE,
EEP_RF_SILENT,
@@ -253,7 +247,9 @@ enum eeprom_param {
EEP_PAPRD,
EEP_MODAL_VER,
EEP_ANT_DIV_CTL1,
- EEP_CHAIN_MASK_REDUCE
+ EEP_CHAIN_MASK_REDUCE,
+ EEP_ANTENNA_GAIN_2G,
+ EEP_ANTENNA_GAIN_5G
};
enum ar5416_rates {
@@ -649,14 +645,15 @@ struct eeprom_ops {
int (*check_eeprom)(struct ath_hw *hw);
u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param);
bool (*fill_eeprom)(struct ath_hw *hw);
+ u32 (*dump_eeprom)(struct ath_hw *hw, bool dump_base_hdr, u8 *buf,
+ u32 len, u32 size);
int (*get_eeprom_ver)(struct ath_hw *hw);
int (*get_eeprom_rev)(struct ath_hw *hw);
void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
u16 cfgCtl, u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower, u8 powerLimit,
- bool test);
+ u8 powerLimit, bool test);
u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 47cc95086e6e..9a7520f987f0 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -72,6 +72,117 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
return __ath9k_hw_4k_fill_eeprom(ah);
}
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size,
+ struct modal_eep_4k_header *modal_hdr)
+{
+ PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
+ PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
+ PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
+ PR_EEP("Switch Settle", modal_hdr->switchSettling);
+ PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
+ PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
+ PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+ PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);
+ PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);
+ PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
+ PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
+ PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+ PR_EEP("CCA Threshold)", modal_hdr->thresh62);
+ PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+ PR_EEP("xpdGain", modal_hdr->xpdGain);
+ PR_EEP("External PD", modal_hdr->xpd);
+ PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
+ PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
+ PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
+ PR_EEP("O/D Bias Version", modal_hdr->version);
+ PR_EEP("CCK OutputBias", modal_hdr->ob_0);
+ PR_EEP("BPSK OutputBias", modal_hdr->ob_1);
+ PR_EEP("QPSK OutputBias", modal_hdr->ob_2);
+ PR_EEP("16QAM OutputBias", modal_hdr->ob_3);
+ PR_EEP("64QAM OutputBias", modal_hdr->ob_4);
+ PR_EEP("CCK Driver1_Bias", modal_hdr->db1_0);
+ PR_EEP("BPSK Driver1_Bias", modal_hdr->db1_1);
+ PR_EEP("QPSK Driver1_Bias", modal_hdr->db1_2);
+ PR_EEP("16QAM Driver1_Bias", modal_hdr->db1_3);
+ PR_EEP("64QAM Driver1_Bias", modal_hdr->db1_4);
+ PR_EEP("CCK Driver2_Bias", modal_hdr->db2_0);
+ PR_EEP("BPSK Driver2_Bias", modal_hdr->db2_1);
+ PR_EEP("QPSK Driver2_Bias", modal_hdr->db2_2);
+ PR_EEP("16QAM Driver2_Bias", modal_hdr->db2_3);
+ PR_EEP("64QAM Driver2_Bias", modal_hdr->db2_4);
+ PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+ PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+ PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+ PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
+ PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
+ PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
+ PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
+ PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);
+ PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);
+ PR_EEP("Ant. Diversity ctl1", modal_hdr->antdiv_ctl1);
+ PR_EEP("Ant. Diversity ctl2", modal_hdr->antdiv_ctl2);
+ PR_EEP("TX Diversity", modal_hdr->tx_diversity);
+
+ return len;
+}
+
+static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+ struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+
+ if (!dump_base_hdr) {
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
+ len += ath9k_dump_4k_modal_eeprom(buf, len, size,
+ &eep->modalHeader);
+ goto out;
+ }
+
+ PR_EEP("Major Version", pBase->version >> 12);
+ PR_EEP("Minor Version", pBase->version & 0xFFF);
+ PR_EEP("Checksum", pBase->checksum);
+ PR_EEP("Length", pBase->length);
+ PR_EEP("RegDomain1", pBase->regDmn[0]);
+ PR_EEP("RegDomain2", pBase->regDmn[1]);
+ PR_EEP("TX Mask", pBase->txMask);
+ PR_EEP("RX Mask", pBase->rxMask);
+ PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
+ PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
+ PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT20));
+ PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT40));
+ PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT20));
+ PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT40));
+ PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
+ PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
+ PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
+ PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
+ PR_EEP("TX Gain type", pBase->txGainType);
+
+ len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
+
+out:
+ if (len > size)
+ len = size;
+
+ return len;
+}
+#else
+static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ return 0;
+}
+#endif
+
+
#undef SIZE_EEPROM_4K
static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
@@ -211,8 +322,6 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0:
return pBase->regDmn[0];
- case EEP_REG_1:
- return pBase->regDmn[1];
case EEP_OP_CAP:
return pBase->deviceCap;
case EEP_OP_MODE:
@@ -238,18 +347,16 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
case EEP_ANT_DIV_CTL1:
return pModal->antdiv_ctl1;
case EEP_TXGAIN_TYPE:
- if (ver_minor >= AR5416_EEP_MINOR_VER_19)
- return pBase->txGainType;
- else
- return AR5416_EEP_TXGAIN_ORIGINAL;
+ return pBase->txGainType;
+ case EEP_ANTENNA_GAIN_2G:
+ return pModal->antennaGainCh[0];
default:
return 0;
}
}
static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- int16_t *pTxPowerIndexOffset)
+ struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
@@ -298,12 +405,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
- if (AR_SREV_5416_20_OR_LATER(ah) &&
- (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
- (i != 0)) {
- regChainOffset = (i == 1) ? 0x2000 : 0x1000;
- } else
- regChainOffset = i * 0x1000;
+ regChainOffset = i * 0x1000;
if (pEepData->baseEepHeader.txMask & (1 << i)) {
pRawDataset = pEepData->calPierData2G[i];
@@ -316,19 +418,17 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
ENABLE_REGWRITE_BUFFER(ah);
- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
- REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
- SM(pdGainOverlap_t2,
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
- | SM(gainBoundaries[0],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
- | SM(gainBoundaries[1],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
- | SM(gainBoundaries[2],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
- | SM(gainBoundaries[3],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
- }
+ REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+ | SM(gainBoundaries[0],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+ | SM(gainBoundaries[1],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+ | SM(gainBoundaries[2],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+ | SM(gainBoundaries[3],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
for (j = 0; j < 32; j++) {
@@ -356,16 +456,13 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah);
}
}
-
- *pTxPowerIndexOffset = 0;
}
static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
- u16 AntennaReduction,
- u16 twiceMaxRegulatoryPower,
+ u16 antenna_reduction,
u16 powerLimit)
{
#define CMP_TEST_GRP \
@@ -374,20 +471,16 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
|| (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
int i;
- int16_t twiceLargestAntenna;
u16 twiceMinEdgePower;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 scaledPower = 0, minCtlPower;
u16 numCtlModes;
const u16 *pCtlMode;
u16 ctlMode, freq;
struct chan_centers centers;
struct cal_ctl_data_4k *rep;
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
- static const u16 tpScaleReductionTable[5] =
- { 0, 3, 6, 9, MAX_RATE_POWER };
struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
0, { 0, 0, 0, 0}
};
@@ -405,19 +498,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
ath9k_hw_get_channel_centers(ah, chan, &centers);
- twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
- twiceLargestAntenna = (int16_t)min(AntennaReduction -
- twiceLargestAntenna, 0);
-
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
- maxRegAllowedPower -=
- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
- }
-
- scaledPower = min(powerLimit, maxRegAllowedPower);
- scaledPower = max((u16)0, scaledPower);
-
+ scaledPower = powerLimit - antenna_reduction;
numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
pCtlMode = ctlModesFor11g;
@@ -573,14 +654,12 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan,
u16 cfgCtl,
u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
int16_t ratesArray[Ar5416RateSize];
- int16_t txPowerIndexOffset = 0;
u8 ht40PowerIncForPdadc = 2;
int i;
@@ -594,14 +673,12 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
ath9k_hw_set_4k_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl,
twiceAntennaReduction,
- twiceMaxRegulatoryPower,
powerLimit);
- ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
+ ath9k_hw_set_4k_power_cal_table(ah, chan);
regulatory->max_power_level = 0;
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
if (ratesArray[i] > MAX_RATE_POWER)
ratesArray[i] = MAX_RATE_POWER;
@@ -612,19 +689,8 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
if (test)
return;
- /* Update regulatory */
- i = rate6mb;
- if (IS_CHAN_HT40(chan))
- i = rateHt40_0;
- else if (IS_CHAN_HT20(chan))
- i = rateHt20_0;
-
- regulatory->max_power_level = ratesArray[i];
-
- if (AR_SREV_9280_20_OR_LATER(ah)) {
- for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
- }
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
ENABLE_REGWRITE_BUFFER(ah);
@@ -694,28 +760,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah);
}
-static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- struct modal_eep_4k_header *pModal;
- struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
- u8 biaslevel;
-
- if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
- return;
-
- if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
- return;
-
- pModal = &eep->modalHeader;
-
- if (pModal->xpaBiasLvl != 0xff) {
- biaslevel = pModal->xpaBiasLvl;
- INI_RA(&ah->iniAddac, 7, 1) =
- (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
- }
-}
-
static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
struct modal_eep_4k_header *pModal,
struct ar5416_eeprom_4k *eep,
@@ -783,6 +827,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
u8 txRxAttenLocal;
u8 ob[5], db1[5], db2[5];
u8 ant_div_control1, ant_div_control2;
+ u8 bb_desired_scale;
u32 regVal;
pModal = &eep->modalHeader;
@@ -1002,30 +1047,29 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
AR_PHY_SETTLING_SWITCH,
pModal->swSettleHt40);
}
- if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
- u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
- EEP_4K_BB_DESIRED_SCALE_MASK);
- if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
- u32 pwrctrl, mask, clr;
-
- mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
- pwrctrl = mask * bb_desired_scale;
- clr = mask * 0x1f;
- REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
- REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
-
- mask = BIT(0)|BIT(5)|BIT(15);
- pwrctrl = mask * bb_desired_scale;
- clr = mask * 0x1f;
- REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
-
- mask = BIT(0)|BIT(5);
- pwrctrl = mask * bb_desired_scale;
- clr = mask * 0x1f;
- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
- }
+
+ bb_desired_scale = (pModal->bb_scale_smrt_antenna &
+ EEP_4K_BB_DESIRED_SCALE_MASK);
+ if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
+ u32 pwrctrl, mask, clr;
+
+ mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
+ pwrctrl = mask * bb_desired_scale;
+ clr = mask * 0x1f;
+ REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
+ REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
+
+ mask = BIT(0)|BIT(5)|BIT(15);
+ pwrctrl = mask * bb_desired_scale;
+ clr = mask * 0x1f;
+ REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
+
+ mask = BIT(0)|BIT(5);
+ pwrctrl = mask * bb_desired_scale;
+ clr = mask * 0x1f;
+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
}
}
@@ -1063,10 +1107,10 @@ const struct eeprom_ops eep_4k_ops = {
.check_eeprom = ath9k_hw_4k_check_eeprom,
.get_eeprom = ath9k_hw_4k_get_eeprom,
.fill_eeprom = ath9k_hw_4k_fill_eeprom,
+ .dump_eeprom = ath9k_hw_4k_dump_eeprom,
.get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
.set_board_values = ath9k_hw_4k_set_board_values,
- .set_addac = ath9k_hw_4k_set_addac,
.set_txpower = ath9k_hw_4k_set_txpower,
.get_spur_channel = ath9k_hw_4k_get_spur_channel
};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index d6f6b192f450..4f5c50a87ce3 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -76,6 +76,111 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
return __ath9k_hw_ar9287_fill_eeprom(ah);
}
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size,
+ struct modal_eep_ar9287_header *modal_hdr)
+{
+ PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
+ PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]);
+ PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
+ PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
+ PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
+ PR_EEP("Switch Settle", modal_hdr->switchSettling);
+ PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
+ PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
+ PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
+ PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
+ PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+ PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
+ PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
+ PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+ PR_EEP("CCA Threshold)", modal_hdr->thresh62);
+ PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+ PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
+ PR_EEP("xpdGain", modal_hdr->xpdGain);
+ PR_EEP("External PD", modal_hdr->xpd);
+ PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
+ PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
+ PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
+ PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
+ PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
+ PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+ PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+ PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+ PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
+ PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
+ PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
+ PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
+ PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
+ PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
+ PR_EEP("AR92x7 Version", modal_hdr->version);
+ PR_EEP("DriverBias1", modal_hdr->db1);
+ PR_EEP("DriverBias2", modal_hdr->db1);
+ PR_EEP("CCK OutputBias", modal_hdr->ob_cck);
+ PR_EEP("PSK OutputBias", modal_hdr->ob_psk);
+ PR_EEP("QAM OutputBias", modal_hdr->ob_qam);
+ PR_EEP("PAL_OFF OutputBias", modal_hdr->ob_pal_off);
+
+ return len;
+}
+
+static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
+
+ if (!dump_base_hdr) {
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
+ len += ar9287_dump_modal_eeprom(buf, len, size,
+ &eep->modalHeader);
+ goto out;
+ }
+
+ PR_EEP("Major Version", pBase->version >> 12);
+ PR_EEP("Minor Version", pBase->version & 0xFFF);
+ PR_EEP("Checksum", pBase->checksum);
+ PR_EEP("Length", pBase->length);
+ PR_EEP("RegDomain1", pBase->regDmn[0]);
+ PR_EEP("RegDomain2", pBase->regDmn[1]);
+ PR_EEP("TX Mask", pBase->txMask);
+ PR_EEP("RX Mask", pBase->rxMask);
+ PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
+ PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
+ PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT20));
+ PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT40));
+ PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT20));
+ PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT40));
+ PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
+ PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
+ PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
+ PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
+ PR_EEP("Power Table Offset", pBase->pwrTableOffset);
+ PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
+
+ len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
+
+out:
+ if (len > size)
+ len = size;
+
+ return len;
+}
+#else
+static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ return 0;
+}
+#endif
+
+
static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
{
u32 sum = 0, el, integer;
@@ -203,8 +308,6 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0:
return pBase->regDmn[0];
- case EEP_REG_1:
- return pBase->regDmn[1];
case EEP_OP_CAP:
return pBase->deviceCap;
case EEP_OP_MODE:
@@ -231,6 +334,9 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
return pBase->tempSensSlopePalOn;
else
return 0;
+ case EEP_ANTENNA_GAIN_2G:
+ return max_t(u8, pModal->antennaGainCh[0],
+ pModal->antennaGainCh[1]);
default:
return 0;
}
@@ -307,8 +413,7 @@ static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
}
static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- int16_t *pTxPowerIndexOffset)
+ struct ath9k_channel *chan)
{
struct cal_data_per_freq_ar9287 *pRawDataset;
struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
@@ -444,16 +549,13 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah);
}
}
-
- *pTxPowerIndexOffset = 0;
}
static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
- u16 AntennaReduction,
- u16 twiceMaxRegulatoryPower,
+ u16 antenna_reduction,
u16 powerLimit)
{
#define CMP_CTL \
@@ -467,12 +569,8 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
u16 twiceMaxEdgePower = MAX_RATE_POWER;
- static const u16 tpScaleReductionTable[5] =
- { 0, 3, 6, 9, MAX_RATE_POWER };
int i;
- int16_t twiceLargestAntenna;
struct cal_ctl_data_ar9287 *rep;
struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
targetPowerCck = {0, {0, 0, 0, 0} };
@@ -480,7 +578,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
targetPowerCckExt = {0, {0, 0, 0, 0} };
struct cal_target_power_ht targetPowerHt20,
targetPowerHt40 = {0, {0, 0, 0, 0} };
- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 scaledPower = 0, minCtlPower;
static const u16 ctlModesFor11g[] = {
CTL_11B, CTL_11G, CTL_2GHT20,
CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
@@ -495,24 +593,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
tx_chainmask = ah->txchainmask;
ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- /* Compute TxPower reduction due to Antenna Gain */
- twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
- pEepData->modalHeader.antennaGainCh[1]);
- twiceLargestAntenna = (int16_t)min((AntennaReduction) -
- twiceLargestAntenna, 0);
-
- /*
- * scaledPower is the minimum of the user input power level
- * and the regulatory allowed power level.
- */
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
- maxRegAllowedPower -=
- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
-
- scaledPower = min(powerLimit, maxRegAllowedPower);
+ scaledPower = powerLimit - antenna_reduction;
/*
* Reduce scaled Power by number of chains active
@@ -713,14 +794,12 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
int16_t ratesArray[Ar5416RateSize];
- int16_t txPowerIndexOffset = 0;
u8 ht40PowerIncForPdadc = 2;
int i;
@@ -733,14 +812,12 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl,
twiceAntennaReduction,
- twiceMaxRegulatoryPower,
powerLimit);
- ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
+ ath9k_hw_set_ar9287_power_cal_table(ah, chan);
regulatory->max_power_level = 0;
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
if (ratesArray[i] > MAX_RATE_POWER)
ratesArray[i] = MAX_RATE_POWER;
@@ -751,17 +828,8 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
if (test)
return;
- if (IS_CHAN_2GHZ(chan))
- i = rate1l;
- else
- i = rate6mb;
-
- regulatory->max_power_level = ratesArray[i];
-
- if (AR_SREV_9280_20_OR_LATER(ah)) {
- for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
- }
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
ENABLE_REGWRITE_BUFFER(ah);
@@ -851,11 +919,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah);
}
-static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
-}
-
static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
struct ath9k_channel *chan)
{
@@ -1003,10 +1066,10 @@ const struct eeprom_ops eep_ar9287_ops = {
.check_eeprom = ath9k_hw_ar9287_check_eeprom,
.get_eeprom = ath9k_hw_ar9287_get_eeprom,
.fill_eeprom = ath9k_hw_ar9287_fill_eeprom,
+ .dump_eeprom = ath9k_hw_ar9287_dump_eeprom,
.get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev,
.set_board_values = ath9k_hw_ar9287_set_board_values,
- .set_addac = ath9k_hw_ar9287_set_addac,
.set_txpower = ath9k_hw_ar9287_set_txpower,
.get_spur_channel = ath9k_hw_ar9287_get_spur_channel
};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index b9540a992616..81e629671679 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -133,6 +133,136 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
#undef SIZE_EEPROM_DEF
+#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
+static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
+ struct modal_eep_header *modal_hdr)
+{
+ PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
+ PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]);
+ PR_EEP("Chain2 Ant. Control", modal_hdr->antCtrlChain[2]);
+ PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
+ PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
+ PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
+ PR_EEP("Chain2 Ant. Gain", modal_hdr->antennaGainCh[2]);
+ PR_EEP("Switch Settle", modal_hdr->switchSettling);
+ PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
+ PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
+ PR_EEP("Chain2 TxRxAtten", modal_hdr->txRxAttenCh[2]);
+ PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
+ PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
+ PR_EEP("Chain2 RxTxMargin", modal_hdr->rxTxMarginCh[2]);
+ PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
+ PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);
+ PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);
+ PR_EEP("Chain1 xlna Gain", modal_hdr->xlnaGainCh[1]);
+ PR_EEP("Chain2 xlna Gain", modal_hdr->xlnaGainCh[2]);
+ PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
+ PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
+ PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
+ PR_EEP("CCA Threshold)", modal_hdr->thresh62);
+ PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
+ PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
+ PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);
+ PR_EEP("xpdGain", modal_hdr->xpdGain);
+ PR_EEP("External PD", modal_hdr->xpd);
+ PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
+ PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
+ PR_EEP("Chain2 I Coefficient", modal_hdr->iqCalICh[2]);
+ PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
+ PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
+ PR_EEP("Chain2 Q Coefficient", modal_hdr->iqCalQCh[2]);
+ PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
+ PR_EEP("Chain0 OutputBias", modal_hdr->ob);
+ PR_EEP("Chain0 DriverBias", modal_hdr->db);
+ PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
+ PR_EEP("2chain pwr decrease", modal_hdr->pwrDecreaseFor2Chain);
+ PR_EEP("3chain pwr decrease", modal_hdr->pwrDecreaseFor3Chain);
+ PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
+ PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
+ PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
+ PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
+ PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
+ PR_EEP("Chain2 bswAtten", modal_hdr->bswAtten[2]);
+ PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
+ PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
+ PR_EEP("Chain2 bswMargin", modal_hdr->bswMargin[2]);
+ PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
+ PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);
+ PR_EEP("Chain1 xatten2Db", modal_hdr->xatten2Db[1]);
+ PR_EEP("Chain2 xatten2Db", modal_hdr->xatten2Db[2]);
+ PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);
+ PR_EEP("Chain1 xatten2Margin", modal_hdr->xatten2Margin[1]);
+ PR_EEP("Chain2 xatten2Margin", modal_hdr->xatten2Margin[2]);
+ PR_EEP("Chain1 OutputBias", modal_hdr->ob_ch1);
+ PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1);
+ PR_EEP("LNA Control", modal_hdr->lna_ctl);
+ PR_EEP("XPA Bias Freq0", modal_hdr->xpaBiasLvlFreq[0]);
+ PR_EEP("XPA Bias Freq1", modal_hdr->xpaBiasLvlFreq[1]);
+ PR_EEP("XPA Bias Freq2", modal_hdr->xpaBiasLvlFreq[2]);
+
+ return len;
+}
+
+static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+
+ if (!dump_base_hdr) {
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
+ len += ath9k_def_dump_modal_eeprom(buf, len, size,
+ &eep->modalHeader[0]);
+ len += snprintf(buf + len, size - len,
+ "%20s :\n", "5GHz modal Header");
+ len += ath9k_def_dump_modal_eeprom(buf, len, size,
+ &eep->modalHeader[1]);
+ goto out;
+ }
+
+ PR_EEP("Major Version", pBase->version >> 12);
+ PR_EEP("Minor Version", pBase->version & 0xFFF);
+ PR_EEP("Checksum", pBase->checksum);
+ PR_EEP("Length", pBase->length);
+ PR_EEP("RegDomain1", pBase->regDmn[0]);
+ PR_EEP("RegDomain2", pBase->regDmn[1]);
+ PR_EEP("TX Mask", pBase->txMask);
+ PR_EEP("RX Mask", pBase->rxMask);
+ PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
+ PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
+ PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT20));
+ PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_2G_HT40));
+ PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT20));
+ PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
+ AR5416_OPFLAGS_N_5G_HT40));
+ PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
+ PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
+ PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
+ PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
+ PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
+
+ len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
+
+out:
+ if (len > size)
+ len = size;
+
+ return len;
+}
+#else
+static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
+ u8 *buf, u32 len, u32 size)
+{
+ return 0;
+}
+#endif
+
+
static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
{
struct ar5416_eeprom_def *eep =
@@ -270,6 +400,7 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct modal_eep_header *pModal = eep->modalHeader;
struct base_eep_header *pBase = &eep->baseEepHeader;
+ int band = 0;
switch (param) {
case EEP_NFTHRESH_5:
@@ -284,8 +415,6 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0:
return pBase->regDmn[0];
- case EEP_REG_1:
- return pBase->regDmn[1];
case EEP_OP_CAP:
return pBase->deviceCap;
case EEP_OP_MODE:
@@ -337,6 +466,14 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
return pBase->pwr_table_offset;
else
return AR5416_PWR_TABLE_OFFSET_DB;
+ case EEP_ANTENNA_GAIN_2G:
+ band = 1;
+ /* fall through */
+ case EEP_ANTENNA_GAIN_5G:
+ return max_t(u8, max_t(u8,
+ pModal[band].antennaGainCh[0],
+ pModal[band].antennaGainCh[1]),
+ pModal[band].antennaGainCh[2]);
default:
return 0;
}
@@ -417,8 +554,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
break;
}
- if (AR_SREV_5416_20_OR_LATER(ah) &&
- (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
+ if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
regChainOffset = (i == 1) ? 0x2000 : 0x1000;
else
regChainOffset = i * 0x1000;
@@ -435,9 +571,8 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
SM(pModal->iqCalQCh[i],
AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
- ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
- regChainOffset, i);
+ ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
+ regChainOffset, i);
}
if (AR_SREV_9280_20_OR_LATER(ah)) {
@@ -693,8 +828,7 @@ static void ath9k_adjust_pdadc_values(struct ath_hw *ah,
}
static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- int16_t *pTxPowerIndexOffset)
+ struct ath9k_channel *chan)
{
#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
#define SM_PDGAIN_B(x, y) \
@@ -764,8 +898,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
xpdGainValues[2]);
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- if (AR_SREV_5416_20_OR_LATER(ah) &&
- (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+ if ((ah->rxchainmask == 5 || ah->txchainmask == 5) &&
(i != 0)) {
regChainOffset = (i == 1) ? 0x2000 : 0x1000;
} else
@@ -806,27 +939,24 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
ENABLE_REGWRITE_BUFFER(ah);
- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
- if (OLC_FOR_AR9280_20_LATER) {
- REG_WRITE(ah,
- AR_PHY_TPCRG5 + regChainOffset,
- SM(0x6,
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
- SM_PD_GAIN(1) | SM_PD_GAIN(2) |
- SM_PD_GAIN(3) | SM_PD_GAIN(4));
- } else {
- REG_WRITE(ah,
- AR_PHY_TPCRG5 + regChainOffset,
- SM(pdGainOverlap_t2,
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
- SM_PDGAIN_B(0, 1) |
- SM_PDGAIN_B(1, 2) |
- SM_PDGAIN_B(2, 3) |
- SM_PDGAIN_B(3, 4));
- }
+ if (OLC_FOR_AR9280_20_LATER) {
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ SM(0x6,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+ SM_PD_GAIN(1) | SM_PD_GAIN(2) |
+ SM_PD_GAIN(3) | SM_PD_GAIN(4));
+ } else {
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
+ SM_PDGAIN_B(0, 1) |
+ SM_PDGAIN_B(1, 2) |
+ SM_PDGAIN_B(2, 3) |
+ SM_PDGAIN_B(3, 4));
}
-
ath9k_adjust_pdadc_values(ah, pwr_table_offset,
diff, pdadcValues);
@@ -855,7 +985,6 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
}
}
- *pTxPowerIndexOffset = 0;
#undef SM_PD_GAIN
#undef SM_PDGAIN_B
}
@@ -864,21 +993,15 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
- u16 AntennaReduction,
- u16 twiceMaxRegulatoryPower,
+ u16 antenna_reduction,
u16 powerLimit)
{
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
- static const u16 tpScaleReductionTable[5] =
- { 0, 3, 6, 9, MAX_RATE_POWER };
-
int i;
- int16_t twiceLargestAntenna;
struct cal_ctl_data *rep;
struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
0, { 0, 0, 0, 0}
@@ -890,7 +1013,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
0, {0, 0, 0, 0}
};
- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 scaledPower = 0, minCtlPower;
static const u16 ctlModesFor11a[] = {
CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
};
@@ -909,27 +1032,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
ath9k_hw_get_channel_centers(ah, chan, &centers);
- twiceLargestAntenna = max(
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
-
- twiceLargestAntenna = max((u8)twiceLargestAntenna,
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
-
- twiceLargestAntenna = (int16_t)min(AntennaReduction -
- twiceLargestAntenna, 0);
-
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
- maxRegAllowedPower -=
- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
- }
-
- scaledPower = min(powerLimit, maxRegAllowedPower);
+ scaledPower = powerLimit - antenna_reduction;
switch (ar5416_get_ntxchains(tx_chainmask)) {
case 1:
@@ -1134,7 +1237,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan,
u16 cfgCtl,
u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test)
{
#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
@@ -1143,7 +1245,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
struct modal_eep_header *pModal =
&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
int16_t ratesArray[Ar5416RateSize];
- int16_t txPowerIndexOffset = 0;
u8 ht40PowerIncForPdadc = 2;
int i, cck_ofdm_delta = 0;
@@ -1157,31 +1258,18 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
ath9k_hw_set_def_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl,
twiceAntennaReduction,
- twiceMaxRegulatoryPower,
powerLimit);
- ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
+ ath9k_hw_set_def_power_cal_table(ah, chan);
regulatory->max_power_level = 0;
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
if (ratesArray[i] > MAX_RATE_POWER)
ratesArray[i] = MAX_RATE_POWER;
if (ratesArray[i] > regulatory->max_power_level)
regulatory->max_power_level = ratesArray[i];
}
- if (!test) {
- i = rate6mb;
-
- if (IS_CHAN_HT40(chan))
- i = rateHt40_0;
- else if (IS_CHAN_HT20(chan))
- i = rateHt20_0;
-
- regulatory->max_power_level = ratesArray[i];
- }
-
switch(ar5416_get_ntxchains(ah->txchainmask)) {
case 1:
break;
@@ -1336,6 +1424,7 @@ const struct eeprom_ops eep_def_ops = {
.check_eeprom = ath9k_hw_def_check_eeprom,
.get_eeprom = ath9k_hw_def_get_eeprom,
.fill_eeprom = ath9k_hw_def_fill_eeprom,
+ .dump_eeprom = ath9k_hw_def_dump_eeprom,
.get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
.set_board_values = ath9k_hw_def_set_board_values,
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index bc713fc28191..655576c8fdab 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -48,6 +48,8 @@ void ath_init_leds(struct ath_softc *sc)
sc->sc_ah->led_pin = ATH_LED_PIN_9485;
else if (AR_SREV_9300(sc->sc_ah))
sc->sc_ah->led_pin = ATH_LED_PIN_9300;
+ else if (AR_SREV_9462(sc->sc_ah))
+ sc->sc_ah->led_pin = ATH_LED_PIN_9462;
else
sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
}
@@ -82,9 +84,14 @@ void ath_init_leds(struct ath_softc *sc)
static bool ath_is_rfkill_set(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
+ bool is_blocked;
- return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
+ ath9k_ps_wakeup(sc);
+ is_blocked = ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
ah->rfkill_polarity;
+ ath9k_ps_restore(sc);
+
+ return is_blocked;
}
void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
@@ -148,7 +155,8 @@ static void ath9k_gen_timer_start(struct ath_hw *ah,
if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
ath9k_hw_disable_interrupts(ah);
ah->imask |= ATH9K_INT_GENTIMER;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
}
}
@@ -162,7 +170,8 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
if (timer_table->timer_mask.val == 0) {
ath9k_hw_disable_interrupts(ah);
ah->imask &= ~ATH9K_INT_GENTIMER;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
}
}
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index d3f4a59cd456..77c8ded8de57 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
{ USB_DEVICE(0x040D, 0x3801) }, /* VIA */
{ USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
+ { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */
{ USB_DEVICE(0x0cf3, 0x7015),
.driver_info = AR9287_USB }, /* Atheros */
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 5bc022087e65..da5596766d82 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -521,8 +521,6 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv,
u8 enable_coex);
-void ath9k_htc_station_work(struct work_struct *work);
-void ath9k_htc_aggr_work(struct work_struct *work);
void ath9k_htc_ani_work(struct work_struct *work);
void ath9k_htc_start_ani(struct ath9k_htc_priv *priv);
void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);
@@ -542,7 +540,6 @@ int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv);
void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot);
void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv);
void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event);
-void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv);
void ath9k_tx_failed_tasklet(unsigned long data);
void ath9k_htc_tx_cleanup_timer(unsigned long data);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
index db2352e5cc0d..e3a02eb8e0cc 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -228,8 +228,14 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv)
static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
{
- return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
- priv->ah->rfkill_polarity;
+ bool is_blocked;
+
+ ath9k_htc_ps_wakeup(priv);
+ is_blocked = ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
+ priv->ah->rfkill_polarity;
+ ath9k_htc_ps_restore(priv);
+
+ return is_blocked;
}
void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 3bea7ea86f0a..966661c9e586 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -509,8 +509,8 @@ static void setup_ht_cap(struct ath9k_htc_priv *priv,
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
/* ath9k_htc supports only 1 or 2 stream devices */
- tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
- rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
+ tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
+ rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
ath_dbg(common, ATH_DBG_CONFIG,
"TX streams %d, RX streams: %d\n",
@@ -572,25 +572,6 @@ err:
return -EINVAL;
}
-static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
-{
- struct ath_common *common = ath9k_hw_common(priv->ah);
- int i = 0;
-
- /* Get the hardware key cache size. */
- common->keymax = AR_KEYTABLE_SIZE;
-
- if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
- common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
-
- /*
- * Reset the key cache since some parts do not
- * reset the contents on initial power up.
- */
- for (i = 0; i < common->keymax; i++)
- ath_hw_keyreset(common, (u16) i);
-}
-
static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
{
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
@@ -620,9 +601,6 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
- common->tx_chainmask = priv->ah->caps.tx_chainmask;
- common->rx_chainmask = priv->ah->caps.rx_chainmask;
-
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
priv->ah->opmode = NL80211_IFTYPE_STATION;
@@ -666,7 +644,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
return -ENOMEM;
ah->hw_version.devid = devid;
- ah->hw_version.subsysid = 0; /* FIXME */
ah->hw_version.usbdev = drv_info;
ah->ah_flags |= AH_USE_EEPROM;
ah->reg_ops.read = ath9k_regread;
@@ -721,7 +698,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
priv->cur_beacon_conf.bslot[i] = NULL;
- ath9k_init_crypto(priv);
+ ath9k_cmn_init_crypto(ah);
ath9k_init_channels_rates(priv);
ath9k_init_misc(priv);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 7212acb2bd6c..0b9a0e8a4958 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -826,8 +826,7 @@ void ath9k_htc_ani_work(struct work_struct *work)
if (longcal || shortcal)
common->ani.caldone =
ath9k_hw_calibrate(ah, ah->curchan,
- common->rx_chainmask,
- longcal);
+ ah->rxchainmask, longcal);
ath9k_htc_ps_restore(priv);
}
@@ -1300,6 +1299,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
if (priv->op_flags & OP_INVALID) {
ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY,
"Unable to configure filter on invalid state\n");
+ mutex_unlock(&priv->mutex);
return;
}
ath9k_htc_ps_wakeup(priv);
@@ -1352,7 +1352,8 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
return ret;
}
-static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct ath9k_htc_priv *priv = hw->priv;
@@ -1563,7 +1564,8 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
mutex_unlock(&priv->mutex);
}
-static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw)
+static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ath9k_htc_priv *priv = hw->priv;
u64 tsf;
@@ -1577,7 +1579,8 @@ static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
-static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+static void ath9k_htc_set_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u64 tsf)
{
struct ath9k_htc_priv *priv = hw->priv;
@@ -1588,7 +1591,8 @@ static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf)
mutex_unlock(&priv->mutex);
}
-static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw)
+static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ath9k_htc_priv *priv = hw->priv;
@@ -1736,6 +1740,22 @@ out:
return ret;
}
+
+static int ath9k_htc_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
+{
+ struct ath9k_htc_priv *priv = hw->priv;
+ struct ath_hw *ah = priv->ah;
+ struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats;
+
+ stats->dot11ACKFailureCount = mib_stats->ackrcv_bad;
+ stats->dot11RTSFailureCount = mib_stats->rts_bad;
+ stats->dot11FCSErrorCount = mib_stats->fcs_bad;
+ stats->dot11RTSSuccessCount = mib_stats->rts_good;
+
+ return 0;
+}
+
struct ieee80211_ops ath9k_htc_ops = {
.tx = ath9k_htc_tx,
.start = ath9k_htc_start,
@@ -1759,4 +1779,5 @@ struct ieee80211_ops ath9k_htc_ops = {
.rfkill_poll = ath9k_htc_rfkill_poll_state,
.set_coverage_class = ath9k_htc_set_coverage_class,
.set_bitrate_mask = ath9k_htc_set_bitrate_mask,
+ .get_stats = ath9k_htc_get_stats,
};
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index cb29e8875386..e74c233757a2 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -22,10 +22,12 @@
/* Hardware core and driver accessible callbacks */
static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah,
- int restore,
- int power_off)
+ bool power_off)
{
- ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off);
+ if (ah->aspm_enabled != true)
+ return;
+
+ ath9k_hw_ops(ah)->config_pci_powersave(ah, power_off);
}
static inline void ath9k_hw_rxena(struct ath_hw *ah)
@@ -52,13 +54,10 @@ static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
return ath9k_hw_ops(ah)->get_isr(ah, masked);
}
-static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen,
- bool is_firstseg, bool is_lastseg,
- const void *ds0, dma_addr_t buf_addr,
- unsigned int qcu)
+static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds,
+ struct ath_tx_info *i)
{
- ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg,
- ds0, buf_addr, qcu);
+ return ath9k_hw_ops(ah)->set_txdesc(ah, ds, i);
}
static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
@@ -67,55 +66,6 @@ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
}
-static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
- u32 pktLen, enum ath9k_pkt_type type,
- u32 txPower, u32 keyIx,
- enum ath9k_key_type keyType,
- u32 flags)
-{
- ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx,
- keyType, flags);
-}
-
-static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
- void *lastds,
- u32 durUpdateEn, u32 rtsctsRate,
- u32 rtsctsDuration,
- struct ath9k_11n_rate_series series[],
- u32 nseries, u32 flags)
-{
- ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn,
- rtsctsRate, rtsctsDuration, series,
- nseries, flags);
-}
-
-static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
- u32 aggrLen)
-{
- ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen);
-}
-
-static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
- u32 numDelims)
-{
- ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims);
-}
-
-static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
-{
- ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds);
-}
-
-static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
-{
- ath9k_hw_ops(ah)->clr11n_aggr(ah, ds);
-}
-
-static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
-{
- ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
-}
-
static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf)
{
@@ -231,11 +181,6 @@ static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah)
return ath9k_hw_private_ops(ah)->restore_chainmask(ah);
}
-static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value)
-{
- return ath9k_hw_private_ops(ah)->set_diversity(ah, value);
-}
-
static inline bool ath9k_hw_ani_control(struct ath_hw *ah,
enum ath9k_ani_cmd cmd, int param)
{
@@ -260,4 +205,11 @@ static inline void ath9k_hw_setup_calibration(struct ath_hw *ah,
ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
}
+static inline int ath9k_hw_fast_chan_change(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 *ini_reloaded)
+{
+ return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan,
+ ini_reloaded);
+}
#endif /* ATH9K_HW_OPS_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 8dcefe74f4c3..f16d2033081f 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -284,7 +284,12 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
ah->hw_version.macVersion =
(val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
- ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
+
+ if (AR_SREV_9462(ah))
+ ah->is_pciexpress = true;
+ else
+ ah->is_pciexpress = (val &
+ AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
} else {
if (!AR_SREV_9100(ah))
ah->hw_version.macVersion = MS(val, AR_SREV_VERSION);
@@ -428,7 +433,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
regulatory->country_code = CTRY_DEFAULT;
regulatory->power_limit = MAX_RATE_POWER;
- regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
ah->hw_version.magic = AR5416_MAGIC;
ah->hw_version.subvendorid = 0;
@@ -440,7 +444,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
if (AR_SREV_9100(ah))
ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
ah->enable_32kHz_clock = DONT_USE_32KHZ;
- ah->slottime = 20;
+ ah->slottime = ATH9K_SLOT_TIME_9;
ah->globaltxtimeout = (u32) -1;
ah->power_mode = ATH9K_PM_UNDEFINED;
}
@@ -537,6 +541,9 @@ static int __ath9k_hw_init(struct ath_hw *ah)
return -EIO;
}
+ if (AR_SREV_9462(ah))
+ ah->WARegVal &= ~AR_WA_D3_L1_DISABLE;
+
ath9k_hw_init_defaults(ah);
ath9k_hw_init_config(ah);
@@ -580,6 +587,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
case AR_SREV_VERSION_9330:
case AR_SREV_VERSION_9485:
case AR_SREV_VERSION_9340:
+ case AR_SREV_VERSION_9462:
break;
default:
ath_err(common,
@@ -603,10 +611,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
ath9k_hw_init_mode_regs(ah);
-
- if (ah->is_pciexpress)
- ath9k_hw_aspm_init(ah);
- else
+ if (!ah->is_pciexpress)
ath9k_hw_disablepcie(ah);
if (!AR_SREV_9300_20_OR_LATER(ah))
@@ -621,6 +626,9 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (r)
return r;
+ if (ah->is_pciexpress)
+ ath9k_hw_aspm_init(ah);
+
r = ath9k_hw_init_macaddr(ah);
if (r) {
ath_err(common, "Failed to initialize MAC address\n");
@@ -663,6 +671,8 @@ int ath9k_hw_init(struct ath_hw *ah)
case AR9300_DEVID_AR9485_PCIE:
case AR9300_DEVID_AR9330:
case AR9300_DEVID_AR9340:
+ case AR9300_DEVID_AR9580:
+ case AR9300_DEVID_AR9462:
break;
default:
if (common->bus_ops->ath_bus_type == ATH_USB)
@@ -959,7 +969,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
const struct ath9k_channel *chan = ah->curchan;
- int acktimeout;
+ int acktimeout, ctstimeout;
int slottime;
int sifstime;
int rx_lat = 0, tx_lat = 0, eifs = 0;
@@ -974,7 +984,10 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
if (ah->misc_mode != 0)
REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
- rx_lat = 37;
+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+ rx_lat = 41;
+ else
+ rx_lat = 37;
tx_lat = 54;
if (IS_CHAN_HALF_RATE(chan)) {
@@ -988,7 +1001,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
sifstime = 32;
} else if (IS_CHAN_QUARTER_RATE(chan)) {
eifs = 340;
- rx_lat *= 4;
+ rx_lat = (rx_lat * 4) - 1;
tx_lat *= 4;
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
tx_lat += 22;
@@ -996,8 +1009,14 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
slottime = 21;
sifstime = 64;
} else {
- eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS);
- reg = REG_READ(ah, AR_USEC);
+ if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
+ eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO;
+ reg = AR_USEC_ASYNC_FIFO;
+ } else {
+ eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/
+ common->clockrate;
+ reg = REG_READ(ah, AR_USEC);
+ }
rx_lat = MS(reg, AR_USEC_RX_LAT);
tx_lat = MS(reg, AR_USEC_TX_LAT);
@@ -1010,6 +1029,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
/* As defined by IEEE 802.11-2007 17.3.8.6 */
acktimeout = slottime + sifstime + 3 * ah->coverage_class;
+ ctstimeout = acktimeout;
/*
* Workaround for early ACK timeouts, add an offset to match the
@@ -1024,7 +1044,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
ath9k_hw_set_sifs_time(ah, sifstime);
ath9k_hw_setslottime(ah, slottime);
ath9k_hw_set_ack_timeout(ah, acktimeout);
- ath9k_hw_set_cts_timeout(ah, acktimeout);
+ ath9k_hw_set_cts_timeout(ah, ctstimeout);
if (ah->globaltxtimeout != (u32) -1)
ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
@@ -1329,6 +1349,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
{
+
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
@@ -1370,11 +1391,17 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
static bool ath9k_hw_channel_change(struct ath_hw *ah,
struct ath9k_channel *chan)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *channel = chan->chan;
u32 qnum;
int r;
+ bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+ bool band_switch, mode_diff;
+ u8 ini_reloaded;
+
+ band_switch = (chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ)) !=
+ (ah->curchan->channelFlags & (CHANNEL_2GHZ |
+ CHANNEL_5GHZ));
+ mode_diff = (chan->chanmode != ah->curchan->chanmode);
for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
if (ath9k_hw_numtxpending(ah, qnum)) {
@@ -1389,6 +1416,18 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
return false;
}
+ if (edma && (band_switch || mode_diff)) {
+ ath9k_hw_mark_phy_inactive(ah);
+ udelay(5);
+
+ ath9k_hw_init_pll(ah, NULL);
+
+ if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) {
+ ath_err(common, "Failed to do fast channel change\n");
+ return false;
+ }
+ }
+
ath9k_hw_set_channel_regs(ah, chan);
r = ath9k_hw_rf_set_freq(ah, chan);
@@ -1397,14 +1436,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
return false;
}
ath9k_hw_set_clockrate(ah);
-
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- channel->max_antenna_gain * 2,
- channel->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit), false);
-
+ ath9k_hw_apply_txpower(ah, chan);
ath9k_hw_rfbus_done(ah);
if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
@@ -1412,6 +1444,18 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
ath9k_hw_spur_mitigate_freq(ah, chan);
+ if (edma && (band_switch || mode_diff)) {
+ ah->ah_flags |= AH_FASTCC;
+ if (band_switch || ini_reloaded)
+ ah->eep_ops->set_board_values(ah, chan);
+
+ ath9k_hw_init_bb(ah, chan);
+
+ if (band_switch || ini_reloaded)
+ ath9k_hw_init_cal(ah, chan);
+ ah->ah_flags &= ~AH_FASTCC;
+ }
+
return true;
}
@@ -1467,9 +1511,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
u32 macStaId1;
u64 tsf = 0;
int i, r;
-
- ah->txchainmask = common->tx_chainmask;
- ah->rxchainmask = common->rx_chainmask;
+ bool allow_fbs = false;
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO;
@@ -1486,15 +1528,24 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
memset(caldata, 0, sizeof(*caldata));
ath9k_init_nfcal_hist_buffer(ah, chan);
}
+ ah->noise = ath9k_hw_getchan_noise(ah, chan);
+
+ if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
+ bChannelChange = false;
+
+ if (caldata &&
+ caldata->done_txiqcal_once &&
+ caldata->done_txclcal_once &&
+ caldata->rtt_hist.num_readings)
+ allow_fbs = true;
if (bChannelChange &&
(ah->chip_fullsleep != true) &&
(ah->curchan != NULL) &&
(chan->channel != ah->curchan->channel) &&
- ((chan->channelFlags & CHANNEL_ALL) ==
- (ah->curchan->channelFlags & CHANNEL_ALL)) &&
- (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) {
-
+ (allow_fbs ||
+ ((chan->channelFlags & CHANNEL_ALL) ==
+ (ah->curchan->channelFlags & CHANNEL_ALL)))) {
if (ath9k_hw_channel_change(ah, chan)) {
ath9k_hw_loadnf(ah, ah->curchan);
ath9k_hw_start_nfcal(ah, true);
@@ -1665,6 +1716,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_bb(ah, chan);
+ if (caldata) {
+ caldata->done_txiqcal_once = false;
+ caldata->done_txclcal_once = false;
+ caldata->rtt_hist.num_readings = 0;
+ }
if (!ath9k_hw_init_cal(ah, chan))
return -EIO;
@@ -1734,25 +1790,40 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
{
REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
if (setChip) {
+ if (AR_SREV_9462(ah)) {
+ REG_WRITE(ah, AR_TIMER_MODE,
+ REG_READ(ah, AR_TIMER_MODE) & 0xFFFFFF00);
+ REG_WRITE(ah, AR_NDP2_TIMER_MODE, REG_READ(ah,
+ AR_NDP2_TIMER_MODE) & 0xFFFFFF00);
+ REG_WRITE(ah, AR_SLP32_INC,
+ REG_READ(ah, AR_SLP32_INC) & 0xFFF00000);
+ /* xxx Required for WLAN only case ? */
+ REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
+ udelay(100);
+ }
+
/*
* Clear the RTC force wake bit to allow the
* mac to go to sleep.
*/
- REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_EN);
+ REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+
+ if (AR_SREV_9462(ah))
+ udelay(100);
+
if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
/* Shutdown chip. Active low */
- if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah))
- REG_CLR_BIT(ah, (AR_RTC_RESET),
- AR_RTC_RESET_EN);
+ if (!AR_SREV_5416(ah) &&
+ !AR_SREV_9271(ah) && !AR_SREV_9462_10(ah)) {
+ REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
+ udelay(2);
+ }
}
/* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
- if (AR_SREV_9300_20_OR_LATER(ah))
- REG_WRITE(ah, AR_WA,
- ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
+ REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
}
/*
@@ -1762,6 +1833,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
*/
static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
{
+ u32 val;
+
REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
if (setChip) {
struct ath9k_hw_capabilities *pCap = &ah->caps;
@@ -1771,12 +1844,30 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
REG_WRITE(ah, AR_RTC_FORCE_WAKE,
AR_RTC_FORCE_WAKE_ON_INT);
} else {
+
+ /* When chip goes into network sleep, it could be waken
+ * up by MCI_INT interrupt caused by BT's HW messages
+ * (LNA_xxx, CONT_xxx) which chould be in a very fast
+ * rate (~100us). This will cause chip to leave and
+ * re-enter network sleep mode frequently, which in
+ * consequence will have WLAN MCI HW to generate lots of
+ * SYS_WAKING and SYS_SLEEPING messages which will make
+ * BT CPU to busy to process.
+ */
+ if (AR_SREV_9462(ah)) {
+ val = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_EN) &
+ ~AR_MCI_INTERRUPT_RX_HW_MSG_MASK;
+ REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, val);
+ }
/*
* Clear the RTC force wake bit to allow the
* mac to go to sleep.
*/
REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
AR_RTC_FORCE_WAKE_EN);
+
+ if (AR_SREV_9462(ah))
+ udelay(30);
}
}
@@ -2027,11 +2118,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
regulatory->current_rd = eeval;
- eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
- if (AR_SREV_9285_12_OR_LATER(ah))
- eeval |= AR9285_RDEXT_DEFAULT;
- regulatory->current_rd_ext = eeval;
-
if (ah->opmode != NL80211_IFTYPE_AP &&
ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
if (regulatory->current_rd == 0x64 ||
@@ -2083,6 +2169,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
+ ah->txchainmask = pCap->tx_chainmask;
+ ah->rxchainmask = pCap->rx_chainmask;
ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
@@ -2101,6 +2189,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->num_gpio_pins = AR9271_NUM_GPIO;
else if (AR_DEVID_7010(ah))
pCap->num_gpio_pins = AR7010_NUM_GPIO;
+ else if (AR_SREV_9300_20_OR_LATER(ah))
+ pCap->num_gpio_pins = AR9300_NUM_GPIO;
+ else if (AR_SREV_9287_11_OR_LATER(ah))
+ pCap->num_gpio_pins = AR9287_NUM_GPIO;
else if (AR_SREV_9285_12_OR_LATER(ah))
pCap->num_gpio_pins = AR9285_NUM_GPIO;
else if (AR_SREV_9280_20_OR_LATER(ah))
@@ -2233,6 +2325,14 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
rx_chainmask >>= 1;
}
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ ah->enabled_cals |= TX_IQ_CAL;
+ if (!AR_SREV_9330(ah))
+ ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
+ }
+ if (AR_SREV_9462(ah))
+ pCap->hw_caps |= ATH9K_HW_CAP_RTT;
+
return 0;
}
@@ -2393,6 +2493,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
ENABLE_REGWRITE_BUFFER(ah);
+ if (AR_SREV_9462(ah))
+ bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
+
REG_WRITE(ah, AR_RX_FILTER, bits);
phybits = 0;
@@ -2434,20 +2537,56 @@ bool ath9k_hw_disable(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_disable);
+static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ enum eeprom_param gain_param;
+
+ if (IS_CHAN_2GHZ(chan))
+ gain_param = EEP_ANTENNA_GAIN_2G;
+ else
+ gain_param = EEP_ANTENNA_GAIN_5G;
+
+ return ah->eep_ops->get_eeprom(ah, gain_param);
+}
+
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+ struct ieee80211_channel *channel;
+ int chan_pwr, new_pwr, max_gain;
+ int ant_gain, ant_reduction = 0;
+
+ if (!chan)
+ return;
+
+ channel = chan->chan;
+ chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
+ new_pwr = min_t(int, chan_pwr, reg->power_limit);
+ max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
+
+ ant_gain = get_antenna_gain(ah, chan);
+ if (ant_gain > max_gain)
+ ant_reduction = ant_gain - max_gain;
+
+ ah->eep_ops->set_txpower(ah, chan,
+ ath9k_regd_get_ctl(reg, chan),
+ ant_reduction, new_pwr, false);
+}
+
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
{
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
struct ath9k_channel *chan = ah->curchan;
struct ieee80211_channel *channel = chan->chan;
- regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER);
+ reg->power_limit = min_t(int, limit, MAX_RATE_POWER);
+ if (test)
+ channel->max_power = MAX_RATE_POWER / 2;
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- channel->max_antenna_gain * 2,
- channel->max_power * 2,
- min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit), test);
+ ath9k_hw_apply_txpower(ah, chan);
+
+ if (test)
+ channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
}
EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
@@ -2646,6 +2785,20 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah,
REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
gen_tmr_configuration[timer->index].mode_mask);
+ if (AR_SREV_9462(ah)) {
+ /*
+ * Starting from AR9462, each generic timer can select which tsf
+ * to use. But we still follow the old rule, 0 - 7 use tsf and
+ * 8 - 15 use tsf2.
+ */
+ if ((timer->index < AR_GEN_TIMER_BANK_1_LEN))
+ REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
+ (1 << timer->index));
+ else
+ REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
+ (1 << timer->index));
+ }
+
/* Enable both trigger and thresh interrupt masks */
REG_SET_BIT(ah, AR_IMR_S5,
(SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
@@ -2749,7 +2902,9 @@ static struct {
{ AR_SREV_VERSION_9271, "9271" },
{ AR_SREV_VERSION_9300, "9300" },
{ AR_SREV_VERSION_9330, "9330" },
+ { AR_SREV_VERSION_9340, "9340" },
{ AR_SREV_VERSION_9485, "9485" },
+ { AR_SREV_VERSION_9462, "9462" },
};
/* For devices with external radios */
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index c79889036ec4..f389b3c93cf3 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -45,6 +45,8 @@
#define AR9300_DEVID_PCIE 0x0030
#define AR9300_DEVID_AR9340 0x0031
#define AR9300_DEVID_AR9485_PCIE 0x0032
+#define AR9300_DEVID_AR9580 0x0033
+#define AR9300_DEVID_AR9462 0x0034
#define AR9300_DEVID_AR9330 0x0035
#define AR5416_AR9100_DEVID 0x000b
@@ -93,6 +95,12 @@
(_ah)->reg_ops.write_flush((_ah)); \
} while (0)
+#define PR_EEP(_s, _val) \
+ do { \
+ len += snprintf(buf + len, size - len, "%20s : %10d\n", \
+ _s, (_val)); \
+ } while (0)
+
#define SM(_v, _f) (((_v) << _f##_S) & _f)
#define MS(_v, _f) (((_v) & _f) >> _f##_S)
#define REG_RMW_FIELD(_a, _r, _f, _v) \
@@ -194,6 +202,7 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_2GHZ = BIT(13),
ATH9K_HW_CAP_5GHZ = BIT(14),
ATH9K_HW_CAP_APM = BIT(15),
+ ATH9K_HW_CAP_RTT = BIT(16),
};
struct ath9k_hw_capabilities {
@@ -329,6 +338,16 @@ enum ath9k_int {
CHANNEL_HT40PLUS | \
CHANNEL_HT40MINUS)
+#define MAX_RTT_TABLE_ENTRY 6
+#define RTT_HIST_MAX 3
+struct ath9k_rtt_hist {
+ u32 table[AR9300_MAX_CHAINS][RTT_HIST_MAX][MAX_RTT_TABLE_ENTRY];
+ u8 num_readings;
+};
+
+#define MAX_IQCAL_MEASUREMENT 8
+#define MAX_CL_TAB_ENTRY 16
+
struct ath9k_hw_cal_data {
u16 channel;
u32 channelFlags;
@@ -338,9 +357,15 @@ struct ath9k_hw_cal_data {
bool paprd_done;
bool nfcal_pending;
bool nfcal_interference;
+ bool done_txiqcal_once;
+ bool done_txclcal_once;
u16 small_signal_gain[AR9300_MAX_CHAINS];
u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
+ u32 num_measures[AR9300_MAX_CHAINS];
+ int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS];
+ u32 tx_clcal[AR9300_MAX_CHAINS][MAX_CL_TAB_ENTRY];
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
+ struct ath9k_rtt_hist rtt_hist;
};
struct ath9k_channel {
@@ -382,14 +407,6 @@ enum ath9k_power_mode {
ATH9K_PM_UNDEFINED
};
-enum ath9k_tp_scale {
- ATH9K_TP_SCALE_MAX = 0,
- ATH9K_TP_SCALE_50,
- ATH9K_TP_SCALE_25,
- ATH9K_TP_SCALE_12,
- ATH9K_TP_SCALE_MIN
-};
-
enum ser_reg_mode {
SER_REG_MODE_OFF = 0,
SER_REG_MODE_ON = 1,
@@ -438,7 +455,6 @@ struct ath9k_hw_version {
u16 phyRev;
u16 analog5GhzRev;
u16 analog2GhzRev;
- u16 subsysid;
enum ath_usb_dev usbdev;
};
@@ -577,7 +593,6 @@ struct ath_hw_private_ops {
bool (*rfbus_req)(struct ath_hw *ah);
void (*rfbus_done)(struct ath_hw *ah);
void (*restore_chainmask)(struct ath_hw *ah);
- void (*set_diversity)(struct ath_hw *ah, bool value);
u32 (*compute_pll_control)(struct ath_hw *ah,
struct ath9k_channel *chan);
bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
@@ -585,6 +600,8 @@ struct ath_hw_private_ops {
void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
void (*set_radar_params)(struct ath_hw *ah,
struct ath_hw_radar_conf *conf);
+ int (*fast_chan_change)(struct ath_hw *ah, struct ath9k_channel *chan,
+ u8 *ini_reloaded);
/* ANI */
void (*ani_cache_ini_regs)(struct ath_hw *ah);
@@ -601,8 +618,7 @@ struct ath_hw_private_ops {
*/
struct ath_hw_ops {
void (*config_pci_powersave)(struct ath_hw *ah,
- int restore,
- int power_off);
+ bool power_off);
void (*rx_enable)(struct ath_hw *ah);
void (*set_desc_link)(void *ds, u32 link);
bool (*calibrate)(struct ath_hw *ah,
@@ -610,30 +626,10 @@ struct ath_hw_ops {
u8 rxchainmask,
bool longcal);
bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
- void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen,
- bool is_firstseg, bool is_is_lastseg,
- const void *ds0, dma_addr_t buf_addr,
- unsigned int qcu);
+ void (*set_txdesc)(struct ath_hw *ah, void *ds,
+ struct ath_tx_info *i);
int (*proc_txdesc)(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts);
- void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
- u32 pktLen, enum ath9k_pkt_type type,
- u32 txPower, u32 keyIx,
- enum ath9k_key_type keyType,
- u32 flags);
- void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
- void *lastds,
- u32 durUpdateEn, u32 rtsctsRate,
- u32 rtsctsDuration,
- struct ath9k_11n_rate_series series[],
- u32 nseries, u32 flags);
- void (*set11n_aggr_first)(struct ath_hw *ah, void *ds,
- u32 aggrLen);
- void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds,
- u32 numDelims);
- void (*set11n_aggr_last)(struct ath_hw *ah, void *ds);
- void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
- void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
void (*antdiv_comb_conf_get)(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf);
void (*antdiv_comb_conf_set)(struct ath_hw *ah,
@@ -647,9 +643,16 @@ struct ath_nf_limits {
s16 nominal;
};
+enum ath_cal_list {
+ TX_IQ_CAL = BIT(0),
+ TX_IQ_ON_AGC_CAL = BIT(1),
+ TX_CL_CAL = BIT(2),
+};
+
/* ah_flags */
#define AH_USE_EEPROM 0x1
#define AH_UNPLUGGED 0x2 /* The card has been physically removed. */
+#define AH_FASTCC 0x4
struct ath_hw {
struct ath_ops reg_ops;
@@ -690,6 +693,7 @@ struct ath_hw {
enum nl80211_iftype opmode;
enum ath9k_power_mode power_mode;
+ s8 noise;
struct ath9k_hw_cal_data *caldata;
struct ath9k_pacal_info pacal_info;
struct ar5416Stats stats;
@@ -703,8 +707,10 @@ struct ath_hw {
u32 txdesc_interrupt_mask;
u32 txeol_interrupt_mask;
u32 txurn_interrupt_mask;
+ atomic_t intr_ref_cnt;
bool chip_fullsleep;
u32 atim_window;
+ u32 modes_index;
/* Calibration */
u32 supp_cals;
@@ -743,6 +749,7 @@ struct ath_hw {
int32_t sign[AR5416_MAX_CHAINS];
} meas3;
u16 cal_samples;
+ u8 enabled_cals;
u32 sta_id1_defaults;
u32 misc_mode;
@@ -820,11 +827,14 @@ struct ath_hw {
struct ar5416IniArray iniModes_9271_1_0_only;
struct ar5416IniArray iniCckfirNormal;
struct ar5416IniArray iniCckfirJapan2484;
+ struct ar5416IniArray ini_japan2484;
struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271;
struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271;
struct ar5416IniArray iniModes_9271_ANI_reg;
struct ar5416IniArray iniModes_high_power_tx_gain_9271;
struct ar5416IniArray iniModes_normal_power_tx_gain_9271;
+ struct ar5416IniArray ini_radio_post_sys2ant;
+ struct ar5416IniArray ini_BTCOEX_MAX_TXPWR;
struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT];
struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT];
@@ -978,6 +988,7 @@ void ath9k_hw_htc_resetinit(struct ath_hw *ah);
/* PHY */
void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
u32 *coef_mantissa, u32 *coef_exponent);
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
/*
* Code Specific to AR5008, AR9001 or AR9002,
@@ -1030,10 +1041,6 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
void ath9k_hw_proc_mib_event(struct ath_hw *ah);
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
-#define ATH_PCIE_CAP_LINK_CTRL 0x70
-#define ATH_PCIE_CAP_LINK_L0S 1
-#define ATH_PCIE_CAP_LINK_L1 2
-
#define ATH9K_CLOCK_RATE_CCK 22
#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index aa0ff7e2c922..af1b32549531 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -270,8 +270,8 @@ static void setup_ht_cap(struct ath_softc *sc,
/* set up supported mcs set */
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
- tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
- rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
+ tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams);
+ rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams);
ath_dbg(common, ATH_DBG_CONFIG,
"TX streams %d, RX streams: %d\n",
@@ -404,31 +404,6 @@ fail:
return error;
}
-void ath9k_init_crypto(struct ath_softc *sc)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- int i = 0;
-
- /* Get the hardware key cache size. */
- common->keymax = AR_KEYTABLE_SIZE;
-
- /*
- * Reset the key cache since some parts do not
- * reset the contents on initial power up.
- */
- for (i = 0; i < common->keymax; i++)
- ath_hw_keyreset(common, (u16) i);
-
- /*
- * Check whether the separate key cache entries
- * are required to handle both tx+rx MIC keys.
- * With split mic keys the number of stations is limited
- * to 27 otherwise 59.
- */
- if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
- common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
-}
-
static int ath9k_init_btcoex(struct ath_softc *sc)
{
struct ath_txq *txq;
@@ -531,10 +506,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
sc->sc_flags |= SC_OP_RXAGGR;
}
- common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
- common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
-
- ath9k_hw_set_diversity(sc->sc_ah, true);
sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
@@ -548,7 +519,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
}
-static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
+static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
struct ath9k_platform_data *pdata = sc->dev->platform_data;
@@ -563,10 +534,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
ah->hw = sc->hw;
ah->hw_version.devid = devid;
- ah->hw_version.subsysid = subsysid;
ah->reg_ops.read = ath9k_ioread32;
ah->reg_ops.write = ath9k_iowrite32;
ah->reg_ops.rmw = ath9k_reg_rmw;
+ atomic_set(&ah->intr_ref_cnt, -1);
sc->sc_ah = ah;
if (!pdata) {
@@ -597,6 +568,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
mutex_init(&sc->mutex);
#ifdef CONFIG_ATH9K_DEBUGFS
spin_lock_init(&sc->nodes_lock);
+ spin_lock_init(&sc->debug.samp_lock);
INIT_LIST_HEAD(&sc->nodes);
#endif
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
@@ -630,7 +602,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
if (ret)
goto err_btcoex;
- ath9k_init_crypto(sc);
+ ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_init_misc(sc);
return 0;
@@ -654,7 +626,6 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
struct ieee80211_supported_band *sband;
struct ieee80211_channel *chan;
struct ath_hw *ah = sc->sc_ah;
- struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
int i;
sband = &sc->sbands[band];
@@ -663,17 +634,14 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
ah->curchan = &ah->channels[chan->hw_value];
ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
- chan->max_power = reg->max_power_level / 2;
}
}
static void ath9k_init_txpower_limits(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath9k_channel *curchan = ah->curchan;
- ah->txchainmask = common->tx_chainmask;
if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
@@ -682,9 +650,22 @@ static void ath9k_init_txpower_limits(struct ath_softc *sc)
ah->curchan = curchan;
}
+void ath9k_reload_chainmask_settings(struct ath_softc *sc)
+{
+ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT))
+ return;
+
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+ setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+ setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+}
+
+
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
@@ -722,6 +703,16 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif);
+ hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
+ hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
+
+ /* single chain devices with rx diversity */
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+ hw->wiphy->available_antennas_rx = BIT(0) | BIT(1);
+
+ sc->ant_rx = hw->wiphy->available_antennas_rx;
+ sc->ant_tx = hw->wiphy->available_antennas_tx;
+
#ifdef CONFIG_ATH9K_RATE_CONTROL
hw->rate_control_algorithm = "ath9k_rate_control";
#endif
@@ -733,17 +724,12 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&sc->sbands[IEEE80211_BAND_5GHZ];
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
- setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
- setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
- }
+ ath9k_reload_chainmask_settings(sc);
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
}
-int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
+int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
struct ieee80211_hw *hw = sc->hw;
@@ -753,7 +739,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
struct ath_regulatory *reg;
/* Bring up device */
- error = ath9k_init_softc(devid, sc, subsysid, bus_ops);
+ error = ath9k_init_softc(devid, sc, bus_ops);
if (error != 0)
goto error_init;
@@ -806,6 +792,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
goto error_world;
}
+ INIT_WORK(&sc->hw_reset_work, ath_reset_work);
INIT_WORK(&sc->hw_check_work, ath_hw_check);
INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index b6b523a897e5..6a8fdf33a527 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -62,18 +62,6 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
}
EXPORT_SYMBOL(ath9k_hw_txstart);
-void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
- ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
- ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
- ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
- ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
-}
-EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
-
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
{
u32 npend;
@@ -345,21 +333,8 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
}
memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
qi->tqi_type = type;
- if (qinfo == NULL) {
- qi->tqi_qflags =
- TXQ_FLAG_TXOKINT_ENABLE
- | TXQ_FLAG_TXERRINT_ENABLE
- | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
- qi->tqi_aifs = INIT_AIFS;
- qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
- qi->tqi_cwmax = INIT_CWMAX;
- qi->tqi_shretry = INIT_SH_RETRY;
- qi->tqi_lgretry = INIT_LG_RETRY;
- qi->tqi_physCompBuf = 0;
- } else {
- qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
- (void) ath9k_hw_set_txq_props(ah, q, qinfo);
- }
+ qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
+ (void) ath9k_hw_set_txq_props(ah, q, qinfo);
return q;
}
@@ -564,7 +539,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
EXPORT_SYMBOL(ath9k_hw_resettxqueue);
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
- struct ath_rx_status *rs, u64 tsf)
+ struct ath_rx_status *rs)
{
struct ar5416_desc ads;
struct ar5416_desc *adsp = AR5416DESC(ds);
@@ -609,7 +584,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
else
rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
- rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
+ rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate);
rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
@@ -645,8 +620,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr)
rs->rs_status |= ATH9K_RXERR_MIC;
- else if (ads.ds_rxstatus8 & AR_KeyMiss)
- rs->rs_status |= ATH9K_RXERR_DECRYPT;
+ if (ads.ds_rxstatus8 & AR_KeyMiss)
+ rs->rs_status |= ATH9K_RXERR_KEYMISS;
}
return 0;
@@ -800,6 +775,11 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
+ if (!(ah->imask & ATH9K_INT_GLOBAL))
+ atomic_set(&ah->intr_ref_cnt, -1);
+ else
+ atomic_dec(&ah->intr_ref_cnt);
+
ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n");
REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
(void) REG_READ(ah, AR_IER);
@@ -821,6 +801,13 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
if (!(ah->imask & ATH9K_INT_GLOBAL))
return;
+ if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
+ ath_dbg(common, ATH_DBG_INTERRUPT,
+ "Do not enable IER ref count %d\n",
+ atomic_read(&ah->intr_ref_cnt));
+ return;
+ }
+
if (AR_SREV_9340(ah))
sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
@@ -840,9 +827,9 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
-void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
+void ath9k_hw_set_interrupts(struct ath_hw *ah)
{
- enum ath9k_int omask = ah->imask;
+ enum ath9k_int ints = ah->imask;
u32 mask, mask2;
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_common *common = ath9k_hw_common(ah);
@@ -850,9 +837,8 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
if (!(ints & ATH9K_INT_GLOBAL))
ath9k_hw_disable_interrupts(ah);
- ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
+ ath_dbg(common, ATH_DBG_INTERRUPT, "New interrupt mask 0x%x\n", ints);
- /* TODO: global int Ref count */
mask = ints & ATH9K_INT_COMMON;
mask2 = 0;
@@ -929,9 +915,6 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
}
- if (ints & ATH9K_INT_GLOBAL)
- ath9k_hw_enable_interrupts(ah);
-
return;
}
EXPORT_SYMBOL(ath9k_hw_set_interrupts);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 8e848c4d16ba..11dbd1473a13 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -17,10 +17,6 @@
#ifndef MAC_H
#define MAC_H
-#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \
- MS(ads->ds_rxstatus0, AR_RxRate) : \
- (ads->ds_rxstatus3 >> 2) & 0xFF)
-
#define set11nTries(_series, _index) \
(SM((_series)[_index].Tries, AR_XmitDataTries##_index))
@@ -79,9 +75,10 @@
#define ATH9K_TXERR_XTXOP 0x08
#define ATH9K_TXERR_TIMER_EXPIRED 0x10
#define ATH9K_TX_ACKED 0x20
+#define ATH9K_TX_FLUSH 0x40
#define ATH9K_TXERR_MASK \
(ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \
- ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED)
+ ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED | ATH9K_TX_FLUSH)
#define ATH9K_TX_BA 0x01
#define ATH9K_TX_PWRMGMT 0x02
@@ -146,6 +143,7 @@ struct ath_rx_status {
u8 rs_moreaggr;
u8 rs_num_delims;
u8 rs_flags;
+ bool is_mybeacon;
u32 evm0;
u32 evm1;
u32 evm2;
@@ -184,6 +182,7 @@ struct ath_htc_rx_status {
#define ATH9K_RXERR_FIFO 0x04
#define ATH9K_RXERR_DECRYPT 0x08
#define ATH9K_RXERR_MIC 0x10
+#define ATH9K_RXERR_KEYMISS 0x20
#define ATH9K_RX_MORE 0x01
#define ATH9K_RX_MORE_AGGR 0x02
@@ -194,7 +193,7 @@ struct ath_htc_rx_status {
#define ATH9K_RX_DECRYPT_BUSY 0x40
#define ATH9K_RXKEYIX_INVALID ((u8)-1)
-#define ATH9K_TXKEYIX_INVALID ((u32)-1)
+#define ATH9K_TXKEYIX_INVALID ((u8)-1)
enum ath9k_phyerr {
ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */
@@ -262,7 +261,11 @@ struct ath_desc {
#define ATH9K_TXDESC_VMF 0x0100
#define ATH9K_TXDESC_FRAG_IS_ON 0x0200
#define ATH9K_TXDESC_LOWRXCHAIN 0x0400
-#define ATH9K_TXDESC_LDPC 0x00010000
+#define ATH9K_TXDESC_LDPC 0x0800
+#define ATH9K_TXDESC_CLRDMASK 0x1000
+
+#define ATH9K_TXDESC_PAPRD 0x70000
+#define ATH9K_TXDESC_PAPRD_S 16
#define ATH9K_RXDESC_INTREQ 0x0020
@@ -643,6 +646,7 @@ enum ath9k_rx_filter {
ATH9K_RX_FILTER_PSPOLL = 0x00004000,
ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
+ ATH9K_RX_FILTER_CONTROL_WRAPPER = 0x00080000,
};
#define ATH9K_RATESERIES_RTS_CTS 0x0001
@@ -658,6 +662,13 @@ struct ath9k_11n_rate_series {
u32 RateFlags;
};
+enum aggr_type {
+ AGGR_BUF_NONE,
+ AGGR_BUF_FIRST,
+ AGGR_BUF_MIDDLE,
+ AGGR_BUF_LAST,
+};
+
enum ath9k_key_type {
ATH9K_KEY_TYPE_CLEAR,
ATH9K_KEY_TYPE_WEP,
@@ -665,6 +676,33 @@ enum ath9k_key_type {
ATH9K_KEY_TYPE_TKIP,
};
+struct ath_tx_info {
+ u8 qcu;
+
+ bool is_first;
+ bool is_last;
+
+ enum aggr_type aggr;
+ u8 ndelim;
+ u16 aggr_len;
+
+ dma_addr_t link;
+ int pkt_len;
+ u32 flags;
+
+ dma_addr_t buf_addr[4];
+ int buf_len[4];
+
+ struct ath9k_11n_rate_series rates[4];
+ u8 rtscts_rate;
+ bool dur_update;
+
+ enum ath9k_pkt_type type;
+ enum ath9k_key_type keytype;
+ u8 keyix;
+ u8 txpower;
+};
+
struct ath_hw;
struct ath9k_channel;
enum ath9k_int;
@@ -672,7 +710,6 @@ enum ath9k_int;
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
-void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
@@ -687,7 +724,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
- struct ath_rx_status *rs, u64 tsf);
+ struct ath_rx_status *rs);
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags);
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
@@ -699,7 +736,7 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah);
/* Interrupt Handling */
bool ath9k_hw_intrpend(struct ath_hw *ah);
-void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
+void ath9k_hw_set_interrupts(struct ath_hw *ah);
void ath9k_hw_enable_interrupts(struct ath_hw *ah);
void ath9k_hw_disable_interrupts(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 722967b86cf1..93fbe6f40898 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -111,24 +111,29 @@ void ath9k_ps_wakeup(struct ath_softc *sc)
void ath9k_ps_restore(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ enum ath9k_power_mode mode;
unsigned long flags;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if (--sc->ps_usecount != 0)
goto unlock;
- spin_lock(&common->cc_lock);
- ath_hw_cycle_counters_update(common);
- spin_unlock(&common->cc_lock);
-
if (sc->ps_idle)
- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
+ mode = ATH9K_PM_FULL_SLEEP;
else if (sc->ps_enabled &&
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
PS_WAIT_FOR_CAB |
PS_WAIT_FOR_PSPOLL_DATA |
PS_WAIT_FOR_TX_ACK)))
- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
+ mode = ATH9K_PM_NETWORK_SLEEP;
+ else
+ goto unlock;
+
+ spin_lock(&common->cc_lock);
+ ath_hw_cycle_counters_update(common);
+ spin_unlock(&common->cc_lock);
+
+ ath9k_hw_setpower(sc->sc_ah, mode);
unlock:
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
@@ -163,7 +168,7 @@ static void ath_update_survey_nf(struct ath_softc *sc, int channel)
if (chan->noisefloor) {
survey->filled |= SURVEY_INFO_NOISE_DBM;
- survey->noise = chan->noisefloor;
+ survey->noise = ath9k_hw_getchan_noise(ah, chan);
}
}
@@ -212,104 +217,168 @@ static int ath_update_survey_stats(struct ath_softc *sc)
return ret;
}
-/*
- * Set/change channels. If the channel is really being changed, it's done
- * by reseting the chip. To accomplish this we must first cleanup any pending
- * DMA, then restart stuff.
-*/
-static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
- struct ath9k_channel *hchan)
+static void __ath_cancel_work(struct ath_softc *sc)
{
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_conf *conf = &common->hw->conf;
- bool fastcc = true, stopped;
- struct ieee80211_channel *channel = hw->conf.channel;
- struct ath9k_hw_cal_data *caldata = NULL;
- int r;
-
- if (sc->sc_flags & SC_OP_INVALID)
- return -EIO;
-
- sc->hw_busy_count = 0;
-
- del_timer_sync(&common->ani.timer);
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
+}
- ath9k_ps_wakeup(sc);
+static void ath_cancel_work(struct ath_softc *sc)
+{
+ __ath_cancel_work(sc);
+ cancel_work_sync(&sc->hw_reset_work);
+}
- spin_lock_bh(&sc->sc_pcu_lock);
+static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ bool ret;
- /*
- * This is only performed if the channel settings have
- * actually changed.
- *
- * To switch channels clear any pending DMA operations;
- * wait long enough for the RX fifo to drain, reset the
- * hardware at the new frequency, and then re-enable
- * the relevant bits of the h/w.
- */
- ath9k_hw_disable_interrupts(ah);
- stopped = ath_drain_all_txq(sc, false);
+ ieee80211_stop_queues(sc->hw);
- if (!ath_stoprecv(sc))
- stopped = false;
+ sc->hw_busy_count = 0;
+ del_timer_sync(&common->ani.timer);
- if (!ath9k_hw_check_alive(ah))
- stopped = false;
+ ath9k_debug_samp_bb_mac(sc);
+ ath9k_hw_disable_interrupts(ah);
- /* XXX: do not flush receive queue here. We don't want
- * to flush data frames already in queue because of
- * changing channel. */
+ ret = ath_drain_all_txq(sc, retry_tx);
- if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
- fastcc = false;
+ if (!ath_stoprecv(sc))
+ ret = false;
- if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
- caldata = &sc->caldata;
+ if (!flush) {
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ ath_rx_tasklet(sc, 1, true);
+ ath_rx_tasklet(sc, 1, false);
+ } else {
+ ath_flushrecv(sc);
+ }
- ath_dbg(common, ATH_DBG_CONFIG,
- "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
- sc->sc_ah->curchan->channel,
- channel->center_freq, conf_is_ht40(conf),
- fastcc);
+ return ret;
+}
- r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
- if (r) {
- ath_err(common,
- "Unable to reset channel (%u MHz), reset status %d\n",
- channel->center_freq, r);
- goto ps_restore;
- }
+static bool ath_complete_reset(struct ath_softc *sc, bool start)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
if (ath_startrecv(sc) != 0) {
ath_err(common, "Unable to restart recv logic\n");
- r = -EIO;
- goto ps_restore;
+ return false;
}
ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow);
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
+ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
if (sc->sc_flags & SC_OP_BEACONS)
ath_set_beacon(sc);
+
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
if (!common->disable_ani)
ath_start_ani(common);
}
- ps_restore:
- ieee80211_wake_queues(hw);
+ if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) {
+ struct ath_hw_antcomb_conf div_ant_conf;
+ u8 lna_conf;
+
+ ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
+
+ if (sc->ant_rx == 1)
+ lna_conf = ATH_ANT_DIV_COMB_LNA1;
+ else
+ lna_conf = ATH_ANT_DIV_COMB_LNA2;
+ div_ant_conf.main_lna_conf = lna_conf;
+ div_ant_conf.alt_lna_conf = lna_conf;
+
+ ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
+ }
+
+ ieee80211_wake_queues(sc->hw);
+
+ return true;
+}
+
+static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
+ bool retry_tx)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_cal_data *caldata = NULL;
+ bool fastcc = true;
+ bool flush = false;
+ int r;
+
+ __ath_cancel_work(sc);
+
+ spin_lock_bh(&sc->sc_pcu_lock);
+
+ if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) {
+ fastcc = false;
+ caldata = &sc->caldata;
+ }
+
+ if (!hchan) {
+ fastcc = false;
+ flush = true;
+ hchan = ah->curchan;
+ }
+
+ if (fastcc && !ath9k_hw_check_alive(ah))
+ fastcc = false;
+
+ if (!ath_prepare_reset(sc, retry_tx, flush))
+ fastcc = false;
+ ath_dbg(common, ATH_DBG_CONFIG,
+ "Reset to %u MHz, HT40: %d fastcc: %d\n",
+ hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
+ CHANNEL_HT40PLUS)),
+ fastcc);
+
+ r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
+ if (r) {
+ ath_err(common,
+ "Unable to reset channel, reset status %d\n", r);
+ goto out;
+ }
+
+ if (!ath_complete_reset(sc, true))
+ r = -EIO;
+
+out:
spin_unlock_bh(&sc->sc_pcu_lock);
+ return r;
+}
+
+
+/*
+ * Set/change channels. If the channel is really being changed, it's done
+ * by reseting the chip. To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+*/
+static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+ struct ath9k_channel *hchan)
+{
+ int r;
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return -EIO;
+
+ ath9k_ps_wakeup(sc);
+
+ r = ath_reset_internal(sc, hchan, false);
ath9k_ps_restore(sc);
+
return r;
}
@@ -317,7 +386,6 @@ static void ath_paprd_activate(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_hw_cal_data *caldata = ah->caldata;
- struct ath_common *common = ath9k_hw_common(ah);
int chain;
if (!caldata || !caldata->paprd_done)
@@ -326,7 +394,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
ath9k_ps_wakeup(sc);
ar9003_paprd_enable(ah, false);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
- if (!(common->tx_chainmask & BIT(chain)))
+ if (!(ah->txchainmask & BIT(chain)))
continue;
ar9003_paprd_populate_single_table(ah, caldata, chain);
@@ -413,7 +481,7 @@ void ath_paprd_calibrate(struct work_struct *work)
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
- if (!(common->tx_chainmask & BIT(chain)))
+ if (!(ah->txchainmask & BIT(chain)))
continue;
chain_ok = 0;
@@ -534,7 +602,7 @@ void ath_ani_calibrate(unsigned long data)
if (longcal || shortcal) {
common->ani.caldone =
ath9k_hw_calibrate(ah, ah->curchan,
- common->rx_chainmask, longcal);
+ ah->rxchainmask, longcal);
}
ath9k_ps_restore(sc);
@@ -545,6 +613,7 @@ set_timer:
* The interval must be the shortest necessary to satisfy ANI,
* short calibration and long calibration.
*/
+ ath9k_debug_samp_bb_mac(sc);
cal_interval = ATH_LONG_CALINTERVAL;
if (sc->sc_ah->config.enable_ani)
cal_interval = min(cal_interval,
@@ -564,7 +633,6 @@ set_timer:
static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
struct ath_node *an;
- struct ath_hw *ah = sc->sc_ah;
an = (struct ath_node *)sta->drv_priv;
#ifdef CONFIG_ATH9K_DEBUGFS
@@ -573,9 +641,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
spin_unlock(&sc->nodes_lock);
an->sta = sta;
#endif
- if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM)
- sc->sc_flags |= SC_OP_ENABLE_APM;
-
if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
@@ -599,74 +664,6 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
ath_tx_node_cleanup(sc, an);
}
-void ath_hw_check(struct work_struct *work)
-{
- struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- unsigned long flags;
- int busy;
-
- ath9k_ps_wakeup(sc);
- if (ath9k_hw_check_alive(sc->sc_ah))
- goto out;
-
- spin_lock_irqsave(&common->cc_lock, flags);
- busy = ath_update_survey_stats(sc);
- spin_unlock_irqrestore(&common->cc_lock, flags);
-
- ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
- "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
- if (busy >= 99) {
- if (++sc->hw_busy_count >= 3) {
- spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock_bh(&sc->sc_pcu_lock);
- }
- } else if (busy >= 0)
- sc->hw_busy_count = 0;
-
-out:
- ath9k_ps_restore(sc);
-}
-
-static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
-{
- static int count;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
- if (pll_sqsum >= 0x40000) {
- count++;
- if (count == 3) {
- /* Rx is hung for more than 500ms. Reset it */
- ath_dbg(common, ATH_DBG_RESET,
- "Possible RX hang, resetting");
- spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock_bh(&sc->sc_pcu_lock);
- count = 0;
- }
- } else
- count = 0;
-}
-
-void ath_hw_pll_work(struct work_struct *work)
-{
- struct ath_softc *sc = container_of(work, struct ath_softc,
- hw_pll_work.work);
- u32 pll_sqsum;
-
- if (AR_SREV_9485(sc->sc_ah)) {
-
- ath9k_ps_wakeup(sc);
- pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
- ath9k_ps_restore(sc);
-
- ath_hw_pll_rx_hang_check(sc, pll_sqsum);
-
- ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
- }
-}
-
void ath9k_tasklet(unsigned long data)
{
@@ -677,16 +674,24 @@ void ath9k_tasklet(unsigned long data)
u32 status = sc->intrstatus;
u32 rxmask;
+ ath9k_ps_wakeup(sc);
+ spin_lock(&sc->sc_pcu_lock);
+
if ((status & ATH9K_INT_FATAL) ||
(status & ATH9K_INT_BB_WATCHDOG)) {
- spin_lock(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock(&sc->sc_pcu_lock);
- return;
- }
+#ifdef CONFIG_ATH9K_DEBUGFS
+ enum ath_reset_type type;
- ath9k_ps_wakeup(sc);
- spin_lock(&sc->sc_pcu_lock);
+ if (status & ATH9K_INT_FATAL)
+ type = RESET_TYPE_FATAL_INT;
+ else
+ type = RESET_TYPE_BB_WATCHDOG;
+
+ RESET_STAT_INC(sc, type);
+#endif
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ goto out;
+ }
/*
* Only run the baseband hang check if beacons stop working in AP or
@@ -706,8 +711,7 @@ void ath9k_tasklet(unsigned long data)
*/
ath_dbg(common, ATH_DBG_PS,
"TSFOOR - Sync with next Beacon\n");
- sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC |
- PS_TSFOOR_SYNC;
+ sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
}
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
@@ -736,6 +740,7 @@ void ath9k_tasklet(unsigned long data)
if (status & ATH9K_INT_GENTIMER)
ath_gen_timer_isr(sc->sc_ah);
+out:
/* re-enable hardware interrupt */
ath9k_hw_enable_interrupts(ah);
@@ -826,11 +831,9 @@ irqreturn_t ath_isr(int irq, void *dev)
if (status & ATH9K_INT_TXURN)
ath9k_hw_updatetxtriglevel(ah, true);
- if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
- if (status & ATH9K_INT_RXEOL) {
- ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
- ath9k_hw_set_interrupts(ah, ah->imask);
- }
+ if (status & ATH9K_INT_RXEOL) {
+ ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+ ath9k_hw_set_interrupts(ah);
}
if (status & ATH9K_INT_MIB) {
@@ -886,8 +889,9 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_pcu_lock);
+ atomic_set(&ah->intr_ref_cnt, -1);
- ath9k_hw_configpcipowersave(ah, 0, 0);
+ ath9k_hw_configpcipowersave(ah, false);
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah);
@@ -899,27 +903,13 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
channel->center_freq, r);
}
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
- if (ath_startrecv(sc) != 0) {
- ath_err(common, "Unable to restart recv logic\n");
- goto out;
- }
- if (sc->sc_flags & SC_OP_BEACONS)
- ath_set_beacon(sc); /* restart beacons */
-
- /* Re-Enable interrupts */
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath_complete_reset(sc, true);
/* Enable LED */
ath9k_hw_cfg_output(ah, ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
- ieee80211_wake_queues(hw);
- ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
-
-out:
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
@@ -932,11 +922,10 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
int r;
ath9k_ps_wakeup(sc);
- cancel_delayed_work_sync(&sc->hw_pll_work);
- spin_lock_bh(&sc->sc_pcu_lock);
+ ath_cancel_work(sc);
- ieee80211_stop_queues(hw);
+ spin_lock_bh(&sc->sc_pcu_lock);
/*
* Keep the LED on when the radio is disabled
@@ -947,13 +936,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
}
- /* Disable interrupts */
- ath9k_hw_disable_interrupts(ah);
-
- ath_drain_all_txq(sc, false); /* clear pending tx frames */
-
- ath_stoprecv(sc); /* turn off frame recv */
- ath_flushrecv(sc); /* flush recv queue */
+ ath_prepare_reset(sc, false, true);
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
@@ -967,55 +950,19 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_hw_phy_disable(ah);
- ath9k_hw_configpcipowersave(ah, 1, 1);
+ ath9k_hw_configpcipowersave(ah, true);
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
}
-int ath_reset(struct ath_softc *sc, bool retry_tx)
+static int ath_reset(struct ath_softc *sc, bool retry_tx)
{
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_hw *hw = sc->hw;
int r;
- sc->hw_busy_count = 0;
-
- /* Stop ANI */
-
- del_timer_sync(&common->ani.timer);
-
ath9k_ps_wakeup(sc);
- ieee80211_stop_queues(hw);
-
- ath9k_hw_disable_interrupts(ah);
- ath_drain_all_txq(sc, retry_tx);
-
- ath_stoprecv(sc);
- ath_flushrecv(sc);
-
- r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
- if (r)
- ath_err(common,
- "Unable to reset hardware; reset status %d\n", r);
-
- if (ath_startrecv(sc) != 0)
- ath_err(common, "Unable to start recv logic\n");
-
- /*
- * We may be doing a reset in response to a request
- * that changes the channel so update any state that
- * might change as a result.
- */
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
-
- if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
- ath_set_beacon(sc); /* restart beacons */
-
- ath9k_hw_set_interrupts(ah, ah->imask);
+ r = ath_reset_internal(sc, NULL, retry_tx);
if (retry_tx) {
int i;
@@ -1028,15 +975,83 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
}
}
- ieee80211_wake_queues(hw);
+ ath9k_ps_restore(sc);
+
+ return r;
+}
+
+void ath_reset_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
+
+ ath_reset(sc, true);
+}
+
+void ath_hw_check(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ unsigned long flags;
+ int busy;
+
+ ath9k_ps_wakeup(sc);
+ if (ath9k_hw_check_alive(sc->sc_ah))
+ goto out;
+
+ spin_lock_irqsave(&common->cc_lock, flags);
+ busy = ath_update_survey_stats(sc);
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+
+ ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
+ "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
+ if (busy >= 99) {
+ if (++sc->hw_busy_count >= 3) {
+ RESET_STAT_INC(sc, RESET_TYPE_BB_HANG);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ }
- /* Start ANI */
- if (!common->disable_ani)
- ath_start_ani(common);
+ } else if (busy >= 0)
+ sc->hw_busy_count = 0;
+out:
ath9k_ps_restore(sc);
+}
- return r;
+static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
+{
+ static int count;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+ if (pll_sqsum >= 0x40000) {
+ count++;
+ if (count == 3) {
+ /* Rx is hung for more than 500ms. Reset it */
+ ath_dbg(common, ATH_DBG_RESET,
+ "Possible RX hang, resetting");
+ RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ count = 0;
+ }
+ } else
+ count = 0;
+}
+
+void ath_hw_pll_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc,
+ hw_pll_work.work);
+ u32 pll_sqsum;
+
+ if (AR_SREV_9485(sc->sc_ah)) {
+
+ ath9k_ps_wakeup(sc);
+ pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
+ ath9k_ps_restore(sc);
+
+ ath_hw_pll_rx_hang_check(sc, pll_sqsum);
+
+ ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
+ }
}
/**********************/
@@ -1066,7 +1081,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
init_channel = ath9k_cmn_get_curchannel(hw, ah);
/* Reset SERDES registers */
- ath9k_hw_configpcipowersave(ah, 0, 0);
+ ath9k_hw_configpcipowersave(ah, false);
/*
* The basic interface to setting the hardware in a good
@@ -1085,28 +1100,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
goto mutex_unlock;
}
- /*
- * This is needed only to setup initial state
- * but it's best done after a reset.
- */
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
-
- /*
- * Setup the hardware after reset:
- * The receive engine is set going.
- * Frame transmit is handled entirely
- * in the frame output path; there's nothing to do
- * here except setup the interrupt mask.
- */
- if (ath_startrecv(sc) != 0) {
- ath_err(common, "Unable to start recv logic\n");
- r = -EIO;
- spin_unlock_bh(&sc->sc_pcu_lock);
- goto mutex_unlock;
- }
- spin_unlock_bh(&sc->sc_pcu_lock);
-
/* Setup our intr mask. */
ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
ATH9K_INT_RXORN | ATH9K_INT_FATAL |
@@ -1129,11 +1122,14 @@ static int ath9k_start(struct ieee80211_hw *hw)
/* Disable BMISS interrupt when we're not associated */
ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
- ath9k_hw_set_interrupts(ah, ah->imask);
- ieee80211_wake_queues(hw);
+ if (!ath_complete_reset(sc, false)) {
+ r = -EIO;
+ spin_unlock_bh(&sc->sc_pcu_lock);
+ goto mutex_unlock;
+ }
- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+ spin_unlock_bh(&sc->sc_pcu_lock);
if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
!ah->btcoex_hw.enabled) {
@@ -1141,8 +1137,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
AR_STOMP_LOW_WLAN_WGHT);
ath9k_hw_btcoex_enable(ah);
- if (common->bus_ops->bt_coex_prep)
- common->bus_ops->bt_coex_prep(common);
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
ath9k_btcoex_timer_resume(sc);
}
@@ -1228,10 +1222,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
mutex_lock(&sc->mutex);
- cancel_delayed_work_sync(&sc->tx_complete_work);
- cancel_delayed_work_sync(&sc->hw_pll_work);
- cancel_work_sync(&sc->paprd_work);
- cancel_work_sync(&sc->hw_check_work);
+ ath_cancel_work(sc);
if (sc->sc_flags & SC_OP_INVALID) {
ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
@@ -1418,7 +1409,7 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
ah->imask &= ~ATH9K_INT_TSFOOR;
}
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
/* Set up ANI */
if (iter_data.naps > 0) {
@@ -1593,7 +1584,7 @@ static void ath9k_enable_ps(struct ath_softc *sc)
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) {
ah->imask |= ATH9K_INT_TIM_TIMER;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
}
ath9k_hw_setrxabort(ah, 1);
}
@@ -1613,7 +1604,7 @@ static void ath9k_disable_ps(struct ath_softc *sc)
PS_WAIT_FOR_TX_ACK);
if (ah->imask & ATH9K_INT_TIM_TIMER) {
ah->imask &= ~ATH9K_INT_TIM_TIMER;
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_set_interrupts(ah);
}
}
@@ -1676,6 +1667,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ath9k_channel old_chan;
int pos = curchan->hw_value;
int old_pos = -1;
unsigned long flags;
@@ -1692,15 +1684,25 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
"Set channel: %d MHz type: %d\n",
curchan->center_freq, conf->channel_type);
- ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
- curchan, conf->channel_type);
-
/* update survey stats for the old channel before switching */
spin_lock_irqsave(&common->cc_lock, flags);
ath_update_survey_stats(sc);
spin_unlock_irqrestore(&common->cc_lock, flags);
/*
+ * Preserve the current channel values, before updating
+ * the same channel
+ */
+ if (old_pos == pos) {
+ memcpy(&old_chan, &sc->sc_ah->channels[pos],
+ sizeof(struct ath9k_channel));
+ ah->curchan = &old_chan;
+ }
+
+ ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
+ curchan, conf->channel_type);
+
+ /*
* If the operating channel changes, change the survey in-use flags
* along with it.
* Reset the survey data for the new channel, unless we're switching
@@ -1844,8 +1846,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
switch (cmd) {
case STA_NOTIFY_SLEEP:
an->sleeping = true;
- if (ath_tx_aggr_sleep(sc, an))
- ieee80211_sta_set_tim(sta);
+ ath_tx_aggr_sleep(sta, sc, an);
break;
case STA_NOTIFY_AWAKE:
an->sleeping = false;
@@ -1854,7 +1855,8 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
}
}
-static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int ath9k_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct ath_softc *sc = hw->priv;
@@ -2032,6 +2034,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
/* Stop ANI */
sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
+ memset(&sc->caldata, 0, sizeof(sc->caldata));
}
}
@@ -2153,7 +2156,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath9k_ps_restore(sc);
}
-static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
+static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct ath_softc *sc = hw->priv;
u64 tsf;
@@ -2167,7 +2170,9 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
-static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+static void ath9k_set_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u64 tsf)
{
struct ath_softc *sc = hw->priv;
@@ -2178,7 +2183,7 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
mutex_unlock(&sc->mutex);
}
-static void ath9k_reset_tsf(struct ieee80211_hw *hw)
+static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct ath_softc *sc = hw->priv;
@@ -2341,9 +2346,11 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_pcu_lock);
drain_txq = ath_drain_all_txq(sc, false);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+
if (!drain_txq)
ath_reset(sc, false);
- spin_unlock_bh(&sc->sc_pcu_lock);
+
ath9k_ps_restore(sc);
ieee80211_wake_queues(hw);
@@ -2406,6 +2413,73 @@ skip:
return sc->beacon.tx_last;
}
+static int ath9k_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats;
+
+ stats->dot11ACKFailureCount = mib_stats->ackrcv_bad;
+ stats->dot11RTSFailureCount = mib_stats->rts_bad;
+ stats->dot11FCSErrorCount = mib_stats->fcs_bad;
+ stats->dot11RTSSuccessCount = mib_stats->rts_good;
+ return 0;
+}
+
+static u32 fill_chainmask(u32 cap, u32 new)
+{
+ u32 filled = 0;
+ int i;
+
+ for (i = 0; cap && new; i++, cap >>= 1) {
+ if (!(cap & BIT(0)))
+ continue;
+
+ if (new & BIT(0))
+ filled |= BIT(i);
+
+ new >>= 1;
+ }
+
+ return filled;
+}
+
+static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+
+ if (!rx_ant || !tx_ant)
+ return -EINVAL;
+
+ sc->ant_rx = rx_ant;
+ sc->ant_tx = tx_ant;
+
+ if (ah->caps.rx_chainmask == 1)
+ return 0;
+
+ /* AR9100 runs into calibration issues if not all rx chains are enabled */
+ if (AR_SREV_9100(ah))
+ ah->rxchainmask = 0x7;
+ else
+ ah->rxchainmask = fill_chainmask(ah->caps.rx_chainmask, rx_ant);
+
+ ah->txchainmask = fill_chainmask(ah->caps.tx_chainmask, tx_ant);
+ ath9k_reload_chainmask_settings(sc);
+
+ return 0;
+}
+
+static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+ struct ath_softc *sc = hw->priv;
+
+ *tx_ant = sc->ant_tx;
+ *rx_ant = sc->ant_rx;
+ return 0;
+}
+
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@@ -2430,5 +2504,8 @@ struct ieee80211_ops ath9k_ops = {
.set_coverage_class = ath9k_set_coverage_class,
.flush = ath9k_flush,
.tx_frames_pending = ath9k_tx_frames_pending,
- .tx_last_beacon = ath9k_tx_last_beacon,
+ .tx_last_beacon = ath9k_tx_last_beacon,
+ .get_stats = ath9k_get_stats,
+ .set_antenna = ath9k_set_antenna,
+ .get_antenna = ath9k_get_antenna,
};
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index be4ea1329813..edb0b4b3da3a 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -32,9 +32,12 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */
{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */
+ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */
+ { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */
{ 0 }
};
+
/* return bus cachesize in 4B word units */
static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
{
@@ -88,23 +91,6 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
return true;
}
-/*
- * Bluetooth coexistance requires disabling ASPM.
- */
-static void ath_pci_bt_coex_prep(struct ath_common *common)
-{
- struct ath_softc *sc = (struct ath_softc *) common->priv;
- struct pci_dev *pdev = to_pci_dev(sc->dev);
- u8 aspm;
-
- if (!pci_is_pcie(pdev))
- return;
-
- pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm);
- aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1);
- pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm);
-}
-
static void ath_pci_extn_synch_enable(struct ath_common *common)
{
struct ath_softc *sc = (struct ath_softc *) common->priv;
@@ -116,6 +102,7 @@ static void ath_pci_extn_synch_enable(struct ath_common *common)
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)
{
struct ath_softc *sc = (struct ath_softc *) common->priv;
@@ -125,19 +112,38 @@ static void ath_pci_aspm_init(struct ath_common *common)
int pos;
u8 aspm;
- if (!pci_is_pcie(pdev))
+ pos = pci_pcie_cap(pdev);
+ if (!pos)
return;
parent = pdev->bus->self;
- if (WARN_ON(!parent))
+ if (!parent)
return;
+ if (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) {
+ /* Bluetooth coexistance requires disabling ASPM. */
+ pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);
+ aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+ pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm);
+
+ /*
+ * Both upstream and downstream PCIe components should
+ * have the same ASPM settings.
+ */
+ pos = pci_pcie_cap(parent);
+ pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);
+ aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+ pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm);
+
+ return;
+ }
+
pos = pci_pcie_cap(parent);
pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);
if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
ah->aspm_enabled = true;
/* Initialize PCIe PM and SERDES registers. */
- ath9k_hw_configpcipowersave(ah, 0, 0);
+ ath9k_hw_configpcipowersave(ah, false);
}
}
@@ -145,7 +151,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,
- .bt_coex_prep = ath_pci_bt_coex_prep,
.extn_synch_en = ath_pci_extn_synch_enable,
.aspm_init = ath_pci_aspm_init,
};
@@ -156,7 +161,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct ath_softc *sc;
struct ieee80211_hw *hw;
u8 csz;
- u16 subsysid;
u32 val;
int ret = 0;
char hw_name[64];
@@ -250,8 +254,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sc->irq = pdev->irq;
- pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid);
- ret = ath9k_init_device(id->device, sc, subsysid, &ath_pci_bus_ops);
+ ret = ath9k_init_device(id->device, sc, &ath_pci_bus_ops);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize device\n");
goto err_init;
@@ -330,17 +333,17 @@ static int ath_pci_resume(struct device *device)
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+ ath9k_ps_wakeup(sc);
/* Enable LED */
ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
/*
* Reset key cache to sane defaults (all entries cleared) instead of
* semi-random values after suspend/resume.
*/
- ath9k_ps_wakeup(sc);
- ath9k_init_crypto(sc);
+ ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_ps_restore(sc);
sc->ps_idle = true;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index c04a6c3cac7f..8448281dd069 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -603,7 +603,8 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
struct ath_rate_priv *ath_rc_priv,
const struct ath_rate_table *rate_table,
- int *is_probing)
+ int *is_probing,
+ bool legacy)
{
u32 best_thruput, this_thruput, now_msec;
u8 rate, next_rate, best_rate, maxindex, minindex;
@@ -624,6 +625,8 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
u8 per_thres;
rate = ath_rc_priv->valid_rate_index[index];
+ if (legacy && !(rate_table->info[rate].rate_flags & RC_LEGACY))
+ continue;
if (rate > ath_rc_priv->rate_max_phy)
continue;
@@ -767,7 +770,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_rate *rates = tx_info->control.rates;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
- u8 try_per_rate, i = 0, rix;
+ u8 try_per_rate, i = 0, rix, high_rix;
int is_probe = 0;
if (rate_control_send_low(sta, priv_sta, txrc))
@@ -786,7 +789,9 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
try_per_rate = 4;
rate_table = ath_rc_priv->rate_table;
- rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
+ rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
+ &is_probe, false);
+ high_rix = rix;
/*
* If we're in HT mode and both us and our peer supports LDPC.
@@ -822,10 +827,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
}
/* Fill in the other rates for multirate retry */
- for ( ; i < 4; i++) {
- /* Use twice the number of tries for the last MRR segment. */
- if (i + 1 == 4)
- try_per_rate = 8;
+ for ( ; i < 3; i++) {
ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
/* All other rates in the series have RTS enabled */
@@ -833,6 +835,24 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
try_per_rate, rix, 1);
}
+ /* Use twice the number of tries for the last MRR segment. */
+ try_per_rate = 8;
+
+ /*
+ * Use a legacy rate as last retry to ensure that the frame
+ * is tried in both MCS and legacy rates.
+ */
+ if ((rates[2].flags & IEEE80211_TX_RC_MCS) &&
+ (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) ||
+ (ath_rc_priv->per[high_rix] > 45)))
+ rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
+ &is_probe, true);
+ else
+ ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
+
+ /* All other rates in the series have RTS enabled */
+ ath_rc_rate_set_series(rate_table, &rates[i], txrc,
+ try_per_rate, rix, 1);
/*
* NB:Change rate series to enable aggregation when operating
* at lower MCS rates. When first rate in series is MCS2
@@ -1342,12 +1362,6 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
return;
- if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) {
- tx_info->status.ampdu_ack_len =
- (tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0);
- tx_info->status.ampdu_len = 1;
- }
-
if (!(tx_info->flags & IEEE80211_TX_STAT_ACK))
tx_status = 1;
@@ -1484,7 +1498,7 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
if (rc->rate_table == NULL)
return 0;
- max = 80 + rc->rate_table->rate_cnt * 1024 + 1;
+ max = 80 + rc->rate_table_size * 1024 + 1;
buf = kmalloc(max, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
@@ -1494,7 +1508,7 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
"HT", "MCS", "Rate",
"Success", "Retries", "XRetries", "PER");
- for (i = 0; i < rc->rate_table->rate_cnt; i++) {
+ for (i = 0; i < rc->rate_table_size; i++) {
u32 ratekbps = rc->rate_table->info[i].ratekbps;
struct ath_rc_stats *stats = &rc->rcstats[i];
char mcs[5];
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index c3d850207bee..b7a4bcd3eec7 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -221,12 +221,6 @@ struct ath_rate_priv {
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
};
-enum ath9k_internal_frame_type {
- ATH9K_IFT_NOT_INTERNAL,
- ATH9K_IFT_PAUSE,
- ATH9K_IFT_UNPAUSE
-};
-
#ifdef CONFIG_ATH9K_RATE_CONTROL
int ath_rate_control_register(void);
void ath_rate_control_unregister(void);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 4c21f8cbdeb5..67b862cdae6d 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -433,12 +433,9 @@ void ath_rx_cleanup(struct ath_softc *sc)
u32 ath_calcrxfilter(struct ath_softc *sc)
{
-#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
-
u32 rfilt;
- rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
- | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
+ rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
if (sc->rx.rxfilter & FIF_PROBE_REQ)
@@ -586,22 +583,11 @@ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
{
- struct ieee80211_mgmt *mgmt;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
if (skb->len < 24 + 8 + 2 + 2)
return;
- mgmt = (struct ieee80211_mgmt *)skb->data;
- if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) {
- /* TODO: This doesn't work well if you have stations
- * associated to two different APs because curbssid
- * is just the last AP that any of the stations associated
- * with.
- */
- return; /* not from our current AP */
- }
-
sc->ps_flags &= ~PS_WAIT_FOR_BEACON;
if (sc->ps_flags & PS_BEACON_SYNC) {
@@ -609,7 +595,6 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
ath_dbg(common, ATH_DBG_PS,
"Reconfigure Beacon timers based on timestamp from the AP\n");
ath_set_beacon(sc);
- sc->ps_flags &= ~PS_TSFOOR_SYNC;
}
if (ath_beacon_dtim_pending_cab(skb)) {
@@ -638,7 +623,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
}
}
-static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
+static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)
{
struct ieee80211_hdr *hdr;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -647,7 +632,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
/* Process Beacon and CAB receive in PS state */
if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc))
- && ieee80211_is_beacon(hdr->frame_control))
+ && mybeacon)
ath_rx_ps_beacon(sc, skb);
else if ((sc->ps_flags & PS_WAIT_FOR_CAB) &&
(ieee80211_is_data(hdr->frame_control) ||
@@ -770,7 +755,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
* on. All this is necessary because of our use of
* a self-linked list to avoid rx overruns.
*/
- ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0);
+ ret = ath9k_hw_rxprocdesc(ah, ds, rs);
if (ret == -EINPROGRESS) {
struct ath_rx_status trs;
struct ath_buf *tbf;
@@ -796,7 +781,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
*/
tds = tbf->bf_desc;
- ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0);
+ ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
if (ret == -EINPROGRESS)
return NULL;
}
@@ -823,6 +808,7 @@ static bool ath9k_rx_accept(struct ath_common *common,
struct ath_rx_status *rx_stats,
bool *decrypt_error)
{
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
bool is_mc, is_valid_tkip, strip_mic, mic_error;
struct ath_hw *ah = common->ah;
__le16 fc;
@@ -833,8 +819,10 @@ static bool ath9k_rx_accept(struct ath_common *common,
is_mc = !!is_multicast_ether_addr(hdr->addr1);
is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
test_bit(rx_stats->rs_keyix, common->tkip_keymap);
- strip_mic = is_valid_tkip && !(rx_stats->rs_status &
- (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC));
+ strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
+ !(rx_stats->rs_status &
+ (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
+ ATH9K_RXERR_KEYMISS));
if (!rx_stats->rs_datalen)
return false;
@@ -862,6 +850,8 @@ static bool ath9k_rx_accept(struct ath_common *common,
* descriptors.
*/
if (rx_stats->rs_status != 0) {
+ u8 status_mask;
+
if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
mic_error = false;
@@ -869,7 +859,8 @@ static bool ath9k_rx_accept(struct ath_common *common,
if (rx_stats->rs_status & ATH9K_RXERR_PHY)
return false;
- if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
+ if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
+ (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
*decrypt_error = true;
mic_error = false;
}
@@ -879,17 +870,14 @@ static bool ath9k_rx_accept(struct ath_common *common,
* decryption and MIC failures. For monitor mode,
* we also ignore the CRC error.
*/
- if (ah->is_monitoring) {
- if (rx_stats->rs_status &
- ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
- ATH9K_RXERR_CRC))
- return false;
- } else {
- if (rx_stats->rs_status &
- ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
- return false;
- }
- }
+ status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
+ ATH9K_RXERR_KEYMISS;
+
+ if (ah->is_monitoring && (sc->rx.rxfilter & FIF_FCSFAIL))
+ status_mask |= ATH9K_RXERR_CRC;
+
+ if (rx_stats->rs_status & ~status_mask)
+ return false;
}
/*
@@ -945,7 +933,7 @@ static int ath9k_process_rate(struct ath_common *common,
* No valid hardware bitrate found -- we should not get here
* because hardware has already validated this frame as OK.
*/
- ath_dbg(common, ATH_DBG_XMIT,
+ ath_dbg(common, ATH_DBG_ANY,
"unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
rx_stats->rs_rate);
@@ -960,23 +948,12 @@ static void ath9k_process_rssi(struct ath_common *common,
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = common->ah;
int last_rssi;
- __le16 fc;
- if ((ah->opmode != NL80211_IFTYPE_STATION) &&
- (ah->opmode != NL80211_IFTYPE_ADHOC))
+ if (!rx_stats->is_mybeacon ||
+ ((ah->opmode != NL80211_IFTYPE_STATION) &&
+ (ah->opmode != NL80211_IFTYPE_ADHOC)))
return;
- fc = hdr->frame_control;
- if (!ieee80211_is_beacon(fc) ||
- compare_ether_addr(hdr->addr3, common->curbssid)) {
- /* TODO: This doesn't work well if you have stations
- * associated to two different APs because curbssid
- * is just the last AP that any of the stations associated
- * with.
- */
- return;
- }
-
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
@@ -1003,6 +980,8 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
struct ieee80211_rx_status *rx_status,
bool *decrypt_error)
{
+ struct ath_hw *ah = common->ah;
+
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
/*
@@ -1023,7 +1002,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
rx_status->band = hw->conf.channel->band;
rx_status->freq = hw->conf.channel->center_freq;
- rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
+ rx_status->signal = ah->noise + rx_stats->rs_rssi;
rx_status->antenna = rx_stats->rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
@@ -1791,11 +1770,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
struct ieee80211_rx_status *rxs;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- /*
- * The hw can technically differ from common->hw when using ath9k
- * virtual wiphy so to account for that we iterate over the active
- * wiphys and find the appropriate wiphy and therefore hw.
- */
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_hdr *hdr;
int retval;
@@ -1849,6 +1823,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
rxs = IEEE80211_SKB_RXCB(hdr_skb);
+ if (ieee80211_is_beacon(hdr->frame_control) &&
+ !compare_ether_addr(hdr->addr3, common->curbssid))
+ rs.is_mybeacon = true;
+ else
+ rs.is_mybeacon = false;
ath_debug_stat_rx(sc, &rs);
@@ -1856,7 +1835,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
* If we're asked to flush receive queue, directly
* chain it back at the queue without processing it.
*/
- if (flush)
+ if (sc->sc_flags & SC_OP_RXFLUSH)
goto requeue_drop_frag;
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
@@ -1961,13 +1940,13 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if ((sc->ps_flags & (PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA)) ||
- ath9k_check_auto_sleep(sc))
- ath_rx_ps(sc, skb);
+ PS_WAIT_FOR_CAB |
+ PS_WAIT_FOR_PSPOLL_DATA)) ||
+ ath9k_check_auto_sleep(sc))
+ ath_rx_ps(sc, skb, rs.is_mybeacon);
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
- if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
ath_ant_comb_scan(sc, &rs);
ieee80211_rx(hw, skb);
@@ -1984,11 +1963,17 @@ requeue:
} else {
list_move_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_buf_link(sc, bf);
- ath9k_hw_rxena(ah);
+ if (!flush)
+ ath9k_hw_rxena(ah);
}
} while (1);
spin_unlock_bh(&sc->rx.rxbuflock);
+ if (!(ah->imask & ATH9K_INT_RXEOL)) {
+ ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+ ath9k_hw_set_interrupts(ah);
+ }
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index fa4c0bbce6b9..8fcb7e9e8399 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -619,6 +619,7 @@
#define AR_D_GBL_IFS_EIFS 0x10b0
#define AR_D_GBL_IFS_EIFS_M 0x0000FFFF
#define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000
+#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO 363
#define AR_D_GBL_IFS_MISC 0x10f0
#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007
@@ -793,14 +794,15 @@
#define AR_SREV_REVISION_9485_10 0
#define AR_SREV_REVISION_9485_11 1
#define AR_SREV_VERSION_9340 0x300
+#define AR_SREV_VERSION_9580 0x1C0
+#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
+#define AR_SREV_VERSION_9462 0x280
+#define AR_SREV_REVISION_9462_10 0
+#define AR_SREV_REVISION_9462_20 2
#define AR_SREV_5416(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
-#define AR_SREV_5416_20_OR_LATER(_ah) \
- (((AR_SREV_5416(_ah)) && \
- ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \
- ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
#define AR_SREV_5416_22_OR_LATER(_ah) \
(((AR_SREV_5416(_ah)) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
@@ -893,6 +895,33 @@
(AR_SREV_9285_12_OR_LATER(_ah) && \
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
+#define AR_SREV_9462(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
+
+#define AR_SREV_9462_10(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_10))
+
+#define AR_SREV_9462_20(_ah) \
+ (((_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_9580(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10))
+
+#define AR_SREV_9580_10(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9580_10))
+
+/* NOTE: When adding chips newer than Peacock, add chip check here */
+#define AR_SREV_9580_10_OR_LATER(_ah) \
+ (AR_SREV_9580(_ah))
+
enum ath_usb_dev {
AR9280_USB = 1, /* AR7010 + AR9280, UB94 */
AR9287_USB = 2, /* AR7010 + AR9287, UB95 */
@@ -1117,7 +1146,7 @@ enum {
#define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
#define AR_ENT_OTP 0x40d8
#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000
-#define AR_ENT_OTP_MPSD 0x00800000
+#define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE 0x00800000
#define AR_CH0_BB_DPLL1 0x16180
#define AR_CH0_BB_DPLL1_REFDIV 0xF8000000
@@ -1489,6 +1518,7 @@ enum {
#define AR_USEC_TX_LAT_S 14
#define AR_USEC_RX_LAT 0x1F800000
#define AR_USEC_RX_LAT_S 23
+#define AR_USEC_ASYNC_FIFO 0x12E00074
#define AR_RESET_TSF 0x8020
#define AR_RESET_TSF_ONCE 0x01000000
@@ -1763,6 +1793,7 @@ enum {
#define AR_TXOP_12_15 0x81fc
#define AR_NEXT_NDP2_TIMER 0x8180
+#define AR_GEN_TIMER_BANK_1_LEN 8
#define AR_FIRST_NDP_TIMER 7
#define AR_NDP2_PERIOD 0x81a0
#define AR_NDP2_TIMER_MODE 0x81c0
@@ -1851,9 +1882,10 @@ enum {
#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000
#define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000
-#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358
-#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400
-#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
+#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
+#define AR_MAC_PCU_GEN_TIMER_TSF_SEL 0x83d8
#define AR_AES_MUTE_MASK0 0x805c
@@ -1901,7 +1933,42 @@ enum {
#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* don't update noise floor automatically */
#define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS 0x00040000 /* extend noise floor power measurement */
#define AR_PHY_AGC_CONTROL_CLC_SUCCESS 0x00080000 /* carrier leak calibration done */
+#define AR_PHY_AGC_CONTROL_PKDET_CAL 0x00100000
#define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0
#define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6
+/* MCI Registers */
+#define AR_MCI_INTERRUPT_RX_MSG_EN 0x183c
+#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001
+#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S 0
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S 1
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S 2
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S 3
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S 4
+#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020
+#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S 5
+#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040
+#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S 6
+#define AR_MCI_INTERRUPT_RX_MSG_GPM 0x00000100
+#define AR_MCI_INTERRUPT_RX_MSG_GPM_S 8
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S 9
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S 10
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S 11
+#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000
+#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S 12
+#define AR_MCI_INTERRUPT_RX_HW_MSG_MASK (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \
+ AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL| \
+ AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \
+ AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \
+ AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \
+ AR_MCI_INTERRUPT_RX_MSG_CONT_RST)
+
+
#endif
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index cc595712f518..03b0a651a591 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -48,19 +48,23 @@ static u16 bits_per_symbol[][2] = {
#define IS_HT_RATE(_rate) ((_rate) & 0x80)
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid,
- struct list_head *bf_head);
+ struct ath_atx_tid *tid, struct sk_buff *skb);
+static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+ int tx_flags, struct ath_txq *txq);
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq, struct list_head *bf_q,
struct ath_tx_status *ts, int txok, int sendbar);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
struct list_head *head, bool internal);
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int nframes, int nbad,
- int txok, bool update_rc);
+ int txok);
static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
int seqno);
+static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+ struct ath_txq *txq,
+ struct ath_atx_tid *tid,
+ struct sk_buff *skb);
enum {
MCS_HT20,
@@ -129,7 +133,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
spin_lock_bh(&txq->axq_lock);
tid->paused = false;
- if (list_empty(&tid->buf_q))
+ if (skb_queue_empty(&tid->buf_q))
goto unlock;
ath_tx_queue_tid(txq, tid);
@@ -149,6 +153,7 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = tid->ac->txq;
+ struct sk_buff *skb;
struct ath_buf *bf;
struct list_head bf_head;
struct ath_tx_status ts;
@@ -159,17 +164,17 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
memset(&ts, 0, sizeof(ts));
spin_lock_bh(&txq->axq_lock);
- while (!list_empty(&tid->buf_q)) {
- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- list_move_tail(&bf->list, &bf_head);
+ while ((skb = __skb_dequeue(&tid->buf_q))) {
+ fi = get_frame_info(skb);
+ bf = fi->bf;
spin_unlock_bh(&txq->axq_lock);
- fi = get_frame_info(bf->bf_mpdu);
- if (fi->retries) {
- ath_tx_update_baw(sc, tid, fi->seqno);
+ if (bf && fi->retries) {
+ list_add_tail(&bf->list, &bf_head);
+ ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
} else {
- ath_tx_send_normal(sc, txq, NULL, &bf_head);
+ ath_tx_send_normal(sc, txq, NULL, skb);
}
spin_lock_bh(&txq->axq_lock);
}
@@ -219,6 +224,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid)
{
+ struct sk_buff *skb;
struct ath_buf *bf;
struct list_head bf_head;
struct ath_tx_status ts;
@@ -227,16 +233,21 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
memset(&ts, 0, sizeof(ts));
INIT_LIST_HEAD(&bf_head);
- for (;;) {
- if (list_empty(&tid->buf_q))
- break;
+ while ((skb = __skb_dequeue(&tid->buf_q))) {
+ fi = get_frame_info(skb);
+ bf = fi->bf;
- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- list_move_tail(&bf->list, &bf_head);
+ if (!bf) {
+ spin_unlock(&txq->axq_lock);
+ ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
+ spin_lock(&txq->axq_lock);
+ continue;
+ }
+
+ list_add_tail(&bf->list, &bf_head);
- fi = get_frame_info(bf->bf_mpdu);
if (fi->retries)
- ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
spin_unlock(&txq->axq_lock);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
@@ -251,6 +262,7 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
struct sk_buff *skb)
{
struct ath_frame_info *fi = get_frame_info(skb);
+ struct ath_buf *bf = fi->bf;
struct ieee80211_hdr *hdr;
TX_STAT_INC(txq->axq_qnum, a_retries);
@@ -259,6 +271,8 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
hdr = (struct ieee80211_hdr *)skb->data;
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
+ dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+ sizeof(*hdr), DMA_TO_DEVICE);
}
static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
@@ -326,7 +340,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
while (bf) {
fi = get_frame_info(bf->bf_mpdu);
- ba_index = ATH_BA_INDEX(seq_st, fi->seqno);
+ ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno);
(*nframes)++;
if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
@@ -349,7 +363,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ieee80211_tx_info *tx_info;
struct ath_atx_tid *tid = NULL;
struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
- struct list_head bf_head, bf_pending;
+ struct list_head bf_head;
+ struct sk_buff_head bf_pending;
u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
u32 ba[WME_BA_BMP_SIZE >> 5];
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
@@ -358,7 +373,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ath_frame_info *fi;
int nframes;
u8 tidno;
- bool clear_filter;
+ bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -377,11 +392,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
while (bf) {
bf_next = bf->bf_next;
- bf->bf_state.bf_type |= BUF_XRETRY;
if (!bf->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
- ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
0, 0);
@@ -422,11 +435,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
}
}
- INIT_LIST_HEAD(&bf_pending);
- INIT_LIST_HEAD(&bf_head);
+ __skb_queue_head_init(&bf_pending);
ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
while (bf) {
+ u16 seqno = bf->bf_state.seqno;
+
txfail = txpending = sendbar = 0;
bf_next = bf->bf_next;
@@ -434,7 +448,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb);
fi = get_frame_info(skb);
- if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) {
+ if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
/* transmit completion, subframe is
* acked by block ack */
acked_cnt++;
@@ -448,15 +462,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* the un-acked sub-frames
*/
txfail = 1;
+ } else if (flush) {
+ txpending = 1;
} else if (fi->retries < ATH_MAX_SW_RETRIES) {
- if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
- !an->sleeping)
+ if (txok || !an->sleeping)
ath_tx_set_retry(sc, txq, bf->bf_mpdu);
- clear_filter = true;
txpending = 1;
} else {
- bf->bf_state.bf_type |= BUF_XRETRY;
txfail = 1;
sendbar = 1;
txfail_cnt++;
@@ -467,10 +480,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* Make sure the last desc is reclaimed if it
* not a holding desc.
*/
- if (!bf_last->bf_stale || bf_next != NULL)
+ INIT_LIST_HEAD(&bf_head);
+ if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
+ bf_next != NULL || !bf_last->bf_stale)
list_move_tail(&bf->list, &bf_head);
- else
- INIT_LIST_HEAD(&bf_head);
if (!txpending || (tid->state & AGGR_CLEANUP)) {
/*
@@ -478,22 +491,19 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* block-ack window
*/
spin_lock_bh(&txq->axq_lock);
- ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock);
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
memcpy(tx_info->control.rates, rates, sizeof(rates));
- ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true);
+ ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok);
rc_update = false;
- } else {
- ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false);
}
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
!txfail, sendbar);
} else {
/* retry the un-acked ones */
- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
if (bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf;
@@ -506,29 +516,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
*/
if (!tbf) {
spin_lock_bh(&txq->axq_lock);
- ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock);
- bf->bf_state.bf_type |=
- BUF_XRETRY;
- ath_tx_rc_status(sc, bf, ts, nframes,
- nbad, 0, false);
ath_tx_complete_buf(sc, bf, txq,
&bf_head,
- ts, 0, 0);
+ ts, 0,
+ !flush);
break;
}
- ath9k_hw_cleartxdesc(sc->sc_ah,
- tbf->bf_desc);
- list_add_tail(&tbf->list, &bf_head);
- } else {
- /*
- * Clear descriptor status words for
- * software retry
- */
- ath9k_hw_cleartxdesc(sc->sc_ah,
- bf->bf_desc);
+ fi->bf = tbf;
}
}
@@ -536,22 +534,25 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* Put this buffer to the temporary pending
* queue to retain ordering
*/
- list_splice_tail_init(&bf_head, &bf_pending);
+ __skb_queue_tail(&bf_pending, skb);
}
bf = bf_next;
}
/* prepend un-acked frames to the beginning of the pending frame queue */
- if (!list_empty(&bf_pending)) {
+ if (!skb_queue_empty(&bf_pending)) {
if (an->sleeping)
- ieee80211_sta_set_tim(sta);
+ ieee80211_sta_set_buffered(sta, tid->tidno, true);
spin_lock_bh(&txq->axq_lock);
- if (clear_filter)
- tid->ac->clear_ps_filter = true;
- list_splice(&bf_pending, &tid->buf_q);
- ath_tx_queue_tid(txq, tid);
+ skb_queue_splice(&bf_pending, &tid->buf_q);
+ if (!an->sleeping) {
+ ath_tx_queue_tid(txq, tid);
+
+ if (ts->ts_status & ATH9K_TXERR_FILT)
+ tid->ac->clear_ps_filter = true;
+ }
spin_unlock_bh(&txq->axq_lock);
}
@@ -566,8 +567,32 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
rcu_read_unlock();
- if (needreset)
- ath_reset(sc, false);
+ if (needreset) {
+ RESET_STAT_INC(sc, RESET_TYPE_TX_ERROR);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ }
+}
+
+static bool ath_lookup_legacy(struct ath_buf *bf)
+{
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *tx_info;
+ struct ieee80211_tx_rate *rates;
+ int i;
+
+ skb = bf->bf_mpdu;
+ tx_info = IEEE80211_SKB_CB(skb);
+ rates = tx_info->control.rates;
+
+ for (i = 0; i < 4; i++) {
+ if (!rates[i].count || rates[i].idx < 0)
+ break;
+
+ if (!(rates[i].flags & IEEE80211_TX_RC_MCS))
+ return true;
+ }
+
+ return false;
}
static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
@@ -643,8 +668,10 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
* meet the minimum required mpdudensity.
*/
static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
- struct ath_buf *bf, u16 frmlen)
+ struct ath_buf *bf, u16 frmlen,
+ bool first_subfrm)
{
+#define FIRST_DESC_NDELIMS 60
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
u32 nsymbits, nsymbols;
@@ -667,6 +694,14 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
ndelim += ATH_AGGR_ENCRYPTDELIM;
/*
+ * Add delimiter when using RTS/CTS with aggregation
+ * and non enterprise AR9003 card
+ */
+ if (first_subfrm && !AR_SREV_9580_10_OR_LATER(sc->sc_ah) &&
+ (sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE))
+ ndelim = max(ndelim, FIRST_DESC_NDELIMS);
+
+ /*
* Convert desired mpdu density from microeconds to bytes based
* on highest rate in rate series (i.e. first rate) to determine
* required minimum length for subframe. Take into account
@@ -711,22 +746,33 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
int *aggr_len)
{
#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
- struct ath_buf *bf, *bf_first, *bf_prev = NULL;
+ struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
int rl = 0, nframes = 0, ndelim, prev_al = 0;
u16 aggr_limit = 0, al = 0, bpad = 0,
al_delta, h_baw = tid->baw_size / 2;
enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
struct ieee80211_tx_info *tx_info;
struct ath_frame_info *fi;
-
- bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
+ struct sk_buff *skb;
+ u16 seqno;
do {
- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- fi = get_frame_info(bf->bf_mpdu);
+ skb = skb_peek(&tid->buf_q);
+ fi = get_frame_info(skb);
+ bf = fi->bf;
+ if (!fi->bf)
+ bf = ath_tx_setup_buffer(sc, txq, tid, skb);
+
+ if (!bf)
+ continue;
+
+ bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
+ seqno = bf->bf_state.seqno;
+ if (!bf_first)
+ bf_first = bf;
/* do not step over block-ack window */
- if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
+ if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
status = ATH_AGGR_BAW_CLOSED;
break;
}
@@ -740,14 +786,14 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;
if (nframes &&
- (aggr_limit < (al + bpad + al_delta + prev_al))) {
+ ((aggr_limit < (al + bpad + al_delta + prev_al)) ||
+ ath_lookup_legacy(bf))) {
status = ATH_AGGR_LIMITED;
break;
}
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
- if (nframes && ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
- !(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)))
+ if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
break;
/* do not exceed subframe limit */
@@ -755,7 +801,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
status = ATH_AGGR_LIMITED;
break;
}
- nframes++;
/* add padding for previous frame to aggregation length */
al += bpad + al_delta;
@@ -764,25 +809,26 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
* Get the delimiters needed to meet the MPDU
* density for this node.
*/
- ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen);
+ ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen,
+ !nframes);
bpad = PADBYTES(al_delta) + (ndelim << 2);
+ nframes++;
bf->bf_next = NULL;
- ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
/* link buffers of this frame to the aggregate */
if (!fi->retries)
- ath_tx_addto_baw(sc, tid, fi->seqno);
- ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
- list_move_tail(&bf->list, bf_q);
- if (bf_prev) {
+ ath_tx_addto_baw(sc, tid, seqno);
+ bf->bf_state.ndelim = ndelim;
+
+ __skb_unlink(skb, &tid->buf_q);
+ list_add_tail(&bf->list, bf_q);
+ if (bf_prev)
bf_prev->bf_next = bf;
- ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
- bf->bf_daddr);
- }
+
bf_prev = bf;
- } while (!list_empty(&tid->buf_q));
+ } while (!skb_queue_empty(&tid->buf_q));
*aggr_len = al;
@@ -790,17 +836,236 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
#undef PADBYTES
}
+/*
+ * rix - rate index
+ * pktlen - total bytes (delims + data + fcs + pads + pad delims)
+ * width - 0 for 20 MHz, 1 for 40 MHz
+ * half_gi - to use 4us v/s 3.6 us for symbol time
+ */
+static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
+ int width, int half_gi, bool shortPreamble)
+{
+ u32 nbits, nsymbits, duration, nsymbols;
+ int streams;
+
+ /* find number of symbols: PLCP + data */
+ streams = HT_RC_2_STREAMS(rix);
+ nbits = (pktlen << 3) + OFDM_PLCP_BITS;
+ nsymbits = bits_per_symbol[rix % 8][width] * streams;
+ nsymbols = (nbits + nsymbits - 1) / nsymbits;
+
+ if (!half_gi)
+ duration = SYMBOL_TIME(nsymbols);
+ else
+ duration = SYMBOL_TIME_HALFGI(nsymbols);
+
+ /* addup duration for legacy/ht training and signal fields */
+ duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
+
+ return duration;
+}
+
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_tx_info *info, int len)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *tx_info;
+ struct ieee80211_tx_rate *rates;
+ const struct ieee80211_rate *rate;
+ struct ieee80211_hdr *hdr;
+ int i;
+ u8 rix = 0;
+
+ skb = bf->bf_mpdu;
+ tx_info = IEEE80211_SKB_CB(skb);
+ rates = tx_info->control.rates;
+ hdr = (struct ieee80211_hdr *)skb->data;
+
+ /* set dur_update_en for l-sig computation except for PS-Poll frames */
+ info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
+
+ /*
+ * We check if Short Preamble is needed for the CTS rate by
+ * checking the BSS's global flag.
+ * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
+ */
+ rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
+ info->rtscts_rate = rate->hw_value;
+ if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+ info->rtscts_rate |= rate->hw_value_short;
+
+ for (i = 0; i < 4; i++) {
+ bool is_40, is_sgi, is_sp;
+ int phy;
+
+ if (!rates[i].count || (rates[i].idx < 0))
+ continue;
+
+ rix = rates[i].idx;
+ info->rates[i].Tries = rates[i].count;
+
+ if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+ info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+ info->flags |= ATH9K_TXDESC_RTSENA;
+ } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+ info->flags |= ATH9K_TXDESC_CTSENA;
+ }
+
+ if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ info->rates[i].RateFlags |= ATH9K_RATESERIES_2040;
+ if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
+ info->rates[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
+
+ is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
+ is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
+ is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
+
+ if (rates[i].flags & IEEE80211_TX_RC_MCS) {
+ /* MCS rates */
+ info->rates[i].Rate = rix | 0x80;
+ info->rates[i].ChSel = ath_txchainmask_reduction(sc,
+ ah->txchainmask, info->rates[i].Rate);
+ info->rates[i].PktDuration = ath_pkt_duration(sc, rix, len,
+ is_40, is_sgi, is_sp);
+ if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
+ info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
+ continue;
+ }
+
+ /* legacy rates */
+ if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
+ !(rate->flags & IEEE80211_RATE_ERP_G))
+ phy = WLAN_RC_PHY_CCK;
+ else
+ phy = WLAN_RC_PHY_OFDM;
+
+ rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
+ info->rates[i].Rate = rate->hw_value;
+ if (rate->hw_value_short) {
+ if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+ info->rates[i].Rate |= rate->hw_value_short;
+ } else {
+ is_sp = false;
+ }
+
+ if (bf->bf_state.bfs_paprd)
+ info->rates[i].ChSel = ah->txchainmask;
+ else
+ info->rates[i].ChSel = ath_txchainmask_reduction(sc,
+ ah->txchainmask, info->rates[i].Rate);
+
+ info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
+ phy, rate->bitrate * 100, len, rix, is_sp);
+ }
+
+ /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
+ if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
+ info->flags &= ~ATH9K_TXDESC_RTSENA;
+
+ /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
+ if (info->flags & ATH9K_TXDESC_RTSENA)
+ info->flags &= ~ATH9K_TXDESC_CTSENA;
+}
+
+static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr;
+ enum ath9k_pkt_type htype;
+ __le16 fc;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ fc = hdr->frame_control;
+
+ if (ieee80211_is_beacon(fc))
+ htype = ATH9K_PKT_TYPE_BEACON;
+ else if (ieee80211_is_probe_resp(fc))
+ htype = ATH9K_PKT_TYPE_PROBE_RESP;
+ else if (ieee80211_is_atim(fc))
+ htype = ATH9K_PKT_TYPE_ATIM;
+ else if (ieee80211_is_pspoll(fc))
+ htype = ATH9K_PKT_TYPE_PSPOLL;
+ else
+ htype = ATH9K_PKT_TYPE_NORMAL;
+
+ return htype;
+}
+
+static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_txq *txq, int len)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
+ struct ath_buf *bf_first = bf;
+ struct ath_tx_info info;
+ bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR);
+
+ memset(&info, 0, sizeof(info));
+ info.is_first = true;
+ info.is_last = true;
+ info.txpower = MAX_RATE_POWER;
+ info.qcu = txq->axq_qnum;
+
+ info.flags = ATH9K_TXDESC_INTREQ;
+ if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
+ info.flags |= ATH9K_TXDESC_NOACK;
+ if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
+ info.flags |= ATH9K_TXDESC_LDPC;
+
+ ath_buf_set_rate(sc, bf, &info, len);
+
+ if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
+ info.flags |= ATH9K_TXDESC_CLRDMASK;
+
+ if (bf->bf_state.bfs_paprd)
+ info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S;
+
+
+ while (bf) {
+ struct sk_buff *skb = bf->bf_mpdu;
+ struct ath_frame_info *fi = get_frame_info(skb);
+
+ info.type = get_hw_packet_type(skb);
+ if (bf->bf_next)
+ info.link = bf->bf_next->bf_daddr;
+ else
+ info.link = 0;
+
+ info.buf_addr[0] = bf->bf_buf_addr;
+ info.buf_len[0] = skb->len;
+ info.pkt_len = fi->framelen;
+ info.keyix = fi->keyix;
+ info.keytype = fi->keytype;
+
+ if (aggr) {
+ if (bf == bf_first)
+ info.aggr = AGGR_BUF_FIRST;
+ else if (!bf->bf_next)
+ info.aggr = AGGR_BUF_LAST;
+ else
+ info.aggr = AGGR_BUF_MIDDLE;
+
+ info.ndelim = bf->bf_state.ndelim;
+ info.aggr_len = len;
+ }
+
+ ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
+ bf = bf->bf_next;
+ }
+}
+
static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid)
{
struct ath_buf *bf;
enum ATH_AGGR_STATUS status;
- struct ath_frame_info *fi;
+ struct ieee80211_tx_info *tx_info;
struct list_head bf_q;
int aggr_len;
do {
- if (list_empty(&tid->buf_q))
+ if (skb_queue_empty(&tid->buf_q))
return;
INIT_LIST_HEAD(&bf_q);
@@ -816,34 +1081,25 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf = list_first_entry(&bf_q, struct ath_buf, list);
bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
+ tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
if (tid->ac->clear_ps_filter) {
tid->ac->clear_ps_filter = false;
- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
+ tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+ } else {
+ tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
}
/* if only one frame, send as non-aggregate */
if (bf == bf->bf_lastbf) {
- fi = get_frame_info(bf->bf_mpdu);
-
- bf->bf_state.bf_type &= ~BUF_AGGR;
- ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
- ath_buf_set_rate(sc, bf, fi->framelen);
- ath_tx_txqaddbuf(sc, txq, &bf_q, false);
- continue;
+ aggr_len = get_frame_info(bf->bf_mpdu)->framelen;
+ bf->bf_state.bf_type = BUF_AMPDU;
+ } else {
+ TX_STAT_INC(txq->axq_qnum, a_aggr);
}
- /* setup first desc of aggregate */
- bf->bf_state.bf_type |= BUF_AGGR;
- ath_buf_set_rate(sc, bf, aggr_len);
- ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len);
-
- /* anchor last desc of aggregate */
- ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
-
+ ath_tx_fill_desc(sc, bf, txq, aggr_len);
ath_tx_txqaddbuf(sc, txq, &bf_q, false);
- TX_STAT_INC(txq->axq_qnum, a_aggr);
-
} while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
status != ATH_AGGR_BAW_CLOSED);
}
@@ -902,12 +1158,13 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
ath_tx_flush_tid(sc, txtid);
}
-bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
+void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
+ struct ath_node *an)
{
struct ath_atx_tid *tid;
struct ath_atx_ac *ac;
struct ath_txq *txq;
- bool buffered = false;
+ bool buffered;
int tidno;
for (tidno = 0, tid = &an->tid[tidno];
@@ -921,8 +1178,7 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
spin_lock_bh(&txq->axq_lock);
- if (!list_empty(&tid->buf_q))
- buffered = true;
+ buffered = !skb_queue_empty(&tid->buf_q);
tid->sched = false;
list_del(&tid->list);
@@ -933,9 +1189,9 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
}
spin_unlock_bh(&txq->axq_lock);
- }
- return buffered;
+ ieee80211_sta_set_buffered(sta, tidno, buffered);
+ }
}
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
@@ -954,7 +1210,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
spin_lock_bh(&txq->axq_lock);
ac->clear_ps_filter = true;
- if (!list_empty(&tid->buf_q) && !tid->paused) {
+ if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
ath_tx_queue_tid(txq, tid);
ath_txq_schedule(sc, txq);
}
@@ -1004,7 +1260,6 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
{
struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_tx_queue_info qi;
static const int subtype_txq_to_hwq[] = {
[WME_AC_BE] = ATH_TXQ_AC_BE,
@@ -1054,12 +1309,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
*/
return NULL;
}
- if (axq_qnum >= ARRAY_SIZE(sc->tx.txq)) {
- ath_err(common, "qnum %u out of range, max %zu!\n",
- axq_qnum, ARRAY_SIZE(sc->tx.txq));
- ath9k_hw_releasetxqueue(ah, axq_qnum);
- return NULL;
- }
if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
struct ath_txq *txq = &sc->tx.txq[axq_qnum];
@@ -1156,6 +1405,7 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
struct ath_tx_status ts;
memset(&ts, 0, sizeof(ts));
+ ts.ts_status = ATH9K_TX_FLUSH;
INIT_LIST_HEAD(&bf_head);
while (!list_empty(list)) {
@@ -1222,7 +1472,8 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_txq *txq;
- int i, npend = 0;
+ int i;
+ u32 npend = 0;
if (sc->sc_flags & SC_OP_INVALID)
return true;
@@ -1234,11 +1485,12 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
if (!ATH_TXQ_SETUP(sc, i))
continue;
- npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
+ if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
+ npend |= BIT(i);
}
if (npend)
- ath_err(common, "Failed to stop TX DMA!\n");
+ ath_err(common, "Failed to stop TX DMA, queues=0x%03x!\n", npend);
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (!ATH_TXQ_SETUP(sc, i))
@@ -1271,7 +1523,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
struct ath_atx_ac *ac, *ac_tmp, *last_ac;
struct ath_atx_tid *tid, *last_tid;
- if (list_empty(&txq->axq_acq) ||
+ if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
return;
@@ -1298,7 +1550,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
* add tid to round-robin queue if more frames
* are pending for the tid
*/
- if (!list_empty(&tid->buf_q))
+ if (!skb_queue_empty(&tid->buf_q))
ath_tx_queue_tid(txq, tid);
if (tid == last_tid ||
@@ -1390,12 +1642,11 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
}
static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
- struct ath_buf *bf, struct ath_tx_control *txctl)
+ struct sk_buff *skb, struct ath_tx_control *txctl)
{
- struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
+ struct ath_frame_info *fi = get_frame_info(skb);
struct list_head bf_head;
-
- bf->bf_state.bf_type |= BUF_AMPDU;
+ struct ath_buf *bf;
/*
* Do not queue to h/w when any of the following conditions is true:
@@ -1404,113 +1655,82 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
* - seqno is not within block-ack window
* - h/w queue depth exceeds low water mark
*/
- if (!list_empty(&tid->buf_q) || tid->paused ||
- !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
+ if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
+ !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) ||
txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
/*
* Add this frame to software queue for scheduling later
* for aggregation.
*/
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
- list_add_tail(&bf->list, &tid->buf_q);
- ath_tx_queue_tid(txctl->txq, tid);
+ __skb_queue_tail(&tid->buf_q, skb);
+ if (!txctl->an || !txctl->an->sleeping)
+ ath_tx_queue_tid(txctl->txq, tid);
return;
}
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (!bf)
+ return;
+
+ bf->bf_state.bf_type = BUF_AMPDU;
INIT_LIST_HEAD(&bf_head);
list_add(&bf->list, &bf_head);
/* Add sub-frame to BAW */
- if (!fi->retries)
- ath_tx_addto_baw(sc, tid, fi->seqno);
+ ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
/* Queue to h/w without aggregation */
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
bf->bf_lastbf = bf;
- ath_buf_set_rate(sc, bf, fi->framelen);
+ ath_tx_fill_desc(sc, bf, txctl->txq, fi->framelen);
ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
}
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid,
- struct list_head *bf_head)
+ struct ath_atx_tid *tid, struct sk_buff *skb)
{
- struct ath_frame_info *fi;
+ struct ath_frame_info *fi = get_frame_info(skb);
+ struct list_head bf_head;
struct ath_buf *bf;
- bf = list_first_entry(bf_head, struct ath_buf, list);
- bf->bf_state.bf_type &= ~BUF_AMPDU;
+ bf = fi->bf;
+ if (!bf)
+ bf = ath_tx_setup_buffer(sc, txq, tid, skb);
+
+ if (!bf)
+ return;
+
+ INIT_LIST_HEAD(&bf_head);
+ list_add_tail(&bf->list, &bf_head);
+ bf->bf_state.bf_type = 0;
/* update starting sequence number for subsequent ADDBA request */
if (tid)
INCR(tid->seq_start, IEEE80211_SEQ_MAX);
bf->bf_lastbf = bf;
- fi = get_frame_info(bf->bf_mpdu);
- ath_buf_set_rate(sc, bf, fi->framelen);
- ath_tx_txqaddbuf(sc, txq, bf_head, false);
+ ath_tx_fill_desc(sc, bf, txq, fi->framelen);
+ ath_tx_txqaddbuf(sc, txq, &bf_head, false);
TX_STAT_INC(txq->axq_qnum, queued);
}
-static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
-{
- struct ieee80211_hdr *hdr;
- enum ath9k_pkt_type htype;
- __le16 fc;
-
- hdr = (struct ieee80211_hdr *)skb->data;
- fc = hdr->frame_control;
-
- if (ieee80211_is_beacon(fc))
- htype = ATH9K_PKT_TYPE_BEACON;
- else if (ieee80211_is_probe_resp(fc))
- htype = ATH9K_PKT_TYPE_PROBE_RESP;
- else if (ieee80211_is_atim(fc))
- htype = ATH9K_PKT_TYPE_ATIM;
- else if (ieee80211_is_pspoll(fc))
- htype = ATH9K_PKT_TYPE_PSPOLL;
- else
- htype = ATH9K_PKT_TYPE_NORMAL;
-
- return htype;
-}
-
static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
int framelen)
{
- struct ath_softc *sc = hw->priv;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = tx_info->control.sta;
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_frame_info *fi = get_frame_info(skb);
struct ath_node *an = NULL;
- struct ath_atx_tid *tid;
enum ath9k_key_type keytype;
- u16 seqno = 0;
- u8 tidno;
keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
if (sta)
an = (struct ath_node *) sta->drv_priv;
- hdr = (struct ieee80211_hdr *)skb->data;
- if (an && ieee80211_is_data_qos(hdr->frame_control) &&
- conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
-
- tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
-
- /*
- * Override seqno set by upper layer with the one
- * in tx aggregation state.
- */
- tid = ATH_AN_2_TID(an, tidno);
- seqno = tid->seq_next;
- hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
- INCR(tid->seq_next, IEEE80211_SEQ_MAX);
- }
-
memset(fi, 0, sizeof(*fi));
if (hw_key)
fi->keyix = hw_key->hw_key_idx;
@@ -1520,199 +1740,50 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
fi->keyix = ATH9K_TXKEYIX_INVALID;
fi->keytype = keytype;
fi->framelen = framelen;
- fi->seqno = seqno;
-}
-
-static int setup_tx_flags(struct sk_buff *skb)
-{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- int flags = 0;
-
- flags |= ATH9K_TXDESC_INTREQ;
-
- if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
- flags |= ATH9K_TXDESC_NOACK;
-
- if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
- flags |= ATH9K_TXDESC_LDPC;
-
- return flags;
-}
-
-/*
- * rix - rate index
- * pktlen - total bytes (delims + data + fcs + pads + pad delims)
- * width - 0 for 20 MHz, 1 for 40 MHz
- * half_gi - to use 4us v/s 3.6 us for symbol time
- */
-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
- int width, int half_gi, bool shortPreamble)
-{
- u32 nbits, nsymbits, duration, nsymbols;
- int streams;
-
- /* find number of symbols: PLCP + data */
- streams = HT_RC_2_STREAMS(rix);
- nbits = (pktlen << 3) + OFDM_PLCP_BITS;
- nsymbits = bits_per_symbol[rix % 8][width] * streams;
- nsymbols = (nbits + nsymbits - 1) / nsymbits;
-
- if (!half_gi)
- duration = SYMBOL_TIME(nsymbols);
- else
- duration = SYMBOL_TIME_HALFGI(nsymbols);
-
- /* addup duration for legacy/ht training and signal fields */
- duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
-
- return duration;
}
u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_channel *curchan = ah->curchan;
- if ((sc->sc_flags & SC_OP_ENABLE_APM) &&
- (curchan->channelFlags & CHANNEL_5GHZ) &&
- (chainmask == 0x7) && (rate < 0x90))
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) &&
+ (curchan->channelFlags & CHANNEL_5GHZ) &&
+ (chainmask == 0x7) && (rate < 0x90))
return 0x3;
else
return chainmask;
}
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath9k_11n_rate_series series[4];
- struct sk_buff *skb;
- struct ieee80211_tx_info *tx_info;
- struct ieee80211_tx_rate *rates;
- const struct ieee80211_rate *rate;
- struct ieee80211_hdr *hdr;
- int i, flags = 0;
- u8 rix = 0, ctsrate = 0;
- bool is_pspoll;
-
- memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
-
- skb = bf->bf_mpdu;
- tx_info = IEEE80211_SKB_CB(skb);
- rates = tx_info->control.rates;
- hdr = (struct ieee80211_hdr *)skb->data;
- is_pspoll = ieee80211_is_pspoll(hdr->frame_control);
-
- /*
- * We check if Short Preamble is needed for the CTS rate by
- * checking the BSS's global flag.
- * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
- */
- rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
- ctsrate = rate->hw_value;
- if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
- ctsrate |= rate->hw_value_short;
-
- for (i = 0; i < 4; i++) {
- bool is_40, is_sgi, is_sp;
- int phy;
-
- if (!rates[i].count || (rates[i].idx < 0))
- continue;
-
- rix = rates[i].idx;
- series[i].Tries = rates[i].count;
-
- if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
- series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
- flags |= ATH9K_TXDESC_RTSENA;
- } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
- series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
- flags |= ATH9K_TXDESC_CTSENA;
- }
-
- if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- series[i].RateFlags |= ATH9K_RATESERIES_2040;
- if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
- series[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
-
- is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
- is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
- is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
-
- if (rates[i].flags & IEEE80211_TX_RC_MCS) {
- /* MCS rates */
- series[i].Rate = rix | 0x80;
- series[i].ChSel = ath_txchainmask_reduction(sc,
- common->tx_chainmask, series[i].Rate);
- series[i].PktDuration = ath_pkt_duration(sc, rix, len,
- is_40, is_sgi, is_sp);
- if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
- series[i].RateFlags |= ATH9K_RATESERIES_STBC;
- continue;
- }
-
- /* legacy rates */
- if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
- !(rate->flags & IEEE80211_RATE_ERP_G))
- phy = WLAN_RC_PHY_CCK;
- else
- phy = WLAN_RC_PHY_OFDM;
-
- rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
- series[i].Rate = rate->hw_value;
- if (rate->hw_value_short) {
- if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
- series[i].Rate |= rate->hw_value_short;
- } else {
- is_sp = false;
- }
-
- if (bf->bf_state.bfs_paprd)
- series[i].ChSel = common->tx_chainmask;
- else
- series[i].ChSel = ath_txchainmask_reduction(sc,
- common->tx_chainmask, series[i].Rate);
-
- series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
- phy, rate->bitrate * 100, len, rix, is_sp);
- }
-
- /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
- if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
- flags &= ~ATH9K_TXDESC_RTSENA;
-
- /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
- if (flags & ATH9K_TXDESC_RTSENA)
- flags &= ~ATH9K_TXDESC_CTSENA;
-
- /* set dur_update_en for l-sig computation except for PS-Poll frames */
- ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
- bf->bf_lastbf->bf_desc,
- !is_pspoll, ctsrate,
- 0, series, 4, flags);
-
-}
-
-static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
+/*
+ * Assign a descriptor (and sequence number if necessary,
+ * and map buffer for DMA. Frees skb on error
+ */
+static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
struct ath_txq *txq,
+ struct ath_atx_tid *tid,
struct sk_buff *skb)
{
- struct ath_softc *sc = hw->priv;
- struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_frame_info *fi = get_frame_info(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_buf *bf;
- struct ath_desc *ds;
- int frm_type;
+ u16 seqno;
bf = ath_tx_get_buffer(sc);
if (!bf) {
ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n");
- return NULL;
+ goto error;
}
ATH_TXBUF_RESET(bf);
- bf->bf_flags = setup_tx_flags(skb);
+ if (tid) {
+ seqno = tid->seq_next;
+ hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
+ INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+ bf->bf_state.seqno = seqno;
+ }
+
bf->bf_mpdu = skb;
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
@@ -1723,38 +1794,26 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
ath_err(ath9k_hw_common(sc->sc_ah),
"dma_mapping_error() on TX\n");
ath_tx_return_buffer(sc, bf);
- return NULL;
+ goto error;
}
- frm_type = get_hw_packet_type(skb);
-
- ds = bf->bf_desc;
- ath9k_hw_set_desc_link(ah, ds, 0);
-
- ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER,
- fi->keyix, fi->keytype, bf->bf_flags);
-
- ath9k_hw_filltxdesc(ah, ds,
- skb->len, /* segment length */
- true, /* first segment */
- true, /* last segment */
- ds, /* first descriptor */
- bf->bf_buf_addr,
- txq->axq_qnum);
-
+ fi->bf = bf;
return bf;
+
+error:
+ dev_kfree_skb_any(skb);
+ return NULL;
}
/* FIXME: tx power */
-static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
+static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
struct ath_tx_control *txctl)
{
- struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct list_head bf_head;
struct ath_atx_tid *tid = NULL;
+ struct ath_buf *bf;
u8 tidno;
spin_lock_bh(&txctl->txq->axq_lock);
@@ -1772,27 +1831,21 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
* Try aggregation if it's a unicast data frame
* and the destination is HT capable.
*/
- ath_tx_send_ampdu(sc, tid, bf, txctl);
+ ath_tx_send_ampdu(sc, tid, skb, txctl);
} else {
- INIT_LIST_HEAD(&bf_head);
- list_add_tail(&bf->list, &bf_head);
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (!bf)
+ goto out;
- bf->bf_state.bfs_ftype = txctl->frame_type;
bf->bf_state.bfs_paprd = txctl->paprd;
- if (bf->bf_state.bfs_paprd)
- ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc,
- bf->bf_state.bfs_paprd);
-
if (txctl->paprd)
bf->bf_state.bfs_paprd_timestamp = jiffies;
- if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
-
- ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
+ ath_tx_send_normal(sc, txctl->txq, tid, skb);
}
+out:
spin_unlock_bh(&txctl->txq->axq_lock);
}
@@ -1806,7 +1859,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
- struct ath_buf *bf;
int padpos, padsize;
int frmlen = skb->len + FCS_LEN;
int q;
@@ -1839,6 +1891,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
skb_push(skb, padsize);
memmove(skb->data, skb->data + padsize, padpos);
+ hdr = (struct ieee80211_hdr *) skb->data;
}
if ((vif && vif->type != NL80211_IFTYPE_AP &&
@@ -1853,10 +1906,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
* info are no longer valid (overwritten by the ath_frame_info data.
*/
- bf = ath_tx_setup_buffer(hw, txctl->txq, skb);
- if (unlikely(!bf))
- return -ENOMEM;
-
q = skb_get_queue_mapping(skb);
spin_lock_bh(&txq->axq_lock);
if (txq == sc->tx.txq_map[q] &&
@@ -1866,8 +1915,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
}
spin_unlock_bh(&txq->axq_lock);
- ath_tx_start_dma(sc, bf, txctl);
-
+ ath_tx_start_dma(sc, skb, txctl);
return 0;
}
@@ -1876,7 +1924,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
/*****************/
static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
- int tx_flags, int ftype, struct ath_txq *txq)
+ int tx_flags, struct ath_txq *txq)
{
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1889,10 +1937,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
if (tx_flags & ATH_TX_BAR)
tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
- if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
+ if (!(tx_flags & ATH_TX_ERROR))
/* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK;
- }
padpos = ath9k_cmn_padpos(hdr->frame_control);
padsize = padpos & 3;
@@ -1936,18 +1983,18 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int txok, int sendbar)
{
struct sk_buff *skb = bf->bf_mpdu;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
unsigned long flags;
int tx_flags = 0;
if (sendbar)
tx_flags = ATH_TX_BAR;
- if (!txok) {
+ if (!txok)
tx_flags |= ATH_TX_ERROR;
- if (bf_isxretried(bf))
- tx_flags |= ATH_TX_XRETRY;
- }
+ if (ts->ts_status & ATH9K_TXERR_FILT)
+ tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
bf->bf_buf_addr = 0;
@@ -1960,9 +2007,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
else
complete(&sc->paprd_complete);
} else {
- ath_debug_stat_tx(sc, bf, ts, txq);
- ath_tx_complete(sc, skb, tx_flags,
- bf->bf_state.bfs_ftype, txq);
+ ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
+ ath_tx_complete(sc, skb, tx_flags, txq);
}
/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
* accidentally reference it later.
@@ -1979,7 +2025,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int nframes, int nbad,
- int txok, bool update_rc)
+ int txok)
{
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -1994,19 +2040,16 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
tx_rateindex = ts->ts_rateindex;
WARN_ON(tx_rateindex >= hw->max_rates);
- if (ts->ts_status & ATH9K_TXERR_FILT)
- tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
BUG_ON(nbad > nframes);
-
- tx_info->status.ampdu_len = nframes;
- tx_info->status.ampdu_ack_len = nframes - nbad;
}
+ tx_info->status.ampdu_len = nframes;
+ tx_info->status.ampdu_ack_len = nframes - nbad;
if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
- (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
+ (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
/*
* If an underrun error is seen assume it as an excessive
* retry only if max frame trigger level has been reached
@@ -2019,9 +2062,9 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
* successfully by eventually preferring slower rates.
* This itself should also alleviate congestion on the bus.
*/
- if (ieee80211_is_data(hdr->frame_control) &&
- (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
- ATH9K_TX_DELIM_UNDERRUN)) &&
+ if (unlikely(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
+ ATH9K_TX_DELIM_UNDERRUN)) &&
+ ieee80211_is_data(hdr->frame_control) &&
ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)
tx_info->status.rates[tx_rateindex].count =
hw->max_rate_tries;
@@ -2052,13 +2095,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
spin_unlock_bh(&txq->axq_lock);
if (!bf_isampdu(bf)) {
- /*
- * This frame is sent out as a single frame.
- * Use hardware retry status for this frame.
- */
- if (ts->ts_status & ATH9K_TXERR_XRETRY)
- bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true);
+ ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
} else
ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
@@ -2085,6 +2122,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
spin_lock_bh(&txq->axq_lock);
for (;;) {
+ if (work_pending(&sc->hw_reset_work))
+ break;
+
if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL;
if (sc->sc_flags & SC_OP_TXAGGR)
@@ -2172,9 +2212,8 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
if (needreset) {
ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
"tx hung, resetting the chip\n");
- spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock_bh(&sc->sc_pcu_lock);
+ RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2207,6 +2246,9 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
int status;
for (;;) {
+ if (work_pending(&sc->hw_reset_work))
+ break;
+
status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
if (status == -EINPROGRESS)
break;
@@ -2361,7 +2403,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
tid->sched = false;
tid->paused = false;
tid->state &= ~AGGR_CLEANUP;
- INIT_LIST_HEAD(&tid->buf_q);
+ __skb_queue_head_init(&tid->buf_q);
acno = TID_TO_WME_AC(tidno);
tid->ac = &an->ac[acno];
tid->state &= ~AGGR_ADDBA_COMPLETE;
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig
index 2d1b821b440d..267d5dcf82dc 100644
--- a/drivers/net/wireless/ath/carl9170/Kconfig
+++ b/drivers/net/wireless/ath/carl9170/Kconfig
@@ -39,3 +39,17 @@ config CARL9170_WPC
bool
depends on CARL9170 && (INPUT = y || INPUT = CARL9170)
default y
+
+config CARL9170_HWRNG
+ bool "Random number generator"
+ depends on CARL9170 && (HW_RANDOM = y || HW_RANDOM = CARL9170)
+ default n
+ help
+ Provides a hardware random number generator to the kernel.
+
+ SECURITY WARNING: It's relatively easy to eavesdrop all
+ generated random numbers from the transport stream with
+ usbmon [software] or special usb sniffer hardware.
+
+ Say N, unless your setup[i.e.: embedded system] has no
+ other rng source and you can afford to take the risk.
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index c5427a72a1e2..6cfbb419e2f6 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -43,6 +43,7 @@
#include <linux/firmware.h>
#include <linux/completion.h>
#include <linux/spinlock.h>
+#include <linux/hw_random.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <linux/usb.h>
@@ -151,6 +152,7 @@ struct carl9170_sta_tid {
#define CARL9170_TX_TIMEOUT 2500
#define CARL9170_JANITOR_DELAY 128
#define CARL9170_QUEUE_STUCK_TIMEOUT 5500
+#define CARL9170_STAT_WORK 30000
#define CARL9170_NUM_TX_AGG_MAX 30
@@ -282,6 +284,7 @@ struct ar9170 {
bool rx_stream;
bool tx_stream;
bool rx_filter;
+ bool hw_counters;
unsigned int mem_blocks;
unsigned int mem_block_size;
unsigned int rx_size;
@@ -331,11 +334,21 @@ struct ar9170 {
/* PHY */
struct ieee80211_channel *channel;
+ unsigned int num_channels;
int noise[4];
unsigned int chan_fail;
unsigned int total_chan_fail;
u8 heavy_clip;
u8 ht_settings;
+ struct {
+ u64 active; /* usec */
+ u64 cca; /* usec */
+ u64 tx_time; /* usec */
+ u64 rx_total;
+ u64 rx_overrun;
+ } tally;
+ struct delayed_work stat_work;
+ struct survey_info *survey;
/* power calibration data */
u8 power_5G_leg[4];
@@ -437,6 +450,17 @@ struct ar9170 {
unsigned int off_override;
bool state;
} ps;
+
+#ifdef CONFIG_CARL9170_HWRNG
+# define CARL9170_HWRNG_CACHE_SIZE CARL9170_MAX_CMD_PAYLOAD_LEN
+ struct {
+ struct hwrng rng;
+ bool initialized;
+ char name[30 + 1];
+ u16 cache[CARL9170_HWRNG_CACHE_SIZE / sizeof(u16)];
+ unsigned int cache_idx;
+ } rng;
+#endif /* CONFIG_CARL9170_HWRNG */
};
enum carl9170_ps_off_override_reasons {
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c
index cdfc94c371b4..195dc6538110 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.c
+++ b/drivers/net/wireless/ath/carl9170/cmd.c
@@ -36,6 +36,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <asm/div64.h>
#include "carl9170.h"
#include "cmd.h"
@@ -165,6 +166,39 @@ int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
return __carl9170_exec_cmd(ar, cmd, true);
}
+int carl9170_collect_tally(struct ar9170 *ar)
+{
+ struct carl9170_tally_rsp tally;
+ struct survey_info *info;
+ unsigned int tick;
+ int err;
+
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_TALLY, 0, NULL,
+ sizeof(tally), (u8 *)&tally);
+ if (err)
+ return err;
+
+ tick = le32_to_cpu(tally.tick);
+ if (tick) {
+ ar->tally.active += le32_to_cpu(tally.active) / tick;
+ ar->tally.cca += le32_to_cpu(tally.cca) / tick;
+ ar->tally.tx_time += le32_to_cpu(tally.tx_time) / tick;
+ ar->tally.rx_total += le32_to_cpu(tally.rx_total);
+ ar->tally.rx_overrun += le32_to_cpu(tally.rx_overrun);
+
+ if (ar->channel) {
+ info = &ar->survey[ar->channel->hw_value];
+ info->channel_time = ar->tally.active;
+ info->channel_time_busy = ar->tally.cca;
+ info->channel_time_tx = ar->tally.tx_time;
+ do_div(info->channel_time, 1000);
+ do_div(info->channel_time_busy, 1000);
+ do_div(info->channel_time_tx, 1000);
+ }
+ }
+ return 0;
+}
+
int carl9170_powersave(struct ar9170 *ar, const bool ps)
{
struct carl9170_cmd *cmd;
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h
index d5f95bdc75c1..885c42778b8b 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.h
+++ b/drivers/net/wireless/ath/carl9170/cmd.h
@@ -50,6 +50,7 @@ int carl9170_echo_test(struct ar9170 *ar, u32 v);
int carl9170_reboot(struct ar9170 *ar);
int carl9170_mac_reset(struct ar9170 *ar);
int carl9170_powersave(struct ar9170 *ar, const bool power_on);
+int carl9170_collect_tally(struct ar9170 *ar);
int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
const u32 mode, const u32 addr, const u32 len);
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 39ddea5794f7..f4cae1cccbff 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -266,6 +266,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
FIF_PROMISC_IN_BSS;
}
+ if (SUPP(CARL9170FW_HW_COUNTERS))
+ ar->fw.hw_counters = true;
+
if (SUPP(CARL9170FW_WOL))
device_set_wakeup_enable(&ar->udev->dev, true);
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
index 0a6dec529b59..9443c802b25b 100644
--- a/drivers/net/wireless/ath/carl9170/fwcmd.h
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -55,6 +55,7 @@ enum carl9170_cmd_oids {
CARL9170_CMD_READ_TSF = 0x06,
CARL9170_CMD_RX_FILTER = 0x07,
CARL9170_CMD_WOL = 0x08,
+ CARL9170_CMD_TALLY = 0x09,
/* CAM */
CARL9170_CMD_EKEY = 0x10,
@@ -286,6 +287,15 @@ struct carl9170_tsf_rsp {
} __packed;
#define CARL9170_TSF_RSP_SIZE 8
+struct carl9170_tally_rsp {
+ __le32 active;
+ __le32 cca;
+ __le32 tx_time;
+ __le32 rx_total;
+ __le32 rx_overrun;
+ __le32 tick;
+} __packed;
+
struct carl9170_rsp {
struct carl9170_cmd_head hdr;
@@ -300,6 +310,7 @@ struct carl9170_rsp {
struct carl9170_gpio gpio;
struct carl9170_tsf_rsp tsf;
struct carl9170_psm psm;
+ struct carl9170_tally_rsp tally;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed;
} __packed __aligned(4);
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 0474e6638d21..f06e0695d412 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -413,6 +413,9 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED);
+ ieee80211_queue_delayed_work(ar->hw, &ar->stat_work,
+ round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
+
ieee80211_wake_queues(ar->hw);
err = 0;
@@ -423,6 +426,7 @@ out:
static void carl9170_cancel_worker(struct ar9170 *ar)
{
+ cancel_delayed_work_sync(&ar->stat_work);
cancel_delayed_work_sync(&ar->tx_janitor);
#ifdef CONFIG_CARL9170_LEDS
cancel_delayed_work_sync(&ar->led_work);
@@ -794,6 +798,43 @@ static void carl9170_ps_work(struct work_struct *work)
mutex_unlock(&ar->mutex);
}
+static int carl9170_update_survey(struct ar9170 *ar, bool flush, bool noise)
+{
+ int err;
+
+ if (noise) {
+ err = carl9170_get_noisefloor(ar);
+ if (err)
+ return err;
+ }
+
+ if (ar->fw.hw_counters) {
+ err = carl9170_collect_tally(ar);
+ if (err)
+ return err;
+ }
+
+ if (flush)
+ memset(&ar->tally, 0, sizeof(ar->tally));
+
+ return 0;
+}
+
+static void carl9170_stat_work(struct work_struct *work)
+{
+ struct ar9170 *ar = container_of(work, struct ar9170, stat_work.work);
+ int err;
+
+ mutex_lock(&ar->mutex);
+ err = carl9170_update_survey(ar, false, true);
+ mutex_unlock(&ar->mutex);
+
+ if (err)
+ return;
+
+ ieee80211_queue_delayed_work(ar->hw, &ar->stat_work,
+ round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
+}
static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
{
@@ -828,11 +869,19 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
if (err)
goto out;
+ err = carl9170_update_survey(ar, true, false);
+ if (err)
+ goto out;
+
err = carl9170_set_channel(ar, hw->conf.channel,
hw->conf.channel_type, CARL9170_RFI_NONE);
if (err)
goto out;
+ err = carl9170_update_survey(ar, false, true);
+ if (err)
+ goto out;
+
err = carl9170_set_dyn_sifs_ack(ar);
if (err)
goto out;
@@ -1029,7 +1078,8 @@ out:
mutex_unlock(&ar->mutex);
}
-static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw)
+static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct ar9170 *ar = hw->priv;
struct carl9170_tsf_rsp tsf;
@@ -1255,7 +1305,8 @@ static int carl9170_op_sta_remove(struct ieee80211_hw *hw,
return 0;
}
-static int carl9170_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int carl9170_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *param)
{
struct ar9170 *ar = hw->priv;
@@ -1421,24 +1472,159 @@ static int carl9170_register_wps_button(struct ar9170 *ar)
}
#endif /* CONFIG_CARL9170_WPC */
-static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
- struct survey_info *survey)
+#ifdef CONFIG_CARL9170_HWRNG
+static int carl9170_rng_get(struct ar9170 *ar)
{
- struct ar9170 *ar = hw->priv;
+
+#define RW (CARL9170_MAX_CMD_PAYLOAD_LEN / sizeof(u32))
+#define RB (CARL9170_MAX_CMD_PAYLOAD_LEN)
+
+ static const __le32 rng_load[RW] = {
+ [0 ... (RW - 1)] = cpu_to_le32(AR9170_RAND_REG_NUM)};
+
+ u32 buf[RW];
+
+ unsigned int i, off = 0, transfer, count;
int err;
- if (idx != 0)
- return -ENOENT;
+ BUILD_BUG_ON(RB > CARL9170_MAX_CMD_PAYLOAD_LEN);
+
+ if (!IS_ACCEPTING_CMD(ar) || !ar->rng.initialized)
+ return -EAGAIN;
+
+ count = ARRAY_SIZE(ar->rng.cache);
+ while (count) {
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
+ RB, (u8 *) rng_load,
+ RB, (u8 *) buf);
+ if (err)
+ return err;
+
+ transfer = min_t(unsigned int, count, RW);
+ for (i = 0; i < transfer; i++)
+ ar->rng.cache[off + i] = buf[i];
+
+ off += transfer;
+ count -= transfer;
+ }
+
+ ar->rng.cache_idx = 0;
+
+#undef RW
+#undef RB
+ return 0;
+}
+
+static int carl9170_rng_read(struct hwrng *rng, u32 *data)
+{
+ struct ar9170 *ar = (struct ar9170 *)rng->priv;
+ int ret = -EIO;
mutex_lock(&ar->mutex);
- err = carl9170_get_noisefloor(ar);
+ if (ar->rng.cache_idx >= ARRAY_SIZE(ar->rng.cache)) {
+ ret = carl9170_rng_get(ar);
+ if (ret) {
+ mutex_unlock(&ar->mutex);
+ return ret;
+ }
+ }
+
+ *data = ar->rng.cache[ar->rng.cache_idx++];
mutex_unlock(&ar->mutex);
- if (err)
+
+ return sizeof(u16);
+}
+
+static void carl9170_unregister_hwrng(struct ar9170 *ar)
+{
+ if (ar->rng.initialized) {
+ hwrng_unregister(&ar->rng.rng);
+ ar->rng.initialized = false;
+ }
+}
+
+static int carl9170_register_hwrng(struct ar9170 *ar)
+{
+ int err;
+
+ snprintf(ar->rng.name, ARRAY_SIZE(ar->rng.name),
+ "%s_%s", KBUILD_MODNAME, wiphy_name(ar->hw->wiphy));
+ ar->rng.rng.name = ar->rng.name;
+ ar->rng.rng.data_read = carl9170_rng_read;
+ ar->rng.rng.priv = (unsigned long)ar;
+
+ if (WARN_ON(ar->rng.initialized))
+ return -EALREADY;
+
+ err = hwrng_register(&ar->rng.rng);
+ if (err) {
+ dev_err(&ar->udev->dev, "Failed to register the random "
+ "number generator (%d)\n", err);
return err;
+ }
+
+ ar->rng.initialized = true;
+
+ err = carl9170_rng_get(ar);
+ if (err) {
+ carl9170_unregister_hwrng(ar);
+ return err;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_CARL9170_HWRNG */
+
+static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct ar9170 *ar = hw->priv;
+ struct ieee80211_channel *chan;
+ struct ieee80211_supported_band *band;
+ int err, b, i;
- survey->channel = ar->channel;
+ chan = ar->channel;
+ if (!chan)
+ return -ENODEV;
+
+ if (idx == chan->hw_value) {
+ mutex_lock(&ar->mutex);
+ err = carl9170_update_survey(ar, false, true);
+ mutex_unlock(&ar->mutex);
+ if (err)
+ return err;
+ }
+
+ for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
+ band = ar->hw->wiphy->bands[b];
+
+ if (!band)
+ continue;
+
+ for (i = 0; i < band->n_channels; i++) {
+ if (band->channels[i].hw_value == idx) {
+ chan = &band->channels[i];
+ goto found;
+ }
+ }
+ }
+ return -ENOENT;
+
+found:
+ memcpy(survey, &ar->survey[idx], sizeof(*survey));
+
+ survey->channel = chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
- survey->noise = ar->noise[0];
+
+ if (ar->channel == chan)
+ survey->filled |= SURVEY_INFO_IN_USE;
+
+ if (ar->fw.hw_counters) {
+ survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ }
+
return 0;
}
@@ -1571,6 +1757,7 @@ void *carl9170_alloc(size_t priv_size)
INIT_WORK(&ar->ping_work, carl9170_ping_work);
INIT_WORK(&ar->restart_work, carl9170_restart_work);
INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
+ INIT_DELAYED_WORK(&ar->stat_work, carl9170_stat_work);
INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
INIT_LIST_HEAD(&ar->tx_ampdu_list);
rcu_assign_pointer(ar->tx_ampdu_iter,
@@ -1654,6 +1841,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
struct ath_regulatory *regulatory = &ar->common.regulatory;
unsigned int rx_streams, tx_streams, tx_params = 0;
int bands = 0;
+ int chans = 0;
if (ar->eeprom.length == cpu_to_le16(0xffff))
return -ENODATA;
@@ -1677,14 +1865,24 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&carl9170_band_2GHz;
+ chans += carl9170_band_2GHz.n_channels;
bands++;
}
if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&carl9170_band_5GHz;
+ chans += carl9170_band_5GHz.n_channels;
bands++;
}
+ if (!bands)
+ return -EINVAL;
+
+ ar->survey = kzalloc(sizeof(struct survey_info) * chans, GFP_KERNEL);
+ if (!ar->survey)
+ return -ENOMEM;
+ ar->num_channels = chans;
+
/*
* I measured this, a bandswitch takes roughly
* 135 ms and a frequency switch about 80.
@@ -1698,12 +1896,11 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
ar->hw->channel_change_time = 80 * 1000;
regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
- regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
/* second part of wiphy init */
SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address);
- return bands ? 0 : -EINVAL;
+ return 0;
}
static int carl9170_reg_notifier(struct wiphy *wiphy,
@@ -1787,6 +1984,12 @@ int carl9170_register(struct ar9170 *ar)
goto err_unreg;
#endif /* CONFIG_CARL9170_WPC */
+#ifdef CONFIG_CARL9170_HWRNG
+ err = carl9170_register_hwrng(ar);
+ if (err)
+ goto err_unreg;
+#endif /* CONFIG_CARL9170_HWRNG */
+
dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n",
wiphy_name(ar->hw->wiphy));
@@ -1819,6 +2022,10 @@ void carl9170_unregister(struct ar9170 *ar)
}
#endif /* CONFIG_CARL9170_WPC */
+#ifdef CONFIG_CARL9170_HWRNG
+ carl9170_unregister_hwrng(ar);
+#endif /* CONFIG_CARL9170_HWRNG */
+
carl9170_cancel_worker(ar);
cancel_work_sync(&ar->restart_work);
@@ -1836,6 +2043,9 @@ void carl9170_free(struct ar9170 *ar)
kfree(ar->mem_bitmap);
ar->mem_bitmap = NULL;
+ kfree(ar->survey);
+ ar->survey = NULL;
+
mutex_destroy(&ar->mutex);
ieee80211_free_hw(ar->hw);
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index aa147a9120b6..472efc7e3402 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -578,11 +578,10 @@ static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
if (err)
return err;
- /* XXX: remove magic! */
- if (is_2ghz)
- err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5163);
- else
- err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5143);
+ if (!ar->fw.hw_counters) {
+ err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC,
+ is_2ghz ? 0x5163 : 0x5143);
+ }
return err;
}
@@ -1574,6 +1573,9 @@ int carl9170_get_noisefloor(struct ar9170 *ar)
AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8);
}
+ if (ar->channel)
+ ar->survey[ar->channel->hw_value].noise = ar->noise[0];
+
return 0;
}
@@ -1766,10 +1768,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
ar->chan_fail = 0;
}
- err = carl9170_get_noisefloor(ar);
- if (err)
- return err;
-
if (ar->heavy_clip) {
err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE,
0x200 | ar->heavy_clip);
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index 64703778cfea..e651db856344 100644
--- a/drivers/net/wireless/ath/carl9170/version.h
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -1,7 +1,7 @@
#ifndef __CARL9170_SHARED_VERSION_H
#define __CARL9170_SHARED_VERSION_H
#define CARL9170FW_VERSION_YEAR 11
-#define CARL9170FW_VERSION_MONTH 6
-#define CARL9170FW_VERSION_DAY 30
+#define CARL9170FW_VERSION_MONTH 8
+#define CARL9170FW_VERSION_DAY 15
#define CARL9170FW_VERSION_GIT "1.9.4"
#endif /* __CARL9170_SHARED_VERSION_H */
diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c
index c325202fdc5f..d9218fe02036 100644
--- a/drivers/net/wireless/ath/main.c
+++ b/drivers/net/wireless/ath/main.c
@@ -57,22 +57,18 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
}
EXPORT_SYMBOL(ath_rxbuf_alloc);
-int ath_printk(const char *level, struct ath_common *common,
- const char *fmt, ...)
+void ath_printk(const char *level, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
- int rtn;
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
- rtn = printk("%sath: %pV", level, &vaf);
+ printk("%sath: %pV", level, &vaf);
va_end(args);
-
- return rtn;
}
EXPORT_SYMBOL(ath_printk);
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h
index 172f63f671cf..03a8268ccf21 100644
--- a/drivers/net/wireless/ath/regd.h
+++ b/drivers/net/wireless/ath/regd.h
@@ -101,7 +101,7 @@ enum CountryCode {
CTRY_GERMANY = 276,
CTRY_GREECE = 300,
CTRY_GREENLAND = 304,
- CTRY_GRENEDA = 308,
+ CTRY_GRENADA = 308,
CTRY_GUAM = 316,
CTRY_GUATEMALA = 320,
CTRY_HAITI = 332,
diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h
index 24b53839fc3a..bdd2b4d61f2f 100644
--- a/drivers/net/wireless/ath/regd_common.h
+++ b/drivers/net/wireless/ath/regd_common.h
@@ -332,7 +332,7 @@ static struct country_code_to_enum_rd allCountries[] = {
{CTRY_GERMANY, ETSI1_WORLD, "DE"},
{CTRY_GREECE, ETSI1_WORLD, "GR"},
{CTRY_GREENLAND, ETSI1_WORLD, "GL"},
- {CTRY_GRENEDA, FCC3_FCCA, "GD"},
+ {CTRY_GRENADA, FCC3_FCCA, "GD"},
{CTRY_GUAM, FCC1_FCCA, "GU"},
{CTRY_GUATEMALA, FCC1_FCCA, "GT"},
{CTRY_HAITI, ETSI1_WORLD, "HT"},
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 3cab843afb05..b97a40ed5fff 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -114,22 +114,22 @@ config B43_PHY_N
affect other devices support and may provide support for basic needs.
config B43_PHY_LP
- bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)"
- depends on B43 && EXPERIMENTAL
+ bool "Support for low-power (LP-PHY) devices"
+ depends on B43
default y
---help---
Support for the LP-PHY.
The LP-PHY is a low-power PHY built into some notebooks
- and embedded devices. It supports 802.11a/g
+ and embedded devices. It supports 802.11a/b/g
(802.11a support is optional, and currently disabled).
config B43_PHY_HT
- bool "Support for HT-PHY devices (BROKEN)"
- depends on B43 && BROKEN
+ bool "Support for HT-PHY (high throughput) devices (EXPERIMENTAL)"
+ depends on B43 && EXPERIMENTAL
---help---
Support for the HT-PHY.
- Say N, this is BROKEN and crashes driver.
+ Enables support for BCM4331 and possibly other chipsets with that PHY.
config B43_PHY_LCN
bool "Support for LCN-PHY devices (BROKEN)"
@@ -169,13 +169,3 @@ config B43_DEBUG
Say N, if you are a distributor or user building a release kernel
for production use.
Only say Y, if you are debugging a problem in the b43 driver sourcecode.
-
-config B43_FORCE_PIO
- bool "Force usage of PIO instead of DMA"
- depends on B43 && B43_DEBUG
- ---help---
- This will disable DMA and always enable PIO instead.
-
- Say N!
- This is only for debugging the PIO engine code. You do
- _NOT_ want to enable this.
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index c818b0bc88ec..37110dfd2c96 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -17,11 +17,6 @@
#include "phy_common.h"
-/* The unique identifier of the firmware that's officially supported by
- * this driver version. */
-#define B43_SUPPORTED_FIRMWARE_ID "FW13"
-
-
#ifdef CONFIG_B43_DEBUG
# define B43_DEBUG 1
#else
@@ -112,21 +107,61 @@
#define B43_MMIO_RADIO_HWENABLED_LO 0x49A
#define B43_MMIO_GPIO_CONTROL 0x49C
#define B43_MMIO_GPIO_MASK 0x49E
+#define B43_MMIO_TXE0_CTL 0x500
+#define B43_MMIO_TXE0_AUX 0x502
+#define B43_MMIO_TXE0_TS_LOC 0x504
+#define B43_MMIO_TXE0_TIME_OUT 0x506
+#define B43_MMIO_TXE0_WM_0 0x508
+#define B43_MMIO_TXE0_WM_1 0x50A
+#define B43_MMIO_TXE0_PHYCTL 0x50C
+#define B43_MMIO_TXE0_STATUS 0x50E
+#define B43_MMIO_TXE0_MMPLCP0 0x510
+#define B43_MMIO_TXE0_MMPLCP1 0x512
+#define B43_MMIO_TXE0_PHYCTL1 0x514
+#define B43_MMIO_XMTFIFODEF 0x520
+#define B43_MMIO_XMTFIFO_FRAME_CNT 0x522 /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_BYTE_CNT 0x524 /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_HEAD 0x526 /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_RD_PTR 0x528 /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_WR_PTR 0x52A /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFODEF1 0x52C /* core rev>= 16 only */
+#define B43_MMIO_XMTFIFOCMD 0x540
+#define B43_MMIO_XMTFIFOFLUSH 0x542
+#define B43_MMIO_XMTFIFOTHRESH 0x544
+#define B43_MMIO_XMTFIFORDY 0x546
+#define B43_MMIO_XMTFIFOPRIRDY 0x548
+#define B43_MMIO_XMTFIFORQPRI 0x54A
+#define B43_MMIO_XMTTPLATETXPTR 0x54C
+#define B43_MMIO_XMTTPLATEPTR 0x550
+#define B43_MMIO_SMPL_CLCT_STRPTR 0x552 /* core rev>= 22 only */
+#define B43_MMIO_SMPL_CLCT_STPPTR 0x554 /* core rev>= 22 only */
+#define B43_MMIO_SMPL_CLCT_CURPTR 0x556 /* core rev>= 22 only */
+#define B43_MMIO_XMTTPLATEDATALO 0x560
+#define B43_MMIO_XMTTPLATEDATAHI 0x562
+#define B43_MMIO_XMTSEL 0x568
+#define B43_MMIO_XMTTXCNT 0x56A
+#define B43_MMIO_XMTTXSHMADDR 0x56C
#define B43_MMIO_TSF_CFP_START_LOW 0x604
#define B43_MMIO_TSF_CFP_START_HIGH 0x606
#define B43_MMIO_TSF_CFP_PRETBTT 0x612
+#define B43_MMIO_TSF_CLK_FRAC_LOW 0x62E
+#define B43_MMIO_TSF_CLK_FRAC_HIGH 0x630
#define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */
#define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */
#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
#define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
#define B43_MMIO_RNG 0x65A
#define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */
-#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
+#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
+#define B43_MMIO_IFSSTAT 0x690
+#define B43_MMIO_IFSMEDBUSYCTL 0x692
+#define B43_MMIO_IFTXDUR 0x694
#define B43_MMIO_IFSCTL_USE_EDCF 0x0004
#define B43_MMIO_POWERUP_DELAY 0x6A8
#define B43_MMIO_BTCOEX_CTL 0x6B4 /* Bluetooth Coexistence Control */
#define B43_MMIO_BTCOEX_STAT 0x6B6 /* Bluetooth Coexistence Status */
#define B43_MMIO_BTCOEX_TXCTL 0x6B8 /* Bluetooth Coexistence Transmit Control */
+#define B43_MMIO_WEPCTL 0x7C0
/* SPROM boardflags_lo values */
#define B43_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */
@@ -594,6 +629,7 @@ struct b43_dma {
struct b43_dmaring *rx_ring;
u32 translation; /* Routing bits */
+ bool translation_in_low; /* Should translation bit go into low addr? */
bool parity; /* Check for parity */
};
@@ -694,6 +730,12 @@ struct b43_firmware_file {
enum b43_firmware_file_type type;
};
+enum b43_firmware_hdr_format {
+ B43_FW_HDR_598,
+ B43_FW_HDR_410,
+ B43_FW_HDR_351,
+};
+
/* Pointers to the firmware data and meta information about it. */
struct b43_firmware {
/* Microcode */
@@ -710,6 +752,9 @@ struct b43_firmware {
/* Firmware patchlevel */
u16 patch;
+ /* Format of header used by firmware */
+ enum b43_firmware_hdr_format hdr_format;
+
/* Set to true, if we are using an opensource firmware.
* Use this to check for proprietary vs opensource. */
bool opensource;
@@ -875,7 +920,7 @@ struct b43_wl {
struct b43_leds leds;
/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
- u8 pio_scratchspace[110] __attribute__((__aligned__(8)));
+ u8 pio_scratchspace[118] __attribute__((__aligned__(8)));
u8 pio_tailspace[4] __attribute__((__aligned__(8)));
};
@@ -965,21 +1010,11 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
return dev->__using_pio_transfers;
}
-#ifdef CONFIG_B43_FORCE_PIO
-# define B43_PIO_DEFAULT 1
-#else
-# define B43_PIO_DEFAULT 0
-#endif
-
/* Message printing */
-void b43info(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-void b43err(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-void b43warn(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-void b43dbg(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
+__printf(2, 3) void b43info(struct b43_wl *wl, const char *fmt, ...);
+__printf(2, 3) void b43err(struct b43_wl *wl, const char *fmt, ...);
+__printf(2, 3) void b43warn(struct b43_wl *wl, const char *fmt, ...);
+__printf(2, 3) void b43dbg(struct b43_wl *wl, const char *fmt, ...);
/* A WARN_ON variant that vanishes when b43 debugging is disabled.
diff --git a/drivers/net/wireless/b43/bus.c b/drivers/net/wireless/b43/bus.c
index 05f6c7bff6ab..424692df239d 100644
--- a/drivers/net/wireless/b43/bus.c
+++ b/drivers/net/wireless/b43/bus.c
@@ -3,6 +3,8 @@
Broadcom B43 wireless driver
Bus abstraction layer
+ Copyright (c) 2011 Rafał Miłecki <zajec5@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
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 481e534534eb..5e45604f0f5d 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -47,6 +47,38 @@
* into separate slots. */
#define TX_SLOTS_PER_FRAME 2
+static u32 b43_dma_address(struct b43_dma *dma, dma_addr_t dmaaddr,
+ enum b43_addrtype addrtype)
+{
+ u32 uninitialized_var(addr);
+
+ switch (addrtype) {
+ case B43_DMA_ADDR_LOW:
+ addr = lower_32_bits(dmaaddr);
+ if (dma->translation_in_low) {
+ addr &= ~SSB_DMA_TRANSLATION_MASK;
+ addr |= dma->translation;
+ }
+ break;
+ case B43_DMA_ADDR_HIGH:
+ addr = upper_32_bits(dmaaddr);
+ if (!dma->translation_in_low) {
+ addr &= ~SSB_DMA_TRANSLATION_MASK;
+ addr |= dma->translation;
+ }
+ break;
+ case B43_DMA_ADDR_EXT:
+ if (dma->translation_in_low)
+ addr = lower_32_bits(dmaaddr);
+ else
+ addr = upper_32_bits(dmaaddr);
+ addr &= SSB_DMA_TRANSLATION_MASK;
+ addr >>= SSB_DMA_TRANSLATION_SHIFT;
+ break;
+ }
+
+ return addr;
+}
/* 32bit DMA ops. */
static
@@ -77,10 +109,9 @@ static void op32_fill_descriptor(struct b43_dmaring *ring,
slot = (int)(&(desc->dma32) - descbase);
B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
- addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
- addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- addr |= ring->dev->dma.translation;
+ addr = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW);
+ addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT);
+
ctl = bufsize & B43_DMA32_DCTL_BYTECNT;
if (slot == ring->nr_slots - 1)
ctl |= B43_DMA32_DCTL_DTABLEEND;
@@ -170,11 +201,10 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,
slot = (int)(&(desc->dma64) - descbase);
B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
- addrlo = (u32) (dmaaddr & 0xFFFFFFFF);
- addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
- addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- addrhi |= ring->dev->dma.translation;
+ addrlo = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW);
+ addrhi = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_HIGH);
+ addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT);
+
if (slot == ring->nr_slots - 1)
ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
if (start)
@@ -389,33 +419,34 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
gfp_t flags = GFP_KERNEL;
/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
- * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing
- * has shown that 4K is sufficient for the latter as long as the buffer
- * does not cross an 8K boundary.
- *
- * For unknown reasons - possibly a hardware error - the BCM4311 rev
- * 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
- * which accounts for the GFP_DMA flag below.
- *
- * The flags here must match the flags in free_ringmemory below!
+ * alignment and 8K buffers for 64-bit DMA with 8K alignment.
+ * In practice we could use smaller buffers for the latter, but the
+ * alignment is really important because of the hardware bug. If bit
+ * 0x00001000 is used in DMA address, some hardware (like BCM4331)
+ * copies that bit into B43_DMA64_RXSTATUS and we get false values from
+ * B43_DMA64_RXSTATDPTR. Let's just use 8K buffers even if we don't use
+ * more than 256 slots for ring.
*/
- if (ring->type == B43_DMA_64BIT)
- flags |= GFP_DMA;
+ u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
+ B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
+
ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
- B43_DMA_RINGMEMSIZE,
- &(ring->dmabase), flags);
+ ring_mem_size, &(ring->dmabase),
+ flags);
if (!ring->descbase) {
b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
return -ENOMEM;
}
- memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE);
+ memset(ring->descbase, 0, ring_mem_size);
return 0;
}
static void free_ringmemory(struct b43_dmaring *ring)
{
- dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
+ u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
+ B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
+ dma_free_coherent(ring->dev->dev->dma_dev, ring_mem_size,
ring->descbase, ring->dmabase);
}
@@ -658,41 +689,37 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
int err = 0;
u32 value;
u32 addrext;
- u32 trans = ring->dev->dma.translation;
bool parity = ring->dev->dma.parity;
+ u32 addrlo;
+ u32 addrhi;
if (ring->tx) {
if (ring->type == B43_DMA_64BIT) {
u64 ringbase = (u64) (ring->dmabase);
+ addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+ addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
+ addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH);
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
value = B43_DMA64_TXENABLE;
value |= (addrext << B43_DMA64_TXADDREXT_SHIFT)
& B43_DMA64_TXADDREXT_MASK;
if (!parity)
value |= B43_DMA64_TXPARITYDISABLE;
b43_dma_write(ring, B43_DMA64_TXCTL, value);
- b43_dma_write(ring, B43_DMA64_TXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43_dma_write(ring, B43_DMA64_TXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK)
- | trans);
+ b43_dma_write(ring, B43_DMA64_TXRINGLO, addrlo);
+ b43_dma_write(ring, B43_DMA64_TXRINGHI, addrhi);
} else {
u32 ringbase = (u32) (ring->dmabase);
+ addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+ addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
value = B43_DMA32_TXENABLE;
value |= (addrext << B43_DMA32_TXADDREXT_SHIFT)
& B43_DMA32_TXADDREXT_MASK;
if (!parity)
value |= B43_DMA32_TXPARITYDISABLE;
b43_dma_write(ring, B43_DMA32_TXCTL, value);
- b43_dma_write(ring, B43_DMA32_TXRING,
- (ringbase & ~SSB_DMA_TRANSLATION_MASK)
- | trans);
+ b43_dma_write(ring, B43_DMA32_TXRING, addrlo);
}
} else {
err = alloc_initial_descbuffers(ring);
@@ -700,9 +727,10 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
goto out;
if (ring->type == B43_DMA_64BIT) {
u64 ringbase = (u64) (ring->dmabase);
+ addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+ addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
+ addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH);
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT);
value |= B43_DMA64_RXENABLE;
value |= (addrext << B43_DMA64_RXADDREXT_SHIFT)
@@ -710,19 +738,15 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
if (!parity)
value |= B43_DMA64_RXPARITYDISABLE;
b43_dma_write(ring, B43_DMA64_RXCTL, value);
- b43_dma_write(ring, B43_DMA64_RXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43_dma_write(ring, B43_DMA64_RXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK)
- | trans);
+ b43_dma_write(ring, B43_DMA64_RXRINGLO, addrlo);
+ b43_dma_write(ring, B43_DMA64_RXRINGHI, addrhi);
b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
sizeof(struct b43_dmadesc64));
} else {
u32 ringbase = (u32) (ring->dmabase);
+ addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+ addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
value = (ring->frameoffset << B43_DMA32_RXFROFF_SHIFT);
value |= B43_DMA32_RXENABLE;
value |= (addrext << B43_DMA32_RXADDREXT_SHIFT)
@@ -730,9 +754,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
if (!parity)
value |= B43_DMA32_RXPARITYDISABLE;
b43_dma_write(ring, B43_DMA32_RXCTL, value);
- b43_dma_write(ring, B43_DMA32_RXRING,
- (ringbase & ~SSB_DMA_TRANSLATION_MASK)
- | trans);
+ b43_dma_write(ring, B43_DMA32_RXRING, addrlo);
b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots *
sizeof(struct b43_dmadesc32));
}
@@ -872,8 +894,17 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
ring->current_slot = -1;
} else {
if (ring->index == 0) {
- ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE;
- ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET;
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ ring->rx_buffersize = B43_DMA0_RX_FW598_BUFSIZE;
+ ring->frameoffset = B43_DMA0_RX_FW598_FO;
+ break;
+ case B43_FW_HDR_410:
+ case B43_FW_HDR_351:
+ ring->rx_buffersize = B43_DMA0_RX_FW351_BUFSIZE;
+ ring->frameoffset = B43_DMA0_RX_FW351_FO;
+ break;
+ }
} else
B43_WARN_ON(1);
}
@@ -1066,6 +1097,25 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
return 0;
}
+/* Some hardware with 64-bit DMA seems to be bugged and looks for translation
+ * bit in low address word instead of high one.
+ */
+static bool b43_dma_translation_in_low_word(struct b43_wldev *dev,
+ enum b43_dmatype type)
+{
+ if (type != B43_DMA_64BIT)
+ return 1;
+
+#ifdef CONFIG_B43_SSB
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+ !(dev->dev->sdev->bus->host_pci->is_pcie &&
+ ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64))
+ return 1;
+#endif
+ return 0;
+}
+
int b43_dma_init(struct b43_wldev *dev)
{
struct b43_dma *dma = &dev->dma;
@@ -1091,6 +1141,7 @@ int b43_dma_init(struct b43_wldev *dev)
break;
#endif
}
+ dma->translation_in_low = b43_dma_translation_in_low_word(dev, type);
dma->parity = true;
#ifdef CONFIG_B43_BCMA
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index cdf87094efe8..315b96ed1d90 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -161,13 +161,17 @@ struct b43_dmadesc_generic {
} __packed;
/* Misc DMA constants */
-#define B43_DMA_RINGMEMSIZE PAGE_SIZE
-#define B43_DMA0_RX_FRAMEOFFSET 30
+#define B43_DMA32_RINGMEMSIZE 4096
+#define B43_DMA64_RINGMEMSIZE 8192
+/* Offset of frame with actual data */
+#define B43_DMA0_RX_FW598_FO 38
+#define B43_DMA0_RX_FW351_FO 30
/* DMA engine tuning knobs */
#define B43_TXRING_SLOTS 256
#define B43_RXRING_SLOTS 64
-#define B43_DMA0_RX_BUFFERSIZE (B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN)
+#define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
+#define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
/* Pointer poison */
#define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM))
@@ -212,6 +216,12 @@ enum b43_dmatype {
B43_DMA_64BIT = 64,
};
+enum b43_addrtype {
+ B43_DMA_ADDR_LOW,
+ B43_DMA_ADDR_HIGH,
+ B43_DMA_ADDR_EXT,
+};
+
struct b43_dmaring {
/* Lowlevel DMA ops. */
const struct b43_dma_ops *ops;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index e293a7921bf0..7cf4125a1624 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -7,6 +7,7 @@
Copyright (c) 2005-2009 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+ Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
SDIO support
Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es>
@@ -37,7 +38,6 @@
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/firmware.h>
-#include <linux/wireless.h>
#include <linux/workqueue.h>
#include <linux/skbuff.h>
#include <linux/io.h>
@@ -65,9 +65,9 @@ MODULE_AUTHOR("Martin Langer");
MODULE_AUTHOR("Stefano Brivio");
MODULE_AUTHOR("Michael Buesch");
MODULE_AUTHOR("Gábor Stefanik");
+MODULE_AUTHOR("Rafał Miłecki");
MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID);
MODULE_FIRMWARE("b43/ucode11.fw");
MODULE_FIRMWARE("b43/ucode13.fw");
MODULE_FIRMWARE("b43/ucode14.fw");
@@ -109,12 +109,13 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT;
module_param_named(verbose, b43_modparam_verbose, int, 0644);
MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug");
-static int b43_modparam_pio = B43_PIO_DEFAULT;
+static int b43_modparam_pio = 0;
module_param_named(pio, b43_modparam_pio, int, 0644);
MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
#ifdef CONFIG_B43_BCMA
static const struct bcma_device_id b43_bcma_tbl[] = {
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
@@ -320,6 +321,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev);
static int b43_wireless_core_init(struct b43_wldev *dev);
static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
static int b43_wireless_core_start(struct b43_wldev *dev);
+static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *conf,
+ u32 changed);
static int b43_ratelimit(struct b43_wl *wl)
{
@@ -724,52 +729,59 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
for (i = 0; i < 5; i++)
b43_ram_write(dev, i * 4, buffer[i]);
- b43_write16(dev, 0x0568, 0x0000);
+ b43_write16(dev, B43_MMIO_XMTSEL, 0x0000);
+
if (dev->dev->core_rev < 11)
- b43_write16(dev, 0x07C0, 0x0000);
+ b43_write16(dev, B43_MMIO_WEPCTL, 0x0000);
else
- b43_write16(dev, 0x07C0, 0x0100);
+ b43_write16(dev, B43_MMIO_WEPCTL, 0x0100);
+
value = (ofdm ? 0x41 : 0x40);
- b43_write16(dev, 0x050C, value);
- if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP))
- b43_write16(dev, 0x0514, 0x1A02);
- b43_write16(dev, 0x0508, 0x0000);
- b43_write16(dev, 0x050A, 0x0000);
- b43_write16(dev, 0x054C, 0x0000);
- b43_write16(dev, 0x056A, 0x0014);
- b43_write16(dev, 0x0568, 0x0826);
- b43_write16(dev, 0x0500, 0x0000);
- if (!pa_on && (phy->type == B43_PHYTYPE_N)) {
- //SPEC TODO
- }
+ b43_write16(dev, B43_MMIO_TXE0_PHYCTL, value);
+ if (phy->type == B43_PHYTYPE_N || phy->type == B43_PHYTYPE_LP ||
+ phy->type == B43_PHYTYPE_LCN)
+ b43_write16(dev, B43_MMIO_TXE0_PHYCTL1, 0x1A02);
+
+ b43_write16(dev, B43_MMIO_TXE0_WM_0, 0x0000);
+ b43_write16(dev, B43_MMIO_TXE0_WM_1, 0x0000);
+
+ b43_write16(dev, B43_MMIO_XMTTPLATETXPTR, 0x0000);
+ b43_write16(dev, B43_MMIO_XMTTXCNT, 0x0014);
+ b43_write16(dev, B43_MMIO_XMTSEL, 0x0826);
+ b43_write16(dev, B43_MMIO_TXE0_CTL, 0x0000);
+
+ if (!pa_on && phy->type == B43_PHYTYPE_N)
+ ; /*b43_nphy_pa_override(dev, false) */
switch (phy->type) {
case B43_PHYTYPE_N:
- b43_write16(dev, 0x0502, 0x00D0);
+ case B43_PHYTYPE_LCN:
+ b43_write16(dev, B43_MMIO_TXE0_AUX, 0x00D0);
break;
case B43_PHYTYPE_LP:
- b43_write16(dev, 0x0502, 0x0050);
+ b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0050);
break;
default:
- b43_write16(dev, 0x0502, 0x0030);
+ b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0030);
}
+ b43_read16(dev, B43_MMIO_TXE0_AUX);
if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
b43_radio_write16(dev, 0x0051, 0x0017);
for (i = 0x00; i < max_loop; i++) {
- value = b43_read16(dev, 0x050E);
+ value = b43_read16(dev, B43_MMIO_TXE0_STATUS);
if (value & 0x0080)
break;
udelay(10);
}
for (i = 0x00; i < 0x0A; i++) {
- value = b43_read16(dev, 0x050E);
+ value = b43_read16(dev, B43_MMIO_TXE0_STATUS);
if (value & 0x0400)
break;
udelay(10);
}
for (i = 0x00; i < 0x19; i++) {
- value = b43_read16(dev, 0x0690);
+ value = b43_read16(dev, B43_MMIO_IFSSTAT);
if (!(value & 0x0100))
break;
udelay(10);
@@ -2511,6 +2523,12 @@ static int b43_upload_microcode(struct b43_wldev *dev)
}
dev->fw.rev = fwrev;
dev->fw.patch = fwpatch;
+ if (dev->fw.rev >= 598)
+ dev->fw.hdr_format = B43_FW_HDR_598;
+ else if (dev->fw.rev >= 410)
+ dev->fw.hdr_format = B43_FW_HDR_410;
+ else
+ dev->fw.hdr_format = B43_FW_HDR_351;
dev->fw.opensource = (fwdate == 0xFFFF);
/* Default to use-all-queues. */
@@ -2558,7 +2576,7 @@ static int b43_upload_microcode(struct b43_wldev *dev)
dev->fw.rev, dev->fw.patch);
wiphy->hw_version = dev->dev->core_id;
- if (b43_is_old_txhdr_format(dev)) {
+ if (dev->fw.hdr_format == B43_FW_HDR_351) {
/* We're over the deadline, but we keep support for old fw
* until it turns out to be in major conflict with something new. */
b43warn(dev->wl, "You are using an old firmware image. "
@@ -2944,6 +2962,8 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
case B43_PHYTYPE_G:
case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
+ case B43_PHYTYPE_HT:
+ case B43_PHYTYPE_LCN:
b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);
@@ -3539,7 +3559,8 @@ static void b43_qos_init(struct b43_wldev *dev)
b43dbg(dev->wl, "QoS enabled\n");
}
-static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue,
+static int b43_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 _queue,
const struct ieee80211_tx_queue_params *params)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
@@ -3586,7 +3607,7 @@ static int b43_op_get_stats(struct ieee80211_hw *hw,
return 0;
}
-static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
+static u64 b43_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
@@ -3605,7 +3626,8 @@ static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
-static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+static void b43_op_set_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u64 tsf)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
@@ -3779,14 +3801,24 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
int antenna;
int err = 0;
+ bool reload_bss = false;
mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+
/* Switch the band (if necessary). This might change the active core. */
err = b43_switch_band(wl, conf->channel);
if (err)
goto out_unlock_mutex;
- dev = wl->current_dev;
+
+ /* Need to reload all settings if the core changed */
+ if (dev != wl->current_dev) {
+ dev = wl->current_dev;
+ changed = ~0;
+ reload_bss = true;
+ }
+
phy = &dev->phy;
if (conf_is_ht(conf))
@@ -3847,6 +3879,9 @@ out_mac_enable:
out_unlock_mutex:
mutex_unlock(&wl->mutex);
+ if (wl->vif && reload_bss)
+ b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0);
+
return err;
}
@@ -3935,7 +3970,8 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BEACON_INT &&
(b43_is_mode(wl, NL80211_IFTYPE_AP) ||
b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) ||
- b43_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+ b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) &&
+ conf->beacon_int)
b43_set_beacon_int(dev, conf->beacon_int);
if (changed & BSS_CHANGED_BASIC_RATES)
@@ -4108,10 +4144,13 @@ out_unlock:
* because the core might be gone away while we unlocked the mutex. */
static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
{
- struct b43_wl *wl = dev->wl;
+ struct b43_wl *wl;
struct b43_wldev *orig_dev;
u32 mask;
+ if (!dev)
+ return NULL;
+ wl = dev->wl;
redo:
if (!dev || b43_status(dev) < B43_STAT_STARTED)
return dev;
@@ -4630,8 +4669,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
if (b43_bus_host_is_pcmcia(dev->dev) ||
- b43_bus_host_is_sdio(dev->dev) ||
- dev->use_pio) {
+ b43_bus_host_is_sdio(dev->dev)) {
+ dev->__using_pio_transfers = 1;
+ err = b43_pio_init(dev);
+ } else if (dev->use_pio) {
+ b43warn(dev->wl, "Forced PIO by use_pio module parameter. "
+ "This should not be needed and will result in lower "
+ "performance.\n");
dev->__using_pio_transfers = 1;
err = b43_pio_init(dev);
} else {
@@ -4703,6 +4747,9 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
out_mutex_unlock:
mutex_unlock(&wl->mutex);
+ if (err == 0)
+ b43_op_bss_info_changed(hw, vif, &vif->bss_conf, ~0);
+
return err;
}
@@ -4773,6 +4820,9 @@ static int b43_op_start(struct ieee80211_hw *hw)
out_mutex_unlock:
mutex_unlock(&wl->mutex);
+ /* reload configuration */
+ b43_op_config(hw, ~0);
+
return err;
}
@@ -4929,10 +4979,18 @@ out:
if (err)
wl->current_dev = NULL; /* Failed to init the dev. */
mutex_unlock(&wl->mutex);
- if (err)
+
+ if (err) {
b43err(wl, "Controller restart FAILED\n");
- else
- b43info(wl, "Controller restarted\n");
+ return;
+ }
+
+ /* reload configuration */
+ b43_op_config(wl->hw, ~0);
+ if (wl->vif)
+ b43_op_bss_info_changed(wl->hw, wl->vif, &wl->vif->bss_conf, ~0);
+
+ b43info(wl, "Controller restarted\n");
}
static int b43_setup_bands(struct b43_wldev *dev,
@@ -5417,8 +5475,7 @@ static void b43_print_driverinfo(void)
feat_sdio = "S";
#endif
printk(KERN_INFO "Broadcom 43xx driver loaded "
- "[ Features: %s%s%s%s%s, Firmware-ID: "
- B43_SUPPORTED_FIRMWARE_ID " ]\n",
+ "[ Features: %s%s%s%s%s ]\n",
feat_pci, feat_pcmcia, feat_nphy,
feat_leds, feat_sdio);
}
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 07f009ff5ee2..3ea44bb03684 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -448,6 +448,38 @@ bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type)
channel_type == NL80211_CHAN_HT40PLUS);
}
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
+void b43_phy_force_clock(struct b43_wldev *dev, bool force)
+{
+ u32 tmp;
+
+ WARN_ON(dev->phy.type != B43_PHYTYPE_N &&
+ dev->phy.type != B43_PHYTYPE_HT);
+
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ if (force)
+ tmp |= BCMA_IOCTL_FGC;
+ else
+ tmp &= ~BCMA_IOCTL_FGC;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ if (force)
+ tmp |= SSB_TMSLOW_FGC;
+ else
+ tmp &= ~SSB_TMSLOW_FGC;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ break;
+#endif
+ }
+}
+
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */
struct b43_c32 b43_cordic(int theta)
{
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index aa77ba612a92..9233b13fc16d 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -444,6 +444,8 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type);
+void b43_phy_force_clock(struct b43_wldev *dev, bool force);
+
struct b43_c32 b43_cordic(int theta);
#endif /* LINUX_B43_PHY_COMMON_H_ */
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
index 7c40919651a7..7416c5e9154d 100644
--- a/drivers/net/wireless/b43/phy_ht.c
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -3,6 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n HT-PHY support
+ Copyright (c) 2011 Rafał Miłecki <zajec5@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
@@ -152,6 +154,92 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
}
/**************************************************
+ * Various PHY ops
+ **************************************************/
+
+static void b43_phy_ht_zero_extg(struct b43_wldev *dev)
+{
+ u8 i, j;
+ u16 base[] = { 0x40, 0x60, 0x80 };
+
+ for (i = 0; i < ARRAY_SIZE(base); i++) {
+ for (j = 0; j < 4; j++)
+ b43_phy_write(dev, B43_PHY_EXTG(base[i] + j), 0);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(base); i++)
+ b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0);
+}
+
+/* Some unknown AFE (Analog Frondned) op */
+static void b43_phy_ht_afe_unk1(struct b43_wldev *dev)
+{
+ u8 i;
+
+ const u16 ctl_regs[3][2] = {
+ { B43_PHY_HT_AFE_CTL1, B43_PHY_HT_AFE_CTL2 },
+ { B43_PHY_HT_AFE_CTL3, B43_PHY_HT_AFE_CTL4 },
+ { B43_PHY_HT_AFE_CTL5, B43_PHY_HT_AFE_CTL6},
+ };
+
+ for (i = 0; i < 3; i++) {
+ /* TODO: verify masks&sets */
+ b43_phy_set(dev, ctl_regs[i][1], 0x4);
+ b43_phy_set(dev, ctl_regs[i][0], 0x4);
+ b43_phy_mask(dev, ctl_regs[i][1], ~0x1);
+ b43_phy_set(dev, ctl_regs[i][0], 0x1);
+ b43_httab_write(dev, B43_HTTAB16(8, 5 + (i * 0x10)), 0);
+ b43_phy_mask(dev, ctl_regs[i][0], ~0x4);
+ }
+}
+
+static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq)
+{
+ u8 i;
+
+ u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE);
+ b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3);
+
+ b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq);
+ for (i = 0; i < 200; i++) {
+ if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) {
+ i = 0;
+ break;
+ }
+ msleep(1);
+ }
+ if (i)
+ b43err(dev->wl, "Forcing RF sequence timeout\n");
+
+ b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode);
+}
+
+static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
+{
+ clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES);
+ clip_st[1] = b43_phy_read(dev, B43_PHY_HT_C2_CLIP1THRES);
+ clip_st[2] = b43_phy_read(dev, B43_PHY_HT_C3_CLIP1THRES);
+}
+
+static void b43_phy_ht_bphy_init(struct b43_wldev *dev)
+{
+ unsigned int i;
+ u16 val;
+
+ val = 0x1E1F;
+ for (i = 0; i < 16; i++) {
+ b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
+ val -= 0x202;
+ }
+ val = 0x3E3F;
+ for (i = 0; i < 16; i++) {
+ b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
+ val -= 0x202;
+ }
+ b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
+}
+
+/**************************************************
* Channel switching ops.
**************************************************/
@@ -255,8 +343,125 @@ static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev)
static int b43_phy_ht_op_init(struct b43_wldev *dev)
{
+ u16 tmp;
+ u16 clip_state[3];
+
b43_phy_ht_tables_init(dev);
+ b43_phy_mask(dev, 0x0be, ~0x2);
+ b43_phy_set(dev, 0x23f, 0x7ff);
+ b43_phy_set(dev, 0x240, 0x7ff);
+ b43_phy_set(dev, 0x241, 0x7ff);
+
+ b43_phy_ht_zero_extg(dev);
+
+ b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3);
+
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0);
+ b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0);
+
+ b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20);
+ b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20);
+ b43_phy_write(dev, 0x20d, 0xb8);
+ b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8);
+ b43_phy_write(dev, 0x70, 0x50);
+ b43_phy_write(dev, 0x1ff, 0x30);
+
+ if (0) /* TODO: condition */
+ ; /* TODO: PHY op on reg 0x217 */
+
+ b43_phy_read(dev, 0xb0); /* TODO: what for? */
+ b43_phy_set(dev, 0xb0, 0x1);
+
+ b43_phy_set(dev, 0xb1, 0x91);
+ b43_phy_write(dev, 0x32f, 0x0003);
+ b43_phy_write(dev, 0x077, 0x0010);
+ b43_phy_write(dev, 0x0b4, 0x0258);
+ b43_phy_mask(dev, 0x17e, ~0x4000);
+
+ b43_phy_write(dev, 0x0b9, 0x0072);
+
+ b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f);
+ b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f);
+ b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f);
+
+ b43_phy_ht_afe_unk1(dev);
+
+ b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111,
+ 0x777, 0x111, 0x111, 0x777, 0x111, 0x111);
+
+ b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777);
+ b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777);
+
+ b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02);
+ b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02);
+ b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02);
+
+ b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4,
+ 0x8e, 0x96, 0x96, 0x96);
+ b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4,
+ 0x8f, 0x9f, 0x9f, 0x9f);
+ b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4,
+ 0x8f, 0x9f, 0x9f, 0x9f);
+
+ b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2);
+ b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2);
+ b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2);
+
+ b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e);
+ b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e);
+ b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46);
+ b43_phy_maskset(dev, 0x0283, 0xff00, 0x40);
+
+ b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4,
+ 0x09, 0x0e, 0x13, 0x18);
+ b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4,
+ 0x09, 0x0e, 0x13, 0x18);
+ /* TODO: Did wl mean 2 instead of 40? */
+ b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4,
+ 0x09, 0x0e, 0x13, 0x18);
+
+ b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd);
+ b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd);
+ b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd);
+
+ b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1);
+ b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1);
+ b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1);
+ b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1);
+
+ /* Copy some tables entries */
+ tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144));
+ b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp);
+ tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154));
+ b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp);
+ tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164));
+ b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp);
+
+ /* Reset CCA */
+ b43_phy_force_clock(dev, true);
+ tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG);
+ b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA);
+ b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA);
+ b43_phy_force_clock(dev, false);
+
+ b43_mac_phy_clock_set(dev, true);
+
+ b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX);
+ b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX);
+
+ /* TODO: PHY op on reg 0xb0 */
+
+ /* TODO: Should we restore it? Or store it in global PHY info? */
+ b43_phy_ht_read_clip_detection(dev, clip_state);
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ b43_phy_ht_bphy_init(dev);
+
+ b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0),
+ B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late);
+
return 0;
}
diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h
index 7ad7affc8df0..6544c4293b34 100644
--- a/drivers/net/wireless/b43/phy_ht.h
+++ b/drivers/net/wireless/b43/phy_ht.h
@@ -4,7 +4,11 @@
#include "phy_common.h"
+#define B43_PHY_HT_BBCFG 0x001 /* BB config */
+#define B43_PHY_HT_BBCFG_RSTCCA 0x4000 /* Reset CCA */
+#define B43_PHY_HT_BBCFG_RSTRX 0x8000 /* Reset RX */
#define B43_PHY_HT_BANDCTL 0x009 /* Band control */
+#define B43_PHY_HT_BANDCTL_5GHZ 0x0001 /* Use the 5GHz band */
#define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */
#define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */
#define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */
@@ -15,6 +19,21 @@
#define B43_PHY_HT_BW5 0x1D2
#define B43_PHY_HT_BW6 0x1D3
+#define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E)
+#define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E)
+#define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E)
+
+#define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000)
+#define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003)
+#define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */
+#define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */
+#define B43_PHY_HT_RF_SEQ_TRIG_UPGH 0x0004 /* Update gain H */
+#define B43_PHY_HT_RF_SEQ_TRIG_UPGL 0x0008 /* Update gain L */
+#define B43_PHY_HT_RF_SEQ_TRIG_UPGU 0x0010 /* Update gain U */
+#define B43_PHY_HT_RF_SEQ_TRIG_RST2RX 0x0020 /* Reset to RX */
+#define B43_PHY_HT_RF_SEQ_STATUS B43_PHY_EXTG(0x004)
+/* Values for the status are the same as for the trigger */
+
#define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010)
#define B43_PHY_HT_AFE_CTL1 B43_PHY_EXTG(0x110)
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
index 9f7dbbd5ced6..a13e28ef6246 100644
--- a/drivers/net/wireless/b43/phy_lcn.c
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -3,6 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n LCN-PHY support
+ Copyright (c) 2011 Rafał Miłecki <zajec5@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
@@ -18,6 +20,14 @@
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
Boston, MA 02110-1301, USA.
+ This file incorporates work covered by the following copyright and
+ permission notice:
+
+ Copyright (c) 2010 Broadcom Corporation
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
*/
#include <linux/slab.h>
@@ -27,12 +37,852 @@
#include "tables_phy_lcn.h"
#include "main.h"
+struct lcn_tx_gains {
+ u16 gm_gain;
+ u16 pga_gain;
+ u16 pad_gain;
+ u16 dac_gain;
+};
+
+struct lcn_tx_iir_filter {
+ u8 type;
+ u16 values[16];
+};
+
+enum lcn_sense_type {
+ B43_SENSE_TEMP,
+ B43_SENSE_VBAT,
+};
+
+/* In theory it's PHY common function, move if needed */
+/* brcms_b_switch_macfreq */
+static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode)
+{
+ if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
+ switch (spurmode) {
+ case 2: /* 126 Mhz */
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+ break;
+ case 1: /* 123 Mhz */
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+ break;
+ default: /* 120 Mhz */
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+ break;
+ }
+ } else if (dev->phy.type == B43_PHYTYPE_LCN) {
+ switch (spurmode) {
+ case 1: /* 82 Mhz */
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
+ break;
+ default: /* 80 Mhz */
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
+ break;
+ }
+ }
+}
+
+/**************************************************
+ * Radio 2064.
+ **************************************************/
+
+/* wlc_lcnphy_radio_2064_channel_tune_4313 */
+static void b43_radio_2064_channel_setup(struct b43_wldev *dev)
+{
+ u16 save[2];
+
+ b43_radio_set(dev, 0x09d, 0x4);
+ b43_radio_write(dev, 0x09e, 0xf);
+
+ /* Channel specific values in theory, in practice always the same */
+ b43_radio_write(dev, 0x02a, 0xb);
+ b43_radio_maskset(dev, 0x030, ~0x3, 0xa);
+ b43_radio_maskset(dev, 0x091, ~0x3, 0);
+ b43_radio_maskset(dev, 0x038, ~0xf, 0x7);
+ b43_radio_maskset(dev, 0x030, ~0xc, 0x8);
+ b43_radio_maskset(dev, 0x05e, ~0xf, 0x8);
+ b43_radio_maskset(dev, 0x05e, ~0xf0, 0x80);
+ b43_radio_write(dev, 0x06c, 0x80);
+
+ save[0] = b43_radio_read(dev, 0x044);
+ save[1] = b43_radio_read(dev, 0x12b);
+
+ b43_radio_set(dev, 0x044, 0x7);
+ b43_radio_set(dev, 0x12b, 0xe);
+
+ /* TODO */
+
+ b43_radio_write(dev, 0x040, 0xfb);
+
+ b43_radio_write(dev, 0x041, 0x9a);
+ b43_radio_write(dev, 0x042, 0xa3);
+ b43_radio_write(dev, 0x043, 0x0c);
+
+ /* TODO */
+
+ b43_radio_set(dev, 0x044, 0x0c);
+ udelay(1);
+
+ b43_radio_write(dev, 0x044, save[0]);
+ b43_radio_write(dev, 0x12b, save[1]);
+
+ if (dev->phy.rev == 1) {
+ /* brcmsmac uses outdated 0x3 for 0x038 */
+ b43_radio_write(dev, 0x038, 0x0);
+ b43_radio_write(dev, 0x091, 0x7);
+ }
+}
+
+/* wlc_radio_2064_init */
+static void b43_radio_2064_init(struct b43_wldev *dev)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ b43_radio_write(dev, 0x09c, 0x0020);
+ b43_radio_write(dev, 0x105, 0x0008);
+ } else {
+ /* TODO */
+ }
+ b43_radio_write(dev, 0x032, 0x0062);
+ b43_radio_write(dev, 0x033, 0x0019);
+ b43_radio_write(dev, 0x090, 0x0010);
+ b43_radio_write(dev, 0x010, 0x0000);
+ if (dev->phy.rev == 1) {
+ b43_radio_write(dev, 0x060, 0x007f);
+ b43_radio_write(dev, 0x061, 0x0072);
+ b43_radio_write(dev, 0x062, 0x007f);
+ }
+ b43_radio_write(dev, 0x01d, 0x0002);
+ b43_radio_write(dev, 0x01e, 0x0006);
+
+ b43_phy_write(dev, 0x4ea, 0x4688);
+ b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2);
+ b43_phy_mask(dev, 0x4eb, ~0x01c0);
+ b43_phy_maskset(dev, 0x46a, 0xff00, 0x19);
+
+ b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0);
+
+ b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
+ b43_radio_set(dev, 0x004, 0x40);
+ b43_radio_set(dev, 0x120, 0x10);
+ b43_radio_set(dev, 0x078, 0x80);
+ b43_radio_set(dev, 0x129, 0x2);
+ b43_radio_set(dev, 0x057, 0x1);
+ b43_radio_set(dev, 0x05b, 0x2);
+
+ /* TODO: wait for some bit to be set */
+ b43_radio_read(dev, 0x05c);
+
+ b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
+ b43_radio_mask(dev, 0x057, (u16) ~0xff01);
+
+ b43_phy_write(dev, 0x933, 0x2d6b);
+ b43_phy_write(dev, 0x934, 0x2d6b);
+ b43_phy_write(dev, 0x935, 0x2d6b);
+ b43_phy_write(dev, 0x936, 0x2d6b);
+ b43_phy_write(dev, 0x937, 0x016b);
+
+ b43_radio_mask(dev, 0x057, (u16) ~0xff02);
+ b43_radio_write(dev, 0x0c2, 0x006f);
+}
+
+/**************************************************
+ * Various PHY ops
+ **************************************************/
+
+/* wlc_lcnphy_toggle_afe_pwdn */
+static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
+{
+ u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2);
+ u16 afe_ctl1 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL1);
+
+ b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 | 0x1);
+ b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 | 0x1);
+
+ b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 & ~0x1);
+ b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 & ~0x1);
+
+ b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2);
+ b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1);
+}
+
+/* wlc_lcnphy_get_pa_gain */
+static u16 b43_phy_lcn_get_pa_gain(struct b43_wldev *dev)
+{
+ return (b43_phy_read(dev, 0x4fb) & 0x7f00) >> 8;
+}
+
+/* wlc_lcnphy_set_dac_gain */
+static void b43_phy_lcn_set_dac_gain(struct b43_wldev *dev, u16 dac_gain)
+{
+ u16 dac_ctrl;
+
+ dac_ctrl = b43_phy_read(dev, 0x439);
+ dac_ctrl = dac_ctrl & 0xc7f;
+ dac_ctrl = dac_ctrl | (dac_gain << 7);
+ b43_phy_maskset(dev, 0x439, ~0xfff, dac_ctrl);
+}
+
+/* wlc_lcnphy_set_bbmult */
+static void b43_phy_lcn_set_bbmult(struct b43_wldev *dev, u8 m0)
+{
+ b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x57), m0 << 8);
+}
+
+/* wlc_lcnphy_clear_tx_power_offsets */
+static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev)
+{
+ u8 i;
+
+ if (1) { /* FIXME */
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
+ for (i = 0; i < 30; i++) {
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
+ }
+ }
+
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80);
+ for (i = 0; i < 64; i++) {
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
+ }
+}
+
+/* wlc_lcnphy_rev0_baseband_init */
+static void b43_phy_lcn_rev0_baseband_init(struct b43_wldev *dev)
+{
+ b43_radio_write(dev, 0x11c, 0);
+
+ b43_phy_write(dev, 0x43b, 0);
+ b43_phy_write(dev, 0x43c, 0);
+ b43_phy_write(dev, 0x44c, 0);
+ b43_phy_write(dev, 0x4e6, 0);
+ b43_phy_write(dev, 0x4f9, 0);
+ b43_phy_write(dev, 0x4b0, 0);
+ b43_phy_write(dev, 0x938, 0);
+ b43_phy_write(dev, 0x4b0, 0);
+ b43_phy_write(dev, 0x44e, 0);
+
+ b43_phy_set(dev, 0x567, 0x03);
+
+ b43_phy_set(dev, 0x44a, 0x44);
+ b43_phy_write(dev, 0x44a, 0x80);
+
+ if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM))
+ ; /* TODO */
+ b43_phy_maskset(dev, 0x634, ~0xff, 0xc);
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM) {
+ b43_phy_maskset(dev, 0x634, ~0xff, 0xa);
+ b43_phy_write(dev, 0x910, 0x1);
+ }
+
+ b43_phy_write(dev, 0x910, 0x1);
+
+ b43_phy_maskset(dev, 0x448, ~0x300, 0x100);
+ b43_phy_maskset(dev, 0x608, ~0xff, 0x17);
+ b43_phy_maskset(dev, 0x604, ~0x7ff, 0x3ea);
+}
+
+/* wlc_lcnphy_bu_tweaks */
+static void b43_phy_lcn_bu_tweaks(struct b43_wldev *dev)
+{
+ b43_phy_set(dev, 0x805, 0x1);
+
+ b43_phy_maskset(dev, 0x42f, ~0x7, 0x3);
+ b43_phy_maskset(dev, 0x030, ~0x7, 0x3);
+
+ b43_phy_write(dev, 0x414, 0x1e10);
+ b43_phy_write(dev, 0x415, 0x0640);
+
+ b43_phy_maskset(dev, 0x4df, (u16) ~0xff00, 0xf700);
+
+ b43_phy_set(dev, 0x44a, 0x44);
+ b43_phy_write(dev, 0x44a, 0x80);
+
+ b43_phy_maskset(dev, 0x434, ~0xff, 0xfd);
+ b43_phy_maskset(dev, 0x420, ~0xff, 0x10);
+
+ if (dev->dev->bus_sprom->board_rev >= 0x1204)
+ b43_radio_set(dev, 0x09b, 0xf0);
+
+ b43_phy_write(dev, 0x7d6, 0x0902);
+
+ b43_phy_maskset(dev, 0x429, ~0xf, 0x9);
+ b43_phy_maskset(dev, 0x429, ~(0x3f << 4), 0xe << 4);
+
+ if (dev->phy.rev == 1) {
+ b43_phy_maskset(dev, 0x423, ~0xff, 0x46);
+ b43_phy_maskset(dev, 0x411, ~0xff, 1);
+ b43_phy_set(dev, 0x434, 0xff); /* FIXME: update to wl */
+
+ /* TODO: wl operates on PHY 0x416, brcmsmac is outdated here */
+
+ b43_phy_maskset(dev, 0x656, ~0xf, 2);
+ b43_phy_set(dev, 0x44d, 4);
+
+ b43_radio_set(dev, 0x0f7, 0x4);
+ b43_radio_mask(dev, 0x0f1, ~0x3);
+ b43_radio_maskset(dev, 0x0f2, ~0xf8, 0x90);
+ b43_radio_maskset(dev, 0x0f3, ~0x3, 0x2);
+ b43_radio_maskset(dev, 0x0f3, ~0xf0, 0xa0);
+
+ b43_radio_set(dev, 0x11f, 0x2);
+
+ b43_phy_lcn_clear_tx_power_offsets(dev);
+
+ /* TODO: something more? */
+ }
+}
+
+/* wlc_lcnphy_vbat_temp_sense_setup */
+static void b43_phy_lcn_sense_setup(struct b43_wldev *dev,
+ enum lcn_sense_type sense_type)
+{
+ u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
+ u16 auxpga_vmid;
+ u8 tx_pwr_idx;
+ u8 i;
+
+ u16 save_radio_regs[6][2] = {
+ { 0x007, 0 }, { 0x0ff, 0 }, { 0x11f, 0 }, { 0x005, 0 },
+ { 0x025, 0 }, { 0x112, 0 },
+ };
+ u16 save_phy_regs[14][2] = {
+ { 0x503, 0 }, { 0x4a4, 0 }, { 0x4d0, 0 }, { 0x4d9, 0 },
+ { 0x4da, 0 }, { 0x4a6, 0 }, { 0x938, 0 }, { 0x939, 0 },
+ { 0x4d8, 0 }, { 0x4d0, 0 }, { 0x4d7, 0 }, { 0x4a5, 0 },
+ { 0x40d, 0 }, { 0x4a2, 0 },
+ };
+ u16 save_radio_4a4;
+
+ msleep(1);
+
+ /* Save */
+ for (i = 0; i < 6; i++)
+ save_radio_regs[i][1] = b43_radio_read(dev,
+ save_radio_regs[i][0]);
+ for (i = 0; i < 14; i++)
+ save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]);
+ b43_mac_suspend(dev);
+ save_radio_4a4 = b43_radio_read(dev, 0x4a4);
+ /* wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); */
+ tx_pwr_idx = dev->phy.lcn->tx_pwr_curr_idx;
+
+ /* Setup */
+ /* TODO: wlc_lcnphy_set_tx_pwr_by_index(pi, 127); */
+ b43_radio_set(dev, 0x007, 0x1);
+ b43_radio_set(dev, 0x0ff, 0x10);
+ b43_radio_set(dev, 0x11f, 0x4);
+
+ b43_phy_mask(dev, 0x503, ~0x1);
+ b43_phy_mask(dev, 0x503, ~0x4);
+ b43_phy_mask(dev, 0x4a4, ~0x4000);
+ b43_phy_mask(dev, 0x4a4, (u16) ~0x8000);
+ b43_phy_mask(dev, 0x4d0, ~0x20);
+ b43_phy_set(dev, 0x4a5, 0xff);
+ b43_phy_maskset(dev, 0x4a5, ~0x7000, 0x5000);
+ b43_phy_mask(dev, 0x4a5, ~0x700);
+ b43_phy_maskset(dev, 0x40d, ~0xff, 64);
+ b43_phy_maskset(dev, 0x40d, ~0x700, 0x600);
+ b43_phy_maskset(dev, 0x4a2, ~0xff, 64);
+ b43_phy_maskset(dev, 0x4a2, ~0x700, 0x600);
+ b43_phy_maskset(dev, 0x4d9, ~0x70, 0x20);
+ b43_phy_maskset(dev, 0x4d9, ~0x700, 0x300);
+ b43_phy_maskset(dev, 0x4d9, ~0x7000, 0x1000);
+ b43_phy_mask(dev, 0x4da, ~0x1000);
+ b43_phy_set(dev, 0x4da, 0x2000);
+ b43_phy_set(dev, 0x4a6, 0x8000);
+
+ b43_radio_write(dev, 0x025, 0xc);
+ b43_radio_set(dev, 0x005, 0x8);
+ b43_phy_set(dev, 0x938, 0x4);
+ b43_phy_set(dev, 0x939, 0x4);
+ b43_phy_set(dev, 0x4a4, 0x1000);
+
+ /* FIXME: don't hardcode */
+ b43_lcntab_write(dev, B43_LCNTAB16(0x8, 0x6), 0x640);
+
+ switch (sense_type) {
+ case B43_SENSE_TEMP:
+ b43_phy_set(dev, 0x4d7, 0x8);
+ b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x1000);
+ auxpga_vmidcourse = 8;
+ auxpga_vmidfine = 0x4;
+ auxpga_gain = 2;
+ b43_radio_set(dev, 0x082, 0x20);
+ break;
+ case B43_SENSE_VBAT:
+ b43_phy_set(dev, 0x4d7, 0x8);
+ b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x3000);
+ auxpga_vmidcourse = 7;
+ auxpga_vmidfine = 0xa;
+ auxpga_gain = 2;
+ break;
+ }
+ auxpga_vmid = (0x200 | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
+
+ b43_phy_set(dev, 0x4d8, 0x1);
+ b43_phy_maskset(dev, 0x4d8, ~(0x3ff << 2), auxpga_vmid << 2);
+ b43_phy_set(dev, 0x4d8, 0x2);
+ b43_phy_maskset(dev, 0x4d8, ~(0x7 << 12), auxpga_gain << 12);
+ b43_phy_set(dev, 0x4d0, 0x20);
+ b43_radio_write(dev, 0x112, 0x6);
+
+ b43_dummy_transmission(dev, true, false);
+ /* Wait if not done */
+ if (!(b43_phy_read(dev, 0x476) & 0x8000))
+ udelay(10);
+
+ /* Restore */
+ for (i = 0; i < 6; i++)
+ b43_radio_write(dev, save_radio_regs[i][0],
+ save_radio_regs[i][1]);
+ for (i = 0; i < 14; i++)
+ b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]);
+ /* TODO: wlc_lcnphy_set_tx_pwr_by_index(tx_pwr_idx) */
+ b43_radio_write(dev, 0x4a4, save_radio_4a4);
+
+ b43_mac_enable(dev);
+
+ msleep(1);
+}
+
+static bool b43_phy_lcn_load_tx_iir_cck_filter(struct b43_wldev *dev,
+ u8 filter_type)
+{
+ int i, j;
+ u16 phy_regs[] = { 0x910, 0x91e, 0x91f, 0x924, 0x925, 0x926, 0x920,
+ 0x921, 0x927, 0x928, 0x929, 0x922, 0x923, 0x930,
+ 0x931, 0x932 };
+ /* Table is from brcmsmac, values for type 25 were outdated, probably
+ * others need updating too */
+ struct lcn_tx_iir_filter tx_iir_filters_cck[] = {
+ { 0, { 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778,
+ 1582, 64, 128, 64 } },
+ { 1, { 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608,
+ 1863, 93, 167, 93 } },
+ { 2, { 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192,
+ 778, 1582, 64, 128, 64 } },
+ { 3, { 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205,
+ 754, 1760, 170, 340, 170 } },
+ { 20, { 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205,
+ 767, 1760, 256, 185, 256 } },
+ { 21, { 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205,
+ 767, 1760, 256, 273, 256 } },
+ { 22, { 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205,
+ 767, 1760, 256, 352, 256 } },
+ { 23, { 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205,
+ 767, 1760, 128, 233, 128 } },
+ { 24, { 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766,
+ 1760, 256, 1881, 256 } },
+ { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765,
+ 1760, 262, 1878, 262 } },
+ /* brcmsmac version { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720,
+ * 256, 471, 256, 765, 1760, 256, 1881, 256 } }, */
+ { 26, { 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614,
+ 1864, 128, 384, 288 } },
+ { 27, { 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576,
+ 613, 1864, 128, 384, 288 } },
+ { 30, { 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205,
+ 754, 1760, 170, 340, 170 } },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(tx_iir_filters_cck); i++) {
+ if (tx_iir_filters_cck[i].type == filter_type) {
+ for (j = 0; j < 16; j++)
+ b43_phy_write(dev, phy_regs[j],
+ tx_iir_filters_cck[i].values[j]);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool b43_phy_lcn_load_tx_iir_ofdm_filter(struct b43_wldev *dev,
+ u8 filter_type)
+{
+ int i, j;
+ u16 phy_regs[] = { 0x90f, 0x900, 0x901, 0x906, 0x907, 0x908, 0x902,
+ 0x903, 0x909, 0x90a, 0x90b, 0x904, 0x905, 0x90c,
+ 0x90d, 0x90e };
+ struct lcn_tx_iir_filter tx_iir_filters_ofdm[] = {
+ { 0, { 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0,
+ 0x0, 0x278, 0xfea0, 0x80, 0x100, 0x80 } },
+ { 1, { 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, 750,
+ 0xFE2B, 212, 0xFFCE, 212 } },
+ { 2, { 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
+ 0xFEF2, 128, 0xFFE2, 128 } },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(tx_iir_filters_ofdm); i++) {
+ if (tx_iir_filters_ofdm[i].type == filter_type) {
+ for (j = 0; j < 16; j++)
+ b43_phy_write(dev, phy_regs[j],
+ tx_iir_filters_ofdm[i].values[j]);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* wlc_lcnphy_set_tx_gain_override */
+static void b43_phy_lcn_set_tx_gain_override(struct b43_wldev *dev, bool enable)
+{
+ b43_phy_maskset(dev, 0x4b0, ~(0x1 << 7), enable << 7);
+ b43_phy_maskset(dev, 0x4b0, ~(0x1 << 14), enable << 14);
+ b43_phy_maskset(dev, 0x43b, ~(0x1 << 6), enable << 6);
+}
+
+/* wlc_lcnphy_set_tx_gain */
+static void b43_phy_lcn_set_tx_gain(struct b43_wldev *dev,
+ struct lcn_tx_gains *target_gains)
+{
+ u16 pa_gain = b43_phy_lcn_get_pa_gain(dev);
+
+ b43_phy_write(dev, 0x4b5,
+ (target_gains->gm_gain | (target_gains->pga_gain << 8)));
+ b43_phy_maskset(dev, 0x4fb, ~0x7fff,
+ (target_gains->pad_gain | (pa_gain << 8)));
+ b43_phy_write(dev, 0x4fc,
+ (target_gains->gm_gain | (target_gains->pga_gain << 8)));
+ b43_phy_maskset(dev, 0x4fd, ~0x7fff,
+ (target_gains->pad_gain | (pa_gain << 8)));
+
+ b43_phy_lcn_set_dac_gain(dev, target_gains->dac_gain);
+ b43_phy_lcn_set_tx_gain_override(dev, true);
+}
+
+/* wlc_lcnphy_tx_pwr_ctrl_init */
+static void b43_phy_lcn_tx_pwr_ctl_init(struct b43_wldev *dev)
+{
+ struct lcn_tx_gains tx_gains;
+ u8 bbmult;
+
+ b43_mac_suspend(dev);
+
+ if (!dev->phy.lcn->hw_pwr_ctl_capable) {
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ tx_gains.gm_gain = 4;
+ tx_gains.pga_gain = 12;
+ tx_gains.pad_gain = 12;
+ tx_gains.dac_gain = 0;
+ bbmult = 150;
+ } else {
+ tx_gains.gm_gain = 7;
+ tx_gains.pga_gain = 15;
+ tx_gains.pad_gain = 14;
+ tx_gains.dac_gain = 0;
+ bbmult = 150;
+ }
+ b43_phy_lcn_set_tx_gain(dev, &tx_gains);
+ b43_phy_lcn_set_bbmult(dev, bbmult);
+ b43_phy_lcn_sense_setup(dev, B43_SENSE_TEMP);
+ } else {
+ b43err(dev->wl, "TX power control not supported for this HW\n");
+ }
+
+ b43_mac_enable(dev);
+}
+
+/* wlc_lcnphy_txrx_spur_avoidance_mode */
+static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev,
+ bool enable)
+{
+ if (enable) {
+ b43_phy_write(dev, 0x942, 0x7);
+ b43_phy_write(dev, 0x93b, ((1 << 13) + 23));
+ b43_phy_write(dev, 0x93c, ((1 << 13) + 1989));
+
+ b43_phy_write(dev, 0x44a, 0x084);
+ b43_phy_write(dev, 0x44a, 0x080);
+ b43_phy_write(dev, 0x6d3, 0x2222);
+ b43_phy_write(dev, 0x6d3, 0x2220);
+ } else {
+ b43_phy_write(dev, 0x942, 0x0);
+ b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
+ b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
+ }
+ b43_phy_switch_macfreq(dev, enable);
+}
+
+/**************************************************
+ * Channel switching ops.
+ **************************************************/
+
+/* wlc_lcnphy_set_chanspec_tweaks */
+static void b43_phy_lcn_set_channel_tweaks(struct b43_wldev *dev, int channel)
+{
+ struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
+
+ b43_phy_maskset(dev, 0x448, ~0x300, (channel == 14) ? 0x200 : 0x100);
+
+ if (channel == 1 || channel == 2 || channel == 3 || channel == 4 ||
+ channel == 9 || channel == 10 || channel == 11 || channel == 12) {
+ bcma_chipco_pll_write(cc, 0x2, 0x03000c04);
+ bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x0);
+ bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
+
+ bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
+
+ b43_phy_write(dev, 0x942, 0);
+
+ b43_phy_lcn_txrx_spur_avoidance_mode(dev, false);
+ b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1b00);
+ b43_phy_write(dev, 0x425, 0x5907);
+ } else {
+ bcma_chipco_pll_write(cc, 0x2, 0x03140c04);
+ bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x333333);
+ bcma_chipco_pll_write(cc, 0x4, 0x202c2820);
+
+ bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
+
+ b43_phy_write(dev, 0x942, 0);
+
+ b43_phy_lcn_txrx_spur_avoidance_mode(dev, true);
+ b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1f00);
+ b43_phy_write(dev, 0x425, 0x590a);
+ }
+
+ b43_phy_set(dev, 0x44a, 0x44);
+ b43_phy_write(dev, 0x44a, 0x80);
+}
+
+/* wlc_phy_chanspec_set_lcnphy */
+static int b43_phy_lcn_set_channel(struct b43_wldev *dev,
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type channel_type)
+{
+ static const u16 sfo_cfg[14][2] = {
+ {965, 1087}, {967, 1085}, {969, 1082}, {971, 1080}, {973, 1078},
+ {975, 1076}, {977, 1073}, {979, 1071}, {981, 1069}, {983, 1067},
+ {985, 1065}, {987, 1063}, {989, 1060}, {994, 1055},
+ };
+
+ b43_phy_lcn_set_channel_tweaks(dev, channel->hw_value);
+
+ b43_phy_set(dev, 0x44a, 0x44);
+ b43_phy_write(dev, 0x44a, 0x80);
+
+ b43_radio_2064_channel_setup(dev);
+ mdelay(1);
+
+ b43_phy_lcn_afe_set_unset(dev);
+
+ b43_phy_write(dev, 0x657, sfo_cfg[channel->hw_value - 1][0]);
+ b43_phy_write(dev, 0x658, sfo_cfg[channel->hw_value - 1][1]);
+
+ if (channel->hw_value == 14) {
+ b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (2) << 8);
+ b43_phy_lcn_load_tx_iir_cck_filter(dev, 3);
+ } else {
+ b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (1) << 8);
+ /* brcmsmac uses filter_type 2, we follow wl with 25 */
+ b43_phy_lcn_load_tx_iir_cck_filter(dev, 25);
+ }
+ /* brcmsmac uses filter_type 2, we follow wl with 0 */
+ b43_phy_lcn_load_tx_iir_ofdm_filter(dev, 0);
+
+ b43_phy_maskset(dev, 0x4eb, ~(0x7 << 3), 0x1 << 3);
+
+ return 0;
+}
+
+/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
+static int b43_phy_lcn_op_allocate(struct b43_wldev *dev)
+{
+ struct b43_phy_lcn *phy_lcn;
+
+ phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL);
+ if (!phy_lcn)
+ return -ENOMEM;
+ dev->phy.lcn = phy_lcn;
+
+ return 0;
+}
+
+static void b43_phy_lcn_op_free(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_lcn *phy_lcn = phy->lcn;
+
+ kfree(phy_lcn);
+ phy->lcn = NULL;
+}
+
+static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_lcn *phy_lcn = phy->lcn;
+
+ memset(phy_lcn, 0, sizeof(*phy_lcn));
+}
+
+/* wlc_phy_init_lcnphy */
+static int b43_phy_lcn_op_init(struct b43_wldev *dev)
+{
+ struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
+
+ b43_phy_set(dev, 0x44a, 0x80);
+ b43_phy_mask(dev, 0x44a, 0x7f);
+ b43_phy_set(dev, 0x6d1, 0x80);
+ b43_phy_write(dev, 0x6d0, 0x7);
+
+ b43_phy_lcn_afe_set_unset(dev);
+
+ b43_phy_write(dev, 0x60a, 0xa0);
+ b43_phy_write(dev, 0x46a, 0x19);
+ b43_phy_maskset(dev, 0x663, 0xFF00, 0x64);
+
+ b43_phy_lcn_tables_init(dev);
+
+ b43_phy_lcn_rev0_baseband_init(dev);
+ b43_phy_lcn_bu_tweaks(dev);
+
+ if (dev->phy.radio_ver == 0x2064)
+ b43_radio_2064_init(dev);
+ else
+ B43_WARN_ON(1);
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ b43_phy_lcn_tx_pwr_ctl_init(dev);
+
+ b43_switch_channel(dev, dev->phy.channel);
+
+ bcma_chipco_regctl_maskset(cc, 0, 0xf, 0x9);
+ bcma_chipco_chipctl_maskset(cc, 0, 0, 0x03cddddd);
+
+ /* TODO */
+
+ b43_phy_set(dev, 0x448, 0x4000);
+ udelay(100);
+ b43_phy_mask(dev, 0x448, ~0x4000);
+
+ /* TODO */
+
+ return 0;
+}
+
+static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev,
+ bool blocked)
+{
+ if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
+ b43err(dev->wl, "MAC not suspended\n");
+
+ if (blocked) {
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00);
+ b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00);
+
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00);
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2);
+ b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808);
+
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8);
+ b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8);
+ } else {
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL1, ~0x1f00);
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL3, ~0x808);
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL6, ~0x8);
+ }
+}
+
+static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+ if (on) {
+ b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7);
+ } else {
+ b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7);
+ b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7);
+ }
+}
+
+static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev,
+ unsigned int new_channel)
+{
+ struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
+ enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ if ((new_channel < 1) || (new_channel > 14))
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
+
+ return b43_phy_lcn_set_channel(dev, channel, channel_type);
+}
+
+static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ return 1;
+ return 36;
+}
+
+static enum b43_txpwr_result
+b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
+{
+ return B43_TXPWR_RES_DONE;
+}
+
+static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
+{
+}
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static u16 b43_phy_lcn_op_read(struct b43_wldev *dev, u16 reg)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_phy_lcn_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+ u16 set)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA,
+ (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+}
+
+static u16 b43_phy_lcn_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+ /* LCN-PHY needs 0x200 for read access */
+ reg |= 0x200;
+
+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+}
+
+static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg,
+ u16 value)
+{
+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+}
+
/**************************************************
* PHY ops struct.
**************************************************/
const struct b43_phy_operations b43_phyops_lcn = {
- /*
.allocate = b43_phy_lcn_op_allocate,
.free = b43_phy_lcn_op_free,
.prepare_structs = b43_phy_lcn_op_prepare_structs,
@@ -48,5 +898,4 @@ const struct b43_phy_operations b43_phyops_lcn = {
.get_default_chan = b43_phy_lcn_op_get_default_chan,
.recalc_txpower = b43_phy_lcn_op_recalc_txpower,
.adjust_txpower = b43_phy_lcn_op_adjust_txpower,
- */
};
diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h
index c046c2a6cab4..6a7092e13fff 100644
--- a/drivers/net/wireless/b43/phy_lcn.h
+++ b/drivers/net/wireless/b43/phy_lcn.h
@@ -4,11 +4,28 @@
#include "phy_common.h"
+#define B43_PHY_LCN_AFE_CTL1 B43_PHY_OFDM(0x03B)
+#define B43_PHY_LCN_AFE_CTL2 B43_PHY_OFDM(0x03C)
+#define B43_PHY_LCN_RF_CTL1 B43_PHY_OFDM(0x04C)
+#define B43_PHY_LCN_RF_CTL2 B43_PHY_OFDM(0x04D)
+#define B43_PHY_LCN_TABLE_ADDR B43_PHY_OFDM(0x055) /* Table address */
+#define B43_PHY_LCN_TABLE_DATALO B43_PHY_OFDM(0x056) /* Table data low */
+#define B43_PHY_LCN_TABLE_DATAHI B43_PHY_OFDM(0x057) /* Table data high */
+#define B43_PHY_LCN_RF_CTL3 B43_PHY_OFDM(0x0B0)
+#define B43_PHY_LCN_RF_CTL4 B43_PHY_OFDM(0x0B1)
+#define B43_PHY_LCN_RF_CTL5 B43_PHY_OFDM(0x0B7)
+#define B43_PHY_LCN_RF_CTL6 B43_PHY_OFDM(0x0F9)
+#define B43_PHY_LCN_RF_CTL7 B43_PHY_OFDM(0x0FA)
+
+
struct b43_phy_lcn {
+ bool hw_pwr_ctl;
+ bool hw_pwr_ctl_capable;
+ u8 tx_pwr_curr_idx;
};
struct b43_phy_operations;
extern const struct b43_phy_operations b43_phyops_lcn;
-#endif /* B43_PHY_LCN_H_ */ \ No newline at end of file
+#endif /* B43_PHY_LCN_H_ */
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 3b46360da99b..b17d9b6c33a5 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -4,6 +4,7 @@
IEEE 802.11n PHY support
Copyright (c) 2008 Michael Buesch <m@bues.ch>
+ Copyright (c) 2010-2011 Rafał Miłecki <zajec5@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
@@ -77,6 +78,7 @@ enum b43_nphy_rssi_type {
B43_NPHY_RSSI_TBD,
};
+/* TODO: reorder functions */
static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev,
bool enable);
static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
@@ -87,6 +89,14 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
u16 value, u8 core, bool off);
static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
u16 value, u8 core);
+static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev);
+
+static inline bool b43_nphy_ipa(struct b43_wldev *dev)
+{
+ enum ieee80211_band band = b43_current_band(dev->wl);
+ return ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
+ (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ));
+}
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
{//TODO
@@ -248,15 +258,25 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
{
struct b43_phy_n *nphy = dev->phy.n;
u8 i;
- u16 tmp;
+ u16 bmask, val, tmp;
+ enum ieee80211_band band = b43_current_band(dev->wl);
if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 1);
nphy->txpwrctrl = enable;
if (!enable) {
- if (dev->phy.rev >= 3)
- ; /* TODO */
+ if (dev->phy.rev >= 3 &&
+ (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
+ (B43_NPHY_TXPCTL_CMD_COEFF |
+ B43_NPHY_TXPCTL_CMD_HWPCTLEN |
+ B43_NPHY_TXPCTL_CMD_PCTLEN))) {
+ /* We disable enabled TX pwr ctl, save it's state */
+ nphy->tx_pwr_idx[0] = b43_phy_read(dev,
+ B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
+ nphy->tx_pwr_idx[1] = b43_phy_read(dev,
+ B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
+ }
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
for (i = 0; i < 84; i++)
@@ -285,10 +305,67 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
- if (dev->phy.rev < 2 && 0)
- ; /* TODO */
+ if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+ b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
} else {
- b43err(dev->wl, "enabling tx pwr ctrl not implemented yet\n");
+ b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
+ nphy->adj_pwr_tbl);
+ b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
+ nphy->adj_pwr_tbl);
+
+ bmask = B43_NPHY_TXPCTL_CMD_COEFF |
+ B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+ /* wl does useless check for "enable" param here */
+ val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+ if (dev->phy.rev >= 3) {
+ bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+ if (val)
+ val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+ }
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
+
+ if (band == IEEE80211_BAND_5GHZ) {
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+ ~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
+ if (dev->phy.rev > 1)
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
+ ~B43_NPHY_TXPCTL_INIT_PIDXI1,
+ 0x64);
+ }
+
+ if (dev->phy.rev >= 3) {
+ if (nphy->tx_pwr_idx[0] != 128 &&
+ nphy->tx_pwr_idx[1] != 128) {
+ /* Recover TX pwr ctl state */
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+ ~B43_NPHY_TXPCTL_CMD_INIT,
+ nphy->tx_pwr_idx[0]);
+ if (dev->phy.rev > 1)
+ b43_phy_maskset(dev,
+ B43_NPHY_TXPCTL_INIT,
+ ~0xff, nphy->tx_pwr_idx[1]);
+ }
+ }
+
+ if (dev->phy.rev >= 3) {
+ b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
+ b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
+ } else {
+ b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
+ }
+
+ if (dev->phy.rev == 2)
+ b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
+ else if (dev->phy.rev < 2)
+ b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
+
+ if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+ b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
+
+ if (b43_nphy_ipa(dev)) {
+ b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
+ b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
+ }
}
if (nphy->hang_avoid)
@@ -369,22 +446,23 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
else
b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D10 + i);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, radio_gain);
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
- tmp = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+ b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
+ tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
if (i == 0)
tmp = (tmp & 0x00FF) | (bbmult << 8);
else
tmp = (tmp & 0xFF00) | bbmult;
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, tmp);
-
- if (0)
- ; /* TODO */
+ b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
+
+ if (b43_nphy_ipa(dev)) {
+ u32 tmp32;
+ u16 reg = (i == 0) ?
+ B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
+ tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i, txpi[i]));
+ b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
+ b43_phy_set(dev, reg, 0x4);
+ }
}
b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
@@ -393,6 +471,57 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
b43_nphy_stay_in_carrier_search(dev, 0);
}
+static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ const u32 *table = NULL;
+#if 0
+ TODO: b43_ntab_papd_pga_gain_delta_ipa_2*
+ u32 rfpwr_offset;
+ u8 pga_gain;
+ int i;
+#endif
+
+ if (phy->rev >= 3) {
+ if (b43_nphy_ipa(dev)) {
+ table = b43_nphy_get_ipa_gain_table(dev);
+ } else {
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+ if (phy->rev == 3)
+ table = b43_ntab_tx_gain_rev3_5ghz;
+ if (phy->rev == 4)
+ table = b43_ntab_tx_gain_rev4_5ghz;
+ else
+ table = b43_ntab_tx_gain_rev5plus_5ghz;
+ } else {
+ table = b43_ntab_tx_gain_rev3plus_2ghz;
+ }
+ }
+ } else {
+ table = b43_ntab_tx_gain_rev0_1_2;
+ }
+ b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
+ b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
+
+ if (phy->rev >= 3) {
+#if 0
+ nphy->gmval = (table[0] >> 16) & 0x7000;
+
+ for (i = 0; i < 128; i++) {
+ pga_gain = (table[i] >> 24) & 0xF;
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
+ else
+ rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain];
+ b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
+ rfpwr_offset);
+ b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
+ rfpwr_offset);
+ }
+#endif
+ }
+}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
static void b43_radio_2055_setup(struct b43_wldev *dev,
@@ -581,14 +710,10 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
{
- struct b43_phy_n *nphy = dev->phy.n;
u16 tmp;
- enum ieee80211_band band = b43_current_band(dev->wl);
- bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ);
if (dev->phy.rev >= 3) {
- if (ipa) {
+ if (b43_nphy_ipa(dev)) {
tmp = 4;
b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
(((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
@@ -600,49 +725,17 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
}
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
-static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
-{
- u32 tmp;
-
- if (dev->phy.type != B43_PHYTYPE_N)
- return;
-
- switch (dev->dev->bus_type) {
-#ifdef CONFIG_B43_BCMA
- case B43_BUS_BCMA:
- tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
- if (force)
- tmp |= BCMA_IOCTL_FGC;
- else
- tmp &= ~BCMA_IOCTL_FGC;
- bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
- break;
-#endif
-#ifdef CONFIG_B43_SSB
- case B43_BUS_SSB:
- tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
- if (force)
- tmp |= SSB_TMSLOW_FGC;
- else
- tmp &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
- break;
-#endif
- }
-}
-
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
static void b43_nphy_reset_cca(struct b43_wldev *dev)
{
u16 bbcfg;
- b43_nphy_bmac_clock_fgc(dev, 1);
+ b43_phy_force_clock(dev, 1);
bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
udelay(1);
b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
- b43_nphy_bmac_clock_fgc(dev, 0);
+ b43_phy_force_clock(dev, 0);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
}
@@ -931,11 +1024,7 @@ static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
{
u16 array[4];
- int i;
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50);
- for (i = 0; i < 4; i++)
- array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+ b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
@@ -1398,180 +1487,220 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
}
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
-static void b43_nphy_workarounds(struct b43_wldev *dev)
+static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
{
+ struct b43_phy_n *nphy = dev->phy.n;
struct ssb_sprom *sprom = dev->dev->bus_sprom;
- struct b43_phy *phy = &dev->phy;
- struct b43_phy_n *nphy = phy->n;
-
- u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
- u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
- u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
- u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
+ /* TX to RX */
+ u8 tx2rx_events[9] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
+ u8 tx2rx_delays[9] = { 8, 4, 2, 2, 4, 4, 6, 1 };
+ /* RX to TX */
+ u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
+ 0x1F };
+ u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
+ u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
+ u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
u16 tmp16;
u32 tmp32;
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
- b43_nphy_classifier(dev, 1, 0);
- else
- b43_nphy_classifier(dev, 1, 1);
+ tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
+ tmp32 &= 0xffffff;
+ b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
+
+ b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+
+ b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
+ b43_phy_write(dev, 0x2AE, 0x000C);
+
+ /* TX to RX */
+ b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, 9);
+
+ /* RX to TX */
+ if (b43_nphy_ipa(dev))
+ b43_nphy_set_rf_sequence(dev, 1, rx2tx_events_ipa,
+ rx2tx_delays_ipa, 9);
+ if (nphy->hw_phyrxchain != 3 &&
+ nphy->hw_phyrxchain != nphy->hw_phytxchain) {
+ if (b43_nphy_ipa(dev)) {
+ rx2tx_delays[5] = 59;
+ rx2tx_delays[6] = 1;
+ rx2tx_events[7] = 0x1F;
+ }
+ b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays, 9);
+ }
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 1);
+ tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
+ 0x2 : 0x9C40;
+ b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
- b43_phy_set(dev, B43_NPHY_IQFLIP,
- B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
+ b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
- if (dev->phy.rev >= 3) {
- tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
- tmp32 &= 0xffffff;
- b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
+ b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
+ b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
- b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
- b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
- b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
- b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
- b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
- b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+ b43_nphy_gain_ctrl_workarounds(dev);
- b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
- b43_phy_write(dev, 0x2AE, 0x000C);
+ b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
+ b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
- /* TODO */
+ /* TODO */
- tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
- 0x2 : 0x9C40;
- b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
+ b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+ b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+ b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+ b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+ b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+ b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+ b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+ b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+ b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+ b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+
+ /* N PHY WAR TX Chain Update with hw_phytxchain as argument */
+
+ if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
+ b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
+ (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
+ b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
+ tmp32 = 0x00088888;
+ else
+ tmp32 = 0x88888888;
+ b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
+ b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
+ b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
+
+ if (dev->phy.rev == 4 &&
+ b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+ b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
+ 0x70);
+ b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
+ 0x70);
+ }
- b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
+ b43_phy_write(dev, 0x224, 0x039C);
+ b43_phy_write(dev, 0x225, 0x0357);
+ b43_phy_write(dev, 0x226, 0x0317);
+ b43_phy_write(dev, 0x227, 0x02D7);
+ b43_phy_write(dev, 0x228, 0x039C);
+ b43_phy_write(dev, 0x229, 0x0357);
+ b43_phy_write(dev, 0x22A, 0x0317);
+ b43_phy_write(dev, 0x22B, 0x02D7);
+ b43_phy_write(dev, 0x22C, 0x039C);
+ b43_phy_write(dev, 0x22D, 0x0357);
+ b43_phy_write(dev, 0x22E, 0x0317);
+ b43_phy_write(dev, 0x22F, 0x02D7);
+}
- b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
- b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
+static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
+{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_n *nphy = phy->n;
- b43_nphy_gain_ctrl_workarounds(dev);
+ u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
+ u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
- b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
- b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
+ u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
+ u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
- /* TODO */
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
+ nphy->band5g_pwrgain) {
+ b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
+ b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
+ } else {
+ b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
+ b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
+ }
- b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
- b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
- b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
- b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
- b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
- b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
- b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
- b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
- b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
- b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
-
- /* N PHY WAR TX Chain Update with hw_phytxchain as argument */
-
- if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
- b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
- (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
- b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
- tmp32 = 0x00088888;
- else
- tmp32 = 0x88888888;
- b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
- b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
- b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
-
- if (dev->phy.rev == 4 &&
- b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
- 0x70);
- b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
- 0x70);
- }
+ b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
- b43_phy_write(dev, 0x224, 0x039C);
- b43_phy_write(dev, 0x225, 0x0357);
- b43_phy_write(dev, 0x226, 0x0317);
- b43_phy_write(dev, 0x227, 0x02D7);
- b43_phy_write(dev, 0x228, 0x039C);
- b43_phy_write(dev, 0x229, 0x0357);
- b43_phy_write(dev, 0x22A, 0x0317);
- b43_phy_write(dev, 0x22B, 0x02D7);
- b43_phy_write(dev, 0x22C, 0x039C);
- b43_phy_write(dev, 0x22D, 0x0357);
- b43_phy_write(dev, 0x22E, 0x0317);
- b43_phy_write(dev, 0x22F, 0x02D7);
- } else {
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
- nphy->band5g_pwrgain) {
- b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
- b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
- } else {
- b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
- b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
- }
+ if (dev->phy.rev < 2) {
+ b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
+ }
- b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
- b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
- b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
- b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
- if (dev->phy.rev < 2) {
- b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
- b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
- b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
- b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
- b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
- b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
- }
+ if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD &&
+ dev->dev->board_type == 0x8B) {
+ delays1[0] = 0x1;
+ delays1[5] = 0x14;
+ }
+ b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
+ b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
+ b43_nphy_gain_ctrl_workarounds(dev);
- if (sprom->boardflags2_lo & 0x100 &&
- dev->dev->board_type == 0x8B) {
- delays1[0] = 0x1;
- delays1[5] = 0x14;
- }
- b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
- b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
+ if (dev->phy.rev < 2) {
+ if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
+ b43_hf_write(dev, b43_hf_read(dev) |
+ B43_HF_MLADVW);
+ } else if (dev->phy.rev == 2) {
+ b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
+ b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
+ }
- b43_nphy_gain_ctrl_workarounds(dev);
+ if (dev->phy.rev < 2)
+ b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
+ ~B43_NPHY_SCRAM_SIGCTL_SCM);
+
+ /* Set phase track alpha and beta */
+ b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
+
+ b43_phy_mask(dev, B43_NPHY_PIL_DW1,
+ ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
+ b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
+ b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
+ b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
+
+ if (dev->phy.rev == 2)
+ b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
+ B43_NPHY_FINERX2_CGC_DECGC);
+}
- if (dev->phy.rev < 2) {
- if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
- b43_hf_write(dev, b43_hf_read(dev) |
- B43_HF_MLADVW);
- } else if (dev->phy.rev == 2) {
- b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
- b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
- }
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
+static void b43_nphy_workarounds(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_n *nphy = phy->n;
- if (dev->phy.rev < 2)
- b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
- ~B43_NPHY_SCRAM_SIGCTL_SCM);
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+ b43_nphy_classifier(dev, 1, 0);
+ else
+ b43_nphy_classifier(dev, 1, 1);
- /* Set phase track alpha and beta */
- b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
- b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
- b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
- b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
- b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
- b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
+ if (nphy->hang_avoid)
+ b43_nphy_stay_in_carrier_search(dev, 1);
- b43_phy_mask(dev, B43_NPHY_PIL_DW1,
- ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
- b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
- b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
- b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
+ b43_phy_set(dev, B43_NPHY_IQFLIP,
+ B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
- if (dev->phy.rev == 2)
- b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
- B43_NPHY_FINERX2_CGC_DECGC);
- }
+ if (dev->phy.rev >= 3)
+ b43_nphy_workarounds_rev3plus(dev);
+ else
+ b43_nphy_workarounds_rev1_2(dev);
if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 0);
@@ -2167,7 +2296,6 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
{
- struct b43_phy_n *nphy = dev->phy.n;
u8 i;
u16 reg, val;
@@ -2231,10 +2359,7 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
enum ieee80211_band band =
b43_current_band(dev->wl);
- if ((nphy->ipa2g_on &&
- band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on &&
- band == IEEE80211_BAND_5GHZ))
+ if (b43_nphy_ipa(dev))
val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
else
val = 0x11;
@@ -2609,8 +2734,8 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
{
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if (dev->phy.rev >= 6) {
- /* TODO If the chip is 47162
- return txpwrctrl_tx_gain_ipa_rev5 */
+ if (dev->dev->chip_id == 47162)
+ return txpwrctrl_tx_gain_ipa_rev5;
return txpwrctrl_tx_gain_ipa_rev6;
} else if (dev->phy.rev >= 5) {
return txpwrctrl_tx_gain_ipa_rev5;
@@ -2860,10 +2985,7 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
enum ieee80211_band band =
b43_current_band(dev->wl);
- if ((nphy->ipa2g_on &&
- band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on &&
- band == IEEE80211_BAND_5GHZ)) {
+ if (b43_nphy_ipa(dev)) {
table = b43_nphy_get_ipa_gain_table(dev);
} else {
if (band == IEEE80211_BAND_5GHZ) {
@@ -3680,7 +3802,7 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
- if (sprom->boardflags2_lo & 0x100 ||
+ if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
(dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
dev->dev->board_type == 0x8B))
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
@@ -3699,8 +3821,7 @@ int b43_phy_initn(struct b43_wldev *dev)
}
tmp2 = b43_current_band(dev->wl);
- if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) {
+ if (b43_nphy_ipa(dev)) {
b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
nphy->papd_epsilon_offset[0] << 7);
@@ -3715,11 +3836,11 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_nphy_workarounds(dev);
/* Reset CCA, in init code it differs a little from standard way */
- b43_nphy_bmac_clock_fgc(dev, 1);
+ b43_phy_force_clock(dev, 1);
tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
- b43_nphy_bmac_clock_fgc(dev, 0);
+ b43_phy_force_clock(dev, 0);
b43_mac_phy_clock_set(dev, true);
@@ -3738,15 +3859,7 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_nphy_tx_power_fix(dev);
/* TODO N PHY TX Power Control Idle TSSI */
/* TODO N PHY TX Power Control Setup */
-
- if (phy->rev >= 3) {
- /* TODO */
- } else {
- b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128,
- b43_ntab_tx_gain_rev0_1_2);
- b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128,
- b43_ntab_tx_gain_rev0_1_2);
- }
+ b43_nphy_tx_gain_table_upload(dev);
if (nphy->phyrxchain != 3)
b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
@@ -3950,6 +4063,10 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
+ /* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
+ * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
+ nphy->tx_pwr_idx[0] = 128;
+ nphy->tx_pwr_idx[1] = 128;
}
static void b43_nphy_op_free(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index e789a89f1047..fbf520285bd1 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -764,6 +764,8 @@ struct b43_phy_n {
u8 cal_orig_pwr_idx[2];
u8 measure_hold;
u8 phyrxchain;
+ u8 hw_phyrxchain;
+ u8 hw_phytxchain;
u8 perical;
u32 deaf_count;
u32 rxcalparams;
@@ -783,6 +785,8 @@ struct b43_phy_n {
u16 mphase_txcal_bestcoeffs[11];
bool txpwrctrl;
+ u8 tx_pwr_idx[2];
+ u16 adj_pwr_tbl[84];
u16 txcal_bbmult;
u16 txiqlocal_bestc[11];
bool txiqlocal_coeffsvalid;
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 6e4228c3ed1b..fcff923b3c18 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -611,7 +611,7 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
struct b43_wldev *dev = q->dev;
struct b43_wl *wl = dev->wl;
u16 len;
- u32 macstat;
+ u32 macstat = 0;
unsigned int i, padding;
struct sk_buff *skb;
const char *err_msg = NULL;
@@ -676,7 +676,15 @@ data_ready:
goto rx_error;
}
- macstat = le32_to_cpu(rxhdr->mac_status);
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ macstat = le32_to_cpu(rxhdr->format_598.mac_status);
+ break;
+ case B43_FW_HDR_410:
+ case B43_FW_HDR_351:
+ macstat = le32_to_cpu(rxhdr->format_351.mac_status);
+ break;
+ }
if (macstat & B43_RX_MAC_FCSERR) {
if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
/* Drop frames with failed FCS. */
diff --git a/drivers/net/wireless/b43/radio_2055.c b/drivers/net/wireless/b43/radio_2055.c
index 93643f18c2b3..5289a18ddd8c 100644
--- a/drivers/net/wireless/b43/radio_2055.c
+++ b/drivers/net/wireless/b43/radio_2055.c
@@ -4,6 +4,7 @@
IEEE 802.11n PHY and radio device data tables
Copyright (c) 2008 Michael Buesch <m@bues.ch>
+ Copyright (c) 2010 Rafał Miłecki <zajec5@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
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c
index 8890df067029..a01f776ca4de 100644
--- a/drivers/net/wireless/b43/radio_2056.c
+++ b/drivers/net/wireless/b43/radio_2056.c
@@ -3,6 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n 2056 radio device data tables
+ Copyright (c) 2010 Rafał Miłecki <zajec5@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
diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h
index d52df6be705a..a7159d8578be 100644
--- a/drivers/net/wireless/b43/radio_2056.h
+++ b/drivers/net/wireless/b43/radio_2056.h
@@ -1,29 +1,3 @@
-/*
-
- Broadcom B43 wireless driver
-
- Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
-
- Some parts of the code in this file are derived from the brcm80211
- driver Copyright (c) 2010 Broadcom Corporation
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
-*/
-
#ifndef B43_RADIO_2056_H_
#define B43_RADIO_2056_H_
diff --git a/drivers/net/wireless/b43/radio_2059.c b/drivers/net/wireless/b43/radio_2059.c
index f029f6e1f5d1..d4ce8a12ff9a 100644
--- a/drivers/net/wireless/b43/radio_2059.c
+++ b/drivers/net/wireless/b43/radio_2059.c
@@ -3,6 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n 2059 radio device data tables
+ Copyright (c) 2011 Rafał Miłecki <zajec5@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
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 916f238a71df..7b326f2efdc9 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -4,6 +4,7 @@
IEEE 802.11n PHY data tables
Copyright (c) 2008 Michael Buesch <m@bues.ch>
+ Copyright (c) 2010 Rafał Miłecki <zajec5@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
diff --git a/drivers/net/wireless/b43/tables_phy_ht.c b/drivers/net/wireless/b43/tables_phy_ht.c
index 603938657b15..176c49d74ef4 100644
--- a/drivers/net/wireless/b43/tables_phy_ht.c
+++ b/drivers/net/wireless/b43/tables_phy_ht.c
@@ -3,6 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n HT-PHY data tables
+ Copyright (c) 2011 Rafał Miłecki <zajec5@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
@@ -574,6 +576,42 @@ static const u32 b43_httab_0x24[] = {
0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
};
+/* Some late-init table */
+const u32 b43_httab_0x1a_0xc0_late[] = {
+ 0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d,
+ 0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b,
+ 0x1091003b, 0x1089003a, 0x1081003a, 0x10790039,
+ 0x10710039, 0x1069003a, 0x1061003b, 0x1059003d,
+ 0x1051003f, 0x10490042, 0x1049003e, 0x1049003b,
+ 0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b,
+ 0x10390038, 0x10390035, 0x1031003a, 0x10310036,
+ 0x10310033, 0x1029003a, 0x10290037, 0x10290034,
+ 0x10290031, 0x10210039, 0x10210036, 0x10210033,
+ 0x10210030, 0x1019003c, 0x10190039, 0x10190036,
+ 0x10190033, 0x10190030, 0x1019002d, 0x1019002b,
+ 0x10190028, 0x1011003a, 0x10110036, 0x10110033,
+ 0x10110030, 0x1011002e, 0x1011002b, 0x10110029,
+ 0x10110027, 0x10110024, 0x10110022, 0x10110020,
+ 0x1011001f, 0x1011001d, 0x1009003a, 0x10090037,
+ 0x10090034, 0x10090031, 0x1009002e, 0x1009002c,
+ 0x10090029, 0x10090027, 0x10090025, 0x10090023,
+ 0x10090021, 0x1009001f, 0x1009001d, 0x1009001b,
+ 0x1009001a, 0x10090018, 0x10090017, 0x10090016,
+ 0x10090015, 0x10090013, 0x10090012, 0x10090011,
+ 0x10090010, 0x1009000f, 0x1009000f, 0x1009000e,
+ 0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b,
+ 0x1009000a, 0x1009000a, 0x10090009, 0x10090009,
+ 0x10090008, 0x10090008, 0x10090007, 0x10090007,
+ 0x10090007, 0x10090006, 0x10090006, 0x10090005,
+ 0x10090005, 0x10090005, 0x10090005, 0x10090004,
+ 0x10090004, 0x10090004, 0x10090004, 0x10090003,
+ 0x10090003, 0x10090003, 0x10090003, 0x10090003,
+ 0x10090003, 0x10090002, 0x10090002, 0x10090002,
+ 0x10090002, 0x10090002, 0x10090002, 0x10090002,
+ 0x10090002, 0x10090002, 0x10090001, 0x10090001,
+ 0x10090001, 0x10090001, 0x10090001, 0x10090001,
+};
+
/**************************************************
* R/W ops.
**************************************************/
@@ -674,6 +712,51 @@ void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value)
return;
}
+void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...)
+{
+ va_list args;
+ u32 type, value;
+ unsigned int i;
+
+ type = offset & B43_HTTAB_TYPEMASK;
+ offset &= 0xFFFF;
+
+ va_start(args, num);
+ switch (type) {
+ case B43_HTTAB_8BIT:
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ for (i = 0; i < num; i++) {
+ value = va_arg(args, int);
+ B43_WARN_ON(value & ~0xFF);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+ }
+ break;
+ case B43_HTTAB_16BIT:
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ for (i = 0; i < num; i++) {
+ value = va_arg(args, int);
+ B43_WARN_ON(value & ~0xFFFF);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+ }
+ break;
+ case B43_HTTAB_32BIT:
+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+ for (i = 0; i < num; i++) {
+ value = va_arg(args, int);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI,
+ value >> 16);
+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO,
+ value & 0xFFFF);
+ }
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+ va_end(args);
+
+ return;
+}
+
void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data)
{
@@ -723,6 +806,9 @@ void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
} while (0)
void b43_phy_ht_tables_init(struct b43_wldev *dev)
{
+ BUILD_BUG_ON(ARRAY_SIZE(b43_httab_0x1a_0xc0_late) !=
+ B43_HTTAB_1A_C0_LATE_SIZE);
+
httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12);
httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27);
httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26);
diff --git a/drivers/net/wireless/b43/tables_phy_ht.h b/drivers/net/wireless/b43/tables_phy_ht.h
index ea3be382c894..1b5ef2bc770c 100644
--- a/drivers/net/wireless/b43/tables_phy_ht.h
+++ b/drivers/net/wireless/b43/tables_phy_ht.h
@@ -14,9 +14,13 @@ u32 b43_httab_read(struct b43_wldev *dev, u32 offset);
void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *_data);
void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value);
+void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...);
void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data);
void b43_phy_ht_tables_init(struct b43_wldev *dev);
+#define B43_HTTAB_1A_C0_LATE_SIZE 128
+extern const u32 b43_httab_0x1a_0xc0_late[];
+
#endif /* B43_TABLES_PHY_HT_H_ */
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c
index 40c1d0915dd3..5176363cadf2 100644
--- a/drivers/net/wireless/b43/tables_phy_lcn.c
+++ b/drivers/net/wireless/b43/tables_phy_lcn.c
@@ -3,6 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n LCN-PHY data tables
+ Copyright (c) 2011 Rafał Miłecki <zajec5@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
@@ -25,10 +27,698 @@
#include "phy_common.h"
#include "phy_lcn.h"
+struct b43_lcntab_tx_gain_tbl_entry {
+ u8 gm;
+ u8 pga;
+ u8 pad;
+ u8 dac;
+ u8 bb_mult;
+};
+
+/**************************************************
+ * Static tables.
+ **************************************************/
+
+static const u16 b43_lcntab_0x02[] = {
+ 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+ 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+ 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+ 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+ 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+ 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+ 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+ 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+ 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+ 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+ 0x014d, 0x014d, 0x014d, 0x014d,
+};
+
+static const u16 b43_lcntab_0x01[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const u32 b43_lcntab_0x0b[] = {
+ 0x000141f8, 0x000021f8, 0x000021fb, 0x000041fb,
+ 0x0001fedb, 0x0000217b, 0x00002133, 0x000040eb,
+ 0x0001fea3, 0x0000024b,
+};
+
+static const u32 b43_lcntab_0x0c[] = {
+ 0x00100001, 0x00200010, 0x00300001, 0x00400010,
+ 0x00500022, 0x00600122, 0x00700222, 0x00800322,
+ 0x00900422, 0x00a00522, 0x00b00622, 0x00c00722,
+ 0x00d00822, 0x00f00922, 0x00100a22, 0x00200b22,
+ 0x00300c22, 0x00400d22, 0x00500e22, 0x00600f22,
+};
+
+static const u32 b43_lcntab_0x0d[] = {
+ 0x00000000, 0x00000000, 0x10000000, 0x00000000,
+ 0x20000000, 0x00000000, 0x30000000, 0x00000000,
+ 0x40000000, 0x00000000, 0x50000000, 0x00000000,
+ 0x60000000, 0x00000000, 0x70000000, 0x00000000,
+ 0x80000000, 0x00000000, 0x90000000, 0x00000008,
+ 0xa0000000, 0x00000008, 0xb0000000, 0x00000008,
+ 0xc0000000, 0x00000008, 0xd0000000, 0x00000008,
+ 0xe0000000, 0x00000008, 0xf0000000, 0x00000008,
+ 0x00000000, 0x00000009, 0x10000000, 0x00000009,
+ 0x20000000, 0x00000019, 0x30000000, 0x00000019,
+ 0x40000000, 0x00000019, 0x50000000, 0x00000019,
+ 0x60000000, 0x00000019, 0x70000000, 0x00000019,
+ 0x80000000, 0x00000019, 0x90000000, 0x00000019,
+ 0xa0000000, 0x00000019, 0xb0000000, 0x00000019,
+ 0xc0000000, 0x00000019, 0xd0000000, 0x00000019,
+ 0xe0000000, 0x00000019, 0xf0000000, 0x00000019,
+ 0x00000000, 0x0000001a, 0x10000000, 0x0000001a,
+ 0x20000000, 0x0000001a, 0x30000000, 0x0000001a,
+ 0x40000000, 0x0000001a, 0x50000000, 0x00000002,
+ 0x60000000, 0x00000002, 0x70000000, 0x00000002,
+ 0x80000000, 0x00000002, 0x90000000, 0x00000002,
+ 0xa0000000, 0x00000002, 0xb0000000, 0x00000002,
+ 0xc0000000, 0x0000000a, 0xd0000000, 0x0000000a,
+ 0xe0000000, 0x0000000a, 0xf0000000, 0x0000000a,
+ 0x00000000, 0x0000000b, 0x10000000, 0x0000000b,
+ 0x20000000, 0x0000000b, 0x30000000, 0x0000000b,
+ 0x40000000, 0x0000000b, 0x50000000, 0x0000001b,
+ 0x60000000, 0x0000001b, 0x70000000, 0x0000001b,
+ 0x80000000, 0x0000001b, 0x90000000, 0x0000001b,
+ 0xa0000000, 0x0000001b, 0xb0000000, 0x0000001b,
+ 0xc0000000, 0x0000001b, 0xd0000000, 0x0000001b,
+ 0xe0000000, 0x0000001b, 0xf0000000, 0x0000001b,
+ 0x00000000, 0x0000001c, 0x10000000, 0x0000001c,
+ 0x20000000, 0x0000001c, 0x30000000, 0x0000001c,
+ 0x40000000, 0x0000001c, 0x50000000, 0x0000001c,
+ 0x60000000, 0x0000001c, 0x70000000, 0x0000001c,
+ 0x80000000, 0x0000001c, 0x90000000, 0x0000001c,
+};
+
+static const u16 b43_lcntab_0x0e[] = {
+ 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406,
+ 0x0407, 0x0408, 0x0409, 0x040a, 0x058b, 0x058c,
+ 0x058d, 0x058e, 0x058f, 0x0090, 0x0091, 0x0092,
+ 0x0193, 0x0194, 0x0195, 0x0196, 0x0197, 0x0198,
+ 0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e,
+ 0x019f, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 0x01a4,
+ 0x01a5, 0x0000,
+};
+
+static const u16 b43_lcntab_0x0f[] = {
+ 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,
+ 0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
+ 0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
+ 0x000a, 0x0009, 0x0006, 0x0005,
+};
+
+static const u16 b43_lcntab_0x10[] = {
+ 0x005f, 0x0036, 0x0029, 0x001f, 0x005f, 0x0036,
+ 0x0029, 0x001f, 0x005f, 0x0036, 0x0029, 0x001f,
+ 0x005f, 0x0036, 0x0029, 0x001f,
+};
+
+static const u16 b43_lcntab_0x11[] = {
+ 0x0009, 0x000f, 0x0014, 0x0018, 0x00fe, 0x0007,
+ 0x000b, 0x000f, 0x00fb, 0x00fe, 0x0001, 0x0005,
+ 0x0008, 0x000b, 0x000e, 0x0011, 0x0014, 0x0017,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f,
+ 0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003,
+ 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015,
+ 0x0018, 0x001b, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0003, 0x00eb, 0x0000, 0x0000,
+};
+
+static const u32 b43_lcntab_0x12[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000004, 0x00000000, 0x00000004, 0x00000008,
+ 0x00000001, 0x00000005, 0x00000009, 0x0000000d,
+ 0x0000004d, 0x0000008d, 0x0000000d, 0x0000004d,
+ 0x0000008d, 0x000000cd, 0x0000004f, 0x0000008f,
+ 0x000000cf, 0x000000d3, 0x00000113, 0x00000513,
+ 0x00000913, 0x00000953, 0x00000d53, 0x00001153,
+ 0x00001193, 0x00005193, 0x00009193, 0x0000d193,
+ 0x00011193, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000004,
+ 0x00000000, 0x00000004, 0x00000008, 0x00000001,
+ 0x00000005, 0x00000009, 0x0000000d, 0x0000004d,
+ 0x0000008d, 0x0000000d, 0x0000004d, 0x0000008d,
+ 0x000000cd, 0x0000004f, 0x0000008f, 0x000000cf,
+ 0x000000d3, 0x00000113, 0x00000513, 0x00000913,
+ 0x00000953, 0x00000d53, 0x00001153, 0x00005153,
+ 0x00009153, 0x0000d153, 0x00011153, 0x00015153,
+ 0x00019153, 0x0001d153, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u16 b43_lcntab_0x14[] = {
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0002, 0x0003, 0x0001, 0x0003, 0x0002, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0003,
+ 0x0001, 0x0003, 0x0002, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001,
+};
+
+static const u16 b43_lcntab_0x17[] = {
+ 0x001a, 0x0034, 0x004e, 0x0068, 0x009c, 0x00d0,
+ 0x00ea, 0x0104, 0x0034, 0x0068, 0x009c, 0x00d0,
+ 0x0138, 0x01a0, 0x01d4, 0x0208, 0x004e, 0x009c,
+ 0x00ea, 0x0138, 0x01d4, 0x0270, 0x02be, 0x030c,
+ 0x0068, 0x00d0, 0x0138, 0x01a0, 0x0270, 0x0340,
+ 0x03a8, 0x0410, 0x0018, 0x009c, 0x00d0, 0x0104,
+ 0x00ea, 0x0138, 0x0186, 0x00d0, 0x0104, 0x0104,
+ 0x0138, 0x016c, 0x016c, 0x01a0, 0x0138, 0x0186,
+ 0x0186, 0x01d4, 0x0222, 0x0222, 0x0270, 0x0104,
+ 0x0138, 0x016c, 0x0138, 0x016c, 0x01a0, 0x01d4,
+ 0x01a0, 0x01d4, 0x0208, 0x0208, 0x023c, 0x0186,
+ 0x01d4, 0x0222, 0x01d4, 0x0222, 0x0270, 0x02be,
+ 0x0270, 0x02be, 0x030c, 0x030c, 0x035a, 0x0036,
+ 0x006c, 0x00a2, 0x00d8, 0x0144, 0x01b0, 0x01e6,
+ 0x021c, 0x006c, 0x00d8, 0x0144, 0x01b0, 0x0288,
+ 0x0360, 0x03cc, 0x0438, 0x00a2, 0x0144, 0x01e6,
+ 0x0288, 0x03cc, 0x0510, 0x05b2, 0x0654, 0x00d8,
+ 0x01b0, 0x0288, 0x0360, 0x0510, 0x06c0, 0x0798,
+ 0x0870, 0x0018, 0x0144, 0x01b0, 0x021c, 0x01e6,
+ 0x0288, 0x032a, 0x01b0, 0x021c, 0x021c, 0x0288,
+ 0x02f4, 0x02f4, 0x0360, 0x0288, 0x032a, 0x032a,
+ 0x03cc, 0x046e, 0x046e, 0x0510, 0x021c, 0x0288,
+ 0x02f4, 0x0288, 0x02f4, 0x0360, 0x03cc, 0x0360,
+ 0x03cc, 0x0438, 0x0438, 0x04a4, 0x032a, 0x03cc,
+ 0x046e, 0x03cc, 0x046e, 0x0510, 0x05b2, 0x0510,
+ 0x05b2, 0x0654, 0x0654, 0x06f6,
+};
+
+static const u16 b43_lcntab_0x00[] = {
+ 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00,
+ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005,
+ 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
+ 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003,
+ 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007,
+ 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const u32 b43_lcntab_0x18[] = {
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+ 0x00080000, 0x00080000, 0x00080000, 0x00080000,
+};
+
+/**************************************************
+ * TX gain.
+ **************************************************/
+
+const struct b43_lcntab_tx_gain_tbl_entry
+ b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = {
+ { 0x03, 0x00, 0x1f, 0x0, 0x48 },
+ { 0x03, 0x00, 0x1f, 0x0, 0x46 },
+ { 0x03, 0x00, 0x1f, 0x0, 0x44 },
+ { 0x03, 0x00, 0x1e, 0x0, 0x43 },
+ { 0x03, 0x00, 0x1d, 0x0, 0x44 },
+ { 0x03, 0x00, 0x1c, 0x0, 0x44 },
+ { 0x03, 0x00, 0x1b, 0x0, 0x45 },
+ { 0x03, 0x00, 0x1a, 0x0, 0x46 },
+ { 0x03, 0x00, 0x19, 0x0, 0x46 },
+ { 0x03, 0x00, 0x18, 0x0, 0x47 },
+ { 0x03, 0x00, 0x17, 0x0, 0x48 },
+ { 0x03, 0x00, 0x17, 0x0, 0x46 },
+ { 0x03, 0x00, 0x16, 0x0, 0x47 },
+ { 0x03, 0x00, 0x15, 0x0, 0x48 },
+ { 0x03, 0x00, 0x15, 0x0, 0x46 },
+ { 0x03, 0x00, 0x15, 0x0, 0x44 },
+ { 0x03, 0x00, 0x15, 0x0, 0x42 },
+ { 0x03, 0x00, 0x15, 0x0, 0x40 },
+ { 0x03, 0x00, 0x15, 0x0, 0x3f },
+ { 0x03, 0x00, 0x14, 0x0, 0x40 },
+ { 0x03, 0x00, 0x13, 0x0, 0x41 },
+ { 0x03, 0x00, 0x13, 0x0, 0x40 },
+ { 0x03, 0x00, 0x12, 0x0, 0x41 },
+ { 0x03, 0x00, 0x12, 0x0, 0x40 },
+ { 0x03, 0x00, 0x11, 0x0, 0x41 },
+ { 0x03, 0x00, 0x11, 0x0, 0x40 },
+ { 0x03, 0x00, 0x10, 0x0, 0x41 },
+ { 0x03, 0x00, 0x10, 0x0, 0x40 },
+ { 0x03, 0x00, 0x10, 0x0, 0x3e },
+ { 0x03, 0x00, 0x10, 0x0, 0x3c },
+ { 0x03, 0x00, 0x10, 0x0, 0x3a },
+ { 0x03, 0x00, 0x0f, 0x0, 0x3d },
+ { 0x03, 0x00, 0x0f, 0x0, 0x3b },
+ { 0x03, 0x00, 0x0e, 0x0, 0x3d },
+ { 0x03, 0x00, 0x0e, 0x0, 0x3c },
+ { 0x03, 0x00, 0x0e, 0x0, 0x3a },
+ { 0x03, 0x00, 0x0d, 0x0, 0x3c },
+ { 0x03, 0x00, 0x0d, 0x0, 0x3b },
+ { 0x03, 0x00, 0x0c, 0x0, 0x3e },
+ { 0x03, 0x00, 0x0c, 0x0, 0x3c },
+ { 0x03, 0x00, 0x0c, 0x0, 0x3a },
+ { 0x03, 0x00, 0x0b, 0x0, 0x3e },
+ { 0x03, 0x00, 0x0b, 0x0, 0x3c },
+ { 0x03, 0x00, 0x0b, 0x0, 0x3b },
+ { 0x03, 0x00, 0x0b, 0x0, 0x39 },
+ { 0x03, 0x00, 0x0a, 0x0, 0x3d },
+ { 0x03, 0x00, 0x0a, 0x0, 0x3b },
+ { 0x03, 0x00, 0x0a, 0x0, 0x39 },
+ { 0x03, 0x00, 0x09, 0x0, 0x3e },
+ { 0x03, 0x00, 0x09, 0x0, 0x3c },
+ { 0x03, 0x00, 0x09, 0x0, 0x3a },
+ { 0x03, 0x00, 0x09, 0x0, 0x39 },
+ { 0x03, 0x00, 0x08, 0x0, 0x3e },
+ { 0x03, 0x00, 0x08, 0x0, 0x3c },
+ { 0x03, 0x00, 0x08, 0x0, 0x3a },
+ { 0x03, 0x00, 0x08, 0x0, 0x39 },
+ { 0x03, 0x00, 0x08, 0x0, 0x37 },
+ { 0x03, 0x00, 0x07, 0x0, 0x3d },
+ { 0x03, 0x00, 0x07, 0x0, 0x3c },
+ { 0x03, 0x00, 0x07, 0x0, 0x3a },
+ { 0x03, 0x00, 0x07, 0x0, 0x38 },
+ { 0x03, 0x00, 0x07, 0x0, 0x37 },
+ { 0x03, 0x00, 0x06, 0x0, 0x3e },
+ { 0x03, 0x00, 0x06, 0x0, 0x3c },
+ { 0x03, 0x00, 0x06, 0x0, 0x3a },
+ { 0x03, 0x00, 0x06, 0x0, 0x39 },
+ { 0x03, 0x00, 0x06, 0x0, 0x37 },
+ { 0x03, 0x00, 0x06, 0x0, 0x36 },
+ { 0x03, 0x00, 0x06, 0x0, 0x34 },
+ { 0x03, 0x00, 0x05, 0x0, 0x3d },
+ { 0x03, 0x00, 0x05, 0x0, 0x3b },
+ { 0x03, 0x00, 0x05, 0x0, 0x39 },
+ { 0x03, 0x00, 0x05, 0x0, 0x38 },
+ { 0x03, 0x00, 0x05, 0x0, 0x36 },
+ { 0x03, 0x00, 0x05, 0x0, 0x35 },
+ { 0x03, 0x00, 0x05, 0x0, 0x33 },
+ { 0x03, 0x00, 0x04, 0x0, 0x3e },
+ { 0x03, 0x00, 0x04, 0x0, 0x3c },
+ { 0x03, 0x00, 0x04, 0x0, 0x3a },
+ { 0x03, 0x00, 0x04, 0x0, 0x39 },
+ { 0x03, 0x00, 0x04, 0x0, 0x37 },
+ { 0x03, 0x00, 0x04, 0x0, 0x36 },
+ { 0x03, 0x00, 0x04, 0x0, 0x34 },
+ { 0x03, 0x00, 0x04, 0x0, 0x33 },
+ { 0x03, 0x00, 0x04, 0x0, 0x31 },
+ { 0x03, 0x00, 0x04, 0x0, 0x30 },
+ { 0x03, 0x00, 0x04, 0x0, 0x2e },
+ { 0x03, 0x00, 0x03, 0x0, 0x3c },
+ { 0x03, 0x00, 0x03, 0x0, 0x3a },
+ { 0x03, 0x00, 0x03, 0x0, 0x39 },
+ { 0x03, 0x00, 0x03, 0x0, 0x37 },
+ { 0x03, 0x00, 0x03, 0x0, 0x36 },
+ { 0x03, 0x00, 0x03, 0x0, 0x34 },
+ { 0x03, 0x00, 0x03, 0x0, 0x33 },
+ { 0x03, 0x00, 0x03, 0x0, 0x31 },
+ { 0x03, 0x00, 0x03, 0x0, 0x30 },
+ { 0x03, 0x00, 0x03, 0x0, 0x2e },
+ { 0x03, 0x00, 0x03, 0x0, 0x2d },
+ { 0x03, 0x00, 0x03, 0x0, 0x2c },
+ { 0x03, 0x00, 0x03, 0x0, 0x2b },
+ { 0x03, 0x00, 0x03, 0x0, 0x29 },
+ { 0x03, 0x00, 0x02, 0x0, 0x3d },
+ { 0x03, 0x00, 0x02, 0x0, 0x3b },
+ { 0x03, 0x00, 0x02, 0x0, 0x39 },
+ { 0x03, 0x00, 0x02, 0x0, 0x38 },
+ { 0x03, 0x00, 0x02, 0x0, 0x36 },
+ { 0x03, 0x00, 0x02, 0x0, 0x35 },
+ { 0x03, 0x00, 0x02, 0x0, 0x33 },
+ { 0x03, 0x00, 0x02, 0x0, 0x32 },
+ { 0x03, 0x00, 0x02, 0x0, 0x30 },
+ { 0x03, 0x00, 0x02, 0x0, 0x2f },
+ { 0x03, 0x00, 0x02, 0x0, 0x2e },
+ { 0x03, 0x00, 0x02, 0x0, 0x2c },
+ { 0x03, 0x00, 0x02, 0x0, 0x2b },
+ { 0x03, 0x00, 0x02, 0x0, 0x2a },
+ { 0x03, 0x00, 0x02, 0x0, 0x29 },
+ { 0x03, 0x00, 0x02, 0x0, 0x27 },
+ { 0x03, 0x00, 0x02, 0x0, 0x26 },
+ { 0x03, 0x00, 0x02, 0x0, 0x25 },
+ { 0x03, 0x00, 0x02, 0x0, 0x24 },
+ { 0x03, 0x00, 0x02, 0x0, 0x23 },
+ { 0x03, 0x00, 0x02, 0x0, 0x22 },
+ { 0x03, 0x00, 0x02, 0x0, 0x21 },
+ { 0x03, 0x00, 0x02, 0x0, 0x20 },
+ { 0x03, 0x00, 0x01, 0x0, 0x3f },
+ { 0x03, 0x00, 0x01, 0x0, 0x3d },
+ { 0x03, 0x00, 0x01, 0x0, 0x3b },
+ { 0x03, 0x00, 0x01, 0x0, 0x39 },
+};
+
+/**************************************************
+ * SW control.
+ **************************************************/
+
+const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
+ 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+ 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+ 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+ 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+ 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+ 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+ 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+ 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+ 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+ 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+ 0x0002, 0x0008, 0x0004, 0x0001,
+};
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset)
+{
+ u32 type, value;
+
+ type = offset & B43_LCNTAB_TYPEMASK;
+ offset &= ~B43_LCNTAB_TYPEMASK;
+ B43_WARN_ON(offset > 0xFFFF);
+
+ switch (type) {
+ case B43_LCNTAB_8BIT:
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+ value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO) & 0xFF;
+ break;
+ case B43_LCNTAB_16BIT:
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+ value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
+ break;
+ case B43_LCNTAB_32BIT:
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+ value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
+ value |= (b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI) << 16);
+ break;
+ default:
+ B43_WARN_ON(1);
+ value = 0;
+ }
+
+ return value;
+}
+
+void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
+ unsigned int nr_elements, void *_data)
+{
+ u32 type;
+ u8 *data = _data;
+ unsigned int i;
+
+ type = offset & B43_LCNTAB_TYPEMASK;
+ offset &= ~B43_LCNTAB_TYPEMASK;
+ B43_WARN_ON(offset > 0xFFFF);
+
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+
+ for (i = 0; i < nr_elements; i++) {
+ switch (type) {
+ case B43_LCNTAB_8BIT:
+ *data = b43_phy_read(dev,
+ B43_PHY_LCN_TABLE_DATALO) & 0xFF;
+ data++;
+ break;
+ case B43_LCNTAB_16BIT:
+ *((u16 *)data) = b43_phy_read(dev,
+ B43_PHY_LCN_TABLE_DATALO);
+ data += 2;
+ break;
+ case B43_LCNTAB_32BIT:
+ *((u32 *)data) = b43_phy_read(dev,
+ B43_PHY_LCN_TABLE_DATALO);
+ *((u32 *)data) |= (b43_phy_read(dev,
+ B43_PHY_LCN_TABLE_DATAHI) << 16);
+ data += 4;
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+ }
+}
+
+void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value)
+{
+ u32 type;
+
+ type = offset & B43_LCNTAB_TYPEMASK;
+ offset &= 0xFFFF;
+
+ switch (type) {
+ case B43_LCNTAB_8BIT:
+ B43_WARN_ON(value & ~0xFF);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
+ break;
+ case B43_LCNTAB_16BIT:
+ B43_WARN_ON(value & ~0xFFFF);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
+ break;
+ case B43_LCNTAB_32BIT:
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, value >> 16);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value & 0xFFFF);
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+
+ return;
+}
+
+void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset,
+ unsigned int nr_elements, const void *_data)
+{
+ u32 type, value;
+ const u8 *data = _data;
+ unsigned int i;
+
+ type = offset & B43_LCNTAB_TYPEMASK;
+ offset &= ~B43_LCNTAB_TYPEMASK;
+ B43_WARN_ON(offset > 0xFFFF);
+
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+
+ for (i = 0; i < nr_elements; i++) {
+ switch (type) {
+ case B43_LCNTAB_8BIT:
+ value = *data;
+ data++;
+ B43_WARN_ON(value & ~0xFF);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
+ break;
+ case B43_LCNTAB_16BIT:
+ value = *((u16 *)data);
+ data += 2;
+ B43_WARN_ON(value & ~0xFFFF);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
+ break;
+ case B43_LCNTAB_32BIT:
+ value = *((u32 *)data);
+ data += 4;
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI,
+ value >> 16);
+ b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO,
+ value & 0xFFFF);
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+ }
+}
+
/**************************************************
* Tables ops.
**************************************************/
+#define lcntab_upload(dev, offset, data) do { \
+ b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
+ } while (0)
+static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev)
+{
+ lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02);
+ lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01);
+ lcntab_upload(dev, B43_LCNTAB32(0x0b, 0), b43_lcntab_0x0b);
+ lcntab_upload(dev, B43_LCNTAB32(0x0c, 0), b43_lcntab_0x0c);
+ lcntab_upload(dev, B43_LCNTAB32(0x0d, 0), b43_lcntab_0x0d);
+ lcntab_upload(dev, B43_LCNTAB16(0x0e, 0), b43_lcntab_0x0e);
+ lcntab_upload(dev, B43_LCNTAB16(0x0f, 0), b43_lcntab_0x0f);
+ lcntab_upload(dev, B43_LCNTAB16(0x10, 0), b43_lcntab_0x10);
+ lcntab_upload(dev, B43_LCNTAB16(0x11, 0), b43_lcntab_0x11);
+ lcntab_upload(dev, B43_LCNTAB32(0x12, 0), b43_lcntab_0x12);
+ lcntab_upload(dev, B43_LCNTAB16(0x14, 0), b43_lcntab_0x14);
+ lcntab_upload(dev, B43_LCNTAB16(0x17, 0), b43_lcntab_0x17);
+ lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00);
+ lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18);
+}
+
+void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
+ const struct b43_lcntab_tx_gain_tbl_entry *gain_table)
+{
+ u32 i;
+ u32 val;
+
+ u16 pa_gain = 0x70;
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM)
+ pa_gain = 0x10;
+
+ for (i = 0; i < B43_LCNTAB_TX_GAIN_SIZE; i++) {
+ val = ((pa_gain << 24) |
+ (gain_table[i].pad << 16) |
+ (gain_table[i].pga << 8) |
+ gain_table[i].gm);
+ b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0xc0 + i), val);
+
+ /* brcmsmac doesn't maskset, we follow newer wl here */
+ val = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
+ val &= 0x000fffff;
+ val |= ((gain_table[i].dac << 28) |
+ (gain_table[i].bb_mult << 20));
+ b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x140 + i), val);
+ }
+}
+
+/* wlc_lcnphy_load_rfpower */
+static void b43_phy_lcn_load_rfpower(struct b43_wldev *dev)
+{
+ u32 bbmult, rfgain;
+ u8 i;
+
+ for (i = 0; i < 128; i++) {
+ bbmult = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
+ bbmult >>= 20;
+ rfgain = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0xc0 + i));
+
+ /* TODO: calculate value for 0x240 + i table offset
+ * b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), val);
+ */
+ }
+}
+
+/* Not implemented in brcmsmac, noticed in wl in MMIO dump */
+static void b43_phy_lcn_rewrite_rfpower_table(struct b43_wldev *dev)
+{
+ int i;
+ u32 tmp;
+ for (i = 0; i < 128; i++) {
+ tmp = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x240 + i));
+ b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), tmp);
+ }
+}
+
+/* wlc_lcnphy_clear_papd_comptable */
+static void b43_phy_lcn_clean_papd_comp_table(struct b43_wldev *dev)
+{
+ u8 i;
+
+ for (i = 0; i < 0x80; i++)
+ b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000);
+}
+
+/* wlc_lcnphy_tbl_init */
void b43_phy_lcn_tables_init(struct b43_wldev *dev)
{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+ b43_phy_lcn_upload_static_tables(dev);
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ if (sprom->boardflags_lo & B43_BFL_FEM)
+ b43_phy_lcn_load_tx_gain_tab(dev,
+ b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0);
+ else
+ b43err(dev->wl,
+ "TX gain table unknown for this card\n");
+ }
+
+ if (sprom->boardflags_lo & B43_BFL_FEM &&
+ !(sprom->boardflags_hi & B43_BFH_FEM_BT))
+ b43_lcntab_write_bulk(dev, B43_LCNTAB16(0xf, 0),
+ ARRAY_SIZE(b43_lcntab_sw_ctl_4313_epa_rev0),
+ b43_lcntab_sw_ctl_4313_epa_rev0);
+ else
+ b43err(dev->wl, "SW ctl table is unknown for this card\n");
+
+ b43_phy_lcn_load_rfpower(dev);
+ b43_phy_lcn_rewrite_rfpower_table(dev);
+ b43_phy_lcn_clean_papd_comp_table(dev);
}
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.h b/drivers/net/wireless/b43/tables_phy_lcn.h
index 5e31b15b81ec..caff9db6831f 100644
--- a/drivers/net/wireless/b43/tables_phy_lcn.h
+++ b/drivers/net/wireless/b43/tables_phy_lcn.h
@@ -1,6 +1,24 @@
#ifndef B43_TABLES_PHY_LCN_H_
#define B43_TABLES_PHY_LCN_H_
+/* The LCN-PHY tables. */
+#define B43_LCNTAB_TYPEMASK 0xF0000000
+#define B43_LCNTAB_8BIT 0x10000000
+#define B43_LCNTAB_16BIT 0x20000000
+#define B43_LCNTAB_32BIT 0x30000000
+#define B43_LCNTAB8(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_8BIT)
+#define B43_LCNTAB16(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_16BIT)
+#define B43_LCNTAB32(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_32BIT)
+
+#define B43_LCNTAB_TX_GAIN_SIZE 128
+
+u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset);
+void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
+ unsigned int nr_elements, void *_data);
+void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value);
+void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset,
+ unsigned int nr_elements, const void *_data);
+
void b43_phy_lcn_tables_init(struct b43_wldev *dev);
#endif /* B43_TABLES_PHY_LCN_H_ */
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index b74f25ec1ab4..c73e8600d218 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -337,12 +337,19 @@ int b43_generate_txhdr(struct b43_wldev *dev,
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
}
}
- if (b43_is_old_txhdr_format(dev)) {
- b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp),
plcp_fragment_len, rate);
- } else {
- b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp),
+ break;
+ case B43_FW_HDR_351:
+ b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp),
+ plcp_fragment_len, rate);
+ break;
+ case B43_FW_HDR_410:
+ b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp),
plcp_fragment_len, rate);
+ break;
}
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
plcp_fragment_len, rate_fb);
@@ -415,10 +422,10 @@ int b43_generate_txhdr(struct b43_wldev *dev,
if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
(rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
unsigned int len;
- struct ieee80211_hdr *hdr;
+ struct ieee80211_hdr *uninitialized_var(hdr);
int rts_rate, rts_rate_fb;
int rts_rate_ofdm, rts_rate_fb_ofdm;
- struct b43_plcp_hdr6 *plcp;
+ struct b43_plcp_hdr6 *uninitialized_var(plcp);
struct ieee80211_rate *rts_cts_rate;
rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
@@ -429,14 +436,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,
rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
- struct ieee80211_cts *cts;
+ struct ieee80211_cts *uninitialized_var(cts);
- if (b43_is_old_txhdr_format(dev)) {
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
cts = (struct ieee80211_cts *)
- (txhdr->old_format.rts_frame);
- } else {
+ (txhdr->format_598.rts_frame);
+ break;
+ case B43_FW_HDR_351:
cts = (struct ieee80211_cts *)
- (txhdr->new_format.rts_frame);
+ (txhdr->format_351.rts_frame);
+ break;
+ case B43_FW_HDR_410:
+ cts = (struct ieee80211_cts *)
+ (txhdr->format_410.rts_frame);
+ break;
}
ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
fragment_data, fragment_len,
@@ -444,14 +458,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,
mac_ctl |= B43_TXH_MAC_SENDCTS;
len = sizeof(struct ieee80211_cts);
} else {
- struct ieee80211_rts *rts;
+ struct ieee80211_rts *uninitialized_var(rts);
- if (b43_is_old_txhdr_format(dev)) {
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
rts = (struct ieee80211_rts *)
- (txhdr->old_format.rts_frame);
- } else {
+ (txhdr->format_598.rts_frame);
+ break;
+ case B43_FW_HDR_351:
rts = (struct ieee80211_rts *)
- (txhdr->new_format.rts_frame);
+ (txhdr->format_351.rts_frame);
+ break;
+ case B43_FW_HDR_410:
+ rts = (struct ieee80211_rts *)
+ (txhdr->format_410.rts_frame);
+ break;
}
ieee80211_rts_get(dev->wl->hw, info->control.vif,
fragment_data, fragment_len,
@@ -462,22 +483,36 @@ int b43_generate_txhdr(struct b43_wldev *dev,
len += FCS_LEN;
/* Generate the PLCP headers for the RTS/CTS frame */
- if (b43_is_old_txhdr_format(dev))
- plcp = &txhdr->old_format.rts_plcp;
- else
- plcp = &txhdr->new_format.rts_plcp;
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ plcp = &txhdr->format_598.rts_plcp;
+ break;
+ case B43_FW_HDR_351:
+ plcp = &txhdr->format_351.rts_plcp;
+ break;
+ case B43_FW_HDR_410:
+ plcp = &txhdr->format_410.rts_plcp;
+ break;
+ }
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
len, rts_rate);
plcp = &txhdr->rts_plcp_fb;
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
len, rts_rate_fb);
- if (b43_is_old_txhdr_format(dev)) {
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
hdr = (struct ieee80211_hdr *)
- (&txhdr->old_format.rts_frame);
- } else {
+ (&txhdr->format_598.rts_frame);
+ break;
+ case B43_FW_HDR_351:
hdr = (struct ieee80211_hdr *)
- (&txhdr->new_format.rts_frame);
+ (&txhdr->format_351.rts_frame);
+ break;
+ case B43_FW_HDR_410:
+ hdr = (struct ieee80211_hdr *)
+ (&txhdr->format_410.rts_frame);
+ break;
}
txhdr->rts_dur_fb = hdr->duration_id;
@@ -505,10 +540,17 @@ int b43_generate_txhdr(struct b43_wldev *dev,
}
/* Magic cookie */
- if (b43_is_old_txhdr_format(dev))
- txhdr->old_format.cookie = cpu_to_le16(cookie);
- else
- txhdr->new_format.cookie = cpu_to_le16(cookie);
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ txhdr->format_598.cookie = cpu_to_le16(cookie);
+ break;
+ case B43_FW_HDR_351:
+ txhdr->format_351.cookie = cpu_to_le16(cookie);
+ break;
+ case B43_FW_HDR_410:
+ txhdr->format_410.cookie = cpu_to_le16(cookie);
+ break;
+ }
if (phy->type == B43_PHYTYPE_N) {
txhdr->phy_ctl1 =
@@ -611,8 +653,9 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
struct ieee80211_hdr *wlhdr;
const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
__le16 fctl;
- u16 phystat0, phystat3, chanstat, mactime;
- u32 macstat;
+ u16 phystat0, phystat3;
+ u16 uninitialized_var(chanstat), uninitialized_var(mactime);
+ u32 uninitialized_var(macstat);
u16 chanid;
u16 phytype;
int padding;
@@ -622,9 +665,19 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
/* Get metadata about the frame from the header. */
phystat0 = le16_to_cpu(rxhdr->phy_status0);
phystat3 = le16_to_cpu(rxhdr->phy_status3);
- macstat = le32_to_cpu(rxhdr->mac_status);
- mactime = le16_to_cpu(rxhdr->mac_time);
- chanstat = le16_to_cpu(rxhdr->channel);
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ macstat = le32_to_cpu(rxhdr->format_598.mac_status);
+ mactime = le16_to_cpu(rxhdr->format_598.mac_time);
+ chanstat = le16_to_cpu(rxhdr->format_598.channel);
+ break;
+ case B43_FW_HDR_410:
+ case B43_FW_HDR_351:
+ macstat = le32_to_cpu(rxhdr->format_351.mac_status);
+ mactime = le16_to_cpu(rxhdr->format_351.mac_time);
+ chanstat = le16_to_cpu(rxhdr->format_351.channel);
+ break;
+ }
phytype = chanstat & B43_RX_CHAN_PHYTYPE;
if (unlikely(macstat & B43_RX_MAC_FCSERR)) {
@@ -682,16 +735,22 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
}
/* Link quality statistics */
- if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
-// s8 rssi = max(rxhdr->power0, rxhdr->power1);
- //TODO: Find out what the rssi value is (dBm or percentage?)
- // and also find out what the maximum possible value is.
- // Fill status.ssi and status.signal fields.
- } else {
+ switch (chanstat & B43_RX_CHAN_PHYTYPE) {
+ case B43_PHYTYPE_N:
+ if (rxhdr->power0 == 16 || rxhdr->power0 == 32)
+ status.signal = max(rxhdr->power1, rxhdr->power2);
+ else
+ status.signal = max(rxhdr->power0, rxhdr->power1);
+ break;
+ case B43_PHYTYPE_A:
+ case B43_PHYTYPE_B:
+ case B43_PHYTYPE_G:
+ case B43_PHYTYPE_LP:
status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
(phystat0 & B43_RX_PHYST0_OFDM),
(phystat0 & B43_RX_PHYST0_GAINCTL),
(phystat3 & B43_RX_PHYST3_TRSTATE));
+ break;
}
if (phystat0 & B43_RX_PHYST0_OFDM)
@@ -744,6 +803,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
break;
case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
+ case B43_PHYTYPE_HT:
/* chanid is the SHM channel cookie. Which is the plain
* channel number in b43. */
if (chanstat & B43_RX_CHAN_5GHZ) {
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index 42debb5cd6fa..16c514d54afa 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -46,7 +46,24 @@ struct b43_txhdr {
__le32 timeout; /* Timeout */
union {
- /* The new r410 format. */
+ /* Tested with 598.314, 644.1001 and 666.2 */
+ struct {
+ __le16 mimo_antenna; /* MIMO antenna select */
+ __le16 preload_size; /* Preload size */
+ PAD_BYTES(2);
+ __le16 cookie; /* TX frame cookie */
+ __le16 tx_status; /* TX status */
+ __le16 max_n_mpdus;
+ __le16 max_a_bytes_mrt;
+ __le16 max_a_bytes_fbr;
+ __le16 min_m_bytes;
+ struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */
+ __u8 rts_frame[16]; /* The RTS frame (if used) */
+ PAD_BYTES(2);
+ struct b43_plcp_hdr6 plcp; /* Main PLCP header */
+ } format_598 __packed;
+
+ /* Tested with 410.2160, 478.104 and 508.* */
struct {
__le16 mimo_antenna; /* MIMO antenna select */
__le16 preload_size; /* Preload size */
@@ -57,9 +74,9 @@ struct b43_txhdr {
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
- } new_format __packed;
+ } format_410 __packed;
- /* The old r351 format. */
+ /* Tested with 351.126 */
struct {
PAD_BYTES(2);
__le16 cookie; /* TX frame cookie */
@@ -68,7 +85,7 @@ struct b43_txhdr {
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
- } old_format __packed;
+ } format_351 __packed;
} __packed;
} __packed;
@@ -166,19 +183,18 @@ struct b43_tx_legacy_rate_phy_ctl_entry {
#define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */
-/* r351 firmware compatibility stuff. */
-static inline
-bool b43_is_old_txhdr_format(struct b43_wldev *dev)
-{
- return (dev->fw.rev <= 351);
-}
-
static inline
size_t b43_txhdr_size(struct b43_wldev *dev)
{
- if (b43_is_old_txhdr_format(dev))
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
+ return 112 + sizeof(struct b43_plcp_hdr6);
+ case B43_FW_HDR_410:
+ return 104 + sizeof(struct b43_plcp_hdr6);
+ case B43_FW_HDR_351:
return 100 + sizeof(struct b43_plcp_hdr6);
- return 104 + sizeof(struct b43_plcp_hdr6);
+ }
+ return 0;
}
@@ -232,11 +248,33 @@ struct b43_rxhdr_fw4 {
__s8 power1; /* PHY RX Status 1: Power 1 */
} __packed;
} __packed;
- __le16 phy_status2; /* PHY RX Status 2 */
+ union {
+ /* RSSI for N-PHYs */
+ struct {
+ __s8 power2;
+ PAD_BYTES(1);
+ } __packed;
+
+ __le16 phy_status2; /* PHY RX Status 2 */
+ } __packed;
__le16 phy_status3; /* PHY RX Status 3 */
- __le32 mac_status; /* MAC RX status */
- __le16 mac_time;
- __le16 channel;
+ union {
+ /* Tested with 598.314, 644.1001 and 666.2 */
+ struct {
+ __le16 phy_status4; /* PHY RX Status 4 */
+ __le16 phy_status5; /* PHY RX Status 5 */
+ __le32 mac_status; /* MAC RX status */
+ __le16 mac_time;
+ __le16 channel;
+ } format_598 __packed;
+
+ /* Tested with 351.126, 410.2160, 478.104 and 508.* */
+ struct {
+ __le32 mac_status; /* MAC RX status */
+ __le16 mac_time;
+ __le16 channel;
+ } format_351 __packed;
+ } __packed;
} __packed;
/* PHY RX Status 0 */
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index a610a352102a..1d4fc9db7f5e 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -14,7 +14,6 @@
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_driver_chipcommon.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include "debugfs.h"
@@ -23,10 +22,6 @@
#include "phy.h"
-/* The unique identifier of the firmware that's officially supported by this
- * driver version. */
-#define B43legacy_SUPPORTED_FIRMWARE_ID "FW10"
-
#define B43legacy_IRQWAIT_MAX_RETRIES 20
/* MMIO offsets */
@@ -815,15 +810,15 @@ struct b43legacy_lopair *b43legacy_get_lopair(struct b43legacy_phy *phy,
/* Message printing */
-void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
+__printf(2, 3)
+void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...);
+__printf(2, 3)
+void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...);
+__printf(2, 3)
+void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...);
#if B43legacy_DEBUG
-void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
+__printf(2, 3)
+void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...);
#else /* DEBUG */
# define b43legacydbg(wl, fmt...) do { /* nothing */ } while (0)
#endif /* DEBUG */
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index 5010c477abdf..c5535adf6991 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -42,10 +42,9 @@
/* 32bit DMA ops. */
static
-struct b43legacy_dmadesc_generic *op32_idx2desc(
- struct b43legacy_dmaring *ring,
- int slot,
- struct b43legacy_dmadesc_meta **meta)
+struct b43legacy_dmadesc32 *op32_idx2desc(struct b43legacy_dmaring *ring,
+ int slot,
+ struct b43legacy_dmadesc_meta **meta)
{
struct b43legacy_dmadesc32 *desc;
@@ -53,11 +52,11 @@ struct b43legacy_dmadesc_generic *op32_idx2desc(
desc = ring->descbase;
desc = &(desc[slot]);
- return (struct b43legacy_dmadesc_generic *)desc;
+ return (struct b43legacy_dmadesc32 *)desc;
}
static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
+ struct b43legacy_dmadesc32 *desc,
dma_addr_t dmaaddr, u16 bufsize,
int start, int end, int irq)
{
@@ -67,7 +66,7 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
u32 addr;
u32 addrext;
- slot = (int)(&(desc->dma32) - descbase);
+ slot = (int)(desc - descbase);
B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
@@ -87,8 +86,8 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
ctl |= (addrext << B43legacy_DMA32_DCTL_ADDREXT_SHIFT)
& B43legacy_DMA32_DCTL_ADDREXT_MASK;
- desc->dma32.control = cpu_to_le32(ctl);
- desc->dma32.address = cpu_to_le32(addr);
+ desc->control = cpu_to_le32(ctl);
+ desc->address = cpu_to_le32(addr);
}
static void op32_poke_tx(struct b43legacy_dmaring *ring, int slot)
@@ -128,121 +127,6 @@ static void op32_set_current_rxslot(struct b43legacy_dmaring *ring,
(u32)(slot * sizeof(struct b43legacy_dmadesc32)));
}
-static const struct b43legacy_dma_ops dma32_ops = {
- .idx2desc = op32_idx2desc,
- .fill_descriptor = op32_fill_descriptor,
- .poke_tx = op32_poke_tx,
- .tx_suspend = op32_tx_suspend,
- .tx_resume = op32_tx_resume,
- .get_current_rxslot = op32_get_current_rxslot,
- .set_current_rxslot = op32_set_current_rxslot,
-};
-
-/* 64bit DMA ops. */
-static
-struct b43legacy_dmadesc_generic *op64_idx2desc(
- struct b43legacy_dmaring *ring,
- int slot,
- struct b43legacy_dmadesc_meta
- **meta)
-{
- struct b43legacy_dmadesc64 *desc;
-
- *meta = &(ring->meta[slot]);
- desc = ring->descbase;
- desc = &(desc[slot]);
-
- return (struct b43legacy_dmadesc_generic *)desc;
-}
-
-static void op64_fill_descriptor(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
- dma_addr_t dmaaddr, u16 bufsize,
- int start, int end, int irq)
-{
- struct b43legacy_dmadesc64 *descbase = ring->descbase;
- int slot;
- u32 ctl0 = 0;
- u32 ctl1 = 0;
- u32 addrlo;
- u32 addrhi;
- u32 addrext;
-
- slot = (int)(&(desc->dma64) - descbase);
- B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
-
- addrlo = (u32)(dmaaddr & 0xFFFFFFFF);
- addrhi = (((u64)dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
- addrext = (((u64)dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- addrhi |= ring->dev->dma.translation;
- if (slot == ring->nr_slots - 1)
- ctl0 |= B43legacy_DMA64_DCTL0_DTABLEEND;
- if (start)
- ctl0 |= B43legacy_DMA64_DCTL0_FRAMESTART;
- if (end)
- ctl0 |= B43legacy_DMA64_DCTL0_FRAMEEND;
- if (irq)
- ctl0 |= B43legacy_DMA64_DCTL0_IRQ;
- ctl1 |= (bufsize - ring->frameoffset)
- & B43legacy_DMA64_DCTL1_BYTECNT;
- ctl1 |= (addrext << B43legacy_DMA64_DCTL1_ADDREXT_SHIFT)
- & B43legacy_DMA64_DCTL1_ADDREXT_MASK;
-
- desc->dma64.control0 = cpu_to_le32(ctl0);
- desc->dma64.control1 = cpu_to_le32(ctl1);
- desc->dma64.address_low = cpu_to_le32(addrlo);
- desc->dma64.address_high = cpu_to_le32(addrhi);
-}
-
-static void op64_poke_tx(struct b43legacy_dmaring *ring, int slot)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_TXINDEX,
- (u32)(slot * sizeof(struct b43legacy_dmadesc64)));
-}
-
-static void op64_tx_suspend(struct b43legacy_dmaring *ring)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
- b43legacy_dma_read(ring, B43legacy_DMA64_TXCTL)
- | B43legacy_DMA64_TXSUSPEND);
-}
-
-static void op64_tx_resume(struct b43legacy_dmaring *ring)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
- b43legacy_dma_read(ring, B43legacy_DMA64_TXCTL)
- & ~B43legacy_DMA64_TXSUSPEND);
-}
-
-static int op64_get_current_rxslot(struct b43legacy_dmaring *ring)
-{
- u32 val;
-
- val = b43legacy_dma_read(ring, B43legacy_DMA64_RXSTATUS);
- val &= B43legacy_DMA64_RXSTATDPTR;
-
- return (val / sizeof(struct b43legacy_dmadesc64));
-}
-
-static void op64_set_current_rxslot(struct b43legacy_dmaring *ring,
- int slot)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_RXINDEX,
- (u32)(slot * sizeof(struct b43legacy_dmadesc64)));
-}
-
-static const struct b43legacy_dma_ops dma64_ops = {
- .idx2desc = op64_idx2desc,
- .fill_descriptor = op64_fill_descriptor,
- .poke_tx = op64_poke_tx,
- .tx_suspend = op64_tx_suspend,
- .tx_resume = op64_tx_resume,
- .get_current_rxslot = op64_get_current_rxslot,
- .set_current_rxslot = op64_set_current_rxslot,
-};
-
-
static inline int free_slots(struct b43legacy_dmaring *ring)
{
return (ring->nr_slots - ring->used_slots);
@@ -358,14 +242,6 @@ return 0;
static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type,
int controller_idx)
{
- static const u16 map64[] = {
- B43legacy_MMIO_DMA64_BASE0,
- B43legacy_MMIO_DMA64_BASE1,
- B43legacy_MMIO_DMA64_BASE2,
- B43legacy_MMIO_DMA64_BASE3,
- B43legacy_MMIO_DMA64_BASE4,
- B43legacy_MMIO_DMA64_BASE5,
- };
static const u16 map32[] = {
B43legacy_MMIO_DMA32_BASE0,
B43legacy_MMIO_DMA32_BASE1,
@@ -375,11 +251,6 @@ static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type,
B43legacy_MMIO_DMA32_BASE5,
};
- if (type == B43legacy_DMA_64BIT) {
- B43legacy_WARN_ON(!(controller_idx >= 0 &&
- controller_idx < ARRAY_SIZE(map64)));
- return map64[controller_idx];
- }
B43legacy_WARN_ON(!(controller_idx >= 0 &&
controller_idx < ARRAY_SIZE(map32)));
return map32[controller_idx];
@@ -491,25 +362,15 @@ static int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev,
might_sleep();
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_RXCTL : B43legacy_DMA32_RXCTL;
+ offset = B43legacy_DMA32_RXCTL;
b43legacy_write32(dev, mmio_base + offset, 0);
for (i = 0; i < 10; i++) {
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_RXSTATUS : B43legacy_DMA32_RXSTATUS;
+ offset = B43legacy_DMA32_RXSTATUS;
value = b43legacy_read32(dev, mmio_base + offset);
- if (type == B43legacy_DMA_64BIT) {
- value &= B43legacy_DMA64_RXSTAT;
- if (value == B43legacy_DMA64_RXSTAT_DISABLED) {
- i = -1;
- break;
- }
- } else {
- value &= B43legacy_DMA32_RXSTATE;
- if (value == B43legacy_DMA32_RXSTAT_DISABLED) {
- i = -1;
- break;
- }
+ value &= B43legacy_DMA32_RXSTATE;
+ if (value == B43legacy_DMA32_RXSTAT_DISABLED) {
+ i = -1;
+ break;
}
msleep(1);
}
@@ -533,43 +394,24 @@ static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev,
might_sleep();
for (i = 0; i < 10; i++) {
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS;
+ offset = B43legacy_DMA32_TXSTATUS;
value = b43legacy_read32(dev, mmio_base + offset);
- if (type == B43legacy_DMA_64BIT) {
- value &= B43legacy_DMA64_TXSTAT;
- if (value == B43legacy_DMA64_TXSTAT_DISABLED ||
- value == B43legacy_DMA64_TXSTAT_IDLEWAIT ||
- value == B43legacy_DMA64_TXSTAT_STOPPED)
- break;
- } else {
- value &= B43legacy_DMA32_TXSTATE;
- if (value == B43legacy_DMA32_TXSTAT_DISABLED ||
- value == B43legacy_DMA32_TXSTAT_IDLEWAIT ||
- value == B43legacy_DMA32_TXSTAT_STOPPED)
- break;
- }
+ value &= B43legacy_DMA32_TXSTATE;
+ if (value == B43legacy_DMA32_TXSTAT_DISABLED ||
+ value == B43legacy_DMA32_TXSTAT_IDLEWAIT ||
+ value == B43legacy_DMA32_TXSTAT_STOPPED)
+ break;
msleep(1);
}
- offset = (type == B43legacy_DMA_64BIT) ? B43legacy_DMA64_TXCTL :
- B43legacy_DMA32_TXCTL;
+ offset = B43legacy_DMA32_TXCTL;
b43legacy_write32(dev, mmio_base + offset, 0);
for (i = 0; i < 10; i++) {
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS;
+ offset = B43legacy_DMA32_TXSTATUS;
value = b43legacy_read32(dev, mmio_base + offset);
- if (type == B43legacy_DMA_64BIT) {
- value &= B43legacy_DMA64_TXSTAT;
- if (value == B43legacy_DMA64_TXSTAT_DISABLED) {
- i = -1;
- break;
- }
- } else {
- value &= B43legacy_DMA32_TXSTATE;
- if (value == B43legacy_DMA32_TXSTAT_DISABLED) {
- i = -1;
- break;
- }
+ value &= B43legacy_DMA32_TXSTATE;
+ if (value == B43legacy_DMA32_TXSTAT_DISABLED) {
+ i = -1;
+ break;
}
msleep(1);
}
@@ -601,9 +443,6 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
if ((u64)addr + buffersize > (1ULL << 32))
goto address_error;
break;
- case B43legacy_DMA_64BIT:
- /* Currently we can't have addresses beyond 64 bits in the kernel. */
- break;
}
/* The address is OK. */
@@ -617,7 +456,7 @@ address_error:
}
static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
+ struct b43legacy_dmadesc32 *desc,
struct b43legacy_dmadesc_meta *meta,
gfp_t gfp_flags)
{
@@ -653,8 +492,7 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
meta->skb = skb;
meta->dmaaddr = dmaaddr;
- ring->ops->fill_descriptor(ring, desc, dmaaddr,
- ring->rx_buffersize, 0, 0, 0);
+ op32_fill_descriptor(ring, desc, dmaaddr, ring->rx_buffersize, 0, 0, 0);
rxhdr = (struct b43legacy_rxhdr_fw3 *)(skb->data);
rxhdr->frame_len = 0;
@@ -671,11 +509,11 @@ static int alloc_initial_descbuffers(struct b43legacy_dmaring *ring)
{
int i;
int err = -ENOMEM;
- struct b43legacy_dmadesc_generic *desc;
+ struct b43legacy_dmadesc32 *desc;
struct b43legacy_dmadesc_meta *meta;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ desc = op32_idx2desc(ring, i, &meta);
err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
if (err) {
@@ -692,7 +530,7 @@ out:
err_unwind:
for (i--; i >= 0; i--) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ desc = op32_idx2desc(ring, i, &meta);
unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
dev_kfree_skb(meta->skb);
@@ -710,83 +548,35 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring)
u32 value;
u32 addrext;
u32 trans = ring->dev->dma.translation;
+ u32 ringbase = (u32)(ring->dmabase);
if (ring->tx) {
- if (ring->type == B43legacy_DMA_64BIT) {
- u64 ringbase = (u64)(ring->dmabase);
-
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = B43legacy_DMA64_TXENABLE;
- value |= (addrext << B43legacy_DMA64_TXADDREXT_SHIFT)
- & B43legacy_DMA64_TXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI,
- ((ringbase >> 32)
- & ~SSB_DMA_TRANSLATION_MASK)
- | trans);
- } else {
- u32 ringbase = (u32)(ring->dmabase);
-
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = B43legacy_DMA32_TXENABLE;
- value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT)
- & B43legacy_DMA32_TXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA32_TXRING,
- (ringbase &
- ~SSB_DMA_TRANSLATION_MASK)
- | trans);
- }
+ addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
+ >> SSB_DMA_TRANSLATION_SHIFT;
+ value = B43legacy_DMA32_TXENABLE;
+ value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT)
+ & B43legacy_DMA32_TXADDREXT_MASK;
+ b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL, value);
+ b43legacy_dma_write(ring, B43legacy_DMA32_TXRING,
+ (ringbase & ~SSB_DMA_TRANSLATION_MASK)
+ | trans);
} else {
err = alloc_initial_descbuffers(ring);
if (err)
goto out;
- if (ring->type == B43legacy_DMA_64BIT) {
- u64 ringbase = (u64)(ring->dmabase);
-
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = (ring->frameoffset <<
- B43legacy_DMA64_RXFROFF_SHIFT);
- value |= B43legacy_DMA64_RXENABLE;
- value |= (addrext << B43legacy_DMA64_RXADDREXT_SHIFT)
- & B43legacy_DMA64_RXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA64_RXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK) |
- trans);
- b43legacy_dma_write(ring, B43legacy_DMA64_RXINDEX,
- 200);
- } else {
- u32 ringbase = (u32)(ring->dmabase);
-
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = (ring->frameoffset <<
- B43legacy_DMA32_RXFROFF_SHIFT);
- value |= B43legacy_DMA32_RXENABLE;
- value |= (addrext <<
- B43legacy_DMA32_RXADDREXT_SHIFT)
- & B43legacy_DMA32_RXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA32_RXRING,
- (ringbase &
- ~SSB_DMA_TRANSLATION_MASK)
- | trans);
- b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX,
- 200);
- }
+
+ addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
+ >> SSB_DMA_TRANSLATION_SHIFT;
+ value = (ring->frameoffset <<
+ B43legacy_DMA32_RXFROFF_SHIFT);
+ value |= B43legacy_DMA32_RXENABLE;
+ value |= (addrext << B43legacy_DMA32_RXADDREXT_SHIFT)
+ & B43legacy_DMA32_RXADDREXT_MASK;
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL, value);
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXRING,
+ (ringbase & ~SSB_DMA_TRANSLATION_MASK)
+ | trans);
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX, 200);
}
out:
@@ -799,19 +589,11 @@ static void dmacontroller_cleanup(struct b43legacy_dmaring *ring)
if (ring->tx) {
b43legacy_dmacontroller_tx_reset(ring->dev, ring->mmio_base,
ring->type);
- if (ring->type == B43legacy_DMA_64BIT) {
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO, 0);
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI, 0);
- } else
- b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0);
+ b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0);
} else {
b43legacy_dmacontroller_rx_reset(ring->dev, ring->mmio_base,
ring->type);
- if (ring->type == B43legacy_DMA_64BIT) {
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO, 0);
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI, 0);
- } else
- b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0);
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0);
}
}
@@ -823,7 +605,7 @@ static void free_all_descbuffers(struct b43legacy_dmaring *ring)
if (!ring->used_slots)
return;
for (i = 0; i < ring->nr_slots; i++) {
- ring->ops->idx2desc(ring, i, &meta);
+ op32_idx2desc(ring, i, &meta);
if (!meta->skb) {
B43legacy_WARN_ON(!ring->tx);
@@ -844,9 +626,6 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev)
u32 tmp;
u16 mmio_base;
- tmp = b43legacy_read32(dev, SSB_TMSHIGH);
- if (tmp & SSB_TMSHIGH_DMA64)
- return DMA_BIT_MASK(64);
mmio_base = b43legacy_dmacontroller_base(0, 0);
b43legacy_write32(dev,
mmio_base + B43legacy_DMA32_TXCTL,
@@ -865,8 +644,6 @@ static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask)
return B43legacy_DMA_30BIT;
if (dmamask == DMA_BIT_MASK(32))
return B43legacy_DMA_32BIT;
- if (dmamask == DMA_BIT_MASK(64))
- return B43legacy_DMA_64BIT;
B43legacy_WARN_ON(1);
return B43legacy_DMA_30BIT;
}
@@ -937,10 +714,6 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
ring->nr_slots = nr_slots;
ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index);
ring->index = controller_index;
- if (type == B43legacy_DMA_64BIT)
- ring->ops = &dma64_ops;
- else
- ring->ops = &dma32_ops;
if (for_tx) {
ring->tx = 1;
ring->current_slot = -1;
@@ -1247,12 +1020,11 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
struct sk_buff **in_skb)
{
struct sk_buff *skb = *in_skb;
- const struct b43legacy_dma_ops *ops = ring->ops;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 *header;
int slot, old_top_slot, old_used_slots;
int err;
- struct b43legacy_dmadesc_generic *desc;
+ struct b43legacy_dmadesc32 *desc;
struct b43legacy_dmadesc_meta *meta;
struct b43legacy_dmadesc_meta *meta_hdr;
struct sk_buff *bounce_skb;
@@ -1265,7 +1037,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
/* Get a slot for the header. */
slot = request_slot(ring);
- desc = ops->idx2desc(ring, slot, &meta_hdr);
+ desc = op32_idx2desc(ring, slot, &meta_hdr);
memset(meta_hdr, 0, sizeof(*meta_hdr));
header = &(ring->txhdr_cache[slot * sizeof(
@@ -1287,12 +1059,12 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
ring->used_slots = old_used_slots;
return -EIO;
}
- ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr,
+ op32_fill_descriptor(ring, desc, meta_hdr->dmaaddr,
sizeof(struct b43legacy_txhdr_fw3), 1, 0, 0);
/* Get a slot for the payload. */
slot = request_slot(ring);
- desc = ops->idx2desc(ring, slot, &meta);
+ desc = op32_idx2desc(ring, slot, &meta);
memset(meta, 0, sizeof(*meta));
meta->skb = skb;
@@ -1328,12 +1100,12 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
}
}
- ops->fill_descriptor(ring, desc, meta->dmaaddr,
+ op32_fill_descriptor(ring, desc, meta->dmaaddr,
skb->len, 0, 1, 1);
wmb(); /* previous stuff MUST be done */
/* Now transfer the whole frame. */
- ops->poke_tx(ring, next_slot(ring, slot));
+ op32_poke_tx(ring, next_slot(ring, slot));
return 0;
out_free_bounce:
@@ -1429,7 +1201,6 @@ out_unlock:
void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
const struct b43legacy_txstatus *status)
{
- const struct b43legacy_dma_ops *ops;
struct b43legacy_dmaring *ring;
struct b43legacy_dmadesc_meta *meta;
int retry_limit;
@@ -1442,10 +1213,9 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
spin_lock(&ring->lock);
B43legacy_WARN_ON(!ring->tx);
- ops = ring->ops;
while (1) {
B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
- ops->idx2desc(ring, slot, &meta);
+ op32_idx2desc(ring, slot, &meta);
if (meta->skb)
unmap_descbuffer(ring, meta->dmaaddr,
@@ -1528,8 +1298,7 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
static void dma_rx(struct b43legacy_dmaring *ring,
int *slot)
{
- const struct b43legacy_dma_ops *ops = ring->ops;
- struct b43legacy_dmadesc_generic *desc;
+ struct b43legacy_dmadesc32 *desc;
struct b43legacy_dmadesc_meta *meta;
struct b43legacy_rxhdr_fw3 *rxhdr;
struct sk_buff *skb;
@@ -1537,7 +1306,7 @@ static void dma_rx(struct b43legacy_dmaring *ring,
int err;
dma_addr_t dmaaddr;
- desc = ops->idx2desc(ring, *slot, &meta);
+ desc = op32_idx2desc(ring, *slot, &meta);
sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
skb = meta->skb;
@@ -1589,7 +1358,7 @@ static void dma_rx(struct b43legacy_dmaring *ring,
s32 tmp = len;
while (1) {
- desc = ops->idx2desc(ring, *slot, &meta);
+ desc = op32_idx2desc(ring, *slot, &meta);
/* recycle the descriptor buffer. */
sync_descbuffer_for_device(ring, meta->dmaaddr,
ring->rx_buffersize);
@@ -1626,13 +1395,12 @@ drop:
void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
{
- const struct b43legacy_dma_ops *ops = ring->ops;
int slot;
int current_slot;
int used_slots = 0;
B43legacy_WARN_ON(ring->tx);
- current_slot = ops->get_current_rxslot(ring);
+ current_slot = op32_get_current_rxslot(ring);
B43legacy_WARN_ON(!(current_slot >= 0 && current_slot <
ring->nr_slots));
@@ -1641,7 +1409,7 @@ void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
dma_rx(ring, &slot);
update_max_used_slots(ring, ++used_slots);
}
- ops->set_current_rxslot(ring, slot);
+ op32_set_current_rxslot(ring, slot);
ring->current_slot = slot;
}
@@ -1651,7 +1419,7 @@ static void b43legacy_dma_tx_suspend_ring(struct b43legacy_dmaring *ring)
spin_lock_irqsave(&ring->lock, flags);
B43legacy_WARN_ON(!ring->tx);
- ring->ops->tx_suspend(ring);
+ op32_tx_suspend(ring);
spin_unlock_irqrestore(&ring->lock, flags);
}
@@ -1661,7 +1429,7 @@ static void b43legacy_dma_tx_resume_ring(struct b43legacy_dmaring *ring)
spin_lock_irqsave(&ring->lock, flags);
B43legacy_WARN_ON(!ring->tx);
- ring->ops->tx_resume(ring);
+ op32_tx_resume(ring);
spin_unlock_irqrestore(&ring->lock, flags);
}
diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h
index 686941c242fc..504a58767e95 100644
--- a/drivers/net/wireless/b43legacy/dma.h
+++ b/drivers/net/wireless/b43legacy/dma.h
@@ -82,90 +82,6 @@ struct b43legacy_dmadesc32 {
#define B43legacy_DMA32_DCTL_FRAMESTART 0x80000000
-
-/*** 64-bit DMA Engine. ***/
-
-/* 64-bit DMA controller registers. */
-#define B43legacy_DMA64_TXCTL 0x00
-#define B43legacy_DMA64_TXENABLE 0x00000001
-#define B43legacy_DMA64_TXSUSPEND 0x00000002
-#define B43legacy_DMA64_TXLOOPBACK 0x00000004
-#define B43legacy_DMA64_TXFLUSH 0x00000010
-#define B43legacy_DMA64_TXADDREXT_MASK 0x00030000
-#define B43legacy_DMA64_TXADDREXT_SHIFT 16
-#define B43legacy_DMA64_TXINDEX 0x04
-#define B43legacy_DMA64_TXRINGLO 0x08
-#define B43legacy_DMA64_TXRINGHI 0x0C
-#define B43legacy_DMA64_TXSTATUS 0x10
-#define B43legacy_DMA64_TXSTATDPTR 0x00001FFF
-#define B43legacy_DMA64_TXSTAT 0xF0000000
-#define B43legacy_DMA64_TXSTAT_DISABLED 0x00000000
-#define B43legacy_DMA64_TXSTAT_ACTIVE 0x10000000
-#define B43legacy_DMA64_TXSTAT_IDLEWAIT 0x20000000
-#define B43legacy_DMA64_TXSTAT_STOPPED 0x30000000
-#define B43legacy_DMA64_TXSTAT_SUSP 0x40000000
-#define B43legacy_DMA64_TXERROR 0x14
-#define B43legacy_DMA64_TXERRDPTR 0x0001FFFF
-#define B43legacy_DMA64_TXERR 0xF0000000
-#define B43legacy_DMA64_TXERR_NOERR 0x00000000
-#define B43legacy_DMA64_TXERR_PROT 0x10000000
-#define B43legacy_DMA64_TXERR_UNDERRUN 0x20000000
-#define B43legacy_DMA64_TXERR_TRANSFER 0x30000000
-#define B43legacy_DMA64_TXERR_DESCREAD 0x40000000
-#define B43legacy_DMA64_TXERR_CORE 0x50000000
-#define B43legacy_DMA64_RXCTL 0x20
-#define B43legacy_DMA64_RXENABLE 0x00000001
-#define B43legacy_DMA64_RXFROFF_MASK 0x000000FE
-#define B43legacy_DMA64_RXFROFF_SHIFT 1
-#define B43legacy_DMA64_RXDIRECTFIFO 0x00000100
-#define B43legacy_DMA64_RXADDREXT_MASK 0x00030000
-#define B43legacy_DMA64_RXADDREXT_SHIFT 16
-#define B43legacy_DMA64_RXINDEX 0x24
-#define B43legacy_DMA64_RXRINGLO 0x28
-#define B43legacy_DMA64_RXRINGHI 0x2C
-#define B43legacy_DMA64_RXSTATUS 0x30
-#define B43legacy_DMA64_RXSTATDPTR 0x00001FFF
-#define B43legacy_DMA64_RXSTAT 0xF0000000
-#define B43legacy_DMA64_RXSTAT_DISABLED 0x00000000
-#define B43legacy_DMA64_RXSTAT_ACTIVE 0x10000000
-#define B43legacy_DMA64_RXSTAT_IDLEWAIT 0x20000000
-#define B43legacy_DMA64_RXSTAT_STOPPED 0x30000000
-#define B43legacy_DMA64_RXSTAT_SUSP 0x40000000
-#define B43legacy_DMA64_RXERROR 0x34
-#define B43legacy_DMA64_RXERRDPTR 0x0001FFFF
-#define B43legacy_DMA64_RXERR 0xF0000000
-#define B43legacy_DMA64_RXERR_NOERR 0x00000000
-#define B43legacy_DMA64_RXERR_PROT 0x10000000
-#define B43legacy_DMA64_RXERR_UNDERRUN 0x20000000
-#define B43legacy_DMA64_RXERR_TRANSFER 0x30000000
-#define B43legacy_DMA64_RXERR_DESCREAD 0x40000000
-#define B43legacy_DMA64_RXERR_CORE 0x50000000
-
-/* 64-bit DMA descriptor. */
-struct b43legacy_dmadesc64 {
- __le32 control0;
- __le32 control1;
- __le32 address_low;
- __le32 address_high;
-} __packed;
-#define B43legacy_DMA64_DCTL0_DTABLEEND 0x10000000
-#define B43legacy_DMA64_DCTL0_IRQ 0x20000000
-#define B43legacy_DMA64_DCTL0_FRAMEEND 0x40000000
-#define B43legacy_DMA64_DCTL0_FRAMESTART 0x80000000
-#define B43legacy_DMA64_DCTL1_BYTECNT 0x00001FFF
-#define B43legacy_DMA64_DCTL1_ADDREXT_MASK 0x00030000
-#define B43legacy_DMA64_DCTL1_ADDREXT_SHIFT 16
-
-
-
-struct b43legacy_dmadesc_generic {
- union {
- struct b43legacy_dmadesc32 dma32;
- struct b43legacy_dmadesc64 dma64;
- } __packed;
-} __packed;
-
-
/* Misc DMA constants */
#define B43legacy_DMA_RINGMEMSIZE PAGE_SIZE
#define B43legacy_DMA0_RX_FRAMEOFFSET 30
@@ -197,35 +113,12 @@ struct b43legacy_dmadesc_meta {
bool is_last_fragment;
};
-struct b43legacy_dmaring;
-
-/* Lowlevel DMA operations that differ between 32bit and 64bit DMA. */
-struct b43legacy_dma_ops {
- struct b43legacy_dmadesc_generic * (*idx2desc)
- (struct b43legacy_dmaring *ring,
- int slot,
- struct b43legacy_dmadesc_meta
- **meta);
- void (*fill_descriptor)(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
- dma_addr_t dmaaddr, u16 bufsize,
- int start, int end, int irq);
- void (*poke_tx)(struct b43legacy_dmaring *ring, int slot);
- void (*tx_suspend)(struct b43legacy_dmaring *ring);
- void (*tx_resume)(struct b43legacy_dmaring *ring);
- int (*get_current_rxslot)(struct b43legacy_dmaring *ring);
- void (*set_current_rxslot)(struct b43legacy_dmaring *ring, int slot);
-};
-
enum b43legacy_dmatype {
B43legacy_DMA_30BIT = 30,
B43legacy_DMA_32BIT = 32,
- B43legacy_DMA_64BIT = 64,
};
struct b43legacy_dmaring {
- /* Lowlevel DMA ops. */
- const struct b43legacy_dma_ops *ops;
/* Kernel virtual base address of the ring memory. */
void *descbase;
/* Meta data about all descriptors. */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 04c03b212a5e..a3b72cd72c66 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -35,7 +35,6 @@
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/firmware.h>
-#include <linux/wireless.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
@@ -61,7 +60,6 @@ MODULE_AUTHOR("Stefano Brivio");
MODULE_AUTHOR("Michael Buesch");
MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID);
MODULE_FIRMWARE("b43legacy/ucode2.fw");
MODULE_FIRMWARE("b43legacy/ucode4.fw");
@@ -2468,7 +2466,8 @@ out:
}
}
-static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
return 0;
@@ -3785,7 +3784,8 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work);
ssb_set_devtypedata(dev, wl);
- b43legacyinfo(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
+ b43legacyinfo(wl, "Broadcom %04X WLAN found (core revision %u)\n",
+ dev->bus->chip_id, dev->id.revision);
err = 0;
out:
return err;
@@ -3947,8 +3947,7 @@ static void b43legacy_print_driverinfo(void)
feat_dma = "D";
#endif
printk(KERN_INFO "Broadcom 43xx-legacy driver loaded "
- "[ Features: %s%s%s%s, Firmware-ID: "
- B43legacy_SUPPORTED_FIRMWARE_ID " ]\n",
+ "[ Features: %s%s%s%s ]\n",
feat_pci, feat_leds, feat_pio, feat_dma);
}
diff --git a/drivers/staging/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index 379cf16e89f7..2069fc8f7ad1 100644
--- a/drivers/staging/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -1,16 +1,16 @@
config BRCMUTIL
tristate
- default n
config BRCMSMAC
tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
- default n
depends on PCI
- depends on WLAN && MAC80211
- depends on X86 || MIPS
+ depends on MAC80211
+ depends on BCMA=n
select BRCMUTIL
select FW_LOADER
select CRC_CCITT
+ select CRC8
+ select CORDIC
---help---
This module adds support for PCIe wireless adapters based on Broadcom
IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll
@@ -18,14 +18,10 @@ config BRCMSMAC
config BRCMFMAC
tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver"
- default n
depends on MMC
- depends on WLAN && CFG80211
- depends on X86 || MIPS
+ depends on CFG80211
select BRCMUTIL
select FW_LOADER
- select WIRELESS_EXT
- select WEXT_PRIV
---help---
This module adds support for embedded wireless adapters based on
Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's
@@ -34,7 +30,6 @@ config BRCMFMAC
config BRCMDBG
bool "Broadcom driver debug functions"
- default n
depends on BRCMSMAC || BRCMFMAC
---help---
Selecting this enables additional code for debug purposes.
diff --git a/drivers/staging/brcm80211/Makefile b/drivers/net/wireless/brcm80211/Makefile
index 8b01f5e7ba25..f41c047eca82 100644
--- a/drivers/staging/brcm80211/Makefile
+++ b/drivers/net/wireless/brcm80211/Makefile
@@ -16,7 +16,6 @@
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# common flags
-subdir-ccflags-y := -DBCMDMA32
subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG
obj-$(CONFIG_BRCMUTIL) += brcmutil/
diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index da3c80575907..b44e3094588a 100644
--- a/drivers/staging/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -15,16 +15,9 @@
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-ccflags-y := \
- -DBRCMF_FIRSTREAD=64 \
- -DBRCMF_SDALIGN=64 \
- -DMAX_HDR_READ=64
-
-ccflags-$(CONFIG_BRCMDBG) += -DSHOW_EVENTS
-
ccflags-y += \
- -Idrivers/staging/brcm80211/brcmfmac \
- -Idrivers/staging/brcm80211/include
+ -Idrivers/net/wireless/brcm80211/brcmfmac \
+ -Idrivers/net/wireless/brcm80211/include
DHDOFILES = \
wl_cfg80211.o \
@@ -37,3 +30,4 @@ DHDOFILES = \
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
brcmfmac-objs += $(DHDOFILES)
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmchip.h b/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h
index d7d3afd5a10f..d7d3afd5a10f 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmchip.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
new file mode 100644
index 000000000000..bff9dcd6fadc
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* ****************** SDIO CARD Interface Functions **************************/
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+
+#include <defs.h>
+#include <brcm_hw_ids.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <soc.h>
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+#include "sdio_host.h"
+
+#define SDIOH_API_ACCESS_RETRY_LIMIT 2
+
+static void brcmf_sdioh_irqhandler(struct sdio_func *func)
+{
+ struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
+
+ brcmf_dbg(TRACE, "***IRQHandler\n");
+
+ sdio_release_host(func);
+
+ brcmf_sdbrcm_isr(sdiodev->bus);
+
+ sdio_claim_host(func);
+}
+
+int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
+{
+ brcmf_dbg(TRACE, "Entering\n");
+
+ sdio_claim_host(sdiodev->func[1]);
+ sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
+ sdio_release_host(sdiodev->func[1]);
+
+ return 0;
+}
+
+int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
+{
+ brcmf_dbg(TRACE, "Entering\n");
+
+ sdio_claim_host(sdiodev->func[1]);
+ sdio_release_irq(sdiodev->func[1]);
+ sdio_release_host(sdiodev->func[1]);
+
+ return 0;
+}
+
+u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
+ int *err)
+{
+ int status;
+ s32 retry = 0;
+ u8 data = 0;
+
+ do {
+ if (retry) /* wait for 1 ms till bus get settled down */
+ udelay(1000);
+ status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num,
+ addr, (u8 *) &data);
+ } while (status != 0
+ && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
+ if (err)
+ *err = status;
+
+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
+ fnc_num, addr, data);
+
+ return data;
+}
+
+void
+brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
+ u8 data, int *err)
+{
+ int status;
+ s32 retry = 0;
+
+ do {
+ if (retry) /* wait for 1 ms till bus get settled down */
+ udelay(1000);
+ status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num,
+ addr, (u8 *) &data);
+ } while (status != 0
+ && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
+ if (err)
+ *err = status;
+
+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
+ fnc_num, addr, data);
+}
+
+int
+brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
+{
+ int err = 0;
+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
+ (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
+ if (!err)
+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_SBADDRMID,
+ (address >> 16) & SBSDIO_SBADDRMID_MASK,
+ &err);
+ if (!err)
+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_SBADDRHIGH,
+ (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
+ &err);
+
+ return err;
+}
+
+u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
+{
+ int status;
+ u32 word = 0;
+ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+
+ brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr);
+
+ if (bar0 != sdiodev->sbwad) {
+ if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
+ return 0xFFFFFFFF;
+
+ sdiodev->sbwad = bar0;
+ }
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ if (size == 4)
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1,
+ addr, &word, size);
+
+ sdiodev->regfail = (status != 0);
+
+ brcmf_dbg(INFO, "u32data = 0x%x\n", word);
+
+ /* if ok, return appropriately masked word */
+ if (status == 0) {
+ switch (size) {
+ case sizeof(u8):
+ return word & 0xff;
+ case sizeof(u16):
+ return word & 0xffff;
+ case sizeof(u32):
+ return word;
+ default:
+ sdiodev->regfail = true;
+
+ }
+ }
+
+ /* otherwise, bad sdio access or invalid size */
+ brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size);
+ return 0xFFFFFFFF;
+}
+
+u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
+ u32 data)
+{
+ int status;
+ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+ int err = 0;
+
+ brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
+ addr, size * 8, data);
+
+ if (bar0 != sdiodev->sbwad) {
+ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
+ if (err)
+ return err;
+
+ sdiodev->sbwad = bar0;
+ }
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ if (size == 4)
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+ status =
+ brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1,
+ addr, &data, size);
+ sdiodev->regfail = (status != 0);
+
+ if (status == 0)
+ return 0;
+
+ brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n",
+ data, addr, size);
+ return 0xFFFFFFFF;
+}
+
+bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
+{
+ return sdiodev->regfail;
+}
+
+int
+brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags,
+ u8 *buf, uint nbytes, struct sk_buff *pkt)
+{
+ int status;
+ uint incr_fix;
+ uint width;
+ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+ int err = 0;
+
+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes);
+
+ /* Async not implemented yet */
+ if (flags & SDIO_REQ_ASYNC)
+ return -ENOTSUPP;
+
+ if (bar0 != sdiodev->sbwad) {
+ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
+ if (err)
+ return err;
+
+ sdiodev->sbwad = bar0;
+ }
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+
+ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
+ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
+ if (width == 4)
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ status = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
+ fn, addr, width, nbytes, buf, pkt);
+
+ return status;
+}
+
+int
+brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt)
+{
+ uint incr_fix;
+ uint width;
+ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+ int err = 0;
+
+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes);
+
+ /* Async not implemented yet */
+ if (flags & SDIO_REQ_ASYNC)
+ return -ENOTSUPP;
+
+ if (bar0 != sdiodev->sbwad) {
+ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
+ if (err)
+ return err;
+
+ sdiodev->sbwad = bar0;
+ }
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+
+ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
+ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
+ if (width == 4)
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
+ addr, width, nbytes, buf, pkt);
+}
+
+int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
+ u8 *buf, uint nbytes)
+{
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC,
+ (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
+ addr, 4, nbytes, buf, NULL);
+}
+
+int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
+{
+ char t_func = (char)fn;
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* issue abort cmd52 command through F0 */
+ brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
+ SDIO_CCCR_ABORT, &t_func);
+
+ brcmf_dbg(TRACE, "Exit\n");
+ return 0;
+}
+
+int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
+{
+ u32 regs = 0;
+ int ret = 0;
+
+ ret = brcmf_sdioh_attach(sdiodev);
+ if (ret)
+ goto out;
+
+ 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(0, 0, 0, 0, regs, sdiodev);
+ if (!sdiodev->bus) {
+ brcmf_dbg(ERROR, "device attach failed\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+out:
+ if (ret)
+ brcmf_sdio_remove(sdiodev);
+
+ return ret;
+}
+EXPORT_SYMBOL(brcmf_sdio_probe);
+
+int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
+{
+ if (sdiodev->bus) {
+ brcmf_sdbrcm_disconnect(sdiodev->bus);
+ sdiodev->bus = NULL;
+ }
+
+ brcmf_sdioh_detach(sdiodev);
+
+ sdiodev->sbwad = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL(brcmf_sdio_remove);
+
+void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
+{
+ if (enable)
+ brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
+ else
+ brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
new file mode 100644
index 000000000000..bbaeb2d5c93a
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -0,0 +1,626 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/card.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/sched.h> /* request_irq() */
+#include <linux/module.h>
+#include <net/cfg80211.h>
+
+#include <defs.h>
+#include <brcm_hw_ids.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include "sdio_host.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "wl_cfg80211.h"
+
+#define SDIO_VENDOR_ID_BROADCOM 0x02d0
+
+#define DMA_ALIGN_MASK 0x03
+
+#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
+
+#define SDIO_FUNC1_BLOCKSIZE 64
+#define SDIO_FUNC2_BLOCKSIZE 512
+
+/* devices we support, null terminated */
+static const struct sdio_device_id brcmf_sdmmc_ids[] = {
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
+ { /* end: all zeroes */ },
+};
+MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
+
+static bool
+brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
+{
+ bool is_err = false;
+#ifdef CONFIG_PM_SLEEP
+ is_err = atomic_read(&sdiodev->suspend);
+#endif
+ return is_err;
+}
+
+static void
+brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq)
+{
+#ifdef CONFIG_PM_SLEEP
+ int retry = 0;
+ while (atomic_read(&sdiodev->suspend) && retry++ != 30)
+ wait_event_timeout(*wq, false, HZ/100);
+#endif
+}
+
+static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
+ uint regaddr, u8 *byte)
+{
+ struct sdio_func *sdfunc = sdiodev->func[0];
+ int err_ret;
+
+ /*
+ * Can only directly write to some F0 registers.
+ * Handle F2 enable/disable and Abort command
+ * as a special case.
+ */
+ if (regaddr == SDIO_CCCR_IOEx) {
+ sdfunc = sdiodev->func[2];
+ if (sdfunc) {
+ sdio_claim_host(sdfunc);
+ if (*byte & SDIO_FUNC_ENABLE_2) {
+ /* Enable Function 2 */
+ err_ret = sdio_enable_func(sdfunc);
+ if (err_ret)
+ brcmf_dbg(ERROR,
+ "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",
+ err_ret);
+ }
+ sdio_release_host(sdfunc);
+ }
+ } else if (regaddr == SDIO_CCCR_ABORT) {
+ sdio_claim_host(sdfunc);
+ sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
+ sdio_release_host(sdfunc);
+ } else if (regaddr < 0xF0) {
+ brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
+ err_ret = -EPERM;
+ } else {
+ sdio_claim_host(sdfunc);
+ sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
+ sdio_release_host(sdfunc);
+ }
+
+ return err_ret;
+}
+
+int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
+ uint regaddr, u8 *byte)
+{
+ int err_ret;
+
+ brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
+
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
+ if (brcmf_pm_resume_error(sdiodev))
+ return -EIO;
+
+ if (rw && func == 0) {
+ /* handle F0 separately */
+ err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
+ } else {
+ sdio_claim_host(sdiodev->func[func]);
+ if (rw) /* CMD52 Write */
+ sdio_writeb(sdiodev->func[func], *byte, regaddr,
+ &err_ret);
+ else if (func == 0) {
+ *byte = sdio_f0_readb(sdiodev->func[func], regaddr,
+ &err_ret);
+ } else {
+ *byte = sdio_readb(sdiodev->func[func], regaddr,
+ &err_ret);
+ }
+ sdio_release_host(sdiodev->func[func]);
+ }
+
+ if (err_ret)
+ brcmf_dbg(ERROR, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
+ rw ? "write" : "read", func, regaddr, *byte, err_ret);
+
+ return err_ret;
+}
+
+int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
+ uint rw, uint func, uint addr, u32 *word,
+ uint nbytes)
+{
+ int err_ret = -EIO;
+
+ if (func == 0) {
+ brcmf_dbg(ERROR, "Only CMD52 allowed to F0\n");
+ return -EINVAL;
+ }
+
+ brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
+ rw, func, addr, nbytes);
+
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
+ if (brcmf_pm_resume_error(sdiodev))
+ return -EIO;
+ /* Claim host controller */
+ sdio_claim_host(sdiodev->func[func]);
+
+ if (rw) { /* CMD52 Write */
+ if (nbytes == 4)
+ sdio_writel(sdiodev->func[func], *word, addr,
+ &err_ret);
+ else if (nbytes == 2)
+ sdio_writew(sdiodev->func[func], (*word & 0xFFFF),
+ addr, &err_ret);
+ else
+ brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
+ } else { /* CMD52 Read */
+ if (nbytes == 4)
+ *word = sdio_readl(sdiodev->func[func], addr, &err_ret);
+ else if (nbytes == 2)
+ *word = sdio_readw(sdiodev->func[func], addr,
+ &err_ret) & 0xFFFF;
+ else
+ brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
+ }
+
+ /* Release host controller */
+ sdio_release_host(sdiodev->func[func]);
+
+ if (err_ret)
+ brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n",
+ rw ? "write" : "read", err_ret);
+
+ return err_ret;
+}
+
+static int
+brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
+ uint write, uint func, uint addr,
+ struct sk_buff *pkt)
+{
+ bool fifo = (fix_inc == SDIOH_DATA_FIX);
+ u32 SGCount = 0;
+ int err_ret = 0;
+
+ struct sk_buff *pnext;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_packet_wait);
+ if (brcmf_pm_resume_error(sdiodev))
+ return -EIO;
+
+ /* Claim host controller */
+ sdio_claim_host(sdiodev->func[func]);
+ for (pnext = pkt; pnext; pnext = pnext->next) {
+ uint pkt_len = pnext->len;
+ pkt_len += 3;
+ pkt_len &= 0xFFFFFFFC;
+
+ if ((write) && (!fifo)) {
+ err_ret = sdio_memcpy_toio(sdiodev->func[func], addr,
+ ((u8 *) (pnext->data)),
+ pkt_len);
+ } else if (write) {
+ err_ret = sdio_memcpy_toio(sdiodev->func[func], addr,
+ ((u8 *) (pnext->data)),
+ pkt_len);
+ } else if (fifo) {
+ err_ret = sdio_readsb(sdiodev->func[func],
+ ((u8 *) (pnext->data)),
+ addr, pkt_len);
+ } else {
+ err_ret = sdio_memcpy_fromio(sdiodev->func[func],
+ ((u8 *) (pnext->data)),
+ addr, pkt_len);
+ }
+
+ if (err_ret) {
+ brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
+ write ? "TX" : "RX", pnext, SGCount, addr,
+ pkt_len, err_ret);
+ } else {
+ brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
+ write ? "TX" : "RX", pnext, SGCount, addr,
+ pkt_len);
+ }
+
+ if (!fifo)
+ addr += pkt_len;
+ SGCount++;
+
+ }
+
+ /* Release host controller */
+ sdio_release_host(sdiodev->func[func]);
+
+ brcmf_dbg(TRACE, "Exit\n");
+ return err_ret;
+}
+
+/*
+ * This function takes a buffer or packet, and fixes everything up
+ * so that in the end, a DMA-able packet is created.
+ *
+ * A buffer does not have an associated packet pointer,
+ * and may or may not be aligned.
+ * A packet may consist of a single packet, or a packet chain.
+ * If it is a packet chain, then all the packets in the chain
+ * must be properly aligned.
+ *
+ * If the packet data is not aligned, then there may only be
+ * one packet, and in this case, it is copied to a new
+ * aligned packet.
+ *
+ */
+int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
+ uint fix_inc, uint write, uint func, uint addr,
+ uint reg_width, uint buflen_u, u8 *buffer,
+ struct sk_buff *pkt)
+{
+ int Status;
+ struct sk_buff *mypkt = NULL;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
+ if (brcmf_pm_resume_error(sdiodev))
+ return -EIO;
+ /* Case 1: we don't have a packet. */
+ if (pkt == NULL) {
+ brcmf_dbg(DATA, "Creating new %s Packet, len=%d\n",
+ write ? "TX" : "RX", buflen_u);
+ mypkt = brcmu_pkt_buf_get_skb(buflen_u);
+ if (!mypkt) {
+ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
+ buflen_u);
+ return -EIO;
+ }
+
+ /* For a write, copy the buffer data into the packet. */
+ if (write)
+ memcpy(mypkt->data, buffer, buflen_u);
+
+ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
+ func, addr, mypkt);
+
+ /* For a read, copy the packet data back to the buffer. */
+ if (!write)
+ memcpy(buffer, mypkt->data, buflen_u);
+
+ brcmu_pkt_buf_free_skb(mypkt);
+ } else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) {
+ /*
+ * Case 2: We have a packet, but it is unaligned.
+ * In this case, we cannot have a chain (pkt->next == NULL)
+ */
+ brcmf_dbg(DATA, "Creating aligned %s Packet, len=%d\n",
+ write ? "TX" : "RX", pkt->len);
+ mypkt = brcmu_pkt_buf_get_skb(pkt->len);
+ if (!mypkt) {
+ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
+ pkt->len);
+ return -EIO;
+ }
+
+ /* For a write, copy the buffer data into the packet. */
+ if (write)
+ memcpy(mypkt->data, pkt->data, pkt->len);
+
+ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
+ func, addr, mypkt);
+
+ /* For a read, copy the packet data back to the buffer. */
+ if (!write)
+ memcpy(pkt->data, mypkt->data, mypkt->len);
+
+ brcmu_pkt_buf_free_skb(mypkt);
+ } else { /* case 3: We have a packet and
+ it is aligned. */
+ brcmf_dbg(DATA, "Aligned %s Packet, direct DMA\n",
+ write ? "Tx" : "Rx");
+ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
+ func, addr, pkt);
+ }
+
+ return Status;
+}
+
+/* Read client card reg */
+static int
+brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr,
+ int regsize, u32 *data)
+{
+
+ if ((func == 0) || (regsize == 1)) {
+ u8 temp = 0;
+
+ brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr,
+ &temp);
+ *data = temp;
+ *data &= 0xff;
+ brcmf_dbg(DATA, "byte read data=0x%02x\n", *data);
+ } else {
+ brcmf_sdioh_request_word(sdiodev, SDIOH_READ, func, regaddr,
+ data, regsize);
+ if (regsize == 2)
+ *data &= 0xffff;
+
+ brcmf_dbg(DATA, "word read data=0x%08x\n", *data);
+ }
+
+ return SUCCESS;
+}
+
+static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr)
+{
+ /* read 24 bits and return valid 17 bit addr */
+ int i;
+ u32 scratch, regdata;
+ __le32 scratch_le;
+ u8 *ptr = (u8 *)&scratch_le;
+
+ for (i = 0; i < 3; i++) {
+ if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1,
+ &regdata)) != SUCCESS)
+ brcmf_dbg(ERROR, "Can't read!\n");
+
+ *ptr++ = (u8) regdata;
+ regaddr++;
+ }
+
+ /* Only the lower 17-bits are valid */
+ scratch = le32_to_cpu(scratch_le);
+ scratch &= 0x0001FFFF;
+ return scratch;
+}
+
+static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
+{
+ int err_ret;
+ u32 fbraddr;
+ u8 func;
+
+ brcmf_dbg(TRACE, "\n");
+
+ /* Get the Card's common CIS address */
+ sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev,
+ SDIO_CCCR_CIS);
+ brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n",
+ sdiodev->func_cis_ptr[0]);
+
+ /* Get the Card's function CIS (for each function) */
+ for (fbraddr = SDIO_FBR_BASE(1), func = 1;
+ func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
+ sdiodev->func_cis_ptr[func] =
+ brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr);
+ brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n",
+ func, sdiodev->func_cis_ptr[func]);
+ }
+
+ /* 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);
+
+ return false;
+}
+
+/*
+ * Public entry points & extern's
+ */
+int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
+{
+ int err_ret = 0;
+
+ brcmf_dbg(TRACE, "\n");
+
+ 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");
+ 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");
+ goto out;
+ }
+
+ brcmf_sdioh_enablefuncs(sdiodev);
+
+out:
+ brcmf_dbg(TRACE, "Done\n");
+ return err_ret;
+}
+
+void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
+{
+ brcmf_dbg(TRACE, "\n");
+
+ /* Disable Function 2 */
+ sdio_claim_host(sdiodev->func[2]);
+ sdio_disable_func(sdiodev->func[2]);
+ sdio_release_host(sdiodev->func[2]);
+
+ /* Disable Function 1 */
+ sdio_claim_host(sdiodev->func[1]);
+ sdio_disable_func(sdiodev->func[1]);
+ sdio_release_host(sdiodev->func[1]);
+
+}
+
+static int brcmf_ops_sdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ int ret = 0;
+ struct brcmf_sdio_dev *sdiodev;
+ 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;
+ }
+ sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
+ if (!sdiodev)
+ return -ENOMEM;
+ sdiodev->func[0] = func->card->sdio_func[0];
+ sdiodev->func[1] = func;
+ 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_packet_wait);
+ init_waitqueue_head(&sdiodev->request_buffer_wait);
+ }
+
+ if (func->num == 2) {
+ sdiodev = dev_get_drvdata(&func->card->dev);
+ if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
+ return -ENODEV;
+ sdiodev->func[2] = func;
+
+ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
+ ret = brcmf_sdio_probe(sdiodev);
+ }
+
+ return ret;
+}
+
+static void brcmf_ops_sdio_remove(struct sdio_func *func)
+{
+ 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);
+
+ if (func->num == 2) {
+ sdiodev = dev_get_drvdata(&func->card->dev);
+ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n");
+ brcmf_sdio_remove(sdiodev);
+ dev_set_drvdata(&func->card->dev, NULL);
+ kfree(sdiodev);
+ }
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int brcmf_sdio_suspend(struct device *dev)
+{
+ mmc_pm_flag_t sdio_flags;
+ struct brcmf_sdio_dev *sdiodev;
+ struct sdio_func *func = dev_to_sdio_func(dev);
+ int ret = 0;
+
+ brcmf_dbg(TRACE, "\n");
+
+ sdiodev = dev_get_drvdata(&func->card->dev);
+
+ atomic_set(&sdiodev->suspend, true);
+
+ 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");
+ 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");
+ return ret;
+ }
+
+ brcmf_sdio_wdtmr_enable(sdiodev, false);
+
+ return ret;
+}
+
+static int brcmf_sdio_resume(struct device *dev)
+{
+ struct brcmf_sdio_dev *sdiodev;
+ struct sdio_func *func = dev_to_sdio_func(dev);
+
+ sdiodev = dev_get_drvdata(&func->card->dev);
+ brcmf_sdio_wdtmr_enable(sdiodev, true);
+ atomic_set(&sdiodev->suspend, false);
+ return 0;
+}
+
+static const struct dev_pm_ops brcmf_sdio_pm_ops = {
+ .suspend = brcmf_sdio_suspend,
+ .resume = brcmf_sdio_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+static struct sdio_driver brcmf_sdmmc_driver = {
+ .probe = brcmf_ops_sdio_probe,
+ .remove = brcmf_ops_sdio_remove,
+ .name = "brcmfmac",
+ .id_table = brcmf_sdmmc_ids,
+#ifdef CONFIG_PM_SLEEP
+ .drv = {
+ .pm = &brcmf_sdio_pm_ops,
+ },
+#endif /* CONFIG_PM_SLEEP */
+};
+
+/* bus register interface */
+int brcmf_bus_register(void)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ return sdio_register_driver(&brcmf_sdmmc_driver);
+}
+
+void brcmf_bus_unregister(void)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ sdio_unregister_driver(&brcmf_sdmmc_driver);
+}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 82bf04df16d0..4645766b4070 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -23,10 +23,9 @@
#define BRCMF_VERSION_STR "4.218.248.5"
-#define BRCMF_C_IOCTL_SMLEN 256 /* "small" ioctl buffer required */
-#define BRCMF_C_IOCTL_MEDLEN 1536 /* "med" ioctl buffer required */
-#define BRCMF_C_IOCTL_MAXLEN 8192
-
+/*******************************************************************************
+ * IO codes that are interpreted by dongle firmware
+ ******************************************************************************/
#define BRCMF_C_UP 2
#define BRCMF_C_SET_PROMISC 10
#define BRCMF_C_GET_RATE 12
@@ -83,18 +82,11 @@
#define WLC_PHY_TYPE_LCN 8
#define WLC_PHY_TYPE_NULL 0xf
-#define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter, u)
-#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \
- offsetof(struct brcmf_pkt_filter_pattern, mask_and_pattern)
-
#define BRCMF_EVENTING_MASK_LEN 16
#define TOE_TX_CSUM_OL 0x00000001
#define TOE_RX_CSUM_OL 0x00000002
-/* maximum channels returned by the get valid channels iovar */
-#define WL_NUMCHANNELS 64
-
#define BRCMF_BSS_INFO_VERSION 108 /* current ver of brcmf_bss_info struct */
/* size of brcmf_scan_params not including variable length array */
@@ -117,11 +109,16 @@
#define BRCMF_SCAN_RESULTS_ABORTED 3
#define BRCMF_SCAN_RESULTS_NO_MEM 4
-#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */
-#define BRCMF_PRIMARY_KEY (1 << 1) /* primary (ie tx) key */
-#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */
-#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */
-#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */
+/* 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
@@ -136,13 +133,13 @@
#define BRCMF_EVENT_MSG_GROUP 0x04
struct brcmf_event_msg {
- u16 version;
- u16 flags;
- u32 event_type;
- u32 status;
- u32 reason;
- u32 auth_type;
- u32 datalen;
+ __be16 version;
+ __be16 flags;
+ __be32 event_type;
+ __be32 status;
+ __be32 reason;
+ __be32 auth_type;
+ __be32 datalen;
u8 addr[ETH_ALEN];
char ifname[IFNAMSIZ];
} __packed;
@@ -173,6 +170,7 @@ struct dngl_stats {
unsigned long multicast; /* multicast packets received */
};
+/* 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
@@ -332,30 +330,35 @@ enum brcmf_bus_state {
* start matching, the pattern to match, the size of the pattern, and a bitmask
* that indicates which bits within the pattern should be matched.
*/
-struct brcmf_pkt_filter_pattern {
- u32 offset; /* Offset within received packet to start pattern matching.
- * Offset '0' is the first byte of the ethernet header.
- */
- u32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */
- u8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts
- * at offset 0. Pattern immediately follows mask.
- */
+struct brcmf_pkt_filter_pattern_le {
+ /*
+ * Offset within received packet to start pattern matching.
+ * Offset '0' is the first byte of the ethernet header.
+ */
+ __le32 offset;
+ /* Size of the pattern. Bitmask must be the same size.*/
+ __le32 size_bytes;
+ /*
+ * Variable length mask and pattern data. mask starts at offset 0.
+ * Pattern immediately follows mask.
+ */
+ u8 mask_and_pattern[1];
};
/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
-struct brcmf_pkt_filter {
- u32 id; /* Unique filter id, specified by app. */
- u32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */
- u32 negate_match; /* Negate the result of filter matches */
+struct brcmf_pkt_filter_le {
+ __le32 id; /* Unique filter id, specified by app. */
+ __le32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */
+ __le32 negate_match; /* Negate the result of filter matches */
union { /* Filter definitions */
- struct brcmf_pkt_filter_pattern pattern; /* Filter pattern */
+ struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */
} u;
};
/* IOVAR "pkt_filter_enable" parameter. */
-struct brcmf_pkt_filter_enable {
- u32 id; /* Unique filter id */
- u32 enable; /* Enable/disable bool */
+struct brcmf_pkt_filter_enable_le {
+ __le32 id; /* Unique filter id */
+ __le32 enable; /* Enable/disable bool */
};
/* BSS info structure
@@ -363,63 +366,76 @@ struct brcmf_pkt_filter_enable {
* next bss_info structure in a vector (in struct brcmf_scan_results)
*/
struct brcmf_bss_info {
- u32 version; /* version field */
- u32 length; /* byte length of data in this record,
+ __le32 version; /* version field */
+ __le32 length; /* byte length of data in this record,
* starting at version and including IEs
*/
u8 BSSID[ETH_ALEN];
- u16 beacon_period; /* units are Kusec */
- u16 capability; /* Capability information */
+ __le16 beacon_period; /* units are Kusec */
+ __le16 capability; /* Capability information */
u8 SSID_len;
u8 SSID[32];
struct {
- uint count; /* # rates in this set */
- u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+ __le32 count; /* # rates in this set */
+ u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
} rateset; /* supported rates */
- chanspec_t chanspec; /* chanspec for bss */
- u16 atim_window; /* units are Kusec */
+ __le16 chanspec; /* chanspec for bss */
+ __le16 atim_window; /* units are Kusec */
u8 dtim_period; /* DTIM period */
- s16 RSSI; /* receive signal strength (in dBm) */
+ __le16 RSSI; /* receive signal strength (in dBm) */
s8 phy_noise; /* noise (in dBm) */
u8 n_cap; /* BSS is 802.11N Capable */
- u32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */
+ /* 802.11N BSS Capabilities (based on HT_CAP_*): */
+ __le32 nbss_cap;
u8 ctl_ch; /* 802.11N BSS control channel number */
- u32 reserved32[1]; /* Reserved for expansion of BSS properties */
+ __le32 reserved32[1]; /* Reserved for expansion of BSS properties */
u8 flags; /* flags */
u8 reserved[3]; /* Reserved for expansion of BSS properties */
u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
- u16 ie_offset; /* offset at which IEs start, from beginning */
- u32 ie_length; /* byte length of Information Elements */
- s16 SNR; /* average SNR of during frame reception */
+ __le16 ie_offset; /* offset at which IEs start, from beginning */
+ __le32 ie_length; /* byte length of Information Elements */
+ __le16 SNR; /* average SNR of during frame reception */
/* Add new fields here */
/* variable length Information Elements */
};
+struct brcm_rateset_le {
+ /* # rates in this set */
+ __le32 count;
+ /* rates in 500kbps units w/hi bit set if basic */
+ u8 rates[WL_NUMRATES];
+};
+
struct brcmf_ssid {
u32 SSID_len;
unsigned char SSID[32];
};
-struct brcmf_scan_params {
- struct brcmf_ssid ssid; /* default: {0, ""} */
+struct brcmf_ssid_le {
+ __le32 SSID_len;
+ unsigned char SSID[32];
+};
+
+struct brcmf_scan_params_le {
+ struct brcmf_ssid_le ssid_le; /* default: {0, ""} */
u8 bssid[ETH_ALEN]; /* default: bcast */
s8 bss_type; /* default: any,
* DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
*/
u8 scan_type; /* flags, 0 use default */
- s32 nprobes; /* -1 use default, number of probes per channel */
- s32 active_time; /* -1 use default, dwell time per channel for
+ __le32 nprobes; /* -1 use default, number of probes per channel */
+ __le32 active_time; /* -1 use default, dwell time per channel for
* active scanning
*/
- s32 passive_time; /* -1 use default, dwell time per channel
+ __le32 passive_time; /* -1 use default, dwell time per channel
* for passive scanning
*/
- s32 home_time; /* -1 use default, dwell time for the home channel
- * between channel scans
+ __le32 home_time; /* -1 use default, dwell time for the
+ * home channel between channel scans
*/
- s32 channel_num; /* count of channels and ssids that follow
+ __le32 channel_num; /* count of channels and ssids that follow
*
* low half is count of channels in
* channel_list, 0 means default (use all
@@ -435,22 +451,17 @@ struct brcmf_scan_params {
* fixed parameter portion is assumed, otherwise
* ssid in the fixed portion is ignored
*/
- u16 channel_list[1]; /* list of chanspecs */
+ __le16 channel_list[1]; /* list of chanspecs */
};
/* incremental scan struct */
-struct brcmf_iscan_params {
- u32 version;
- u16 action;
- u16 scan_duration;
- struct brcmf_scan_params params;
+struct brcmf_iscan_params_le {
+ __le32 version;
+ __le16 action;
+ __le16 scan_duration;
+ struct brcmf_scan_params_le params_le;
};
-/* 3 fields + size of brcmf_scan_params, not including variable length array */
-#define BRCMF_ISCAN_PARAMS_FIXED_SIZE \
- (offsetof(struct brcmf_iscan_params, params) + \
- sizeof(struct brcmf_ssid))
-
struct brcmf_scan_results {
u32 buflen;
u32 version;
@@ -458,21 +469,28 @@ struct brcmf_scan_results {
struct brcmf_bss_info bss_info[1];
};
+struct brcmf_scan_results_le {
+ __le32 buflen;
+ __le32 version;
+ __le32 count;
+ struct brcmf_bss_info bss_info[1];
+};
+
/* used for association with a specific BSSID and chanspec list */
-struct brcmf_assoc_params {
- u8 bssid[ETH_ALEN]; /* 00:00:00:00:00:00: broadcast scan */
- s32 chanspec_num; /* 0: all available channels,
- * otherwise count of chanspecs in chanspec_list
- */
- chanspec_t chanspec_list[1]; /* list of chanspecs */
+struct brcmf_assoc_params_le {
+ /* 00:00:00:00:00:00: broadcast scan */
+ u8 bssid[ETH_ALEN];
+ /* 0: all available channels, otherwise count of chanspecs in
+ * chanspec_list */
+ __le32 chanspec_num;
+ /* list of chanspecs */
+ __le16 chanspec_list[1];
};
-#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
- (sizeof(struct brcmf_assoc_params) - sizeof(chanspec_t))
/* used for join with or without a specific bssid and channel list */
struct brcmf_join_params {
- struct brcmf_ssid ssid;
- struct brcmf_assoc_params params;
+ struct brcmf_ssid_le ssid_le;
+ struct brcmf_assoc_params_le params_le;
};
/* size of brcmf_scan_results not including variable length array */
@@ -481,8 +499,14 @@ struct brcmf_join_params {
/* incremental scan results struct */
struct brcmf_iscan_results {
- u32 status;
- struct brcmf_scan_results 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 */
@@ -495,40 +519,61 @@ struct brcmf_wsec_key {
u32 len; /* key length */
u8 data[WLAN_MAX_KEY_LEN]; /* key data */
u32 pad_1[18];
- u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
- u32 flags; /* misc flags */
- u32 pad_2[2];
- int pad_3;
- int iv_initialized; /* has IV been initialized already? */
- int pad_4;
+ u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ u32 flags; /* misc flags */
+ u32 pad_2[3];
+ u32 iv_initialized; /* has IV been initialized already? */
+ u32 pad_3;
/* Rx IV */
struct {
u32 hi; /* upper 32 bits of IV */
u16 lo; /* lower 16 bits of IV */
} rxiv;
- u32 pad_5[2];
+ u32 pad_4[2];
+ u8 ea[ETH_ALEN]; /* per station */
+};
+
+/*
+ * dongle requires same struct as above but with fields in little endian order
+ */
+struct brcmf_wsec_key_le {
+ __le32 index; /* key index */
+ __le32 len; /* key length */
+ u8 data[WLAN_MAX_KEY_LEN]; /* key data */
+ __le32 pad_1[18];
+ __le32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+ __le32 flags; /* misc flags */
+ __le32 pad_2[3];
+ __le32 iv_initialized; /* has IV been initialized already? */
+ __le32 pad_3;
+ /* Rx IV */
+ struct {
+ __le32 hi; /* upper 32 bits of IV */
+ __le16 lo; /* lower 16 bits of IV */
+ } rxiv;
+ __le32 pad_4[2];
u8 ea[ETH_ALEN]; /* per station */
};
/* Used to get specific STA parameters */
-struct brcmf_scb_val {
- u32 val;
+struct brcmf_scb_val_le {
+ __le32 val;
u8 ea[ETH_ALEN];
};
/* channel encoding */
-struct brcmf_channel_info {
- int hw_channel;
- int target_channel;
- int scan_channel;
+struct brcmf_channel_info_le {
+ __le32 hw_channel;
+ __le32 target_channel;
+ __le32 scan_channel;
};
-/* Linux network driver ioctl encoding */
-struct brcmf_ioctl {
- uint cmd; /* common ioctl definition */
+/* Bus independent dongle command */
+struct brcmf_dcmd {
+ uint cmd; /* common dongle cmd definition */
void *buf; /* pointer to user buffer */
uint len; /* length of user buffer */
- u8 set; /* get or set request (optional) */
+ u8 set; /* get or set request (optional) */
uint used; /* bytes read or written (optional) */
uint needed; /* bytes needed (optional) */
};
@@ -537,6 +582,7 @@ struct brcmf_ioctl {
struct brcmf_bus; /* device bus info */
struct brcmf_proto; /* device communication protocol info */
struct brcmf_info; /* device driver info */
+struct brcmf_cfg80211_dev; /* cfg80211 device info */
/* Common structure for module and instance linkage */
struct brcmf_pub {
@@ -544,11 +590,11 @@ struct brcmf_pub {
struct brcmf_bus *bus;
struct brcmf_proto *prot;
struct brcmf_info *info;
+ struct brcmf_cfg80211_dev *config;
/* Internal brcmf items */
bool up; /* Driver up/down (to OS) */
bool txoff; /* Transmit flow-controlled */
- bool dongle_reset; /* true = DEVRESET put dongle into reset */
enum brcmf_bus_state busstate;
uint hdrlen; /* Total BRCMF header length (proto + bus) */
uint maxctl; /* Max size rxctl request from proto to bus */
@@ -558,32 +604,45 @@ struct brcmf_pub {
/* 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 */
+ u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
struct dngl_stats dstats; /* Stats for dongle-based data */
/* Additional stats for the bus level */
- unsigned long tx_packets; /* Data packets sent to dongle */
- unsigned long tx_multicast; /* Multicast data packets sent to dongle */
- unsigned long tx_errors; /* Errors in sending data to dongle */
- unsigned long tx_ctlpkts; /* Control packets sent to dongle */
- unsigned long tx_ctlerrs; /* Errors sending control frames to dongle */
- unsigned long rx_packets; /* Packets sent up the network interface */
- unsigned long rx_multicast; /* Multicast packets sent up the network
- interface */
- unsigned long rx_errors; /* Errors processing rx data packets */
- unsigned long rx_ctlpkts; /* Control frames processed from dongle */
- unsigned long rx_ctlerrs; /* Errors in processing rx control frames */
- unsigned long rx_dropped; /* Packets dropped locally (no memory) */
- unsigned long rx_flushed; /* Packets flushed due to
- unscheduled sendup thread */
- unsigned long wd_dpc_sched; /* Number of times dpc scheduled by
- watchdog timer */
-
- unsigned long rx_readahead_cnt; /* Number of packets where header read-ahead
- was used. */
- unsigned long tx_realloc; /* Number of tx packets we had to realloc for
- headroom */
- unsigned long fc_packets; /* Number of flow control pkts recvd */
+
+ /* Data packets sent to dongle */
+ unsigned long tx_packets;
+ /* Multicast data packets sent to dongle */
+ unsigned long tx_multicast;
+ /* Errors in sending data to dongle */
+ unsigned long tx_errors;
+ /* Control packets sent to dongle */
+ unsigned long tx_ctlpkts;
+ /* Errors sending control frames to dongle */
+ unsigned long tx_ctlerrs;
+ /* Packets sent up the network interface */
+ unsigned long rx_packets;
+ /* Multicast packets sent up the network interface */
+ unsigned long rx_multicast;
+ /* Errors processing rx data packets */
+ unsigned long rx_errors;
+ /* Control frames processed from dongle */
+ unsigned long rx_ctlpkts;
+
+ /* Errors in processing rx control frames */
+ unsigned long rx_ctlerrs;
+ /* Packets dropped locally (no memory) */
+ unsigned long rx_dropped;
+ /* Packets flushed due to unscheduled sendup thread */
+ unsigned long rx_flushed;
+ /* Number of times dpc scheduled by watchdog timer */
+ unsigned long wd_dpc_sched;
+
+ /* Number of packets where header read-ahead was used. */
+ unsigned long rx_readahead_cnt;
+ /* Number of tx packets we had to realloc for headroom */
+ unsigned long tx_realloc;
+ /* Number of flow control pkts recvd */
+ unsigned long fc_packets;
/* Last error return */
int bcmerror;
@@ -614,146 +673,15 @@ struct brcmf_if_event {
u8 bssidx;
};
-struct brcmf_timeout {
- u32 limit; /* Expiration time (usec) */
- u32 increment; /* Current expiration increment (usec) */
- u32 elapsed; /* Current elapsed time (usec) */
- u32 tick; /* O/S tick time (usec) */
-};
-
struct bcmevent_name {
uint event;
const char *name;
};
-#if defined(CONFIG_PM_SLEEP)
-extern atomic_t brcmf_mmc_suspend;
-#define BRCMF_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-#define _BRCMF_PM_RESUME_WAIT(a, b) do { \
- int retry = 0; \
- while (atomic_read(&brcmf_mmc_suspend) && retry++ != b) { \
- wait_event_timeout(a, false, HZ/100); \
- } \
- } while (0)
-#define BRCMF_PM_RESUME_WAIT(a) _BRCMF_PM_RESUME_WAIT(a, 30)
-#define BRCMF_PM_RESUME_RETURN_ERROR(a) \
- do { if (atomic_read(&brcmf_mmc_suspend)) return a; } while (0)
-
-#define BRCMF_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \
- uint countdown = (us) + 9999; \
- while ((exp) && (countdown >= 10000)) { \
- wait_event_timeout(a, false, HZ/100); \
- countdown -= 10000; \
- } \
- } while (0)
-
-#else
-
-#define BRCMF_PM_RESUME_WAIT_INIT(a)
-#define BRCMF_PM_RESUME_WAIT(a)
-#define BRCMF_PM_RESUME_RETURN_ERROR(a)
-
-#define BRCMF_SPINWAIT_SLEEP_INIT(a)
-#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \
- uint countdown = (us) + 9; \
- while ((exp) && (countdown >= 10)) { \
- udelay(10); \
- countdown -= 10; \
- } \
- } while (0)
-
-#endif /* defined(CONFIG_PM_SLEEP) */
-
-/*
- * Insmod parameters for debug/test
- */
-
-/* Use interrupts */
-extern uint brcmf_intr;
-
-/* Use polling */
-extern uint brcmf_poll;
-
-/* ARP offload agent mode */
-extern uint brcmf_arp_mode;
-
-/* ARP offload enable */
-extern uint brcmf_arp_enable;
-
-/* Pkt filte enable control */
-extern uint brcmf_pkt_filter_enable;
-
-/* Pkt filter init setup */
-extern uint brcmf_pkt_filter_init;
-
-/* Pkt filter mode control */
-extern uint brcmf_master_mode;
-
-/* Roaming mode control */
-extern uint brcmf_roam;
-
-/* Roaming mode control */
-extern uint brcmf_radio_up;
-
-/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
-extern int brcmf_idletime;
-#define BRCMF_IDLETIME_TICKS 1
-
-/* SDIO Drive Strength */
-extern uint brcmf_sdiod_drive_strength;
-
-/* Override to force tx queueing all the time */
-extern uint brcmf_force_tx_queueing;
-
-#ifdef SDTEST
-/* Echo packet generator (SDIO), pkts/s */
-extern uint brcmf_pktgen;
-
-/* Echo packet len (0 => sawtooth, max 1800) */
-extern uint brcmf_pktgen_len;
-#define BRCMF_MAX_PKTGEN_LEN 1800
-#endif
-
extern const struct bcmevent_name bcmevent_names[];
-extern const int bcmevent_names_size;
-
-
-static inline void MUTEX_LOCK_INIT(struct brcmf_pub *drvr)
-{
-}
-
-static inline void MUTEX_LOCK(struct brcmf_pub *drvr)
-{
-}
-
-static inline void MUTEX_UNLOCK(struct brcmf_pub *drvr)
-{
-}
-
-static inline void MUTEX_LOCK_SOFTAP_SET_INIT(struct brcmf_pub *drvr)
-{
-}
-
-static inline void MUTEX_LOCK_SOFTAP_SET(struct brcmf_pub *drvr)
-{
-}
-
-static inline void MUTEX_UNLOCK_SOFTAP_SET(struct brcmf_pub *drvr)
-{
-}
-static inline void MUTEX_LOCK_WL_SCAN_SET_INIT(void)
-{
-}
-
-static inline void MUTEX_LOCK_WL_SCAN_SET(void)
-{
-}
-
-static inline void MUTEX_UNLOCK_WL_SCAN_SET(void)
-{
-}
+extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
+ char *buf, uint len);
/* Indication from bus module regarding presence/insertion of dongle.
* Return struct brcmf_pub pointer, used as handle to OS module in later calls.
@@ -763,7 +691,9 @@ static inline void MUTEX_UNLOCK_WL_SCAN_SET(void)
extern struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus,
uint bus_hdrlen);
extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx);
-extern int brcmf_netdev_wait_pend8021x(struct net_device *dev);
+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);
/* Indication from bus module regarding removal/absence of dongle */
extern void brcmf_detach(struct brcmf_pub *drvr);
@@ -785,25 +715,17 @@ extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp,
bool success);
-/* Query ioctl */
-extern int brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx,
+/* Query dongle */
+extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
uint cmd, void *buf, uint len);
/* OS independent layer functions */
extern int brcmf_os_proto_block(struct brcmf_pub *drvr);
extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr);
-extern int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition,
- bool *pending);
-extern int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr);
-extern unsigned int brcmf_os_get_ioctl_resp_timeout(void);
-extern void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
#ifdef BCMDBG
-extern int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size);
+extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size);
#endif /* BCMDBG */
-extern void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec);
-extern int brcmf_timeout_expired(struct brcmf_timeout *tmo);
-
extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name);
extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
void *pktdata, struct brcmf_event_msg *,
@@ -811,44 +733,24 @@ extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
extern void brcmf_c_init(void);
-extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle,
- char *name, u8 *mac_addr, u32 flags, u8 bssidx);
+extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx,
+ struct net_device *ndev, char *name, u8 *mac_addr,
+ u32 flags, u8 bssidx);
extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx);
/* Send packet to dongle via data channel */
extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\
struct sk_buff *pkt);
-extern int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag);
extern int brcmf_bus_start(struct brcmf_pub *drvr);
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);
-/* Linux network driver ioctl encoding */
-struct brcmf_c_ioctl {
- uint cmd; /* common ioctl definition */
- void *buf; /* pointer to user buffer */
- uint len; /* length of user buffer */
- bool set; /* get or set request (optional) */
- uint used; /* bytes read or written (optional) */
- uint needed; /* bytes needed (optional) */
- uint driver; /* to identify target driver */
-};
-
-/* per-driver magic numbers */
-#define BRCMF_IOCTL_MAGIC 0x00444944
-
-/* bump this number if you change the ioctl interface */
-#define BRCMF_IOCTL_VERSION 1
-#define BRCMF_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */
-
-/* common ioctl definitions */
-#define BRCMF_GET_MAGIC 0
-#define BRCMF_GET_VERSION 1
-#define BRCMF_GET_VAR 2
-#define BRCMF_SET_VAR 3
+#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 */
/* message levels */
#define BRCMF_ERROR_VAL 0x0001
@@ -865,40 +767,10 @@ struct brcmf_c_ioctl {
#define BRCMF_BTA_VAL 0x1000
#define BRCMF_ISCAN_VAL 0x2000
-#ifdef SDTEST
-/* For pktgen iovar */
-struct brcmf_pktgen {
- uint version; /* To allow structure change tracking */
- uint freq; /* Max ticks between tx/rx attempts */
- uint count; /* Test packets to send/rcv each attempt */
- uint print; /* Print counts every <print> attempts */
- uint total; /* Total packets (or bursts) */
- uint minlen; /* Minimum length of packets to send */
- uint maxlen; /* Maximum length of packets to send */
- uint numsent; /* Count of test packets sent */
- uint numrcvd; /* Count of test packets received */
- uint numfail; /* Count of test send failures */
- uint mode; /* Test mode (type of test packets) */
- uint stop; /* Stop after this many tx failures */
-};
-
-/* Version in case structure changes */
-#define BRCMF_PKTGEN_VERSION 2
-
-/* Type of test packets to use */
-#define BRCMF_PKTGEN_ECHO 1 /* Send echo requests */
-#define BRCMF_PKTGEN_SEND 2 /* Send discard packets */
-#define BRCMF_PKTGEN_RXBURST 3 /* Request dongle send N packets */
-#define BRCMF_PKTGEN_RECV 4 /* Continuous rx from continuous
- tx dongle */
-#endif /* SDTEST */
-
/* Enter idle immediately (no timeout) */
#define BRCMF_IDLE_IMMEDIATE (-1)
-
-/* Values for idleclock iovar: other values are the sd_divisor to use
- when idle */
#define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change
when idle */
+#define BRCMF_IDLE_INTERVAL 1
#endif /* _BRCMF_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index 653cf0daa0eb..a249407c9a1b 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -18,36 +18,27 @@
#define _BRCMF_BUS_H_
/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef BRCMF_SDALIGN
-#define BRCMF_SDALIGN 32
-#endif
-#if !ISPOWEROF2(BRCMF_SDALIGN)
-#error BRCMF_SDALIGN is not a power of 2!
-#endif
+#define BRCMF_SDALIGN (1 << 6)
+
+/* watchdog polling interval in ms */
+#define BRCMF_WD_POLL_MS 10
/*
* Exported from brcmf bus module (brcmf_usb, brcmf_sdio)
*/
-/* dongle ram module parameter */
-extern int brcmf_dongle_memsize;
-
-/* Tx/Rx bounds module parameters */
-extern uint brcmf_txbound;
-extern uint brcmf_rxbound;
-
-/* Watchdog timer interval */
-extern uint brcmf_watchdog_ms;
-
/* Indicate (dis)interest in finding dongles. */
extern int brcmf_bus_register(void);
extern void brcmf_bus_unregister(void);
+/* obtain linux device object providing bus function */
+extern struct device *brcmf_bus_get_device(struct brcmf_bus *bus);
+
/* Stop bus module: clear pending frames, disable data flow */
-extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex);
+extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus);
/* Initialize bus module: prepare for communication w/dongle */
-extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex);
+extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr);
/* Send a data frame to the dongle. Callee disposes of txp. */
extern int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *txp);
@@ -61,18 +52,6 @@ brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
extern int
brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
-/* Check for and handle local prot-specific iovar commands */
-extern int brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name,
- void *params, int plen, void *arg, int len,
- bool set);
-
-/* Add bus dump output to a buffer */
-extern void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr,
- struct brcmu_strbuf *strbuf);
-
-/* Clear any bus counters */
-extern void brcmf_bus_clearcounts(struct brcmf_pub *drvr);
-
extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick);
#endif /* _BRCMF_BUS_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
index 345acabe935e..e34c5c3d1d55 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
@@ -14,6 +14,11 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/*******************************************************************************
+ * Communicates with the dongle by using dcmd codes.
+ * For certain dcmd codes, the dongle interprets string data from the host.
+ ******************************************************************************/
+
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/sched.h>
@@ -27,29 +32,26 @@
#include "dhd_bus.h"
#include "dhd_dbg.h"
-struct brcmf_proto_cdc_ioctl {
- u32 cmd; /* ioctl command value */
- u32 len; /* lower 16: output buflen;
+struct brcmf_proto_cdc_dcmd {
+ __le32 cmd; /* dongle command value */
+ __le32 len; /* lower 16: output buflen;
* upper 16: input buflen (excludes header) */
- u32 flags; /* flag defns given below */
- u32 status; /* status code returned from the device */
+ __le32 flags; /* flag defns given below */
+ __le32 status; /* status code returned from the device */
};
/* Max valid buffer size that can be sent to the dongle */
#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN)
/* CDC flag definitions */
-#define CDCF_IOC_ERROR 0x01 /* 1=ioctl cmd failed */
-#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */
-#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */
-#define CDCF_IOC_IF_SHIFT 12
-#define CDCF_IOC_ID_MASK 0xFFFF0000 /* id an ioctl pairing */
-#define CDCF_IOC_ID_SHIFT 16 /* ID Mask shift bits */
-#define CDC_IOC_ID(flags) \
- (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
-#define CDC_SET_IF_IDX(hdr, idx) \
- ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
- ((idx) << CDCF_IOC_IF_SHIFT)))
+#define CDC_DCMD_ERROR 0x01 /* 1=cmd failed */
+#define CDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */
+#define CDC_DCMD_IF_MASK 0xF000 /* I/F index */
+#define CDC_DCMD_IF_SHIFT 12
+#define CDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */
+#define CDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */
+#define CDC_DCMD_ID(flags) \
+ (((flags) & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT)
/*
* BDC header - Broadcom specific extension of CDC.
@@ -79,7 +81,7 @@ struct brcmf_proto_bdc_header {
};
-#define RETRIES 2 /* # of retries to retrieve matching ioctl response */
+#define RETRIES 2 /* # of retries to retrieve matching dcmd response */
#define BUS_HEADER_LEN (16+BRCMF_SDALIGN) /* Must be atleast SDPCM_RESERVE
* (amount of header tha might be added)
* plus any space that might be needed
@@ -94,17 +96,17 @@ struct brcmf_proto {
u8 pending;
u32 lastcmd;
u8 bus_header[BUS_HEADER_LEN];
- struct brcmf_proto_cdc_ioctl msg;
- unsigned char buf[BRCMF_C_IOCTL_MAXLEN + ROUND_UP_MARGIN];
+ struct brcmf_proto_cdc_dcmd msg;
+ unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN];
};
static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)
{
struct brcmf_proto *prot = drvr->prot;
int len = le32_to_cpu(prot->msg.len) +
- sizeof(struct brcmf_proto_cdc_ioctl);
+ sizeof(struct brcmf_proto_cdc_dcmd);
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
/* NOTE : cdc->msg.len holds the desired length of the buffer to be
* returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
@@ -123,31 +125,31 @@ static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
int ret;
struct brcmf_proto *prot = drvr->prot;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
do {
ret = brcmf_sdbrcm_bus_rxctl(drvr->bus,
(unsigned char *)&prot->msg,
- len + sizeof(struct brcmf_proto_cdc_ioctl));
+ len + sizeof(struct brcmf_proto_cdc_dcmd));
if (ret < 0)
break;
- } while (CDC_IOC_ID(le32_to_cpu(prot->msg.flags)) != id);
+ } while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id);
return ret;
}
int
-brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
- void *buf, uint len)
+brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+ void *buf, uint len)
{
struct brcmf_proto *prot = drvr->prot;
- struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
+ struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
void *info;
int ret = 0, retries = 0;
- u32 id, flags = 0;
+ u32 id, flags;
- BRCMF_TRACE(("%s: Enter\n", __func__));
- BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len);
/* Respond "bcmerror" and "bcmerrorstr" with local cache */
if (cmd == BRCMF_C_GET_VAR && buf) {
@@ -161,21 +163,22 @@ brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
}
}
- memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
+ memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
- msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
- CDC_SET_IF_IDX(msg, ifidx);
- msg->flags = cpu_to_le32(msg->flags);
+ flags = (++prot->reqid << CDC_DCMD_ID_SHIFT);
+ flags = (flags & ~CDC_DCMD_IF_MASK) |
+ (ifidx << CDC_DCMD_IF_SHIFT);
+ msg->flags = cpu_to_le32(flags);
if (buf)
memcpy(prot->buf, buf, len);
ret = brcmf_proto_cdc_msg(drvr);
if (ret < 0) {
- BRCMF_ERROR(("brcmf_proto_cdc_query_ioctl: brcmf_proto_cdc_msg "
- "failed w/status %d\n", ret));
+ brcmf_dbg(ERROR, "brcmf_proto_cdc_msg failed w/status %d\n",
+ ret);
goto done;
}
@@ -186,14 +189,13 @@ retry:
goto done;
flags = le32_to_cpu(msg->flags);
- id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
+ id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT;
if ((id < prot->reqid) && (++retries < RETRIES))
goto retry;
if (id != prot->reqid) {
- BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
- brcmf_ifname(drvr, ifidx), __func__, id,
- prot->reqid));
+ brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n",
+ brcmf_ifname(drvr, ifidx), id, prot->reqid);
ret = -EINVAL;
goto done;
}
@@ -209,7 +211,7 @@ retry:
}
/* Check the ERROR flag */
- if (flags & CDCF_IOC_ERROR) {
+ if (flags & CDC_DCMD_ERROR) {
ret = le32_to_cpu(msg->status);
/* Cache error from dongle */
drvr->dongle_error = ret;
@@ -219,24 +221,25 @@ done:
return ret;
}
-int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
- void *buf, uint len)
+int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+ void *buf, uint len)
{
struct brcmf_proto *prot = drvr->prot;
- struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
+ struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
int ret = 0;
u32 flags, id;
- BRCMF_TRACE(("%s: Enter\n", __func__));
- BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len);
- memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
+ memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
- msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET;
- CDC_SET_IF_IDX(msg, ifidx);
- msg->flags = cpu_to_le32(msg->flags);
+ flags = (++prot->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET;
+ flags = (flags & ~CDC_DCMD_IF_MASK) |
+ (ifidx << CDC_DCMD_IF_SHIFT);
+ msg->flags = cpu_to_le32(flags);
if (buf)
memcpy(prot->buf, buf, len);
@@ -250,18 +253,17 @@ int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
goto done;
flags = le32_to_cpu(msg->flags);
- id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
+ id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT;
if (id != prot->reqid) {
- BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
- brcmf_ifname(drvr, ifidx), __func__, id,
- prot->reqid));
+ brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n",
+ brcmf_ifname(drvr, ifidx), id, prot->reqid);
ret = -EINVAL;
goto done;
}
/* Check the ERROR flag */
- if (flags & CDCF_IOC_ERROR) {
+ if (flags & CDC_DCMD_ERROR) {
ret = le32_to_cpu(msg->status);
/* Cache error from dongle */
drvr->dongle_error = ret;
@@ -272,65 +274,64 @@ done:
}
int
-brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx, struct brcmf_ioctl *ioc,
- void *buf, int len)
+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->busstate == BRCMF_BUS_DOWN) {
- BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
- __func__));
+ brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n");
return ret;
}
brcmf_os_proto_block(drvr);
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
- if (len > BRCMF_C_IOCTL_MAXLEN)
+ if (len > BRCMF_DCMD_MAXLEN)
goto done;
if (prot->pending == true) {
- BRCMF_TRACE(("CDC packet is pending!!!! cmd=0x%x (%lu) "
- "lastcmd=0x%x (%lu)\n",
- ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
- (unsigned long)prot->lastcmd));
- if ((ioc->cmd == BRCMF_C_SET_VAR) ||
- (ioc->cmd == BRCMF_C_GET_VAR))
- BRCMF_TRACE(("iovar cmd=%s\n", (char *)buf));
+ 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 = ioc->cmd;
- if (ioc->set)
- ret = brcmf_proto_cdc_set_ioctl(drvr, ifidx, ioc->cmd,
- buf, len);
+ 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_ioctl(drvr, ifidx, ioc->cmd,
- buf, len);
+ ret = brcmf_proto_cdc_query_dcmd(drvr, ifidx, dcmd->cmd,
+ dcmd->buf, len);
if (ret > 0)
- ioc->used = ret - sizeof(struct brcmf_proto_cdc_ioctl);
+ dcmd->used = ret -
+ sizeof(struct brcmf_proto_cdc_dcmd);
}
- /* Too many programs assume ioctl() returns 0 on success */
if (ret >= 0)
ret = 0;
else {
- struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
+ struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
/* len == needed when set/query fails from dongle */
- ioc->needed = le32_to_cpu(msg->len);
+ dcmd->needed = le32_to_cpu(msg->len);
}
- /* Intercept the wme_dp ioctl here */
- if (!ret && ioc->cmd == BRCMF_C_SET_VAR &&
- !strcmp(buf, "wme_dp")) {
- int slen, val = 0;
+ /* 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 *)buf + slen, sizeof(int));
+ memcpy(&val, (char *)dcmd->buf + slen, sizeof(int));
drvr->wme_dp = (u8) le32_to_cpu(val);
}
@@ -342,15 +343,14 @@ done:
return ret;
}
-#define PKTSUMNEEDED(skb) \
- (((struct sk_buff *)(skb))->ip_summed == CHECKSUM_PARTIAL)
-#define PKTSETSUMGOOD(skb, x) \
- (((struct sk_buff *)(skb))->ip_summed = \
- ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE))
+static bool pkt_sum_needed(struct sk_buff *skb)
+{
+ return skb->ip_summed == CHECKSUM_PARTIAL;
+}
-void brcmf_proto_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
+static void pkt_set_sum_good(struct sk_buff *skb, bool x)
{
- brcmu_bprintf(strbuf, "Protocol CDC: reqid %d\n", drvr->prot->reqid);
+ skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
}
void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
@@ -358,7 +358,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
{
struct brcmf_proto_bdc_header *h;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
/* Push BDC header used to convey priority for buses that don't */
@@ -367,7 +367,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
- if (PKTSUMNEEDED(pktbuf))
+ if (pkt_sum_needed(pktbuf))
h->flags |= BDC_FLAG_SUM_NEEDED;
h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
@@ -381,13 +381,13 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx,
{
struct brcmf_proto_bdc_header *h;
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
/* Pop BDC header used to convey priority for buses that don't */
if (pktbuf->len < BDC_HEADER_LEN) {
- BRCMF_ERROR(("%s: rx data too short (%d < %d)\n", __func__,
- pktbuf->len, BDC_HEADER_LEN));
+ brcmf_dbg(ERROR, "rx data too short (%d < %d)\n",
+ pktbuf->len, BDC_HEADER_LEN);
return -EBADE;
}
@@ -395,23 +395,21 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx,
*ifidx = BDC_GET_IF_IDX(h);
if (*ifidx >= BRCMF_MAX_IFS) {
- BRCMF_ERROR(("%s: rx data ifnum out of range (%d)\n",
- __func__, *ifidx));
+ brcmf_dbg(ERROR, "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_ERROR(("%s: non-BDC packet received, flags 0x%x\n",
- brcmf_ifname(drvr, *ifidx), h->flags));
+ brcmf_dbg(ERROR, "%s: non-BDC packet received, flags 0x%x\n",
+ brcmf_ifname(drvr, *ifidx), h->flags);
return -EBADE;
}
if (h->flags & BDC_FLAG_SUM_GOOD) {
- BRCMF_INFO(("%s: BDC packet received with good rx-csum, "
- "flags 0x%x\n",
- brcmf_ifname(drvr, *ifidx), h->flags));
- PKTSETSUMGOOD(pktbuf, true);
+ brcmf_dbg(INFO, "%s: BDC packet received with good rx-csum, flags 0x%x\n",
+ brcmf_ifname(drvr, *ifidx), h->flags);
+ pkt_set_sum_good(pktbuf, true);
}
pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
@@ -426,21 +424,19 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
struct brcmf_proto *cdc;
cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC);
- if (!cdc) {
- BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
+ if (!cdc)
goto fail;
- }
/* ensure that the msg buf directly follows the cdc msg struct */
if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) {
- BRCMF_ERROR(("struct brcmf_proto is not correctly defined\n"));
+ brcmf_dbg(ERROR, "struct brcmf_proto is not correctly defined\n");
goto fail;
}
drvr->prot = cdc;
drvr->hdrlen += BDC_HEADER_LEN;
- drvr->maxctl = BRCMF_C_IOCTL_MAXLEN +
- sizeof(struct brcmf_proto_cdc_ioctl) + ROUND_UP_MARGIN;
+ drvr->maxctl = BRCMF_DCMD_MAXLEN +
+ sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN;
return 0;
fail:
@@ -472,13 +468,13 @@ int brcmf_proto_init(struct brcmf_pub *drvr)
int ret = 0;
char buf[128];
- BRCMF_TRACE(("%s: Enter\n", __func__));
+ brcmf_dbg(TRACE, "Enter\n");
brcmf_os_proto_block(drvr);
/* Get the device MAC address */
strcpy(buf, "cur_etheraddr");
- ret = brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR,
+ ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR,
buf, sizeof(buf));
if (ret < 0) {
brcmf_os_proto_unblock(drvr);
@@ -488,7 +484,7 @@ int brcmf_proto_init(struct brcmf_pub *drvr)
brcmf_os_proto_unblock(drvr);
- ret = brcmf_c_preinit_ioctls(drvr);
+ ret = brcmf_c_preinit_dcmds(drvr);
/* Always assumes wl for now */
drvr->iswl = true;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
new file mode 100644
index 000000000000..891826197f96
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -0,0 +1,895 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#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"
+
+#define BRCM_OUI "\x00\x10\x18"
+#define DOT11_OUI_LEN 3
+#define BCMILCP_BCM_SUBTYPE_EVENT 1
+#define PKTFILTER_BUF_SIZE 2048
+#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */
+
+int brcmf_msg_level;
+
+#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)
+
+#ifdef BCMDBG
+static const char brcmf_version[] =
+ "Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on "
+ __DATE__ " at " __TIME__;
+#else
+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 */
+ memcpy(&buf[len], data, datalen);
+ len += datalen;
+
+ return len;
+}
+
+void brcmf_c_init(void)
+{
+ /* Init global variables at run-time, not as part of the declaration.
+ * This is required to support init/de-init of the driver.
+ * Initialization
+ * of globals as part of the declaration results in non-deterministic
+ * behaviour since the value of the globals may be different on the
+ * first time that the driver is initialized vs subsequent
+ * initializations.
+ */
+ brcmf_msg_level = BRCMF_ERROR_VAL;
+}
+
+bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
+ struct sk_buff *pkt, int prec)
+{
+ struct sk_buff *p;
+ int eprec = -1; /* precedence to evict from */
+ bool discard_oldest;
+
+ /* Fast case, precedence queue is not full and we are also not
+ * exceeding total queue length
+ */
+ if (!pktq_pfull(q, prec) && !pktq_full(q)) {
+ brcmu_pktq_penq(q, prec, pkt);
+ return true;
+ }
+
+ /* 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)
+ return false;
+ }
+
+ /* Evict if needed */
+ if (eprec >= 0) {
+ /* Detect queueing to unconfigured precedence */
+ discard_oldest = ac_bitmap_tst(drvr->wme_dp, eprec);
+ if (eprec == prec && !discard_oldest)
+ return false; /* refuse newer (incoming) packet */
+ /* Evict packet according to discard policy */
+ 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",
+ discard_oldest);
+
+ brcmu_pkt_buf_free_skb(p);
+ }
+
+ /* Enqueue */
+ p = brcmu_pktq_penq(q, prec, pkt);
+ if (p == NULL)
+ brcmf_dbg(ERROR, "brcmu_pktq_penq() failed\n");
+
+ return p != NULL;
+}
+
+#ifdef BCMDBG
+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"}
+ };
+ 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_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';
+ printk(KERN_DEBUG"%s\n", p);
+ p = s + 1;
+ }
+ printk(KERN_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 */
+ if (datalen) {
+ buf = (unsigned char *) event_data;
+ brcmf_dbg(EVENT, " data (%d) : ", datalen);
+ for (i = 0; i < datalen; i++)
+ brcmf_dbg(EVENT, " 0x%02x ", *buf++);
+ brcmf_dbg(EVENT, "\n");
+ }
+}
+#endif /* BCMDBG */
+
+int
+brcmf_c_host_event(struct brcmf_info *drvr_priv, 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_priv, ifevent->ifidx, NULL,
+ event->ifname,
+ pvt_data->eth.h_dest,
+ ifevent->flags, ifevent->bssidx);
+ else
+ brcmf_del_if(drvr_priv, 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_priv, 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_priv, 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 BCMDBG
+ brcmf_c_show_host_event(event, event_data);
+#endif /* BCMDBG */
+
+ 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");
+ return -EINVAL;
+ }
+ src = src + 2; /* Skip past 0x */
+ if (strlen(src) % 2 != 0) {
+ brcmf_dbg(ERROR, "Mask invalid format. Length must be even.\n");
+ return -EINVAL;
+ }
+ for (i = 0; *src != '\0'; i++) {
+ unsigned long res;
+ char num[3];
+ strncpy(num, src, 2);
+ num[2] = '\0';
+ if (kstrtoul(num, 16, &res))
+ return -EINVAL;
+ dst[i] = (u8)res;
+ src += 2;
+ }
+ return i;
+}
+
+void
+brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, 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 *arg_save = NULL, *arg_org = NULL;
+ int rc;
+ char buf[128];
+ 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);
+ if (!arg_save)
+ goto fail;
+
+ arg_org = arg_save;
+ memcpy(arg_save, arg, strlen(arg) + 1);
+
+ argv[i] = strsep(&arg_save, " ");
+
+ i = 0;
+ if (NULL == argv[i]) {
+ brcmf_dbg(ERROR, "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))
+ enable_parm.id = cpu_to_le32((u32)res);
+
+ /* Parse enable/disable value. */
+ enable_parm.enable = cpu_to_le32(enable);
+
+ buf_len += sizeof(enable_parm);
+ memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
+
+ /* 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);
+
+fail:
+ kfree(arg_org);
+}
+
+void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
+{
+ const char *str;
+ struct brcmf_pkt_filter_le pkt_filter;
+ struct brcmf_pkt_filter_le *pkt_filterp;
+ unsigned long res;
+ int buf_len;
+ int str_len;
+ int rc;
+ u32 mask_size;
+ u32 pattern_size;
+ char *argv[8], *buf = NULL;
+ int i = 0;
+ char *arg_save = NULL, *arg_org = NULL;
+
+ arg_save = kstrdup(arg, GFP_ATOMIC);
+ if (!arg_save)
+ goto fail;
+
+ arg_org = arg_save;
+
+ buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC);
+ if (!buf)
+ goto fail;
+
+ argv[i] = strsep(&arg_save, " ");
+ while (argv[i++])
+ argv[i] = strsep(&arg_save, " ");
+
+ i = 0;
+ if (NULL == argv[i]) {
+ brcmf_dbg(ERROR, "No args provided\n");
+ 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);
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+
+ /* Parse pattern filter pattern. */
+ pattern_size =
+ brcmf_c_pattern_atoh(argv[i],
+ (char *)&pkt_filterp->u.pattern.
+ mask_and_pattern[mask_size]);
+
+ if (mask_size != pattern_size) {
+ brcmf_dbg(ERROR, "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;
+
+ 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);
+
+fail:
+ kfree(arg_org);
+
+ kfree(buf);
+}
+
+static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
+{
+ char iovbuf[32];
+ int retcode;
+
+ brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 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;
+
+ brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 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 */
+ uint up = 0;
+ char buf[128], *ptr;
+ u32 dongle_align = BRCMF_SDALIGN;
+ u32 glom = 0;
+ u32 roaming = 1;
+ uint bcn_timeout = 3;
+ int scan_assoc_time = 40;
+ int scan_unassoc_time = 40;
+ int i;
+
+ brcmf_os_proto_block(drvr);
+
+ /* 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");
+ }
+
+ /* 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));
+ strsep(&ptr, "\n");
+ /* Print fw version info */
+ brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
+
+ /* Match Host and Dongle rx alignment */
+ brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
+ sizeof(iovbuf));
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+ sizeof(iovbuf));
+
+ /* disable glom option per default */
+ brcmf_c_mkiovar("bus:txglom", (char *)&glom, 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 */
+ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
+ sizeof(iovbuf));
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+ sizeof(iovbuf));
+
+ /* Enable/Disable build-in roaming to allowed ext supplicant to take
+ of romaing */
+ brcmf_c_mkiovar("roam_off", (char *)&roaming, 4,
+ iovbuf, sizeof(iovbuf));
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+ sizeof(iovbuf));
+
+ /* Force STA UP */
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up));
+
+ /* 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, sizeof(scan_assoc_time));
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+ (char *)&scan_unassoc_time, sizeof(scan_unassoc_time));
+
+ /* 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);
+ }
+
+ brcmf_os_proto_unblock(drvr);
+
+ return 0;
+}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
index 5be4d7a609c2..7467922f0536 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
@@ -19,25 +19,21 @@
#if defined(BCMDBG)
-#define BRCMF_ERROR(args) \
- do {if ((brcmf_msg_level & BRCMF_ERROR_VAL) && (net_ratelimit())) \
- printk args; } while (0)
-#define BRCMF_TRACE(args) do {if (brcmf_msg_level & BRCMF_TRACE_VAL) \
- printk args; } while (0)
-#define BRCMF_INFO(args) do {if (brcmf_msg_level & BRCMF_INFO_VAL) \
- printk args; } while (0)
-#define BRCMF_DATA(args) do {if (brcmf_msg_level & BRCMF_DATA_VAL) \
- printk args; } while (0)
-#define BRCMF_CTL(args) do {if (brcmf_msg_level & BRCMF_CTL_VAL) \
- printk args; } while (0)
-#define BRCMF_TIMER(args) do {if (brcmf_msg_level & BRCMF_TIMER_VAL) \
- printk args; } while (0)
-#define BRCMF_INTR(args) do {if (brcmf_msg_level & BRCMF_INTR_VAL) \
- printk args; } while (0)
-#define BRCMF_GLOM(args) do {if (brcmf_msg_level & BRCMF_GLOM_VAL) \
- printk args; } while (0)
-#define BRCMF_EVENT(args) do {if (brcmf_msg_level & BRCMF_EVENT_VAL) \
- printk args; } while (0)
+#define brcmf_dbg(level, fmt, ...) \
+do { \
+ if (BRCMF_ERROR_VAL == BRCMF_##level##_VAL) { \
+ if (brcmf_msg_level & BRCMF_##level##_VAL) { \
+ if (net_ratelimit()) \
+ printk(KERN_DEBUG "%s: " fmt, \
+ __func__, ##__VA_ARGS__); \
+ } \
+ } else { \
+ if (brcmf_msg_level & BRCMF_##level##_VAL) { \
+ printk(KERN_DEBUG "%s: " fmt, \
+ __func__, ##__VA_ARGS__); \
+ } \
+ } \
+} while (0)
#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL)
#define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL)
@@ -47,20 +43,12 @@
#else /* (defined BCMDBG) || (defined BCMDBG) */
-#define BRCMF_ERROR(args) do {if (net_ratelimit()) printk args; } while (0)
-#define BRCMF_TRACE(args)
-#define BRCMF_INFO(args)
-#define BRCMF_DATA(args)
-#define BRCMF_CTL(args)
-#define BRCMF_TIMER(args)
-#define BRCMF_INTR(args)
-#define BRCMF_GLOM(args)
-#define BRCMF_EVENT(args)
+#define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__)
#define BRCMF_DATA_ON() 0
#define BRCMF_CTL_ON() 0
#define BRCMF_HDRS_ON() 0
-#define BRCMF_BYTES_ON() 0
+#define BRCMF_BYTES_ON() 0
#define BRCMF_GLOM_ON() 0
#endif /* defined(BCMDBG) */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
new file mode 100644
index 000000000000..4acbac5a74c6
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -0,0 +1,1356 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#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.h"
+#include "dhd_bus.h"
+#include "dhd_proto.h"
+#include "dhd_dbg.h"
+#include "wl_cfg80211.h"
+#include "bcmchip.h"
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver.");
+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+
+/* Interface control information */
+struct brcmf_if {
+ struct brcmf_info *info; /* back pointer to brcmf_info */
+ /* OS/stack specifics */
+ struct net_device *ndev;
+ struct net_device_stats stats;
+ int idx; /* iface idx in dongle */
+ int state; /* interface state */
+ u8 mac_addr[ETH_ALEN]; /* assigned MAC address */
+};
+
+/* Local private structure (extension of pub) */
+struct brcmf_info {
+ struct brcmf_pub pub;
+
+ /* OS/stack specifics */
+ struct brcmf_if *iflist[BRCMF_MAX_IFS];
+
+ struct mutex proto_block;
+
+ struct work_struct setmacaddr_work;
+ struct work_struct multicast_work;
+ u8 macvalue[ETH_ALEN];
+ atomic_t pend_8021x_cnt;
+};
+
+/* Error bits */
+module_param(brcmf_msg_level, int, 0);
+
+
+static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *ndev)
+{
+ int i = 0;
+
+ while (i < BRCMF_MAX_IFS) {
+ if (drvr_priv->iflist[i] && drvr_priv->iflist[i]->ndev == ndev)
+ return i;
+ i++;
+ }
+
+ return BRCMF_BAD_IF;
+}
+
+int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
+{
+ int i = BRCMF_MAX_IFS;
+ struct brcmf_if *ifp;
+
+ if (name == NULL || *name == '\0')
+ return 0;
+
+ while (--i > 0) {
+ ifp = drvr_priv->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)
+{
+ struct brcmf_info *drvr_priv = drvr->info;
+
+ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+ brcmf_dbg(ERROR, "ifidx %d out of range\n", ifidx);
+ return "<if_bad>";
+ }
+
+ if (drvr_priv->iflist[ifidx] == NULL) {
+ brcmf_dbg(ERROR, "null i/f %d\n", ifidx);
+ return "<if_null>";
+ }
+
+ if (drvr_priv->iflist[ifidx]->ndev)
+ return drvr_priv->iflist[ifidx]->ndev->name;
+
+ return "<if_none>";
+}
+
+static void _brcmf_set_multicast_list(struct work_struct *work)
+{
+ struct net_device *ndev;
+ struct netdev_hw_addr *ha;
+ u32 dcmd_value, cnt;
+ __le32 cnt_le;
+ __le32 dcmd_le_value;
+
+ struct brcmf_dcmd dcmd;
+ char *buf, *bufp;
+ uint buflen;
+ int ret;
+
+ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info,
+ multicast_work);
+
+ ndev = drvr_priv->iflist[0]->ndev;
+ cnt = netdev_mc_count(ndev);
+
+ /* Determine initial value of allmulti flag */
+ dcmd_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)
+ return;
+
+ strcpy(bufp, "mcast_list");
+ bufp += strlen("mcast_list") + 1;
+
+ cnt_le = cpu_to_le32(cnt);
+ memcpy(bufp, &cnt_le, sizeof(cnt));
+ bufp += sizeof(cnt_le);
+
+ netdev_for_each_mc_addr(ha, ndev) {
+ if (!cnt)
+ break;
+ memcpy(bufp, ha->addr, ETH_ALEN);
+ bufp += ETH_ALEN;
+ 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_priv->pub, 0, &dcmd, dcmd.len);
+ if (ret < 0) {
+ brcmf_dbg(ERROR, "%s: set mcast_list failed, cnt %d\n",
+ brcmf_ifname(&drvr_priv->pub, 0), cnt);
+ dcmd_value = cnt ? true : dcmd_value;
+ }
+
+ kfree(buf);
+
+ /* 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...
+ */
+
+ 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_priv->pub, 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_priv->pub, 0, &dcmd, dcmd.len);
+ if (ret < 0) {
+ brcmf_dbg(ERROR, "%s: set allmulti %d failed\n",
+ brcmf_ifname(&drvr_priv->pub, 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_priv->pub, 0, &dcmd, dcmd.len);
+ if (ret < 0) {
+ brcmf_dbg(ERROR, "%s: set promisc %d failed\n",
+ brcmf_ifname(&drvr_priv->pub, 0),
+ le32_to_cpu(dcmd_le_value));
+ }
+}
+
+static void
+_brcmf_set_mac_address(struct work_struct *work)
+{
+ char buf[32];
+ struct brcmf_dcmd dcmd;
+ int ret;
+
+ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info,
+ setmacaddr_work);
+
+ brcmf_dbg(TRACE, "enter\n");
+ if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr_priv->macvalue,
+ ETH_ALEN, buf, 32)) {
+ brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n",
+ brcmf_ifname(&drvr_priv->pub, 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_priv->pub, 0, &dcmd, dcmd.len);
+ if (ret < 0)
+ brcmf_dbg(ERROR, "%s: set cur_etheraddr failed\n",
+ brcmf_ifname(&drvr_priv->pub, 0));
+ else
+ memcpy(drvr_priv->iflist[0]->ndev->dev_addr,
+ drvr_priv->macvalue, ETH_ALEN);
+
+ return;
+}
+
+static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
+{
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
+ struct sockaddr *sa = (struct sockaddr *)addr;
+ int ifidx;
+
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
+ if (ifidx == BRCMF_BAD_IF)
+ return -1;
+
+ memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
+ schedule_work(&drvr_priv->setmacaddr_work);
+ return 0;
+}
+
+static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
+{
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
+ int ifidx;
+
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
+ if (ifidx == BRCMF_BAD_IF)
+ return;
+
+ schedule_work(&drvr_priv->multicast_work);
+}
+
+int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
+{
+ struct brcmf_info *drvr_priv = drvr->info;
+
+ /* Reject if down */
+ if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN))
+ return -ENODEV;
+
+ /* Update multicast statistic */
+ if (pktbuf->len >= ETH_ALEN) {
+ u8 *pktdata = (u8 *) (pktbuf->data);
+ struct ethhdr *eh = (struct ethhdr *)pktdata;
+
+ if (is_multicast_ether_addr(eh->h_dest))
+ drvr->tx_multicast++;
+ if (ntohs(eh->h_proto) == ETH_P_PAE)
+ atomic_inc(&drvr_priv->pend_8021x_cnt);
+ }
+
+ /* If the protocol uses a data header, apply it */
+ brcmf_proto_hdrpush(drvr, ifidx, pktbuf);
+
+ /* Use bus module to send data frame */
+ return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf);
+}
+
+static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ int ret;
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
+ int ifidx;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Reject if down */
+ if (!drvr_priv->pub.up || (drvr_priv->pub.busstate == BRCMF_BUS_DOWN)) {
+ brcmf_dbg(ERROR, "xmit rejected pub.up=%d busstate=%d\n",
+ drvr_priv->pub.up, drvr_priv->pub.busstate);
+ netif_stop_queue(ndev);
+ return -ENODEV;
+ }
+
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
+ if (ifidx == BRCMF_BAD_IF) {
+ brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx);
+ netif_stop_queue(ndev);
+ return -ENODEV;
+ }
+
+ /* Make sure there's enough room for any header */
+ if (skb_headroom(skb) < drvr_priv->pub.hdrlen) {
+ struct sk_buff *skb2;
+
+ brcmf_dbg(INFO, "%s: insufficient headroom\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx));
+ drvr_priv->pub.tx_realloc++;
+ skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
+ dev_kfree_skb(skb);
+ skb = skb2;
+ if (skb == NULL) {
+ brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx));
+ ret = -ENOMEM;
+ goto done;
+ }
+ }
+
+ ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb);
+
+done:
+ if (ret)
+ drvr_priv->pub.dstats.tx_dropped++;
+ else
+ drvr_priv->pub.tx_packets++;
+
+ /* Return ok: we always eat the packet */
+ return 0;
+}
+
+void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state)
+{
+ struct net_device *ndev;
+ struct brcmf_info *drvr_priv = drvr->info;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ drvr->txoff = state;
+ ndev = drvr_priv->iflist[ifidx]->ndev;
+ if (state == ON)
+ netif_stop_queue(ndev);
+ else
+ netif_wake_queue(ndev);
+}
+
+static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx,
+ void *pktdata, struct brcmf_event_msg *event,
+ void **data)
+{
+ int bcmerror = 0;
+
+ bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data);
+ if (bcmerror != 0)
+ return bcmerror;
+
+ if (drvr_priv->iflist[*ifidx]->ndev)
+ brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->ndev,
+ event, *data);
+
+ return bcmerror;
+}
+
+void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
+ int numpkt)
+{
+ struct brcmf_info *drvr_priv = drvr->info;
+ unsigned char *eth;
+ uint len;
+ void *data;
+ struct sk_buff *pnext, *save_pktbuf;
+ int i;
+ struct brcmf_if *ifp;
+ struct brcmf_event_msg event;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ save_pktbuf = skb;
+
+ for (i = 0; skb && i < numpkt; i++, skb = pnext) {
+
+ pnext = skb->next;
+ skb->next = NULL;
+
+ /* Get the protocol, maintain skb around eth_type_trans()
+ * The main reason for this hack is for the limitation of
+ * Linux 2.4 where 'eth_type_trans' uses the
+ * 'net->hard_header_len'
+ * to perform skb_pull inside vs ETH_HLEN. Since to avoid
+ * coping of the packet coming from the network stack to add
+ * BDC, Hardware header etc, during network interface
+ * registration
+ * we set the 'net->hard_header_len' to ETH_HLEN + extra space
+ * required
+ * for BDC, Hardware header etc. and not just the ETH_HLEN
+ */
+ eth = skb->data;
+ len = skb->len;
+
+ ifp = drvr_priv->iflist[ifidx];
+ if (ifp == NULL)
+ ifp = drvr_priv->iflist[0];
+
+ skb->dev = ifp->ndev;
+ skb->protocol = eth_type_trans(skb, skb->dev);
+
+ if (skb->pkt_type == PACKET_MULTICAST)
+ drvr_priv->pub.rx_multicast++;
+
+ skb->data = eth;
+ skb->len = len;
+
+ /* Strip header, count, deliver upward */
+ 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_priv, &ifidx,
+ skb_mac_header(skb),
+ &event, &data);
+
+ if (drvr_priv->iflist[ifidx] &&
+ !drvr_priv->iflist[ifidx]->state)
+ ifp = drvr_priv->iflist[ifidx];
+
+ if (ifp->ndev)
+ ifp->ndev->last_rx = jiffies;
+
+ drvr->dstats.rx_bytes += skb->len;
+ drvr->rx_packets++; /* Local count */
+
+ if (in_interrupt())
+ netif_rx(skb);
+ else
+ /* If the receive is not processed inside an ISR,
+ * the softirqd must be woken explicitly to service
+ * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled
+ * by netif_rx_ni(), but in earlier kernels, we need
+ * to do it manually.
+ */
+ netif_rx_ni(skb);
+ }
+}
+
+void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
+{
+ uint ifidx;
+ struct brcmf_info *drvr_priv = drvr->info;
+ struct ethhdr *eh;
+ u16 type;
+
+ brcmf_proto_hdrpull(drvr, &ifidx, txp);
+
+ eh = (struct ethhdr *)(txp->data);
+ type = ntohs(eh->h_proto);
+
+ if (type == ETH_P_PAE)
+ atomic_dec(&drvr_priv->pend_8021x_cnt);
+
+}
+
+static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
+{
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
+ struct brcmf_if *ifp;
+ int ifidx;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
+ if (ifidx == BRCMF_BAD_IF)
+ return NULL;
+
+ ifp = drvr_priv->iflist[ifidx];
+
+ if (drvr_priv->pub.up)
+ /* Use the protocol to get dongle stats */
+ brcmf_proto_dstats(&drvr_priv->pub);
+
+ /* Copy dongle stats to net device stats */
+ ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets;
+ ifp->stats.tx_packets = drvr_priv->pub.dstats.tx_packets;
+ ifp->stats.rx_bytes = drvr_priv->pub.dstats.rx_bytes;
+ ifp->stats.tx_bytes = drvr_priv->pub.dstats.tx_bytes;
+ ifp->stats.rx_errors = drvr_priv->pub.dstats.rx_errors;
+ ifp->stats.tx_errors = drvr_priv->pub.dstats.tx_errors;
+ ifp->stats.rx_dropped = drvr_priv->pub.dstats.rx_dropped;
+ ifp->stats.tx_dropped = drvr_priv->pub.dstats.tx_dropped;
+ ifp->stats.multicast = drvr_priv->pub.dstats.multicast;
+
+ 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_info *drvr_priv, 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_priv->pub, 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_priv->pub, ifidx));
+ return -EOPNOTSUPP;
+ }
+
+ brcmf_dbg(INFO, "%s: could not get toe_ol: ret=%d\n",
+ brcmf_ifname(&drvr_priv->pub, 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_info *drvr_priv, int ifidx, 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));
+
+ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len);
+ if (ret < 0) {
+ brcmf_dbg(ERROR, "%s: could not set toe_ol: ret=%d\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx), ret);
+ return ret;
+ }
+
+ /* 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));
+
+ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len);
+ if (ret < 0) {
+ brcmf_dbg(ERROR, "%s: could not set toe: ret=%d\n",
+ brcmf_ifname(&drvr_priv->pub, ifidx), ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
+
+ sprintf(info->driver, KBUILD_MODNAME);
+ sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
+ sprintf(info->fw_version, "%s", BCM4329_FW_NAME);
+ sprintf(info->bus_info, "%s",
+ dev_name(brcmf_bus_get_device(drvr_priv->pub.bus)));
+}
+
+static struct ethtool_ops brcmf_ethtool_ops = {
+ .get_drvinfo = brcmf_ethtool_get_drvinfo
+};
+
+static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
+{
+ struct ethtool_drvinfo info;
+ char drvname[sizeof(info.driver)];
+ u32 cmd;
+ struct ethtool_value edata;
+ u32 toe_cmpnt, csum_dir;
+ int ret;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* all ethtool calls start with a cmd word */
+ if (copy_from_user(&cmd, uaddr, sizeof(u32)))
+ return -EFAULT;
+
+ switch (cmd) {
+ case ETHTOOL_GDRVINFO:
+ /* Copy out any request driver name */
+ if (copy_from_user(&info, uaddr, sizeof(info)))
+ return -EFAULT;
+ strncpy(drvname, info.driver, sizeof(info.driver));
+ drvname[sizeof(info.driver) - 1] = '\0';
+
+ /* clear struct for return */
+ memset(&info, 0, sizeof(info));
+ info.cmd = cmd;
+
+ /* if requested, identify ourselves */
+ if (strcmp(drvname, "?dhd") == 0) {
+ sprintf(info.driver, "dhd");
+ strcpy(info.version, BRCMF_VERSION_STR);
+ }
+
+ /* otherwise, require dongle to be up */
+ else if (!drvr_priv->pub.up) {
+ brcmf_dbg(ERROR, "dongle is not up\n");
+ return -ENODEV;
+ }
+
+ /* finally, report dongle driver type */
+ else if (drvr_priv->pub.iswl)
+ sprintf(info.driver, "wl");
+ else
+ sprintf(info.driver, "xx");
+
+ sprintf(info.version, "%lu", drvr_priv->pub.drv_version);
+ if (copy_to_user(uaddr, &info, sizeof(info)))
+ return -EFAULT;
+ brcmf_dbg(CTL, "given %*s, returning %s\n",
+ (int)sizeof(drvname), drvname, info.driver);
+ break;
+
+ /* Get toe offload components from dongle */
+ case ETHTOOL_GRXCSUM:
+ case ETHTOOL_GTXCSUM:
+ ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
+ if (ret < 0)
+ return ret;
+
+ csum_dir =
+ (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
+
+ edata.cmd = cmd;
+ edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;
+
+ if (copy_to_user(uaddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ break;
+
+ /* Set toe offload components in dongle */
+ case ETHTOOL_SRXCSUM:
+ case ETHTOOL_STXCSUM:
+ if (copy_from_user(&edata, uaddr, sizeof(edata)))
+ return -EFAULT;
+
+ /* Read the current settings, update and write back */
+ ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
+ if (ret < 0)
+ return ret;
+
+ csum_dir =
+ (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
+
+ if (edata.data != 0)
+ toe_cmpnt |= csum_dir;
+ else
+ toe_cmpnt &= ~csum_dir;
+
+ ret = brcmf_toe_set(drvr_priv, 0, 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_priv->iflist[0]->ndev->features |=
+ NETIF_F_IP_CSUM;
+ else
+ drvr_priv->iflist[0]->ndev->features &=
+ ~NETIF_F_IP_CSUM;
+ }
+
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
+ int cmd)
+{
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
+ int ifidx;
+
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
+ brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd);
+
+ if (ifidx == BRCMF_BAD_IF)
+ return -1;
+
+ if (cmd == SIOCETHTOOL)
+ return brcmf_ethtool(drvr_priv, 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_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
+ int ifidx;
+
+ memset(&dcmd, 0, sizeof(dcmd));
+ dcmd.cmd = cmd;
+ dcmd.buf = arg;
+ dcmd.len = len;
+
+ ifidx = brcmf_net2idx(drvr_priv, ndev);
+
+ if (dcmd.buf != NULL)
+ buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN);
+
+ /* send to dongle (must be up, and wl) */
+ if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) {
+ brcmf_dbg(ERROR, "DONGLE_DOWN\n");
+ err = -EIO;
+ goto done;
+ }
+
+ if (!drvr_priv->pub.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_priv->pub, ifidx, &dcmd, buflen);
+
+done:
+ if (err > 0)
+ err = 0;
+
+ return err;
+}
+
+static int brcmf_netdev_stop(struct net_device *ndev)
+{
+ struct brcmf_pub *drvr = *(struct brcmf_pub **) netdev_priv(ndev);
+
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_cfg80211_down(drvr->config);
+ if (drvr->up == 0)
+ return 0;
+
+ /* Set state and stop OS transmissions */
+ drvr->up = 0;
+ netif_stop_queue(ndev);
+
+ return 0;
+}
+
+static int brcmf_netdev_open(struct net_device *ndev)
+{
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)
+ netdev_priv(ndev);
+ u32 toe_ol;
+ int ifidx = brcmf_net2idx(drvr_priv, ndev);
+ s32 ret = 0;
+
+ brcmf_dbg(TRACE, "ifidx %d\n", ifidx);
+
+ if (ifidx == 0) { /* do it only for primary eth0 */
+
+ /* try to bring up bus */
+ ret = brcmf_bus_start(&drvr_priv->pub);
+ if (ret != 0) {
+ brcmf_dbg(ERROR, "failed with code %d\n", ret);
+ return -1;
+ }
+ atomic_set(&drvr_priv->pend_8021x_cnt, 0);
+
+ memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
+
+ /* Get current TOE mode from dongle */
+ if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0
+ && (toe_ol & TOE_TX_CSUM_OL) != 0)
+ drvr_priv->iflist[ifidx]->ndev->features |=
+ NETIF_F_IP_CSUM;
+ else
+ drvr_priv->iflist[ifidx]->ndev->features &=
+ ~NETIF_F_IP_CSUM;
+ }
+ /* Allow transmit calls */
+ netif_start_queue(ndev);
+ drvr_priv->pub.up = 1;
+ if (brcmf_cfg80211_up(drvr_priv->pub.config)) {
+ brcmf_dbg(ERROR, "failed to bring up cfg80211\n");
+ return -1;
+ }
+
+ return ret;
+}
+
+int
+brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *ndev,
+ char *name, u8 *mac_addr, u32 flags, u8 bssidx)
+{
+ struct brcmf_if *ifp;
+ int ret = 0, err = 0;
+
+ brcmf_dbg(TRACE, "idx %d, handle->%p\n", ifidx, ndev);
+
+ ifp = drvr_priv->iflist[ifidx];
+ if (!ifp) {
+ ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC);
+ if (!ifp)
+ return -ENOMEM;
+ }
+
+ memset(ifp, 0, sizeof(struct brcmf_if));
+ ifp->info = drvr_priv;
+ drvr_priv->iflist[ifidx] = ifp;
+ if (mac_addr != NULL)
+ memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
+
+ if (ndev == NULL) {
+ ifp->state = BRCMF_E_IF_ADD;
+ ifp->idx = ifidx;
+ /*
+ * Delete the existing interface before overwriting it
+ * in case we missed the BRCMF_E_IF_DEL event.
+ */
+ if (ifp->ndev != NULL) {
+ brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
+ ifp->ndev->name);
+ netif_stop_queue(ifp->ndev);
+ unregister_netdev(ifp->ndev);
+ free_netdev(ifp->ndev);
+ }
+
+ /* Allocate netdev, including space for private structure */
+ ifp->ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d",
+ ether_setup);
+ if (!ifp->ndev) {
+ brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
+ ret = -ENOMEM;
+ }
+
+ if (ret == 0) {
+ memcpy(netdev_priv(ifp->ndev), &drvr_priv,
+ sizeof(drvr_priv));
+ err = brcmf_net_attach(&drvr_priv->pub, ifp->idx);
+ if (err != 0) {
+ brcmf_dbg(ERROR, "brcmf_net_attach failed, err %d\n",
+ err);
+ ret = -EOPNOTSUPP;
+ } else {
+ brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
+ current->pid, ifp->ndev->name);
+ ifp->state = 0;
+ }
+ }
+
+ if (ret < 0) {
+ if (ifp->ndev)
+ free_netdev(ifp->ndev);
+
+ drvr_priv->iflist[ifp->idx] = NULL;
+ kfree(ifp);
+ }
+ } else
+ ifp->ndev = ndev;
+
+ return 0;
+}
+
+void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
+{
+ struct brcmf_if *ifp;
+
+ brcmf_dbg(TRACE, "idx %d\n", ifidx);
+
+ ifp = drvr_priv->iflist[ifidx];
+ if (!ifp) {
+ brcmf_dbg(ERROR, "Null interface\n");
+ return;
+ }
+
+ ifp->state = BRCMF_E_IF_DEL;
+ ifp->idx = ifidx;
+ if (ifp->ndev != NULL) {
+ netif_stop_queue(ifp->ndev);
+ unregister_netdev(ifp->ndev);
+ free_netdev(ifp->ndev);
+ drvr_priv->iflist[ifidx] = NULL;
+ kfree(ifp);
+ }
+}
+
+struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
+{
+ struct brcmf_info *drvr_priv = NULL;
+ struct net_device *ndev;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Allocate netdev, including space for private structure */
+ ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", ether_setup);
+ if (!ndev) {
+ brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
+ goto fail;
+ }
+
+ /* Allocate primary brcmf_info */
+ drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
+ if (!drvr_priv)
+ goto fail;
+
+ /*
+ * Save the brcmf_info into the priv
+ */
+ memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv));
+
+ if (brcmf_add_if(drvr_priv, 0, ndev, ndev->name, NULL, 0, 0) ==
+ BRCMF_BAD_IF)
+ goto fail;
+
+ ndev->netdev_ops = NULL;
+ mutex_init(&drvr_priv->proto_block);
+
+ /* Link to info module */
+ drvr_priv->pub.info = drvr_priv;
+
+ /* Link to bus module */
+ drvr_priv->pub.bus = bus;
+ drvr_priv->pub.hdrlen = bus_hdrlen;
+
+ /* Attach and link in the protocol */
+ if (brcmf_proto_attach(&drvr_priv->pub) != 0) {
+ brcmf_dbg(ERROR, "brcmf_prot_attach failed\n");
+ goto fail;
+ }
+
+ /* Attach and link in the cfg80211 */
+ drvr_priv->pub.config =
+ brcmf_cfg80211_attach(ndev,
+ brcmf_bus_get_device(bus),
+ &drvr_priv->pub);
+ if (drvr_priv->pub.config == NULL) {
+ brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
+ goto fail;
+ }
+
+ INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address);
+ INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list);
+
+ /*
+ * Save the brcmf_info into the priv
+ */
+ memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv));
+
+ return &drvr_priv->pub;
+
+fail:
+ if (ndev)
+ free_netdev(ndev);
+ if (drvr_priv)
+ brcmf_detach(&drvr_priv->pub);
+
+ return NULL;
+}
+
+int brcmf_bus_start(struct brcmf_pub *drvr)
+{
+ int ret = -1;
+ struct brcmf_info *drvr_priv = drvr->info;
+ /* Room for "event_msgs" + '\0' + bitvec */
+ char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
+
+ brcmf_dbg(TRACE, "\n");
+
+ /* Bring up the bus */
+ ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub);
+ if (ret != 0) {
+ brcmf_dbg(ERROR, "brcmf_sdbrcm_bus_init failed %d\n", ret);
+ return ret;
+ }
+
+ /* If bus is not ready, can't come up */
+ if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) {
+ brcmf_dbg(ERROR, "failed bus is not ready\n");
+ return -ENODEV;
+ }
+
+ 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_priv->pub);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct net_device_ops brcmf_netdev_ops_pri = {
+ .ndo_open = brcmf_netdev_open,
+ .ndo_stop = brcmf_netdev_stop,
+ .ndo_get_stats = brcmf_netdev_get_stats,
+ .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
+ .ndo_start_xmit = brcmf_netdev_start_xmit,
+ .ndo_set_mac_address = brcmf_netdev_set_mac_address,
+ .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
+};
+
+int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
+{
+ struct brcmf_info *drvr_priv = drvr->info;
+ struct net_device *ndev;
+ u8 temp_addr[ETH_ALEN] = {
+ 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33};
+
+ brcmf_dbg(TRACE, "ifidx %d\n", ifidx);
+
+ ndev = drvr_priv->iflist[ifidx]->ndev;
+ ndev->netdev_ops = &brcmf_netdev_ops_pri;
+
+ /*
+ * We have to use the primary MAC for virtual interfaces
+ */
+ if (ifidx != 0) {
+ /* for virtual interfaces use the primary MAC */
+ memcpy(temp_addr, drvr_priv->pub.mac, ETH_ALEN);
+
+ }
+
+ if (ifidx == 1) {
+ brcmf_dbg(TRACE, "ACCESS POINT MAC:\n");
+ /* ACCESSPOINT INTERFACE CASE */
+ temp_addr[0] |= 0X02; /* set bit 2 ,
+ - Locally Administered address */
+
+ }
+ ndev->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen;
+ ndev->ethtool_ops = &brcmf_ethtool_ops;
+
+ drvr_priv->pub.rxsz = ndev->mtu + ndev->hard_header_len +
+ drvr_priv->pub.hdrlen;
+
+ memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
+
+ if (register_netdev(ndev) != 0) {
+ brcmf_dbg(ERROR, "couldn't register the net device\n");
+ goto fail;
+ }
+
+ brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
+
+ return 0;
+
+fail:
+ ndev->netdev_ops = NULL;
+ return -EBADE;
+}
+
+static void brcmf_bus_detach(struct brcmf_pub *drvr)
+{
+ struct brcmf_info *drvr_priv;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (drvr) {
+ drvr_priv = drvr->info;
+ if (drvr_priv) {
+ /* Stop the protocol module */
+ brcmf_proto_stop(&drvr_priv->pub);
+
+ /* Stop the bus module */
+ brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus);
+ }
+ }
+}
+
+void brcmf_detach(struct brcmf_pub *drvr)
+{
+ struct brcmf_info *drvr_priv;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (drvr) {
+ drvr_priv = drvr->info;
+ if (drvr_priv) {
+ struct brcmf_if *ifp;
+ int i;
+
+ for (i = 1; i < BRCMF_MAX_IFS; i++)
+ if (drvr_priv->iflist[i])
+ brcmf_del_if(drvr_priv, i);
+
+ ifp = drvr_priv->iflist[0];
+ if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+ rtnl_lock();
+ brcmf_netdev_stop(ifp->ndev);
+ rtnl_unlock();
+ unregister_netdev(ifp->ndev);
+ }
+
+ cancel_work_sync(&drvr_priv->setmacaddr_work);
+ cancel_work_sync(&drvr_priv->multicast_work);
+
+ brcmf_bus_detach(drvr);
+
+ if (drvr->prot)
+ brcmf_proto_detach(drvr);
+
+ brcmf_cfg80211_detach(drvr->config);
+
+ free_netdev(ifp->ndev);
+ kfree(ifp);
+ kfree(drvr_priv);
+ }
+ }
+}
+
+static void __exit brcmf_module_cleanup(void)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ brcmf_bus_unregister();
+}
+
+static int __init brcmf_module_init(void)
+{
+ int error;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ error = brcmf_bus_register();
+
+ if (error) {
+ brcmf_dbg(ERROR, "brcmf_bus_register failed\n");
+ goto failed;
+ }
+ return 0;
+
+failed:
+ return -EINVAL;
+}
+
+module_init(brcmf_module_init);
+module_exit(brcmf_module_cleanup);
+
+int brcmf_os_proto_block(struct brcmf_pub *drvr)
+{
+ struct brcmf_info *drvr_priv = drvr->info;
+
+ if (drvr_priv) {
+ mutex_lock(&drvr_priv->proto_block);
+ return 1;
+ }
+ return 0;
+}
+
+int brcmf_os_proto_unblock(struct brcmf_pub *drvr)
+{
+ struct brcmf_info *drvr_priv = drvr->info;
+
+ if (drvr_priv) {
+ mutex_unlock(&drvr_priv->proto_block);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
+{
+ return atomic_read(&drvr_priv->pend_8021x_cnt);
+}
+
+#define MAX_WAIT_FOR_8021X_TX 10
+
+int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
+{
+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(ndev);
+ int timeout = 10 * HZ / 1000;
+ int ntimes = MAX_WAIT_FOR_8021X_TX;
+ int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
+
+ 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_priv);
+ }
+ return pend;
+}
+
+#ifdef BCMDBG
+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;
+ }
+
+ /* Write buf to file */
+ fp->f_op->write(fp, (char __user *)buf, size, &pos);
+
+exit:
+ /* free buf before return */
+ kfree(buf);
+ /* close file before return */
+ if (fp)
+ filp_close(fp, current->files);
+ /* restore previous address limit */
+ set_fs(old_fs);
+
+ return ret;
+}
+#endif /* BCMDBG */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
index ff788b37afdc..4ee1ea846f6d 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
@@ -17,14 +17,6 @@
#ifndef _BRCMF_PROTO_H_
#define _BRCMF_PROTO_H_
-#ifndef IOCTL_RESP_TIMEOUT
-#define IOCTL_RESP_TIMEOUT 2000 /* In milli second */
-#endif
-
-#ifndef IOCTL_CHIP_ACTIVE_TIMEOUT
-#define IOCTL_CHIP_ACTIVE_TIMEOUT 10 /* In milli second */
-#endif
-
/*
* Exported from the brcmf protocol module (brcmf_cdc)
*/
@@ -53,23 +45,16 @@ extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx,
struct sk_buff *rxp);
-/* Use protocol to issue ioctl to dongle */
-extern int brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx,
- struct brcmf_ioctl *ioc, void *buf, int len);
-
-/* Add prot dump output to a buffer */
-extern void brcmf_proto_dump(struct brcmf_pub *drvr,
- struct brcmu_strbuf *strbuf);
+/* Use protocol to issue command to dongle */
+extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx,
+ struct brcmf_dcmd *dcmd, int len);
/* Update local copy of dongle statistics */
extern void brcmf_proto_dstats(struct brcmf_pub *drvr);
-extern int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc,
- void *buf, uint buflen);
-
-extern int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr);
+extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr);
-extern int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx,
+extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx,
uint cmd, void *buf, uint len);
#endif /* _BRCMF_PROTO_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
new file mode 100644
index 000000000000..313b8bf592d1
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -0,0 +1,4591 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/printk.h>
+#include <linux/pci_ids.h>
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+#include <linux/semaphore.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
+#include <defs.h>
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include <brcm_hw_ids.h>
+#include <soc.h>
+#include "sdio_host.h"
+
+#define DCMD_RESP_TIMEOUT 2000 /* In milli second */
+
+#ifdef BCMDBG
+
+#define BRCMF_TRAP_INFO_SIZE 80
+
+#define CBUF_LEN (128)
+
+struct rte_log_le {
+ __le32 buf; /* Can't be pointer on (64-bit) hosts */
+ __le32 buf_size;
+ __le32 idx;
+ char *_buf_compat; /* Redundant pointer for backward compat. */
+};
+
+struct rte_console {
+ /* Virtual UART
+ * When there is no UART (e.g. Quickturn),
+ * the host should write a complete
+ * input line directly into cbuf and then write
+ * the length into vcons_in.
+ * This may also be used when there is a real UART
+ * (at risk of conflicting with
+ * the real UART). vcons_out is currently unused.
+ */
+ uint vcons_in;
+ uint vcons_out;
+
+ /* Output (logging) buffer
+ * Console output is written to a ring buffer log_buf at index log_idx.
+ * The host may read the output when it sees log_idx advance.
+ * Output will be lost if the output wraps around faster than the host
+ * polls.
+ */
+ struct rte_log_le log_le;
+
+ /* Console input line buffer
+ * Characters are read one at a time into cbuf
+ * until <CR> is received, then
+ * the buffer is processed as a command line.
+ * Also used for virtual UART.
+ */
+ uint cbuf_idx;
+ char cbuf[CBUF_LEN];
+};
+
+#endif /* BCMDBG */
+#include <chipcommon.h>
+
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_proto.h"
+#include "dhd_dbg.h"
+#include <bcmchip.h>
+
+#define TXQLEN 2048 /* bulk tx queue length */
+#define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */
+#define TXLOW (TXHI - 256) /* turn off flow control below TXLOW */
+#define PRIOMASK 7
+
+#define TXRETRIES 2 /* # of retries for tx frames */
+
+#define BRCMF_RXBOUND 50 /* Default for max rx frames in
+ one scheduling */
+
+#define BRCMF_TXBOUND 20 /* Default for max tx frames in
+ one scheduling */
+
+#define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */
+
+#define MEMBLOCK 2048 /* Block size used for downloading
+ of dongle image */
+#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold
+ biggest possible glom */
+
+#define BRCMF_FIRSTREAD (1 << 6)
+
+
+/* SBSDIO_DEVICE_CTL */
+
+/* 1: device will assert busy signal when receiving CMD53 */
+#define SBSDIO_DEVCTL_SETBUSY 0x01
+/* 1: assertion of sdio interrupt is synchronous to the sdio clock */
+#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02
+/* 1: mask all interrupts to host except the chipActive (rev 8) */
+#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04
+/* 1: isolate internal sdio signals, put external pads in tri-state; requires
+ * sdio bus power cycle to clear (rev 9) */
+#define SBSDIO_DEVCTL_PADS_ISO 0x08
+/* Force SD->SB reset mapping (rev 11) */
+#define SBSDIO_DEVCTL_SB_RST_CTL 0x30
+/* Determined by CoreControl bit */
+#define SBSDIO_DEVCTL_RST_CORECTL 0x00
+/* Force backplane reset */
+#define SBSDIO_DEVCTL_RST_BPRESET 0x10
+/* Force no backplane reset */
+#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20
+
+/* SBSDIO_FUNC1_CHIPCLKCSR */
+
+/* Force ALP request to backplane */
+#define SBSDIO_FORCE_ALP 0x01
+/* Force HT request to backplane */
+#define SBSDIO_FORCE_HT 0x02
+/* Force ILP request to backplane */
+#define SBSDIO_FORCE_ILP 0x04
+/* Make ALP ready (power up xtal) */
+#define SBSDIO_ALP_AVAIL_REQ 0x08
+/* Make HT ready (power up PLL) */
+#define SBSDIO_HT_AVAIL_REQ 0x10
+/* Squelch clock requests from HW */
+#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20
+/* Status: ALP is ready */
+#define SBSDIO_ALP_AVAIL 0x40
+/* Status: HT is ready */
+#define SBSDIO_HT_AVAIL 0x80
+
+#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
+#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
+#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
+#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
+
+#define SBSDIO_CLKAV(regval, alponly) \
+ (SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval)))
+
+/* direct(mapped) cis space */
+
+/* MAPPED common CIS address */
+#define SBSDIO_CIS_BASE_COMMON 0x1000
+/* maximum bytes in one CIS */
+#define SBSDIO_CIS_SIZE_LIMIT 0x200
+/* cis offset addr is < 17 bits */
+#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF
+
+/* manfid tuple length, include tuple, link bytes */
+#define SBSDIO_CIS_MANFID_TUPLE_LEN 6
+
+/* intstatus */
+#define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */
+#define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */
+#define I_SMB_SW2 (1 << 2) /* To SB Mail S/W interrupt 2 */
+#define I_SMB_SW3 (1 << 3) /* To SB Mail S/W interrupt 3 */
+#define I_SMB_SW_MASK 0x0000000f /* To SB Mail S/W interrupts mask */
+#define I_SMB_SW_SHIFT 0 /* To SB Mail S/W interrupts shift */
+#define I_HMB_SW0 (1 << 4) /* To Host Mail S/W interrupt 0 */
+#define I_HMB_SW1 (1 << 5) /* To Host Mail S/W interrupt 1 */
+#define I_HMB_SW2 (1 << 6) /* To Host Mail S/W interrupt 2 */
+#define I_HMB_SW3 (1 << 7) /* To Host Mail S/W interrupt 3 */
+#define I_HMB_SW_MASK 0x000000f0 /* To Host Mail S/W interrupts mask */
+#define I_HMB_SW_SHIFT 4 /* To Host Mail S/W interrupts shift */
+#define I_WR_OOSYNC (1 << 8) /* Write Frame Out Of Sync */
+#define I_RD_OOSYNC (1 << 9) /* Read Frame Out Of Sync */
+#define I_PC (1 << 10) /* descriptor error */
+#define I_PD (1 << 11) /* data error */
+#define I_DE (1 << 12) /* Descriptor protocol Error */
+#define I_RU (1 << 13) /* Receive descriptor Underflow */
+#define I_RO (1 << 14) /* Receive fifo Overflow */
+#define I_XU (1 << 15) /* Transmit fifo Underflow */
+#define I_RI (1 << 16) /* Receive Interrupt */
+#define I_BUSPWR (1 << 17) /* SDIO Bus Power Change (rev 9) */
+#define I_XMTDATA_AVAIL (1 << 23) /* bits in fifo */
+#define I_XI (1 << 24) /* Transmit Interrupt */
+#define I_RF_TERM (1 << 25) /* Read Frame Terminate */
+#define I_WF_TERM (1 << 26) /* Write Frame Terminate */
+#define I_PCMCIA_XU (1 << 27) /* PCMCIA Transmit FIFO Underflow */
+#define I_SBINT (1 << 28) /* sbintstatus Interrupt */
+#define I_CHIPACTIVE (1 << 29) /* chip from doze to active state */
+#define I_SRESET (1 << 30) /* CCCR RES interrupt */
+#define I_IOE2 (1U << 31) /* CCCR IOE2 Bit Changed */
+#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)
+#define I_DMA (I_RI | I_XI | I_ERRORS)
+
+/* corecontrol */
+#define CC_CISRDY (1 << 0) /* CIS Ready */
+#define CC_BPRESEN (1 << 1) /* CCCR RES signal */
+#define CC_F2RDY (1 << 2) /* set CCCR IOR2 bit */
+#define CC_CLRPADSISO (1 << 3) /* clear SDIO pads isolation */
+#define CC_XMTDATAAVAIL_MODE (1 << 4)
+#define CC_XMTDATAAVAIL_CTRL (1 << 5)
+
+/* SDA_FRAMECTRL */
+#define SFC_RF_TERM (1 << 0) /* Read Frame Terminate */
+#define SFC_WF_TERM (1 << 1) /* Write Frame Terminate */
+#define SFC_CRC4WOOS (1 << 2) /* CRC error for write out of sync */
+#define SFC_ABORTALL (1 << 3) /* Abort all in-progress frames */
+
+/* HW frame tag */
+#define SDPCM_FRAMETAG_LEN 4 /* 2 bytes len, 2 bytes check val */
+
+/* Total length of frame header for dongle protocol */
+#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
+#define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN)
+
+/*
+ * Software allocation of To SB Mailbox resources
+ */
+
+/* tosbmailbox bits corresponding to intstatus bits */
+#define SMB_NAK (1 << 0) /* Frame NAK */
+#define SMB_INT_ACK (1 << 1) /* Host Interrupt ACK */
+#define SMB_USE_OOB (1 << 2) /* Use OOB Wakeup */
+#define SMB_DEV_INT (1 << 3) /* Miscellaneous Interrupt */
+
+/* tosbmailboxdata */
+#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version */
+
+/*
+ * Software allocation of To Host Mailbox resources
+ */
+
+/* intstatus bits */
+#define I_HMB_FC_STATE I_HMB_SW0 /* Flow Control State */
+#define I_HMB_FC_CHANGE I_HMB_SW1 /* Flow Control State Changed */
+#define I_HMB_FRAME_IND I_HMB_SW2 /* Frame Indication */
+#define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */
+
+/* tohostmailboxdata */
+#define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */
+#define HMB_DATA_DEVREADY 2 /* talk to host after enable */
+#define HMB_DATA_FC 4 /* per prio flowcontrol update flag */
+#define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */
+
+#define HMB_DATA_FCDATA_MASK 0xff000000
+#define HMB_DATA_FCDATA_SHIFT 24
+
+#define HMB_DATA_VERSION_MASK 0x00ff0000
+#define HMB_DATA_VERSION_SHIFT 16
+
+/*
+ * Software-defined protocol header
+ */
+
+/* Current protocol version */
+#define SDPCM_PROT_VERSION 4
+
+/* SW frame header */
+#define SDPCM_PACKET_SEQUENCE(p) (((u8 *)p)[0] & 0xff)
+
+#define SDPCM_CHANNEL_MASK 0x00000f00
+#define SDPCM_CHANNEL_SHIFT 8
+#define SDPCM_PACKET_CHANNEL(p) (((u8 *)p)[1] & 0x0f)
+
+#define SDPCM_NEXTLEN_OFFSET 2
+
+/* Data Offset from SOF (HW Tag, SW Tag, Pad) */
+#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */
+#define SDPCM_DOFFSET_VALUE(p) (((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff)
+#define SDPCM_DOFFSET_MASK 0xff000000
+#define SDPCM_DOFFSET_SHIFT 24
+#define SDPCM_FCMASK_OFFSET 4 /* Flow control */
+#define SDPCM_FCMASK_VALUE(p) (((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff)
+#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */
+#define SDPCM_WINDOW_VALUE(p) (((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff)
+
+#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */
+
+/* logical channel numbers */
+#define SDPCM_CONTROL_CHANNEL 0 /* Control channel Id */
+#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */
+#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */
+#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets */
+#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */
+
+#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for 8bit frame seq */
+
+#define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80)
+
+/*
+ * Shared structure between dongle and the host.
+ * The structure contains pointers to trap or assert information.
+ */
+#define SDPCM_SHARED_VERSION 0x0002
+#define SDPCM_SHARED_VERSION_MASK 0x00FF
+#define SDPCM_SHARED_ASSERT_BUILT 0x0100
+#define SDPCM_SHARED_ASSERT 0x0200
+#define SDPCM_SHARED_TRAP 0x0400
+
+/* Space for header read, limit for data packets */
+#define MAX_HDR_READ (1 << 6)
+#define MAX_RX_DATASZ 2048
+
+/* Maximum milliseconds to wait for F2 to come up */
+#define BRCMF_WAIT_F2RDY 3000
+
+/* Bump up limit on waiting for HT to account for first startup;
+ * if the image is doing a CRC calculation before programming the PMU
+ * for HT availability, it could take a couple hundred ms more, so
+ * max out at a 1 second (1000000us).
+ */
+#undef PMU_MAX_TRANSITION_DLY
+#define PMU_MAX_TRANSITION_DLY 1000000
+
+/* Value for ChipClockCSR during initial setup */
+#define BRCMF_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \
+ SBSDIO_ALP_AVAIL_REQ)
+
+/* Flags for SDH calls */
+#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
+
+/* sbimstate */
+#define SBIM_IBE 0x20000 /* inbanderror */
+#define SBIM_TO 0x40000 /* timeout */
+#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */
+#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */
+
+/* sbtmstatelow */
+
+/* reset */
+#define SBTML_RESET 0x0001
+/* reject field */
+#define SBTML_REJ_MASK 0x0006
+/* reject */
+#define SBTML_REJ 0x0002
+/* temporary reject, for error recovery */
+#define SBTML_TMPREJ 0x0004
+
+/* Shift to locate the SI control flags in sbtml */
+#define SBTML_SICF_SHIFT 16
+
+/* sbtmstatehigh */
+#define SBTMH_SERR 0x0001 /* serror */
+#define SBTMH_INT 0x0002 /* interrupt */
+#define SBTMH_BUSY 0x0004 /* busy */
+#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */
+
+/* Shift to locate the SI status flags in sbtmh */
+#define SBTMH_SISF_SHIFT 16
+
+/* sbidlow */
+#define SBIDL_INIT 0x80 /* initiator */
+
+/* sbidhigh */
+#define SBIDH_RC_MASK 0x000f /* revision code */
+#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
+#define SBIDH_RCE_SHIFT 8
+#define SBCOREREV(sbidh) \
+ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | \
+ ((sbidh) & SBIDH_RC_MASK))
+#define SBIDH_CC_MASK 0x8ff0 /* core code */
+#define SBIDH_CC_SHIFT 4
+#define SBIDH_VC_MASK 0xffff0000 /* vendor code */
+#define SBIDH_VC_SHIFT 16
+
+/*
+ * Conversion of 802.1D priority to precedence level
+ */
+static uint prio2prec(u32 prio)
+{
+ return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ?
+ (prio^2) : prio;
+}
+
+/*
+ * Core reg address translation.
+ * Both macro's returns a 32 bits byte address on the backplane bus.
+ */
+#define CORE_CC_REG(base, field) \
+ (base + offsetof(struct chipcregs, field))
+#define CORE_BUS_REG(base, field) \
+ (base + offsetof(struct sdpcmd_regs, field))
+#define CORE_SB(base, field) \
+ (base + SBCONFIGOFF + offsetof(struct sbconfig, field))
+
+/* core registers */
+struct sdpcmd_regs {
+ u32 corecontrol; /* 0x00, rev8 */
+ u32 corestatus; /* rev8 */
+ u32 PAD[1];
+ u32 biststatus; /* rev8 */
+
+ /* PCMCIA access */
+ u16 pcmciamesportaladdr; /* 0x010, rev8 */
+ u16 PAD[1];
+ u16 pcmciamesportalmask; /* rev8 */
+ u16 PAD[1];
+ u16 pcmciawrframebc; /* rev8 */
+ u16 PAD[1];
+ u16 pcmciaunderflowtimer; /* rev8 */
+ u16 PAD[1];
+
+ /* interrupt */
+ u32 intstatus; /* 0x020, rev8 */
+ u32 hostintmask; /* rev8 */
+ u32 intmask; /* rev8 */
+ u32 sbintstatus; /* rev8 */
+ u32 sbintmask; /* rev8 */
+ u32 funcintmask; /* rev4 */
+ u32 PAD[2];
+ u32 tosbmailbox; /* 0x040, rev8 */
+ u32 tohostmailbox; /* rev8 */
+ u32 tosbmailboxdata; /* rev8 */
+ u32 tohostmailboxdata; /* rev8 */
+
+ /* synchronized access to registers in SDIO clock domain */
+ u32 sdioaccess; /* 0x050, rev8 */
+ u32 PAD[3];
+
+ /* PCMCIA frame control */
+ u8 pcmciaframectrl; /* 0x060, rev8 */
+ u8 PAD[3];
+ u8 pcmciawatermark; /* rev8 */
+ u8 PAD[155];
+
+ /* interrupt batching control */
+ u32 intrcvlazy; /* 0x100, rev8 */
+ u32 PAD[3];
+
+ /* counters */
+ u32 cmd52rd; /* 0x110, rev8 */
+ u32 cmd52wr; /* rev8 */
+ u32 cmd53rd; /* rev8 */
+ u32 cmd53wr; /* rev8 */
+ u32 abort; /* rev8 */
+ u32 datacrcerror; /* rev8 */
+ u32 rdoutofsync; /* rev8 */
+ u32 wroutofsync; /* rev8 */
+ u32 writebusy; /* rev8 */
+ u32 readwait; /* rev8 */
+ u32 readterm; /* rev8 */
+ u32 writeterm; /* rev8 */
+ u32 PAD[40];
+ u32 clockctlstatus; /* rev8 */
+ u32 PAD[7];
+
+ u32 PAD[128]; /* DMA engines */
+
+ /* SDIO/PCMCIA CIS region */
+ char cis[512]; /* 0x400-0x5ff, rev6 */
+
+ /* PCMCIA function control registers */
+ char pcmciafcr[256]; /* 0x600-6ff, rev6 */
+ u16 PAD[55];
+
+ /* PCMCIA backplane access */
+ u16 backplanecsr; /* 0x76E, rev6 */
+ u16 backplaneaddr0; /* rev6 */
+ u16 backplaneaddr1; /* rev6 */
+ u16 backplaneaddr2; /* rev6 */
+ u16 backplaneaddr3; /* rev6 */
+ u16 backplanedata0; /* rev6 */
+ u16 backplanedata1; /* rev6 */
+ u16 backplanedata2; /* rev6 */
+ u16 backplanedata3; /* rev6 */
+ u16 PAD[31];
+
+ /* sprom "size" & "blank" info */
+ u16 spromstatus; /* 0x7BE, rev2 */
+ u32 PAD[464];
+
+ u16 PAD[0x80];
+};
+
+#ifdef BCMDBG
+/* Device console log buffer state */
+struct brcmf_console {
+ uint count; /* Poll interval msec counter */
+ uint log_addr; /* Log struct address (fixed) */
+ struct rte_log_le log_le; /* Log struct (host copy) */
+ uint bufsize; /* Size of log buffer */
+ u8 *buf; /* Log buffer (host copy) */
+ uint last; /* Last buffer read index */
+};
+#endif /* BCMDBG */
+
+struct sdpcm_shared {
+ u32 flags;
+ u32 trap_addr;
+ u32 assert_exp_addr;
+ u32 assert_file_addr;
+ u32 assert_line;
+ u32 console_addr; /* Address of struct rte_console */
+ u32 msgtrace_addr;
+ u8 tag[32];
+};
+
+struct sdpcm_shared_le {
+ __le32 flags;
+ __le32 trap_addr;
+ __le32 assert_exp_addr;
+ __le32 assert_file_addr;
+ __le32 assert_line;
+ __le32 console_addr; /* Address of struct rte_console */
+ __le32 msgtrace_addr;
+ u8 tag[32];
+};
+
+
+/* misc chip info needed by some of the routines */
+struct chip_info {
+ u32 chip;
+ u32 chiprev;
+ u32 cccorebase;
+ u32 ccrev;
+ u32 cccaps;
+ u32 buscorebase; /* 32 bits backplane bus address */
+ u32 buscorerev;
+ u32 buscoretype;
+ u32 ramcorebase;
+ u32 armcorebase;
+ u32 pmurev;
+ u32 ramsize;
+};
+
+/* Private data for SDIO bus interaction */
+struct brcmf_bus {
+ struct brcmf_pub *drvr;
+
+ struct brcmf_sdio_dev *sdiodev; /* sdio device handler */
+ struct chip_info *ci; /* Chip info struct */
+ char *vars; /* Variables (from CIS and/or other) */
+ uint varsz; /* Size of variables buffer */
+
+ u32 ramsize; /* Size of RAM in SOCRAM (bytes) */
+
+ u32 hostintmask; /* Copy of Host Interrupt Mask */
+ u32 intstatus; /* Intstatus bits (events) pending */
+ bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
+ bool fcstate; /* State of dongle flow-control */
+
+ uint blocksize; /* Block size of SDIO transfers */
+ uint roundup; /* Max roundup limit */
+
+ struct pktq txq; /* Queue length used for flow-control */
+ u8 flowcontrol; /* per prio flow control bitmask */
+ u8 tx_seq; /* Transmit sequence number (next) */
+ u8 tx_max; /* Maximum transmit sequence allowed */
+
+ u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN];
+ u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */
+ u16 nextlen; /* Next Read Len from last header */
+ u8 rx_seq; /* Receive sequence number (expected) */
+ bool rxskip; /* Skip receive (awaiting NAK ACK) */
+
+ uint rxbound; /* Rx frames to read before resched */
+ uint txbound; /* Tx frames to send before resched */
+ uint txminmax;
+
+ struct sk_buff *glomd; /* Packet containing glomming descriptor */
+ struct sk_buff *glom; /* Packet chain for glommed superframe */
+ uint glomerr; /* Glom packet read errors */
+
+ u8 *rxbuf; /* Buffer for receiving control packets */
+ uint rxblen; /* Allocated length of rxbuf */
+ u8 *rxctl; /* Aligned pointer into rxbuf */
+ u8 *databuf; /* Buffer for receiving big glom packet */
+ u8 *dataptr; /* Aligned pointer into databuf */
+ uint rxlen; /* Length of valid data in buffer */
+
+ u8 sdpcm_ver; /* Bus protocol reported by dongle */
+
+ bool intr; /* Use interrupts */
+ bool poll; /* Use polling */
+ bool ipend; /* Device interrupt is pending */
+ uint intrcount; /* Count of device interrupt callbacks */
+ uint lastintrs; /* Count as of last watchdog timer */
+ uint spurious; /* Count of spurious interrupts */
+ uint pollrate; /* Ticks between device polls */
+ uint polltick; /* Tick counter */
+ uint pollcnt; /* Count of active polls */
+
+#ifdef BCMDBG
+ uint console_interval;
+ struct brcmf_console console; /* Console output polling support */
+ uint console_addr; /* Console address from shared struct */
+#endif /* BCMDBG */
+
+ uint regfails; /* Count of R_REG failures */
+
+ uint clkstate; /* State of sd and backplane clock(s) */
+ bool activity; /* Activity flag for clock down */
+ s32 idletime; /* Control for activity timeout */
+ s32 idlecount; /* Activity timeout counter */
+ s32 idleclock; /* How to set bus driver when idle */
+ s32 sd_rxchain;
+ bool use_rxchain; /* If brcmf should use PKT chains */
+ bool sleeping; /* Is SDIO bus sleeping? */
+ bool rxflow_mode; /* Rx flow control mode */
+ bool rxflow; /* Is rx flow control on */
+ bool alp_only; /* Don't use HT clock (ALP only) */
+/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
+ bool usebufpool;
+
+ /* Some additional counters */
+ uint tx_sderrs; /* Count of tx attempts with sd errors */
+ uint fcqueued; /* Tx packets that got queued */
+ uint rxrtx; /* Count of rtx requests (NAK to dongle) */
+ uint rx_toolong; /* Receive frames too long to receive */
+ uint rxc_errors; /* SDIO errors when reading control frames */
+ uint rx_hdrfail; /* SDIO errors on header reads */
+ uint rx_badhdr; /* Bad received headers (roosync?) */
+ uint rx_badseq; /* Mismatched rx sequence number */
+ uint fc_rcvd; /* Number of flow-control events received */
+ uint fc_xoff; /* Number which turned on flow-control */
+ uint fc_xon; /* Number which turned off flow-control */
+ uint rxglomfail; /* Failed deglom attempts */
+ uint rxglomframes; /* Number of glom frames (superframes) */
+ uint rxglompkts; /* Number of packets from glom frames */
+ uint f2rxhdrs; /* Number of header reads */
+ uint f2rxdata; /* Number of frame data reads */
+ uint f2txdata; /* Number of f2 frame writes */
+ uint f1regdata; /* Number of f1 register accesses */
+
+ u8 *ctrl_frame_buf;
+ u32 ctrl_frame_len;
+ bool ctrl_frame_stat;
+
+ spinlock_t txqlock;
+ wait_queue_head_t ctrl_wait;
+ wait_queue_head_t dcmd_resp_wait;
+
+ struct timer_list timer;
+ struct completion watchdog_wait;
+ struct task_struct *watchdog_tsk;
+ bool wd_timer_valid;
+ uint save_ms;
+
+ struct task_struct *dpc_tsk;
+ struct completion dpc_wait;
+
+ struct semaphore sdsem;
+
+ const char *fw_name;
+ const struct firmware *firmware;
+ const char *nv_name;
+ u32 fw_ptr;
+};
+
+struct sbconfig {
+ u32 PAD[2];
+ u32 sbipsflag; /* initiator port ocp slave flag */
+ u32 PAD[3];
+ u32 sbtpsflag; /* target port ocp slave flag */
+ u32 PAD[11];
+ u32 sbtmerrloga; /* (sonics >= 2.3) */
+ u32 PAD;
+ u32 sbtmerrlog; /* (sonics >= 2.3) */
+ u32 PAD[3];
+ u32 sbadmatch3; /* address match3 */
+ u32 PAD;
+ u32 sbadmatch2; /* address match2 */
+ u32 PAD;
+ u32 sbadmatch1; /* address match1 */
+ u32 PAD[7];
+ u32 sbimstate; /* initiator agent state */
+ u32 sbintvec; /* interrupt mask */
+ u32 sbtmstatelow; /* target state */
+ u32 sbtmstatehigh; /* target state */
+ u32 sbbwa0; /* bandwidth allocation table0 */
+ u32 PAD;
+ u32 sbimconfiglow; /* initiator configuration */
+ u32 sbimconfighigh; /* initiator configuration */
+ u32 sbadmatch0; /* address match0 */
+ u32 PAD;
+ u32 sbtmconfiglow; /* target configuration */
+ u32 sbtmconfighigh; /* target configuration */
+ u32 sbbconfig; /* broadcast configuration */
+ u32 PAD;
+ u32 sbbstate; /* broadcast state */
+ u32 PAD[3];
+ u32 sbactcnfg; /* activate configuration */
+ u32 PAD[3];
+ u32 sbflagst; /* current sbflags */
+ u32 PAD[3];
+ u32 sbidlow; /* identification */
+ u32 sbidhigh; /* identification */
+};
+
+/* clkstate */
+#define CLK_NONE 0
+#define CLK_SDONLY 1
+#define CLK_PENDING 2 /* Not used yet */
+#define CLK_AVAIL 3
+
+#ifdef BCMDBG
+static int qcount[NUMPRIO];
+static int tx_packets[NUMPRIO];
+#endif /* BCMDBG */
+
+#define SDIO_DRIVE_STRENGTH 6 /* in milliamps */
+
+#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL)
+
+/* Retry count for register access failures */
+static const uint retry_limit = 2;
+
+/* Limit on rounding up frames */
+static const uint max_roundup = 512;
+
+#define ALIGNMENT 4
+
+static void pkt_align(struct sk_buff *p, int len, int align)
+{
+ uint datalign;
+ datalign = (unsigned long)(p->data);
+ datalign = roundup(datalign, (align)) - datalign;
+ if (datalign)
+ skb_pull(p, datalign);
+ __skb_trim(p, len);
+}
+
+/* To check if there's window offered */
+static bool data_ok(struct brcmf_bus *bus)
+{
+ return (u8)(bus->tx_max - bus->tx_seq) != 0 &&
+ ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
+}
+
+/*
+ * Reads a register in the SDIO hardware block. This block occupies a series of
+ * adresses on the 32 bit backplane bus.
+ */
+static void
+r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
+{
+ *retryvar = 0;
+ do {
+ *regvar = brcmf_sdcard_reg_read(bus->sdiodev,
+ bus->ci->buscorebase + reg_offset, sizeof(u32));
+ } while (brcmf_sdcard_regfail(bus->sdiodev) &&
+ (++(*retryvar) <= retry_limit));
+ if (*retryvar) {
+ bus->regfails += (*retryvar-1);
+ if (*retryvar > retry_limit) {
+ brcmf_dbg(ERROR, "FAILED READ %Xh\n", reg_offset);
+ *regvar = 0;
+ }
+ }
+}
+
+static void
+w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar)
+{
+ *retryvar = 0;
+ do {
+ brcmf_sdcard_reg_write(bus->sdiodev,
+ bus->ci->buscorebase + reg_offset,
+ sizeof(u32), regval);
+ } while (brcmf_sdcard_regfail(bus->sdiodev) &&
+ (++(*retryvar) <= retry_limit));
+ if (*retryvar) {
+ bus->regfails += (*retryvar-1);
+ if (*retryvar > retry_limit)
+ brcmf_dbg(ERROR, "FAILED REGISTER WRITE %Xh\n",
+ reg_offset);
+ }
+}
+
+#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
+
+#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
+
+/* Packet free applicable unconditionally for sdio and sdspi.
+ * Conditional if bufpool was present for gspi bus.
+ */
+static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt)
+{
+ if (bus->usebufpool)
+ brcmu_pkt_buf_free_skb(pkt);
+}
+
+/* Turn backplane clock on or off */
+static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
+{
+ int err;
+ u8 clkctl, clkreq, devctl;
+ unsigned long timeout;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ clkctl = 0;
+
+ if (on) {
+ /* Request HT Avail */
+ clkreq =
+ bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
+
+ if ((bus->ci->chip == BCM4329_CHIP_ID)
+ && (bus->ci->chiprev == 0))
+ clkreq |= SBSDIO_FORCE_ALP;
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
+ if (err) {
+ brcmf_dbg(ERROR, "HT Avail request error: %d\n", err);
+ return -EBADE;
+ }
+
+ if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID)
+ && (bus->ci->buscorerev == 9))) {
+ u32 dummy, retries;
+ r_sdreg32(bus, &dummy,
+ offsetof(struct sdpcmd_regs, clockctlstatus),
+ &retries);
+ }
+
+ /* Check current status */
+ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (err) {
+ brcmf_dbg(ERROR, "HT Avail read error: %d\n", err);
+ return -EBADE;
+ }
+
+ /* Go to pending and await interrupt if appropriate */
+ if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
+ /* Allow only clock-available interrupt */
+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, &err);
+ if (err) {
+ brcmf_dbg(ERROR, "Devctl error setting CA: %d\n",
+ err);
+ return -EBADE;
+ }
+
+ devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, devctl, &err);
+ brcmf_dbg(INFO, "CLKCTL: set PENDING\n");
+ bus->clkstate = CLK_PENDING;
+
+ return 0;
+ } else if (bus->clkstate == CLK_PENDING) {
+ /* Cancel CA-only interrupt filter */
+ devctl =
+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, &err);
+ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, devctl, &err);
+ }
+
+ /* Otherwise, wait here (polling) for HT Avail */
+ timeout = jiffies +
+ msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000);
+ while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
+ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ &err);
+ if (time_after(jiffies, timeout))
+ break;
+ else
+ usleep_range(5000, 10000);
+ }
+ if (err) {
+ brcmf_dbg(ERROR, "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",
+ PMU_MAX_TRANSITION_DLY, clkctl);
+ return -EBADE;
+ }
+
+ /* Mark clock available */
+ bus->clkstate = CLK_AVAIL;
+ brcmf_dbg(INFO, "CLKCTL: turned ON\n");
+
+#if defined(BCMDBG)
+ if (bus->alp_only != true) {
+ if (SBSDIO_ALPONLY(clkctl))
+ brcmf_dbg(ERROR, "HT Clock should be on\n");
+ }
+#endif /* defined (BCMDBG) */
+
+ bus->activity = true;
+ } else {
+ clkreq = 0;
+
+ if (bus->clkstate == CLK_PENDING) {
+ /* Cancel CA-only interrupt filter */
+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, &err);
+ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, devctl, &err);
+ }
+
+ bus->clkstate = CLK_SDONLY;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
+ brcmf_dbg(INFO, "CLKCTL: turned OFF\n");
+ if (err) {
+ brcmf_dbg(ERROR, "Failed access turning clock off: %d\n",
+ err);
+ return -EBADE;
+ }
+ }
+ return 0;
+}
+
+/* Change idle/active SD state */
+static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (on)
+ bus->clkstate = CLK_SDONLY;
+ else
+ bus->clkstate = CLK_NONE;
+
+ return 0;
+}
+
+/* Transition SD and backplane clock readiness */
+static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
+{
+#ifdef BCMDBG
+ uint oldstate = bus->clkstate;
+#endif /* BCMDBG */
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Early exit if we're already there */
+ if (bus->clkstate == target) {
+ if (target == CLK_AVAIL) {
+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+ bus->activity = true;
+ }
+ return 0;
+ }
+
+ switch (target) {
+ case CLK_AVAIL:
+ /* Make sure SD clock is available */
+ if (bus->clkstate == CLK_NONE)
+ brcmf_sdbrcm_sdclk(bus, true);
+ /* Now request HT Avail on the backplane */
+ brcmf_sdbrcm_htclk(bus, true, pendok);
+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+ bus->activity = true;
+ break;
+
+ case CLK_SDONLY:
+ /* Remove HT request, or bring up SD clock */
+ if (bus->clkstate == CLK_NONE)
+ brcmf_sdbrcm_sdclk(bus, true);
+ else if (bus->clkstate == CLK_AVAIL)
+ brcmf_sdbrcm_htclk(bus, false, false);
+ else
+ brcmf_dbg(ERROR, "request for %d -> %d\n",
+ bus->clkstate, target);
+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+ break;
+
+ case CLK_NONE:
+ /* Make sure to remove HT request */
+ if (bus->clkstate == CLK_AVAIL)
+ brcmf_sdbrcm_htclk(bus, false, false);
+ /* Now remove the SD clock */
+ brcmf_sdbrcm_sdclk(bus, false);
+ brcmf_sdbrcm_wd_timer(bus, 0);
+ break;
+ }
+#ifdef BCMDBG
+ brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate);
+#endif /* BCMDBG */
+
+ return 0;
+}
+
+static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
+{
+ uint retries = 0;
+
+ brcmf_dbg(INFO, "request %s (currently %s)\n",
+ sleep ? "SLEEP" : "WAKE",
+ bus->sleeping ? "SLEEP" : "WAKE");
+
+ /* Done if we're already in the requested state */
+ if (sleep == bus->sleeping)
+ return 0;
+
+ /* Going to sleep: set the alarm and turn off the lights... */
+ if (sleep) {
+ /* Don't sleep if something is pending */
+ if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
+ return -EBUSY;
+
+ /* Make sure the controller has the bus up */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+
+ /* Tell device to start using OOB wakeup */
+ w_sdreg32(bus, SMB_USE_OOB,
+ offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
+ if (retries > retry_limit)
+ brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n");
+
+ /* Turn off our contribution to the HT clock request */
+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
+
+ /* Isolate the bus */
+ if (bus->ci->chip != BCM4329_CHIP_ID) {
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL,
+ SBSDIO_DEVCTL_PADS_ISO, NULL);
+ }
+
+ /* Change state */
+ bus->sleeping = true;
+
+ } else {
+ /* Waking up: bus power up is ok, set local state */
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+
+ /* Force pad isolation off if possible
+ (in case power never toggled) */
+ if ((bus->ci->buscoretype == PCMCIA_CORE_ID)
+ && (bus->ci->buscorerev >= 10))
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, 0, NULL);
+
+ /* Make sure the controller has the bus up */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+
+ /* Send misc interrupt to indicate OOB not needed */
+ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata),
+ &retries);
+ if (retries <= retry_limit)
+ w_sdreg32(bus, SMB_DEV_INT,
+ offsetof(struct sdpcmd_regs, tosbmailbox),
+ &retries);
+
+ if (retries > retry_limit)
+ brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n");
+
+ /* Make sure we have SD bus access */
+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+
+ /* Change state */
+ bus->sleeping = false;
+ }
+
+ return 0;
+}
+
+static void bus_wake(struct brcmf_bus *bus)
+{
+ if (bus->sleeping)
+ brcmf_sdbrcm_bussleep(bus, false);
+}
+
+static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus)
+{
+ u32 intstatus = 0;
+ u32 hmb_data;
+ u8 fcbits;
+ uint retries = 0;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Read mailbox data and ack that we did so */
+ r_sdreg32(bus, &hmb_data,
+ offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries);
+
+ if (retries <= retry_limit)
+ w_sdreg32(bus, SMB_INT_ACK,
+ offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
+ bus->f1regdata += 2;
+
+ /* Dongle recomposed rx frames, accept them again */
+ if (hmb_data & HMB_DATA_NAKHANDLED) {
+ brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n",
+ bus->rx_seq);
+ if (!bus->rxskip)
+ brcmf_dbg(ERROR, "unexpected NAKHANDLED!\n");
+
+ bus->rxskip = false;
+ intstatus |= I_HMB_FRAME_IND;
+ }
+
+ /*
+ * DEVREADY does not occur with gSPI.
+ */
+ if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
+ bus->sdpcm_ver =
+ (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, "
+ "expecting %d\n",
+ bus->sdpcm_ver, SDPCM_PROT_VERSION);
+ else
+ brcmf_dbg(INFO, "Dongle ready, protocol version %d\n",
+ bus->sdpcm_ver);
+ }
+
+ /*
+ * Flow Control has been moved into the RX headers and this out of band
+ * method isn't used any more.
+ * remaining backward compatible with older dongles.
+ */
+ if (hmb_data & HMB_DATA_FC) {
+ fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >>
+ HMB_DATA_FCDATA_SHIFT;
+
+ if (fcbits & ~bus->flowcontrol)
+ bus->fc_xoff++;
+
+ if (bus->flowcontrol & ~fcbits)
+ bus->fc_xon++;
+
+ bus->fc_rcvd++;
+ bus->flowcontrol = fcbits;
+ }
+
+ /* Shouldn't be any others */
+ if (hmb_data & ~(HMB_DATA_DEVREADY |
+ HMB_DATA_NAKHANDLED |
+ HMB_DATA_FC |
+ HMB_DATA_FWREADY |
+ HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK))
+ brcmf_dbg(ERROR, "Unknown mailbox data content: 0x%02x\n",
+ hmb_data);
+
+ return intstatus;
+}
+
+static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
+{
+ uint retries = 0;
+ u16 lastrbc;
+ u8 hi, lo;
+ int err;
+
+ brcmf_dbg(ERROR, "%sterminate frame%s\n",
+ abort ? "abort command, " : "",
+ rtx ? ", send NAK" : "");
+
+ if (abort)
+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_FRAMECTRL,
+ SFC_RF_TERM, &err);
+ bus->f1regdata++;
+
+ /* Wait until the packet has been flushed (device/FIFO stable) */
+ for (lastrbc = retries = 0xffff; retries > 0; retries--) {
+ hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_RFRAMEBCHI, NULL);
+ lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_RFRAMEBCLO, NULL);
+ bus->f1regdata += 2;
+
+ if ((hi == 0) && (lo == 0))
+ break;
+
+ if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
+ brcmf_dbg(ERROR, "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);
+ else
+ brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries);
+
+ if (rtx) {
+ bus->rxrtx++;
+ w_sdreg32(bus, SMB_NAK,
+ offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
+
+ bus->f1regdata++;
+ if (retries <= retry_limit)
+ bus->rxskip = true;
+ }
+
+ /* Clear partial in any case */
+ bus->nextlen = 0;
+
+ /* If we can't reach the device, signal failure */
+ if (err || brcmf_sdcard_regfail(bus->sdiodev))
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
+}
+
+static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
+{
+ u16 dlen, totlen;
+ u8 *dptr, num = 0;
+
+ u16 sublen, check;
+ struct sk_buff *pfirst, *plast, *pnext, *save_pfirst;
+
+ int errcode;
+ u8 chan, seq, doff, sfdoff;
+ u8 txmax;
+
+ int ifidx = 0;
+ bool usechain = bus->use_rxchain;
+
+ /* If packets, issue read(s) and send up packet chain */
+ /* Return sequence numbers consumed? */
+
+ brcmf_dbg(TRACE, "start: glomd %p glom %p\n", bus->glomd, bus->glom);
+
+ /* If there's a descriptor, generate the packet chain */
+ if (bus->glomd) {
+ pfirst = plast = pnext = NULL;
+ dlen = (u16) (bus->glomd->len);
+ dptr = bus->glomd->data;
+ if (!dlen || (dlen & 1)) {
+ brcmf_dbg(ERROR, "bad glomd len(%d), ignore descriptor\n",
+ dlen);
+ dlen = 0;
+ }
+
+ for (totlen = num = 0; dlen; num++) {
+ /* Get (and move past) next length */
+ sublen = get_unaligned_le16(dptr);
+ dlen -= sizeof(u16);
+ dptr += sizeof(u16);
+ if ((sublen < SDPCM_HDRLEN) ||
+ ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
+ brcmf_dbg(ERROR, "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",
+ sublen, BRCMF_SDALIGN);
+ usechain = false;
+ }
+ totlen += sublen;
+
+ /* For last frame, adjust read len so total
+ is a block multiple */
+ if (!dlen) {
+ sublen +=
+ (roundup(totlen, bus->blocksize) - totlen);
+ totlen = roundup(totlen, bus->blocksize);
+ }
+
+ /* 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",
+ num, sublen);
+ break;
+ }
+ if (!pfirst) {
+ pfirst = plast = pnext;
+ } else {
+ plast->next = pnext;
+ plast = pnext;
+ }
+
+ /* Adhere to start alignment requirements */
+ pkt_align(pnext, sublen, BRCMF_SDALIGN);
+ }
+
+ /* If all allocations succeeded, save packet chain
+ in bus structure */
+ if (pnext) {
+ brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n",
+ totlen, num);
+ if (BRCMF_GLOM_ON() && bus->nextlen &&
+ totlen != bus->nextlen) {
+ brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n",
+ bus->nextlen, totlen, rxseq);
+ }
+ bus->glom = pfirst;
+ pfirst = pnext = NULL;
+ } else {
+ if (pfirst)
+ brcmu_pkt_buf_free_skb(pfirst);
+ bus->glom = NULL;
+ num = 0;
+ }
+
+ /* Done with descriptor packet */
+ brcmu_pkt_buf_free_skb(bus->glomd);
+ bus->glomd = NULL;
+ bus->nextlen = 0;
+ }
+
+ /* Ok -- either we just generated a packet chain,
+ or had one from before */
+ if (bus->glom) {
+ if (BRCMF_GLOM_ON()) {
+ brcmf_dbg(GLOM, "try superframe read, packet chain:\n");
+ for (pnext = bus->glom; pnext; pnext = pnext->next) {
+ brcmf_dbg(GLOM, " %p: %p len 0x%04x (%d)\n",
+ pnext, (u8 *) (pnext->data),
+ pnext->len, pnext->len);
+ }
+ }
+
+ pfirst = bus->glom;
+ dlen = (u16) brcmu_pkttotlen(pfirst);
+
+ /* Do an SDIO read for the superframe. Configurable iovar to
+ * read directly into the chained packet, or allocate a large
+ * packet and and copy into the chain.
+ */
+ if (usechain) {
+ errcode = brcmf_sdcard_recv_buf(bus->sdiodev,
+ bus->sdiodev->sbwad,
+ SDIO_FUNC_2,
+ F2SYNC, (u8 *) pfirst->data, dlen,
+ pfirst);
+ } else if (bus->dataptr) {
+ errcode = brcmf_sdcard_recv_buf(bus->sdiodev,
+ bus->sdiodev->sbwad,
+ SDIO_FUNC_2,
+ F2SYNC, bus->dataptr, dlen,
+ NULL);
+ sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen,
+ bus->dataptr);
+ if (sublen != dlen) {
+ brcmf_dbg(ERROR, "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",
+ dlen);
+ errcode = -1;
+ }
+ bus->f2rxdata++;
+
+ /* On failure, kill the superframe, allow a couple retries */
+ if (errcode < 0) {
+ brcmf_dbg(ERROR, "glom read of %d bytes failed: %d\n",
+ dlen, errcode);
+ bus->drvr->rx_errors++;
+
+ if (bus->glomerr++ < 3) {
+ brcmf_sdbrcm_rxfail(bus, true, true);
+ } else {
+ bus->glomerr = 0;
+ brcmf_sdbrcm_rxfail(bus, true, false);
+ brcmu_pkt_buf_free_skb(bus->glom);
+ bus->rxglomfail++;
+ bus->glom = NULL;
+ }
+ return 0;
+ }
+#ifdef BCMDBG
+ if (BRCMF_GLOM_ON()) {
+ printk(KERN_DEBUG "SUPERFRAME:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ pfirst->data, min_t(int, pfirst->len, 48));
+ }
+#endif
+
+ /* 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]);
+ bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
+ if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
+ brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n",
+ bus->nextlen, seq);
+ bus->nextlen = 0;
+ }
+ 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->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;
+
+ /* Remove superframe header, remember offset */
+ skb_pull(pfirst, doff);
+ sfdoff = doff;
+
+ /* Validate all the subframe headers */
+ for (num = 0, pnext = pfirst; pnext && !errcode;
+ num++, pnext = pnext->next) {
+ 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]);
+#ifdef BCMDBG
+ if (BRCMF_GLOM_ON()) {
+ printk(KERN_DEBUG "subframe:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ dptr, 32);
+ }
+#endif
+
+ 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;
+ }
+ }
+
+ if (errcode) {
+ /* Terminate frame on error, request
+ a couple retries */
+ if (bus->glomerr++ < 3) {
+ /* Restore superframe header space */
+ skb_push(pfirst, sfdoff);
+ brcmf_sdbrcm_rxfail(bus, true, true);
+ } else {
+ bus->glomerr = 0;
+ brcmf_sdbrcm_rxfail(bus, true, false);
+ brcmu_pkt_buf_free_skb(bus->glom);
+ bus->rxglomfail++;
+ bus->glom = NULL;
+ }
+ bus->nextlen = 0;
+ return 0;
+ }
+
+ /* Basic SD framing looks ok - process each packet (header) */
+ save_pfirst = pfirst;
+ bus->glom = NULL;
+ plast = NULL;
+
+ for (num = 0; pfirst; rxseq++, pfirst = pnext) {
+ pnext = pfirst->next;
+ pfirst->next = NULL;
+
+ 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->rx_badseq++;
+ rxseq = seq;
+ }
+#ifdef BCMDBG
+ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
+ printk(KERN_DEBUG "Rx Subframe Data:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ dptr, dlen);
+ }
+#endif
+
+ __skb_trim(pfirst, sublen);
+ skb_pull(pfirst, doff);
+
+ if (pfirst->len == 0) {
+ brcmu_pkt_buf_free_skb(pfirst);
+ if (plast)
+ plast->next = pnext;
+ else
+ save_pfirst = pnext;
+
+ continue;
+ } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx,
+ pfirst) != 0) {
+ brcmf_dbg(ERROR, "rx protocol error\n");
+ bus->drvr->rx_errors++;
+ brcmu_pkt_buf_free_skb(pfirst);
+ if (plast)
+ plast->next = pnext;
+ else
+ save_pfirst = pnext;
+
+ continue;
+ }
+
+ /* this packet will go up, link back into
+ chain and count it */
+ pfirst->next = pnext;
+ plast = pfirst;
+ num++;
+
+#ifdef BCMDBG
+ if (BRCMF_GLOM_ON()) {
+ brcmf_dbg(GLOM, "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n",
+ num, pfirst, pfirst->data,
+ pfirst->len, pfirst->next,
+ pfirst->prev);
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ pfirst->data,
+ min_t(int, pfirst->len, 32));
+ }
+#endif /* BCMDBG */
+ }
+ if (num) {
+ up(&bus->sdsem);
+ brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num);
+ down(&bus->sdsem);
+ }
+
+ bus->rxglomframes++;
+ bus->rxglompkts += num;
+ }
+ return num;
+}
+
+static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_bus *bus, uint *condition,
+ bool *pending)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int timeout = msecs_to_jiffies(DCMD_RESP_TIMEOUT);
+
+ /* Wait until control frame is available */
+ add_wait_queue(&bus->dcmd_resp_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ while (!(*condition) && (!signal_pending(current) && timeout))
+ timeout = schedule_timeout(timeout);
+
+ if (signal_pending(current))
+ *pending = true;
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&bus->dcmd_resp_wait, &wait);
+
+ return timeout;
+}
+
+static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_bus *bus)
+{
+ if (waitqueue_active(&bus->dcmd_resp_wait))
+ wake_up_interruptible(&bus->dcmd_resp_wait);
+
+ return 0;
+}
+static void
+brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff)
+{
+ uint rdlen, pad;
+
+ 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 (pad)
+ bus->rxctl += (BRCMF_SDALIGN - pad);
+ bus->rxctl -= BRCMF_FIRSTREAD;
+
+ /* Copy the already-read portion over */
+ memcpy(bus->rxctl, hdr, BRCMF_FIRSTREAD);
+ if (len <= BRCMF_FIRSTREAD)
+ goto gotpkt;
+
+ /* Raise rdlen to next SDIO block to avoid tail command */
+ rdlen = len - BRCMF_FIRSTREAD;
+ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
+ pad = bus->blocksize - (rdlen % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
+ ((len + pad) < bus->drvr->maxctl))
+ rdlen += pad;
+ } else if (rdlen % BRCMF_SDALIGN) {
+ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
+ }
+
+ /* Satisfy length-alignment requirements */
+ if (rdlen & (ALIGNMENT - 1))
+ rdlen = roundup(rdlen, ALIGNMENT);
+
+ /* Drop if the read is too big or it exceeds our maximum */
+ if ((rdlen + BRCMF_FIRSTREAD) > bus->drvr->maxctl) {
+ brcmf_dbg(ERROR, "%d-byte control read exceeds %d-byte buffer\n",
+ rdlen, bus->drvr->maxctl);
+ bus->drvr->rx_errors++;
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ goto done;
+ }
+
+ if ((len - doff) > bus->drvr->maxctl) {
+ brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
+ len, len - doff, bus->drvr->maxctl);
+ bus->drvr->rx_errors++;
+ bus->rx_toolong++;
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ goto done;
+ }
+
+ /* Read remainder of frame body into the rxctl buffer */
+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
+ bus->sdiodev->sbwad,
+ SDIO_FUNC_2,
+ F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen,
+ NULL);
+ bus->f2rxdata++;
+
+ /* Control frame failures need retransmission */
+ if (sdret < 0) {
+ brcmf_dbg(ERROR, "read %d control bytes failed: %d\n",
+ rdlen, sdret);
+ bus->rxc_errors++;
+ brcmf_sdbrcm_rxfail(bus, true, true);
+ goto done;
+ }
+
+gotpkt:
+
+#ifdef BCMDBG
+ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
+ printk(KERN_DEBUG "RxCtrl:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len);
+ }
+#endif
+
+ /* Point to valid data and indicate its length */
+ bus->rxctl += doff;
+ bus->rxlen = len - doff;
+
+done:
+ /* Awake any waiters */
+ brcmf_sdbrcm_dcmd_resp_wake(bus);
+}
+
+/* Pad read to blocksize for efficiency */
+static void brcmf_pad(struct brcmf_bus *bus, u16 *pad, u16 *rdlen)
+{
+ if (bus->roundup && bus->blocksize && *rdlen > bus->blocksize) {
+ *pad = bus->blocksize - (*rdlen % bus->blocksize);
+ if (*pad <= bus->roundup && *pad < bus->blocksize &&
+ *rdlen + *pad + BRCMF_FIRSTREAD < MAX_RX_DATASZ)
+ *rdlen += *pad;
+ } else if (*rdlen % BRCMF_SDALIGN) {
+ *rdlen += BRCMF_SDALIGN - (*rdlen % BRCMF_SDALIGN);
+ }
+}
+
+static void
+brcmf_alloc_pkt_and_read(struct brcmf_bus *bus, u16 rdlen,
+ struct sk_buff **pkt, u8 **rxbuf)
+{
+ int sdret; /* Return code from calls */
+
+ *pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN);
+ if (*pkt == NULL)
+ return;
+
+ pkt_align(*pkt, rdlen, BRCMF_SDALIGN);
+ *rxbuf = (u8 *) ((*pkt)->data);
+ /* Read the entire frame */
+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC,
+ *rxbuf, rdlen, *pkt);
+ bus->f2rxdata++;
+
+ if (sdret < 0) {
+ brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n",
+ rdlen, sdret);
+ brcmu_pkt_buf_free_skb(*pkt);
+ bus->drvr->rx_errors++;
+ /* Force retry w/normal header read.
+ * Don't attempt NAK for
+ * gSPI
+ */
+ brcmf_sdbrcm_rxfail(bus, true, true);
+ *pkt = NULL;
+ }
+}
+
+/* Checks the header */
+static int
+brcmf_check_rxbuf(struct brcmf_bus *bus, struct sk_buff *pkt, u8 *rxbuf,
+ u8 rxseq, u16 nextlen, u16 *len)
+{
+ u16 check;
+ bool len_consistent; /* Result of comparing readahead len and
+ len from hw-hdr */
+
+ memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
+
+ /* Extract hardware header fields */
+ *len = get_unaligned_le16(bus->rxhdr);
+ check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
+
+ /* All zeros means readahead info was bad */
+ if (!(*len | check)) {
+ brcmf_dbg(INFO, "(nextlen): read zeros in HW header???\n");
+ goto fail;
+ }
+
+ /* Validate check bytes */
+ if ((u16)~(*len ^ check)) {
+ brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n",
+ nextlen, *len, check);
+ bus->rx_badhdr++;
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ goto fail;
+ }
+
+ /* Validate frame length */
+ if (*len < SDPCM_HDRLEN) {
+ brcmf_dbg(ERROR, "(nextlen): HW hdr length invalid: %d\n",
+ *len);
+ goto fail;
+ }
+
+ /* Check for consistency with readahead info */
+ len_consistent = (nextlen != (roundup(*len, 16) >> 4));
+ if (len_consistent) {
+ /* Mismatch, force retry w/normal
+ header (may be >4K) */
+ brcmf_dbg(ERROR, "(nextlen): mismatch, nextlen %d len %d rnd %d; expected rxseq %d\n",
+ nextlen, *len, roundup(*len, 16),
+ rxseq);
+ brcmf_sdbrcm_rxfail(bus, true, true);
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ brcmf_sdbrcm_pktfree2(bus, pkt);
+ return -EINVAL;
+}
+
+/* Return true if there may be more frames to read */
+static uint
+brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
+{
+ u16 len, check; /* Extracted hardware header fields */
+ u8 chan, seq, doff; /* Extracted software header fields */
+ u8 fcbits; /* Extracted fcbits from software header */
+
+ struct sk_buff *pkt; /* Packet for event or data frames */
+ u16 pad; /* Number of pad bytes to read */
+ u16 rdlen; /* Total number of bytes to read */
+ u8 rxseq; /* Next sequence number to expect */
+ uint rxleft = 0; /* Remaining number of frames allowed */
+ int sdret; /* Return code from calls */
+ u8 txmax; /* Maximum tx sequence offered */
+ u8 *rxbuf;
+ int ifidx = 0;
+ uint rxcount = 0; /* Total frames read */
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Not finished unless we encounter no more frames indication */
+ *finished = false;
+
+ for (rxseq = bus->rx_seq, rxleft = maxframes;
+ !bus->rxskip && rxleft && bus->drvr->busstate != BRCMF_BUS_DOWN;
+ rxseq++, rxleft--) {
+
+ /* Handle glomming separately */
+ if (bus->glom || bus->glomd) {
+ u8 cnt;
+ brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n",
+ bus->glomd, bus->glom);
+ cnt = brcmf_sdbrcm_rxglom(bus, rxseq);
+ brcmf_dbg(GLOM, "rxglom returned %d\n", cnt);
+ rxseq += cnt - 1;
+ rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
+ continue;
+ }
+
+ /* Try doing single read if we can */
+ if (bus->nextlen) {
+ u16 nextlen = bus->nextlen;
+ bus->nextlen = 0;
+
+ rdlen = len = nextlen << 4;
+ brcmf_pad(bus, &pad, &rdlen);
+
+ /*
+ * After the frame is received we have to
+ * distinguish whether it is data
+ * or non-data frame.
+ */
+ brcmf_alloc_pkt_and_read(bus, rdlen, &pkt, &rxbuf);
+ if (pkt == NULL) {
+ /* Give up on data, request rtx of events */
+ brcmf_dbg(ERROR, "(nextlen): brcmf_alloc_pkt_and_read failed: len %d rdlen %d expected rxseq %d\n",
+ len, rdlen, rxseq);
+ continue;
+ }
+
+ if (brcmf_check_rxbuf(bus, pkt, rxbuf, rxseq, nextlen,
+ &len) < 0)
+ continue;
+
+ /* Extract software header fields */
+ chan = SDPCM_PACKET_CHANNEL(
+ &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ seq = SDPCM_PACKET_SEQUENCE(
+ &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ doff = SDPCM_DOFFSET_VALUE(
+ &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ txmax = SDPCM_WINDOW_VALUE(
+ &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+
+ bus->nextlen =
+ bus->rxhdr[SDPCM_FRAMETAG_LEN +
+ SDPCM_NEXTLEN_OFFSET];
+ if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
+ brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n",
+ bus->nextlen, seq);
+ bus->nextlen = 0;
+ }
+
+ bus->drvr->rx_readahead_cnt++;
+
+ /* Handle Flow Control */
+ fcbits = SDPCM_FCMASK_VALUE(
+ &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+
+ if (bus->flowcontrol != fcbits) {
+ if (~bus->flowcontrol & fcbits)
+ bus->fc_xoff++;
+
+ if (bus->flowcontrol & ~fcbits)
+ bus->fc_xon++;
+
+ bus->fc_rcvd++;
+ bus->flowcontrol = fcbits;
+ }
+
+ /* Check and update sequence number */
+ if (rxseq != seq) {
+ brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n",
+ seq, rxseq);
+ bus->rx_badseq++;
+ rxseq = seq;
+ }
+
+ /* Check window for sanity */
+ if ((u8) (txmax - bus->tx_seq) > 0x40) {
+ brcmf_dbg(ERROR, "got unlikely tx max %d with tx_seq %d\n",
+ txmax, bus->tx_seq);
+ txmax = bus->tx_seq + 2;
+ }
+ bus->tx_max = txmax;
+
+#ifdef BCMDBG
+ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
+ printk(KERN_DEBUG "Rx Data:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ rxbuf, len);
+ } else if (BRCMF_HDRS_ON()) {
+ printk(KERN_DEBUG "RxHdr:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ bus->rxhdr, SDPCM_HDRLEN);
+ }
+#endif
+
+ if (chan == SDPCM_CONTROL_CHANNEL) {
+ brcmf_dbg(ERROR, "(nextlen): readahead on control packet %d?\n",
+ seq);
+ /* Force retry w/normal header read */
+ bus->nextlen = 0;
+ brcmf_sdbrcm_rxfail(bus, false, true);
+ brcmf_sdbrcm_pktfree2(bus, pkt);
+ continue;
+ }
+
+ /* Validate data offset */
+ if ((doff < SDPCM_HDRLEN) || (doff > len)) {
+ brcmf_dbg(ERROR, "(nextlen): bad data offset %d: HW len %d min %d\n",
+ doff, len, SDPCM_HDRLEN);
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ brcmf_sdbrcm_pktfree2(bus, pkt);
+ continue;
+ }
+
+ /* All done with this one -- now deliver the packet */
+ goto deliver;
+ }
+
+ /* Read frame header (hardware and software) */
+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC, bus->rxhdr,
+ BRCMF_FIRSTREAD, NULL);
+ bus->f2rxhdrs++;
+
+ if (sdret < 0) {
+ brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret);
+ bus->rx_hdrfail++;
+ brcmf_sdbrcm_rxfail(bus, true, true);
+ continue;
+ }
+#ifdef BCMDBG
+ if (BRCMF_BYTES_ON() || BRCMF_HDRS_ON()) {
+ printk(KERN_DEBUG "RxHdr:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ bus->rxhdr, SDPCM_HDRLEN);
+ }
+#endif
+
+ /* Extract hardware header fields */
+ len = get_unaligned_le16(bus->rxhdr);
+ check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
+
+ /* All zeros means no more frames */
+ if (!(len | check)) {
+ *finished = true;
+ break;
+ }
+
+ /* Validate check bytes */
+ if ((u16) ~(len ^ check)) {
+ brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n",
+ len, check);
+ bus->rx_badhdr++;
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ continue;
+ }
+
+ /* Validate frame length */
+ if (len < SDPCM_HDRLEN) {
+ brcmf_dbg(ERROR, "HW hdr length invalid: %d\n", len);
+ continue;
+ }
+
+ /* Extract software header fields */
+ chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+ txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+
+ /* Validate data offset */
+ if ((doff < SDPCM_HDRLEN) || (doff > len)) {
+ brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n",
+ doff, len, SDPCM_HDRLEN, seq);
+ bus->rx_badhdr++;
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ continue;
+ }
+
+ /* Save the readahead length if there is one */
+ bus->nextlen =
+ bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
+ if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
+ brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n",
+ bus->nextlen, seq);
+ bus->nextlen = 0;
+ }
+
+ /* Handle Flow Control */
+ fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+
+ if (bus->flowcontrol != fcbits) {
+ if (~bus->flowcontrol & fcbits)
+ bus->fc_xoff++;
+
+ if (bus->flowcontrol & ~fcbits)
+ bus->fc_xon++;
+
+ bus->fc_rcvd++;
+ bus->flowcontrol = fcbits;
+ }
+
+ /* Check and update sequence number */
+ if (rxseq != seq) {
+ brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq);
+ bus->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;
+
+ /* Call a separate function for control frames */
+ if (chan == SDPCM_CONTROL_CHANNEL) {
+ brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff);
+ continue;
+ }
+
+ /* precondition: chan is either SDPCM_DATA_CHANNEL,
+ SDPCM_EVENT_CHANNEL, SDPCM_TEST_CHANNEL or
+ SDPCM_GLOM_CHANNEL */
+
+ /* Length to read */
+ rdlen = (len > BRCMF_FIRSTREAD) ? (len - BRCMF_FIRSTREAD) : 0;
+
+ /* May pad read to blocksize for efficiency */
+ if (bus->roundup && bus->blocksize &&
+ (rdlen > bus->blocksize)) {
+ pad = bus->blocksize - (rdlen % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
+ ((rdlen + pad + BRCMF_FIRSTREAD) < MAX_RX_DATASZ))
+ rdlen += pad;
+ } else if (rdlen % BRCMF_SDALIGN) {
+ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
+ }
+
+ /* Satisfy length-alignment requirements */
+ if (rdlen & (ALIGNMENT - 1))
+ rdlen = roundup(rdlen, ALIGNMENT);
+
+ if ((rdlen + BRCMF_FIRSTREAD) > MAX_RX_DATASZ) {
+ /* Too long -- skip this frame */
+ brcmf_dbg(ERROR, "too long: len %d rdlen %d\n",
+ len, rdlen);
+ bus->drvr->rx_errors++;
+ bus->rx_toolong++;
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ continue;
+ }
+
+ pkt = brcmu_pkt_buf_get_skb(rdlen +
+ BRCMF_FIRSTREAD + BRCMF_SDALIGN);
+ if (!pkt) {
+ /* Give up on data, request rtx of events */
+ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: rdlen %d chan %d\n",
+ rdlen, chan);
+ bus->drvr->rx_dropped++;
+ brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan));
+ continue;
+ }
+
+ /* Leave room for what we already read, and align remainder */
+ skb_pull(pkt, BRCMF_FIRSTREAD);
+ pkt_align(pkt, rdlen, BRCMF_SDALIGN);
+
+ /* Read the remaining frame data */
+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)),
+ rdlen, pkt);
+ bus->f2rxdata++;
+
+ if (sdret < 0) {
+ brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen,
+ ((chan == SDPCM_EVENT_CHANNEL) ? "event"
+ : ((chan == SDPCM_DATA_CHANNEL) ? "data"
+ : "test")), sdret);
+ brcmu_pkt_buf_free_skb(pkt);
+ bus->drvr->rx_errors++;
+ brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan));
+ continue;
+ }
+
+ /* Copy the already-read portion */
+ skb_push(pkt, BRCMF_FIRSTREAD);
+ memcpy(pkt->data, bus->rxhdr, BRCMF_FIRSTREAD);
+
+#ifdef BCMDBG
+ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
+ printk(KERN_DEBUG "Rx Data:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ pkt->data, len);
+ }
+#endif
+
+deliver:
+ /* Save superframe descriptor and allocate packet frame */
+ if (chan == SDPCM_GLOM_CHANNEL) {
+ if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
+ brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n",
+ len);
+#ifdef BCMDBG
+ if (BRCMF_GLOM_ON()) {
+ printk(KERN_DEBUG "Glom Data:\n");
+ print_hex_dump_bytes("",
+ DUMP_PREFIX_OFFSET,
+ pkt->data, len);
+ }
+#endif
+ __skb_trim(pkt, len);
+ skb_pull(pkt, SDPCM_HDRLEN);
+ bus->glomd = pkt;
+ } else {
+ brcmf_dbg(ERROR, "%s: glom superframe w/o "
+ "descriptor!\n", __func__);
+ brcmf_sdbrcm_rxfail(bus, false, false);
+ }
+ continue;
+ }
+
+ /* Fill in packet len and prio, deliver upward */
+ __skb_trim(pkt, len);
+ skb_pull(pkt, doff);
+
+ if (pkt->len == 0) {
+ brcmu_pkt_buf_free_skb(pkt);
+ continue;
+ } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pkt) != 0) {
+ brcmf_dbg(ERROR, "rx protocol error\n");
+ brcmu_pkt_buf_free_skb(pkt);
+ bus->drvr->rx_errors++;
+ continue;
+ }
+
+ /* Unlock during rx call */
+ up(&bus->sdsem);
+ brcmf_rx_frame(bus->drvr, ifidx, pkt, 1);
+ down(&bus->sdsem);
+ }
+ rxcount = maxframes - rxleft;
+#ifdef BCMDBG
+ /* Message if we hit the limit */
+ if (!rxleft)
+ brcmf_dbg(DATA, "hit rx limit of %d frames\n",
+ maxframes);
+ else
+#endif /* BCMDBG */
+ brcmf_dbg(DATA, "processed %d frames\n", rxcount);
+ /* Back off rxseq if awaiting rtx, update rx_seq */
+ if (bus->rxskip)
+ rxseq--;
+ bus->rx_seq = rxseq;
+
+ return rxcount;
+}
+
+static int
+brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags,
+ u8 *buf, uint nbytes, struct sk_buff *pkt)
+{
+ return brcmf_sdcard_send_buf
+ (bus->sdiodev, addr, fn, flags, buf, nbytes, pkt);
+}
+
+static void
+brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar)
+{
+ up(&bus->sdsem);
+ wait_event_interruptible_timeout(bus->ctrl_wait,
+ (*lockvar == false), HZ * 2);
+ down(&bus->sdsem);
+ return;
+}
+
+static void
+brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus)
+{
+ if (waitqueue_active(&bus->ctrl_wait))
+ wake_up_interruptible(&bus->ctrl_wait);
+ return;
+}
+
+/* Writes a HW/SW header into the packet and sends it. */
+/* Assumes: (a) header space already there, (b) caller holds lock */
+static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt,
+ uint chan, bool free_pkt)
+{
+ int ret;
+ u8 *frame;
+ u16 len, pad = 0;
+ u32 swheader;
+ struct sk_buff *new;
+ int i;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ frame = (u8 *) (pkt->data);
+
+ /* Add alignment padding, allocate new packet if needed */
+ pad = ((unsigned long)frame % BRCMF_SDALIGN);
+ if (pad) {
+ if (skb_headroom(pkt) < pad) {
+ brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n",
+ skb_headroom(pkt), pad);
+ bus->drvr->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",
+ pkt->len + BRCMF_SDALIGN);
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ pkt_align(new, pkt->len, BRCMF_SDALIGN);
+ memcpy(new->data, pkt->data, pkt->len);
+ if (free_pkt)
+ brcmu_pkt_buf_free_skb(pkt);
+ /* free the pkt if canned one is not used */
+ free_pkt = true;
+ pkt = new;
+ frame = (u8 *) (pkt->data);
+ /* precondition: (frame % BRCMF_SDALIGN) == 0) */
+ pad = 0;
+ } else {
+ skb_push(pkt, pad);
+ frame = (u8 *) (pkt->data);
+ /* precondition: pad + SDPCM_HDRLEN <= pkt->len */
+ memset(frame, 0, pad + SDPCM_HDRLEN);
+ }
+ }
+ /* precondition: pad < BRCMF_SDALIGN */
+
+ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
+ len = (u16) (pkt->len);
+ *(__le16 *) frame = cpu_to_le16(len);
+ *(((__le16 *) frame) + 1) = cpu_to_le16(~len);
+
+ /* Software tag: channel, sequence number, data offset */
+ swheader =
+ ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
+ (((pad +
+ SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
+
+ put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
+ put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+
+#ifdef BCMDBG
+ tx_packets[pkt->priority]++;
+ if (BRCMF_BYTES_ON() &&
+ (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
+ (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
+ printk(KERN_DEBUG "Tx Frame:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len);
+ } else if (BRCMF_HDRS_ON()) {
+ printk(KERN_DEBUG "TxHdr:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ frame, min_t(u16, len, 16));
+ }
+#endif
+
+ /* Raise len to next SDIO block to eliminate tail command */
+ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
+ u16 pad = bus->blocksize - (len % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize))
+ len += pad;
+ } else if (len % BRCMF_SDALIGN) {
+ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
+ }
+
+ /* Some controllers have trouble with odd bytes -- round to even */
+ if (len & (ALIGNMENT - 1))
+ len = roundup(len, ALIGNMENT);
+
+ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC, frame,
+ len, pkt);
+ bus->f2txdata++;
+
+ if (ret < 0) {
+ /* On failure, abort the command and terminate the frame */
+ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
+ ret);
+ bus->tx_sderrs++;
+
+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
+ NULL);
+ bus->f1regdata++;
+
+ for (i = 0; i < 3; i++) {
+ u8 hi, lo;
+ hi = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_FUNC1_WFRAMEBCHI,
+ NULL);
+ lo = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_FUNC1_WFRAMEBCLO,
+ NULL);
+ bus->f1regdata += 2;
+ if ((hi == 0) && (lo == 0))
+ break;
+ }
+
+ }
+ 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->drvr, pkt, ret != 0);
+ down(&bus->sdsem);
+
+ if (free_pkt)
+ brcmu_pkt_buf_free_skb(pkt);
+
+ return ret;
+}
+
+static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes)
+{
+ struct sk_buff *pkt;
+ u32 intstatus = 0;
+ uint retries = 0;
+ int ret = 0, prec_out;
+ uint cnt = 0;
+ uint datalen;
+ u8 tx_prec_map;
+
+ struct brcmf_pub *drvr = bus->drvr;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ tx_prec_map = ~bus->flowcontrol;
+
+ /* Send frames until the limit or some other event */
+ for (cnt = 0; (cnt < maxframes) && data_ok(bus); cnt++) {
+ spin_lock_bh(&bus->txqlock);
+ pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
+ if (pkt == NULL) {
+ spin_unlock_bh(&bus->txqlock);
+ break;
+ }
+ spin_unlock_bh(&bus->txqlock);
+ datalen = pkt->len - SDPCM_HDRLEN;
+
+ ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+ if (ret)
+ bus->drvr->tx_errors++;
+ else
+ bus->drvr->dstats.tx_bytes += datalen;
+
+ /* In poll mode, need to check for other events */
+ if (!bus->intr && cnt) {
+ /* Check device status, signal pending interrupt */
+ r_sdreg32(bus, &intstatus,
+ offsetof(struct sdpcmd_regs, intstatus),
+ &retries);
+ bus->f2txdata++;
+ if (brcmf_sdcard_regfail(bus->sdiodev))
+ break;
+ if (intstatus & bus->hostintmask)
+ bus->ipend = true;
+ }
+ }
+
+ /* Deflow-control stack if needed */
+ if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) &&
+ drvr->txoff && (pktq_len(&bus->txq) < TXLOW))
+ brcmf_txflowcontrol(drvr, 0, OFF);
+
+ return cnt;
+}
+
+static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
+{
+ u32 intstatus, newstatus = 0;
+ uint retries = 0;
+ uint rxlimit = bus->rxbound; /* Rx frames to read before resched */
+ uint txlimit = bus->txbound; /* Tx frames to send before resched */
+ uint framecnt = 0; /* Temporary counter of tx/rx frames */
+ bool rxdone = true; /* Flag for no more read data */
+ bool resched = false; /* Flag indicating resched wanted */
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Start with leftover status bits */
+ intstatus = bus->intstatus;
+
+ down(&bus->sdsem);
+
+ /* If waiting for HTAVAIL, check status */
+ if (bus->clkstate == CLK_PENDING) {
+ int err;
+ u8 clkctl, devctl = 0;
+
+#ifdef BCMDBG
+ /* Check for inconsistent device control */
+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, &err);
+ if (err) {
+ brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err);
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
+ }
+#endif /* BCMDBG */
+
+ /* Read CSR, if clock on switch to AVAIL, else ignore */
+ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (err) {
+ brcmf_dbg(ERROR, "error reading CSR: %d\n",
+ err);
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
+ }
+
+ brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
+ devctl, clkctl);
+
+ if (SBSDIO_HTAV(clkctl)) {
+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, &err);
+ if (err) {
+ brcmf_dbg(ERROR, "error reading DEVCTL: %d\n",
+ err);
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
+ }
+ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_DEVICE_CTL, devctl, &err);
+ if (err) {
+ brcmf_dbg(ERROR, "error writing DEVCTL: %d\n",
+ err);
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
+ }
+ bus->clkstate = CLK_AVAIL;
+ } else {
+ goto clkwait;
+ }
+ }
+
+ bus_wake(bus);
+
+ /* Make sure backplane clock is on */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
+ if (bus->clkstate == CLK_PENDING)
+ goto clkwait;
+
+ /* Pending interrupt indicates new device status */
+ if (bus->ipend) {
+ bus->ipend = false;
+ r_sdreg32(bus, &newstatus,
+ offsetof(struct sdpcmd_regs, intstatus), &retries);
+ bus->f1regdata++;
+ if (brcmf_sdcard_regfail(bus->sdiodev))
+ newstatus = 0;
+ newstatus &= bus->hostintmask;
+ bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
+ if (newstatus) {
+ w_sdreg32(bus, newstatus,
+ offsetof(struct sdpcmd_regs, intstatus),
+ &retries);
+ bus->f1regdata++;
+ }
+ }
+
+ /* Merge new bits with previous */
+ intstatus |= newstatus;
+ bus->intstatus = 0;
+
+ /* Handle flow-control change: read new state in case our ack
+ * crossed another change interrupt. If change still set, assume
+ * FC ON for safety, let next loop through do the debounce.
+ */
+ if (intstatus & I_HMB_FC_CHANGE) {
+ intstatus &= ~I_HMB_FC_CHANGE;
+ w_sdreg32(bus, I_HMB_FC_CHANGE,
+ offsetof(struct sdpcmd_regs, intstatus), &retries);
+
+ r_sdreg32(bus, &newstatus,
+ offsetof(struct sdpcmd_regs, intstatus), &retries);
+ bus->f1regdata += 2;
+ bus->fcstate =
+ !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
+ intstatus |= (newstatus & bus->hostintmask);
+ }
+
+ /* Handle host mailbox indication */
+ if (intstatus & I_HMB_HOST_INT) {
+ intstatus &= ~I_HMB_HOST_INT;
+ intstatus |= brcmf_sdbrcm_hostmail(bus);
+ }
+
+ /* Generally don't ask for these, can get CRC errors... */
+ if (intstatus & I_WR_OOSYNC) {
+ brcmf_dbg(ERROR, "Dongle reports WR_OOSYNC\n");
+ intstatus &= ~I_WR_OOSYNC;
+ }
+
+ if (intstatus & I_RD_OOSYNC) {
+ brcmf_dbg(ERROR, "Dongle reports RD_OOSYNC\n");
+ intstatus &= ~I_RD_OOSYNC;
+ }
+
+ if (intstatus & I_SBINT) {
+ brcmf_dbg(ERROR, "Dongle reports SBINT\n");
+ intstatus &= ~I_SBINT;
+ }
+
+ /* Would be active due to wake-wlan in gSPI */
+ if (intstatus & I_CHIPACTIVE) {
+ brcmf_dbg(INFO, "Dongle reports CHIPACTIVE\n");
+ intstatus &= ~I_CHIPACTIVE;
+ }
+
+ /* Ignore frame indications if rxskip is set */
+ if (bus->rxskip)
+ intstatus &= ~I_HMB_FRAME_IND;
+
+ /* On frame indication, read available frames */
+ if (PKT_AVAILABLE()) {
+ framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone);
+ if (rxdone || bus->rxskip)
+ intstatus &= ~I_HMB_FRAME_IND;
+ rxlimit -= min(framecnt, rxlimit);
+ }
+
+ /* Keep still-pending events for next scheduling */
+ bus->intstatus = intstatus;
+
+clkwait:
+ if (data_ok(bus) && bus->ctrl_frame_stat &&
+ (bus->clkstate == CLK_AVAIL)) {
+ int ret, i;
+
+ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf,
+ (u32) bus->ctrl_frame_len, NULL);
+
+ if (ret < 0) {
+ /* On failure, abort the command and
+ terminate the frame */
+ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
+ ret);
+ bus->tx_sderrs++;
+
+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
+ NULL);
+ bus->f1regdata++;
+
+ for (i = 0; i < 3; i++) {
+ u8 hi, lo;
+ hi = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_FUNC1_WFRAMEBCHI,
+ NULL);
+ lo = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_1,
+ SBSDIO_FUNC1_WFRAMEBCLO,
+ NULL);
+ bus->f1regdata += 2;
+ if ((hi == 0) && (lo == 0))
+ break;
+ }
+
+ }
+ if (ret == 0)
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+
+ brcmf_dbg(INFO, "Return_dpc value is : %d\n", ret);
+ bus->ctrl_frame_stat = false;
+ brcmf_sdbrcm_wait_event_wakeup(bus);
+ }
+ /* Send queued frames (limit 1 if rx may still be pending) */
+ else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
+ brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
+ && data_ok(bus)) {
+ framecnt = rxdone ? txlimit : min(txlimit, bus->txminmax);
+ framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt);
+ txlimit -= framecnt;
+ }
+
+ /* Resched if events or tx frames are pending,
+ else await next interrupt */
+ /* On failed register access, all bets are off:
+ no resched or interrupts */
+ if ((bus->drvr->busstate == BRCMF_BUS_DOWN) ||
+ brcmf_sdcard_regfail(bus->sdiodev)) {
+ brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation %d\n",
+ brcmf_sdcard_regfail(bus->sdiodev));
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
+ bus->intstatus = 0;
+ } else if (bus->clkstate == CLK_PENDING) {
+ brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n");
+ resched = true;
+ } else if (bus->intstatus || bus->ipend ||
+ (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)
+ && data_ok(bus)) || PKT_AVAILABLE()) {
+ resched = true;
+ }
+
+ bus->dpc_sched = resched;
+
+ /* If we're done for now, turn off clock request. */
+ if ((bus->clkstate != CLK_PENDING)
+ && bus->idletime == BRCMF_IDLE_IMMEDIATE) {
+ bus->activity = false;
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ }
+
+ up(&bus->sdsem);
+
+ return resched;
+}
+
+static int brcmf_sdbrcm_dpc_thread(void *data)
+{
+ struct brcmf_bus *bus = (struct brcmf_bus *) data;
+
+ allow_signal(SIGTERM);
+ /* Run until signal received */
+ while (1) {
+ if (kthread_should_stop())
+ break;
+ if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
+ /* Call bus dpc unless it indicated down
+ (then clean stop) */
+ if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
+ if (brcmf_sdbrcm_dpc(bus))
+ complete(&bus->dpc_wait);
+ } else {
+ /* after stopping the bus, exit thread */
+ brcmf_sdbrcm_bus_stop(bus);
+ bus->dpc_tsk = NULL;
+ break;
+ }
+ } else
+ break;
+ }
+ return 0;
+}
+
+int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
+{
+ int ret = -EBADE;
+ uint datalen, prec;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ datalen = pkt->len;
+
+ /* Add space for the header */
+ skb_push(pkt, SDPCM_HDRLEN);
+ /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */
+
+ prec = prio2prec((pkt->priority & PRIOMASK));
+
+ /* Check for existing queue, current flow-control,
+ pending event, or pending clock */
+ brcmf_dbg(TRACE, "deferring pktq len %d\n", pktq_len(&bus->txq));
+ bus->fcqueued++;
+
+ /* Priority based enq */
+ spin_lock_bh(&bus->txqlock);
+ if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) {
+ skb_pull(pkt, SDPCM_HDRLEN);
+ brcmf_txcomplete(bus->drvr, pkt, false);
+ brcmu_pkt_buf_free_skb(pkt);
+ brcmf_dbg(ERROR, "out of bus->txq !!!\n");
+ ret = -ENOSR;
+ } else {
+ ret = 0;
+ }
+ spin_unlock_bh(&bus->txqlock);
+
+ if (pktq_len(&bus->txq) >= TXHI)
+ brcmf_txflowcontrol(bus->drvr, 0, ON);
+
+#ifdef BCMDBG
+ if (pktq_plen(&bus->txq, prec) > qcount[prec])
+ qcount[prec] = pktq_plen(&bus->txq, prec);
+#endif
+ /* Schedule DPC if needed to send queued packet(s) */
+ if (!bus->dpc_sched) {
+ bus->dpc_sched = true;
+ if (bus->dpc_tsk)
+ complete(&bus->dpc_wait);
+ }
+
+ return ret;
+}
+
+static int
+brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data,
+ uint size)
+{
+ int bcmerror = 0;
+ u32 sdaddr;
+ uint dsize;
+
+ /* Determine initial transfer parameters */
+ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
+ if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
+ dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
+ else
+ dsize = size;
+
+ /* 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");
+ goto xfer_done;
+ }
+
+ /* Do the transfer(s) */
+ while (size) {
+ brcmf_dbg(INFO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
+ write ? "write" : "read", dsize,
+ sdaddr, address & SBSDIO_SBWINDOW_MASK);
+ bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
+ sdaddr, data, dsize);
+ if (bcmerror) {
+ brcmf_dbg(ERROR, "membytes transfer failed\n");
+ break;
+ }
+
+ /* Adjust for next transfer (if any) */
+ size -= dsize;
+ if (size) {
+ data += dsize;
+ address += dsize;
+ bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev,
+ address);
+ if (bcmerror) {
+ brcmf_dbg(ERROR, "window change failed\n");
+ break;
+ }
+ sdaddr = 0;
+ dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
+ }
+ }
+
+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",
+ bus->sdiodev->sbwad);
+
+ return bcmerror;
+}
+
+#ifdef BCMDBG
+#define CONSOLE_LINE_MAX 192
+
+static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus)
+{
+ struct brcmf_console *c = &bus->console;
+ u8 line[CONSOLE_LINE_MAX], ch;
+ u32 n, idx, addr;
+ int rv;
+
+ /* Don't do anything until FWREADY updates console address */
+ if (bus->console_addr == 0)
+ return 0;
+
+ /* Read console log struct */
+ addr = bus->console_addr + offsetof(struct rte_console, log_le);
+ rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log_le,
+ sizeof(c->log_le));
+ if (rv < 0)
+ return rv;
+
+ /* Allocate console buffer (one time only) */
+ if (c->buf == NULL) {
+ c->bufsize = le32_to_cpu(c->log_le.buf_size);
+ c->buf = kmalloc(c->bufsize, GFP_ATOMIC);
+ if (c->buf == NULL)
+ return -ENOMEM;
+ }
+
+ idx = le32_to_cpu(c->log_le.idx);
+
+ /* Protect against corrupt value */
+ if (idx > c->bufsize)
+ return -EBADE;
+
+ /* Skip reading the console buffer if the index pointer
+ has not moved */
+ if (idx == c->last)
+ return 0;
+
+ /* Read the console buffer */
+ addr = le32_to_cpu(c->log_le.buf);
+ rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
+ if (rv < 0)
+ return rv;
+
+ while (c->last != idx) {
+ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
+ if (c->last == idx) {
+ /* This would output a partial line.
+ * Instead, back up
+ * the buffer pointer and output this
+ * line next time around.
+ */
+ if (c->last >= n)
+ c->last -= n;
+ else
+ c->last = c->bufsize - n;
+ goto break2;
+ }
+ ch = c->buf[c->last];
+ c->last = (c->last + 1) % c->bufsize;
+ if (ch == '\n')
+ break;
+ line[n] = ch;
+ }
+
+ if (n > 0) {
+ if (line[n - 1] == '\r')
+ n--;
+ line[n] = 0;
+ printk(KERN_DEBUG "CONSOLE: %s\n", line);
+ }
+ }
+break2:
+
+ return 0;
+}
+#endif /* BCMDBG */
+
+static int brcmf_tx_frame(struct brcmf_bus *bus, u8 *frame, u16 len)
+{
+ int i;
+ int ret;
+
+ bus->ctrl_frame_stat = false;
+ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC, frame, len, NULL);
+
+ if (ret < 0) {
+ /* On failure, abort the command and terminate the frame */
+ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
+ ret);
+ bus->tx_sderrs++;
+
+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_FRAMECTRL,
+ SFC_WF_TERM, NULL);
+ bus->f1regdata++;
+
+ for (i = 0; i < 3; i++) {
+ u8 hi, lo;
+ hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_WFRAMEBCHI,
+ NULL);
+ lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_WFRAMEBCLO,
+ NULL);
+ bus->f1regdata += 2;
+ if (hi == 0 && lo == 0)
+ break;
+ }
+ return ret;
+ }
+
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+
+ return ret;
+}
+
+int
+brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
+{
+ u8 *frame;
+ u16 len;
+ u32 swheader;
+ uint retries = 0;
+ u8 doff = 0;
+ int ret = -1;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Back the pointer to make a room for bus header */
+ frame = msg - SDPCM_HDRLEN;
+ len = (msglen += SDPCM_HDRLEN);
+
+ /* Add alignment padding (optional for ctl frames) */
+ doff = ((unsigned long)frame % BRCMF_SDALIGN);
+ if (doff) {
+ frame -= doff;
+ len += doff;
+ msglen += doff;
+ memset(frame, 0, doff + SDPCM_HDRLEN);
+ }
+ /* precondition: doff < BRCMF_SDALIGN */
+ doff += SDPCM_HDRLEN;
+
+ /* Round send length to next SDIO block */
+ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
+ u16 pad = bus->blocksize - (len % bus->blocksize);
+ if ((pad <= bus->roundup) && (pad < bus->blocksize))
+ len += pad;
+ } else if (len % BRCMF_SDALIGN) {
+ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
+ }
+
+ /* Satisfy length-alignment requirements */
+ if (len & (ALIGNMENT - 1))
+ len = roundup(len, ALIGNMENT);
+
+ /* precondition: IS_ALIGNED((unsigned long)frame, 2) */
+
+ /* Need to lock here to protect txseq and SDIO tx calls */
+ down(&bus->sdsem);
+
+ bus_wake(bus);
+
+ /* Make sure backplane clock is on */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+
+ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
+ *(__le16 *) frame = cpu_to_le16((u16) msglen);
+ *(((__le16 *) frame) + 1) = cpu_to_le16(~msglen);
+
+ /* Software tag: channel, sequence number, data offset */
+ swheader =
+ ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) &
+ SDPCM_CHANNEL_MASK)
+ | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) &
+ SDPCM_DOFFSET_MASK);
+ put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
+ put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+
+ if (!data_ok(bus)) {
+ brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n",
+ bus->tx_max, bus->tx_seq);
+ bus->ctrl_frame_stat = true;
+ /* Send from dpc */
+ bus->ctrl_frame_buf = frame;
+ bus->ctrl_frame_len = len;
+
+ brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
+
+ if (bus->ctrl_frame_stat == false) {
+ brcmf_dbg(INFO, "ctrl_frame_stat == false\n");
+ ret = 0;
+ } else {
+ brcmf_dbg(INFO, "ctrl_frame_stat == true\n");
+ ret = -1;
+ }
+ }
+
+ if (ret == -1) {
+#ifdef BCMDBG
+ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
+ printk(KERN_DEBUG "Tx Frame:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ frame, len);
+ } else if (BRCMF_HDRS_ON()) {
+ printk(KERN_DEBUG "TxHdr:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ frame, min_t(u16, len, 16));
+ }
+#endif
+
+ do {
+ ret = brcmf_tx_frame(bus, frame, len);
+ } while (ret < 0 && retries++ < TXRETRIES);
+ }
+
+ if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ bus->activity = false;
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
+ }
+
+ up(&bus->sdsem);
+
+ if (ret)
+ bus->drvr->tx_ctlerrs++;
+ else
+ bus->drvr->tx_ctlpkts++;
+
+ return ret ? -EIO : 0;
+}
+
+int
+brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
+{
+ int timeleft;
+ uint rxlen = 0;
+ bool pending;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Wait until control frame is available */
+ timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending);
+
+ down(&bus->sdsem);
+ rxlen = bus->rxlen;
+ memcpy(msg, bus->rxctl, min(msglen, rxlen));
+ bus->rxlen = 0;
+ up(&bus->sdsem);
+
+ 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");
+ } else if (pending == true) {
+ brcmf_dbg(CTL, "cancelled\n");
+ return -ERESTARTSYS;
+ } else {
+ brcmf_dbg(CTL, "resumed for unknown reason?\n");
+ }
+
+ if (rxlen)
+ bus->drvr->rx_ctlpkts++;
+ else
+ bus->drvr->rx_ctlerrs++;
+
+ return rxlen ? (int)rxlen : -ETIMEDOUT;
+}
+
+static int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len)
+{
+ int bcmerror = 0;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Basic sanity checks */
+ if (bus->drvr->up) {
+ bcmerror = -EISCONN;
+ goto err;
+ }
+ if (!len) {
+ bcmerror = -EOVERFLOW;
+ goto err;
+ }
+
+ /* Free the old ones and replace with passed variables */
+ kfree(bus->vars);
+
+ bus->vars = kmalloc(len, GFP_ATOMIC);
+ bus->varsz = bus->vars ? len : 0;
+ if (bus->vars == NULL) {
+ bcmerror = -ENOMEM;
+ goto err;
+ }
+
+ /* Copy the passed variables, which should include the
+ terminating double-null */
+ memcpy(bus->vars, arg, bus->varsz);
+err:
+ return bcmerror;
+}
+
+static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
+{
+ int bcmerror = 0;
+ u32 varsize;
+ u32 varaddr;
+ u8 *vbuffer;
+ u32 varsizew;
+ __le32 varsizew_le;
+#ifdef BCMDBG
+ char *nvram_ularray;
+#endif /* BCMDBG */
+
+ /* Even if there are no vars are to be written, we still
+ need to set the ramsize. */
+ varsize = bus->varsz ? roundup(bus->varsz, 4) : 0;
+ varaddr = (bus->ramsize - 4) - varsize;
+
+ if (bus->vars) {
+ vbuffer = kzalloc(varsize, GFP_ATOMIC);
+ if (!vbuffer)
+ return -ENOMEM;
+
+ memcpy(vbuffer, bus->vars, bus->varsz);
+
+ /* Write the vars list */
+ bcmerror =
+ brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize);
+#ifdef BCMDBG
+ /* Verify NVRAM bytes */
+ brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize);
+ nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
+ if (!nvram_ularray)
+ return -ENOMEM;
+
+ /* Upload image to verify downloaded contents. */
+ memset(nvram_ularray, 0xaa, varsize);
+
+ /* Read the vars list to temp buffer for comparison */
+ bcmerror =
+ brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray,
+ varsize);
+ if (bcmerror) {
+ brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n",
+ bcmerror, varsize, varaddr);
+ }
+ /* Compare the org NVRAM with the one read from RAM */
+ if (memcmp(vbuffer, nvram_ularray, varsize))
+ brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n");
+ else
+ brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n");
+
+ kfree(nvram_ularray);
+#endif /* BCMDBG */
+
+ kfree(vbuffer);
+ }
+
+ /* adjust to the user specified RAM */
+ brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize);
+ brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n",
+ varaddr, varsize);
+ varsize = ((bus->ramsize - 4) - varaddr);
+
+ /*
+ * Determine the length token:
+ * Varsize, converted to words, in lower 16-bits, checksum
+ * in upper 16-bits.
+ */
+ if (bcmerror) {
+ varsizew = 0;
+ varsizew_le = cpu_to_le32(0);
+ } else {
+ varsizew = varsize / 4;
+ varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
+ varsizew_le = cpu_to_le32(varsizew);
+ }
+
+ brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n",
+ varsize, varsizew);
+
+ /* Write the length token to the last word */
+ bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4),
+ (u8 *)&varsizew_le, 4);
+
+ return bcmerror;
+}
+
+static void
+brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
+{
+ u32 regdata;
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4);
+ if (regdata & SBTML_RESET)
+ return;
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4);
+ if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
+ /*
+ * set target reject and spin until busy is clear
+ * (preserve core-specific bits)
+ */
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4);
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
+ 4, regdata | SBTML_REJ);
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4);
+ udelay(1);
+ SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatehigh), 4) &
+ SBTMH_BUSY), 100000);
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatehigh), 4);
+ if (regdata & SBTMH_BUSY)
+ brcmf_dbg(ERROR, "ARM core still busy\n");
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbidlow), 4);
+ if (regdata & SBIDL_INIT) {
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbimstate), 4) |
+ SBIM_RJ;
+ brcmf_sdcard_reg_write(sdiodev,
+ CORE_SB(corebase, sbimstate), 4,
+ regdata);
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbimstate), 4);
+ udelay(1);
+ SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbimstate), 4) &
+ SBIM_BY), 100000);
+ }
+
+ /* set reset and reject while enabling the clocks */
+ brcmf_sdcard_reg_write(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4,
+ (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
+ SBTML_REJ | SBTML_RESET));
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatelow), 4);
+ udelay(10);
+
+ /* clear the initiator reject bit */
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbidlow), 4);
+ if (regdata & SBIDL_INIT) {
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbimstate), 4) &
+ ~SBIM_RJ;
+ brcmf_sdcard_reg_write(sdiodev,
+ CORE_SB(corebase, sbimstate), 4,
+ regdata);
+ }
+ }
+
+ /* leave reset and reject asserted */
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
+ (SBTML_REJ | SBTML_RESET));
+ udelay(1);
+}
+
+static void
+brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
+{
+ u32 regdata;
+
+ /*
+ * Must do the disable sequence first to work for
+ * arbitrary current core state.
+ */
+ brcmf_sdbrcm_chip_disablecore(sdiodev, corebase);
+
+ /*
+ * Now do the initialization sequence.
+ * set reset while enabling the clock and
+ * forcing them on throughout the core
+ */
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
+ ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
+ SBTML_RESET);
+ udelay(1);
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbtmstatehigh), 4);
+ if (regdata & SBTMH_SERR)
+ brcmf_sdcard_reg_write(sdiodev,
+ CORE_SB(corebase, sbtmstatehigh), 4, 0);
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(corebase, sbimstate), 4);
+ if (regdata & (SBIM_IBE | SBIM_TO))
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4,
+ regdata & ~(SBIM_IBE | SBIM_TO));
+
+ /* clear reset and allow it to propagate throughout the core */
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
+ (SICF_FGC << SBTML_SICF_SHIFT) |
+ (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
+ udelay(1);
+
+ /* leave clock enabled */
+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
+ (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
+ udelay(1);
+}
+
+static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
+{
+ uint retries;
+ u32 regdata;
+ int bcmerror = 0;
+
+ /* To enter download state, disable ARM and reset SOCRAM.
+ * To exit download state, simply reset ARM (default is RAM boot).
+ */
+ if (enter) {
+ bus->alp_only = true;
+
+ brcmf_sdbrcm_chip_disablecore(bus->sdiodev,
+ bus->ci->armcorebase);
+
+ brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->ramcorebase);
+
+ /* Clear the top bit of memory */
+ if (bus->ramsize) {
+ u32 zeros = 0;
+ brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
+ (u8 *)&zeros, 4);
+ }
+ } else {
+ regdata = brcmf_sdcard_reg_read(bus->sdiodev,
+ CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4);
+ regdata &= (SBTML_RESET | SBTML_REJ_MASK |
+ (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
+ if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) {
+ brcmf_dbg(ERROR, "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");
+ bcmerror = 0;
+ }
+
+ w_sdreg32(bus, 0xFFFFFFFF,
+ offsetof(struct sdpcmd_regs, intstatus), &retries);
+
+ brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->armcorebase);
+
+ /* Allow HT Clock now that the ARM is running. */
+ bus->alp_only = false;
+
+ bus->drvr->busstate = BRCMF_BUS_LOAD;
+ }
+fail:
+ return bcmerror;
+}
+
+static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus)
+{
+ if (bus->firmware->size < bus->fw_ptr + len)
+ len = bus->firmware->size - bus->fw_ptr;
+
+ memcpy(buf, &bus->firmware->data[bus->fw_ptr], len);
+ bus->fw_ptr += len;
+ return len;
+}
+
+MODULE_FIRMWARE(BCM4329_FW_NAME);
+MODULE_FIRMWARE(BCM4329_NV_NAME);
+
+static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus)
+{
+ int offset = 0;
+ uint len;
+ u8 *memblock = NULL, *memptr;
+ int ret;
+
+ brcmf_dbg(INFO, "Enter\n");
+
+ bus->fw_name = BCM4329_FW_NAME;
+ ret = request_firmware(&bus->firmware, bus->fw_name,
+ &bus->sdiodev->func[2]->dev);
+ if (ret) {
+ brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret);
+ return ret;
+ }
+ bus->fw_ptr = 0;
+
+ memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC);
+ if (memblock == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ if ((u32)(unsigned long)memblock % BRCMF_SDALIGN)
+ memptr += (BRCMF_SDALIGN -
+ ((u32)(unsigned long)memblock % BRCMF_SDALIGN));
+
+ /* Download image */
+ while ((len =
+ 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",
+ ret, MEMBLOCK, offset);
+ goto err;
+ }
+
+ offset += MEMBLOCK;
+ }
+
+err:
+ kfree(memblock);
+
+ release_firmware(bus->firmware);
+ bus->fw_ptr = 0;
+
+ return ret;
+}
+
+/*
+ * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file
+ * and ending in a NUL.
+ * Removes carriage returns, empty lines, comment lines, and converts
+ * newlines to NULs.
+ * Shortens buffer as needed and pads with NULs. End of buffer is marked
+ * by two NULs.
+*/
+
+static uint brcmf_process_nvram_vars(char *varbuf, uint len)
+{
+ char *dp;
+ bool findNewline;
+ int column;
+ uint buf_len, n;
+
+ dp = varbuf;
+
+ findNewline = false;
+ column = 0;
+
+ for (n = 0; n < len; n++) {
+ if (varbuf[n] == 0)
+ break;
+ if (varbuf[n] == '\r')
+ continue;
+ if (findNewline && varbuf[n] != '\n')
+ continue;
+ findNewline = false;
+ if (varbuf[n] == '#') {
+ findNewline = true;
+ continue;
+ }
+ if (varbuf[n] == '\n') {
+ if (column == 0)
+ continue;
+ *dp++ = 0;
+ column = 0;
+ continue;
+ }
+ *dp++ = varbuf[n];
+ column++;
+ }
+ buf_len = dp - varbuf;
+
+ while (dp < varbuf + n)
+ *dp++ = 0;
+
+ return buf_len;
+}
+
+static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus)
+{
+ uint len;
+ char *memblock = NULL;
+ char *bufp;
+ int ret;
+
+ bus->nv_name = BCM4329_NV_NAME;
+ ret = request_firmware(&bus->firmware, bus->nv_name,
+ &bus->sdiodev->func[2]->dev);
+ if (ret) {
+ brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret);
+ return ret;
+ }
+ bus->fw_ptr = 0;
+
+ memblock = kmalloc(MEMBLOCK, GFP_ATOMIC);
+ if (memblock == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus);
+
+ if (len > 0 && len < MEMBLOCK) {
+ bufp = (char *)memblock;
+ bufp[len] = 0;
+ len = brcmf_process_nvram_vars(bufp, len);
+ bufp += len;
+ *bufp++ = 0;
+ if (len)
+ ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1);
+ if (ret)
+ brcmf_dbg(ERROR, "error downloading vars: %d\n", ret);
+ } else {
+ brcmf_dbg(ERROR, "error reading nvram file: %d\n", len);
+ ret = -EIO;
+ }
+
+err:
+ kfree(memblock);
+
+ release_firmware(bus->firmware);
+ bus->fw_ptr = 0;
+
+ return ret;
+}
+
+static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
+{
+ int bcmerror = -1;
+
+ /* Keep arm in reset */
+ if (brcmf_sdbrcm_download_state(bus, true)) {
+ brcmf_dbg(ERROR, "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");
+ goto err;
+ }
+
+ /* External nvram takes precedence if specified */
+ if (brcmf_sdbrcm_download_nvram(bus))
+ brcmf_dbg(ERROR, "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");
+ goto err;
+ }
+
+ bcmerror = 0;
+
+err:
+ return bcmerror;
+}
+
+static bool
+brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
+{
+ bool ret;
+
+ /* Download the firmware */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+
+ ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
+
+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+
+ return ret;
+}
+
+void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
+{
+ u32 local_hostintmask;
+ u8 saveclk;
+ uint retries;
+ int err;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (bus->watchdog_tsk) {
+ send_sig(SIGTERM, bus->watchdog_tsk, 1);
+ kthread_stop(bus->watchdog_tsk);
+ bus->watchdog_tsk = NULL;
+ }
+
+ if (bus->dpc_tsk && bus->dpc_tsk != current) {
+ send_sig(SIGTERM, bus->dpc_tsk, 1);
+ kthread_stop(bus->dpc_tsk);
+ bus->dpc_tsk = NULL;
+ }
+
+ down(&bus->sdsem);
+
+ bus_wake(bus);
+
+ /* Enable clock for device interrupts */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+
+ /* Disable and clear interrupts at the chip level also */
+ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
+ local_hostintmask = bus->hostintmask;
+ bus->hostintmask = 0;
+
+ /* Change our idea of bus state */
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
+
+ /* Force clocks on backplane to be sure F2 interrupt propagates */
+ saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (!err) {
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
+ }
+ if (err)
+ brcmf_dbg(ERROR, "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");
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+ SDIO_FUNC_ENABLE_1, NULL);
+
+ /* Clear any pending interrupts now that F2 is disabled */
+ w_sdreg32(bus, local_hostintmask,
+ offsetof(struct sdpcmd_regs, intstatus), &retries);
+
+ /* Turn off the backplane clock (only) */
+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+
+ /* Clear the data packet queues */
+ brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
+
+ /* Clear any held glomming stuff */
+ if (bus->glomd)
+ brcmu_pkt_buf_free_skb(bus->glomd);
+
+ if (bus->glom)
+ brcmu_pkt_buf_free_skb(bus->glom);
+
+ bus->glom = bus->glomd = NULL;
+
+ /* Clear rx control and wake any waiters */
+ bus->rxlen = 0;
+ brcmf_sdbrcm_dcmd_resp_wake(bus);
+
+ /* Reset some F2 state stuff */
+ bus->rxskip = false;
+ bus->tx_seq = bus->rx_seq = 0;
+
+ up(&bus->sdsem);
+}
+
+int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr)
+{
+ struct brcmf_bus *bus = drvr->bus;
+ unsigned long timeout;
+ uint retries = 0;
+ u8 ready, enable;
+ int err, ret = 0;
+ u8 saveclk;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* try to download image and nvram to the dongle */
+ if (drvr->busstate == BRCMF_BUS_DOWN) {
+ if (!(brcmf_sdbrcm_download_firmware(bus)))
+ return -1;
+ }
+
+ if (!bus->drvr)
+ return 0;
+
+ /* Start the watchdog timer */
+ bus->drvr->tickcnt = 0;
+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+
+ down(&bus->sdsem);
+
+ /* Make sure backplane clock is on, needed to generate F2 interrupt */
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ if (bus->clkstate != CLK_AVAIL)
+ goto exit;
+
+ /* Force clocks on backplane to be sure F2 interrupt propagates */
+ saveclk =
+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (!err) {
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
+ }
+ if (err) {
+ brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err);
+ goto exit;
+ }
+
+ /* Enable function 2 (frame transfers) */
+ w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
+ offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries);
+ enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+ enable, NULL);
+
+ timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY);
+ ready = 0;
+ while (enable != ready) {
+ ready = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_0,
+ SDIO_CCCR_IORx, NULL);
+ if (time_after(jiffies, timeout))
+ break;
+ else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50))
+ /* prevent busy waiting if it takes too long */
+ msleep_interruptible(20);
+ }
+
+ brcmf_dbg(INFO, "enable 0x%02x, ready 0x%02x\n", enable, ready);
+
+ /* If F2 successfully enabled, set core and enable interrupts */
+ if (ready == enable) {
+ /* Set up the interrupt mask and enable interrupts */
+ bus->hostintmask = HOSTINTMASK;
+ w_sdreg32(bus, bus->hostintmask,
+ offsetof(struct sdpcmd_regs, hostintmask), &retries);
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_WATERMARK, 8, &err);
+
+ /* Set bus state according to enable result */
+ drvr->busstate = BRCMF_BUS_DATA;
+ }
+
+ else {
+ /* Disable F2 again */
+ enable = SDIO_FUNC_ENABLE_1;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0,
+ SDIO_CCCR_IOEx, enable, NULL);
+ }
+
+ /* Restore previous clock setting */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
+
+ /* If we didn't come up, turn off backplane clock */
+ if (drvr->busstate != BRCMF_BUS_DATA)
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+
+exit:
+ up(&bus->sdsem);
+
+ return ret;
+}
+
+void brcmf_sdbrcm_isr(void *arg)
+{
+ struct brcmf_bus *bus = (struct brcmf_bus *) arg;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (!bus) {
+ brcmf_dbg(ERROR, "bus is null pointer, exiting\n");
+ return;
+ }
+
+ if (bus->drvr->busstate == BRCMF_BUS_DOWN) {
+ brcmf_dbg(ERROR, "bus is down. we have nothing to do\n");
+ return;
+ }
+ /* Count the interrupt call */
+ bus->intrcount++;
+ bus->ipend = true;
+
+ /* Shouldn't get this interrupt if we're sleeping? */
+ if (bus->sleeping) {
+ brcmf_dbg(ERROR, "INTERRUPT WHILE SLEEPING??\n");
+ return;
+ }
+
+ /* Disable additional interrupts (is this needed now)? */
+ if (!bus->intr)
+ brcmf_dbg(ERROR, "isr w/o interrupt configured!\n");
+
+ bus->dpc_sched = true;
+ if (bus->dpc_tsk)
+ complete(&bus->dpc_wait);
+}
+
+static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr)
+{
+ struct brcmf_bus *bus;
+
+ brcmf_dbg(TIMER, "Enter\n");
+
+ bus = drvr->bus;
+
+ /* Ignore the timer if simulating bus down */
+ if (bus->sleeping)
+ return false;
+
+ down(&bus->sdsem);
+
+ /* Poll period: check device if appropriate. */
+ if (bus->poll && (++bus->polltick >= bus->pollrate)) {
+ u32 intstatus = 0;
+
+ /* Reset poll tick */
+ bus->polltick = 0;
+
+ /* Check device if no interrupts */
+ if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
+
+ if (!bus->dpc_sched) {
+ u8 devpend;
+ devpend = brcmf_sdcard_cfg_read(bus->sdiodev,
+ SDIO_FUNC_0, SDIO_CCCR_INTx,
+ NULL);
+ intstatus =
+ devpend & (INTR_STATUS_FUNC1 |
+ INTR_STATUS_FUNC2);
+ }
+
+ /* If there is something, make like the ISR and
+ schedule the DPC */
+ if (intstatus) {
+ bus->pollcnt++;
+ bus->ipend = true;
+
+ bus->dpc_sched = true;
+ if (bus->dpc_tsk)
+ complete(&bus->dpc_wait);
+ }
+ }
+
+ /* Update interrupt tracking */
+ bus->lastintrs = bus->intrcount;
+ }
+#ifdef BCMDBG
+ /* Poll for console output periodically */
+ if (drvr->busstate == 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;
+ /* 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;
+ }
+ }
+#endif /* BCMDBG */
+
+ /* On idle timeout clear activity flag and/or turn off clock */
+ if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
+ if (++bus->idlecount >= bus->idletime) {
+ bus->idlecount = 0;
+ if (bus->activity) {
+ bus->activity = false;
+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
+ } else {
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ }
+ }
+ }
+
+ up(&bus->sdsem);
+
+ return bus->ipend;
+}
+
+static bool brcmf_sdbrcm_chipmatch(u16 chipid)
+{
+ if (chipid == BCM4329_CHIP_ID)
+ return true;
+ return false;
+}
+
+static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ kfree(bus->rxbuf);
+ bus->rxctl = bus->rxbuf = NULL;
+ bus->rxlen = 0;
+
+ kfree(bus->databuf);
+ bus->databuf = NULL;
+}
+
+static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (bus->drvr->maxctl) {
+ bus->rxblen =
+ roundup((bus->drvr->maxctl + SDPCM_HDRLEN),
+ ALIGNMENT) + BRCMF_SDALIGN;
+ bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
+ if (!(bus->rxbuf))
+ goto fail;
+ }
+
+ /* Allocate buffer to receive glomed packet */
+ bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC);
+ if (!(bus->databuf)) {
+ /* release rxbuf which was already located as above */
+ if (!bus->rxblen)
+ kfree(bus->rxbuf);
+ goto fail;
+ }
+
+ /* Align the buffer */
+ if ((unsigned long)bus->databuf % BRCMF_SDALIGN)
+ bus->dataptr = bus->databuf + (BRCMF_SDALIGN -
+ ((unsigned long)bus->databuf % BRCMF_SDALIGN));
+ else
+ bus->dataptr = bus->databuf;
+
+ return true;
+
+fail:
+ return false;
+}
+
+/* SDIO Pad drive strength to select value mappings */
+struct sdiod_drive_str {
+ u8 strength; /* Pad Drive Strength in mA */
+ u8 sel; /* Chip-specific select value */
+};
+
+/* SDIO Drive Strength to sel value table for PMU Rev 1 */
+static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
+ {
+ 4, 0x2}, {
+ 2, 0x3}, {
+ 1, 0x0}, {
+ 0, 0x0}
+ };
+
+/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
+static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
+ {
+ 12, 0x7}, {
+ 10, 0x6}, {
+ 8, 0x5}, {
+ 6, 0x4}, {
+ 4, 0x2}, {
+ 2, 0x1}, {
+ 0, 0x0}
+ };
+
+/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
+static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
+ {
+ 32, 0x7}, {
+ 26, 0x6}, {
+ 22, 0x5}, {
+ 16, 0x4}, {
+ 12, 0x3}, {
+ 8, 0x2}, {
+ 4, 0x1}, {
+ 0, 0x0}
+ };
+
+#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
+
+static char *brcmf_chipname(uint chipid, char *buf, uint len)
+{
+ const char *fmt;
+
+ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
+ snprintf(buf, len, fmt, chipid);
+ return buf;
+}
+
+static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus,
+ u32 drivestrength) {
+ struct sdiod_drive_str *str_tab = NULL;
+ u32 str_mask = 0;
+ u32 str_shift = 0;
+ char chn[8];
+
+ if (!(bus->ci->cccaps & CC_CAP_PMU))
+ return;
+
+ switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->ci->pmurev)) {
+ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
+ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
+ str_mask = 0x30000000;
+ str_shift = 28;
+ break;
+ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
+ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
+ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
+ str_mask = 0x00003800;
+ str_shift = 11;
+ break;
+ case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
+ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
+ str_mask = 0x00003800;
+ str_shift = 11;
+ break;
+ default:
+ brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
+ brcmf_chipname(bus->ci->chip, chn, 8),
+ bus->ci->chiprev, bus->ci->pmurev);
+ break;
+ }
+
+ if (str_tab != NULL) {
+ u32 drivestrength_sel = 0;
+ u32 cc_data_temp;
+ int i;
+
+ for (i = 0; str_tab[i].strength != 0; i++) {
+ if (drivestrength >= str_tab[i].strength) {
+ drivestrength_sel = str_tab[i].sel;
+ break;
+ }
+ }
+
+ brcmf_sdcard_reg_write(bus->sdiodev,
+ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
+ 4, 1);
+ cc_data_temp = brcmf_sdcard_reg_read(bus->sdiodev,
+ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4);
+ cc_data_temp &= ~str_mask;
+ drivestrength_sel <<= str_shift;
+ cc_data_temp |= drivestrength_sel;
+ brcmf_sdcard_reg_write(bus->sdiodev,
+ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
+ 4, cc_data_temp);
+
+ brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
+ drivestrength, cc_data_temp);
+ }
+}
+
+static int
+brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci, u32 regs)
+{
+ u32 regdata;
+
+ /*
+ * Get CC core rev
+ * Chipid is assume to be at offset 0 from regs arg
+ * For different chiptypes or old sdio hosts w/o chipcommon,
+ * other ways of recognition should be added here.
+ */
+ ci->cccorebase = regs;
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_CC_REG(ci->cccorebase, chipid), 4);
+ ci->chip = regdata & CID_ID_MASK;
+ ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
+
+ brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
+
+ /* Address of cores for new chips should be added here */
+ switch (ci->chip) {
+ case BCM4329_CHIP_ID:
+ ci->buscorebase = BCM4329_CORE_BUS_BASE;
+ ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
+ ci->armcorebase = BCM4329_CORE_ARM_BASE;
+ ci->ramsize = BCM4329_RAMSIZE;
+ break;
+ default:
+ brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
+ return -ENODEV;
+ }
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(ci->cccorebase, sbidhigh), 4);
+ ci->ccrev = SBCOREREV(regdata);
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
+ ci->pmurev = regdata & PCAP_REV_MASK;
+
+ regdata = brcmf_sdcard_reg_read(sdiodev,
+ CORE_SB(ci->buscorebase, sbidhigh), 4);
+ ci->buscorerev = SBCOREREV(regdata);
+ ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
+
+ brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
+ ci->ccrev, ci->pmurev, ci->buscorerev, ci->buscoretype);
+
+ /* get chipcommon capabilites */
+ ci->cccaps = brcmf_sdcard_reg_read(sdiodev,
+ CORE_CC_REG(ci->cccorebase, capabilities), 4);
+
+ return 0;
+}
+
+static int
+brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs)
+{
+ struct chip_info *ci;
+ int err;
+ u8 clkval, clkset;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* alloc chip_info_t */
+ ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
+ if (NULL == ci)
+ return -ENOMEM;
+
+ /* bus/core/clk setup for register access */
+ /* Try forcing SDIO core to do ALPAvail request only */
+ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+ if (err) {
+ brcmf_dbg(ERROR, "error writing for HT off\n");
+ goto fail;
+ }
+
+ /* If register supported, wait for ALPAvail and then force ALP */
+ /* This may take up to 15 milliseconds */
+ clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, NULL);
+ if ((clkval & ~SBSDIO_AVBITS) == clkset) {
+ SPINWAIT(((clkval =
+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ NULL)),
+ !SBSDIO_ALPAV(clkval)),
+ PMU_MAX_TRANSITION_DLY);
+ if (!SBSDIO_ALPAV(clkval)) {
+ brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
+ clkval);
+ err = -EBUSY;
+ goto fail;
+ }
+ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF |
+ SBSDIO_FORCE_ALP;
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ clkset, &err);
+ udelay(65);
+ } else {
+ brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
+ clkset, clkval);
+ err = -EACCES;
+ goto fail;
+ }
+
+ /* Also, disable the extra SDIO pull-ups */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
+
+ err = brcmf_sdbrcm_chip_recognition(bus->sdiodev, ci, regs);
+ if (err)
+ goto fail;
+
+ /*
+ * Make sure any on-chip ARM is off (in case strapping is wrong),
+ * or downloaded code was already running.
+ */
+ brcmf_sdbrcm_chip_disablecore(bus->sdiodev, ci->armcorebase);
+
+ brcmf_sdcard_reg_write(bus->sdiodev,
+ CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
+ brcmf_sdcard_reg_write(bus->sdiodev,
+ CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
+
+ /* Disable F2 to clear any intermediate frame state on the dongle */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+ SDIO_FUNC_ENABLE_1, NULL);
+
+ /* WAR: cmd52 backplane read so core HW will drop ALPReq */
+ clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ 0, NULL);
+
+ /* Done with backplane-dependent accesses, can drop clock... */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+
+ bus->ci = ci;
+ return 0;
+fail:
+ bus->ci = NULL;
+ kfree(ci);
+ return err;
+}
+
+static bool
+brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
+{
+ u8 clkctl = 0;
+ int err = 0;
+ int reg_addr;
+ u32 reg_val;
+
+ bus->alp_only = true;
+
+ /* Return the window to backplane enumeration space for core access */
+ if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, SI_ENUM_BASE))
+ brcmf_dbg(ERROR, "FAILED to return to SI_ENUM_BASE\n");
+
+#ifdef BCMDBG
+ printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
+ brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4));
+
+#endif /* BCMDBG */
+
+ /*
+ * Force PLL off until brcmf_sdbrcm_chip_attach()
+ * programs PLL control regs
+ */
+
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ BRCMF_INIT_CLKCTL1, &err);
+ if (!err)
+ clkctl =
+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+ 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",
+ err, BRCMF_INIT_CLKCTL1, clkctl);
+ goto fail;
+ }
+
+ if (brcmf_sdbrcm_chip_attach(bus, regsva)) {
+ brcmf_dbg(ERROR, "brcmf_sdbrcm_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);
+ goto fail;
+ }
+
+ brcmf_sdbrcm_sdiod_drive_strength_init(bus, SDIO_DRIVE_STRENGTH);
+
+ /* Get info on the ARM and SOCRAM cores... */
+ brcmf_sdcard_reg_read(bus->sdiodev,
+ CORE_SB(bus->ci->armcorebase, sbidhigh), 4);
+ bus->ramsize = bus->ci->ramsize;
+ if (!(bus->ramsize)) {
+ brcmf_dbg(ERROR, "failed to find SOCRAM memory!\n");
+ goto fail;
+ }
+
+ /* Set core control so an SDIO reset does a backplane reset */
+ reg_addr = bus->ci->buscorebase +
+ offsetof(struct sdpcmd_regs, corecontrol);
+ reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32));
+ brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32),
+ reg_val | CC_BPRESEN);
+
+ brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
+
+ /* Locate an appropriately-aligned portion of hdrbuf */
+ bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
+ BRCMF_SDALIGN);
+
+ /* Set the poll and/or interrupt flags */
+ bus->intr = true;
+ bus->poll = false;
+ if (bus->poll)
+ bus->pollrate = 1;
+
+ return true;
+
+fail:
+ return false;
+}
+
+static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* Disable F2 to clear any intermediate frame state on the dongle */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+ SDIO_FUNC_ENABLE_1, NULL);
+
+ bus->drvr->busstate = BRCMF_BUS_DOWN;
+ bus->sleeping = false;
+ bus->rxflow = false;
+
+ /* Done with backplane-dependent accesses, can drop clock... */
+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+
+ /* ...and initialize clock/power states */
+ bus->clkstate = CLK_SDONLY;
+ bus->idletime = BRCMF_IDLE_INTERVAL;
+ bus->idleclock = BRCMF_IDLE_ACTIVE;
+
+ /* Query the F2 block size, set roundup accordingly */
+ bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
+ bus->roundup = min(max_roundup, bus->blocksize);
+
+ /* bus module does not support packet chaining */
+ bus->use_rxchain = false;
+ bus->sd_rxchain = false;
+
+ return true;
+}
+
+static int
+brcmf_sdbrcm_watchdog_thread(void *data)
+{
+ struct brcmf_bus *bus = (struct brcmf_bus *)data;
+
+ allow_signal(SIGTERM);
+ /* Run until signal received */
+ while (1) {
+ if (kthread_should_stop())
+ break;
+ if (!wait_for_completion_interruptible(&bus->watchdog_wait)) {
+ brcmf_sdbrcm_bus_watchdog(bus->drvr);
+ /* Count the tick for reference */
+ bus->drvr->tickcnt++;
+ } else
+ break;
+ }
+ return 0;
+}
+
+static void
+brcmf_sdbrcm_watchdog(unsigned long data)
+{
+ struct brcmf_bus *bus = (struct brcmf_bus *)data;
+
+ if (bus->watchdog_tsk) {
+ complete(&bus->watchdog_wait);
+ /* Reschedule the watchdog */
+ if (bus->wd_timer_valid)
+ mod_timer(&bus->timer,
+ jiffies + BRCMF_WD_POLL_MS * HZ / 1000);
+ }
+}
+
+static void
+brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ kfree(bus->ci);
+ bus->ci = NULL;
+}
+
+static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (bus->ci) {
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ brcmf_sdbrcm_chip_detach(bus);
+ if (bus->vars && bus->varsz)
+ kfree(bus->vars);
+ bus->vars = NULL;
+ }
+
+ brcmf_dbg(TRACE, "Disconnected\n");
+}
+
+/* Detach and free everything */
+static void brcmf_sdbrcm_release(struct brcmf_bus *bus)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (bus) {
+ /* De-register interrupt handler */
+ brcmf_sdcard_intr_dereg(bus->sdiodev);
+
+ if (bus->drvr) {
+ brcmf_detach(bus->drvr);
+ brcmf_sdbrcm_release_dongle(bus);
+ bus->drvr = NULL;
+ }
+
+ brcmf_sdbrcm_release_malloc(bus);
+
+ kfree(bus);
+ }
+
+ brcmf_dbg(TRACE, "Disconnected\n");
+}
+
+void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
+ u32 regsva, struct brcmf_sdio_dev *sdiodev)
+{
+ int ret;
+ struct brcmf_bus *bus;
+
+ /* Init global variables at run-time, not as part of the declaration.
+ * This is required to support init/de-init of the driver.
+ * Initialization
+ * of globals as part of the declaration results in non-deterministic
+ * behavior since the value of the globals may be different on the
+ * first time that the driver is initialized vs subsequent
+ * initializations.
+ */
+ brcmf_c_init();
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* We make an assumption about address window mappings:
+ * regsva == SI_ENUM_BASE*/
+
+ /* Allocate private bus interface state */
+ bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
+ if (!bus)
+ goto fail;
+
+ bus->sdiodev = sdiodev;
+ sdiodev->bus = bus;
+ bus->txbound = BRCMF_TXBOUND;
+ bus->rxbound = BRCMF_RXBOUND;
+ bus->txminmax = BRCMF_TXMINMAX;
+ bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
+ bus->usebufpool = false; /* Use bufpool if allocated,
+ else use locally malloced rxbuf */
+
+ /* attempt to attach to the dongle */
+ if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) {
+ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_attach failed\n");
+ goto fail;
+ }
+
+ spin_lock_init(&bus->txqlock);
+ init_waitqueue_head(&bus->ctrl_wait);
+ init_waitqueue_head(&bus->dcmd_resp_wait);
+
+ /* 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,
+ bus, "brcmf_watchdog");
+ if (IS_ERR(bus->watchdog_tsk)) {
+ printk(KERN_WARNING
+ "brcmf_watchdog thread failed to start\n");
+ bus->watchdog_tsk = NULL;
+ }
+ /* Initialize DPC thread */
+ init_completion(&bus->dpc_wait);
+ bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
+ bus, "brcmf_dpc");
+ if (IS_ERR(bus->dpc_tsk)) {
+ printk(KERN_WARNING
+ "brcmf_dpc thread failed to start\n");
+ bus->dpc_tsk = NULL;
+ }
+
+ /* Attach to the brcmf/OS/network interface */
+ bus->drvr = brcmf_attach(bus, SDPCM_RESERVE);
+ if (!bus->drvr) {
+ brcmf_dbg(ERROR, "brcmf_attach failed\n");
+ goto fail;
+ }
+
+ /* Allocate buffers */
+ if (!(brcmf_sdbrcm_probe_malloc(bus))) {
+ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_malloc failed\n");
+ goto fail;
+ }
+
+ if (!(brcmf_sdbrcm_probe_init(bus))) {
+ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_init failed\n");
+ goto fail;
+ }
+
+ /* Register interrupt callback, but mask it (not operational yet). */
+ brcmf_dbg(INTR, "disable SDIO interrupts (not interested yet)\n");
+ ret = brcmf_sdcard_intr_reg(bus->sdiodev);
+ if (ret != 0) {
+ brcmf_dbg(ERROR, "FAILED: sdcard_intr_reg returned %d\n", ret);
+ goto fail;
+ }
+ brcmf_dbg(INTR, "registered SDIO interrupt function ok\n");
+
+ brcmf_dbg(INFO, "completed!!\n");
+
+ /* if firmware path present try to download and bring up bus */
+ ret = brcmf_bus_start(bus->drvr);
+ if (ret != 0) {
+ if (ret == -ENOLINK) {
+ brcmf_dbg(ERROR, "dongle is not responding\n");
+ goto fail;
+ }
+ }
+ /* Ok, have the per-port tell the stack we're open for business */
+ if (brcmf_net_attach(bus->drvr, 0) != 0) {
+ brcmf_dbg(ERROR, "Net attach failed!!\n");
+ goto fail;
+ }
+
+ return bus;
+
+fail:
+ brcmf_sdbrcm_release(bus);
+ return NULL;
+}
+
+void brcmf_sdbrcm_disconnect(void *ptr)
+{
+ struct brcmf_bus *bus = (struct brcmf_bus *)ptr;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ if (bus)
+ brcmf_sdbrcm_release(bus);
+
+ brcmf_dbg(TRACE, "Disconnected\n");
+}
+
+struct device *brcmf_bus_get_device(struct brcmf_bus *bus)
+{
+ return &bus->sdiodev->func[2]->dev;
+}
+
+void
+brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
+{
+ /* don't start the wd until fw is loaded */
+ if (bus->drvr->busstate == BRCMF_BUS_DOWN)
+ return;
+
+ /* Totally stop the timer */
+ if (!wdtick && bus->wd_timer_valid == true) {
+ del_timer_sync(&bus->timer);
+ bus->wd_timer_valid = false;
+ bus->save_ms = wdtick;
+ return;
+ }
+
+ if (wdtick) {
+ if (bus->save_ms != BRCMF_WD_POLL_MS) {
+ if (bus->wd_timer_valid == true)
+ /* Stop timer and restart at new value */
+ del_timer_sync(&bus->timer);
+
+ /* Create timer again when watchdog period is
+ dynamically changed or in the first instance
+ */
+ bus->timer.expires =
+ jiffies + BRCMF_WD_POLL_MS * HZ / 1000;
+ add_timer(&bus->timer);
+
+ } else {
+ /* Re arm the timer, at last watchdog period */
+ mod_timer(&bus->timer,
+ jiffies + BRCMF_WD_POLL_MS * HZ / 1000);
+ }
+
+ bus->wd_timer_valid = true;
+ bus->save_ms = wdtick;
+ }
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
new file mode 100644
index 000000000000..726fa8981113
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_SDH_H_
+#define _BRCM_SDH_H_
+
+#include <linux/skbuff.h>
+
+#define SDIO_FUNC_0 0
+#define SDIO_FUNC_1 1
+#define SDIO_FUNC_2 2
+
+#define SDIOD_FBR_SIZE 0x100
+
+/* io_en */
+#define SDIO_FUNC_ENABLE_1 0x02
+#define SDIO_FUNC_ENABLE_2 0x04
+
+/* io_rdys */
+#define SDIO_FUNC_READY_1 0x02
+#define SDIO_FUNC_READY_2 0x04
+
+/* intr_status */
+#define INTR_STATUS_FUNC1 0x2
+#define INTR_STATUS_FUNC2 0x4
+
+/* Maximum number of I/O funcs */
+#define SDIOD_MAX_IOFUNCS 7
+
+/* as of sdiod rev 0, supports 3 functions */
+#define SBSDIO_NUM_FUNCTION 3
+
+/* function 1 miscellaneous registers */
+
+/* sprom command and status */
+#define SBSDIO_SPROM_CS 0x10000
+/* sprom info register */
+#define SBSDIO_SPROM_INFO 0x10001
+/* sprom indirect access data byte 0 */
+#define SBSDIO_SPROM_DATA_LOW 0x10002
+/* sprom indirect access data byte 1 */
+#define SBSDIO_SPROM_DATA_HIGH 0x10003
+/* sprom indirect access addr byte 0 */
+#define SBSDIO_SPROM_ADDR_LOW 0x10004
+/* sprom indirect access addr byte 0 */
+#define SBSDIO_SPROM_ADDR_HIGH 0x10005
+/* xtal_pu (gpio) output */
+#define SBSDIO_CHIP_CTRL_DATA 0x10006
+/* xtal_pu (gpio) enable */
+#define SBSDIO_CHIP_CTRL_EN 0x10007
+/* rev < 7, watermark for sdio device */
+#define SBSDIO_WATERMARK 0x10008
+/* control busy signal generation */
+#define SBSDIO_DEVICE_CTL 0x10009
+
+/* SB Address Window Low (b15) */
+#define SBSDIO_FUNC1_SBADDRLOW 0x1000A
+/* SB Address Window Mid (b23:b16) */
+#define SBSDIO_FUNC1_SBADDRMID 0x1000B
+/* SB Address Window High (b31:b24) */
+#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C
+/* Frame Control (frame term/abort) */
+#define SBSDIO_FUNC1_FRAMECTRL 0x1000D
+/* ChipClockCSR (ALP/HT ctl/status) */
+#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E
+/* SdioPullUp (on cmd, d0-d2) */
+#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F
+/* Write Frame Byte Count Low */
+#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019
+/* Write Frame Byte Count High */
+#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A
+/* Read Frame Byte Count Low */
+#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B
+/* Read Frame Byte Count High */
+#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C
+
+#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
+#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */
+
+/* function 1 OCP space */
+
+/* sb offset addr is <= 15 bits, 32k */
+#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF
+#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000
+/* with b15, maps to 32-bit SB access */
+#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000
+
+/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
+
+#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
+#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
+#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
+/* Address bits from SBADDR regs */
+#define SBSDIO_SBWINDOW_MASK 0xffff8000
+
+#define SDIOH_READ 0 /* Read request */
+#define SDIOH_WRITE 1 /* Write request */
+
+#define SDIOH_DATA_FIX 0 /* Fixed addressing */
+#define SDIOH_DATA_INC 1 /* Incremental addressing */
+
+/* internal return code */
+#define SUCCESS 0
+#define ERROR 1
+
+struct brcmf_sdreg {
+ int func;
+ int offset;
+ int value;
+};
+
+struct brcmf_sdio_dev {
+ struct sdio_func *func[SDIO_MAX_FUNCS];
+ u8 num_funcs; /* Supported funcs on client */
+ u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
+ u32 sbwad; /* Save backplane window address */
+ bool regfail; /* status of last reg_r/w call */
+ void *bus;
+ atomic_t suspend; /* suspend flag */
+ wait_queue_head_t request_byte_wait;
+ wait_queue_head_t request_word_wait;
+ wait_queue_head_t request_packet_wait;
+ wait_queue_head_t request_buffer_wait;
+
+};
+
+/* Register/deregister device interrupt handler. */
+extern int
+brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev);
+
+extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev);
+
+/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
+ * fn: function number
+ * addr: unmodified SDIO-space address
+ * data: data byte to write
+ * err: pointer to error code (or NULL)
+ */
+extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint func,
+ u32 addr, int *err);
+extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint func,
+ u32 addr, u8 data, int *err);
+
+/* Synchronous access to device (client) core registers via CMD53 to F1.
+ * addr: backplane address (i.e. >= regsva from attach)
+ * size: register width in bytes (2 or 4)
+ * data: data for register write
+ */
+extern u32
+brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size);
+
+extern u32
+brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
+ u32 data);
+
+/* Indicate if last reg read/write failed */
+extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev);
+
+/* Buffer transfer to/from device (client) core via cmd53.
+ * fn: function number
+ * addr: backplane address (i.e. >= regsva from attach)
+ * flags: backplane width, address increment, sync/async
+ * buf: pointer to memory data buffer
+ * nbytes: number of bytes to transfer to/from buf
+ * pkt: pointer to packet associated with buf (if any)
+ * complete: callback function for command completion (async only)
+ * handle: handle for completion callback (first arg in callback)
+ * Returns 0 or error code.
+ * NOTE: Async operation is not currently supported.
+ */
+extern int
+brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt);
+extern int
+brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt);
+
+/* Flags bits */
+
+/* Four-byte target (backplane) width (vs. two-byte) */
+#define SDIO_REQ_4BYTE 0x1
+/* Fixed address (FIFO) (vs. incrementing address) */
+#define SDIO_REQ_FIXED 0x2
+/* Async request (vs. sync request) */
+#define SDIO_REQ_ASYNC 0x4
+
+/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
+ * rw: read or write (0/1)
+ * addr: direct SDIO address
+ * buf: pointer to memory data buffer
+ * nbytes: number of bytes to transfer to/from buf
+ * Returns 0 or error code.
+ */
+extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw,
+ u32 addr, u8 *buf, uint nbytes);
+
+/* Issue an abort to the specified function */
+extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
+
+/* platform specific/high level functions */
+extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
+extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev);
+
+extern int brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
+ u32 address);
+
+/* attach, return handler on success, NULL if failed.
+ * The handler shall be provided by all subsequent calls. No local cache
+ * cfghdl points to the starting address of pci device mapped memory
+ */
+extern int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev);
+extern void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev);
+
+/* read or write one byte using cmd52 */
+extern int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw,
+ uint fnc, uint addr, u8 *byte);
+
+/* read or write 2/4 bytes using cmd53 */
+extern int
+brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
+ uint rw, uint fnc, uint addr,
+ u32 *word, uint nbyte);
+
+/* read or write any buffer using cmd53 */
+extern int
+brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
+ uint fix_inc, uint rw, uint fnc_num,
+ u32 addr, uint regwidth,
+ u32 buflen, u8 *buffer, struct sk_buff *pkt);
+
+/* Watchdog timer interface for pm ops */
+extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev,
+ bool enable);
+
+extern void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
+ u32 regsva, struct brcmf_sdio_dev *sdiodev);
+extern void brcmf_sdbrcm_disconnect(void *ptr);
+extern void brcmf_sdbrcm_isr(void *arg);
+#endif /* _BRCM_SDH_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 821206d3e536..5eddabe5228a 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -14,19 +14,18 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
+
#include <linux/kernel.h>
#include <linux/if_arp.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/netdevice.h>
-#include <linux/sched.h>
+#include <linux/bitops.h>
#include <linux/etherdevice.h>
-#include <linux/wireless.h>
#include <linux/ieee80211.h>
-#include <linux/mmc/sdio_func.h>
#include <linux/uaccess.h>
#include <net/cfg80211.h>
-#include <net/rtnetlink.h>
#include <brcmu_utils.h>
#include <defs.h>
@@ -34,306 +33,44 @@
#include "dhd.h"
#include "wl_cfg80211.h"
-static struct sdio_func *cfg80211_sdio_func;
-static struct brcmf_cfg80211_dev *cfg80211_dev;
-static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
-
-u32 brcmf_dbg_level = WL_DBG_ERR;
-
-/*
-** cfg80211_ops api/callback list
-*/
-static s32 brcmf_cfg80211_change_iface(struct wiphy *wiphy,
- struct net_device *ndev,
- enum nl80211_iftype type, u32 *flags,
- struct vif_params *params);
-static s32 __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_scan_request *request,
- struct cfg80211_ssid *this_ssid);
-static s32 brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_scan_request *request);
-static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
-static s32 brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_ibss_params *params);
-static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy,
- struct net_device *dev);
-static s32 brcmf_cfg80211_get_station(struct wiphy *wiphy,
- struct net_device *dev, u8 *mac,
- struct station_info *sinfo);
-static s32 brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy,
- struct net_device *dev, bool enabled,
- s32 timeout);
-static s32 brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
- struct net_device *dev,
- const u8 *addr,
- const struct cfg80211_bitrate_mask
- *mask);
-static int brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_cfg80211_disconnect(struct wiphy *wiphy,
- struct net_device *dev,
- u16 reason_code);
-static s32 brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
- enum nl80211_tx_power_setting type,
- s32 dbm);
-static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
-static s32 brcmf_cfg80211_config_default_key(struct wiphy *wiphy,
- struct net_device *dev, u8 key_idx,
- bool unicast, bool multicast);
-static s32 brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, bool pairwise, const u8 *mac_addr,
- struct key_params *params);
-static s32 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, bool pairwise, const u8 *mac_addr);
-static s32 brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, bool pairwise, const u8 *mac_addr,
- void *cookie, void (*callback) (void *cookie,
- struct
- key_params *
- params));
-static s32 brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
- struct net_device *dev,
- u8 key_idx);
-static s32 brcmf_cfg80211_resume(struct wiphy *wiphy);
-static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
- struct cfg80211_wowlan *wow);
-static s32 brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_pmksa *pmksa);
-static s32 brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_pmksa *pmksa);
-static s32 brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy,
- struct net_device *dev);
-/*
-** event & event Q handlers for cfg80211 interfaces
-*/
-static s32 brcmf_create_event_handler(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_destroy_event_handler(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_event_handler(void *data);
-static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_lock_eq(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_unlock_eq(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_init_eq_lock(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el);
-static struct brcmf_cfg80211_event_q *
-brcmf_deq_event(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 type,
- const struct brcmf_event_msg *msg, void *data);
-static void brcmf_put_event(struct brcmf_cfg80211_event_q *e);
-static void brcmf_wakeup_event(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e,
- void *data);
-static s32 brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e,
- void *data);
-static s32 brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e,
- void *data);
-static s32 brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data,
- bool completed);
-static s32 brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data);
-static s32 brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data);
-
-/*
-** register/deregister sdio function
-*/
-static void brcmf_clear_sdio_func(void);
-
-/*
-** ioctl utilites
-*/
-static s32 brcmf_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
- s32 buf_len);
-static __used s32 brcmf_dev_bufvar_set(struct net_device *dev, s8 *name,
- s8 *buf, s32 len);
-static s32 brcmf_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
-static s32 brcmf_dev_intvar_get(struct net_device *dev, s8 *name,
- s32 *retval);
-static s32 brcmf_dev_ioctl(struct net_device *dev, u32 cmd, void *arg,
- u32 len);
-
-/*
-** cfg80211 set_wiphy_params utilities
-*/
-static s32 brcmf_set_frag(struct net_device *dev, u32 frag_threshold);
-static s32 brcmf_set_rts(struct net_device *dev, u32 frag_threshold);
-static s32 brcmf_set_retry(struct net_device *dev, u32 retry, bool l);
-
-/*
-** wl profile utilities
-*/
-static s32 brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
- const struct brcmf_event_msg *e,
- void *data, s32 item);
-static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item);
-static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof);
-
-/*
-** cfg80211 connect utilites
-*/
-static s32 brcmf_set_wpa_version(struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_set_auth_type(struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_set_set_cipher(struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_set_key_mgmt(struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_set_set_sharedkey(struct net_device *dev,
- struct cfg80211_connect_params *sme);
-static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_ch_to_chanspec(int ch,
- struct brcmf_join_params *join_params, size_t *join_params_size);
-
-/*
-** information element utilities
-*/
-static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
- u8 t, u8 l, u8 *v);
-static s32 brcmf_mode_to_nl80211_iftype(s32 mode);
-static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
- struct device *dev);
-static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
- struct brcmf_bss_info *bi);
-static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, const u8 *mac_addr,
- struct key_params *params);
-
-/*
-** key indianess swap utilities
-*/
-static void swap_key_from_BE(struct brcmf_wsec_key *key);
-static void swap_key_to_BE(struct brcmf_wsec_key *key);
-
-/*
-** brcmf_cfg80211_priv memory init/deinit utilities
-*/
-static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv);
-
-static void brcmf_delay(u32 ms);
-
-/*
-** store/restore cfg80211 instance data
-*/
-static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data);
-static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev);
-
-/*
-** ibss mode utilities
-*/
-static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv);
+#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
+ (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
-/*
-** dongle up/down , default configuration utilities
-*/
-static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
- const struct brcmf_event_msg *e);
-static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
- const struct brcmf_event_msg *e);
-static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
- const struct brcmf_event_msg *e);
-static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype);
-static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf);
+static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
-/*
-** dongle configuration utilities
-*/
-static s32 brcmf_dongle_eventmsg(struct net_device *ndev);
-static s32 brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
- s32 scan_unassoc_time, s32 scan_passive_time);
-static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv,
- bool need_lock);
-static s32 brcmf_dongle_roam(struct net_device *ndev, u32 roamvar,
- u32 bcn_timeout);
+static u32 brcmf_dbg_level = WL_DBG_ERR;
-/*
-** iscan handler
-*/
-static void brcmf_iscan_timer(unsigned long data);
-static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_iscan_thread(void *data);
-static s32 brcmf_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
- void *param, s32 paramlen, void *bufptr,
- s32 buflen);
-static s32 brcmf_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
- void *param, s32 paramlen, void *bufptr,
- s32 buflen);
-static s32 brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
- struct brcmf_ssid *ssid, u16 action);
-static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan);
-static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan,
- u32 *status,
- struct brcmf_scan_results **bss_list);
-static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
- bool aborted);
-static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el);
-static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv);
-static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data)
+{
+ dev->driver_data = data;
+}
-/*
-* find most significant bit set
-*/
-static __used u32 brcmf_find_msb(u16 bit16);
+static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev)
+{
+ void *data = NULL;
-/*
-* update pmklist to dongle
-*/
-static __used s32 brcmf_update_pmklist(struct net_device *dev,
- struct brcmf_cfg80211_pmk_list *pmk_list,
- s32 err);
+ if (dev)
+ data = dev->driver_data;
+ return data;
+}
-static void brcmf_set_mpc(struct net_device *ndev, int mpc);
+static
+struct brcmf_cfg80211_priv *brcmf_priv_get(struct brcmf_cfg80211_dev *cfg_dev)
+{
+ struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg_dev);
+ return ci->cfg_priv;
+}
-/*
-* debufs support
-*/
-static int
-brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv);
-static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv);
-
-#define WL_PRIV_GET() \
- ({ \
- struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg80211_dev); \
- if (unlikely(!ci)) { \
- WL_ERR("wl_cfg80211_dev is unavailable\n"); \
- BUG(); \
- } \
- ci->cfg_priv; \
-})
-
-#define CHECK_SYS_UP() \
-do { \
- struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); \
- if (unlikely(!test_bit(WL_STATUS_READY, &cfg_priv->status))) { \
- WL_INFO("device is not ready : status (%d)\n", \
- (int)cfg_priv->status); \
- return -EIO; \
- } \
-} while (0)
+static bool check_sys_up(struct wiphy *wiphy)
+{
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+ if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
+ WL_INFO("device is not ready : status (%d)\n",
+ (int)cfg_priv->status);
+ return false;
+ }
+ return true;
+}
#define CHAN2G(_channel, _freq, _flags) { \
.band = IEEE80211_BAND_2GHZ, \
@@ -510,48 +247,134 @@ static const u32 __wl_cipher_suites[] = {
WLAN_CIPHER_SUITE_AES_CMAC,
};
-static void swap_key_from_BE(struct brcmf_wsec_key *key)
+/* tag_ID/length/value_buffer tuple */
+struct brcmf_tlv {
+ u8 id;
+ u8 len;
+ u8 data[1];
+};
+
+/* Quarter dBm units to mW
+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
+ * Table is offset so the last entry is largest mW value that fits in
+ * a u16.
+ */
+
+#define QDBM_OFFSET 153 /* Offset for first entry */
+#define QDBM_TABLE_LEN 40 /* Table size */
+
+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
+ */
+#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
+
+/* Largest mW value that will round down to the last table entry,
+ * QDBM_OFFSET + QDBM_TABLE_LEN-1.
+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
+ * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
+ */
+#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
+
+static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
+/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
+/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
+/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
+/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
+/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
+/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
+};
+
+static u16 brcmf_qdbm_to_mw(u8 qdbm)
{
- key->index = cpu_to_le32(key->index);
- key->len = cpu_to_le32(key->len);
- key->algo = cpu_to_le32(key->algo);
- key->flags = cpu_to_le32(key->flags);
- key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
- key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
- key->iv_initialized = cpu_to_le32(key->iv_initialized);
+ uint factor = 1;
+ int idx = qdbm - QDBM_OFFSET;
+
+ if (idx >= QDBM_TABLE_LEN)
+ /* clamp to max u16 mW value */
+ return 0xFFFF;
+
+ /* scale the qdBm index up to the range of the table 0-40
+ * where an offset of 40 qdBm equals a factor of 10 mW.
+ */
+ while (idx < 0) {
+ idx += 40;
+ factor *= 10;
+ }
+
+ /* return the mW value scaled down to the correct factor of 10,
+ * adding in factor/2 to get proper rounding.
+ */
+ return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
}
-static void swap_key_to_BE(struct brcmf_wsec_key *key)
+static u8 brcmf_mw_to_qdbm(u16 mw)
{
- key->index = le32_to_cpu(key->index);
- key->len = le32_to_cpu(key->len);
- key->algo = le32_to_cpu(key->algo);
- key->flags = le32_to_cpu(key->flags);
- key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
- key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
- key->iv_initialized = le32_to_cpu(key->iv_initialized);
+ u8 qdbm;
+ int offset;
+ uint mw_uint = mw;
+ uint boundary;
+
+ /* handle boundary case */
+ if (mw_uint <= 1)
+ return 0;
+
+ offset = QDBM_OFFSET;
+
+ /* move mw into the range of the table */
+ while (mw_uint < QDBM_TABLE_LOW_BOUND) {
+ mw_uint *= 10;
+ offset -= 40;
+ }
+
+ for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
+ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
+ nqdBm_to_mW_map[qdbm]) / 2;
+ if (mw_uint < boundary)
+ break;
+ }
+
+ qdbm += (u8) offset;
+
+ return qdbm;
}
-static s32
-brcmf_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
+/* 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)
{
- struct ifreq ifr;
- struct brcmf_ioctl ioc;
- mm_segment_t fs;
- s32 err = 0;
+ int err;
+ __le32 par_le = cpu_to_le32(*par);
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = cmd;
- ioc.buf = arg;
- ioc.len = len;
- strcpy(ifr.ifr_name, dev->name);
- ifr.ifr_data = (caddr_t)&ioc;
+ err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32));
+ *par = le32_to_cpu(par_le);
- fs = get_fs();
- set_fs(get_ds());
- err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
- set_fs(fs);
+ return err;
+}
+
+static void convert_key_from_CPU(struct brcmf_wsec_key *key,
+ struct brcmf_wsec_key_le *key_le)
+{
+ key_le->index = cpu_to_le32(key->index);
+ key_le->len = cpu_to_le32(key->len);
+ key_le->algo = cpu_to_le32(key->algo);
+ key_le->flags = cpu_to_le32(key->flags);
+ key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
+ key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
+ key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
+ memcpy(key_le->data, key->data, sizeof(key->data));
+ memcpy(key_le->ea, key->ea, sizeof(key->ea));
+}
+
+static int 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_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, sizeof(key_le));
+ if (err)
+ WL_ERR("WLC_SET_KEY error (%d)\n", err);
return err;
}
@@ -566,7 +389,8 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
switch (type) {
case NL80211_IFTYPE_MONITOR:
@@ -587,9 +411,8 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
goto done;
}
- infra = cpu_to_le32(infra);
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_INFRA, &infra, sizeof(infra));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
+ if (err) {
WL_ERR("WLC_SET_INFRA error (%d)\n", err);
err = -EAGAIN;
} else {
@@ -606,83 +429,134 @@ done:
return err;
}
-static void wl_iscan_prep(struct brcmf_scan_params *params,
+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 void brcmf_set_mpc(struct net_device *ndev, int mpc)
+{
+ s32 err = 0;
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
+
+ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
+ err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
+ if (err) {
+ WL_ERR("fail to set mpc\n");
+ return;
+ }
+ WL_INFO("MPC : %d\n", mpc);
+ }
+}
+
+static void wl_iscan_prep(struct brcmf_scan_params_le *params_le,
struct brcmf_ssid *ssid)
{
- memcpy(params->bssid, ether_bcast, ETH_ALEN);
- params->bss_type = DOT11_BSSTYPE_ANY;
- params->scan_type = 0;
- params->nprobes = -1;
- params->active_time = -1;
- params->passive_time = -1;
- params->home_time = -1;
- params->channel_num = 0;
-
- params->nprobes = cpu_to_le32(params->nprobes);
- params->active_time = cpu_to_le32(params->active_time);
- params->passive_time = cpu_to_le32(params->passive_time);
- params->home_time = cpu_to_le32(params->home_time);
+ 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)
- memcpy(&params->ssid, ssid, sizeof(struct brcmf_ssid));
-
+ memcpy(&params_le->ssid_le, ssid, sizeof(struct brcmf_ssid));
}
static s32
-brcmf_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
+brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param,
s32 paramlen, void *bufptr, s32 buflen)
{
s32 iolen;
- iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
+ iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
BUG_ON(!iolen);
- return brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, bufptr, iolen);
+ return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen);
}
static s32
-brcmf_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
+brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param,
s32 paramlen, void *bufptr, s32 buflen)
{
s32 iolen;
- iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
+ iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
BUG_ON(!iolen);
- return brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, bufptr, buflen);
+ 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, params));
- struct brcmf_iscan_params *params;
+ 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 (unlikely(!params))
+ if (!params)
return -ENOMEM;
- BUG_ON(params_size >= BRCMF_C_IOCTL_SMLEN);
+ BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
- wl_iscan_prep(&params->params, ssid);
+ wl_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);
- /* params_size += offsetof(struct brcmf_iscan_params, params); */
- err = brcmf_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
- iscan->ioctl_buf, BRCMF_C_IOCTL_SMLEN);
- if (unlikely(err)) {
- if (err == -EBUSY) {
+ 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 {
+ else
WL_ERR("error (%d)\n", err);
- }
}
+
kfree(params);
return err;
}
@@ -692,7 +566,7 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
struct net_device *ndev = cfg_to_ndev(cfg_priv);
struct brcmf_ssid ssid;
- s32 passive_scan;
+ __le32 passive_scan;
s32 err = 0;
/* Broadcast scan by default */
@@ -700,19 +574,23 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
iscan->state = WL_ISCAN_STATE_SCANING;
- passive_scan = cfg_priv->active_scan ? 0 : 1;
- err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
+ passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
+ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
&passive_scan, sizeof(passive_scan));
- if (unlikely(err)) {
+ if (err) {
WL_ERR("error (%d)\n", err);
return err;
}
brcmf_set_mpc(ndev, 0);
cfg_priv->iscan_kickstart = true;
- brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
+ err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
+ if (err) {
+ brcmf_set_mpc(ndev, 1);
+ cfg_priv->iscan_kickstart = false;
+ return err;
+ }
mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
iscan->timer_on = 1;
-
return err;
}
@@ -724,16 +602,17 @@ __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct cfg80211_ssid *ssids;
struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
- s32 passive_scan;
+ __le32 passive_scan;
bool iscan_req;
bool spec_scan;
s32 err = 0;
+ u32 SSID_len;
- if (unlikely(test_bit(WL_STATUS_SCANNING, &cfg_priv->status))) {
+ if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
return -EAGAIN;
}
- if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status))) {
+ if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) {
WL_ERR("Scanning being aborted : status (%lu)\n",
cfg_priv->status);
return -EAGAIN;
@@ -761,41 +640,41 @@ __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
if (iscan_req) {
err = brcmf_do_iscan(cfg_priv);
- if (likely(!err))
+ 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, 0, sizeof(sr->ssid));
- sr->ssid.SSID_len =
- min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
- if (sr->ssid.SSID_len) {
- memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
- sr->ssid.SSID_len = cpu_to_le32(sr->ssid.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_priv->active_scan ? 0 : 1;
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_PASSIVE_SCAN,
+ passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
&passive_scan, sizeof(passive_scan));
- if (unlikely(err)) {
+ if (err) {
WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
goto scan_out;
}
brcmf_set_mpc(ndev, 0);
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SCAN, &sr->ssid,
- sizeof(sr->ssid));
+ 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.SSID);
- } else {
+ 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;
}
@@ -817,88 +696,46 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL);
- if (unlikely(err))
+ if (err)
WL_ERR("scan error (%d)\n", err);
WL_TRACE("Exit\n");
return err;
}
-static s32 brcmf_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
+static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
{
- s8 buf[BRCMF_C_IOCTL_SMLEN];
- u32 len;
s32 err = 0;
- val = cpu_to_le32(val);
- len = brcmu_mkiovar(name, (char *)(&val), sizeof(val), buf,
- sizeof(buf));
- BUG_ON(!len);
-
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, buf, len);
- if (unlikely(err))
- WL_ERR("error (%d)\n", err);
-
- return err;
-}
-
-static s32
-brcmf_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
-{
- union {
- s8 buf[BRCMF_C_IOCTL_SMLEN];
- s32 val;
- } var;
- u32 len;
- u32 data_null;
- s32 err = 0;
-
- len =
- brcmu_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
- sizeof(var.buf));
- BUG_ON(!len);
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, &var, len);
- if (unlikely(err))
- WL_ERR("error (%d)\n", err);
-
- *retval = le32_to_cpu(var.val);
-
- return err;
-}
-
-static s32 brcmf_set_rts(struct net_device *dev, u32 rts_threshold)
-{
- s32 err = 0;
-
- err = brcmf_dev_intvar_set(dev, "rtsthresh", rts_threshold);
- if (unlikely(err))
+ err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold);
+ if (err)
WL_ERR("Error (%d)\n", err);
return err;
}
-static s32 brcmf_set_frag(struct net_device *dev, u32 frag_threshold)
+static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
{
s32 err = 0;
- err = brcmf_dev_intvar_set(dev, "fragthresh", frag_threshold);
- if (unlikely(err))
+ err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold);
+ if (err)
WL_ERR("Error (%d)\n", err);
return err;
}
-static s32 brcmf_set_retry(struct net_device *dev, u32 retry, bool l)
+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);
- retry = cpu_to_le32(retry);
- err = brcmf_dev_ioctl(dev, cmd, &retry, sizeof(retry));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, cmd, &retry);
+ if (err) {
WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
return err;
}
@@ -912,7 +749,8 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
(cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) {
@@ -948,8 +786,113 @@ done:
return err;
}
+static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
+{
+ switch (item) {
+ case WL_PROF_SEC:
+ return &cfg_priv->profile->sec;
+ case WL_PROF_BSSID:
+ return &cfg_priv->profile->bssid;
+ case WL_PROF_SSID:
+ return &cfg_priv->profile->ssid;
+ }
+ WL_ERR("invalid item (%d)\n", item);
+ return NULL;
+}
+
+static s32
+brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
+ const struct brcmf_event_msg *e, void *data, s32 item)
+{
+ s32 err = 0;
+ struct brcmf_ssid *ssid;
+
+ switch (item) {
+ case WL_PROF_SSID:
+ ssid = (struct brcmf_ssid *) data;
+ memset(cfg_priv->profile->ssid.SSID, 0,
+ sizeof(cfg_priv->profile->ssid.SSID));
+ memcpy(cfg_priv->profile->ssid.SSID,
+ ssid->SSID, ssid->SSID_len);
+ cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
+ break;
+ case WL_PROF_BSSID:
+ if (data)
+ memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
+ else
+ memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
+ break;
+ case WL_PROF_SEC:
+ memcpy(&cfg_priv->profile->sec, data,
+ sizeof(cfg_priv->profile->sec));
+ break;
+ case WL_PROF_BEACONINT:
+ cfg_priv->profile->beacon_interval = *(u16 *)data;
+ break;
+ case WL_PROF_DTIMPERIOD:
+ cfg_priv->profile->dtim_period = *(u8 *)data;
+ break;
+ default:
+ WL_ERR("unsupported item (%d)\n", item);
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
+{
+ memset(prof, 0, sizeof(*prof));
+}
+
+static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
+ size_t *join_params_size)
+{
+ u16 chanspec = 0;
+
+ if (ch != 0) {
+ if (ch <= CH_MAX_2G_CHANNEL)
+ chanspec |= WL_CHANSPEC_BAND_2G;
+ else
+ chanspec |= WL_CHANSPEC_BAND_5G;
+
+ chanspec |= WL_CHANSPEC_BW_20;
+ chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+
+ *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
+ sizeof(u16);
+
+ chanspec |= (ch & WL_CHANSPEC_CHAN_MASK);
+ 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);
+ }
+}
+
+static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct net_device *ndev = NULL;
+ s32 err = 0;
+
+ WL_TRACE("Enter\n");
+
+ if (cfg_priv->link_up) {
+ ndev = cfg_to_ndev(cfg_priv);
+ WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0);
+ if (err)
+ WL_ERR("WLC_DISASSOC failed (%d)\n", err);
+ cfg_priv->link_up = false;
+ }
+ WL_TRACE("Exit\n");
+}
+
static s32
-brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_ibss_params *params)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
@@ -958,9 +901,11 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
s32 err = 0;
s32 wsec = 0;
s32 bcnprd;
+ struct brcmf_ssid ssid;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
if (params->ssid)
WL_CONN("SSID: %s\n", params->ssid);
@@ -1012,20 +957,20 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
if (params->privacy)
wsec |= WEP_ENABLED;
- err = brcmf_dev_intvar_set(dev, "wsec", wsec);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
+ if (err) {
WL_ERR("wsec failed (%d)\n", err);
goto done;
}
/* Configure Beacon Interval for starter */
if (params->beacon_interval)
- bcnprd = cpu_to_le32(params->beacon_interval);
+ bcnprd = params->beacon_interval;
else
- bcnprd = cpu_to_le32(100);
+ bcnprd = 100;
- err = brcmf_dev_ioctl(dev, BRCM_SET_BCNPRD, &bcnprd, sizeof(bcnprd));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd);
+ if (err) {
WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
goto done;
}
@@ -1034,23 +979,24 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
memset(&join_params, 0, sizeof(struct brcmf_join_params));
/* SSID */
- join_params.ssid.SSID_len =
- (params->ssid_len > 32) ? 32 : params->ssid_len;
- memcpy(join_params.ssid.SSID, params->ssid, join_params.ssid.SSID_len);
- join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
- join_params_size = sizeof(join_params.ssid);
- brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID);
+ ssid.SSID_len = min_t(u32, params->ssid_len, 32);
+ memcpy(ssid.SSID, params->ssid, ssid.SSID_len);
+ memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len);
+ join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
+ join_params_size = sizeof(join_params.ssid_le);
+ brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
/* BSSID */
if (params->bssid) {
- memcpy(join_params.params.bssid, params->bssid, ETH_ALEN);
- join_params_size = sizeof(join_params.ssid) +
- BRCMF_ASSOC_PARAMS_FIXED_SIZE;
+ memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
+ join_params_size = sizeof(join_params.ssid_le) +
+ BRCMF_ASSOC_PARAMS_FIXED_SIZE;
} else {
- memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
+ memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
}
+
brcmf_update_prof(cfg_priv, NULL,
- &join_params.params.bssid, WL_PROF_BSSID);
+ &join_params.params_le.bssid, WL_PROF_BSSID);
/* Channel */
if (params->channel) {
@@ -1066,10 +1012,10 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
}
/* set channel for starter */
- target_channel = cpu_to_le32(cfg_priv->channel);
- err = brcmf_dev_ioctl(dev, BRCM_SET_CHANNEL,
- &target_channel, sizeof(target_channel));
- if (unlikely(err)) {
+ target_channel = cfg_priv->channel;
+ err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL,
+ &target_channel);
+ if (err) {
WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
goto done;
}
@@ -1079,9 +1025,9 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
cfg_priv->ibss_starter = false;
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_SSID,
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
&join_params, join_params_size);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("WLC_SET_SSID failed (%d)\n", err);
goto done;
}
@@ -1093,13 +1039,15 @@ done:
return err;
}
-static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+static s32
+brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
brcmf_link_down(cfg_priv);
@@ -1108,10 +1056,10 @@ static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev
return err;
}
-static s32
-brcmf_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
+static s32 brcmf_set_wpa_version(struct net_device *ndev,
+ struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
@@ -1123,8 +1071,8 @@ brcmf_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sm
else
val = WPA_AUTH_DISABLED;
WL_CONN("setting wpa_auth to 0x%0x\n", val);
- err = brcmf_dev_intvar_set(dev, "wpa_auth", val);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
+ if (err) {
WL_ERR("set wpa_auth failed (%d)\n", err);
return err;
}
@@ -1133,10 +1081,10 @@ brcmf_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sm
return err;
}
-static s32
-brcmf_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
+static s32 brcmf_set_auth_type(struct net_device *ndev,
+ struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
@@ -1162,8 +1110,8 @@ brcmf_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
break;
}
- err = brcmf_dev_intvar_set(dev, "auth", val);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "auth", val);
+ if (err) {
WL_ERR("set auth failed (%d)\n", err);
return err;
}
@@ -1173,9 +1121,10 @@ brcmf_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
}
static s32
-brcmf_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_set_cipher(struct net_device *ndev,
+ struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct brcmf_cfg80211_security *sec;
s32 pval = 0;
s32 gval = 0;
@@ -1225,8 +1174,8 @@ brcmf_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme
}
WL_CONN("pval (%d) gval (%d)\n", pval, gval);
- err = brcmf_dev_intvar_set(dev, "wsec", pval | gval);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval);
+ if (err) {
WL_ERR("error (%d)\n", err);
return err;
}
@@ -1239,16 +1188,16 @@ brcmf_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme
}
static s32
-brcmf_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
if (sme->crypto.n_akm_suites) {
- err = brcmf_dev_intvar_get(dev, "wpa_auth", &val);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val);
+ if (err) {
WL_ERR("could not get wpa_auth (%d)\n", err);
return err;
}
@@ -1281,8 +1230,8 @@ brcmf_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
}
WL_CONN("setting wpa_auth to %d\n", val);
- err = brcmf_dev_intvar_set(dev, "wpa_auth", val);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
+ if (err) {
WL_ERR("could not set wpa_auth (%d)\n", err);
return err;
}
@@ -1294,86 +1243,88 @@ brcmf_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
}
static s32
-brcmf_set_set_sharedkey(struct net_device *dev,
+brcmf_set_wep_sharedkey(struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
struct brcmf_cfg80211_security *sec;
struct brcmf_wsec_key key;
s32 val;
s32 err = 0;
WL_CONN("key len (%d)\n", sme->key_len);
- if (sme->key_len) {
- sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
- WL_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))
-&& (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
- WLAN_CIPHER_SUITE_WEP104))) {
- memset(&key, 0, sizeof(key));
- key.len = (u32) sme->key_len;
- key.index = (u32) sme->key_idx;
- if (unlikely(key.len > sizeof(key.data))) {
- WL_ERR("Too long key length (%u)\n", key.len);
- return -EINVAL;
- }
- memcpy(key.data, sme->key, key.len);
- key.flags = BRCMF_PRIMARY_KEY;
- switch (sec->cipher_pairwise) {
- case WLAN_CIPHER_SUITE_WEP40:
- key.algo = CRYPTO_ALGO_WEP1;
- break;
- case WLAN_CIPHER_SUITE_WEP104:
- key.algo = CRYPTO_ALGO_WEP128;
- break;
- default:
- WL_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);
- swap_key_from_BE(&key);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key,
- sizeof(key));
- if (unlikely(err)) {
- WL_ERR("WLC_SET_KEY error (%d)\n", err);
+
+ if (sme->key_len == 0)
+ return 0;
+
+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
+ WL_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;
+
+ if (sec->cipher_pairwise &
+ (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)) {
+ memset(&key, 0, sizeof(key));
+ 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);
+ return -EINVAL;
+ }
+ memcpy(key.data, sme->key, key.len);
+ key.flags = BRCMF_PRIMARY_KEY;
+ switch (sec->cipher_pairwise) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ key.algo = CRYPTO_ALGO_WEP1;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+ default:
+ WL_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);
+ err = send_key_to_dongle(ndev, &key);
+ if (err)
+ return err;
+
+ if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
+ WL_CONN("set auth_type to shared key\n");
+ val = 1; /* shared key */
+ err = brcmf_dev_intvar_set(ndev, "auth", val);
+ if (err) {
+ WL_ERR("set auth failed (%d)\n", err);
return err;
}
- if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
- WL_CONN("set auth_type to shared key\n");
- val = 1; /* shared key */
- err = brcmf_dev_intvar_set(dev, "auth", val);
- if (unlikely(err)) {
- WL_ERR("set auth failed (%d)\n", err);
- return err;
- }
- }
}
}
return err;
}
static s32
-brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_connect_params *sme)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
struct ieee80211_channel *chan = sme->channel;
struct brcmf_join_params join_params;
size_t join_params_size;
+ struct brcmf_ssid ssid;
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
- if (unlikely(!sme->ssid)) {
+ if (!sme->ssid) {
WL_ERR("Invalid ssid\n");
return -EOPNOTSUPP;
}
@@ -1390,62 +1341,54 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
- err = brcmf_set_wpa_version(dev, sme);
+ err = brcmf_set_wpa_version(ndev, sme);
if (err) {
WL_ERR("wl_set_wpa_version failed (%d)\n", err);
goto done;
}
- err = brcmf_set_auth_type(dev, sme);
+ err = brcmf_set_auth_type(ndev, sme);
if (err) {
WL_ERR("wl_set_auth_type failed (%d)\n", err);
goto done;
}
- err = brcmf_set_set_cipher(dev, sme);
+ err = brcmf_set_set_cipher(ndev, sme);
if (err) {
WL_ERR("wl_set_set_cipher failed (%d)\n", err);
goto done;
}
- err = brcmf_set_key_mgmt(dev, sme);
+ err = brcmf_set_key_mgmt(ndev, sme);
if (err) {
WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
goto done;
}
- err = brcmf_set_set_sharedkey(dev, sme);
+ err = brcmf_set_wep_sharedkey(ndev, sme);
if (err) {
- WL_ERR("wl_set_set_sharedkey failed (%d)\n", err);
+ WL_ERR("brcmf_set_wep_sharedkey failed (%d)\n", err);
goto done;
}
- brcmf_update_prof(cfg_priv, NULL, sme->bssid, WL_PROF_BSSID);
- /*
- ** Join with specific BSSID and cached SSID
- ** If SSID is zero join based on BSSID only
- */
memset(&join_params, 0, sizeof(join_params));
- join_params_size = sizeof(join_params.ssid);
+ join_params_size = sizeof(join_params.ssid_le);
- join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
- memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
- join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
- brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID);
+ ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), sme->ssid_len);
+ memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len);
+ memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len);
+ join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
+ brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
- if (sme->bssid)
- memcpy(join_params.params.bssid, sme->bssid, ETH_ALEN);
- else
- memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
+ memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
- if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
+ if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN)
WL_CONN("ssid \"%s\", len (%d)\n",
- join_params.ssid.SSID, join_params.ssid.SSID_len);
- }
+ ssid.SSID, ssid.SSID_len);
brcmf_ch_to_chanspec(cfg_priv->channel,
&join_params, &join_params_size);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_SSID,
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
&join_params, join_params_size);
if (err)
WL_ERR("WLC_SET_SSID failed (%d)\n", err);
@@ -1458,24 +1401,24 @@ done:
}
static s32
-brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
u16 reason_code)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
- struct brcmf_scb_val scbval;
+ struct brcmf_scb_val_le scbval;
s32 err = 0;
WL_TRACE("Enter. Reason code = %d\n", reason_code);
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
- scbval.val = reason_code;
memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN);
- scbval.val = cpu_to_le32(scbval.val);
- err = brcmf_dev_ioctl(dev, BRCMF_C_DISASSOC, &scbval,
- sizeof(struct brcmf_scb_val));
- if (unlikely(err))
+ scbval.val = cpu_to_le32(reason_code);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval,
+ sizeof(struct brcmf_scb_val_le));
+ if (err)
WL_ERR("error (%d)\n", err);
cfg_priv->link_up = false;
@@ -1496,7 +1439,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
s32 disable = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
switch (type) {
case NL80211_TX_POWER_AUTOMATIC:
@@ -1518,9 +1462,8 @@ 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;
- disable = cpu_to_le32(disable);
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_RADIO, &disable, sizeof(disable));
- if (unlikely(err))
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable);
+ if (err)
WL_ERR("WLC_SET_RADIO error (%d)\n", err);
if (dbm > 0xffff)
@@ -1528,8 +1471,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
else
txpwrmw = (u16) dbm;
err = brcmf_dev_intvar_set(ndev, "qtxpower",
- (s32) (brcmu_mw_to_qdbm(txpwrmw)));
- if (unlikely(err))
+ (s32) (brcmf_mw_to_qdbm(txpwrmw)));
+ if (err)
WL_ERR("qtxpower error (%d)\n", err);
cfg_priv->conf->tx_power = dbm;
@@ -1547,16 +1490,17 @@ static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("error (%d)\n", err);
goto done;
}
result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
- *dbm = (s32) brcmu_qdbm_to_mw(result);
+ *dbm = (s32) brcmf_qdbm_to_mw(result);
done:
WL_TRACE("Exit\n");
@@ -1564,31 +1508,30 @@ done:
}
static s32
-brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool unicast, bool multicast)
{
u32 index;
- s32 wsec;
+ u32 wsec;
s32 err = 0;
WL_TRACE("Enter\n");
WL_CONN("key index (%d)\n", key_idx);
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_WSEC, &wsec, sizeof(wsec));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec);
+ if (err) {
WL_ERR("WLC_GET_WSEC error (%d)\n", err);
goto done;
}
- wsec = le32_to_cpu(wsec);
if (wsec & WEP_ENABLED) {
/* Just select a new current key */
- index = (u32) key_idx;
- index = cpu_to_le32(index);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY_PRIMARY, &index,
- sizeof(index));
- if (unlikely(err))
+ index = key_idx;
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY,
+ &index);
+ if (err)
WL_ERR("error (%d)\n", err);
}
done:
@@ -1597,10 +1540,11 @@ done:
}
static s32
-brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
+brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, const u8 *mac_addr, struct key_params *params)
{
struct brcmf_wsec_key key;
+ struct brcmf_wsec_key_le key_le;
s32 err = 0;
memset(&key, 0, sizeof(key));
@@ -1613,12 +1557,9 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
/* check for key index change */
if (key.len == 0) {
/* key delete */
- swap_key_from_BE(&key);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
- if (unlikely(err)) {
- WL_ERR("key delete error (%d)\n", err);
+ err = send_key_to_dongle(ndev, &key);
+ if (err)
return err;
- }
} else {
if (key.len > sizeof(key.data)) {
WL_ERR("Invalid key length (%d)\n", key.len);
@@ -1671,11 +1612,12 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
return -EINVAL;
}
- swap_key_from_BE(&key);
+ convert_key_from_CPU(&key, &key_le);
- brcmf_netdev_wait_pend8021x(dev);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
- if (unlikely(err)) {
+ brcmf_netdev_wait_pend8021x(ndev);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le,
+ sizeof(key_le));
+ if (err) {
WL_ERR("WLC_SET_KEY error (%d)\n", err);
return err;
}
@@ -1684,7 +1626,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
}
static s32
-brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params)
{
@@ -1696,18 +1638,19 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
WL_TRACE("Enter\n");
WL_CONN("key index (%d)\n", key_idx);
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
if (mac_addr) {
WL_TRACE("Exit");
- return brcmf_add_keyext(wiphy, dev, key_idx, mac_addr, params);
+ return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
}
memset(&key, 0, sizeof(key));
key.len = (u32) params->key_len;
key.index = (u32) key_idx;
- if (unlikely(key.len > sizeof(key.data))) {
+ if (key.len > sizeof(key.data)) {
WL_ERR("Too long key length (%u)\n", key.len);
err = -EINVAL;
goto done;
@@ -1745,32 +1688,27 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
goto done;
}
- /* Set the new key/index */
- swap_key_from_BE(&key);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
- if (unlikely(err)) {
- WL_ERR("WLC_SET_KEY error (%d)\n", err);
+ err = send_key_to_dongle(ndev, &key); /* Set the new key/index */
+ if (err)
goto done;
- }
val = WEP_ENABLED;
- err = brcmf_dev_intvar_get(dev, "wsec", &wsec);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_get(ndev, "wsec", &wsec);
+ if (err) {
WL_ERR("get wsec error (%d)\n", err);
goto done;
}
wsec &= ~(WEP_ENABLED);
wsec |= val;
- err = brcmf_dev_intvar_set(dev, "wsec", wsec);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
+ if (err) {
WL_ERR("set wsec error (%d)\n", err);
goto done;
}
val = 1; /* assume shared key. otherwise 0 */
- val = cpu_to_le32(val);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_AUTH, &val, sizeof(val));
- if (unlikely(err))
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val);
+ if (err)
WL_ERR("WLC_SET_AUTH error (%d)\n", err);
done:
WL_TRACE("Exit\n");
@@ -1778,7 +1716,7 @@ done:
}
static s32
-brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool pairwise, const u8 *mac_addr)
{
struct brcmf_wsec_key key;
@@ -1787,7 +1725,9 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
s32 wsec;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
+
memset(&key, 0, sizeof(key));
key.index = (u32) key_idx;
@@ -1795,25 +1735,23 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
key.algo = CRYPTO_ALGO_OFF;
WL_CONN("key index (%d)\n", key_idx);
+
/* Set the new key/index */
- swap_key_from_BE(&key);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
- if (unlikely(err)) {
+ err = send_key_to_dongle(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);
- } else
- WL_ERR("WLC_SET_KEY error (%d)\n", err);
-
+ }
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
goto done;
}
val = 0;
- err = brcmf_dev_intvar_get(dev, "wsec", &wsec);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_get(ndev, "wsec", &wsec);
+ if (err) {
WL_ERR("get wsec error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
@@ -1821,8 +1759,8 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
}
wsec &= ~(WEP_ENABLED);
wsec |= val;
- err = brcmf_dev_intvar_set(dev, "wsec", wsec);
- if (unlikely(err)) {
+ err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
+ if (err) {
WL_ERR("set wsec error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
@@ -1830,9 +1768,8 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
}
val = 0; /* assume open key. otherwise 1 */
- val = cpu_to_le32(val);
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_AUTH, &val, sizeof(val));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val);
+ if (err) {
WL_ERR("WLC_SET_AUTH error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
@@ -1843,12 +1780,11 @@ done:
}
static s32
-brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
void (*callback) (void *cookie, struct key_params * params))
{
struct key_params params;
- struct brcmf_wsec_key key;
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
struct brcmf_cfg80211_security *sec;
s32 wsec;
@@ -1856,23 +1792,18 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
WL_TRACE("Enter\n");
WL_CONN("key index (%d)\n", key_idx);
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
- memset(&key, 0, sizeof(key));
- key.index = key_idx;
- swap_key_to_BE(&key);
memset(&params, 0, sizeof(params));
- params.key_len = (u8) min_t(u8, WLAN_MAX_KEY_LEN, key.len);
- memcpy(params.key, key.data, params.key_len);
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_WSEC, &wsec, sizeof(wsec));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec);
+ if (err) {
WL_ERR("WLC_GET_WSEC error (%d)\n", err);
/* Ignore this error, may happen during DISASSOC */
err = -EAGAIN;
goto done;
}
- wsec = le32_to_cpu(wsec);
switch (wsec) {
case WEP_ENABLED:
sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
@@ -1906,30 +1837,29 @@ done:
static s32
brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
- struct net_device *dev, u8 key_idx)
+ struct net_device *ndev, u8 key_idx)
{
WL_INFO("Not supported\n");
- CHECK_SYS_UP();
return -EOPNOTSUPP;
}
static s32
-brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
u8 *mac, struct station_info *sinfo)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
- struct brcmf_scb_val scb_val;
+ struct brcmf_scb_val_le scb_val;
int rssi;
s32 rate;
s32 err = 0;
u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID);
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
- if (unlikely
- (memcmp(mac, bssid, ETH_ALEN))) {
+ if (memcmp(mac, bssid, ETH_ALEN)) {
WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X"
"wl_bssid-%X:%X:%X:%X:%X:%X\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
@@ -1940,23 +1870,22 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
}
/* Report the current tx rate */
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RATE, &rate, sizeof(rate));
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate);
if (err) {
WL_ERR("Could not get rate (%d)\n", err);
} else {
- rate = le32_to_cpu(rate);
sinfo->filled |= STATION_INFO_TX_BITRATE;
sinfo->txrate.legacy = rate * 5;
WL_CONN("Rate %d Mbps\n", rate / 2);
}
if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
- scb_val.val = 0;
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RSSI, &scb_val,
- sizeof(struct brcmf_scb_val));
- if (unlikely(err)) {
+ scb_val.val = cpu_to_le32(0);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
+ sizeof(struct brcmf_scb_val_le));
+ if (err)
WL_ERR("Could not get rssi (%d)\n", err);
- }
+
rssi = le32_to_cpu(scb_val.val);
sinfo->filled |= STATION_INFO_SIGNAL;
sinfo->signal = rssi;
@@ -1969,63 +1898,51 @@ done:
}
static s32
-brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
bool enabled, s32 timeout)
{
s32 pm;
s32 err = 0;
+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+
+ /*
+ * Powersave enable/disable request is coming from the
+ * cfg80211 even before the interface is up. In that
+ * scenario, driver will be storing the power save
+ * preference in cfg_priv struct to apply this to
+ * FW later while initializing the dongle
+ */
+ cfg_priv->pwr_save = enabled;
+ if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
+
+ WL_INFO("Device is not ready,"
+ "storing the value in cfg_priv struct\n");
+ goto done;
+ }
pm = enabled ? PM_FAST : PM_OFF;
- pm = cpu_to_le32(pm);
WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
- err = brcmf_dev_ioctl(dev, BRCMF_C_SET_PM, &pm, sizeof(pm));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm);
+ if (err) {
if (err == -ENODEV)
WL_ERR("net_device is not ready yet\n");
else
WL_ERR("error (%d)\n", err);
}
+done:
WL_TRACE("Exit\n");
return err;
}
-static __used u32 brcmf_find_msb(u16 bit16)
-{
- u32 ret = 0;
-
- if (bit16 & 0xff00) {
- ret += 8;
- bit16 >>= 8;
- }
-
- if (bit16 & 0xf0) {
- ret += 4;
- bit16 >>= 4;
- }
-
- if (bit16 & 0xc) {
- ret += 2;
- bit16 >>= 2;
- }
-
- if (bit16 & 2)
- ret += bit16 & 2;
- else if (bit16)
- ret += bit16;
-
- return ret;
-}
-
static s32
-brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
const u8 *addr,
const struct cfg80211_bitrate_mask *mask)
{
- struct wl_rateset rateset;
+ struct brcm_rateset_le rateset_le;
s32 rate;
s32 val;
s32 err_bg;
@@ -2034,28 +1951,28 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
/* addr param is always NULL. ignore it */
/* Get current rateset */
- err = brcmf_dev_ioctl(dev, BRCM_GET_CURR_RATESET, &rateset,
- sizeof(rateset));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le,
+ sizeof(rateset_le));
+ if (err) {
WL_ERR("could not get current rateset (%d)\n", err);
goto done;
}
- rateset.count = le32_to_cpu(rateset.count);
-
- legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
+ legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF);
if (!legacy)
- legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
+ legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy &
+ 0xFFFF);
val = wl_g_rates[legacy - 1].bitrate * 100000;
- if (val < rateset.count)
+ if (val < le32_to_cpu(rateset_le.count))
/* Select rate by rateset index */
- rate = rateset.rates[val] & 0x7f;
+ rate = rateset_le.rates[val] & 0x7f;
else
/* Specified rate in bps */
rate = val / 500000;
@@ -2067,9 +1984,9 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
* Set rate override,
* Since the is a/b/g-blind, both a/bg_rate are enforced.
*/
- err_bg = brcmf_dev_intvar_set(dev, "bg_rate", rate);
- err_a = brcmf_dev_intvar_set(dev, "a_rate", rate);
- if (unlikely(err_bg && err_a)) {
+ err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate);
+ err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate);
+ if (err_bg && err_a) {
WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
err = err_bg | err_a;
}
@@ -2079,6 +1996,483 @@ done:
return err;
}
+static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
+ struct brcmf_bss_info *bi)
+{
+ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
+ struct ieee80211_channel *notify_channel;
+ struct cfg80211_bss *bss;
+ struct ieee80211_supported_band *band;
+ s32 err = 0;
+ u16 channel;
+ u32 freq;
+ u64 notify_timestamp;
+ u16 notify_capability;
+ u16 notify_interval;
+ u8 *notify_ie;
+ size_t notify_ielen;
+ s32 notify_signal;
+
+ if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
+ WL_ERR("Bss info is larger than buffer. Discarding\n");
+ return 0;
+ }
+
+ channel = bi->ctl_ch ? bi->ctl_ch :
+ CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+ freq = ieee80211_channel_to_frequency(channel, band->band);
+ notify_channel = ieee80211_get_channel(wiphy, freq);
+
+ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
+ notify_capability = le16_to_cpu(bi->capability);
+ notify_interval = le16_to_cpu(bi->beacon_period);
+ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+ 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);
+ WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
+
+ bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
+ notify_timestamp, notify_capability, notify_interval, notify_ie,
+ notify_ielen, notify_signal, GFP_KERNEL);
+
+ if (!bss) {
+ WL_ERR("cfg80211_inform_bss_frame error\n");
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_scan_results *bss_list;
+ struct brcmf_bss_info *bi = NULL; /* must be initialized */
+ s32 err = 0;
+ int i;
+
+ bss_list = cfg_priv->bss_list;
+ if (bss_list->version != BRCMF_BSS_INFO_VERSION) {
+ WL_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++) {
+ bi = next_bss(bss_list, bi);
+ err = brcmf_inform_single_bss(cfg_priv, bi);
+ if (err)
+ break;
+ }
+ return err;
+}
+
+static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
+ struct net_device *ndev, const u8 *bssid)
+{
+ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
+ struct ieee80211_channel *notify_channel;
+ struct brcmf_bss_info *bi = NULL;
+ struct ieee80211_supported_band *band;
+ u8 *buf = NULL;
+ s32 err = 0;
+ u16 channel;
+ u32 freq;
+ u64 notify_timestamp;
+ u16 notify_capability;
+ u16 notify_interval;
+ u8 *notify_ie;
+ size_t notify_ielen;
+ s32 notify_signal;
+
+ WL_TRACE("Enter\n");
+
+ buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+ if (buf == NULL) {
+ err = -ENOMEM;
+ goto CleanUp;
+ }
+
+ *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
+
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+ if (err) {
+ WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
+ goto CleanUp;
+ }
+
+ bi = (struct brcmf_bss_info *)(buf + 4);
+
+ channel = bi->ctl_ch ? bi->ctl_ch :
+ CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+
+ if (channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+ freq = ieee80211_channel_to_frequency(channel, band->band);
+ notify_channel = ieee80211_get_channel(wiphy, freq);
+
+ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
+ notify_capability = le16_to_cpu(bi->capability);
+ notify_interval = le16_to_cpu(bi->beacon_period);
+ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+ 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);
+ WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
+
+ cfg80211_inform_bss(wiphy, notify_channel, bssid,
+ notify_timestamp, notify_capability, notify_interval,
+ notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
+
+CleanUp:
+
+ kfree(buf);
+
+ WL_TRACE("Exit\n");
+
+ return err;
+}
+
+static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ return cfg_priv->conf->mode == WL_MODE_IBSS;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
+{
+ struct brcmf_tlv *elt;
+ int totlen;
+
+ elt = (struct brcmf_tlv *) buf;
+ totlen = buflen;
+
+ /* find tagged parameter */
+ while (totlen >= 2) {
+ int len = elt->len;
+
+ /* validate remaining totlen */
+ if ((elt->id == key) && (totlen >= (len + 2)))
+ return elt;
+
+ elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2));
+ totlen -= (len + 2);
+ }
+
+ return NULL;
+}
+
+static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_bss_info *bi;
+ struct brcmf_ssid *ssid;
+ struct brcmf_tlv *tim;
+ u16 beacon_interval;
+ u8 dtim_period;
+ size_t ie_len;
+ u8 *ie;
+ s32 err = 0;
+
+ WL_TRACE("Enter\n");
+ if (brcmf_is_ibssmode(cfg_priv))
+ return err;
+
+ ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
+
+ *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
+ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
+ cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
+ if (err) {
+ WL_ERR("Could not get bss info %d\n", err);
+ goto update_bss_info_out;
+ }
+
+ bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4);
+ err = brcmf_inform_single_bss(cfg_priv, bi);
+ if (err)
+ goto update_bss_info_out;
+
+ ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
+ ie_len = le32_to_cpu(bi->ie_length);
+ beacon_interval = le16_to_cpu(bi->beacon_period);
+
+ tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
+ if (tim)
+ dtim_period = tim->data[1];
+ else {
+ /*
+ * active scan was done so we could not get dtim
+ * information out of probe response.
+ * so we speficially query dtim information to dongle.
+ */
+ u32 var;
+ err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
+ "dtim_assoc", &var);
+ if (err) {
+ WL_ERR("wl dtim_assoc failed (%d)\n", err);
+ goto update_bss_info_out;
+ }
+ dtim_period = (u8)var;
+ }
+
+ brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
+ brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
+
+update_bss_info_out:
+ WL_TRACE("Exit");
+ return err;
+}
+
+static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
+ struct brcmf_ssid ssid;
+
+ if (cfg_priv->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);
+ }
+}
+
+static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
+ bool aborted)
+{
+ struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
+ struct net_device *ndev = cfg_to_ndev(cfg_priv);
+
+ if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
+ WL_ERR("Scan complete while device not scanning\n");
+ return;
+ }
+ if (cfg_priv->scan_request) {
+ WL_SCAN("ISCAN Completed scan: %s\n",
+ aborted ? "Aborted" : "Done");
+ cfg80211_scan_done(cfg_priv->scan_request, aborted);
+ brcmf_set_mpc(ndev, 1);
+ cfg_priv->scan_request = NULL;
+ }
+ cfg_priv->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_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
+ s32 err = 0;
+
+ iscan->state = WL_ISCAN_STATE_IDLE;
+ brcmf_inform_bss(cfg_priv);
+ brcmf_notify_iscan_complete(iscan, false);
+
+ return err;
+}
+
+static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->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_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
+ s32 err = 0;
+
+ brcmf_inform_bss(cfg_priv);
+ 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_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->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_priv *cfg_priv = 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_priv->bss_list)) {
+ status = BRCMF_SCAN_RESULTS_ABORTED;
+ WL_ERR("Abort iscan\n");
+ }
+
+ el->handler[status](cfg_priv);
+}
+
+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_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
+
+ if (cfg_priv->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_priv *cfg_priv)
+{
+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
+ int err = 0;
+
+ if (cfg_priv->iscan_on) {
+ iscan->ndev = cfg_to_ndev(cfg_priv);
+ 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_priv);
+ if (!err)
+ iscan->data = cfg_priv;
+ }
+
+ return err;
+}
+
+static void brcmf_delay(u32 ms)
+{
+ if (ms < 1000 / HZ) {
+ cond_resched();
+ mdelay(ms);
+ } else {
+ msleep(ms);
+ }
+}
+
static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
@@ -2090,10 +2484,6 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
*/
WL_TRACE("Enter\n");
-#if defined(CONFIG_PM_SLEEP)
- atomic_set(&brcmf_mmc_suspend, false);
-#endif /* defined(CONFIG_PM_SLEEP) */
-
if (test_bit(WL_STATUS_READY, &cfg_priv->status))
brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
@@ -2131,9 +2521,7 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
* generated due to DISASSOC call to the fw to keep
* the state fw and WPA_Supplicant state consistent
*/
- rtnl_unlock();
brcmf_delay(500);
- rtnl_lock();
}
set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
@@ -2155,81 +2543,123 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
brcmf_set_mpc(ndev, 1);
}
-#if defined(CONFIG_PM_SLEEP)
- atomic_set(&brcmf_mmc_suspend, true);
-#endif /* defined(CONFIG_PM_SLEEP) */
-
WL_TRACE("Exit\n");
return 0;
}
static __used s32
-brcmf_update_pmklist(struct net_device *dev,
+brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
+{
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
+ u32 buflen;
+
+ buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf,
+ WL_DCMD_LEN_MAX);
+ BUG_ON(!buflen);
+
+ return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf,
+ buflen);
+}
+
+static s32
+brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
+ s32 buf_len)
+{
+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
+ u32 len;
+ s32 err = 0;
+
+ len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf,
+ WL_DCMD_LEN_MAX);
+ BUG_ON(!len);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf,
+ WL_DCMD_LEN_MAX);
+ if (err) {
+ WL_ERR("error (%d)\n", err);
+ return err;
+ }
+ memcpy(buf, cfg_priv->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)
{
int i, j;
+ int pmkid_len;
+
+ pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
- WL_CONN("No of elements %d\n", pmk_list->pmkids.npmkid);
- for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
+ WL_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);
for (j = 0; j < WLAN_PMKID_LEN; j++)
WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
}
- if (likely(!err))
- brcmf_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
+ if (!err)
+ brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
sizeof(*pmk_list));
return err;
}
static s32
-brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_pmksa *pmksa)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
- struct _pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
+ struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
s32 err = 0;
int i;
+ int pmkid_len;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
- for (i = 0; i < pmkids->npmkid; i++)
+ pmkid_len = le32_to_cpu(pmkids->npmkid);
+ for (i = 0; i < pmkid_len; i++)
if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
break;
if (i < WL_NUM_PMKIDS_MAX) {
memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
- if (i == pmkids->npmkid)
- pmkids->npmkid++;
+ if (i == pmkid_len) {
+ pmkid_len++;
+ pmkids->npmkid = cpu_to_le32(pmkid_len);
+ }
} else
err = -EINVAL;
WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
- pmkids->pmkid[pmkids->npmkid].BSSID);
+ pmkids->pmkid[pmkid_len].BSSID);
for (i = 0; i < WLAN_PMKID_LEN; i++)
- WL_CONN("%02x\n", pmkids->pmkid[pmkids->npmkid].PMKID[i]);
+ WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
- err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
+ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
WL_TRACE("Exit\n");
return err;
}
static s32
-brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_pmksa *pmksa)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
- struct _pmkid_list pmkid;
+ struct pmkid_list pmkid;
s32 err = 0;
- int i;
+ int i, pmkid_len;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
+
memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
@@ -2238,17 +2668,18 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
for (i = 0; i < WLAN_PMKID_LEN; i++)
WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
- for (i = 0; i < cfg_priv->pmk_list->pmkids.npmkid; i++)
+ pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid);
+ for (i = 0; i < pmkid_len; i++)
if (!memcmp
(pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
ETH_ALEN))
break;
- if ((cfg_priv->pmk_list->pmkids.npmkid > 0)
- && (i < cfg_priv->pmk_list->pmkids.npmkid)) {
+ if ((pmkid_len > 0)
+ && (i < pmkid_len)) {
memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
- sizeof(pmkid_t));
- for (; i < (cfg_priv->pmk_list->pmkids.npmkid - 1); i++) {
+ sizeof(struct pmkid));
+ for (; i < (pmkid_len - 1); i++) {
memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
&cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
ETH_ALEN);
@@ -2256,11 +2687,11 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
&cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
WLAN_PMKID_LEN);
}
- cfg_priv->pmk_list->pmkids.npmkid--;
+ cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
} else
err = -EINVAL;
- err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
+ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
WL_TRACE("Exit\n");
return err;
@@ -2268,16 +2699,17 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
}
static s32
-brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
+brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
{
struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
s32 err = 0;
WL_TRACE("Enter\n");
- CHECK_SYS_UP();
+ if (!check_sys_up(wiphy))
+ return -EIO;
memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
- err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
+ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
WL_TRACE("Exit\n");
return err;
@@ -2326,25 +2758,24 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
}
static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
- struct device *dev)
+ struct device *ndev)
{
struct wireless_dev *wdev;
s32 err = 0;
wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
- if (unlikely(!wdev)) {
- WL_ERR("Could not allocate wireless device\n");
+ if (!wdev)
return ERR_PTR(-ENOMEM);
- }
+
wdev->wiphy =
wiphy_new(&wl_cfg80211_ops,
sizeof(struct brcmf_cfg80211_priv) + sizeof_iface);
- if (unlikely(!wdev->wiphy)) {
+ if (!wdev->wiphy) {
WL_ERR("Couldn not allocate wiphy device\n");
err = -ENOMEM;
goto wiphy_new_out;
}
- set_wiphy_dev(wdev->wiphy, dev);
+ 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 =
@@ -2360,16 +2791,12 @@ static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
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);
-#ifndef WL_POWERSAVE_DISABLED
wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
* save mode
* by default
*/
-#else
- wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-#endif /* !WL_POWERSAVE_DISABLED */
err = wiphy_register(wdev->wiphy);
- if (unlikely(err < 0)) {
+ if (err < 0) {
WL_ERR("Couldn not register wiphy device (%d)\n", err);
goto wiphy_register_out;
}
@@ -2386,175 +2813,16 @@ wiphy_new_out:
static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct wireless_dev *wdev = cfg_to_wdev(cfg_priv);
+ struct wireless_dev *wdev = cfg_priv->wdev;
- if (unlikely(!wdev)) {
+ if (!wdev) {
WL_ERR("wdev is invalid\n");
return;
}
wiphy_unregister(wdev->wiphy);
wiphy_free(wdev->wiphy);
kfree(wdev);
- cfg_to_wdev(cfg_priv) = NULL;
-}
-
-static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_scan_results *bss_list;
- struct brcmf_bss_info *bi = NULL; /* must be initialized */
- s32 err = 0;
- int i;
-
- bss_list = cfg_priv->bss_list;
- if (unlikely(bss_list->version != BRCMF_BSS_INFO_VERSION)) {
- WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
- bss_list->version);
- return -EOPNOTSUPP;
- }
- WL_SCAN("scanned AP count (%d)\n", bss_list->count);
- bi = next_bss(bss_list, bi);
- for_each_bss(bss_list, bi, i) {
- err = brcmf_inform_single_bss(cfg_priv, bi);
- if (unlikely(err))
- break;
- }
- return err;
-}
-
-
-static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
- struct brcmf_bss_info *bi)
-{
- struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
- struct ieee80211_channel *notify_channel;
- struct cfg80211_bss *bss;
- struct ieee80211_supported_band *band;
- s32 err = 0;
- u16 channel;
- u32 freq;
- u64 notify_timestamp;
- u16 notify_capability;
- u16 notify_interval;
- u8 *notify_ie;
- size_t notify_ielen;
- s32 notify_signal;
-
- if (unlikely(le32_to_cpu(bi->length) > WL_BSS_INFO_MAX)) {
- WL_ERR("Bss info is larger than buffer. Discarding\n");
- return 0;
- }
-
- channel = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
-
- if (channel <= CH_MAX_2G_CHANNEL)
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
- else
- band = wiphy->bands[IEEE80211_BAND_5GHZ];
-
- freq = ieee80211_channel_to_frequency(channel, band->band);
- notify_channel = ieee80211_get_channel(wiphy, freq);
-
- notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
- notify_capability = le16_to_cpu(bi->capability);
- notify_interval = le16_to_cpu(bi->beacon_period);
- notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
- notify_ielen = le16_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);
- WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
-
- bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
- notify_timestamp, notify_capability, notify_interval, notify_ie,
- notify_ielen, notify_signal, GFP_KERNEL);
-
- if (unlikely(!bss)) {
- WL_ERR("cfg80211_inform_bss_frame error\n");
- return -EINVAL;
- }
-
- return err;
-}
-
-static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *dev, const u8 *bssid)
-{
- struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
- struct ieee80211_channel *notify_channel;
- struct brcmf_bss_info *bi = NULL;
- struct ieee80211_supported_band *band;
- u8 *buf = NULL;
- s32 err = 0;
- u16 channel;
- u32 freq;
- u64 notify_timestamp;
- u16 notify_capability;
- u16 notify_interval;
- u8 *notify_ie;
- size_t notify_ielen;
- s32 notify_signal;
-
- WL_TRACE("Enter\n");
-
- buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
- if (buf == NULL) {
- WL_ERR("kzalloc() failed\n");
- err = -ENOMEM;
- goto CleanUp;
- }
-
- *(u32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
-
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
- if (unlikely(err)) {
- WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
- goto CleanUp;
- }
-
- bi = (struct brcmf_bss_info *)(buf + 4);
-
- channel = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
-
- if (channel <= CH_MAX_2G_CHANNEL)
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
- else
- band = wiphy->bands[IEEE80211_BAND_5GHZ];
-
- freq = ieee80211_channel_to_frequency(channel, band->band);
- notify_channel = ieee80211_get_channel(wiphy, freq);
-
- notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
- notify_capability = le16_to_cpu(bi->capability);
- notify_interval = le16_to_cpu(bi->beacon_period);
- notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
- notify_ielen = le16_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);
- WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
-
- cfg80211_inform_bss(wiphy, notify_channel, bssid,
- notify_timestamp, notify_capability, notify_interval,
- notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
-
-CleanUp:
-
- kfree(buf);
-
- WL_TRACE("Exit\n");
-
- return err;
+ cfg_priv->wdev = NULL;
}
static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
@@ -2606,110 +2874,22 @@ static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
return false;
}
-static s32
-brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data)
-{
- s32 err = 0;
-
- if (brcmf_is_linkup(cfg_priv, e)) {
- WL_CONN("Linkup\n");
- if (brcmf_is_ibssmode(cfg_priv)) {
- brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
- WL_PROF_BSSID);
- wl_inform_ibss(cfg_priv, ndev, e->addr);
- cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
- clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
- set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
- } else
- brcmf_bss_connect_done(cfg_priv, ndev, e, data, true);
- } else if (brcmf_is_linkdown(cfg_priv, e)) {
- WL_CONN("Linkdown\n");
- if (brcmf_is_ibssmode(cfg_priv)) {
- clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
- if (test_and_clear_bit(WL_STATUS_CONNECTED,
- &cfg_priv->status))
- brcmf_link_down(cfg_priv);
- } else {
- brcmf_bss_connect_done(cfg_priv, ndev, e, data, false);
- if (test_and_clear_bit(WL_STATUS_CONNECTED,
- &cfg_priv->status)) {
- cfg80211_disconnected(ndev, 0, NULL, 0,
- GFP_KERNEL);
- brcmf_link_down(cfg_priv);
- }
- }
- brcmf_init_prof(cfg_priv->profile);
- } else if (brcmf_is_nonetwork(cfg_priv, e)) {
- if (brcmf_is_ibssmode(cfg_priv))
- clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
- else
- brcmf_bss_connect_done(cfg_priv, ndev, e, data, false);
- }
-
- return err;
-}
-
-static s32
-brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
- struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data)
-{
- s32 err = 0;
- u32 event = be32_to_cpu(e->event_type);
- u32 status = be32_to_cpu(e->status);
-
- if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
- if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
- brcmf_bss_roaming_done(cfg_priv, ndev, e, data);
- else
- brcmf_bss_connect_done(cfg_priv, ndev, e, data, true);
- }
-
- return err;
-}
-
-static __used s32
-brcmf_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
-{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
- u32 buflen;
-
- buflen = brcmu_mkiovar(name, buf, len, cfg_priv->ioctl_buf,
- WL_IOCTL_LEN_MAX);
- BUG_ON(!buflen);
-
- return brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, cfg_priv->ioctl_buf,
- buflen);
-}
-
-static s32
-brcmf_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
- s32 buf_len)
+static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
- u32 len;
- s32 err = 0;
-
- len = brcmu_mkiovar(name, NULL, 0, cfg_priv->ioctl_buf,
- WL_IOCTL_LEN_MAX);
- BUG_ON(!len);
- err = brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, (void *)cfg_priv->ioctl_buf,
- WL_IOCTL_LEN_MAX);
- if (unlikely(err)) {
- WL_ERR("error (%d)\n", err);
- return err;
- }
- memcpy(buf, cfg_priv->ioctl_buf, buf_len);
+ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
- return err;
+ kfree(conn_info->req_ie);
+ conn_info->req_ie = NULL;
+ conn_info->req_ie_len = 0;
+ kfree(conn_info->resp_ie);
+ conn_info->resp_ie = NULL;
+ conn_info->resp_ie_len = 0;
}
static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
{
struct net_device *ndev = cfg_to_ndev(cfg_priv);
- struct brcmf_cfg80211_assoc_ielen *assoc_info;
+ struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
u32 req_len;
u32 resp_len;
@@ -2719,18 +2899,19 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
WL_ASSOC_INFO_MAX);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("could not get assoc info (%d)\n", err);
return err;
}
- assoc_info = (struct brcmf_cfg80211_assoc_ielen *)cfg_priv->extra_buf;
- req_len = assoc_info->req_len;
- resp_len = assoc_info->resp_len;
+ assoc_info =
+ (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf;
+ 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_priv->extra_buf,
WL_ASSOC_INFO_MAX);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("could not get assoc req (%d)\n", err);
return err;
}
@@ -2746,7 +2927,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
cfg_priv->extra_buf,
WL_ASSOC_INFO_MAX);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("could not get assoc resp (%d)\n", err);
return err;
}
@@ -2764,121 +2945,19 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
return err;
}
-static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
-
- kfree(conn_info->req_ie);
- conn_info->req_ie = NULL;
- conn_info->req_ie_len = 0;
- kfree(conn_info->resp_ie);
- conn_info->resp_ie = NULL;
- conn_info->resp_ie_len = 0;
-}
-
-
-static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
- size_t *join_params_size)
-{
- chanspec_t chanspec = 0;
-
- if (ch != 0) {
- join_params->params.chanspec_num = 1;
- join_params->params.chanspec_list[0] = ch;
-
- if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
- chanspec |= WL_CHANSPEC_BAND_2G;
- else
- chanspec |= WL_CHANSPEC_BAND_5G;
-
- chanspec |= WL_CHANSPEC_BW_20;
- chanspec |= WL_CHANSPEC_CTL_SB_NONE;
-
- *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
- join_params->params.chanspec_num * sizeof(chanspec_t);
-
- join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
- join_params->params.chanspec_list[0] |= chanspec;
- join_params->params.chanspec_list[0] =
- cpu_to_le16(join_params->params.chanspec_list[0]);
-
- join_params->params.chanspec_num =
- cpu_to_le32(join_params->params.chanspec_num);
-
- WL_CONN("join_params->params.chanspec_list[0]= %#X,"
- "channel %d, chanspec %#X\n",
- join_params->params.chanspec_list[0], ch, chanspec);
- }
-}
-
-static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_bss_info *bi;
- struct brcmf_ssid *ssid;
- struct brcmu_tlv *tim;
- u16 beacon_interval;
- u8 dtim_period;
- size_t ie_len;
- u8 *ie;
- s32 err = 0;
-
- WL_TRACE("Enter\n");
- if (brcmf_is_ibssmode(cfg_priv))
- return err;
-
- ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
-
- *(u32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
- err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
- cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
- if (unlikely(err)) {
- WL_ERR("Could not get bss info %d\n", err);
- goto update_bss_info_out;
- }
-
- bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4);
- err = brcmf_inform_single_bss(cfg_priv, bi);
- if (unlikely(err))
- goto update_bss_info_out;
-
- ie = ((u8 *)bi) + bi->ie_offset;
- ie_len = bi->ie_length;
- beacon_interval = cpu_to_le16(bi->beacon_period);
-
- tim = brcmu_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
- if (tim)
- dtim_period = tim->data[1];
- else {
- /*
- * active scan was done so we could not get dtim
- * information out of probe response.
- * so we speficially query dtim information to dongle.
- */
- u32 var;
- err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
- "dtim_assoc", &var);
- if (unlikely(err)) {
- WL_ERR("wl dtim_assoc failed (%d)\n", err);
- goto update_bss_info_out;
- }
- dtim_period = (u8)var;
- }
-
- brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
- brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
-
-update_bss_info_out:
- WL_TRACE("Exit");
- return err;
-}
-
static s32
brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev,
- const struct brcmf_event_msg *e, void *data)
+ const struct brcmf_event_msg *e)
{
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
+ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
+ struct brcmf_channel_info_le channel_le;
+ struct ieee80211_channel *notify_channel;
+ struct ieee80211_supported_band *band;
+ u32 freq;
s32 err = 0;
+ u32 target_channel;
WL_TRACE("Enter\n");
@@ -2886,7 +2965,21 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
brcmf_update_bss_info(cfg_priv);
- cfg80211_roamed(ndev, NULL,
+ brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
+ sizeof(channel_le));
+
+ target_channel = le32_to_cpu(channel_le.target_channel);
+ WL_CONN("Roamed to channel %d\n", target_channel);
+
+ if (target_channel <= CH_MAX_2G_CHANNEL)
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
+ else
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+ freq = ieee80211_channel_to_frequency(target_channel, band->band);
+ notify_channel = ieee80211_get_channel(wiphy, freq);
+
+ cfg80211_roamed(ndev, notify_channel,
(u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
conn_info->req_ie, conn_info->req_ie_len,
conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
@@ -2900,7 +2993,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
static s32
brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev, const struct brcmf_event_msg *e,
- void *data, bool completed)
+ bool completed)
{
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
s32 err = 0;
@@ -2934,6 +3027,70 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
}
static s32
+brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
+ struct net_device *ndev,
+ const struct brcmf_event_msg *e, void *data)
+{
+ s32 err = 0;
+
+ if (brcmf_is_linkup(cfg_priv, e)) {
+ WL_CONN("Linkup\n");
+ if (brcmf_is_ibssmode(cfg_priv)) {
+ brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
+ WL_PROF_BSSID);
+ wl_inform_ibss(cfg_priv, ndev, e->addr);
+ cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
+ } else
+ brcmf_bss_connect_done(cfg_priv, ndev, e, true);
+ } else if (brcmf_is_linkdown(cfg_priv, e)) {
+ WL_CONN("Linkdown\n");
+ if (brcmf_is_ibssmode(cfg_priv)) {
+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+ if (test_and_clear_bit(WL_STATUS_CONNECTED,
+ &cfg_priv->status))
+ brcmf_link_down(cfg_priv);
+ } else {
+ brcmf_bss_connect_done(cfg_priv, ndev, e, false);
+ if (test_and_clear_bit(WL_STATUS_CONNECTED,
+ &cfg_priv->status)) {
+ cfg80211_disconnected(ndev, 0, NULL, 0,
+ GFP_KERNEL);
+ brcmf_link_down(cfg_priv);
+ }
+ }
+ brcmf_init_prof(cfg_priv->profile);
+ } else if (brcmf_is_nonetwork(cfg_priv, e)) {
+ if (brcmf_is_ibssmode(cfg_priv))
+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+ else
+ brcmf_bss_connect_done(cfg_priv, ndev, e, false);
+ }
+
+ return err;
+}
+
+static s32
+brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
+ struct net_device *ndev,
+ const struct brcmf_event_msg *e, void *data)
+{
+ s32 err = 0;
+ u32 event = be32_to_cpu(e->event_type);
+ u32 status = be32_to_cpu(e->status);
+
+ if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
+ if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
+ brcmf_bss_roaming_done(cfg_priv, ndev, e);
+ else
+ brcmf_bss_connect_done(cfg_priv, ndev, e, true);
+ }
+
+ return err;
+}
+
+static s32
brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev,
const struct brcmf_event_msg *e, void *data)
@@ -2941,7 +3098,6 @@ brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
u16 flags = be16_to_cpu(e->flags);
enum nl80211_key_type key_type;
- rtnl_lock();
if (flags & BRCMF_EVENT_MSG_GROUP)
key_type = NL80211_KEYTYPE_GROUP;
else
@@ -2949,7 +3105,6 @@ brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
NULL, GFP_KERNEL);
- rtnl_unlock();
return 0;
}
@@ -2959,11 +3114,12 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev,
const struct brcmf_event_msg *e, void *data)
{
- struct brcmf_channel_info channel_inform;
- struct brcmf_scan_results *bss_list;
+ 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");
@@ -2972,42 +3128,39 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
}
- if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING,
- &cfg_priv->status))) {
+ if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
WL_ERR("Scan complete while device not scanning\n");
scan_abort = true;
err = -EINVAL;
goto scan_done_out;
}
- err = brcmf_dev_ioctl(ndev, BRCMF_C_GET_CHANNEL, &channel_inform,
- sizeof(channel_inform));
- if (unlikely(err)) {
+ 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;
}
- channel_inform.scan_channel = le32_to_cpu(channel_inform.scan_channel);
- if (unlikely(channel_inform.scan_channel)) {
-
- WL_CONN("channel_inform.scan_channel (%d)\n",
- channel_inform.scan_channel);
- }
+ scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
+ if (scan_channel)
+ WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
cfg_priv->bss_list = cfg_priv->scan_results;
- bss_list = cfg_priv->bss_list;
- memset(bss_list, 0, len);
- bss_list->buflen = cpu_to_le32(len);
+ bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list;
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SCAN_RESULTS, bss_list, len);
- if (unlikely(err)) {
+ memset(cfg_priv->scan_results, 0, len);
+ bss_list_le->buflen = cpu_to_le32(len);
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
+ cfg_priv->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;
}
- bss_list->buflen = le32_to_cpu(bss_list->buflen);
- bss_list->version = le32_to_cpu(bss_list->version);
- bss_list->count = le32_to_cpu(bss_list->count);
+ cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
+ cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version);
+ cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
err = brcmf_inform_bss(cfg_priv);
if (err) {
@@ -3038,11 +3191,6 @@ static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
conf->tx_power = -1;
}
-static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
-{
- memset(prof, 0, sizeof(*prof));
-}
-
static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
{
memset(el, 0, sizeof(*el));
@@ -3053,54 +3201,58 @@ static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
}
+static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ kfree(cfg_priv->scan_results);
+ cfg_priv->scan_results = NULL;
+ kfree(cfg_priv->bss_info);
+ cfg_priv->bss_info = NULL;
+ kfree(cfg_priv->conf);
+ cfg_priv->conf = NULL;
+ kfree(cfg_priv->profile);
+ cfg_priv->profile = NULL;
+ kfree(cfg_priv->scan_req_int);
+ cfg_priv->scan_req_int = NULL;
+ kfree(cfg_priv->dcmd_buf);
+ cfg_priv->dcmd_buf = NULL;
+ kfree(cfg_priv->extra_buf);
+ cfg_priv->extra_buf = NULL;
+ kfree(cfg_priv->iscan);
+ cfg_priv->iscan = NULL;
+ kfree(cfg_priv->pmk_list);
+ cfg_priv->pmk_list = NULL;
+}
+
static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
{
cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
- if (unlikely(!cfg_priv->scan_results)) {
- WL_ERR("Scan results alloc failed\n");
+ if (!cfg_priv->scan_results)
goto init_priv_mem_out;
- }
cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
- if (unlikely(!cfg_priv->conf)) {
- WL_ERR("wl_conf alloc failed\n");
+ if (!cfg_priv->conf)
goto init_priv_mem_out;
- }
cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
- if (unlikely(!cfg_priv->profile)) {
- WL_ERR("wl_profile alloc failed\n");
+ if (!cfg_priv->profile)
goto init_priv_mem_out;
- }
cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
- if (unlikely(!cfg_priv->bss_info)) {
- WL_ERR("Bss information alloc failed\n");
+ if (!cfg_priv->bss_info)
goto init_priv_mem_out;
- }
cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
GFP_KERNEL);
- if (unlikely(!cfg_priv->scan_req_int)) {
- WL_ERR("Scan req alloc failed\n");
+ if (!cfg_priv->scan_req_int)
goto init_priv_mem_out;
- }
- cfg_priv->ioctl_buf = kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
- if (unlikely(!cfg_priv->ioctl_buf)) {
- WL_ERR("Ioctl buf alloc failed\n");
+ cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
+ if (!cfg_priv->dcmd_buf)
goto init_priv_mem_out;
- }
cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
- if (unlikely(!cfg_priv->extra_buf)) {
- WL_ERR("Extra buf alloc failed\n");
+ if (!cfg_priv->extra_buf)
goto init_priv_mem_out;
- }
cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
- if (unlikely(!cfg_priv->iscan)) {
- WL_ERR("Iscan buf alloc failed\n");
+ if (!cfg_priv->iscan)
goto init_priv_mem_out;
- }
cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
- if (unlikely(!cfg_priv->pmk_list)) {
- WL_ERR("pmk list alloc failed\n");
+ if (!cfg_priv->pmk_list)
goto init_priv_mem_out;
- }
return 0;
@@ -3110,301 +3262,111 @@ init_priv_mem_out:
return -ENOMEM;
}
-static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
-{
- kfree(cfg_priv->scan_results);
- cfg_priv->scan_results = NULL;
- kfree(cfg_priv->bss_info);
- cfg_priv->bss_info = NULL;
- kfree(cfg_priv->conf);
- cfg_priv->conf = NULL;
- kfree(cfg_priv->profile);
- cfg_priv->profile = NULL;
- kfree(cfg_priv->scan_req_int);
- cfg_priv->scan_req_int = NULL;
- kfree(cfg_priv->ioctl_buf);
- cfg_priv->ioctl_buf = NULL;
- kfree(cfg_priv->extra_buf);
- cfg_priv->extra_buf = NULL;
- kfree(cfg_priv->iscan);
- cfg_priv->iscan = NULL;
- kfree(cfg_priv->pmk_list);
- cfg_priv->pmk_list = NULL;
-}
-
-static s32 brcmf_create_event_handler(struct brcmf_cfg80211_priv *cfg_priv)
-{
- sema_init(&cfg_priv->event_sync, 0);
- cfg_priv->event_tsk = kthread_run(brcmf_event_handler, cfg_priv,
- "wl_event_handler");
- if (IS_ERR(cfg_priv->event_tsk)) {
- cfg_priv->event_tsk = NULL;
- WL_ERR("failed to create event thread\n");
- return -ENOMEM;
- }
- return 0;
-}
-
-static void brcmf_destroy_event_handler(struct brcmf_cfg80211_priv *cfg_priv)
-{
- if (cfg_priv->event_tsk) {
- send_sig(SIGTERM, cfg_priv->event_tsk, 1);
- kthread_stop(cfg_priv->event_tsk);
- cfg_priv->event_tsk = NULL;
- }
-}
+/*
+* retrieve first queued event from head
+*/
-static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv)
+static struct brcmf_cfg80211_event_q *brcmf_deq_event(
+ struct brcmf_cfg80211_priv *cfg_priv)
{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
+ struct brcmf_cfg80211_event_q *e = NULL;
- if (cfg_priv->iscan_on && iscan->tsk) {
- iscan->state = WL_ISCAN_STATE_IDLE;
- send_sig(SIGTERM, iscan->tsk, 1);
- kthread_stop(iscan->tsk);
- iscan->tsk = NULL;
+ spin_lock_irq(&cfg_priv->evt_q_lock);
+ if (!list_empty(&cfg_priv->evt_q_list)) {
+ e = list_first_entry(&cfg_priv->evt_q_list,
+ struct brcmf_cfg80211_event_q, evt_q_list);
+ list_del(&e->evt_q_list);
}
-}
+ spin_unlock_irq(&cfg_priv->evt_q_lock);
-static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
- bool aborted)
-{
- struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
- struct net_device *ndev = cfg_to_ndev(cfg_priv);
-
- if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING,
- &cfg_priv->status))) {
- WL_ERR("Scan complete while device not scanning\n");
- return;
- }
- if (likely(cfg_priv->scan_request)) {
- WL_SCAN("ISCAN Completed scan: %s\n",
- aborted ? "Aborted" : "Done");
- cfg80211_scan_done(cfg_priv->scan_request, aborted);
- brcmf_set_mpc(ndev, 1);
- cfg_priv->scan_request = NULL;
- }
- cfg_priv->iscan_kickstart = false;
+ return e;
}
-static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
-{
- if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
- WL_SCAN("wake up iscan\n");
- up(&iscan->sync);
- return 0;
- }
-
- return -EIO;
-}
+/*
+** push event to tail of the queue
+*/
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_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->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
- results->version = 0;
- results->count = 0;
-
- memset(&list, 0, sizeof(list));
- list.results.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
- err = brcmf_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
- BRCMF_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
- WL_ISCAN_BUF_MAX);
- if (unlikely(err)) {
- WL_ERR("error (%d)\n", err);
- return err;
- }
- results->buflen = le32_to_cpu(results->buflen);
- results->version = le32_to_cpu(results->version);
- results->count = le32_to_cpu(results->count);
- WL_SCAN("results->count = %d\n", results->count);
- WL_SCAN("results->buflen = %d\n", results->buflen);
- *status = le32_to_cpu(list_buf->status);
- *bss_list = results;
-
- return err;
-}
-
-static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
- s32 err = 0;
-
- iscan->state = WL_ISCAN_STATE_IDLE;
- rtnl_lock();
- brcmf_inform_bss(cfg_priv);
- brcmf_notify_iscan_complete(iscan, false);
- rtnl_unlock();
-
- return err;
-}
-
-static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->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_priv *cfg_priv)
+brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
+ const struct brcmf_event_msg *msg)
{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
+ struct brcmf_cfg80211_event_q *e;
s32 err = 0;
- rtnl_lock();
- brcmf_inform_bss(cfg_priv);
- brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
- rtnl_unlock();
- /* Reschedule the timer */
- mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
- iscan->timer_on = 1;
-
- return err;
-}
+ e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
-static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
- s32 err = 0;
+ e->etype = event;
+ memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
- iscan->state = WL_ISCAN_STATE_IDLE;
- rtnl_lock();
- brcmf_notify_iscan_complete(iscan, true);
- rtnl_unlock();
+ spin_lock_irq(&cfg_priv->evt_q_lock);
+ list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
+ spin_unlock_irq(&cfg_priv->evt_q_lock);
return err;
}
-static s32 brcmf_iscan_thread(void *data)
+static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
{
- struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
- struct brcmf_cfg80211_iscan_ctrl *iscan =
- (struct brcmf_cfg80211_iscan_ctrl *)data;
- struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
- struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
- u32 status;
- int err = 0;
-
- sched_setscheduler(current, SCHED_FIFO, &param);
- allow_signal(SIGTERM);
- status = BRCMF_SCAN_RESULTS_PARTIAL;
- while (likely(!down_interruptible(&iscan->sync))) {
- if (kthread_should_stop())
- break;
- if (iscan->timer_on) {
- del_timer_sync(&iscan->timer);
- iscan->timer_on = 0;
- }
- rtnl_lock();
- err = brcmf_get_iscan_results(iscan, &status,
- &cfg_priv->bss_list);
- if (unlikely(err)) {
- status = BRCMF_SCAN_RESULTS_ABORTED;
- WL_ERR("Abort iscan\n");
- }
- rtnl_unlock();
- el->handler[status](cfg_priv);
- }
- if (iscan->timer_on) {
- del_timer_sync(&iscan->timer);
- iscan->timer_on = 0;
- }
- WL_SCAN("ISCAN thread terminated\n");
-
- return 0;
+ kfree(e);
}
-static void brcmf_iscan_timer(unsigned long data)
+static void brcmf_cfg80211_event_handler(struct work_struct *work)
{
- struct brcmf_cfg80211_iscan_ctrl *iscan =
- (struct brcmf_cfg80211_iscan_ctrl *)data;
+ struct brcmf_cfg80211_priv *cfg_priv =
+ container_of(work, struct brcmf_cfg80211_priv,
+ event_work);
+ struct brcmf_cfg80211_event_q *e;
- if (iscan) {
- iscan->timer_on = 0;
- WL_SCAN("timer expired\n");
- brcmf_wakeup_iscan(iscan);
+ e = brcmf_deq_event(cfg_priv);
+ if (unlikely(!e)) {
+ WL_ERR("event queue empty...\n");
+ return;
}
-}
-static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
- int err = 0;
-
- if (cfg_priv->iscan_on && !iscan->tsk) {
- iscan->state = WL_ISCAN_STATE_IDLE;
- sema_init(&iscan->sync, 0);
- iscan->tsk = kthread_run(brcmf_iscan_thread, iscan, "wl_iscan");
- if (IS_ERR(iscan->tsk)) {
- WL_ERR("Could not create iscan thread\n");
- iscan->tsk = NULL;
- return -ENOMEM;
- }
- }
+ do {
+ WL_INFO("event type (%d)\n", e->etype);
+ if (cfg_priv->el.handler[e->etype])
+ cfg_priv->el.handler[e->etype](cfg_priv,
+ cfg_to_ndev(cfg_priv),
+ &e->emsg, e->edata);
+ else
+ WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
+ brcmf_put_event(e);
+ } while ((e = brcmf_deq_event(cfg_priv)));
- return err;
}
-static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
+static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
{
- 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;
+ spin_lock_init(&cfg_priv->evt_q_lock);
+ INIT_LIST_HEAD(&cfg_priv->evt_q_list);
}
-static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
+static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
- int err = 0;
+ struct brcmf_cfg80211_event_q *e;
- if (cfg_priv->iscan_on) {
- iscan->dev = cfg_to_ndev(cfg_priv);
- iscan->state = WL_ISCAN_STATE_IDLE;
- 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;
- sema_init(&iscan->sync, 0);
- iscan->tsk = kthread_run(brcmf_iscan_thread, iscan, "wl_iscan");
- if (IS_ERR(iscan->tsk)) {
- WL_ERR("Could not create iscan thread\n");
- iscan->tsk = NULL;
- return -ENOMEM;
- }
- iscan->data = cfg_priv;
+ spin_lock_irq(&cfg_priv->evt_q_lock);
+ while (!list_empty(&cfg_priv->evt_q_list)) {
+ e = list_first_entry(&cfg_priv->evt_q_list,
+ struct brcmf_cfg80211_event_q, evt_q_list);
+ list_del(&e->evt_q_list);
+ kfree(e);
}
-
- return err;
+ spin_unlock_irq(&cfg_priv->evt_q_lock);
}
static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
s32 err = 0;
cfg_priv->scan_request = NULL;
- cfg_priv->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
+ cfg_priv->pwr_save = true;
cfg_priv->iscan_on = true; /* iscan on & off switch.
we enable iscan per default */
- cfg_priv->roam_on = false; /* roam on & off switch.
+ cfg_priv->roam_on = true; /* roam on & off switch.
we enable roam per default */
cfg_priv->iscan_kickstart = false;
@@ -3413,14 +3375,13 @@ static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
cfg_priv->dongle_up = false; /* dongle is not up yet */
brcmf_init_eq(cfg_priv);
err = brcmf_init_priv_mem(cfg_priv);
- if (unlikely(err))
+ if (err)
return err;
- if (unlikely(brcmf_create_event_handler(cfg_priv)))
- return -ENOMEM;
+ INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler);
brcmf_init_eloop_handler(&cfg_priv->el);
mutex_init(&cfg_priv->usr_sync);
err = brcmf_init_iscan(cfg_priv);
- if (unlikely(err))
+ if (err)
return err;
brcmf_init_conf(cfg_priv->conf);
brcmf_init_prof(cfg_priv->profile);
@@ -3431,7 +3392,7 @@ static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
{
- brcmf_destroy_event_handler(cfg_priv);
+ cancel_work_sync(&cfg_priv->event_work);
cfg_priv->dongle_up = false; /* dongle down */
brcmf_flush_eq(cfg_priv);
brcmf_link_down(cfg_priv);
@@ -3439,27 +3400,29 @@ static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
brcmf_deinit_priv_mem(cfg_priv);
}
-s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data)
+struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
+ struct device *busdev,
+ void *data)
{
struct wireless_dev *wdev;
struct brcmf_cfg80211_priv *cfg_priv;
struct brcmf_cfg80211_iface *ci;
+ struct brcmf_cfg80211_dev *cfg_dev;
s32 err = 0;
- if (unlikely(!ndev)) {
+ if (!ndev) {
WL_ERR("ndev is invalid\n");
- return -ENODEV;
+ return NULL;
}
- cfg80211_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
- if (unlikely(!cfg80211_dev)) {
- WL_ERR("wl_cfg80211_dev is invalid\n");
- return -ENOMEM;
+ cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
+ if (!cfg_dev)
+ return NULL;
+
+ wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev);
+ if (IS_ERR(wdev)) {
+ kfree(cfg_dev);
+ return NULL;
}
- WL_INFO("func %p\n", brcmf_cfg80211_get_sdio_func());
- wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface),
- &brcmf_cfg80211_get_sdio_func()->dev);
- if (IS_ERR(wdev))
- return -ENOMEM;
wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
cfg_priv = wdev_to_cfg(wdev);
@@ -3471,67 +3434,30 @@ s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data)
SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
wdev->netdev = ndev;
err = wl_init_priv(cfg_priv);
- if (unlikely(err)) {
+ if (err) {
WL_ERR("Failed to init iwm_priv (%d)\n", err);
goto cfg80211_attach_out;
}
- brcmf_set_drvdata(cfg80211_dev, ci);
+ brcmf_set_drvdata(cfg_dev, ci);
- return err;
+ return cfg_dev;
cfg80211_attach_out:
brcmf_free_wdev(cfg_priv);
- return err;
+ kfree(cfg_dev);
+ return NULL;
}
-void brcmf_cfg80211_detach(void)
+void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev)
{
struct brcmf_cfg80211_priv *cfg_priv;
- cfg_priv = WL_PRIV_GET();
+ cfg_priv = brcmf_priv_get(cfg_dev);
wl_deinit_priv(cfg_priv);
brcmf_free_wdev(cfg_priv);
- brcmf_set_drvdata(cfg80211_dev, NULL);
- kfree(cfg80211_dev);
- cfg80211_dev = NULL;
- brcmf_clear_sdio_func();
-}
-
-static void brcmf_wakeup_event(struct brcmf_cfg80211_priv *cfg_priv)
-{
- up(&cfg_priv->event_sync);
-}
-
-static s32 brcmf_event_handler(void *data)
-{
- struct brcmf_cfg80211_priv *cfg_priv =
- (struct brcmf_cfg80211_priv *)data;
- struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
- struct brcmf_cfg80211_event_q *e;
-
- sched_setscheduler(current, SCHED_FIFO, &param);
- allow_signal(SIGTERM);
- while (likely(!down_interruptible(&cfg_priv->event_sync))) {
- if (kthread_should_stop())
- break;
- e = brcmf_deq_event(cfg_priv);
- if (unlikely(!e)) {
- WL_ERR("event queue empty...\n");
- BUG();
- }
- WL_INFO("event type (%d)\n", e->etype);
- if (cfg_priv->el.handler[e->etype]) {
- cfg_priv->el.handler[e->etype](cfg_priv,
- cfg_to_ndev(cfg_priv),
- &e->emsg, e->edata);
- } else {
- WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
- }
- brcmf_put_event(e);
- }
- WL_INFO("was terminated\n");
- return 0;
+ brcmf_set_drvdata(cfg_dev, NULL);
+ kfree(cfg_dev);
}
void
@@ -3541,95 +3467,8 @@ brcmf_cfg80211_event(struct net_device *ndev,
u32 event_type = be32_to_cpu(e->event_type);
struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
- if (likely(!brcmf_enq_event(cfg_priv, event_type, e, data)))
- brcmf_wakeup_event(cfg_priv);
-}
-
-static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
-{
- brcmf_init_eq_lock(cfg_priv);
- INIT_LIST_HEAD(&cfg_priv->eq_list);
-}
-
-static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_event_q *e;
-
- brcmf_lock_eq(cfg_priv);
- while (!list_empty(&cfg_priv->eq_list)) {
- e = list_first_entry(&cfg_priv->eq_list,
- struct brcmf_cfg80211_event_q, eq_list);
- list_del(&e->eq_list);
- kfree(e);
- }
- brcmf_unlock_eq(cfg_priv);
-}
-
-/*
-* retrieve first queued event from head
-*/
-
-static struct brcmf_cfg80211_event_q *brcmf_deq_event(
- struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct brcmf_cfg80211_event_q *e = NULL;
-
- brcmf_lock_eq(cfg_priv);
- if (likely(!list_empty(&cfg_priv->eq_list))) {
- e = list_first_entry(&cfg_priv->eq_list,
- struct brcmf_cfg80211_event_q, eq_list);
- list_del(&e->eq_list);
- }
- brcmf_unlock_eq(cfg_priv);
-
- return e;
-}
-
-/*
-** push event to tail of the queue
-*/
-
-static s32
-brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
- const struct brcmf_event_msg *msg, void *data)
-{
- struct brcmf_cfg80211_event_q *e;
- s32 err = 0;
-
- e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
- if (unlikely(!e)) {
- WL_ERR("event alloc failed\n");
- return -ENOMEM;
- }
-
- e->etype = event;
- memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
-
- brcmf_lock_eq(cfg_priv);
- list_add_tail(&e->eq_list, &cfg_priv->eq_list);
- brcmf_unlock_eq(cfg_priv);
-
- return err;
-}
-
-static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
-{
- kfree(e);
-}
-
-void brcmf_cfg80211_sdio_func(void *func)
-{
- cfg80211_sdio_func = (struct sdio_func *)func;
-}
-
-static void brcmf_clear_sdio_func(void)
-{
- cfg80211_sdio_func = NULL;
-}
-
-struct sdio_func *brcmf_cfg80211_get_sdio_func(void)
-{
- return cfg80211_sdio_func;
+ if (!brcmf_enq_event(cfg_priv, event_type, e))
+ schedule_work(&cfg_priv->event_work);
}
static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
@@ -3655,9 +3494,8 @@ static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
WL_ERR("invalid type (%d)\n", iftype);
return err;
}
- infra = cpu_to_le32(infra);
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_INFRA, &infra, sizeof(infra));
- if (unlikely(err)) {
+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
+ if (err) {
WL_ERR("WLC_SET_INFRA error (%d)\n", err);
return err;
}
@@ -3675,10 +3513,10 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
WL_TRACE("Enter\n");
/* Setup event_msgs */
- brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
- sizeof(iovbuf));
- err = brcmf_dev_ioctl(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
- if (unlikely(err)) {
+ 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;
}
@@ -3704,10 +3542,10 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
setbit(eventmask, BRCMF_E_JOIN_START);
setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
- brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
- sizeof(iovbuf));
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
- if (unlikely(err)) {
+ 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;
}
@@ -3721,20 +3559,23 @@ static s32
brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
{
s8 iovbuf[32];
- s32 roamtrigger[2];
- s32 roam_delta[2];
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) {
- brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout,
- sizeof(bcn_timeout), iovbuf, sizeof(iovbuf));
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR,
+ 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));
- if (unlikely(err)) {
+ if (err) {
WL_ERR("bcn_timeout error (%d)\n", err);
goto dongle_rom_out;
}
@@ -3745,28 +3586,29 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
* to take care of roaming
*/
WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
- brcmu_mkiovar("roam_off", (char *)&roamvar,
- sizeof(roamvar), iovbuf, sizeof(iovbuf));
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
- if (unlikely(err)) {
+ 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));
+ if (err) {
WL_ERR("roam_off error (%d)\n", err);
goto dongle_rom_out;
}
- roamtrigger[0] = WL_ROAM_TRIGGER_LEVEL;
- roamtrigger[1] = BRCM_BAND_ALL;
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_ROAM_TRIGGER,
+ 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));
- if (unlikely(err)) {
+ if (err) {
WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
goto dongle_rom_out;
}
- roam_delta[0] = WL_ROAM_DELTA;
- roam_delta[1] = BRCM_BAND_ALL;
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_ROAM_DELTA,
+ 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));
- if (unlikely(err)) {
+ if (err) {
WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
goto dongle_rom_out;
}
@@ -3777,12 +3619,15 @@ dongle_rom_out:
static s32
brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
- s32 scan_unassoc_time, s32 scan_passive_time)
+ s32 scan_unassoc_time, s32 scan_passive_time)
{
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_dev_ioctl(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
- &scan_assoc_time, sizeof(scan_assoc_time));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+ &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO("Scan assoc time is not supported\n");
@@ -3790,8 +3635,8 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
WL_ERR("Scan assoc time error (%d)\n", err);
goto dongle_scantime_out;
}
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
- &scan_unassoc_time, sizeof(scan_unassoc_time));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+ &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO("Scan unassoc time is not supported\n");
@@ -3800,8 +3645,8 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
goto dongle_scantime_out;
}
- err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
- &scan_passive_time, sizeof(scan_passive_time));
+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
+ &scan_passive_tm_le, sizeof(scan_passive_tm_le));
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO("Scan passive time is not supported\n");
@@ -3814,10 +3659,40 @@ dongle_scantime_out:
return err;
}
-s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv, bool need_lock)
+static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ struct wiphy *wiphy;
+ s32 phy_list;
+ s8 phy;
+ s32 err = 0;
+
+ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
+ &phy_list, sizeof(phy_list));
+ if (err) {
+ WL_ERR("error (%d)\n", err);
+ return err;
+ }
+
+ phy = ((char *)&phy_list)[1];
+ WL_INFO("%c phy\n", phy);
+ if (phy == 'n' || phy == 'a') {
+ wiphy = cfg_to_wiphy(cfg_priv);
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
+ }
+
+ return err;
+}
+
+static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ return wl_update_wiphybands(cfg_priv);
+}
+
+static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv)
{
struct net_device *ndev;
struct wireless_dev *wdev;
+ s32 power_mode;
s32 err = 0;
if (cfg_priv->dongle_up)
@@ -3825,31 +3700,35 @@ s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv, bool need_lock)
ndev = cfg_to_ndev(cfg_priv);
wdev = ndev->ieee80211_ptr;
- if (need_lock)
- rtnl_lock();
brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
err = brcmf_dongle_eventmsg(ndev);
- if (unlikely(err))
+ if (err)
+ goto default_conf_out;
+
+ power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF;
+ err = brcmf_exec_dcmd_u32(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"));
+
err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
WL_BEACON_TIMEOUT);
- if (unlikely(err))
+ if (err)
goto default_conf_out;
err = brcmf_dongle_mode(ndev, wdev->iftype);
- if (unlikely(err && err != -EINPROGRESS))
+ if (err && err != -EINPROGRESS)
goto default_conf_out;
err = brcmf_dongle_probecap(cfg_priv);
- if (unlikely(err))
+ if (err)
goto default_conf_out;
/* -EINPROGRESS: Call commit handler */
default_conf_out:
- if (need_lock)
- rtnl_unlock();
cfg_priv->dongle_up = true;
@@ -3857,30 +3736,40 @@ default_conf_out:
}
-static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
+static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
{
- struct wiphy *wiphy;
- s32 phy_list;
- s8 phy;
+ char buf[10+IFNAMSIZ];
+ struct dentry *fd;
s32 err = 0;
- err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
- &phy_list, sizeof(phy_list));
- if (unlikely(err)) {
- WL_ERR("error (%d)\n", err);
- return err;
+ sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
+ cfg_priv->debugfsdir = debugfs_create_dir(buf,
+ cfg_to_wiphy(cfg_priv)->debugfsdir);
+
+ fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
+ (u16 *)&cfg_priv->profile->beacon_interval);
+ if (!fd) {
+ err = -ENOMEM;
+ goto err_out;
}
- phy = ((char *)&phy_list)[1];
- WL_INFO("%c phy\n", phy);
- if (phy == 'n' || phy == 'a') {
- wiphy = cfg_to_wiphy(cfg_priv);
- wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
+ fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
+ (u8 *)&cfg_priv->profile->dtim_period);
+ if (!fd) {
+ err = -ENOMEM;
+ goto err_out;
}
+err_out:
return err;
}
+static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
+{
+ debugfs_remove_recursive(cfg_priv->debugfsdir);
+ cfg_priv->debugfsdir = NULL;
+}
+
static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
{
s32 err = 0;
@@ -3889,8 +3778,8 @@ static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
brcmf_debugfs_add_netdev_params(cfg_priv);
- err = brcmf_config_dongle(cfg_priv, false);
- if (unlikely(err))
+ err = brcmf_config_dongle(cfg_priv);
+ if (err)
return err;
brcmf_invoke_iscan(cfg_priv);
@@ -3914,9 +3803,7 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
generated due to DISASSOC call to the fw to keep
the state fw and WPA_Supplicant state consistent
*/
- rtnl_unlock();
brcmf_delay(500);
- rtnl_lock();
}
set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
@@ -3936,12 +3823,12 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
return 0;
}
-s32 brcmf_cfg80211_up(void)
+s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev)
{
struct brcmf_cfg80211_priv *cfg_priv;
s32 err = 0;
- cfg_priv = WL_PRIV_GET();
+ cfg_priv = brcmf_priv_get(cfg_dev);
mutex_lock(&cfg_priv->usr_sync);
err = __brcmf_cfg80211_up(cfg_priv);
mutex_unlock(&cfg_priv->usr_sync);
@@ -3949,12 +3836,12 @@ s32 brcmf_cfg80211_up(void)
return err;
}
-s32 brcmf_cfg80211_down(void)
+s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev)
{
struct brcmf_cfg80211_priv *cfg_priv;
s32 err = 0;
- cfg_priv = WL_PRIV_GET();
+ cfg_priv = brcmf_priv_get(cfg_dev);
mutex_lock(&cfg_priv->usr_sync);
err = __brcmf_cfg80211_down(cfg_priv);
mutex_unlock(&cfg_priv->usr_sync);
@@ -3962,78 +3849,13 @@ s32 brcmf_cfg80211_down(void)
return err;
}
-static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
-{
- return wl_update_wiphybands(cfg_priv);
-}
-
-static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
-{
- switch (item) {
- case WL_PROF_SEC:
- return &cfg_priv->profile->sec;
- case WL_PROF_BSSID:
- return &cfg_priv->profile->bssid;
- case WL_PROF_SSID:
- return &cfg_priv->profile->ssid;
- }
- WL_ERR("invalid item (%d)\n", item);
- return NULL;
-}
-
-static s32
-brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
- const struct brcmf_event_msg *e, void *data, s32 item)
-{
- s32 err = 0;
- struct brcmf_ssid *ssid;
-
- switch (item) {
- case WL_PROF_SSID:
- ssid = (struct brcmf_ssid *) data;
- memset(cfg_priv->profile->ssid.SSID, 0,
- sizeof(cfg_priv->profile->ssid.SSID));
- memcpy(cfg_priv->profile->ssid.SSID,
- ssid->SSID, ssid->SSID_len);
- cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
- break;
- case WL_PROF_BSSID:
- if (data)
- memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
- else
- memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
- break;
- case WL_PROF_SEC:
- memcpy(&cfg_priv->profile->sec, data,
- sizeof(cfg_priv->profile->sec));
- break;
- case WL_PROF_BEACONINT:
- cfg_priv->profile->beacon_interval = *(u16 *)data;
- break;
- case WL_PROF_DTIMPERIOD:
- cfg_priv->profile->dtim_period = *(u8 *)data;
- break;
- default:
- WL_ERR("unsupported item (%d)\n", item);
- err = -EOPNOTSUPP;
- break;
- }
-
- return err;
-}
-
-static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
-{
- return cfg_priv->conf->mode == WL_MODE_IBSS;
-}
-
static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
u8 t, u8 l, u8 *v)
{
struct brcmf_cfg80211_ie *ie = &cfg_priv->ie;
s32 err = 0;
- if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
+ if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
WL_ERR("ei crosses buffer boundary\n");
return -ENOSPC;
}
@@ -4044,109 +3866,3 @@ static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
return err;
}
-
-static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
-{
- struct net_device *dev = NULL;
- s32 err = 0;
-
- WL_TRACE("Enter\n");
-
- if (cfg_priv->link_up) {
- dev = cfg_to_ndev(cfg_priv);
- WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
- err = brcmf_dev_ioctl(dev, BRCMF_C_DISASSOC, NULL, 0);
- if (unlikely(err))
- WL_ERR("WLC_DISASSOC failed (%d)\n", err);
- cfg_priv->link_up = false;
- }
- WL_TRACE("Exit\n");
-}
-
-static void brcmf_lock_eq(struct brcmf_cfg80211_priv *cfg_priv)
-{
- spin_lock_irq(&cfg_priv->eq_lock);
-}
-
-static void brcmf_unlock_eq(struct brcmf_cfg80211_priv *cfg_priv)
-{
- spin_unlock_irq(&cfg_priv->eq_lock);
-}
-
-static void brcmf_init_eq_lock(struct brcmf_cfg80211_priv *cfg_priv)
-{
- spin_lock_init(&cfg_priv->eq_lock);
-}
-
-static void brcmf_delay(u32 ms)
-{
- if (ms < 1000 / HZ) {
- cond_resched();
- mdelay(ms);
- } else {
- msleep(ms);
- }
-}
-
-static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data)
-{
- dev->driver_data = data;
-}
-
-static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev)
-{
- void *data = NULL;
-
- if (dev)
- data = dev->driver_data;
- return data;
-}
-
-static void brcmf_set_mpc(struct net_device *ndev, int mpc)
-{
- s32 err = 0;
- struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
-
- if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
- err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
- if (unlikely(err)) {
- WL_ERR("fail to set mpc\n");
- return;
- }
- WL_INFO("MPC : %d\n", mpc);
- }
-}
-
-static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
-{
- char buf[10+IFNAMSIZ];
- struct dentry *fd;
- s32 err = 0;
-
- sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
- cfg_priv->debugfsdir = debugfs_create_dir(buf,
- cfg_to_wiphy(cfg_priv)->debugfsdir);
-
- fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
- (u16 *)&cfg_priv->profile->beacon_interval);
- if (!fd) {
- err = -ENOMEM;
- goto err_out;
- }
-
- fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
- (u8 *)&cfg_priv->profile->dtim_period);
- if (!fd) {
- err = -ENOMEM;
- goto err_out;
- }
-
-err_out:
- return err;
-}
-
-static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
-{
- debugfs_remove_recursive(cfg_priv->debugfsdir);
- cfg_priv->debugfsdir = NULL;
-}
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index f26d08793ca8..62dc46144ede 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -103,10 +103,10 @@ do { \
* report it to cfg80211 through "connect"
* event
*/
-#define WL_IOCTL_LEN_MAX 1024
+#define WL_DCMD_LEN_MAX 1024
#define WL_EXTRA_BUF_MAX 2048
#define WL_ISCAN_BUF_MAX 2048 /*
- * the buf length can be BRCMF_C_IOCTL_MAXLEN
+ * the buf length can be BRCMF_DCMD_MAXLEN
* to reduce iteration
*/
#define WL_ISCAN_TIMER_INTERVAL_MS 3000
@@ -188,7 +188,7 @@ struct brcmf_cfg80211_dev {
/* basic structure of scan request */
struct brcmf_cfg80211_scan_req {
- struct brcmf_ssid ssid;
+ struct brcmf_ssid_le ssid_le;
};
/* basic structure of information element */
@@ -199,7 +199,7 @@ struct brcmf_cfg80211_ie {
/* event queue for cfg80211 main event */
struct brcmf_cfg80211_event_q {
- struct list_head eq_list;
+ struct list_head evt_q_list;
u32 etype;
struct brcmf_event_msg emsg;
s8 edata[1];
@@ -243,16 +243,15 @@ struct brcmf_cfg80211_iscan_eloop {
/* dongle iscan controller */
struct brcmf_cfg80211_iscan_ctrl {
- struct net_device *dev;
+ struct net_device *ndev;
struct timer_list timer;
u32 timer_ms;
u32 timer_on;
s32 state;
- struct task_struct *tsk;
- struct semaphore sync;
+ struct work_struct work;
struct brcmf_cfg80211_iscan_eloop el;
void *data;
- s8 ioctl_buf[BRCMF_C_IOCTL_SMLEN];
+ s8 dcmd_buf[BRCMF_DCMD_SMLEN];
s8 scan_buf[WL_ISCAN_BUF_MAX];
};
@@ -265,15 +264,15 @@ struct brcmf_cfg80211_connect_info {
};
/* assoc ie length */
-struct brcmf_cfg80211_assoc_ielen {
- u32 req_len;
- u32 resp_len;
+struct brcmf_cfg80211_assoc_ielen_le {
+ __le32 req_len;
+ __le32 resp_len;
};
/* wpa2 pmk list */
struct brcmf_cfg80211_pmk_list {
- pmkid_list_t pmkids;
- pmkid_t foo[MAXPMKID - 1];
+ struct pmkid_list pmkids;
+ struct pmkid foo[MAXPMKID - 1];
};
/* dongle private data of cfg80211 interface */
@@ -283,8 +282,8 @@ struct brcmf_cfg80211_priv {
struct cfg80211_scan_request *scan_request; /* scan request
object */
struct brcmf_cfg80211_event_loop el; /* main event loop */
- struct list_head eq_list; /* used for event queue */
- spinlock_t eq_lock; /* for event queue synchronization */
+ struct list_head evt_q_list; /* used for event queue */
+ spinlock_t evt_q_lock; /* for event queue synchronization */
struct mutex usr_sync; /* maily for dongle up/down synchronization */
struct brcmf_scan_results *bss_list; /* bss_list holding scanned
ap information */
@@ -295,13 +294,11 @@ struct brcmf_cfg80211_priv {
cfg80211 layer */
struct brcmf_cfg80211_ie ie; /* information element object for
internal purpose */
- struct semaphore event_sync; /* for synchronization of main event
- thread */
struct brcmf_cfg80211_profile *profile; /* holding dongle profile */
struct brcmf_cfg80211_iscan_ctrl *iscan; /* iscan controller */
struct brcmf_cfg80211_connect_info conn_info; /* association info */
struct brcmf_cfg80211_pmk_list *pmk_list; /* wpa2 pmk list */
- struct task_struct *event_tsk; /* task of main event handler thread */
+ struct work_struct event_work; /* event handler work struct */
unsigned long status; /* current dongle status */
void *pub;
u32 channel; /* current channel */
@@ -315,21 +312,45 @@ struct brcmf_cfg80211_priv {
bool dongle_up; /* indicate whether dongle up or not */
bool roam_on; /* on/off switch for dongle self-roaming */
bool scan_tried; /* indicates if first scan attempted */
- u8 *ioctl_buf; /* ioctl buffer */
- u8 *extra_buf; /* maily to grab assoc information */
+ u8 *dcmd_buf; /* dcmd buffer */
+ u8 *extra_buf; /* maily to grab assoc information */
struct dentry *debugfsdir;
- u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
+ u8 ci[0] __aligned(NETDEV_ALIGN);
};
-#define cfg_to_wiphy(w) (w->wdev->wiphy)
-#define wiphy_to_cfg(w) ((struct brcmf_cfg80211_priv *)(wiphy_priv(w)))
-#define cfg_to_wdev(w) (w->wdev)
-#define wdev_to_cfg(w) ((struct brcmf_cfg80211_priv *)(wdev_priv(w)))
-#define cfg_to_ndev(w) (w->wdev->netdev)
-#define ndev_to_cfg(n) (wdev_to_cfg(n->ieee80211_ptr))
+static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_priv *w)
+{
+ return w->wdev->wiphy;
+}
+
+static inline struct brcmf_cfg80211_priv *wiphy_to_cfg(struct wiphy *w)
+{
+ return (struct brcmf_cfg80211_priv *)(wiphy_priv(w));
+}
+
+static inline struct brcmf_cfg80211_priv *wdev_to_cfg(struct wireless_dev *wd)
+{
+ return (struct brcmf_cfg80211_priv *)(wdev_priv(wd));
+}
+
+static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_priv *cfg)
+{
+ return cfg->wdev->netdev;
+}
+
+static inline struct brcmf_cfg80211_priv *ndev_to_cfg(struct net_device *ndev)
+{
+ return wdev_to_cfg(ndev->ieee80211_ptr);
+}
+
#define iscan_to_cfg(i) ((struct brcmf_cfg80211_priv *)(i->data))
#define cfg_to_iscan(w) (w->iscan)
-#define cfg_to_conn(w) (&w->conn_info)
+
+static inline struct
+brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg)
+{
+ return &cfg->conn_info;
+}
static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list,
struct brcmf_bss_info *bss)
@@ -340,17 +361,15 @@ static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list,
list->bss_info;
}
-#define for_each_bss(list, bss, __i) \
- for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss))
+extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
+ struct device *busdev,
+ void *data);
+extern void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg);
-extern s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data);
-extern void brcmf_cfg80211_detach(void);
/* event handler from dongle */
extern void brcmf_cfg80211_event(struct net_device *ndev,
const struct brcmf_event_msg *e, void *data);
-extern void brcmf_cfg80211_sdio_func(void *func); /* set sdio function info */
-extern struct sdio_func *brcmf_cfg80211_get_sdio_func(void);
-extern s32 brcmf_cfg80211_up(void); /* dongle up */
-extern s32 brcmf_cfg80211_down(void); /* dongle down */
+extern s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev);
+extern s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev);
#endif /* _wl_cfg80211_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
index 1ea3e0c48f3e..c2eb2d0af386 100644
--- a/drivers/staging/brcm80211/brcmsmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
@@ -15,25 +15,17 @@
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-ccflags-y := \
- -DWLC_HIGH \
- -DWLC_LOW \
- -DSTA \
- -DWME \
- -DWL11N \
- -DDBAND \
- -DBCMNVRAMR \
- -Idrivers/staging/brcm80211/brcmsmac \
- -Idrivers/staging/brcm80211/brcmsmac/phy \
- -Idrivers/staging/brcm80211/include
+ccflags-y := \
+ -D__CHECK_ENDIAN__ \
+ -Idrivers/net/wireless/brcm80211/brcmsmac \
+ -Idrivers/net/wireless/brcm80211/brcmsmac/phy \
+ -Idrivers/net/wireless/brcm80211/include
BRCMSMAC_OFILES := \
mac80211_if.o \
ucode_loader.o \
- alloc.o \
ampdu.o \
antsel.o \
- bmac.o \
channel.o \
main.o \
phy_shim.o \
@@ -50,7 +42,8 @@ BRCMSMAC_OFILES := \
otp.o \
srom.o \
dma.o \
- nicpci.o
+ nicpci.o \
+ brcms_trace_events.o
MODULEPFX := brcmsmac
diff --git a/drivers/staging/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
index a25901e9981b..025fa0eb6f47 100644
--- a/drivers/staging/brcm80211/brcmsmac/aiutils.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
@@ -12,7 +12,10 @@
* 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.
+ *
+ * File contents: support functions for PCI/PCIe
*/
+
#include <linux/delay.h>
#include <linux/pci.h>
@@ -20,6 +23,7 @@
#include <chipcommon.h>
#include <brcmu_utils.h>
#include <brcm_hw_ids.h>
+#include <soc.h>
#include "types.h"
#include "pub.h"
#include "pmu.h"
@@ -28,48 +32,68 @@
#include "aiutils.h"
/* slow_clk_ctl */
-#define SCC_SS_MASK 0x00000007 /* slow clock source mask */
-#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */
-#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */
-#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */
-#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */
-#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled,
- * 0: LPO is enabled
- */
-#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock,
- * 0: power logic control
- */
-#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors
- * PLL clock disable requests from core
- */
-#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't
- * disable crystal when appropriate
- */
-#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */
-#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */
+ /* slow clock source mask */
+#define SCC_SS_MASK 0x00000007
+ /* source of slow clock is LPO */
+#define SCC_SS_LPO 0x00000000
+ /* source of slow clock is crystal */
+#define SCC_SS_XTAL 0x00000001
+ /* source of slow clock is PCI */
+#define SCC_SS_PCI 0x00000002
+ /* LPOFreqSel, 1: 160Khz, 0: 32KHz */
+#define SCC_LF 0x00000200
+ /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */
+#define SCC_LP 0x00000400
+ /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */
+#define SCC_FS 0x00000800
+ /* IgnorePllOffReq, 1/0:
+ * power logic ignores/honors PLL clock disable requests from core
+ */
+#define SCC_IP 0x00001000
+ /* XtalControlEn, 1/0:
+ * power logic does/doesn't disable crystal when appropriate
+ */
+#define SCC_XC 0x00002000
+ /* XtalPU (RO), 1/0: crystal running/disabled */
+#define SCC_XP 0x00004000
+ /* ClockDivider (SlowClk = 1/(4+divisor)) */
+#define SCC_CD_MASK 0xffff0000
#define SCC_CD_SHIFT 16
/* system_clk_ctl */
-#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */
-#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */
-#define SYCC_FP 0x00000004 /* ForcePLLOn */
-#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */
-#define SYCC_HR 0x00000010 /* Force HT */
-#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */
+ /* ILPen: Enable Idle Low Power */
+#define SYCC_IE 0x00000001
+ /* ALPen: Enable Active Low Power */
+#define SYCC_AE 0x00000002
+ /* ForcePLLOn */
+#define SYCC_FP 0x00000004
+ /* Force ALP (or HT if ALPen is not set */
+#define SYCC_AR 0x00000008
+ /* Force HT */
+#define SYCC_HR 0x00000010
+ /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */
+#define SYCC_CD_MASK 0xffff0000
#define SYCC_CD_SHIFT 16
#define CST4329_SPROM_OTP_SEL_MASK 0x00000003
-#define CST4329_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */
-#define CST4329_SPROM_SEL 1 /* OTP is powered up, SPROM is present */
-#define CST4329_OTP_SEL 2 /* OTP is powered up, no SPROM */
-#define CST4329_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */
+ /* OTP is powered up, use def. CIS, no SPROM */
+#define CST4329_DEFCIS_SEL 0
+ /* OTP is powered up, SPROM is present */
+#define CST4329_SPROM_SEL 1
+ /* OTP is powered up, no SPROM */
+#define CST4329_OTP_SEL 2
+ /* OTP is powered down, SPROM is present */
+#define CST4329_OTP_PWRDN 3
+
#define CST4329_SPI_SDIO_MODE_MASK 0x00000004
#define CST4329_SPI_SDIO_MODE_SHIFT 2
/* 43224 chip-specific ChipControl register bits */
#define CCTRL43224_GPIO_TOGGLE 0x8000
-#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */
-#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */
+ /* 12 mA drive strength */
+#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0
+ /* 12 mA drive strength for later 43224s */
+#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0
/* 43236 Chip specific ChipStatus register bits */
#define CST43236_SFLASH_MASK 0x00000040
@@ -78,29 +102,44 @@
#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */
#define CST43236_BOOT_MASK 0x00001800
#define CST43236_BOOT_SHIFT 11
-#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */
-#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */
-#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */
+#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */
+#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */
+#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */
#define CST43236_BOOT_FROM_INVALID 3
/* 4331 chip-specific ChipControl register bits */
-#define CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */
-#define CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */
-#define CCTRL4331_EXT_LNA (1<<2) /* 0 disable */
-#define CCTRL4331_SPROM_GPIO13_15 (1<<3) /* sprom/gpio13-15 mux */
-#define CCTRL4331_EXTPA_EN (1<<4) /* 0 ext pa disable, 1 ext pa enabled */
-#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) /* set drive out GPIO_CLK on sprom_cs pin */
-#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) /* use sprom_cs pin as PCIE mdio interface */
-#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) /* aband extpa will be at gpio2/5 and sprom_dout */
-#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) /* override core control on pipe_AuxClkEnable */
-#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */
-#define CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */
-#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */
-#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */
-#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */
+ /* 0 disable */
+#define CCTRL4331_BT_COEXIST (1<<0)
+ /* 0 SECI is disabled (JTAG functional) */
+#define CCTRL4331_SECI (1<<1)
+ /* 0 disable */
+#define CCTRL4331_EXT_LNA (1<<2)
+ /* sprom/gpio13-15 mux */
+#define CCTRL4331_SPROM_GPIO13_15 (1<<3)
+ /* 0 ext pa disable, 1 ext pa enabled */
+#define CCTRL4331_EXTPA_EN (1<<4)
+ /* set drive out GPIO_CLK on sprom_cs pin */
+#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5)
+ /* use sprom_cs pin as PCIE mdio interface */
+#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6)
+ /* aband extpa will be at gpio2/5 and sprom_dout */
+#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7)
+ /* override core control on pipe_AuxClkEnable */
+#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8)
+ /* override core control on pipe_AuxPowerDown */
+#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9)
+ /* pcie_auxclkenable */
+#define CCTRL4331_PCIE_AUXCLKEN (1<<10)
+ /* pcie_pipe_pllpowerdown */
+#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11)
+ /* enable bt_shd0 at gpio4 */
+#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16)
+ /* enable bt_shd1 at gpio5 */
+#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17)
/* 4331 Chip specific ChipStatus register bits */
-#define CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */
+ /* crystal frequency 20/40Mhz */
+#define CST4331_XTAL_FREQ 0x00000001
#define CST4331_SPROM_PRESENT 0x00000002
#define CST4331_OTP_PRESENT 0x00000004
#define CST4331_LDO_RF 0x00000008
@@ -110,19 +149,26 @@
#define CST4319_SPI_CPULESSUSB 0x00000001
#define CST4319_SPI_CLK_POL 0x00000002
#define CST4319_SPI_CLK_PH 0x00000008
-#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 /* gpio [7:6], SDIO CIS selection */
+ /* gpio [7:6], SDIO CIS selection */
+#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0
#define CST4319_SPROM_OTP_SEL_SHIFT 6
-#define CST4319_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */
-#define CST4319_SPROM_SEL 0x00000040 /* use SPROM, OTP is powered up */
-#define CST4319_OTP_SEL 0x00000080 /* use OTP, OTP is powered up */
-#define CST4319_OTP_PWRDN 0x000000c0 /* use SPROM, OTP is powered down */
-#define CST4319_SDIO_USB_MODE 0x00000100 /* gpio [8], sdio/usb mode */
+ /* use default CIS, OTP is powered up */
+#define CST4319_DEFCIS_SEL 0x00000000
+ /* use SPROM, OTP is powered up */
+#define CST4319_SPROM_SEL 0x00000040
+ /* use OTP, OTP is powered up */
+#define CST4319_OTP_SEL 0x00000080
+ /* use SPROM, OTP is powered down */
+#define CST4319_OTP_PWRDN 0x000000c0
+ /* gpio [8], sdio/usb mode */
+#define CST4319_SDIO_USB_MODE 0x00000100
#define CST4319_REMAP_SEL_MASK 0x00000600
#define CST4319_ILPDIV_EN 0x00000800
#define CST4319_XTAL_PD_POL 0x00001000
#define CST4319_LPO_SEL 0x00002000
#define CST4319_RES_INIT_MODE 0x0000c000
-#define CST4319_PALDO_EXTPNP 0x00010000 /* PALDO is configured with external PNP */
+ /* PALDO is configured with external PNP */
+#define CST4319_PALDO_EXTPNP 0x00010000
#define CST4319_CBUCK_MODE_MASK 0x00060000
#define CST4319_CBUCK_MODE_BURST 0x00020000
#define CST4319_CBUCK_MODE_LPBURST 0x00060000
@@ -153,11 +199,8 @@
#define CST4313_SPROM_OTP_SEL_SHIFT 0
/* 4313 Chip specific ChipControl register bits */
-#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */
-
-#define BCM47162_DMP() ((sih->chip == BCM47162_CHIP_ID) && \
- (sih->chiprev == 0) && \
- (sii->coreid[sii->curidx] == MIPS74K_CORE_ID))
+ /* 12 mA drive strengh for later 4313 */
+#define CCTRL_4313_12MA_LED_DRIVE 0x00000007
/* Manufacturer Ids */
#define MFGID_ARM 0x43b
@@ -227,9 +270,12 @@
#define SD_SG32 0x00000008
#define SD_SZ_ALIGN 0x00000fff
-#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */
-#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal power-up */
-#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL power-down */
+/* PCI config space bit 4 for 4306c0 slow clock source */
+#define PCI_CFG_GPIO_SCS 0x10
+/* PCI config space GPIO 14 for Xtal power-up */
+#define PCI_CFG_GPIO_XTAL 0x40
+/* PCI config space GPIO 15 for PLL power-down */
+#define PCI_CFG_GPIO_PLL 0x80
/* power control defines */
#define PLL_DELAY 150 /* us pll on delay */
@@ -239,6 +285,82 @@
/* resetctrl */
#define AIRC_RESET 1
+#define NOREV -1 /* Invalid rev */
+
+/* GPIO Based LED powersave defines */
+#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */
+#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */
+
+/* When Srom support present, fields in sromcontrol */
+#define SRC_START 0x80000000
+#define SRC_BUSY 0x80000000
+#define SRC_OPCODE 0x60000000
+#define SRC_OP_READ 0x00000000
+#define SRC_OP_WRITE 0x20000000
+#define SRC_OP_WRDIS 0x40000000
+#define SRC_OP_WREN 0x60000000
+#define SRC_OTPSEL 0x00000010
+#define SRC_LOCK 0x00000008
+#define SRC_SIZE_MASK 0x00000006
+#define SRC_SIZE_1K 0x00000000
+#define SRC_SIZE_4K 0x00000002
+#define SRC_SIZE_16K 0x00000004
+#define SRC_SIZE_SHIFT 1
+#define SRC_PRESENT 0x00000001
+
+/* External PA enable mask */
+#define GPIO_CTRL_EPA_EN_MASK 0x40
+
+#define DEFAULT_GPIOTIMERVAL \
+ ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
+
+#define BADIDX (SI_MAXCORES + 1)
+
+/* Newer chips can access PCI/PCIE and CC core without requiring to change
+ * PCI BAR0 WIN
+ */
+#define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) || \
+ (((si)->pub.buscoretype == PCI_CORE_ID) && \
+ (si)->pub.buscorerev >= 13))
+
+#define CCREGS_FAST(si) (((char __iomem *)((si)->curmap) + \
+ PCI_16KB0_CCREGS_OFFSET))
+
+#define IS_SIM(chippkg) \
+ ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
+
+/*
+ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts
+ * before after core switching to avoid invalid register accesss inside ISR.
+ */
+#define INTR_OFF(si, intr_val) \
+ if ((si)->intrsoff_fn && \
+ (si)->coreid[(si)->curidx] == (si)->dev_coreid) \
+ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg)
+
+#define INTR_RESTORE(si, intr_val) \
+ if ((si)->intrsrestore_fn && \
+ (si)->coreid[(si)->curidx] == (si)->dev_coreid) \
+ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val)
+
+#define PCI(si) ((si)->pub.buscoretype == PCI_CORE_ID)
+#define PCIE(si) ((si)->pub.buscoretype == PCIE_CORE_ID)
+
+#define PCI_FORCEHT(si) (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID))
+
+#ifdef BCMDBG
+#define SI_MSG(args) printk args
+#else
+#define SI_MSG(args)
+#endif /* BCMDBG */
+
+#define GOODCOREADDR(x, b) \
+ (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
+ IS_ALIGNED((x), SI_CORE_SIZE))
+
+#define PCIEREGS(si) ((__iomem char *)((si)->curmap) + \
+ PCI_16KB0_PCIREGS_OFFSET)
+
struct aidmp {
u32 oobselina30; /* 0x000 */
u32 oobselina74; /* 0x004 */
@@ -360,7 +482,7 @@ struct aidmp {
/* EROM parsing */
static u32
-get_erom_ent(struct si_pub *sih, u32 **eromptr, u32 mask, u32 match)
+get_erom_ent(struct si_pub *sih, u32 __iomem **eromptr, u32 mask, u32 match)
{
u32 ent;
uint inv = 0, nom = 0;
@@ -386,16 +508,11 @@ get_erom_ent(struct si_pub *sih, u32 **eromptr, u32 mask, u32 match)
nom++;
}
- SI_VMSG(("%s: Returning ent 0x%08x\n", __func__, ent));
- if (inv + nom) {
- SI_VMSG((" after %d invalid and %d non-matching entries\n",
- inv, nom));
- }
return ent;
}
static u32
-get_asd(struct si_pub *sih, u32 **eromptr, uint sp, uint ad, uint st,
+get_asd(struct si_pub *sih, u32 __iomem **eromptr, uint sp, uint ad, uint st,
u32 *addrl, u32 *addrh, u32 *sizel, u32 *sizeh)
{
u32 asd, sz, szd;
@@ -423,9 +540,6 @@ get_asd(struct si_pub *sih, u32 **eromptr, uint sp, uint ad, uint st,
} else
*sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT);
- SI_VMSG((" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n",
- sp, ad, st, *sizeh, *sizel, *addrh, *addrl));
-
return asd;
}
@@ -434,45 +548,28 @@ static void ai_hwfixup(struct si_info *sii)
}
/* parse the enumeration rom to identify all cores */
-void ai_scan(struct si_pub *sih, void *regs)
+static void ai_scan(struct si_pub *sih, struct chipcregs __iomem *cc)
{
- struct si_info *sii = SI_INFO(sih);
- chipcregs_t *cc = (chipcregs_t *) regs;
- u32 erombase, *eromptr, *eromlim;
+ struct si_info *sii = (struct si_info *)sih;
- erombase = R_REG(&cc->eromptr);
-
- switch (sih->bustype) {
- case SI_BUS:
- eromptr = (u32 *) REG_MAP(erombase, SI_CORE_SIZE);
- break;
+ u32 erombase;
+ u32 __iomem *eromptr, *eromlim;
+ void __iomem *regs = cc;
- case PCI_BUS:
- /* Set wrappers address */
- sii->curwrap = (void *)((unsigned long)regs + SI_CORE_SIZE);
-
- /* Now point the window at the erom */
- pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase);
- eromptr = regs;
- break;
+ erombase = R_REG(&cc->eromptr);
- case SPI_BUS:
- case SDIO_BUS:
- eromptr = (u32 *)(unsigned long)erombase;
- break;
+ /* Set wrappers address */
+ sii->curwrap = (void *)((unsigned long)cc + SI_CORE_SIZE);
- default:
- SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n",
- sih->bustype));
- return;
- }
+ /* Now point the window at the erom */
+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase);
+ eromptr = regs;
eromlim = eromptr + (ER_REMAPCONTROL / sizeof(u32));
- SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n", regs, erombase, eromptr, eromlim));
while (eromptr < eromlim) {
u32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp;
u32 mpd, asd, addrl, addrh, sizel, sizeh;
- u32 *base;
+ u32 __iomem *base;
uint i, j, idx;
bool br;
@@ -481,8 +578,7 @@ void ai_scan(struct si_pub *sih, void *regs)
/* Grok a component */
cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI);
if (cia == (ER_END | ER_VALID)) {
- SI_VMSG(("Found END of erom after %d cores\n",
- sii->numcores));
+ /* Found END of erom */
ai_hwfixup(sii);
return;
}
@@ -490,7 +586,7 @@ void ai_scan(struct si_pub *sih, void *regs)
cib = get_erom_ent(sih, &eromptr, 0, 0);
if ((cib & ER_TAG) != ER_CI) {
- SI_ERROR(("CIA not followed by CIB\n"));
+ /* CIA not followed by CIB */
goto error;
}
@@ -502,8 +598,6 @@ void ai_scan(struct si_pub *sih, void *regs)
nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
- SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, " "nsw = %d, nmp = %d & nsp = %d\n", mfg, cid, crev, base, nmw, nsw, nmp, nsp));
-
if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0))
continue;
if ((nmw + nsw == 0)) {
@@ -511,9 +605,8 @@ void ai_scan(struct si_pub *sih, void *regs)
if (cid == OOB_ROUTER_CORE_ID) {
asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE,
&addrl, &addrh, &sizel, &sizeh);
- if (asd != 0) {
+ if (asd != 0)
sii->oob_router = addrl;
- }
}
continue;
}
@@ -527,12 +620,9 @@ void ai_scan(struct si_pub *sih, void *regs)
for (i = 0; i < nmp; i++) {
mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
if ((mpd & ER_TAG) != ER_MP) {
- SI_ERROR(("Not enough MP entries for component 0x%x\n", cid));
+ /* Not enough MP entries for component */
goto error;
}
- SI_VMSG((" Master port %d, mp: %d id: %d\n", i,
- (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT,
- (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT));
}
/* First Slave Address Descriptor should be port 0:
@@ -550,7 +640,7 @@ void ai_scan(struct si_pub *sih, void *regs)
br = true;
else if ((addrh != 0) || (sizeh != 0)
|| (sizel != SI_CORE_SIZE)) {
- SI_ERROR(("First Slave ASD for core 0x%04x malformed " "(0x%08x)\n", cid, asd));
+ /* First Slave ASD for core malformed */
goto error;
}
}
@@ -578,8 +668,7 @@ void ai_scan(struct si_pub *sih, void *regs)
&addrl, &addrh, &sizel, &sizeh);
} while (asd != 0);
if (j == 0) {
- SI_ERROR((" SP %d has no address descriptors\n",
- i));
+ /* SP has no address descriptors */
goto error;
}
}
@@ -590,11 +679,11 @@ void ai_scan(struct si_pub *sih, void *regs)
get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl,
&addrh, &sizel, &sizeh);
if (asd == 0) {
- SI_ERROR(("Missing descriptor for MW %d\n", i));
+ /* Missing descriptor for MW */
goto error;
}
if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
- SI_ERROR(("Master wrapper %d is not 4KB\n", i));
+ /* Master wrapper %d is not 4KB */
goto error;
}
if (i == 0)
@@ -608,11 +697,11 @@ void ai_scan(struct si_pub *sih, void *regs)
get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP,
&addrl, &addrh, &sizel, &sizeh);
if (asd == 0) {
- SI_ERROR(("Missing descriptor for SW %d\n", i));
+ /* Missing descriptor for SW */
goto error;
}
if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
- SI_ERROR(("Slave wrapper %d is not 4KB\n", i));
+ /* Slave wrapper is not 4KB */
goto error;
}
if ((nmw == 0) && (i == 0))
@@ -627,62 +716,35 @@ void ai_scan(struct si_pub *sih, void *regs)
sii->numcores++;
}
- SI_ERROR(("Reached end of erom without finding END"));
-
error:
+ /* Reached end of erom without finding END */
sii->numcores = 0;
return;
}
-/* This function changes the logical "focus" to the indicated core.
- * Return the current core's virtual address.
+/*
+ * This function changes the logical "focus" to the indicated core.
+ * Return the current core's virtual address. Since each core starts with the
+ * same set of registers (BIST, clock control, etc), the returned address
+ * contains the first register of this 'common' register block (not to be
+ * confused with 'common core').
*/
-void *ai_setcoreidx(struct si_pub *sih, uint coreidx)
+void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx)
{
- struct si_info *sii = SI_INFO(sih);
+ struct si_info *sii = (struct si_info *)sih;
u32 addr = sii->coresba[coreidx];
u32 wrap = sii->wrapba[coreidx];
- void *regs;
if (coreidx >= sii->numcores)
return NULL;
- switch (sih->bustype) {
- case SI_BUS:
- /* map new one */
- if (!sii->regs[coreidx]) {
- sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE);
- }
- sii->curmap = regs = sii->regs[coreidx];
- if (!sii->wrappers[coreidx]) {
- sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE);
- }
- sii->curwrap = sii->wrappers[coreidx];
- break;
-
- case PCI_BUS:
- /* point bar0 window */
- pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr);
- regs = sii->curmap;
- /* point bar0 2nd 4KB window */
- pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap);
- break;
-
- case SPI_BUS:
- case SDIO_BUS:
- sii->curmap = regs = (void *)(unsigned long)addr;
- sii->curwrap = (void *)(unsigned long)wrap;
- break;
-
- default:
- regs = NULL;
- break;
- }
-
- sii->curmap = regs;
+ /* point bar0 window */
+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr);
+ /* point bar0 2nd 4KB window */
+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap);
sii->curidx = coreidx;
- return regs;
+ return sii->curmap;
}
/* Return the number of address spaces in current core */
@@ -697,7 +759,7 @@ u32 ai_addrspace(struct si_pub *sih, uint asidx)
struct si_info *sii;
uint cidx;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
cidx = sii->curidx;
if (asidx == 0)
@@ -705,7 +767,7 @@ u32 ai_addrspace(struct si_pub *sih, uint asidx)
else if (asidx == 1)
return sii->coresba2[cidx];
else {
- SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", __func__, asidx));
+ /* Need to parse the erom again to find addr space */
return 0;
}
}
@@ -716,7 +778,7 @@ u32 ai_addrspacesize(struct si_pub *sih, uint asidx)
struct si_info *sii;
uint cidx;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
cidx = sii->curidx;
if (asidx == 0)
@@ -724,7 +786,7 @@ u32 ai_addrspacesize(struct si_pub *sih, uint asidx)
else if (asidx == 1)
return sii->coresba2_size[cidx];
else {
- SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", __func__, asidx));
+ /* Need to parse the erom again to find addr */
return 0;
}
}
@@ -734,11 +796,7 @@ uint ai_flag(struct si_pub *sih)
struct si_info *sii;
struct aidmp *ai;
- sii = SI_INFO(sih);
- if (BCM47162_DMP()) {
- SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __func__));
- return sii->curidx;
- }
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
return R_REG(&ai->oobselouta30) & 0x1f;
@@ -753,7 +811,7 @@ uint ai_corevendor(struct si_pub *sih)
struct si_info *sii;
u32 cia;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
cia = sii->cia[sii->curidx];
return (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
}
@@ -763,7 +821,7 @@ uint ai_corerev(struct si_pub *sih)
struct si_info *sii;
u32 cib;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
cib = sii->cib[sii->curidx];
return (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
}
@@ -773,7 +831,7 @@ bool ai_iscoreup(struct si_pub *sih)
struct si_info *sii;
struct aidmp *ai;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
return (((R_REG(&ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) ==
@@ -787,13 +845,7 @@ void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val)
struct aidmp *ai;
u32 w;
- sii = SI_INFO(sih);
-
- if (BCM47162_DMP()) {
- SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
- __func__));
- return;
- }
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
@@ -809,13 +861,7 @@ u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val)
struct aidmp *ai;
u32 w;
- sii = SI_INFO(sih);
- if (BCM47162_DMP()) {
- SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
- __func__));
- return 0;
- }
-
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
if (mask || val) {
@@ -826,18 +872,35 @@ u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val)
return R_REG(&ai->ioctrl);
}
+/* return true if PCIE capability exists in the pci config space */
+static bool ai_ispcie(struct si_info *sii)
+{
+ u8 cap_ptr;
+
+ cap_ptr =
+ pcicore_find_pci_capability(sii->pbus, PCI_CAP_ID_EXP, NULL,
+ NULL);
+ if (!cap_ptr)
+ return false;
+
+ return true;
+}
+
+static bool ai_buscore_prep(struct si_info *sii)
+{
+ /* kludge to enable the clock on the 4306 which lacks a slowclock */
+ if (!ai_ispcie(sii))
+ ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON);
+ return true;
+}
+
u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val)
{
struct si_info *sii;
struct aidmp *ai;
u32 w;
- sii = SI_INFO(sih);
- if (BCM47162_DMP()) {
- SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0", __func__));
- return 0;
- }
-
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
if (mask || val) {
@@ -848,74 +911,13 @@ u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val)
return R_REG(&ai->iostatus);
}
-/* *************** from siutils.c ************** */
-/* local prototypes */
-static struct si_info *ai_doattach(struct si_info *sii, void *regs,
- uint bustype, void *sdh, char **vars,
- uint *varsz);
-static bool ai_buscore_prep(struct si_info *sii, uint bustype);
-static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
- u32 savewin, uint *origidx, void *regs);
-static void ai_nvram_process(struct si_info *sii, char *pvars);
-
-/* dev path concatenation util */
-static char *ai_devpathvar(struct si_pub *sih, char *var, int len,
- const char *name);
-static bool _ai_clkctl_cc(struct si_info *sii, uint mode);
-static bool ai_ispcie(struct si_info *sii);
-
-/* global variable to indicate reservation/release of gpio's */
-static u32 ai_gpioreservation;
-
-/*
- * Allocate a si handle.
- * devid - pci device id (used to determine chip#)
- * osh - opaque OS handle
- * regs - virtual address of initial core registers
- * bustype - pci/sb/sdio/etc
- * vars - pointer to a pointer area for "environment" variables
- * varsz - pointer to int to return the size of the vars
- */
-struct si_pub *ai_attach(void *regs, uint bustype,
- void *sdh, char **vars, uint *varsz)
-{
- struct si_info *sii;
-
- /* alloc struct si_info */
- sii = kmalloc(sizeof(struct si_info), GFP_ATOMIC);
- if (sii == NULL) {
- SI_ERROR(("si_attach: malloc failed!\n"));
- return NULL;
- }
-
- if (ai_doattach(sii, regs, bustype, sdh, vars, varsz) ==
- NULL) {
- kfree(sii);
- return NULL;
- }
- sii->vars = vars ? *vars : NULL;
- sii->varsz = varsz ? *varsz : 0;
-
- return (struct si_pub *) sii;
-}
-
-/* global kernel resource */
-static struct si_info ksii;
-
-static bool ai_buscore_prep(struct si_info *sii, uint bustype)
-{
- /* kludge to enable the clock on the 4306 which lacks a slowclock */
- if (bustype == PCI_BUS && !ai_ispcie(sii))
- ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON);
- return true;
-}
-
-static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
- u32 savewin, uint *origidx, void *regs)
+static bool
+ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx)
{
bool pci, pcie;
uint i;
uint pciidx, pcieidx, pcirev, pcierev;
+ struct chipcregs __iomem *cc;
cc = ai_setcoreidx(&sii->pub, SI_CC_IDX);
@@ -955,25 +957,19 @@ static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
cid = ai_coreid(&sii->pub);
crev = ai_corerev(&sii->pub);
- /* Display cores found */
- SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
- i, cid, crev, sii->coresba[i], sii->regs[i]));
-
- if (bustype == PCI_BUS) {
- if (cid == PCI_CORE_ID) {
- pciidx = i;
- pcirev = crev;
- pci = true;
- } else if (cid == PCIE_CORE_ID) {
- pcieidx = i;
- pcierev = crev;
- pcie = true;
- }
+ if (cid == PCI_CORE_ID) {
+ pciidx = i;
+ pcirev = crev;
+ pci = true;
+ } else if (cid == PCIE_CORE_ID) {
+ pcieidx = i;
+ pcierev = crev;
+ pcie = true;
}
/* find the core idx before entering this func. */
if ((savewin && (savewin == sii->coresba[i])) ||
- (regs == sii->regs[i]))
+ (cc == sii->regs[i]))
*origidx = i;
}
@@ -993,25 +989,19 @@ static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
sii->pub.buscoreidx = pcieidx;
}
- SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx,
- sii->pub.buscoretype, sii->pub.buscorerev));
-
/* fixup necessary chip/core configurations */
- if (sii->pub.bustype == PCI_BUS) {
- if (SI_FAST(sii)) {
- if (!sii->pch) {
- sii->pch = (void *)pcicore_init(
- &sii->pub, sii->pbus,
- (void *)PCIEREGS(sii));
- if (sii->pch == NULL)
- return false;
- }
- }
- if (ai_pci_fixcfg(&sii->pub)) {
- SI_ERROR(("si_doattach: si_pci_fixcfg failed\n"));
- return false;
+ if (SI_FAST(sii)) {
+ if (!sii->pch) {
+ sii->pch = pcicore_init(&sii->pub, sii->pbus,
+ (__iomem void *)PCIEREGS(sii));
+ if (sii->pch == NULL)
+ return false;
}
}
+ if (ai_pci_fixcfg(&sii->pub)) {
+ /* si_doattach: si_pci_fixcfg failed */
+ return false;
+ }
/* return to the original core */
ai_setcoreidx(&sii->pub, *origidx);
@@ -1019,63 +1009,27 @@ static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
return true;
}
-static __used void ai_nvram_process(struct si_info *sii, char *pvars)
+/*
+ * get boardtype and boardrev
+ */
+static __used void ai_nvram_process(struct si_info *sii)
{
uint w = 0;
- /* get boardtype and boardrev */
- switch (sii->pub.bustype) {
- case PCI_BUS:
- /* do a pci config read to get subsystem id and subvendor id */
- pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w);
- /* Let nvram variables override subsystem Vend/ID */
- sii->pub.boardvendor = (u16)ai_getdevpathintvar(&sii->pub,
- "boardvendor");
- if (sii->pub.boardvendor == 0)
- sii->pub.boardvendor = w & 0xffff;
- else
- SI_ERROR(("Overriding boardvendor: 0x%x instead of "
- "0x%x\n", sii->pub.boardvendor, w & 0xffff));
- sii->pub.boardtype = (u16)ai_getdevpathintvar(&sii->pub,
- "boardtype");
- if (sii->pub.boardtype == 0)
- sii->pub.boardtype = (w >> 16) & 0xffff;
- else
- SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n"
- , sii->pub.boardtype, (w >> 16) & 0xffff));
- break;
-
- sii->pub.boardvendor = getintvar(pvars, "manfid");
- sii->pub.boardtype = getintvar(pvars, "prodid");
- break;
-
- case SI_BUS:
- case JTAG_BUS:
- sii->pub.boardvendor = PCI_VENDOR_ID_BROADCOM;
- sii->pub.boardtype = getintvar(pvars, "prodid");
- if (pvars == NULL || (sii->pub.boardtype == 0)) {
- sii->pub.boardtype = getintvar(NULL, "boardtype");
- if (sii->pub.boardtype == 0)
- sii->pub.boardtype = 0xffff;
- }
- break;
- }
-
- if (sii->pub.boardtype == 0) {
- SI_ERROR(("si_doattach: unknown board type\n"));
- }
+ /* do a pci config read to get subsystem id and subvendor id */
+ pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w);
- sii->pub.boardflags = getintvar(pvars, "boardflags");
+ sii->pub.boardvendor = w & 0xffff;
+ sii->pub.boardtype = (w >> 16) & 0xffff;
+ sii->pub.boardflags = getintvar(&sii->pub, BRCMS_SROM_BOARDFLAGS);
}
static struct si_info *ai_doattach(struct si_info *sii,
- void *regs, uint bustype, void *pbus,
- char **vars, uint *varsz)
+ void __iomem *regs, struct pci_dev *pbus)
{
struct si_pub *sih = &sii->pub;
u32 w, savewin;
- chipcregs_t *cc;
- char *pvars = NULL;
+ struct chipcregs __iomem *cc;
uint socitype;
uint origidx;
@@ -1088,37 +1042,18 @@ static struct si_info *ai_doattach(struct si_info *sii,
sii->curmap = regs;
sii->pbus = pbus;
- /* check to see if we are a si core mimic'ing a pci core */
- if (bustype == PCI_BUS) {
- pci_read_config_dword(sii->pbus, PCI_SPROM_CONTROL, &w);
- if (w == 0xffffffff) {
- SI_ERROR(("%s: incoming bus is PCI but it's a lie, "
- " switching to SI devid:0x%x\n",
- __func__, devid));
- bustype = SI_BUS;
- }
- }
-
/* find Chipcommon address */
- if (bustype == PCI_BUS) {
- pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin);
- if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
- savewin = SI_ENUM_BASE;
- pci_write_config_dword(sii->pbus, PCI_BAR0_WIN,
- SI_ENUM_BASE);
- cc = (chipcregs_t *) regs;
- } else {
- cc = (chipcregs_t *) REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
- }
+ pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin);
+ if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
+ savewin = SI_ENUM_BASE;
- sih->bustype = bustype;
+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN,
+ SI_ENUM_BASE);
+ cc = (struct chipcregs __iomem *) regs;
/* bus/core/clk setup for register access */
- if (!ai_buscore_prep(sii, bustype)) {
- SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
- bustype));
+ if (!ai_buscore_prep(sii))
return NULL;
- }
/*
* ChipID recognition.
@@ -1134,67 +1069,59 @@ static struct si_info *ai_doattach(struct si_info *sii,
sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
- sih->issim = IS_SIM(sih->chippkg);
+ sih->issim = false;
/* scan for cores */
if (socitype == SOCI_AI) {
SI_MSG(("Found chip type AI (0x%08x)\n", w));
/* pass chipc address instead of original core base */
- ai_scan(&sii->pub, (void *)cc);
+ ai_scan(&sii->pub, cc);
} else {
- SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
+ /* Found chip of unknown type */
return NULL;
}
/* no cores found, bail out */
- if (sii->numcores == 0) {
- SI_ERROR(("si_doattach: could not find any cores\n"));
+ if (sii->numcores == 0)
return NULL;
- }
+
/* bus/core/clk setup */
origidx = SI_CC_IDX;
- if (!ai_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
- SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
+ if (!ai_buscore_setup(sii, savewin, &origidx))
goto exit;
- }
/* Init nvram from sprom/otp if they exist */
- if (srom_var_init
- (&sii->pub, bustype, regs, vars, varsz)) {
- SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
+ if (srom_var_init(&sii->pub, cc))
goto exit;
- }
- pvars = vars ? *vars : NULL;
- ai_nvram_process(sii, pvars);
+
+ ai_nvram_process(sii);
/* === NVRAM, clock is ready === */
- cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0);
+ cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0);
W_REG(&cc->gpiopullup, 0);
W_REG(&cc->gpiopulldown, 0);
ai_setcoreidx(sih, origidx);
/* PMU specific initializations */
- if (PMUCTL_ENAB(sih)) {
+ if (sih->cccaps & CC_CAP_PMU) {
u32 xtalfreq;
si_pmu_init(sih);
si_pmu_chip_init(sih);
- xtalfreq = getintvar(pvars, "xtalfreq");
- /* If xtalfreq var not available, try to measure it */
- if (xtalfreq == 0)
- xtalfreq = si_pmu_measure_alpclk(sih);
+
+ xtalfreq = si_pmu_measure_alpclk(sih);
si_pmu_pll_init(sih, xtalfreq);
si_pmu_res_init(sih);
si_pmu_swreg_init(sih);
}
/* setup the GPIO based LED powersave register */
- w = getintvar(pvars, "leddc");
+ w = getintvar(sih, BRCMS_SROM_LEDDC);
if (w == 0)
w = DEFAULT_GPIOTIMERVAL;
- ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, gpiotimerval), ~0, w);
+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, gpiotimerval),
+ ~0, w);
- if (PCIE(sii)) {
- pcicore_attach(sii->pch, pvars, SI_DOATTACH);
- }
+ if (PCIE(sii))
+ pcicore_attach(sii->pch, SI_DOATTACH);
if (sih->chip == BCM43224_CHIP_ID) {
/*
@@ -1204,7 +1131,7 @@ static struct si_info *ai_doattach(struct si_info *sii,
if (sih->chiprev == 0) {
SI_MSG(("Applying 43224A0 WARs\n"));
ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol),
+ offsetof(struct chipcregs, chipcontrol),
CCTRL43224_GPIO_TOGGLE,
CCTRL43224_GPIO_TOGGLE);
si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
@@ -1228,45 +1155,58 @@ static struct si_info *ai_doattach(struct si_info *sii,
}
return sii;
+
exit:
- if (sih->bustype == PCI_BUS) {
- if (sii->pch)
- pcicore_deinit(sii->pch);
- sii->pch = NULL;
- }
+ if (sii->pch)
+ pcicore_deinit(sii->pch);
+ sii->pch = NULL;
return NULL;
}
+/*
+ * Allocate a si handle.
+ * devid - pci device id (used to determine chip#)
+ * osh - opaque OS handle
+ * regs - virtual address of initial core registers
+ */
+struct si_pub *
+ai_attach(void __iomem *regs, struct pci_dev *sdh)
+{
+ struct si_info *sii;
+
+ /* alloc struct si_info */
+ sii = kmalloc(sizeof(struct si_info), GFP_ATOMIC);
+ if (sii == NULL)
+ return NULL;
+
+ if (ai_doattach(sii, regs, sdh) == NULL) {
+ kfree(sii);
+ return NULL;
+ }
+
+ return (struct si_pub *) sii;
+}
+
/* may be called with core in reset */
void ai_detach(struct si_pub *sih)
{
struct si_info *sii;
- uint idx;
struct si_pub *si_local = NULL;
memcpy(&si_local, &sih, sizeof(struct si_pub **));
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
if (sii == NULL)
return;
- if (sih->bustype == SI_BUS)
- for (idx = 0; idx < SI_MAXCORES; idx++)
- if (sii->regs[idx]) {
- iounmap(sii->regs[idx]);
- sii->regs[idx] = NULL;
- }
-
- if (sih->bustype == PCI_BUS) {
- if (sii->pch)
- pcicore_deinit(sii->pch);
- sii->pch = NULL;
- }
+ if (sii->pch)
+ pcicore_deinit(sii->pch);
+ sii->pch = NULL;
- if (sii != &ksii)
- kfree(sii);
+ srom_free_vars(sih);
+ kfree(sii);
}
/* register driver interrupt disabling and restoring callback functions */
@@ -1277,11 +1217,11 @@ ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn,
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
sii->intr_arg = intr_arg;
- sii->intrsoff_fn = (si_intrsoff_t) intrsoff_fn;
- sii->intrsrestore_fn = (si_intrsrestore_t) intrsrestore_fn;
- sii->intrsenabled_fn = (si_intrsenabled_t) intrsenabled_fn;
+ sii->intrsoff_fn = (u32 (*)(void *)) intrsoff_fn;
+ sii->intrsrestore_fn = (void (*) (void *, u32)) intrsrestore_fn;
+ sii->intrsenabled_fn = (bool (*)(void *)) intrsenabled_fn;
/* save current core id. when this function called, the current core
* must be the core which provides driver functions(il, et, wl, etc.)
*/
@@ -1292,7 +1232,7 @@ void ai_deregister_intr_callback(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
sii->intrsoff_fn = NULL;
}
@@ -1300,7 +1240,7 @@ uint ai_coreid(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
return sii->coreid[sii->curidx];
}
@@ -1308,7 +1248,7 @@ uint ai_coreidx(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
return sii->curidx;
}
@@ -1324,7 +1264,7 @@ uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit)
uint found;
uint i;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
found = 0;
@@ -1344,25 +1284,25 @@ uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit)
* Moreover, callers should keep interrupts off during switching
* out of and back to d11 core.
*/
-void *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit)
+void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit)
{
uint idx;
idx = ai_findcoreidx(sih, coreid, coreunit);
- if (!GOODIDX(idx))
+ if (idx >= SI_MAXCORES)
return NULL;
return ai_setcoreidx(sih, idx);
}
/* Turn off interrupt as required by ai_setcore, before switch core */
-void *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
- uint *intr_val)
+void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
+ uint *intr_val)
{
- void *cc;
+ void __iomem *cc;
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
if (SI_FAST(sii)) {
/* Overloading the origidx variable to remember the coreid,
@@ -1371,9 +1311,9 @@ void *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
*/
*origidx = coreid;
if (coreid == CC_CORE_ID)
- return (void *)CCREGS_FAST(sii);
+ return CCREGS_FAST(sii);
else if (coreid == sih->buscoretype)
- return (void *)PCIEREGS(sii);
+ return PCIEREGS(sii);
}
INTR_OFF(sii, *intr_val);
*origidx = sii->curidx;
@@ -1386,7 +1326,7 @@ void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val)
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
if (SI_FAST(sii)
&& ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
return;
@@ -1397,7 +1337,7 @@ void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val)
void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val)
{
- struct si_info *sii = SI_INFO(sih);
+ struct si_info *sii = (struct si_info *)sih;
u32 *w = (u32 *) sii->curwrap;
W_REG(w + (offset / 4), val);
return;
@@ -1417,54 +1357,40 @@ uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
uint val)
{
uint origidx = 0;
- u32 *r = NULL;
+ u32 __iomem *r = NULL;
uint w;
uint intr_val = 0;
bool fast = false;
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
if (coreidx >= SI_MAXCORES)
return 0;
- if (sih->bustype == SI_BUS) {
- /* If internal bus, we can always get at everything */
+ /*
+ * If pci/pcie, we can get at pci/pcie regs
+ * and on newer cores to chipc
+ */
+ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
+ /* Chipc registers are mapped at 12KB */
fast = true;
- /* map if does not exist */
- if (!sii->regs[coreidx]) {
- sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx],
- SI_CORE_SIZE);
- }
- r = (u32 *) ((unsigned char *) sii->regs[coreidx] + regoff);
- } else if (sih->bustype == PCI_BUS) {
+ r = (u32 __iomem *)((__iomem char *)sii->curmap +
+ PCI_16KB0_CCREGS_OFFSET + regoff);
+ } else if (sii->pub.buscoreidx == coreidx) {
/*
- * If pci/pcie, we can get at pci/pcie regs
- * and on newer cores to chipc
+ * pci registers are at either in the last 2KB of
+ * an 8KB window or, in pcie and pci rev 13 at 8KB
*/
- if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
- /* Chipc registers are mapped at 12KB */
-
- fast = true;
- r = (u32 *) ((char *)sii->curmap +
- PCI_16KB0_CCREGS_OFFSET + regoff);
- } else if (sii->pub.buscoreidx == coreidx) {
- /*
- * pci registers are at either in the last 2KB of
- * an 8KB window or, in pcie and pci rev 13 at 8KB
- */
- fast = true;
- if (SI_FAST(sii))
- r = (u32 *) ((char *)sii->curmap +
- PCI_16KB0_PCIREGS_OFFSET +
- regoff);
- else
- r = (u32 *) ((char *)sii->curmap +
- ((regoff >= SBCONFIGOFF) ?
- PCI_BAR0_PCISBR_OFFSET :
- PCI_BAR0_PCIREGS_OFFSET) +
- regoff);
- }
+ fast = true;
+ if (SI_FAST(sii))
+ r = (u32 __iomem *)((__iomem char *)sii->curmap +
+ PCI_16KB0_PCIREGS_OFFSET + regoff);
+ else
+ r = (u32 __iomem *)((__iomem char *)sii->curmap +
+ ((regoff >= SBCONFIGOFF) ?
+ PCI_BAR0_PCISBR_OFFSET :
+ PCI_BAR0_PCIREGS_OFFSET) + regoff);
}
if (!fast) {
@@ -1474,8 +1400,8 @@ uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
origidx = ai_coreidx(&sii->pub);
/* switch core */
- r = (u32 *) ((unsigned char *) ai_setcoreidx(&sii->pub, coreidx)
- + regoff);
+ r = (u32 __iomem *) ((unsigned char __iomem *)
+ ai_setcoreidx(&sii->pub, coreidx) + regoff);
}
/* mask and set */
@@ -1504,7 +1430,7 @@ void ai_core_disable(struct si_pub *sih, u32 bits)
u32 dummy;
struct aidmp *ai;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
@@ -1531,7 +1457,7 @@ void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits)
struct aidmp *ai;
u32 dummy;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
ai = sii->curwrap;
/*
@@ -1556,19 +1482,18 @@ void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits)
/* return the slow clock source - LPO, XTAL, or PCI */
static uint ai_slowclk_src(struct si_info *sii)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
u32 val;
if (sii->pub.ccrev < 6) {
- if (sii->pub.bustype == PCI_BUS) {
- pci_read_config_dword(sii->pbus, PCI_GPIO_OUT,
- &val);
- if (val & PCI_CFG_GPIO_SCS)
- return SCC_SS_PCI;
- }
+ pci_read_config_dword(sii->pbus, PCI_GPIO_OUT,
+ &val);
+ if (val & PCI_CFG_GPIO_SCS)
+ return SCC_SS_PCI;
return SCC_SS_XTAL;
} else if (sii->pub.ccrev < 10) {
- cc = (chipcregs_t *) ai_setcoreidx(&sii->pub, sii->curidx);
+ cc = (struct chipcregs __iomem *)
+ ai_setcoreidx(&sii->pub, sii->curidx);
return R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK;
} else /* Insta-clock */
return SCC_SS_XTAL;
@@ -1578,7 +1503,8 @@ static uint ai_slowclk_src(struct si_info *sii)
* return the ILP (slowclock) min or max frequency
* precondition: we've established the chip has dynamic clk control
*/
-static uint ai_slowclk_freq(struct si_info *sii, bool max_freq, chipcregs_t *cc)
+static uint ai_slowclk_freq(struct si_info *sii, bool max_freq,
+ struct chipcregs __iomem *cc)
{
u32 slowclk;
uint div;
@@ -1612,9 +1538,9 @@ static uint ai_slowclk_freq(struct si_info *sii, bool max_freq, chipcregs_t *cc)
return 0;
}
-static void ai_clkctl_setdelay(struct si_info *sii, void *chipcregs)
+static void
+ai_clkctl_setdelay(struct si_info *sii, struct chipcregs __iomem *cc)
{
- chipcregs_t *cc = (chipcregs_t *) chipcregs;
uint slowmaxfreq, pll_delay, slowclk;
uint pll_on_delay, fref_sel_delay;
@@ -1646,21 +1572,22 @@ void ai_clkctl_init(struct si_pub *sih)
{
struct si_info *sii;
uint origidx = 0;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
bool fast;
- if (!CCCTL_ENAB(sih))
+ if (!(sih->cccaps & CC_CAP_PWR_CTL))
return;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
fast = SI_FAST(sii);
if (!fast) {
origidx = sii->curidx;
- cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0);
+ cc = (struct chipcregs __iomem *)
+ ai_setcore(sih, CC_CORE_ID, 0);
if (cc == NULL)
return;
} else {
- cc = (chipcregs_t *) CCREGS_FAST(sii);
+ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii);
if (cc == NULL)
return;
}
@@ -1670,7 +1597,7 @@ void ai_clkctl_init(struct si_pub *sih)
SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK,
(ILP_DIV_1MHZ << SYCC_CD_SHIFT));
- ai_clkctl_setdelay(sii, (void *)cc);
+ ai_clkctl_setdelay(sii, cc);
if (!fast)
ai_setcoreidx(sih, origidx);
@@ -1684,21 +1611,21 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
{
struct si_info *sii;
uint origidx = 0;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint slowminfreq;
u16 fpdelay;
uint intr_val = 0;
bool fast;
- sii = SI_INFO(sih);
- if (PMUCTL_ENAB(sih)) {
+ sii = (struct si_info *)sih;
+ if (sih->cccaps & CC_CAP_PMU) {
INTR_OFF(sii, intr_val);
fpdelay = si_pmu_fast_pwrup_delay(sih);
INTR_RESTORE(sii, intr_val);
return fpdelay;
}
- if (!CCCTL_ENAB(sih))
+ if (!(sih->cccaps & CC_CAP_PWR_CTL))
return 0;
fast = SI_FAST(sii);
@@ -1706,11 +1633,12 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
if (!fast) {
origidx = sii->curidx;
INTR_OFF(sii, intr_val);
- cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0);
+ cc = (struct chipcregs __iomem *)
+ ai_setcore(sih, CC_CORE_ID, 0);
if (cc == NULL)
goto done;
} else {
- cc = (chipcregs_t *) CCREGS_FAST(sii);
+ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii);
if (cc == NULL)
goto done;
}
@@ -1733,99 +1661,68 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on)
struct si_info *sii;
u32 in, out, outen;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
- switch (sih->bustype) {
-
- case PCI_BUS:
- /* pcie core doesn't have any mapping to control the xtal pu */
- if (PCIE(sii))
- return -1;
+ /* pcie core doesn't have any mapping to control the xtal pu */
+ if (PCIE(sii))
+ return -1;
- pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in);
- pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out);
- pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen);
+ pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in);
+ pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out);
+ pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen);
- /*
- * Avoid glitching the clock if GPRS is already using it.
- * We can't actually read the state of the PLLPD so we infer it
- * by the value of XTAL_PU which *is* readable via gpioin.
- */
- if (on && (in & PCI_CFG_GPIO_XTAL))
- return 0;
+ /*
+ * Avoid glitching the clock if GPRS is already using it.
+ * We can't actually read the state of the PLLPD so we infer it
+ * by the value of XTAL_PU which *is* readable via gpioin.
+ */
+ if (on && (in & PCI_CFG_GPIO_XTAL))
+ return 0;
- if (what & XTAL)
- outen |= PCI_CFG_GPIO_XTAL;
- if (what & PLL)
- outen |= PCI_CFG_GPIO_PLL;
-
- if (on) {
- /* turn primary xtal on */
- if (what & XTAL) {
- out |= PCI_CFG_GPIO_XTAL;
- if (what & PLL)
- out |= PCI_CFG_GPIO_PLL;
- pci_write_config_dword(sii->pbus,
- PCI_GPIO_OUT, out);
- pci_write_config_dword(sii->pbus,
- PCI_GPIO_OUTEN, outen);
- udelay(XTAL_ON_DELAY);
- }
+ if (what & XTAL)
+ outen |= PCI_CFG_GPIO_XTAL;
+ if (what & PLL)
+ outen |= PCI_CFG_GPIO_PLL;
- /* turn pll on */
- if (what & PLL) {
- out &= ~PCI_CFG_GPIO_PLL;
- pci_write_config_dword(sii->pbus,
- PCI_GPIO_OUT, out);
- mdelay(2);
- }
- } else {
- if (what & XTAL)
- out &= ~PCI_CFG_GPIO_XTAL;
+ if (on) {
+ /* turn primary xtal on */
+ if (what & XTAL) {
+ out |= PCI_CFG_GPIO_XTAL;
if (what & PLL)
out |= PCI_CFG_GPIO_PLL;
pci_write_config_dword(sii->pbus,
PCI_GPIO_OUT, out);
pci_write_config_dword(sii->pbus,
PCI_GPIO_OUTEN, outen);
+ udelay(XTAL_ON_DELAY);
}
- default:
- return -1;
+ /* turn pll on */
+ if (what & PLL) {
+ out &= ~PCI_CFG_GPIO_PLL;
+ pci_write_config_dword(sii->pbus,
+ PCI_GPIO_OUT, out);
+ mdelay(2);
+ }
+ } else {
+ if (what & XTAL)
+ out &= ~PCI_CFG_GPIO_XTAL;
+ if (what & PLL)
+ out |= PCI_CFG_GPIO_PLL;
+ pci_write_config_dword(sii->pbus,
+ PCI_GPIO_OUT, out);
+ pci_write_config_dword(sii->pbus,
+ PCI_GPIO_OUTEN, outen);
}
return 0;
}
-/*
- * clock control policy function throught chipcommon
- *
- * set dynamic clk control mode (forceslow, forcefast, dynamic)
- * returns true if we are forcing fast clock
- * this is a wrapper over the next internal function
- * to allow flexible policy settings for outside caller
- */
-bool ai_clkctl_cc(struct si_pub *sih, uint mode)
-{
- struct si_info *sii;
-
- sii = SI_INFO(sih);
-
- /* chipcommon cores prior to rev6 don't support dynamic clock control */
- if (sih->ccrev < 6)
- return false;
-
- if (PCI_FORCEHT(sii))
- return mode == CLK_FAST;
-
- return _ai_clkctl_cc(sii, mode);
-}
-
/* clk control mechanism through chipcommon, no policy checking */
static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
{
uint origidx = 0;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
u32 scc;
uint intr_val = 0;
bool fast = SI_FAST(sii);
@@ -1837,20 +1734,15 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
if (!fast) {
INTR_OFF(sii, intr_val);
origidx = sii->curidx;
-
- if ((sii->pub.bustype == SI_BUS) &&
- ai_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
- (ai_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
- goto done;
-
- cc = (chipcregs_t *) ai_setcore(&sii->pub, CC_CORE_ID, 0);
+ cc = (struct chipcregs __iomem *)
+ ai_setcore(&sii->pub, CC_CORE_ID, 0);
} else {
- cc = (chipcregs_t *) CCREGS_FAST(sii);
+ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii);
if (cc == NULL)
goto done;
}
- if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
+ if (!(sii->pub.cccaps & CC_CAP_PWR_CTL) && (sii->pub.ccrev < 20))
goto done;
switch (mode) {
@@ -1870,7 +1762,7 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
}
/* wait for the PLL */
- if (PMUCTL_ENAB(&sii->pub)) {
+ if (sii->pub.cccaps & CC_CAP_PMU) {
u32 htavail = CCS_HTAVAIL;
SPINWAIT(((R_REG(&cc->clk_ctl_st) & htavail)
== 0), PMU_MAX_TRANSITION_DLY);
@@ -1913,7 +1805,31 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
return mode == CLK_FAST;
}
-/* Build device path. Support SI, PCI, and JTAG for now. */
+/*
+ * clock control policy function throught chipcommon
+ *
+ * set dynamic clk control mode (forceslow, forcefast, dynamic)
+ * returns true if we are forcing fast clock
+ * this is a wrapper over the next internal function
+ * to allow flexible policy settings for outside caller
+ */
+bool ai_clkctl_cc(struct si_pub *sih, uint mode)
+{
+ struct si_info *sii;
+
+ sii = (struct si_info *)sih;
+
+ /* chipcommon cores prior to rev6 don't support dynamic clock control */
+ if (sih->ccrev < 6)
+ return false;
+
+ if (PCI_FORCEHT(sii))
+ return mode == CLK_FAST;
+
+ return _ai_clkctl_cc(sii, mode);
+}
+
+/* Build device path */
int ai_devpath(struct si_pub *sih, char *path, int size)
{
int slen;
@@ -1921,22 +1837,10 @@ int ai_devpath(struct si_pub *sih, char *path, int size)
if (!path || size <= 0)
return -1;
- switch (sih->bustype) {
- case SI_BUS:
- case JTAG_BUS:
- slen = snprintf(path, (size_t) size, "sb/%u/", ai_coreidx(sih));
- break;
- case PCI_BUS:
- slen = snprintf(path, (size_t) size, "pci/%u/%u/",
- ((struct pci_dev *)((SI_INFO(sih))->pbus))->bus->number,
- PCI_SLOT(
- ((struct pci_dev *)((SI_INFO(sih))->pbus))->devfn));
- break;
-
- default:
- slen = -1;
- break;
- }
+ slen = snprintf(path, (size_t) size, "pci/%u/%u/",
+ ((struct si_info *)sih)->pbus->bus->number,
+ PCI_SLOT(((struct pci_dev *)
+ (((struct si_info *)(sih))->pbus))->devfn));
if (slen < 0 || slen >= size) {
path[0] = '\0';
@@ -1946,95 +1850,11 @@ int ai_devpath(struct si_pub *sih, char *path, int size)
return 0;
}
-/* Get a variable, but only if it has a devpath prefix */
-char *ai_getdevpathvar(struct si_pub *sih, const char *name)
-{
- char varname[SI_DEVPATH_BUFSZ + 32];
-
- ai_devpathvar(sih, varname, sizeof(varname), name);
-
- return getvar(NULL, varname);
-}
-
-/* Get a variable, but only if it has a devpath prefix */
-int ai_getdevpathintvar(struct si_pub *sih, const char *name)
-{
-#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
- return getintvar(NULL, name);
-#else
- char varname[SI_DEVPATH_BUFSZ + 32];
-
- ai_devpathvar(sih, varname, sizeof(varname), name);
-
- return getintvar(NULL, varname);
-#endif
-}
-
-char *ai_getnvramflvar(struct si_pub *sih, const char *name)
-{
- return getvar(NULL, name);
-}
-
-/* Concatenate the dev path with a varname into the given 'var' buffer
- * and return the 'var' pointer. Nothing is done to the arguments if
- * len == 0 or var is NULL, var is still returned. On overflow, the
- * first char will be set to '\0'.
- */
-static char *ai_devpathvar(struct si_pub *sih, char *var, int len,
- const char *name)
-{
- uint path_len;
-
- if (!var || len <= 0)
- return var;
-
- if (ai_devpath(sih, var, len) == 0) {
- path_len = strlen(var);
-
- if (strlen(name) + 1 > (uint) (len - path_len))
- var[0] = '\0';
- else
- strncpy(var + path_len, name, len - path_len - 1);
- }
-
- return var;
-}
-
-/* return true if PCIE capability exists in the pci config space */
-static bool ai_ispcie(struct si_info *sii)
-{
- u8 cap_ptr;
-
- if (sii->pub.bustype != PCI_BUS)
- return false;
-
- cap_ptr =
- pcicore_find_pci_capability(sii->pbus, PCI_CAP_ID_EXP, NULL,
- NULL);
- if (!cap_ptr)
- return false;
-
- return true;
-}
-
-bool ai_pci_war16165(struct si_pub *sih)
-{
- struct si_info *sii;
-
- sii = SI_INFO(sih);
-
- return PCI(sii) && (sih->buscorerev <= 10);
-}
-
void ai_pci_up(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
-
- /* if not pci bus, we're done */
- if (sih->bustype != PCI_BUS)
- return;
+ sii = (struct si_info *)sih;
if (PCI_FORCEHT(sii))
_ai_clkctl_cc(sii, CLK_FAST);
@@ -2049,7 +1869,7 @@ void ai_pci_sleep(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
pcicore_sleep(sii->pch);
}
@@ -2059,11 +1879,7 @@ void ai_pci_down(struct si_pub *sih)
{
struct si_info *sii;
- sii = SI_INFO(sih);
-
- /* if not pci bus, we're done */
- if (sih->bustype != PCI_BUS)
- return;
+ sii = (struct si_info *)sih;
/* release FORCEHT since chip is going to "down" state */
if (PCI_FORCEHT(sii))
@@ -2079,14 +1895,11 @@ void ai_pci_down(struct si_pub *sih)
void ai_pci_setup(struct si_pub *sih, uint coremask)
{
struct si_info *sii;
- void *regs = NULL;
+ struct sbpciregs __iomem *regs = NULL;
u32 siflag = 0, w;
uint idx = 0;
- sii = SI_INFO(sih);
-
- if (sii->pub.bustype != PCI_BUS)
- return;
+ sii = (struct si_info *)sih;
if (PCI(sii)) {
/* get current core index */
@@ -2128,9 +1941,8 @@ void ai_pci_setup(struct si_pub *sih, uint coremask)
int ai_pci_fixcfg(struct si_pub *sih)
{
uint origidx;
- void *regs = NULL;
-
- struct si_info *sii = SI_INFO(sih);
+ void __iomem *regs = NULL;
+ struct si_info *sii = (struct si_info *)sih;
/* Fixup PI in SROM shadow area to enable the correct PCI core access */
/* save the current index */
@@ -2138,7 +1950,11 @@ int ai_pci_fixcfg(struct si_pub *sih)
/* check 'pi' is correct and fix it if not */
regs = ai_setcore(&sii->pub, sii->pub.buscoretype, 0);
- pcicore_fixcfg(sii->pch, regs);
+ if (sii->pub.buscoretype == PCIE_CORE_ID)
+ pcicore_fixcfg_pcie(sii->pch,
+ (struct sbpcieregs __iomem *)regs);
+ else if (sii->pub.buscoretype == PCI_CORE_ID)
+ pcicore_fixcfg_pci(sii->pch, (struct sbpciregs __iomem *)regs);
/* restore the original index */
ai_setcoreidx(&sii->pub, origidx);
@@ -2152,47 +1968,34 @@ u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority)
{
uint regoff;
- regoff = 0;
-
- /* gpios could be shared on router platforms
- * ignore reservation if it's high priority (e.g., test apps)
- */
- if ((priority != GPIO_HI_PRIORITY) &&
- (sih->bustype == SI_BUS) && (val || mask)) {
- mask = priority ? (ai_gpioreservation & mask) :
- ((ai_gpioreservation | mask) & ~(ai_gpioreservation));
- val &= mask;
- }
-
- regoff = offsetof(chipcregs_t, gpiocontrol);
+ regoff = offsetof(struct chipcregs, gpiocontrol);
return ai_corereg(sih, SI_CC_IDX, regoff, mask, val);
}
void ai_chipcontrl_epa4331(struct si_pub *sih, bool on)
{
struct si_info *sii;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
u32 val;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
origidx = ai_coreidx(sih);
- cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0);
+ cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0);
val = R_REG(&cc->chipcontrol);
if (on) {
- if (sih->chippkg == 9 || sih->chippkg == 0xb) {
+ if (sih->chippkg == 9 || sih->chippkg == 0xb)
/* Ext PA Controls for 4331 12x9 Package */
W_REG(&cc->chipcontrol, val |
- (CCTRL4331_EXTPA_EN |
- CCTRL4331_EXTPA_ON_GPIO2_5));
- } else {
+ CCTRL4331_EXTPA_EN |
+ CCTRL4331_EXTPA_ON_GPIO2_5);
+ else
/* Ext PA Controls for 4331 12x12 Package */
W_REG(&cc->chipcontrol,
- val | (CCTRL4331_EXTPA_EN));
- }
+ val | CCTRL4331_EXTPA_EN);
} else {
val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
W_REG(&cc->chipcontrol, val);
@@ -2205,13 +2008,13 @@ void ai_chipcontrl_epa4331(struct si_pub *sih, bool on)
void ai_epa_4313war(struct si_pub *sih)
{
struct si_info *sii;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
origidx = ai_coreidx(sih);
- cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0);
+ cc = ai_setcore(sih, CC_CORE_ID, 0);
/* EPA Fix */
W_REG(&cc->gpiocontrol,
@@ -2226,15 +2029,12 @@ bool ai_deviceremoved(struct si_pub *sih)
u32 w;
struct si_info *sii;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
+
+ pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w);
+ if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM)
+ return true;
- switch (sih->bustype) {
- case PCI_BUS:
- pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w);
- if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM)
- return true;
- break;
- }
return false;
}
@@ -2243,13 +2043,13 @@ bool ai_is_sprom_available(struct si_pub *sih)
if (sih->ccrev >= 31) {
struct si_info *sii;
uint origidx;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
u32 sromctrl;
if ((sih->cccaps & CC_CAP_SROM) == 0)
return false;
- sii = SI_INFO(sih);
+ sii = (struct si_info *)sih;
origidx = sii->curidx;
cc = ai_setcoreidx(sih, SI_CC_IDX);
sromctrl = R_REG(&cc->sromcontrol);
diff --git a/drivers/staging/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
index e245c278bebc..106a7424a7cd 100644
--- a/drivers/staging/brcm80211/brcmsmac/aiutils.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
@@ -23,26 +23,6 @@
* SOC Interconnect Address Map.
* All regions may not exist on all chips.
*/
-/* Physical SDRAM */
-#define SI_SDRAM_BASE 0x00000000
-/* Host Mode sb2pcitranslation0 (64 MB) */
-#define SI_PCI_MEM 0x08000000
-#define SI_PCI_MEM_SZ (64 * 1024 * 1024)
-/* Host Mode sb2pcitranslation1 (64 MB) */
-#define SI_PCI_CFG 0x0c000000
-/* Byteswapped Physical SDRAM */
-#define SI_SDRAM_SWAPPED 0x10000000
-/* Region 2 for sdram (512 MB) */
-#define SI_SDRAM_R2 0x80000000
-
-#ifdef SI_ENUM_BASE_VARIABLE
-#define SI_ENUM_BASE (sii->pub.si_enum_base)
-#else
-#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */
-#endif /* SI_ENUM_BASE_VARIABLE */
-
-/* Wrapper space base */
-#define SI_WRAP_BASE 0x18100000
/* each core gets 4Kbytes for registers */
#define SI_CORE_SIZE 0x1000
/*
@@ -52,39 +32,9 @@
*/
#define SI_MAXCORES 16
-/* On-chip RAM on chips that also have DDR */
-#define SI_FASTRAM 0x19000000
-#define SI_FASTRAM_SWAPPED 0x19800000
-
-/* Flash Region 2 (region 1 shadowed here) */
-#define SI_FLASH2 0x1c000000
-/* Size of Flash Region 2 */
-#define SI_FLASH2_SZ 0x02000000
-/* ARM Cortex-M3 ROM */
-#define SI_ARMCM3_ROM 0x1e000000
-/* MIPS Flash Region 1 */
-#define SI_FLASH1 0x1fc00000
-/* MIPS Size of Flash Region 1 */
-#define SI_FLASH1_SZ 0x00400000
-/* ARM7TDMI-S ROM */
-#define SI_ARM7S_ROM 0x20000000
-/* ARM Cortex-M3 SRAM Region 2 */
-#define SI_ARMCM3_SRAM2 0x60000000
-/* ARM7TDMI-S SRAM Region 2 */
-#define SI_ARM7S_SRAM2 0x80000000
-/* ARM Flash Region 1 */
-#define SI_ARM_FLASH1 0xffff0000
-/* ARM Size of Flash Region 1 */
-#define SI_ARM_FLASH1_SZ 0x00010000
-
-/* Client Mode sb2pcitranslation2 (1 GB) */
-#define SI_PCI_DMA 0x40000000
-/* Client Mode sb2pcitranslation2 (1 GB) */
-#define SI_PCI_DMA2 0x80000000
/* Client Mode sb2pcitranslation2 size in bytes */
#define SI_PCI_DMA_SZ 0x40000000
-/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), low 32 bits */
-#define SI_PCIE_DMA_L32 0x00000000
+
/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
#define SI_PCIE_DMA_H32 0x80000000
@@ -203,18 +153,6 @@
/* Minumum amount of flash we support */
#define FLASH_MIN 0x00020000 /* Minimum flash size */
-/* A boot/binary may have an embedded block that describes its size */
-#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */
-#define BISZ_MAGIC 0x4249535a /* Marked with value: 'BISZ' */
-#define BISZ_MAGIC_IDX 0 /* Word 0: magic */
-#define BISZ_TXTST_IDX 1 /* 1: text start */
-#define BISZ_TXTEND_IDX 2 /* 2: text end */
-#define BISZ_DATAST_IDX 3 /* 3: data start */
-#define BISZ_DATAEND_IDX 4 /* 4: data end */
-#define BISZ_BSSST_IDX 5 /* 5: bss start */
-#define BISZ_BSSEND_IDX 6 /* 6: bss end */
-#define BISZ_SIZE 7 /* descriptor size in 32-bit integers */
-
#define CC_SROM_OTP 0x800 /* SROM/OTP address space */
/* gpiotimerval */
@@ -224,93 +162,15 @@
#define CLKD_OTP 0x000f0000
#define CLKD_OTP_SHIFT 16
-/* When Srom support present, fields in sromcontrol */
-#define SRC_START 0x80000000
-#define SRC_BUSY 0x80000000
-#define SRC_OPCODE 0x60000000
-#define SRC_OP_READ 0x00000000
-#define SRC_OP_WRITE 0x20000000
-#define SRC_OP_WRDIS 0x40000000
-#define SRC_OP_WREN 0x60000000
-#define SRC_OTPSEL 0x00000010
-#define SRC_LOCK 0x00000008
-#define SRC_SIZE_MASK 0x00000006
-#define SRC_SIZE_1K 0x00000000
-#define SRC_SIZE_4K 0x00000002
-#define SRC_SIZE_16K 0x00000004
-#define SRC_SIZE_SHIFT 1
-#define SRC_PRESENT 0x00000001
-
-/* 4330 chip-specific ChipStatus register bits */
-#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */
-#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */
-#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /* SDIO */
-#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /* gSPI */
-#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /* USB packet-oriented */
-#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /* USB Direct Access */
-#define CST4330_OTP_PRESENT 0x00000010
-#define CST4330_LPO_AUTODET_EN 0x00000020
-#define CST4330_ARMREMAP_0 0x00000040
-#define CST4330_SPROM_PRESENT 0x00000080 /* takes priority over OTP if both set */
-#define CST4330_ILPDIV_EN 0x00000100
-#define CST4330_LPO_SEL 0x00000200
-#define CST4330_RES_INIT_MODE_SHIFT 10
-#define CST4330_RES_INIT_MODE_MASK 0x00000c00
-#define CST4330_CBUCK_MODE_SHIFT 12
-#define CST4330_CBUCK_MODE_MASK 0x00003000
-#define CST4330_CBUCK_POWER_OK 0x00004000
-#define CST4330_BB_PLL_LOCKED 0x00008000
-
/* Package IDs */
-#define BCM4329_289PIN_PKG_ID 0 /* 4329 289-pin package id */
-#define BCM4329_182PIN_PKG_ID 1 /* 4329N 182-pin package id */
#define BCM4717_PKG_ID 9 /* 4717 package id */
#define BCM4718_PKG_ID 10 /* 4718 package id */
-#define HDLSIM_PKG_ID 14 /* HDL simulator package id */
-#define HWSIM_PKG_ID 15 /* Hardware simulator package id */
#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */
/* these are router chips */
#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */
#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */
#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */
-#define BCM5356_CHIP_ID 0x5356 /* 5356 chipcommon chipid */
-#define BCM5357_CHIP_ID 0x5357 /* 5357 chipcommon chipid */
-
-
-#define SI_INFO(sih) ((struct si_info *)sih)
-
-#define GOODCOREADDR(x, b) \
- (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
- IS_ALIGNED((x), SI_CORE_SIZE))
-#define GOODREGS(regs) \
- ((regs) != NULL && IS_ALIGNED((unsigned long)(regs), SI_CORE_SIZE))
-#define BADCOREADDR 0
-#define GOODIDX(idx) (((uint)idx) < SI_MAXCORES)
-#define NOREV -1 /* Invalid rev */
-
-/* Newer chips can access PCI/PCIE and CC core without requiring to change
- * PCI BAR0 WIN
- */
-#define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) || \
- (((si)->pub.buscoretype == PCI_CORE_ID) && \
- (si)->pub.buscorerev >= 13))
-
-#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET))
-#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET))
-
-/*
- * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts
- * before after core switching to avoid invalid register accesss inside ISR.
- */
-#define INTR_OFF(si, intr_val) \
- if ((si)->intrsoff_fn && \
- (si)->coreid[(si)->curidx] == (si)->dev_coreid) \
- intr_val = (*(si)->intrsoff_fn)((si)->intr_arg)
-#define INTR_RESTORE(si, intr_val) \
- if ((si)->intrsrestore_fn && \
- (si)->coreid[(si)->curidx] == (si)->dev_coreid) \
- (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val)
/* dynamic clock control defines */
#define LPOMINFREQ 25000 /* low power oscillator min */
@@ -323,60 +183,6 @@
#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
-#define PCI(si) (((si)->pub.bustype == PCI_BUS) && \
- ((si)->pub.buscoretype == PCI_CORE_ID))
-#define PCIE(si) (((si)->pub.bustype == PCI_BUS) && \
- ((si)->pub.buscoretype == PCIE_CORE_ID))
-#define PCI_FORCEHT(si) \
- (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID))
-
-/* GPIO Based LED powersave defines */
-#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */
-#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */
-
-#ifndef DEFAULT_GPIOTIMERVAL
-#define DEFAULT_GPIOTIMERVAL \
- ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
-#endif
-
-/*
- * Data structure to export all chip specific common variables
- * public (read-only) portion of aiutils handle returned by si_attach()
- */
-struct si_pub {
- uint bustype; /* SI_BUS, PCI_BUS */
- uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */
- uint buscorerev; /* buscore rev */
- uint buscoreidx; /* buscore index */
- int ccrev; /* chip common core rev */
- u32 cccaps; /* chip common capabilities */
- u32 cccaps_ext; /* chip common capabilities extension */
- int pmurev; /* pmu core rev */
- u32 pmucaps; /* pmu capabilities */
- uint boardtype; /* board type */
- uint boardvendor; /* board vendor */
- uint boardflags; /* board flags */
- uint boardflags2; /* board flags2 */
- uint chip; /* chip number */
- uint chiprev; /* chip revision */
- uint chippkg; /* chip package option */
- u32 chipst; /* chip status */
- bool issim; /* chip is in simulation or emulation */
- uint socirev; /* SOC interconnect rev */
- bool pci_pr32414;
-
-};
-
-/*
- * Many of the routines below take an 'sih' handle as their first arg.
- * Allocate this by calling si_attach(). Free it by calling si_detach().
- * At any one time, the sih is logically focused on one particular si core
- * (the "current core").
- * Use si_setcore() or si_setcoreidx() to change the association to another core
- */
-
-#define BADIDX (SI_MAXCORES + 1)
-
/* clkctl xtal what flags */
#define XTAL 0x1 /* primary crystal oscillator (2050) */
#define PLL 0x2 /* main chip pll */
@@ -409,49 +215,39 @@ struct si_pub {
#define SI_PCIDOWN 2
#define SI_PCIUP 3
-/* PMU clock/power control */
-#if defined(BCMPMUCTL)
-#define PMUCTL_ENAB(sih) (BCMPMUCTL)
-#else
-#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU)
-#endif
-
-/* chipcommon clock/power control (exclusive with PMU's) */
-#if defined(BCMPMUCTL) && BCMPMUCTL
-#define CCCTL_ENAB(sih) (0)
-#define CCPLL_ENAB(sih) (0)
-#else
-#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL)
-#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK)
-#endif
-
-typedef void (*gpio_handler_t) (u32 stat, void *arg);
-
-/* External PA enable mask */
-#define GPIO_CTRL_EPA_EN_MASK 0x40
-
-#define SI_ERROR(args)
-
-#ifdef BCMDBG
-#define SI_MSG(args) printk args
-#else
-#define SI_MSG(args)
-#endif /* BCMDBG */
-
-/* Define SI_VMSG to printf for verbose debugging, but don't check it in */
-#define SI_VMSG(args)
+/*
+ * Data structure to export all chip specific common variables
+ * public (read-only) portion of aiutils handle returned by si_attach()
+ */
+struct si_pub {
+ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */
+ uint buscorerev; /* buscore rev */
+ uint buscoreidx; /* buscore index */
+ int ccrev; /* chip common core rev */
+ u32 cccaps; /* chip common capabilities */
+ u32 cccaps_ext; /* chip common capabilities extension */
+ int pmurev; /* pmu core rev */
+ u32 pmucaps; /* pmu capabilities */
+ uint boardtype; /* board type */
+ uint boardvendor; /* board vendor */
+ uint boardflags; /* board flags */
+ uint boardflags2; /* board flags2 */
+ uint chip; /* chip number */
+ uint chiprev; /* chip revision */
+ uint chippkg; /* chip package option */
+ u32 chipst; /* chip status */
+ bool issim; /* chip is in simulation or emulation */
+ uint socirev; /* SOC interconnect rev */
+ bool pci_pr32414;
-#define IS_SIM(chippkg) \
- ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
+};
-typedef u32(*si_intrsoff_t) (void *intr_arg);
-typedef void (*si_intrsrestore_t) (void *intr_arg, u32 arg);
-typedef bool(*si_intrsenabled_t) (void *intr_arg);
+struct pci_dev;
struct gpioh_item {
void *arg;
bool level;
- gpio_handler_t handler;
+ void (*handler) (u32 stat, void *arg);
u32 event;
struct gpioh_item *next;
};
@@ -459,20 +255,21 @@ struct gpioh_item {
/* misc si info needed by some of the routines */
struct si_info {
struct si_pub pub; /* back plane public state (must be first) */
- void *pbus; /* handle to bus (pci/sdio/..) */
+ struct pci_dev *pbus; /* handle to pci bus */
uint dev_coreid; /* the core provides driver functions */
void *intr_arg; /* interrupt callback function arg */
- si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */
- si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */
- si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */
+ u32 (*intrsoff_fn) (void *intr_arg); /* turns chip interrupts off */
+ /* restore chip interrupts */
+ void (*intrsrestore_fn) (void *intr_arg, u32 arg);
+ /* check if interrupts are enabled */
+ bool (*intrsenabled_fn) (void *intr_arg);
- void *pch; /* PCI/E core handle */
+ struct pcicore_info *pch; /* PCI/E core handle */
- char *vars;
- uint varsz;
+ struct list_head var_list; /* list of srom variables */
- void *curmap; /* current regs va */
- void *regs[SI_MAXCORES]; /* other regs va */
+ void __iomem *curmap; /* current regs va */
+ void __iomem *regs[SI_MAXCORES]; /* other regs va */
uint curidx; /* current core index */
uint numcores; /* # discovered cores */
@@ -492,16 +289,22 @@ struct si_info {
u32 oob_router; /* oob router registers for axi */
};
-/* AMBA Interconnect exported externs */
-extern void ai_scan(struct si_pub *sih, void *regs);
+/*
+ * Many of the routines below take an 'sih' handle as their first arg.
+ * Allocate this by calling si_attach(). Free it by calling si_detach().
+ * At any one time, the sih is logically focused on one particular si core
+ * (the "current core").
+ * Use si_setcore() or si_setcoreidx() to change the association to another core
+ */
+
+/* AMBA Interconnect exported externs */
extern uint ai_flag(struct si_pub *sih);
extern void ai_setint(struct si_pub *sih, int siflag);
extern uint ai_coreidx(struct si_pub *sih);
extern uint ai_corevendor(struct si_pub *sih);
extern uint ai_corerev(struct si_pub *sih);
extern bool ai_iscoreup(struct si_pub *sih);
-extern void *ai_setcoreidx(struct si_pub *sih, uint coreidx);
extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val);
extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
@@ -515,12 +318,8 @@ extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx);
extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val);
/* === exported functions === */
-extern struct si_pub *ai_attach(void *regs, uint bustype,
- void *sdh, char **vars, uint *varsz);
-
+extern struct si_pub *ai_attach(void __iomem *regs, struct pci_dev *sdh);
extern void ai_detach(struct si_pub *sih);
-extern bool ai_pci_war16165(struct si_pub *sih);
-
extern uint ai_coreid(struct si_pub *sih);
extern uint ai_corerev(struct si_pub *sih);
extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
@@ -530,10 +329,10 @@ extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
extern bool ai_iscoreup(struct si_pub *sih);
extern uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit);
-extern void *ai_setcoreidx(struct si_pub *sih, uint coreidx);
-extern void *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit);
-extern void *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
- uint *intr_val);
+extern void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx);
+extern void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit);
+extern void __iomem *ai_switch_core(struct si_pub *sih, uint coreid,
+ uint *origidx, uint *intr_val);
extern void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val);
extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits);
extern void ai_core_disable(struct si_pub *sih, u32 bits);
@@ -566,9 +365,6 @@ extern bool ai_is_sprom_available(struct si_pub *sih);
* Return 0 on success, nonzero otherwise.
*/
extern int ai_devpath(struct si_pub *sih, char *path, int size);
-/* Read variable with prepending the devpath to the name */
-extern char *ai_getdevpathvar(struct si_pub *sih, const char *name);
-extern int ai_getdevpathintvar(struct si_pub *sih, const char *name);
extern void ai_pci_sleep(struct si_pub *sih);
extern void ai_pci_down(struct si_pub *sih);
@@ -579,6 +375,4 @@ extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on);
/* Enable Ex-PA for 4313 */
extern void ai_epa_4313war(struct si_pub *sih);
-char *ai_getnvramflvar(struct si_pub *sih, const char *name);
-
#endif /* _BRCM_AIUTILS_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index fcaf61e3b134..7f27dbdb6b60 100644
--- a/drivers/staging/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -22,19 +22,32 @@
#include "main.h"
#include "ampdu.h"
-#define AMPDU_MAX_MPDU 32 /* max number of mpdus in an ampdu */
-#define AMPDU_NUM_MPDU_LEGACY 16 /* max number of mpdus in an ampdu to a legacy */
-#define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
-#define AMPDU_TX_BA_DEF_WSIZE 64 /* default Tx ba window size (in pdu) */
-#define AMPDU_RX_BA_DEF_WSIZE 64 /* max Rx ba window size (in pdu) */
-#define AMPDU_RX_BA_MAX_WSIZE 64 /* default Rx ba window size (in pdu) */
-#define AMPDU_MAX_DUR 5 /* max dur of tx ampdu (in msec) */
-#define AMPDU_DEF_RETRY_LIMIT 5 /* default tx retry limit */
-#define AMPDU_DEF_RR_RETRY_LIMIT 2 /* default tx retry limit at reg rate */
-#define AMPDU_DEF_TXPKT_WEIGHT 2 /* default weight of ampdu in txfifo */
-#define AMPDU_DEF_FFPLD_RSVD 2048 /* default ffpld reserved bytes */
-#define AMPDU_INI_FREE 10 /* # of inis to be freed on detach */
-#define AMPDU_SCB_MAX_RELEASE 20 /* max # of mpdus released at a time */
+/* max number of mpdus in an ampdu */
+#define AMPDU_MAX_MPDU 32
+/* max number of mpdus in an ampdu to a legacy */
+#define AMPDU_NUM_MPDU_LEGACY 16
+/* max Tx ba window size (in pdu) */
+#define AMPDU_TX_BA_MAX_WSIZE 64
+/* default Tx ba window size (in pdu) */
+#define AMPDU_TX_BA_DEF_WSIZE 64
+/* default Rx ba window size (in pdu) */
+#define AMPDU_RX_BA_DEF_WSIZE 64
+/* max Rx ba window size (in pdu) */
+#define AMPDU_RX_BA_MAX_WSIZE 64
+/* max dur of tx ampdu (in msec) */
+#define AMPDU_MAX_DUR 5
+/* default tx retry limit */
+#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 */
+#define AMPDU_INI_FREE 10
+/* max # of mpdus released at a time */
+#define AMPDU_SCB_MAX_RELEASE 20
#define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */
#define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu
@@ -47,6 +60,11 @@
* accumulate between resets.
*/
+#define AMPDU_DELIMITER_LEN 4
+
+/* max allowed number of mpdus in an ampdu (2 streams) */
+#define AMPDU_NUM_MPDU 16
+
#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
@@ -54,49 +72,77 @@
AMPDU_DELIMITER_LEN + 3\
+ DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
+/* modulo add/sub, bound = 2^k */
+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
+
/* structure to hold tx fifo information and pre-loading state
* counters specific to tx underflows of ampdus
* some counters might be redundant with the ones in wlc or ampdu structures.
* This allows to maintain a specific state independently of
* how often and/or when the wlc counters are updated.
+ *
+ * ampdu_pld_size: number of bytes to be pre-loaded
+ * mcs2ampdu_table: per-mcs max # of mpdus in an ampdu
+ * prev_txfunfl: num of underflows last read from the HW macstats counter
+ * accum_txfunfl: num of underflows since we modified pld params
+ * accum_txampdu: num of tx ampdu since we modified pld params
+ * prev_txampdu: previous reading of tx ampdu
+ * dmaxferrate: estimated dma avg xfer rate in kbits/sec
*/
struct brcms_fifo_info {
- u16 ampdu_pld_size; /* number of bytes to be pre-loaded */
- u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; /* per-mcs max # of mpdus in an ampdu */
- u16 prev_txfunfl; /* num of underflows last read from the HW macstats counter */
- u32 accum_txfunfl; /* num of underflows since we modified pld params */
- u32 accum_txampdu; /* num of tx ampdu since we modified pld params */
- u32 prev_txampdu; /* previous reading of tx ampdu */
- u32 dmaxferrate; /* estimated dma avg xfer rate in kbits/sec */
+ u16 ampdu_pld_size;
+ u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];
+ u16 prev_txfunfl;
+ u32 accum_txfunfl;
+ u32 accum_txampdu;
+ u32 prev_txampdu;
+ u32 dmaxferrate;
};
-/* AMPDU module specific state */
+/* AMPDU module specific state
+ *
+ * wlc: pointer to main wlc structure
+ * scb_handle: scb cubby handle to retrieve data from scb
+ * ini_enable: per-tid initiator enable/disable of ampdu
+ * ba_tx_wsize: Tx ba window size (in pdu)
+ * ba_rx_wsize: Rx ba window size (in pdu)
+ * retry_limit: mpdu transmit retry limit
+ * rr_retry_limit: mpdu transmit retry limit at regular rate
+ * retry_limit_tid: per-tid mpdu transmit retry limit
+ * rr_retry_limit_tid: per-tid mpdu transmit retry limit at regular rate
+ * 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
+ * mfbr: enable multiple fallback rate
+ * tx_max_funl: underflows should be kept such that
+ * (tx_max_funfl*underflows) < tx frames
+ * fifo_tb: table of fifo infos
+ */
struct ampdu_info {
- struct brcms_c_info *wlc; /* pointer to main wlc structure */
- int scb_handle; /* scb cubby handle to retrieve data from scb */
- u8 ini_enable[AMPDU_MAX_SCB_TID]; /* per-tid initiator enable/disable of ampdu */
- u8 ba_tx_wsize; /* Tx ba window size (in pdu) */
- u8 ba_rx_wsize; /* Rx ba window size (in pdu) */
- u8 retry_limit; /* mpdu transmit retry limit */
- u8 rr_retry_limit; /* mpdu transmit retry limit at regular rate */
- u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; /* per-tid mpdu transmit retry limit */
- /* per-tid mpdu transmit retry limit at regular rate */
+ struct brcms_c_info *wlc;
+ int scb_handle;
+ u8 ini_enable[AMPDU_MAX_SCB_TID];
+ u8 ba_tx_wsize;
+ u8 ba_rx_wsize;
+ u8 retry_limit;
+ u8 rr_retry_limit;
+ u8 retry_limit_tid[AMPDU_MAX_SCB_TID];
u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
- u8 mpdu_density; /* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
- s8 max_pdu; /* max pdus allowed in ampdu */
- u8 dur; /* max duration of an ampdu (in msec) */
- u8 txpkt_weight; /* weight of ampdu in txfifo; reduces rate lag */
- u8 rx_factor; /* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
- u32 ffpld_rsvd; /* number of bytes to reserve for preload */
- u32 max_txlen[MCS_TABLE_SIZE][2][2]; /* max size of ampdu per mcs, bw and sgi */
- void *ini_free[AMPDU_INI_FREE]; /* array of ini's to be freed on detach */
- bool mfbr; /* enable multiple fallback rate */
- u32 tx_max_funl; /* underflows should be kept such that
- * (tx_max_funfl*underflows) < tx frames
- */
- /* table of fifo infos */
+ 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];
+ bool mfbr;
+ u32 tx_max_funl;
struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO];
-
};
/* used for flushing ampdu packets */
@@ -105,32 +151,75 @@ struct cb_del_ampdu_pars {
u16 tid;
};
-#define AMPDU_CLEANUPFLAG_RX (0x1)
-#define AMPDU_CLEANUPFLAG_TX (0x2)
+static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
+{
+ u32 rate, mcs;
-#define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
-#define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
+ for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
+ /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
+ /* 20MHz, No SGI */
+ rate = mcs_2_rate(mcs, false, false);
+ ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
+ /* 40 MHz, No SGI */
+ rate = mcs_2_rate(mcs, true, false);
+ ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
+ /* 20MHz, SGI */
+ rate = mcs_2_rate(mcs, false, true);
+ ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
+ /* 40 MHz, SGI */
+ rate = mcs_2_rate(mcs, true, true);
+ ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
+ }
+}
-static void brcms_c_ffpld_init(struct ampdu_info *ampdu);
-static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int f);
-static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
+static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
+{
+ if (BRCMS_PHY_11N_CAP(ampdu->wlc->band))
+ return true;
+ else
+ return false;
+}
-static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu,
- u8 dur);
-static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
- struct scb *scb);
-static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu);
+static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
+{
+ struct brcms_c_info *wlc = ampdu->wlc;
-#define brcms_c_ampdu_txflowcontrol(a, b, c) do {} while (0)
+ wlc->pub->_ampdu = false;
-static void
-brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
- struct scb *scb,
- struct sk_buff *p, struct tx_status *txs,
- u32 frmtxstatus, u32 frmtxstatus2);
+ if (on) {
+ if (!(wlc->pub->_n_enab & SUPPORT_11N)) {
+ wiphy_err(ampdu->wlc->wiphy, "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);
+ return -ENOTSUPP;
+ }
+ wlc->pub->_ampdu = on;
+ }
+
+ return 0;
+}
+
+static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
+{
+ int i, j;
+ struct brcms_fifo_info *fifo;
+
+ for (j = 0; j < NUM_FFPLD_FIFO; j++) {
+ fifo = (ampdu->fifo_tb + j);
+ fifo->ampdu_pld_size = 0;
+ for (i = 0; i <= FFPLD_MAX_MCS; i++)
+ fifo->mcs2ampdu_table[i] = 255;
+ fifo->dmaxferrate = 0;
+ fifo->accum_txampdu = 0;
+ fifo->prev_txfunfl = 0;
+ fifo->accum_txfunfl = 0;
-static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu);
-static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on);
+ }
+}
struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
{
@@ -138,11 +227,9 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
int i;
ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
- if (!ampdu) {
- wiphy_err(wlc->wiphy, "wl%d: brcms_c_ampdu_attach: out of mem"
- "\n", wlc->pub->unit);
+ if (!ampdu)
return NULL;
- }
+
ampdu->wlc = wlc;
for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
@@ -163,7 +250,10 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
- /* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
+ /*
+ * bump max ampdu rcv size to 64k for all 11n
+ * devices except 4321A0 and 4321A1
+ */
if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
else
@@ -189,27 +279,16 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
void brcms_c_ampdu_detach(struct ampdu_info *ampdu)
{
- int i;
-
- if (!ampdu)
- return;
-
- /* free all ini's which were to be freed on callbacks which were never called */
- for (i = 0; i < AMPDU_INI_FREE; i++) {
- kfree(ampdu->ini_free[i]);
- }
-
- brcms_c_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
kfree(ampdu);
}
static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
struct scb *scb)
{
- struct scb_ampdu *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+ struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
int i;
- scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
+ scb_ampdu->max_pdu = AMPDU_NUM_MPDU;
/* go back to legacy size if some preloading is occurring */
for (i = 0; i < NUM_FFPLD_FIFO; i++) {
@@ -221,7 +300,8 @@ static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
if (ampdu->max_pdu != AUTO)
scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
- scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
+ scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu,
+ AMPDU_SCB_MAX_RELEASE);
if (scb_ampdu->max_rx_ampdu_bytes)
scb_ampdu->release = min_t(u8, scb_ampdu->release,
@@ -234,24 +314,38 @@ static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu)
{
- brcms_c_scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
+ brcms_c_scb_ampdu_update_config(ampdu, &ampdu->wlc->pri_scb);
}
-static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
+static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
{
- int i, j;
- struct brcms_fifo_info *fifo;
+ int i;
+ u32 phy_rate, dma_rate, tmp;
+ u8 max_mpdu;
+ struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f);
- for (j = 0; j < NUM_FFPLD_FIFO; j++) {
- fifo = (ampdu->fifo_tb + j);
- fifo->ampdu_pld_size = 0;
- for (i = 0; i <= FFPLD_MAX_MCS; i++)
- fifo->mcs2ampdu_table[i] = 255;
- fifo->dmaxferrate = 0;
- fifo->accum_txampdu = 0;
- fifo->prev_txfunfl = 0;
- fifo->accum_txfunfl = 0;
+ /* recompute the dma rate */
+ /* note : we divide/multiply by 100 to avoid integer overflows */
+ max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
+ AMPDU_NUM_MPDU_LEGACY);
+ phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
+ dma_rate =
+ (((phy_rate / 100) *
+ (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
+ / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
+ fifo->dmaxferrate = dma_rate;
+ /* fill up the mcs2ampdu table; do not recalc the last mcs */
+ dma_rate = dma_rate >> 7;
+ for (i = 0; i < FFPLD_MAX_MCS; i++) {
+ /* shifting to keep it within integer range */
+ phy_rate = mcs_2_rate(i, true, false) >> 7;
+ if (phy_rate > dma_rate) {
+ tmp = ((fifo->ampdu_pld_size * phy_rate) /
+ ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
+ tmp = min_t(u32, tmp, 255);
+ fifo->mcs2ampdu_table[i] = (u8) tmp;
+ }
}
}
@@ -264,7 +358,7 @@ static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
{
struct ampdu_info *ampdu = wlc->ampdu;
- u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
+ u32 phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
u32 txunfl_ratio;
u8 max_mpdu;
u32 current_ampdu_cnt = 0;
@@ -275,7 +369,7 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
u16 cur_txunfl;
/* return if we got here for a different reason than underflows */
- cur_txunfl = brcms_c_read_shm(wlc,
+ cur_txunfl = brcms_b_read_shm(wlc->hw,
M_UCODE_MACSTAT +
offsetof(struct macstat, txfunfl[fid]));
new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
@@ -289,7 +383,7 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
return 1;
/* check if fifo is big enough */
- if (brcms_c_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz))
+ if (brcms_b_xmtfifo_sz_get(wlc->hw, fid, &xmtfifo_sz))
return -1;
if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
@@ -317,13 +411,13 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
if (txunfl_ratio > ampdu->tx_max_funl) {
- if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
+ if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT)
fifo->accum_txfunfl = 0;
- }
+
return 0;
}
- max_mpdu =
- min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
+ max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
+ AMPDU_NUM_MPDU_LEGACY);
/* In case max value max_pdu is already lower than
the fifo depth, there is nothing more we can do.
@@ -345,11 +439,12 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
brcms_c_scb_ampdu_update_config_all(ampdu);
/*
- compute a new dma xfer rate for max_mpdu @ max mcs.
- This is the minimum dma rate that
- can achieve no underflow condition for the current mpdu size.
+ * compute a new dma xfer rate for max_mpdu @ max mcs.
+ * This is the minimum dma rate that can achieve no
+ * underflow condition for the current mpdu size.
+ *
+ * note : we divide/multiply by 100 to avoid integer overflows
*/
- /* note : we divide/multiply by 100 to avoid integer overflows */
fifo->dmaxferrate =
(((phy_rate / 100) *
(max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
@@ -379,38 +474,6 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
return 0;
}
-static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
-{
- int i;
- u32 phy_rate, dma_rate, tmp;
- u8 max_mpdu;
- struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f);
-
- /* recompute the dma rate */
- /* note : we divide/multiply by 100 to avoid integer overflows */
- max_mpdu =
- min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
- phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
- dma_rate =
- (((phy_rate / 100) *
- (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
- / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
- fifo->dmaxferrate = dma_rate;
-
- /* fill up the mcs2ampdu table; do not recalc the last mcs */
- dma_rate = dma_rate >> 7;
- for (i = 0; i < FFPLD_MAX_MCS; i++) {
- /* shifting to keep it within integer range */
- phy_rate = MCS_RATE(i, true, false) >> 7;
- if (phy_rate > dma_rate) {
- tmp = ((fifo->ampdu_pld_size * phy_rate) /
- ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
- tmp = min_t(u32, tmp, 255);
- fifo->mcs2ampdu_table[i] = (u8) tmp;
- }
- }
-}
-
void
brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
u8 ba_wsize, /* negotiated ba window size (in pdu) */
@@ -419,8 +482,8 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
struct scb_ampdu *scb_ampdu;
struct scb_ampdu_tid_ini *ini;
struct ampdu_info *ampdu = wlc->ampdu;
- struct scb *scb = wlc->pub->global_scb;
- scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+ struct scb *scb = &wlc->pri_scb;
+ scb_ampdu = &scb->scb_ampdu;
if (!ampdu->ini_enable[tid]) {
wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
@@ -428,7 +491,7 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
return;
}
- ini = SCB_AMPDU_INI(scb_ampdu, tid);
+ ini = &scb_ampdu->ini[tid];
ini->tid = tid;
ini->scb = scb_ampdu->scb;
ini->ba_wsize = ba_wsize;
@@ -460,8 +523,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
struct scb_ampdu_tid_ini *ini;
u8 mcs = 0;
bool use_rts = false, use_cts = false;
- ratespec_t rspec = 0, rspec_fallback = 0;
- ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
+ 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;
@@ -479,17 +542,16 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
f = ampdu->fifo_tb + prio2fifo[tid];
- scb = wlc->pub->global_scb;
- scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+ scb = &wlc->pri_scb;
+ scb_ampdu = &scb->scb_ampdu;
ini = &scb_ampdu->ini[tid];
/* 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)) {
+ qlen < min(scb_ampdu->max_pdu, ini->ba_wsize))
/* Collect multiple MPDU's to be sent in the next AMPDU */
return -EBUSY;
- }
/* at this point we intend to transmit an AMPDU */
rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
@@ -614,7 +676,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
}
is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
- sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
+ sgi = plcp3_issgi(plcp3) ? 1 : 0;
mcs = plcp0 & ~MIMO_PLCP_40MHZ;
max_ampdu_bytes =
min(scb_ampdu->max_rx_ampdu_bytes,
@@ -622,7 +684,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
if (is40)
mimo_ctlchbw =
- CHSPEC_SB_UPPER(BRCMS_BAND_PI_RADIO_CHANSPEC)
+ 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 */
@@ -632,9 +695,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
if (fbr_iscck) /* CCK */
- rspec_fallback =
- CCK_RSPEC(CCK_PHY2MAC_RATE
- (txh->FragPLCPFallback[0]));
+ rspec_fallback = cck_rspec(cck_phy2mac_rate
+ (txh->FragPLCPFallback[0]));
else { /* MIMO */
rspec_fallback = RSPEC_MIMORATE;
rspec_fallback |=
@@ -657,7 +719,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
/* if (first mpdu for host agg) */
/* test whether to add more */
- if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
+ 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",
@@ -665,13 +727,16 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
break;
}
- if (count == scb_ampdu->max_pdu) {
+ if (count == scb_ampdu->max_pdu)
break;
- }
- /* check to see if the next pkt is a candidate for aggregation */
+ /*
+ * check to see if the next pkt is
+ * a candidate for aggregation
+ */
p = pktq_ppeek(&qi->q, prec);
- tx_info = IEEE80211_SKB_CB(p); /* tx_info must be checked with current p */
+ /* tx_info must be checked with current p */
+ tx_info = IEEE80211_SKB_CB(p);
if (p) {
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
@@ -686,8 +751,11 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
continue;
}
- /* check if there are enough descriptors available */
- if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
+ /*
+ * 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;
@@ -745,7 +813,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
}
/* set the preload length */
- if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
+ 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
@@ -797,10 +865,10 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
/* inform rate_sel if it this is a rate probe pkt */
frameid = le16_to_cpu(txh->TxFrameID);
- if (frameid & TXFID_RATE_PROBE_MASK) {
+ 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);
@@ -810,62 +878,6 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
return err;
}
-void
-brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
- struct sk_buff *p, struct tx_status *txs)
-{
- struct scb_ampdu *scb_ampdu;
- struct brcms_c_info *wlc = ampdu->wlc;
- struct scb_ampdu_tid_ini *ini;
- u32 s1 = 0, s2 = 0;
- struct ieee80211_tx_info *tx_info;
-
- tx_info = IEEE80211_SKB_CB(p);
-
- /* BMAC_NOTE: For the split driver, second level txstatus comes later
- * So if the ACK was received then wait for the second level else just
- * call the first one
- */
- if (txs->status & TX_STATUS_ACK_RCV) {
- u8 status_delay = 0;
-
- /* wait till the next 8 bytes of txstatus is available */
- while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
- udelay(1);
- status_delay++;
- if (status_delay > 10) {
- return; /* error condition */
- }
- }
-
- s2 = R_REG(&wlc->regs->frmtxstatus2);
- }
-
- if (likely(scb)) {
- scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
- ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
- brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
- } else {
- /* loop through all pkts and free */
- u8 queue = txs->frameid & TXFID_QUEUE_MASK;
- struct d11txh *txh;
- u16 mcl;
- while (p) {
- tx_info = IEEE80211_SKB_CB(p);
- txh = (struct d11txh *) p->data;
- mcl = le16_to_cpu(txh->MacTxControlLow);
- brcmu_pkt_buf_free_skb(p);
- /* break out if last packet of ampdu */
- if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
- TXC_AMPDU_LAST)
- break;
- p = GETNEXTTXP(wlc, queue);
- }
- brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
- }
- brcms_c_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
-}
-
static void
brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
struct ieee80211_tx_info *tx_info,
@@ -881,8 +893,6 @@ brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
}
}
-#define SHORTNAME "AMPDU status"
-
static void
brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
struct sk_buff *p, struct tx_status *txs,
@@ -912,10 +922,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
memset(hole, 0, sizeof(hole));
#endif
- scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+ scb_ampdu = &scb->scb_ampdu;
tid = (u8) (p->priority);
- ini = SCB_AMPDU_INI(scb_ampdu, tid);
+ ini = &scb_ampdu->ini[tid];
retry_limit = ampdu->retry_limit_tid[tid];
rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
memset(bitmap, 0, sizeof(bitmap));
@@ -923,9 +933,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
supr_status = txs->status & TX_STATUS_SUPR_MASK;
if (txs->status & TX_STATUS_ACK_RCV) {
- if (TX_STATUS_SUPR_UF == supr_status) {
+ if (TX_STATUS_SUPR_UF == supr_status)
update_rate = false;
- }
WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
start_seq = txs->sequence >> SEQNUM_SHIFT;
@@ -967,15 +976,17 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
supr_status == TX_STATUS_SUPR_EXPTIME) {
retry = false;
} else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
- /* TX underflow : try tuning pre-loading or ampdu size */
+ /* TX underflow:
+ * try tuning pre-loading or ampdu size
+ */
} else if (supr_status == TX_STATUS_SUPR_FRAG) {
- /* if there were underflows, but pre-loading is not active,
- notify rate adaptation.
+ /*
+ * if there were underflows, but pre-loading
+ * is not active, notify rate adaptation.
*/
if (brcms_c_ffpld_check_txfunfl(wlc,
- prio2fifo[tid]) > 0) {
+ prio2fifo[tid]) > 0)
tx_error = true;
- }
}
} else if (txs->phyerr) {
update_rate = false;
@@ -983,7 +994,7 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
"error (0x%x)\n", wlc->pub->unit,
txs->phyerr);
- if (WL_ERROR_ON()) {
+ if (brcm_msg_level & LOG_ERROR_VAL) {
brcmu_prpkt("txpkt (AMPDU)", p);
brcms_c_print_txdesc((struct d11txh *) p->data);
}
@@ -1019,7 +1030,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
ini->tx_in_transit--;
ini->txretry[index] = 0;
- /* ampdu_ack_len: number of acked aggregated frames */
+ /*
+ * ampdu_ack_len:
+ * number of acked aggregated frames
+ */
/* ampdu_len: number of aggregated frames */
brcms_c_ampdu_rate_status(wlc, tx_info, txs,
mcs);
@@ -1044,11 +1058,14 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
if (retry && (txrate[0].count < (int)retry_limit)) {
ini->txretry[index]++;
ini->tx_in_transit--;
- /* Use high prededence for retransmit to give some punch */
+ /*
+ * Use high prededence for retransmit to
+ * give some punch
+ */
/* brcms_c_txq_enq(wlc, scb, p,
* BRCMS_PRIO_TO_PREC(tid)); */
brcms_c_txq_enq(wlc, scb, p,
- BRCMS_PRIO_TO_HI_PREC(tid));
+ BRCMS_PRIO_TO_HI_PREC(tid));
} else {
/* Retry timeout */
ini->tx_in_transit--;
@@ -1060,7 +1077,7 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
skb_pull(p, D11_PHY_HDR_LEN);
skb_pull(p, D11_TXH_LEN);
wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
- "transit %d\n", SHORTNAME, seq,
+ "transit %d\n", "AMPDU status", seq,
ini->tx_in_transit);
ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
p);
@@ -1073,7 +1090,7 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
TXC_AMPDU_LAST)
break;
- p = GETNEXTTXP(wlc, queue);
+ p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
}
brcms_c_send_q(wlc);
@@ -1083,55 +1100,58 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
}
-static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
+void
+brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
+ struct sk_buff *p, struct tx_status *txs)
{
+ struct scb_ampdu *scb_ampdu;
struct brcms_c_info *wlc = ampdu->wlc;
+ struct scb_ampdu_tid_ini *ini;
+ u32 s1 = 0, s2 = 0;
+ struct ieee80211_tx_info *tx_info;
- wlc->pub->_ampdu = false;
-
- if (on) {
- if (!N_ENAB(wlc->pub)) {
- wiphy_err(ampdu->wlc->wiphy, "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);
- return -ENOTSUPP;
- }
- wlc->pub->_ampdu = on;
- }
+ tx_info = IEEE80211_SKB_CB(p);
- return 0;
-}
+ /* BMAC_NOTE: For the split driver, second level txstatus comes later
+ * So if the ACK was received then wait for the second level else just
+ * call the first one
+ */
+ if (txs->status & TX_STATUS_ACK_RCV) {
+ u8 status_delay = 0;
-static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
-{
- if (BRCMS_PHY_11N_CAP(ampdu->wlc->band))
- return true;
- else
- return false;
-}
+ /* wait till the next 8 bytes of txstatus is available */
+ while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
+ udelay(1);
+ status_delay++;
+ if (status_delay > 10)
+ return; /* error condition */
+ }
-static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
-{
- u32 rate, mcs;
+ s2 = R_REG(&wlc->regs->frmtxstatus2);
+ }
- for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
- /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
- /* 20MHz, No SGI */
- rate = MCS_RATE(mcs, false, false);
- ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
- /* 40 MHz, No SGI */
- rate = MCS_RATE(mcs, true, false);
- ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
- /* 20MHz, SGI */
- rate = MCS_RATE(mcs, false, true);
- ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
- /* 40 MHz, SGI */
- rate = MCS_RATE(mcs, true, true);
- ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
+ if (scb) {
+ scb_ampdu = &scb->scb_ampdu;
+ ini = &scb_ampdu->ini[p->priority];
+ brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
+ } else {
+ /* loop through all pkts and free */
+ u8 queue = txs->frameid & TXFID_QUEUE_MASK;
+ struct d11txh *txh;
+ u16 mcl;
+ while (p) {
+ tx_info = IEEE80211_SKB_CB(p);
+ txh = (struct d11txh *) p->data;
+ mcl = le16_to_cpu(txh->MacTxControlLow);
+ brcmu_pkt_buf_free_skb(p);
+ /* break out if last packet of ampdu */
+ if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
+ TXC_AMPDU_LAST)
+ break;
+ p = dma_getnexttxp(wlc->hw->di[queue],
+ DMA_RANGE_TRANSMITTED);
+ }
+ brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
}
}
@@ -1142,7 +1162,7 @@ void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
/* driver needs to write the ta in the template; ta is at offset 16 */
memset(template, 0, sizeof(template));
memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
- brcms_c_write_template_ram(wlc, (T_BA_TPL_BASE + 16),
+ brcms_b_write_template_ram(wlc->hw, (T_BA_TPL_BASE + 16),
(T_RAM_ACCESS_SZ * 2),
template);
}
@@ -1156,14 +1176,17 @@ void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
{
struct brcms_c_info *wlc = ampdu->wlc;
- /* Extend ucode internal watchdog timer to match larger received frames */
+ /*
+ * Extend ucode internal watchdog timer to
+ * match larger received frames
+ */
if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
IEEE80211_HT_MAX_AMPDU_64K) {
- brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
- brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
+ brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
+ brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
} else {
- brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
- brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
+ brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
+ brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
}
}
@@ -1211,9 +1234,8 @@ void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
ampdu_pars.sta = sta;
ampdu_pars.tid = tid;
- for (prec = 0; prec < pq->num_prec; prec++) {
+ for (prec = 0; prec < pq->num_prec; prec++)
brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
(void *)&ampdu_pars);
- }
brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
}
diff --git a/drivers/staging/brcm80211/brcmsmac/ampdu.h b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
index 421f4ba7c63c..421f4ba7c63c 100644
--- a/drivers/staging/brcm80211/brcmsmac/ampdu.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
diff --git a/drivers/staging/brcm80211/brcmsmac/antsel.c b/drivers/net/wireless/brcm80211/brcmsmac/antsel.c
index c4e76c093ae9..a47ce25cb9a2 100644
--- a/drivers/staging/brcm80211/brcmsmac/antsel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/antsel.c
@@ -18,7 +18,6 @@
#include <net/mac80211.h>
#include "types.h"
-#include "bmac.h"
#include "main.h"
#include "phy_shim.h"
#include "antsel.h"
@@ -50,55 +49,76 @@
#define ANT_SELCFG_NUM_2x4 4
#define ANT_SELCFG_DEF_2x4 0x02 /* default antenna configuration */
-/* static functions */
-static int brcms_c_antsel_cfgupd(struct antsel_info *asi,
- struct brcms_antselcfg *antsel);
-static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id);
-static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg);
-static void brcms_c_antsel_init_cfg(struct antsel_info *asi,
- struct brcms_antselcfg *antsel,
- bool auto_sel);
-
-const u16 mimo_2x4_div_antselpat_tbl[] = {
+static const u16 mimo_2x4_div_antselpat_tbl[] = {
0, 0, 0x9, 0xa, /* ant0: 0 ant1: 2,3 */
0, 0, 0x5, 0x6, /* ant0: 1 ant1: 2,3 */
0, 0, 0, 0, /* n.a. */
0, 0, 0, 0 /* n.a. */
};
-const u8 mimo_2x4_div_antselid_tbl[16] = {
+static const u8 mimo_2x4_div_antselid_tbl[16] = {
0, 0, 0, 0, 0, 2, 3, 0,
0, 0, 1, 0, 0, 0, 0, 0 /* pat to antselid */
};
-const u16 mimo_2x3_div_antselpat_tbl[] = {
+static const u16 mimo_2x3_div_antselpat_tbl[] = {
16, 0, 1, 16, /* ant0: 0 ant1: 1,2 */
16, 16, 16, 16, /* n.a. */
16, 2, 16, 16, /* ant0: 2 ant1: 1 */
16, 16, 16, 16 /* n.a. */
};
-const u8 mimo_2x3_div_antselid_tbl[16] = {
+static const u8 mimo_2x3_div_antselid_tbl[16] = {
0, 1, 2, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 /* pat to antselid */
};
+/* boardlevel antenna selection: init antenna selection structure */
+static void
+brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel,
+ bool auto_sel)
+{
+ if (asi->antsel_type == ANTSEL_2x3) {
+ u8 antcfg_def = ANT_SELCFG_DEF_2x3 |
+ ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0);
+ antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def;
+ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def;
+ antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def;
+ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def;
+ antsel->num_antcfg = ANT_SELCFG_NUM_2x3;
+
+ } else if (asi->antsel_type == ANTSEL_2x4) {
+
+ antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4;
+ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4;
+ antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4;
+ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4;
+ antsel->num_antcfg = ANT_SELCFG_NUM_2x4;
+
+ } else { /* no antenna selection available */
+
+ antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2;
+ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2;
+ antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2;
+ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2;
+ antsel->num_antcfg = 0;
+ }
+}
+
struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
{
struct antsel_info *asi;
+ struct si_pub *sih = wlc->hw->sih;
asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC);
- if (!asi) {
- wiphy_err(wlc->wiphy, "wl%d: brcms_c_antsel_attach: out of "
- "mem\n", wlc->pub->unit);
+ if (!asi)
return NULL;
- }
asi->wlc = wlc;
asi->pub = wlc->pub;
asi->antsel_type = ANTSEL_NA;
asi->antsel_avail = false;
- asi->antsel_antswitch = (u8) getintvar(asi->pub->vars, "antswitch");
+ asi->antsel_antswitch = (u8) getintvar(sih, BRCMS_SROM_ANTSWITCH);
if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) {
switch (asi->antsel_antswitch) {
@@ -108,27 +128,26 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
/* 4321/2 board with 2x3 switch logic */
asi->antsel_type = ANTSEL_2x3;
/* Antenna selection availability */
- if (((u16) getintvar(asi->pub->vars, "aa2g") == 7) ||
- ((u16) getintvar(asi->pub->vars, "aa5g") == 7)) {
+ if (((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) ||
+ ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 7)) {
asi->antsel_avail = true;
- } else
- if (((u16) getintvar(asi->pub->vars, "aa2g") ==
- 3)
- || ((u16) getintvar(asi->pub->vars, "aa5g")
- == 3)) {
+ } else if (
+ (u16) getintvar(sih, BRCMS_SROM_AA2G) == 3 ||
+ (u16) getintvar(sih, BRCMS_SROM_AA5G) == 3) {
asi->antsel_avail = false;
} else {
asi->antsel_avail = false;
wiphy_err(wlc->wiphy, "antsel_attach: 2o3 "
"board cfg invalid\n");
}
+
break;
default:
break;
}
} else if ((asi->pub->sromrev == 4) &&
- ((u16) getintvar(asi->pub->vars, "aa2g") == 7) &&
- ((u16) getintvar(asi->pub->vars, "aa5g") == 0)) {
+ ((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) &&
+ ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 0)) {
/* hack to match old 4321CB2 cards with 2of3 antenna switch */
asi->antsel_type = ANTSEL_2x3;
asi->antsel_avail = true;
@@ -152,6 +171,64 @@ void brcms_c_antsel_detach(struct antsel_info *asi)
kfree(asi);
}
+/*
+ * boardlevel antenna selection:
+ * convert ant_cfg to mimo_antsel (ucode interface)
+ */
+static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg)
+{
+ u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg));
+ u16 mimo_antsel = 0;
+
+ if (asi->antsel_type == ANTSEL_2x4) {
+ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+ mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf);
+ return mimo_antsel;
+
+ } else if (asi->antsel_type == ANTSEL_2x3) {
+ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+ mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf);
+ return mimo_antsel;
+ }
+
+ return mimo_antsel;
+}
+
+/* boardlevel antenna selection: ucode interface control */
+static int brcms_c_antsel_cfgupd(struct antsel_info *asi,
+ struct brcms_antselcfg *antsel)
+{
+ struct brcms_c_info *wlc = asi->wlc;
+ u8 ant_cfg;
+ u16 mimo_antsel;
+
+ /* 1) Update TX antconfig for all frames that are not unicast data
+ * (aka default TX)
+ */
+ ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF];
+ mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
+ brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_TXDFLT, mimo_antsel);
+ /*
+ * Update driver stats for currently selected
+ * default tx/rx antenna config
+ */
+ asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg;
+
+ /* 2) Update RX antconfig for all frames that are not unicast data
+ * (aka default RX)
+ */
+ ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF];
+ mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
+ brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_RXDFLT, mimo_antsel);
+ /*
+ * Update driver stats for currently selected
+ * default tx/rx antenna config
+ */
+ asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg;
+
+ return 0;
+}
+
void brcms_c_antsel_init(struct antsel_info *asi)
{
if ((asi->antsel_type == ANTSEL_2x3) ||
@@ -159,36 +236,23 @@ void brcms_c_antsel_init(struct antsel_info *asi)
brcms_c_antsel_cfgupd(asi, &asi->antcfg_11n);
}
-/* boardlevel antenna selection: init antenna selection structure */
-static void
-brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel,
- bool auto_sel)
+/* boardlevel antenna selection: convert id to ant_cfg */
+static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id)
{
- if (asi->antsel_type == ANTSEL_2x3) {
- u8 antcfg_def = ANT_SELCFG_DEF_2x3 |
- ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0);
- antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def;
- antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def;
- antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def;
- antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def;
- antsel->num_antcfg = ANT_SELCFG_NUM_2x3;
-
- } else if (asi->antsel_type == ANTSEL_2x4) {
-
- antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4;
- antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4;
- antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4;
- antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4;
- antsel->num_antcfg = ANT_SELCFG_NUM_2x4;
+ u8 antcfg = ANT_SELCFG_DEF_2x2;
- } else { /* no antenna selection available */
+ if (asi->antsel_type == ANTSEL_2x4) {
+ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+ antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2));
+ return antcfg;
- antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2;
- antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2;
- antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2;
- antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2;
- antsel->num_antcfg = 0;
+ } else if (asi->antsel_type == ANTSEL_2x3) {
+ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+ antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1));
+ return antcfg;
}
+
+ return antcfg;
}
void
@@ -241,71 +305,3 @@ u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel)
return antselid;
}
-
-/* boardlevel antenna selection: convert id to ant_cfg */
-static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id)
-{
- u8 antcfg = ANT_SELCFG_DEF_2x2;
-
- if (asi->antsel_type == ANTSEL_2x4) {
- /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
- antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2));
- return antcfg;
-
- } else if (asi->antsel_type == ANTSEL_2x3) {
- /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
- antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1));
- return antcfg;
- }
-
- return antcfg;
-}
-
-/* boardlevel antenna selection: convert ant_cfg to mimo_antsel (ucode interface) */
-static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg)
-{
- u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg));
- u16 mimo_antsel = 0;
-
- if (asi->antsel_type == ANTSEL_2x4) {
- /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
- mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf);
- return mimo_antsel;
-
- } else if (asi->antsel_type == ANTSEL_2x3) {
- /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
- mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf);
- return mimo_antsel;
- }
-
- return mimo_antsel;
-}
-
-/* boardlevel antenna selection: ucode interface control */
-static int brcms_c_antsel_cfgupd(struct antsel_info *asi,
- struct brcms_antselcfg *antsel)
-{
- struct brcms_c_info *wlc = asi->wlc;
- u8 ant_cfg;
- u16 mimo_antsel;
-
- /* 1) Update TX antconfig for all frames that are not unicast data
- * (aka default TX)
- */
- ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF];
- mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
- brcms_c_write_shm(wlc, M_MIMO_ANTSEL_TXDFLT, mimo_antsel);
- /* Update driver stats for currently selected default tx/rx antenna config */
- asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg;
-
- /* 2) Update RX antconfig for all frames that are not unicast data
- * (aka default RX)
- */
- ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF];
- mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
- brcms_c_write_shm(wlc, M_MIMO_ANTSEL_RXDFLT, mimo_antsel);
- /* Update driver stats for currently selected default tx/rx antenna config */
- asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg;
-
- return 0;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/antsel.h b/drivers/net/wireless/brcm80211/brcmsmac/antsel.h
index 97ea3881a8ec..97ea3881a8ec 100644
--- a/drivers/staging/brcm80211/brcmsmac/antsel.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/antsel.h
diff --git a/drivers/staging/brcm80211/brcmsmac/alloc.h b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c
index f465d3043030..52fc9eeb5fa5 100644
--- a/drivers/staging/brcm80211/brcmsmac/alloc.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Broadcom Corporation
+ * Copyright (c) 2011 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
@@ -14,6 +14,10 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-extern struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err,
- uint devid);
-extern void brcms_c_detach_mfree(struct brcms_c_info *wlc);
+#include <linux/module.h> /* bug in tracepoint.h, it should include this */
+
+#ifndef __CHECKER__
+#include "mac80211_if.h"
+#define CREATE_TRACE_POINTS
+#include "brcms_trace_events.h"
+#endif
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h
new file mode 100644
index 000000000000..27dd73eef56d
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac
+
+#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ)
+
+#define __TRACE_BRCMSMAC_H
+
+#include <linux/tracepoint.h>
+#include "mac80211_if.h"
+
+#ifndef CONFIG_BRCMDBG
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#endif
+
+/*
+ * We define a tracepoint, its arguments, its printk format and its
+ * 'fast binary record' layout.
+ */
+TRACE_EVENT(brcms_timer,
+ /* TPPROTO is the prototype of the function called by this tracepoint */
+ TP_PROTO(struct brcms_timer *t),
+ /*
+ * TPARGS(firstarg, p) are the parameters names, same as found in the
+ * prototype.
+ */
+ TP_ARGS(t),
+ /*
+ * Fast binary tracing: define the trace record via TP_STRUCT__entry().
+ * You can think about it like a regular C structure local variable
+ * definition.
+ */
+ TP_STRUCT__entry(
+ __field(uint, ms)
+ __field(uint, set)
+ __field(uint, periodic)
+ ),
+ TP_fast_assign(
+ __entry->ms = t->ms;
+ __entry->set = t->set;
+ __entry->periodic = t->periodic;
+ ),
+ TP_printk(
+ "ms=%u set=%u periodic=%u",
+ __entry->ms, __entry->set, __entry->periodic
+ )
+);
+
+TRACE_EVENT(brcms_dpc,
+ TP_PROTO(unsigned long data),
+ TP_ARGS(data),
+ TP_STRUCT__entry(
+ __field(unsigned long, data)
+ ),
+ TP_fast_assign(
+ __entry->data = data;
+ ),
+ TP_printk(
+ "data=%p",
+ (void *)__entry->data
+ )
+);
+
+#endif /* __TRACE_BRCMSMAC_H */
+
+#ifdef CONFIG_BRCMDBG
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE brcms_trace_events
+
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCMDBG */
diff --git a/drivers/staging/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index f59693e1d8a2..89ad1b7dab8f 100644
--- a/drivers/staging/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -20,24 +20,138 @@
#include <defs.h>
#include "pub.h"
#include "phy/phy_hal.h"
-#include "bmac.h"
#include "main.h"
#include "stf.h"
#include "channel.h"
-#define VALID_CHANNEL20_DB(wlc, val) brcms_c_valid_channel20_db((wlc)->cmi, val)
-#define VALID_CHANNEL20_IN_BAND(wlc, bandunit, val) \
- brcms_c_valid_channel20_in_band((wlc)->cmi, bandunit, val)
-#define VALID_CHANNEL20(wlc, val) brcms_c_valid_channel20((wlc)->cmi, val)
+/* QDB() macro takes a dB value and converts to a quarter dB value */
+#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
+
+#define LOCALE_CHAN_01_11 (1<<0)
+#define LOCALE_CHAN_12_13 (1<<1)
+#define LOCALE_CHAN_14 (1<<2)
+#define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */
+#define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */
+#define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */
+#define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */
+#define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */
+#define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */
+#define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */
+#define LOCALE_SET_5G_MID3 (1<<10) /* 128 */
+#define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */
+#define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */
+#define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */
+#define LOCALE_CHAN_52_140_ALL (1<<14)
+#define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */
+
+#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \
+ LOCALE_SET_5G_LOW2 | \
+ LOCALE_SET_5G_LOW3)
+#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
+#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
+#define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \
+ LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
+#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
+#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4
+
+#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \
+ LOCALE_CHAN_12_13 | \
+ LOCALE_CHAN_14)
+
+#define LOCALE_RADAR_SET_NONE 0
+#define LOCALE_RADAR_SET_1 1
+
+#define LOCALE_RESTRICTED_NONE 0
+#define LOCALE_RESTRICTED_SET_2G_SHORT 1
+#define LOCALE_RESTRICTED_CHAN_165 2
+#define LOCALE_CHAN_ALL_5G 3
+#define LOCALE_RESTRICTED_JAPAN_LEGACY 4
+#define LOCALE_RESTRICTED_11D_2G 5
+#define LOCALE_RESTRICTED_11D_5G 6
+#define LOCALE_RESTRICTED_LOW_HI 7
+#define LOCALE_RESTRICTED_12_13_14 8
+
+#define LOCALE_2G_IDX_i 0
+#define LOCALE_5G_IDX_11 0
+#define LOCALE_MIMO_IDX_bn 0
+#define LOCALE_MIMO_IDX_11n 0
+
+/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
+#define BRCMS_MAXPWR_TBL_SIZE 6
+/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
+#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14
+
+/* power level in group of 2.4GHz band channels:
+ * maxpwr[0] - CCK channels [1]
+ * maxpwr[1] - CCK channels [2-10]
+ * maxpwr[2] - CCK channels [11-14]
+ * maxpwr[3] - OFDM channels [1]
+ * maxpwr[4] - OFDM channels [2-10]
+ * maxpwr[5] - OFDM channels [11-14]
+ */
+
+/* maxpwr mapping to 5GHz band channels:
+ * maxpwr[0] - channels [34-48]
+ * maxpwr[1] - channels [52-60]
+ * maxpwr[2] - channels [62-64]
+ * maxpwr[3] - channels [100-140]
+ * maxpwr[4] - channels [149-165]
+ */
+#define BAND_5G_PWR_LVLS 5 /* 5 power levels for 5G */
+
+#define LC(id) LOCALE_MIMO_IDX_ ## id
+
+#define LC_2G(id) LOCALE_2G_IDX_ ## id
+
+#define LC_5G(id) LOCALE_5G_IDX_ ## id
+
+#define LOCALES(band2, band5, mimo2, mimo5) \
+ {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
+
+/* macro to get 2.4 GHz channel group index for tx power */
+#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2))
+#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5))
+
+/* macro to get 5 GHz channel group index for tx power */
+#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
+ (((c) < 62) ? 1 : \
+ (((c) < 100) ? 2 : \
+ (((c) < 149) ? 3 : 4))))
+
+#define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU)
struct brcms_cm_band {
- u8 locale_flags; /* struct locale_info flags */
- chanvec_t valid_channels; /* List of valid channels in the country */
- const chanvec_t *restricted_channels; /* List of restricted use channels */
- const chanvec_t *radar_channels; /* List of radar sensitive channels */
+ /* struct locale_info flags */
+ u8 locale_flags;
+ /* List of valid channels in the country */
+ struct brcms_chanvec valid_channels;
+ /* List of restricted use channels */
+ const struct brcms_chanvec *restricted_channels;
+ /* List of radar sensitive channels */
+ const struct brcms_chanvec *radar_channels;
u8 PAD[8];
};
+ /* locale per-channel tx power limits for MIMO frames
+ * maxpwr arrays are index by channel for 2.4 GHz limits, and
+ * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
+ */
+struct locale_mimo_info {
+ /* tx 20 MHz power limits, qdBm units */
+ s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
+ /* tx 40 MHz power limits, qdBm units */
+ s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
+ u8 flags;
+};
+
+/* Country names and abbreviations with locale defined from ISO 3166 */
+struct country_info {
+ const u8 locale_2G; /* 2.4G band locale */
+ const u8 locale_5G; /* 5G band locale */
+ const u8 locale_mimo_2G; /* 2.4G mimo info */
+ const u8 locale_mimo_5G; /* 5G mimo info */
+};
+
struct brcms_cm_info {
struct brcms_pub *pub;
struct brcms_c_info *wlc;
@@ -50,63 +164,23 @@ struct brcms_cm_info {
/* per-band state (one per phy/radio) */
struct brcms_cm_band bandstate[MAXBANDS];
/* quiet channels currently for radar sensitivity or 11h support */
- chanvec_t quiet_channels; /* channels on which we cannot transmit */
+ /* channels on which we cannot transmit */
+ struct brcms_chanvec quiet_channels;
};
-static int brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
- const struct country_info *country);
-static void brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, uint regrev,
- const struct country_info *country);
-static int brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm,
- const char *ccode);
-static int brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, int regrev);
-static int brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm,
- const char *ccode,
- char *mapped_ccode, uint *mapped_regrev);
-
-static const struct country_info *
-brcms_c_country_lookup_direct(const char *ccode, uint regrev);
-
-static const struct country_info *
-brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm,
- const char *ccode, char *mapped_ccode,
- uint *mapped_regrev);
-
-static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm);
-static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm);
-static bool brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm,
- chanspec_t chspec);
-static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val);
-static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit, uint val);
-static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val);
-
-static const struct country_info *
-brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode);
-
-static void brcms_c_locale_get_channels(const struct locale_info *locale,
- chanvec_t *valid_channels);
-static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx);
-static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx);
-static bool brcms_c_japan(struct brcms_c_info *wlc);
-static bool brcms_c_japan_ccode(const char *ccode);
-static void brcms_c_channel_min_txpower_limits_with_local_constraint(
- struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
- u8 local_constraint_qdbm);
-static void brcms_c_locale_add_channels(chanvec_t *target,
- const chanvec_t *channels);
-static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx);
-static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx);
-
-/* QDB() macro takes a dB value and converts to a quarter dB value */
-#ifdef QDB
-#undef QDB
-#endif
-#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
+/* locale channel and power info. */
+struct locale_info {
+ u32 valid_channels;
+ /* List of radar sensitive channels */
+ u8 radar_channels;
+ /* List of channels used only if APs are detected */
+ u8 restricted_channels;
+ /* Max tx pwr in qdBm for each sub-band */
+ s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
+ /* Country IE advertised max tx pwr in dBm per sub-band */
+ s8 pub_maxpwr[BAND_5G_PWR_LVLS];
+ u8 flags;
+};
/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
@@ -115,7 +189,7 @@ static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx);
*/
/* No channels */
-static const chanvec_t chanvec_none = {
+static const struct brcms_chanvec chanvec_none = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -123,7 +197,7 @@ static const chanvec_t chanvec_none = {
};
/* All 2.4 GHz HW channels */
-const chanvec_t chanvec_all_2G = {
+static const struct brcms_chanvec chanvec_all_2G = {
{0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -131,7 +205,7 @@ const chanvec_t chanvec_all_2G = {
};
/* All 5 GHz HW channels */
-const chanvec_t chanvec_all_5G = {
+static const struct brcms_chanvec chanvec_all_5G = {
{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11,
0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11,
@@ -142,13 +216,11 @@ const chanvec_t chanvec_all_5G = {
* Radar channel sets
*/
-/* No radar */
-#define radar_set_none chanvec_none
-
-static const chanvec_t radar_set1 = { /* Channels 52 - 64, 100 - 140 */
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */
- 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */
- 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */
+/* Channels 52 - 64, 100 - 140 */
+static const struct brcms_chanvec radar_set1 = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */
+ 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */
0x00, 0x00, 0x00, 0x00}
};
@@ -156,10 +228,8 @@ static const chanvec_t radar_set1 = { /* Channels 52 - 64, 100 - 140 */
* Restricted channel sets
*/
-#define restricted_set_none chanvec_none
-
/* Channels 34, 38, 42, 46 */
-static const chanvec_t restricted_set_japan_legacy = {
+static const struct brcms_chanvec restricted_set_japan_legacy = {
{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -167,7 +237,7 @@ static const chanvec_t restricted_set_japan_legacy = {
};
/* Channels 12, 13 */
-static const chanvec_t restricted_set_2g_short = {
+static const struct brcms_chanvec restricted_set_2g_short = {
{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -175,7 +245,7 @@ static const chanvec_t restricted_set_2g_short = {
};
/* Channel 165 */
-static const chanvec_t restricted_chan_165 = {
+static const struct brcms_chanvec restricted_chan_165 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
@@ -183,7 +253,7 @@ static const chanvec_t restricted_chan_165 = {
};
/* Channels 36 - 48 & 149 - 165 */
-static const chanvec_t restricted_low_hi = {
+static const struct brcms_chanvec restricted_low_hi = {
{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00,
@@ -191,61 +261,21 @@ static const chanvec_t restricted_low_hi = {
};
/* Channels 12 - 14 */
-static const chanvec_t restricted_set_12_13_14 = {
+static const struct brcms_chanvec restricted_set_12_13_14 = {
{0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-#define LOCALE_CHAN_01_11 (1<<0)
-#define LOCALE_CHAN_12_13 (1<<1)
-#define LOCALE_CHAN_14 (1<<2)
-#define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */
-#define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */
-#define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */
-#define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */
-#define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */
-#define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */
-#define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */
-#define LOCALE_SET_5G_MID3 (1<<10) /* 128 */
-#define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */
-#define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */
-#define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */
-#define LOCALE_CHAN_52_140_ALL (1<<14)
-#define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */
-
-#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
-#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
-#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
-#define LOCALE_CHAN_100_140 \
- (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
-#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
-#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4
-
-#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13 | LOCALE_CHAN_14)
-
-#define LOCALE_RADAR_SET_NONE 0
-#define LOCALE_RADAR_SET_1 1
-
-#define LOCALE_RESTRICTED_NONE 0
-#define LOCALE_RESTRICTED_SET_2G_SHORT 1
-#define LOCALE_RESTRICTED_CHAN_165 2
-#define LOCALE_CHAN_ALL_5G 3
-#define LOCALE_RESTRICTED_JAPAN_LEGACY 4
-#define LOCALE_RESTRICTED_11D_2G 5
-#define LOCALE_RESTRICTED_11D_5G 6
-#define LOCALE_RESTRICTED_LOW_HI 7
-#define LOCALE_RESTRICTED_12_13_14 8
-
/* global memory to provide working buffer for expanded locale */
-static const chanvec_t *g_table_radar_set[] = {
+static const struct brcms_chanvec *g_table_radar_set[] = {
&chanvec_none,
&radar_set1
};
-static const chanvec_t *g_table_restricted_chan[] = {
+static const struct brcms_chanvec *g_table_restricted_chan[] = {
&chanvec_none, /* restricted_set_none */
&restricted_set_2g_short,
&restricted_chan_165,
@@ -257,119 +287,119 @@ static const chanvec_t *g_table_restricted_chan[] = {
&restricted_set_12_13_14
};
-static const chanvec_t locale_2g_01_11 = {
+static const struct brcms_chanvec locale_2g_01_11 = {
{0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_2g_12_13 = {
+static const struct brcms_chanvec locale_2g_12_13 = {
{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_2g_14 = {
+static const struct brcms_chanvec locale_2g_14 = {
{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_LOW_JP1 = {
+static const struct brcms_chanvec locale_5g_LOW_JP1 = {
{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_LOW_JP2 = {
+static const struct brcms_chanvec locale_5g_LOW_JP2 = {
{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_LOW1 = {
+static const struct brcms_chanvec locale_5g_LOW1 = {
{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_LOW2 = {
+static const struct brcms_chanvec locale_5g_LOW2 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_LOW3 = {
+static const struct brcms_chanvec locale_5g_LOW3 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_MID1 = {
+static const struct brcms_chanvec locale_5g_MID1 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_MID2 = {
+static const struct brcms_chanvec locale_5g_MID2 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_MID3 = {
+static const struct brcms_chanvec locale_5g_MID3 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_HIGH1 = {
+static const struct brcms_chanvec locale_5g_HIGH1 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_HIGH2 = {
+static const struct brcms_chanvec locale_5g_HIGH2 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_HIGH3 = {
+static const struct brcms_chanvec locale_5g_HIGH3 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_52_140_ALL = {
+static const struct brcms_chanvec locale_5g_52_140_ALL = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
-static const chanvec_t locale_5g_HIGH4 = {
+static const struct brcms_chanvec locale_5g_HIGH4 = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
0x11, 0x11, 0x11, 0x11}
};
-static const chanvec_t *g_table_locale_base[] = {
+static const struct brcms_chanvec *g_table_locale_base[] = {
&locale_2g_01_11,
&locale_2g_12_13,
&locale_2g_14,
@@ -388,27 +418,25 @@ static const chanvec_t *g_table_locale_base[] = {
&locale_5g_HIGH4
};
-static void brcms_c_locale_add_channels(chanvec_t *target,
- const chanvec_t *channels)
+static void brcms_c_locale_add_channels(struct brcms_chanvec *target,
+ const struct brcms_chanvec *channels)
{
u8 i;
- for (i = 0; i < sizeof(chanvec_t); i++) {
+ for (i = 0; i < sizeof(struct brcms_chanvec); i++)
target->vec[i] |= channels->vec[i];
- }
}
static void brcms_c_locale_get_channels(const struct locale_info *locale,
- chanvec_t *channels)
+ struct brcms_chanvec *channels)
{
u8 i;
- memset(channels, 0, sizeof(chanvec_t));
+ memset(channels, 0, sizeof(struct brcms_chanvec));
for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) {
- if (locale->valid_channels & (1 << i)) {
+ if (locale->valid_channels & (1 << i))
brcms_c_locale_add_channels(channels,
g_table_locale_base[i]);
- }
}
}
@@ -438,12 +466,10 @@ static const struct locale_info locale_11 = {
BRCMS_EIRP | BRCMS_DFS_EU
};
-#define LOCALE_2G_IDX_i 0
static const struct locale_info *g_locale_2g_table[] = {
&locale_i
};
-#define LOCALE_5G_IDX_11 0
static const struct locale_info *g_locale_5g_table[] = {
&locale_11
};
@@ -461,9 +487,6 @@ static const struct locale_mimo_info locale_bn = {
0
};
-/* locale mimo 2g indexes */
-#define LOCALE_MIMO_IDX_bn 0
-
static const struct locale_mimo_info *g_mimo_2g_table[] = {
&locale_bn
};
@@ -477,28 +500,10 @@ static const struct locale_mimo_info locale_11n = {
0
};
-#define LOCALE_MIMO_IDX_11n 0
static const struct locale_mimo_info *g_mimo_5g_table[] = {
&locale_11n
};
-#ifdef LC
-#undef LC
-#endif
-#define LC(id) LOCALE_MIMO_IDX_ ## id
-
-#ifdef LC_2G
-#undef LC_2G
-#endif
-#define LC_2G(id) LOCALE_2G_IDX_ ## id
-
-#ifdef LC_5G
-#undef LC_5G
-#endif
-#define LC_5G(id) LOCALE_5G_IDX_ ## id
-
-#define LOCALES(band2, band5, mimo2, mimo5) {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
-
static const struct {
char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */
struct country_info country;
@@ -586,201 +591,68 @@ struct chan20_info chan20_info[] = {
static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
{
- if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) {
+ if (locale_idx >= ARRAY_SIZE(g_locale_2g_table))
return NULL; /* error condition */
- }
+
return g_locale_2g_table[locale_idx];
}
static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx)
{
- if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) {
+ if (locale_idx >= ARRAY_SIZE(g_locale_5g_table))
return NULL; /* error condition */
- }
+
return g_locale_5g_table[locale_idx];
}
static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
{
- if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) {
+ if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table))
return NULL;
- }
+
return g_mimo_2g_table[locale_idx];
}
static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
{
- if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table)) {
- return NULL;
- }
- return g_mimo_5g_table[locale_idx];
-}
-
-struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
-{
- struct brcms_cm_info *wlc_cm;
- char country_abbrev[BRCM_CNTRY_BUF_SZ];
- const struct country_info *country;
- struct brcms_pub *pub = wlc->pub;
- char *ccode;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
- wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
- if (wlc_cm == NULL) {
- wiphy_err(wlc->wiphy, "wl%d: %s: out of memory", pub->unit,
- __func__);
+ if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table))
return NULL;
- }
- wlc_cm->pub = pub;
- wlc_cm->wlc = wlc;
- wlc->cmi = wlc_cm;
-
- /* store the country code for passing up as a regulatory hint */
- ccode = getvar(wlc->pub->vars, "ccode");
- if (ccode) {
- strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
- }
-
- /* internal country information which must match regulatory constraints in firmware */
- memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
- strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
- country = brcms_c_country_lookup(wlc, country_abbrev);
-
- /* save default country for exiting 11d regulatory mode */
- strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
-
- /* initialize autocountry_default to driver default */
- strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
-
- brcms_c_set_countrycode(wlc_cm, country_abbrev);
-
- return wlc_cm;
-}
-
-void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
-{
- kfree(wlc_cm);
-}
-u8
-brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit)
-{
- return wlc_cm->bandstate[bandunit].locale_flags;
-}
-
-/* set the driver's current country and regulatory information using a country code
- * as the source. Lookup built in country information found with the country code.
- */
-static int
-brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode)
-{
- char country_abbrev[BRCM_CNTRY_BUF_SZ];
- strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ);
- return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
+ return g_mimo_5g_table[locale_idx];
}
static int
-brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, int regrev)
+brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode,
+ char *mapped_ccode, uint *mapped_regrev)
{
- const struct country_info *country;
- char mapped_ccode[BRCM_CNTRY_BUF_SZ];
- uint mapped_regrev;
-
- /* if regrev is -1, lookup the mapped country code,
- * otherwise use the ccode and regrev directly
- */
- if (regrev == -1) {
- /* map the country code to a built-in country code, regrev, and country_info */
- country =
- brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode,
- &mapped_regrev);
- } else {
- /* find the matching built-in country definition */
- country = brcms_c_country_lookup_direct(ccode, regrev);
- strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
- mapped_regrev = regrev;
- }
-
- if (country == NULL)
- return -EINVAL;
-
- /* set the driver state for the country */
- brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
- mapped_regrev, country);
-
- return 0;
+ return false;
}
-/* set the driver's current country and regulatory information using a country code
- * as the source. Look up built in country information found with the country code.
+/* Lookup a country info structure from a null terminated country
+ * abbreviation and regrev directly with no translation.
*/
-static void
-brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, uint regrev,
- const struct country_info *country)
+static const struct country_info *
+brcms_c_country_lookup_direct(const char *ccode, uint regrev)
{
- const struct locale_mimo_info *li_mimo;
- const struct locale_info *locale;
- struct brcms_c_info *wlc = wlc_cm->wlc;
- char prev_country_abbrev[BRCM_CNTRY_BUF_SZ];
-
- /* save current country state */
- wlc_cm->country = country;
-
- memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
- strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
- BRCM_CNTRY_BUF_SZ - 1);
+ uint size, i;
- strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
- strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
- wlc_cm->regrev = regrev;
+ /* Should just return 0 for single locale driver. */
+ /* Keep it this way in case we add more locales. (for now anyway) */
- /* disable/restore nmode based on country regulations */
- li_mimo = brcms_c_get_mimo_2g(country->locale_mimo_2G);
- if (li_mimo && (li_mimo->flags & BRCMS_NO_MIMO)) {
- brcms_c_set_nmode(wlc, OFF);
- wlc->stf->no_cddstbc = true;
- } else {
- wlc->stf->no_cddstbc = false;
- if (N_ENAB(wlc->pub) != wlc->protection->nmode_user)
- brcms_c_set_nmode(wlc, wlc->protection->nmode_user);
- }
+ /*
+ * all other country def arrays are for regrev == 0, so if
+ * regrev is non-zero, fail
+ */
+ if (regrev > 0)
+ return NULL;
- brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
- brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
- /* set or restore gmode as required by regulatory */
- locale = brcms_c_get_locale_2g(country->locale_2G);
- if (locale && (locale->flags & BRCMS_NO_OFDM)) {
- brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
- } else {
- brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
+ /* find matched table entry from country code */
+ size = ARRAY_SIZE(cntry_locales);
+ for (i = 0; i < size; i++) {
+ if (strcmp(ccode, cntry_locales[i].abbrev) == 0)
+ return &cntry_locales[i].country;
}
-
- brcms_c_channels_init(wlc_cm, country);
-
- return;
-}
-
-/* Lookup a country info structure from a null terminated country code
- * The lookup is case sensitive.
- */
-static const struct country_info *
-brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode)
-{
- const struct country_info *country;
- char mapped_ccode[BRCM_CNTRY_BUF_SZ];
- uint mapped_regrev;
-
- /* map the country code to a built-in country code, regrev, and country_info struct */
- country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode,
- &mapped_regrev);
-
- return country;
+ return NULL;
}
static const struct country_info *
@@ -831,174 +703,67 @@ brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode,
return country;
}
-static int
-brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode,
- char *mapped_ccode, uint *mapped_regrev)
-{
- return false;
-}
-
-/* Lookup a country info structure from a null terminated country
- * abbreviation and regrev directly with no translation.
+/* Lookup a country info structure from a null terminated country code
+ * The lookup is case sensitive.
*/
static const struct country_info *
-brcms_c_country_lookup_direct(const char *ccode, uint regrev)
-{
- uint size, i;
-
- /* Should just return 0 for single locale driver. */
- /* Keep it this way in case we add more locales. (for now anyway) */
-
- /* all other country def arrays are for regrev == 0, so if regrev is non-zero, fail */
- if (regrev > 0)
- return NULL;
-
- /* find matched table entry from country code */
- size = ARRAY_SIZE(cntry_locales);
- for (i = 0; i < size; i++) {
- if (strcmp(ccode, cntry_locales[i].abbrev) == 0) {
- return &cntry_locales[i].country;
- }
- }
- return NULL;
-}
-
-static int
-brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
- const struct country_info *country)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- uint i, j;
- struct brcms_band *band;
- const struct locale_info *li;
- chanvec_t sup_chan;
- const struct locale_mimo_info *li_mimo;
-
- band = wlc->band;
- for (i = 0; i < NBANDS(wlc);
- i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
-
- li = BAND_5G(band->bandtype) ?
- brcms_c_get_locale_5g(country->locale_5G) :
- brcms_c_get_locale_2g(country->locale_2G);
- wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
- li_mimo = BAND_5G(band->bandtype) ?
- brcms_c_get_mimo_5g(country->locale_mimo_5G) :
- brcms_c_get_mimo_2g(country->locale_mimo_2G);
-
- /* merge the mimo non-mimo locale flags */
- wlc_cm->bandstate[band->bandunit].locale_flags |=
- li_mimo->flags;
-
- wlc_cm->bandstate[band->bandunit].restricted_channels =
- g_table_restricted_chan[li->restricted_channels];
- wlc_cm->bandstate[band->bandunit].radar_channels =
- g_table_radar_set[li->radar_channels];
-
- /* set the channel availability,
- * masking out the channels that may not be supported on this phy
- */
- wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
- &sup_chan);
- brcms_c_locale_get_channels(li,
- &wlc_cm->bandstate[band->bandunit].
- valid_channels);
- for (j = 0; j < sizeof(chanvec_t); j++)
- wlc_cm->bandstate[band->bandunit].valid_channels.
- vec[j] &= sup_chan.vec[j];
- }
-
- brcms_c_quiet_channels_reset(wlc_cm);
- brcms_c_channels_commit(wlc_cm);
-
- return 0;
-}
-
-/* Update the radio state (enable/disable) and tx power targets
- * based on a new set of channel/regulatory information
- */
-static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
+brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode)
{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- uint chan;
- struct txpwr_limits txpwr;
-
- /* search for the existence of any valid channel */
- for (chan = 0; chan < MAXCHANNEL; chan++) {
- if (VALID_CHANNEL20_DB(wlc, chan)) {
- break;
- }
- }
- if (chan == MAXCHANNEL)
- chan = INVCHANNEL;
-
- /* based on the channel search above, set or clear WL_RADIO_COUNTRY_DISABLE */
- if (chan == INVCHANNEL) {
- /* country/locale with no valid channels, set the radio disable bit */
- mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
- wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
- "nbands %d bandlocked %d\n", wlc->pub->unit,
- __func__, wlc_cm->country_abbrev, NBANDS(wlc),
- wlc->bandlocked);
- } else
- if (mboolisset(wlc->pub->radio_disabled,
- WL_RADIO_COUNTRY_DISABLE)) {
- /* country/locale with valid channel, clear the radio disable bit */
- mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
- }
+ const struct country_info *country;
+ char mapped_ccode[BRCM_CNTRY_BUF_SZ];
+ uint mapped_regrev;
- /* Now that the country abbreviation is set, if the radio supports 2G, then
- * set channel 14 restrictions based on the new locale.
+ /*
+ * map the country code to a built-in country code, regrev, and
+ * country_info struct
*/
- if (NBANDS(wlc) > 1 || BAND_2G(wlc->band->bandtype)) {
- wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
- brcms_c_japan(wlc) ? true :
- false);
- }
+ country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode,
+ &mapped_regrev);
- if (wlc->pub->up && chan != INVCHANNEL) {
- brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
- brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm,
- &txpwr, BRCMS_TXPWR_MAX);
- wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
- }
+ return country;
}
-/* reset the quiet channels vector to the union of the restricted and radar channel sets */
+/*
+ * reset the quiet channels vector to the union
+ * of the restricted and radar channel sets
+ */
static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
uint i, j;
struct brcms_band *band;
- const chanvec_t *chanvec;
+ const struct brcms_chanvec *chanvec;
- memset(&wlc_cm->quiet_channels, 0, sizeof(chanvec_t));
+ memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec));
band = wlc->band;
- for (i = 0; i < NBANDS(wlc);
+ for (i = 0; i < wlc->pub->_nbands;
i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
/* initialize quiet channels for restricted channels */
chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels;
- for (j = 0; j < sizeof(chanvec_t); j++)
+ for (j = 0; j < sizeof(struct brcms_chanvec); j++)
wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j];
}
}
-static bool
-brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, chanspec_t chspec)
+/* Is the channel valid for the current locale and current band? */
+static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val)
+{
+ struct brcms_c_info *wlc = wlc_cm->wlc;
+
+ return ((val < MAXCHANNEL) &&
+ isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
+ val));
+}
+
+/* Is the channel valid for the current locale and specified band? */
+static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
+ uint bandunit, uint val)
{
- return N_ENAB(wlc_cm->wlc->pub) && CHSPEC_IS40(chspec) ?
- (isset
- (wlc_cm->quiet_channels.vec,
- LOWER_20_SB(CHSPEC_CHANNEL(chspec)))
- || isset(wlc_cm->quiet_channels.vec,
- UPPER_20_SB(CHSPEC_CHANNEL(chspec)))) : isset(wlc_cm->
- quiet_channels.
- vec,
- CHSPEC_CHANNEL
- (chspec));
+ return ((val < MAXCHANNEL)
+ && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
}
/* Is the channel valid for the current locale? (but don't consider channels not
@@ -1008,27 +773,23 @@ static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
- return VALID_CHANNEL20(wlc, val) ||
+ return brcms_c_valid_channel20(wlc->cmi, val) ||
(!wlc->bandlocked
- && VALID_CHANNEL20_IN_BAND(wlc, OTHERBANDUNIT(wlc), val));
+ && brcms_c_valid_channel20_in_band(wlc->cmi,
+ OTHERBANDUNIT(wlc), val));
}
-/* Is the channel valid for the current locale and specified band? */
-static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit, uint val)
+/* JP, J1 - J10 are Japan ccodes */
+static bool brcms_c_japan_ccode(const char *ccode)
{
- return ((val < MAXCHANNEL)
- && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
+ return (ccode[0] == 'J' &&
+ (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
}
-/* Is the channel valid for the current locale and current band? */
-static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val)
+/* Returns true if currently set country is Japan or variant */
+static bool brcms_c_japan(struct brcms_c_info *wlc)
{
- struct brcms_c_info *wlc = wlc_cm->wlc;
-
- return ((val < MAXCHANNEL) &&
- isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
- val));
+ return brcms_c_japan_ccode(wlc->cmi->country_abbrev);
}
static void
@@ -1039,50 +800,42 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(
int j;
/* CCK Rates */
- for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) {
+ for (j = 0; j < WL_TX_POWER_CCK_NUM; j++)
txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
- }
/* 20 MHz Legacy OFDM SISO */
- for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++) {
+ for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++)
txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
- }
/* 20 MHz Legacy OFDM CDD */
- for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) {
+ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_cdd[j] =
min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
- }
/* 40 MHz Legacy OFDM SISO */
- for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) {
+ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_40_siso[j] =
min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
- }
/* 40 MHz Legacy OFDM CDD */
- for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) {
+ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_40_cdd[j] =
min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
- }
/* 20MHz MCS 0-7 SISO */
- for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_siso[j] =
min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
- }
/* 20MHz MCS 0-7 CDD */
- for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_cdd[j] =
min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
- }
/* 20MHz MCS 0-7 STBC */
- for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_stbc[j] =
min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
- }
/* 20MHz MCS 8-15 MIMO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
@@ -1090,22 +843,19 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(
min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
/* 40MHz MCS 0-7 SISO */
- for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_siso[j] =
min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
- }
/* 40MHz MCS 0-7 CDD */
- for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_cdd[j] =
min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
- }
/* 40MHz MCS 0-7 STBC */
- for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_stbc[j] =
min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
- }
/* 40MHz MCS 8-15 MIMO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
@@ -1117,8 +867,276 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(
}
+/* Update the radio state (enable/disable) and tx power targets
+ * based on a new set of channel/regulatory information
+ */
+static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
+{
+ struct brcms_c_info *wlc = wlc_cm->wlc;
+ uint chan;
+ struct txpwr_limits txpwr;
+
+ /* search for the existence of any valid channel */
+ for (chan = 0; chan < MAXCHANNEL; chan++) {
+ if (brcms_c_valid_channel20_db(wlc->cmi, chan))
+ break;
+ }
+ if (chan == MAXCHANNEL)
+ chan = INVCHANNEL;
+
+ /*
+ * based on the channel search above, set or
+ * clear WL_RADIO_COUNTRY_DISABLE.
+ */
+ if (chan == INVCHANNEL) {
+ /*
+ * country/locale with no valid channels, set
+ * the radio disable bit
+ */
+ mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+ wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
+ "nbands %d bandlocked %d\n", wlc->pub->unit,
+ __func__, wlc_cm->country_abbrev, wlc->pub->_nbands,
+ wlc->bandlocked);
+ } else if (mboolisset(wlc->pub->radio_disabled,
+ WL_RADIO_COUNTRY_DISABLE)) {
+ /*
+ * country/locale with valid channel, clear
+ * the radio disable bit
+ */
+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+ }
+
+ /*
+ * Now that the country abbreviation is set, if the radio supports 2G,
+ * then set channel 14 restrictions based on the new locale.
+ */
+ if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
+ wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
+ brcms_c_japan(wlc) ? true :
+ false);
+
+ if (wlc->pub->up && chan != INVCHANNEL) {
+ brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
+ brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm,
+ &txpwr, BRCMS_TXPWR_MAX);
+ wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
+ }
+}
+
+static int
+brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
+ const struct country_info *country)
+{
+ struct brcms_c_info *wlc = wlc_cm->wlc;
+ uint i, j;
+ struct brcms_band *band;
+ const struct locale_info *li;
+ struct brcms_chanvec sup_chan;
+ const struct locale_mimo_info *li_mimo;
+
+ band = wlc->band;
+ for (i = 0; i < wlc->pub->_nbands;
+ i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
+
+ li = (band->bandtype == BRCM_BAND_5G) ?
+ brcms_c_get_locale_5g(country->locale_5G) :
+ brcms_c_get_locale_2g(country->locale_2G);
+ wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
+ li_mimo = (band->bandtype == BRCM_BAND_5G) ?
+ brcms_c_get_mimo_5g(country->locale_mimo_5G) :
+ brcms_c_get_mimo_2g(country->locale_mimo_2G);
+
+ /* merge the mimo non-mimo locale flags */
+ wlc_cm->bandstate[band->bandunit].locale_flags |=
+ li_mimo->flags;
+
+ wlc_cm->bandstate[band->bandunit].restricted_channels =
+ g_table_restricted_chan[li->restricted_channels];
+ wlc_cm->bandstate[band->bandunit].radar_channels =
+ g_table_radar_set[li->radar_channels];
+
+ /*
+ * set the channel availability, masking out the channels
+ * that may not be supported on this phy.
+ */
+ wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
+ &sup_chan);
+ brcms_c_locale_get_channels(li,
+ &wlc_cm->bandstate[band->bandunit].
+ valid_channels);
+ for (j = 0; j < sizeof(struct brcms_chanvec); j++)
+ wlc_cm->bandstate[band->bandunit].valid_channels.
+ vec[j] &= sup_chan.vec[j];
+ }
+
+ brcms_c_quiet_channels_reset(wlc_cm);
+ brcms_c_channels_commit(wlc_cm);
+
+ return 0;
+}
+
+/*
+ * set the driver's current country and regulatory information
+ * using a country code as the source. Look up built in country
+ * information found with the country code.
+ */
+static void
+brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
+ const char *country_abbrev,
+ const char *ccode, uint regrev,
+ const struct country_info *country)
+{
+ const struct locale_info *locale;
+ struct brcms_c_info *wlc = wlc_cm->wlc;
+ char prev_country_abbrev[BRCM_CNTRY_BUF_SZ];
+
+ /* save current country state */
+ wlc_cm->country = country;
+
+ memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
+ strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
+ BRCM_CNTRY_BUF_SZ - 1);
+
+ strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
+ strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
+ wlc_cm->regrev = regrev;
+
+ if ((wlc->pub->_n_enab & SUPPORT_11N) !=
+ wlc->protection->nmode_user)
+ brcms_c_set_nmode(wlc);
+
+ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
+ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
+ /* set or restore gmode as required by regulatory */
+ locale = brcms_c_get_locale_2g(country->locale_2G);
+ if (locale && (locale->flags & BRCMS_NO_OFDM))
+ brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
+ else
+ brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
+
+ brcms_c_channels_init(wlc_cm, country);
+
+ return;
+}
+
+static int
+brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
+ const char *country_abbrev,
+ const char *ccode, int regrev)
+{
+ const struct country_info *country;
+ char mapped_ccode[BRCM_CNTRY_BUF_SZ];
+ uint mapped_regrev;
+
+ /* if regrev is -1, lookup the mapped country code,
+ * otherwise use the ccode and regrev directly
+ */
+ if (regrev == -1) {
+ /*
+ * map the country code to a built-in country
+ * code, regrev, and country_info
+ */
+ country =
+ brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode,
+ &mapped_regrev);
+ } else {
+ /* find the matching built-in country definition */
+ country = brcms_c_country_lookup_direct(ccode, regrev);
+ strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
+ mapped_regrev = regrev;
+ }
+
+ if (country == NULL)
+ return -EINVAL;
+
+ /* set the driver state for the country */
+ brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
+ mapped_regrev, country);
+
+ return 0;
+}
+
+/*
+ * set the driver's current country and regulatory information using
+ * a country code as the source. Lookup built in country information
+ * found with the country code.
+ */
+static int
+brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode)
+{
+ char country_abbrev[BRCM_CNTRY_BUF_SZ];
+ strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ);
+ return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
+}
+
+struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
+{
+ struct brcms_cm_info *wlc_cm;
+ char country_abbrev[BRCM_CNTRY_BUF_SZ];
+ const struct country_info *country;
+ struct brcms_pub *pub = wlc->pub;
+ char *ccode;
+
+ 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;
+ wlc_cm->pub = pub;
+ wlc_cm->wlc = wlc;
+ wlc->cmi = wlc_cm;
+
+ /* store the country code for passing up as a regulatory hint */
+ ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE);
+ if (ccode)
+ strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
+
+ /*
+ * internal country information which must match
+ * regulatory constraints in firmware
+ */
+ memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
+ strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
+ country = brcms_c_country_lookup(wlc, country_abbrev);
+
+ /* save default country for exiting 11d regulatory mode */
+ strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
+
+ /* initialize autocountry_default to driver default */
+ strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
+
+ brcms_c_set_countrycode(wlc_cm, country_abbrev);
+
+ return wlc_cm;
+}
+
+void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
+{
+ kfree(wlc_cm);
+}
+
+u8
+brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
+ uint bandunit)
+{
+ return wlc_cm->bandstate[bandunit].locale_flags;
+}
+
+static bool
+brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec)
+{
+ return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) &&
+ CHSPEC_IS40(chspec) ?
+ (isset(wlc_cm->quiet_channels.vec,
+ lower_20_sb(CHSPEC_CHANNEL(chspec))) ||
+ isset(wlc_cm->quiet_channels.vec,
+ upper_20_sb(CHSPEC_CHANNEL(chspec)))) :
+ isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec));
+}
+
void
-brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
+brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
u8 local_constraint_qdbm)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
@@ -1126,8 +1144,9 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
- brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm, &txpwr,
- local_constraint_qdbm);
+ brcms_c_channel_min_txpower_limits_with_local_constraint(
+ wlc_cm, &txpwr, local_constraint_qdbm
+ );
brcms_b_set_chanspec(wlc->hw, chanspec,
(brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0),
@@ -1142,112 +1161,100 @@ static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr)
char fraction[4][4] = { " ", ".25", ".5 ", ".75" };
sprintf(buf, "CCK ");
- for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->cck[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->cck[i] % BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz OFDM SISO ");
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm[i] % BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz OFDM CDD ");
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm_cdd[i] % BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz OFDM SISO ");
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm_40_siso[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm_40_siso[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz OFDM CDD ");
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm_40_cdd[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS0-7 SISO ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_siso[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_siso[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS0-7 CDD ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_cdd[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS0-7 STBC ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_stbc[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_stbc[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS8-15 SDM ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_mimo[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_mimo[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS0-7 SISO ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_siso[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_siso[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS0-7 CDD ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_cdd[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS0-7 STBC ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_stbc[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_stbc[i] %
BRCMS_TXPWR_DB_FACTOR]);
- }
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS8-15 SDM ");
- for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
+ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_mimo[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_mimo[i] %
@@ -1262,7 +1269,7 @@ static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr)
#endif /* POWER_DBG */
void
-brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
+brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
struct txpwr_limits *txpwr)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
@@ -1273,8 +1280,8 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
const struct country_info *country;
struct brcms_band *band;
const struct locale_info *li;
- int conducted_max;
- int conducted_ofdm_max;
+ int conducted_max = BRCMS_TXPWR_MAX;
+ int conducted_ofdm_max = BRCMS_TXPWR_MAX;
const struct locale_mimo_info *li_mimo;
int maxpwr20, maxpwr40;
int maxpwr_idx;
@@ -1291,12 +1298,12 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
}
chan = CHSPEC_CHANNEL(chanspec);
- band = wlc->bandstate[CHSPEC_BANDUNIT(chanspec)];
- li = BAND_5G(band->bandtype) ?
+ band = wlc->bandstate[chspec_bandunit(chanspec)];
+ li = (band->bandtype == BRCM_BAND_5G) ?
brcms_c_get_locale_5g(country->locale_5G) :
brcms_c_get_locale_2g(country->locale_2G);
- li_mimo = BAND_5G(band->bandtype) ?
+ li_mimo = (band->bandtype == BRCM_BAND_5G) ?
brcms_c_get_mimo_5g(country->locale_mimo_5G) :
brcms_c_get_mimo_2g(country->locale_mimo_2G);
@@ -1314,7 +1321,7 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
}
/* CCK txpwr limits for 2.4G band */
- if (BAND_2G(band->bandtype)) {
+ if (band->bandtype == BRCM_BAND_2G) {
maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)];
maxpwr = maxpwr - delta;
@@ -1326,29 +1333,29 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
}
/* OFDM txpwr limits for 2.4G or 5G bands */
- if (BAND_2G(band->bandtype)) {
+ if (band->bandtype == BRCM_BAND_2G)
maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)];
-
- } else {
+ else
maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)];
- }
maxpwr = maxpwr - delta;
maxpwr = max(maxpwr, 0);
maxpwr = min(maxpwr, conducted_ofdm_max);
/* Keep OFDM lmit below CCK limit */
- if (BAND_2G(band->bandtype))
+ if (band->bandtype == BRCM_BAND_2G)
maxpwr = min_t(int, maxpwr, txpwr->cck[0]);
for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
txpwr->ofdm[i] = (u8) maxpwr;
for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
- /* OFDM 40 MHz SISO has the same power as the corresponding MCS0-7 rate unless
- * overriden by the locale specific code. We set this value to 0 as a
- * flag (presumably 0 dBm isn't a possibility) and then copy the MCS0-7 value
- * to the 40 MHz value if it wasn't explicitly set.
+ /*
+ * OFDM 40 MHz SISO has the same power as the corresponding
+ * MCS0-7 rate unless overriden by the locale specific code.
+ * We set this value to 0 as a flag (presumably 0 dBm isn't
+ * a possibility) and then copy the MCS0-7 value to the 40 MHz
+ * value if it wasn't explicitly set.
*/
txpwr->ofdm_40_siso[i] = 0;
@@ -1366,7 +1373,7 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
delta = band->antgain - QDB(6); /* Excess over 6 dB */
}
- if (BAND_2G(band->bandtype))
+ if (band->bandtype == BRCM_BAND_2G)
maxpwr_idx = (chan - 1);
else
maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
@@ -1382,8 +1389,9 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
/* Fill in the MCS 0-7 (SISO) rates */
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
- /* 20 MHz has the same power as the corresponding OFDM rate unless
- * overriden by the locale specific code.
+ /*
+ * 20 MHz has the same power as the corresponding OFDM rate
+ * unless overriden by the locale specific code.
*/
txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
txpwr->mcs_40_siso[i] = 0;
@@ -1395,15 +1403,17 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
}
- /* These locales have SISO expressed in the table and override CDD later */
+ /*
+ * These locales have SISO expressed in the
+ * table and override CDD later
+ */
if (li_mimo == &locale_bn) {
if (li_mimo == &locale_bn) {
maxpwr20 = QDB(16);
maxpwr40 = 0;
- if (chan >= 3 && chan <= 11) {
+ if (chan >= 3 && chan <= 11)
maxpwr40 = QDB(16);
- }
}
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
@@ -1437,10 +1447,10 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
}
}
- /* Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO value if it wasn't
- * provided explicitly.
+ /*
+ * Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO
+ * value if it wasn't provided explicitly.
*/
-
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
if (txpwr->mcs_40_siso[i] == 0)
txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
@@ -1456,8 +1466,9 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
}
}
- /* Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding STBC values if they weren't
- * provided explicitly.
+ /*
+ * Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding
+ * STBC values if they weren't provided explicitly.
*/
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
if (txpwr->mcs_20_stbc[i] == 0)
@@ -1473,73 +1484,94 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
return;
}
-/* Returns true if currently set country is Japan or variant */
-static bool brcms_c_japan(struct brcms_c_info *wlc)
+/*
+ * Verify the chanspec is using a legal set of parameters, i.e. that the
+ * chanspec specified a band, bw, ctl_sb and channel and that the
+ * combination could be legal given any set of circumstances.
+ * RETURNS: true is the chanspec is malformed, false if it looks good.
+ */
+static bool brcms_c_chspec_malformed(u16 chanspec)
{
- return brcms_c_japan_ccode(wlc->cmi->country_abbrev);
-}
+ /* must be 2G or 5G band */
+ if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
+ return true;
+ /* must be 20 or 40 bandwidth */
+ if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
+ return true;
+
+ /* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
+ if (CHSPEC_IS20(chanspec)) {
+ if (!CHSPEC_SB_NONE(chanspec))
+ return true;
+ } else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) {
+ return true;
+ }
-/* JP, J1 - J10 are Japan ccodes */
-static bool brcms_c_japan_ccode(const char *ccode)
-{
- return (ccode[0] == 'J' &&
- (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
+ return false;
}
/*
- * Validate the chanspec for this locale, for 40MHZ we need to also check that the sidebands
- * are valid 20MZH channels in this locale and they are also a legal HT combination
+ * Validate the chanspec for this locale, for 40MHZ we need to also
+ * check that the sidebands are valid 20MZH channels in this locale
+ * and they are also a legal HT combination
*/
static bool
-brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, chanspec_t chspec,
+brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
bool dualband)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
u8 channel = CHSPEC_CHANNEL(chspec);
/* check the chanspec */
- if (brcmu_chspec_malformed(chspec)) {
+ if (brcms_c_chspec_malformed(chspec)) {
wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
wlc->pub->unit, chspec);
return false;
}
if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
- CHSPEC_BANDUNIT(chspec))
+ chspec_bandunit(chspec))
return false;
/* Check a 20Mhz channel */
if (CHSPEC_IS20(chspec)) {
if (dualband)
- return VALID_CHANNEL20_DB(wlc_cm->wlc, channel);
+ return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi,
+ channel);
else
- return VALID_CHANNEL20(wlc_cm->wlc, channel);
+ return brcms_c_valid_channel20(wlc_cm->wlc->cmi,
+ channel);
}
#ifdef SUPPORT_40MHZ
- /* We know we are now checking a 40MHZ channel, so we should only be here
- * for NPHYS
+ /*
+ * We know we are now checking a 40MHZ channel, so we should
+ * only be here for NPHYS
*/
if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) {
u8 upper_sideband = 0, idx;
u8 num_ch20_entries =
sizeof(chan20_info) / sizeof(struct chan20_info);
- if (!VALID_40CHANSPEC_IN_BAND(wlc, CHSPEC_BANDUNIT(chspec)))
+ if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec)))
return false;
if (dualband) {
- if (!VALID_CHANNEL20_DB(wlc, LOWER_20_SB(channel)) ||
- !VALID_CHANNEL20_DB(wlc, UPPER_20_SB(channel)))
+ if (!brcms_c_valid_channel20_db(wlc->cmi,
+ lower_20_sb(channel)) ||
+ !brcms_c_valid_channel20_db(wlc->cmi,
+ upper_20_sb(channel)))
return false;
} else {
- if (!VALID_CHANNEL20(wlc, LOWER_20_SB(channel)) ||
- !VALID_CHANNEL20(wlc, UPPER_20_SB(channel)))
+ if (!brcms_c_valid_channel20(wlc->cmi,
+ lower_20_sb(channel)) ||
+ !brcms_c_valid_channel20(wlc->cmi,
+ upper_20_sb(channel)))
return false;
}
/* find the lower sideband info in the sideband array */
for (idx = 0; idx < num_ch20_entries; idx++) {
- if (chan20_info[idx].sb == LOWER_20_SB(channel))
+ if (chan20_info[idx].sb == lower_20_sb(channel))
upper_sideband = chan20_info[idx].adj_sbs;
}
/* check that the lower sideband allows an upper sideband */
@@ -1553,7 +1585,7 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, chanspec_t chspec,
return false;
}
-bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, chanspec_t chspec)
+bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
{
return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true);
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.h b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
new file mode 100644
index 000000000000..808cb4fbfbe7
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_CHANNEL_H_
+#define _BRCM_CHANNEL_H_
+
+/* conversion for phy txpwr calculations that use .25 dB units */
+#define BRCMS_TXPWR_DB_FACTOR 4
+
+/* bits for locale_info flags */
+#define BRCMS_PEAK_CONDUCTED 0x00 /* Peak for locals */
+#define BRCMS_EIRP 0x01 /* Flag for EIRP */
+#define BRCMS_DFS_TPC 0x02 /* Flag for DFS TPC */
+#define BRCMS_NO_OFDM 0x04 /* Flag for No OFDM */
+#define BRCMS_NO_40MHZ 0x08 /* Flag for No MIMO 40MHz */
+#define BRCMS_NO_MIMO 0x10 /* Flag for No MIMO, 20 or 40 MHz */
+#define BRCMS_RADAR_TYPE_EU 0x20 /* Flag for EU */
+#define BRCMS_DFS_FCC BRCMS_DFS_TPC /* Flag for DFS FCC */
+
+#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */
+
+extern struct brcms_cm_info *
+brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
+
+extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
+
+extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
+ uint bandunit);
+
+extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm,
+ u16 chspec);
+
+extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm,
+ u16 chanspec,
+ struct txpwr_limits *txpwr);
+extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
+ u16 chanspec,
+ u8 local_constraint_qdbm);
+
+#endif /* _WLC_CHANNEL_H */
diff --git a/drivers/staging/brcm80211/brcmsmac/d11.h b/drivers/net/wireless/brcm80211/brcmsmac/d11.h
index e7ff0e6f28e0..ed51616abc85 100644
--- a/drivers/staging/brcm80211/brcmsmac/d11.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/d11.h
@@ -23,17 +23,15 @@
#include "pub.h"
#include "dma.h"
-#define BCN_TMPL_LEN 512 /* length of the BCN template area */
-
/* RX FIFO numbers */
#define RX_FIFO 0 /* data and ctl frames */
#define RX_TXSTATUS_FIFO 3 /* RX fifo for tx status packages */
-/* TX FIFO numbers using WME Access Classes */
-#define TX_AC_BK_FIFO 0 /* Access Category Background TX FIFO */
-#define TX_AC_BE_FIFO 1 /* Access Category Best-Effort TX FIFO */
-#define TX_AC_VI_FIFO 2 /* Access Class Video TX FIFO */
-#define TX_AC_VO_FIFO 3 /* Access Class Voice TX FIFO */
+/* TX FIFO numbers using WME Access Category */
+#define TX_AC_BK_FIFO 0 /* Background TX FIFO */
+#define TX_AC_BE_FIFO 1 /* Best-Effort TX FIFO */
+#define TX_AC_VI_FIFO 2 /* Video TX FIFO */
+#define TX_AC_VO_FIFO 3 /* Voice TX FIFO */
#define TX_BCMC_FIFO 4 /* Broadcast/Multicast TX FIFO */
#define TX_ATIM_FIFO 5 /* TX fifo for ATIM window info */
@@ -47,11 +45,7 @@
#define TX_DATA_FIFO TX_AC_BE_FIFO
#define TX_CTL_FIFO TX_AC_VO_FIFO
-#ifndef WL_RSSI_ANT_MAX
#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */
-#elif WL_RSSI_ANT_MAX != 4
-#error "WL_RSSI_ANT_MAX does not match"
-#endif
struct intctrlregs {
u32 intstatus;
@@ -73,8 +67,8 @@ struct pio2regs {
/* a pair of pio channels(tx and rx) */
struct pio2regp {
- pio2regs_t tx;
- pio2regs_t rx;
+ struct pio2regs tx;
+ struct pio2regs rx;
};
/* 4byte-wide pio register set per channel(xmt or rcv) */
@@ -85,8 +79,8 @@ struct pio4regs {
/* a pair of pio channels(tx and rx) */
struct pio4regp {
- pio4regs_t tx;
- pio4regs_t rx;
+ struct pio4regs tx;
+ struct pio4regs rx;
};
/* read: 32-bit register that can be read as 32-bit or as 2 16-bit
@@ -101,10 +95,10 @@ union pmqreg {
};
struct fifo64 {
- dma64regs_t dmaxmt; /* dma tx */
- pio4regs_t piotx; /* pio tx */
- dma64regs_t dmarcv; /* dma rx */
- pio4regs_t piorx; /* pio rx */
+ struct dma64regs dmaxmt; /* dma tx */
+ struct pio4regs piotx; /* pio tx */
+ struct dma64regs dmarcv; /* dma rx */
+ struct pio4regs piorx; /* pio rx */
};
/*
@@ -120,7 +114,7 @@ struct d11regs {
u32 usectimer; /* 0x1c *//* for corerev >= 26 */
/* Interrupt Control *//* 0x20 */
- intctrlregs_t intctrlregs[8];
+ struct intctrlregs intctrlregs[8];
u32 PAD[40]; /* 0x60 - 0xFC */
@@ -139,7 +133,7 @@ struct d11regs {
u32 PAD[2]; /* 0x138 - 0x13C */
/* PMQ registers */
- pmqreg_t pmqreg; /* 0x140 */
+ union pmqreg pmqreg; /* 0x140 */
u32 pmqpatl; /* 0x144 */
u32 pmqpath; /* 0x148 */
u32 PAD; /* 0x14C */
@@ -179,10 +173,10 @@ struct d11regs {
u32 PAD[5]; /* 0x1ec - 0x1fc */
/* 0x200-0x37F dma/pio registers */
- fifo64_t fifo64regs[6];
+ struct fifo64 fifo64regs[6];
/* FIFO diagnostic port access */
- dma32diag_t dmafifo; /* 0x380 - 0x38C */
+ struct dma32diag dmafifo; /* 0x380 - 0x38C */
u32 aggfifocnt; /* 0x390 */
u32 aggfifodata; /* 0x394 */
@@ -457,7 +451,7 @@ struct d11regs {
#define IRL_FC_MASK 0xff000000 /* frame count */
#define IRL_FC_SHIFT 24 /* frame count */
-/* maccontrol register */
+/*== maccontrol register ==*/
#define MCTL_GMODE (1U << 31)
#define MCTL_DISCARD_PMQ (1 << 30)
#define MCTL_WAKE (1 << 26)
@@ -481,75 +475,119 @@ struct d11regs {
#define MCTL_PSM_RUN (1 << 1)
#define MCTL_EN_MAC (1 << 0)
-/* maccommand register */
+/*== maccommand register ==*/
#define MCMD_BCN0VLD (1 << 0)
#define MCMD_BCN1VLD (1 << 1)
#define MCMD_DIRFRMQVAL (1 << 2)
#define MCMD_CCA (1 << 3)
#define MCMD_BG_NOISE (1 << 4)
#define MCMD_SKIP_SHMINIT (1 << 5) /* only used for simulation */
-#define MCMD_SAMPLECOLL MCMD_SKIP_SHMINIT /* reuse for sample collect */
-
-/* macintstatus/macintmask */
-#define MI_MACSSPNDD (1 << 0) /* MAC has gracefully suspended */
-#define MI_BCNTPL (1 << 1) /* beacon template available */
-#define MI_TBTT (1 << 2) /* TBTT indication */
-#define MI_BCNSUCCESS (1 << 3) /* beacon successfully tx'd */
-#define MI_BCNCANCLD (1 << 4) /* beacon canceled (IBSS) */
-#define MI_ATIMWINEND (1 << 5) /* end of ATIM-window (IBSS) */
-#define MI_PMQ (1 << 6) /* PMQ entries available */
-#define MI_NSPECGEN_0 (1 << 7) /* non-specific gen-stat bits that are set by PSM */
-#define MI_NSPECGEN_1 (1 << 8) /* non-specific gen-stat bits that are set by PSM */
-#define MI_MACTXERR (1 << 9) /* MAC level Tx error */
-#define MI_NSPECGEN_3 (1 << 10) /* non-specific gen-stat bits that are set by PSM */
-#define MI_PHYTXERR (1 << 11) /* PHY Tx error */
-#define MI_PME (1 << 12) /* Power Management Event */
-#define MI_GP0 (1 << 13) /* General-purpose timer0 */
-#define MI_GP1 (1 << 14) /* General-purpose timer1 */
-#define MI_DMAINT (1 << 15) /* (ORed) DMA-interrupts */
-#define MI_TXSTOP (1 << 16) /* MAC has completed a TX FIFO Suspend/Flush */
-#define MI_CCA (1 << 17) /* MAC has completed a CCA measurement */
-#define MI_BG_NOISE (1 << 18) /* MAC has collected background noise samples */
-#define MI_DTIM_TBTT (1 << 19) /* MBSS DTIM TBTT indication */
-#define MI_PRQ (1 << 20) /* Probe response queue needs attention */
-#define MI_PWRUP (1 << 21) /* Radio/PHY has been powered back up. */
+#define MCMD_SAMPLECOLL MCMD_SKIP_SHMINIT /* reuse for sample collect */
+
+/*== macintstatus/macintmask ==*/
+/* gracefully suspended */
+#define MI_MACSSPNDD (1 << 0)
+/* beacon template available */
+#define MI_BCNTPL (1 << 1)
+/* TBTT indication */
+#define MI_TBTT (1 << 2)
+/* beacon successfully tx'd */
+#define MI_BCNSUCCESS (1 << 3)
+/* beacon canceled (IBSS) */
+#define MI_BCNCANCLD (1 << 4)
+/* end of ATIM-window (IBSS) */
+#define MI_ATIMWINEND (1 << 5)
+/* PMQ entries available */
+#define MI_PMQ (1 << 6)
+/* non-specific gen-stat bits that are set by PSM */
+#define MI_NSPECGEN_0 (1 << 7)
+/* non-specific gen-stat bits that are set by PSM */
+#define MI_NSPECGEN_1 (1 << 8)
+/* MAC level Tx error */
+#define MI_MACTXERR (1 << 9)
+/* non-specific gen-stat bits that are set by PSM */
+#define MI_NSPECGEN_3 (1 << 10)
+/* PHY Tx error */
+#define MI_PHYTXERR (1 << 11)
+/* Power Management Event */
+#define MI_PME (1 << 12)
+/* General-purpose timer0 */
+#define MI_GP0 (1 << 13)
+/* General-purpose timer1 */
+#define MI_GP1 (1 << 14)
+/* (ORed) DMA-interrupts */
+#define MI_DMAINT (1 << 15)
+/* MAC has completed a TX FIFO Suspend/Flush */
+#define MI_TXSTOP (1 << 16)
+/* MAC has completed a CCA measurement */
+#define MI_CCA (1 << 17)
+/* MAC has collected background noise samples */
+#define MI_BG_NOISE (1 << 18)
+/* MBSS DTIM TBTT indication */
+#define MI_DTIM_TBTT (1 << 19)
+/* Probe response queue needs attention */
+#define MI_PRQ (1 << 20)
+/* Radio/PHY has been powered back up. */
+#define MI_PWRUP (1 << 21)
#define MI_RESERVED3 (1 << 22)
#define MI_RESERVED2 (1 << 23)
#define MI_RESERVED1 (1 << 25)
/* MAC detected change on RF Disable input*/
#define MI_RFDISABLE (1 << 28)
-#define MI_TFS (1 << 29) /* MAC has completed a TX */
-#define MI_PHYCHANGED (1 << 30) /* A phy status change wrt G mode */
-#define MI_TO (1U << 31) /* general purpose timeout */
+/* MAC has completed a TX */
+#define MI_TFS (1 << 29)
+/* A phy status change wrt G mode */
+#define MI_PHYCHANGED (1 << 30)
+/* general purpose timeout */
+#define MI_TO (1U << 31)
/* Mac capabilities registers */
-/* machwcap */
+/*== machwcap ==*/
#define MCAP_TKIPMIC 0x80000000 /* TKIP MIC hardware present */
-/* pmqhost data */
-#define PMQH_DATA_MASK 0xffff0000 /* data entry of head pmq entry */
-#define PMQH_BSSCFG 0x00100000 /* PM entry for BSS config */
-#define PMQH_PMOFF 0x00010000 /* PM Mode OFF: power save off */
-#define PMQH_PMON 0x00020000 /* PM Mode ON: power save on */
-#define PMQH_DASAT 0x00040000 /* Dis-associated or De-authenticated */
-#define PMQH_ATIMFAIL 0x00080000 /* ATIM not acknowledged */
-#define PMQH_DEL_ENTRY 0x00000001 /* delete head entry */
-#define PMQH_DEL_MULT 0x00000002 /* delete head entry to cur read pointer -1 */
-#define PMQH_OFLO 0x00000004 /* pmq overflow indication */
-#define PMQH_NOT_EMPTY 0x00000008 /* entries are present in pmq */
-
-/* phydebug */
-#define PDBG_CRS (1 << 0) /* phy is asserting carrier sense */
-#define PDBG_TXA (1 << 1) /* phy is taking xmit byte from mac this cycle */
-#define PDBG_TXF (1 << 2) /* mac is instructing the phy to transmit a frame */
-#define PDBG_TXE (1 << 3) /* phy is signalling a transmit Error to the mac */
-#define PDBG_RXF (1 << 4) /* phy detected the end of a valid frame preamble */
-#define PDBG_RXS (1 << 5) /* phy detected the end of a valid PLCP header */
-#define PDBG_RXFRG (1 << 6) /* rx start not asserted */
-#define PDBG_RXV (1 << 7) /* mac is taking receive byte from phy this cycle */
-#define PDBG_RFD (1 << 16) /* RF portion of the radio is disabled */
-
-/* objaddr register */
+/*== pmqhost data ==*/
+/* data entry of head pmq entry */
+#define PMQH_DATA_MASK 0xffff0000
+/* PM entry for BSS config */
+#define PMQH_BSSCFG 0x00100000
+/* PM Mode OFF: power save off */
+#define PMQH_PMOFF 0x00010000
+/* PM Mode ON: power save on */
+#define PMQH_PMON 0x00020000
+/* Dis-associated or De-authenticated */
+#define PMQH_DASAT 0x00040000
+/* ATIM not acknowledged */
+#define PMQH_ATIMFAIL 0x00080000
+/* delete head entry */
+#define PMQH_DEL_ENTRY 0x00000001
+/* delete head entry to cur read pointer -1 */
+#define PMQH_DEL_MULT 0x00000002
+/* pmq overflow indication */
+#define PMQH_OFLO 0x00000004
+/* entries are present in pmq */
+#define PMQH_NOT_EMPTY 0x00000008
+
+/*== phydebug ==*/
+/* phy is asserting carrier sense */
+#define PDBG_CRS (1 << 0)
+/* phy is taking xmit byte from mac this cycle */
+#define PDBG_TXA (1 << 1)
+/* mac is instructing the phy to transmit a frame */
+#define PDBG_TXF (1 << 2)
+/* phy is signalling a transmit Error to the mac */
+#define PDBG_TXE (1 << 3)
+/* phy detected the end of a valid frame preamble */
+#define PDBG_RXF (1 << 4)
+/* phy detected the end of a valid PLCP header */
+#define PDBG_RXS (1 << 5)
+/* rx start not asserted */
+#define PDBG_RXFRG (1 << 6)
+/* mac is taking receive byte from phy this cycle */
+#define PDBG_RXV (1 << 7)
+/* RF portion of the radio is disabled */
+#define PDBG_RFD (1 << 16)
+
+/*== objaddr register ==*/
#define OBJADDR_SEL_MASK 0x000F0000
#define OBJADDR_UCM_SEL 0x00000000
#define OBJADDR_SHM_SEL 0x00010000
@@ -564,20 +602,20 @@ struct d11regs {
#define WEP_PCMADDR 0x07d4
#define WEP_PCMDATA 0x07d6
-/* frmtxstatus */
+/*== frmtxstatus ==*/
#define TXS_V (1 << 0) /* valid bit */
#define TXS_STATUS_MASK 0xffff
#define TXS_FID_MASK 0xffff0000
#define TXS_FID_SHIFT 16
-/* frmtxstatus2 */
+/*== frmtxstatus2 ==*/
#define TXS_SEQ_MASK 0xffff
#define TXS_PTX_MASK 0xff0000
#define TXS_PTX_SHIFT 16
#define TXS_MU_MASK 0x01000000
#define TXS_MU_SHIFT 24
-/* clk_ctl_st */
+/*== clk_ctl_st ==*/
#define CCS_ERSRC_REQ_D11PLL 0x00000100 /* d11 core pll request */
#define CCS_ERSRC_REQ_PHYPLL 0x00000200 /* PHY pll request */
#define CCS_ERSRC_AVAIL_D11PLL 0x01000000 /* d11 core pll available */
@@ -602,22 +640,27 @@ struct d11regs {
#define TXFIFO_SIZE_UNIT 256 /* one unit corresponds to 256 bytes */
#define MBSS16_TEMPLMEM_MINBLKS 65 /* one unit corresponds to 256 bytes */
-/* phy versions, PhyVersion:Revision field */
-#define PV_AV_MASK 0xf000 /* analog block version */
-#define PV_AV_SHIFT 12 /* analog block version bitfield offset */
-#define PV_PT_MASK 0x0f00 /* phy type */
-#define PV_PT_SHIFT 8 /* phy type bitfield offset */
-#define PV_PV_MASK 0x000f /* phy version */
+/*== phy versions (PhyVersion:Revision field) ==*/
+/* analog block version */
+#define PV_AV_MASK 0xf000
+/* analog block version bitfield offset */
+#define PV_AV_SHIFT 12
+/* phy type */
+#define PV_PT_MASK 0x0f00
+/* phy type bitfield offset */
+#define PV_PT_SHIFT 8
+/* phy version */
+#define PV_PV_MASK 0x000f
#define PHY_TYPE(v) ((v & PV_PT_MASK) >> PV_PT_SHIFT)
-/* phy types, PhyVersion:PhyType field */
+/*== phy types (PhyVersion:PhyType field) ==*/
#define PHY_TYPE_N 4 /* N-Phy value */
#define PHY_TYPE_SSN 6 /* SSLPN-Phy value */
#define PHY_TYPE_LCN 8 /* LCN-Phy value */
#define PHY_TYPE_LCNXN 9 /* LCNXN-Phy value */
#define PHY_TYPE_NULL 0xf /* Invalid Phy value */
-/* analog types, PhyVersion:AnalogType field */
+/*== analog types (PhyVersion:AnalogType field) ==*/
#define ANA_11N_013 5
/* 802.11a PLCP header def */
@@ -693,45 +736,46 @@ struct cck_phy_hdr {
#define BRCMS_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU)
#define BRCMS_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU)
-/* The dot11a PLCP header is 5 bytes. To simplify the software (so that we
- * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header has
- * padding added in the ucode.
+/*
+ * The dot11a PLCP header is 5 bytes. To simplify the software (so that we
+ * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header
+ * has padding added in the ucode.
*/
#define D11_PHY_HDR_LEN 6
/* TX DMA buffer header */
struct d11txh {
- u16 MacTxControlLow; /* 0x0 */
- u16 MacTxControlHigh; /* 0x1 */
- u16 MacFrameControl; /* 0x2 */
- u16 TxFesTimeNormal; /* 0x3 */
- u16 PhyTxControlWord; /* 0x4 */
- u16 PhyTxControlWord_1; /* 0x5 */
- u16 PhyTxControlWord_1_Fbr; /* 0x6 */
- u16 PhyTxControlWord_1_Rts; /* 0x7 */
- u16 PhyTxControlWord_1_FbrRts; /* 0x8 */
- u16 MainRates; /* 0x9 */
- u16 XtraFrameTypes; /* 0xa */
+ __le16 MacTxControlLow; /* 0x0 */
+ __le16 MacTxControlHigh; /* 0x1 */
+ __le16 MacFrameControl; /* 0x2 */
+ __le16 TxFesTimeNormal; /* 0x3 */
+ __le16 PhyTxControlWord; /* 0x4 */
+ __le16 PhyTxControlWord_1; /* 0x5 */
+ __le16 PhyTxControlWord_1_Fbr; /* 0x6 */
+ __le16 PhyTxControlWord_1_Rts; /* 0x7 */
+ __le16 PhyTxControlWord_1_FbrRts; /* 0x8 */
+ __le16 MainRates; /* 0x9 */
+ __le16 XtraFrameTypes; /* 0xa */
u8 IV[16]; /* 0x0b - 0x12 */
u8 TxFrameRA[6]; /* 0x13 - 0x15 */
- u16 TxFesTimeFallback; /* 0x16 */
+ __le16 TxFesTimeFallback; /* 0x16 */
u8 RTSPLCPFallback[6]; /* 0x17 - 0x19 */
- u16 RTSDurFallback; /* 0x1a */
+ __le16 RTSDurFallback; /* 0x1a */
u8 FragPLCPFallback[6]; /* 0x1b - 1d */
- u16 FragDurFallback; /* 0x1e */
- u16 MModeLen; /* 0x1f */
- u16 MModeFbrLen; /* 0x20 */
- u16 TstampLow; /* 0x21 */
- u16 TstampHigh; /* 0x22 */
- u16 ABI_MimoAntSel; /* 0x23 */
- u16 PreloadSize; /* 0x24 */
- u16 AmpduSeqCtl; /* 0x25 */
- u16 TxFrameID; /* 0x26 */
- u16 TxStatus; /* 0x27 */
- u16 MaxNMpdus; /* 0x28 */
- u16 MaxABytes_MRT; /* 0x29 */
- u16 MaxABytes_FBR; /* 0x2a */
- u16 MinMBytes; /* 0x2b */
+ __le16 FragDurFallback; /* 0x1e */
+ __le16 MModeLen; /* 0x1f */
+ __le16 MModeFbrLen; /* 0x20 */
+ __le16 TstampLow; /* 0x21 */
+ __le16 TstampHigh; /* 0x22 */
+ __le16 ABI_MimoAntSel; /* 0x23 */
+ __le16 PreloadSize; /* 0x24 */
+ __le16 AmpduSeqCtl; /* 0x25 */
+ __le16 TxFrameID; /* 0x26 */
+ __le16 TxStatus; /* 0x27 */
+ __le16 MaxNMpdus; /* 0x28 */
+ __le16 MaxABytes_MRT; /* 0x29 */
+ __le16 MaxABytes_FBR; /* 0x2a */
+ __le16 MinMBytes; /* 0x2b */
u8 RTSPhyHeader[D11_PHY_HDR_LEN]; /* 0x2c - 0x2e */
struct ieee80211_rts rts_frame; /* 0x2f - 0x36 */
u16 PAD; /* 0x37 */
@@ -745,14 +789,17 @@ struct d11txh {
#define FT_HT 2
#define FT_N 3
-/* Position of MPDU inside A-MPDU; indicated with bits 10:9 of MacTxControlLow */
+/*
+ * Position of MPDU inside A-MPDU; indicated with bits 10:9
+ * of MacTxControlLow
+ */
#define TXC_AMPDU_SHIFT 9 /* shift for ampdu settings */
#define TXC_AMPDU_NONE 0 /* Regular MPDU, not an A-MPDU */
#define TXC_AMPDU_FIRST 1 /* first MPDU of an A-MPDU */
#define TXC_AMPDU_MIDDLE 2 /* intermediate MPDU of an A-MPDU */
#define TXC_AMPDU_LAST 3 /* last (or single) MPDU of an A-MPDU */
-/* MacTxControlLow */
+/*== MacTxControlLow ==*/
#define TXC_AMIC 0x8000
#define TXC_SENDCTS 0x0800
#define TXC_AMPDU_MASK 0x0600
@@ -766,18 +813,25 @@ struct d11txh {
#define TXC_LONGFRAME 0x0002
#define TXC_IMMEDACK 0x0001
-/* MacTxControlHigh */
-#define TXC_PREAMBLE_RTS_FB_SHORT 0x8000 /* RTS fallback preamble type 1 = SHORT 0 = LONG */
-#define TXC_PREAMBLE_RTS_MAIN_SHORT 0x4000 /* RTS main rate preamble type 1 = SHORT 0 = LONG */
-#define TXC_PREAMBLE_DATA_FB_SHORT 0x2000 /* Main fallback rate preamble type
- * 1 = SHORT for OFDM/GF for MIMO
- * 0 = LONG for CCK/MM for MIMO
- */
+/*== MacTxControlHigh ==*/
+/* RTS fallback preamble type 1 = SHORT 0 = LONG */
+#define TXC_PREAMBLE_RTS_FB_SHORT 0x8000
+/* RTS main rate preamble type 1 = SHORT 0 = LONG */
+#define TXC_PREAMBLE_RTS_MAIN_SHORT 0x4000
+/*
+ * Main fallback rate preamble type
+ * 1 = SHORT for OFDM/GF for MIMO
+ * 0 = LONG for CCK/MM for MIMO
+ */
+#define TXC_PREAMBLE_DATA_FB_SHORT 0x2000
+
/* TXC_PREAMBLE_DATA_MAIN is in PhyTxControl bit 5 */
-#define TXC_AMPDU_FBR 0x1000 /* use fallback rate for this AMPDU */
+/* use fallback rate for this AMPDU */
+#define TXC_AMPDU_FBR 0x1000
#define TXC_SECKEY_MASK 0x0FF0
#define TXC_SECKEY_SHIFT 4
-#define TXC_ALT_TXPWR 0x0008 /* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */
+/* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */
+#define TXC_ALT_TXPWR 0x0008
#define TXC_SECTYPE_MASK 0x0007
#define TXC_SECTYPE_SHIFT 0
@@ -817,7 +871,7 @@ struct d11txh {
#define PHY_TXC1_MODE_SDM 3
/* PhyTxControl for HTphy that are different from Mimophy */
-#define PHY_TXC_HTANT_MASK 0x3fC0 /* bit 6, 7, 8, 9, 10, 11, 12, 13 */
+#define PHY_TXC_HTANT_MASK 0x3fC0 /* bits 6-13 */
/* XtraFrameTypes */
#define XFTS_RTS_FT_SHIFT 2
@@ -862,23 +916,23 @@ struct tx_status {
#define TX_STATUS_RTS_RTX_MASK 0x0F00
#define TX_STATUS_RTS_RTX_SHIFT 8
#define TX_STATUS_MASK 0x00FE
-#define TX_STATUS_PMINDCTD (1 << 7) /* PM mode indicated to AP */
-#define TX_STATUS_INTERMEDIATE (1 << 6) /* intermediate or 1st ampdu pkg */
-#define TX_STATUS_AMPDU (1 << 5) /* AMPDU status */
-#define TX_STATUS_SUPR_MASK 0x1C /* suppress status bits (4:2) */
+#define TX_STATUS_PMINDCTD (1 << 7) /* PM mode indicated to AP */
+#define TX_STATUS_INTERMEDIATE (1 << 6) /* intermediate or 1st ampdu pkg */
+#define TX_STATUS_AMPDU (1 << 5) /* AMPDU status */
+#define TX_STATUS_SUPR_MASK 0x1C /* suppress status bits (4:2) */
#define TX_STATUS_SUPR_SHIFT 2
-#define TX_STATUS_ACK_RCV (1 << 1) /* ACK received */
-#define TX_STATUS_VALID (1 << 0) /* Tx status valid */
+#define TX_STATUS_ACK_RCV (1 << 1) /* ACK received */
+#define TX_STATUS_VALID (1 << 0) /* Tx status valid */
#define TX_STATUS_NO_ACK 0
/* suppress status reason codes */
-#define TX_STATUS_SUPR_PMQ (1 << 2) /* PMQ entry */
-#define TX_STATUS_SUPR_FLUSH (2 << 2) /* flush request */
-#define TX_STATUS_SUPR_FRAG (3 << 2) /* previous frag failure */
-#define TX_STATUS_SUPR_TBTT (3 << 2) /* SHARED: Probe response supr for TBTT */
-#define TX_STATUS_SUPR_BADCH (4 << 2) /* channel mismatch */
-#define TX_STATUS_SUPR_EXPTIME (5 << 2) /* lifetime expiry */
-#define TX_STATUS_SUPR_UF (6 << 2) /* underflow */
+#define TX_STATUS_SUPR_PMQ (1 << 2) /* PMQ entry */
+#define TX_STATUS_SUPR_FLUSH (2 << 2) /* flush request */
+#define TX_STATUS_SUPR_FRAG (3 << 2) /* previous frag failure */
+#define TX_STATUS_SUPR_TBTT (3 << 2) /* SHARED: Probe resp supr for TBTT */
+#define TX_STATUS_SUPR_BADCH (4 << 2) /* channel mismatch */
+#define TX_STATUS_SUPR_EXPTIME (5 << 2) /* lifetime expiry */
+#define TX_STATUS_SUPR_UF (6 << 2) /* underflow */
/* Unexpected tx status for rate update */
#define TX_STATUS_UNEXP(status) \
@@ -939,8 +993,8 @@ struct tx_status {
#define ADDR_BMP_RA (1 << 0) /* Receiver Address (RA) */
#define ADDR_BMP_TA (1 << 1) /* Transmitter Address (TA) */
#define ADDR_BMP_BSSID (1 << 2) /* BSSID */
-#define ADDR_BMP_AP (1 << 3) /* Infra-BSS Access Point (AP) */
-#define ADDR_BMP_STA (1 << 4) /* Infra-BSS Station (STA) */
+#define ADDR_BMP_AP (1 << 3) /* Infra-BSS Access Point */
+#define ADDR_BMP_STA (1 << 4) /* Infra-BSS Station */
#define ADDR_BMP_RESERVED1 (1 << 5)
#define ADDR_BMP_RESERVED2 (1 << 6)
#define ADDR_BMP_RESERVED3 (1 << 7)
@@ -1012,9 +1066,10 @@ struct tx_status {
#define T_BCN0_TPL_BASE (0x34 * 2)
#define T_PRS_TPL_BASE (0x134 * 2)
#define T_BCN1_TPL_BASE (0x234 * 2)
-#define T_TX_FIFO_TXRAM_BASE (T_ACTS_TPL_BASE + (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT))
+#define T_TX_FIFO_TXRAM_BASE (T_ACTS_TPL_BASE + \
+ (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT))
-#define T_BA_TPL_BASE T_QNULL_TPL_BASE /* template area for BA */
+#define T_BA_TPL_BASE T_QNULL_TPL_BASE /* template area for BA */
#define T_RAM_ACCESS_SZ 4 /* template ram is 4 byte access only */
@@ -1207,14 +1262,18 @@ struct tx_status {
#define WATCHDOG_8TU_MAX 10
/* Manufacturing Test Variables */
-#define M_PKTENG_CTRL (0x6c * 2) /* PER test mode */
-#define M_PKTENG_IFS (0x6d * 2) /* IFS for TX mode */
-#define M_PKTENG_FRMCNT_LO (0x6e * 2) /* Lower word of tx frmcnt/rx lostcnt */
-#define M_PKTENG_FRMCNT_HI (0x6f * 2) /* Upper word of tx frmcnt/rx lostcnt */
+/* PER test mode */
+#define M_PKTENG_CTRL (0x6c * 2)
+/* IFS for TX mode */
+#define M_PKTENG_IFS (0x6d * 2)
+/* Lower word of tx frmcnt/rx lostcnt */
+#define M_PKTENG_FRMCNT_LO (0x6e * 2)
+/* Upper word of tx frmcnt/rx lostcnt */
+#define M_PKTENG_FRMCNT_HI (0x6f * 2)
/* Index variation in vbat ripple */
-#define M_LCN_PWR_IDX_MAX (0x67 * 2) /* highest index read by ucode */
-#define M_LCN_PWR_IDX_MIN (0x66 * 2) /* lowest index read by ucode */
+#define M_LCN_PWR_IDX_MAX (0x67 * 2) /* highest index read by ucode */
+#define M_LCN_PWR_IDX_MIN (0x66 * 2) /* lowest index read by ucode */
/* M_PKTENG_CTRL bit definitions */
#define M_PKTENG_MODE_TX 0x0001
@@ -1223,11 +1282,14 @@ struct tx_status {
#define M_PKTENG_MODE_RX 0x0002
#define M_PKTENG_MODE_RX_WITH_ACK 0x0402
#define M_PKTENG_MODE_MASK 0x0003
-#define M_PKTENG_FRMCNT_VLD 0x0100 /* TX frames indicated in the frmcnt reg */
+/* TX frames indicated in the frmcnt reg */
+#define M_PKTENG_FRMCNT_VLD 0x0100
/* Sample Collect parameters (bitmap and type) */
-#define M_SMPL_COL_BMP (0x37d * 2) /* Trigger bitmap for sample collect */
-#define M_SMPL_COL_CTL (0x3b2 * 2) /* Sample collect type */
+/* Trigger bitmap for sample collect */
+#define M_SMPL_COL_BMP (0x37d * 2)
+/* Sample collect type */
+#define M_SMPL_COL_CTL (0x3b2 * 2)
#define ANTSEL_CLKDIV_4MHZ 6
#define MIMO_ANTSEL_BUSY 0x4000 /* bit 14 (busy) */
@@ -1259,27 +1321,36 @@ struct shm_acparams {
#define MHF5 4 /* Hostflag 5 index */
/* Flags in M_HOST_FLAGS */
-#define MHF1_ANTDIV 0x0001 /* Enable ucode antenna diversity help */
-#define MHF1_EDCF 0x0100 /* Enable EDCF access control */
+/* Enable ucode antenna diversity help */
+#define MHF1_ANTDIV 0x0001
+/* Enable EDCF access control */
+#define MHF1_EDCF 0x0100
#define MHF1_IQSWAP_WAR 0x0200
-#define MHF1_FORCEFASTCLK 0x0400 /* Disable Slow clock request, for corerev < 11 */
+/* Disable Slow clock request, for corerev < 11 */
+#define MHF1_FORCEFASTCLK 0x0400
/* Flags in M_HOST_FLAGS2 */
-#define MHF2_PCISLOWCLKWAR 0x0008 /* PR16165WAR : Enable ucode PCI slow clock WAR */
-#define MHF2_TXBCMC_NOW 0x0040 /* Flush BCMC FIFO immediately */
-#define MHF2_HWPWRCTL 0x0080 /* Enable ucode/hw power control */
+
+/* Flush BCMC FIFO immediately */
+#define MHF2_TXBCMC_NOW 0x0040
+/* Enable ucode/hw power control */
+#define MHF2_HWPWRCTL 0x0080
#define MHF2_NPHY40MHZ_WAR 0x0800
/* Flags in M_HOST_FLAGS3 */
-#define MHF3_ANTSEL_EN 0x0001 /* enabled mimo antenna selection */
-#define MHF3_ANTSEL_MODE 0x0002 /* antenna selection mode: 0: 2x3, 1: 2x4 */
+/* enabled mimo antenna selection */
+#define MHF3_ANTSEL_EN 0x0001
+/* antenna selection mode: 0: 2x3, 1: 2x4 */
+#define MHF3_ANTSEL_MODE 0x0002
#define MHF3_RESERVED1 0x0004
#define MHF3_RESERVED2 0x0008
#define MHF3_NPHY_MLADV_WAR 0x0010
/* Flags in M_HOST_FLAGS4 */
-#define MHF4_BPHY_TXCORE0 0x0080 /* force bphy Tx on core 0 (board level WAR) */
-#define MHF4_EXTPA_ENABLE 0x4000 /* for 4313A0 FEM boards */
+/* force bphy Tx on core 0 (board level WAR) */
+#define MHF4_BPHY_TXCORE0 0x0080
+/* for 4313A0 FEM boards */
+#define MHF4_EXTPA_ENABLE 0x4000
/* Flags in M_HOST_FLAGS5 */
#define MHF5_4313_GPIOCTRL 0x0001
@@ -1292,52 +1363,80 @@ struct shm_acparams {
#define M_PHY_NOISE (0x037 * 2)
#define PHY_NOISE_MASK 0x00ff
-/* Receive Frame Data Header for 802.11b DCF-only frames */
-struct d11rxhdr {
- u16 RxFrameSize; /* Actual byte length of the frame data received */
+/*
+ * Receive Frame Data Header for 802.11b DCF-only frames
+ *
+ * RxFrameSize: Actual byte length of the frame data received
+ * PAD: padding (not used)
+ * PhyRxStatus_0: PhyRxStatus 15:0
+ * PhyRxStatus_1: PhyRxStatus 31:16
+ * PhyRxStatus_2: PhyRxStatus 47:32
+ * PhyRxStatus_3: PhyRxStatus 63:48
+ * PhyRxStatus_4: PhyRxStatus 79:64
+ * PhyRxStatus_5: PhyRxStatus 95:80
+ * RxStatus1: MAC Rx Status
+ * RxStatus2: extended MAC Rx status
+ * RxTSFTime: RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY
+ * RxChan: gain code, channel radio code, and phy type
+ */
+struct d11rxhdr_le {
+ __le16 RxFrameSize;
u16 PAD;
- u16 PhyRxStatus_0; /* PhyRxStatus 15:0 */
- u16 PhyRxStatus_1; /* PhyRxStatus 31:16 */
- u16 PhyRxStatus_2; /* PhyRxStatus 47:32 */
- u16 PhyRxStatus_3; /* PhyRxStatus 63:48 */
- u16 PhyRxStatus_4; /* PhyRxStatus 79:64 */
- u16 PhyRxStatus_5; /* PhyRxStatus 95:80 */
- u16 RxStatus1; /* MAC Rx Status */
- u16 RxStatus2; /* extended MAC Rx status */
- u16 RxTSFTime; /* RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY */
- u16 RxChan; /* gain code, channel radio code, and phy type */
+ __le16 PhyRxStatus_0;
+ __le16 PhyRxStatus_1;
+ __le16 PhyRxStatus_2;
+ __le16 PhyRxStatus_3;
+ __le16 PhyRxStatus_4;
+ __le16 PhyRxStatus_5;
+ __le16 RxStatus1;
+ __le16 RxStatus2;
+ __le16 RxTSFTime;
+ __le16 RxChan;
} __packed;
-#define RXHDR_LEN 24 /* sizeof struct d11rxhdr */
-#define FRAMELEN(h) ((h)->RxFrameSize)
-
-struct brcms_d11rxhdr {
- struct d11rxhdr rxhdr;
- u32 tsf_l; /* TSF_L reading */
- s8 rssi; /* computed instanteneous rssi in BMAC */
- s8 rxpwr0; /* obsoleted, place holder for legacy ROM code. use rxpwr[] */
- s8 rxpwr1; /* obsoleted, place holder for legacy ROM code. use rxpwr[] */
- s8 do_rssi_ma; /* do per-pkt sampling for per-antenna ma in HIGH */
- s8 rxpwr[WL_RSSI_ANT_MAX]; /* rssi for supported antennas */
+struct d11rxhdr {
+ u16 RxFrameSize;
+ u16 PAD;
+ u16 PhyRxStatus_0;
+ u16 PhyRxStatus_1;
+ u16 PhyRxStatus_2;
+ u16 PhyRxStatus_3;
+ u16 PhyRxStatus_4;
+ u16 PhyRxStatus_5;
+ u16 RxStatus1;
+ u16 RxStatus2;
+ u16 RxTSFTime;
+ u16 RxChan;
} __packed;
/* PhyRxStatus_0: */
-#define PRXS0_FT_MASK 0x0003 /* NPHY only: CCK, OFDM, preN, N */
-#define PRXS0_CLIP_MASK 0x000C /* NPHY only: clip count adjustment steps by AGC */
+/* NPHY only: CCK, OFDM, preN, N */
+#define PRXS0_FT_MASK 0x0003
+/* NPHY only: clip count adjustment steps by AGC */
+#define PRXS0_CLIP_MASK 0x000C
#define PRXS0_CLIP_SHIFT 2
-#define PRXS0_UNSRATE 0x0010 /* PHY received a frame with unsupported rate */
-#define PRXS0_RXANT_UPSUBBAND 0x0020 /* GPHY: rx ant, NPHY: upper sideband */
-#define PRXS0_LCRS 0x0040 /* CCK frame only: lost crs during cck frame reception */
-#define PRXS0_SHORTH 0x0080 /* Short Preamble */
-#define PRXS0_PLCPFV 0x0100 /* PLCP violation */
-#define PRXS0_PLCPHCF 0x0200 /* PLCP header integrity check failed */
-#define PRXS0_GAIN_CTL 0x4000 /* legacy PHY gain control */
-#define PRXS0_ANTSEL_MASK 0xF000 /* NPHY: Antennas used for received frame, bitmask */
+/* PHY received a frame with unsupported rate */
+#define PRXS0_UNSRATE 0x0010
+/* GPHY: rx ant, NPHY: upper sideband */
+#define PRXS0_RXANT_UPSUBBAND 0x0020
+/* CCK frame only: lost crs during cck frame reception */
+#define PRXS0_LCRS 0x0040
+/* Short Preamble */
+#define PRXS0_SHORTH 0x0080
+/* PLCP violation */
+#define PRXS0_PLCPFV 0x0100
+/* PLCP header integrity check failed */
+#define PRXS0_PLCPHCF 0x0200
+/* legacy PHY gain control */
+#define PRXS0_GAIN_CTL 0x4000
+/* NPHY: Antennas used for received frame, bitmask */
+#define PRXS0_ANTSEL_MASK 0xF000
#define PRXS0_ANTSEL_SHIFT 0x12
/* subfield PRXS0_FT_MASK */
#define PRXS0_CCK 0x0000
-#define PRXS0_OFDM 0x0001 /* valid only for G phy, use rxh->RxChan for A phy */
+/* valid only for G phy, use rxh->RxChan for A phy */
+#define PRXS0_OFDM 0x0001
#define PRXS0_PREN 0x0002
#define PRXS0_STDN 0x0003
@@ -1364,35 +1463,51 @@ struct brcms_d11rxhdr {
#define PRXS0_UNUSED 0xF000 /* unused and not defined; set to 0 */
/* htphy PhyRxStatus_1: */
-#define PRXS1_HTPHY_CORE_MASK 0x000F /* core enables for {3..0}, 0=disabled, 1=enabled */
-#define PRXS1_HTPHY_ANTCFG_MASK 0x00F0 /* antenna configation */
-#define PRXS1_HTPHY_MMPLCPLenL_MASK 0xFF00 /* Mixmode PLCP Length low byte mask */
+/* core enables for {3..0}, 0=disabled, 1=enabled */
+#define PRXS1_HTPHY_CORE_MASK 0x000F
+/* antenna configation */
+#define PRXS1_HTPHY_ANTCFG_MASK 0x00F0
+/* Mixmode PLCP Length low byte mask */
+#define PRXS1_HTPHY_MMPLCPLenL_MASK 0xFF00
/* htphy PhyRxStatus_2: */
-#define PRXS2_HTPHY_MMPLCPLenH_MASK 0x000F /* Mixmode PLCP Length high byte maskw */
-#define PRXS2_HTPHY_MMPLCH_RATE_MASK 0x00F0 /* Mixmode PLCP rate mask */
-#define PRXS2_HTPHY_RXPWR_ANT0 0xFF00 /* Rx power on core 0 */
+/* Mixmode PLCP Length high byte maskw */
+#define PRXS2_HTPHY_MMPLCPLenH_MASK 0x000F
+/* Mixmode PLCP rate mask */
+#define PRXS2_HTPHY_MMPLCH_RATE_MASK 0x00F0
+/* Rx power on core 0 */
+#define PRXS2_HTPHY_RXPWR_ANT0 0xFF00
/* htphy PhyRxStatus_3: */
-#define PRXS3_HTPHY_RXPWR_ANT1 0x00FF /* Rx power on core 1 */
-#define PRXS3_HTPHY_RXPWR_ANT2 0xFF00 /* Rx power on core 2 */
+/* Rx power on core 1 */
+#define PRXS3_HTPHY_RXPWR_ANT1 0x00FF
+/* Rx power on core 2 */
+#define PRXS3_HTPHY_RXPWR_ANT2 0xFF00
/* htphy PhyRxStatus_4: */
-#define PRXS4_HTPHY_RXPWR_ANT3 0x00FF /* Rx power on core 3 */
-#define PRXS4_HTPHY_CFO 0xFF00 /* Coarse frequency offset */
+/* Rx power on core 3 */
+#define PRXS4_HTPHY_RXPWR_ANT3 0x00FF
+/* Coarse frequency offset */
+#define PRXS4_HTPHY_CFO 0xFF00
/* htphy PhyRxStatus_5: */
-#define PRXS5_HTPHY_FFO 0x00FF /* Fine frequency offset */
-#define PRXS5_HTPHY_AR 0xFF00 /* Advance Retard */
+/* Fine frequency offset */
+#define PRXS5_HTPHY_FFO 0x00FF
+/* Advance Retard */
+#define PRXS5_HTPHY_AR 0xFF00
-#define HTPHY_MMPLCPLen(rxs) ((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \
+#define HTPHY_MMPLCPLen(rxs) \
+ ((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \
(((rxs)->PhyRxStatus_2 & PRXS2_HTPHY_MMPLCPLenH_MASK) << 8))
/* Get Rx power on core 0 */
-#define HTPHY_RXPWR_ANT0(rxs) ((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8)
+#define HTPHY_RXPWR_ANT0(rxs) \
+ ((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8)
/* Get Rx power on core 1 */
-#define HTPHY_RXPWR_ANT1(rxs) (((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1)
+#define HTPHY_RXPWR_ANT1(rxs) \
+ (((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1)
/* Get Rx power on core 2 */
-#define HTPHY_RXPWR_ANT2(rxs) ((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8)
+#define HTPHY_RXPWR_ANT2(rxs) \
+ ((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8)
/* ucode RxStatus1: */
#define RXS_BCNSENT 0x8000
@@ -1400,7 +1515,8 @@ struct brcms_d11rxhdr {
#define RXS_SECKINDX_SHIFT 5
#define RXS_DECERR (1 << 4)
#define RXS_DECATMPT (1 << 3)
-#define RXS_PBPRES (1 << 2) /* PAD bytes to make IP data 4 bytes aligned */
+/* PAD bytes to make IP data 4 bytes aligned */
+#define RXS_PBPRES (1 << 2)
#define RXS_RESPFRAMETX (1 << 1)
#define RXS_FCSERR (1 << 0)
@@ -1433,16 +1549,17 @@ struct brcms_d11rxhdr {
#define M_PSM_SOFT_REGS 0x0
#define M_BOM_REV_MAJOR (M_PSM_SOFT_REGS + 0x0)
#define M_BOM_REV_MINOR (M_PSM_SOFT_REGS + 0x2)
-#define M_UCODE_DBGST (M_PSM_SOFT_REGS + 0x40) /* ucode debug status code */
-#define M_UCODE_MACSTAT (M_PSM_SOFT_REGS + 0xE0) /* macstat counters */
+#define M_UCODE_DBGST (M_PSM_SOFT_REGS + 0x40) /* ucode debug status code */
+#define M_UCODE_MACSTAT (M_PSM_SOFT_REGS + 0xE0) /* macstat counters */
-#define M_AGING_THRSH (0x3e * 2) /* max time waiting for medium before tx */
-#define M_MBURST_SIZE (0x40 * 2) /* max frames in a frameburst */
-#define M_MBURST_TXOP (0x41 * 2) /* max frameburst TXOP in unit of us */
-#define M_SYNTHPU_DLY (0x4a * 2) /* pre-wakeup for synthpu, default: 500 */
+#define M_AGING_THRSH (0x3e * 2) /* max time waiting for medium before tx */
+#define M_MBURST_SIZE (0x40 * 2) /* max frames in a frameburst */
+#define M_MBURST_TXOP (0x41 * 2) /* max frameburst TXOP in unit of us */
+#define M_SYNTHPU_DLY (0x4a * 2) /* pre-wakeup for synthpu, default: 500 */
#define M_PRETBTT (0x4b * 2)
-#define M_ALT_TXPWR_IDX (M_PSM_SOFT_REGS + (0x3b * 2)) /* offset to the target txpwr */
+/* offset to the target txpwr */
+#define M_ALT_TXPWR_IDX (M_PSM_SOFT_REGS + (0x3b * 2))
#define M_PHY_TX_FLT_PTR (M_PSM_SOFT_REGS + (0x3d * 2))
#define M_CTS_DURATION (M_PSM_SOFT_REGS + (0x5c * 2))
#define M_LP_RCCAL_OVR (M_PSM_SOFT_REGS + (0x6b * 2))
@@ -1451,11 +1568,16 @@ struct brcms_d11rxhdr {
#define M_RXSTATS_BLK_PTR (M_PSM_SOFT_REGS + (0x65 * 2))
/* ucode debug status codes */
-#define DBGST_INACTIVE 0 /* not valid really */
-#define DBGST_INIT 1 /* after zeroing SHM, before suspending at init */
-#define DBGST_ACTIVE 2 /* "normal" state */
-#define DBGST_SUSPENDED 3 /* suspended */
-#define DBGST_ASLEEP 4 /* asleep (PS mode) */
+/* not valid really */
+#define DBGST_INACTIVE 0
+/* after zeroing SHM, before suspending at init */
+#define DBGST_INIT 1
+/* "normal" state */
+#define DBGST_ACTIVE 2
+/* suspended */
+#define DBGST_SUSPENDED 3
+/* asleep (PS mode) */
+#define DBGST_ASLEEP 4
/* Scratch Reg defs */
enum _ePsmScratchPadRegDefinitions {
@@ -1463,66 +1585,66 @@ enum _ePsmScratchPadRegDefinitions {
S_RSV1,
S_RSV2,
- /* scratch registers for Dot11-contants */
- S_DOT11_CWMIN, /* CW-minimum 0x03 */
- S_DOT11_CWMAX, /* CW-maximum 0x04 */
- S_DOT11_CWCUR, /* CW-current 0x05 */
- S_DOT11_SRC_LMT, /* short retry count limit 0x06 */
- S_DOT11_LRC_LMT, /* long retry count limit 0x07 */
- S_DOT11_DTIMCOUNT, /* DTIM-count 0x08 */
-
- /* Tx-side scratch registers */
- S_SEQ_NUM, /* hardware sequence number reg 0x09 */
- S_SEQ_NUM_FRAG, /* seq-num for frags (Set at the start os MSDU 0x0A */
- S_FRMRETX_CNT, /* frame retx count 0x0B */
- S_SSRC, /* Station short retry count 0x0C */
- S_SLRC, /* Station long retry count 0x0D */
- S_EXP_RSP, /* Expected response frame 0x0E */
- S_OLD_BREM, /* Remaining backoff ctr 0x0F */
- S_OLD_CWWIN, /* saved-off CW-cur 0x10 */
- S_TXECTL, /* TXE-Ctl word constructed in scr-pad 0x11 */
- S_CTXTST, /* frm type-subtype as read from Tx-descr 0x12 */
-
- /* Rx-side scratch registers */
- S_RXTST, /* Type and subtype in Rxframe 0x13 */
+ /* offset 0x03: scratch registers for Dot11-contants */
+ S_DOT11_CWMIN, /* CW-minimum */
+ S_DOT11_CWMAX, /* CW-maximum */
+ S_DOT11_CWCUR, /* CW-current */
+ S_DOT11_SRC_LMT, /* short retry count limit */
+ S_DOT11_LRC_LMT, /* long retry count limit */
+ S_DOT11_DTIMCOUNT, /* DTIM-count */
+
+ /* offset 0x09: Tx-side scratch registers */
+ S_SEQ_NUM, /* hardware sequence number reg */
+ S_SEQ_NUM_FRAG, /* seq num for frags (at the start of MSDU) */
+ S_FRMRETX_CNT, /* frame retx count */
+ S_SSRC, /* Station short retry count */
+ S_SLRC, /* Station long retry count */
+ S_EXP_RSP, /* Expected response frame */
+ S_OLD_BREM, /* Remaining backoff ctr */
+ S_OLD_CWWIN, /* saved-off CW-cur */
+ S_TXECTL, /* TXE-Ctl word constructed in scr-pad */
+ S_CTXTST, /* frm type-subtype as read from Tx-descr */
+
+ /* offset 0x13: Rx-side scratch registers */
+ S_RXTST, /* Type and subtype in Rxframe */
/* Global state register */
- S_STREG, /* state storage actual bit maps below 0x14 */
-
- S_TXPWR_SUM, /* Tx power control: accumulator 0x15 */
- S_TXPWR_ITER, /* Tx power control: iteration 0x16 */
- S_RX_FRMTYPE, /* Rate and PHY type for frames 0x17 */
- S_THIS_AGG, /* Size of this AGG (A-MSDU) 0x18 */
-
- S_KEYINDX, /* 0x19 */
- S_RXFRMLEN, /* Receive MPDU length in bytes 0x1A */
-
- /* Receive TSF time stored in SCR */
- S_RXTSFTMRVAL_WD3, /* TSF value at the start of rx 0x1B */
- S_RXTSFTMRVAL_WD2, /* TSF value at the start of rx 0x1C */
- S_RXTSFTMRVAL_WD1, /* TSF value at the start of rx 0x1D */
- S_RXTSFTMRVAL_WD0, /* TSF value at the start of rx 0x1E */
- S_RXSSN, /* Received start seq number for A-MPDU BA 0x1F */
- S_RXQOSFLD, /* Rx-QoS field (if present) 0x20 */
-
- /* Scratch pad regs used in microcode as temp storage */
- S_TMP0, /* stmp0 0x21 */
- S_TMP1, /* stmp1 0x22 */
- S_TMP2, /* stmp2 0x23 */
- S_TMP3, /* stmp3 0x24 */
- S_TMP4, /* stmp4 0x25 */
- S_TMP5, /* stmp5 0x26 */
- S_PRQPENALTY_CTR, /* Probe response queue penalty counter 0x27 */
- S_ANTCNT, /* unsuccessful attempts on current ant. 0x28 */
- S_SYMBOL, /* flag for possible symbol ctl frames 0x29 */
- S_RXTP, /* rx frame type 0x2A */
- S_STREG2, /* extra state storage 0x2B */
- S_STREG3, /* even more extra state storage 0x2C */
- S_STREG4, /* ... 0x2D */
- S_STREG5, /* remember to initialize it to zero 0x2E */
+ S_STREG, /* state storage actual bit maps below */
+
+ S_TXPWR_SUM, /* Tx power control: accumulator */
+ S_TXPWR_ITER, /* Tx power control: iteration */
+ S_RX_FRMTYPE, /* Rate and PHY type for frames */
+ S_THIS_AGG, /* Size of this AGG (A-MSDU) */
+
+ S_KEYINDX,
+ S_RXFRMLEN, /* Receive MPDU length in bytes */
+
+ /* offset 0x1B: Receive TSF time stored in SCR */
+ S_RXTSFTMRVAL_WD3, /* TSF value at the start of rx */
+ S_RXTSFTMRVAL_WD2, /* TSF value at the start of rx */
+ S_RXTSFTMRVAL_WD1, /* TSF value at the start of rx */
+ S_RXTSFTMRVAL_WD0, /* TSF value at the start of rx */
+ S_RXSSN, /* Received start seq number for A-MPDU BA */
+ S_RXQOSFLD, /* Rx-QoS field (if present) */
+
+ /* offset 0x21: Scratch pad regs used in microcode as temp storage */
+ S_TMP0, /* stmp0 */
+ S_TMP1, /* stmp1 */
+ S_TMP2, /* stmp2 */
+ S_TMP3, /* stmp3 */
+ S_TMP4, /* stmp4 */
+ S_TMP5, /* stmp5 */
+ S_PRQPENALTY_CTR, /* Probe response queue penalty counter */
+ S_ANTCNT, /* unsuccessful attempts on current ant. */
+ S_SYMBOL, /* flag for possible symbol ctl frames */
+ S_RXTP, /* rx frame type */
+ S_STREG2, /* extra state storage */
+ S_STREG3, /* even more extra state storage */
+ S_STREG4, /* ... */
+ S_STREG5, /* remember to initialize it to zero */
S_ADJPWR_IDX,
- S_CUR_PTR, /* Temp pointer for A-MPDU re-Tx SHM table 0x32 */
+ S_CUR_PTR, /* Temp pointer for A-MPDU re-Tx SHM table */
S_REVID4, /* 0x33 */
S_INDX, /* 0x34 */
S_ADDR0, /* 0x35 */
@@ -1532,9 +1654,9 @@ enum _ePsmScratchPadRegDefinitions {
S_ADDR4, /* 0x39 */
S_ADDR5, /* 0x3A */
S_TMP6, /* 0x3B */
- S_KEYINDX_BU, /* Backup for Key index 0x3C */
- S_MFGTEST_TMP0, /* Temp register used for RX test calculations 0x3D */
- S_RXESN, /* Received end sequence number for A-MPDU BA 0x3E */
+ S_KEYINDX_BU, /* Backup for Key index */
+ S_MFGTEST_TMP0, /* Temp regs used for RX test calculations */
+ S_RXESN, /* Received end sequence number for A-MPDU BA */
S_STREG6, /* 0x3F */
};
@@ -1628,7 +1750,8 @@ struct macstat {
#define SISF_FCLKA 0x0004 /* FastClkAvailable */
#define SISF_DB_PHY 0x0008 /* Dualband phy */
-/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg, radio and LPPHY regs are separated === */
+/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg === */
+/* radio and LPPHY regs are separated */
#define BPHY_REG_OFT_BASE 0x0
/* offsets for indirect access to bphy registers */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
new file mode 100644
index 000000000000..b56a30297c26
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
@@ -0,0 +1,1425 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <brcmu_utils.h>
+#include <aiutils.h>
+#include "types.h"
+#include "dma.h"
+
+/*
+ * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within
+ * a contiguous 8kB physical address.
+ */
+#define D64RINGALIGN_BITS 13
+#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS)
+#define D64RINGALIGN (1 << D64RINGALIGN_BITS)
+
+#define D64MAXDD (D64MAXRINGSZ / sizeof(struct dma64desc))
+
+/* transmit channel control */
+#define D64_XC_XE 0x00000001 /* transmit enable */
+#define D64_XC_SE 0x00000002 /* transmit suspend request */
+#define D64_XC_LE 0x00000004 /* loopback enable */
+#define D64_XC_FL 0x00000010 /* flush request */
+#define D64_XC_PD 0x00000800 /* parity check disable */
+#define D64_XC_AE 0x00030000 /* address extension bits */
+#define D64_XC_AE_SHIFT 16
+
+/* transmit descriptor table pointer */
+#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */
+
+/* transmit channel status */
+#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */
+#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */
+#define D64_XS0_XS_SHIFT 28
+#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */
+#define D64_XS0_XS_ACTIVE 0x10000000 /* active */
+#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */
+#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */
+#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */
+
+#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */
+#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */
+#define D64_XS1_XE_SHIFT 28
+#define D64_XS1_XE_NOERR 0x00000000 /* no error */
+#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */
+#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */
+#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */
+#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */
+#define D64_XS1_XE_COREE 0x50000000 /* core error */
+
+/* receive channel control */
+/* receive enable */
+#define D64_RC_RE 0x00000001
+/* receive frame offset */
+#define D64_RC_RO_MASK 0x000000fe
+#define D64_RC_RO_SHIFT 1
+/* direct fifo receive (pio) mode */
+#define D64_RC_FM 0x00000100
+/* separate rx header descriptor enable */
+#define D64_RC_SH 0x00000200
+/* overflow continue */
+#define D64_RC_OC 0x00000400
+/* parity check disable */
+#define D64_RC_PD 0x00000800
+/* address extension bits */
+#define D64_RC_AE 0x00030000
+#define D64_RC_AE_SHIFT 16
+
+/* flags for dma controller */
+/* partity enable */
+#define DMA_CTRL_PEN (1 << 0)
+/* rx overflow continue */
+#define DMA_CTRL_ROC (1 << 1)
+/* allow rx scatter to multiple descriptors */
+#define DMA_CTRL_RXMULTI (1 << 2)
+/* Unframed Rx/Tx data */
+#define DMA_CTRL_UNFRAMED (1 << 3)
+
+/* receive descriptor table pointer */
+#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */
+
+/* receive channel status */
+#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */
+#define D64_RS0_RS_MASK 0xf0000000 /* receive state */
+#define D64_RS0_RS_SHIFT 28
+#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */
+#define D64_RS0_RS_ACTIVE 0x10000000 /* active */
+#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */
+#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */
+#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */
+
+#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */
+#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */
+#define D64_RS1_RE_SHIFT 28
+#define D64_RS1_RE_NOERR 0x00000000 /* no error */
+#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */
+#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */
+#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */
+#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */
+#define D64_RS1_RE_COREE 0x50000000 /* core error */
+
+/* fifoaddr */
+#define D64_FA_OFF_MASK 0xffff /* offset */
+#define D64_FA_SEL_MASK 0xf0000 /* select */
+#define D64_FA_SEL_SHIFT 16
+#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */
+#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */
+#define D64_FA_SEL_RDD 0x40000 /* receive dma data */
+#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */
+#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */
+#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */
+#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */
+#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */
+#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */
+#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */
+
+/* descriptor control flags 1 */
+#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */
+#define D64_CTRL1_EOT ((u32)1 << 28) /* end of descriptor table */
+#define D64_CTRL1_IOC ((u32)1 << 29) /* interrupt on completion */
+#define D64_CTRL1_EOF ((u32)1 << 30) /* end of frame */
+#define D64_CTRL1_SOF ((u32)1 << 31) /* start of frame */
+
+/* descriptor control flags 2 */
+/* buffer byte count. real data len must <= 16KB */
+#define D64_CTRL2_BC_MASK 0x00007fff
+/* address extension bits */
+#define D64_CTRL2_AE 0x00030000
+#define D64_CTRL2_AE_SHIFT 16
+/* parity bit */
+#define D64_CTRL2_PARITY 0x00040000
+
+/* control flags in the range [27:20] are core-specific and not defined here */
+#define D64_CTRL_CORE_MASK 0x0ff00000
+
+#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */
+#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */
+#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1 */
+#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */
+
+/*
+ * packet headroom necessary to accommodate the largest header
+ * in the system, (i.e TXOFF). By doing, we avoid the need to
+ * allocate an extra buffer for the header when bridging to WL.
+ * There is a compile time check in wlc.c which ensure that this
+ * value is at least as big as TXOFF. This value is used in
+ * dma_rxfill().
+ */
+
+#define BCMEXTRAHDROOM 172
+
+/* debug/trace */
+#ifdef BCMDBG
+#define DMA_ERROR(args) \
+ do { \
+ if (!(*di->msg_level & 1)) \
+ ; \
+ else \
+ printk args; \
+ } while (0)
+#define DMA_TRACE(args) \
+ do { \
+ if (!(*di->msg_level & 2)) \
+ ; \
+ else \
+ printk args; \
+ } while (0)
+#else
+#define DMA_ERROR(args)
+#define DMA_TRACE(args)
+#endif /* BCMDBG */
+
+#define DMA_NONE(args)
+
+#define MAXNAMEL 8 /* 8 char names */
+
+/* macros to convert between byte offsets and indexes */
+#define B2I(bytes, type) ((bytes) / sizeof(type))
+#define I2B(index, type) ((index) * sizeof(type))
+
+#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */
+#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */
+
+#define PCI64ADDR_HIGH 0x80000000 /* address[63] */
+#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */
+
+/*
+ * DMA Descriptor
+ * Descriptors are only read by the hardware, never written back.
+ */
+struct dma64desc {
+ __le32 ctrl1; /* misc control bits & bufcount */
+ __le32 ctrl2; /* buffer count and address extension */
+ __le32 addrlow; /* memory address of the date buffer, bits 31:0 */
+ __le32 addrhigh; /* memory address of the date buffer, bits 63:32 */
+};
+
+/* 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 pci_dev *pbus; /* bus handle */
+
+ bool dma64; /* this dma engine is operating in 64-bit mode */
+ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */
+
+ /* 64-bit dma tx engine registers */
+ struct dma64regs __iomem *d64txregs;
+ /* 64-bit dma rx engine registers */
+ struct dma64regs __iomem *d64rxregs;
+ /* pointer to dma64 tx descriptor ring */
+ struct dma64desc *txd64;
+ /* pointer to dma64 rx descriptor ring */
+ struct dma64desc *rxd64;
+
+ u16 dmadesc_align; /* alignment requirement for dma descriptors */
+
+ u16 ntxd; /* # tx descriptors tunable */
+ u16 txin; /* index of next descriptor to reclaim */
+ u16 txout; /* index of next descriptor to post */
+ /* pointer to parallel array of pointers to packets */
+ struct sk_buff **txp;
+ /* Aligned physical address of descriptor ring */
+ dma_addr_t txdpa;
+ /* Original physical address of descriptor ring */
+ dma_addr_t txdpaorig;
+ u16 txdalign; /* #bytes added to alloc'd mem to align txd */
+ u32 txdalloc; /* #bytes allocated for the ring */
+ u32 xmtptrbase; /* When using unaligned descriptors, the ptr register
+ * is not just an index, it needs all 13 bits to be
+ * an offset from the addr register.
+ */
+
+ u16 nrxd; /* # rx descriptors tunable */
+ u16 rxin; /* index of next descriptor to reclaim */
+ u16 rxout; /* index of next descriptor to post */
+ /* pointer to parallel array of pointers to packets */
+ struct sk_buff **rxp;
+ /* Aligned physical address of descriptor ring */
+ dma_addr_t rxdpa;
+ /* Original physical address of descriptor ring */
+ dma_addr_t rxdpaorig;
+ u16 rxdalign; /* #bytes added to alloc'd mem to align rxd */
+ u32 rxdalloc; /* #bytes allocated for the ring */
+ u32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */
+
+ /* tunables */
+ unsigned int rxbufsize; /* rx buffer size in bytes, not including
+ * the extra headroom
+ */
+ uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper
+ * stack, e.g. some rx pkt buffers will be
+ * bridged to tx side without byte copying.
+ * The extra headroom needs to be large enough
+ * to fit txheader needs. Some dongle driver may
+ * not need it.
+ */
+ uint nrxpost; /* # rx buffers to keep posted */
+ unsigned int rxoffset; /* rxcontrol offset */
+ /* add to get dma address of descriptor ring, low 32 bits */
+ uint ddoffsetlow;
+ /* high 32 bits */
+ uint ddoffsethigh;
+ /* add to get dma address of data buffer, low 32 bits */
+ uint dataoffsetlow;
+ /* high 32 bits */
+ uint dataoffsethigh;
+ /* descriptor base need to be aligned or not */
+ 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)
+{
+ /* no swap needed for counting 1's */
+ u32 par_data = *(u32 *)&data;
+
+ par_data ^= par_data >> 16;
+ par_data ^= par_data >> 8;
+ par_data ^= par_data >> 4;
+ par_data ^= par_data >> 2;
+ par_data ^= par_data >> 1;
+
+ return par_data & 1;
+}
+
+static bool dma64_dd_parity(struct dma64desc *dd)
+{
+ return parity32(dd->addrlow ^ dd->addrhigh ^ dd->ctrl1 ^ dd->ctrl2);
+}
+
+/* descriptor bumping functions */
+
+static uint xxd(uint x, uint n)
+{
+ return x & (n - 1); /* faster than %, but n must be power of 2 */
+}
+
+static uint txd(struct dma_info *di, uint x)
+{
+ return xxd(x, di->ntxd);
+}
+
+static uint rxd(struct dma_info *di, uint x)
+{
+ return xxd(x, di->nrxd);
+}
+
+static uint nexttxd(struct dma_info *di, uint i)
+{
+ return txd(di, i + 1);
+}
+
+static uint prevtxd(struct dma_info *di, uint i)
+{
+ return txd(di, i - 1);
+}
+
+static uint nextrxd(struct dma_info *di, uint i)
+{
+ return txd(di, i + 1);
+}
+
+static uint ntxdactive(struct dma_info *di, uint h, uint t)
+{
+ return txd(di, t-h);
+}
+
+static uint nrxdactive(struct dma_info *di, uint h, uint t)
+{
+ return rxd(di, t-h);
+}
+
+static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
+{
+ uint dmactrlflags = di->dma.dmactrlflags;
+
+ if (di == NULL) {
+ DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name));
+ return 0;
+ }
+
+ dmactrlflags &= ~mask;
+ dmactrlflags |= flags;
+
+ /* If trying to enable parity, check if parity is actually supported */
+ if (dmactrlflags & DMA_CTRL_PEN) {
+ u32 control;
+
+ control = R_REG(&di->d64txregs->control);
+ W_REG(&di->d64txregs->control,
+ control | D64_XC_PD);
+ if (R_REG(&di->d64txregs->control) & D64_XC_PD)
+ /* We *can* disable it so it is supported,
+ * restore control register
+ */
+ W_REG(&di->d64txregs->control,
+ control);
+ else
+ /* Not supported, don't allow it to be enabled */
+ dmactrlflags &= ~DMA_CTRL_PEN;
+ }
+
+ di->dma.dmactrlflags = dmactrlflags;
+
+ return dmactrlflags;
+}
+
+static bool _dma64_addrext(struct dma64regs __iomem *dma64regs)
+{
+ u32 w;
+ OR_REG(&dma64regs->control, D64_XC_AE);
+ w = R_REG(&dma64regs->control);
+ AND_REG(&dma64regs->control, ~D64_XC_AE);
+ return (w & D64_XC_AE) == D64_XC_AE;
+}
+
+/*
+ * return true if this dma engine supports DmaExtendedAddrChanges,
+ * otherwise false
+ */
+static bool _dma_isaddrext(struct dma_info *di)
+{
+ /* DMA64 supports full 32- or 64-bit operation. AE is always valid */
+
+ /* not all tx or rx channel are available */
+ if (di->d64txregs != NULL) {
+ if (!_dma64_addrext(di->d64txregs))
+ DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have "
+ "AE set\n", di->name));
+ return true;
+ } else if (di->d64rxregs != NULL) {
+ if (!_dma64_addrext(di->d64rxregs))
+ DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have "
+ "AE set\n", di->name));
+ return true;
+ }
+
+ return false;
+}
+
+static bool _dma_descriptor_align(struct dma_info *di)
+{
+ u32 addrl;
+
+ /* Check to see if the descriptors need to be aligned on 4K/8K or not */
+ if (di->d64txregs != NULL) {
+ W_REG(&di->d64txregs->addrlow, 0xff0);
+ addrl = R_REG(&di->d64txregs->addrlow);
+ if (addrl != 0)
+ return false;
+ } else if (di->d64rxregs != NULL) {
+ W_REG(&di->d64rxregs->addrlow, 0xff0);
+ addrl = R_REG(&di->d64rxregs->addrlow);
+ if (addrl != 0)
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Descriptor table must start at the DMA hardware dictated alignment, so
+ * allocated memory must be large enough to support this requirement.
+ */
+static void *dma_alloc_consistent(struct pci_dev *pdev, uint size,
+ u16 align_bits, uint *alloced,
+ dma_addr_t *pap)
+{
+ if (align_bits) {
+ u16 align = (1 << align_bits);
+ if (!IS_ALIGNED(PAGE_SIZE, align))
+ size += align;
+ *alloced = size;
+ }
+ return pci_alloc_consistent(pdev, size, pap);
+}
+
+static
+u8 dma_align_sizetobits(uint size)
+{
+ u8 bitpos = 0;
+ while (size >>= 1)
+ bitpos++;
+ return bitpos;
+}
+
+/* This function ensures that the DMA descriptor ring will not get allocated
+ * across Page boundary. If the allocation is done across the page boundary
+ * at the first time, then it is freed and the allocation is done at
+ * descriptor ring size aligned location. This will ensure that the ring will
+ * not cross page boundary
+ */
+static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
+ u16 *alignbits, uint *alloced,
+ dma_addr_t *descpa)
+{
+ void *va;
+ u32 desc_strtaddr;
+ u32 alignbytes = 1 << *alignbits;
+
+ va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa);
+
+ if (NULL == va)
+ return NULL;
+
+ desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes);
+ if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
+ & boundary)) {
+ *alignbits = dma_align_sizetobits(size);
+ pci_free_consistent(di->pbus, size, va, *descpa);
+ va = dma_alloc_consistent(di->pbus, size, *alignbits,
+ alloced, descpa);
+ }
+ return va;
+}
+
+static bool dma64_alloc(struct dma_info *di, uint direction)
+{
+ u16 size;
+ uint ddlen;
+ void *va;
+ uint alloced = 0;
+ u16 align;
+ u16 align_bits;
+
+ ddlen = sizeof(struct dma64desc);
+
+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
+ align_bits = di->dmadesc_align;
+ align = (1 << align_bits);
+
+ if (direction == DMA_TX) {
+ va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
+ &alloced, &di->txdpaorig);
+ if (va == NULL) {
+ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd)"
+ " failed\n", di->name));
+ return false;
+ }
+ align = (1 << align_bits);
+ di->txd64 = (struct dma64desc *)
+ roundup((unsigned long)va, align);
+ di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);
+ di->txdpa = di->txdpaorig + di->txdalign;
+ di->txdalloc = alloced;
+ } else {
+ va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
+ &alloced, &di->rxdpaorig);
+ if (va == NULL) {
+ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd)"
+ " failed\n", di->name));
+ return false;
+ }
+ align = (1 << align_bits);
+ di->rxd64 = (struct dma64desc *)
+ roundup((unsigned long)va, align);
+ di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);
+ di->rxdpa = di->rxdpaorig + di->rxdalign;
+ di->rxdalloc = alloced;
+ }
+
+ return true;
+}
+
+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,
+ void __iomem *dmaregstx, void __iomem *dmaregsrx,
+ uint ntxd, uint nrxd,
+ uint rxbufsize, int rxextheadroom,
+ uint nrxpost, uint rxoffset, uint *msg_level)
+{
+ struct dma_info *di;
+ uint size;
+
+ /* allocate private info structure */
+ di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC);
+ if (di == NULL)
+ return NULL;
+
+ di->msg_level = msg_level ? msg_level : &dma_msg_level;
+
+
+ di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64);
+
+ /* init dma reg pointer */
+ di->d64txregs = (struct dma64regs __iomem *) dmaregstx;
+ di->d64rxregs = (struct dma64regs __iomem *) dmaregsrx;
+
+ /*
+ * Default flags (which can be changed by the driver calling
+ * dma_ctrlflags before enable): For backwards compatibility
+ * both Rx Overflow Continue and Parity are DISABLED.
+ */
+ _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0);
+
+ DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d "
+ "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
+ "dmaregstx %p dmaregsrx %p\n", name, "DMA64",
+ di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
+ rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx));
+
+ /* make a private copy of our callers name */
+ strncpy(di->name, name, MAXNAMEL);
+ di->name[MAXNAMEL - 1] = '\0';
+
+ di->pbus = ((struct si_info *)sih)->pbus;
+
+ /* save tunables */
+ di->ntxd = (u16) ntxd;
+ di->nrxd = (u16) nrxd;
+
+ /* the actual dma size doesn't include the extra headroom */
+ di->rxextrahdrroom =
+ (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom;
+ if (rxbufsize > BCMEXTRAHDROOM)
+ di->rxbufsize = (u16) (rxbufsize - di->rxextrahdrroom);
+ else
+ di->rxbufsize = (u16) rxbufsize;
+
+ di->nrxpost = (u16) nrxpost;
+ di->rxoffset = (u8) rxoffset;
+
+ /*
+ * figure out the DMA physical address offset for dd and data
+ * PCI/PCIE: they map silicon backplace address to zero
+ * based memory, need offset
+ * Other bus: use zero SI_BUS BIGENDIAN kludge: use sdram
+ * swapped region for data buffer, not descriptor
+ */
+ di->ddoffsetlow = 0;
+ di->dataoffsetlow = 0;
+ /* add offset for pcie with DMA64 bus */
+ di->ddoffsetlow = 0;
+ di->ddoffsethigh = SI_PCIE_DMA_H32;
+ di->dataoffsetlow = di->ddoffsetlow;
+ di->dataoffsethigh = di->ddoffsethigh;
+ /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
+ if ((ai_coreid(sih) == SDIOD_CORE_ID)
+ && ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2)))
+ di->addrext = 0;
+ else if ((ai_coreid(sih) == I2S_CORE_ID) &&
+ ((ai_corerev(sih) == 0) || (ai_corerev(sih) == 1)))
+ di->addrext = 0;
+ else
+ di->addrext = _dma_isaddrext(di);
+
+ /* does the descriptor need to be aligned and if yes, on 4K/8K or not */
+ di->aligndesc_4k = _dma_descriptor_align(di);
+ if (di->aligndesc_4k) {
+ di->dmadesc_align = D64RINGALIGN_BITS;
+ if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2))
+ /* for smaller dd table, HW relax alignment reqmnt */
+ di->dmadesc_align = D64RINGALIGN_BITS - 1;
+ } else {
+ di->dmadesc_align = 4; /* 16 byte alignment */
+ }
+
+ DMA_NONE(("DMA descriptor align_needed %d, align %d\n",
+ di->aligndesc_4k, di->dmadesc_align));
+
+ /* allocate tx packet pointer vector */
+ if (ntxd) {
+ size = ntxd * sizeof(void *);
+ di->txp = kzalloc(size, GFP_ATOMIC);
+ if (di->txp == NULL)
+ goto fail;
+ }
+
+ /* allocate rx packet pointer vector */
+ if (nrxd) {
+ size = nrxd * sizeof(void *);
+ di->rxp = kzalloc(size, GFP_ATOMIC);
+ if (di->rxp == NULL)
+ goto fail;
+ }
+
+ /*
+ * allocate transmit descriptor ring, only need ntxd descriptors
+ * but it must be aligned
+ */
+ if (ntxd) {
+ if (!_dma_alloc(di, DMA_TX))
+ goto fail;
+ }
+
+ /*
+ * allocate receive descriptor ring, only need nrxd descriptors
+ * but it must be aligned
+ */
+ if (nrxd) {
+ if (!_dma_alloc(di, DMA_RX))
+ goto fail;
+ }
+
+ if ((di->ddoffsetlow != 0) && !di->addrext) {
+ if (di->txdpa > SI_PCI_DMA_SZ) {
+ DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not "
+ "supported\n", di->name, (u32)di->txdpa));
+ goto fail;
+ }
+ if (di->rxdpa > SI_PCI_DMA_SZ) {
+ DMA_ERROR(("%s: dma_attach: 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));
+
+ return (struct dma_pub *) di;
+
+ fail:
+ dma_detach((struct dma_pub *)di);
+ return NULL;
+}
+
+static inline void
+dma64_dd_upd(struct dma_info *di, struct dma64desc *ddring,
+ dma_addr_t pa, uint outidx, u32 *flags, u32 bufcount)
+{
+ u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK;
+
+ /* PCI bus with big(>1G) physical address, use address extension */
+ if ((di->dataoffsetlow == 0) || !(pa & PCI32ADDR_HIGH)) {
+ ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow);
+ ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh);
+ ddring[outidx].ctrl1 = cpu_to_le32(*flags);
+ ddring[outidx].ctrl2 = cpu_to_le32(ctrl2);
+ } else {
+ /* address extension for 32-bit PCI */
+ u32 ae;
+
+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
+ pa &= ~PCI32ADDR_HIGH;
+
+ ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE;
+ ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow);
+ ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh);
+ ddring[outidx].ctrl1 = cpu_to_le32(*flags);
+ ddring[outidx].ctrl2 = cpu_to_le32(ctrl2);
+ }
+ if (di->dma.dmactrlflags & DMA_CTRL_PEN) {
+ if (dma64_dd_parity(&ddring[outidx]))
+ ddring[outidx].ctrl2 =
+ cpu_to_le32(ctrl2 | D64_CTRL2_PARITY);
+ }
+}
+
+/* !! may be called with core in reset */
+void dma_detach(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+
+ DMA_TRACE(("%s: dma_detach\n", di->name));
+
+ /* free dma descriptor rings */
+ if (di->txd64)
+ pci_free_consistent(di->pbus, di->txdalloc,
+ ((s8 *)di->txd64 - di->txdalign),
+ (di->txdpaorig));
+ if (di->rxd64)
+ pci_free_consistent(di->pbus, di->rxdalloc,
+ ((s8 *)di->rxd64 - di->rxdalign),
+ (di->rxdpaorig));
+
+ /* free packet pointer vectors */
+ kfree(di->txp);
+ kfree(di->rxp);
+
+ /* free our private info structure */
+ kfree(di);
+
+}
+
+/* initialize descriptor table base address */
+static void
+_dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa)
+{
+ if (!di->aligndesc_4k) {
+ if (direction == DMA_TX)
+ di->xmtptrbase = pa;
+ else
+ di->rcvptrbase = pa;
+ }
+
+ if ((di->ddoffsetlow == 0)
+ || !(pa & PCI32ADDR_HIGH)) {
+ if (direction == DMA_TX) {
+ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow);
+ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh);
+ } else {
+ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow);
+ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh);
+ }
+ } else {
+ /* DMA64 32bits address extension */
+ u32 ae;
+
+ /* shift the high bit(s) from pa to ae */
+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
+ pa &= ~PCI32ADDR_HIGH;
+
+ if (direction == DMA_TX) {
+ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow);
+ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh);
+ SET_REG(&di->d64txregs->control,
+ D64_XC_AE, (ae << D64_XC_AE_SHIFT));
+ } else {
+ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow);
+ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh);
+ SET_REG(&di->d64rxregs->control,
+ D64_RC_AE, (ae << D64_RC_AE_SHIFT));
+ }
+ }
+}
+
+static void _dma_rxenable(struct dma_info *di)
+{
+ uint dmactrlflags = di->dma.dmactrlflags;
+ u32 control;
+
+ DMA_TRACE(("%s: dma_rxenable\n", di->name));
+
+ control =
+ (R_REG(&di->d64rxregs->control) & D64_RC_AE) |
+ D64_RC_RE;
+
+ if ((dmactrlflags & DMA_CTRL_PEN) == 0)
+ control |= D64_RC_PD;
+
+ if (dmactrlflags & DMA_CTRL_ROC)
+ control |= D64_RC_OC;
+
+ W_REG(&di->d64rxregs->control,
+ ((di->rxoffset << D64_RC_RO_SHIFT) | control));
+}
+
+void dma_rxinit(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+
+ DMA_TRACE(("%s: dma_rxinit\n", di->name));
+
+ if (di->nrxd == 0)
+ return;
+
+ di->rxin = di->rxout = 0;
+
+ /* clear rx descriptor ring */
+ memset(di->rxd64, '\0', di->nrxd * sizeof(struct dma64desc));
+
+ /* DMA engine with out alignment requirement requires table to be inited
+ * before enabling the engine
+ */
+ if (!di->aligndesc_4k)
+ _dma_ddtable_init(di, DMA_RX, di->rxdpa);
+
+ _dma_rxenable(di);
+
+ if (di->aligndesc_4k)
+ _dma_ddtable_init(di, DMA_RX, di->rxdpa);
+}
+
+static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall)
+{
+ uint i, curr;
+ struct sk_buff *rxp;
+ dma_addr_t pa;
+
+ i = di->rxin;
+
+ /* return if no packets posted */
+ if (i == di->rxout)
+ return NULL;
+
+ curr =
+ B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) -
+ di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc);
+
+ /* ignore curr if forceall */
+ if (!forceall && (i == curr))
+ return NULL;
+
+ /* get the packet pointer that corresponds to the rx descriptor */
+ rxp = di->rxp[i];
+ di->rxp[i] = NULL;
+
+ pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow;
+
+ /* clear this packet from the descriptor ring */
+ pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE);
+
+ di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef);
+ di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef);
+
+ di->rxin = nextrxd(di, i);
+
+ return rxp;
+}
+
+static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall)
+{
+ if (di->nrxd == 0)
+ return NULL;
+
+ return dma64_getnextrxp(di, forceall);
+}
+
+/*
+ * !! rx entry routine
+ * returns a pointer to the next frame received, or NULL if there are no more
+ * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is
+ * supported with pkts chain
+ * otherwise, it's treated as giant pkt and will be tossed.
+ * The DMA scattering starts with normal DMA header, followed by first
+ * buffer data. After it reaches the max size of buffer, the data continues
+ * in next DMA descriptor buffer WITHOUT DMA header
+ */
+struct sk_buff *dma_rx(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ struct sk_buff *p, *head, *tail;
+ uint len;
+ uint pkt_len;
+ int resid = 0;
+
+ next_frame:
+ head = _dma_getnextrxp(di, false);
+ if (head == NULL)
+ return NULL;
+
+ len = le16_to_cpu(*(__le16 *) (head->data));
+ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
+ dma_spin_for_len(len, head);
+
+ /* set actual length */
+ pkt_len = min((di->rxoffset + len), di->rxbufsize);
+ __skb_trim(head, pkt_len);
+ resid = len - (di->rxbufsize - di->rxoffset);
+
+ /* check for single or multi-buffer rx */
+ if (resid > 0) {
+ tail = head;
+ while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {
+ tail->next = p;
+ pkt_len = min_t(uint, resid, di->rxbufsize);
+ __skb_trim(p, pkt_len);
+
+ tail = p;
+ resid -= di->rxbufsize;
+ }
+
+#ifdef BCMDBG
+ if (resid > 0) {
+ uint cur;
+ cur =
+ B2I(((R_REG(&di->d64rxregs->status0) &
+ D64_RS0_CD_MASK) -
+ di->rcvptrbase) & D64_RS0_CD_MASK,
+ struct dma64desc);
+ DMA_ERROR(("dma_rx, rxin %d rxout %d, hw_curr %d\n",
+ di->rxin, di->rxout, cur));
+ }
+#endif /* BCMDBG */
+
+ if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
+ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n",
+ di->name, len));
+ brcmu_pkt_buf_free_skb(head);
+ di->dma.rxgiants++;
+ goto next_frame;
+ }
+ }
+
+ return head;
+}
+
+static bool dma64_rxidle(struct dma_info *di)
+{
+ DMA_TRACE(("%s: dma_rxidle\n", di->name));
+
+ if (di->nrxd == 0)
+ return true;
+
+ return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
+ (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK));
+}
+
+/*
+ * post receive buffers
+ * return false is refill failed completely and ring is empty this will stall
+ * the rx dma and user might want to call rxfill again asap. This unlikely
+ * happens on memory-rich NIC, but often on memory-constrained dongle
+ */
+bool dma_rxfill(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ struct sk_buff *p;
+ u16 rxin, rxout;
+ u32 flags = 0;
+ uint n;
+ uint i;
+ dma_addr_t pa;
+ uint extra_offset = 0;
+ bool ring_empty;
+
+ ring_empty = false;
+
+ /*
+ * Determine how many receive buffers we're lacking
+ * from the full complement, allocate, initialize,
+ * and post them, then update the chip rx lastdscr.
+ */
+
+ rxin = di->rxin;
+ rxout = di->rxout;
+
+ n = di->nrxpost - nrxdactive(di, rxin, rxout);
+
+ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n));
+
+ if (di->rxbufsize > BCMEXTRAHDROOM)
+ extra_offset = di->rxextrahdrroom;
+
+ for (i = 0; i < n; i++) {
+ /*
+ * the di->rxbufsize doesn't include the extra headroom,
+ * we need to add it to the size to be allocated
+ */
+ p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset);
+
+ if (p == NULL) {
+ DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n",
+ di->name));
+ if (i == 0 && dma64_rxidle(di)) {
+ DMA_ERROR(("%s: rxfill64: ring is empty !\n",
+ di->name));
+ ring_empty = true;
+ }
+ di->dma.rxnobuf++;
+ break;
+ }
+ /* reserve an extra headroom, if applicable */
+ if (extra_offset)
+ skb_pull(p, extra_offset);
+
+ /* Do a cached write instead of uncached write since DMA_MAP
+ * will flush the cache.
+ */
+ *(u32 *) (p->data) = 0;
+
+ pa = pci_map_single(di->pbus, p->data,
+ di->rxbufsize, PCI_DMA_FROMDEVICE);
+
+ /* save the free packet pointer */
+ di->rxp[rxout] = p;
+
+ /* reset flags for each descriptor */
+ flags = 0;
+ if (rxout == (di->nrxd - 1))
+ flags = D64_CTRL1_EOT;
+
+ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags,
+ di->rxbufsize);
+ rxout = nextrxd(di, rxout);
+ }
+
+ di->rxout = rxout;
+
+ /* update the chip lastdscr pointer */
+ W_REG(&di->d64rxregs->ptr,
+ di->rcvptrbase + I2B(rxout, struct dma64desc));
+
+ return ring_empty;
+}
+
+void dma_rxreclaim(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ struct sk_buff *p;
+
+ DMA_TRACE(("%s: dma_rxreclaim\n", di->name));
+
+ while ((p = _dma_getnextrxp(di, true)))
+ brcmu_pkt_buf_free_skb(p);
+}
+
+void dma_counterreset(struct dma_pub *pub)
+{
+ /* reset all software counters */
+ pub->rxgiants = 0;
+ pub->rxnobuf = 0;
+ pub->txnobuf = 0;
+}
+
+/* get the address of the var in order to change later */
+unsigned long dma_getvar(struct dma_pub *pub, const char *name)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+
+ if (!strcmp(name, "&txavail"))
+ return (unsigned long)&(di->dma.txavail);
+ return 0;
+}
+
+/* 64-bit DMA functions */
+
+void dma_txinit(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ u32 control = D64_XC_XE;
+
+ DMA_TRACE(("%s: dma_txinit\n", di->name));
+
+ if (di->ntxd == 0)
+ return;
+
+ di->txin = di->txout = 0;
+ di->dma.txavail = di->ntxd - 1;
+
+ /* clear tx descriptor ring */
+ memset(di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc)));
+
+ /* DMA engine with out alignment requirement requires table to be inited
+ * before enabling the engine
+ */
+ if (!di->aligndesc_4k)
+ _dma_ddtable_init(di, DMA_TX, di->txdpa);
+
+ if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0)
+ control |= D64_XC_PD;
+ OR_REG(&di->d64txregs->control, control);
+
+ /* DMA engine with alignment requirement requires table to be inited
+ * before enabling the engine
+ */
+ if (di->aligndesc_4k)
+ _dma_ddtable_init(di, DMA_TX, di->txdpa);
+}
+
+void dma_txsuspend(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+
+ DMA_TRACE(("%s: dma_txsuspend\n", di->name));
+
+ if (di->ntxd == 0)
+ return;
+
+ OR_REG(&di->d64txregs->control, D64_XC_SE);
+}
+
+void dma_txresume(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+
+ DMA_TRACE(("%s: dma_txresume\n", di->name));
+
+ if (di->ntxd == 0)
+ return;
+
+ AND_REG(&di->d64txregs->control, ~D64_XC_SE);
+}
+
+bool dma_txsuspended(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+
+ return (di->ntxd == 0) ||
+ ((R_REG(&di->d64txregs->control) & D64_XC_SE) ==
+ D64_XC_SE);
+}
+
+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: dma_txreclaim %s\n", di->name,
+ (range == DMA_RANGE_ALL) ? "all" :
+ ((range ==
+ DMA_RANGE_TRANSMITTED) ? "transmitted" :
+ "transferred")));
+
+ if (di->txin == di->txout)
+ return;
+
+ while ((p = dma_getnexttxp(pub, range))) {
+ /* For unframed data, we don't have any packets to free */
+ if (!(di->dma.dmactrlflags & DMA_CTRL_UNFRAMED))
+ brcmu_pkt_buf_free_skb(p);
+ }
+}
+
+bool dma_txreset(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ u32 status;
+
+ if (di->ntxd == 0)
+ return true;
+
+ /* suspend tx DMA first */
+ W_REG(&di->d64txregs->control, D64_XC_SE);
+ SPINWAIT(((status =
+ (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
+ != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE)
+ && (status != D64_XS0_XS_STOPPED), 10000);
+
+ W_REG(&di->d64txregs->control, 0);
+ SPINWAIT(((status =
+ (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
+ != D64_XS0_XS_DISABLED), 10000);
+
+ /* wait for the last transaction to complete */
+ udelay(300);
+
+ return status == D64_XS0_XS_DISABLED;
+}
+
+bool dma_rxreset(struct dma_pub *pub)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ u32 status;
+
+ if (di->nrxd == 0)
+ return true;
+
+ W_REG(&di->d64rxregs->control, 0);
+ SPINWAIT(((status =
+ (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK))
+ != D64_RS0_RS_DISABLED), 10000);
+
+ 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 *p0, bool commit)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ struct sk_buff *p, *next;
+ unsigned char *data;
+ uint len;
+ u16 txout;
+ u32 flags = 0;
+ dma_addr_t pa;
+
+ DMA_TRACE(("%s: dma_txfast\n", di->name));
+
+ txout = di->txout;
+
+ /*
+ * Walk the chain of packet buffers
+ * allocating and initializing transmit descriptor entries.
+ */
+ for (p = p0; p; p = next) {
+ data = p->data;
+ len = p->len;
+ next = p->next;
+
+ /* return nonzero if out of tx descriptors */
+ if (nexttxd(di, txout) == di->txin)
+ goto outoftxd;
+
+ if (len == 0)
+ continue;
+
+ /* get physical address of buffer start */
+ pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE);
+
+ flags = 0;
+ if (p == p0)
+ flags |= D64_CTRL1_SOF;
+
+ /* With a DMA segment list, Descriptor table is filled
+ * using the segment list instead of looping over
+ * buffers in multi-chain DMA. Therefore, EOF for SGLIST
+ * is when end of segment list is reached.
+ */
+ if (next == NULL)
+ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF);
+ if (txout == (di->ntxd - 1))
+ flags |= D64_CTRL1_EOT;
+
+ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
+
+ txout = nexttxd(di, txout);
+ }
+
+ /* if last txd eof not set, fix it */
+ if (!(flags & D64_CTRL1_EOF))
+ di->txd64[prevtxd(di, txout)].ctrl1 =
+ cpu_to_le32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF);
+
+ /* save the packet */
+ di->txp[prevtxd(di, txout)] = p0;
+
+ /* bump the tx descriptor index */
+ di->txout = txout;
+
+ /* kick the chip */
+ if (commit)
+ W_REG(&di->d64txregs->ptr,
+ di->xmtptrbase + I2B(txout, struct dma64desc));
+
+ /* tx flow control */
+ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1;
+
+ return 0;
+
+ outoftxd:
+ DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name));
+ brcmu_pkt_buf_free_skb(p0);
+ di->dma.txavail = 0;
+ di->dma.txnobuf++;
+ return -1;
+}
+
+/*
+ * Reclaim next completed txd (txds if using chained buffers) in the range
+ * specified and return associated packet.
+ * If range is DMA_RANGE_TRANSMITTED, reclaim descriptors that have be
+ * transmitted as noted by the hardware "CurrDescr" pointer.
+ * If range is DMA_RANGE_TRANSFERED, reclaim descriptors that have be
+ * transferred by the DMA as noted by the hardware "ActiveDescr" pointer.
+ * If range is DMA_RANGE_ALL, reclaim all txd(s) posted to the ring and
+ * return associated packet regardless of the value of hardware pointers.
+ */
+struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
+{
+ struct dma_info *di = (struct dma_info *)pub;
+ u16 start, end, i;
+ u16 active_desc;
+ struct sk_buff *txp;
+
+ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name,
+ (range == DMA_RANGE_ALL) ? "all" :
+ ((range ==
+ DMA_RANGE_TRANSMITTED) ? "transmitted" :
+ "transferred")));
+
+ if (di->ntxd == 0)
+ return NULL;
+
+ txp = NULL;
+
+ start = di->txin;
+ if (range == DMA_RANGE_ALL)
+ end = di->txout;
+ else {
+ struct dma64regs __iomem *dregs = di->d64txregs;
+
+ end = (u16) (B2I(((R_REG(&dregs->status0) &
+ D64_XS0_CD_MASK) -
+ di->xmtptrbase) & D64_XS0_CD_MASK,
+ struct dma64desc));
+
+ if (range == DMA_RANGE_TRANSFERED) {
+ active_desc =
+ (u16) (R_REG(&dregs->status1) &
+ D64_XS1_AD_MASK);
+ active_desc =
+ (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;
+ active_desc = B2I(active_desc, struct dma64desc);
+ if (end != active_desc)
+ end = prevtxd(di, active_desc);
+ }
+ }
+
+ if ((start == 0) && (end > di->txout))
+ goto bogus;
+
+ for (i = start; i != end && !txp; i = nexttxd(di, i)) {
+ dma_addr_t pa;
+ uint size;
+
+ pa = le32_to_cpu(di->txd64[i].addrlow) - di->dataoffsetlow;
+
+ size =
+ (le32_to_cpu(di->txd64[i].ctrl2) &
+ D64_CTRL2_BC_MASK);
+
+ di->txd64[i].addrlow = cpu_to_le32(0xdeadbeef);
+ di->txd64[i].addrhigh = cpu_to_le32(0xdeadbeef);
+
+ txp = di->txp[i];
+ di->txp[i] = NULL;
+
+ pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE);
+ }
+
+ di->txin = i;
+
+ /* tx flow control */
+ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1;
+
+ return txp;
+
+ bogus:
+ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d "
+ "force %d\n", start, end, di->txout, forceall));
+ return NULL;
+}
+
+/*
+ * Mac80211 initiated actions sometimes require packets in the DMA queue to be
+ * modified. The modified portion of the packet is not under control of the DMA
+ * engine. This function calls a caller-supplied function for each packet in
+ * the caller specified dma chain.
+ */
+void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
+ (void *pkt, void *arg_a), void *arg_a)
+{
+ struct dma_info *di = (struct dma_info *) dmah;
+ uint i = di->txin;
+ uint end = di->txout;
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *tx_info;
+
+ while (i != end) {
+ skb = (struct sk_buff *)di->txp[i];
+ if (skb != NULL) {
+ tx_info = (struct ieee80211_tx_info *)skb->cb;
+ (callback_fnc)(tx_info, arg_a);
+ }
+ i = nexttxd(di, i);
+ }
+}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.h b/drivers/net/wireless/brcm80211/brcmsmac/dma.h
new file mode 100644
index 000000000000..ebc5bc546f3b
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_DMA_H_
+#define _BRCM_DMA_H_
+
+#include <linux/delay.h>
+#include "types.h" /* forward structure declarations */
+
+/* map/unmap direction */
+#define DMA_TX 1 /* TX direction for DMA */
+#define DMA_RX 2 /* RX direction for DMA */
+
+/* DMA structure:
+ * support two DMA engines: 32 bits address or 64 bit addressing
+ * basic DMA register set is per channel(transmit or receive)
+ * a pair of channels is defined for convenience
+ */
+
+/* 32 bits addressing */
+
+struct dma32diag { /* diag access */
+ u32 fifoaddr; /* diag address */
+ u32 fifodatalow; /* low 32bits of data */
+ u32 fifodatahigh; /* high 32bits of data */
+ u32 pad; /* reserved */
+};
+
+/* 64 bits addressing */
+
+/* dma registers per channel(xmt or rcv) */
+struct dma64regs {
+ u32 control; /* enable, et al */
+ u32 ptr; /* last descriptor posted to chip */
+ u32 addrlow; /* desc ring base address low 32-bits (8K aligned) */
+ u32 addrhigh; /* desc ring base address bits 63:32 (8K aligned) */
+ u32 status0; /* current descriptor, xmt state */
+ u32 status1; /* active descriptor, xmt error */
+};
+
+/* range param for dma_getnexttxp() and dma_txreclaim */
+enum txd_range {
+ DMA_RANGE_ALL = 1,
+ DMA_RANGE_TRANSMITTED,
+ DMA_RANGE_TRANSFERED
+};
+
+/*
+ * Exported data structure (read-only)
+ */
+/* export structure */
+struct dma_pub {
+ uint txavail; /* # free tx descriptors */
+ uint dmactrlflags; /* dma control flags */
+
+ /* rx error counters */
+ uint rxgiants; /* rx giant frames */
+ uint rxnobuf; /* rx out of dma descriptors */
+ /* tx error counters */
+ uint txnobuf; /* tx out of dma descriptors */
+};
+
+extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
+ void __iomem *dmaregstx, void __iomem *dmaregsrx,
+ uint ntxd, uint nrxd,
+ uint rxbufsize, int rxextheadroom,
+ uint nrxpost, uint rxoffset, uint *msg_level);
+
+void dma_rxinit(struct dma_pub *pub);
+struct sk_buff *dma_rx(struct dma_pub *pub);
+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);
+void dma_txsuspend(struct dma_pub *pub);
+bool dma_txsuspended(struct dma_pub *pub);
+void dma_txresume(struct dma_pub *pub);
+void dma_txreclaim(struct dma_pub *pub, enum txd_range range);
+void dma_rxreclaim(struct dma_pub *pub);
+void dma_detach(struct dma_pub *pub);
+unsigned long dma_getvar(struct dma_pub *pub, const char *name);
+struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range);
+void dma_counterreset(struct dma_pub *pub);
+
+void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
+ (void *pkt, void *arg_a), void *arg_a);
+
+/*
+ * DMA(Bug) on bcm47xx chips seems to declare that the packet is ready, but
+ * the packet length is not updated yet (by DMA) on the expected time.
+ * Workaround is to hold processor till DMA updates the length, and stay off
+ * the bus to allow DMA update the length in buffer
+ */
+static inline void dma_spin_for_len(uint len, struct sk_buff *head)
+{
+#if defined(CONFIG_BCM47XX)
+ if (!len) {
+ while (!(len = *(u16 *) KSEG1ADDR(head->data)))
+ udelay(1);
+
+ *(u16 *) (head->data) = cpu_to_le16((u16) len);
+ }
+#endif /* defined(CONFIG_BCM47XX) */
+}
+
+#endif /* _BRCM_DMA_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index d6de44e430d3..ac8d02bd34f2 100644
--- a/drivers/staging/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -31,38 +31,10 @@
#include "pub.h"
#include "ucode_loader.h"
#include "mac80211_if.h"
+#include "main.h"
#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */
-#define LOCK(wl) spin_lock_bh(&(wl)->lock)
-#define UNLOCK(wl) spin_unlock_bh(&(wl)->lock)
-
-/* locking from inside brcms_isr */
-#define ISR_LOCK(wl, flags)\
- do {\
- spin_lock(&(wl)->isr_lock);\
- (void)(flags); } \
- while (0)
-
-#define ISR_UNLOCK(wl, flags)\
- do {\
- spin_unlock(&(wl)->isr_lock);\
- (void)(flags); } \
- while (0)
-
-/* locking under LOCK() to synchronize with brcms_isr */
-#define INT_LOCK(wl, flags) spin_lock_irqsave(&(wl)->isr_lock, flags)
-#define INT_UNLOCK(wl, flags) spin_unlock_irqrestore(&(wl)->isr_lock, flags)
-
-static void brcms_timer(unsigned long data);
-static void _brcms_timer(struct brcms_timer *t);
-
-
-static int ieee_hw_init(struct ieee80211_hw *hw);
-static int ieee_hw_rate_init(struct ieee80211_hw *hw);
-
-static int wl_linux_watchdog(void *ctx);
-
/* Flags we support */
#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | \
@@ -72,20 +44,42 @@ static int wl_linux_watchdog(void *ctx);
FIF_OTHER_BSS | \
FIF_BCN_PRBRESP_PROMISC)
-static int n_adapters_found;
+#define CHAN2GHZ(channel, freqency, chflags) { \
+ .band = IEEE80211_BAND_2GHZ, \
+ .center_freq = (freqency), \
+ .hw_value = (channel), \
+ .flags = chflags, \
+ .max_antenna_gain = 0, \
+ .max_power = 19, \
+}
-static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev);
-static void brcms_release_fw(struct brcms_info *wl);
+#define CHAN5GHZ(channel, chflags) { \
+ .band = IEEE80211_BAND_5GHZ, \
+ .center_freq = 5000 + 5*(channel), \
+ .hw_value = (channel), \
+ .flags = chflags, \
+ .max_antenna_gain = 0, \
+ .max_power = 21, \
+}
-/* local prototypes */
-static void brcms_dpc(unsigned long data);
-static irqreturn_t brcms_isr(int irq, void *dev_id);
+#define RATE(rate100m, _flags) { \
+ .bitrate = (rate100m), \
+ .flags = (_flags), \
+ .hw_value = (rate100m / 5), \
+}
-static int __devinit brcms_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent);
-static void brcms_remove(struct pci_dev *pdev);
-static void brcms_free(struct brcms_info *wl);
-static void brcms_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br);
+struct firmware_hdr {
+ __le32 offset;
+ __le32 len;
+ __le32 idx;
+};
+
+static const char * const brcms_firmwares[MAX_FW_IMAGES] = {
+ "brcm/bcm43xx",
+ NULL
+};
+
+static int n_adapters_found;
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
@@ -94,11 +88,10 @@ MODULE_LICENSE("Dual BSD/GPL");
/* recognized PCI IDs */
static DEFINE_PCI_DEVICE_TABLE(brcms_pci_id_table) = {
- {PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 43225 2G */
- {PCI_VENDOR_ID_BROADCOM, 0x4353, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 43224 DUAL */
- {PCI_VENDOR_ID_BROADCOM, 0x4727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 4313 DUAL */
- /* 43224 Ven */
- {PCI_VENDOR_ID_BROADCOM, 0x0576, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, /* 43225 2G */
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, /* 43224 DUAL */
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, /* 4313 DUAL */
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, /* 43224 Ven */
{0}
};
@@ -107,60 +100,178 @@ MODULE_DEVICE_TABLE(pci, brcms_pci_id_table);
#ifdef BCMDBG
static int msglevel = 0xdeadbeef;
module_param(msglevel, int, 0);
-static int phymsglevel = 0xdeadbeef;
-module_param(phymsglevel, int, 0);
#endif /* BCMDBG */
-#define HW_TO_WL(hw) (hw->priv)
-#define WL_TO_HW(wl) (wl->pub->ieee_hw)
-
-/* MAC80211 callback functions */
-static int brcms_ops_start(struct ieee80211_hw *hw);
-static void brcms_ops_stop(struct ieee80211_hw *hw);
-static int brcms_ops_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-static void brcms_ops_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed);
-static void brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info,
- u32 changed);
-static void brcms_ops_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags, u64 multicast);
-static int brcms_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- bool set);
-static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw);
-static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw);
-static void brcms_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf);
-static int brcms_ops_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats);
-static void brcms_ops_sta_notify(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum sta_notify_cmd cmd,
- struct ieee80211_sta *sta);
-static int brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
- const struct ieee80211_tx_queue_params *params);
-static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw);
-static int brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-static int brcms_ops_sta_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-static int brcms_ops_ampdu_action(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta, u16 tid, u16 *ssn,
- u8 buf_size);
-static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw);
-static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop);
+static struct ieee80211_channel brcms_2ghz_chantable[] = {
+ CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN2GHZ(5, 2432, 0),
+ CHAN2GHZ(6, 2437, 0),
+ CHAN2GHZ(7, 2442, 0),
+ CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(12, 2467,
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(13, 2472,
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN2GHZ(14, 2484,
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+};
+
+static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = {
+ /* UNII-1 */
+ CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
+ /* UNII-2 */
+ CHAN5GHZ(52,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(56,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(60,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(64,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ /* MID */
+ CHAN5GHZ(100,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(104,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(108,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(112,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(116,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(120,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(124,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(128,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(132,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(136,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(140,
+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
+ IEEE80211_CHAN_NO_HT40MINUS),
+ /* UNII-3 */
+ CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
+ CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
+ CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+};
+
+/*
+ * The rate table is used for both 2.4G and 5G rates. The
+ * latter being a subset as it does not support CCK rates.
+ */
+static struct ieee80211_rate legacy_ratetable[] = {
+ RATE(10, 0),
+ RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(60, 0),
+ RATE(90, 0),
+ RATE(120, 0),
+ RATE(180, 0),
+ RATE(240, 0),
+ RATE(360, 0),
+ RATE(480, 0),
+ RATE(540, 0),
+};
+
+static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = {
+ .band = IEEE80211_BAND_2GHZ,
+ .channels = brcms_2ghz_chantable,
+ .n_channels = ARRAY_SIZE(brcms_2ghz_chantable),
+ .bitrates = legacy_ratetable,
+ .n_bitrates = ARRAY_SIZE(legacy_ratetable),
+ .ht_cap = {
+ /* from include/linux/ieee80211.h */
+ .cap = IEEE80211_HT_CAP_GRN_FLD |
+ IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
+ .ht_supported = true,
+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+ .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
+ .mcs = {
+ /* placeholders for now */
+ .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
+ .rx_highest = cpu_to_le16(500),
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
+ }
+};
+
+static const struct ieee80211_supported_band brcms_band_5GHz_nphy_template = {
+ .band = IEEE80211_BAND_5GHZ,
+ .channels = brcms_5ghz_nphy_chantable,
+ .n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable),
+ .bitrates = legacy_ratetable + BRCMS_LEGACY_5G_RATE_OFFSET,
+ .n_bitrates = ARRAY_SIZE(legacy_ratetable) -
+ BRCMS_LEGACY_5G_RATE_OFFSET,
+ .ht_cap = {
+ .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_SGI_40 |
+ IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */
+ .ht_supported = true,
+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+ .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
+ .mcs = {
+ /* placeholders for now */
+ .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
+ .rx_highest = cpu_to_le16(500),
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
+ }
+};
+
+/* flags the given rate in rateset as requested */
+static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br)
+{
+ u32 i;
+
+ for (i = 0; i < rs->count; i++) {
+ if (rate != (rs->rates[i] & 0x7f))
+ continue;
+
+ if (is_br)
+ rs->rates[i] |= BRCMS_RATE_FLAG;
+ else
+ rs->rates[i] &= BRCMS_RATE_MASK;
+ return;
+ }
+}
static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct brcms_info *wl = hw->priv;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
if (!wl->pub->up) {
wiphy_err(wl->wiphy, "ops->tx called while down\n");
kfree_skb(skb);
@@ -168,21 +279,18 @@ static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
}
brcms_c_sendpkt_mac80211(wl->wlc, skb, hw);
done:
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
}
static int brcms_ops_start(struct ieee80211_hw *hw)
{
struct brcms_info *wl = hw->priv;
bool blocked;
- /*
- struct ieee80211_channel *curchan = hw->conf.channel;
- */
ieee80211_wake_queues(hw);
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
blocked = brcms_rfkill_set_hw_state(wl);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
if (!blocked)
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
@@ -211,15 +319,18 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
return -EOPNOTSUPP;
}
- wl = HW_TO_WL(hw);
- LOCK(wl);
- err = brcms_up(wl);
- UNLOCK(wl);
+ wl = hw->priv;
+ spin_lock_bh(&wl->lock);
+ if (!wl->pub->up)
+ err = brcms_up(wl);
+ else
+ err = -ENODEV;
+ spin_unlock_bh(&wl->lock);
- if (err != 0) {
+ if (err != 0)
wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__,
err);
- }
+
return err;
}
@@ -228,60 +339,26 @@ brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct brcms_info *wl;
- wl = HW_TO_WL(hw);
+ wl = hw->priv;
/* put driver in down state */
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_down(wl);
- UNLOCK(wl);
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-static int
-ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
- enum nl80211_channel_type type)
-{
- struct brcms_info *wl = HW_TO_WL(hw);
- int err = 0;
-
- switch (type) {
- case NL80211_CHAN_HT20:
- case NL80211_CHAN_NO_HT:
- err = brcms_c_set(wl->wlc, BRCM_SET_CHANNEL, chan->hw_value);
- break;
- case NL80211_CHAN_HT40MINUS:
- case NL80211_CHAN_HT40PLUS:
- wiphy_err(hw->wiphy,
- "%s: Need to implement 40 Mhz Channels!\n", __func__);
- err = 1;
- break;
- }
-
- if (err)
- return -EIO;
- return err;
+ spin_unlock_bh(&wl->lock);
}
static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
{
struct ieee80211_conf *conf = &hw->conf;
- struct brcms_info *wl = HW_TO_WL(hw);
+ struct brcms_info *wl = hw->priv;
int err = 0;
int new_int;
struct wiphy *wiphy = hw->wiphy;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
- if (brcms_c_set_par(wl->wlc, IOV_BCN_LI_BCN,
- conf->listen_interval) < 0) {
- wiphy_err(wiphy, "%s: Error setting listen_interval\n",
- __func__);
- err = -EIO;
- goto config_out;
- }
- brcms_c_get_par(wl->wlc, IOV_BCN_LI_BCN, &new_int);
+ brcms_c_set_beacon_listen_interval(wl->wlc,
+ conf->listen_interval);
}
if (changed & IEEE80211_CONF_CHANGE_MONITOR)
wiphy_err(wiphy, "%s: change monitor mode: %s (implement)\n",
@@ -293,40 +370,33 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
"true" : "false");
if (changed & IEEE80211_CONF_CHANGE_POWER) {
- if (brcms_c_set_par(wl->wlc, IOV_QTXPOWER,
- conf->power_level * 4) < 0) {
+ err = brcms_c_set_tx_power(wl->wlc, conf->power_level);
+ if (err < 0) {
wiphy_err(wiphy, "%s: Error setting power_level\n",
__func__);
- err = -EIO;
goto config_out;
}
- brcms_c_get_par(wl->wlc, IOV_QTXPOWER, &new_int);
- if (new_int != (conf->power_level * 4))
+ 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 * 4,
+ "\n", __func__, conf->power_level,
new_int);
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- err = ieee_set_channel(hw, conf->channel, conf->channel_type);
- }
- if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
- if (brcms_c_set
- (wl->wlc, BRCM_SET_SRL,
- conf->short_frame_max_tx_count) < 0) {
- wiphy_err(wiphy, "%s: Error setting srl\n", __func__);
- err = -EIO;
- goto config_out;
- }
- if (brcms_c_set(wl->wlc, BRCM_SET_LRL,
- conf->long_frame_max_tx_count) < 0) {
- wiphy_err(wiphy, "%s: Error setting lrl\n", __func__);
- err = -EIO;
- goto config_out;
- }
+ if (conf->channel_type == NL80211_CHAN_HT20 ||
+ conf->channel_type == NL80211_CHAN_NO_HT)
+ err = brcms_c_set_channel(wl->wlc,
+ conf->channel->hw_value);
+ else
+ err = -ENOTSUPP;
}
+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+ err = brcms_c_set_rate_limit(wl->wlc,
+ conf->short_frame_max_tx_count,
+ conf->long_frame_max_tx_count);
config_out:
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
return err;
}
@@ -335,9 +405,8 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info, u32 changed)
{
- struct brcms_info *wl = HW_TO_WL(hw);
+ struct brcms_info *wl = hw->priv;
struct wiphy *wiphy = hw->wiphy;
- int val;
if (changed & BSS_CHANGED_ASSOC) {
/* association status changed (associated/disassociated)
@@ -345,51 +414,48 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
*/
wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME,
__func__, info->assoc ? "" : "dis");
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_associate_upd(wl->wlc, info->assoc);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_ERP_SLOT) {
+ s8 val;
+
/* slot timing changed */
if (info->use_short_slot)
val = 1;
else
val = 0;
- LOCK(wl);
- brcms_c_set(wl->wlc, BRCMS_SET_SHORTSLOT_OVERRIDE, val);
- UNLOCK(wl);
+ spin_lock_bh(&wl->lock);
+ brcms_c_set_shortslot_override(wl->wlc, val);
+ spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_HT) {
/* 802.11n parameters changed */
u16 mode = info->ht_operation_mode;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_CFG,
mode & IEEE80211_HT_OP_MODE_PROTECTION);
brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_NONGF,
mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_OBSS,
mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
struct ieee80211_supported_band *bi;
u32 br_mask, i;
u16 rate;
- struct wl_rateset rs;
+ struct brcm_rateset rs;
int error;
/* retrieve the current rates */
- LOCK(wl);
- error = brcms_c_ioctl(wl->wlc, BRCM_GET_CURR_RATESET,
- &rs, sizeof(rs), NULL);
- UNLOCK(wl);
- if (error) {
- wiphy_err(wiphy, "%s: retrieve rateset failed: %d\n",
- __func__, error);
- return;
- }
+ spin_lock_bh(&wl->lock);
+ brcms_c_get_current_rateset(wl->wlc, &rs);
+ spin_unlock_bh(&wl->lock);
+
br_mask = info->basic_rates;
bi = hw->wiphy->bands[brcms_c_get_curband(wl->wlc)];
for (i = 0; i < bi->n_bitrates; i++) {
@@ -402,49 +468,55 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
}
/* update the rate set */
- LOCK(wl);
- brcms_c_ioctl(wl->wlc, BRCM_SET_RATESET, &rs, sizeof(rs), NULL);
- UNLOCK(wl);
+ spin_lock_bh(&wl->lock);
+ error = brcms_c_set_rateset(wl->wlc, &rs);
+ spin_unlock_bh(&wl->lock);
+ if (error)
+ wiphy_err(wiphy, "changing basic rates failed: %d\n",
+ error);
}
if (changed & BSS_CHANGED_BEACON_INT) {
/* Beacon interval changed */
- LOCK(wl);
- brcms_c_set(wl->wlc, BRCM_SET_BCNPRD, info->beacon_int);
- UNLOCK(wl);
+ spin_lock_bh(&wl->lock);
+ brcms_c_set_beacon_period(wl->wlc, info->beacon_int);
+ spin_unlock_bh(&wl->lock);
}
if (changed & BSS_CHANGED_BSSID) {
/* BSSID changed, for whatever reason (IBSS and managed mode) */
- LOCK(wl);
- brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
- info->bssid);
- UNLOCK(wl);
+ spin_lock_bh(&wl->lock);
+ brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid);
+ spin_unlock_bh(&wl->lock);
}
- if (changed & BSS_CHANGED_BEACON) {
+ if (changed & BSS_CHANGED_BEACON)
/* Beacon data changed, retrieve new beacon (beaconing modes) */
wiphy_err(wiphy, "%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__,
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 "
" (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");
}
+
if (changed & BSS_CHANGED_ARP_FILTER) {
/* Hardware ARP filter address list or state changed */
wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d"
" (implement)\n", __func__, info->arp_filter_enabled ?
"true" : "false", info->arp_addr_cnt);
}
+
if (changed & BSS_CHANGED_QOS) {
/*
* QoS for this association was enabled/disabled.
@@ -479,7 +551,7 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw,
if (changed_flags & FIF_OTHER_BSS)
wiphy_err(wiphy, "FIF_OTHER_BSS\n");
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS;
brcms_c_mac_bcn_promisc_change(wl->wlc, 1);
@@ -487,87 +559,39 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw,
brcms_c_mac_bcn_promisc_change(wl->wlc, 0);
wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS;
}
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
}
return;
}
-static int
-brcms_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
-{
- return 0;
-}
-
static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw)
{
struct brcms_info *wl = hw->priv;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_scan_start(wl->wlc);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
return;
}
static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw)
{
struct brcms_info *wl = hw->priv;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_scan_stop(wl->wlc);
- UNLOCK(wl);
- return;
-}
-
-static void brcms_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf)
-{
- wiphy_err(hw->wiphy, "%s: Enter\n", __func__);
+ spin_unlock_bh(&wl->lock);
return;
}
static int
-brcms_ops_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
+brcms_ops_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
{
struct brcms_info *wl = hw->priv;
- struct wl_cnt *cnt;
-
- LOCK(wl);
- cnt = wl->pub->_cnt;
- stats->dot11ACKFailureCount = 0;
- stats->dot11RTSFailureCount = 0;
- stats->dot11FCSErrorCount = 0;
- stats->dot11RTSSuccessCount = 0;
- UNLOCK(wl);
- return 0;
-}
-static void
-brcms_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
-{
- switch (cmd) {
- default:
- wiphy_err(hw->wiphy, "%s: Unknown cmd = %d\n", __func__,
- cmd);
- break;
- }
- return;
-}
-
-static int
-brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
- const struct ieee80211_tx_queue_params *params)
-{
- struct brcms_info *wl = hw->priv;
-
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_wme_setparams(wl->wlc, queue, params, true);
- UNLOCK(wl);
-
- return 0;
-}
+ spin_unlock_bh(&wl->lock);
-static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw)
-{
- wiphy_err(hw->wiphy, "%s: Enter\n", __func__);
return 0;
}
@@ -575,25 +599,14 @@ static int
brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct scb *scb;
-
- int i;
struct brcms_info *wl = hw->priv;
+ struct scb *scb = &wl->wlc->pri_scb;
- /* Init the scb */
- scb = (struct scb *)sta->drv_priv;
- memset(scb, 0, sizeof(struct scb));
- for (i = 0; i < NUMPRIO; i++)
- scb->seqctl[i] = 0xFFFF;
- scb->seqctl_nonqos = 0xFFFF;
- scb->magic = SCB_MAGIC;
+ brcms_c_init_scb(scb);
- wl->pub->global_scb = scb;
wl->pub->global_ampdu = &(scb->scb_ampdu);
wl->pub->global_ampdu->scb = scb;
wl->pub->global_ampdu->max_pdu = 16;
- brcmu_pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
- AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT);
sta->ht_cap.ht_supported = true;
sta->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
@@ -602,14 +615,10 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT;
- /* minstrel_ht initiates addBA on our behalf by calling ieee80211_start_tx_ba_session() */
- return 0;
-}
-
-static int
-brcms_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
+ /*
+ * minstrel_ht initiates addBA on our behalf by calling
+ * ieee80211_start_tx_ba_session()
+ */
return 0;
}
@@ -620,8 +629,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
u8 buf_size)
{
- struct scb *scb = (struct scb *)sta->drv_priv;
struct brcms_info *wl = hw->priv;
+ struct scb *scb = &wl->wlc->pri_scb;
int status;
if (WARN_ON(scb->magic != SCB_MAGIC))
@@ -632,23 +641,21 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_RX_STOP:
break;
case IEEE80211_AMPDU_TX_START:
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
status = brcms_c_aggregatable(wl->wlc, tid);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
if (!status) {
wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n",
tid);
return -EINVAL;
}
- /* Future improvement: Use the starting sequence number provided ... */
- *ssn = 0;
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP:
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_ampdu_flush(wl->wlc, sta, tid);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
@@ -658,11 +665,11 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
* recipient and traffic class. 'ampdu_factor' gives maximum
* AMPDU size.
*/
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size,
(1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor)) - 1);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
/* Power save wakeup */
break;
default:
@@ -675,26 +682,26 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw)
{
- struct brcms_info *wl = HW_TO_WL(hw);
+ struct brcms_info *wl = hw->priv;
bool blocked;
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
blocked = brcms_c_check_radio_disabled(wl->wlc);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
}
static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
{
- struct brcms_info *wl = HW_TO_WL(hw);
+ struct brcms_info *wl = hw->priv;
no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
/* wait for packet queue and dma fifos to run empty */
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
brcms_c_wait_for_tx_completion(wl->wlc, drop);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
}
static const struct ieee80211_ops brcms_ops = {
@@ -706,16 +713,10 @@ static const struct ieee80211_ops brcms_ops = {
.config = brcms_ops_config,
.bss_info_changed = brcms_ops_bss_info_changed,
.configure_filter = brcms_ops_configure_filter,
- .set_tim = brcms_ops_set_tim,
.sw_scan_start = brcms_ops_sw_scan_start,
.sw_scan_complete = brcms_ops_sw_scan_complete,
- .set_tsf = brcms_ops_set_tsf,
- .get_stats = brcms_ops_get_stats,
- .sta_notify = brcms_ops_sta_notify,
.conf_tx = brcms_ops_conf_tx,
- .get_tsf = brcms_ops_get_tsf,
.sta_add = brcms_ops_sta_add,
- .sta_remove = brcms_ops_sta_remove,
.ampdu_action = brcms_ops_ampdu_action,
.rfkill_poll = brcms_ops_rfkill_poll,
.flush = brcms_ops_flush,
@@ -729,6 +730,284 @@ static int brcms_set_hint(struct brcms_info *wl, char *abbrev)
return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
}
+void brcms_dpc(unsigned long data)
+{
+ struct brcms_info *wl;
+
+ wl = (struct brcms_info *) data;
+
+ spin_lock_bh(&wl->lock);
+
+ /* call the common second level interrupt handler */
+ if (wl->pub->up) {
+ if (wl->resched) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&wl->isr_lock, flags);
+ brcms_c_intrsupd(wl->wlc);
+ spin_unlock_irqrestore(&wl->isr_lock, flags);
+ }
+
+ wl->resched = brcms_c_dpc(wl->wlc, true);
+ }
+
+ /* brcms_c_dpc() may bring the driver down */
+ if (!wl->pub->up)
+ goto done;
+
+ /* re-schedule dpc */
+ if (wl->resched)
+ tasklet_schedule(&wl->tasklet);
+ else
+ /* re-enable interrupts */
+ brcms_intrson(wl);
+
+ done:
+ spin_unlock_bh(&wl->lock);
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev)
+{
+ int status;
+ struct device *device = &pdev->dev;
+ char fw_name[100];
+ int i;
+
+ memset(&wl->fw, 0, sizeof(struct brcms_firmware));
+ for (i = 0; i < MAX_FW_IMAGES; i++) {
+ if (brcms_firmwares[i] == NULL)
+ break;
+ sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
+ UCODE_LOADER_API_VER);
+ status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
+ if (status) {
+ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+ KBUILD_MODNAME, fw_name);
+ return status;
+ }
+ sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
+ UCODE_LOADER_API_VER);
+ status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
+ if (status) {
+ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+ KBUILD_MODNAME, fw_name);
+ return status;
+ }
+ wl->fw.hdr_num_entries[i] =
+ wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
+ }
+ wl->fw.fw_cnt = i;
+ return brcms_ucode_data_init(wl, &wl->ucode);
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static void brcms_release_fw(struct brcms_info *wl)
+{
+ int i;
+ for (i = 0; i < MAX_FW_IMAGES; i++) {
+ release_firmware(wl->fw.fw_bin[i]);
+ release_firmware(wl->fw.fw_hdr[i]);
+ }
+}
+
+/**
+ * This function frees the WL per-device resources.
+ *
+ * This function frees resources owned by the WL device pointed to
+ * by the wl parameter.
+ *
+ * precondition: can both be called locked and unlocked
+ *
+ */
+static void brcms_free(struct brcms_info *wl)
+{
+ struct brcms_timer *t, *next;
+
+ /* free ucode data */
+ if (wl->fw.fw_cnt)
+ brcms_ucode_data_free(&wl->ucode);
+ if (wl->irq)
+ free_irq(wl->irq, wl);
+
+ /* kill dpc */
+ tasklet_kill(&wl->tasklet);
+
+ if (wl->pub)
+ brcms_c_module_unregister(wl->pub, "linux", wl);
+
+ /* free common resources */
+ if (wl->wlc) {
+ brcms_c_detach(wl->wlc);
+ wl->wlc = NULL;
+ wl->pub = NULL;
+ }
+
+ /* virtual interface deletion is deferred so we cannot spinwait */
+
+ /* wait for all pending callbacks to complete */
+ while (atomic_read(&wl->callbacks) > 0)
+ schedule();
+
+ /* free timers */
+ for (t = wl->timers; t; t = next) {
+ next = t->next;
+#ifdef BCMDBG
+ kfree(t->name);
+#endif
+ kfree(t);
+ }
+
+ /*
+ * unregister_netdev() calls get_stats() which may read chip
+ * registers so we cannot unmap the chip registers until
+ * after calling unregister_netdev() .
+ */
+ if (wl->regsva)
+ iounmap(wl->regsva);
+
+ wl->regsva = NULL;
+}
+
+/*
+* called from both kernel as from this kernel module.
+* precondition: perimeter lock is not acquired.
+*/
+static void brcms_remove(struct pci_dev *pdev)
+{
+ struct brcms_info *wl;
+ struct ieee80211_hw *hw;
+ int status;
+
+ hw = pci_get_drvdata(pdev);
+ wl = hw->priv;
+ if (!wl) {
+ pr_err("wl: brcms_remove: pci_get_drvdata failed\n");
+ return;
+ }
+
+ spin_lock_bh(&wl->lock);
+ status = brcms_c_chipmatch(pdev->vendor, pdev->device);
+ spin_unlock_bh(&wl->lock);
+ if (!status) {
+ wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch "
+ "failed\n");
+ return;
+ }
+ if (wl->wlc) {
+ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
+ wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+ ieee80211_unregister_hw(hw);
+ spin_lock_bh(&wl->lock);
+ brcms_down(wl);
+ spin_unlock_bh(&wl->lock);
+ }
+ pci_disable_device(pdev);
+
+ brcms_free(wl);
+
+ pci_set_drvdata(pdev, NULL);
+ ieee80211_free_hw(hw);
+}
+
+static irqreturn_t brcms_isr(int irq, void *dev_id)
+{
+ struct brcms_info *wl;
+ bool ours, wantdpc;
+
+ 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);
+ }
+ }
+
+ spin_unlock(&wl->isr_lock);
+
+ return IRQ_RETVAL(ours);
+}
+
+/*
+ * is called in brcms_pci_probe() context, therefore no locking required.
+ */
+static int ieee_hw_rate_init(struct ieee80211_hw *hw)
+{
+ struct brcms_info *wl = hw->priv;
+ struct brcms_c_info *wlc = wl->wlc;
+ struct ieee80211_supported_band *band;
+ int has_5g = 0;
+ u16 phy_type;
+
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+
+ phy_type = brcms_c_get_phy_type(wl->wlc, 0);
+ if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) {
+ band = &wlc->bandstate[BAND_2G_INDEX]->band;
+ *band = brcms_band_2GHz_nphy_template;
+ if (phy_type == PHY_TYPE_LCN) {
+ /* Single stream */
+ band->ht_cap.mcs.rx_mask[1] = 0;
+ band->ht_cap.mcs.rx_highest = cpu_to_le16(72);
+ }
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band;
+ } else {
+ return -EPERM;
+ }
+
+ /* Assume all bands use the same phy. True for 11n devices. */
+ if (wl->pub->_nbands > 1) {
+ has_5g++;
+ if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) {
+ band = &wlc->bandstate[BAND_5G_INDEX]->band;
+ *band = brcms_band_5GHz_nphy_template;
+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band;
+ } else {
+ return -EPERM;
+ }
+ }
+ return 0;
+}
+
+/*
+ * is called in brcms_pci_probe() context, therefore no locking required.
+ */
+static int ieee_hw_init(struct ieee80211_hw *hw)
+{
+ hw->flags = IEEE80211_HW_SIGNAL_DBM
+ /* | IEEE80211_HW_CONNECTION_MONITOR What is this? */
+ | IEEE80211_HW_REPORTS_TX_ACK_STATUS
+ | IEEE80211_HW_AMPDU_AGGREGATION;
+
+ hw->extra_tx_headroom = brcms_c_get_header_len();
+ hw->queues = N_TX_QUEUES;
+ hw->max_rates = 2; /* Primary rate and 1 fallback rate */
+
+ /* channel change time is dependent on chip and band */
+ hw->channel_change_time = 7 * 1000;
+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+ hw->rate_control_algorithm = "minstrel_ht";
+
+ hw->sta_data_size = 0;
+ return ieee_hw_rate_init(hw);
+}
+
/**
* attach to the WL device.
*
@@ -744,21 +1023,19 @@ static int brcms_set_hint(struct brcms_info *wl, char *abbrev)
* is called in brcms_pci_probe() context, therefore no locking required.
*/
static struct brcms_info *brcms_attach(u16 vendor, u16 device,
- unsigned long regs,
- uint bustype, void *btparam, uint irq)
+ resource_size_t regs,
+ struct pci_dev *btparam, uint irq)
{
struct brcms_info *wl = NULL;
int unit, err;
- unsigned long base_addr;
struct ieee80211_hw *hw;
u8 perm[ETH_ALEN];
unit = n_adapters_found;
err = 0;
- if (unit < 0) {
+ if (unit < 0)
return NULL;
- }
/* allocate private info */
hw = pci_get_drvdata(btparam); /* btparam == pdev */
@@ -773,19 +1050,7 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
/* setup the bottom half handler */
tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);
-
-
- base_addr = regs;
-
- if (bustype == PCI_BUS || bustype == RPC_BUS) {
- /* Do nothing */
- } else {
- bustype = PCI_BUS;
- BCMMSG(wl->wiphy, "force to PCI\n");
- }
- wl->bcm_bustype = bustype;
-
- wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ);
+ wl->regsva = ioremap_nocache(regs, PCI_BAR0_WINSZ);
if (wl->regsva == NULL) {
wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit);
goto fail;
@@ -794,17 +1059,17 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
spin_lock_init(&wl->isr_lock);
/* prepare ucode */
- if (brcms_request_fw(wl, (struct pci_dev *)btparam) < 0) {
+ if (brcms_request_fw(wl, btparam) < 0) {
wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
"%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
brcms_release_fw(wl);
- brcms_remove((struct pci_dev *)btparam);
+ brcms_remove(btparam);
return NULL;
}
/* common load-time initialization */
- wl->wlc = brcms_c_attach((void *)wl, vendor, device, unit, false,
- wl->regsva, wl->bcm_bustype, btparam, &err);
+ wl->wlc = brcms_c_attach(wl, vendor, device, unit, false,
+ wl->regsva, btparam, &err);
brcms_release_fw(wl);
if (!wl->wlc) {
wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
@@ -815,10 +1080,8 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
wl->pub->ieee_hw = hw;
- if (brcms_c_set_par(wl->wlc, IOV_MPC, 0) < 0) {
- wiphy_err(wl->wiphy, "wl%d: Error setting MPC variable to 0\n",
- unit);
- }
+ /* disable mpc */
+ brcms_c_set_radio_mpc(wl->wlc, false);
/* register our interrupt handler */
if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
@@ -828,7 +1091,7 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
wl->irq = irq;
/* register module */
- brcms_c_module_register(wl->pub, "linux", wl, wl_linux_watchdog, NULL);
+ brcms_c_module_register(wl->pub, "linux", wl, NULL);
if (ieee_hw_init(hw)) {
wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit,
@@ -842,19 +1105,17 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
SET_IEEE80211_PERM_ADDR(hw, perm);
err = ieee80211_register_hw(hw);
- if (err) {
+ if (err)
wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status"
"%d\n", __func__, err);
- }
if (wl->pub->srom_ccode[0])
err = brcms_set_hint(wl, wl->pub->srom_ccode);
else
err = brcms_set_hint(wl, "US");
- if (err) {
+ if (err)
wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n",
__func__, err);
- }
n_adapters_found++;
return wl;
@@ -866,236 +1127,6 @@ fail:
-#define CHAN2GHZ(channel, freqency, chflags) { \
- .band = IEEE80211_BAND_2GHZ, \
- .center_freq = (freqency), \
- .hw_value = (channel), \
- .flags = chflags, \
- .max_antenna_gain = 0, \
- .max_power = 19, \
-}
-
-static struct ieee80211_channel brcms_2ghz_chantable[] = {
- CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN2GHZ(5, 2432, 0),
- CHAN2GHZ(6, 2437, 0),
- CHAN2GHZ(7, 2442, 0),
- CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(12, 2467,
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(13, 2472,
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_NO_HT40PLUS),
- CHAN2GHZ(14, 2484,
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
-};
-
-#define CHAN5GHZ(channel, chflags) { \
- .band = IEEE80211_BAND_5GHZ, \
- .center_freq = 5000 + 5*(channel), \
- .hw_value = (channel), \
- .flags = chflags, \
- .max_antenna_gain = 0, \
- .max_power = 21, \
-}
-
-static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = {
- /* UNII-1 */
- CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
- /* UNII-2 */
- CHAN5GHZ(52,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(56,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(60,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(64,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- /* MID */
- CHAN5GHZ(100,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(104,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(108,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(112,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(116,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(120,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(124,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(128,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(132,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(136,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(140,
- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
- IEEE80211_CHAN_NO_HT40MINUS),
- /* UNII-3 */
- CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
- CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
- CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
-};
-
-#define RATE(rate100m, _flags) { \
- .bitrate = (rate100m), \
- .flags = (_flags), \
- .hw_value = (rate100m / 5), \
-}
-
-static struct ieee80211_rate legacy_ratetable[] = {
- RATE(10, 0),
- RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
- RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
- RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
- RATE(60, 0),
- RATE(90, 0),
- RATE(120, 0),
- RATE(180, 0),
- RATE(240, 0),
- RATE(360, 0),
- RATE(480, 0),
- RATE(540, 0),
-};
-
-static struct ieee80211_supported_band brcms_band_2GHz_nphy = {
- .band = IEEE80211_BAND_2GHZ,
- .channels = brcms_2ghz_chantable,
- .n_channels = ARRAY_SIZE(brcms_2ghz_chantable),
- .bitrates = legacy_ratetable,
- .n_bitrates = ARRAY_SIZE(legacy_ratetable),
- .ht_cap = {
- /* from include/linux/ieee80211.h */
- .cap = IEEE80211_HT_CAP_GRN_FLD |
- IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
- .ht_supported = true,
- .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
- .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
- .mcs = {
- /* placeholders for now */
- .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
- .rx_highest = 500,
- .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
- }
-};
-
-static struct ieee80211_supported_band brcms_band_5GHz_nphy = {
- .band = IEEE80211_BAND_5GHZ,
- .channels = brcms_5ghz_nphy_chantable,
- .n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable),
- .bitrates = legacy_ratetable + 4,
- .n_bitrates = ARRAY_SIZE(legacy_ratetable) - 4,
- .ht_cap = {
- /* use IEEE80211_HT_CAP_* from include/linux/ieee80211.h */
- .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */
- .ht_supported = true,
- .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
- .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
- .mcs = {
- /* placeholders for now */
- .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
- .rx_highest = 500,
- .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
- }
-};
-
-/*
- * is called in brcms_pci_probe() context, therefore no locking required.
- */
-static int ieee_hw_rate_init(struct ieee80211_hw *hw)
-{
- struct brcms_info *wl = HW_TO_WL(hw);
- int has_5g;
- char phy_list[4];
-
- has_5g = 0;
-
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
- hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
-
- if (brcms_c_get(wl->wlc, BRCM_GET_PHYLIST, (int *)&phy_list) < 0)
- wiphy_err(hw->wiphy, "Phy list failed\n");
-
- if (phy_list[0] == 'n' || phy_list[0] == 'c') {
- if (phy_list[0] == 'c') {
- /* Single stream */
- brcms_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0;
- brcms_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72;
- }
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &brcms_band_2GHz_nphy;
- } else {
- return -EPERM;
- }
-
- /* Assume all bands use the same phy. True for 11n devices. */
- if (NBANDS_PUB(wl->pub) > 1) {
- has_5g++;
- if (phy_list[0] == 'n' || phy_list[0] == 'c') {
- hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
- &brcms_band_5GHz_nphy;
- } else {
- return -EPERM;
- }
- }
- return 0;
-}
-
-/*
- * is called in brcms_pci_probe() context, therefore no locking required.
- */
-static int ieee_hw_init(struct ieee80211_hw *hw)
-{
- hw->flags = IEEE80211_HW_SIGNAL_DBM
- /* | IEEE80211_HW_CONNECTION_MONITOR What is this? */
- | IEEE80211_HW_REPORTS_TX_ACK_STATUS
- | IEEE80211_HW_AMPDU_AGGREGATION;
-
- hw->extra_tx_headroom = brcms_c_get_header_len();
- hw->queues = N_TX_QUEUES;
- hw->max_rates = 2; /* Primary rate and 1 fallback rate */
-
- hw->channel_change_time = 7 * 1000; /* channel change time is dependent on chip and band */
- hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
-
- hw->rate_control_algorithm = "minstrel_ht";
-
- hw->sta_data_size = sizeof(struct scb);
- return ieee_hw_rate_init(hw);
-}
-
/**
* determines if a device is a WL device, and if so, attaches it.
*
@@ -1149,7 +1180,7 @@ brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
memset(hw->priv, 0, sizeof(*wl));
wl = brcms_attach(pdev->vendor, pdev->device,
- pci_resource_start(pdev, 0), PCI_BUS, pdev,
+ pci_resource_start(pdev, 0), pdev,
pdev->irq);
if (!wl) {
@@ -1166,7 +1197,7 @@ static int brcms_suspend(struct pci_dev *pdev, pm_message_t state)
struct ieee80211_hw *hw;
hw = pci_get_drvdata(pdev);
- wl = HW_TO_WL(hw);
+ wl = hw->priv;
if (!wl) {
wiphy_err(wl->wiphy,
"brcms_suspend: pci_get_drvdata failed\n");
@@ -1174,9 +1205,9 @@ static int brcms_suspend(struct pci_dev *pdev, pm_message_t state)
}
/* only need to flag hw is down for proper resume */
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
wl->pub->hw_up = false;
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
pci_save_state(pdev);
pci_disable_device(pdev);
@@ -1191,7 +1222,7 @@ static int brcms_resume(struct pci_dev *pdev)
u32 val;
hw = pci_get_drvdata(pdev);
- wl = HW_TO_WL(hw);
+ wl = hw->priv;
if (!wl) {
wiphy_err(wl->wiphy,
"wl: brcms_resume: pci_get_drvdata failed\n");
@@ -1221,47 +1252,6 @@ static int brcms_resume(struct pci_dev *pdev)
return err;
}
-/*
-* called from both kernel as from this kernel module.
-* precondition: perimeter lock is not acquired.
-*/
-static void brcms_remove(struct pci_dev *pdev)
-{
- struct brcms_info *wl;
- struct ieee80211_hw *hw;
- int status;
-
- hw = pci_get_drvdata(pdev);
- wl = HW_TO_WL(hw);
- if (!wl) {
- pr_err("wl: brcms_remove: pci_get_drvdata failed\n");
- return;
- }
-
- LOCK(wl);
- status = brcms_c_chipmatch(pdev->vendor, pdev->device);
- UNLOCK(wl);
- if (!status) {
- wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch "
- "failed\n");
- return;
- }
- if (wl->wlc) {
- wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
- wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
- ieee80211_unregister_hw(hw);
- LOCK(wl);
- brcms_down(wl);
- UNLOCK(wl);
- }
- pci_disable_device(pdev);
-
- brcms_free(wl);
-
- pci_set_drvdata(pdev, NULL);
- ieee80211_free_hw(hw);
-}
-
static struct pci_driver brcms_pci_driver = {
.name = KBUILD_MODNAME,
.probe = brcms_pci_probe,
@@ -1285,8 +1275,6 @@ static int __init brcms_module_init(void)
#ifdef BCMDBG
if (msglevel != 0xdeadbeef)
brcm_msg_level = msglevel;
- if (phymsglevel != 0xdeadbeef)
- phyhal_msg_level = phymsglevel;
#endif /* BCMDBG */
error = pci_register_driver(&brcms_pci_driver);
@@ -1314,82 +1302,6 @@ static void __exit brcms_module_exit(void)
module_init(brcms_module_init);
module_exit(brcms_module_exit);
-/**
- * This function frees the WL per-device resources.
- *
- * This function frees resources owned by the WL device pointed to
- * by the wl parameter.
- *
- * precondition: can both be called locked and unlocked
- *
- */
-static void brcms_free(struct brcms_info *wl)
-{
- struct brcms_timer *t, *next;
-
- /* free ucode data */
- if (wl->fw.fw_cnt)
- brcms_ucode_data_free();
- if (wl->irq)
- free_irq(wl->irq, wl);
-
- /* kill dpc */
- tasklet_kill(&wl->tasklet);
-
- if (wl->pub) {
- brcms_c_module_unregister(wl->pub, "linux", wl);
- }
-
- /* free common resources */
- if (wl->wlc) {
- brcms_c_detach(wl->wlc);
- wl->wlc = NULL;
- wl->pub = NULL;
- }
-
- /* virtual interface deletion is deferred so we cannot spinwait */
-
- /* wait for all pending callbacks to complete */
- while (atomic_read(&wl->callbacks) > 0)
- schedule();
-
- /* free timers */
- for (t = wl->timers; t; t = next) {
- next = t->next;
-#ifdef BCMDBG
- kfree(t->name);
-#endif
- kfree(t);
- }
-
- /*
- * unregister_netdev() calls get_stats() which may read chip registers
- * so we cannot unmap the chip registers until after calling unregister_netdev() .
- */
- if (wl->regsva && wl->bcm_bustype != SDIO_BUS &&
- wl->bcm_bustype != JTAG_BUS) {
- iounmap((void *)wl->regsva);
- }
- wl->regsva = NULL;
-}
-
-/* flags the given rate in rateset as requested */
-static void brcms_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br)
-{
- u32 i;
-
- for (i = 0; i < rs->count; i++) {
- if (rate != (rs->rates[i] & 0x7f))
- continue;
-
- if (is_br)
- rs->rates[i] |= BRCMS_RATE_FLAG;
- else
- rs->rates[i] &= BRCMS_RATE_MASK;
- return;
- }
-}
-
/*
* precondition: perimeter lock has been acquired
*/
@@ -1404,7 +1316,7 @@ void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
*/
void brcms_init(struct brcms_info *wl)
{
- BCMMSG(WL_TO_HW(wl)->wiphy, "wl%d\n", wl->pub->unit);
+ BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
brcms_reset(wl);
brcms_c_init(wl->wlc);
@@ -1415,7 +1327,7 @@ void brcms_init(struct brcms_info *wl)
*/
uint brcms_reset(struct brcms_info *wl)
{
- BCMMSG(WL_TO_HW(wl)->wiphy, "wl%d\n", wl->pub->unit);
+ BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
brcms_c_reset(wl->wlc);
/* dpc will not be rescheduled */
@@ -1432,17 +1344,9 @@ void brcms_intrson(struct brcms_info *wl)
{
unsigned long flags;
- INT_LOCK(wl, flags);
+ spin_lock_irqsave(&wl->isr_lock, flags);
brcms_c_intrson(wl->wlc);
- INT_UNLOCK(wl, flags);
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-bool wl_alloc_dma_resources(struct brcms_info *wl, uint addrwidth)
-{
- return true;
+ spin_unlock_irqrestore(&wl->isr_lock, flags);
}
u32 brcms_intrsoff(struct brcms_info *wl)
@@ -1450,9 +1354,9 @@ u32 brcms_intrsoff(struct brcms_info *wl)
unsigned long flags;
u32 status;
- INT_LOCK(wl, flags);
+ spin_lock_irqsave(&wl->isr_lock, flags);
status = brcms_c_intrsoff(wl->wlc);
- INT_UNLOCK(wl, flags);
+ spin_unlock_irqrestore(&wl->isr_lock, flags);
return status;
}
@@ -1460,9 +1364,9 @@ void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask)
{
unsigned long flags;
- INT_LOCK(wl, flags);
+ spin_lock_irqsave(&wl->isr_lock, flags);
brcms_c_intrsrestore(wl->wlc, macintmask);
- INT_UNLOCK(wl, flags);
+ spin_unlock_irqrestore(&wl->isr_lock, flags);
}
/*
@@ -1492,110 +1396,42 @@ void brcms_down(struct brcms_info *wl)
callbacks = atomic_read(&wl->callbacks) - ret_val;
/* wait for down callbacks to complete */
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
/* For HIGH_only driver, it's important to actually schedule other work,
* not just spin wait since everything runs at schedule level
*/
SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
- LOCK(wl);
-}
-
-static irqreturn_t brcms_isr(int irq, void *dev_id)
-{
- struct brcms_info *wl;
- bool ours, wantdpc;
- unsigned long flags;
-
- wl = (struct brcms_info *) dev_id;
-
- ISR_LOCK(wl, flags);
-
- /* 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);
- }
- }
-
- ISR_UNLOCK(wl, flags);
-
- return IRQ_RETVAL(ours);
-}
-
-static void brcms_dpc(unsigned long data)
-{
- struct brcms_info *wl;
-
- wl = (struct brcms_info *) data;
-
- LOCK(wl);
-
- /* call the common second level interrupt handler */
- if (wl->pub->up) {
- if (wl->resched) {
- unsigned long flags;
-
- INT_LOCK(wl, flags);
- brcms_c_intrsupd(wl->wlc);
- INT_UNLOCK(wl, flags);
- }
-
- wl->resched = brcms_c_dpc(wl->wlc, true);
- }
-
- /* brcms_c_dpc() may bring the driver down */
- if (!wl->pub->up)
- goto done;
-
- /* re-schedule dpc */
- if (wl->resched)
- tasklet_schedule(&wl->tasklet);
- else {
- /* re-enable interrupts */
- brcms_intrson(wl);
- }
-
- done:
- UNLOCK(wl);
-}
-
-/*
- * is called by the kernel from software irq context
- */
-static void brcms_timer(unsigned long data)
-{
- _brcms_timer((struct brcms_timer *) data);
+ spin_lock_bh(&wl->lock);
}
/*
* precondition: perimeter lock is not acquired
*/
-static void _brcms_timer(struct brcms_timer *t)
+static void _brcms_timer(struct work_struct *work)
{
- LOCK(t->wl);
+ struct brcms_timer *t = container_of(work, struct brcms_timer,
+ dly_wrk.work);
+
+ spin_lock_bh(&t->wl->lock);
if (t->set) {
if (t->periodic) {
- t->timer.expires = jiffies + t->ms * HZ / 1000;
atomic_inc(&t->wl->callbacks);
- add_timer(&t->timer);
- t->set = true;
- } else
+ ieee80211_queue_delayed_work(t->wl->pub->ieee_hw,
+ &t->dly_wrk,
+ msecs_to_jiffies(t->ms));
+ } else {
t->set = false;
+ }
t->fn(t->arg);
}
atomic_dec(&t->wl->callbacks);
- UNLOCK(t->wl);
+ spin_unlock_bh(&t->wl->lock);
}
/*
@@ -1611,15 +1447,10 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
struct brcms_timer *t;
t = kzalloc(sizeof(struct brcms_timer), GFP_ATOMIC);
- if (!t) {
- wiphy_err(wl->wiphy, "wl%d: brcms_init_timer: out of memory\n",
- wl->pub->unit);
- return 0;
- }
+ if (!t)
+ return NULL;
- init_timer(&t->timer);
- t->timer.data = (unsigned long) t;
- t->timer.function = brcms_timer;
+ INIT_DELAYED_WORK(&t->dly_wrk, _brcms_timer);
t->wl = wl;
t->fn = fn;
t->arg = arg;
@@ -1635,27 +1466,28 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
return t;
}
-/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate
+/*
+ * adds only the kernel timer since it's going to be more accurate
* as well as it's easier to make it periodic
*
* precondition: perimeter lock has been acquired
*/
-void brcms_add_timer(struct brcms_info *wl, struct brcms_timer *t, uint ms,
- int periodic)
+void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)
{
+ struct ieee80211_hw *hw = t->wl->pub->ieee_hw;
+
#ifdef BCMDBG
- if (t->set) {
- wiphy_err(wl->wiphy, "%s: Already set. Name: %s, per %d\n",
+ if (t->set)
+ wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n",
__func__, t->name, periodic);
- }
#endif
t->ms = ms;
t->periodic = (bool) periodic;
t->set = true;
- t->timer.expires = jiffies + ms * HZ / 1000;
- atomic_inc(&wl->callbacks);
- add_timer(&t->timer);
+ atomic_inc(&t->wl->callbacks);
+
+ ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms));
}
/*
@@ -1663,14 +1495,14 @@ void brcms_add_timer(struct brcms_info *wl, struct brcms_timer *t, uint ms,
*
* precondition: perimeter lock has been acquired
*/
-bool brcms_del_timer(struct brcms_info *wl, struct brcms_timer *t)
+bool brcms_del_timer(struct brcms_timer *t)
{
if (t->set) {
t->set = false;
- if (!del_timer(&t->timer)) {
+ if (!cancel_delayed_work(&t->dly_wrk))
return false;
- }
- atomic_dec(&wl->callbacks);
+
+ atomic_dec(&t->wl->callbacks);
}
return true;
@@ -1679,12 +1511,13 @@ bool brcms_del_timer(struct brcms_info *wl, struct brcms_timer *t)
/*
* precondition: perimeter lock has been acquired
*/
-void brcms_free_timer(struct brcms_info *wl, struct brcms_timer *t)
+void brcms_free_timer(struct brcms_timer *t)
{
+ struct brcms_info *wl = t->wl;
struct brcms_timer *tmp;
/* delete the timer in case it is active */
- brcms_del_timer(wl, t);
+ brcms_del_timer(t);
if (wl->timers == t) {
wl->timers = wl->timers->next;
@@ -1712,27 +1545,6 @@ void brcms_free_timer(struct brcms_info *wl, struct brcms_timer *t)
}
/*
- * runs in software irq context
- *
- * precondition: perimeter lock is not acquired
- */
-static int wl_linux_watchdog(void *ctx)
-{
- return 0;
-}
-
-struct firmware_hdr {
- u32 offset;
- u32 len;
- u32 idx;
-};
-
-char *brcms_firmwares[MAX_FW_IMAGES] = {
- "brcm/bcm43xx",
- NULL
-};
-
-/*
* precondition: perimeter lock has been acquired
*/
int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
@@ -1744,15 +1556,15 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
for (entry = 0; entry < wl->fw.hdr_num_entries[i];
entry++, hdr++) {
- if (hdr->idx == idx) {
- pdata = wl->fw.fw_bin[i]->data + hdr->offset;
- *pbuf = kmalloc(hdr->len, GFP_ATOMIC);
- if (*pbuf == NULL) {
- wiphy_err(wl->wiphy, "fail to alloc %d"
- " bytes\n", hdr->len);
+ u32 len = le32_to_cpu(hdr->len);
+ if (le32_to_cpu(hdr->idx) == idx) {
+ pdata = wl->fw.fw_bin[i]->data +
+ le32_to_cpu(hdr->offset);
+ *pbuf = kmalloc(len, GFP_ATOMIC);
+ if (*pbuf == NULL)
goto fail;
- }
- memcpy(*pbuf, pdata, hdr->len);
+
+ memcpy(*pbuf, pdata, len);
return 0;
}
}
@@ -1768,7 +1580,7 @@ fail:
* Precondition: Since this function is called in brcms_pci_probe() context,
* no locking is required.
*/
-int brcms_ucode_init_uint(struct brcms_info *wl, u32 *data, u32 idx)
+int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
{
int i, entry;
const u8 *pdata;
@@ -1777,14 +1589,15 @@ int brcms_ucode_init_uint(struct brcms_info *wl, u32 *data, u32 idx)
hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
for (entry = 0; entry < wl->fw.hdr_num_entries[i];
entry++, hdr++) {
- if (hdr->idx == idx) {
- pdata = wl->fw.fw_bin[i]->data + hdr->offset;
- if (hdr->len != 4) {
+ if (le32_to_cpu(hdr->idx) == idx) {
+ pdata = wl->fw.fw_bin[i]->data +
+ le32_to_cpu(hdr->offset);
+ if (le32_to_cpu(hdr->len) != 4) {
wiphy_err(wl->wiphy,
"ERROR: fw hdr len\n");
return -ENOMSG;
}
- *data = *((u32 *) pdata);
+ *n_bytes = le32_to_cpu(*((__le32 *) pdata));
return 0;
}
}
@@ -1794,44 +1607,6 @@ int brcms_ucode_init_uint(struct brcms_info *wl, u32 *data, u32 idx)
}
/*
- * Precondition: Since this function is called in brcms_pci_probe() context,
- * no locking is required.
- */
-static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev)
-{
- int status;
- struct device *device = &pdev->dev;
- char fw_name[100];
- int i;
-
- memset((void *)&wl->fw, 0, sizeof(struct brcms_firmware));
- for (i = 0; i < MAX_FW_IMAGES; i++) {
- if (brcms_firmwares[i] == NULL)
- break;
- sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
- UCODE_LOADER_API_VER);
- status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
- if (status) {
- wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
- KBUILD_MODNAME, fw_name);
- return status;
- }
- sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
- UCODE_LOADER_API_VER);
- status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
- if (status) {
- wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
- KBUILD_MODNAME, fw_name);
- return status;
- }
- wl->fw.hdr_num_entries[i] =
- wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
- }
- wl->fw.fw_cnt = i;
- return brcms_ucode_data_init(wl);
-}
-
-/*
* precondition: can both be called locked and unlocked
*/
void brcms_ucode_free_buf(void *p)
@@ -1840,20 +1615,6 @@ void brcms_ucode_free_buf(void *p)
}
/*
- * Precondition: Since this function is called in brcms_pci_probe() context,
- * no locking is required.
- */
-static void brcms_release_fw(struct brcms_info *wl)
-{
- int i;
- for (i = 0; i < MAX_FW_IMAGES; i++) {
- release_firmware(wl->fw.fw_bin[i]);
- release_firmware(wl->fw.fw_hdr[i]);
- }
-}
-
-
-/*
* checks validity of all firmware images loaded from user space
*
* Precondition: Since this function is called in brcms_pci_probe() context,
@@ -1890,7 +1651,8 @@ int brcms_check_firmwares(struct brcms_info *wl)
ucode_hdr = (struct firmware_hdr *)fw_hdr->data;
for (entry = 0; entry < wl->fw.hdr_num_entries[i] &&
!rc; entry++, ucode_hdr++) {
- if (ucode_hdr->offset + ucode_hdr->len >
+ if (le32_to_cpu(ucode_hdr->offset) +
+ le32_to_cpu(ucode_hdr->len) >
fw->size) {
wiphy_err(wl->wiphy,
"%s: conflicting bin/hdr\n",
@@ -1915,11 +1677,11 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl)
{
bool blocked = brcms_c_check_radio_disabled(wl->wlc);
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
if (blocked)
wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy);
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
return blocked;
}
@@ -1928,7 +1690,7 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl)
*/
void brcms_msleep(struct brcms_info *wl, uint ms)
{
- UNLOCK(wl);
+ spin_unlock_bh(&wl->lock);
msleep(ms);
- LOCK(wl);
+ spin_lock_bh(&wl->lock);
}
diff --git a/drivers/staging/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
index 40e3d375ea99..177f0e44e4b6 100644
--- a/drivers/staging/brcm80211/brcmsmac/mac80211_if.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
@@ -19,24 +19,27 @@
#include <linux/timer.h>
#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+
+#include "ucode_loader.h"
+/*
+ * Starting index for 5G rates in the
+ * legacy rate table.
+ */
+#define BRCMS_LEGACY_5G_RATE_OFFSET 4
/* softmac ioctl definitions */
#define BRCMS_SET_SHORTSLOT_OVERRIDE 146
-
-/* BMAC Note: High-only driver is no longer working in softirq context as it needs to block and
- * sleep so perimeter lock has to be a semaphore instead of spinlock. This requires timers to be
- * submitted to workqueue instead of being on kernel timer
- */
struct brcms_timer {
- struct timer_list timer;
+ struct delayed_work dly_wrk;
struct brcms_info *wl;
- void (*fn) (void *);
- void *arg; /* argument to fn */
+ void (*fn) (void *); /* function called upon expiration */
+ void *arg; /* fixed argument provided to called function */
uint ms;
bool periodic;
- bool set;
- struct brcms_timer *next;
+ bool set; /* indicates if timer is active */
+ struct brcms_timer *next; /* for freeing on unload */
#ifdef BCMDBG
char *name; /* Description of the timer */
#endif
@@ -57,7 +60,7 @@ struct brcms_firmware {
struct brcms_info {
struct brcms_pub *pub; /* pointer to public wlc state */
- void *wlc; /* pointer to private common os-independent data */
+ struct brcms_c_info *wlc; /* pointer to private common data */
u32 magic;
int irq;
@@ -65,9 +68,8 @@ struct brcms_info {
spinlock_t lock; /* per-device perimeter lock */
spinlock_t isr_lock; /* per-device ISR synchronization lock */
- /* bus type and regsva for unmap in brcms_free() */
- uint bcm_bustype; /* bus type */
- void *regsva; /* opaque chip registers virtual address */
+ /* regsva for unmap in brcms_free() */
+ void __iomem *regsva; /* opaque chip registers virtual address */
/* timer related fields */
atomic_t callbacks; /* # outstanding callback functions */
@@ -75,11 +77,9 @@ struct brcms_info {
struct tasklet_struct tasklet; /* dpc tasklet */
bool resched; /* dpc needs to be and is rescheduled */
-#ifdef LINUXSTA_PS
- u32 pci_psstate[16]; /* pci ps-state save/restore */
-#endif
struct brcms_firmware fw;
struct wiphy *wiphy;
+ struct brcms_ucode ucode;
};
/* misc callbacks */
@@ -92,17 +92,17 @@ extern int brcms_up(struct brcms_info *wl);
extern void brcms_down(struct brcms_info *wl);
extern void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
bool state, int prio);
-extern bool wl_alloc_dma_resources(struct brcms_info *wl, uint dmaddrwidth);
extern bool brcms_rfkill_set_hw_state(struct brcms_info *wl);
/* timer functions */
extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
void (*fn) (void *arg), void *arg,
const char *name);
-extern void brcms_free_timer(struct brcms_info *wl, struct brcms_timer *timer);
-extern void brcms_add_timer(struct brcms_info *wl, struct brcms_timer *timer,
- uint ms, int periodic);
-extern bool brcms_del_timer(struct brcms_info *wl, struct brcms_timer *timer);
+extern void brcms_free_timer(struct brcms_timer *timer);
+extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic);
+extern bool brcms_del_timer(struct brcms_timer *timer);
extern void brcms_msleep(struct brcms_info *wl, uint ms);
+extern void brcms_dpc(unsigned long data);
+extern void brcms_timer(struct brcms_timer *t);
#endif /* _BRCM_MAC80211_IF_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
new file mode 100644
index 000000000000..510e9bb52287
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -0,0 +1,8775 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/pci_ids.h>
+#include <linux/if_ether.h>
+#include <net/mac80211.h>
+#include <brcm_hw_ids.h>
+#include <aiutils.h>
+#include <chipcommon.h>
+#include "rate.h"
+#include "scb.h"
+#include "phy/phy_hal.h"
+#include "channel.h"
+#include "antsel.h"
+#include "stf.h"
+#include "ampdu.h"
+#include "mac80211_if.h"
+#include "ucode_loader.h"
+#include "main.h"
+
+/*
+ * Indication for txflowcontrol that all priority bits in
+ * TXQ_STOP_FOR_PRIOFC_MASK are to be considered.
+ */
+#define ALLPRIO -1
+
+/*
+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
+ */
+#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1)
+
+/* watchdog timer, in unit of ms */
+#define TIMER_INTERVAL_WATCHDOG 1000
+/* radio monitor timer, in unit of ms */
+#define TIMER_INTERVAL_RADIOCHK 800
+
+/* Max MPC timeout, in unit of watchdog */
+#ifndef BRCMS_MPC_MAX_DELAYCNT
+#define BRCMS_MPC_MAX_DELAYCNT 10
+#endif
+
+/* Min MPC timeout, in unit of watchdog */
+#define BRCMS_MPC_MIN_DELAYCNT 1
+#define BRCMS_MPC_THRESHOLD 3 /* MPC count threshold level */
+
+/* beacon interval, in unit of 1024TU */
+#define BEACON_INTERVAL_DEFAULT 100
+/* DTIM interval, in unit of beacon interval */
+#define DTIM_INTERVAL_DEFAULT 3
+
+/* Scale down delays to accommodate QT slow speed */
+/* beacon interval, in unit of 1024TU */
+#define BEACON_INTERVAL_DEF_QT 20
+/* DTIM interval, in unit of beacon interval */
+#define DTIM_INTERVAL_DEF_QT 1
+
+#define TBTT_ALIGN_LEEWAY_US 100 /* min leeway before first TBTT in us */
+
+/* n-mode support capability */
+/* 2x2 includes both 1x1 & 2x2 devices
+ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
+ * control it independently
+ */
+#define WL_11N_2x2 1
+#define WL_11N_3x3 3
+#define WL_11N_4x4 4
+
+/* define 11n feature disable flags */
+#define WLFEATURE_DISABLE_11N 0x00000001
+#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002
+#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004
+#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008
+#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010
+#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020
+#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040
+#define WLFEATURE_DISABLE_11N_GF 0x00000080
+
+#define EDCF_ACI_MASK 0x60
+#define EDCF_ACI_SHIFT 5
+#define EDCF_ECWMIN_MASK 0x0f
+#define EDCF_ECWMAX_SHIFT 4
+#define EDCF_AIFSN_MASK 0x0f
+#define EDCF_AIFSN_MAX 15
+#define EDCF_ECWMAX_MASK 0xf0
+
+#define EDCF_AC_BE_TXOP_STA 0x0000
+#define EDCF_AC_BK_TXOP_STA 0x0000
+#define EDCF_AC_VO_ACI_STA 0x62
+#define EDCF_AC_VO_ECW_STA 0x32
+#define EDCF_AC_VI_ACI_STA 0x42
+#define EDCF_AC_VI_ECW_STA 0x43
+#define EDCF_AC_BK_ECW_STA 0xA4
+#define EDCF_AC_VI_TXOP_STA 0x005e
+#define EDCF_AC_VO_TXOP_STA 0x002f
+#define EDCF_AC_BE_ACI_STA 0x03
+#define EDCF_AC_BE_ECW_STA 0xA4
+#define EDCF_AC_BK_ACI_STA 0x27
+#define EDCF_AC_VO_TXOP_AP 0x002f
+
+#define EDCF_TXOP2USEC(txop) ((txop) << 5)
+#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1)
+
+#define APHY_SYMBOL_TIME 4
+#define APHY_PREAMBLE_TIME 16
+#define APHY_SIGNAL_TIME 4
+#define APHY_SIFS_TIME 16
+#define APHY_SERVICE_NBITS 16
+#define APHY_TAIL_NBITS 6
+#define BPHY_SIFS_TIME 10
+#define BPHY_PLCP_SHORT_TIME 96
+
+#define PREN_PREAMBLE 24
+#define PREN_MM_EXT 12
+#define PREN_PREAMBLE_EXT 4
+
+#define DOT11_MAC_HDR_LEN 24
+#define DOT11_ACK_LEN 10
+#define DOT11_BA_LEN 4
+#define DOT11_OFDM_SIGNAL_EXTENSION 6
+#define DOT11_MIN_FRAG_LEN 256
+#define DOT11_RTS_LEN 16
+#define DOT11_CTS_LEN 10
+#define DOT11_BA_BITMAP_LEN 128
+#define DOT11_MIN_BEACON_PERIOD 1
+#define DOT11_MAX_BEACON_PERIOD 0xFFFF
+#define DOT11_MAXNUMFRAGS 16
+#define DOT11_MAX_FRAG_LEN 2346
+
+#define BPHY_PLCP_TIME 192
+#define RIFS_11N_TIME 2
+
+#define WME_VER 1
+#define WME_SUBTYPE_PARAM_IE 1
+#define WME_TYPE 2
+#define WME_OUI "\x00\x50\xf2"
+
+#define AC_BE 0
+#define AC_BK 1
+#define AC_VI 2
+#define AC_VO 3
+
+#define BCN_TMPL_LEN 512 /* length of the BCN template area */
+
+/* brcms_bss_info flag bit values */
+#define BRCMS_BSS_HT 0x0020 /* BSS is HT (MIMO) capable */
+
+/* Flags used in brcms_c_txq_info.stopped */
+/* per prio flow control bits */
+#define TXQ_STOP_FOR_PRIOFC_MASK 0x000000FF
+/* stop txq enqueue for packet drain */
+#define TXQ_STOP_FOR_PKT_DRAIN 0x00000100
+/* stop txq enqueue for ampdu flow control */
+#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL 0x00000200
+
+#define BRCMS_HWRXOFF 38 /* chip rx buffer offset */
+
+/* Find basic rate for a given rate */
+static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec)
+{
+ if (is_mcs_rate(rspec))
+ return wlc->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK]
+ .leg_ofdm];
+ return wlc->band->basic_rate[rspec & RSPEC_RATE_MASK];
+}
+
+static u16 frametype(u32 rspec, u8 mimoframe)
+{
+ if (is_mcs_rate(rspec))
+ return mimoframe;
+ return is_cck_rate(rspec) ? FT_CCK : FT_OFDM;
+}
+
+/* rfdisable delay timer 500 ms, runs of ALP clock */
+#define RFDISABLE_DEFAULT 10000000
+
+#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 */
+
+/* The BSS is generating beacons in HW */
+#define BRCMS_BSSCFG_HW_BCN 0x20
+
+#define SYNTHPU_DLY_APHY_US 3700 /* a phy synthpu_dly time in us */
+#define SYNTHPU_DLY_BPHY_US 1050 /* b/g phy synthpu_dly time in us */
+#define SYNTHPU_DLY_NPHY_US 2048 /* n phy REV3 synthpu_dly time in us */
+#define SYNTHPU_DLY_LPPHY_US 300 /* lpphy synthpu_dly time in us */
+
+#define SYNTHPU_DLY_PHY_US_QT 100 /* QT synthpu_dly time in us */
+
+#define ANTCNT 10 /* vanilla M_MAX_ANTCNT value */
+
+/* Per-AC retry limit register definitions; uses defs.h bitfield macros */
+#define EDCF_SHORT_S 0
+#define EDCF_SFB_S 4
+#define EDCF_LONG_S 8
+#define EDCF_LFB_S 12
+#define EDCF_SHORT_M BITFIELD_MASK(4)
+#define EDCF_SFB_M BITFIELD_MASK(4)
+#define EDCF_LONG_M BITFIELD_MASK(4)
+#define EDCF_LFB_M BITFIELD_MASK(4)
+
+#define RETRY_SHORT_DEF 7 /* Default Short retry Limit */
+#define RETRY_SHORT_MAX 255 /* Maximum Short retry Limit */
+#define RETRY_LONG_DEF 4 /* Default Long retry count */
+#define RETRY_SHORT_FB 3 /* Short count for fallback rate */
+#define RETRY_LONG_FB 2 /* Long count for fallback rate */
+
+#define APHY_CWMIN 15
+#define PHY_CWMAX 1023
+
+#define EDCF_AIFSN_MIN 1
+
+#define FRAGNUM_MASK 0xF
+
+#define APHY_SLOT_TIME 9
+#define BPHY_SLOT_TIME 20
+
+#define WL_SPURAVOID_OFF 0
+#define WL_SPURAVOID_ON1 1
+#define WL_SPURAVOID_ON2 2
+
+/* invalid core flags, use the saved coreflags */
+#define BRCMS_USE_COREFLAGS 0xffffffff
+
+/* values for PLCPHdr_override */
+#define BRCMS_PLCP_AUTO -1
+#define BRCMS_PLCP_SHORT 0
+#define BRCMS_PLCP_LONG 1
+
+/* values for g_protection_override and n_protection_override */
+#define BRCMS_PROTECTION_AUTO -1
+#define BRCMS_PROTECTION_OFF 0
+#define BRCMS_PROTECTION_ON 1
+#define BRCMS_PROTECTION_MMHDR_ONLY 2
+#define BRCMS_PROTECTION_CTS_ONLY 3
+
+/* values for g_protection_control and n_protection_control */
+#define BRCMS_PROTECTION_CTL_OFF 0
+#define BRCMS_PROTECTION_CTL_LOCAL 1
+#define BRCMS_PROTECTION_CTL_OVERLAP 2
+
+/* values for n_protection */
+#define BRCMS_N_PROTECTION_OFF 0
+#define BRCMS_N_PROTECTION_OPTIONAL 1
+#define BRCMS_N_PROTECTION_20IN40 2
+#define BRCMS_N_PROTECTION_MIXEDMODE 3
+
+/* values for band specific 40MHz capabilities */
+#define BRCMS_N_BW_20ALL 0
+#define BRCMS_N_BW_40ALL 1
+#define BRCMS_N_BW_20IN2G_40IN5G 2
+
+/* bitflags for SGI support (sgi_rx iovar) */
+#define BRCMS_N_SGI_20 0x01
+#define BRCMS_N_SGI_40 0x02
+
+/* defines used by the nrate iovar */
+/* MSC in use,indicates b0-6 holds an mcs */
+#define NRATE_MCS_INUSE 0x00000080
+/* rate/mcs value */
+#define NRATE_RATE_MASK 0x0000007f
+/* stf mode mask: siso, cdd, stbc, sdm */
+#define NRATE_STF_MASK 0x0000ff00
+/* stf mode shift */
+#define NRATE_STF_SHIFT 8
+/* bit indicates override both rate & mode */
+#define NRATE_OVERRIDE 0x80000000
+/* bit indicate to override mcs only */
+#define NRATE_OVERRIDE_MCS_ONLY 0x40000000
+#define NRATE_SGI_MASK 0x00800000 /* sgi mode */
+#define NRATE_SGI_SHIFT 23 /* sgi mode */
+#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */
+#define NRATE_LDPC_SHIFT 22 /* ldpc shift */
+
+#define NRATE_STF_SISO 0 /* stf mode SISO */
+#define NRATE_STF_CDD 1 /* stf mode CDD */
+#define NRATE_STF_STBC 2 /* stf mode STBC */
+#define NRATE_STF_SDM 3 /* stf mode SDM */
+
+#define MAX_DMA_SEGS 4
+
+/* Max # of entries in Tx FIFO based on 4kb page size */
+#define NTXD 256
+/* Max # of entries in Rx FIFO based on 4kb page size */
+#define NRXD 256
+
+/* try to keep this # rbufs posted to the chip */
+#define NRXBUFPOST 32
+
+/* data msg txq hiwat mark */
+#define BRCMS_DATAHIWAT 50
+
+/* bounded rx loops */
+#define RXBND 8 /* max # frames to process in brcms_c_recv() */
+#define TXSBND 8 /* max # tx status to process in wlc_txstatus() */
+
+/*
+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
+ */
+#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1)
+
+/* brcmu_format_flags() bit description structure */
+struct brcms_c_bit_desc {
+ u32 bit;
+ const char *name;
+};
+
+/*
+ * The following table lists the buffer memory allocated to xmt fifos in HW.
+ * the size is in units of 256bytes(one block), total size is HW dependent
+ * ucode has default fifo partition, sw can overwrite if necessary
+ *
+ * This is documented in twiki under the topic UcodeTxFifo. Please ensure
+ * the twiki is updated before making changes.
+ */
+
+/* Starting corerev for the fifo size table */
+#define XMTFIFOTBL_STARTREV 20
+
+struct d11init {
+ __le16 addr;
+ __le16 size;
+ __le32 value;
+};
+
+struct edcf_acparam {
+ u8 ACI;
+ u8 ECW;
+ 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(BCMDBG)
+ LOG_ERROR_VAL;
+#else
+ 0;
+#endif /* BCMDBG */
+
+/* TX FIFO number to WME/802.1E Access Category */
+static const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE };
+
+/* WME/802.1E Access Category to TX FIFO number */
+static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 };
+
+/* 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 20: 5120, 49152, 49152, 5376, 4352, 1280 */
+ {20, 192, 192, 21, 17, 5},
+ /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
+ {9, 58, 22, 14, 14, 5},
+ /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
+ {20, 192, 192, 21, 17, 5},
+ /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
+ {20, 192, 192, 21, 17, 5},
+ /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
+ {9, 58, 22, 14, 14, 5},
+};
+
+static const u8 acbitmap2maxprio[] = {
+ PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK,
+ PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI,
+ PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO,
+ PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO
+};
+
+#ifdef BCMDBG
+static const char * const fifo_names[] = {
+ "AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
+#else
+static const char fifo_names[6][0];
+#endif
+
+#ifdef BCMDBG
+/* pointer to most recently allocated wl/wlc */
+static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
+#endif
+
+/* currently the best mechanism for determining SIFS is the band in use */
+static u16 get_sifs(struct brcms_band *band)
+{
+ return band->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME :
+ BPHY_SIFS_TIME;
+}
+
+/*
+ * Detect Card removed.
+ * Even checking an sbconfig register read will not false trigger when the core
+ * is in reset it breaks CF address mechanism. Accessing gphy phyversion will
+ * cause SB error if aphy is in reset on 4306B0-DB. Need a simple accessible
+ * reg with fixed 0/1 pattern (some platforms return all 0).
+ * If clocks are present, call the sb routine which will figure out if the
+ * device is removed.
+ */
+static bool brcms_deviceremoved(struct brcms_c_info *wlc)
+{
+ if (!wlc->hw->clk)
+ return ai_deviceremoved(wlc->hw->sih);
+ return (R_REG(&wlc->hw->regs->maccontrol) &
+ (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN;
+}
+
+/* sum the individual fifo tx pending packet counts */
+static s16 brcms_txpktpendtot(struct brcms_c_info *wlc)
+{
+ return wlc->core->txpktpend[0] + wlc->core->txpktpend[1] +
+ wlc->core->txpktpend[2] + wlc->core->txpktpend[3];
+}
+
+static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc)
+{
+ return wlc->pub->_nbands > 1 && !wlc->bandlocked;
+}
+
+static int brcms_chspec_bw(u16 chanspec)
+{
+ if (CHSPEC_IS40(chanspec))
+ return BRCMS_40_MHZ;
+ if (CHSPEC_IS20(chanspec))
+ return BRCMS_20_MHZ;
+
+ return BRCMS_10_MHZ;
+}
+
+/*
+ * return true if Minimum Power Consumption should
+ * be entered, false otherwise
+ */
+static bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc)
+{
+ return false;
+}
+
+static bool brcms_c_ismpc(struct brcms_c_info *wlc)
+{
+ return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc));
+}
+
+static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg)
+{
+ if (cfg == NULL)
+ return;
+
+ kfree(cfg->current_bss);
+ kfree(cfg);
+}
+
+static void brcms_c_detach_mfree(struct brcms_c_info *wlc)
+{
+ if (wlc == NULL)
+ return;
+
+ brcms_c_bsscfg_mfree(wlc->bsscfg);
+ kfree(wlc->pub);
+ kfree(wlc->modulecb);
+ kfree(wlc->default_bss);
+ kfree(wlc->protection);
+ kfree(wlc->stf);
+ kfree(wlc->bandstate[0]);
+ kfree(wlc->corestate->macstat_snapshot);
+ kfree(wlc->corestate);
+ kfree(wlc->hw->bandstate[0]);
+ kfree(wlc->hw);
+
+ /* free the wlc */
+ kfree(wlc);
+ wlc = NULL;
+}
+
+static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit)
+{
+ struct brcms_bss_cfg *cfg;
+
+ cfg = kzalloc(sizeof(struct brcms_bss_cfg), GFP_ATOMIC);
+ if (cfg == NULL)
+ goto fail;
+
+ cfg->current_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
+ if (cfg->current_bss == NULL)
+ goto fail;
+
+ return cfg;
+
+ fail:
+ brcms_c_bsscfg_mfree(cfg);
+ return NULL;
+}
+
+static struct brcms_c_info *
+brcms_c_attach_malloc(uint unit, uint *err, uint devid)
+{
+ struct brcms_c_info *wlc;
+
+ wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC);
+ if (wlc == NULL) {
+ *err = 1002;
+ goto fail;
+ }
+
+ /* allocate struct brcms_c_pub state structure */
+ wlc->pub = kzalloc(sizeof(struct brcms_pub), GFP_ATOMIC);
+ if (wlc->pub == NULL) {
+ *err = 1003;
+ goto fail;
+ }
+ wlc->pub->wlc = wlc;
+
+ /* allocate struct brcms_hardware state structure */
+
+ wlc->hw = kzalloc(sizeof(struct brcms_hardware), GFP_ATOMIC);
+ if (wlc->hw == NULL) {
+ *err = 1005;
+ goto fail;
+ }
+ wlc->hw->wlc = wlc;
+
+ wlc->hw->bandstate[0] =
+ kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC);
+ if (wlc->hw->bandstate[0] == NULL) {
+ *err = 1006;
+ goto fail;
+ } else {
+ int i;
+
+ for (i = 1; i < MAXBANDS; i++)
+ wlc->hw->bandstate[i] = (struct brcms_hw_band *)
+ ((unsigned long)wlc->hw->bandstate[0] +
+ (sizeof(struct brcms_hw_band) * i));
+ }
+
+ wlc->modulecb =
+ kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC);
+ if (wlc->modulecb == NULL) {
+ *err = 1009;
+ goto fail;
+ }
+
+ wlc->default_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
+ if (wlc->default_bss == NULL) {
+ *err = 1010;
+ goto fail;
+ }
+
+ wlc->bsscfg = brcms_c_bsscfg_malloc(unit);
+ if (wlc->bsscfg == NULL) {
+ *err = 1011;
+ goto fail;
+ }
+
+ wlc->protection = kzalloc(sizeof(struct brcms_protection),
+ GFP_ATOMIC);
+ if (wlc->protection == NULL) {
+ *err = 1016;
+ goto fail;
+ }
+
+ wlc->stf = kzalloc(sizeof(struct brcms_stf), GFP_ATOMIC);
+ if (wlc->stf == NULL) {
+ *err = 1017;
+ goto fail;
+ }
+
+ wlc->bandstate[0] =
+ kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC);
+ if (wlc->bandstate[0] == NULL) {
+ *err = 1025;
+ goto fail;
+ } else {
+ int i;
+
+ for (i = 1; i < MAXBANDS; i++)
+ wlc->bandstate[i] = (struct brcms_band *)
+ ((unsigned long)wlc->bandstate[0]
+ + (sizeof(struct brcms_band)*i));
+ }
+
+ wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC);
+ if (wlc->corestate == NULL) {
+ *err = 1026;
+ goto fail;
+ }
+
+ wlc->corestate->macstat_snapshot =
+ kzalloc(sizeof(struct macstat), GFP_ATOMIC);
+ if (wlc->corestate->macstat_snapshot == NULL) {
+ *err = 1027;
+ goto fail;
+ }
+
+ return wlc;
+
+ fail:
+ brcms_c_detach_mfree(wlc);
+ return NULL;
+}
+
+/*
+ * Update the slot timing for standard 11b/g (20us slots)
+ * or shortslot 11g (9us slots)
+ * The PSM needs to be suspended for this call.
+ */
+static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
+ bool shortslot)
+{
+ struct d11regs __iomem *regs;
+
+ regs = wlc_hw->regs;
+
+ if (shortslot) {
+ /* 11g short slot: 11a timing */
+ W_REG(&regs->ifs_slot, 0x0207); /* APHY_SLOT_TIME */
+ brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
+ } else {
+ /* 11g long slot: 11b timing */
+ W_REG(&regs->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */
+ brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
+ }
+}
+
+/*
+ * calculate frame duration of a given rate and length, return
+ * time in usec unit
+ */
+uint
+brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
+ u8 preamble_type, uint mac_len)
+{
+ uint nsyms, dur = 0, Ndps, kNdps;
+ uint rate = rspec2rate(ratespec);
+
+ if (rate == 0) {
+ wiphy_err(wlc->wiphy, "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);
+
+ dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+ if (preamble_type == BRCMS_MM_PREAMBLE)
+ dur += PREN_MM_EXT;
+ /* 1000Ndbps = kbps * 4 */
+ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+ rspec_issgi(ratespec)) * 4;
+
+ if (rspec_stc(ratespec) == 0)
+ nsyms =
+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+ APHY_TAIL_NBITS) * 1000, kNdps);
+ else
+ /* STBC needs to have even number of symbols */
+ nsyms =
+ 2 *
+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+ APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+
+ dur += APHY_SYMBOL_TIME * nsyms;
+ if (wlc->band->bandtype == BRCM_BAND_2G)
+ dur += DOT11_OFDM_SIGNAL_EXTENSION;
+ } else if (is_ofdm_rate(rate)) {
+ dur = APHY_PREAMBLE_TIME;
+ dur += APHY_SIGNAL_TIME;
+ /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+ Ndps = rate * 2;
+ /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+ nsyms =
+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
+ Ndps);
+ dur += APHY_SYMBOL_TIME * nsyms;
+ if (wlc->band->bandtype == BRCM_BAND_2G)
+ dur += DOT11_OFDM_SIGNAL_EXTENSION;
+ } else {
+ /*
+ * calc # bits * 2 so factor of 2 in rate (1/2 mbps)
+ * will divide out
+ */
+ mac_len = mac_len * 8 * 2;
+ /* calc ceiling of bits/rate = microseconds of air time */
+ dur = (mac_len + rate - 1) / rate;
+ if (preamble_type & BRCMS_SHORT_PREAMBLE)
+ dur += BPHY_PLCP_SHORT_TIME;
+ else
+ dur += BPHY_PLCP_TIME;
+ }
+ return dur;
+}
+
+static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
+ const struct d11init *inits)
+{
+ int i;
+ u8 __iomem *base;
+ u8 __iomem *addr;
+ u16 size;
+ u32 value;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ base = (u8 __iomem *)wlc_hw->regs;
+
+ for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) {
+ size = le16_to_cpu(inits[i].size);
+ addr = base + le16_to_cpu(inits[i].addr);
+ value = le32_to_cpu(inits[i].value);
+ if (size == 2)
+ W_REG((u16 __iomem *)addr, value);
+ else if (size == 4)
+ W_REG((u32 __iomem *)addr, value);
+ else
+ break;
+ }
+}
+
+static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs)
+{
+ u8 idx;
+ u16 addr[] = {
+ M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
+ M_HOST_FLAGS5
+ };
+
+ for (idx = 0; idx < MHFMAX; idx++)
+ brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]);
+}
+
+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 (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,
+ wlc_hw->corerev);
+ } else {
+ if (D11REV_IS(wlc_hw->corerev, 24)) {
+ if (BRCMS_ISLCNPHY(wlc_hw->band))
+ 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);
+ } else {
+ wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
+ __func__, wlc_hw->unit, wlc_hw->corerev);
+ }
+ }
+}
+
+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);
+
+ wlc_hw->phyclk = clk;
+
+ if (OFF == clk) { /* clear gmode bit, put phy into reset */
+
+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
+ (SICF_PRST | SICF_FGC));
+ udelay(1);
+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
+ udelay(1);
+
+ } else { /* take phy out of reset */
+
+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
+ udelay(1);
+ ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
+ udelay(1);
+
+ }
+}
+
+/* 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);
+
+ wlc_hw->band = wlc_hw->bandstate[bandunit];
+
+ /*
+ * BMAC_NOTE:
+ * until we eliminate need for wlc->band refs in low level code
+ */
+ wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
+
+ /* set gmode core flag */
+ if (wlc_hw->sbclk && !wlc_hw->noreset)
+ ai_core_cflags(wlc_hw->sih, SICF_GMODE,
+ ((bandunit == 0) ? SICF_GMODE : 0));
+}
+
+/* switch to new band but leave it inactive */
+static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ u32 macintmask;
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
+
+ /* disable interrupts */
+ macintmask = brcms_intrsoff(wlc->wl);
+
+ /* radio off */
+ wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
+
+ brcms_b_core_phy_clk(wlc_hw, OFF);
+
+ brcms_c_setxband(wlc_hw, bandunit);
+
+ return macintmask;
+}
+
+/* process an individual struct tx_status */
+static bool
+brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
+{
+ struct sk_buff *p;
+ uint queue;
+ struct d11txh *txh;
+ struct scb *scb = NULL;
+ bool free_pdu;
+ int tx_rts, tx_frame_count, tx_rts_count;
+ uint totlen, supr_status;
+ bool lastframe;
+ struct ieee80211_hdr *h;
+ u16 mcl;
+ struct ieee80211_tx_info *tx_info;
+ struct ieee80211_tx_rate *txrate;
+ int i;
+
+ /* discard intermediate indications for ucode with one legitimate case:
+ * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange,
+ * but the subsequent tx of DATA failed. so it will start rts/cts
+ * from the beginning (resetting the rts transmission count)
+ */
+ if (!(txs->status & TX_STATUS_AMPDU)
+ && (txs->status & TX_STATUS_INTERMEDIATE)) {
+ wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
+ __func__);
+ return false;
+ }
+
+ queue = txs->frameid & TXFID_QUEUE_MASK;
+ if (queue >= NFIFO) {
+ p = NULL;
+ goto fatal;
+ }
+
+ p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
+ if (p == NULL)
+ goto fatal;
+
+ 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->frameid != le16_to_cpu(txh->TxFrameID))
+ goto fatal;
+ tx_info = IEEE80211_SKB_CB(p);
+ h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
+
+ if (tx_info->control.sta)
+ scb = &wlc->pri_scb;
+
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+ brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
+ return false;
+ }
+
+ 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));
+
+ tx_rts = le16_to_cpu(txh->MacTxControlLow) & TXC_SENDRTS;
+ tx_frame_count =
+ (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT;
+ tx_rts_count =
+ (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT;
+
+ lastframe = !ieee80211_has_morefrags(h->frame_control);
+
+ if (!lastframe) {
+ wiphy_err(wlc->wiphy, "Not last frame!\n");
+ } else {
+ /*
+ * Set information to be consumed by Minstrel ht.
+ *
+ * The "fallback limit" is the number of tx attempts a given
+ * MPDU is sent at the "primary" rate. Tx attempts beyond that
+ * limit are sent at the "secondary" rate.
+ * A 'short frame' does not exceed RTS treshold.
+ */
+ u16 sfbl, /* Short Frame Rate Fallback Limit */
+ lfbl, /* Long Frame Rate Fallback Limit */
+ fbl;
+
+ if (queue < AC_COUNT) {
+ sfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]],
+ EDCF_SFB);
+ lfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]],
+ EDCF_LFB);
+ } else {
+ sfbl = wlc->SFBL;
+ lfbl = wlc->LFBL;
+ }
+
+ txrate = tx_info->status.rates;
+ if (txrate[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+ fbl = lfbl;
+ else
+ fbl = sfbl;
+
+ ieee80211_tx_info_clear_status(tx_info);
+
+ if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) {
+ /*
+ * rate selection requested a fallback rate
+ * and we used it
+ */
+ txrate[0].count = fbl;
+ txrate[1].count = tx_frame_count - fbl;
+ } else {
+ /*
+ * rate selection did not request fallback rate, or
+ * we didn't need it
+ */
+ txrate[0].count = tx_frame_count;
+ /*
+ * rc80211_minstrel.c:minstrel_tx_status() expects
+ * unused rates to be marked with idx = -1
+ */
+ txrate[1].idx = -1;
+ txrate[1].count = 0;
+ }
+
+ /* clear the rest of the rates */
+ for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
+ txrate[i].idx = -1;
+ txrate[i].count = 0;
+ }
+
+ if (txs->status & TX_STATUS_ACK_RCV)
+ tx_info->flags |= IEEE80211_TX_STAT_ACK;
+ }
+
+ totlen = brcmu_pkttotlen(p);
+ free_pdu = true;
+
+ brcms_c_txfifo_complete(wlc, queue, 1);
+
+ if (lastframe) {
+ p->next = NULL;
+ p->prev = NULL;
+ /* 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__);
+ }
+
+ return false;
+
+ fatal:
+ if (p)
+ brcmu_pkt_buf_free_skb(p);
+
+ return true;
+
+}
+
+/* process tx completion events in BMAC
+ * Return true if more tx status need to be processed. false otherwise.
+ */
+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 d11regs __iomem *regs;
+ struct tx_status txstatus, *txs;
+ u32 s1, s2;
+ uint n = 0;
+ /*
+ * Param 'max_tx_num' indicates max. # tx status to process before
+ * break out.
+ */
+ uint max_tx_num = bound ? TXSBND : -1;
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ txs = &txstatus;
+ regs = wlc_hw->regs;
+ *fatal = false;
+ while (!(*fatal)
+ && (s1 = R_REG(&regs->frmtxstatus)) & TXS_V) {
+
+ if (s1 == 0xffffffff) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
+ wlc_hw->unit, __func__);
+ return morepending;
+ }
+
+ s2 = R_REG(&regs->frmtxstatus2);
+
+ txs->status = s1 & TXS_STATUS_MASK;
+ txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
+ txs->sequence = s2 & TXS_SEQ_MASK;
+ txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
+ txs->lasttxtime = 0;
+
+ *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs);
+
+ /* !give others some time to run! */
+ if (++n >= max_tx_num)
+ break;
+ }
+
+ if (*fatal)
+ return 0;
+
+ if (n >= max_tx_num)
+ morepending = true;
+
+ if (!pktq_empty(&wlc->pkt_queue->q))
+ brcms_c_send_q(wlc);
+
+ return morepending;
+}
+
+static void brcms_c_tbtt(struct brcms_c_info *wlc)
+{
+ if (!wlc->bsscfg->BSS)
+ /*
+ * DirFrmQ is now valid...defer setting until end
+ * of ATIM window
+ */
+ wlc->qvalid |= MCMD_DIRFRMQVAL;
+}
+
+/* set initial host flags value */
+static void
+brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+
+ memset(mhfs, 0, MHFMAX * sizeof(u16));
+
+ mhfs[MHF2] |= mhf2_init;
+
+ /* prohibit use of slowclock on multifunction boards */
+ if (wlc_hw->boardflags & BFL_NOPLLDOWN)
+ mhfs[MHF1] |= MHF1_FORCEFASTCLK;
+
+ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
+ mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
+ mhfs[MHF1] |= MHF1_IQSWAP_WAR;
+ }
+}
+
+static struct dma64regs __iomem *
+dmareg(struct brcms_hardware *hw, uint direction, uint fifonum)
+{
+ if (direction == DMA_TX)
+ return &(hw->regs->fifo64regs[fifonum].dmaxmt);
+ return &(hw->regs->fifo64regs[fifonum].dmarcv);
+}
+
+static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
+{
+ uint i;
+ char name[8];
+ /*
+ * ucode host flag 2 needed for pio mode, independent of band and fifo
+ */
+ 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);
+
+ if (wlc_hw->di[0] == NULL) { /* Init FIFOs */
+ int dma_attach_err = 0;
+
+ /*
+ * FIFO 0
+ * 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,
+ (wme ? dmareg(wlc_hw, DMA_TX, 0) :
+ NULL), dmareg(wlc_hw, DMA_RX, 0),
+ (wme ? NTXD : 0), NRXD,
+ RXBUFSZ, -1, NRXBUFPOST,
+ BRCMS_HWRXOFF, &brcm_msg_level);
+ dma_attach_err |= (NULL == wlc_hw->di[0]);
+
+ /*
+ * FIFO 1
+ * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
+ * (legacy) TX_DATA_FIFO (TX data packets)
+ * RX: UNUSED
+ */
+ wlc_hw->di[1] = dma_attach(name, wlc_hw->sih,
+ dmareg(wlc_hw, DMA_TX, 1), NULL,
+ NTXD, 0, 0, -1, 0, 0,
+ &brcm_msg_level);
+ dma_attach_err |= (NULL == wlc_hw->di[1]);
+
+ /*
+ * FIFO 2
+ * TX: TX_AC_VI_FIFO (TX AC Video data packets)
+ * RX: UNUSED
+ */
+ wlc_hw->di[2] = dma_attach(name, wlc_hw->sih,
+ dmareg(wlc_hw, DMA_TX, 2), NULL,
+ NTXD, 0, 0, -1, 0, 0,
+ &brcm_msg_level);
+ 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,
+ dmareg(wlc_hw, DMA_TX, 3),
+ NULL, NTXD, 0, 0, -1,
+ 0, 0, &brcm_msg_level);
+ 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);
+ return false;
+ }
+
+ /* get pointer to dma engine tx flow control variable */
+ for (i = 0; i < NFIFO; i++)
+ if (wlc_hw->di[i])
+ wlc_hw->txavail[i] =
+ (uint *) dma_getvar(wlc_hw->di[i],
+ "&txavail");
+ }
+
+ /* initial ucode host flags */
+ brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
+
+ return true;
+}
+
+static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw)
+{
+ uint j;
+
+ for (j = 0; j < NFIFO; j++) {
+ if (wlc_hw->di[j]) {
+ dma_detach(wlc_hw->di[j]);
+ wlc_hw->di[j] = NULL;
+ }
+ }
+}
+
+/*
+ * Initialize brcms_c_info default values ...
+ * may get overrides later in this function
+ * BMAC_NOTES, move low out and resolve the dangling ones
+ */
+static void brcms_b_info_init(struct brcms_hardware *wlc_hw)
+{
+ struct brcms_c_info *wlc = wlc_hw->wlc;
+
+ /* set default sw macintmask value */
+ wlc->defmacintmask = DEF_MACINTMASK;
+
+ /* various 802.11g modes */
+ wlc_hw->shortslot = false;
+
+ wlc_hw->SFBL = RETRY_SHORT_FB;
+ wlc_hw->LFBL = RETRY_LONG_FB;
+
+ /* default mac retry limits */
+ wlc_hw->SRL = RETRY_SHORT_DEF;
+ wlc_hw->LRL = RETRY_LONG_DEF;
+ wlc_hw->chanspec = ch20mhz_chspec(1);
+}
+
+static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw)
+{
+ /* delay before first read of ucode state */
+ udelay(40);
+
+ /* wait until ucode is no longer asleep */
+ SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) ==
+ DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
+}
+
+/* control chip clock to save power, enable dynamic clock or force fast clock */
+static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
+{
+ if (wlc_hw->sih->cccaps & CC_CAP_PMU) {
+ /* new chips with PMU, CCS_FORCEHT will distribute the HT clock
+ * on backplane, but mac core will still run on ALP(not HT) when
+ * it enters powersave mode, which means the FCA bit may not be
+ * set. Should wakeup mac if driver wants it to run on HT.
+ */
+
+ if (wlc_hw->clk) {
+ if (mode == CLK_FAST) {
+ OR_REG(&wlc_hw->regs->clk_ctl_st,
+ CCS_FORCEHT);
+
+ udelay(64);
+
+ SPINWAIT(((R_REG
+ (&wlc_hw->regs->
+ clk_ctl_st) & CCS_HTAVAIL) == 0),
+ PMU_MAX_TRANSITION_DLY);
+ WARN_ON(!(R_REG
+ (&wlc_hw->regs->
+ clk_ctl_st) & CCS_HTAVAIL));
+ } else {
+ if ((wlc_hw->sih->pmurev == 0) &&
+ (R_REG
+ (&wlc_hw->regs->
+ clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
+ SPINWAIT(((R_REG
+ (&wlc_hw->regs->
+ clk_ctl_st) & CCS_HTAVAIL)
+ == 0),
+ PMU_MAX_TRANSITION_DLY);
+ AND_REG(&wlc_hw->regs->clk_ctl_st,
+ ~CCS_FORCEHT);
+ }
+ }
+ wlc_hw->forcefastclk = (mode == CLK_FAST);
+ } else {
+
+ /* old chips w/o PMU, force HT through cc,
+ * then use FCA to verify mac is running fast clock
+ */
+
+ wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode);
+
+ /* check fast clock is available (if core is not in reset) */
+ if (wlc_hw->forcefastclk && wlc_hw->clk)
+ WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) &
+ SISF_FCLKA));
+
+ /*
+ * keep the ucode wake bit on if forcefastclk is on since we
+ * do not want ucode to put us back to slow clock when it dozes
+ * for PM mode. Code below matches the wake override bit with
+ * current forcefastclk state. Only setting bit in wake_override
+ * instead of waking ucode immediately since old code had this
+ * behavior. Older code set wlc->forcefastclk but only had the
+ * wake happen if the wakup_ucode work (protected by an up
+ * check) was executed just below.
+ */
+ if (wlc_hw->forcefastclk)
+ mboolset(wlc_hw->wake_override,
+ BRCMS_WAKE_OVERRIDE_FORCEFAST);
+ else
+ mboolclr(wlc_hw->wake_override,
+ BRCMS_WAKE_OVERRIDE_FORCEFAST);
+ }
+}
+
+/* set or clear ucode host flag bits
+ * it has an optimization for no-change write
+ * it only writes through shared memory when the core has clock;
+ * pre-CLK changes should use wlc_write_mhf to get around the optimization
+ *
+ *
+ * bands values are: BRCM_BAND_AUTO <--- Current band only
+ * BRCM_BAND_5G <--- 5G band only
+ * BRCM_BAND_2G <--- 2G band only
+ * BRCM_BAND_ALL <--- All bands
+ */
+void
+brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val,
+ int bands)
+{
+ u16 save;
+ u16 addr[MHFMAX] = {
+ M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
+ M_HOST_FLAGS5
+ };
+ struct brcms_hw_band *band;
+
+ if ((val & ~mask) || idx >= MHFMAX)
+ return; /* error condition */
+
+ switch (bands) {
+ /* Current band only or all bands,
+ * then set the band to current band
+ */
+ case BRCM_BAND_AUTO:
+ case BRCM_BAND_ALL:
+ band = wlc_hw->band;
+ break;
+ case BRCM_BAND_5G:
+ band = wlc_hw->bandstate[BAND_5G_INDEX];
+ break;
+ case BRCM_BAND_2G:
+ band = wlc_hw->bandstate[BAND_2G_INDEX];
+ break;
+ default:
+ band = NULL; /* error condition */
+ }
+
+ if (band) {
+ save = band->mhfs[idx];
+ band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
+
+ /* optimization: only write through if changed, and
+ * changed band is the current band
+ */
+ if (wlc_hw->clk && (band->mhfs[idx] != save)
+ && (band == wlc_hw->band))
+ brcms_b_write_shm(wlc_hw, addr[idx],
+ (u16) band->mhfs[idx]);
+ }
+
+ if (bands == BRCM_BAND_ALL) {
+ wlc_hw->bandstate[0]->mhfs[idx] =
+ (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
+ wlc_hw->bandstate[1]->mhfs[idx] =
+ (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
+ }
+}
+
+/* set the maccontrol register to desired reset state and
+ * initialize the sw cache of the register
+ */
+static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw)
+{
+ /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
+ wlc_hw->maccontrol = 0;
+ wlc_hw->suspended_fifos = 0;
+ wlc_hw->wake_override = 0;
+ wlc_hw->mute_override = 0;
+ brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
+}
+
+/*
+ * write the software state of maccontrol and
+ * overrides to the maccontrol register
+ */
+static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw)
+{
+ u32 maccontrol = wlc_hw->maccontrol;
+
+ /* OR in the wake bit if overridden */
+ if (wlc_hw->wake_override)
+ maccontrol |= MCTL_WAKE;
+
+ /* set AP and INFRA bits for mute if needed */
+ if (wlc_hw->mute_override) {
+ maccontrol &= ~(MCTL_AP);
+ maccontrol |= MCTL_INFRA;
+ }
+
+ W_REG(&wlc_hw->regs->maccontrol, maccontrol);
+}
+
+/* set or clear maccontrol bits */
+void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val)
+{
+ u32 maccontrol;
+ u32 new_maccontrol;
+
+ if (val & ~mask)
+ return; /* error condition */
+ maccontrol = wlc_hw->maccontrol;
+ new_maccontrol = (maccontrol & ~mask) | val;
+
+ /* if the new maccontrol value is the same as the old, nothing to do */
+ if (new_maccontrol == maccontrol)
+ return;
+
+ /* something changed, cache the new value */
+ wlc_hw->maccontrol = new_maccontrol;
+
+ /* write the new values with overrides applied */
+ brcms_c_mctrl_write(wlc_hw);
+}
+
+void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
+ u32 override_bit)
+{
+ if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
+ mboolset(wlc_hw->wake_override, override_bit);
+ return;
+ }
+
+ mboolset(wlc_hw->wake_override, override_bit);
+
+ brcms_c_mctrl_write(wlc_hw);
+ brcms_b_wait_for_wake(wlc_hw);
+}
+
+void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
+ u32 override_bit)
+{
+ mboolclr(wlc_hw->wake_override, override_bit);
+
+ if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
+ return;
+
+ brcms_c_mctrl_write(wlc_hw);
+}
+
+/* When driver needs ucode to stop beaconing, it has to make sure that
+ * MCTL_AP is clear and MCTL_INFRA is set
+ * Mode MCTL_AP MCTL_INFRA
+ * AP 1 1
+ * STA 0 1 <--- This will ensure no beacons
+ * IBSS 0 0
+ */
+static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw)
+{
+ wlc_hw->mute_override = 1;
+
+ /* if maccontrol already has AP == 0 and INFRA == 1 without this
+ * override, then there is no change to write
+ */
+ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
+ return;
+
+ brcms_c_mctrl_write(wlc_hw);
+}
+
+/* Clear the override on AP and INFRA bits */
+static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw)
+{
+ if (wlc_hw->mute_override == 0)
+ return;
+
+ wlc_hw->mute_override = 0;
+
+ /* if maccontrol already has AP == 0 and INFRA == 1 without this
+ * override, then there is no change to write
+ */
+ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
+ return;
+
+ brcms_c_mctrl_write(wlc_hw);
+}
+
+/*
+ * Write a MAC address to the given match reg offset in the RXE match engine.
+ */
+static void
+brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
+ const u8 *addr)
+{
+ struct d11regs __iomem *regs;
+ u16 mac_l;
+ u16 mac_m;
+ u16 mac_h;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n",
+ wlc_hw->unit);
+
+ regs = wlc_hw->regs;
+ mac_l = addr[0] | (addr[1] << 8);
+ mac_m = addr[2] | (addr[3] << 8);
+ mac_h = addr[4] | (addr[5] << 8);
+
+ /* enter the MAC addr into the RXE match registers */
+ W_REG(&regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
+ W_REG(&regs->rcm_mat_data, mac_l);
+ W_REG(&regs->rcm_mat_data, mac_m);
+ W_REG(&regs->rcm_mat_data, mac_h);
+
+}
+
+void
+brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
+ void *buf)
+{
+ struct d11regs __iomem *regs;
+ u32 word;
+ __le32 word_le;
+ __be32 word_be;
+ bool be_bit;
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ regs = wlc_hw->regs;
+ W_REG(&regs->tplatewrptr, offset);
+
+ /* if MCTL_BIGEND bit set in mac control register,
+ * the chip swaps data in fifo, as well as data in
+ * template ram
+ */
+ be_bit = (R_REG(&regs->maccontrol) & MCTL_BIGEND) != 0;
+
+ while (len > 0) {
+ memcpy(&word, buf, sizeof(u32));
+
+ if (be_bit) {
+ word_be = cpu_to_be32(word);
+ word = *(u32 *)&word_be;
+ } else {
+ word_le = cpu_to_le32(word);
+ word = *(u32 *)&word_le;
+ }
+
+ W_REG(&regs->tplatewrdata, word);
+
+ buf = (u8 *) buf + sizeof(u32);
+ len -= sizeof(u32);
+ }
+}
+
+static void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin)
+{
+ wlc_hw->band->CWmin = newmin;
+
+ W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
+ (void)R_REG(&wlc_hw->regs->objaddr);
+ W_REG(&wlc_hw->regs->objdata, newmin);
+}
+
+static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax)
+{
+ wlc_hw->band->CWmax = newmax;
+
+ W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
+ (void)R_REG(&wlc_hw->regs->objaddr);
+ W_REG(&wlc_hw->regs->objdata, newmax);
+}
+
+void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw)
+{
+ bool fastclk;
+
+ /* request FAST clock if not on */
+ fastclk = wlc_hw->forcefastclk;
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+ wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
+
+ brcms_b_phy_reset(wlc_hw);
+ wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
+
+ /* restore the clk */
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw)
+{
+ u16 v;
+ struct brcms_c_info *wlc = wlc_hw->wlc;
+ /* update SYNTHPU_DLY */
+
+ if (BRCMS_ISLCNPHY(wlc->band))
+ v = SYNTHPU_DLY_LPPHY_US;
+ else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3)))
+ v = SYNTHPU_DLY_NPHY_US;
+ else
+ v = SYNTHPU_DLY_BPHY_US;
+
+ brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
+}
+
+static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw)
+{
+ u16 phyctl;
+ u16 phytxant = wlc_hw->bmac_phytxant;
+ u16 mask = PHY_TXC_ANT_MASK;
+
+ /* set the Probe Response frame phy control word */
+ phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
+ phyctl = (phyctl & ~mask) | phytxant;
+ brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
+
+ /* set the Response (ACK/CTS) frame phy control word */
+ phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD);
+ phyctl = (phyctl & ~mask) | phytxant;
+ brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
+}
+
+static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw,
+ u8 rate)
+{
+ uint i;
+ u8 plcp_rate = 0;
+ struct plcp_signal_rate_lookup {
+ u8 rate;
+ u8 signal_rate;
+ };
+ /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
+ const struct plcp_signal_rate_lookup rate_lookup[] = {
+ {BRCM_RATE_6M, 0xB},
+ {BRCM_RATE_9M, 0xF},
+ {BRCM_RATE_12M, 0xA},
+ {BRCM_RATE_18M, 0xE},
+ {BRCM_RATE_24M, 0x9},
+ {BRCM_RATE_36M, 0xD},
+ {BRCM_RATE_48M, 0x8},
+ {BRCM_RATE_54M, 0xC}
+ };
+
+ for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
+ if (rate == rate_lookup[i].rate) {
+ plcp_rate = rate_lookup[i].signal_rate;
+ break;
+ }
+ }
+
+ /* Find the SHM pointer to the rate table entry by looking in the
+ * Direct-map Table
+ */
+ return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
+}
+
+static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw)
+{
+ u8 rate;
+ u8 rates[8] = {
+ BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M,
+ BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M
+ };
+ u16 entry_ptr;
+ u16 pctl1;
+ uint i;
+
+ if (!BRCMS_PHY_11N_CAP(wlc_hw->band))
+ return;
+
+ /* walk the phy rate table and update the entries */
+ for (i = 0; i < ARRAY_SIZE(rates); i++) {
+ rate = rates[i];
+
+ entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate);
+
+ /* read the SHM Rate Table entry OFDM PCTL1 values */
+ pctl1 =
+ brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
+
+ /* modify the value */
+ pctl1 &= ~PHY_TXC1_MODE_MASK;
+ pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
+
+ /* Update the SHM Rate Table entry OFDM PCTL1 values */
+ brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
+ pctl1);
+ }
+}
+
+/* band-specific init */
+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_c_ucode_bsinit(wlc_hw);
+
+ wlc_phy_init(wlc_hw->band->pi, chanspec);
+
+ brcms_c_ucode_txant_set(wlc_hw);
+
+ /*
+ * cwmin is band-specific, update hardware
+ * with value for current band
+ */
+ brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
+ brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
+
+ brcms_b_update_slot_timing(wlc_hw,
+ wlc_hw->band->bandtype == BRCM_BAND_5G ?
+ true : wlc_hw->shortslot);
+
+ /* write phytype and phyvers */
+ brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
+ brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
+
+ /*
+ * initialize the txphyctl1 rate table since
+ * shmem is shared between bands
+ */
+ brcms_upd_ofdm_pctl1_table(wlc_hw);
+
+ brcms_b_upd_synthpu(wlc_hw);
+}
+
+/* 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_corereg(wlc_hw->sih, SI_CC_IDX,
+ offsetof(struct chipcregs, chipcontrol_addr), ~0, 0);
+ udelay(1);
+ ai_corereg(wlc_hw->sih, SI_CC_IDX,
+ offsetof(struct chipcregs, chipcontrol_data), 0x4, 0);
+ udelay(1);
+ ai_corereg(wlc_hw->sih, SI_CC_IDX,
+ offsetof(struct chipcregs, chipcontrol_data), 0x4, 4);
+ udelay(1);
+ ai_corereg(wlc_hw->sih, SI_CC_IDX,
+ offsetof(struct chipcregs, chipcontrol_data), 0x4, 0);
+ udelay(1);
+}
+
+/* light way to turn on phy clock without reset for NPHY only
+ * refer to brcms_b_core_phy_clk for full version
+ */
+void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk)
+{
+ /* support(necessary for NPHY and HYPHY) only */
+ if (!BRCMS_ISNPHY(wlc_hw->band))
+ return;
+
+ if (ON == clk)
+ ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
+ else
+ ai_core_cflags(wlc_hw->sih, SICF_FGC, 0);
+
+}
+
+void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk)
+{
+ if (ON == clk)
+ ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
+ else
+ ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
+}
+
+void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
+{
+ struct brcms_phy_pub *pih = wlc_hw->band->pi;
+ u32 phy_bw_clkbits;
+ bool phy_in_reset = false;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ if (pih == NULL)
+ return;
+
+ phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
+
+ /* Specific reset sequence required for NPHY rev 3 and 4 */
+ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
+ NREV_LE(wlc_hw->band->phyrev, 4)) {
+ /* Set the PHY bandwidth */
+ ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
+
+ udelay(1);
+
+ /* Perform a soft reset of the PHY PLL */
+ brcms_b_core_phypll_reset(wlc_hw);
+
+ /* reset the PHY */
+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
+ (SICF_PRST | SICF_PCLKE));
+ phy_in_reset = true;
+ } else {
+ ai_core_cflags(wlc_hw->sih,
+ (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
+ (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
+ }
+
+ udelay(2);
+ brcms_b_core_phy_clk(wlc_hw, ON);
+
+ if (pih)
+ wlc_phy_anacore(pih, ON);
+}
+
+/* switch to and initialize new band */
+static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
+ u16 chanspec) {
+ struct brcms_c_info *wlc = wlc_hw->wlc;
+ u32 macintmask;
+
+ /* Enable the d11 core before accessing it */
+ if (!ai_iscoreup(wlc_hw->sih)) {
+ ai_core_reset(wlc_hw->sih, 0, 0);
+ brcms_c_mctrl_reset(wlc_hw);
+ }
+
+ macintmask = brcms_c_setband_inact(wlc, bandunit);
+
+ if (!wlc_hw->up)
+ return;
+
+ brcms_b_core_phy_clk(wlc_hw, ON);
+
+ /* band-specific initializations */
+ brcms_b_bsinit(wlc, chanspec);
+
+ /*
+ * If there are any pending software interrupt bits,
+ * then replace these with a harmless nonzero value
+ * so brcms_c_dpc() will re-enable interrupts when done.
+ */
+ if (wlc->macintstatus)
+ wlc->macintstatus = MI_DMAINT;
+
+ /* restore macintmask */
+ brcms_intrsrestore(wlc->wl, macintmask);
+
+ /* ucode should still be suspended.. */
+ WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
+}
+
+static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw)
+{
+
+ /* reject unsupported corerev */
+ if (!CONF_HAS(D11CONF, wlc_hw->corerev)) {
+ wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n",
+ wlc_hw->corerev);
+ return false;
+ }
+
+ return true;
+}
+
+/* Validate some board info parameters */
+static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw)
+{
+ uint boardrev = wlc_hw->boardrev;
+
+ /* 4 bits each for board type, major, minor, and tiny version */
+ uint brt = (boardrev & 0xf000) >> 12;
+ uint b0 = (boardrev & 0xf00) >> 8;
+ uint b1 = (boardrev & 0xf0) >> 4;
+ uint b2 = boardrev & 0xf;
+
+ /* voards from other vendors are always considered valid */
+ if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM)
+ return true;
+
+ /* do some boardrev sanity checks when boardvendor is Broadcom */
+ if (boardrev == 0)
+ return false;
+
+ if (boardrev <= 0xff)
+ return true;
+
+ if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
+ || (b2 > 9))
+ return false;
+
+ return true;
+}
+
+static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw)
+{
+ enum brcms_srom_id var_id = BRCMS_SROM_MACADDR;
+ char *macaddr;
+
+ /* If macaddr exists, use it (Sromrev4, CIS, ...). */
+ macaddr = getvar(wlc_hw->sih, var_id);
+ if (macaddr != NULL)
+ return macaddr;
+
+ if (wlc_hw->_nbands > 1)
+ var_id = BRCMS_SROM_ET1MACADDR;
+ else
+ var_id = BRCMS_SROM_IL0MACADDR;
+
+ macaddr = getvar(wlc_hw->sih, var_id);
+ if (macaddr == NULL)
+ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr "
+ "getvar(%d) not found\n", wlc_hw->unit, var_id);
+
+ return macaddr;
+}
+
+/* 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);
+
+ /*
+ * dont power down if plldown is false or
+ * we must poll hw radio disable
+ */
+ if (!want && wlc_hw->pllreq)
+ return;
+
+ if (wlc_hw->sih)
+ ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
+
+ wlc_hw->sbclk = want;
+ if (!wlc_hw->sbclk) {
+ wlc_hw->clk = false;
+ if (wlc_hw->band && wlc_hw->band->pi)
+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+ }
+}
+
+/*
+ * Return true if radio is disabled, otherwise false.
+ * hw radio disable signal is an external pin, users activate it asynchronously
+ * this function could be called when driver is down and w/o clock
+ * it operates on different registers depending on corerev and boardflag.
+ */
+static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
+{
+ bool v, clk, xtal;
+ u32 resetbits = 0, flags = 0;
+
+ xtal = wlc_hw->sbclk;
+ if (!xtal)
+ brcms_b_xtal(wlc_hw, ON);
+
+ /* may need to take core out of reset first */
+ clk = wlc_hw->clk;
+ if (!clk) {
+ /*
+ * mac no longer enables phyclk automatically when driver
+ * accesses phyreg throughput mac. This can be skipped since
+ * only mac reg is accessed below
+ */
+ flags |= SICF_PCLKE;
+
+ /*
+ * AI chip doesn't restore bar0win2 on
+ * hibernation/resume, need sw fixup
+ */
+ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+ (wlc_hw->sih->chip == BCM43225_CHIP_ID))
+ wlc_hw->regs = (struct d11regs __iomem *)
+ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
+ ai_core_reset(wlc_hw->sih, flags, resetbits);
+ brcms_c_mctrl_reset(wlc_hw);
+ }
+
+ v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
+
+ /* put core back into reset */
+ if (!clk)
+ ai_core_disable(wlc_hw->sih, 0);
+
+ if (!xtal)
+ brcms_b_xtal(wlc_hw, OFF);
+
+ return v;
+}
+
+static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo)
+{
+ struct dma_pub *di = wlc_hw->di[fifo];
+ return dma_rxreset(di);
+}
+
+/* d11 core reset
+ * ensure fask clock during reset
+ * reset dma
+ * reset d11(out of reset)
+ * reset phy(out of reset)
+ * clear software macintstatus for fresh new start
+ * one testing hack wlc_hw->noreset will bypass the d11/phy reset
+ */
+void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
+{
+ struct d11regs __iomem *regs;
+ uint i;
+ bool fastclk;
+ u32 resetbits = 0;
+
+ 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);
+
+ regs = wlc_hw->regs;
+
+ /* request FAST clock if not on */
+ fastclk = wlc_hw->forcefastclk;
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+ /* reset the dma engines except first time thru */
+ if (ai_iscoreup(wlc_hw->sih)) {
+ 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: "
+ "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"
+ "[%d]: cannot stop dma\n",
+ wlc_hw->unit, __func__, RX_FIFO);
+ }
+ /* if noreset, just stop the psm and return */
+ if (wlc_hw->noreset) {
+ wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */
+ brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
+ return;
+ }
+
+ /*
+ * mac no longer enables phyclk automatically when driver accesses
+ * phyreg throughput mac, AND phy_reset is skipped at early stage when
+ * band->pi is invalid. need to enable PHY CLK
+ */
+ flags |= SICF_PCLKE;
+
+ /*
+ * reset the core
+ * In chips with PMU, the fastclk request goes through d11 core
+ * reg 0x1e0, which is cleared by the core_reset. have to re-request it.
+ *
+ * This adds some delay and we can optimize it by also requesting
+ * fastclk through chipcommon during this period if necessary. But
+ * that has to work coordinate with other driver like mips/arm since
+ * they may touch chipcommon as well.
+ */
+ wlc_hw->clk = false;
+ ai_core_reset(wlc_hw->sih, flags, resetbits);
+ wlc_hw->clk = true;
+ if (wlc_hw->band && wlc_hw->band->pi)
+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
+
+ brcms_c_mctrl_reset(wlc_hw);
+
+ if (wlc_hw->sih->cccaps & CC_CAP_PMU)
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+ brcms_b_phy_reset(wlc_hw);
+
+ /* turn on PHY_PLL */
+ brcms_b_core_phypll_ctl(wlc_hw, true);
+
+ /* clear sw intstatus */
+ wlc_hw->wlc->macintstatus = 0;
+
+ /* restore the clk setting */
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+/* txfifo sizes needs to be modified(increased) since the newer cores
+ * have more memory.
+ */
+static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u16 fifo_nu;
+ u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
+ u16 txfifo_def, txfifo_def1;
+ u16 txfifo_cmd;
+
+ /* tx fifos start at TXFIFO_START_BLK from the Base address */
+ txfifo_startblk = TXFIFO_START_BLK;
+
+ /* sequence of operations: reset fifo, set fifo size, reset fifo */
+ for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
+
+ txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
+ txfifo_def = (txfifo_startblk & 0xff) |
+ (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
+ txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
+ ((((txfifo_endblk -
+ 1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
+ txfifo_cmd =
+ TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
+
+ W_REG(&regs->xmtfifocmd, txfifo_cmd);
+ W_REG(&regs->xmtfifodef, txfifo_def);
+ W_REG(&regs->xmtfifodef1, txfifo_def1);
+
+ W_REG(&regs->xmtfifocmd, txfifo_cmd);
+
+ txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
+ }
+ /*
+ * need to propagate to shm location to be in sync since ucode/hw won't
+ * do this
+ */
+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE0,
+ wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE1,
+ wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE2,
+ ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
+ xmtfifo_sz[TX_AC_BK_FIFO]));
+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE3,
+ ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
+ xmtfifo_sz[TX_BCMC_FIFO]));
+}
+
+/* This function is used for changing the tsf frac register
+ * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
+ * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
+ * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
+ * HTPHY Formula is 2^26/freq(MHz) e.g.
+ * For spuron2 - 126MHz -> 2^26/126 = 532610.0
+ * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
+ * For spuron: 123MHz -> 2^26/123 = 545600.5
+ * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
+ * For spur off: 120MHz -> 2^26/120 = 559240.5
+ * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
+ */
+
+void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+
+ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
+ if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */
+ W_REG(&regs->tsf_clk_frac_l, 0x2082);
+ W_REG(&regs->tsf_clk_frac_h, 0x8);
+ } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */
+ W_REG(&regs->tsf_clk_frac_l, 0x5341);
+ W_REG(&regs->tsf_clk_frac_h, 0x8);
+ } else { /* 120Mhz */
+ W_REG(&regs->tsf_clk_frac_l, 0x8889);
+ W_REG(&regs->tsf_clk_frac_h, 0x8);
+ }
+ } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+ if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */
+ W_REG(&regs->tsf_clk_frac_l, 0x7CE0);
+ W_REG(&regs->tsf_clk_frac_h, 0xC);
+ } else { /* 80Mhz */
+ W_REG(&regs->tsf_clk_frac_l, 0xCCCD);
+ W_REG(&regs->tsf_clk_frac_h, 0xC);
+ }
+ }
+}
+
+/* Initialize GPIOs that are controlled by D11 core */
+static void brcms_c_gpio_init(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs;
+ u32 gc, gm;
+
+ regs = wlc_hw->regs;
+
+ /* use GPIO select 0 to get all gpio signals from the gpio out reg */
+ brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
+
+ /*
+ * Common GPIO setup:
+ * G0 = LED 0 = WLAN Activity
+ * G1 = LED 1 = WLAN 2.4 GHz Radio State
+ * G2 = LED 2 = WLAN 5 GHz Radio State
+ * G4 = radio disable input (HI enabled, LO disabled)
+ */
+
+ gc = gm = 0;
+
+ /* Allocate GPIOs for mimo antenna diversity feature */
+ if (wlc_hw->antsel_type == ANTSEL_2x3) {
+ /* Enable antenna diversity, use 2x3 mode */
+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
+ MHF3_ANTSEL_EN, BRCM_BAND_ALL);
+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
+ MHF3_ANTSEL_MODE, BRCM_BAND_ALL);
+
+ /* init superswitch control */
+ wlc_phy_antsel_init(wlc_hw->band->pi, false);
+
+ } else if (wlc_hw->antsel_type == ANTSEL_2x4) {
+ gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
+ /*
+ * The board itself is powered by these GPIOs
+ * (when not sending pattern) so set them high
+ */
+ OR_REG(&regs->psm_gpio_oe,
+ (BOARD_GPIO_12 | BOARD_GPIO_13));
+ OR_REG(&regs->psm_gpio_out,
+ (BOARD_GPIO_12 | BOARD_GPIO_13));
+
+ /* Enable antenna diversity, use 2x4 mode */
+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
+ MHF3_ANTSEL_EN, BRCM_BAND_ALL);
+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
+ BRCM_BAND_ALL);
+
+ /* Configure the desired clock to be 4Mhz */
+ brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
+ ANTSEL_CLKDIV_4MHZ);
+ }
+
+ /*
+ * gpio 9 controls the PA. ucode is responsible
+ * for wiggling out and oe
+ */
+ if (wlc_hw->boardflags & BFL_PACTRL)
+ gm |= gc |= BOARD_GPIO_PACTRL;
+
+ /* apply to gpiocontrol register */
+ ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
+}
+
+static void brcms_ucode_write(struct brcms_hardware *wlc_hw,
+ const __le32 ucode[], const size_t nbytes)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ uint i;
+ uint count;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ count = (nbytes / sizeof(u32));
+
+ W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
+ (void)R_REG(&regs->objaddr);
+ for (i = 0; i < count; i++)
+ W_REG(&regs->objdata, le32_to_cpu(ucode[i]));
+
+}
+
+static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
+{
+ struct brcms_c_info *wlc;
+ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
+
+ wlc = wlc_hw->wlc;
+
+ if (wlc_hw->ucode_loaded)
+ return;
+
+ if (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",
+ __func__, wlc_hw->unit, wlc_hw->corerev);
+ } else if (D11REV_IS(wlc_hw->corerev, 24)) {
+ if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+ brcms_ucode_write(wlc_hw, ucode->bcm43xx_24_lcn,
+ ucode->bcm43xx_24_lcnsz);
+ wlc_hw->ucode_loaded = true;
+ } else {
+ wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
+ "corerev %d\n",
+ __func__, wlc_hw->unit, wlc_hw->corerev);
+ }
+ }
+}
+
+void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant)
+{
+ /* update sw state */
+ wlc_hw->bmac_phytxant = phytxant;
+
+ /* push to ucode if up */
+ if (!wlc_hw->up)
+ return;
+ brcms_c_ucode_txant_set(wlc_hw);
+
+}
+
+u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw)
+{
+ return (u16) wlc_hw->wlc->stf->txant;
+}
+
+void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type)
+{
+ wlc_hw->antsel_type = antsel_type;
+
+ /* Update the antsel type for phy module to use */
+ wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
+}
+
+static void brcms_c_fatal_error(struct brcms_c_info *wlc)
+{
+ wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n",
+ wlc->pub->unit);
+ brcms_init(wlc->wl);
+}
+
+static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
+{
+ bool fatal = false;
+ uint unit;
+ uint intstatus, idx;
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ struct wiphy *wiphy = wlc_hw->wlc->wiphy;
+
+ unit = wlc_hw->unit;
+
+ for (idx = 0; idx < NFIFO; idx++) {
+ /* read intstatus register and ignore any non-error bits */
+ intstatus =
+ R_REG(&regs->intctrlregs[idx].intstatus) & I_ERRORS;
+ if (!intstatus)
+ continue;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n",
+ unit, idx, intstatus);
+
+ if (intstatus & I_RO) {
+ wiphy_err(wiphy, "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);
+ fatal = true;
+ }
+
+ if (intstatus & I_PD) {
+ wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit,
+ idx);
+ fatal = true;
+ }
+
+ if (intstatus & I_DE) {
+ wiphy_err(wiphy, "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 "
+ "underflow\n", idx, unit);
+
+ if (intstatus & I_XU) {
+ wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo "
+ "underflow\n", idx, unit);
+ fatal = true;
+ }
+
+ if (fatal) {
+ brcms_c_fatal_error(wlc_hw->wlc); /* big hammer */
+ break;
+ } else
+ W_REG(&regs->intctrlregs[idx].intstatus,
+ intstatus);
+ }
+}
+
+void brcms_c_intrson(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ wlc->macintmask = wlc->defmacintmask;
+ W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
+}
+
+/*
+ * callback for siutils.c, which has only wlc handler, no wl they both check
+ * up, not only because there is no need to off/restore d11 interrupt but also
+ * because per-port code may require sync with valid interrupt.
+ */
+static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc)
+{
+ if (!wlc->hw->up)
+ return 0;
+
+ return brcms_intrsoff(wlc->wl);
+}
+
+static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask)
+{
+ if (!wlc->hw->up)
+ return;
+
+ brcms_intrsrestore(wlc->wl, macintmask);
+}
+
+u32 brcms_c_intrsoff(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ u32 macintmask;
+
+ if (!wlc_hw->clk)
+ return 0;
+
+ macintmask = wlc->macintmask; /* isr can still happen */
+
+ W_REG(&wlc_hw->regs->macintmask, 0);
+ (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */
+ udelay(1); /* ensure int line is no longer driven */
+ wlc->macintmask = 0;
+
+ /* return previous macintmask; resolve race between us and our isr */
+ return wlc->macintstatus ? 0 : macintmask;
+}
+
+void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ if (!wlc_hw->clk)
+ return;
+
+ wlc->macintmask = macintmask;
+ W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
+}
+
+static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
+ uint tx_fifo)
+{
+ u8 fifo = 1 << tx_fifo;
+
+ /* Two clients of this code, 11h Quiet period and scanning. */
+
+ /* only suspend if not already suspended */
+ if ((wlc_hw->suspended_fifos & fifo) == fifo)
+ return;
+
+ /* force the core awake only if not already */
+ if (wlc_hw->suspended_fifos == 0)
+ brcms_c_ucode_wake_override_set(wlc_hw,
+ BRCMS_WAKE_OVERRIDE_TXFIFO);
+
+ wlc_hw->suspended_fifos |= fifo;
+
+ if (wlc_hw->di[tx_fifo]) {
+ /*
+ * Suspending AMPDU transmissions in the middle can cause
+ * underflow which may result in mismatch between ucode and
+ * driver so suspend the mac before suspending the FIFO
+ */
+ if (BRCMS_PHY_11N_CAP(wlc_hw->band))
+ brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+
+ dma_txsuspend(wlc_hw->di[tx_fifo]);
+
+ if (BRCMS_PHY_11N_CAP(wlc_hw->band))
+ brcms_c_enable_mac(wlc_hw->wlc);
+ }
+}
+
+static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
+ uint tx_fifo)
+{
+ /* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case
+ * but need to be done here for PIO otherwise the watchdog will catch
+ * the inconsistency and fire
+ */
+ /* Two clients of this code, 11h Quiet period and scanning. */
+ if (wlc_hw->di[tx_fifo])
+ dma_txresume(wlc_hw->di[tx_fifo]);
+
+ /* allow core to sleep again */
+ if (wlc_hw->suspended_fifos == 0)
+ return;
+ else {
+ wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
+ if (wlc_hw->suspended_fifos == 0)
+ brcms_c_ucode_wake_override_clear(wlc_hw,
+ BRCMS_WAKE_OVERRIDE_TXFIFO);
+ }
+}
+
+static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, u32 flags)
+{
+ static const u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+
+ if (on) {
+ /* suspend tx fifos */
+ brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
+ brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
+ brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
+ brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
+
+ /* zero the address match register so we do not send ACKs */
+ brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
+ null_ether_addr);
+ } else {
+ /* resume tx fifos */
+ brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
+ brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
+ brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
+ brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
+
+ /* Restore address */
+ brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
+ wlc_hw->etheraddr);
+ }
+
+ wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
+
+ if (on)
+ brcms_c_ucode_mute_override_set(wlc_hw);
+ else
+ brcms_c_ucode_mute_override_clear(wlc_hw);
+}
+
+/*
+ * Read and clear macintmask and macintstatus and intstatus registers.
+ * This routine should be called with interrupts off
+ * Return:
+ * -1 if brcms_deviceremoved(wlc) evaluates to true;
+ * 0 if the interrupt is not for us, or we are in some special cases;
+ * device interrupt status bits otherwise.
+ */
+static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u32 macintstatus;
+
+ /* macintstatus includes a DMA interrupt summary bit */
+ macintstatus = R_REG(&regs->macintstatus);
+
+ BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
+ macintstatus);
+
+ /* detect cardbus removed, in power down(suspend) and in reset */
+ if (brcms_deviceremoved(wlc))
+ return -1;
+
+ /* brcms_deviceremoved() succeeds even when the core is still resetting,
+ * handle that case here.
+ */
+ if (macintstatus == 0xffffffff)
+ return 0;
+
+ /* defer unsolicited interrupts */
+ macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
+
+ /* 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 */
+ W_REG(&regs->macintmask, 0);
+ (void)R_REG(&regs->macintmask); /* sync readback */
+ wlc->macintmask = 0;
+
+ /* clear device interrupts */
+ W_REG(&regs->macintstatus, macintstatus);
+
+ /* MI_DMAINT is indication of non-zero intstatus */
+ if (macintstatus & MI_DMAINT)
+ /*
+ * only fifo interrupt enabled is I_RI in
+ * RX_FIFO. If MI_DMAINT is set, assume it
+ * is set and clear the interrupt.
+ */
+ W_REG(&regs->intctrlregs[RX_FIFO].intstatus,
+ DEF_RXINTMASK);
+
+ return macintstatus;
+}
+
+/* Update wlc->macintstatus and wlc->intstatus[]. */
+/* Return true if they are updated successfully. false otherwise */
+bool brcms_c_intrsupd(struct brcms_c_info *wlc)
+{
+ u32 macintstatus;
+
+ /* read and clear macintstatus and intstatus registers */
+ macintstatus = wlc_intstatus(wlc, false);
+
+ /* device is removed */
+ if (macintstatus == 0xffffffff)
+ return false;
+
+ /* update interrupt status in software */
+ wlc->macintstatus |= macintstatus;
+
+ return true;
+}
+
+/*
+ * 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,
+ * false otherwise.
+ */
+bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc)
+{
+ 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");
+
+ /* it is not for us */
+ if (macintstatus == 0)
+ return false;
+
+ *wantdpc = true;
+
+ /* save interrupt status bits */
+ wlc->macintstatus = macintstatus;
+
+ return true;
+
+}
+
+void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u32 mc, mi;
+ struct wiphy *wiphy = wlc->wiphy;
+
+ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+ wlc_hw->band->bandunit);
+
+ /*
+ * Track overlapping suspend requests
+ */
+ wlc_hw->mac_suspend_depth++;
+ if (wlc_hw->mac_suspend_depth > 1)
+ return;
+
+ /* force the core awake */
+ brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+
+ mc = R_REG(&regs->maccontrol);
+
+ if (mc == 0xffffffff) {
+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ __func__);
+ brcms_down(wlc->wl);
+ return;
+ }
+ WARN_ON(mc & MCTL_PSM_JMP_0);
+ WARN_ON(!(mc & MCTL_PSM_RUN));
+ WARN_ON(!(mc & MCTL_EN_MAC));
+
+ mi = R_REG(&regs->macintstatus);
+ if (mi == 0xffffffff) {
+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ __func__);
+ brcms_down(wlc->wl);
+ return;
+ }
+ WARN_ON(mi & MI_MACSSPNDD);
+
+ brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0);
+
+ SPINWAIT(!(R_REG(&regs->macintstatus) & MI_MACSSPNDD),
+ BRCMS_MAX_MAC_SUSPEND);
+
+ if (!(R_REG(&regs->macintstatus) & MI_MACSSPNDD)) {
+ wiphy_err(wiphy, "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, "
+ "psm_brc 0x%04x\n", wlc_hw->unit,
+ R_REG(&regs->psmdebug),
+ R_REG(&regs->phydebug),
+ R_REG(&regs->psm_brc));
+ }
+
+ mc = R_REG(&regs->maccontrol);
+ if (mc == 0xffffffff) {
+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ __func__);
+ brcms_down(wlc->wl);
+ return;
+ }
+ WARN_ON(mc & MCTL_PSM_JMP_0);
+ WARN_ON(!(mc & MCTL_PSM_RUN));
+ WARN_ON(mc & MCTL_EN_MAC);
+}
+
+void brcms_c_enable_mac(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u32 mc, mi;
+
+ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+ wlc->band->bandunit);
+
+ /*
+ * Track overlapping suspend requests
+ */
+ wlc_hw->mac_suspend_depth--;
+ if (wlc_hw->mac_suspend_depth > 0)
+ return;
+
+ mc = R_REG(&regs->maccontrol);
+ WARN_ON(mc & MCTL_PSM_JMP_0);
+ WARN_ON(mc & MCTL_EN_MAC);
+ WARN_ON(!(mc & MCTL_PSM_RUN));
+
+ brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
+ W_REG(&regs->macintstatus, MI_MACSSPNDD);
+
+ mc = R_REG(&regs->maccontrol);
+ WARN_ON(mc & MCTL_PSM_JMP_0);
+ WARN_ON(!(mc & MCTL_EN_MAC));
+ WARN_ON(!(mc & MCTL_PSM_RUN));
+
+ mi = R_REG(&regs->macintstatus);
+ WARN_ON(mi & MI_MACSSPNDD);
+
+ brcms_c_ucode_wake_override_clear(wlc_hw,
+ BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+}
+
+void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode)
+{
+ wlc_hw->hw_stf_ss_opmode = stf_mode;
+
+ if (wlc_hw->clk)
+ brcms_upd_ofdm_pctl1_table(wlc_hw);
+}
+
+static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
+{
+ struct d11regs __iomem *regs;
+ u32 w, val;
+ struct wiphy *wiphy = wlc_hw->wlc->wiphy;
+
+ BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
+
+ regs = wlc_hw->regs;
+
+ /* Validate dchip register access */
+
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ w = R_REG(&regs->objdata);
+
+ /* Can we write and read back a 32bit register? */
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ W_REG(&regs->objdata, (u32) 0xaa5555aa);
+
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ val = R_REG(&regs->objdata);
+ if (val != (u32) 0xaa5555aa) {
+ wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
+ "expected 0xaa5555aa\n", wlc_hw->unit, val);
+ return false;
+ }
+
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ W_REG(&regs->objdata, (u32) 0x55aaaa55);
+
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ val = R_REG(&regs->objdata);
+ if (val != (u32) 0x55aaaa55) {
+ wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
+ "expected 0x55aaaa55\n", wlc_hw->unit, val);
+ return false;
+ }
+
+ W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+ (void)R_REG(&regs->objaddr);
+ W_REG(&regs->objdata, w);
+
+ /* clear CFPStart */
+ W_REG(&regs->tsf_cfpstart, 0);
+
+ w = R_REG(&regs->maccontrol);
+ if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
+ (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
+ wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = "
+ "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w,
+ (MCTL_IHR_EN | MCTL_WAKE),
+ (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
+ return false;
+ }
+
+ return true;
+}
+
+#define PHYPLL_WAIT_US 100000
+
+void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
+{
+ struct d11regs __iomem *regs;
+ u32 tmp;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ tmp = 0;
+ regs = wlc_hw->regs;
+
+ if (on) {
+ if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
+ OR_REG(&regs->clk_ctl_st,
+ (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
+ CCS_ERSRC_REQ_PHYPLL));
+ SPINWAIT((R_REG(&regs->clk_ctl_st) &
+ (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
+ PHYPLL_WAIT_US);
+
+ tmp = R_REG(&regs->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__);
+ } else {
+ OR_REG(&regs->clk_ctl_st,
+ (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
+ SPINWAIT((R_REG(&regs->clk_ctl_st) &
+ (CCS_ERSRC_AVAIL_D11PLL |
+ CCS_ERSRC_AVAIL_PHYPLL)) !=
+ (CCS_ERSRC_AVAIL_D11PLL |
+ CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
+
+ tmp = R_REG(&regs->clk_ctl_st);
+ if ((tmp &
+ (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__);
+ }
+ } else {
+ /*
+ * Since the PLL may be shared, other cores can still
+ * be requesting it; so we'll deassert the request but
+ * not wait for status to comply.
+ */
+ AND_REG(&regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
+ tmp = R_REG(&regs->clk_ctl_st);
+ }
+}
+
+static void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
+{
+ bool dev_gone;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ dev_gone = brcms_deviceremoved(wlc_hw->wlc);
+
+ if (dev_gone)
+ return;
+
+ if (wlc_hw->noreset)
+ return;
+
+ /* radio off */
+ wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
+
+ /* turn off analog core */
+ wlc_phy_anacore(wlc_hw->band->pi, OFF);
+
+ /* turn off PHYPLL to save power */
+ brcms_b_core_phypll_ctl(wlc_hw, false);
+
+ wlc_hw->clk = false;
+ ai_core_disable(wlc_hw->sih, 0);
+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+}
+
+static void brcms_c_flushqueues(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ uint i;
+
+ /* free any posted tx packets */
+ 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);
+ }
+
+ /* free any posted rx packets */
+ dma_rxreclaim(wlc_hw->di[RX_FIFO]);
+}
+
+static u16
+brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u16 __iomem *objdata_lo = (u16 __iomem *)&regs->objdata;
+ u16 __iomem *objdata_hi = objdata_lo + 1;
+ u16 v;
+
+ W_REG(&regs->objaddr, sel | (offset >> 2));
+ (void)R_REG(&regs->objaddr);
+ if (offset & 2)
+ v = R_REG(objdata_hi);
+ else
+ v = R_REG(objdata_lo);
+
+ return v;
+}
+
+static void
+brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v,
+ u32 sel)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ u16 __iomem *objdata_lo = (u16 __iomem *)&regs->objdata;
+ u16 __iomem *objdata_hi = objdata_lo + 1;
+
+ W_REG(&regs->objaddr, sel | (offset >> 2));
+ (void)R_REG(&regs->objaddr);
+ if (offset & 2)
+ W_REG(objdata_hi, v);
+ else
+ W_REG(objdata_lo, v);
+}
+
+/*
+ * Read a single u16 from shared memory.
+ * SHM 'offset' needs to be an even address
+ */
+u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset)
+{
+ return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
+}
+
+/*
+ * Write a single u16 to shared memory.
+ * SHM 'offset' needs to be an even address
+ */
+void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v)
+{
+ brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
+}
+
+/*
+ * Copy a buffer to shared memory of specified type .
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ * 'sel' selects the type of memory
+ */
+void
+brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset,
+ const void *buf, int len, u32 sel)
+{
+ u16 v;
+ const u8 *p = (const u8 *)buf;
+ int i;
+
+ if (len <= 0 || (offset & 1) || (len & 1))
+ return;
+
+ for (i = 0; i < len; i += 2) {
+ v = p[i] | (p[i + 1] << 8);
+ brcms_b_write_objmem(wlc_hw, offset + i, v, sel);
+ }
+}
+
+/*
+ * Copy a piece of shared memory of specified type to a buffer .
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ * 'sel' selects the type of memory
+ */
+void
+brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf,
+ int len, u32 sel)
+{
+ u16 v;
+ u8 *p = (u8 *) buf;
+ int i;
+
+ if (len <= 0 || (offset & 1) || (len & 1))
+ return;
+
+ for (i = 0; i < len; i += 2) {
+ v = brcms_b_read_objmem(wlc_hw, offset + i, sel);
+ p[i] = v & 0xFF;
+ p[i + 1] = (v >> 8) & 0xFF;
+ }
+}
+
+/* Copy a buffer to shared memory.
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ */
+static void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset,
+ const void *buf, int len)
+{
+ brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
+}
+
+static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw,
+ u16 SRL, u16 LRL)
+{
+ wlc_hw->SRL = SRL;
+ wlc_hw->LRL = LRL;
+
+ /* write retry limit to SCR, shouldn't need to suspend */
+ if (wlc_hw->up) {
+ W_REG(&wlc_hw->regs->objaddr,
+ OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+ (void)R_REG(&wlc_hw->regs->objaddr);
+ W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL);
+ W_REG(&wlc_hw->regs->objaddr,
+ OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+ (void)R_REG(&wlc_hw->regs->objaddr);
+ W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL);
+ }
+}
+
+static void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, u32 req_bit)
+{
+ if (set) {
+ if (mboolisset(wlc_hw->pllreq, req_bit))
+ return;
+
+ mboolset(wlc_hw->pllreq, req_bit);
+
+ if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
+ if (!wlc_hw->sbclk)
+ brcms_b_xtal(wlc_hw, ON);
+ }
+ } else {
+ if (!mboolisset(wlc_hw->pllreq, req_bit))
+ return;
+
+ mboolclr(wlc_hw->pllreq, req_bit);
+
+ if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
+ if (wlc_hw->sbclk)
+ brcms_b_xtal(wlc_hw, OFF);
+ }
+ }
+}
+
+static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
+{
+ wlc_hw->antsel_avail = antsel_avail;
+}
+
+/*
+ * conditions under which the PM bit should be set in outgoing frames
+ * and STAY_AWAKE is meaningful
+ */
+static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
+{
+ struct brcms_bss_cfg *cfg = wlc->bsscfg;
+
+ /* disallow PS when one of the following global conditions meets */
+ if (!wlc->pub->associated)
+ return false;
+
+ /* disallow PS when one of these meets when not scanning */
+ if (wlc->monitor)
+ return false;
+
+ if (cfg->associated) {
+ /*
+ * disallow PS when one of the following
+ * bsscfg specific conditions meets
+ */
+ if (!cfg->BSS)
+ return false;
+
+ return false;
+ }
+
+ return true;
+}
+
+static void brcms_c_statsupd(struct brcms_c_info *wlc)
+{
+ int i;
+ struct macstat macstats;
+#ifdef BCMDBG
+ u16 delta;
+ u16 rxf0ovfl;
+ u16 txfunfl[NFIFO];
+#endif /* BCMDBG */
+
+ /* if driver down, make no sense to update stats */
+ if (!wlc->pub->up)
+ return;
+
+#ifdef BCMDBG
+ /* save last rx fifo 0 overflow count */
+ rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
+
+ /* save last tx fifo underflow count */
+ for (i = 0; i < NFIFO; i++)
+ txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
+#endif /* BCMDBG */
+
+ /* Read mac stats from contiguous shared memory */
+ brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats,
+ sizeof(struct macstat), OBJADDR_SHM_SEL);
+
+#ifdef BCMDBG
+ /* 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",
+ wlc->pub->unit, delta);
+
+ /* check for tx fifo underflows */
+ for (i = 0; i < NFIFO; i++) {
+ delta =
+ (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);
+ }
+#endif /* BCMDBG */
+
+ /* merge counters from dma module */
+ for (i = 0; i < NFIFO; i++) {
+ if (wlc->hw->di[i])
+ dma_counterreset(wlc->hw->di[i]);
+ }
+}
+
+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);
+
+ /* purge the dma rings */
+ brcms_c_flushqueues(wlc_hw->wlc);
+}
+
+void brcms_c_reset(struct brcms_c_info *wlc)
+{
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+ /* slurp up hw mac counters before core reset */
+ brcms_c_statsupd(wlc);
+
+ /* reset our snapshot of macstat counters */
+ memset((char *)wlc->core->macstat_snapshot, 0,
+ sizeof(struct macstat));
+
+ brcms_b_reset(wlc->hw);
+}
+
+/* Return the channel the driver should initialize during brcms_c_init.
+ * the channel may have to be changed from the currently configured channel
+ * if other configurations are in conflict (bandlocked, 11n mode disabled,
+ * invalid channel for current country, etc.)
+ */
+static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc)
+{
+ u16 chanspec =
+ 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
+ WL_CHANSPEC_BAND_2G;
+
+ return chanspec;
+}
+
+void brcms_c_init_scb(struct scb *scb)
+{
+ int i;
+
+ memset(scb, 0, sizeof(struct scb));
+ scb->flags = SCB_WMECAP | SCB_HTCAP;
+ for (i = 0; i < NUMPRIO; i++) {
+ scb->seqnum[i] = 0;
+ scb->seqctl[i] = 0xFFFF;
+ }
+
+ scb->seqctl_nonqos = 0xFFFF;
+ scb->magic = SCB_MAGIC;
+}
+
+/* d11 core init
+ * reset PSM
+ * download ucode/PCM
+ * let ucode run to suspended
+ * download ucode inits
+ * config other core registers
+ * init dma
+ */
+static void brcms_b_coreinit(struct brcms_c_info *wlc)
+{
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs;
+ u32 sflags;
+ uint bcnint_us;
+ uint i = 0;
+ bool fifosz_fixup = false;
+ int err = 0;
+ u16 buf[NFIFO];
+ struct wiphy *wiphy = wlc->wiphy;
+ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
+
+ regs = wlc_hw->regs;
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ /* reset PSM */
+ brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
+
+ brcms_ucode_download(wlc_hw);
+ /*
+ * FIFOSZ fixup. driver wants to controls the fifo allocation.
+ */
+ fifosz_fixup = true;
+
+ /* let the PSM run to the suspended state, set mode to BSS STA */
+ W_REG(&regs->macintstatus, -1);
+ brcms_b_mctrl(wlc_hw, ~0,
+ (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
+
+ /* wait for ucode to self-suspend after auto-init */
+ SPINWAIT(((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0),
+ 1000 * 1000);
+ if ((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0)
+ wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
+ "suspend!\n", wlc_hw->unit);
+
+ brcms_c_gpio_init(wlc);
+
+ sflags = ai_core_sflags(wlc_hw->sih, 0, 0);
+
+ if (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"
+ " %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"
+ " %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);
+ }
+
+ /* For old ucode, txfifo sizes needs to be modified(increased) */
+ if (fifosz_fixup == true)
+ brcms_b_corerev_fifofixup(wlc_hw);
+
+ /* check txfifo allocations match between ucode and driver */
+ buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0);
+ if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
+ i = TX_AC_BE_FIFO;
+ err = -1;
+ }
+ buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1);
+ if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
+ i = TX_AC_VI_FIFO;
+ err = -1;
+ }
+ buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2);
+ buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
+ buf[TX_AC_BK_FIFO] &= 0xff;
+ if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
+ i = TX_AC_BK_FIFO;
+ err = -1;
+ }
+ if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
+ i = TX_AC_VO_FIFO;
+ err = -1;
+ }
+ buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3);
+ buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
+ buf[TX_BCMC_FIFO] &= 0xff;
+ if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
+ i = TX_BCMC_FIFO;
+ err = -1;
+ }
+ if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
+ i = TX_ATIM_FIFO;
+ err = -1;
+ }
+ if (err != 0)
+ wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d"
+ " driver size %d index %d\n", buf[i],
+ wlc_hw->xmtfifo_sz[i], i);
+
+ /* make sure we can still talk to the mac */
+ WARN_ON(R_REG(&regs->maccontrol) == 0xffffffff);
+
+ /* band-specific inits done by wlc_bsinit() */
+
+ /* Set up frame burst size and antenna swap threshold init values */
+ brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
+ brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
+
+ /* enable one rx interrupt per received frame */
+ W_REG(&regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
+
+ /* set the station mode (BSS STA) */
+ brcms_b_mctrl(wlc_hw,
+ (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
+ (MCTL_INFRA | MCTL_DISCARD_PMQ));
+
+ /* set up Beacon interval */
+ bcnint_us = 0x8000 << 10;
+ W_REG(&regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
+ W_REG(&regs->tsf_cfpstart, bcnint_us);
+ W_REG(&regs->macintstatus, MI_GP1);
+
+ /* write interrupt mask */
+ W_REG(&regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
+
+ /* allow the MAC to control the PHY clock (dynamic on/off) */
+ brcms_b_macphyclk_set(wlc_hw, ON);
+
+ /* program dynamic clock control fast powerup delay register */
+ wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih);
+ W_REG(&regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
+
+ /* tell the ucode the corerev */
+ brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
+
+ /* tell the ucode MAC capabilities */
+ brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L,
+ (u16) (wlc_hw->machwcap & 0xffff));
+ brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H,
+ (u16) ((wlc_hw->
+ machwcap >> 16) & 0xffff));
+
+ /* write retry limits to SCR, this done after PSM init */
+ W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+ (void)R_REG(&regs->objaddr);
+ W_REG(&regs->objdata, wlc_hw->SRL);
+ W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+ (void)R_REG(&regs->objaddr);
+ W_REG(&regs->objdata, wlc_hw->LRL);
+
+ /* write rate fallback retry limits */
+ brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
+ brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
+
+ AND_REG(&regs->ifs_ctl, 0x0FFF);
+ W_REG(&regs->ifs_aifsn, EDCF_AIFSN_MIN);
+
+ /* init the tx dma engines */
+ for (i = 0; i < NFIFO; i++) {
+ if (wlc_hw->di[i])
+ dma_txinit(wlc_hw->di[i]);
+ }
+
+ /* init the rx dma engine(s) and post receive buffers */
+ dma_rxinit(wlc_hw->di[RX_FIFO]);
+ dma_rxfill(wlc_hw->di[RX_FIFO]);
+}
+
+void
+static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec,
+ bool mute) {
+ u32 macintmask;
+ 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)
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+ /* disable interrupts */
+ macintmask = brcms_intrsoff(wlc->wl);
+
+ /* set up the specified band and chanspec */
+ brcms_c_setxband(wlc_hw, chspec_bandunit(chanspec));
+ wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
+
+ /* do one-time phy inits and calibration */
+ wlc_phy_cal_init(wlc_hw->band->pi);
+
+ /* core-specific initialization */
+ brcms_b_coreinit(wlc);
+
+ /* suspend the tx fifos and mute the phy for preism cac time */
+ if (mute)
+ brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
+
+ /* band-specific inits */
+ brcms_b_bsinit(wlc, chanspec);
+
+ /* restore macintmask */
+ brcms_intrsrestore(wlc->wl, macintmask);
+
+ /* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac
+ * is suspended and brcms_c_enable_mac() will clear this override bit.
+ */
+ mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+
+ /*
+ * initialize mac_suspend_depth to 1 to match ucode
+ * initial suspended state
+ */
+ wlc_hw->mac_suspend_depth = 1;
+
+ /* restore the clk */
+ if (!fastclk)
+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc,
+ u16 chanspec)
+{
+ /* Save our copy of the chanspec */
+ wlc->chanspec = chanspec;
+
+ /* Set the chanspec and power limits for this locale */
+ brcms_c_channel_set_chanspec(wlc->cmi, chanspec, BRCMS_TXPWR_MAX);
+
+ if (wlc->stf->ss_algosel_auto)
+ brcms_c_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel,
+ chanspec);
+
+ brcms_c_stf_ss_update(wlc, wlc->band);
+}
+
+static void
+brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs)
+{
+ brcms_c_rateset_default(rs, NULL, wlc->band->phytype,
+ wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL,
+ (bool) (wlc->pub->_n_enab & SUPPORT_11N),
+ brcms_chspec_bw(wlc->default_bss->chanspec),
+ wlc->stf->txstreams);
+}
+
+/* derive wlc->band->basic_rate[] table from 'rateset' */
+static void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
+ struct brcms_c_rateset *rateset)
+{
+ u8 rate;
+ u8 mandatory;
+ u8 cck_basic = 0;
+ u8 ofdm_basic = 0;
+ u8 *br = wlc->band->basic_rate;
+ uint i;
+
+ /* incoming rates are in 500kbps units as in 802.11 Supported Rates */
+ memset(br, 0, BRCM_MAXRATE + 1);
+
+ /* For each basic rate in the rates list, make an entry in the
+ * best basic lookup.
+ */
+ for (i = 0; i < rateset->count; i++) {
+ /* only make an entry for a basic rate */
+ if (!(rateset->rates[i] & BRCMS_RATE_FLAG))
+ continue;
+
+ /* mask off basic bit */
+ rate = (rateset->rates[i] & BRCMS_RATE_MASK);
+
+ if (rate > BRCM_MAXRATE) {
+ wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: "
+ "invalid rate 0x%X in rate set\n",
+ rateset->rates[i]);
+ continue;
+ }
+
+ br[rate] = rate;
+ }
+
+ /* The rate lookup table now has non-zero entries for each
+ * basic rate, equal to the basic rate: br[basicN] = basicN
+ *
+ * To look up the best basic rate corresponding to any
+ * particular rate, code can use the basic_rate table
+ * like this
+ *
+ * basic_rate = wlc->band->basic_rate[tx_rate]
+ *
+ * Make sure there is a best basic rate entry for
+ * every rate by walking up the table from low rates
+ * to high, filling in holes in the lookup table
+ */
+
+ for (i = 0; i < wlc->band->hw_rateset.count; i++) {
+ rate = wlc->band->hw_rateset.rates[i];
+
+ if (br[rate] != 0) {
+ /* This rate is a basic rate.
+ * Keep track of the best basic rate so far by
+ * modulation type.
+ */
+ if (is_ofdm_rate(rate))
+ ofdm_basic = rate;
+ else
+ cck_basic = rate;
+
+ continue;
+ }
+
+ /* This rate is not a basic rate so figure out the
+ * best basic rate less than this rate and fill in
+ * the hole in the table
+ */
+
+ br[rate] = is_ofdm_rate(rate) ? ofdm_basic : cck_basic;
+
+ if (br[rate] != 0)
+ continue;
+
+ if (is_ofdm_rate(rate)) {
+ /*
+ * In 11g and 11a, the OFDM mandatory rates
+ * are 6, 12, and 24 Mbps
+ */
+ if (rate >= BRCM_RATE_24M)
+ mandatory = BRCM_RATE_24M;
+ else if (rate >= BRCM_RATE_12M)
+ mandatory = BRCM_RATE_12M;
+ else
+ mandatory = BRCM_RATE_6M;
+ } else {
+ /* In 11b, all CCK rates are mandatory 1 - 11 Mbps */
+ mandatory = rate;
+ }
+
+ br[rate] = mandatory;
+ }
+}
+
+static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
+ u16 chanspec)
+{
+ struct brcms_c_rateset default_rateset;
+ 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
+ */
+ if (wlc->bandlocked || wlc->pub->_nbands == 1) {
+ /* updated in brcms_c_bandlock() */
+ parkband = wlc->band->bandunit;
+ band_order[0] = band_order[1] = parkband;
+ } else {
+ /* park on the band of the specified chanspec */
+ parkband = chspec_bandunit(chanspec);
+
+ /* order so that parkband initialize last */
+ band_order[0] = parkband ^ 1;
+ band_order[1] = parkband;
+ }
+
+ /* make each band operational, software state init */
+ for (i = 0; i < wlc->pub->_nbands; i++) {
+ uint j = band_order[i];
+
+ wlc->band = wlc->bandstate[j];
+
+ brcms_default_rateset(wlc, &default_rateset);
+
+ /* fill in hw_rate */
+ brcms_c_rateset_filter(&default_rateset, &wlc->band->hw_rateset,
+ false, BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
+ (bool) (wlc->pub->_n_enab & SUPPORT_11N));
+
+ /* init basic rate lookup */
+ brcms_c_rate_lookup_init(wlc, &default_rateset);
+ }
+
+ /* sync up phy/radio chanspec */
+ brcms_c_set_phy_chanspec(wlc, chanspec);
+}
+
+static void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc)
+{
+ if (wlc->bcnmisc_monitor)
+ brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
+ else
+ brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, 0);
+}
+
+void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc)
+{
+ wlc->bcnmisc_monitor = promisc;
+ brcms_c_mac_bcn_promisc(wlc);
+}
+
+/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */
+static void brcms_c_mac_promisc(struct brcms_c_info *wlc)
+{
+ u32 promisc_bits = 0;
+
+ /*
+ * promiscuous mode just sets MCTL_PROMISC
+ * Note: APs get all BSS traffic without the need to set
+ * the MCTL_PROMISC bit since all BSS data traffic is
+ * directed at the AP
+ */
+ if (wlc->pub->promisc)
+ promisc_bits |= MCTL_PROMISC;
+
+ /* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL
+ * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is
+ * handled in brcms_c_mac_bcn_promisc()
+ */
+ if (wlc->monitor)
+ promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL;
+
+ brcms_b_mctrl(wlc->hw, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
+}
+
+/*
+ * ucode, hwmac update
+ * Channel dependent updates for ucode and hw
+ */
+static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc)
+{
+ /* enable or disable any active IBSSs depending on whether or not
+ * we are on the home channel
+ */
+ if (wlc->home_chanspec == wlc_phy_chanspec_get(wlc->band->pi)) {
+ if (wlc->pub->associated) {
+ /*
+ * BMAC_NOTE: This is something that should be fixed
+ * in ucode inits. I think that the ucode inits set
+ * up the bcn templates and shm values with a bogus
+ * beacon. This should not be done in the inits. If
+ * ucode needs to set up a beacon for testing, the
+ * test routines should write it down, not expect the
+ * inits to populate a bogus beacon.
+ */
+ if (BRCMS_PHY_11N_CAP(wlc->band))
+ brcms_b_write_shm(wlc->hw,
+ M_BCN_TXTSF_OFFSET, 0);
+ }
+ } else {
+ /* disable an active IBSS if we are not on the home channel */
+ }
+
+ /* update the various promisc bits */
+ brcms_c_mac_bcn_promisc(wlc);
+ brcms_c_mac_promisc(wlc);
+}
+
+static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate,
+ u8 basic_rate)
+{
+ u8 phy_rate, index;
+ u8 basic_phy_rate, basic_index;
+ u16 dir_table, basic_table;
+ u16 basic_ptr;
+
+ /* Shared memory address for the table we are reading */
+ dir_table = is_ofdm_rate(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
+
+ /* Shared memory address for the table we are writing */
+ basic_table = is_ofdm_rate(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
+
+ /*
+ * for a given rate, the LS-nibble of the PLCP SIGNAL field is
+ * the index into the rate table.
+ */
+ phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
+ basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK;
+ index = phy_rate & 0xf;
+ basic_index = basic_phy_rate & 0xf;
+
+ /* Find the SHM pointer to the ACK rate entry by looking in the
+ * Direct-map Table
+ */
+ basic_ptr = brcms_b_read_shm(wlc->hw, (dir_table + basic_index * 2));
+
+ /* Update the SHM BSS-basic-rate-set mapping table with the pointer
+ * to the correct basic rate for the given incoming rate
+ */
+ brcms_b_write_shm(wlc->hw, (basic_table + index * 2), basic_ptr);
+}
+
+static const struct brcms_c_rateset *
+brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc)
+{
+ const struct brcms_c_rateset *rs_dflt;
+
+ if (BRCMS_PHY_11N_CAP(wlc->band)) {
+ if (wlc->band->bandtype == BRCM_BAND_5G)
+ rs_dflt = &ofdm_mimo_rates;
+ else
+ rs_dflt = &cck_ofdm_mimo_rates;
+ } else if (wlc->band->gmode)
+ rs_dflt = &cck_ofdm_rates;
+ else
+ rs_dflt = &cck_rates;
+
+ return rs_dflt;
+}
+
+static void brcms_c_set_ratetable(struct brcms_c_info *wlc)
+{
+ const struct brcms_c_rateset *rs_dflt;
+ struct brcms_c_rateset rs;
+ u8 rate, basic_rate;
+ uint i;
+
+ rs_dflt = brcms_c_rateset_get_hwrs(wlc);
+
+ brcms_c_rateset_copy(rs_dflt, &rs);
+ brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+
+ /* walk the phy rate table and update SHM basic rate lookup table */
+ for (i = 0; i < rs.count; i++) {
+ rate = rs.rates[i] & BRCMS_RATE_MASK;
+
+ /* for a given rate brcms_basic_rate returns the rate at
+ * which a response ACK/CTS should be sent.
+ */
+ basic_rate = brcms_basic_rate(wlc, rate);
+ if (basic_rate == 0)
+ /* This should only happen if we are using a
+ * restricted rateset.
+ */
+ basic_rate = rs.rates[0] & BRCMS_RATE_MASK;
+
+ brcms_c_write_rate_shm(wlc, rate, basic_rate);
+ }
+}
+
+/* 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);
+
+ /* write ucode ACK/CTS rate table */
+ brcms_c_set_ratetable(wlc);
+
+ /* update some band specific mac configuration */
+ brcms_c_ucode_mac_upd(wlc);
+
+ /* init antenna selection */
+ brcms_c_antsel_init(wlc->asi);
+
+}
+
+/* formula: IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */
+static int
+brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
+ bool writeToShm)
+{
+ int idle_busy_ratio_x_16 = 0;
+ uint offset =
+ 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",
+ wlc->pub->unit);
+ return -EINVAL;
+ }
+ if (duty_cycle)
+ idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle;
+ /* Only write to shared memory when wl is up */
+ if (writeToShm)
+ brcms_b_write_shm(wlc->hw, offset, (u16) idle_busy_ratio_x_16);
+
+ if (isOFDM)
+ wlc->tx_duty_cycle_ofdm = (u16) duty_cycle;
+ else
+ wlc->tx_duty_cycle_cck = (u16) duty_cycle;
+
+ 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)
+{
+ u32 v1, v2;
+ bool hps;
+ bool awake_before;
+
+ hps = brcms_c_ps_allowed(wlc);
+
+ BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
+
+ v1 = R_REG(&wlc->regs->maccontrol);
+ v2 = MCTL_WAKE;
+ if (hps)
+ v2 |= MCTL_HPS;
+
+ brcms_b_mctrl(wlc->hw, MCTL_WAKE | MCTL_HPS, v2);
+
+ awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
+
+ if (!awake_before)
+ brcms_b_wait_for_wake(wlc->hw);
+}
+
+/*
+ * Write this BSS config's MAC address to core.
+ * Updates RXE match engine.
+ */
+static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg)
+{
+ int err = 0;
+ struct brcms_c_info *wlc = bsscfg->wlc;
+
+ /* enter the MAC addr into the RXE match registers */
+ brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr);
+
+ brcms_c_ampdu_macaddr_upd(wlc);
+
+ return err;
+}
+
+/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl).
+ * Updates RXE match engine.
+ */
+static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg)
+{
+ /* we need to update BSSID in RXE match registers */
+ brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID);
+}
+
+static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
+{
+ wlc_hw->shortslot = shortslot;
+
+ if (wlc_hw->band->bandtype == BRCM_BAND_2G && wlc_hw->up) {
+ brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+ brcms_b_update_slot_timing(wlc_hw, shortslot);
+ brcms_c_enable_mac(wlc_hw->wlc);
+ }
+}
+
+/*
+ * Suspend the the MAC and update the slot timing
+ * for standard 11b/g (20us slots) or shortslot 11g (9us slots).
+ */
+static void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
+{
+ /* use the override if it is set */
+ if (wlc->shortslot_override != BRCMS_SHORTSLOT_AUTO)
+ shortslot = (wlc->shortslot_override == BRCMS_SHORTSLOT_ON);
+
+ if (wlc->shortslot == shortslot)
+ return;
+
+ wlc->shortslot = shortslot;
+
+ brcms_b_set_shortslot(wlc->hw, shortslot);
+}
+
+static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
+{
+ if (wlc->home_chanspec != chanspec) {
+ wlc->home_chanspec = chanspec;
+
+ if (wlc->bsscfg->associated)
+ wlc->bsscfg->current_bss->chanspec = chanspec;
+ }
+}
+
+void
+brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
+ bool mute, struct txpwr_limits *txpwr)
+{
+ uint bandunit;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec);
+
+ wlc_hw->chanspec = chanspec;
+
+ /* Switch bands if necessary */
+ if (wlc_hw->_nbands > 1) {
+ bandunit = chspec_bandunit(chanspec);
+ if (wlc_hw->band->bandunit != bandunit) {
+ /* brcms_b_setband disables other bandunit,
+ * use light band switch if not up yet
+ */
+ if (wlc_hw->up) {
+ wlc_phy_chanspec_radio_set(wlc_hw->
+ bandstate[bandunit]->
+ pi, chanspec);
+ brcms_b_setband(wlc_hw, bandunit, chanspec);
+ } else {
+ brcms_c_setxband(wlc_hw, bandunit);
+ }
+ }
+ }
+
+ wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
+
+ if (!wlc_hw->up) {
+ if (wlc_hw->clk)
+ wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
+ chanspec);
+ wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
+ } else {
+ wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
+ wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
+
+ /* Update muting of the channel */
+ brcms_b_mute(wlc_hw, mute, 0);
+ }
+}
+
+/* switch to and initialize new band */
+static void brcms_c_setband(struct brcms_c_info *wlc,
+ uint bandunit)
+{
+ wlc->band = wlc->bandstate[bandunit];
+
+ if (!wlc->pub->up)
+ return;
+
+ /* wait for at least one beacon before entering sleeping state */
+ brcms_c_set_ps_ctrl(wlc);
+
+ /* band-specific initializations */
+ brcms_c_bsinit(wlc);
+}
+
+static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
+{
+ uint bandunit;
+ bool switchband = false;
+ 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",
+ wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec));
+ return;
+ }
+
+ /* Switch bands if necessary */
+ if (wlc->pub->_nbands > 1) {
+ bandunit = chspec_bandunit(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",
+ wlc->pub->unit, __func__,
+ CHSPEC_CHANNEL(chanspec));
+ return;
+ }
+ /*
+ * should the setband call come after the
+ * brcms_b_chanspec() ? if the setband updates
+ * (brcms_c_bsinit) use low level calls to inspect and
+ * set state, the state inspected may be from the wrong
+ * band, or the following brcms_b_set_chanspec() may
+ * undo the work.
+ */
+ brcms_c_setband(wlc, bandunit);
+ }
+ }
+
+ /* sync up phy/radio chanspec */
+ brcms_c_set_phy_chanspec(wlc, chanspec);
+
+ /* init antenna selection */
+ if (brcms_chspec_bw(old_chanspec) != brcms_chspec_bw(chanspec)) {
+ brcms_c_antsel_init(wlc->asi);
+
+ /* Fix the hardware rateset based on bw.
+ * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz
+ */
+ brcms_c_rateset_bw_mcs_filter(&wlc->band->hw_rateset,
+ wlc->band->mimo_cap_40 ? brcms_chspec_bw(chanspec) : 0);
+ }
+
+ /* update some mac configuration since chanspec changed */
+ brcms_c_ucode_mac_upd(wlc);
+}
+
+/*
+ * This function changes the phytxctl for beacon based on current
+ * beacon ratespec AND txant setting as per this table:
+ * ratespec CCK ant = wlc->stf->txant
+ * OFDM ant = 3
+ */
+void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
+ u32 bcn_rspec)
+{
+ u16 phyctl;
+ u16 phytxant = wlc->stf->phytxant;
+ u16 mask = PHY_TXC_ANT_MASK;
+
+ /* for non-siso rates or default setting, use the available chains */
+ if (BRCMS_PHY_11N_CAP(wlc->band))
+ phytxant = brcms_c_stf_phytxchain_sel(wlc, bcn_rspec);
+
+ phyctl = brcms_b_read_shm(wlc->hw, M_BCN_PCTLWD);
+ phyctl = (phyctl & ~mask) | phytxant;
+ brcms_b_write_shm(wlc->hw, M_BCN_PCTLWD, phyctl);
+}
+
+/*
+ * centralized protection config change function to simplify debugging, no
+ * consistency checking this should be called only on changes to avoid overhead
+ * in periodic function
+ */
+void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val)
+{
+ BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val);
+
+ switch (idx) {
+ case BRCMS_PROT_G_SPEC:
+ wlc->protection->_g = (bool) val;
+ break;
+ case BRCMS_PROT_G_OVR:
+ wlc->protection->g_override = (s8) val;
+ break;
+ case BRCMS_PROT_G_USER:
+ wlc->protection->gmode_user = (u8) val;
+ break;
+ case BRCMS_PROT_OVERLAP:
+ wlc->protection->overlap = (s8) val;
+ break;
+ case BRCMS_PROT_N_USER:
+ wlc->protection->nmode_user = (s8) val;
+ break;
+ case BRCMS_PROT_N_CFG:
+ wlc->protection->n_cfg = (s8) val;
+ break;
+ case BRCMS_PROT_N_CFG_OVR:
+ wlc->protection->n_cfg_override = (s8) val;
+ break;
+ case BRCMS_PROT_N_NONGF:
+ wlc->protection->nongf = (bool) val;
+ break;
+ case BRCMS_PROT_N_NONGF_OVR:
+ wlc->protection->nongf_override = (s8) val;
+ break;
+ case BRCMS_PROT_N_PAM_OVR:
+ wlc->protection->n_pam_override = (s8) val;
+ break;
+ case BRCMS_PROT_N_OBSS:
+ wlc->protection->n_obss = (bool) val;
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val)
+{
+ if (wlc->pub->up) {
+ brcms_c_update_beacon(wlc);
+ brcms_c_update_probe_resp(wlc, true);
+ }
+}
+
+static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val)
+{
+ wlc->stf->ldpc = val;
+
+ if (wlc->pub->up) {
+ brcms_c_update_beacon(wlc);
+ brcms_c_update_probe_resp(wlc, true);
+ wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false));
+ }
+}
+
+void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
+ const struct ieee80211_tx_queue_params *params,
+ bool suspend)
+{
+ int i;
+ struct shm_acparams acp_shm;
+ u16 *shm_entry;
+
+ /* 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__);
+ return;
+ }
+
+ memset((char *)&acp_shm, 0, sizeof(struct shm_acparams));
+ /* fill in shm ac params struct */
+ acp_shm.txop = params->txop;
+ /* convert from units of 32us to us for ucode */
+ wlc->edcf_txop[aci & 0x3] = acp_shm.txop =
+ EDCF_TXOP2USEC(acp_shm.txop);
+ acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK);
+
+ if (aci == AC_VI && acp_shm.txop == 0
+ && acp_shm.aifs < EDCF_AIFSN_MAX)
+ acp_shm.aifs++;
+
+ if (acp_shm.aifs < EDCF_AIFSN_MIN
+ || acp_shm.aifs > EDCF_AIFSN_MAX) {
+ wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad "
+ "aifs %d\n", wlc->pub->unit, acp_shm.aifs);
+ } else {
+ acp_shm.cwmin = params->cw_min;
+ acp_shm.cwmax = params->cw_max;
+ acp_shm.cwcur = acp_shm.cwmin;
+ acp_shm.bslots =
+ R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur;
+ acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
+ /* Indicate the new params to the ucode */
+ acp_shm.status = brcms_b_read_shm(wlc->hw, (M_EDCF_QINFO +
+ wme_ac2fifo[aci] *
+ M_EDCF_QLEN +
+ M_EDCF_STATUS_OFF));
+ acp_shm.status |= WME_STATUS_NEWAC;
+
+ /* Fill in shm acparam table */
+ shm_entry = (u16 *) &acp_shm;
+ for (i = 0; i < (int)sizeof(struct shm_acparams); i += 2)
+ brcms_b_write_shm(wlc->hw,
+ M_EDCF_QINFO +
+ wme_ac2fifo[aci] * M_EDCF_QLEN + i,
+ *shm_entry++);
+ }
+
+ if (suspend) {
+ brcms_c_suspend_mac_and_wait(wlc);
+ brcms_c_enable_mac(wlc);
+ }
+}
+
+void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
+{
+ u16 aci;
+ int i_ac;
+ struct ieee80211_tx_queue_params txq_pars;
+ static const struct edcf_acparam default_edcf_acparams[] = {
+ {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA, EDCF_AC_BE_TXOP_STA},
+ {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA, EDCF_AC_BK_TXOP_STA},
+ {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA, EDCF_AC_VI_TXOP_STA},
+ {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA, EDCF_AC_VO_TXOP_STA}
+ }; /* ucode needs these parameters during its initialization */
+ const struct edcf_acparam *edcf_acp = &default_edcf_acparams[0];
+
+ for (i_ac = 0; i_ac < AC_COUNT; i_ac++, edcf_acp++) {
+ /* find out which ac this set of params applies to */
+ aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT;
+
+ /* fill in shm ac params struct */
+ txq_pars.txop = edcf_acp->TXOP;
+ txq_pars.aifs = edcf_acp->ACI;
+
+ /* CWmin = 2^(ECWmin) - 1 */
+ txq_pars.cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK);
+ /* CWmax = 2^(ECWmax) - 1 */
+ txq_pars.cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK)
+ >> EDCF_ECWMAX_SHIFT);
+ brcms_c_wme_setparams(wlc, aci, &txq_pars, suspend);
+ }
+
+ if (suspend) {
+ brcms_c_suspend_mac_and_wait(wlc);
+ brcms_c_enable_mac(wlc);
+ }
+}
+
+/* maintain LED behavior in down state */
+static void brcms_c_down_led_upd(struct brcms_c_info *wlc)
+{
+ /*
+ * maintain LEDs while in down state, turn on sbclk if
+ * not available yet. Turn on sbclk if necessary
+ */
+ brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_FLIP);
+ brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_FLIP);
+}
+
+static void brcms_c_radio_monitor_start(struct brcms_c_info *wlc)
+{
+ /* Don't start the timer if HWRADIO feature is disabled */
+ if (wlc->radio_monitor)
+ return;
+
+ wlc->radio_monitor = true;
+ brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_RADIO_MON);
+ brcms_add_timer(wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true);
+}
+
+static void brcms_c_radio_disable(struct brcms_c_info *wlc)
+{
+ if (!wlc->pub->up) {
+ brcms_c_down_led_upd(wlc);
+ return;
+ }
+
+ brcms_c_radio_monitor_start(wlc);
+ brcms_down(wlc->wl);
+}
+
+static void brcms_c_radio_enable(struct brcms_c_info *wlc)
+{
+ if (wlc->pub->up)
+ return;
+
+ if (brcms_deviceremoved(wlc))
+ return;
+
+ brcms_up(wlc->wl);
+}
+
+static bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc)
+{
+ if (!wlc->radio_monitor)
+ return true;
+
+ wlc->radio_monitor = false;
+ brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_RADIO_MON);
+ return brcms_del_timer(wlc->radio_timer);
+}
+
+/* read hwdisable state and propagate to wlc flag */
+static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc)
+{
+ if (wlc->pub->hw_off)
+ return;
+
+ if (brcms_b_radio_read_hwdisabled(wlc->hw))
+ mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
+ else
+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
+}
+
+/*
+ * centralized radio disable/enable function,
+ * invoke radio enable/disable after updating hwradio status
+ */
+static void brcms_c_radio_upd(struct brcms_c_info *wlc)
+{
+ if (wlc->pub->radio_disabled)
+ brcms_c_radio_disable(wlc);
+ else
+ brcms_c_radio_enable(wlc);
+}
+
+/* update hwradio status and return it */
+bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc)
+{
+ brcms_c_radio_hwdisable_upd(wlc);
+
+ return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ?
+ true : false;
+}
+
+/* periodical query hw radio button while driver is "down" */
+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_down(wlc->wl);
+ return;
+ }
+
+ /* cap mpc off count */
+ if (wlc->mpc_offcnt < BRCMS_MPC_MAX_DELAYCNT)
+ wlc->mpc_offcnt++;
+
+ brcms_c_radio_hwdisable_upd(wlc);
+ brcms_c_radio_upd(wlc);
+}
+
+/* common low-level watchdog code */
+static void brcms_b_watchdog(void *arg)
+{
+ struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
+ struct brcms_hardware *wlc_hw = wlc->hw;
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ if (!wlc_hw->up)
+ return;
+
+ /* increment second count */
+ wlc_hw->now++;
+
+ /* Check for FIFO error interrupts */
+ brcms_b_fifoerrors(wlc_hw);
+
+ /* make sure RX dma has buffers */
+ dma_rxfill(wlc->hw->di[RX_FIFO]);
+
+ wlc_phy_watchdog(wlc_hw->band->pi);
+}
+
+static void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc)
+{
+ bool mpc_radio, radio_state;
+
+ /*
+ * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
+ * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
+ * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
+ * the radio is going down.
+ */
+ if (!wlc->mpc) {
+ if (!wlc->pub->radio_disabled)
+ return;
+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
+ brcms_c_radio_upd(wlc);
+ if (!wlc->pub->radio_disabled)
+ brcms_c_radio_monitor_stop(wlc);
+ return;
+ }
+
+ /*
+ * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in
+ * wlc->pub->radio_disabled to go ON, always call radio_upd
+ * synchronously to go OFF, postpone radio_upd to later when
+ * context is safe(e.g. watchdog)
+ */
+ radio_state =
+ (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
+ ON);
+ mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON;
+
+ if (radio_state == ON && mpc_radio == OFF)
+ wlc->mpc_delay_off = wlc->mpc_dlycnt;
+ else if (radio_state == OFF && mpc_radio == ON) {
+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
+ brcms_c_radio_upd(wlc);
+ if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD)
+ wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT;
+ else
+ wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
+ }
+ /*
+ * Below logic is meant to capture the transition from mpc off
+ * to mpc on for reasons other than wlc->mpc_delay_off keeping
+ * the mpc off. In that case reset wlc->mpc_delay_off to
+ * wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
+ */
+ if ((wlc->prev_non_delay_mpc == false) &&
+ (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off)
+ wlc->mpc_delay_off = wlc->mpc_dlycnt;
+
+ wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc);
+}
+
+/* common watchdog code */
+static void brcms_c_watchdog(void *arg)
+{
+ struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
+
+ BCMMSG(wlc->wiphy, "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_down(wlc->wl);
+ return;
+ }
+
+ /* increment second count */
+ wlc->pub->now++;
+
+ /* delay radio disable */
+ if (wlc->mpc_delay_off) {
+ if (--wlc->mpc_delay_off == 0) {
+ mboolset(wlc->pub->radio_disabled,
+ WL_RADIO_MPC_DISABLE);
+ if (wlc->mpc && brcms_c_ismpc(wlc))
+ wlc->mpc_offcnt = 0;
+ }
+ }
+
+ /* mpc sync */
+ brcms_c_radio_mpc_upd(wlc);
+ /* radio sync: sw/hw/mpc --> radio_disable/radio_enable */
+ brcms_c_radio_hwdisable_upd(wlc);
+ brcms_c_radio_upd(wlc);
+ /* if radio is disable, driver may be down, quit here */
+ if (wlc->pub->radio_disabled)
+ return;
+
+ brcms_b_watchdog(wlc);
+
+ /*
+ * occasionally sample mac stat counters to
+ * detect 16-bit counter wrap
+ */
+ if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0)
+ brcms_c_statsupd(wlc);
+
+ if (BRCMS_ISNPHY(wlc->band) &&
+ ((wlc->pub->now - wlc->tempsense_lasttime) >=
+ BRCMS_TEMPSENSE_PERIOD)) {
+ wlc->tempsense_lasttime = wlc->pub->now;
+ brcms_c_tempsense_upd(wlc);
+ }
+}
+
+static void brcms_c_watchdog_by_timer(void *arg)
+{
+ brcms_c_watchdog(arg);
+}
+
+static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
+{
+ wlc->wdtimer = brcms_init_timer(wlc->wl, brcms_c_watchdog_by_timer,
+ wlc, "watchdog");
+ if (!wlc->wdtimer) {
+ wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for wdtimer "
+ "failed\n", unit);
+ goto fail;
+ }
+
+ wlc->radio_timer = brcms_init_timer(wlc->wl, brcms_c_radio_timer,
+ wlc, "radio");
+ if (!wlc->radio_timer) {
+ wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for radio_timer "
+ "failed\n", unit);
+ goto fail;
+ }
+
+ return true;
+
+ fail:
+ return false;
+}
+
+/*
+ * Initialize brcms_c_info default values ...
+ * may get overrides later in this function
+ */
+static void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
+{
+ int i;
+
+ /* Save our copy of the chanspec */
+ wlc->chanspec = ch20mhz_chspec(1);
+
+ /* various 802.11g modes */
+ wlc->shortslot = false;
+ wlc->shortslot_override = BRCMS_SHORTSLOT_AUTO;
+
+ brcms_c_protection_upd(wlc, BRCMS_PROT_G_OVR, BRCMS_PROTECTION_AUTO);
+ brcms_c_protection_upd(wlc, BRCMS_PROT_G_SPEC, false);
+
+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG_OVR,
+ BRCMS_PROTECTION_AUTO);
+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG, BRCMS_N_PROTECTION_OFF);
+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF_OVR,
+ BRCMS_PROTECTION_AUTO);
+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF, false);
+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, AUTO);
+
+ brcms_c_protection_upd(wlc, BRCMS_PROT_OVERLAP,
+ BRCMS_PROTECTION_CTL_OVERLAP);
+
+ /* 802.11g draft 4.0 NonERP elt advertisement */
+ wlc->include_legacy_erp = true;
+
+ wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF;
+ wlc->stf->txant = ANT_TX_DEF;
+
+ wlc->prb_resp_timeout = BRCMS_PRB_RESP_TIMEOUT;
+
+ wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN;
+ for (i = 0; i < NFIFO; i++)
+ wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN;
+ wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN;
+
+ /* default rate fallback retry limits */
+ wlc->SFBL = RETRY_SHORT_FB;
+ wlc->LFBL = RETRY_LONG_FB;
+
+ /* default mac retry limits */
+ wlc->SRL = RETRY_SHORT_DEF;
+ wlc->LRL = RETRY_LONG_DEF;
+
+ /* WME QoS mode is Auto by default */
+ wlc->pub->_ampdu = AMPDU_AGG_HOST;
+ wlc->pub->bcmerror = 0;
+
+ /* initialize mpc delay */
+ wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
+}
+
+static uint brcms_c_attach_module(struct brcms_c_info *wlc)
+{
+ uint err = 0;
+ uint unit;
+ unit = wlc->pub->unit;
+
+ wlc->asi = brcms_c_antsel_attach(wlc);
+ if (wlc->asi == NULL) {
+ wiphy_err(wlc->wiphy, "wl%d: attach: antsel_attach "
+ "failed\n", unit);
+ err = 44;
+ goto fail;
+ }
+
+ wlc->ampdu = brcms_c_ampdu_attach(wlc);
+ if (wlc->ampdu == NULL) {
+ wiphy_err(wlc->wiphy, "wl%d: attach: ampdu_attach "
+ "failed\n", unit);
+ err = 50;
+ goto fail;
+ }
+
+ if ((brcms_c_stf_attach(wlc) != 0)) {
+ wiphy_err(wlc->wiphy, "wl%d: attach: stf_attach "
+ "failed\n", unit);
+ err = 68;
+ goto fail;
+ }
+ fail:
+ return err;
+}
+
+struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc)
+{
+ return wlc->pub;
+}
+
+/* low level attach
+ * run backplane attach, init nvram
+ * run phy attach
+ * initialize software state for each core and band
+ * put the whole chip in reset(driver down state), no clock
+ */
+static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
+ uint unit, bool piomode, void __iomem *regsva,
+ struct pci_dev *btparam)
+{
+ struct brcms_hardware *wlc_hw;
+ struct d11regs __iomem *regs;
+ char *macaddr = NULL;
+ uint err = 0;
+ uint j;
+ bool wme = false;
+ struct shared_phy_params sha_params;
+ struct wiphy *wiphy = wlc->wiphy;
+
+ BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor,
+ device);
+
+ wme = true;
+
+ wlc_hw = wlc->hw;
+ wlc_hw->wlc = wlc;
+ wlc_hw->unit = unit;
+ wlc_hw->band = wlc_hw->bandstate[0];
+ wlc_hw->_piomode = piomode;
+
+ /* populate struct brcms_hardware with default values */
+ brcms_b_info_init(wlc_hw);
+
+ /*
+ * Do the hardware portion of the attach. Also initialize software
+ * state that depends on the particular hardware we are running.
+ */
+ wlc_hw->sih = ai_attach(regsva, btparam);
+ if (wlc_hw->sih == NULL) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n",
+ unit);
+ err = 11;
+ goto fail;
+ }
+
+ /* verify again the device is supported */
+ if (!brcms_c_chipmatch(vendor, device)) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported "
+ "vendor/device (0x%x/0x%x)\n",
+ unit, vendor, device);
+ err = 12;
+ goto fail;
+ }
+
+ wlc_hw->vendorid = vendor;
+ wlc_hw->deviceid = device;
+
+ /* set bar0 window to point at D11 core */
+ wlc_hw->regs = (struct d11regs __iomem *)
+ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
+ wlc_hw->corerev = ai_corerev(wlc_hw->sih);
+
+ regs = wlc_hw->regs;
+
+ wlc->regs = wlc_hw->regs;
+
+ /* validate chip, chiprev and corerev */
+ if (!brcms_c_isgoodchip(wlc_hw)) {
+ err = 13;
+ goto fail;
+ }
+
+ /* initialize power control registers */
+ ai_clkctl_init(wlc_hw->sih);
+
+ /* request fastclock and force fastclock for the rest of attach
+ * bring the d11 core out of reset.
+ * For PMU chips, the first wlc_clkctl_clk is no-op since core-clk
+ * is still false; But it will be called again inside wlc_corereset,
+ * after d11 is out of reset.
+ */
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
+
+ if (!brcms_b_validate_chip_access(wlc_hw)) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access "
+ "failed\n", unit);
+ err = 14;
+ goto fail;
+ }
+
+ /* get the board rev, used just below */
+ j = getintvar(wlc_hw->sih, BRCMS_SROM_BOARDREV);
+ /* promote srom boardrev of 0xFF to 1 */
+ if (j == BOARDREV_PROMOTABLE)
+ j = BOARDREV_PROMOTED;
+ wlc_hw->boardrev = (u16) j;
+ if (!brcms_c_validboardtype(wlc_hw)) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom "
+ "board type (0x%x)" " or revision level (0x%x)\n",
+ unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
+ err = 15;
+ goto fail;
+ }
+ wlc_hw->sromrev = (u8) getintvar(wlc_hw->sih, BRCMS_SROM_REV);
+ wlc_hw->boardflags = (u32) getintvar(wlc_hw->sih,
+ BRCMS_SROM_BOARDFLAGS);
+ wlc_hw->boardflags2 = (u32) getintvar(wlc_hw->sih,
+ BRCMS_SROM_BOARDFLAGS2);
+
+ if (wlc_hw->boardflags & BFL_NOPLLDOWN)
+ brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED);
+
+ /* check device id(srom, nvram etc.) to set bands */
+ if (wlc_hw->deviceid == BCM43224_D11N_ID ||
+ wlc_hw->deviceid == BCM43224_D11N_ID_VEN1)
+ /* Dualband boards */
+ wlc_hw->_nbands = 2;
+ else
+ wlc_hw->_nbands = 1;
+
+ if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
+ wlc_hw->_nbands = 1;
+
+ /* BMAC_NOTE: remove init of pub values when brcms_c_attach()
+ * unconditionally does the init of these values
+ */
+ wlc->vendorid = wlc_hw->vendorid;
+ wlc->deviceid = wlc_hw->deviceid;
+ wlc->pub->sih = wlc_hw->sih;
+ wlc->pub->corerev = wlc_hw->corerev;
+ wlc->pub->sromrev = wlc_hw->sromrev;
+ wlc->pub->boardrev = wlc_hw->boardrev;
+ wlc->pub->boardflags = wlc_hw->boardflags;
+ wlc->pub->boardflags2 = wlc_hw->boardflags2;
+ wlc->pub->_nbands = wlc_hw->_nbands;
+
+ wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
+
+ if (wlc_hw->physhim == NULL) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach "
+ "failed\n", unit);
+ err = 25;
+ goto fail;
+ }
+
+ /* pass all the parameters to wlc_phy_shared_attach in one struct */
+ sha_params.sih = wlc_hw->sih;
+ sha_params.physhim = wlc_hw->physhim;
+ sha_params.unit = unit;
+ sha_params.corerev = wlc_hw->corerev;
+ sha_params.vid = wlc_hw->vendorid;
+ sha_params.did = wlc_hw->deviceid;
+ sha_params.chip = wlc_hw->sih->chip;
+ sha_params.chiprev = wlc_hw->sih->chiprev;
+ sha_params.chippkg = wlc_hw->sih->chippkg;
+ sha_params.sromrev = wlc_hw->sromrev;
+ sha_params.boardtype = wlc_hw->sih->boardtype;
+ sha_params.boardrev = wlc_hw->boardrev;
+ sha_params.boardvendor = wlc_hw->sih->boardvendor;
+ sha_params.boardflags = wlc_hw->boardflags;
+ sha_params.boardflags2 = wlc_hw->boardflags2;
+ sha_params.buscorerev = wlc_hw->sih->buscorerev;
+
+ /* alloc and save pointer to shared phy state area */
+ wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
+ if (!wlc_hw->phy_sh) {
+ err = 16;
+ goto fail;
+ }
+
+ /* initialize software state for each core and band */
+ for (j = 0; j < wlc_hw->_nbands; j++) {
+ /*
+ * band0 is always 2.4Ghz
+ * band1, if present, is 5Ghz
+ */
+
+ brcms_c_setxband(wlc_hw, j);
+
+ wlc_hw->band->bandunit = j;
+ wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
+ wlc->band->bandunit = j;
+ wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
+ wlc->core->coreidx = ai_coreidx(wlc_hw->sih);
+
+ wlc_hw->machwcap = R_REG(&regs->machwcap);
+ wlc_hw->machwcap_backup = wlc_hw->machwcap;
+
+ /* init tx fifo size */
+ wlc_hw->xmtfifo_sz =
+ xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
+
+ /* Get a phy for this band */
+ wlc_hw->band->pi =
+ wlc_phy_attach(wlc_hw->phy_sh, regs,
+ wlc_hw->band->bandtype,
+ wlc->wiphy);
+ if (wlc_hw->band->pi == NULL) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_"
+ "attach failed\n", unit);
+ err = 17;
+ goto fail;
+ }
+
+ wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
+
+ wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
+ &wlc_hw->band->phyrev,
+ &wlc_hw->band->radioid,
+ &wlc_hw->band->radiorev);
+ wlc_hw->band->abgphy_encore =
+ wlc_phy_get_encore(wlc_hw->band->pi);
+ wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
+ wlc_hw->band->core_flags =
+ wlc_phy_get_coreflags(wlc_hw->band->pi);
+
+ /* verify good phy_type & supported phy revision */
+ if (BRCMS_ISNPHY(wlc_hw->band)) {
+ if (NCONF_HAS(wlc_hw->band->phyrev))
+ goto good_phy;
+ else
+ goto bad_phy;
+ } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+ if (LCNCONF_HAS(wlc_hw->band->phyrev))
+ goto good_phy;
+ else
+ goto bad_phy;
+ } else {
+ bad_phy:
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported "
+ "phy type/rev (%d/%d)\n", unit,
+ wlc_hw->band->phytype, wlc_hw->band->phyrev);
+ err = 18;
+ goto fail;
+ }
+
+ good_phy:
+ /*
+ * BMAC_NOTE: wlc->band->pi should not be set below and should
+ * be done in the high level attach. However we can not make
+ * that change until all low level access is changed to
+ * wlc_hw->band->pi. Instead do the wlc->band->pi init below,
+ * keeping wlc_hw->band->pi as well for incremental update of
+ * low level fns, and cut over low only init when all fns
+ * updated.
+ */
+ wlc->band->pi = wlc_hw->band->pi;
+ wlc->band->phytype = wlc_hw->band->phytype;
+ wlc->band->phyrev = wlc_hw->band->phyrev;
+ wlc->band->radioid = wlc_hw->band->radioid;
+ wlc->band->radiorev = wlc_hw->band->radiorev;
+
+ /* default contention windows size limits */
+ wlc_hw->band->CWmin = APHY_CWMIN;
+ wlc_hw->band->CWmax = PHY_CWMAX;
+
+ if (!brcms_b_attach_dmapio(wlc, j, wme)) {
+ err = 19;
+ goto fail;
+ }
+ }
+
+ /* disable core to match driver "down" state */
+ brcms_c_coredisable(wlc_hw);
+
+ /* Match driver "down" state */
+ ai_pci_down(wlc_hw->sih);
+
+ /* register sb interrupt callback functions */
+ ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff,
+ (void *)brcms_c_wlintrsrestore, NULL, wlc);
+
+ /* turn off pll and xtal to match driver "down" state */
+ brcms_b_xtal(wlc_hw, OFF);
+
+ /* *******************************************************************
+ * The hardware is in the DOWN state at this point. D11 core
+ * or cores are in reset with clocks off, and the board PLLs
+ * are off if possible.
+ *
+ * Beyond this point, wlc->sbclk == false and chip registers
+ * should not be touched.
+ *********************************************************************
+ */
+
+ /* init etheraddr state variables */
+ macaddr = brcms_c_get_macaddr(wlc_hw);
+ if (macaddr == NULL) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n",
+ unit);
+ err = 21;
+ goto fail;
+ }
+ if (!mac_pton(macaddr, wlc_hw->etheraddr) ||
+ is_broadcast_ether_addr(wlc_hw->etheraddr) ||
+ is_zero_ether_addr(wlc_hw->etheraddr)) {
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n",
+ unit, macaddr);
+ err = 22;
+ goto fail;
+ }
+
+ BCMMSG(wlc->wiphy,
+ "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
+ wlc_hw->deviceid, wlc_hw->_nbands,
+ wlc_hw->sih->boardtype, macaddr);
+
+ return err;
+
+ fail:
+ wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit,
+ err);
+ return err;
+}
+
+static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc)
+{
+ uint unit;
+ unit = wlc->pub->unit;
+
+ if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
+ /* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
+ wlc->band->antgain = 8;
+ } else if (wlc->band->antgain == -1) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
+ " srom, using 2dB\n", unit, __func__);
+ wlc->band->antgain = 8;
+ } else {
+ s8 gain, fract;
+ /* Older sroms specified gain in whole dbm only. In order
+ * be able to specify qdbm granularity and remain backward
+ * compatible the whole dbms are now encoded in only
+ * low 6 bits and remaining qdbms are encoded in the hi 2 bits.
+ * 6 bit signed number ranges from -32 - 31.
+ *
+ * Examples:
+ * 0x1 = 1 db,
+ * 0xc1 = 1.75 db (1 + 3 quarters),
+ * 0x3f = -1 (-1 + 0 quarters),
+ * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm.
+ * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm.
+ */
+ gain = wlc->band->antgain & 0x3f;
+ gain <<= 2; /* Sign extend */
+ gain >>= 2;
+ fract = (wlc->band->antgain & 0xc0) >> 6;
+ wlc->band->antgain = 4 * gain + fract;
+ }
+}
+
+static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
+{
+ int aa;
+ uint unit;
+ int bandtype;
+ struct si_pub *sih = wlc->hw->sih;
+
+ unit = wlc->pub->unit;
+ bandtype = wlc->band->bandtype;
+
+ /* get antennas available */
+ if (bandtype == BRCM_BAND_5G)
+ aa = (s8) getintvar(sih, BRCMS_SROM_AA5G);
+ else
+ aa = (s8) getintvar(sih, BRCMS_SROM_AA2G);
+
+ if ((aa < 1) || (aa > 15)) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
+ " srom (0x%x), using 3\n", unit, __func__, aa);
+ aa = 3;
+ }
+
+ /* reset the defaults if we have a single antenna */
+ if (aa == 1) {
+ wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0;
+ wlc->stf->txant = ANT_TX_FORCE_0;
+ } else if (aa == 2) {
+ wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1;
+ wlc->stf->txant = ANT_TX_FORCE_1;
+ } else {
+ }
+
+ /* Compute Antenna Gain */
+ if (bandtype == BRCM_BAND_5G)
+ wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG1);
+ else
+ wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG0);
+
+ brcms_c_attach_antgain_init(wlc);
+
+ return true;
+}
+
+static void brcms_c_bss_default_init(struct brcms_c_info *wlc)
+{
+ u16 chanspec;
+ struct brcms_band *band;
+ struct brcms_bss_info *bi = wlc->default_bss;
+
+ /* init default and target BSS with some sane initial values */
+ memset((char *)(bi), 0, sizeof(struct brcms_bss_info));
+ bi->beacon_period = BEACON_INTERVAL_DEFAULT;
+
+ /* fill the default channel as the first valid channel
+ * starting from the 2G channels
+ */
+ chanspec = ch20mhz_chspec(1);
+ wlc->home_chanspec = bi->chanspec = chanspec;
+
+ /* find the band of our default channel */
+ band = wlc->band;
+ if (wlc->pub->_nbands > 1 &&
+ band->bandunit != chspec_bandunit(chanspec))
+ band = wlc->bandstate[OTHERBANDUNIT(wlc)];
+
+ /* init bss rates to the band specific default rate set */
+ brcms_c_rateset_default(&bi->rateset, NULL, band->phytype,
+ band->bandtype, false, BRCMS_RATE_MASK_FULL,
+ (bool) (wlc->pub->_n_enab & SUPPORT_11N),
+ brcms_chspec_bw(chanspec), wlc->stf->txstreams);
+
+ if (wlc->pub->_n_enab & SUPPORT_11N)
+ 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;
+ struct brcms_band *band;
+
+ for (i = 0; i < wlc->pub->_nbands; i++) {
+ band = wlc->bandstate[i];
+ if (band->bandtype == BRCM_BAND_5G) {
+ if ((bwcap == BRCMS_N_BW_40ALL)
+ || (bwcap == BRCMS_N_BW_20IN2G_40IN5G))
+ band->mimo_cap_40 = true;
+ else
+ band->mimo_cap_40 = false;
+ } else {
+ if (bwcap == BRCMS_N_BW_40ALL)
+ band->mimo_cap_40 = true;
+ else
+ band->mimo_cap_40 = false;
+ }
+ }
+}
+
+static void brcms_c_timers_deinit(struct brcms_c_info *wlc)
+{
+ /* free timer state */
+ if (wlc->wdtimer) {
+ brcms_free_timer(wlc->wdtimer);
+ wlc->wdtimer = NULL;
+ }
+ if (wlc->radio_timer) {
+ brcms_free_timer(wlc->radio_timer);
+ wlc->radio_timer = NULL;
+ }
+}
+
+static void brcms_c_detach_module(struct brcms_c_info *wlc)
+{
+ if (wlc->asi) {
+ brcms_c_antsel_detach(wlc->asi);
+ wlc->asi = NULL;
+ }
+
+ if (wlc->ampdu) {
+ brcms_c_ampdu_detach(wlc->ampdu);
+ wlc->ampdu = NULL;
+ }
+
+ brcms_c_stf_detach(wlc);
+}
+
+/*
+ * low level detach
+ */
+static int brcms_b_detach(struct brcms_c_info *wlc)
+{
+ uint i;
+ struct brcms_hw_band *band;
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ int callbacks;
+
+ callbacks = 0;
+
+ if (wlc_hw->sih) {
+ /*
+ * detach interrupt sync mechanism since interrupt is disabled
+ * and per-port interrupt object may has been freed. this must
+ * be done before sb core switch
+ */
+ ai_deregister_intr_callback(wlc_hw->sih);
+ ai_pci_sleep(wlc_hw->sih);
+ }
+
+ brcms_b_detach_dmapio(wlc_hw);
+
+ band = wlc_hw->band;
+ for (i = 0; i < wlc_hw->_nbands; i++) {
+ if (band->pi) {
+ /* Detach this band's phy */
+ wlc_phy_detach(band->pi);
+ band->pi = NULL;
+ }
+ band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
+ }
+
+ /* Free shared phy state */
+ kfree(wlc_hw->phy_sh);
+
+ wlc_phy_shim_detach(wlc_hw->physhim);
+
+ if (wlc_hw->sih) {
+ ai_detach(wlc_hw->sih);
+ wlc_hw->sih = NULL;
+ }
+
+ return callbacks;
+
+}
+
+/*
+ * Return a count of the number of driver callbacks still pending.
+ *
+ * General policy is that brcms_c_detach can only dealloc/free software states.
+ * It can NOT touch hardware registers since the d11core may be in reset and
+ * clock may not be available.
+ * One exception is sb register access, which is possible if crystal is turned
+ * on after "down" state, driver should avoid software timer with the exception
+ * of radio_monitor.
+ */
+uint brcms_c_detach(struct brcms_c_info *wlc)
+{
+ uint callbacks = 0;
+
+ if (wlc == NULL)
+ return 0;
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+ callbacks += brcms_b_detach(wlc);
+
+ /* delete software timers */
+ if (!brcms_c_radio_monitor_stop(wlc))
+ callbacks++;
+
+ brcms_c_channel_mgr_detach(wlc->cmi);
+
+ brcms_c_timers_deinit(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;
+}
+
+/* update state that depends on the current value of "ap" */
+static void brcms_c_ap_upd(struct brcms_c_info *wlc)
+{
+ /* STA-BSS; short capable */
+ wlc->PLCPHdr_override = BRCMS_PLCP_SHORT;
+
+ /* fixup mpc */
+ wlc->mpc = true;
+}
+
+/* Initialize just the hardware when coming out of POR or S3/S5 system states */
+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);
+
+ /*
+ * Enable pll and xtal, initialize the power control registers,
+ * and force fastclock for the remainder of brcms_c_up().
+ */
+ brcms_b_xtal(wlc_hw, ON);
+ ai_clkctl_init(wlc_hw->sih);
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+ ai_pci_fixcfg(wlc_hw->sih);
+
+ /*
+ * AI chip doesn't restore bar0win2 on
+ * hibernation/resume, need sw fixup
+ */
+ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+ (wlc_hw->sih->chip == BCM43225_CHIP_ID))
+ wlc_hw->regs = (struct d11regs __iomem *)
+ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
+
+ /*
+ * Inform phy that a POR reset has occurred so
+ * it does a complete phy init
+ */
+ wlc_phy_por_inform(wlc_hw->band->pi);
+
+ wlc_hw->ucode_loaded = false;
+ wlc_hw->wlc->pub->hw_up = true;
+
+ if ((wlc_hw->boardflags & BFL_FEM)
+ && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
+ if (!
+ (wlc_hw->boardrev >= 0x1250
+ && (wlc_hw->boardflags & BFL_FEM_BT)))
+ ai_epa_4313war(wlc_hw->sih);
+ }
+}
+
+static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
+{
+ uint coremask;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+ /*
+ * Enable pll and xtal, initialize the power control registers,
+ * and force fastclock for the remainder of brcms_c_up().
+ */
+ brcms_b_xtal(wlc_hw, ON);
+ ai_clkctl_init(wlc_hw->sih);
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+ /*
+ * Configure pci/pcmcia here instead of in brcms_c_attach()
+ * to allow mfg hotswap: down, hotswap (chip power cycle), up.
+ */
+ coremask = (1 << wlc_hw->wlc->core->coreidx);
+
+ ai_pci_setup(wlc_hw->sih, coremask);
+
+ /*
+ * Need to read the hwradio status here to cover the case where the
+ * system is loaded with the hw radio disabled. We do not want to
+ * bring the driver up in this case.
+ */
+ if (brcms_b_radio_read_hwdisabled(wlc_hw)) {
+ /* put SB PCI in down state again */
+ ai_pci_down(wlc_hw->sih);
+ brcms_b_xtal(wlc_hw, OFF);
+ return -ENOMEDIUM;
+ }
+
+ ai_pci_up(wlc_hw->sih);
+
+ /* reset the d11 core */
+ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
+
+ return 0;
+}
+
+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);
+
+ /* FULLY enable dynamic power control and d11 core interrupt */
+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+ brcms_intrson(wlc_hw->wlc->wl);
+ return 0;
+}
+
+/*
+ * Write WME tunable parameters for retransmit/max rate
+ * from wlc struct to ucode
+ */
+static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
+{
+ int ac;
+
+ /* Need clock to do this */
+ if (!wlc->clk)
+ return;
+
+ for (ac = 0; ac < AC_COUNT; ac++)
+ brcms_b_write_shm(wlc->hw, M_AC_TXLMT_ADDR(ac),
+ wlc->wme_retries[ac]);
+}
+
+/* make interface operational */
+int brcms_c_up(struct brcms_c_info *wlc)
+{
+ BCMMSG(wlc->wiphy, "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))
+ return -ENOMEDIUM;
+
+ if (!wlc->pub->hw_up) {
+ brcms_b_hw_up(wlc->hw);
+ wlc->pub->hw_up = true;
+ }
+
+ if ((wlc->pub->boardflags & BFL_FEM)
+ && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) {
+ if (wlc->pub->boardrev >= 0x1250
+ && (wlc->pub->boardflags & BFL_FEM_BT))
+ brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL,
+ MHF5_4313_GPIOCTRL, BRCM_BAND_ALL);
+ else
+ brcms_b_mhf(wlc->hw, MHF4, MHF4_EXTPA_ENABLE,
+ MHF4_EXTPA_ENABLE, BRCM_BAND_ALL);
+ }
+
+ /*
+ * Need to read the hwradio status here to cover the case where the
+ * system is loaded with the hw radio disabled. We do not want to bring
+ * the driver up in this case. If radio is disabled, abort up, lower
+ * power, start radio timer and return 0(for NDIS) don't call
+ * radio_update to avoid looping brcms_c_up.
+ *
+ * brcms_b_up_prep() returns either 0 or -BCME_RADIOOFF only
+ */
+ if (!wlc->pub->radio_disabled) {
+ int status = brcms_b_up_prep(wlc->hw);
+ if (status == -ENOMEDIUM) {
+ if (!mboolisset
+ (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) {
+ struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
+ mboolset(wlc->pub->radio_disabled,
+ WL_RADIO_HW_DISABLE);
+
+ if (bsscfg->enable && bsscfg->BSS)
+ wiphy_err(wlc->wiphy, "wl%d: up"
+ ": rfdisable -> "
+ "bsscfg_disable()\n",
+ wlc->pub->unit);
+ }
+ }
+ }
+
+ if (wlc->pub->radio_disabled) {
+ brcms_c_radio_monitor_start(wlc);
+ return 0;
+ }
+
+ /* brcms_b_up_prep has done brcms_c_corereset(). so clk is on, set it */
+ wlc->clk = true;
+
+ brcms_c_radio_monitor_stop(wlc);
+
+ /* Set EDCF hostflags */
+ brcms_b_mhf(wlc->hw, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL);
+
+ brcms_init(wlc->wl);
+ wlc->pub->up = true;
+
+ if (wlc->bandinit_pending) {
+ brcms_c_suspend_mac_and_wait(wlc);
+ brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec);
+ wlc->bandinit_pending = false;
+ brcms_c_enable_mac(wlc);
+ }
+
+ brcms_b_up_finish(wlc->hw);
+
+ /* Program the TX wme params with the current settings */
+ brcms_c_wme_retries_write(wlc);
+
+ /* start one second watchdog timer */
+ brcms_add_timer(wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true);
+ wlc->WDarmed = true;
+
+ /* ensure antenna config is up to date */
+ brcms_c_stf_phy_txant_upd(wlc);
+ /* ensure LDPC config is in sync */
+ brcms_c_ht_update_ldpc(wlc, wlc->stf->ldpc);
+
+ return 0;
+}
+
+static uint brcms_c_down_del_timer(struct brcms_c_info *wlc)
+{
+ uint callbacks = 0;
+
+ return callbacks;
+}
+
+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;
+
+ dev_gone = brcms_deviceremoved(wlc_hw->wlc);
+
+ /* disable interrupts */
+ if (dev_gone)
+ wlc_hw->wlc->macintmask = 0;
+ else {
+ /* now disable interrupts */
+ brcms_intrsoff(wlc_hw->wlc->wl);
+
+ /* ensure we're running on the pll clock again */
+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+ }
+ /* down phy at the last of this stage */
+ callbacks += wlc_phy_down(wlc_hw->band->pi);
+
+ return callbacks;
+}
+
+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;
+
+ wlc_hw->up = false;
+ wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
+
+ dev_gone = brcms_deviceremoved(wlc_hw->wlc);
+
+ if (dev_gone) {
+ wlc_hw->sbclk = false;
+ wlc_hw->clk = false;
+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+
+ /* reclaim any posted packets */
+ brcms_c_flushqueues(wlc_hw->wlc);
+ } else {
+
+ /* Reset and disable the core */
+ if (ai_iscoreup(wlc_hw->sih)) {
+ if (R_REG(&wlc_hw->regs->maccontrol) &
+ MCTL_EN_MAC)
+ brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+ callbacks += brcms_reset(wlc_hw->wlc->wl);
+ brcms_c_coredisable(wlc_hw);
+ }
+
+ /* turn off primary xtal and pll */
+ if (!wlc_hw->noreset) {
+ ai_pci_down(wlc_hw->sih);
+ brcms_b_xtal(wlc_hw, OFF);
+ }
+ }
+
+ return callbacks;
+}
+
+/*
+ * Mark the interface nonoperational, stop the software mechanisms,
+ * disable the hardware, free any transient buffer state.
+ * Return a count of the number of driver callbacks still pending.
+ */
+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);
+
+ /* 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__);
+ return 0;
+ }
+ if (!wlc->pub->up)
+ return callbacks;
+
+ /* in between, mpc could try to bring down again.. */
+ wlc->going_down = true;
+
+ callbacks += brcms_b_bmac_down_prep(wlc->hw);
+
+ dev_gone = brcms_deviceremoved(wlc);
+
+ /* Call any registered down handlers */
+ for (i = 0; i < BRCMS_MAXMODULES; i++) {
+ if (wlc->modulecb[i].down_fn)
+ callbacks +=
+ wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl);
+ }
+
+ /* cancel the watchdog timer */
+ if (wlc->WDarmed) {
+ if (!brcms_del_timer(wlc->wdtimer))
+ callbacks++;
+ wlc->WDarmed = false;
+ }
+ /* cancel all other timers */
+ callbacks += brcms_c_down_del_timer(wlc);
+
+ wlc->pub->up = false;
+
+ 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 */
+ wlc->clk = false;
+
+ wlc->going_down = false;
+ return callbacks;
+}
+
+/* Set the current gmode configuration */
+int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
+{
+ int ret = 0;
+ uint i;
+ struct brcms_c_rateset rs;
+ /* Default to 54g Auto */
+ /* Advertise and use shortslot (-1/0/1 Auto/Off/On) */
+ s8 shortslot = BRCMS_SHORTSLOT_AUTO;
+ bool shortslot_restrict = false; /* Restrict association to stations
+ * that support shortslot
+ */
+ bool ofdm_basic = false; /* Make 6, 12, and 24 basic rates */
+ /* Advertise and use short preambles (-1/0/1 Auto/Off/On) */
+ int preamble = BRCMS_PLCP_LONG;
+ bool preamble_restrict = false; /* Restrict association to stations
+ * that support short preambles
+ */
+ struct brcms_band *band;
+
+ /* if N-support is enabled, allow Gmode set as long as requested
+ * Gmode is not GMODE_LEGACY_B
+ */
+ if ((wlc->pub->_n_enab & SUPPORT_11N) && gmode == GMODE_LEGACY_B)
+ return -ENOTSUPP;
+
+ /* verify that we are dealing with 2G band and grab the band pointer */
+ if (wlc->band->bandtype == BRCM_BAND_2G)
+ band = wlc->band;
+ else if ((wlc->pub->_nbands > 1) &&
+ (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == BRCM_BAND_2G))
+ band = wlc->bandstate[OTHERBANDUNIT(wlc)];
+ else
+ return -EINVAL;
+
+ /* Legacy or bust when no OFDM is supported by regulatory */
+ if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
+ BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B))
+ return -EINVAL;
+
+ /* update configuration value */
+ if (config == true)
+ brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
+
+ /* Clear rateset override */
+ memset(&rs, 0, sizeof(struct brcms_c_rateset));
+
+ switch (gmode) {
+ case GMODE_LEGACY_B:
+ shortslot = BRCMS_SHORTSLOT_OFF;
+ brcms_c_rateset_copy(&gphy_legacy_rates, &rs);
+
+ break;
+
+ case GMODE_LRS:
+ break;
+
+ case GMODE_AUTO:
+ /* Accept defaults */
+ break;
+
+ case GMODE_ONLY:
+ ofdm_basic = true;
+ preamble = BRCMS_PLCP_SHORT;
+ preamble_restrict = true;
+ break;
+
+ case GMODE_PERFORMANCE:
+ shortslot = BRCMS_SHORTSLOT_ON;
+ shortslot_restrict = true;
+ ofdm_basic = true;
+ preamble = BRCMS_PLCP_SHORT;
+ preamble_restrict = true;
+ break;
+
+ default:
+ /* Error */
+ wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n",
+ wlc->pub->unit, __func__, gmode);
+ return -ENOTSUPP;
+ }
+
+ band->gmode = gmode;
+
+ wlc->shortslot_override = shortslot;
+
+ /* Use the default 11g rateset */
+ if (!rs.count)
+ brcms_c_rateset_copy(&cck_ofdm_rates, &rs);
+
+ if (ofdm_basic) {
+ for (i = 0; i < rs.count; i++) {
+ if (rs.rates[i] == BRCM_RATE_6M
+ || rs.rates[i] == BRCM_RATE_12M
+ || rs.rates[i] == BRCM_RATE_24M)
+ rs.rates[i] |= BRCMS_RATE_FLAG;
+ }
+ }
+
+ /* Set default bss rateset */
+ wlc->default_bss->rateset.count = rs.count;
+ memcpy(wlc->default_bss->rateset.rates, rs.rates,
+ sizeof(wlc->default_bss->rateset.rates));
+
+ return ret;
+}
+
+int brcms_c_set_nmode(struct brcms_c_info *wlc)
+{
+ uint i;
+ s32 nmode = AUTO;
+
+ if (wlc->stf->txstreams == WL_11N_3x3)
+ nmode = WL_11N_3x3;
+ else
+ nmode = WL_11N_2x2;
+
+ /* force GMODE_AUTO if NMODE is ON */
+ brcms_c_set_gmode(wlc, GMODE_AUTO, true);
+ if (nmode == WL_11N_3x3)
+ wlc->pub->_n_enab = SUPPORT_HT;
+ else
+ wlc->pub->_n_enab = SUPPORT_11N;
+ wlc->default_bss->flags |= BRCMS_BSS_HT;
+ /* add the mcs rates to the default and hw ratesets */
+ brcms_c_rateset_mcs_build(&wlc->default_bss->rateset,
+ wlc->stf->txstreams);
+ for (i = 0; i < wlc->pub->_nbands; i++)
+ memcpy(wlc->bandstate[i]->hw_rateset.mcs,
+ wlc->default_bss->rateset.mcs, MCSSET_LEN);
+
+ return 0;
+}
+
+static int
+brcms_c_set_internal_rateset(struct brcms_c_info *wlc,
+ struct brcms_c_rateset *rs_arg)
+{
+ struct brcms_c_rateset rs, new;
+ uint bandunit;
+
+ memcpy(&rs, rs_arg, sizeof(struct brcms_c_rateset));
+
+ /* check for bad count value */
+ if ((rs.count == 0) || (rs.count > BRCMS_NUMRATES))
+ return -EINVAL;
+
+ /* try the current band */
+ bandunit = wlc->band->bandunit;
+ memcpy(&new, &rs, sizeof(struct brcms_c_rateset));
+ if (brcms_c_rate_hwrs_filter_sort_validate
+ (&new, &wlc->bandstate[bandunit]->hw_rateset, true,
+ wlc->stf->txstreams))
+ goto good;
+
+ /* try the other band */
+ if (brcms_is_mband_unlocked(wlc)) {
+ bandunit = OTHERBANDUNIT(wlc);
+ memcpy(&new, &rs, sizeof(struct brcms_c_rateset));
+ if (brcms_c_rate_hwrs_filter_sort_validate(&new,
+ &wlc->
+ bandstate[bandunit]->
+ hw_rateset, true,
+ wlc->stf->txstreams))
+ goto good;
+ }
+
+ return -EBADE;
+
+ good:
+ /* apply new rateset */
+ memcpy(&wlc->default_bss->rateset, &new,
+ sizeof(struct brcms_c_rateset));
+ memcpy(&wlc->bandstate[bandunit]->defrateset, &new,
+ sizeof(struct brcms_c_rateset));
+ return 0;
+}
+
+static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
+{
+ u8 r;
+ bool war = false;
+
+ if (wlc->bsscfg->associated)
+ r = wlc->bsscfg->current_bss->rateset.rates[0];
+ else
+ r = wlc->default_bss->rateset.rates[0];
+
+ wlc_phy_ofdm_rateset_war(wlc->band->pi, war);
+}
+
+int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel)
+{
+ u16 chspec = ch20mhz_chspec(channel);
+
+ if (channel < 0 || channel > MAXCHANNEL)
+ return -EINVAL;
+
+ if (!brcms_c_valid_chanspec_db(wlc->cmi, chspec))
+ return -EINVAL;
+
+
+ if (!wlc->pub->up && brcms_is_mband_unlocked(wlc)) {
+ if (wlc->band->bandunit != chspec_bandunit(chspec))
+ wlc->bandinit_pending = true;
+ else
+ wlc->bandinit_pending = false;
+ }
+
+ wlc->default_bss->chanspec = chspec;
+ /* brcms_c_BSSinit() will sanitize the rateset before
+ * using it.. */
+ if (wlc->pub->up && (wlc_phy_chanspec_get(wlc->band->pi) != chspec)) {
+ brcms_c_set_home_chanspec(wlc, chspec);
+ brcms_c_suspend_mac_and_wait(wlc);
+ brcms_c_set_chanspec(wlc, chspec);
+ brcms_c_enable_mac(wlc);
+ }
+ return 0;
+}
+
+int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl)
+{
+ int ac;
+
+ if (srl < 1 || srl > RETRY_SHORT_MAX ||
+ lrl < 1 || lrl > RETRY_SHORT_MAX)
+ return -EINVAL;
+
+ wlc->SRL = srl;
+ wlc->LRL = lrl;
+
+ brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
+
+ for (ac = 0; ac < AC_COUNT; ac++) {
+ wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac],
+ EDCF_SHORT, wlc->SRL);
+ wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac],
+ EDCF_LONG, wlc->LRL);
+ }
+ brcms_c_wme_retries_write(wlc);
+
+ return 0;
+}
+
+void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
+ struct brcm_rateset *currs)
+{
+ struct brcms_c_rateset *rs;
+
+ if (wlc->pub->associated)
+ rs = &wlc->bsscfg->current_bss->rateset;
+ else
+ rs = &wlc->default_bss->rateset;
+
+ /* Copy only legacy rateset section */
+ currs->count = rs->count;
+ memcpy(&currs->rates, &rs->rates, rs->count);
+}
+
+int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
+{
+ struct brcms_c_rateset internal_rs;
+ int bcmerror;
+
+ if (rs->count > BRCMS_NUMRATES)
+ return -ENOBUFS;
+
+ memset(&internal_rs, 0, sizeof(struct brcms_c_rateset));
+
+ /* Copy only legacy rateset section */
+ internal_rs.count = rs->count;
+ memcpy(&internal_rs.rates, &rs->rates, internal_rs.count);
+
+ /* merge rateset coming in with the current mcsset */
+ if (wlc->pub->_n_enab & SUPPORT_11N) {
+ struct brcms_bss_info *mcsset_bss;
+ if (wlc->bsscfg->associated)
+ mcsset_bss = wlc->bsscfg->current_bss;
+ else
+ mcsset_bss = wlc->default_bss;
+ memcpy(internal_rs.mcs, &mcsset_bss->rateset.mcs[0],
+ MCSSET_LEN);
+ }
+
+ bcmerror = brcms_c_set_internal_rateset(wlc, &internal_rs);
+ if (!bcmerror)
+ brcms_c_ofdm_rateset_war(wlc);
+
+ return bcmerror;
+}
+
+int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
+{
+ if (period < DOT11_MIN_BEACON_PERIOD ||
+ period > DOT11_MAX_BEACON_PERIOD)
+ return -EINVAL;
+
+ wlc->default_bss->beacon_period = period;
+ return 0;
+}
+
+u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx)
+{
+ return wlc->band->phytype;
+}
+
+void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, s8 sslot_override)
+{
+ wlc->shortslot_override = sslot_override;
+
+ /*
+ * shortslot is an 11g feature, so no more work if we are
+ * currently on the 5G band
+ */
+ if (wlc->band->bandtype == BRCM_BAND_5G)
+ return;
+
+ if (wlc->pub->up && wlc->pub->associated) {
+ /* let watchdog or beacon processing update shortslot */
+ } else if (wlc->pub->up) {
+ /* unassociated shortslot is off */
+ brcms_c_switch_shortslot(wlc, false);
+ } else {
+ /* driver is down, so just update the brcms_c_info
+ * value */
+ if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO)
+ wlc->shortslot = false;
+ else
+ wlc->shortslot =
+ (wlc->shortslot_override ==
+ BRCMS_SHORTSLOT_ON);
+ }
+}
+
+/*
+ * register watchdog and down handlers.
+ */
+int brcms_c_module_register(struct brcms_pub *pub,
+ const char *name, struct brcms_info *hdl,
+ int (*d_fn)(void *handle))
+{
+ struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
+ int i;
+
+ /* find an empty entry and just add, no duplication check! */
+ for (i = 0; i < BRCMS_MAXMODULES; i++) {
+ if (wlc->modulecb[i].name[0] == '\0') {
+ strncpy(wlc->modulecb[i].name, name,
+ sizeof(wlc->modulecb[i].name) - 1);
+ wlc->modulecb[i].hdl = hdl;
+ wlc->modulecb[i].down_fn = d_fn;
+ return 0;
+ }
+ }
+
+ return -ENOSR;
+}
+
+/* unregister module callbacks */
+int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
+ struct brcms_info *hdl)
+{
+ struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
+ int i;
+
+ if (wlc == NULL)
+ return -ENODATA;
+
+ for (i = 0; i < BRCMS_MAXMODULES; i++) {
+ if (!strcmp(wlc->modulecb[i].name, name) &&
+ (wlc->modulecb[i].hdl == hdl)) {
+ memset(&wlc->modulecb[i], 0, sizeof(struct modulecb));
+ return 0;
+ }
+ }
+
+ /* table not found! */
+ return -ENODATA;
+}
+
+#ifdef BCMDBG
+static const char * const supr_reason[] = {
+ "None", "PMQ Entry", "Flush request",
+ "Previous frag failure", "Channel mismatch",
+ "Lifetime Expiry", "Underflow"
+};
+
+static void brcms_c_print_txs_status(u16 s)
+{
+ printk(KERN_DEBUG "[15:12] %d frame attempts\n",
+ (s & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT);
+ printk(KERN_DEBUG " [11:8] %d rts attempts\n",
+ (s & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT);
+ printk(KERN_DEBUG " [7] %d PM mode indicated\n",
+ ((s & TX_STATUS_PMINDCTD) ? 1 : 0));
+ printk(KERN_DEBUG " [6] %d intermediate status\n",
+ ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0));
+ printk(KERN_DEBUG " [5] %d AMPDU\n",
+ (s & TX_STATUS_AMPDU) ? 1 : 0);
+ printk(KERN_DEBUG " [4:2] %d Frame Suppressed Reason (%s)\n",
+ ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT),
+ supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]);
+ printk(KERN_DEBUG " [1] %d acked\n",
+ ((s & TX_STATUS_ACK_RCV) ? 1 : 0));
+}
+#endif /* BCMDBG */
+
+void brcms_c_print_txstatus(struct tx_status *txs)
+{
+#if defined(BCMDBG)
+ u16 s = txs->status;
+ u16 ackphyrxsh = txs->ackphyrxsh;
+
+ printk(KERN_DEBUG "\ntxpkt (MPDU) Complete\n");
+
+ printk(KERN_DEBUG "FrameID: %04x ", txs->frameid);
+ printk(KERN_DEBUG "TxStatus: %04x", s);
+ printk(KERN_DEBUG "\n");
+
+ brcms_c_print_txs_status(s);
+
+ printk(KERN_DEBUG "LastTxTime: %04x ", txs->lasttxtime);
+ printk(KERN_DEBUG "Seq: %04x ", txs->sequence);
+ printk(KERN_DEBUG "PHYTxStatus: %04x ", txs->phyerr);
+ printk(KERN_DEBUG "RxAckRSSI: %04x ",
+ (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT);
+ printk(KERN_DEBUG "RxAckSQ: %04x",
+ (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
+ printk(KERN_DEBUG "\n");
+#endif /* defined(BCMDBG) */
+}
+
+bool brcms_c_chipmatch(u16 vendor, u16 device)
+{
+ if (vendor != PCI_VENDOR_ID_BROADCOM) {
+ pr_err("chipmatch: unknown vendor id %04x\n", vendor);
+ return false;
+ }
+
+ if (device == BCM43224_D11N_ID_VEN1)
+ return true;
+ if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID))
+ return true;
+ if (device == BCM4313_D11N2G_ID)
+ return true;
+ if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID))
+ return true;
+
+ pr_err("chipmatch: unknown device id %04x\n", device);
+ return false;
+}
+
+#if defined(BCMDBG)
+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;
+ char hexbuf[256];
+
+ /* add plcp header along with txh descriptor */
+ printk(KERN_DEBUG "Raw TxDesc + plcp header:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+ txh, sizeof(struct d11txh) + 48);
+
+ printk(KERN_DEBUG "TxCtlLow: %04x ", mtcl);
+ printk(KERN_DEBUG "TxCtlHigh: %04x ", mtch);
+ printk(KERN_DEBUG "FC: %04x ", mfc);
+ printk(KERN_DEBUG "FES Time: %04x\n", tfest);
+ printk(KERN_DEBUG "PhyCtl: %04x%s ", ptcw,
+ (ptcw & PHY_TXC_SHORT_HDR) ? " short" : "");
+ printk(KERN_DEBUG "PhyCtl_1: %04x ", ptcw_1);
+ printk(KERN_DEBUG "PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr);
+ printk(KERN_DEBUG "PhyCtl_1_Rts: %04x ", ptcw_1_Rts);
+ printk(KERN_DEBUG "PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts);
+ printk(KERN_DEBUG "MainRates: %04x ", mainrates);
+ printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft);
+ printk(KERN_DEBUG "\n");
+
+ brcmu_format_hex(hexbuf, iv, sizeof(txh->IV));
+ printk(KERN_DEBUG "SecIV: %s\n", hexbuf);
+ brcmu_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA));
+ printk(KERN_DEBUG "RA: %s\n", hexbuf);
+
+ printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb);
+ brcmu_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback));
+ printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
+ printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb);
+ brcmu_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback));
+ printk(KERN_DEBUG "PLCP: %s ", hexbuf);
+ printk(KERN_DEBUG "DUR: %04x", fragdfb);
+ printk(KERN_DEBUG "\n");
+
+ printk(KERN_DEBUG "MModeLen: %04x ", mmodelen);
+ printk(KERN_DEBUG "MModeFbrLen: %04x\n", mmodefbrlen);
+
+ printk(KERN_DEBUG "FrameID: %04x\n", tfid);
+ printk(KERN_DEBUG "TxStatus: %04x\n", txs);
+
+ printk(KERN_DEBUG "MaxNumMpdu: %04x\n", mnmpdu);
+ printk(KERN_DEBUG "MaxAggbyte: %04x\n", mabyte);
+ printk(KERN_DEBUG "MaxAggbyte_fb: %04x\n", mabyte_f);
+ printk(KERN_DEBUG "MinByte: %04x\n", mmbyte);
+
+ brcmu_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader));
+ printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
+ brcmu_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame));
+ printk(KERN_DEBUG "RTS Frame: %s", hexbuf);
+ printk(KERN_DEBUG "\n");
+}
+#endif /* defined(BCMDBG) */
+
+#if defined(BCMDBG)
+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(BCMDBG) */
+
+#if defined(BCMDBG)
+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}
+ };
+
+ printk(KERN_DEBUG "Raw RxDesc:\n");
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, rxh,
+ sizeof(struct d11rxhdr));
+
+ brcms_c_format_flags(macstat_flags, macstatus1, flagstr, 64);
+
+ snprintf(lenbuf, sizeof(lenbuf), "0x%x", len);
+
+ printk(KERN_DEBUG "RxFrameSize: %6s (%d)%s\n", lenbuf, len,
+ (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : "");
+ printk(KERN_DEBUG "RxPHYStatus: %04x %04x %04x %04x\n",
+ phystatus_0, phystatus_1, phystatus_2, phystatus_3);
+ printk(KERN_DEBUG "RxMACStatus: %x %s\n", macstatus1, flagstr);
+ printk(KERN_DEBUG "RXMACaggtype: %x\n",
+ (macstatus2 & RXS_AGGTYPE_MASK));
+ printk(KERN_DEBUG "RxTSFTime: %04x\n", rxh->RxTSFTime);
+}
+#endif /* defined(BCMDBG) */
+
+u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
+{
+ u16 table_ptr;
+ u8 phy_rate, index;
+
+ /* get the phy specific rate encoding for the PLCP SIGNAL field */
+ if (is_ofdm_rate(rate))
+ table_ptr = M_RT_DIRMAP_A;
+ else
+ table_ptr = M_RT_DIRMAP_B;
+
+ /* for a given rate, the LS-nibble of the PLCP SIGNAL field is
+ * the index into the rate table.
+ */
+ phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
+ index = phy_rate & 0xf;
+
+ /* Find the SHM pointer to the rate table entry by looking in the
+ * Direct-map Table
+ */
+ 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
+ * for MC frames so is used as part of the sequence number.
+ */
+static inline u16
+bcmc_fid_generate(struct brcms_c_info *wlc, struct brcms_bss_cfg *bsscfg,
+ struct d11txh *txh)
+{
+ u16 frameid;
+
+ frameid = le16_to_cpu(txh->TxFrameID) & ~(TXFID_SEQ_MASK |
+ TXFID_QUEUE_MASK);
+ frameid |=
+ (((wlc->
+ mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
+ TX_BCMC_FIFO;
+
+ return frameid;
+}
+
+static uint
+brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec,
+ u8 preamble_type)
+{
+ 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
+ * frame in the FES
+ */
+ rspec = brcms_basic_rate(wlc, rspec);
+ /* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */
+ dur =
+ brcms_c_calc_frame_time(wlc, rspec, preamble_type,
+ (DOT11_ACK_LEN + FCS_LEN));
+ return dur;
+}
+
+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);
+}
+
+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
+ * frame in the FES
+ */
+ rspec = brcms_basic_rate(wlc, rspec);
+ /* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */
+ return brcms_c_calc_frame_time(wlc, rspec, preamble_type,
+ (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN +
+ FCS_LEN));
+}
+
+/* brcms_c_compute_frame_dur()
+ *
+ * Calculate the 802.11 MAC header DUR field for MPDU
+ * DUR for a single frame = 1 SIFS + 1 ACK
+ * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time
+ *
+ * rate MPDU rate in unit of 500kbps
+ * next_frag_len next MPDU length in bytes
+ * preamble_type use short/GF or long/MM PLCP header
+ */
+static u16
+brcms_c_compute_frame_dur(struct brcms_c_info *wlc, u32 rate,
+ u8 preamble_type, uint next_frag_len)
+{
+ u16 dur, sifs;
+
+ sifs = get_sifs(wlc->band);
+
+ dur = sifs;
+ dur += (u16) brcms_c_calc_ack_time(wlc, rate, preamble_type);
+
+ if (next_frag_len) {
+ /* Double the current DUR to get 2 SIFS + 2 ACKs */
+ dur *= 2;
+ /* add another SIFS and the frag time */
+ dur += sifs;
+ dur +=
+ (u16) brcms_c_calc_frame_time(wlc, rate, preamble_type,
+ next_frag_len);
+ }
+ return dur;
+}
+
+/* The opposite of brcms_c_calc_frame_time */
+static uint
+brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec,
+ u8 preamble_type, uint dur)
+{
+ 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);
+ dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+ /* payload calculation matches that of regular ofdm */
+ if (wlc->band->bandtype == BRCM_BAND_2G)
+ dur -= DOT11_OFDM_SIGNAL_EXTENSION;
+ /* kNdbps = kbps * 4 */
+ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+ rspec_issgi(ratespec)) * 4;
+ nsyms = dur / APHY_SYMBOL_TIME;
+ mac_len =
+ ((nsyms * kNdps) -
+ ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000;
+ } else if (is_ofdm_rate(ratespec)) {
+ dur -= APHY_PREAMBLE_TIME;
+ dur -= APHY_SIGNAL_TIME;
+ /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+ Ndps = rate * 2;
+ nsyms = dur / APHY_SYMBOL_TIME;
+ mac_len =
+ ((nsyms * Ndps) -
+ (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8;
+ } else {
+ if (preamble_type & BRCMS_SHORT_PREAMBLE)
+ dur -= BPHY_PLCP_SHORT_TIME;
+ else
+ dur -= BPHY_PLCP_TIME;
+ mac_len = dur * rate;
+ /* divide out factor of 2 in rate (1/2 mbps) */
+ mac_len = mac_len / 8 / 2;
+ }
+ return mac_len;
+}
+
+/*
+ * Return true if the specified rate is supported by the specified band.
+ * BRCM_BAND_AUTO indicates the current band.
+ */
+static bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band,
+ bool verbose)
+{
+ struct brcms_c_rateset *hw_rateset;
+ uint i;
+
+ if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype))
+ hw_rateset = &wlc->band->hw_rateset;
+ else if (wlc->pub->_nbands > 1)
+ hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
+ else
+ /* other band specified and we are a single band device */
+ return false;
+
+ /* check if this is a mimo rate */
+ if (is_mcs_rate(rspec)) {
+ if ((rspec & RSPEC_RATE_MASK) >= MCS_TABLE_SIZE)
+ goto error;
+
+ return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
+ }
+
+ for (i = 0; i < hw_rateset->count; i++)
+ if (hw_rateset->rates[i] == rspec2rate(rspec))
+ return true;
+ error:
+ if (verbose)
+ wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x "
+ "not in hw_rateset\n", wlc->pub->unit, rspec);
+
+ return false;
+}
+
+static u32
+mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
+ u32 int_val)
+{
+ u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
+ u8 rate = int_val & NRATE_RATE_MASK;
+ u32 rspec;
+ bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE);
+ bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT);
+ bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY)
+ == NRATE_OVERRIDE_MCS_ONLY);
+ int bcmerror = 0;
+
+ if (!ismcs)
+ return (u32) rate;
+
+ /* validate the combination of rate/mcs/stf is allowed */
+ 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",
+ wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+
+ /* mcs 32 is a special case, DUP mode 40 only */
+ if (rate == 32) {
+ 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__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+ /* mcs > 7 must use stf SDM */
+ } 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);
+ stf = PHY_TXC1_MODE_SDM;
+ }
+ } else {
+ /*
+ * MCS 0-7 may use SISO, CDD, and for
+ * phy_rev >= 3 STBC
+ */
+ 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__);
+ 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",
+ wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+ } 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",
+ wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+ } else {
+ wiphy_err(wlc->wiphy, "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 "
+ "request\n", wlc->pub->unit, __func__);
+ bcmerror = -EINVAL;
+ goto done;
+ }
+
+ rspec = rate;
+ if (ismcs) {
+ rspec |= RSPEC_MIMORATE;
+ /* For STBC populate the STC field of the ratespec */
+ if (stf == PHY_TXC1_MODE_STBC) {
+ u8 stc;
+ stc = 1; /* Nss for single stream is always 1 */
+ rspec |= (stc << RSPEC_STC_SHIFT);
+ }
+ }
+
+ rspec |= (stf << RSPEC_STF_SHIFT);
+
+ if (override_mcs_only)
+ rspec |= RSPEC_OVERRIDE_MCS_ONLY;
+
+ if (issgi)
+ rspec |= RSPEC_SHORT_GI;
+
+ if ((rate != 0)
+ && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true))
+ return rate;
+
+ return rspec;
+done:
+ return rate;
+}
+
+/*
+ * Compute PLCP, but only requires actual rate and length of pkt.
+ * Rate is given in the driver standard multiple of 500 kbps.
+ * le is set for 11 Mbps rate if necessary.
+ * Broken out for PRQ.
+ */
+
+static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
+ uint length, u8 *plcp)
+{
+ u16 usec = 0;
+ u8 le = 0;
+
+ switch (rate_500) {
+ case BRCM_RATE_1M:
+ usec = length << 3;
+ break;
+ case BRCM_RATE_2M:
+ usec = length << 2;
+ break;
+ case BRCM_RATE_5M5:
+ usec = (length << 4) / 11;
+ if ((length << 4) - (usec * 11) > 0)
+ usec++;
+ break;
+ case BRCM_RATE_11M:
+ usec = (length << 3) / 11;
+ if ((length << 3) - (usec * 11) > 0) {
+ usec++;
+ if ((usec * 11) - (length << 3) >= 8)
+ le = D11B_PLCP_SIGNAL_LE;
+ }
+ break;
+
+ default:
+ wiphy_err(wlc->wiphy,
+ "brcms_c_cck_plcp_set: unsupported rate %d\n",
+ rate_500);
+ rate_500 = BRCM_RATE_1M;
+ usec = length << 3;
+ break;
+ }
+ /* PLCP signal byte */
+ plcp[0] = rate_500 * 5; /* r (500kbps) * 5 == r (100kbps) */
+ /* PLCP service byte */
+ plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED);
+ /* PLCP length u16, little endian */
+ plcp[2] = usec & 0xff;
+ plcp[3] = (usec >> 8) & 0xff;
+ /* PLCP CRC16 */
+ plcp[4] = 0;
+ plcp[5] = 0;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void brcms_c_compute_mimo_plcp(u32 rspec, uint length, u8 *plcp)
+{
+ u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
+ plcp[0] = mcs;
+ if (rspec_is40mhz(rspec) || (mcs == 32))
+ plcp[0] |= MIMO_PLCP_40MHZ;
+ BRCMS_SET_MIMO_PLCP_LEN(plcp, length);
+ plcp[3] = rspec_mimoplcp3(rspec); /* rspec already holds this byte */
+ plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */
+ plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */
+ plcp[5] = 0;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void
+brcms_c_compute_ofdm_plcp(u32 rspec, u32 length, u8 *plcp)
+{
+ u8 rate_signal;
+ u32 tmp = 0;
+ int rate = rspec2rate(rspec);
+
+ /*
+ * encode rate per 802.11a-1999 sec 17.3.4.1, with lsb
+ * transmitted first
+ */
+ rate_signal = rate_info[rate] & BRCMS_RATE_MASK;
+ memset(plcp, 0, D11_PHY_HDR_LEN);
+ D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal);
+
+ tmp = (length & 0xfff) << 5;
+ plcp[2] |= (tmp >> 16) & 0xff;
+ plcp[1] |= (tmp >> 8) & 0xff;
+ plcp[0] |= tmp & 0xff;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec,
+ uint length, u8 *plcp)
+{
+ int rate = rspec2rate(rspec);
+
+ brcms_c_cck_plcp_set(wlc, rate, length, plcp);
+}
+
+static void
+brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rspec,
+ uint length, u8 *plcp)
+{
+ if (is_mcs_rate(rspec))
+ brcms_c_compute_mimo_plcp(rspec, length, plcp);
+ else if (is_ofdm_rate(rspec))
+ brcms_c_compute_ofdm_plcp(rspec, length, plcp);
+ else
+ brcms_c_compute_cck_plcp(wlc, rspec, length, plcp);
+}
+
+/* brcms_c_compute_rtscts_dur()
+ *
+ * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame
+ * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK
+ * DUR for CTS-TO-SELF w/ frame = 2 SIFS + next frame time + 1 ACK
+ *
+ * cts cts-to-self or rts/cts
+ * rts_rate rts or cts rate in unit of 500kbps
+ * rate next MPDU rate in unit of 500kbps
+ * frame_len next MPDU frame length in bytes
+ */
+u16
+brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
+ u32 rts_rate,
+ u32 frame_rate, u8 rts_preamble_type,
+ u8 frame_preamble_type, uint frame_len, bool ba)
+{
+ u16 dur, sifs;
+
+ sifs = get_sifs(wlc->band);
+
+ if (!cts_only) {
+ /* RTS/CTS */
+ dur = 3 * sifs;
+ dur +=
+ (u16) brcms_c_calc_cts_time(wlc, rts_rate,
+ rts_preamble_type);
+ } else {
+ /* CTS-TO-SELF */
+ dur = 2 * sifs;
+ }
+
+ dur +=
+ (u16) brcms_c_calc_frame_time(wlc, frame_rate, frame_preamble_type,
+ frame_len);
+ if (ba)
+ dur +=
+ (u16) brcms_c_calc_ba_time(wlc, frame_rate,
+ BRCMS_SHORT_PREAMBLE);
+ else
+ dur +=
+ (u16) brcms_c_calc_ack_time(wlc, frame_rate,
+ frame_preamble_type);
+ return dur;
+}
+
+static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec)
+{
+ u16 phyctl1 = 0;
+ u16 bw;
+
+ if (BRCMS_ISLCNPHY(wlc->band)) {
+ bw = PHY_TXC1_BW_20MHZ;
+ } else {
+ 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 "
+ "not supported yet, set to 20L\n", bw);
+ bw = PHY_TXC1_BW_20MHZ;
+ }
+ }
+
+ if (is_mcs_rate(rspec)) {
+ uint mcs = rspec & RSPEC_RATE_MASK;
+
+ /* bw, stf, coding-type is part of rspec_phytxbyte2 returns */
+ phyctl1 = rspec_phytxbyte2(rspec);
+ /* set the upper byte of phyctl1 */
+ phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
+ } else if (is_cck_rate(rspec) && !BRCMS_ISLCNPHY(wlc->band)
+ && !BRCMS_ISSSLPNPHY(wlc->band)) {
+ /*
+ * In CCK mode LPPHY overloads OFDM Modulation bits with CCK
+ * Data Rate. Eventually MIMOPHY would also be converted to
+ * this format
+ */
+ /* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
+ phyctl1 = (bw | (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT));
+ } else { /* legacy OFDM/CCK */
+ s16 phycfg;
+ /* 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 "
+ "legacy OFDM/CCK rate\n");
+ phycfg = 0;
+ }
+ /* set the upper byte of phyctl1 */
+ phyctl1 =
+ (bw | (phycfg << 8) |
+ (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT));
+ }
+ return phyctl1;
+}
+
+/*
+ * Add struct d11txh, struct cck_phy_hdr.
+ *
+ * 'p' data must start with 802.11 MAC header
+ * 'p' must allow enough bytes of local headers to be "pushed" onto the packet
+ *
+ * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes)
+ *
+ */
+static u16
+brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
+ struct sk_buff *p, struct scb *scb, uint frag,
+ uint nfrags, uint queue, uint next_frag_len)
+{
+ struct ieee80211_hdr *h;
+ struct d11txh *txh;
+ u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN];
+ int len, phylen, rts_phylen;
+ u16 mch, phyctl, xfts, mainrates;
+ u16 seq = 0, mcl = 0, status = 0, frameid = 0;
+ u32 rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M };
+ u32 rts_rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M };
+ bool use_rts = false;
+ bool use_cts = false;
+ bool use_rifs = false;
+ bool short_preamble[2] = { false, false };
+ u8 preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
+ u8 rts_preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
+ u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN];
+ struct ieee80211_rts *rts = NULL;
+ bool qos;
+ uint ac;
+ bool hwtkmic = false;
+ u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+#define ANTCFG_NONE 0xFF
+ u8 antcfg = ANTCFG_NONE;
+ u8 fbantcfg = ANTCFG_NONE;
+ uint phyctl1_stf = 0;
+ u16 durid = 0;
+ struct ieee80211_tx_rate *txrate[2];
+ int k;
+ struct ieee80211_tx_info *tx_info;
+ bool is_mcs;
+ u16 mimo_txbw;
+ u8 mimo_preamble_type;
+
+ /* locate 802.11 MAC header */
+ h = (struct ieee80211_hdr *)(p->data);
+ qos = ieee80211_is_data_qos(h->frame_control);
+
+ /* compute length of frame in bytes for use in PLCP computations */
+ len = brcmu_pkttotlen(p);
+ phylen = len + FCS_LEN;
+
+ /* Get tx_info */
+ tx_info = IEEE80211_SKB_CB(p);
+
+ /* add PLCP */
+ plcp = skb_push(p, D11_PHY_HDR_LEN);
+
+ /* add Broadcom tx descriptor header */
+ txh = (struct d11txh *) skb_push(p, D11_TXH_LEN);
+ memset(txh, 0, D11_TXH_LEN);
+
+ /* setup frameid */
+ 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__);
+ frameid = bcmc_fid_generate(wlc, NULL, txh);
+ } else {
+ /* Increment the counter for first fragment */
+ if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+ scb->seqnum[p->priority]++;
+
+ /* extract fragment number from frame first */
+ seq = le16_to_cpu(h->seq_ctrl) & FRAGNUM_MASK;
+ seq |= (scb->seqnum[p->priority] << SEQNUM_SHIFT);
+ h->seq_ctrl = cpu_to_le16(seq);
+
+ frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
+ (queue & TXFID_QUEUE_MASK);
+ }
+ }
+ frameid |= queue & TXFID_QUEUE_MASK;
+
+ /* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */
+ if (ieee80211_is_beacon(h->frame_control))
+ mcl |= TXC_IGNOREPMQ;
+
+ txrate[0] = tx_info->control.rates;
+ txrate[1] = txrate[0] + 1;
+
+ /*
+ * if rate control algorithm didn't give us a fallback
+ * rate, use the primary rate
+ */
+ if (txrate[1]->idx < 0)
+ txrate[1] = txrate[0];
+
+ for (k = 0; k < hw->max_rates; k++) {
+ is_mcs = txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false;
+ if (!is_mcs) {
+ if ((txrate[k]->idx >= 0)
+ && (txrate[k]->idx <
+ hw->wiphy->bands[tx_info->band]->n_bitrates)) {
+ rspec[k] =
+ hw->wiphy->bands[tx_info->band]->
+ bitrates[txrate[k]->idx].hw_value;
+ short_preamble[k] =
+ txrate[k]->
+ flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ?
+ true : false;
+ } else {
+ rspec[k] = BRCM_RATE_1M;
+ }
+ } else {
+ rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band,
+ NRATE_MCS_INUSE | txrate[k]->idx);
+ }
+
+ /*
+ * Currently only support same setting for primay and
+ * fallback rates. Unify flags for each rate into a
+ * single value for the frame
+ */
+ use_rts |=
+ txrate[k]->
+ flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false;
+ use_cts |=
+ txrate[k]->
+ flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false;
+
+
+ /*
+ * (1) RATE:
+ * determine and validate primary rate
+ * and fallback rates
+ */
+ if (!rspec_active(rspec[k])) {
+ rspec[k] = BRCM_RATE_1M;
+ } else {
+ if (!is_multicast_ether_addr(h->addr1)) {
+ /* set tx antenna config */
+ brcms_c_antsel_antcfg_get(wlc->asi, false,
+ false, 0, 0, &antcfg, &fbantcfg);
+ }
+ }
+ }
+
+ phyctl1_stf = wlc->stf->ss_opmode;
+
+ if (wlc->pub->_n_enab & SUPPORT_11N) {
+ for (k = 0; k < hw->max_rates; k++) {
+ /*
+ * apply siso/cdd to single stream mcs's or ofdm
+ * if rspec is auto selected
+ */
+ if (((is_mcs_rate(rspec[k]) &&
+ is_single_stream(rspec[k] & RSPEC_RATE_MASK)) ||
+ is_ofdm_rate(rspec[k]))
+ && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY)
+ || !(rspec[k] & RSPEC_OVERRIDE))) {
+ rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK);
+
+ /* For SISO MCS use STBC if possible */
+ if (is_mcs_rate(rspec[k])
+ && BRCMS_STF_SS_STBC_TX(wlc, scb)) {
+ u8 stc;
+
+ /* Nss for single stream is always 1 */
+ stc = 1;
+ rspec[k] |= (PHY_TXC1_MODE_STBC <<
+ RSPEC_STF_SHIFT) |
+ (stc << RSPEC_STC_SHIFT);
+ } else
+ rspec[k] |=
+ (phyctl1_stf << RSPEC_STF_SHIFT);
+ }
+
+ /*
+ * Is the phy configured to use 40MHZ frames? If
+ * so then pick the desired txbw
+ */
+ if (brcms_chspec_bw(wlc->chanspec) == BRCMS_40_MHZ) {
+ /* default txbw is 20in40 SB */
+ mimo_ctlchbw = mimo_txbw =
+ CHSPEC_SB_UPPER(wlc_phy_chanspec_get(
+ wlc->band->pi))
+ ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
+
+ if (is_mcs_rate(rspec[k])) {
+ /* mcs 32 must be 40b/w DUP */
+ if ((rspec[k] & RSPEC_RATE_MASK)
+ == 32) {
+ mimo_txbw =
+ PHY_TXC1_BW_40MHZ_DUP;
+ /* use override */
+ } else if (wlc->mimo_40txbw != AUTO)
+ mimo_txbw = wlc->mimo_40txbw;
+ /* else check if dst is using 40 Mhz */
+ else if (scb->flags & SCB_IS40)
+ mimo_txbw = PHY_TXC1_BW_40MHZ;
+ } else if (is_ofdm_rate(rspec[k])) {
+ if (wlc->ofdm_40txbw != AUTO)
+ mimo_txbw = wlc->ofdm_40txbw;
+ } else if (wlc->cck_40txbw != AUTO) {
+ mimo_txbw = wlc->cck_40txbw;
+ }
+ } else {
+ /*
+ * mcs32 is 40 b/w only.
+ * This is possible for probe packets on
+ * a STA during SCAN
+ */
+ if ((rspec[k] & RSPEC_RATE_MASK) == 32)
+ /* mcs 0 */
+ rspec[k] = RSPEC_MIMORATE;
+
+ mimo_txbw = PHY_TXC1_BW_20MHZ;
+ }
+
+ /* Set channel width */
+ rspec[k] &= ~RSPEC_BW_MASK;
+ if ((k == 0) || ((k > 0) && is_mcs_rate(rspec[k])))
+ rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT);
+ else
+ rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
+
+ /* Disable short GI, not supported yet */
+ rspec[k] &= ~RSPEC_SHORT_GI;
+
+ mimo_preamble_type = BRCMS_MM_PREAMBLE;
+ if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD)
+ mimo_preamble_type = BRCMS_GF_PREAMBLE;
+
+ if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
+ && (!is_mcs_rate(rspec[k]))) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_"
+ "RC_MCS != is_mcs_rate(rspec)\n",
+ wlc->pub->unit, __func__);
+ }
+
+ if (is_mcs_rate(rspec[k])) {
+ preamble_type[k] = mimo_preamble_type;
+
+ /*
+ * if SGI is selected, then forced mm
+ * for single stream
+ */
+ if ((rspec[k] & RSPEC_SHORT_GI)
+ && is_single_stream(rspec[k] &
+ RSPEC_RATE_MASK))
+ preamble_type[k] = BRCMS_MM_PREAMBLE;
+ }
+
+ /* should be better conditionalized */
+ if (!is_mcs_rate(rspec[0])
+ && (tx_info->control.rates[0].
+ flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
+ preamble_type[k] = BRCMS_SHORT_PREAMBLE;
+ }
+ } else {
+ for (k = 0; k < hw->max_rates; k++) {
+ /* Set ctrlchbw as 20Mhz */
+ rspec[k] &= ~RSPEC_BW_MASK;
+ rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT);
+
+ /* for nphy, stf of ofdm frames must follow policies */
+ if (BRCMS_ISNPHY(wlc->band) && is_ofdm_rate(rspec[k])) {
+ rspec[k] &= ~RSPEC_STF_MASK;
+ rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT;
+ }
+ }
+ }
+
+ /* Reset these for use with AMPDU's */
+ txrate[0]->count = 0;
+ txrate[1]->count = 0;
+
+ /* (2) PROTECTION, may change rspec */
+ if ((ieee80211_is_data(h->frame_control) ||
+ ieee80211_is_mgmt(h->frame_control)) &&
+ (phylen > wlc->RTSThresh) && !is_multicast_ether_addr(h->addr1))
+ use_rts = true;
+
+ /* (3) PLCP: determine PLCP header and MAC duration,
+ * fill struct d11txh */
+ brcms_c_compute_plcp(wlc, rspec[0], phylen, plcp);
+ brcms_c_compute_plcp(wlc, rspec[1], phylen, plcp_fallback);
+ memcpy(&txh->FragPLCPFallback,
+ plcp_fallback, sizeof(txh->FragPLCPFallback));
+
+ /* Length field now put in CCK FBR CRC field */
+ if (is_cck_rate(rspec[1])) {
+ txh->FragPLCPFallback[4] = phylen & 0xff;
+ txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8;
+ }
+
+ /* MIMO-RATE: need validation ?? */
+ mainrates = is_ofdm_rate(rspec[0]) ?
+ D11A_PHY_HDR_GRATE((struct ofdm_phy_hdr *) plcp) :
+ plcp[0];
+
+ /* DUR field for main rate */
+ if (!ieee80211_is_pspoll(h->frame_control) &&
+ !is_multicast_ether_addr(h->addr1) && !use_rifs) {
+ durid =
+ brcms_c_compute_frame_dur(wlc, rspec[0], preamble_type[0],
+ next_frag_len);
+ h->duration_id = cpu_to_le16(durid);
+ } else if (use_rifs) {
+ /* NAV protect to end of next max packet size */
+ durid =
+ (u16) brcms_c_calc_frame_time(wlc, rspec[0],
+ preamble_type[0],
+ DOT11_MAX_FRAG_LEN);
+ durid += RIFS_11N_TIME;
+ h->duration_id = cpu_to_le16(durid);
+ }
+
+ /* DUR field for fallback rate */
+ if (ieee80211_is_pspoll(h->frame_control))
+ txh->FragDurFallback = h->duration_id;
+ else if (is_multicast_ether_addr(h->addr1) || use_rifs)
+ txh->FragDurFallback = 0;
+ else {
+ durid = brcms_c_compute_frame_dur(wlc, rspec[1],
+ preamble_type[1], next_frag_len);
+ txh->FragDurFallback = cpu_to_le16(durid);
+ }
+
+ /* (4) MAC-HDR: MacTxControlLow */
+ if (frag == 0)
+ mcl |= TXC_STARTMSDU;
+
+ if (!is_multicast_ether_addr(h->addr1))
+ mcl |= TXC_IMMEDACK;
+
+ if (wlc->band->bandtype == BRCM_BAND_5G)
+ mcl |= TXC_FREQBAND_5G;
+
+ if (CHSPEC_IS40(wlc_phy_chanspec_get(wlc->band->pi)))
+ mcl |= TXC_BW_40;
+
+ /* set AMIC bit if using hardware TKIP MIC */
+ if (hwtkmic)
+ mcl |= TXC_AMIC;
+
+ txh->MacTxControlLow = cpu_to_le16(mcl);
+
+ /* MacTxControlHigh */
+ mch = 0;
+
+ /* Set fallback rate preamble type */
+ if ((preamble_type[1] == BRCMS_SHORT_PREAMBLE) ||
+ (preamble_type[1] == BRCMS_GF_PREAMBLE)) {
+ if (rspec2rate(rspec[1]) != BRCM_RATE_1M)
+ mch |= TXC_PREAMBLE_DATA_FB_SHORT;
+ }
+
+ /* MacFrameControl */
+ memcpy(&txh->MacFrameControl, &h->frame_control, sizeof(u16));
+ txh->TxFesTimeNormal = cpu_to_le16(0);
+
+ txh->TxFesTimeFallback = cpu_to_le16(0);
+
+ /* TxFrameRA */
+ memcpy(&txh->TxFrameRA, &h->addr1, ETH_ALEN);
+
+ /* TxFrameID */
+ txh->TxFrameID = cpu_to_le16(frameid);
+
+ /*
+ * TxStatus, Note the case of recreating the first frag of a suppressed
+ * frame then we may need to reset the retry cnt's via the status reg
+ */
+ txh->TxStatus = cpu_to_le16(status);
+
+ /*
+ * extra fields for ucode AMPDU aggregation, the new fields are added to
+ * the END of previous structure so that it's compatible in driver.
+ */
+ txh->MaxNMpdus = cpu_to_le16(0);
+ txh->MaxABytes_MRT = cpu_to_le16(0);
+ txh->MaxABytes_FBR = cpu_to_le16(0);
+ txh->MinMBytes = cpu_to_le16(0);
+
+ /* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration,
+ * furnish struct d11txh */
+ /* RTS PLCP header and RTS frame */
+ if (use_rts || use_cts) {
+ if (use_rts && use_cts)
+ use_cts = false;
+
+ for (k = 0; k < 2; k++) {
+ rts_rspec[k] = brcms_c_rspec_to_rts_rspec(wlc, rspec[k],
+ false,
+ mimo_ctlchbw);
+ }
+
+ if (!is_ofdm_rate(rts_rspec[0]) &&
+ !((rspec2rate(rts_rspec[0]) == BRCM_RATE_1M) ||
+ (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
+ rts_preamble_type[0] = BRCMS_SHORT_PREAMBLE;
+ mch |= TXC_PREAMBLE_RTS_MAIN_SHORT;
+ }
+
+ if (!is_ofdm_rate(rts_rspec[1]) &&
+ !((rspec2rate(rts_rspec[1]) == BRCM_RATE_1M) ||
+ (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
+ rts_preamble_type[1] = BRCMS_SHORT_PREAMBLE;
+ mch |= TXC_PREAMBLE_RTS_FB_SHORT;
+ }
+
+ /* RTS/CTS additions to MacTxControlLow */
+ if (use_cts) {
+ txh->MacTxControlLow |= cpu_to_le16(TXC_SENDCTS);
+ } else {
+ txh->MacTxControlLow |= cpu_to_le16(TXC_SENDRTS);
+ txh->MacTxControlLow |= cpu_to_le16(TXC_LONGFRAME);
+ }
+
+ /* RTS PLCP header */
+ rts_plcp = txh->RTSPhyHeader;
+ if (use_cts)
+ rts_phylen = DOT11_CTS_LEN + FCS_LEN;
+ else
+ rts_phylen = DOT11_RTS_LEN + FCS_LEN;
+
+ brcms_c_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp);
+
+ /* fallback rate version of RTS PLCP header */
+ brcms_c_compute_plcp(wlc, rts_rspec[1], rts_phylen,
+ rts_plcp_fallback);
+ memcpy(&txh->RTSPLCPFallback, rts_plcp_fallback,
+ sizeof(txh->RTSPLCPFallback));
+
+ /* RTS frame fields... */
+ rts = (struct ieee80211_rts *)&txh->rts_frame;
+
+ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec[0],
+ rspec[0], rts_preamble_type[0],
+ preamble_type[0], phylen, false);
+ rts->duration = cpu_to_le16(durid);
+ /* fallback rate version of RTS DUR field */
+ durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
+ rts_rspec[1], rspec[1],
+ rts_preamble_type[1],
+ preamble_type[1], phylen, false);
+ txh->RTSDurFallback = cpu_to_le16(durid);
+
+ if (use_cts) {
+ rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
+ IEEE80211_STYPE_CTS);
+
+ memcpy(&rts->ra, &h->addr2, ETH_ALEN);
+ } else {
+ rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
+ IEEE80211_STYPE_RTS);
+
+ memcpy(&rts->ra, &h->addr1, 2 * ETH_ALEN);
+ }
+
+ /* mainrate
+ * low 8 bits: main frag rate/mcs,
+ * high 8 bits: rts/cts rate/mcs
+ */
+ mainrates |= (is_ofdm_rate(rts_rspec[0]) ?
+ D11A_PHY_HDR_GRATE(
+ (struct ofdm_phy_hdr *) rts_plcp) :
+ rts_plcp[0]) << 8;
+ } else {
+ memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN);
+ memset((char *)&txh->rts_frame, 0,
+ sizeof(struct ieee80211_rts));
+ memset((char *)txh->RTSPLCPFallback, 0,
+ sizeof(txh->RTSPLCPFallback));
+ txh->RTSDurFallback = 0;
+ }
+
+#ifdef SUPPORT_40MHZ
+ /* add null delimiter count */
+ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && is_mcs_rate(rspec))
+ txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] =
+ brcm_c_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen);
+
+#endif
+
+ /*
+ * Now that RTS/RTS FB preamble types are updated, write
+ * the final value
+ */
+ txh->MacTxControlHigh = cpu_to_le16(mch);
+
+ /*
+ * MainRates (both the rts and frag plcp rates have
+ * been calculated now)
+ */
+ txh->MainRates = cpu_to_le16(mainrates);
+
+ /* XtraFrameTypes */
+ xfts = frametype(rspec[1], wlc->mimoft);
+ xfts |= (frametype(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT);
+ xfts |= (frametype(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT);
+ xfts |= CHSPEC_CHANNEL(wlc_phy_chanspec_get(wlc->band->pi)) <<
+ XFTS_CHANNEL_SHIFT;
+ txh->XtraFrameTypes = cpu_to_le16(xfts);
+
+ /* PhyTxControlWord */
+ phyctl = frametype(rspec[0], wlc->mimoft);
+ if ((preamble_type[0] == BRCMS_SHORT_PREAMBLE) ||
+ (preamble_type[0] == BRCMS_GF_PREAMBLE)) {
+ if (rspec2rate(rspec[0]) != BRCM_RATE_1M)
+ phyctl |= PHY_TXC_SHORT_HDR;
+ }
+
+ /* phytxant is properly bit shifted */
+ phyctl |= brcms_c_stf_d11hdrs_phyctl_txant(wlc, rspec[0]);
+ txh->PhyTxControlWord = cpu_to_le16(phyctl);
+
+ /* PhyTxControlWord_1 */
+ if (BRCMS_PHY_11N_CAP(wlc->band)) {
+ u16 phyctl1 = 0;
+
+ phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[0]);
+ txh->PhyTxControlWord_1 = cpu_to_le16(phyctl1);
+ phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[1]);
+ txh->PhyTxControlWord_1_Fbr = cpu_to_le16(phyctl1);
+
+ if (use_rts || use_cts) {
+ phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[0]);
+ txh->PhyTxControlWord_1_Rts = cpu_to_le16(phyctl1);
+ phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[1]);
+ txh->PhyTxControlWord_1_FbrRts = cpu_to_le16(phyctl1);
+ }
+
+ /*
+ * For mcs frames, if mixedmode(overloaded with long preamble)
+ * is going to be set, fill in non-zero MModeLen and/or
+ * MModeFbrLen it will be unnecessary if they are separated
+ */
+ if (is_mcs_rate(rspec[0]) &&
+ (preamble_type[0] == BRCMS_MM_PREAMBLE)) {
+ u16 mmodelen =
+ brcms_c_calc_lsig_len(wlc, rspec[0], phylen);
+ txh->MModeLen = cpu_to_le16(mmodelen);
+ }
+
+ if (is_mcs_rate(rspec[1]) &&
+ (preamble_type[1] == BRCMS_MM_PREAMBLE)) {
+ u16 mmodefbrlen =
+ brcms_c_calc_lsig_len(wlc, rspec[1], phylen);
+ txh->MModeFbrLen = cpu_to_le16(mmodefbrlen);
+ }
+ }
+
+ ac = skb_get_queue_mapping(p);
+ if ((scb->flags & SCB_WMECAP) && qos && wlc->edcf_txop[ac]) {
+ uint frag_dur, dur, dur_fallback;
+
+ /* WME: Update TXOP threshold */
+ if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) && frag == 0) {
+ frag_dur =
+ brcms_c_calc_frame_time(wlc, rspec[0],
+ preamble_type[0], phylen);
+
+ if (rts) {
+ /* 1 RTS or CTS-to-self frame */
+ dur =
+ brcms_c_calc_cts_time(wlc, rts_rspec[0],
+ rts_preamble_type[0]);
+ dur_fallback =
+ brcms_c_calc_cts_time(wlc, rts_rspec[1],
+ rts_preamble_type[1]);
+ /* (SIFS + CTS) + SIFS + frame + SIFS + ACK */
+ dur += le16_to_cpu(rts->duration);
+ dur_fallback +=
+ le16_to_cpu(txh->RTSDurFallback);
+ } else if (use_rifs) {
+ dur = frag_dur;
+ dur_fallback = 0;
+ } else {
+ /* frame + SIFS + ACK */
+ dur = frag_dur;
+ dur +=
+ brcms_c_compute_frame_dur(wlc, rspec[0],
+ preamble_type[0], 0);
+
+ dur_fallback =
+ brcms_c_calc_frame_time(wlc, rspec[1],
+ preamble_type[1],
+ phylen);
+ dur_fallback +=
+ brcms_c_compute_frame_dur(wlc, rspec[1],
+ preamble_type[1], 0);
+ }
+ /* NEED to set TxFesTimeNormal (hard) */
+ txh->TxFesTimeNormal = cpu_to_le16((u16) dur);
+ /*
+ * NEED to set fallback rate version of
+ * TxFesTimeNormal (hard)
+ */
+ txh->TxFesTimeFallback =
+ cpu_to_le16((u16) dur_fallback);
+
+ /*
+ * update txop byte threshold (txop minus intraframe
+ * overhead)
+ */
+ if (wlc->edcf_txop[ac] >= (dur - frag_dur)) {
+ uint newfragthresh;
+
+ newfragthresh =
+ brcms_c_calc_frame_len(wlc,
+ rspec[0], preamble_type[0],
+ (wlc->edcf_txop[ac] -
+ (dur - frag_dur)));
+ /* range bound the fragthreshold */
+ if (newfragthresh < DOT11_MIN_FRAG_LEN)
+ newfragthresh =
+ DOT11_MIN_FRAG_LEN;
+ else if (newfragthresh >
+ wlc->usr_fragthresh)
+ newfragthresh =
+ wlc->usr_fragthresh;
+ /* update the fragthresh and do txc update */
+ if (wlc->fragthresh[queue] !=
+ (u16) newfragthresh)
+ wlc->fragthresh[queue] =
+ (u16) newfragthresh;
+ } else {
+ wiphy_err(wlc->wiphy, "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 "
+ "exceeded phylen %d/%d dur %d/%d\n",
+ wlc->pub->unit, __func__,
+ fifo_names[queue],
+ phylen, wlc->fragthresh[queue],
+ dur, wlc->edcf_txop[ac]);
+ }
+ }
+
+ return 0;
+}
+
+void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
+ struct ieee80211_hw *hw)
+{
+ 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;
+
+ prec_map = wlc->tx_prec_map;
+
+ /* 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;
+ }
+ }
+}
+
+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.
+ */
+ 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) {
+ /*
+ * To inform the ucode of the last mcast frame posted
+ * so that it can clear moredata bit
+ */
+ brcms_b_write_shm(wlc->hw, M_BCMC_FID, frameid);
+ }
+
+ if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0)
+ wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n");
+}
+
+u32
+brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
+ bool use_rspec, u16 mimo_ctlchbw)
+{
+ u32 rts_rspec = 0;
+
+ if (use_rspec)
+ /* use frame rate as rts rate */
+ rts_rspec = rspec;
+ else if (wlc->band->gmode && wlc->protection->_g && !is_cck_rate(rspec))
+ /* Use 11Mbps as the g protection RTS target rate and fallback.
+ * Use the brcms_basic_rate() lookup to find the best basic rate
+ * under the target in case 11 Mbps is not Basic.
+ * 6 and 9 Mbps are not usually selected by rate selection, but
+ * even if the OFDM rate we are protecting is 6 or 9 Mbps, 11
+ * is more robust.
+ */
+ rts_rspec = brcms_basic_rate(wlc, BRCM_RATE_11M);
+ else
+ /* calculate RTS rate and fallback rate based on the frame rate
+ * RTS must be sent at a basic rate since it is a
+ * control frame, sec 9.6 of 802.11 spec
+ */
+ rts_rspec = brcms_basic_rate(wlc, rspec);
+
+ if (BRCMS_PHY_11N_CAP(wlc->band)) {
+ /* set rts txbw to correct side band */
+ rts_rspec &= ~RSPEC_BW_MASK;
+
+ /*
+ * if rspec/rspec_fallback is 40MHz, then send RTS on both
+ * 20MHz channel (DUP), otherwise send RTS on control channel
+ */
+ if (rspec_is40mhz(rspec) && !is_cck_rate(rts_rspec))
+ rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT);
+ else
+ rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
+
+ /* pick siso/cdd as default for ofdm */
+ if (is_ofdm_rate(rts_rspec)) {
+ rts_rspec &= ~RSPEC_STF_MASK;
+ rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
+ }
+ }
+ 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)
+{
+ /* wake up every DTIM is the default */
+ if (wlc->bcn_li_dtim == 1)
+ brcms_b_write_shm(wlc->hw, M_BCN_LI, 0);
+ else
+ brcms_b_write_shm(wlc->hw, M_BCN_LI,
+ (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn);
+}
+
+static void
+brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
+ u32 *tsf_h_ptr)
+{
+ struct d11regs __iomem *regs = wlc_hw->regs;
+
+ /* read the tsf timer low, then high to get an atomic read */
+ *tsf_l_ptr = R_REG(&regs->tsf_timerlow);
+ *tsf_h_ptr = R_REG(&regs->tsf_timerhigh);
+}
+
+/*
+ * recover 64bit TSF value from the 16bit TSF value in the rx header
+ * given the assumption that the TSF passed in header is within 65ms
+ * of the current tsf.
+ *
+ * 6 5 4 4 3 2 1
+ * 3.......6.......8.......0.......2.......4.......6.......8......0
+ * |<---------- tsf_h ----------->||<--- tsf_l -->||<-RxTSFTime ->|
+ *
+ * The RxTSFTime are the lowest 16 bits and provided by the ucode. The
+ * tsf_l is filled in by brcms_b_recv, which is done earlier in the
+ * receive call sequence after rx interrupt. Only the higher 16 bits
+ * are used. Finally, the tsf_h is read from the tsf register.
+ */
+static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc,
+ struct d11rxhdr *rxh)
+{
+ u32 tsf_h, tsf_l;
+ u16 rx_tsf_0_15, rx_tsf_16_31;
+
+ brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
+
+ rx_tsf_16_31 = (u16)(tsf_l >> 16);
+ rx_tsf_0_15 = rxh->RxTSFTime;
+
+ /*
+ * a greater tsf time indicates the low 16 bits of
+ * tsf_l wrapped, so decrement the high 16 bits.
+ */
+ if ((u16)tsf_l < rx_tsf_0_15) {
+ rx_tsf_16_31 -= 1;
+ if (rx_tsf_16_31 == 0xffff)
+ tsf_h -= 1;
+ }
+
+ return ((u64)tsf_h << 32) | (((u32)rx_tsf_16_31 << 16) + rx_tsf_0_15);
+}
+
+static void
+prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
+ struct sk_buff *p,
+ struct ieee80211_rx_status *rx_status)
+{
+ int preamble;
+ int channel;
+ u32 rspec;
+ unsigned char *plcp;
+
+ /* fill in TSF and flag its presence */
+ rx_status->mactime = brcms_c_recover_tsf64(wlc, rxh);
+ rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+
+ channel = BRCMS_CHAN_CHANNEL(rxh->RxChan);
+
+ if (channel > 14) {
+ rx_status->band = IEEE80211_BAND_5GHZ;
+ rx_status->freq = ieee80211_ofdm_chan_to_freq(
+ WF_CHAN_FACTOR_5_G/2, channel);
+
+ } else {
+ rx_status->band = IEEE80211_BAND_2GHZ;
+ rx_status->freq = ieee80211_dsss_chan_to_freq(channel);
+ }
+
+ rx_status->signal = wlc_phy_rssi_compute(wlc->hw->band->pi, rxh);
+
+ /* noise */
+ /* qual */
+ rx_status->antenna =
+ (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;
+
+ plcp = p->data;
+
+ rspec = brcms_c_compute_rspec(rxh, plcp);
+ if (is_mcs_rate(rspec)) {
+ rx_status->rate_idx = rspec & RSPEC_RATE_MASK;
+ rx_status->flag |= RX_FLAG_HT;
+ if (rspec_is40mhz(rspec))
+ rx_status->flag |= RX_FLAG_40MHZ;
+ } else {
+ switch (rspec2rate(rspec)) {
+ case BRCM_RATE_1M:
+ rx_status->rate_idx = 0;
+ break;
+ case BRCM_RATE_2M:
+ rx_status->rate_idx = 1;
+ break;
+ case BRCM_RATE_5M5:
+ rx_status->rate_idx = 2;
+ break;
+ case BRCM_RATE_11M:
+ rx_status->rate_idx = 3;
+ break;
+ case BRCM_RATE_6M:
+ rx_status->rate_idx = 4;
+ break;
+ case BRCM_RATE_9M:
+ rx_status->rate_idx = 5;
+ break;
+ case BRCM_RATE_12M:
+ rx_status->rate_idx = 6;
+ break;
+ case BRCM_RATE_18M:
+ rx_status->rate_idx = 7;
+ break;
+ case BRCM_RATE_24M:
+ rx_status->rate_idx = 8;
+ break;
+ case BRCM_RATE_36M:
+ rx_status->rate_idx = 9;
+ break;
+ case BRCM_RATE_48M:
+ rx_status->rate_idx = 10;
+ break;
+ case BRCM_RATE_54M:
+ rx_status->rate_idx = 11;
+ break;
+ default:
+ wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__);
+ }
+
+ /*
+ * For 5GHz, we should decrease the index as it is
+ * a subset of the 2.4G rates. See bitrates field
+ * of brcms_band_5GHz_nphy (in mac80211_if.c).
+ */
+ if (rx_status->band == IEEE80211_BAND_5GHZ)
+ rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET;
+
+ /* Determine short preamble and rate_idx */
+ preamble = 0;
+ if (is_cck_rate(rspec)) {
+ if (rxh->PhyRxStatus_0 & PRXS0_SHORTH)
+ rx_status->flag |= RX_FLAG_SHORTPRE;
+ } else if (is_ofdm_rate(rspec)) {
+ rx_status->flag |= RX_FLAG_SHORTPRE;
+ } else {
+ wiphy_err(wlc->wiphy, "%s: Unknown modulation\n",
+ __func__);
+ }
+ }
+
+ if (plcp3_issgi(plcp[3]))
+ rx_status->flag |= RX_FLAG_SHORT_GI;
+
+ if (rxh->RxStatus1 & RXS_DECERR) {
+ rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
+ wiphy_err(wlc->wiphy, "%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",
+ __func__);
+ }
+}
+
+static void
+brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
+ struct sk_buff *p)
+{
+ int len_mpdu;
+ struct ieee80211_rx_status rx_status;
+
+ memset(&rx_status, 0, sizeof(rx_status));
+ prep_mac80211_status(wlc, rxh, p, &rx_status);
+
+ /* mac header+body length, exclude CRC and plcp header */
+ len_mpdu = p->len - D11_PHY_HDR_LEN - FCS_LEN;
+ skb_pull(p, D11_PHY_HDR_LEN);
+ __skb_trim(p, len_mpdu);
+
+ memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
+}
+
+/* calculate frame duration for Mixed-mode L-SIG spoofing, return
+ * number of bytes goes in the length field
+ *
+ * Formula given by HT PHY Spec v 1.13
+ * len = 3(nsyms + nstream + 3) - 3
+ */
+u16
+brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
+ uint mac_len)
+{
+ 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) +
+ rspec_stc(ratespec);
+
+ /*
+ * the payload duration calculation matches that
+ * of regular ofdm
+ */
+ /* 1000Ndbps = kbps * 4 */
+ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+ rspec_issgi(ratespec)) * 4;
+
+ if (rspec_stc(ratespec) == 0)
+ nsyms =
+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+ APHY_TAIL_NBITS) * 1000, kNdps);
+ else
+ /* STBC needs to have even number of symbols */
+ nsyms =
+ 2 *
+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+ APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+
+ /* (+3) account for HT-SIG(2) and HT-STF(1) */
+ nsyms += (tot_streams + 3);
+ /*
+ * 3 bytes/symbol @ legacy 6Mbps rate
+ * (-3) excluding service bits and tail bits
+ */
+ len = (3 * nsyms) - 3;
+ }
+
+ return (u16) len;
+}
+
+static void
+brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
+{
+ const struct brcms_c_rateset *rs_dflt;
+ struct brcms_c_rateset rs;
+ u8 rate;
+ u16 entry_ptr;
+ u8 plcp[D11_PHY_HDR_LEN];
+ u16 dur, sifs;
+ uint i;
+
+ sifs = get_sifs(wlc->band);
+
+ rs_dflt = brcms_c_rateset_get_hwrs(wlc);
+
+ brcms_c_rateset_copy(rs_dflt, &rs);
+ brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+
+ /*
+ * walk the phy rate table and update MAC core SHM
+ * basic rate table entries
+ */
+ for (i = 0; i < rs.count; i++) {
+ rate = rs.rates[i] & BRCMS_RATE_MASK;
+
+ entry_ptr = brcms_b_rate_shm_offset(wlc->hw, rate);
+
+ /* Calculate the Probe Response PLCP for the given rate */
+ brcms_c_compute_plcp(wlc, rate, frame_len, plcp);
+
+ /*
+ * Calculate the duration of the Probe Response
+ * frame plus SIFS for the MAC
+ */
+ dur = (u16) brcms_c_calc_frame_time(wlc, rate,
+ BRCMS_LONG_PREAMBLE, frame_len);
+ dur += sifs;
+
+ /* Update the SHM Rate Table entry Probe Response values */
+ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS,
+ (u16) (plcp[0] + (plcp[1] << 8)));
+ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS + 2,
+ (u16) (plcp[2] + (plcp[3] << 8)));
+ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_DUR_POS, dur);
+ }
+}
+
+/* Max buffering needed for beacon template/prb resp template is 142 bytes.
+ *
+ * PLCP header is 6 bytes.
+ * 802.11 A3 header is 24 bytes.
+ * Max beacon frame body template length is 112 bytes.
+ * Max probe resp frame body template length is 110 bytes.
+ *
+ * *len on input contains the max length of the packet available.
+ *
+ * The *len value is set to the number of bytes in buf used, and starts
+ * with the PLCP and included up to, but not including, the 4 byte FCS.
+ */
+static void
+brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
+ u32 bcn_rspec,
+ struct brcms_bss_cfg *cfg, u16 *buf, int *len)
+{
+ static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
+ struct cck_phy_hdr *plcp;
+ struct ieee80211_mgmt *h;
+ int hdr_len, body_len;
+
+ hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
+
+ /* calc buffer size provided for frame body */
+ body_len = *len - hdr_len;
+ /* return actual size */
+ *len = hdr_len + body_len;
+
+ /* format PHY and MAC headers */
+ memset((char *)buf, 0, hdr_len);
+
+ plcp = (struct cck_phy_hdr *) buf;
+
+ /*
+ * PLCP for Probe Response frames are filled in from
+ * core's rate table
+ */
+ if (type == IEEE80211_STYPE_BEACON)
+ /* fill in PLCP */
+ brcms_c_compute_plcp(wlc, bcn_rspec,
+ (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
+ (u8 *) plcp);
+
+ /* "Regular" and 16 MBSS but not for 4 MBSS */
+ /* Update the phytxctl for the beacon based on the rspec */
+ brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
+
+ h = (struct ieee80211_mgmt *)&plcp[1];
+
+ /* fill in 802.11 header */
+ h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
+
+ /* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
+ /* A1 filled in by MAC for prb resp, broadcast for bcn */
+ if (type == IEEE80211_STYPE_BEACON)
+ memcpy(&h->da, &ether_bcast, ETH_ALEN);
+ memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN);
+ memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
+
+ /* SEQ filled in by MAC */
+}
+
+int brcms_c_get_header_len(void)
+{
+ return TXOFF;
+}
+
+/*
+ * Update all beacons for the system.
+ */
+void brcms_c_update_beacon(struct brcms_c_info *wlc)
+{
+ struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
+
+ if (bsscfg->up && !bsscfg->BSS)
+ /* Clear the soft intmask */
+ wlc->defmacintmask &= ~MI_BCNTPL;
+}
+
+/* Write ssid into shared memory */
+static void
+brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
+{
+ u8 *ssidptr = cfg->SSID;
+ u16 base = M_SSID;
+ u8 ssidbuf[IEEE80211_MAX_SSID_LEN];
+
+ /* padding the ssid with zero and copy it into shm */
+ memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN);
+ memcpy(ssidbuf, ssidptr, cfg->SSID_len);
+
+ brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN);
+ brcms_b_write_shm(wlc->hw, M_SSIDLEN, (u16) cfg->SSID_len);
+}
+
+static void
+brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
+ struct brcms_bss_cfg *cfg,
+ bool suspend)
+{
+ u16 prb_resp[BCN_TMPL_LEN / 2];
+ int len = BCN_TMPL_LEN;
+
+ /*
+ * write the probe response to hardware, or save in
+ * the config structure
+ */
+
+ /* create the probe response template */
+ brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
+ cfg, prb_resp, &len);
+
+ if (suspend)
+ brcms_c_suspend_mac_and_wait(wlc);
+
+ /* write the probe response into the template region */
+ brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
+ (len + 3) & ~3, prb_resp);
+
+ /* write the length of the probe response frame (+PLCP/-FCS) */
+ brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len);
+
+ /* write the SSID and SSID length */
+ brcms_c_shm_ssid_upd(wlc, cfg);
+
+ /*
+ * Write PLCP headers and durations for probe response frames
+ * at all rates. Use the actual frame length covered by the
+ * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table()
+ * by subtracting the PLCP len and adding the FCS.
+ */
+ len += (-D11_PHY_HDR_LEN + FCS_LEN);
+ brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
+
+ if (suspend)
+ brcms_c_enable_mac(wlc);
+}
+
+void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
+{
+ struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
+
+ /* update AP or IBSS probe responses */
+ if (bsscfg->up && !bsscfg->BSS)
+ 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)
+{
+ if (fifo >= NFIFO)
+ return -EINVAL;
+
+ *blocks = wlc_hw->xmtfifo_sz[fifo];
+
+ return 0;
+}
+
+void
+brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
+ const u8 *addr)
+{
+ brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr);
+ if (match_reg_offset == RCM_BSSID_OFFSET)
+ memcpy(wlc->bsscfg->BSSID, addr, ETH_ALEN);
+}
+
+/*
+ * Flag 'scan in progress' to withhold dynamic phy calibration
+ */
+void brcms_c_scan_start(struct brcms_c_info *wlc)
+{
+ wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
+}
+
+void brcms_c_scan_stop(struct brcms_c_info *wlc)
+{
+ wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
+}
+
+void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
+{
+ wlc->pub->associated = state;
+ wlc->bsscfg->associated = state;
+}
+
+/*
+ * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
+ * AMPDU traffic, packets pending in hardware have to be invalidated so that
+ * when later on hardware releases them, they can be handled appropriately.
+ */
+void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
+ struct ieee80211_sta *sta,
+ void (*dma_callback_fn))
+{
+ struct dma_pub *dmah;
+ int i;
+ for (i = 0; i < NFIFO; i++) {
+ dmah = hw->di[i];
+ if (dmah != NULL)
+ dma_walk_packets(dmah, dma_callback_fn, sta);
+ }
+}
+
+int brcms_c_get_curband(struct brcms_c_info *wlc)
+{
+ return wlc->band->bandunit;
+}
+
+void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
+{
+ /* flush packet queue when requested */
+ if (drop)
+ brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
+
+ /* wait for queue and DMA fifos to run dry */
+ while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0)
+ brcms_msleep(wlc->wl, 1);
+}
+
+void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
+{
+ wlc->bcn_li_bcn = interval;
+ if (wlc->pub->up)
+ brcms_c_bcn_li_upd(wlc);
+}
+
+int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr)
+{
+ uint qdbm;
+
+ /* Remove override bit and clip to max qdbm value */
+ qdbm = min_t(uint, txpwr * BRCMS_TXPWR_DB_FACTOR, 0xff);
+ return wlc_phy_txpower_set(wlc->band->pi, qdbm, false);
+}
+
+int brcms_c_get_tx_power(struct brcms_c_info *wlc)
+{
+ uint qdbm;
+ bool override;
+
+ wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override);
+
+ /* Return qdbm units */
+ return (int)(qdbm / BRCMS_TXPWR_DB_FACTOR);
+}
+
+void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc)
+{
+ wlc->mpc = mpc;
+ brcms_c_radio_mpc_upd(wlc);
+}
+
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
+{
+ struct d11rxhdr *rxh;
+ struct ieee80211_hdr *h;
+ uint len;
+ bool is_amsdu;
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+ /* frame starts with rxhdr */
+ rxh = (struct d11rxhdr *) (p->data);
+
+ /* strip off rxhdr */
+ skb_pull(p, BRCMS_HWRXOFF);
+
+ /* 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);
+ goto toss;
+ }
+ skb_pull(p, 2);
+ }
+
+ h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
+ len = p->len;
+
+ if (rxh->RxStatus1 & RXS_FCSERR) {
+ if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
+ wiphy_err(wlc->wiphy, "FCSERR while scanning******* -"
+ " tossing\n");
+ goto toss;
+ } else {
+ wiphy_err(wlc->wiphy, "RCSERR!!!\n");
+ goto toss;
+ }
+ }
+
+ /* check received pkt has at least frame control field */
+ if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control))
+ goto toss;
+
+ /* not supporting A-MSDU */
+ is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
+ if (is_amsdu)
+ goto toss;
+
+ brcms_c_recvctl(wlc, rxh, p);
+ return;
+
+ toss:
+ brcmu_pkt_buf_free_skb(p);
+}
+
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+static bool
+brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
+{
+ struct sk_buff *p;
+ struct sk_buff *head = NULL;
+ struct sk_buff *tail = NULL;
+ uint n = 0;
+ uint bound_limit = bound ? RXBND : -1;
+
+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+ /* gather received frames */
+ while ((p = dma_rx(wlc_hw->di[fifo]))) {
+
+ if (!tail)
+ head = tail = p;
+ else {
+ tail->prev = p;
+ tail = p;
+ }
+
+ /* !give others some time to run! */
+ if (++n >= bound_limit)
+ break;
+ }
+
+ /* post more rbufs */
+ dma_rxfill(wlc_hw->di[fifo]);
+
+ /* process each frame */
+ while ((p = head) != NULL) {
+ struct d11rxhdr_le *rxh_le;
+ struct d11rxhdr *rxh;
+ head = head->prev;
+ p->prev = NULL;
+
+ rxh_le = (struct d11rxhdr_le *)p->data;
+ rxh = (struct d11rxhdr *)p->data;
+
+ /* fixup rx header endianness */
+ rxh->RxFrameSize = le16_to_cpu(rxh_le->RxFrameSize);
+ rxh->PhyRxStatus_0 = le16_to_cpu(rxh_le->PhyRxStatus_0);
+ rxh->PhyRxStatus_1 = le16_to_cpu(rxh_le->PhyRxStatus_1);
+ rxh->PhyRxStatus_2 = le16_to_cpu(rxh_le->PhyRxStatus_2);
+ rxh->PhyRxStatus_3 = le16_to_cpu(rxh_le->PhyRxStatus_3);
+ rxh->PhyRxStatus_4 = le16_to_cpu(rxh_le->PhyRxStatus_4);
+ rxh->PhyRxStatus_5 = le16_to_cpu(rxh_le->PhyRxStatus_5);
+ rxh->RxStatus1 = le16_to_cpu(rxh_le->RxStatus1);
+ rxh->RxStatus2 = le16_to_cpu(rxh_le->RxStatus2);
+ rxh->RxTSFTime = le16_to_cpu(rxh_le->RxTSFTime);
+ rxh->RxChan = le16_to_cpu(rxh_le->RxChan);
+
+ brcms_c_recv(wlc_hw->wlc, p);
+ }
+
+ return n >= bound_limit;
+}
+
+/* second-level interrupt processing
+ * Return true if another dpc needs to be re-scheduled. false otherwise.
+ * Param 'bounded' indicates if applicable loops should be bounded.
+ */
+bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
+{
+ u32 macintstatus;
+ struct brcms_hardware *wlc_hw = wlc->hw;
+ struct d11regs __iomem *regs = wlc_hw->regs;
+ struct wiphy *wiphy = wlc->wiphy;
+
+ if (brcms_deviceremoved(wlc)) {
+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+ __func__);
+ brcms_down(wlc->wl);
+ return false;
+ }
+
+ /* grab and clear the saved software intstatus bits */
+ macintstatus = wlc->macintstatus;
+ wlc->macintstatus = 0;
+
+ BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
+ wlc_hw->unit, macintstatus);
+
+ WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
+
+ /* tx status */
+ if (macintstatus & MI_TFS) {
+ bool fatal;
+ if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
+ wlc->macintstatus |= MI_TFS;
+ if (fatal) {
+ wiphy_err(wiphy, "MI_TFS: fatal\n");
+ goto fatal;
+ }
+ }
+
+ if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
+ brcms_c_tbtt(wlc);
+
+ /* ATIM window end */
+ if (macintstatus & MI_ATIMWINEND) {
+ BCMMSG(wlc->wiphy, "end of ATIM window\n");
+ OR_REG(&regs->maccommand, wlc->qvalid);
+ wlc->qvalid = 0;
+ }
+
+ /*
+ * received data or control frame, MI_DMAINT is
+ * indication of RX_FIFO interrupt
+ */
+ if (macintstatus & MI_DMAINT)
+ if (brcms_b_recv(wlc_hw, RX_FIFO, bounded))
+ wlc->macintstatus |= MI_DMAINT;
+
+ /* noise sample collected */
+ if (macintstatus & MI_BG_NOISE)
+ wlc_phy_noise_sample_intr(wlc_hw->band->pi);
+
+ if (macintstatus & MI_GP0) {
+ wiphy_err(wiphy, "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",
+ __func__, wlc_hw->sih->chip,
+ wlc_hw->sih->chiprev);
+ /* big hammer */
+ brcms_init(wlc->wl);
+ }
+
+ /* gptimer timeout */
+ if (macintstatus & MI_TO)
+ W_REG(&regs->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_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;
+
+ fatal:
+ brcms_init(wlc->wl);
+ return wlc->macintstatus != 0;
+}
+
+void brcms_c_init(struct brcms_c_info *wlc)
+{
+ struct d11regs __iomem *regs;
+ u16 chanspec;
+ bool mute = false;
+
+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+ regs = wlc->regs;
+
+ /*
+ * This will happen if a big-hammer was executed. In
+ * that case, we want to go back to the channel that
+ * we were on and not new channel
+ */
+ if (wlc->pub->associated)
+ chanspec = wlc->home_chanspec;
+ else
+ chanspec = brcms_c_init_chanspec(wlc);
+
+ brcms_b_init(wlc->hw, chanspec, mute);
+
+ /* update beacon listen interval */
+ brcms_c_bcn_li_upd(wlc);
+
+ /* write ethernet address to core */
+ brcms_c_set_mac(wlc->bsscfg);
+ brcms_c_set_bssid(wlc->bsscfg);
+
+ /* Update tsf_cfprep if associated and up */
+ if (wlc->pub->associated && wlc->bsscfg->up) {
+ u32 bi;
+
+ /* get beacon period and convert to uS */
+ bi = wlc->bsscfg->current_bss->beacon_period << 10;
+ /*
+ * update since init path would reset
+ * to default value
+ */
+ W_REG(&regs->tsf_cfprep,
+ (bi << CFPREP_CBI_SHIFT));
+
+ /* Update maccontrol PM related bits */
+ brcms_c_set_ps_ctrl(wlc);
+ }
+
+ brcms_c_bandinit_ordered(wlc, chanspec);
+
+ /* init probe response timeout */
+ brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout);
+
+ /* init max burst txop (framebursting) */
+ brcms_b_write_shm(wlc->hw, M_MBURST_TXOP,
+ (wlc->
+ _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
+
+ /* initialize maximum allowed duty cycle */
+ brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
+ brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
+
+ /*
+ * Update some shared memory locations related to
+ * max AMPDU size allowed to received
+ */
+ brcms_c_ampdu_shm_upd(wlc->ampdu);
+
+ /* band-specific inits */
+ brcms_c_bsinit(wlc);
+
+ /* Enable EDCF mode (while the MAC is suspended) */
+ OR_REG(&regs->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 =
+ brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16);
+ wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR);
+ }
+
+ /* ..now really unleash hell (allow the MAC out of suspend) */
+ brcms_c_enable_mac(wlc);
+
+ /* clear tx flow control */
+ brcms_c_txflowcontrol_reset(wlc);
+
+ /* enable the RF Disable Delay timer */
+ W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
+
+ /* initialize mpc delay */
+ wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
+
+ /*
+ * Initialize WME parameters; if they haven't been set by some other
+ * mechanism (IOVar, etc) then read them from the hardware.
+ */
+ if (GFIELD(wlc->wme_retries[0], EDCF_SHORT) == 0) {
+ /* Uninitialized; read from HW */
+ int ac;
+
+ for (ac = 0; ac < AC_COUNT; ac++)
+ wlc->wme_retries[ac] =
+ brcms_b_read_shm(wlc->hw, M_AC_TXLMT_ADDR(ac));
+ }
+}
+
+/*
+ * The common driver entry routine. Error codes should be unique
+ */
+struct brcms_c_info *
+brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
+ bool piomode, void __iomem *regsva, struct pci_dev *btparam,
+ uint *perr)
+{
+ struct brcms_c_info *wlc;
+ uint err = 0;
+ uint i, j;
+ struct brcms_pub *pub;
+
+ /* allocate struct brcms_c_info state and its substructures */
+ wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device);
+ if (wlc == NULL)
+ goto fail;
+ wlc->wiphy = wl->wiphy;
+ pub = wlc->pub;
+
+#if defined(BCMDBG)
+ wlc_info_dbg = wlc;
+#endif
+
+ wlc->band = wlc->bandstate[0];
+ wlc->core = wlc->corestate;
+ wlc->wl = wl;
+ pub->unit = unit;
+ pub->_piomode = piomode;
+ wlc->bandinit_pending = false;
+
+ /* populate struct brcms_c_info with default values */
+ brcms_c_info_init(wlc, unit);
+
+ /* update sta/ap related parameters */
+ brcms_c_ap_upd(wlc);
+
+ /*
+ * low level attach steps(all hw accesses go
+ * inside, no more in rest of the attach)
+ */
+ err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva,
+ btparam);
+ if (err)
+ goto fail;
+
+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, OFF);
+
+ pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band);
+
+ /* disable allowed duty cycle */
+ wlc->tx_duty_cycle_ofdm = 0;
+ wlc->tx_duty_cycle_cck = 0;
+
+ brcms_c_stf_phy_chain_calc(wlc);
+
+ /* txchain 1: txant 0, txchain 2: txant 1 */
+ if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
+ wlc->stf->txant = wlc->stf->hw_txchain - 1;
+
+ /* push to BMAC driver */
+ wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
+ wlc->stf->hw_rxchain);
+
+ /* pull up some info resulting from the low attach */
+ for (i = 0; i < NFIFO; i++)
+ wlc->core->txavail[i] = wlc->hw->txavail[i];
+
+ memcpy(&wlc->perm_etheraddr, &wlc->hw->etheraddr, ETH_ALEN);
+ memcpy(&pub->cur_etheraddr, &wlc->hw->etheraddr, ETH_ALEN);
+
+ for (j = 0; j < wlc->pub->_nbands; j++) {
+ wlc->band = wlc->bandstate[j];
+
+ if (!brcms_c_attach_stf_ant_init(wlc)) {
+ err = 24;
+ goto fail;
+ }
+
+ /* default contention windows size limits */
+ wlc->band->CWmin = APHY_CWMIN;
+ wlc->band->CWmax = PHY_CWMAX;
+
+ /* init gmode value */
+ if (wlc->band->bandtype == BRCM_BAND_2G) {
+ wlc->band->gmode = GMODE_AUTO;
+ brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER,
+ wlc->band->gmode);
+ }
+
+ /* init _n_enab supported mode */
+ if (BRCMS_PHY_11N_CAP(wlc->band)) {
+ pub->_n_enab = SUPPORT_11N;
+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
+ ((pub->_n_enab ==
+ SUPPORT_11N) ? WL_11N_2x2 :
+ WL_11N_3x3));
+ }
+
+ /* init per-band default rateset, depend on band->gmode */
+ brcms_default_rateset(wlc, &wlc->band->defrateset);
+
+ /* fill in hw_rateset */
+ brcms_c_rateset_filter(&wlc->band->defrateset,
+ &wlc->band->hw_rateset, false,
+ BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
+ (bool) (wlc->pub->_n_enab & SUPPORT_11N));
+ }
+
+ /*
+ * update antenna config due to
+ * wlc->stf->txant/txchain/ant_rx_ovr change
+ */
+ brcms_c_stf_phy_txant_upd(wlc);
+
+ /* attach each modules */
+ err = brcms_c_attach_module(wlc);
+ if (err != 0)
+ goto fail;
+
+ if (!brcms_c_timers_init(wlc, unit)) {
+ wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit,
+ __func__);
+ err = 32;
+ goto fail;
+ }
+
+ /* depend on rateset, gmode */
+ wlc->cmi = brcms_c_channel_mgr_attach(wlc);
+ if (!wlc->cmi) {
+ wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed"
+ "\n", unit, __func__);
+ err = 33;
+ goto fail;
+ }
+
+ /* init default when all parameters are ready, i.e. ->rateset */
+ brcms_c_bss_default_init(wlc);
+
+ /*
+ * 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;
+ wlc->mimo_40txbw = AUTO;
+ wlc->ofdm_40txbw = AUTO;
+ wlc->cck_40txbw = AUTO;
+ brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G);
+
+ /* Set default values of SGI */
+ if (BRCMS_SGI_CAP_PHY(wlc)) {
+ brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
+ BRCMS_N_SGI_40));
+ } else if (BRCMS_ISSSLPNPHY(wlc->band)) {
+ brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
+ BRCMS_N_SGI_40));
+ } else {
+ brcms_c_ht_update_sgi_rx(wlc, 0);
+ }
+
+ /* initialize radio_mpc_disable according to wlc->mpc */
+ brcms_c_radio_mpc_upd(wlc);
+ brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail);
+
+ if (perr)
+ *perr = 0;
+
+ return wlc;
+
+ fail:
+ wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n",
+ unit, __func__, err);
+ if (wlc)
+ brcms_c_detach(wlc);
+
+ if (perr)
+ *perr = err;
+ return NULL;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
new file mode 100644
index 000000000000..c0e0fcfdfaf8
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
@@ -0,0 +1,735 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_MAIN_H_
+#define _BRCM_MAIN_H_
+
+#include <linux/etherdevice.h>
+
+#include <brcmu_utils.h>
+#include "types.h"
+#include "d11.h"
+#include "scb.h"
+
+#define INVCHANNEL 255 /* invalid channel */
+
+/* max # brcms_c_module_register() calls */
+#define BRCMS_MAXMODULES 22
+
+#define SEQNUM_SHIFT 4
+#define SEQNUM_MAX 0x1000
+
+#define NTXRATE 64 /* # tx MPDUs rate is reported for */
+
+/* Maximum wait time for a MAC suspend */
+/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */
+#define BRCMS_MAX_MAC_SUSPEND 83000
+
+/* responses for probe requests older that this are tossed, zero to disable */
+#define BRCMS_PRB_RESP_TIMEOUT 0 /* Disable probe response timeout */
+
+/* transmit buffer max headroom for protocol headers */
+#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN)
+
+#define AC_COUNT 4
+
+/* Macros for doing definition and get/set of bitfields
+ * Usage example, e.g. a three-bit field (bits 4-6):
+ * #define <NAME>_M BITFIELD_MASK(3)
+ * #define <NAME>_S 4
+ * ...
+ * regval = R_REG(osh, &regs->regfoo);
+ * field = GFIELD(regval, <NAME>);
+ * regval = SFIELD(regval, <NAME>, 1);
+ * W_REG(osh, &regs->regfoo, regval);
+ */
+#define BITFIELD_MASK(width) \
+ (((unsigned)1 << (width)) - 1)
+#define GFIELD(val, field) \
+ (((val) >> field ## _S) & field ## _M)
+#define SFIELD(val, field, bits) \
+ (((val) & (~(field ## _M << field ## _S))) | \
+ ((unsigned)(bits) << field ## _S))
+
+#define SW_TIMER_MAC_STAT_UPD 30 /* periodic MAC stats update */
+
+/* max # supported core revisions (0 .. MAXCOREREV - 1) */
+#define MAXCOREREV 28
+
+/* Double check that unsupported cores are not enabled */
+#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV)
+#error "Configuration for D11CONF includes unsupported versions."
+#endif /* Bad versions */
+
+/* values for shortslot_override */
+#define BRCMS_SHORTSLOT_AUTO -1 /* Driver will manage Shortslot setting */
+#define BRCMS_SHORTSLOT_OFF 0 /* Turn off short slot */
+#define BRCMS_SHORTSLOT_ON 1 /* Turn on short slot */
+
+/* value for short/long and mixmode/greenfield preamble */
+#define BRCMS_LONG_PREAMBLE (0)
+#define BRCMS_SHORT_PREAMBLE (1 << 0)
+#define BRCMS_GF_PREAMBLE (1 << 1)
+#define BRCMS_MM_PREAMBLE (1 << 2)
+#define BRCMS_IS_MIMO_PREAMBLE(_pre) (((_pre) == BRCMS_GF_PREAMBLE) || \
+ ((_pre) == BRCMS_MM_PREAMBLE))
+
+/* TxFrameID */
+/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */
+/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */
+#define TXFID_QUEUE_MASK 0x0007 /* Bits 0-2 */
+#define TXFID_SEQ_MASK 0x7FE0 /* Bits 5-15 */
+#define TXFID_SEQ_SHIFT 5 /* Number of bit shifts */
+#define TXFID_RATE_PROBE_MASK 0x8000 /* Bit 15 for rate probe */
+#define TXFID_RATE_MASK 0x0018 /* Mask for bits 3 and 4 */
+#define TXFID_RATE_SHIFT 3 /* Shift 3 bits for rate mask */
+
+/* promote boardrev */
+#define BOARDREV_PROMOTABLE 0xFF /* from */
+#define BOARDREV_PROMOTED 1 /* to */
+
+#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
+#define BRCMS_WAKE_OVERRIDE_MACSUSPEND 0x04
+#define BRCMS_WAKE_OVERRIDE_TXFIFO 0x08
+#define BRCMS_WAKE_OVERRIDE_FORCEFAST 0x10
+
+/* stuff pulled in from wlc.c */
+
+/* Interrupt bit error summary. Don't include I_RU: we refill DMA at other
+ * times; and if we run out, constant I_RU interrupts may cause lockup. We
+ * will still get error counts from rx0ovfl.
+ */
+#define I_ERRORS (I_PC | I_PD | I_DE | I_RO | I_XU)
+/* default software intmasks */
+#define DEF_RXINTMASK (I_RI) /* enable rx int on rxfifo only */
+#define DEF_MACINTMASK (MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \
+ MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \
+ MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP)
+
+#define MAXTXPKTS 6 /* max # pkts pending */
+
+/* frameburst */
+#define MAXTXFRAMEBURST 8 /* vanilla xpress mode: max frames/burst */
+#define MAXFRAMEBURST_TXOP 10000 /* Frameburst TXOP in usec */
+
+#define NFIFO 6 /* # tx/rx fifopairs */
+
+/* PLL requests */
+
+/* pll is shared on old chips */
+#define BRCMS_PLLREQ_SHARED 0x1
+/* hold pll for radio monitor register checking */
+#define BRCMS_PLLREQ_RADIO_MON 0x2
+/* hold/release pll for some short operation */
+#define BRCMS_PLLREQ_FLIP 0x4
+
+#define CHANNEL_BANDUNIT(wlc, ch) \
+ (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX)
+
+#define OTHERBANDUNIT(wlc) \
+ ((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX))
+
+/*
+ * 802.11 protection information
+ *
+ * _g: use g spec protection, driver internal.
+ * g_override: override for use of g spec protection.
+ * gmode_user: user config gmode, operating band->gmode is different.
+ * overlap: Overlap BSS/IBSS protection for both 11g and 11n.
+ * nmode_user: user config nmode, operating pub->nmode is different.
+ * n_cfg: use OFDM protection on MIMO frames.
+ * n_cfg_override: override for use of N protection.
+ * nongf: non-GF present protection.
+ * nongf_override: override for use of GF protection.
+ * n_pam_override: override for preamble: MM or GF.
+ * n_obss: indicated OBSS Non-HT STA present.
+*/
+struct brcms_protection {
+ bool _g;
+ s8 g_override;
+ u8 gmode_user;
+ s8 overlap;
+ s8 nmode_user;
+ s8 n_cfg;
+ s8 n_cfg_override;
+ bool nongf;
+ s8 nongf_override;
+ s8 n_pam_override;
+ bool n_obss;
+};
+
+/*
+ * anything affecting the single/dual streams/antenna operation
+ *
+ * hw_txchain: HW txchain bitmap cfg.
+ * txchain: txchain bitmap being used.
+ * txstreams: number of txchains being used.
+ * hw_rxchain: HW rxchain bitmap cfg.
+ * rxchain: rxchain bitmap being used.
+ * rxstreams: number of rxchains being used.
+ * ant_rx_ovr: rx antenna override.
+ * txant: userTx antenna setting.
+ * phytxant: phyTx antenna setting in txheader.
+ * ss_opmode: singlestream Operational mode, 0:siso; 1:cdd.
+ * ss_algosel_auto: if true, use wlc->stf->ss_algo_channel;
+ * else use wlc->band->stf->ss_mode_band.
+ * ss_algo_channel: ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC.
+ * rxchain_restore_delay: delay time to restore default rxchain.
+ * ldpc: AUTO/ON/OFF ldpc cap supported.
+ * txcore[MAX_STREAMS_SUPPORTED + 1]: bitmap of selected core for each Nsts.
+ * spatial_policy:
+ */
+struct brcms_stf {
+ u8 hw_txchain;
+ u8 txchain;
+ u8 txstreams;
+ u8 hw_rxchain;
+ u8 rxchain;
+ u8 rxstreams;
+ u8 ant_rx_ovr;
+ s8 txant;
+ u16 phytxant;
+ u8 ss_opmode;
+ bool ss_algosel_auto;
+ u16 ss_algo_channel;
+ u8 rxchain_restore_delay;
+ s8 ldpc;
+ u8 txcore[MAX_STREAMS_SUPPORTED + 1];
+ s8 spatial_policy;
+};
+
+#define BRCMS_STF_SS_STBC_TX(wlc, scb) \
+ (((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) \
+ || (((scb)->flags & SCB_STBCCAP) && \
+ (wlc)->band->band_stf_stbc_tx == AUTO && \
+ isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC))))
+
+#define BRCMS_STBC_CAP_PHY(wlc) (BRCMS_ISNPHY(wlc->band) && \
+ NREV_GE(wlc->band->phyrev, 3))
+
+#define BRCMS_SGI_CAP_PHY(wlc) ((BRCMS_ISNPHY(wlc->band) && \
+ NREV_GE(wlc->band->phyrev, 3)) || \
+ BRCMS_ISLCNPHY(wlc->band))
+
+#define BRCMS_CHAN_PHYTYPE(x) (((x) & RXS_CHAN_PHYTYPE_MASK) \
+ >> RXS_CHAN_PHYTYPE_SHIFT)
+#define BRCMS_CHAN_CHANNEL(x) (((x) & RXS_CHAN_ID_MASK) \
+ >> RXS_CHAN_ID_SHIFT)
+
+/*
+ * core state (mac)
+ */
+struct brcms_core {
+ uint coreidx; /* # sb enumerated core */
+
+ /* fifo */
+ uint *txavail[NFIFO]; /* # tx descriptors available */
+ s16 txpktpend[NFIFO]; /* tx admission control */
+
+ struct macstat *macstat_snapshot; /* mac hw prev read values */
+};
+
+/*
+ * band state (phy+ana+radio)
+ */
+struct brcms_band {
+ int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */
+ uint bandunit; /* bandstate[] index */
+
+ u16 phytype; /* phytype */
+ u16 phyrev;
+ u16 radioid;
+ u16 radiorev;
+ struct brcms_phy_pub *pi; /* pointer to phy specific information */
+ bool abgphy_encore;
+
+ u8 gmode; /* currently active gmode */
+
+ struct scb *hwrs_scb; /* permanent scb for hw rateset */
+
+ /* band-specific copy of default_bss.rateset */
+ struct brcms_c_rateset defrateset;
+
+ u8 band_stf_ss_mode; /* Configured STF type, 0:siso; 1:cdd */
+ s8 band_stf_stbc_tx; /* STBC TX 0:off; 1:force on; -1:auto */
+ /* rates supported by chip (phy-specific) */
+ struct brcms_c_rateset hw_rateset;
+ u8 basic_rate[BRCM_MAXRATE + 1]; /* basic rates indexed by rate */
+ bool mimo_cap_40; /* 40 MHz cap enabled on this band */
+ s8 antgain; /* antenna gain from srom */
+
+ u16 CWmin; /* minimum size of contention window, in unit of aSlotTime */
+ u16 CWmax; /* maximum size of contention window, in unit of aSlotTime */
+ struct ieee80211_supported_band band;
+};
+
+/* module control blocks */
+struct modulecb {
+ /* module name : NULL indicates empty array member */
+ char name[32];
+ /* handle passed when handler 'doiovar' is called */
+ struct brcms_info *hdl;
+
+ int (*down_fn)(void *handle); /* down handler. Note: the int returned
+ * by the down function is a count of the
+ * number of timers that could not be
+ * freed.
+ */
+
+};
+
+struct brcms_hw_band {
+ int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */
+ uint bandunit; /* bandstate[] index */
+ u16 mhfs[MHFMAX]; /* MHF array shadow */
+ u8 bandhw_stf_ss_mode; /* HW configured STF type, 0:siso; 1:cdd */
+ u16 CWmin;
+ u16 CWmax;
+ u32 core_flags;
+
+ u16 phytype; /* phytype */
+ u16 phyrev;
+ u16 radioid;
+ u16 radiorev;
+ struct brcms_phy_pub *pi; /* pointer to phy specific information */
+ bool abgphy_encore;
+};
+
+struct brcms_hardware {
+ bool _piomode; /* true if pio mode */
+ struct brcms_c_info *wlc;
+
+ /* fifo */
+ struct dma_pub *di[NFIFO]; /* dma handles, per fifo */
+
+ uint unit; /* device instance number */
+
+ /* version info */
+ u16 vendorid; /* PCI vendor id */
+ u16 deviceid; /* PCI device id */
+ uint corerev; /* core revision */
+ u8 sromrev; /* version # of the srom */
+ u16 boardrev; /* version # of particular board */
+ u32 boardflags; /* Board specific flags from srom */
+ u32 boardflags2; /* More board flags if sromrev >= 4 */
+ u32 machwcap; /* MAC capabilities */
+ u32 machwcap_backup; /* backup of machwcap */
+
+ struct si_pub *sih; /* SI handle (cookie for siutils calls) */
+ struct d11regs __iomem *regs; /* pointer to device registers */
+ struct phy_shim_info *physhim; /* phy shim layer handler */
+ struct shared_phy *phy_sh; /* pointer to shared phy state */
+ struct brcms_hw_band *band;/* pointer to active per-band state */
+ /* band state per phy/radio */
+ struct brcms_hw_band *bandstate[MAXBANDS];
+ u16 bmac_phytxant; /* cache of high phytxant state */
+ bool shortslot; /* currently using 11g ShortSlot timing */
+ u16 SRL; /* 802.11 dot11ShortRetryLimit */
+ u16 LRL; /* 802.11 dot11LongRetryLimit */
+ u16 SFBL; /* Short Frame Rate Fallback Limit */
+ u16 LFBL; /* Long Frame Rate Fallback Limit */
+
+ bool up; /* d11 hardware up and running */
+ uint now; /* # elapsed seconds */
+ uint _nbands; /* # bands supported */
+ u16 chanspec; /* bmac chanspec shadow */
+
+ uint *txavail[NFIFO]; /* # tx descriptors available */
+ const u16 *xmtfifo_sz; /* fifo size in 256B for each xmt fifo */
+
+ u32 pllreq; /* pll requests to keep PLL on */
+
+ u8 suspended_fifos; /* Which TX fifo to remain awake for */
+ u32 maccontrol; /* Cached value of maccontrol */
+ uint mac_suspend_depth; /* current depth of mac_suspend levels */
+ u32 wake_override; /* bit flags to force MAC to WAKE mode */
+ u32 mute_override; /* Prevent ucode from sending beacons */
+ u8 etheraddr[ETH_ALEN]; /* currently configured ethernet address */
+ bool noreset; /* true= do not reset hw, used by WLC_OUT */
+ bool forcefastclk; /* true if h/w is forcing to use fast clk */
+ bool clk; /* core is out of reset and has clock */
+ bool sbclk; /* sb has clock */
+ bool phyclk; /* phy is out of reset and has clock */
+
+ bool ucode_loaded; /* true after ucode downloaded */
+
+
+ u8 hw_stf_ss_opmode; /* STF single stream operation mode */
+ u8 antsel_type; /* Type of boardlevel mimo antenna switch-logic
+ * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
+ */
+ u32 antsel_avail; /*
+ * put struct antsel_info here if more info is
+ * needed
+ */
+};
+
+/* 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.
+ *
+ * pub: pointer to driver public state.
+ * wl: pointer to specific private state.
+ * regs: pointer to device registers.
+ * hw: HW related state.
+ * clkreq_override: setting for clkreq for PCIE : Auto, 0, 1.
+ * fastpwrup_dly: time in us needed to bring up d11 fast clock.
+ * macintstatus: bit channel between isr and dpc.
+ * macintmask: sw runtime master macintmask value.
+ * defmacintmask: default "on" macintmask value.
+ * clk: core is out of reset and has clock.
+ * core: pointer to active io core.
+ * band: pointer to active per-band state.
+ * corestate: per-core state (one per hw core).
+ * bandstate: per-band state (one per phy/radio).
+ * qvalid: DirFrmQValid and BcMcFrmQValid.
+ * ampdu: ampdu module handler.
+ * asi: antsel module handler.
+ * cmi: channel manager module handler.
+ * vendorid: PCI vendor id.
+ * deviceid: PCI device id.
+ * ucode_rev: microcode revision.
+ * machwcap: MAC capabilities, BMAC shadow.
+ * perm_etheraddr: original sprom local ethernet address.
+ * bandlocked: disable auto multi-band switching.
+ * bandinit_pending: track band init in auto band.
+ * radio_monitor: radio timer is running.
+ * going_down: down path intermediate variable.
+ * mpc: enable minimum power consumption.
+ * mpc_dlycnt: # of watchdog cnt before turn disable radio.
+ * mpc_offcnt: # of watchdog cnt that radio is disabled.
+ * mpc_delay_off: delay radio disable by # of watchdog cnt.
+ * prev_non_delay_mpc: prev state brcms_c_is_non_delay_mpc.
+ * wdtimer: timer for watchdog routine.
+ * radio_timer: timer for hw radio button monitor routine.
+ * monitor: monitor (MPDU sniffing) mode.
+ * bcnmisc_monitor: bcns promisc mode override for monitor.
+ * _rifs: enable per-packet rifs.
+ * bcn_li_bcn: beacon listen interval in # beacons.
+ * bcn_li_dtim: beacon listen interval in # dtims.
+ * WDarmed: watchdog timer is armed.
+ * WDlast: last time wlc_watchdog() was called.
+ * edcf_txop[AC_COUNT]: 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.
+ * ofdm_40txbw: 11N, ofdm tx b/w override when in 40MHZ mode.
+ * mimo_40txbw: 11N, mimo tx b/w override when in 40MHZ mode.
+ * default_bss: configured BSS parameters.
+ * mc_fid_counter: BC/MC FIFO frame ID counter.
+ * country_default: saved country for leaving 802.11d auto-country mode.
+ * autocountry_default: initial country for 802.11d auto-country mode.
+ * prb_resp_timeout: do not send prb resp if request older
+ * than this, 0 = disable.
+ * home_chanspec: shared home chanspec.
+ * chanspec: target operational channel.
+ * usr_fragthresh: user configured fragmentation threshold.
+ * fragthresh[NFIFO]: per-fifo fragmentation thresholds.
+ * RTSThresh: 802.11 dot11RTSThreshold.
+ * SRL: 802.11 dot11ShortRetryLimit.
+ * LRL: 802.11 dot11LongRetryLimit.
+ * SFBL: Short Frame Rate Fallback Limit.
+ * LFBL: Long Frame Rate Fallback Limit.
+ * shortslot: currently using 11g ShortSlot timing.
+ * shortslot_override: 11g ShortSlot override.
+ * include_legacy_erp: include Legacy ERP info elt ID 47 as well as g ID 42.
+ * PLCPHdr_override: 802.11b Preamble Type override.
+ * stf:
+ * bcn_rspec: save bcn ratespec purpose.
+ * 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
+ */
+struct brcms_c_info {
+ struct brcms_pub *pub;
+ struct brcms_info *wl;
+ struct d11regs __iomem *regs;
+ struct brcms_hardware *hw;
+
+ /* clock */
+ u16 fastpwrup_dly;
+
+ /* interrupt */
+ u32 macintstatus;
+ u32 macintmask;
+ u32 defmacintmask;
+
+ bool clk;
+
+ /* multiband */
+ struct brcms_core *core;
+ struct brcms_band *band;
+ struct brcms_core *corestate;
+ struct brcms_band *bandstate[MAXBANDS];
+
+ /* packet queue */
+ uint qvalid;
+
+ struct ampdu_info *ampdu;
+ struct antsel_info *asi;
+ struct brcms_cm_info *cmi;
+
+ u16 vendorid;
+ u16 deviceid;
+ uint ucode_rev;
+
+ u8 perm_etheraddr[ETH_ALEN];
+
+ bool bandlocked;
+ bool bandinit_pending;
+
+ bool radio_monitor;
+ bool going_down;
+
+ bool mpc;
+ u8 mpc_dlycnt;
+ u8 mpc_offcnt;
+ u8 mpc_delay_off;
+ u8 prev_non_delay_mpc;
+
+ struct brcms_timer *wdtimer;
+ struct brcms_timer *radio_timer;
+
+ /* promiscuous */
+ bool monitor;
+ bool bcnmisc_monitor;
+
+ /* driver feature */
+ bool _rifs;
+
+ /* AP-STA synchronization, power save */
+ u8 bcn_li_bcn;
+ u8 bcn_li_dtim;
+
+ bool WDarmed;
+ u32 WDlast;
+
+ /* WME */
+ u16 edcf_txop[AC_COUNT];
+
+ u16 wme_retries[AC_COUNT];
+ 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;
+ s8 cck_40txbw;
+ s8 ofdm_40txbw;
+ s8 mimo_40txbw;
+
+ struct brcms_bss_info *default_bss;
+
+ u16 mc_fid_counter;
+
+ char country_default[BRCM_CNTRY_BUF_SZ];
+ char autocountry_default[BRCM_CNTRY_BUF_SZ];
+ u16 prb_resp_timeout;
+
+ u16 home_chanspec;
+
+ /* PHY parameters */
+ u16 chanspec;
+ u16 usr_fragthresh;
+ u16 fragthresh[NFIFO];
+ u16 RTSThresh;
+ u16 SRL;
+ u16 LRL;
+ u16 SFBL;
+ u16 LFBL;
+
+ /* network config */
+ bool shortslot;
+ s8 shortslot_override;
+ bool include_legacy_erp;
+
+ struct brcms_protection *protection;
+ s8 PLCPHdr_override;
+
+ struct brcms_stf *stf;
+
+ u32 bcn_rspec;
+
+ uint tempsense_lasttime;
+
+ u16 tx_duty_cycle_ofdm;
+ u16 tx_duty_cycle_cck;
+
+ struct brcms_txq_info *pkt_queue;
+ struct wiphy *wiphy;
+ struct scb pri_scb;
+};
+
+/* antsel module specific state */
+struct antsel_info {
+ struct brcms_c_info *wlc; /* pointer to main wlc structure */
+ struct brcms_pub *pub; /* pointer to public fn */
+ u8 antsel_type; /* Type of boardlevel mimo antenna switch-logic
+ * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
+ */
+ u8 antsel_antswitch; /* board level antenna switch type */
+ bool antsel_avail; /* Ant selection availability (SROM based) */
+ struct brcms_antselcfg antcfg_11n; /* antenna configuration */
+ struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */
+};
+
+/*
+ * BSS configuration state
+ *
+ * wlc: wlc to which this bsscfg belongs to.
+ * up: is this configuration up operational
+ * enable: is this configuration enabled
+ * associated: is BSS in ASSOCIATED state
+ * BSS: infraustructure or adhoc
+ * SSID_len: the length of SSID
+ * SSID: SSID string
+ *
+ *
+ * BSSID: BSSID (associated)
+ * cur_etheraddr: h/w address
+ * flags: BSSCFG flags; see below
+ *
+ * current_bss: BSS parms in ASSOCIATED state
+ *
+ *
+ * ID: 'unique' ID of this bsscfg, assigned at bsscfg allocation
+ */
+struct brcms_bss_cfg {
+ struct brcms_c_info *wlc;
+ bool up;
+ bool enable;
+ bool associated;
+ bool BSS;
+ u8 SSID_len;
+ u8 SSID[IEEE80211_MAX_SSID_LEN];
+ u8 BSSID[ETH_ALEN];
+ u8 cur_etheraddr[ETH_ALEN];
+ 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_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
+ uint *blocks);
+
+#if defined(BCMDBG)
+extern void brcms_c_print_txdesc(struct d11txh *txh);
+#else
+#define brcms_c_print_txdesc(a)
+#endif
+
+extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
+extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc,
+ bool promisc);
+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,
+ u32 rspec,
+ bool use_rspec, u16 mimo_ctlchbw);
+extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
+ u32 rts_rate,
+ u32 frame_rate,
+ u8 rts_preamble_type,
+ u8 frame_preamble_type, uint frame_len,
+ bool ba);
+extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
+ struct ieee80211_sta *sta,
+ void (*dma_callback_fn));
+extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
+extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
+extern int brcms_c_set_nmode(struct brcms_c_info *wlc);
+extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
+ u32 bcn_rate);
+extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw,
+ u8 antsel_type);
+extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw,
+ u16 chanspec,
+ bool mute, struct txpwr_limits *txpwr);
+extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset,
+ u16 v);
+extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
+extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask,
+ u16 val, int bands);
+extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
+extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
+extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
+extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
+extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
+extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
+ u32 override_bit);
+extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
+ u32 override_bit);
+extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw,
+ int offset, int len, void *buf);
+extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate);
+extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw,
+ uint offset, const void *buf, int len,
+ u32 sel);
+extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset,
+ void *buf, int len, u32 sel);
+extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode);
+extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw);
+extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk);
+extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk);
+extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on);
+extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant);
+extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw,
+ u8 stf_mode);
+extern void brcms_c_init_scb(struct scb *scb);
+
+#endif /* _BRCM_MAIN_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/nicpci.c b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c
index 3d71c590fcef..0bcb26792046 100644
--- a/drivers/staging/brcm80211/brcmsmac/nicpci.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c
@@ -127,6 +127,18 @@
/* PCIE protocol TLP diagnostic registers */
#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */
+/* Sonics to PCI translation types */
+#define SBTOPCI_PREF 0x4 /* prefetch enable */
+#define SBTOPCI_BURST 0x8 /* burst enable */
+#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */
+
+#define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */
+
+/* PCI core index in SROM shadow area */
+#define SRSH_PI_OFFSET 0 /* first word */
+#define SRSH_PI_MASK 0xf000 /* bit 15:12 */
+#define SRSH_PI_SHIFT 12 /* bit 15:12 */
+
/* Sonics side: PCI core and host control registers */
struct sbpciregs {
u32 control; /* PCI control */
@@ -194,8 +206,8 @@ struct sbpcieregs {
struct pcicore_info {
union {
- struct sbpcieregs *pcieregs;
- struct sbpciregs *pciregs;
+ struct sbpcieregs __iomem *pcieregs;
+ struct sbpciregs __iomem *pciregs;
} regs; /* Memory mapped register to the core */
struct si_pub *sih; /* System interconnect handle */
@@ -211,52 +223,30 @@ struct pcicore_info {
bool pmecap; /* Capable of generating PME */
};
-/* debug/trace */
-#define PCI_ERROR(args)
-#define PCIE_PUB(sih) \
- (((sih)->bustype == PCI_BUS) && \
- ((sih)->buscoretype == PCIE_CORE_ID))
-
-/* routines to access mdio slave device registers */
-static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk);
-static int pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr,
- bool write, uint *val);
-static int pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint readdr,
- uint val);
-static int pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint readdr,
- uint *ret_val);
-
-static void pcie_extendL1timer(struct pcicore_info *pi, bool extend);
-static void pcie_clkreq_upd(struct pcicore_info *pi, uint state);
-
-static void pcie_war_aspm_clkreq(struct pcicore_info *pi);
-static void pcie_war_serdes(struct pcicore_info *pi);
-static void pcie_war_noplldown(struct pcicore_info *pi);
-static void pcie_war_polarity(struct pcicore_info *pi);
-static void pcie_war_pci_setup(struct pcicore_info *pi);
-
#define PCIE_ASPM(sih) \
- ((PCIE_PUB(sih)) && \
+ (((sih)->buscoretype == PCIE_CORE_ID) && \
(((sih)->buscorerev >= 3) && \
((sih)->buscorerev <= 5)))
/* delay needed between the mdio control/ mdiodata register data access */
-#define PR28829_DELAY() udelay(10)
+static void pr28829_delay(void)
+{
+ udelay(10);
+}
/* Initialize the PCI core.
* It's caller's responsibility to make sure that this is done only once
*/
-void *pcicore_init(struct si_pub *sih, void *pdev, void *regs)
+struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev,
+ void __iomem *regs)
{
struct pcicore_info *pi;
/* alloc struct pcicore_info */
pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC);
- if (pi == NULL) {
- PCI_ERROR(("pci_attach: malloc failed!\n"));
+ if (pi == NULL)
return NULL;
- }
pi->sih = sih;
pi->dev = pdev;
@@ -273,7 +263,7 @@ void *pcicore_init(struct si_pub *sih, void *pdev, void *regs)
return pi;
}
-void pcicore_deinit(void *pch)
+void pcicore_deinit(struct pcicore_info *pch)
{
kfree(pch);
}
@@ -281,7 +271,7 @@ void pcicore_deinit(void *pch)
/* return cap_offset if requested capability exists in the PCI config space */
/* Note that it's caller's responsibility to make sure it's a pci bus */
u8
-pcicore_find_pci_capability(void *dev, u8 req_cap_id,
+pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
unsigned char *buf, u32 *buflen)
{
u8 cap_id;
@@ -344,7 +334,7 @@ end:
/* ***** Register Access API */
static uint
-pcie_readreg(struct sbpcieregs *pcieregs, uint addrtype, uint offset)
+pcie_readreg(struct sbpcieregs __iomem *pcieregs, uint addrtype, uint offset)
{
uint retval = 0xFFFFFFFF;
@@ -364,8 +354,8 @@ pcie_readreg(struct sbpcieregs *pcieregs, uint addrtype, uint offset)
return retval;
}
-static uint
-pcie_writereg(struct sbpcieregs *pcieregs, uint addrtype, uint offset, uint val)
+static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype,
+ uint offset, uint val)
{
switch (addrtype) {
case PCIE_CONFIGREGS:
@@ -384,7 +374,7 @@ pcie_writereg(struct sbpcieregs *pcieregs, uint addrtype, uint offset, uint val)
static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
{
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
uint mdiodata, i = 0;
uint pcie_serdes_spinwait = 200;
@@ -394,19 +384,18 @@ static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
(blk << 4));
W_REG(&pcieregs->mdiodata, mdiodata);
- PR28829_DELAY();
+ pr28829_delay();
/* retry till the transaction is complete */
while (i < pcie_serdes_spinwait) {
if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE)
break;
+
udelay(1000);
i++;
}
- if (i >= pcie_serdes_spinwait) {
- PCI_ERROR(("pcie_mdiosetblock: timed out\n"));
+ if (i >= pcie_serdes_spinwait)
return false;
- }
return true;
}
@@ -415,7 +404,7 @@ static int
pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
uint *val)
{
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
uint mdiodata;
uint i = 0;
uint pcie_serdes_spinwait = 10;
@@ -445,13 +434,13 @@ pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
W_REG(&pcieregs->mdiodata, mdiodata);
- PR28829_DELAY();
+ pr28829_delay();
/* retry till the transaction is complete */
while (i < pcie_serdes_spinwait) {
if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) {
if (!write) {
- PR28829_DELAY();
+ pr28829_delay();
*val = (R_REG(&pcieregs->mdiodata) &
MDIODATA_MASK);
}
@@ -463,8 +452,7 @@ pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
i++;
}
- PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write));
- /* Disable mdio access to SERDES */
+ /* Timed out. Disable mdio access to SERDES. */
W_REG(&pcieregs->mdiocontrol, 0);
return 1;
}
@@ -485,9 +473,8 @@ pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val)
}
/* ***** Support functions ***** */
-static u8 pcie_clkreq(void *pch, u32 mask, u32 val)
+static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val)
{
- struct pcicore_info *pi = pch;
u32 reg_val;
u8 offset;
@@ -515,9 +502,9 @@ static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
{
u32 w;
struct si_pub *sih = pi->sih;
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
- if (!PCIE_PUB(sih) || sih->buscorerev < 7)
+ if (sih->buscoretype != PCIE_CORE_ID || sih->buscorerev < 7)
return;
w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
@@ -537,30 +524,30 @@ static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
switch (state) {
case SI_DOATTACH:
if (PCIE_ASPM(sih))
- pcie_clkreq((void *)pi, 1, 0);
+ pcie_clkreq(pi, 1, 0);
break;
case SI_PCIDOWN:
if (sih->buscorerev == 6) { /* turn on serdes PLL down */
ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_addr),
+ offsetof(struct chipcregs, chipcontrol_addr),
~0, 0);
ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data),
+ offsetof(struct chipcregs, chipcontrol_data),
~0x40, 0);
} else if (pi->pcie_pr42767) {
- pcie_clkreq((void *)pi, 1, 1);
+ pcie_clkreq(pi, 1, 1);
}
break;
case SI_PCIUP:
if (sih->buscorerev == 6) { /* turn off serdes PLL down */
ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_addr),
+ offsetof(struct chipcregs, chipcontrol_addr),
~0, 0);
ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data),
+ offsetof(struct chipcregs, chipcontrol_data),
~0x40, 0x40);
} else if (PCIE_ASPM(sih)) { /* disable clkreq */
- pcie_clkreq((void *)pi, 1, 0);
+ pcie_clkreq(pi, 1, 0);
}
break;
}
@@ -594,9 +581,10 @@ static void pcie_war_polarity(struct pcicore_info *pi)
*/
static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
{
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
struct si_pub *sih = pi->sih;
- u16 val16, *reg16;
+ u16 val16;
+ u16 __iomem *reg16;
u32 w;
if (!PCIE_ASPM(sih))
@@ -654,8 +642,9 @@ static void pcie_war_serdes(struct pcicore_info *pi)
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_misc_config_fixup(struct pcicore_info *pi)
{
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
- u16 val16, *reg16;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
+ u16 val16;
+ u16 __iomem *reg16;
reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG];
val16 = R_REG(reg16);
@@ -670,11 +659,11 @@ static void pcie_misc_config_fixup(struct pcicore_info *pi)
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_war_noplldown(struct pcicore_info *pi)
{
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
- u16 *reg16;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
+ u16 __iomem *reg16;
/* turn off serdes PLL down */
- ai_corereg(pi->sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol),
+ ai_corereg(pi->sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol),
CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
/* clear srom shadow backdoor */
@@ -686,7 +675,7 @@ static void pcie_war_noplldown(struct pcicore_info *pi)
static void pcie_war_pci_setup(struct pcicore_info *pi)
{
struct si_pub *sih = pi->sih;
- struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
u32 w;
if (sih->buscorerev == 0 || sih->buscorerev == 1) {
@@ -730,14 +719,14 @@ static void pcie_war_pci_setup(struct pcicore_info *pi)
}
/* ***** Functions called during driver state changes ***** */
-void pcicore_attach(void *pch, char *pvars, int state)
+void pcicore_attach(struct pcicore_info *pi, int state)
{
- struct pcicore_info *pi = pch;
struct si_pub *sih = pi->sih;
+ u32 bfl2 = (u32)getintvar(sih, BRCMS_SROM_BOARDFLAGS2);
/* Determine if this board needs override */
if (PCIE_ASPM(sih)) {
- if ((u32)getintvar(pvars, "boardflags2") & BFL2_PCIEWAR_OVR)
+ if (bfl2 & BFL2_PCIEWAR_OVR)
pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB;
else
pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB;
@@ -754,21 +743,17 @@ void pcicore_attach(void *pch, char *pvars, int state)
}
-void pcicore_hwup(void *pch)
+void pcicore_hwup(struct pcicore_info *pi)
{
- struct pcicore_info *pi = pch;
-
- if (!pi || !PCIE_PUB(pi->sih))
+ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
return;
pcie_war_pci_setup(pi);
}
-void pcicore_up(void *pch, int state)
+void pcicore_up(struct pcicore_info *pi, int state)
{
- struct pcicore_info *pi = pch;
-
- if (!pi || !PCIE_PUB(pi->sih))
+ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
return;
/* Restore L1 timer for better performance */
@@ -780,9 +765,8 @@ void pcicore_up(void *pch, int state)
/* When the device is going to enter D3 state
* (or the system is going to enter S3/S4 states)
*/
-void pcicore_sleep(void *pch)
+void pcicore_sleep(struct pcicore_info *pi)
{
- struct pcicore_info *pi = pch;
u32 w;
if (!pi || !PCIE_ASPM(pi->sih))
@@ -795,11 +779,9 @@ void pcicore_sleep(void *pch)
pi->pcie_pr42767 = false;
}
-void pcicore_down(void *pch, int state)
+void pcicore_down(struct pcicore_info *pi, int state)
{
- struct pcicore_info *pi = pch;
-
- if (!pi || !PCIE_PUB(pi->sih))
+ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
return;
pcie_clkreq_upd(pi, state);
@@ -809,20 +791,12 @@ void pcicore_down(void *pch, int state)
}
/* precondition: current core is sii->buscoretype */
-void pcicore_fixcfg(void *pch, void *regs)
+static void pcicore_fixcfg(struct pcicore_info *pi, u16 __iomem *reg16)
{
- struct pcicore_info *pi = pch;
- struct si_info *sii = SI_INFO(pi->sih);
- struct sbpciregs *pciregs = regs;
- struct sbpcieregs *pcieregs = regs;
- u16 val16, *reg16 = NULL;
+ struct si_info *sii = (struct si_info *)(pi->sih);
+ u16 val16;
uint pciidx;
- /* check 'pi' is correct and fix it if not */
- if (sii->pub.buscoretype == PCIE_CORE_ID)
- reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
- else if (sii->pub.buscoretype == PCI_CORE_ID)
- reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
pciidx = ai_coreidx(&sii->pub);
val16 = R_REG(reg16);
if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) {
@@ -832,16 +806,27 @@ void pcicore_fixcfg(void *pch, void *regs)
}
}
+void
+pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs)
+{
+ pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]);
+}
+
+void pcicore_fixcfg_pcie(struct pcicore_info *pi,
+ struct sbpcieregs __iomem *pcieregs)
+{
+ pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]);
+}
+
/* precondition: current core is pci core */
-void pcicore_pci_setup(void *pch, void *regs)
+void
+pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs)
{
- struct pcicore_info *pi = pch;
- struct sbpciregs *pciregs = regs;
u32 w;
OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST);
- if (SI_INFO(pi->sih)->pub.buscorerev >= 11) {
+ if (((struct si_info *)(pi->sih))->pub.buscorerev >= 11) {
OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
w = R_REG(&pciregs->clkrun);
W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL);
diff --git a/drivers/staging/brcm80211/brcmsmac/nicpci.h b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h
index f71f842a2156..58aa80dc3329 100644
--- a/drivers/staging/brcm80211/brcmsmac/nicpci.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h
@@ -58,28 +58,25 @@
/* bar0 + 12K accesses chipc core registers */
#define PCI_16KB0_CCREGS_OFFSET (12 * 1024)
-#define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */
+struct sbpciregs;
+struct sbpcieregs;
-/* Sonics to PCI translation types */
-#define SBTOPCI_PREF 0x4 /* prefetch enable */
-#define SBTOPCI_BURST 0x8 /* burst enable */
-#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */
-
-/* PCI core index in SROM shadow area */
-#define SRSH_PI_OFFSET 0 /* first word */
-#define SRSH_PI_MASK 0xf000 /* bit 15:12 */
-#define SRSH_PI_SHIFT 12 /* bit 15:12 */
-
-extern void *pcicore_init(struct si_pub *sih, void *pdev, void *regs);
-extern void pcicore_deinit(void *pch);
-extern void pcicore_attach(void *pch, char *pvars, int state);
-extern void pcicore_hwup(void *pch);
-extern void pcicore_up(void *pch, int state);
-extern void pcicore_sleep(void *pch);
-extern void pcicore_down(void *pch, int state);
-extern u8 pcicore_find_pci_capability(void *dev, u8 req_cap_id,
- unsigned char *buf, u32 *buflen);
-extern void pcicore_fixcfg(void *pch, void *regs);
-extern void pcicore_pci_setup(void *pch, void *regs);
+extern struct pcicore_info *pcicore_init(struct si_pub *sih,
+ struct pci_dev *pdev,
+ void __iomem *regs);
+extern void pcicore_deinit(struct pcicore_info *pch);
+extern void pcicore_attach(struct pcicore_info *pch, int state);
+extern void pcicore_hwup(struct pcicore_info *pch);
+extern void pcicore_up(struct pcicore_info *pch, int state);
+extern void pcicore_sleep(struct pcicore_info *pch);
+extern void pcicore_down(struct pcicore_info *pch, int state);
+extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
+ unsigned char *buf, u32 *buflen);
+extern void pcicore_fixcfg_pci(struct pcicore_info *pch,
+ struct sbpciregs __iomem *pciregs);
+extern void pcicore_fixcfg_pcie(struct pcicore_info *pch,
+ struct sbpcieregs __iomem *pciregs);
+extern void pcicore_pci_setup(struct pcicore_info *pch,
+ struct sbpciregs __iomem *pciregs);
#endif /* _BRCM_NICPCI_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/otp.c b/drivers/net/wireless/brcm80211/brcmsmac/otp.c
index 4a70180eba5d..edf551561fd8 100644
--- a/drivers/staging/brcm80211/brcmsmac/otp.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/otp.c
@@ -25,10 +25,14 @@
#define OTPS_GUP_MASK 0x00000f00
#define OTPS_GUP_SHIFT 8
-#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */
-#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */
-#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */
-#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */
+/* h/w subregion is programmed */
+#define OTPS_GUP_HW 0x00000100
+/* s/w subregion is programmed */
+#define OTPS_GUP_SW 0x00000200
+/* chipid/pkgopt subregion is programmed */
+#define OTPS_GUP_CI 0x00000400
+/* fuse subregion is programmed */
+#define OTPS_GUP_FUSE 0x00000800
/* Fields in otpprog in rev >= 21 */
#define OTPP_COL_MASK 0x000000ff
@@ -60,28 +64,21 @@
#define MAXNUMRDES 9 /* Maximum OTP redundancy entries */
-/* OTP common function type */
-typedef int (*otp_status_t) (void *oh);
-typedef int (*otp_size_t) (void *oh);
-typedef void *(*otp_init_t) (struct si_pub *sih);
-typedef u16(*otp_read_bit_t) (void *oh, chipcregs_t *cc, uint off);
-typedef int (*otp_read_region_t) (struct si_pub *sih, int region, u16 *data,
- uint *wlen);
-typedef int (*otp_nvread_t) (void *oh, char *data, uint *len);
+/* Fixed size subregions sizes in words */
+#define OTPGU_CI_SZ 2
+
+struct otpinfo;
/* OTP function struct */
struct otp_fn_s {
- otp_size_t size;
- otp_read_bit_t read_bit;
- otp_init_t init;
- otp_read_region_t read_region;
- otp_nvread_t nvread;
- otp_status_t status;
+ int (*init)(struct si_pub *sih, struct otpinfo *oi);
+ int (*read_region)(struct otpinfo *oi, int region, u16 *data,
+ uint *wlen);
};
struct otpinfo {
uint ccrev; /* chipc revision */
- struct otp_fn_s *fn; /* OTP functions */
+ const struct otp_fn_s *fn; /* OTP functions */
struct si_pub *sih; /* Saved sb handle */
/* IPX OTP section */
@@ -100,23 +97,6 @@ struct otpinfo {
int otpgu_base; /* offset to General Use Region */
};
-static struct otpinfo otpinfo;
-
-/*
- * IPX OTP Code
- *
- * Exported functions:
- * ipxotp_status()
- * ipxotp_size()
- * ipxotp_init()
- * ipxotp_read_bit()
- * ipxotp_read_region()
- * ipxotp_nvread()
- *
- */
-
-#define HWSW_RGN(rgn) (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
-
/* OTP layout */
/* CC revs 21, 24 and 27 OTP General Use Region word offset */
#define REVA4_OTPGU_BASE 12
@@ -152,60 +132,15 @@ static struct otpinfo otpinfo;
#define OTP4315_SWREG_SZ 178 /* 178 bytes */
#define OTP_SZ_FU_144 (144/8) /* 144 bits */
-static int ipxotp_status(void *oh)
+static u16
+ipxotp_otpr(struct otpinfo *oi, struct chipcregs __iomem *cc, uint wn)
{
- struct otpinfo *oi = (struct otpinfo *) oh;
- return (int)(oi->status);
-}
-
-/* Return size in bytes */
-static int ipxotp_size(void *oh)
-{
- struct otpinfo *oi = (struct otpinfo *) oh;
- return (int)oi->wsize * 2;
-}
-
-static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
-{
- struct otpinfo *oi;
-
- oi = (struct otpinfo *) oh;
-
return R_REG(&cc->sromotp[wn]);
}
-static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
-{
- struct otpinfo *oi = (struct otpinfo *) oh;
- uint k, row, col;
- u32 otpp, st;
-
- row = off / oi->cols;
- col = off % oi->cols;
-
- otpp = OTPP_START_BUSY |
- ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
- ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
- ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
- W_REG(&cc->otpprog, otpp);
-
- for (k = 0;
- ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
- && (k < OTPP_TRIES); k++)
- ;
- if (k >= OTPP_TRIES) {
- return 0xffff;
- }
- if (st & OTPP_READERR) {
- return 0xffff;
- }
- st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
-
- return (int)st;
-}
-
-/* Calculate max HW/SW region byte size by subtracting fuse region and checksum size,
- * osizew is oi->wsize (OTP size - GU size) in words
+/*
+ * Calculate max HW/SW region byte size by subtracting fuse region
+ * and checksum size, osizew is oi->wsize (OTP size - GU size) in words
*/
static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
{
@@ -226,17 +161,23 @@ static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
return ret;
}
-static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc)
+static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
{
uint k;
u32 otpp, st;
- /* record word offset of General Use Region for various chipcommon revs */
+ /*
+ * record word offset of General Use Region
+ * for various chipcommon revs
+ */
if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
|| oi->sih->ccrev == 27) {
oi->otpgu_base = REVA4_OTPGU_BASE;
} else if (oi->sih->ccrev == 36) {
- /* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */
+ /*
+ * OTP size greater than equal to 2KB (128 words),
+ * otpgu_base is similar to rev23
+ */
if (oi->wsize >= 128)
oi->otpgu_base = REVB8_OTPGU_BASE;
else
@@ -254,9 +195,8 @@ static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc)
((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
&& (k < OTPP_TRIES); k++)
;
- if (k >= OTPP_TRIES) {
+ if (k >= OTPP_TRIES)
return;
- }
/* Read OTP lock bits and subregion programmed indication bits */
oi->status = R_REG(&cc->otpstatus);
@@ -272,8 +212,9 @@ static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc)
}
/*
- * h/w region base and fuse region limit are fixed to the top and
- * the bottom of the general use region. Everything else can be flexible.
+ * h/w region base and fuse region limit are fixed to
+ * the top and the bottom of the general use region.
+ * Everything else can be flexible.
*/
oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
oi->hwlim = oi->wsize;
@@ -297,28 +238,24 @@ static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc)
oi->flim = oi->wsize;
}
-static void *ipxotp_init(struct si_pub *sih)
+static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
{
uint idx;
- chipcregs_t *cc;
- struct otpinfo *oi;
+ struct chipcregs __iomem *cc;
/* Make sure we're running IPX OTP */
if (!OTPTYPE_IPX(sih->ccrev))
- return NULL;
+ return -EBADE;
/* Make sure OTP is not disabled */
if (ai_is_otp_disabled(sih))
- return NULL;
-
- /* OTP is always powered */
- oi = &otpinfo;
+ return -EBADE;
/* Check for otp size */
switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
case 0:
/* Nothing there */
- return NULL;
+ return -EBADE;
case 1: /* 32x64 */
oi->rows = 32;
oi->cols = 64;
@@ -341,7 +278,7 @@ static void *ipxotp_init(struct si_pub *sih)
break;
default:
/* Don't know the geometry */
- return NULL;
+ return -EBADE;
}
/* Retrieve OTP region info */
@@ -352,14 +289,14 @@ static void *ipxotp_init(struct si_pub *sih)
ai_setcoreidx(sih, idx);
- return (void *)oi;
+ return 0;
}
-static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
+static int
+ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
{
- struct otpinfo *oi = (struct otpinfo *) oh;
uint idx;
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint base, i, sz;
/* Validate region selection */
@@ -433,68 +370,23 @@ static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
/* Read the data */
for (i = 0; i < sz; i++)
- data[i] = ipxotp_otpr(oh, cc, base + i);
+ data[i] = ipxotp_otpr(oi, cc, base + i);
ai_setcoreidx(oi->sih, idx);
*wlen = sz;
return 0;
}
-static int ipxotp_nvread(void *oh, char *data, uint *len)
-{
- return -ENOTSUPP;
-}
-
-static struct otp_fn_s ipxotp_fn = {
- (otp_size_t) ipxotp_size,
- (otp_read_bit_t) ipxotp_read_bit,
-
- (otp_init_t) ipxotp_init,
- (otp_read_region_t) ipxotp_read_region,
- (otp_nvread_t) ipxotp_nvread,
-
- (otp_status_t) ipxotp_status
+static const struct otp_fn_s ipxotp_fn = {
+ (int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init,
+ (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region,
};
-/*
- * otp_status()
- * otp_size()
- * otp_read_bit()
- * otp_init()
- * otp_read_region()
- * otp_nvread()
- */
-
-int otp_status(void *oh)
+static int otp_init(struct si_pub *sih, struct otpinfo *oi)
{
- struct otpinfo *oi = (struct otpinfo *) oh;
- return oi->fn->status(oh);
-}
+ int ret;
-int otp_size(void *oh)
-{
- struct otpinfo *oi = (struct otpinfo *) oh;
-
- return oi->fn->size(oh);
-}
-
-u16 otp_read_bit(void *oh, uint offset)
-{
- struct otpinfo *oi = (struct otpinfo *) oh;
- uint idx = ai_coreidx(oi->sih);
- chipcregs_t *cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
- u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset);
- ai_setcoreidx(oi->sih, idx);
- return readBit;
-}
-
-void *otp_init(struct si_pub *sih)
-{
- struct otpinfo *oi;
- void *ret = NULL;
-
- oi = &otpinfo;
memset(oi, 0, sizeof(struct otpinfo));
oi->ccrev = sih->ccrev;
@@ -502,21 +394,20 @@ void *otp_init(struct si_pub *sih)
if (OTPTYPE_IPX(oi->ccrev))
oi->fn = &ipxotp_fn;
- if (oi->fn == NULL) {
- return NULL;
- }
+ if (oi->fn == NULL)
+ return -EBADE;
oi->sih = sih;
- ret = (oi->fn->init) (sih);
+ ret = (oi->fn->init) (sih, oi);
return ret;
}
int
-otp_read_region(struct si_pub *sih, int region, u16 *data,
- uint *wlen) {
- void *oh;
+otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) {
+ struct otpinfo otpinfo;
+ struct otpinfo *oi = &otpinfo;
int err = 0;
if (ai_is_otp_disabled(sih)) {
@@ -524,22 +415,12 @@ otp_read_region(struct si_pub *sih, int region, u16 *data,
goto out;
}
- oh = otp_init(sih);
- if (oh == NULL) {
- err = -EBADE;
+ err = otp_init(sih, oi);
+ if (err)
goto out;
- }
- err = (((struct otpinfo *) oh)->fn->read_region)
- (oh, region, data, wlen);
+ err = ((oi)->fn->read_region)(oi, region, data, wlen);
out:
return err;
}
-
-int otp_nvread(void *oh, char *data, uint *len)
-{
- struct otpinfo *oi = (struct otpinfo *) oh;
-
- return oi->fn->nvread(oh, data, len);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/otp.h b/drivers/net/wireless/brcm80211/brcmsmac/otp.h
index f6d3a56acf1e..6b6d31cf9569 100644
--- a/drivers/staging/brcm80211/brcmsmac/otp.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/otp.h
@@ -24,24 +24,13 @@
#define OTP_SW_RGN 2
#define OTP_CI_RGN 4
#define OTP_FUSE_RGN 8
-#define OTP_ALL_RGN 0xf /* From h/w region to end of OTP including checksum */
+/* From h/w region to end of OTP including checksum */
+#define OTP_ALL_RGN 0xf
/* OTP Size */
#define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */
-/* Fixed size subregions sizes in words */
-#define OTPGU_CI_SZ 2
-
-/* OTP usage */
-#define OTP4325_FM_DISABLED_OFFSET 188
-
-/* Exported functions */
-extern int otp_status(void *oh);
-extern int otp_size(void *oh);
-extern u16 otp_read_bit(void *oh, uint offset);
-extern void *otp_init(struct si_pub *sih);
extern int otp_read_region(struct si_pub *sih, int region, u16 *data,
uint *wlen);
-extern int otp_nvread(void *oh, char *data, uint *len);
#endif /* _BRCM_OTP_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
index 17012fbe9c97..a3149254cbcd 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
@@ -13,8 +13,9 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-
+#include <linux/kernel.h>
#include <linux/delay.h>
+#include <linux/bitops.h>
#include <brcm_hw_ids.h>
#include <chipcommon.h>
@@ -27,14 +28,32 @@
#include "phy_lcn.h"
#include "phyreg_n.h"
-u32 phyhal_msg_level = PHYHAL_ERROR;
+#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || \
+ (radioid == BCM2056_ID) || \
+ (radioid == BCM2057_ID))
+
+#define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID)
+
+#define VALID_RADIO(pi, radioid) ( \
+ (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
+ (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
+
+/* basic mux operation - can be optimized on several architectures */
+#define MUX(pred, true, false) ((pred) ? (true) : (false))
+
+/* modulo inc/dec - assumes x E [0, bound - 1] */
+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
+
+/* modulo inc/dec, bound = 2^k */
+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
struct chan_info_basic {
u16 chan;
u16 freq;
};
-static struct chan_info_basic chan_info_all[] = {
+static const struct chan_info_basic chan_info_all[] = {
{1, 2412},
{2, 2417},
{3, 2422},
@@ -93,20 +112,6 @@ static struct chan_info_basic chan_info_all[] = {
{216, 50800}
};
-u16 ltrn_list[PHY_LTRN_LIST_LEN] = {
- 0x18f9, 0x0d01, 0x00e4, 0xdef4, 0x06f1, 0x0ffc,
- 0xfa27, 0x1dff, 0x10f0, 0x0918, 0xf20a, 0xe010,
- 0x1417, 0x1104, 0xf114, 0xf2fa, 0xf7db, 0xe2fc,
- 0xe1fb, 0x13ee, 0xff0d, 0xe91c, 0x171a, 0x0318,
- 0xda00, 0x03e8, 0x17e6, 0xe9e4, 0xfff3, 0x1312,
- 0xe105, 0xe204, 0xf725, 0xf206, 0xf1ec, 0x11fc,
- 0x14e9, 0xe0f0, 0xf2f6, 0x09e8, 0x1010, 0x1d01,
- 0xfad9, 0x0f04, 0x060f, 0xde0c, 0x001c, 0x0dff,
- 0x1807, 0xf61a, 0xe40e, 0x0f16, 0x05f9, 0x18ec,
- 0x0a1b, 0xff1e, 0x2600, 0xffe2, 0x0ae5, 0x1814,
- 0x0507, 0x0fea, 0xe4f2, 0xf6e6
-};
-
const u8 ofdm_rate_lookup[] = {
BRCM_RATE_48M,
@@ -119,66 +124,7 @@ const u8 ofdm_rate_lookup[] = {
BRCM_RATE_9M
};
-#define PHY_WREG_LIMIT 24
-
-static void wlc_set_phy_uninitted(struct brcms_phy *pi);
-static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi);
-static void wlc_phy_timercb_phycal(void *arg);
-
-static bool wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr,
- s8 *pwr_ant);
-
-static void wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi,
- uint delay);
-
-static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm);
-static void wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason,
- u8 ch);
-
-static void wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi,
- struct txpwr_limits *tp, chanspec_t);
-static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi);
-
-static s8 wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan,
- u32 band, u8 rate);
-static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band);
-static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi);
-static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi);
-
-char *phy_getvar(struct brcms_phy *pi, const char *name)
-{
- char *vars = pi->vars;
- char *s;
- int len;
-
- if (!name)
- return NULL;
-
- len = strlen(name);
- if (len == 0)
- return NULL;
-
- for (s = vars; s && *s;) {
- if ((memcmp(s, name, len) == 0) && (s[len] == '='))
- return &s[len + 1];
-
- while (*s++)
- ;
- }
-
- return NULL;
-}
-
-int phy_getintvar(struct brcms_phy *pi, const char *name)
-{
- char *val;
-
- val = PHY_GETVAR(pi, name);
- if (val == NULL)
- return 0;
-
- return simple_strtoul(val, NULL, 0);
-}
+#define PHY_WREG_LIMIT 24
void wlc_phyreg_enter(struct brcms_phy_pub *pih)
{
@@ -203,7 +149,7 @@ void wlc_radioreg_enter(struct brcms_phy_pub *pih)
void wlc_radioreg_exit(struct brcms_phy_pub *pih)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
- volatile u16 dummy;
+ u16 dummy;
dummy = R_REG(&pi->regs->phyversion);
pi->phy_wreg = 0;
@@ -217,12 +163,10 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
if ((addr == RADIO_IDCODE))
return 0xffff;
- if (NORADIO_ENAB(pi->pubpi))
- return NORADIO_IDCODE & 0xffff;
-
switch (pi->pubpi.phy_type) {
case PHY_TYPE_N:
- CASECHECK(PHYTYPE, PHY_TYPE_N);
+ if (!CONF_HAS(PHYTYPE, PHY_TYPE_N))
+ break;
if (NREV_GE(pi->pubpi.phy_rev, 7))
addr |= RADIO_2057_READ_OFF;
else
@@ -230,7 +174,8 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
break;
case PHY_TYPE_LCN:
- CASECHECK(PHYTYPE, PHY_TYPE_LCN);
+ if (!CONF_HAS(PHYTYPE, PHY_TYPE_LCN))
+ break;
addr |= RADIO_2064_READ_OFF;
break;
@@ -262,9 +207,6 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
if ((D11REV_GE(pi->sh->corerev, 24)) ||
(D11REV_IS(pi->sh->corerev, 22)
&& (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
@@ -276,11 +218,9 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
W_REG(&pi->regs->phy4wdatalo, val);
}
- if (pi->sh->bustype == PCI_BUS) {
- if (++pi->phy_wreg >= pi->phy_wreg_limit) {
- (void)R_REG(&pi->regs->maccontrol);
- pi->phy_wreg = 0;
- }
+ if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+ (void)R_REG(&pi->regs->maccontrol);
+ pi->phy_wreg = 0;
}
}
@@ -288,9 +228,6 @@ static u32 read_radio_id(struct brcms_phy *pi)
{
u32 id;
- if (NORADIO_ENAB(pi->pubpi))
- return NORADIO_IDCODE;
-
if (D11REV_GE(pi->sh->corerev, 24)) {
u32 b0, b1, b2;
@@ -316,9 +253,6 @@ void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
u16 rval;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
rval = read_radio_reg(pi, addr);
write_radio_reg(pi, addr, (rval & val));
}
@@ -327,9 +261,6 @@ void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
u16 rval;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
rval = read_radio_reg(pi, addr);
write_radio_reg(pi, addr, (rval | val));
}
@@ -338,9 +269,6 @@ void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask)
{
u16 rval;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
rval = read_radio_reg(pi, addr);
write_radio_reg(pi, addr, (rval ^ mask));
}
@@ -349,9 +277,6 @@ void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
{
u16 rval;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
rval = read_radio_reg(pi, addr);
write_radio_reg(pi, addr, (rval & ~mask) | (val & mask));
}
@@ -363,7 +288,7 @@ void write_phy_channel_reg(struct brcms_phy *pi, uint val)
u16 read_phy_reg(struct brcms_phy *pi, u16 addr)
{
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
regs = pi->regs;
@@ -375,30 +300,27 @@ u16 read_phy_reg(struct brcms_phy *pi, u16 addr)
void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
regs = pi->regs;
-#ifdef __mips__
+#ifdef CONFIG_BCM47XX
W_REG_FLUSH(&regs->phyregaddr, addr);
W_REG(&regs->phyregdata, val);
if (addr == 0x72)
(void)R_REG(&regs->phyregdata);
#else
- W_REG((u32 *)(&regs->phyregaddr),
- addr | (val << 16));
- if (pi->sh->bustype == PCI_BUS) {
- if (++pi->phy_wreg >= pi->phy_wreg_limit) {
- pi->phy_wreg = 0;
- (void)R_REG(&regs->phyversion);
- }
+ W_REG((u32 __iomem *)(&regs->phyregaddr), addr | (val << 16));
+ if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+ pi->phy_wreg = 0;
+ (void)R_REG(&regs->phyversion);
}
#endif
}
void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
regs = pi->regs;
@@ -410,7 +332,7 @@ void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
regs = pi->regs;
@@ -422,7 +344,7 @@ void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
{
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
regs = pi->regs;
@@ -464,9 +386,8 @@ static void wlc_set_phy_uninitted(struct brcms_phy *pi)
}
pi->radiopwr = 0xffff;
for (i = 0; i < STATIC_NUM_RF; i++) {
- for (j = 0; j < STATIC_NUM_BB; j++) {
+ for (j = 0; j < STATIC_NUM_BB; j++)
pi->stats_11b_txpower[i][j] = -1;
- }
}
}
@@ -475,9 +396,8 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
struct shared_phy *sh;
sh = kzalloc(sizeof(struct shared_phy), GFP_ATOMIC);
- if (sh == NULL) {
+ if (sh == NULL)
return NULL;
- }
sh->sih = shp->sih;
sh->physhim = shp->physhim;
@@ -495,7 +415,6 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
sh->boardvendor = shp->boardvendor;
sh->boardflags = shp->boardflags;
sh->boardflags2 = shp->boardflags2;
- sh->bustype = shp->bustype;
sh->buscorerev = shp->buscorerev;
sh->fast_timer = PHY_SW_TIMER_FAST;
@@ -507,9 +426,40 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
return sh;
}
+static void wlc_phy_timercb_phycal(struct brcms_phy *pi)
+{
+ uint delay = 5;
+
+ if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+ if (!pi->sh->up) {
+ wlc_phy_cal_perical_mphase_reset(pi);
+ return;
+ }
+
+ if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
+
+ delay = 1000;
+ wlc_phy_cal_perical_mphase_restart(pi);
+ } else
+ wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
+ wlapi_add_timer(pi->phycal_timer, delay, 0);
+ return;
+ }
+
+}
+
+static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi)
+{
+ u32 ver;
+
+ ver = read_radio_id(pi);
+
+ return ver;
+}
+
struct brcms_phy_pub *
-wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
- char *vars, struct wiphy *wiphy)
+wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
+ int bandtype, struct wiphy *wiphy)
{
struct brcms_phy *pi;
u32 sflags = 0;
@@ -522,42 +472,35 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
else
sflags = ai_core_sflags(sh->sih, 0, 0);
- if (BAND_5G(bandtype)) {
- if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) {
+ if (bandtype == BRCM_BAND_5G) {
+ if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0)
return NULL;
- }
}
pi = sh->phy_head;
if ((sflags & SISF_DB_PHY) && pi) {
-
wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
pi->refcnt++;
return &pi->pubpi_ro;
}
pi = kzalloc(sizeof(struct brcms_phy), GFP_ATOMIC);
- if (pi == NULL) {
+ if (pi == NULL)
return NULL;
- }
pi->wiphy = wiphy;
- pi->regs = (d11regs_t *) regs;
+ pi->regs = regs;
pi->sh = sh;
pi->phy_init_por = true;
pi->phy_wreg_limit = PHY_WREG_LIMIT;
- pi->vars = vars;
-
pi->txpwr_percent = 100;
pi->do_initcal = true;
pi->phycal_tempdelta = 0;
- if (BAND_2G(bandtype) && (sflags & SISF_2G_PHY)) {
-
+ if (bandtype == BRCM_BAND_2G && (sflags & SISF_2G_PHY))
pi->pubpi.coreflags = SICF_GMODE;
- }
wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
phyversion = R_REG(&pi->regs->phyversion);
@@ -572,28 +515,26 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
- if (!VALID_PHYTYPE(pi->pubpi.phy_type)) {
+ if (!pi->pubpi.phy_type == PHY_TYPE_N &&
+ !pi->pubpi.phy_type == PHY_TYPE_LCN)
goto err;
- }
- if (BAND_5G(bandtype)) {
- if (!ISNPHY(pi)) {
- goto err;
- }
- } else {
- if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
+
+ if (bandtype == BRCM_BAND_5G) {
+ if (!ISNPHY(pi))
goto err;
- }
+ } else if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
+ goto err;
}
wlc_phy_anacore((struct brcms_phy_pub *) pi, ON);
idcode = wlc_phy_get_radio_ver(pi);
pi->pubpi.radioid =
- (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
+ (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
pi->pubpi.radiorev =
- (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
+ (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
pi->pubpi.radiover =
- (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
+ (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
if (!VALID_RADIO(pi, pi->pubpi.radioid))
goto err;
@@ -602,8 +543,8 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
wlc_set_phy_uninitted(pi);
pi->bw = WL_CHANSPEC_BW_20;
- pi->radio_chanspec =
- BAND_2G(bandtype) ? CH20MHZ_CHSPEC(1) : CH20MHZ_CHSPEC(36);
+ pi->radio_chanspec = (bandtype == BRCM_BAND_2G) ?
+ ch20mhz_chspec(1) : ch20mhz_chspec(36);
pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
pi->rxiq_antsel = ANT_RX_DIV_DEF;
@@ -625,7 +566,7 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
pi->phy_txcore_enable_temp =
- PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
+ PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
pi->phy_tempsense_offset = 0;
pi->phy_txcore_heatedup = false;
@@ -648,11 +589,10 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
if (ISNPHY(pi)) {
pi->phycal_timer = wlapi_init_timer(pi->sh->physhim,
- wlc_phy_timercb_phycal,
- pi, "phycal");
- if (!pi->phycal_timer) {
+ wlc_phy_timercb_phycal,
+ pi, "phycal");
+ if (!pi->phycal_timer)
goto err;
- }
if (!wlc_phy_attach_nphy(pi))
goto err;
@@ -661,21 +601,17 @@ wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
if (!wlc_phy_attach_lcnphy(pi))
goto err;
- } else {
-
}
pi->refcnt++;
pi->next = pi->sh->phy_head;
sh->phy_head = pi;
- pi->vars = (char *)&pi->vars;
-
memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(struct brcms_phy_pub));
return &pi->pubpi_ro;
- err:
+err:
kfree(pi);
return NULL;
}
@@ -685,12 +621,11 @@ void wlc_phy_detach(struct brcms_phy_pub *pih)
struct brcms_phy *pi = (struct brcms_phy *) pih;
if (pih) {
- if (--pi->refcnt) {
+ if (--pi->refcnt)
return;
- }
if (pi->phycal_timer) {
- wlapi_free_timer(pi->sh->physhim, pi->phycal_timer);
+ wlapi_free_timer(pi->phycal_timer);
pi->phycal_timer = NULL;
}
@@ -700,7 +635,7 @@ void wlc_phy_detach(struct brcms_phy_pub *pih)
pi->sh->phy_head->next = NULL;
if (pi->pi_fptr.detach)
- (pi->pi_fptr.detach) (pi);
+ (pi->pi_fptr.detach)(pi);
kfree(pi);
}
@@ -731,29 +666,6 @@ u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih)
return pi->pubpi.coreflags;
}
-static void wlc_phy_timercb_phycal(void *arg)
-{
- struct brcms_phy *pi = (struct brcms_phy *) arg;
- uint delay = 5;
-
- if (PHY_PERICAL_MPHASE_PENDING(pi)) {
- if (!pi->sh->up) {
- wlc_phy_cal_perical_mphase_reset(pi);
- return;
- }
-
- if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
-
- delay = 1000;
- wlc_phy_cal_perical_mphase_restart(pi);
- } else
- wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
- wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
- return;
- }
-
-}
-
void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
@@ -862,10 +774,10 @@ void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate)
pi->sh->up = newstate;
}
-void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
+void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec)
{
u32 mc;
- initfn_t phy_init = NULL;
+ void (*phy_init)(struct brcms_phy *) = NULL;
struct brcms_phy *pi = (struct brcms_phy *) pih;
if (pi->init_in_progress)
@@ -879,9 +791,8 @@ void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init"))
return;
- if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
+ if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN))
pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
- }
if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA),
"HW error SISF_FCLKA\n"))
@@ -889,9 +800,8 @@ void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
phy_init = pi->pi_fptr.init;
- if (phy_init == NULL) {
+ if (phy_init == NULL)
return;
- }
wlc_phy_anacore(pih, ON);
@@ -903,7 +813,7 @@ void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON);
- (*phy_init) (pi);
+ (*phy_init)(pi);
pi->phy_init_por = false;
@@ -921,7 +831,7 @@ void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
void wlc_phy_cal_init(struct brcms_phy_pub *pih)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
- initfn_t cal_init = NULL;
+ void (*cal_init)(struct brcms_phy *) = NULL;
if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0,
"HW error: MAC enabled during phy cal\n"))
@@ -930,7 +840,7 @@ void wlc_phy_cal_init(struct brcms_phy_pub *pih)
if (!pi->initialized) {
cal_init = pi->pi_fptr.calinit;
if (cal_init)
- (*cal_init) (pi);
+ (*cal_init)(pi);
pi->initialized = true;
}
@@ -942,7 +852,7 @@ int wlc_phy_down(struct brcms_phy_pub *pih)
int callbacks = 0;
if (pi->phycal_timer
- && !wlapi_del_timer(pi->sh->physhim, pi->phycal_timer))
+ && !wlapi_del_timer(pi->phycal_timer))
callbacks++;
pi->nphy_iqcal_chanspec_2G = 0;
@@ -951,15 +861,6 @@ int wlc_phy_down(struct brcms_phy_pub *pih)
return callbacks;
}
-static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi)
-{
- u32 ver;
-
- ver = read_radio_id(pi);
-
- return ver;
-}
-
void
wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
@@ -990,11 +891,9 @@ void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val)
}
if (width == 32) {
-
write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16));
write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
} else {
-
write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
}
}
@@ -1025,15 +924,12 @@ wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
}
if (tbl_width == 32) {
-
write_phy_reg(pi, tblDataHi,
(u16) (ptbl_32b[idx] >> 16));
write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]);
} else if (tbl_width == 16) {
-
write_phy_reg(pi, tblDataLo, ptbl_16b[idx]);
} else {
-
write_phy_reg(pi, tblDataLo, ptbl_8b[idx]);
}
}
@@ -1064,14 +960,11 @@ wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
}
if (tbl_width == 32) {
-
ptbl_32b[idx] = read_phy_reg(pi, tblDataLo);
ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16);
} else if (tbl_width == 16) {
-
ptbl_16b[idx] = read_phy_reg(pi, tblDataLo);
} else {
-
ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo);
}
}
@@ -1084,10 +977,9 @@ wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
uint i = 0;
do {
- if (radioregs[i].do_init) {
+ if (radioregs[i].do_init)
write_radio_reg(pi, radioregs[i].address,
(u16) radioregs[i].init);
- }
i++;
} while (radioregs[i].address != 0xffff);
@@ -1096,7 +988,8 @@ wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
}
uint
-wlc_phy_init_radio_regs(struct brcms_phy *pi, struct radio_regs *radioregs,
+wlc_phy_init_radio_regs(struct brcms_phy *pi,
+ const struct radio_regs *radioregs,
u16 core_offset)
{
uint i = 0;
@@ -1131,8 +1024,8 @@ wlc_phy_init_radio_regs(struct brcms_phy *pi, struct radio_regs *radioregs,
void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
{
-#define DUMMY_PKT_LEN 20
- d11regs_t *regs = pi->regs;
+#define DUMMY_PKT_LEN 20
+ struct d11regs __iomem *regs = pi->regs;
int i, count;
u8 ofdmpkt[DUMMY_PKT_LEN] = {
0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
@@ -1156,9 +1049,8 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
W_REG(&regs->wepctl, 0);
W_REG(&regs->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
- if (ISNPHY(pi) || ISLCNPHY(pi)) {
+ if (ISNPHY(pi) || ISLCNPHY(pi))
W_REG(&regs->txe_phyctl1, 0x1A02);
- }
W_REG(&regs->txe_wm_0, 0);
W_REG(&regs->txe_wm_1, 0);
@@ -1185,16 +1077,14 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
i = 0;
count = ofdm ? 30 : 250;
while ((i++ < count)
- && (R_REG(&regs->txe_status) & (1 << 7))) {
+ && (R_REG(&regs->txe_status) & (1 << 7)))
udelay(10);
- }
i = 0;
while ((i++ < 10)
- && ((R_REG(&regs->txe_status) & (1 << 10)) == 0)) {
+ && ((R_REG(&regs->txe_status) & (1 << 10)) == 0))
udelay(10);
- }
i = 0;
@@ -1207,28 +1097,26 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
}
}
-void wlc_phy_hold_upd(struct brcms_phy_pub *pih, mbool id, bool set)
+void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
- if (set) {
+ if (set)
mboolset(pi->measure_hold, id);
- } else {
+ else
mboolclr(pi->measure_hold, id);
- }
return;
}
-void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, mbool flags)
+void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
- if (mute) {
+ if (mute)
mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE);
- } else {
+ else
mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE);
- }
if (!mute && (flags & PHY_MUTE_FOR_PREISM))
pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer;
@@ -1257,19 +1145,10 @@ static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
-
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
- {
- uint mc;
-
- mc = R_REG(&pi->regs->maccontrol);
- }
+ (void)R_REG(&pi->regs->maccontrol);
if (ISNPHY(pi)) {
wlc_phy_switch_radio_nphy(pi, on);
-
} else if (ISLCNPHY(pi)) {
if (on) {
and_phy_reg(pi, 0x44c,
@@ -1311,26 +1190,25 @@ void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw)
pi->bw = bw;
}
-void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, chanspec_t newch)
+void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
pi->radio_chanspec = newch;
}
-chanspec_t wlc_phy_chanspec_get(struct brcms_phy_pub *ppi)
+u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
return pi->radio_chanspec;
}
-void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, chanspec_t chanspec)
+void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
u16 m_cur_channel;
- chansetfn_t chanspec_set = NULL;
-
+ void (*chanspec_set)(struct brcms_phy *, u16) = NULL;
m_cur_channel = CHSPEC_CHANNEL(chanspec);
if (CHSPEC_IS5G(chanspec))
m_cur_channel |= D11_CURCHANNEL_5G;
@@ -1340,7 +1218,7 @@ void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, chanspec_t chanspec)
chanspec_set = pi->pi_fptr.chanset;
if (chanspec_set)
- (*chanspec_set) (pi, chanspec);
+ (*chanspec_set)(pi, chanspec);
}
@@ -1360,17 +1238,16 @@ int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq)
return range;
}
-int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, chanspec_t chanspec)
+int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, u16 chanspec)
{
int range = -1;
uint channel = CHSPEC_CHANNEL(chanspec);
uint freq = wlc_phy_channel2freq(channel);
- if (ISNPHY(pi)) {
+ if (ISNPHY(pi))
range = wlc_phy_get_chan_freq_range_nphy(pi, channel);
- } else if (ISLCNPHY(pi)) {
+ else if (ISLCNPHY(pi))
range = wlc_phy_chanspec_freq2bandrange_lpssn(freq);
- }
return range;
}
@@ -1396,13 +1273,13 @@ int wlc_phy_channel2freq(uint channel)
void
wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
- chanvec_t *channels)
+ struct brcms_chanvec *channels)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
uint i;
uint channel;
- memset(channels, 0, sizeof(chanvec_t));
+ memset(channels, 0, sizeof(struct brcms_chanvec));
for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
channel = chan_info_all[i].chan;
@@ -1417,17 +1294,17 @@ wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
}
}
-chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
+u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
uint i;
uint channel;
- chanspec_t chspec;
+ u16 chspec;
for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
channel = chan_info_all[i].chan;
- if (ISNPHY(pi) && IS40MHZ(pi)) {
+ if (ISNPHY(pi) && pi->bw == WL_CHANSPEC_BW_40) {
uint j;
for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) {
@@ -1439,16 +1316,15 @@ chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
if (j == ARRAY_SIZE(chan_info_all))
continue;
- channel = UPPER_20_SB(channel);
- chspec =
- channel | WL_CHANSPEC_BW_40 |
- WL_CHANSPEC_CTL_SB_LOWER;
+ channel = upper_20_sb(channel);
+ chspec = channel | WL_CHANSPEC_BW_40 |
+ WL_CHANSPEC_CTL_SB_LOWER;
if (band == BRCM_BAND_2G)
chspec |= WL_CHANSPEC_BAND_2G;
else
chspec |= WL_CHANSPEC_BAND_5G;
} else
- chspec = CH20MHZ_CHSPEC(channel);
+ chspec = ch20mhz_chspec(channel);
if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
&& (channel <= LAST_REF5_CHANNUM))
@@ -1459,7 +1335,7 @@ chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
return chspec;
}
- return (chanspec_t) INVCHANSPEC;
+ return (u16) INVCHANSPEC;
}
int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override)
@@ -1528,7 +1404,7 @@ int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
int i;
if (qdbm > 127)
- return 5;
+ return -EINVAL;
for (i = 0; i < TXP_NUM_RATES; i++)
pi->tx_user_target[i] = (u8) qdbm;
@@ -1539,10 +1415,8 @@ int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
if (!SCAN_INPROG_PHY(pi)) {
bool suspend;
- suspend =
- (0 ==
- (R_REG(&pi->regs->maccontrol) &
- MCTL_EN_MAC));
+ suspend = (0 == (R_REG(&pi->regs->maccontrol) &
+ MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@@ -1584,9 +1458,8 @@ wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr,
txp_rate_idx = TXP_FIRST_OFDM;
for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
- if (channel == chan_info_all[i].chan) {
+ if (channel == chan_info_all[i].chan)
break;
- }
}
if (pi->hwtxpwr) {
@@ -1620,7 +1493,8 @@ wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan,
pactrl = 0;
max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES :
- ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1);
+ ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 +
+ 1) : (TXP_LAST_OFDM + 1);
for (rate = 0; rate < max_num_rate; rate++) {
@@ -1659,6 +1533,46 @@ u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi)
return pi->tx_power_max;
}
+static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi)
+{
+ if (ISLCNPHY(pi))
+ return wlc_lcnphy_vbatsense(pi, 0);
+ else
+ return 0;
+}
+
+static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi)
+{
+ if (ISLCNPHY(pi))
+ return wlc_lcnphy_tempsense_degree(pi, 0);
+ else
+ return 0;
+}
+
+static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band)
+{
+ u8 i;
+ s8 temp, vbat;
+
+ for (i = 0; i < TXP_NUM_RATES; i++)
+ pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
+
+ vbat = wlc_phy_env_measure_vbat(pi);
+ temp = wlc_phy_env_measure_temperature(pi);
+
+}
+
+static s8
+wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
+ u8 rate)
+{
+ s8 offset = 0;
+
+ if (!pi->user_txpwr_at_rfport)
+ return offset;
+ return offset;
+}
+
void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
{
u8 maxtxpwr, mintxpwr, rate, pactrl;
@@ -1669,17 +1583,17 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
u8 tx_pwr_max_rate_ind = 0;
u8 max_num_rate;
u8 start_rate = 0;
- chanspec_t chspec;
+ u16 chspec;
u32 band = CHSPEC2BAND(pi->radio_chanspec);
- initfn_t txpwr_recalc_fn = NULL;
+ void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL;
chspec = pi->radio_chanspec;
if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
target_chan = CHSPEC_CHANNEL(chspec);
else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
- target_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
+ target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec));
else
- target_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
+ target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec));
pactrl = 0;
if (ISLCNPHY(pi)) {
@@ -1690,8 +1604,8 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
for (i = TXP_FIRST_SISO_MCS_20;
i <= TXP_LAST_SISO_MCS_20; i++) {
pi->tx_srom_max_rate_2g[i - 8] =
- pi->tx_srom_max_2g -
- ((offset_mcs & 0xf) * 2);
+ pi->tx_srom_max_2g -
+ ((offset_mcs & 0xf) * 2);
offset_mcs >>= 4;
}
} else {
@@ -1699,19 +1613,16 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
for (i = TXP_FIRST_SISO_MCS_20;
i <= TXP_LAST_SISO_MCS_20; i++) {
pi->tx_srom_max_rate_2g[i - 8] =
- pi->tx_srom_max_2g -
- ((offset_mcs & 0xf) * 2);
+ pi->tx_srom_max_2g -
+ ((offset_mcs & 0xf) * 2);
offset_mcs >>= 4;
}
}
}
-#if WL11N
+
max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
((ISLCNPHY(pi)) ?
(TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
-#else
- max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : (TXP_LAST_OFDM + 1));
-#endif
wlc_phy_upd_env_txpwr_rate_limits(pi, band);
@@ -1719,35 +1630,32 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
tx_pwr_target[rate] = pi->tx_user_target[rate];
- if (pi->user_txpwr_at_rfport) {
+ if (pi->user_txpwr_at_rfport)
tx_pwr_target[rate] +=
- wlc_user_txpwr_antport_to_rfport(pi, target_chan,
- band, rate);
- }
+ wlc_user_txpwr_antport_to_rfport(pi,
+ target_chan,
+ band,
+ rate);
- {
+ wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi,
+ target_chan,
+ &mintxpwr, &maxtxpwr, rate);
- wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi,
- target_chan,
- &mintxpwr, &maxtxpwr, rate);
+ maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
- maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
-
- maxtxpwr =
- (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
+ maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
- maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
+ maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
- maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
+ maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
- if (pi->txpwr_percent <= 100)
- maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
+ if (pi->txpwr_percent <= 100)
+ maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
- tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
- }
+ tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
tx_pwr_target[rate] =
- min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
+ min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
if (tx_pwr_target[rate] > tx_pwr_max)
tx_pwr_max_rate_ind = rate;
@@ -1764,23 +1672,22 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
pi->tx_power_target[rate] = tx_pwr_target[rate];
- if (!pi->hwpwrctrl || ISNPHY(pi)) {
+ if (!pi->hwpwrctrl || ISNPHY(pi))
pi->tx_power_offset[rate] =
- pi->tx_power_max - pi->tx_power_target[rate];
- } else {
+ pi->tx_power_max - pi->tx_power_target[rate];
+ else
pi->tx_power_offset[rate] =
- pi->tx_power_target[rate] - pi->tx_power_min;
- }
+ pi->tx_power_target[rate] - pi->tx_power_min;
}
txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
if (txpwr_recalc_fn)
- (*txpwr_recalc_fn) (pi);
+ (*txpwr_recalc_fn)(pi);
}
-void
+static void
wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
- chanspec_t chanspec)
+ u16 chanspec)
{
u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM];
u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
@@ -1815,7 +1722,7 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
txpwr_ptr1 = txpwr->mcs_40_siso;
txpwr_ptr2 = txpwr->ofdm_40_siso;
rate_start_index =
- WL_TX_POWER_OFDM40_SISO_FIRST;
+ WL_TX_POWER_OFDM40_SISO_FIRST;
break;
case 3:
@@ -1825,18 +1732,21 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
break;
}
- for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; rate2++) {
+ for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
+ rate2++) {
tmp_txpwr_limit[rate2] = 0;
tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
- txpwr_ptr1[rate2];
+ txpwr_ptr1[rate2];
}
- wlc_phy_mcs_to_ofdm_powers_nphy(tmp_txpwr_limit, 0,
- BRCMS_NUM_RATES_OFDM - 1, BRCMS_NUM_RATES_OFDM);
+ wlc_phy_mcs_to_ofdm_powers_nphy(
+ tmp_txpwr_limit, 0,
+ BRCMS_NUM_RATES_OFDM -
+ 1, BRCMS_NUM_RATES_OFDM);
for (rate1 = rate_start_index, rate2 = 0;
rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++)
pi->txpwr_limit[rate1] =
- min(txpwr_ptr2[rate2],
- tmp_txpwr_limit[rate2]);
+ min(txpwr_ptr2[rate2],
+ tmp_txpwr_limit[rate2]);
}
for (k = 0; k < 4; k++) {
@@ -1866,19 +1776,22 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
break;
}
- for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; rate2++) {
+ for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
+ rate2++) {
tmp_txpwr_limit[rate2] = 0;
tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
- txpwr_ptr1[rate2];
+ txpwr_ptr1[rate2];
}
- wlc_phy_ofdm_to_mcs_powers_nphy(tmp_txpwr_limit, 0,
- BRCMS_NUM_RATES_OFDM - 1, BRCMS_NUM_RATES_OFDM);
+ wlc_phy_ofdm_to_mcs_powers_nphy(
+ tmp_txpwr_limit, 0,
+ BRCMS_NUM_RATES_OFDM -
+ 1, BRCMS_NUM_RATES_OFDM);
for (rate1 = rate_start_index, rate2 = 0;
rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
rate1++, rate2++)
pi->txpwr_limit[rate1] =
- min(txpwr_ptr2[rate2],
- tmp_txpwr_limit[rate2]);
+ min(txpwr_ptr2[rate2],
+ tmp_txpwr_limit[rate2]);
}
for (k = 0; k < 2; k++) {
@@ -1922,10 +1835,10 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
- min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
- pi->txpwr_limit[WL_TX_POWER_MCS_32]);
+ min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
+ pi->txpwr_limit[WL_TX_POWER_MCS_32]);
pi->txpwr_limit[WL_TX_POWER_MCS_32] =
- pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
+ pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
}
}
@@ -1975,7 +1888,7 @@ void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end)
void
wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr,
- chanspec_t chanspec)
+ u16 chanspec)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
@@ -2016,9 +1929,8 @@ void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt)
void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
{
int j;
- if (ISNPHY(pi)) {
+ if (ISNPHY(pi))
return;
- }
if (!pi->sh->clk)
return;
@@ -2040,9 +1952,9 @@ void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
const u8 ucode_ofdm_rates[] = {
0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
};
- offset = wlapi_bmac_rate_shm_offset(pi->sh->physhim,
- ucode_ofdm_rates[j -
- TXP_FIRST_OFDM]);
+ offset = wlapi_bmac_rate_shm_offset(
+ pi->sh->physhim,
+ ucode_ofdm_rates[j - TXP_FIRST_OFDM]);
wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
pi->tx_power_offset[j]);
wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
@@ -2056,11 +1968,11 @@ void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
pi->tx_power_offset[i] =
- (u8) roundup(pi->tx_power_offset[i], 8);
+ (u8) roundup(pi->tx_power_offset[i], 8);
wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
- (u16) ((pi->
- tx_power_offset[TXP_FIRST_OFDM]
- + 7) >> 3));
+ (u16)
+ ((pi->tx_power_offset[TXP_FIRST_OFDM]
+ + 7) >> 3));
}
}
@@ -2068,48 +1980,38 @@ bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
- if (ISNPHY(pi)) {
+ if (ISNPHY(pi))
return pi->nphy_txpwrctrl;
- } else {
+ else
return pi->hwpwrctrl;
- }
}
void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl)
{
struct brcms_phy *pi = (struct brcms_phy *) ppi;
- bool cur_hwpwrctrl = pi->hwpwrctrl;
bool suspend;
- if (!pi->hwpwrctrl_capable) {
+ if (!pi->hwpwrctrl_capable)
return;
- }
pi->hwpwrctrl = hwpwrctrl;
pi->nphy_txpwrctrl = hwpwrctrl;
pi->txpwrctrl = hwpwrctrl;
if (ISNPHY(pi)) {
- suspend =
- (0 ==
- (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
- if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF)
wlc_phy_txpwr_fixpower_nphy(pi);
- } else {
-
+ else
mod_phy_reg(pi, 0x1e7, (0x7f << 0),
pi->saved_txpwr_idx);
- }
if (!suspend)
wlapi_enable_mac(pi->sh->physhim);
- } else if (hwpwrctrl != cur_hwpwrctrl) {
-
- return;
}
}
@@ -2125,8 +2027,6 @@ void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi)
}
}
-static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi);
-
static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi)
{
s16 tx0_status, tx1_status;
@@ -2137,42 +2037,31 @@ static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi)
estPower1 = read_phy_reg(pi, 0x118);
estPower2 = read_phy_reg(pi, 0x119);
- if ((estPower1 & (0x1 << 8))
- == (0x1 << 8)) {
- pwr0 = (u8) (estPower1 & (0xff << 0))
- >> 0;
- } else {
+ if ((estPower1 & (0x1 << 8)) == (0x1 << 8))
+ pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0;
+ else
pwr0 = 0x80;
- }
- if ((estPower2 & (0x1 << 8))
- == (0x1 << 8)) {
- pwr1 = (u8) (estPower2 & (0xff << 0))
- >> 0;
- } else {
+ if ((estPower2 & (0x1 << 8)) == (0x1 << 8))
+ pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0;
+ else
pwr1 = 0x80;
- }
tx0_status = read_phy_reg(pi, 0x1ed);
tx1_status = read_phy_reg(pi, 0x1ee);
- if ((tx0_status & (0x1 << 15))
- == (0x1 << 15)) {
- adj_pwr0 = (u8) (tx0_status & (0xff << 0))
- >> 0;
- } else {
+ if ((tx0_status & (0x1 << 15)) == (0x1 << 15))
+ adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0;
+ else
adj_pwr0 = 0x80;
- }
- if ((tx1_status & (0x1 << 15))
- == (0x1 << 15)) {
- adj_pwr1 = (u8) (tx1_status & (0xff << 0))
- >> 0;
- } else {
+ if ((tx1_status & (0x1 << 15)) == (0x1 << 15))
+ adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0;
+ else
adj_pwr1 = 0x80;
- }
- est_pwr =
- (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | adj_pwr1);
+ est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) |
+ adj_pwr1);
+
return est_pwr;
}
@@ -2193,7 +2082,7 @@ wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power,
power->flags |= (WL_TX_POWER_F_MIMO);
if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
power->flags |=
- (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
+ (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
} else if (ISLCNPHY(pi)) {
power->rf_cores = 1;
power->flags |= (WL_TX_POWER_F_SISO);
@@ -2256,16 +2145,18 @@ wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power,
power->tx_power_max[1] = pi->tx_power_max;
power->tx_power_max_rate_ind[0] =
- pi->tx_power_max_rate_ind;
+ pi->tx_power_max_rate_ind;
power->tx_power_max_rate_ind[1] =
- pi->tx_power_max_rate_ind;
+ pi->tx_power_max_rate_ind;
if (wlc_phy_tpc_isenabled_lcnphy(pi))
power->flags |=
- (WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
+ (WL_TX_POWER_F_HW |
+ WL_TX_POWER_F_ENABLED);
else
power->flags &=
- ~(WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
+ ~(WL_TX_POWER_F_HW |
+ WL_TX_POWER_F_ENABLED);
wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
(s8 *) &power->est_Pout_cck);
@@ -2304,16 +2195,13 @@ void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val)
BRCM_BAND_ALL);
}
- if (ISNPHY(pi)) {
-
+ if (ISNPHY(pi))
return;
- }
if (!pi->sh->clk)
return;
- suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@@ -2357,10 +2245,127 @@ wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant)
pwr_ant[i] = cmplx_pwr_dbm[i];
}
pi->nphy_noise_index =
- MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+ MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
return true;
}
+static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm)
+{
+ if (!pi->phynoise_state)
+ return;
+
+ if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
+ if (pi->phynoise_chan_watchdog == channel) {
+ pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
+ noise_dbm;
+ pi->sh->phy_noise_index =
+ MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
+ }
+ pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
+ }
+
+ if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL)
+ pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
+
+}
+
+static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi)
+{
+ u32 cmplx_pwr[PHY_CORE_MAX];
+ s8 noise_dbm_ant[PHY_CORE_MAX];
+ u16 lo, hi;
+ u32 cmplx_pwr_tot = 0;
+ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+ u8 idx, core;
+
+ memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
+ memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
+
+ for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2,
+ core++) {
+ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
+ hi = wlapi_bmac_read_shm(pi->sh->physhim,
+ M_PWRIND_MAP(idx + 1));
+ cmplx_pwr[core] = (hi << 16) + lo;
+ cmplx_pwr_tot += cmplx_pwr[core];
+ if (cmplx_pwr[core] == 0)
+ noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
+ else
+ cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
+ }
+
+ if (cmplx_pwr_tot != 0)
+ wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
+
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+ pi->nphy_noise_win[core][pi->nphy_noise_index] =
+ noise_dbm_ant[core];
+
+ if (noise_dbm_ant[core] > noise_dbm)
+ noise_dbm = noise_dbm_ant[core];
+ }
+ pi->nphy_noise_index =
+ MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+
+ return noise_dbm;
+
+}
+
+void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih)
+{
+ struct brcms_phy *pi = (struct brcms_phy *) pih;
+ u16 jssi_aux;
+ u8 channel = 0;
+ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+
+ if (ISLCNPHY(pi)) {
+ u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
+ u16 lo, hi;
+ s32 pwr_offset_dB, gain_dB;
+ u16 status_0, status_1;
+
+ jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+ channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
+ hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
+ cmplx_pwr0 = (hi << 16) + lo;
+
+ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
+ hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
+ cmplx_pwr1 = (hi << 16) + lo;
+ cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
+
+ status_0 = 0x44;
+ status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
+ if ((cmplx_pwr > 0 && cmplx_pwr < 500)
+ && ((status_1 & 0xc000) == 0x4000)) {
+
+ wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
+ pi->pubpi.phy_corenum);
+ pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
+ if (pwr_offset_dB > 127)
+ pwr_offset_dB -= 256;
+
+ noise_dbm += (s8) (pwr_offset_dB - 30);
+
+ gain_dB = (status_0 & 0x1ff);
+ noise_dbm -= (s8) (gain_dB);
+ } else {
+ noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
+ }
+ } else if (ISNPHY(pi)) {
+
+ jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+ channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+ noise_dbm = wlc_phy_noise_read_shmem(pi);
+ }
+
+ wlc_phy_noise_cb(pi, channel, noise_dbm);
+
+}
+
static void
wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
{
@@ -2369,20 +2374,13 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
bool sampling_in_progress = (pi->phynoise_state != 0);
bool wait_for_intr = true;
- if (NORADIO_ENAB(pi->pubpi)) {
- return;
- }
-
switch (reason) {
case PHY_NOISE_SAMPLE_MON:
-
pi->phynoise_chan_watchdog = ch;
pi->phynoise_state |= PHY_NOISE_STATE_MON;
-
break;
case PHY_NOISE_SAMPLE_EXTERNAL:
-
pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
break;
@@ -2398,15 +2396,13 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
if (pi->phy_fixed_noise) {
if (ISNPHY(pi)) {
pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
- PHY_NOISE_FIXED_VAL_NPHY;
+ PHY_NOISE_FIXED_VAL_NPHY;
pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
- PHY_NOISE_FIXED_VAL_NPHY;
+ PHY_NOISE_FIXED_VAL_NPHY;
pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
PHY_NOISE_WINDOW_SZ);
-
noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
} else {
-
noise_dbm = PHY_NOISE_FIXED_VAL;
}
@@ -2469,15 +2465,14 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
wlapi_enable_mac(pi->sh->physhim);
for (i = 0; i < pi->pubpi.phy_corenum; i++)
- cmplx_pwr[i] =
- (est[i].i_pwr +
- est[i].q_pwr) >> log_num_samps;
+ cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >>
+ log_num_samps;
wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
for (i = 0; i < pi->pubpi.phy_corenum; i++) {
pi->nphy_noise_win[i][pi->nphy_noise_index] =
- noise_dbm_ant[i];
+ noise_dbm_ant[i];
if (noise_dbm_ant[i] > noise_dbm)
noise_dbm = noise_dbm_ant[i];
@@ -2489,7 +2484,7 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
}
}
- done:
+done:
if (!wait_for_intr)
wlc_phy_noise_cb(pi, ch, noise_dbm);
@@ -2505,124 +2500,7 @@ void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih)
wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel);
}
-static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm)
-{
- if (!pi->phynoise_state)
- return;
-
- if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
- if (pi->phynoise_chan_watchdog == channel) {
- pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
- noise_dbm;
- pi->sh->phy_noise_index =
- MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
- }
- pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
- }
-
- if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) {
- pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
- }
-
-}
-
-static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi)
-{
- u32 cmplx_pwr[PHY_CORE_MAX];
- s8 noise_dbm_ant[PHY_CORE_MAX];
- u16 lo, hi;
- u32 cmplx_pwr_tot = 0;
- s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
- u8 idx, core;
-
- memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
- memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
-
- for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, core++) {
- lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
- hi = wlapi_bmac_read_shm(pi->sh->physhim,
- M_PWRIND_MAP(idx + 1));
- cmplx_pwr[core] = (hi << 16) + lo;
- cmplx_pwr_tot += cmplx_pwr[core];
- if (cmplx_pwr[core] == 0) {
- noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
- } else
- cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
- }
-
- if (cmplx_pwr_tot != 0)
- wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
-
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- pi->nphy_noise_win[core][pi->nphy_noise_index] =
- noise_dbm_ant[core];
-
- if (noise_dbm_ant[core] > noise_dbm)
- noise_dbm = noise_dbm_ant[core];
- }
- pi->nphy_noise_index =
- MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
-
- return noise_dbm;
-
-}
-
-void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih)
-{
- struct brcms_phy *pi = (struct brcms_phy *) pih;
- u16 jssi_aux;
- u8 channel = 0;
- s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
-
- if (ISLCNPHY(pi)) {
- u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
- u16 lo, hi;
- s32 pwr_offset_dB, gain_dB;
- u16 status_0, status_1;
-
- jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
- channel = jssi_aux & D11_CURCHANNEL_MAX;
-
- lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
- hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
- cmplx_pwr0 = (hi << 16) + lo;
-
- lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
- hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
- cmplx_pwr1 = (hi << 16) + lo;
- cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
-
- status_0 = 0x44;
- status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
- if ((cmplx_pwr > 0 && cmplx_pwr < 500)
- && ((status_1 & 0xc000) == 0x4000)) {
-
- wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
- pi->pubpi.phy_corenum);
- pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
- if (pwr_offset_dB > 127)
- pwr_offset_dB -= 256;
-
- noise_dbm += (s8) (pwr_offset_dB - 30);
-
- gain_dB = (status_0 & 0x1ff);
- noise_dbm -= (s8) (gain_dB);
- } else {
- noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
- }
- } else if (ISNPHY(pi)) {
-
- jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
- channel = jssi_aux & D11_CURCHANNEL_MAX;
-
- noise_dbm = wlc_phy_noise_read_shmem(pi);
- }
-
- wlc_phy_noise_cb(pi, channel, noise_dbm);
-
-}
-
-s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
+static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
8,
8,
8,
@@ -2678,27 +2556,21 @@ void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
}
}
-void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx)
+int wlc_phy_rssi_compute(struct brcms_phy_pub *pih,
+ struct d11rxhdr *rxh)
{
- struct brcms_d11rxhdr *wlc_rxhdr = (struct brcms_d11rxhdr *) ctx;
- struct d11rxhdr *rxh = &wlc_rxhdr->rxhdr;
- int rssi = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_JSSI_MASK;
+ int rssi = rxh->PhyRxStatus_1 & PRXS1_JSSI_MASK;
uint radioid = pih->radioid;
struct brcms_phy *pi = (struct brcms_phy *) pih;
- if (NORADIO_ENAB(pi->pubpi)) {
- rssi = BRCMS_RSSI_INVALID;
- goto end;
- }
-
if ((pi->sh->corerev >= 11)
- && !(le16_to_cpu(rxh->RxStatus2) & RXS_PHYRXST_VALID)) {
+ && !(rxh->RxStatus2 & RXS_PHYRXST_VALID)) {
rssi = BRCMS_RSSI_INVALID;
goto end;
}
if (ISLCNPHY(pi)) {
- u8 gidx = (le16_to_cpu(rxh->PhyRxStatus_2) & 0xFC00) >> 10;
+ u8 gidx = (rxh->PhyRxStatus_2 & 0xFC00) >> 10;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
if (rssi > 127)
@@ -2715,16 +2587,15 @@ void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx)
}
if (ISLCNPHY(pi)) {
-
if (rssi > 127)
rssi -= 256;
} else if (radioid == BCM2055_ID || radioid == BCM2056_ID
|| radioid == BCM2057_ID) {
- rssi = wlc_phy_rssi_compute_nphy(pi, wlc_rxhdr);
+ rssi = wlc_phy_rssi_compute_nphy(pi, rxh);
}
- end:
- wlc_rxhdr->rssi = (s8) rssi;
+end:
+ return rssi;
}
void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih)
@@ -2757,28 +2628,22 @@ void wlc_phy_watchdog(struct brcms_phy_pub *pih)
if (!pi->watchdog_override)
return;
- if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) {
+ if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)))
wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi,
PHY_NOISE_SAMPLE_MON,
CHSPEC_CHANNEL(pi->
radio_chanspec));
- }
- if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) {
+ if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5)
pi->phynoise_state = 0;
- }
if ((!pi->phycal_txpower) ||
((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
- if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) {
+ if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi))
pi->phycal_txpower = pi->sh->now;
- }
}
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
|| ASSOC_INPROG_PHY(pi)))
return;
@@ -2800,8 +2665,9 @@ void wlc_phy_watchdog(struct brcms_phy_pub *pih)
((pi->sh->now - pi->phy_lastcal) >=
pi->sh->glacial_timer)) {
if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
- wlc_lcnphy_calib_modes(pi,
- LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
+ wlc_lcnphy_calib_modes(
+ pi,
+ LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
if (!
(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
|| ASSOC_INPROG_PHY(pi)
@@ -2819,13 +2685,12 @@ void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi)
uint i;
uint k;
- for (i = 0; i < MA_WINDOW_SZ; i++) {
+ for (i = 0; i < MA_WINDOW_SZ; i++)
pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff);
- }
if (ISLCNPHY(pi)) {
for (i = 0; i < MA_WINDOW_SZ; i++)
pi->sh->phy_noise_window[i] =
- PHY_NOISE_FIXED_VAL_LCNPHY;
+ PHY_NOISE_FIXED_VAL_LCNPHY;
}
pi->sh->phy_noise_index = 0;
@@ -2848,72 +2713,9 @@ wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
*eps_real -= 0x2000;
}
-static const fixed AtanTbl[] = {
- 2949120,
- 1740967,
- 919879,
- 466945,
- 234379,
- 117304,
- 58666,
- 29335,
- 14668,
- 7334,
- 3667,
- 1833,
- 917,
- 458,
- 229,
- 115,
- 57,
- 29
-};
-
-void wlc_phy_cordic(fixed theta, cs32 *val)
-{
- fixed angle, valtmp;
- unsigned iter;
- int signx = 1;
- int signtheta;
-
- val[0].i = CORDIC_AG;
- val[0].q = 0;
- angle = 0;
-
- signtheta = (theta < 0) ? -1 : 1;
- theta =
- ((theta + FIXED(180) * signtheta) % FIXED(360)) -
- FIXED(180) * signtheta;
-
- if (FLOAT(theta) > 90) {
- theta -= FIXED(180);
- signx = -1;
- } else if (FLOAT(theta) < -90) {
- theta += FIXED(180);
- signx = -1;
- }
-
- for (iter = 0; iter < CORDIC_NI; iter++) {
- if (theta > angle) {
- valtmp = val[0].i - (val[0].q >> iter);
- val[0].q = (val[0].i >> iter) + val[0].q;
- val[0].i = valtmp;
- angle += AtanTbl[iter];
- } else {
- valtmp = val[0].i + (val[0].q >> iter);
- val[0].q = -(val[0].i >> iter) + val[0].q;
- val[0].i = valtmp;
- angle -= AtanTbl[iter];
- }
- }
-
- val[0].i = val[0].i * signx;
- val[0].q = val[0].q * signx;
-}
-
void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi)
{
- wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
+ wlapi_del_timer(pi->phycal_timer);
pi->cal_type_override = PHY_PERICAL_AUTO;
pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
@@ -2928,10 +2730,10 @@ wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay)
(pi->nphy_perical != PHY_PERICAL_MANUAL))
return;
- wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
+ wlapi_del_timer(pi->phycal_timer);
pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
- wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
+ wlapi_add_timer(pi->phycal_timer, delay, 0);
}
void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
@@ -2954,11 +2756,12 @@ void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
case PHY_PERICAL_PHYINIT:
if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
- if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+ if (PHY_PERICAL_MPHASE_PENDING(pi))
wlc_phy_cal_perical_mphase_reset(pi);
- }
- wlc_phy_cal_perical_mphase_schedule(pi,
- PHY_PERICAL_INIT_DELAY);
+
+ wlc_phy_cal_perical_mphase_schedule(
+ pi,
+ PHY_PERICAL_INIT_DELAY);
}
break;
@@ -2966,17 +2769,16 @@ void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
case PHY_PERICAL_START_IBSS:
case PHY_PERICAL_UP_BSS:
if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
- PHY_PERICAL_MPHASE_PENDING(pi)) {
+ PHY_PERICAL_MPHASE_PENDING(pi))
wlc_phy_cal_perical_mphase_reset(pi);
- }
pi->first_cal_after_assoc = true;
pi->cal_type_override = PHY_PERICAL_FULL;
- if (pi->phycal_tempdelta) {
+ if (pi->phycal_tempdelta)
pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
- }
+
wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
break;
@@ -2984,26 +2786,24 @@ void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
if (pi->phycal_tempdelta) {
nphy_currtemp = wlc_phy_tempsense_nphy(pi);
delta_temp =
- (nphy_currtemp > pi->nphy_lastcal_temp) ?
- nphy_currtemp - pi->nphy_lastcal_temp :
- pi->nphy_lastcal_temp - nphy_currtemp;
+ (nphy_currtemp > pi->nphy_lastcal_temp) ?
+ nphy_currtemp - pi->nphy_lastcal_temp :
+ pi->nphy_lastcal_temp - nphy_currtemp;
if ((delta_temp < (s16) pi->phycal_tempdelta) &&
(pi->nphy_txiqlocal_chanspec ==
- pi->radio_chanspec)) {
+ pi->radio_chanspec))
do_periodic_cal = false;
- } else {
+ else
pi->nphy_lastcal_temp = nphy_currtemp;
- }
}
if (do_periodic_cal) {
-
if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
-
if (!PHY_PERICAL_MPHASE_PENDING(pi))
- wlc_phy_cal_perical_mphase_schedule(pi,
- PHY_PERICAL_WDOG_DELAY);
+ wlc_phy_cal_perical_mphase_schedule(
+ pi,
+ PHY_PERICAL_WDOG_DELAY);
} else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
wlc_phy_cal_perical_nphy_run(pi,
PHY_PERICAL_AUTO);
@@ -3025,7 +2825,7 @@ u8 wlc_phy_nbits(s32 value)
s32 abs_val;
u8 nbits = 0;
- abs_val = ABS(value);
+ abs_val = abs(value);
while ((abs_val >> nbits) > 0)
nbits++;
@@ -3040,7 +2840,7 @@ void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
pi->sh->hw_phyrxchain = rxchain;
pi->sh->phytxchain = txchain;
pi->sh->phyrxchain = rxchain;
- pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
+ pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain);
}
void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
@@ -3049,10 +2849,10 @@ void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
pi->sh->phytxchain = txchain;
- if (ISNPHY(pi)) {
+ if (ISNPHY(pi))
wlc_phy_rxcore_setstate_nphy(pih, rxchain);
- }
- pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
+
+ pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain);
}
void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain)
@@ -3095,17 +2895,17 @@ u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih)
return active_bitmap;
}
-s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, chanspec_t chanspec)
+s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
u8 siso_mcs_id, cdd_mcs_id;
siso_mcs_id =
- (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
- TXP_FIRST_MCS_20_SISO;
+ (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
+ TXP_FIRST_MCS_20_SISO;
cdd_mcs_id =
- (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
- TXP_FIRST_MCS_20_CDD;
+ (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
+ TXP_FIRST_MCS_20_CDD;
if (pi->tx_power_target[siso_mcs_id] >
(pi->tx_power_target[cdd_mcs_id] + 12))
@@ -3133,12 +2933,13 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
}
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpiocontrol), ~0x0,
- 0x0);
+ offsetof(struct chipcregs, gpiocontrol),
+ ~0x0, 0x0);
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpioout), 0x40, 0x40);
+ offsetof(struct chipcregs, gpioout), 0x40,
+ 0x40);
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpioouten), 0x40,
+ offsetof(struct chipcregs, gpioouten), 0x40,
0x40);
} else {
mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
@@ -3146,56 +2947,18 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpioout), 0x40, 0x00);
+ offsetof(struct chipcregs, gpioout), 0x40,
+ 0x00);
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpioouten), 0x40, 0x0);
+ offsetof(struct chipcregs, gpioouten), 0x40,
+ 0x0);
ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, gpiocontrol), ~0x0,
- 0x40);
+ offsetof(struct chipcregs, gpiocontrol),
+ ~0x0, 0x40);
}
}
}
-static s8
-wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
- u8 rate)
-{
- s8 offset = 0;
-
- if (!pi->user_txpwr_at_rfport)
- return offset;
- return offset;
-}
-
-static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi)
-{
- if (ISLCNPHY(pi))
- return wlc_lcnphy_vbatsense(pi, 0);
- else
- return 0;
-}
-
-static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi)
-{
- if (ISLCNPHY(pi))
- return wlc_lcnphy_tempsense_degree(pi, 0);
- else
- return 0;
-}
-
-static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band)
-{
- u8 i;
- s8 temp, vbat;
-
- for (i = 0; i < TXP_NUM_RATES; i++)
- pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
-
- vbat = wlc_phy_env_measure_vbat(pi);
- temp = wlc_phy_env_measure_temperature(pi);
-
-}
-
void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc)
{
return;
@@ -3208,7 +2971,7 @@ wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset)
*ofdmoffset = 0;
}
-s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, chanspec_t chanspec)
+s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec)
{
return rssi;
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h
index e27d9e95a2dc..96e15163222b 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h
@@ -103,6 +103,9 @@
#define BRCMS_RSSI_INVALID 0 /* invalid RSSI value */
+struct d11regs;
+struct phy_shim_info;
+
struct txpwr_limits {
u8 cck[BRCMS_NUM_RATES_CCK];
u8 ofdm[BRCMS_NUM_RATES_OFDM];
@@ -126,42 +129,44 @@ struct txpwr_limits {
struct tx_power {
u32 flags;
- chanspec_t chanspec; /* txpwr report for this channel */
- chanspec_t local_chanspec; /* channel on which we are associated */
- u8 local_max; /* local max according to the AP */
- u8 local_constraint; /* local constraint according to the AP */
- s8 antgain[2]; /* Ant gain for each band - from SROM */
- u8 rf_cores; /* count of RF Cores being reported */
- u8 est_Pout[4]; /* Latest tx power out estimate per RF chain */
- u8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain
- * without adjustment
- */
- u8 est_Pout_cck; /* Latest CCK tx power out estimate */
- u8 tx_power_max[4]; /* Maximum target power among all rates */
- u8 tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */
- u8 user_limit[WL_TX_POWER_RATES]; /* User limit */
- u8 reg_limit[WL_TX_POWER_RATES]; /* Regulatory power limit */
- u8 board_limit[WL_TX_POWER_RATES]; /* Max power board can support (SROM) */
- u8 target[WL_TX_POWER_RATES]; /* Latest target power */
+ u16 chanspec; /* txpwr report for this channel */
+ u16 local_chanspec; /* channel on which we are associated */
+ u8 local_max; /* local max according to the AP */
+ u8 local_constraint; /* local constraint according to the AP */
+ s8 antgain[2]; /* Ant gain for each band - from SROM */
+ u8 rf_cores; /* count of RF Cores being reported */
+ u8 est_Pout[4]; /* Latest tx power out estimate per RF chain */
+ u8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain
+ * without adjustment */
+ u8 est_Pout_cck; /* Latest CCK tx power out estimate */
+ u8 tx_power_max[4]; /* Maximum target power among all rates */
+ /* Index of the rate with the max target power */
+ u8 tx_power_max_rate_ind[4];
+ /* User limit */
+ u8 user_limit[WL_TX_POWER_RATES];
+ /* Regulatory power limit */
+ u8 reg_limit[WL_TX_POWER_RATES];
+ /* Max power board can support (SROM) */
+ u8 board_limit[WL_TX_POWER_RATES];
+ /* Latest target power */
+ u8 target[WL_TX_POWER_RATES];
};
struct tx_inst_power {
- u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */
- u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */
+ u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */
+ u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */
};
-struct chanvec {
+struct brcms_chanvec {
u8 vec[MAXCHANNEL / NBBY];
};
struct shared_phy_params {
struct si_pub *sih;
- void *physhim;
+ struct phy_shim_info *physhim;
uint unit;
uint corerev;
- uint bustype;
uint buscorerev;
- char *vars;
u16 vid;
u16 did;
uint chip;
@@ -177,8 +182,9 @@ struct shared_phy_params {
extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp);
-extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, void *regs,
- int bandtype, char *vars, struct wiphy *wiphy);
+extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh,
+ struct d11regs __iomem *regs,
+ int bandtype, struct wiphy *wiphy);
extern void wlc_phy_detach(struct brcms_phy_pub *ppi);
extern bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype,
@@ -189,7 +195,7 @@ extern u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih);
extern void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate);
extern void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate);
-extern void wlc_phy_init(struct brcms_phy_pub *ppi, chanspec_t chanspec);
+extern void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec);
extern void wlc_phy_watchdog(struct brcms_phy_pub *ppi);
extern int wlc_phy_down(struct brcms_phy_pub *ppi);
extern u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih);
@@ -197,14 +203,15 @@ extern void wlc_phy_cal_init(struct brcms_phy_pub *ppi);
extern void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init);
extern void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi,
- chanspec_t chanspec);
-extern chanspec_t wlc_phy_chanspec_get(struct brcms_phy_pub *ppi);
+ u16 chanspec);
+extern u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi);
extern void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi,
- chanspec_t newch);
+ u16 newch);
extern u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi);
extern void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw);
-extern void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx);
+extern int wlc_phy_rssi_compute(struct brcms_phy_pub *pih,
+ struct d11rxhdr *rxh);
extern void wlc_phy_por_inform(struct brcms_phy_pub *ppi);
extern void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi);
extern bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi);
@@ -220,9 +227,9 @@ extern void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi);
extern void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
bool wide_filter);
extern void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
- chanvec_t *channels);
-extern chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi,
- uint band);
+ struct brcms_chanvec *channels);
+extern u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi,
+ uint band);
extern void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan,
u8 *_min_, u8 *_max_, int rate);
@@ -232,7 +239,7 @@ extern void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi,
uint band, s32 *, s32 *, u32 *);
extern void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi,
struct txpwr_limits *,
- chanspec_t chanspec);
+ u16 chanspec);
extern int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm,
bool *override);
extern int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm,
@@ -254,7 +261,7 @@ extern void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain,
u8 *rxchain);
extern u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih);
extern s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih,
- chanspec_t chanspec);
+ u16 chanspec);
extern void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val);
extern void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason);
@@ -264,8 +271,8 @@ extern void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi);
extern void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val);
extern void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi);
-extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, mbool id, bool val);
-extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, mbool flags);
+extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val);
+extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags);
extern void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type);
@@ -289,6 +296,6 @@ extern void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi);
extern const u8 *wlc_phy_get_ofdm_rate_lookup(void);
extern s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi,
- u8 mcs_offset);
+ u8 mcs_offset);
extern s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset);
-#endif /* _BRCM_PHY_HAL_H_ */
+#endif /* _BRCM_PHY_HAL_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h
index a01b01ccd9ff..bea85241a244 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h
@@ -23,53 +23,26 @@
#define PHY_VERSION { 1, 82, 8, 0 }
-#define PHYHAL_ERROR 0x0001
-#define PHYHAL_TRACE 0x0002
-#define PHYHAL_INFORM 0x0004
-
-extern u32 phyhal_msg_level;
-
-#define PHY_INFORM_ON() (phyhal_msg_level & PHYHAL_INFORM)
-#define PHY_THERMAL_ON() (phyhal_msg_level & PHYHAL_THERMAL)
-#define PHY_CAL_ON() (phyhal_msg_level & PHYHAL_CAL)
-
-#ifdef BOARD_TYPE
-#define BOARDTYPE(_type) BOARD_TYPE
-#else
-#define BOARDTYPE(_type) _type
-#endif
-
#define LCNXN_BASEREV 16
+struct phy_shim_info;
+
struct brcms_phy_srom_fem {
- u8 tssipos; /* TSSI positive slope, 1: positive, 0: negative */
- u8 extpagain; /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
- u8 pdetrange; /* support 32 combinations of different Pdet dynamic ranges */
- u8 triso; /* TR switch isolation */
- u8 antswctrllut; /* antswctrl lookup table configuration: 32 possible choices */
+ /* TSSI positive slope, 1: positive, 0: negative */
+ u8 tssipos;
+ /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
+ u8 extpagain;
+ /* support 32 combinations of different Pdet dynamic ranges */
+ u8 pdetrange;
+ /* TR switch isolation */
+ u8 triso;
+ /* antswctrl lookup table configuration: 32 possible choices */
+ u8 antswctrllut;
};
-typedef void (*initfn_t) (struct brcms_phy *);
-typedef void (*chansetfn_t) (struct brcms_phy *, chanspec_t);
-typedef int (*longtrnfn_t) (struct brcms_phy *, int);
-typedef void (*txiqccgetfn_t) (struct brcms_phy *, u16 *, u16 *);
-typedef void (*txiqccsetfn_t) (struct brcms_phy *, u16, u16);
-typedef u16(*txloccgetfn_t) (struct brcms_phy *);
-typedef void (*radioloftgetfn_t) (struct brcms_phy *, u8 *, u8 *, u8 *,
- u8 *);
-typedef s32(*rxsigpwrfn_t) (struct brcms_phy *, s32);
-typedef void (*detachfn_t) (struct brcms_phy *);
-
-#undef ISNPHY
-#undef ISLCNPHY
#define ISNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N)
#define ISLCNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN)
-#define ISPHY_11N_CAP(pi) (ISNPHY(pi) || ISLCNPHY(pi))
-
-#define IS20MHZ(pi) ((pi)->bw == WL_CHANSPEC_BW_20)
-#define IS40MHZ(pi) ((pi)->bw == WL_CHANSPEC_BW_40)
-
#define PHY_GET_RFATTN(rfgain) ((rfgain) & 0x0f)
#define PHY_GET_PADMIX(rfgain) (((rfgain) & 0x10) >> 4)
#define PHY_GET_RFGAINID(rfattn, padmix, width) ((rfattn) + ((padmix)*(width)))
@@ -203,7 +176,9 @@ typedef void (*detachfn_t) (struct brcms_phy *);
#define PHY_PERICAL_WDOG_DELAY 5
#define MPHASE_TXCAL_NUMCMDS 2
-#define PHY_PERICAL_MPHASE_PENDING(pi) (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE)
+
+#define PHY_PERICAL_MPHASE_PENDING(pi) \
+ (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE)
enum {
MPHASE_CAL_STATE_IDLE = 0,
@@ -248,47 +223,29 @@ enum phy_cal_mode {
#define CORDIC_AG 39797
#define CORDIC_NI 18
#define FIXED(X) ((s32)((X) << 16))
-#define FLOAT(X) (((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1))
+
+#define FLOAT(X) \
+ (((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1))
#define PHY_CHAIN_TX_DISABLE_TEMP 115
#define PHY_HYSTERESIS_DELTATEMP 5
-#define PHY_BITSCNT(x) brcmu_bitcount((u8 *)&(x), sizeof(u8))
-
-#define MOD_PHY_REG(pi, phy_type, reg_name, field, value) \
- mod_phy_reg(pi, phy_type##_##reg_name, phy_type##_##reg_name##_##field##_MASK, \
- (value) << phy_type##_##reg_name##_##field##_##SHIFT);
-#define READ_PHY_REG(pi, phy_type, reg_name, field) \
- ((read_phy_reg(pi, phy_type##_##reg_name) & phy_type##_##reg_name##_##field##_##MASK)\
- >> phy_type##_##reg_name##_##field##_##SHIFT)
+#define SCAN_INPROG_PHY(pi) \
+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN))
-#define VALID_PHYTYPE(phytype) (((uint)phytype == PHY_TYPE_N) || \
- ((uint)phytype == PHY_TYPE_LCN))
+#define PLT_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT))
-#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || (radioid == BCM2056_ID) || \
- (radioid == BCM2057_ID))
-#define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID)
+#define ASSOC_INPROG_PHY(pi) \
+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC))
-#define VALID_RADIO(pi, radioid) (\
- (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
- (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
+#define SCAN_RM_IN_PROGRESS(pi) \
+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM))
-#define SCAN_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN))
-#define RM_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_RM))
-#define PLT_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT))
-#define ASSOC_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC))
-#define SCAN_RM_IN_PROGRESS(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM))
-#define PHY_MUTED(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE))
-#define PUB_NOT_ASSOC(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC))
+#define PHY_MUTED(pi) \
+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE))
-#if defined(EXT_CBALL)
-#define NORADIO_ENAB(pub) ((pub).radioid == NORADIO_ID)
-#else
-#define NORADIO_ENAB(pub) 0
-#endif
-
-#define PHY_LTRN_LIST_LEN 64
-extern u16 ltrn_list[PHY_LTRN_LIST_LEN];
+#define PUB_NOT_ASSOC(pi) \
+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC))
struct phy_table_info {
uint table;
@@ -532,7 +489,7 @@ struct shared_phy {
struct brcms_phy *phy_head;
uint unit;
struct si_pub *sih;
- void *physhim;
+ struct phy_shim_info *physhim;
uint corerev;
u32 machwcap;
bool up;
@@ -549,7 +506,6 @@ struct shared_phy {
uint boardvendor;
u32 boardflags;
u32 boardflags2;
- uint bustype;
uint buscorerev;
uint fast_timer;
uint slow_timer;
@@ -579,41 +535,39 @@ struct brcms_phy_pub {
};
struct phy_func_ptr {
- initfn_t init;
- initfn_t calinit;
- chansetfn_t chanset;
- initfn_t txpwrrecalc;
- longtrnfn_t longtrn;
- txiqccgetfn_t txiqccget;
- txiqccsetfn_t txiqccset;
- txloccgetfn_t txloccget;
- radioloftgetfn_t radioloftget;
- initfn_t carrsuppr;
- rxsigpwrfn_t rxsigpwr;
- detachfn_t detach;
+ void (*init)(struct brcms_phy *);
+ void (*calinit)(struct brcms_phy *);
+ void (*chanset)(struct brcms_phy *, u16 chanspec);
+ void (*txpwrrecalc)(struct brcms_phy *);
+ int (*longtrn)(struct brcms_phy *, int);
+ void (*txiqccget)(struct brcms_phy *, u16 *, u16 *);
+ void (*txiqccset)(struct brcms_phy *, u16, u16);
+ u16 (*txloccget)(struct brcms_phy *);
+ void (*radioloftget)(struct brcms_phy *, u8 *, u8 *, u8 *, u8 *);
+ void (*carrsuppr)(struct brcms_phy *);
+ s32 (*rxsigpwr)(struct brcms_phy *, s32);
+ void (*detach)(struct brcms_phy *);
};
struct brcms_phy {
struct brcms_phy_pub pubpi_ro;
struct shared_phy *sh;
struct phy_func_ptr pi_fptr;
- void *pi_ptr;
union {
struct brcms_phy_lcnphy *pi_lcnphy;
} u;
bool user_txpwr_at_rfport;
- d11regs_t *regs;
+ struct d11regs __iomem *regs;
struct brcms_phy *next;
- char *vars;
struct brcms_phy_pub pubpi;
bool do_initcal;
bool phytest_on;
bool ofdm_rateset_war;
bool bf_preempt_4306;
- chanspec_t radio_chanspec;
+ u16 radio_chanspec;
u8 antsel_type;
u16 bw;
u8 txpwr_percent;
@@ -629,7 +583,7 @@ struct brcms_phy {
int phynoise_chan_watchdog;
bool phynoise_polling;
bool disable_percal;
- mbool measure_hold;
+ u32 measure_hold;
s16 txpa_2g[PWRTBL_NUM_COEFF];
s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF];
@@ -723,7 +677,7 @@ struct brcms_phy {
u16 mintxbias;
u16 mintxmag;
struct lo_complex_abgphy_info gphy_locomp_iq
- [STATIC_NUM_RF][STATIC_NUM_BB];
+ [STATIC_NUM_RF][STATIC_NUM_BB];
s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB];
u16 gain_table[TX_GAIN_TABLE_LENGTH];
bool loopback_gain;
@@ -840,11 +794,11 @@ struct brcms_phy {
u8 mphase_txcal_cmdidx;
u8 mphase_txcal_numcmds;
u16 mphase_txcal_bestcoeffs[11];
- chanspec_t nphy_txiqlocal_chanspec;
- chanspec_t nphy_iqcal_chanspec_2G;
- chanspec_t nphy_iqcal_chanspec_5G;
- chanspec_t nphy_rssical_chanspec_2G;
- chanspec_t nphy_rssical_chanspec_5G;
+ u16 nphy_txiqlocal_chanspec;
+ u16 nphy_iqcal_chanspec_2G;
+ u16 nphy_iqcal_chanspec_5G;
+ u16 nphy_rssical_chanspec_2G;
+ u16 nphy_rssical_chanspec_5G;
struct wlapi_timer *phycal_timer;
bool use_int_tx_iqlo_cal_nphy;
bool internal_tx_iqlo_cal_tapoff_intpa_nphy;
@@ -937,9 +891,9 @@ struct brcms_phy {
struct wiphy *wiphy;
};
-struct _cs32 {
- fixed q;
- fixed i;
+struct cs32 {
+ s32 q;
+ s32 i;
};
struct radio_regs {
@@ -964,29 +918,6 @@ struct lcnphy_radio_regs {
u8 do_init_g;
};
-extern struct lcnphy_radio_regs lcnphy_radio_regs_2064[];
-extern struct lcnphy_radio_regs lcnphy_radio_regs_2066[];
-extern struct radio_regs regs_2055[], regs_SYN_2056[], regs_TX_2056[],
- regs_RX_2056[];
-extern struct radio_regs regs_SYN_2056_A1[], regs_TX_2056_A1[],
- regs_RX_2056_A1[];
-extern struct radio_regs regs_SYN_2056_rev5[], regs_TX_2056_rev5[],
- regs_RX_2056_rev5[];
-extern struct radio_regs regs_SYN_2056_rev6[], regs_TX_2056_rev6[],
- regs_RX_2056_rev6[];
-extern struct radio_regs regs_SYN_2056_rev7[], regs_TX_2056_rev7[],
- regs_RX_2056_rev7[];
-extern struct radio_regs regs_SYN_2056_rev8[], regs_TX_2056_rev8[],
- regs_RX_2056_rev8[];
-extern struct radio_20xx_regs regs_2057_rev4[], regs_2057_rev5[],
- regs_2057_rev5v1[];
-extern struct radio_20xx_regs regs_2057_rev7[], regs_2057_rev8[];
-
-extern char *phy_getvar(struct brcms_phy *pi, const char *name);
-extern int phy_getintvar(struct brcms_phy *pi, const char *name);
-#define PHY_GETVAR(pi, name) phy_getvar(pi, name)
-#define PHY_GETINTVAR(pi, name) phy_getintvar(pi, name)
-
extern u16 read_phy_reg(struct brcms_phy *pi, u16 addr);
extern void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
extern void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
@@ -1022,14 +953,13 @@ extern void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val);
extern void write_phy_channel_reg(struct brcms_phy *pi, uint val);
extern void wlc_phy_txpower_update_shm(struct brcms_phy *pi);
-extern void wlc_phy_cordic(fixed theta, cs32 *val);
extern u8 wlc_phy_nbits(s32 value);
extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core);
extern uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
struct radio_20xx_regs *radioregs);
extern uint wlc_phy_init_radio_regs(struct brcms_phy *pi,
- struct radio_regs *radioregs,
+ const struct radio_regs *radioregs,
u16 core_offset);
extern void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi);
@@ -1053,14 +983,14 @@ extern void wlc_phy_cal_init_nphy(struct brcms_phy *pi);
extern void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi);
extern void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi,
- chanspec_t chanspec);
+ u16 chanspec);
extern void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi,
- chanspec_t chanspec);
+ u16 chanspec);
extern void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi,
- chanspec_t chanspec);
+ u16 chanspec);
extern int wlc_phy_channel2freq(uint channel);
extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint);
-extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, chanspec_t);
+extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec);
extern void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode);
extern s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi);
@@ -1142,13 +1072,17 @@ extern void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi,
bool enable);
extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode);
-#define wlc_phy_write_table_nphy(pi, pti) wlc_phy_write_table(pi, pti, 0x72, \
- 0x74, 0x73)
-#define wlc_phy_read_table_nphy(pi, pti) wlc_phy_read_table(pi, pti, 0x72, \
- 0x74, 0x73)
-#define wlc_nphy_table_addr(pi, id, off) wlc_phy_table_addr((pi), (id), (off), \
- 0x72, 0x74, 0x73)
-#define wlc_nphy_table_data_write(pi, w, v) wlc_phy_table_data_write((pi), (w), (v))
+#define wlc_phy_write_table_nphy(pi, pti) \
+ wlc_phy_write_table(pi, pti, 0x72, 0x74, 0x73)
+
+#define wlc_phy_read_table_nphy(pi, pti) \
+ wlc_phy_read_table(pi, pti, 0x72, 0x74, 0x73)
+
+#define wlc_nphy_table_addr(pi, id, off) \
+ wlc_phy_table_addr((pi), (id), (off), 0x72, 0x74, 0x73)
+
+#define wlc_nphy_table_data_write(pi, w, v) \
+ wlc_phy_table_data_write((pi), (w), (v))
extern void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o,
u32 w, void *d);
@@ -1160,7 +1094,7 @@ extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32,
(pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec)))
#define BRCMS_PHY_WAR_PR51571(pi) \
- if (((pi)->sh->bustype == PCI_BUS) && NREV_LT((pi)->pubpi.phy_rev, 3)) \
+ if (NREV_LT((pi)->pubpi.phy_rev, 3)) \
(void)R_REG(&(pi)->regs->maccontrol)
extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype);
@@ -1219,7 +1153,7 @@ extern void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf,
extern void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi);
extern int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi,
- struct brcms_d11rxhdr *wlc_rxh);
+ struct d11rxhdr *rxh);
#define NPHY_TESTPATTERN_BPHY_EVM 0
#define NPHY_TESTPATTERN_BPHY_RFCS 1
@@ -1229,7 +1163,7 @@ extern void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs);
void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset,
s8 *ofdmoffset);
extern s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi,
- chanspec_t chanspec);
+ u16 chanspec);
extern bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih);
#endif /* _BRCM_PHY_INT_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
index 6a3fbe67302f..a63aa99d9810 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -14,7 +14,9 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/kernel.h>
#include <linux/delay.h>
+#include <linux/cordic.h>
#include <pmu.h>
#include <d11.h>
@@ -67,6 +69,14 @@
#define LCN_TEMPSENSE_OFFSET 80812
#define LCN_TEMPSENSE_DEN 2647
+#define LCN_BW_LMT 200
+#define LCN_CUR_LMT 1250
+#define LCN_MULT 1
+#define LCN_VCO_DIV 30
+#define LCN_OFFSET 680
+#define LCN_FACT 490
+#define LCN_CUR_DIV 2640
+
#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
(0 + 8)
#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
@@ -79,15 +89,15 @@
#define wlc_lcnphy_enable_tx_gain_override(pi) \
wlc_lcnphy_set_tx_gain_override(pi, true)
-#define wlc_lcnphy_disable_tx_gain_override(pi) \
+#define wlc_lcnphy_disable_tx_gain_override(pi) \
wlc_lcnphy_set_tx_gain_override(pi, false)
#define wlc_lcnphy_iqcal_active(pi) \
(read_phy_reg((pi), 0x451) & \
- ((0x1 << 15) | (0x1 << 14)))
+ ((0x1 << 15) | (0x1 << 14)))
#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
-#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
+#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
(pi->temppwrctrl_capable)
#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
(pi->hwpwrctrl_capable)
@@ -132,12 +142,12 @@
#define LCNPHY_ACI_DETECT_TIMEOUT 2
#define LCNPHY_ACI_START_DELAY 0
-#define wlc_lcnphy_tx_gain_override_enabled(pi) \
+#define wlc_lcnphy_tx_gain_override_enabled(pi) \
(0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
#define wlc_lcnphy_total_tx_frames(pi) \
- wlapi_bmac_read_shm((pi)->sh->physhim, \
- M_UCODE_MACSTAT + offsetof(struct macstat, txallfrm))
+ wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + \
+ offsetof(struct macstat, txallfrm))
struct lcnphy_txgains {
u16 gm_gain;
@@ -198,7 +208,7 @@ static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
sizeof(tbl_iqcal_gainparams_lcnphy_2G) /
- sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
+ sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
};
static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = {
@@ -548,7 +558,7 @@ struct chan_info_2064_lcnphy {
u8 rxrf_rxrf_spare1;
};
-static struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = {
+static const struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = {
{1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
{2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
{3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
@@ -565,7 +575,7 @@ static struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = {
{14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
};
-struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = {
+static const struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = {
{0x00, 0, 0, 0, 0},
{0x01, 0x64, 0x64, 0, 0},
{0x02, 0x20, 0x20, 0, 0},
@@ -877,7 +887,7 @@ struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = {
#define LCNPHY_NUM_DIG_FILT_COEFFS 16
#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
-u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
+static const u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
{0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
128, 64,},
@@ -908,7 +918,7 @@ u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
};
#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
-u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
+static const u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
{0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
0x278, 0xfea0, 0x80, 0x100, 0x80,},
@@ -920,108 +930,50 @@ u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
mod_phy_reg(pi, 0x4a4, \
- (0x1ff << 0), \
- (u16)(idx) << 0)
+ (0x1ff << 0), \
+ (u16)(idx) << 0)
#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
mod_phy_reg(pi, 0x4a5, \
- (0x7 << 8), \
- (u16)(npt) << 8)
+ (0x7 << 8), \
+ (u16)(npt) << 8)
#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
(read_phy_reg((pi), 0x4a4) & \
- ((0x1 << 15) | \
- (0x1 << 14) | \
- (0x1 << 13)))
+ ((0x1 << 15) | \
+ (0x1 << 14) | \
+ (0x1 << 13)))
#define wlc_lcnphy_get_tx_pwr_npt(pi) \
((read_phy_reg(pi, 0x4a5) & \
- (0x7 << 8)) >> \
- 8)
+ (0x7 << 8)) >> \
+ 8)
#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
(read_phy_reg(pi, 0x473) & 0x1ff)
#define wlc_lcnphy_get_target_tx_pwr(pi) \
((read_phy_reg(pi, 0x4a7) & \
- (0xff << 0)) >> \
- 0)
+ (0xff << 0)) >> \
+ 0)
#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
mod_phy_reg(pi, 0x4a7, \
- (0xff << 0), \
- (u16)(target) << 0)
+ (0xff << 0), \
+ (u16)(target) << 0)
+
+#define wlc_radio_2064_rcal_done(pi) \
+ (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
+
+#define tempsense_done(pi) \
+ (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
-#define wlc_radio_2064_rcal_done(pi) (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
-#define tempsense_done(pi) (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
+#define LCNPHY_IQLOCC_READ(val) \
+ ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
-#define LCNPHY_IQLOCC_READ(val) ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
#define FIXED_TXPWR 78
#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
-static u32 wlc_lcnphy_qdiv_roundup(u32 divident, u32 divisor,
- u8 precision);
-static void wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
- u16 ext_lna, u16 trsw,
- u16 biq2, u16 biq1,
- u16 tia, u16 lna2,
- u16 lna1);
-static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi);
-static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain);
-static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx,
- bool rx);
-static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0);
-static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi);
-static void wlc_lcnphy_get_tx_gain(struct brcms_phy *pi,
- struct lcnphy_txgains *gains);
-static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable);
-static void wlc_lcnphy_toggle_afe_pwdn(struct brcms_phy *pi);
-static void wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi,
- bool enable);
-static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi,
- struct lcnphy_txgains *target_gains);
-static bool wlc_lcnphy_rx_iq_est(struct brcms_phy *pi, u16 num_samps,
- u8 wait_time, struct lcnphy_iq_est *iq_est);
-static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps);
-static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi);
-static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode);
-static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi);
-static void wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi,
- u8 channel);
-
-static void wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
- const struct lcnphy_tx_gain_tbl_entry *g);
-
-static void wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo,
- u16 thresh, s16 *ptr, int mode);
-static int wlc_lcnphy_calc_floor(s16 coeff, int type);
-static void wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi,
- u16 *values_to_save);
-static void wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi,
- u16 *values_to_save);
-static void wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x,
- s16 coeff_y);
-static struct lcnphy_unsign16_struct wlc_lcnphy_get_cc(struct brcms_phy *pi,
- int cal_type);
-static void wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type,
- int num_levels, int step_size_lg2);
-static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi);
-
-static void wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi,
- chanspec_t chanspec);
-static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi);
-static void wlc_lcnphy_temp_adj(struct brcms_phy *pi);
-static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi);
-static void wlc_lcnphy_baseband_init(struct brcms_phy *pi);
-static void wlc_lcnphy_radio_init(struct brcms_phy *pi);
-static void wlc_lcnphy_rc_cal(struct brcms_phy *pi);
-static void wlc_lcnphy_rcal(struct brcms_phy *pi);
-static void wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi,
- bool enable);
-static int wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm,
- s16 filt_type);
-static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b);
-
void wlc_lcnphy_write_table(struct brcms_phy *pi, const struct phytbl_info *pti)
{
wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
@@ -1034,7 +986,7 @@ void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti)
static void
wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id,
- const void *tbl_ptr, u32 tbl_len,
+ const u16 *tbl_ptr, u32 tbl_len,
u32 tbl_width, u32 tbl_offset)
{
struct phytbl_info tab;
@@ -1048,7 +1000,7 @@ wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id,
static void
wlc_lcnphy_common_write_table(struct brcms_phy *pi, u32 tbl_id,
- const void *tbl_ptr, u32 tbl_len,
+ const u16 *tbl_ptr, u32 tbl_len,
u32 tbl_width, u32 tbl_offset)
{
@@ -1092,12 +1044,12 @@ static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
int k;
k = 0;
if (type == 0) {
- if (coeff_x < 0) {
+ if (coeff_x < 0)
k = (coeff_x - 1) / 2;
- } else {
+ else
k = coeff_x / 2;
- }
}
+
if (type == 1) {
if ((coeff_x + 1) < 0)
k = (coeff_x) / 2;
@@ -1107,20 +1059,265 @@ static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
return k;
}
-s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi)
+static void
+wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains)
{
- s8 index;
+ u16 dac_gain, rfgain0, rfgain1;
+
+ dac_gain = read_phy_reg(pi, 0x439) >> 0;
+ gains->dac_gain = (dac_gain & 0x380) >> 7;
+
+ rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
+ rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
+
+ gains->gm_gain = rfgain0 & 0xff;
+ gains->pga_gain = (rfgain0 >> 8) & 0xff;
+ gains->pad_gain = rfgain1 & 0xff;
+}
+
+
+static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain)
+{
+ u16 dac_ctrl;
+
+ dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
+ dac_ctrl = dac_ctrl & 0xc7f;
+ dac_ctrl = dac_ctrl | (dac_gain << 7);
+ mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
+
+}
+
+static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable)
+{
+ u16 bit = bEnable ? 1 : 0;
+
+ mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
+
+ mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
+
+ mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
+}
+
+static void
+wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable)
+{
+ u16 ebit = enable ? 1 : 0;
+
+ mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
+
+ mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
+
+ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+ mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
+ mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
+ mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+ mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
+ } else {
+ mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
+ mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
+ mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+ }
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
+ mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
+ }
+}
+
+static void
+wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
+ u16 trsw,
+ u16 ext_lna,
+ u16 biq2,
+ u16 biq1,
+ u16 tia, u16 lna2, u16 lna1)
+{
+ u16 gain0_15, gain16_19;
+
+ gain16_19 = biq2 & 0xf;
+ gain0_15 = ((biq1 & 0xf) << 12) |
+ ((tia & 0xf) << 8) |
+ ((lna2 & 0x3) << 6) |
+ ((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);
+ mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+
+ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+ mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
+ } else {
+ mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
+
+ mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
+
+ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+ }
+
+ mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
+
+}
+
+static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx)
+{
+
+ mod_phy_reg(pi, 0x44d,
+ (0x1 << 1) |
+ (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
+
+ or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
+}
+
+static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi)
+{
+
+ and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
+}
+
+static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b)
+{
+ mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
+
+ mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
+
+ mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
+
+ mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
+
+ mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
+
+ mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
+
+}
+
+static bool
+wlc_lcnphy_rx_iq_est(struct brcms_phy *pi,
+ u16 num_samps,
+ u8 wait_time, struct lcnphy_iq_est *iq_est)
+{
+ int wait_count = 0;
+ bool result = true;
+ u8 phybw40;
+ phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+ mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
+
+ mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
+
+ mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
+
+ mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
+
+ mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
+
+ mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
+
+ while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
+
+ if (wait_count > (10 * 500)) {
+ result = false;
+ goto cleanup;
+ }
+ udelay(100);
+ wait_count++;
+ }
+
+ iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
+ (u32) read_phy_reg(pi, 0x484);
+ iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
+ (u32) read_phy_reg(pi, 0x486);
+ iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
+ (u32) read_phy_reg(pi, 0x488);
+
+cleanup:
+ mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
+
+ mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
+
+ return result;
+}
+
+static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps)
+{
+#define LCNPHY_MIN_RXIQ_PWR 2
+ bool result;
+ u16 a0_new, b0_new;
+ struct lcnphy_iq_est iq_est = { 0, 0, 0 };
+ s32 a, b, temp;
+ s16 iq_nbits, qq_nbits, arsh, brsh;
+ s32 iq;
+ u32 ii, qq;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- if (txpwrctrl_off(pi))
- index = pi_lcn->lcnphy_current_index;
- else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
- index =
- (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi)
- / 2);
- else
- index = pi_lcn->lcnphy_current_index;
- return index;
+ a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
+ b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
+ mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
+
+ mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
+
+ wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
+
+ result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
+ if (!result)
+ goto cleanup;
+
+ iq = (s32) iq_est.iq_prod;
+ ii = iq_est.i_pwr;
+ qq = iq_est.q_pwr;
+
+ if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
+ result = false;
+ goto cleanup;
+ }
+
+ iq_nbits = wlc_phy_nbits(iq);
+ qq_nbits = wlc_phy_nbits(qq);
+
+ arsh = 10 - (30 - iq_nbits);
+ if (arsh >= 0) {
+ a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+ temp = (s32) (ii >> arsh);
+ if (temp == 0)
+ return false;
+ } else {
+ a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+ temp = (s32) (ii << -arsh);
+ if (temp == 0)
+ return false;
+ }
+ a /= temp;
+ brsh = qq_nbits - 31 + 20;
+ if (brsh >= 0) {
+ b = (qq << (31 - qq_nbits));
+ temp = (s32) (ii >> brsh);
+ if (temp == 0)
+ return false;
+ } else {
+ b = (qq << (31 - qq_nbits));
+ temp = (s32) (ii << -brsh);
+ if (temp == 0)
+ return false;
+ }
+ b /= temp;
+ b -= a * a;
+ b = (s32) int_sqrt((unsigned long) b);
+ b -= (1 << 10);
+ a0_new = (u16) (a & 0x3ff);
+ b0_new = (u16) (b & 0x3ff);
+cleanup:
+
+ wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
+
+ mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
+
+ mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
+
+ pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
+ pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
+
+ return result;
}
static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
@@ -1132,6 +1329,187 @@ 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(struct brcms_phy *pi,
+ const struct lcnphy_rx_iqcomp *iqcomp,
+ int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
+ int tx_gain_idx)
+{
+ struct lcnphy_txgains old_gains;
+ u16 tx_pwr_ctrl;
+ u8 tx_gain_index_old = 0;
+ bool result = false, tx_gain_override_old = false;
+ u16 i, Core1TxControl_old, RFOverride0_old,
+ 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;
+ u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
+ u16 values_to_save[11];
+ s16 *ptr;
+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+ ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+ if (NULL == ptr)
+ return false;
+ if (module == 2) {
+ while (iqcomp_sz--) {
+ if (iqcomp[iqcomp_sz].chan ==
+ CHSPEC_CHANNEL(pi->radio_chanspec)) {
+ wlc_lcnphy_set_rx_iq_comp(pi,
+ (u16)
+ iqcomp[iqcomp_sz].a,
+ (u16)
+ iqcomp[iqcomp_sz].b);
+ result = true;
+ break;
+ }
+ }
+ goto cal_done;
+ }
+
+ if (module == 1) {
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ received_power =
+ wlc_lcnphy_measure_digital_power(pi, 2000);
+ if (received_power < rx_pwr_threshold)
+ break;
+ }
+ result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
+
+ wlc_lcnphy_stop_tx_tone(pi);
+
+ 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);
+
+ 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]);
+
+ 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);
+ }
+
+cal_done:
+ kfree(ptr);
+ return result;
+}
+
+s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi)
+{
+ s8 index;
+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+ if (txpwrctrl_off(pi))
+ index = pi_lcn->lcnphy_current_index;
+ else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+ index = (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(
+ pi) / 2);
+ else
+ index = pi_lcn->lcnphy_current_index;
+ return index;
+}
+
void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel)
{
u16 afectrlovr, afectrlovrval;
@@ -1200,7 +1578,290 @@ wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi, bool enable)
wlapi_switch_macfreq(pi->sh->physhim, enable);
}
-void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, chanspec_t chanspec)
+static void
+wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec)
+{
+ u8 channel = CHSPEC_CHANNEL(chanspec);
+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+ if (channel == 14)
+ mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+ else
+ mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+ pi_lcn->lcnphy_bandedge_corr = 2;
+ if (channel == 1)
+ pi_lcn->lcnphy_bandedge_corr = 4;
+
+ if (channel == 1 || channel == 2 || channel == 3 ||
+ channel == 4 || channel == 9 ||
+ channel == 10 || channel == 11 || channel == 12) {
+ si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
+ si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
+ si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
+
+ si_pmu_pllupd(pi->sh->sih);
+ write_phy_reg(pi, 0x942, 0);
+ wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
+ pi_lcn->lcnphy_spurmod = 0;
+ mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
+
+ write_phy_reg(pi, 0x425, 0x5907);
+ } else {
+ si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
+ si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
+ si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
+
+ si_pmu_pllupd(pi->sh->sih);
+ write_phy_reg(pi, 0x942, 0);
+ wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
+
+ pi_lcn->lcnphy_spurmod = 0;
+ mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
+
+ write_phy_reg(pi, 0x425, 0x590a);
+ }
+
+ or_phy_reg(pi, 0x44a, 0x44);
+ write_phy_reg(pi, 0x44a, 0x80);
+}
+
+static void
+wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
+{
+ uint i;
+ const struct chan_info_2064_lcnphy *ci;
+ u8 rfpll_doubler = 0;
+ u8 pll_pwrup, pll_pwrup_ovr;
+ s32 qFxtal, qFref, qFvco, qFcal;
+ u8 d15, d16, f16, e44, e45;
+ u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
+ u16 loop_bw, d30, setCount;
+
+ u8 h29, h28_ten, e30, h30_ten, cp_current;
+ u16 g30, d28;
+
+ ci = &chan_info_2064_lcnphy[0];
+ rfpll_doubler = 1;
+
+ mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
+
+ write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
+ if (!rfpll_doubler) {
+ loop_bw = PLL_2064_LOOP_BW;
+ d30 = PLL_2064_D30;
+ } else {
+ loop_bw = PLL_2064_LOOP_BW_DOUBLER;
+ d30 = PLL_2064_D30_DOUBLER;
+ }
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
+ if (chan_info_2064_lcnphy[i].chan == channel)
+ break;
+
+ if (i >= ARRAY_SIZE(chan_info_2064_lcnphy))
+ return;
+
+ ci = &chan_info_2064_lcnphy[i];
+ }
+
+ write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
+
+ mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
+
+ mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
+
+ mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
+
+ mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
+ (ci->logen_rccr_rx) << 2);
+
+ mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
+
+ mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
+ (ci->pa_rxrf_lna2_freq_tune) << 4);
+
+ write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
+
+ pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
+ pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
+
+ or_radio_reg(pi, RADIO_2064_REG044, 0x07);
+
+ or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
+ e44 = 0;
+ e45 = 0;
+
+ fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
+ if (pi->xtalfreq > 26000000)
+ e44 = 1;
+ if (pi->xtalfreq > 52000000)
+ e45 = 1;
+ if (e44 == 0)
+ fcal_div = 1;
+ else if (e45 == 0)
+ fcal_div = 2;
+ else
+ fcal_div = 4;
+ fvco3 = (ci->freq * 3);
+ fref3 = 2 * fpfd;
+
+ qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
+ qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
+ qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
+ qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
+
+ write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
+
+ d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
+ write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
+ write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
+
+ d16 = (qFcal * 8 / (d15 + 1)) - 1;
+ write_radio_reg(pi, RADIO_2064_REG051, d16);
+
+ f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
+ setCount = f16 * 3 * (ci->freq) / 32 - 1;
+ mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
+ (u8) (setCount >> 8));
+
+ or_radio_reg(pi, RADIO_2064_REG053, 0x10);
+ write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
+
+ div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
+
+ div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
+ while (div_frac >= fref3) {
+ div_int++;
+ div_frac -= fref3;
+ }
+ div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
+
+ mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
+ (u8) (div_int >> 4));
+ mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
+ (u8) (div_int << 4));
+ mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
+ (u8) (div_frac >> 16));
+ write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
+ write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
+
+ write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
+
+ write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
+ write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
+ write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
+
+ h29 = LCN_BW_LMT / loop_bw;
+ d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
+ (fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
+ (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
+ + PLL_2064_LOW_END_KVCO;
+ h28_ten = (d28 * 10) / LCN_VCO_DIV;
+ e30 = (d30 - LCN_OFFSET) / LCN_FACT;
+ g30 = LCN_OFFSET + (e30 * LCN_FACT);
+ h30_ten = (g30 * 10) / LCN_CUR_DIV;
+ cp_current = ((LCN_CUR_LMT * h29 * LCN_MULT * 100) / h28_ten) / h30_ten;
+ mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
+
+ if (channel >= 1 && channel <= 5)
+ write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
+ else
+ write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
+ write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
+
+ mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
+ udelay(1);
+
+ wlc_2064_vco_cal(pi);
+
+ write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
+ write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+ write_radio_reg(pi, RADIO_2064_REG038, 3);
+ write_radio_reg(pi, RADIO_2064_REG091, 7);
+ }
+}
+
+static int
+wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type)
+{
+ s16 filt_index = -1;
+ int j;
+
+ u16 addr[] = {
+ 0x910,
+ 0x91e,
+ 0x91f,
+ 0x924,
+ 0x925,
+ 0x926,
+ 0x920,
+ 0x921,
+ 0x927,
+ 0x928,
+ 0x929,
+ 0x922,
+ 0x923,
+ 0x930,
+ 0x931,
+ 0x932
+ };
+
+ u16 addr_ofdm[] = {
+ 0x90f,
+ 0x900,
+ 0x901,
+ 0x906,
+ 0x907,
+ 0x908,
+ 0x902,
+ 0x903,
+ 0x909,
+ 0x90a,
+ 0x90b,
+ 0x904,
+ 0x905,
+ 0x90c,
+ 0x90d,
+ 0x90e
+ };
+
+ if (!is_ofdm) {
+ for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
+ if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
+ filt_index = (s16) j;
+ break;
+ }
+ }
+
+ if (filt_index != -1) {
+ for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, addr[j],
+ LCNPHY_txdigfiltcoeffs_cck
+ [filt_index][j + 1]);
+ }
+ } else {
+ for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
+ if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
+ filt_index = (s16) j;
+ break;
+ }
+ }
+
+ if (filt_index != -1) {
+ for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, addr_ofdm[j],
+ LCNPHY_txdigfiltcoeffs_ofdm
+ [filt_index][j + 1]);
+ }
+ }
+
+ return (filt_index != -1) ? 0 : -1;
+}
+
+void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
{
u8 channel = CHSPEC_CHANNEL(chanspec);
@@ -1211,10 +1872,8 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, chanspec_t chanspec)
or_phy_reg(pi, 0x44a, 0x44);
write_phy_reg(pi, 0x44a, 0x80);
- if (!NORADIO_ENAB(pi->pubpi)) {
- wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
- udelay(1000);
- }
+ wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
+ udelay(1000);
wlc_lcnphy_toggle_afe_pwdn(pi);
@@ -1237,35 +1896,13 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, chanspec_t chanspec)
}
-static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain)
-{
- u16 dac_ctrl;
-
- dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
- dac_ctrl = dac_ctrl & 0xc7f;
- dac_ctrl = dac_ctrl | (dac_gain << 7);
- mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
-
-}
-
-static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable)
-{
- u16 bit = bEnable ? 1 : 0;
-
- mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
-
- mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
-
- mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
-}
-
static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi)
{
u16 pa_gain;
pa_gain = (read_phy_reg(pi, 0x4fb) &
LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
- LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
+ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
return pa_gain;
}
@@ -1275,18 +1912,22 @@ static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi,
{
u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
- mod_phy_reg(pi, 0x4b5,
- (0xffff << 0),
- ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
- 0);
+ mod_phy_reg(
+ pi, 0x4b5,
+ (0xffff << 0),
+ ((target_gains->gm_gain) |
+ (target_gains->pga_gain << 8)) <<
+ 0);
mod_phy_reg(pi, 0x4fb,
(0x7fff << 0),
((target_gains->pad_gain) | (pa_gain << 8)) << 0);
- mod_phy_reg(pi, 0x4fc,
- (0xffff << 0),
- ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
- 0);
+ mod_phy_reg(
+ pi, 0x4fc,
+ (0xffff << 0),
+ ((target_gains->gm_gain) |
+ (target_gains->pga_gain << 8)) <<
+ 0);
mod_phy_reg(pi, 0x4fd,
(0x7fff << 0),
((target_gains->pad_gain) | (pa_gain << 8)) << 0);
@@ -1404,8 +2045,8 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- auxpga_vmid =
- (2 << 8) | (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
+ auxpga_vmid = (2 << 8) |
+ (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
auxpga_gain_temp = 2;
@@ -1531,10 +2172,9 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
- if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
mod_phy_reg(pi, 0x4d7,
(0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
- }
rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
@@ -1601,7 +2241,7 @@ void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi)
{
struct phytbl_info tab;
u32 rate_table[BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM +
- BRCMS_NUM_RATES_MCS_1_STREAM];
+ BRCMS_NUM_RATES_MCS_1_STREAM];
uint i, j;
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
return;
@@ -1694,34 +2334,28 @@ static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi)
index = FIXED_TXPWR;
- if (NORADIO_ENAB(pi->pubpi))
+ if (pi_lcn->lcnphy_tempsense_slope == 0)
return index;
- if (pi_lcn->lcnphy_tempsense_slope == 0) {
- return index;
- }
temp = (u16) wlc_lcnphy_tempsense(pi, 0);
meas_temp = LCNPHY_TEMPSENSE(temp);
- if (pi->tx_power_min != 0) {
+ if (pi->tx_power_min != 0)
delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
- } else {
+ else
delta_brd = 0;
- }
manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
temp_diff = manp - meas_temp;
if (temp_diff < 0) {
-
neg = 1;
-
temp_diff = -temp_diff;
}
delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
- (u32) (pi_lcn->
- lcnphy_tempsense_slope
- * 10), 0);
+ (u32) (pi_lcn->
+ lcnphy_tempsense_slope
+ * 10), 0);
if (neg)
delta_temp = -delta_temp;
@@ -1735,14 +2369,15 @@ static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi)
if (LCNREV_IS(pi->pubpi.phy_rev, 1))
tempcorrx = 4;
new_index =
- index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
+ index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
new_index += tempcorrx;
if (LCNREV_IS(pi->pubpi.phy_rev, 1))
index = 127;
- if (new_index < 0 || new_index > 126) {
+
+ if (new_index < 0 || new_index > 126)
return index;
- }
+
return new_index;
}
@@ -1792,7 +2427,7 @@ void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode)
mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
pi_lcn->lcnphy_tssi_tx_cnt =
- wlc_lcnphy_total_tx_frames(pi);
+ wlc_lcnphy_total_tx_frames(pi);
wlc_lcnphy_disable_tx_gain_override(pi);
pi_lcn->lcnphy_tx_power_idx_override = -1;
@@ -1805,11 +2440,105 @@ void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode)
index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
pi_lcn->lcnphy_current_index = (s8)
- ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
+ ((read_phy_reg(pi,
+ 0x4a9) &
+ 0xFF) / 2);
}
}
}
+static void
+wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save)
+{
+ u16 vmid;
+ int i;
+ for (i = 0; i < 20; i++)
+ values_to_save[i] =
+ read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
+
+ mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
+ mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
+
+ mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
+ mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
+
+ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+ if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+ and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
+ else
+ and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
+ or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
+
+ or_radio_reg(pi, RADIO_2064_REG036, 0x01);
+ or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
+ udelay(20);
+
+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
+ else
+ or_radio_reg(pi, RADIO_2064_REG03A, 1);
+ } else {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
+ else
+ or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
+ }
+
+ udelay(20);
+
+ write_radio_reg(pi, RADIO_2064_REG025, 0xF);
+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
+ else
+ mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
+ } else {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
+ else
+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
+ }
+
+ udelay(20);
+
+ write_radio_reg(pi, RADIO_2064_REG005, 0x8);
+ or_radio_reg(pi, RADIO_2064_REG112, 0x80);
+ udelay(20);
+
+ or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+ or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+ udelay(20);
+
+ or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+ or_radio_reg(pi, RADIO_2064_REG113, 0x10);
+ udelay(20);
+
+ write_radio_reg(pi, RADIO_2064_REG007, 0x1);
+ udelay(20);
+
+ vmid = 0x2A6;
+ mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
+ write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
+ or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+ udelay(20);
+
+ or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+ udelay(20);
+ write_radio_reg(pi, RADIO_2064_REG012, 0x02);
+ or_radio_reg(pi, RADIO_2064_REG112, 0x06);
+ write_radio_reg(pi, RADIO_2064_REG036, 0x11);
+ write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
+ write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
+ write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
+ write_radio_reg(pi, RADIO_2064_REG092, 0x15);
+}
+
static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi)
{
uint delay_count = 0;
@@ -1826,6 +2555,20 @@ static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi)
}
static void
+wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save)
+{
+ int i;
+
+ and_phy_reg(pi, 0x44c, 0x0 >> 11);
+
+ and_phy_reg(pi, 0x43b, 0xC);
+
+ for (i = 0; i < 20; i++)
+ write_radio_reg(pi, iqlo_loopback_rf_regs[i],
+ values_to_save[i]);
+}
+
+static void
wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
struct lcnphy_txgains *target_gains,
enum lcnphy_cal_mode cal_mode, bool keep_tone)
@@ -1837,20 +2580,23 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
int j;
u16 ncorr_override[5];
u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
- };
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000};
u16 commands_fullcal[] = {
- 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
+ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234
+ };
u16 commands_recal[] = {
- 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
+ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234
+ };
u16 command_nums_fullcal[] = {
- 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
+ 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97
+ };
u16 command_nums_recal[] = {
- 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
+ 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97
+ };
u16 *command_nums = command_nums_fullcal;
u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
@@ -1862,13 +2608,9 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
u16 *values_to_save;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
- if (NULL == values_to_save) {
+ if (NULL == values_to_save)
return;
- }
save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
@@ -1927,7 +2669,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
}
hash = (target_gains->gm_gain << 8) |
- (target_gains->pga_gain << 4) | (target_gains->pad_gain);
+ (target_gains->pga_gain << 4) | (target_gains->pad_gain);
band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
@@ -1936,11 +2678,11 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
cal_gains.gm_gain =
- tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
+ tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
cal_gains.pga_gain =
- tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
+ tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
cal_gains.pad_gain =
- tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
+ tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
memcpy(ncorr_override,
&tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
sizeof(ncorr_override));
@@ -1954,14 +2696,14 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
write_phy_reg(pi, 0x93d, 0xc0);
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
- (const void *)
lcnphy_iqcal_loft_gainladder,
ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
16, 0);
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
- (const void *)lcnphy_iqcal_ir_gainladder,
- ARRAY_SIZE(lcnphy_iqcal_ir_gainladder), 16,
+ lcnphy_iqcal_ir_gainladder,
+ ARRAY_SIZE(
+ lcnphy_iqcal_ir_gainladder), 16,
32);
if (pi->phy_tx_tone_freq) {
@@ -1985,13 +2727,12 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
command_num = command_nums[i];
if (ncorr_override[cal_type])
command_num =
- ncorr_override[cal_type] << 8 | (command_num &
- 0xff);
+ ncorr_override[cal_type] << 8 | (command_num &
+ 0xff);
write_phy_reg(pi, 0x452, command_num);
if ((cal_type == 3) || (cal_type == 4)) {
-
wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
&diq_start, 1, 16, 69);
@@ -2001,10 +2742,8 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
write_phy_reg(pi, 0x451, cal_cmds[i]);
- if (!wlc_lcnphy_iqcal_wait(pi)) {
-
+ if (!wlc_lcnphy_iqcal_wait(pi))
goto cleanup;
- }
wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
best_coeffs,
@@ -2013,16 +2752,15 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
best_coeffs,
ARRAY_SIZE(best_coeffs), 16, 64);
- if ((cal_type == 3) || (cal_type == 4)) {
+ if ((cal_type == 3) || (cal_type == 4))
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
&diq_start, 1, 16, 69);
- }
wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
pi_lcn->lcnphy_cal_results.
txiqlocal_bestcoeffs,
ARRAY_SIZE(pi_lcn->
- lcnphy_cal_results.
- txiqlocal_bestcoeffs),
+ lcnphy_cal_results.
+ txiqlocal_bestcoeffs),
16, 96);
}
@@ -2030,7 +2768,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
pi_lcn->lcnphy_cal_results.
txiqlocal_bestcoeffs,
ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
- txiqlocal_bestcoeffs), 16, 96);
+ txiqlocal_bestcoeffs), 16, 96);
pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
@@ -2041,7 +2779,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
&pi_lcn->lcnphy_cal_results.
txiqlocal_bestcoeffs[5], 2, 16, 85);
- cleanup:
+cleanup:
wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
kfree(values_to_save);
@@ -2071,14 +2809,14 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
u16 SAVE_jtag_bb_afe_switch =
- read_radio_reg(pi, RADIO_2064_REG007) & 1;
+ 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;
idleTssi = read_phy_reg(pi, 0x4ab);
suspend =
- (0 ==
- (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) &
- MCTL_EN_MAC));
+ (0 ==
+ (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) &
+ MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
@@ -2136,7 +2874,7 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
struct phytbl_info tab;
u32 val;
u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
- save_reg112;
+ save_reg112;
u16 values_to_save[14];
s8 index;
int i;
@@ -2152,8 +2890,7 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
for (i = 0; i < 14; i++)
values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
- suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
@@ -2236,7 +2973,7 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
auxpga_gain = 2;
}
auxpga_vmid =
- (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
+ (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
@@ -2280,17 +3017,10 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
struct brcms_phy *pi = (struct brcms_phy *) ppi;
suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
- if (NORADIO_ENAB(pi->pubpi)) {
- wlc_lcnphy_set_bbmult(pi, 0x30);
- if (!suspend)
- wlapi_enable_mac(pi->sh->physhim);
- return;
- }
-
if (!pi->hwpwrctrl_capable) {
if (CHSPEC_IS2G(pi->radio_chanspec)) {
tx_gains.gm_gain = 4;
@@ -2382,26 +3112,6 @@ wlc_lcnphy_get_radio_loft(struct brcms_phy *pi,
*fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
}
-static void
-wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains)
-{
- u16 dac_gain;
-
- dac_gain = read_phy_reg(pi, 0x439) >> 0;
- gains->dac_gain = (dac_gain & 0x380) >> 7;
-
- {
- u16 rfgain0, rfgain1;
-
- rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
- rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
-
- gains->gm_gain = rfgain0 & 0xff;
- gains->pga_gain = (rfgain0 >> 8) & 0xff;
- gains->pad_gain = rfgain1 & 0xff;
- }
-}
-
void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b)
{
struct phytbl_info tab;
@@ -2489,16 +3199,6 @@ void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index)
}
}
-static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx)
-{
-
- mod_phy_reg(pi, 0x44d,
- (0x1 << 1) |
- (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
-
- or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
-}
-
static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi)
{
u32 j;
@@ -2518,67 +3218,6 @@ static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi)
return;
}
-static void
-wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
- u16 trsw,
- u16 ext_lna,
- u16 biq2,
- u16 biq1,
- u16 tia, u16 lna2, u16 lna1)
-{
- u16 gain0_15, gain16_19;
-
- gain16_19 = biq2 & 0xf;
- gain0_15 = ((biq1 & 0xf) << 12) |
- ((tia & 0xf) << 8) |
- ((lna2 & 0x3) << 6) |
- ((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);
- mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-
- if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
- mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
- mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
- } else {
- mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
-
- mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
-
- mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
- }
-
- mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
-
-}
-
-static void
-wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable)
-{
- u16 ebit = enable ? 1 : 0;
-
- mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
-
- mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
-
- if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
- mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
- mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
- mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
- mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
- } else {
- mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
- mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
- mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
- mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
- }
-}
-
void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable)
{
if (!bEnable) {
@@ -2589,9 +3228,9 @@ void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable)
and_phy_reg(pi, 0x44c,
~(u16) ((0x1 << 3) |
- (0x1 << 5) |
- (0x1 << 12) |
- (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+ (0x1 << 5) |
+ (0x1 << 12) |
+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
and_phy_reg(pi, 0x44d,
~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
@@ -2701,7 +3340,8 @@ void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode)
mod_phy_reg((pi), 0x410,
(0x1 << 6) |
(0x1 << 5),
- ((CHSPEC_IS2G(pi->radio_chanspec)) ? (!mode) : 0) <<
+ ((CHSPEC_IS2G(
+ pi->radio_chanspec)) ? (!mode) : 0) <<
6 | (!mode) << 5);
mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
}
@@ -2714,8 +3354,8 @@ wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val,
u8 phy_bw;
u16 num_samps, t, k;
u32 bw;
- fixed theta = 0, rot = 0;
- cs32 tone_samp;
+ s32 theta = 0, rot = 0;
+ struct cordic_iq tone_samp;
u32 data_buf[64];
u16 i_samp, q_samp;
struct phytbl_info tab;
@@ -2737,18 +3377,18 @@ wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val,
k = 1;
do {
bw = phy_bw * 1000 * k;
- num_samps = bw / ABS(f_kHz);
+ num_samps = bw / abs(f_kHz);
k++;
- } while ((num_samps * (u32) (ABS(f_kHz))) != bw);
+ } while ((num_samps * (u32) (abs(f_kHz))) != bw);
} else
num_samps = 2;
- rot = FIXED((f_kHz * 36) / phy_bw) / 100;
+ rot = ((f_kHz * 36) / phy_bw) / 100;
theta = 0;
for (t = 0; t < num_samps; t++) {
- wlc_phy_cordic(theta, &tone_samp);
+ tone_samp = cordic_calc_iq(theta);
theta += rot;
@@ -2802,10 +3442,359 @@ void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi)
wlc_lcnphy_deaf_mode(pi, false);
}
-static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi)
+static void
+wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y)
{
+ u16 di0dq0;
+ u16 x, y, data_rf;
+ int k;
+ switch (cal_type) {
+ case 0:
+ wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
+ break;
+ case 2:
+ di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
+ wlc_lcnphy_set_tx_locc(pi, di0dq0);
+ break;
+ case 3:
+ k = wlc_lcnphy_calc_floor(coeff_x, 0);
+ y = 8 + k;
+ k = wlc_lcnphy_calc_floor(coeff_x, 1);
+ x = 8 - k;
+ data_rf = (x * 16 + y);
+ write_radio_reg(pi, RADIO_2064_REG089, data_rf);
+ k = wlc_lcnphy_calc_floor(coeff_y, 0);
+ y = 8 + k;
+ k = wlc_lcnphy_calc_floor(coeff_y, 1);
+ x = 8 - k;
+ data_rf = (x * 16 + y);
+ write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
+ break;
+ case 4:
+ k = wlc_lcnphy_calc_floor(coeff_x, 0);
+ y = 8 + k;
+ k = wlc_lcnphy_calc_floor(coeff_x, 1);
+ x = 8 - k;
+ data_rf = (x * 16 + y);
+ write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
+ k = wlc_lcnphy_calc_floor(coeff_y, 0);
+ y = 8 + k;
+ k = wlc_lcnphy_calc_floor(coeff_y, 1);
+ x = 8 - k;
+ data_rf = (x * 16 + y);
+ write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
+ break;
+ }
+}
- and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
+static struct lcnphy_unsign16_struct
+wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type)
+{
+ u16 a, b, didq;
+ u8 di0, dq0, ei, eq, fi, fq;
+ struct lcnphy_unsign16_struct cc;
+ cc.re = 0;
+ cc.im = 0;
+ switch (cal_type) {
+ case 0:
+ wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
+ cc.re = a;
+ cc.im = b;
+ break;
+ case 2:
+ didq = wlc_lcnphy_get_tx_locc(pi);
+ di0 = (((didq & 0xff00) << 16) >> 24);
+ dq0 = (((didq & 0x00ff) << 24) >> 24);
+ cc.re = (u16) di0;
+ cc.im = (u16) dq0;
+ break;
+ case 3:
+ wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+ cc.re = (u16) ei;
+ cc.im = (u16) eq;
+ break;
+ case 4:
+ wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+ cc.re = (u16) fi;
+ cc.im = (u16) fq;
+ break;
+ }
+ return cc;
+}
+
+static void
+wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
+ s16 *ptr, int mode)
+{
+ u32 curval1, curval2, stpptr, curptr, strptr, val;
+ u16 sslpnCalibClkEnCtrl, timer;
+ u16 old_sslpnCalibClkEnCtrl;
+ s16 imag, real;
+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+ timer = 0;
+ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+
+ curval1 = R_REG(&pi->regs->psm_corectlsts);
+ ptr[130] = 0;
+ W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
+
+ W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
+ W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
+ udelay(20);
+ curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
+ W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
+
+ write_phy_reg(pi, 0x555, 0x0);
+ write_phy_reg(pi, 0x5a6, 0x5);
+
+ write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
+ write_phy_reg(pi, 0x5cf, 3);
+ write_phy_reg(pi, 0x5a5, 0x3);
+ write_phy_reg(pi, 0x583, 0x0);
+ write_phy_reg(pi, 0x584, 0x0);
+ write_phy_reg(pi, 0x585, 0x0fff);
+ write_phy_reg(pi, 0x586, 0x0000);
+
+ write_phy_reg(pi, 0x580, 0x4501);
+
+ sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+ write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
+ stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
+ curptr = R_REG(&pi->regs->smpl_clct_curptr);
+ do {
+ udelay(10);
+ curptr = R_REG(&pi->regs->smpl_clct_curptr);
+ timer++;
+ } while ((curptr != stpptr) && (timer < 500));
+
+ W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
+ strptr = 0x7E00;
+ W_REG(&pi->regs->tplatewrptr, strptr);
+ while (strptr < 0x8000) {
+ val = R_REG(&pi->regs->tplatewrdata);
+ imag = ((val >> 16) & 0x3ff);
+ real = ((val) & 0x3ff);
+ if (imag > 511)
+ imag -= 1024;
+
+ if (real > 511)
+ real -= 1024;
+
+ if (pi_lcn->lcnphy_iqcal_swp_dis)
+ ptr[(strptr - 0x7E00) / 4] = real;
+ else
+ ptr[(strptr - 0x7E00) / 4] = imag;
+
+ if (clip_detect_algo) {
+ if (imag > thresh || imag < -thresh) {
+ strptr = 0x8000;
+ ptr[130] = 1;
+ }
+ }
+
+ strptr += 4;
+ }
+
+ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+ W_REG(&pi->regs->psm_phy_hdr_param, curval2);
+ W_REG(&pi->regs->psm_corectlsts, curval1);
+}
+
+static void
+wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels,
+ int step_size_lg2)
+{
+ const struct lcnphy_spb_tone *phy_c1;
+ struct lcnphy_spb_tone phy_c2;
+ struct lcnphy_unsign16_struct phy_c3;
+ int phy_c4, phy_c5, k, l, j, phy_c6;
+ u16 phy_c7, phy_c8, phy_c9;
+ s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
+ s16 *ptr, phy_c17;
+ s32 phy_c18, phy_c19;
+ u32 phy_c20, phy_c21;
+ bool phy_c22, phy_c23, phy_c24, phy_c25;
+ u16 phy_c26, phy_c27;
+ u16 phy_c28, phy_c29, phy_c30;
+ u16 phy_c31;
+ u16 *phy_c32;
+ phy_c21 = 0;
+ phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
+ ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+ if (NULL == ptr)
+ return;
+
+ phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
+ if (NULL == phy_c32) {
+ kfree(ptr);
+ return;
+ }
+ phy_c26 = read_phy_reg(pi, 0x6da);
+ phy_c27 = read_phy_reg(pi, 0x6db);
+ phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
+ write_phy_reg(pi, 0x93d, 0xC0);
+
+ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
+ write_phy_reg(pi, 0x6da, 0xffff);
+ or_phy_reg(pi, 0x6db, 0x3);
+
+ wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
+ udelay(500);
+ phy_c28 = read_phy_reg(pi, 0x938);
+ phy_c29 = read_phy_reg(pi, 0x4d7);
+ phy_c30 = read_phy_reg(pi, 0x4d8);
+ or_phy_reg(pi, 0x938, 0x1 << 2);
+ or_phy_reg(pi, 0x4d7, 0x1 << 2);
+ or_phy_reg(pi, 0x4d7, 0x1 << 3);
+ mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
+ or_phy_reg(pi, 0x4d8, 1 << 0);
+ or_phy_reg(pi, 0x4d8, 1 << 1);
+ mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
+ mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
+ phy_c1 = &lcnphy_spb_tone_3750[0];
+ phy_c4 = 32;
+
+ if (num_levels == 0) {
+ if (cal_type != 0)
+ num_levels = 4;
+ else
+ num_levels = 9;
+ }
+ if (step_size_lg2 == 0) {
+ if (cal_type != 0)
+ step_size_lg2 = 3;
+ else
+ step_size_lg2 = 8;
+ }
+
+ phy_c7 = (1 << step_size_lg2);
+ phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
+ phy_c15 = (s16) phy_c3.re;
+ phy_c16 = (s16) phy_c3.im;
+ if (cal_type == 2) {
+ if (phy_c3.re > 127)
+ phy_c15 = phy_c3.re - 256;
+ if (phy_c3.im > 127)
+ phy_c16 = phy_c3.im - 256;
+ }
+ wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+ udelay(20);
+ for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
+ phy_c23 = 1;
+ phy_c22 = 0;
+ switch (cal_type) {
+ case 0:
+ phy_c10 = 511;
+ break;
+ case 2:
+ phy_c10 = 127;
+ break;
+ case 3:
+ phy_c10 = 15;
+ break;
+ case 4:
+ phy_c10 = 15;
+ break;
+ }
+
+ phy_c9 = read_phy_reg(pi, 0x93d);
+ phy_c9 = 2 * phy_c9;
+ phy_c24 = 0;
+ phy_c5 = 7;
+ phy_c25 = 1;
+ while (1) {
+ write_radio_reg(pi, RADIO_2064_REG026,
+ (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
+ udelay(50);
+ phy_c22 = 0;
+ ptr[130] = 0;
+ wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
+ if (ptr[130] == 1)
+ phy_c22 = 1;
+ if (phy_c22)
+ phy_c5 -= 1;
+ if ((phy_c22 != phy_c24) && (!phy_c25))
+ break;
+ if (!phy_c22)
+ phy_c5 += 1;
+ if (phy_c5 <= 0 || phy_c5 >= 7)
+ break;
+ phy_c24 = phy_c22;
+ phy_c25 = 0;
+ }
+
+ if (phy_c5 < 0)
+ phy_c5 = 0;
+ else if (phy_c5 > 7)
+ phy_c5 = 7;
+
+ for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
+ for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
+ phy_c11 = phy_c15 + k;
+ phy_c12 = phy_c16 + l;
+
+ if (phy_c11 < -phy_c10)
+ phy_c11 = -phy_c10;
+ else if (phy_c11 > phy_c10)
+ phy_c11 = phy_c10;
+ if (phy_c12 < -phy_c10)
+ phy_c12 = -phy_c10;
+ else if (phy_c12 > phy_c10)
+ phy_c12 = phy_c10;
+ wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
+ phy_c12);
+ udelay(20);
+ wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
+
+ phy_c18 = 0;
+ phy_c19 = 0;
+ for (j = 0; j < 128; j++) {
+ if (cal_type != 0)
+ phy_c6 = j % phy_c4;
+ else
+ phy_c6 = (2 * j) % phy_c4;
+
+ phy_c2.re = phy_c1[phy_c6].re;
+ phy_c2.im = phy_c1[phy_c6].im;
+ phy_c17 = ptr[j];
+ phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
+ phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
+ }
+
+ phy_c18 = phy_c18 >> 10;
+ phy_c19 = phy_c19 >> 10;
+ phy_c20 = ((phy_c18 * phy_c18) +
+ (phy_c19 * phy_c19));
+
+ if (phy_c23 || phy_c20 < phy_c21) {
+ phy_c21 = phy_c20;
+ phy_c13 = phy_c11;
+ phy_c14 = phy_c12;
+ }
+ phy_c23 = 0;
+ }
+ }
+ phy_c23 = 1;
+ phy_c15 = phy_c13;
+ phy_c16 = phy_c14;
+ phy_c7 = phy_c7 >> 1;
+ wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+ udelay(20);
+ }
+ goto cleanup;
+cleanup:
+ wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
+ wlc_lcnphy_stop_tx_tone(pi);
+ write_phy_reg(pi, 0x6da, phy_c26);
+ write_phy_reg(pi, 0x6db, phy_c27);
+ write_phy_reg(pi, 0x938, phy_c28);
+ write_phy_reg(pi, 0x4d7, phy_c29);
+ write_phy_reg(pi, 0x4d8, phy_c30);
+ write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
+
+ kfree(phy_c32);
+ kfree(ptr);
}
void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b)
@@ -2824,6 +3813,28 @@ void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b)
*b = iqcc[1];
}
+static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi)
+{
+ struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
+
+ wlc_lcnphy_set_cc(pi, 0, 0, 0);
+ wlc_lcnphy_set_cc(pi, 2, 0, 0);
+ wlc_lcnphy_set_cc(pi, 3, 0, 0);
+ wlc_lcnphy_set_cc(pi, 4, 0, 0);
+
+ wlc_lcnphy_a1(pi, 4, 0, 0);
+ wlc_lcnphy_a1(pi, 3, 0, 0);
+ wlc_lcnphy_a1(pi, 2, 3, 2);
+ wlc_lcnphy_a1(pi, 0, 5, 8);
+ wlc_lcnphy_a1(pi, 2, 2, 1);
+ wlc_lcnphy_a1(pi, 0, 4, 3);
+
+ iqcc0 = wlc_lcnphy_get_cc(pi, 0);
+ locc2 = wlc_lcnphy_get_cc(pi, 2);
+ locc3 = wlc_lcnphy_get_cc(pi, 3);
+ locc4 = wlc_lcnphy_get_cc(pi, 4);
+}
+
u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi)
{
struct phytbl_info tab;
@@ -2878,12 +3889,11 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
lcnphy_recal ? LCNPHY_CAL_RECAL :
LCNPHY_CAL_FULL), false);
} else {
-
wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
}
wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
- if ((ABS((s8) fi0) == 15) && (ABS((s8) fq0) == 15)) {
+ if ((abs((s8) fi0) == 15) && (abs((s8) fq0) == 15)) {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
target_gains.gm_gain = 255;
target_gains.pga_gain = 255;
@@ -2905,10 +3915,8 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
LCNPHY_CAL_FULL, false);
} else {
-
wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
}
-
}
wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
@@ -2927,7 +3935,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
wlc_lcnphy_read_table(pi, &tab);
val = (val & 0xfff00000) |
- ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
+ ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
wlc_lcnphy_write_table(pi, &tab);
val = didq;
@@ -2959,13 +3967,10 @@ s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode)
s16 avg = 0;
bool suspend = 0;
- if (NORADIO_ENAB(pi->pubpi))
- return -1;
-
if (mode == 1) {
suspend =
- (0 ==
- (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 ==
+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
@@ -3006,13 +4011,10 @@ u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode)
u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- if (NORADIO_ENAB(pi->pubpi))
- return -1;
-
if (mode == 1) {
suspend =
- (0 ==
- (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 ==
+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
@@ -3063,8 +4065,9 @@ s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode)
{
s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
degree =
- ((degree << 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
- / LCN_TEMPSENSE_DEN;
+ ((degree <<
+ 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
+ / LCN_TEMPSENSE_DEN;
return (s8) degree;
}
@@ -3074,13 +4077,10 @@ s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode)
s32 avg = 0;
bool suspend = 0;
- if (NORADIO_ENAB(pi->pubpi))
- return -1;
-
if (mode == 1) {
suspend =
- (0 ==
- (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 ==
+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
@@ -3093,9 +4093,8 @@ s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode)
else
avg = (s32) vbatsenseval;
- avg =
- (avg * LCN_VBAT_SCALE_NOM +
- (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
+ avg = (avg * LCN_VBAT_SCALE_NOM +
+ (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
if (mode == 1) {
if (!suspend)
@@ -3118,312 +4117,8 @@ static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode)
wlc_lcnphy_toggle_afe_pwdn(pi);
}
-static bool
-wlc_lcnphy_rx_iq_est(struct brcms_phy *pi,
- u16 num_samps,
- u8 wait_time, struct lcnphy_iq_est *iq_est)
-{
- int wait_count = 0;
- bool result = true;
- u8 phybw40;
- phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
- mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
-
- mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
-
- mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
-
- mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
-
- mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
-
- mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
-
- while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
-
- if (wait_count > (10 * 500)) {
- result = false;
- goto cleanup;
- }
- udelay(100);
- wait_count++;
- }
-
- iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
- (u32) read_phy_reg(pi, 0x484);
- iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
- (u32) read_phy_reg(pi, 0x486);
- iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
- (u32) read_phy_reg(pi, 0x488);
-
- cleanup:
- mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
-
- mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
-
- return result;
-}
-
-static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps)
-{
-#define LCNPHY_MIN_RXIQ_PWR 2
- bool result;
- u16 a0_new, b0_new;
- struct lcnphy_iq_est iq_est = { 0, 0, 0 };
- s32 a, b, temp;
- s16 iq_nbits, qq_nbits, arsh, brsh;
- s32 iq;
- u32 ii, qq;
- struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
-
- a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
- b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
- mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
-
- mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
-
- wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
-
- result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
- if (!result)
- goto cleanup;
-
- iq = (s32) iq_est.iq_prod;
- ii = iq_est.i_pwr;
- qq = iq_est.q_pwr;
-
- if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
- result = false;
- goto cleanup;
- }
-
- iq_nbits = wlc_phy_nbits(iq);
- qq_nbits = wlc_phy_nbits(qq);
-
- arsh = 10 - (30 - iq_nbits);
- if (arsh >= 0) {
- a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
- temp = (s32) (ii >> arsh);
- if (temp == 0) {
- return false;
- }
- } else {
- a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
- temp = (s32) (ii << -arsh);
- if (temp == 0) {
- return false;
- }
- }
- a /= temp;
- brsh = qq_nbits - 31 + 20;
- if (brsh >= 0) {
- b = (qq << (31 - qq_nbits));
- temp = (s32) (ii >> brsh);
- if (temp == 0) {
- return false;
- }
- } else {
- b = (qq << (31 - qq_nbits));
- temp = (s32) (ii << -brsh);
- if (temp == 0) {
- return false;
- }
- }
- b /= temp;
- b -= a * a;
- b = (s32) int_sqrt((unsigned long) b);
- b -= (1 << 10);
- a0_new = (u16) (a & 0x3ff);
- b0_new = (u16) (b & 0x3ff);
- cleanup:
-
- wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
-
- mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
-
- mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
-
- pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
- pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
-
- return result;
-}
-
-static bool
-wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
- const struct lcnphy_rx_iqcomp *iqcomp,
- int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
- int tx_gain_idx)
-{
- struct lcnphy_txgains old_gains;
- u16 tx_pwr_ctrl;
- u8 tx_gain_index_old = 0;
- bool result = false, tx_gain_override_old = false;
- u16 i, Core1TxControl_old, RFOverride0_old,
- 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;
- u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
- u16 values_to_save[11];
- s16 *ptr;
- struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
-
- ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
- if (NULL == ptr) {
- return false;
- }
- if (module == 2) {
- while (iqcomp_sz--) {
- if (iqcomp[iqcomp_sz].chan ==
- CHSPEC_CHANNEL(pi->radio_chanspec)) {
-
- wlc_lcnphy_set_rx_iq_comp(pi,
- (u16)
- iqcomp[iqcomp_sz].a,
- (u16)
- iqcomp[iqcomp_sz].b);
- result = true;
- break;
- }
- }
- goto cal_done;
- }
-
- if (module == 1) {
-
- 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);
-
- 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);
-
- 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);
-
- 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);
-
- received_power =
- wlc_lcnphy_measure_digital_power(pi, 2000);
- if (received_power < rx_pwr_threshold)
- break;
- }
- result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
-
- wlc_lcnphy_stop_tx_tone(pi);
-
- 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);
-
- 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]);
- }
-
- 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);
- }
-
- cal_done:
- kfree(ptr);
- return result;
-}
-
static void wlc_lcnphy_temp_adj(struct brcms_phy *pi)
{
- if (NORADIO_ENAB(pi->pubpi))
- return;
}
static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi)
@@ -3433,7 +4128,7 @@ static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi)
u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_deaf_mode(pi, true);
@@ -3463,24 +4158,21 @@ static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi)
s32 tssi, pwr, maxtargetpwr, mintargetpwr;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
pi->phy_lastcal = pi->sh->now;
pi->phy_forcecal = false;
full_cal =
- (pi_lcn->lcnphy_full_cal_channel !=
- CHSPEC_CHANNEL(pi->radio_chanspec));
+ (pi_lcn->lcnphy_full_cal_channel !=
+ CHSPEC_CHANNEL(pi->radio_chanspec));
pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
index = pi_lcn->lcnphy_current_index;
suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
if (!suspend) {
-
wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
wlapi_suspend_mac_and_wait(pi->sh->physhim);
}
+
wlc_lcnphy_deaf_mode(pi, true);
wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
@@ -3531,7 +4223,6 @@ void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode)
switch (mode) {
case PHY_PERICAL_CHAN:
-
break;
case PHY_FULLCAL:
wlc_lcnphy_periodic_cal(pi);
@@ -3558,7 +4249,7 @@ void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode)
case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
wlc_lcnphy_tx_power_adjustment(
- (struct brcms_phy_pub *) pi);
+ (struct brcms_phy_pub *) pi);
break;
}
}
@@ -3571,7 +4262,7 @@ void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr)
if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
(status & (0x1 << 15))) {
*ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
- >> 0) >> 1);
+ >> 0) >> 1);
if (wlc_phy_tpc_isenabled_lcnphy(pi))
cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
@@ -3591,59 +4282,6 @@ void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi)
}
-static void
-wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, chanspec_t chanspec)
-{
- u8 channel = CHSPEC_CHANNEL(chanspec);
- struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
-
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
- if (channel == 14) {
- mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
-
- } else {
- mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
-
- }
- pi_lcn->lcnphy_bandedge_corr = 2;
- if (channel == 1)
- pi_lcn->lcnphy_bandedge_corr = 4;
-
- if (channel == 1 || channel == 2 || channel == 3 ||
- channel == 4 || channel == 9 ||
- channel == 10 || channel == 11 || channel == 12) {
- si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
- si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
- si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
-
- si_pmu_pllupd(pi->sh->sih);
- write_phy_reg(pi, 0x942, 0);
- wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
- pi_lcn->lcnphy_spurmod = 0;
- mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
-
- write_phy_reg(pi, 0x425, 0x5907);
- } else {
- si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
- si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
- si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
-
- si_pmu_pllupd(pi->sh->sih);
- write_phy_reg(pi, 0x942, 0);
- wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
-
- pi_lcn->lcnphy_spurmod = 0;
- mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
-
- write_phy_reg(pi, 0x425, 0x590a);
- }
-
- or_phy_reg(pi, 0x44a, 0x44);
- write_phy_reg(pi, 0x44a, 0x80);
-}
-
void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi)
{
s8 index;
@@ -3651,570 +4289,21 @@ void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi)
struct brcms_phy *pi = (struct brcms_phy *) ppi;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
- if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && SAVE_txpwrctrl) {
+ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
+ SAVE_txpwrctrl) {
index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
index2 = (u16) (index * 2);
mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
- pi_lcn->lcnphy_current_index = (s8)
- ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
- }
-}
-
-static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b)
-{
- mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
-
- mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
-
- mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
-
- mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
-
- mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
-
- mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
-
-}
-
-void wlc_phy_init_lcnphy(struct brcms_phy *pi)
-{
- u8 phybw40;
- struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
- pi_lcn->lcnphy_cal_counter = 0;
- pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
-
- or_phy_reg(pi, 0x44a, 0x80);
- and_phy_reg(pi, 0x44a, 0x7f);
-
- wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
-
- write_phy_reg(pi, 0x60a, 160);
-
- write_phy_reg(pi, 0x46a, 25);
-
- wlc_lcnphy_baseband_init(pi);
-
- wlc_lcnphy_radio_init(pi);
-
- if (CHSPEC_IS2G(pi->radio_chanspec))
- wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi);
-
- wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
-
- si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
-
- si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
-
- if ((pi->sh->boardflags & BFL_FEM)
- && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
- wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
-
- wlc_lcnphy_agc_temp_init(pi);
-
- wlc_lcnphy_temp_adj(pi);
-
- mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
-
- udelay(100);
- mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
-
- wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
- pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
- wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
-}
-
-static void
-wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save)
-{
- u16 vmid;
- int i;
- for (i = 0; i < 20; i++) {
- values_to_save[i] =
- read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
- }
-
- mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
- mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
-
- mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
- mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
-
- mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
-
- mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
-
- if (LCNREV_IS(pi->pubpi.phy_rev, 2))
- and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
- else
- and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
- or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
-
- or_radio_reg(pi, RADIO_2064_REG036, 0x01);
- or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
- udelay(20);
-
- if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
- if (CHSPEC_IS5G(pi->radio_chanspec))
- mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
- else
- or_radio_reg(pi, RADIO_2064_REG03A, 1);
- } else {
- if (CHSPEC_IS5G(pi->radio_chanspec))
- mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
- else
- or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
- }
-
- udelay(20);
-
- write_radio_reg(pi, RADIO_2064_REG025, 0xF);
- if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
- if (CHSPEC_IS5G(pi->radio_chanspec))
- mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
- else
- mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
- } else {
- if (CHSPEC_IS5G(pi->radio_chanspec))
- mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
- else
- mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
- }
-
- udelay(20);
-
- write_radio_reg(pi, RADIO_2064_REG005, 0x8);
- or_radio_reg(pi, RADIO_2064_REG112, 0x80);
- udelay(20);
-
- or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
- or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
- udelay(20);
-
- or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
- or_radio_reg(pi, RADIO_2064_REG113, 0x10);
- udelay(20);
-
- write_radio_reg(pi, RADIO_2064_REG007, 0x1);
- udelay(20);
-
- vmid = 0x2A6;
- mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
- write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
- or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
- udelay(20);
-
- or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
- udelay(20);
- write_radio_reg(pi, RADIO_2064_REG012, 0x02);
- or_radio_reg(pi, RADIO_2064_REG112, 0x06);
- write_radio_reg(pi, RADIO_2064_REG036, 0x11);
- write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
- write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
- write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
- write_radio_reg(pi, RADIO_2064_REG092, 0x15);
-}
-
-static void
-wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
- s16 *ptr, int mode)
-{
- u32 curval1, curval2, stpptr, curptr, strptr, val;
- u16 sslpnCalibClkEnCtrl, timer;
- u16 old_sslpnCalibClkEnCtrl;
- s16 imag, real;
- struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
-
- timer = 0;
- old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-
- curval1 = R_REG(&pi->regs->psm_corectlsts);
- ptr[130] = 0;
- W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
-
- W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
- W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
- udelay(20);
- curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
- W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
-
- write_phy_reg(pi, 0x555, 0x0);
- write_phy_reg(pi, 0x5a6, 0x5);
-
- write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
- write_phy_reg(pi, 0x5cf, 3);
- write_phy_reg(pi, 0x5a5, 0x3);
- write_phy_reg(pi, 0x583, 0x0);
- write_phy_reg(pi, 0x584, 0x0);
- write_phy_reg(pi, 0x585, 0x0fff);
- write_phy_reg(pi, 0x586, 0x0000);
-
- write_phy_reg(pi, 0x580, 0x4501);
-
- sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
- write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
- stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
- curptr = R_REG(&pi->regs->smpl_clct_curptr);
- do {
- udelay(10);
- curptr = R_REG(&pi->regs->smpl_clct_curptr);
- timer++;
- } while ((curptr != stpptr) && (timer < 500));
-
- W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
- strptr = 0x7E00;
- W_REG(&pi->regs->tplatewrptr, strptr);
- while (strptr < 0x8000) {
- val = R_REG(&pi->regs->tplatewrdata);
- imag = ((val >> 16) & 0x3ff);
- real = ((val) & 0x3ff);
- if (imag > 511) {
- imag -= 1024;
- }
- if (real > 511) {
- real -= 1024;
- }
- if (pi_lcn->lcnphy_iqcal_swp_dis)
- ptr[(strptr - 0x7E00) / 4] = real;
- else
- ptr[(strptr - 0x7E00) / 4] = imag;
- if (clip_detect_algo) {
- if (imag > thresh || imag < -thresh) {
- strptr = 0x8000;
- ptr[130] = 1;
- }
- }
- strptr += 4;
- }
-
- write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
- W_REG(&pi->regs->psm_phy_hdr_param, curval2);
- W_REG(&pi->regs->psm_corectlsts, curval1);
-}
-
-static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi)
-{
- struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
-
- wlc_lcnphy_set_cc(pi, 0, 0, 0);
- wlc_lcnphy_set_cc(pi, 2, 0, 0);
- wlc_lcnphy_set_cc(pi, 3, 0, 0);
- wlc_lcnphy_set_cc(pi, 4, 0, 0);
-
- wlc_lcnphy_a1(pi, 4, 0, 0);
- wlc_lcnphy_a1(pi, 3, 0, 0);
- wlc_lcnphy_a1(pi, 2, 3, 2);
- wlc_lcnphy_a1(pi, 0, 5, 8);
- wlc_lcnphy_a1(pi, 2, 2, 1);
- wlc_lcnphy_a1(pi, 0, 4, 3);
-
- iqcc0 = wlc_lcnphy_get_cc(pi, 0);
- locc2 = wlc_lcnphy_get_cc(pi, 2);
- locc3 = wlc_lcnphy_get_cc(pi, 3);
- locc4 = wlc_lcnphy_get_cc(pi, 4);
-}
-
-static void
-wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y)
-{
- u16 di0dq0;
- u16 x, y, data_rf;
- int k;
- switch (cal_type) {
- case 0:
- wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
- break;
- case 2:
- di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
- wlc_lcnphy_set_tx_locc(pi, di0dq0);
- break;
- case 3:
- k = wlc_lcnphy_calc_floor(coeff_x, 0);
- y = 8 + k;
- k = wlc_lcnphy_calc_floor(coeff_x, 1);
- x = 8 - k;
- data_rf = (x * 16 + y);
- write_radio_reg(pi, RADIO_2064_REG089, data_rf);
- k = wlc_lcnphy_calc_floor(coeff_y, 0);
- y = 8 + k;
- k = wlc_lcnphy_calc_floor(coeff_y, 1);
- x = 8 - k;
- data_rf = (x * 16 + y);
- write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
- break;
- case 4:
- k = wlc_lcnphy_calc_floor(coeff_x, 0);
- y = 8 + k;
- k = wlc_lcnphy_calc_floor(coeff_x, 1);
- x = 8 - k;
- data_rf = (x * 16 + y);
- write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
- k = wlc_lcnphy_calc_floor(coeff_y, 0);
- y = 8 + k;
- k = wlc_lcnphy_calc_floor(coeff_y, 1);
- x = 8 - k;
- data_rf = (x * 16 + y);
- write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
- break;
- }
-}
-
-static struct lcnphy_unsign16_struct
-wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type)
-{
- u16 a, b, didq;
- u8 di0, dq0, ei, eq, fi, fq;
- struct lcnphy_unsign16_struct cc;
- cc.re = 0;
- cc.im = 0;
- switch (cal_type) {
- case 0:
- wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
- cc.re = a;
- cc.im = b;
- break;
- case 2:
- didq = wlc_lcnphy_get_tx_locc(pi);
- di0 = (((didq & 0xff00) << 16) >> 24);
- dq0 = (((didq & 0x00ff) << 24) >> 24);
- cc.re = (u16) di0;
- cc.im = (u16) dq0;
- break;
- case 3:
- wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
- cc.re = (u16) ei;
- cc.im = (u16) eq;
- break;
- case 4:
- wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
- cc.re = (u16) fi;
- cc.im = (u16) fq;
- break;
- }
- return cc;
-}
-
-static void
-wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels,
- int step_size_lg2)
-{
- const struct lcnphy_spb_tone *phy_c1;
- struct lcnphy_spb_tone phy_c2;
- struct lcnphy_unsign16_struct phy_c3;
- int phy_c4, phy_c5, k, l, j, phy_c6;
- u16 phy_c7, phy_c8, phy_c9;
- s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
- s16 *ptr, phy_c17;
- s32 phy_c18, phy_c19;
- u32 phy_c20, phy_c21;
- bool phy_c22, phy_c23, phy_c24, phy_c25;
- u16 phy_c26, phy_c27;
- u16 phy_c28, phy_c29, phy_c30;
- u16 phy_c31;
- u16 *phy_c32;
- phy_c21 = 0;
- phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
- ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
- if (NULL == ptr) {
- return;
- }
-
- phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
- if (NULL == phy_c32) {
- kfree(ptr);
- return;
- }
- phy_c26 = read_phy_reg(pi, 0x6da);
- phy_c27 = read_phy_reg(pi, 0x6db);
- phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
- write_phy_reg(pi, 0x93d, 0xC0);
-
- wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
- write_phy_reg(pi, 0x6da, 0xffff);
- or_phy_reg(pi, 0x6db, 0x3);
-
- wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
- udelay(500);
- phy_c28 = read_phy_reg(pi, 0x938);
- phy_c29 = read_phy_reg(pi, 0x4d7);
- phy_c30 = read_phy_reg(pi, 0x4d8);
- or_phy_reg(pi, 0x938, 0x1 << 2);
- or_phy_reg(pi, 0x4d7, 0x1 << 2);
- or_phy_reg(pi, 0x4d7, 0x1 << 3);
- mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
- or_phy_reg(pi, 0x4d8, 1 << 0);
- or_phy_reg(pi, 0x4d8, 1 << 1);
- mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
- mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
- phy_c1 = &lcnphy_spb_tone_3750[0];
- phy_c4 = 32;
-
- if (num_levels == 0) {
- if (cal_type != 0) {
- num_levels = 4;
- } else {
- num_levels = 9;
- }
- }
- if (step_size_lg2 == 0) {
- if (cal_type != 0) {
- step_size_lg2 = 3;
- } else {
- step_size_lg2 = 8;
- }
- }
-
- phy_c7 = (1 << step_size_lg2);
- phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
- phy_c15 = (s16) phy_c3.re;
- phy_c16 = (s16) phy_c3.im;
- if (cal_type == 2) {
- if (phy_c3.re > 127)
- phy_c15 = phy_c3.re - 256;
- if (phy_c3.im > 127)
- phy_c16 = phy_c3.im - 256;
- }
- wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
- udelay(20);
- for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
- phy_c23 = 1;
- phy_c22 = 0;
- switch (cal_type) {
- case 0:
- phy_c10 = 511;
- break;
- case 2:
- phy_c10 = 127;
- break;
- case 3:
- phy_c10 = 15;
- break;
- case 4:
- phy_c10 = 15;
- break;
- }
-
- phy_c9 = read_phy_reg(pi, 0x93d);
- phy_c9 = 2 * phy_c9;
- phy_c24 = 0;
- phy_c5 = 7;
- phy_c25 = 1;
- while (1) {
- write_radio_reg(pi, RADIO_2064_REG026,
- (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
- udelay(50);
- phy_c22 = 0;
- ptr[130] = 0;
- wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
- if (ptr[130] == 1)
- phy_c22 = 1;
- if (phy_c22)
- phy_c5 -= 1;
- if ((phy_c22 != phy_c24) && (!phy_c25))
- break;
- if (!phy_c22)
- phy_c5 += 1;
- if (phy_c5 <= 0 || phy_c5 >= 7)
- break;
- phy_c24 = phy_c22;
- phy_c25 = 0;
- }
-
- if (phy_c5 < 0)
- phy_c5 = 0;
- else if (phy_c5 > 7)
- phy_c5 = 7;
-
- for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
- for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
- phy_c11 = phy_c15 + k;
- phy_c12 = phy_c16 + l;
-
- if (phy_c11 < -phy_c10)
- phy_c11 = -phy_c10;
- else if (phy_c11 > phy_c10)
- phy_c11 = phy_c10;
- if (phy_c12 < -phy_c10)
- phy_c12 = -phy_c10;
- else if (phy_c12 > phy_c10)
- phy_c12 = phy_c10;
- wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
- phy_c12);
- udelay(20);
- wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
-
- phy_c18 = 0;
- phy_c19 = 0;
- for (j = 0; j < 128; j++) {
- if (cal_type != 0) {
- phy_c6 = j % phy_c4;
- } else {
- phy_c6 = (2 * j) % phy_c4;
- }
- phy_c2.re = phy_c1[phy_c6].re;
- phy_c2.im = phy_c1[phy_c6].im;
- phy_c17 = ptr[j];
- phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
- phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
- }
-
- phy_c18 = phy_c18 >> 10;
- phy_c19 = phy_c19 >> 10;
- phy_c20 =
- ((phy_c18 * phy_c18) + (phy_c19 * phy_c19));
-
- if (phy_c23 || phy_c20 < phy_c21) {
- phy_c21 = phy_c20;
- phy_c13 = phy_c11;
- phy_c14 = phy_c12;
- }
- phy_c23 = 0;
- }
- }
- phy_c23 = 1;
- phy_c15 = phy_c13;
- phy_c16 = phy_c14;
- phy_c7 = phy_c7 >> 1;
- wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
- udelay(20);
- }
- goto cleanup;
- cleanup:
- wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
- wlc_lcnphy_stop_tx_tone(pi);
- write_phy_reg(pi, 0x6da, phy_c26);
- write_phy_reg(pi, 0x6db, phy_c27);
- write_phy_reg(pi, 0x938, phy_c28);
- write_phy_reg(pi, 0x4d7, phy_c29);
- write_phy_reg(pi, 0x4d8, phy_c30);
- write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
-
- kfree(phy_c32);
- kfree(ptr);
-}
-
-static void
-wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save)
-{
- int i;
-
- and_phy_reg(pi, 0x44c, 0x0 >> 11);
-
- and_phy_reg(pi, 0x43b, 0xC);
-
- for (i = 0; i < 20; i++) {
- write_radio_reg(pi, iqlo_loopback_rf_regs[i],
- values_to_save[i]);
+ pi_lcn->lcnphy_current_index =
+ (s8)((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
}
}
static void
wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
- const struct lcnphy_tx_gain_tbl_entry *gain_table) {
+ const struct lcnphy_tx_gain_tbl_entry *gain_table)
+{
u32 j;
struct phytbl_info tab;
u32 val;
@@ -4297,6 +4386,172 @@ static void wlc_lcnphy_load_rfpower(struct brcms_phy *pi)
}
}
+static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi)
+{
+ or_phy_reg(pi, 0x805, 0x1);
+
+ mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
+
+ mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
+
+ write_phy_reg(pi, 0x414, 0x1e10);
+ write_phy_reg(pi, 0x415, 0x0640);
+
+ mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
+
+ or_phy_reg(pi, 0x44a, 0x44);
+ write_phy_reg(pi, 0x44a, 0x80);
+ mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
+
+ mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
+
+ if (!(pi->sh->boardrev < 0x1204))
+ mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
+
+ write_phy_reg(pi, 0x7d6, 0x0902);
+ mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
+
+ mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
+
+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+ mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
+
+ mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
+
+ mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
+
+ mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
+
+ mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
+
+ mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
+ mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
+ mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
+ mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
+ mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
+
+ mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
+
+ wlc_lcnphy_clear_tx_power_offsets(pi);
+ mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
+
+ }
+}
+
+static void wlc_lcnphy_rcal(struct brcms_phy *pi)
+{
+ u8 rcal_value;
+
+ and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+ or_radio_reg(pi, RADIO_2064_REG004, 0x40);
+ or_radio_reg(pi, RADIO_2064_REG120, 0x10);
+
+ or_radio_reg(pi, RADIO_2064_REG078, 0x80);
+ or_radio_reg(pi, RADIO_2064_REG129, 0x02);
+
+ or_radio_reg(pi, RADIO_2064_REG057, 0x01);
+
+ or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
+ mdelay(5);
+ SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
+
+ if (wlc_radio_2064_rcal_done(pi)) {
+ rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
+ rcal_value = rcal_value & 0x1f;
+ }
+
+ and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+ and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
+}
+
+static void wlc_lcnphy_rc_cal(struct brcms_phy *pi)
+{
+ u8 dflt_rc_cal_val;
+ u16 flt_val;
+
+ dflt_rc_cal_val = 7;
+ if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+ dflt_rc_cal_val = 11;
+ flt_val =
+ (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
+ (dflt_rc_cal_val);
+ write_phy_reg(pi, 0x933, flt_val);
+ write_phy_reg(pi, 0x934, flt_val);
+ write_phy_reg(pi, 0x935, flt_val);
+ write_phy_reg(pi, 0x936, flt_val);
+ write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
+
+ return;
+}
+
+static void wlc_radio_2064_init(struct brcms_phy *pi)
+{
+ u32 i;
+ const struct lcnphy_radio_regs *lcnphyregs = NULL;
+
+ lcnphyregs = lcnphy_radio_regs_2064;
+
+ for (i = 0; lcnphyregs[i].address != 0xffff; i++)
+ if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
+ write_radio_reg(pi,
+ ((lcnphyregs[i].address & 0x3fff) |
+ RADIO_DEFAULT_CORE),
+ (u16) lcnphyregs[i].init_a);
+ else if (lcnphyregs[i].do_init_g)
+ write_radio_reg(pi,
+ ((lcnphyregs[i].address & 0x3fff) |
+ RADIO_DEFAULT_CORE),
+ (u16) lcnphyregs[i].init_g);
+
+ write_radio_reg(pi, RADIO_2064_REG032, 0x62);
+ write_radio_reg(pi, RADIO_2064_REG033, 0x19);
+
+ write_radio_reg(pi, RADIO_2064_REG090, 0x10);
+
+ write_radio_reg(pi, RADIO_2064_REG010, 0x00);
+
+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+
+ write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
+ write_radio_reg(pi, RADIO_2064_REG061, 0x72);
+ write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
+ }
+
+ write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
+ write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
+
+ mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
+
+ mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
+
+ mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
+
+ mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
+
+ mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
+
+ write_phy_reg(pi, 0x4ea, 0x4688);
+
+ mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
+
+ mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
+
+ mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
+
+ wlc_lcnphy_set_tx_locc(pi, 0);
+
+ wlc_lcnphy_rcal(pi);
+
+ wlc_lcnphy_rc_cal(pi);
+}
+
+static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
+{
+ wlc_radio_2064_init(pi);
+}
+
static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
{
uint idx;
@@ -4306,9 +4561,8 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
phybw40 = CHSPEC_IS40(pi->radio_chanspec);
- for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) {
+ for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++)
wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
- }
if (pi->sh->boardflags & BFL_FEM_BT) {
tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
@@ -4339,39 +4593,35 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if (pi->sh->boardflags & BFL_FEM)
- wlc_lcnphy_load_tx_gain_table(pi,
- dot11lcnphy_2GHz_extPA_gaintable_rev0);
+ wlc_lcnphy_load_tx_gain_table(
+ pi,
+ dot11lcnphy_2GHz_extPA_gaintable_rev0);
else
- wlc_lcnphy_load_tx_gain_table(pi,
- dot11lcnphy_2GHz_gaintable_rev0);
+ wlc_lcnphy_load_tx_gain_table(
+ pi,
+ dot11lcnphy_2GHz_gaintable_rev0);
}
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+ const struct phytbl_info *tb;
+ int l;
+
if (CHSPEC_IS2G(pi->radio_chanspec)) {
- for (idx = 0;
- idx < dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
- idx++)
- if (pi->sh->boardflags & BFL_EXTLNA)
- wlc_lcnphy_write_table(pi,
- &dot11lcnphytbl_rx_gain_info_extlna_2G_rev2
- [idx]);
- else
- wlc_lcnphy_write_table(pi,
- &dot11lcnphytbl_rx_gain_info_2G_rev2
- [idx]);
+ l = dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
+ if (pi->sh->boardflags & BFL_EXTLNA)
+ tb = dot11lcnphytbl_rx_gain_info_extlna_2G_rev2;
+ else
+ tb = dot11lcnphytbl_rx_gain_info_2G_rev2;
} else {
- for (idx = 0;
- idx < dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
- idx++)
- if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
- wlc_lcnphy_write_table(pi,
- &dot11lcnphytbl_rx_gain_info_extlna_5G_rev2
- [idx]);
- else
- wlc_lcnphy_write_table(pi,
- &dot11lcnphytbl_rx_gain_info_5G_rev2
- [idx]);
+ l = dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
+ if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
+ tb = dot11lcnphytbl_rx_gain_info_extlna_5G_rev2;
+ else
+ tb = dot11lcnphytbl_rx_gain_info_5G_rev2;
}
+
+ for (idx = 0; idx < l; idx++)
+ wlc_lcnphy_write_table(pi, &tb[idx]);
}
if ((pi->sh->boardflags & BFL_FEM)
@@ -4379,11 +4629,13 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
else if (pi->sh->boardflags & BFL_FEM_BT) {
if (pi->sh->boardrev < 0x1250)
- wlc_lcnphy_write_table(pi,
- &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
+ wlc_lcnphy_write_table(
+ pi,
+ &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
else
- wlc_lcnphy_write_table(pi,
- &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
+ wlc_lcnphy_write_table(
+ pi,
+ &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
} else
wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
@@ -4420,9 +4672,8 @@ static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi)
if (0) {
afectrl1 = 0;
afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
- (pi_lcn->lcnphy_rssi_vc << 4) | (pi_lcn->
- lcnphy_rssi_gs
- << 10));
+ (pi_lcn->lcnphy_rssi_vc << 4) |
+ (pi_lcn->lcnphy_rssi_gs << 10));
write_phy_reg(pi, 0x43e, afectrl1);
}
@@ -4443,7 +4694,6 @@ static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi)
{
if (CHSPEC_IS5G(pi->radio_chanspec)) {
mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
-
mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
}
}
@@ -4455,9 +4705,6 @@ static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi)
u32 tableBuffer[2];
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
temp = (s16) read_phy_reg(pi, 0x4df);
pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
@@ -4484,18 +4731,15 @@ static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi)
tableBuffer[1] -= 128;
pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
- temp = (s16) (read_phy_reg(pi, 0x434)
- & (0xff << 0));
+ temp = (s16) (read_phy_reg(pi, 0x434) & (0xff << 0));
if (temp > 127)
temp -= 256;
pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
- pi_lcn->lcnphy_Med_Low_Gain_db = (read_phy_reg(pi, 0x424)
- & (0xff << 8))
- >> 8;
- pi_lcn->lcnphy_Very_Low_Gain_db = (read_phy_reg(pi, 0x425)
- & (0xff << 0))
- >> 0;
+ pi_lcn->lcnphy_Med_Low_Gain_db =
+ (read_phy_reg(pi, 0x424) & (0xff << 8)) >> 8;
+ pi_lcn->lcnphy_Very_Low_Gain_db =
+ (read_phy_reg(pi, 0x425) & (0xff << 0)) >> 0;
tab.tbl_ptr = tableBuffer;
tab.tbl_len = 2;
@@ -4509,61 +4753,6 @@ static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi)
}
-static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi)
-{
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
- or_phy_reg(pi, 0x805, 0x1);
-
- mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
-
- mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
-
- write_phy_reg(pi, 0x414, 0x1e10);
- write_phy_reg(pi, 0x415, 0x0640);
-
- mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
-
- or_phy_reg(pi, 0x44a, 0x44);
- write_phy_reg(pi, 0x44a, 0x80);
- mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
-
- mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
-
- if (!(pi->sh->boardrev < 0x1204))
- mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
-
- write_phy_reg(pi, 0x7d6, 0x0902);
- mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
-
- mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
-
- if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
- mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
-
- mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
-
- mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
-
- mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
-
- mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
-
- mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
- mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
- mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
- mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
- mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
-
- mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
-
- wlc_lcnphy_clear_tx_power_offsets(pi);
- mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
-
- }
-}
-
static void wlc_lcnphy_baseband_init(struct brcms_phy *pi)
{
@@ -4574,127 +4763,53 @@ static void wlc_lcnphy_baseband_init(struct brcms_phy *pi)
wlc_lcnphy_bu_tweaks(pi);
}
-static void wlc_radio_2064_init(struct brcms_phy *pi)
+void wlc_phy_init_lcnphy(struct brcms_phy *pi)
{
- u32 i;
- struct lcnphy_radio_regs *lcnphyregs = NULL;
-
- lcnphyregs = lcnphy_radio_regs_2064;
-
- for (i = 0; lcnphyregs[i].address != 0xffff; i++)
- if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
- write_radio_reg(pi,
- ((lcnphyregs[i].address & 0x3fff) |
- RADIO_DEFAULT_CORE),
- (u16) lcnphyregs[i].init_a);
- else if (lcnphyregs[i].do_init_g)
- write_radio_reg(pi,
- ((lcnphyregs[i].address & 0x3fff) |
- RADIO_DEFAULT_CORE),
- (u16) lcnphyregs[i].init_g);
-
- write_radio_reg(pi, RADIO_2064_REG032, 0x62);
- write_radio_reg(pi, RADIO_2064_REG033, 0x19);
-
- write_radio_reg(pi, RADIO_2064_REG090, 0x10);
-
- write_radio_reg(pi, RADIO_2064_REG010, 0x00);
-
- if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
-
- write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
- write_radio_reg(pi, RADIO_2064_REG061, 0x72);
- write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
- }
-
- write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
- write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
-
- mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
-
- mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
-
- mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
-
- mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
-
- mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
-
- write_phy_reg(pi, 0x4ea, 0x4688);
-
- mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
-
- mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
-
- mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
-
- wlc_lcnphy_set_tx_locc(pi, 0);
-
- wlc_lcnphy_rcal(pi);
+ u8 phybw40;
+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+ phybw40 = CHSPEC_IS40(pi->radio_chanspec);
- wlc_lcnphy_rc_cal(pi);
-}
+ pi_lcn->lcnphy_cal_counter = 0;
+ pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
-static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
-{
- if (NORADIO_ENAB(pi->pubpi))
- return;
+ or_phy_reg(pi, 0x44a, 0x80);
+ and_phy_reg(pi, 0x44a, 0x7f);
- wlc_radio_2064_init(pi);
-}
+ wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
-static void wlc_lcnphy_rcal(struct brcms_phy *pi)
-{
- u8 rcal_value;
+ write_phy_reg(pi, 0x60a, 160);
- if (NORADIO_ENAB(pi->pubpi))
- return;
+ write_phy_reg(pi, 0x46a, 25);
- and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+ wlc_lcnphy_baseband_init(pi);
- or_radio_reg(pi, RADIO_2064_REG004, 0x40);
- or_radio_reg(pi, RADIO_2064_REG120, 0x10);
+ wlc_lcnphy_radio_init(pi);
- or_radio_reg(pi, RADIO_2064_REG078, 0x80);
- or_radio_reg(pi, RADIO_2064_REG129, 0x02);
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi);
- or_radio_reg(pi, RADIO_2064_REG057, 0x01);
+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
- or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
- mdelay(5);
- SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
+ si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
- if (wlc_radio_2064_rcal_done(pi)) {
- rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
- rcal_value = rcal_value & 0x1f;
- }
+ si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
- and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+ if ((pi->sh->boardflags & BFL_FEM)
+ && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+ wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
- and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
-}
+ wlc_lcnphy_agc_temp_init(pi);
-static void wlc_lcnphy_rc_cal(struct brcms_phy *pi)
-{
- u8 dflt_rc_cal_val;
- u16 flt_val;
+ wlc_lcnphy_temp_adj(pi);
- if (NORADIO_ENAB(pi->pubpi))
- return;
+ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
- dflt_rc_cal_val = 7;
- if (LCNREV_IS(pi->pubpi.phy_rev, 1))
- dflt_rc_cal_val = 11;
- flt_val =
- (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
- (dflt_rc_cal_val);
- write_phy_reg(pi, 0x933, flt_val);
- write_phy_reg(pi, 0x934, flt_val);
- write_phy_reg(pi, 0x935, flt_val);
- write_phy_reg(pi, 0x936, flt_val);
- write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
+ udelay(100);
+ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
- return;
+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
+ pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
+ wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
}
static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
@@ -4702,39 +4817,38 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
s8 txpwr = 0;
int i;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+ struct phy_shim_info *shim = pi->sh->physhim;
if (CHSPEC_IS2G(pi->radio_chanspec)) {
u16 cckpo = 0;
u32 offset_ofdm, offset_mcs;
pi_lcn->lcnphy_tr_isolation_mid =
- (u8) PHY_GETINTVAR(pi, "triso2g");
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TRISO2G);
pi_lcn->lcnphy_rx_power_offset =
- (u8) PHY_GETINTVAR(pi, "rxpo2g");
-
- pi->txpa_2g[0] = (s16) PHY_GETINTVAR(pi, "pa0b0");
- pi->txpa_2g[1] = (s16) PHY_GETINTVAR(pi, "pa0b1");
- pi->txpa_2g[2] = (s16) PHY_GETINTVAR(pi, "pa0b2");
-
- pi_lcn->lcnphy_rssi_vf = (u8) PHY_GETINTVAR(pi, "rssismf2g");
- pi_lcn->lcnphy_rssi_vc = (u8) PHY_GETINTVAR(pi, "rssismc2g");
- pi_lcn->lcnphy_rssi_gs = (u8) PHY_GETINTVAR(pi, "rssisav2g");
-
- {
- pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
- pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
- pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
-
- pi_lcn->lcnphy_rssi_vf_hightemp =
- pi_lcn->lcnphy_rssi_vf;
- pi_lcn->lcnphy_rssi_vc_hightemp =
- pi_lcn->lcnphy_rssi_vc;
- pi_lcn->lcnphy_rssi_gs_hightemp =
- pi_lcn->lcnphy_rssi_gs;
- }
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RXPO2G);
+
+ pi->txpa_2g[0] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B0);
+ pi->txpa_2g[1] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B1);
+ pi->txpa_2g[2] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B2);
- txpwr = (s8) PHY_GETINTVAR(pi, "maxp2ga0");
+ pi_lcn->lcnphy_rssi_vf =
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMF2G);
+ pi_lcn->lcnphy_rssi_vc =
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMC2G);
+ pi_lcn->lcnphy_rssi_gs =
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISAV2G);
+
+ pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
+ pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
+ pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
+
+ pi_lcn->lcnphy_rssi_vf_hightemp = pi_lcn->lcnphy_rssi_vf;
+ pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc;
+ pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs;
+
+ txpwr = (s8)wlapi_getintvar(shim, BRCMS_SROM_MAXP2GA0);
pi->tx_srom_max_2g = txpwr;
for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
@@ -4742,79 +4856,72 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
}
- cckpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
+ cckpo = (u16)wlapi_getintvar(shim, BRCMS_SROM_CCK2GPO);
+ offset_ofdm = (u32)wlapi_getintvar(shim, BRCMS_SROM_OFDM2GPO);
if (cckpo) {
uint max_pwr_chan = txpwr;
for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
- pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
- ((cckpo & 0xf) * 2);
+ pi->tx_srom_max_rate_2g[i] =
+ max_pwr_chan - ((cckpo & 0xf) * 2);
cckpo >>= 4;
}
- offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
- pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
- ((offset_ofdm & 0xf) * 2);
+ pi->tx_srom_max_rate_2g[i] =
+ max_pwr_chan -
+ ((offset_ofdm & 0xf) * 2);
offset_ofdm >>= 4;
}
} else {
u8 opo = 0;
- opo = (u8) PHY_GETINTVAR(pi, "opo");
+ opo = (u8)wlapi_getintvar(shim, BRCMS_SROM_OPO);
- for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
+ for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++)
pi->tx_srom_max_rate_2g[i] = txpwr;
- }
-
- offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
pi->tx_srom_max_rate_2g[i] = txpwr -
- ((offset_ofdm & 0xf) * 2);
+ ((offset_ofdm & 0xf) * 2);
offset_ofdm >>= 4;
}
offset_mcs =
- ((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) |
- (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
+ wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO1) << 16;
+ offset_mcs |=
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO0);
pi_lcn->lcnphy_mcs20_po = offset_mcs;
for (i = TXP_FIRST_SISO_MCS_20;
i <= TXP_LAST_SISO_MCS_20; i++) {
pi->tx_srom_max_rate_2g[i] =
- txpwr - ((offset_mcs & 0xf) * 2);
+ txpwr - ((offset_mcs & 0xf) * 2);
offset_mcs >>= 4;
}
}
pi_lcn->lcnphy_rawtempsense =
- (u16) PHY_GETINTVAR(pi, "rawtempsense");
+ (u16)wlapi_getintvar(shim, BRCMS_SROM_RAWTEMPSENSE);
pi_lcn->lcnphy_measPower =
- (u8) PHY_GETINTVAR(pi, "measpower");
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_MEASPOWER);
pi_lcn->lcnphy_tempsense_slope =
- (u8) PHY_GETINTVAR(pi, "tempsense_slope");
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_SLOPE);
pi_lcn->lcnphy_hw_iqcal_en =
- (bool) PHY_GETINTVAR(pi, "hw_iqcal_en");
+ (bool)wlapi_getintvar(shim, BRCMS_SROM_HW_IQCAL_EN);
pi_lcn->lcnphy_iqcal_swp_dis =
- (bool) PHY_GETINTVAR(pi, "iqcal_swp_dis");
+ (bool)wlapi_getintvar(shim, BRCMS_SROM_IQCAL_SWP_DIS);
pi_lcn->lcnphy_tempcorrx =
- (u8) PHY_GETINTVAR(pi, "tempcorrx");
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPCORRX);
pi_lcn->lcnphy_tempsense_option =
- (u8) PHY_GETINTVAR(pi, "tempsense_option");
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_OPTION);
pi_lcn->lcnphy_freqoffset_corr =
- (u8) PHY_GETINTVAR(pi, "freqoffset_corr");
- if ((u8) getintvar(pi->vars, "aa2g") > 1)
+ (u8)wlapi_getintvar(shim, BRCMS_SROM_FREQOFFSET_CORR);
+ if ((u8)wlapi_getintvar(shim, BRCMS_SROM_AA2G) > 1)
wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi,
- (u8) getintvar(pi->vars,
- "aa2g"));
+ (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G));
}
pi_lcn->lcnphy_cck_dig_filt_type = -1;
- if (PHY_GETVAR(pi, "cckdigfilttype")) {
- s16 temp;
- temp = (s16) PHY_GETINTVAR(pi, "cckdigfilttype");
- if (temp >= 0) {
- pi_lcn->lcnphy_cck_dig_filt_type = temp;
- }
- }
return true;
}
@@ -4834,172 +4941,6 @@ void wlc_2064_vco_cal(struct brcms_phy *pi)
mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
}
-static void
-wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
-{
- uint i;
- const struct chan_info_2064_lcnphy *ci;
- u8 rfpll_doubler = 0;
- u8 pll_pwrup, pll_pwrup_ovr;
- fixed qFxtal, qFref, qFvco, qFcal;
- u8 d15, d16, f16, e44, e45;
- u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
- u16 loop_bw, d30, setCount;
- if (NORADIO_ENAB(pi->pubpi))
- return;
- ci = &chan_info_2064_lcnphy[0];
- rfpll_doubler = 1;
-
- mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
-
- write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
- if (!rfpll_doubler) {
- loop_bw = PLL_2064_LOOP_BW;
- d30 = PLL_2064_D30;
- } else {
- loop_bw = PLL_2064_LOOP_BW_DOUBLER;
- d30 = PLL_2064_D30_DOUBLER;
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
- if (chan_info_2064_lcnphy[i].chan == channel)
- break;
-
- if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) {
- return;
- }
-
- ci = &chan_info_2064_lcnphy[i];
- }
-
- write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
-
- mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
-
- mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
-
- mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
-
- mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
- (ci->logen_rccr_rx) << 2);
-
- mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
-
- mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
- (ci->pa_rxrf_lna2_freq_tune) << 4);
-
- write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
-
- pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
- pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
-
- or_radio_reg(pi, RADIO_2064_REG044, 0x07);
-
- or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
- e44 = 0;
- e45 = 0;
-
- fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
- if (pi->xtalfreq > 26000000)
- e44 = 1;
- if (pi->xtalfreq > 52000000)
- e45 = 1;
- if (e44 == 0)
- fcal_div = 1;
- else if (e45 == 0)
- fcal_div = 2;
- else
- fcal_div = 4;
- fvco3 = (ci->freq * 3);
- fref3 = 2 * fpfd;
-
- qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
- qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
- qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
- qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
-
- write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
-
- d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
- write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
- write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
-
- d16 = (qFcal * 8 / (d15 + 1)) - 1;
- write_radio_reg(pi, RADIO_2064_REG051, d16);
-
- f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
- setCount = f16 * 3 * (ci->freq) / 32 - 1;
- mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
- (u8) (setCount >> 8));
-
- or_radio_reg(pi, RADIO_2064_REG053, 0x10);
- write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
-
- div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
-
- div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
- while (div_frac >= fref3) {
- div_int++;
- div_frac -= fref3;
- }
- div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
-
- mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
- (u8) (div_int >> 4));
- mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
- (u8) (div_int << 4));
- mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
- (u8) (div_frac >> 16));
- write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
- write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
-
- write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
-
- write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
- write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
- write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
-
- {
- u8 h29, h23, c28, d29, h28_ten, e30, h30_ten, cp_current;
- u16 c29, c38, c30, g30, d28;
- c29 = loop_bw;
- d29 = 200;
- c38 = 1250;
- h29 = d29 / c29;
- h23 = 1;
- c28 = 30;
- d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
- (fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
- (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
- + PLL_2064_LOW_END_KVCO;
- h28_ten = (d28 * 10) / c28;
- c30 = 2640;
- e30 = (d30 - 680) / 490;
- g30 = 680 + (e30 * 490);
- h30_ten = (g30 * 10) / c30;
- cp_current = ((c38 * h29 * h23 * 100) / h28_ten) / h30_ten;
- mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
- }
- if (channel >= 1 && channel <= 5)
- write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
- else
- write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
- write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
-
- mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
- udelay(1);
-
- wlc_2064_vco_cal(pi);
-
- write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
- write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
- if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
- write_radio_reg(pi, RADIO_2064_REG038, 3);
- write_radio_reg(pi, RADIO_2064_REG091, 7);
- }
-}
-
bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi)
{
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
@@ -5015,14 +4956,11 @@ void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi)
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
} else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
-
pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
wlc_lcnphy_txpower_recalc_target(pi);
-
wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
- } else
- return;
+ }
}
void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
@@ -5035,13 +4973,12 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
struct brcms_phy_lcnphy *pi_lcn;
pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC);
- if (pi->u.pi_lcnphy == NULL) {
+ if (pi->u.pi_lcnphy == NULL)
return false;
- }
pi_lcn = pi->u.pi_lcnphy;
- if ((0 == (pi->sh->boardflags & BFL_NOPA)) && !NORADIO_ENAB(pi->pubpi)) {
+ if (0 == (pi->sh->boardflags & BFL_NOPA)) {
pi->hwpwrctrl = true;
pi->hwpwrctrl_capable = true;
}
@@ -5062,7 +4999,8 @@ 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 ((pi->sh->boardflags & BFL_FEM) &&
+ (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
if (pi_lcn->lcnphy_tempsense_option == 3) {
pi->hwpwrctrl = true;
pi->hwpwrctrl_capable = true;
@@ -5090,8 +5028,8 @@ static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain)
biq1 = (u16) (gain >> 16) & 0xf;
gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
- ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
- ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
+ ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
+ ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
gain16_19 = biq1;
mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
@@ -5126,18 +5064,19 @@ static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index)
lcnphy_23bitgaincode_table
[*gain_index]);
received_power =
- wlc_lcnphy_measure_digital_power(pi,
- pi_lcn->
- lcnphy_noise_samples);
+ wlc_lcnphy_measure_digital_power(
+ pi,
+ pi_lcn->
+ lcnphy_noise_samples);
(*gain_index)++;
}
(*gain_index)--;
} else {
wlc_lcnphy_set_rx_gain(pi, gain_code);
received_power =
- wlc_lcnphy_measure_digital_power(pi,
- pi_lcn->
- lcnphy_noise_samples);
+ wlc_lcnphy_measure_digital_power(pi,
+ pi_lcn->
+ lcnphy_noise_samples);
}
return received_power;
@@ -5150,6 +5089,8 @@ s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
input_power_db;
s32 received_power, temperature;
+ u32 power;
+ u32 msb1, msb2, val1, val2, diff1, diff2;
uint freq;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
@@ -5159,20 +5100,17 @@ s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
- {
- u32 power = (received_power * 16);
- u32 msb1, msb2, val1, val2, diff1, diff2;
- msb1 = ffs(power) - 1;
- msb2 = msb1 + 1;
- val1 = 1 << msb1;
- val2 = 1 << msb2;
- diff1 = (power - val1);
- diff2 = (val2 - power);
- if (diff1 < diff2)
- log_val = msb1;
- else
- log_val = msb2;
- }
+ power = (received_power * 16);
+ msb1 = ffs(power) - 1;
+ msb2 = msb1 + 1;
+ val1 = 1 << msb1;
+ val2 = 1 << msb2;
+ diff1 = (power - val1);
+ diff2 = (val2 - power);
+ if (diff1 < diff2)
+ log_val = msb1;
+ else
+ log_val = msb2;
log_val = log_val * 3;
@@ -5188,7 +5126,7 @@ s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
input_power_db = input_power_offset_db - desired_gain;
input_power_db =
- input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
+ input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
if ((freq > 2427) && (freq <= 2467))
@@ -5196,99 +5134,21 @@ s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
temperature = pi_lcn->lcnphy_lastsensed_temperature;
- if ((temperature - 15) < -30) {
+ if ((temperature - 15) < -30)
input_power_db =
- input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
- 7;
- } else if ((temperature - 15) < 4) {
+ input_power_db +
+ (((temperature - 10 - 25) * 286) >> 12) -
+ 7;
+ else if ((temperature - 15) < 4)
input_power_db =
- input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
- 3;
- } else {
- input_power_db =
- input_power_db + (((temperature - 10 - 25) * 286) >> 12);
- }
+ input_power_db +
+ (((temperature - 10 - 25) * 286) >> 12) -
+ 3;
+ else
+ input_power_db = input_power_db +
+ (((temperature - 10 - 25) * 286) >> 12);
wlc_lcnphy_rx_gain_override_enable(pi, 0);
return input_power_db;
}
-
-static int
-wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type)
-{
- s16 filt_index = -1;
- int j;
-
- u16 addr[] = {
- 0x910,
- 0x91e,
- 0x91f,
- 0x924,
- 0x925,
- 0x926,
- 0x920,
- 0x921,
- 0x927,
- 0x928,
- 0x929,
- 0x922,
- 0x923,
- 0x930,
- 0x931,
- 0x932
- };
-
- u16 addr_ofdm[] = {
- 0x90f,
- 0x900,
- 0x901,
- 0x906,
- 0x907,
- 0x908,
- 0x902,
- 0x903,
- 0x909,
- 0x90a,
- 0x90b,
- 0x904,
- 0x905,
- 0x90c,
- 0x90d,
- 0x90e
- };
-
- if (!is_ofdm) {
- for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
- if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
- filt_index = (s16) j;
- break;
- }
- }
-
- if (filt_index != -1) {
- for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, addr[j],
- LCNPHY_txdigfiltcoeffs_cck
- [filt_index][j + 1]);
- }
- }
- } else {
- for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
- if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
- filt_index = (s16) j;
- break;
- }
- }
-
- if (filt_index != -1) {
- for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, addr_ofdm[j],
- LCNPHY_txdigfiltcoeffs_ofdm
- [filt_index][j + 1]);
- }
- }
- }
-
- return (filt_index != -1) ? 0 : -1;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h
index f4a8ab09da43..f4a8ab09da43 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
index f8e419239425..cd19c2f7a347 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
@@ -14,7 +14,9 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/kernel.h>
#include <linux/delay.h>
+#include <linux/cordic.h>
#include <brcm_hw_ids.h>
#include <aiutils.h>
@@ -28,27 +30,42 @@
#include "phyreg_n.h"
#include "phytbl_n.h"
-#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \
- read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
- ((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1))
-#define WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \
+#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \
+ read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
+ ((core == PHY_CORE_0) ? \
+ radio_type##_##jspace##0 : \
+ radio_type##_##jspace##1))
+
+#define WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \
write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
- ((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1), value);
-#define WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \
- write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value);
-
-#define READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \
- read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
- radio_type##_##jspace##1##_##reg_name));
-#define WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \
- write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
- radio_type##_##jspace##1##_##reg_name), value);
-#define READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \
- read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
- radio_type##_##reg_name##_##jspace##1));
-#define WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \
- write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
- radio_type##_##reg_name##_##jspace##1), value);
+ ((core == PHY_CORE_0) ? \
+ radio_type##_##jspace##0 : \
+ radio_type##_##jspace##1), value)
+
+#define WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \
+ write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value)
+
+#define READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \
+ read_radio_reg(pi, ((core == PHY_CORE_0) ? \
+ radio_type##_##jspace##0##_##reg_name : \
+ radio_type##_##jspace##1##_##reg_name))
+
+#define WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \
+ write_radio_reg(pi, ((core == PHY_CORE_0) ? \
+ radio_type##_##jspace##0##_##reg_name : \
+ radio_type##_##jspace##1##_##reg_name), \
+ value)
+
+#define READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \
+ read_radio_reg(pi, ((core == PHY_CORE_0) ? \
+ radio_type##_##reg_name##_##jspace##0 : \
+ radio_type##_##reg_name##_##jspace##1))
+
+#define WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \
+ write_radio_reg(pi, ((core == PHY_CORE_0) ? \
+ radio_type##_##reg_name##_##jspace##0 : \
+ radio_type##_##reg_name##_##jspace##1), \
+ value)
#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40
#define NPHY_ACI_CHANNEL_DELTA 5
@@ -103,9 +120,11 @@
#define NPHY_CALSANITY_RSSI_NB_MAX_POS 9
#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9
#define NPHY_CALSANITY_RSSI_W1_MAX_POS 12
-#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - NPHY_RSSICAL_MAXREAD)
+#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - \
+ NPHY_RSSICAL_MAXREAD)
#define NPHY_CALSANITY_RSSI_W2_MAX_POS NPHY_CALSANITY_RSSI_W1_MAX_POS
-#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - NPHY_RSSICAL_MAXREAD)
+#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - \
+ NPHY_RSSICAL_MAXREAD)
#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f)))
#define NPHY_RSSI_NB_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \
((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG))
@@ -124,11 +143,11 @@
#define NPHY_PAPD_COMP_OFF 0
#define NPHY_PAPD_COMP_ON 1
-#define NPHY_SROM_TEMPSHIFT 32
-#define NPHY_SROM_MAXTEMPOFFSET 16
-#define NPHY_SROM_MINTEMPOFFSET -16
+#define NPHY_SROM_TEMPSHIFT 32
+#define NPHY_SROM_MAXTEMPOFFSET 16
+#define NPHY_SROM_MINTEMPOFFSET -16
-#define NPHY_CAL_MAXTEMPDELTA 64
+#define NPHY_CAL_MAXTEMPDELTA 64
#define NPHY_NOISEVAR_TBLLEN40 256
#define NPHY_NOISEVAR_TBLLEN20 128
@@ -138,8 +157,24 @@
#define NPHY_ADJUSTED_MINCRSPOWER 0x1e
/* 5357 Chip specific ChipControl register bits */
-#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */
-#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */
+#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */
+#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */
+
+#define NPHY_CAL_TSSISAMPS 64
+#define NPHY_TEST_TONE_FREQ_40MHz 4000
+#define NPHY_TEST_TONE_FREQ_20MHz 2500
+
+#define MAX_205x_RCAL_WAITLOOPS 10000
+
+#define NPHY_RXCAL_TONEAMP 181
+#define NPHY_RXCAL_TONEFREQ_40MHz 4000
+#define NPHY_RXCAL_TONEFREQ_20MHz 2000
+
+#define TXFILT_SHAPING_OFDM20 0
+#define TXFILT_SHAPING_OFDM40 1
+#define TXFILT_SHAPING_CCK 2
+#define TXFILT_DEFAULT_OFDM20 3
+#define TXFILT_DEFAULT_OFDM40 4
struct nphy_iqcal_params {
u16 txlpf;
@@ -184,44 +219,42 @@ struct nphy_ipa_txrxgain {
#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1)
-struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = { {0, 0, 0, 0, 0, 100},
-{0, 0, 0, 0, 0, 50},
-{0, 0, 0, 0, 0, -1},
-{0, 0, 0, 3, 0, -1},
-{0, 0, 3, 3, 0, -1},
-{0, 2, 3, 3, 0, -1}
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = {
+ {0, 0, 0, 0, 0, 100},
+ {0, 0, 0, 0, 0, 50},
+ {0, 0, 0, 0, 0, -1},
+ {0, 0, 0, 3, 0, -1},
+ {0, 0, 3, 3, 0, -1},
+ {0, 2, 3, 3, 0, -1}
};
-struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = { {0, 0, 0, 0, 0, 128},
-{0, 0, 0, 0, 0, 70},
-{0, 0, 0, 0, 0, 20},
-{0, 0, 0, 3, 0, 20},
-{0, 0, 3, 3, 0, 20},
-{0, 2, 3, 3, 0, 20}
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = {
+ {0, 0, 0, 0, 0, 128},
+ {0, 0, 0, 0, 0, 70},
+ {0, 0, 0, 0, 0, 20},
+ {0, 0, 0, 3, 0, 20},
+ {0, 0, 3, 3, 0, 20},
+ {0, 2, 3, 3, 0, 20}
};
-struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = {
-{0, 0, 0, 0, 0, 100},
-{0, 0, 0, 0, 0, 50},
-{0, 0, 0, 0, 0, -1},
-{0, 0, 0, 3, 0, -1},
-{0, 0, 3, 3, 0, -1},
-{0, 0, 5, 3, 0, -1}
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = {
+ {0, 0, 0, 0, 0, 100},
+ {0, 0, 0, 0, 0, 50},
+ {0, 0, 0, 0, 0, -1},
+ {0, 0, 0, 3, 0, -1},
+ {0, 0, 3, 3, 0, -1},
+ {0, 0, 5, 3, 0, -1}
};
-struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = {
-{0, 0, 0, 0, 0, 10},
-{0, 0, 0, 1, 0, 10},
-{0, 0, 1, 2, 0, 10},
-{0, 0, 1, 3, 0, 10},
-{0, 0, 4, 3, 0, 10},
-{0, 0, 6, 3, 0, 10}
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = {
+ {0, 0, 0, 0, 0, 10},
+ {0, 0, 0, 1, 0, 10},
+ {0, 0, 1, 2, 0, 10},
+ {0, 0, 1, 3, 0, 10},
+ {0, 0, 4, 3, 0, 10},
+ {0, 0, 6, 3, 0, 10}
};
-#define NPHY_RXCAL_TONEAMP 181
-#define NPHY_RXCAL_TONEFREQ_40MHz 4000
-#define NPHY_RXCAL_TONEFREQ_20MHz 2000
-
enum {
NPHY_RXCAL_GAIN_INIT = 0,
NPHY_RXCAL_GAIN_UP,
@@ -230,17 +263,11 @@ enum {
#define wlc_phy_get_papd_nphy(pi) \
(read_phy_reg((pi), 0x1e7) & \
- ((0x1 << 15) | \
- (0x1 << 14) | \
- (0x1 << 13)))
+ ((0x1 << 15) | \
+ (0x1 << 14) | \
+ (0x1 << 13)))
-#define TXFILT_SHAPING_OFDM20 0
-#define TXFILT_SHAPING_OFDM40 1
-#define TXFILT_SHAPING_CCK 2
-#define TXFILT_DEFAULT_OFDM20 3
-#define TXFILT_DEFAULT_OFDM40 4
-
-u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = {
+static const u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = {
{-377, 137, -407, 208, -1527, 956, 93, 186, 93,
230, -44, 230, 201, -191, 201},
{-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5,
@@ -416,7 +443,7 @@ struct nphy_sfo_cfg {
u16 PHY_BW6;
};
-static struct chan_info_nphy_2055 chan_info_nphy_2055[] = {
+static const struct chan_info_nphy_2055 chan_info_nphy_2055[] = {
{
184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
@@ -915,7 +942,7 @@ static struct chan_info_nphy_2055 chan_info_nphy_2055[] = {
0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
@@ -1538,7 +1565,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = {
0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
@@ -2161,7 +2188,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = {
0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
@@ -2784,7 +2811,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = {
0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
@@ -3407,7 +3434,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = {
0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
@@ -4030,7 +4057,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = {
0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
@@ -4653,7 +4680,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = {
0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = {
+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = {
{
184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01,
0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
@@ -5276,7 +5303,7 @@ static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = {
0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = {
+static const struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = {
{
184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
@@ -6139,7 +6166,8 @@ static struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = {
0x0424}
};
-static struct chan_info_nphy_radio2057_rev5 chan_info_nphyrev8_2057_rev5[] = {
+static const struct chan_info_nphy_radio2057_rev5
+chan_info_nphyrev8_2057_rev5[] = {
{
1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
@@ -6198,7 +6226,8 @@ static struct chan_info_nphy_radio2057_rev5 chan_info_nphyrev8_2057_rev5[] = {
0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio2057_rev5 chan_info_nphyrev9_2057_rev5v1[] = {
+static const struct chan_info_nphy_radio2057_rev5
+chan_info_nphyrev9_2057_rev5v1[] = {
{
1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
@@ -6257,7 +6286,7 @@ static struct chan_info_nphy_radio2057_rev5 chan_info_nphyrev9_2057_rev5v1[] = {
0x041b, 0x041f, 0x0424}
};
-static struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = {
+static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = {
{
184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
@@ -6998,7 +7027,7 @@ static struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = {
0x0424}
};
-static struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = {
+static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = {
{
186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
@@ -7733,7 +7762,7 @@ static struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = {
0x0424}
};
-struct radio_regs regs_2055[] = {
+static struct radio_regs regs_2055[] = {
{0x02, 0x80, 0x80, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0x27, 0x27, 0, 0},
@@ -7962,7 +7991,7 @@ struct radio_regs regs_2055[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_SYN_2056[] = {
+static struct radio_regs regs_SYN_2056[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8147,7 +8176,7 @@ struct radio_regs regs_SYN_2056[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_TX_2056[] = {
+static struct radio_regs regs_TX_2056[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8296,7 +8325,7 @@ struct radio_regs regs_TX_2056[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_RX_2056[] = {
+static struct radio_regs regs_RX_2056[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8447,7 +8476,7 @@ struct radio_regs regs_RX_2056[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_SYN_2056_A1[] = {
+static struct radio_regs regs_SYN_2056_A1[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8632,7 +8661,7 @@ struct radio_regs regs_SYN_2056_A1[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_TX_2056_A1[] = {
+static struct radio_regs regs_TX_2056_A1[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8781,7 +8810,7 @@ struct radio_regs regs_TX_2056_A1[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_RX_2056_A1[] = {
+static struct radio_regs regs_RX_2056_A1[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -8932,7 +8961,7 @@ struct radio_regs regs_RX_2056_A1[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_SYN_2056_rev5[] = {
+static struct radio_regs regs_SYN_2056_rev5[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9117,7 +9146,7 @@ struct radio_regs regs_SYN_2056_rev5[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_TX_2056_rev5[] = {
+static struct radio_regs regs_TX_2056_rev5[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9274,7 +9303,7 @@ struct radio_regs regs_TX_2056_rev5[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_RX_2056_rev5[] = {
+static struct radio_regs regs_RX_2056_rev5[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9425,7 +9454,7 @@ struct radio_regs regs_RX_2056_rev5[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_SYN_2056_rev6[] = {
+static struct radio_regs regs_SYN_2056_rev6[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9610,7 +9639,7 @@ struct radio_regs regs_SYN_2056_rev6[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_TX_2056_rev6[] = {
+static struct radio_regs regs_TX_2056_rev6[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9767,7 +9796,7 @@ struct radio_regs regs_TX_2056_rev6[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_RX_2056_rev6[] = {
+static struct radio_regs regs_RX_2056_rev6[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -9918,7 +9947,7 @@ struct radio_regs regs_RX_2056_rev6[] = {
{0xFFFF, 0, 0, 0, 0}
};
-struct radio_regs regs_SYN_2056_rev7[] = {
+static struct radio_regs regs_SYN_2056_rev7[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10103,7 +10132,7 @@ struct radio_regs regs_SYN_2056_rev7[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_TX_2056_rev7[] = {
+static struct radio_regs regs_TX_2056_rev7[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10260,7 +10289,7 @@ struct radio_regs regs_TX_2056_rev7[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_RX_2056_rev7[] = {
+static struct radio_regs regs_RX_2056_rev7[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10411,7 +10440,7 @@ struct radio_regs regs_RX_2056_rev7[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_SYN_2056_rev8[] = {
+static struct radio_regs regs_SYN_2056_rev8[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10596,7 +10625,7 @@ struct radio_regs regs_SYN_2056_rev8[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_TX_2056_rev8[] = {
+static struct radio_regs regs_TX_2056_rev8[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10753,7 +10782,7 @@ struct radio_regs regs_TX_2056_rev8[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_RX_2056_rev8[] = {
+static struct radio_regs regs_RX_2056_rev8[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -10904,7 +10933,7 @@ struct radio_regs regs_RX_2056_rev8[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_SYN_2056_rev11[] = {
+static const struct radio_regs regs_SYN_2056_rev11[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -11089,7 +11118,7 @@ struct radio_regs regs_SYN_2056_rev11[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_TX_2056_rev11[] = {
+static const struct radio_regs regs_TX_2056_rev11[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -11246,7 +11275,7 @@ struct radio_regs regs_TX_2056_rev11[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_regs regs_RX_2056_rev11[] = {
+static const struct radio_regs regs_RX_2056_rev11[] = {
{0x02, 0, 0, 0, 0},
{0x03, 0, 0, 0, 0},
{0x04, 0, 0, 0, 0},
@@ -11397,7 +11426,7 @@ struct radio_regs regs_RX_2056_rev11[] = {
{0xFFFF, 0, 0, 0, 0},
};
-struct radio_20xx_regs regs_2057_rev4[] = {
+static struct radio_20xx_regs regs_2057_rev4[] = {
{0x00, 0x84, 0},
{0x01, 0, 0},
{0x02, 0x60, 0},
@@ -11787,7 +11816,7 @@ struct radio_20xx_regs regs_2057_rev4[] = {
{0xFFFF, 0, 0},
};
-struct radio_20xx_regs regs_2057_rev5[] = {
+static struct radio_20xx_regs regs_2057_rev5[] = {
{0x00, 0, 1},
{0x01, 0x57, 1},
{0x02, 0x20, 1},
@@ -12119,7 +12148,7 @@ struct radio_20xx_regs regs_2057_rev5[] = {
{0xFFFF, 0, 0}
};
-struct radio_20xx_regs regs_2057_rev5v1[] = {
+static struct radio_20xx_regs regs_2057_rev5v1[] = {
{0x00, 0x15, 1},
{0x01, 0x57, 1},
{0x02, 0x20, 1},
@@ -12451,7 +12480,7 @@ struct radio_20xx_regs regs_2057_rev5v1[] = {
{0xFFFF, 0, 0}
};
-struct radio_20xx_regs regs_2057_rev7[] = {
+static struct radio_20xx_regs regs_2057_rev7[] = {
{0x00, 0, 1},
{0x01, 0x57, 1},
{0x02, 0x20, 1},
@@ -12867,7 +12896,7 @@ struct radio_20xx_regs regs_2057_rev7[] = {
{0xFFFF, 0, 0}
};
-struct radio_20xx_regs regs_2057_rev8[] = {
+static struct radio_20xx_regs regs_2057_rev8[] = {
{0x00, 0x8, 1},
{0x01, 0x57, 1},
{0x02, 0x20, 1},
@@ -13290,27 +13319,27 @@ static s32 nphy_lnagain_est1[] = { -224, 23242 };
static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = {
{
- {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69},
- {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69},
- {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68},
- {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67},
- {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66},
- {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65},
- {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65},
- {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65},
- {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65}
- },
- {
- {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
- {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
- {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79},
- {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78},
- {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78},
- {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78},
- {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78},
- {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78},
- {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78}
- }
+ {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69},
+ {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69},
+ {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68},
+ {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67},
+ {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66},
+ {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65},
+ {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65},
+ {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65},
+ {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65}
+ },
+ {
+ {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+ {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+ {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79},
+ {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78},
+ {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78},
+ {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78},
+ {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78},
+ {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78},
+ {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78}
+ }
};
static const u32 nphy_tpc_txgain[] = {
@@ -14081,118 +14110,11 @@ static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = {
static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 };
static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 };
static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = {
- 0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a };
+ 0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a
+};
static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = {
- 0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 };
-
-static bool wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
- struct chan_info_nphy_radio2057 **t0,
- struct chan_info_nphy_radio205x **t1,
- struct chan_info_nphy_radio2057_rev5 **t2,
- struct chan_info_nphy_2055 **t3);
-static void wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chans,
- const struct nphy_sfo_cfg *c);
-
-static void wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi,
- u16 reduction_factr);
-static void wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi,
- int ntones, int *, u32 *buf);
-static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr);
-static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi);
-static void wlc_phy_spurwar_nphy(struct brcms_phy *pi);
-
-static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi);
-static void wlc_phy_radio_init_2055(struct brcms_phy *pi);
-static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi);
-static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi);
-static void wlc_phy_radio_init_2056(struct brcms_phy *pi);
-static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi);
-static void wlc_phy_radio_init_2057(struct brcms_phy *pi);
-static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi);
-static void wlc_phy_workarounds_nphy(struct brcms_phy *pi);
-static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi);
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi);
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi);
-static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi);
-
-static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi);
-static void wlc_phy_reapply_txcal_coeffs_nphy(struct brcms_phy *pi);
-static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi);
-static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
- struct nphy_txgains tg, u8 type, bool d);
-static void wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rxcore,
- u16 *rg, u8 type);
-static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble);
-static void wlc_phy_savecal_nphy(struct brcms_phy *pi);
-static void wlc_phy_restorecal_nphy(struct brcms_phy *pi);
-static void wlc_phy_resetcca_nphy(struct brcms_phy *pi);
-
-static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi);
-static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi);
-static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi);
-static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core);
-
-static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi);
-static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi);
-static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi);
-static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi);
-static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1);
-static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi);
-
-static void wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32,
- u32 e);
-static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core);
-static void wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *,
- enum phy_cal_mode, u8);
-static void wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi,
- struct nphy_papd_restore_state *state);
-static void wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi,
- struct nphy_papd_restore_state *state, u8);
-
-static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals);
-
-static void wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *evts,
- u8 *dlys, u8 len);
-
-static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset);
-
-static void
-wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value,
- u8 core_mask, u8 off,
- u8 override_id);
-
-static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type);
-static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi);
-
-static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi);
-static void wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max,
- u16 *pwr_offset,
- u8 tmp_max_pwr, u8 rate_start,
- u8 rate_end);
-
-static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi);
-static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi);
-static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi);
-static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi);
-
-static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi);
-static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core);
-static void wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0,
- u8 idx1);
-static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal);
-
-static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi);
-
-static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi);
-
-static u16 wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz,
- u16 max_val,
- u8 dac_test_mode);
-static void wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, cs32 *tone_buf,
- u16 num_samps);
-static void wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 n, u16 lps,
- u16 wait, u8 iq, u8 dac_test_mode,
- bool modify_bbmult);
+ 0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16
+};
bool wlc_phy_bist_check_phy(struct brcms_phy_pub *pih)
{
@@ -14209,9 +14131,8 @@ bool wlc_phy_bist_check_phy(struct brcms_phy_pub *pih)
phybist4 = read_phy_reg(pi, 0x156);
if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) &&
- (phybist3 == 0) && (phybist4 == 0)) {
+ (phybist3 == 0) && (phybist4 == 0))
return true;
- }
return false;
}
@@ -14230,18 +14151,7 @@ static void wlc_phy_bphy_init_nphy(struct brcms_phy *pi)
val -= 0x0202;
}
- if (NORADIO_ENAB(pi->pubpi)) {
-
- write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_PHYCRSTH, 0x3206);
-
- write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_RSSI_TRESH, 0x281e);
-
- or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_LNA_GAIN_RANGE, 0x1a);
-
- } else {
-
- write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668);
- }
+ write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668);
}
void
@@ -14307,7 +14217,8 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi)
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
- pi->srom_fem2g.antswctrllut : pi->srom_fem5g.antswctrllut;
+ pi->srom_fem2g.antswctrllut : pi->srom_fem5g.
+ antswctrllut;
switch (antswctrllut) {
case 0:
@@ -14316,20 +14227,20 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi)
case 1:
- if (pi->aa2g == 7) {
+ if (pi->aa2g == 7)
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x21, 8,
+ &ant_sw_ctrl_tbl_rev8_2o3[0]);
+ else
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x21, 8,
+ &ant_sw_ctrl_tbl_rev8
+ [0]);
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x21, 8,
- &ant_sw_ctrl_tbl_rev8_2o3
- [0]);
- } else {
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x21, 8,
- &ant_sw_ctrl_tbl_rev8
- [0]);
- }
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
2, 0x25, 8,
&ant_sw_ctrl_tbl_rev8[2]);
@@ -14340,31 +14251,31 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi)
case 2:
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x1, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core0
- [0]);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x5, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core0
- [2]);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x9, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core0
- [4]);
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x21, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core1
- [0]);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x25, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core1
- [2]);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
- 2, 0x29, 8,
- &ant_sw_ctrl_tbl_rev8_2057v7_core1
- [4]);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x1, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core0[0]);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x5, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core0[2]);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x9, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core0[4]);
+
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x21, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core1[0]);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x25, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core1[2]);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+ 2, 0x29, 8,
+ &ant_sw_ctrl_tbl_rev8_2057v7_core1[4]);
break;
default:
@@ -14375,45 +14286,49 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi)
for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) {
if (idx == ANT_SWCTRL_TBL_REV3_IDX) {
- antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
- pi->srom_fem2g.antswctrllut : pi->
- srom_fem5g.antswctrllut;
+ antswctrllut =
+ CHSPEC_IS2G(pi->radio_chanspec) ?
+ pi->srom_fem2g.antswctrllut :
+ pi->srom_fem5g.antswctrllut;
switch (antswctrllut) {
case 0:
- wlc_phy_write_table_nphy(pi,
- &mimophytbl_info_rev3_volatile
- [idx]);
+ wlc_phy_write_table_nphy(
+ pi,
+ &mimophytbl_info_rev3_volatile
+ [idx]);
break;
case 1:
- wlc_phy_write_table_nphy(pi,
- &mimophytbl_info_rev3_volatile1
- [idx]);
+ wlc_phy_write_table_nphy(
+ pi,
+ &mimophytbl_info_rev3_volatile1
+ [idx]);
break;
case 2:
- wlc_phy_write_table_nphy(pi,
- &mimophytbl_info_rev3_volatile2
- [idx]);
+ wlc_phy_write_table_nphy(
+ pi,
+ &mimophytbl_info_rev3_volatile2
+ [idx]);
break;
case 3:
- wlc_phy_write_table_nphy(pi,
- &mimophytbl_info_rev3_volatile3
- [idx]);
+ wlc_phy_write_table_nphy(
+ pi,
+ &mimophytbl_info_rev3_volatile3
+ [idx]);
break;
default:
break;
}
} else {
- wlc_phy_write_table_nphy(pi,
- &mimophytbl_info_rev3_volatile
- [idx]);
+ wlc_phy_write_table_nphy(
+ pi,
+ &mimophytbl_info_rev3_volatile[idx]);
}
}
} else {
- for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) {
+ for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++)
wlc_phy_write_table_nphy(pi,
&mimophytbl_info_rev0_volatile
[idx]);
- }
}
}
@@ -14440,32 +14355,414 @@ void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs)
wlc_phy_write_txmacreg_nphy(pi, holdoff, delay);
- if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) {
+ if (pi && pi->sh && (pi->sh->_rifs_phy != rifs))
pi->sh->_rifs_phy = rifs;
+}
+
+static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi)
+{
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+ pi->phy_5g_pwrgain = true;
+ return;
+ }
+
+ pi->nphy_txpwrctrl = PHY_TPC_HW_OFF;
+ pi->phy_5g_pwrgain = false;
+
+ if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) &&
+ NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4))
+ pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+ else if ((pi->sh->sromrev >= 4)
+ && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN))
+ pi->phy_5g_pwrgain = true;
+}
+
+static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
+{
+ u16 bw40po, cddpo, stbcpo, bwduppo;
+ uint band_num;
+ struct phy_shim_info *shim = pi->sh->physhim;
+
+ if (pi->sh->sromrev >= 9)
+ return;
+
+ bw40po = (u16) wlapi_getintvar(shim, BRCMS_SROM_BW40PO);
+ pi->bw402gpo = bw40po & 0xf;
+ pi->bw405gpo = (bw40po & 0xf0) >> 4;
+ pi->bw405glpo = (bw40po & 0xf00) >> 8;
+ pi->bw405ghpo = (bw40po & 0xf000) >> 12;
+
+ cddpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_CDDPO);
+ pi->cdd2gpo = cddpo & 0xf;
+ pi->cdd5gpo = (cddpo & 0xf0) >> 4;
+ pi->cdd5glpo = (cddpo & 0xf00) >> 8;
+ pi->cdd5ghpo = (cddpo & 0xf000) >> 12;
+
+ stbcpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_STBCPO);
+ pi->stbc2gpo = stbcpo & 0xf;
+ pi->stbc5gpo = (stbcpo & 0xf0) >> 4;
+ pi->stbc5glpo = (stbcpo & 0xf00) >> 8;
+ pi->stbc5ghpo = (stbcpo & 0xf000) >> 12;
+
+ bwduppo = (u16) wlapi_getintvar(shim, BRCMS_SROM_BWDUPPO);
+ pi->bwdup2gpo = bwduppo & 0xf;
+ pi->bwdup5gpo = (bwduppo & 0xf0) >> 4;
+ pi->bwdup5glpo = (bwduppo & 0xf00) >> 8;
+ pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12;
+
+ for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP);
+ band_num++) {
+ switch (band_num) {
+ case 0:
+
+ pi->nphy_txpid2g[PHY_CORE_0] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID2GA0);
+ pi->nphy_txpid2g[PHY_CORE_1] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID2GA1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP2GA0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP2GA1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW0A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW0A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW1A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW1A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW2A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA2GW2A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g =
+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g =
+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA1);
+
+ pi->cck2gpo = (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_CCK2GPO);
+
+ pi->ofdm2gpo =
+ (u32) wlapi_getintvar(shim,
+ BRCMS_SROM_OFDM2GPO);
+
+ pi->mcs2gpo[0] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO0);
+ pi->mcs2gpo[1] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO1);
+ pi->mcs2gpo[2] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO2);
+ pi->mcs2gpo[3] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO3);
+ pi->mcs2gpo[4] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO4);
+ pi->mcs2gpo[5] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO5);
+ pi->mcs2gpo[6] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO6);
+ pi->mcs2gpo[7] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS2GPO7);
+ break;
+ case 1:
+
+ pi->nphy_txpid5g[PHY_CORE_0] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GA0);
+ pi->nphy_txpid5g[PHY_CORE_1] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GA1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
+ (s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP5GA1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW0A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW0A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW1A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW1A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW2A0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GW2A1);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm =
+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA0);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm =
+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA1);
+
+ pi->ofdm5gpo =
+ (u32) wlapi_getintvar(shim,
+ BRCMS_SROM_OFDM5GPO);
+
+ pi->mcs5gpo[0] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO0);
+ pi->mcs5gpo[1] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO1);
+ pi->mcs5gpo[2] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO2);
+ pi->mcs5gpo[3] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO3);
+ pi->mcs5gpo[4] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO4);
+ pi->mcs5gpo[5] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO5);
+ pi->mcs5gpo[6] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO6);
+ pi->mcs5gpo[7] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GPO7);
+ break;
+ case 2:
+
+ pi->nphy_txpid5gl[0] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GLA0);
+ pi->nphy_txpid5gl[1] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GLA1);
+ pi->nphy_pwrctrl_info[0].max_pwr_5gl =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP5GLA0);
+ pi->nphy_pwrctrl_info[1].max_pwr_5gl =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP5GLA1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW0A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW0A1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW1A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW1A1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW2A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GLW2A1);
+ pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0;
+ pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0;
+
+ pi->ofdm5glpo =
+ (u32) wlapi_getintvar(shim,
+ BRCMS_SROM_OFDM5GLPO);
+
+ pi->mcs5glpo[0] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO0);
+ pi->mcs5glpo[1] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO1);
+ pi->mcs5glpo[2] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO2);
+ pi->mcs5glpo[3] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO3);
+ pi->mcs5glpo[4] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO4);
+ pi->mcs5glpo[5] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO5);
+ pi->mcs5glpo[6] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO6);
+ pi->mcs5glpo[7] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GLPO7);
+ break;
+ case 3:
+
+ pi->nphy_txpid5gh[0] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GHA0);
+ pi->nphy_txpid5gh[1] =
+ (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TXPID5GHA1);
+ pi->nphy_pwrctrl_info[0].max_pwr_5gh =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP5GHA0);
+ pi->nphy_pwrctrl_info[1].max_pwr_5gh =
+ (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_MAXP5GHA1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW0A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW0A1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW1A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW1A1);
+ pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW2A0);
+ pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 =
+ (s16) wlapi_getintvar(shim,
+ BRCMS_SROM_PA5GHW2A1);
+ pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0;
+ pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0;
+
+ pi->ofdm5ghpo =
+ (u32) wlapi_getintvar(shim,
+ BRCMS_SROM_OFDM5GHPO);
+
+ pi->mcs5ghpo[0] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO0);
+ pi->mcs5ghpo[1] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO1);
+ pi->mcs5ghpo[2] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO2);
+ pi->mcs5ghpo[3] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO3);
+ pi->mcs5ghpo[4] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO4);
+ pi->mcs5ghpo[5] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO5);
+ pi->mcs5ghpo[6] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO6);
+ pi->mcs5ghpo[7] =
+ (u16) wlapi_getintvar(shim,
+ BRCMS_SROM_MCS5GHPO7);
+ break;
+ }
}
+
+ wlc_phy_txpwr_apply_nphy(pi);
+}
+
+static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi)
+{
+ struct phy_shim_info *shim = pi->sh->physhim;
+
+ pi->antswitch = (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWITCH);
+ pi->aa2g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G);
+ pi->aa5g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA5G);
+
+ pi->srom_fem2g.tssipos = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TSSIPOS2G);
+ pi->srom_fem2g.extpagain = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_EXTPAGAIN2G);
+ pi->srom_fem2g.pdetrange = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_PDETRANGE2G);
+ pi->srom_fem2g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO2G);
+ pi->srom_fem2g.antswctrllut =
+ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G);
+
+ pi->srom_fem5g.tssipos = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_TSSIPOS5G);
+ pi->srom_fem5g.extpagain = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_EXTPAGAIN5G);
+ pi->srom_fem5g.pdetrange = (u8) wlapi_getintvar(shim,
+ BRCMS_SROM_PDETRANGE5G);
+ pi->srom_fem5g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO5G);
+ if (wlapi_getvar(shim, BRCMS_SROM_ANTSWCTL5G))
+ pi->srom_fem5g.antswctrllut =
+ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL5G);
+ else
+ pi->srom_fem5g.antswctrllut =
+ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G);
+
+ wlc_phy_txpower_ipa_upd(pi);
+
+ pi->phy_txcore_disable_temp =
+ (s16) wlapi_getintvar(shim, BRCMS_SROM_TEMPTHRESH);
+ if (pi->phy_txcore_disable_temp == 0)
+ pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
+
+ pi->phy_tempsense_offset = (s8) wlapi_getintvar(shim,
+ BRCMS_SROM_TEMPOFFSET);
+ if (pi->phy_tempsense_offset != 0) {
+ if (pi->phy_tempsense_offset >
+ (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET))
+ pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET;
+ else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT +
+ NPHY_SROM_MINTEMPOFFSET))
+ pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET;
+ else
+ pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT;
+ }
+
+ pi->phy_txcore_enable_temp =
+ pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP;
+
+ pi->phycal_tempdelta =
+ (u8) wlapi_getintvar(shim, BRCMS_SROM_PHYCAL_TEMPDELTA);
+ if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA)
+ pi->phycal_tempdelta = 0;
+
+ wlc_phy_txpwr_srom_read_ppr_nphy(pi);
+
+ return true;
}
bool wlc_phy_attach_nphy(struct brcms_phy *pi)
{
uint i;
- if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6))
pi->phyhang_avoid = true;
- }
if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
pi->nphy_gband_spurwar_en = true;
-
- if (pi->sh->boardflags2 & BFL2_SPUR_WAR) {
+ if (pi->sh->boardflags2 & BFL2_SPUR_WAR)
pi->nphy_aband_spurwar_en = true;
- }
}
if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
- if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) {
+ if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR)
pi->nphy_gband_spurwar2_en = true;
- }
}
pi->n_preamble_override = AUTO;
@@ -14485,9 +14782,8 @@ bool wlc_phy_attach_nphy(struct brcms_phy *pi)
pi->nphy_elna_gain_config = false;
pi->radio_is_on = false;
- for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+ for (i = 0; i < pi->pubpi.phy_corenum; i++)
pi->nphy_txpwrindex[i].index = AUTO;
- }
wlc_phy_txpwrctrl_config_nphy(pi);
if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
@@ -14504,751 +14800,1405 @@ bool wlc_phy_attach_nphy(struct brcms_phy *pi)
return true;
}
-static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi)
+static s32 get_rf_pwr_offset(struct brcms_phy *pi, s16 pga_gn, s16 pad_gn)
{
+ s32 rfpwr_offset = 0;
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
- pi->phy_5g_pwrgain = true;
- return;
- }
-
- pi->nphy_txpwrctrl = PHY_TPC_HW_OFF;
- pi->phy_5g_pwrgain = false;
-
- if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) &&
- NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4))
- pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
- else if ((pi->sh->sromrev >= 4)
- && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN))
- pi->phy_5g_pwrgain = true;
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6))
+ rfpwr_offset = (s16)
+ nphy_papd_padgain_dlt_2g_2057rev3n4
+ [pad_gn];
+ else if (pi->pubpi.radiorev == 5)
+ rfpwr_offset = (s16)
+ nphy_papd_padgain_dlt_2g_2057rev5
+ [pad_gn];
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev ==
+ 8))
+ rfpwr_offset = (s16)
+ nphy_papd_padgain_dlt_2g_2057rev7
+ [pad_gn];
+ } else {
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6))
+ rfpwr_offset = (s16)
+ nphy_papd_pgagain_dlt_5g_2057
+ [pga_gn];
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev ==
+ 8))
+ rfpwr_offset = (s16)
+ nphy_papd_pgagain_dlt_5g_2057rev7
+ [pga_gn];
+ }
+ return rfpwr_offset;
}
-void wlc_phy_init_nphy(struct brcms_phy *pi)
+static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble)
{
+ bool gf_preamble = false;
u16 val;
- u16 clip1_ths[2];
- struct nphy_txgains target_gain;
- u8 tx_pwr_ctrl_state;
- bool do_nphy_cal = false;
- uint core;
- uint origidx, intr_val;
- d11regs_t *regs;
- u32 d11_clk_ctl_st;
- core = 0;
-
- if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
- pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
- }
+ if (preamble == BRCMS_N_PREAMBLE_GF)
+ gf_preamble = true;
- if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
- ((pi->sh->chippkg == BCM4717_PKG_ID) ||
- (pi->sh->chippkg == BCM4718_PKG_ID))) {
- if ((pi->sh->boardflags & BFL_EXTLNA) &&
- (CHSPEC_IS2G(pi->radio_chanspec))) {
- ai_corereg(pi->sh->sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol), 0x40,
- 0x40);
- }
- }
+ val = read_phy_reg(pi, 0xed);
- if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
- CHSPEC_IS40(pi->radio_chanspec)) {
+ val |= RX_GF_MM_AUTO;
+ val &= ~RX_GF_OR_MM;
+ if (gf_preamble)
+ val |= RX_GF_OR_MM;
- regs = (d11regs_t *) ai_switch_core(pi->sh->sih, D11_CORE_ID,
- &origidx, &intr_val);
- d11_clk_ctl_st = R_REG(&regs->clk_ctl_st);
- AND_REG(&regs->clk_ctl_st,
- ~(CCS_FORCEHT | CCS_HTAREQ));
+ write_phy_reg(pi, 0xed, val);
+}
- W_REG(&regs->clk_ctl_st, d11_clk_ctl_st);
+static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
+{
+ int j, type;
+ u16 addr_offset[] = { 0x186, 0x195, 0x2c5};
- ai_restore_core(pi->sh->sih, origidx, intr_val);
+ for (type = 0; type < 3; type++) {
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, addr_offset[type] + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
}
- pi->use_int_tx_iqlo_cal_nphy =
- (PHY_IPA(pi) ||
- (NREV_GE(pi->pubpi.phy_rev, 7) ||
- (NREV_GE(pi->pubpi.phy_rev, 5)
- && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL)));
-
- pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false;
-
- pi->nphy_deaf_count = 0;
-
- wlc_phy_tbl_init_nphy(pi);
-
- pi->nphy_crsminpwr_adjusted = false;
- pi->nphy_noisevars_adjusted = false;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- write_phy_reg(pi, 0xe7, 0);
- write_phy_reg(pi, 0xec, 0);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- write_phy_reg(pi, 0x342, 0);
- write_phy_reg(pi, 0x343, 0);
- write_phy_reg(pi, 0x346, 0);
- write_phy_reg(pi, 0x347, 0);
- }
- write_phy_reg(pi, 0xe5, 0);
- write_phy_reg(pi, 0xe6, 0);
+ if (pi->bw == WL_CHANSPEC_BW_40) {
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, 0x186 + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
} else {
- write_phy_reg(pi, 0xec, 0);
- }
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, 0x186 + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[5][j]);
+ }
- write_phy_reg(pi, 0x91, 0);
- write_phy_reg(pi, 0x92, 0);
- if (NREV_LT(pi->pubpi.phy_rev, 6)) {
- write_phy_reg(pi, 0x93, 0);
- write_phy_reg(pi, 0x94, 0);
+ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, 0x2c5 + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[6][j]);
+ }
}
+}
- and_phy_reg(pi, 0xa1, ~3);
+static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi)
+{
+ int j;
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- write_phy_reg(pi, 0x8f, 0);
- write_phy_reg(pi, 0xa5, 0);
+ if (pi->bw == WL_CHANSPEC_BW_40) {
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, 0x195 + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]);
} else {
- write_phy_reg(pi, 0xa5, 0);
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, 0x186 + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
}
+}
- if (NREV_IS(pi->pubpi.phy_rev, 2))
- mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
- else if (NREV_LT(pi->pubpi.phy_rev, 2))
- mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
-
- write_phy_reg(pi, 0x203, 32);
- write_phy_reg(pi, 0x201, 32);
-
- if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD)
- write_phy_reg(pi, 0x20d, 160);
- else
- write_phy_reg(pi, 0x20d, 184);
-
- write_phy_reg(pi, 0x13a, 200);
-
- write_phy_reg(pi, 0x70, 80);
-
- write_phy_reg(pi, 0x1ff, 48);
+static void
+wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys,
+ u8 len)
+{
+ u32 t1_offset, t2_offset;
+ u8 ctr;
+ u8 end_event =
+ NREV_GE(pi->pubpi.phy_rev,
+ 3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END;
+ u8 end_dly = 1;
- if (NREV_LT(pi->pubpi.phy_rev, 8)) {
- wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override);
- }
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
- wlc_phy_stf_chain_upd_nphy(pi);
+ t1_offset = cmd << 4;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8,
+ events);
+ t2_offset = t1_offset + 0x080;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8,
+ dlys);
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
- write_phy_reg(pi, 0x180, 0xaa8);
- write_phy_reg(pi, 0x181, 0x9a4);
+ for (ctr = len; ctr < 16; ctr++) {
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+ t1_offset + ctr, 8, &end_event);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+ t2_offset + ctr, 8, &end_dly);
}
- if (PHY_IPA(pi)) {
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (1) << 0);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 :
- 0x29c, (0x1ff << 7),
- (pi->nphy_papd_epsilon_offset[core]) << 7);
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
- }
+static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset)
+{
+ u16 lpf_bw_ctl_val = 0;
+ u16 rx2tx_lpf_rc_lut_offset = 0;
- wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+ if (offset == 0) {
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ rx2tx_lpf_rc_lut_offset = 0x159;
+ else
+ rx2tx_lpf_rc_lut_offset = 0x154;
} else {
-
- if (NREV_GE(pi->pubpi.phy_rev, 5)) {
- wlc_phy_extpa_set_tx_digi_filts_nphy(pi);
- }
+ rx2tx_lpf_rc_lut_offset = offset;
}
+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+ (u32) rx2tx_lpf_rc_lut_offset, 16,
+ &lpf_bw_ctl_val);
- wlc_phy_workarounds_nphy(pi);
-
- wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
-
- val = read_phy_reg(pi, 0x01);
- write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
- write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
- wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
-
- wlapi_bmac_macphyclk_set(pi->sh->physhim, ON);
-
- wlc_phy_pa_override_nphy(pi, OFF);
- wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
- wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
- wlc_phy_pa_override_nphy(pi, ON);
+ lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7;
- wlc_phy_classifier_nphy(pi, 0, 0);
- wlc_phy_clip_det_nphy(pi, 0, clip1_ths);
+ return lpf_bw_ctl_val;
+}
- if (CHSPEC_IS2G(pi->radio_chanspec))
- wlc_phy_bphy_init_nphy(pi);
+static void
+wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value,
+ u8 core_mask, u8 off, u8 override_id)
+{
+ u8 core_num;
+ u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0;
+ u8 val_shift = 0;
- tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
- wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ en_mask = field;
+ for (core_num = 0; core_num < 2; core_num++) {
+ if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) {
- wlc_phy_txpwr_fixpower_nphy(pi);
+ switch (field) {
+ case (0x1 << 2):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 1);
+ val_shift = 1;
+ break;
+ case (0x1 << 3):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 2);
+ val_shift = 2;
+ break;
+ case (0x1 << 4):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 4);
+ val_shift = 4;
+ break;
+ case (0x1 << 5):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 5);
+ val_shift = 5;
+ break;
+ case (0x1 << 6):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 6);
+ val_shift = 6;
+ break;
+ case (0x1 << 7):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a :
+ 0x7d;
+ val_mask = (0x1 << 7);
+ val_shift = 7;
+ break;
+ case (0x1 << 10):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0xf8 :
+ 0xfa;
+ val_mask = (0x7 << 4);
+ val_shift = 4;
+ break;
+ case (0x1 << 11):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7b :
+ 0x7e;
+ val_mask = (0xffff << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 12):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7c :
+ 0x7f;
+ val_mask = (0xffff << 0);
+ val_shift = 0;
+ break;
+ case (0x3 << 13):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x348 :
+ 0x349;
+ val_mask = (0xff << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 13):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x348 :
+ 0x349;
+ val_mask = (0xf << 0);
+ val_shift = 0;
+ break;
+ default:
+ addr = 0xffff;
+ break;
+ }
+ } else if (override_id ==
+ NPHY_REV7_RFCTRLOVERRIDE_ID1) {
- wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+ switch (field) {
+ case (0x1 << 1):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 1);
+ val_shift = 1;
+ break;
+ case (0x1 << 3):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 3);
+ val_shift = 3;
+ break;
+ case (0x1 << 5):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 5);
+ val_shift = 5;
+ break;
+ case (0x1 << 4):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 4);
+ val_shift = 4;
+ break;
+ case (0x1 << 2):
- wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 2);
+ val_shift = 2;
+ break;
+ case (0x1 << 7):
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- u32 *tx_pwrctrl_tbl = NULL;
- u16 idx;
- s16 pga_gn = 0;
- s16 pad_gn = 0;
- s32 rfpwr_offset = 0;
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x7 << 8);
+ val_shift = 8;
+ break;
+ case (0x1 << 11):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 14);
+ val_shift = 14;
+ break;
+ case (0x1 << 10):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 13);
+ val_shift = 13;
+ break;
+ case (0x1 << 9):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 12);
+ val_shift = 12;
+ break;
+ case (0x1 << 8):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 11);
+ val_shift = 11;
+ break;
+ case (0x1 << 6):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 6);
+ val_shift = 6;
+ break;
+ case (0x1 << 0):
+ en_addr = (core_num == 0) ? 0x342 :
+ 0x343;
+ val_addr = (core_num == 0) ? 0x340 :
+ 0x341;
+ val_mask = (0x1 << 0);
+ val_shift = 0;
+ break;
+ default:
+ addr = 0xffff;
+ break;
+ }
+ } else if (override_id ==
+ NPHY_REV7_RFCTRLOVERRIDE_ID2) {
- if (PHY_IPA(pi)) {
- tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi);
- } else {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (NREV_IS(pi->pubpi.phy_rev, 3)) {
- tx_pwrctrl_tbl =
- nphy_tpc_5GHz_txgain_rev3;
- } else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
- tx_pwrctrl_tbl =
- (pi->srom_fem5g.extpagain == 3) ?
- nphy_tpc_5GHz_txgain_HiPwrEPA :
- nphy_tpc_5GHz_txgain_rev4;
- } else {
- tx_pwrctrl_tbl =
- nphy_tpc_5GHz_txgain_rev5;
+ switch (field) {
+ case (0x1 << 3):
+ en_addr = (core_num == 0) ? 0x346 :
+ 0x347;
+ val_addr = (core_num == 0) ? 0x344 :
+ 0x345;
+ val_mask = (0x1 << 3);
+ val_shift = 3;
+ break;
+ case (0x1 << 1):
+ en_addr = (core_num == 0) ? 0x346 :
+ 0x347;
+ val_addr = (core_num == 0) ? 0x344 :
+ 0x345;
+ val_mask = (0x1 << 1);
+ val_shift = 1;
+ break;
+ case (0x1 << 0):
+ en_addr = (core_num == 0) ? 0x346 :
+ 0x347;
+ val_addr = (core_num == 0) ? 0x344 :
+ 0x345;
+ val_mask = (0x1 << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 2):
+ en_addr = (core_num == 0) ? 0x346 :
+ 0x347;
+ val_addr = (core_num == 0) ? 0x344 :
+ 0x345;
+ val_mask = (0x1 << 2);
+ val_shift = 2;
+ break;
+ case (0x1 << 4):
+ en_addr = (core_num == 0) ? 0x346 :
+ 0x347;
+ val_addr = (core_num == 0) ? 0x344 :
+ 0x345;
+ val_mask = (0x1 << 4);
+ val_shift = 4;
+ break;
+ default:
+ addr = 0xffff;
+ break;
}
+ }
+ if (off) {
+ and_phy_reg(pi, en_addr, ~en_mask);
+ and_phy_reg(pi, val_addr, ~val_mask);
} else {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (pi->pubpi.radiorev == 5) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_epa_2057rev5;
- } else if (pi->pubpi.radiorev == 3) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_epa_2057rev3;
- }
- } else {
- if (NREV_GE(pi->pubpi.phy_rev, 5) &&
- (pi->srom_fem2g.extpagain == 3)) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_HiPwrEPA;
- } else {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_rev3;
- }
+ if ((core_mask == 0)
+ || (core_mask & (1 << core_num))) {
+ or_phy_reg(pi, en_addr, en_mask);
+
+ if (addr != 0xffff)
+ mod_phy_reg(pi, val_addr,
+ val_mask,
+ (value <<
+ val_shift));
}
}
}
+ }
+}
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
- 192, 32, tx_pwrctrl_tbl);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
- 192, 32, tx_pwrctrl_tbl);
-
- pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000);
+static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi)
+{
+ uint core;
+ int ctr;
+ s16 gain_delta[2];
+ u8 curr_channel;
+ u16 minmax_gain[2];
+ u16 regval[4];
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
- for (idx = 0; idx < 128; idx++) {
- pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
- pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f;
+ if (pi->nphy_gain_boost) {
+ if ((CHSPEC_IS2G(pi->radio_chanspec))) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
- rfpwr_offset = (s16)
- nphy_papd_padgain_dlt_2g_2057rev3n4
- [pad_gn];
- } else if (pi->pubpi.radiorev == 5) {
- rfpwr_offset = (s16)
- nphy_papd_padgain_dlt_2g_2057rev5
- [pad_gn];
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev ==
- 8)) {
- rfpwr_offset = (s16)
- nphy_papd_padgain_dlt_2g_2057rev7
- [pad_gn];
- }
- } else {
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
- rfpwr_offset = (s16)
- nphy_papd_pgagain_dlt_5g_2057
- [pga_gn];
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev ==
- 8)) {
- rfpwr_offset = (s16)
- nphy_papd_pgagain_dlt_5g_2057rev7
- [pga_gn];
- }
- }
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_CORE1TXPWRCTL,
- 1, 576 + idx, 32,
- &rfpwr_offset);
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_CORE2TXPWRCTL,
- 1, 576 + idx, 32,
- &rfpwr_offset);
- }
+ gain_delta[0] = 6;
+ gain_delta[1] = 6;
} else {
- for (idx = 0; idx < 128; idx++) {
- pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- rfpwr_offset = (s16)
- nphy_papd_pga_gain_delta_ipa_2g
- [pga_gn];
- } else {
- rfpwr_offset = (s16)
- nphy_papd_pga_gain_delta_ipa_5g
- [pga_gn];
- }
-
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_CORE1TXPWRCTL,
- 1, 576 + idx, 32,
- &rfpwr_offset);
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_CORE2TXPWRCTL,
- 1, 576 + idx, 32,
- &rfpwr_offset);
- }
-
+ curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+ gain_delta[0] =
+ (s16)
+ PHY_HW_ROUND(((nphy_lnagain_est0[0] *
+ curr_channel) +
+ nphy_lnagain_est0[1]), 13);
+ gain_delta[1] =
+ (s16)
+ PHY_HW_ROUND(((nphy_lnagain_est1[0] *
+ curr_channel) +
+ nphy_lnagain_est1[1]), 13);
}
} else {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
- 192, 32, nphy_tpc_txgain);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
- 192, 32, nphy_tpc_txgain);
+ gain_delta[0] = 0;
+ gain_delta[1] = 0;
}
- if (pi->sh->phyrxchain != 0x3) {
- wlc_phy_rxcore_setstate_nphy((struct brcms_phy_pub *) pi,
- pi->sh->phyrxchain);
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+ if (pi->nphy_elna_gain_config) {
+
+ regval[0] = nphy_def_lnagains[2] + gain_delta[core];
+ regval[1] = nphy_def_lnagains[3] + gain_delta[core];
+ regval[2] = nphy_def_lnagains[3] + gain_delta[core];
+ regval[3] = nphy_def_lnagains[3] + gain_delta[core];
+ } else {
+ for (ctr = 0; ctr < 4; ctr++)
+ regval[ctr] =
+ nphy_def_lnagains[ctr] +
+ gain_delta[core];
+ }
+ wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval);
+
+ minmax_gain[core] =
+ (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4);
}
- if (PHY_PERICAL_MPHASE_PENDING(pi)) {
- wlc_phy_cal_perical_mphase_restart(pi);
+ mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0));
+ mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0));
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void
+wlc_phy_war_force_trsw_to_R_cliplo_nphy(struct brcms_phy *pi, u8 core)
+{
+ if (core == PHY_CORE_0) {
+ write_phy_reg(pi, 0x38, 0x4);
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ write_phy_reg(pi, 0x37, 0x0060);
+ else
+ write_phy_reg(pi, 0x37, 0x1080);
+ } else if (core == PHY_CORE_1) {
+ write_phy_reg(pi, 0x2ae, 0x4);
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ write_phy_reg(pi, 0x2ad, 0x0060);
+ else
+ write_phy_reg(pi, 0x2ad, 0x1080);
}
+}
- if (!NORADIO_ENAB(pi->pubpi)) {
- bool do_rssi_cal = false;
+static void wlc_phy_war_txchain_upd_nphy(struct brcms_phy *pi, u8 txchain)
+{
+ u8 txchain0, txchain1;
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
- (pi->nphy_rssical_chanspec_2G == 0) :
- (pi->nphy_rssical_chanspec_5G == 0);
+ txchain0 = txchain & 0x1;
+ txchain1 = (txchain & 0x2) >> 1;
+ if (!txchain0)
+ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
- if (do_rssi_cal) {
- wlc_phy_rssi_cal_nphy(pi);
- } else {
- wlc_phy_restore_rssical_nphy(pi);
- }
- } else {
- wlc_phy_rssi_cal_nphy(pi);
- }
+ if (!txchain1)
+ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+}
- if (!SCAN_RM_IN_PROGRESS(pi)) {
- do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
- (pi->nphy_iqcal_chanspec_2G == 0) :
- (pi->nphy_iqcal_chanspec_5G == 0);
- }
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi)
+{
+ s8 lna1_gain_db[] = { 8, 13, 17, 22 };
+ s8 lna2_gain_db[] = { -2, 7, 11, 15 };
+ s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 };
+ s8 tia_gainbits[] = {
+ 0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
- if (!pi->do_initcal)
- do_nphy_cal = false;
+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
- if (do_nphy_cal) {
+ mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
- target_gain = wlc_phy_get_tx_gain_nphy(pi);
+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0));
+ mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0));
- if (pi->antsel_type == ANTSEL_2x3)
- wlc_phy_antsel_init((struct brcms_phy_pub *) pi,
- true);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8,
+ lna1_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8,
+ lna1_gain_db);
- if (pi->nphy_perical != PHY_PERICAL_MPHASE) {
- wlc_phy_rssi_cal_nphy(pi);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8,
+ lna2_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8,
+ lna2_gain_db);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- pi->nphy_cal_orig_pwr_idx[0] =
- pi->nphy_txpwrindex[PHY_CORE_0].
- index_internal;
- pi->nphy_cal_orig_pwr_idx[1] =
- pi->nphy_txpwrindex[PHY_CORE_1].
- index_internal;
-
- wlc_phy_precal_txgain_nphy(pi);
- target_gain =
- wlc_phy_get_tx_gain_nphy(pi);
- }
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+ tia_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+ tia_gain_db);
- if (wlc_phy_cal_txiqlo_nphy
- (pi, target_gain, true, false) == 0) {
- if (wlc_phy_cal_rxiq_nphy
- (pi, target_gain, 2,
- false) == 0) {
- wlc_phy_savecal_nphy(pi);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+ tia_gainbits);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+ tia_gainbits);
- }
- }
- } else if (pi->mphase_cal_phase_id ==
- MPHASE_CAL_STATE_IDLE) {
+ write_phy_reg(pi, 0x37, 0x74);
+ write_phy_reg(pi, 0x2ad, 0x74);
+ write_phy_reg(pi, 0x38, 0x18);
+ write_phy_reg(pi, 0x2ae, 0x18);
- wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
- PHY_PERICAL_PHYINIT);
- }
- } else {
- wlc_phy_restorecal_nphy(pi);
- }
- }
+ write_phy_reg(pi, 0x2b, 0xe8);
+ write_phy_reg(pi, 0x41, 0xe8);
- wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
- wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+ mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0));
+ mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0));
+ } else {
- wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy);
+ mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0));
+ mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0));
+ }
+}
- if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6))
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
+{
+ u16 currband;
+ s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
+ s8 *lna1_gain_db = NULL;
+ s8 *lna1_gain_db_2 = NULL;
+ s8 *lna2_gain_db = NULL;
+ s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
+ s8 *tia_gain_db;
+ s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
+ s8 *tia_gainbits;
+ u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
+ u16 *rfseq_init_gain;
+ u16 init_gaincode;
+ u16 clip1hi_gaincode;
+ u16 clip1md_gaincode = 0;
+ u16 clip1md_gaincode_B;
+ u16 clip1lo_gaincode;
+ u16 clip1lo_gaincode_B;
+ u8 crsminl_th = 0;
+ u8 crsminu_th;
+ u16 nbclip_th = 0;
+ u8 w1clip_th;
+ u16 freq;
+ s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0;
+ u8 chg_nbclip_th = 0;
- write_phy_reg(pi, 0x70, 50);
+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
- wlc_phy_txlpfbw_nphy(pi);
+ currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+ if (currband == 0) {
- wlc_phy_spurwar_nphy(pi);
+ lna1_gain_db = lna1G_gain_db_rev7;
-}
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+ lna1_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+ lna1_gain_db);
-static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble)
-{
- bool gf_preamble = false;
- u16 val;
+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0));
- if (preamble == BRCMS_N_PREAMBLE_GF)
- gf_preamble = true;
+ if (CHSPEC_IS40(pi->radio_chanspec)) {
+ mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0));
+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0));
+ }
- val = read_phy_reg(pi, 0xed);
+ mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
- val |= RX_GF_MM_AUTO;
- val &= ~RX_GF_OR_MM;
- if (gf_preamble)
- val |= RX_GF_OR_MM;
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
+ mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0));
+ mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0));
+ }
+ } else {
- write_phy_reg(pi, 0xed, val);
-}
+ init_gaincode = 0x9e;
+ clip1hi_gaincode = 0x9e;
+ clip1md_gaincode_B = 0x24;
+ clip1lo_gaincode = 0x8a;
+ clip1lo_gaincode_B = 8;
+ rfseq_init_gain = rfseqA_init_gain_rev7;
-static void wlc_phy_resetcca_nphy(struct brcms_phy *pi)
-{
- u16 val;
+ tia_gain_db = tiaA_gain_db_rev7;
+ tia_gainbits = tiaA_gainbits_rev7;
- wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+ freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
- val = read_phy_reg(pi, 0x01);
- write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
- udelay(1);
- write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+ w1clip_th = 25;
+ clip1md_gaincode = 0x82;
- wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+ if ((freq <= 5080) || (freq == 5825)) {
- wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-}
+ s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
+ s8 lna1A_gain_db_2_rev7[] = {
+ 11, 17, 22, 25};
+ s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
-void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en)
-{
- u16 rfctrlintc_override_val;
+ crsminu_th = 0x3e;
+ lna1_gain_db = lna1A_gain_db_rev7;
+ lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+ lna2_gain_db = lna2A_gain_db_rev7;
+ } else if ((freq >= 5500) && (freq <= 5700)) {
- if (!en) {
+ s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
+ s8 lna1A_gain_db_2_rev7[] = {
+ 12, 18, 22, 26};
+ s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
- pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91);
- pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92);
+ crsminu_th = 0x45;
+ clip1md_gaincode_B = 0x14;
+ nbclip_th = 0xff;
+ chg_nbclip_th = 1;
+ lna1_gain_db = lna1A_gain_db_rev7;
+ lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+ lna2_gain_db = lna2A_gain_db_rev7;
+ } else {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- rfctrlintc_override_val = 0x1480;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- rfctrlintc_override_val =
- CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480;
+ s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
+ s8 lna1A_gain_db_2_rev7[] = {
+ 12, 18, 22, 26};
+ s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+
+ crsminu_th = 0x41;
+ lna1_gain_db = lna1A_gain_db_rev7;
+ lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+ lna2_gain_db = lna2A_gain_db_rev7;
+ }
+
+ if (freq <= 4920) {
+ nvar_baseline_offset0 = 5;
+ nvar_baseline_offset1 = 5;
+ } else if ((freq > 4920) && (freq <= 5320)) {
+ nvar_baseline_offset0 = 3;
+ nvar_baseline_offset1 = 5;
+ } else if ((freq > 5320) && (freq <= 5700)) {
+ nvar_baseline_offset0 = 3;
+ nvar_baseline_offset1 = 2;
+ } else {
+ nvar_baseline_offset0 = 4;
+ nvar_baseline_offset1 = 0;
+ }
} else {
- rfctrlintc_override_val =
- CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+
+ crsminu_th = 0x3a;
+ crsminl_th = 0x3a;
+ w1clip_th = 20;
+
+ if ((freq >= 4920) && (freq <= 5320)) {
+ nvar_baseline_offset0 = 4;
+ nvar_baseline_offset1 = 5;
+ } else if ((freq > 5320) && (freq <= 5550)) {
+ nvar_baseline_offset0 = 4;
+ nvar_baseline_offset1 = 2;
+ } else {
+ nvar_baseline_offset0 = 5;
+ nvar_baseline_offset1 = 3;
+ }
}
- write_phy_reg(pi, 0x91, rfctrlintc_override_val);
- write_phy_reg(pi, 0x92, rfctrlintc_override_val);
- } else {
+ write_phy_reg(pi, 0x20, init_gaincode);
+ write_phy_reg(pi, 0x2a7, init_gaincode);
- write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save);
- write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save);
- }
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+ pi->pubpi.phy_corenum, 0x106, 16,
+ rfseq_init_gain);
-}
+ write_phy_reg(pi, 0x22, clip1hi_gaincode);
+ write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
-void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi)
-{
+ write_phy_reg(pi, 0x36, clip1md_gaincode_B);
+ write_phy_reg(pi, 0x2ac, clip1md_gaincode_B);
- u16 txrx_chain =
- (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1);
- bool CoreActv_override = false;
+ write_phy_reg(pi, 0x37, clip1lo_gaincode);
+ write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+ write_phy_reg(pi, 0x38, clip1lo_gaincode_B);
+ write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B);
- if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN0) {
- txrx_chain = NPHY_RfseqCoreActv_TxRxChain0;
- CoreActv_override = true;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+ tia_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+ tia_gain_db);
- if (NREV_LE(pi->pubpi.phy_rev, 2)) {
- and_phy_reg(pi, 0xa0, ~0x20);
- }
- } else if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN1) {
- txrx_chain = NPHY_RfseqCoreActv_TxRxChain1;
- CoreActv_override = true;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+ tia_gainbits);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+ tia_gainbits);
- if (NREV_LE(pi->pubpi.phy_rev, 2)) {
- or_phy_reg(pi, 0xa0, 0x20);
+ mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+
+ if (chg_nbclip_th == 1) {
+ write_phy_reg(pi, 0x2b, nbclip_th);
+ write_phy_reg(pi, 0x41, nbclip_th);
}
- }
- mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain);
+ mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0));
+ mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0));
- if (CoreActv_override) {
+ mod_phy_reg(pi, 0x2e4,
+ (0x3f << 0), (nvar_baseline_offset0 << 0));
- pi->nphy_perical = PHY_PERICAL_DISABLE;
- or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
- } else {
- pi->nphy_perical = PHY_PERICAL_MPHASE;
- and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override);
+ mod_phy_reg(pi, 0x2e4,
+ (0x3f << 6), (nvar_baseline_offset1 << 6));
+
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+ lna1_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+ lna1_gain_db_2);
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+ 8, lna2_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+ 8, lna2_gain_db);
+
+ write_phy_reg(pi, 0x24, clip1md_gaincode);
+ write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+ } else {
+ mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+ }
}
}
-void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask)
+static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi)
{
- u16 regval;
- u16 tbl_buf[16];
- uint i;
- struct brcms_phy *pi = (struct brcms_phy *) pih;
- u16 tbl_opcode;
- bool suspend;
+ u16 w1th, hpf_code, currband;
+ int ctr;
+ u8 rfseq_updategainu_events[] = {
+ NPHY_RFSEQ_CMD_RX_GAIN,
+ NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
+ NPHY_RFSEQ_CMD_SET_HPF_BW
+ };
+ u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
+ s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
+ s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
+ s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
+ s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
+ s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
+ s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
+ s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
+ s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
+ s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
+ s8 *lna1_gain_db = NULL;
+ s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
+ s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
+ s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
+ s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
+ s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
+ s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
+ s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
+ s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
+ s8 *lna2_gain_db = NULL;
+ s8 tiaG_gain_db[] = {
+ 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
+ s8 tiaA_gain_db[] = {
+ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
+ s8 tiaA_gain_db_rev4[] = {
+ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+ s8 tiaA_gain_db_rev5[] = {
+ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+ s8 tiaA_gain_db_rev6[] = {
+ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+ s8 *tia_gain_db;
+ s8 tiaG_gainbits[] = {
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+ s8 tiaA_gainbits[] = {
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
+ s8 tiaA_gainbits_rev4[] = {
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+ s8 tiaA_gainbits_rev5[] = {
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+ s8 tiaA_gainbits_rev6[] = {
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+ s8 *tia_gainbits;
+ s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
+ s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
+ u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
+ u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
+ u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
+ u16 rfseqG_init_gain_rev5_elna[] = {
+ 0x013f, 0x013f, 0x013f, 0x013f };
+ u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
+ u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
+ u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
+ u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
+ u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
+ u16 rfseqA_init_gain_rev4_elna[] = {
+ 0x314f, 0x314f, 0x314f, 0x314f };
+ u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
+ u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
+ u16 *rfseq_init_gain;
+ u16 initG_gaincode = 0x627e;
+ u16 initG_gaincode_rev4 = 0x527e;
+ u16 initG_gaincode_rev5 = 0x427e;
+ u16 initG_gaincode_rev5_elna = 0x027e;
+ u16 initG_gaincode_rev6 = 0x527e;
+ u16 initG_gaincode_rev6_224B0 = 0x427e;
+ u16 initG_gaincode_rev6_elna = 0x127e;
+ u16 initA_gaincode = 0x52de;
+ u16 initA_gaincode_rev4 = 0x629e;
+ u16 initA_gaincode_rev4_elna = 0x329e;
+ u16 initA_gaincode_rev5 = 0x729e;
+ u16 initA_gaincode_rev6 = 0x729e;
+ u16 init_gaincode;
+ u16 clip1hiG_gaincode = 0x107e;
+ u16 clip1hiG_gaincode_rev4 = 0x007e;
+ u16 clip1hiG_gaincode_rev5 = 0x1076;
+ u16 clip1hiG_gaincode_rev6 = 0x007e;
+ u16 clip1hiA_gaincode = 0x00de;
+ u16 clip1hiA_gaincode_rev4 = 0x029e;
+ u16 clip1hiA_gaincode_rev5 = 0x029e;
+ u16 clip1hiA_gaincode_rev6 = 0x029e;
+ u16 clip1hi_gaincode;
+ u16 clip1mdG_gaincode = 0x0066;
+ u16 clip1mdA_gaincode = 0x00ca;
+ u16 clip1mdA_gaincode_rev4 = 0x1084;
+ u16 clip1mdA_gaincode_rev5 = 0x2084;
+ u16 clip1mdA_gaincode_rev6 = 0x2084;
+ u16 clip1md_gaincode = 0;
+ u16 clip1loG_gaincode = 0x0074;
+ u16 clip1loG_gaincode_rev5[] = {
+ 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
+ };
+ u16 clip1loG_gaincode_rev6[] = {
+ 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
+ };
+ u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
+ u16 clip1loA_gaincode = 0x00cc;
+ u16 clip1loA_gaincode_rev4 = 0x0086;
+ u16 clip1loA_gaincode_rev5 = 0x2086;
+ u16 clip1loA_gaincode_rev6 = 0x2086;
+ u16 clip1lo_gaincode;
+ u8 crsminG_th = 0x18;
+ u8 crsminG_th_rev5 = 0x18;
+ u8 crsminG_th_rev6 = 0x18;
+ u8 crsminA_th = 0x1e;
+ u8 crsminA_th_rev4 = 0x24;
+ u8 crsminA_th_rev5 = 0x24;
+ u8 crsminA_th_rev6 = 0x24;
+ u8 crsmin_th;
+ u8 crsminlG_th = 0x18;
+ u8 crsminlG_th_rev5 = 0x18;
+ u8 crsminlG_th_rev6 = 0x18;
+ u8 crsminlA_th = 0x1e;
+ u8 crsminlA_th_rev4 = 0x24;
+ u8 crsminlA_th_rev5 = 0x24;
+ u8 crsminlA_th_rev6 = 0x24;
+ u8 crsminl_th = 0;
+ u8 crsminuG_th = 0x18;
+ u8 crsminuG_th_rev5 = 0x18;
+ u8 crsminuG_th_rev6 = 0x18;
+ u8 crsminuA_th = 0x1e;
+ u8 crsminuA_th_rev4 = 0x24;
+ u8 crsminuA_th_rev5 = 0x24;
+ u8 crsminuA_th_rev6 = 0x24;
+ u8 crsminuA_th_rev6_224B0 = 0x2d;
+ u8 crsminu_th;
+ u16 nbclipG_th = 0x20d;
+ u16 nbclipG_th_rev4 = 0x1a1;
+ u16 nbclipG_th_rev5 = 0x1d0;
+ u16 nbclipG_th_rev6 = 0x1d0;
+ u16 nbclipA_th = 0x1a1;
+ u16 nbclipA_th_rev4 = 0x107;
+ u16 nbclipA_th_rev5 = 0x0a9;
+ u16 nbclipA_th_rev6 = 0x0f0;
+ u16 nbclip_th = 0;
+ u8 w1clipG_th = 5;
+ u8 w1clipG_th_rev5 = 9;
+ u8 w1clipG_th_rev6 = 5;
+ u8 w1clipA_th = 25, w1clip_th;
+ u8 rssi_gain_default = 0x50;
+ u8 rssiG_gain_rev6_224B0 = 0x50;
+ u8 rssiA_gain_rev5 = 0x90;
+ u8 rssiA_gain_rev6 = 0x90;
+ u8 rssi_gain;
+ u16 regval[21];
+ u8 triso;
- pi->sh->phyrxchain = rxcore_bitmask;
+ triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso :
+ pi->srom_fem2g.triso;
- if (!pi->sh->clk)
- return;
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (pi->pubpi.radiorev == 5) {
+ wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi);
+ } else if (pi->pubpi.radiorev == 7) {
+ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
- suspend =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
- if (!suspend)
- wlapi_suspend_mac_and_wait(pi->sh->physhim);
+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0));
+ mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0));
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
+ } else if ((pi->pubpi.radiorev == 3)
+ || (pi->pubpi.radiorev == 8)) {
+ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
- regval = read_phy_reg(pi, 0xa2);
- regval &= ~(0xf << 4);
- regval |= ((u16) (rxcore_bitmask & 0x3)) << 4;
- write_phy_reg(pi, 0xa2, regval);
+ if (pi->pubpi.radiorev == 8) {
+ mod_phy_reg(pi, 0x283,
+ (0xff << 0), (0x44 << 0));
+ mod_phy_reg(pi, 0x280,
+ (0xff << 0), (0x44 << 0));
+ }
+ } else {
+ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+ }
+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if ((rxcore_bitmask & 0x3) != 0x3) {
+ mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6));
- write_phy_reg(pi, 0x20e, 1);
+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if (pi->rx2tx_biasentry == -1) {
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ,
- ARRAY_SIZE(tbl_buf), 80,
- 16, tbl_buf);
+ currband =
+ read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+ if (currband == 0) {
+ if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+ if (pi->pubpi.radiorev == 11) {
+ lna1_gain_db = lna1G_gain_db_rev6_224B0;
+ lna2_gain_db = lna2G_gain_db_rev6_224B0;
+ rfseq_init_gain =
+ rfseqG_init_gain_rev6_224B0;
+ init_gaincode =
+ initG_gaincode_rev6_224B0;
+ clip1hi_gaincode =
+ clip1hiG_gaincode_rev6;
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6_224B0;
+ nbclip_th = nbclipG_th_rev6;
+ w1clip_th = w1clipG_th_rev6;
+ crsmin_th = crsminG_th_rev6;
+ crsminl_th = crsminlG_th_rev6;
+ crsminu_th = crsminuG_th_rev6;
+ rssi_gain = rssiG_gain_rev6_224B0;
+ } else {
+ lna1_gain_db = lna1G_gain_db_rev6;
+ lna2_gain_db = lna2G_gain_db_rev6;
+ if (pi->sh->boardflags & BFL_EXTLNA) {
- for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) {
- if (tbl_buf[i] ==
- NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) {
+ rfseq_init_gain =
+ rfseqG_init_gain_rev6_elna;
+ init_gaincode =
+ initG_gaincode_rev6_elna;
+ } else {
+ rfseq_init_gain =
+ rfseqG_init_gain_rev6;
+ init_gaincode =
+ initG_gaincode_rev6;
+ }
+ clip1hi_gaincode =
+ clip1hiG_gaincode_rev6;
+ switch (triso) {
+ case 0:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [0];
+ break;
+ case 1:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [1];
+ break;
+ case 2:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [2];
+ break;
+ case 3:
+ default:
- pi->rx2tx_biasentry = (u8) i;
- tbl_opcode =
- NPHY_REV3_RFSEQ_CMD_NOP;
- wlc_phy_table_write_nphy(pi,
- NPHY_TBL_ID_RFSEQ,
- 1, i,
- 16,
- &tbl_opcode);
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [3];
break;
- } else if (tbl_buf[i] ==
- NPHY_REV3_RFSEQ_CMD_END) {
+ case 4:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [4];
+ break;
+ case 5:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [5];
+ break;
+ case 6:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [6];
+ break;
+ case 7:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev6
+ [7];
break;
}
+ nbclip_th = nbclipG_th_rev6;
+ w1clip_th = w1clipG_th_rev6;
+ crsmin_th = crsminG_th_rev6;
+ crsminl_th = crsminlG_th_rev6;
+ crsminu_th = crsminuG_th_rev6;
+ rssi_gain = rssi_gain_default;
+ }
+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+ lna1_gain_db = lna1G_gain_db_rev5;
+ lna2_gain_db = lna2G_gain_db_rev5;
+ if (pi->sh->boardflags & BFL_EXTLNA) {
+
+ rfseq_init_gain =
+ rfseqG_init_gain_rev5_elna;
+ init_gaincode =
+ initG_gaincode_rev5_elna;
+ } else {
+ rfseq_init_gain = rfseqG_init_gain_rev5;
+ init_gaincode = initG_gaincode_rev5;
}
+ clip1hi_gaincode = clip1hiG_gaincode_rev5;
+ switch (triso) {
+ case 0:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[0];
+ break;
+ case 1:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[1];
+ break;
+ case 2:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[2];
+ break;
+ case 3:
+
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[3];
+ break;
+ case 4:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[4];
+ break;
+ case 5:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[5];
+ break;
+ case 6:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[6];
+ break;
+ case 7:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[7];
+ break;
+ default:
+ clip1lo_gaincode =
+ clip1loG_gaincode_rev5[3];
+ break;
+ }
+ nbclip_th = nbclipG_th_rev5;
+ w1clip_th = w1clipG_th_rev5;
+ crsmin_th = crsminG_th_rev5;
+ crsminl_th = crsminlG_th_rev5;
+ crsminu_th = crsminuG_th_rev5;
+ rssi_gain = rssi_gain_default;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+ lna1_gain_db = lna1G_gain_db_rev4;
+ lna2_gain_db = lna2G_gain_db;
+ rfseq_init_gain = rfseqG_init_gain_rev4;
+ init_gaincode = initG_gaincode_rev4;
+ clip1hi_gaincode = clip1hiG_gaincode_rev4;
+ clip1lo_gaincode = clip1loG_gaincode;
+ nbclip_th = nbclipG_th_rev4;
+ w1clip_th = w1clipG_th;
+ crsmin_th = crsminG_th;
+ crsminl_th = crsminlG_th;
+ crsminu_th = crsminuG_th;
+ rssi_gain = rssi_gain_default;
+ } else {
+ lna1_gain_db = lna1G_gain_db;
+ lna2_gain_db = lna2G_gain_db;
+ rfseq_init_gain = rfseqG_init_gain;
+ init_gaincode = initG_gaincode;
+ clip1hi_gaincode = clip1hiG_gaincode;
+ clip1lo_gaincode = clip1loG_gaincode;
+ nbclip_th = nbclipG_th;
+ w1clip_th = w1clipG_th;
+ crsmin_th = crsminG_th;
+ crsminl_th = crsminlG_th;
+ crsminu_th = crsminuG_th;
+ rssi_gain = rssi_gain_default;
}
- }
- } else {
+ tia_gain_db = tiaG_gain_db;
+ tia_gainbits = tiaG_gainbits;
+ clip1md_gaincode = clip1mdG_gaincode;
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+ lna1_gain_db = lna1A_gain_db_rev6;
+ lna2_gain_db = lna2A_gain_db_rev6;
+ tia_gain_db = tiaA_gain_db_rev6;
+ tia_gainbits = tiaA_gainbits_rev6;
+ rfseq_init_gain = rfseqA_init_gain_rev6;
+ init_gaincode = initA_gaincode_rev6;
+ clip1hi_gaincode = clip1hiA_gaincode_rev6;
+ clip1md_gaincode = clip1mdA_gaincode_rev6;
+ clip1lo_gaincode = clip1loA_gaincode_rev6;
+ crsmin_th = crsminA_th_rev6;
+ crsminl_th = crsminlA_th_rev6;
+ if ((pi->pubpi.radiorev == 11) &&
+ (CHSPEC_IS40(pi->radio_chanspec) == 0))
+ crsminu_th = crsminuA_th_rev6_224B0;
+ else
+ crsminu_th = crsminuA_th_rev6;
- write_phy_reg(pi, 0x20e, 30);
+ nbclip_th = nbclipA_th_rev6;
+ rssi_gain = rssiA_gain_rev6;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+ lna1_gain_db = lna1A_gain_db_rev5;
+ lna2_gain_db = lna2A_gain_db_rev5;
+ tia_gain_db = tiaA_gain_db_rev5;
+ tia_gainbits = tiaA_gainbits_rev5;
+ rfseq_init_gain = rfseqA_init_gain_rev5;
+ init_gaincode = initA_gaincode_rev5;
+ clip1hi_gaincode = clip1hiA_gaincode_rev5;
+ clip1md_gaincode = clip1mdA_gaincode_rev5;
+ clip1lo_gaincode = clip1loA_gaincode_rev5;
+ crsmin_th = crsminA_th_rev5;
+ crsminl_th = crsminlA_th_rev5;
+ crsminu_th = crsminuA_th_rev5;
+ nbclip_th = nbclipA_th_rev5;
+ rssi_gain = rssiA_gain_rev5;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+ lna1_gain_db = lna1A_gain_db_rev4;
+ lna2_gain_db = lna2A_gain_db_rev4;
+ tia_gain_db = tiaA_gain_db_rev4;
+ tia_gainbits = tiaA_gainbits_rev4;
+ if (pi->sh->boardflags & BFL_EXTLNA_5GHz) {
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if (pi->rx2tx_biasentry != -1) {
- tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1, pi->rx2tx_biasentry,
- 16, &tbl_opcode);
- pi->rx2tx_biasentry = -1;
+ rfseq_init_gain =
+ rfseqA_init_gain_rev4_elna;
+ init_gaincode =
+ initA_gaincode_rev4_elna;
+ } else {
+ rfseq_init_gain = rfseqA_init_gain_rev4;
+ init_gaincode = initA_gaincode_rev4;
+ }
+ clip1hi_gaincode = clip1hiA_gaincode_rev4;
+ clip1md_gaincode = clip1mdA_gaincode_rev4;
+ clip1lo_gaincode = clip1loA_gaincode_rev4;
+ crsmin_th = crsminA_th_rev4;
+ crsminl_th = crsminlA_th_rev4;
+ crsminu_th = crsminuA_th_rev4;
+ nbclip_th = nbclipA_th_rev4;
+ rssi_gain = rssi_gain_default;
+ } else {
+ lna1_gain_db = lna1A_gain_db;
+ lna2_gain_db = lna2A_gain_db;
+ tia_gain_db = tiaA_gain_db;
+ tia_gainbits = tiaA_gainbits;
+ rfseq_init_gain = rfseqA_init_gain;
+ init_gaincode = initA_gaincode;
+ clip1hi_gaincode = clip1hiA_gaincode;
+ clip1md_gaincode = clip1mdA_gaincode;
+ clip1lo_gaincode = clip1loA_gaincode;
+ crsmin_th = crsminA_th;
+ crsminl_th = crsminlA_th;
+ crsminu_th = crsminuA_th;
+ nbclip_th = nbclipA_th;
+ rssi_gain = rssi_gain_default;
}
+ w1clip_th = w1clipA_th;
}
- }
- wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+ write_radio_reg(pi,
+ (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+ RADIO_2056_RX0), 0x17);
+ write_radio_reg(pi,
+ (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+ RADIO_2056_RX1), 0x17);
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
+ write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0),
+ 0xf0);
+ write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1),
+ 0xf0);
- if (!suspend)
- wlapi_enable_mac(pi->sh->physhim);
-}
+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0),
+ 0x0);
+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1),
+ 0x0);
-u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih)
-{
- u16 regval, rxen_bits;
- struct brcms_phy *pi = (struct brcms_phy *) pih;
+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0),
+ rssi_gain);
+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1),
+ rssi_gain);
- regval = read_phy_reg(pi, 0xa2);
- rxen_bits = (regval >> 4) & 0xf;
+ write_radio_reg(pi,
+ (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+ RADIO_2056_RX0), 0x17);
+ write_radio_reg(pi,
+ (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+ RADIO_2056_RX1), 0x17);
- return (u8) rxen_bits;
-}
+ write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0),
+ 0xFF);
+ write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1),
+ 0xFF);
-bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pi)
-{
- return PHY_IPA(pi);
-}
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8,
+ 8, lna1_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8,
+ 8, lna1_gain_db);
-static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi)
-{
- u8 idx, idx2, i, delta_ind;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+ 8, lna2_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+ 8, lna2_gain_db);
- for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) {
- pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx];
- }
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20,
+ 8, tia_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20,
+ 8, tia_gain_db);
- for (i = 0; i < 4; i++) {
- idx2 = 0;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20,
+ 8, tia_gainbits);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20,
+ 8, tia_gainbits);
- delta_ind = 0;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40,
+ 8, &lpf_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40,
+ 8, &lpf_gain_db);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40,
+ 8, &lpf_gainbits);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40,
+ 8, &lpf_gainbits);
- switch (i) {
- case 0:
+ write_phy_reg(pi, 0x20, init_gaincode);
+ write_phy_reg(pi, 0x2a7, init_gaincode);
- if (CHSPEC_IS40(pi->radio_chanspec)
- && NPHY_IS_SROM_REINTERPRET) {
- idx = TXP_FIRST_MCS_40_SISO;
- } else {
- idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
- TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM;
- delta_ind = 1;
- }
- break;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+ pi->pubpi.phy_corenum, 0x106, 16,
+ rfseq_init_gain);
- case 1:
+ write_phy_reg(pi, 0x22, clip1hi_gaincode);
+ write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
- idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
- TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD;
- break;
+ write_phy_reg(pi, 0x24, clip1md_gaincode);
+ write_phy_reg(pi, 0x2ab, clip1md_gaincode);
- case 2:
+ write_phy_reg(pi, 0x37, clip1lo_gaincode);
+ write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
- idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
- TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC;
- break;
+ mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0));
+ mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+ mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
- case 3:
+ write_phy_reg(pi, 0x2b, nbclip_th);
+ write_phy_reg(pi, 0x41, nbclip_th);
- idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
- TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM;
- break;
+ mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0));
+ mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0));
+
+ write_phy_reg(pi, 0x150, 0x809c);
+
+ } else {
+
+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+ write_phy_reg(pi, 0x2b, 0x84);
+ write_phy_reg(pi, 0x41, 0x84);
+
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
+ write_phy_reg(pi, 0x6b, 0x2b);
+ write_phy_reg(pi, 0x6c, 0x2b);
+ write_phy_reg(pi, 0x6d, 0x9);
+ write_phy_reg(pi, 0x6e, 0x9);
}
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- idx = idx + delta_ind;
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
+ w1th = NPHY_RSSICAL_W1_TARGET - 4;
+ mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0));
+ mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0));
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
+ if (CHSPEC_IS20(pi->radio_chanspec)) {
+ mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0));
+ mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0));
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
+ mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0));
+ mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0));
+ }
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx++];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- idx = idx + 1 - delta_ind;
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
+ write_phy_reg(pi, 0x150, 0x809c);
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
- pi->tx_power_offset[idx];
- }
-}
+ if (pi->nphy_gain_boost)
+ if ((CHSPEC_IS2G(pi->radio_chanspec)) &&
+ (CHSPEC_IS40(pi->radio_chanspec)))
+ hpf_code = 4;
+ else
+ hpf_code = 5;
+ else if (CHSPEC_IS40(pi->radio_chanspec))
+ hpf_code = 6;
+ else
+ hpf_code = 7;
-void wlc_phy_cal_init_nphy(struct brcms_phy *pi)
-{
-}
+ mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7));
+ mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7));
-static void
-wlc_phy_war_force_trsw_to_R_cliplo_nphy(struct brcms_phy *pi, u8 core)
-{
- if (core == PHY_CORE_0) {
- write_phy_reg(pi, 0x38, 0x4);
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- write_phy_reg(pi, 0x37, 0x0060);
- } else {
- write_phy_reg(pi, 0x37, 0x1080);
+ for (ctr = 0; ctr < 4; ctr++)
+ regval[ctr] = (hpf_code << 8) | 0x7c;
+ wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+
+ wlc_phy_adjust_lnagaintbl_nphy(pi);
+
+ if (pi->nphy_elna_gain_config) {
+ regval[0] = 0;
+ regval[1] = 1;
+ regval[2] = 1;
+ regval[3] = 1;
+ wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval);
+ wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval);
+
+ for (ctr = 0; ctr < 4; ctr++)
+ regval[ctr] = (hpf_code << 8) | 0x74;
+ wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
}
- } else if (core == PHY_CORE_1) {
- write_phy_reg(pi, 0x2ae, 0x4);
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- write_phy_reg(pi, 0x2ad, 0x0060);
- } else {
- write_phy_reg(pi, 0x2ad, 0x1080);
+
+ if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+ for (ctr = 0; ctr < 21; ctr++)
+ regval[ctr] = 3 * ctr;
+ wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval);
+ wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval);
+
+ for (ctr = 0; ctr < 21; ctr++)
+ regval[ctr] = (u16) ctr;
+ wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval);
+ wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval);
}
- }
-}
-static void wlc_phy_war_txchain_upd_nphy(struct brcms_phy *pi, u8 txchain)
-{
- u8 txchain0, txchain1;
+ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU,
+ rfseq_updategainu_events,
+ rfseq_updategainu_dlys,
+ sizeof(rfseq_updategainu_events) /
+ sizeof(rfseq_updategainu_events[0]));
- txchain0 = txchain & 0x1;
- txchain1 = (txchain & 0x2) >> 1;
- if (!txchain0) {
- wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
- }
+ mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8));
- if (!txchain1) {
- wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ mod_phy_reg(pi,
+ (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES),
+ 0x7f, 0x4);
}
}
@@ -15362,11 +16312,10 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
u16 freq;
int coreNum;
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0);
- } else {
+ else
wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1);
- }
if (pi->phyhang_avoid)
wlc_phy_stay_in_carriersearch_nphy(pi, true);
@@ -15401,9 +16350,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
write_phy_reg(pi, 0x240, 0x1b0);
}
- if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 8))
mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
- }
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
&dac_control);
@@ -15422,7 +16370,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16,
rfseq_rx2tx_dacbufpu_rev7);
- if (PHY_IPA(pi)) {
+ if (PHY_IPA(pi))
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
rfseq_rx2tx_events_rev3_ipa,
rfseq_rx2tx_dlys_rev3_ipa,
@@ -15431,7 +16379,6 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
sizeof
(rfseq_rx2tx_events_rev3_ipa
[0]));
- }
mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14));
mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
@@ -15448,11 +16395,13 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
|| (pi->pubpi.radiorev == 8)) {
rccal_bcap_val =
- read_radio_reg(pi,
- RADIO_2057_RCCAL_BCAP_VAL);
+ read_radio_reg(
+ pi,
+ RADIO_2057_RCCAL_BCAP_VAL);
rccal_scap_val =
- read_radio_reg(pi,
- RADIO_2057_RCCAL_SCAP_VAL);
+ read_radio_reg(
+ pi,
+ RADIO_2057_RCCAL_SCAP_VAL);
rccal_tx20_11b_bcap = rccal_bcap_val;
rccal_tx20_11b_scap = rccal_scap_val;
@@ -15497,11 +16446,13 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
tx_lpf_bw_ofdm_40mhz = 3;
rccal_bcap_val =
- read_radio_reg(pi,
- RADIO_2057_RCCAL_BCAP_VAL);
+ read_radio_reg(
+ pi,
+ RADIO_2057_RCCAL_BCAP_VAL);
rccal_scap_val =
- read_radio_reg(pi,
- RADIO_2057_RCCAL_SCAP_VAL);
+ read_radio_reg(
+ pi,
+ RADIO_2057_RCCAL_SCAP_VAL);
rccal_tx20_11b_bcap = rccal_bcap_val;
rccal_tx20_11b_scap = rccal_scap_val;
@@ -15517,70 +16468,83 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
if (rccal_ovrd) {
- rx2tx_lpf_rc_lut_tx20_11b = (rccal_tx20_11b_bcap << 8) |
- (rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b;
- rx2tx_lpf_rc_lut_tx20_11n = (rccal_tx20_11n_bcap << 8) |
- (rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz;
- rx2tx_lpf_rc_lut_tx40_11n = (rccal_tx40_11n_bcap << 8) |
- (rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz;
+ rx2tx_lpf_rc_lut_tx20_11b =
+ (rccal_tx20_11b_bcap << 8) |
+ (rccal_tx20_11b_scap << 3) |
+ tx_lpf_bw_11b;
+ rx2tx_lpf_rc_lut_tx20_11n =
+ (rccal_tx20_11n_bcap << 8) |
+ (rccal_tx20_11n_scap << 3) |
+ tx_lpf_bw_ofdm_20mhz;
+ rx2tx_lpf_rc_lut_tx40_11n =
+ (rccal_tx40_11n_bcap << 8) |
+ (rccal_tx40_11n_scap << 3) |
+ tx_lpf_bw_ofdm_40mhz;
for (coreNum = 0; coreNum <= 1; coreNum++) {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x152 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx20_11b);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x153 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx20_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x154 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx20_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x155 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx40_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x156 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx40_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x157 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx40_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x158 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx40_11n);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- 1,
- 0x159 + coreNum * 0x10,
- 16,
- &rx2tx_lpf_rc_lut_tx40_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x152 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx20_11b);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x153 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx20_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x154 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx20_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x155 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx40_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x156 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx40_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x157 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx40_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x158 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx40_11n);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_RFSEQ,
+ 1,
+ 0x159 + coreNum * 0x10,
+ 16,
+ &rx2tx_lpf_rc_lut_tx40_11n);
}
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
- 1, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 4),
+ 1, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
}
- if (!NORADIO_ENAB(pi->pubpi)) {
- write_phy_reg(pi, 0x32f, 0x3);
- }
+ write_phy_reg(pi, 0x32f, 0x3);
- if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
- 1, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- }
+ if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2),
+ 1, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) ||
(pi->pubpi.radiorev == 6)) {
@@ -15635,17 +16599,16 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if ((pi->pubpi.radiorev == 3)
|| (pi->pubpi.radiorev == 4)
- || (pi->pubpi.radiorev == 6)) {
-
+ || (pi->pubpi.radiorev == 6))
txgm_idac_bleed = 0x7f;
- }
for (coreNum = 0; coreNum <= 1; coreNum++) {
if (txgm_idac_bleed != 0)
- WRITE_RADIO_REG4(pi, RADIO_2057,
- CORE, coreNum,
- TXGM_IDAC_BLEED,
- txgm_idac_bleed);
+ WRITE_RADIO_REG4(
+ pi, RADIO_2057,
+ CORE, coreNum,
+ TXGM_IDAC_BLEED,
+ txgm_idac_bleed);
}
if (pi->pubpi.radiorev == 5) {
@@ -15660,18 +16623,20 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
CORE, coreNum,
IPA2G_IMAIN,
0x1f);
- WRITE_RADIO_REG4(pi, RADIO_2057,
- CORE, coreNum,
- IPA2G_BIAS_FILTER,
- 0xee);
+ WRITE_RADIO_REG4(
+ pi, RADIO_2057,
+ CORE, coreNum,
+ IPA2G_BIAS_FILTER,
+ 0xee);
WRITE_RADIO_REG4(pi, RADIO_2057,
CORE, coreNum,
PAD2G_IDACS,
0x8a);
- WRITE_RADIO_REG4(pi, RADIO_2057,
- CORE, coreNum,
- PAD_BIAS_FILTER_BWS,
- 0x3e);
+ WRITE_RADIO_REG4(
+ pi, RADIO_2057,
+ CORE, coreNum,
+ PAD_BIAS_FILTER_BWS,
+ 0x3e);
}
} else if ((pi->pubpi.radiorev == 7)
@@ -15700,9 +16665,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
}
} else {
- freq =
- CHAN5G_FREQ(CHSPEC_CHANNEL
- (pi->radio_chanspec));
+ freq = CHAN5G_FREQ(CHSPEC_CHANNEL(
+ pi->radio_chanspec));
if (((freq >= 5180) && (freq <= 5230))
|| ((freq >= 5745) && (freq <= 5805))) {
WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
@@ -15809,12 +16773,12 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
wlc_phy_workarounds_nphy_gainctrl(pi);
pdetrange =
- (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
- pdetrange : pi->srom_fem2g.pdetrange;
+ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+ pdetrange : pi->srom_fem2g.pdetrange;
if (pdetrange == 0) {
chan_freq_range =
- wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] = 0x70;
aux_adc_vmid_rev7_core1[3] = 0x70;
@@ -15842,15 +16806,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
if (chan_freq_range ==
WL_CHAN_FREQ_RANGE_2G) {
aux_adc_vmid_rev7_core0[3] =
- 0x8c;
+ 0x8c;
aux_adc_vmid_rev7_core1[3] =
- 0x8c;
+ 0x8c;
aux_adc_gain_rev7[3] = 0;
} else {
aux_adc_vmid_rev7_core0[3] =
- 0x96;
+ 0x96;
aux_adc_vmid_rev7_core1[3] =
- 0x96;
+ 0x96;
aux_adc_gain_rev7[3] = 0;
}
}
@@ -15918,7 +16882,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
sizeof(rfseq_tx2rx_events_rev3) /
sizeof(rfseq_tx2rx_events_rev3[0]));
- if (PHY_IPA(pi)) {
+ if (PHY_IPA(pi))
wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
rfseq_rx2tx_events_rev3_ipa,
rfseq_rx2tx_dlys_rev3_ipa,
@@ -15927,7 +16891,6 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
sizeof
(rfseq_rx2tx_events_rev3_ipa
[0]));
- }
if ((pi->sh->hw_phyrxchain != 0x3) &&
(pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
@@ -15936,22 +16899,21 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
rfseq_rx2tx_dlys_rev3[5] = 59;
rfseq_rx2tx_dlys_rev3[6] = 1;
rfseq_rx2tx_events_rev3[7] =
- NPHY_REV3_RFSEQ_CMD_END;
+ NPHY_REV3_RFSEQ_CMD_END;
}
- wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
- rfseq_rx2tx_events_rev3,
- rfseq_rx2tx_dlys_rev3,
- sizeof(rfseq_rx2tx_events_rev3) /
- sizeof(rfseq_rx2tx_events_rev3
- [0]));
+ wlc_phy_set_rfseq_nphy(
+ pi, NPHY_RFSEQ_RX2TX,
+ rfseq_rx2tx_events_rev3,
+ rfseq_rx2tx_dlys_rev3,
+ sizeof(rfseq_rx2tx_events_rev3) /
+ sizeof(rfseq_rx2tx_events_rev3[0]));
}
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec))
write_phy_reg(pi, 0x6a, 0x2);
- } else {
+ else
write_phy_reg(pi, 0x6a, 0x9c40);
- }
mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
@@ -15978,8 +16940,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
&dac_control);
pdetrange =
- (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
- pdetrange : pi->srom_fem2g.pdetrange;
+ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+ pdetrange : pi->srom_fem2g.pdetrange;
if (pdetrange == 0) {
if (NREV_GE(pi->pubpi.phy_rev, 4)) {
@@ -15990,7 +16952,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
aux_adc_gain = aux_adc_gain_rev3;
}
chan_freq_range =
- wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
switch (chan_freq_range) {
case WL_CHAN_FREQ_RANGE_5GL:
@@ -16033,7 +16995,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
if (NREV_GE(pi->pubpi.phy_rev, 6)) {
chan_freq_range =
- wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
bcm_adc_vmid[3] = 0x8e;
bcm_adc_gain[3] = 0x03;
@@ -16056,14 +17018,16 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
0x1c, 16, bcm_adc_gain);
} else if (pdetrange == 3) {
chan_freq_range =
- wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ wlc_phy_get_chan_freq_range_nphy(pi, 0);
if ((NREV_GE(pi->pubpi.phy_rev, 4))
&& (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) {
u16 auxadc_vmid[] = {
- 0xa2, 0xb4, 0xb4, 0x270 };
+ 0xa2, 0xb4, 0xb4, 0x270
+ };
u16 auxadc_gain[] = {
- 0x02, 0x02, 0x02, 0x00 };
+ 0x02, 0x02, 0x02, 0x00
+ };
wlc_phy_table_write_nphy(pi,
NPHY_TBL_ID_AFECTRL, 4,
@@ -16084,7 +17048,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
u16 Vmid[2], Av[2];
chan_freq_range =
- wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ wlc_phy_get_chan_freq_range_nphy(pi, 0);
if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89;
Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89;
@@ -16155,8 +17119,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
0x0);
triso =
- (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
- triso : pi->srom_fem2g.triso;
+ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+ triso : pi->srom_fem2g.triso;
if (triso == 7) {
wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
@@ -16212,11 +17176,10 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) {
+ if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK)
wlapi_bmac_mhf(pi->sh->physhim, MHF4,
- MHF4_BPHY_TXCORE0,
- MHF4_BPHY_TXCORE0, BRCM_BAND_ALL);
- }
+ MHF4_BPHY_TXCORE0,
+ MHF4_BPHY_TXCORE0, BRCM_BAND_ALL);
}
} else {
@@ -16314,1121 +17277,2720 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
write_phy_reg(pi, 0x194, 0x0);
}
- if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+ if (NREV_IS(pi->pubpi.phy_rev, 2))
mod_phy_reg(pi, 0x221,
NPHY_FORCESIG_DECODEGATEDCLKS,
NPHY_FORCESIG_DECODEGATEDCLKS);
- }
}
if (pi->phyhang_avoid)
wlc_phy_stay_in_carriersearch_nphy(pi, false);
}
-static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi)
+static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
{
- u16 w1th, hpf_code, currband;
- int ctr;
- u8 rfseq_updategainu_events[] = {
- NPHY_RFSEQ_CMD_RX_GAIN,
- NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
- NPHY_RFSEQ_CMD_SET_HPF_BW
- };
- u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
- s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
- s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
- s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
- s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
- s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
- s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
- s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
- s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
- s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
- s8 *lna1_gain_db = NULL;
- s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
- s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
- s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
- s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
- s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
- s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
- s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
- s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
- s8 *lna2_gain_db = NULL;
- s8 tiaG_gain_db[] = {
- 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
- s8 tiaA_gain_db[] = {
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
- s8 tiaA_gain_db_rev4[] = {
- 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
- s8 tiaA_gain_db_rev5[] = {
- 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
- s8 tiaA_gain_db_rev6[] = {
- 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
- s8 *tia_gain_db;
- s8 tiaG_gainbits[] = {
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
- s8 tiaA_gainbits[] = {
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
- s8 tiaA_gainbits_rev4[] = {
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
- s8 tiaA_gainbits_rev5[] = {
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
- s8 tiaA_gainbits_rev6[] = {
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
- s8 *tia_gainbits;
- s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
- s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
- u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
- u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
- u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
- u16 rfseqG_init_gain_rev5_elna[] = {
- 0x013f, 0x013f, 0x013f, 0x013f };
- u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
- u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
- u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
- u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
- u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
- u16 rfseqA_init_gain_rev4_elna[] = {
- 0x314f, 0x314f, 0x314f, 0x314f };
- u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
- u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
- u16 *rfseq_init_gain;
- u16 initG_gaincode = 0x627e;
- u16 initG_gaincode_rev4 = 0x527e;
- u16 initG_gaincode_rev5 = 0x427e;
- u16 initG_gaincode_rev5_elna = 0x027e;
- u16 initG_gaincode_rev6 = 0x527e;
- u16 initG_gaincode_rev6_224B0 = 0x427e;
- u16 initG_gaincode_rev6_elna = 0x127e;
- u16 initA_gaincode = 0x52de;
- u16 initA_gaincode_rev4 = 0x629e;
- u16 initA_gaincode_rev4_elna = 0x329e;
- u16 initA_gaincode_rev5 = 0x729e;
- u16 initA_gaincode_rev6 = 0x729e;
- u16 init_gaincode;
- u16 clip1hiG_gaincode = 0x107e;
- u16 clip1hiG_gaincode_rev4 = 0x007e;
- u16 clip1hiG_gaincode_rev5 = 0x1076;
- u16 clip1hiG_gaincode_rev6 = 0x007e;
- u16 clip1hiA_gaincode = 0x00de;
- u16 clip1hiA_gaincode_rev4 = 0x029e;
- u16 clip1hiA_gaincode_rev5 = 0x029e;
- u16 clip1hiA_gaincode_rev6 = 0x029e;
- u16 clip1hi_gaincode;
- u16 clip1mdG_gaincode = 0x0066;
- u16 clip1mdA_gaincode = 0x00ca;
- u16 clip1mdA_gaincode_rev4 = 0x1084;
- u16 clip1mdA_gaincode_rev5 = 0x2084;
- u16 clip1mdA_gaincode_rev6 = 0x2084;
- u16 clip1md_gaincode = 0;
- u16 clip1loG_gaincode = 0x0074;
- u16 clip1loG_gaincode_rev5[] = {
- 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
- };
- u16 clip1loG_gaincode_rev6[] = {
- 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
- };
- u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
- u16 clip1loA_gaincode = 0x00cc;
- u16 clip1loA_gaincode_rev4 = 0x0086;
- u16 clip1loA_gaincode_rev5 = 0x2086;
- u16 clip1loA_gaincode_rev6 = 0x2086;
- u16 clip1lo_gaincode;
- u8 crsminG_th = 0x18;
- u8 crsminG_th_rev5 = 0x18;
- u8 crsminG_th_rev6 = 0x18;
- u8 crsminA_th = 0x1e;
- u8 crsminA_th_rev4 = 0x24;
- u8 crsminA_th_rev5 = 0x24;
- u8 crsminA_th_rev6 = 0x24;
- u8 crsmin_th;
- u8 crsminlG_th = 0x18;
- u8 crsminlG_th_rev5 = 0x18;
- u8 crsminlG_th_rev6 = 0x18;
- u8 crsminlA_th = 0x1e;
- u8 crsminlA_th_rev4 = 0x24;
- u8 crsminlA_th_rev5 = 0x24;
- u8 crsminlA_th_rev6 = 0x24;
- u8 crsminl_th = 0;
- u8 crsminuG_th = 0x18;
- u8 crsminuG_th_rev5 = 0x18;
- u8 crsminuG_th_rev6 = 0x18;
- u8 crsminuA_th = 0x1e;
- u8 crsminuA_th_rev4 = 0x24;
- u8 crsminuA_th_rev5 = 0x24;
- u8 crsminuA_th_rev6 = 0x24;
- u8 crsminuA_th_rev6_224B0 = 0x2d;
- u8 crsminu_th;
- u16 nbclipG_th = 0x20d;
- u16 nbclipG_th_rev4 = 0x1a1;
- u16 nbclipG_th_rev5 = 0x1d0;
- u16 nbclipG_th_rev6 = 0x1d0;
- u16 nbclipA_th = 0x1a1;
- u16 nbclipA_th_rev4 = 0x107;
- u16 nbclipA_th_rev5 = 0x0a9;
- u16 nbclipA_th_rev6 = 0x0f0;
- u16 nbclip_th = 0;
- u8 w1clipG_th = 5;
- u8 w1clipG_th_rev5 = 9;
- u8 w1clipG_th_rev6 = 5;
- u8 w1clipA_th = 25, w1clip_th;
- u8 rssi_gain_default = 0x50;
- u8 rssiG_gain_rev6_224B0 = 0x50;
- u8 rssiA_gain_rev5 = 0x90;
- u8 rssiA_gain_rev6 = 0x90;
- u8 rssi_gain;
- u16 regval[21];
- u8 triso;
+ int j, type = 2;
+ u16 addr_offset = 0x2c5;
- triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso :
- pi->srom_fem2g.triso;
+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+ write_phy_reg(pi, addr_offset + j,
+ NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
+}
+
+static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals)
+{
+
+ if (write == 0) {
+ vals[0] = read_phy_reg(pi, 0x2c);
+ vals[1] = read_phy_reg(pi, 0x42);
+ } else {
+ write_phy_reg(pi, 0x2c, vals[0]);
+ write_phy_reg(pi, 0x42, vals[1]);
+ }
+}
+
+static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi)
+{
+ u8 core;
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (pi->pubpi.radiorev == 5) {
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MASTER, 0x5);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MUX, 0xe);
- wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi);
- } else if (pi->pubpi.radiorev == 7) {
- wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+ if (pi->pubpi.radiorev != 5)
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+ core, TSSIA, 0);
- mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0));
- mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0));
+ if (!NREV_IS(pi->pubpi.phy_rev, 7))
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+ core, TSSIG, 0x1);
+ else
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+ core, TSSIG, 0x31);
+ } else {
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MASTER, 0x9);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MUX, 0xc);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TSSIG, 0);
- } else if ((pi->pubpi.radiorev == 3)
- || (pi->pubpi.radiorev == 8)) {
- wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+ if (pi->pubpi.radiorev != 5) {
+ if (!NREV_IS(pi->pubpi.phy_rev, 7))
+ WRITE_RADIO_REG3(pi, RADIO_2057,
+ TX, core,
+ TSSIA, 0x1);
+ else
+ WRITE_RADIO_REG3(pi, RADIO_2057,
+ TX, core,
+ TSSIA, 0x31);
+ }
+ }
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
+ 0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
+ 0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
+ 0x3);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
+ 0x0);
+ }
+ } else {
+ WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31,
+ (CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 :
+ 0x80);
+ WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0);
+ WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29);
- if (pi->pubpi.radiorev == 8) {
- mod_phy_reg(pi, 0x283,
- (0xff << 0), (0x44 << 0));
- mod_phy_reg(pi, 0x280,
- (0xff << 0), (0x44 << 0));
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG,
+ 0x0);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC,
+ 0x0);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM,
+ 0x3);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET,
+ 0x0);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1,
+ 0x8);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2,
+ 0x0);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3,
+ 0x0);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TX_SSI_MASTER, 0x5);
+
+ if (pi->pubpi.radiorev != 5)
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+ core, TSSIA, 0x0);
+ if (NREV_GE(pi->pubpi.phy_rev, 5))
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+ core, TSSIG, 0x31);
+ else
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+ core, TSSIG, 0x11);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TX_SSI_MUX, 0xe);
+ } else {
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TX_SSI_MASTER, 0x9);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TSSIA, 0x31);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TSSIG, 0x0);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ TX_SSI_MUX, 0xc);
}
- } else {
- wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
}
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ }
+}
- mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6));
+static void
+wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value,
+ u8 core_mask, u8 off)
+{
+ u8 core_num;
+ u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask =
+ 0, val_mask = 0;
+ u8 shift = 0, val_shift = 0;
- mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
- mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
- currband =
- read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
- if (currband == 0) {
- if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- if (pi->pubpi.radiorev == 11) {
- lna1_gain_db = lna1G_gain_db_rev6_224B0;
- lna2_gain_db = lna2G_gain_db_rev6_224B0;
- rfseq_init_gain =
- rfseqG_init_gain_rev6_224B0;
- init_gaincode =
- initG_gaincode_rev6_224B0;
- clip1hi_gaincode =
- clip1hiG_gaincode_rev6;
- clip1lo_gaincode =
- clip1loG_gaincode_rev6_224B0;
- nbclip_th = nbclipG_th_rev6;
- w1clip_th = w1clipG_th_rev6;
- crsmin_th = crsminG_th_rev6;
- crsminl_th = crsminlG_th_rev6;
- crsminu_th = crsminuG_th_rev6;
- rssi_gain = rssiG_gain_rev6_224B0;
- } else {
- lna1_gain_db = lna1G_gain_db_rev6;
- lna2_gain_db = lna2G_gain_db_rev6;
- if (pi->sh->boardflags & BFL_EXTLNA) {
+ en_mask = field;
+ for (core_num = 0; core_num < 2; core_num++) {
- rfseq_init_gain =
- rfseqG_init_gain_rev6_elna;
- init_gaincode =
- initG_gaincode_rev6_elna;
- } else {
- rfseq_init_gain =
- rfseqG_init_gain_rev6;
- init_gaincode =
- initG_gaincode_rev6;
- }
- clip1hi_gaincode =
- clip1hiG_gaincode_rev6;
- switch (triso) {
- case 0:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[0];
- break;
- case 1:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[1];
- break;
- case 2:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[2];
- break;
- case 3:
- default:
+ switch (field) {
+ case (0x1 << 1):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 2):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 1);
+ val_shift = 1;
+ break;
+ case (0x1 << 3):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 2);
+ val_shift = 2;
+ break;
+ case (0x1 << 4):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 4);
+ val_shift = 4;
+ break;
+ case (0x1 << 5):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 5);
+ val_shift = 5;
+ break;
+ case (0x1 << 6):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 6);
+ val_shift = 6;
+ break;
+ case (0x1 << 7):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x1 << 7);
+ val_shift = 7;
+ break;
+ case (0x1 << 8):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x7 << 8);
+ val_shift = 8;
+ break;
+ case (0x1 << 11):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7a : 0x7d;
+ val_mask = (0x7 << 13);
+ val_shift = 13;
+ break;
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[3];
- break;
- case 4:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[4];
- break;
- case 5:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[5];
- break;
- case 6:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[6];
- break;
- case 7:
- clip1lo_gaincode =
- clip1loG_gaincode_rev6[7];
- break;
- }
- nbclip_th = nbclipG_th_rev6;
- w1clip_th = w1clipG_th_rev6;
- crsmin_th = crsminG_th_rev6;
- crsminl_th = crsminlG_th_rev6;
- crsminu_th = crsminuG_th_rev6;
- rssi_gain = rssi_gain_default;
- }
- } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
- lna1_gain_db = lna1G_gain_db_rev5;
- lna2_gain_db = lna2G_gain_db_rev5;
- if (pi->sh->boardflags & BFL_EXTLNA) {
+ case (0x1 << 9):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+ val_mask = (0x7 << 0);
+ val_shift = 0;
+ break;
- rfseq_init_gain =
- rfseqG_init_gain_rev5_elna;
- init_gaincode =
- initG_gaincode_rev5_elna;
- } else {
- rfseq_init_gain = rfseqG_init_gain_rev5;
- init_gaincode = initG_gaincode_rev5;
- }
- clip1hi_gaincode = clip1hiG_gaincode_rev5;
- switch (triso) {
- case 0:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[0];
- break;
- case 1:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[1];
- break;
- case 2:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[2];
- break;
- case 3:
+ case (0x1 << 10):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+ val_mask = (0x7 << 4);
+ val_shift = 4;
+ break;
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[3];
- break;
- case 4:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[4];
- break;
- case 5:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[5];
- break;
- case 6:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[6];
- break;
- case 7:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[7];
- break;
- default:
- clip1lo_gaincode =
- clip1loG_gaincode_rev5[3];
- break;
- }
- nbclip_th = nbclipG_th_rev5;
- w1clip_th = w1clipG_th_rev5;
- crsmin_th = crsminG_th_rev5;
- crsminl_th = crsminlG_th_rev5;
- crsminu_th = crsminuG_th_rev5;
- rssi_gain = rssi_gain_default;
- } else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
- lna1_gain_db = lna1G_gain_db_rev4;
- lna2_gain_db = lna2G_gain_db;
- rfseq_init_gain = rfseqG_init_gain_rev4;
- init_gaincode = initG_gaincode_rev4;
- clip1hi_gaincode = clip1hiG_gaincode_rev4;
- clip1lo_gaincode = clip1loG_gaincode;
- nbclip_th = nbclipG_th_rev4;
- w1clip_th = w1clipG_th;
- crsmin_th = crsminG_th;
- crsminl_th = crsminlG_th;
- crsminu_th = crsminuG_th;
- rssi_gain = rssi_gain_default;
- } else {
- lna1_gain_db = lna1G_gain_db;
- lna2_gain_db = lna2G_gain_db;
- rfseq_init_gain = rfseqG_init_gain;
- init_gaincode = initG_gaincode;
- clip1hi_gaincode = clip1hiG_gaincode;
- clip1lo_gaincode = clip1loG_gaincode;
- nbclip_th = nbclipG_th;
- w1clip_th = w1clipG_th;
- crsmin_th = crsminG_th;
- crsminl_th = crsminlG_th;
- crsminu_th = crsminuG_th;
- rssi_gain = rssi_gain_default;
+ case (0x1 << 12):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7b : 0x7e;
+ val_mask = (0xffff << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 13):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0x7c : 0x7f;
+ val_mask = (0xffff << 0);
+ val_shift = 0;
+ break;
+ case (0x1 << 14):
+ en_addr = (core_num == 0) ? 0xe7 : 0xec;
+ val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+ val_mask = (0x3 << 6);
+ val_shift = 6;
+ break;
+ case (0x1 << 0):
+ en_addr = (core_num == 0) ? 0xe5 : 0xe6;
+ val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+ val_mask = (0x1 << 15);
+ val_shift = 15;
+ break;
+ default:
+ addr = 0xffff;
+ break;
}
- tia_gain_db = tiaG_gain_db;
- tia_gainbits = tiaG_gainbits;
- clip1md_gaincode = clip1mdG_gaincode;
- } else {
- if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- lna1_gain_db = lna1A_gain_db_rev6;
- lna2_gain_db = lna2A_gain_db_rev6;
- tia_gain_db = tiaA_gain_db_rev6;
- tia_gainbits = tiaA_gainbits_rev6;
- rfseq_init_gain = rfseqA_init_gain_rev6;
- init_gaincode = initA_gaincode_rev6;
- clip1hi_gaincode = clip1hiA_gaincode_rev6;
- clip1md_gaincode = clip1mdA_gaincode_rev6;
- clip1lo_gaincode = clip1loA_gaincode_rev6;
- crsmin_th = crsminA_th_rev6;
- crsminl_th = crsminlA_th_rev6;
- if ((pi->pubpi.radiorev == 11) &&
- (CHSPEC_IS40(pi->radio_chanspec) == 0)) {
- crsminu_th = crsminuA_th_rev6_224B0;
- } else {
- crsminu_th = crsminuA_th_rev6;
- }
- nbclip_th = nbclipA_th_rev6;
- rssi_gain = rssiA_gain_rev6;
- } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
- lna1_gain_db = lna1A_gain_db_rev5;
- lna2_gain_db = lna2A_gain_db_rev5;
- tia_gain_db = tiaA_gain_db_rev5;
- tia_gainbits = tiaA_gainbits_rev5;
- rfseq_init_gain = rfseqA_init_gain_rev5;
- init_gaincode = initA_gaincode_rev5;
- clip1hi_gaincode = clip1hiA_gaincode_rev5;
- clip1md_gaincode = clip1mdA_gaincode_rev5;
- clip1lo_gaincode = clip1loA_gaincode_rev5;
- crsmin_th = crsminA_th_rev5;
- crsminl_th = crsminlA_th_rev5;
- crsminu_th = crsminuA_th_rev5;
- nbclip_th = nbclipA_th_rev5;
- rssi_gain = rssiA_gain_rev5;
- } else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
- lna1_gain_db = lna1A_gain_db_rev4;
- lna2_gain_db = lna2A_gain_db_rev4;
- tia_gain_db = tiaA_gain_db_rev4;
- tia_gainbits = tiaA_gainbits_rev4;
- if (pi->sh->boardflags & BFL_EXTLNA_5GHz) {
- rfseq_init_gain =
- rfseqA_init_gain_rev4_elna;
- init_gaincode =
- initA_gaincode_rev4_elna;
- } else {
- rfseq_init_gain = rfseqA_init_gain_rev4;
- init_gaincode = initA_gaincode_rev4;
- }
- clip1hi_gaincode = clip1hiA_gaincode_rev4;
- clip1md_gaincode = clip1mdA_gaincode_rev4;
- clip1lo_gaincode = clip1loA_gaincode_rev4;
- crsmin_th = crsminA_th_rev4;
- crsminl_th = crsminlA_th_rev4;
- crsminu_th = crsminuA_th_rev4;
- nbclip_th = nbclipA_th_rev4;
- rssi_gain = rssi_gain_default;
+ if (off) {
+ and_phy_reg(pi, en_addr, ~en_mask);
+ and_phy_reg(pi, val_addr, ~val_mask);
} else {
- lna1_gain_db = lna1A_gain_db;
- lna2_gain_db = lna2A_gain_db;
- tia_gain_db = tiaA_gain_db;
- tia_gainbits = tiaA_gainbits;
- rfseq_init_gain = rfseqA_init_gain;
- init_gaincode = initA_gaincode;
- clip1hi_gaincode = clip1hiA_gaincode;
- clip1md_gaincode = clip1mdA_gaincode;
- clip1lo_gaincode = clip1loA_gaincode;
- crsmin_th = crsminA_th;
- crsminl_th = crsminlA_th;
- crsminu_th = crsminuA_th;
- nbclip_th = nbclipA_th;
- rssi_gain = rssi_gain_default;
+
+ if ((core_mask == 0)
+ || (core_mask & (1 << core_num))) {
+ or_phy_reg(pi, en_addr, en_mask);
+
+ if (addr != 0xffff)
+ mod_phy_reg(pi, val_addr,
+ val_mask,
+ (value <<
+ val_shift));
+ }
}
- w1clip_th = w1clipA_th;
}
+ } else {
- write_radio_reg(pi,
- (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
- RADIO_2056_RX0), 0x17);
- write_radio_reg(pi,
- (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
- RADIO_2056_RX1), 0x17);
+ if (off) {
+ and_phy_reg(pi, 0xec, ~field);
+ value = 0x0;
+ } else {
+ or_phy_reg(pi, 0xec, field);
+ }
- write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0),
- 0xf0);
- write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1),
- 0xf0);
+ for (core_num = 0; core_num < 2; core_num++) {
- write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0),
- 0x0);
- write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1),
- 0x0);
+ switch (field) {
+ case (0x1 << 1):
+ case (0x1 << 9):
+ case (0x1 << 12):
+ case (0x1 << 13):
+ case (0x1 << 14):
+ addr = 0x78;
- write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0),
- rssi_gain);
- write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1),
- rssi_gain);
+ core_mask = 0x1;
+ break;
+ case (0x1 << 2):
+ case (0x1 << 3):
+ case (0x1 << 4):
+ case (0x1 << 5):
+ case (0x1 << 6):
+ case (0x1 << 7):
+ case (0x1 << 8):
+ addr = (core_num == 0) ? 0x7a : 0x7d;
+ break;
+ case (0x1 << 10):
+ addr = (core_num == 0) ? 0x7b : 0x7e;
+ break;
+ case (0x1 << 11):
+ addr = (core_num == 0) ? 0x7c : 0x7f;
+ break;
+ default:
+ addr = 0xffff;
+ }
- write_radio_reg(pi,
- (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
- RADIO_2056_RX0), 0x17);
- write_radio_reg(pi,
- (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
- RADIO_2056_RX1), 0x17);
+ switch (field) {
+ case (0x1 << 1):
+ mask = (0x7 << 3);
+ shift = 3;
+ break;
+ case (0x1 << 9):
+ mask = (0x1 << 2);
+ shift = 2;
+ break;
+ case (0x1 << 12):
+ mask = (0x1 << 8);
+ shift = 8;
+ break;
+ case (0x1 << 13):
+ mask = (0x1 << 9);
+ shift = 9;
+ break;
+ case (0x1 << 14):
+ mask = (0xf << 12);
+ shift = 12;
+ break;
+ case (0x1 << 2):
+ mask = (0x1 << 0);
+ shift = 0;
+ break;
+ case (0x1 << 3):
+ mask = (0x1 << 1);
+ shift = 1;
+ break;
+ case (0x1 << 4):
+ mask = (0x1 << 2);
+ shift = 2;
+ break;
+ case (0x1 << 5):
+ mask = (0x3 << 4);
+ shift = 4;
+ break;
+ case (0x1 << 6):
+ mask = (0x3 << 6);
+ shift = 6;
+ break;
+ case (0x1 << 7):
+ mask = (0x1 << 8);
+ shift = 8;
+ break;
+ case (0x1 << 8):
+ mask = (0x1 << 9);
+ shift = 9;
+ break;
+ case (0x1 << 10):
+ mask = 0x1fff;
+ shift = 0x0;
+ break;
+ case (0x1 << 11):
+ mask = 0x1fff;
+ shift = 0x0;
+ break;
+ default:
+ mask = 0x0;
+ shift = 0x0;
+ break;
+ }
- write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0),
- 0xFF);
- write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1),
- 0xFF);
+ if ((addr != 0xffff) && (core_mask & (1 << core_num)))
+ mod_phy_reg(pi, addr, mask, (value << shift));
+ }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8,
- 8, lna1_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8,
- 8, lna1_gain_db);
+ or_phy_reg(pi, 0xec, (0x1 << 0));
+ or_phy_reg(pi, 0x78, (0x1 << 0));
+ udelay(1);
+ and_phy_reg(pi, 0xec, ~(0x1 << 0));
+ }
+}
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
- 8, lna2_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
- 8, lna2_gain_db);
+static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi)
+{
+ s32 rssi_buf[4];
+ s32 int_val;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20,
- 8, tia_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20,
- 8, tia_gain_db);
+ if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi))
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20,
- 8, tia_gainbits);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20,
- 8, tia_gainbits);
+ return;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40,
- 8, &lpf_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40,
- 8, &lpf_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40,
- 8, &lpf_gainbits);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40,
- 8, &lpf_gainbits);
+ if (PHY_IPA(pi))
+ wlc_phy_ipa_internal_tssi_setup_nphy(pi);
- write_phy_reg(pi, 0x20, init_gaincode);
- write_phy_reg(pi, 0x2a7, init_gaincode);
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+ 0, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ else if (NREV_GE(pi->pubpi.phy_rev, 3))
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- pi->pubpi.phy_corenum, 0x106, 16,
- rfseq_init_gain);
+ wlc_phy_stopplayback_nphy(pi);
- write_phy_reg(pi, 0x22, clip1hi_gaincode);
- write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+ wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false);
- write_phy_reg(pi, 0x24, clip1md_gaincode);
- write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+ udelay(20);
+ int_val =
+ wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf,
+ 1);
+ wlc_phy_stopplayback_nphy(pi);
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0);
- write_phy_reg(pi, 0x37, clip1lo_gaincode);
- write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+ 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ else if (NREV_GE(pi->pubpi.phy_rev, 3))
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1);
- mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0));
- mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
- mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- write_phy_reg(pi, 0x2b, nbclip_th);
- write_phy_reg(pi, 0x41, nbclip_th);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
+ (u8) ((int_val >> 24) & 0xff);
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
+ (u8) ((int_val >> 24) & 0xff);
- mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0));
- mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0));
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
+ (u8) ((int_val >> 8) & 0xff);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
+ (u8) ((int_val >> 8) & 0xff);
+ } else {
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
+ (u8) ((int_val >> 24) & 0xff);
- write_phy_reg(pi, 0x150, 0x809c);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
+ (u8) ((int_val >> 8) & 0xff);
- } else {
+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
+ (u8) ((int_val >> 16) & 0xff);
+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
+ (u8) ((int_val) & 0xff);
+ }
- mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
- mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+}
- write_phy_reg(pi, 0x2b, 0x84);
- write_phy_reg(pi, 0x41, 0x84);
+static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi)
+{
+ u8 idx, idx2, i, delta_ind;
- if (CHSPEC_IS20(pi->radio_chanspec)) {
- write_phy_reg(pi, 0x6b, 0x2b);
- write_phy_reg(pi, 0x6c, 0x2b);
- write_phy_reg(pi, 0x6d, 0x9);
- write_phy_reg(pi, 0x6e, 0x9);
- }
+ for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++)
+ pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx];
- w1th = NPHY_RSSICAL_W1_TARGET - 4;
- mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0));
- mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0));
+ for (i = 0; i < 4; i++) {
+ idx2 = 0;
- if (CHSPEC_IS20(pi->radio_chanspec)) {
- mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0));
- mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0));
+ delta_ind = 0;
- mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0));
- mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0));
- }
+ switch (i) {
+ case 0:
- write_phy_reg(pi, 0x150, 0x809c);
+ if (CHSPEC_IS40(pi->radio_chanspec)
+ && NPHY_IS_SROM_REINTERPRET) {
+ idx = TXP_FIRST_MCS_40_SISO;
+ } else {
+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+ TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM;
+ delta_ind = 1;
+ }
+ break;
- if (pi->nphy_gain_boost)
- if ((CHSPEC_IS2G(pi->radio_chanspec)) &&
- (CHSPEC_IS40(pi->radio_chanspec)))
- hpf_code = 4;
- else
- hpf_code = 5;
- else if (CHSPEC_IS40(pi->radio_chanspec))
- hpf_code = 6;
- else
- hpf_code = 7;
+ case 1:
- mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7));
- mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7));
+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+ TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD;
+ break;
- for (ctr = 0; ctr < 4; ctr++) {
- regval[ctr] = (hpf_code << 8) | 0x7c;
- }
- wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+ case 2:
- wlc_phy_adjust_lnagaintbl_nphy(pi);
+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+ TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC;
+ break;
- if (pi->nphy_elna_gain_config) {
- regval[0] = 0;
- regval[1] = 1;
- regval[2] = 1;
- regval[3] = 1;
- wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval);
- wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval);
+ case 3:
- for (ctr = 0; ctr < 4; ctr++) {
- regval[ctr] = (hpf_code << 8) | 0x74;
- }
- wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+ TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM;
+ break;
}
- if (NREV_IS(pi->pubpi.phy_rev, 2)) {
- for (ctr = 0; ctr < 21; ctr++) {
- regval[ctr] = 3 * ctr;
- }
- wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval);
- wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval);
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ idx = idx + delta_ind;
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
- for (ctr = 0; ctr < 21; ctr++) {
- regval[ctr] = (u16) ctr;
- }
- wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval);
- wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval);
- }
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
- wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU,
- rfseq_updategainu_events,
- rfseq_updategainu_dlys,
- sizeof(rfseq_updategainu_events) /
- sizeof(rfseq_updategainu_events[0]));
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
- mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8));
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx++];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ idx = idx + 1 - delta_ind;
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
- if (CHSPEC_IS2G(pi->radio_chanspec))
- mod_phy_reg(pi,
- (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES),
- 0x7f, 0x4);
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+ pi->tx_power_offset[idx];
}
}
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi)
+static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
{
- s8 lna1_gain_db[] = { 8, 13, 17, 22 };
- s8 lna2_gain_db[] = { -2, 7, 11, 15 };
- s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 };
- s8 tia_gainbits[] = {
- 0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+ u32 idx;
+ s16 a1[2], b0[2], b1[2];
+ s8 target_pwr_qtrdbm[2];
+ s32 num, den, pwr_est;
+ u8 chan_freq_range;
+ u8 idle_tssi[2];
+ u32 tbl_id, tbl_len, tbl_offset;
+ u32 regval[64];
+ u8 core;
- mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
- mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+ (void)R_REG(&pi->regs->maccontrol);
+ udelay(1);
+ }
- mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
- mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0));
- mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0));
+ or_phy_reg(pi, 0x122, (0x1 << 0));
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8,
- lna1_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8,
- lna1_gain_db);
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
+ and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15)));
+ else
+ or_phy_reg(pi, 0x1e7, (0x1 << 15));
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8,
- lna2_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8,
- lna2_gain_db);
+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
- tia_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
- tia_gain_db);
+ if (pi->sh->sromrev < 4) {
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+ target_pwr_qtrdbm[0] = 13 * 4;
+ target_pwr_qtrdbm[1] = 13 * 4;
+ a1[0] = -424;
+ a1[1] = -424;
+ b0[0] = 5612;
+ b0[1] = 5612;
+ b1[1] = -1393;
+ b1[0] = -1393;
+ } else {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
- tia_gainbits);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
- tia_gainbits);
+ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+ switch (chan_freq_range) {
+ case WL_CHAN_FREQ_RANGE_2G:
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+ target_pwr_qtrdbm[0] =
+ pi->nphy_pwrctrl_info[0].max_pwr_2g;
+ target_pwr_qtrdbm[1] =
+ pi->nphy_pwrctrl_info[1].max_pwr_2g;
+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1;
+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1;
+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0;
+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0;
+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1;
+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1;
+ break;
+ case WL_CHAN_FREQ_RANGE_5GL:
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+ target_pwr_qtrdbm[0] =
+ pi->nphy_pwrctrl_info[0].max_pwr_5gl;
+ target_pwr_qtrdbm[1] =
+ pi->nphy_pwrctrl_info[1].max_pwr_5gl;
+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1;
+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1;
+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0;
+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0;
+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1;
+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1;
+ break;
+ case WL_CHAN_FREQ_RANGE_5GM:
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+ target_pwr_qtrdbm[0] =
+ pi->nphy_pwrctrl_info[0].max_pwr_5gm;
+ target_pwr_qtrdbm[1] =
+ pi->nphy_pwrctrl_info[1].max_pwr_5gm;
+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1;
+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1;
+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0;
+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0;
+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1;
+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1;
+ break;
+ case WL_CHAN_FREQ_RANGE_5GH:
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+ target_pwr_qtrdbm[0] =
+ pi->nphy_pwrctrl_info[0].max_pwr_5gh;
+ target_pwr_qtrdbm[1] =
+ pi->nphy_pwrctrl_info[1].max_pwr_5gh;
+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1;
+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1;
+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0;
+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0;
+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1;
+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1;
+ break;
+ default:
+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+ target_pwr_qtrdbm[0] = 13 * 4;
+ target_pwr_qtrdbm[1] = 13 * 4;
+ a1[0] = -424;
+ a1[1] = -424;
+ b0[0] = 5612;
+ b0[1] = 5612;
+ b1[1] = -1393;
+ b1[0] = -1393;
+ break;
+ }
+ }
- write_phy_reg(pi, 0x37, 0x74);
- write_phy_reg(pi, 0x2ad, 0x74);
- write_phy_reg(pi, 0x38, 0x18);
- write_phy_reg(pi, 0x2ae, 0x18);
+ target_pwr_qtrdbm[0] = (s8) pi->tx_power_max;
+ target_pwr_qtrdbm[1] = (s8) pi->tx_power_max;
- write_phy_reg(pi, 0x2b, 0xe8);
- write_phy_reg(pi, 0x41, 0xe8);
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (pi->srom_fem2g.tssipos)
+ or_phy_reg(pi, 0x1e9, (0x1 << 14));
- if (CHSPEC_IS20(pi->radio_chanspec)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ for (core = 0; core <= 1; core++) {
+ if (PHY_IPA(pi)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ WRITE_RADIO_REG3(pi, RADIO_2057,
+ TX, core,
+ TX_SSI_MUX,
+ 0xe);
+ else
+ WRITE_RADIO_REG3(pi, RADIO_2057,
+ TX, core,
+ TX_SSI_MUX,
+ 0xc);
+ }
+ }
+ } else {
+ if (PHY_IPA(pi)) {
- mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0));
- mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0));
- } else {
+ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+ RADIO_2056_TX0,
+ (CHSPEC_IS5G
+ (pi->radio_chanspec)) ?
+ 0xc : 0xe);
+ write_radio_reg(pi,
+ RADIO_2056_TX_TX_SSI_MUX |
+ RADIO_2056_TX1,
+ (CHSPEC_IS5G
+ (pi->radio_chanspec)) ?
+ 0xc : 0xe);
+ } else {
- mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0));
- mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0));
+ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+ RADIO_2056_TX0, 0x11);
+ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+ RADIO_2056_TX1, 0x11);
+ }
+ }
}
-}
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
-{
- u16 currband;
- s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
- s8 *lna1_gain_db = NULL;
- s8 *lna1_gain_db_2 = NULL;
- s8 *lna2_gain_db = NULL;
- s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
- s8 *tia_gain_db;
- s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
- s8 *tia_gainbits;
- u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
- u16 *rfseq_init_gain;
- u16 init_gaincode;
- u16 clip1hi_gaincode;
- u16 clip1md_gaincode = 0;
- u16 clip1md_gaincode_B;
- u16 clip1lo_gaincode;
- u16 clip1lo_gaincode_B;
- u8 crsminl_th = 0;
- u8 crsminu_th;
- u16 nbclip_th = 0;
- u8 w1clip_th;
- u16 freq;
- s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0;
- u8 chg_nbclip_th = 0;
+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+ (void)R_REG(&pi->regs->maccontrol);
+ udelay(1);
+ }
- mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
- mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+ (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
+ else
+ mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+ (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
- currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
- if (currband == 0) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ mod_phy_reg(pi, 0x222, (0xff << 0),
+ (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
+ else if (NREV_GT(pi->pubpi.phy_rev, 1))
+ mod_phy_reg(pi, 0x222, (0xff << 0),
+ (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
- lna1_gain_db = lna1G_gain_db_rev7;
+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
- lna1_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
- lna1_gain_db);
+ write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0));
- mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0));
+ write_phy_reg(pi, 0x1e9,
+ (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8));
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0));
- mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0));
+ write_phy_reg(pi, 0x1ea,
+ (target_pwr_qtrdbm[0] << 0) |
+ (target_pwr_qtrdbm[1] << 8));
+
+ tbl_len = 64;
+ tbl_offset = 0;
+ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+
+ for (idx = 0; idx < tbl_len; idx++) {
+ num = 8 *
+ (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx);
+ den = 32768 + a1[tbl_id - 26] * idx;
+ pwr_est = max(((4 * num + den / 2) / den), -8);
+ if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+ if (idx <=
+ (uint) (31 - idle_tssi[tbl_id - 26] + 1))
+ pwr_est =
+ max(pwr_est,
+ target_pwr_qtrdbm
+ [tbl_id - 26] + 1);
+ }
+ regval[idx] = (u32) pwr_est;
}
+ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+ regval);
+ }
- mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+ wlc_phy_txpwr_limit_to_tbl_nphy(pi);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8,
+ pi->adj_pwr_tbl_nphy);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8,
+ pi->adj_pwr_tbl_nphy);
- if (CHSPEC_IS20(pi->radio_chanspec)) {
- mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0));
- mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0));
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi)
+{
+ u32 *tx_pwrctrl_tbl = NULL;
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if ((pi->pubpi.radiorev == 4)
+ || (pi->pubpi.radiorev == 6))
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_ipa_2g_2057rev4n6;
+ else if (pi->pubpi.radiorev == 3)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_ipa_2g_2057rev3;
+ else if (pi->pubpi.radiorev == 5)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_ipa_2g_2057rev5;
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_ipa_2g_2057rev7;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
+ } else {
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa;
}
} else {
- init_gaincode = 0x9e;
- clip1hi_gaincode = 0x9e;
- clip1md_gaincode_B = 0x24;
- clip1lo_gaincode = 0x8a;
- clip1lo_gaincode_B = 8;
- rfseq_init_gain = rfseqA_init_gain_rev7;
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6))
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057;
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_ipa_5g_2057rev7;
+ } else {
+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g;
+ }
+ }
- tia_gain_db = tiaA_gain_db_rev7;
- tia_gainbits = tiaA_gainbits_rev7;
+ return tx_pwrctrl_tbl;
+}
- freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
- if (CHSPEC_IS20(pi->radio_chanspec)) {
+static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi)
+{
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (pi->nphy_rssical_chanspec_2G == 0)
+ return;
- w1clip_th = 25;
- clip1md_gaincode = 0x82;
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+ RADIO_2057_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_2G[0]);
+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+ RADIO_2057_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_2G[1]);
+ } else {
+ mod_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+ RADIO_2056_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_2G[0]);
+ mod_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+ RADIO_2056_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_2G[1]);
+ }
- if ((freq <= 5080) || (freq == 5825)) {
+ write_phy_reg(pi, 0x1a6,
+ pi->rssical_cache.rssical_phyregs_2G[0]);
+ write_phy_reg(pi, 0x1ac,
+ pi->rssical_cache.rssical_phyregs_2G[1]);
+ write_phy_reg(pi, 0x1b2,
+ pi->rssical_cache.rssical_phyregs_2G[2]);
+ write_phy_reg(pi, 0x1b8,
+ pi->rssical_cache.rssical_phyregs_2G[3]);
+ write_phy_reg(pi, 0x1a4,
+ pi->rssical_cache.rssical_phyregs_2G[4]);
+ write_phy_reg(pi, 0x1aa,
+ pi->rssical_cache.rssical_phyregs_2G[5]);
+ write_phy_reg(pi, 0x1b0,
+ pi->rssical_cache.rssical_phyregs_2G[6]);
+ write_phy_reg(pi, 0x1b6,
+ pi->rssical_cache.rssical_phyregs_2G[7]);
+ write_phy_reg(pi, 0x1a5,
+ pi->rssical_cache.rssical_phyregs_2G[8]);
+ write_phy_reg(pi, 0x1ab,
+ pi->rssical_cache.rssical_phyregs_2G[9]);
+ write_phy_reg(pi, 0x1b1,
+ pi->rssical_cache.rssical_phyregs_2G[10]);
+ write_phy_reg(pi, 0x1b7,
+ pi->rssical_cache.rssical_phyregs_2G[11]);
- s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
- s8 lna1A_gain_db_2_rev7[] = {
- 11, 17, 22, 25 };
- s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+ } else {
+ if (pi->nphy_rssical_chanspec_5G == 0)
+ return;
- crsminu_th = 0x3e;
- lna1_gain_db = lna1A_gain_db_rev7;
- lna1_gain_db_2 = lna1A_gain_db_2_rev7;
- lna2_gain_db = lna2A_gain_db_rev7;
- } else if ((freq >= 5500) && (freq <= 5700)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+ RADIO_2057_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_5G[0]);
+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+ RADIO_2057_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_5G[1]);
+ } else {
+ mod_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+ RADIO_2056_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_5G[0]);
+ mod_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+ RADIO_2056_VCM_MASK,
+ pi->rssical_cache.
+ rssical_radio_regs_5G[1]);
+ }
- s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
- s8 lna1A_gain_db_2_rev7[] = {
- 12, 18, 22, 26 };
- s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
+ write_phy_reg(pi, 0x1a6,
+ pi->rssical_cache.rssical_phyregs_5G[0]);
+ write_phy_reg(pi, 0x1ac,
+ pi->rssical_cache.rssical_phyregs_5G[1]);
+ write_phy_reg(pi, 0x1b2,
+ pi->rssical_cache.rssical_phyregs_5G[2]);
+ write_phy_reg(pi, 0x1b8,
+ pi->rssical_cache.rssical_phyregs_5G[3]);
+ write_phy_reg(pi, 0x1a4,
+ pi->rssical_cache.rssical_phyregs_5G[4]);
+ write_phy_reg(pi, 0x1aa,
+ pi->rssical_cache.rssical_phyregs_5G[5]);
+ write_phy_reg(pi, 0x1b0,
+ pi->rssical_cache.rssical_phyregs_5G[6]);
+ write_phy_reg(pi, 0x1b6,
+ pi->rssical_cache.rssical_phyregs_5G[7]);
+ write_phy_reg(pi, 0x1a5,
+ pi->rssical_cache.rssical_phyregs_5G[8]);
+ write_phy_reg(pi, 0x1ab,
+ pi->rssical_cache.rssical_phyregs_5G[9]);
+ write_phy_reg(pi, 0x1b1,
+ pi->rssical_cache.rssical_phyregs_5G[10]);
+ write_phy_reg(pi, 0x1b7,
+ pi->rssical_cache.rssical_phyregs_5G[11]);
+ }
+}
- crsminu_th = 0x45;
- clip1md_gaincode_B = 0x14;
- nbclip_th = 0xff;
- chg_nbclip_th = 1;
- lna1_gain_db = lna1A_gain_db_rev7;
- lna1_gain_db_2 = lna1A_gain_db_2_rev7;
- lna2_gain_db = lna2A_gain_db_rev7;
+static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi)
+{
+ u16 txcal_gain[2];
+
+ pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0];
+ pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0];
+ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+
+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+ txcal_gain);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40;
+ txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40;
+ } else {
+ txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60;
+ txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60;
+ }
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+ txcal_gain);
+}
+
+static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi)
+{
+ bool save_bbmult = false;
+ u8 txcal_index_2057_rev5n7 = 0;
+ u8 txcal_index_2057_rev3n4n6 = 10;
+
+ if (pi->use_int_tx_iqlo_cal_nphy) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6)) {
+
+ pi->nphy_txcal_pwr_idx[0] =
+ txcal_index_2057_rev3n4n6;
+ pi->nphy_txcal_pwr_idx[1] =
+ txcal_index_2057_rev3n4n6;
+ wlc_phy_txpwr_index_nphy(
+ pi, 3,
+ txcal_index_2057_rev3n4n6,
+ false);
} else {
- s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
- s8 lna1A_gain_db_2_rev7[] = {
- 12, 18, 22, 26 };
- s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+ pi->nphy_txcal_pwr_idx[0] =
+ txcal_index_2057_rev5n7;
+ pi->nphy_txcal_pwr_idx[1] =
+ txcal_index_2057_rev5n7;
+ wlc_phy_txpwr_index_nphy(
+ pi, 3,
+ txcal_index_2057_rev5n7,
+ false);
+ }
+ save_bbmult = true;
- crsminu_th = 0x41;
- lna1_gain_db = lna1A_gain_db_rev7;
- lna1_gain_db_2 = lna1A_gain_db_2_rev7;
- lna2_gain_db = lna2A_gain_db_rev7;
+ } else if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+ wlc_phy_cal_txgainctrl_nphy(pi, 11, false);
+ if (pi->sh->hw_phytxchain != 3) {
+ pi->nphy_txcal_pwr_idx[1] =
+ pi->nphy_txcal_pwr_idx[0];
+ wlc_phy_txpwr_index_nphy(pi, 3,
+ pi->
+ nphy_txcal_pwr_idx[0],
+ true);
+ save_bbmult = true;
}
- if (freq <= 4920) {
- nvar_baseline_offset0 = 5;
- nvar_baseline_offset1 = 5;
- } else if ((freq > 4920) && (freq <= 5320)) {
- nvar_baseline_offset0 = 3;
- nvar_baseline_offset1 = 5;
- } else if ((freq > 5320) && (freq <= 5700)) {
- nvar_baseline_offset0 = 3;
- nvar_baseline_offset1 = 2;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+ if (PHY_IPA(pi)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ wlc_phy_cal_txgainctrl_nphy(pi, 12,
+ false);
+ } else {
+ pi->nphy_txcal_pwr_idx[0] = 80;
+ pi->nphy_txcal_pwr_idx[1] = 80;
+ wlc_phy_txpwr_index_nphy(pi, 3, 80,
+ false);
+ save_bbmult = true;
+ }
} else {
- nvar_baseline_offset0 = 4;
- nvar_baseline_offset1 = 0;
+ wlc_phy_internal_cal_txgain_nphy(pi);
+ save_bbmult = true;
}
- } else {
-
- crsminu_th = 0x3a;
- crsminl_th = 0x3a;
- w1clip_th = 20;
- if ((freq >= 4920) && (freq <= 5320)) {
- nvar_baseline_offset0 = 4;
- nvar_baseline_offset1 = 5;
- } else if ((freq > 5320) && (freq <= 5550)) {
- nvar_baseline_offset0 = 4;
- nvar_baseline_offset1 = 2;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+ if (PHY_IPA(pi)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ wlc_phy_cal_txgainctrl_nphy(pi, 12,
+ false);
+ else
+ wlc_phy_cal_txgainctrl_nphy(pi, 14,
+ false);
} else {
- nvar_baseline_offset0 = 5;
- nvar_baseline_offset1 = 3;
+ wlc_phy_internal_cal_txgain_nphy(pi);
+ save_bbmult = true;
}
}
- write_phy_reg(pi, 0x20, init_gaincode);
- write_phy_reg(pi, 0x2a7, init_gaincode);
+ } else {
+ wlc_phy_cal_txgainctrl_nphy(pi, 10, false);
+ }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
- pi->pubpi.phy_corenum, 0x106, 16,
- rfseq_init_gain);
+ if (save_bbmult)
+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
+ &pi->nphy_txcal_bbmult);
+}
- write_phy_reg(pi, 0x22, clip1hi_gaincode);
- write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+static void
+wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value,
+ u8 core_code)
+{
+ u16 mask;
+ u16 val;
+ u8 core;
- write_phy_reg(pi, 0x36, clip1md_gaincode_B);
- write_phy_reg(pi, 0x2ac, clip1md_gaincode_B);
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+ if (core_code == RADIO_MIMO_CORESEL_CORE1
+ && core == PHY_CORE_1)
+ continue;
+ else if (core_code == RADIO_MIMO_CORESEL_CORE2
+ && core == PHY_CORE_0)
+ continue;
- write_phy_reg(pi, 0x37, clip1lo_gaincode);
- write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
- write_phy_reg(pi, 0x38, clip1lo_gaincode_B);
- write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B);
+ if (NREV_LT(pi->pubpi.phy_rev, 7)) {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
- tia_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
- tia_gain_db);
+ mask = (0x1 << 10);
+ val = 1 << 10;
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+ 0x92, mask, val);
+ }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
- tia_gainbits);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
- tia_gainbits);
+ if (field == NPHY_RfctrlIntc_override_OFF) {
- mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+ 0x92, 0);
- if (chg_nbclip_th == 1) {
- write_phy_reg(pi, 0x2b, nbclip_th);
- write_phy_reg(pi, 0x41, nbclip_th);
- }
+ wlc_phy_force_rfseq_nphy(pi,
+ NPHY_RFSEQ_RESET2RX);
+ } else if (field == NPHY_RfctrlIntc_override_TRSW) {
- mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0));
- mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0));
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- mod_phy_reg(pi, 0x2e4,
- (0x3f << 0), (nvar_baseline_offset0 << 0));
+ mask = (0x1 << 6) | (0x1 << 7);
- mod_phy_reg(pi, 0x2e4,
- (0x3f << 6), (nvar_baseline_offset1 << 6));
+ val = value << 6;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
- if (CHSPEC_IS20(pi->radio_chanspec)) {
+ or_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ (0x1 << 10));
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
- lna1_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
- lna1_gain_db_2);
+ and_phy_reg(pi, 0x2ff, (u16)
+ ~(0x3 << 14));
+ or_phy_reg(pi, 0x2ff, (0x1 << 13));
+ or_phy_reg(pi, 0x2ff, (0x1 << 0));
+ } else {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
- 8, lna2_gain_db);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
- 8, lna2_gain_db);
+ mask = (0x1 << 6) |
+ (0x1 << 7) |
+ (0x1 << 8) | (0x1 << 9);
+ val = value << 6;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
- write_phy_reg(pi, 0x24, clip1md_gaincode);
- write_phy_reg(pi, 0x2ab, clip1md_gaincode);
- } else {
- mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
- }
+ mask = (0x1 << 0);
+ val = 1 << 0;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0xe7 : 0xec,
+ mask, val);
- }
+ mask = (core == PHY_CORE_0) ?
+ (0x1 << 0) : (0x1 << 1);
+ val = 1 << ((core == PHY_CORE_0) ?
+ 0 : 1);
+ mod_phy_reg(pi, 0x78, mask, val);
+
+ SPINWAIT(((read_phy_reg(pi, 0x78) & val)
+ != 0), 10000);
+ if (WARN(read_phy_reg(pi, 0x78) & val,
+ "HW error: override failed"))
+ return;
+
+ mask = (0x1 << 0);
+ val = 0 << 0;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0xe7 : 0xec,
+ mask, val);
+ }
+ } else if (field == NPHY_RfctrlIntc_override_PA) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ mask = (0x1 << 4) | (0x1 << 5);
+
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ val = value << 5;
+ else
+ val = value << 4;
+
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ or_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ (0x1 << 12));
+ } else {
+
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ mask = (0x1 << 5);
+ val = value << 5;
+ } else {
+ mask = (0x1 << 4);
+ val = value << 4;
+ }
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ }
+ } else if (field ==
+ NPHY_RfctrlIntc_override_EXT_LNA_PU) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+ mask = (0x1 << 0);
+ val = value << 0;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, val);
+
+ mask = (0x1 << 2);
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, 0);
+ } else {
+
+ mask = (0x1 << 2);
+ val = value << 2;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, val);
+
+ mask = (0x1 << 0);
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, 0);
+ }
+
+ mask = (0x1 << 11);
+ val = 1 << 11;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ } else {
+
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ mask = (0x1 << 0);
+ val = value << 0;
+ } else {
+ mask = (0x1 << 2);
+ val = value << 2;
+ }
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ }
+ } else if (field ==
+ NPHY_RfctrlIntc_override_EXT_LNA_GAIN) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+ mask = (0x1 << 1);
+ val = value << 1;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, val);
+
+ mask = (0x1 << 3);
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, 0);
+ } else {
+
+ mask = (0x1 << 3);
+ val = value << 3;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, val);
+
+ mask = (0x1 << 1);
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91
+ : 0x92, mask, 0);
+ }
+
+ mask = (0x1 << 11);
+ val = 1 << 11;
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ } else {
+
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ mask = (0x1 << 1);
+ val = value << 1;
+ } else {
+ mask = (0x1 << 3);
+ val = value << 3;
+ }
+ mod_phy_reg(pi,
+ (core ==
+ PHY_CORE_0) ? 0x91 : 0x92,
+ mask, val);
+ }
+ }
+ }
+ }
}
-static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi)
+void
+wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower,
+ bool debug)
{
+ int gainctrl_loopidx;
uint core;
- int ctr;
- s16 gain_delta[2];
- u8 curr_channel;
- u16 minmax_gain[2];
- u16 regval[4];
+ u16 m0m1, curr_m0m1;
+ s32 delta_power;
+ s32 txpwrindex;
+ s32 qdBm_power[2];
+ u16 orig_BBConfig;
+ u16 phy_saveregs[4];
+ u32 freq_test;
+ u16 ampl_test = 250;
+ uint stepsize;
+ bool phyhang_avoid_state = false;
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ stepsize = 2;
+ else
+ stepsize = 1;
+
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ freq_test = 5000;
+ else
+ freq_test = 2500;
+
+ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
if (pi->phyhang_avoid)
wlc_phy_stay_in_carriersearch_nphy(pi, true);
- if (pi->nphy_gain_boost) {
- if ((CHSPEC_IS2G(pi->radio_chanspec))) {
+ phyhang_avoid_state = pi->phyhang_avoid;
+ pi->phyhang_avoid = false;
- gain_delta[0] = 6;
- gain_delta[1] = 6;
- } else {
+ phy_saveregs[0] = read_phy_reg(pi, 0x91);
+ phy_saveregs[1] = read_phy_reg(pi, 0x92);
+ phy_saveregs[2] = read_phy_reg(pi, 0xe7);
+ phy_saveregs[3] = read_phy_reg(pi, 0xec);
+ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1,
+ RADIO_MIMO_CORESEL_CORE1 |
+ RADIO_MIMO_CORESEL_CORE2);
- curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
- gain_delta[0] =
- (s16)
- PHY_HW_ROUND(((nphy_lnagain_est0[0] *
- curr_channel) +
- nphy_lnagain_est0[1]), 13);
- gain_delta[1] =
- (s16)
- PHY_HW_ROUND(((nphy_lnagain_est1[0] *
- curr_channel) +
- nphy_lnagain_est1[1]), 13);
- }
+ if (!debug) {
+ wlc_phy_rfctrlintc_override_nphy(pi,
+ NPHY_RfctrlIntc_override_TRSW,
+ 0x2, RADIO_MIMO_CORESEL_CORE1);
+ wlc_phy_rfctrlintc_override_nphy(pi,
+ NPHY_RfctrlIntc_override_TRSW,
+ 0x8, RADIO_MIMO_CORESEL_CORE2);
} else {
-
- gain_delta[0] = 0;
- gain_delta[1] = 0;
+ wlc_phy_rfctrlintc_override_nphy(pi,
+ NPHY_RfctrlIntc_override_TRSW,
+ 0x1, RADIO_MIMO_CORESEL_CORE1);
+ wlc_phy_rfctrlintc_override_nphy(pi,
+ NPHY_RfctrlIntc_override_TRSW,
+ 0x7, RADIO_MIMO_CORESEL_CORE2);
}
+ orig_BBConfig = read_phy_reg(pi, 0x01);
+ mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- if (pi->nphy_elna_gain_config) {
+ txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core];
- regval[0] = nphy_def_lnagains[2] + gain_delta[core];
- regval[1] = nphy_def_lnagains[3] + gain_delta[core];
- regval[2] = nphy_def_lnagains[3] + gain_delta[core];
- regval[3] = nphy_def_lnagains[3] + gain_delta[core];
- } else {
- for (ctr = 0; ctr < 4; ctr++) {
- regval[ctr] =
- nphy_def_lnagains[ctr] + gain_delta[core];
+ for (gainctrl_loopidx = 0; gainctrl_loopidx < 2;
+ gainctrl_loopidx++) {
+ wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+ false);
+
+ if (core == PHY_CORE_0)
+ curr_m0m1 = m0m1 & 0xff00;
+ else
+ curr_m0m1 = m0m1 & 0x00ff;
+
+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1);
+ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1);
+
+ udelay(50);
+
+ wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+ NPHY_CAL_TSSISAMPS);
+
+ pi->nphy_bb_mult_save = 0;
+ wlc_phy_stopplayback_nphy(pi);
+
+ delta_power = (dBm_targetpower * 4) - qdBm_power[core];
+
+ txpwrindex -= stepsize * delta_power;
+ if (txpwrindex < 0)
+ txpwrindex = 0;
+ else if (txpwrindex > 127)
+ txpwrindex = 127;
+
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ if (NREV_IS(pi->pubpi.phy_rev, 4) &&
+ (pi->srom_fem5g.extpagain == 3)) {
+ if (txpwrindex < 30)
+ txpwrindex = 30;
+ }
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+ (pi->srom_fem2g.extpagain == 3)) {
+ if (txpwrindex < 50)
+ txpwrindex = 50;
+ }
}
+
+ wlc_phy_txpwr_index_nphy(pi, (1 << core),
+ (u8) txpwrindex, true);
}
- wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval);
- minmax_gain[core] =
- (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4);
+ pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex;
+
+ if (debug) {
+ u16 radio_gain;
+ u16 dbg_m0m1;
+
+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+
+ wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+ false);
+
+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1);
+
+ udelay(100);
+
+ wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+ NPHY_CAL_TSSISAMPS);
+
+ wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16,
+ &radio_gain);
+
+ mdelay(4000);
+ pi->nphy_bb_mult_save = 0;
+ wlc_phy_stopplayback_nphy(pi);
+ }
}
- mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0));
- mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0));
+ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true);
+ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true);
+
+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult);
+
+ write_phy_reg(pi, 0x01, orig_BBConfig);
+
+ write_phy_reg(pi, 0x91, phy_saveregs[0]);
+ write_phy_reg(pi, 0x92, phy_saveregs[1]);
+ write_phy_reg(pi, 0xe7, phy_saveregs[2]);
+ write_phy_reg(pi, 0xec, phy_saveregs[3]);
+
+ pi->phyhang_avoid = phyhang_avoid_state;
if (pi->phyhang_avoid)
wlc_phy_stay_in_carriersearch_nphy(pi, false);
}
-void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on)
+static void wlc_phy_savecal_nphy(struct brcms_phy *pi)
{
- if (on) {
+ void *tbl_ptr;
+ int coreNum;
+ u16 *txcal_radio_regs = NULL;
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+ wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+ &pi->calibration_cache.
+ rxcal_coeffs_2G);
+
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (!pi->radio_is_on) {
- wlc_phy_radio_preinit_205x(pi);
- wlc_phy_radio_init_2057(pi);
- wlc_phy_radio_postinit_2057(pi);
- }
+ txcal_radio_regs =
+ pi->calibration_cache.txcal_radio_regs_2G;
+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
- pi->radio_chanspec);
+ pi->calibration_cache.txcal_radio_regs_2G[0] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_2G[1] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_2G[2] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX1);
+ pi->calibration_cache.txcal_radio_regs_2G[3] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX1);
+
+ pi->calibration_cache.txcal_radio_regs_2G[4] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_2G[5] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_2G[6] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX1);
+ pi->calibration_cache.txcal_radio_regs_2G[7] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX1);
+ } else {
+ pi->calibration_cache.txcal_radio_regs_2G[0] =
+ read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+ pi->calibration_cache.txcal_radio_regs_2G[1] =
+ read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+ pi->calibration_cache.txcal_radio_regs_2G[2] =
+ read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+ pi->calibration_cache.txcal_radio_regs_2G[3] =
+ read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
+ }
+
+ pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec;
+ tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+ } else {
+
+ wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+ &pi->calibration_cache.
+ rxcal_coeffs_5G);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ txcal_radio_regs =
+ pi->calibration_cache.txcal_radio_regs_5G;
} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- wlc_phy_radio_preinit_205x(pi);
- wlc_phy_radio_init_2056(pi);
- wlc_phy_radio_postinit_2056(pi);
- wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
- pi->radio_chanspec);
+ pi->calibration_cache.txcal_radio_regs_5G[0] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_5G[1] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_5G[2] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX1);
+ pi->calibration_cache.txcal_radio_regs_5G[3] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX1);
+
+ pi->calibration_cache.txcal_radio_regs_5G[4] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_5G[5] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX0);
+ pi->calibration_cache.txcal_radio_regs_5G[6] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX1);
+ pi->calibration_cache.txcal_radio_regs_5G[7] =
+ read_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX1);
} else {
- wlc_phy_radio_preinit_2055(pi);
- wlc_phy_radio_init_2055(pi);
- wlc_phy_radio_postinit_2055(pi);
+ pi->calibration_cache.txcal_radio_regs_5G[0] =
+ read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+ pi->calibration_cache.txcal_radio_regs_5G[1] =
+ read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+ pi->calibration_cache.txcal_radio_regs_5G[2] =
+ read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+ pi->calibration_cache.txcal_radio_regs_5G[3] =
+ read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
}
- pi->radio_is_on = true;
+ pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec;
+ tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+ }
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+ txcal_radio_regs[2 * coreNum] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_FINE_I);
+ txcal_radio_regs[2 * coreNum + 1] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_FINE_Q);
+
+ txcal_radio_regs[2 * coreNum + 4] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_COARSE_I);
+ txcal_radio_regs[2 * coreNum + 5] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_COARSE_Q);
+ }
+ }
+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr);
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi)
+{
+ struct nphy_iq_comp tx_comp;
+
+ wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, &tx_comp);
+
+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0);
+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0);
+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1);
+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1);
+}
+
+static void wlc_phy_restorecal_nphy(struct brcms_phy *pi)
+{
+ u16 *loft_comp;
+ u16 txcal_coeffs_bphy[4];
+ u16 *tbl_ptr;
+ int coreNum;
+ u16 *txcal_radio_regs = NULL;
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (pi->nphy_iqcal_chanspec_2G == 0)
+ return;
+
+ tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+ loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5];
} else {
+ if (pi->nphy_iqcal_chanspec_5G == 0)
+ return;
- if (NREV_GE(pi->pubpi.phy_rev, 3)
- && NREV_LT(pi->pubpi.phy_rev, 7)) {
- and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
- mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0);
+ tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+ loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5];
+ }
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16, tbl_ptr);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ txcal_coeffs_bphy[0] = tbl_ptr[0];
+ txcal_coeffs_bphy[1] = tbl_ptr[1];
+ txcal_coeffs_bphy[2] = tbl_ptr[2];
+ txcal_coeffs_bphy[3] = tbl_ptr[3];
+ } else {
+ txcal_coeffs_bphy[0] = 0;
+ txcal_coeffs_bphy[1] = 0;
+ txcal_coeffs_bphy[2] = 0;
+ txcal_coeffs_bphy[3] = 0;
+ }
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16,
+ txcal_coeffs_bphy);
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp);
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp);
+
+ if (NREV_LT(pi->pubpi.phy_rev, 2))
+ wlc_phy_tx_iq_war_nphy(pi);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ txcal_radio_regs =
+ pi->calibration_cache.txcal_radio_regs_2G;
+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
write_radio_reg(pi,
- RADIO_2056_TX_PADA_BOOST_TUNE |
- RADIO_2056_TX0, 0);
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[0]);
write_radio_reg(pi,
- RADIO_2056_TX_PADG_BOOST_TUNE |
- RADIO_2056_TX0, 0);
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[1]);
write_radio_reg(pi,
- RADIO_2056_TX_PGAA_BOOST_TUNE |
- RADIO_2056_TX0, 0);
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[2]);
write_radio_reg(pi,
- RADIO_2056_TX_PGAG_BOOST_TUNE |
- RADIO_2056_TX0, 0);
- mod_radio_reg(pi,
- RADIO_2056_TX_MIXA_BOOST_TUNE |
- RADIO_2056_TX0, 0xf0, 0);
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[3]);
+
write_radio_reg(pi,
- RADIO_2056_TX_MIXG_BOOST_TUNE |
- RADIO_2056_TX0, 0);
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[4]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[5]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[6]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[7]);
+ } else {
+ write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[0]);
+ write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[1]);
+ write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[2]);
+ write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+ pi->calibration_cache.
+ txcal_radio_regs_2G[3]);
+ }
+
+ wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+ &pi->calibration_cache.
+ rxcal_coeffs_2G);
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ txcal_radio_regs =
+ pi->calibration_cache.txcal_radio_regs_5G;
+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
write_radio_reg(pi,
- RADIO_2056_TX_PADA_BOOST_TUNE |
- RADIO_2056_TX1, 0);
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[0]);
write_radio_reg(pi,
- RADIO_2056_TX_PADG_BOOST_TUNE |
- RADIO_2056_TX1, 0);
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[1]);
write_radio_reg(pi,
- RADIO_2056_TX_PGAA_BOOST_TUNE |
- RADIO_2056_TX1, 0);
+ RADIO_2056_TX_LOFT_FINE_I |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[2]);
write_radio_reg(pi,
- RADIO_2056_TX_PGAG_BOOST_TUNE |
- RADIO_2056_TX1, 0);
- mod_radio_reg(pi,
- RADIO_2056_TX_MIXA_BOOST_TUNE |
- RADIO_2056_TX1, 0xf0, 0);
+ RADIO_2056_TX_LOFT_FINE_Q |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[3]);
+
write_radio_reg(pi,
- RADIO_2056_TX_MIXG_BOOST_TUNE |
- RADIO_2056_TX1, 0);
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[4]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX0,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[5]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_I |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[6]);
+ write_radio_reg(pi,
+ RADIO_2056_TX_LOFT_COARSE_Q |
+ RADIO_2056_TX1,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[7]);
+ } else {
+ write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[0]);
+ write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[1]);
+ write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[2]);
+ write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+ pi->calibration_cache.
+ txcal_radio_regs_5G[3]);
+ }
- pi->radio_is_on = false;
+ wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+ &pi->calibration_cache.
+ rxcal_coeffs_5G);
+ }
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_FINE_I,
+ txcal_radio_regs[2 * coreNum]);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_FINE_Q,
+ txcal_radio_regs[2 * coreNum + 1]);
+
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_COARSE_I,
+ txcal_radio_regs[2 * coreNum + 4]);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+ LOFT_COARSE_Q,
+ txcal_radio_regs[2 * coreNum + 5]);
}
+ }
+}
- if (NREV_GE(pi->pubpi.phy_rev, 8)) {
- and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
- pi->radio_is_on = false;
+static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi)
+{
+ u32 idx;
+ u16 iqloCalbuf[7];
+ u32 iqcomp, locomp, curr_locomp;
+ s8 locomp_i, locomp_q;
+ s8 curr_locomp_i, curr_locomp_q;
+ u32 tbl_id, tbl_len, tbl_offset;
+ u32 regval[128];
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+ wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf);
+
+ tbl_len = 128;
+ tbl_offset = 320;
+ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+ iqcomp =
+ (tbl_id ==
+ 26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) |
+ (iqloCalbuf[1] & 0x3ff)
+ : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) |
+ (iqloCalbuf[3] & 0x3ff);
+
+ for (idx = 0; idx < tbl_len; idx++)
+ regval[idx] = iqcomp;
+ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+ regval);
+ }
+
+ tbl_offset = 448;
+ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+
+ locomp =
+ (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]);
+ locomp_i = (s8) ((locomp >> 8) & 0xff);
+ locomp_q = (s8) ((locomp) & 0xff);
+ for (idx = 0; idx < tbl_len; idx++) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ curr_locomp_i = locomp_i;
+ curr_locomp_q = locomp_q;
+ } else {
+ curr_locomp_i = (s8) ((locomp_i *
+ nphy_tpc_loscale[idx] +
+ 128) >> 8);
+ curr_locomp_q =
+ (s8) ((locomp_q *
+ nphy_tpc_loscale[idx] +
+ 128) >> 8);
+ }
+ curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8);
+ curr_locomp |= (u32) (curr_locomp_q & 0xff);
+ regval[idx] = curr_locomp;
}
+ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+ regval);
+ }
+
+ if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+ wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF);
+ wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF);
}
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
}
-static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi)
+static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi)
{
+ u8 tx_lpf_bw = 0;
- and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE);
- or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE);
+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ tx_lpf_bw = 3;
+ else
+ tx_lpf_bw = 1;
- or_phy_reg(pi, 0x78, RFCC_POR_FORCE);
+ if (PHY_IPA(pi)) {
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ tx_lpf_bw = 5;
+ else
+ tx_lpf_bw = 4;
+ }
+
+ write_phy_reg(pi, 0xe8,
+ (tx_lpf_bw << 0) |
+ (tx_lpf_bw << 3) |
+ (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+
+ if (PHY_IPA(pi)) {
+
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ tx_lpf_bw = 4;
+ else
+ tx_lpf_bw = 1;
+
+ write_phy_reg(pi, 0xe9,
+ (tx_lpf_bw << 0) |
+ (tx_lpf_bw << 3) |
+ (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+ }
+ }
}
-static void wlc_phy_radio_init_2055(struct brcms_phy *pi)
+static void
+wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi, u16 reduction_factr)
{
- wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE);
+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+ if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+ CHSPEC_IS40(pi->radio_chanspec)) {
+ if (!pi->nphy_anarxlpf_adjusted) {
+ write_radio_reg(pi,
+ (RADIO_2056_RX_RXLPF_RCCAL_LPC |
+ RADIO_2056_RX0),
+ ((pi->nphy_rccal_value +
+ reduction_factr) | 0x80));
+
+ pi->nphy_anarxlpf_adjusted = true;
+ }
+ } else {
+ if (pi->nphy_anarxlpf_adjusted) {
+ write_radio_reg(pi,
+ (RADIO_2056_RX_RXLPF_RCCAL_LPC |
+ RADIO_2056_RX0),
+ (pi->nphy_rccal_value | 0x80));
+
+ pi->nphy_anarxlpf_adjusted = false;
+ }
+ }
+ }
}
-static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi)
+static void
+wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones,
+ int *tone_id_buf, u32 *noise_var_buf)
{
+ int i;
+ u32 offset;
+ int tone_id;
+ int tbllen =
+ CHSPEC_IS40(pi->radio_chanspec) ?
+ NPHY_NOISEVAR_TBLLEN40 : NPHY_NOISEVAR_TBLLEN20;
- and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1,
- ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK));
+ if (pi->nphy_noisevars_adjusted) {
+ for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) {
+ tone_id = pi->nphy_saved_noisevars.tone_id[i];
+ offset = (tone_id >= 0) ?
+ ((tone_id *
+ 2) + 1) : (tbllen + (tone_id * 2) + 1);
+ wlc_phy_table_write_nphy(
+ pi, NPHY_TBL_ID_NOISEVAR, 1,
+ offset, 32,
+ &pi->nphy_saved_noisevars.min_noise_vars[i]);
+ }
- if (((pi->sh->sromrev >= 4)
- && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS))
- || ((pi->sh->sromrev < 4))) {
- and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F);
- and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F);
+ pi->nphy_saved_noisevars.bufcount = 0;
+ pi->nphy_noisevars_adjusted = false;
}
- mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C);
- write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C);
+ if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) {
+ pi->nphy_saved_noisevars.bufcount = 0;
- and_radio_reg(pi, RADIO_2055_CAL_MISC,
- ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N));
+ for (i = 0; i < ntones; i++) {
+ tone_id = tone_id_buf[i];
+ offset = (tone_id >= 0) ?
+ ((tone_id * 2) + 1) :
+ (tbllen + (tone_id * 2) + 1);
+ pi->nphy_saved_noisevars.tone_id[i] = tone_id;
+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+ offset, 32,
+ &pi->nphy_saved_noisevars.
+ min_noise_vars[i]);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+ offset, 32, &noise_var_buf[i]);
+ pi->nphy_saved_noisevars.bufcount++;
+ }
- or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE);
+ pi->nphy_noisevars_adjusted = true;
+ }
+}
- or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N);
+static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr)
+{
+ u16 regval;
- udelay(1000);
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+ CHSPEC_IS40(pi->radio_chanspec)) {
+ if (!pi->nphy_crsminpwr_adjusted) {
+ regval = read_phy_reg(pi, 0x27d);
+ pi->nphy_crsminpwr[0] = regval & 0xff;
+ regval &= 0xff00;
+ regval |= (u16) minpwr;
+ write_phy_reg(pi, 0x27d, regval);
- or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START);
+ regval = read_phy_reg(pi, 0x280);
+ pi->nphy_crsminpwr[1] = regval & 0xff;
+ regval &= 0xff00;
+ regval |= (u16) minpwr;
+ write_phy_reg(pi, 0x280, regval);
- SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
- RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000);
+ regval = read_phy_reg(pi, 0x283);
+ pi->nphy_crsminpwr[2] = regval & 0xff;
+ regval &= 0xff00;
+ regval |= (u16) minpwr;
+ write_phy_reg(pi, 0x283, regval);
- if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
- RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE,
- "HW error: radio calibration1\n"))
+ pi->nphy_crsminpwr_adjusted = true;
+ }
+ } else {
+ if (pi->nphy_crsminpwr_adjusted) {
+ regval = read_phy_reg(pi, 0x27d);
+ regval &= 0xff00;
+ regval |= pi->nphy_crsminpwr[0];
+ write_phy_reg(pi, 0x27d, regval);
+
+ regval = read_phy_reg(pi, 0x280);
+ regval &= 0xff00;
+ regval |= pi->nphy_crsminpwr[1];
+ write_phy_reg(pi, 0x280, regval);
+
+ regval = read_phy_reg(pi, 0x283);
+ regval &= 0xff00;
+ regval |= pi->nphy_crsminpwr[2];
+ write_phy_reg(pi, 0x283, regval);
+
+ pi->nphy_crsminpwr_adjusted = false;
+ }
+ }
+ }
+}
+
+static void wlc_phy_spurwar_nphy(struct brcms_phy *pi)
+{
+ u16 cur_channel = 0;
+ int nphy_adj_tone_id_buf[] = { 57, 58 };
+ u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff };
+ bool isAdjustNoiseVar = false;
+ uint numTonesAdjust = 0;
+ u32 tempval = 0;
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+ cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+
+ if (pi->nphy_gband_spurwar_en) {
+
+ wlc_phy_adjust_rx_analpfbw_nphy(
+ pi,
+ NPHY_ANARXLPFBW_REDUCTIONFACT);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if ((cur_channel == 11)
+ && CHSPEC_IS40(pi->radio_chanspec))
+ wlc_phy_adjust_min_noisevar_nphy(
+ pi, 2,
+ nphy_adj_tone_id_buf,
+ nphy_adj_noise_var_buf);
+ else
+ wlc_phy_adjust_min_noisevar_nphy(pi, 0,
+ NULL,
+ NULL);
+ }
+
+ wlc_phy_adjust_crsminpwr_nphy(pi,
+ NPHY_ADJUSTED_MINCRSPOWER);
+ }
+
+ if ((pi->nphy_gband_spurwar2_en)
+ && CHSPEC_IS2G(pi->radio_chanspec)) {
+
+ if (CHSPEC_IS40(pi->radio_chanspec)) {
+ switch (cur_channel) {
+ case 3:
+ nphy_adj_tone_id_buf[0] = 57;
+ nphy_adj_tone_id_buf[1] = 58;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x25f;
+ isAdjustNoiseVar = true;
+ break;
+ case 4:
+ nphy_adj_tone_id_buf[0] = 41;
+ nphy_adj_tone_id_buf[1] = 42;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x25f;
+ isAdjustNoiseVar = true;
+ break;
+ case 5:
+ nphy_adj_tone_id_buf[0] = 25;
+ nphy_adj_tone_id_buf[1] = 26;
+ nphy_adj_noise_var_buf[0] = 0x24f;
+ nphy_adj_noise_var_buf[1] = 0x25f;
+ isAdjustNoiseVar = true;
+ break;
+ case 6:
+ nphy_adj_tone_id_buf[0] = 9;
+ nphy_adj_tone_id_buf[1] = 10;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x24f;
+ isAdjustNoiseVar = true;
+ break;
+ case 7:
+ nphy_adj_tone_id_buf[0] = 121;
+ nphy_adj_tone_id_buf[1] = 122;
+ nphy_adj_noise_var_buf[0] = 0x18f;
+ nphy_adj_noise_var_buf[1] = 0x24f;
+ isAdjustNoiseVar = true;
+ break;
+ case 8:
+ nphy_adj_tone_id_buf[0] = 105;
+ nphy_adj_tone_id_buf[1] = 106;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x25f;
+ isAdjustNoiseVar = true;
+ break;
+ case 9:
+ nphy_adj_tone_id_buf[0] = 89;
+ nphy_adj_tone_id_buf[1] = 90;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x24f;
+ isAdjustNoiseVar = true;
+ break;
+ case 10:
+ nphy_adj_tone_id_buf[0] = 73;
+ nphy_adj_tone_id_buf[1] = 74;
+ nphy_adj_noise_var_buf[0] = 0x22f;
+ nphy_adj_noise_var_buf[1] = 0x24f;
+ isAdjustNoiseVar = true;
+ break;
+ default:
+ isAdjustNoiseVar = false;
+ break;
+ }
+ }
+
+ if (isAdjustNoiseVar) {
+ numTonesAdjust = sizeof(nphy_adj_tone_id_buf) /
+ sizeof(nphy_adj_tone_id_buf[0]);
+
+ wlc_phy_adjust_min_noisevar_nphy(
+ pi,
+ numTonesAdjust,
+ nphy_adj_tone_id_buf,
+ nphy_adj_noise_var_buf);
+
+ tempval = 0;
+
+ } else {
+ wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+ NULL);
+ }
+ }
+
+ if ((pi->nphy_aband_spurwar_en) &&
+ (CHSPEC_IS5G(pi->radio_chanspec))) {
+ switch (cur_channel) {
+ case 54:
+ nphy_adj_tone_id_buf[0] = 32;
+ nphy_adj_noise_var_buf[0] = 0x25f;
+ break;
+ case 38:
+ case 102:
+ case 118:
+ nphy_adj_tone_id_buf[0] = 0;
+ nphy_adj_noise_var_buf[0] = 0x0;
+ break;
+ case 134:
+ nphy_adj_tone_id_buf[0] = 32;
+ nphy_adj_noise_var_buf[0] = 0x21f;
+ break;
+ case 151:
+ nphy_adj_tone_id_buf[0] = 16;
+ nphy_adj_noise_var_buf[0] = 0x23f;
+ break;
+ case 153:
+ case 161:
+ nphy_adj_tone_id_buf[0] = 48;
+ nphy_adj_noise_var_buf[0] = 0x23f;
+ break;
+ default:
+ nphy_adj_tone_id_buf[0] = 0;
+ nphy_adj_noise_var_buf[0] = 0x0;
+ break;
+ }
+
+ if (nphy_adj_tone_id_buf[0]
+ && nphy_adj_noise_var_buf[0])
+ wlc_phy_adjust_min_noisevar_nphy(
+ pi, 1,
+ nphy_adj_tone_id_buf,
+ nphy_adj_noise_var_buf);
+ else
+ wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+ NULL);
+ }
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+ }
+}
+
+void wlc_phy_init_nphy(struct brcms_phy *pi)
+{
+ u16 val;
+ u16 clip1_ths[2];
+ struct nphy_txgains target_gain;
+ u8 tx_pwr_ctrl_state;
+ bool do_nphy_cal = false;
+ uint core;
+ uint origidx, intr_val;
+ struct d11regs __iomem *regs;
+ u32 d11_clk_ctl_st;
+ bool do_rssi_cal = false;
+
+ core = 0;
+
+ if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN))
+ pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
+
+ if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
+ ((pi->sh->chippkg == BCM4717_PKG_ID) ||
+ (pi->sh->chippkg == BCM4718_PKG_ID))) {
+ if ((pi->sh->boardflags & BFL_EXTLNA) &&
+ (CHSPEC_IS2G(pi->radio_chanspec)))
+ ai_corereg(pi->sh->sih, SI_CC_IDX,
+ offsetof(struct chipcregs, chipcontrol),
+ 0x40, 0x40);
+ }
+
+ if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
+ CHSPEC_IS40(pi->radio_chanspec)) {
+
+ regs = (struct d11regs __iomem *)
+ ai_switch_core(pi->sh->sih,
+ D11_CORE_ID, &origidx,
+ &intr_val);
+ d11_clk_ctl_st = R_REG(&regs->clk_ctl_st);
+ AND_REG(&regs->clk_ctl_st,
+ ~(CCS_FORCEHT | CCS_HTAREQ));
+
+ W_REG(&regs->clk_ctl_st, d11_clk_ctl_st);
+
+ ai_restore_core(pi->sh->sih, origidx, intr_val);
+ }
+
+ pi->use_int_tx_iqlo_cal_nphy =
+ (PHY_IPA(pi) ||
+ (NREV_GE(pi->pubpi.phy_rev, 7) ||
+ (NREV_GE(pi->pubpi.phy_rev, 5)
+ && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL)));
+
+ pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false;
+
+ pi->nphy_deaf_count = 0;
+
+ wlc_phy_tbl_init_nphy(pi);
+
+ pi->nphy_crsminpwr_adjusted = false;
+ pi->nphy_noisevars_adjusted = false;
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ write_phy_reg(pi, 0xe7, 0);
+ write_phy_reg(pi, 0xec, 0);
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ write_phy_reg(pi, 0x342, 0);
+ write_phy_reg(pi, 0x343, 0);
+ write_phy_reg(pi, 0x346, 0);
+ write_phy_reg(pi, 0x347, 0);
+ }
+ write_phy_reg(pi, 0xe5, 0);
+ write_phy_reg(pi, 0xe6, 0);
+ } else {
+ write_phy_reg(pi, 0xec, 0);
+ }
+
+ write_phy_reg(pi, 0x91, 0);
+ write_phy_reg(pi, 0x92, 0);
+ if (NREV_LT(pi->pubpi.phy_rev, 6)) {
+ write_phy_reg(pi, 0x93, 0);
+ write_phy_reg(pi, 0x94, 0);
+ }
+
+ and_phy_reg(pi, 0xa1, ~3);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ write_phy_reg(pi, 0x8f, 0);
+ write_phy_reg(pi, 0xa5, 0);
+ } else {
+ write_phy_reg(pi, 0xa5, 0);
+ }
+
+ if (NREV_IS(pi->pubpi.phy_rev, 2))
+ mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
+ else if (NREV_LT(pi->pubpi.phy_rev, 2))
+ mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
+
+ write_phy_reg(pi, 0x203, 32);
+ write_phy_reg(pi, 0x201, 32);
+
+ if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD)
+ write_phy_reg(pi, 0x20d, 160);
+ else
+ write_phy_reg(pi, 0x20d, 184);
+
+ write_phy_reg(pi, 0x13a, 200);
+
+ write_phy_reg(pi, 0x70, 80);
+
+ write_phy_reg(pi, 0x1ff, 48);
+
+ if (NREV_LT(pi->pubpi.phy_rev, 8))
+ wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override);
+
+ wlc_phy_stf_chain_upd_nphy(pi);
+
+ if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+ write_phy_reg(pi, 0x180, 0xaa8);
+ write_phy_reg(pi, 0x181, 0x9a4);
+ }
+
+ if (PHY_IPA(pi)) {
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (1) << 0);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 :
+ 0x29c, (0x1ff << 7),
+ (pi->nphy_papd_epsilon_offset[core]) << 7);
+
+ }
+
+ wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+ } else if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+ wlc_phy_extpa_set_tx_digi_filts_nphy(pi);
+ }
+
+ wlc_phy_workarounds_nphy(pi);
+
+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+ val = read_phy_reg(pi, 0x01);
+ write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+ write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+ wlapi_bmac_macphyclk_set(pi->sh->physhim, ON);
+
+ wlc_phy_pa_override_nphy(pi, OFF);
+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+ wlc_phy_pa_override_nphy(pi, ON);
+
+ wlc_phy_classifier_nphy(pi, 0, 0);
+ wlc_phy_clip_det_nphy(pi, 0, clip1_ths);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ wlc_phy_bphy_init_nphy(pi);
+
+ tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+ wlc_phy_txpwr_fixpower_nphy(pi);
+
+ wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+
+ wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ u32 *tx_pwrctrl_tbl = NULL;
+ u16 idx;
+ s16 pga_gn = 0;
+ s16 pad_gn = 0;
+ s32 rfpwr_offset;
+
+ if (PHY_IPA(pi)) {
+ tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi);
+ } else {
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ if (NREV_IS(pi->pubpi.phy_rev, 3))
+ tx_pwrctrl_tbl =
+ nphy_tpc_5GHz_txgain_rev3;
+ else if (NREV_IS(pi->pubpi.phy_rev, 4))
+ tx_pwrctrl_tbl =
+ (pi->srom_fem5g.extpagain ==
+ 3) ?
+ nphy_tpc_5GHz_txgain_HiPwrEPA :
+ nphy_tpc_5GHz_txgain_rev4;
+ else
+ tx_pwrctrl_tbl =
+ nphy_tpc_5GHz_txgain_rev5;
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (pi->pubpi.radiorev == 5)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_epa_2057rev5;
+ else if (pi->pubpi.radiorev == 3)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_epa_2057rev3;
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+ (pi->srom_fem2g.extpagain == 3))
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_HiPwrEPA;
+ else
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_rev3;
+ }
+ }
+ }
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+ 192, 32, tx_pwrctrl_tbl);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+ 192, 32, tx_pwrctrl_tbl);
+
+ pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ for (idx = 0; idx < 128; idx++) {
+ pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+ pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f;
+ rfpwr_offset = get_rf_pwr_offset(pi, pga_gn,
+ pad_gn);
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_CORE1TXPWRCTL,
+ 1, 576 + idx, 32,
+ &rfpwr_offset);
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_CORE2TXPWRCTL,
+ 1, 576 + idx, 32,
+ &rfpwr_offset);
+ }
+ } else {
+
+ for (idx = 0; idx < 128; idx++) {
+ pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ rfpwr_offset = (s16)
+ nphy_papd_pga_gain_delta_ipa_2g
+ [pga_gn];
+ else
+ rfpwr_offset = (s16)
+ nphy_papd_pga_gain_delta_ipa_5g
+ [pga_gn];
+
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_CORE1TXPWRCTL,
+ 1, 576 + idx, 32,
+ &rfpwr_offset);
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_CORE2TXPWRCTL,
+ 1, 576 + idx, 32,
+ &rfpwr_offset);
+ }
+
+ }
+ } else {
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+ 192, 32, nphy_tpc_txgain);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+ 192, 32, nphy_tpc_txgain);
+ }
+
+ if (pi->sh->phyrxchain != 0x3)
+ wlc_phy_rxcore_setstate_nphy((struct brcms_phy_pub *) pi,
+ pi->sh->phyrxchain);
+
+ if (PHY_PERICAL_MPHASE_PENDING(pi))
+ wlc_phy_cal_perical_mphase_restart(pi);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+ (pi->nphy_rssical_chanspec_2G == 0) :
+ (pi->nphy_rssical_chanspec_5G == 0);
+
+ if (do_rssi_cal)
+ wlc_phy_rssi_cal_nphy(pi);
+ else
+ wlc_phy_restore_rssical_nphy(pi);
+ } else {
+ wlc_phy_rssi_cal_nphy(pi);
+ }
+
+ if (!SCAN_RM_IN_PROGRESS(pi))
+ do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+ (pi->nphy_iqcal_chanspec_2G == 0) :
+ (pi->nphy_iqcal_chanspec_5G == 0);
+
+ if (!pi->do_initcal)
+ do_nphy_cal = false;
+
+ if (do_nphy_cal) {
+
+ target_gain = wlc_phy_get_tx_gain_nphy(pi);
+
+ if (pi->antsel_type == ANTSEL_2x3)
+ wlc_phy_antsel_init((struct brcms_phy_pub *) pi,
+ true);
+
+ if (pi->nphy_perical != PHY_PERICAL_MPHASE) {
+ wlc_phy_rssi_cal_nphy(pi);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ pi->nphy_cal_orig_pwr_idx[0] =
+ pi->nphy_txpwrindex[PHY_CORE_0]
+ .
+ index_internal;
+ pi->nphy_cal_orig_pwr_idx[1] =
+ pi->nphy_txpwrindex[PHY_CORE_1]
+ .
+ index_internal;
+
+ wlc_phy_precal_txgain_nphy(pi);
+ target_gain =
+ wlc_phy_get_tx_gain_nphy(pi);
+ }
+
+ if (wlc_phy_cal_txiqlo_nphy
+ (pi, target_gain, true,
+ false) == 0) {
+ if (wlc_phy_cal_rxiq_nphy
+ (pi, target_gain, 2,
+ false) == 0)
+ wlc_phy_savecal_nphy(pi);
+
+ }
+ } else if (pi->mphase_cal_phase_id ==
+ MPHASE_CAL_STATE_IDLE) {
+ wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
+ PHY_PERICAL_PHYINIT);
+ }
+ } else {
+ wlc_phy_restorecal_nphy(pi);
+ }
+
+ wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+
+ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+
+ wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6))
+
+ write_phy_reg(pi, 0x70, 50);
+
+ wlc_phy_txlpfbw_nphy(pi);
+
+ wlc_phy_spurwar_nphy(pi);
+
+}
+
+static void wlc_phy_resetcca_nphy(struct brcms_phy *pi)
+{
+ u16 val;
+
+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+ val = read_phy_reg(pi, 0x01);
+ write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+ udelay(1);
+ write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+
+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+}
+
+void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en)
+{
+ u16 rfctrlintc_override_val;
+
+ if (!en) {
+
+ pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91);
+ pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ rfctrlintc_override_val = 0x1480;
+ else if (NREV_GE(pi->pubpi.phy_rev, 3))
+ rfctrlintc_override_val =
+ CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480;
+ else
+ rfctrlintc_override_val =
+ CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+
+ write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+ write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+ } else {
+ write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save);
+ write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save);
+ }
+
+}
+
+void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi)
+{
+
+ u16 txrx_chain =
+ (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1);
+ bool CoreActv_override = false;
+
+ if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN0) {
+ txrx_chain = NPHY_RfseqCoreActv_TxRxChain0;
+ CoreActv_override = true;
+
+ if (NREV_LE(pi->pubpi.phy_rev, 2))
+ and_phy_reg(pi, 0xa0, ~0x20);
+ } else if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN1) {
+ txrx_chain = NPHY_RfseqCoreActv_TxRxChain1;
+ CoreActv_override = true;
+
+ if (NREV_LE(pi->pubpi.phy_rev, 2))
+ or_phy_reg(pi, 0xa0, 0x20);
+ }
+
+ mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain);
+
+ if (CoreActv_override) {
+ pi->nphy_perical = PHY_PERICAL_DISABLE;
+ or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
+ } else {
+ pi->nphy_perical = PHY_PERICAL_MPHASE;
+ and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override);
+ }
+}
+
+void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask)
+{
+ u16 regval;
+ u16 tbl_buf[16];
+ uint i;
+ struct brcms_phy *pi = (struct brcms_phy *) pih;
+ u16 tbl_opcode;
+ bool suspend;
+
+ pi->sh->phyrxchain = rxcore_bitmask;
+
+ if (!pi->sh->clk)
return;
- and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL,
- ~(RADIO_2055_CAL_LPO_ENABLE));
+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ if (!suspend)
+ wlapi_suspend_mac_and_wait(pi->sh->physhim);
- wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
- write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9);
- write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9);
+ regval = read_phy_reg(pi, 0xa2);
+ regval &= ~(0xf << 4);
+ regval |= ((u16) (rxcore_bitmask & 0x3)) << 4;
+ write_phy_reg(pi, 0xa2, regval);
- write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83);
- write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83);
+ if ((rxcore_bitmask & 0x3) != 0x3) {
- mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST,
- RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
- mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST,
- RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
- if (pi->nphy_gain_boost) {
- and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
- ~(RADIO_2055_GAINBST_DISABLE));
- and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
- ~(RADIO_2055_GAINBST_DISABLE));
+ write_phy_reg(pi, 0x20e, 1);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (pi->rx2tx_biasentry == -1) {
+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ,
+ ARRAY_SIZE(tbl_buf), 80,
+ 16, tbl_buf);
+
+ for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) {
+ if (tbl_buf[i] ==
+ NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) {
+ pi->rx2tx_biasentry = (u8) i;
+ tbl_opcode =
+ NPHY_REV3_RFSEQ_CMD_NOP;
+ wlc_phy_table_write_nphy(
+ pi,
+ NPHY_TBL_ID_RFSEQ,
+ 1, i,
+ 16,
+ &tbl_opcode);
+ break;
+ } else if (tbl_buf[i] ==
+ NPHY_REV3_RFSEQ_CMD_END)
+ break;
+ }
+ }
+ }
} else {
- or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
- RADIO_2055_GAINBST_DISABLE);
- or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
- RADIO_2055_GAINBST_DISABLE);
+
+ write_phy_reg(pi, 0x20e, 30);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (pi->rx2tx_biasentry != -1) {
+ tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+ 1, pi->rx2tx_biasentry,
+ 16, &tbl_opcode);
+ pi->rx2tx_biasentry = -1;
+ }
+ }
}
- udelay(2);
+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+ if (!suspend)
+ wlapi_enable_mac(pi->sh->physhim);
+}
+
+u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih)
+{
+ u16 regval, rxen_bits;
+ struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+ regval = read_phy_reg(pi, 0xa2);
+ rxen_bits = (regval >> 4) & 0xf;
+
+ return (u8) rxen_bits;
+}
+
+bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pi)
+{
+ return PHY_IPA(pi);
+}
+
+void wlc_phy_cal_init_nphy(struct brcms_phy *pi)
+{
}
static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi)
@@ -17442,11 +20004,257 @@ static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi)
}
+static void wlc_phy_radio_init_2057(struct brcms_phy *pi)
+{
+ struct radio_20xx_regs *regs_2057_ptr = NULL;
+
+ if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+ regs_2057_ptr = regs_2057_rev4;
+ } else if (NREV_IS(pi->pubpi.phy_rev, 8)
+ || NREV_IS(pi->pubpi.phy_rev, 9)) {
+ switch (pi->pubpi.radiorev) {
+ case 5:
+
+ if (pi->pubpi.radiover == 0x0)
+ regs_2057_ptr = regs_2057_rev5;
+ else if (pi->pubpi.radiover == 0x1)
+ regs_2057_ptr = regs_2057_rev5v1;
+ else
+ break;
+
+ case 7:
+
+ regs_2057_ptr = regs_2057_rev7;
+ break;
+
+ case 8:
+
+ regs_2057_ptr = regs_2057_rev8;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr);
+}
+
+static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi)
+{
+ u16 rcal_reg = 0;
+ int i;
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ if (pi->pubpi.radiorev == 5) {
+
+ and_phy_reg(pi, 0x342, ~(0x1 << 1));
+
+ udelay(10);
+
+ mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1);
+ mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+ 0x1);
+ }
+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1);
+
+ udelay(10);
+
+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3);
+
+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+ rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS);
+ if (rcal_reg & 0x1)
+ break;
+
+ udelay(100);
+ }
+
+ if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
+ "HW error: radio calib2"))
+ return 0;
+
+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0);
+
+ rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e;
+
+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0);
+ if (pi->pubpi.radiorev == 5) {
+
+ mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0);
+ mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+ 0x0);
+ }
+
+ if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
+
+ mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c,
+ rcal_reg);
+ mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0,
+ rcal_reg << 2);
+ }
+
+ } else if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+ u16 savereg;
+
+ savereg =
+ read_radio_reg(
+ pi,
+ RADIO_2056_SYN_PLL_MAST2 |
+ RADIO_2056_SYN);
+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+ savereg | 0x7);
+ udelay(10);
+
+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+ 0x1);
+ udelay(10);
+
+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+ 0x9);
+
+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+ rcal_reg = read_radio_reg(
+ pi,
+ RADIO_2056_SYN_RCAL_CODE_OUT |
+ RADIO_2056_SYN);
+ if (rcal_reg & 0x80)
+ break;
+
+ udelay(100);
+ }
+
+ if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
+ "HW error: radio calib3"))
+ return 0;
+
+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+ 0x1);
+
+ rcal_reg =
+ read_radio_reg(pi,
+ RADIO_2056_SYN_RCAL_CODE_OUT |
+ RADIO_2056_SYN);
+
+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+ 0x0);
+
+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+ savereg);
+
+ return rcal_reg & 0x1f;
+ }
+ return rcal_reg & 0x3e;
+}
+
+static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi)
+{
+ u16 rccal_valid;
+ int i;
+ bool chip43226_6362A0;
+
+ chip43226_6362A0 = ((pi->pubpi.radiorev == 3)
+ || (pi->pubpi.radiorev == 4)
+ || (pi->pubpi.radiorev == 6));
+
+ rccal_valid = 0;
+ if (chip43226_6362A0) {
+ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61);
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0);
+ } else {
+ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61);
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9);
+ }
+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+ if (rccal_valid & 0x2)
+ break;
+
+ udelay(500);
+ }
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+ rccal_valid = 0;
+ if (chip43226_6362A0) {
+ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69);
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+ } else {
+ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69);
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5);
+ }
+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+ if (rccal_valid & 0x2)
+ break;
+
+ udelay(500);
+ }
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+ rccal_valid = 0;
+ if (chip43226_6362A0) {
+ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73);
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28);
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+ } else {
+ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73);
+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99);
+ }
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+ if (rccal_valid & 0x2)
+ break;
+
+ udelay(500);
+ }
+
+ if (WARN(!(rccal_valid & 0x2), "HW error: radio calib4"))
+ return 0;
+
+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+ return rccal_valid;
+}
+
+static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi)
+{
+
+ mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1);
+
+ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78);
+ mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80);
+ mdelay(2);
+ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0);
+ mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0);
+
+ if (pi->phy_init_por) {
+ wlc_phy_radio205x_rcal(pi);
+ wlc_phy_radio2057_rccal(pi);
+ }
+
+ mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0);
+}
+
static void wlc_phy_radio_init_2056(struct brcms_phy *pi)
{
- struct radio_regs *regs_SYN_2056_ptr = NULL;
- struct radio_regs *regs_TX_2056_ptr = NULL;
- struct radio_regs *regs_RX_2056_ptr = NULL;
+ const struct radio_regs *regs_SYN_2056_ptr = NULL;
+ const struct radio_regs *regs_TX_2056_ptr = NULL;
+ const struct radio_regs *regs_RX_2056_ptr = NULL;
if (NREV_IS(pi->pubpi.phy_rev, 3)) {
regs_SYN_2056_ptr = regs_SYN_2056;
@@ -17515,92 +20323,190 @@ static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi)
mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0);
if ((pi->sh->boardflags2 & BFL2_LEGACY)
- || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) {
-
+ || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN))
mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0);
- } else {
-
+ else
mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0);
- }
mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0);
- if (pi->phy_init_por) {
+ if (pi->phy_init_por)
wlc_phy_radio205x_rcal(pi);
- }
}
-static void wlc_phy_radio_init_2057(struct brcms_phy *pi)
+static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi)
{
- struct radio_20xx_regs *regs_2057_ptr = NULL;
- if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+ and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE);
+ or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE);
- regs_2057_ptr = regs_2057_rev4;
- } else if (NREV_IS(pi->pubpi.phy_rev, 8)
- || NREV_IS(pi->pubpi.phy_rev, 9)) {
- switch (pi->pubpi.radiorev) {
- case 5:
+ or_phy_reg(pi, 0x78, RFCC_POR_FORCE);
+}
- if (pi->pubpi.radiover == 0x0) {
+static void wlc_phy_radio_init_2055(struct brcms_phy *pi)
+{
+ wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE);
+}
- regs_2057_ptr = regs_2057_rev5;
+static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi)
+{
- } else if (pi->pubpi.radiover == 0x1) {
+ and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1,
+ ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK));
- regs_2057_ptr = regs_2057_rev5v1;
- } else {
- break;
- }
+ if (((pi->sh->sromrev >= 4)
+ && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS))
+ || ((pi->sh->sromrev < 4))) {
+ and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F);
+ and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F);
+ }
- case 7:
+ mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C);
+ write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C);
- regs_2057_ptr = regs_2057_rev7;
- break;
+ and_radio_reg(pi, RADIO_2055_CAL_MISC,
+ ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N));
- case 8:
+ or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE);
- regs_2057_ptr = regs_2057_rev8;
- break;
+ or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N);
- default:
- break;
- }
+ udelay(1000);
+
+ or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START);
+
+ SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+ RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000);
+
+ if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+ RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE,
+ "HW error: radio calibration1\n"))
+ return;
+
+ and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL,
+ ~(RADIO_2055_CAL_LPO_ENABLE));
+
+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
+
+ write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9);
+ write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9);
+
+ write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83);
+ write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83);
+
+ mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST,
+ RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+ mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST,
+ RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+ if (pi->nphy_gain_boost) {
+ and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+ ~(RADIO_2055_GAINBST_DISABLE));
+ and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+ ~(RADIO_2055_GAINBST_DISABLE));
+ } else {
+ or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+ RADIO_2055_GAINBST_DISABLE);
+ or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+ RADIO_2055_GAINBST_DISABLE);
}
- wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr);
+ udelay(2);
}
-static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi)
+void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on)
{
+ if (on) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (!pi->radio_is_on) {
+ wlc_phy_radio_preinit_205x(pi);
+ wlc_phy_radio_init_2057(pi);
+ wlc_phy_radio_postinit_2057(pi);
+ }
- mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1);
+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
+ pi->radio_chanspec);
+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ wlc_phy_radio_preinit_205x(pi);
+ wlc_phy_radio_init_2056(pi);
+ wlc_phy_radio_postinit_2056(pi);
- mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78);
- mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80);
- mdelay(2);
- mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0);
- mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0);
+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
+ pi->radio_chanspec);
+ } else {
+ wlc_phy_radio_preinit_2055(pi);
+ wlc_phy_radio_init_2055(pi);
+ wlc_phy_radio_postinit_2055(pi);
+ }
- if (pi->phy_init_por) {
- wlc_phy_radio205x_rcal(pi);
- wlc_phy_radio2057_rccal(pi);
- }
+ pi->radio_is_on = true;
- mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0);
+ } else {
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3)
+ && NREV_LT(pi->pubpi.phy_rev, 7)) {
+ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+ mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0);
+
+ write_radio_reg(pi,
+ RADIO_2056_TX_PADA_BOOST_TUNE |
+ RADIO_2056_TX0, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PADG_BOOST_TUNE |
+ RADIO_2056_TX0, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PGAA_BOOST_TUNE |
+ RADIO_2056_TX0, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PGAG_BOOST_TUNE |
+ RADIO_2056_TX0, 0);
+ mod_radio_reg(pi,
+ RADIO_2056_TX_MIXA_BOOST_TUNE |
+ RADIO_2056_TX0, 0xf0, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_MIXG_BOOST_TUNE |
+ RADIO_2056_TX0, 0);
+
+ write_radio_reg(pi,
+ RADIO_2056_TX_PADA_BOOST_TUNE |
+ RADIO_2056_TX1, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PADG_BOOST_TUNE |
+ RADIO_2056_TX1, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PGAA_BOOST_TUNE |
+ RADIO_2056_TX1, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_PGAG_BOOST_TUNE |
+ RADIO_2056_TX1, 0);
+ mod_radio_reg(pi,
+ RADIO_2056_TX_MIXA_BOOST_TUNE |
+ RADIO_2056_TX1, 0xf0, 0);
+ write_radio_reg(pi,
+ RADIO_2056_TX_MIXG_BOOST_TUNE |
+ RADIO_2056_TX1, 0);
+
+ pi->radio_is_on = false;
+ }
+
+ if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+ pi->radio_is_on = false;
+ }
+
+ }
}
static bool
wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
- struct chan_info_nphy_radio2057 **t0,
- struct chan_info_nphy_radio205x **t1,
- struct chan_info_nphy_radio2057_rev5 **t2,
- struct chan_info_nphy_2055 **t3)
+ const struct chan_info_nphy_radio2057 **t0,
+ const struct chan_info_nphy_radio205x **t1,
+ const struct chan_info_nphy_radio2057_rev5 **t2,
+ const struct chan_info_nphy_2055 **t3)
{
uint i;
- struct chan_info_nphy_radio2057 *chan_info_tbl_p_0 = NULL;
- struct chan_info_nphy_radio205x *chan_info_tbl_p_1 = NULL;
- struct chan_info_nphy_radio2057_rev5 *chan_info_tbl_p_2 = NULL;
+ const struct chan_info_nphy_radio2057 *chan_info_tbl_p_0 = NULL;
+ const struct chan_info_nphy_radio205x *chan_info_tbl_p_1 = NULL;
+ const struct chan_info_nphy_radio2057_rev5 *chan_info_tbl_p_2 = NULL;
u32 tbl_len = 0;
int freq = 0;
@@ -17621,40 +20527,35 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
if (pi->pubpi.radiover == 0x0) {
chan_info_tbl_p_2 =
- chan_info_nphyrev8_2057_rev5;
- tbl_len =
- ARRAY_SIZE
- (chan_info_nphyrev8_2057_rev5);
+ chan_info_nphyrev8_2057_rev5;
+ tbl_len = ARRAY_SIZE(
+ chan_info_nphyrev8_2057_rev5);
} else if (pi->pubpi.radiover == 0x1) {
chan_info_tbl_p_2 =
- chan_info_nphyrev9_2057_rev5v1;
- tbl_len =
- ARRAY_SIZE
- (chan_info_nphyrev9_2057_rev5v1);
+ chan_info_nphyrev9_2057_rev5v1;
+ tbl_len = ARRAY_SIZE(
+ chan_info_nphyrev9_2057_rev5v1);
}
break;
case 7:
chan_info_tbl_p_0 =
- chan_info_nphyrev8_2057_rev7;
- tbl_len =
- ARRAY_SIZE(chan_info_nphyrev8_2057_rev7);
+ chan_info_nphyrev8_2057_rev7;
+ tbl_len = ARRAY_SIZE(
+ chan_info_nphyrev8_2057_rev7);
break;
case 8:
chan_info_tbl_p_0 =
- chan_info_nphyrev8_2057_rev8;
- tbl_len =
- ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
+ chan_info_nphyrev8_2057_rev8;
+ tbl_len = ARRAY_SIZE(
+ chan_info_nphyrev8_2057_rev8);
break;
default:
- if (NORADIO_ENAB(pi->pubpi)) {
- goto fail;
- }
break;
}
} else if (NREV_IS(pi->pubpi.phy_rev, 16)) {
@@ -17677,9 +20578,9 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
}
}
- if (i >= tbl_len) {
+ if (i >= tbl_len)
goto fail;
- }
+
if (pi->pubpi.radiorev == 5) {
*t2 = &chan_info_tbl_p_2[i];
freq = chan_info_tbl_p_2[i].freq;
@@ -17710,7 +20611,7 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
case 9:
chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7;
tbl_len =
- ARRAY_SIZE(chan_info_nphyrev5n6_2056v7);
+ ARRAY_SIZE(chan_info_nphyrev5n6_2056v7);
break;
case 8:
chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8;
@@ -17718,12 +20619,10 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
break;
case 11:
chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11;
- tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v11);
+ tbl_len = ARRAY_SIZE(
+ chan_info_nphyrev6_2056v11);
break;
default:
- if (NORADIO_ENAB(pi->pubpi)) {
- goto fail;
- }
break;
}
}
@@ -17733,9 +20632,9 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
break;
}
- if (i >= tbl_len) {
+ if (i >= tbl_len)
goto fail;
- }
+
*t1 = &chan_info_tbl_p_1[i];
freq = chan_info_tbl_p_1[i].freq;
@@ -17744,9 +20643,9 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
if (chan_info_nphy_2055[i].chan == channel)
break;
- if (i >= ARRAY_SIZE(chan_info_nphy_2055)) {
+ if (i >= ARRAY_SIZE(chan_info_nphy_2055))
goto fail;
- }
+
*t3 = &chan_info_nphy_2055[i];
freq = chan_info_nphy_2055[i].freq;
}
@@ -17754,7 +20653,7 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
*f = freq;
return true;
- fail:
+fail:
*f = WL_CHAN_FREQ_RANGE_2G;
return false;
}
@@ -17762,13 +20661,10 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint channel)
{
int freq;
- struct chan_info_nphy_radio2057 *t0 = NULL;
- struct chan_info_nphy_radio205x *t1 = NULL;
- struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
- struct chan_info_nphy_2055 *t3 = NULL;
-
- if (NORADIO_ENAB(pi->pubpi))
- return WL_CHAN_FREQ_RANGE_2G;
+ const struct chan_info_nphy_radio2057 *t0 = NULL;
+ const struct chan_info_nphy_radio205x *t1 = NULL;
+ const struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
+ const struct chan_info_nphy_2055 *t3 = NULL;
if (channel == 0)
channel = CHSPEC_CHANNEL(pi->radio_chanspec);
@@ -17778,18 +20674,17 @@ u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint channel)
if (CHSPEC_IS2G(pi->radio_chanspec))
return WL_CHAN_FREQ_RANGE_2G;
- if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) {
+ if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN))
return WL_CHAN_FREQ_RANGE_5GL;
- } else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) {
+ else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN))
return WL_CHAN_FREQ_RANGE_5GM;
- } else {
+ else
return WL_CHAN_FREQ_RANGE_5GH;
- }
}
static void
wlc_phy_chanspec_radio2055_setup(struct brcms_phy *pi,
- struct chan_info_nphy_2055 *ci)
+ const struct chan_info_nphy_2055 *ci)
{
write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref);
@@ -17854,7 +20749,7 @@ static void
wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
const struct chan_info_nphy_radio205x *ci)
{
- struct radio_regs *regs_SYN_2056_ptr = NULL;
+ const struct radio_regs *regs_SYN_2056_ptr = NULL;
write_radio_reg(pi,
RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN,
@@ -17960,15 +20855,14 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
break;
}
}
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec))
write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
RADIO_2056_SYN,
(u16) regs_SYN_2056_ptr[0x49 - 2].init_g);
- } else {
+ else
write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
RADIO_2056_SYN,
(u16) regs_SYN_2056_ptr[0x49 - 2].init_a);
- }
if (pi->sh->boardflags2 & BFL2_GPLL_WAR) {
if (CHSPEC_IS2G(pi->radio_chanspec)) {
@@ -18069,7 +20963,8 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
mixg_boost_tune);
} else {
- bias = IS40MHZ(pi) ? 0x40 : 0x20;
+ bias = (pi->bw == WL_CHANSPEC_BW_40) ?
+ 0x40 : 0x20;
WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
INTPAG_IMAIN_STAT, bias);
@@ -18116,11 +21011,11 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
paa_boost_tune = 0x0;
pada_boost_tune = 0x77;
- if (freq != 5825) {
+ if (freq != 5825)
pgaa_boost_tune = -(int)(freq - 18) / 36 + 168;
- } else {
+ else
pgaa_boost_tune = 6;
- }
+
mixa_boost_tune = 0xf;
}
@@ -18146,9 +21041,8 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
if ((pi->sh->chip == BCM43224_CHIP_ID) ||
(pi->sh->chip == BCM43225_CHIP_ID)) {
- if (pi->sh->chippkg == BCM43224_FAB_SMIC) {
+ if (pi->sh->chippkg == BCM43224_FAB_SMIC)
cascbias = 0x35;
- }
}
pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias;
@@ -18186,117 +21080,12 @@ void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi)
udelay(300);
}
-#define MAX_205x_RCAL_WAITLOOPS 10000
-
-static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi)
-{
- u16 rcal_reg = 0;
- int i;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- if (pi->pubpi.radiorev == 5) {
-
- and_phy_reg(pi, 0x342, ~(0x1 << 1));
-
- udelay(10);
-
- mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1);
- mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
- 0x1);
- }
- mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1);
-
- udelay(10);
-
- mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3);
-
- for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
- rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS);
- if (rcal_reg & 0x1) {
- break;
- }
- udelay(100);
- }
-
- if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
- "HW error: radio calib2"))
- return 0;
-
- mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0);
-
- rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e;
-
- mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0);
- if (pi->pubpi.radiorev == 5) {
-
- mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0);
- mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
- 0x0);
- }
-
- if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
-
- mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c,
- rcal_reg);
- mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0,
- rcal_reg << 2);
- }
-
- } else if (NREV_IS(pi->pubpi.phy_rev, 3)) {
- u16 savereg;
-
- savereg =
- read_radio_reg(pi,
- RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN);
- write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
- savereg | 0x7);
- udelay(10);
-
- write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
- 0x1);
- udelay(10);
-
- write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
- 0x9);
-
- for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
- rcal_reg = read_radio_reg(pi,
- RADIO_2056_SYN_RCAL_CODE_OUT |
- RADIO_2056_SYN);
- if (rcal_reg & 0x80) {
- break;
- }
- udelay(100);
- }
-
- if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
- "HW error: radio calib3"))
- return 0;
-
- write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
- 0x1);
-
- rcal_reg =
- read_radio_reg(pi,
- RADIO_2056_SYN_RCAL_CODE_OUT |
- RADIO_2056_SYN);
-
- write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
- 0x0);
-
- write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
- savereg);
-
- return rcal_reg & 0x1f;
- }
- return rcal_reg & 0x3e;
-}
-
static void
-wlc_phy_chanspec_radio2057_setup(struct brcms_phy *pi,
- const struct chan_info_nphy_radio2057 *ci,
- const struct chan_info_nphy_radio2057_rev5 *ci2)
+wlc_phy_chanspec_radio2057_setup(
+ struct brcms_phy *pi,
+ const struct chan_info_nphy_radio2057 *ci,
+ const struct chan_info_nphy_radio2057_rev5 *
+ ci2)
{
int coreNum;
u16 txmix2g_tune_boost_pu = 0;
@@ -18455,9 +21244,8 @@ wlc_phy_chanspec_radio2057_setup(struct brcms_phy *pi,
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if (PHY_IPA(pi)) {
- if (pi->pubpi.radiorev == 3) {
+ if (pi->pubpi.radiorev == 3)
txmix2g_tune_boost_pu = 0x6b;
- }
if (pi->pubpi.radiorev == 5)
pad2g_tune_pus = 0x73;
@@ -18489,430 +21277,8 @@ wlc_phy_chanspec_radio2057_setup(struct brcms_phy *pi,
wlc_phy_radio205x_vcocal_nphy(pi);
}
-static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi)
-{
- u16 rccal_valid;
- int i;
- bool chip43226_6362A0;
-
- chip43226_6362A0 = ((pi->pubpi.radiorev == 3)
- || (pi->pubpi.radiorev == 4)
- || (pi->pubpi.radiorev == 6));
-
- rccal_valid = 0;
- if (chip43226_6362A0) {
- write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61);
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0);
- } else {
- write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61);
-
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9);
- }
- write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
- for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
- rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
- if (rccal_valid & 0x2) {
- break;
- }
- udelay(500);
- }
-
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
- rccal_valid = 0;
- if (chip43226_6362A0) {
- write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69);
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
- } else {
- write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69);
-
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5);
- }
- write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
- for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
- rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
- if (rccal_valid & 0x2) {
- break;
- }
- udelay(500);
- }
-
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
- rccal_valid = 0;
- if (chip43226_6362A0) {
- write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73);
-
- write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28);
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
- } else {
- write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73);
- write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
- write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99);
- }
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
- for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
- rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
- if (rccal_valid & 0x2) {
- break;
- }
- udelay(500);
- }
-
- if (WARN(!(rccal_valid & 0x2), "HW error: radio calib4"))
- return 0;
-
- write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
- return rccal_valid;
-}
-
-static void
-wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi, u16 reduction_factr)
-{
- if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
- if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
- CHSPEC_IS40(pi->radio_chanspec)) {
- if (!pi->nphy_anarxlpf_adjusted) {
- write_radio_reg(pi,
- (RADIO_2056_RX_RXLPF_RCCAL_LPC |
- RADIO_2056_RX0),
- ((pi->nphy_rccal_value +
- reduction_factr) | 0x80));
-
- pi->nphy_anarxlpf_adjusted = true;
- }
- } else {
- if (pi->nphy_anarxlpf_adjusted) {
- write_radio_reg(pi,
- (RADIO_2056_RX_RXLPF_RCCAL_LPC |
- RADIO_2056_RX0),
- (pi->nphy_rccal_value | 0x80));
-
- pi->nphy_anarxlpf_adjusted = false;
- }
- }
- }
-}
-
-static void
-wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones,
- int *tone_id_buf, u32 *noise_var_buf)
-{
- int i;
- u32 offset;
- int tone_id;
- int tbllen =
- CHSPEC_IS40(pi->
- radio_chanspec) ? NPHY_NOISEVAR_TBLLEN40 :
- NPHY_NOISEVAR_TBLLEN20;
-
- if (pi->nphy_noisevars_adjusted) {
- for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) {
- tone_id = pi->nphy_saved_noisevars.tone_id[i];
- offset = (tone_id >= 0) ?
- ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
- offset, 32,
- (void *)&pi->
- nphy_saved_noisevars.
- min_noise_vars[i]);
- }
-
- pi->nphy_saved_noisevars.bufcount = 0;
- pi->nphy_noisevars_adjusted = false;
- }
-
- if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) {
- pi->nphy_saved_noisevars.bufcount = 0;
-
- for (i = 0; i < ntones; i++) {
- tone_id = tone_id_buf[i];
- offset = (tone_id >= 0) ?
- ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
- pi->nphy_saved_noisevars.tone_id[i] = tone_id;
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
- offset, 32,
- &pi->nphy_saved_noisevars.
- min_noise_vars[i]);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
- offset, 32,
- (void *)&noise_var_buf[i]);
- pi->nphy_saved_noisevars.bufcount++;
- }
-
- pi->nphy_noisevars_adjusted = true;
- }
-}
-
-static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr)
-{
- u16 regval;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
- CHSPEC_IS40(pi->radio_chanspec)) {
- if (!pi->nphy_crsminpwr_adjusted) {
- regval = read_phy_reg(pi, 0x27d);
- pi->nphy_crsminpwr[0] = regval & 0xff;
- regval &= 0xff00;
- regval |= (u16) minpwr;
- write_phy_reg(pi, 0x27d, regval);
-
- regval = read_phy_reg(pi, 0x280);
- pi->nphy_crsminpwr[1] = regval & 0xff;
- regval &= 0xff00;
- regval |= (u16) minpwr;
- write_phy_reg(pi, 0x280, regval);
-
- regval = read_phy_reg(pi, 0x283);
- pi->nphy_crsminpwr[2] = regval & 0xff;
- regval &= 0xff00;
- regval |= (u16) minpwr;
- write_phy_reg(pi, 0x283, regval);
-
- pi->nphy_crsminpwr_adjusted = true;
- }
- } else {
- if (pi->nphy_crsminpwr_adjusted) {
- regval = read_phy_reg(pi, 0x27d);
- regval &= 0xff00;
- regval |= pi->nphy_crsminpwr[0];
- write_phy_reg(pi, 0x27d, regval);
-
- regval = read_phy_reg(pi, 0x280);
- regval &= 0xff00;
- regval |= pi->nphy_crsminpwr[1];
- write_phy_reg(pi, 0x280, regval);
-
- regval = read_phy_reg(pi, 0x283);
- regval &= 0xff00;
- regval |= pi->nphy_crsminpwr[2];
- write_phy_reg(pi, 0x283, regval);
-
- pi->nphy_crsminpwr_adjusted = false;
- }
- }
- }
-}
-
-static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi)
-{
- u8 tx_lpf_bw = 0;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- tx_lpf_bw = 3;
- } else {
- tx_lpf_bw = 1;
- }
-
- if (PHY_IPA(pi)) {
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- tx_lpf_bw = 5;
- } else {
- tx_lpf_bw = 4;
- }
- }
- write_phy_reg(pi, 0xe8,
- (tx_lpf_bw << 0) |
- (tx_lpf_bw << 3) |
- (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
-
- if (PHY_IPA(pi)) {
-
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- tx_lpf_bw = 4;
- } else {
- tx_lpf_bw = 1;
- }
-
- write_phy_reg(pi, 0xe9,
- (tx_lpf_bw << 0) |
- (tx_lpf_bw << 3) |
- (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
- }
- }
-}
-
-static void wlc_phy_spurwar_nphy(struct brcms_phy *pi)
-{
- u16 cur_channel = 0;
- int nphy_adj_tone_id_buf[] = { 57, 58 };
- u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff };
- bool isAdjustNoiseVar = false;
- uint numTonesAdjust = 0;
- u32 tempval = 0;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
-
- if (pi->nphy_gband_spurwar_en) {
-
- wlc_phy_adjust_rx_analpfbw_nphy(pi,
- NPHY_ANARXLPFBW_REDUCTIONFACT);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if ((cur_channel == 11)
- && CHSPEC_IS40(pi->radio_chanspec)) {
-
- wlc_phy_adjust_min_noisevar_nphy(pi, 2,
- nphy_adj_tone_id_buf,
- nphy_adj_noise_var_buf);
- } else {
-
- wlc_phy_adjust_min_noisevar_nphy(pi, 0,
- NULL,
- NULL);
- }
- }
- wlc_phy_adjust_crsminpwr_nphy(pi,
- NPHY_ADJUSTED_MINCRSPOWER);
- }
-
- if ((pi->nphy_gband_spurwar2_en)
- && CHSPEC_IS2G(pi->radio_chanspec)) {
-
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- switch (cur_channel) {
- case 3:
- nphy_adj_tone_id_buf[0] = 57;
- nphy_adj_tone_id_buf[1] = 58;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x25f;
- isAdjustNoiseVar = true;
- break;
- case 4:
- nphy_adj_tone_id_buf[0] = 41;
- nphy_adj_tone_id_buf[1] = 42;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x25f;
- isAdjustNoiseVar = true;
- break;
- case 5:
- nphy_adj_tone_id_buf[0] = 25;
- nphy_adj_tone_id_buf[1] = 26;
- nphy_adj_noise_var_buf[0] = 0x24f;
- nphy_adj_noise_var_buf[1] = 0x25f;
- isAdjustNoiseVar = true;
- break;
- case 6:
- nphy_adj_tone_id_buf[0] = 9;
- nphy_adj_tone_id_buf[1] = 10;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x24f;
- isAdjustNoiseVar = true;
- break;
- case 7:
- nphy_adj_tone_id_buf[0] = 121;
- nphy_adj_tone_id_buf[1] = 122;
- nphy_adj_noise_var_buf[0] = 0x18f;
- nphy_adj_noise_var_buf[1] = 0x24f;
- isAdjustNoiseVar = true;
- break;
- case 8:
- nphy_adj_tone_id_buf[0] = 105;
- nphy_adj_tone_id_buf[1] = 106;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x25f;
- isAdjustNoiseVar = true;
- break;
- case 9:
- nphy_adj_tone_id_buf[0] = 89;
- nphy_adj_tone_id_buf[1] = 90;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x24f;
- isAdjustNoiseVar = true;
- break;
- case 10:
- nphy_adj_tone_id_buf[0] = 73;
- nphy_adj_tone_id_buf[1] = 74;
- nphy_adj_noise_var_buf[0] = 0x22f;
- nphy_adj_noise_var_buf[1] = 0x24f;
- isAdjustNoiseVar = true;
- break;
- default:
- isAdjustNoiseVar = false;
- break;
- }
- }
-
- if (isAdjustNoiseVar) {
- numTonesAdjust = sizeof(nphy_adj_tone_id_buf) /
- sizeof(nphy_adj_tone_id_buf[0]);
-
- wlc_phy_adjust_min_noisevar_nphy(pi,
- numTonesAdjust,
- nphy_adj_tone_id_buf,
- nphy_adj_noise_var_buf);
-
- tempval = 0;
-
- } else {
-
- wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
- NULL);
- }
- }
-
- if ((pi->nphy_aband_spurwar_en) &&
- (CHSPEC_IS5G(pi->radio_chanspec))) {
- switch (cur_channel) {
- case 54:
- nphy_adj_tone_id_buf[0] = 32;
- nphy_adj_noise_var_buf[0] = 0x25f;
- break;
- case 38:
- case 102:
- case 118:
- nphy_adj_tone_id_buf[0] = 0;
- nphy_adj_noise_var_buf[0] = 0x0;
- break;
- case 134:
- nphy_adj_tone_id_buf[0] = 32;
- nphy_adj_noise_var_buf[0] = 0x21f;
- break;
- case 151:
- nphy_adj_tone_id_buf[0] = 16;
- nphy_adj_noise_var_buf[0] = 0x23f;
- break;
- case 153:
- case 161:
- nphy_adj_tone_id_buf[0] = 48;
- nphy_adj_noise_var_buf[0] = 0x23f;
- break;
- default:
- nphy_adj_tone_id_buf[0] = 0;
- nphy_adj_noise_var_buf[0] = 0x0;
- break;
- }
-
- if (nphy_adj_tone_id_buf[0]
- && nphy_adj_noise_var_buf[0]) {
- wlc_phy_adjust_min_noisevar_nphy(pi, 1,
- nphy_adj_tone_id_buf,
- nphy_adj_noise_var_buf);
- } else {
- wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
- NULL);
- }
- }
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
- }
-}
-
static void
-wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chanspec,
+wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
const struct nphy_sfo_cfg *ci)
{
u16 val;
@@ -18964,14 +21330,11 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chanspec,
and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840);
}
- if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF)
wlc_phy_txpwr_fixpower_nphy(pi);
- }
-
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
wlc_phy_adjust_lnagaintbl_nphy(pi);
- }
wlc_phy_txlpfbw_nphy(pi);
@@ -18982,28 +21345,20 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chanspec,
val = CHSPEC_CHANNEL(chanspec);
if (!CHSPEC_IS40(pi->radio_chanspec)) {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if ((val == 13) || (val == 14) || (val == 153)) {
- spuravoid = 1;
- }
- } else {
-
- if (((val >= 5) && (val <= 8)) || (val == 13)
- || (val == 14)) {
+ if ((val == 13) || (val == 14) || (val == 153))
spuravoid = 1;
- }
+ } else if (((val >= 5) && (val <= 8)) || (val == 13)
+ || (val == 14)) {
+ spuravoid = 1;
}
+ } else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (val == 54)
+ spuravoid = 1;
} else {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (val == 54) {
- spuravoid = 1;
- }
- } else {
-
- if (pi->nphy_aband_spurwar_en &&
- ((val == 38) || (val == 102)
- || (val == 118)))
- spuravoid = 1;
- }
+ if (pi->nphy_aband_spurwar_en &&
+ ((val == 38) || (val == 102)
+ || (val == 118)))
+ spuravoid = 1;
}
if (pi->phy_spuravoid == SPURAVOID_FORCEON)
@@ -19047,20 +21402,16 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chanspec,
wlc_phy_spurwar_nphy(pi);
}
-void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, chanspec_t chanspec)
+void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec)
{
int freq;
- struct chan_info_nphy_radio2057 *t0 = NULL;
- struct chan_info_nphy_radio205x *t1 = NULL;
- struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
- struct chan_info_nphy_2055 *t3 = NULL;
-
- if (NORADIO_ENAB(pi->pubpi)) {
- return;
- }
+ const struct chan_info_nphy_radio2057 *t0 = NULL;
+ const struct chan_info_nphy_radio205x *t1 = NULL;
+ const struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
+ const struct chan_info_nphy_2055 *t3 = NULL;
if (!wlc_phy_chan2freq_nphy
- (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3))
+ (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3))
return;
wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec);
@@ -19071,15 +21422,13 @@ void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, chanspec_t chanspec)
if (CHSPEC_IS40(chanspec)) {
if (CHSPEC_SB_UPPER(chanspec)) {
or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
or_phy_reg(pi, 0x310, PRIM_SEL_UP20);
- }
} else {
and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
and_phy_reg(pi, 0x310,
(~PRIM_SEL_UP20 & 0xffff));
- }
}
}
@@ -19124,358 +21473,10 @@ void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, chanspec_t chanspec)
wlc_phy_chanspec_radio2055_setup(pi, t3);
wlc_phy_chanspec_nphy_setup(pi, chanspec,
- (const struct nphy_sfo_cfg *)&(t3->
- PHY_BW1a));
- }
-
-}
-
-static void wlc_phy_savecal_nphy(struct brcms_phy *pi)
-{
- void *tbl_ptr;
- int coreNum;
- u16 *txcal_radio_regs = NULL;
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
- wlc_phy_rx_iq_coeffs_nphy(pi, 0,
- &pi->calibration_cache.
- rxcal_coeffs_2G);
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- txcal_radio_regs =
- pi->calibration_cache.txcal_radio_regs_2G;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- pi->calibration_cache.txcal_radio_regs_2G[0] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_2G[1] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_2G[2] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX1);
- pi->calibration_cache.txcal_radio_regs_2G[3] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX1);
-
- pi->calibration_cache.txcal_radio_regs_2G[4] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_2G[5] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_2G[6] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX1);
- pi->calibration_cache.txcal_radio_regs_2G[7] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX1);
- } else {
- pi->calibration_cache.txcal_radio_regs_2G[0] =
- read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
- pi->calibration_cache.txcal_radio_regs_2G[1] =
- read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
- pi->calibration_cache.txcal_radio_regs_2G[2] =
- read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
- pi->calibration_cache.txcal_radio_regs_2G[3] =
- read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
- }
-
- pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec;
- tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
- } else {
-
- wlc_phy_rx_iq_coeffs_nphy(pi, 0,
- &pi->calibration_cache.
- rxcal_coeffs_5G);
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- txcal_radio_regs =
- pi->calibration_cache.txcal_radio_regs_5G;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- pi->calibration_cache.txcal_radio_regs_5G[0] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_5G[1] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_5G[2] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX1);
- pi->calibration_cache.txcal_radio_regs_5G[3] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX1);
-
- pi->calibration_cache.txcal_radio_regs_5G[4] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_5G[5] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX0);
- pi->calibration_cache.txcal_radio_regs_5G[6] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX1);
- pi->calibration_cache.txcal_radio_regs_5G[7] =
- read_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX1);
- } else {
- pi->calibration_cache.txcal_radio_regs_5G[0] =
- read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
- pi->calibration_cache.txcal_radio_regs_5G[1] =
- read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
- pi->calibration_cache.txcal_radio_regs_5G[2] =
- read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
- pi->calibration_cache.txcal_radio_regs_5G[3] =
- read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
- }
-
- pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec;
- tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
- }
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- for (coreNum = 0; coreNum <= 1; coreNum++) {
-
- txcal_radio_regs[2 * coreNum] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_FINE_I);
- txcal_radio_regs[2 * coreNum + 1] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_FINE_Q);
-
- txcal_radio_regs[2 * coreNum + 4] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_COARSE_I);
- txcal_radio_regs[2 * coreNum + 5] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_COARSE_Q);
- }
- }
-
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr);
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_restorecal_nphy(struct brcms_phy *pi)
-{
- u16 *loft_comp;
- u16 txcal_coeffs_bphy[4];
- u16 *tbl_ptr;
- int coreNum;
- u16 *txcal_radio_regs = NULL;
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (pi->nphy_iqcal_chanspec_2G == 0)
- return;
-
- tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
- loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5];
- } else {
- if (pi->nphy_iqcal_chanspec_5G == 0)
- return;
-
- tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
- loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5];
- }
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16,
- (void *)tbl_ptr);
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- txcal_coeffs_bphy[0] = tbl_ptr[0];
- txcal_coeffs_bphy[1] = tbl_ptr[1];
- txcal_coeffs_bphy[2] = tbl_ptr[2];
- txcal_coeffs_bphy[3] = tbl_ptr[3];
- } else {
- txcal_coeffs_bphy[0] = 0;
- txcal_coeffs_bphy[1] = 0;
- txcal_coeffs_bphy[2] = 0;
- txcal_coeffs_bphy[3] = 0;
- }
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16,
- txcal_coeffs_bphy);
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp);
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp);
-
- if (NREV_LT(pi->pubpi.phy_rev, 2))
- wlc_phy_tx_iq_war_nphy(pi);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- txcal_radio_regs =
- pi->calibration_cache.txcal_radio_regs_2G;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_2G[0]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_2G[1]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_2G[2]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_2G[3]);
-
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_2G[4]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_2G[5]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_2G[6]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_2G[7]);
- } else {
- write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
- pi->calibration_cache.
- txcal_radio_regs_2G[0]);
- write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
- pi->calibration_cache.
- txcal_radio_regs_2G[1]);
- write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
- pi->calibration_cache.
- txcal_radio_regs_2G[2]);
- write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
- pi->calibration_cache.
- txcal_radio_regs_2G[3]);
- }
-
- wlc_phy_rx_iq_coeffs_nphy(pi, 1,
- &pi->calibration_cache.
- rxcal_coeffs_2G);
- } else {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- txcal_radio_regs =
- pi->calibration_cache.txcal_radio_regs_5G;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_5G[0]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_5G[1]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_I |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_5G[2]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_FINE_Q |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_5G[3]);
-
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_5G[4]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX0,
- pi->calibration_cache.
- txcal_radio_regs_5G[5]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_I |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_5G[6]);
- write_radio_reg(pi,
- RADIO_2056_TX_LOFT_COARSE_Q |
- RADIO_2056_TX1,
- pi->calibration_cache.
- txcal_radio_regs_5G[7]);
- } else {
- write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
- pi->calibration_cache.
- txcal_radio_regs_5G[0]);
- write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
- pi->calibration_cache.
- txcal_radio_regs_5G[1]);
- write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
- pi->calibration_cache.
- txcal_radio_regs_5G[2]);
- write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
- pi->calibration_cache.
- txcal_radio_regs_5G[3]);
- }
-
- wlc_phy_rx_iq_coeffs_nphy(pi, 1,
- &pi->calibration_cache.
- rxcal_coeffs_5G);
+ (const struct nphy_sfo_cfg *)
+ &(t3->PHY_BW1a));
}
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- for (coreNum = 0; coreNum <= 1; coreNum++) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_FINE_I,
- txcal_radio_regs[2 * coreNum]);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_FINE_Q,
- txcal_radio_regs[2 * coreNum + 1]);
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_COARSE_I,
- txcal_radio_regs[2 * coreNum + 4]);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
- LOFT_COARSE_Q,
- txcal_radio_regs[2 * coreNum + 5]);
- }
- }
}
void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init)
@@ -19545,8 +21546,8 @@ u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val)
if (D11REV_IS(pi->sh->corerev, 16)) {
suspended =
- (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ?
- false : true;
+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ?
+ false : true;
if (!suspended)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
}
@@ -19563,18 +21564,6 @@ u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val)
return new_ctl;
}
-static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals)
-{
-
- if (write == 0) {
- vals[0] = read_phy_reg(pi, 0x2c);
- vals[1] = read_phy_reg(pi, 0x42);
- } else {
- write_phy_reg(pi, 0x2c, vals[0]);
- write_phy_reg(pi, 0x42, vals[1]);
- }
-}
-
void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd)
{
u16 trigger_mask, status_mask;
@@ -19620,577 +21609,6 @@ void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd)
}
static void
-wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys,
- u8 len)
-{
- u32 t1_offset, t2_offset;
- u8 ctr;
- u8 end_event =
- NREV_GE(pi->pubpi.phy_rev,
- 3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END;
- u8 end_dly = 1;
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- t1_offset = cmd << 4;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8,
- events);
- t2_offset = t1_offset + 0x080;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8,
- dlys);
-
- for (ctr = len; ctr < 16; ctr++) {
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
- t1_offset + ctr, 8, &end_event);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
- t2_offset + ctr, 8, &end_dly);
- }
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset)
-{
- u16 lpf_bw_ctl_val = 0;
- u16 rx2tx_lpf_rc_lut_offset = 0;
-
- if (offset == 0) {
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- rx2tx_lpf_rc_lut_offset = 0x159;
- } else {
- rx2tx_lpf_rc_lut_offset = 0x154;
- }
- } else {
- rx2tx_lpf_rc_lut_offset = offset;
- }
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
- (u32) rx2tx_lpf_rc_lut_offset, 16,
- &lpf_bw_ctl_val);
-
- lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7;
-
- return lpf_bw_ctl_val;
-}
-
-static void
-wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value,
- u8 core_mask, u8 off, u8 override_id)
-{
- u8 core_num;
- u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0;
- u8 val_shift = 0;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- en_mask = field;
- for (core_num = 0; core_num < 2; core_num++) {
- if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) {
-
- switch (field) {
- case (0x1 << 2):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 1);
- val_shift = 1;
- break;
- case (0x1 << 3):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 2);
- val_shift = 2;
- break;
- case (0x1 << 4):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 4);
- val_shift = 4;
- break;
- case (0x1 << 5):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 5);
- val_shift = 5;
- break;
- case (0x1 << 6):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 6);
- val_shift = 6;
- break;
- case (0x1 << 7):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a :
- 0x7d;
- val_mask = (0x1 << 7);
- val_shift = 7;
- break;
- case (0x1 << 10):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0xf8 :
- 0xfa;
- val_mask = (0x7 << 4);
- val_shift = 4;
- break;
- case (0x1 << 11):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7b :
- 0x7e;
- val_mask = (0xffff << 0);
- val_shift = 0;
- break;
- case (0x1 << 12):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7c :
- 0x7f;
- val_mask = (0xffff << 0);
- val_shift = 0;
- break;
- case (0x3 << 13):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x348 :
- 0x349;
- val_mask = (0xff << 0);
- val_shift = 0;
- break;
- case (0x1 << 13):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x348 :
- 0x349;
- val_mask = (0xf << 0);
- val_shift = 0;
- break;
- default:
- addr = 0xffff;
- break;
- }
- } else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID1) {
-
- switch (field) {
- case (0x1 << 1):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 1);
- val_shift = 1;
- break;
- case (0x1 << 3):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 3);
- val_shift = 3;
- break;
- case (0x1 << 5):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 5);
- val_shift = 5;
- break;
- case (0x1 << 4):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 4);
- val_shift = 4;
- break;
- case (0x1 << 2):
-
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 2);
- val_shift = 2;
- break;
- case (0x1 << 7):
-
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x7 << 8);
- val_shift = 8;
- break;
- case (0x1 << 11):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 14);
- val_shift = 14;
- break;
- case (0x1 << 10):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 13);
- val_shift = 13;
- break;
- case (0x1 << 9):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 12);
- val_shift = 12;
- break;
- case (0x1 << 8):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 11);
- val_shift = 11;
- break;
- case (0x1 << 6):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 6);
- val_shift = 6;
- break;
- case (0x1 << 0):
- en_addr = (core_num == 0) ? 0x342 :
- 0x343;
- val_addr = (core_num == 0) ? 0x340 :
- 0x341;
- val_mask = (0x1 << 0);
- val_shift = 0;
- break;
- default:
- addr = 0xffff;
- break;
- }
- } else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID2) {
-
- switch (field) {
- case (0x1 << 3):
- en_addr = (core_num == 0) ? 0x346 :
- 0x347;
- val_addr = (core_num == 0) ? 0x344 :
- 0x345;
- val_mask = (0x1 << 3);
- val_shift = 3;
- break;
- case (0x1 << 1):
- en_addr = (core_num == 0) ? 0x346 :
- 0x347;
- val_addr = (core_num == 0) ? 0x344 :
- 0x345;
- val_mask = (0x1 << 1);
- val_shift = 1;
- break;
- case (0x1 << 0):
- en_addr = (core_num == 0) ? 0x346 :
- 0x347;
- val_addr = (core_num == 0) ? 0x344 :
- 0x345;
- val_mask = (0x1 << 0);
- val_shift = 0;
- break;
- case (0x1 << 2):
- en_addr = (core_num == 0) ? 0x346 :
- 0x347;
- val_addr = (core_num == 0) ? 0x344 :
- 0x345;
- val_mask = (0x1 << 2);
- val_shift = 2;
- break;
- case (0x1 << 4):
- en_addr = (core_num == 0) ? 0x346 :
- 0x347;
- val_addr = (core_num == 0) ? 0x344 :
- 0x345;
- val_mask = (0x1 << 4);
- val_shift = 4;
- break;
- default:
- addr = 0xffff;
- break;
- }
- }
-
- if (off) {
- and_phy_reg(pi, en_addr, ~en_mask);
- and_phy_reg(pi, val_addr, ~val_mask);
- } else {
-
- if ((core_mask == 0)
- || (core_mask & (1 << core_num))) {
- or_phy_reg(pi, en_addr, en_mask);
-
- if (addr != 0xffff) {
- mod_phy_reg(pi, val_addr,
- val_mask,
- (value <<
- val_shift));
- }
- }
- }
- }
- }
-}
-
-static void
-wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value,
- u8 core_mask, u8 off)
-{
- u8 core_num;
- u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask =
- 0, val_mask = 0;
- u8 shift = 0, val_shift = 0;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
- en_mask = field;
- for (core_num = 0; core_num < 2; core_num++) {
-
- switch (field) {
- case (0x1 << 1):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 0);
- val_shift = 0;
- break;
- case (0x1 << 2):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 1);
- val_shift = 1;
- break;
- case (0x1 << 3):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 2);
- val_shift = 2;
- break;
- case (0x1 << 4):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 4);
- val_shift = 4;
- break;
- case (0x1 << 5):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 5);
- val_shift = 5;
- break;
- case (0x1 << 6):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 6);
- val_shift = 6;
- break;
- case (0x1 << 7):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x1 << 7);
- val_shift = 7;
- break;
- case (0x1 << 8):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x7 << 8);
- val_shift = 8;
- break;
- case (0x1 << 11):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7a : 0x7d;
- val_mask = (0x7 << 13);
- val_shift = 13;
- break;
-
- case (0x1 << 9):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0xf8 : 0xfa;
- val_mask = (0x7 << 0);
- val_shift = 0;
- break;
-
- case (0x1 << 10):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0xf8 : 0xfa;
- val_mask = (0x7 << 4);
- val_shift = 4;
- break;
-
- case (0x1 << 12):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7b : 0x7e;
- val_mask = (0xffff << 0);
- val_shift = 0;
- break;
- case (0x1 << 13):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0x7c : 0x7f;
- val_mask = (0xffff << 0);
- val_shift = 0;
- break;
- case (0x1 << 14):
- en_addr = (core_num == 0) ? 0xe7 : 0xec;
- val_addr = (core_num == 0) ? 0xf9 : 0xfb;
- val_mask = (0x3 << 6);
- val_shift = 6;
- break;
- case (0x1 << 0):
- en_addr = (core_num == 0) ? 0xe5 : 0xe6;
- val_addr = (core_num == 0) ? 0xf9 : 0xfb;
- val_mask = (0x1 << 15);
- val_shift = 15;
- break;
- default:
- addr = 0xffff;
- break;
- }
-
- if (off) {
- and_phy_reg(pi, en_addr, ~en_mask);
- and_phy_reg(pi, val_addr, ~val_mask);
- } else {
-
- if ((core_mask == 0)
- || (core_mask & (1 << core_num))) {
- or_phy_reg(pi, en_addr, en_mask);
-
- if (addr != 0xffff) {
- mod_phy_reg(pi, val_addr,
- val_mask,
- (value <<
- val_shift));
- }
- }
- }
- }
- } else {
-
- if (off) {
- and_phy_reg(pi, 0xec, ~field);
- value = 0x0;
- } else {
- or_phy_reg(pi, 0xec, field);
- }
-
- for (core_num = 0; core_num < 2; core_num++) {
-
- switch (field) {
- case (0x1 << 1):
- case (0x1 << 9):
- case (0x1 << 12):
- case (0x1 << 13):
- case (0x1 << 14):
- addr = 0x78;
-
- core_mask = 0x1;
- break;
- case (0x1 << 2):
- case (0x1 << 3):
- case (0x1 << 4):
- case (0x1 << 5):
- case (0x1 << 6):
- case (0x1 << 7):
- case (0x1 << 8):
- addr = (core_num == 0) ? 0x7a : 0x7d;
- break;
- case (0x1 << 10):
- addr = (core_num == 0) ? 0x7b : 0x7e;
- break;
- case (0x1 << 11):
- addr = (core_num == 0) ? 0x7c : 0x7f;
- break;
- default:
- addr = 0xffff;
- }
-
- switch (field) {
- case (0x1 << 1):
- mask = (0x7 << 3);
- shift = 3;
- break;
- case (0x1 << 9):
- mask = (0x1 << 2);
- shift = 2;
- break;
- case (0x1 << 12):
- mask = (0x1 << 8);
- shift = 8;
- break;
- case (0x1 << 13):
- mask = (0x1 << 9);
- shift = 9;
- break;
- case (0x1 << 14):
- mask = (0xf << 12);
- shift = 12;
- break;
- case (0x1 << 2):
- mask = (0x1 << 0);
- shift = 0;
- break;
- case (0x1 << 3):
- mask = (0x1 << 1);
- shift = 1;
- break;
- case (0x1 << 4):
- mask = (0x1 << 2);
- shift = 2;
- break;
- case (0x1 << 5):
- mask = (0x3 << 4);
- shift = 4;
- break;
- case (0x1 << 6):
- mask = (0x3 << 6);
- shift = 6;
- break;
- case (0x1 << 7):
- mask = (0x1 << 8);
- shift = 8;
- break;
- case (0x1 << 8):
- mask = (0x1 << 9);
- shift = 9;
- break;
- case (0x1 << 10):
- mask = 0x1fff;
- shift = 0x0;
- break;
- case (0x1 << 11):
- mask = 0x1fff;
- shift = 0x0;
- break;
- default:
- mask = 0x0;
- shift = 0x0;
- break;
- }
-
- if ((addr != 0xffff) && (core_mask & (1 << core_num))) {
- mod_phy_reg(pi, addr, mask, (value << shift));
- }
- }
-
- or_phy_reg(pi, 0xec, (0x1 << 0));
- or_phy_reg(pi, 0x78, (0x1 << 0));
- udelay(1);
- and_phy_reg(pi, 0xec, ~(0x1 << 0));
- }
-}
-
-static void
wlc_phy_rfctrl_override_1tomany_nphy(struct brcms_phy *pi, u16 cmd, u16 value,
u8 core_mask, u8 off)
{
@@ -20201,76 +21619,93 @@ wlc_phy_rfctrl_override_1tomany_nphy(struct brcms_phy *pi, u16 cmd, u16 value,
switch (cmd) {
case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu:
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
- value, core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 5),
+ value, core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 4), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 3), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
break;
case NPHY_REV7_RfctrlOverride_cmd_rx_pu:
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
- value, core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2),
+ value, core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 1), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 0), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 1), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 11), 0,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
break;
case NPHY_REV7_RfctrlOverride_cmd_tx_pu:
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
- value, core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), value,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1,
- core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2),
+ value, core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 1), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 0), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2), value,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 11), 1,
+ core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
break;
case NPHY_REV7_RfctrlOverride_cmd_rxgain:
rfmxgain = value & 0x000ff;
lpfgain = value & 0x0ff00;
lpfgain = lpfgain >> 8;
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
- rfmxgain, core_mask,
- off,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x3 << 13),
- lpfgain, core_mask,
- off,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 11),
+ rfmxgain, core_mask,
+ off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x3 << 13),
+ lpfgain, core_mask,
+ off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
break;
case NPHY_REV7_RfctrlOverride_cmd_txgain:
tgain = value & 0x7fff;
lpfgain = value & 0x8000;
lpfgain = lpfgain >> 14;
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
- tgain, core_mask, off,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 13),
- lpfgain, core_mask,
- off,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 12),
+ tgain, core_mask, off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 13),
+ lpfgain, core_mask,
+ off,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
break;
}
}
@@ -20283,137 +21718,164 @@ wlc_phy_scale_offset_rssi_nphy(struct brcms_phy *pi, u16 scale, s8 offset,
u16 valuetostuff;
offset = (offset > NPHY_RSSICAL_MAXREAD) ?
- NPHY_RSSICAL_MAXREAD : offset;
+ NPHY_RSSICAL_MAXREAD : offset;
offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ?
- -NPHY_RSSICAL_MAXREAD - 1 : offset;
+ -NPHY_RSSICAL_MAXREAD - 1 : offset;
valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f);
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB))
write_phy_reg(pi, 0x1a6, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB))
write_phy_reg(pi, 0x1ac, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB))
write_phy_reg(pi, 0x1b2, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB))
write_phy_reg(pi, 0x1b8, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1))
write_phy_reg(pi, 0x1a4, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1))
write_phy_reg(pi, 0x1aa, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1))
write_phy_reg(pi, 0x1b0, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1))
write_phy_reg(pi, 0x1b6, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2))
write_phy_reg(pi, 0x1a5, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2))
write_phy_reg(pi, 0x1ab, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2))
write_phy_reg(pi, 0x1b1, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2))
write_phy_reg(pi, 0x1b7, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD))
write_phy_reg(pi, 0x1a7, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD))
write_phy_reg(pi, 0x1ad, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD))
write_phy_reg(pi, 0x1b3, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD))
write_phy_reg(pi, 0x1b9, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ))
write_phy_reg(pi, 0x1a8, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ))
write_phy_reg(pi, 0x1ae, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ))
write_phy_reg(pi, 0x1b4, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ))
write_phy_reg(pi, 0x1ba, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
+ (rssi_type == NPHY_RSSI_SEL_TSSI_2G))
write_phy_reg(pi, 0x1a9, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
+ (rssi_type == NPHY_RSSI_SEL_TSSI_2G))
write_phy_reg(pi, 0x1b5, valuetostuff);
- }
if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
+ (rssi_type == NPHY_RSSI_SEL_TSSI_5G))
write_phy_reg(pi, 0x1af, valuetostuff);
- }
+
if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
(coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
- (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
+ (rssi_type == NPHY_RSSI_SEL_TSSI_5G))
write_phy_reg(pi, 0x1bb, valuetostuff);
+}
+
+static void brcms_phy_wr_tx_mux(struct brcms_phy *pi, u8 core)
+{
+ if (PHY_IPA(pi)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ write_radio_reg(pi,
+ ((core == PHY_CORE_0) ?
+ RADIO_2057_TX0_TX_SSI_MUX :
+ RADIO_2057_TX1_TX_SSI_MUX),
+ (CHSPEC_IS5G(pi->radio_chanspec) ?
+ 0xc : 0xe));
+ else
+ write_radio_reg(pi,
+ RADIO_2056_TX_TX_SSI_MUX |
+ ((core == PHY_CORE_0) ?
+ RADIO_2056_TX0 : RADIO_2056_TX1),
+ (CHSPEC_IS5G(pi->radio_chanspec) ?
+ 0xc : 0xe));
+ } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ write_radio_reg(pi,
+ ((core == PHY_CORE_0) ?
+ RADIO_2057_TX0_TX_SSI_MUX :
+ RADIO_2057_TX1_TX_SSI_MUX),
+ 0x11);
+
+ if (pi->pubpi.radioid == BCM2057_ID)
+ write_radio_reg(pi,
+ RADIO_2057_IQTEST_SEL_PU, 0x1);
+
+ } else {
+ write_radio_reg(pi,
+ RADIO_2056_TX_TX_SSI_MUX |
+ ((core == PHY_CORE_0) ?
+ RADIO_2056_TX0 : RADIO_2056_TX1),
+ 0x11);
+ }
}
}
@@ -20440,7 +21902,7 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
mod_phy_reg(pi, 0xe6, (0x1 << 5), 0);
mask = (0x1 << 2) |
- (0x1 << 3) | (0x1 << 4) | (0x1 << 5);
+ (0x1 << 3) | (0x1 << 4) | (0x1 << 5);
mod_phy_reg(pi, 0xf9, mask, 0);
mod_phy_reg(pi, 0xfb, mask, 0);
@@ -20459,23 +21921,22 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
if (rssi_type == NPHY_RSSI_SEL_W1 ||
rssi_type == NPHY_RSSI_SEL_W2 ||
rssi_type == NPHY_RSSI_SEL_NB) {
-
mod_phy_reg(pi,
(core ==
PHY_CORE_0) ? 0xa6 : 0xa7,
(0x3 << 8), 0);
mask = (0x1 << 2) |
- (0x1 << 3) |
- (0x1 << 4) | (0x1 << 5);
+ (0x1 << 3) |
+ (0x1 << 4) | (0x1 << 5);
mod_phy_reg(pi,
(core ==
PHY_CORE_0) ? 0xf9 : 0xfb,
mask, 0);
if (rssi_type == NPHY_RSSI_SEL_W1) {
- if (CHSPEC_IS5G
- (pi->radio_chanspec)) {
+ if (CHSPEC_IS5G(
+ pi->radio_chanspec)) {
mask = (0x1 << 2);
val = 1 << 2;
} else {
@@ -20501,7 +21962,6 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
0xe5 : 0xe6, mask, val);
} else {
if (rssi_type == NPHY_RSSI_SEL_TBD) {
-
mask = (0x3 << 8);
val = 1 << 8;
mod_phy_reg(pi,
@@ -20516,7 +21976,6 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
: 0xa7, mask, val);
} else if (rssi_type ==
NPHY_RSSI_SEL_IQ) {
-
mask = (0x3 << 8);
val = 2 << 8;
mod_phy_reg(pi,
@@ -20530,7 +21989,6 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
PHY_CORE_0) ? 0xa6
: 0xa7, mask, val);
} else {
-
mask = (0x3 << 8);
val = 3 << 8;
mod_phy_reg(pi,
@@ -20543,86 +22001,13 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
(core ==
PHY_CORE_0) ? 0xa6
: 0xa7, mask, val);
-
- if (PHY_IPA(pi)) {
- if (NREV_GE
- (pi->pubpi.phy_rev,
- 7)) {
-
- write_radio_reg
- (pi,
- ((core ==
- PHY_CORE_0)
- ?
- RADIO_2057_TX0_TX_SSI_MUX
- :
- RADIO_2057_TX1_TX_SSI_MUX),
- (CHSPEC_IS5G
- (pi->
- radio_chanspec)
- ? 0xc :
- 0xe));
- } else {
- write_radio_reg
- (pi,
- RADIO_2056_TX_TX_SSI_MUX
- |
- ((core ==
- PHY_CORE_0)
- ?
- RADIO_2056_TX0
- :
- RADIO_2056_TX1),
- (CHSPEC_IS5G
- (pi->
- radio_chanspec)
- ? 0xc :
- 0xe));
- }
- } else {
-
- if (NREV_GE
- (pi->pubpi.phy_rev,
- 7)) {
- write_radio_reg
- (pi,
- ((core ==
- PHY_CORE_0)
- ?
- RADIO_2057_TX0_TX_SSI_MUX
- :
- RADIO_2057_TX1_TX_SSI_MUX),
- 0x11);
-
- if (pi->pubpi.
- radioid ==
- BCM2057_ID)
- write_radio_reg
- (pi,
- RADIO_2057_IQTEST_SEL_PU,
- 0x1);
-
- } else {
- write_radio_reg
- (pi,
- RADIO_2056_TX_TX_SSI_MUX
- |
- ((core ==
- PHY_CORE_0)
- ?
- RADIO_2056_TX0
- :
- RADIO_2056_TX1),
- 0x11);
- }
- }
-
+ brcms_phy_wr_tx_mux(pi, core);
afectrlovr_rssi_val = 1 << 9;
mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x8f
- : 0xa5, (0x1 << 9),
- afectrlovr_rssi_val);
+ (core ==
+ PHY_CORE_0) ? 0x8f
+ : 0xa5, (0x1 << 9),
+ afectrlovr_rssi_val);
}
}
}
@@ -20631,19 +22016,15 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
if ((rssi_type == NPHY_RSSI_SEL_W1) ||
(rssi_type == NPHY_RSSI_SEL_W2) ||
- (rssi_type == NPHY_RSSI_SEL_NB)) {
-
+ (rssi_type == NPHY_RSSI_SEL_NB))
val = 0x0;
- } else if (rssi_type == NPHY_RSSI_SEL_TBD) {
-
+ else if (rssi_type == NPHY_RSSI_SEL_TBD)
val = 0x1;
- } else if (rssi_type == NPHY_RSSI_SEL_IQ) {
-
+ else if (rssi_type == NPHY_RSSI_SEL_IQ)
val = 0x2;
- } else {
-
+ else
val = 0x3;
- }
+
mask = ((0x3 << 12) | (0x3 << 14));
val = (val << 12) | (val << 14);
mod_phy_reg(pi, 0xa6, mask, val);
@@ -20652,15 +22033,13 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
if ((rssi_type == NPHY_RSSI_SEL_W1) ||
(rssi_type == NPHY_RSSI_SEL_W2) ||
(rssi_type == NPHY_RSSI_SEL_NB)) {
- if (rssi_type == NPHY_RSSI_SEL_W1) {
+ if (rssi_type == NPHY_RSSI_SEL_W1)
val = 0x1;
- }
- if (rssi_type == NPHY_RSSI_SEL_W2) {
+ if (rssi_type == NPHY_RSSI_SEL_W2)
val = 0x2;
- }
- if (rssi_type == NPHY_RSSI_SEL_NB) {
+ if (rssi_type == NPHY_RSSI_SEL_NB)
val = 0x3;
- }
+
mask = (0x3 << 4);
val = (val << 4);
mod_phy_reg(pi, 0x7a, mask, val);
@@ -20698,16 +22077,16 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
(rssi_type == NPHY_RSSI_SEL_NB)) {
rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3));
rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) |
- (rfctrlcmd_coresel_val << 3);
+ (rfctrlcmd_coresel_val << 3);
rfctrlovr_mask = ((0x1 << 5) |
(0x1 << 12) |
(0x1 << 1) | (0x1 << 0));
rfctrlovr_val = (rfctrlovr_rssi_val <<
5) |
- (rfctrlovr_rxen_val << 12) |
- (rfctrlovr_coresel_val << 1) |
- (rfctrlovr_trigger_val << 0);
+ (rfctrlovr_rxen_val << 12) |
+ (rfctrlovr_coresel_val << 1) |
+ (rfctrlovr_trigger_val << 0);
mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val);
mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val);
@@ -20762,13 +22141,11 @@ wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf,
wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
gpiosel_orig = read_phy_reg(pi, 0xca);
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+ if (NREV_LT(pi->pubpi.phy_rev, 2))
write_phy_reg(pi, 0xca, 5);
- }
- for (ctr = 0; ctr < 4; ctr++) {
+ for (ctr = 0; ctr < 4; ctr++)
rssi_buf[ctr] = 0;
- }
for (samp = 0; samp < nsamps; samp++) {
if (NREV_LT(pi->pubpi.phy_rev, 2)) {
@@ -20785,9 +22162,8 @@ wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf,
tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2;
tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2;
- for (ctr = 0; ctr < 4; ctr++) {
+ for (ctr = 0; ctr < 4; ctr++)
rssi_buf[ctr] += tmp_buf[ctr];
- }
}
@@ -20796,9 +22172,8 @@ wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf,
rssi_out_val |= (rssi_buf[1] & 0xff) << 16;
rssi_out_val |= (rssi_buf[0] & 0xff) << 24;
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+ if (NREV_LT(pi->pubpi.phy_rev, 2))
write_phy_reg(pi, 0xca, gpiosel_orig);
- }
write_phy_reg(pi, 0xa6, afectrlCore1_save);
write_phy_reg(pi, 0xa7, afectrlCore2_save);
@@ -20848,7 +22223,7 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
u16 tempsense_Rcal;
syn_tempprocsense_save =
- read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG);
+ read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG);
afectrlCore1_save = read_phy_reg(pi, 0xa6);
afectrlCore2_save = read_phy_reg(pi, 0xa7);
@@ -20982,7 +22357,7 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
syn_tempprocsense_save =
- read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE);
+ read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE);
afectrlCore1_save = read_phy_reg(pi, 0xa6);
afectrlCore2_save = read_phy_reg(pi, 0xa7);
@@ -20997,14 +22372,13 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05);
wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01);
- } else {
+ else
write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
- }
radio_temp[0] =
- (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64;
+ (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64;
write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE,
syn_tempprocsense_save);
@@ -21019,17 +22393,17 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
} else {
pwrdet_rxtx_core1_save =
- read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
pwrdet_rxtx_core2_save =
- read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
core1_txrf_iqcal1_save =
- read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
core1_txrf_iqcal2_save =
- read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
core2_txrf_iqcal1_save =
- read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
core2_txrf_iqcal2_save =
- read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS);
afectrlCore1_save = read_phy_reg(pi, 0xa6);
@@ -21060,11 +22434,12 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
radio_temp[3] = (radio_temp[3] + radio_temp2[3]);
radio_temp[0] =
- (radio_temp[0] + radio_temp[1] + radio_temp[2] +
- radio_temp[3]);
+ (radio_temp[0] + radio_temp[1] + radio_temp[2] +
+ radio_temp[3]);
radio_temp[0] =
- (radio_temp[0] + (8 * 32)) * (950 - 350) / 63 + (350 * 8);
+ (radio_temp[0] +
+ (8 * 32)) * (950 - 350) / 63 + (350 * 8);
radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38;
@@ -21126,521 +22501,24 @@ wlc_phy_set_rssi_2055_vcm(struct brcms_phy *pi, u8 rssi_type, u8 *vcm_buf)
RADIO_2055_NBRSSI_VCM_Q_SHIFT);
}
} else {
-
- if (core == PHY_CORE_0) {
+ if (core == PHY_CORE_0)
mod_radio_reg(pi,
RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
RADIO_2055_WBRSSI_VCM_IQ_MASK,
vcm_buf[2 *
core] <<
RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
- } else {
+ else
mod_radio_reg(pi,
RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
RADIO_2055_WBRSSI_VCM_IQ_MASK,
vcm_buf[2 *
core] <<
RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
- }
}
}
}
-void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi)
-{
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- wlc_phy_rssi_cal_nphy_rev3(pi);
- } else {
- wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB);
- wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1);
- wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2);
- }
-}
-
-static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type)
-{
- s32 target_code;
- u16 classif_state;
- u16 clip_state[2];
- u16 rssi_ctrl_state[2], pd_state[2];
- u16 rfctrlintc_state[2], rfpdcorerxtx_state[2];
- u16 rfctrlintc_override_val;
- u16 clip_off[] = { 0xffff, 0xffff };
- u16 rf_pd_val, pd_mask, rssi_ctrl_mask;
- u8 vcm, min_vcm, vcm_tmp[4];
- u8 vcm_final[4] = { 0, 0, 0, 0 };
- u8 result_idx, ctr;
- s32 poll_results[4][4] = {
- {0, 0, 0, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0},
- {0, 0, 0, 0}
- };
- s32 poll_miniq[4][2] = {
- {0, 0},
- {0, 0},
- {0, 0},
- {0, 0}
- };
- s32 min_d, curr_d;
- s32 fine_digital_offset[4];
- s32 poll_results_min[4] = { 0, 0, 0, 0 };
- s32 min_poll;
-
- switch (rssi_type) {
- case NPHY_RSSI_SEL_NB:
- target_code = NPHY_RSSICAL_NB_TARGET;
- break;
- case NPHY_RSSI_SEL_W1:
- target_code = NPHY_RSSICAL_W1_TARGET;
- break;
- case NPHY_RSSI_SEL_W2:
- target_code = NPHY_RSSICAL_W2_TARGET;
- break;
- default:
- return;
- break;
- }
-
- classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
- wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
- wlc_phy_clip_det_nphy(pi, 0, clip_state);
- wlc_phy_clip_det_nphy(pi, 1, clip_off);
-
- rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4;
- rfctrlintc_override_val =
- CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110;
-
- rfctrlintc_state[0] = read_phy_reg(pi, 0x91);
- rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX);
- write_phy_reg(pi, 0x91, rfctrlintc_override_val);
- write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val);
-
- rfctrlintc_state[1] = read_phy_reg(pi, 0x92);
- rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX);
- write_phy_reg(pi, 0x92, rfctrlintc_override_val);
- write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val);
-
- pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD |
- RADIO_2055_WBRSSI_G2_PD;
- pd_state[0] =
- read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask;
- pd_state[1] =
- read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask;
- mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0);
- mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0);
- rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
- RADIO_2055_WBRSSI_G2_SEL;
- rssi_ctrl_state[0] =
- read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask;
- rssi_ctrl_state[1] =
- read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask;
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
-
- wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
- NPHY_RAIL_I, rssi_type);
- wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
- NPHY_RAIL_Q, rssi_type);
-
- for (vcm = 0; vcm < 4; vcm++) {
-
- vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm;
- if (rssi_type != NPHY_RSSI_SEL_W2) {
- wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp);
- }
-
- wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0],
- NPHY_RSSICAL_NPOLL);
-
- if ((rssi_type == NPHY_RSSI_SEL_W1)
- || (rssi_type == NPHY_RSSI_SEL_W2)) {
- for (ctr = 0; ctr < 2; ctr++) {
- poll_miniq[vcm][ctr] =
- min(poll_results[vcm][ctr * 2 + 0],
- poll_results[vcm][ctr * 2 + 1]);
- }
- }
- }
-
- for (result_idx = 0; result_idx < 4; result_idx++) {
- min_d = NPHY_RSSICAL_MAXD;
- min_vcm = 0;
- min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1;
- for (vcm = 0; vcm < 4; vcm++) {
- curr_d = ABS(((rssi_type == NPHY_RSSI_SEL_NB) ?
- poll_results[vcm][result_idx] :
- poll_miniq[vcm][result_idx / 2]) -
- (target_code * NPHY_RSSICAL_NPOLL));
- if (curr_d < min_d) {
- min_d = curr_d;
- min_vcm = vcm;
- }
- if (poll_results[vcm][result_idx] < min_poll) {
- min_poll = poll_results[vcm][result_idx];
- }
- }
- vcm_final[result_idx] = min_vcm;
- poll_results_min[result_idx] = min_poll;
- }
-
- if (rssi_type != NPHY_RSSI_SEL_W2) {
- wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final);
- }
-
- for (result_idx = 0; result_idx < 4; result_idx++) {
- fine_digital_offset[result_idx] =
- (target_code * NPHY_RSSICAL_NPOLL) -
- poll_results[vcm_final[result_idx]][result_idx];
- if (fine_digital_offset[result_idx] < 0) {
- fine_digital_offset[result_idx] =
- ABS(fine_digital_offset[result_idx]);
- fine_digital_offset[result_idx] +=
- (NPHY_RSSICAL_NPOLL / 2);
- fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
- fine_digital_offset[result_idx] =
- -fine_digital_offset[result_idx];
- } else {
- fine_digital_offset[result_idx] +=
- (NPHY_RSSICAL_NPOLL / 2);
- fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
- }
-
- if (poll_results_min[result_idx] ==
- NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
- fine_digital_offset[result_idx] =
- (target_code - NPHY_RSSICAL_MAXREAD - 1);
- }
-
- wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
- (s8)
- fine_digital_offset[result_idx],
- (result_idx / 2 ==
- 0) ? RADIO_MIMO_CORESEL_CORE1 :
- RADIO_MIMO_CORESEL_CORE2,
- (result_idx % 2 ==
- 0) ? NPHY_RAIL_I : NPHY_RAIL_Q,
- rssi_type);
- }
-
- mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]);
- mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]);
- if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
- NPHY_RSSI_SEL_NB);
- } else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
- NPHY_RSSI_SEL_W1);
- } else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
- NPHY_RSSI_SEL_W2);
- } else {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
- NPHY_RSSI_SEL_W2);
- }
- if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
- NPHY_RSSI_SEL_NB);
- } else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
- NPHY_RSSI_SEL_W1);
- } else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
- NPHY_RSSI_SEL_W2);
- } else {
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
- NPHY_RSSI_SEL_W2);
- }
-
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
-
- write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
- write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]);
- write_phy_reg(pi, 0x92, rfctrlintc_state[1]);
- write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]);
-
- wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
- wlc_phy_clip_det_nphy(pi, 1, clip_state);
-
- wlc_phy_resetcca_nphy(pi);
-}
-
-int
-wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct brcms_d11rxhdr *wlc_rxh)
-{
- struct d11rxhdr *rxh = &wlc_rxh->rxhdr;
- s16 rxpwr, rxpwr0, rxpwr1;
- s16 phyRx0_l, phyRx2_l;
-
- rxpwr = 0;
- rxpwr0 = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR0_MASK;
- rxpwr1 = (le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR1_MASK) >> 8;
-
- if (rxpwr0 > 127)
- rxpwr0 -= 256;
- if (rxpwr1 > 127)
- rxpwr1 -= 256;
-
- phyRx0_l = le16_to_cpu(rxh->PhyRxStatus_0) & 0x00ff;
- phyRx2_l = le16_to_cpu(rxh->PhyRxStatus_2) & 0x00ff;
- if (phyRx2_l > 127)
- phyRx2_l -= 256;
-
- if (((rxpwr0 == 16) || (rxpwr0 == 32))) {
- rxpwr0 = rxpwr1;
- rxpwr1 = phyRx2_l;
- }
-
- wlc_rxh->rxpwr[0] = (s8) rxpwr0;
- wlc_rxh->rxpwr[1] = (s8) rxpwr1;
- wlc_rxh->do_rssi_ma = 0;
-
- if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX)
- rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1;
- else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN)
- rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1;
- else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG)
- rxpwr = (rxpwr0 + rxpwr1) >> 1;
-
- return rxpwr;
-}
-
-static void
-wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value,
- u8 core_code)
-{
- u16 mask;
- u16 val;
- u8 core;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- if (core_code == RADIO_MIMO_CORESEL_CORE1
- && core == PHY_CORE_1)
- continue;
- else if (core_code == RADIO_MIMO_CORESEL_CORE2
- && core == PHY_CORE_0)
- continue;
-
- if (NREV_LT(pi->pubpi.phy_rev, 7)) {
-
- mask = (0x1 << 10);
- val = 1 << 10;
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
- 0x92, mask, val);
- }
-
- if (field == NPHY_RfctrlIntc_override_OFF) {
-
- write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
- 0x92, 0);
-
- wlc_phy_force_rfseq_nphy(pi,
- NPHY_RFSEQ_RESET2RX);
- } else if (field == NPHY_RfctrlIntc_override_TRSW) {
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- mask = (0x1 << 6) | (0x1 << 7);
-
- val = value << 6;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
-
- or_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- (0x1 << 10));
-
- and_phy_reg(pi, 0x2ff, (u16)
- ~(0x3 << 14));
- or_phy_reg(pi, 0x2ff, (0x1 << 13));
- or_phy_reg(pi, 0x2ff, (0x1 << 0));
- } else {
-
- mask = (0x1 << 6) |
- (0x1 << 7) |
- (0x1 << 8) | (0x1 << 9);
- val = value << 6;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
-
- mask = (0x1 << 0);
- val = 1 << 0;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0xe7 : 0xec,
- mask, val);
-
- mask = (core == PHY_CORE_0) ? (0x1 << 0)
- : (0x1 << 1);
- val = 1 << ((core == PHY_CORE_0) ?
- 0 : 1);
- mod_phy_reg(pi, 0x78, mask, val);
-
- SPINWAIT(((read_phy_reg(pi, 0x78) & val)
- != 0), 10000);
- if (WARN(read_phy_reg(pi, 0x78) & val,
- "HW error: override failed"))
- return;
-
- mask = (0x1 << 0);
- val = 0 << 0;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0xe7 : 0xec,
- mask, val);
- }
- } else if (field == NPHY_RfctrlIntc_override_PA) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- mask = (0x1 << 4) | (0x1 << 5);
-
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- val = value << 5;
- } else {
- val = value << 4;
- }
-
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
-
- or_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- (0x1 << 12));
- } else {
-
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- mask = (0x1 << 5);
- val = value << 5;
- } else {
- mask = (0x1 << 4);
- val = value << 4;
- }
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
- }
- } else if (field == NPHY_RfctrlIntc_override_EXT_LNA_PU) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
- mask = (0x1 << 0);
- val = value << 0;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, val);
-
- mask = (0x1 << 2);
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, 0);
- } else {
-
- mask = (0x1 << 2);
- val = value << 2;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, val);
-
- mask = (0x1 << 0);
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, 0);
- }
-
- mask = (0x1 << 11);
- val = 1 << 11;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
- } else {
-
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- mask = (0x1 << 0);
- val = value << 0;
- } else {
- mask = (0x1 << 2);
- val = value << 2;
- }
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
- }
- } else if (field ==
- NPHY_RfctrlIntc_override_EXT_LNA_GAIN) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
- mask = (0x1 << 1);
- val = value << 1;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, val);
-
- mask = (0x1 << 3);
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, 0);
- } else {
-
- mask = (0x1 << 3);
- val = value << 3;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, val);
-
- mask = (0x1 << 1);
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91
- : 0x92, mask, 0);
- }
-
- mask = (0x1 << 11);
- val = 1 << 11;
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
- } else {
-
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- mask = (0x1 << 1);
- val = value << 1;
- } else {
- mask = (0x1 << 3);
- val = value << 3;
- }
- mod_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0x91 : 0x92,
- mask, val);
- }
- }
- }
- } else {
- return;
- }
-}
-
static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
{
u16 classif_state;
@@ -21683,10 +22561,14 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save;
u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save;
- NPHY_REV7_RfctrlOverride3_save = NPHY_REV7_RfctrlOverride4_save =
- NPHY_REV7_RfctrlOverride5_save = NPHY_REV7_RfctrlOverride6_save =
- NPHY_REV7_RfctrlMiscReg3_save = NPHY_REV7_RfctrlMiscReg4_save =
- NPHY_REV7_RfctrlMiscReg5_save = NPHY_REV7_RfctrlMiscReg6_save = 0;
+ NPHY_REV7_RfctrlOverride3_save =
+ NPHY_REV7_RfctrlOverride4_save =
+ NPHY_REV7_RfctrlOverride5_save =
+ NPHY_REV7_RfctrlOverride6_save =
+ NPHY_REV7_RfctrlMiscReg3_save =
+ NPHY_REV7_RfctrlMiscReg4_save =
+ NPHY_REV7_RfctrlMiscReg5_save =
+ NPHY_REV7_RfctrlMiscReg6_save = 0;
classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
@@ -21726,21 +22608,21 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1,
RADIO_MIMO_CORESEL_ALLRXTX);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_rxrf_pu,
- 0, 0, 0);
- } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_rxrf_pu,
+ 0, 0, 0);
+ else
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0);
- }
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_rx_pu,
- 1, 0, 0);
- } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_rx_pu,
+ 1, 0, 0);
+ else
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0);
- }
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
@@ -21755,12 +22637,14 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
if (CHSPEC_IS5G(pi->radio_chanspec)) {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
- 0, 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0,
- 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 5),
+ 0, 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 4), 1, 0,
+ 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
} else {
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0);
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0);
@@ -21768,12 +22652,14 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
} else {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
- 0, 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 1, 0,
- 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 4),
+ 0, 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 5), 1, 0,
+ 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
} else {
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0);
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0);
@@ -21781,7 +22667,7 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
}
rxcore_state = wlc_phy_rxcore_getstate_nphy(
- (struct brcms_phy_pub *) pi);
+ (struct brcms_phy_pub *) pi);
vcm_level_max = 8;
@@ -21804,21 +22690,18 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
NPHY_RAIL_Q, NPHY_RSSI_SEL_NB);
for (vcm = 0; vcm < vcm_level_max; vcm++) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
mod_radio_reg(pi, (core == PHY_CORE_0) ?
RADIO_2057_NB_MASTER_CORE0 :
RADIO_2057_NB_MASTER_CORE1,
RADIO_2057_VCM_MASK, vcm);
- } else {
-
+ else
mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
((core ==
PHY_CORE_0) ? RADIO_2056_RX0 :
RADIO_2056_RX1),
RADIO_2056_VCM_MASK,
vcm << RADIO_2056_RSSI_VCM_SHIFT);
- }
wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB,
&poll_results[vcm][0],
@@ -21826,92 +22709,90 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
}
for (result_idx = 0; result_idx < 4; result_idx++) {
- if ((core == result_idx / 2) && (result_idx % 2 == 0)) {
+ if ((core == result_idx / 2) &&
+ (result_idx % 2 == 0)) {
min_d = NPHY_RSSICAL_MAXD;
min_vcm = 0;
min_poll =
- NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL +
- 1;
+ NPHY_RSSICAL_MAXREAD *
+ NPHY_RSSICAL_NPOLL + 1;
for (vcm = 0; vcm < vcm_level_max; vcm++) {
- curr_d = poll_results[vcm][result_idx] *
- poll_results[vcm][result_idx] +
- poll_results[vcm][result_idx + 1] *
- poll_results[vcm][result_idx + 1];
+ curr_d =
+ poll_results[vcm][result_idx] *
+ poll_results[vcm][result_idx] +
+ poll_results[vcm][result_idx +
+ 1] *
+ poll_results[vcm][result_idx +
+ 1];
if (curr_d < min_d) {
min_d = curr_d;
min_vcm = vcm;
}
if (poll_results[vcm][result_idx] <
- min_poll) {
+ min_poll)
min_poll =
- poll_results[vcm]
- [result_idx];
- }
+ poll_results[vcm]
+ [result_idx];
}
vcm_final = min_vcm;
poll_results_min[result_idx] = min_poll;
}
}
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
mod_radio_reg(pi, (core == PHY_CORE_0) ?
RADIO_2057_NB_MASTER_CORE0 :
RADIO_2057_NB_MASTER_CORE1,
RADIO_2057_VCM_MASK, vcm_final);
- } else {
+ else
mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
((core ==
PHY_CORE_0) ? RADIO_2056_RX0 :
RADIO_2056_RX1), RADIO_2056_VCM_MASK,
vcm_final << RADIO_2056_RSSI_VCM_SHIFT);
- }
for (result_idx = 0; result_idx < 4; result_idx++) {
if (core == result_idx / 2) {
fine_digital_offset[result_idx] =
- (NPHY_RSSICAL_NB_TARGET *
- NPHY_RSSICAL_NPOLL) -
- poll_results[vcm_final][result_idx];
+ (NPHY_RSSICAL_NB_TARGET *
+ NPHY_RSSICAL_NPOLL) -
+ poll_results[vcm_final][result_idx];
if (fine_digital_offset[result_idx] < 0) {
fine_digital_offset[result_idx] =
- ABS(fine_digital_offset
- [result_idx]);
+ abs(fine_digital_offset
+ [result_idx]);
fine_digital_offset[result_idx] +=
- (NPHY_RSSICAL_NPOLL / 2);
+ (NPHY_RSSICAL_NPOLL / 2);
fine_digital_offset[result_idx] /=
- NPHY_RSSICAL_NPOLL;
+ NPHY_RSSICAL_NPOLL;
fine_digital_offset[result_idx] =
- -fine_digital_offset[result_idx];
+ -fine_digital_offset[
+ result_idx];
} else {
fine_digital_offset[result_idx] +=
- (NPHY_RSSICAL_NPOLL / 2);
+ (NPHY_RSSICAL_NPOLL / 2);
fine_digital_offset[result_idx] /=
- NPHY_RSSICAL_NPOLL;
+ NPHY_RSSICAL_NPOLL;
}
if (poll_results_min[result_idx] ==
- NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
+ NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL)
fine_digital_offset[result_idx] =
- (NPHY_RSSICAL_NB_TARGET -
- NPHY_RSSICAL_MAXREAD - 1);
- }
-
- wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
- (s8)
- fine_digital_offset
- [result_idx],
- (result_idx /
- 2 ==
- 0) ?
- RADIO_MIMO_CORESEL_CORE1
- :
- RADIO_MIMO_CORESEL_CORE2,
- (result_idx %
- 2 ==
- 0) ? NPHY_RAIL_I
- : NPHY_RAIL_Q,
- NPHY_RSSI_SEL_NB);
+ (NPHY_RSSICAL_NB_TARGET -
+ NPHY_RSSICAL_MAXREAD - 1);
+
+ wlc_phy_scale_offset_rssi_nphy(
+ pi, 0x0,
+ (s8)
+ fine_digital_offset
+ [result_idx],
+ (result_idx / 2 == 0) ?
+ RADIO_MIMO_CORESEL_CORE1 :
+ RADIO_MIMO_CORESEL_CORE2,
+ (result_idx % 2 == 0) ?
+ NPHY_RAIL_I : NPHY_RAIL_Q,
+ NPHY_RSSI_SEL_NB);
}
}
@@ -21952,46 +22833,44 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
for (result_idx = 0; result_idx < 4; result_idx++) {
if (core == result_idx / 2) {
fine_digital_offset[result_idx] =
- (target_code * NPHY_RSSICAL_NPOLL) -
- poll_result_core[result_idx];
- if (fine_digital_offset[result_idx] < 0) {
+ (target_code *
+ NPHY_RSSICAL_NPOLL) -
+ poll_result_core[result_idx];
+ if (fine_digital_offset[result_idx] <
+ 0) {
fine_digital_offset[result_idx]
- =
- ABS(fine_digital_offset
- [result_idx]);
+ = abs(
+ fine_digital_offset
+ [result_idx]);
fine_digital_offset[result_idx]
- += (NPHY_RSSICAL_NPOLL / 2);
+ += (NPHY_RSSICAL_NPOLL
+ / 2);
fine_digital_offset[result_idx]
- /= NPHY_RSSICAL_NPOLL;
+ /= NPHY_RSSICAL_NPOLL;
fine_digital_offset[result_idx]
- =
- -fine_digital_offset
- [result_idx];
+ = -fine_digital_offset
+ [result_idx];
} else {
fine_digital_offset[result_idx]
- += (NPHY_RSSICAL_NPOLL / 2);
+ += (NPHY_RSSICAL_NPOLL
+ / 2);
fine_digital_offset[result_idx]
- /= NPHY_RSSICAL_NPOLL;
+ /= NPHY_RSSICAL_NPOLL;
}
- wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
- (s8)
- fine_digital_offset
- [core *
- 2],
- (core ==
- PHY_CORE_0)
- ?
- RADIO_MIMO_CORESEL_CORE1
- :
- RADIO_MIMO_CORESEL_CORE2,
- (result_idx
- % 2 ==
- 0) ?
- NPHY_RAIL_I
- :
- NPHY_RAIL_Q,
- rssi_type);
+ wlc_phy_scale_offset_rssi_nphy(
+ pi, 0x0,
+ (s8)
+ fine_digital_offset
+ [core *
+ 2],
+ (core == PHY_CORE_0) ?
+ RADIO_MIMO_CORESEL_CORE1 :
+ RADIO_MIMO_CORESEL_CORE2,
+ (result_idx % 2 == 0) ?
+ NPHY_RAIL_I :
+ NPHY_RAIL_Q,
+ rssi_type);
}
}
@@ -22040,87 +22919,87 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
pi->rssical_cache.rssical_radio_regs_2G[0] =
- read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
pi->rssical_cache.rssical_radio_regs_2G[1] =
- read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
} else {
pi->rssical_cache.rssical_radio_regs_2G[0] =
- read_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC |
- RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC |
+ RADIO_2056_RX0);
pi->rssical_cache.rssical_radio_regs_2G[1] =
- read_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC |
- RADIO_2056_RX1);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC |
+ RADIO_2056_RX1);
}
pi->rssical_cache.rssical_phyregs_2G[0] =
- read_phy_reg(pi, 0x1a6);
+ read_phy_reg(pi, 0x1a6);
pi->rssical_cache.rssical_phyregs_2G[1] =
- read_phy_reg(pi, 0x1ac);
+ read_phy_reg(pi, 0x1ac);
pi->rssical_cache.rssical_phyregs_2G[2] =
- read_phy_reg(pi, 0x1b2);
+ read_phy_reg(pi, 0x1b2);
pi->rssical_cache.rssical_phyregs_2G[3] =
- read_phy_reg(pi, 0x1b8);
+ read_phy_reg(pi, 0x1b8);
pi->rssical_cache.rssical_phyregs_2G[4] =
- read_phy_reg(pi, 0x1a4);
+ read_phy_reg(pi, 0x1a4);
pi->rssical_cache.rssical_phyregs_2G[5] =
- read_phy_reg(pi, 0x1aa);
+ read_phy_reg(pi, 0x1aa);
pi->rssical_cache.rssical_phyregs_2G[6] =
- read_phy_reg(pi, 0x1b0);
+ read_phy_reg(pi, 0x1b0);
pi->rssical_cache.rssical_phyregs_2G[7] =
- read_phy_reg(pi, 0x1b6);
+ read_phy_reg(pi, 0x1b6);
pi->rssical_cache.rssical_phyregs_2G[8] =
- read_phy_reg(pi, 0x1a5);
+ read_phy_reg(pi, 0x1a5);
pi->rssical_cache.rssical_phyregs_2G[9] =
- read_phy_reg(pi, 0x1ab);
+ read_phy_reg(pi, 0x1ab);
pi->rssical_cache.rssical_phyregs_2G[10] =
- read_phy_reg(pi, 0x1b1);
+ read_phy_reg(pi, 0x1b1);
pi->rssical_cache.rssical_phyregs_2G[11] =
- read_phy_reg(pi, 0x1b7);
+ read_phy_reg(pi, 0x1b7);
pi->nphy_rssical_chanspec_2G = pi->radio_chanspec;
} else {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
pi->rssical_cache.rssical_radio_regs_5G[0] =
- read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
pi->rssical_cache.rssical_radio_regs_5G[1] =
- read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
} else {
pi->rssical_cache.rssical_radio_regs_5G[0] =
- read_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC |
- RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC |
+ RADIO_2056_RX0);
pi->rssical_cache.rssical_radio_regs_5G[1] =
- read_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC |
- RADIO_2056_RX1);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RSSI_MISC |
+ RADIO_2056_RX1);
}
pi->rssical_cache.rssical_phyregs_5G[0] =
- read_phy_reg(pi, 0x1a6);
+ read_phy_reg(pi, 0x1a6);
pi->rssical_cache.rssical_phyregs_5G[1] =
- read_phy_reg(pi, 0x1ac);
+ read_phy_reg(pi, 0x1ac);
pi->rssical_cache.rssical_phyregs_5G[2] =
- read_phy_reg(pi, 0x1b2);
+ read_phy_reg(pi, 0x1b2);
pi->rssical_cache.rssical_phyregs_5G[3] =
- read_phy_reg(pi, 0x1b8);
+ read_phy_reg(pi, 0x1b8);
pi->rssical_cache.rssical_phyregs_5G[4] =
- read_phy_reg(pi, 0x1a4);
+ read_phy_reg(pi, 0x1a4);
pi->rssical_cache.rssical_phyregs_5G[5] =
- read_phy_reg(pi, 0x1aa);
+ read_phy_reg(pi, 0x1aa);
pi->rssical_cache.rssical_phyregs_5G[6] =
- read_phy_reg(pi, 0x1b0);
+ read_phy_reg(pi, 0x1b0);
pi->rssical_cache.rssical_phyregs_5G[7] =
- read_phy_reg(pi, 0x1b6);
+ read_phy_reg(pi, 0x1b6);
pi->rssical_cache.rssical_phyregs_5G[8] =
- read_phy_reg(pi, 0x1a5);
+ read_phy_reg(pi, 0x1a5);
pi->rssical_cache.rssical_phyregs_5G[9] =
- read_phy_reg(pi, 0x1ab);
+ read_phy_reg(pi, 0x1ab);
pi->rssical_cache.rssical_phyregs_5G[10] =
- read_phy_reg(pi, 0x1b1);
+ read_phy_reg(pi, 0x1b1);
pi->rssical_cache.rssical_phyregs_5G[11] =
- read_phy_reg(pi, 0x1b7);
+ read_phy_reg(pi, 0x1b7);
pi->nphy_rssical_chanspec_5G = pi->radio_chanspec;
}
@@ -22129,121 +23008,287 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
wlc_phy_clip_det_nphy(pi, 1, clip_state);
}
-static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi)
+static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type)
{
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (pi->nphy_rssical_chanspec_2G == 0)
- return;
+ s32 target_code;
+ u16 classif_state;
+ u16 clip_state[2];
+ u16 rssi_ctrl_state[2], pd_state[2];
+ u16 rfctrlintc_state[2], rfpdcorerxtx_state[2];
+ u16 rfctrlintc_override_val;
+ u16 clip_off[] = { 0xffff, 0xffff };
+ u16 rf_pd_val, pd_mask, rssi_ctrl_mask;
+ u8 vcm, min_vcm, vcm_tmp[4];
+ u8 vcm_final[4] = { 0, 0, 0, 0 };
+ u8 result_idx, ctr;
+ s32 poll_results[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+ };
+ s32 poll_miniq[4][2] = {
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}
+ };
+ s32 min_d, curr_d;
+ s32 fine_digital_offset[4];
+ s32 poll_results_min[4] = { 0, 0, 0, 0 };
+ s32 min_poll;
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
- RADIO_2057_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_2G[0]);
- mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
- RADIO_2057_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_2G[1]);
- } else {
- mod_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
- RADIO_2056_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_2G[0]);
- mod_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
- RADIO_2056_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_2G[1]);
+ switch (rssi_type) {
+ case NPHY_RSSI_SEL_NB:
+ target_code = NPHY_RSSICAL_NB_TARGET;
+ break;
+ case NPHY_RSSI_SEL_W1:
+ target_code = NPHY_RSSICAL_W1_TARGET;
+ break;
+ case NPHY_RSSI_SEL_W2:
+ target_code = NPHY_RSSICAL_W2_TARGET;
+ break;
+ default:
+ return;
+ break;
+ }
+
+ classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+ wlc_phy_clip_det_nphy(pi, 0, clip_state);
+ wlc_phy_clip_det_nphy(pi, 1, clip_off);
+
+ rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4;
+ rfctrlintc_override_val =
+ CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110;
+
+ rfctrlintc_state[0] = read_phy_reg(pi, 0x91);
+ rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX);
+ write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+ write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val);
+
+ rfctrlintc_state[1] = read_phy_reg(pi, 0x92);
+ rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX);
+ write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+ write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val);
+
+ pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD |
+ RADIO_2055_WBRSSI_G2_PD;
+ pd_state[0] =
+ read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask;
+ pd_state[1] =
+ read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask;
+ mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0);
+ mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0);
+ rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
+ RADIO_2055_WBRSSI_G2_SEL;
+ rssi_ctrl_state[0] =
+ read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask;
+ rssi_ctrl_state[1] =
+ read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask;
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
+
+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+ NPHY_RAIL_I, rssi_type);
+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+ NPHY_RAIL_Q, rssi_type);
+
+ for (vcm = 0; vcm < 4; vcm++) {
+
+ vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm;
+ if (rssi_type != NPHY_RSSI_SEL_W2)
+ wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp);
+
+ wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0],
+ NPHY_RSSICAL_NPOLL);
+
+ if ((rssi_type == NPHY_RSSI_SEL_W1)
+ || (rssi_type == NPHY_RSSI_SEL_W2)) {
+ for (ctr = 0; ctr < 2; ctr++)
+ poll_miniq[vcm][ctr] =
+ min(poll_results[vcm][ctr * 2 + 0],
+ poll_results[vcm][ctr * 2 + 1]);
}
+ }
- write_phy_reg(pi, 0x1a6,
- pi->rssical_cache.rssical_phyregs_2G[0]);
- write_phy_reg(pi, 0x1ac,
- pi->rssical_cache.rssical_phyregs_2G[1]);
- write_phy_reg(pi, 0x1b2,
- pi->rssical_cache.rssical_phyregs_2G[2]);
- write_phy_reg(pi, 0x1b8,
- pi->rssical_cache.rssical_phyregs_2G[3]);
- write_phy_reg(pi, 0x1a4,
- pi->rssical_cache.rssical_phyregs_2G[4]);
- write_phy_reg(pi, 0x1aa,
- pi->rssical_cache.rssical_phyregs_2G[5]);
- write_phy_reg(pi, 0x1b0,
- pi->rssical_cache.rssical_phyregs_2G[6]);
- write_phy_reg(pi, 0x1b6,
- pi->rssical_cache.rssical_phyregs_2G[7]);
- write_phy_reg(pi, 0x1a5,
- pi->rssical_cache.rssical_phyregs_2G[8]);
- write_phy_reg(pi, 0x1ab,
- pi->rssical_cache.rssical_phyregs_2G[9]);
- write_phy_reg(pi, 0x1b1,
- pi->rssical_cache.rssical_phyregs_2G[10]);
- write_phy_reg(pi, 0x1b7,
- pi->rssical_cache.rssical_phyregs_2G[11]);
+ for (result_idx = 0; result_idx < 4; result_idx++) {
+ min_d = NPHY_RSSICAL_MAXD;
+ min_vcm = 0;
+ min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1;
+ for (vcm = 0; vcm < 4; vcm++) {
+ curr_d = abs(((rssi_type == NPHY_RSSI_SEL_NB) ?
+ poll_results[vcm][result_idx] :
+ poll_miniq[vcm][result_idx / 2]) -
+ (target_code * NPHY_RSSICAL_NPOLL));
+ if (curr_d < min_d) {
+ min_d = curr_d;
+ min_vcm = vcm;
+ }
+ if (poll_results[vcm][result_idx] < min_poll)
+ min_poll = poll_results[vcm][result_idx];
+ }
+ vcm_final[result_idx] = min_vcm;
+ poll_results_min[result_idx] = min_poll;
+ }
- } else {
- if (pi->nphy_rssical_chanspec_5G == 0)
- return;
+ if (rssi_type != NPHY_RSSI_SEL_W2)
+ wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
- RADIO_2057_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_5G[0]);
- mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
- RADIO_2057_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_5G[1]);
+ for (result_idx = 0; result_idx < 4; result_idx++) {
+ fine_digital_offset[result_idx] =
+ (target_code * NPHY_RSSICAL_NPOLL) -
+ poll_results[vcm_final[result_idx]][result_idx];
+ if (fine_digital_offset[result_idx] < 0) {
+ fine_digital_offset[result_idx] =
+ abs(fine_digital_offset[result_idx]);
+ fine_digital_offset[result_idx] +=
+ (NPHY_RSSICAL_NPOLL / 2);
+ fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
+ fine_digital_offset[result_idx] =
+ -fine_digital_offset[result_idx];
} else {
- mod_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
- RADIO_2056_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_5G[0]);
- mod_radio_reg(pi,
- RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
- RADIO_2056_VCM_MASK,
- pi->rssical_cache.
- rssical_radio_regs_5G[1]);
+ fine_digital_offset[result_idx] +=
+ (NPHY_RSSICAL_NPOLL / 2);
+ fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
}
- write_phy_reg(pi, 0x1a6,
- pi->rssical_cache.rssical_phyregs_5G[0]);
- write_phy_reg(pi, 0x1ac,
- pi->rssical_cache.rssical_phyregs_5G[1]);
- write_phy_reg(pi, 0x1b2,
- pi->rssical_cache.rssical_phyregs_5G[2]);
- write_phy_reg(pi, 0x1b8,
- pi->rssical_cache.rssical_phyregs_5G[3]);
- write_phy_reg(pi, 0x1a4,
- pi->rssical_cache.rssical_phyregs_5G[4]);
- write_phy_reg(pi, 0x1aa,
- pi->rssical_cache.rssical_phyregs_5G[5]);
- write_phy_reg(pi, 0x1b0,
- pi->rssical_cache.rssical_phyregs_5G[6]);
- write_phy_reg(pi, 0x1b6,
- pi->rssical_cache.rssical_phyregs_5G[7]);
- write_phy_reg(pi, 0x1a5,
- pi->rssical_cache.rssical_phyregs_5G[8]);
- write_phy_reg(pi, 0x1ab,
- pi->rssical_cache.rssical_phyregs_5G[9]);
- write_phy_reg(pi, 0x1b1,
- pi->rssical_cache.rssical_phyregs_5G[10]);
- write_phy_reg(pi, 0x1b7,
- pi->rssical_cache.rssical_phyregs_5G[11]);
+ if (poll_results_min[result_idx] ==
+ NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL)
+ fine_digital_offset[result_idx] =
+ (target_code - NPHY_RSSICAL_MAXREAD - 1);
+
+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+ (s8)
+ fine_digital_offset[result_idx],
+ (result_idx / 2 ==
+ 0) ? RADIO_MIMO_CORESEL_CORE1 :
+ RADIO_MIMO_CORESEL_CORE2,
+ (result_idx % 2 ==
+ 0) ? NPHY_RAIL_I : NPHY_RAIL_Q,
+ rssi_type);
+ }
+
+ mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]);
+ mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]);
+ if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+ NPHY_RSSI_SEL_NB);
+ else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+ NPHY_RSSI_SEL_W1);
+ else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+ NPHY_RSSI_SEL_W2);
+ else
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+ NPHY_RSSI_SEL_W2);
+ if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+ NPHY_RSSI_SEL_NB);
+ else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+ NPHY_RSSI_SEL_W1);
+ else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL)
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+ NPHY_RSSI_SEL_W2);
+ else
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+ NPHY_RSSI_SEL_W2);
+
+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
+
+ write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
+ write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]);
+ write_phy_reg(pi, 0x92, rfctrlintc_state[1]);
+ write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]);
+
+ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+ wlc_phy_clip_det_nphy(pi, 1, clip_state);
+
+ wlc_phy_resetcca_nphy(pi);
+}
+
+void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi)
+{
+ if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ wlc_phy_rssi_cal_nphy_rev3(pi);
+ } else {
+ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB);
+ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1);
+ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2);
}
}
+int
+wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct d11rxhdr *rxh)
+{
+ s16 rxpwr, rxpwr0, rxpwr1;
+ s16 phyRx0_l, phyRx2_l;
+
+ rxpwr = 0;
+ rxpwr0 = rxh->PhyRxStatus_1 & PRXS1_nphy_PWR0_MASK;
+ rxpwr1 = (rxh->PhyRxStatus_1 & PRXS1_nphy_PWR1_MASK) >> 8;
+
+ if (rxpwr0 > 127)
+ rxpwr0 -= 256;
+ if (rxpwr1 > 127)
+ rxpwr1 -= 256;
+
+ phyRx0_l = rxh->PhyRxStatus_0 & 0x00ff;
+ phyRx2_l = rxh->PhyRxStatus_2 & 0x00ff;
+ if (phyRx2_l > 127)
+ phyRx2_l -= 256;
+
+ if (((rxpwr0 == 16) || (rxpwr0 == 32))) {
+ rxpwr0 = rxpwr1;
+ rxpwr1 = phyRx2_l;
+ }
+
+ if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX)
+ rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1;
+ else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN)
+ rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1;
+ else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG)
+ rxpwr = (rxpwr0 + rxpwr1) >> 1;
+
+ return rxpwr;
+}
+
+static void
+wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, struct cordic_iq *tone_buf,
+ u16 num_samps)
+{
+ u16 t;
+ u32 *data_buf = NULL;
+
+ data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC);
+ if (data_buf == NULL)
+ return;
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+ for (t = 0; t < num_samps; t++)
+ data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) |
+ (((unsigned int)tone_buf[t].q) & 0x3ff);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
+ data_buf);
+
+ kfree(data_buf);
+
+ if (pi->phyhang_avoid)
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
static u16
wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
u8 dac_test_mode)
{
u8 phy_bw, is_phybw40;
u16 num_samps, t, spur;
- fixed theta = 0, rot = 0;
+ s32 theta = 0, rot = 0;
u32 tbl_len;
- cs32 *tone_buf = NULL;
+ struct cordic_iq *tone_buf = NULL;
is_phybw40 = CHSPEC_IS40(pi->radio_chanspec);
phy_bw = (is_phybw40 == 1) ? 40 : 20;
@@ -22258,18 +23303,17 @@ wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
tbl_len = (phy_bw << 1);
}
- tone_buf = kmalloc(sizeof(cs32) * tbl_len, GFP_ATOMIC);
- if (tone_buf == NULL) {
+ tone_buf = kmalloc(sizeof(struct cordic_iq) * tbl_len, GFP_ATOMIC);
+ if (tone_buf == NULL)
return 0;
- }
num_samps = (u16) tbl_len;
- rot = FIXED((f_kHz * 36) / phy_bw) / 100;
+ rot = ((f_kHz * 36) / phy_bw) / 100;
theta = 0;
for (t = 0; t < num_samps; t++) {
- wlc_phy_cordic(theta, &tone_buf[t]);
+ tone_buf[t] = cordic_calc_iq(theta);
theta += rot;
@@ -22284,54 +23328,6 @@ wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
return num_samps;
}
-int
-wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
- u8 iqmode, u8 dac_test_mode, bool modify_bbmult)
-{
- u16 num_samps;
- u16 loops = 0xffff;
- u16 wait = 0;
-
- num_samps =
- wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, dac_test_mode);
- if (num_samps == 0) {
- return -EBADE;
- }
-
- wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode,
- dac_test_mode, modify_bbmult);
-
- return 0;
-}
-
-static void
-wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, cs32 *tone_buf,
- u16 num_samps)
-{
- u16 t;
- u32 *data_buf = NULL;
-
- data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC);
- if (data_buf == NULL) {
- return;
- }
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- for (t = 0; t < num_samps; t++) {
- data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) |
- (((unsigned int)tone_buf[t].q) & 0x3ff);
- }
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
- data_buf);
-
- kfree(data_buf);
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
static void
wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
u16 wait, u8 iqmode, u8 dac_test_mode,
@@ -22356,22 +23352,24 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7);
if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) {
lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
- (0x7 << 8);
+ (0x7 << 8);
lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
- (0x7 << 8);
+ (0x7 << 8);
} else {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 7),
- wlc_phy_read_lpf_bw_ctl_nphy
- (pi, 0), 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 7),
+ wlc_phy_read_lpf_bw_ctl_nphy
+ (pi,
+ 0), 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
pi->nphy_sample_play_lpf_bw_ctl_ovr = true;
lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
- (0x7 << 8);
+ (0x7 << 8);
lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
- (0x7 << 8);
+ (0x7 << 8);
}
}
@@ -22380,7 +23378,7 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
&bb_mult);
pi->nphy_bb_mult_save =
- BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK);
+ BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK);
}
if (modify_bbmult) {
@@ -22395,11 +23393,11 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
write_phy_reg(pi, 0xc6, num_samps - 1);
- if (loops != 0xffff) {
+ if (loops != 0xffff)
write_phy_reg(pi, 0xc4, loops - 1);
- } else {
+ else
write_phy_reg(pi, 0xc4, loops);
- }
+
write_phy_reg(pi, 0xc5, wait);
orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
@@ -22420,6 +23418,25 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
}
+int
+wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
+ u8 iqmode, u8 dac_test_mode, bool modify_bbmult)
+{
+ u16 num_samps;
+ u16 loops = 0xffff;
+ u16 wait = 0;
+
+ num_samps = wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val,
+ dac_test_mode);
+ if (num_samps == 0)
+ return -EBADE;
+
+ wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode,
+ dac_test_mode, modify_bbmult);
+
+ return 0;
+}
+
void wlc_phy_stopplayback_nphy(struct brcms_phy *pi)
{
u16 playback_status;
@@ -22429,13 +23446,11 @@ void wlc_phy_stopplayback_nphy(struct brcms_phy *pi)
wlc_phy_stay_in_carriersearch_nphy(pi, true);
playback_status = read_phy_reg(pi, 0xc7);
- if (playback_status & 0x1) {
+ if (playback_status & 0x1)
or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP);
- } else if (playback_status & 0x2) {
-
+ else if (playback_status & 0x2)
and_phy_reg(pi, 0xc2,
(u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN);
- }
and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2));
@@ -22450,10 +23465,11 @@ void wlc_phy_stopplayback_nphy(struct brcms_phy *pi)
if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) {
if (pi->nphy_sample_play_lpf_bw_ctl_ovr) {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 7),
- 0, 0, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 7),
+ 0, 0, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
pi->nphy_sample_play_lpf_bw_ctl_ovr = false;
}
}
@@ -22462,6 +23478,47 @@ void wlc_phy_stopplayback_nphy(struct brcms_phy *pi)
wlc_phy_stay_in_carriersearch_nphy(pi, false);
}
+static u32 *brcms_phy_get_tx_pwrctrl_tbl(struct brcms_phy *pi)
+{
+ u32 *tx_pwrctrl_tbl = NULL;
+ uint phyrev = pi->pubpi.phy_rev;
+
+ if (PHY_IPA(pi)) {
+ tx_pwrctrl_tbl =
+ wlc_phy_get_ipa_gaintbl_nphy(pi);
+ } else {
+ if (CHSPEC_IS5G(pi->radio_chanspec)) {
+ if (NREV_IS(phyrev, 3))
+ tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev3;
+ else if (NREV_IS(phyrev, 4))
+ tx_pwrctrl_tbl =
+ (pi->srom_fem5g.extpagain == 3) ?
+ nphy_tpc_5GHz_txgain_HiPwrEPA :
+ nphy_tpc_5GHz_txgain_rev4;
+ else
+ tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev5;
+ } else {
+ if (NREV_GE(phyrev, 7)) {
+ if (pi->pubpi.radiorev == 3)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_epa_2057rev3;
+ else if (pi->pubpi.radiorev == 5)
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_epa_2057rev5;
+ } else {
+ if (NREV_GE(phyrev, 5) &&
+ (pi->srom_fem2g.extpagain == 3))
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_HiPwrEPA;
+ else
+ tx_pwrctrl_tbl =
+ nphy_tpc_txgain_rev3;
+ }
+ }
+ }
+ return tx_pwrctrl_tbl;
+}
+
struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi)
{
u16 base_idx[2], curr_gain[2];
@@ -22482,33 +23539,33 @@ struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi)
for (core_no = 0; core_no < 2; core_no++) {
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
target_gain.ipa[core_no] =
- curr_gain[core_no] & 0x0007;
+ curr_gain[core_no] & 0x0007;
target_gain.pad[core_no] =
- ((curr_gain[core_no] & 0x00F8) >> 3);
+ ((curr_gain[core_no] & 0x00F8) >> 3);
target_gain.pga[core_no] =
- ((curr_gain[core_no] & 0x0F00) >> 8);
+ ((curr_gain[core_no] & 0x0F00) >> 8);
target_gain.txgm[core_no] =
- ((curr_gain[core_no] & 0x7000) >> 12);
+ ((curr_gain[core_no] & 0x7000) >> 12);
target_gain.txlpf[core_no] =
- ((curr_gain[core_no] & 0x8000) >> 15);
+ ((curr_gain[core_no] & 0x8000) >> 15);
} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
target_gain.ipa[core_no] =
- curr_gain[core_no] & 0x000F;
+ curr_gain[core_no] & 0x000F;
target_gain.pad[core_no] =
- ((curr_gain[core_no] & 0x00F0) >> 4);
+ ((curr_gain[core_no] & 0x00F0) >> 4);
target_gain.pga[core_no] =
- ((curr_gain[core_no] & 0x0F00) >> 8);
+ ((curr_gain[core_no] & 0x0F00) >> 8);
target_gain.txgm[core_no] =
- ((curr_gain[core_no] & 0x7000) >> 12);
+ ((curr_gain[core_no] & 0x7000) >> 12);
} else {
target_gain.ipa[core_no] =
- curr_gain[core_no] & 0x0003;
+ curr_gain[core_no] & 0x0003;
target_gain.pad[core_no] =
- ((curr_gain[core_no] & 0x000C) >> 2);
+ ((curr_gain[core_no] & 0x000C) >> 2);
target_gain.pga[core_no] =
- ((curr_gain[core_no] & 0x0070) >> 4);
+ ((curr_gain[core_no] & 0x0070) >> 4);
target_gain.txgm[core_no] =
- ((curr_gain[core_no] & 0x0380) >> 7);
+ ((curr_gain[core_no] & 0x0380) >> 7);
}
}
} else {
@@ -22518,96 +23575,60 @@ struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi)
base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f;
for (core_no = 0; core_no < 2; core_no++) {
if (NREV_GE(phyrev, 3)) {
- if (PHY_IPA(pi)) {
- tx_pwrctrl_tbl =
- wlc_phy_get_ipa_gaintbl_nphy(pi);
- } else {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (NREV_IS(phyrev, 3)) {
- tx_pwrctrl_tbl =
- nphy_tpc_5GHz_txgain_rev3;
- } else if (NREV_IS(phyrev, 4)) {
- tx_pwrctrl_tbl =
- (pi->srom_fem5g.
- extpagain ==
- 3) ?
- nphy_tpc_5GHz_txgain_HiPwrEPA
- :
- nphy_tpc_5GHz_txgain_rev4;
- } else {
- tx_pwrctrl_tbl =
- nphy_tpc_5GHz_txgain_rev5;
- }
- } else {
- if (NREV_GE(phyrev, 7)) {
- if (pi->pubpi.
- radiorev == 3) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_epa_2057rev3;
- } else if (pi->pubpi.
- radiorev ==
- 5) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_epa_2057rev5;
- }
-
- } else {
- if (NREV_GE(phyrev, 5)
- && (pi->srom_fem2g.
- extpagain ==
- 3)) {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_HiPwrEPA;
- } else {
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_rev3;
- }
- }
- }
- }
+ tx_pwrctrl_tbl =
+ brcms_phy_get_tx_pwrctrl_tbl(pi);
if (NREV_GE(phyrev, 7)) {
target_gain.ipa[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 16) & 0x7;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 16) & 0x7;
target_gain.pad[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 19) & 0x1f;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 19) & 0x1f;
target_gain.pga[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 24) & 0xf;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 24) & 0xf;
target_gain.txgm[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 28) & 0x7;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 28) & 0x7;
target_gain.txlpf[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 31) & 0x1;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 31) & 0x1;
} else {
target_gain.ipa[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 16) & 0xf;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 16) & 0xf;
target_gain.pad[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 20) & 0xf;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 20) & 0xf;
target_gain.pga[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 24) & 0xf;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 24) & 0xf;
target_gain.txgm[core_no] =
- (tx_pwrctrl_tbl[base_idx[core_no]]
- >> 28) & 0x7;
+ (tx_pwrctrl_tbl
+ [base_idx[core_no]]
+ >> 28) & 0x7;
}
} else {
target_gain.ipa[core_no] =
- (nphy_tpc_txgain[base_idx[core_no]] >> 16) &
- 0x3;
+ (nphy_tpc_txgain[base_idx[core_no]] >>
+ 16) & 0x3;
target_gain.pad[core_no] =
- (nphy_tpc_txgain[base_idx[core_no]] >> 18) &
- 0x3;
+ (nphy_tpc_txgain[base_idx[core_no]] >>
+ 18) & 0x3;
target_gain.pga[core_no] =
- (nphy_tpc_txgain[base_idx[core_no]] >> 20) &
- 0x7;
+ (nphy_tpc_txgain[base_idx[core_no]] >>
+ 20) & 0x7;
target_gain.txgm[core_no] =
- (nphy_tpc_txgain[base_idx[core_no]] >> 23) &
- 0x7;
+ (nphy_tpc_txgain[base_idx[core_no]] >>
+ 23) & 0x7;
}
}
}
@@ -22626,26 +23647,23 @@ wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no,
u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
params->txlpf = target_gain.txlpf[core_no];
- }
+
params->txgm = target_gain.txgm[core_no];
params->pga = target_gain.pga[core_no];
params->pad = target_gain.pad[core_no];
params->ipa = target_gain.ipa[core_no];
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
params->cal_gain =
- ((params->txlpf << 15) | (params->
- txgm << 12) | (params->
- pga << 8) |
- (params->pad << 3) | (params->ipa));
- } else {
+ ((params->txlpf << 15) | (params->txgm << 12) |
+ (params->pga << 8) |
+ (params->pad << 3) | (params->ipa));
+ else
params->cal_gain =
- ((params->txgm << 12) | (params->
- pga << 8) | (params->
- pad << 4) |
- (params->ipa));
- }
+ ((params->txgm << 12) | (params->pga << 8) |
+ (params->pad << 4) | (params->ipa));
+
params->ncorr[0] = 0x79;
params->ncorr[1] = 0x79;
params->ncorr[2] = 0x79;
@@ -22654,9 +23672,8 @@ wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no,
} else {
gain_index = ((target_gain.pad[core_no] << 0) |
- (target_gain.pga[core_no] << 4) | (target_gain.
- txgm[core_no]
- << 8));
+ (target_gain.pga[core_no] << 4) |
+ (target_gain.txgm[core_no] << 8));
idx = -1;
for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) {
@@ -22688,37 +23705,39 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
for (core = 0; core <= 1; core++) {
pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MASTER);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MASTER);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- IQCAL_VCM_HG);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ IQCAL_VCM_HG);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- IQCAL_IDAC);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ IQCAL_IDAC);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TSSI_VCM);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0;
pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MUX);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TX_SSI_MUX);
if (pi->pubpi.radiorev != 5)
pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TSSIA);
+ READ_RADIO_REG3(pi, RADIO_2057, TX,
+ core,
+ TSSIA);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TSSI_MISC1);
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TSSI_MISC1);
if (CHSPEC_IS5G(pi->radio_chanspec)) {
WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
@@ -22734,19 +23753,15 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
if (pi->use_int_tx_iqlo_cal_nphy) {
WRITE_RADIO_REG3(pi, RADIO_2057, TX,
core, TX_SSI_MUX, 0x4);
- if (!
- (pi->
- internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
+ if (!(pi->
+ internal_tx_iqlo_cal_tapoff_intpa_nphy))
WRITE_RADIO_REG3(pi, RADIO_2057,
TX, core,
TSSIA, 0x31);
- } else {
-
+ else
WRITE_RADIO_REG3(pi, RADIO_2057,
TX, core,
TSSIA, 0x21);
- }
}
WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
TSSI_MISC1, 0x00);
@@ -22767,19 +23782,15 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
WRITE_RADIO_REG3(pi, RADIO_2057, TX,
core, TX_SSI_MUX,
0x06);
- if (!
- (pi->
- internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
+ if (!(pi->
+ internal_tx_iqlo_cal_tapoff_intpa_nphy))
WRITE_RADIO_REG3(pi, RADIO_2057,
TX, core,
TSSIG, 0x31);
- } else {
-
+ else
WRITE_RADIO_REG3(pi, RADIO_2057,
TX, core,
TSSIG, 0x21);
- }
}
WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
TSSI_MISC1, 0x00);
@@ -22789,58 +23800,62 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
for (core = 0; core <= 1; core++) {
jtag_core =
- (core ==
- PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+ (core ==
+ PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
- read_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MASTER |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TX_SSI_MASTER |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
- read_radio_reg(pi,
- RADIO_2056_TX_IQCAL_VCM_HG |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_IQCAL_VCM_HG |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
- read_radio_reg(pi,
- RADIO_2056_TX_IQCAL_IDAC |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_IQCAL_IDAC |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
- read_radio_reg(pi,
- RADIO_2056_TX_TSSI_VCM | jtag_core);
+ read_radio_reg(
+ pi,
+ RADIO_2056_TX_TSSI_VCM |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] =
- read_radio_reg(pi,
- RADIO_2056_TX_TX_AMP_DET |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TX_AMP_DET |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
- read_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TX_SSI_MUX |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
- read_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TSSIA | jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
- read_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TSSIG | jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
- read_radio_reg(pi,
- RADIO_2056_TX_TSSI_MISC1 |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TSSI_MISC1 |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] =
- read_radio_reg(pi,
- RADIO_2056_TX_TSSI_MISC2 |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TSSI_MISC2 |
+ jtag_core);
pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] =
- read_radio_reg(pi,
- RADIO_2056_TX_TSSI_MISC3 |
- jtag_core);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TSSI_MISC3 |
+ jtag_core);
if (CHSPEC_IS5G(pi->radio_chanspec)) {
write_radio_reg(pi,
@@ -22860,16 +23875,18 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
jtag_core, 0x00);
if (PHY_IPA(pi)) {
- write_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX
- | jtag_core, 0x4);
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TX_SSI_MUX
+ | jtag_core, 0x4);
write_radio_reg(pi,
RADIO_2056_TX_TSSIA |
jtag_core, 0x1);
} else {
- write_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX
- | jtag_core, 0x00);
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TX_SSI_MUX
+ | jtag_core, 0x00);
write_radio_reg(pi,
RADIO_2056_TX_TSSIA |
jtag_core, 0x2f);
@@ -22909,26 +23926,27 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
if (PHY_IPA(pi)) {
- write_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX
- | jtag_core, 0x06);
- if (NREV_LT(pi->pubpi.phy_rev, 5)) {
-
- write_radio_reg(pi,
- RADIO_2056_TX_TSSIG
- | jtag_core,
- 0x11);
- } else {
-
- write_radio_reg(pi,
- RADIO_2056_TX_TSSIG
- | jtag_core,
- 0x1);
- }
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TX_SSI_MUX
+ | jtag_core, 0x06);
+ if (NREV_LT(pi->pubpi.phy_rev, 5))
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TSSIG
+ | jtag_core,
+ 0x11);
+ else
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TSSIG
+ | jtag_core,
+ 0x1);
} else {
- write_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX
- | jtag_core, 0x00);
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TX_SSI_MUX
+ | jtag_core, 0x00);
write_radio_reg(pi,
RADIO_2056_TX_TSSIG |
jtag_core, 0x20);
@@ -22948,23 +23966,23 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
} else {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54);
pi->tx_rx_cal_radio_saveregs[2] =
- read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29);
pi->tx_rx_cal_radio_saveregs[3] =
- read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54);
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
pi->tx_rx_cal_radio_saveregs[5] =
- read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) ==
0) {
@@ -23025,11 +24043,8 @@ static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi)
if (pi->pubpi.radiorev != 5)
WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
TSSIA,
- pi->
- tx_rx_cal_radio_saveregs[(core
- *
- 11) +
- 6]);
+ pi->tx_rx_cal_radio_saveregs
+ [(core * 11) + 6]);
WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG,
pi->
@@ -23043,9 +24058,8 @@ static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi)
}
} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
for (core = 0; core <= 1; core++) {
- jtag_core =
- (core ==
- PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+ jtag_core = (core == PHY_CORE_0) ?
+ RADIO_2056_TX0 : RADIO_2056_TX1;
write_radio_reg(pi,
RADIO_2056_TX_TX_SSI_MASTER | jtag_core,
@@ -23171,23 +24185,22 @@ static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi)
pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91);
pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92);
- if (!(pi->use_int_tx_iqlo_cal_nphy)) {
-
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_PA,
- 1,
- RADIO_MIMO_CORESEL_CORE1
- |
- RADIO_MIMO_CORESEL_CORE2);
- } else {
-
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_PA,
- 0,
- RADIO_MIMO_CORESEL_CORE1
- |
- RADIO_MIMO_CORESEL_CORE2);
- }
+ if (!(pi->use_int_tx_iqlo_cal_nphy))
+ wlc_phy_rfctrlintc_override_nphy(
+ pi,
+ NPHY_RfctrlIntc_override_PA,
+ 1,
+ RADIO_MIMO_CORESEL_CORE1
+ |
+ RADIO_MIMO_CORESEL_CORE2);
+ else
+ wlc_phy_rfctrlintc_override_nphy(
+ pi,
+ NPHY_RfctrlIntc_override_PA,
+ 0,
+ RADIO_MIMO_CORESEL_CORE1
+ |
+ RADIO_MIMO_CORESEL_CORE2);
wlc_phy_rfctrlintc_override_nphy(pi,
NPHY_RfctrlIntc_override_TRSW,
@@ -23205,12 +24218,13 @@ static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi)
0x29b, (0x1 << 0), (0) << 0);
if (NREV_IS(pi->pubpi.phy_rev, 7)
- || NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
- wlc_phy_read_lpf_bw_ctl_nphy
- (pi, 0), 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- }
+ || NREV_GE(pi->pubpi.phy_rev, 8))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 7),
+ wlc_phy_read_lpf_bw_ctl_nphy
+ (pi,
+ 0), 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
if (pi->use_int_tx_iqlo_cal_nphy
&& !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
@@ -23221,25 +24235,30 @@ static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi)
1 << 4);
if (CHSPEC_IS2G(pi->radio_chanspec)) {
- mod_radio_reg(pi,
- RADIO_2057_PAD2G_TUNE_PUS_CORE0,
- 1, 0);
- mod_radio_reg(pi,
- RADIO_2057_PAD2G_TUNE_PUS_CORE1,
- 1, 0);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+ 1, 0);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+ 1, 0);
} else {
- mod_radio_reg(pi,
- RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
- 1, 0);
- mod_radio_reg(pi,
- RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
- 1, 0);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+ 1, 0);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+ 1, 0);
}
} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 3), 0,
- 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 3), 0,
+ 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
}
}
} else {
@@ -23302,11 +24321,11 @@ static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi)
write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
if (NREV_IS(pi->pubpi.phy_rev, 7)
- || NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
- 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- }
+ || NREV_GE(pi->pubpi.phy_rev, 8))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 7), 0, 0,
+ 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
wlc_phy_resetcca_nphy(pi);
@@ -23315,28 +24334,33 @@ static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi)
if (NREV_IS(pi->pubpi.phy_rev, 7)) {
if (CHSPEC_IS2G(pi->radio_chanspec)) {
- mod_radio_reg(pi,
- RADIO_2057_PAD2G_TUNE_PUS_CORE0,
- 1, 1);
- mod_radio_reg(pi,
- RADIO_2057_PAD2G_TUNE_PUS_CORE1,
- 1, 1);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+ 1, 1);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+ 1, 1);
} else {
- mod_radio_reg(pi,
- RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
- 1, 1);
- mod_radio_reg(pi,
- RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
- 1, 1);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+ 1, 1);
+ mod_radio_reg(
+ pi,
+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+ 1, 1);
}
mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
0);
} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 3), 0,
- 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 3), 0,
+ 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
}
}
} else {
@@ -23356,10 +24380,6 @@ static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi)
}
}
-#define NPHY_CAL_TSSISAMPS 64
-#define NPHY_TEST_TONE_FREQ_40MHz 4000
-#define NPHY_TEST_TONE_FREQ_20MHz 2500
-
void
wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps)
{
@@ -23379,8 +24399,8 @@ wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps)
idle_tssi[1] = (temp <= 31) ? temp : (temp - 64);
tssi_type =
- CHSPEC_IS5G(pi->radio_chanspec) ?
- (u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G;
+ CHSPEC_IS5G(pi->radio_chanspec) ?
+ (u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G;
wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps);
@@ -23390,17 +24410,15 @@ wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps)
pwrindex[0] = idle_tssi[0] - tssival[0] + 64;
pwrindex[1] = idle_tssi[1] - tssival[1] + 64;
- if (pwrindex[0] < 0) {
+ if (pwrindex[0] < 0)
pwrindex[0] = 0;
- } else if (pwrindex[0] > 63) {
+ else if (pwrindex[0] > 63)
pwrindex[0] = 63;
- }
- if (pwrindex[1] < 0) {
+ if (pwrindex[1] < 0)
pwrindex[1] = 0;
- } else if (pwrindex[1] > 63) {
+ else if (pwrindex[1] > 63)
pwrindex[1] = 63;
- }
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1,
(u32) pwrindex[0], 32, &qdBm_pwrbuf[0]);
@@ -23408,326 +24426,1241 @@ wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps)
(u32) pwrindex[1], 32, &qdBm_pwrbuf[1]);
}
-static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi)
+static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core)
{
- u16 txcal_gain[2];
+ int index;
+ u32 bbmult_scale;
+ u16 bbmult;
+ u16 tblentry;
- pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0];
- pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0];
- wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
- wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+ struct nphy_txiqcal_ladder ladder_lo[] = {
+ {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+ {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
+ {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
+ };
- wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
- txcal_gain);
+ struct nphy_txiqcal_ladder ladder_iq[] = {
+ {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+ {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
+ {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
+ };
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40;
- txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40;
- } else {
- txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60;
- txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60;
+ bbmult = (core == PHY_CORE_0) ?
+ ((pi->nphy_txcal_bbmult >> 8) & 0xff) :
+ (pi->nphy_txcal_bbmult & 0xff);
+
+ for (index = 0; index < 18; index++) {
+ bbmult_scale = ladder_lo[index].percent * bbmult;
+ bbmult_scale /= 100;
+
+ tblentry =
+ ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16,
+ &tblentry);
+
+ bbmult_scale = ladder_iq[index].percent * bbmult;
+ bbmult_scale /= 100;
+
+ tblentry =
+ ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env;
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32,
+ 16, &tblentry);
}
+}
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
- txcal_gain);
+static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core)
+{
+ u16 tmp;
+ tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee));
+
+ tmp = (tmp & (0x7f << 8)) >> 8;
+ return (u8) tmp;
}
-static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi)
+static void
+wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0, u8 idx1)
{
- bool save_bbmult = false;
- u8 txcal_index_2057_rev5n7 = 0;
- u8 txcal_index_2057_rev3n4n6 = 10;
+ mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0);
+
+ if (NREV_GT(pi->pubpi.phy_rev, 1))
+ mod_phy_reg(pi, 0x222, (0xff << 0), idx1);
+}
+
+static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi)
+{
+ u16 m0m1;
+
+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
+ return m0m1;
+}
+
+static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1)
+{
+ u16 m0m1 = (u16) ((m0 << 8) | m1);
+
+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1);
+ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1);
+}
+
+static void
+wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi,
+ struct nphy_papd_restore_state *state, u8 core)
+{
+ s32 tone_freq;
+ u8 off_core;
+ u16 mixgain = 0;
+
+ off_core = core ^ 0x1;
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ if (NREV_IS(pi->pubpi.phy_rev, 7)
+ || NREV_GE(pi->pubpi.phy_rev, 8))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 7),
+ wlc_phy_read_lpf_bw_ctl_nphy
+ (pi,
+ 0), 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (pi->pubpi.radiorev == 5)
+ mixgain = (core == 0) ? 0x20 : 0x00;
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ mixgain = 0x00;
+ else if ((pi->pubpi.radiorev <= 4)
+ || (pi->pubpi.radiorev == 6))
+ mixgain = 0x00;
+ } else {
+ if ((pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6))
+ mixgain = 0x50;
+ else if ((pi->pubpi.radiorev == 3)
+ || (pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ mixgain = 0x0;
+ }
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
+ mixgain, (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+ 1, (1 << core), 0);
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+ 0, (1 << off_core), 0);
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+ 0, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+ 0, (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0,
+ (1 << core), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+ state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+ 0xa6 : 0xa7);
+ state->afeoverride[core] =
+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+ state->afectrl[off_core] =
+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6);
+ state->afeoverride[off_core] =
+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f);
+
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+ (0x1 << 2), 0);
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+ 0xa5), (0x1 << 2), (0x1 << 2));
+
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6),
+ (0x1 << 2), (0x1 << 2));
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 :
+ 0x8f), (0x1 << 2), (0x1 << 2));
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ state->pwrup[core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_PWRUP);
+ state->atten[core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_ATTEN);
+ state->pwrup[off_core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_2G_PWRUP);
+ state->atten[off_core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_2G_ATTEN);
+
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_PWRUP, 0xc);
- if (pi->use_int_tx_iqlo_cal_nphy) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
if ((pi->pubpi.radiorev == 3) ||
(pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
+ (pi->pubpi.radiorev == 6))
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_ATTEN, 0xf0);
+ else if (pi->pubpi.radiorev == 5)
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_ATTEN,
+ (core == 0) ? 0xf7 : 0xf2);
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_ATTEN, 0xf0);
- pi->nphy_txcal_pwr_idx[0] =
- txcal_index_2057_rev3n4n6;
- pi->nphy_txcal_pwr_idx[1] =
- txcal_index_2057_rev3n4n6;
- wlc_phy_txpwr_index_nphy(pi, 3,
- txcal_index_2057_rev3n4n6,
- false);
- } else {
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_2G_PWRUP, 0x0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_2G_ATTEN, 0xff);
+ } else {
+ state->pwrup[core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_PWRUP);
+ state->atten[core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_ATTEN);
+ state->pwrup[off_core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_5G_PWRUP);
+ state->atten[off_core] =
+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_5G_ATTEN);
- pi->nphy_txcal_pwr_idx[0] =
- txcal_index_2057_rev5n7;
- pi->nphy_txcal_pwr_idx[1] =
- txcal_index_2057_rev5n7;
- wlc_phy_txpwr_index_nphy(pi, 3,
- txcal_index_2057_rev5n7,
- false);
- }
- save_bbmult = true;
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_PWRUP, 0xc);
- } else if (NREV_LT(pi->pubpi.phy_rev, 5)) {
- wlc_phy_cal_txgainctrl_nphy(pi, 11, false);
- if (pi->sh->hw_phytxchain != 3) {
- pi->nphy_txcal_pwr_idx[1] =
- pi->nphy_txcal_pwr_idx[0];
- wlc_phy_txpwr_index_nphy(pi, 3,
- pi->
- nphy_txcal_pwr_idx[0],
- true);
- save_bbmult = true;
+ if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_ATTEN, 0xf4);
+
+ else
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_ATTEN, 0xf0);
+
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_5G_PWRUP, 0x0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+ TXRXCOUPLE_5G_ATTEN, 0xff);
+ }
+
+ tone_freq = 4000;
+
+ wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (1) << 13);
+
+ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0);
+
+ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (0) << 13);
+
+ } else {
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0);
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0);
+
+ state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+ 0xa6 : 0xa7);
+ state->afeoverride[core] =
+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0);
+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+ 0xa5),
+ (0x1 << 0) |
+ (0x1 << 1) |
+ (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+
+ state->vga_master[core] =
+ READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER);
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b);
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ state->fbmix[core] =
+ READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+ TXFBMIX_G);
+ state->intpa_master[core] =
+ READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAG_MASTER);
+
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G,
+ 0x03);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAG_MASTER, 0x04);
+ } else {
+ state->fbmix[core] =
+ READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+ TXFBMIX_A);
+ state->intpa_master[core] =
+ READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAA_MASTER);
+
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A,
+ 0x03);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAA_MASTER, 0x04);
+
+ }
+
+ tone_freq = 4000;
+
+ wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (1) << 0);
+
+ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (0) << 0);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+ }
+}
+
+static void
+wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi,
+ struct nphy_papd_restore_state *state)
+{
+ u8 core;
+
+ wlc_phy_stopplayback_nphy(pi);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_PWRUP, 0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_2G_ATTEN,
+ state->atten[core]);
+ } else {
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_PWRUP, 0);
+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+ TXRXCOUPLE_5G_ATTEN,
+ state->atten[core]);
}
+ }
- } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
- if (PHY_IPA(pi)) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- wlc_phy_cal_txgainctrl_nphy(pi, 12,
- false);
- } else {
- pi->nphy_txcal_pwr_idx[0] = 80;
- pi->nphy_txcal_pwr_idx[1] = 80;
- wlc_phy_txpwr_index_nphy(pi, 3, 80,
- false);
- save_bbmult = true;
- }
+ if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2),
+ 1, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ else
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 2),
+ 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
+ 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID2);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+ write_phy_reg(pi, (core == PHY_CORE_0) ?
+ 0xa6 : 0xa7, state->afectrl[core]);
+ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+ 0xa5, state->afeoverride[core]);
+ }
+
+ wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+ (state->mm & 0xff));
+
+ if (NREV_IS(pi->pubpi.phy_rev, 7)
+ || NREV_GE(pi->pubpi.phy_rev, 8))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi, (0x1 << 7), 0, 0,
+ 1,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ } else {
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1);
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1);
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1);
+
+ for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER,
+ state->vga_master[core]);
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+ TXFBMIX_G, state->fbmix[core]);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAG_MASTER,
+ state->intpa_master[core]);
} else {
+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+ TXFBMIX_A, state->fbmix[core]);
+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+ INTPAA_MASTER,
+ state->intpa_master[core]);
+ }
- wlc_phy_internal_cal_txgain_nphy(pi);
- save_bbmult = true;
+ write_phy_reg(pi, (core == PHY_CORE_0) ?
+ 0xa6 : 0xa7, state->afectrl[core]);
+ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+ 0xa5, state->afeoverride[core]);
+ }
+
+ wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+ (state->mm & 0xff));
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1);
+ }
+}
+
+static void
+wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start,
+ u32 end)
+{
+ u32 *buf, *src, *dst, sz;
+
+ sz = end - start + 1;
+
+ buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC);
+ if (NULL == buf)
+ return;
+
+ src = buf;
+ dst = buf + NPHY_PAPD_EPS_TBL_SIZE;
+
+ wlc_phy_table_read_nphy(pi,
+ (core ==
+ PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 :
+ NPHY_TBL_ID_EPSILONTBL1),
+ NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src);
+
+ do {
+ u32 phy_a1, phy_a2;
+ s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7;
+
+ phy_a1 = end - min(end, (winsz >> 1));
+ phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1,
+ end + (winsz >> 1));
+ phy_a3 = phy_a2 - phy_a1 + 1;
+ phy_a6 = 0;
+ phy_a7 = 0;
+
+ do {
+ wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4,
+ &phy_a5);
+ phy_a6 += phy_a4;
+ phy_a7 += phy_a5;
+ } while (phy_a2-- != phy_a1);
+
+ phy_a6 /= phy_a3;
+ phy_a7 /= phy_a3;
+ dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff);
+ } while (end-- != start);
+
+ wlc_phy_table_write_nphy(pi,
+ (core ==
+ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 :
+ NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst);
+
+ kfree(buf);
+}
+
+static void
+wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains,
+ enum phy_cal_mode cal_mode, u8 core)
+{
+ u16 phy_a1, phy_a2, phy_a3;
+ u16 phy_a4, phy_a5;
+ bool phy_a6;
+ u8 phy_a7, m[2];
+ u32 phy_a8 = 0;
+ struct nphy_txgains phy_a9;
+
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
+ return;
+
+ phy_a7 = (core == PHY_CORE_0) ? 1 : 0;
+
+ phy_a6 = ((cal_mode == CAL_GCTRL)
+ || (cal_mode == CAL_SOFT)) ? true : false;
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+ phy_a9 = wlc_phy_get_tx_gain_nphy(pi);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ phy_a5 = ((phy_a9.txlpf[core] << 15) |
+ (phy_a9.txgm[core] << 12) |
+ (phy_a9.pga[core] << 8) |
+ (txgains->gains.pad[core] << 3) |
+ (phy_a9.ipa[core]));
+ else
+ phy_a5 = ((phy_a9.txlpf[core] << 15) |
+ (phy_a9.txgm[core] << 12) |
+ (txgains->gains.pga[core] << 8) |
+ (phy_a9.pad[core] << 3) | (phy_a9.ipa[core]));
+
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_txgain,
+ phy_a5, (1 << core), 0);
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if ((pi->pubpi.radiorev <= 4)
+ || (pi->pubpi.radiorev == 6))
+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ?
+ 60 : 79;
+ else
+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ?
+ 45 : 64;
+ } else {
+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107;
+ }
+
+ m[phy_a7] = 0;
+ wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+ phy_a2 = 63;
+
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if ((pi->pubpi.radiorev == 4)
+ || (pi->pubpi.radiorev == 6)) {
+ phy_a1 = 30;
+ phy_a3 = 30;
+ } else {
+ phy_a1 = 25;
+ phy_a3 = 25;
+ }
+ } else {
+ if ((pi->pubpi.radiorev == 5)
+ || (pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8)) {
+ phy_a1 = 25;
+ phy_a3 = 25;
+ } else {
+ phy_a1 = 35;
+ phy_a3 = 35;
}
+ }
- } else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
- if (PHY_IPA(pi)) {
+ if (cal_mode == CAL_GCTRL) {
+ if ((pi->pubpi.radiorev == 5)
+ && (CHSPEC_IS2G(pi->radio_chanspec)))
+ phy_a1 = 55;
+ else if (((pi->pubpi.radiorev == 7) &&
+ (CHSPEC_IS2G(pi->radio_chanspec))) ||
+ ((pi->pubpi.radiorev == 8) &&
+ (CHSPEC_IS2G(pi->radio_chanspec))))
+ phy_a1 = 60;
+ else
+ phy_a1 = 63;
+
+ } else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) {
+
+ phy_a1 = 35;
+ phy_a3 = 35;
+ }
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (1) << 0);
+
+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (0) << 0);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (1) << 13);
+
+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (0) << 13);
+
+ write_phy_reg(pi, 0x2a1, 0x80);
+ write_phy_reg(pi, 0x2a2, 0x100);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 4), (11) << 4);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 8), (11) << 8);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 0), (0x3) << 0);
+
+ write_phy_reg(pi, 0x2e5, 0x20);
+
+ mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+ mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+ mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+ 1, ((core == 0) ? 1 : 2), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+ 0, ((core == 0) ? 2 : 1), 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+ write_phy_reg(pi, 0x2be, 1);
+ SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+ 0, 0x3, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+ wlc_phy_table_write_nphy(pi,
+ (core ==
+ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+ : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+ 32, &phy_a8);
+
+ if (cal_mode != CAL_GCTRL) {
+ if (CHSPEC_IS5G(pi->radio_chanspec))
+ wlc_phy_a1_nphy(pi, core, 5, 0, 35);
+ }
+
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_txgain,
+ phy_a5, (1 << core), 1);
+
+ } else {
+
+ if (txgains) {
+ if (txgains->useindex) {
+ phy_a4 = 15 - ((txgains->index) >> 3);
if (CHSPEC_IS2G(pi->radio_chanspec)) {
- wlc_phy_cal_txgainctrl_nphy(pi, 12,
- false);
+ if (NREV_GE(pi->pubpi.phy_rev, 6))
+ phy_a5 = 0x00f7 | (phy_a4 << 8);
+
+ else
+ if (NREV_IS(pi->pubpi.phy_rev, 5))
+ phy_a5 = 0x10f7 | (phy_a4 << 8);
+ else
+ phy_a5 = 0x50f7 | (phy_a4 << 8);
} else {
- wlc_phy_cal_txgainctrl_nphy(pi, 14,
- false);
+ phy_a5 = 0x70f7 | (phy_a4 << 8);
}
+ wlc_phy_rfctrl_override_nphy(pi,
+ (0x1 << 13),
+ phy_a5,
+ (1 << core), 0);
} else {
-
- wlc_phy_internal_cal_txgain_nphy(pi);
- save_bbmult = true;
+ wlc_phy_rfctrl_override_nphy(pi,
+ (0x1 << 13),
+ 0x5bf7,
+ (1 << core), 0);
}
}
- } else {
- wlc_phy_cal_txgainctrl_nphy(pi, 10, false);
- }
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 45 : 64;
+ else
+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107;
- if (save_bbmult) {
- wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
- &pi->nphy_txcal_bbmult);
+ m[phy_a7] = 0;
+ wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+ phy_a2 = 63;
+
+ if (cal_mode == CAL_FULL) {
+ phy_a1 = 25;
+ phy_a3 = 25;
+ } else if (cal_mode == CAL_SOFT) {
+ phy_a1 = 25;
+ phy_a3 = 25;
+ } else if (cal_mode == CAL_GCTRL) {
+ phy_a1 = 63;
+ phy_a3 = 25;
+ } else {
+
+ phy_a1 = 25;
+ phy_a3 = 25;
+ }
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (1) << 0);
+
+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (0) << 0);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (1) << 13);
+
+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (0) << 13);
+
+ write_phy_reg(pi, 0x2a1, 0x20);
+ write_phy_reg(pi, 0x2a2, 0x60);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0xf << 4), (9) << 4);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0xf << 8), (9) << 8);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0xf << 0), (0x2) << 0);
+
+ write_phy_reg(pi, 0x2e5, 0x20);
+ } else {
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 11), (1) << 11);
+
+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 11), (0) << 11);
+
+ write_phy_reg(pi, 0x2a1, 0x80);
+ write_phy_reg(pi, 0x2a2, 0x600);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 4), (0) << 4);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 8), (0) << 8);
+
+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x7 << 0), (0x3) << 0);
+
+ mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8);
+
+ }
+
+ mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+ mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+ mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0);
+
+ write_phy_reg(pi, 0x2be, 1);
+ SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+
+ wlc_phy_table_write_nphy(pi,
+ (core ==
+ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+ : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+ 32, &phy_a8);
+
+ if (cal_mode != CAL_GCTRL)
+ wlc_phy_a1_nphy(pi, core, 5, 0, 40);
}
}
-void
-wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower,
- bool debug)
+static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core)
{
- int gainctrl_loopidx;
- uint core;
- u16 m0m1, curr_m0m1;
- s32 delta_power;
- s32 txpwrindex;
- s32 qdBm_power[2];
- u16 orig_BBConfig;
- u16 phy_saveregs[4];
- u32 freq_test;
- u16 ampl_test = 250;
- uint stepsize;
- bool phyhang_avoid_state = false;
+ int phy_a1;
+ int phy_a2;
+ bool phy_a3;
+ struct nphy_ipa_txcalgains phy_a4;
+ bool phy_a5 = false;
+ bool phy_a6 = true;
+ s32 phy_a7, phy_a8;
+ u32 phy_a9;
+ int phy_a10;
+ bool phy_a11 = false;
+ int phy_a12;
+ u8 phy_a13 = 0;
+ u8 phy_a14;
+ u8 *phy_a15 = NULL;
+
+ phy_a4.useindex = true;
+ phy_a12 = start_gain;
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- stepsize = 2;
- } else {
+ phy_a2 = 20;
+ phy_a1 = 1;
- stepsize = 1;
- }
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (pi->pubpi.radiorev == 5) {
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- freq_test = 5000;
- } else {
- freq_test = 2500;
- }
+ phy_a15 = pad_gain_codes_used_2057rev5;
+ phy_a13 =
+ sizeof(pad_gain_codes_used_2057rev5) /
+ sizeof(pad_gain_codes_used_2057rev5
+ [0]) - 1;
- wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
- wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+ } else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8)) {
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
+ phy_a15 = pad_gain_codes_used_2057rev7;
+ phy_a13 =
+ sizeof(pad_gain_codes_used_2057rev7) /
+ sizeof(pad_gain_codes_used_2057rev7
+ [0]) - 1;
- phyhang_avoid_state = pi->phyhang_avoid;
- pi->phyhang_avoid = false;
+ } else {
- phy_saveregs[0] = read_phy_reg(pi, 0x91);
- phy_saveregs[1] = read_phy_reg(pi, 0x92);
- phy_saveregs[2] = read_phy_reg(pi, 0xe7);
- phy_saveregs[3] = read_phy_reg(pi, 0xec);
- wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1,
- RADIO_MIMO_CORESEL_CORE1 |
- RADIO_MIMO_CORESEL_CORE2);
+ phy_a15 = pad_all_gain_codes_2057;
+ phy_a13 = sizeof(pad_all_gain_codes_2057) /
+ sizeof(pad_all_gain_codes_2057[0]) -
+ 1;
+ }
- if (!debug) {
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_TRSW,
- 0x2, RADIO_MIMO_CORESEL_CORE1);
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_TRSW,
- 0x8, RADIO_MIMO_CORESEL_CORE2);
- } else {
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_TRSW,
- 0x1, RADIO_MIMO_CORESEL_CORE1);
- wlc_phy_rfctrlintc_override_nphy(pi,
- NPHY_RfctrlIntc_override_TRSW,
- 0x7, RADIO_MIMO_CORESEL_CORE2);
- }
+ } else {
- orig_BBConfig = read_phy_reg(pi, 0x01);
- mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+ phy_a15 = pga_all_gain_codes_2057;
+ phy_a13 = sizeof(pga_all_gain_codes_2057) /
+ sizeof(pga_all_gain_codes_2057[0]) - 1;
+ }
- wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+ phy_a14 = 0;
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core];
+ for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ phy_a4.gains.pad[core] =
+ (u16) phy_a15[phy_a12];
+ else
+ phy_a4.gains.pga[core] =
+ (u16) phy_a15[phy_a12];
- for (gainctrl_loopidx = 0; gainctrl_loopidx < 2;
- gainctrl_loopidx++) {
- wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
- false);
+ wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
- if (core == PHY_CORE_0) {
- curr_m0m1 = m0m1 & 0xff00;
- } else {
- curr_m0m1 = m0m1 & 0x00ff;
+ wlc_phy_table_read_nphy(pi,
+ (core ==
+ PHY_CORE_0 ?
+ NPHY_TBL_ID_EPSILONTBL0 :
+ NPHY_TBL_ID_EPSILONTBL1), 1,
+ 63, 32, &phy_a9);
+
+ wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
+
+ phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
+ (phy_a8 == 4095) || (phy_a8 == -4096));
+
+ if (!phy_a6 && (phy_a3 != phy_a5)) {
+ if (!phy_a3)
+ phy_a12 -= (u8) phy_a1;
+
+ phy_a11 = true;
+ break;
}
- wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1);
- wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1);
+ if (phy_a3)
+ phy_a12 += (u8) phy_a1;
+ else
+ phy_a12 -= (u8) phy_a1;
- udelay(50);
+ if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) {
+ if (phy_a12 < phy_a14)
+ phy_a12 = phy_a14;
+ else
+ phy_a12 = phy_a13;
- wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
- NPHY_CAL_TSSISAMPS);
+ phy_a11 = true;
+ break;
+ }
- pi->nphy_bb_mult_save = 0;
- wlc_phy_stopplayback_nphy(pi);
+ phy_a6 = false;
+ phy_a5 = phy_a3;
+ }
- delta_power = (dBm_targetpower * 4) - qdBm_power[core];
+ } else {
+ phy_a2 = 10;
+ phy_a1 = 8;
+ for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+ phy_a4.index = (u8) phy_a12;
+ wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
- txpwrindex -= stepsize * delta_power;
- if (txpwrindex < 0) {
- txpwrindex = 0;
- } else if (txpwrindex > 127) {
- txpwrindex = 127;
+ wlc_phy_table_read_nphy(pi,
+ (core ==
+ PHY_CORE_0 ?
+ NPHY_TBL_ID_EPSILONTBL0 :
+ NPHY_TBL_ID_EPSILONTBL1), 1,
+ 63, 32, &phy_a9);
+
+ wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
+
+ phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
+ (phy_a8 == 4095) || (phy_a8 == -4096));
+
+ if (!phy_a6 && (phy_a3 != phy_a5)) {
+ if (!phy_a3)
+ phy_a12 -= (u8) phy_a1;
+
+ phy_a11 = true;
+ break;
}
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (NREV_IS(pi->pubpi.phy_rev, 4) &&
- (pi->srom_fem5g.extpagain == 3)) {
- if (txpwrindex < 30) {
- txpwrindex = 30;
- }
- }
- } else {
- if (NREV_GE(pi->pubpi.phy_rev, 5) &&
- (pi->srom_fem2g.extpagain == 3)) {
- if (txpwrindex < 50) {
- txpwrindex = 50;
- }
- }
+ if (phy_a3)
+ phy_a12 += (u8) phy_a1;
+ else
+ phy_a12 -= (u8) phy_a1;
+
+ if ((phy_a12 < 0) || (phy_a12 > 127)) {
+ if (phy_a12 < 0)
+ phy_a12 = 0;
+ else
+ phy_a12 = 127;
+
+ phy_a11 = true;
+ break;
}
- wlc_phy_txpwr_index_nphy(pi, (1 << core),
- (u8) txpwrindex, true);
+ phy_a6 = false;
+ phy_a5 = phy_a3;
}
- pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex;
+ }
- if (debug) {
- u16 radio_gain;
- u16 dbg_m0m1;
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ return (u8) phy_a15[phy_a12];
+ else
+ return (u8) phy_a12;
- wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+}
- wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
- false);
+static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal)
+{
+ struct nphy_ipa_txcalgains phy_b1[2];
+ struct nphy_papd_restore_state phy_b2;
+ bool phy_b3;
+ u8 phy_b4;
+ u8 phy_b5;
+ s16 phy_b6, phy_b7, phy_b8;
+ u16 phy_b9;
+ s16 phy_b10, phy_b11, phy_b12;
- wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
- wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1);
+ phy_b11 = 0;
+ phy_b12 = 0;
+ phy_b7 = 0;
+ phy_b8 = 0;
+ phy_b6 = 0;
- udelay(100);
+ if (pi->nphy_papd_skip == 1)
+ return;
- wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
- NPHY_CAL_TSSISAMPS);
+ phy_b3 = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+ if (!phy_b3)
+ wlapi_suspend_mac_and_wait(pi->sh->physhim);
- wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16,
- &radio_gain);
+ wlc_phy_stay_in_carriersearch_nphy(pi, true);
- mdelay(4000);
- pi->nphy_bb_mult_save = 0;
- wlc_phy_stopplayback_nphy(pi);
+ pi->nphy_force_papd_cal = false;
+
+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++)
+ pi->nphy_papd_tx_gain_at_last_cal[phy_b5] =
+ wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5);
+
+ pi->nphy_papd_last_cal = pi->sh->now;
+ pi->nphy_papd_recal_counter++;
+
+ phy_b4 = pi->nphy_txpwrctrl;
+ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32,
+ nphy_papd_scaltbl);
+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32,
+ nphy_papd_scaltbl);
+
+ phy_b9 = read_phy_reg(pi, 0x01);
+ mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+ s32 i, val = 0;
+ for (i = 0; i < 64; i++)
+ wlc_phy_table_write_nphy(pi,
+ ((phy_b5 ==
+ PHY_CORE_0) ?
+ NPHY_TBL_ID_EPSILONTBL0 :
+ NPHY_TBL_ID_EPSILONTBL1), 1,
+ i, 32, &val);
+ }
+
+ wlc_phy_ipa_restore_tx_digi_filts_nphy(pi);
+
+ phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi);
+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+ wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if ((pi->pubpi.radiorev == 3)
+ || (pi->pubpi.radiorev == 4)
+ || (pi->pubpi.radiorev == 6)) {
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ 23;
+ } else if (pi->pubpi.radiorev == 5) {
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ 0;
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ wlc_phy_a3_nphy(
+ pi,
+ pi->
+ nphy_papd_cal_gain_index
+ [phy_b5],
+ phy_b5);
+
+ } else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8)) {
+
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ 0;
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ wlc_phy_a3_nphy(
+ pi,
+ pi->
+ nphy_papd_cal_gain_index
+ [phy_b5],
+ phy_b5);
+
+ }
+
+ phy_b1[phy_b5].gains.pad[phy_b5] =
+ pi->nphy_papd_cal_gain_index[phy_b5];
+
+ } else {
+ pi->nphy_papd_cal_gain_index[phy_b5] = 0;
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ wlc_phy_a3_nphy(
+ pi,
+ pi->
+ nphy_papd_cal_gain_index
+ [phy_b5], phy_b5);
+ phy_b1[phy_b5].gains.pga[phy_b5] =
+ pi->nphy_papd_cal_gain_index[phy_b5];
+ }
+ } else {
+ phy_b1[phy_b5].useindex = true;
+ phy_b1[phy_b5].index = 16;
+ phy_b1[phy_b5].index =
+ wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index,
+ phy_b5);
+
+ pi->nphy_papd_cal_gain_index[phy_b5] =
+ 15 - ((phy_b1[phy_b5].index) >> 3);
}
+
+ switch (pi->nphy_papd_cal_type) {
+ case 0:
+ wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5);
+ break;
+ case 1:
+ wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5);
+ break;
+ }
+
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
}
- wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true);
- wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true);
+ if (NREV_LT(pi->pubpi.phy_rev, 7))
+ wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
- wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult);
+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+ int eps_offset = 0;
- write_phy_reg(pi, 0x01, orig_BBConfig);
+ if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ if (pi->pubpi.radiorev == 3)
+ eps_offset = -2;
+ else if (pi->pubpi.radiorev == 5)
+ eps_offset = 3;
+ else
+ eps_offset = -1;
+ } else {
+ eps_offset = 2;
+ }
- write_phy_reg(pi, 0x91, phy_saveregs[0]);
- write_phy_reg(pi, 0x92, phy_saveregs[1]);
- write_phy_reg(pi, 0xe7, phy_saveregs[2]);
- write_phy_reg(pi, 0xec, phy_saveregs[3]);
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5];
+ phy_b10 = 0;
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6)) {
+ phy_b12 = -(
+ nphy_papd_padgain_dlt_2g_2057rev3n4
+ [phy_b8] + 1) / 2;
+ phy_b10 = -1;
+ } else if (pi->pubpi.radiorev == 5) {
+ phy_b12 = -(
+ nphy_papd_padgain_dlt_2g_2057rev5
+ [phy_b8] + 1) / 2;
+ } else if ((pi->pubpi.radiorev == 7) ||
+ (pi->pubpi.radiorev == 8)) {
+ phy_b12 = -(
+ nphy_papd_padgain_dlt_2g_2057rev7
+ [phy_b8] + 1) / 2;
+ }
+ } else {
+ phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5];
+ if ((pi->pubpi.radiorev == 3) ||
+ (pi->pubpi.radiorev == 4) ||
+ (pi->pubpi.radiorev == 6))
+ phy_b11 =
+ -(nphy_papd_pgagain_dlt_5g_2057
+ [phy_b7]
+ + 1) / 2;
+ else if ((pi->pubpi.radiorev == 7)
+ || (pi->pubpi.radiorev == 8))
+ phy_b11 = -(
+ nphy_papd_pgagain_dlt_5g_2057rev7
+ [phy_b7] + 1) / 2;
- pi->phyhang_avoid = phyhang_avoid_state;
+ phy_b10 = -9;
+ }
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
+ if (CHSPEC_IS2G(pi->radio_chanspec))
+ phy_b6 =
+ -60 + 27 + eps_offset + phy_b12 +
+ phy_b10;
+ else
+ phy_b6 =
+ -60 + 27 + eps_offset + phy_b11 +
+ phy_b10;
-static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core)
-{
- int index;
- u32 bbmult_scale;
- u16 bbmult;
- u16 tblentry;
+ mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
+ 0x29c, (0x1ff << 7), (phy_b6) << 7);
- struct nphy_txiqcal_ladder ladder_lo[] = {
- {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
- {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
- {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
- };
+ pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
+ } else {
+ if (NREV_LT(pi->pubpi.phy_rev, 5))
+ eps_offset = 4;
+ else
+ eps_offset = 2;
- struct nphy_txiqcal_ladder ladder_iq[] = {
- {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
- {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
- {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
- };
+ phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3);
- bbmult = (core == PHY_CORE_0) ?
- ((pi->nphy_txcal_bbmult >> 8) & 0xff) : (pi->
- nphy_txcal_bbmult & 0xff);
+ if (CHSPEC_IS2G(pi->radio_chanspec)) {
+ phy_b11 =
+ -(nphy_papd_pga_gain_delta_ipa_2g[
+ phy_b7] +
+ 1) / 2;
+ phy_b10 = 0;
+ } else {
+ phy_b11 =
+ -(nphy_papd_pga_gain_delta_ipa_5g[
+ phy_b7] +
+ 1) / 2;
+ phy_b10 = -9;
+ }
- for (index = 0; index < 18; index++) {
- bbmult_scale = ladder_lo[index].percent * bbmult;
- bbmult_scale /= 100;
+ phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10;
- tblentry =
- ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16,
- &tblentry);
+ mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
+ 0x29c, (0x1ff << 7), (phy_b6) << 7);
- bbmult_scale = ladder_iq[index].percent * bbmult;
- bbmult_scale /= 100;
+ pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
+ }
+ }
+
+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+ if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (0) << 13);
+
+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 13), (0) << 13);
+
+ } else {
+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 11), (0) << 11);
+
+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
+ 0x2a4, (0x1 << 11), (0) << 11);
- tblentry =
- ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env;
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32,
- 16, &tblentry);
}
+ pi->nphy_papdcomp = NPHY_PAPD_COMP_ON;
+
+ write_phy_reg(pi, 0x01, phy_b9);
+
+ wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+
+ wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4);
+ if (phy_b4 == PHY_TPC_HW_OFF) {
+ wlc_phy_txpwr_index_nphy(pi, (1 << 0),
+ (s8) (pi->nphy_txpwrindex[0].
+ index_internal), false);
+ wlc_phy_txpwr_index_nphy(pi, (1 << 1),
+ (s8) (pi->nphy_txpwrindex[1].
+ index_internal), false);
+ }
+
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+ if (!phy_b3)
+ wlapi_enable_mac(pi->sh->physhim);
}
void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
@@ -23738,11 +25671,6 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
bool restore_tx_gain = false;
bool mphase;
- if (NORADIO_ENAB(pi->pubpi)) {
- wlc_phy_cal_perical_mphase_reset(pi);
- return;
- }
-
if (PHY_MUTED(pi))
return;
@@ -23751,19 +25679,18 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
else if (caltype == PHY_PERICAL_PARTIAL)
fullcal = false;
- if (pi->cal_type_override != PHY_PERICAL_AUTO) {
+ if (pi->cal_type_override != PHY_PERICAL_AUTO)
fullcal =
- (pi->cal_type_override == PHY_PERICAL_FULL) ? true : false;
- }
+ (pi->cal_type_override ==
+ PHY_PERICAL_FULL) ? true : false;
if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) {
if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec)
wlc_phy_cal_perical_mphase_restart(pi);
}
- if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) {
+ if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL))
wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
- }
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@@ -23772,9 +25699,9 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) ||
(pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) {
pi->nphy_cal_orig_pwr_idx[0] =
- (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f);
+ (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f);
pi->nphy_cal_orig_pwr_idx[1] =
- (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f);
+ (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f);
if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) {
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2,
@@ -23803,7 +25730,8 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
target_gain = pi->nphy_cal_target_gain;
}
if (0 ==
- wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, mphase)) {
+ wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal,
+ mphase)) {
if (PHY_IPA(pi))
wlc_phy_a4(pi, true);
@@ -23815,13 +25743,9 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
wlc_phyreg_enter((struct brcms_phy_pub *) pi);
if (0 == wlc_phy_cal_rxiq_nphy(pi, target_gain,
- (pi->
- first_cal_after_assoc
- || (pi->
- cal_type_override
- ==
- PHY_PERICAL_FULL))
- ? 2 : 0, false)) {
+ (pi->first_cal_after_assoc ||
+ (pi->cal_type_override ==
+ PHY_PERICAL_FULL)) ? 2 : 0, false)) {
wlc_phy_savecal_nphy(pi);
wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
@@ -23829,9 +25753,8 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
pi->nphy_perical_last = pi->sh->now;
}
}
- if (caltype != PHY_PERICAL_AUTO) {
+ if (caltype != PHY_PERICAL_AUTO)
wlc_phy_rssi_cal_nphy(pi);
- }
if (pi->first_cal_after_assoc
|| (pi->cal_type_override == PHY_PERICAL_FULL)) {
@@ -23840,18 +25763,17 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
}
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_radio205x_vcocal_nphy(pi);
- }
} else {
switch (pi->mphase_cal_phase_id) {
case MPHASE_CAL_STATE_INIT:
pi->nphy_perical_last = pi->sh->now;
pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_precal_txgain_nphy(pi);
- }
+
pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
pi->mphase_cal_phase_id++;
break;
@@ -23866,8 +25788,8 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
pi->nphy_rxcal_active = true;
if (wlc_phy_cal_txiqlo_nphy
- (pi, pi->nphy_cal_target_gain, fullcal,
- true) != 0) {
+ (pi, pi->nphy_cal_target_gain, fullcal,
+ true) != 0) {
wlc_phy_cal_perical_mphase_reset(pi);
break;
@@ -23875,20 +25797,19 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
if (NREV_LE(pi->pubpi.phy_rev, 2) &&
(pi->mphase_cal_phase_id ==
- MPHASE_CAL_STATE_TXPHASE4)) {
+ MPHASE_CAL_STATE_TXPHASE4))
pi->mphase_cal_phase_id += 2;
- } else {
+ else
pi->mphase_cal_phase_id++;
- }
break;
case MPHASE_CAL_STATE_PAPDCAL:
if ((pi->radar_percal_mask & 0x2) != 0)
pi->nphy_rxcal_active = true;
- if (PHY_IPA(pi)) {
+ if (PHY_IPA(pi))
wlc_phy_a4(pi, true);
- }
+
pi->mphase_cal_phase_id++;
break;
@@ -23899,9 +25820,8 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
(pi->first_cal_after_assoc ||
(pi->cal_type_override ==
PHY_PERICAL_FULL)) ? 2 : 0,
- false) == 0) {
+ false) == 0)
wlc_phy_savecal_nphy(pi);
- }
pi->mphase_cal_phase_id++;
break;
@@ -23912,16 +25832,15 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
wlc_phy_rssi_cal_nphy(pi);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_radio205x_vcocal_nphy(pi);
- }
+
restore_tx_gain = true;
- if (pi->first_cal_after_assoc) {
+ if (pi->first_cal_after_assoc)
pi->mphase_cal_phase_id++;
- } else {
+ else
wlc_phy_cal_perical_mphase_reset(pi);
- }
break;
@@ -23962,15 +25881,15 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
} else {
wlc_phy_txpwr_index_nphy(pi, (1 << 0),
(s8) (pi->
- nphy_txpwrindex
- [0].
- index_internal),
+ nphy_txpwrindex
+ [0].
+ index_internal),
false);
wlc_phy_txpwr_index_nphy(pi, (1 << 1),
(s8) (pi->
- nphy_txpwrindex
- [1].
- index_internal),
+ nphy_txpwrindex
+ [1].
+ index_internal),
false);
}
}
@@ -24007,35 +25926,35 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901,
- 0x1902,
+ 0x1902,
0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607,
- 0x6407
+ 0x6407
};
u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400,
- 0x3200,
+ 0x3200,
0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406,
- 0x6407
+ 0x6407
};
u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201,
- 0x1202,
+ 0x1202,
0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207,
- 0x4707
+ 0x4707
};
u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900,
- 0x2300,
+ 0x2300,
0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706,
- 0x4707
+ 0x4707
};
u16 tbl_tx_iqlo_cal_startcoefs[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000
+ 0x0000
};
u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
@@ -24071,11 +25990,10 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
pi->phyhang_avoid = false;
}
- if (CHSPEC_IS40(pi->radio_chanspec)) {
+ if (CHSPEC_IS40(pi->radio_chanspec))
phy_bw = 40;
- } else {
+ else
phy_bw = 20;
- }
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
@@ -24117,11 +26035,10 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
16, tbl_ptr);
}
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
write_phy_reg(pi, 0xc2, 0x8ad9);
- } else {
+ else
write_phy_reg(pi, 0xc2, 0x8aa9);
- }
max_val = 250;
tone_freq = (phy_bw == 20) ? 2500 : 5000;
@@ -24131,7 +26048,8 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
bcmerror = 0;
} else {
bcmerror =
- wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, false);
+ wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0,
+ false);
}
if (bcmerror == 0) {
@@ -24139,19 +26057,15 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
tbl_ptr = pi->mphase_txcal_bestcoeffs;
tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
tbl_len -= 2;
- }
} else {
if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) {
tbl_ptr = pi->nphy_txiqlocal_bestc;
tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
tbl_len -= 2;
- }
} else {
fullcal = true;
@@ -24159,14 +26073,12 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
tbl_ptr =
tbl_tx_iqlo_cal_startcoefs_nphyrev3;
- tbl_len =
- ARRAY_SIZE
- (tbl_tx_iqlo_cal_startcoefs_nphyrev3);
+ tbl_len = ARRAY_SIZE(
+ tbl_tx_iqlo_cal_startcoefs_nphyrev3);
} else {
tbl_ptr = tbl_tx_iqlo_cal_startcoefs;
- tbl_len =
- ARRAY_SIZE
- (tbl_tx_iqlo_cal_startcoefs);
+ tbl_len = ARRAY_SIZE(
+ tbl_tx_iqlo_cal_startcoefs);
}
}
}
@@ -24175,21 +26087,22 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
if (fullcal) {
max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
- ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) :
- ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal);
+ ARRAY_SIZE(
+ tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) :
+ ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal);
} else {
max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
- ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal_nphyrev3) :
- ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal);
+ ARRAY_SIZE(
+ tbl_tx_iqlo_cal_cmds_recal_nphyrev3) :
+ ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal);
}
if (mphase) {
cal_cnt = pi->mphase_txcal_cmdidx;
- if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) {
+ if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds)
num_cals = cal_cnt + pi->mphase_txcal_numcmds;
- } else {
+ else
num_cals = max_cal_cmds;
- }
} else {
cal_cnt = 0;
num_cals = max_cal_cmds;
@@ -24199,13 +26112,14 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
if (fullcal) {
cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
- tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
- [cal_cnt] :
- tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt];
+ tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
+ [cal_cnt] :
+ tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt];
} else {
cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
- tbl_tx_iqlo_cal_cmds_recal_nphyrev3[cal_cnt]
- : tbl_tx_iqlo_cal_cmds_recal[cal_cnt];
+ tbl_tx_iqlo_cal_cmds_recal_nphyrev3[
+ cal_cnt]
+ : tbl_tx_iqlo_cal_cmds_recal[cal_cnt];
}
core_no = ((cal_cmd & 0x3000) >> 12);
@@ -24216,15 +26130,16 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
PHY_IPA(pi)
&& (CHSPEC_IS2G(pi->radio_chanspec)))) {
if (!ladder_updated[core_no]) {
- wlc_phy_update_txcal_ladder_nphy(pi,
- core_no);
+ wlc_phy_update_txcal_ladder_nphy(
+ pi,
+ core_no);
ladder_updated[core_no] = true;
}
}
val =
- (cal_params[core_no].
- ncorr[cal_type] << 8) | NPHY_N_GCTL;
+ (cal_params[core_no].
+ ncorr[cal_type] << 8) | NPHY_N_GCTL;
write_phy_reg(pi, 0xc1, val);
if ((cal_type == 1) || (cal_type == 3)
@@ -24272,8 +26187,8 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
}
mphase_cal_lastphase =
- (NREV_LE(pi->pubpi.phy_rev, 2)) ?
- MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5;
+ (NREV_LE(pi->pubpi.phy_rev, 2)) ?
+ MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5;
if (!mphase
|| (pi->mphase_cal_phase_id == mphase_cal_lastphase)) {
@@ -24303,10 +26218,9 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
16, tbl_buf);
tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
tbl_len -= 2;
- }
+
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
tbl_len, 96, 16,
pi->nphy_txiqlocal_bestc);
@@ -24315,10 +26229,9 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
} else {
tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_LT(pi->pubpi.phy_rev, 3))
tbl_len -= 2;
- }
+
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
tbl_len, 96, 16,
pi->mphase_txcal_bestcoeffs);
@@ -24343,9 +26256,8 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
wlc_phy_tx_iq_war_nphy(pi);
}
- if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 4))
pi->phyhang_avoid = phyhang_avoid_state;
- }
wlc_phy_stay_in_carriersearch_nphy(pi, false);
@@ -24387,18 +26299,6 @@ static void wlc_phy_reapply_txcal_coeffs_nphy(struct brcms_phy *pi)
}
}
-static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi)
-{
- struct nphy_iq_comp tx_comp;
-
- wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, (void *)&tx_comp);
-
- wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0);
- wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0);
- wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1);
- wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1);
-}
-
void
wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write,
struct nphy_iq_comp *pcomp)
@@ -24438,14 +26338,17 @@ wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est,
if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) {
for (core = 0; core < pi->pubpi.phy_corenum; core++) {
est[core].i_pwr =
- (read_phy_reg(pi, NPHY_IqestipwrAccHi(core)) << 16)
- | read_phy_reg(pi, NPHY_IqestipwrAccLo(core));
+ (read_phy_reg(pi,
+ NPHY_IqestipwrAccHi(core)) << 16)
+ | read_phy_reg(pi, NPHY_IqestipwrAccLo(core));
est[core].q_pwr =
- (read_phy_reg(pi, NPHY_IqestqpwrAccHi(core)) << 16)
- | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core));
+ (read_phy_reg(pi,
+ NPHY_IqestqpwrAccHi(core)) << 16)
+ | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core));
est[core].iq_prod =
- (read_phy_reg(pi, NPHY_IqestIqAccHi(core)) << 16) |
- read_phy_reg(pi, NPHY_IqestIqAccLo(core));
+ (read_phy_reg(pi,
+ NPHY_IqestIqAccHi(core)) << 16) |
+ read_phy_reg(pi, NPHY_IqestIqAccLo(core));
}
}
}
@@ -24470,7 +26373,7 @@ static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask)
new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0;
wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
- cal_try:
+cal_try:
wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0);
new_comp = old_comp;
@@ -24561,7 +26464,7 @@ static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask)
if (bcmerror != 0) {
printk(KERN_DEBUG "%s: Failed, cnt = %d\n", __func__,
- cal_retry);
+ cal_retry);
if (cal_retry < CAL_RETRY_CNT) {
cal_retry++;
@@ -24584,121 +26487,125 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core)
if (rx_core == PHY_CORE_0) {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP);
+ read_radio_reg(pi,
+ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN);
+ read_radio_reg(pi,
+ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN);
write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
- 0x3);
+ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+ 0x3);
write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
- 0xaf);
+ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+ 0xaf);
} else {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP);
+ read_radio_reg(pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN);
-
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
- 0x3);
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
- 0x7f);
+ read_radio_reg(pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN);
+
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+ 0x3);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+ 0x7f);
}
} else {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP);
+ read_radio_reg(pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN);
-
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
- 0x3);
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
- 0xaf);
+ read_radio_reg(pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN);
+
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+ 0x3);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+ 0xaf);
} else {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP);
+ read_radio_reg(pi,
+ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN);
+ read_radio_reg(pi,
+ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN);
write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
- 0x3);
+ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+ 0x3);
write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
- 0x7f);
+ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+ 0x7f);
}
}
} else {
if (rx_core == PHY_CORE_0) {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2056_TX_RXIQCAL_TXMUX |
- RADIO_2056_TX1);
+ read_radio_reg(pi,
+ RADIO_2056_TX_RXIQCAL_TXMUX |
+ RADIO_2056_TX1);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2056_RX_RXIQCAL_RXMUX |
- RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RXIQCAL_RXMUX |
+ RADIO_2056_RX0);
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[2] =
- read_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RXSPARE2 |
+ RADIO_2056_RX0);
pi->tx_rx_cal_radio_saveregs[3] =
- read_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX1);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TXSPARE2 |
+ RADIO_2056_TX1);
}
if (CHSPEC_IS5G(pi->radio_chanspec)) {
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_LNAA_MASTER
+ | RADIO_2056_RX0);
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX0, 0x40);
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_MASTER
+ | RADIO_2056_RX0, 0x40);
write_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX1, bias_a);
+ RADIO_2056_TX_TXSPARE2 |
+ RADIO_2056_TX1, bias_a);
write_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX0, bias_a);
+ RADIO_2056_RX_RXSPARE2 |
+ RADIO_2056_RX0, bias_a);
} else {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAA_TUNE
- | RADIO_2056_RX0);
+ read_radio_reg(pi,
+ RADIO_2056_RX_LNAA_TUNE
+ | RADIO_2056_RX0);
offtune_val =
- (pi->
- tx_rx_cal_radio_saveregs[2] & 0xF0)
- >> 8;
+ (pi->tx_rx_cal_radio_saveregs
+ [2] & 0xF0) >> 8;
offtune_val =
- (offtune_val <= 0x7) ? 0xF : 0;
+ (offtune_val <= 0x7) ? 0xF : 0;
mod_radio_reg(pi,
RADIO_2056_RX_LNAA_TUNE |
@@ -24715,34 +26622,41 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core)
} else {
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX0);
-
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX0, 0x40);
-
- write_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX1, bias_g);
-
- write_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX0, bias_g);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX0);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX0, 0x40);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TXSPARE2
+ |
+ RADIO_2056_TX1, bias_g);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_RXSPARE2
+ |
+ RADIO_2056_RX0, bias_g);
} else {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAG_TUNE
- | RADIO_2056_RX0);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_TUNE
+ | RADIO_2056_RX0);
offtune_val =
- (pi->
- tx_rx_cal_radio_saveregs[2] & 0xF0)
- >> 8;
+ (pi->
+ tx_rx_cal_radio_saveregs[2] &
+ 0xF0) >> 8;
offtune_val =
- (offtune_val <= 0x7) ? 0xF : 0;
+ (offtune_val <= 0x7) ? 0xF : 0;
mod_radio_reg(pi,
RADIO_2056_RX_LNAG_TUNE |
@@ -24760,56 +26674,63 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core)
} else {
pi->tx_rx_cal_radio_saveregs[0] =
- read_radio_reg(pi,
- RADIO_2056_TX_RXIQCAL_TXMUX |
- RADIO_2056_TX0);
+ read_radio_reg(pi,
+ RADIO_2056_TX_RXIQCAL_TXMUX |
+ RADIO_2056_TX0);
pi->tx_rx_cal_radio_saveregs[1] =
- read_radio_reg(pi,
- RADIO_2056_RX_RXIQCAL_RXMUX |
- RADIO_2056_RX1);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RXIQCAL_RXMUX |
+ RADIO_2056_RX1);
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[2] =
- read_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX1);
+ read_radio_reg(pi,
+ RADIO_2056_RX_RXSPARE2 |
+ RADIO_2056_RX1);
pi->tx_rx_cal_radio_saveregs[3] =
- read_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX0);
+ read_radio_reg(pi,
+ RADIO_2056_TX_TXSPARE2 |
+ RADIO_2056_TX0);
}
if (CHSPEC_IS5G(pi->radio_chanspec)) {
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX1);
-
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX1, 0x40);
-
- write_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX0, bias_a);
-
- write_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX1, bias_a);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_MASTER
+ | RADIO_2056_RX1);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_MASTER |
+ RADIO_2056_RX1, 0x40);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TXSPARE2
+ |
+ RADIO_2056_TX0, bias_a);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_RXSPARE2
+ |
+ RADIO_2056_RX1, bias_a);
} else {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAA_TUNE
- | RADIO_2056_RX1);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_TUNE
+ | RADIO_2056_RX1);
offtune_val =
- (pi->
- tx_rx_cal_radio_saveregs[2] & 0xF0)
- >> 8;
+ (pi->
+ tx_rx_cal_radio_saveregs[2] &
+ 0xF0) >> 8;
offtune_val =
- (offtune_val <= 0x7) ? 0xF : 0;
+ (offtune_val <= 0x7) ? 0xF : 0;
mod_radio_reg(pi,
RADIO_2056_RX_LNAA_TUNE |
@@ -24826,33 +26747,40 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core)
} else {
if (pi->pubpi.radiorev >= 5) {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX1);
-
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX1, 0x40);
-
- write_radio_reg(pi,
- RADIO_2056_TX_TXSPARE2 |
- RADIO_2056_TX0, bias_g);
-
- write_radio_reg(pi,
- RADIO_2056_RX_RXSPARE2 |
- RADIO_2056_RX1, bias_g);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX1);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX1, 0x40);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_TX_TXSPARE2
+ |
+ RADIO_2056_TX0, bias_g);
+
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_RXSPARE2
+ |
+ RADIO_2056_RX1, bias_g);
} else {
pi->tx_rx_cal_radio_saveregs[4] =
- read_radio_reg(pi,
- RADIO_2056_RX_LNAG_TUNE
- | RADIO_2056_RX1);
+ read_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_TUNE
+ | RADIO_2056_RX1);
offtune_val =
- (pi->
- tx_rx_cal_radio_saveregs[2] & 0xF0)
- >> 8;
+ (pi->
+ tx_rx_cal_radio_saveregs[2] &
+ 0xF0) >> 8;
offtune_val =
- (offtune_val <= 0x7) ? 0xF : 0;
+ (offtune_val <= 0x7) ? 0xF : 0;
mod_radio_reg(pi,
RADIO_2056_RX_LNAG_TUNE |
@@ -24876,46 +26804,54 @@ static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core)
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
if (rx_core == PHY_CORE_0) {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
- pi->
- tx_rx_cal_radio_saveregs[0]);
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
- pi->
- tx_rx_cal_radio_saveregs[1]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+ pi->
+ tx_rx_cal_radio_saveregs[0]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+ pi->
+ tx_rx_cal_radio_saveregs[1]);
} else {
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
- pi->
- tx_rx_cal_radio_saveregs[0]);
- write_radio_reg(pi,
- RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
- pi->
- tx_rx_cal_radio_saveregs[1]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+ pi->
+ tx_rx_cal_radio_saveregs[0]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+ pi->
+ tx_rx_cal_radio_saveregs[1]);
}
} else {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
- pi->
- tx_rx_cal_radio_saveregs[0]);
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
- pi->
- tx_rx_cal_radio_saveregs[1]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+ pi->
+ tx_rx_cal_radio_saveregs[0]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+ pi->
+ tx_rx_cal_radio_saveregs[1]);
} else {
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
- pi->
- tx_rx_cal_radio_saveregs[0]);
- write_radio_reg(pi,
- RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
- pi->
- tx_rx_cal_radio_saveregs[1]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+ pi->
+ tx_rx_cal_radio_saveregs[0]);
+ write_radio_reg(
+ pi,
+ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+ pi->
+ tx_rx_cal_radio_saveregs[1]);
}
}
@@ -24946,37 +26882,39 @@ static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core)
}
if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (pi->pubpi.radiorev >= 5) {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX0,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- } else {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_TUNE
- | RADIO_2056_RX0,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- }
+ if (pi->pubpi.radiorev >= 5)
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_MASTER
+ | RADIO_2056_RX0,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
+ else
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_TUNE
+ | RADIO_2056_RX0,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
} else {
- if (pi->pubpi.radiorev >= 5) {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX0,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- } else {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_TUNE
- | RADIO_2056_RX0,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- }
+ if (pi->pubpi.radiorev >= 5)
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX0,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
+ else
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_TUNE
+ | RADIO_2056_RX0,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
}
} else {
@@ -25005,37 +26943,39 @@ static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core)
}
if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (pi->pubpi.radiorev >= 5) {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_MASTER
- | RADIO_2056_RX1,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- } else {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAA_TUNE
- | RADIO_2056_RX1,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- }
+ if (pi->pubpi.radiorev >= 5)
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_MASTER
+ | RADIO_2056_RX1,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
+ else
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAA_TUNE
+ | RADIO_2056_RX1,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
} else {
- if (pi->pubpi.radiorev >= 5) {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_MASTER
- | RADIO_2056_RX1,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- } else {
- write_radio_reg(pi,
- RADIO_2056_RX_LNAG_TUNE
- | RADIO_2056_RX1,
- pi->
- tx_rx_cal_radio_saveregs
- [4]);
- }
+ if (pi->pubpi.radiorev >= 5)
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_MASTER
+ | RADIO_2056_RX1,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
+ else
+ write_radio_reg(
+ pi,
+ RADIO_2056_RX_LNAG_TUNE
+ | RADIO_2056_RX1,
+ pi->
+ tx_rx_cal_radio_saveregs
+ [4]);
}
}
}
@@ -25046,18 +26986,16 @@ static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core)
u8 tx_core;
u16 rx_antval, tx_antval;
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
tx_core = rx_core;
- } else {
+ else
tx_core = (rx_core == PHY_CORE_0) ? 1 : 0;
- }
pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2);
pi->tx_rx_cal_phy_saveregs[1] =
- read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7);
+ read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7);
pi->tx_rx_cal_phy_saveregs[2] =
- read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5);
+ read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5);
pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91);
pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92);
pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a);
@@ -25122,17 +27060,19 @@ static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core)
NPHY_REV7_RFCTRLOVERRIDE_ID2);
wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0,
NPHY_REV7_RFCTRLOVERRIDE_ID1);
- if (CHSPEC_IS40(pi->radio_chanspec)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 7),
- 2, 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- } else {
- wlc_phy_rfctrl_override_nphy_rev7(pi,
- (0x1 << 7),
- 0, 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- }
+ if (CHSPEC_IS40(pi->radio_chanspec))
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 7),
+ 2, 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+ else
+ wlc_phy_rfctrl_override_nphy_rev7(
+ pi,
+ (0x1 << 7),
+ 0, 0, 0,
+ NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
0, 0, 0,
NPHY_REV7_RFCTRLOVERRIDE_ID1);
@@ -25203,26 +27143,24 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core,
struct phy_iq_est est[PHY_CORE_MAX];
u8 tx_core;
struct nphy_iq_comp save_comp, zero_comp;
- u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, thresh_pwr =
- 10000;
+ u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0,
+ thresh_pwr = 10000;
s16 desired_log2_pwr, actual_log2_pwr, delta_pwr;
bool gainctrl_done = false;
u8 mix_tia_gain = 3;
s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0;
s8 curr_gaintbl_index = 3;
u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT;
- struct nphy_ipa_txrxgain *nphy_rxcal_gaintbl;
+ const struct nphy_ipa_txrxgain *nphy_rxcal_gaintbl;
u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1;
int fine_gain_idx;
s8 txpwrindex;
u16 nphy_rxcal_txgain[2];
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
tx_core = rx_core;
- } else {
+ else
tx_core = 1 - rx_core;
- }
num_samps = 1024;
desired_log2_pwr = (cal_type == 0) ? 13 : 13;
@@ -25232,45 +27170,42 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core,
wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp);
if (CHSPEC_IS5G(pi->radio_chanspec)) {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
mix_tia_gain = 3;
- } else if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+ else if (NREV_GE(pi->pubpi.phy_rev, 4))
mix_tia_gain = 4;
- } else {
+ else
mix_tia_gain = 6;
- }
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7;
- } else {
+ else
nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz;
- }
} else {
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7;
- } else {
+ else
nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz;
- }
}
do {
hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ?
- 0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga;
+ 0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga;
lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1;
lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0;
lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2;
lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1;
txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex;
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_rxgain,
- ((lpf_biq1 << 12) |
- (lpf_biq0 << 8) |
- (mix_tia_gain <<
- 4) | (lna2 << 2)
- | lna1), 0x3, 0);
- } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_rxgain,
+ ((lpf_biq1 << 12) |
+ (lpf_biq0 << 8) |
+ (mix_tia_gain << 4) | (lna2 << 2)
+ | lna1), 0x3, 0);
+ else
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
((hpvga << 12) |
(lpf_biq1 << 10) |
@@ -25278,7 +27213,6 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core,
(mix_tia_gain << 4) |
(lna2 << 2) | lna1), 0x3,
0);
- }
pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex;
@@ -25367,27 +27301,28 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core,
if (NREV_GE(pi->pubpi.phy_rev, 7)) {
fine_gain_idx = (int)lpf_biq1 + delta_pwr;
- if (fine_gain_idx + (int)lpf_biq0 > 10) {
+ if (fine_gain_idx + (int)lpf_biq0 > 10)
lpf_biq1 = 10 - lpf_biq0;
- } else {
+ else
lpf_biq1 = (u16) max(fine_gain_idx, 0);
- }
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_rxgain,
- ((lpf_biq1 << 12) |
- (lpf_biq0 << 8) |
- (mix_tia_gain << 4) |
- (lna2 << 2) | lna1), 0x3,
- 0);
+
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_rxgain,
+ ((lpf_biq1 << 12) |
+ (lpf_biq0 << 8) |
+ (mix_tia_gain << 4) |
+ (lna2 << 2) | lna1), 0x3,
+ 0);
} else {
hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0);
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
- ((hpvga << 12) | (lpf_biq1 << 10) |
- (lpf_biq0 << 8) | (mix_tia_gain <<
- 4) | (lna2 <<
- 2) |
+ ((hpvga << 12) |
+ (lpf_biq1 << 10) |
+ (lpf_biq0 << 8) |
+ (mix_tia_gain << 4) |
+ (lna2 << 2) |
lna1), 0x3, 0);
-
}
if (rxgain != NULL) {
@@ -25444,9 +27379,8 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
u16 num_samps, log_num_samps = 10;
struct phy_iq_est est[PHY_CORE_MAX];
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
return 0;
- }
num_samps = (1 << log_num_samps);
@@ -25465,20 +27399,21 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
if (core_idx == 0) {
radio_addr_offset_rx = RADIO_2056_RX0;
radio_addr_offset_tx =
- (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+ (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
} else {
radio_addr_offset_rx = RADIO_2056_RX1;
radio_addr_offset_tx =
- (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0;
+ (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0;
}
orig_txlpf_rccal_lpc_ovr_val =
- read_radio_reg(pi,
- (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx));
+ read_radio_reg(pi,
+ (RADIO_2056_TX_TXLPF_RCCAL |
+ radio_addr_offset_tx));
orig_rxlpf_rccal_hpc_ovr_val =
- read_radio_reg(pi,
- (RADIO_2056_RX_RXLPF_RCCAL_HPC |
- radio_addr_offset_rx));
+ read_radio_reg(pi,
+ (RADIO_2056_RX_RXLPF_RCCAL_HPC |
+ radio_addr_offset_rx));
orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1);
@@ -25549,17 +27484,18 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
- if (core_idx == 0) {
+ if (core_idx == 0)
ref_iq_vals =
- max_t(u32, (est[0].i_pwr +
- est[0].q_pwr) >> (log_num_samps + 1),
- 1);
- } else {
+ max_t(u32, (est[0].i_pwr +
+ est[0].q_pwr) >>
+ (log_num_samps + 1),
+ 1);
+ else
ref_iq_vals =
- max_t(u32, (est[1].i_pwr +
- est[1].q_pwr) >> (log_num_samps + 1),
- 1);
- }
+ max_t(u32, (est[1].i_pwr +
+ est[1].q_pwr) >>
+ (log_num_samps + 1),
+ 1);
wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP,
0, 1, false);
@@ -25568,20 +27504,19 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
- if (core_idx == 0) {
- target_iq_vals =
- (est[0].i_pwr + est[0].q_pwr) >> (log_num_samps +
- 1);
- } else {
+ if (core_idx == 0)
+ target_iq_vals = (est[0].i_pwr + est[0].q_pwr) >>
+ (log_num_samps + 1);
+ else
target_iq_vals =
- (est[1].i_pwr + est[1].q_pwr) >> (log_num_samps +
- 1);
- }
+ (est[1].i_pwr +
+ est[1].q_pwr) >> (log_num_samps + 1);
+
pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals);
- if (rccal_stepsize == 0) {
+ if (rccal_stepsize == 0)
rccal_stepsize--;
- } else if (rccal_stepsize == 1) {
+ else if (rccal_stepsize == 1) {
last_rccal_val = rccal_val;
rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1;
last_pwr_ratio = pwr_ratio;
@@ -25594,21 +27529,20 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
if (rccal_stepsize == -1) {
best_rccal_val =
- (ABS((int)last_pwr_ratio - (int)target_pwr_ratio) <
- ABS((int)pwr_ratio -
- (int)target_pwr_ratio)) ? last_rccal_val :
- rccal_val;
+ (abs((int)last_pwr_ratio -
+ (int)target_pwr_ratio) <
+ abs((int)pwr_ratio -
+ (int)target_pwr_ratio)) ? last_rccal_val :
+ rccal_val;
if (CHSPEC_IS40(pi->radio_chanspec)) {
if ((best_rccal_val > 140)
- || (best_rccal_val < 135)) {
+ || (best_rccal_val < 135))
best_rccal_val = 138;
- }
} else {
if ((best_rccal_val > 142)
- || (best_rccal_val < 137)) {
+ || (best_rccal_val < 137))
best_rccal_val = 140;
- }
}
write_radio_reg(pi,
@@ -25649,7 +27583,7 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
return best_rccal_val - 0x80;
}
-#define WAIT_FOR_SCOPE 4000
+#define WAIT_FOR_SCOPE 4000
static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
struct nphy_txgains target_gain,
u8 cal_type, bool debug)
@@ -25687,12 +27621,12 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
rxcore_state = wlc_phy_rxcore_getstate_nphy(
- (struct brcms_phy_pub *) pi);
+ (struct brcms_phy_pub *) pi);
for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
skip_rxiqcal =
- ((rxcore_state & (1 << rx_core)) == 0) ? true : false;
+ ((rxcore_state & (1 << rx_core)) == 0) ? true : false;
wlc_phy_rxcal_physetup_nphy(pi, rx_core);
@@ -25703,7 +27637,8 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0);
wlc_phy_tx_tone_nphy(pi,
- (CHSPEC_IS40(pi->radio_chanspec)) ?
+ (CHSPEC_IS40(
+ pi->radio_chanspec)) ?
NPHY_RXCAL_TONEFREQ_40MHz :
NPHY_RXCAL_TONEFREQ_20MHz,
NPHY_RXCAL_TONEAMP, 0, cal_type,
@@ -25721,23 +27656,21 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
if (rx_core == PHY_CORE_1) {
- if (rxcore_state == 1) {
+ if (rxcore_state == 1)
wlc_phy_rxcore_setstate_nphy(
(struct brcms_phy_pub *) pi, 3);
- }
wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL,
1);
best_rccal[rx_core] =
- wlc_phy_rc_sweep_nphy(pi, rx_core, 1);
+ wlc_phy_rc_sweep_nphy(pi, rx_core, 1);
pi->nphy_rccal_value = best_rccal[rx_core];
- if (rxcore_state == 1) {
+ if (rxcore_state == 1)
wlc_phy_rxcore_setstate_nphy(
(struct brcms_phy_pub *) pi,
rxcore_state);
- }
}
}
@@ -25756,18 +27689,22 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
rxlpf_rccal_hpc =
- (((int)best_rccal[rx_core] - 12) >> 1) + 10;
+ (((int)best_rccal[rx_core] - 12) >> 1) + 10;
txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10;
if (PHY_IPA(pi)) {
- txlpf_rccal_lpc += IS40MHZ(pi) ? 24 : 12;
- txlpf_idac = IS40MHZ(pi) ? 0x0e : 0x13;
+ txlpf_rccal_lpc +=
+ (pi->bw == WL_CHANSPEC_BW_40) ? 24 : 12;
+ txlpf_idac = (pi->bw == WL_CHANSPEC_BW_40) ?
+ 0x0e : 0x13;
WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core,
TXLPF_IDAC_4, txlpf_idac);
}
- rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), 0);
- txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), 0);
+ rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31),
+ 0);
+ txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31),
+ 0);
write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC |
((rx_core ==
@@ -25787,21 +27724,21 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
wlc_phy_resetcca_nphy(pi);
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_rxgain,
- 0, 0x3, 1);
- } else {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
+ wlc_phy_rfctrl_override_1tomany_nphy(
+ pi,
+ NPHY_REV7_RfctrlOverride_cmd_rxgain,
+ 0, 0x3, 1);
+ else
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
- }
+
wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
gain_save);
- if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 4))
pi->phyhang_avoid = phyhang_avoid_state;
- }
wlc_phy_stay_in_carriersearch_nphy(pi, false);
@@ -25835,10 +27772,8 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
wlc_phy_stay_in_carriersearch_nphy(pi, true);
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
+ if (NREV_LT(pi->pubpi.phy_rev, 2))
wlc_phy_reapply_txcal_coeffs_nphy(pi);
- }
wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
@@ -25874,19 +27809,16 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
((0x1 << 1) | (0x1 << 2)));
or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2)));
- if (((pi->nphy_rxcalparams) & 0xff000000)) {
-
+ if (((pi->nphy_rxcalparams) & 0xff000000))
write_phy_reg(pi,
(rx_core == PHY_CORE_0) ? 0x91 : 0x92,
- (CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 :
- 0x110));
- } else {
-
+ (CHSPEC_IS5G(pi->radio_chanspec) ?
+ 0x140 : 0x110));
+ else
write_phy_reg(pi,
(rx_core == PHY_CORE_0) ? 0x91 : 0x92,
- (CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 :
- 0x120));
- }
+ (CHSPEC_IS5G(pi->radio_chanspec) ?
+ 0x180 : 0x120));
write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92,
(CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 :
@@ -25926,7 +27858,7 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
use_hpf_num = 1;
curr_hpf = curr_hpf1;
actual_log2_pwr =
- wlc_phy_nbits(tot_pwr[2]);
+ wlc_phy_nbits(tot_pwr[2]);
} else {
if (tot_pwr[0] > 10000) {
curr_lna = lna_vals[1];
@@ -25935,7 +27867,8 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
use_hpf_num = 1;
curr_hpf = curr_hpf1;
actual_log2_pwr =
- wlc_phy_nbits(tot_pwr[1]);
+ wlc_phy_nbits(
+ tot_pwr[1]);
} else {
curr_lna = lna_vals[0];
curr_hpf1 = hpf1_vals[0];
@@ -25943,18 +27876,18 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
use_hpf_num = 2;
curr_hpf = curr_hpf2;
actual_log2_pwr =
- wlc_phy_nbits(tot_pwr[0]);
+ wlc_phy_nbits(
+ tot_pwr[0]);
}
}
hpf_change = desired_log2_pwr - actual_log2_pwr;
curr_hpf += hpf_change;
curr_hpf = max(min_t(u16, curr_hpf, 10), 0);
- if (use_hpf_num == 1) {
+ if (use_hpf_num == 1)
curr_hpf1 = curr_hpf;
- } else {
+ else
curr_hpf2 = curr_hpf;
- }
}
wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10),
@@ -25967,15 +27900,12 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
if (first_playtone) {
bcmerror = wlc_phy_tx_tone_nphy(pi, 4000,
- (u16) (pi->
- nphy_rxcalparams
- &
- 0xffff),
- 0, 0, true);
+ (u16) (pi->nphy_rxcalparams &
+ 0xffff), 0, 0, true);
first_playtone = false;
} else {
- phy_bw =
- (CHSPEC_IS40(pi->radio_chanspec)) ? 40 : 20;
+ phy_bw = (CHSPEC_IS40(pi->radio_chanspec)) ?
+ 40 : 20;
wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff,
0, 0, 0, true);
}
@@ -25986,12 +27916,10 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
wlc_phy_rx_iq_est_nphy(pi, est,
num_samps, 32,
0);
- i_pwr =
- (est[rx_core].i_pwr +
- num_samps / 2) / num_samps;
- q_pwr =
- (est[rx_core].q_pwr +
- num_samps / 2) / num_samps;
+ i_pwr = (est[rx_core].i_pwr +
+ num_samps / 2) / num_samps;
+ q_pwr = (est[rx_core].q_pwr +
+ num_samps / 2) / num_samps;
tot_pwr[gain_pass] = i_pwr + q_pwr;
} else {
@@ -26038,1350 +27966,14 @@ int
wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
u8 cal_type, bool debug)
{
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
cal_type = 0;
- }
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type,
debug);
- } else {
+ else
return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug);
- }
-}
-
-static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
-{
- int j, type = 2;
- u16 addr_offset = 0x2c5;
-
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, addr_offset + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
- }
-}
-
-static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
-{
- int j, type;
- u16 addr_offset[] = { 0x186, 0x195,
- 0x2c5
- };
-
- for (type = 0; type < 3; type++) {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, addr_offset[type] + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
- }
- }
-
- if (IS40MHZ(pi)) {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, 0x186 + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
- }
- } else {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, 0x186 + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[5]
- [j]);
- }
- }
-
- if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, 0x2c5 + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[6]
- [j]);
- }
- }
- }
-}
-
-static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi)
-{
- int j;
-
- if (IS40MHZ(pi)) {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, 0x195 + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]);
- }
- } else {
- for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
- write_phy_reg(pi, 0x186 + j,
- NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
- }
- }
-}
-
-static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi)
-{
- u16 m0m1;
-
- wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
-
- return m0m1;
-}
-
-static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1)
-{
- u16 m0m1 = (u16) ((m0 << 8) | m1);
-
- wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1);
- wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1);
-}
-
-static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi)
-{
- u32 *tx_pwrctrl_tbl = NULL;
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- if ((pi->pubpi.radiorev == 4)
- || (pi->pubpi.radiorev == 6)) {
-
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_ipa_2g_2057rev4n6;
- } else if (pi->pubpi.radiorev == 3) {
-
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_ipa_2g_2057rev3;
- } else if (pi->pubpi.radiorev == 5) {
-
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_ipa_2g_2057rev5;
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_ipa_2g_2057rev7;
- }
-
- } else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
-
- tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
- } else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-
- tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
- } else {
-
- tx_pwrctrl_tbl = nphy_tpc_txgain_ipa;
- }
-
- } else {
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
-
- tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057;
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- tx_pwrctrl_tbl =
- nphy_tpc_txgain_ipa_5g_2057rev7;
- }
-
- } else {
- tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g;
- }
- }
-
- return tx_pwrctrl_tbl;
-}
-
-static void
-wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi,
- struct nphy_papd_restore_state *state, u8 core)
-{
- s32 tone_freq;
- u8 off_core;
- u16 mixgain = 0;
-
- off_core = core ^ 0x1;
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- if (NREV_IS(pi->pubpi.phy_rev, 7)
- || NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
- wlc_phy_read_lpf_bw_ctl_nphy
- (pi, 0), 0, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (pi->pubpi.radiorev == 5) {
- mixgain = (core == 0) ? 0x20 : 0x00;
-
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- mixgain = 0x00;
-
- } else if ((pi->pubpi.radiorev <= 4)
- || (pi->pubpi.radiorev == 6)) {
-
- mixgain = 0x00;
- }
-
- } else {
- if ((pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
-
- mixgain = 0x50;
- } else if ((pi->pubpi.radiorev == 3)
- || (pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- mixgain = 0x0;
- }
- }
-
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
- mixgain, (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_tx_pu,
- 1, (1 << core), 0);
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_tx_pu,
- 0, (1 << off_core), 0);
-
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
- 0, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
- 0, (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0,
- (1 << core), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
- state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
- 0xa6 : 0xa7);
- state->afeoverride[core] =
- read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
- state->afectrl[off_core] =
- read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6);
- state->afeoverride[off_core] =
- read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f);
-
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
- (0x1 << 2), 0);
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
- 0xa5), (0x1 << 2), (0x1 << 2));
-
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6),
- (0x1 << 2), (0x1 << 2));
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 :
- 0x8f), (0x1 << 2), (0x1 << 2));
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- state->pwrup[core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_PWRUP);
- state->atten[core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_ATTEN);
- state->pwrup[off_core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_2G_PWRUP);
- state->atten[off_core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_2G_ATTEN);
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_PWRUP, 0xc);
-
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_ATTEN, 0xf0);
-
- } else if (pi->pubpi.radiorev == 5) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_ATTEN,
- (core == 0) ? 0xf7 : 0xf2);
-
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_ATTEN, 0xf0);
-
- }
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_2G_PWRUP, 0x0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_2G_ATTEN, 0xff);
-
- } else {
- state->pwrup[core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_PWRUP);
- state->atten[core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_ATTEN);
- state->pwrup[off_core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_5G_PWRUP);
- state->atten[off_core] =
- READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_5G_ATTEN);
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_PWRUP, 0xc);
-
- if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_ATTEN, 0xf4);
-
- } else {
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_ATTEN, 0xf0);
- }
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_5G_PWRUP, 0x0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
- TXRXCOUPLE_5G_ATTEN, 0xff);
- }
-
- tone_freq = 4000;
-
- wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (1) << 13);
-
- mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0);
-
- mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (0) << 13);
-
- } else {
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0);
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0);
-
- state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
- 0xa6 : 0xa7);
- state->afeoverride[core] =
- read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
-
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
- (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0);
- mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
- 0xa5),
- (0x1 << 0) |
- (0x1 << 1) |
- (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
-
- state->vga_master[core] =
- READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER);
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b);
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- state->fbmix[core] =
- READ_RADIO_REG2(pi, RADIO_2056, RX, core,
- TXFBMIX_G);
- state->intpa_master[core] =
- READ_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAG_MASTER);
-
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G,
- 0x03);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAG_MASTER, 0x04);
- } else {
- state->fbmix[core] =
- READ_RADIO_REG2(pi, RADIO_2056, RX, core,
- TXFBMIX_A);
- state->intpa_master[core] =
- READ_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAA_MASTER);
-
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A,
- 0x03);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAA_MASTER, 0x04);
-
- }
-
- tone_freq = 4000;
-
- wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (1) << 0);
-
- mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (0) << 0);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
- }
-}
-
-static void
-wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi,
- struct nphy_papd_restore_state *state)
-{
- u8 core;
-
- wlc_phy_stopplayback_nphy(pi);
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_PWRUP, 0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_2G_ATTEN,
- state->atten[core]);
- } else {
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_PWRUP, 0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TXRXCOUPLE_5G_ATTEN,
- state->atten[core]);
- }
- }
-
- if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
- 1, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- } else {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
- 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- }
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
- 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID2);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
- write_phy_reg(pi, (core == PHY_CORE_0) ?
- 0xa6 : 0xa7, state->afectrl[core]);
- write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
- 0xa5, state->afeoverride[core]);
- }
-
- wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
- (state->mm & 0xff));
-
- if (NREV_IS(pi->pubpi.phy_rev, 7)
- || NREV_GE(pi->pubpi.phy_rev, 8)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
- 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID1);
- }
- } else {
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1);
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1);
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1);
-
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER,
- state->vga_master[core]);
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
- TXFBMIX_G, state->fbmix[core]);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAG_MASTER,
- state->intpa_master[core]);
- } else {
- WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
- TXFBMIX_A, state->fbmix[core]);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- INTPAA_MASTER,
- state->intpa_master[core]);
- }
-
- write_phy_reg(pi, (core == PHY_CORE_0) ?
- 0xa6 : 0xa7, state->afectrl[core]);
- write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
- 0xa5, state->afeoverride[core]);
- }
-
- wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
- (state->mm & 0xff));
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1);
- }
-}
-
-static void
-wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start,
- u32 end)
-{
- u32 *buf, *src, *dst, sz;
-
- sz = end - start + 1;
-
- buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC);
- if (NULL == buf) {
- return;
- }
-
- src = buf;
- dst = buf + NPHY_PAPD_EPS_TBL_SIZE;
-
- wlc_phy_table_read_nphy(pi,
- (core ==
- PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 :
- NPHY_TBL_ID_EPSILONTBL1),
- NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src);
-
- do {
- u32 phy_a1, phy_a2;
- s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7;
-
- phy_a1 = end - min(end, (winsz >> 1));
- phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, end + (winsz >> 1));
- phy_a3 = phy_a2 - phy_a1 + 1;
- phy_a6 = 0;
- phy_a7 = 0;
-
- do {
- wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4,
- &phy_a5);
- phy_a6 += phy_a4;
- phy_a7 += phy_a5;
- } while (phy_a2-- != phy_a1);
-
- phy_a6 /= phy_a3;
- phy_a7 /= phy_a3;
- dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff);
- } while (end-- != start);
-
- wlc_phy_table_write_nphy(pi,
- (core ==
- PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 :
- NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst);
-
- kfree(buf);
-}
-
-static void
-wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains,
- enum phy_cal_mode cal_mode, u8 core)
-{
- u16 phy_a1, phy_a2, phy_a3;
- u16 phy_a4, phy_a5;
- bool phy_a6;
- u8 phy_a7, m[2];
- u32 phy_a8 = 0;
- struct nphy_txgains phy_a9;
-
- if (NREV_LT(pi->pubpi.phy_rev, 3))
- return;
-
- phy_a7 = (core == PHY_CORE_0) ? 1 : 0;
-
- phy_a6 = ((cal_mode == CAL_GCTRL)
- || (cal_mode == CAL_SOFT)) ? true : false;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- phy_a9 = wlc_phy_get_tx_gain_nphy(pi);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- phy_a5 = ((phy_a9.txlpf[core] << 15) |
- (phy_a9.txgm[core] << 12) |
- (phy_a9.pga[core] << 8) |
- (txgains->gains.pad[core] << 3) |
- (phy_a9.ipa[core]));
- } else {
- phy_a5 = ((phy_a9.txlpf[core] << 15) |
- (phy_a9.txgm[core] << 12) |
- (txgains->gains.pga[core] << 8) |
- (phy_a9.pad[core] << 3) | (phy_a9.ipa[core]));
- }
-
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_txgain,
- phy_a5, (1 << core), 0);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if ((pi->pubpi.radiorev <= 4)
- || (pi->pubpi.radiorev == 6)) {
-
- m[core] = IS40MHZ(pi) ? 60 : 79;
- } else {
-
- m[core] = IS40MHZ(pi) ? 45 : 64;
- }
-
- } else {
- m[core] = IS40MHZ(pi) ? 75 : 107;
- }
-
- m[phy_a7] = 0;
- wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
-
- phy_a2 = 63;
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if ((pi->pubpi.radiorev == 4)
- || (pi->pubpi.radiorev == 6)) {
- phy_a1 = 30;
- phy_a3 = 30;
- } else {
- phy_a1 = 25;
- phy_a3 = 25;
- }
- } else {
- if ((pi->pubpi.radiorev == 5)
- || (pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
- phy_a1 = 25;
- phy_a3 = 25;
- } else {
- phy_a1 = 35;
- phy_a3 = 35;
- }
- }
-
- if (cal_mode == CAL_GCTRL) {
- if ((pi->pubpi.radiorev == 5)
- && (CHSPEC_IS2G(pi->radio_chanspec))) {
- phy_a1 = 55;
- } else if (((pi->pubpi.radiorev == 7) &&
- (CHSPEC_IS2G(pi->radio_chanspec))) ||
- ((pi->pubpi.radiorev == 8) &&
- (CHSPEC_IS2G(pi->radio_chanspec)))) {
- phy_a1 = 60;
- } else {
- phy_a1 = 63;
- }
-
- } else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) {
-
- phy_a1 = 35;
- phy_a3 = 35;
- }
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (1) << 0);
-
- mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (0) << 0);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (1) << 13);
-
- mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (0) << 13);
-
- write_phy_reg(pi, 0x2a1, 0x80);
- write_phy_reg(pi, 0x2a2, 0x100);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 4), (11) << 4);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 8), (11) << 8);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 0), (0x3) << 0);
-
- write_phy_reg(pi, 0x2e5, 0x20);
-
- mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
-
- mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
-
- mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
-
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
- 1, ((core == 0) ? 1 : 2), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
- 0, ((core == 0) ? 2 : 1), 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
- write_phy_reg(pi, 0x2be, 1);
- SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
-
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
- 0, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
- wlc_phy_table_write_nphy(pi,
- (core ==
- PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
- : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
- 32, &phy_a8);
-
- if (cal_mode != CAL_GCTRL) {
- if (CHSPEC_IS5G(pi->radio_chanspec)) {
- wlc_phy_a1_nphy(pi, core, 5, 0, 35);
- }
- }
-
- wlc_phy_rfctrl_override_1tomany_nphy(pi,
- NPHY_REV7_RfctrlOverride_cmd_txgain,
- phy_a5, (1 << core), 1);
-
- } else {
-
- if (txgains) {
- if (txgains->useindex) {
- phy_a4 = 15 - ((txgains->index) >> 3);
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (NREV_GE(pi->pubpi.phy_rev, 6))
- phy_a5 = 0x00f7 | (phy_a4 << 8);
-
- else
- if (NREV_IS(pi->pubpi.phy_rev, 5))
- phy_a5 = 0x10f7 | (phy_a4 << 8);
- else
- phy_a5 = 0x50f7 | (phy_a4 << 8);
- } else {
- phy_a5 = 0x70f7 | (phy_a4 << 8);
- }
- wlc_phy_rfctrl_override_nphy(pi,
- (0x1 << 13),
- phy_a5,
- (1 << core), 0);
- } else {
- wlc_phy_rfctrl_override_nphy(pi,
- (0x1 << 13),
- 0x5bf7,
- (1 << core), 0);
- }
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- m[core] = IS40MHZ(pi) ? 45 : 64;
- } else {
- m[core] = IS40MHZ(pi) ? 75 : 107;
- }
-
- m[phy_a7] = 0;
- wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
-
- phy_a2 = 63;
-
- if (cal_mode == CAL_FULL) {
- phy_a1 = 25;
- phy_a3 = 25;
- } else if (cal_mode == CAL_SOFT) {
- phy_a1 = 25;
- phy_a3 = 25;
- } else if (cal_mode == CAL_GCTRL) {
- phy_a1 = 63;
- phy_a3 = 25;
- } else {
-
- phy_a1 = 25;
- phy_a3 = 25;
- }
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (1) << 0);
-
- mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (0) << 0);
-
- if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (1) << 13);
-
- mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (0) << 13);
-
- write_phy_reg(pi, 0x2a1, 0x20);
- write_phy_reg(pi, 0x2a2, 0x60);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0xf << 4), (9) << 4);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0xf << 8), (9) << 8);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0xf << 0), (0x2) << 0);
-
- write_phy_reg(pi, 0x2e5, 0x20);
- } else {
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 11), (1) << 11);
-
- mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 11), (0) << 11);
-
- write_phy_reg(pi, 0x2a1, 0x80);
- write_phy_reg(pi, 0x2a2, 0x600);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 4), (0) << 4);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 8), (0) << 8);
-
- mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x7 << 0), (0x3) << 0);
-
- mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8);
-
- }
-
- mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
-
- mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
-
- mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0);
-
- write_phy_reg(pi, 0x2be, 1);
- SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
-
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
-
- wlc_phy_table_write_nphy(pi,
- (core ==
- PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
- : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
- 32, &phy_a8);
-
- if (cal_mode != CAL_GCTRL) {
- wlc_phy_a1_nphy(pi, core, 5, 0, 40);
- }
- }
-}
-
-static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core)
-{
- int phy_a1;
- int phy_a2;
- bool phy_a3;
- struct nphy_ipa_txcalgains phy_a4;
- bool phy_a5 = false;
- bool phy_a6 = true;
- s32 phy_a7, phy_a8;
- u32 phy_a9;
- int phy_a10;
- bool phy_a11 = false;
- int phy_a12;
- u8 phy_a13 = 0;
- u8 phy_a14;
- u8 *phy_a15 = NULL;
-
- phy_a4.useindex = true;
- phy_a12 = start_gain;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
- phy_a2 = 20;
- phy_a1 = 1;
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (pi->pubpi.radiorev == 5) {
-
- phy_a15 = pad_gain_codes_used_2057rev5;
- phy_a13 = sizeof(pad_gain_codes_used_2057rev5) /
- sizeof(pad_gain_codes_used_2057rev5[0]) - 1;
-
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- phy_a15 = pad_gain_codes_used_2057rev7;
- phy_a13 = sizeof(pad_gain_codes_used_2057rev7) /
- sizeof(pad_gain_codes_used_2057rev7[0]) - 1;
-
- } else {
-
- phy_a15 = pad_all_gain_codes_2057;
- phy_a13 = sizeof(pad_all_gain_codes_2057) /
- sizeof(pad_all_gain_codes_2057[0]) - 1;
- }
-
- } else {
-
- phy_a15 = pga_all_gain_codes_2057;
- phy_a13 = sizeof(pga_all_gain_codes_2057) /
- sizeof(pga_all_gain_codes_2057[0]) - 1;
- }
-
- phy_a14 = 0;
-
- for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- phy_a4.gains.pad[core] =
- (u16) phy_a15[phy_a12];
- } else {
- phy_a4.gains.pga[core] =
- (u16) phy_a15[phy_a12];
- }
-
- wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
-
- wlc_phy_table_read_nphy(pi,
- (core ==
- PHY_CORE_0 ?
- NPHY_TBL_ID_EPSILONTBL0 :
- NPHY_TBL_ID_EPSILONTBL1), 1,
- 63, 32, &phy_a9);
-
- wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
-
- phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
- (phy_a8 == 4095) || (phy_a8 == -4096));
-
- if (!phy_a6 && (phy_a3 != phy_a5)) {
- if (!phy_a3) {
- phy_a12 -= (u8) phy_a1;
- }
- phy_a11 = true;
- break;
- }
-
- if (phy_a3)
- phy_a12 += (u8) phy_a1;
- else
- phy_a12 -= (u8) phy_a1;
-
- if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) {
- if (phy_a12 < phy_a14) {
- phy_a12 = phy_a14;
- } else {
- phy_a12 = phy_a13;
- }
- phy_a11 = true;
- break;
- }
-
- phy_a6 = false;
- phy_a5 = phy_a3;
- }
-
- } else {
- phy_a2 = 10;
- phy_a1 = 8;
- for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
- phy_a4.index = (u8) phy_a12;
- wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
-
- wlc_phy_table_read_nphy(pi,
- (core ==
- PHY_CORE_0 ?
- NPHY_TBL_ID_EPSILONTBL0 :
- NPHY_TBL_ID_EPSILONTBL1), 1,
- 63, 32, &phy_a9);
-
- wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
-
- phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
- (phy_a8 == 4095) || (phy_a8 == -4096));
-
- if (!phy_a6 && (phy_a3 != phy_a5)) {
- if (!phy_a3) {
- phy_a12 -= (u8) phy_a1;
- }
- phy_a11 = true;
- break;
- }
-
- if (phy_a3)
- phy_a12 += (u8) phy_a1;
- else
- phy_a12 -= (u8) phy_a1;
-
- if ((phy_a12 < 0) || (phy_a12 > 127)) {
- if (phy_a12 < 0) {
- phy_a12 = 0;
- } else {
- phy_a12 = 127;
- }
- phy_a11 = true;
- break;
- }
-
- phy_a6 = false;
- phy_a5 = phy_a3;
- }
-
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- return (u8) phy_a15[phy_a12];
- } else {
- return (u8) phy_a12;
- }
-
-}
-
-static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal)
-{
- struct nphy_ipa_txcalgains phy_b1[2];
- struct nphy_papd_restore_state phy_b2;
- bool phy_b3;
- u8 phy_b4;
- u8 phy_b5;
- s16 phy_b6, phy_b7, phy_b8;
- u16 phy_b9;
- s16 phy_b10, phy_b11, phy_b12;
-
- phy_b11 = 0;
- phy_b12 = 0;
- phy_b7 = 0;
- phy_b8 = 0;
- phy_b6 = 0;
-
- if (pi->nphy_papd_skip == 1)
- return;
-
- phy_b3 =
- (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
- if (!phy_b3) {
- wlapi_suspend_mac_and_wait(pi->sh->physhim);
- }
-
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- pi->nphy_force_papd_cal = false;
-
- for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++)
- pi->nphy_papd_tx_gain_at_last_cal[phy_b5] =
- wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5);
-
- pi->nphy_papd_last_cal = pi->sh->now;
- pi->nphy_papd_recal_counter++;
-
- if (NORADIO_ENAB(pi->pubpi))
- return;
-
- phy_b4 = pi->nphy_txpwrctrl;
- wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
-
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32,
- nphy_papd_scaltbl);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32,
- nphy_papd_scaltbl);
-
- phy_b9 = read_phy_reg(pi, 0x01);
- mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
-
- for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
- s32 i, val = 0;
- for (i = 0; i < 64; i++) {
- wlc_phy_table_write_nphy(pi,
- ((phy_b5 ==
- PHY_CORE_0) ?
- NPHY_TBL_ID_EPSILONTBL0 :
- NPHY_TBL_ID_EPSILONTBL1), 1,
- i, 32, &val);
- }
- }
-
- wlc_phy_ipa_restore_tx_digi_filts_nphy(pi);
-
- phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi);
- for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
- wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5);
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
- if ((pi->pubpi.radiorev == 3)
- || (pi->pubpi.radiorev == 4)
- || (pi->pubpi.radiorev == 6)) {
-
- pi->nphy_papd_cal_gain_index[phy_b5] =
- 23;
-
- } else if (pi->pubpi.radiorev == 5) {
-
- pi->nphy_papd_cal_gain_index[phy_b5] =
- 0;
- pi->nphy_papd_cal_gain_index[phy_b5] =
- wlc_phy_a3_nphy(pi,
- pi->
- nphy_papd_cal_gain_index
- [phy_b5], phy_b5);
-
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
-
- pi->nphy_papd_cal_gain_index[phy_b5] =
- 0;
- pi->nphy_papd_cal_gain_index[phy_b5] =
- wlc_phy_a3_nphy(pi,
- pi->
- nphy_papd_cal_gain_index
- [phy_b5], phy_b5);
-
- }
-
- phy_b1[phy_b5].gains.pad[phy_b5] =
- pi->nphy_papd_cal_gain_index[phy_b5];
-
- } else {
- pi->nphy_papd_cal_gain_index[phy_b5] = 0;
- pi->nphy_papd_cal_gain_index[phy_b5] =
- wlc_phy_a3_nphy(pi,
- pi->
- nphy_papd_cal_gain_index
- [phy_b5], phy_b5);
- phy_b1[phy_b5].gains.pga[phy_b5] =
- pi->nphy_papd_cal_gain_index[phy_b5];
- }
- } else {
- phy_b1[phy_b5].useindex = true;
- phy_b1[phy_b5].index = 16;
- phy_b1[phy_b5].index =
- wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, phy_b5);
-
- pi->nphy_papd_cal_gain_index[phy_b5] =
- 15 - ((phy_b1[phy_b5].index) >> 3);
- }
-
- switch (pi->nphy_papd_cal_type) {
- case 0:
- wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5);
- break;
- case 1:
- wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5);
- break;
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
- }
- }
-
- if (NREV_LT(pi->pubpi.phy_rev, 7)) {
- wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
- }
-
- for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
- int eps_offset = 0;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- if (pi->pubpi.radiorev == 3) {
- eps_offset = -2;
- } else if (pi->pubpi.radiorev == 5) {
- eps_offset = 3;
- } else {
- eps_offset = -1;
- }
- } else {
- eps_offset = 2;
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5];
- phy_b10 = 0;
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
- phy_b12 =
- -
- (nphy_papd_padgain_dlt_2g_2057rev3n4
- [phy_b8]
- + 1) / 2;
- phy_b10 = -1;
- } else if (pi->pubpi.radiorev == 5) {
- phy_b12 =
- -(nphy_papd_padgain_dlt_2g_2057rev5
- [phy_b8]
- + 1) / 2;
- } else if ((pi->pubpi.radiorev == 7) ||
- (pi->pubpi.radiorev == 8)) {
- phy_b12 =
- -(nphy_papd_padgain_dlt_2g_2057rev7
- [phy_b8]
- + 1) / 2;
- }
- } else {
- phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5];
- if ((pi->pubpi.radiorev == 3) ||
- (pi->pubpi.radiorev == 4) ||
- (pi->pubpi.radiorev == 6)) {
- phy_b11 =
- -(nphy_papd_pgagain_dlt_5g_2057
- [phy_b7]
- + 1) / 2;
- } else if ((pi->pubpi.radiorev == 7)
- || (pi->pubpi.radiorev == 8)) {
- phy_b11 =
- -(nphy_papd_pgagain_dlt_5g_2057rev7
- [phy_b7]
- + 1) / 2;
- }
-
- phy_b10 = -9;
- }
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- phy_b6 =
- -60 + 27 + eps_offset + phy_b12 + phy_b10;
- } else {
- phy_b6 =
- -60 + 27 + eps_offset + phy_b11 + phy_b10;
- }
-
- mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
- 0x29c, (0x1ff << 7), (phy_b6) << 7);
-
- pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
- } else {
- if (NREV_LT(pi->pubpi.phy_rev, 5)) {
- eps_offset = 4;
- } else {
- eps_offset = 2;
- }
-
- phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- phy_b11 =
- -(nphy_papd_pga_gain_delta_ipa_2g[phy_b7] +
- 1) / 2;
- phy_b10 = 0;
- } else {
- phy_b11 =
- -(nphy_papd_pga_gain_delta_ipa_5g[phy_b7] +
- 1) / 2;
- phy_b10 = -9;
- }
-
- phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10;
-
- mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
- 0x29c, (0x1ff << 7), (phy_b6) << 7);
-
- pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
- }
- }
-
- mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
- mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
- 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
- if (NREV_GE(pi->pubpi.phy_rev, 6)) {
- mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (0) << 13);
-
- mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 13), (0) << 13);
-
- } else {
- mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 11), (0) << 11);
-
- mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
- 0x2a4, (0x1 << 11), (0) << 11);
-
- }
- pi->nphy_papdcomp = NPHY_PAPD_COMP_ON;
-
- write_phy_reg(pi, 0x01, phy_b9);
-
- wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
-
- wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4);
- if (phy_b4 == PHY_TPC_HW_OFF) {
- wlc_phy_txpwr_index_nphy(pi, (1 << 0),
- (s8) (pi->nphy_txpwrindex[0].
- index_internal), false);
- wlc_phy_txpwr_index_nphy(pi, (1 << 1),
- (s8) (pi->nphy_txpwrindex[1].
- index_internal), false);
- }
-
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
- if (!phy_b3) {
- wlapi_enable_mac(pi->sh->physhim);
- }
}
void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
@@ -27423,11 +28015,10 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
}
}
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 7))
txpi[0] = txpi[1] = 30;
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ else if (NREV_GE(pi->pubpi.phy_rev, 3))
txpi[0] = txpi[1] = 40;
- }
if (NREV_LT(pi->pubpi.phy_rev, 7)) {
@@ -27447,37 +28038,36 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
if (NREV_GE(phyrev, 3)) {
if (PHY_IPA(pi)) {
u32 *tx_gaintbl =
- wlc_phy_get_ipa_gaintbl_nphy(pi);
+ wlc_phy_get_ipa_gaintbl_nphy(pi);
txgain = tx_gaintbl[txpi[core]];
} else {
if (CHSPEC_IS5G(pi->radio_chanspec)) {
if (NREV_IS(phyrev, 3)) {
txgain =
- nphy_tpc_5GHz_txgain_rev3
- [txpi[core]];
+ nphy_tpc_5GHz_txgain_rev3
+ [txpi[core]];
} else if (NREV_IS(phyrev, 4)) {
- txgain =
- (pi->srom_fem5g.extpagain ==
- 3) ?
- nphy_tpc_5GHz_txgain_HiPwrEPA
- [txpi[core]] :
- nphy_tpc_5GHz_txgain_rev4
- [txpi[core]];
+ txgain = (
+ pi->srom_fem5g.extpagain ==
+ 3) ?
+ nphy_tpc_5GHz_txgain_HiPwrEPA
+ [txpi[core]] :
+ nphy_tpc_5GHz_txgain_rev4
+ [txpi[core]];
} else {
txgain =
- nphy_tpc_5GHz_txgain_rev5
- [txpi[core]];
+ nphy_tpc_5GHz_txgain_rev5
+ [txpi[core]];
}
} else {
if (NREV_GE(phyrev, 5) &&
(pi->srom_fem2g.extpagain == 3)) {
txgain =
- nphy_tpc_txgain_HiPwrEPA
- [txpi[core]];
+ nphy_tpc_txgain_HiPwrEPA
+ [txpi[core]];
} else {
- txgain =
- nphy_tpc_txgain_rev3[txpi
- [core]];
+ txgain = nphy_tpc_txgain_rev3
+ [txpi[core]];
}
}
}
@@ -27497,12 +28087,12 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
- if (NREV_GE(phyrev, 3)) {
+ if (NREV_GE(phyrev, 3))
mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
0xa5), (0x1 << 8), (0x1 << 8));
- } else {
+ else
mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
- }
+
write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain);
wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
@@ -27562,9 +28152,8 @@ wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset,
{
u8 rate;
- for (rate = rate_start; rate <= rate_end; rate++) {
+ for (rate = rate_start; rate <= rate_end; rate++)
srom_max[rate] -= 2 * pwr_offset;
- }
}
void
@@ -27603,7 +28192,8 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
u16 pwr_offsets1[2], *pwr_offsets2 = NULL;
u8 *tx_srom_max_rate = NULL;
- for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
+ for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP);
+ band_num++) {
switch (band_num) {
case 0:
@@ -27619,7 +28209,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff);
pwr_offsets1[1] =
- (u16) (pi->ofdm2gpo >> 16) & 0xffff;
+ (u16) (pi->ofdm2gpo >> 16) & 0xffff;
pwr_offsets2 = pi->mcs2gpo;
@@ -27636,7 +28226,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff);
pwr_offsets1[1] =
- (u16) (pi->ofdm5gpo >> 16) & 0xffff;
+ (u16) (pi->ofdm5gpo >> 16) & 0xffff;
pwr_offsets2 = pi->mcs5gpo;
@@ -27653,7 +28243,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff);
pwr_offsets1[1] =
- (u16) (pi->ofdm5glpo >> 16) & 0xffff;
+ (u16) (pi->ofdm5glpo >> 16) & 0xffff;
pwr_offsets2 = pi->mcs5glpo;
@@ -27670,7 +28260,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff);
pwr_offsets1[1] =
- (u16) (pi->ofdm5ghpo >> 16) & 0xffff;
+ (u16) (pi->ofdm5ghpo >> 16) & 0xffff;
pwr_offsets2 = pi->mcs5ghpo;
@@ -27696,12 +28286,10 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
TXP_FIRST_MCS_20_CDD,
TXP_LAST_MCS_20_CDD);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
TXP_FIRST_MCS_20_CDD,
TXP_LAST_MCS_20_CDD);
- }
wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
TXP_FIRST_OFDM_20_CDD,
@@ -27713,13 +28301,11 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
TXP_FIRST_MCS_20_STBC,
TXP_LAST_MCS_20_STBC);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
tmp_stbcpo,
TXP_FIRST_MCS_20_STBC,
TXP_LAST_MCS_20_STBC);
- }
wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
&pwr_offsets2[2], tmp_max_pwr,
@@ -27773,294 +28359,26 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
} else {
for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 =
- TXP_FIRST_OFDM; rate1 <= TXP_LAST_MCS_40_SDM;
+ TXP_FIRST_OFDM;
+ rate1 <= TXP_LAST_MCS_40_SDM;
rate1++, rate2++)
tx_srom_max_rate[rate1] =
- tx_srom_max_rate[rate2];
+ tx_srom_max_rate[rate2];
}
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
tmp_bw40po,
TXP_FIRST_OFDM_40_SISO,
TXP_LAST_MCS_40_SDM);
- }
tx_srom_max_rate[TXP_MCS_32] =
- tx_srom_max_rate[TXP_FIRST_MCS_40_CDD];
+ tx_srom_max_rate[TXP_FIRST_MCS_40_CDD];
}
return;
}
-static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
-{
- u16 bw40po, cddpo, stbcpo, bwduppo;
- uint band_num;
-
- if (pi->sh->sromrev >= 9) {
-
- return;
- }
-
- bw40po = (u16) PHY_GETINTVAR(pi, "bw40po");
- pi->bw402gpo = bw40po & 0xf;
- pi->bw405gpo = (bw40po & 0xf0) >> 4;
- pi->bw405glpo = (bw40po & 0xf00) >> 8;
- pi->bw405ghpo = (bw40po & 0xf000) >> 12;
-
- cddpo = (u16) PHY_GETINTVAR(pi, "cddpo");
- pi->cdd2gpo = cddpo & 0xf;
- pi->cdd5gpo = (cddpo & 0xf0) >> 4;
- pi->cdd5glpo = (cddpo & 0xf00) >> 8;
- pi->cdd5ghpo = (cddpo & 0xf000) >> 12;
-
- stbcpo = (u16) PHY_GETINTVAR(pi, "stbcpo");
- pi->stbc2gpo = stbcpo & 0xf;
- pi->stbc5gpo = (stbcpo & 0xf0) >> 4;
- pi->stbc5glpo = (stbcpo & 0xf00) >> 8;
- pi->stbc5ghpo = (stbcpo & 0xf000) >> 12;
-
- bwduppo = (u16) PHY_GETINTVAR(pi, "bwduppo");
- pi->bwdup2gpo = bwduppo & 0xf;
- pi->bwdup5gpo = (bwduppo & 0xf0) >> 4;
- pi->bwdup5glpo = (bwduppo & 0xf00) >> 8;
- pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12;
-
- for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
- switch (band_num) {
- case 0:
-
- pi->nphy_txpid2g[PHY_CORE_0] =
- (u8) PHY_GETINTVAR(pi, "txpid2ga0");
- pi->nphy_txpid2g[PHY_CORE_1] =
- (u8) PHY_GETINTVAR(pi, "txpid2ga1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
- (s8) PHY_GETINTVAR(pi, "maxp2ga0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g =
- (s8) PHY_GETINTVAR(pi, "maxp2ga1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 =
- (s16) PHY_GETINTVAR(pi, "pa2gw0a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 =
- (s16) PHY_GETINTVAR(pi, "pa2gw0a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 =
- (s16) PHY_GETINTVAR(pi, "pa2gw1a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 =
- (s16) PHY_GETINTVAR(pi, "pa2gw1a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 =
- (s16) PHY_GETINTVAR(pi, "pa2gw2a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 =
- (s16) PHY_GETINTVAR(pi, "pa2gw2a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g =
- (s8) PHY_GETINTVAR(pi, "itt2ga0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g =
- (s8) PHY_GETINTVAR(pi, "itt2ga1");
-
- pi->cck2gpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
-
- pi->ofdm2gpo = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
-
- pi->mcs2gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
- pi->mcs2gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs2gpo1");
- pi->mcs2gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs2gpo2");
- pi->mcs2gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs2gpo3");
- pi->mcs2gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs2gpo4");
- pi->mcs2gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs2gpo5");
- pi->mcs2gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs2gpo6");
- pi->mcs2gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs2gpo7");
- break;
- case 1:
-
- pi->nphy_txpid5g[PHY_CORE_0] =
- (u8) PHY_GETINTVAR(pi, "txpid5ga0");
- pi->nphy_txpid5g[PHY_CORE_1] =
- (u8) PHY_GETINTVAR(pi, "txpid5ga1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
- (s8) PHY_GETINTVAR(pi, "maxp5ga0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
- (s8) PHY_GETINTVAR(pi, "maxp5ga1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5gw0a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5gw0a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5gw1a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5gw1a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5gw2a0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5gw2a1");
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm =
- (s8) PHY_GETINTVAR(pi, "itt5ga0");
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm =
- (s8) PHY_GETINTVAR(pi, "itt5ga1");
-
- pi->ofdm5gpo = (u32) PHY_GETINTVAR(pi, "ofdm5gpo");
-
- pi->mcs5gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs5gpo0");
- pi->mcs5gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs5gpo1");
- pi->mcs5gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs5gpo2");
- pi->mcs5gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs5gpo3");
- pi->mcs5gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs5gpo4");
- pi->mcs5gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs5gpo5");
- pi->mcs5gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs5gpo6");
- pi->mcs5gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs5gpo7");
- break;
- case 2:
-
- pi->nphy_txpid5gl[0] =
- (u8) PHY_GETINTVAR(pi, "txpid5gla0");
- pi->nphy_txpid5gl[1] =
- (u8) PHY_GETINTVAR(pi, "txpid5gla1");
- pi->nphy_pwrctrl_info[0].max_pwr_5gl =
- (s8) PHY_GETINTVAR(pi, "maxp5gla0");
- pi->nphy_pwrctrl_info[1].max_pwr_5gl =
- (s8) PHY_GETINTVAR(pi, "maxp5gla1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5glw0a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5glw0a1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5glw1a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5glw1a1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5glw2a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5glw2a1");
- pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0;
- pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0;
-
- pi->ofdm5glpo = (u32) PHY_GETINTVAR(pi, "ofdm5glpo");
-
- pi->mcs5glpo[0] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo0");
- pi->mcs5glpo[1] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo1");
- pi->mcs5glpo[2] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo2");
- pi->mcs5glpo[3] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo3");
- pi->mcs5glpo[4] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo4");
- pi->mcs5glpo[5] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo5");
- pi->mcs5glpo[6] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo6");
- pi->mcs5glpo[7] =
- (u16) PHY_GETINTVAR(pi, "mcs5glpo7");
- break;
- case 3:
-
- pi->nphy_txpid5gh[0] =
- (u8) PHY_GETINTVAR(pi, "txpid5gha0");
- pi->nphy_txpid5gh[1] =
- (u8) PHY_GETINTVAR(pi, "txpid5gha1");
- pi->nphy_pwrctrl_info[0].max_pwr_5gh =
- (s8) PHY_GETINTVAR(pi, "maxp5gha0");
- pi->nphy_pwrctrl_info[1].max_pwr_5gh =
- (s8) PHY_GETINTVAR(pi, "maxp5gha1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw0a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw0a1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw1a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw1a1");
- pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw2a0");
- pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 =
- (s16) PHY_GETINTVAR(pi, "pa5ghw2a1");
- pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0;
- pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0;
-
- pi->ofdm5ghpo = (u32) PHY_GETINTVAR(pi, "ofdm5ghpo");
-
- pi->mcs5ghpo[0] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo0");
- pi->mcs5ghpo[1] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo1");
- pi->mcs5ghpo[2] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo2");
- pi->mcs5ghpo[3] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo3");
- pi->mcs5ghpo[4] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo4");
- pi->mcs5ghpo[5] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo5");
- pi->mcs5ghpo[6] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo6");
- pi->mcs5ghpo[7] =
- (u16) PHY_GETINTVAR(pi, "mcs5ghpo7");
- break;
- }
- }
-
- wlc_phy_txpwr_apply_nphy(pi);
-}
-
-static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi)
-{
-
- pi->antswitch = (u8) PHY_GETINTVAR(pi, "antswitch");
- pi->aa2g = (u8) PHY_GETINTVAR(pi, "aa2g");
- pi->aa5g = (u8) PHY_GETINTVAR(pi, "aa5g");
-
- pi->srom_fem2g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos2g");
- pi->srom_fem2g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain2g");
- pi->srom_fem2g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange2g");
- pi->srom_fem2g.triso = (u8) PHY_GETINTVAR(pi, "triso2g");
- pi->srom_fem2g.antswctrllut = (u8) PHY_GETINTVAR(pi, "antswctl2g");
-
- pi->srom_fem5g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos5g");
- pi->srom_fem5g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain5g");
- pi->srom_fem5g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange5g");
- pi->srom_fem5g.triso = (u8) PHY_GETINTVAR(pi, "triso5g");
- if (PHY_GETVAR(pi, "antswctl5g")) {
-
- pi->srom_fem5g.antswctrllut =
- (u8) PHY_GETINTVAR(pi, "antswctl5g");
- } else {
-
- pi->srom_fem5g.antswctrllut =
- (u8) PHY_GETINTVAR(pi, "antswctl2g");
- }
-
- wlc_phy_txpower_ipa_upd(pi);
-
- pi->phy_txcore_disable_temp = (s16) PHY_GETINTVAR(pi, "tempthresh");
- if (pi->phy_txcore_disable_temp == 0) {
- pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
- }
-
- pi->phy_tempsense_offset = (s8) PHY_GETINTVAR(pi, "tempoffset");
- if (pi->phy_tempsense_offset != 0) {
- if (pi->phy_tempsense_offset >
- (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) {
- pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET;
- } else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT +
- NPHY_SROM_MINTEMPOFFSET)) {
- pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET;
- } else {
- pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT;
- }
- }
-
- pi->phy_txcore_enable_temp =
- pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP;
-
- pi->phycal_tempdelta = (u8) PHY_GETINTVAR(pi, "phycal_tempdelta");
- if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) {
- pi->phycal_tempdelta = 0;
- }
-
- wlc_phy_txpwr_srom_read_ppr_nphy(pi);
-
- return true;
-}
-
void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi)
{
u8 tx_pwr_ctrl_state;
@@ -28081,512 +28399,10 @@ void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi)
wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
}
-static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi)
-{
- u32 idx;
- u16 iqloCalbuf[7];
- u32 iqcomp, locomp, curr_locomp;
- s8 locomp_i, locomp_q;
- s8 curr_locomp_i, curr_locomp_q;
- u32 tbl_id, tbl_len, tbl_offset;
- u32 regval[128];
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf);
-
- tbl_len = 128;
- tbl_offset = 320;
- for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
- tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
- iqcomp =
- (tbl_id ==
- 26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) |
- (iqloCalbuf[1] & 0x3ff)
- : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) |
- (iqloCalbuf[3] & 0x3ff);
-
- for (idx = 0; idx < tbl_len; idx++) {
- regval[idx] = iqcomp;
- }
- wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
- regval);
- }
-
- tbl_offset = 448;
- for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
- tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
-
- locomp =
- (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]);
- locomp_i = (s8) ((locomp >> 8) & 0xff);
- locomp_q = (s8) ((locomp) & 0xff);
- for (idx = 0; idx < tbl_len; idx++) {
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- curr_locomp_i = locomp_i;
- curr_locomp_q = locomp_q;
- } else {
- curr_locomp_i = (s8) ((locomp_i *
- nphy_tpc_loscale[idx] +
- 128) >> 8);
- curr_locomp_q =
- (s8) ((locomp_q * nphy_tpc_loscale[idx] +
- 128) >> 8);
- }
- curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8);
- curr_locomp |= (u32) (curr_locomp_q & 0xff);
- regval[idx] = curr_locomp;
- }
- wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
- regval);
- }
-
- if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
- wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF);
- wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF);
- }
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi)
-{
- u8 core;
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MASTER, 0x5);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MUX, 0xe);
-
- if (pi->pubpi.radiorev != 5)
- WRITE_RADIO_REG3(pi, RADIO_2057, TX,
- core, TSSIA, 0);
-
- if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX,
- core, TSSIG, 0x1);
- } else {
-
- WRITE_RADIO_REG3(pi, RADIO_2057, TX,
- core, TSSIG, 0x31);
- }
- } else {
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MASTER, 0x9);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TX_SSI_MUX, 0xc);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
- TSSIG, 0);
-
- if (pi->pubpi.radiorev != 5) {
- if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
-
- WRITE_RADIO_REG3(pi, RADIO_2057,
- TX, core,
- TSSIA, 0x1);
- } else {
-
- WRITE_RADIO_REG3(pi, RADIO_2057,
- TX, core,
- TSSIA, 0x31);
- }
- }
- }
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
- 0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
- 0);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
- 0x3);
- WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
- 0x0);
- }
- } else {
- WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31,
- (CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 :
- 0x80);
- WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0);
- WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29);
-
- for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG,
- 0x0);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC,
- 0x0);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM,
- 0x3);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET,
- 0x0);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1,
- 0x8);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2,
- 0x0);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3,
- 0x0);
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TX_SSI_MASTER, 0x5);
-
- if (pi->pubpi.radiorev != 5)
- WRITE_RADIO_REG2(pi, RADIO_2056, TX,
- core, TSSIA, 0x0);
- if (NREV_GE(pi->pubpi.phy_rev, 5)) {
-
- WRITE_RADIO_REG2(pi, RADIO_2056, TX,
- core, TSSIG, 0x31);
- } else {
- WRITE_RADIO_REG2(pi, RADIO_2056, TX,
- core, TSSIG, 0x11);
- }
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TX_SSI_MUX, 0xe);
- } else {
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TX_SSI_MASTER, 0x9);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TSSIA, 0x31);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TSSIG, 0x0);
- WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
- TX_SSI_MUX, 0xc);
- }
- }
- }
-}
-
-static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi)
-{
- s32 rssi_buf[4];
- s32 int_val;
-
- if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi))
-
- return;
-
- if (PHY_IPA(pi)) {
- wlc_phy_ipa_internal_tssi_setup_nphy(pi);
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
- 0, 0x3, 0,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0);
- }
-
- wlc_phy_stopplayback_nphy(pi);
-
- wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false);
-
- udelay(20);
- int_val =
- wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf,
- 1);
- wlc_phy_stopplayback_nphy(pi);
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0);
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
- 0, 0x3, 1,
- NPHY_REV7_RFCTRLOVERRIDE_ID0);
- } else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1);
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
- (u8) ((int_val >> 24) & 0xff);
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
- (u8) ((int_val >> 24) & 0xff);
-
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
- (u8) ((int_val >> 8) & 0xff);
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
- (u8) ((int_val >> 8) & 0xff);
- } else {
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
- (u8) ((int_val >> 24) & 0xff);
-
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
- (u8) ((int_val >> 8) & 0xff);
-
- pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
- (u8) ((int_val >> 16) & 0xff);
- pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
- (u8) ((int_val) & 0xff);
- }
-
-}
-
-static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
-{
- u32 idx;
- s16 a1[2], b0[2], b1[2];
- s8 target_pwr_qtrdbm[2];
- s32 num, den, pwr_est;
- u8 chan_freq_range;
- u8 idle_tssi[2];
- u32 tbl_id, tbl_len, tbl_offset;
- u32 regval[64];
- u8 core;
-
- if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
- wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
- (void)R_REG(&pi->regs->maccontrol);
- udelay(1);
- }
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
- or_phy_reg(pi, 0x122, (0x1 << 0));
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15)));
- } else {
-
- or_phy_reg(pi, 0x1e7, (0x1 << 15));
- }
-
- if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
- wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
-
- if (pi->sh->sromrev < 4) {
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
- target_pwr_qtrdbm[0] = 13 * 4;
- target_pwr_qtrdbm[1] = 13 * 4;
- a1[0] = -424;
- a1[1] = -424;
- b0[0] = 5612;
- b0[1] = 5612;
- b1[1] = -1393;
- b1[0] = -1393;
- } else {
-
- chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
- switch (chan_freq_range) {
- case WL_CHAN_FREQ_RANGE_2G:
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
- target_pwr_qtrdbm[0] =
- pi->nphy_pwrctrl_info[0].max_pwr_2g;
- target_pwr_qtrdbm[1] =
- pi->nphy_pwrctrl_info[1].max_pwr_2g;
- a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1;
- a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1;
- b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0;
- b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0;
- b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1;
- b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1;
- break;
- case WL_CHAN_FREQ_RANGE_5GL:
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
- target_pwr_qtrdbm[0] =
- pi->nphy_pwrctrl_info[0].max_pwr_5gl;
- target_pwr_qtrdbm[1] =
- pi->nphy_pwrctrl_info[1].max_pwr_5gl;
- a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1;
- a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1;
- b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0;
- b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0;
- b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1;
- b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1;
- break;
- case WL_CHAN_FREQ_RANGE_5GM:
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
- target_pwr_qtrdbm[0] =
- pi->nphy_pwrctrl_info[0].max_pwr_5gm;
- target_pwr_qtrdbm[1] =
- pi->nphy_pwrctrl_info[1].max_pwr_5gm;
- a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1;
- a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1;
- b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0;
- b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0;
- b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1;
- b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1;
- break;
- case WL_CHAN_FREQ_RANGE_5GH:
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
- target_pwr_qtrdbm[0] =
- pi->nphy_pwrctrl_info[0].max_pwr_5gh;
- target_pwr_qtrdbm[1] =
- pi->nphy_pwrctrl_info[1].max_pwr_5gh;
- a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1;
- a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1;
- b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0;
- b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0;
- b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1;
- b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1;
- break;
- default:
- idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
- idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
- target_pwr_qtrdbm[0] = 13 * 4;
- target_pwr_qtrdbm[1] = 13 * 4;
- a1[0] = -424;
- a1[1] = -424;
- b0[0] = 5612;
- b0[1] = 5612;
- b1[1] = -1393;
- b1[0] = -1393;
- break;
- }
- }
-
- target_pwr_qtrdbm[0] = (s8) pi->tx_power_max;
- target_pwr_qtrdbm[1] = (s8) pi->tx_power_max;
-
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- if (pi->srom_fem2g.tssipos) {
- or_phy_reg(pi, 0x1e9, (0x1 << 14));
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- for (core = 0; core <= 1; core++) {
- if (PHY_IPA(pi)) {
-
- if (CHSPEC_IS2G(pi->radio_chanspec)) {
- WRITE_RADIO_REG3(pi, RADIO_2057,
- TX, core,
- TX_SSI_MUX,
- 0xe);
- } else {
- WRITE_RADIO_REG3(pi, RADIO_2057,
- TX, core,
- TX_SSI_MUX,
- 0xc);
- }
- } else {
- }
- }
- } else {
- if (PHY_IPA(pi)) {
-
- write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
- RADIO_2056_TX0,
- (CHSPEC_IS5G
- (pi->
- radio_chanspec)) ? 0xc : 0xe);
- write_radio_reg(pi,
- RADIO_2056_TX_TX_SSI_MUX |
- RADIO_2056_TX1,
- (CHSPEC_IS5G
- (pi->
- radio_chanspec)) ? 0xc : 0xe);
- } else {
-
- write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
- RADIO_2056_TX0, 0x11);
- write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
- RADIO_2056_TX1, 0x11);
- }
- }
- }
-
- if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
- wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
- (void)R_REG(&pi->regs->maccontrol);
- udelay(1);
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- mod_phy_reg(pi, 0x1e7, (0x7f << 0),
- (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
- } else {
- mod_phy_reg(pi, 0x1e7, (0x7f << 0),
- (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
- }
-
- if (NREV_GE(pi->pubpi.phy_rev, 7)) {
- mod_phy_reg(pi, 0x222, (0xff << 0),
- (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
- } else if (NREV_GT(pi->pubpi.phy_rev, 1)) {
- mod_phy_reg(pi, 0x222, (0xff << 0),
- (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
- }
-
- if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
- wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
-
- write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0));
-
- write_phy_reg(pi, 0x1e9,
- (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8));
-
- write_phy_reg(pi, 0x1ea,
- (target_pwr_qtrdbm[0] << 0) |
- (target_pwr_qtrdbm[1] << 8));
-
- tbl_len = 64;
- tbl_offset = 0;
- for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
- tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
-
- for (idx = 0; idx < tbl_len; idx++) {
- num =
- 8 * (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx);
- den = 32768 + a1[tbl_id - 26] * idx;
- pwr_est = max(((4 * num + den / 2) / den), -8);
- if (NREV_LT(pi->pubpi.phy_rev, 3)) {
- if (idx <=
- (uint) (31 - idle_tssi[tbl_id - 26] + 1))
- pwr_est =
- max(pwr_est,
- target_pwr_qtrdbm[tbl_id - 26] +
- 1);
- }
- regval[idx] = (u32) pwr_est;
- }
- wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
- regval);
- }
-
- wlc_phy_txpwr_limit_to_tbl_nphy(pi);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8,
- pi->adj_pwr_tbl_nphy);
- wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8,
- pi->adj_pwr_tbl_nphy);
-
- if (pi->phyhang_avoid)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi)
{
return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) |
- (0x1 << 14) | (0x1 << 13));
-}
-
-static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core)
-{
- u16 tmp;
- tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee));
-
- tmp = (tmp & (0x7f << 8)) >> 8;
- return (u8) tmp;
-}
-
-static void
-wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0, u8 idx1)
-{
- mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0);
-
- if (NREV_GT(pi->pubpi.phy_rev, 1))
- mod_phy_reg(pi, 0x222, (0xff << 0), idx1);
+ (0x1 << 14) | (0x1 << 13));
}
u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi)
@@ -28600,12 +28416,9 @@ u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi)
tmp = (pwr_idx[0] << 8) | pwr_idx[1];
} else {
- tmp =
- ((pi->nphy_txpwrindex[PHY_CORE_0].
- index_internal & 0xff) << 8) | (pi->
- nphy_txpwrindex
- [PHY_CORE_1].
- index_internal & 0xff);
+ tmp = ((pi->nphy_txpwrindex[PHY_CORE_0].index_internal & 0xff)
+ << 8) |
+ (pi->nphy_txpwrindex[PHY_CORE_1].index_internal & 0xff);
}
return tmp;
@@ -28618,13 +28431,12 @@ void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi)
|| (wlc_phy_txpwr_ison_nphy(pi)
&&
(((u32)
- ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) -
+ abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) -
pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4)
|| ((u32)
- ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) -
- pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) {
+ abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) -
+ pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4)))))
wlc_phy_a4(pi, true);
- }
}
void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
@@ -28655,32 +28467,29 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
for (core = 0; core < pi->pubpi.phy_corenum;
core++)
pi->nphy_txpwr_idx[core] =
- wlc_phy_txpwr_idx_cur_get_nphy(pi,
- (u8)
- core);
+ wlc_phy_txpwr_idx_cur_get_nphy(
+ pi,
+ (u8) core);
}
}
tbl_len = 84;
tbl_offset = 64;
- for (ctr = 0; ctr < tbl_len; ctr++) {
+ for (ctr = 0; ctr < tbl_len; ctr++)
regval[ctr] = 0;
- }
wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16,
regval);
wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16,
regval);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
and_phy_reg(pi, 0x1e7,
(u16) (~((0x1 << 15) |
- (0x1 << 14) | (0x1 << 13))));
- } else {
+ (0x1 << 14) | (0x1 << 13))));
+ else
and_phy_reg(pi, 0x1e7,
(u16) (~((0x1 << 14) | (0x1 << 13))));
- }
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
or_phy_reg(pi, 0x8f, (0x1 << 8));
@@ -28694,7 +28503,8 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
else if (NREV_LT(pi->pubpi.phy_rev, 2))
mod_phy_reg(pi, 0xdc, 0x00ff, 0x5a);
- if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
+ if (NREV_LT(pi->pubpi.phy_rev, 2) &&
+ pi->bw == WL_CHANSPEC_BW_40)
wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
MHF1_IQSWAP_WAR, BRCM_BAND_ALL);
@@ -28730,7 +28540,7 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
if ((pi->nphy_txpwr_idx[0] != 128)
- && (pi->nphy_txpwr_idx[1] != 128)) {
+ && (pi->nphy_txpwr_idx[1] != 128))
wlc_phy_txpwr_idx_cur_set_nphy(pi,
pi->
nphy_txpwr_idx
@@ -28738,7 +28548,6 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
pi->
nphy_txpwr_idx
[1]);
- }
}
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
@@ -28753,7 +28562,8 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
else if (NREV_LT(pi->pubpi.phy_rev, 2))
mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
- if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
+ if (NREV_LT(pi->pubpi.phy_rev, 2) &&
+ pi->bw == WL_CHANSPEC_BW_40)
wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
0x0, BRCM_BAND_ALL);
@@ -28799,17 +28609,14 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
for (core = 0; core < pi->pubpi.phy_corenum; core++) {
- if ((core_mask & (1 << core)) == 0) {
+ if ((core_mask & (1 << core)) == 0)
continue;
- }
txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27;
if (txpwrindex < 0) {
- if (pi->nphy_txpwrindex[core].index < 0) {
-
+ if (pi->nphy_txpwrindex[core].index < 0)
continue;
- }
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
mod_phy_reg(pi, 0x8f,
@@ -28842,29 +28649,21 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
if (restore_cals) {
-
- wlc_phy_table_write_nphy(pi, 15, 2,
- (80 + 2 * core), 16,
- (void *)&pi->
- nphy_txpwrindex[core].
- iqcomp_a);
-
- wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
- 16,
- &pi->
- nphy_txpwrindex[core].
- locomp);
- wlc_phy_table_write_nphy(pi, 15, 1, (93 + core),
- 16,
- (void *)&pi->
- nphy_txpwrindex[core].
- locomp);
+ wlc_phy_table_write_nphy(
+ pi, 15, 2, (80 + 2 * core), 16,
+ &pi->nphy_txpwrindex[core].iqcomp_a);
+ wlc_phy_table_write_nphy(
+ pi, 15, 1, (85 + core), 16,
+ &pi->nphy_txpwrindex[core].locomp);
+ wlc_phy_table_write_nphy(
+ pi, 15, 1, (93 + core), 16,
+ &pi->nphy_txpwrindex[core].locomp);
}
wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
pi->nphy_txpwrindex[core].index_internal =
- pi->nphy_txpwrindex[core].index_internal_save;
+ pi->nphy_txpwrindex[core].index_internal_save;
} else {
if (pi->nphy_txpwrindex[core].index < 0) {
@@ -28879,14 +28678,13 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
AfectrlOverride);
} else {
pi->nphy_txpwrindex[core].
- AfectrlOverride =
- read_phy_reg(pi, 0xa5);
+ AfectrlOverride =
+ read_phy_reg(pi, 0xa5);
}
pi->nphy_txpwrindex[core].AfeCtrlDacGain =
- read_phy_reg(pi,
- (core ==
- PHY_CORE_0) ? 0xaa : 0xab);
+ read_phy_reg(pi, (core == PHY_CORE_0) ?
+ 0xaa : 0xab);
wlc_phy_table_read_nphy(pi, 7, 1,
(0x110 + core), 16,
@@ -28898,23 +28696,23 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
&tmpval);
tmpval >>= ((core == PHY_CORE_0) ? 8 : 0);
tmpval &= 0xff;
- pi->nphy_txpwrindex[core].bbmult =
- (u8) tmpval;
+ pi->nphy_txpwrindex[core].bbmult = (u8) tmpval;
wlc_phy_table_read_nphy(pi, 15, 2,
(80 + 2 * core), 16,
- (void *)&pi->
+ &pi->
nphy_txpwrindex[core].
iqcomp_a);
wlc_phy_table_read_nphy(pi, 15, 1, (85 + core),
16,
- (void *)&pi->
+ &pi->
nphy_txpwrindex[core].
locomp);
pi->nphy_txpwrindex[core].index_internal_save =
- pi->nphy_txpwrindex[core].index_internal;
+ pi->nphy_txpwrindex[core].
+ index_internal;
}
tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
@@ -28927,22 +28725,22 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
(tx_ind0 + txpwrindex), 32,
&txgain);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
- rad_gain =
- (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
- } else {
- rad_gain =
- (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
- }
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
+ rad_gain = (txgain >> 16) &
+ ((1 << (32 - 16 + 1)) - 1);
+ else
+ rad_gain = (txgain >> 16) &
+ ((1 << (28 - 16 + 1)) - 1);
+
dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
- if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+ if (NREV_GE(pi->pubpi.phy_rev, 3))
mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
0xa5), (0x1 << 8), (0x1 << 8));
- } else {
+ else
mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
- }
+
write_phy_reg(pi, (core == PHY_CORE_0) ?
0xaa : 0xab, dac_gain);
@@ -28951,9 +28749,8 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
- m1m2 |=
- ((core ==
- PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
+ m1m2 |= ((core == PHY_CORE_0) ?
+ (bbmult << 8) : (bbmult << 0));
wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
@@ -28974,23 +28771,20 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
(lo_ind0 + txpwrindex), 32,
&locomp);
- if (restore_cals) {
+ if (restore_cals)
wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
16, &locomp);
- }
if (NREV_IS(pi->pubpi.phy_rev, 1))
wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
if (PHY_IPA(pi)) {
wlc_phy_table_read_nphy(pi,
- (core ==
- PHY_CORE_0 ?
- NPHY_TBL_ID_CORE1TXPWRCTL
- :
- NPHY_TBL_ID_CORE2TXPWRCTL),
- 1, 576 + txpwrindex, 32,
- &rfpwr_offset);
+ (core == PHY_CORE_0 ?
+ NPHY_TBL_ID_CORE1TXPWRCTL :
+ NPHY_TBL_ID_CORE2TXPWRCTL),
+ 1, 576 + txpwrindex, 32,
+ &rfpwr_offset);
mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
0x29b, (0x1ff << 4),
@@ -29046,7 +28840,7 @@ void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable)
if (enable) {
if (pi->nphy_deaf_count == 0) {
pi->classifier_state =
- wlc_phy_classifier_nphy(pi, 0, 0);
+ wlc_phy_classifier_nphy(pi, 0, 0);
wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
wlc_phy_clip_det_nphy(pi, 0, pi->clip_state);
wlc_phy_clip_det_nphy(pi, 1, clip_off);
@@ -29074,9 +28868,9 @@ void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode)
if (mode) {
if (pi->nphy_deaf_count == 0)
wlc_phy_stay_in_carriersearch_nphy(pi, true);
- } else {
- if (pi->nphy_deaf_count > 0)
- wlc_phy_stay_in_carriersearch_nphy(pi, false);
+ } else if (pi->nphy_deaf_count > 0) {
+ wlc_phy_stay_in_carriersearch_nphy(pi, false);
}
+
wlapi_enable_mac(pi->sh->physhim);
}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c
index 01ff0c8eb4b9..faf1ebe76068 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c
@@ -17,89 +17,95 @@
#include "phy_qmath.h"
/*
-Description: This function make 16 bit unsigned multiplication. To fit the output into
-16 bits the 32 bit multiplication result is right shifted by 16 bits.
-*/
+ * Description: This function make 16 bit unsigned multiplication.
+ * To fit the output into 16 bits the 32 bit multiplication result is right
+ * shifted by 16 bits.
+ */
u16 qm_mulu16(u16 op1, u16 op2)
{
return (u16) (((u32) op1 * (u32) op2) >> 16);
}
/*
-Description: This function make 16 bit multiplication and return the result in 16 bits.
-To fit the multiplication result into 16 bits the multiplication result is right shifted by
-15 bits. Right shifting 15 bits instead of 16 bits is done to remove the extra sign bit formed
-due to the multiplication.
-When both the 16bit inputs are 0x8000 then the output is saturated to 0x7fffffff.
-*/
+ * Description: This function make 16 bit multiplication and return the result
+ * in 16 bits. To fit the multiplication result into 16 bits the multiplication
+ * result is right shifted by 15 bits. Right shifting 15 bits instead of 16 bits
+ * is done to remove the extra sign bit formed due to the multiplication.
+ * When both the 16bit inputs are 0x8000 then the output is saturated to
+ * 0x7fffffff.
+ */
s16 qm_muls16(s16 op1, s16 op2)
{
s32 result;
- if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000) {
+ if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000)
result = 0x7fffffff;
- } else {
+ else
result = ((s32) (op1) * (s32) (op2));
- }
+
return (s16) (result >> 15);
}
/*
-Description: This function add two 32 bit numbers and return the 32bit result.
-If the result overflow 32 bits, the output will be saturated to 32bits.
-*/
+ * Description: This function add two 32 bit numbers and return the 32bit
+ * result. If the result overflow 32 bits, the output will be saturated to
+ * 32bits.
+ */
s32 qm_add32(s32 op1, s32 op2)
{
s32 result;
result = op1 + op2;
- if (op1 < 0 && op2 < 0 && result > 0) {
+ if (op1 < 0 && op2 < 0 && result > 0)
result = 0x80000000;
- } else if (op1 > 0 && op2 > 0 && result < 0) {
+ else if (op1 > 0 && op2 > 0 && result < 0)
result = 0x7fffffff;
- }
+
return result;
}
/*
-Description: This function add two 16 bit numbers and return the 16bit result.
-If the result overflow 16 bits, the output will be saturated to 16bits.
-*/
+ * Description: This function add two 16 bit numbers and return the 16bit
+ * result. If the result overflow 16 bits, the output will be saturated to
+ * 16bits.
+ */
s16 qm_add16(s16 op1, s16 op2)
{
s16 result;
s32 temp = (s32) op1 + (s32) op2;
- if (temp > (s32) 0x7fff) {
+ if (temp > (s32) 0x7fff)
result = (s16) 0x7fff;
- } else if (temp < (s32) 0xffff8000) {
+ else if (temp < (s32) 0xffff8000)
result = (s16) 0xffff8000;
- } else {
+ else
result = (s16) temp;
- }
+
return result;
}
/*
-Description: This function make 16 bit subtraction and return the 16bit result.
-If the result overflow 16 bits, the output will be saturated to 16bits.
-*/
+ * Description: This function make 16 bit subtraction and return the 16bit
+ * result. If the result overflow 16 bits, the output will be saturated to
+ * 16bits.
+ */
s16 qm_sub16(s16 op1, s16 op2)
{
s16 result;
s32 temp = (s32) op1 - (s32) op2;
- if (temp > (s32) 0x7fff) {
+ if (temp > (s32) 0x7fff)
result = (s16) 0x7fff;
- } else if (temp < (s32) 0xffff8000) {
+ else if (temp < (s32) 0xffff8000)
result = (s16) 0xffff8000;
- } else {
+ else
result = (s16) temp;
- }
+
return result;
}
/*
-Description: This function make a 32 bit saturated left shift when the specified shift
-is +ve. This function will make a 32 bit right shift when the specified shift is -ve.
-This function return the result after shifting operation.
-*/
+ * Description: This function make a 32 bit saturated left shift when the
+ * specified shift is +ve. This function will make a 32 bit right shift when
+ * the specified shift is -ve. This function return the result after shifting
+ * operation.
+ */
s32 qm_shl32(s32 op, int shift)
{
int i;
@@ -110,20 +116,21 @@ s32 qm_shl32(s32 op, int shift)
else if (shift < -31)
shift = -31;
if (shift >= 0) {
- for (i = 0; i < shift; i++) {
+ for (i = 0; i < shift; i++)
result = qm_add32(result, result);
- }
} else {
result = result >> (-shift);
}
+
return result;
}
/*
-Description: This function make a 16 bit saturated left shift when the specified shift
-is +ve. This function will make a 16 bit right shift when the specified shift is -ve.
-This function return the result after shifting operation.
-*/
+ * Description: This function make a 16 bit saturated left shift when the
+ * specified shift is +ve. This function will make a 16 bit right shift when
+ * the specified shift is -ve. This function return the result after shifting
+ * operation.
+ */
s16 qm_shl16(s16 op, int shift)
{
int i;
@@ -134,29 +141,29 @@ s16 qm_shl16(s16 op, int shift)
else if (shift < -15)
shift = -15;
if (shift > 0) {
- for (i = 0; i < shift; i++) {
+ for (i = 0; i < shift; i++)
result = qm_add16(result, result);
- }
} else {
result = result >> (-shift);
}
+
return result;
}
/*
-Description: This function make a 16 bit right shift when shift is +ve.
-This function make a 16 bit saturated left shift when shift is -ve. This function
-return the result of the shift operation.
-*/
+ * Description: This function make a 16 bit right shift when shift is +ve.
+ * This function make a 16 bit saturated left shift when shift is -ve. This
+ * function return the result of the shift operation.
+ */
s16 qm_shr16(s16 op, int shift)
{
return qm_shl16(op, -shift);
}
/*
-Description: This function return the number of redundant sign bits in a 32 bit number.
-Example: qm_norm32(0x00000080) = 23
-*/
+ * Description: This function return the number of redundant sign bits in a
+ * 32 bit number. Example: qm_norm32(0x00000080) = 23
+ */
s16 qm_norm32(s32 op)
{
u16 u16extraSignBits;
@@ -208,28 +215,30 @@ static const s16 log_table[] = {
32024
};
-#define LOG_TABLE_SIZE 32 /* log_table size */
-#define LOG2_LOG_TABLE_SIZE 5 /* log2(log_table size) */
-#define Q_LOG_TABLE 15 /* qformat of log_table */
-#define LOG10_2 19728 /* log10(2) in q.16 */
+#define LOG_TABLE_SIZE 32 /* log_table size */
+#define LOG2_LOG_TABLE_SIZE 5 /* log2(log_table size) */
+#define Q_LOG_TABLE 15 /* qformat of log_table */
+#define LOG10_2 19728 /* log10(2) in q.16 */
/*
-Description:
-This routine takes the input number N and its q format qN and compute
-the log10(N). This routine first normalizes the input no N. Then N is in mag*(2^x) format.
-mag is any number in the range 2^30-(2^31 - 1). Then log2(mag * 2^x) = log2(mag) + x is computed.
-From that log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed.
-This routine looks the log2 value in the table considering LOG2_LOG_TABLE_SIZE+1 MSBs.
-As the MSB is always 1, only next LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup.
-Next 16 MSBs are used for interpolation.
-Inputs:
-N - number to which log10 has to be found.
-qN - q format of N
-log10N - address where log10(N) will be written.
-qLog10N - address where log10N qformat will be written.
-Note/Problem:
-For accurate results input should be in normalized or near normalized form.
-*/
+ * Description:
+ * This routine takes the input number N and its q format qN and compute
+ * the log10(N). This routine first normalizes the input no N. Then N is in
+ * mag*(2^x) format. mag is any number in the range 2^30-(2^31 - 1).
+ * Then log2(mag * 2^x) = log2(mag) + x is computed. From that
+ * log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed.
+ * This routine looks the log2 value in the table considering
+ * LOG2_LOG_TABLE_SIZE+1 MSBs. As the MSB is always 1, only next
+ * LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup. Next 16 MSBs are used
+ * for interpolation.
+ * Inputs:
+ * N - number to which log10 has to be found.
+ * qN - q format of N
+ * log10N - address where log10(N) will be written.
+ * qLog10N - address where log10N qformat will be written.
+ * Note/Problem:
+ * For accurate results input should be in normalized or near normalized form.
+ */
void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
{
s16 s16norm, s16tableIndex, s16errorApproximation;
@@ -248,12 +257,13 @@ void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
*/
qN = qN + s16norm - 30;
- /* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the MSB */
+ /* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the
+ * MSB */
s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE)));
/* remove the MSB. the MSB is always 1 after normalization. */
s16tableIndex =
- s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1);
+ s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1);
/* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */
N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1);
@@ -263,23 +273,27 @@ void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16)));
/* look the log value in the table. */
- s32log = log_table[s16tableIndex]; /* q.15 format */
+ s32log = log_table[s16tableIndex]; /* q.15 format */
- /* interpolate using the offset. */
- s16errorApproximation = (s16) qm_mulu16(u16offset, (u16) (log_table[s16tableIndex + 1] - log_table[s16tableIndex])); /* q.15 */
+ /* interpolate using the offset. q.15 format. */
+ s16errorApproximation = (s16) qm_mulu16(u16offset,
+ (u16) (log_table[s16tableIndex + 1] -
+ log_table[s16tableIndex]));
- s32log = qm_add16((s16) s32log, s16errorApproximation); /* q.15 format */
+ /* q.15 format */
+ s32log = qm_add16((s16) s32log, s16errorApproximation);
/* adjust for the qformat of the N as
* log2(mag * 2^x) = log2(mag) + x
*/
- s32log = qm_add32(s32log, ((s32) -qN) << 15); /* q.15 format */
+ s32log = qm_add32(s32log, ((s32) -qN) << 15); /* q.15 format */
/* normalize the result. */
s16norm = qm_norm32(s32log);
/* bring all the important bits into lower 16 bits */
- s32log = qm_shl32(s32log, s16norm - 16); /* q.15+s16norm-16 format */
+ /* q.15+s16norm-16 format */
+ s32log = qm_shl32(s32log, s16norm - 16);
/* compute the log10(N) by multiplying log2(N) with log10(2).
* as log10(mag * 2^x) = log2(mag * 2^x) * log10(2)
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h
index 20e3783f921b..20e3783f921b 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_radio.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h
index c3a675455ff5..c3a675455ff5 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_radio.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phyreg_n.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h
index a97c3a799479..a97c3a799479 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phyreg_n.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
index 023d05aa97ad..622c01ca72c5 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
@@ -17,7 +17,7 @@
#include <types.h>
#include "phytbl_lcn.h"
-const u32 dot11lcn_gain_tbl_rev0[] = {
+static const u32 dot11lcn_gain_tbl_rev0[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -116,7 +116,7 @@ const u32 dot11lcn_gain_tbl_rev0[] = {
0x00000000,
};
-const u32 dot11lcn_gain_tbl_rev1[] = {
+static const u32 dot11lcn_gain_tbl_rev1[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -215,7 +215,7 @@ const u32 dot11lcn_gain_tbl_rev1[] = {
0x00000000,
};
-const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
+static const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
0x0401,
0x0402,
0x0403,
@@ -256,7 +256,7 @@ const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
0x0000,
};
-const u32 dot11lcn_gain_idx_tbl_rev0[] = {
+static const u32 dot11lcn_gain_idx_tbl_rev0[] = {
0x00000000,
0x00000000,
0x10000000,
@@ -407,7 +407,7 @@ const u32 dot11lcn_gain_idx_tbl_rev0[] = {
0x0000001c,
};
-const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
+static const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
0x0000,
0x0000,
0x0000,
@@ -448,7 +448,7 @@ const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
0x0000
};
-const u8 dot11lcn_gain_val_tbl_2G[] = {
+static const u8 dot11lcn_gain_val_tbl_2G[] = {
0xfc,
0x02,
0x08,
@@ -519,7 +519,7 @@ const u8 dot11lcn_gain_val_tbl_2G[] = {
0x00
};
-const u32 dot11lcn_gain_idx_tbl_2G[] = {
+static const u32 dot11lcn_gain_idx_tbl_2G[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -674,7 +674,7 @@ const u32 dot11lcn_gain_idx_tbl_2G[] = {
0x00000000
};
-const u32 dot11lcn_gain_tbl_2G[] = {
+static const u32 dot11lcn_gain_tbl_2G[] = {
0x00000000,
0x00000004,
0x00000008,
@@ -773,7 +773,7 @@ const u32 dot11lcn_gain_tbl_2G[] = {
0x00000000
};
-const u32 dot11lcn_gain_tbl_extlna_2G[] = {
+static const u32 dot11lcn_gain_tbl_extlna_2G[] = {
0x00000000,
0x00000004,
0x00000008,
@@ -872,7 +872,7 @@ const u32 dot11lcn_gain_tbl_extlna_2G[] = {
0x00000000
};
-const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
+static const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
0x0400,
0x0400,
0x0400,
@@ -913,7 +913,7 @@ const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
0x0000
};
-const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
+static const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
0xfc,
0x02,
0x08,
@@ -984,7 +984,7 @@ const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
0x00
};
-const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
+static const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
0x00000000,
0x00000040,
0x00000000,
@@ -1139,7 +1139,7 @@ const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
0x00000000
};
-const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
+static const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
0x0000,
0x0000,
0x0000,
@@ -1180,7 +1180,7 @@ const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
0x0000
};
-const u32 dot11lcn_gain_val_tbl_5G[] = {
+static const u32 dot11lcn_gain_val_tbl_5G[] = {
0xf7,
0xfd,
0x00,
@@ -1251,7 +1251,7 @@ const u32 dot11lcn_gain_val_tbl_5G[] = {
0x00
};
-const u32 dot11lcn_gain_idx_tbl_5G[] = {
+static const u32 dot11lcn_gain_idx_tbl_5G[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -1406,7 +1406,7 @@ const u32 dot11lcn_gain_idx_tbl_5G[] = {
0x00000000
};
-const u32 dot11lcn_gain_tbl_5G[] = {
+static const u32 dot11lcn_gain_tbl_5G[] = {
0x00000000,
0x00000040,
0x00000080,
@@ -1520,7 +1520,7 @@ const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[] = {
,
};
-const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev1[] = {
+static const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev1[] = {
{&dot11lcn_gain_tbl_rev1,
sizeof(dot11lcn_gain_tbl_rev1) / sizeof(dot11lcn_gain_tbl_rev1[0]), 18,
0, 32}
@@ -1611,10 +1611,6 @@ const u32 dot11lcnphytbl_rx_gain_info_sz_rev0 =
sizeof(dot11lcnphytbl_rx_gain_info_rev0) /
sizeof(dot11lcnphytbl_rx_gain_info_rev0[0]);
-const u32 dot11lcnphytbl_rx_gain_info_sz_rev1 =
- sizeof(dot11lcnphytbl_rx_gain_info_rev1) /
- sizeof(dot11lcnphytbl_rx_gain_info_rev1[0]);
-
const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz =
sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2) /
sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2[0]);
@@ -1623,7 +1619,7 @@ const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz =
sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2) /
sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2[0]);
-const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
+static const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
0x014d,
0x014d,
0x014d,
@@ -1690,7 +1686,7 @@ const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
0x014d,
};
-const u16 dot11lcn_noise_scale_tbl_rev0[] = {
+static const u16 dot11lcn_noise_scale_tbl_rev0[] = {
0x0000,
0x0000,
0x0000,
@@ -1757,7 +1753,7 @@ const u16 dot11lcn_noise_scale_tbl_rev0[] = {
0x0000,
};
-const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = {
+static const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = {
0x000141f8,
0x000021f8,
0x000021fb,
@@ -1770,7 +1766,7 @@ const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = {
0x0000024b,
};
-const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
+static const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
0x00100001,
0x00200010,
0x00300001,
@@ -1793,7 +1789,7 @@ const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
0x00600f22,
};
-const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
+static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
0x0007,
0x0005,
0x0006,
@@ -1861,7 +1857,7 @@ const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
};
-const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
+static const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
0x0007,
0x0005,
0x0002,
@@ -1928,7 +1924,7 @@ const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
0x0002,
};
-const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
+static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
0x0002,
0x0008,
0x0004,
@@ -1995,7 +1991,7 @@ const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
0x0001,
};
-const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
+static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
0x000a,
0x0009,
0x0006,
@@ -2062,7 +2058,7 @@ const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
0x0005,
};
-const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
+static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
0x0004,
0x0004,
0x0002,
@@ -2129,7 +2125,7 @@ const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
0x0002,
};
-const u8 dot11lcn_nf_table_rev0[] = {
+static const u8 dot11lcn_nf_table_rev0[] = {
0x5f,
0x36,
0x29,
@@ -2148,7 +2144,7 @@ const u8 dot11lcn_nf_table_rev0[] = {
0x1f,
};
-const u8 dot11lcn_gain_val_tbl_rev0[] = {
+static const u8 dot11lcn_gain_val_tbl_rev0[] = {
0x09,
0x0f,
0x14,
@@ -2211,7 +2207,7 @@ const u8 dot11lcn_gain_val_tbl_rev0[] = {
0x00,
};
-const u8 dot11lcn_spur_tbl_rev0[] = {
+static const u8 dot11lcn_spur_tbl_rev0[] = {
0x01,
0x01,
0x01,
@@ -2342,7 +2338,7 @@ const u8 dot11lcn_spur_tbl_rev0[] = {
0x01,
};
-const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
+static const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
0x001a,
0x0034,
0x004e,
@@ -2499,7 +2495,7 @@ const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
0x06f6,
};
-const u16 dot11lcn_iq_local_tbl_rev0[] = {
+static const u16 dot11lcn_iq_local_tbl_rev0[] = {
0x0200,
0x0300,
0x0400,
@@ -2610,7 +2606,7 @@ const u16 dot11lcn_iq_local_tbl_rev0[] = {
0x0000,
};
-const u32 dot11lcn_papd_compdelta_tbl_rev0[] = {
+static const u32 dot11lcn_papd_compdelta_tbl_rev0[] = {
0x00080000,
0x00080000,
0x00080000,
@@ -2834,26 +2830,26 @@ const struct phytbl_info dot11lcnphytbl_info_rev0[] = {
const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = {
&dot11lcn_sw_ctrl_tbl_4313_rev0,
- sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) /
- sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) /
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
};
const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa = {
&dot11lcn_sw_ctrl_tbl_4313_epa_rev0,
- sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) /
- sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) /
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16
};
const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = {
&dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo,
- sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) /
- sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) /
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16
};
const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = {
&dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0,
- sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) /
- sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) /
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16
};
const u32 dot11lcnphytbl_info_sz_rev0 =
@@ -2861,778 +2857,394 @@ const u32 dot11lcnphytbl_info_sz_rev0 =
const struct lcnphy_tx_gain_tbl_entry
dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = {
- {3, 0, 31, 0, 72,}
- ,
- {3, 0, 31, 0, 70,}
- ,
- {3, 0, 31, 0, 68,}
- ,
- {3, 0, 30, 0, 67,}
- ,
- {3, 0, 29, 0, 68,}
- ,
- {3, 0, 28, 0, 68,}
- ,
- {3, 0, 27, 0, 69,}
- ,
- {3, 0, 26, 0, 70,}
- ,
- {3, 0, 25, 0, 70,}
- ,
- {3, 0, 24, 0, 71,}
- ,
- {3, 0, 23, 0, 72,}
- ,
- {3, 0, 23, 0, 70,}
- ,
- {3, 0, 22, 0, 71,}
- ,
- {3, 0, 21, 0, 72,}
- ,
- {3, 0, 21, 0, 70,}
- ,
- {3, 0, 21, 0, 68,}
- ,
- {3, 0, 21, 0, 66,}
- ,
- {3, 0, 21, 0, 64,}
- ,
- {3, 0, 21, 0, 63,}
- ,
- {3, 0, 20, 0, 64,}
- ,
- {3, 0, 19, 0, 65,}
- ,
- {3, 0, 19, 0, 64,}
- ,
- {3, 0, 18, 0, 65,}
- ,
- {3, 0, 18, 0, 64,}
- ,
- {3, 0, 17, 0, 65,}
- ,
- {3, 0, 17, 0, 64,}
- ,
- {3, 0, 16, 0, 65,}
- ,
- {3, 0, 16, 0, 64,}
- ,
- {3, 0, 16, 0, 62,}
- ,
- {3, 0, 16, 0, 60,}
- ,
- {3, 0, 16, 0, 58,}
- ,
- {3, 0, 15, 0, 61,}
- ,
- {3, 0, 15, 0, 59,}
- ,
- {3, 0, 14, 0, 61,}
- ,
- {3, 0, 14, 0, 60,}
- ,
- {3, 0, 14, 0, 58,}
- ,
- {3, 0, 13, 0, 60,}
- ,
- {3, 0, 13, 0, 59,}
- ,
- {3, 0, 12, 0, 62,}
- ,
- {3, 0, 12, 0, 60,}
- ,
- {3, 0, 12, 0, 58,}
- ,
- {3, 0, 11, 0, 62,}
- ,
- {3, 0, 11, 0, 60,}
- ,
- {3, 0, 11, 0, 59,}
- ,
- {3, 0, 11, 0, 57,}
- ,
- {3, 0, 10, 0, 61,}
- ,
- {3, 0, 10, 0, 59,}
- ,
- {3, 0, 10, 0, 57,}
- ,
- {3, 0, 9, 0, 62,}
- ,
- {3, 0, 9, 0, 60,}
- ,
- {3, 0, 9, 0, 58,}
- ,
- {3, 0, 9, 0, 57,}
- ,
- {3, 0, 8, 0, 62,}
- ,
- {3, 0, 8, 0, 60,}
- ,
- {3, 0, 8, 0, 58,}
- ,
- {3, 0, 8, 0, 57,}
- ,
- {3, 0, 8, 0, 55,}
- ,
- {3, 0, 7, 0, 61,}
- ,
- {3, 0, 7, 0, 60,}
- ,
- {3, 0, 7, 0, 58,}
- ,
- {3, 0, 7, 0, 56,}
- ,
- {3, 0, 7, 0, 55,}
- ,
- {3, 0, 6, 0, 62,}
- ,
- {3, 0, 6, 0, 60,}
- ,
- {3, 0, 6, 0, 58,}
- ,
- {3, 0, 6, 0, 57,}
- ,
- {3, 0, 6, 0, 55,}
- ,
- {3, 0, 6, 0, 54,}
- ,
- {3, 0, 6, 0, 52,}
- ,
- {3, 0, 5, 0, 61,}
- ,
- {3, 0, 5, 0, 59,}
- ,
- {3, 0, 5, 0, 57,}
- ,
- {3, 0, 5, 0, 56,}
- ,
- {3, 0, 5, 0, 54,}
- ,
- {3, 0, 5, 0, 53,}
- ,
- {3, 0, 5, 0, 51,}
- ,
- {3, 0, 4, 0, 62,}
- ,
- {3, 0, 4, 0, 60,}
- ,
- {3, 0, 4, 0, 58,}
- ,
- {3, 0, 4, 0, 57,}
- ,
- {3, 0, 4, 0, 55,}
- ,
- {3, 0, 4, 0, 54,}
- ,
- {3, 0, 4, 0, 52,}
- ,
- {3, 0, 4, 0, 51,}
- ,
- {3, 0, 4, 0, 49,}
- ,
- {3, 0, 4, 0, 48,}
- ,
- {3, 0, 4, 0, 46,}
- ,
- {3, 0, 3, 0, 60,}
- ,
- {3, 0, 3, 0, 58,}
- ,
- {3, 0, 3, 0, 57,}
- ,
- {3, 0, 3, 0, 55,}
- ,
- {3, 0, 3, 0, 54,}
- ,
- {3, 0, 3, 0, 52,}
- ,
- {3, 0, 3, 0, 51,}
- ,
- {3, 0, 3, 0, 49,}
- ,
- {3, 0, 3, 0, 48,}
- ,
- {3, 0, 3, 0, 46,}
- ,
- {3, 0, 3, 0, 45,}
- ,
- {3, 0, 3, 0, 44,}
- ,
- {3, 0, 3, 0, 43,}
- ,
- {3, 0, 3, 0, 41,}
- ,
- {3, 0, 2, 0, 61,}
- ,
- {3, 0, 2, 0, 59,}
- ,
- {3, 0, 2, 0, 57,}
- ,
- {3, 0, 2, 0, 56,}
- ,
- {3, 0, 2, 0, 54,}
- ,
- {3, 0, 2, 0, 53,}
- ,
- {3, 0, 2, 0, 51,}
- ,
- {3, 0, 2, 0, 50,}
- ,
- {3, 0, 2, 0, 48,}
- ,
- {3, 0, 2, 0, 47,}
- ,
- {3, 0, 2, 0, 46,}
- ,
- {3, 0, 2, 0, 44,}
- ,
- {3, 0, 2, 0, 43,}
- ,
- {3, 0, 2, 0, 42,}
- ,
- {3, 0, 2, 0, 41,}
- ,
- {3, 0, 2, 0, 39,}
- ,
- {3, 0, 2, 0, 38,}
- ,
- {3, 0, 2, 0, 37,}
- ,
- {3, 0, 2, 0, 36,}
- ,
- {3, 0, 2, 0, 35,}
- ,
- {3, 0, 2, 0, 34,}
- ,
- {3, 0, 2, 0, 33,}
- ,
- {3, 0, 2, 0, 32,}
- ,
- {3, 0, 1, 0, 63,}
- ,
- {3, 0, 1, 0, 61,}
- ,
- {3, 0, 1, 0, 59,}
- ,
- {3, 0, 1, 0, 57,}
- ,
+ {3, 0, 31, 0, 72},
+ {3, 0, 31, 0, 70},
+ {3, 0, 31, 0, 68},
+ {3, 0, 30, 0, 67},
+ {3, 0, 29, 0, 68},
+ {3, 0, 28, 0, 68},
+ {3, 0, 27, 0, 69},
+ {3, 0, 26, 0, 70},
+ {3, 0, 25, 0, 70},
+ {3, 0, 24, 0, 71},
+ {3, 0, 23, 0, 72},
+ {3, 0, 23, 0, 70},
+ {3, 0, 22, 0, 71},
+ {3, 0, 21, 0, 72},
+ {3, 0, 21, 0, 70},
+ {3, 0, 21, 0, 68},
+ {3, 0, 21, 0, 66},
+ {3, 0, 21, 0, 64},
+ {3, 0, 21, 0, 63},
+ {3, 0, 20, 0, 64},
+ {3, 0, 19, 0, 65},
+ {3, 0, 19, 0, 64},
+ {3, 0, 18, 0, 65},
+ {3, 0, 18, 0, 64},
+ {3, 0, 17, 0, 65},
+ {3, 0, 17, 0, 64},
+ {3, 0, 16, 0, 65},
+ {3, 0, 16, 0, 64},
+ {3, 0, 16, 0, 62},
+ {3, 0, 16, 0, 60},
+ {3, 0, 16, 0, 58},
+ {3, 0, 15, 0, 61},
+ {3, 0, 15, 0, 59},
+ {3, 0, 14, 0, 61},
+ {3, 0, 14, 0, 60},
+ {3, 0, 14, 0, 58},
+ {3, 0, 13, 0, 60},
+ {3, 0, 13, 0, 59},
+ {3, 0, 12, 0, 62},
+ {3, 0, 12, 0, 60},
+ {3, 0, 12, 0, 58},
+ {3, 0, 11, 0, 62},
+ {3, 0, 11, 0, 60},
+ {3, 0, 11, 0, 59},
+ {3, 0, 11, 0, 57},
+ {3, 0, 10, 0, 61},
+ {3, 0, 10, 0, 59},
+ {3, 0, 10, 0, 57},
+ {3, 0, 9, 0, 62},
+ {3, 0, 9, 0, 60},
+ {3, 0, 9, 0, 58},
+ {3, 0, 9, 0, 57},
+ {3, 0, 8, 0, 62},
+ {3, 0, 8, 0, 60},
+ {3, 0, 8, 0, 58},
+ {3, 0, 8, 0, 57},
+ {3, 0, 8, 0, 55},
+ {3, 0, 7, 0, 61},
+ {3, 0, 7, 0, 60},
+ {3, 0, 7, 0, 58},
+ {3, 0, 7, 0, 56},
+ {3, 0, 7, 0, 55},
+ {3, 0, 6, 0, 62},
+ {3, 0, 6, 0, 60},
+ {3, 0, 6, 0, 58},
+ {3, 0, 6, 0, 57},
+ {3, 0, 6, 0, 55},
+ {3, 0, 6, 0, 54},
+ {3, 0, 6, 0, 52},
+ {3, 0, 5, 0, 61},
+ {3, 0, 5, 0, 59},
+ {3, 0, 5, 0, 57},
+ {3, 0, 5, 0, 56},
+ {3, 0, 5, 0, 54},
+ {3, 0, 5, 0, 53},
+ {3, 0, 5, 0, 51},
+ {3, 0, 4, 0, 62},
+ {3, 0, 4, 0, 60},
+ {3, 0, 4, 0, 58},
+ {3, 0, 4, 0, 57},
+ {3, 0, 4, 0, 55},
+ {3, 0, 4, 0, 54},
+ {3, 0, 4, 0, 52},
+ {3, 0, 4, 0, 51},
+ {3, 0, 4, 0, 49},
+ {3, 0, 4, 0, 48},
+ {3, 0, 4, 0, 46},
+ {3, 0, 3, 0, 60},
+ {3, 0, 3, 0, 58},
+ {3, 0, 3, 0, 57},
+ {3, 0, 3, 0, 55},
+ {3, 0, 3, 0, 54},
+ {3, 0, 3, 0, 52},
+ {3, 0, 3, 0, 51},
+ {3, 0, 3, 0, 49},
+ {3, 0, 3, 0, 48},
+ {3, 0, 3, 0, 46},
+ {3, 0, 3, 0, 45},
+ {3, 0, 3, 0, 44},
+ {3, 0, 3, 0, 43},
+ {3, 0, 3, 0, 41},
+ {3, 0, 2, 0, 61},
+ {3, 0, 2, 0, 59},
+ {3, 0, 2, 0, 57},
+ {3, 0, 2, 0, 56},
+ {3, 0, 2, 0, 54},
+ {3, 0, 2, 0, 53},
+ {3, 0, 2, 0, 51},
+ {3, 0, 2, 0, 50},
+ {3, 0, 2, 0, 48},
+ {3, 0, 2, 0, 47},
+ {3, 0, 2, 0, 46},
+ {3, 0, 2, 0, 44},
+ {3, 0, 2, 0, 43},
+ {3, 0, 2, 0, 42},
+ {3, 0, 2, 0, 41},
+ {3, 0, 2, 0, 39},
+ {3, 0, 2, 0, 38},
+ {3, 0, 2, 0, 37},
+ {3, 0, 2, 0, 36},
+ {3, 0, 2, 0, 35},
+ {3, 0, 2, 0, 34},
+ {3, 0, 2, 0, 33},
+ {3, 0, 2, 0, 32},
+ {3, 0, 1, 0, 63},
+ {3, 0, 1, 0, 61},
+ {3, 0, 1, 0, 59},
+ {3, 0, 1, 0, 57},
};
const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = {
- {7, 0, 31, 0, 72,}
- ,
- {7, 0, 31, 0, 70,}
- ,
- {7, 0, 31, 0, 68,}
- ,
- {7, 0, 30, 0, 67,}
- ,
- {7, 0, 29, 0, 68,}
- ,
- {7, 0, 28, 0, 68,}
- ,
- {7, 0, 27, 0, 69,}
- ,
- {7, 0, 26, 0, 70,}
- ,
- {7, 0, 25, 0, 70,}
- ,
- {7, 0, 24, 0, 71,}
- ,
- {7, 0, 23, 0, 72,}
- ,
- {7, 0, 23, 0, 70,}
- ,
- {7, 0, 22, 0, 71,}
- ,
- {7, 0, 21, 0, 72,}
- ,
- {7, 0, 21, 0, 70,}
- ,
- {7, 0, 21, 0, 68,}
- ,
- {7, 0, 21, 0, 66,}
- ,
- {7, 0, 21, 0, 64,}
- ,
- {7, 0, 21, 0, 63,}
- ,
- {7, 0, 20, 0, 64,}
- ,
- {7, 0, 19, 0, 65,}
- ,
- {7, 0, 19, 0, 64,}
- ,
- {7, 0, 18, 0, 65,}
- ,
- {7, 0, 18, 0, 64,}
- ,
- {7, 0, 17, 0, 65,}
- ,
- {7, 0, 17, 0, 64,}
- ,
- {7, 0, 16, 0, 65,}
- ,
- {7, 0, 16, 0, 64,}
- ,
- {7, 0, 16, 0, 62,}
- ,
- {7, 0, 16, 0, 60,}
- ,
- {7, 0, 16, 0, 58,}
- ,
- {7, 0, 15, 0, 61,}
- ,
- {7, 0, 15, 0, 59,}
- ,
- {7, 0, 14, 0, 61,}
- ,
- {7, 0, 14, 0, 60,}
- ,
- {7, 0, 14, 0, 58,}
- ,
- {7, 0, 13, 0, 60,}
- ,
- {7, 0, 13, 0, 59,}
- ,
- {7, 0, 12, 0, 62,}
- ,
- {7, 0, 12, 0, 60,}
- ,
- {7, 0, 12, 0, 58,}
- ,
- {7, 0, 11, 0, 62,}
- ,
- {7, 0, 11, 0, 60,}
- ,
- {7, 0, 11, 0, 59,}
- ,
- {7, 0, 11, 0, 57,}
- ,
- {7, 0, 10, 0, 61,}
- ,
- {7, 0, 10, 0, 59,}
- ,
- {7, 0, 10, 0, 57,}
- ,
- {7, 0, 9, 0, 62,}
- ,
- {7, 0, 9, 0, 60,}
- ,
- {7, 0, 9, 0, 58,}
- ,
- {7, 0, 9, 0, 57,}
- ,
- {7, 0, 8, 0, 62,}
- ,
- {7, 0, 8, 0, 60,}
- ,
- {7, 0, 8, 0, 58,}
- ,
- {7, 0, 8, 0, 57,}
- ,
- {7, 0, 8, 0, 55,}
- ,
- {7, 0, 7, 0, 61,}
- ,
- {7, 0, 7, 0, 60,}
- ,
- {7, 0, 7, 0, 58,}
- ,
- {7, 0, 7, 0, 56,}
- ,
- {7, 0, 7, 0, 55,}
- ,
- {7, 0, 6, 0, 62,}
- ,
- {7, 0, 6, 0, 60,}
- ,
- {7, 0, 6, 0, 58,}
- ,
- {7, 0, 6, 0, 57,}
- ,
- {7, 0, 6, 0, 55,}
- ,
- {7, 0, 6, 0, 54,}
- ,
- {7, 0, 6, 0, 52,}
- ,
- {7, 0, 5, 0, 61,}
- ,
- {7, 0, 5, 0, 59,}
- ,
- {7, 0, 5, 0, 57,}
- ,
- {7, 0, 5, 0, 56,}
- ,
- {7, 0, 5, 0, 54,}
- ,
- {7, 0, 5, 0, 53,}
- ,
- {7, 0, 5, 0, 51,}
- ,
- {7, 0, 4, 0, 62,}
- ,
- {7, 0, 4, 0, 60,}
- ,
- {7, 0, 4, 0, 58,}
- ,
- {7, 0, 4, 0, 57,}
- ,
- {7, 0, 4, 0, 55,}
- ,
- {7, 0, 4, 0, 54,}
- ,
- {7, 0, 4, 0, 52,}
- ,
- {7, 0, 4, 0, 51,}
- ,
- {7, 0, 4, 0, 49,}
- ,
- {7, 0, 4, 0, 48,}
- ,
- {7, 0, 4, 0, 46,}
- ,
- {7, 0, 3, 0, 60,}
- ,
- {7, 0, 3, 0, 58,}
- ,
- {7, 0, 3, 0, 57,}
- ,
- {7, 0, 3, 0, 55,}
- ,
- {7, 0, 3, 0, 54,}
- ,
- {7, 0, 3, 0, 52,}
- ,
- {7, 0, 3, 0, 51,}
- ,
- {7, 0, 3, 0, 49,}
- ,
- {7, 0, 3, 0, 48,}
- ,
- {7, 0, 3, 0, 46,}
- ,
- {7, 0, 3, 0, 45,}
- ,
- {7, 0, 3, 0, 44,}
- ,
- {7, 0, 3, 0, 43,}
- ,
- {7, 0, 3, 0, 41,}
- ,
- {7, 0, 2, 0, 61,}
- ,
- {7, 0, 2, 0, 59,}
- ,
- {7, 0, 2, 0, 57,}
- ,
- {7, 0, 2, 0, 56,}
- ,
- {7, 0, 2, 0, 54,}
- ,
- {7, 0, 2, 0, 53,}
- ,
- {7, 0, 2, 0, 51,}
- ,
- {7, 0, 2, 0, 50,}
- ,
- {7, 0, 2, 0, 48,}
- ,
- {7, 0, 2, 0, 47,}
- ,
- {7, 0, 2, 0, 46,}
- ,
- {7, 0, 2, 0, 44,}
- ,
- {7, 0, 2, 0, 43,}
- ,
- {7, 0, 2, 0, 42,}
- ,
- {7, 0, 2, 0, 41,}
- ,
- {7, 0, 2, 0, 39,}
- ,
- {7, 0, 2, 0, 38,}
- ,
- {7, 0, 2, 0, 37,}
- ,
- {7, 0, 2, 0, 36,}
- ,
- {7, 0, 2, 0, 35,}
- ,
- {7, 0, 2, 0, 34,}
- ,
- {7, 0, 2, 0, 33,}
- ,
- {7, 0, 2, 0, 32,}
- ,
- {7, 0, 1, 0, 63,}
- ,
- {7, 0, 1, 0, 61,}
- ,
- {7, 0, 1, 0, 59,}
- ,
- {7, 0, 1, 0, 57,}
- ,
+ {7, 0, 31, 0, 72},
+ {7, 0, 31, 0, 70},
+ {7, 0, 31, 0, 68},
+ {7, 0, 30, 0, 67},
+ {7, 0, 29, 0, 68},
+ {7, 0, 28, 0, 68},
+ {7, 0, 27, 0, 69},
+ {7, 0, 26, 0, 70},
+ {7, 0, 25, 0, 70},
+ {7, 0, 24, 0, 71},
+ {7, 0, 23, 0, 72},
+ {7, 0, 23, 0, 70},
+ {7, 0, 22, 0, 71},
+ {7, 0, 21, 0, 72},
+ {7, 0, 21, 0, 70},
+ {7, 0, 21, 0, 68},
+ {7, 0, 21, 0, 66},
+ {7, 0, 21, 0, 64},
+ {7, 0, 21, 0, 63},
+ {7, 0, 20, 0, 64},
+ {7, 0, 19, 0, 65},
+ {7, 0, 19, 0, 64},
+ {7, 0, 18, 0, 65},
+ {7, 0, 18, 0, 64},
+ {7, 0, 17, 0, 65},
+ {7, 0, 17, 0, 64},
+ {7, 0, 16, 0, 65},
+ {7, 0, 16, 0, 64},
+ {7, 0, 16, 0, 62},
+ {7, 0, 16, 0, 60},
+ {7, 0, 16, 0, 58},
+ {7, 0, 15, 0, 61},
+ {7, 0, 15, 0, 59},
+ {7, 0, 14, 0, 61},
+ {7, 0, 14, 0, 60},
+ {7, 0, 14, 0, 58},
+ {7, 0, 13, 0, 60},
+ {7, 0, 13, 0, 59},
+ {7, 0, 12, 0, 62},
+ {7, 0, 12, 0, 60},
+ {7, 0, 12, 0, 58},
+ {7, 0, 11, 0, 62},
+ {7, 0, 11, 0, 60},
+ {7, 0, 11, 0, 59},
+ {7, 0, 11, 0, 57},
+ {7, 0, 10, 0, 61},
+ {7, 0, 10, 0, 59},
+ {7, 0, 10, 0, 57},
+ {7, 0, 9, 0, 62},
+ {7, 0, 9, 0, 60},
+ {7, 0, 9, 0, 58},
+ {7, 0, 9, 0, 57},
+ {7, 0, 8, 0, 62},
+ {7, 0, 8, 0, 60},
+ {7, 0, 8, 0, 58},
+ {7, 0, 8, 0, 57},
+ {7, 0, 8, 0, 55},
+ {7, 0, 7, 0, 61},
+ {7, 0, 7, 0, 60},
+ {7, 0, 7, 0, 58},
+ {7, 0, 7, 0, 56},
+ {7, 0, 7, 0, 55},
+ {7, 0, 6, 0, 62},
+ {7, 0, 6, 0, 60},
+ {7, 0, 6, 0, 58},
+ {7, 0, 6, 0, 57},
+ {7, 0, 6, 0, 55},
+ {7, 0, 6, 0, 54},
+ {7, 0, 6, 0, 52},
+ {7, 0, 5, 0, 61},
+ {7, 0, 5, 0, 59},
+ {7, 0, 5, 0, 57},
+ {7, 0, 5, 0, 56},
+ {7, 0, 5, 0, 54},
+ {7, 0, 5, 0, 53},
+ {7, 0, 5, 0, 51},
+ {7, 0, 4, 0, 62},
+ {7, 0, 4, 0, 60},
+ {7, 0, 4, 0, 58},
+ {7, 0, 4, 0, 57},
+ {7, 0, 4, 0, 55},
+ {7, 0, 4, 0, 54},
+ {7, 0, 4, 0, 52},
+ {7, 0, 4, 0, 51},
+ {7, 0, 4, 0, 49},
+ {7, 0, 4, 0, 48},
+ {7, 0, 4, 0, 46},
+ {7, 0, 3, 0, 60},
+ {7, 0, 3, 0, 58},
+ {7, 0, 3, 0, 57},
+ {7, 0, 3, 0, 55},
+ {7, 0, 3, 0, 54},
+ {7, 0, 3, 0, 52},
+ {7, 0, 3, 0, 51},
+ {7, 0, 3, 0, 49},
+ {7, 0, 3, 0, 48},
+ {7, 0, 3, 0, 46},
+ {7, 0, 3, 0, 45},
+ {7, 0, 3, 0, 44},
+ {7, 0, 3, 0, 43},
+ {7, 0, 3, 0, 41},
+ {7, 0, 2, 0, 61},
+ {7, 0, 2, 0, 59},
+ {7, 0, 2, 0, 57},
+ {7, 0, 2, 0, 56},
+ {7, 0, 2, 0, 54},
+ {7, 0, 2, 0, 53},
+ {7, 0, 2, 0, 51},
+ {7, 0, 2, 0, 50},
+ {7, 0, 2, 0, 48},
+ {7, 0, 2, 0, 47},
+ {7, 0, 2, 0, 46},
+ {7, 0, 2, 0, 44},
+ {7, 0, 2, 0, 43},
+ {7, 0, 2, 0, 42},
+ {7, 0, 2, 0, 41},
+ {7, 0, 2, 0, 39},
+ {7, 0, 2, 0, 38},
+ {7, 0, 2, 0, 37},
+ {7, 0, 2, 0, 36},
+ {7, 0, 2, 0, 35},
+ {7, 0, 2, 0, 34},
+ {7, 0, 2, 0, 33},
+ {7, 0, 2, 0, 32},
+ {7, 0, 1, 0, 63},
+ {7, 0, 1, 0, 61},
+ {7, 0, 1, 0, 59},
+ {7, 0, 1, 0, 57},
};
const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = {
- {255, 255, 0xf0, 0, 152,}
- ,
- {255, 255, 0xf0, 0, 147,}
- ,
- {255, 255, 0xf0, 0, 143,}
- ,
- {255, 255, 0xf0, 0, 139,}
- ,
- {255, 255, 0xf0, 0, 135,}
- ,
- {255, 255, 0xf0, 0, 131,}
- ,
- {255, 255, 0xf0, 0, 128,}
- ,
- {255, 255, 0xf0, 0, 124,}
- ,
- {255, 255, 0xf0, 0, 121,}
- ,
- {255, 255, 0xf0, 0, 117,}
- ,
- {255, 255, 0xf0, 0, 114,}
- ,
- {255, 255, 0xf0, 0, 111,}
- ,
- {255, 255, 0xf0, 0, 107,}
- ,
- {255, 255, 0xf0, 0, 104,}
- ,
- {255, 255, 0xf0, 0, 101,}
- ,
- {255, 255, 0xf0, 0, 99,}
- ,
- {255, 255, 0xf0, 0, 96,}
- ,
- {255, 255, 0xf0, 0, 93,}
- ,
- {255, 255, 0xf0, 0, 90,}
- ,
- {255, 255, 0xf0, 0, 88,}
- ,
- {255, 255, 0xf0, 0, 85,}
- ,
- {255, 255, 0xf0, 0, 83,}
- ,
- {255, 255, 0xf0, 0, 81,}
- ,
- {255, 255, 0xf0, 0, 78,}
- ,
- {255, 255, 0xf0, 0, 76,}
- ,
- {255, 255, 0xf0, 0, 74,}
- ,
- {255, 255, 0xf0, 0, 72,}
- ,
- {255, 255, 0xf0, 0, 70,}
- ,
- {255, 255, 0xf0, 0, 68,}
- ,
- {255, 255, 0xf0, 0, 66,}
- ,
- {255, 255, 0xf0, 0, 64,}
- ,
- {255, 248, 0xf0, 0, 64,}
- ,
- {255, 241, 0xf0, 0, 64,}
- ,
- {255, 251, 0xe0, 0, 64,}
- ,
- {255, 244, 0xe0, 0, 64,}
- ,
- {255, 254, 0xd0, 0, 64,}
- ,
- {255, 246, 0xd0, 0, 64,}
- ,
- {255, 239, 0xd0, 0, 64,}
- ,
- {255, 249, 0xc0, 0, 64,}
- ,
- {255, 242, 0xc0, 0, 64,}
- ,
- {255, 255, 0xb0, 0, 64,}
- ,
- {255, 248, 0xb0, 0, 64,}
- ,
- {255, 241, 0xb0, 0, 64,}
- ,
- {255, 254, 0xa0, 0, 64,}
- ,
- {255, 246, 0xa0, 0, 64,}
- ,
- {255, 239, 0xa0, 0, 64,}
- ,
- {255, 255, 0x90, 0, 64,}
- ,
- {255, 248, 0x90, 0, 64,}
- ,
- {255, 241, 0x90, 0, 64,}
- ,
- {255, 234, 0x90, 0, 64,}
- ,
- {255, 255, 0x80, 0, 64,}
- ,
- {255, 248, 0x80, 0, 64,}
- ,
- {255, 241, 0x80, 0, 64,}
- ,
- {255, 234, 0x80, 0, 64,}
- ,
- {255, 255, 0x70, 0, 64,}
- ,
- {255, 248, 0x70, 0, 64,}
- ,
- {255, 241, 0x70, 0, 64,}
- ,
- {255, 234, 0x70, 0, 64,}
- ,
- {255, 227, 0x70, 0, 64,}
- ,
- {255, 221, 0x70, 0, 64,}
- ,
- {255, 215, 0x70, 0, 64,}
- ,
- {255, 208, 0x70, 0, 64,}
- ,
- {255, 203, 0x70, 0, 64,}
- ,
- {255, 197, 0x70, 0, 64,}
- ,
- {255, 255, 0x60, 0, 64,}
- ,
- {255, 248, 0x60, 0, 64,}
- ,
- {255, 241, 0x60, 0, 64,}
- ,
- {255, 234, 0x60, 0, 64,}
- ,
- {255, 227, 0x60, 0, 64,}
- ,
- {255, 221, 0x60, 0, 64,}
- ,
- {255, 255, 0x50, 0, 64,}
- ,
- {255, 248, 0x50, 0, 64,}
- ,
- {255, 241, 0x50, 0, 64,}
- ,
- {255, 234, 0x50, 0, 64,}
- ,
- {255, 227, 0x50, 0, 64,}
- ,
- {255, 221, 0x50, 0, 64,}
- ,
- {255, 215, 0x50, 0, 64,}
- ,
- {255, 208, 0x50, 0, 64,}
- ,
- {255, 255, 0x40, 0, 64,}
- ,
- {255, 248, 0x40, 0, 64,}
- ,
- {255, 241, 0x40, 0, 64,}
- ,
- {255, 234, 0x40, 0, 64,}
- ,
- {255, 227, 0x40, 0, 64,}
- ,
- {255, 221, 0x40, 0, 64,}
- ,
- {255, 215, 0x40, 0, 64,}
- ,
- {255, 208, 0x40, 0, 64,}
- ,
- {255, 203, 0x40, 0, 64,}
- ,
- {255, 197, 0x40, 0, 64,}
- ,
- {255, 255, 0x30, 0, 64,}
- ,
- {255, 248, 0x30, 0, 64,}
- ,
- {255, 241, 0x30, 0, 64,}
- ,
- {255, 234, 0x30, 0, 64,}
- ,
- {255, 227, 0x30, 0, 64,}
- ,
- {255, 221, 0x30, 0, 64,}
- ,
- {255, 215, 0x30, 0, 64,}
- ,
- {255, 208, 0x30, 0, 64,}
- ,
- {255, 203, 0x30, 0, 64,}
- ,
- {255, 197, 0x30, 0, 64,}
- ,
- {255, 191, 0x30, 0, 64,}
- ,
- {255, 186, 0x30, 0, 64,}
- ,
- {255, 181, 0x30, 0, 64,}
- ,
- {255, 175, 0x30, 0, 64,}
- ,
- {255, 255, 0x20, 0, 64,}
- ,
- {255, 248, 0x20, 0, 64,}
- ,
- {255, 241, 0x20, 0, 64,}
- ,
- {255, 234, 0x20, 0, 64,}
- ,
- {255, 227, 0x20, 0, 64,}
- ,
- {255, 221, 0x20, 0, 64,}
- ,
- {255, 215, 0x20, 0, 64,}
- ,
- {255, 208, 0x20, 0, 64,}
- ,
- {255, 203, 0x20, 0, 64,}
- ,
- {255, 197, 0x20, 0, 64,}
- ,
- {255, 191, 0x20, 0, 64,}
- ,
- {255, 186, 0x20, 0, 64,}
- ,
- {255, 181, 0x20, 0, 64,}
- ,
- {255, 175, 0x20, 0, 64,}
- ,
- {255, 170, 0x20, 0, 64,}
- ,
- {255, 166, 0x20, 0, 64,}
- ,
- {255, 161, 0x20, 0, 64,}
- ,
- {255, 156, 0x20, 0, 64,}
- ,
- {255, 152, 0x20, 0, 64,}
- ,
- {255, 148, 0x20, 0, 64,}
- ,
- {255, 143, 0x20, 0, 64,}
- ,
- {255, 139, 0x20, 0, 64,}
- ,
- {255, 135, 0x20, 0, 64,}
- ,
- {255, 132, 0x20, 0, 64,}
- ,
- {255, 255, 0x10, 0, 64,}
- ,
- {255, 248, 0x10, 0, 64,}
- ,
+ {255, 255, 0xf0, 0, 152},
+ {255, 255, 0xf0, 0, 147},
+ {255, 255, 0xf0, 0, 143},
+ {255, 255, 0xf0, 0, 139},
+ {255, 255, 0xf0, 0, 135},
+ {255, 255, 0xf0, 0, 131},
+ {255, 255, 0xf0, 0, 128},
+ {255, 255, 0xf0, 0, 124},
+ {255, 255, 0xf0, 0, 121},
+ {255, 255, 0xf0, 0, 117},
+ {255, 255, 0xf0, 0, 114},
+ {255, 255, 0xf0, 0, 111},
+ {255, 255, 0xf0, 0, 107},
+ {255, 255, 0xf0, 0, 104},
+ {255, 255, 0xf0, 0, 101},
+ {255, 255, 0xf0, 0, 99},
+ {255, 255, 0xf0, 0, 96},
+ {255, 255, 0xf0, 0, 93},
+ {255, 255, 0xf0, 0, 90},
+ {255, 255, 0xf0, 0, 88},
+ {255, 255, 0xf0, 0, 85},
+ {255, 255, 0xf0, 0, 83},
+ {255, 255, 0xf0, 0, 81},
+ {255, 255, 0xf0, 0, 78},
+ {255, 255, 0xf0, 0, 76},
+ {255, 255, 0xf0, 0, 74},
+ {255, 255, 0xf0, 0, 72},
+ {255, 255, 0xf0, 0, 70},
+ {255, 255, 0xf0, 0, 68},
+ {255, 255, 0xf0, 0, 66},
+ {255, 255, 0xf0, 0, 64},
+ {255, 248, 0xf0, 0, 64},
+ {255, 241, 0xf0, 0, 64},
+ {255, 251, 0xe0, 0, 64},
+ {255, 244, 0xe0, 0, 64},
+ {255, 254, 0xd0, 0, 64},
+ {255, 246, 0xd0, 0, 64},
+ {255, 239, 0xd0, 0, 64},
+ {255, 249, 0xc0, 0, 64},
+ {255, 242, 0xc0, 0, 64},
+ {255, 255, 0xb0, 0, 64},
+ {255, 248, 0xb0, 0, 64},
+ {255, 241, 0xb0, 0, 64},
+ {255, 254, 0xa0, 0, 64},
+ {255, 246, 0xa0, 0, 64},
+ {255, 239, 0xa0, 0, 64},
+ {255, 255, 0x90, 0, 64},
+ {255, 248, 0x90, 0, 64},
+ {255, 241, 0x90, 0, 64},
+ {255, 234, 0x90, 0, 64},
+ {255, 255, 0x80, 0, 64},
+ {255, 248, 0x80, 0, 64},
+ {255, 241, 0x80, 0, 64},
+ {255, 234, 0x80, 0, 64},
+ {255, 255, 0x70, 0, 64},
+ {255, 248, 0x70, 0, 64},
+ {255, 241, 0x70, 0, 64},
+ {255, 234, 0x70, 0, 64},
+ {255, 227, 0x70, 0, 64},
+ {255, 221, 0x70, 0, 64},
+ {255, 215, 0x70, 0, 64},
+ {255, 208, 0x70, 0, 64},
+ {255, 203, 0x70, 0, 64},
+ {255, 197, 0x70, 0, 64},
+ {255, 255, 0x60, 0, 64},
+ {255, 248, 0x60, 0, 64},
+ {255, 241, 0x60, 0, 64},
+ {255, 234, 0x60, 0, 64},
+ {255, 227, 0x60, 0, 64},
+ {255, 221, 0x60, 0, 64},
+ {255, 255, 0x50, 0, 64},
+ {255, 248, 0x50, 0, 64},
+ {255, 241, 0x50, 0, 64},
+ {255, 234, 0x50, 0, 64},
+ {255, 227, 0x50, 0, 64},
+ {255, 221, 0x50, 0, 64},
+ {255, 215, 0x50, 0, 64},
+ {255, 208, 0x50, 0, 64},
+ {255, 255, 0x40, 0, 64},
+ {255, 248, 0x40, 0, 64},
+ {255, 241, 0x40, 0, 64},
+ {255, 234, 0x40, 0, 64},
+ {255, 227, 0x40, 0, 64},
+ {255, 221, 0x40, 0, 64},
+ {255, 215, 0x40, 0, 64},
+ {255, 208, 0x40, 0, 64},
+ {255, 203, 0x40, 0, 64},
+ {255, 197, 0x40, 0, 64},
+ {255, 255, 0x30, 0, 64},
+ {255, 248, 0x30, 0, 64},
+ {255, 241, 0x30, 0, 64},
+ {255, 234, 0x30, 0, 64},
+ {255, 227, 0x30, 0, 64},
+ {255, 221, 0x30, 0, 64},
+ {255, 215, 0x30, 0, 64},
+ {255, 208, 0x30, 0, 64},
+ {255, 203, 0x30, 0, 64},
+ {255, 197, 0x30, 0, 64},
+ {255, 191, 0x30, 0, 64},
+ {255, 186, 0x30, 0, 64},
+ {255, 181, 0x30, 0, 64},
+ {255, 175, 0x30, 0, 64},
+ {255, 255, 0x20, 0, 64},
+ {255, 248, 0x20, 0, 64},
+ {255, 241, 0x20, 0, 64},
+ {255, 234, 0x20, 0, 64},
+ {255, 227, 0x20, 0, 64},
+ {255, 221, 0x20, 0, 64},
+ {255, 215, 0x20, 0, 64},
+ {255, 208, 0x20, 0, 64},
+ {255, 203, 0x20, 0, 64},
+ {255, 197, 0x20, 0, 64},
+ {255, 191, 0x20, 0, 64},
+ {255, 186, 0x20, 0, 64},
+ {255, 181, 0x20, 0, 64},
+ {255, 175, 0x20, 0, 64},
+ {255, 170, 0x20, 0, 64},
+ {255, 166, 0x20, 0, 64},
+ {255, 161, 0x20, 0, 64},
+ {255, 156, 0x20, 0, 64},
+ {255, 152, 0x20, 0, 64},
+ {255, 148, 0x20, 0, 64},
+ {255, 143, 0x20, 0, 64},
+ {255, 139, 0x20, 0, 64},
+ {255, 135, 0x20, 0, 64},
+ {255, 132, 0x20, 0, 64},
+ {255, 255, 0x10, 0, 64},
+ {255, 248, 0x10, 0, 64},
};
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h
index 5f75e16bf5a7..5f75e16bf5a7 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c
index 7f741f4868a6..dbf50ef6cd75 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c
@@ -17,7 +17,7 @@
#include <types.h>
#include "phytbl_n.h"
-const u32 frame_struct_rev0[] = {
+static const u32 frame_struct_rev0[] = {
0x08004a04,
0x00100000,
0x01000a05,
@@ -852,7 +852,7 @@ const u32 frame_struct_rev0[] = {
0x00000000,
};
-const u8 frame_lut_rev0[] = {
+static const u8 frame_lut_rev0[] = {
0x02,
0x04,
0x14,
@@ -887,7 +887,7 @@ const u8 frame_lut_rev0[] = {
0x2a,
};
-const u32 tmap_tbl_rev0[] = {
+static const u32 tmap_tbl_rev0[] = {
0x8a88aa80,
0x8aaaaa8a,
0x8a8a8aa8,
@@ -1338,7 +1338,7 @@ const u32 tmap_tbl_rev0[] = {
0x00000000,
};
-const u32 tdtrn_tbl_rev0[] = {
+static const u32 tdtrn_tbl_rev0[] = {
0x061c061c,
0x0050ee68,
0xf592fe36,
@@ -2045,7 +2045,7 @@ const u32 tdtrn_tbl_rev0[] = {
0x00f006be,
};
-const u32 intlv_tbl_rev0[] = {
+static const u32 intlv_tbl_rev0[] = {
0x00802070,
0x0671188d,
0x0a60192c,
@@ -2055,7 +2055,7 @@ const u32 intlv_tbl_rev0[] = {
0x00000070,
};
-const u16 pilot_tbl_rev0[] = {
+static const u16 pilot_tbl_rev0[] = {
0xff08,
0xff08,
0xff08,
@@ -2146,7 +2146,7 @@ const u16 pilot_tbl_rev0[] = {
0xffff,
};
-const u32 pltlut_tbl_rev0[] = {
+static const u32 pltlut_tbl_rev0[] = {
0x76540123,
0x62407351,
0x76543201,
@@ -2155,7 +2155,7 @@ const u32 pltlut_tbl_rev0[] = {
0x76430521,
};
-const u32 tdi_tbl20_ant0_rev0[] = {
+static const u32 tdi_tbl20_ant0_rev0[] = {
0x00091226,
0x000a1429,
0x000b56ad,
@@ -2213,7 +2213,7 @@ const u32 tdi_tbl20_ant0_rev0[] = {
0x00000000,
};
-const u32 tdi_tbl20_ant1_rev0[] = {
+static const u32 tdi_tbl20_ant1_rev0[] = {
0x00014b26,
0x00028d29,
0x000393ad,
@@ -2271,7 +2271,7 @@ const u32 tdi_tbl20_ant1_rev0[] = {
0x00000000,
};
-const u32 tdi_tbl40_ant0_rev0[] = {
+static const u32 tdi_tbl40_ant0_rev0[] = {
0x0011a346,
0x00136ccf,
0x0014f5d9,
@@ -2384,7 +2384,7 @@ const u32 tdi_tbl40_ant0_rev0[] = {
0x00000000,
};
-const u32 tdi_tbl40_ant1_rev0[] = {
+static const u32 tdi_tbl40_ant1_rev0[] = {
0x001edb36,
0x000129ca,
0x0002b353,
@@ -2497,7 +2497,7 @@ const u32 tdi_tbl40_ant1_rev0[] = {
0x00000000,
};
-const u16 bdi_tbl_rev0[] = {
+static const u16 bdi_tbl_rev0[] = {
0x0070,
0x0126,
0x012c,
@@ -2506,7 +2506,7 @@ const u16 bdi_tbl_rev0[] = {
0x04d2,
};
-const u32 chanest_tbl_rev0[] = {
+static const u32 chanest_tbl_rev0[] = {
0x44444444,
0x44444444,
0x44444444,
@@ -2605,7 +2605,7 @@ const u32 chanest_tbl_rev0[] = {
0x10101010,
};
-const u8 mcs_tbl_rev0[] = {
+static const u8 mcs_tbl_rev0[] = {
0x00,
0x08,
0x0a,
@@ -2736,7 +2736,7 @@ const u8 mcs_tbl_rev0[] = {
0x00,
};
-const u32 noise_var_tbl0_rev0[] = {
+static const u32 noise_var_tbl0_rev0[] = {
0x020c020c,
0x0000014d,
0x020c020c,
@@ -2995,7 +2995,7 @@ const u32 noise_var_tbl0_rev0[] = {
0x0000014d,
};
-const u32 noise_var_tbl1_rev0[] = {
+static const u32 noise_var_tbl1_rev0[] = {
0x020c020c,
0x0000014d,
0x020c020c,
@@ -3254,7 +3254,7 @@ const u32 noise_var_tbl1_rev0[] = {
0x0000014d,
};
-const u8 est_pwr_lut_core0_rev0[] = {
+static const u8 est_pwr_lut_core0_rev0[] = {
0x50,
0x4f,
0x4e,
@@ -3321,7 +3321,7 @@ const u8 est_pwr_lut_core0_rev0[] = {
0x11,
};
-const u8 est_pwr_lut_core1_rev0[] = {
+static const u8 est_pwr_lut_core1_rev0[] = {
0x50,
0x4f,
0x4e,
@@ -3388,7 +3388,7 @@ const u8 est_pwr_lut_core1_rev0[] = {
0x11,
};
-const u8 adj_pwr_lut_core0_rev0[] = {
+static const u8 adj_pwr_lut_core0_rev0[] = {
0x00,
0x00,
0x00,
@@ -3519,7 +3519,7 @@ const u8 adj_pwr_lut_core0_rev0[] = {
0x00,
};
-const u8 adj_pwr_lut_core1_rev0[] = {
+static const u8 adj_pwr_lut_core1_rev0[] = {
0x00,
0x00,
0x00,
@@ -3650,7 +3650,7 @@ const u8 adj_pwr_lut_core1_rev0[] = {
0x00,
};
-const u32 gainctrl_lut_core0_rev0[] = {
+static const u32 gainctrl_lut_core0_rev0[] = {
0x03cc2b44,
0x03cc2b42,
0x03cc2b40,
@@ -3781,7 +3781,7 @@ const u32 gainctrl_lut_core0_rev0[] = {
0x00002b00,
};
-const u32 gainctrl_lut_core1_rev0[] = {
+static const u32 gainctrl_lut_core1_rev0[] = {
0x03cc2b44,
0x03cc2b42,
0x03cc2b40,
@@ -3912,7 +3912,7 @@ const u32 gainctrl_lut_core1_rev0[] = {
0x00002b00,
};
-const u32 iq_lut_core0_rev0[] = {
+static const u32 iq_lut_core0_rev0[] = {
0x0000007f,
0x0000007f,
0x0000007f,
@@ -4043,7 +4043,7 @@ const u32 iq_lut_core0_rev0[] = {
0x0000007f,
};
-const u32 iq_lut_core1_rev0[] = {
+static const u32 iq_lut_core1_rev0[] = {
0x0000007f,
0x0000007f,
0x0000007f,
@@ -4174,7 +4174,7 @@ const u32 iq_lut_core1_rev0[] = {
0x0000007f,
};
-const u16 loft_lut_core0_rev0[] = {
+static const u16 loft_lut_core0_rev0[] = {
0x0000,
0x0101,
0x0002,
@@ -4305,7 +4305,7 @@ const u16 loft_lut_core0_rev0[] = {
0x0103,
};
-const u16 loft_lut_core1_rev0[] = {
+static const u16 loft_lut_core1_rev0[] = {
0x0000,
0x0101,
0x0002,
@@ -4522,7 +4522,8 @@ const struct phytbl_info mimophytbl_info_rev0[] = {
{&chanest_tbl_rev0,
sizeof(chanest_tbl_rev0) / sizeof(chanest_tbl_rev0[0]), 22, 0, 32}
,
- {&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, 8}
+ {&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0,
+ 8}
,
{&noise_var_tbl0_rev0,
sizeof(noise_var_tbl0_rev0) / sizeof(noise_var_tbl0_rev0[0]), 16, 0,
@@ -4540,7 +4541,7 @@ const u32 mimophytbl_info_sz_rev0_volatile =
sizeof(mimophytbl_info_rev0_volatile) /
sizeof(mimophytbl_info_rev0_volatile[0]);
-const u16 ant_swctrl_tbl_rev3[] = {
+static const u16 ant_swctrl_tbl_rev3[] = {
0x0082,
0x0082,
0x0211,
@@ -4575,7 +4576,7 @@ const u16 ant_swctrl_tbl_rev3[] = {
0x0000,
};
-const u16 ant_swctrl_tbl_rev3_1[] = {
+static const u16 ant_swctrl_tbl_rev3_1[] = {
0x0022,
0x0022,
0x0011,
@@ -4610,7 +4611,7 @@ const u16 ant_swctrl_tbl_rev3_1[] = {
0x0000,
};
-const u16 ant_swctrl_tbl_rev3_2[] = {
+static const u16 ant_swctrl_tbl_rev3_2[] = {
0x0088,
0x0088,
0x0044,
@@ -4645,7 +4646,7 @@ const u16 ant_swctrl_tbl_rev3_2[] = {
0x0000,
};
-const u16 ant_swctrl_tbl_rev3_3[] = {
+static const u16 ant_swctrl_tbl_rev3_3[] = {
0x022,
0x022,
0x011,
@@ -4680,7 +4681,7 @@ const u16 ant_swctrl_tbl_rev3_3[] = {
0x3cc
};
-const u32 frame_struct_rev3[] = {
+static const u32 frame_struct_rev3[] = {
0x08004a04,
0x00100000,
0x01000a05,
@@ -5515,7 +5516,7 @@ const u32 frame_struct_rev3[] = {
0x00000000,
};
-const u16 pilot_tbl_rev3[] = {
+static const u16 pilot_tbl_rev3[] = {
0xff08,
0xff08,
0xff08,
@@ -5606,7 +5607,7 @@ const u16 pilot_tbl_rev3[] = {
0xffff,
};
-const u32 tmap_tbl_rev3[] = {
+static const u32 tmap_tbl_rev3[] = {
0x8a88aa80,
0x8aaaaa8a,
0x8a8a8aa8,
@@ -6057,7 +6058,7 @@ const u32 tmap_tbl_rev3[] = {
0x00000000,
};
-const u32 intlv_tbl_rev3[] = {
+static const u32 intlv_tbl_rev3[] = {
0x00802070,
0x0671188d,
0x0a60192c,
@@ -6067,7 +6068,7 @@ const u32 intlv_tbl_rev3[] = {
0x00000070,
};
-const u32 tdtrn_tbl_rev3[] = {
+static const u32 tdtrn_tbl_rev3[] = {
0x061c061c,
0x0050ee68,
0xf592fe36,
@@ -7033,7 +7034,7 @@ const u32 noise_var_tbl_rev3[] = {
0x0000014d,
};
-const u16 mcs_tbl_rev3[] = {
+static const u16 mcs_tbl_rev3[] = {
0x0000,
0x0008,
0x000a,
@@ -7164,7 +7165,7 @@ const u16 mcs_tbl_rev3[] = {
0x0007,
};
-const u32 tdi_tbl20_ant0_rev3[] = {
+static const u32 tdi_tbl20_ant0_rev3[] = {
0x00091226,
0x000a1429,
0x000b56ad,
@@ -7222,7 +7223,7 @@ const u32 tdi_tbl20_ant0_rev3[] = {
0x00000000,
};
-const u32 tdi_tbl20_ant1_rev3[] = {
+static const u32 tdi_tbl20_ant1_rev3[] = {
0x00014b26,
0x00028d29,
0x000393ad,
@@ -7280,7 +7281,7 @@ const u32 tdi_tbl20_ant1_rev3[] = {
0x00000000,
};
-const u32 tdi_tbl40_ant0_rev3[] = {
+static const u32 tdi_tbl40_ant0_rev3[] = {
0x0011a346,
0x00136ccf,
0x0014f5d9,
@@ -7393,7 +7394,7 @@ const u32 tdi_tbl40_ant0_rev3[] = {
0x00000000,
};
-const u32 tdi_tbl40_ant1_rev3[] = {
+static const u32 tdi_tbl40_ant1_rev3[] = {
0x001edb36,
0x000129ca,
0x0002b353,
@@ -7506,7 +7507,7 @@ const u32 tdi_tbl40_ant1_rev3[] = {
0x00000000,
};
-const u32 pltlut_tbl_rev3[] = {
+static const u32 pltlut_tbl_rev3[] = {
0x76540213,
0x62407351,
0x76543210,
@@ -7515,7 +7516,7 @@ const u32 pltlut_tbl_rev3[] = {
0x76430521,
};
-const u32 chanest_tbl_rev3[] = {
+static const u32 chanest_tbl_rev3[] = {
0x44444444,
0x44444444,
0x44444444,
@@ -7614,7 +7615,7 @@ const u32 chanest_tbl_rev3[] = {
0x10101010,
};
-const u8 frame_lut_rev3[] = {
+static const u8 frame_lut_rev3[] = {
0x02,
0x04,
0x14,
@@ -7649,7 +7650,7 @@ const u8 frame_lut_rev3[] = {
0x2a,
};
-const u8 est_pwr_lut_core0_rev3[] = {
+static const u8 est_pwr_lut_core0_rev3[] = {
0x55,
0x54,
0x54,
@@ -7716,7 +7717,7 @@ const u8 est_pwr_lut_core0_rev3[] = {
0xfd,
};
-const u8 est_pwr_lut_core1_rev3[] = {
+static const u8 est_pwr_lut_core1_rev3[] = {
0x55,
0x54,
0x54,
@@ -7783,7 +7784,7 @@ const u8 est_pwr_lut_core1_rev3[] = {
0xfd,
};
-const u8 adj_pwr_lut_core0_rev3[] = {
+static const u8 adj_pwr_lut_core0_rev3[] = {
0x00,
0x00,
0x00,
@@ -7914,7 +7915,7 @@ const u8 adj_pwr_lut_core0_rev3[] = {
0x00,
};
-const u8 adj_pwr_lut_core1_rev3[] = {
+static const u8 adj_pwr_lut_core1_rev3[] = {
0x00,
0x00,
0x00,
@@ -8045,7 +8046,7 @@ const u8 adj_pwr_lut_core1_rev3[] = {
0x00,
};
-const u32 gainctrl_lut_core0_rev3[] = {
+static const u32 gainctrl_lut_core0_rev3[] = {
0x5bf70044,
0x5bf70042,
0x5bf70040,
@@ -8176,7 +8177,7 @@ const u32 gainctrl_lut_core0_rev3[] = {
0x5b07001c,
};
-const u32 gainctrl_lut_core1_rev3[] = {
+static const u32 gainctrl_lut_core1_rev3[] = {
0x5bf70044,
0x5bf70042,
0x5bf70040,
@@ -8307,7 +8308,7 @@ const u32 gainctrl_lut_core1_rev3[] = {
0x5b07001c,
};
-const u32 iq_lut_core0_rev3[] = {
+static const u32 iq_lut_core0_rev3[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -8438,7 +8439,7 @@ const u32 iq_lut_core0_rev3[] = {
0x00000000,
};
-const u32 iq_lut_core1_rev3[] = {
+static const u32 iq_lut_core1_rev3[] = {
0x00000000,
0x00000000,
0x00000000,
@@ -8569,7 +8570,7 @@ const u32 iq_lut_core1_rev3[] = {
0x00000000,
};
-const u16 loft_lut_core0_rev3[] = {
+static const u16 loft_lut_core0_rev3[] = {
0x0000,
0x0000,
0x0000,
@@ -8700,7 +8701,7 @@ const u16 loft_lut_core0_rev3[] = {
0x0000,
};
-const u16 loft_lut_core1_rev3[] = {
+static const u16 loft_lut_core1_rev3[] = {
0x0000,
0x0000,
0x0000,
@@ -8831,7 +8832,7 @@ const u16 loft_lut_core1_rev3[] = {
0x0000,
};
-const u16 papd_comp_rfpwr_tbl_core0_rev3[] = {
+static const u16 papd_comp_rfpwr_tbl_core0_rev3[] = {
0x0036,
0x0036,
0x0036,
@@ -8962,7 +8963,7 @@ const u16 papd_comp_rfpwr_tbl_core0_rev3[] = {
0x01d6,
};
-const u16 papd_comp_rfpwr_tbl_core1_rev3[] = {
+static const u16 papd_comp_rfpwr_tbl_core1_rev3[] = {
0x0036,
0x0036,
0x0036,
@@ -9093,7 +9094,7 @@ const u16 papd_comp_rfpwr_tbl_core1_rev3[] = {
0x01d6,
};
-const u32 papd_comp_epsilon_tbl_core0_rev3[] = {
+static const u32 papd_comp_epsilon_tbl_core0_rev3[] = {
0x00000000,
0x00001fa0,
0x00019f78,
@@ -9160,7 +9161,7 @@ const u32 papd_comp_epsilon_tbl_core0_rev3[] = {
0x03e38ffe,
};
-const u32 papd_cal_scalars_tbl_core0_rev3[] = {
+static const u32 papd_cal_scalars_tbl_core0_rev3[] = {
0x05af005a,
0x0571005e,
0x05040066,
@@ -9227,7 +9228,7 @@ const u32 papd_cal_scalars_tbl_core0_rev3[] = {
0x002606a4,
};
-const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
+static const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
0x00000000,
0x00001fa0,
0x00019f78,
@@ -9294,7 +9295,7 @@ const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
0x03e38ffe,
};
-const u32 papd_cal_scalars_tbl_core1_rev3[] = {
+static const u32 papd_cal_scalars_tbl_core1_rev3[] = {
0x05af005a,
0x0571005e,
0x05040066,
@@ -9489,7 +9490,7 @@ const u32 mimophytbl_info_sz_rev3_volatile3 =
sizeof(mimophytbl_info_rev3_volatile3) /
sizeof(mimophytbl_info_rev3_volatile3[0]);
-const u32 tmap_tbl_rev7[] = {
+static const u32 tmap_tbl_rev7[] = {
0x8a88aa80,
0x8aaaaa8a,
0x8a8a8aa8,
@@ -10199,7 +10200,7 @@ const u32 noise_var_tbl_rev7[] = {
0x0000014d,
};
-const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
+static const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
0x00000000,
0x00000000,
0x00016023,
@@ -10266,7 +10267,7 @@ const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
0x0156cfff,
};
-const u32 papd_cal_scalars_tbl_core0_rev7[] = {
+static const u32 papd_cal_scalars_tbl_core0_rev7[] = {
0x0b5e002d,
0x0ae2002f,
0x0a3b0032,
@@ -10333,7 +10334,7 @@ const u32 papd_cal_scalars_tbl_core0_rev7[] = {
0x004e068c,
};
-const u32 papd_comp_epsilon_tbl_core1_rev7[] = {
+static const u32 papd_comp_epsilon_tbl_core1_rev7[] = {
0x00000000,
0x00000000,
0x00016023,
@@ -10400,7 +10401,7 @@ const u32 papd_comp_epsilon_tbl_core1_rev7[] = {
0x0156cfff,
};
-const u32 papd_cal_scalars_tbl_core1_rev7[] = {
+static const u32 papd_cal_scalars_tbl_core1_rev7[] = {
0x0b5e002d,
0x0ae2002f,
0x0a3b0032,
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h
index c5266cf23725..dc8a84e85117 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h
@@ -20,21 +20,31 @@
#include "phy_int.h"
extern const struct phytbl_info mimophytbl_info_rev0[],
- mimophytbl_info_rev0_volatile[];
-extern const u32 mimophytbl_info_sz_rev0, mimophytbl_info_sz_rev0_volatile;
+ mimophytbl_info_rev0_volatile[];
+
+extern const u32 mimophytbl_info_sz_rev0,
+ mimophytbl_info_sz_rev0_volatile;
extern const struct phytbl_info mimophytbl_info_rev3[],
- mimophytbl_info_rev3_volatile[], mimophytbl_info_rev3_volatile1[],
- mimophytbl_info_rev3_volatile2[], mimophytbl_info_rev3_volatile3[];
-extern const u32 mimophytbl_info_sz_rev3, mimophytbl_info_sz_rev3_volatile,
- mimophytbl_info_sz_rev3_volatile1, mimophytbl_info_sz_rev3_volatile2,
- mimophytbl_info_sz_rev3_volatile3;
+ mimophytbl_info_rev3_volatile[],
+ mimophytbl_info_rev3_volatile1[],
+ mimophytbl_info_rev3_volatile2[],
+ mimophytbl_info_rev3_volatile3[];
+
+extern const u32 mimophytbl_info_sz_rev3,
+ mimophytbl_info_sz_rev3_volatile,
+ mimophytbl_info_sz_rev3_volatile1,
+ mimophytbl_info_sz_rev3_volatile2,
+ mimophytbl_info_sz_rev3_volatile3;
extern const u32 noise_var_tbl_rev3[];
extern const struct phytbl_info mimophytbl_info_rev7[];
+
extern const u32 mimophytbl_info_sz_rev7;
+
extern const u32 noise_var_tbl_rev7[];
extern const struct phytbl_info mimophytbl_info_rev16[];
+
extern const u32 mimophytbl_info_sz_rev16;
diff --git a/drivers/staging/brcm80211/brcmsmac/phy_shim.c b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c
index 82ecdcda271f..5926854f62e2 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy_shim.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c
@@ -15,15 +15,15 @@
*/
/*
- * This is "two-way" interface, acting as the SHIM layer between WL and PHY layer.
- * WL driver can optinally call this translation layer to do some preprocessing, then reach PHY.
- * On the PHY->WL driver direction, all calls go through this layer since PHY doesn't have the
- * access to wlc_hw pointer.
+ * This is "two-way" interface, acting as the SHIM layer between driver
+ * and PHY layer. The driver can optionally call this translation layer
+ * to do some preprocessing, then reach PHY. On the PHY->driver direction,
+ * all calls go through this layer since PHY doesn't have access to the
+ * driver's brcms_hardware pointer.
*/
#include <linux/slab.h>
#include <net/mac80211.h>
-#include "bmac.h"
#include "main.h"
#include "mac80211_if.h"
#include "phy_shim.h"
@@ -31,21 +31,19 @@
/* PHY SHIM module specific state */
struct phy_shim_info {
struct brcms_hardware *wlc_hw; /* pointer to main wlc_hw structure */
- void *wlc; /* pointer to main wlc structure */
- void *wl; /* pointer to os-specific private state */
+ struct brcms_c_info *wlc; /* pointer to main wlc structure */
+ struct brcms_info *wl; /* pointer to os-specific private state */
};
struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
- void *wl, void *wlc) {
+ struct brcms_info *wl,
+ struct brcms_c_info *wlc) {
struct phy_shim_info *physhim = NULL;
physhim = kzalloc(sizeof(struct phy_shim_info), GFP_ATOMIC);
- if (!physhim) {
- wiphy_err(wlc_hw->wlc->wiphy,
- "wl%d: wlc_phy_shim_attach: out of mem\n",
- wlc_hw->unit);
+ if (!physhim)
return NULL;
- }
+
physhim->wlc_hw = wlc_hw;
physhim->wlc = wlc;
physhim->wl = wl;
@@ -59,28 +57,28 @@ void wlc_phy_shim_detach(struct phy_shim_info *physhim)
}
struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
- void (*fn) (void *arg), void *arg,
- const char *name)
+ void (*fn)(struct brcms_phy *pi),
+ void *arg, const char *name)
{
return (struct wlapi_timer *)
- brcms_init_timer(physhim->wl, fn, arg, name);
+ brcms_init_timer(physhim->wl, (void (*)(void *))fn,
+ arg, name);
}
-void wlapi_free_timer(struct phy_shim_info *physhim, struct wlapi_timer *t)
+void wlapi_free_timer(struct wlapi_timer *t)
{
- brcms_free_timer(physhim->wl, (struct brcms_timer *)t);
+ brcms_free_timer((struct brcms_timer *)t);
}
void
-wlapi_add_timer(struct phy_shim_info *physhim, struct wlapi_timer *t, uint ms,
- int periodic)
+wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic)
{
- brcms_add_timer(physhim->wl, (struct brcms_timer *)t, ms, periodic);
+ brcms_add_timer((struct brcms_timer *)t, ms, periodic);
}
-bool wlapi_del_timer(struct phy_shim_info *physhim, struct wlapi_timer *t)
+bool wlapi_del_timer(struct wlapi_timer *t)
{
- return brcms_del_timer(physhim->wl, (struct brcms_timer *)t);
+ return brcms_del_timer((struct brcms_timer *)t);
}
void wlapi_intrson(struct phy_shim_info *physhim)
@@ -216,3 +214,12 @@ wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf,
{
brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel);
}
+
+char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id)
+{
+ return getvar(physhim->wlc_hw->sih, id);
+}
+int wlapi_getintvar(struct phy_shim_info *physhim, enum brcms_srom_id id)
+{
+ return getintvar(physhim->wlc_hw->sih, id);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy_shim.h b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h
index 2d12bb4400f1..9168c459b185 100644
--- a/drivers/staging/brcm80211/brcmsmac/phy_shim.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h
@@ -45,17 +45,17 @@
#define FRA_ERR_20MHZ 60
#define FRA_ERR_40MHZ 120
-#define ANTSEL_NA 0 /* No boardlevel selection available */
-#define ANTSEL_2x4 1 /* 2x4 boardlevel selection available */
-#define ANTSEL_2x3 2 /* 2x3 CB2 boardlevel selection available */
+#define ANTSEL_NA 0 /* No boardlevel selection available */
+#define ANTSEL_2x4 1 /* 2x4 boardlevel selection available */
+#define ANTSEL_2x3 2 /* 2x3 CB2 boardlevel selection available */
/* Rx Antenna diversity control values */
-#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */
-#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */
-#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */
-#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */
-#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */
-#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */
+#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */
+#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */
+#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */
+#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */
+#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */
+#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */
#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */
#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */
@@ -77,26 +77,40 @@
#define WL_TX_POWER_RATES 101
#define WL_TX_POWER_CCK_FIRST 0
#define WL_TX_POWER_CCK_NUM 4
-#define WL_TX_POWER_OFDM_FIRST 4 /* Index for first 20MHz OFDM SISO rate */
-#define WL_TX_POWER_OFDM20_CDD_FIRST 12 /* Index for first 20MHz OFDM CDD rate */
-#define WL_TX_POWER_OFDM40_SISO_FIRST 52 /* Index for first 40MHz OFDM SISO rate */
-#define WL_TX_POWER_OFDM40_CDD_FIRST 60 /* Index for first 40MHz OFDM CDD rate */
+/* Index for first 20MHz OFDM SISO rate */
+#define WL_TX_POWER_OFDM_FIRST 4
+/* Index for first 20MHz OFDM CDD rate */
+#define WL_TX_POWER_OFDM20_CDD_FIRST 12
+/* Index for first 40MHz OFDM SISO rate */
+#define WL_TX_POWER_OFDM40_SISO_FIRST 52
+/* Index for first 40MHz OFDM CDD rate */
+#define WL_TX_POWER_OFDM40_CDD_FIRST 60
#define WL_TX_POWER_OFDM_NUM 8
-#define WL_TX_POWER_MCS20_SISO_FIRST 20 /* Index for first 20MHz MCS SISO rate */
-#define WL_TX_POWER_MCS20_CDD_FIRST 28 /* Index for first 20MHz MCS CDD rate */
-#define WL_TX_POWER_MCS20_STBC_FIRST 36 /* Index for first 20MHz MCS STBC rate */
-#define WL_TX_POWER_MCS20_SDM_FIRST 44 /* Index for first 20MHz MCS SDM rate */
-#define WL_TX_POWER_MCS40_SISO_FIRST 68 /* Index for first 40MHz MCS SISO rate */
-#define WL_TX_POWER_MCS40_CDD_FIRST 76 /* Index for first 40MHz MCS CDD rate */
-#define WL_TX_POWER_MCS40_STBC_FIRST 84 /* Index for first 40MHz MCS STBC rate */
-#define WL_TX_POWER_MCS40_SDM_FIRST 92 /* Index for first 40MHz MCS SDM rate */
+/* Index for first 20MHz MCS SISO rate */
+#define WL_TX_POWER_MCS20_SISO_FIRST 20
+/* Index for first 20MHz MCS CDD rate */
+#define WL_TX_POWER_MCS20_CDD_FIRST 28
+/* Index for first 20MHz MCS STBC rate */
+#define WL_TX_POWER_MCS20_STBC_FIRST 36
+/* Index for first 20MHz MCS SDM rate */
+#define WL_TX_POWER_MCS20_SDM_FIRST 44
+/* Index for first 40MHz MCS SISO rate */
+#define WL_TX_POWER_MCS40_SISO_FIRST 68
+/* Index for first 40MHz MCS CDD rate */
+#define WL_TX_POWER_MCS40_CDD_FIRST 76
+/* Index for first 40MHz MCS STBC rate */
+#define WL_TX_POWER_MCS40_STBC_FIRST 84
+/* Index for first 40MHz MCS SDM rate */
+#define WL_TX_POWER_MCS40_SDM_FIRST 92
#define WL_TX_POWER_MCS_1_STREAM_NUM 8
#define WL_TX_POWER_MCS_2_STREAM_NUM 8
-#define WL_TX_POWER_MCS_32 100 /* Index for 40MHz rate MCS 32 */
+/* Index for 40MHz rate MCS 32 */
+#define WL_TX_POWER_MCS_32 100
#define WL_TX_POWER_MCS_32_NUM 1
/* sslpnphy specifics */
-#define WL_TX_POWER_MCS20_SISO_FIRST_SSN 12 /* Index for first 20MHz MCS SISO rate */
+/* Index for first 20MHz MCS SISO rate */
+#define WL_TX_POWER_MCS20_SISO_FIRST_SSN 12
/* struct tx_power::flags bits */
#define WL_TX_POWER_F_ENABLED 1
@@ -108,20 +122,20 @@
#define BRCMS_N_TXRX_CHAIN0 0
#define BRCMS_N_TXRX_CHAIN1 1
+struct brcms_phy;
+
extern struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
- void *wl, void *wlc);
+ struct brcms_info *wl,
+ struct brcms_c_info *wlc);
extern void wlc_phy_shim_detach(struct phy_shim_info *physhim);
/* PHY to WL utility functions */
extern struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
- void (*fn) (void *arg), void *arg,
- const char *name);
-extern void wlapi_free_timer(struct phy_shim_info *physhim,
- struct wlapi_timer *t);
-extern void wlapi_add_timer(struct phy_shim_info *physhim,
- struct wlapi_timer *t, uint ms, int periodic);
-extern bool wlapi_del_timer(struct phy_shim_info *physhim,
- struct wlapi_timer *t);
+ void (*fn) (struct brcms_phy *pi),
+ void *arg, const char *name);
+extern void wlapi_free_timer(struct wlapi_timer *t);
+extern void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic);
+extern bool wlapi_del_timer(struct wlapi_timer *t);
extern void wlapi_intrson(struct phy_shim_info *physhim);
extern u32 wlapi_intrsoff(struct phy_shim_info *physhim);
extern void wlapi_intrsrestore(struct phy_shim_info *physhim,
@@ -161,4 +175,8 @@ extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint,
extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim,
u32 phy_mode);
extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim);
+extern char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id);
+extern int wlapi_getintvar(struct phy_shim_info *physhim,
+ enum brcms_srom_id id);
+
#endif /* _BRCM_PHY_SHIM_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/pmu.c b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
index e8b2b81d2d04..3b36e3acfd74 100644
--- a/drivers/staging/brcm80211/brcmsmac/pmu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c
@@ -70,11 +70,13 @@
#define PMURES_BIT(bit) (1 << (bit))
/* PMU corerev and chip specific PLL controls.
- * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary number
- * to differentiate different PLLs controlled by the same PMU rev.
+ * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary
+ * number to differentiate different PLLs controlled by the same PMU rev.
+ */
+/* pllcontrol registers:
+ * ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>,
+ * p1div, p2div, _bypass_sdmod
*/
-/* pllcontrol registers */
-/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
#define PMU1_PLL0_PLLCTL0 0
#define PMU1_PLL0_PLLCTL1 1
#define PMU1_PLL0_PLLCTL2 2
@@ -137,7 +139,8 @@ static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
}
static void
-si_pmu_spuravoid_pllupdate(struct si_pub *sih, chipcregs_t *cc, u8 spuravoid)
+si_pmu_spuravoid_pllupdate(struct si_pub *sih, struct chipcregs __iomem *cc,
+ u8 spuravoid)
{
u32 tmp = 0;
@@ -199,28 +202,6 @@ si_pmu_spuravoid_pllupdate(struct si_pub *sih, chipcregs_t *cc, u8 spuravoid)
W_REG(&cc->pmucontrol, tmp);
}
-u32 si_pmu_ilp_clock(struct si_pub *sih)
-{
- static u32 ilpcycles_per_sec;
-
- if (!PMUCTL_ENAB(sih))
- return ILP_CLOCK;
-
- if (ilpcycles_per_sec == 0) {
- u32 start, end, delta;
- u32 origidx = ai_coreidx(sih);
- chipcregs_t *cc = ai_setcoreidx(sih, SI_CC_IDX);
- start = R_REG(&cc->pmutimer);
- mdelay(ILP_CALC_DUR);
- end = R_REG(&cc->pmutimer);
- delta = end - start;
- ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
- ai_setcoreidx(sih, origidx);
- }
-
- return ilpcycles_per_sec;
-}
-
u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
{
uint delay = PMU_MAX_TRANSITION_DLY;
@@ -240,7 +221,7 @@ u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
void si_pmu_sprom_enable(struct si_pub *sih, bool enable)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
/* Remember original core before switch to chipc */
@@ -254,34 +235,37 @@ void si_pmu_sprom_enable(struct si_pub *sih, bool enable)
/* Read/write a chipcontrol reg */
u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
- ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol_addr), ~0,
- reg);
+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol_addr),
+ ~0, reg);
return ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data), mask, val);
+ offsetof(struct chipcregs, chipcontrol_data), mask,
+ val);
}
/* Read/write a regcontrol reg */
u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
- ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, regcontrol_addr), ~0,
- reg);
+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, regcontrol_addr),
+ ~0, reg);
return ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, regcontrol_data), mask, val);
+ offsetof(struct chipcregs, regcontrol_data), mask,
+ val);
}
/* Read/write a pllcontrol reg */
u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
- ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pllcontrol_addr), ~0,
- reg);
+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pllcontrol_addr),
+ ~0, reg);
return ai_corereg(sih, SI_CC_IDX,
- offsetof(chipcregs_t, pllcontrol_data), mask, val);
+ offsetof(struct chipcregs, pllcontrol_data), mask,
+ val);
}
/* PMU PLL update */
void si_pmu_pllupd(struct si_pub *sih)
{
- ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pmucontrol),
+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pmucontrol),
PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
}
@@ -291,7 +275,7 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
u32 clock = ALP_CLOCK;
/* bail out with default */
- if (!PMUCTL_ENAB(sih))
+ if (!(sih->cccaps & CC_CAP_PMU))
return clock;
switch (sih->chip) {
@@ -310,12 +294,12 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx, intr_val;
/* Remember original core before switch to chipc */
- cc = (chipcregs_t *) ai_switch_core(sih, CC_CORE_ID, &origidx,
- &intr_val);
+ cc = (struct chipcregs __iomem *)
+ ai_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
/* update the pll changes */
si_pmu_spuravoid_pllupdate(sih, cc, spuravoid);
@@ -327,7 +311,7 @@ void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid)
/* initialize PMU */
void si_pmu_init(struct si_pub *sih)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
/* Remember original core before switch to chipc */
@@ -366,7 +350,7 @@ void si_pmu_swreg_init(struct si_pub *sih)
/* initialize PLL */
void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
/* Remember original core before switch to chipc */
@@ -390,7 +374,7 @@ void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq)
/* initialize PMU resources */
void si_pmu_res_init(struct si_pub *sih)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
u32 min_mask = 0, max_mask = 0;
@@ -422,7 +406,7 @@ void si_pmu_res_init(struct si_pub *sih)
u32 si_pmu_measure_alpclk(struct si_pub *sih)
{
- chipcregs_t *cc;
+ struct chipcregs __iomem *cc;
uint origidx;
u32 alp_khz;
diff --git a/drivers/staging/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
index 0c7e48c4bcd8..3a08c620640e 100644
--- a/drivers/staging/brcm80211/brcmsmac/pmu.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
@@ -19,25 +19,11 @@
#define _BRCM_PMU_H_
#include "types.h"
-/*
- * LDO selections used in si_pmu_set_ldo_voltage
- */
-#define SET_LDO_VOLTAGE_LDO1 1
-#define SET_LDO_VOLTAGE_LDO2 2
-#define SET_LDO_VOLTAGE_LDO3 3
-#define SET_LDO_VOLTAGE_PAREF 4
-#define SET_LDO_VOLTAGE_CLDO_PWM 5
-#define SET_LDO_VOLTAGE_CLDO_BURST 6
-#define SET_LDO_VOLTAGE_CBUCK_PWM 7
-#define SET_LDO_VOLTAGE_CBUCK_BURST 8
-#define SET_LDO_VOLTAGE_LNLDO1 9
-#define SET_LDO_VOLTAGE_LNLDO2_SEL 10
extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih);
extern void si_pmu_sprom_enable(struct si_pub *sih, bool enable);
extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
-extern u32 si_pmu_ilp_clock(struct si_pub *sih);
extern u32 si_pmu_alp_clock(struct si_pub *sih);
extern void si_pmu_pllupd(struct si_pub *sih);
extern void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
new file mode 100644
index 000000000000..37bb2dcc113f
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
@@ -0,0 +1,634 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_PUB_H_
+#define _BRCM_PUB_H_
+
+#include <brcmu_wifi.h>
+#include "types.h"
+#include "defs.h"
+
+enum brcms_srom_id {
+ BRCMS_SROM_NULL,
+ BRCMS_SROM_CONT,
+ BRCMS_SROM_AA2G,
+ BRCMS_SROM_AA5G,
+ BRCMS_SROM_AG0,
+ BRCMS_SROM_AG1,
+ BRCMS_SROM_AG2,
+ BRCMS_SROM_AG3,
+ BRCMS_SROM_ANTSWCTL2G,
+ BRCMS_SROM_ANTSWCTL5G,
+ BRCMS_SROM_ANTSWITCH,
+ BRCMS_SROM_BOARDFLAGS2,
+ BRCMS_SROM_BOARDFLAGS,
+ BRCMS_SROM_BOARDNUM,
+ BRCMS_SROM_BOARDREV,
+ BRCMS_SROM_BOARDTYPE,
+ BRCMS_SROM_BW40PO,
+ BRCMS_SROM_BWDUPPO,
+ BRCMS_SROM_BXA2G,
+ BRCMS_SROM_BXA5G,
+ BRCMS_SROM_CC,
+ BRCMS_SROM_CCK2GPO,
+ BRCMS_SROM_CCKBW202GPO,
+ BRCMS_SROM_CCKBW20UL2GPO,
+ BRCMS_SROM_CCODE,
+ BRCMS_SROM_CDDPO,
+ BRCMS_SROM_DEVID,
+ BRCMS_SROM_ET1MACADDR,
+ BRCMS_SROM_EXTPAGAIN2G,
+ BRCMS_SROM_EXTPAGAIN5G,
+ BRCMS_SROM_FREQOFFSET_CORR,
+ BRCMS_SROM_HW_IQCAL_EN,
+ BRCMS_SROM_IL0MACADDR,
+ BRCMS_SROM_IQCAL_SWP_DIS,
+ BRCMS_SROM_LEDBH0,
+ BRCMS_SROM_LEDBH1,
+ BRCMS_SROM_LEDBH2,
+ BRCMS_SROM_LEDBH3,
+ BRCMS_SROM_LEDDC,
+ BRCMS_SROM_LEGOFDM40DUPPO,
+ BRCMS_SROM_LEGOFDMBW202GPO,
+ BRCMS_SROM_LEGOFDMBW205GHPO,
+ BRCMS_SROM_LEGOFDMBW205GLPO,
+ BRCMS_SROM_LEGOFDMBW205GMPO,
+ BRCMS_SROM_LEGOFDMBW20UL2GPO,
+ BRCMS_SROM_LEGOFDMBW20UL5GHPO,
+ BRCMS_SROM_LEGOFDMBW20UL5GLPO,
+ BRCMS_SROM_LEGOFDMBW20UL5GMPO,
+ BRCMS_SROM_MACADDR,
+ BRCMS_SROM_MCS2GPO0,
+ BRCMS_SROM_MCS2GPO1,
+ BRCMS_SROM_MCS2GPO2,
+ BRCMS_SROM_MCS2GPO3,
+ BRCMS_SROM_MCS2GPO4,
+ BRCMS_SROM_MCS2GPO5,
+ BRCMS_SROM_MCS2GPO6,
+ BRCMS_SROM_MCS2GPO7,
+ BRCMS_SROM_MCS32PO,
+ BRCMS_SROM_MCS5GHPO0,
+ BRCMS_SROM_MCS5GHPO1,
+ BRCMS_SROM_MCS5GHPO2,
+ BRCMS_SROM_MCS5GHPO3,
+ BRCMS_SROM_MCS5GHPO4,
+ BRCMS_SROM_MCS5GHPO5,
+ BRCMS_SROM_MCS5GHPO6,
+ BRCMS_SROM_MCS5GHPO7,
+ BRCMS_SROM_MCS5GLPO0,
+ BRCMS_SROM_MCS5GLPO1,
+ BRCMS_SROM_MCS5GLPO2,
+ BRCMS_SROM_MCS5GLPO3,
+ BRCMS_SROM_MCS5GLPO4,
+ BRCMS_SROM_MCS5GLPO5,
+ BRCMS_SROM_MCS5GLPO6,
+ BRCMS_SROM_MCS5GLPO7,
+ BRCMS_SROM_MCS5GPO0,
+ BRCMS_SROM_MCS5GPO1,
+ BRCMS_SROM_MCS5GPO2,
+ BRCMS_SROM_MCS5GPO3,
+ BRCMS_SROM_MCS5GPO4,
+ BRCMS_SROM_MCS5GPO5,
+ BRCMS_SROM_MCS5GPO6,
+ BRCMS_SROM_MCS5GPO7,
+ BRCMS_SROM_MCSBW202GPO,
+ BRCMS_SROM_MCSBW205GHPO,
+ BRCMS_SROM_MCSBW205GLPO,
+ BRCMS_SROM_MCSBW205GMPO,
+ BRCMS_SROM_MCSBW20UL2GPO,
+ BRCMS_SROM_MCSBW20UL5GHPO,
+ BRCMS_SROM_MCSBW20UL5GLPO,
+ BRCMS_SROM_MCSBW20UL5GMPO,
+ BRCMS_SROM_MCSBW402GPO,
+ BRCMS_SROM_MCSBW405GHPO,
+ BRCMS_SROM_MCSBW405GLPO,
+ BRCMS_SROM_MCSBW405GMPO,
+ BRCMS_SROM_MEASPOWER,
+ BRCMS_SROM_OFDM2GPO,
+ BRCMS_SROM_OFDM5GHPO,
+ BRCMS_SROM_OFDM5GLPO,
+ BRCMS_SROM_OFDM5GPO,
+ BRCMS_SROM_OPO,
+ BRCMS_SROM_PA0B0,
+ BRCMS_SROM_PA0B1,
+ BRCMS_SROM_PA0B2,
+ BRCMS_SROM_PA0ITSSIT,
+ BRCMS_SROM_PA0MAXPWR,
+ BRCMS_SROM_PA1B0,
+ BRCMS_SROM_PA1B1,
+ BRCMS_SROM_PA1B2,
+ BRCMS_SROM_PA1HIB0,
+ BRCMS_SROM_PA1HIB1,
+ BRCMS_SROM_PA1HIB2,
+ BRCMS_SROM_PA1HIMAXPWR,
+ BRCMS_SROM_PA1ITSSIT,
+ BRCMS_SROM_PA1LOB0,
+ BRCMS_SROM_PA1LOB1,
+ BRCMS_SROM_PA1LOB2,
+ BRCMS_SROM_PA1LOMAXPWR,
+ BRCMS_SROM_PA1MAXPWR,
+ BRCMS_SROM_PDETRANGE2G,
+ BRCMS_SROM_PDETRANGE5G,
+ BRCMS_SROM_PHYCAL_TEMPDELTA,
+ BRCMS_SROM_RAWTEMPSENSE,
+ BRCMS_SROM_REGREV,
+ BRCMS_SROM_REV,
+ BRCMS_SROM_RSSISAV2G,
+ BRCMS_SROM_RSSISAV5G,
+ BRCMS_SROM_RSSISMC2G,
+ BRCMS_SROM_RSSISMC5G,
+ BRCMS_SROM_RSSISMF2G,
+ BRCMS_SROM_RSSISMF5G,
+ BRCMS_SROM_RXCHAIN,
+ BRCMS_SROM_RXPO2G,
+ BRCMS_SROM_RXPO5G,
+ BRCMS_SROM_STBCPO,
+ BRCMS_SROM_TEMPCORRX,
+ BRCMS_SROM_TEMPOFFSET,
+ BRCMS_SROM_TEMPSENSE_OPTION,
+ BRCMS_SROM_TEMPSENSE_SLOPE,
+ BRCMS_SROM_TEMPTHRESH,
+ BRCMS_SROM_TRI2G,
+ BRCMS_SROM_TRI5GH,
+ BRCMS_SROM_TRI5GL,
+ BRCMS_SROM_TRI5G,
+ BRCMS_SROM_TRISO2G,
+ BRCMS_SROM_TRISO5G,
+ BRCMS_SROM_TSSIPOS2G,
+ BRCMS_SROM_TSSIPOS5G,
+ BRCMS_SROM_TXCHAIN,
+ BRCMS_SROM_TXPID2GA0,
+ BRCMS_SROM_TXPID2GA1,
+ BRCMS_SROM_TXPID2GA2,
+ BRCMS_SROM_TXPID2GA3,
+ BRCMS_SROM_TXPID5GA0,
+ BRCMS_SROM_TXPID5GA1,
+ BRCMS_SROM_TXPID5GA2,
+ BRCMS_SROM_TXPID5GA3,
+ BRCMS_SROM_TXPID5GHA0,
+ BRCMS_SROM_TXPID5GHA1,
+ BRCMS_SROM_TXPID5GHA2,
+ BRCMS_SROM_TXPID5GHA3,
+ BRCMS_SROM_TXPID5GLA0,
+ BRCMS_SROM_TXPID5GLA1,
+ BRCMS_SROM_TXPID5GLA2,
+ BRCMS_SROM_TXPID5GLA3,
+ /*
+ * per-path identifiers (see srom.c)
+ */
+ BRCMS_SROM_ITT2GA0,
+ BRCMS_SROM_ITT2GA1,
+ BRCMS_SROM_ITT2GA2,
+ BRCMS_SROM_ITT2GA3,
+ BRCMS_SROM_ITT5GA0,
+ BRCMS_SROM_ITT5GA1,
+ BRCMS_SROM_ITT5GA2,
+ BRCMS_SROM_ITT5GA3,
+ BRCMS_SROM_MAXP2GA0,
+ BRCMS_SROM_MAXP2GA1,
+ BRCMS_SROM_MAXP2GA2,
+ BRCMS_SROM_MAXP2GA3,
+ BRCMS_SROM_MAXP5GA0,
+ BRCMS_SROM_MAXP5GA1,
+ BRCMS_SROM_MAXP5GA2,
+ BRCMS_SROM_MAXP5GA3,
+ BRCMS_SROM_MAXP5GHA0,
+ BRCMS_SROM_MAXP5GHA1,
+ BRCMS_SROM_MAXP5GHA2,
+ BRCMS_SROM_MAXP5GHA3,
+ BRCMS_SROM_MAXP5GLA0,
+ BRCMS_SROM_MAXP5GLA1,
+ BRCMS_SROM_MAXP5GLA2,
+ BRCMS_SROM_MAXP5GLA3,
+ BRCMS_SROM_PA2GW0A0,
+ BRCMS_SROM_PA2GW0A1,
+ BRCMS_SROM_PA2GW0A2,
+ BRCMS_SROM_PA2GW0A3,
+ BRCMS_SROM_PA2GW1A0,
+ BRCMS_SROM_PA2GW1A1,
+ BRCMS_SROM_PA2GW1A2,
+ BRCMS_SROM_PA2GW1A3,
+ BRCMS_SROM_PA2GW2A0,
+ BRCMS_SROM_PA2GW2A1,
+ BRCMS_SROM_PA2GW2A2,
+ BRCMS_SROM_PA2GW2A3,
+ BRCMS_SROM_PA2GW3A0,
+ BRCMS_SROM_PA2GW3A1,
+ BRCMS_SROM_PA2GW3A2,
+ BRCMS_SROM_PA2GW3A3,
+ BRCMS_SROM_PA5GHW0A0,
+ BRCMS_SROM_PA5GHW0A1,
+ BRCMS_SROM_PA5GHW0A2,
+ BRCMS_SROM_PA5GHW0A3,
+ BRCMS_SROM_PA5GHW1A0,
+ BRCMS_SROM_PA5GHW1A1,
+ BRCMS_SROM_PA5GHW1A2,
+ BRCMS_SROM_PA5GHW1A3,
+ BRCMS_SROM_PA5GHW2A0,
+ BRCMS_SROM_PA5GHW2A1,
+ BRCMS_SROM_PA5GHW2A2,
+ BRCMS_SROM_PA5GHW2A3,
+ BRCMS_SROM_PA5GHW3A0,
+ BRCMS_SROM_PA5GHW3A1,
+ BRCMS_SROM_PA5GHW3A2,
+ BRCMS_SROM_PA5GHW3A3,
+ BRCMS_SROM_PA5GLW0A0,
+ BRCMS_SROM_PA5GLW0A1,
+ BRCMS_SROM_PA5GLW0A2,
+ BRCMS_SROM_PA5GLW0A3,
+ BRCMS_SROM_PA5GLW1A0,
+ BRCMS_SROM_PA5GLW1A1,
+ BRCMS_SROM_PA5GLW1A2,
+ BRCMS_SROM_PA5GLW1A3,
+ BRCMS_SROM_PA5GLW2A0,
+ BRCMS_SROM_PA5GLW2A1,
+ BRCMS_SROM_PA5GLW2A2,
+ BRCMS_SROM_PA5GLW2A3,
+ BRCMS_SROM_PA5GLW3A0,
+ BRCMS_SROM_PA5GLW3A1,
+ BRCMS_SROM_PA5GLW3A2,
+ BRCMS_SROM_PA5GLW3A3,
+ BRCMS_SROM_PA5GW0A0,
+ BRCMS_SROM_PA5GW0A1,
+ BRCMS_SROM_PA5GW0A2,
+ BRCMS_SROM_PA5GW0A3,
+ BRCMS_SROM_PA5GW1A0,
+ BRCMS_SROM_PA5GW1A1,
+ BRCMS_SROM_PA5GW1A2,
+ BRCMS_SROM_PA5GW1A3,
+ BRCMS_SROM_PA5GW2A0,
+ BRCMS_SROM_PA5GW2A1,
+ BRCMS_SROM_PA5GW2A2,
+ BRCMS_SROM_PA5GW2A3,
+ BRCMS_SROM_PA5GW3A0,
+ BRCMS_SROM_PA5GW3A1,
+ BRCMS_SROM_PA5GW3A2,
+ BRCMS_SROM_PA5GW3A3,
+};
+
+#define BRCMS_NUMRATES 16 /* max # of rates in a rateset */
+#define D11_PHY_HDR_LEN 6 /* Phy header length - 6 bytes */
+
+/* phy types */
+#define PHY_TYPE_A 0 /* Phy type A */
+#define PHY_TYPE_G 2 /* Phy type G */
+#define PHY_TYPE_N 4 /* Phy type N */
+#define PHY_TYPE_LP 5 /* Phy type Low Power A/B/G */
+#define PHY_TYPE_SSN 6 /* Phy type Single Stream N */
+#define PHY_TYPE_LCN 8 /* Phy type Single Stream N */
+#define PHY_TYPE_LCNXN 9 /* Phy type 2-stream N */
+#define PHY_TYPE_HT 7 /* Phy type 3-Stream N */
+
+/* bw */
+#define BRCMS_10_MHZ 10 /* 10Mhz nphy channel bandwidth */
+#define BRCMS_20_MHZ 20 /* 20Mhz nphy channel bandwidth */
+#define BRCMS_40_MHZ 40 /* 40Mhz nphy channel bandwidth */
+
+#define BRCMS_RSSI_MINVAL -200 /* Low value, e.g. for forcing roam */
+#define BRCMS_RSSI_NO_SIGNAL -91 /* NDIS RSSI link quality cutoffs */
+#define BRCMS_RSSI_VERY_LOW -80 /* Very low quality cutoffs */
+#define BRCMS_RSSI_LOW -70 /* Low quality cutoffs */
+#define BRCMS_RSSI_GOOD -68 /* Good quality cutoffs */
+#define BRCMS_RSSI_VERY_GOOD -58 /* Very good quality cutoffs */
+#define BRCMS_RSSI_EXCELLENT -57 /* Excellent quality cutoffs */
+
+/* a large TX Power as an init value to factor out of min() calculations,
+ * keep low enough to fit in an s8, units are .25 dBm
+ */
+#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */
+
+/* rate related definitions */
+#define BRCMS_RATE_FLAG 0x80 /* Flag to indicate it is a basic rate */
+#define BRCMS_RATE_MASK 0x7f /* Rate value mask w/o basic rate flag */
+
+/* legacy rx Antenna diversity for SISO rates */
+#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */
+#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */
+#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */
+#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */
+#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */
+/* default antdiv setting */
+#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0
+
+/* legacy rx Antenna diversity for SISO rates */
+/* Tx on antenna 0, "legacy term Main" */
+#define ANT_TX_FORCE_0 0
+/* Tx on antenna 1, "legacy term Aux" */
+#define ANT_TX_FORCE_1 1
+/* Tx on phy's last good Rx antenna */
+#define ANT_TX_LAST_RX 3
+/* driver's default tx antenna setting */
+#define ANT_TX_DEF 3
+
+/* Tx Chain values */
+/* def bitmap of txchain */
+#define TXCHAIN_DEF 0x1
+/* default bitmap of tx chains for nphy */
+#define TXCHAIN_DEF_NPHY 0x3
+/* default bitmap of tx chains for nphy */
+#define TXCHAIN_DEF_HTPHY 0x7
+/* def bitmap of rxchain */
+#define RXCHAIN_DEF 0x1
+/* default bitmap of rx chains for nphy */
+#define RXCHAIN_DEF_NPHY 0x3
+/* default bitmap of rx chains for nphy */
+#define RXCHAIN_DEF_HTPHY 0x7
+/* no antenna switch */
+#define ANTSWITCH_NONE 0
+/* antenna switch on 4321CB2, 2of3 */
+#define ANTSWITCH_TYPE_1 1
+/* antenna switch on 4321MPCI, 2of3 */
+#define ANTSWITCH_TYPE_2 2
+/* antenna switch on 4322, 2of3 */
+#define ANTSWITCH_TYPE_3 3
+
+#define RXBUFSZ PKTBUFSZ
+
+#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */
+
+struct brcm_rateset {
+ /* # rates in this set */
+ u32 count;
+ /* rates in 500kbps units w/hi bit set if basic */
+ u8 rates[WL_NUMRATES];
+};
+
+struct brcms_c_rateset {
+ uint count; /* number of rates in rates[] */
+ /* rates in 500kbps units w/hi bit set if basic */
+ u8 rates[BRCMS_NUMRATES];
+ u8 htphy_membership; /* HT PHY Membership */
+ u8 mcs[MCSSET_LEN]; /* supported mcs index bit map */
+};
+
+/* All the HT-specific default advertised capabilities (including AMPDU)
+ * should be grouped here at one place
+ */
+#define AMPDU_DEF_MPDU_DENSITY 6 /* default mpdu density (110 ==> 4us) */
+
+/* wlc internal bss_info */
+struct brcms_bss_info {
+ u8 BSSID[ETH_ALEN]; /* network BSSID */
+ u16 flags; /* flags for internal attributes */
+ u8 SSID_len; /* the length of SSID */
+ u8 SSID[32]; /* SSID string */
+ s16 RSSI; /* receive signal strength (in dBm) */
+ s16 SNR; /* receive signal SNR in dB */
+ u16 beacon_period; /* units are Kusec */
+ u16 chanspec; /* Channel num, bw, ctrl_sb and band */
+ struct brcms_c_rateset rateset; /* supported rates */
+};
+
+#define MAC80211_PROMISC_BCNS (1 << 0)
+#define MAC80211_SCAN (1 << 1)
+
+/*
+ * Public portion of common driver state structure.
+ * The wlc handle points at this.
+ */
+struct brcms_pub {
+ struct brcms_c_info *wlc;
+ struct ieee80211_hw *ieee_hw;
+ struct scb_ampdu *global_ampdu;
+ uint mac80211_state;
+ uint unit; /* device instance number */
+ uint corerev; /* core revision */
+ struct si_pub *sih; /* SI handle (cookie for siutils calls) */
+ bool up; /* interface up and running */
+ bool hw_off; /* HW is off */
+ bool hw_up; /* one time hw up/down */
+ bool _piomode; /* true if pio mode */
+ uint _nbands; /* # bands supported */
+ uint now; /* # elapsed seconds */
+
+ bool promisc; /* promiscuous destination address */
+ bool delayed_down; /* down delayed */
+ bool associated; /* true:part of [I]BSS, false: not */
+ /* (union of stas_associated, aps_associated) */
+ bool _ampdu; /* ampdu enabled or not */
+ u8 _n_enab; /* bitmap of 11N + HT support */
+
+ u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */
+
+ int bcmerror; /* last bcm error */
+
+ u32 radio_disabled; /* bit vector for radio disabled reasons */
+
+ u16 boardrev; /* version # of particular board */
+ u8 sromrev; /* version # of the srom */
+ char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */
+ u32 boardflags; /* Board specific flags from srom */
+ u32 boardflags2; /* More board flags if sromrev >= 4 */
+ bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */
+
+ struct wl_cnt *_cnt; /* low-level counters in driver */
+};
+
+enum wlc_par_id {
+ IOV_MPC = 1,
+ IOV_RTSTHRESH,
+ IOV_QTXPOWER,
+ IOV_BCN_LI_BCN /* Beacon listen interval in # of beacons */
+};
+
+/***********************************************
+ * Feature-related macros to optimize out code *
+ * *********************************************
+ */
+
+#define ENAB_1x1 0x01
+#define ENAB_2x2 0x02
+#define ENAB_3x3 0x04
+#define ENAB_4x4 0x08
+#define SUPPORT_11N (ENAB_1x1|ENAB_2x2)
+#define SUPPORT_HT (ENAB_1x1|ENAB_2x2|ENAB_3x3)
+
+/* 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 */
+#define BRCMS_PROT_G_USER 3 /* gmode specified by user */
+#define BRCMS_PROT_OVERLAP 4 /* overlap */
+#define BRCMS_PROT_N_USER 10 /* nmode specified by user */
+#define BRCMS_PROT_N_CFG 11 /* n protection */
+#define BRCMS_PROT_N_CFG_OVR 12 /* n protection override */
+#define BRCMS_PROT_N_NONGF 13 /* non-GF protection */
+#define BRCMS_PROT_N_NONGF_OVR 14 /* non-GF protection override */
+#define BRCMS_PROT_N_PAM_OVR 15 /* n preamble override */
+#define BRCMS_PROT_N_OBSS 16 /* non-HT OBSS present */
+
+/*
+ * 54g modes (basic bits may still be overridden)
+ *
+ * GMODE_LEGACY_B
+ * Rateset: 1b, 2b, 5.5, 11
+ * Preamble: Long
+ * Shortslot: Off
+ * GMODE_AUTO
+ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ * Extended Rateset: 6, 9, 12, 48
+ * Preamble: Long
+ * Shortslot: Auto
+ * GMODE_ONLY
+ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54
+ * Extended Rateset: 6b, 9, 12b, 48
+ * Preamble: Short required
+ * Shortslot: Auto
+ * GMODE_B_DEFERRED
+ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ * Extended Rateset: 6, 9, 12, 48
+ * Preamble: Long
+ * Shortslot: On
+ * GMODE_PERFORMANCE
+ * Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54
+ * Preamble: Short required
+ * Shortslot: On and required
+ * GMODE_LRS
+ * Rateset: 1b, 2b, 5.5b, 11b
+ * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54
+ * Preamble: Long
+ * Shortslot: Auto
+ */
+#define GMODE_LEGACY_B 0
+#define GMODE_AUTO 1
+#define GMODE_ONLY 2
+#define GMODE_B_DEFERRED 3
+#define GMODE_PERFORMANCE 4
+#define GMODE_LRS 5
+#define GMODE_MAX 6
+
+/* MCS values greater than this enable multiple streams */
+#define HIGHEST_SINGLE_STREAM_MCS 7
+
+#define MAXBANDS 2 /* Maximum #of bands */
+
+/* max number of antenna configurations */
+#define ANT_SELCFG_MAX 4
+
+struct brcms_antselcfg {
+ u8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */
+ u8 num_antcfg; /* number of available antenna configurations */
+};
+
+/* common functions for every port */
+extern struct brcms_c_info *
+brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
+ bool piomode, void __iomem *regsva, struct pci_dev *btparam,
+ uint *perr);
+extern uint brcms_c_detach(struct brcms_c_info *wlc);
+extern int brcms_c_up(struct brcms_c_info *wlc);
+extern uint brcms_c_down(struct brcms_c_info *wlc);
+
+extern bool brcms_c_chipmatch(u16 vendor, u16 device);
+extern void brcms_c_init(struct brcms_c_info *wlc);
+extern void brcms_c_reset(struct brcms_c_info *wlc);
+
+extern void brcms_c_intrson(struct brcms_c_info *wlc);
+extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc);
+extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask);
+extern bool brcms_c_intrsupd(struct brcms_c_info *wlc);
+extern bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc);
+extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded);
+extern void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc,
+ struct sk_buff *sdu,
+ struct ieee80211_hw *hw);
+extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid);
+extern void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx,
+ int val);
+extern int brcms_c_get_header_len(void);
+extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc,
+ int match_reg_offset,
+ const u8 *addr);
+extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
+ const struct ieee80211_tx_queue_params *arg,
+ bool suspend);
+extern struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc);
+extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
+ struct ieee80211_sta *sta, u16 tid);
+extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
+ u8 ba_wsize, uint max_rx_ampdu_bytes);
+extern char *getvar(struct si_pub *sih, enum brcms_srom_id id);
+extern int getintvar(struct si_pub *sih, enum brcms_srom_id id);
+extern int brcms_c_module_register(struct brcms_pub *pub,
+ const char *name, struct brcms_info *hdl,
+ int (*down_fn)(void *handle));
+extern int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
+ struct brcms_info *hdl);
+extern void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc);
+extern void brcms_c_enable_mac(struct brcms_c_info *wlc);
+extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
+extern void brcms_c_scan_start(struct brcms_c_info *wlc);
+extern void brcms_c_scan_stop(struct brcms_c_info *wlc);
+extern int brcms_c_get_curband(struct brcms_c_info *wlc);
+extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc,
+ bool drop);
+extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
+extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
+extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
+ struct brcm_rateset *currs);
+extern int brcms_c_set_rateset(struct brcms_c_info *wlc,
+ struct brcm_rateset *rs);
+extern int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period);
+extern u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx);
+extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc,
+ s8 sslot_override);
+extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
+ u8 interval);
+extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
+extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
+extern void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc);
+extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
+
+#endif /* _BRCM_PUB_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/rate.c b/drivers/net/wireless/brcm80211/brcmsmac/rate.c
index f0e4b99c2566..0a0c0ad4f96f 100644
--- a/drivers/staging/brcm80211/brcmsmac/rate.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/rate.c
@@ -21,7 +21,10 @@
#include "pub.h"
#include "rate.h"
-/* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate value */
+/*
+ * Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate
+ * value
+ */
const u8 rate_info[BRCM_MAXRATE + 1] = {
/* 0 1 2 3 4 5 6 7 8 9 */
/* 0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -139,20 +142,25 @@ const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = {
{0, 6000, 0, CEIL(6000 * 10, 9), 0x00, BRCM_RATE_6M},
};
-/* phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams
- * Number of spatial streams: always 1
- * other fields: refer to table 78 of section 17.3.2.2 of the original .11a standard
+/*
+ * phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams
+ * Number of spatial streams: always 1 other fields: refer to table 78 of
+ * section 17.3.2.2 of the original .11a standard
*/
struct legacy_phycfg {
u32 rate_ofdm; /* ofdm mac rate */
- u8 tx_phy_ctl3; /* phy ctl byte 3, code rate, modulation type, # of streams */
+ /* phy ctl byte 3, code rate, modulation type, # of streams */
+ u8 tx_phy_ctl3;
};
-#define LEGACY_PHYCFG_TABLE_SIZE 12 /* Number of legacy_rate_cfg entries in the table */
+/* Number of legacy_rate_cfg entries in the table */
+#define LEGACY_PHYCFG_TABLE_SIZE 12
-/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
-/* Eventually MIMOPHY would also be converted to this format */
-/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
+/*
+ * In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate
+ * Eventually MIMOPHY would also be converted to this format
+ * 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps
+ */
static const struct
legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
{BRCM_RATE_1M, 0x00}, /* CCK 1Mbps, data rate 0 */
@@ -179,86 +187,89 @@ legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
/* Hardware rates (also encodes default basic rates) */
-const wlc_rateset_t cck_ofdm_mimo_rates = {
+const struct brcms_c_rateset cck_ofdm_mimo_rates = {
12,
- { /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */
- 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
- 0x6c},
+ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, */
+ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+ /* 54 Mbps */
+ 0x6c},
0x00,
- {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
+ { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t ofdm_mimo_rates = {
+const struct brcms_c_rateset ofdm_mimo_rates = {
8,
- { /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
- 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
+ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0x00,
- {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
+ { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
/* Default ratesets that include MCS32 for 40BW channels */
-const wlc_rateset_t cck_ofdm_40bw_mimo_rates = {
+static const struct brcms_c_rateset cck_ofdm_40bw_mimo_rates = {
12,
- { /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */
- 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
- 0x6c},
+ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48 */
+ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+ /* 54 Mbps */
+ 0x6c},
0x00,
- {0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
+ { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t ofdm_40bw_mimo_rates = {
+static const struct brcms_c_rateset ofdm_40bw_mimo_rates = {
8,
- { /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
- 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
+ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0x00,
- {0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
+ { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t cck_ofdm_rates = {
+const struct brcms_c_rateset cck_ofdm_rates = {
12,
- { /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */
- 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
- 0x6c},
+ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48,*/
+ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+ /*54 Mbps */
+ 0x6c},
0x00,
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t gphy_legacy_rates = {
+const struct brcms_c_rateset gphy_legacy_rates = {
4,
- { /* 1b, 2b, 5.5b, 11b Mbps */
- 0x82, 0x84, 0x8b, 0x96},
+ /* 1b, 2b, 5.5b, 11b Mbps */
+ { 0x82, 0x84, 0x8b, 0x96},
0x00,
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t ofdm_rates = {
+const struct brcms_c_rateset ofdm_rates = {
8,
- { /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
- 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
+ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0x00,
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
-const wlc_rateset_t cck_rates = {
+const struct brcms_c_rateset cck_rates = {
4,
- { /* 1b, 2b, 5.5, 11 Mbps */
- 0x82, 0x84, 0x0b, 0x16},
+ /* 1b, 2b, 5.5, 11 Mbps */
+ { 0x82, 0x84, 0x0b, 0x16},
0x00,
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00}
};
/* check if rateset is valid.
* if check_brate is true, rateset without a basic rate is considered NOT valid.
*/
-static bool brcms_c_rateset_valid(wlc_rateset_t *rs, bool check_brate)
+static bool brcms_c_rateset_valid(struct brcms_c_rateset *rs, bool check_brate)
{
uint idx;
@@ -276,19 +287,20 @@ static bool brcms_c_rateset_valid(wlc_rateset_t *rs, bool check_brate)
return false;
}
-void brcms_c_rateset_mcs_upd(wlc_rateset_t *rs, u8 txstreams)
+void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams)
{
int i;
for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++)
rs->mcs[i] = 0;
}
-/* filter based on hardware rateset, and sort filtered rateset with basic bit(s) preserved,
- * and check if resulting rateset is valid.
+/*
+ * filter based on hardware rateset, and sort filtered rateset with basic
+ * bit(s) preserved, and check if resulting rateset is valid.
*/
bool
-brcms_c_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs,
- const wlc_rateset_t *hw_rs,
+brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs,
+ const struct brcms_c_rateset *hw_rs,
bool check_brate, u8 txstreams)
{
u8 rateset[BRCM_MAXRATE + 1];
@@ -328,10 +340,10 @@ brcms_c_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs,
}
/* calculate the rate of a rx'd frame and return it as a ratespec */
-ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
+u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
{
int phy_type;
- ratespec_t rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
+ u32 rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
phy_type =
((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
@@ -341,12 +353,12 @@ ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
case PRXS0_CCK:
rspec =
- CCK_PHY2MAC_RATE(
+ cck_phy2mac_rate(
((struct cck_phy_hdr *) plcp)->signal);
break;
case PRXS0_OFDM:
rspec =
- OFDM_PHY2MAC_RATE(
+ ofdm_phy2mac_rate(
((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
break;
case PRXS0_PREN:
@@ -363,23 +375,24 @@ ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
/* not supported, error condition */
break;
}
- if (PLCP3_ISSGI(plcp[3]))
+ if (plcp3_issgi(plcp[3]))
rspec |= RSPEC_SHORT_GI;
} else
if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM))
- rspec = OFDM_PHY2MAC_RATE(
+ rspec = ofdm_phy2mac_rate(
((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
else
- rspec = CCK_PHY2MAC_RATE(
+ rspec = cck_phy2mac_rate(
((struct cck_phy_hdr *) plcp)->signal);
return rspec;
}
/* copy rateset src to dst as-is (no masking or sorting) */
-void brcms_c_rateset_copy(const wlc_rateset_t *src, wlc_rateset_t *dst)
+void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
+ struct brcms_c_rateset *dst)
{
- memcpy(dst, src, sizeof(wlc_rateset_t));
+ memcpy(dst, src, sizeof(struct brcms_c_rateset));
}
/*
@@ -392,8 +405,8 @@ void brcms_c_rateset_copy(const wlc_rateset_t *src, wlc_rateset_t *dst)
* 'xmask' is the copy mask (typically 0x7f or 0xff).
*/
void
-brcms_c_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
- u8 rates, uint xmask, bool mcsallow)
+brcms_c_rateset_filter(struct brcms_c_rateset *src, struct brcms_c_rateset *dst,
+ bool basic_only, u8 rates, uint xmask, bool mcsallow)
{
uint i;
uint r;
@@ -404,9 +417,11 @@ brcms_c_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
r = src->rates[i];
if (basic_only && !(r & BRCMS_RATE_FLAG))
continue;
- if (rates == BRCMS_RATES_CCK && IS_OFDM((r & BRCMS_RATE_MASK)))
+ if (rates == BRCMS_RATES_CCK &&
+ is_ofdm_rate((r & BRCMS_RATE_MASK)))
continue;
- if (rates == BRCMS_RATES_OFDM && IS_CCK((r & BRCMS_RATE_MASK)))
+ if (rates == BRCMS_RATES_OFDM &&
+ is_cck_rate((r & BRCMS_RATE_MASK)))
continue;
dst->rates[count++] = r & xmask;
}
@@ -423,26 +438,27 @@ brcms_c_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
* and fill rs_tgt with result
*/
void
-brcms_c_rateset_default(wlc_rateset_t *rs_tgt, const wlc_rateset_t *rs_hw,
- uint phy_type, int bandtype, bool cck_only, uint rate_mask,
- bool mcsallow, u8 bw, u8 txstreams)
+brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt,
+ const struct brcms_c_rateset *rs_hw,
+ uint phy_type, int bandtype, bool cck_only,
+ uint rate_mask, bool mcsallow, u8 bw, u8 txstreams)
{
- const wlc_rateset_t *rs_dflt;
- wlc_rateset_t rs_sel;
+ const struct brcms_c_rateset *rs_dflt;
+ struct brcms_c_rateset rs_sel;
if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) ||
(PHYTYPE_IS(phy_type, PHY_TYPE_N)) ||
(PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) ||
(PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) {
- if (BAND_5G(bandtype)) {
+ if (bandtype == BRCM_BAND_5G)
rs_dflt = (bw == BRCMS_20_MHZ ?
&ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
- } else {
+ else
rs_dflt = (bw == BRCMS_20_MHZ ?
&cck_ofdm_mimo_rates :
&cck_ofdm_40bw_mimo_rates);
- }
} else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) {
- rs_dflt = (BAND_5G(bandtype)) ? &ofdm_rates : &cck_ofdm_rates;
+ rs_dflt = (bandtype == BRCM_BAND_5G) ?
+ &ofdm_rates : &cck_ofdm_rates;
} else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) {
rs_dflt = &ofdm_rates;
} else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) {
@@ -475,21 +491,21 @@ s16 brcms_c_rate_legacy_phyctl(uint rate)
return -1;
}
-void brcms_c_rateset_mcs_clear(wlc_rateset_t *rateset)
+void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset)
{
uint i;
for (i = 0; i < MCSSET_LEN; i++)
rateset->mcs[i] = 0;
}
-void brcms_c_rateset_mcs_build(wlc_rateset_t *rateset, u8 txstreams)
+void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams)
{
memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN);
brcms_c_rateset_mcs_upd(rateset, txstreams);
}
/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */
-void brcms_c_rateset_bw_mcs_filter(wlc_rateset_t *rateset, u8 bw)
+void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw)
{
if (bw == BRCMS_40_MHZ)
setbit(rateset->mcs, 32);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/rate.h b/drivers/net/wireless/brcm80211/brcmsmac/rate.h
new file mode 100644
index 000000000000..e7b9dc2f2731
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/rate.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_RATE_H_
+#define _BRCM_RATE_H_
+
+#include "types.h"
+#include "d11.h"
+
+extern const u8 rate_info[];
+extern const struct brcms_c_rateset cck_ofdm_mimo_rates;
+extern const struct brcms_c_rateset ofdm_mimo_rates;
+extern const struct brcms_c_rateset cck_ofdm_rates;
+extern const struct brcms_c_rateset ofdm_rates;
+extern const struct brcms_c_rateset cck_rates;
+extern const struct brcms_c_rateset gphy_legacy_rates;
+extern const struct brcms_c_rateset rate_limit_1_2;
+
+struct brcms_mcs_info {
+ /* phy rate in kbps [20Mhz] */
+ u32 phy_rate_20;
+ /* phy rate in kbps [40Mhz] */
+ u32 phy_rate_40;
+ /* phy rate in kbps [20Mhz] with SGI */
+ u32 phy_rate_20_sgi;
+ /* phy rate in kbps [40Mhz] with SGI */
+ u32 phy_rate_40_sgi;
+ /* phy ctl byte 3, code rate, modulation type, # of streams */
+ u8 tx_phy_ctl3;
+ /* matching legacy ofdm rate in 500bkps */
+ u8 leg_ofdm;
+};
+
+#define BRCMS_MAXMCS 32 /* max valid mcs index */
+#define MCS_TABLE_SIZE 33 /* Number of mcs entries in the table */
+extern const struct brcms_mcs_info mcs_table[];
+
+#define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */
+#define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */
+
+/* returns num tx streams - 1 */
+static inline u8 mcs_2_txstreams(u8 mcs)
+{
+ return (mcs_table[mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT;
+}
+
+static inline uint mcs_2_rate(u8 mcs, bool is40, bool sgi)
+{
+ if (sgi) {
+ if (is40)
+ return mcs_table[mcs].phy_rate_40_sgi;
+ return mcs_table[mcs].phy_rate_20_sgi;
+ }
+ if (is40)
+ return mcs_table[mcs].phy_rate_40;
+
+ return mcs_table[mcs].phy_rate_20;
+}
+
+/* Macro to use the rate_info table */
+#define BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */
+
+/*
+ * rate spec : holds rate and mode specific information required to generate a
+ * tx frame. Legacy CCK and OFDM information is held in the same manner as was
+ * done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO
+ * specific information
+ */
+
+/* rate spec bit fields */
+
+/* Either 500Kbps units or MIMO MCS idx */
+#define RSPEC_RATE_MASK 0x0000007F
+/* mimo MCS is stored in RSPEC_RATE_MASK */
+#define RSPEC_MIMORATE 0x08000000
+/* mimo bw mask */
+#define RSPEC_BW_MASK 0x00000700
+/* mimo bw shift */
+#define RSPEC_BW_SHIFT 8
+/* mimo Space/Time/Frequency mode mask */
+#define RSPEC_STF_MASK 0x00003800
+/* mimo Space/Time/Frequency mode shift */
+#define RSPEC_STF_SHIFT 11
+/* mimo coding type mask */
+#define RSPEC_CT_MASK 0x0000C000
+/* mimo coding type shift */
+#define RSPEC_CT_SHIFT 14
+/* mimo num STC streams per PLCP defn. */
+#define RSPEC_STC_MASK 0x00300000
+/* mimo num STC streams per PLCP defn. */
+#define RSPEC_STC_SHIFT 20
+/* mimo bit indicates adv coding in use */
+#define RSPEC_LDPC_CODING 0x00400000
+/* mimo bit indicates short GI in use */
+#define RSPEC_SHORT_GI 0x00800000
+/* bit indicates override both rate & mode */
+#define RSPEC_OVERRIDE 0x80000000
+/* bit indicates override rate only */
+#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000
+
+static inline bool rspec_active(u32 rspec)
+{
+ return rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE);
+}
+
+static inline u8 rspec_phytxbyte2(u32 rspec)
+{
+ return (rspec & 0xff00) >> 8;
+}
+
+static inline u32 rspec_get_bw(u32 rspec)
+{
+ return (rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT;
+}
+
+static inline bool rspec_issgi(u32 rspec)
+{
+ return (rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI;
+}
+
+static inline bool rspec_is40mhz(u32 rspec)
+{
+ u32 bw = rspec_get_bw(rspec);
+
+ return bw == PHY_TXC1_BW_40MHZ || bw == PHY_TXC1_BW_40MHZ_DUP;
+}
+
+static inline uint rspec2rate(u32 rspec)
+{
+ if (rspec & RSPEC_MIMORATE)
+ return mcs_2_rate(rspec & RSPEC_RATE_MASK, rspec_is40mhz(rspec),
+ rspec_issgi(rspec));
+ return rspec & RSPEC_RATE_MASK;
+}
+
+static inline u8 rspec_mimoplcp3(u32 rspec)
+{
+ return (rspec & 0xf00000) >> 16;
+}
+
+static inline bool plcp3_issgi(u8 plcp)
+{
+ return (plcp & (RSPEC_SHORT_GI >> 16)) != 0;
+}
+
+static inline uint rspec_stc(u32 rspec)
+{
+ return (rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT;
+}
+
+static inline uint rspec_stf(u32 rspec)
+{
+ return (rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT;
+}
+
+static inline bool is_mcs_rate(u32 ratespec)
+{
+ return (ratespec & RSPEC_MIMORATE) != 0;
+}
+
+static inline bool is_ofdm_rate(u32 ratespec)
+{
+ return !is_mcs_rate(ratespec) &&
+ (rate_info[ratespec & RSPEC_RATE_MASK] & BRCMS_RATE_FLAG);
+}
+
+static inline bool is_cck_rate(u32 ratespec)
+{
+ u32 rate = (ratespec & BRCMS_RATE_MASK);
+
+ return !is_mcs_rate(ratespec) && (
+ rate == BRCM_RATE_1M || rate == BRCM_RATE_2M ||
+ rate == BRCM_RATE_5M5 || rate == BRCM_RATE_11M);
+}
+
+static inline bool is_single_stream(u8 mcs)
+{
+ return mcs <= HIGHEST_SINGLE_STREAM_MCS || mcs == 32;
+}
+
+static inline u8 cck_rspec(u8 cck)
+{
+ return cck & RSPEC_RATE_MASK;
+}
+
+/* Convert encoded rate value in plcp header to numerical rates in 500 KHz
+ * increments */
+extern const u8 ofdm_rate_lookup[];
+
+static inline u8 ofdm_phy2mac_rate(u8 rlpt)
+{
+ return ofdm_rate_lookup[rlpt & 0x7];
+}
+
+static inline u8 cck_phy2mac_rate(u8 signal)
+{
+ return signal/5;
+}
+
+/* Rates specified in brcms_c_rateset_filter() */
+#define BRCMS_RATES_CCK_OFDM 0
+#define BRCMS_RATES_CCK 1
+#define BRCMS_RATES_OFDM 2
+
+/* sanitize, and sort a rateset with the basic bit(s) preserved, validate
+ * rateset */
+extern bool
+brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs,
+ const struct brcms_c_rateset *hw_rs,
+ bool check_brate, u8 txstreams);
+/* copy rateset src to dst as-is (no masking or sorting) */
+extern void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
+ struct brcms_c_rateset *dst);
+
+/* would be nice to have these documented ... */
+extern u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp);
+
+extern void brcms_c_rateset_filter(struct brcms_c_rateset *src,
+ struct brcms_c_rateset *dst, bool basic_only, u8 rates, uint xmask,
+ bool mcsallow);
+
+extern void
+brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt,
+ const struct brcms_c_rateset *rs_hw, uint phy_type,
+ int bandtype, bool cck_only, uint rate_mask,
+ bool mcsallow, u8 bw, u8 txstreams);
+
+extern s16 brcms_c_rate_legacy_phyctl(uint rate);
+
+extern void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams);
+extern void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset);
+extern void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset,
+ u8 txstreams);
+extern void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset,
+ u8 bw);
+
+#endif /* _BRCM_RATE_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/scb.h b/drivers/net/wireless/brcm80211/brcmsmac/scb.h
index d6c8328554d0..51c79c7239b7 100644
--- a/drivers/staging/brcm80211/brcmsmac/scb.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/scb.h
@@ -23,17 +23,27 @@
#include "types.h"
#define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
+
+#define AMPDU_MAX_SCB_TID NUMPRIO
+
+/* scb flags */
+#define SCB_WMECAP 0x0040
+#define SCB_HTCAP 0x10000 /* HT (MIMO) capable device */
+#define SCB_IS40 0x80000 /* 40MHz capable */
+#define SCB_STBCCAP 0x40000000 /* STBC Capable */
+
+#define SCB_MAGIC 0xbeefcafe
+
/* structure to store per-tid state for the ampdu initiator */
struct scb_ampdu_tid_ini {
- u8 tx_in_transit; /* number of pending mpdus in transit in driver */
- u8 tid; /* initiator tid for easy lookup */
- u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; /* tx retry count; indexed by seq modulo */
- struct scb *scb; /* backptr for easy lookup */
- u8 ba_wsize; /* negotiated ba window size (in pdu) */
+ u8 tx_in_transit; /* number of pending mpdus in transit in driver */
+ u8 tid; /* initiator tid for easy lookup */
+ /* tx retry count; indexed by seq modulo */
+ u8 txretry[AMPDU_TX_BA_MAX_WSIZE];
+ struct scb *scb; /* backptr for easy lookup */
+ u8 ba_wsize; /* negotiated ba window size (in pdu) */
};
-#define AMPDU_MAX_SCB_TID NUMPRIO
-
struct scb_ampdu {
struct scb *scb; /* back pointer for easy reference */
u8 mpdu_density; /* mpdu density */
@@ -41,45 +51,32 @@ struct scb_ampdu {
u8 release; /* # of mpdus released at a time */
u16 min_len; /* min mpdu len to support the density */
u32 max_rx_ampdu_bytes; /* max ampdu rcv length; 8k, 16k, 32k, 64k */
- struct pktq txq; /* sdu transmit queue pending aggregation */
- /* This could easily be a ini[] pointer and we keep this info in wl itself instead
- * of having mac80211 hold it for us. Also could be made dynamic per tid instead of
- * static.
+ /*
+ * This could easily be a ini[] pointer and we keep this info in wl
+ * itself instead of having mac80211 hold it for us. Also could be made
+ * dynamic per tid instead of static.
*/
/* initiator info - per tid (NUMPRIO): */
struct scb_ampdu_tid_ini ini[AMPDU_MAX_SCB_TID];
};
-#define SCB_MAGIC 0xbeefcafe
-
/* station control block - one per remote MAC address */
struct scb {
u32 magic;
- u32 flags; /* various bit flags as defined below */
- u32 flags2; /* various bit flags2 as defined below */
- u8 state; /* current state bitfield of auth/assoc process */
+ u32 flags; /* various bit flags as defined below */
+ u32 flags2; /* various bit flags2 as defined below */
+ u8 state; /* current state bitfield of auth/assoc process */
u8 ea[ETH_ALEN]; /* station address */
- void *fragbuf[NUMPRIO]; /* defragmentation buffer per prio */
- uint fragresid[NUMPRIO]; /* #bytes unused in frag buffer per prio */
+ uint fragresid[NUMPRIO];/* #bytes unused in frag buffer per prio */
u16 seqctl[NUMPRIO]; /* seqctl of last received frame (for dups) */
- u16 seqctl_nonqos; /* seqctl of last received frame (for dups) for
- * non-QoS data and management
- */
- u16 seqnum[NUMPRIO]; /* WME: driver maintained sw seqnum per priority */
+ /* seqctl of last received frame (for dups) for non-QoS data and
+ * management */
+ u16 seqctl_nonqos;
+ u16 seqnum[NUMPRIO];/* WME: driver maintained sw seqnum per priority */
struct scb_ampdu scb_ampdu; /* AMPDU state including per tid info */
};
-/* scb flags */
-#define SCB_WMECAP 0x0040 /* may ONLY be set if WME_ENAB(wlc) */
-#define SCB_HTCAP 0x10000 /* HT (MIMO) capable device */
-#define SCB_IS40 0x80000 /* 40MHz capable */
-#define SCB_STBCCAP 0x40000000 /* STBC Capable */
-#define SCB_WME(a) ((a)->flags & SCB_WMECAP)/* implies WME_ENAB */
-#define SCB_SEQNUM(scb, prio) ((scb)->seqnum[(prio)])
-#define SCB_PS(a) NULL
-#define SCB_STBC_CAP(a) ((a)->flags & SCB_STBCCAP)
-#define SCB_AMPDU(a) true
#endif /* _BRCM_SCB_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.c b/drivers/net/wireless/brcm80211/brcmsmac/srom.c
new file mode 100644
index 000000000000..99f791048e84
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/srom.c
@@ -0,0 +1,1298 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/etherdevice.h>
+#include <linux/crc8.h>
+#include <stdarg.h>
+
+#include <chipcommon.h>
+#include <brcmu_utils.h>
+#include "pub.h"
+#include "nicpci.h"
+#include "aiutils.h"
+#include "otp.h"
+#include "srom.h"
+
+/*
+ * SROM CRC8 polynomial value:
+ *
+ * x^8 + x^7 +x^6 + x^4 + x^2 + 1
+ */
+#define SROM_CRC8_POLY 0xAB
+
+/* Maximum srom: 6 Kilobits == 768 bytes */
+#define SROM_MAX 768
+
+/* PCI fields */
+#define PCI_F0DEVID 48
+
+#define SROM_WORDS 64
+
+#define SROM_SSID 2
+
+#define SROM_WL1LHMAXP 29
+
+#define SROM_WL1LPAB0 30
+#define SROM_WL1LPAB1 31
+#define SROM_WL1LPAB2 32
+
+#define SROM_WL1HPAB0 33
+#define SROM_WL1HPAB1 34
+#define SROM_WL1HPAB2 35
+
+#define SROM_MACHI_IL0 36
+#define SROM_MACMID_IL0 37
+#define SROM_MACLO_IL0 38
+#define SROM_MACHI_ET1 42
+#define SROM_MACMID_ET1 43
+#define SROM_MACLO_ET1 44
+#define SROM3_MACHI 37
+#define SROM3_MACMID 38
+#define SROM3_MACLO 39
+
+#define SROM_BXARSSI2G 40
+#define SROM_BXARSSI5G 41
+
+#define SROM_TRI52G 42
+#define SROM_TRI5GHL 43
+
+#define SROM_RXPO52G 45
+
+#define SROM_AABREV 46
+/* Fields in AABREV */
+#define SROM_BR_MASK 0x00ff
+#define SROM_CC_MASK 0x0f00
+#define SROM_CC_SHIFT 8
+#define SROM_AA0_MASK 0x3000
+#define SROM_AA0_SHIFT 12
+#define SROM_AA1_MASK 0xc000
+#define SROM_AA1_SHIFT 14
+
+#define SROM_WL0PAB0 47
+#define SROM_WL0PAB1 48
+#define SROM_WL0PAB2 49
+
+#define SROM_LEDBH10 50
+#define SROM_LEDBH32 51
+
+#define SROM_WL10MAXP 52
+
+#define SROM_WL1PAB0 53
+#define SROM_WL1PAB1 54
+#define SROM_WL1PAB2 55
+
+#define SROM_ITT 56
+
+#define SROM_BFL 57
+#define SROM_BFL2 28
+#define SROM3_BFL2 61
+
+#define SROM_AG10 58
+
+#define SROM_CCODE 59
+
+#define SROM_OPO 60
+
+#define SROM3_LEDDC 62
+
+#define SROM_CRCREV 63
+
+/* SROM Rev 4: Reallocate the software part of the srom to accommodate
+ * MIMO features. It assumes up to two PCIE functions and 440 bytes
+ * of usable srom i.e. the usable storage in chips with OTP that
+ * implements hardware redundancy.
+ */
+
+#define SROM4_WORDS 220
+
+#define SROM4_SIGN 32
+#define SROM4_SIGNATURE 0x5372
+
+#define SROM4_BREV 33
+
+#define SROM4_BFL0 34
+#define SROM4_BFL1 35
+#define SROM4_BFL2 36
+#define SROM4_BFL3 37
+#define SROM5_BFL0 37
+#define SROM5_BFL1 38
+#define SROM5_BFL2 39
+#define SROM5_BFL3 40
+
+#define SROM4_MACHI 38
+#define SROM4_MACMID 39
+#define SROM4_MACLO 40
+#define SROM5_MACHI 41
+#define SROM5_MACMID 42
+#define SROM5_MACLO 43
+
+#define SROM4_CCODE 41
+#define SROM4_REGREV 42
+#define SROM5_CCODE 34
+#define SROM5_REGREV 35
+
+#define SROM4_LEDBH10 43
+#define SROM4_LEDBH32 44
+#define SROM5_LEDBH10 59
+#define SROM5_LEDBH32 60
+
+#define SROM4_LEDDC 45
+#define SROM5_LEDDC 45
+
+#define SROM4_AA 46
+
+#define SROM4_AG10 47
+#define SROM4_AG32 48
+
+#define SROM4_TXPID2G 49
+#define SROM4_TXPID5G 51
+#define SROM4_TXPID5GL 53
+#define SROM4_TXPID5GH 55
+
+#define SROM4_TXRXC 61
+#define SROM4_TXCHAIN_MASK 0x000f
+#define SROM4_TXCHAIN_SHIFT 0
+#define SROM4_RXCHAIN_MASK 0x00f0
+#define SROM4_RXCHAIN_SHIFT 4
+#define SROM4_SWITCH_MASK 0xff00
+#define SROM4_SWITCH_SHIFT 8
+
+/* Per-path fields */
+#define MAX_PATH_SROM 4
+#define SROM4_PATH0 64
+#define SROM4_PATH1 87
+#define SROM4_PATH2 110
+#define SROM4_PATH3 133
+
+#define SROM4_2G_ITT_MAXP 0
+#define SROM4_2G_PA 1
+#define SROM4_5G_ITT_MAXP 5
+#define SROM4_5GLH_MAXP 6
+#define SROM4_5G_PA 7
+#define SROM4_5GL_PA 11
+#define SROM4_5GH_PA 15
+
+/* All the miriad power offsets */
+#define SROM4_2G_CCKPO 156
+#define SROM4_2G_OFDMPO 157
+#define SROM4_5G_OFDMPO 159
+#define SROM4_5GL_OFDMPO 161
+#define SROM4_5GH_OFDMPO 163
+#define SROM4_2G_MCSPO 165
+#define SROM4_5G_MCSPO 173
+#define SROM4_5GL_MCSPO 181
+#define SROM4_5GH_MCSPO 189
+#define SROM4_CDDPO 197
+#define SROM4_STBCPO 198
+#define SROM4_BW40PO 199
+#define SROM4_BWDUPPO 200
+
+#define SROM4_CRCREV 219
+
+/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
+ * This is acombined srom for both MIMO and SISO boards, usable in
+ * the .130 4Kilobit OTP with hardware redundancy.
+ */
+#define SROM8_BREV 65
+
+#define SROM8_BFL0 66
+#define SROM8_BFL1 67
+#define SROM8_BFL2 68
+#define SROM8_BFL3 69
+
+#define SROM8_MACHI 70
+#define SROM8_MACMID 71
+#define SROM8_MACLO 72
+
+#define SROM8_CCODE 73
+#define SROM8_REGREV 74
+
+#define SROM8_LEDBH10 75
+#define SROM8_LEDBH32 76
+
+#define SROM8_LEDDC 77
+
+#define SROM8_AA 78
+
+#define SROM8_AG10 79
+#define SROM8_AG32 80
+
+#define SROM8_TXRXC 81
+
+#define SROM8_BXARSSI2G 82
+#define SROM8_BXARSSI5G 83
+#define SROM8_TRI52G 84
+#define SROM8_TRI5GHL 85
+#define SROM8_RXPO52G 86
+
+#define SROM8_FEM2G 87
+#define SROM8_FEM5G 88
+#define SROM8_FEM_ANTSWLUT_MASK 0xf800
+#define SROM8_FEM_ANTSWLUT_SHIFT 11
+#define SROM8_FEM_TR_ISO_MASK 0x0700
+#define SROM8_FEM_TR_ISO_SHIFT 8
+#define SROM8_FEM_PDET_RANGE_MASK 0x00f8
+#define SROM8_FEM_PDET_RANGE_SHIFT 3
+#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006
+#define SROM8_FEM_EXTPA_GAIN_SHIFT 1
+#define SROM8_FEM_TSSIPOS_MASK 0x0001
+#define SROM8_FEM_TSSIPOS_SHIFT 0
+
+#define SROM8_THERMAL 89
+
+/* Temp sense related entries */
+#define SROM8_MPWR_RAWTS 90
+#define SROM8_TS_SLP_OPT_CORRX 91
+/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable,
+ * IQSWP: IQ CAL swap disable */
+#define SROM8_FOC_HWIQ_IQSWP 92
+
+/* Temperature delta for PHY calibration */
+#define SROM8_PHYCAL_TEMPDELTA 93
+
+/* Per-path offsets & fields */
+#define SROM8_PATH0 96
+#define SROM8_PATH1 112
+#define SROM8_PATH2 128
+#define SROM8_PATH3 144
+
+#define SROM8_2G_ITT_MAXP 0
+#define SROM8_2G_PA 1
+#define SROM8_5G_ITT_MAXP 4
+#define SROM8_5GLH_MAXP 5
+#define SROM8_5G_PA 6
+#define SROM8_5GL_PA 9
+#define SROM8_5GH_PA 12
+
+/* All the miriad power offsets */
+#define SROM8_2G_CCKPO 160
+
+#define SROM8_2G_OFDMPO 161
+#define SROM8_5G_OFDMPO 163
+#define SROM8_5GL_OFDMPO 165
+#define SROM8_5GH_OFDMPO 167
+
+#define SROM8_2G_MCSPO 169
+#define SROM8_5G_MCSPO 177
+#define SROM8_5GL_MCSPO 185
+#define SROM8_5GH_MCSPO 193
+
+#define SROM8_CDDPO 201
+#define SROM8_STBCPO 202
+#define SROM8_BW40PO 203
+#define SROM8_BWDUPPO 204
+
+/* SISO PA parameters are in the path0 spaces */
+#define SROM8_SISO 96
+
+/* Legacy names for SISO PA paramters */
+#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP)
+#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA)
+#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1)
+#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2)
+#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP)
+#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP)
+#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA)
+#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1)
+#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2)
+#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA)
+#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1)
+#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2)
+#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA)
+#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1)
+#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2)
+
+/* SROM REV 9 */
+#define SROM9_2GPO_CCKBW20 160
+#define SROM9_2GPO_CCKBW20UL 161
+#define SROM9_2GPO_LOFDMBW20 162
+#define SROM9_2GPO_LOFDMBW20UL 164
+
+#define SROM9_5GLPO_LOFDMBW20 166
+#define SROM9_5GLPO_LOFDMBW20UL 168
+#define SROM9_5GMPO_LOFDMBW20 170
+#define SROM9_5GMPO_LOFDMBW20UL 172
+#define SROM9_5GHPO_LOFDMBW20 174
+#define SROM9_5GHPO_LOFDMBW20UL 176
+
+#define SROM9_2GPO_MCSBW20 178
+#define SROM9_2GPO_MCSBW20UL 180
+#define SROM9_2GPO_MCSBW40 182
+
+#define SROM9_5GLPO_MCSBW20 184
+#define SROM9_5GLPO_MCSBW20UL 186
+#define SROM9_5GLPO_MCSBW40 188
+#define SROM9_5GMPO_MCSBW20 190
+#define SROM9_5GMPO_MCSBW20UL 192
+#define SROM9_5GMPO_MCSBW40 194
+#define SROM9_5GHPO_MCSBW20 196
+#define SROM9_5GHPO_MCSBW20UL 198
+#define SROM9_5GHPO_MCSBW40 200
+
+#define SROM9_PO_MCS32 202
+#define SROM9_PO_LOFDM40DUP 203
+
+/* SROM flags (see sromvar_t) */
+
+/* value continues as described by the next entry */
+#define SRFL_MORE 1
+#define SRFL_NOFFS 2 /* value bits can't be all one's */
+#define SRFL_PRHEX 4 /* value is in hexdecimal format */
+#define SRFL_PRSIGN 8 /* value is in signed decimal format */
+#define SRFL_CCODE 0x10 /* value is in country code format */
+#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */
+#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */
+/* do not generate a nvram param, entry is for mfgc */
+#define SRFL_NOVAR 0x80
+
+/* Max. nvram variable table size */
+#define MAXSZ_NVRAM_VARS 4096
+
+/*
+ * indicates type of value.
+ */
+enum brcms_srom_var_type {
+ BRCMS_SROM_STRING,
+ BRCMS_SROM_SNUMBER,
+ BRCMS_SROM_UNUMBER
+};
+
+/*
+ * storage type for srom variable.
+ *
+ * var_list: for linked list operations.
+ * varid: identifier of the variable.
+ * var_type: type of variable.
+ * buf: variable value when var_type == BRCMS_SROM_STRING.
+ * uval: unsigned variable value when var_type == BRCMS_SROM_UNUMBER.
+ * sval: signed variable value when var_type == BRCMS_SROM_SNUMBER.
+ */
+struct brcms_srom_list_head {
+ struct list_head var_list;
+ enum brcms_srom_id varid;
+ enum brcms_srom_var_type var_type;
+ union {
+ char buf[0];
+ u32 uval;
+ s32 sval;
+ };
+};
+
+struct brcms_sromvar {
+ enum brcms_srom_id varid;
+ u32 revmask;
+ u32 flags;
+ u16 off;
+ u16 mask;
+};
+
+struct brcms_varbuf {
+ char *base; /* pointer to buffer base */
+ char *buf; /* pointer to current position */
+ unsigned int size; /* current (residual) size in bytes */
+};
+
+/*
+ * Assumptions:
+ * - Ethernet address spans across 3 consecutive words
+ *
+ * Table rules:
+ * - Add multiple entries next to each other if a value spans across multiple
+ * words (even multiple fields in the same word) with each entry except the
+ * last having it's SRFL_MORE bit set.
+ * - Ethernet address entry does not follow above rule and must not have
+ * SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
+ * - The last entry's name field must be NULL to indicate the end of the table.
+ * Other entries must have non-NULL name.
+ */
+static const struct brcms_sromvar pci_sromvars[] = {
+ {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID,
+ 0xffff},
+ {BRCMS_SROM_BOARDREV, 0x0000000e, SRFL_PRHEX, SROM_AABREV,
+ SROM_BR_MASK},
+ {BRCMS_SROM_BOARDREV, 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
+ {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM_BFL2, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM3_BFL2, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_BFL1, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM5_BFL1, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS2, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_BFL3, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS2, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM5_BFL3, 0xffff},
+ {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff},
+ {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
+ {BRCMS_SROM_BOARDNUM, 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
+ {BRCMS_SROM_BOARDNUM, 0x00000008, 0, SROM3_MACLO, 0xffff},
+ {BRCMS_SROM_BOARDNUM, 0x00000010, 0, SROM4_MACLO, 0xffff},
+ {BRCMS_SROM_BOARDNUM, 0x000000e0, 0, SROM5_MACLO, 0xffff},
+ {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff},
+ {BRCMS_SROM_CC, 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
+ {BRCMS_SROM_REGREV, 0x00000008, 0, SROM_OPO, 0xff00},
+ {BRCMS_SROM_REGREV, 0x00000010, 0, SROM4_REGREV, 0x00ff},
+ {BRCMS_SROM_REGREV, 0x000000e0, 0, SROM5_REGREV, 0x00ff},
+ {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff},
+ {BRCMS_SROM_LEDBH0, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
+ {BRCMS_SROM_LEDBH1, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
+ {BRCMS_SROM_LEDBH2, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
+ {BRCMS_SROM_LEDBH3, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
+ {BRCMS_SROM_LEDBH0, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
+ {BRCMS_SROM_LEDBH1, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
+ {BRCMS_SROM_LEDBH2, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
+ {BRCMS_SROM_LEDBH3, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
+ {BRCMS_SROM_LEDBH0, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
+ {BRCMS_SROM_LEDBH1, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
+ {BRCMS_SROM_LEDBH2, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
+ {BRCMS_SROM_LEDBH3, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
+ {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
+ {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
+ {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
+ {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
+ {BRCMS_SROM_PA0B0, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
+ {BRCMS_SROM_PA0B1, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
+ {BRCMS_SROM_PA0B2, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
+ {BRCMS_SROM_PA0ITSSIT, 0x0000000e, 0, SROM_ITT, 0x00ff},
+ {BRCMS_SROM_PA0MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
+ {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
+ {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
+ {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
+ {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
+ {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
+ {BRCMS_SROM_OPO, 0x0000000c, 0, SROM_OPO, 0x00ff},
+ {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
+ {BRCMS_SROM_AA2G, 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
+ {BRCMS_SROM_AA2G, 0x000000f0, 0, SROM4_AA, 0x00ff},
+ {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff},
+ {BRCMS_SROM_AA5G, 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
+ {BRCMS_SROM_AA5G, 0x000000f0, 0, SROM4_AA, 0xff00},
+ {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00},
+ {BRCMS_SROM_AG0, 0x0000000e, 0, SROM_AG10, 0x00ff},
+ {BRCMS_SROM_AG1, 0x0000000e, 0, SROM_AG10, 0xff00},
+ {BRCMS_SROM_AG0, 0x000000f0, 0, SROM4_AG10, 0x00ff},
+ {BRCMS_SROM_AG1, 0x000000f0, 0, SROM4_AG10, 0xff00},
+ {BRCMS_SROM_AG2, 0x000000f0, 0, SROM4_AG32, 0x00ff},
+ {BRCMS_SROM_AG3, 0x000000f0, 0, SROM4_AG32, 0xff00},
+ {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff},
+ {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00},
+ {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff},
+ {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00},
+ {BRCMS_SROM_PA1B0, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
+ {BRCMS_SROM_PA1B1, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
+ {BRCMS_SROM_PA1B2, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
+ {BRCMS_SROM_PA1LOB0, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
+ {BRCMS_SROM_PA1LOB1, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
+ {BRCMS_SROM_PA1LOB2, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
+ {BRCMS_SROM_PA1HIB0, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
+ {BRCMS_SROM_PA1HIB1, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
+ {BRCMS_SROM_PA1HIB2, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
+ {BRCMS_SROM_PA1ITSSIT, 0x0000000e, 0, SROM_ITT, 0xff00},
+ {BRCMS_SROM_PA1MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
+ {BRCMS_SROM_PA1LOMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
+ {BRCMS_SROM_PA1HIMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
+ {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
+ {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
+ {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
+ {BRCMS_SROM_PA1LOB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
+ {BRCMS_SROM_PA1LOB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
+ {BRCMS_SROM_PA1LOB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
+ {BRCMS_SROM_PA1HIB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
+ {BRCMS_SROM_PA1HIB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
+ {BRCMS_SROM_PA1HIB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
+ {BRCMS_SROM_PA1ITSSIT, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
+ {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
+ {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
+ {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
+ {BRCMS_SROM_BXA2G, 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
+ {BRCMS_SROM_RSSISAV2G, 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
+ {BRCMS_SROM_RSSISMC2G, 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
+ {BRCMS_SROM_RSSISMF2G, 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
+ {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
+ {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
+ {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
+ {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
+ {BRCMS_SROM_BXA5G, 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
+ {BRCMS_SROM_RSSISAV5G, 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
+ {BRCMS_SROM_RSSISMC5G, 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
+ {BRCMS_SROM_RSSISMF5G, 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
+ {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
+ {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
+ {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
+ {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
+ {BRCMS_SROM_TRI2G, 0x00000008, 0, SROM_TRI52G, 0x00ff},
+ {BRCMS_SROM_TRI5G, 0x00000008, 0, SROM_TRI52G, 0xff00},
+ {BRCMS_SROM_TRI5GL, 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
+ {BRCMS_SROM_TRI5GH, 0x00000008, 0, SROM_TRI5GHL, 0xff00},
+ {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
+ {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00},
+ {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
+ {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
+ {BRCMS_SROM_RXPO2G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
+ {BRCMS_SROM_RXPO5G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
+ {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
+ {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
+ {BRCMS_SROM_TXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
+ SROM4_TXCHAIN_MASK},
+ {BRCMS_SROM_RXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
+ SROM4_RXCHAIN_MASK},
+ {BRCMS_SROM_ANTSWITCH, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
+ SROM4_SWITCH_MASK},
+ {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
+ SROM4_TXCHAIN_MASK},
+ {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
+ SROM4_RXCHAIN_MASK},
+ {BRCMS_SROM_ANTSWITCH, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
+ SROM4_SWITCH_MASK},
+ {BRCMS_SROM_TSSIPOS2G, 0xffffff00, 0, SROM8_FEM2G,
+ SROM8_FEM_TSSIPOS_MASK},
+ {BRCMS_SROM_EXTPAGAIN2G, 0xffffff00, 0, SROM8_FEM2G,
+ SROM8_FEM_EXTPA_GAIN_MASK},
+ {BRCMS_SROM_PDETRANGE2G, 0xffffff00, 0, SROM8_FEM2G,
+ SROM8_FEM_PDET_RANGE_MASK},
+ {BRCMS_SROM_TRISO2G, 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
+ {BRCMS_SROM_ANTSWCTL2G, 0xffffff00, 0, SROM8_FEM2G,
+ SROM8_FEM_ANTSWLUT_MASK},
+ {BRCMS_SROM_TSSIPOS5G, 0xffffff00, 0, SROM8_FEM5G,
+ SROM8_FEM_TSSIPOS_MASK},
+ {BRCMS_SROM_EXTPAGAIN5G, 0xffffff00, 0, SROM8_FEM5G,
+ SROM8_FEM_EXTPA_GAIN_MASK},
+ {BRCMS_SROM_PDETRANGE5G, 0xffffff00, 0, SROM8_FEM5G,
+ SROM8_FEM_PDET_RANGE_MASK},
+ {BRCMS_SROM_TRISO5G, 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
+ {BRCMS_SROM_ANTSWCTL5G, 0xffffff00, 0, SROM8_FEM5G,
+ SROM8_FEM_ANTSWLUT_MASK},
+ {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00},
+ {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
+ {BRCMS_SROM_TXPID2GA0, 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
+ {BRCMS_SROM_TXPID2GA1, 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
+ {BRCMS_SROM_TXPID2GA2, 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
+ {BRCMS_SROM_TXPID2GA3, 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
+ {BRCMS_SROM_TXPID5GA0, 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
+ {BRCMS_SROM_TXPID5GA1, 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
+ {BRCMS_SROM_TXPID5GA2, 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
+ {BRCMS_SROM_TXPID5GA3, 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
+ {BRCMS_SROM_TXPID5GLA0, 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
+ {BRCMS_SROM_TXPID5GLA1, 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
+ {BRCMS_SROM_TXPID5GLA2, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
+ {BRCMS_SROM_TXPID5GLA3, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
+ {BRCMS_SROM_TXPID5GHA0, 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
+ {BRCMS_SROM_TXPID5GHA1, 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
+ {BRCMS_SROM_TXPID5GHA2, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
+ {BRCMS_SROM_TXPID5GHA3, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
+
+ {BRCMS_SROM_CCODE, 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
+ {BRCMS_SROM_CCODE, 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
+ {BRCMS_SROM_CCODE, 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
+ {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
+ {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
+ {BRCMS_SROM_MACADDR, 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
+ {BRCMS_SROM_MACADDR, 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
+ {BRCMS_SROM_MACADDR, 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
+ {BRCMS_SROM_IL0MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0,
+ 0xffff},
+ {BRCMS_SROM_ET1MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1,
+ 0xffff},
+ {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC,
+ 0xffff},
+ {BRCMS_SROM_LEDDC, 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC,
+ 0xffff},
+ {BRCMS_SROM_LEDDC, 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC,
+ 0xffff},
+ {BRCMS_SROM_LEDDC, 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC,
+ 0xffff},
+ {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
+ 0x01ff},
+ {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
+ 0xfe00},
+ {BRCMS_SROM_TEMPSENSE_SLOPE, 0xffffff00, SRFL_PRHEX,
+ SROM8_TS_SLP_OPT_CORRX, 0x00ff},
+ {BRCMS_SROM_TEMPCORRX, 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
+ 0xfc00},
+ {BRCMS_SROM_TEMPSENSE_OPTION, 0xffffff00, SRFL_PRHEX,
+ SROM8_TS_SLP_OPT_CORRX, 0x0300},
+ {BRCMS_SROM_FREQOFFSET_CORR, 0xffffff00, SRFL_PRHEX,
+ SROM8_FOC_HWIQ_IQSWP, 0x000f},
+ {BRCMS_SROM_IQCAL_SWP_DIS, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
+ 0x0010},
+ {BRCMS_SROM_HW_IQCAL_EN, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
+ 0x0020},
+ {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA,
+ 0x00ff},
+
+ {BRCMS_SROM_CCK2GPO, 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
+ {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
+ {BRCMS_SROM_OFDM2GPO, 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GPO, 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GLPO, 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GHPO, 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GLPO, 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
+ {BRCMS_SROM_MCS2GPO0, 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS2GPO1, 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS2GPO2, 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS2GPO3, 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS2GPO4, 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS2GPO5, 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS2GPO6, 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS2GPO7, 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GPO0, 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GPO1, 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GPO2, 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GPO3, 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GPO4, 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GPO5, 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GPO6, 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GPO7, 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GLPO0, 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GLPO1, 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GLPO2, 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GLPO3, 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GLPO4, 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GLPO5, 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GLPO6, 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GLPO7, 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GHPO0, 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GHPO1, 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GHPO2, 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GHPO3, 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GHPO4, 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GHPO5, 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GHPO6, 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GHPO7, 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS2GPO3, 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS2GPO4, 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS2GPO5, 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS2GPO6, 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS2GPO7, 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GPO0, 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GPO1, 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GPO2, 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GPO3, 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GPO4, 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GPO5, 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GPO6, 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GPO7, 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GLPO0, 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GLPO1, 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GLPO2, 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GLPO3, 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GLPO4, 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GLPO5, 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GLPO6, 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GLPO7, 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_MCS5GHPO0, 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
+ {BRCMS_SROM_MCS5GHPO1, 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
+ {BRCMS_SROM_MCS5GHPO2, 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
+ {BRCMS_SROM_MCS5GHPO3, 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
+ {BRCMS_SROM_MCS5GHPO4, 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
+ {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
+ {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
+ {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
+ {BRCMS_SROM_CDDPO, 0x000000f0, 0, SROM4_CDDPO, 0xffff},
+ {BRCMS_SROM_STBCPO, 0x000000f0, 0, SROM4_STBCPO, 0xffff},
+ {BRCMS_SROM_BW40PO, 0x000000f0, 0, SROM4_BW40PO, 0xffff},
+ {BRCMS_SROM_BWDUPPO, 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
+ {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff},
+ {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff},
+ {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff},
+ {BRCMS_SROM_BWDUPPO, 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
+
+ /* power per rate from sromrev 9 */
+ {BRCMS_SROM_CCKBW202GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
+ {BRCMS_SROM_CCKBW20UL2GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW202GPO, 0xfffffe00, SRFL_MORE,
+ SROM9_2GPO_LOFDMBW20, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW20UL2GPO, 0xfffffe00, SRFL_MORE,
+ SROM9_2GPO_LOFDMBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW205GLPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GLPO_LOFDMBW20, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW20UL5GLPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GLPO_LOFDMBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW205GMPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GMPO_LOFDMBW20, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW20UL5GMPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GMPO_LOFDMBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW205GHPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GHPO_LOFDMBW20, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
+ {BRCMS_SROM_LEGOFDMBW20UL5GHPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GHPO_LOFDMBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
+ {BRCMS_SROM_MCSBW202GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW20UL2GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
+ {BRCMS_SROM_MCSBW402GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW205GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW20UL5GLPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GLPO_MCSBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
+ {BRCMS_SROM_MCSBW405GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW205GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW20UL5GMPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GMPO_MCSBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
+ {BRCMS_SROM_MCSBW405GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW205GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
+ {BRCMS_SROM_MCSBW20UL5GHPO, 0xfffffe00, SRFL_MORE,
+ SROM9_5GHPO_MCSBW20UL, 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
+ {BRCMS_SROM_MCSBW405GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40,
+ 0xffff},
+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
+ {BRCMS_SROM_MCS32PO, 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
+ {BRCMS_SROM_LEGOFDM40DUPPO, 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
+
+ {BRCMS_SROM_NULL, 0, 0, 0, 0}
+};
+
+static const struct brcms_sromvar perpath_pci_sromvars[] = {
+ {BRCMS_SROM_MAXP2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
+ {BRCMS_SROM_ITT2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
+ {BRCMS_SROM_ITT5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
+ {BRCMS_SROM_PA2GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
+ {BRCMS_SROM_PA2GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
+ {BRCMS_SROM_PA2GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
+ {BRCMS_SROM_PA2GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
+ {BRCMS_SROM_MAXP5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
+ {BRCMS_SROM_MAXP5GHA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
+ {BRCMS_SROM_MAXP5GLA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
+ {BRCMS_SROM_PA5GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
+ {BRCMS_SROM_PA5GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
+ {BRCMS_SROM_PA5GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
+ {BRCMS_SROM_PA5GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
+ {BRCMS_SROM_PA5GLW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
+ {BRCMS_SROM_PA5GLW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1,
+ 0xffff},
+ {BRCMS_SROM_PA5GLW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2,
+ 0xffff},
+ {BRCMS_SROM_PA5GLW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3,
+ 0xffff},
+ {BRCMS_SROM_PA5GHW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
+ {BRCMS_SROM_PA5GHW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1,
+ 0xffff},
+ {BRCMS_SROM_PA5GHW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2,
+ 0xffff},
+ {BRCMS_SROM_PA5GHW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3,
+ 0xffff},
+ {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
+ {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
+ {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
+ {BRCMS_SROM_PA2GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
+ {BRCMS_SROM_PA2GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
+ {BRCMS_SROM_PA2GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
+ {BRCMS_SROM_MAXP5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
+ {BRCMS_SROM_MAXP5GHA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
+ {BRCMS_SROM_MAXP5GLA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
+ {BRCMS_SROM_PA5GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
+ {BRCMS_SROM_PA5GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
+ {BRCMS_SROM_PA5GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
+ {BRCMS_SROM_PA5GLW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
+ {BRCMS_SROM_PA5GLW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1,
+ 0xffff},
+ {BRCMS_SROM_PA5GLW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2,
+ 0xffff},
+ {BRCMS_SROM_PA5GHW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
+ {BRCMS_SROM_PA5GHW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1,
+ 0xffff},
+ {BRCMS_SROM_PA5GHW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2,
+ 0xffff},
+ {BRCMS_SROM_NULL, 0, 0, 0, 0}
+};
+
+/* crc table has the same contents for every device instance, so it can be
+ * shared between devices. */
+static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE];
+
+static u16 __iomem *
+srom_window_address(struct si_pub *sih, u8 __iomem *curmap)
+{
+ if (sih->ccrev < 32)
+ return (u16 __iomem *)(curmap + PCI_BAR0_SPROM_OFFSET);
+ if (sih->cccaps & CC_CAP_SROM)
+ return (u16 __iomem *)
+ (curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP);
+
+ return NULL;
+}
+
+/* Parse SROM and create name=value pairs. 'srom' points to
+ * the SROM word array. 'off' specifies the offset of the
+ * first word 'srom' points to, which should be either 0 or
+ * SROM3_SWRG_OFF (full SROM or software region).
+ */
+
+static uint mask_shift(u16 mask)
+{
+ uint i;
+ for (i = 0; i < (sizeof(mask) << 3); i++) {
+ if (mask & (1 << i))
+ return i;
+ }
+ return 0;
+}
+
+static uint mask_width(u16 mask)
+{
+ int i;
+ for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
+ if (mask & (1 << i))
+ return (uint) (i - mask_shift(mask) + 1);
+ }
+ return 0;
+}
+
+static inline void ltoh16_buf(u16 *buf, unsigned int size)
+{
+ size /= 2;
+ while (size--)
+ *(buf + size) = le16_to_cpu(*(__le16 *)(buf + size));
+}
+
+static inline void htol16_buf(u16 *buf, unsigned int size)
+{
+ size /= 2;
+ while (size--)
+ *(__le16 *)(buf + size) = cpu_to_le16(*(buf + size));
+}
+
+/*
+ * convert binary srom data into linked list of srom variable items.
+ */
+static void
+_initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
+{
+ struct brcms_srom_list_head *entry;
+ enum brcms_srom_id id;
+ u16 w;
+ u32 val;
+ const struct brcms_sromvar *srv;
+ uint width;
+ uint flags;
+ u32 sr = (1 << sromrev);
+
+ /* first store the srom revision */
+ entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL);
+ entry->varid = BRCMS_SROM_REV;
+ entry->var_type = BRCMS_SROM_UNUMBER;
+ entry->uval = sromrev;
+ list_add(&entry->var_list, var_list);
+
+ for (srv = pci_sromvars; srv->varid != BRCMS_SROM_NULL; srv++) {
+ enum brcms_srom_var_type type;
+ u8 ea[ETH_ALEN];
+ u8 extra_space = 0;
+
+ if ((srv->revmask & sr) == 0)
+ continue;
+
+ flags = srv->flags;
+ id = srv->varid;
+
+ /* This entry is for mfgc only. Don't generate param for it, */
+ if (flags & SRFL_NOVAR)
+ continue;
+
+ if (flags & SRFL_ETHADDR) {
+ /*
+ * stored in string format XX:XX:XX:XX:XX:XX (17 chars)
+ */
+ ea[0] = (srom[srv->off] >> 8) & 0xff;
+ ea[1] = srom[srv->off] & 0xff;
+ ea[2] = (srom[srv->off + 1] >> 8) & 0xff;
+ ea[3] = srom[srv->off + 1] & 0xff;
+ ea[4] = (srom[srv->off + 2] >> 8) & 0xff;
+ ea[5] = srom[srv->off + 2] & 0xff;
+ /* 17 characters + string terminator - union size */
+ extra_space = 18 - sizeof(s32);
+ type = BRCMS_SROM_STRING;
+ } else {
+ w = srom[srv->off];
+ val = (w & srv->mask) >> mask_shift(srv->mask);
+ width = mask_width(srv->mask);
+
+ while (srv->flags & SRFL_MORE) {
+ srv++;
+ if (srv->off == 0)
+ continue;
+
+ w = srom[srv->off];
+ val +=
+ ((w & srv->mask) >> mask_shift(srv->
+ mask)) <<
+ width;
+ width += mask_width(srv->mask);
+ }
+
+ if ((flags & SRFL_NOFFS)
+ && ((int)val == (1 << width) - 1))
+ continue;
+
+ if (flags & SRFL_CCODE) {
+ type = BRCMS_SROM_STRING;
+ } else if (flags & SRFL_LEDDC) {
+ /* LED Powersave duty cycle has to be scaled:
+ *(oncount >> 24) (offcount >> 8)
+ */
+ u32 w32 = /* oncount */
+ (((val >> 8) & 0xff) << 24) |
+ /* offcount */
+ (((val & 0xff)) << 8);
+ type = BRCMS_SROM_UNUMBER;
+ val = w32;
+ } else if ((flags & SRFL_PRSIGN)
+ && (val & (1 << (width - 1)))) {
+ type = BRCMS_SROM_SNUMBER;
+ val |= ~0 << width;
+ } else
+ type = BRCMS_SROM_UNUMBER;
+ }
+
+ entry = kzalloc(sizeof(struct brcms_srom_list_head) +
+ extra_space, GFP_KERNEL);
+ entry->varid = id;
+ entry->var_type = type;
+ if (flags & SRFL_ETHADDR) {
+ snprintf(entry->buf, 18, "%pM", ea);
+ } else if (flags & SRFL_CCODE) {
+ if (val == 0)
+ entry->buf[0] = '\0';
+ else
+ snprintf(entry->buf, 3, "%c%c",
+ (val >> 8), (val & 0xff));
+ } else {
+ entry->uval = val;
+ }
+
+ list_add(&entry->var_list, var_list);
+ }
+
+ if (sromrev >= 4) {
+ /* Do per-path variables */
+ uint p, pb, psz;
+
+ if (sromrev >= 8) {
+ pb = SROM8_PATH0;
+ psz = SROM8_PATH1 - SROM8_PATH0;
+ } else {
+ pb = SROM4_PATH0;
+ psz = SROM4_PATH1 - SROM4_PATH0;
+ }
+
+ for (p = 0; p < MAX_PATH_SROM; p++) {
+ for (srv = perpath_pci_sromvars;
+ srv->varid != BRCMS_SROM_NULL; srv++) {
+ if ((srv->revmask & sr) == 0)
+ continue;
+
+ if (srv->flags & SRFL_NOVAR)
+ continue;
+
+ w = srom[pb + srv->off];
+ val = (w & srv->mask) >> mask_shift(srv->mask);
+ width = mask_width(srv->mask);
+
+ /* Cheating: no per-path var is more than
+ * 1 word */
+ if ((srv->flags & SRFL_NOFFS)
+ && ((int)val == (1 << width) - 1))
+ continue;
+
+ entry =
+ kzalloc(sizeof(struct brcms_srom_list_head),
+ GFP_KERNEL);
+ entry->varid = srv->varid+p;
+ entry->var_type = BRCMS_SROM_UNUMBER;
+ entry->uval = val;
+ list_add(&entry->var_list, var_list);
+ }
+ pb += psz;
+ }
+ }
+}
+
+/*
+ * Read in and validate sprom.
+ * Return 0 on success, nonzero on error.
+ */
+static int
+sprom_read_pci(struct si_pub *sih, u16 __iomem *sprom, uint wordoff,
+ u16 *buf, uint nwords, bool check_crc)
+{
+ int err = 0;
+ uint i;
+
+ /* read the sprom */
+ for (i = 0; i < nwords; i++)
+ buf[i] = R_REG(&sprom[wordoff + i]);
+
+ if (check_crc) {
+
+ if (buf[0] == 0xffff)
+ /*
+ * The hardware thinks that an srom that starts with
+ * 0xffff is blank, regardless of the rest of the
+ * content, so declare it bad.
+ */
+ return -ENODATA;
+
+ /* fixup the endianness so crc8 will pass */
+ htol16_buf(buf, nwords * 2);
+ if (crc8(brcms_srom_crc8_table, (u8 *) buf, nwords * 2,
+ CRC8_INIT_VALUE) !=
+ CRC8_GOOD_VALUE(brcms_srom_crc8_table))
+ /* DBG only pci always read srom4 first, then srom8/9 */
+ err = -EIO;
+
+ /* now correct the endianness of the byte array */
+ ltoh16_buf(buf, nwords * 2);
+ }
+ return err;
+}
+
+static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
+{
+ u8 *otp;
+ uint sz = OTP_SZ_MAX / 2; /* size in words */
+ int err = 0;
+
+ otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
+ if (otp == NULL)
+ return -ENOMEM;
+
+ err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
+
+ memcpy(buf, otp, bufsz);
+
+ kfree(otp);
+
+ /* Check CRC */
+ if (buf[0] == 0xffff)
+ /* The hardware thinks that an srom that starts with 0xffff
+ * is blank, regardless of the rest of the content, so declare
+ * it bad.
+ */
+ return -ENODATA;
+
+ /* fixup the endianness so crc8 will pass */
+ htol16_buf(buf, bufsz);
+ if (crc8(brcms_srom_crc8_table, (u8 *) buf, SROM4_WORDS * 2,
+ CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table))
+ err = -EIO;
+
+ /* now correct the endianness of the byte array */
+ ltoh16_buf(buf, bufsz);
+
+ return err;
+}
+
+/*
+ * Initialize nonvolatile variable table from sprom.
+ * Return 0 on success, nonzero on error.
+ */
+static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
+{
+ u16 *srom;
+ u16 __iomem *sromwindow;
+ u8 sromrev = 0;
+ u32 sr;
+ int err = 0;
+
+ /*
+ * Apply CRC over SROM content regardless SROM is present or not.
+ */
+ srom = kmalloc(SROM_MAX, GFP_ATOMIC);
+ if (!srom)
+ return -ENOMEM;
+
+ sromwindow = srom_window_address(sih, curmap);
+
+ crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY);
+ if (ai_is_sprom_available(sih)) {
+ err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
+ true);
+
+ if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
+ (((sih->buscoretype == PCIE_CORE_ID)
+ && (sih->buscorerev >= 6))
+ || ((sih->buscoretype == PCI_CORE_ID)
+ && (sih->buscorerev >= 0xe)))) {
+ /* sromrev >= 4, read more */
+ err = sprom_read_pci(sih, sromwindow, 0, srom,
+ SROM4_WORDS, true);
+ sromrev = srom[SROM4_CRCREV] & 0xff;
+ } else if (err == 0) {
+ /* srom is good and is rev < 4 */
+ /* top word of sprom contains version and crc8 */
+ sromrev = srom[SROM_CRCREV] & 0xff;
+ /* bcm4401 sroms misprogrammed */
+ if (sromrev == 0x10)
+ sromrev = 1;
+ }
+ } else {
+ /* Use OTP if SPROM not available */
+ err = otp_read_pci(sih, srom, SROM_MAX);
+ if (err == 0)
+ /* OTP only contain SROM rev8/rev9 for now */
+ sromrev = srom[SROM4_CRCREV] & 0xff;
+ }
+
+ if (!err) {
+ struct si_info *sii = (struct si_info *)sih;
+
+ /* Bitmask for the sromrev */
+ sr = 1 << sromrev;
+
+ /*
+ * srom version check: Current valid versions: 1, 2, 3, 4, 5, 8,
+ * 9
+ */
+ if ((sr & 0x33e) == 0) {
+ err = -EINVAL;
+ goto errout;
+ }
+
+ INIT_LIST_HEAD(&sii->var_list);
+
+ /* parse SROM into name=value pairs. */
+ _initvars_srom_pci(sromrev, srom, &sii->var_list);
+ }
+
+errout:
+ kfree(srom);
+ return err;
+}
+
+void srom_free_vars(struct si_pub *sih)
+{
+ struct si_info *sii;
+ struct brcms_srom_list_head *entry, *next;
+
+ sii = (struct si_info *)sih;
+ list_for_each_entry_safe(entry, next, &sii->var_list, var_list) {
+ list_del(&entry->var_list);
+ kfree(entry);
+ }
+}
+/*
+ * Initialize local vars from the right source for this platform.
+ * Return 0 on success, nonzero on error.
+ */
+int srom_var_init(struct si_pub *sih, void __iomem *curmap)
+{
+ uint len;
+
+ len = 0;
+
+ if (curmap != NULL)
+ return initvars_srom_pci(sih, curmap);
+
+ return -EINVAL;
+}
+
+/*
+ * Search the name=value vars for a specific one and return its value.
+ * Returns NULL if not found.
+ */
+char *getvar(struct si_pub *sih, enum brcms_srom_id id)
+{
+ struct si_info *sii;
+ struct brcms_srom_list_head *entry;
+
+ sii = (struct si_info *)sih;
+
+ list_for_each_entry(entry, &sii->var_list, var_list)
+ if (entry->varid == id)
+ return &entry->buf[0];
+
+ /* nothing found */
+ return NULL;
+}
+
+/*
+ * Search the vars for a specific one and return its value as
+ * an integer. Returns 0 if not found.-
+ */
+int getintvar(struct si_pub *sih, enum brcms_srom_id id)
+{
+ struct si_info *sii;
+ struct brcms_srom_list_head *entry;
+ unsigned long res;
+
+ sii = (struct si_info *)sih;
+
+ list_for_each_entry(entry, &sii->var_list, var_list)
+ if (entry->varid == id) {
+ if (entry->var_type == BRCMS_SROM_SNUMBER ||
+ entry->var_type == BRCMS_SROM_UNUMBER)
+ return (int)entry->sval;
+ else if (!kstrtoul(&entry->buf[0], 0, &res))
+ return (int)res;
+ }
+
+ return 0;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/srom.h b/drivers/net/wireless/brcm80211/brcmsmac/srom.h
index efc4d1edd86d..708c43ff51cc 100644
--- a/drivers/staging/brcm80211/brcmsmac/srom.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/srom.h
@@ -20,8 +20,8 @@
#include "types.h"
/* Prototypes */
-extern int srom_var_init(struct si_pub *sih, uint bus, void *curmap,
- char **vars, uint *count);
+extern int srom_var_init(struct si_pub *sih, void __iomem *curmap);
+extern void srom_free_vars(struct si_pub *sih);
extern int srom_read(struct si_pub *sih, uint bus, void *curmap,
uint byteoff, uint nbytes, u16 *buf, bool check_crc);
diff --git a/drivers/staging/brcm80211/brcmsmac/stf.c b/drivers/net/wireless/brcm80211/brcmsmac/stf.c
index a55ff0101782..d8f528eb180c 100644
--- a/drivers/staging/brcm80211/brcmsmac/stf.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.c
@@ -22,7 +22,6 @@
#include "phy/phy_hal.h"
#include "channel.h"
#include "main.h"
-#include "bmac.h"
#include "stf.h"
#define MIN_SPATIAL_EXPANSION 0
@@ -31,20 +30,12 @@
#define BRCMS_STF_SS_STBC_RX(wlc) (BRCMS_ISNPHY(wlc->band) && \
NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6))
-static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val);
-static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts, u8 val);
-static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val);
-static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val);
-
-static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
-static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
- ratespec_t rspec);
-
#define NSTS_1 1
#define NSTS_2 2
#define NSTS_3 3
#define NSTS_4 4
-const u8 txcore_default[5] = {
+
+static const u8 txcore_default[5] = {
(0), /* bitmap of the core enabled */
(0x01), /* For Nsts = 1, enable core 1 */
(0x03), /* For Nsts = 2, enable core 1 & 2 */
@@ -60,16 +51,16 @@ static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val)
return;
}
- wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_RX_STBC;
- wlc->ht_cap.cap_info |= (val << IEEE80211_HT_CAP_RX_STBC_SHIFT);
-
if (wlc->pub->up) {
brcms_c_update_beacon(wlc);
brcms_c_update_probe_resp(wlc, true);
}
}
-/* every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to turn on/off txchain */
+/*
+ * every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to
+ * turn on/off txchain.
+ */
void brcms_c_tempsense_upd(struct brcms_c_info *wlc)
{
struct brcms_phy_pub *pi = wlc->band->pi;
@@ -81,21 +72,19 @@ void brcms_c_tempsense_upd(struct brcms_c_info *wlc)
txchain = active_chains & 0xf;
if (wlc->stf->txchain == wlc->stf->hw_txchain) {
- if (txchain && (txchain < wlc->stf->hw_txchain)) {
+ if (txchain && (txchain < wlc->stf->hw_txchain))
/* turn off 1 tx chain */
brcms_c_stf_txchain_set(wlc, txchain, true);
- }
} else if (wlc->stf->txchain < wlc->stf->hw_txchain) {
- if (txchain == wlc->stf->hw_txchain) {
+ if (txchain == wlc->stf->hw_txchain)
/* turn back on txchain */
brcms_c_stf_txchain_set(wlc, txchain, true);
- }
}
}
void
brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
- chanspec_t chanspec)
+ u16 chanspec)
{
struct tx_power power;
u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
@@ -120,16 +109,19 @@ brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
/* criteria to choose stf mode */
- /* the "+3dbm (12 0.25db units)" is to account for the fact that with CDD, tx occurs
- * on both chains
+ /*
+ * the "+3dbm (12 0.25db units)" is to account for the fact that with
+ * CDD, tx occurs on both chains
*/
if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12))
setbit(ss_algo_channel, PHY_TXC1_MODE_SISO);
else
setbit(ss_algo_channel, PHY_TXC1_MODE_CDD);
- /* STBC is ORed into to algo channel as STBC requires per-packet SCB capability check
- * so cannot be default mode of operation. One of SISO, CDD have to be set
+ /*
+ * STBC is ORed into to algo channel as STBC requires per-packet SCB
+ * capability check so cannot be default mode of operation. One of
+ * SISO, CDD have to be set
*/
if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12))
setbit(ss_algo_channel, PHY_TXC1_MODE_STBC);
@@ -137,19 +129,12 @@ brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val)
{
- if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) {
+ if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON))
return false;
- }
if ((int_val == ON) && (wlc->stf->txstreams == 1))
return false;
- if ((int_val == OFF) || (wlc->stf->txstreams == 1)
- || !BRCMS_STBC_CAP_PHY(wlc))
- wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
- else
- wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_TX_STBC;
-
wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val;
wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val;
@@ -159,9 +144,8 @@ static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val)
bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val)
{
if ((int_val != HT_CAP_RX_STBC_NO)
- && (int_val != HT_CAP_RX_STBC_ONE_STREAM)) {
+ && (int_val != HT_CAP_RX_STBC_ONE_STREAM))
return false;
- }
if (BRCMS_STF_SS_STBC_RX(wlc)) {
if ((int_val != HT_CAP_RX_STBC_NO)
@@ -179,15 +163,13 @@ static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts,
BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n",
wlc->pub->unit, Nsts, core_mask);
- if (BRCMS_BITSCNT(core_mask) > wlc->stf->txstreams) {
+ if (hweight8(core_mask) > wlc->stf->txstreams)
core_mask = 0;
- }
- if ((BRCMS_BITSCNT(core_mask) == wlc->stf->txstreams) &&
+ if ((hweight8(core_mask) == wlc->stf->txstreams) &&
((core_mask & ~wlc->stf->txchain)
- || !(core_mask & wlc->stf->txchain))) {
+ || !(core_mask & wlc->stf->txchain)))
core_mask = wlc->stf->txchain;
- }
wlc->stf->txcore[Nsts] = core_mask;
/* Nsts = 1..4, txcore index = 1..4 */
@@ -223,6 +205,60 @@ static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val)
return 0;
}
+/*
+ * Centralized txant update function. call it whenever wlc->stf->txant and/or
+ * wlc->stf->txchain change.
+ *
+ * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to
+ * achieve various tx/rx antenna selection schemes
+ *
+ * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7
+ * means auto(last rx).
+ * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7
+ * means last rx and do tx-antenna selection for SISO transmissions
+ * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7
+ * means last rx and do tx-antenna selection for SISO transmissions
+ * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7
+ * means both cores active
+*/
+static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
+{
+ s8 txant;
+
+ txant = (s8) wlc->stf->txant;
+ if (BRCMS_PHY_11N_CAP(wlc->band)) {
+ if (txant == ANT_TX_FORCE_0) {
+ wlc->stf->phytxant = PHY_TXC_ANT_0;
+ } else if (txant == ANT_TX_FORCE_1) {
+ wlc->stf->phytxant = PHY_TXC_ANT_1;
+
+ if (BRCMS_ISNPHY(wlc->band) &&
+ NREV_GE(wlc->band->phyrev, 3)
+ && NREV_LT(wlc->band->phyrev, 7))
+ wlc->stf->phytxant = PHY_TXC_ANT_2;
+ } else {
+ if (BRCMS_ISLCNPHY(wlc->band) ||
+ BRCMS_ISSSLPNPHY(wlc->band))
+ wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST;
+ else {
+ /* catch out of sync wlc->stf->txcore */
+ WARN_ON(wlc->stf->txchain <= 0);
+ wlc->stf->phytxant =
+ wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
+ }
+ }
+ } else {
+ if (txant == ANT_TX_FORCE_0)
+ wlc->stf->phytxant = PHY_TXC_OLD_ANT_0;
+ else if (txant == ANT_TX_FORCE_1)
+ wlc->stf->phytxant = PHY_TXC_OLD_ANT_1;
+ else
+ wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST;
+ }
+
+ brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
+}
+
int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force)
{
u8 txchain = (u8) int_val;
@@ -236,41 +272,14 @@ int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force)
|| !(txchain & wlc->stf->hw_txchain))
return -EINVAL;
- /* if nrate override is configured to be non-SISO STF mode, reject reducing txchain to 1 */
- txstreams = (u8) BRCMS_BITSCNT(txchain);
+ /*
+ * if nrate override is configured to be non-SISO STF mode, reject
+ * reducing txchain to 1
+ */
+ txstreams = (u8) hweight8(txchain);
if (txstreams > MAX_STREAMS_SUPPORTED)
return -EINVAL;
- if (txstreams == 1) {
- for (i = 0; i < NBANDS(wlc); i++)
- if ((RSPEC_STF(wlc->bandstate[i]->rspec_override) !=
- PHY_TXC1_MODE_SISO)
- || (RSPEC_STF(wlc->bandstate[i]->mrspec_override) !=
- PHY_TXC1_MODE_SISO)) {
- if (!force)
- return -EBADE;
-
- /* over-write the override rspec */
- if (RSPEC_STF(wlc->bandstate[i]->rspec_override)
- != PHY_TXC1_MODE_SISO) {
- wlc->bandstate[i]->rspec_override = 0;
- wiphy_err(wlc->wiphy, "%s(): temp "
- "sense override non-SISO "
- "rspec_override\n",
- __func__);
- }
- if (RSPEC_STF
- (wlc->bandstate[i]->mrspec_override) !=
- PHY_TXC1_MODE_SISO) {
- wlc->bandstate[i]->mrspec_override = 0;
- wiphy_err(wlc->wiphy, "%s(): temp "
- "sense override non-SISO "
- "mrspec_override\n",
- __func__);
- }
- }
- }
-
wlc->stf->txchain = txchain;
wlc->stf->txstreams = txstreams;
brcms_c_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx);
@@ -289,7 +298,10 @@ int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force)
return 0;
}
-/* update wlc->stf->ss_opmode which represents the operational stf_ss mode we're using */
+/*
+ * update wlc->stf->ss_opmode which represents the operational stf_ss mode
+ * we're using
+ */
int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band)
{
int ret_code = 0;
@@ -298,21 +310,22 @@ int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band)
prev_stf_ss = wlc->stf->ss_opmode;
- /* NOTE: opmode can only be SISO or CDD as STBC is decided on a per-packet basis */
+ /*
+ * NOTE: opmode can only be SISO or CDD as STBC is decided on a
+ * per-packet basis
+ */
if (BRCMS_STBC_CAP_PHY(wlc) &&
wlc->stf->ss_algosel_auto
&& (wlc->stf->ss_algo_channel != (u16) -1)) {
- upd_stf_ss = (wlc->stf->no_cddstbc || (wlc->stf->txstreams == 1)
- || isset(&wlc->stf->ss_algo_channel,
- PHY_TXC1_MODE_SISO)) ? PHY_TXC1_MODE_SISO
- : PHY_TXC1_MODE_CDD;
+ upd_stf_ss = (wlc->stf->txstreams == 1 ||
+ isset(&wlc->stf->ss_algo_channel,
+ PHY_TXC1_MODE_SISO)) ?
+ PHY_TXC1_MODE_SISO : PHY_TXC1_MODE_CDD;
} else {
if (wlc->band != band)
return ret_code;
- upd_stf_ss = (wlc->stf->no_cddstbc
- || (wlc->stf->txstreams ==
- 1)) ? PHY_TXC1_MODE_SISO : band->
- band_stf_ss_mode;
+ upd_stf_ss = (wlc->stf->txstreams == 1) ?
+ PHY_TXC1_MODE_SISO : band->band_stf_ss_mode;
}
if (prev_stf_ss != upd_stf_ss) {
wlc->stf->ss_opmode = upd_stf_ss;
@@ -340,7 +353,8 @@ int brcms_c_stf_attach(struct brcms_c_info *wlc)
if (BRCMS_STBC_CAP_PHY(wlc)) {
wlc->stf->ss_algosel_auto = true;
- wlc->stf->ss_algo_channel = (u16) -1; /* Init the default value */
+ /* Init the default value */
+ wlc->stf->ss_algo_channel = (u16) -1;
}
return 0;
}
@@ -349,59 +363,6 @@ void brcms_c_stf_detach(struct brcms_c_info *wlc)
{
}
-/*
- * Centralized txant update function. call it whenever wlc->stf->txant and/or wlc->stf->txchain
- * change
- *
- * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to
- * achieve various tx/rx antenna selection schemes
- *
- * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means auto(last rx)
- * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means last rx and
- * do tx-antenna selection for SISO transmissions
- * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 means last rx and
- * do tx-antenna selection for SISO transmissions
- * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 means both cores active
-*/
-static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
-{
- s8 txant;
-
- txant = (s8) wlc->stf->txant;
- if (BRCMS_PHY_11N_CAP(wlc->band)) {
- if (txant == ANT_TX_FORCE_0) {
- wlc->stf->phytxant = PHY_TXC_ANT_0;
- } else if (txant == ANT_TX_FORCE_1) {
- wlc->stf->phytxant = PHY_TXC_ANT_1;
-
- if (BRCMS_ISNPHY(wlc->band) &&
- NREV_GE(wlc->band->phyrev, 3)
- && NREV_LT(wlc->band->phyrev, 7)) {
- wlc->stf->phytxant = PHY_TXC_ANT_2;
- }
- } else {
- if (BRCMS_ISLCNPHY(wlc->band) ||
- BRCMS_ISSSLPNPHY(wlc->band))
- wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST;
- else {
- /* catch out of sync wlc->stf->txcore */
- WARN_ON(wlc->stf->txchain <= 0);
- wlc->stf->phytxant =
- wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
- }
- }
- } else {
- if (txant == ANT_TX_FORCE_0)
- wlc->stf->phytxant = PHY_TXC_OLD_ANT_0;
- else if (txant == ANT_TX_FORCE_1)
- wlc->stf->phytxant = PHY_TXC_OLD_ANT_1;
- else
- wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST;
- }
-
- brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
-}
-
void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
{
_brcms_c_stf_phy_txant_upd(wlc);
@@ -410,31 +371,29 @@ void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc)
{
/* get available rx/tx chains */
- wlc->stf->hw_txchain = (u8) getintvar(wlc->pub->vars, "txchain");
- wlc->stf->hw_rxchain = (u8) getintvar(wlc->pub->vars, "rxchain");
+ wlc->stf->hw_txchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_TXCHAIN);
+ wlc->stf->hw_rxchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_RXCHAIN);
/* these parameter are intended to be used for all PHY types */
if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) {
- if (BRCMS_ISNPHY(wlc->band)) {
+ if (BRCMS_ISNPHY(wlc->band))
wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY;
- } else {
+ else
wlc->stf->hw_txchain = TXCHAIN_DEF;
- }
}
wlc->stf->txchain = wlc->stf->hw_txchain;
- wlc->stf->txstreams = (u8) BRCMS_BITSCNT(wlc->stf->hw_txchain);
+ wlc->stf->txstreams = (u8) hweight8(wlc->stf->hw_txchain);
if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) {
- if (BRCMS_ISNPHY(wlc->band)) {
+ if (BRCMS_ISNPHY(wlc->band))
wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY;
- } else {
+ else
wlc->stf->hw_rxchain = RXCHAIN_DEF;
- }
}
wlc->stf->rxchain = wlc->stf->hw_rxchain;
- wlc->stf->rxstreams = (u8) BRCMS_BITSCNT(wlc->stf->hw_rxchain);
+ wlc->stf->rxstreams = (u8) hweight8(wlc->stf->hw_rxchain);
/* initialize the txcore table */
memcpy(wlc->stf->txcore, txcore_default, sizeof(wlc->stf->txcore));
@@ -445,24 +404,24 @@ void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc)
}
static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
- ratespec_t rspec)
+ u32 rspec)
{
u16 phytxant = wlc->stf->phytxant;
- if (RSPEC_STF(rspec) != PHY_TXC1_MODE_SISO) {
+ if (rspec_stf(rspec) != PHY_TXC1_MODE_SISO)
phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
- } else if (wlc->stf->txant == ANT_TX_DEF)
+ else if (wlc->stf->txant == ANT_TX_DEF)
phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
phytxant &= PHY_TXC_ANT_MASK;
return phytxant;
}
-u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, ratespec_t rspec)
+u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec)
{
return _brcms_c_stf_phytxchain_sel(wlc, rspec);
}
-u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, ratespec_t rspec)
+u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec)
{
u16 phytxant = wlc->stf->phytxant;
u16 mask = PHY_TXC_ANT_MASK;
diff --git a/drivers/staging/brcm80211/brcmsmac/stf.h b/drivers/net/wireless/brcm80211/brcmsmac/stf.h
index 06c2a399649e..19f6580f69be 100644
--- a/drivers/staging/brcm80211/brcmsmac/stf.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.h
@@ -25,7 +25,7 @@ extern void brcms_c_stf_detach(struct brcms_c_info *wlc);
extern void brcms_c_tempsense_upd(struct brcms_c_info *wlc);
extern void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc,
u16 *ss_algo_channel,
- chanspec_t chanspec);
+ u16 chanspec);
extern int brcms_c_stf_ss_update(struct brcms_c_info *wlc,
struct brcms_band *band);
extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
@@ -35,8 +35,8 @@ extern bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val);
extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
extern void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc);
extern u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
- ratespec_t rspec);
+ u32 rspec);
extern u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc,
- ratespec_t rspec);
+ u32 rspec);
#endif /* _BRCM_STF_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/types.h b/drivers/net/wireless/brcm80211/brcmsmac/types.h
new file mode 100644
index 000000000000..27a814b07462
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/types.h
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_TYPES_H_
+#define _BRCM_TYPES_H_
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#define WL_CHAN_FREQ_RANGE_2G 0
+#define WL_CHAN_FREQ_RANGE_5GL 1
+#define WL_CHAN_FREQ_RANGE_5GM 2
+#define WL_CHAN_FREQ_RANGE_5GH 3
+
+/* boardflags */
+
+/* Board has gpio 9 controlling the PA */
+#define BFL_PACTRL 0x00000002
+/* Not ok to power down the chip pll and oscillator */
+#define BFL_NOPLLDOWN 0x00000020
+/* Board supports the Front End Module */
+#define BFL_FEM 0x00000800
+/* Board has an external LNA in 2.4GHz band */
+#define BFL_EXTLNA 0x00001000
+/* Board has no PA */
+#define BFL_NOPA 0x00010000
+/* Power topology uses BUCKBOOST */
+#define BFL_BUCKBOOST 0x00200000
+/* Board has FEM and switch to share antenna w/ BT */
+#define BFL_FEM_BT 0x00400000
+/* Power topology doesn't use CBUCK */
+#define BFL_NOCBUCK 0x00800000
+/* Power topology uses PALDO */
+#define BFL_PALDO 0x02000000
+/* Board has an external LNA in 5GHz band */
+#define BFL_EXTLNA_5GHz 0x10000000
+
+/* boardflags2 */
+
+/* Board has an external rxbb regulator */
+#define BFL2_RXBB_INT_REG_DIS 0x00000001
+/* Flag to implement alternative A-band PLL settings */
+#define BFL2_APLL_WAR 0x00000002
+/* Board permits enabling TX Power Control */
+#define BFL2_TXPWRCTRL_EN 0x00000004
+/* Board supports the 2X4 diversity switch */
+#define BFL2_2X4_DIV 0x00000008
+/* Board supports 5G band power gain */
+#define BFL2_5G_PWRGAIN 0x00000010
+/* Board overrides ASPM and Clkreq settings */
+#define BFL2_PCIEWAR_OVR 0x00000020
+#define BFL2_LEGACY 0x00000080
+/* 4321mcm93 board uses Skyworks FEM */
+#define BFL2_SKWRKFEM_BRD 0x00000100
+/* Board has a WAR for clock-harmonic spurs */
+#define BFL2_SPUR_WAR 0x00000200
+/* Flag to narrow G-band PLL loop b/w */
+#define BFL2_GPLL_WAR 0x00000400
+/* Tx CCK pkts on Ant 0 only */
+#define BFL2_SINGLEANT_CCK 0x00001000
+/* WAR to reduce and avoid clock-harmonic spurs in 2G */
+#define BFL2_2G_SPUR_WAR 0x00002000
+/* Flag to widen G-band PLL loop b/w */
+#define BFL2_GPLL_WAR2 0x00010000
+#define BFL2_IPALVLSHIFT_3P3 0x00020000
+/* Use internal envelope detector for TX IQCAL */
+#define BFL2_INTERNDET_TXIQCAL 0x00040000
+/* Keep the buffered Xtal output from radio "ON". Most drivers will turn it
+ * off without this flag to save power. */
+#define BFL2_XTALBUFOUTEN 0x00080000
+
+/*
+ * board specific GPIO assignment, gpio 0-3 are also customer-configurable
+ * led
+ */
+
+/* bit 9 controls the PA on new 4306 boards */
+#define BOARD_GPIO_PACTRL 0x200
+#define BOARD_GPIO_12 0x1000
+#define BOARD_GPIO_13 0x2000
+
+/* **** Core type/rev defaults **** */
+#define D11CONF 0x0fffffb0 /* Supported D11 revs: 4, 5, 7-27
+ * also need to update wlc.h MAXCOREREV
+ */
+
+#define NCONF 0x000001ff /* Supported nphy revs:
+ * 0 4321a0
+ * 1 4321a1
+ * 2 4321b0/b1/c0/c1
+ * 3 4322a0
+ * 4 4322a1
+ * 5 4716a0
+ * 6 43222a0, 43224a0
+ * 7 43226a0
+ * 8 5357a0, 43236a0
+ */
+
+#define LCNCONF 0x00000007 /* Supported lcnphy revs:
+ * 0 4313a0, 4336a0, 4330a0
+ * 1
+ * 2 4330a0
+ */
+
+#define SSLPNCONF 0x0000000f /* Supported sslpnphy revs:
+ * 0 4329a0/k0
+ * 1 4329b0/4329C0
+ * 2 4319a0
+ * 3 5356a0
+ */
+
+/********************************************************************
+ * Phy/Core Configuration. Defines macros to to check core phy/rev *
+ * compile-time configuration. Defines default core support. *
+ * ******************************************************************
+ */
+
+/* Basic macros to check a configuration bitmask */
+
+#define CONF_HAS(config, val) ((config) & (1 << (val)))
+#define CONF_MSK(config, mask) ((config) & (mask))
+#define MSK_RANGE(low, hi) ((1 << ((hi)+1)) - (1 << (low)))
+#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high)))
+
+#define CONF_IS(config, val) ((config) == (1 << (val)))
+#define CONF_GE(config, val) ((config) & (0-(1 << (val))))
+#define CONF_GT(config, val) ((config) & (0-2*(1 << (val))))
+#define CONF_LT(config, val) ((config) & ((1 << (val))-1))
+#define CONF_LE(config, val) ((config) & (2*(1 << (val))-1))
+
+/* Wrappers for some of the above, specific to config constants */
+
+#define NCONF_HAS(val) CONF_HAS(NCONF, val)
+#define NCONF_MSK(mask) CONF_MSK(NCONF, mask)
+#define NCONF_IS(val) CONF_IS(NCONF, val)
+#define NCONF_GE(val) CONF_GE(NCONF, val)
+#define NCONF_GT(val) CONF_GT(NCONF, val)
+#define NCONF_LT(val) CONF_LT(NCONF, val)
+#define NCONF_LE(val) CONF_LE(NCONF, val)
+
+#define LCNCONF_HAS(val) CONF_HAS(LCNCONF, val)
+#define LCNCONF_MSK(mask) CONF_MSK(LCNCONF, mask)
+#define LCNCONF_IS(val) CONF_IS(LCNCONF, val)
+#define LCNCONF_GE(val) CONF_GE(LCNCONF, val)
+#define LCNCONF_GT(val) CONF_GT(LCNCONF, val)
+#define LCNCONF_LT(val) CONF_LT(LCNCONF, val)
+#define LCNCONF_LE(val) CONF_LE(LCNCONF, val)
+
+#define D11CONF_HAS(val) CONF_HAS(D11CONF, val)
+#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask)
+#define D11CONF_IS(val) CONF_IS(D11CONF, val)
+#define D11CONF_GE(val) CONF_GE(D11CONF, val)
+#define D11CONF_GT(val) CONF_GT(D11CONF, val)
+#define D11CONF_LT(val) CONF_LT(D11CONF, val)
+#define D11CONF_LE(val) CONF_LE(D11CONF, val)
+
+#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val)
+#define PHYCONF_IS(val) CONF_IS(PHYTYPE, val)
+
+#define NREV_IS(var, val) \
+ (NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val))))
+
+#define NREV_GE(var, val) \
+ (NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val))))
+
+#define NREV_GT(var, val) \
+ (NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val))))
+
+#define NREV_LT(var, val) \
+ (NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val))))
+
+#define NREV_LE(var, val) \
+ (NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val))))
+
+#define LCNREV_IS(var, val) \
+ (LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val))))
+
+#define LCNREV_GE(var, val) \
+ (LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val))))
+
+#define LCNREV_GT(var, val) \
+ (LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val))))
+
+#define LCNREV_LT(var, val) \
+ (LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val))))
+
+#define LCNREV_LE(var, val) \
+ (LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val))))
+
+#define D11REV_IS(var, val) \
+ (D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val))))
+
+#define D11REV_GE(var, val) \
+ (D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val))))
+
+#define D11REV_GT(var, val) \
+ (D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val))))
+
+#define D11REV_LT(var, val) \
+ (D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val))))
+
+#define D11REV_LE(var, val) \
+ (D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val))))
+
+#define PHYTYPE_IS(var, val)\
+ (PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val))))
+
+/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */
+
+#define _PHYCONF_N (1 << PHY_TYPE_N)
+#define _PHYCONF_LCN (1 << PHY_TYPE_LCN)
+#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN)
+
+#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN)
+
+/* Utility macro to identify 802.11n (HT) capable PHYs */
+#define PHYTYPE_11N_CAP(phytype) \
+ (PHYTYPE_IS(phytype, PHY_TYPE_N) || \
+ PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \
+ PHYTYPE_IS(phytype, PHY_TYPE_SSN))
+
+/* Last but not least: shorter wlc-specific var checks */
+#define BRCMS_ISNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_N)
+#define BRCMS_ISLCNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN)
+#define BRCMS_ISSSLPNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN)
+
+#define BRCMS_PHY_11N_CAP(band) PHYTYPE_11N_CAP((band)->phytype)
+
+/**********************************************************************
+ * ------------- End of Core phy/rev configuration. ----------------- *
+ * ********************************************************************
+ */
+
+#define BCMMSG(dev, fmt, args...) \
+do { \
+ if (brcm_msg_level & LOG_TRACE_VAL) \
+ wiphy_err(dev, "%s: " fmt, __func__, ##args); \
+} while (0)
+
+/*
+ * Register access macros.
+ *
+ * These macro's take a pointer to the address to read as one of their
+ * arguments. The macro itself deduces the size of the IO transaction (u8, u16
+ * or u32). Advantage of this approach in combination with using a struct to
+ * define the registers in a register block, is that access size and access
+ * location are defined in only one spot. This reduces the risk of the
+ * programmer trying to use an unsupported transaction size on a register.
+ *
+ */
+
+#define R_REG(r) \
+ ({ \
+ __typeof(*(r)) __osl_v; \
+ switch (sizeof(*(r))) { \
+ case sizeof(u8): \
+ __osl_v = readb((u8 __iomem *)(r)); \
+ break; \
+ case sizeof(u16): \
+ __osl_v = readw((u16 __iomem *)(r)); \
+ break; \
+ case sizeof(u32): \
+ __osl_v = readl((u32 __iomem *)(r)); \
+ break; \
+ } \
+ __osl_v; \
+ })
+
+#define W_REG(r, v) do { \
+ switch (sizeof(*(r))) { \
+ case sizeof(u8): \
+ writeb((u8)((v) & 0xFF), (u8 __iomem *)(r)); \
+ break; \
+ case sizeof(u16): \
+ writew((u16)((v) & 0xFFFF), (u16 __iomem *)(r)); \
+ break; \
+ case sizeof(u32): \
+ writel((u32)(v), (u32 __iomem *)(r)); \
+ break; \
+ } \
+ } while (0)
+
+#ifdef CONFIG_BCM47XX
+/*
+ * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
+ * transactions. As a fix, a read after write is performed on certain places
+ * in the code. Older chips and the newer 5357 family don't require this fix.
+ */
+#define W_REG_FLUSH(r, v) ({ W_REG((r), (v)); (void)R_REG(r); })
+#else
+#define W_REG_FLUSH(r, v) W_REG((r), (v))
+#endif /* CONFIG_BCM47XX */
+
+#define AND_REG(r, v) W_REG((r), R_REG(r) & (v))
+#define OR_REG(r, v) W_REG((r), R_REG(r) | (v))
+
+#define SET_REG(r, mask, val) \
+ W_REG((r), ((R_REG(r) & ~(mask)) | (val)))
+
+/* multi-bool data type: set of bools, mbool is true if any is set */
+
+/* set one bool */
+#define mboolset(mb, bit) ((mb) |= (bit))
+/* clear one bool */
+#define mboolclr(mb, bit) ((mb) &= ~(bit))
+/* true if one bool is set */
+#define mboolisset(mb, bit) (((mb) & (bit)) != 0)
+#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val)))
+
+#define CEIL(x, y) (((x) + ((y)-1)) / (y))
+
+/* forward declarations */
+struct wiphy;
+struct ieee80211_sta;
+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;
+struct tx_status;
+struct d11rxhdr;
+struct txpwr_limits;
+
+/* iovar structure */
+struct brcmu_iovar {
+ const char *name; /* name for lookup and display */
+ u16 varid; /* id for switch */
+ u16 flags; /* driver-specific flag bits */
+ u16 type; /* base type of argument */
+ u16 minlen; /* min length for buffer vars */
+};
+
+/* brcm_msg_level is a bit vector with defs in defs.h */
+extern u32 brcm_msg_level;
+
+#endif /* _BRCM_TYPES_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c b/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c
new file mode 100644
index 000000000000..80e3ccf865e3
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <defs.h>
+#include "types.h"
+#include <ucode_loader.h>
+
+enum {
+ D11UCODE_NAMETAG_START = 0,
+ D11LCN0BSINITVALS24,
+ D11LCN0INITVALS24,
+ D11LCN1BSINITVALS24,
+ D11LCN1INITVALS24,
+ D11LCN2BSINITVALS24,
+ D11LCN2INITVALS24,
+ D11N0ABSINITVALS16,
+ D11N0BSINITVALS16,
+ D11N0INITVALS16,
+ D11UCODE_OVERSIGHT16_MIMO,
+ D11UCODE_OVERSIGHT16_MIMOSZ,
+ D11UCODE_OVERSIGHT24_LCN,
+ D11UCODE_OVERSIGHT24_LCNSZ,
+ D11UCODE_OVERSIGHT_BOMMAJOR,
+ D11UCODE_OVERSIGHT_BOMMINOR
+};
+
+int brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode)
+{
+ int rc;
+
+ rc = brcms_check_firmwares(wl);
+
+ rc = rc < 0 ? rc :
+ brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0bsinitvals24,
+ D11LCN0BSINITVALS24);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0initvals24,
+ D11LCN0INITVALS24);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1bsinitvals24,
+ D11LCN1BSINITVALS24);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1initvals24,
+ D11LCN1INITVALS24);
+ rc = rc < 0 ? rc :
+ brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2bsinitvals24,
+ D11LCN2BSINITVALS24);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2initvals24,
+ D11LCN2INITVALS24);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0absinitvals16,
+ D11N0ABSINITVALS16);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0bsinitvals16,
+ D11N0BSINITVALS16);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0initvals16,
+ D11N0INITVALS16);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_16_mimo,
+ D11UCODE_OVERSIGHT16_MIMO);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_16_mimosz,
+ D11UCODE_OVERSIGHT16_MIMOSZ);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_24_lcn,
+ D11UCODE_OVERSIGHT24_LCN);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_24_lcnsz,
+ D11UCODE_OVERSIGHT24_LCNSZ);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bommajor,
+ D11UCODE_OVERSIGHT_BOMMAJOR);
+ rc = rc < 0 ?
+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bomminor,
+ D11UCODE_OVERSIGHT_BOMMINOR);
+ return rc;
+}
+
+void brcms_ucode_data_free(struct brcms_ucode *ucode)
+{
+ brcms_ucode_free_buf((void *)ucode->d11lcn0bsinitvals24);
+ brcms_ucode_free_buf((void *)ucode->d11lcn0initvals24);
+ brcms_ucode_free_buf((void *)ucode->d11lcn1bsinitvals24);
+ brcms_ucode_free_buf((void *)ucode->d11lcn1initvals24);
+ brcms_ucode_free_buf((void *)ucode->d11lcn2bsinitvals24);
+ brcms_ucode_free_buf((void *)ucode->d11lcn2initvals24);
+ brcms_ucode_free_buf((void *)ucode->d11n0absinitvals16);
+ brcms_ucode_free_buf((void *)ucode->d11n0bsinitvals16);
+ brcms_ucode_free_buf((void *)ucode->d11n0initvals16);
+ brcms_ucode_free_buf((void *)ucode->bcm43xx_16_mimo);
+ brcms_ucode_free_buf((void *)ucode->bcm43xx_24_lcn);
+ brcms_ucode_free_buf((void *)ucode->bcm43xx_bommajor);
+ brcms_ucode_free_buf((void *)ucode->bcm43xx_bomminor);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/ucode_loader.h b/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h
index ca53deced7bf..18750a814b4f 100644
--- a/drivers/staging/brcm80211/brcmsmac/ucode_loader.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h
@@ -13,6 +13,8 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#ifndef _BRCM_UCODE_H_
+#define _BRCM_UCODE_H_
#include "types.h" /* forward structure declarations */
@@ -21,32 +23,36 @@
#define UCODE_LOADER_API_VER 0
-struct d11init {
- u16 addr;
- u16 size;
- u32 value;
+struct d11init;
+
+struct brcms_ucode {
+ struct d11init *d11lcn0bsinitvals24;
+ struct d11init *d11lcn0initvals24;
+ struct d11init *d11lcn1bsinitvals24;
+ struct d11init *d11lcn1initvals24;
+ struct d11init *d11lcn2bsinitvals24;
+ struct d11init *d11lcn2initvals24;
+ struct d11init *d11n0absinitvals16;
+ struct d11init *d11n0bsinitvals16;
+ struct d11init *d11n0initvals16;
+ __le32 *bcm43xx_16_mimo;
+ size_t bcm43xx_16_mimosz;
+ __le32 *bcm43xx_24_lcn;
+ size_t bcm43xx_24_lcnsz;
+ u32 *bcm43xx_bommajor;
+ u32 *bcm43xx_bomminor;
};
-extern struct d11init *d11lcn0bsinitvals24;
-extern struct d11init *d11lcn0initvals24;
-extern struct d11init *d11lcn1bsinitvals24;
-extern struct d11init *d11lcn1initvals24;
-extern struct d11init *d11lcn2bsinitvals24;
-extern struct d11init *d11lcn2initvals24;
-extern struct d11init *d11n0absinitvals16;
-extern struct d11init *d11n0bsinitvals16;
-extern struct d11init *d11n0initvals16;
-extern u32 *bcm43xx_16_mimo;
-extern u32 bcm43xx_16_mimosz;
-extern u32 *bcm43xx_24_lcn;
-extern u32 bcm43xx_24_lcnsz;
-
-extern int brcms_ucode_data_init(struct brcms_info *wl);
-extern void brcms_ucode_data_free(void);
+extern int
+brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode);
+
+extern void brcms_ucode_data_free(struct brcms_ucode *ucode);
extern int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf,
unsigned int idx);
-extern int brcms_ucode_init_uint(struct brcms_info *wl, unsigned *data,
- unsigned int idx);
+extern int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes,
+ unsigned int idx);
extern void brcms_ucode_free_buf(void *);
extern int brcms_check_firmwares(struct brcms_info *wl);
+
+#endif /* _BRCM_UCODE_H_ */
diff --git a/drivers/staging/brcm80211/brcmutil/Makefile b/drivers/net/wireless/brcm80211/brcmutil/Makefile
index 6403423c0212..6281c416289e 100644
--- a/drivers/staging/brcm80211/brcmutil/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmutil/Makefile
@@ -16,12 +16,11 @@
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ccflags-y := \
- -Idrivers/staging/brcm80211/brcmutil \
- -Idrivers/staging/brcm80211/include
+ -Idrivers/net/wireless/brcm80211/brcmutil \
+ -Idrivers/net/wireless/brcm80211/include
BRCMUTIL_OFILES := \
- utils.o \
- wifi.o
+ utils.o
MODULEPFX := brcmutil
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
new file mode 100644
index 000000000000..f27c48910827
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <brcmu_utils.h>
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver utilities.");
+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+struct sk_buff *brcmu_pkt_buf_get_skb(uint len)
+{
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(len);
+ if (skb) {
+ skb_put(skb, len);
+ skb->priority = 0;
+ }
+
+ return skb;
+}
+EXPORT_SYMBOL(brcmu_pkt_buf_get_skb);
+
+/* Free the driver packet. Free the tag if present */
+void brcmu_pkt_buf_free_skb(struct sk_buff *skb)
+{
+ struct sk_buff *nskb;
+ int nest = 0;
+
+ /* perversion: we use skb->next to chain multi-skb packets */
+ while (skb) {
+ nskb = skb->next;
+ skb->next = NULL;
+
+ if (skb->destructor)
+ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
+ * destructor exists
+ */
+ dev_kfree_skb_any(skb);
+ else
+ /* can free immediately (even in_irq()) if destructor
+ * does not exist
+ */
+ dev_kfree_skb(skb);
+
+ nest++;
+ skb = nskb;
+ }
+}
+EXPORT_SYMBOL(brcmu_pkt_buf_free_skb);
+
+
+/* copy a buffer into a pkt buffer chain */
+uint brcmu_pktfrombuf(struct sk_buff *p, uint offset, int len,
+ unsigned char *buf)
+{
+ uint n, ret = 0;
+
+ /* skip 'offset' bytes */
+ for (; p && offset; p = p->next) {
+ if (offset < (uint) (p->len))
+ break;
+ offset -= p->len;
+ }
+
+ if (!p)
+ return 0;
+
+ /* copy the data */
+ for (; p && len; p = p->next) {
+ n = min((uint) (p->len) - offset, (uint) len);
+ memcpy(p->data + offset, buf, n);
+ buf += n;
+ len -= n;
+ ret += n;
+ offset = 0;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(brcmu_pktfrombuf);
+
+/* return total length of buffer chain */
+uint brcmu_pkttotlen(struct sk_buff *p)
+{
+ uint total;
+
+ total = 0;
+ for (; p; p = p->next)
+ total += p->len;
+ return total;
+}
+EXPORT_SYMBOL(brcmu_pkttotlen);
+
+/*
+ * osl multiple-precedence packet queue
+ * hi_prec is always >= the number of the highest non-empty precedence
+ */
+struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec,
+ struct sk_buff *p)
+{
+ struct pktq_prec *q;
+
+ if (pktq_full(pq) || pktq_pfull(pq, prec))
+ return NULL;
+
+ q = &pq->q[prec];
+
+ if (q->head)
+ q->tail->prev = p;
+ else
+ q->head = p;
+
+ q->tail = p;
+ q->len++;
+
+ pq->len++;
+
+ if (pq->hi_prec < prec)
+ pq->hi_prec = (u8) prec;
+
+ return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_penq);
+
+struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
+ struct sk_buff *p)
+{
+ struct pktq_prec *q;
+
+ if (pktq_full(pq) || pktq_pfull(pq, prec))
+ return NULL;
+
+ q = &pq->q[prec];
+
+ if (q->head == NULL)
+ q->tail = p;
+
+ p->prev = q->head;
+ q->head = p;
+ q->len++;
+
+ pq->len++;
+
+ if (pq->hi_prec < prec)
+ pq->hi_prec = (u8) prec;
+
+ return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_penq_head);
+
+struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec)
+{
+ struct pktq_prec *q;
+ struct sk_buff *p;
+
+ q = &pq->q[prec];
+
+ p = q->head;
+ if (p == NULL)
+ return NULL;
+
+ q->head = p->prev;
+ if (q->head == NULL)
+ q->tail = NULL;
+
+ q->len--;
+
+ pq->len--;
+
+ p->prev = NULL;
+
+ return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_pdeq);
+
+struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec)
+{
+ struct pktq_prec *q;
+ struct sk_buff *p, *prev;
+
+ q = &pq->q[prec];
+
+ p = q->head;
+ if (p == NULL)
+ return NULL;
+
+ for (prev = NULL; p != q->tail; p = p->prev)
+ prev = p;
+
+ if (prev)
+ prev->prev = NULL;
+ else
+ q->head = NULL;
+
+ q->tail = prev;
+ q->len--;
+
+ pq->len--;
+
+ return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_pdeq_tail);
+
+void
+brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir,
+ bool (*fn)(struct sk_buff *, void *), void *arg)
+{
+ struct pktq_prec *q;
+ struct sk_buff *p, *prev = NULL;
+
+ q = &pq->q[prec];
+ p = q->head;
+ while (p) {
+ if (fn == NULL || (*fn) (p, arg)) {
+ bool head = (p == q->head);
+ if (head)
+ q->head = p->prev;
+ else
+ prev->prev = p->prev;
+ p->prev = NULL;
+ brcmu_pkt_buf_free_skb(p);
+ q->len--;
+ pq->len--;
+ p = (head ? q->head : prev->prev);
+ } else {
+ prev = p;
+ p = p->prev;
+ }
+ }
+
+ if (q->head == NULL)
+ q->tail = NULL;
+}
+EXPORT_SYMBOL(brcmu_pktq_pflush);
+
+void brcmu_pktq_flush(struct pktq *pq, bool dir,
+ bool (*fn)(struct sk_buff *, void *), void *arg)
+{
+ int prec;
+ for (prec = 0; prec < pq->num_prec; prec++)
+ brcmu_pktq_pflush(pq, prec, dir, fn, arg);
+}
+EXPORT_SYMBOL(brcmu_pktq_flush);
+
+void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len)
+{
+ int prec;
+
+ /* pq is variable size; only zero out what's requested */
+ memset(pq, 0,
+ offsetof(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
+
+ pq->num_prec = (u16) num_prec;
+
+ pq->max = (u16) max_len;
+
+ for (prec = 0; prec < num_prec; prec++)
+ pq->q[prec].max = pq->max;
+}
+EXPORT_SYMBOL(brcmu_pktq_init);
+
+struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out)
+{
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ for (prec = 0; prec < pq->hi_prec; prec++)
+ if (pq->q[prec].head)
+ break;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ return pq->q[prec].tail;
+}
+EXPORT_SYMBOL(brcmu_pktq_peek_tail);
+
+/* Return sum of lengths of a specific set of precedences */
+int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp)
+{
+ int prec, len;
+
+ len = 0;
+
+ for (prec = 0; prec <= pq->hi_prec; prec++)
+ if (prec_bmp & (1 << prec))
+ len += pq->q[prec].len;
+
+ return len;
+}
+EXPORT_SYMBOL(brcmu_pktq_mlen);
+
+/* Priority dequeue from a specific set of precedences */
+struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
+ int *prec_out)
+{
+ struct pktq_prec *q;
+ struct sk_buff *p;
+ int prec;
+
+ if (pq->len == 0)
+ return NULL;
+
+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+ pq->hi_prec--;
+
+ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
+ if (prec-- == 0)
+ return NULL;
+
+ q = &pq->q[prec];
+
+ p = q->head;
+ if (p == NULL)
+ return NULL;
+
+ q->head = p->prev;
+ if (q->head == NULL)
+ q->tail = NULL;
+
+ q->len--;
+
+ if (prec_out)
+ *prec_out = prec;
+
+ pq->len--;
+
+ p->prev = NULL;
+
+ return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_mdeq);
+
+#if defined(BCMDBG)
+/* pretty hex print a pkt buffer chain */
+void brcmu_prpkt(const char *msg, struct sk_buff *p0)
+{
+ struct sk_buff *p;
+
+ if (msg && (msg[0] != '\0'))
+ printk(KERN_DEBUG "%s:\n", msg);
+
+ for (p = p0; p; p = p->next)
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len);
+}
+EXPORT_SYMBOL(brcmu_prpkt);
+#endif /* defined(BCMDBG) */
+
+#if defined(BCMDBG)
+/*
+ * print bytes formatted as hex to a string. return the resulting
+ * string length
+ */
+int brcmu_format_hex(char *str, const void *bytes, int len)
+{
+ int i;
+ char *p = str;
+ const u8 *src = (const u8 *)bytes;
+
+ for (i = 0; i < len; i++) {
+ p += snprintf(p, 3, "%02X", *src);
+ src++;
+ }
+ return (int)(p - str);
+}
+EXPORT_SYMBOL(brcmu_format_hex);
+#endif /* defined(BCMDBG) */
diff --git a/drivers/staging/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
index 5fb17d53c9b2..5fb17d53c9b2 100644
--- a/drivers/staging/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
new file mode 100644
index 000000000000..7d0f46e0eb95
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCMU_UTILS_H_
+#define _BRCMU_UTILS_H_
+
+#include <linux/skbuff.h>
+
+/*
+ * Spin at most 'us' microseconds while 'exp' is true.
+ * Caller should explicitly test 'exp' when this completes
+ * and take appropriate error action if 'exp' is still true.
+ */
+#define SPINWAIT(exp, us) { \
+ uint countdown = (us) + 9; \
+ while ((exp) && (countdown >= 10)) {\
+ udelay(10); \
+ countdown -= 10; \
+ } \
+}
+
+/* osl multi-precedence packet queue */
+#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */
+#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */
+
+#define BCME_STRLEN 64 /* Max string length for BCM errors */
+
+/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
+#define PKTBUFSZ 2048
+
+#ifndef setbit
+#ifndef NBBY /* the BSD family defines NBBY */
+#define NBBY 8 /* 8 bits per byte */
+#endif /* #ifndef NBBY */
+#define setbit(a, i) (((u8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define clrbit(a, i) (((u8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define isset(a, i) (((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY)))
+#define isclr(a, i) ((((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif /* setbit */
+
+#define NBITS(type) (sizeof(type) * 8)
+#define NBITVAL(nbits) (1 << (nbits))
+#define MAXBITVAL(nbits) ((1 << (nbits)) - 1)
+#define NBITMASK(nbits) MAXBITVAL(nbits)
+#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8)
+
+/* crc defines */
+#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */
+#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */
+
+/* 18-bytes of Ethernet address buffer length */
+#define ETHER_ADDR_STR_LEN 18
+
+struct pktq_prec {
+ struct sk_buff *head; /* first packet to dequeue */
+ struct sk_buff *tail; /* last packet to dequeue */
+ u16 len; /* number of queued packets */
+ u16 max; /* maximum number of queued packets */
+};
+
+/* multi-priority pkt queue */
+struct pktq {
+ u16 num_prec; /* number of precedences in use */
+ u16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */
+ u16 max; /* total max packets */
+ u16 len; /* total number of packets */
+ /*
+ * q array must be last since # of elements can be either
+ * PKTQ_MAX_PREC or 1
+ */
+ struct pktq_prec q[PKTQ_MAX_PREC];
+};
+
+/* operations on a specific precedence in packet queue */
+
+static inline int pktq_plen(struct pktq *pq, int prec)
+{
+ return pq->q[prec].len;
+}
+
+static inline int pktq_pavail(struct pktq *pq, int prec)
+{
+ return pq->q[prec].max - pq->q[prec].len;
+}
+
+static inline bool pktq_pfull(struct pktq *pq, int prec)
+{
+ return pq->q[prec].len >= pq->q[prec].max;
+}
+
+static inline bool pktq_pempty(struct pktq *pq, int prec)
+{
+ return pq->q[prec].len == 0;
+}
+
+static inline struct sk_buff *pktq_ppeek(struct pktq *pq, int prec)
+{
+ return pq->q[prec].head;
+}
+
+static inline struct sk_buff *pktq_ppeek_tail(struct pktq *pq, int prec)
+{
+ return pq->q[prec].tail;
+}
+
+extern struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec,
+ struct sk_buff *p);
+extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
+ struct sk_buff *p);
+extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec);
+extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec);
+
+/* packet primitives */
+extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len);
+extern void brcmu_pkt_buf_free_skb(struct sk_buff *skb);
+
+/* Empty the queue at particular precedence level */
+/* callback function fn(pkt, arg) returns true if pkt belongs to if */
+extern void brcmu_pktq_pflush(struct pktq *pq, int prec,
+ bool dir, bool (*fn)(struct sk_buff *, void *), void *arg);
+
+/* operations on a set of precedences in packet queue */
+
+extern int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp);
+extern struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
+ int *prec_out);
+
+/* operations on packet queue as a whole */
+
+static inline int pktq_len(struct pktq *pq)
+{
+ return (int)pq->len;
+}
+
+static inline int pktq_max(struct pktq *pq)
+{
+ return (int)pq->max;
+}
+
+static inline int pktq_avail(struct pktq *pq)
+{
+ return (int)(pq->max - pq->len);
+}
+
+static inline bool pktq_full(struct pktq *pq)
+{
+ return pq->len >= pq->max;
+}
+
+static inline bool pktq_empty(struct pktq *pq)
+{
+ return pq->len == 0;
+}
+
+extern void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len);
+/* prec_out may be NULL if caller is not interested in return value */
+extern struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out);
+extern void brcmu_pktq_flush(struct pktq *pq, bool dir,
+ bool (*fn)(struct sk_buff *, void *), void *arg);
+
+/* externs */
+/* packet */
+extern uint brcmu_pktfrombuf(struct sk_buff *p,
+ uint offset, int len, unsigned char *buf);
+extern uint brcmu_pkttotlen(struct sk_buff *p);
+
+/* ip address */
+struct ipv4_addr;
+
+#ifdef BCMDBG
+extern void brcmu_prpkt(const char *msg, struct sk_buff *p0);
+#else
+#define brcmu_prpkt(a, b)
+#endif /* BCMDBG */
+
+/* externs */
+/* format/print */
+#if defined(BCMDBG)
+extern int brcmu_format_hex(char *str, const void *bytes, int len);
+#endif
+
+#endif /* _BRCMU_UTILS_H_ */
diff --git a/drivers/staging/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
index fde592bd9177..f10d30274c23 100644
--- a/drivers/staging/brcm80211/include/brcmu_wifi.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
@@ -20,8 +20,10 @@
#include <linux/if_ether.h> /* for ETH_ALEN */
#include <linux/ieee80211.h> /* for WLAN_PMKID_LEN */
-/* A chanspec holds the channel number, band, bandwidth and control sideband */
-typedef u16 chanspec_t;
+/*
+ * A chanspec (u16) holds the channel number, band, bandwidth and control
+ * sideband
+ */
/* channel defines */
#define CH_UPPER_SB 0x01
@@ -29,13 +31,20 @@ typedef u16 chanspec_t;
#define CH_EWA_VALID 0x04
#define CH_20MHZ_APART 4
#define CH_10MHZ_APART 2
-#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
+#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */
#define BRCM_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL /* legacy define */
-#define MAXCHANNEL 224 /* max # supported channels. The max channel no is 216,
- * this is that + 1 rounded up to a multiple of NBBY (8).
- * DO NOT MAKE it > 255: channels are u8's all over
- */
+
+/* bandstate array indices */
+#define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */
+#define BAND_5G_INDEX 1 /* wlc->bandstate[x] index */
+
+/*
+ * max # supported channels. The max channel no is 216, this is that + 1
+ * rounded up to a multiple of NBBY (8). DO NOT MAKE it > 255: channels are
+ * u8's all over
+*/
+#define MAXCHANNEL 224
#define WL_CHANSPEC_CHAN_MASK 0x00ff
#define WL_CHANSPEC_CHAN_SHIFT 0
@@ -63,58 +72,78 @@ typedef u16 chanspec_t;
#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */
#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */
-/* channel defines */
-#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0)
-#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
- ((channel) + CH_10MHZ_APART) : 0)
-#define CHSPEC_BANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : \
- BAND_2G_INDEX)
-#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
- WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
- WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
- ((channel) + CH_20MHZ_APART) : 0)
-#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
- ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
- ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
- WL_CHANSPEC_BAND_5G))
#define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK))
#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
-#ifdef WL11N_20MHZONLY
+#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK)
+#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK)
-#define CHSPEC_CTL_SB(chspec) WL_CHANSPEC_CTL_SB_NONE
-#define CHSPEC_BW(chspec) WL_CHANSPEC_BW_20
-#define CHSPEC_IS10(chspec) 0
-#define CHSPEC_IS20(chspec) 1
-#ifndef CHSPEC_IS40
-#define CHSPEC_IS40(chspec) 0
-#endif
+#define CHSPEC_IS10(chspec) \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
-#else /* !WL11N_20MHZONLY */
+#define CHSPEC_IS20(chspec) \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
-#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK)
-#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK)
-#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
-#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
#ifndef CHSPEC_IS40
-#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
+#define CHSPEC_IS40(chspec) \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
#endif
-#endif /* !WL11N_20MHZONLY */
+#define CHSPEC_IS5G(chspec) \
+ (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
+
+#define CHSPEC_IS2G(chspec) \
+ (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
+
+#define CHSPEC_SB_NONE(chspec) \
+ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE)
+
+#define CHSPEC_SB_UPPER(chspec) \
+ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER)
+
+#define CHSPEC_SB_LOWER(chspec) \
+ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER)
+
+#define CHSPEC_CTL_CHAN(chspec) \
+ ((CHSPEC_SB_LOWER(chspec)) ? \
+ (lower_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \
+ (upper_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK))))
-#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
-#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
-#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE)
-#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER)
-#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER)
-#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \
- (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \
- (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))))
#define CHSPEC2BAND(chspec) (CHSPEC_IS5G(chspec) ? BRCM_BAND_5G : BRCM_BAND_2G)
#define CHANSPEC_STR_LEN 8
+static inline int lower_20_sb(int channel)
+{
+ return channel > CH_10MHZ_APART ? (channel - CH_10MHZ_APART) : 0;
+}
+
+static inline int upper_20_sb(int channel)
+{
+ return (channel < (MAXCHANNEL - CH_10MHZ_APART)) ?
+ channel + CH_10MHZ_APART : 0;
+}
+
+static inline int chspec_bandunit(u16 chspec)
+{
+ return CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX;
+}
+
+static inline u16 ch20mhz_chspec(int channel)
+{
+ u16 rc = channel <= CH_MAX_2G_CHANNEL ?
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G;
+
+ return (u16)((u16)channel | WL_CHANSPEC_BW_20 |
+ WL_CHANSPEC_CTL_SB_NONE | rc);
+}
+
+static inline int next_20mhz_chan(int channel)
+{
+ return channel < (MAXCHANNEL - CH_20MHZ_APART) ?
+ channel + CH_20MHZ_APART : 0;
+}
+
/* defined rate in 500kbps */
#define BRCM_MAXRATE 108 /* in 500kbps units */
#define BRCM_RATE_1M 2 /* in 500kbps units */
@@ -134,43 +163,10 @@ typedef u16 chanspec_t;
#define MCSSET_LEN 16
-#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0)
-
-/*
- * Verify the chanspec is using a legal set of parameters, i.e. that the
- * chanspec specified a band, bw, ctl_sb and channel and that the
- * combination could be legal given any set of circumstances.
- * RETURNS: true is the chanspec is malformed, false if it looks good.
- */
-extern bool brcmu_chspec_malformed(chanspec_t chanspec);
-
-/*
- * This function returns the channel number that control traffic is being sent on, for legacy
- * channels this is just the channel number, for 40MHZ channels it is the upper or lowre 20MHZ
- * sideband depending on the chanspec selected
- */
-extern u8 brcmu_chspec_ctlchan(chanspec_t chspec);
-
-/*
- * Return the channel number for a given frequency and base frequency.
- * The returned channel number is relative to the given base frequency.
- * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
- * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
- *
- * Frequency is specified in MHz.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- *
- * The returned channel will be in the range [1, 14] in the 2.4 GHz band
- * and [0, 200] otherwise.
- * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
- * frequency is not a 2.4 GHz channel, or if the frequency is not and even
- * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-extern int brcmu_mhz2channel(uint freq, uint start_factor);
+static inline bool ac_bitmap_tst(u8 bitmap, int prec)
+{
+ return (bitmap & (1 << (prec))) != 0;
+}
/* Enumerate crypto algorithms */
#define CRYPTO_ALGO_OFF 0
@@ -183,11 +179,13 @@ extern int brcmu_mhz2channel(uint freq, uint start_factor);
#define CRYPTO_ALGO_NALG 7
/* wireless security bitvec */
+
#define WEP_ENABLED 0x0001
#define TKIP_ENABLED 0x0002
#define AES_ENABLED 0x0004
#define WSEC_SWFLAG 0x0008
-#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */
+/* to go into transition mode without setting wep */
+#define SES_OW_ENABLED 0x0040
/* WPA authentication mode bitvec */
#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */
@@ -196,7 +194,7 @@ extern int brcmu_mhz2channel(uint freq, uint start_factor);
#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */
#define WPA_AUTH_RESERVED1 0x0008
#define WPA_AUTH_RESERVED2 0x0010
- /* #define WPA_AUTH_8021X 0x0020 *//* 802.1x, reserved */
+
#define WPA2_AUTH_RESERVED1 0x0020
#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */
#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */
@@ -218,26 +216,24 @@ extern int brcmu_mhz2channel(uint freq, uint start_factor);
#define HT_CAP_RX_STBC_NO 0x0
#define HT_CAP_RX_STBC_ONE_STREAM 0x1
-typedef struct _pmkid {
+struct pmkid {
u8 BSSID[ETH_ALEN];
u8 PMKID[WLAN_PMKID_LEN];
-} pmkid_t;
+};
-typedef struct _pmkid_list {
- u32 npmkid;
- pmkid_t pmkid[1];
-} pmkid_list_t;
+struct pmkid_list {
+ __le32 npmkid;
+ struct pmkid pmkid[1];
+};
-typedef struct _pmkid_cand {
+struct pmkid_cand {
u8 BSSID[ETH_ALEN];
u8 preauth;
-} pmkid_cand_t;
+};
-typedef struct _pmkid_cand_list {
+struct pmkid_cand_list {
u32 npmkid_cand;
- pmkid_cand_t pmkid_cand[1];
-} pmkid_cand_list_t;
-
-typedef u8 ac_bitmap_t;
+ struct pmkid_cand pmkid_cand[1];
+};
#endif /* _BRCMU_WIFI_H_ */
diff --git a/drivers/staging/brcm80211/include/chipcommon.h b/drivers/net/wireless/brcm80211/include/chipcommon.h
index 296582aced69..fefabc39e646 100644
--- a/drivers/staging/brcm80211/include/chipcommon.h
+++ b/drivers/net/wireless/brcm80211/include/chipcommon.h
@@ -19,7 +19,7 @@
#include "defs.h" /* for PAD macro */
-typedef volatile struct {
+struct chipcregs {
u32 chipid; /* 0x0 */
u32 capabilities;
u32 corecontrol; /* corerev >= 1 */
@@ -214,7 +214,7 @@ typedef volatile struct {
u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */
u32 PAD[100];
u16 sromotp[768];
-} chipcregs_t;
+};
/* chipid */
#define CID_ID_MASK 0x0000ffff /* Chip Id mask */
@@ -231,7 +231,8 @@ typedef volatile struct {
#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */
#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */
#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */
-#define CC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */
+/* UARTs are driven by internal divided clock */
+#define CC_CAP_UINTCLK 0x00000008
#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */
#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */
#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */
@@ -248,10 +249,12 @@ typedef volatile struct {
#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */
#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */
#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */
-#define CC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */
+/* Nand flash present, rev >= 35 */
+#define CC_CAP_NFLASH 0x80000000
#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */
-#define CC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */
+/* GSIO (spi/i2c) present, rev >= 37 */
+#define CC_CAP2_GSIO 0x00000002
/* pmucapabilities */
#define PCAP_REV_MASK 0x000000ff
diff --git a/drivers/staging/brcm80211/include/defs.h b/drivers/net/wireless/brcm80211/include/defs.h
index 8b3e17dec150..1e5f310af1e7 100644
--- a/drivers/staging/brcm80211/include/defs.h
+++ b/drivers/net/wireless/brcm80211/include/defs.h
@@ -27,14 +27,8 @@
#define USB_BUS 5
#define SPI_BUS 6
-#ifndef OFF
#define OFF 0
-#endif
-
-#ifndef ON
#define ON 1 /* ON = 1 */
-#endif
-
#define AUTO (-1) /* Auto = -1 */
/*
@@ -54,27 +48,23 @@
#define WL_NUMRATES 16 /* max # of rates in a rateset */
-typedef struct wl_rateset {
- u32 count; /* # rates in this set */
- u8 rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */
-} wl_rateset_t;
-
#define BRCM_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */
-#define BRCM_SET_CHANNEL 30
-#define BRCM_SET_SRL 32
-#define BRCM_SET_LRL 34
+#define BRCM_SET_CHANNEL 30
+#define BRCM_SET_SRL 32
+#define BRCM_SET_LRL 34
+#define BRCM_SET_BCNPRD 76
-#define BRCM_SET_RATESET 72
-#define BRCM_SET_BCNPRD 76
-#define BRCM_GET_CURR_RATESET 114 /* current rateset */
-#define BRCM_GET_PHYLIST 180
+#define BRCM_GET_CURR_RATESET 114 /* current rateset */
+#define BRCM_GET_PHYLIST 180
/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
+
#define WL_RADIO_SW_DISABLE (1<<0)
#define WL_RADIO_HW_DISABLE (1<<1)
#define WL_RADIO_MPC_DISABLE (1<<2)
-#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */
+/* some countries don't support any channel */
+#define WL_RADIO_COUNTRY_DISABLE (1<<3)
/* Override bit for SET_TXPWR. if set, ignore other level limits */
#define WL_TXPWR_OVERRIDE (1U<<31)
@@ -100,7 +90,9 @@ typedef struct wl_rateset {
/*
* Sonics Configuration Space Registers.
*/
-#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */
+
+/* core sbconfig regs are top 256bytes of regs */
+#define SBCONFIGOFF 0xf00
/* cpp contortions to concatenate w/arg prescan */
#ifndef PAD
diff --git a/drivers/staging/brcm80211/include/soc.h b/drivers/net/wireless/brcm80211/include/soc.h
index 6e5a705c4937..4fcb956ad9e0 100644
--- a/drivers/staging/brcm80211/include/soc.h
+++ b/drivers/net/wireless/brcm80211/include/soc.h
@@ -17,11 +17,7 @@
#ifndef _BRCM_SOC_H
#define _BRCM_SOC_H
-#ifdef SI_ENUM_BASE_VARIABLE
-#define SI_ENUM_BASE (sii->pub.si_enum_base)
-#else
#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */
-#endif /* SI_ENUM_BASE_VARIABLE */
/* core codes */
#define NODEV_CORE_ID 0x700 /* Invalid coreid */
@@ -81,9 +77,8 @@
#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */
#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */
#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */
-#define DEF_AI_COMP 0xfff /* Default component, in ai chips it maps all
- * unused address ranges
- */
+/* Default component, in ai chips it maps all unused address ranges */
+#define DEF_AI_COMP 0xfff
/* Common core control flags */
#define SICF_BIST_EN 0x8000
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 89a116fba1de..bfa0d54221e8 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -816,7 +816,7 @@ static const struct net_device_ops hostap_netdev_ops = {
.ndo_stop = prism2_close,
.ndo_do_ioctl = hostap_ioctl,
.ndo_set_mac_address = prism2_set_mac_address,
- .ndo_set_multicast_list = hostap_set_multicast_list,
+ .ndo_set_rx_mode = hostap_set_multicast_list,
.ndo_change_mtu = prism2_change_mtu,
.ndo_tx_timeout = prism2_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
@@ -829,7 +829,7 @@ static const struct net_device_ops hostap_mgmt_netdev_ops = {
.ndo_stop = prism2_close,
.ndo_do_ioctl = hostap_ioctl,
.ndo_set_mac_address = prism2_set_mac_address,
- .ndo_set_multicast_list = hostap_set_multicast_list,
+ .ndo_set_rx_mode = hostap_set_multicast_list,
.ndo_change_mtu = prism2_change_mtu,
.ndo_tx_timeout = prism2_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
@@ -842,7 +842,7 @@ static const struct net_device_ops hostap_master_ops = {
.ndo_stop = prism2_close,
.ndo_do_ioctl = hostap_ioctl,
.ndo_set_mac_address = prism2_set_mac_address,
- .ndo_set_multicast_list = hostap_set_multicast_list,
+ .ndo_set_rx_mode = hostap_set_multicast_list,
.ndo_change_mtu = prism2_change_mtu,
.ndo_tx_timeout = prism2_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index ef9ad79d1bfd..127e9c63beaf 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -161,7 +161,7 @@ that only one external action is invoked at a time.
#include <linux/firmware.h>
#include <linux/acpi.h>
#include <linux/ctype.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
#include <net/lib80211.h>
@@ -174,7 +174,7 @@ that only one external action is invoked at a time.
#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
-static struct pm_qos_request_list ipw2100_pm_qos_req;
+static struct pm_qos_request ipw2100_pm_qos_req;
/* Debugging stuff */
#ifdef CONFIG_IPW2100_DEBUG
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 4ffebede5e03..99a710dfe771 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -32,6 +32,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
+#include <net/cfg80211-wext.h>
#include "ipw2200.h"
@@ -11704,7 +11705,7 @@ static const struct net_device_ops ipw_netdev_ops = {
.ndo_init = ipw_net_init,
.ndo_open = ipw_net_open,
.ndo_stop = ipw_net_stop,
- .ndo_set_multicast_list = ipw_net_set_multicast_list,
+ .ndo_set_rx_mode = ipw_net_set_multicast_list,
.ndo_set_mac_address = ipw_net_set_mac_address,
.ndo_start_xmit = libipw_xmit,
.ndo_change_mtu = libipw_change_mtu,
diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c
index 01c88a71abe1..e8c039879b05 100644
--- a/drivers/net/wireless/ipw2x00/libipw_tx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_tx.c
@@ -395,7 +395,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
(CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
bytes_per_frag -= LIBIPW_FCS_LEN;
- /* Each fragment may need to have room for encryptiong
+ /* Each fragment may need to have room for encryption
* pre/postfix */
if (host_encrypt)
bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-led.c b/drivers/net/wireless/iwlegacy/iwl-3945-led.c
index abd923558d48..7a7f0f38c8ab 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945-led.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-led.c
@@ -32,7 +32,6 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-rs.c b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
index 164bcae821f8..8faeaf2dddec 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
@@ -28,7 +28,6 @@
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
index 73fe3cdf796b..f7c0a7438476 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.c
@@ -34,7 +34,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-led.c b/drivers/net/wireless/iwlegacy/iwl-4965-led.c
index 26d324e30692..6862fdcaee62 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-led.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-led.c
@@ -32,7 +32,6 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
index 9b65153bdd01..57ebe214e68c 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
@@ -27,7 +27,6 @@
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
index ac4f64de1363..7f12e3638bae 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
@@ -335,7 +335,7 @@ int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
sta_priv = (void *)sta->drv_priv;
if (sta_priv && sta_priv->asleep &&
- (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) {
+ (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) {
/*
* This sends an asynchronous command to the device,
* but we can rely on it being processed before the
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
index ecdc6e557428..86f4fce193e4 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
@@ -33,7 +33,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
index e5971fe9d169..2bd5659310d7 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.c
+++ b/drivers/net/wireless/iwlegacy/iwl-core.c
@@ -1250,7 +1250,8 @@ void iwl_legacy_clear_isr_stats(struct iwl_priv *priv)
memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
}
-int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct iwl_priv *priv = hw->priv;
@@ -2220,7 +2221,8 @@ out:
}
EXPORT_SYMBOL(iwl_legacy_mac_config);
-void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h
index 84da79376ef8..d1271fe07d4b 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.h
+++ b/drivers/net/wireless/iwlegacy/iwl-core.h
@@ -286,7 +286,8 @@ struct iwl_cfg {
***************************/
struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg);
-int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params);
int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw);
void iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv,
@@ -620,7 +621,8 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
/* mac80211 handlers */
int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
-void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
diff --git a/drivers/net/wireless/iwlegacy/iwl-led.c b/drivers/net/wireless/iwlegacy/iwl-led.c
index bda0d61b2c0d..dc568a474c5d 100644
--- a/drivers/net/wireless/iwlegacy/iwl-led.c
+++ b/drivers/net/wireless/iwlegacy/iwl-led.c
@@ -33,7 +33,6 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
index 66ee15629a76..b282d869a546 100644
--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -40,7 +40,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c
index aa0c2539761e..d2fba9eae153 100644
--- a/drivers/net/wireless/iwlegacy/iwl4965-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c
@@ -40,7 +40,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index ad3bdba6beed..57703d5209d7 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -1,5 +1,5 @@
-config IWLAGN
- tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlagn) "
+config IWLWIFI
+ tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
depends on PCI && MAC80211
select FW_LOADER
select NEW_LEDS
@@ -39,14 +39,14 @@ config IWLAGN
If you want to compile the driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/kbuild/modules.txt>. The
- module will be called iwlagn.
+ module will be called iwlwifi.
menu "Debugging Options"
- depends on IWLAGN
+ depends on IWLWIFI
config IWLWIFI_DEBUG
- bool "Enable full debugging output in the iwlagn driver"
- depends on IWLAGN
+ bool "Enable full debugging output in the iwlwifi driver"
+ depends on IWLWIFI
---help---
This option will enable debug tracing output for the iwlwifi drivers
@@ -54,13 +54,13 @@ config IWLWIFI_DEBUG
control which debug output is sent to the kernel log by setting the
value in
- /sys/class/net/wlan0/device/debug_level
+ /sys/module/iwlwifi/parameters/debug
This entry will only exist if this option is enabled.
To set a value, simply echo an 8-byte hex value to the same file:
- % echo 0x43fff > /sys/class/net/wlan0/device/debug_level
+ % echo 0x43fff > /sys/module/iwlwifi/parameters/debug
You can find the list of debug mask values in:
drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -70,8 +70,8 @@ config IWLWIFI_DEBUG
any problems you may encounter.
config IWLWIFI_DEBUGFS
- bool "iwlagn debugfs support"
- depends on IWLAGN && MAC80211_DEBUGFS
+ bool "iwlwifi debugfs support"
+ depends on IWLWIFI && MAC80211_DEBUGFS
---help---
Enable creation of debugfs files for the iwlwifi drivers. This
is a low-impact option that allows getting insight into the
@@ -79,13 +79,13 @@ config IWLWIFI_DEBUGFS
config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
bool "Experimental uCode support"
- depends on IWLAGN && IWLWIFI_DEBUG
+ depends on IWLWIFI && IWLWIFI_DEBUG
---help---
Enable use of experimental ucode for testing and debugging.
config IWLWIFI_DEVICE_TRACING
bool "iwlwifi device access tracing"
- depends on IWLAGN
+ depends on IWLWIFI
depends on EVENT_TRACING
help
Say Y here to trace all commands, including TX frames and IO
@@ -104,27 +104,10 @@ endmenu
config IWLWIFI_DEVICE_SVTOOL
bool "iwlwifi device svtool support"
- depends on IWLAGN
+ depends on IWLWIFI
select NL80211_TESTMODE
help
This option enables the svtool support for iwlwifi device through
NL80211_TESTMODE. svtool is a software validation tool that runs in
the user space and interacts with the device in the kernel space
through the generic netlink message via NL80211_TESTMODE channel.
-
-config IWL_P2P
- bool "iwlwifi experimental P2P support"
- depends on IWLAGN
- help
- This option enables experimental P2P support for some devices
- based on microcode support. Since P2P support is still under
- development, this option may even enable it for some devices
- now that turn out to not support it in the future due to
- microcode restrictions.
-
- To determine if your microcode supports the experimental P2P
- offered by this option, check if the driver advertises AP
- support when it is loaded.
-
- Say Y only if you want to experiment with P2P.
-
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 48ab9142af38..c73e5ed8db5e 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -1,24 +1,24 @@
-# AGN
-obj-$(CONFIG_IWLAGN) += iwlagn.o
-iwlagn-objs := iwl-agn.o iwl-agn-rs.o
-iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o
-iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
-iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
+# WIFI
+obj-$(CONFIG_IWLWIFI) += iwlwifi.o
+iwlwifi-objs := iwl-agn.o iwl-agn-rs.o
+iwlwifi-objs += iwl-agn-ucode.o iwl-agn-tx.o
+iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
+iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o
-iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-power.o
-iwlagn-objs += iwl-rx.o iwl-sta.o
-iwlagn-objs += iwl-scan.o iwl-led.o
-iwlagn-objs += iwl-agn-rxon.o
-iwlagn-objs += iwl-5000.o
-iwlagn-objs += iwl-6000.o
-iwlagn-objs += iwl-1000.o
-iwlagn-objs += iwl-2000.o
-iwlagn-objs += iwl-pci.o
-iwlagn-objs += iwl-trans.o iwl-trans-rx-pcie.o iwl-trans-tx-pcie.o
+iwlwifi-objs += iwl-core.o iwl-eeprom.o iwl-power.o
+iwlwifi-objs += iwl-scan.o iwl-led.o
+iwlwifi-objs += iwl-agn-rxon.o
+iwlwifi-objs += iwl-5000.o
+iwlwifi-objs += iwl-6000.o
+iwlwifi-objs += iwl-1000.o
+iwlwifi-objs += iwl-2000.o
+iwlwifi-objs += iwl-pci.o
+iwlwifi-objs += iwl-trans.o
+iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
-iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
-iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
-iwlagn-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o
+iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
+iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
+iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o
CFLAGS_iwl-devtrace.o := -I$(src)
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 01b49eb8c8ec..e12b48c2cff6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -30,7 +30,6 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
@@ -40,14 +39,18 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
-#include "iwl-sta.h"
#include "iwl-agn.h"
-#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
+#include "iwl-shared.h"
+#include "iwl-cfg.h"
/* Highest firmware API version supported */
-#define IWL1000_UCODE_API_MAX 5
-#define IWL100_UCODE_API_MAX 5
+#define IWL1000_UCODE_API_MAX 6
+#define IWL100_UCODE_API_MAX 6
+
+/* Oldest version we won't warn about */
+#define IWL1000_UCODE_API_OK 5
+#define IWL100_UCODE_API_OK 5
/* Lowest firmware API version supported */
#define IWL1000_UCODE_API_MIN 1
@@ -73,21 +76,21 @@
static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
{
/* want Celsius */
- priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
- priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
+ hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
+ hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
}
/* NIC configuration for 1000 series */
static void iwl1000_nic_config(struct iwl_priv *priv)
{
/* set CSR_HW_CONFIG_REG for uCode use */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
/* Setting digital SVR for 1000 card to 1.32V */
/* locking is acquired in iwl_set_bits_mask_prph() function */
- iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG,
+ iwl_set_bits_mask_prph(bus(priv), APMG_DIGITAL_SVR_REG,
APMG_SVR_DIGITAL_VOLTAGE_1_32,
~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
}
@@ -124,44 +127,36 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->base_params->num_of_queues =
iwlagn_mod_params.num_of_queues;
- priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.scd_bc_tbls_size =
- priv->cfg->base_params->num_of_queues *
- sizeof(struct iwlagn_scd_bc_tbl);
- priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
- priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
+ hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
- priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
- priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
+ hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
+ hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE;
- priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
- BIT(IEEE80211_BAND_5GHZ);
+ hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
- priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
+ hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
if (priv->cfg->rx_with_siso_diversity)
- priv->hw_params.rx_chains_num = 1;
+ hw_params(priv).rx_chains_num = 1;
else
- priv->hw_params.rx_chains_num =
+ hw_params(priv).rx_chains_num =
num_of_ant(priv->cfg->valid_rx_ant);
- priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
- priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+ hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
+ hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
iwl1000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */
/* Set initial calibration set */
- priv->hw_params.sens = &iwl1000_sensitivity;
- priv->hw_params.calib_init_cfg =
+ hw_params(priv).sens = &iwl1000_sensitivity;
+ hw_params(priv).calib_init_cfg =
BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_TX_IQ_PERD) |
BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib)
- priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
-
- priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
+ hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC);
return 0;
}
@@ -191,7 +186,6 @@ static struct iwl_base_params iwl1000_base_params = {
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
.shadow_ram_support = false,
.led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
.chain_noise_scale = 1000,
@@ -201,12 +195,13 @@ static struct iwl_base_params iwl1000_base_params = {
static struct iwl_ht_params iwl1000_ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
- .smps_mode = IEEE80211_SMPS_STATIC,
+ .smps_mode = IEEE80211_SMPS_DYNAMIC,
};
#define IWL_DEVICE_1000 \
.fw_name_pre = IWL1000_FW_PRE, \
.ucode_api_max = IWL1000_UCODE_API_MAX, \
+ .ucode_api_ok = IWL1000_UCODE_API_OK, \
.ucode_api_min = IWL1000_UCODE_API_MIN, \
.eeprom_ver = EEPROM_1000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
@@ -228,6 +223,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
#define IWL_DEVICE_100 \
.fw_name_pre = IWL100_FW_PRE, \
.ucode_api_max = IWL100_UCODE_API_MAX, \
+ .ucode_api_ok = IWL100_UCODE_API_OK, \
.ucode_api_min = IWL100_UCODE_API_MIN, \
.eeprom_ver = EEPROM_1000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index 0e13f0bb2e17..79431977a968 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -30,7 +30,6 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
@@ -40,17 +39,22 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
-#include "iwl-sta.h"
#include "iwl-agn.h"
-#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
-#include "iwl-6000-hw.h"
+#include "iwl-shared.h"
+#include "iwl-cfg.h"
/* Highest firmware API version supported */
-#define IWL2030_UCODE_API_MAX 5
-#define IWL2000_UCODE_API_MAX 5
-#define IWL105_UCODE_API_MAX 5
-#define IWL135_UCODE_API_MAX 5
+#define IWL2030_UCODE_API_MAX 6
+#define IWL2000_UCODE_API_MAX 6
+#define IWL105_UCODE_API_MAX 6
+#define IWL135_UCODE_API_MAX 6
+
+/* Oldest version we won't warn about */
+#define IWL2030_UCODE_API_OK 5
+#define IWL2000_UCODE_API_OK 5
+#define IWL105_UCODE_API_OK 5
+#define IWL135_UCODE_API_OK 5
/* Lowest firmware API version supported */
#define IWL2030_UCODE_API_MIN 5
@@ -68,13 +72,13 @@
#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode"
#define IWL135_FW_PRE "iwlwifi-135-"
-#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE #api ".ucode"
+#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE __stringify(api) ".ucode"
static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
{
/* want Celsius */
- priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
- priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
+ hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD;
+ hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
}
/* NIC configuration for 2000 series */
@@ -83,7 +87,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
iwl_rf_config(priv);
if (priv->cfg->iq_invert)
- iwl_set_bit(priv, CSR_GP_DRIVER_REG,
+ iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
}
@@ -119,45 +123,37 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->base_params->num_of_queues =
iwlagn_mod_params.num_of_queues;
- priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.scd_bc_tbls_size =
- priv->cfg->base_params->num_of_queues *
- sizeof(struct iwlagn_scd_bc_tbl);
- priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
- priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
+ hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
- priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
- priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
+ hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
+ hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE;
- priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
- BIT(IEEE80211_BAND_5GHZ);
+ hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
- priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
+ hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
if (priv->cfg->rx_with_siso_diversity)
- priv->hw_params.rx_chains_num = 1;
+ hw_params(priv).rx_chains_num = 1;
else
- priv->hw_params.rx_chains_num =
+ hw_params(priv).rx_chains_num =
num_of_ant(priv->cfg->valid_rx_ant);
- priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
- priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+ hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
+ hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
iwl2000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */
/* Set initial calibration set */
- priv->hw_params.sens = &iwl2000_sensitivity;
- priv->hw_params.calib_init_cfg =
+ hw_params(priv).sens = &iwl2000_sensitivity;
+ hw_params(priv).calib_init_cfg =
BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib)
- priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX;
+ hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX;
if (priv->cfg->need_temp_offset_calib)
- priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
-
- priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
+ hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
return 0;
}
@@ -175,7 +171,7 @@ static struct iwl_lib_ops iwl2000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40,
},
- .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+ .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
},
.temperature = iwlagn_temperature,
};
@@ -196,7 +192,7 @@ static struct iwl_lib_ops iwl2030_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40,
},
- .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+ .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
},
.temperature = iwlagn_temperature,
};
@@ -209,7 +205,6 @@ static struct iwl_base_params iwl2000_base_params = {
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
.shadow_ram_support = true,
.led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -217,6 +212,7 @@ static struct iwl_base_params iwl2000_base_params = {
.wd_timeout = IWL_DEF_WD_TIMEOUT,
.max_event_log_size = 512,
.shadow_reg_enable = true,
+ .hd_v2 = true,
};
@@ -228,7 +224,6 @@ static struct iwl_base_params iwl2030_base_params = {
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
.shadow_ram_support = true,
.led_compensation = 57,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -236,6 +231,7 @@ static struct iwl_base_params iwl2030_base_params = {
.wd_timeout = IWL_LONG_WD_TIMEOUT,
.max_event_log_size = 512,
.shadow_reg_enable = true,
+ .hd_v2 = true,
};
static struct iwl_ht_params iwl2000_ht_params = {
@@ -256,6 +252,7 @@ static struct iwl_bt_params iwl2030_bt_params = {
#define IWL_DEVICE_2000 \
.fw_name_pre = IWL2000_FW_PRE, \
.ucode_api_max = IWL2000_UCODE_API_MAX, \
+ .ucode_api_ok = IWL2000_UCODE_API_OK, \
.ucode_api_min = IWL2000_UCODE_API_MIN, \
.eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
@@ -263,6 +260,7 @@ static struct iwl_bt_params iwl2030_bt_params = {
.base_params = &iwl2000_base_params, \
.need_dc_calib = true, \
.need_temp_offset_calib = true, \
+ .temp_offset_v2 = true, \
.led_mode = IWL_LED_RF_STATE, \
.iq_invert = true \
@@ -277,9 +275,16 @@ struct iwl_cfg iwl2000_2bg_cfg = {
IWL_DEVICE_2000,
};
+struct iwl_cfg iwl2000_2bgn_d_cfg = {
+ .name = "2000D Series 2x2 BGN",
+ IWL_DEVICE_2000,
+ .ht_params = &iwl2000_ht_params,
+};
+
#define IWL_DEVICE_2030 \
.fw_name_pre = IWL2030_FW_PRE, \
.ucode_api_max = IWL2030_UCODE_API_MAX, \
+ .ucode_api_ok = IWL2030_UCODE_API_OK, \
.ucode_api_min = IWL2030_UCODE_API_MIN, \
.eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
@@ -288,6 +293,7 @@ struct iwl_cfg iwl2000_2bg_cfg = {
.bt_params = &iwl2030_bt_params, \
.need_dc_calib = true, \
.need_temp_offset_calib = true, \
+ .temp_offset_v2 = true, \
.led_mode = IWL_LED_RF_STATE, \
.adv_pm = true, \
.iq_invert = true \
@@ -306,6 +312,7 @@ struct iwl_cfg iwl2030_2bg_cfg = {
#define IWL_DEVICE_105 \
.fw_name_pre = IWL105_FW_PRE, \
.ucode_api_max = IWL105_UCODE_API_MAX, \
+ .ucode_api_ok = IWL105_UCODE_API_OK, \
.ucode_api_min = IWL105_UCODE_API_MIN, \
.eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
@@ -313,6 +320,7 @@ struct iwl_cfg iwl2030_2bg_cfg = {
.base_params = &iwl2000_base_params, \
.need_dc_calib = true, \
.need_temp_offset_calib = true, \
+ .temp_offset_v2 = true, \
.led_mode = IWL_LED_RF_STATE, \
.adv_pm = true, \
.rx_with_siso_diversity = true, \
@@ -329,9 +337,16 @@ struct iwl_cfg iwl105_bgn_cfg = {
.ht_params = &iwl2000_ht_params,
};
+struct iwl_cfg iwl105_bgn_d_cfg = {
+ .name = "105D Series 1x1 BGN",
+ IWL_DEVICE_105,
+ .ht_params = &iwl2000_ht_params,
+};
+
#define IWL_DEVICE_135 \
.fw_name_pre = IWL135_FW_PRE, \
.ucode_api_max = IWL135_UCODE_API_MAX, \
+ .ucode_api_ok = IWL135_UCODE_API_OK, \
.ucode_api_min = IWL135_UCODE_API_MIN, \
.eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
@@ -340,6 +355,7 @@ struct iwl_cfg iwl105_bgn_cfg = {
.bt_params = &iwl2030_bt_params, \
.need_dc_calib = true, \
.need_temp_offset_calib = true, \
+ .temp_offset_v2 = true, \
.led_mode = IWL_LED_RF_STATE, \
.adv_pm = true, \
.rx_with_siso_diversity = true, \
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
deleted file mode 100644
index f9630a3c79fe..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- * Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-5000-hw.h) only for hardware-related definitions.
- * Use iwl-commands.h for uCode API definitions.
- */
-
-#ifndef __iwl_5000_hw_h__
-#define __iwl_5000_hw_h__
-
-/* 5150 only */
-#define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5)
-
-static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
-{
- u16 temperature, voltage;
- __le16 *temp_calib =
- (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
-
- temperature = le16_to_cpu(temp_calib[0]);
- voltage = le16_to_cpu(temp_calib[1]);
-
- /* offset = temp - volt / coeff */
- return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF);
-}
-
-#endif /* __iwl_5000_hw_h__ */
-
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index c95cefd529dc..c511c98a89a8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -31,7 +31,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
@@ -41,12 +40,11 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
-#include "iwl-sta.h"
-#include "iwl-helpers.h"
#include "iwl-agn.h"
#include "iwl-agn-hw.h"
-#include "iwl-5000-hw.h"
#include "iwl-trans.h"
+#include "iwl-shared.h"
+#include "iwl-cfg.h"
/* Highest firmware API version supported */
#define IWL5000_UCODE_API_MAX 5
@@ -69,27 +67,27 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
iwl_rf_config(priv);
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->shrd->lock, flags);
/* W/A : NIC is stuck in a reset state after Early PCIe power off
* (PCIe power is lost before PERST# is asserted),
* causing ME FW to lose ownership and not being able to obtain it back.
*/
- iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+ iwl_set_bits_mask_prph(bus(priv), APMG_PS_CTRL_REG,
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
}
static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
- .min_nrg_cck = 95,
+ .min_nrg_cck = 100,
.max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 90,
.auto_corr_min_ofdm_mrc = 170,
- .auto_corr_min_ofdm_x1 = 120,
- .auto_corr_min_ofdm_mrc_x1 = 240,
+ .auto_corr_min_ofdm_x1 = 105,
+ .auto_corr_min_ofdm_mrc_x1 = 220,
.auto_corr_max_ofdm = 120,
.auto_corr_max_ofdm_mrc = 210,
@@ -98,10 +96,10 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
.auto_corr_min_cck = 125,
.auto_corr_max_cck = 200,
- .auto_corr_min_cck_mrc = 170,
+ .auto_corr_min_cck_mrc = 200,
.auto_corr_max_cck_mrc = 400,
- .nrg_th_cck = 95,
- .nrg_th_ofdm = 95,
+ .nrg_th_cck = 100,
+ .nrg_th_ofdm = 100,
.barker_corr_th_min = 190,
.barker_corr_th_min_mrc = 390,
@@ -134,19 +132,34 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
.nrg_th_cca = 62,
};
+#define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5)
+
+static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
+{
+ u16 temperature, voltage;
+ __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv,
+ EEPROM_KELVIN_TEMPERATURE);
+
+ temperature = le16_to_cpu(temp_calib[0]);
+ voltage = le16_to_cpu(temp_calib[1]);
+
+ /* offset = temp - volt / coeff */
+ return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF);
+}
+
static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
{
const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) -
iwl_temp_calib_to_offset(priv);
- priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef;
+ hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef;
}
static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
{
/* want Celsius */
- priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
+ hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
}
static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
@@ -156,39 +169,32 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->base_params->num_of_queues =
iwlagn_mod_params.num_of_queues;
- priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.scd_bc_tbls_size =
- priv->cfg->base_params->num_of_queues *
- sizeof(struct iwlagn_scd_bc_tbl);
- priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
- priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
+ hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
- priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
- priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
+ hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
+ hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE;
- priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
+ hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
- priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
- priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
- priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+ hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
+ hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
+ hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
+ hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
iwl5000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */
/* Set initial calibration set */
- priv->hw_params.sens = &iwl5000_sensitivity;
- priv->hw_params.calib_init_cfg =
+ hw_params(priv).sens = &iwl5000_sensitivity;
+ hw_params(priv).calib_init_cfg =
BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_TX_IQ_PERD) |
BIT(IWL_CALIB_BASE_BAND);
- priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
-
return 0;
}
@@ -199,38 +205,31 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->base_params->num_of_queues =
iwlagn_mod_params.num_of_queues;
- priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.scd_bc_tbls_size =
- priv->cfg->base_params->num_of_queues *
- sizeof(struct iwlagn_scd_bc_tbl);
- priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
- priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
+ hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
- priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
- priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
+ hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
+ hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE;
- priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
+ hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
- priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
- priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
- priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+ hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
+ hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
+ hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
+ hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
iwl5150_set_ct_threshold(priv);
/* Set initial sensitivity parameters */
/* Set initial calibration set */
- priv->hw_params.sens = &iwl5150_sensitivity;
- priv->hw_params.calib_init_cfg =
+ hw_params(priv).sens = &iwl5150_sensitivity;
+ hw_params(priv).calib_init_cfg =
BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib)
- priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
-
- priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
+ hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC);
return 0;
}
@@ -252,7 +251,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
{
/*
* MULTI-FIXME
- * See iwl_mac_channel_switch.
+ * See iwlagn_mac_channel_switch.
*/
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl5000_channel_switch_cmd cmd;
@@ -315,7 +314,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT;
}
- return trans_send_cmd(&priv->trans, &hcmd);
+ return iwl_trans_send_cmd(trans(priv), &hcmd);
}
static struct iwl_lib_ops iwl5000_lib = {
@@ -360,7 +359,6 @@ static struct iwl_base_params iwl5000_base_params = {
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
.led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
.chain_noise_scale = 1000,
.wd_timeout = IWL_LONG_WD_TIMEOUT,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 973d1972e8cc..c840c78278db 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -30,7 +30,6 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
@@ -40,17 +39,19 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
-#include "iwl-sta.h"
#include "iwl-agn.h"
-#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
-#include "iwl-6000-hw.h"
#include "iwl-trans.h"
+#include "iwl-shared.h"
+#include "iwl-cfg.h"
/* Highest firmware API version supported */
#define IWL6000_UCODE_API_MAX 4
#define IWL6050_UCODE_API_MAX 5
-#define IWL6000G2_UCODE_API_MAX 5
+#define IWL6000G2_UCODE_API_MAX 6
+
+/* Oldest version we won't warn about */
+#define IWL6000G2_UCODE_API_OK 5
/* Lowest firmware API version supported */
#define IWL6000_UCODE_API_MIN 4
@@ -72,15 +73,15 @@
static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
{
/* want Celsius */
- priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
- priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
+ hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD;
+ hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
}
static void iwl6050_additional_nic_config(struct iwl_priv *priv)
{
/* Indicate calibration version to uCode. */
if (iwlagn_eeprom_calib_version(priv) >= 6)
- iwl_set_bit(priv, CSR_GP_DRIVER_REG,
+ iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
}
@@ -88,9 +89,9 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
{
/* Indicate calibration version to uCode. */
if (iwlagn_eeprom_calib_version(priv) >= 6)
- iwl_set_bit(priv, CSR_GP_DRIVER_REG,
+ iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
- iwl_set_bit(priv, CSR_GP_DRIVER_REG,
+ iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_6050_1x2);
}
@@ -102,7 +103,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
/* no locking required for register write */
if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
/* 2x2 IPA phy type */
- iwl_write32(priv, CSR_GP_DRIVER_REG,
+ iwl_write32(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
}
/* do additional nic configuration if needed */
@@ -111,7 +112,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
}
static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
- .min_nrg_cck = 97,
+ .min_nrg_cck = 110,
.max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 80,
.auto_corr_min_ofdm_mrc = 128,
@@ -127,11 +128,11 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
.auto_corr_max_cck = 175,
.auto_corr_min_cck_mrc = 160,
.auto_corr_max_cck_mrc = 310,
- .nrg_th_cck = 97,
- .nrg_th_ofdm = 100,
+ .nrg_th_cck = 110,
+ .nrg_th_ofdm = 110,
.barker_corr_th_min = 190,
- .barker_corr_th_min_mrc = 390,
+ .barker_corr_th_min_mrc = 336,
.nrg_th_cca = 62,
};
@@ -142,45 +143,38 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
priv->cfg->base_params->num_of_queues =
iwlagn_mod_params.num_of_queues;
- priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.scd_bc_tbls_size =
- priv->cfg->base_params->num_of_queues *
- sizeof(struct iwlagn_scd_bc_tbl);
- priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
- priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
+ hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
- priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
- priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
+ hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
+ hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE;
- priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
+ hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ);
- priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
+ hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
if (priv->cfg->rx_with_siso_diversity)
- priv->hw_params.rx_chains_num = 1;
+ hw_params(priv).rx_chains_num = 1;
else
- priv->hw_params.rx_chains_num =
+ hw_params(priv).rx_chains_num =
num_of_ant(priv->cfg->valid_rx_ant);
- priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
- priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+ hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
+ hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
iwl6000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */
/* Set initial calibration set */
- priv->hw_params.sens = &iwl6000_sensitivity;
- priv->hw_params.calib_init_cfg =
+ hw_params(priv).sens = &iwl6000_sensitivity;
+ hw_params(priv).calib_init_cfg =
BIT(IWL_CALIB_XTAL) |
BIT(IWL_CALIB_LO) |
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib)
- priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX;
+ hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX;
if (priv->cfg->need_temp_offset_calib)
- priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
-
- priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
+ hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
return 0;
}
@@ -190,7 +184,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
{
/*
* MULTI-FIXME
- * See iwl_mac_channel_switch.
+ * See iwlagn_mac_channel_switch.
*/
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl6000_channel_switch_cmd cmd;
@@ -253,7 +247,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT;
}
- return trans_send_cmd(&priv->trans, &hcmd);
+ return iwl_trans_send_cmd(trans(priv), &hcmd);
}
static struct iwl_lib_ops iwl6000_lib = {
@@ -270,7 +264,7 @@ static struct iwl_lib_ops iwl6000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+ .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
},
.temperature = iwlagn_temperature,
};
@@ -292,7 +286,7 @@ static struct iwl_lib_ops iwl6030_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+ .update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
},
.temperature = iwlagn_temperature,
};
@@ -305,7 +299,6 @@ static struct iwl_base_params iwl6000_base_params = {
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
.shadow_ram_support = true,
.led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -323,7 +316,6 @@ static struct iwl_base_params iwl6050_base_params = {
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
.shadow_ram_support = true,
.led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -340,7 +332,6 @@ static struct iwl_base_params iwl6000_g2_base_params = {
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
.shadow_ram_support = true,
.led_compensation = 57,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -365,8 +356,9 @@ static struct iwl_bt_params iwl6000_bt_params = {
};
#define IWL_DEVICE_6005 \
- .fw_name_pre = IWL6005_FW_PRE, \
+ .fw_name_pre = IWL6005_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
+ .ucode_api_ok = IWL6000G2_UCODE_API_OK, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.eeprom_ver = EEPROM_6005_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \
@@ -392,9 +384,22 @@ struct iwl_cfg iwl6005_2bg_cfg = {
IWL_DEVICE_6005,
};
+struct iwl_cfg iwl6005_2agn_sff_cfg = {
+ .name = "Intel(R) Centrino(R) Advanced-N 6205S AGN",
+ IWL_DEVICE_6005,
+ .ht_params = &iwl6000_ht_params,
+};
+
+struct iwl_cfg iwl6005_2agn_d_cfg = {
+ .name = "Intel(R) Centrino(R) Advanced-N 6205D AGN",
+ IWL_DEVICE_6005,
+ .ht_params = &iwl6000_ht_params,
+};
+
#define IWL_DEVICE_6030 \
- .fw_name_pre = IWL6030_FW_PRE, \
+ .fw_name_pre = IWL6030_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
+ .ucode_api_ok = IWL6000G2_UCODE_API_OK, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.eeprom_ver = EEPROM_6030_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index 72d6297602b8..03bac48558b2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -93,12 +93,12 @@ int iwl_send_calib_results(struct iwl_priv *priv)
};
for (i = 0; i < IWL_CALIB_MAX; i++) {
- if ((BIT(i) & priv->hw_params.calib_init_cfg) &&
+ if ((BIT(i) & hw_params(priv).calib_init_cfg) &&
priv->calib_results[i].buf) {
hcmd.len[0] = priv->calib_results[i].buf_len;
hcmd.data[0] = priv->calib_results[i].buf;
hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
- ret = trans_send_cmd(&priv->trans, &hcmd);
+ ret = iwl_trans_send_cmd(trans(priv), &hcmd);
if (ret) {
IWL_ERR(priv, "Error %d iteration %d\n",
ret, i);
@@ -174,7 +174,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv,
u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
struct iwl_sensitivity_data *data = NULL;
- const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+ const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens;
data = &(priv->sensitivity_data);
@@ -357,7 +357,7 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv,
u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
struct iwl_sensitivity_data *data = NULL;
- const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+ const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens;
data = &(priv->sensitivity_data);
@@ -484,7 +484,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
sizeof(u16)*HD_TABLE_SIZE);
- return trans_send_cmd(&priv->trans, &cmd_out);
+ return iwl_trans_send_cmd(trans(priv), &cmd_out);
}
/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
@@ -505,28 +505,53 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]);
- cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] =
- HD_INA_NON_SQUARE_DET_OFDM_DATA;
- cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] =
- HD_INA_NON_SQUARE_DET_CCK_DATA;
- cmd.enhance_table[HD_CORR_11_INSTEAD_OF_CORR_9_EN_INDEX] =
- HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA;
- cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
- HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA;
- cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
- HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA;
- cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_INDEX] =
- HD_OFDM_NON_SQUARE_DET_SLOPE_DATA;
- cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_INDEX] =
- HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA;
- cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
- HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA;
- cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
- HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA;
- cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_INDEX] =
- HD_CCK_NON_SQUARE_DET_SLOPE_DATA;
- cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_INDEX] =
- HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA;
+ if (priv->cfg->base_params->hd_v2) {
+ cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] =
+ HD_INA_NON_SQUARE_DET_OFDM_DATA_V2;
+ cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] =
+ HD_INA_NON_SQUARE_DET_CCK_DATA_V2;
+ cmd.enhance_table[HD_CORR_11_INSTEAD_OF_CORR_9_EN_INDEX] =
+ HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA_V2;
+ cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
+ HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA_V2;
+ cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
+ HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V2;
+ cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_INDEX] =
+ HD_OFDM_NON_SQUARE_DET_SLOPE_DATA_V2;
+ cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_INDEX] =
+ HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA_V2;
+ cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
+ HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA_V2;
+ cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
+ HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V2;
+ cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_INDEX] =
+ HD_CCK_NON_SQUARE_DET_SLOPE_DATA_V2;
+ cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_INDEX] =
+ HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA_V2;
+ } else {
+ cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] =
+ HD_INA_NON_SQUARE_DET_OFDM_DATA_V1;
+ cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] =
+ HD_INA_NON_SQUARE_DET_CCK_DATA_V1;
+ cmd.enhance_table[HD_CORR_11_INSTEAD_OF_CORR_9_EN_INDEX] =
+ HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA_V1;
+ cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
+ HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA_V1;
+ cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
+ HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V1;
+ cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_INDEX] =
+ HD_OFDM_NON_SQUARE_DET_SLOPE_DATA_V1;
+ cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_INDEX] =
+ HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA_V1;
+ cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
+ HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA_V1;
+ cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
+ HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V1;
+ cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_INDEX] =
+ HD_CCK_NON_SQUARE_DET_SLOPE_DATA_V1;
+ cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_INDEX] =
+ HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA_V1;
+ }
/* Update uCode's "work" table, and copy it to DSP */
cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
@@ -548,7 +573,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
&(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]),
sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES);
- return trans_send_cmd(&priv->trans, &cmd_out);
+ return iwl_trans_send_cmd(trans(priv), &cmd_out);
}
void iwl_init_sensitivity(struct iwl_priv *priv)
@@ -556,7 +581,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
int ret = 0;
int i;
struct iwl_sensitivity_data *data = NULL;
- const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+ const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens;
if (priv->disable_sens_cal)
return;
@@ -633,13 +658,13 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
return;
}
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->shrd->lock, flags);
rx_info = &priv->statistics.rx_non_phy;
ofdm = &priv->statistics.rx_ofdm;
cck = &priv->statistics.rx_cck;
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
return;
}
@@ -663,7 +688,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
statis.beacon_energy_c =
le32_to_cpu(rx_info->beacon_energy_c);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
@@ -741,12 +766,9 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
u8 first_chain;
u16 i = 0;
- average_sig[0] = data->chain_signal_a /
- priv->cfg->base_params->chain_noise_num_beacons;
- average_sig[1] = data->chain_signal_b /
- priv->cfg->base_params->chain_noise_num_beacons;
- average_sig[2] = data->chain_signal_c /
- priv->cfg->base_params->chain_noise_num_beacons;
+ average_sig[0] = data->chain_signal_a / IWL_CAL_NUM_BEACONS;
+ average_sig[1] = data->chain_signal_b / IWL_CAL_NUM_BEACONS;
+ average_sig[2] = data->chain_signal_c / IWL_CAL_NUM_BEACONS;
if (average_sig[0] >= average_sig[1]) {
max_average_sig = average_sig[0];
@@ -796,21 +818,21 @@ 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->hw_params.valid_rx_ant;
+ active_chains &= hw_params(priv).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->hw_params.valid_tx_ant & ant_msk))
+ if (!(hw_params(priv).valid_tx_ant & ant_msk))
continue;
num_tx_chains++;
if (data->disconn_array[i] == 0)
/* there is a Tx antenna connected */
break;
- if (num_tx_chains == priv->hw_params.tx_chains_num &&
+ if (num_tx_chains == hw_params(priv).tx_chains_num &&
data->disconn_array[i]) {
/*
* If all chains are disconnected
@@ -827,12 +849,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
}
}
- if (active_chains != priv->hw_params.valid_rx_ant &&
+ if (active_chains != hw_params(priv).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->hw_params.valid_rx_ant);
+ active_chains,
+ hw_params(priv).valid_rx_ant);
/* Save for use within RXON, TX, SCAN commands, etc. */
data->active_chains = active_chains;
@@ -892,7 +915,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
priv->phy_calib_chain_noise_gain_cmd);
cmd.delta_gain_1 = data->delta_gain_code[1];
cmd.delta_gain_2 = data->delta_gain_code[2];
- trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD,
+ iwl_trans_send_cmd_pdu(trans(priv), REPLY_PHY_CALIBRATION_CMD,
CMD_ASYNC, sizeof(cmd), &cmd);
data->radio_write = 1;
@@ -950,13 +973,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
return;
}
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->shrd->lock, flags);
rx_info = &priv->statistics.rx_non_phy;
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
return;
}
@@ -971,7 +994,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
rxon_chnum, rxon_band24);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
return;
}
@@ -990,7 +1013,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
data->beacon_count++;
@@ -1012,8 +1035,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
/* If this is the "chain_noise_num_beacons", determine:
* 1) Disconnected antennas (using signal strengths)
* 2) Differential gain (using silence noise) to balance receivers */
- if (data->beacon_count !=
- priv->cfg->base_params->chain_noise_num_beacons)
+ if (data->beacon_count != IWL_CAL_NUM_BEACONS)
return;
/* Analyze signal for disconnected antenna */
@@ -1021,7 +1043,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->hw_params.valid_rx_ant;
+ data->active_chains = hw_params(priv).valid_rx_ant;
for (i = 0; i < NUM_RX_CHAINS; i++)
if (!(data->active_chains & (1<<i)))
data->disconn_array[i] = 1;
@@ -1029,12 +1051,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
iwl_find_disconn_antenna(priv, average_sig, data);
/* Analyze noise for rx balance */
- average_noise[0] = data->chain_noise_a /
- priv->cfg->base_params->chain_noise_num_beacons;
- average_noise[1] = data->chain_noise_b /
- priv->cfg->base_params->chain_noise_num_beacons;
- average_noise[2] = data->chain_noise_c /
- priv->cfg->base_params->chain_noise_num_beacons;
+ average_noise[0] = data->chain_noise_a / IWL_CAL_NUM_BEACONS;
+ average_noise[1] = data->chain_noise_b / IWL_CAL_NUM_BEACONS;
+ average_noise[2] = data->chain_noise_c / IWL_CAL_NUM_BEACONS;
for (i = 0; i < NUM_RX_CHAINS; i++) {
if (!(data->disconn_array[i]) &&
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
deleted file mode 100644
index b8347db850e7..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- * Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include <net/mac80211.h>
-
-#include "iwl-commands.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-debug.h"
-#include "iwl-agn.h"
-#include "iwl-io.h"
-
-/******************************************************************************
- *
- * EEPROM related functions
- *
-******************************************************************************/
-
-int iwl_eeprom_check_version(struct iwl_priv *priv)
-{
- u16 eeprom_ver;
- u16 calib_ver;
-
- eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
- calib_ver = iwlagn_eeprom_calib_version(priv);
-
- if (eeprom_ver < priv->cfg->eeprom_ver ||
- calib_ver < priv->cfg->eeprom_calib_ver)
- goto err;
-
- IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
- eeprom_ver, calib_ver);
-
- return 0;
-err:
- IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
- "CALIB=0x%x < 0x%x\n",
- eeprom_ver, priv->cfg->eeprom_ver,
- calib_ver, priv->cfg->eeprom_calib_ver);
- return -EINVAL;
-
-}
-
-int iwl_eeprom_check_sku(struct iwl_priv *priv)
-{
- u16 radio_cfg;
-
- if (!priv->cfg->sku) {
- /* not using sku overwrite */
- priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
- if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
- !priv->cfg->ht_params) {
- IWL_ERR(priv, "Invalid 11n configuration\n");
- return -EINVAL;
- }
- }
- if (!priv->cfg->sku) {
- IWL_ERR(priv, "Invalid device sku\n");
- return -EINVAL;
- }
-
- IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku);
-
- if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
- /* not using .cfg overwrite */
- radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
- priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
- priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
- if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
- IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n",
- priv->cfg->valid_tx_ant,
- priv->cfg->valid_rx_ant);
- return -EINVAL;
- }
- IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n",
- priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant);
- }
- /*
- * for some special cases,
- * EEPROM did not reflect the correct antenna setting
- * so overwrite the valid tx/rx antenna from .cfg
- */
- return 0;
-}
-
-void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
-{
- const u8 *addr = iwl_eeprom_query_addr(priv,
- EEPROM_MAC_ADDRESS);
- memcpy(mac, addr, ETH_ALEN);
-}
-
-/**
- * iwl_get_max_txpower_avg - get the highest tx power from all chains.
- * find the highest tx power from all chains for the channel
- */
-static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
- struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
- int element, s8 *max_txpower_in_half_dbm)
-{
- s8 max_txpower_avg = 0; /* (dBm) */
-
- /* Take the highest tx power from any valid chains */
- if ((priv->cfg->valid_tx_ant & ANT_A) &&
- (enhanced_txpower[element].chain_a_max > max_txpower_avg))
- max_txpower_avg = enhanced_txpower[element].chain_a_max;
- if ((priv->cfg->valid_tx_ant & ANT_B) &&
- (enhanced_txpower[element].chain_b_max > max_txpower_avg))
- max_txpower_avg = enhanced_txpower[element].chain_b_max;
- if ((priv->cfg->valid_tx_ant & ANT_C) &&
- (enhanced_txpower[element].chain_c_max > max_txpower_avg))
- max_txpower_avg = enhanced_txpower[element].chain_c_max;
- if (((priv->cfg->valid_tx_ant == ANT_AB) |
- (priv->cfg->valid_tx_ant == ANT_BC) |
- (priv->cfg->valid_tx_ant == ANT_AC)) &&
- (enhanced_txpower[element].mimo2_max > max_txpower_avg))
- max_txpower_avg = enhanced_txpower[element].mimo2_max;
- if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
- (enhanced_txpower[element].mimo3_max > max_txpower_avg))
- max_txpower_avg = enhanced_txpower[element].mimo3_max;
-
- /*
- * max. tx power in EEPROM is in 1/2 dBm format
- * convert from 1/2 dBm to dBm (round-up convert)
- * but we also do not want to loss 1/2 dBm resolution which
- * will impact performance
- */
- *max_txpower_in_half_dbm = max_txpower_avg;
- return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
-}
-
-static void
-iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv,
- struct iwl_eeprom_enhanced_txpwr *txp,
- s8 max_txpower_avg)
-{
- int ch_idx;
- bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ;
- enum ieee80211_band band;
-
- band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ?
- IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
-
- for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) {
- struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx];
-
- /* update matching channel or from common data only */
- if (txp->channel != 0 && ch_info->channel != txp->channel)
- continue;
-
- /* update matching band only */
- if (band != ch_info->band)
- continue;
-
- if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) {
- ch_info->max_power_avg = max_txpower_avg;
- ch_info->curr_txpow = max_txpower_avg;
- ch_info->scan_power = max_txpower_avg;
- }
-
- if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg)
- ch_info->ht40_max_power_avg = max_txpower_avg;
- }
-}
-
-#define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT)
-#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
-#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
-
-#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
- ? # x " " : "")
-
-void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
-{
- struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
- int idx, entries;
- __le16 *txp_len;
- s8 max_txp_avg, max_txp_avg_halfdbm;
-
- BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
-
- /* the length is in 16-bit words, but we want entries */
- txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
- entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
-
- txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
-
- for (idx = 0; idx < entries; idx++) {
- txp = &txp_array[idx];
- /* skip invalid entries */
- if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
- continue;
-
- IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n",
- (txp->channel && (txp->flags &
- IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ?
- "Common " : (txp->channel) ?
- "Channel" : "Common",
- (txp->channel),
- TXP_CHECK_AND_PRINT(VALID),
- TXP_CHECK_AND_PRINT(BAND_52G),
- TXP_CHECK_AND_PRINT(OFDM),
- TXP_CHECK_AND_PRINT(40MHZ),
- TXP_CHECK_AND_PRINT(HT_AP),
- TXP_CHECK_AND_PRINT(RES1),
- TXP_CHECK_AND_PRINT(RES2),
- TXP_CHECK_AND_PRINT(COMMON_TYPE),
- txp->flags);
- IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x "
- "chain_B: 0X%02x chain_C: 0X%02x\n",
- txp->chain_a_max, txp->chain_b_max,
- txp->chain_c_max);
- IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x "
- "MIMO3: 0x%02x High 20_on_40: 0x%02x "
- "Low 20_on_40: 0x%02x\n",
- txp->mimo2_max, txp->mimo3_max,
- ((txp->delta_20_in_40 & 0xf0) >> 4),
- (txp->delta_20_in_40 & 0x0f));
-
- max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
- &max_txp_avg_halfdbm);
-
- /*
- * Update the user limit values values to the highest
- * power supported by any channel
- */
- if (max_txp_avg > priv->tx_power_user_lmt)
- priv->tx_power_user_lmt = max_txp_avg;
- if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm)
- priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm;
-
- iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
- }
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
index 0e5b842529c4..123ef5e129d5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
@@ -78,10 +78,23 @@
#define IWLAGN_RTC_DATA_SIZE (IWLAGN_RTC_DATA_UPPER_BOUND - \
IWLAGN_RTC_DATA_LOWER_BOUND)
+#define IWL60_RTC_INST_LOWER_BOUND (0x000000)
+#define IWL60_RTC_INST_UPPER_BOUND (0x040000)
+#define IWL60_RTC_DATA_LOWER_BOUND (0x800000)
+#define IWL60_RTC_DATA_UPPER_BOUND (0x814000)
+#define IWL60_RTC_INST_SIZE \
+ (IWL60_RTC_INST_UPPER_BOUND - IWL60_RTC_INST_LOWER_BOUND)
+#define IWL60_RTC_DATA_SIZE \
+ (IWL60_RTC_DATA_UPPER_BOUND - IWL60_RTC_DATA_LOWER_BOUND)
+
/* RSSI to dBm */
#define IWLAGN_RSSI_OFFSET 44
-#define IWLAGN_DEFAULT_TX_RETRY 15
+#define IWLAGN_DEFAULT_TX_RETRY 15
+#define IWLAGN_MGMT_DFAULT_RETRY_LIMIT 3
+#define IWLAGN_RTS_DFAULT_RETRY_LIMIT 60
+#define IWLAGN_BAR_DFAULT_RETRY_LIMIT 60
+#define IWLAGN_LOW_RETRY_LIMIT 7
/* Limit range of txpower output target to be between these values */
#define IWLAGN_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm: 1 milliwatt */
@@ -92,20 +105,7 @@
#define IWLAGN_CMD_FIFO_NUM 7
#define IWLAGN_NUM_QUEUES 20
-#define IWLAGN_NUM_AMPDU_QUEUES 10
-#define IWLAGN_FIRST_AMPDU_QUEUE 10
-
-/* Fixed (non-configurable) rx data from phy */
-
-/**
- * struct iwlagn_schedq_bc_tbl scheduler byte count table
- * base physical address provided by SCD_DRAM_BASE_ADDR
- * @tfd_offset 0-12 - tx command byte count
- * 12-16 - station index
- */
-struct iwlagn_scd_bc_tbl {
- __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
-} __packed;
-
+#define IWLAGN_NUM_AMPDU_QUEUES 9
+#define IWLAGN_FIRST_AMPDU_QUEUE 11
#endif /* __iwl_agn_hw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 3bee0f119bcd..1a52ed29f2d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -35,454 +35,10 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
-#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
#include "iwl-agn.h"
-#include "iwl-sta.h"
#include "iwl-trans.h"
-
-static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
-{
- return le32_to_cpup((__le32 *)&tx_resp->status +
- tx_resp->frame_count) & MAX_SN;
-}
-
-static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
-{
- status &= TX_STATUS_MSK;
-
- switch (status) {
- case TX_STATUS_POSTPONE_DELAY:
- priv->reply_tx_stats.pp_delay++;
- break;
- case TX_STATUS_POSTPONE_FEW_BYTES:
- priv->reply_tx_stats.pp_few_bytes++;
- break;
- case TX_STATUS_POSTPONE_BT_PRIO:
- priv->reply_tx_stats.pp_bt_prio++;
- break;
- case TX_STATUS_POSTPONE_QUIET_PERIOD:
- priv->reply_tx_stats.pp_quiet_period++;
- break;
- case TX_STATUS_POSTPONE_CALC_TTAK:
- priv->reply_tx_stats.pp_calc_ttak++;
- break;
- case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY:
- priv->reply_tx_stats.int_crossed_retry++;
- break;
- case TX_STATUS_FAIL_SHORT_LIMIT:
- priv->reply_tx_stats.short_limit++;
- break;
- case TX_STATUS_FAIL_LONG_LIMIT:
- priv->reply_tx_stats.long_limit++;
- break;
- case TX_STATUS_FAIL_FIFO_UNDERRUN:
- priv->reply_tx_stats.fifo_underrun++;
- break;
- case TX_STATUS_FAIL_DRAIN_FLOW:
- priv->reply_tx_stats.drain_flow++;
- break;
- case TX_STATUS_FAIL_RFKILL_FLUSH:
- priv->reply_tx_stats.rfkill_flush++;
- break;
- case TX_STATUS_FAIL_LIFE_EXPIRE:
- priv->reply_tx_stats.life_expire++;
- break;
- case TX_STATUS_FAIL_DEST_PS:
- priv->reply_tx_stats.dest_ps++;
- break;
- case TX_STATUS_FAIL_HOST_ABORTED:
- priv->reply_tx_stats.host_abort++;
- break;
- case TX_STATUS_FAIL_BT_RETRY:
- priv->reply_tx_stats.bt_retry++;
- break;
- case TX_STATUS_FAIL_STA_INVALID:
- priv->reply_tx_stats.sta_invalid++;
- break;
- case TX_STATUS_FAIL_FRAG_DROPPED:
- priv->reply_tx_stats.frag_drop++;
- break;
- case TX_STATUS_FAIL_TID_DISABLE:
- priv->reply_tx_stats.tid_disable++;
- break;
- case TX_STATUS_FAIL_FIFO_FLUSHED:
- priv->reply_tx_stats.fifo_flush++;
- break;
- case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL:
- priv->reply_tx_stats.insuff_cf_poll++;
- break;
- case TX_STATUS_FAIL_PASSIVE_NO_RX:
- priv->reply_tx_stats.fail_hw_drop++;
- break;
- case TX_STATUS_FAIL_NO_BEACON_ON_RADAR:
- priv->reply_tx_stats.sta_color_mismatch++;
- break;
- default:
- priv->reply_tx_stats.unknown++;
- break;
- }
-}
-
-static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
-{
- status &= AGG_TX_STATUS_MSK;
-
- switch (status) {
- case AGG_TX_STATE_UNDERRUN_MSK:
- priv->reply_agg_tx_stats.underrun++;
- break;
- case AGG_TX_STATE_BT_PRIO_MSK:
- priv->reply_agg_tx_stats.bt_prio++;
- break;
- case AGG_TX_STATE_FEW_BYTES_MSK:
- priv->reply_agg_tx_stats.few_bytes++;
- break;
- case AGG_TX_STATE_ABORT_MSK:
- priv->reply_agg_tx_stats.abort++;
- break;
- case AGG_TX_STATE_LAST_SENT_TTL_MSK:
- priv->reply_agg_tx_stats.last_sent_ttl++;
- break;
- case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK:
- priv->reply_agg_tx_stats.last_sent_try++;
- break;
- case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK:
- priv->reply_agg_tx_stats.last_sent_bt_kill++;
- break;
- case AGG_TX_STATE_SCD_QUERY_MSK:
- priv->reply_agg_tx_stats.scd_query++;
- break;
- case AGG_TX_STATE_TEST_BAD_CRC32_MSK:
- priv->reply_agg_tx_stats.bad_crc32++;
- break;
- case AGG_TX_STATE_RESPONSE_MSK:
- priv->reply_agg_tx_stats.response++;
- break;
- case AGG_TX_STATE_DUMP_TX_MSK:
- priv->reply_agg_tx_stats.dump_tx++;
- break;
- case AGG_TX_STATE_DELAY_TX_MSK:
- priv->reply_agg_tx_stats.delay_tx++;
- break;
- default:
- priv->reply_agg_tx_stats.unknown++;
- break;
- }
-}
-
-static void iwlagn_set_tx_status(struct iwl_priv *priv,
- struct ieee80211_tx_info *info,
- struct iwl_rxon_context *ctx,
- struct iwlagn_tx_resp *tx_resp,
- int txq_id, bool is_agg)
-{
- 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);
- if (!iwl_is_tx_success(status))
- iwlagn_count_tx_err_status(priv, status);
-
- if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
- iwl_is_associated_ctx(ctx) && ctx->vif &&
- ctx->vif->type == NL80211_IFTYPE_STATION) {
- ctx->last_tx_rejected = true;
- iwl_stop_queue(priv, &priv->txq[txq_id]);
- }
-
- IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags "
- "0x%x retries %d\n",
- txq_id,
- iwl_get_tx_fail_reason(status), status,
- le32_to_cpu(tx_resp->rate_n_flags),
- tx_resp->failure_frame);
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x
-
-const char *iwl_get_agg_tx_fail_reason(u16 status)
-{
- status &= AGG_TX_STATUS_MSK;
- switch (status) {
- case AGG_TX_STATE_TRANSMITTED:
- return "SUCCESS";
- AGG_TX_STATE_FAIL(UNDERRUN_MSK);
- AGG_TX_STATE_FAIL(BT_PRIO_MSK);
- AGG_TX_STATE_FAIL(FEW_BYTES_MSK);
- AGG_TX_STATE_FAIL(ABORT_MSK);
- AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK);
- AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK);
- AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK);
- AGG_TX_STATE_FAIL(SCD_QUERY_MSK);
- AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK);
- AGG_TX_STATE_FAIL(RESPONSE_MSK);
- AGG_TX_STATE_FAIL(DUMP_TX_MSK);
- AGG_TX_STATE_FAIL(DELAY_TX_MSK);
- }
-
- return "UNKNOWN";
-}
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
-static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
- struct iwl_ht_agg *agg,
- struct iwlagn_tx_resp *tx_resp,
- int txq_id, u16 start_idx)
-{
- u16 status;
- struct agg_tx_status *frame_status = &tx_resp->status;
- struct ieee80211_hdr *hdr = NULL;
- int i, sh, idx;
- u16 seq;
-
- if (agg->wait_for_ba)
- IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
-
- agg->frame_count = tx_resp->frame_count;
- agg->start_idx = start_idx;
- agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
- agg->bitmap = 0;
-
- /* # frames attempted by Tx command */
- if (agg->frame_count == 1) {
- struct iwl_tx_info *txb;
-
- /* Only one frame was attempted; no block-ack will arrive */
- idx = start_idx;
-
- IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
- agg->frame_count, agg->start_idx, idx);
- txb = &priv->txq[txq_id].txb[idx];
- iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(txb->skb),
- txb->ctx, tx_resp, txq_id, true);
- agg->wait_for_ba = 0;
- } else {
- /* Two or more frames were attempted; expect block-ack */
- u64 bitmap = 0;
-
- /*
- * Start is the lowest frame sent. It may not be the first
- * frame in the batch; we figure this out dynamically during
- * the following loop.
- */
- int start = agg->start_idx;
-
- /* Construct bit-map of pending frames within Tx window */
- for (i = 0; i < agg->frame_count; i++) {
- u16 sc;
- status = le16_to_cpu(frame_status[i].status);
- seq = le16_to_cpu(frame_status[i].sequence);
- idx = SEQ_TO_INDEX(seq);
- txq_id = SEQ_TO_QUEUE(seq);
-
- if (status & AGG_TX_STATUS_MSK)
- iwlagn_count_agg_tx_err_status(priv, status);
-
- if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
- AGG_TX_STATE_ABORT_MSK))
- continue;
-
- IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
- agg->frame_count, txq_id, idx);
- IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), "
- "try-count (0x%08x)\n",
- iwl_get_agg_tx_fail_reason(status),
- status & AGG_TX_STATUS_MSK,
- status & AGG_TX_TRY_MSK);
-
- hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
- if (!hdr) {
- IWL_ERR(priv,
- "BUG_ON idx doesn't point to valid skb"
- " idx=%d, txq_id=%d\n", idx, txq_id);
- return -1;
- }
-
- sc = le16_to_cpu(hdr->seq_ctrl);
- if (idx != (SEQ_TO_SN(sc) & 0xff)) {
- IWL_ERR(priv,
- "BUG_ON idx doesn't match seq control"
- " idx=%d, seq_idx=%d, seq=%d\n",
- idx, SEQ_TO_SN(sc),
- hdr->seq_ctrl);
- return -1;
- }
-
- IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
- i, idx, SEQ_TO_SN(sc));
-
- /*
- * sh -> how many frames ahead of the starting frame is
- * the current one?
- *
- * Note that all frames sent in the batch must be in a
- * 64-frame window, so this number should be in [0,63].
- * If outside of this window, then we've found a new
- * "first" frame in the batch and need to change start.
- */
- sh = idx - start;
-
- /*
- * If >= 64, out of window. start must be at the front
- * of the circular buffer, idx must be near the end of
- * the buffer, and idx is the new "first" frame. Shift
- * the indices around.
- */
- if (sh >= 64) {
- /* Shift bitmap by start - idx, wrapped */
- sh = 0x100 - idx + start;
- bitmap = bitmap << sh;
- /* Now idx is the new start so sh = 0 */
- sh = 0;
- start = idx;
- /*
- * If <= -64 then wraps the 256-pkt circular buffer
- * (e.g., start = 255 and idx = 0, sh should be 1)
- */
- } else if (sh <= -64) {
- sh = 0x100 - start + idx;
- /*
- * If < 0 but > -64, out of window. idx is before start
- * but not wrapped. Shift the indices around.
- */
- } else if (sh < 0) {
- /* Shift by how far start is ahead of idx */
- sh = start - idx;
- bitmap = bitmap << sh;
- /* Now idx is the new start so sh = 0 */
- start = idx;
- sh = 0;
- }
- /* Sequence number start + sh was sent in this batch */
- bitmap |= 1ULL << sh;
- IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
- start, (unsigned long long)bitmap);
- }
-
- /*
- * Store the bitmap and possibly the new start, if we wrapped
- * the buffer above
- */
- agg->bitmap = bitmap;
- agg->start_idx = start;
- IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
- agg->frame_count, agg->start_idx,
- (unsigned long long)agg->bitmap);
-
- if (bitmap)
- agg->wait_for_ba = 1;
- }
- return 0;
-}
-
-void iwl_check_abort_status(struct iwl_priv *priv,
- u8 frame_count, u32 status)
-{
- if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
- IWL_ERR(priv, "Tx flush command to flush out all frames\n");
- if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- queue_work(priv->workqueue, &priv->tx_flush);
- }
-}
-
-void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- u16 sequence = le16_to_cpu(pkt->hdr.sequence);
- int txq_id = SEQ_TO_QUEUE(sequence);
- int index = SEQ_TO_INDEX(sequence);
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct ieee80211_tx_info *info;
- struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
- struct ieee80211_hdr *hdr;
- struct iwl_tx_info *txb;
- u32 status = le16_to_cpu(tx_resp->status.status);
- int tid;
- int sta_id;
- int freed;
- unsigned long flags;
-
- if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
- IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) "
- "index %d is out of range [0-%d] %d %d\n", __func__,
- txq_id, index, txq->q.n_bd, txq->q.write_ptr,
- txq->q.read_ptr);
- return;
- }
-
- txq->time_stamp = jiffies;
- txb = &txq->txb[txq->q.read_ptr];
- info = IEEE80211_SKB_CB(txb->skb);
- memset(&info->status, 0, sizeof(info->status));
-
- tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
- IWLAGN_TX_RES_TID_POS;
- sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
- IWLAGN_TX_RES_RA_POS;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- hdr = (void *)txb->skb->data;
- if (!ieee80211_is_data_qos(hdr->frame_control))
- priv->last_seq_ctl = tx_resp->seq_ctl;
-
- if (txq->sched_retry) {
- const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp);
- struct iwl_ht_agg *agg;
-
- agg = &priv->stations[sta_id].tid[tid].agg;
- /*
- * If the BT kill count is non-zero, we'll get this
- * notification again.
- */
- if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
- priv->cfg->bt_params &&
- priv->cfg->bt_params->advanced_bt_coexist) {
- IWL_DEBUG_COEX(priv, "receive reply tx with bt_kill\n");
- }
- iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
-
- /* check if BAR is needed */
- if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status))
- info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
-
- if (txq->q.read_ptr != (scd_ssn & 0xff)) {
- index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
- IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim "
- "scd_ssn=%d idx=%d txq=%d swq=%d\n",
- scd_ssn , index, txq_id, txq->swq_id);
-
- freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
- iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
-
- if (priv->mac80211_registered &&
- (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
- (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
- iwl_wake_queue(priv, txq);
- }
- } else {
- iwlagn_set_tx_status(priv, info, txb->ctx, tx_resp,
- txq_id, false);
- freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
- iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
-
- if (priv->mac80211_registered &&
- iwl_queue_space(&txq->q) > txq->q.low_mark &&
- status != TX_STATUS_FAIL_PASSIVE_NO_RX)
- iwl_wake_queue(priv, txq);
- }
-
- iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
-
- iwl_check_abort_status(priv, tx_resp->frame_count, status);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
+#include "iwl-shared.h"
int iwlagn_hw_valid_rtc_data_addr(u32 addr)
{
@@ -495,7 +51,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
u8 tx_ant_cfg_cmd;
- if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+ if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status),
"TX Power requested while scanning!\n"))
return -EAGAIN;
@@ -525,7 +81,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
else
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
- return trans_send_cmd_pdu(&priv->trans, tx_ant_cfg_cmd, CMD_SYNC,
+ return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC,
sizeof(tx_power_cmd), &tx_power_cmd);
}
@@ -538,11 +94,7 @@ void iwlagn_temperature(struct iwl_priv *priv)
u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
{
- struct iwl_eeprom_calib_hdr {
- u8 version;
- u8 pa_type;
- u16 voltage;
- } *hdr;
+ struct iwl_eeprom_calib_hdr *hdr;
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
EEPROM_CALIB_ALL);
@@ -609,6 +161,9 @@ struct iwl_mod_params iwlagn_mod_params = {
.bt_coex_active = true,
.no_sleep_autoadjust = true,
.power_level = IWL_POWER_INDEX_1,
+ .bt_ch_announce = true,
+ .wanted_ucode_alternative = 1,
+ .auto_agg = true,
/* the rest are 0 by default */
};
@@ -633,449 +188,6 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
return -1;
}
-static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- enum ieee80211_band band,
- struct iwl_scan_channel *scan_ch)
-{
- const struct ieee80211_supported_band *sband;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int added = 0;
- u16 channel = 0;
-
- sband = iwl_get_hw_mode(priv, band);
- if (!sband) {
- IWL_ERR(priv, "invalid band\n");
- return added;
- }
-
- active_dwell = iwl_get_active_dwell_time(priv, band, 0);
- passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
-
- if (passive_dwell <= active_dwell)
- passive_dwell = active_dwell + 1;
-
- channel = iwl_get_single_channel_number(priv, band);
- if (channel) {
- scan_ch->channel = cpu_to_le16(channel);
- scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
- scan_ch->active_dwell = cpu_to_le16(active_dwell);
- scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
- /* Set txpower levels to defaults */
- scan_ch->dsp_atten = 110;
- if (band == IEEE80211_BAND_5GHZ)
- scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else
- scan_ch->tx_gain = ((1 << 5) | (5 << 3));
- added++;
- } else
- IWL_ERR(priv, "no valid channel found\n");
- return added;
-}
-
-static int iwl_get_channels_for_scan(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- enum ieee80211_band band,
- u8 is_active, u8 n_probes,
- struct iwl_scan_channel *scan_ch)
-{
- struct ieee80211_channel *chan;
- const struct ieee80211_supported_band *sband;
- const struct iwl_channel_info *ch_info;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int added, i;
- u16 channel;
-
- sband = iwl_get_hw_mode(priv, band);
- if (!sband)
- return 0;
-
- active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
- passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
-
- if (passive_dwell <= active_dwell)
- passive_dwell = active_dwell + 1;
-
- for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
- chan = priv->scan_request->channels[i];
-
- if (chan->band != band)
- continue;
-
- channel = chan->hw_value;
- scan_ch->channel = cpu_to_le16(channel);
-
- ch_info = iwl_get_channel_info(priv, band, channel);
- if (!is_channel_valid(ch_info)) {
- IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
- channel);
- continue;
- }
-
- if (!is_active || is_channel_passive(ch_info) ||
- (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
- scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
- else
- scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
-
- if (n_probes)
- scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
-
- scan_ch->active_dwell = cpu_to_le16(active_dwell);
- scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-
- /* Set txpower levels to defaults */
- scan_ch->dsp_atten = 110;
-
- /* NOTE: if we were doing 6Mb OFDM for scans we'd use
- * power level:
- * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
- */
- if (band == IEEE80211_BAND_5GHZ)
- scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else
- scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-
- IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
- channel, le32_to_cpu(scan_ch->type),
- (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
- "ACTIVE" : "PASSIVE",
- (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
- active_dwell : passive_dwell);
-
- scan_ch++;
- added++;
- }
-
- IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
- return added;
-}
-
-static int iwl_fill_offch_tx(struct iwl_priv *priv, void *data, size_t maxlen)
-{
- struct sk_buff *skb = priv->offchan_tx_skb;
-
- if (skb->len < maxlen)
- maxlen = skb->len;
-
- memcpy(data, skb->data, maxlen);
-
- return maxlen;
-}
-
-int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
- struct iwl_host_cmd cmd = {
- .id = REPLY_SCAN_CMD,
- .len = { sizeof(struct iwl_scan_cmd), },
- .flags = CMD_SYNC,
- };
- struct iwl_scan_cmd *scan;
- struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- u32 rate_flags = 0;
- u16 cmd_len;
- u16 rx_chain = 0;
- enum ieee80211_band band;
- u8 n_probes = 0;
- u8 rx_ant = priv->hw_params.valid_rx_ant;
- u8 rate;
- bool is_active = false;
- int chan_mod;
- u8 active_chains;
- u8 scan_tx_antennas = priv->hw_params.valid_tx_ant;
- int ret;
-
- lockdep_assert_held(&priv->mutex);
-
- if (vif)
- ctx = iwl_rxon_ctx_from_vif(vif);
-
- if (!priv->scan_cmd) {
- priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
- IWL_MAX_SCAN_SIZE, GFP_KERNEL);
- if (!priv->scan_cmd) {
- IWL_DEBUG_SCAN(priv,
- "fail to allocate memory for scan\n");
- return -ENOMEM;
- }
- }
- scan = priv->scan_cmd;
- memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
-
- scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
- scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
-
- if (priv->scan_type != IWL_SCAN_OFFCH_TX &&
- iwl_is_any_associated(priv)) {
- u16 interval = 0;
- u32 extra;
- u32 suspend_time = 100;
- u32 scan_suspend_time = 100;
-
- IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
- switch (priv->scan_type) {
- case IWL_SCAN_OFFCH_TX:
- WARN_ON(1);
- break;
- case IWL_SCAN_RADIO_RESET:
- interval = 0;
- break;
- case IWL_SCAN_NORMAL:
- interval = vif->bss_conf.beacon_int;
- break;
- }
-
- scan->suspend_time = 0;
- scan->max_out_time = cpu_to_le32(200 * 1024);
- if (!interval)
- interval = suspend_time;
-
- extra = (suspend_time / interval) << 22;
- scan_suspend_time = (extra |
- ((suspend_time % interval) * 1024));
- scan->suspend_time = cpu_to_le32(scan_suspend_time);
- IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
- scan_suspend_time, interval);
- } else if (priv->scan_type == IWL_SCAN_OFFCH_TX) {
- scan->suspend_time = 0;
- scan->max_out_time =
- cpu_to_le32(1024 * priv->offchan_tx_timeout);
- }
-
- switch (priv->scan_type) {
- case IWL_SCAN_RADIO_RESET:
- IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
- break;
- case IWL_SCAN_NORMAL:
- if (priv->scan_request->n_ssids) {
- int i, p = 0;
- IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
- for (i = 0; i < priv->scan_request->n_ssids; i++) {
- /* always does wildcard anyway */
- if (!priv->scan_request->ssids[i].ssid_len)
- continue;
- scan->direct_scan[p].id = WLAN_EID_SSID;
- scan->direct_scan[p].len =
- priv->scan_request->ssids[i].ssid_len;
- memcpy(scan->direct_scan[p].ssid,
- priv->scan_request->ssids[i].ssid,
- priv->scan_request->ssids[i].ssid_len);
- n_probes++;
- p++;
- }
- is_active = true;
- } else
- IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
- break;
- case IWL_SCAN_OFFCH_TX:
- IWL_DEBUG_SCAN(priv, "Start offchannel TX scan.\n");
- break;
- }
-
- scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
- scan->tx_cmd.sta_id = ctx->bcast_sta_id;
- scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
- switch (priv->scan_band) {
- case IEEE80211_BAND_2GHZ:
- scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
- chan_mod = le32_to_cpu(
- priv->contexts[IWL_RXON_CTX_BSS].active.flags &
- RXON_FLG_CHANNEL_MODE_MSK)
- >> RXON_FLG_CHANNEL_MODE_POS;
- if (chan_mod == CHANNEL_MODE_PURE_40) {
- rate = IWL_RATE_6M_PLCP;
- } else {
- rate = IWL_RATE_1M_PLCP;
- rate_flags = RATE_MCS_CCK_MSK;
- }
- /*
- * Internal scans are passive, so we can indiscriminately set
- * the BT ignore flag on 2.4 GHz since it applies to TX only.
- */
- if (priv->cfg->bt_params &&
- priv->cfg->bt_params->advanced_bt_coexist)
- scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
- break;
- case IEEE80211_BAND_5GHZ:
- rate = IWL_RATE_6M_PLCP;
- break;
- default:
- IWL_WARN(priv, "Invalid scan band\n");
- return -EIO;
- }
-
- /*
- * If active scanning is requested but a certain channel is
- * marked passive, we can do active scanning if we detect
- * transmissions.
- *
- * There is an issue with some firmware versions that triggers
- * a sysassert on a "good CRC threshold" of zero (== disabled),
- * on a radar channel even though this means that we should NOT
- * send probes.
- *
- * The "good CRC threshold" is the number of frames that we
- * need to receive during our dwell time on a channel before
- * sending out probes -- setting this to a huge value will
- * mean we never reach it, but at the same time work around
- * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
- * here instead of IWL_GOOD_CRC_TH_DISABLED.
- *
- * This was fixed in later versions along with some other
- * scan changes, and the threshold behaves as a flag in those
- * versions.
- */
- if (priv->new_scan_threshold_behaviour)
- scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
- IWL_GOOD_CRC_TH_DISABLED;
- else
- scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
- IWL_GOOD_CRC_TH_NEVER;
-
- band = priv->scan_band;
-
- if (priv->cfg->scan_rx_antennas[band])
- rx_ant = priv->cfg->scan_rx_antennas[band];
-
- if (band == IEEE80211_BAND_2GHZ &&
- priv->cfg->bt_params &&
- priv->cfg->bt_params->advanced_bt_coexist) {
- /* transmit 2.4 GHz probes only on first antenna */
- scan_tx_antennas = first_antenna(scan_tx_antennas);
- }
-
- priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band],
- scan_tx_antennas);
- rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
- scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
-
- /* In power save mode use one chain, otherwise use all chains */
- if (test_bit(STATUS_POWER_PMI, &priv->status)) {
- /* rx_ant has been set to all valid chains previously */
- active_chains = rx_ant &
- ((u8)(priv->chain_noise_data.active_chains));
- if (!active_chains)
- active_chains = rx_ant;
-
- IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
- priv->chain_noise_data.active_chains);
-
- rx_ant = first_antenna(active_chains);
- }
- if (priv->cfg->bt_params &&
- priv->cfg->bt_params->advanced_bt_coexist &&
- priv->bt_full_concurrent) {
- /* operated as 1x1 in full concurrency mode */
- rx_ant = first_antenna(rx_ant);
- }
-
- /* MIMO is not used here, but value is required */
- rx_chain |= priv->hw_params.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;
- scan->rx_chain = cpu_to_le16(rx_chain);
- switch (priv->scan_type) {
- case IWL_SCAN_NORMAL:
- cmd_len = iwl_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- vif->addr,
- priv->scan_request->ie,
- priv->scan_request->ie_len,
- IWL_MAX_SCAN_SIZE - sizeof(*scan));
- break;
- case IWL_SCAN_RADIO_RESET:
- /* use bcast addr, will not be transmitted but must be valid */
- cmd_len = iwl_fill_probe_req(priv,
- (struct ieee80211_mgmt *)scan->data,
- iwl_bcast_addr, NULL, 0,
- IWL_MAX_SCAN_SIZE - sizeof(*scan));
- break;
- case IWL_SCAN_OFFCH_TX:
- cmd_len = iwl_fill_offch_tx(priv, scan->data,
- IWL_MAX_SCAN_SIZE
- - sizeof(*scan)
- - sizeof(struct iwl_scan_channel));
- scan->scan_flags |= IWL_SCAN_FLAGS_ACTION_FRAME_TX;
- break;
- default:
- BUG();
- }
- scan->tx_cmd.len = cpu_to_le16(cmd_len);
-
- scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
- RXON_FILTER_BCON_AWARE_MSK);
-
- switch (priv->scan_type) {
- case IWL_SCAN_RADIO_RESET:
- scan->channel_count =
- iwl_get_single_channel_for_scan(priv, vif, band,
- (void *)&scan->data[cmd_len]);
- break;
- case IWL_SCAN_NORMAL:
- scan->channel_count =
- iwl_get_channels_for_scan(priv, vif, band,
- is_active, n_probes,
- (void *)&scan->data[cmd_len]);
- break;
- case IWL_SCAN_OFFCH_TX: {
- struct iwl_scan_channel *scan_ch;
-
- scan->channel_count = 1;
-
- scan_ch = (void *)&scan->data[cmd_len];
- scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
- scan_ch->channel =
- cpu_to_le16(priv->offchan_tx_chan->hw_value);
- scan_ch->active_dwell =
- cpu_to_le16(priv->offchan_tx_timeout);
- scan_ch->passive_dwell = 0;
-
- /* Set txpower levels to defaults */
- scan_ch->dsp_atten = 110;
-
- /* NOTE: if we were doing 6Mb OFDM for scans we'd use
- * power level:
- * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
- */
- if (priv->offchan_tx_chan->band == IEEE80211_BAND_5GHZ)
- scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else
- scan_ch->tx_gain = ((1 << 5) | (5 << 3));
- }
- break;
- }
-
- if (scan->channel_count == 0) {
- IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
- return -EIO;
- }
-
- cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) +
- scan->channel_count * sizeof(struct iwl_scan_channel);
- cmd.data[0] = scan;
- cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
- scan->len = cpu_to_le16(cmd.len[0]);
-
- /* set scan bit here for PAN params */
- set_bit(STATUS_SCAN_HW, &priv->status);
-
- ret = iwlagn_set_pan_params(priv);
- if (ret)
- return ret;
-
- ret = trans_send_cmd(&priv->trans, &cmd);
- if (ret) {
- clear_bit(STATUS_SCAN_HW, &priv->status);
- iwlagn_set_pan_params(priv);
- }
-
- return ret;
-}
-
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add)
{
@@ -1089,52 +201,6 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
vif->bss_conf.bssid);
}
-void iwl_free_tfds_in_queue(struct iwl_priv *priv,
- int sta_id, int tid, int freed)
-{
- lockdep_assert_held(&priv->sta_lock);
-
- if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed)
- priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
- else {
- IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
- priv->stations[sta_id].tid[tid].tfds_in_queue,
- freed);
- priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
- }
-}
-
-#define IWL_FLUSH_WAIT_MS 2000
-
-int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv)
-{
- struct iwl_tx_queue *txq;
- struct iwl_queue *q;
- int cnt;
- unsigned long now = jiffies;
- int ret = 0;
-
- /* waiting for all the tx frames complete might take a while */
- for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
- if (cnt == priv->cmd_queue)
- continue;
- txq = &priv->txq[cnt];
- q = &txq->q;
- while (q->read_ptr != q->write_ptr && !time_after(jiffies,
- now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS)))
- msleep(1);
-
- if (q->read_ptr != q->write_ptr) {
- IWL_ERR(priv, "fail to flush all tx fifo queues\n");
- ret = -ETIMEDOUT;
- break;
- }
- }
- return ret;
-}
-
-#define IWL_TX_QUEUE_MSK 0xfffff
-
/**
* iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode
*
@@ -1160,7 +226,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
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)))
+ (priv->shrd->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 |
@@ -1173,22 +239,22 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
flush_cmd.fifo_control);
flush_cmd.flush_control = cpu_to_le16(flush_control);
- return trans_send_cmd(&priv->trans, &cmd);
+ return iwl_trans_send_cmd(trans(priv), &cmd);
}
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
{
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
ieee80211_stop_queues(priv->hw);
if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n");
- iwlagn_wait_tx_queue_empty(priv);
+ iwl_trans_wait_tx_queue_empty(trans(priv));
done:
ieee80211_wake_queues(priv->hw);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
/*
@@ -1367,12 +433,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
if (priv->cfg->bt_params->bt_session_2) {
memcpy(&bt_cmd_2000.basic, &basic,
sizeof(basic));
- ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG,
+ ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
} else {
memcpy(&bt_cmd_6000.basic, &basic,
sizeof(basic));
- ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG,
+ ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
}
if (ret)
@@ -1385,7 +451,7 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena)
struct iwl_rxon_context *ctx, *found_ctx = NULL;
bool found_ap = false;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
/* Check whether AP or GO mode is active. */
if (rssi_ena) {
@@ -1498,7 +564,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
break;
}
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
/*
* We can not send command to firmware while scanning. When the scan
@@ -1507,7 +573,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
* STATUS_SCANNING to avoid race when queue_work two times from
* different notifications, but quit and not perform any work at all.
*/
- if (test_bit(STATUS_SCAN_HW, &priv->status))
+ if (test_bit(STATUS_SCAN_HW, &priv->shrd->status))
goto out;
iwl_update_chain_flags(priv);
@@ -1526,7 +592,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
*/
iwlagn_bt_coex_rssi_monitor(priv);
out:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
/*
@@ -1633,12 +699,13 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv,
priv->kill_cts_mask = bt_kill_cts_msg[kill_msk];
/* schedule to send runtime bt_config */
- queue_work(priv->workqueue, &priv->bt_runtime_config);
+ queue_work(priv->shrd->workqueue, &priv->bt_runtime_config);
}
}
-void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
unsigned long flags;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -1647,7 +714,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
/* bt coex disabled */
- return;
+ return 0;
}
IWL_DEBUG_COEX(priv, "BT Coex notification:\n");
@@ -1677,7 +744,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
IWL_BT_COEX_TRAFFIC_LOAD_NONE;
}
priv->bt_status = coex->bt_status;
- queue_work(priv->workqueue,
+ queue_work(priv->shrd->workqueue,
&priv->bt_traffic_change_work);
}
}
@@ -1686,9 +753,10 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
/* FIXME: based on notification, adjust the prio_boost */
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->shrd->lock, flags);
priv->bt_ci_compliance = coex->bt_ci_compliance;
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
+ return 0;
}
void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv)
@@ -1788,7 +856,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
bool is_single = is_single_rx_stream(priv);
- bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
+ bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->shrd->status);
u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
u32 active_chains;
u16 rx_chain;
@@ -1800,7 +868,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->hw_params.valid_rx_ant;
+ active_chains = hw_params(priv).valid_rx_ant;
if (priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist &&
@@ -1865,136 +933,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
return ant;
}
-static const char *get_csr_string(int cmd)
-{
- switch (cmd) {
- IWL_CMD(CSR_HW_IF_CONFIG_REG);
- IWL_CMD(CSR_INT_COALESCING);
- IWL_CMD(CSR_INT);
- IWL_CMD(CSR_INT_MASK);
- IWL_CMD(CSR_FH_INT_STATUS);
- IWL_CMD(CSR_GPIO_IN);
- IWL_CMD(CSR_RESET);
- IWL_CMD(CSR_GP_CNTRL);
- IWL_CMD(CSR_HW_REV);
- IWL_CMD(CSR_EEPROM_REG);
- IWL_CMD(CSR_EEPROM_GP);
- IWL_CMD(CSR_OTP_GP_REG);
- IWL_CMD(CSR_GIO_REG);
- IWL_CMD(CSR_GP_UCODE_REG);
- IWL_CMD(CSR_GP_DRIVER_REG);
- IWL_CMD(CSR_UCODE_DRV_GP1);
- IWL_CMD(CSR_UCODE_DRV_GP2);
- IWL_CMD(CSR_LED_REG);
- IWL_CMD(CSR_DRAM_INT_TBL_REG);
- IWL_CMD(CSR_GIO_CHICKEN_BITS);
- IWL_CMD(CSR_ANA_PLL_CFG);
- IWL_CMD(CSR_HW_REV_WA_REG);
- IWL_CMD(CSR_DBG_HPET_MEM_REG);
- default:
- return "UNKNOWN";
- }
-}
-
-void iwl_dump_csr(struct iwl_priv *priv)
-{
- int i;
- static const u32 csr_tbl[] = {
- CSR_HW_IF_CONFIG_REG,
- CSR_INT_COALESCING,
- CSR_INT,
- CSR_INT_MASK,
- CSR_FH_INT_STATUS,
- CSR_GPIO_IN,
- CSR_RESET,
- CSR_GP_CNTRL,
- CSR_HW_REV,
- CSR_EEPROM_REG,
- CSR_EEPROM_GP,
- CSR_OTP_GP_REG,
- CSR_GIO_REG,
- CSR_GP_UCODE_REG,
- CSR_GP_DRIVER_REG,
- CSR_UCODE_DRV_GP1,
- CSR_UCODE_DRV_GP2,
- CSR_LED_REG,
- CSR_DRAM_INT_TBL_REG,
- CSR_GIO_CHICKEN_BITS,
- CSR_ANA_PLL_CFG,
- CSR_HW_REV_WA_REG,
- CSR_DBG_HPET_MEM_REG
- };
- IWL_ERR(priv, "CSR values:\n");
- IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is "
- "CSR_INT_PERIODIC_REG)\n");
- for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) {
- IWL_ERR(priv, " %25s: 0X%08x\n",
- get_csr_string(csr_tbl[i]),
- iwl_read32(priv, csr_tbl[i]));
- }
-}
-
-static const char *get_fh_string(int cmd)
-{
- switch (cmd) {
- IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
- IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
- IWL_CMD(FH_RSCSR_CHNL0_WPTR);
- IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
- IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
- IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
- IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
- IWL_CMD(FH_TSSR_TX_STATUS_REG);
- IWL_CMD(FH_TSSR_TX_ERROR_REG);
- default:
- return "UNKNOWN";
- }
-}
-
-int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
-{
- int i;
-#ifdef CONFIG_IWLWIFI_DEBUG
- int pos = 0;
- size_t bufsz = 0;
-#endif
- static const u32 fh_tbl[] = {
- FH_RSCSR_CHNL0_STTS_WPTR_REG,
- FH_RSCSR_CHNL0_RBDCB_BASE_REG,
- FH_RSCSR_CHNL0_WPTR,
- FH_MEM_RCSR_CHNL0_CONFIG_REG,
- FH_MEM_RSSR_SHARED_CTRL_REG,
- FH_MEM_RSSR_RX_STATUS_REG,
- FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
- FH_TSSR_TX_STATUS_REG,
- FH_TSSR_TX_ERROR_REG
- };
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (display) {
- bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- pos += scnprintf(*buf + pos, bufsz - pos,
- "FH register values:\n");
- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- " %34s: 0X%08x\n",
- get_fh_string(fh_tbl[i]),
- iwl_read_direct32(priv, fh_tbl[i]));
- }
- return pos;
- }
-#endif
- IWL_ERR(priv, "FH register values:\n");
- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
- IWL_ERR(priv, " %34s: 0X%08x\n",
- get_fh_string(fh_tbl[i]),
- iwl_read_direct32(priv, fh_tbl[i]));
- }
- return 0;
-}
-
/* notification wait support */
void iwlagn_init_notification_wait(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 3789ff4bf53b..66118cea2af3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -27,7 +27,6 @@
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/netdevice.h>
@@ -37,7 +36,6 @@
#include <linux/workqueue.h>
#include "iwl-dev.h"
-#include "iwl-sta.h"
#include "iwl-core.h"
#include "iwl-agn.h"
@@ -298,10 +296,10 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
u8 *qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & 0xf;
} else
- return MAX_TID_COUNT;
+ return IWL_MAX_TID_COUNT;
if (unlikely(tid >= TID_MAX_LOAD_COUNT))
- return MAX_TID_COUNT;
+ return IWL_MAX_TID_COUNT;
tl = &lq_data->load[tid];
@@ -314,7 +312,7 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
tl->queue_count = 1;
tl->head = 0;
tl->packet_count[0] = 1;
- return MAX_TID_COUNT;
+ return IWL_MAX_TID_COUNT;
}
time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
@@ -347,7 +345,7 @@ static void rs_program_fix_rate(struct iwl_priv *priv,
{
struct iwl_station_priv *sta_priv =
container_of(lq_sta, struct iwl_station_priv, lq_sta);
- struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+ struct iwl_rxon_context *ctx = sta_priv->ctx;
lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */
lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
@@ -421,7 +419,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
load = rs_tl_get_load(lq_data, tid);
- if (load > IWL_AGG_LOAD_THRESHOLD) {
+ if ((iwlagn_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) {
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
sta->addr, tid);
ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
@@ -711,7 +709,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
static bool rs_use_green(struct ieee80211_sta *sta)
{
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
- struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+ struct iwl_rxon_context *ctx = sta_priv->ctx;
return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
!(ctx->ht.non_gf_sta_present);
@@ -820,7 +818,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->hw_params.valid_tx_ant);
+ first_antenna(hw_params(priv).valid_tx_ant);
tbl->is_ht40 = 0;
tbl->is_SGI = 0;
@@ -878,12 +876,12 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
* Is there a need to switch between
* full concurrency and 3-wire?
*/
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->shrd->lock, flags);
if (priv->bt_ci_compliance && priv->bt_ant_couple_ok)
full_concurrent = true;
else
full_concurrent = false;
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
}
if ((priv->bt_traffic_load != priv->last_bt_traffic_load) ||
(priv->bt_full_concurrent != full_concurrent)) {
@@ -894,7 +892,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
- queue_work(priv->workqueue, &priv->bt_full_concurrency);
+ queue_work(priv->shrd->workqueue, &priv->bt_full_concurrency);
}
}
@@ -918,7 +916,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
struct iwl_scale_tbl_info tbl_type;
struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
- struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+ struct iwl_rxon_context *ctx = sta_priv->ctx;
IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
@@ -1284,7 +1282,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
s32 rate;
s8 is_green = lq_sta->is_green;
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
- struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+ struct iwl_rxon_context *ctx = sta_priv->ctx;
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
return -1;
@@ -1294,7 +1292,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
return -1;
/* Need both Tx chains/antennas to support MIMO */
- if (priv->hw_params.tx_chains_num < 2)
+ if (hw_params(priv).tx_chains_num < 2)
return -1;
IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n");
@@ -1340,7 +1338,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
s32 rate;
s8 is_green = lq_sta->is_green;
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
- struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+ struct iwl_rxon_context *ctx = sta_priv->ctx;
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
return -1;
@@ -1350,7 +1348,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
return -1;
/* Need both Tx chains/antennas to support MIMO */
- if (priv->hw_params.tx_chains_num < 3)
+ if (hw_params(priv).tx_chains_num < 3)
return -1;
IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n");
@@ -1397,7 +1395,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
u8 is_green = lq_sta->is_green;
s32 rate;
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
- struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+ struct iwl_rxon_context *ctx = sta_priv->ctx;
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
return -1;
@@ -1449,8 +1447,8 @@ 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->hw_params.valid_tx_ant;
- u8 tx_chains_num = priv->hw_params.tx_chains_num;
+ u8 valid_tx_ant = hw_params(priv).valid_tx_ant;
+ u8 tx_chains_num = hw_params(priv).tx_chains_num;
int ret = 0;
u8 update_search_tbl_counter = 0;
@@ -1460,14 +1458,16 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
break;
case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
/* avoid antenna B unless MIMO */
- valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ valid_tx_ant =
+ first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2)
tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
break;
case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
/* avoid antenna B and MIMO */
- valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ valid_tx_ant =
+ first_antenna(hw_params(priv).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,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
tbl->action = IWL_LEGACY_SWITCH_SISO;
- valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ valid_tx_ant =
+ first_antenna(hw_params(priv).valid_tx_ant);
}
start_action = tbl->action;
@@ -1624,8 +1625,8 @@ 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->hw_params.valid_tx_ant;
- u8 tx_chains_num = priv->hw_params.tx_chains_num;
+ u8 valid_tx_ant = hw_params(priv).valid_tx_ant;
+ u8 tx_chains_num = hw_params(priv).tx_chains_num;
u8 update_search_tbl_counter = 0;
int ret;
@@ -1635,14 +1636,16 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
break;
case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
/* avoid antenna B unless MIMO */
- valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ valid_tx_ant =
+ first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action == IWL_SISO_SWITCH_ANTENNA2)
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
break;
case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
/* avoid antenna B and MIMO */
- valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ valid_tx_ant =
+ first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action != IWL_SISO_SWITCH_ANTENNA1)
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
break;
@@ -1659,7 +1662,8 @@ 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->hw_params.valid_tx_ant);
+ valid_tx_ant =
+ first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
}
@@ -1795,8 +1799,8 @@ 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->hw_params.valid_tx_ant;
- u8 tx_chains_num = priv->hw_params.tx_chains_num;
+ u8 valid_tx_ant = hw_params(priv).valid_tx_ant;
+ u8 tx_chains_num = hw_params(priv).tx_chains_num;
u8 update_search_tbl_counter = 0;
int ret;
@@ -1965,8 +1969,8 @@ 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->hw_params.valid_tx_ant;
- u8 tx_chains_num = priv->hw_params.tx_chains_num;
+ u8 valid_tx_ant = hw_params(priv).valid_tx_ant;
+ u8 tx_chains_num = hw_params(priv).tx_chains_num;
int ret;
u8 update_search_tbl_counter = 0;
@@ -2209,7 +2213,6 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
/*
* setup rate table in uCode
- * return rate_n_flags as used in the table
*/
static void rs_update_rate_tbl(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
@@ -2256,10 +2259,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
u8 done_search = 0;
u16 high_low;
s32 sr;
- u8 tid = MAX_TID_COUNT;
+ u8 tid = IWL_MAX_TID_COUNT;
struct iwl_tid_data *tid_data;
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
- struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+ struct iwl_rxon_context *ctx = sta_priv->ctx;
IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n");
@@ -2269,14 +2272,12 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
info->flags & IEEE80211_TX_CTL_NO_ACK)
return;
- if (!sta || !lq_sta)
- return;
-
lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
tid = rs_tl_add_packet(lq_sta, hdr);
- if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) {
- tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid];
+ if ((tid != IWL_MAX_TID_COUNT) &&
+ (lq_sta->tx_agg_tid_en & (1 << tid))) {
+ tid_data = &priv->shrd->tid_data[lq_sta->lq.sta_id][tid];
if (tid_data->agg.state == IWL_AGG_OFF)
lq_sta->is_agg = 0;
else
@@ -2646,9 +2647,10 @@ lq_update:
iwl_ht_enabled(priv)) {
if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
(lq_sta->tx_agg_tid_en & (1 << tid)) &&
- (tid != MAX_TID_COUNT)) {
+ (tid != IWL_MAX_TID_COUNT)) {
+ u8 sta_id = lq_sta->lq.sta_id;
tid_data =
- &priv->stations[lq_sta->lq.sta_id].tid[tid];
+ &priv->shrd->tid_data[sta_id][tid];
if (tid_data->agg.state == IWL_AGG_OFF) {
IWL_DEBUG_RATE(priv,
"try to aggregate tid %d\n",
@@ -2663,8 +2665,7 @@ lq_update:
out:
tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
- i = index;
- lq_sta->last_txrate_idx = i;
+ lq_sta->last_txrate_idx = index;
}
/**
@@ -2700,11 +2701,11 @@ static void rs_initialize_lq(struct iwl_priv *priv,
return;
sta_priv = (void *)sta->drv_priv;
- ctx = sta_priv->common.ctx;
+ ctx = sta_priv->ctx;
i = lq_sta->last_txrate_idx;
- valid_tx_ant = priv->hw_params.valid_tx_ant;
+ valid_tx_ant = hw_params(priv).valid_tx_ant;
if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl;
@@ -2887,15 +2888,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->hw_params.valid_tx_ant);
+ first_antenna(hw_params(priv).valid_tx_ant);
lq_sta->lq.general_params.dual_stream_ant_msk =
- priv->hw_params.valid_tx_ant &
- ~first_antenna(priv->hw_params.valid_tx_ant);
+ hw_params(priv).valid_tx_ant &
+ ~first_antenna(hw_params(priv).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->hw_params.valid_tx_ant) == 2) {
+ } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) {
lq_sta->lq.general_params.dual_stream_ant_msk =
- priv->hw_params.valid_tx_ant;
+ hw_params(priv).valid_tx_ant;
}
/* as default allow aggregation for all tids */
@@ -2941,7 +2942,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->hw_params.valid_tx_ant);
+ first_antenna(hw_params(priv).valid_tx_ant);
}
/* How many times should we repeat the initial rate? */
@@ -2973,7 +2974,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->hw_params.valid_tx_ant;
+ valid_tx_ant = hw_params(priv).valid_tx_ant;
}
/* Fill rest of rate table */
@@ -3007,7 +3008,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->hw_params.valid_tx_ant);
+ first_antenna(hw_params(priv).valid_tx_ant);
}
/* Indicate to uCode which entries might be MIMO.
@@ -3098,7 +3099,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->hw_params.valid_tx_ant;
+ valid_tx_ant = hw_params(priv).valid_tx_ant;
if (lq_sta->dbg_fixed_rate) {
ant_sel_tx =
((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK)
@@ -3169,9 +3170,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->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",
- (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "",
- (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : "");
+ (hw_params(priv).valid_tx_ant & ANT_A) ? "ANT_A," : "",
+ (hw_params(priv).valid_tx_ant & ANT_B) ? "ANT_B," : "",
+ (hw_params(priv).valid_tx_ant & ANT_C) ? "ANT_C" : "");
desc += sprintf(buff+desc, "lq type %s\n",
(is_legacy(tbl->lq_type)) ? "legacy" : "HT");
if (is_Ht(tbl->lq_type)) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index bdae82e7fa90..f4f6deb829ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -27,6 +27,10 @@
#ifndef __iwl_agn_rs_h__
#define __iwl_agn_rs_h__
+#include <net/mac80211.h>
+
+#include "iwl-commands.h"
+
struct iwl_rate_info {
u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */
u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 8e314003b63a..5af9e6258a16 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -3,7 +3,7 @@
* Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
*
* Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
+ * as portionhelp of the ieee80211 subsystem header files.
*
* 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
@@ -35,12 +35,93 @@
#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-core.h"
-#include "iwl-sta.h"
#include "iwl-io.h"
-#include "iwl-helpers.h"
#include "iwl-agn-calib.h"
#include "iwl-agn.h"
+#include "iwl-shared.h"
+const char *get_cmd_string(u8 cmd)
+{
+ switch (cmd) {
+ IWL_CMD(REPLY_ALIVE);
+ IWL_CMD(REPLY_ERROR);
+ IWL_CMD(REPLY_ECHO);
+ IWL_CMD(REPLY_RXON);
+ IWL_CMD(REPLY_RXON_ASSOC);
+ IWL_CMD(REPLY_QOS_PARAM);
+ IWL_CMD(REPLY_RXON_TIMING);
+ IWL_CMD(REPLY_ADD_STA);
+ IWL_CMD(REPLY_REMOVE_STA);
+ IWL_CMD(REPLY_REMOVE_ALL_STA);
+ IWL_CMD(REPLY_TXFIFO_FLUSH);
+ IWL_CMD(REPLY_WEPKEY);
+ IWL_CMD(REPLY_TX);
+ IWL_CMD(REPLY_LEDS_CMD);
+ IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
+ IWL_CMD(COEX_PRIORITY_TABLE_CMD);
+ IWL_CMD(COEX_MEDIUM_NOTIFICATION);
+ IWL_CMD(COEX_EVENT_CMD);
+ IWL_CMD(REPLY_QUIET_CMD);
+ IWL_CMD(REPLY_CHANNEL_SWITCH);
+ IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
+ IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
+ IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
+ IWL_CMD(POWER_TABLE_CMD);
+ IWL_CMD(PM_SLEEP_NOTIFICATION);
+ IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
+ IWL_CMD(REPLY_SCAN_CMD);
+ IWL_CMD(REPLY_SCAN_ABORT_CMD);
+ IWL_CMD(SCAN_START_NOTIFICATION);
+ IWL_CMD(SCAN_RESULTS_NOTIFICATION);
+ IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
+ IWL_CMD(BEACON_NOTIFICATION);
+ IWL_CMD(REPLY_TX_BEACON);
+ IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
+ IWL_CMD(QUIET_NOTIFICATION);
+ IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
+ IWL_CMD(MEASURE_ABORT_NOTIFICATION);
+ IWL_CMD(REPLY_BT_CONFIG);
+ IWL_CMD(REPLY_STATISTICS_CMD);
+ IWL_CMD(STATISTICS_NOTIFICATION);
+ IWL_CMD(REPLY_CARD_STATE_CMD);
+ IWL_CMD(CARD_STATE_NOTIFICATION);
+ IWL_CMD(MISSED_BEACONS_NOTIFICATION);
+ IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
+ IWL_CMD(SENSITIVITY_CMD);
+ IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
+ IWL_CMD(REPLY_RX_PHY_CMD);
+ IWL_CMD(REPLY_RX_MPDU_CMD);
+ IWL_CMD(REPLY_RX);
+ IWL_CMD(REPLY_COMPRESSED_BA);
+ IWL_CMD(CALIBRATION_CFG_CMD);
+ IWL_CMD(CALIBRATION_RES_NOTIFICATION);
+ IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
+ IWL_CMD(REPLY_TX_POWER_DBM_CMD);
+ IWL_CMD(TEMPERATURE_NOTIFICATION);
+ IWL_CMD(TX_ANT_CONFIGURATION_CMD);
+ IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
+ IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
+ IWL_CMD(REPLY_BT_COEX_PROT_ENV);
+ IWL_CMD(REPLY_WIPAN_PARAMS);
+ IWL_CMD(REPLY_WIPAN_RXON);
+ IWL_CMD(REPLY_WIPAN_RXON_TIMING);
+ IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
+ IWL_CMD(REPLY_WIPAN_QOS_PARAM);
+ IWL_CMD(REPLY_WIPAN_WEPKEY);
+ IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
+ IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
+ IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
+ IWL_CMD(REPLY_WOWLAN_PATTERNS);
+ IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER);
+ IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS);
+ IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS);
+ IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL);
+ IWL_CMD(REPLY_WOWLAN_GET_STATUS);
+ default:
+ return "UNKNOWN";
+
+ }
+}
/******************************************************************************
*
@@ -48,8 +129,9 @@
*
******************************************************************************/
-static void iwl_rx_reply_error(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_reply_error(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -60,21 +142,23 @@ static void iwl_rx_reply_error(struct iwl_priv *priv,
pkt->u.err_resp.cmd_id,
le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
le32_to_cpu(pkt->u.err_resp.error_info));
+ return 0;
}
-static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
/*
* MULTI-FIXME
- * See iwl_mac_channel_switch.
+ * See iwlagn_mac_channel_switch.
*/
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
- if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
- return;
+ if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
+ return 0;
if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
rxon->channel = csa->channel;
@@ -87,11 +171,13 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
le16_to_cpu(csa->channel));
iwl_chswitch_done(priv, false);
}
+ return 0;
}
-static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_spectrum_measure_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
@@ -99,15 +185,17 @@ static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
if (!report->state) {
IWL_DEBUG_11H(priv,
"Spectrum Measure Notification: Start\n");
- return;
+ return 0;
}
memcpy(&priv->measure_report, report, sizeof(*report));
priv->measurement_status |= MEASUREMENT_READY;
+ return 0;
}
-static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_pm_sleep_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -115,21 +203,26 @@ static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
+ return 0;
}
-static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+ u32 __maybe_unused len =
+ le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
"notification for %s:\n", len,
get_cmd_string(pkt->hdr.cmd));
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
+ return 0;
}
-static void iwl_rx_beacon_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_beacon_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw;
@@ -148,8 +241,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
- if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- queue_work(priv->workqueue, &priv->beacon_update);
+ return 0;
}
/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
@@ -164,7 +256,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
* the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
* operation state.
*/
-static bool iwl_good_ack_health(struct iwl_priv *priv,
+static bool iwlagn_good_ack_health(struct iwl_priv *priv,
struct statistics_tx *cur)
{
int actual_delta, expected_delta, ba_timeout_delta;
@@ -189,8 +281,9 @@ static bool iwl_good_ack_health(struct iwl_priv *priv,
if ((actual_delta * 100 / expected_delta) < ACK_CNT_RATIO &&
ba_timeout_delta > BA_TIMEOUT_CNT) {
- IWL_DEBUG_RADIO(priv, "deltas: actual %d expected %d ba_timeout %d\n",
- actual_delta, expected_delta, ba_timeout_delta);
+ IWL_DEBUG_RADIO(priv,
+ "deltas: actual %d expected %d ba_timeout %d\n",
+ actual_delta, expected_delta, ba_timeout_delta);
#ifdef CONFIG_IWLWIFI_DEBUGFS
/*
@@ -218,7 +311,7 @@ static bool iwl_good_ack_health(struct iwl_priv *priv,
* When the plcp error is exceeding the thresholds, reset the radio
* to improve the throughput.
*/
-static bool iwl_good_plcp_health(struct iwl_priv *priv,
+static bool iwlagn_good_plcp_health(struct iwl_priv *priv,
struct statistics_rx_phy *cur_ofdm,
struct statistics_rx_ht_phy *cur_ofdm_ht,
unsigned int msecs)
@@ -250,15 +343,15 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv,
return true;
}
-static void iwl_recover_from_statistics(struct iwl_priv *priv,
- struct statistics_rx_phy *cur_ofdm,
- struct statistics_rx_ht_phy *cur_ofdm_ht,
- struct statistics_tx *tx,
- unsigned long stamp)
+static void iwlagn_recover_from_statistics(struct iwl_priv *priv,
+ struct statistics_rx_phy *cur_ofdm,
+ struct statistics_rx_ht_phy *cur_ofdm_ht,
+ struct statistics_tx *tx,
+ unsigned long stamp)
{
unsigned int msecs;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
@@ -271,21 +364,21 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv,
if (msecs < 99)
return;
- if (iwlagn_mod_params.ack_check && !iwl_good_ack_health(priv, tx)) {
+ if (iwlagn_mod_params.ack_check && !iwlagn_good_ack_health(priv, tx)) {
IWL_ERR(priv, "low ack count detected, restart firmware\n");
if (!iwl_force_reset(priv, IWL_FW_RESET, false))
return;
}
if (iwlagn_mod_params.plcp_check &&
- !iwl_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs))
+ !iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs))
iwl_force_reset(priv, IWL_RF_RESET, false);
}
/* Calculate noise level, based on measurements during network silence just
* before arriving beacon. This measurement can be done only if we know
* exactly when to expect beacons, therefore only when we're associated. */
-static void iwl_rx_calc_noise(struct iwl_priv *priv)
+static void iwlagn_rx_calc_noise(struct iwl_priv *priv)
{
struct statistics_rx_non_phy *rx_info;
int num_active_rx = 0;
@@ -351,7 +444,7 @@ static void accum_stats(__le32 *prev, __le32 *cur, __le32 *delta,
}
static void
-iwl_accumulative_statistics(struct iwl_priv *priv,
+iwlagn_accumulative_statistics(struct iwl_priv *priv,
struct statistics_general_common *common,
struct statistics_rx_non_phy *rx_non_phy,
struct statistics_rx_phy *rx_ofdm,
@@ -380,7 +473,7 @@ iwl_accumulative_statistics(struct iwl_priv *priv,
}
#else
static inline void
-iwl_accumulative_statistics(struct iwl_priv *priv,
+iwlagn_accumulative_statistics(struct iwl_priv *priv,
struct statistics_general_common *common,
struct statistics_rx_non_phy *rx_non_phy,
struct statistics_rx_phy *rx_ofdm,
@@ -392,8 +485,9 @@ iwl_accumulative_statistics(struct iwl_priv *priv,
}
#endif
-static void iwl_rx_statistics(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_statistics(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
unsigned long stamp = jiffies;
const int reg_recalib_period = 60;
@@ -447,17 +541,17 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n",
len, sizeof(struct iwl_bt_notif_statistics),
sizeof(struct iwl_notif_statistics));
- return;
+ return 0;
}
change = common->temperature != priv->statistics.common.temperature ||
(*flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
(priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK);
- iwl_accumulative_statistics(priv, common, rx_non_phy, rx_ofdm,
+ iwlagn_accumulative_statistics(priv, common, rx_non_phy, rx_ofdm,
rx_ofdm_ht, rx_cck, tx, bt_activity);
- iwl_recover_from_statistics(priv, rx_ofdm, rx_ofdm_ht, tx, stamp);
+ iwlagn_recover_from_statistics(priv, rx_ofdm, rx_ofdm_ht, tx, stamp);
priv->statistics.flag = *flag;
memcpy(&priv->statistics.common, common, sizeof(*common));
@@ -474,7 +568,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
priv->rx_statistics_jiffies = stamp;
- set_bit(STATUS_STATISTICS, &priv->status);
+ set_bit(STATUS_STATISTICS, &priv->shrd->status);
/* Reschedule the statistics timer to occur in
* reg_recalib_period seconds to ensure we get a
@@ -483,17 +577,19 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
mod_timer(&priv->statistics_periodic, jiffies +
msecs_to_jiffies(reg_recalib_period * 1000));
- if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
+ if (unlikely(!test_bit(STATUS_SCANNING, &priv->shrd->status)) &&
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
- iwl_rx_calc_noise(priv);
- queue_work(priv->workqueue, &priv->run_time_calib_work);
+ iwlagn_rx_calc_noise(priv);
+ queue_work(priv->shrd->workqueue, &priv->run_time_calib_work);
}
if (priv->cfg->lib->temperature && change)
priv->cfg->lib->temperature(priv);
+ return 0;
}
-static void iwl_rx_reply_statistics(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_reply_statistics(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -508,17 +604,19 @@ static void iwl_rx_reply_statistics(struct iwl_priv *priv,
#endif
IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
}
- iwl_rx_statistics(priv, rxb);
+ iwlagn_rx_statistics(priv, rxb, cmd);
+ return 0;
}
/* Handle notification from uCode that card's power state is changing
* due to software, hardware, or critical temperature RFKILL */
-static void iwl_rx_card_state_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
- unsigned long status = priv->status;
+ unsigned long status = priv->shrd->status;
IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
@@ -529,16 +627,16 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
CT_CARD_DISABLED)) {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
- iwl_write_direct32(priv, HBUS_TARG_MBX_C,
+ iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
if (!(flags & RXON_CARD_DISABLED)) {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
- iwl_write_direct32(priv, HBUS_TARG_MBX_C,
+ iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
}
if (flags & CT_CARD_DISABLED)
@@ -548,24 +646,26 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
iwl_tt_exit_ct_kill(priv);
if (flags & HW_CARD_DISABLED)
- set_bit(STATUS_RF_KILL_HW, &priv->status);
+ set_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
else
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
if (!(flags & RXON_CARD_DISABLED))
iwl_scan_cancel(priv);
if ((test_bit(STATUS_RF_KILL_HW, &status) !=
- test_bit(STATUS_RF_KILL_HW, &priv->status)))
+ test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)))
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
- test_bit(STATUS_RF_KILL_HW, &priv->status));
+ test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
else
- wake_up_interruptible(&priv->wait_command_queue);
+ wake_up(&priv->shrd->wait_command_queue);
+ return 0;
}
-static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -580,27 +680,30 @@ static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
le32_to_cpu(missed_beacon->total_missed_becons),
le32_to_cpu(missed_beacon->num_recvd_beacons),
le32_to_cpu(missed_beacon->num_expected_beacons));
- if (!test_bit(STATUS_SCANNING, &priv->status))
+ if (!test_bit(STATUS_SCANNING, &priv->shrd->status))
iwl_init_sensitivity(priv);
}
+ return 0;
}
/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
* This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
-static void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
priv->last_phy_res_valid = true;
memcpy(&priv->last_phy_res, pkt->u.raw,
sizeof(struct iwl_rx_phy_res));
+ return 0;
}
/*
* returns non-zero if packet should be dropped
*/
-static int iwl_set_decrypted_flag(struct iwl_priv *priv,
+static int iwlagn_set_decrypted_flag(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,
u32 decrypt_res,
struct ieee80211_rx_status *stats)
@@ -649,7 +752,7 @@ static int iwl_set_decrypted_flag(struct iwl_priv *priv,
return 0;
}
-static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
+static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,
u16 len,
u32 ampdu_status,
@@ -669,7 +772,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
/* In case of HW accelerated crypto and bad decryption, drop */
if (!iwlagn_mod_params.sw_crypto &&
- iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
+ iwlagn_set_decrypted_flag(priv, hdr, ampdu_status, stats))
return;
skb = dev_alloc_skb(128);
@@ -697,7 +800,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
ctx->active.bssid_addr))
continue;
ctx->last_tx_rejected = false;
- iwl_wake_any_queue(priv, ctx);
+ iwl_trans_wake_any_queue(trans(priv), ctx->ctxid);
}
}
@@ -707,7 +810,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
rxb->page = NULL;
}
-static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
+static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
{
u32 decrypt_out = 0;
@@ -809,8 +912,9 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
/* Called for REPLY_RX (legacy ABG frames), or
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
-static void iwl_rx_reply_rx(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct ieee80211_hdr *header;
struct ieee80211_rx_status rx_status;
@@ -843,28 +947,28 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
} else {
if (!priv->last_phy_res_valid) {
IWL_ERR(priv, "MPDU frame without cached PHY data\n");
- return;
+ return 0;
}
phy_res = &priv->last_phy_res;
amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
len = le16_to_cpu(amsdu->byte_count);
rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
- ampdu_status = iwl_translate_rx_status(priv,
+ ampdu_status = iwlagn_translate_rx_status(priv,
le32_to_cpu(rx_pkt_status));
}
if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
phy_res->cfg_phy_cnt);
- return;
+ return 0;
}
if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
!(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
le32_to_cpu(rx_pkt_status));
- return;
+ return 0;
}
/* This will be used in several places later */
@@ -923,8 +1027,9 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
if (rate_n_flags & RATE_MCS_SGI_MSK)
rx_status.flag |= RX_FLAG_SHORT_GI;
- iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
+ iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status,
rxb, &rx_status);
+ return 0;
}
/**
@@ -935,36 +1040,42 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
*/
void iwl_setup_rx_handlers(struct iwl_priv *priv)
{
- void (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
+ int (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd);
handlers = priv->rx_handlers;
- handlers[REPLY_ERROR] = iwl_rx_reply_error;
- handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
- handlers[SPECTRUM_MEASURE_NOTIFICATION] = iwl_rx_spectrum_measure_notif;
- handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
- handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif;
- handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
+ handlers[REPLY_ERROR] = iwlagn_rx_reply_error;
+ handlers[CHANNEL_SWITCH_NOTIFICATION] = iwlagn_rx_csa;
+ handlers[SPECTRUM_MEASURE_NOTIFICATION] =
+ iwlagn_rx_spectrum_measure_notif;
+ handlers[PM_SLEEP_NOTIFICATION] = iwlagn_rx_pm_sleep_notif;
+ handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
+ iwlagn_rx_pm_debug_statistics_notif;
+ handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif;
+ handlers[REPLY_ADD_STA] = iwl_add_sta_callback;
/*
* The same handler is used for both the REPLY to a discrete
* statistics request from the host as well as for the periodic
* statistics notifications (after received beacons) from the uCode.
*/
- handlers[REPLY_STATISTICS_CMD] = iwl_rx_reply_statistics;
- handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
+ handlers[REPLY_STATISTICS_CMD] = iwlagn_rx_reply_statistics;
+ handlers[STATISTICS_NOTIFICATION] = iwlagn_rx_statistics;
iwl_setup_rx_scan_handlers(priv);
- handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
- handlers[MISSED_BEACONS_NOTIFICATION] = iwl_rx_missed_beacon_notif;
+ handlers[CARD_STATE_NOTIFICATION] = iwlagn_rx_card_state_notif;
+ handlers[MISSED_BEACONS_NOTIFICATION] =
+ iwlagn_rx_missed_beacon_notif;
/* Rx handlers */
- handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy;
- handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx;
+ handlers[REPLY_RX_PHY_CMD] = iwlagn_rx_reply_rx_phy;
+ handlers[REPLY_RX_MPDU_CMD] = iwlagn_rx_reply_rx;
/* block ack */
- handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba;
+ handlers[REPLY_COMPRESSED_BA] =
+ iwlagn_rx_reply_compressed_ba;
/* init calibration handlers */
priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
@@ -982,9 +1093,11 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
}
-void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ int err = 0;
/*
* Do the notification wait before RX handlers so
@@ -1018,12 +1131,13 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
* handle those that need handling via function in
* rx_handlers table. See iwl_setup_rx_handlers() */
if (priv->rx_handlers[pkt->hdr.cmd]) {
- priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
- priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+ priv->rx_handlers_stats[pkt->hdr.cmd]++;
+ err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd);
} else {
/* No handling needed */
IWL_DEBUG_RX(priv,
"No handler needed for %s, 0x%02x\n",
get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
}
+ return err;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index d42ef1763a71..58a381c01c89 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -26,11 +26,10 @@
#include "iwl-dev.h"
#include "iwl-agn.h"
-#include "iwl-sta.h"
#include "iwl-core.h"
#include "iwl-agn-calib.h"
-#include "iwl-helpers.h"
#include "iwl-trans.h"
+#include "iwl-shared.h"
static int iwlagn_disable_bss(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
@@ -40,7 +39,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,
int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd,
+ ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd,
CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter;
@@ -66,7 +65,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
send->dev_type = RXON_DEV_TYPE_P2P;
- ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd,
+ ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd,
CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter;
@@ -92,7 +91,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv,
int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC,
+ ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC,
sizeof(*send), send);
send->filter_flags = old_filter;
@@ -121,7 +120,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
ctx->qos_data.qos_active,
ctx->qos_data.def_qos_parm.qos_flags);
- ret = trans_send_cmd_pdu(&priv->trans, ctx->qos_cmd, CMD_SYNC,
+ ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->qos_cmd, CMD_SYNC,
sizeof(struct iwl_qosparam_cmd),
&ctx->qos_data.def_qos_parm);
if (ret)
@@ -131,7 +130,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
static int iwlagn_update_beacon(struct iwl_priv *priv,
struct ieee80211_vif *vif)
{
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif);
@@ -180,7 +179,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
ctx->staging.ofdm_ht_triple_stream_basic_rates;
rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
- ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_assoc_cmd,
+ ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_assoc_cmd,
CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc);
return ret;
}
@@ -266,7 +265,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
* Associated RXON doesn't clear the station table in uCode,
* so we don't need to restore stations etc. after this.
*/
- ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC,
+ ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC,
sizeof(struct iwl_rxon_cmd), &ctx->staging);
if (ret) {
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
@@ -295,8 +294,8 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
return ret;
}
- if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) &&
- priv->cfg->ht_params->smps_mode)
+ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION &&
+ priv->cfg->ht_params && priv->cfg->ht_params->smps_mode)
ieee80211_request_smps(ctx->vif,
priv->cfg->ht_params->smps_mode);
@@ -310,12 +309,12 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
int slot0 = 300, slot1 = 0;
int ret;
- if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
+ if (priv->shrd->valid_contexts == BIT(IWL_RXON_CTX_BSS))
return 0;
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
@@ -337,10 +336,10 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
cmd.slots[0].type = 0; /* BSS */
cmd.slots[1].type = 1; /* PAN */
- if (priv->hw_roc_channel) {
+ if (priv->hw_roc_setup) {
/* both contexts must be used for this to happen */
- slot1 = priv->hw_roc_duration;
- slot0 = IWL_MIN_SLOT_TIME;
+ slot1 = IWL_MIN_SLOT_TIME;
+ slot0 = 3000;
} else if (ctx_bss->vif && ctx_pan->vif) {
int bcnint = ctx_pan->beacon_int;
int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
@@ -362,14 +361,14 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
slot0 = bcnint / 2;
slot1 = bcnint - slot0;
- if (test_bit(STATUS_SCAN_HW, &priv->status) ||
+ if (test_bit(STATUS_SCAN_HW, &priv->shrd->status) ||
(!ctx_bss->vif->bss_conf.idle &&
!ctx_bss->vif->bss_conf.assoc)) {
slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
slot1 = IWL_MIN_SLOT_TIME;
} else if (!ctx_pan->vif->bss_conf.idle &&
!ctx_pan->vif->bss_conf.assoc) {
- slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME;
+ slot1 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
slot0 = IWL_MIN_SLOT_TIME;
}
} else if (ctx_pan->vif) {
@@ -378,7 +377,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
ctx_pan->beacon_int;
slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
- if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+ if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
slot1 = IWL_MIN_SLOT_TIME;
}
@@ -387,7 +386,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
cmd.slots[0].width = cpu_to_le16(slot0);
cmd.slots[1].width = cpu_to_le16(slot1);
- ret = trans_send_cmd_pdu(&priv->trans, REPLY_WIPAN_PARAMS, CMD_SYNC,
+ ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WIPAN_PARAMS, CMD_SYNC,
sizeof(cmd), &cmd);
if (ret)
IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
@@ -420,12 +419,12 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
int ret;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return -EINVAL;
- if (!iwl_is_alive(priv))
+ if (!iwl_is_alive(priv->shrd))
return -EBUSY;
/* This function hardcodes a bunch of dual-mode assumptions */
@@ -434,26 +433,13 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
if (!ctx->is_active)
return 0;
+ /* override BSSID if necessary due to preauth */
+ if (ctx->preauth_bssid)
+ memcpy(ctx->staging.bssid_addr, ctx->bssid, ETH_ALEN);
+
/* always get timestamp with Rx frame */
ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
- if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->hw_roc_channel) {
- struct ieee80211_channel *chan = priv->hw_roc_channel;
-
- iwl_set_rxon_channel(priv, chan, ctx);
- iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
- ctx->staging.filter_flags |=
- RXON_FILTER_ASSOC_MSK |
- RXON_FILTER_PROMISC_MSK |
- RXON_FILTER_CTL2HOST_MSK;
- ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
- new_assoc = true;
-
- if (memcmp(&ctx->staging, &ctx->active,
- sizeof(ctx->staging)) == 0)
- return 0;
- }
-
/*
* force CTS-to-self frames protection if RTS-CTS is not preferred
* one aggregation protection method
@@ -468,7 +454,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
else
ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
- iwl_print_rx_config_cmd(priv, ctx);
+ iwl_print_rx_config_cmd(priv, ctx->ctxid);
ret = iwl_check_rxon_cmd(priv, ctx);
if (ret) {
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
@@ -479,7 +465,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
* receive commit_rxon request
* abort any previous channel switch if still in process
*/
- if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) &&
+ if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status) &&
(priv->switch_channel != ctx->staging.channel)) {
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
le16_to_cpu(priv->switch_channel));
@@ -551,16 +537,16 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
const struct iwl_channel_info *ch_info;
int ret = 0;
- IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
+ IWL_DEBUG_MAC80211(priv, "enter: changed %#x", changed);
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
- if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
+ if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) {
IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
goto out;
}
- if (!iwl_is_ready(priv)) {
+ if (!iwl_is_ready(priv->shrd)) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
goto out;
}
@@ -592,7 +578,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
goto out;
}
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->shrd->lock, flags);
for_each_context(priv, ctx) {
/* Configure HT40 channels */
@@ -636,7 +622,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
ctx->vif);
}
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
iwl_update_bcast_stations(priv);
@@ -668,7 +654,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
iwlagn_commit_rxon(priv, ctx);
}
out:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+
return ret;
}
@@ -683,7 +671,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *ht_cap;
bool need_multiple;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
switch (vif->type) {
case NL80211_IFTYPE_STATION:
@@ -787,7 +775,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
memset(&cmd, 0, sizeof(cmd));
iwl_set_calib_hdr(&cmd.hdr,
priv->phy_calib_chain_noise_reset_cmd);
- ret = trans_send_cmd_pdu(&priv->trans,
+ ret = iwl_trans_send_cmd_pdu(trans(priv),
REPLY_PHY_CALIBRATION_CMD,
CMD_SYNC, sizeof(cmd), &cmd);
if (ret)
@@ -808,17 +796,17 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
int ret;
bool force = false;
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
- if (unlikely(!iwl_is_ready(priv))) {
+ if (unlikely(!iwl_is_ready(priv->shrd))) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
return;
}
if (unlikely(!ctx->vif)) {
IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n");
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
return;
}
@@ -851,7 +839,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
*/
if (ctx->last_tx_rejected) {
ctx->last_tx_rejected = false;
- iwl_wake_any_queue(priv, ctx);
+ iwl_trans_wake_any_queue(trans(priv),
+ ctx->ctxid);
}
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
@@ -912,6 +901,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
if (!priv->disable_chain_noise_cal)
iwlagn_chain_noise_reset(priv);
priv->start_calib = 1;
+ WARN_ON(ctx->preauth_bssid);
}
if (changes & BSS_CHANGED_IBSS) {
@@ -929,7 +919,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
IWL_ERR(priv, "Error sending IBSS beacon\n");
}
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
void iwlagn_post_scan(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index 37e624095e40..ed6283623932 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -31,25 +31,833 @@
#include "iwl-dev.h"
#include "iwl-core.h"
-#include "iwl-sta.h"
#include "iwl-agn.h"
#include "iwl-trans.h"
-static struct iwl_link_quality_cmd *
-iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)
+/* priv->shrd->sta_lock must be held */
+static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
+{
+
+ if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
+ IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u "
+ "addr %pM\n",
+ sta_id, priv->stations[sta_id].sta.sta.addr);
+
+ if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) {
+ IWL_DEBUG_ASSOC(priv,
+ "STA id %u addr %pM already present in uCode "
+ "(according to driver)\n",
+ sta_id, priv->stations[sta_id].sta.sta.addr);
+ } else {
+ priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
+ IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n",
+ sta_id, priv->stations[sta_id].sta.sta.addr);
+ }
+}
+
+static int iwl_process_add_sta_resp(struct iwl_priv *priv,
+ struct iwl_addsta_cmd *addsta,
+ struct iwl_rx_packet *pkt)
+{
+ u8 sta_id = addsta->sta.sta_id;
+ unsigned long flags;
+ int ret = -EIO;
+
+ if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+ IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
+ pkt->hdr.flags);
+ return ret;
+ }
+
+ IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
+ sta_id);
+
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+
+ switch (pkt->u.add_sta.status) {
+ case ADD_STA_SUCCESS_MSK:
+ IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
+ iwl_sta_ucode_activate(priv, sta_id);
+ ret = 0;
+ break;
+ case ADD_STA_NO_ROOM_IN_TABLE:
+ IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
+ sta_id);
+ break;
+ case ADD_STA_NO_BLOCK_ACK_RESOURCE:
+ IWL_ERR(priv, "Adding station %d failed, no block ack "
+ "resource.\n", sta_id);
+ break;
+ case ADD_STA_MODIFY_NON_EXIST_STA:
+ IWL_ERR(priv, "Attempting to modify non-existing station %d\n",
+ sta_id);
+ break;
+ default:
+ IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
+ pkt->u.add_sta.status);
+ break;
+ }
+
+ IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n",
+ priv->stations[sta_id].sta.mode ==
+ STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
+ sta_id, priv->stations[sta_id].sta.sta.addr);
+
+ /*
+ * XXX: The MAC address in the command buffer is often changed from
+ * the original sent to the device. That is, the MAC address
+ * written to the command buffer often is not the same MAC address
+ * read from the command buffer when the command returns. This
+ * issue has not yet been resolved and this debugging is left to
+ * observe the problem.
+ */
+ IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n",
+ priv->stations[sta_id].sta.mode ==
+ STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
+ addsta->sta.addr);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+
+ return ret;
+}
+
+int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_addsta_cmd *addsta =
+ (struct iwl_addsta_cmd *) cmd->payload;
+
+ return iwl_process_add_sta_resp(priv, addsta, pkt);
+}
+
+static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
+{
+ u16 size = (u16)sizeof(struct iwl_addsta_cmd);
+ struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
+ memcpy(addsta, cmd, size);
+ /* resrved in 5000 */
+ addsta->rate_n_flags = cpu_to_le16(0);
+ return size;
+}
+
+int iwl_send_add_sta(struct iwl_priv *priv,
+ struct iwl_addsta_cmd *sta, u8 flags)
+{
+ int ret = 0;
+ u8 data[sizeof(*sta)];
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_ADD_STA,
+ .flags = flags,
+ .data = { data, },
+ };
+ u8 sta_id __maybe_unused = sta->sta.sta_id;
+
+ IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n",
+ sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : "");
+
+ if (!(flags & CMD_ASYNC)) {
+ cmd.flags |= CMD_WANT_SKB;
+ might_sleep();
+ }
+
+ cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data);
+ ret = iwl_trans_send_cmd(trans(priv), &cmd);
+
+ if (ret || (flags & CMD_ASYNC))
+ return ret;
+ /*else the command was successfully sent in SYNC mode, need to free
+ * the reply page */
+
+ iwl_free_pages(priv->shrd, cmd.reply_page);
+
+ if (cmd.handler_status)
+ IWL_ERR(priv, "%s - error in the CMD response %d", __func__,
+ cmd.handler_status);
+
+ return cmd.handler_status;
+}
+
+static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
+ struct ieee80211_sta *sta,
+ struct iwl_rxon_context *ctx)
+{
+ struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
+ __le32 sta_flags;
+ u8 mimo_ps_mode;
+
+ if (!sta || !sta_ht_inf->ht_supported)
+ goto done;
+
+ mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
+ IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
+ (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
+ "static" :
+ (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
+ "dynamic" : "disabled");
+
+ sta_flags = priv->stations[index].sta.station_flags;
+
+ sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
+
+ switch (mimo_ps_mode) {
+ case WLAN_HT_CAP_SM_PS_STATIC:
+ sta_flags |= STA_FLG_MIMO_DIS_MSK;
+ break;
+ case WLAN_HT_CAP_SM_PS_DYNAMIC:
+ sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
+ break;
+ case WLAN_HT_CAP_SM_PS_DISABLED:
+ break;
+ default:
+ IWL_WARN(priv, "Invalid MIMO PS mode %d\n", mimo_ps_mode);
+ break;
+ }
+
+ sta_flags |= cpu_to_le32(
+ (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
+
+ sta_flags |= cpu_to_le32(
+ (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
+
+ if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
+ sta_flags |= STA_FLG_HT40_EN_MSK;
+ else
+ sta_flags &= ~STA_FLG_HT40_EN_MSK;
+
+ priv->stations[index].sta.station_flags = sta_flags;
+ done:
+ return;
+}
+
+/**
+ * iwl_prep_station - Prepare station information for addition
+ *
+ * should be called with sta_lock held
+ */
+u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ const u8 *addr, bool is_ap, struct ieee80211_sta *sta)
+{
+ struct iwl_station_entry *station;
+ int i;
+ u8 sta_id = IWL_INVALID_STATION;
+
+ if (is_ap)
+ sta_id = ctx->ap_sta_id;
+ else if (is_broadcast_ether_addr(addr))
+ sta_id = ctx->bcast_sta_id;
+ else
+ for (i = IWL_STA_ID; i < IWLAGN_STATION_COUNT; i++) {
+ if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+ addr)) {
+ sta_id = i;
+ break;
+ }
+
+ if (!priv->stations[i].used &&
+ sta_id == IWL_INVALID_STATION)
+ sta_id = i;
+ }
+
+ /*
+ * These two conditions have the same outcome, but keep them
+ * separate
+ */
+ if (unlikely(sta_id == IWL_INVALID_STATION))
+ return sta_id;
+
+ /*
+ * uCode is not able to deal with multiple requests to add a
+ * station. Keep track if one is in progress so that we do not send
+ * another.
+ */
+ if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
+ IWL_DEBUG_INFO(priv, "STA %d already in process of being "
+ "added.\n", sta_id);
+ return sta_id;
+ }
+
+ if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
+ (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) &&
+ !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) {
+ IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not "
+ "adding again.\n", sta_id, addr);
+ return sta_id;
+ }
+
+ station = &priv->stations[sta_id];
+ station->used = IWL_STA_DRIVER_ACTIVE;
+ IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n",
+ sta_id, addr);
+ priv->num_stations++;
+
+ /* Set up the REPLY_ADD_STA command to send to device */
+ memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
+ memcpy(station->sta.sta.addr, addr, ETH_ALEN);
+ station->sta.mode = 0;
+ station->sta.sta.sta_id = sta_id;
+ station->sta.station_flags = ctx->station_flags;
+ station->ctxid = ctx->ctxid;
+
+ if (sta) {
+ struct iwl_station_priv *sta_priv;
+
+ sta_priv = (void *)sta->drv_priv;
+ sta_priv->ctx = ctx;
+ }
+
+ /*
+ * OK to call unconditionally, since local stations (IBSS BSSID
+ * STA and broadcast STA) pass in a NULL sta, and mac80211
+ * doesn't allow HT IBSS.
+ */
+ iwl_set_ht_add_station(priv, sta_id, sta, ctx);
+
+ return sta_id;
+
+}
+
+#define STA_WAIT_TIMEOUT (HZ/2)
+
+/**
+ * iwl_add_station_common -
+ */
+int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ const u8 *addr, bool is_ap,
+ struct ieee80211_sta *sta, u8 *sta_id_r)
+{
+ unsigned long flags_spin;
+ int ret = 0;
+ u8 sta_id;
+ struct iwl_addsta_cmd sta_cmd;
+
+ *sta_id_r = 0;
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta);
+ if (sta_id == IWL_INVALID_STATION) {
+ IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
+ addr);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ return -EINVAL;
+ }
+
+ /*
+ * uCode is not able to deal with multiple requests to add a
+ * station. Keep track if one is in progress so that we do not send
+ * another.
+ */
+ if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
+ IWL_DEBUG_INFO(priv, "STA %d already in process of being "
+ "added.\n", sta_id);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ return -EEXIST;
+ }
+
+ if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
+ (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
+ IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not "
+ "adding again.\n", sta_id, addr);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ return -EEXIST;
+ }
+
+ priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
+ memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+ sizeof(struct iwl_addsta_cmd));
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+
+ /* Add station to device's station table */
+ ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+ if (ret) {
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ IWL_ERR(priv, "Adding station %pM failed.\n",
+ priv->stations[sta_id].sta.sta.addr);
+ priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+ priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ }
+ *sta_id_r = sta_id;
+ return ret;
+}
+
+/**
+ * iwl_sta_ucode_deactivate - deactivate ucode status for a station
+ *
+ * priv->shrd->sta_lock must be held
+ */
+static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
+{
+ /* Ucode must be active and driver must be non active */
+ if ((priv->stations[sta_id].used &
+ (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) !=
+ IWL_STA_UCODE_ACTIVE)
+ IWL_ERR(priv, "removed non active STA %u\n", sta_id);
+
+ priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
+
+ memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry));
+ IWL_DEBUG_ASSOC(priv, "Removed STA %u\n", sta_id);
+}
+
+static int iwl_send_remove_station(struct iwl_priv *priv,
+ const u8 *addr, int sta_id,
+ bool temporary)
+{
+ struct iwl_rx_packet *pkt;
+ int ret;
+
+ unsigned long flags_spin;
+ struct iwl_rem_sta_cmd rm_sta_cmd;
+
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_REMOVE_STA,
+ .len = { sizeof(struct iwl_rem_sta_cmd), },
+ .flags = CMD_SYNC,
+ .data = { &rm_sta_cmd, },
+ };
+
+ memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
+ rm_sta_cmd.num_sta = 1;
+ memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN);
+
+ cmd.flags |= CMD_WANT_SKB;
+
+ ret = iwl_trans_send_cmd(trans(priv), &cmd);
+
+ if (ret)
+ return ret;
+
+ pkt = (struct iwl_rx_packet *)cmd.reply_page;
+ if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+ IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
+ pkt->hdr.flags);
+ ret = -EIO;
+ }
+
+ if (!ret) {
+ switch (pkt->u.rem_sta.status) {
+ case REM_STA_SUCCESS_MSK:
+ if (!temporary) {
+ spin_lock_irqsave(&priv->shrd->sta_lock,
+ flags_spin);
+ iwl_sta_ucode_deactivate(priv, sta_id);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock,
+ flags_spin);
+ }
+ IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
+ break;
+ default:
+ ret = -EIO;
+ IWL_ERR(priv, "REPLY_REMOVE_STA failed\n");
+ break;
+ }
+ }
+ iwl_free_pages(priv->shrd, cmd.reply_page);
+
+ return ret;
+}
+
+/**
+ * iwl_remove_station - Remove driver's knowledge of station.
+ */
+int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
+ const u8 *addr)
+{
+ unsigned long flags;
+
+ if (!iwl_is_ready(priv->shrd)) {
+ IWL_DEBUG_INFO(priv,
+ "Unable to remove station %pM, device not ready.\n",
+ addr);
+ /*
+ * It is typical for stations to be removed when we are
+ * going down. Return success since device will be down
+ * soon anyway
+ */
+ return 0;
+ }
+
+ IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n",
+ sta_id, addr);
+
+ if (WARN_ON(sta_id == IWL_INVALID_STATION))
+ return -EINVAL;
+
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+
+ if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+ IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
+ addr);
+ goto out_err;
+ }
+
+ if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
+ IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n",
+ addr);
+ goto out_err;
+ }
+
+ if (priv->stations[sta_id].used & IWL_STA_LOCAL) {
+ kfree(priv->stations[sta_id].lq);
+ priv->stations[sta_id].lq = NULL;
+ }
+
+ priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+
+ priv->num_stations--;
+
+ if (WARN_ON(priv->num_stations < 0))
+ priv->num_stations = 0;
+
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+
+ return iwl_send_remove_station(priv, addr, sta_id, false);
+out_err:
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ return -EINVAL;
+}
+
+/**
+ * iwl_clear_ucode_stations - clear ucode station table bits
+ *
+ * This function clears all the bits in the driver indicating
+ * which stations are active in the ucode. Call when something
+ * other than explicit station management would cause this in
+ * the ucode, e.g. unassociated RXON.
+ */
+void iwl_clear_ucode_stations(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
+{
+ int i;
+ unsigned long flags_spin;
+ bool cleared = false;
+
+ IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
+
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
+ if (ctx && ctx->ctxid != priv->stations[i].ctxid)
+ continue;
+
+ if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
+ IWL_DEBUG_INFO(priv,
+ "Clearing ucode active for station %d\n", i);
+ priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
+ cleared = true;
+ }
+ }
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+
+ if (!cleared)
+ IWL_DEBUG_INFO(priv,
+ "No active stations found to be cleared\n");
+}
+
+/**
+ * iwl_restore_stations() - Restore driver known stations to device
+ *
+ * All stations considered active by driver, but not present in ucode, is
+ * restored.
+ *
+ * Function sleeps.
+ */
+void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+ struct iwl_addsta_cmd sta_cmd;
+ struct iwl_link_quality_cmd lq;
+ unsigned long flags_spin;
+ int i;
+ bool found = false;
+ int ret;
+ bool send_lq;
+
+ if (!iwl_is_ready(priv->shrd)) {
+ IWL_DEBUG_INFO(priv,
+ "Not ready yet, not restoring any stations.\n");
+ return;
+ }
+
+ IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
+ if (ctx->ctxid != priv->stations[i].ctxid)
+ continue;
+ if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) &&
+ !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) {
+ IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n",
+ priv->stations[i].sta.sta.addr);
+ priv->stations[i].sta.mode = 0;
+ priv->stations[i].used |= IWL_STA_UCODE_INPROGRESS;
+ found = true;
+ }
+ }
+
+ for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
+ if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) {
+ memcpy(&sta_cmd, &priv->stations[i].sta,
+ sizeof(struct iwl_addsta_cmd));
+ send_lq = false;
+ if (priv->stations[i].lq) {
+ if (priv->shrd->wowlan)
+ iwl_sta_fill_lq(priv, ctx, i, &lq);
+ else
+ memcpy(&lq, priv->stations[i].lq,
+ sizeof(struct iwl_link_quality_cmd));
+ send_lq = true;
+ }
+ spin_unlock_irqrestore(&priv->shrd->sta_lock,
+ flags_spin);
+ ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+ if (ret) {
+ spin_lock_irqsave(&priv->shrd->sta_lock,
+ flags_spin);
+ IWL_ERR(priv, "Adding station %pM failed.\n",
+ priv->stations[i].sta.sta.addr);
+ priv->stations[i].used &=
+ ~IWL_STA_DRIVER_ACTIVE;
+ priv->stations[i].used &=
+ ~IWL_STA_UCODE_INPROGRESS;
+ spin_unlock_irqrestore(&priv->shrd->sta_lock,
+ flags_spin);
+ }
+ /*
+ * Rate scaling has already been initialized, send
+ * current LQ command
+ */
+ if (send_lq)
+ iwl_send_lq_cmd(priv, ctx, &lq,
+ CMD_SYNC, true);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
+ }
+ }
+
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ if (!found)
+ IWL_DEBUG_INFO(priv, "Restoring all known stations .... "
+ "no stations to be restored.\n");
+ else
+ IWL_DEBUG_INFO(priv, "Restoring all known stations .... "
+ "complete.\n");
+}
+
+void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+ unsigned long flags;
+ int sta_id = ctx->ap_sta_id;
+ int ret;
+ struct iwl_addsta_cmd sta_cmd;
+ struct iwl_link_quality_cmd lq;
+ bool active;
+
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ return;
+ }
+
+ memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
+ sta_cmd.mode = 0;
+ memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq));
+
+ active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
+ priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+
+ if (active) {
+ ret = iwl_send_remove_station(
+ priv, priv->stations[sta_id].sta.sta.addr,
+ sta_id, true);
+ if (ret)
+ IWL_ERR(priv, "failed to remove STA %pM (%d)\n",
+ priv->stations[sta_id].sta.sta.addr, ret);
+ }
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+
+ ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+ if (ret)
+ IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
+ priv->stations[sta_id].sta.sta.addr, ret);
+ iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
+}
+
+int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->sta_key_max_num; i++)
+ if (!test_and_set_bit(i, &priv->ucode_key_table))
+ return i;
+
+ return WEP_INVALID_OFFSET;
+}
+
+void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
+{
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
+ if (!(priv->stations[i].used & IWL_STA_BCAST))
+ continue;
+
+ priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
+ priv->num_stations--;
+ if (WARN_ON(priv->num_stations < 0))
+ priv->num_stations = 0;
+ kfree(priv->stations[i].lq);
+ priv->stations[i].lq = NULL;
+ }
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+static void iwl_dump_lq_cmd(struct iwl_priv *priv,
+ struct iwl_link_quality_cmd *lq)
+{
+ int i;
+ IWL_DEBUG_RATE(priv, "lq station id 0x%x\n", lq->sta_id);
+ IWL_DEBUG_RATE(priv, "lq ant 0x%X 0x%X\n",
+ lq->general_params.single_stream_ant_msk,
+ lq->general_params.dual_stream_ant_msk);
+
+ for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+ IWL_DEBUG_RATE(priv, "lq index %d 0x%X\n",
+ i, lq->rs_table[i].rate_n_flags);
+}
+#else
+static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
+ struct iwl_link_quality_cmd *lq)
+{
+}
+#endif
+
+/**
+ * is_lq_table_valid() - Test one aspect of LQ cmd for validity
+ *
+ * It sometimes happens when a HT rate has been in use and we
+ * loose connectivity with AP then mac80211 will first tell us that the
+ * current channel is not HT anymore before removing the station. In such a
+ * scenario the RXON flags will be updated to indicate we are not
+ * communicating HT anymore, but the LQ command may still contain HT rates.
+ * Test for this to prevent driver from sending LQ command between the time
+ * RXON flags are updated and when LQ command is updated.
+ */
+static bool is_lq_table_valid(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct iwl_link_quality_cmd *lq)
+{
+ int i;
+
+ if (ctx->ht.enabled)
+ return true;
+
+ IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n",
+ ctx->active.channel);
+ for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+ if (le32_to_cpu(lq->rs_table[i].rate_n_flags) &
+ RATE_MCS_HT_MSK) {
+ IWL_DEBUG_INFO(priv,
+ "index %d of LQ expects HT channel\n",
+ i);
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * iwl_send_lq_cmd() - Send link quality command
+ * @init: This command is sent as part of station initialization right
+ * after station has been added.
+ *
+ * The link quality command is sent as the last step of station creation.
+ * This is the special case in which init is set and we call a callback in
+ * this case to clear the state indicating that station creation is in
+ * progress.
+ */
+int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ struct iwl_link_quality_cmd *lq, u8 flags, bool init)
+{
+ int ret = 0;
+ unsigned long flags_spin;
+
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_TX_LINK_QUALITY_CMD,
+ .len = { sizeof(struct iwl_link_quality_cmd), },
+ .flags = flags,
+ .data = { lq, },
+ };
+
+ if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
+ return -EINVAL;
+
+
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ return -EINVAL;
+ }
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+
+ iwl_dump_lq_cmd(priv, lq);
+ if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
+ return -EINVAL;
+
+ if (is_lq_table_valid(priv, ctx, lq))
+ ret = iwl_trans_send_cmd(trans(priv), &cmd);
+ else
+ ret = -EINVAL;
+
+ if (cmd.flags & CMD_ASYNC)
+ return ret;
+
+ if (init) {
+ IWL_DEBUG_INFO(priv, "init LQ command complete, "
+ "clearing sta addition status for sta %d\n",
+ lq->sta_id);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+ priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+ }
+ return ret;
+}
+
+int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_priv *priv = hw->priv;
+ struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+ int ret;
+
+ IWL_DEBUG_MAC80211(priv, "enter: received request to remove "
+ "station %pM\n", sta->addr);
+ mutex_lock(&priv->shrd->mutex);
+ IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
+ sta->addr);
+ ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr);
+ if (ret)
+ IWL_ERR(priv, "Error removing station %pM\n",
+ sta->addr);
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+
+ return ret;
+}
+
+void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ u8 sta_id, struct iwl_link_quality_cmd *link_cmd)
{
int i, r;
- struct iwl_link_quality_cmd *link_cmd;
u32 rate_flags = 0;
__le32 rate_n_flags;
- link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
- if (!link_cmd) {
- IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
- return NULL;
- }
+ lockdep_assert_held(&priv->shrd->mutex);
- lockdep_assert_held(&priv->mutex);
+ memset(link_cmd, 0, sizeof(*link_cmd));
/* Set up the rate scaling to start at selected rate, fall back
* all the way down to 1M in IEEE order, and then spin on 1M */
@@ -63,30 +871,46 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)
if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
rate_flags |= RATE_MCS_CCK_MSK;
- rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
+ rate_flags |= first_antenna(hw_params(priv).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->hw_params.valid_tx_ant);
+ first_antenna(hw_params(priv).valid_tx_ant);
link_cmd->general_params.dual_stream_ant_msk =
- priv->hw_params.valid_tx_ant &
- ~first_antenna(priv->hw_params.valid_tx_ant);
+ hw_params(priv).valid_tx_ant &
+ ~first_antenna(hw_params(priv).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->hw_params.valid_tx_ant) == 2) {
+ } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) {
link_cmd->general_params.dual_stream_ant_msk =
- priv->hw_params.valid_tx_ant;
+ hw_params(priv).valid_tx_ant;
}
- link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+ link_cmd->agg_params.agg_dis_start_th =
+ LINK_QUAL_AGG_DISABLE_START_DEF;
link_cmd->agg_params.agg_time_limit =
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
link_cmd->sta_id = sta_id;
+}
+
+static struct iwl_link_quality_cmd *
+iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ u8 sta_id)
+{
+ struct iwl_link_quality_cmd *link_cmd;
+
+ link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
+ if (!link_cmd) {
+ IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
+ return NULL;
+ }
+
+ iwl_sta_fill_lq(priv, ctx, sta_id, link_cmd);
return link_cmd;
}
@@ -96,7 +920,8 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)
*
* Function sleeps.
*/
-int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+int iwlagn_add_bssid_station(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
const u8 *addr, u8 *sta_id_r)
{
int ret;
@@ -116,14 +941,15 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx
if (sta_id_r)
*sta_id_r = sta_id;
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].used |= IWL_STA_LOCAL;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
/* Set up default rate scaling table in device's station table */
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
if (!link_cmd) {
- IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
+ IWL_ERR(priv,
+ "Unable to initialize rate scaling for station %pM.\n",
addr);
return -ENOMEM;
}
@@ -132,9 +958,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx
if (ret)
IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].lq = link_cmd;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return 0;
}
@@ -189,7 +1015,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
cmd.len[0] = cmd_size;
if (not_empty || send_if_empty)
- return trans_send_cmd(&priv->trans, &cmd);
+ return iwl_trans_send_cmd(trans(priv), &cmd);
else
return 0;
}
@@ -197,7 +1023,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
return iwl_send_static_wepkey_cmd(priv, ctx, false);
}
@@ -208,14 +1034,15 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
{
int ret;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
keyconf->keyidx);
memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
- if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
+ if (iwl_is_rfkill(priv->shrd)) {
+ IWL_DEBUG_WEP(priv,
+ "Not sending REPLY_WEPKEY command due to RFKILL.\n");
/* but keys in device are clear anyway so return success */
return 0;
}
@@ -232,11 +1059,12 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
{
int ret;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
if (keyconf->keylen != WEP_KEY_LEN_128 &&
keyconf->keylen != WEP_KEY_LEN_64) {
- IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen);
+ IWL_DEBUG_WEP(priv,
+ "Bad WEP key length %d\n", keyconf->keylen);
return -EINVAL;
}
@@ -311,9 +1139,9 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv,
struct iwl_addsta_cmd sta_cmd;
int i;
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
key_flags |= STA_KEY_FLG_MAP_KEY_MSK;
@@ -388,16 +1216,16 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
if (sta_id == IWL_INVALID_STATION)
return -ENOENT;
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE))
sta_id = IWL_INVALID_STATION;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
if (sta_id == IWL_INVALID_STATION)
return 0;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
ctx->key_mapping_keys--;
@@ -430,7 +1258,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
if (sta_id == IWL_INVALID_STATION)
return -EINVAL;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv);
if (keyconf->hw_key_idx == WEP_INVALID_OFFSET)
@@ -493,18 +1321,18 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
unsigned long flags;
u8 sta_id;
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
if (sta_id == IWL_INVALID_STATION) {
IWL_ERR(priv, "Unable to prepare broadcast station\n");
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return -EINVAL;
}
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
priv->stations[sta_id].used |= IWL_STA_BCAST;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
if (!link_cmd) {
@@ -513,9 +1341,9 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
return -ENOMEM;
}
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].lq = link_cmd;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return 0;
}
@@ -539,13 +1367,13 @@ int iwl_update_bcast_station(struct iwl_priv *priv,
return -ENOMEM;
}
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
if (priv->stations[sta_id].lq)
kfree(priv->stations[sta_id].lq);
else
IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
priv->stations[sta_id].lq = link_cmd;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return 0;
}
@@ -572,15 +1400,15 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
unsigned long flags;
struct iwl_addsta_cmd sta_cmd;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
/* Remove "disable" flag, to enable Tx for this TID */
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
@@ -592,20 +1420,20 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
int sta_id;
struct iwl_addsta_cmd sta_cmd;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
sta_id = iwl_sta_id(sta);
if (sta_id == IWL_INVALID_STATION)
return -ENXIO;
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.station_flags_msk = 0;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
@@ -617,7 +1445,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
int sta_id;
struct iwl_addsta_cmd sta_cmd;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
sta_id = iwl_sta_id(sta);
if (sta_id == IWL_INVALID_STATION) {
@@ -625,13 +1453,13 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
return -ENXIO;
}
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.station_flags_msk = 0;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
@@ -640,14 +1468,14 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
{
unsigned long flags;
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
priv->stations[sta_id].sta.sta.modify_mask = 0;
priv->stations[sta_id].sta.sleep_tx_count = 0;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
}
@@ -655,7 +1483,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
{
unsigned long flags;
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
priv->stations[sta_id].sta.sta.modify_mask =
@@ -663,7 +1491,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
}
@@ -676,6 +1504,8 @@ void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
int sta_id;
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+
switch (cmd) {
case STA_NOTIFY_SLEEP:
WARN_ON(!sta_priv->client);
@@ -695,4 +1525,5 @@ void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
default:
break;
}
+ IWL_DEBUG_MAC80211(priv, "leave\n");
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
index f501d742984c..c27180a73351 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
@@ -114,9 +114,6 @@ static bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
s32 temp = priv->temperature; /* degrees CELSIUS except specified */
bool within_margin = false;
- if (priv->cfg->base_params->temperature_kelvin)
- temp = KELVIN_TO_CELSIUS(priv->temperature);
-
if (!priv->thermal_throttle.advanced_tt)
within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
CT_KILL_THRESHOLD_LEGACY) ? true : false;
@@ -176,24 +173,24 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
unsigned long flags;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
if (tt->state == IWL_TI_CT_KILL) {
if (priv->thermal_throttle.ct_kill_toggle) {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
priv->thermal_throttle.ct_kill_toggle = false;
} else {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
priv->thermal_throttle.ct_kill_toggle = true;
}
- iwl_read32(priv, CSR_UCODE_DRV_GP1);
- spin_lock_irqsave(&priv->reg_lock, flags);
- if (!iwl_grab_nic_access(priv))
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ iwl_read32(bus(priv), CSR_UCODE_DRV_GP1);
+ spin_lock_irqsave(&bus(priv)->reg_lock, flags);
+ if (!iwl_grab_nic_access(bus(priv)))
+ iwl_release_nic_access(bus(priv));
+ spin_unlock_irqrestore(&bus(priv)->reg_lock, flags);
/* Reschedule the ct_kill timer to occur in
* CT_KILL_EXIT_DURATION seconds to ensure we get a
@@ -227,7 +224,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
struct iwl_priv *priv = (struct iwl_priv *)data;
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
/* temperature timer expired, ready to go into CT_KILL state */
@@ -235,7 +232,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "
"temperature timer expired\n");
tt->state = IWL_TI_CT_KILL;
- set_bit(STATUS_CT_KILL, &priv->status);
+ set_bit(STATUS_CT_KILL, &priv->shrd->status);
iwl_perform_ct_kill_task(priv, true);
}
}
@@ -313,23 +310,24 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
tt->tt_power_mode = IWL_POWER_INDEX_5;
break;
}
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
if (old_state == IWL_TI_CT_KILL)
- clear_bit(STATUS_CT_KILL, &priv->status);
+ clear_bit(STATUS_CT_KILL, &priv->shrd->status);
if (tt->state != IWL_TI_CT_KILL &&
iwl_power_update_mode(priv, true)) {
/* TT state not updated
* try again during next temperature read
*/
if (old_state == IWL_TI_CT_KILL)
- set_bit(STATUS_CT_KILL, &priv->status);
+ set_bit(STATUS_CT_KILL, &priv->shrd->status);
tt->state = old_state;
IWL_ERR(priv, "Cannot update power mode, "
"TT state not updated\n");
} else {
if (tt->state == IWL_TI_CT_KILL) {
if (force) {
- set_bit(STATUS_CT_KILL, &priv->status);
+ set_bit(STATUS_CT_KILL,
+ &priv->shrd->status);
iwl_perform_ct_kill_task(priv, true);
} else {
iwl_prepare_ct_kill_task(priv);
@@ -343,7 +341,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
tt->tt_power_mode);
}
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
}
@@ -453,9 +451,9 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
* in case get disabled before */
iwl_set_rxon_ht(priv, &priv->current_ht_config);
}
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
if (old_state == IWL_TI_CT_KILL)
- clear_bit(STATUS_CT_KILL, &priv->status);
+ clear_bit(STATUS_CT_KILL, &priv->shrd->status);
if (tt->state != IWL_TI_CT_KILL &&
iwl_power_update_mode(priv, true)) {
/* TT state not updated
@@ -464,7 +462,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
IWL_ERR(priv, "Cannot update power mode, "
"TT state not updated\n");
if (old_state == IWL_TI_CT_KILL)
- set_bit(STATUS_CT_KILL, &priv->status);
+ set_bit(STATUS_CT_KILL, &priv->shrd->status);
tt->state = old_state;
} else {
IWL_DEBUG_TEMP(priv,
@@ -475,7 +473,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
if (force) {
IWL_DEBUG_TEMP(priv,
"Enter IWL_TI_CT_KILL\n");
- set_bit(STATUS_CT_KILL, &priv->status);
+ set_bit(STATUS_CT_KILL,
+ &priv->shrd->status);
iwl_perform_ct_kill_task(priv, true);
} else {
iwl_prepare_ct_kill_task(priv);
@@ -487,7 +486,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
iwl_perform_ct_kill_task(priv, false);
}
}
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
}
@@ -506,10 +505,10 @@ static void iwl_bg_ct_enter(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
- if (!iwl_is_ready(priv))
+ if (!iwl_is_ready(priv->shrd))
return;
if (tt->state != IWL_TI_CT_KILL) {
@@ -535,10 +534,10 @@ static void iwl_bg_ct_exit(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
- if (!iwl_is_ready(priv))
+ if (!iwl_is_ready(priv->shrd))
return;
/* stop ct_kill_exit_tm timer */
@@ -565,20 +564,20 @@ static void iwl_bg_ct_exit(struct work_struct *work)
void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
- queue_work(priv->workqueue, &priv->ct_enter);
+ queue_work(priv->shrd->workqueue, &priv->ct_enter);
}
void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
- queue_work(priv->workqueue, &priv->ct_exit);
+ queue_work(priv->shrd->workqueue, &priv->ct_exit);
}
static void iwl_bg_tt_work(struct work_struct *work)
@@ -586,12 +585,9 @@ static void iwl_bg_tt_work(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
s32 temp = priv->temperature; /* degrees CELSIUS except specified */
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
- if (priv->cfg->base_params->temperature_kelvin)
- temp = KELVIN_TO_CELSIUS(priv->temperature);
-
if (!priv->thermal_throttle.advanced_tt)
iwl_legacy_tt_handler(priv, temp, false);
else
@@ -600,11 +596,11 @@ static void iwl_bg_tt_work(struct work_struct *work)
void iwl_tt_handler(struct iwl_priv *priv)
{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
- queue_work(priv->workqueue, &priv->tt_work);
+ queue_work(priv->shrd->workqueue, &priv->tt_work);
}
/* Thermal throttling initialization
@@ -639,11 +635,13 @@ void iwl_tt_initialize(struct iwl_priv *priv)
if (priv->cfg->base_params->adv_thermal_throttle) {
IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");
- tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
- IWL_TI_STATE_MAX, GFP_KERNEL);
- tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
- IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
- GFP_KERNEL);
+ tt->restriction = kcalloc(IWL_TI_STATE_MAX,
+ sizeof(struct iwl_tt_restriction),
+ GFP_KERNEL);
+ tt->transaction = kcalloc(IWL_TI_STATE_MAX *
+ (IWL_TI_STATE_MAX - 1),
+ sizeof(struct iwl_tt_trans),
+ GFP_KERNEL);
if (!tt->restriction || !tt->transaction) {
IWL_ERR(priv, "Fallback to Legacy Throttling\n");
priv->thermal_throttle.advanced_tt = false;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h
index d118ed29bf3f..7282a23e8f1c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h
@@ -117,7 +117,6 @@ struct iwl_tt_mgmt {
u8 iwl_tt_current_power_mode(struct iwl_priv *priv);
bool iwl_tt_is_low_power_state(struct iwl_priv *priv);
bool iwl_ht_enabled(struct iwl_priv *priv);
-bool iwl_check_for_ct_kill(struct iwl_priv *priv);
enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 53bb59ee719d..35a6b71f358c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -31,89 +31,15 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
+#include <linux/ieee80211.h>
#include "iwl-dev.h"
#include "iwl-core.h"
-#include "iwl-sta.h"
#include "iwl-io.h"
-#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
#include "iwl-agn.h"
#include "iwl-trans.h"
-/*
- * mac80211 queues, ACs, hardware queues, FIFOs.
- *
- * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
- *
- * Mac80211 uses the following numbers, which we get as from it
- * by way of skb_get_queue_mapping(skb):
- *
- * VO 0
- * VI 1
- * BE 2
- * BK 3
- *
- *
- * Regular (not A-MPDU) frames are put into hardware queues corresponding
- * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
- * own queue per aggregation session (RA/TID combination), such queues are
- * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
- * order to map frames to the right queue, we also need an AC->hw queue
- * mapping. This is implemented here.
- *
- * Due to the way hw queues are set up (by the hw specific modules like
- * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity
- * mapping.
- */
-
-static const u8 tid_to_ac[] = {
- IEEE80211_AC_BE,
- IEEE80211_AC_BK,
- IEEE80211_AC_BK,
- IEEE80211_AC_BE,
- IEEE80211_AC_VI,
- IEEE80211_AC_VI,
- IEEE80211_AC_VO,
- IEEE80211_AC_VO
-};
-
-static inline int get_ac_from_tid(u16 tid)
-{
- if (likely(tid < ARRAY_SIZE(tid_to_ac)))
- return tid_to_ac[tid];
-
- /* no support for TIDs 8-15 yet */
- return -EINVAL;
-}
-
-static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
-{
- if (likely(tid < ARRAY_SIZE(tid_to_ac)))
- return ctx->ac_to_fifo[tid_to_ac[tid]];
-
- /* no support for TIDs 8-15 yet */
- return -EINVAL;
-}
-
-static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id,
- int tid)
-{
- if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
- (IWLAGN_FIRST_AMPDU_QUEUE +
- priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
- IWL_WARN(priv,
- "queue number out of range: %d, must be %d to %d\n",
- txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
- IWLAGN_FIRST_AMPDU_QUEUE +
- priv->cfg->base_params->num_of_ampdu_queues - 1);
- return -EINVAL;
- }
-
- /* Modify device's station table to Tx this TID */
- return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
-}
-
static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
struct ieee80211_tx_info *info,
__le16 fc, __le32 *tx_flags)
@@ -128,11 +54,10 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
* handle build REPLY_TX command notification.
*/
static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
- struct sk_buff *skb,
- struct iwl_tx_cmd *tx_cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_hdr *hdr,
- u8 std_id)
+ struct sk_buff *skb,
+ struct iwl_tx_cmd *tx_cmd,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_hdr *hdr, u8 sta_id)
{
__le16 fc = hdr->frame_control;
__le32 tx_flags = tx_cmd->tx_flags;
@@ -157,7 +82,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
tx_flags |= TX_CMD_FLG_IGNORE_BT;
- tx_cmd->sta_id = std_id;
+ tx_cmd->sta_id = sta_id;
if (ieee80211_has_morefrags(fc))
tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
@@ -186,12 +111,10 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
tx_cmd->next_frame_len = 0;
}
-#define RTS_DFAULT_RETRY_LIMIT 60
-
static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
- struct iwl_tx_cmd *tx_cmd,
- struct ieee80211_tx_info *info,
- __le16 fc)
+ struct iwl_tx_cmd *tx_cmd,
+ struct ieee80211_tx_info *info,
+ __le16 fc)
{
u32 rate_flags;
int rate_idx;
@@ -199,17 +122,25 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
u8 data_retry_limit;
u8 rate_plcp;
- /* Set retry limit on DATA packets and Probe Responses*/
- if (ieee80211_is_probe_resp(fc))
- data_retry_limit = 3;
- else
- data_retry_limit = IWLAGN_DEFAULT_TX_RETRY;
- tx_cmd->data_retry_limit = data_retry_limit;
+ if (priv->shrd->wowlan) {
+ rts_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
+ data_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
+ } else {
+ /* Set retry limit on RTS packets */
+ rts_retry_limit = IWLAGN_RTS_DFAULT_RETRY_LIMIT;
+
+ /* Set retry limit on DATA packets and Probe Responses*/
+ if (ieee80211_is_probe_resp(fc)) {
+ data_retry_limit = IWLAGN_MGMT_DFAULT_RETRY_LIMIT;
+ rts_retry_limit =
+ min(data_retry_limit, rts_retry_limit);
+ } else if (ieee80211_is_back_req(fc))
+ data_retry_limit = IWLAGN_BAR_DFAULT_RETRY_LIMIT;
+ else
+ data_retry_limit = IWLAGN_DEFAULT_TX_RETRY;
+ }
- /* Set retry limit on RTS packets */
- rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
- if (data_retry_limit < rts_retry_limit)
- rts_retry_limit = data_retry_limit;
+ tx_cmd->data_retry_limit = data_retry_limit;
tx_cmd->rts_retry_limit = rts_retry_limit;
/* DATA packets will use the uCode station table for rate/antenna
@@ -261,10 +192,10 @@ 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->hw_params.valid_tx_ant));
+ first_antenna(hw_params(priv).valid_tx_ant));
} else
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
- priv->hw_params.valid_tx_ant);
+ hw_params(priv).valid_tx_ant);
rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
/* Set the rate in the TX cmd */
@@ -322,30 +253,21 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_station_priv *sta_priv = NULL;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ struct iwl_device_cmd *dev_cmd = NULL;
struct iwl_tx_cmd *tx_cmd;
- int txq_id;
- u16 seq_number = 0;
__le16 fc;
u8 hdr_len;
u16 len;
u8 sta_id;
- u8 tid = 0;
unsigned long flags;
bool is_agg = false;
- /*
- * If the frame needs to go out off-channel, then
- * we'll have put the PAN context to that channel,
- * so make the frame go out there.
- */
- if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
- ctx = &priv->contexts[IWL_RXON_CTX_PAN];
- else if (info->control.vif)
+ if (info->control.vif)
ctx = iwl_rxon_ctx_from_vif(info->control.vif);
- spin_lock_irqsave(&priv->lock, flags);
- if (iwl_is_rfkill(priv)) {
+ spin_lock_irqsave(&priv->shrd->lock, flags);
+ if (iwl_is_rfkill(priv->shrd)) {
IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
goto drop_unlock_priv;
}
@@ -382,7 +304,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
sta_priv = (void *)info->control.sta->drv_priv;
if (sta_priv && sta_priv->asleep &&
- (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) {
+ (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) {
/*
* This sends an asynchronous command to the device,
* but we can rely on it being processed before the
@@ -395,52 +317,19 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
}
- /*
- * Send this frame after DTIM -- there's a special queue
- * reserved for this for contexts that support AP mode.
- */
- if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
- txq_id = ctx->mcast_queue;
- /*
- * The microcode will clear the more data
- * bit in the last frame it transmits.
- */
- hdr->frame_control |=
- cpu_to_le16(IEEE80211_FCTL_MOREDATA);
- } else
- txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
+ if (info->flags & IEEE80211_TX_CTL_AMPDU)
+ is_agg = true;
- /* irqs already disabled/saved above when locking priv->lock */
- spin_lock(&priv->sta_lock);
+ /* irqs already disabled/saved above when locking priv->shrd->lock */
+ spin_lock(&priv->shrd->sta_lock);
- if (ieee80211_is_data_qos(fc)) {
- u8 *qc = NULL;
- qc = ieee80211_get_qos_ctl(hdr);
- tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-
- if (WARN_ON_ONCE(tid >= MAX_TID_COUNT))
- goto drop_unlock_sta;
-
- seq_number = priv->stations[sta_id].tid[tid].seq_number;
- seq_number &= IEEE80211_SCTL_SEQ;
- hdr->seq_ctrl = hdr->seq_ctrl &
- cpu_to_le16(IEEE80211_SCTL_FRAG);
- hdr->seq_ctrl |= cpu_to_le16(seq_number);
- seq_number += 0x10;
- /* aggregation is on for this <sta,tid> */
- if (info->flags & IEEE80211_TX_CTL_AMPDU &&
- priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
- txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
- is_agg = true;
- }
- }
+ dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC);
- tx_cmd = trans_get_tx_cmd(&priv->trans, txq_id);
- if (unlikely(!tx_cmd))
+ if (unlikely(!dev_cmd))
goto drop_unlock_sta;
- /* Copy MAC header from skb into command buffer */
- memcpy(tx_cmd->hdr, hdr, hdr_len);
+ memset(dev_cmd, 0, sizeof(*dev_cmd));
+ tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
/* Total # bytes to be transmitted */
len = (u16)skb->len;
@@ -457,17 +346,16 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwl_update_stats(priv, true, fc, len);
- if (trans_tx(&priv->trans, skb, tx_cmd, txq_id, fc, is_agg, ctx))
- goto drop_unlock_sta;
+ memset(&info->status, 0, sizeof(info->status));
- if (ieee80211_is_data_qos(fc)) {
- priv->stations[sta_id].tid[tid].tfds_in_queue++;
- if (!ieee80211_has_morefrags(fc))
- priv->stations[sta_id].tid[tid].seq_number = seq_number;
- }
+ info->driver_data[0] = ctx;
+ info->driver_data[1] = dev_cmd;
+
+ if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id))
+ goto drop_unlock_sta;
- spin_unlock(&priv->sta_lock);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock(&priv->shrd->sta_lock);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
/*
* Avoid atomic ops if it isn't an associated client.
@@ -482,41 +370,20 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
return 0;
drop_unlock_sta:
- spin_unlock(&priv->sta_lock);
+ if (dev_cmd)
+ kmem_cache_free(priv->tx_cmd_pool, dev_cmd);
+ spin_unlock(&priv->shrd->sta_lock);
drop_unlock_priv:
- spin_unlock_irqrestore(&priv->lock, flags);
- return -1;
-}
-
-/*
- * Find first available (lowest unused) Tx Queue, mark it "active".
- * Called only when finding queue for aggregation.
- * Should never return anything < 7, because they should already
- * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
- */
-static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv)
-{
- int txq_id;
-
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk))
- return txq_id;
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
return -1;
}
int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
int sta_id;
- int tx_fifo;
- int txq_id;
int ret;
- unsigned long flags;
- struct iwl_tid_data *tid_data;
-
- tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid);
- if (unlikely(tx_fifo < 0))
- return tx_fifo;
IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n",
sta->addr, tid);
@@ -526,58 +393,29 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
IWL_ERR(priv, "Start AGG on invalid station\n");
return -ENXIO;
}
- if (unlikely(tid >= MAX_TID_COUNT))
+ if (unlikely(tid >= IWL_MAX_TID_COUNT))
return -EINVAL;
- if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
+ if (priv->shrd->tid_data[sta_id][tid].agg.state != IWL_AGG_OFF) {
IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
return -ENXIO;
}
- txq_id = iwlagn_txq_ctx_activate_free(priv);
- if (txq_id == -1) {
- IWL_ERR(priv, "No free aggregation queue available\n");
- return -ENXIO;
- }
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- tid_data = &priv->stations[sta_id].tid[tid];
- *ssn = SEQ_TO_SN(tid_data->seq_number);
- tid_data->agg.txq_id = txq_id;
- tid_data->agg.tx_fifo = tx_fifo;
- iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- ret = iwlagn_txq_agg_enable(priv, txq_id, sta_id, tid);
+ ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
if (ret)
return ret;
- spin_lock_irqsave(&priv->sta_lock, flags);
- tid_data = &priv->stations[sta_id].tid[tid];
- if (tid_data->tfds_in_queue == 0) {
- IWL_DEBUG_HT(priv, "HW queue is empty\n");
- tid_data->agg.state = IWL_AGG_ON;
- ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
- } else {
- IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n",
- tid_data->tfds_in_queue);
- tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
- }
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ ret = iwl_trans_tx_agg_alloc(trans(priv), vif_priv->ctx->ctxid, sta_id,
+ tid, ssn);
+
return ret;
}
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid)
{
- int tx_fifo_id, txq_id, sta_id, ssn;
- struct iwl_tid_data *tid_data;
- int write_ptr, read_ptr;
- unsigned long flags;
-
- tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid);
- if (unlikely(tx_fifo_id < 0))
- return tx_fifo_id;
+ int sta_id;
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
sta_id = iwl_sta_id(sta);
@@ -586,101 +424,8 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
return -ENXIO;
}
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- tid_data = &priv->stations[sta_id].tid[tid];
- ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
- txq_id = tid_data->agg.txq_id;
-
- switch (priv->stations[sta_id].tid[tid].agg.state) {
- case IWL_EMPTYING_HW_QUEUE_ADDBA:
- /*
- * This can happen if the peer stops aggregation
- * again before we've had a chance to drain the
- * queue we selected previously, i.e. before the
- * session was really started completely.
- */
- IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
- goto turn_off;
- case IWL_AGG_ON:
- break;
- default:
- IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
- }
-
- write_ptr = priv->txq[txq_id].q.write_ptr;
- read_ptr = priv->txq[txq_id].q.read_ptr;
-
- /* The queue is not empty */
- if (write_ptr != read_ptr) {
- IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n");
- priv->stations[sta_id].tid[tid].agg.state =
- IWL_EMPTYING_HW_QUEUE_DELBA;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
- }
-
- IWL_DEBUG_HT(priv, "HW queue is empty\n");
- turn_off:
- priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
-
- /* do not restore/save irqs */
- spin_unlock(&priv->sta_lock);
- spin_lock(&priv->lock);
-
- /*
- * the only reason this call can fail is queue number out of range,
- * which can happen if uCode is reloaded and all the station
- * information are lost. if it is outside the range, there is no need
- * to deactivate the uCode queue, just return "success" to allow
- * mac80211 to clean up it own data.
- */
- trans_txq_agg_disable(&priv->trans, txq_id, ssn, tx_fifo_id);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-
- return 0;
-}
-
-int iwlagn_txq_check_empty(struct iwl_priv *priv,
- int sta_id, u8 tid, int txq_id)
-{
- struct iwl_queue *q = &priv->txq[txq_id].q;
- u8 *addr = priv->stations[sta_id].sta.sta.addr;
- struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
- struct iwl_rxon_context *ctx;
-
- ctx = &priv->contexts[priv->stations[sta_id].ctxid];
-
- lockdep_assert_held(&priv->sta_lock);
-
- switch (priv->stations[sta_id].tid[tid].agg.state) {
- case IWL_EMPTYING_HW_QUEUE_DELBA:
- /* We are reclaiming the last packet of the */
- /* aggregated HW queue */
- if ((txq_id == tid_data->agg.txq_id) &&
- (q->read_ptr == q->write_ptr)) {
- u16 ssn = SEQ_TO_SN(tid_data->seq_number);
- int tx_fifo = get_fifo_from_tid(ctx, tid);
- IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
- trans_txq_agg_disable(&priv->trans, txq_id,
- ssn, tx_fifo);
- tid_data->agg.state = IWL_AGG_OFF;
- ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
- }
- break;
- case IWL_EMPTYING_HW_QUEUE_ADDBA:
- /* We are reclaiming the last packet of the queue */
- if (tid_data->tfds_in_queue == 0) {
- IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
- tid_data->agg.state = IWL_AGG_ON;
- ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
- }
- break;
- }
-
- return 0;
+ return iwl_trans_tx_agg_disable(trans(priv), vif_priv->ctx->ctxid,
+ sta_id, tid);
}
static void iwlagn_non_agg_tx_status(struct iwl_priv *priv,
@@ -702,147 +447,394 @@ static void iwlagn_non_agg_tx_status(struct iwl_priv *priv,
rcu_read_unlock();
}
-static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info,
- bool is_agg)
+/**
+ * translate ucode response to mac80211 tx status control values
+ */
+static void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
+ struct ieee80211_tx_info *info)
+{
+ struct ieee80211_tx_rate *r = &info->control.rates[0];
+
+ info->antenna_sel_tx =
+ ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
+ if (rate_n_flags & RATE_MCS_HT_MSK)
+ r->flags |= IEEE80211_TX_RC_MCS;
+ if (rate_n_flags & RATE_MCS_GF_MSK)
+ r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
+ if (rate_n_flags & RATE_MCS_HT40_MSK)
+ r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+ if (rate_n_flags & RATE_MCS_DUP_MSK)
+ r->flags |= IEEE80211_TX_RC_DUP_DATA;
+ if (rate_n_flags & RATE_MCS_SGI_MSK)
+ r->flags |= IEEE80211_TX_RC_SHORT_GI;
+ r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band);
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+const char *iwl_get_tx_fail_reason(u32 status)
{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data;
+#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
+#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
+
+ switch (status & TX_STATUS_MSK) {
+ case TX_STATUS_SUCCESS:
+ return "SUCCESS";
+ TX_STATUS_POSTPONE(DELAY);
+ TX_STATUS_POSTPONE(FEW_BYTES);
+ TX_STATUS_POSTPONE(BT_PRIO);
+ TX_STATUS_POSTPONE(QUIET_PERIOD);
+ TX_STATUS_POSTPONE(CALC_TTAK);
+ TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
+ TX_STATUS_FAIL(SHORT_LIMIT);
+ TX_STATUS_FAIL(LONG_LIMIT);
+ TX_STATUS_FAIL(FIFO_UNDERRUN);
+ TX_STATUS_FAIL(DRAIN_FLOW);
+ TX_STATUS_FAIL(RFKILL_FLUSH);
+ TX_STATUS_FAIL(LIFE_EXPIRE);
+ TX_STATUS_FAIL(DEST_PS);
+ TX_STATUS_FAIL(HOST_ABORTED);
+ TX_STATUS_FAIL(BT_RETRY);
+ TX_STATUS_FAIL(STA_INVALID);
+ TX_STATUS_FAIL(FRAG_DROPPED);
+ TX_STATUS_FAIL(TID_DISABLE);
+ TX_STATUS_FAIL(FIFO_FLUSHED);
+ TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
+ TX_STATUS_FAIL(PASSIVE_NO_RX);
+ TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
+ }
- if (!is_agg)
- iwlagn_non_agg_tx_status(priv, tx_info->ctx, hdr->addr1);
+ return "UNKNOWN";
- ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
+#undef TX_STATUS_FAIL
+#undef TX_STATUS_POSTPONE
}
+#endif /* CONFIG_IWLWIFI_DEBUG */
-int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
+static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
{
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct iwl_queue *q = &txq->q;
- struct iwl_tx_info *tx_info;
- int nfreed = 0;
- struct ieee80211_hdr *hdr;
+ status &= AGG_TX_STATUS_MSK;
- if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
- IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), "
- "index %d is out of range [0-%d] %d %d.\n", __func__,
- txq_id, index, q->n_bd, q->write_ptr, q->read_ptr);
- return 0;
+ switch (status) {
+ case AGG_TX_STATE_UNDERRUN_MSK:
+ priv->reply_agg_tx_stats.underrun++;
+ break;
+ case AGG_TX_STATE_BT_PRIO_MSK:
+ priv->reply_agg_tx_stats.bt_prio++;
+ break;
+ case AGG_TX_STATE_FEW_BYTES_MSK:
+ priv->reply_agg_tx_stats.few_bytes++;
+ break;
+ case AGG_TX_STATE_ABORT_MSK:
+ priv->reply_agg_tx_stats.abort++;
+ break;
+ case AGG_TX_STATE_LAST_SENT_TTL_MSK:
+ priv->reply_agg_tx_stats.last_sent_ttl++;
+ break;
+ case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK:
+ priv->reply_agg_tx_stats.last_sent_try++;
+ break;
+ case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK:
+ priv->reply_agg_tx_stats.last_sent_bt_kill++;
+ break;
+ case AGG_TX_STATE_SCD_QUERY_MSK:
+ priv->reply_agg_tx_stats.scd_query++;
+ break;
+ case AGG_TX_STATE_TEST_BAD_CRC32_MSK:
+ priv->reply_agg_tx_stats.bad_crc32++;
+ break;
+ case AGG_TX_STATE_RESPONSE_MSK:
+ priv->reply_agg_tx_stats.response++;
+ break;
+ case AGG_TX_STATE_DUMP_TX_MSK:
+ priv->reply_agg_tx_stats.dump_tx++;
+ break;
+ case AGG_TX_STATE_DELAY_TX_MSK:
+ priv->reply_agg_tx_stats.delay_tx++;
+ break;
+ default:
+ priv->reply_agg_tx_stats.unknown++;
+ break;
}
+}
+
+static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
+ struct iwlagn_tx_resp *tx_resp)
+{
+ struct agg_tx_status *frame_status = &tx_resp->status;
+ int tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
+ IWLAGN_TX_RES_TID_POS;
+ int sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
+ IWLAGN_TX_RES_RA_POS;
+ struct iwl_ht_agg *agg = &priv->shrd->tid_data[sta_id][tid].agg;
+ u32 status = le16_to_cpu(tx_resp->status.status);
+ int i;
+
+ if (agg->wait_for_ba)
+ IWL_DEBUG_TX_REPLY(priv,
+ "got tx response w/o block-ack\n");
- for (index = iwl_queue_inc_wrap(index, q->n_bd);
- q->read_ptr != index;
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+ agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+ agg->wait_for_ba = (tx_resp->frame_count > 1);
- tx_info = &txq->txb[txq->q.read_ptr];
+ /*
+ * If the BT kill count is non-zero, we'll get this
+ * notification again.
+ */
+ if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
+ priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist) {
+ IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n");
+ }
- if (WARN_ON_ONCE(tx_info->skb == NULL))
- continue;
+ if (tx_resp->frame_count == 1)
+ return;
- hdr = (struct ieee80211_hdr *)tx_info->skb->data;
- if (ieee80211_is_data_qos(hdr->frame_control))
- nfreed++;
+ /* Construct bit-map of pending frames within Tx window */
+ for (i = 0; i < tx_resp->frame_count; i++) {
+ u16 fstatus = le16_to_cpu(frame_status[i].status);
- iwlagn_tx_status(priv, tx_info,
- txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
- tx_info->skb = NULL;
+ if (status & AGG_TX_STATUS_MSK)
+ iwlagn_count_agg_tx_err_status(priv, fstatus);
- iwlagn_txq_inval_byte_cnt_tbl(priv, txq);
+ if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
+ AGG_TX_STATE_ABORT_MSK))
+ continue;
- iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr);
+ IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), "
+ "try-count (0x%08x)\n",
+ iwl_get_agg_tx_fail_reason(fstatus),
+ fstatus & AGG_TX_STATUS_MSK,
+ fstatus & AGG_TX_TRY_MSK);
}
- return nfreed;
}
-/**
- * iwlagn_tx_status_reply_compressed_ba - Update tx status from block-ack
- *
- * Go through block-ack's bitmap of ACK'd frames, update driver's record of
- * ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
- */
-static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl_ht_agg *agg,
- struct iwl_compressed_ba_resp *ba_resp)
+#ifdef CONFIG_IWLWIFI_DEBUG
+#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x
+const char *iwl_get_agg_tx_fail_reason(u16 status)
{
- int sh;
- u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
- u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
- struct ieee80211_tx_info *info;
- u64 bitmap, sent_bitmap;
-
- if (unlikely(!agg->wait_for_ba)) {
- if (unlikely(ba_resp->bitmap))
- IWL_ERR(priv, "Received BA when not expected\n");
- return -EINVAL;
+ status &= AGG_TX_STATUS_MSK;
+ switch (status) {
+ case AGG_TX_STATE_TRANSMITTED:
+ return "SUCCESS";
+ AGG_TX_STATE_FAIL(UNDERRUN_MSK);
+ AGG_TX_STATE_FAIL(BT_PRIO_MSK);
+ AGG_TX_STATE_FAIL(FEW_BYTES_MSK);
+ AGG_TX_STATE_FAIL(ABORT_MSK);
+ AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK);
+ AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK);
+ AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK);
+ AGG_TX_STATE_FAIL(SCD_QUERY_MSK);
+ AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK);
+ AGG_TX_STATE_FAIL(RESPONSE_MSK);
+ AGG_TX_STATE_FAIL(DUMP_TX_MSK);
+ AGG_TX_STATE_FAIL(DELAY_TX_MSK);
}
- /* Mark that the expected block-ack response arrived */
- agg->wait_for_ba = 0;
- IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
-
- /* Calculate shift to align block-ack bits with our Tx window bits */
- sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4);
- if (sh < 0)
- sh += 0x100;
+ return "UNKNOWN";
+}
+#endif /* CONFIG_IWLWIFI_DEBUG */
- /*
- * Check for success or failure according to the
- * transmitted bitmap and block-ack bitmap
- */
- bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
- sent_bitmap = bitmap & agg->bitmap;
+static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
+{
+ return le32_to_cpup((__le32 *)&tx_resp->status +
+ tx_resp->frame_count) & MAX_SN;
+}
- /* Sanity check values reported by uCode */
- if (ba_resp->txed_2_done > ba_resp->txed) {
- IWL_DEBUG_TX_REPLY(priv,
- "bogus sent(%d) and ack(%d) count\n",
- ba_resp->txed, ba_resp->txed_2_done);
- /*
- * set txed_2_done = txed,
- * so it won't impact rate scale
- */
- ba_resp->txed = ba_resp->txed_2_done;
- }
- IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
- ba_resp->txed, ba_resp->txed_2_done);
+static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
+{
+ status &= TX_STATUS_MSK;
- /* Find the first ACKed frame to store the TX status */
- while (sent_bitmap && !(sent_bitmap & 1)) {
- agg->start_idx = (agg->start_idx + 1) & 0xff;
- sent_bitmap >>= 1;
+ switch (status) {
+ case TX_STATUS_POSTPONE_DELAY:
+ priv->reply_tx_stats.pp_delay++;
+ break;
+ case TX_STATUS_POSTPONE_FEW_BYTES:
+ priv->reply_tx_stats.pp_few_bytes++;
+ break;
+ case TX_STATUS_POSTPONE_BT_PRIO:
+ priv->reply_tx_stats.pp_bt_prio++;
+ break;
+ case TX_STATUS_POSTPONE_QUIET_PERIOD:
+ priv->reply_tx_stats.pp_quiet_period++;
+ break;
+ case TX_STATUS_POSTPONE_CALC_TTAK:
+ priv->reply_tx_stats.pp_calc_ttak++;
+ break;
+ case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY:
+ priv->reply_tx_stats.int_crossed_retry++;
+ break;
+ case TX_STATUS_FAIL_SHORT_LIMIT:
+ priv->reply_tx_stats.short_limit++;
+ break;
+ case TX_STATUS_FAIL_LONG_LIMIT:
+ priv->reply_tx_stats.long_limit++;
+ break;
+ case TX_STATUS_FAIL_FIFO_UNDERRUN:
+ priv->reply_tx_stats.fifo_underrun++;
+ break;
+ case TX_STATUS_FAIL_DRAIN_FLOW:
+ priv->reply_tx_stats.drain_flow++;
+ break;
+ case TX_STATUS_FAIL_RFKILL_FLUSH:
+ priv->reply_tx_stats.rfkill_flush++;
+ break;
+ case TX_STATUS_FAIL_LIFE_EXPIRE:
+ priv->reply_tx_stats.life_expire++;
+ break;
+ case TX_STATUS_FAIL_DEST_PS:
+ priv->reply_tx_stats.dest_ps++;
+ break;
+ case TX_STATUS_FAIL_HOST_ABORTED:
+ priv->reply_tx_stats.host_abort++;
+ break;
+ case TX_STATUS_FAIL_BT_RETRY:
+ priv->reply_tx_stats.bt_retry++;
+ break;
+ case TX_STATUS_FAIL_STA_INVALID:
+ priv->reply_tx_stats.sta_invalid++;
+ break;
+ case TX_STATUS_FAIL_FRAG_DROPPED:
+ priv->reply_tx_stats.frag_drop++;
+ break;
+ case TX_STATUS_FAIL_TID_DISABLE:
+ priv->reply_tx_stats.tid_disable++;
+ break;
+ case TX_STATUS_FAIL_FIFO_FLUSHED:
+ priv->reply_tx_stats.fifo_flush++;
+ break;
+ case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL:
+ priv->reply_tx_stats.insuff_cf_poll++;
+ break;
+ case TX_STATUS_FAIL_PASSIVE_NO_RX:
+ priv->reply_tx_stats.fail_hw_drop++;
+ break;
+ case TX_STATUS_FAIL_NO_BEACON_ON_RADAR:
+ priv->reply_tx_stats.sta_color_mismatch++;
+ break;
+ default:
+ priv->reply_tx_stats.unknown++;
+ break;
}
+}
- info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
- memset(&info->status, 0, sizeof(info->status));
- info->flags |= IEEE80211_TX_STAT_ACK;
- info->flags |= IEEE80211_TX_STAT_AMPDU;
- info->status.ampdu_ack_len = ba_resp->txed_2_done;
- info->status.ampdu_len = ba_resp->txed;
- iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
+static void iwlagn_set_tx_status(struct iwl_priv *priv,
+ struct ieee80211_tx_info *info,
+ struct iwlagn_tx_resp *tx_resp,
+ bool is_agg)
+{
+ 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);
+ if (!iwl_is_tx_success(status))
+ iwlagn_count_tx_err_status(priv, status);
+}
- return 0;
+static void iwl_check_abort_status(struct iwl_priv *priv,
+ u8 frame_count, u32 status)
+{
+ if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
+ IWL_ERR(priv, "Tx flush command to flush out all frames\n");
+ if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ queue_work(priv->shrd->workqueue, &priv->tx_flush);
+ }
}
-/**
- * translate ucode response to mac80211 tx status control values
- */
-void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
- struct ieee80211_tx_info *info)
+int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
- struct ieee80211_tx_rate *r = &info->control.rates[0];
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+ int txq_id = SEQ_TO_QUEUE(sequence);
+ int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence);
+ struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+ struct ieee80211_hdr *hdr;
+ u32 status = le16_to_cpu(tx_resp->status.status);
+ u32 ssn = iwlagn_get_scd_ssn(tx_resp);
+ int tid;
+ int sta_id;
+ int freed;
+ struct ieee80211_tx_info *info;
+ unsigned long flags;
+ struct sk_buff_head skbs;
+ struct sk_buff *skb;
+ struct iwl_rxon_context *ctx;
+ bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
+
+ tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
+ IWLAGN_TX_RES_TID_POS;
+ sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
+ IWLAGN_TX_RES_RA_POS;
+
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+
+ if (is_agg)
+ iwl_rx_reply_tx_agg(priv, tx_resp);
+
+ if (tx_resp->frame_count == 1) {
+ __skb_queue_head_init(&skbs);
+ /*we can free until ssn % q.n_bd not inclusive */
+ iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
+ ssn, status, &skbs);
+ freed = 0;
+ while (!skb_queue_empty(&skbs)) {
+ skb = __skb_dequeue(&skbs);
+ hdr = (struct ieee80211_hdr *)skb->data;
+
+ if (!ieee80211_is_data_qos(hdr->frame_control))
+ priv->last_seq_ctl = tx_resp->seq_ctl;
+
+ info = IEEE80211_SKB_CB(skb);
+ ctx = info->driver_data[0];
+ kmem_cache_free(priv->tx_cmd_pool,
+ (info->driver_data[1]));
+
+ memset(&info->status, 0, sizeof(info->status));
+
+ if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
+ iwl_is_associated_ctx(ctx) && ctx->vif &&
+ ctx->vif->type == NL80211_IFTYPE_STATION) {
+ ctx->last_tx_rejected = true;
+ iwl_trans_stop_queue(trans(priv), txq_id);
+
+ IWL_DEBUG_TX_REPLY(priv,
+ "TXQ %d status %s (0x%08x) "
+ "rate_n_flags 0x%x retries %d\n",
+ txq_id,
+ iwl_get_tx_fail_reason(status),
+ status,
+ le32_to_cpu(tx_resp->rate_n_flags),
+ tx_resp->failure_frame);
+
+ IWL_DEBUG_TX_REPLY(priv,
+ "FrameCnt = %d, idx=%d\n",
+ tx_resp->frame_count, cmd_index);
+ }
+
+ /* check if BAR is needed */
+ 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);
+ if (!is_agg)
+ iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
+
+ ieee80211_tx_status_irqsafe(priv->hw, skb);
+
+ freed++;
+ }
- info->antenna_sel_tx =
- ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
- if (rate_n_flags & RATE_MCS_HT_MSK)
- r->flags |= IEEE80211_TX_RC_MCS;
- if (rate_n_flags & RATE_MCS_GF_MSK)
- r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
- if (rate_n_flags & RATE_MCS_HT40_MSK)
- r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
- if (rate_n_flags & RATE_MCS_DUP_MSK)
- r->flags |= IEEE80211_TX_RC_DUP_DATA;
- if (rate_n_flags & RATE_MCS_SGI_MSK)
- r->flags |= IEEE80211_TX_RC_SHORT_GI;
- r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band);
+ WARN_ON(!is_agg && freed != 1);
+ }
+
+ iwl_check_abort_status(priv, tx_resp->frame_count, status);
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ return 0;
}
/**
@@ -851,17 +843,21 @@ void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
* Handles block-acknowledge notification from device, which reports success
* of frames sent via aggregation.
*/
-void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
- struct iwl_tx_queue *txq = NULL;
struct iwl_ht_agg *agg;
- int index;
+ struct sk_buff_head reclaimed_skbs;
+ struct ieee80211_tx_info *info;
+ struct ieee80211_hdr *hdr;
+ struct sk_buff *skb;
+ unsigned long flags;
int sta_id;
int tid;
- unsigned long flags;
+ int freed;
/* "flow" corresponds to Tx queue */
u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
@@ -870,16 +866,18 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
* (in Tx queue's circular buffer) of first TFD/frame in window */
u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
- if (scd_flow >= priv->hw_params.max_txq_num) {
+ if (scd_flow >= hw_params(priv).max_txq_num) {
IWL_ERR(priv,
"BUG_ON scd_flow is bigger than number of queues\n");
- return;
+ return 0;
}
- txq = &priv->txq[scd_flow];
sta_id = ba_resp->sta_id;
tid = ba_resp->tid;
- agg = &priv->stations[sta_id].tid[tid].agg;
+ agg = &priv->shrd->tid_data[sta_id][tid].agg;
+
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+
if (unlikely(agg->txq_id != scd_flow)) {
/*
* FIXME: this is a uCode bug which need to be addressed,
@@ -890,88 +888,84 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
IWL_DEBUG_TX_REPLY(priv,
"BA scd_flow %d does not match txq_id %d\n",
scd_flow, agg->txq_id);
- return;
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ return 0;
}
- /* Find index just before block-ack window */
- index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
-
- spin_lock_irqsave(&priv->sta_lock, flags);
+ if (unlikely(!agg->wait_for_ba)) {
+ if (unlikely(ba_resp->bitmap))
+ IWL_ERR(priv, "Received BA when not expected\n");
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ return 0;
+ }
IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
"sta_id = %d\n",
agg->wait_for_ba,
(u8 *) &ba_resp->sta_addr_lo32,
ba_resp->sta_id);
- IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
- "%d, scd_ssn = %d\n",
+ IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, "
+ "scd_flow = %d, scd_ssn = %d\n",
ba_resp->tid,
ba_resp->seq_ctl,
(unsigned long long)le64_to_cpu(ba_resp->bitmap),
ba_resp->scd_flow,
ba_resp->scd_ssn);
- IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n",
- agg->start_idx,
- (unsigned long long)agg->bitmap);
- /* Update driver's record of ACK vs. not for each frame in window */
- iwlagn_tx_status_reply_compressed_ba(priv, agg, ba_resp);
+ /* Mark that the expected block-ack response arrived */
+ agg->wait_for_ba = false;
+
+ /* Sanity check values reported by uCode */
+ if (ba_resp->txed_2_done > ba_resp->txed) {
+ IWL_DEBUG_TX_REPLY(priv,
+ "bogus sent(%d) and ack(%d) count\n",
+ ba_resp->txed, ba_resp->txed_2_done);
+ /*
+ * set txed_2_done = txed,
+ * so it won't impact rate scale
+ */
+ ba_resp->txed = ba_resp->txed_2_done;
+ }
+ IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
+ ba_resp->txed, ba_resp->txed_2_done);
+
+ __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 (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
- /* calculate mac80211 ampdu sw queue to wake */
- int freed = iwlagn_tx_queue_reclaim(priv, scd_flow, index);
- iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
-
- if ((iwl_queue_space(&txq->q) > txq->q.low_mark) &&
- priv->mac80211_registered &&
- (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
- iwl_wake_queue(priv, txq);
-
- iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow);
- }
+ iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn,
+ 0, &reclaimed_skbs);
+ freed = 0;
+ while (!skb_queue_empty(&reclaimed_skbs)) {
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
+ skb = __skb_dequeue(&reclaimed_skbs);
+ hdr = (struct ieee80211_hdr *)skb->data;
-#ifdef CONFIG_IWLWIFI_DEBUG
-const char *iwl_get_tx_fail_reason(u32 status)
-{
-#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
-#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
+ if (ieee80211_is_data_qos(hdr->frame_control))
+ freed++;
+ else
+ WARN_ON_ONCE(1);
+
+ info = IEEE80211_SKB_CB(skb);
+ kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
+
+ if (freed == 1) {
+ /* this is the first skb we deliver in this batch */
+ /* put the rate scaling data there */
+ info = IEEE80211_SKB_CB(skb);
+ memset(&info->status, 0, sizeof(info->status));
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ info->flags |= IEEE80211_TX_STAT_AMPDU;
+ info->status.ampdu_ack_len = ba_resp->txed_2_done;
+ info->status.ampdu_len = ba_resp->txed;
+ iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags,
+ info);
+ }
- switch (status & TX_STATUS_MSK) {
- case TX_STATUS_SUCCESS:
- return "SUCCESS";
- TX_STATUS_POSTPONE(DELAY);
- TX_STATUS_POSTPONE(FEW_BYTES);
- TX_STATUS_POSTPONE(BT_PRIO);
- TX_STATUS_POSTPONE(QUIET_PERIOD);
- TX_STATUS_POSTPONE(CALC_TTAK);
- TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
- TX_STATUS_FAIL(SHORT_LIMIT);
- TX_STATUS_FAIL(LONG_LIMIT);
- TX_STATUS_FAIL(FIFO_UNDERRUN);
- TX_STATUS_FAIL(DRAIN_FLOW);
- TX_STATUS_FAIL(RFKILL_FLUSH);
- TX_STATUS_FAIL(LIFE_EXPIRE);
- TX_STATUS_FAIL(DEST_PS);
- TX_STATUS_FAIL(HOST_ABORTED);
- TX_STATUS_FAIL(BT_RETRY);
- TX_STATUS_FAIL(STA_INVALID);
- TX_STATUS_FAIL(FRAG_DROPPED);
- TX_STATUS_FAIL(TID_DISABLE);
- TX_STATUS_FAIL(FIFO_FLUSHED);
- TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
- TX_STATUS_FAIL(PASSIVE_NO_RX);
- TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
+ ieee80211_tx_status_irqsafe(priv->hw, skb);
}
- return "UNKNOWN";
-
-#undef TX_STATUS_FAIL
-#undef TX_STATUS_POSTPONE
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+ return 0;
}
-#endif /* CONFIG_IWLWIFI_DEBUG */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 56211006a182..8ba0dd54e37d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -35,11 +35,11 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
-#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
#include "iwl-agn.h"
#include "iwl-agn-calib.h"
#include "iwl-trans.h"
+#include "iwl-fh.h"
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
@@ -84,42 +84,37 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
priv->ucode_write_complete = 0;
- iwl_write_direct32(priv,
+ iwl_write_direct32(bus(priv),
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
- iwl_write_direct32(priv,
+ iwl_write_direct32(bus(priv),
FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr);
- iwl_write_direct32(priv,
+ iwl_write_direct32(bus(priv),
FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
- iwl_write_direct32(priv,
+ iwl_write_direct32(bus(priv),
FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
(iwl_get_dma_hi_addr(phy_addr)
<< FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
- iwl_write_direct32(priv,
+ iwl_write_direct32(bus(priv),
FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL),
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX |
FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);
- iwl_write_direct32(priv,
+ iwl_write_direct32(bus(priv),
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
- priv->ucode_write_complete, 5 * HZ);
- if (ret == -ERESTARTSYS) {
- IWL_ERR(priv, "Could not load the %s uCode section due "
- "to interrupt\n", name);
- return ret;
- }
+ ret = wait_event_timeout(priv->shrd->wait_command_queue,
+ priv->ucode_write_complete, 5 * HZ);
if (!ret) {
IWL_ERR(priv, "Could not load the %s uCode section\n",
name);
@@ -163,7 +158,7 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
{
struct iwl_calib_temperature_offset_cmd cmd;
__le16 *offset_calib =
- (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
+ (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
memset(&cmd, 0, sizeof(cmd));
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
@@ -177,6 +172,42 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
(u8 *)&cmd, sizeof(cmd));
}
+static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv)
+{
+ struct iwl_calib_temperature_offset_v2_cmd cmd;
+ __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv,
+ EEPROM_KELVIN_TEMPERATURE);
+ __le16 *offset_calib_low =
+ (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
+ struct iwl_eeprom_calib_hdr *hdr;
+
+ memset(&cmd, 0, sizeof(cmd));
+ iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
+ hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
+ EEPROM_CALIB_ALL);
+ memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
+ sizeof(*offset_calib_high));
+ memcpy(&cmd.radio_sensor_offset_low, offset_calib_low,
+ sizeof(*offset_calib_low));
+ 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;
+ }
+ memcpy(&cmd.burntVoltageRef, &hdr->voltage,
+ sizeof(hdr->voltage));
+
+ IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n",
+ le16_to_cpu(cmd.radio_sensor_offset_high));
+ IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n",
+ le16_to_cpu(cmd.radio_sensor_offset_low));
+ IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
+ le16_to_cpu(cmd.burntVoltageRef));
+
+ return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
+ (u8 *)&cmd, sizeof(cmd));
+}
+
static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
{
struct iwl_calib_cfg_cmd calib_cfg_cmd;
@@ -193,11 +224,12 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
calib_cfg_cmd.ucd_calib_cfg.flags =
IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK;
- return trans_send_cmd(&priv->trans, &cmd);
+ return iwl_trans_send_cmd(trans(priv), &cmd);
}
-void iwlagn_rx_calib_result(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+int iwlagn_rx_calib_result(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
@@ -230,9 +262,10 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv,
default:
IWL_ERR(priv, "Unknown calibration notification %d\n",
hdr->op_code);
- return;
+ return -1;
}
iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
+ return 0;
}
int iwlagn_init_alive_start(struct iwl_priv *priv)
@@ -262,8 +295,12 @@ int iwlagn_init_alive_start(struct iwl_priv *priv)
* temperature offset calibration is only needed for runtime ucode,
* so prepare the value now.
*/
- if (priv->cfg->need_temp_offset_calib)
- return iwlagn_set_temperature_offset_calib(priv);
+ if (priv->cfg->need_temp_offset_calib) {
+ if (priv->cfg->temp_offset_v2)
+ return iwlagn_set_temperature_offset_calib_v2(priv);
+ else
+ return iwlagn_set_temperature_offset_calib(priv);
+ }
return 0;
}
@@ -291,7 +328,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
/* coexistence is disabled */
memset(&coex_cmd, 0, sizeof(coex_cmd));
}
- return trans_send_cmd_pdu(&priv->trans,
+ return iwl_trans_send_cmd_pdu(trans(priv),
COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
sizeof(coex_cmd), &coex_cmd);
}
@@ -324,7 +361,7 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv)
memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl,
sizeof(iwlagn_bt_prio_tbl));
- if (trans_send_cmd_pdu(&priv->trans,
+ if (iwl_trans_send_cmd_pdu(trans(priv),
REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,
sizeof(prio_tbl_cmd), &prio_tbl_cmd))
IWL_ERR(priv, "failed to send BT prio tbl command\n");
@@ -337,7 +374,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
env_cmd.action = action;
env_cmd.type = type;
- ret = trans_send_cmd_pdu(&priv->trans,
+ ret = iwl_trans_send_cmd_pdu(trans(priv),
REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
sizeof(env_cmd), &env_cmd);
if (ret)
@@ -348,9 +385,21 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
static int iwlagn_alive_notify(struct iwl_priv *priv)
{
+ struct iwl_rxon_context *ctx;
int ret;
- trans_tx_start(&priv->trans);
+ if (!priv->tx_cmd_pool)
+ priv->tx_cmd_pool =
+ kmem_cache_create("iwlagn_dev_cmd",
+ sizeof(struct iwl_device_cmd),
+ sizeof(void *), 0, NULL);
+
+ if (!priv->tx_cmd_pool)
+ return -ENOMEM;
+
+ iwl_trans_tx_start(trans(priv));
+ for_each_context(priv, ctx)
+ ctx->last_tx_rejected = false;
ret = iwlagn_send_wimax_coex(priv);
if (ret)
@@ -369,7 +418,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
* using sample data 100 bytes apart. If these sample points are good,
* it's a pretty good bet that everything between them is good, too.
*/
-static int iwlcore_verify_inst_sparse(struct iwl_priv *priv,
+static int iwl_verify_inst_sparse(struct iwl_priv *priv,
struct fw_desc *fw_desc)
{
__le32 *image = (__le32 *)fw_desc->v_addr;
@@ -383,9 +432,9 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv,
/* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log
* if IWL_DL_IO is set */
- iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+ iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR,
i + IWLAGN_RTC_INST_LOWER_BOUND);
- val = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
+ val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image))
return -EIO;
}
@@ -404,14 +453,14 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
- iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+ iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR,
IWLAGN_RTC_INST_LOWER_BOUND);
for (offs = 0;
offs < len && errors < 20;
offs += sizeof(u32), image++) {
/* read data comes through single port, auto-incr addr */
- val = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
+ val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image)) {
IWL_ERR(priv, "uCode INST section at "
"offset 0x%x, is 0x%x, s/b 0x%x\n",
@@ -427,7 +476,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
*/
static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img)
{
- if (!iwlcore_verify_inst_sparse(priv, &img->code)) {
+ if (!iwl_verify_inst_sparse(priv, &img->code)) {
IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
return 0;
}
@@ -478,7 +527,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
int ret;
enum iwlagn_ucode_type old_type;
- ret = trans_start_device(&priv->trans);
+ ret = iwl_trans_start_device(trans(priv));
if (ret)
return ret;
@@ -495,7 +544,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
return ret;
}
- trans_kick_nic(&priv->trans);
+ iwl_trans_kick_nic(trans(priv));
/*
* Some things may run in the background now, but we
@@ -545,7 +594,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
struct iwl_notification_wait calib_wait;
int ret;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
/* No init ucode required? Curious, but maybe ok */
if (!priv->ucode_init.code.len)
@@ -580,6 +629,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
iwlagn_remove_notification(priv, &calib_wait);
out:
/* Whatever happened, stop the device */
- trans_stop_device(&priv->trans);
+ iwl_trans_stop_device(trans(priv));
return ret;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index f9c3cd95d614..ccba69b7f8a7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -35,7 +35,6 @@
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
@@ -48,10 +47,9 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-sta.h"
#include "iwl-agn-calib.h"
#include "iwl-agn.h"
+#include "iwl-shared.h"
#include "iwl-bus.h"
#include "iwl-trans.h"
@@ -79,9 +77,7 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
-
-static int iwlagn_ant_coupling;
-static bool iwlagn_bt_ch_announce = 1;
+MODULE_ALIAS("iwlagn");
void iwl_update_chain_flags(struct iwl_priv *priv)
{
@@ -138,7 +134,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
* beacon contents.
*/
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
if (!priv->beacon_ctx) {
IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
@@ -183,7 +179,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->hw_params.valid_tx_ant);
+ hw_params(priv).valid_tx_ant);
rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
/* In mac80211, rates for 5 GHz start at 0 */
@@ -203,7 +199,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
cmd.data[1] = priv->beacon_skb->data;
cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
- return trans_send_cmd(&priv->trans, &cmd);
+ return iwl_trans_send_cmd(trans(priv), &cmd);
}
static void iwl_bg_beacon_update(struct work_struct *work)
@@ -212,7 +208,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
container_of(work, struct iwl_priv, beacon_update);
struct sk_buff *beacon;
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
if (!priv->beacon_ctx) {
IWL_ERR(priv, "updating beacon w/o beacon context!\n");
goto out;
@@ -242,7 +238,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
iwlagn_send_beacon_cmd(priv);
out:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
static void iwl_bg_bt_runtime_config(struct work_struct *work)
@@ -250,11 +246,11 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work)
struct iwl_priv *priv =
container_of(work, struct iwl_priv, bt_runtime_config);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
/* dont send host command if rf-kill is on */
- if (!iwl_is_ready_rf(priv))
+ if (!iwl_is_ready_rf(priv->shrd))
return;
iwlagn_send_advance_bt_config(priv);
}
@@ -265,13 +261,13 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
container_of(work, struct iwl_priv, bt_full_concurrency);
struct iwl_rxon_context *ctx;
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
goto out;
/* dont send host command if rf-kill is on */
- if (!iwl_is_ready_rf(priv))
+ if (!iwl_is_ready_rf(priv->shrd))
goto out;
IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
@@ -289,7 +285,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
iwlagn_send_advance_bt_config(priv);
out:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
/**
@@ -306,11 +302,11 @@ static void iwl_bg_statistics_periodic(unsigned long data)
{
struct iwl_priv *priv = (struct iwl_priv *)data;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
/* dont send host command if rf-kill is on */
- if (!iwl_is_ready_rf(priv))
+ if (!iwl_is_ready_rf(priv->shrd))
return;
iwl_send_statistics_request(priv, CMD_ASYNC, false);
@@ -332,14 +328,14 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
/* Make sure device is powered up for SRAM reads */
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- if (iwl_grab_nic_access(priv)) {
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+ spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags);
+ if (iwl_grab_nic_access(bus(priv))) {
+ spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags);
return;
}
/* Set starting address; reads will auto-increment */
- iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr);
+ iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr);
rmb();
/*
@@ -347,20 +343,20 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
* place event id # at far right for easier visual parsing.
*/
for (i = 0; i < num_events; i++) {
- ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
- time = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
+ ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
+ time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
if (mode == 0) {
trace_iwlwifi_dev_ucode_cont_event(priv,
0, time, ev);
} else {
- data = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
+ data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
trace_iwlwifi_dev_ucode_cont_event(priv,
time, data, ev);
}
}
/* Allow device to power down */
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+ iwl_release_nic_access(bus(priv));
+ spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags);
}
static void iwl_continuous_event_trace(struct iwl_priv *priv)
@@ -373,10 +369,12 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
base = priv->device_pointers.error_event_table;
if (iwlagn_hw_valid_rtc_data_addr(base)) {
- capacity = iwl_read_targ_mem(priv, base);
- num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
- mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
- next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
+ capacity = iwl_read_targ_mem(bus(priv), base);
+ num_wraps = iwl_read_targ_mem(bus(priv),
+ base + (2 * sizeof(u32)));
+ mode = iwl_read_targ_mem(bus(priv), base + (1 * sizeof(u32)));
+ next_entry = iwl_read_targ_mem(bus(priv),
+ base + (3 * sizeof(u32)));
} else
return;
@@ -427,7 +425,7 @@ static void iwl_bg_ucode_trace(unsigned long data)
{
struct iwl_priv *priv = (struct iwl_priv *)data;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
if (priv->event_log.ucode_trace) {
@@ -443,131 +441,17 @@ static void iwl_bg_tx_flush(struct work_struct *work)
struct iwl_priv *priv =
container_of(work, struct iwl_priv, tx_flush);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
/* do nothing if rf-kill is on */
- if (!iwl_is_ready_rf(priv))
+ if (!iwl_is_ready_rf(priv->shrd))
return;
IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
}
-/*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-
-/*
- * The following adds a new attribute to the sysfs representation
- * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
- * used for controlling the debug level.
- *
- * See the level definitions in iwl for details.
- *
- * The debug_level being managed using sysfs below is a per device debug
- * level that is used instead of the global debug level if it (the per
- * device debug level) is set.
- */
-static ssize_t show_debug_level(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
-}
-static ssize_t store_debug_level(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- unsigned long val;
- int ret;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret)
- IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
- else {
- priv->debug_level = val;
- if (iwl_alloc_traffic_mem(priv))
- IWL_ERR(priv,
- "Not enough memory to generate traffic log\n");
- }
- return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
- show_debug_level, store_debug_level);
-
-
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
-
-static ssize_t show_temperature(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
-
- if (!iwl_is_alive(priv))
- return -EAGAIN;
-
- return sprintf(buf, "%d\n", priv->temperature);
-}
-
-static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
-
-static ssize_t show_tx_power(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
-
- if (!iwl_is_ready_rf(priv))
- return sprintf(buf, "off\n");
- else
- return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
-}
-
-static ssize_t store_tx_power(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- unsigned long val;
- int ret;
-
- ret = strict_strtoul(buf, 10, &val);
- if (ret)
- IWL_INFO(priv, "%s is not in decimal form.\n", buf);
- else {
- ret = iwl_set_tx_power(priv, val, false);
- if (ret)
- IWL_ERR(priv, "failed setting tx power (0x%d).\n",
- ret);
- else
- ret = count;
- }
- return ret;
-}
-
-static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
-
-static struct attribute *iwl_sysfs_entries[] = {
- &dev_attr_temperature.attr,
- &dev_attr_tx_power.attr,
-#ifdef CONFIG_IWLWIFI_DEBUG
- &dev_attr_debug_level.attr,
-#endif
- NULL
-};
-
-static struct attribute_group iwl_attribute_group = {
- .name = NULL, /* put in device directory */
- .attrs = iwl_sysfs_entries,
-};
-
/******************************************************************************
*
* uCode download functions
@@ -577,7 +461,7 @@ static struct attribute_group iwl_attribute_group = {
static void iwl_free_fw_desc(struct iwl_priv *priv, struct fw_desc *desc)
{
if (desc->v_addr)
- dma_free_coherent(priv->bus->dev, desc->len,
+ dma_free_coherent(bus(priv)->dev, desc->len,
desc->v_addr, desc->p_addr);
desc->v_addr = NULL;
desc->len = 0;
@@ -604,7 +488,7 @@ static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,
return -EINVAL;
}
- desc->v_addr = dma_alloc_coherent(priv->bus->dev, len,
+ desc->v_addr = dma_alloc_coherent(bus(priv)->dev, len,
&desc->p_addr, GFP_KERNEL);
if (!desc->v_addr)
return -ENOMEM;
@@ -614,6 +498,64 @@ static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,
return 0;
}
+static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
+{
+ int i;
+
+ /*
+ * The default context is always valid,
+ * the PAN context depends on uCode.
+ */
+ priv->shrd->valid_contexts = BIT(IWL_RXON_CTX_BSS);
+ if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN)
+ priv->shrd->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
+
+ for (i = 0; i < NUM_IWL_RXON_CTX; i++)
+ priv->contexts[i].ctxid = i;
+
+ priv->contexts[IWL_RXON_CTX_BSS].always_active = true;
+ priv->contexts[IWL_RXON_CTX_BSS].is_active = true;
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
+ priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
+ priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
+ priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
+ priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
+ BIT(NL80211_IFTYPE_ADHOC);
+ priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
+ BIT(NL80211_IFTYPE_STATION);
+ priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
+ priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
+ priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
+ priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
+
+ priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
+ priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd =
+ REPLY_WIPAN_RXON_TIMING;
+ priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd =
+ REPLY_WIPAN_RXON_ASSOC;
+ priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
+ priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
+ priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
+ priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID;
+ priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION;
+ priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
+ BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
+
+ if (ucode_flags & IWL_UCODE_TLV_FLAGS_P2P)
+ priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO);
+
+ priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
+ priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
+ priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
+
+ BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+}
+
+
struct iwlagn_ucode_capabilities {
u32 max_probe_length;
u32 standard_phy_calibration_size;
@@ -621,7 +563,7 @@ struct iwlagn_ucode_capabilities {
};
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
-static int iwl_mac_setup_register(struct iwl_priv *priv,
+static int iwlagn_mac_setup_register(struct iwl_priv *priv,
struct iwlagn_ucode_capabilities *capa);
#define UCODE_EXPERIMENTAL_INDEX 100
@@ -658,7 +600,7 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
priv->firmware_name);
return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
- priv->bus->dev,
+ bus(priv)->dev,
GFP_KERNEL, priv, iwl_ucode_callback);
}
@@ -738,8 +680,6 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
return 0;
}
-static int iwlagn_wanted_ucode_alternative = 1;
-
static int iwlagn_load_firmware(struct iwl_priv *priv,
const struct firmware *ucode_raw,
struct iwlagn_firmware_pieces *pieces,
@@ -749,7 +689,8 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
struct iwl_ucode_tlv *tlv;
size_t len = ucode_raw->size;
const u8 *data;
- int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp;
+ int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative;
+ int tmp;
u64 alternatives;
u32 tlv_len;
enum iwl_ucode_tlv_type tlv_type;
@@ -952,6 +893,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
int err;
struct iwlagn_firmware_pieces pieces;
const unsigned int api_max = priv->cfg->ucode_api_max;
+ unsigned int api_ok = priv->cfg->ucode_api_ok;
const unsigned int api_min = priv->cfg->ucode_api_min;
u32 api_ver;
char buildstr[25];
@@ -962,10 +904,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE,
};
+ if (!api_ok)
+ api_ok = api_max;
+
memset(&pieces, 0, sizeof(pieces));
if (!ucode_raw) {
- if (priv->fw_index <= priv->cfg->ucode_api_max)
+ if (priv->fw_index <= api_ok)
IWL_ERR(priv,
"request for firmware file '%s' failed.\n",
priv->firmware_name);
@@ -1011,12 +956,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
goto try_again;
}
- if (api_ver != api_max)
- IWL_ERR(priv,
- "Firmware has old API version. Expected v%u, "
- "got v%u. New firmware can be obtained "
- "from http://www.intellinuxwireless.org.\n",
- api_max, api_ver);
+ if (api_ver < api_ok) {
+ if (api_ok != api_max)
+ IWL_ERR(priv, "Firmware has old API version, "
+ "expected v%u through v%u, got v%u.\n",
+ api_ok, api_max, api_ver);
+ else
+ IWL_ERR(priv, "Firmware has old API version, "
+ "expected v%u, got v%u.\n",
+ api_max, api_ver);
+ IWL_ERR(priv, "New firmware can be obtained from "
+ "http://www.intellinuxwireless.org/.\n");
+ }
}
if (build)
@@ -1060,25 +1011,25 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
pieces.init_data_size);
/* Verify that uCode images will fit in card's SRAM */
- if (pieces.inst_size > priv->hw_params.max_inst_size) {
+ if (pieces.inst_size > hw_params(priv).max_inst_size) {
IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n",
pieces.inst_size);
goto try_again;
}
- if (pieces.data_size > priv->hw_params.max_data_size) {
+ if (pieces.data_size > hw_params(priv).max_data_size) {
IWL_ERR(priv, "uCode data len %Zd too large to fit in\n",
pieces.data_size);
goto try_again;
}
- if (pieces.init_size > priv->hw_params.max_inst_size) {
+ if (pieces.init_size > hw_params(priv).max_inst_size) {
IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n",
pieces.init_size);
goto try_again;
}
- if (pieces.init_data_size > priv->hw_params.max_data_size) {
+ if (pieces.init_data_size > hw_params(priv).max_data_size) {
IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n",
pieces.init_data_size);
goto try_again;
@@ -1143,17 +1094,23 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
priv->new_scan_threshold_behaviour =
!!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
- if ((priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE) &&
- (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) {
- priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
+ if (!(priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
+ ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+
+ /*
+ * if not PAN, then don't support P2P -- might be a uCode
+ * packaging bug or due to the eeprom check above
+ */
+ if (!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN))
+ ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
+
+ if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
- } else
+ priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
+ } else {
priv->sta_key_max_num = STA_KEY_MAX_NUM;
-
- if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
- priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
- else
- priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+ priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+ }
/*
* figure out the offset of chain noise reset and gain commands
@@ -1169,12 +1126,15 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
priv->phy_calib_chain_noise_gain_cmd =
ucode_capa.standard_phy_calibration_size + 1;
+ /* initialize all valid contexts */
+ iwl_init_context(priv, ucode_capa.flags);
+
/**************************************************
* This is still part of probe() in a sense...
*
* 9. Setup and register with mac80211 and debugfs
**************************************************/
- err = iwl_mac_setup_register(priv, &ucode_capa);
+ err = iwlagn_mac_setup_register(priv, &ucode_capa);
if (err)
goto out_unbind;
@@ -1182,13 +1142,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
if (err)
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
- err = sysfs_create_group(&(priv->bus->dev->kobj),
- &iwl_attribute_group);
- if (err) {
- IWL_ERR(priv, "failed to create sysfs device attributes\n");
- goto out_unbind;
- }
-
/* We have our copies now, allow OS release its copies */
release_firmware(ucode_raw);
complete(&priv->firmware_loading_complete);
@@ -1206,368 +1159,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
iwl_dealloc_ucode(priv);
out_unbind:
complete(&priv->firmware_loading_complete);
- device_release_driver(priv->bus->dev);
+ device_release_driver(bus(priv)->dev);
release_firmware(ucode_raw);
}
-static const char * const desc_lookup_text[] = {
- "OK",
- "FAIL",
- "BAD_PARAM",
- "BAD_CHECKSUM",
- "NMI_INTERRUPT_WDG",
- "SYSASSERT",
- "FATAL_ERROR",
- "BAD_COMMAND",
- "HW_ERROR_TUNE_LOCK",
- "HW_ERROR_TEMPERATURE",
- "ILLEGAL_CHAN_FREQ",
- "VCC_NOT_STABLE",
- "FH_ERROR",
- "NMI_INTERRUPT_HOST",
- "NMI_INTERRUPT_ACTION_PT",
- "NMI_INTERRUPT_UNKNOWN",
- "UCODE_VERSION_MISMATCH",
- "HW_ERROR_ABS_LOCK",
- "HW_ERROR_CAL_LOCK_FAIL",
- "NMI_INTERRUPT_INST_ACTION_PT",
- "NMI_INTERRUPT_DATA_ACTION_PT",
- "NMI_TRM_HW_ER",
- "NMI_INTERRUPT_TRM",
- "NMI_INTERRUPT_BREAK_POINT",
- "DEBUG_0",
- "DEBUG_1",
- "DEBUG_2",
- "DEBUG_3",
-};
-
-static struct { char *name; u8 num; } advanced_lookup[] = {
- { "NMI_INTERRUPT_WDG", 0x34 },
- { "SYSASSERT", 0x35 },
- { "UCODE_VERSION_MISMATCH", 0x37 },
- { "BAD_COMMAND", 0x38 },
- { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
- { "FATAL_ERROR", 0x3D },
- { "NMI_TRM_HW_ERR", 0x46 },
- { "NMI_INTERRUPT_TRM", 0x4C },
- { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
- { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
- { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
- { "NMI_INTERRUPT_HOST", 0x66 },
- { "NMI_INTERRUPT_ACTION_PT", 0x7C },
- { "NMI_INTERRUPT_UNKNOWN", 0x84 },
- { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
- { "ADVANCED_SYSASSERT", 0 },
-};
-
-static const char *desc_lookup(u32 num)
-{
- int i;
- int max = ARRAY_SIZE(desc_lookup_text);
-
- if (num < max)
- return desc_lookup_text[num];
-
- max = ARRAY_SIZE(advanced_lookup) - 1;
- for (i = 0; i < max; i++) {
- if (advanced_lookup[i].num == num)
- break;
- }
- return advanced_lookup[i].name;
-}
-
-#define ERROR_START_OFFSET (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-
-void iwl_dump_nic_error_log(struct iwl_priv *priv)
-{
- u32 base;
- struct iwl_error_event_table table;
-
- base = priv->device_pointers.error_event_table;
- if (priv->ucode_type == IWL_UCODE_INIT) {
- if (!base)
- base = priv->init_errlog_ptr;
- } else {
- if (!base)
- base = priv->inst_errlog_ptr;
- }
-
- if (!iwlagn_hw_valid_rtc_data_addr(base)) {
- IWL_ERR(priv,
- "Not valid error log pointer 0x%08X for %s uCode\n",
- base,
- (priv->ucode_type == IWL_UCODE_INIT)
- ? "Init" : "RT");
- return;
- }
-
- iwl_read_targ_mem_words(priv, base, &table, sizeof(table));
-
- if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
- IWL_ERR(priv, "Start IWL Error Log Dump:\n");
- IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
- priv->status, table.valid);
- }
-
- priv->isr_stats.err_code = table.error_id;
-
- trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
- table.data1, table.data2, table.line,
- table.blink1, table.blink2, table.ilink1,
- table.ilink2, table.bcon_time, table.gp1,
- table.gp2, table.gp3, table.ucode_ver,
- table.hw_ver, table.brd_ver);
- IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id,
- desc_lookup(table.error_id));
- IWL_ERR(priv, "0x%08X | uPc\n", table.pc);
- IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1);
- IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2);
- IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1);
- IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2);
- IWL_ERR(priv, "0x%08X | data1\n", table.data1);
- IWL_ERR(priv, "0x%08X | data2\n", table.data2);
- IWL_ERR(priv, "0x%08X | line\n", table.line);
- IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time);
- IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low);
- IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi);
- IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1);
- IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2);
- IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3);
- IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver);
- IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver);
- IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver);
- IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd);
-}
-
-#define EVENT_START_OFFSET (4 * sizeof(u32))
-
-/**
- * iwl_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode,
- int pos, char **buf, size_t bufsz)
-{
- u32 i;
- u32 base; /* SRAM byte address of event log header */
- u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
- unsigned long reg_flags;
-
- if (num_events == 0)
- return pos;
-
- base = priv->device_pointers.log_event_table;
- if (priv->ucode_type == IWL_UCODE_INIT) {
- if (!base)
- base = priv->init_evtlog_ptr;
- } else {
- if (!base)
- base = priv->inst_evtlog_ptr;
- }
-
- if (mode == 0)
- event_size = 2 * sizeof(u32);
- else
- event_size = 3 * sizeof(u32);
-
- ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
- /* Make sure device is powered up for SRAM reads */
- spin_lock_irqsave(&priv->reg_lock, reg_flags);
- iwl_grab_nic_access(priv);
-
- /* Set starting address; reads will auto-increment */
- iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr);
- rmb();
-
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
- ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
- time = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
- if (mode == 0) {
- /* data, ev */
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "EVT_LOG:0x%08x:%04u\n",
- time, ev);
- } else {
- trace_iwlwifi_dev_ucode_event(priv, 0,
- time, ev);
- IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
- time, ev);
- }
- } else {
- data = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
- if (bufsz) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- } else {
- IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- trace_iwlwifi_dev_ucode_event(priv, time,
- data, ev);
- }
- }
- }
-
- /* Allow device to power down */
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
- return pos;
-}
-
-/**
- * iwl_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
- u32 num_wraps, u32 next_entry,
- u32 size, u32 mode,
- int pos, char **buf, size_t bufsz)
-{
- /*
- * display the newest DEFAULT_LOG_ENTRIES entries
- * i.e the entries just before the next ont that uCode would fill.
- */
- if (num_wraps) {
- if (next_entry < size) {
- pos = iwl_print_event_log(priv,
- capacity - (size - next_entry),
- size - next_entry, mode,
- pos, buf, bufsz);
- pos = iwl_print_event_log(priv, 0,
- next_entry, mode,
- pos, buf, bufsz);
- } else
- pos = iwl_print_event_log(priv, next_entry - size,
- size, mode, pos, buf, bufsz);
- } else {
- if (next_entry < size) {
- pos = iwl_print_event_log(priv, 0, next_entry,
- mode, pos, buf, bufsz);
- } else {
- pos = iwl_print_event_log(priv, next_entry - size,
- size, mode, pos, buf, bufsz);
- }
- }
- return pos;
-}
-
-#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
- char **buf, bool display)
-{
- u32 base; /* SRAM byte address of event log header */
- u32 capacity; /* event log capacity in # entries */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
- u32 size; /* # entries that we'll print */
- u32 logsize;
- int pos = 0;
- size_t bufsz = 0;
-
- base = priv->device_pointers.log_event_table;
- if (priv->ucode_type == IWL_UCODE_INIT) {
- logsize = priv->init_evtlog_size;
- if (!base)
- base = priv->init_evtlog_ptr;
- } else {
- logsize = priv->inst_evtlog_size;
- if (!base)
- base = priv->inst_evtlog_ptr;
- }
-
- if (!iwlagn_hw_valid_rtc_data_addr(base)) {
- IWL_ERR(priv,
- "Invalid event log pointer 0x%08X for %s uCode\n",
- base,
- (priv->ucode_type == IWL_UCODE_INIT)
- ? "Init" : "RT");
- return -EINVAL;
- }
-
- /* event log header */
- capacity = iwl_read_targ_mem(priv, base);
- mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- if (capacity > logsize) {
- IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
- capacity, logsize);
- capacity = logsize;
- }
-
- if (next_entry > logsize) {
- IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
- next_entry, logsize);
- next_entry = logsize;
- }
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return pos;
- }
-
- /* enable/disable bt channel inhibition */
- priv->bt_ch_announce = iwlagn_bt_ch_announce;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
- size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#else
- size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
- ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
- IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
- size);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (display) {
- if (full_log)
- bufsz = capacity * 48;
- else
- bufsz = size * 48;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- }
- if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
- /*
- * if uCode has wrapped back to top of log,
- * start at the oldest entry,
- * i.e the next one that uCode would fill.
- */
- if (num_wraps)
- pos = iwl_print_event_log(priv, next_entry,
- capacity - next_entry, mode,
- pos, buf, bufsz);
- /* (then/else) start at top of log */
- pos = iwl_print_event_log(priv, 0,
- next_entry, mode, pos, buf, bufsz);
- } else
- pos = iwl_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#else
- pos = iwl_print_last_event_logs(priv, capacity, num_wraps,
- next_entry, size, mode,
- pos, buf, bufsz);
-#endif
- return pos;
-}
-
static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
{
struct iwl_ct_kill_config cmd;
@@ -1575,44 +1170,43 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
unsigned long flags;
int ret = 0;
- spin_lock_irqsave(&priv->lock, flags);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ spin_lock_irqsave(&priv->shrd->lock, flags);
+ iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
priv->thermal_throttle.ct_kill_toggle = false;
if (priv->cfg->base_params->support_ct_kill_exit) {
adv_cmd.critical_temperature_enter =
- cpu_to_le32(priv->hw_params.ct_kill_threshold);
+ cpu_to_le32(hw_params(priv).ct_kill_threshold);
adv_cmd.critical_temperature_exit =
- cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
+ cpu_to_le32(hw_params(priv).ct_kill_exit_threshold);
- ret = trans_send_cmd_pdu(&priv->trans,
+ ret = iwl_trans_send_cmd_pdu(trans(priv),
REPLY_CT_KILL_CONFIG_CMD,
CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
if (ret)
IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
else
IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
- "succeeded, "
- "critical temperature enter is %d,"
- "exit is %d\n",
- priv->hw_params.ct_kill_threshold,
- priv->hw_params.ct_kill_exit_threshold);
+ "succeeded, critical temperature enter is %d,"
+ "exit is %d\n",
+ hw_params(priv).ct_kill_threshold,
+ hw_params(priv).ct_kill_exit_threshold);
} else {
cmd.critical_temperature_R =
- cpu_to_le32(priv->hw_params.ct_kill_threshold);
+ cpu_to_le32(hw_params(priv).ct_kill_threshold);
- ret = trans_send_cmd_pdu(&priv->trans,
+ ret = iwl_trans_send_cmd_pdu(trans(priv),
REPLY_CT_KILL_CONFIG_CMD,
CMD_SYNC, sizeof(cmd), &cmd);
if (ret)
IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
else
IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
- "succeeded, "
- "critical temperature is %d\n",
- priv->hw_params.ct_kill_threshold);
+ "succeeded, "
+ "critical temperature is %d\n",
+ hw_params(priv).ct_kill_threshold);
}
}
@@ -1626,10 +1220,10 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
};
memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
- calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
+ calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_RT_CFG_ALL;
calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
- return trans_send_cmd(&priv->trans, &cmd);
+ return iwl_trans_send_cmd(trans(priv), &cmd);
}
@@ -1641,7 +1235,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
if (IWL_UCODE_API(priv->ucode_ver) > 1) {
IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
- return trans_send_cmd_pdu(&priv->trans,
+ return iwl_trans_send_cmd_pdu(trans(priv),
TX_ANT_CONFIGURATION_CMD,
CMD_SYNC,
sizeof(struct iwl_tx_ant_config_cmd),
@@ -1663,17 +1257,17 @@ int iwl_alive_start(struct iwl_priv *priv)
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
/*TODO: this should go to the transport layer */
- iwl_reset_ict(priv);
+ iwl_reset_ict(trans(priv));
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
/* After the ALIVE response, we can send host commands to the uCode */
- set_bit(STATUS_ALIVE, &priv->status);
+ set_bit(STATUS_ALIVE, &priv->shrd->status);
/* Enable watchdog to monitor the driver tx queues */
iwl_setup_watchdog(priv);
- if (iwl_is_rfkill(priv))
+ if (iwl_is_rfkill(priv->shrd))
return -ERFKILL;
/* download priority table before any calibration request */
@@ -1710,8 +1304,9 @@ int iwl_alive_start(struct iwl_priv *priv)
iwl_send_bt_config(priv);
}
- if (priv->hw_params.calib_rt_cfg)
- iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
+ if (hw_params(priv).calib_rt_cfg)
+ iwlagn_send_calib_cfg_rt(priv,
+ hw_params(priv).calib_rt_cfg);
ieee80211_wake_queues(priv->hw);
@@ -1720,7 +1315,7 @@ int iwl_alive_start(struct iwl_priv *priv)
/* Configure Tx antenna selection based on H/W config */
iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);
- if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
+ if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) {
struct iwl_rxon_cmd *active_rxon =
(struct iwl_rxon_cmd *)&ctx->active;
/* apply any changes in staging */
@@ -1735,12 +1330,12 @@ int iwl_alive_start(struct iwl_priv *priv)
iwlagn_set_rxon_chain(priv, ctx);
}
- if (!priv->wowlan) {
+ if (!priv->shrd->wowlan) {
/* WoWLAN ucode will not reply in the same way, skip it */
iwl_reset_run_time_calib(priv);
}
- set_bit(STATUS_READY, &priv->status);
+ set_bit(STATUS_READY, &priv->shrd->status);
/* Configure the adapter for unassociated operation */
ret = iwlagn_commit_rxon(priv, ctx);
@@ -1765,7 +1360,15 @@ static void __iwl_down(struct iwl_priv *priv)
iwl_scan_cancel_timeout(priv, 200);
- exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
+ /*
+ * If active, scanning won't cancel it, so say it expired.
+ * No race since we hold the mutex here and a new one
+ * can't come in at this time.
+ */
+ ieee80211_remain_on_channel_expired(priv->hw);
+
+ exit_pending =
+ test_and_set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
* to prevent rearm timer */
@@ -1790,32 +1393,33 @@ static void __iwl_down(struct iwl_priv *priv)
/* Wipe out the EXIT_PENDING status bit if we are not actually
* exiting the module */
if (!exit_pending)
- clear_bit(STATUS_EXIT_PENDING, &priv->status);
+ clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
if (priv->mac80211_registered)
ieee80211_stop_queues(priv->hw);
+ iwl_trans_stop_device(trans(priv));
+
/* Clear out all status bits but a few that are stable across reset */
- priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
+ priv->shrd->status &=
+ test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) <<
STATUS_RF_KILL_HW |
- test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
+ test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) <<
STATUS_GEO_CONFIGURED |
- test_bit(STATUS_FW_ERROR, &priv->status) <<
+ test_bit(STATUS_FW_ERROR, &priv->shrd->status) <<
STATUS_FW_ERROR |
- test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+ test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) <<
STATUS_EXIT_PENDING;
- trans_stop_device(&priv->trans);
-
dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = NULL;
}
static void iwl_down(struct iwl_priv *priv)
{
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
__iwl_down(priv);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
iwl_cancel_deferred_work(priv);
}
@@ -1827,9 +1431,9 @@ static int __iwl_up(struct iwl_priv *priv)
struct iwl_rxon_context *ctx;
int ret;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
return -EIO;
}
@@ -1862,9 +1466,9 @@ static int __iwl_up(struct iwl_priv *priv)
return 0;
error:
- set_bit(STATUS_EXIT_PENDING, &priv->status);
+ set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
__iwl_down(priv);
- clear_bit(STATUS_EXIT_PENDING, &priv->status);
+ clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
IWL_ERR(priv, "Unable to initialize device.\n");
return ret;
@@ -1882,11 +1486,11 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv,
run_time_calib_work);
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
- test_bit(STATUS_SCANNING, &priv->status)) {
- mutex_unlock(&priv->mutex);
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) ||
+ test_bit(STATUS_SCANNING, &priv->shrd->status)) {
+ mutex_unlock(&priv->shrd->mutex);
return;
}
@@ -1895,7 +1499,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
iwl_sensitivity_calibration(priv);
}
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
static void iwlagn_prepare_restart(struct iwl_priv *priv)
@@ -1907,7 +1511,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
u8 bt_status;
bool bt_is_sco;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
for_each_context(priv, ctx)
ctx->vif = NULL;
@@ -1941,13 +1545,13 @@ static void iwl_bg_restart(struct work_struct *data)
{
struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
- if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
- mutex_lock(&priv->mutex);
+ if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) {
+ mutex_lock(&priv->shrd->mutex);
iwlagn_prepare_restart(priv);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
iwl_cancel_deferred_work(priv);
ieee80211_restart_hw(priv->hw);
} else {
@@ -1955,94 +1559,6 @@ static void iwl_bg_restart(struct work_struct *data)
}
}
-static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int wait)
-{
- struct iwl_priv *priv = hw->priv;
- int ret;
-
- /* Not supported if we don't have PAN */
- if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) {
- ret = -EOPNOTSUPP;
- goto free;
- }
-
- /* Not supported on pre-P2P firmware */
- if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
- BIT(NL80211_IFTYPE_P2P_CLIENT))) {
- ret = -EOPNOTSUPP;
- goto free;
- }
-
- mutex_lock(&priv->mutex);
-
- if (!priv->contexts[IWL_RXON_CTX_PAN].is_active) {
- /*
- * If the PAN context is free, use the normal
- * way of doing remain-on-channel offload + TX.
- */
- ret = 1;
- goto out;
- }
-
- /* TODO: queue up if scanning? */
- if (test_bit(STATUS_SCANNING, &priv->status) ||
- priv->offchan_tx_skb) {
- ret = -EBUSY;
- goto out;
- }
-
- /*
- * max_scan_ie_len doesn't include the blank SSID or the header,
- * so need to add that again here.
- */
- if (skb->len > hw->wiphy->max_scan_ie_len + 24 + 2) {
- ret = -ENOBUFS;
- goto out;
- }
-
- priv->offchan_tx_skb = skb;
- priv->offchan_tx_timeout = wait;
- priv->offchan_tx_chan = chan;
-
- ret = iwl_scan_initiate(priv, priv->contexts[IWL_RXON_CTX_PAN].vif,
- IWL_SCAN_OFFCH_TX, chan->band);
- if (ret)
- priv->offchan_tx_skb = NULL;
- out:
- mutex_unlock(&priv->mutex);
- free:
- if (ret < 0)
- kfree_skb(skb);
-
- return ret;
-}
-
-static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw)
-{
- struct iwl_priv *priv = hw->priv;
- int ret;
-
- mutex_lock(&priv->mutex);
-
- if (!priv->offchan_tx_skb) {
- ret = -EINVAL;
- goto unlock;
- }
-
- priv->offchan_tx_skb = NULL;
-
- ret = iwl_scan_cancel_timeout(priv, 200);
- if (ret)
- ret = -EIO;
-unlock:
- mutex_unlock(&priv->mutex);
-
- return ret;
-}
-
/*****************************************************************************
*
* mac80211 entry point functions
@@ -2124,7 +1640,7 @@ iwlagn_iface_combinations_p2p[] = {
* Not a mac80211 entry point function, but it fits in with all the
* other mac80211 functions grouped here.
*/
-static int iwl_mac_setup_register(struct iwl_priv *priv,
+static int iwlagn_mac_setup_register(struct iwl_priv *priv,
struct iwlagn_ucode_capabilities *capa)
{
int ret;
@@ -2183,7 +1699,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
WIPHY_FLAG_DISABLE_BEACON_HINTS |
WIPHY_FLAG_IBSS_RSN;
- if (priv->ucode_wowlan.code.len && device_can_wakeup(priv->bus->dev)) {
+ if (priv->ucode_wowlan.code.len && device_can_wakeup(bus(priv)->dev)) {
hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
@@ -2242,16 +1758,16 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw)
IWL_DEBUG_MAC80211(priv, "enter\n");
/* we should be verifying the device is ready to be opened */
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
ret = __iwl_up(priv);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
if (ret)
return ret;
IWL_DEBUG_INFO(priv, "Start UP work done.\n");
/* Now we should be done, and the READY bit should be set. */
- if (WARN_ON(!test_bit(STATUS_READY, &priv->status)))
+ if (WARN_ON(!test_bit(STATUS_READY, &priv->shrd->status)))
ret = -EIO;
iwlagn_led_enable(priv);
@@ -2274,17 +1790,17 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
iwl_down(priv);
- flush_workqueue(priv->workqueue);
+ flush_workqueue(priv->shrd->workqueue);
/* User space software may expect getting rfkill changes
* even if interface is down */
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+ iwl_write32(bus(priv), CSR_INT, 0xFFFFFFFF);
iwl_enable_rfkill_int(priv);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int iwlagn_send_patterns(struct iwl_priv *priv,
struct cfg80211_wowlan *wowlan)
{
@@ -2322,7 +1838,7 @@ static int iwlagn_send_patterns(struct iwl_priv *priv,
}
cmd.data[0] = pattern_cmd;
- err = trans_send_cmd(&priv->trans, &cmd);
+ err = iwl_trans_send_cmd(trans(priv), &cmd);
kfree(pattern_cmd);
return err;
}
@@ -2337,7 +1853,8 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
if (iwlagn_mod_params.sw_crypto)
return;
- mutex_lock(&priv->mutex);
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+ mutex_lock(&priv->shrd->mutex);
if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif)
goto out;
@@ -2348,7 +1865,8 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
priv->have_rekey_data = true;
out:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
}
struct wowlan_key_data {
@@ -2359,7 +1877,7 @@ struct wowlan_key_data {
bool error, use_rsc_tsc, use_tkip;
};
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static void iwlagn_convert_p1k(u16 *p1k, __le16 *out)
{
int i;
@@ -2386,7 +1904,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
u16 p1k[IWLAGN_P1K_SIZE];
int ret, i;
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
@@ -2491,7 +2009,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
break;
}
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
@@ -2516,7 +2034,8 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
if (WARN_ON(!wowlan))
return -EINVAL;
- mutex_lock(&priv->mutex);
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+ mutex_lock(&priv->shrd->mutex);
/* Don't attempt WoWLAN when not associated, tear down instead. */
if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION ||
@@ -2545,7 +2064,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
* since the uCode will add 0x10 before using the value.
*/
for (i = 0; i < 8; i++) {
- seq = priv->stations[IWL_AP_ID].tid[i].seq_number;
+ seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number;
seq -= 0x10;
wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);
}
@@ -2577,9 +2096,9 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
memcpy(&rxon, &ctx->active, sizeof(rxon));
- trans_stop_device(&priv->trans);
+ iwl_trans_stop_device(trans(priv));
- priv->wowlan = true;
+ priv->shrd->wowlan = true;
ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_wowlan,
IWL_UCODE_WOWLAN);
@@ -2610,11 +2129,11 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
* constraints. Since we're in the suspend path
* that isn't really a problem though.
*/
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
ieee80211_iter_keys(priv->hw, ctx->vif,
iwlagn_wowlan_program_keys,
&key_data);
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
if (key_data.error) {
ret = -EIO;
goto error;
@@ -2629,13 +2148,13 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
.len[0] = sizeof(*key_data.rsc_tsc),
};
- ret = trans_send_cmd(&priv->trans, &rsc_tsc_cmd);
+ ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd);
if (ret)
goto error;
}
if (key_data.use_tkip) {
- ret = trans_send_cmd_pdu(&priv->trans,
+ ret = iwl_trans_send_cmd_pdu(trans(priv),
REPLY_WOWLAN_TKIP_PARAMS,
CMD_SYNC, sizeof(tkip_cmd),
&tkip_cmd);
@@ -2651,7 +2170,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
kek_kck_cmd.replay_ctr = priv->replay_ctr;
- ret = trans_send_cmd_pdu(&priv->trans,
+ ret = iwl_trans_send_cmd_pdu(trans(priv),
REPLY_WOWLAN_KEK_KCK_MATERIAL,
CMD_SYNC, sizeof(kek_kck_cmd),
&kek_kck_cmd);
@@ -2660,7 +2179,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
}
}
- ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_WAKEUP_FILTER,
+ ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER,
CMD_SYNC, sizeof(wakeup_filter_cmd),
&wakeup_filter_cmd);
if (ret)
@@ -2670,21 +2189,23 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
if (ret)
goto error;
- device_set_wakeup_enable(priv->bus->dev, true);
+ device_set_wakeup_enable(bus(priv)->dev, true);
/* Now let the ucode operate on its own */
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
goto out;
error:
- priv->wowlan = false;
+ priv->shrd->wowlan = false;
iwlagn_prepare_restart(priv);
ieee80211_restart_hw(priv->hw);
out:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
kfree(key_data.rsc_tsc);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+
return ret;
}
@@ -2697,21 +2218,22 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
u32 base, status = 0xffffffff;
int ret = -EIO;
- mutex_lock(&priv->mutex);
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+ mutex_lock(&priv->shrd->mutex);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
base = priv->device_pointers.error_event_table;
if (iwlagn_hw_valid_rtc_data_addr(base)) {
- spin_lock_irqsave(&priv->reg_lock, flags);
- ret = iwl_grab_nic_access_silent(priv);
+ spin_lock_irqsave(&bus(priv)->reg_lock, flags);
+ ret = iwl_grab_nic_access_silent(bus(priv));
if (ret == 0) {
- iwl_write32(priv, HBUS_TARG_MEM_RADDR, base);
- status = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
- iwl_release_nic_access(priv);
+ iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, base);
+ status = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
+ iwl_release_nic_access(bus(priv));
}
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_unlock_irqrestore(&bus(priv)->reg_lock, flags);
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (ret == 0) {
@@ -2722,7 +2244,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
if (priv->wowlan_sram)
_iwl_read_targ_mem_words(
- priv, 0x800000, priv->wowlan_sram,
+ bus(priv), 0x800000, priv->wowlan_sram,
priv->ucode_wowlan.data.len / 4);
}
#endif
@@ -2731,9 +2253,9 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
/* we'll clear ctx->vif during iwlagn_prepare_restart() */
vif = ctx->vif;
- priv->wowlan = false;
+ priv->shrd->wowlan = false;
- device_set_wakeup_enable(priv->bus->dev, false);
+ device_set_wakeup_enable(bus(priv)->dev, false);
iwlagn_prepare_restart(priv);
@@ -2741,7 +2263,8 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
iwl_connection_init_rx_config(priv, ctx);
iwlagn_set_rxon_chain(priv, ctx);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
ieee80211_resume_disconnect(vif);
@@ -2810,7 +2333,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET)
return 0;
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
iwl_scan_cancel_timeout(priv, 100);
BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT);
@@ -2861,7 +2384,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
ret = -EINVAL;
}
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return ret;
@@ -2876,6 +2399,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
struct iwl_priv *priv = hw->priv;
int ret = -EINVAL;
struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
+ struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
sta->addr, tid);
@@ -2883,7 +2407,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE))
return -EACCES;
- mutex_lock(&priv->mutex);
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+ mutex_lock(&priv->shrd->mutex);
switch (action) {
case IEEE80211_AMPDU_RX_START:
@@ -2893,17 +2418,12 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_RX_STOP:
IWL_DEBUG_HT(priv, "stop Rx\n");
ret = iwl_sta_rx_agg_stop(priv, sta, tid);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
ret = 0;
break;
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT(priv, "start Tx\n");
ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
- if (ret == 0) {
- priv->agg_tids_count++;
- IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
- priv->agg_tids_count);
- }
break;
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT(priv, "stop Tx\n");
@@ -2913,9 +2433,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
priv->agg_tids_count);
}
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
ret = 0;
- if (priv->cfg->ht_params &&
+ if (!priv->agg_tids_count && priv->cfg->ht_params &&
priv->cfg->ht_params->use_rts_for_aggregation) {
/*
* switch off RTS/CTS if it was previously enabled
@@ -2929,8 +2449,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_TX_OPERATIONAL:
buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
- trans_txq_agg_setup(&priv->trans, iwl_sta_id(sta), tid,
- buf_size);
+ iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, iwl_sta_id(sta),
+ tid, buf_size);
/*
* If the limit is 0, then it wasn't initialised yet,
@@ -2962,6 +2482,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
sta_priv->lq_sta.lq.general_params.flags |=
LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
}
+ priv->agg_tids_count++;
+ IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
+ priv->agg_tids_count);
sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
sta_priv->max_agg_bufsize;
@@ -2974,8 +2497,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
ret = 0;
break;
}
- mutex_unlock(&priv->mutex);
-
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
return ret;
}
@@ -2987,15 +2510,15 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
- int ret;
+ int ret = 0;
u8 sta_id;
- IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
+ IWL_DEBUG_MAC80211(priv, "received request to add station %pM\n",
sta->addr);
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
sta->addr);
- sta_priv->common.sta_id = IWL_INVALID_STATION;
+ sta_priv->sta_id = IWL_INVALID_STATION;
atomic_set(&sta_priv->pending_frames, 0);
if (vif->type == NL80211_IFTYPE_AP)
@@ -3007,19 +2530,20 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
/* Should we return success if return code is EEXIST ? */
- mutex_unlock(&priv->mutex);
- return ret;
+ goto out;
}
- sta_priv->common.sta_id = sta_id;
+ sta_priv->sta_id = sta_id;
/* Initialize rate scaling */
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
sta->addr);
iwl_rs_rate_init(priv, sta, sta_id);
- mutex_unlock(&priv->mutex);
+ out:
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
- return 0;
+ return ret;
}
static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
@@ -3043,14 +2567,14 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
- if (iwl_is_rfkill(priv))
+ if (iwl_is_rfkill(priv->shrd))
goto out;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
- test_bit(STATUS_SCANNING, &priv->status) ||
- test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) ||
+ test_bit(STATUS_SCANNING, &priv->shrd->status) ||
+ test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
goto out;
if (!iwl_is_associated_ctx(ctx))
@@ -3069,7 +2593,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
goto out;
}
- spin_lock_irq(&priv->lock);
+ spin_lock_irq(&priv->shrd->lock);
priv->current_ht_config.smps = conf->smps_mode;
@@ -3099,23 +2623,23 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
iwl_set_rxon_ht(priv, ht_conf);
iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
- spin_unlock_irq(&priv->lock);
+ spin_unlock_irq(&priv->shrd->lock);
iwl_set_rate(priv);
/*
* at this point, staging_rxon has the
* configuration for channel switch
*/
- set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+ set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
priv->switch_channel = cpu_to_le16(ch);
if (priv->cfg->lib->set_channel_switch(priv, ch_switch)) {
- clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+ clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
priv->switch_channel = 0;
ieee80211_chswitch_done(ctx->vif, false);
}
out:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
@@ -3145,7 +2669,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
#undef CHK
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
for_each_context(priv, ctx) {
ctx->staging.filter_flags &= ~filter_nand;
@@ -3157,7 +2681,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
*/
}
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
/*
* Receiving all multicast frames is always enabled by the
@@ -3173,14 +2697,14 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
{
struct iwl_priv *priv = hw->priv;
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n");
- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
goto done;
}
- if (iwl_is_rfkill(priv)) {
+ if (iwl_is_rfkill(priv->shrd)) {
IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n");
goto done;
}
@@ -3197,101 +2721,198 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
}
}
IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
- iwlagn_wait_tx_queue_empty(priv);
+ iwl_trans_wait_tx_queue_empty(trans(priv));
done:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
-static void iwlagn_disable_roc(struct iwl_priv *priv)
+void iwlagn_disable_roc(struct iwl_priv *priv)
{
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
- struct ieee80211_channel *chan = ACCESS_ONCE(priv->hw->conf.channel);
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
- if (!ctx->is_active)
+ if (!priv->hw_roc_setup)
return;
- ctx->staging.dev_type = RXON_DEV_TYPE_2STA;
+ ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_set_rxon_channel(priv, chan, ctx);
- iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
priv->hw_roc_channel = NULL;
+ memset(ctx->staging.node_addr, 0, ETH_ALEN);
+
iwlagn_commit_rxon(priv, ctx);
ctx->is_active = false;
+ priv->hw_roc_setup = false;
}
-static void iwlagn_bg_roc_done(struct work_struct *work)
+static void iwlagn_disable_roc_work(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv,
- hw_roc_work.work);
+ hw_roc_disable_work.work);
- mutex_lock(&priv->mutex);
- ieee80211_remain_on_channel_expired(priv->hw);
+ mutex_lock(&priv->shrd->mutex);
iwlagn_disable_roc(priv);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
-static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
+static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type,
int duration)
{
struct iwl_priv *priv = hw->priv;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
int err = 0;
- if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+ if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
return -EOPNOTSUPP;
- if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
- BIT(NL80211_IFTYPE_P2P_CLIENT)))
+ if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)))
return -EOPNOTSUPP;
- mutex_lock(&priv->mutex);
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+ mutex_lock(&priv->shrd->mutex);
- if (priv->contexts[IWL_RXON_CTX_PAN].is_active ||
- test_bit(STATUS_SCAN_HW, &priv->status)) {
+ if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
err = -EBUSY;
goto out;
}
- priv->contexts[IWL_RXON_CTX_PAN].is_active = true;
priv->hw_roc_channel = channel;
priv->hw_roc_chantype = channel_type;
- priv->hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024);
- iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
- queue_delayed_work(priv->workqueue, &priv->hw_roc_work,
- msecs_to_jiffies(duration + 20));
+ priv->hw_roc_duration = duration;
+ priv->hw_roc_start_notified = false;
+ cancel_delayed_work(&priv->hw_roc_disable_work);
+
+ if (!ctx->is_active) {
+ ctx->is_active = true;
+ ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
+ memcpy(ctx->staging.node_addr,
+ priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr,
+ ETH_ALEN);
+ memcpy(ctx->staging.bssid_addr,
+ priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr,
+ ETH_ALEN);
+ err = iwlagn_commit_rxon(priv, ctx);
+ if (err)
+ goto out;
+ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK |
+ RXON_FILTER_PROMISC_MSK |
+ RXON_FILTER_CTL2HOST_MSK;
+
+ err = iwlagn_commit_rxon(priv, ctx);
+ if (err) {
+ iwlagn_disable_roc(priv);
+ goto out;
+ }
+ priv->hw_roc_setup = true;
+ }
- msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */
- ieee80211_ready_on_channel(priv->hw);
+ err = iwl_scan_initiate(priv, ctx->vif, IWL_SCAN_ROC, channel->band);
+ if (err)
+ iwlagn_disable_roc(priv);
out:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
return err;
}
-static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
+static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
- if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+ if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
return -EOPNOTSUPP;
- cancel_delayed_work_sync(&priv->hw_roc_work);
-
- mutex_lock(&priv->mutex);
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+ mutex_lock(&priv->shrd->mutex);
+ iwl_scan_cancel_timeout(priv, priv->hw_roc_duration);
iwlagn_disable_roc(priv);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
return 0;
}
+static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const u8 *bssid,
+ enum ieee80211_tx_sync_type type)
+{
+ struct iwl_priv *priv = hw->priv;
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+ struct iwl_rxon_context *ctx = vif_priv->ctx;
+ int ret;
+ u8 sta_id;
+
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+ mutex_lock(&priv->shrd->mutex);
+
+ if (iwl_is_associated_ctx(ctx)) {
+ ret = 0;
+ goto out;
+ }
+
+ if (ctx->preauth_bssid || test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ret = iwl_add_station_common(priv, ctx, bssid, true, NULL, &sta_id);
+ if (ret)
+ goto out;
+
+ if (WARN_ON(sta_id != ctx->ap_sta_id)) {
+ ret = -EIO;
+ goto out_remove_sta;
+ }
+
+ memcpy(ctx->bssid, bssid, ETH_ALEN);
+ ctx->preauth_bssid = true;
+
+ ret = iwlagn_commit_rxon(priv, ctx);
+
+ if (ret == 0)
+ goto out;
+
+ out_remove_sta:
+ iwl_remove_station(priv, sta_id, bssid);
+ out:
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+
+ return ret;
+}
+
+static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const u8 *bssid,
+ enum ieee80211_tx_sync_type type)
+{
+ struct iwl_priv *priv = hw->priv;
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+ struct iwl_rxon_context *ctx = vif_priv->ctx;
+
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+ mutex_lock(&priv->shrd->mutex);
+
+ if (iwl_is_associated_ctx(ctx))
+ goto out;
+
+ iwl_remove_station(priv, ctx->ap_sta_id, bssid);
+ ctx->preauth_bssid = false;
+ /* no need to commit */
+ out:
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
/*****************************************************************************
*
* driver setup and teardown
@@ -3300,9 +2921,9 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
static void iwl_setup_deferred_work(struct iwl_priv *priv)
{
- priv->workqueue = create_singlethread_workqueue(DRV_NAME);
+ priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME);
- init_waitqueue_head(&priv->wait_command_queue);
+ init_waitqueue_head(&priv->shrd->wait_command_queue);
INIT_WORK(&priv->restart, iwl_bg_restart);
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
@@ -3310,7 +2931,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
- INIT_DELAYED_WORK(&priv->hw_roc_work, iwlagn_bg_roc_done);
+ INIT_DELAYED_WORK(&priv->hw_roc_disable_work,
+ iwlagn_disable_roc_work);
iwl_setup_scan_deferred_work(priv);
@@ -3342,6 +2964,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->bt_full_concurrency);
cancel_work_sync(&priv->bt_runtime_config);
+ cancel_delayed_work_sync(&priv->hw_roc_disable_work);
del_timer_sync(&priv->statistics_periodic);
del_timer_sync(&priv->ucode_trace);
@@ -3372,10 +2995,9 @@ static int iwl_init_drv(struct iwl_priv *priv)
{
int ret;
- spin_lock_init(&priv->sta_lock);
- spin_lock_init(&priv->hcmd_lock);
+ spin_lock_init(&priv->shrd->sta_lock);
- mutex_init(&priv->mutex);
+ mutex_init(&priv->shrd->mutex);
priv->ieee_channels = NULL;
priv->ieee_rates = NULL;
@@ -3416,7 +3038,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
goto err;
}
- ret = iwlcore_init_geos(priv);
+ ret = iwl_init_geos(priv);
if (ret) {
IWL_ERR(priv, "initializing geos failed: %d\n", ret);
goto err_free_channel_map;
@@ -3434,8 +3056,10 @@ err:
static void iwl_uninit_drv(struct iwl_priv *priv)
{
iwl_calib_free_results(priv);
- iwlcore_free_geos(priv);
+ iwl_free_geos(priv);
iwl_free_channel_map(priv);
+ if (priv->tx_cmd_pool)
+ kmem_cache_destroy(priv->tx_cmd_pool);
kfree(priv->scan_cmd);
kfree(priv->beacon_cmd);
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -3443,12 +3067,13 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
#endif
}
-static void iwl_mac_rssi_callback(struct ieee80211_hw *hw,
+static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
enum ieee80211_rssi_event rssi_event)
{
struct iwl_priv *priv = hw->priv;
- mutex_lock(&priv->mutex);
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+ mutex_lock(&priv->shrd->mutex);
if (priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist) {
@@ -3463,89 +3088,88 @@ static void iwl_mac_rssi_callback(struct ieee80211_hw *hw,
"ignoring RSSI callback\n");
}
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+static int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, bool set)
+{
+ struct iwl_priv *priv = hw->priv;
+
+ queue_work(priv->shrd->workqueue, &priv->beacon_update);
+
+ return 0;
}
struct ieee80211_ops iwlagn_hw_ops = {
.tx = iwlagn_mac_tx,
.start = iwlagn_mac_start,
.stop = iwlagn_mac_stop,
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
.suspend = iwlagn_mac_suspend,
.resume = iwlagn_mac_resume,
#endif
- .add_interface = iwl_mac_add_interface,
- .remove_interface = iwl_mac_remove_interface,
- .change_interface = iwl_mac_change_interface,
+ .add_interface = iwlagn_mac_add_interface,
+ .remove_interface = iwlagn_mac_remove_interface,
+ .change_interface = iwlagn_mac_change_interface,
.config = iwlagn_mac_config,
.configure_filter = iwlagn_configure_filter,
.set_key = iwlagn_mac_set_key,
.update_tkip_key = iwlagn_mac_update_tkip_key,
.set_rekey_data = iwlagn_mac_set_rekey_data,
- .conf_tx = iwl_mac_conf_tx,
+ .conf_tx = iwlagn_mac_conf_tx,
.bss_info_changed = iwlagn_bss_info_changed,
.ampdu_action = iwlagn_mac_ampdu_action,
- .hw_scan = iwl_mac_hw_scan,
+ .hw_scan = iwlagn_mac_hw_scan,
.sta_notify = iwlagn_mac_sta_notify,
.sta_add = iwlagn_mac_sta_add,
- .sta_remove = iwl_mac_sta_remove,
+ .sta_remove = iwlagn_mac_sta_remove,
.channel_switch = iwlagn_mac_channel_switch,
.flush = iwlagn_mac_flush,
- .tx_last_beacon = iwl_mac_tx_last_beacon,
- .remain_on_channel = iwl_mac_remain_on_channel,
- .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,
- .offchannel_tx = iwl_mac_offchannel_tx,
- .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
- .rssi_callback = iwl_mac_rssi_callback,
- CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
- CFG80211_TESTMODE_DUMP(iwl_testmode_dump)
+ .tx_last_beacon = iwlagn_mac_tx_last_beacon,
+ .remain_on_channel = iwlagn_mac_remain_on_channel,
+ .cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel,
+ .rssi_callback = iwlagn_mac_rssi_callback,
+ CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd)
+ CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump)
+ .tx_sync = iwlagn_mac_tx_sync,
+ .finish_tx_sync = iwlagn_mac_finish_tx_sync,
+ .set_tim = iwlagn_mac_set_tim,
};
static u32 iwl_hw_detect(struct iwl_priv *priv)
{
- return iwl_read32(priv, CSR_HW_REV);
+ return iwl_read32(bus(priv), CSR_HW_REV);
}
+/* Size of one Rx buffer in host DRAM */
+#define IWL_RX_BUF_SIZE_4K (4 * 1024)
+#define IWL_RX_BUF_SIZE_8K (8 * 1024)
+
static int iwl_set_hw_params(struct iwl_priv *priv)
{
- priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
- priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
if (iwlagn_mod_params.amsdu_size_8K)
- priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
+ hw_params(priv).rx_page_order =
+ get_order(IWL_RX_BUF_SIZE_8K);
else
- priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
-
- priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
+ hw_params(priv).rx_page_order =
+ get_order(IWL_RX_BUF_SIZE_4K);
if (iwlagn_mod_params.disable_11n)
priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
+ hw_params(priv).num_ampdu_queues =
+ priv->cfg->base_params->num_of_ampdu_queues;
+ hw_params(priv).shadow_reg_enable =
+ priv->cfg->base_params->shadow_reg_enable;
+ hw_params(priv).sku = priv->cfg->sku;
+ hw_params(priv).wd_timeout = priv->cfg->base_params->wd_timeout;
+
/* Device-specific setup */
return priv->cfg->lib->set_hw_params(priv);
}
-static const u8 iwlagn_bss_ac_to_fifo[] = {
- IWL_TX_FIFO_VO,
- IWL_TX_FIFO_VI,
- IWL_TX_FIFO_BE,
- IWL_TX_FIFO_BK,
-};
-
-static const u8 iwlagn_bss_ac_to_queue[] = {
- 0, 1, 2, 3,
-};
-
-static const u8 iwlagn_pan_ac_to_fifo[] = {
- IWL_TX_FIFO_VO_IPAN,
- IWL_TX_FIFO_VI_IPAN,
- IWL_TX_FIFO_BE_IPAN,
- IWL_TX_FIFO_BK_IPAN,
-};
-
-static const u8 iwlagn_pan_ac_to_queue[] = {
- 7, 6, 5, 4,
-};
-
/* This function both allocates and initializes hw and priv. */
static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
{
@@ -3568,66 +3192,8 @@ out:
return hw;
}
-static void iwl_init_context(struct iwl_priv *priv)
-{
- int i;
-
- /*
- * The default context is always valid,
- * more may be discovered when firmware
- * is loaded.
- */
- priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
-
- for (i = 0; i < NUM_IWL_RXON_CTX; i++)
- priv->contexts[i].ctxid = i;
-
- priv->contexts[IWL_RXON_CTX_BSS].always_active = true;
- priv->contexts[IWL_RXON_CTX_BSS].is_active = true;
- priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
- priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
- priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
- priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
- priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
- priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
- priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo;
- priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue;
- priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
- BIT(NL80211_IFTYPE_ADHOC);
- priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
- BIT(NL80211_IFTYPE_STATION);
- priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
- priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
- priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
- priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
-
- priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
- priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd =
- REPLY_WIPAN_RXON_TIMING;
- priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd =
- REPLY_WIPAN_RXON_ASSOC;
- priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
- priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
- priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
- priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID;
- priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION;
- priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo;
- priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue;
- priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
- priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
- BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
-#ifdef CONFIG_IWL_P2P
- priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
- BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
-#endif
- priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
- priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
- priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
-
- BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
-}
-
-int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
+int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
+ struct iwl_cfg *cfg)
{
int err = 0;
struct iwl_priv *priv;
@@ -3645,24 +3211,32 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
}
priv = hw->priv;
- priv->bus = bus;
- bus_set_drv_data(priv->bus, priv);
+ priv->shrd = &priv->_shrd;
+ bus->shrd = priv->shrd;
+ priv->shrd->bus = bus;
+ priv->shrd->priv = priv;
+
+ priv->shrd->trans = trans_ops->alloc(priv->shrd);
+ if (priv->shrd->trans == NULL) {
+ err = -ENOMEM;
+ goto out_free_traffic_mem;
+ }
/* At this point both hw and priv are allocated. */
- SET_IEEE80211_DEV(hw, priv->bus->dev);
+ SET_IEEE80211_DEV(hw, bus(priv)->dev);
IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
priv->cfg = cfg;
- priv->inta_mask = CSR_INI_SET_MASK;
/* is antenna coupling more than 35dB ? */
priv->bt_ant_couple_ok =
- (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
- true : false;
+ (iwlagn_mod_params.ant_coupling >
+ IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
+ true : false;
/* enable/disable bt channel inhibition */
- priv->bt_ch_announce = iwlagn_bt_ch_announce;
+ priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce;
IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n",
(priv->bt_ch_announce) ? "On" : "Off");
@@ -3672,15 +3246,15 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
/* these spin locks will be used in apm_ops.init and EEPROM access
* we should init now
*/
- spin_lock_init(&priv->reg_lock);
- spin_lock_init(&priv->lock);
+ spin_lock_init(&bus(priv)->reg_lock);
+ spin_lock_init(&priv->shrd->lock);
/*
* stop and reset the on-board processor just in case it is in a
* strange state ... like being left stranded by a primary kernel
* and this is now the kdump kernel trying to start up
*/
- iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+ iwl_write32(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
/***********************
* 3. Read REV register
@@ -3689,11 +3263,11 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
IWL_INFO(priv, "Detected %s, REV=0x%X\n",
priv->cfg->name, hw_rev);
- err = iwl_trans_register(&priv->trans, priv);
+ err = iwl_trans_request_irq(trans(priv));
if (err)
- goto out_free_traffic_mem;
+ goto out_free_trans;
- if (trans_prepare_card_hw(&priv->trans)) {
+ if (iwl_trans_prepare_card_hw(trans(priv))) {
err = -EIO;
IWL_WARN(priv, "Failed, HW not ready\n");
goto out_free_trans;
@@ -3729,9 +3303,6 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
priv->hw->wiphy->n_addresses++;
}
- /* initialize all valid contexts */
- iwl_init_context(priv);
-
/************************
* 5. Setup HW constants
************************/
@@ -3764,13 +3335,14 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
iwl_enable_rfkill_int(priv);
/* If platform's RF_KILL switch is NOT set to KILL */
- if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ if (iwl_read32(bus(priv),
+ CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+ clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
else
- set_bit(STATUS_RF_KILL_HW, &priv->status);
+ set_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
- test_bit(STATUS_RF_KILL_HW, &priv->status));
+ test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
iwl_power_initialize(priv);
iwl_tt_initialize(priv);
@@ -3784,13 +3356,13 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
return 0;
out_destroy_workqueue:
- destroy_workqueue(priv->workqueue);
- priv->workqueue = NULL;
+ destroy_workqueue(priv->shrd->workqueue);
+ priv->shrd->workqueue = NULL;
iwl_uninit_drv(priv);
out_free_eeprom:
iwl_eeprom_free(priv);
out_free_trans:
- trans_free(&priv->trans);
+ iwl_trans_free(trans(priv));
out_free_traffic_mem:
iwl_free_traffic_mem(priv);
ieee80211_free_hw(priv->hw);
@@ -3800,21 +3372,17 @@ out:
void __devexit iwl_remove(struct iwl_priv * priv)
{
- unsigned long flags;
-
wait_for_completion(&priv->firmware_loading_complete);
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
iwl_dbgfs_unregister(priv);
- sysfs_remove_group(&priv->bus->dev->kobj,
- &iwl_attribute_group);
- /* ieee80211_unregister_hw call wil cause iwl_mac_stop to
+ /* ieee80211_unregister_hw call wil cause iwlagn_mac_stop to
* to be called and iwl_down since we are removing the device
* we need to set STATUS_EXIT_PENDING bit.
*/
- set_bit(STATUS_EXIT_PENDING, &priv->status);
+ set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
iwl_testmode_cleanup(priv);
iwl_leds_exit(priv);
@@ -3824,40 +3392,26 @@ void __devexit iwl_remove(struct iwl_priv * priv)
priv->mac80211_registered = 0;
}
- /* Reset to low power before unloading driver. */
- iwl_apm_stop(priv);
-
iwl_tt_exit(priv);
- /* make sure we flush any pending irq or
- * tasklet for the driver
- */
- spin_lock_irqsave(&priv->lock, flags);
- iwl_disable_interrupts(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- trans_sync_irq(&priv->trans);
+ /*This will stop the queues, move the device to low power state */
+ iwl_trans_stop_device(trans(priv));
iwl_dealloc_ucode(priv);
- trans_rx_free(&priv->trans);
- trans_tx_free(&priv->trans);
-
iwl_eeprom_free(priv);
/*netif_stop_queue(dev); */
- flush_workqueue(priv->workqueue);
+ flush_workqueue(priv->shrd->workqueue);
- /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
- * priv->workqueue... so we can't take down the workqueue
+ /* ieee80211_unregister_hw calls iwlagn_mac_stop, which flushes
+ * priv->shrd->workqueue... so we can't take down the workqueue
* until now... */
- destroy_workqueue(priv->workqueue);
- priv->workqueue = NULL;
+ destroy_workqueue(priv->shrd->workqueue);
+ priv->shrd->workqueue = NULL;
iwl_free_traffic_mem(priv);
- trans_free(&priv->trans);
-
- bus_set_drv_data(priv->bus, NULL);
+ iwl_trans_free(trans(priv));
iwl_uninit_drv(priv);
@@ -3906,7 +3460,8 @@ module_exit(iwl_exit);
module_init(iwl_init);
#ifdef CONFIG_IWLWIFI_DEBUG
-module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR);
+module_param_named(debug, iwlagn_mod_params.debug_level, uint,
+ S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "debug output mask");
#endif
@@ -3922,18 +3477,21 @@ MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO);
MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
-module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int,
- S_IRUGO);
+module_param_named(ucode_alternative,
+ iwlagn_mod_params.wanted_ucode_alternative,
+ int, S_IRUGO);
MODULE_PARM_DESC(ucode_alternative,
"specify ucode alternative to use from ucode file");
-module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO);
+module_param_named(antenna_coupling, iwlagn_mod_params.ant_coupling,
+ int, S_IRUGO);
MODULE_PARM_DESC(antenna_coupling,
"specify antenna coupling in dB (defualt: 0 dB)");
-module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO);
+module_param_named(bt_ch_inhibition, iwlagn_mod_params.bt_ch_announce,
+ bool, S_IRUGO);
MODULE_PARM_DESC(bt_ch_inhibition,
- "Disable BT channel inhibition (default: enable)");
+ "Enable BT channel inhibition (default: enable)");
module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO);
MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
@@ -3979,6 +3537,11 @@ module_param_named(power_level, iwlagn_mod_params.power_level,
MODULE_PARM_DESC(power_level,
"default power save level (range from 1 - 5, default: 1)");
+module_param_named(auto_agg, iwlagn_mod_params.auto_agg,
+ bool, S_IRUGO);
+MODULE_PARM_DESC(auto_agg,
+ "enable agg w/o check traffic load (default: enable)");
+
/*
* For now, keep using power level 1 instead of automatically
* adjusting ...
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index d941c4c98e4b..5b936ec1a541 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -65,54 +65,9 @@
#include "iwl-dev.h"
-/* configuration for the _agn devices */
-extern struct iwl_cfg iwl5300_agn_cfg;
-extern struct iwl_cfg iwl5100_agn_cfg;
-extern struct iwl_cfg iwl5350_agn_cfg;
-extern struct iwl_cfg iwl5100_bgn_cfg;
-extern struct iwl_cfg iwl5100_abg_cfg;
-extern struct iwl_cfg iwl5150_agn_cfg;
-extern struct iwl_cfg iwl5150_abg_cfg;
-extern struct iwl_cfg iwl6005_2agn_cfg;
-extern struct iwl_cfg iwl6005_2abg_cfg;
-extern struct iwl_cfg iwl6005_2bg_cfg;
-extern struct iwl_cfg iwl1030_bgn_cfg;
-extern struct iwl_cfg iwl1030_bg_cfg;
-extern struct iwl_cfg iwl6030_2agn_cfg;
-extern struct iwl_cfg iwl6030_2abg_cfg;
-extern struct iwl_cfg iwl6030_2bgn_cfg;
-extern struct iwl_cfg iwl6030_2bg_cfg;
-extern struct iwl_cfg iwl6000i_2agn_cfg;
-extern struct iwl_cfg iwl6000i_2abg_cfg;
-extern struct iwl_cfg iwl6000i_2bg_cfg;
-extern struct iwl_cfg iwl6000_3agn_cfg;
-extern struct iwl_cfg iwl6050_2agn_cfg;
-extern struct iwl_cfg iwl6050_2abg_cfg;
-extern struct iwl_cfg iwl6150_bgn_cfg;
-extern struct iwl_cfg iwl6150_bg_cfg;
-extern struct iwl_cfg iwl1000_bgn_cfg;
-extern struct iwl_cfg iwl1000_bg_cfg;
-extern struct iwl_cfg iwl100_bgn_cfg;
-extern struct iwl_cfg iwl100_bg_cfg;
-extern struct iwl_cfg iwl130_bgn_cfg;
-extern struct iwl_cfg iwl130_bg_cfg;
-extern struct iwl_cfg iwl2000_2bgn_cfg;
-extern struct iwl_cfg iwl2000_2bg_cfg;
-extern struct iwl_cfg iwl2030_2bgn_cfg;
-extern struct iwl_cfg iwl2030_2bg_cfg;
-extern struct iwl_cfg iwl6035_2agn_cfg;
-extern struct iwl_cfg iwl6035_2abg_cfg;
-extern struct iwl_cfg iwl6035_2bg_cfg;
-extern struct iwl_cfg iwl105_bg_cfg;
-extern struct iwl_cfg iwl105_bgn_cfg;
-extern struct iwl_cfg iwl135_bg_cfg;
-extern struct iwl_cfg iwl135_bgn_cfg;
-
-extern struct iwl_mod_params iwlagn_mod_params;
-
extern struct ieee80211_ops iwlagn_hw_ops;
-int iwl_reset_ict(struct iwl_priv *priv);
+int iwl_reset_ict(struct iwl_trans *trans);
static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
{
@@ -122,10 +77,6 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
hdr->data_valid = 1;
}
-/* tx queue */
-void iwl_free_tfds_in_queue(struct iwl_priv *priv,
- int sta_id, int tid, int freed);
-
/* RXON */
int iwlagn_set_pan_params(struct iwl_priv *priv);
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@@ -137,8 +88,9 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
u32 changes);
/* uCode */
-void iwlagn_rx_calib_result(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb);
+int iwlagn_rx_calib_result(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd);
int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
void iwlagn_send_prio_tbl(struct iwl_priv *priv);
int iwlagn_run_init_ucode(struct iwl_priv *priv);
@@ -147,13 +99,9 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
enum iwlagn_ucode_type ucode_type);
/* lib */
-void iwl_check_abort_status(struct iwl_priv *priv,
- u8 frame_count, u32 status);
-int iwlagn_hw_valid_rtc_data_addr(u32 addr);
int iwlagn_send_tx_power(struct iwl_priv *priv);
void iwlagn_temperature(struct iwl_priv *priv);
u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
-int iwlagn_wait_tx_queue_empty(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_send_beacon_cmd(struct iwl_priv *priv);
@@ -161,25 +109,19 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
/* rx */
int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
void iwl_setup_rx_handlers(struct iwl_priv *priv);
-void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
/* tx */
-void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
- int index);
-void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
- struct ieee80211_tx_info *info);
int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid);
-int iwlagn_txq_check_empty(struct iwl_priv *priv,
- int sta_id, u8 tid, int txq_id);
-void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb);
-void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
-int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
+int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd);
+int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd);
static inline u32 iwl_tx_status_to_mac80211(u32 status)
{
@@ -207,17 +149,14 @@ static inline bool iwl_is_tx_success(u32 status)
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
/* scan */
-int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
void iwlagn_post_scan(struct iwl_priv *priv);
-
-/* station mgmt */
-int iwlagn_manage_ibss_station(struct iwl_priv *priv,
- struct ieee80211_vif *vif, bool add);
+void iwlagn_disable_roc(struct iwl_priv *priv);
/* bt coex */
void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
-void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb);
+int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd);
void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv);
@@ -232,7 +171,120 @@ static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
static inline const char *iwl_get_agg_tx_fail_reason(u16 status) { return ""; }
#endif
+
/* station management */
+int iwlagn_manage_ibss_station(struct iwl_priv *priv,
+ struct ieee80211_vif *vif, bool add);
+#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
+#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */
+#define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of
+ being activated */
+#define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211;
+ (this is for the IBSS BSSID stations) */
+#define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */
+
+
+void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+void iwl_clear_ucode_stations(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
+void iwl_dealloc_bcast_stations(struct iwl_priv *priv);
+int iwl_get_free_ucode_key_offset(struct iwl_priv *priv);
+int iwl_send_add_sta(struct iwl_priv *priv,
+ struct iwl_addsta_cmd *sta, u8 flags);
+int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ const u8 *addr, bool is_ap,
+ struct ieee80211_sta *sta, u8 *sta_id_r);
+int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
+ const u8 *addr);
+int iwlagn_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+
+u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
+
+void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ u8 sta_id, struct iwl_link_quality_cmd *link_cmd);
+int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ struct iwl_link_quality_cmd *lq, u8 flags, bool init);
+void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd);
+
+
+/**
+ * iwl_clear_driver_stations - clear knowledge of all stations from driver
+ * @priv: iwl priv struct
+ *
+ * This is called during iwl_down() to make sure that in the case
+ * we're coming there from a hardware restart mac80211 will be
+ * able to reconfigure stations -- if we're getting there in the
+ * normal down flow then the stations will already be cleared.
+ */
+static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
+{
+ unsigned long flags;
+ struct iwl_rxon_context *ctx;
+
+ spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+ memset(priv->stations, 0, sizeof(priv->stations));
+ priv->num_stations = 0;
+
+ priv->ucode_key_table = 0;
+
+ for_each_context(priv, ctx) {
+ /*
+ * Remove all key information that is not stored as part
+ * of station information since mac80211 may not have had
+ * a chance to remove all the keys. When device is
+ * reconfigured by mac80211 after an error all keys will
+ * be reconfigured.
+ */
+ memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
+ ctx->key_mapping_keys = 0;
+ }
+
+ spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+}
+
+static inline int iwl_sta_id(struct ieee80211_sta *sta)
+{
+ if (WARN_ON(!sta))
+ return IWL_INVALID_STATION;
+
+ return ((struct iwl_station_priv *)sta->drv_priv)->sta_id;
+}
+
+/**
+ * iwl_sta_id_or_broadcast - return sta_id or broadcast sta
+ * @priv: iwl priv
+ * @context: the current context
+ * @sta: mac80211 station
+ *
+ * In certain circumstances mac80211 passes a station pointer
+ * that may be %NULL, for example during TX or key setup. In
+ * that case, we need to use the broadcast station, so this
+ * inline wraps that pattern.
+ */
+static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv,
+ struct iwl_rxon_context *context,
+ struct ieee80211_sta *sta)
+{
+ int sta_id;
+
+ if (!sta)
+ return context->bcast_sta_id;
+
+ sta_id = iwl_sta_id(sta);
+
+ /*
+ * mac80211 should not be passing a partially
+ * initialised station!
+ */
+ WARN_ON(sta_id == IWL_INVALID_STATION);
+
+ return sta_id;
+}
+
int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
@@ -286,7 +338,7 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
}
/* eeprom */
-void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
+void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
/* notification wait support */
@@ -309,20 +361,22 @@ extern int iwlagn_init_alive_start(struct iwl_priv *priv);
extern int iwl_alive_start(struct iwl_priv *priv);
/* svtool */
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
-extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len);
-extern int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct netlink_callback *cb,
- void *data, int len);
+extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data,
+ int len);
+extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct netlink_callback *cb,
+ void *data, int len);
extern void iwl_testmode_init(struct iwl_priv *priv);
extern void iwl_testmode_cleanup(struct iwl_priv *priv);
#else
static inline
-int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
+int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
{
return -ENOSYS;
}
static inline
-int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
struct netlink_callback *cb,
void *data, int len)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h
index f3ee1c0c004c..08b97594e305 100644
--- a/drivers/net/wireless/iwlwifi/iwl-bus.h
+++ b/drivers/net/wireless/iwlwifi/iwl-bus.h
@@ -60,16 +60,68 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
-#ifndef __iwl_pci_h__
-#define __iwl_pci_h__
+#ifndef __iwl_bus_h__
+#define __iwl_bus_h__
+#include <linux/types.h>
+#include <linux/spinlock.h>
+
+/**
+ * DOC: Bus layer - role and goal
+ *
+ * iwl-bus.h defines the API to the bus layer of the iwlwifi driver.
+ * The bus layer is responsible for doing very basic bus operations that are
+ * listed in the iwl_bus_ops structure.
+ * The bus layer registers to the bus driver, advertises the supported HW and
+ * gets notifications about enumeration, suspend, resume.
+ * For the moment, the bus layer is not a linux kernel module as itself, and
+ * the module_init function of the driver must call the bus specific
+ * registration functions. These functions are listed at the end of this file.
+ * For the moment, there is only one implementation of this interface: PCI-e.
+ * This implementation is iwl-pci.c
+ */
+
+/**
+ * DOC: encapsulation and type safety
+ *
+ * The iwl_bus describes the data that is shared amongst all the bus layer
+ * implementations. This data is visible to other layers. Data in the bus
+ * specific area is not visible outside the bus specific implementation.
+ * iwl_bus holds a pointer to iwl_shared which holds pointer to all the other
+ * layers of the driver (iwl_priv, iwl_trans). In fact, this is the way to go
+ * when the transport layer needs to call a function of another layer.
+ *
+ * In order to achieve encapsulation, iwl_priv cannot be dereferenced from the
+ * bus layer. Type safety is still kept since functions that gets iwl_priv gets
+ * a typed pointer (as opposed to void *).
+ */
+
+/**
+ * DOC: probe flow
+ *
+ * The module_init calls the bus specific registration function. The
+ * registration to the bus layer will trigger an enumeration of the bus which
+ * will call the bus specific probe function.
+ * The first thing this function must do is to allocate the memory needed by
+ * iwl_bus + the bus_specific data.
+ * Once the bus specific probe function has configured the hardware, it
+ * chooses the appropriate transport layer and calls iwl_probe that will run
+ * the bus independent probe flow.
+ *
+ * Note: The bus specific code must set the following data in iwl_bus before it
+ * calls iwl_probe:
+ * * bus->dev
+ * * bus->irq
+ * * bus->ops
+ */
+
+struct iwl_shared;
struct iwl_bus;
/**
* struct iwl_bus_ops - bus specific operations
* @get_pm_support: must returns true if the bus can go to sleep
- * @apm_config: will be called during the config of the APM configuration
- * @set_drv_data: set the drv_data pointer to the bus layer
+ * @apm_config: will be called during the config of the APM
* @get_hw_id: prints the hw_id in the provided buffer
* @write8: write a byte to register at offset ofs
* @write32: write a dword to register at offset ofs
@@ -78,20 +130,32 @@ struct iwl_bus;
struct iwl_bus_ops {
bool (*get_pm_support)(struct iwl_bus *bus);
void (*apm_config)(struct iwl_bus *bus);
- void (*set_drv_data)(struct iwl_bus *bus, void *drv_data);
void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len);
void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val);
void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val);
u32 (*read32)(struct iwl_bus *bus, u32 ofs);
};
+/**
+ * struct iwl_bus - bus common data
+ *
+ * This data is common to all bus layer implementations.
+ *
+ * @dev - pointer to struct device * that represents the device
+ * @ops - pointer to iwl_bus_ops
+ * @shrd - pointer to iwl_shared which holds shared data from the upper layer
+ * NB: for the time being this needs to be set by the upper layer since
+ * it allocates the shared data
+ * @irq - the irq number for the device
+ * @reg_lock - protect hw register access
+ */
struct iwl_bus {
- /* Common data to all buses */
- void *drv_data; /* driver's context */
struct device *dev;
- struct iwl_bus_ops *ops;
+ const struct iwl_bus_ops *ops;
+ struct iwl_shared *shrd;
unsigned int irq;
+ spinlock_t reg_lock;
/* pointer to bus specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
@@ -108,11 +172,6 @@ static inline void bus_apm_config(struct iwl_bus *bus)
bus->ops->apm_config(bus);
}
-static inline void bus_set_drv_data(struct iwl_bus *bus, void *drv_data)
-{
- bus->ops->set_drv_data(bus, drv_data);
-}
-
static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len)
{
bus->ops->get_hw_id(bus, buf, buf_len);
@@ -133,7 +192,10 @@ static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs)
return bus->ops->read32(bus, ofs);
}
+/*****************************************************
+* Bus layer registration functions
+******************************************************/
int __must_check iwl_pci_register_driver(void);
void iwl_pci_unregister_driver(void);
-#endif
+#endif /* __iwl_bus_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/drivers/net/wireless/iwlwifi/iwl-cfg.h
index b27986e57c92..2a2dc4597ba1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-cfg.h
@@ -60,22 +60,58 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
-/*
- * Please use this file (iwl-6000-hw.h) only for hardware-related definitions.
- * Use iwl-commands.h for uCode API definitions.
- */
+#ifndef __iwl_pci_h__
+#define __iwl_pci_h__
-#ifndef __iwl_6000_hw_h__
-#define __iwl_6000_hw_h__
-#define IWL60_RTC_INST_LOWER_BOUND (0x000000)
-#define IWL60_RTC_INST_UPPER_BOUND (0x040000)
-#define IWL60_RTC_DATA_LOWER_BOUND (0x800000)
-#define IWL60_RTC_DATA_UPPER_BOUND (0x814000)
-#define IWL60_RTC_INST_SIZE \
- (IWL60_RTC_INST_UPPER_BOUND - IWL60_RTC_INST_LOWER_BOUND)
-#define IWL60_RTC_DATA_SIZE \
- (IWL60_RTC_DATA_UPPER_BOUND - IWL60_RTC_DATA_LOWER_BOUND)
+/*
+ * This file declares the config structures for all devices.
+ */
-#endif /* __iwl_6000_hw_h__ */
+extern struct iwl_cfg iwl5300_agn_cfg;
+extern struct iwl_cfg iwl5100_agn_cfg;
+extern struct iwl_cfg iwl5350_agn_cfg;
+extern struct iwl_cfg iwl5100_bgn_cfg;
+extern struct iwl_cfg iwl5100_abg_cfg;
+extern struct iwl_cfg iwl5150_agn_cfg;
+extern struct iwl_cfg iwl5150_abg_cfg;
+extern struct iwl_cfg iwl6005_2agn_cfg;
+extern struct iwl_cfg iwl6005_2abg_cfg;
+extern struct iwl_cfg iwl6005_2bg_cfg;
+extern struct iwl_cfg iwl6005_2agn_sff_cfg;
+extern struct iwl_cfg iwl6005_2agn_d_cfg;
+extern struct iwl_cfg iwl1030_bgn_cfg;
+extern struct iwl_cfg iwl1030_bg_cfg;
+extern struct iwl_cfg iwl6030_2agn_cfg;
+extern struct iwl_cfg iwl6030_2abg_cfg;
+extern struct iwl_cfg iwl6030_2bgn_cfg;
+extern struct iwl_cfg iwl6030_2bg_cfg;
+extern struct iwl_cfg iwl6000i_2agn_cfg;
+extern struct iwl_cfg iwl6000i_2abg_cfg;
+extern struct iwl_cfg iwl6000i_2bg_cfg;
+extern struct iwl_cfg iwl6000_3agn_cfg;
+extern struct iwl_cfg iwl6050_2agn_cfg;
+extern struct iwl_cfg iwl6050_2abg_cfg;
+extern struct iwl_cfg iwl6150_bgn_cfg;
+extern struct iwl_cfg iwl6150_bg_cfg;
+extern struct iwl_cfg iwl1000_bgn_cfg;
+extern struct iwl_cfg iwl1000_bg_cfg;
+extern struct iwl_cfg iwl100_bgn_cfg;
+extern struct iwl_cfg iwl100_bg_cfg;
+extern struct iwl_cfg iwl130_bgn_cfg;
+extern struct iwl_cfg iwl130_bg_cfg;
+extern struct iwl_cfg iwl2000_2bgn_cfg;
+extern struct iwl_cfg iwl2000_2bg_cfg;
+extern struct iwl_cfg iwl2000_2bgn_d_cfg;
+extern struct iwl_cfg iwl2030_2bgn_cfg;
+extern struct iwl_cfg iwl2030_2bg_cfg;
+extern struct iwl_cfg iwl6035_2agn_cfg;
+extern struct iwl_cfg iwl6035_2abg_cfg;
+extern struct iwl_cfg iwl6035_2bg_cfg;
+extern struct iwl_cfg iwl105_bg_cfg;
+extern struct iwl_cfg iwl105_bgn_cfg;
+extern struct iwl_cfg iwl105_bgn_d_cfg;
+extern struct iwl_cfg iwl135_bg_cfg;
+extern struct iwl_cfg iwl135_bgn_cfg;
+#endif /* __iwl_pci_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index e9e9d1d1778d..69d5f85d11e2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -69,6 +69,9 @@
#ifndef __iwl_commands_h__
#define __iwl_commands_h__
+#include <linux/etherdevice.h>
+#include <linux/ieee80211.h>
+
struct iwl_priv;
/* uCode version contains 4 values: Major/Minor/API/Serial */
@@ -86,6 +89,7 @@ struct iwl_priv;
enum {
REPLY_ALIVE = 0x1,
REPLY_ERROR = 0x2,
+ REPLY_ECHO = 0x3, /* test command */
/* RXON and QOS commands */
REPLY_RXON = 0x10,
@@ -670,7 +674,6 @@ struct iwl_rxon_assoc_cmd {
#define IWL_CONN_MAX_LISTEN_INTERVAL 10
#define IWL_MAX_UCODE_BEACON_INTERVAL 4 /* 4096 */
-#define IWL39_MAX_UCODE_BEACON_INTERVAL 1 /* 1024 */
/*
* REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
@@ -806,6 +809,7 @@ struct iwl_qosparam_cmd {
#define IWLAGN_STATION_COUNT 16
#define IWL_INVALID_STATION 255
+#define IWL_MAX_TID_COUNT 9
#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2)
#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8)
@@ -3067,17 +3071,29 @@ struct iwl_missed_beacon_notif {
/* number of additional entries for enhanced tbl */
#define ENHANCE_HD_TABLE_ENTRIES (ENHANCE_HD_TABLE_SIZE - HD_TABLE_SIZE)
-#define HD_INA_NON_SQUARE_DET_OFDM_DATA cpu_to_le16(0)
-#define HD_INA_NON_SQUARE_DET_CCK_DATA cpu_to_le16(0)
-#define HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA cpu_to_le16(0)
-#define HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA cpu_to_le16(668)
-#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA cpu_to_le16(4)
-#define HD_OFDM_NON_SQUARE_DET_SLOPE_DATA cpu_to_le16(486)
-#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA cpu_to_le16(37)
-#define HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA cpu_to_le16(853)
-#define HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA cpu_to_le16(4)
-#define HD_CCK_NON_SQUARE_DET_SLOPE_DATA cpu_to_le16(476)
-#define HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA cpu_to_le16(99)
+#define HD_INA_NON_SQUARE_DET_OFDM_DATA_V1 cpu_to_le16(0)
+#define HD_INA_NON_SQUARE_DET_CCK_DATA_V1 cpu_to_le16(0)
+#define HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA_V1 cpu_to_le16(0)
+#define HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA_V1 cpu_to_le16(668)
+#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V1 cpu_to_le16(4)
+#define HD_OFDM_NON_SQUARE_DET_SLOPE_DATA_V1 cpu_to_le16(486)
+#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA_V1 cpu_to_le16(37)
+#define HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA_V1 cpu_to_le16(853)
+#define HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V1 cpu_to_le16(4)
+#define HD_CCK_NON_SQUARE_DET_SLOPE_DATA_V1 cpu_to_le16(476)
+#define HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA_V1 cpu_to_le16(99)
+
+#define HD_INA_NON_SQUARE_DET_OFDM_DATA_V2 cpu_to_le16(1)
+#define HD_INA_NON_SQUARE_DET_CCK_DATA_V2 cpu_to_le16(1)
+#define HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA_V2 cpu_to_le16(1)
+#define HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA_V2 cpu_to_le16(600)
+#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V2 cpu_to_le16(40)
+#define HD_OFDM_NON_SQUARE_DET_SLOPE_DATA_V2 cpu_to_le16(486)
+#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA_V2 cpu_to_le16(45)
+#define HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA_V2 cpu_to_le16(853)
+#define HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V2 cpu_to_le16(60)
+#define HD_CCK_NON_SQUARE_DET_SLOPE_DATA_V2 cpu_to_le16(476)
+#define HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA_V2 cpu_to_le16(99)
/* Control field in struct iwl_sensitivity_cmd */
@@ -3198,12 +3214,17 @@ enum iwl_ucode_calib_cfg {
IWL_CALIB_CFG_LO_IDX | \
IWL_CALIB_CFG_TX_IQ_IDX | \
IWL_CALIB_CFG_RX_IQ_IDX | \
- IWL_CALIB_CFG_NOISE_IDX | \
- IWL_CALIB_CFG_CRYSTAL_IDX | \
+ IWL_CALIB_CFG_CRYSTAL_IDX)
+
+#define IWL_CALIB_RT_CFG_ALL cpu_to_le32(IWL_CALIB_CFG_RX_BB_IDX | \
+ IWL_CALIB_CFG_DC_IDX | \
+ IWL_CALIB_CFG_LO_IDX | \
+ IWL_CALIB_CFG_TX_IQ_IDX | \
+ IWL_CALIB_CFG_RX_IQ_IDX | \
IWL_CALIB_CFG_TEMPERATURE_IDX | \
IWL_CALIB_CFG_PAPD_IDX | \
- IWL_CALIB_CFG_SENSITIVITY_IDX | \
- IWL_CALIB_CFG_TX_PWR_IDX)
+ IWL_CALIB_CFG_TX_PWR_IDX | \
+ IWL_CALIB_CFG_CRYSTAL_IDX)
#define IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK cpu_to_le32(BIT(0))
@@ -3253,6 +3274,14 @@ struct iwl_calib_temperature_offset_cmd {
__le16 reserved;
} __packed;
+struct iwl_calib_temperature_offset_v2_cmd {
+ struct iwl_calib_hdr hdr;
+ __le16 radio_sensor_offset_high;
+ __le16 radio_sensor_offset_low;
+ __le16 burntVoltageRef;
+ __le16 reserved;
+} __packed;
+
/* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
struct iwl_calib_chain_noise_reset_cmd {
struct iwl_calib_hdr hdr;
@@ -3897,6 +3926,7 @@ struct iwlagn_wowlan_kek_kck_material_cmd {
* Union of all expected notifications/responses:
*
*****************************************************************************/
+#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
struct iwl_rx_packet {
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index cf376f62b2f6..b247a56d5135 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -34,29 +34,26 @@
#include <net/mac80211.h>
#include "iwl-eeprom.h"
-#include "iwl-dev.h" /* FIXME: remove */
#include "iwl-debug.h"
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-power.h"
-#include "iwl-sta.h"
-#include "iwl-helpers.h"
+#include "iwl-agn.h"
+#include "iwl-shared.h"
#include "iwl-agn.h"
#include "iwl-trans.h"
-u32 iwl_debug_level;
-
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
-static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
+static void iwl_init_ht_hw_capab(const struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *ht_info,
enum ieee80211_band band)
{
u16 max_bit_rate = 0;
- u8 rx_chains_num = priv->hw_params.rx_chains_num;
- u8 tx_chains_num = priv->hw_params.tx_chains_num;
+ u8 rx_chains_num = hw_params(priv).rx_chains_num;
+ u8 tx_chains_num = hw_params(priv).tx_chains_num;
ht_info->cap = 0;
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
@@ -68,7 +65,7 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
max_bit_rate = MAX_BIT_RATE_20_MHZ;
- if (priv->hw_params.ht40_channel & BIT(band)) {
+ if (hw_params(priv).ht40_channel & BIT(band)) {
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
ht_info->mcs.rx_mask[4] = 0x01;
@@ -106,9 +103,9 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
}
/**
- * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom
+ * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom
*/
-int iwlcore_init_geos(struct iwl_priv *priv)
+int iwl_init_geos(struct iwl_priv *priv)
{
struct iwl_channel_info *ch;
struct ieee80211_supported_band *sband;
@@ -121,16 +118,16 @@ int iwlcore_init_geos(struct iwl_priv *priv)
if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
- set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+ set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
return 0;
}
- channels = kzalloc(sizeof(struct ieee80211_channel) *
- priv->channel_count, GFP_KERNEL);
+ channels = kcalloc(priv->channel_count,
+ sizeof(struct ieee80211_channel), GFP_KERNEL);
if (!channels)
return -ENOMEM;
- rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY),
+ rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate),
GFP_KERNEL);
if (!rates) {
kfree(channels);
@@ -145,7 +142,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
- iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
+ iwl_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_5GHZ);
sband = &priv->bands[IEEE80211_BAND_2GHZ];
@@ -155,7 +152,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
- iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
+ iwl_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_2GHZ);
priv->ieee_channels = channels;
@@ -211,7 +208,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
char buf[32];
- bus_get_hw_id(priv->bus, buf, sizeof(buf));
+ bus_get_hw_id(bus(priv), buf, sizeof(buf));
IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
"Please send your %s to maintainer.\n", buf);
priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
@@ -221,19 +218,19 @@ int iwlcore_init_geos(struct iwl_priv *priv)
priv->bands[IEEE80211_BAND_2GHZ].n_channels,
priv->bands[IEEE80211_BAND_5GHZ].n_channels);
- set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+ set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
return 0;
}
/*
- * iwlcore_free_geos - undo allocations in iwlcore_init_geos
+ * iwl_free_geos - undo allocations in iwl_init_geos
*/
-void iwlcore_free_geos(struct iwl_priv *priv)
+void iwl_free_geos(struct iwl_priv *priv)
{
kfree(priv->ieee_channels);
kfree(priv->ieee_rates);
- clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+ clear_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
}
static bool iwl_is_channel_extension(struct iwl_priv *priv,
@@ -323,9 +320,9 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
u16 beacon_int;
struct ieee80211_vif *vif = ctx->vif;
- conf = ieee80211_get_hw_conf(priv->hw);
+ conf = &priv->hw->conf;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
@@ -359,7 +356,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
beacon_int = le16_to_cpu(ctx->timing.beacon_interval);
} else {
beacon_int = iwl_adjust_beacon_interval(beacon_int,
- priv->hw_params.max_beacon_itrvl * TIME_UNIT);
+ IWL_MAX_UCODE_BEACON_INTERVAL * TIME_UNIT);
ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
}
@@ -378,7 +375,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
le32_to_cpu(ctx->timing.beacon_init_val),
le16_to_cpu(ctx->timing.atim_window));
- return trans_send_cmd_pdu(&priv->trans, ctx->rxon_timing_cmd,
+ return iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_timing_cmd,
CMD_SYNC, sizeof(ctx->timing), &ctx->timing);
}
@@ -804,21 +801,23 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
{
/*
* MULTI-FIXME
- * See iwl_mac_channel_switch.
+ * See iwlagn_mac_channel_switch.
*/
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
- if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+ if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
+ &priv->shrd->status))
ieee80211_chswitch_done(ctx->vif, is_success);
}
#ifdef CONFIG_IWLWIFI_DEBUG
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
+ enum iwl_rxon_context_id ctxid)
{
+ struct iwl_rxon_context *ctx = &priv->contexts[ctxid];
struct iwl_rxon_cmd *rxon = &ctx->staging;
IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
@@ -856,18 +855,18 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
unsigned long reload_jiffies;
/* Set the FW error flag -- cleared on iwl_down */
- set_bit(STATUS_FW_ERROR, &priv->status);
+ set_bit(STATUS_FW_ERROR, &priv->shrd->status);
/* Cancel currently queued command. */
- clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+ clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status);
iwlagn_abort_notification_waits(priv);
/* Keep the restart process from trying to send host
* commands by clearing the ready bit */
- clear_bit(STATUS_READY, &priv->status);
+ clear_bit(STATUS_READY, &priv->shrd->status);
- wake_up_interruptible(&priv->wait_command_queue);
+ wake_up(&priv->shrd->wait_command_queue);
if (!ondemand) {
/*
@@ -890,63 +889,26 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
priv->reload_count = 0;
}
- if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+ if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
if (iwlagn_mod_params.restart_fw) {
- IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
+ IWL_DEBUG_FW_ERRORS(priv,
"Restarting adapter due to uCode error.\n");
- queue_work(priv->workqueue, &priv->restart);
+ queue_work(priv->shrd->workqueue, &priv->restart);
} else
- IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
+ IWL_DEBUG_FW_ERRORS(priv,
"Detected FW error, but not restarting\n");
}
}
-/**
- * iwl_irq_handle_error - called for HW or SW error interrupt from card
- */
-void iwl_irq_handle_error(struct iwl_priv *priv)
-{
- /* W/A for WiFi/WiMAX coex and WiMAX own the RF */
- if (priv->cfg->internal_wimax_coex &&
- (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) &
- APMS_CLK_VAL_MRB_FUNC_MODE) ||
- (iwl_read_prph(priv, APMG_PS_CTRL_REG) &
- APMG_PS_CTRL_VAL_RESET_REQ))) {
- /*
- * Keep the restart process from trying to send host
- * commands by clearing the ready bit.
- */
- clear_bit(STATUS_READY, &priv->status);
- clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
- wake_up_interruptible(&priv->wait_command_queue);
- IWL_ERR(priv, "RF is used by WiMAX\n");
- return;
- }
-
- IWL_ERR(priv, "Loaded firmware version: %s\n",
- priv->hw->wiphy->fw_version);
-
- iwl_dump_nic_error_log(priv);
- iwl_dump_csr(priv);
- iwl_dump_fh(priv, NULL, false);
- iwl_dump_nic_event_log(priv, false, NULL, false);
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
- iwl_print_rx_config_cmd(priv,
- &priv->contexts[IWL_RXON_CTX_BSS]);
-#endif
-
- iwlagn_fw_error(priv, false);
-}
-
static int iwl_apm_stop_master(struct iwl_priv *priv)
{
int ret = 0;
/* stop device's busmaster DMA activity */
- iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+ iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
- ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
+ ret = iwl_poll_bit(bus(priv), CSR_RESET,
+ CSR_RESET_REG_FLAG_MASTER_DISABLED,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
if (ret)
IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n");
@@ -960,13 +922,13 @@ void iwl_apm_stop(struct iwl_priv *priv)
{
IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n");
- clear_bit(STATUS_DEVICE_ENABLED, &priv->status);
+ clear_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status);
/* Stop device's DMA activity */
iwl_apm_stop_master(priv);
/* Reset the entire device */
- iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
udelay(10);
@@ -974,7 +936,7 @@ void iwl_apm_stop(struct iwl_priv *priv)
* Clear "initialization complete" bit to move adapter from
* D0A* (powered-up Active) --> D0U* (Uninitialized) state.
*/
- iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ iwl_clear_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
}
@@ -994,45 +956,45 @@ int iwl_apm_init(struct iwl_priv *priv)
*/
/* Disable L0S exit timer (platform NMI Work/Around) */
- iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
/*
* Disable L0s without affecting L1;
* don't wait for ICH L0s (ICH bug W/A)
*/
- iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
/* Set FH wait threshold to maximum (HW error during stress W/A) */
- iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);
+ iwl_set_bit(bus(priv), CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);
/*
* Enable HAP INTA (interrupt from management bus) to
* wake device's PCI Express link L1a -> L0s
*/
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
- bus_apm_config(priv->bus);
+ bus_apm_config(bus(priv));
/* Configure analog phase-lock-loop before activating to D0A */
if (priv->cfg->base_params->pll_cfg_val)
- iwl_set_bit(priv, CSR_ANA_PLL_CFG,
+ iwl_set_bit(bus(priv), CSR_ANA_PLL_CFG,
priv->cfg->base_params->pll_cfg_val);
/*
* Set "initialization complete" bit to move adapter from
* D0U* --> D0A* (powered-up active) state.
*/
- iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ iwl_set_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/*
* Wait for clock stabilization; once stabilized, access to
* device-internal resources is supported, e.g. iwl_write_prph()
* and accesses to uCode SRAM.
*/
- ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
+ ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0) {
@@ -1047,14 +1009,14 @@ int iwl_apm_init(struct iwl_priv *priv)
* do not disable clocks. This preserves any hardware bits already
* set by default in "CLK_CTRL_REG" after reset.
*/
- iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+ iwl_write_prph(bus(priv), APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
udelay(20);
/* Disable L1-Active */
- iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+ iwl_set_bits_prph(bus(priv), APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
- set_bit(STATUS_DEVICE_ENABLED, &priv->status);
+ set_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status);
out:
return ret;
@@ -1068,7 +1030,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
bool defer;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
if (priv->tx_power_user_lmt == tx_power && !force)
return 0;
@@ -1088,7 +1050,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
return -EINVAL;
}
- if (!iwl_is_ready_rf(priv))
+ if (!iwl_is_ready_rf(priv->shrd))
return -EIO;
/* scan complete and commit_rxon use tx_power_next value,
@@ -1096,7 +1058,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
priv->tx_power_next = tx_power;
/* do not set tx power when scanning or channel changing */
- defer = test_bit(STATUS_SCANNING, &priv->status) ||
+ defer = test_bit(STATUS_SCANNING, &priv->shrd->status) ||
memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
if (defer && !force) {
IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
@@ -1134,7 +1096,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "BT coex %s\n",
(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
- if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG,
+ if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
IWL_ERR(priv, "failed to send BT Coex Config\n");
}
@@ -1147,24 +1109,20 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
};
if (flags & CMD_ASYNC)
- return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD,
+ return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD,
CMD_ASYNC,
sizeof(struct iwl_statistics_cmd),
&statistics_cmd);
else
- return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD,
+ return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD,
CMD_SYNC,
sizeof(struct iwl_statistics_cmd),
&statistics_cmd);
}
-void iwl_clear_isr_stats(struct iwl_priv *priv)
-{
- memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
-}
-
-int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
- const struct ieee80211_tx_queue_params *params)
+int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
{
struct iwl_priv *priv = hw->priv;
struct iwl_rxon_context *ctx;
@@ -1173,7 +1131,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
IWL_DEBUG_MAC80211(priv, "enter\n");
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl_is_ready_rf(priv->shrd)) {
IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
return -EIO;
}
@@ -1185,7 +1143,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
q = AC_NUM - 1 - queue;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->shrd->lock, flags);
/*
* MULTI-FIXME
@@ -1203,13 +1161,13 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
}
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->shrd->lock, flags);
IWL_DEBUG_MAC80211(priv, "leave\n");
return 0;
}
-int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
+int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
@@ -1231,7 +1189,7 @@ static int iwl_setup_interface(struct iwl_priv *priv,
struct ieee80211_vif *vif = ctx->vif;
int err;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
/*
* This variable will be correct only when there's just
@@ -1262,7 +1220,8 @@ static int iwl_setup_interface(struct iwl_priv *priv,
return 0;
}
-int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
@@ -1273,9 +1232,13 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
viftype, vif->addr);
- mutex_lock(&priv->mutex);
+ cancel_delayed_work_sync(&priv->hw_roc_disable_work);
+
+ mutex_lock(&priv->shrd->mutex);
+
+ iwlagn_disable_roc(priv);
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl_is_ready_rf(priv->shrd)) {
IWL_WARN(priv, "Try to add interface when device not ready\n");
err = -EINVAL;
goto out;
@@ -1318,7 +1281,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
ctx->vif = NULL;
priv->iw_mode = NL80211_IFTYPE_STATION;
out:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return err;
@@ -1330,7 +1293,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv,
{
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
if (priv->scan_vif == vif) {
iwl_scan_cancel_timeout(priv, 200);
@@ -1354,7 +1317,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv,
priv->bt_traffic_load = priv->last_bt_traffic_load;
}
-void iwl_mac_remove_interface(struct ieee80211_hw *hw,
+void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
@@ -1362,14 +1325,20 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "enter\n");
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
- WARN_ON(ctx->vif != vif);
+ if (WARN_ON(ctx->vif != vif)) {
+ struct iwl_rxon_context *tmp;
+ IWL_ERR(priv, "ctx->vif = %p, vif = %p\n", ctx->vif, vif);
+ for_each_context(priv, tmp)
+ IWL_ERR(priv, "\tID = %d:\tctx = %p\tctx->vif = %p\n",
+ tmp->ctxid, tmp, tmp->vif);
+ }
ctx->vif = NULL;
iwl_teardown_interface(priv, vif, false);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -1393,7 +1362,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
{
u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
- if (iwl_debug_level & IWL_DL_TX) {
+ if (iwl_get_debug_level(priv->shrd) & IWL_DL_TX) {
if (!priv->tx_traffic) {
priv->tx_traffic =
kzalloc(traffic_size, GFP_KERNEL);
@@ -1401,7 +1370,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
return -ENOMEM;
}
}
- if (iwl_debug_level & IWL_DL_RX) {
+ if (iwl_get_debug_level(priv->shrd) & IWL_DL_RX) {
if (!priv->rx_traffic) {
priv->rx_traffic =
kzalloc(traffic_size, GFP_KERNEL);
@@ -1428,7 +1397,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
__le16 fc;
u16 len;
- if (likely(!(iwl_debug_level & IWL_DL_TX)))
+ if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_TX)))
return;
if (!priv->tx_traffic)
@@ -1452,7 +1421,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
__le16 fc;
u16 len;
- if (likely(!(iwl_debug_level & IWL_DL_RX)))
+ if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_RX)))
return;
if (!priv->rx_traffic)
@@ -1609,7 +1578,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
static void iwl_force_rf_reset(struct iwl_priv *priv)
{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return;
if (!iwl_is_any_associated(priv)) {
@@ -1634,7 +1603,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
{
struct iwl_force_reset *force_reset;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return -EINVAL;
if (mode >= IWL_MAX_FORCE_RESET) {
@@ -1680,8 +1649,9 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
return 0;
}
-int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- enum nl80211_iftype newtype, bool newp2p)
+int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum nl80211_iftype newtype, bool newp2p)
{
struct iwl_priv *priv = hw->priv;
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
@@ -1691,11 +1661,13 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 interface_modes;
int err;
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+
newtype = ieee80211_iftype_p2p(newtype, newp2p);
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
- if (!ctx->vif || !iwl_is_ready_rf(priv)) {
+ if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) {
/*
* Huh? But wait ... this can maybe happen when
* we're in the middle of a firmware restart!
@@ -1757,36 +1729,45 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
err = 0;
out:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+
return err;
}
-/*
- * On every watchdog tick we check (latest) time stamp. If it does not
- * change during timeout period and queue is not empty we reset firmware.
- */
-static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt)
+int iwl_cmd_echo_test(struct iwl_priv *priv)
{
- struct iwl_tx_queue *txq = &priv->txq[cnt];
- struct iwl_queue *q = &txq->q;
- unsigned long timeout;
int ret;
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_ECHO,
+ .flags = CMD_SYNC,
+ };
- if (q->read_ptr == q->write_ptr) {
- txq->time_stamp = jiffies;
- return 0;
- }
-
- timeout = txq->time_stamp +
- msecs_to_jiffies(priv->cfg->base_params->wd_timeout);
+ ret = iwl_trans_send_cmd(trans(priv), &cmd);
+ if (ret)
+ IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);
+ else
+ IWL_DEBUG_INFO(priv, "echo testing pass\n");
+ return ret;
+}
- if (time_after(jiffies, timeout)) {
- IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
- q->id, priv->cfg->base_params->wd_timeout);
+static inline int iwl_check_stuck_queue(struct iwl_priv *priv, int txq)
+{
+ if (iwl_trans_check_stuck_queue(trans(priv), txq)) {
+ int ret;
+ if (txq == priv->shrd->cmd_queue) {
+ /*
+ * validate command queue still working
+ * by sending "ECHO" command
+ */
+ if (!iwl_cmd_echo_test(priv))
+ return 0;
+ else
+ IWL_DEBUG_HC(priv, "echo testing fail\n");
+ }
ret = iwl_force_reset(priv, IWL_FW_RESET, false);
return (ret == -EAGAIN) ? 0 : 1;
}
-
return 0;
}
@@ -1806,7 +1787,10 @@ void iwl_bg_watchdog(unsigned long data)
int cnt;
unsigned long timeout;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+ return;
+
+ if (iwl_is_rfkill(priv->shrd))
return;
timeout = priv->cfg->base_params->wd_timeout;
@@ -1814,14 +1798,14 @@ void iwl_bg_watchdog(unsigned long data)
return;
/* monitor and check for stuck cmd queue */
- if (iwl_check_stuck_queue(priv, priv->cmd_queue))
+ if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue))
return;
/* monitor and check for other stuck queues */
if (iwl_is_any_associated(priv)) {
- for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+ for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) {
/* skip as we already checked the command queue */
- if (cnt == priv->cmd_queue)
+ if (cnt == priv->shrd->cmd_queue)
continue;
if (iwl_check_stuck_queue(priv, cnt))
return;
@@ -1843,6 +1827,28 @@ void iwl_setup_watchdog(struct iwl_priv *priv)
del_timer(&priv->watchdog);
}
+/**
+ * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
+ * @priv -- pointer to iwl_priv data structure
+ * @tsf_bits -- number of bits need to shift for masking)
+ */
+static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
+ u16 tsf_bits)
+{
+ return (1 << tsf_bits) - 1;
+}
+
+/**
+ * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
+ * @priv -- pointer to iwl_priv data structure
+ * @tsf_bits -- number of bits need to shift for masking)
+ */
+static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv,
+ u16 tsf_bits)
+{
+ return ((1 << (32 - tsf_bits)) - 1) << tsf_bits;
+}
+
/*
* extended beacon time format
* time in usec will be changed into a 32-bit value in extended:internal format
@@ -1859,13 +1865,12 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval)
return 0;
quot = (usec / interval) &
- (iwl_beacon_time_mask_high(priv,
- priv->hw_params.beacon_time_tsf_bits) >>
- priv->hw_params.beacon_time_tsf_bits);
+ (iwl_beacon_time_mask_high(priv, IWLAGN_EXT_BEACON_TIME_POS) >>
+ IWLAGN_EXT_BEACON_TIME_POS);
rem = (usec % interval) & iwl_beacon_time_mask_low(priv,
- priv->hw_params.beacon_time_tsf_bits);
+ IWLAGN_EXT_BEACON_TIME_POS);
- return (quot << priv->hw_params.beacon_time_tsf_bits) + rem;
+ return (quot << IWLAGN_EXT_BEACON_TIME_POS) + rem;
}
/* base is usually what we get from ucode with each received frame,
@@ -1875,64 +1880,80 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
u32 addon, u32 beacon_interval)
{
u32 base_low = base & iwl_beacon_time_mask_low(priv,
- priv->hw_params.beacon_time_tsf_bits);
+ IWLAGN_EXT_BEACON_TIME_POS);
u32 addon_low = addon & iwl_beacon_time_mask_low(priv,
- priv->hw_params.beacon_time_tsf_bits);
+ IWLAGN_EXT_BEACON_TIME_POS);
u32 interval = beacon_interval * TIME_UNIT;
u32 res = (base & iwl_beacon_time_mask_high(priv,
- priv->hw_params.beacon_time_tsf_bits)) +
+ IWLAGN_EXT_BEACON_TIME_POS)) +
(addon & iwl_beacon_time_mask_high(priv,
- priv->hw_params.beacon_time_tsf_bits));
+ IWLAGN_EXT_BEACON_TIME_POS));
if (base_low > addon_low)
res += base_low - addon_low;
else if (base_low < addon_low) {
res += interval + base_low - addon_low;
- res += (1 << priv->hw_params.beacon_time_tsf_bits);
+ res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
} else
- res += (1 << priv->hw_params.beacon_time_tsf_bits);
+ res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
return cpu_to_le32(res);
}
-#ifdef CONFIG_PM
+void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
+ enum iwl_rxon_context_id ctx,
+ u8 sta_id, u8 tid)
+{
+ struct ieee80211_vif *vif;
+ u8 *addr = priv->stations[sta_id].sta.sta.addr;
-int iwl_suspend(struct iwl_priv *priv)
+ if (ctx == NUM_IWL_RXON_CTX)
+ ctx = priv->stations[sta_id].ctxid;
+ vif = priv->contexts[ctx].vif;
+
+ ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
+}
+
+void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
+ enum iwl_rxon_context_id ctx,
+ u8 sta_id, u8 tid)
{
- /*
- * This function is called when system goes into suspend state
- * mac80211 will call iwl_mac_stop() from the mac80211 suspend function
- * first but since iwl_mac_stop() has no knowledge of who the caller is,
- * it will not call apm_ops.stop() to stop the DMA operation.
- * Calling apm_ops.stop here to make sure we stop the DMA.
- *
- * But of course ... if we have configured WoWLAN then we did other
- * things already :-)
- */
- if (!priv->wowlan)
- iwl_apm_stop(priv);
+ struct ieee80211_vif *vif;
+ u8 *addr = priv->stations[sta_id].sta.sta.addr;
- return 0;
+ if (ctx == NUM_IWL_RXON_CTX)
+ ctx = priv->stations[sta_id].ctxid;
+ vif = priv->contexts[ctx].vif;
+
+ ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
}
-int iwl_resume(struct iwl_priv *priv)
+void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state)
{
- bool hw_rfkill = false;
+ wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
+}
- iwl_enable_interrupts(priv);
+void iwl_nic_config(struct iwl_priv *priv)
+{
+ priv->cfg->lib->nic_config(priv);
- if (!(iwl_read32(priv, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
- hw_rfkill = true;
+}
- if (hw_rfkill)
- set_bit(STATUS_RF_KILL_HW, &priv->status);
- else
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
+void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info;
- wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill);
+ info = IEEE80211_SKB_CB(skb);
+ kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
+ dev_kfree_skb_any(skb);
+}
- return 0;
+void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac)
+{
+ ieee80211_stop_queue(priv->hw, ac);
}
-#endif /* CONFIG_PM */
+void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac)
+{
+ ieee80211_wake_queue(priv->hw, ac);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 02817a438550..137da3380704 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -64,6 +64,7 @@
#define __iwl_core_h__
#include "iwl-dev.h"
+#include "iwl-io.h"
/************************
* forward declarations *
@@ -71,15 +72,8 @@
struct iwl_host_cmd;
struct iwl_cmd;
-
-#define IWLWIFI_VERSION "in-tree:"
-#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation"
-#define DRV_AUTHOR "<ilw@linux.intel.com>"
-
#define TIME_UNIT 1024
-#define IWL_CMD(x) case x: return #x
-
struct iwl_lib_ops {
/* set hw dependent parameters */
int (*set_hw_params)(struct iwl_priv *priv);
@@ -101,23 +95,6 @@ struct iwl_lib_ops {
void (*temperature)(struct iwl_priv *priv);
};
-struct iwl_mod_params {
- int sw_crypto; /* def: 0 = using hardware encryption */
- int num_of_queues; /* def: HW dependent */
- int disable_11n; /* def: 0 = 11n capabilities enabled */
- int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
- int antenna; /* def: 0 = both antennas (use diversity) */
- int restart_fw; /* def: 1 = restart firmware */
- bool plcp_check; /* def: true = enable plcp health check */
- bool ack_check; /* def: false = disable ack health check */
- bool wd_disable; /* def: false = enable stuck queue check */
- bool bt_coex_active; /* def: true = enable bt coex */
- int led_mode; /* def: 0 = system default */
- bool no_sleep_autoadjust; /* def: true = disable autoadjust */
- bool power_save; /* def: false = disable power save */
- int power_level; /* def: 1 = power level */
-};
-
/*
* @max_ll_items: max number of OTP blocks
* @shadow_ram_support: shadow support for OTP memory
@@ -132,10 +109,10 @@ struct iwl_mod_params {
* radio tuning when there is a high receiving plcp error rate
* @chain_noise_scale: default chain noise scale used for gain computation
* @wd_timeout: TX queues watchdog timeout
- * @temperature_kelvin: temperature report by uCode in kelvin
* @max_event_log_size: size of event log buffer size for ucode event logging
* @shadow_reg_enable: HW shadhow register bit
* @no_idle_support: do not support idle mode
+ * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
*/
struct iwl_base_params {
int eeprom_size;
@@ -147,17 +124,16 @@ struct iwl_base_params {
const u16 max_ll_items;
const bool shadow_ram_support;
u16 led_compensation;
- int chain_noise_num_beacons;
bool adv_thermal_throttle;
bool support_ct_kill_exit;
const bool support_wimax_coexist;
u8 plcp_delta_threshold;
s32 chain_noise_scale;
unsigned int wd_timeout;
- bool temperature_kelvin;
u32 max_event_log_size;
const bool shadow_reg_enable;
const bool no_idle_support;
+ const bool hd_v2;
};
/*
* @advanced_bt_coexist: support advanced bt coexist
@@ -194,6 +170,8 @@ struct iwl_ht_params {
* (.ucode) will be added to filename before loading from disk. The
* filename is constructed as fw_name_pre<api>.ucode.
* @ucode_api_max: Highest version of uCode API supported by driver.
+ * @ucode_api_ok: oldest version of the uCode API that is OK to load
+ * without a warning, for use in transitions
* @ucode_api_min: Lowest version of uCode API supported by driver.
* @valid_tx_ant: valid transmit antenna
* @valid_rx_ant: valid receive antenna
@@ -214,20 +192,12 @@ struct iwl_ht_params {
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
* @internal_wimax_coex: internal wifi/wimax combo device
* @iq_invert: I/Q inversion
+ * @temp_offset_v2: support v2 of temperature offset calibration
*
* We enable the driver to be backward compatible wrt API version. The
* driver specifies which APIs it supports (with @ucode_api_max being the
* highest and @ucode_api_min the lowest). Firmware will only be loaded if
- * it has a supported API version. The firmware's API version will be
- * stored in @iwl_priv, enabling the driver to make runtime changes based
- * on firmware version used.
- *
- * For example,
- * if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
- * Driver interacts with Firmware API version >= 2.
- * } else {
- * Driver interacts with Firmware API version 1.
- * }
+ * it has a supported API version.
*
* The ideal usage of this infrastructure is to treat a new ucode API
* release as a new hardware revision.
@@ -237,6 +207,7 @@ struct iwl_cfg {
const char *name;
const char *fw_name_pre;
const unsigned int ucode_api_max;
+ const unsigned int ucode_api_ok;
const unsigned int ucode_api_min;
u8 valid_tx_ant;
u8 valid_rx_ant;
@@ -259,15 +230,17 @@ struct iwl_cfg {
const bool rx_with_siso_diversity;
const bool internal_wimax_coex;
const bool iq_invert;
+ const bool temp_offset_v2;
};
/***************************
* L i b *
***************************/
-int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params);
-int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
+int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw);
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
int hw_decrypt);
int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@@ -287,18 +260,17 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
void iwl_connection_init_rx_config(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
void iwl_set_rate(struct iwl_priv *priv);
-void iwl_irq_handle_error(struct iwl_priv *priv);
-int iwl_mac_add_interface(struct ieee80211_hw *hw,
+int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
-void iwl_mac_remove_interface(struct ieee80211_hw *hw,
+void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
-int iwl_mac_change_interface(struct ieee80211_hw *hw,
+int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p);
+int iwl_cmd_echo_test(struct iwl_priv *priv);
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_alloc_traffic_mem(struct iwl_priv *priv);
void iwl_free_traffic_mem(struct iwl_priv *priv);
-void iwl_reset_traffic_log(struct iwl_priv *priv);
void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
u16 length, struct ieee80211_hdr *header);
void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
@@ -349,9 +321,9 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
******************************************************************************/
void iwl_init_scan_params(struct iwl_priv *priv);
int iwl_scan_cancel(struct iwl_priv *priv);
-int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
+void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
void iwl_force_scan_end(struct iwl_priv *priv);
-int iwl_mac_hw_scan(struct ieee80211_hw *hw,
+int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req);
void iwl_internal_short_hw_scan(struct iwl_priv *priv);
@@ -359,12 +331,6 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
const u8 *ta, const u8 *ie, int ie_len, int left);
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
-u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
- enum ieee80211_band band,
- u8 n_probes);
-u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
- enum ieee80211_band band,
- struct ieee80211_vif *vif);
void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
int __must_check iwl_scan_initiate(struct iwl_priv *priv,
@@ -387,117 +353,21 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
* S e n d i n g H o s t C o m m a n d s *
*****************************************************/
-const char *get_cmd_string(u8 cmd);
void iwl_bg_watchdog(unsigned long data);
u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
u32 addon, u32 beacon_interval);
-#ifdef CONFIG_PM
-int iwl_suspend(struct iwl_priv *priv);
-int iwl_resume(struct iwl_priv *priv);
-#endif /* !CONFIG_PM */
-
-int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg);
-void __devexit iwl_remove(struct iwl_priv * priv);
-
-/*****************************************************
-* Error Handling Debugging
-******************************************************/
-void iwl_dump_nic_error_log(struct iwl_priv *priv);
-int iwl_dump_nic_event_log(struct iwl_priv *priv,
- bool full_log, char **buf, bool display);
-void iwl_dump_csr(struct iwl_priv *priv);
-int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
-#ifdef CONFIG_IWLWIFI_DEBUG
-void iwl_print_rx_config_cmd(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx);
-#else
-static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
-{
-}
-#endif
-
-void iwl_clear_isr_stats(struct iwl_priv *priv);
/*****************************************************
* GEOS
******************************************************/
-int iwlcore_init_geos(struct iwl_priv *priv);
-void iwlcore_free_geos(struct iwl_priv *priv);
-
-/*************** DRIVER STATUS FUNCTIONS *****/
-
-#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
-/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
-#define STATUS_INT_ENABLED 2
-#define STATUS_RF_KILL_HW 3
-#define STATUS_CT_KILL 4
-#define STATUS_INIT 5
-#define STATUS_ALIVE 6
-#define STATUS_READY 7
-#define STATUS_TEMPERATURE 8
-#define STATUS_GEO_CONFIGURED 9
-#define STATUS_EXIT_PENDING 10
-#define STATUS_STATISTICS 12
-#define STATUS_SCANNING 13
-#define STATUS_SCAN_ABORTING 14
-#define STATUS_SCAN_HW 15
-#define STATUS_POWER_PMI 16
-#define STATUS_FW_ERROR 17
-#define STATUS_DEVICE_ENABLED 18
-#define STATUS_CHANNEL_SWITCH_PENDING 19
-
-
-static inline int iwl_is_ready(struct iwl_priv *priv)
-{
- /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
- * set but EXIT_PENDING is not */
- return test_bit(STATUS_READY, &priv->status) &&
- test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
- !test_bit(STATUS_EXIT_PENDING, &priv->status);
-}
-
-static inline int iwl_is_alive(struct iwl_priv *priv)
-{
- return test_bit(STATUS_ALIVE, &priv->status);
-}
-
-static inline int iwl_is_init(struct iwl_priv *priv)
-{
- return test_bit(STATUS_INIT, &priv->status);
-}
-
-static inline int iwl_is_rfkill_hw(struct iwl_priv *priv)
-{
- return test_bit(STATUS_RF_KILL_HW, &priv->status);
-}
-
-static inline int iwl_is_rfkill(struct iwl_priv *priv)
-{
- return iwl_is_rfkill_hw(priv);
-}
-
-static inline int iwl_is_ctkill(struct iwl_priv *priv)
-{
- return test_bit(STATUS_CT_KILL, &priv->status);
-}
-
-static inline int iwl_is_ready_rf(struct iwl_priv *priv)
-{
-
- if (iwl_is_rfkill(priv))
- return 0;
-
- return iwl_is_ready(priv);
-}
+int iwl_init_geos(struct iwl_priv *priv);
+void iwl_free_geos(struct iwl_priv *priv);
extern void iwl_send_bt_config(struct iwl_priv *priv);
extern int iwl_send_statistics_request(struct iwl_priv *priv,
u8 flags, bool clear);
-void iwl_apm_stop(struct iwl_priv *priv);
-int iwl_apm_init(struct iwl_priv *priv);
int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@@ -513,9 +383,12 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
priv->cfg->bt_params->advanced_bt_coexist;
}
-extern bool bt_siso_mode;
-
+static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
+{
+ IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
+ iwl_write32(bus(priv), CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+}
-void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand);
+extern bool bt_siso_mode;
#endif /* __iwl_core_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index d6dbb0423045..b9f3267e720c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -439,4 +439,22 @@
*/
#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
+/**********************************************************
+ * CSR values
+ **********************************************************/
+ /*
+ * host interrupt timeout value
+ * used with setting interrupt coalescing timer
+ * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
+ *
+ * default interrupt coalescing timer is 64 x 32 = 2048 usecs
+ * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
+ */
+#define IWL_HOST_INT_TIMEOUT_MAX (0xFF)
+#define IWL_HOST_INT_TIMEOUT_DEF (0x40)
+#define IWL_HOST_INT_TIMEOUT_MIN (0x0)
+#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
+#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
+#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
+
#endif /* !__iwl_csr_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index f9a407e40aff..69a77e24d229 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -29,50 +29,51 @@
#ifndef __iwl_debug_h__
#define __iwl_debug_h__
+#include "iwl-bus.h"
+#include "iwl-shared.h"
+
struct iwl_priv;
-extern u32 iwl_debug_level;
-#define IWL_ERR(p, f, a...) dev_err(p->bus->dev, f, ## a)
-#define IWL_WARN(p, f, a...) dev_warn(p->bus->dev, f, ## a)
-#define IWL_INFO(p, f, a...) dev_info(p->bus->dev, f, ## a)
-#define IWL_CRIT(p, f, a...) dev_crit(p->bus->dev, f, ## a)
+/*No matter what is m (priv, bus, trans), this will work */
+#define IWL_ERR(m, f, a...) dev_err(bus(m)->dev, f, ## a)
+#define IWL_WARN(m, f, a...) dev_warn(bus(m)->dev, f, ## a)
+#define IWL_INFO(m, f, a...) dev_info(bus(m)->dev, f, ## a)
+#define IWL_CRIT(m, f, a...) dev_crit(bus(m)->dev, f, ## a)
-#define iwl_print_hex_error(priv, p, len) \
+#define iwl_print_hex_error(m, p, len) \
do { \
print_hex_dump(KERN_ERR, "iwl data: ", \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0)
#ifdef CONFIG_IWLWIFI_DEBUG
-#define IWL_DEBUG(__priv, level, fmt, args...) \
+#define IWL_DEBUG(m, level, fmt, args...) \
do { \
- if (iwl_get_debug_level(__priv) & (level)) \
- dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \
+ if (iwl_get_debug_level((m)->shrd) & (level)) \
+ dev_printk(KERN_ERR, bus(m)->dev, \
"%c %s " fmt, in_interrupt() ? 'I' : 'U', \
__func__ , ## args); \
} while (0)
-#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \
+#define IWL_DEBUG_LIMIT(m, level, fmt, args...) \
do { \
- if ((iwl_get_debug_level(__priv) & (level)) && net_ratelimit()) \
- dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \
+ if (iwl_get_debug_level((m)->shrd) & (level) && net_ratelimit())\
+ dev_printk(KERN_ERR, bus(m)->dev, \
"%c %s " fmt, in_interrupt() ? 'I' : 'U', \
__func__ , ## args); \
} while (0)
-#define iwl_print_hex_dump(priv, level, p, len) \
+#define iwl_print_hex_dump(m, level, p, len) \
do { \
- if (iwl_get_debug_level(priv) & level) \
+ if (iwl_get_debug_level((m)->shrd) & level) \
print_hex_dump(KERN_DEBUG, "iwl data: ", \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0)
#else
-#define IWL_DEBUG(__priv, level, fmt, args...)
-#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)
-static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
- const void *p, u32 len)
-{}
+#define IWL_DEBUG(m, level, fmt, args...)
+#define IWL_DEBUG_LIMIT(m, level, fmt, args...)
+#define iwl_print_hex_dump(m, level, p, len)
#endif /* CONFIG_IWLWIFI_DEBUG */
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -104,10 +105,12 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
*
* The active debug levels can be accessed via files
*
- * /sys/module/iwlagn/parameters/debug{50}
- * /sys/class/net/wlan0/device/debug_level
- *
+ * /sys/module/iwlwifi/parameters/debug
* when CONFIG_IWLWIFI_DEBUG=y.
+ *
+ * /sys/kernel/debug/phy0/iwlwifi/debug/debug_level
+ * when CONFIG_IWLWIFI_DEBUGFS=y.
+ *
*/
/* 0x0000000F - 0x00000001 */
@@ -166,6 +169,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
#define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
+#define IWL_DEBUG_FW_ERRORS(p, f, a...) IWL_DEBUG(p, IWL_DL_FW_ERRORS, f, ## a)
#define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
#define IWL_DEBUG_DROP_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index ec1485b2d3fe..a1670e3f8bfa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -64,6 +64,14 @@
goto err; \
} while (0)
+#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \
+ struct dentry *__tmp; \
+ __tmp = debugfs_create_u32(#name, mode, \
+ parent, ptr); \
+ if (IS_ERR(__tmp) || !__tmp) \
+ goto err; \
+} while (0)
+
/* file operation */
#define DEBUGFS_READ_FUNC(name) \
static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
@@ -254,7 +262,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
sram = priv->dbgfs_sram_offset & ~0x3;
/* read the first u32 from sram */
- val = iwl_read_targ_mem(priv, sram);
+ val = iwl_read_targ_mem(bus(priv), sram);
for (; len; len--) {
/* put the address at the start of every line */
@@ -273,7 +281,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
if (++offset == 4) {
sram += 4;
offset = 0;
- val = iwl_read_targ_mem(priv, sram);
+ val = iwl_read_targ_mem(bus(priv), sram);
}
/* put in extra spaces and split lines for human readability */
@@ -340,7 +348,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
{
struct iwl_priv *priv = file->private_data;
struct iwl_station_entry *station;
- int max_sta = priv->hw_params.max_stations;
+ struct iwl_tid_data *tid_data;
char *buf;
int i, j, pos = 0;
ssize_t ret;
@@ -354,7 +362,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
priv->num_stations);
- for (i = 0; i < max_sta; i++) {
+ for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
station = &priv->stations[i];
if (!station->used)
continue;
@@ -363,22 +371,18 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
i, station->sta.sta.addr,
station->sta.station_flags_msk);
pos += scnprintf(buf + pos, bufsz - pos,
- "TID\tseq_num\ttxq_id\tframes\ttfds\t");
- pos += scnprintf(buf + pos, bufsz - pos,
- "start_idx\tbitmap\t\t\trate_n_flags\n");
+ "TID\tseq_num\ttxq_id\ttfds\trate_n_flags\n");
- for (j = 0; j < MAX_TID_COUNT; j++) {
+ for (j = 0; j < IWL_MAX_TID_COUNT; j++) {
+ tid_data = &priv->shrd->tid_data[i][j];
pos += scnprintf(buf + pos, bufsz - pos,
- "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
- j, station->tid[j].seq_number,
- station->tid[j].agg.txq_id,
- station->tid[j].agg.frame_count,
- station->tid[j].tfds_in_queue,
- station->tid[j].agg.start_idx,
- station->tid[j].agg.bitmap,
- station->tid[j].agg.rate_n_flags);
-
- if (station->tid[j].agg.wait_for_ba)
+ "%d:\t%#x\t%#x\t%u\t%#x",
+ j, tid_data->seq_number,
+ tid_data->agg.txq_id,
+ tid_data->tfds_in_queue,
+ tid_data->agg.rate_n_flags);
+
+ if (tid_data->agg.wait_for_ba)
pos += scnprintf(buf + pos, bufsz - pos,
" - waitforba");
pos += scnprintf(buf + pos, bufsz - pos, "\n");
@@ -442,46 +446,6 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
return ret;
}
-static ssize_t iwl_dbgfs_log_event_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char *buf;
- int pos = 0;
- ssize_t ret = -ENOMEM;
-
- ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true);
- if (buf) {
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- kfree(buf);
- }
- return ret;
-}
-
-static ssize_t iwl_dbgfs_log_event_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- u32 event_log_flag;
- char buf[8];
- int buf_size;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &event_log_flag) != 1)
- return -EFAULT;
- if (event_log_flag == 1)
- iwl_dump_nic_event_log(priv, true, NULL, false);
-
- return count;
-}
-
-
-
static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -492,7 +456,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
char *buf;
ssize_t ret;
- if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
+ if (!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -562,45 +526,46 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
const size_t bufsz = sizeof(buf);
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
- test_bit(STATUS_HCMD_ACTIVE, &priv->status));
+ test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
- test_bit(STATUS_INT_ENABLED, &priv->status));
+ test_bit(STATUS_INT_ENABLED, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
- test_bit(STATUS_RF_KILL_HW, &priv->status));
+ test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
- test_bit(STATUS_CT_KILL, &priv->status));
+ test_bit(STATUS_CT_KILL, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
- test_bit(STATUS_INIT, &priv->status));
+ test_bit(STATUS_INIT, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
- test_bit(STATUS_ALIVE, &priv->status));
+ test_bit(STATUS_ALIVE, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
- test_bit(STATUS_READY, &priv->status));
+ test_bit(STATUS_READY, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
- test_bit(STATUS_TEMPERATURE, &priv->status));
+ test_bit(STATUS_TEMPERATURE, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
- test_bit(STATUS_GEO_CONFIGURED, &priv->status));
+ test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
- test_bit(STATUS_EXIT_PENDING, &priv->status));
+ test_bit(STATUS_EXIT_PENDING, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
- test_bit(STATUS_STATISTICS, &priv->status));
+ test_bit(STATUS_STATISTICS, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
- test_bit(STATUS_SCANNING, &priv->status));
+ test_bit(STATUS_SCANNING, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
- test_bit(STATUS_SCAN_ABORTING, &priv->status));
+ test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
- test_bit(STATUS_SCAN_HW, &priv->status));
+ test_bit(STATUS_SCAN_HW, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
- test_bit(STATUS_POWER_PMI, &priv->status));
+ test_bit(STATUS_POWER_PMI, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
- test_bit(STATUS_FW_ERROR, &priv->status));
+ test_bit(STATUS_FW_ERROR, &priv->shrd->status));
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
-static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
+static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
struct iwl_priv *priv = file->private_data;
+
int pos = 0;
int cnt = 0;
char *buf;
@@ -613,61 +578,25 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
return -ENOMEM;
}
- pos += scnprintf(buf + pos, bufsz - pos,
- "Interrupt Statistics Report:\n");
-
- pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
- priv->isr_stats.hw);
- pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
- priv->isr_stats.sw);
- if (priv->isr_stats.sw || priv->isr_stats.hw) {
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tLast Restarting Code: 0x%X\n",
- priv->isr_stats.err_code);
- }
-#ifdef CONFIG_IWLWIFI_DEBUG
- pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
- priv->isr_stats.sch);
- pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
- priv->isr_stats.alive);
-#endif
- pos += scnprintf(buf + pos, bufsz - pos,
- "HW RF KILL switch toggled:\t %u\n",
- priv->isr_stats.rfkill);
-
- pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
- priv->isr_stats.ctkill);
-
- pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
- priv->isr_stats.wakeup);
-
- pos += scnprintf(buf + pos, bufsz - pos,
- "Rx command responses:\t\t %u\n",
- priv->isr_stats.rx);
for (cnt = 0; cnt < REPLY_MAX; cnt++) {
- if (priv->isr_stats.rx_handlers[cnt] > 0)
+ if (priv->rx_handlers_stats[cnt] > 0)
pos += scnprintf(buf + pos, bufsz - pos,
"\tRx handler[%36s]:\t\t %u\n",
get_cmd_string(cnt),
- priv->isr_stats.rx_handlers[cnt]);
+ priv->rx_handlers_stats[cnt]);
}
- pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
- priv->isr_stats.tx);
-
- pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
- priv->isr_stats.unhandled);
-
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
}
-static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
+static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
+
char buf[8];
int buf_size;
u32 reset_flag;
@@ -679,7 +608,8 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
if (sscanf(buf, "%x", &reset_flag) != 1)
return -EFAULT;
if (reset_flag == 0)
- iwl_clear_isr_stats(priv);
+ memset(&priv->rx_handlers_stats[0], 0,
+ sizeof(priv->rx_handlers_stats));
return count;
}
@@ -784,6 +714,20 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
+static ssize_t iwl_dbgfs_temperature_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ char buf[8];
+ int pos = 0;
+ const size_t bufsz = sizeof(buf);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "%d\n", priv->temperature);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+
static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
@@ -814,14 +758,14 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
return -EINVAL;
- if (!iwl_is_ready_rf(priv))
+ if (!iwl_is_ready_rf(priv->shrd))
return -EAGAIN;
priv->power_data.debug_sleep_level_override = value;
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
iwl_power_update_mode(priv, true);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
return count;
}
@@ -870,15 +814,15 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
DEBUGFS_READ_WRITE_FILE_OPS(sram);
DEBUGFS_READ_FILE_OPS(wowlan_sram);
-DEBUGFS_READ_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(nvm);
DEBUGFS_READ_FILE_OPS(stations);
DEBUGFS_READ_FILE_OPS(channels);
DEBUGFS_READ_FILE_OPS(status);
-DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
+DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers);
DEBUGFS_READ_FILE_OPS(qos);
DEBUGFS_READ_FILE_OPS(thermal_throttling);
DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
+DEBUGFS_READ_FILE_OPS(temperature);
DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
DEBUGFS_READ_FILE_OPS(current_sleep_command);
@@ -889,36 +833,23 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
struct iwl_priv *priv = file->private_data;
int pos = 0, ofs = 0;
int cnt = 0, entry;
- struct iwl_tx_queue *txq;
- struct iwl_queue *q;
- struct iwl_rx_queue *rxq = &priv->rxq;
+
char *buf;
int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
- (priv->cfg->base_params->num_of_queues * 32 * 8) + 400;
+ (hw_params(priv).max_txq_num * 32 * 8) + 400;
const u8 *ptr;
ssize_t ret;
- if (!priv->txq) {
- IWL_ERR(priv, "txq not ready\n");
- return -EAGAIN;
- }
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate buffer\n");
return -ENOMEM;
}
- pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
- for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
- txq = &priv->txq[cnt];
- q = &txq->q;
- pos += scnprintf(buf + pos, bufsz - pos,
- "q[%d]: read_ptr: %u, write_ptr: %u\n",
- cnt, q->read_ptr, q->write_ptr);
- }
- if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
+ if (priv->tx_traffic &&
+ (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) {
ptr = priv->tx_traffic;
pos += scnprintf(buf + pos, bufsz - pos,
- "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
+ "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
entry++, ofs += 16) {
@@ -933,15 +864,11 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
}
}
- pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
- pos += scnprintf(buf + pos, bufsz - pos,
- "read: %u, write: %u\n",
- rxq->read, rxq->write);
-
- if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
+ if (priv->rx_traffic &&
+ (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) {
ptr = priv->rx_traffic;
pos += scnprintf(buf + pos, bufsz - pos,
- "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
+ "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
entry++, ofs += 16) {
@@ -982,76 +909,6 @@ static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
return count;
}
-static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- struct iwl_tx_queue *txq;
- struct iwl_queue *q;
- char *buf;
- int pos = 0;
- int cnt;
- int ret;
- const size_t bufsz = sizeof(char) * 64 *
- priv->cfg->base_params->num_of_queues;
-
- if (!priv->txq) {
- IWL_ERR(priv, "txq not ready\n");
- return -EAGAIN;
- }
- buf = kzalloc(bufsz, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
- txq = &priv->txq[cnt];
- q = &txq->q;
- pos += scnprintf(buf + pos, bufsz - pos,
- "hwq %.2d: read=%u write=%u stop=%d"
- " swq_id=%#.2x (ac %d/hwq %d)\n",
- cnt, q->read_ptr, q->write_ptr,
- !!test_bit(cnt, priv->queue_stopped),
- txq->swq_id, txq->swq_id & 3,
- (txq->swq_id >> 2) & 0x1f);
- if (cnt >= 4)
- continue;
- /* for the ACs, display the stop count too */
- pos += scnprintf(buf + pos, bufsz - pos,
- " stop-count: %d\n",
- atomic_read(&priv->queue_stop_count[cnt]));
- }
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- kfree(buf);
- return ret;
-}
-
-static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos) {
-
- struct iwl_priv *priv = file->private_data;
- struct iwl_rx_queue *rxq = &priv->rxq;
- char buf[256];
- int pos = 0;
- const size_t bufsz = sizeof(buf);
-
- pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
- rxq->read);
- pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
- rxq->write);
- pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
- rxq->free_count);
- if (rxq->rb_stts) {
- pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
- le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF);
- } else {
- pos += scnprintf(buf + pos, bufsz - pos,
- "closed_rb_num: Not Allocated\n");
- }
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
static const char *fmt_value = " %-30s %10u\n";
static const char *fmt_hex = " %-30s 0x%02X\n";
static const char *fmt_table = " %-30s %10u %10u %10u %10u\n";
@@ -1096,7 +953,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
struct statistics_rx_non_phy *delta_general, *max_general;
struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
- if (!iwl_is_alive(priv))
+ if (!iwl_is_alive(priv->shrd))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -1522,7 +1379,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
ssize_t ret;
struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
- if (!iwl_is_alive(priv))
+ if (!iwl_is_alive(priv->shrd))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -1716,7 +1573,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
struct statistics_div *div, *accum_div, *delta_div, *max_div;
- if (!iwl_is_alive(priv))
+ if (!iwl_is_alive(priv->shrd))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -1829,16 +1686,16 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
ssize_t ret;
struct statistics_bt_activity *bt, *accum_bt;
- if (!iwl_is_alive(priv))
+ if (!iwl_is_alive(priv->shrd))
return -EAGAIN;
if (!priv->bt_enable_flag)
return -EINVAL;
/* make request to uCode to retrieve statistics information */
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
if (ret) {
IWL_ERR(priv,
@@ -1917,7 +1774,7 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
(sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;
ssize_t ret;
- if (!iwl_is_alive(priv))
+ if (!iwl_is_alive(priv->shrd))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
@@ -2199,7 +2056,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
const size_t bufsz = sizeof(buf);
u32 pwrsave_status;
- pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) &
+ pwrsave_status = iwl_read32(bus(priv), CSR_GP_CNTRL) &
CSR_GP_REG_POWER_SAVE_STATUS_MSK;
pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
@@ -2229,30 +2086,9 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
return -EFAULT;
/* make request to uCode to retrieve statistics information */
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
iwl_send_statistics_request(priv, CMD_SYNC, true);
- mutex_unlock(&priv->mutex);
-
- return count;
-}
-
-static ssize_t iwl_dbgfs_csr_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int csr;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &csr) != 1)
- return -EFAULT;
-
- iwl_dump_csr(priv);
+ mutex_unlock(&priv->shrd->mutex);
return count;
}
@@ -2333,25 +2169,6 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
-static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char *buf;
- int pos = 0;
- ssize_t ret = -EFAULT;
-
- ret = pos = iwl_dump_fh(priv, &buf, true);
- if (buf) {
- ret = simple_read_from_buffer(user_buf,
- count, ppos, buf, pos);
- kfree(buf);
- }
-
- return ret;
-}
-
static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
@@ -2434,8 +2251,8 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
static ssize_t iwl_dbgfs_force_reset_read(struct file *file,
char __user *user_buf,
- size_t count, loff_t *ppos) {
-
+ size_t count, loff_t *ppos)
+{
struct iwl_priv *priv = file->private_data;
int i, pos = 0;
char buf[300];
@@ -2504,7 +2321,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
if (sscanf(buf, "%d", &flush) != 1)
return -EINVAL;
- if (iwl_is_rfkill(priv))
+ if (iwl_is_rfkill(priv->shrd))
return -EFAULT;
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
@@ -2514,8 +2331,8 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
const char __user *user_buf,
- size_t count, loff_t *ppos) {
-
+ size_t count, loff_t *ppos)
+{
struct iwl_priv *priv = file->private_data;
char buf[8];
int buf_size;
@@ -2626,11 +2443,26 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
return count;
}
+static ssize_t iwl_dbgfs_echo_test_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ char buf[8];
+ int buf_size;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+
+ iwl_cmd_echo_test(priv);
+ return count;
+}
+
DEBUGFS_READ_FILE_OPS(rx_statistics);
DEBUGFS_READ_FILE_OPS(tx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
-DEBUGFS_READ_FILE_OPS(rx_queue);
-DEBUGFS_READ_FILE_OPS(tx_queue);
DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
DEBUGFS_READ_FILE_OPS(ucode_general_stats);
@@ -2639,9 +2471,7 @@ DEBUGFS_READ_FILE_OPS(chain_noise);
DEBUGFS_READ_FILE_OPS(power_save_status);
DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
-DEBUGFS_WRITE_FILE_OPS(csr);
DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
-DEBUGFS_READ_FILE_OPS(fh_reg);
DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
@@ -2653,6 +2483,53 @@ DEBUGFS_WRITE_FILE_OPS(wd_timeout);
DEBUGFS_READ_FILE_OPS(bt_traffic);
DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
DEBUGFS_READ_FILE_OPS(reply_tx_error);
+DEBUGFS_WRITE_FILE_OPS(echo_test);
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+static ssize_t iwl_dbgfs_debug_level_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ struct iwl_shared *shrd = priv->shrd;
+ char buf[11];
+ int len;
+
+ len = scnprintf(buf, sizeof(buf), "0x%.8x",
+ iwl_get_debug_level(shrd));
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t iwl_dbgfs_debug_level_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ struct iwl_shared *shrd = priv->shrd;
+ char buf[11];
+ unsigned long val;
+ int ret;
+
+ if (count > sizeof(buf))
+ return -EINVAL;
+
+ memset(buf, 0, sizeof(buf));
+ if (copy_from_user(buf, user_buf, count))
+ return -EFAULT;
+
+ ret = strict_strtoul(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ shrd->dbg_level_dev = val;
+ if (iwl_alloc_traffic_mem(priv))
+ IWL_ERR(priv, "Not enough memory to generate traffic log\n");
+
+ return count;
+}
+DEBUGFS_READ_WRITE_FILE_OPS(debug_level);
+#endif /* CONFIG_IWLWIFI_DEBUG */
/*
* Create the debugfs files and directories
@@ -2682,26 +2559,23 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR);
- DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
- DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(rx_handlers, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(temperature, dir_data, S_IRUSR);
+
DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
- DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
- DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
- DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR);
- DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
@@ -2710,7 +2584,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);
-
DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
@@ -2719,12 +2592,20 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
+ DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR);
if (iwl_advanced_bt_coexist(priv))
DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
+#ifdef CONFIG_IWLWIFI_DEBUG
+ DEBUGFS_ADD_FILE(debug_level, dir_debug, S_IRUSR | S_IWUSR);
+#endif
+
DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
&priv->disable_sens_cal);
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
&priv->disable_chain_noise_cal);
+
+ if (iwl_trans_dbgfs_register(trans(priv), dir_debug))
+ goto err;
return 0;
err:
@@ -2745,6 +2626,3 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
debugfs_remove_recursive(priv->debugfs_dir);
priv->debugfs_dir = NULL;
}
-
-
-
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 6c9790cac8d0..6c00a447963d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -32,16 +32,15 @@
#define __iwl_dev_h__
#include <linux/interrupt.h>
-#include <linux/pci.h> /* for struct pci_device_id */
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/leds.h>
+#include <linux/slab.h>
#include <net/ieee80211_radiotap.h>
#include "iwl-eeprom.h"
#include "iwl-csr.h"
#include "iwl-prph.h"
-#include "iwl-fh.h"
#include "iwl-debug.h"
#include "iwl-agn-hw.h"
#include "iwl-led.h"
@@ -50,8 +49,7 @@
#include "iwl-agn-tt.h"
#include "iwl-bus.h"
#include "iwl-trans.h"
-
-#define DRV_NAME "iwlagn"
+#include "iwl-shared.h"
struct iwl_tx_queue;
@@ -90,109 +88,6 @@ struct iwl_tx_queue;
#define DEFAULT_SHORT_RETRY_LIMIT 7U
#define DEFAULT_LONG_RETRY_LIMIT 4U
-struct iwl_rx_mem_buffer {
- dma_addr_t page_dma;
- struct page *page;
- struct list_head list;
-};
-
-#define rxb_addr(r) page_address(r->page)
-
-/* defined below */
-struct iwl_device_cmd;
-
-struct iwl_cmd_meta {
- /* only for SYNC commands, iff the reply skb is wanted */
- struct iwl_host_cmd *source;
- /*
- * only for ASYNC commands
- * (which is somewhat stupid -- look at iwl-sta.c for instance
- * which duplicates a bunch of code because the callback isn't
- * invoked for SYNC commands, if it were and its result passed
- * through it would be simpler...)
- */
- void (*callback)(struct iwl_priv *priv,
- struct iwl_device_cmd *cmd,
- struct iwl_rx_packet *pkt);
-
- u32 flags;
-
- DEFINE_DMA_UNMAP_ADDR(mapping);
- DEFINE_DMA_UNMAP_LEN(len);
-};
-
-/*
- * Generic queue structure
- *
- * Contains common data for Rx and Tx queues.
- *
- * Note the difference between n_bd and n_window: the hardware
- * always assumes 256 descriptors, so n_bd is always 256 (unless
- * there might be HW changes in the future). For the normal TX
- * queues, n_window, which is the size of the software queue data
- * is also 256; however, for the command queue, n_window is only
- * 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.
- * This means that we end up with the following:
- * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
- * SW entries: | 0 | ... | 31 |
- * where N is a number between 0 and 7. This means that the SW
- * data is a window overlayed over the HW queue.
- */
-struct iwl_queue {
- int n_bd; /* number of BDs in this queue */
- int write_ptr; /* 1-st empty entry (index) host_w*/
- int read_ptr; /* last used entry (index) host_r*/
- /* use for monitoring and recovering the stuck queue */
- dma_addr_t dma_addr; /* physical addr for BD's */
- int n_window; /* safe queue window */
- u32 id;
- int low_mark; /* low watermark, resume queue if free
- * space more than this */
- int high_mark; /* high watermark, stop queue if free
- * space less than this */
-};
-
-/* One for each TFD */
-struct iwl_tx_info {
- struct sk_buff *skb;
- struct iwl_rxon_context *ctx;
-};
-
-/**
- * struct iwl_tx_queue - Tx Queue for DMA
- * @q: generic Rx/Tx queue descriptor
- * @bd: base of circular buffer of TFDs
- * @cmd: array of command/TX buffer pointers
- * @meta: array of meta data for each command/tx buffer
- * @dma_addr_cmd: physical address of cmd/tx buffer array
- * @txb: array of per-TFD driver data
- * @time_stamp: time (in jiffies) of last read_ptr change
- * @need_update: indicates need to update read/write index
- * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
- *
- * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
- * descriptors) and required locking structures.
- */
-#define TFD_TX_CMD_SLOTS 256
-#define TFD_CMD_SLOTS 32
-
-struct iwl_tx_queue {
- struct iwl_queue q;
- struct iwl_tfd *tfds;
- struct iwl_device_cmd **cmd;
- struct iwl_cmd_meta *meta;
- struct iwl_tx_info *txb;
- unsigned long time_stamp;
- u8 need_update;
- u8 sched_retry;
- u8 active;
- u8 swq_id;
-};
-
#define IWL_NUM_SCAN_RATES (2)
/*
@@ -222,20 +117,16 @@ struct iwl_channel_info {
u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
};
-#define IWL_TX_FIFO_BK 0 /* shared */
-#define IWL_TX_FIFO_BE 1
-#define IWL_TX_FIFO_VI 2 /* shared */
-#define IWL_TX_FIFO_VO 3
-#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK
-#define IWL_TX_FIFO_BE_IPAN 4
-#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI
-#define IWL_TX_FIFO_VO_IPAN 5
-#define IWL_TX_FIFO_UNUSED -1
-
-/* Minimum number of queues. MAX_NUM is defined in hw specific files.
- * Set the minimum to accommodate the 4 standard TX queues, 1 command
- * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */
-#define IWL_MIN_NUM_QUEUES 10
+/*
+ * Minimum number of queues. MAX_NUM is defined in hw specific files.
+ * Set the minimum to accommodate
+ * - 4 standard TX queues
+ * - the command queue
+ * - 4 PAN TX queues
+ * - the PAN multicast queue, and
+ * - the AUX (TX during scan dwell) queue.
+ */
+#define IWL_MIN_NUM_QUEUES 11
/*
* Command queue depends on iPAN support.
@@ -243,161 +134,20 @@ struct iwl_channel_info {
#define IWL_DEFAULT_CMD_QUEUE_NUM 4
#define IWL_IPAN_CMD_QUEUE_NUM 9
-/*
- * This queue number is required for proper operation
- * because the ucode will stop/start the scheduler as
- * required.
- */
-#define IWL_IPAN_MCAST_QUEUE 8
-
#define IEEE80211_DATA_LEN 2304
#define IEEE80211_4ADDR_LEN 30
#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
-
-#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
-
-enum {
- CMD_SYNC = 0,
- CMD_ASYNC = BIT(0),
- CMD_WANT_SKB = BIT(1),
- CMD_ON_DEMAND = BIT(2),
-};
-
-#define DEF_CMD_PAYLOAD_SIZE 320
-
-/**
- * struct iwl_device_cmd
- *
- * For allocation of the command and tx queues, this establishes the overall
- * size of the largest command we send to uCode, except for commands that
- * aren't fully copied and use other TFD space.
- */
-struct iwl_device_cmd {
- struct iwl_cmd_header hdr; /* uCode API */
- union {
- u32 flags;
- u8 val8;
- u16 val16;
- u32 val32;
- struct iwl_tx_cmd tx;
- struct iwl6000_channel_switch_cmd chswitch;
- u8 payload[DEF_CMD_PAYLOAD_SIZE];
- } __packed cmd;
-} __packed;
-
-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
-
-#define IWL_MAX_CMD_TFDS 2
-
-enum iwl_hcmd_dataflag {
- IWL_HCMD_DFL_NOCOPY = BIT(0),
-};
-
-/**
- * struct iwl_host_cmd - Host command to the uCode
- * @data: array of chunks that composes the data of the host command
- * @reply_page: pointer to the page that holds the response to the host command
- * @callback:
- * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
- * @len: array of the lenths of the chunks in data
- * @dataflags:
- * @id: id of the host command
- */
-struct iwl_host_cmd {
- const void *data[IWL_MAX_CMD_TFDS];
- unsigned long reply_page;
- void (*callback)(struct iwl_priv *priv,
- struct iwl_device_cmd *cmd,
- struct iwl_rx_packet *pkt);
- u32 flags;
- u16 len[IWL_MAX_CMD_TFDS];
- u8 dataflags[IWL_MAX_CMD_TFDS];
- u8 id;
-};
-
#define SUP_RATE_11A_MAX_NUM_CHANNELS 8
#define SUP_RATE_11B_MAX_NUM_CHANNELS 4
#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
-/**
- * struct iwl_rx_queue - Rx queue
- * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
- * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
- * @read: Shared index to newest available Rx buffer
- * @write: Shared index to oldest written Rx packet
- * @free_count: Number of pre-allocated buffers in rx_free
- * @rx_free: list of free SKBs for use
- * @rx_used: List of Rx buffers with no SKB
- * @need_update: flag to indicate we need to update read/write index
- * @rb_stts: driver's pointer to receive buffer status
- * @rb_stts_dma: bus address of receive buffer status
- *
- * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
- */
-struct iwl_rx_queue {
- __le32 *bd;
- dma_addr_t bd_dma;
- struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
- struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
- u32 read;
- u32 write;
- u32 free_count;
- u32 write_actual;
- struct list_head rx_free;
- struct list_head rx_used;
- int need_update;
- struct iwl_rb_status *rb_stts;
- dma_addr_t rb_stts_dma;
- spinlock_t lock;
-};
-
#define IWL_SUPPORTED_RATES_IE_LEN 8
-#define MAX_TID_COUNT 9
-
#define IWL_INVALID_RATE 0xFF
#define IWL_INVALID_VALUE -1
-/**
- * struct iwl_ht_agg -- aggregation status while waiting for block-ack
- * @txq_id: Tx queue used for Tx attempt
- * @frame_count: # frames attempted by Tx command
- * @wait_for_ba: Expect block-ack before next Tx reply
- * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window
- * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window
- * @bitmap1: High order, one bit for each frame pending ACK in Tx window
- * @rate_n_flags: Rate at which Tx was attempted
- *
- * If REPLY_TX indicates that aggregation was attempted, driver must wait
- * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info
- * until block ack arrives.
- */
-struct iwl_ht_agg {
- u16 txq_id;
- u16 frame_count;
- u16 wait_for_ba;
- u16 start_idx;
- u64 bitmap;
- u32 rate_n_flags;
-#define IWL_AGG_OFF 0
-#define IWL_AGG_ON 1
-#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
-#define IWL_EMPTYING_HW_QUEUE_DELBA 3
- u8 state;
- u8 tx_fifo;
-};
-
-
-struct iwl_tid_data {
- u16 seq_number; /* agn only */
- u16 tfds_in_queue;
- struct iwl_ht_agg agg;
-};
-
union iwl_ht_rate_supp {
u16 rates;
struct {
@@ -448,16 +198,10 @@ struct iwl_qos_info {
*/
struct iwl_station_entry {
struct iwl_addsta_cmd sta;
- struct iwl_tid_data tid[MAX_TID_COUNT];
u8 used, ctxid;
struct iwl_link_quality_cmd *lq;
};
-struct iwl_station_priv_common {
- struct iwl_rxon_context *ctx;
- u8 sta_id;
-};
-
/*
* iwl_station_priv: Driver's private station information
*
@@ -466,12 +210,13 @@ struct iwl_station_priv_common {
* space.
*/
struct iwl_station_priv {
- struct iwl_station_priv_common common;
+ struct iwl_rxon_context *ctx;
struct iwl_lq_sta lq_sta;
atomic_t pending_frames;
bool client;
bool asleep;
u8 max_agg_bufsize;
+ u8 sta_id;
};
/**
@@ -564,11 +309,13 @@ enum iwl_ucode_tlv_type {
* @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
* treats good CRC threshold as a boolean
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
+ * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
*/
enum iwl_ucode_tlv_flag {
IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
+ IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
};
struct iwl_ucode_tlv {
@@ -634,54 +381,6 @@ struct iwl_sensitivity_ranges {
#define CELSIUS_TO_KELVIN(x) ((x)+273)
-/**
- * struct iwl_hw_params
- * @max_txq_num: Max # Tx queues supported
- * @scd_bc_tbls_size: size of scheduler byte count tables
- * @tfd_size: TFD size
- * @tx/rx_chains_num: Number of TX/RX chains
- * @valid_tx/rx_ant: usable antennas
- * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
- * @max_rxq_log: Log-base-2 of max_rxq_size
- * @rx_page_order: Rx buffer page order
- * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
- * @max_stations:
- * @ht40_channel: is 40MHz width possible in band 2.4
- * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
- * @sw_crypto: 0 for hw, 1 for sw
- * @max_xxx_size: for ucode uses
- * @ct_kill_threshold: temperature threshold
- * @beacon_time_tsf_bits: number of valid tsf bits for beacon time
- * @calib_init_cfg: setup initial calibrations for the hw
- * @calib_rt_cfg: setup runtime calibrations for the hw
- * @struct iwl_sensitivity_ranges: range of sensitivity values
- */
-struct iwl_hw_params {
- u8 max_txq_num;
- u16 scd_bc_tbls_size;
- u32 tfd_size;
- u8 tx_chains_num;
- u8 rx_chains_num;
- u8 valid_tx_ant;
- u8 valid_rx_ant;
- u16 max_rxq_size;
- u16 max_rxq_log;
- u32 rx_page_order;
- u8 max_stations;
- u8 ht40_channel;
- u8 max_beacon_itrvl; /* in 1024 ms */
- u32 max_inst_size;
- u32 max_data_size;
- u32 ct_kill_threshold; /* value in hw-dependent units */
- u32 ct_kill_exit_threshold; /* value in hw-dependent units */
- /* for 1000, 6000 series and up */
- u16 beacon_time_tsf_bits;
- u32 calib_init_cfg;
- u32 calib_rt_cfg;
- const struct iwl_sensitivity_ranges *sens;
-};
-
-
/******************************************************************************
*
* Functions implemented in core module which are forward declared here
@@ -697,35 +396,12 @@ struct iwl_hw_params {
****************************************************************************/
extern void iwl_update_chain_flags(struct iwl_priv *priv);
extern const u8 iwl_bcast_addr[ETH_ALEN];
-extern int iwl_queue_space(const struct iwl_queue *q);
-static inline int 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) :
- !(i < q->read_ptr && i >= q->write_ptr);
-}
-
-
-static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
-{
- return index & (q->n_window - 1);
-}
-
-
-struct iwl_dma_ptr {
- dma_addr_t dma;
- void *addr;
- size_t size;
-};
#define IWL_OPERATION_MODE_AUTO 0
#define IWL_OPERATION_MODE_HT_ONLY 1
#define IWL_OPERATION_MODE_MIXED 2
#define IWL_OPERATION_MODE_20MHZ 3
-#define IWL_TX_CRC_SIZE 4
-#define IWL_TX_DELIMITER_SIZE 4
-
#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
/* Sensitivity and chain noise calibration */
@@ -849,9 +525,6 @@ struct iwl_chain_noise_data {
#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */
#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
-#define IWL_TRAFFIC_ENTRIES (256)
-#define IWL_TRAFFIC_ENTRY_SIZE (64)
-
enum {
MEASUREMENT_READY = (1 << 0),
MEASUREMENT_ACTIVE = (1 << 1),
@@ -884,22 +557,6 @@ enum iwl_pa_type {
IWL_PA_INTERNAL = 1,
};
-/* interrupt statistics */
-struct isr_statistics {
- u32 hw;
- u32 sw;
- u32 err_code;
- u32 sch;
- u32 alive;
- u32 rfkill;
- u32 ctkill;
- u32 wakeup;
- u32 rx;
- u32 rx_handlers[REPLY_MAX];
- u32 tx;
- u32 unhandled;
-};
-
/* reply_tx_statistics (for _agn devices) */
struct reply_tx_error_statistics {
u32 pp_delay;
@@ -1009,21 +666,6 @@ struct iwl_event_log {
};
/*
- * host interrupt timeout value
- * used with setting interrupt coalescing timer
- * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
- *
- * default interrupt coalescing timer is 64 x 32 = 2048 usecs
- * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
- */
-#define IWL_HOST_INT_TIMEOUT_MAX (0xFF)
-#define IWL_HOST_INT_TIMEOUT_DEF (0x40)
-#define IWL_HOST_INT_TIMEOUT_MIN (0x0)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
-#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
-
-/*
* This is the threshold value of plcp error rate per 100mSecs. It is
* used to set and check for the validity of plcp_delta.
*/
@@ -1101,20 +743,9 @@ struct iwl_notification_wait {
bool triggered, aborted;
};
-enum iwl_rxon_context_id {
- IWL_RXON_CTX_BSS,
- IWL_RXON_CTX_PAN,
-
- NUM_IWL_RXON_CTX
-};
-
struct iwl_rxon_context {
struct ieee80211_vif *vif;
- const u8 *ac_to_fifo;
- const u8 *ac_to_queue;
- u8 mcast_queue;
-
/*
* We could use the vif to indicate active, but we
* also need it to be active during disabling when
@@ -1162,13 +793,16 @@ struct iwl_rxon_context {
u8 extension_chan_offset;
} ht;
+ u8 bssid[ETH_ALEN];
+ bool preauth_bssid;
+
bool last_tx_rejected;
};
enum iwl_scan_type {
IWL_SCAN_NORMAL,
IWL_SCAN_RADIO_RESET,
- IWL_SCAN_OFFCH_TX,
+ IWL_SCAN_ROC,
};
enum iwlagn_ucode_type {
@@ -1190,24 +824,26 @@ struct iwl_testmode_trace {
};
#endif
-/* uCode ownership */
-#define IWL_OWNERSHIP_DRIVER 0
-#define IWL_OWNERSHIP_TM 1
-
struct iwl_priv {
+ /*data shared among all the driver's layers */
+ struct iwl_shared _shrd;
+ struct iwl_shared *shrd;
+
/* ieee device used by generic ieee processing code */
struct ieee80211_hw *hw;
struct ieee80211_channel *ieee_channels;
struct ieee80211_rate *ieee_rates;
+ struct kmem_cache *tx_cmd_pool;
struct iwl_cfg *cfg;
enum ieee80211_band band;
void (*pre_rx_handler)(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
- void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb);
+ int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd);
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
@@ -1225,6 +861,9 @@ struct iwl_priv {
/* jiffies when last recovery from statistics was performed */
unsigned long rx_statistics_jiffies;
+ /*counters */
+ u32 rx_handlers_stats[REPLY_MAX];
+
/* force reset */
struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
@@ -1238,7 +877,7 @@ struct iwl_priv {
u8 channel_count; /* # of channels */
/* thermal calibration */
- s32 temperature; /* degrees Kelvin */
+ s32 temperature; /* Celsius */
s32 last_temperature;
/* init calibration results */
@@ -1255,21 +894,6 @@ struct iwl_priv {
u8 scan_tx_ant[IEEE80211_NUM_BANDS];
u8 mgmt_tx_ant;
- /* spinlock */
- spinlock_t lock; /* protect general shared data */
- spinlock_t hcmd_lock; /* protect hcmd */
- spinlock_t reg_lock; /* protect hw register access */
- struct mutex mutex;
-
- struct iwl_bus *bus; /* bus specific data */
- struct iwl_trans trans;
-
- /* microcode/device supports multiple contexts */
- u8 valid_contexts;
-
- /* command queue number */
- u8 cmd_queue;
-
/* max number of station keys */
u8 sta_key_max_num;
@@ -1283,9 +907,6 @@ struct iwl_priv {
u32 ucode_ver; /* version of ucode, copy of
iwl_ucode.ver */
- /* uCode owner: default: IWL_OWNERSHIP_DRIVER */
- u8 ucode_owner;
-
struct fw_img ucode_rt;
struct fw_img ucode_init;
struct fw_img ucode_wowlan;
@@ -1317,52 +938,25 @@ struct iwl_priv {
/* Rate scaling data */
u8 retry_rate;
- wait_queue_head_t wait_command_queue;
-
int activity_timer_active;
- /* Rx and Tx DMA processing queues */
- struct iwl_rx_queue rxq;
- struct iwl_tx_queue *txq;
- unsigned long txq_ctx_active_msk;
- struct iwl_dma_ptr kw; /* keep warm address */
- struct iwl_dma_ptr scd_bc_tbls;
-
- u32 scd_base_addr; /* scheduler sram base address */
-
- unsigned long status;
-
/* counts mgmt, ctl, and data packets */
struct traffic_stats tx_stats;
struct traffic_stats rx_stats;
- /* counts interrupts */
- struct isr_statistics isr_stats;
-
struct iwl_power_mgr power_data;
struct iwl_tt_mgmt thermal_throttle;
/* station table variables */
-
- /* Note: if lock and sta_lock are needed, lock must be acquired first */
- spinlock_t sta_lock;
int num_stations;
struct iwl_station_entry stations[IWLAGN_STATION_COUNT];
unsigned long ucode_key_table;
- /* queue refcounts */
-#define IWL_MAX_HW_QUEUES 32
- unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
- /* for each AC */
- atomic_t queue_stop_count[4];
+ u8 mac80211_registered;
/* Indication if ieee80211_ops->open has been called */
u8 is_open;
- u8 mac80211_registered;
-
- bool wowlan;
-
/* eeprom -- this is in the card's little endian byte order */
u8 *eeprom;
int nvm_device_type;
@@ -1398,14 +992,6 @@ struct iwl_priv {
} accum_stats, delta_stats, max_delta_stats;
#endif
- /* INT ICT Table */
- __le32 *ict_tbl;
- void *ict_tbl_vir;
- dma_addr_t ict_tbl_dma;
- dma_addr_t aligned_ict_tbl_dma;
- int ict_index;
- u32 inta;
- bool use_ict;
/*
* reporting the number of tids has AGG on. 0 means
* no AGGREGATION
@@ -1438,14 +1024,10 @@ struct iwl_priv {
/* remain-on-channel offload support */
struct ieee80211_channel *hw_roc_channel;
- struct delayed_work hw_roc_work;
+ struct delayed_work hw_roc_disable_work;
enum nl80211_channel_type hw_roc_chantype;
int hw_roc_duration;
- bool hw_roc_setup;
-
- struct sk_buff *offchan_tx_skb;
- int offchan_tx_timeout;
- struct ieee80211_channel *offchan_tx_chan;
+ bool hw_roc_setup, hw_roc_start_notified;
/* bt coex */
u8 bt_enable_flag;
@@ -1466,15 +1048,8 @@ struct iwl_priv {
struct iwl_rxon_context *cur_rssi_ctx;
bool bt_is_sco;
- struct iwl_hw_params hw_params;
-
- u32 inta_mask;
-
- struct workqueue_struct *workqueue;
-
struct work_struct restart;
struct work_struct scan_completed;
- struct work_struct rx_replenish;
struct work_struct abort_scan;
struct work_struct beacon_update;
@@ -1490,8 +1065,6 @@ struct iwl_priv {
struct work_struct bt_full_concurrency;
struct work_struct bt_runtime_config;
- struct tasklet_struct irq_tasklet;
-
struct delayed_work scan_check;
/* TX Power */
@@ -1500,12 +1073,6 @@ struct iwl_priv {
s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */
s8 tx_power_next;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- /* debugging info */
- u32 debug_level; /* per device debugging will override global
- iwl_debug_level if set */
-#endif /* CONFIG_IWLWIFI_DEBUG */
#ifdef CONFIG_IWLWIFI_DEBUGFS
/* debugfs */
u16 tx_traffic_idx;
@@ -1543,47 +1110,7 @@ struct iwl_priv {
bool have_rekey_data;
}; /*iwl_priv */
-static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
-{
- set_bit(txq_id, &priv->txq_ctx_active_msk);
-}
-
-static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
-{
- clear_bit(txq_id, &priv->txq_ctx_active_msk);
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-/*
- * iwl_get_debug_level: Return active debug level for device
- *
- * Using sysfs it is possible to set per device debug level. This debug
- * level will be used if set, otherwise the global debug level which can be
- * set via module parameter is used.
- */
-static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
-{
- if (priv->debug_level)
- return priv->debug_level;
- else
- return iwl_debug_level;
-}
-#else
-static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
-{
- return iwl_debug_level;
-}
-#endif
-
-
-static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv,
- int txq_id, int idx)
-{
- if (priv->txq[txq_id].txb[idx].skb)
- return (struct ieee80211_hdr *)priv->txq[txq_id].
- txb[idx].skb->data;
- return NULL;
-}
+extern struct iwl_mod_params iwlagn_mod_params;
static inline struct iwl_rxon_context *
iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
@@ -1596,7 +1123,7 @@ iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
#define for_each_context(priv, ctx) \
for (ctx = &priv->contexts[IWL_RXON_CTX_BSS]; \
ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \
- if (priv->valid_contexts & BIT(ctx->ctxid))
+ if (priv->shrd->valid_contexts & BIT(ctx->ctxid))
static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
{
@@ -1650,13 +1177,4 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch)
return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
}
-static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page)
-{
- __free_pages(page, priv->hw_params.rx_page_order);
-}
-
-static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page)
-{
- free_pages(page, priv->hw_params.rx_page_order);
-}
#endif /* __iwl_dev_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index 2c84ba95afca..8a51c5ccda1e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -29,6 +29,8 @@
#include <linux/tracepoint.h>
+struct iwl_priv;
+
#if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__)
#undef TRACE_EVENT
#define TRACE_EVENT(name, proto, ...) \
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 19d31a5e32e5..a4e43bd4a547 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -72,6 +72,7 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-debug.h"
+#include "iwl-agn.h"
#include "iwl-eeprom.h"
#include "iwl-io.h"
@@ -138,7 +139,7 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
/******************************************************************************
*
- * EEPROM related functions
+ * generic NVM functions
*
******************************************************************************/
@@ -155,11 +156,11 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv)
for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
/* Request semaphore */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
/* See if we got it */
- ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+ ret = iwl_poll_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
EEPROM_SEM_TIMEOUT);
@@ -176,14 +177,14 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv)
static void iwl_eeprom_release_semaphore(struct iwl_priv *priv)
{
- iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl_clear_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
}
static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
{
- u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
+ u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
int ret = 0;
IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp);
@@ -214,19 +215,106 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
return ret;
}
+u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
+{
+ if (!priv->eeprom)
+ return 0;
+ return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
+}
+
+int iwl_eeprom_check_version(struct iwl_priv *priv)
+{
+ u16 eeprom_ver;
+ u16 calib_ver;
+
+ eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+ calib_ver = iwlagn_eeprom_calib_version(priv);
+
+ if (eeprom_ver < priv->cfg->eeprom_ver ||
+ calib_ver < priv->cfg->eeprom_calib_ver)
+ goto err;
+
+ IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
+ eeprom_ver, calib_ver);
+
+ return 0;
+err:
+ IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
+ "CALIB=0x%x < 0x%x\n",
+ eeprom_ver, priv->cfg->eeprom_ver,
+ calib_ver, priv->cfg->eeprom_calib_ver);
+ return -EINVAL;
+
+}
+
+int iwl_eeprom_check_sku(struct iwl_priv *priv)
+{
+ u16 radio_cfg;
+
+ if (!priv->cfg->sku) {
+ /* not using sku overwrite */
+ priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
+ if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
+ !priv->cfg->ht_params) {
+ IWL_ERR(priv, "Invalid 11n configuration\n");
+ return -EINVAL;
+ }
+ }
+ if (!priv->cfg->sku) {
+ IWL_ERR(priv, "Invalid device sku\n");
+ return -EINVAL;
+ }
+
+ IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku);
+
+ if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
+ /* not using .cfg overwrite */
+ radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+ priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
+ priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
+ if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
+ IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n",
+ priv->cfg->valid_tx_ant,
+ priv->cfg->valid_rx_ant);
+ return -EINVAL;
+ }
+ IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n",
+ priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant);
+ }
+ /*
+ * for some special cases,
+ * EEPROM did not reflect the correct antenna setting
+ * so overwrite the valid tx/rx antenna from .cfg
+ */
+ return 0;
+}
+
+void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
+{
+ const u8 *addr = iwl_eeprom_query_addr(priv,
+ EEPROM_MAC_ADDRESS);
+ memcpy(mac, addr, ETH_ALEN);
+}
+
+/******************************************************************************
+ *
+ * OTP related functions
+ *
+******************************************************************************/
+
static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
{
- iwl_read32(priv, CSR_OTP_GP_REG);
+ iwl_read32(bus(priv), CSR_OTP_GP_REG);
if (mode == IWL_OTP_ACCESS_ABSOLUTE)
- iwl_clear_bit(priv, CSR_OTP_GP_REG,
+ iwl_clear_bit(bus(priv), CSR_OTP_GP_REG,
CSR_OTP_GP_REG_OTP_ACCESS_MODE);
else
- iwl_set_bit(priv, CSR_OTP_GP_REG,
+ iwl_set_bit(bus(priv), CSR_OTP_GP_REG,
CSR_OTP_GP_REG_OTP_ACCESS_MODE);
}
-static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)
+static int iwl_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)
{
u32 otpgp;
int nvm_type;
@@ -243,7 +331,7 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)
nvm_type = NVM_DEVICE_TYPE_EEPROM;
break;
default:
- otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+ otpgp = iwl_read32(bus(priv), CSR_OTP_GP_REG);
if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT)
nvm_type = NVM_DEVICE_TYPE_OTP;
else
@@ -258,22 +346,22 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
int ret;
/* Enable 40MHz radio clock */
- iwl_write32(priv, CSR_GP_CNTRL,
- iwl_read32(priv, CSR_GP_CNTRL) |
+ iwl_write32(bus(priv), CSR_GP_CNTRL,
+ iwl_read32(bus(priv), CSR_GP_CNTRL) |
CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* wait for clock to be ready */
- ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
+ ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
25000);
if (ret < 0)
IWL_ERR(priv, "Time out access OTP\n");
else {
- iwl_set_bits_prph(priv, APMG_PS_CTRL_REG,
+ iwl_set_bits_prph(bus(priv), APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
udelay(5);
- iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
+ iwl_clear_bits_prph(bus(priv), APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
/*
@@ -281,7 +369,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
* this is only applicable for HW with OTP shadow RAM
*/
if (priv->cfg->base_params->shadow_ram_support)
- iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG,
+ iwl_set_bit(bus(priv), CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED);
}
return ret;
@@ -293,9 +381,9 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat
u32 r;
u32 otpgp;
- iwl_write32(priv, CSR_EEPROM_REG,
+ iwl_write32(bus(priv), CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
- ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
+ ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK,
CSR_EEPROM_REG_READ_VALID_MSK,
IWL_EEPROM_ACCESS_TIMEOUT);
@@ -303,13 +391,13 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat
IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
return ret;
}
- r = iwl_read32(priv, CSR_EEPROM_REG);
+ r = iwl_read32(bus(priv), CSR_EEPROM_REG);
/* check for ECC errors: */
- otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+ otpgp = iwl_read32(bus(priv), CSR_OTP_GP_REG);
if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
/* stop in this case */
/* set the uncorrectable OTP ECC bit for acknowledgement */
- iwl_set_bit(priv, CSR_OTP_GP_REG,
+ iwl_set_bit(bus(priv), CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n");
return -EINVAL;
@@ -317,7 +405,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat
if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
/* continue in this case */
/* set the correctable OTP ECC bit for acknowledgement */
- iwl_set_bit(priv, CSR_OTP_GP_REG,
+ iwl_set_bit(bus(priv), CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
}
@@ -407,11 +495,152 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
return -EINVAL;
}
-u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
+/******************************************************************************
+ *
+ * Tx Power related functions
+ *
+******************************************************************************/
+/**
+ * iwl_get_max_txpower_avg - get the highest tx power from all chains.
+ * find the highest tx power from all chains for the channel
+ */
+static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
+ struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+ int element, s8 *max_txpower_in_half_dbm)
{
- if (!priv->eeprom)
- return 0;
- return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
+ s8 max_txpower_avg = 0; /* (dBm) */
+
+ /* Take the highest tx power from any valid chains */
+ if ((priv->cfg->valid_tx_ant & ANT_A) &&
+ (enhanced_txpower[element].chain_a_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].chain_a_max;
+ if ((priv->cfg->valid_tx_ant & ANT_B) &&
+ (enhanced_txpower[element].chain_b_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].chain_b_max;
+ if ((priv->cfg->valid_tx_ant & ANT_C) &&
+ (enhanced_txpower[element].chain_c_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].chain_c_max;
+ if (((priv->cfg->valid_tx_ant == ANT_AB) |
+ (priv->cfg->valid_tx_ant == ANT_BC) |
+ (priv->cfg->valid_tx_ant == ANT_AC)) &&
+ (enhanced_txpower[element].mimo2_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].mimo2_max;
+ if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
+ (enhanced_txpower[element].mimo3_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].mimo3_max;
+
+ /*
+ * max. tx power in EEPROM is in 1/2 dBm format
+ * convert from 1/2 dBm to dBm (round-up convert)
+ * but we also do not want to loss 1/2 dBm resolution which
+ * will impact performance
+ */
+ *max_txpower_in_half_dbm = max_txpower_avg;
+ return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
+}
+
+static void
+iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv,
+ struct iwl_eeprom_enhanced_txpwr *txp,
+ s8 max_txpower_avg)
+{
+ int ch_idx;
+ bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ;
+ enum ieee80211_band band;
+
+ band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ?
+ IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
+
+ for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) {
+ struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx];
+
+ /* update matching channel or from common data only */
+ if (txp->channel != 0 && ch_info->channel != txp->channel)
+ continue;
+
+ /* update matching band only */
+ if (band != ch_info->band)
+ continue;
+
+ if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) {
+ ch_info->max_power_avg = max_txpower_avg;
+ ch_info->curr_txpow = max_txpower_avg;
+ ch_info->scan_power = max_txpower_avg;
+ }
+
+ if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg)
+ ch_info->ht40_max_power_avg = max_txpower_avg;
+ }
+}
+
+#define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT)
+#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
+#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
+
+#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
+ ? # x " " : "")
+
+void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
+{
+ struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
+ int idx, entries;
+ __le16 *txp_len;
+ s8 max_txp_avg, max_txp_avg_halfdbm;
+
+ BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
+
+ /* the length is in 16-bit words, but we want entries */
+ txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
+ entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
+
+ txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
+
+ for (idx = 0; idx < entries; idx++) {
+ txp = &txp_array[idx];
+ /* skip invalid entries */
+ if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
+ continue;
+
+ IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n",
+ (txp->channel && (txp->flags &
+ IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ?
+ "Common " : (txp->channel) ?
+ "Channel" : "Common",
+ (txp->channel),
+ TXP_CHECK_AND_PRINT(VALID),
+ TXP_CHECK_AND_PRINT(BAND_52G),
+ TXP_CHECK_AND_PRINT(OFDM),
+ TXP_CHECK_AND_PRINT(40MHZ),
+ TXP_CHECK_AND_PRINT(HT_AP),
+ TXP_CHECK_AND_PRINT(RES1),
+ TXP_CHECK_AND_PRINT(RES2),
+ TXP_CHECK_AND_PRINT(COMMON_TYPE),
+ txp->flags);
+ IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x "
+ "chain_B: 0X%02x chain_C: 0X%02x\n",
+ txp->chain_a_max, txp->chain_b_max,
+ txp->chain_c_max);
+ IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x "
+ "MIMO3: 0x%02x High 20_on_40: 0x%02x "
+ "Low 20_on_40: 0x%02x\n",
+ txp->mimo2_max, txp->mimo3_max,
+ ((txp->delta_20_in_40 & 0xf0) >> 4),
+ (txp->delta_20_in_40 & 0x0f));
+
+ max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
+ &max_txp_avg_halfdbm);
+
+ /*
+ * Update the user limit values values to the highest
+ * power supported by any channel
+ */
+ if (max_txp_avg > priv->tx_power_user_lmt)
+ priv->tx_power_user_lmt = max_txp_avg;
+ if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm)
+ priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm;
+
+ iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
+ }
}
/**
@@ -424,14 +653,14 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
{
__le16 *e;
- u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
+ u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP);
int sz;
int ret;
u16 addr;
u16 validblockaddr = 0;
u16 cache_addr = 0;
- priv->nvm_device_type = iwlcore_get_nvm_type(priv, hw_rev);
+ priv->nvm_device_type = iwl_get_nvm_type(priv, hw_rev);
if (priv->nvm_device_type == -ENOENT)
return -ENOENT;
/* allocate eeprom */
@@ -469,11 +698,11 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
ret = -ENOENT;
goto done;
}
- iwl_write32(priv, CSR_EEPROM_GP,
- iwl_read32(priv, CSR_EEPROM_GP) &
+ iwl_write32(bus(priv), CSR_EEPROM_GP,
+ iwl_read32(bus(priv), CSR_EEPROM_GP) &
~CSR_EEPROM_GP_IF_OWNER_MSK);
- iwl_set_bit(priv, CSR_OTP_GP_REG,
+ iwl_set_bit(bus(priv), CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
/* traversing the linked list if no shadow ram supported */
@@ -498,10 +727,10 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
for (addr = 0; addr < sz; addr += sizeof(u16)) {
u32 r;
- iwl_write32(priv, CSR_EEPROM_REG,
+ iwl_write32(bus(priv), CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
- ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
+ ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK,
CSR_EEPROM_REG_READ_VALID_MSK,
IWL_EEPROM_ACCESS_TIMEOUT);
@@ -509,7 +738,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr);
goto done;
}
- r = iwl_read32(priv, CSR_EEPROM_REG);
+ r = iwl_read32(bus(priv), CSR_EEPROM_REG);
e[addr / 2] = cpu_to_le16(r >> 16);
}
}
@@ -670,8 +899,9 @@ int iwl_init_channel_map(struct iwl_priv *priv)
IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n",
priv->channel_count);
- priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
- priv->channel_count, GFP_KERNEL);
+ priv->channel_info = kcalloc(priv->channel_count,
+ sizeof(struct iwl_channel_info),
+ GFP_KERNEL);
if (!priv->channel_info) {
IWL_ERR(priv, "Could not allocate channel_info\n");
priv->channel_count = 0;
@@ -838,7 +1068,7 @@ void iwl_rf_config(struct iwl_priv *priv)
/* write radio config values to register */
if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) {
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
EEPROM_RF_CFG_DASH_MSK(radio_cfg));
@@ -850,7 +1080,7 @@ void iwl_rf_config(struct iwl_priv *priv)
WARN_ON(1);
/* set CSR_HW_CONFIG_REG for uCode use */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index e4bf8ac5e64e..c94747e7299e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -163,11 +163,19 @@ struct iwl_eeprom_enhanced_txpwr {
} __packed;
/* calibration */
+struct iwl_eeprom_calib_hdr {
+ u8 version;
+ u8 pa_type;
+ __le16 voltage;
+} __packed;
+
#define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
#define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL)
/* temperature */
-#define EEPROM_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
+#define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
+#define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL)
+
/* agn links */
#define EEPROM_LINK_HOST (2*0x64)
@@ -301,7 +309,6 @@ void iwl_eeprom_free(struct iwl_priv *priv);
int iwl_eeprom_check_version(struct iwl_priv *priv);
int iwl_eeprom_check_sku(struct iwl_priv *priv);
const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
-int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
int iwl_init_channel_map(struct iwl_priv *priv);
void iwl_free_channel_map(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index 0ad60b3c04db..5bede9d7f955 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -63,6 +63,8 @@
#ifndef __iwl_fh_h__
#define __iwl_fh_h__
+#include <linux/types.h>
+
/****************************/
/* Flow Handler Definitions */
/****************************/
@@ -266,8 +268,6 @@
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
-#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
-
/**
* Rx Shared Status Registers (RSSR)
*
@@ -422,10 +422,6 @@
#define RX_FREE_BUFFERS 64
#define RX_LOW_WATERMARK 8
-/* Size of one Rx buffer in host DRAM */
-#define IWL_RX_BUF_SIZE_4K (4 * 1024)
-#define IWL_RX_BUF_SIZE_8K (8 * 1024)
-
/**
* struct iwl_rb_status - reseve buffer status
* host memory mapped FH registers
@@ -508,4 +504,16 @@ struct iwl_tfd {
/* Keep Warm Size */
#define IWL_KW_SIZE 0x1000 /* 4k */
+/* Fixed (non-configurable) rx data from phy */
+
+/**
+ * struct iwlagn_schedq_bc_tbl scheduler byte count table
+ * base physical address provided by SCD_DRAM_BASE_ADDR
+ * @tfd_offset 0-12 - tx command byte count
+ * 12-16 - station index
+ */
+struct iwlagn_scd_bc_tbl {
+ __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
+} __packed;
+
#endif /* !__iwl_fh_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
deleted file mode 100644
index 9d91552d13c1..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * 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:
- * Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_helpers_h__
-#define __iwl_helpers_h__
-
-#include <linux/ctype.h>
-#include <net/mac80211.h>
-
-#include "iwl-io.h"
-
-#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
-
-
-static inline struct ieee80211_conf *ieee80211_get_hw_conf(
- struct ieee80211_hw *hw)
-{
- return &hw->conf;
-}
-
-/**
- * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl_queue_inc_wrap(int index, int n_bd)
-{
- return ++index & (n_bd - 1);
-}
-
-/**
- * iwl_queue_dec_wrap - decrement queue index, wrap back to end
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl_queue_dec_wrap(int index, int n_bd)
-{
- return --index & (n_bd - 1);
-}
-
-/*
- * we have 8 bits used like this:
- *
- * 7 6 5 4 3 2 1 0
- * | | | | | | | |
- * | | | | | | +-+-------- AC queue (0-3)
- * | | | | | |
- * | +-+-+-+-+------------ HW queue ID
- * |
- * +---------------------- unused
- */
-static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
-{
- BUG_ON(ac > 3); /* only have 2 bits */
- BUG_ON(hwq > 31); /* only use 5 bits */
-
- txq->swq_id = (hwq << 2) | ac;
-}
-
-static inline void iwl_wake_queue(struct iwl_priv *priv,
- struct iwl_tx_queue *txq)
-{
- u8 queue = txq->swq_id;
- u8 ac = queue & 3;
- u8 hwq = (queue >> 2) & 0x1f;
-
- if (test_and_clear_bit(hwq, priv->queue_stopped))
- if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0)
- ieee80211_wake_queue(priv->hw, ac);
-}
-
-static inline void iwl_stop_queue(struct iwl_priv *priv,
- struct iwl_tx_queue *txq)
-{
- u8 queue = txq->swq_id;
- u8 ac = queue & 3;
- u8 hwq = (queue >> 2) & 0x1f;
-
- if (!test_and_set_bit(hwq, priv->queue_stopped))
- if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0)
- ieee80211_stop_queue(priv->hw, ac);
-}
-
-static inline void iwl_wake_any_queue(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
-{
- u8 ac;
-
- for (ac = 0; ac < AC_NUM; ac++) {
- IWL_DEBUG_INFO(priv, "Queue Status: Q[%d] %s\n",
- ac, (atomic_read(&priv->queue_stop_count[ac]) > 0)
- ? "stopped" : "awake");
- iwl_wake_queue(priv, &priv->txq[ctx->ac_to_queue[ac]]);
- }
-}
-
-#ifdef ieee80211_stop_queue
-#undef ieee80211_stop_queue
-#endif
-
-#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
-
-#ifdef ieee80211_wake_queue
-#undef ieee80211_wake_queue
-#endif
-
-#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
-
-static inline void iwl_disable_interrupts(struct iwl_priv *priv)
-{
- clear_bit(STATUS_INT_ENABLED, &priv->status);
-
- /* disable interrupts from uCode/NIC to host */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
- /* acknowledge/clear/reset any interrupts still pending
- * from uCode or flow handler (Rx/Tx DMA) */
- iwl_write32(priv, CSR_INT, 0xffffffff);
- iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
- IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
-}
-
-static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
-{
- IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
- iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
-}
-
-static inline void iwl_enable_interrupts(struct iwl_priv *priv)
-{
- IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
- set_bit(STATUS_INT_ENABLED, &priv->status);
- iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
-}
-
-/**
- * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
- * @priv -- pointer to iwl_priv data structure
- * @tsf_bits -- number of bits need to shift for masking)
- */
-static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
- u16 tsf_bits)
-{
- return (1 << tsf_bits) - 1;
-}
-
-/**
- * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
- * @priv -- pointer to iwl_priv data structure
- * @tsf_bits -- number of bits need to shift for masking)
- */
-static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv,
- u16 tsf_bits)
-{
- return ((1 << (32 - tsf_bits)) - 1) << tsf_bits;
-}
-
-#endif /* __iwl_helpers_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index aa4a90674452..3ffa8e62b856 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -25,46 +25,50 @@
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
+#include <linux/delay.h>
+#include <linux/device.h>
#include "iwl-io.h"
+#include"iwl-csr.h"
+#include "iwl-debug.h"
#define IWL_POLL_INTERVAL 10 /* microseconds */
-static inline void __iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
+static inline void __iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask)
{
- iwl_write32(priv, reg, iwl_read32(priv, reg) | mask);
+ iwl_write32(bus, reg, iwl_read32(bus, reg) | mask);
}
-static inline void __iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
+static inline void __iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask)
{
- iwl_write32(priv, reg, iwl_read32(priv, reg) & ~mask);
+ iwl_write32(bus, reg, iwl_read32(bus, reg) & ~mask);
}
-void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
+void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask)
{
unsigned long flags;
- spin_lock_irqsave(&priv->reg_lock, flags);
- __iwl_set_bit(priv, reg, mask);
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ __iwl_set_bit(bus, reg, mask);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
}
-void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
+void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask)
{
unsigned long flags;
- spin_lock_irqsave(&priv->reg_lock, flags);
- __iwl_clear_bit(priv, reg, mask);
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ __iwl_clear_bit(bus, reg, mask);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
}
-int iwl_poll_bit(struct iwl_priv *priv, u32 addr,
+int iwl_poll_bit(struct iwl_bus *bus, u32 addr,
u32 bits, u32 mask, int timeout)
{
int t = 0;
do {
- if ((iwl_read32(priv, addr) & mask) == (bits & mask))
+ if ((iwl_read32(bus, addr) & mask) == (bits & mask))
return t;
udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL;
@@ -73,14 +77,14 @@ int iwl_poll_bit(struct iwl_priv *priv, u32 addr,
return -ETIMEDOUT;
}
-int iwl_grab_nic_access_silent(struct iwl_priv *priv)
+int iwl_grab_nic_access_silent(struct iwl_bus *bus)
{
int ret;
- lockdep_assert_held(&priv->reg_lock);
+ lockdep_assert_held(&bus->reg_lock);
/* this bit wakes up the NIC */
- __iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ __iwl_set_bit(bus, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/*
* These bits say the device is running, and should keep running for
@@ -101,70 +105,70 @@ int iwl_grab_nic_access_silent(struct iwl_priv *priv)
* 5000 series and later (including 1000 series) have non-volatile SRAM,
* and do not save/restore SRAM when power cycling.
*/
- ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
+ ret = iwl_poll_bit(bus, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
if (ret < 0) {
- iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
+ iwl_write32(bus, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
return -EIO;
}
return 0;
}
-int iwl_grab_nic_access(struct iwl_priv *priv)
+int iwl_grab_nic_access(struct iwl_bus *bus)
{
- int ret = iwl_grab_nic_access_silent(priv);
+ int ret = iwl_grab_nic_access_silent(bus);
if (ret) {
- u32 val = iwl_read32(priv, CSR_GP_CNTRL);
- IWL_ERR(priv,
+ u32 val = iwl_read32(bus, CSR_GP_CNTRL);
+ IWL_ERR(bus,
"MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val);
}
return ret;
}
-void iwl_release_nic_access(struct iwl_priv *priv)
+void iwl_release_nic_access(struct iwl_bus *bus)
{
- lockdep_assert_held(&priv->reg_lock);
- __iwl_clear_bit(priv, CSR_GP_CNTRL,
+ lockdep_assert_held(&bus->reg_lock);
+ __iwl_clear_bit(bus, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
}
-u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg)
+u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg)
{
u32 value;
unsigned long flags;
- spin_lock_irqsave(&priv->reg_lock, flags);
- iwl_grab_nic_access(priv);
- value = iwl_read32(priv, reg);
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ iwl_grab_nic_access(bus);
+ value = iwl_read32(bus(bus), reg);
+ iwl_release_nic_access(bus);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
return value;
}
-void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value)
+void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value)
{
unsigned long flags;
- spin_lock_irqsave(&priv->reg_lock, flags);
- if (!iwl_grab_nic_access(priv)) {
- iwl_write32(priv, reg, value);
- iwl_release_nic_access(priv);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ if (!iwl_grab_nic_access(bus)) {
+ iwl_write32(bus, reg, value);
+ iwl_release_nic_access(bus);
}
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
}
-int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask,
+int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask,
int timeout)
{
int t = 0;
do {
- if ((iwl_read_direct32(priv, addr) & mask) == mask)
+ if ((iwl_read_direct32(bus, addr) & mask) == mask)
return t;
udelay(IWL_POLL_INTERVAL);
t += IWL_POLL_INTERVAL;
@@ -173,122 +177,122 @@ int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask,
return -ETIMEDOUT;
}
-static inline u32 __iwl_read_prph(struct iwl_priv *priv, u32 reg)
+static inline u32 __iwl_read_prph(struct iwl_bus *bus, u32 reg)
{
- iwl_write32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+ iwl_write32(bus, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
rmb();
- return iwl_read32(priv, HBUS_TARG_PRPH_RDAT);
+ return iwl_read32(bus, HBUS_TARG_PRPH_RDAT);
}
-static inline void __iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val)
+static inline void __iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val)
{
- iwl_write32(priv, HBUS_TARG_PRPH_WADDR,
+ iwl_write32(bus, HBUS_TARG_PRPH_WADDR,
((addr & 0x0000FFFF) | (3 << 24)));
wmb();
- iwl_write32(priv, HBUS_TARG_PRPH_WDAT, val);
+ iwl_write32(bus, HBUS_TARG_PRPH_WDAT, val);
}
-u32 iwl_read_prph(struct iwl_priv *priv, u32 reg)
+u32 iwl_read_prph(struct iwl_bus *bus, u32 reg)
{
unsigned long flags;
u32 val;
- spin_lock_irqsave(&priv->reg_lock, flags);
- iwl_grab_nic_access(priv);
- val = __iwl_read_prph(priv, reg);
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ iwl_grab_nic_access(bus);
+ val = __iwl_read_prph(bus, reg);
+ iwl_release_nic_access(bus);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
return val;
}
-void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val)
+void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val)
{
unsigned long flags;
- spin_lock_irqsave(&priv->reg_lock, flags);
- if (!iwl_grab_nic_access(priv)) {
- __iwl_write_prph(priv, addr, val);
- iwl_release_nic_access(priv);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ if (!iwl_grab_nic_access(bus)) {
+ __iwl_write_prph(bus, addr, val);
+ iwl_release_nic_access(bus);
}
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
}
-void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
+void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask)
{
unsigned long flags;
- spin_lock_irqsave(&priv->reg_lock, flags);
- iwl_grab_nic_access(priv);
- __iwl_write_prph(priv, reg, __iwl_read_prph(priv, reg) | mask);
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ iwl_grab_nic_access(bus);
+ __iwl_write_prph(bus, reg, __iwl_read_prph(bus, reg) | mask);
+ iwl_release_nic_access(bus);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
}
-void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg,
+void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg,
u32 bits, u32 mask)
{
unsigned long flags;
- spin_lock_irqsave(&priv->reg_lock, flags);
- iwl_grab_nic_access(priv);
- __iwl_write_prph(priv, reg,
- (__iwl_read_prph(priv, reg) & mask) | bits);
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ iwl_grab_nic_access(bus);
+ __iwl_write_prph(bus, reg,
+ (__iwl_read_prph(bus, reg) & mask) | bits);
+ iwl_release_nic_access(bus);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
}
-void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
+void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask)
{
unsigned long flags;
u32 val;
- spin_lock_irqsave(&priv->reg_lock, flags);
- iwl_grab_nic_access(priv);
- val = __iwl_read_prph(priv, reg);
- __iwl_write_prph(priv, reg, (val & ~mask));
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ iwl_grab_nic_access(bus);
+ val = __iwl_read_prph(bus, reg);
+ __iwl_write_prph(bus, reg, (val & ~mask));
+ iwl_release_nic_access(bus);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
}
-void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr,
+void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr,
void *buf, int words)
{
unsigned long flags;
int offs;
u32 *vals = buf;
- spin_lock_irqsave(&priv->reg_lock, flags);
- iwl_grab_nic_access(priv);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ iwl_grab_nic_access(bus);
- iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr);
+ iwl_write32(bus, HBUS_TARG_MEM_RADDR, addr);
rmb();
for (offs = 0; offs < words; offs++)
- vals[offs] = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
+ vals[offs] = iwl_read32(bus, HBUS_TARG_MEM_RDAT);
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ iwl_release_nic_access(bus);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
}
-u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr)
+u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr)
{
u32 value;
- _iwl_read_targ_mem_words(priv, addr, &value, 1);
+ _iwl_read_targ_mem_words(bus, addr, &value, 1);
return value;
}
-void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
+void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val)
{
unsigned long flags;
- spin_lock_irqsave(&priv->reg_lock, flags);
- if (!iwl_grab_nic_access(priv)) {
- iwl_write32(priv, HBUS_TARG_MEM_WADDR, addr);
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ if (!iwl_grab_nic_access(bus)) {
+ iwl_write32(bus, HBUS_TARG_MEM_WADDR, addr);
wmb();
- iwl_write32(priv, HBUS_TARG_MEM_WDAT, val);
- iwl_release_nic_access(priv);
+ iwl_write32(bus, HBUS_TARG_MEM_WDAT, val);
+ iwl_release_nic_access(bus);
}
- spin_unlock_irqrestore(&priv->reg_lock, flags);
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 19a093101122..ced2cbeb6eae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -29,65 +29,62 @@
#ifndef __iwl_io_h__
#define __iwl_io_h__
-#include <linux/io.h>
-
-#include "iwl-dev.h"
-#include "iwl-debug.h"
#include "iwl-devtrace.h"
+#include "iwl-shared.h"
#include "iwl-bus.h"
-static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val)
+static inline void iwl_write8(struct iwl_bus *bus, u32 ofs, u8 val)
{
- trace_iwlwifi_dev_iowrite8(priv, ofs, val);
- bus_write8(priv->bus, ofs, val);
+ trace_iwlwifi_dev_iowrite8(priv(bus), ofs, val);
+ bus_write8(bus, ofs, val);
}
-static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val)
+static inline void iwl_write32(struct iwl_bus *bus, u32 ofs, u32 val)
{
- trace_iwlwifi_dev_iowrite32(priv, ofs, val);
- bus_write32(priv->bus, ofs, val);
+ trace_iwlwifi_dev_iowrite32(priv(bus), ofs, val);
+ bus_write32(bus, ofs, val);
}
-static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs)
+static inline u32 iwl_read32(struct iwl_bus *bus, u32 ofs)
{
- u32 val = bus_read32(priv->bus, ofs);
- trace_iwlwifi_dev_ioread32(priv, ofs, val);
+ u32 val = bus_read32(bus, ofs);
+ trace_iwlwifi_dev_ioread32(priv(bus), ofs, val);
return val;
}
-void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask);
-void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask);
+void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask);
+void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask);
-int iwl_poll_bit(struct iwl_priv *priv, u32 addr,
+int iwl_poll_bit(struct iwl_bus *bus, u32 addr,
u32 bits, u32 mask, int timeout);
-int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask,
+int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask,
int timeout);
-int iwl_grab_nic_access_silent(struct iwl_priv *priv);
-int iwl_grab_nic_access(struct iwl_priv *priv);
-void iwl_release_nic_access(struct iwl_priv *priv);
+int iwl_grab_nic_access_silent(struct iwl_bus *bus);
+int iwl_grab_nic_access(struct iwl_bus *bus);
+void iwl_release_nic_access(struct iwl_bus *bus);
-u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg);
-void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value);
+u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg);
+void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value);
-u32 iwl_read_prph(struct iwl_priv *priv, u32 reg);
-void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val);
-void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask);
-void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg,
+u32 iwl_read_prph(struct iwl_bus *bus, u32 reg);
+void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val);
+void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask);
+void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg,
u32 bits, u32 mask);
-void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask);
+void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask);
-void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr,
+void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr,
void *buf, int words);
-#define iwl_read_targ_mem_words(priv, addr, buf, bufsize) \
+#define iwl_read_targ_mem_words(bus, addr, buf, bufsize) \
do { \
BUILD_BUG_ON((bufsize) % sizeof(u32)); \
- _iwl_read_targ_mem_words(priv, addr, buf, \
+ _iwl_read_targ_mem_words(bus, addr, buf, \
(bufsize) / sizeof(u32));\
} while (0)
-u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr);
-void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val);
+u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr);
+void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val);
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index a67ae56d5464..eb541735296c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -31,7 +31,6 @@
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
@@ -41,6 +40,7 @@
#include "iwl-agn.h"
#include "iwl-io.h"
#include "iwl-trans.h"
+#include "iwl-shared.h"
/* Throughput OFF time(ms) ON time (ms)
* >300 25 25
@@ -71,7 +71,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = {
/* Set led register off */
void iwlagn_led_enable(struct iwl_priv *priv)
{
- iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
+ iwl_write32(bus(priv), CSR_LED_REG, CSR_LED_REG_TRUN_ON);
}
/*
@@ -104,15 +104,14 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
.len = { sizeof(struct iwl_led_cmd), },
.data = { led_cmd, },
.flags = CMD_ASYNC,
- .callback = NULL,
};
u32 reg;
- reg = iwl_read32(priv, CSR_LED_REG);
+ reg = iwl_read32(bus(priv), CSR_LED_REG);
if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
- iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
+ iwl_write32(bus(priv), CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
- return trans_send_cmd(&priv->trans, &cmd);
+ return iwl_trans_send_cmd(trans(priv), &cmd);
}
/* Set led pattern command */
@@ -126,7 +125,7 @@ static int iwl_led_cmd(struct iwl_priv *priv,
};
int ret;
- if (!test_bit(STATUS_READY, &priv->status))
+ if (!test_bit(STATUS_READY, &priv->shrd->status))
return -EBUSY;
if (priv->blink_on == on && priv->blink_off == off)
@@ -203,8 +202,7 @@ void iwl_leds_init(struct iwl_priv *priv)
break;
}
- ret = led_classdev_register(priv->bus->dev,
- &priv->led);
+ ret = led_classdev_register(bus(priv)->dev, &priv->led);
if (ret) {
kfree(priv->led.name);
return;
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c
index 2fdbffa079c1..3b6cc66365e5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-pci.c
+++ b/drivers/net/wireless/iwlwifi/iwl-pci.c
@@ -64,9 +64,11 @@
#include <linux/pci-aspm.h>
#include "iwl-bus.h"
-#include "iwl-agn.h"
-#include "iwl-core.h"
#include "iwl-io.h"
+#include "iwl-shared.h"
+#include "iwl-trans.h"
+#include "iwl-csr.h"
+#include "iwl-cfg.h"
/* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041
@@ -91,6 +93,7 @@ static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus)
{
int pos;
u16 pci_lnk_ctl;
+
struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
pos = pci_pcie_cap(pci_dev);
@@ -120,23 +123,17 @@ static void iwl_pci_apm_config(struct iwl_bus *bus)
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
PCI_CFG_LINK_CTRL_VAL_L1_EN) {
/* L1-ASPM enabled; disable(!) L0S */
- iwl_set_bit(bus->drv_data, CSR_GIO_REG,
+ iwl_set_bit(bus, CSR_GIO_REG,
CSR_GIO_REG_VAL_L0S_ENABLED);
dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n");
} else {
/* L1-ASPM disabled; enable(!) L0S */
- iwl_clear_bit(bus->drv_data, CSR_GIO_REG,
+ iwl_clear_bit(bus, CSR_GIO_REG,
CSR_GIO_REG_VAL_L0S_ENABLED);
dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n");
}
}
-static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_data)
-{
- bus->drv_data = drv_data;
- pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_data);
-}
-
static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[],
int buf_len)
{
@@ -162,10 +159,9 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs)
return val;
}
-static struct iwl_bus_ops pci_ops = {
+static const struct iwl_bus_ops bus_ops_pci = {
.get_pm_support = iwl_pci_is_pm_supported,
.apm_config = iwl_pci_apm_config,
- .set_drv_data = iwl_pci_set_drv_data,
.get_hw_id = iwl_pci_get_hw_id,
.write8 = iwl_pci_write8,
.write32 = iwl_pci_write32,
@@ -256,6 +252,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)},
+ {IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1341, iwl6005_2agn_d_cfg)},
/* 6x30 Series */
{IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
@@ -328,6 +327,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
{IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
{IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
+ {IWL_PCI_DEVICE(0x0890, 0x4822, iwl2000_2bgn_d_cfg)},
/* 2x30 Series */
{IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
@@ -355,6 +355,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)},
{IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)},
{IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0894, 0x0822, iwl105_bgn_d_cfg)},
/* 135 Series */
{IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
@@ -387,6 +388,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_bus = IWL_BUS_GET_PCI_BUS(bus);
pci_bus->pci_dev = pdev;
+ pci_set_drvdata(pdev, bus);
+
/* W/A - seems to solve weird behavior. We need to remove this if we
* don't want to stay in L1 all the time. This wastes a lot of power */
pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
@@ -457,9 +460,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
bus->dev = &pdev->dev;
bus->irq = pdev->irq;
- bus->ops = &pci_ops;
+ bus->ops = &bus_ops_pci;
- err = iwl_probe(bus, cfg);
+ err = iwl_probe(bus, &trans_ops_pcie, cfg);
if (err)
goto out_disable_msi;
return 0;
@@ -480,12 +483,12 @@ out_no_pci:
static void __devexit iwl_pci_remove(struct pci_dev *pdev)
{
- struct iwl_priv *priv = pci_get_drvdata(pdev);
- struct iwl_bus *bus = priv->bus;
+ struct iwl_bus *bus = pci_get_drvdata(pdev);
struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus);
struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+ struct iwl_shared *shrd = bus->shrd;
- iwl_remove(priv);
+ iwl_remove(shrd->priv);
pci_disable_msi(pci_dev);
pci_iounmap(pci_dev, pci_bus->hw_base);
@@ -496,25 +499,27 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
kfree(bus);
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int iwl_pci_suspend(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
- struct iwl_priv *priv = pci_get_drvdata(pdev);
+ struct iwl_bus *bus = pci_get_drvdata(pdev);
+ struct iwl_shared *shrd = bus->shrd;
/* Before you put code here, think about WoWLAN. You cannot check here
* whether WoWLAN is enabled or not, and your code will run even if
* WoWLAN is enabled - don't kill the NIC, someone may need it in Sx.
*/
- return iwl_suspend(priv);
+ return iwl_trans_suspend(shrd->trans);
}
static int iwl_pci_resume(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
- struct iwl_priv *priv = pci_get_drvdata(pdev);
+ struct iwl_bus *bus = pci_get_drvdata(pdev);
+ struct iwl_shared *shrd = bus->shrd;
/* Before you put code here, think about WoWLAN. You cannot check here
* whether WoWLAN is enabled or not, and your code will run even if
@@ -527,7 +532,7 @@ static int iwl_pci_resume(struct device *device)
*/
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
- return iwl_resume(priv);
+ return iwl_trans_resume(shrd->trans);
}
static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume);
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index cd64df05f9ed..4eaab204322d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -43,6 +43,7 @@
#include "iwl-debug.h"
#include "iwl-power.h"
#include "iwl-trans.h"
+#include "iwl-shared.h"
/*
* Setting power level allows the card to go to sleep when not busy.
@@ -214,7 +215,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
else
cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
- if (priv->cfg->base_params->shadow_reg_enable)
+ if (hw_params(priv).shadow_reg_enable)
cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
else
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
@@ -300,7 +301,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
if (priv->power_data.bus_pm)
cmd->flags |= IWL_POWER_PCI_PM_MSK;
- if (priv->cfg->base_params->shadow_reg_enable)
+ if (hw_params(priv).shadow_reg_enable)
cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
else
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
@@ -335,7 +336,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
le32_to_cpu(cmd->sleep_interval[3]),
le32_to_cpu(cmd->sleep_interval[4]));
- return trans_send_cmd_pdu(&priv->trans, POWER_TABLE_CMD, CMD_SYNC,
+ return iwl_trans_send_cmd_pdu(trans(priv), POWER_TABLE_CMD, CMD_SYNC,
sizeof(struct iwl_powertable_cmd), cmd);
}
@@ -347,7 +348,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
- if (priv->wowlan)
+ if (priv->shrd->wowlan)
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
else if (!priv->cfg->base_params->no_idle_support &&
priv->hw->conf.flags & IEEE80211_CONF_IDLE)
@@ -382,7 +383,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
int ret;
bool update_chains;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
/* Don't update the RX chain when chain noise calibration is running */
update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
@@ -391,23 +392,23 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
return 0;
- if (!iwl_is_ready_rf(priv))
+ if (!iwl_is_ready_rf(priv->shrd))
return -EIO;
/* scan complete use sleep_power_next, need to be updated */
memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
- if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
+ if (test_bit(STATUS_SCANNING, &priv->shrd->status) && !force) {
IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
return 0;
}
if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
- set_bit(STATUS_POWER_PMI, &priv->status);
+ set_bit(STATUS_POWER_PMI, &priv->shrd->status);
ret = iwl_set_power(priv, cmd);
if (!ret) {
if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
- clear_bit(STATUS_POWER_PMI, &priv->status);
+ clear_bit(STATUS_POWER_PMI, &priv->shrd->status);
if (update_chains)
iwl_update_chain_flags(priv);
@@ -435,7 +436,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
{
- priv->power_data.bus_pm = bus_get_pm_support(priv->bus);
+ priv->power_data.bus_pm = bus_get_pm_support(bus(priv));
priv->power_data.debug_sleep_level_override = -1;
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 2f267b8aabbb..bebdd828f324 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -217,8 +217,8 @@
((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
#define SCD_QUEUECHAIN_SEL_ALL(priv) \
- (((1<<(priv)->hw_params.max_txq_num) - 1) &\
- (~(1<<(priv)->cmd_queue)))
+ (((1<<hw_params(priv).max_txq_num) - 1) &\
+ (~(1<<(priv)->shrd->cmd_queue)))
#define SCD_BASE (PRPH_BASE + 0xa02c00)
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 77e528f5db88..e5d727f537d0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -33,9 +33,7 @@
#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-core.h"
-#include "iwl-sta.h"
#include "iwl-io.h"
-#include "iwl-helpers.h"
#include "iwl-agn.h"
#include "iwl-trans.h"
@@ -68,14 +66,14 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
/* Exit instantly with error when device is not ready
* to receive scan abort command or it does not perform
* hardware scan currently */
- if (!test_bit(STATUS_READY, &priv->status) ||
- !test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
- !test_bit(STATUS_SCAN_HW, &priv->status) ||
- test_bit(STATUS_FW_ERROR, &priv->status) ||
- test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (!test_bit(STATUS_READY, &priv->shrd->status) ||
+ !test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) ||
+ !test_bit(STATUS_SCAN_HW, &priv->shrd->status) ||
+ test_bit(STATUS_FW_ERROR, &priv->shrd->status) ||
+ test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
return -EIO;
- ret = trans_send_cmd(&priv->trans, &cmd);
+ ret = iwl_trans_send_cmd(trans(priv), &cmd);
if (ret)
return ret;
@@ -91,7 +89,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
ret = -EIO;
}
- iwl_free_pages(priv, cmd.reply_page);
+ iwl_free_pages(priv->shrd, cmd.reply_page);
return ret;
}
@@ -103,24 +101,90 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
ieee80211_scan_completed(priv->hw, aborted);
}
+ if (priv->scan_type == IWL_SCAN_ROC) {
+ ieee80211_remain_on_channel_expired(priv->hw);
+ priv->hw_roc_channel = NULL;
+ schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ);
+ }
+
priv->scan_type = IWL_SCAN_NORMAL;
priv->scan_vif = NULL;
priv->scan_request = NULL;
}
+static void iwl_process_scan_complete(struct iwl_priv *priv)
+{
+ bool aborted;
+
+ lockdep_assert_held(&priv->shrd->mutex);
+
+ if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status))
+ return;
+
+ IWL_DEBUG_SCAN(priv, "Completed scan.\n");
+
+ cancel_delayed_work(&priv->scan_check);
+
+ aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
+ if (aborted)
+ IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
+
+ if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) {
+ IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
+ goto out_settings;
+ }
+
+ if (priv->scan_type == IWL_SCAN_ROC) {
+ ieee80211_remain_on_channel_expired(priv->hw);
+ priv->hw_roc_channel = NULL;
+ schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ);
+ }
+
+ if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
+ int err;
+
+ /* Check if mac80211 requested scan during our internal scan */
+ if (priv->scan_request == NULL)
+ goto out_complete;
+
+ /* If so request a new scan */
+ err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL,
+ priv->scan_request->channels[0]->band);
+ if (err) {
+ IWL_DEBUG_SCAN(priv,
+ "failed to initiate pending scan: %d\n", err);
+ aborted = true;
+ goto out_complete;
+ }
+
+ return;
+ }
+
+out_complete:
+ iwl_complete_scan(priv, aborted);
+
+out_settings:
+ /* Can we still talk to firmware ? */
+ if (!iwl_is_ready_rf(priv->shrd))
+ return;
+
+ iwlagn_post_scan(priv);
+}
+
void iwl_force_scan_end(struct iwl_priv *priv)
{
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
- if (!test_bit(STATUS_SCANNING, &priv->status)) {
+ if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
return;
}
IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
- clear_bit(STATUS_SCANNING, &priv->status);
- clear_bit(STATUS_SCAN_HW, &priv->status);
- clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+ clear_bit(STATUS_SCANNING, &priv->shrd->status);
+ clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
+ clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
+ clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
iwl_complete_scan(priv, true);
}
@@ -128,14 +192,14 @@ static void iwl_do_scan_abort(struct iwl_priv *priv)
{
int ret;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
- if (!test_bit(STATUS_SCANNING, &priv->status)) {
+ if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
return;
}
- if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+ if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
return;
}
@@ -154,7 +218,7 @@ static void iwl_do_scan_abort(struct iwl_priv *priv)
int iwl_scan_cancel(struct iwl_priv *priv)
{
IWL_DEBUG_SCAN(priv, "Queuing abort scan\n");
- queue_work(priv->workqueue, &priv->abort_scan);
+ queue_work(priv->shrd->workqueue, &priv->abort_scan);
return 0;
}
@@ -163,28 +227,42 @@ int iwl_scan_cancel(struct iwl_priv *priv)
* @ms: amount of time to wait (in milliseconds) for scan to abort
*
*/
-int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
+void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
{
unsigned long timeout = jiffies + msecs_to_jiffies(ms);
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
iwl_do_scan_abort(priv);
while (time_before_eq(jiffies, timeout)) {
- if (!test_bit(STATUS_SCAN_HW, &priv->status))
- break;
+ if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status))
+ goto finished;
msleep(20);
}
- return test_bit(STATUS_SCAN_HW, &priv->status);
+ return;
+
+ finished:
+ /*
+ * Now STATUS_SCAN_HW is clear. This means that the
+ * device finished, but the background work is going
+ * to execute at best as soon as we release the mutex.
+ * Since we need to be able to issue a new scan right
+ * after this function returns, run the complete here.
+ * The STATUS_SCAN_COMPLETE bit will then be cleared
+ * and prevent the background work from "completing"
+ * a possible new scan.
+ */
+ iwl_process_scan_complete(priv);
}
/* Service response to REPLY_SCAN_CMD (0x80) */
-static void iwl_rx_reply_scan(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_reply_scan(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -193,11 +271,13 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,
IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
#endif
+ return 0;
}
/* Service SCAN_START_NOTIFICATION (0x82) */
-static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_scanstart_notification *notif =
@@ -211,11 +291,20 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
le32_to_cpu(notif->tsf_high),
le32_to_cpu(notif->tsf_low),
notif->status, notif->beacon_timer);
+
+ if (priv->scan_type == IWL_SCAN_ROC &&
+ !priv->hw_roc_start_notified) {
+ ieee80211_ready_on_channel(priv->hw);
+ priv->hw_roc_start_notified = true;
+ }
+
+ return 0;
}
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
-static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_scan_results_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -224,20 +313,24 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
IWL_DEBUG_SCAN(priv, "Scan ch.res: "
"%d [802.11%s] "
+ "probe status: %u:%u "
"(TSF: 0x%08X:%08X) - %d "
"elapsed=%lu usec\n",
notif->channel,
notif->band ? "bg" : "a",
+ notif->probe_status, notif->num_probe_not_sent,
le32_to_cpu(notif->tsf_high),
le32_to_cpu(notif->tsf_low),
le32_to_cpu(notif->statistics[0]),
le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
#endif
+ return 0;
}
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
-static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
@@ -247,14 +340,21 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
scan_notif->tsf_low,
scan_notif->tsf_high, scan_notif->status);
- /* The HW is no longer scanning */
- clear_bit(STATUS_SCAN_HW, &priv->status);
-
IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
(priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
jiffies_to_msecs(jiffies - priv->scan_start));
- queue_work(priv->workqueue, &priv->scan_completed);
+ /*
+ * When aborting, we run the scan completed background work inline
+ * and the background work must then do nothing. The SCAN_COMPLETE
+ * bit helps implement that logic and thus needs to be set before
+ * queueing the work. Also, since the scan abort waits for SCAN_HW
+ * to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW
+ * to avoid a race there.
+ */
+ set_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
+ clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
+ queue_work(priv->shrd->workqueue, &priv->scan_completed);
if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
iwl_advanced_bt_coexist(priv) &&
@@ -274,8 +374,10 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
IWL_BT_COEX_TRAFFIC_LOAD_NONE;
}
priv->bt_status = scan_notif->bt_status;
- queue_work(priv->workqueue, &priv->bt_traffic_change_work);
+ queue_work(priv->shrd->workqueue,
+ &priv->bt_traffic_change_work);
}
+ return 0;
}
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
@@ -289,9 +391,8 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
iwl_rx_scan_complete_notif;
}
-inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
- enum ieee80211_band band,
- u8 n_probes)
+static u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
+ enum ieee80211_band band, u8 n_probes)
{
if (band == IEEE80211_BAND_5GHZ)
return IWL_ACTIVE_DWELL_TIME_52 +
@@ -301,40 +402,486 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
}
-u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
- enum ieee80211_band band,
- struct ieee80211_vif *vif)
+static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time)
{
struct iwl_rxon_context *ctx;
+
+ /*
+ * If we're associated, we clamp the dwell time 98%
+ * of the smallest beacon interval (minus 2 * channel
+ * tune time)
+ */
+ for_each_context(priv, ctx) {
+ u16 value;
+
+ if (!iwl_is_associated_ctx(ctx))
+ continue;
+ value = ctx->beacon_int;
+ if (!value)
+ value = IWL_PASSIVE_DWELL_BASE;
+ value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
+ dwell_time = min(value, dwell_time);
+ }
+
+ return dwell_time;
+}
+
+static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
+ enum ieee80211_band band)
+{
u16 passive = (band == IEEE80211_BAND_2GHZ) ?
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
- if (iwl_is_any_associated(priv)) {
+ return iwl_limit_dwell(priv, passive);
+}
+
+static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
+ struct ieee80211_vif *vif,
+ enum ieee80211_band band,
+ struct iwl_scan_channel *scan_ch)
+{
+ const struct ieee80211_supported_band *sband;
+ u16 passive_dwell = 0;
+ u16 active_dwell = 0;
+ int added = 0;
+ u16 channel = 0;
+
+ sband = iwl_get_hw_mode(priv, band);
+ if (!sband) {
+ IWL_ERR(priv, "invalid band\n");
+ return added;
+ }
+
+ active_dwell = iwl_get_active_dwell_time(priv, band, 0);
+ passive_dwell = iwl_get_passive_dwell_time(priv, band);
+
+ if (passive_dwell <= active_dwell)
+ passive_dwell = active_dwell + 1;
+
+ channel = iwl_get_single_channel_number(priv, band);
+ if (channel) {
+ scan_ch->channel = cpu_to_le16(channel);
+ scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+ scan_ch->active_dwell = cpu_to_le16(active_dwell);
+ scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+ /* Set txpower levels to defaults */
+ scan_ch->dsp_atten = 110;
+ if (band == IEEE80211_BAND_5GHZ)
+ scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+ else
+ scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+ added++;
+ } else
+ IWL_ERR(priv, "no valid channel found\n");
+ return added;
+}
+
+static int iwl_get_channels_for_scan(struct iwl_priv *priv,
+ struct ieee80211_vif *vif,
+ enum ieee80211_band band,
+ u8 is_active, u8 n_probes,
+ struct iwl_scan_channel *scan_ch)
+{
+ struct ieee80211_channel *chan;
+ const struct ieee80211_supported_band *sband;
+ const struct iwl_channel_info *ch_info;
+ u16 passive_dwell = 0;
+ u16 active_dwell = 0;
+ int added, i;
+ u16 channel;
+
+ sband = iwl_get_hw_mode(priv, band);
+ if (!sband)
+ return 0;
+
+ active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
+ passive_dwell = iwl_get_passive_dwell_time(priv, band);
+
+ if (passive_dwell <= active_dwell)
+ passive_dwell = active_dwell + 1;
+
+ for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+ chan = priv->scan_request->channels[i];
+
+ if (chan->band != band)
+ continue;
+
+ channel = chan->hw_value;
+ scan_ch->channel = cpu_to_le16(channel);
+
+ ch_info = iwl_get_channel_info(priv, band, channel);
+ if (!is_channel_valid(ch_info)) {
+ IWL_DEBUG_SCAN(priv,
+ "Channel %d is INVALID for this band.\n",
+ channel);
+ continue;
+ }
+
+ if (!is_active || is_channel_passive(ch_info) ||
+ (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
+ scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+ else
+ scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
+
+ if (n_probes)
+ scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+
+ scan_ch->active_dwell = cpu_to_le16(active_dwell);
+ scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+
+ /* Set txpower levels to defaults */
+ scan_ch->dsp_atten = 110;
+
+ /* NOTE: if we were doing 6Mb OFDM for scans we'd use
+ * power level:
+ * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+ */
+ if (band == IEEE80211_BAND_5GHZ)
+ scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+ else
+ scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+
+ IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
+ channel, le32_to_cpu(scan_ch->type),
+ (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+ "ACTIVE" : "PASSIVE",
+ (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+ active_dwell : passive_dwell);
+
+ scan_ch++;
+ added++;
+ }
+
+ IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
+ return added;
+}
+
+static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+{
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_SCAN_CMD,
+ .len = { sizeof(struct iwl_scan_cmd), },
+ .flags = CMD_SYNC,
+ };
+ struct iwl_scan_cmd *scan;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ u32 rate_flags = 0;
+ u16 cmd_len;
+ u16 rx_chain = 0;
+ enum ieee80211_band band;
+ u8 n_probes = 0;
+ u8 rx_ant = hw_params(priv).valid_rx_ant;
+ u8 rate;
+ bool is_active = false;
+ int chan_mod;
+ u8 active_chains;
+ u8 scan_tx_antennas = hw_params(priv).valid_tx_ant;
+ int ret;
+
+ lockdep_assert_held(&priv->shrd->mutex);
+
+ if (vif)
+ ctx = iwl_rxon_ctx_from_vif(vif);
+
+ if (!priv->scan_cmd) {
+ priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
+ IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+ if (!priv->scan_cmd) {
+ IWL_DEBUG_SCAN(priv,
+ "fail to allocate memory for scan\n");
+ return -ENOMEM;
+ }
+ }
+ scan = priv->scan_cmd;
+ memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
+
+ scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
+ scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
+
+ if (priv->scan_type != IWL_SCAN_ROC &&
+ iwl_is_any_associated(priv)) {
+ u16 interval = 0;
+ u32 extra;
+ u32 suspend_time = 100;
+ u32 scan_suspend_time = 100;
+
+ IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
+ switch (priv->scan_type) {
+ case IWL_SCAN_ROC:
+ WARN_ON(1);
+ break;
+ case IWL_SCAN_RADIO_RESET:
+ interval = 0;
+ break;
+ case IWL_SCAN_NORMAL:
+ interval = vif->bss_conf.beacon_int;
+ break;
+ }
+
+ scan->suspend_time = 0;
+ scan->max_out_time = cpu_to_le32(200 * 1024);
+ if (!interval)
+ interval = suspend_time;
+
+ extra = (suspend_time / interval) << 22;
+ scan_suspend_time = (extra |
+ ((suspend_time % interval) * 1024));
+ scan->suspend_time = cpu_to_le32(scan_suspend_time);
+ IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
+ scan_suspend_time, interval);
+ } else if (priv->scan_type == IWL_SCAN_ROC) {
+ scan->suspend_time = 0;
+ scan->max_out_time = 0;
+ scan->quiet_time = 0;
+ scan->quiet_plcp_th = 0;
+ }
+
+ switch (priv->scan_type) {
+ case IWL_SCAN_RADIO_RESET:
+ IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
+ break;
+ case IWL_SCAN_NORMAL:
+ if (priv->scan_request->n_ssids) {
+ int i, p = 0;
+ IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+ for (i = 0; i < priv->scan_request->n_ssids; i++) {
+ /* always does wildcard anyway */
+ if (!priv->scan_request->ssids[i].ssid_len)
+ continue;
+ scan->direct_scan[p].id = WLAN_EID_SSID;
+ scan->direct_scan[p].len =
+ priv->scan_request->ssids[i].ssid_len;
+ memcpy(scan->direct_scan[p].ssid,
+ priv->scan_request->ssids[i].ssid,
+ priv->scan_request->ssids[i].ssid_len);
+ n_probes++;
+ p++;
+ }
+ is_active = true;
+ } else
+ IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
+ break;
+ case IWL_SCAN_ROC:
+ IWL_DEBUG_SCAN(priv, "Start ROC scan.\n");
+ break;
+ }
+
+ scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
+ scan->tx_cmd.sta_id = ctx->bcast_sta_id;
+ scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+ switch (priv->scan_band) {
+ case IEEE80211_BAND_2GHZ:
+ scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
+ chan_mod = le32_to_cpu(
+ priv->contexts[IWL_RXON_CTX_BSS].active.flags &
+ RXON_FLG_CHANNEL_MODE_MSK)
+ >> RXON_FLG_CHANNEL_MODE_POS;
+ if (chan_mod == CHANNEL_MODE_PURE_40) {
+ rate = IWL_RATE_6M_PLCP;
+ } else {
+ rate = IWL_RATE_1M_PLCP;
+ rate_flags = RATE_MCS_CCK_MSK;
+ }
/*
- * If we're associated, we clamp the maximum passive
- * dwell time to be 98% of the smallest beacon interval
- * (minus 2 * channel tune time)
+ * Internal scans are passive, so we can indiscriminately set
+ * the BT ignore flag on 2.4 GHz since it applies to TX only.
*/
- for_each_context(priv, ctx) {
- u16 value;
-
- if (!iwl_is_associated_ctx(ctx))
- continue;
- value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
- if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
- value = IWL_PASSIVE_DWELL_BASE;
- value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
- passive = min(value, passive);
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist)
+ scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
+ break;
+ case IEEE80211_BAND_5GHZ:
+ rate = IWL_RATE_6M_PLCP;
+ break;
+ default:
+ IWL_WARN(priv, "Invalid scan band\n");
+ return -EIO;
+ }
+
+ /*
+ * If active scanning is requested but a certain channel is
+ * marked passive, we can do active scanning if we detect
+ * transmissions.
+ *
+ * There is an issue with some firmware versions that triggers
+ * a sysassert on a "good CRC threshold" of zero (== disabled),
+ * on a radar channel even though this means that we should NOT
+ * send probes.
+ *
+ * The "good CRC threshold" is the number of frames that we
+ * need to receive during our dwell time on a channel before
+ * sending out probes -- setting this to a huge value will
+ * mean we never reach it, but at the same time work around
+ * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
+ * here instead of IWL_GOOD_CRC_TH_DISABLED.
+ *
+ * This was fixed in later versions along with some other
+ * scan changes, and the threshold behaves as a flag in those
+ * versions.
+ */
+ if (priv->new_scan_threshold_behaviour)
+ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+ IWL_GOOD_CRC_TH_DISABLED;
+ else
+ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+ IWL_GOOD_CRC_TH_NEVER;
+
+ band = priv->scan_band;
+
+ if (priv->cfg->scan_rx_antennas[band])
+ rx_ant = priv->cfg->scan_rx_antennas[band];
+
+ if (band == IEEE80211_BAND_2GHZ &&
+ priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist) {
+ /* transmit 2.4 GHz probes only on first antenna */
+ scan_tx_antennas = first_antenna(scan_tx_antennas);
+ }
+
+ priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv,
+ priv->scan_tx_ant[band],
+ scan_tx_antennas);
+ rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
+ scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
+
+ /* In power save mode use one chain, otherwise use all chains */
+ if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) {
+ /* rx_ant has been set to all valid chains previously */
+ active_chains = rx_ant &
+ ((u8)(priv->chain_noise_data.active_chains));
+ if (!active_chains)
+ active_chains = rx_ant;
+
+ IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
+ priv->chain_noise_data.active_chains);
+
+ rx_ant = first_antenna(active_chains);
+ }
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist &&
+ priv->bt_full_concurrent) {
+ /* operated as 1x1 in full concurrency mode */
+ rx_ant = first_antenna(rx_ant);
+ }
+
+ /* MIMO is not used here, but value is required */
+ rx_chain |=
+ hw_params(priv).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;
+ scan->rx_chain = cpu_to_le16(rx_chain);
+ switch (priv->scan_type) {
+ case IWL_SCAN_NORMAL:
+ cmd_len = iwl_fill_probe_req(priv,
+ (struct ieee80211_mgmt *)scan->data,
+ vif->addr,
+ priv->scan_request->ie,
+ priv->scan_request->ie_len,
+ IWL_MAX_SCAN_SIZE - sizeof(*scan));
+ break;
+ case IWL_SCAN_RADIO_RESET:
+ case IWL_SCAN_ROC:
+ /* use bcast addr, will not be transmitted but must be valid */
+ cmd_len = iwl_fill_probe_req(priv,
+ (struct ieee80211_mgmt *)scan->data,
+ iwl_bcast_addr, NULL, 0,
+ IWL_MAX_SCAN_SIZE - sizeof(*scan));
+ break;
+ default:
+ BUG();
+ }
+ scan->tx_cmd.len = cpu_to_le16(cmd_len);
+
+ scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
+ RXON_FILTER_BCON_AWARE_MSK);
+
+ switch (priv->scan_type) {
+ case IWL_SCAN_RADIO_RESET:
+ scan->channel_count =
+ iwl_get_single_channel_for_scan(priv, vif, band,
+ (void *)&scan->data[cmd_len]);
+ break;
+ case IWL_SCAN_NORMAL:
+ scan->channel_count =
+ iwl_get_channels_for_scan(priv, vif, band,
+ is_active, n_probes,
+ (void *)&scan->data[cmd_len]);
+ break;
+ case IWL_SCAN_ROC: {
+ struct iwl_scan_channel *scan_ch;
+ int n_chan, i;
+ u16 dwell;
+
+ dwell = iwl_limit_dwell(priv, priv->hw_roc_duration);
+ n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell);
+
+ scan->channel_count = n_chan;
+
+ scan_ch = (void *)&scan->data[cmd_len];
+
+ for (i = 0; i < n_chan; i++) {
+ scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+ scan_ch->channel =
+ cpu_to_le16(priv->hw_roc_channel->hw_value);
+
+ if (i == n_chan - 1)
+ dwell = priv->hw_roc_duration - i * dwell;
+
+ scan_ch->active_dwell =
+ scan_ch->passive_dwell = cpu_to_le16(dwell);
+
+ /* Set txpower levels to defaults */
+ scan_ch->dsp_atten = 110;
+
+ /* NOTE: if we were doing 6Mb OFDM for scans we'd use
+ * power level:
+ * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+ */
+ if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
+ scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+ else
+ scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+
+ scan_ch++;
}
+ }
+
+ break;
+ }
+
+ if (scan->channel_count == 0) {
+ IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
+ return -EIO;
+ }
+
+ cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) +
+ scan->channel_count * sizeof(struct iwl_scan_channel);
+ cmd.data[0] = scan;
+ cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
+ scan->len = cpu_to_le16(cmd.len[0]);
+
+ /* set scan bit here for PAN params */
+ set_bit(STATUS_SCAN_HW, &priv->shrd->status);
+
+ ret = iwlagn_set_pan_params(priv);
+ if (ret)
+ return ret;
+
+ ret = iwl_trans_send_cmd(trans(priv), &cmd);
+ if (ret) {
+ clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
+ iwlagn_set_pan_params(priv);
}
- return passive;
+ return ret;
}
void iwl_init_scan_params(struct iwl_priv *priv)
{
- u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
+ u8 ant_idx = fls(hw_params(priv).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])
@@ -348,50 +895,50 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
{
int ret;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&priv->shrd->mutex);
cancel_delayed_work(&priv->scan_check);
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl_is_ready_rf(priv->shrd)) {
IWL_WARN(priv, "Request scan called when driver not ready.\n");
return -EIO;
}
- if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+ if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv,
"Multiple concurrent scan requests in parallel.\n");
return -EBUSY;
}
- if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+ if (test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n");
return -EBUSY;
}
IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
scan_type == IWL_SCAN_NORMAL ? "" :
- scan_type == IWL_SCAN_OFFCH_TX ? "offchan TX " :
+ scan_type == IWL_SCAN_ROC ? "remain-on-channel " :
"internal short ");
- set_bit(STATUS_SCANNING, &priv->status);
+ set_bit(STATUS_SCANNING, &priv->shrd->status);
priv->scan_type = scan_type;
priv->scan_start = jiffies;
priv->scan_band = band;
ret = iwlagn_request_scan(priv, vif);
if (ret) {
- clear_bit(STATUS_SCANNING, &priv->status);
+ clear_bit(STATUS_SCANNING, &priv->shrd->status);
priv->scan_type = IWL_SCAN_NORMAL;
return ret;
}
- queue_delayed_work(priv->workqueue, &priv->scan_check,
+ queue_delayed_work(priv->shrd->workqueue, &priv->scan_check,
IWL_SCAN_CHECK_WATCHDOG);
return 0;
}
-int iwl_mac_hw_scan(struct ieee80211_hw *hw,
+int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req)
{
@@ -403,7 +950,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
if (req->n_channels == 0)
return -EINVAL;
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
/*
* If an internal scan is in progress, just set
@@ -432,7 +979,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n");
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
return ret;
}
@@ -443,7 +990,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
*/
void iwl_internal_short_hw_scan(struct iwl_priv *priv)
{
- queue_work(priv->workqueue, &priv->start_internal_scan);
+ queue_work(priv->shrd->workqueue, &priv->start_internal_scan);
}
static void iwl_bg_start_internal_scan(struct work_struct *work)
@@ -453,14 +1000,14 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
IWL_DEBUG_SCAN(priv, "Start internal scan\n");
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
if (priv->scan_type == IWL_SCAN_RADIO_RESET) {
IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
goto unlock;
}
- if (test_bit(STATUS_SCANNING, &priv->status)) {
+ if (test_bit(STATUS_SCANNING, &priv->shrd->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
goto unlock;
}
@@ -468,7 +1015,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band))
IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
unlock:
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
static void iwl_bg_scan_check(struct work_struct *data)
@@ -481,9 +1028,9 @@ static void iwl_bg_scan_check(struct work_struct *data)
/* Since we are here firmware does not finish scan and
* most likely is in bad shape, so we don't bother to
* send abort command, just force scan complete to mac80211 */
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
iwl_force_scan_end(priv);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
/**
@@ -541,70 +1088,19 @@ static void iwl_bg_abort_scan(struct work_struct *work)
/* We keep scan_check work queued in case when firmware will not
* report back scan completed notification */
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
iwl_scan_cancel_timeout(priv, 200);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
static void iwl_bg_scan_completed(struct work_struct *work)
{
struct iwl_priv *priv =
- container_of(work, struct iwl_priv, scan_completed);
- bool aborted;
-
- IWL_DEBUG_SCAN(priv, "Completed scan.\n");
-
- cancel_delayed_work(&priv->scan_check);
-
- mutex_lock(&priv->mutex);
-
- aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status);
- if (aborted)
- IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
-
- if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
- goto out_settings;
- }
-
- if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->offchan_tx_skb) {
- ieee80211_tx_status_irqsafe(priv->hw,
- priv->offchan_tx_skb);
- priv->offchan_tx_skb = NULL;
- }
-
- if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
- int err;
-
- /* Check if mac80211 requested scan during our internal scan */
- if (priv->scan_request == NULL)
- goto out_complete;
-
- /* If so request a new scan */
- err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL,
- priv->scan_request->channels[0]->band);
- if (err) {
- IWL_DEBUG_SCAN(priv,
- "failed to initiate pending scan: %d\n", err);
- aborted = true;
- goto out_complete;
- }
-
- goto out;
- }
-
-out_complete:
- iwl_complete_scan(priv, aborted);
-
-out_settings:
- /* Can we still talk to firmware ? */
- if (!iwl_is_ready_rf(priv))
- goto out;
-
- iwlagn_post_scan(priv);
+ container_of(work, struct iwl_priv, scan_completed);
-out:
- mutex_unlock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
+ iwl_process_scan_complete(priv);
+ mutex_unlock(&priv->shrd->mutex);
}
void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
@@ -622,8 +1118,8 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->scan_completed);
if (cancel_delayed_work_sync(&priv->scan_check)) {
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
iwl_force_scan_end(priv);
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
}
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h
new file mode 100644
index 000000000000..1f7a93c67c45
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-shared.h
@@ -0,0 +1,534 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_shared_h__
+#define __iwl_shared_h__
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/gfp.h>
+#include <linux/mm.h> /* for page_address */
+#include <net/mac80211.h>
+
+#include "iwl-commands.h"
+
+/**
+ * DOC: shared area - role and goal
+ *
+ * The shared area contains all the data exported by the upper layer to the
+ * other layers. Since the bus and transport layer shouldn't dereference
+ * iwl_priv, all the data needed by the upper layer and the transport / bus
+ * layer must be here.
+ * The shared area also holds pointer to all the other layers. This allows a
+ * layer to call a function from another layer.
+ *
+ * NOTE: All the layers hold a pointer to the shared area which must be shrd.
+ * A few macros assume that (_m)->shrd points to the shared area no matter
+ * what _m is.
+ *
+ * gets notifications about enumeration, suspend, resume.
+ * For the moment, the bus layer is not a linux kernel module as itself, and
+ * the module_init function of the driver must call the bus specific
+ * registration functions. These functions are listed at the end of this file.
+ * For the moment, there is only one implementation of this interface: PCI-e.
+ * This implementation is iwl-pci.c
+ */
+
+struct iwl_cfg;
+struct iwl_bus;
+struct iwl_priv;
+struct iwl_sensitivity_ranges;
+struct iwl_trans_ops;
+
+#define DRV_NAME "iwlwifi"
+#define IWLWIFI_VERSION "in-tree:"
+#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation"
+#define DRV_AUTHOR "<ilw@linux.intel.com>"
+
+extern struct iwl_mod_params iwlagn_mod_params;
+
+/**
+ * struct iwl_mod_params
+ *
+ * Holds the module parameters
+ *
+ * @sw_crypto: using hardware encryption, default = 0
+ * @num_of_queues: number of tx queue, HW dependent
+ * @disable_11n: 11n capabilities enabled, default = 0
+ * @amsdu_size_8K: enable 8K amsdu size, default = 1
+ * @antenna: both antennas (use diversity), default = 0
+ * @restart_fw: restart firmware, default = 1
+ * @plcp_check: enable plcp health check, default = true
+ * @ack_check: disable ack health check, default = false
+ * @wd_disable: enable stuck queue check, default = false
+ * @bt_coex_active: enable bt coex, default = true
+ * @led_mode: system default, default = 0
+ * @no_sleep_autoadjust: disable autoadjust, default = true
+ * @power_save: disable power save, default = false
+ * @power_level: power level, default = 1
+ * @debug_level: levels are IWL_DL_*
+ * @ant_coupling: antenna coupling in dB, default = 0
+ * @bt_ch_announce: BT channel inhibition, default = enable
+ * @wanted_ucode_alternative: ucode alternative to use, default = 1
+ * @auto_agg: enable agg. without check, default = true
+ */
+struct iwl_mod_params {
+ int sw_crypto;
+ int num_of_queues;
+ int disable_11n;
+ int amsdu_size_8K;
+ int antenna;
+ int restart_fw;
+ bool plcp_check;
+ bool ack_check;
+ bool wd_disable;
+ bool bt_coex_active;
+ int led_mode;
+ bool no_sleep_autoadjust;
+ bool power_save;
+ int power_level;
+ u32 debug_level;
+ int ant_coupling;
+ bool bt_ch_announce;
+ int wanted_ucode_alternative;
+ bool auto_agg;
+};
+
+/**
+ * struct iwl_hw_params
+ *
+ * Holds the module parameters
+ *
+ * @max_txq_num: Max # Tx queues supported
+ * @num_ampdu_queues: num of ampdu queues
+ * @tx_chains_num: Number of TX chains
+ * @rx_chains_num: Number of RX chains
+ * @valid_tx_ant: usable antennas for TX
+ * @valid_rx_ant: usable antennas for RX
+ * @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX)
+ * @sku: sku read from EEPROM
+ * @rx_page_order: Rx buffer page order
+ * @max_inst_size: for ucode use
+ * @max_data_size: for ucode use
+ * @ct_kill_threshold: temperature threshold - in hw dependent unit
+ * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit
+ * relevant for 1000, 6000 and up
+ * @wd_timeout: TX queues watchdog timeout
+ * @calib_init_cfg: setup initial calibrations for the hw
+ * @calib_rt_cfg: setup runtime calibrations for the hw
+ * @struct iwl_sensitivity_ranges: range of sensitivity values
+ */
+struct iwl_hw_params {
+ u8 max_txq_num;
+ u8 num_ampdu_queues;
+ u8 tx_chains_num;
+ u8 rx_chains_num;
+ u8 valid_tx_ant;
+ u8 valid_rx_ant;
+ u8 ht40_channel;
+ bool shadow_reg_enable;
+ u16 sku;
+ u32 rx_page_order;
+ u32 max_inst_size;
+ u32 max_data_size;
+ u32 ct_kill_threshold;
+ u32 ct_kill_exit_threshold;
+ unsigned int wd_timeout;
+
+ u32 calib_init_cfg;
+ u32 calib_rt_cfg;
+ const struct iwl_sensitivity_ranges *sens;
+};
+
+/**
+ * enum iwl_agg_state
+ *
+ * The state machine of the BA agreement establishment / tear down.
+ * These states relate to a specific RA / TID.
+ *
+ * @IWL_AGG_OFF: aggregation is not used
+ * @IWL_AGG_ON: aggregation session is up
+ * @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
+ * HW queue to be empty from packets for this RA /TID.
+ * @IWL_EMPTYING_HW_QUEUE_DELBA: tearing down a BA session - waiting for the
+ * HW queue to be empty from packets for this RA /TID.
+ */
+enum iwl_agg_state {
+ IWL_AGG_OFF = 0,
+ IWL_AGG_ON,
+ IWL_EMPTYING_HW_QUEUE_ADDBA,
+ IWL_EMPTYING_HW_QUEUE_DELBA,
+};
+
+/**
+ * struct iwl_ht_agg - aggregation state machine
+
+ * This structs holds the states for the BA agreement establishment and tear
+ * down. It also holds the state during the BA session itself. This struct is
+ * duplicated for each RA / TID.
+
+ * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
+ * Tx response (REPLY_TX), and the block ack notification
+ * (REPLY_COMPRESSED_BA).
+ * @state: state of the BA agreement establishment / tear down.
+ * @txq_id: Tx queue used by the BA session - used by the transport layer.
+ * Needed by the upper layer for debugfs only.
+ * @wait_for_ba: Expect block-ack before next Tx reply
+ */
+struct iwl_ht_agg {
+ u32 rate_n_flags;
+ enum iwl_agg_state state;
+ u16 txq_id;
+ bool wait_for_ba;
+};
+
+/**
+ * struct iwl_tid_data - one for each RA / TID
+
+ * This structs holds the states for each RA / TID.
+
+ * @seq_number: the next WiFi sequence number to use
+ * @tfds_in_queue: number of packets sent to the HW queues.
+ * Exported for debugfs only
+ * @agg: aggregation state machine
+ */
+struct iwl_tid_data {
+ u16 seq_number;
+ u16 tfds_in_queue;
+ struct iwl_ht_agg agg;
+};
+
+/**
+ * struct iwl_shared - shared fields for all the layers of the driver
+ *
+ * @dbg_level_dev: dbg level set per device. Prevails on
+ * iwlagn_mod_params.debug_level if set (!= 0)
+ * @ucode_owner: IWL_OWNERSHIP_*
+ * @cmd_queue: command queue number
+ * @status: STATUS_*
+ * @valid_contexts: microcode/device supports multiple contexts
+ * @bus: pointer to the bus layer data
+ * @priv: pointer to the upper layer data
+ * @hw_params: see struct iwl_hw_params
+ * @workqueue: the workqueue used by all the layers of the driver
+ * @lock: protect general shared data
+ * @sta_lock: protects the station table.
+ * If lock and sta_lock are needed, lock must be acquired first.
+ * @mutex:
+ */
+struct iwl_shared {
+#ifdef CONFIG_IWLWIFI_DEBUG
+ u32 dbg_level_dev;
+#endif /* CONFIG_IWLWIFI_DEBUG */
+
+#define IWL_OWNERSHIP_DRIVER 0
+#define IWL_OWNERSHIP_TM 1
+ u8 ucode_owner;
+ u8 cmd_queue;
+ unsigned long status;
+ bool wowlan;
+ u8 valid_contexts;
+
+ struct iwl_bus *bus;
+ struct iwl_priv *priv;
+ struct iwl_trans *trans;
+ struct iwl_hw_params hw_params;
+
+ struct workqueue_struct *workqueue;
+ spinlock_t lock;
+ spinlock_t sta_lock;
+ struct mutex mutex;
+
+ struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
+
+ wait_queue_head_t wait_command_queue;
+};
+
+/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
+#define priv(_m) ((_m)->shrd->priv)
+#define bus(_m) ((_m)->shrd->bus)
+#define trans(_m) ((_m)->shrd->trans)
+#define hw_params(_m) ((_m)->shrd->hw_params)
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+/*
+ * iwl_get_debug_level: Return active debug level for device
+ *
+ * Using sysfs it is possible to set per device debug level. This debug
+ * level will be used if set, otherwise the global debug level which can be
+ * set via module parameter is used.
+ */
+static inline u32 iwl_get_debug_level(struct iwl_shared *shrd)
+{
+ if (shrd->dbg_level_dev)
+ return shrd->dbg_level_dev;
+ else
+ return iwlagn_mod_params.debug_level;
+}
+#else
+static inline u32 iwl_get_debug_level(struct iwl_shared *shrd)
+{
+ return iwlagn_mod_params.debug_level;
+}
+#endif
+
+static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page)
+{
+ free_pages(page, shrd->hw_params.rx_page_order);
+}
+
+/**
+ * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_queue_inc_wrap(int index, int n_bd)
+{
+ return ++index & (n_bd - 1);
+}
+
+/**
+ * iwl_queue_dec_wrap - decrement queue index, wrap back to end
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_queue_dec_wrap(int index, int n_bd)
+{
+ return --index & (n_bd - 1);
+}
+
+struct iwl_rx_mem_buffer {
+ dma_addr_t page_dma;
+ struct page *page;
+ struct list_head list;
+};
+
+#define rxb_addr(r) page_address(r->page)
+
+/*
+ * mac80211 queues, ACs, hardware queues, FIFOs.
+ *
+ * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
+ *
+ * Mac80211 uses the following numbers, which we get as from it
+ * by way of skb_get_queue_mapping(skb):
+ *
+ * VO 0
+ * VI 1
+ * BE 2
+ * BK 3
+ *
+ *
+ * Regular (not A-MPDU) frames are put into hardware queues corresponding
+ * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
+ * own queue per aggregation session (RA/TID combination), such queues are
+ * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
+ * order to map frames to the right queue, we also need an AC->hw queue
+ * mapping. This is implemented here.
+ *
+ * Due to the way hw queues are set up (by the hw specific modules like
+ * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity
+ * mapping.
+ */
+
+static const u8 tid_to_ac[] = {
+ IEEE80211_AC_BE,
+ IEEE80211_AC_BK,
+ IEEE80211_AC_BK,
+ IEEE80211_AC_BE,
+ IEEE80211_AC_VI,
+ IEEE80211_AC_VI,
+ IEEE80211_AC_VO,
+ IEEE80211_AC_VO
+};
+
+static inline int get_ac_from_tid(u16 tid)
+{
+ if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+ return tid_to_ac[tid];
+
+ /* no support for TIDs 8-15 yet */
+ return -EINVAL;
+}
+
+enum iwl_rxon_context_id {
+ IWL_RXON_CTX_BSS,
+ IWL_RXON_CTX_PAN,
+
+ NUM_IWL_RXON_CTX
+};
+
+int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
+ struct iwl_cfg *cfg);
+void __devexit iwl_remove(struct iwl_priv * priv);
+struct iwl_device_cmd;
+int __must_check iwl_rx_dispatch(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd);
+
+int iwlagn_hw_valid_rtc_data_addr(u32 addr);
+void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
+ enum iwl_rxon_context_id ctx,
+ u8 sta_id, u8 tid);
+void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
+ enum iwl_rxon_context_id ctx,
+ u8 sta_id, u8 tid);
+void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state);
+void iwl_nic_config(struct iwl_priv *priv);
+void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb);
+void iwl_apm_stop(struct iwl_priv *priv);
+int iwl_apm_init(struct iwl_priv *priv);
+void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand);
+const char *get_cmd_string(u8 cmd);
+bool iwl_check_for_ct_kill(struct iwl_priv *priv);
+
+void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac);
+void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+void iwl_reset_traffic_log(struct iwl_priv *priv);
+#endif /* CONFIG_IWLWIFI_DEBUGFS */
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+ enum iwl_rxon_context_id ctxid);
+#else
+static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+ enum iwl_rxon_context_id ctxid)
+{
+}
+#endif
+
+#define IWL_CMD(x) case x: return #x
+#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
+
+#define IWL_TRAFFIC_ENTRIES (256)
+#define IWL_TRAFFIC_ENTRY_SIZE (64)
+
+/*****************************************************
+* DRIVER STATUS FUNCTIONS
+******************************************************/
+#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
+/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
+#define STATUS_INT_ENABLED 2
+#define STATUS_RF_KILL_HW 3
+#define STATUS_CT_KILL 4
+#define STATUS_INIT 5
+#define STATUS_ALIVE 6
+#define STATUS_READY 7
+#define STATUS_TEMPERATURE 8
+#define STATUS_GEO_CONFIGURED 9
+#define STATUS_EXIT_PENDING 10
+#define STATUS_STATISTICS 12
+#define STATUS_SCANNING 13
+#define STATUS_SCAN_ABORTING 14
+#define STATUS_SCAN_HW 15
+#define STATUS_POWER_PMI 16
+#define STATUS_FW_ERROR 17
+#define STATUS_DEVICE_ENABLED 18
+#define STATUS_CHANNEL_SWITCH_PENDING 19
+#define STATUS_SCAN_COMPLETE 20
+
+static inline int iwl_is_ready(struct iwl_shared *shrd)
+{
+ /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
+ * set but EXIT_PENDING is not */
+ return test_bit(STATUS_READY, &shrd->status) &&
+ test_bit(STATUS_GEO_CONFIGURED, &shrd->status) &&
+ !test_bit(STATUS_EXIT_PENDING, &shrd->status);
+}
+
+static inline int iwl_is_alive(struct iwl_shared *shrd)
+{
+ return test_bit(STATUS_ALIVE, &shrd->status);
+}
+
+static inline int iwl_is_init(struct iwl_shared *shrd)
+{
+ return test_bit(STATUS_INIT, &shrd->status);
+}
+
+static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd)
+{
+ return test_bit(STATUS_RF_KILL_HW, &shrd->status);
+}
+
+static inline int iwl_is_rfkill(struct iwl_shared *shrd)
+{
+ return iwl_is_rfkill_hw(shrd);
+}
+
+static inline int iwl_is_ctkill(struct iwl_shared *shrd)
+{
+ return test_bit(STATUS_CT_KILL, &shrd->status);
+}
+
+static inline int iwl_is_ready_rf(struct iwl_shared *shrd)
+{
+ if (iwl_is_rfkill(shrd))
+ return 0;
+
+ return iwl_is_ready(shrd);
+}
+
+#endif /* #__iwl_shared_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
deleted file mode 100644
index 1ef3b7106ad5..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ /dev/null
@@ -1,832 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * 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:
- * Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <net/mac80211.h>
-#include <linux/etherdevice.h>
-#include <linux/sched.h>
-#include <linux/lockdep.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-sta.h"
-#include "iwl-trans.h"
-#include "iwl-agn.h"
-
-/* priv->sta_lock must be held */
-static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
-{
-
- if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
- IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u addr %pM\n",
- sta_id, priv->stations[sta_id].sta.sta.addr);
-
- if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) {
- IWL_DEBUG_ASSOC(priv,
- "STA id %u addr %pM already present in uCode (according to driver)\n",
- sta_id, priv->stations[sta_id].sta.sta.addr);
- } else {
- priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
- IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n",
- sta_id, priv->stations[sta_id].sta.sta.addr);
- }
-}
-
-static int iwl_process_add_sta_resp(struct iwl_priv *priv,
- struct iwl_addsta_cmd *addsta,
- struct iwl_rx_packet *pkt,
- bool sync)
-{
- u8 sta_id = addsta->sta.sta_id;
- unsigned long flags;
- int ret = -EIO;
-
- if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
- pkt->hdr.flags);
- return ret;
- }
-
- IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
- sta_id);
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- switch (pkt->u.add_sta.status) {
- case ADD_STA_SUCCESS_MSK:
- IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
- iwl_sta_ucode_activate(priv, sta_id);
- ret = 0;
- break;
- case ADD_STA_NO_ROOM_IN_TABLE:
- IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
- sta_id);
- break;
- case ADD_STA_NO_BLOCK_ACK_RESOURCE:
- IWL_ERR(priv, "Adding station %d failed, no block ack resource.\n",
- sta_id);
- break;
- case ADD_STA_MODIFY_NON_EXIST_STA:
- IWL_ERR(priv, "Attempting to modify non-existing station %d\n",
- sta_id);
- break;
- default:
- IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
- pkt->u.add_sta.status);
- break;
- }
-
- IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n",
- priv->stations[sta_id].sta.mode ==
- STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
- sta_id, priv->stations[sta_id].sta.sta.addr);
-
- /*
- * XXX: The MAC address in the command buffer is often changed from
- * the original sent to the device. That is, the MAC address
- * written to the command buffer often is not the same MAC address
- * read from the command buffer when the command returns. This
- * issue has not yet been resolved and this debugging is left to
- * observe the problem.
- */
- IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n",
- priv->stations[sta_id].sta.mode ==
- STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
- addsta->sta.addr);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return ret;
-}
-
-static void iwl_add_sta_callback(struct iwl_priv *priv,
- struct iwl_device_cmd *cmd,
- struct iwl_rx_packet *pkt)
-{
- struct iwl_addsta_cmd *addsta =
- (struct iwl_addsta_cmd *)cmd->cmd.payload;
-
- iwl_process_add_sta_resp(priv, addsta, pkt, false);
-
-}
-
-static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
-{
- u16 size = (u16)sizeof(struct iwl_addsta_cmd);
- struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
- memcpy(addsta, cmd, size);
- /* resrved in 5000 */
- addsta->rate_n_flags = cpu_to_le16(0);
- return size;
-}
-
-int iwl_send_add_sta(struct iwl_priv *priv,
- struct iwl_addsta_cmd *sta, u8 flags)
-{
- struct iwl_rx_packet *pkt = NULL;
- int ret = 0;
- u8 data[sizeof(*sta)];
- struct iwl_host_cmd cmd = {
- .id = REPLY_ADD_STA,
- .flags = flags,
- .data = { data, },
- };
- u8 sta_id __maybe_unused = sta->sta.sta_id;
-
- IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n",
- sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : "");
-
- if (flags & CMD_ASYNC)
- cmd.callback = iwl_add_sta_callback;
- else {
- cmd.flags |= CMD_WANT_SKB;
- might_sleep();
- }
-
- cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data);
- ret = trans_send_cmd(&priv->trans, &cmd);
-
- if (ret || (flags & CMD_ASYNC))
- return ret;
-
- if (ret == 0) {
- pkt = (struct iwl_rx_packet *)cmd.reply_page;
- ret = iwl_process_add_sta_resp(priv, sta, pkt, true);
- }
- iwl_free_pages(priv, cmd.reply_page);
-
- return ret;
-}
-
-static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
- struct ieee80211_sta *sta,
- struct iwl_rxon_context *ctx)
-{
- struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
- __le32 sta_flags;
- u8 mimo_ps_mode;
-
- if (!sta || !sta_ht_inf->ht_supported)
- goto done;
-
- mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
- IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
- (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
- "static" :
- (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
- "dynamic" : "disabled");
-
- sta_flags = priv->stations[index].sta.station_flags;
-
- sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
-
- switch (mimo_ps_mode) {
- case WLAN_HT_CAP_SM_PS_STATIC:
- sta_flags |= STA_FLG_MIMO_DIS_MSK;
- break;
- case WLAN_HT_CAP_SM_PS_DYNAMIC:
- sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
- break;
- case WLAN_HT_CAP_SM_PS_DISABLED:
- break;
- default:
- IWL_WARN(priv, "Invalid MIMO PS mode %d\n", mimo_ps_mode);
- break;
- }
-
- sta_flags |= cpu_to_le32(
- (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
-
- sta_flags |= cpu_to_le32(
- (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
-
- if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
- sta_flags |= STA_FLG_HT40_EN_MSK;
- else
- sta_flags &= ~STA_FLG_HT40_EN_MSK;
-
- priv->stations[index].sta.station_flags = sta_flags;
- done:
- return;
-}
-
-/**
- * iwl_prep_station - Prepare station information for addition
- *
- * should be called with sta_lock held
- */
-u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- const u8 *addr, bool is_ap, struct ieee80211_sta *sta)
-{
- struct iwl_station_entry *station;
- int i;
- u8 sta_id = IWL_INVALID_STATION;
-
- if (is_ap)
- sta_id = ctx->ap_sta_id;
- else if (is_broadcast_ether_addr(addr))
- sta_id = ctx->bcast_sta_id;
- else
- for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
- if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
- addr)) {
- sta_id = i;
- break;
- }
-
- if (!priv->stations[i].used &&
- sta_id == IWL_INVALID_STATION)
- sta_id = i;
- }
-
- /*
- * These two conditions have the same outcome, but keep them
- * separate
- */
- if (unlikely(sta_id == IWL_INVALID_STATION))
- return sta_id;
-
- /*
- * uCode is not able to deal with multiple requests to add a
- * station. Keep track if one is in progress so that we do not send
- * another.
- */
- if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
- IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n",
- sta_id);
- return sta_id;
- }
-
- if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
- (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) &&
- !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) {
- IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n",
- sta_id, addr);
- return sta_id;
- }
-
- station = &priv->stations[sta_id];
- station->used = IWL_STA_DRIVER_ACTIVE;
- IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n",
- sta_id, addr);
- priv->num_stations++;
-
- /* Set up the REPLY_ADD_STA command to send to device */
- memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
- memcpy(station->sta.sta.addr, addr, ETH_ALEN);
- station->sta.mode = 0;
- station->sta.sta.sta_id = sta_id;
- station->sta.station_flags = ctx->station_flags;
- station->ctxid = ctx->ctxid;
-
- if (sta) {
- struct iwl_station_priv_common *sta_priv;
-
- sta_priv = (void *)sta->drv_priv;
- sta_priv->ctx = ctx;
- }
-
- /*
- * OK to call unconditionally, since local stations (IBSS BSSID
- * STA and broadcast STA) pass in a NULL sta, and mac80211
- * doesn't allow HT IBSS.
- */
- iwl_set_ht_add_station(priv, sta_id, sta, ctx);
-
- return sta_id;
-
-}
-
-#define STA_WAIT_TIMEOUT (HZ/2)
-
-/**
- * iwl_add_station_common -
- */
-int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- const u8 *addr, bool is_ap,
- struct ieee80211_sta *sta, u8 *sta_id_r)
-{
- unsigned long flags_spin;
- int ret = 0;
- u8 sta_id;
- struct iwl_addsta_cmd sta_cmd;
-
- *sta_id_r = 0;
- spin_lock_irqsave(&priv->sta_lock, flags_spin);
- sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta);
- if (sta_id == IWL_INVALID_STATION) {
- IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
- addr);
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- return -EINVAL;
- }
-
- /*
- * uCode is not able to deal with multiple requests to add a
- * station. Keep track if one is in progress so that we do not send
- * another.
- */
- if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
- IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n",
- sta_id);
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- return -EEXIST;
- }
-
- if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
- (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
- IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n",
- sta_id, addr);
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- return -EEXIST;
- }
-
- priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-
- /* Add station to device's station table */
- ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
- if (ret) {
- spin_lock_irqsave(&priv->sta_lock, flags_spin);
- IWL_ERR(priv, "Adding station %pM failed.\n",
- priv->stations[sta_id].sta.sta.addr);
- priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
- priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- }
- *sta_id_r = sta_id;
- return ret;
-}
-
-/**
- * iwl_sta_ucode_deactivate - deactivate ucode status for a station
- *
- * priv->sta_lock must be held
- */
-static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
-{
- /* Ucode must be active and driver must be non active */
- if ((priv->stations[sta_id].used &
- (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) != IWL_STA_UCODE_ACTIVE)
- IWL_ERR(priv, "removed non active STA %u\n", sta_id);
-
- priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
-
- memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry));
- IWL_DEBUG_ASSOC(priv, "Removed STA %u\n", sta_id);
-}
-
-static int iwl_send_remove_station(struct iwl_priv *priv,
- const u8 *addr, int sta_id,
- bool temporary)
-{
- struct iwl_rx_packet *pkt;
- int ret;
-
- unsigned long flags_spin;
- struct iwl_rem_sta_cmd rm_sta_cmd;
-
- struct iwl_host_cmd cmd = {
- .id = REPLY_REMOVE_STA,
- .len = { sizeof(struct iwl_rem_sta_cmd), },
- .flags = CMD_SYNC,
- .data = { &rm_sta_cmd, },
- };
-
- memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
- rm_sta_cmd.num_sta = 1;
- memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN);
-
- cmd.flags |= CMD_WANT_SKB;
-
- ret = trans_send_cmd(&priv->trans, &cmd);
-
- if (ret)
- return ret;
-
- pkt = (struct iwl_rx_packet *)cmd.reply_page;
- if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
- pkt->hdr.flags);
- ret = -EIO;
- }
-
- if (!ret) {
- switch (pkt->u.rem_sta.status) {
- case REM_STA_SUCCESS_MSK:
- if (!temporary) {
- spin_lock_irqsave(&priv->sta_lock, flags_spin);
- iwl_sta_ucode_deactivate(priv, sta_id);
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- }
- IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
- break;
- default:
- ret = -EIO;
- IWL_ERR(priv, "REPLY_REMOVE_STA failed\n");
- break;
- }
- }
- iwl_free_pages(priv, cmd.reply_page);
-
- return ret;
-}
-
-/**
- * iwl_remove_station - Remove driver's knowledge of station.
- */
-int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
- const u8 *addr)
-{
- unsigned long flags;
-
- if (!iwl_is_ready(priv)) {
- IWL_DEBUG_INFO(priv,
- "Unable to remove station %pM, device not ready.\n",
- addr);
- /*
- * It is typical for stations to be removed when we are
- * going down. Return success since device will be down
- * soon anyway
- */
- return 0;
- }
-
- IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n",
- sta_id, addr);
-
- if (WARN_ON(sta_id == IWL_INVALID_STATION))
- return -EINVAL;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
- IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
- addr);
- goto out_err;
- }
-
- if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
- IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n",
- addr);
- goto out_err;
- }
-
- if (priv->stations[sta_id].used & IWL_STA_LOCAL) {
- kfree(priv->stations[sta_id].lq);
- priv->stations[sta_id].lq = NULL;
- }
-
- priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
-
- priv->num_stations--;
-
- if (WARN_ON(priv->num_stations < 0))
- priv->num_stations = 0;
-
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_remove_station(priv, addr, sta_id, false);
-out_err:
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return -EINVAL;
-}
-
-/**
- * iwl_clear_ucode_stations - clear ucode station table bits
- *
- * This function clears all the bits in the driver indicating
- * which stations are active in the ucode. Call when something
- * other than explicit station management would cause this in
- * the ucode, e.g. unassociated RXON.
- */
-void iwl_clear_ucode_stations(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
-{
- int i;
- unsigned long flags_spin;
- bool cleared = false;
-
- IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
-
- spin_lock_irqsave(&priv->sta_lock, flags_spin);
- for (i = 0; i < priv->hw_params.max_stations; i++) {
- if (ctx && ctx->ctxid != priv->stations[i].ctxid)
- continue;
-
- if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
- IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i);
- priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
- cleared = true;
- }
- }
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-
- if (!cleared)
- IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n");
-}
-
-/**
- * iwl_restore_stations() - Restore driver known stations to device
- *
- * All stations considered active by driver, but not present in ucode, is
- * restored.
- *
- * Function sleeps.
- */
-void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
- struct iwl_addsta_cmd sta_cmd;
- struct iwl_link_quality_cmd lq;
- unsigned long flags_spin;
- int i;
- bool found = false;
- int ret;
- bool send_lq;
-
- if (!iwl_is_ready(priv)) {
- IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n");
- return;
- }
-
- IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
- spin_lock_irqsave(&priv->sta_lock, flags_spin);
- for (i = 0; i < priv->hw_params.max_stations; i++) {
- if (ctx->ctxid != priv->stations[i].ctxid)
- continue;
- if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) &&
- !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) {
- IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n",
- priv->stations[i].sta.sta.addr);
- priv->stations[i].sta.mode = 0;
- priv->stations[i].used |= IWL_STA_UCODE_INPROGRESS;
- found = true;
- }
- }
-
- for (i = 0; i < priv->hw_params.max_stations; i++) {
- if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) {
- memcpy(&sta_cmd, &priv->stations[i].sta,
- sizeof(struct iwl_addsta_cmd));
- send_lq = false;
- if (priv->stations[i].lq) {
- memcpy(&lq, priv->stations[i].lq,
- sizeof(struct iwl_link_quality_cmd));
- send_lq = true;
- }
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
- if (ret) {
- spin_lock_irqsave(&priv->sta_lock, flags_spin);
- IWL_ERR(priv, "Adding station %pM failed.\n",
- priv->stations[i].sta.sta.addr);
- priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE;
- priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- }
- /*
- * Rate scaling has already been initialized, send
- * current LQ command
- */
- if (send_lq)
- iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
- spin_lock_irqsave(&priv->sta_lock, flags_spin);
- priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
- }
- }
-
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- if (!found)
- IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n");
- else
- IWL_DEBUG_INFO(priv, "Restoring all known stations .... complete.\n");
-}
-
-void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
- unsigned long flags;
- int sta_id = ctx->ap_sta_id;
- int ret;
- struct iwl_addsta_cmd sta_cmd;
- struct iwl_link_quality_cmd lq;
- bool active;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return;
- }
-
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
- sta_cmd.mode = 0;
- memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq));
-
- active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
- priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- if (active) {
- ret = iwl_send_remove_station(
- priv, priv->stations[sta_id].sta.sta.addr,
- sta_id, true);
- if (ret)
- IWL_ERR(priv, "failed to remove STA %pM (%d)\n",
- priv->stations[sta_id].sta.sta.addr, ret);
- }
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
- if (ret)
- IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
- priv->stations[sta_id].sta.sta.addr, ret);
- iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
-}
-
-int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
-{
- int i;
-
- for (i = 0; i < priv->sta_key_max_num; i++)
- if (!test_and_set_bit(i, &priv->ucode_key_table))
- return i;
-
- return WEP_INVALID_OFFSET;
-}
-
-void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
-{
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- for (i = 0; i < priv->hw_params.max_stations; i++) {
- if (!(priv->stations[i].used & IWL_STA_BCAST))
- continue;
-
- priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
- priv->num_stations--;
- if (WARN_ON(priv->num_stations < 0))
- priv->num_stations = 0;
- kfree(priv->stations[i].lq);
- priv->stations[i].lq = NULL;
- }
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-static void iwl_dump_lq_cmd(struct iwl_priv *priv,
- struct iwl_link_quality_cmd *lq)
-{
- int i;
- IWL_DEBUG_RATE(priv, "lq station id 0x%x\n", lq->sta_id);
- IWL_DEBUG_RATE(priv, "lq ant 0x%X 0x%X\n",
- lq->general_params.single_stream_ant_msk,
- lq->general_params.dual_stream_ant_msk);
-
- for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
- IWL_DEBUG_RATE(priv, "lq index %d 0x%X\n",
- i, lq->rs_table[i].rate_n_flags);
-}
-#else
-static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
- struct iwl_link_quality_cmd *lq)
-{
-}
-#endif
-
-/**
- * is_lq_table_valid() - Test one aspect of LQ cmd for validity
- *
- * It sometimes happens when a HT rate has been in use and we
- * loose connectivity with AP then mac80211 will first tell us that the
- * current channel is not HT anymore before removing the station. In such a
- * scenario the RXON flags will be updated to indicate we are not
- * communicating HT anymore, but the LQ command may still contain HT rates.
- * Test for this to prevent driver from sending LQ command between the time
- * RXON flags are updated and when LQ command is updated.
- */
-static bool is_lq_table_valid(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx,
- struct iwl_link_quality_cmd *lq)
-{
- int i;
-
- if (ctx->ht.enabled)
- return true;
-
- IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n",
- ctx->active.channel);
- for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
- if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) {
- IWL_DEBUG_INFO(priv,
- "index %d of LQ expects HT channel\n",
- i);
- return false;
- }
- }
- return true;
-}
-
-/**
- * iwl_send_lq_cmd() - Send link quality command
- * @init: This command is sent as part of station initialization right
- * after station has been added.
- *
- * The link quality command is sent as the last step of station creation.
- * This is the special case in which init is set and we call a callback in
- * this case to clear the state indicating that station creation is in
- * progress.
- */
-int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- struct iwl_link_quality_cmd *lq, u8 flags, bool init)
-{
- int ret = 0;
- unsigned long flags_spin;
-
- struct iwl_host_cmd cmd = {
- .id = REPLY_TX_LINK_QUALITY_CMD,
- .len = { sizeof(struct iwl_link_quality_cmd), },
- .flags = flags,
- .data = { lq, },
- };
-
- if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
- return -EINVAL;
-
-
- spin_lock_irqsave(&priv->sta_lock, flags_spin);
- if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- return -EINVAL;
- }
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-
- iwl_dump_lq_cmd(priv, lq);
- if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
- return -EINVAL;
-
- if (is_lq_table_valid(priv, ctx, lq))
- ret = trans_send_cmd(&priv->trans, &cmd);
- else
- ret = -EINVAL;
-
- if (cmd.flags & CMD_ASYNC)
- return ret;
-
- if (init) {
- IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n",
- lq->sta_id);
- spin_lock_irqsave(&priv->sta_lock, flags_spin);
- priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
- spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- }
- return ret;
-}
-
-int iwl_mac_sta_remove(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- struct iwl_priv *priv = hw->priv;
- struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv;
- int ret;
-
- IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
- sta->addr);
- mutex_lock(&priv->mutex);
- IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
- sta->addr);
- ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
- if (ret)
- IWL_ERR(priv, "Error removing station %pM\n",
- sta->addr);
- mutex_unlock(&priv->mutex);
- return ret;
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
deleted file mode 100644
index 9a6768d66851..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * 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:
- * Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-#ifndef __iwl_sta_h__
-#define __iwl_sta_h__
-
-#include "iwl-dev.h"
-
-#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
-#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */
-#define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of
- being activated */
-#define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211;
- (this is for the IBSS BSSID stations) */
-#define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */
-
-
-void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-void iwl_clear_ucode_stations(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx);
-void iwl_dealloc_bcast_stations(struct iwl_priv *priv);
-int iwl_get_free_ucode_key_offset(struct iwl_priv *priv);
-int iwl_send_add_sta(struct iwl_priv *priv,
- struct iwl_addsta_cmd *sta, u8 flags);
-int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- const u8 *addr, bool is_ap,
- struct ieee80211_sta *sta, u8 *sta_id_r);
-int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
- const u8 *addr);
-int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-
-u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
-
-int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- struct iwl_link_quality_cmd *lq, u8 flags, bool init);
-void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-
-/**
- * iwl_clear_driver_stations - clear knowledge of all stations from driver
- * @priv: iwl priv struct
- *
- * This is called during iwl_down() to make sure that in the case
- * we're coming there from a hardware restart mac80211 will be
- * able to reconfigure stations -- if we're getting there in the
- * normal down flow then the stations will already be cleared.
- */
-static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
-{
- unsigned long flags;
- struct iwl_rxon_context *ctx;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- memset(priv->stations, 0, sizeof(priv->stations));
- priv->num_stations = 0;
-
- priv->ucode_key_table = 0;
-
- for_each_context(priv, ctx) {
- /*
- * Remove all key information that is not stored as part
- * of station information since mac80211 may not have had
- * a chance to remove all the keys. When device is
- * reconfigured by mac80211 after an error all keys will
- * be reconfigured.
- */
- memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
- ctx->key_mapping_keys = 0;
- }
-
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-
-static inline int iwl_sta_id(struct ieee80211_sta *sta)
-{
- if (WARN_ON(!sta))
- return IWL_INVALID_STATION;
-
- return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id;
-}
-
-/**
- * iwl_sta_id_or_broadcast - return sta_id or broadcast sta
- * @priv: iwl priv
- * @context: the current context
- * @sta: mac80211 station
- *
- * In certain circumstances mac80211 passes a station pointer
- * that may be %NULL, for example during TX or key setup. In
- * that case, we need to use the broadcast station, so this
- * inline wraps that pattern.
- */
-static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv,
- struct iwl_rxon_context *context,
- struct ieee80211_sta *sta)
-{
- int sta_id;
-
- if (!sta)
- return context->bcast_sta_id;
-
- sta_id = iwl_sta_id(sta);
-
- /*
- * mac80211 should not be passing a partially
- * initialised station!
- */
- WARN_ON(sta_id == IWL_INVALID_STATION);
-
- return sta_id;
-}
-#endif /* __iwl_sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
index b11f60de4f1e..5e50d88f302b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
@@ -63,6 +63,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/dma-mapping.h>
#include <net/net_namespace.h>
#include <linux/netdevice.h>
#include <net/cfg80211.h>
@@ -72,7 +73,6 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-debug.h"
-#include "iwl-fh.h"
#include "iwl-io.h"
#include "iwl-agn.h"
#include "iwl-testmode.h"
@@ -184,7 +184,7 @@ static void iwl_trace_cleanup(struct iwl_priv *priv)
if (priv->testmode_trace.trace_enabled) {
if (priv->testmode_trace.cpu_addr &&
priv->testmode_trace.dma_addr)
- dma_free_coherent(priv->bus->dev,
+ dma_free_coherent(bus(priv)->dev,
priv->testmode_trace.total_size,
priv->testmode_trace.cpu_addr,
priv->testmode_trace.dma_addr);
@@ -239,7 +239,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
" len %d\n", cmd.id, cmd.flags, cmd.len[0]);
/* ok, let's submit the command to ucode */
- return trans_send_cmd(&priv->trans, &cmd);
+ return iwl_trans_send_cmd(trans(priv), &cmd);
}
@@ -277,7 +277,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_REG_READ32:
- val32 = iwl_read32(priv, ofs);
+ val32 = iwl_read32(bus(priv), ofs);
IWL_INFO(priv, "32bit value to read 0x%x\n", val32);
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
@@ -299,7 +299,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
} else {
val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
IWL_INFO(priv, "32bit value to write 0x%x\n", val32);
- iwl_write32(priv, ofs, val32);
+ iwl_write32(bus(priv), ofs, val32);
}
break;
case IWL_TM_CMD_APP2DEV_REG_WRITE8:
@@ -309,7 +309,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
} else {
val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]);
IWL_INFO(priv, "8bit value to write 0x%x\n", val8);
- iwl_write8(priv, ofs, val8);
+ iwl_write8(bus(priv), ofs, val8);
}
break;
default:
@@ -405,7 +405,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
iwl_testmode_cfg_init_calib(priv);
- trans_stop_device(&priv->trans);
+ iwl_trans_stop_device(trans(priv));
break;
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
@@ -484,7 +484,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
struct iwl_priv *priv = hw->priv;
struct sk_buff *skb;
int status = 0;
- struct device *dev = priv->bus->dev;
+ struct device *dev = bus(priv)->dev;
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
@@ -613,7 +613,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
- priv->ucode_owner = owner;
+ priv->shrd->ucode_owner = owner;
else {
IWL_DEBUG_INFO(priv, "Invalid owner\n");
return -EINVAL;
@@ -641,7 +641,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
* @data: pointer to user space message
* @len: length in byte of @data
*/
-int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
+int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
{
struct nlattr *tb[IWL_TM_ATTR_MAX];
struct iwl_priv *priv = hw->priv;
@@ -661,7 +661,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
return -ENOMSG;
}
/* in case multiple accesses to the device happens */
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_UCODE:
@@ -702,11 +702,11 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
break;
}
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
return result;
}
-int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
struct netlink_callback *cb,
void *data, int len)
{
@@ -738,7 +738,7 @@ int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
}
/* in case multiple accesses to the device happens */
- mutex_lock(&priv->mutex);
+ mutex_lock(&priv->shrd->mutex);
switch (cmd) {
case IWL_TM_CMD_APP2DEV_READ_TRACE:
IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
@@ -749,6 +749,6 @@ int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
break;
}
- mutex_unlock(&priv->mutex);
+ mutex_unlock(&priv->shrd->mutex);
return result;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
deleted file mode 100644
index b79330d84185..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * 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:
- * Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-#ifndef __iwl_trans_int_pcie_h__
-#define __iwl_trans_int_pcie_h__
-
-/*This file includes the declaration that are internal to the
- * trans_pcie layer */
-
-/*****************************************************
-* RX
-******************************************************/
-void iwl_bg_rx_replenish(struct work_struct *data);
-void iwl_irq_tasklet(struct iwl_priv *priv);
-void iwlagn_rx_replenish(struct iwl_priv *priv);
-void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl_rx_queue *q);
-
-/*****************************************************
-* ICT
-******************************************************/
-int iwl_reset_ict(struct iwl_priv *priv);
-void iwl_disable_ict(struct iwl_priv *priv);
-int iwl_alloc_isr_ict(struct iwl_priv *priv);
-void iwl_free_isr_ict(struct iwl_priv *priv);
-irqreturn_t iwl_isr_ict(int irq, void *data);
-
-
-/*****************************************************
-* TX / HCMD
-******************************************************/
-void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
- int index);
-int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
- dma_addr_t addr, u16 len, u8 reset);
-int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
- int count, int slots_num, u32 id);
-int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags,
- u16 len, const void *data);
-void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
-void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
- u16 byte_cnt);
-int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
- u16 ssn_idx, u8 tx_fifo);
-void iwl_trans_set_wr_ptrs(struct iwl_priv *priv,
- int txq_id, u32 index);
-void iwl_trans_tx_queue_set_status(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
- int tx_fifo_id, int scd_retry);
-void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid,
- int frame_limit);
-
-#endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
new file mode 100644
index 000000000000..2b6756e8b8f9
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
@@ -0,0 +1,436 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * 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:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#ifndef __iwl_trans_int_pcie_h__
+#define __iwl_trans_int_pcie_h__
+
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+
+#include "iwl-fh.h"
+#include "iwl-csr.h"
+#include "iwl-shared.h"
+#include "iwl-trans.h"
+#include "iwl-debug.h"
+#include "iwl-io.h"
+
+struct iwl_tx_queue;
+struct iwl_queue;
+struct iwl_host_cmd;
+
+/*This file includes the declaration that are internal to the
+ * trans_pcie layer */
+
+/**
+ * struct isr_statistics - interrupt statistics
+ *
+ */
+struct isr_statistics {
+ u32 hw;
+ u32 sw;
+ u32 err_code;
+ u32 sch;
+ u32 alive;
+ u32 rfkill;
+ u32 ctkill;
+ u32 wakeup;
+ u32 rx;
+ u32 tx;
+ u32 unhandled;
+};
+
+/**
+ * struct iwl_rx_queue - 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:
+ * @queue:
+ * @read: Shared index to newest available Rx buffer
+ * @write: Shared index to oldest written Rx packet
+ * @free_count: Number of pre-allocated buffers in rx_free
+ * @write_actual:
+ * @rx_free: list of free SKBs for use
+ * @rx_used: List of Rx buffers with no SKB
+ * @need_update: flag to indicate we need to update read/write index
+ * @rb_stts: driver's pointer to receive buffer status
+ * @rb_stts_dma: bus address of receive buffer status
+ * @lock:
+ *
+ * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
+ */
+struct iwl_rx_queue {
+ __le32 *bd;
+ dma_addr_t bd_dma;
+ struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+ struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
+ u32 read;
+ u32 write;
+ u32 free_count;
+ u32 write_actual;
+ struct list_head rx_free;
+ struct list_head rx_used;
+ int need_update;
+ struct iwl_rb_status *rb_stts;
+ dma_addr_t rb_stts_dma;
+ spinlock_t lock;
+};
+
+struct iwl_dma_ptr {
+ dma_addr_t dma;
+ void *addr;
+ size_t size;
+};
+
+/*
+ * This queue number is required for proper operation
+ * because the ucode will stop/start the scheduler as
+ * required.
+ */
+#define IWL_IPAN_MCAST_QUEUE 8
+
+struct iwl_cmd_meta {
+ /* only for SYNC commands, iff the reply skb is wanted */
+ struct iwl_host_cmd *source;
+
+ u32 flags;
+
+ DEFINE_DMA_UNMAP_ADDR(mapping);
+ DEFINE_DMA_UNMAP_LEN(len);
+};
+
+/*
+ * Generic queue structure
+ *
+ * Contains common data for Rx and Tx queues.
+ *
+ * Note the difference between n_bd and n_window: the hardware
+ * always assumes 256 descriptors, so n_bd is always 256 (unless
+ * there might be HW changes in the future). For the normal TX
+ * queues, n_window, which is the size of the software queue data
+ * is also 256; however, for the command queue, n_window is only
+ * 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.
+ * This means that we end up with the following:
+ * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
+ * SW entries: | 0 | ... | 31 |
+ * where N is a number between 0 and 7. This means that the SW
+ * data is a window overlayed over the HW queue.
+ */
+struct iwl_queue {
+ int n_bd; /* number of BDs in this queue */
+ int write_ptr; /* 1-st empty entry (index) host_w*/
+ int read_ptr; /* last used entry (index) host_r*/
+ /* use for monitoring and recovering the stuck queue */
+ dma_addr_t dma_addr; /* physical addr for BD's */
+ int n_window; /* safe queue window */
+ u32 id;
+ int low_mark; /* low watermark, resume queue if free
+ * space more than this */
+ int high_mark; /* high watermark, stop queue if free
+ * space less than this */
+};
+
+/**
+ * struct iwl_tx_queue - Tx Queue for DMA
+ * @q: generic Rx/Tx queue descriptor
+ * @bd: base of circular buffer of TFDs
+ * @cmd: array of command/TX buffer pointers
+ * @meta: array of meta data for each command/tx buffer
+ * @dma_addr_cmd: physical address of cmd/tx buffer array
+ * @txb: array of per-TFD driver data
+ * @time_stamp: time (in jiffies) of last read_ptr change
+ * @need_update: indicates need to update read/write index
+ * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
+ * @sta_id: valid if sched_retry is set
+ * @tid: valid if sched_retry is set
+ *
+ * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
+ * descriptors) and required locking structures.
+ */
+#define TFD_TX_CMD_SLOTS 256
+#define TFD_CMD_SLOTS 32
+
+struct iwl_tx_queue {
+ struct iwl_queue q;
+ struct iwl_tfd *tfds;
+ struct iwl_device_cmd **cmd;
+ struct iwl_cmd_meta *meta;
+ struct sk_buff **skbs;
+ unsigned long time_stamp;
+ u8 need_update;
+ u8 sched_retry;
+ u8 active;
+ u8 swq_id;
+
+ u16 sta_id;
+ u16 tid;
+};
+
+/**
+ * struct iwl_trans_pcie - PCIe transport specific data
+ * @rxq: all the RX queue data
+ * @rx_replenish: work that will be called when buffers need to be allocated
+ * @trans: pointer to the generic transport area
+ * @scd_base_addr: scheduler sram base address in SRAM
+ * @scd_bc_tbls: pointer to the byte count table of the scheduler
+ * @kw: keep warm address
+ * @ac_to_fifo: to what fifo is a specifc AC mapped ?
+ * @ac_to_queue: to what tx queue is a specifc AC mapped ?
+ * @mcast_queue:
+ * @txq: Tx DMA processing queues
+ * @txq_ctx_active_msk: what queue is active
+ * queue_stopped: tracks what queue is stopped
+ * queue_stop_count: tracks what SW queue is stopped
+ */
+struct iwl_trans_pcie {
+ struct iwl_rx_queue rxq;
+ struct work_struct rx_replenish;
+ struct iwl_trans *trans;
+
+ /* INT ICT Table */
+ __le32 *ict_tbl;
+ void *ict_tbl_vir;
+ dma_addr_t ict_tbl_dma;
+ dma_addr_t aligned_ict_tbl_dma;
+ int ict_index;
+ u32 inta;
+ bool use_ict;
+ struct tasklet_struct irq_tasklet;
+ struct isr_statistics isr_stats;
+
+ u32 inta_mask;
+ u32 scd_base_addr;
+ struct iwl_dma_ptr scd_bc_tbls;
+ struct iwl_dma_ptr kw;
+
+ const u8 *ac_to_fifo[NUM_IWL_RXON_CTX];
+ const u8 *ac_to_queue[NUM_IWL_RXON_CTX];
+ u8 mcast_queue[NUM_IWL_RXON_CTX];
+
+ struct iwl_tx_queue *txq;
+ unsigned long txq_ctx_active_msk;
+#define IWL_MAX_HW_QUEUES 32
+ unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
+ atomic_t queue_stop_count[4];
+};
+
+#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
+ ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific))
+
+/*****************************************************
+* RX
+******************************************************/
+void iwl_bg_rx_replenish(struct work_struct *data);
+void iwl_irq_tasklet(struct iwl_trans *trans);
+void iwlagn_rx_replenish(struct iwl_trans *trans);
+void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
+ struct iwl_rx_queue *q);
+
+/*****************************************************
+* ICT
+******************************************************/
+int 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);
+
+/*****************************************************
+* 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_mem_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);
+void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id);
+int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx, int sta_id,
+ int tid);
+void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index);
+void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
+ struct iwl_tx_queue *txq,
+ int tx_fifo_id, int scd_retry);
+int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx, int sta_id,
+ int tid, u16 *ssn);
+void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx,
+ int sta_id, int tid, int frame_limit);
+void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
+ int index, 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);
+
+/*****************************************************
+* Error handling
+******************************************************/
+int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
+ char **buf, bool display);
+int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display);
+void iwl_dump_csr(struct iwl_trans *trans);
+
+/*****************************************************
+* Helpers
+******************************************************/
+static inline void iwl_disable_interrupts(struct iwl_trans *trans)
+{
+ clear_bit(STATUS_INT_ENABLED, &trans->shrd->status);
+
+ /* disable interrupts from uCode/NIC to host */
+ iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000);
+
+ /* acknowledge/clear/reset any interrupts still pending
+ * from uCode or flow handler (Rx/Tx DMA) */
+ iwl_write32(bus(trans), CSR_INT, 0xffffffff);
+ iwl_write32(bus(trans), CSR_FH_INT_STATUS, 0xffffffff);
+ IWL_DEBUG_ISR(trans, "Disabled interrupts\n");
+}
+
+static inline void iwl_enable_interrupts(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
+ set_bit(STATUS_INT_ENABLED, &trans->shrd->status);
+ iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask);
+}
+
+/*
+ * we have 8 bits used like this:
+ *
+ * 7 6 5 4 3 2 1 0
+ * | | | | | | | |
+ * | | | | | | +-+-------- AC queue (0-3)
+ * | | | | | |
+ * | +-+-+-+-+------------ HW queue ID
+ * |
+ * +---------------------- unused
+ */
+static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
+{
+ BUG_ON(ac > 3); /* only have 2 bits */
+ BUG_ON(hwq > 31); /* only use 5 bits */
+
+ txq->swq_id = (hwq << 2) | ac;
+}
+
+static inline void iwl_wake_queue(struct iwl_trans *trans,
+ struct iwl_tx_queue *txq)
+{
+ u8 queue = txq->swq_id;
+ u8 ac = queue & 3;
+ u8 hwq = (queue >> 2) & 0x1f;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ if (test_and_clear_bit(hwq, trans_pcie->queue_stopped))
+ if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0)
+ iwl_wake_sw_queue(priv(trans), ac);
+}
+
+static inline void iwl_stop_queue(struct iwl_trans *trans,
+ struct iwl_tx_queue *txq)
+{
+ u8 queue = txq->swq_id;
+ u8 ac = queue & 3;
+ u8 hwq = (queue >> 2) & 0x1f;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ if (!test_and_set_bit(hwq, trans_pcie->queue_stopped))
+ if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0)
+ iwl_stop_sw_queue(priv(trans), ac);
+}
+
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
+#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
+#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
+
+static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie,
+ int txq_id)
+{
+ set_bit(txq_id, &trans_pcie->txq_ctx_active_msk);
+}
+
+static inline void iwl_txq_ctx_deactivate(struct iwl_trans_pcie *trans_pcie,
+ int txq_id)
+{
+ clear_bit(txq_id, &trans_pcie->txq_ctx_active_msk);
+}
+
+static inline int 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) :
+ !(i < q->read_ptr && i >= q->write_ptr);
+}
+
+static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
+{
+ return index & (q->n_window - 1);
+}
+
+#define IWL_TX_FIFO_BK 0 /* shared */
+#define IWL_TX_FIFO_BE 1
+#define IWL_TX_FIFO_VI 2 /* shared */
+#define IWL_TX_FIFO_VO 3
+#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK
+#define IWL_TX_FIFO_BE_IPAN 4
+#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI
+#define IWL_TX_FIFO_VO_IPAN 5
+/* re-uses the VO FIFO, uCode will properly flush/schedule */
+#define IWL_TX_FIFO_AUX 5
+#define IWL_TX_FIFO_UNUSED -1
+
+/* AUX (TX during scan dwell) queue */
+#define IWL_AUX_QUEUE 10
+
+#endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
new file mode 100644
index 000000000000..374c68cc1d70
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
@@ -0,0 +1,1435 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * 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:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/gfp.h>
+
+/*TODO: Remove include to iwl-core.h*/
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-trans-pcie-int.h"
+
+/******************************************************************************
+ *
+ * RX path functions
+ *
+ ******************************************************************************/
+
+/*
+ * Rx theory of operation
+ *
+ * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
+ * each of which point to Receive Buffers to be filled by the NIC. These get
+ * used not only for Rx frames, but for any command response or notification
+ * from the NIC. The driver and NIC manage the Rx buffers by means
+ * of indexes into the circular buffer.
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two index registers for managing the Rx buffers.
+ *
+ * The READ index maps to the first position that the firmware may be writing
+ * to -- the driver can read up to (but not including) this position and get
+ * good data.
+ * The READ index is managed by the firmware once the card is enabled.
+ *
+ * The WRITE index maps to the last position the driver has read from -- the
+ * position preceding WRITE is the last slot the firmware can place a packet.
+ *
+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
+ * WRITE = READ.
+ *
+ * During initialization, the host sets up the READ queue position to the first
+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer, it will advance the READ index
+ * and fire the RX interrupt. The driver can then query the READ index and
+ * process as many packets as possible, moving the WRITE index forward as it
+ * resets the Rx queue buffers with new memory.
+ *
+ * The management in the driver is as follows:
+ * + 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
+ * 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,
+ * detached from the iwl->rxq. The driver 'processed' index is updated.
+ * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
+ * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
+ * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there
+ * were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * 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
+ * queue, updates firmware pointers, and updates
+ * the WRITE index. If insufficient rx_free buffers
+ * are available, schedules iwl_rx_replenish
+ *
+ * -- enable interrupts --
+ * 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
+ * slots.
+ * ...
+ *
+ */
+
+/**
+ * iwl_rx_queue_space - Return number of free slots available in queue.
+ */
+static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
+{
+ int s = q->read - q->write;
+ if (s <= 0)
+ s += RX_QUEUE_SIZE;
+ /* keep some buffer to not confuse full and empty queue */
+ s -= 2;
+ if (s < 0)
+ s = 0;
+ return s;
+}
+
+/**
+ * iwl_rx_queue_update_write_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)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&q->lock, flags);
+
+ if (q->need_update == 0)
+ goto exit_unlock;
+
+ if (hw_params(trans).shadow_reg_enable) {
+ /* shadow register enabled */
+ /* Device expects a multiple of 8 */
+ q->write_actual = (q->write & ~0x7);
+ iwl_write32(bus(trans), FH_RSCSR_CHNL0_WPTR, q->write_actual);
+ } else {
+ /* If power-saving is in use, make sure device is awake */
+ if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) {
+ reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1);
+
+ if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+ IWL_DEBUG_INFO(trans,
+ "Rx queue requesting wakeup,"
+ " GP1 = 0x%x\n", reg);
+ iwl_set_bit(bus(trans), CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ goto exit_unlock;
+ }
+
+ q->write_actual = (q->write & ~0x7);
+ iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR,
+ q->write_actual);
+
+ /* Else device is assumed to be awake */
+ } else {
+ /* Device expects a multiple of 8 */
+ q->write_actual = (q->write & ~0x7);
+ iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR,
+ q->write_actual);
+ }
+ }
+ q->need_update = 0;
+
+ exit_unlock:
+ spin_unlock_irqrestore(&q->lock, flags);
+}
+
+/**
+ * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr)
+{
+ return cpu_to_le32((u32)(dma_addr >> 8));
+}
+
+/**
+ * iwlagn_rx_queue_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
+ * as we can, pulling from rx_free.
+ *
+ * This moves the 'write' index forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+static void iwlagn_rx_queue_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_rx_mem_buffer *rxb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rxq->lock, flags);
+ while ((iwl_rx_queue_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);
+
+ /* Point to Rx buffer via next RBD in circular buffer */
+ rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma);
+ rxq->queue[rxq->write] = rxb;
+ rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
+ rxq->free_count--;
+ }
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ /* If the pre-allocated buffer pool is dropping low, schedule to
+ * refill it */
+ if (rxq->free_count <= RX_LOW_WATERMARK)
+ queue_work(trans->shrd->workqueue, &trans_pcie->rx_replenish);
+
+
+ /* If we've added more space for the firmware to place data, tell it.
+ * Increment device's write pointer in multiples of 8. */
+ if (rxq->write_actual != (rxq->write & ~0x7)) {
+ spin_lock_irqsave(&rxq->lock, flags);
+ rxq->need_update = 1;
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ iwl_rx_queue_update_write_ptr(trans, rxq);
+ }
+}
+
+/**
+ * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free
+ *
+ * When moving to rx_free an SKB is allocated for the slot.
+ *
+ * Also restock the Rx queue via iwl_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
+ */
+static void iwlagn_rx_allocate(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_rx_mem_buffer *rxb;
+ struct page *page;
+ unsigned long flags;
+ gfp_t gfp_mask = priority;
+
+ while (1) {
+ spin_lock_irqsave(&rxq->lock, flags);
+ if (list_empty(&rxq->rx_used)) {
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ if (rxq->free_count > RX_LOW_WATERMARK)
+ gfp_mask |= __GFP_NOWARN;
+
+ if (hw_params(trans).rx_page_order > 0)
+ gfp_mask |= __GFP_COMP;
+
+ /* Alloc a new receive buffer */
+ page = alloc_pages(gfp_mask,
+ hw_params(trans).rx_page_order);
+ if (!page) {
+ if (net_ratelimit())
+ IWL_DEBUG_INFO(trans, "alloc_pages failed, "
+ "order: %d\n",
+ hw_params(trans).rx_page_order);
+
+ if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+ net_ratelimit())
+ IWL_CRIT(trans, "Failed to alloc_pages with %s."
+ "Only %u free buffers remaining.\n",
+ priority == GFP_ATOMIC ?
+ "GFP_ATOMIC" : "GFP_KERNEL",
+ rxq->free_count);
+ /* We don't reschedule replenish work here -- we will
+ * call the restock method and if it still needs
+ * more buffers it will schedule replenish */
+ return;
+ }
+
+ spin_lock_irqsave(&rxq->lock, flags);
+
+ if (list_empty(&rxq->rx_used)) {
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ __free_pages(page, hw_params(trans).rx_page_order);
+ return;
+ }
+ element = rxq->rx_used.next;
+ rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+ list_del(element);
+
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ BUG_ON(rxb->page);
+ rxb->page = page;
+ /* Get physical address of the RB */
+ rxb->page_dma = dma_map_page(bus(trans)->dev, page, 0,
+ PAGE_SIZE << hw_params(trans).rx_page_order,
+ DMA_FROM_DEVICE);
+ /* dma address must be no more than 36 bits */
+ BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
+ /* and also 256 byte aligned! */
+ BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
+
+ spin_lock_irqsave(&rxq->lock, flags);
+
+ list_add_tail(&rxb->list, &rxq->rx_free);
+ rxq->free_count++;
+
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ }
+}
+
+void iwlagn_rx_replenish(struct iwl_trans *trans)
+{
+ unsigned long flags;
+
+ iwlagn_rx_allocate(trans, GFP_KERNEL);
+
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+ iwlagn_rx_queue_restock(trans);
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+}
+
+static void iwlagn_rx_replenish_now(struct iwl_trans *trans)
+{
+ iwlagn_rx_allocate(trans, GFP_ATOMIC);
+
+ iwlagn_rx_queue_restock(trans);
+}
+
+void iwl_bg_rx_replenish(struct work_struct *data)
+{
+ struct iwl_trans_pcie *trans_pcie =
+ container_of(data, struct iwl_trans_pcie, rx_replenish);
+ struct iwl_trans *trans = trans_pcie->trans;
+
+ if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
+ return;
+
+ mutex_lock(&trans->shrd->mutex);
+ iwlagn_rx_replenish(trans);
+ mutex_unlock(&trans->shrd->mutex);
+}
+
+/**
+ * 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.
+ */
+static void iwl_rx_handle(struct iwl_trans *trans)
+{
+ struct iwl_rx_mem_buffer *rxb;
+ struct iwl_rx_packet *pkt;
+ 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->shrd->cmd_queue];
+ struct iwl_device_cmd *cmd;
+ u32 r, i;
+ int reclaim;
+ unsigned long flags;
+ u8 fill_rx = 0;
+ u32 count = 8;
+ int total_empty;
+ int index, cmd_index;
+
+ /* 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;
+ i = rxq->read;
+
+ /* Rx interrupt, but nothing sent from uCode */
+ if (i == r)
+ IWL_DEBUG_RX(trans, "r = %d, i = %d\n", r, i);
+
+ /* calculate total frames need to be restock after handling RX */
+ total_empty = r - rxq->write_actual;
+ if (total_empty < 0)
+ total_empty += RX_QUEUE_SIZE;
+
+ if (total_empty > (RX_QUEUE_SIZE / 2))
+ fill_rx = 1;
+
+ while (i != r) {
+ int len, err;
+ u16 sequence;
+
+ rxb = rxq->queue[i];
+
+ /* If an RXB doesn't have a Rx queue slot associated with it,
+ * then a bug has been introduced in the queue refilling
+ * routines -- catch it here */
+ if (WARN_ON(rxb == NULL)) {
+ i = (i + 1) & RX_QUEUE_MASK;
+ continue;
+ }
+
+ rxq->queue[i] = NULL;
+
+ dma_unmap_page(bus(trans)->dev, rxb->page_dma,
+ PAGE_SIZE << hw_params(trans).rx_page_order,
+ DMA_FROM_DEVICE);
+ pkt = rxb_addr(rxb);
+
+ IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r,
+ i, get_cmd_string(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(priv(trans), pkt, len);
+
+ /* Reclaim a command buffer only if this packet is a response
+ * to a (driver-originated) command.
+ * If the packet (e.g. Rx frame) originated from uCode,
+ * there is no command buffer to reclaim.
+ * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
+ * but apparently a few don't get set; catch them here. */
+ reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+ (pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
+ (pkt->hdr.cmd != REPLY_RX) &&
+ (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
+ (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
+ (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
+ (pkt->hdr.cmd != REPLY_TX);
+
+ sequence = le16_to_cpu(pkt->hdr.sequence);
+ index = SEQ_TO_INDEX(sequence);
+ cmd_index = get_cmd_index(&txq->q, index);
+
+ if (reclaim)
+ cmd = txq->cmd[cmd_index];
+ else
+ cmd = NULL;
+
+ /* warn if this is cmd response / notification and the uCode
+ * didn't set the SEQ_RX_FRAME for a frame that is
+ * uCode-originated
+ * If you saw this code after the second half of 2012, then
+ * please remove it
+ */
+ WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false &&
+ (!(pkt->hdr.sequence & SEQ_RX_FRAME)),
+ "reclaim is false, SEQ_RX_FRAME unset: %s\n",
+ get_cmd_string(pkt->hdr.cmd));
+
+ err = iwl_rx_dispatch(priv(trans), rxb, cmd);
+
+ /*
+ * XXX: After here, we should always check rxb->page
+ * against NULL before touching it or its virtual
+ * memory (pkt). Because some rx_handler might have
+ * already taken or freed the pages.
+ */
+
+ if (reclaim) {
+ /* Invoke any callbacks, transfer the buffer to caller,
+ * and fire off the (possibly) blocking
+ * iwl_trans_send_cmd()
+ * as we reclaim the driver command queue */
+ if (rxb->page)
+ iwl_tx_cmd_complete(trans, rxb, err);
+ else
+ IWL_WARN(trans, "Claim null rxb?\n");
+ }
+
+ /* Reuse the page if possible. For notification packets and
+ * SKBs that fail to Rx correctly, add them back into the
+ * rx_free list for reuse later. */
+ spin_lock_irqsave(&rxq->lock, flags);
+ if (rxb->page != NULL) {
+ rxb->page_dma = dma_map_page(bus(trans)->dev, rxb->page,
+ 0, PAGE_SIZE <<
+ hw_params(trans).rx_page_order,
+ DMA_FROM_DEVICE);
+ list_add_tail(&rxb->list, &rxq->rx_free);
+ rxq->free_count++;
+ } else
+ list_add_tail(&rxb->list, &rxq->rx_used);
+
+ spin_unlock_irqrestore(&rxq->lock, flags);
+
+ i = (i + 1) & RX_QUEUE_MASK;
+ /* If there are a lot of unused frames,
+ * restock the Rx queue so ucode wont assert. */
+ if (fill_rx) {
+ count++;
+ if (count >= 8) {
+ rxq->read = i;
+ iwlagn_rx_replenish_now(trans);
+ count = 0;
+ }
+ }
+ }
+
+ /* Backtrack one entry */
+ rxq->read = i;
+ if (fill_rx)
+ iwlagn_rx_replenish_now(trans);
+ else
+ iwlagn_rx_queue_restock(trans);
+}
+
+static const char * const desc_lookup_text[] = {
+ "OK",
+ "FAIL",
+ "BAD_PARAM",
+ "BAD_CHECKSUM",
+ "NMI_INTERRUPT_WDG",
+ "SYSASSERT",
+ "FATAL_ERROR",
+ "BAD_COMMAND",
+ "HW_ERROR_TUNE_LOCK",
+ "HW_ERROR_TEMPERATURE",
+ "ILLEGAL_CHAN_FREQ",
+ "VCC_NOT_STABLE",
+ "FH_ERROR",
+ "NMI_INTERRUPT_HOST",
+ "NMI_INTERRUPT_ACTION_PT",
+ "NMI_INTERRUPT_UNKNOWN",
+ "UCODE_VERSION_MISMATCH",
+ "HW_ERROR_ABS_LOCK",
+ "HW_ERROR_CAL_LOCK_FAIL",
+ "NMI_INTERRUPT_INST_ACTION_PT",
+ "NMI_INTERRUPT_DATA_ACTION_PT",
+ "NMI_TRM_HW_ER",
+ "NMI_INTERRUPT_TRM",
+ "NMI_INTERRUPT_BREAK_POINT",
+ "DEBUG_0",
+ "DEBUG_1",
+ "DEBUG_2",
+ "DEBUG_3",
+};
+
+static struct { char *name; u8 num; } advanced_lookup[] = {
+ { "NMI_INTERRUPT_WDG", 0x34 },
+ { "SYSASSERT", 0x35 },
+ { "UCODE_VERSION_MISMATCH", 0x37 },
+ { "BAD_COMMAND", 0x38 },
+ { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
+ { "FATAL_ERROR", 0x3D },
+ { "NMI_TRM_HW_ERR", 0x46 },
+ { "NMI_INTERRUPT_TRM", 0x4C },
+ { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
+ { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
+ { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
+ { "NMI_INTERRUPT_HOST", 0x66 },
+ { "NMI_INTERRUPT_ACTION_PT", 0x7C },
+ { "NMI_INTERRUPT_UNKNOWN", 0x84 },
+ { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
+ { "ADVANCED_SYSASSERT", 0 },
+};
+
+static const char *desc_lookup(u32 num)
+{
+ int i;
+ int max = ARRAY_SIZE(desc_lookup_text);
+
+ if (num < max)
+ return desc_lookup_text[num];
+
+ max = ARRAY_SIZE(advanced_lookup) - 1;
+ for (i = 0; i < max; i++) {
+ if (advanced_lookup[i].num == num)
+ break;
+ }
+ return advanced_lookup[i].name;
+}
+
+#define ERROR_START_OFFSET (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE (7 * sizeof(u32))
+
+static void iwl_dump_nic_error_log(struct iwl_trans *trans)
+{
+ u32 base;
+ struct iwl_error_event_table table;
+ struct iwl_priv *priv = priv(trans);
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ base = priv->device_pointers.error_event_table;
+ if (priv->ucode_type == IWL_UCODE_INIT) {
+ if (!base)
+ base = priv->init_errlog_ptr;
+ } else {
+ if (!base)
+ base = priv->inst_errlog_ptr;
+ }
+
+ if (!iwlagn_hw_valid_rtc_data_addr(base)) {
+ IWL_ERR(trans,
+ "Not valid error log pointer 0x%08X for %s uCode\n",
+ base,
+ (priv->ucode_type == IWL_UCODE_INIT)
+ ? "Init" : "RT");
+ return;
+ }
+
+ iwl_read_targ_mem_words(bus(priv), base, &table, sizeof(table));
+
+ if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
+ IWL_ERR(trans, "Start IWL Error Log Dump:\n");
+ IWL_ERR(trans, "Status: 0x%08lX, count: %d\n",
+ trans->shrd->status, table.valid);
+ }
+
+ trans_pcie->isr_stats.err_code = table.error_id;
+
+ trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
+ table.data1, table.data2, table.line,
+ table.blink1, table.blink2, table.ilink1,
+ table.ilink2, table.bcon_time, table.gp1,
+ table.gp2, table.gp3, table.ucode_ver,
+ table.hw_ver, table.brd_ver);
+ IWL_ERR(trans, "0x%08X | %-28s\n", table.error_id,
+ desc_lookup(table.error_id));
+ IWL_ERR(trans, "0x%08X | uPc\n", table.pc);
+ IWL_ERR(trans, "0x%08X | branchlink1\n", table.blink1);
+ IWL_ERR(trans, "0x%08X | branchlink2\n", table.blink2);
+ IWL_ERR(trans, "0x%08X | interruptlink1\n", table.ilink1);
+ IWL_ERR(trans, "0x%08X | interruptlink2\n", table.ilink2);
+ IWL_ERR(trans, "0x%08X | data1\n", table.data1);
+ IWL_ERR(trans, "0x%08X | data2\n", table.data2);
+ IWL_ERR(trans, "0x%08X | line\n", table.line);
+ IWL_ERR(trans, "0x%08X | beacon time\n", table.bcon_time);
+ IWL_ERR(trans, "0x%08X | tsf low\n", table.tsf_low);
+ IWL_ERR(trans, "0x%08X | tsf hi\n", table.tsf_hi);
+ IWL_ERR(trans, "0x%08X | time gp1\n", table.gp1);
+ IWL_ERR(trans, "0x%08X | time gp2\n", table.gp2);
+ IWL_ERR(trans, "0x%08X | time gp3\n", table.gp3);
+ IWL_ERR(trans, "0x%08X | uCode version\n", table.ucode_ver);
+ IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver);
+ IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver);
+ IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd);
+}
+
+/**
+ * iwl_irq_handle_error - called for HW or SW error interrupt from card
+ */
+static void iwl_irq_handle_error(struct iwl_trans *trans)
+{
+ struct iwl_priv *priv = priv(trans);
+ /* W/A for WiFi/WiMAX coex and WiMAX own the RF */
+ if (priv->cfg->internal_wimax_coex &&
+ (!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) &
+ APMS_CLK_VAL_MRB_FUNC_MODE) ||
+ (iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) &
+ APMG_PS_CTRL_VAL_RESET_REQ))) {
+ /*
+ * Keep the restart process from trying to send host
+ * commands by clearing the ready bit.
+ */
+ clear_bit(STATUS_READY, &trans->shrd->status);
+ clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+ wake_up(&priv->shrd->wait_command_queue);
+ IWL_ERR(trans, "RF is used by WiMAX\n");
+ return;
+ }
+
+ IWL_ERR(trans, "Loaded firmware version: %s\n",
+ priv->hw->wiphy->fw_version);
+
+ iwl_dump_nic_error_log(trans);
+ iwl_dump_csr(trans);
+ iwl_dump_fh(trans, NULL, false);
+ iwl_dump_nic_event_log(trans, false, NULL, false);
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS)
+ iwl_print_rx_config_cmd(priv(trans), IWL_RXON_CTX_BSS);
+#endif
+
+ iwlagn_fw_error(priv, false);
+}
+
+#define EVENT_START_OFFSET (4 * sizeof(u32))
+
+/**
+ * iwl_print_event_log - Dump error event log to syslog
+ *
+ */
+static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
+ u32 num_events, u32 mode,
+ int pos, char **buf, size_t bufsz)
+{
+ u32 i;
+ u32 base; /* SRAM byte address of event log header */
+ u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
+ u32 ptr; /* SRAM byte address of log data */
+ u32 ev, time, data; /* event log data */
+ unsigned long reg_flags;
+ struct iwl_priv *priv = priv(trans);
+
+ if (num_events == 0)
+ return pos;
+
+ base = priv->device_pointers.log_event_table;
+ if (priv->ucode_type == IWL_UCODE_INIT) {
+ if (!base)
+ base = priv->init_evtlog_ptr;
+ } else {
+ if (!base)
+ base = priv->inst_evtlog_ptr;
+ }
+
+ if (mode == 0)
+ event_size = 2 * sizeof(u32);
+ else
+ event_size = 3 * sizeof(u32);
+
+ ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+ /* Make sure device is powered up for SRAM reads */
+ spin_lock_irqsave(&bus(trans)->reg_lock, reg_flags);
+ iwl_grab_nic_access(bus(trans));
+
+ /* Set starting address; reads will auto-increment */
+ iwl_write32(bus(trans), HBUS_TARG_MEM_RADDR, ptr);
+ rmb();
+
+ /* "time" is actually "data" for mode 0 (no timestamp).
+ * place event id # at far right for easier visual parsing. */
+ for (i = 0; i < num_events; i++) {
+ ev = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT);
+ time = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT);
+ if (mode == 0) {
+ /* data, ev */
+ if (bufsz) {
+ pos += scnprintf(*buf + pos, bufsz - pos,
+ "EVT_LOG:0x%08x:%04u\n",
+ time, ev);
+ } else {
+ trace_iwlwifi_dev_ucode_event(priv, 0,
+ time, ev);
+ IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n",
+ time, ev);
+ }
+ } else {
+ data = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT);
+ if (bufsz) {
+ pos += scnprintf(*buf + pos, bufsz - pos,
+ "EVT_LOGT:%010u:0x%08x:%04u\n",
+ time, data, ev);
+ } else {
+ IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n",
+ time, data, ev);
+ trace_iwlwifi_dev_ucode_event(priv, time,
+ data, ev);
+ }
+ }
+ }
+
+ /* Allow device to power down */
+ iwl_release_nic_access(bus(trans));
+ spin_unlock_irqrestore(&bus(trans)->reg_lock, reg_flags);
+ return pos;
+}
+
+/**
+ * iwl_print_last_event_logs - Dump the newest # of event log to syslog
+ */
+static int iwl_print_last_event_logs(struct iwl_trans *trans, u32 capacity,
+ u32 num_wraps, u32 next_entry,
+ u32 size, u32 mode,
+ int pos, char **buf, size_t bufsz)
+{
+ /*
+ * display the newest DEFAULT_LOG_ENTRIES entries
+ * i.e the entries just before the next ont that uCode would fill.
+ */
+ if (num_wraps) {
+ if (next_entry < size) {
+ pos = iwl_print_event_log(trans,
+ capacity - (size - next_entry),
+ size - next_entry, mode,
+ pos, buf, bufsz);
+ pos = iwl_print_event_log(trans, 0,
+ next_entry, mode,
+ pos, buf, bufsz);
+ } else
+ pos = iwl_print_event_log(trans, next_entry - size,
+ size, mode, pos, buf, bufsz);
+ } else {
+ if (next_entry < size) {
+ pos = iwl_print_event_log(trans, 0, next_entry,
+ mode, pos, buf, bufsz);
+ } else {
+ pos = iwl_print_event_log(trans, next_entry - size,
+ size, mode, pos, buf, bufsz);
+ }
+ }
+ return pos;
+}
+
+#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
+
+int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
+ char **buf, bool display)
+{
+ u32 base; /* SRAM byte address of event log header */
+ u32 capacity; /* event log capacity in # entries */
+ u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
+ u32 num_wraps; /* # times uCode wrapped to top of log */
+ u32 next_entry; /* index of next entry to be written by uCode */
+ u32 size; /* # entries that we'll print */
+ u32 logsize;
+ int pos = 0;
+ size_t bufsz = 0;
+ struct iwl_priv *priv = priv(trans);
+
+ base = priv->device_pointers.log_event_table;
+ if (priv->ucode_type == IWL_UCODE_INIT) {
+ logsize = priv->init_evtlog_size;
+ if (!base)
+ base = priv->init_evtlog_ptr;
+ } else {
+ logsize = priv->inst_evtlog_size;
+ if (!base)
+ base = priv->inst_evtlog_ptr;
+ }
+
+ if (!iwlagn_hw_valid_rtc_data_addr(base)) {
+ IWL_ERR(trans,
+ "Invalid event log pointer 0x%08X for %s uCode\n",
+ base,
+ (priv->ucode_type == IWL_UCODE_INIT)
+ ? "Init" : "RT");
+ return -EINVAL;
+ }
+
+ /* event log header */
+ capacity = iwl_read_targ_mem(bus(trans), base);
+ mode = iwl_read_targ_mem(bus(trans), base + (1 * sizeof(u32)));
+ num_wraps = iwl_read_targ_mem(bus(trans), base + (2 * sizeof(u32)));
+ next_entry = iwl_read_targ_mem(bus(trans), base + (3 * sizeof(u32)));
+
+ if (capacity > logsize) {
+ IWL_ERR(trans, "Log capacity %d is bogus, limit to %d "
+ "entries\n", capacity, logsize);
+ capacity = logsize;
+ }
+
+ if (next_entry > logsize) {
+ IWL_ERR(trans, "Log write index %d is bogus, limit to %d\n",
+ next_entry, logsize);
+ next_entry = logsize;
+ }
+
+ size = num_wraps ? capacity : next_entry;
+
+ /* bail out if nothing in log */
+ if (size == 0) {
+ IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n");
+ return pos;
+ }
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log)
+ size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
+ ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
+#else
+ size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
+ ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
+#endif
+ IWL_ERR(trans, "Start IWL Event Log Dump: display last %u entries\n",
+ size);
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (display) {
+ if (full_log)
+ bufsz = capacity * 48;
+ else
+ bufsz = size * 48;
+ *buf = kmalloc(bufsz, GFP_KERNEL);
+ if (!*buf)
+ return -ENOMEM;
+ }
+ if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) {
+ /*
+ * if uCode has wrapped back to top of log,
+ * start at the oldest entry,
+ * i.e the next one that uCode would fill.
+ */
+ if (num_wraps)
+ pos = iwl_print_event_log(trans, next_entry,
+ capacity - next_entry, mode,
+ pos, buf, bufsz);
+ /* (then/else) start at top of log */
+ pos = iwl_print_event_log(trans, 0,
+ next_entry, mode, pos, buf, bufsz);
+ } else
+ pos = iwl_print_last_event_logs(trans, capacity, num_wraps,
+ next_entry, size, mode,
+ pos, buf, bufsz);
+#else
+ pos = iwl_print_last_event_logs(trans, capacity, num_wraps,
+ next_entry, size, mode,
+ pos, buf, bufsz);
+#endif
+ return pos;
+}
+
+/* tasklet for iwlagn interrupt */
+void iwl_irq_tasklet(struct iwl_trans *trans)
+{
+ u32 inta = 0;
+ u32 handled = 0;
+ unsigned long flags;
+ u32 i;
+#ifdef CONFIG_IWLWIFI_DEBUG
+ u32 inta_mask;
+#endif
+
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
+
+
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+
+ /* Ack/clear/reset pending uCode interrupts.
+ * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
+ */
+ /* There is a hardware bug in the interrupt mask function that some
+ * interrupts (i.e. CSR_INT_BIT_SCD) can still be generated even if
+ * they are disabled in the CSR_INT_MASK register. Furthermore the
+ * ICT interrupt handling mechanism has another bug that might cause
+ * these unmasked interrupts fail to be detected. We workaround the
+ * hardware bugs here by ACKing all the possible interrupts so that
+ * interrupt coalescing can still be achieved.
+ */
+ iwl_write32(bus(trans), CSR_INT,
+ trans_pcie->inta | ~trans_pcie->inta_mask);
+
+ inta = trans_pcie->inta;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) {
+ /* just for debug */
+ inta_mask = iwl_read32(bus(trans), CSR_INT_MASK);
+ IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ",
+ inta, inta_mask);
+ }
+#endif
+
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+ /* saved interrupt in inta variable now we can reset trans_pcie->inta */
+ trans_pcie->inta = 0;
+
+ /* Now service all interrupt bits discovered above. */
+ if (inta & CSR_INT_BIT_HW_ERR) {
+ IWL_ERR(trans, "Hardware error detected. Restarting.\n");
+
+ /* Tell the device to stop sending interrupts */
+ iwl_disable_interrupts(trans);
+
+ isr_stats->hw++;
+ iwl_irq_handle_error(trans);
+
+ handled |= CSR_INT_BIT_HW_ERR;
+
+ return;
+ }
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
+ /* NIC fires this, but we don't use it, redundant with WAKEUP */
+ if (inta & CSR_INT_BIT_SCD) {
+ IWL_DEBUG_ISR(trans, "Scheduler finished to transmit "
+ "the frame/frames.\n");
+ isr_stats->sch++;
+ }
+
+ /* Alive notification via Rx interrupt will do the real work */
+ if (inta & CSR_INT_BIT_ALIVE) {
+ IWL_DEBUG_ISR(trans, "Alive interrupt\n");
+ isr_stats->alive++;
+ }
+ }
+#endif
+ /* Safely ignore these bits for debug checks below */
+ inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
+
+ /* HW RF KILL switch toggled */
+ if (inta & CSR_INT_BIT_RF_KILL) {
+ int hw_rf_kill = 0;
+ if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+ hw_rf_kill = 1;
+
+ IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
+ hw_rf_kill ? "disable radio" : "enable radio");
+
+ isr_stats->rfkill++;
+
+ /* driver only loads ucode once setting the interface up.
+ * the driver allows loading the ucode even if the radio
+ * is killed. Hence update the killswitch state here. The
+ * rfkill handler will care about restarting if needed.
+ */
+ if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) {
+ if (hw_rf_kill)
+ set_bit(STATUS_RF_KILL_HW,
+ &trans->shrd->status);
+ else
+ clear_bit(STATUS_RF_KILL_HW,
+ &trans->shrd->status);
+ iwl_set_hw_rfkill_state(priv(trans), hw_rf_kill);
+ }
+
+ handled |= CSR_INT_BIT_RF_KILL;
+ }
+
+ /* Chip got too hot and stopped itself */
+ if (inta & CSR_INT_BIT_CT_KILL) {
+ IWL_ERR(trans, "Microcode CT kill error detected.\n");
+ isr_stats->ctkill++;
+ handled |= CSR_INT_BIT_CT_KILL;
+ }
+
+ /* Error detected by uCode */
+ if (inta & CSR_INT_BIT_SW_ERR) {
+ IWL_ERR(trans, "Microcode SW error detected. "
+ " Restarting 0x%X.\n", inta);
+ isr_stats->sw++;
+ iwl_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);
+ for (i = 0; i < hw_params(trans).max_txq_num; i++)
+ iwl_txq_update_write_ptr(trans,
+ &trans_pcie->txq[i]);
+
+ isr_stats->wakeup++;
+
+ handled |= CSR_INT_BIT_WAKEUP;
+ }
+
+ /* All uCode command responses, including Tx command responses,
+ * Rx "responses" (frame-received notification), and other
+ * notifications from uCode come through here*/
+ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX |
+ CSR_INT_BIT_RX_PERIODIC)) {
+ IWL_DEBUG_ISR(trans, "Rx interrupt\n");
+ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
+ handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
+ iwl_write32(bus(trans), CSR_FH_INT_STATUS,
+ CSR_FH_INT_RX_MASK);
+ }
+ if (inta & CSR_INT_BIT_RX_PERIODIC) {
+ handled |= CSR_INT_BIT_RX_PERIODIC;
+ iwl_write32(bus(trans),
+ CSR_INT, CSR_INT_BIT_RX_PERIODIC);
+ }
+ /* Sending RX interrupt require many steps to be done in the
+ * the device:
+ * 1- write interrupt to current index in ICT table.
+ * 2- dma RX frame.
+ * 3- update RX shared data to indicate last write index.
+ * 4- send interrupt.
+ * This could lead to RX race, driver could receive RX interrupt
+ * but the shared data changes does not reflect this;
+ * periodic interrupt will detect any dangling Rx activity.
+ */
+
+ /* Disable periodic interrupt; we use it as just a one-shot. */
+ iwl_write8(bus(trans), CSR_INT_PERIODIC_REG,
+ CSR_INT_PERIODIC_DIS);
+ iwl_rx_handle(trans);
+
+ /*
+ * Enable periodic interrupt in 8 msec only if we received
+ * real RX interrupt (instead of just periodic int), to catch
+ * any dangling Rx interrupt. If it was just the periodic
+ * interrupt, there was no dangling Rx activity, and no need
+ * to extend the periodic interrupt; one-shot is enough.
+ */
+ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX))
+ iwl_write8(bus(trans), CSR_INT_PERIODIC_REG,
+ CSR_INT_PERIODIC_ENA);
+
+ isr_stats->rx++;
+ }
+
+ /* This "Tx" DMA channel is used only for loading uCode */
+ if (inta & CSR_INT_BIT_FH_TX) {
+ iwl_write32(bus(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK);
+ IWL_DEBUG_ISR(trans, "uCode load interrupt\n");
+ isr_stats->tx++;
+ handled |= CSR_INT_BIT_FH_TX;
+ /* Wake up uCode load routine, now that load is complete */
+ priv(trans)->ucode_write_complete = 1;
+ wake_up(&trans->shrd->wait_command_queue);
+ }
+
+ if (inta & ~handled) {
+ IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+ isr_stats->unhandled++;
+ }
+
+ if (inta & ~(trans_pcie->inta_mask)) {
+ IWL_WARN(trans, "Disabled INTA bits 0x%08x were pending\n",
+ inta & ~trans_pcie->inta_mask);
+ }
+
+ /* Re-enable all interrupts */
+ /* only Re-enable if disabled by irq */
+ if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status))
+ iwl_enable_interrupts(trans);
+ /* Re-enable RF_KILL if it occurred */
+ else if (handled & CSR_INT_BIT_RF_KILL)
+ iwl_enable_rfkill_int(priv(trans));
+}
+
+/******************************************************************************
+ *
+ * ICT functions
+ *
+ ******************************************************************************/
+#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
+
+/* Free dram table */
+void iwl_free_isr_ict(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ if (trans_pcie->ict_tbl_vir) {
+ dma_free_coherent(bus(trans)->dev,
+ (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+ trans_pcie->ict_tbl_vir,
+ trans_pcie->ict_tbl_dma);
+ trans_pcie->ict_tbl_vir = NULL;
+ memset(&trans_pcie->ict_tbl_dma, 0,
+ sizeof(trans_pcie->ict_tbl_dma));
+ memset(&trans_pcie->aligned_ict_tbl_dma, 0,
+ sizeof(trans_pcie->aligned_ict_tbl_dma));
+ }
+}
+
+
+/* allocate dram shared table it is a PAGE_SIZE aligned
+ * also reset all data related to ICT table interrupt.
+ */
+int iwl_alloc_isr_ict(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ /* allocate shrared data table */
+ trans_pcie->ict_tbl_vir =
+ dma_alloc_coherent(bus(trans)->dev,
+ (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+ &trans_pcie->ict_tbl_dma, GFP_KERNEL);
+ if (!trans_pcie->ict_tbl_vir)
+ return -ENOMEM;
+
+ /* align table to PAGE_SIZE boundary */
+ trans_pcie->aligned_ict_tbl_dma =
+ ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE);
+
+ IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n",
+ (unsigned long long)trans_pcie->ict_tbl_dma,
+ (unsigned long long)trans_pcie->aligned_ict_tbl_dma,
+ (int)(trans_pcie->aligned_ict_tbl_dma -
+ trans_pcie->ict_tbl_dma));
+
+ trans_pcie->ict_tbl = trans_pcie->ict_tbl_vir +
+ (trans_pcie->aligned_ict_tbl_dma -
+ trans_pcie->ict_tbl_dma);
+
+ IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n",
+ trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir,
+ (int)(trans_pcie->aligned_ict_tbl_dma -
+ trans_pcie->ict_tbl_dma));
+
+ /* reset table and index to all 0 */
+ memset(trans_pcie->ict_tbl_vir, 0,
+ (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
+ trans_pcie->ict_index = 0;
+
+ /* add periodic RX interrupt */
+ trans_pcie->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
+ return 0;
+}
+
+/* Device is going up inform it about using ICT interrupt table,
+ * also we need to tell the driver to start using ICT interrupt.
+ */
+int iwl_reset_ict(struct iwl_trans *trans)
+{
+ u32 val;
+ unsigned long flags;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ if (!trans_pcie->ict_tbl_vir)
+ return 0;
+
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+ iwl_disable_interrupts(trans);
+
+ memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
+
+ val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT;
+
+ val |= CSR_DRAM_INT_TBL_ENABLE;
+ val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
+
+ IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X "
+ "aligned dma address %Lx\n",
+ val,
+ (unsigned long long)trans_pcie->aligned_ict_tbl_dma);
+
+ iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val);
+ trans_pcie->use_ict = true;
+ trans_pcie->ict_index = 0;
+ iwl_write32(bus(trans), CSR_INT, trans_pcie->inta_mask);
+ iwl_enable_interrupts(trans);
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+ return 0;
+}
+
+/* Device is going down disable ict interrupt usage */
+void iwl_disable_ict(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+ trans_pcie->use_ict = false;
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+}
+
+static irqreturn_t iwl_isr(int irq, void *data)
+{
+ struct iwl_trans *trans = data;
+ struct iwl_trans_pcie *trans_pcie;
+ u32 inta, inta_mask;
+ unsigned long flags;
+#ifdef CONFIG_IWLWIFI_DEBUG
+ u32 inta_fh;
+#endif
+ if (!trans)
+ return IRQ_NONE;
+
+ trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+
+ /* 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(bus(trans), CSR_INT_MASK); /* just for debug */
+ iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000);
+
+ /* Discover which interrupts are active/pending */
+ inta = iwl_read32(bus(trans), CSR_INT);
+
+ /* 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. */
+ if (!inta) {
+ IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
+ goto none;
+ }
+
+ if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+ /* Hardware disappeared. It might have already raised
+ * an interrupt */
+ IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+ goto unplugged;
+ }
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
+ inta_fh = iwl_read32(bus(trans), CSR_FH_INT_STATUS);
+ IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, "
+ "fh 0x%08x\n", inta, inta_mask, inta_fh);
+ }
+#endif
+
+ trans_pcie->inta |= inta;
+ /* iwl_irq_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->shrd->status) &&
+ !trans_pcie->inta)
+ iwl_enable_interrupts(trans);
+
+ unplugged:
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+ return IRQ_HANDLED;
+
+ none:
+ /* re-enable interrupts here since we don't have anything to service. */
+ /* only Re-enable if disabled by irq and no schedules tasklet. */
+ if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+ !trans_pcie->inta)
+ iwl_enable_interrupts(trans);
+
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+ return IRQ_NONE;
+}
+
+/* interrupt handler using ict table, with this interrupt driver will
+ * stop using INTA register to get device's interrupt, reading this register
+ * is expensive, device will write interrupts in ICT dram table, increment
+ * index then will fire interrupt to driver, driver will OR all ICT table
+ * entries from current index up to table entry with 0 value. the result is
+ * 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)
+{
+ struct iwl_trans *trans = data;
+ struct iwl_trans_pcie *trans_pcie;
+ u32 inta, inta_mask;
+ u32 val = 0;
+ unsigned long flags;
+
+ if (!trans)
+ return IRQ_NONE;
+
+ trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ /* dram interrupt table not set yet,
+ * use legacy interrupt.
+ */
+ if (!trans_pcie->use_ict)
+ return iwl_isr(irq, data);
+
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+
+ /* 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(bus(trans), CSR_INT_MASK); /* just for debug */
+ iwl_write32(bus(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. */
+ if (!trans_pcie->ict_tbl[trans_pcie->ict_index]) {
+ IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
+ goto none;
+ }
+
+ /* read all entries that not 0 start with ict_index */
+ while (trans_pcie->ict_tbl[trans_pcie->ict_index]) {
+
+ val |= le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+ IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
+ trans_pcie->ict_index,
+ le32_to_cpu(
+ trans_pcie->ict_tbl[trans_pcie->ict_index]));
+ trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
+ trans_pcie->ict_index =
+ iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
+
+ }
+
+ /* We should not get this value, just ignore it. */
+ if (val == 0xffffffff)
+ val = 0;
+
+ /*
+ * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
+ * (bit 15 before shifting it to 31) to clear when using interrupt
+ * coalescing. fortunately, bits 18 and 19 stay set when this happens
+ * so we use them to decide on the real state of the Rx bit.
+ * In order words, bit 15 is set if bit 18 or bit 19 are set.
+ */
+ if (val & 0xC0000)
+ val |= 0x8000;
+
+ inta = (0xff & val) | ((0xff00 & val) << 16);
+ IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
+ inta, inta_mask, val);
+
+ inta &= trans_pcie->inta_mask;
+ trans_pcie->inta |= inta;
+
+ /* iwl_irq_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->shrd->status) &&
+ !trans_pcie->inta) {
+ /* Allow interrupt if was disabled by this handler and
+ * no tasklet was schedules, We should not enable interrupt,
+ * tasklet will enable it.
+ */
+ iwl_enable_interrupts(trans);
+ }
+
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+ return IRQ_HANDLED;
+
+ none:
+ /* re-enable interrupts here since we don't have anything to service.
+ * only Re-enable if disabled by irq.
+ */
+ if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+ !trans_pcie->inta)
+ iwl_enable_interrupts(trans);
+
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+ return IRQ_NONE;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
index 222d410c586e..4a0c95302a7e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
@@ -29,34 +29,42 @@
#include <linux/etherdevice.h>
#include <linux/slab.h>
#include <linux/sched.h>
-#include <net/mac80211.h>
-#include "iwl-agn.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
+#include "iwl-debug.h"
+#include "iwl-csr.h"
+#include "iwl-prph.h"
#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-trans-int-pcie.h"
+#include "iwl-agn-hw.h"
+#include "iwl-trans-pcie-int.h"
+
+#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
*/
-void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
struct iwl_tx_queue *txq,
u16 byte_cnt)
{
- struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
+ struct iwlagn_scd_bc_tbl *scd_bc_tbl;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
int write_ptr = txq->q.write_ptr;
int txq_id = txq->q.id;
u8 sec_ctl = 0;
u8 sta_id = 0;
u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
__le16 bc_ent;
+ struct iwl_tx_cmd *tx_cmd =
+ (struct iwl_tx_cmd *) txq->cmd[txq->q.write_ptr]->payload;
+
+ scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
- sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
- sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
+ sta_id = tx_cmd->sta_id;
+ sec_ctl = tx_cmd->sec_ctl;
switch (sec_ctl & TX_CMD_SEC_MSK) {
case TX_CMD_SEC_CCM:
@@ -82,7 +90,7 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
/**
* iwl_txq_update_write_ptr - Send new write index to hardware
*/
-void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
{
u32 reg = 0;
int txq_id = txq->q.id;
@@ -90,28 +98,28 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
if (txq->need_update == 0)
return;
- if (priv->cfg->base_params->shadow_reg_enable) {
+ if (hw_params(trans).shadow_reg_enable) {
/* shadow register enabled */
- iwl_write32(priv, HBUS_TARG_WRPTR,
+ iwl_write32(bus(trans), HBUS_TARG_WRPTR,
txq->q.write_ptr | (txq_id << 8));
} else {
/* if we're trying to save power */
- if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+ if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) {
/* wake up nic if it's powered down ...
* uCode will wake up, and interrupt us again, so next
* time we'll skip this part. */
- reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+ reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1);
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
- IWL_DEBUG_INFO(priv,
+ IWL_DEBUG_INFO(trans,
"Tx queue %d requesting wakeup,"
" GP1 = 0x%x\n", txq_id, reg);
- iwl_set_bit(priv, CSR_GP_CNTRL,
+ iwl_set_bit(bus(trans), CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
return;
}
- iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+ iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
txq->q.write_ptr | (txq_id << 8));
/*
@@ -120,7 +128,7 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
* trying to tx (during RFKILL, we're not trying to tx).
*/
} else
- iwl_write32(priv, HBUS_TARG_WRPTR,
+ iwl_write32(bus(trans), HBUS_TARG_WRPTR,
txq->q.write_ptr | (txq_id << 8));
}
txq->need_update = 0;
@@ -165,7 +173,7 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
return tfd->num_tbs & 0x1f;
}
-static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
+static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
struct iwl_tfd *tfd, enum dma_data_direction dma_dir)
{
int i;
@@ -175,56 +183,59 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
num_tbs = iwl_tfd_get_num_tbs(tfd);
if (num_tbs >= IWL_NUM_OF_TBS) {
- IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
+ IWL_ERR(trans, "Too many chunks: %i\n", num_tbs);
/* @todo issue fatal error, it is quite serious situation */
return;
}
/* Unmap tx_cmd */
if (num_tbs)
- dma_unmap_single(priv->bus->dev,
+ dma_unmap_single(bus(trans)->dev,
dma_unmap_addr(meta, mapping),
dma_unmap_len(meta, len),
DMA_BIDIRECTIONAL);
/* Unmap chunks, if any. */
for (i = 1; i < num_tbs; i++)
- dma_unmap_single(priv->bus->dev, iwl_tfd_tb_get_addr(tfd, i),
+ dma_unmap_single(bus(trans)->dev, iwl_tfd_tb_get_addr(tfd, i),
iwl_tfd_tb_get_len(tfd, i), dma_dir);
}
/**
* iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
- * @priv - driver private data
+ * @trans - transport private data
* @txq - tx queue
* @index - the index of the TFD to be freed
+ *@dma_dir - the direction of the DMA mapping
*
* Does NOT advance any TFD circular buffer read/write indexes
* Does NOT free the TFD itself (which is within circular buffer)
*/
-void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
- int index)
+void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
+ int index, enum dma_data_direction dma_dir)
{
struct iwl_tfd *tfd_tmp = txq->tfds;
- iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index],
- DMA_TO_DEVICE);
+ iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], dma_dir);
/* free SKB */
- if (txq->txb) {
+ if (txq->skbs) {
struct sk_buff *skb;
- skb = txq->txb[index].skb;
+ skb = txq->skbs[index];
- /* can be called from irqs-disabled context */
+ /* Can be called from irqs-disabled context
+ * If skb is not NULL, it means that the whole queue is being
+ * freed and that the queue is not empty - free the skb
+ */
if (skb) {
- dev_kfree_skb_any(skb);
- txq->txb[index].skb = NULL;
+ iwl_free_skb(priv(trans), skb);
+ txq->skbs[index] = NULL;
}
}
}
-int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
struct iwl_tx_queue *txq,
dma_addr_t addr, u16 len,
u8 reset)
@@ -244,7 +255,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
/* Each TFD can point to a maximum 20 Tx buffers */
if (num_tbs >= IWL_NUM_OF_TBS) {
- IWL_ERR(priv, "Error can not send more than %d chunks\n",
+ IWL_ERR(trans, "Error can not send more than %d chunks\n",
IWL_NUM_OF_TBS);
return -EINVAL;
}
@@ -253,7 +264,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
return -EINVAL;
if (unlikely(addr & ~IWL_TX_DMA_MASK))
- IWL_ERR(priv, "Unaligned address = %llx\n",
+ IWL_ERR(trans, "Unaligned address = %llx\n",
(unsigned long long)addr);
iwl_tfd_set_tb(tfd, num_tbs, addr, len);
@@ -302,8 +313,7 @@ int iwl_queue_space(const struct iwl_queue *q)
/**
* iwl_queue_init - Initialize queue's high/low-water and read/write indexes
*/
-int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
- int count, int slots_num, u32 id)
+int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)
{
q->n_bd = count;
q->n_window = slots_num;
@@ -332,25 +342,23 @@ int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
return 0;
}
-/*TODO: this functions should NOT be exported from trans module - export it
- * until the reclaim flow will be brought to the transport module too.
- * Add a declaration to make sparse happy */
-void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
- struct iwl_tx_queue *txq);
-
-void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
+static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
struct iwl_tx_queue *txq)
{
- struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
+ 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 =
+ (struct iwl_tx_cmd *) txq->cmd[txq->q.read_ptr]->payload;
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
- if (txq_id != priv->cmd_queue)
- sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
+ if (txq_id != trans->shrd->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;
@@ -360,56 +368,61 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
}
-static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
+static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid,
u16 txq_id)
{
u32 tbl_dw_addr;
u32 tbl_dw;
u16 scd_q2ratid;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK;
- tbl_dw_addr = priv->scd_base_addr +
+ tbl_dw_addr = trans_pcie->scd_base_addr +
SCD_TRANS_TBL_OFFSET_QUEUE(txq_id);
- tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr);
+ tbl_dw = iwl_read_targ_mem(bus(trans), tbl_dw_addr);
if (txq_id & 0x1)
tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
else
tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
- iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
+ iwl_write_targ_mem(bus(trans), tbl_dw_addr, tbl_dw);
return 0;
}
-static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)
+static void iwlagn_tx_queue_stop_scheduler(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. */
- iwl_write_prph(priv,
+ iwl_write_prph(bus(trans),
SCD_QUEUE_STATUS_BITS(txq_id),
(0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
(1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
}
-void iwl_trans_set_wr_ptrs(struct iwl_priv *priv,
+void iwl_trans_set_wr_ptrs(struct iwl_trans *trans,
int txq_id, u32 index)
{
- iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+ iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
(index & 0xff) | (txq_id << 8));
- iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index);
+ iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index);
}
-void iwl_trans_tx_queue_set_status(struct iwl_priv *priv,
+void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
struct iwl_tx_queue *txq,
int tx_fifo_id, int scd_retry)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int txq_id = txq->q.id;
- int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
+ int active =
+ test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0;
- iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id),
+ iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id),
(active << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
(tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) |
(1 << SCD_QUEUE_STTS_REG_POS_WSL) |
@@ -417,55 +430,75 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv,
txq->sched_retry = scd_retry;
- IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n",
+ IWL_DEBUG_INFO(trans, "%s %s Queue %d on FIFO %d\n",
active ? "Activate" : "Deactivate",
scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
}
-void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid,
- int frame_limit)
+static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie,
+ u8 ctx, u16 tid)
+{
+ const u8 *ac_to_fifo = trans_pcie->ac_to_fifo[ctx];
+ if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+ return ac_to_fifo[tid_to_ac[tid]];
+
+ /* no support for TIDs 8-15 yet */
+ return -EINVAL;
+}
+
+void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx, int sta_id,
+ int tid, int frame_limit)
{
int tx_fifo, txq_id, ssn_idx;
u16 ra_tid;
unsigned long flags;
struct iwl_tid_data *tid_data;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
if (WARN_ON(sta_id == IWL_INVALID_STATION))
return;
- if (WARN_ON(tid >= MAX_TID_COUNT))
+ if (WARN_ON(tid >= IWL_MAX_TID_COUNT))
return;
- spin_lock_irqsave(&priv->sta_lock, flags);
- tid_data = &priv->stations[sta_id].tid[tid];
+ tx_fifo = get_fifo_from_tid(trans_pcie, ctx, tid);
+ if (WARN_ON(tx_fifo < 0)) {
+ IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo);
+ return;
+ }
+
+ spin_lock_irqsave(&trans->shrd->sta_lock, flags);
+ tid_data = &trans->shrd->tid_data[sta_id][tid];
ssn_idx = SEQ_TO_SN(tid_data->seq_number);
txq_id = tid_data->agg.txq_id;
- tx_fifo = tid_data->agg.tx_fifo;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
ra_tid = BUILD_RAxTID(sta_id, tid);
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&trans->shrd->lock, flags);
/* Stop this Tx queue before configuring it */
- iwlagn_tx_queue_stop_scheduler(priv, txq_id);
+ iwlagn_tx_queue_stop_scheduler(trans, txq_id);
/* Map receiver-address / traffic-ID to this queue */
- iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
+ iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id);
/* Set this queue as a chain-building queue */
- iwl_set_bits_prph(priv, SCD_QUEUECHAIN_SEL, (1<<txq_id));
+ iwl_set_bits_prph(bus(trans), SCD_QUEUECHAIN_SEL, (1<<txq_id));
/* enable aggregations for the queue */
- iwl_set_bits_prph(priv, SCD_AGGR_SEL, (1<<txq_id));
+ iwl_set_bits_prph(bus(trans), SCD_AGGR_SEL, (1<<txq_id));
/* Place first TFD at index corresponding to start sequence number.
* Assumes that ssn_idx is valid (!= 0xFFF) */
- priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
- priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
- iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx);
+ trans_pcie->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+ trans_pcie->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+ iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx);
/* Set up Tx window size and frame limit for this queue */
- iwl_write_targ_mem(priv, priv->scd_base_addr +
+ iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
sizeof(u32),
((frame_limit <<
@@ -475,40 +508,161 @@ void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid,
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
- iwl_set_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id));
+ iwl_set_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
- iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
+ iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id],
+ tx_fifo, 1);
+
+ trans_pcie->txq[txq_id].sta_id = sta_id;
+ trans_pcie->txq[txq_id].tid = tid;
+
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+}
- spin_unlock_irqrestore(&priv->lock, flags);
+/*
+ * Find first available (lowest unused) Tx Queue, mark it "active".
+ * Called only when finding queue for aggregation.
+ * Should never return anything < 7, because they should already
+ * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
+ */
+static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ int txq_id;
+
+ for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
+ if (!test_and_set_bit(txq_id,
+ &trans_pcie->txq_ctx_active_msk))
+ return txq_id;
+ return -1;
}
-int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
- u16 ssn_idx, u8 tx_fifo)
+int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx, int sta_id,
+ int tid, u16 *ssn)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_tid_data *tid_data;
+ unsigned long flags;
+ int txq_id;
+
+ txq_id = iwlagn_txq_ctx_activate_free(trans);
+ if (txq_id == -1) {
+ IWL_ERR(trans, "No free aggregation queue available\n");
+ return -ENXIO;
+ }
+
+ spin_lock_irqsave(&trans->shrd->sta_lock, flags);
+ tid_data = &trans->shrd->tid_data[sta_id][tid];
+ *ssn = SEQ_TO_SN(tid_data->seq_number);
+ tid_data->agg.txq_id = txq_id;
+ iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id);
+
+ tid_data = &trans->shrd->tid_data[sta_id][tid];
+ if (tid_data->tfds_in_queue == 0) {
+ IWL_DEBUG_HT(trans, "HW queue is empty\n");
+ tid_data->agg.state = IWL_AGG_ON;
+ iwl_start_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
+ } else {
+ IWL_DEBUG_HT(trans, "HW queue is NOT empty: %d packets in HW"
+ "queue\n", tid_data->tfds_in_queue);
+ tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
+ }
+ spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
+
+ return 0;
+}
+
+void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ iwlagn_tx_queue_stop_scheduler(trans, txq_id);
+
+ iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id));
+
+ trans_pcie->txq[txq_id].q.read_ptr = 0;
+ trans_pcie->txq[txq_id].q.write_ptr = 0;
+ /* supposes that ssn_idx is valid (!= 0xFFF) */
+ iwl_trans_set_wr_ptrs(trans, txq_id, 0);
+
+ iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
+ iwl_txq_ctx_deactivate(trans_pcie, txq_id);
+ iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0);
+}
+
+int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx, int sta_id,
+ int tid)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ unsigned long flags;
+ int read_ptr, write_ptr;
+ struct iwl_tid_data *tid_data;
+ int txq_id;
+
+ spin_lock_irqsave(&trans->shrd->sta_lock, flags);
+
+ tid_data = &trans->shrd->tid_data[sta_id][tid];
+ txq_id = tid_data->agg.txq_id;
+
if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
(IWLAGN_FIRST_AMPDU_QUEUE +
- priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
- IWL_ERR(priv,
+ hw_params(trans).num_ampdu_queues <= txq_id)) {
+ IWL_ERR(trans,
"queue number out of range: %d, must be %d to %d\n",
txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
IWLAGN_FIRST_AMPDU_QUEUE +
- priv->cfg->base_params->num_of_ampdu_queues - 1);
+ hw_params(trans).num_ampdu_queues - 1);
+ spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
return -EINVAL;
}
- iwlagn_tx_queue_stop_scheduler(priv, txq_id);
+ switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
+ case IWL_EMPTYING_HW_QUEUE_ADDBA:
+ /*
+ * This can happen if the peer stops aggregation
+ * again before we've had a chance to drain the
+ * queue we selected previously, i.e. before the
+ * session was really started completely.
+ */
+ IWL_DEBUG_HT(trans, "AGG stop before setup done\n");
+ goto turn_off;
+ case IWL_AGG_ON:
+ break;
+ default:
+ IWL_WARN(trans, "Stopping AGG while state not ON "
+ "or starting for %d on %d (%d)\n", sta_id, tid,
+ trans->shrd->tid_data[sta_id][tid].agg.state);
+ spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
+ return 0;
+ }
- iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id));
+ write_ptr = trans_pcie->txq[txq_id].q.write_ptr;
+ read_ptr = trans_pcie->txq[txq_id].q.read_ptr;
- priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
- priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
- /* supposes that ssn_idx is valid (!= 0xFFF) */
- iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx);
+ /* The queue is not empty */
+ if (write_ptr != read_ptr) {
+ IWL_DEBUG_HT(trans, "Stopping a non empty AGG HW QUEUE\n");
+ trans->shrd->tid_data[sta_id][tid].agg.state =
+ IWL_EMPTYING_HW_QUEUE_DELBA;
+ spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
+ return 0;
+ }
+
+ IWL_DEBUG_HT(trans, "HW queue is empty\n");
+turn_off:
+ trans->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
+
+ /* do not restore/save irqs */
+ spin_unlock(&trans->shrd->sta_lock);
+ spin_lock(&trans->shrd->lock);
- iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id));
- iwl_txq_ctx_deactivate(priv, txq_id);
- iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
+ iwl_trans_pcie_txq_agg_disable(trans, txq_id);
+
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+ iwl_stop_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
return 0;
}
@@ -524,9 +678,10 @@ int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
* failed. On success, it turns the index (> 0) of command in the
* command queue.
*/
-static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{
- struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
struct iwl_queue *q = &txq->q;
struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta;
@@ -544,14 +699,14 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
int trace_idx;
#endif
- if (test_bit(STATUS_FW_ERROR, &priv->status)) {
- IWL_WARN(priv, "fw recovery, no hcmd send\n");
+ if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
+ IWL_WARN(trans, "fw recovery, no hcmd send\n");
return -EIO;
}
- if ((priv->ucode_owner == IWL_OWNERSHIP_TM) &&
+ if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) &&
!(cmd->flags & CMD_ON_DEMAND)) {
- IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n");
+ IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n");
return -EIO;
}
@@ -584,22 +739,22 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
return -EINVAL;
- if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
- IWL_WARN(priv, "Not sending command - %s KILL\n",
- iwl_is_rfkill(priv) ? "RF" : "CT");
+ if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) {
+ IWL_WARN(trans, "Not sending command - %s KILL\n",
+ iwl_is_rfkill(trans->shrd) ? "RF" : "CT");
return -EIO;
}
- spin_lock_irqsave(&priv->hcmd_lock, flags);
+ spin_lock_irqsave(&trans->hcmd_lock, flags);
if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
- spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+ spin_unlock_irqrestore(&trans->hcmd_lock, flags);
- IWL_ERR(priv, "No space in command queue\n");
- is_ct_kill = iwl_check_for_ct_kill(priv);
+ IWL_ERR(trans, "No space in command queue\n");
+ is_ct_kill = iwl_check_for_ct_kill(priv(trans));
if (!is_ct_kill) {
- IWL_ERR(priv, "Restarting adapter due to queue full\n");
- iwlagn_fw_error(priv, false);
+ IWL_ERR(trans, "Restarting adapter queue is full\n");
+ iwlagn_fw_error(priv(trans), false);
}
return -ENOSPC;
}
@@ -611,19 +766,18 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
if (cmd->flags & CMD_WANT_SKB)
out_meta->source = cmd;
- if (cmd->flags & CMD_ASYNC)
- out_meta->callback = cmd->callback;
/* set up the header */
out_cmd->hdr.cmd = cmd->id;
out_cmd->hdr.flags = 0;
- out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) |
- INDEX_TO_SEQ(q->write_ptr));
+ out_cmd->hdr.sequence =
+ cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) |
+ INDEX_TO_SEQ(q->write_ptr));
/* and copy the data that needs to be copied */
- cmd_dest = &out_cmd->cmd.payload[0];
+ cmd_dest = out_cmd->payload;
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
if (!cmd->len[i])
continue;
@@ -633,16 +787,16 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
cmd_dest += cmd->len[i];
}
- IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
+ IWL_DEBUG_HC(trans, "Sending command %s (#%x), seq: 0x%04X, "
"%d bytes at %d[%d]:%d\n",
get_cmd_string(out_cmd->hdr.cmd),
out_cmd->hdr.cmd,
le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
- q->write_ptr, idx, priv->cmd_queue);
+ q->write_ptr, idx, trans->shrd->cmd_queue);
- phys_addr = dma_map_single(priv->bus->dev, &out_cmd->hdr, copy_size,
+ phys_addr = dma_map_single(bus(trans)->dev, &out_cmd->hdr, copy_size,
DMA_BIDIRECTIONAL);
- if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) {
+ if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) {
idx = -ENOMEM;
goto out;
}
@@ -650,7 +804,8 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, 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(priv, txq, phys_addr, copy_size, 1);
+ iwlagn_txq_attach_buf_to_tfd(trans, txq,
+ phys_addr, copy_size, 1);
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
trace_bufs[0] = &out_cmd->hdr;
trace_lens[0] = copy_size;
@@ -662,17 +817,18 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
continue;
if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
continue;
- phys_addr = dma_map_single(priv->bus->dev, (void *)cmd->data[i],
+ phys_addr = dma_map_single(bus(trans)->dev,
+ (void *)cmd->data[i],
cmd->len[i], DMA_BIDIRECTIONAL);
- if (dma_mapping_error(priv->bus->dev, phys_addr)) {
- iwlagn_unmap_tfd(priv, out_meta,
+ if (dma_mapping_error(bus(trans)->dev, phys_addr)) {
+ iwlagn_unmap_tfd(trans, out_meta,
&txq->tfds[q->write_ptr],
DMA_BIDIRECTIONAL);
idx = -ENOMEM;
goto out;
}
- iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr,
+ iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
cmd->len[i], 0);
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
trace_bufs[trace_idx] = cmd->data[i];
@@ -688,7 +844,7 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
/* check that tracing gets all possible blocks */
BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
- trace_iwlwifi_dev_hcmd(priv, cmd->flags,
+ trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags,
trace_bufs[0], trace_lens[0],
trace_bufs[1], trace_lens[1],
trace_bufs[2], trace_lens[2]);
@@ -696,10 +852,10 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, 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(priv, txq);
+ iwl_txq_update_write_ptr(trans, txq);
out:
- spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+ spin_unlock_irqrestore(&trans->hcmd_lock, flags);
return idx;
}
@@ -710,14 +866,16 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
* 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_priv *priv, int txq_id, int idx)
+static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
+ int idx)
{
- struct iwl_tx_queue *txq = &priv->txq[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 nfreed = 0;
if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
- IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), "
+ 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;
@@ -727,9 +885,9 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
if (nfreed++ > 0) {
- IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx,
+ IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", idx,
q->write_ptr, q->read_ptr);
- iwlagn_fw_error(priv, false);
+ iwlagn_fw_error(priv(trans), false);
}
}
@@ -738,12 +896,15 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
/**
* iwl_tx_cmd_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)
*
* If an Rx buffer has an async callback associated with it the callback
* will be executed. The attached skb (if present) will only be freed
* if the callback returns 1
*/
-void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
+ int handler_status)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
@@ -752,18 +913,19 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
int cmd_index;
struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta;
- struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
unsigned long flags;
/* 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
* in the queue management code. */
- if (WARN(txq_id != priv->cmd_queue,
+ if (WARN(txq_id != trans->shrd->cmd_queue,
"wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
- txq_id, priv->cmd_queue, sequence,
- priv->txq[priv->cmd_queue].q.read_ptr,
- priv->txq[priv->cmd_queue].q.write_ptr)) {
- iwl_print_hex_error(priv, pkt, 32);
+ txq_id, trans->shrd->cmd_queue, sequence,
+ trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr,
+ trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) {
+ iwl_print_hex_error(trans, pkt, 32);
return;
}
@@ -773,140 +935,40 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
txq->time_stamp = jiffies;
- iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
+ iwlagn_unmap_tfd(trans, meta, &txq->tfds[index],
+ DMA_BIDIRECTIONAL);
/* Input error checking is done when commands are added to queue. */
if (meta->flags & CMD_WANT_SKB) {
meta->source->reply_page = (unsigned long)rxb_addr(rxb);
+ meta->source->handler_status = handler_status;
rxb->page = NULL;
- } else if (meta->callback)
- meta->callback(priv, cmd, pkt);
+ }
- spin_lock_irqsave(&priv->hcmd_lock, flags);
+ spin_lock_irqsave(&trans->hcmd_lock, flags);
- iwl_hcmd_queue_reclaim(priv, txq_id, index);
+ iwl_hcmd_queue_reclaim(trans, txq_id, index);
if (!(meta->flags & CMD_ASYNC)) {
- clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
- IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
+ if (!test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) {
+ IWL_WARN(trans,
+ "HCMD_ACTIVE already clear for command %s\n",
+ get_cmd_string(cmd->hdr.cmd));
+ }
+ clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+ IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
get_cmd_string(cmd->hdr.cmd));
- wake_up_interruptible(&priv->wait_command_queue);
+ wake_up(&trans->shrd->wait_command_queue);
}
meta->flags = 0;
- spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-}
-
-const char *get_cmd_string(u8 cmd)
-{
- switch (cmd) {
- IWL_CMD(REPLY_ALIVE);
- IWL_CMD(REPLY_ERROR);
- IWL_CMD(REPLY_RXON);
- IWL_CMD(REPLY_RXON_ASSOC);
- IWL_CMD(REPLY_QOS_PARAM);
- IWL_CMD(REPLY_RXON_TIMING);
- IWL_CMD(REPLY_ADD_STA);
- IWL_CMD(REPLY_REMOVE_STA);
- IWL_CMD(REPLY_REMOVE_ALL_STA);
- IWL_CMD(REPLY_TXFIFO_FLUSH);
- IWL_CMD(REPLY_WEPKEY);
- IWL_CMD(REPLY_TX);
- IWL_CMD(REPLY_LEDS_CMD);
- IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
- IWL_CMD(COEX_PRIORITY_TABLE_CMD);
- IWL_CMD(COEX_MEDIUM_NOTIFICATION);
- IWL_CMD(COEX_EVENT_CMD);
- IWL_CMD(REPLY_QUIET_CMD);
- IWL_CMD(REPLY_CHANNEL_SWITCH);
- IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
- IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
- IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
- IWL_CMD(POWER_TABLE_CMD);
- IWL_CMD(PM_SLEEP_NOTIFICATION);
- IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
- IWL_CMD(REPLY_SCAN_CMD);
- IWL_CMD(REPLY_SCAN_ABORT_CMD);
- IWL_CMD(SCAN_START_NOTIFICATION);
- IWL_CMD(SCAN_RESULTS_NOTIFICATION);
- IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
- IWL_CMD(BEACON_NOTIFICATION);
- IWL_CMD(REPLY_TX_BEACON);
- IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
- IWL_CMD(QUIET_NOTIFICATION);
- IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
- IWL_CMD(MEASURE_ABORT_NOTIFICATION);
- IWL_CMD(REPLY_BT_CONFIG);
- IWL_CMD(REPLY_STATISTICS_CMD);
- IWL_CMD(STATISTICS_NOTIFICATION);
- IWL_CMD(REPLY_CARD_STATE_CMD);
- IWL_CMD(CARD_STATE_NOTIFICATION);
- IWL_CMD(MISSED_BEACONS_NOTIFICATION);
- IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
- IWL_CMD(SENSITIVITY_CMD);
- IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
- IWL_CMD(REPLY_RX_PHY_CMD);
- IWL_CMD(REPLY_RX_MPDU_CMD);
- IWL_CMD(REPLY_RX);
- IWL_CMD(REPLY_COMPRESSED_BA);
- IWL_CMD(CALIBRATION_CFG_CMD);
- IWL_CMD(CALIBRATION_RES_NOTIFICATION);
- IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
- IWL_CMD(REPLY_TX_POWER_DBM_CMD);
- IWL_CMD(TEMPERATURE_NOTIFICATION);
- IWL_CMD(TX_ANT_CONFIGURATION_CMD);
- IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
- IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
- IWL_CMD(REPLY_BT_COEX_PROT_ENV);
- IWL_CMD(REPLY_WIPAN_PARAMS);
- IWL_CMD(REPLY_WIPAN_RXON);
- IWL_CMD(REPLY_WIPAN_RXON_TIMING);
- IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
- IWL_CMD(REPLY_WIPAN_QOS_PARAM);
- IWL_CMD(REPLY_WIPAN_WEPKEY);
- IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
- IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
- IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
- IWL_CMD(REPLY_WOWLAN_PATTERNS);
- IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER);
- IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS);
- IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS);
- IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL);
- IWL_CMD(REPLY_WOWLAN_GET_STATUS);
- default:
- return "UNKNOWN";
-
- }
+ spin_unlock_irqrestore(&trans->hcmd_lock, flags);
}
#define HOST_COMPLETE_TIMEOUT (2 * HZ)
-static void iwl_generic_cmd_callback(struct iwl_priv *priv,
- struct iwl_device_cmd *cmd,
- struct iwl_rx_packet *pkt)
-{
- if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
- get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
- return;
- }
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- switch (cmd->hdr.cmd) {
- case REPLY_TX_LINK_QUALITY_CMD:
- case SENSITIVITY_CMD:
- IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n",
- get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
- break;
- default:
- IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n",
- get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
- }
-#endif
-}
-
-static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{
int ret;
@@ -914,81 +976,83 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (WARN_ON(cmd->flags & CMD_WANT_SKB))
return -EINVAL;
- /* Assign a generic callback if one is not provided */
- if (!cmd->callback)
- cmd->callback = iwl_generic_cmd_callback;
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
return -EBUSY;
- ret = iwl_enqueue_hcmd(priv, cmd);
+ ret = iwl_enqueue_hcmd(trans, cmd);
if (ret < 0) {
- IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
+ IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret);
return ret;
}
return 0;
}
-static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl_send_cmd_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;
- lockdep_assert_held(&priv->mutex);
+ lockdep_assert_held(&trans->shrd->mutex);
- /* A synchronous command can not have a callback set. */
- if (WARN_ON(cmd->callback))
- return -EINVAL;
-
- IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
+ IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
get_cmd_string(cmd->id));
- set_bit(STATUS_HCMD_ACTIVE, &priv->status);
- IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
+ set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+ IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
get_cmd_string(cmd->id));
- cmd_idx = iwl_enqueue_hcmd(priv, cmd);
+ cmd_idx = iwl_enqueue_hcmd(trans, cmd);
if (cmd_idx < 0) {
ret = cmd_idx;
- clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
- IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
+ clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+ IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret);
return ret;
}
- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
- !test_bit(STATUS_HCMD_ACTIVE, &priv->status),
+ ret = wait_event_timeout(trans->shrd->wait_command_queue,
+ !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status),
HOST_COMPLETE_TIMEOUT);
if (!ret) {
- if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
- IWL_ERR(priv,
+ if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) {
+ struct iwl_tx_queue *txq =
+ &trans_pcie->txq[trans->shrd->cmd_queue];
+ struct iwl_queue *q = &txq->q;
+
+ IWL_ERR(trans,
"Error sending %s: time out after %dms.\n",
get_cmd_string(cmd->id),
jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
- clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
- IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command"
+ IWL_ERR(trans,
+ "Current CMD queue read_ptr %d write_ptr %d\n",
+ q->read_ptr, q->write_ptr);
+
+ clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+ IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command"
"%s\n", get_cmd_string(cmd->id));
ret = -ETIMEDOUT;
goto cancel;
}
}
- if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
- IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n",
+ if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) {
+ IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n",
get_cmd_string(cmd->id));
ret = -ECANCELED;
goto fail;
}
- if (test_bit(STATUS_FW_ERROR, &priv->status)) {
- IWL_ERR(priv, "Command %s failed: FW Error\n",
+ if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
+ IWL_ERR(trans, "Command %s failed: FW Error\n",
get_cmd_string(cmd->id));
ret = -EIO;
goto fail;
}
if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
- IWL_ERR(priv, "Error: Response NULL in '%s'\n",
+ IWL_ERR(trans, "Error: Response NULL in '%s'\n",
get_cmd_string(cmd->id));
ret = -EIO;
goto cancel;
@@ -1004,35 +1068,74 @@ cancel:
* in later, it will possibly set an invalid
* address (cmd->meta.source).
*/
- priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
+ trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &=
~CMD_WANT_SKB;
}
fail:
if (cmd->reply_page) {
- iwl_free_pages(priv, cmd->reply_page);
+ iwl_free_pages(trans->shrd, cmd->reply_page);
cmd->reply_page = 0;
}
return ret;
}
-int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{
if (cmd->flags & CMD_ASYNC)
- return iwl_send_cmd_async(priv, cmd);
+ return iwl_send_cmd_async(trans, cmd);
- return iwl_send_cmd_sync(priv, cmd);
+ return iwl_send_cmd_sync(trans, cmd);
}
-int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len,
- const void *data)
+/* 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)
{
- struct iwl_host_cmd cmd = {
- .id = id,
- .len = { len, },
- .data = { data, },
- .flags = flags,
- };
-
- return iwl_send_cmd(priv, &cmd);
+ 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;
+
+ /* This function is not meant to release cmd queue*/
+ if (WARN_ON(txq_id == trans->shrd->cmd_queue))
+ return 0;
+
+ /*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);
+
+ 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;
+ }
+
+ IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id,
+ q->read_ptr, index);
+
+ if (WARN_ON(!skb_queue_empty(skbs)))
+ return 0;
+
+ for (;
+ q->read_ptr != index;
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+ if (WARN_ON_ONCE(txq->skbs[txq->q.read_ptr] == NULL))
+ continue;
+
+ __skb_queue_tail(skbs, txq->skbs[txq->q.read_ptr]);
+
+ txq->skbs[txq->q.read_ptr] = NULL;
+
+ iwlagn_txq_inval_byte_cnt_tbl(trans, txq);
+
+ iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr, DMA_TO_DEVICE);
+ freed++;
+ }
+ return freed;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
new file mode 100644
index 000000000000..8e8c75c997ee
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -0,0 +1,1998 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#include <linux/interrupt.h>
+#include <linux/debugfs.h>
+#include <linux/bitops.h>
+#include <linux/gfp.h>
+
+#include "iwl-trans.h"
+#include "iwl-trans-pcie-int.h"
+#include "iwl-csr.h"
+#include "iwl-prph.h"
+#include "iwl-shared.h"
+#include "iwl-eeprom.h"
+#include "iwl-agn-hw.h"
+
+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 = bus(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_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
+ &rxq->bd_dma, GFP_KERNEL);
+ if (!rxq->bd)
+ goto err_bd;
+ memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE);
+
+ /*Allocate the driver's pointer to receive buffer status */
+ rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts),
+ &rxq->rb_stts_dma, GFP_KERNEL);
+ if (!rxq->rb_stts)
+ goto err_rb_stts;
+ memset(rxq->rb_stts, 0, sizeof(*rxq->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(bus(trans)->dev, rxq->pool[i].page_dma,
+ PAGE_SIZE << hw_params(trans).rx_page_order,
+ DMA_FROM_DEVICE);
+ __free_pages(rxq->pool[i].page,
+ hw_params(trans).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)
+{
+ 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 (iwlagn_mod_params.amsdu_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(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+ /* Reset driver's Rx queue write index */
+ iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+
+ /* Tell device where to find RBD circular buffer in DRAM */
+ iwl_write_direct32(bus(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(bus(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(bus(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 |
+ FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
+ 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(bus(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);
+
+ iwlagn_rx_replenish(trans);
+
+ iwl_trans_rx_hw_init(trans, rxq);
+
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+ rxq->need_update = 1;
+ iwl_rx_queue_update_write_ptr(trans, rxq);
+ spin_unlock_irqrestore(&trans->shrd->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(bus(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(bus(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(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+ return iwl_poll_direct_bit(bus(trans), FH_MEM_RSSR_RX_STATUS_REG,
+ FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+}
+
+static inline 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(bus(trans)->dev, size,
+ &ptr->dma, GFP_KERNEL);
+ if (!ptr->addr)
+ return -ENOMEM;
+ ptr->size = size;
+ return 0;
+}
+
+static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans,
+ struct iwl_dma_ptr *ptr)
+{
+ if (unlikely(!ptr->addr))
+ return;
+
+ dma_free_coherent(bus(trans)->dev, ptr->size, ptr->addr, ptr->dma);
+ memset(ptr, 0, sizeof(*ptr));
+}
+
+static int iwl_trans_txq_alloc(struct iwl_trans *trans,
+ struct iwl_tx_queue *txq, int slots_num,
+ u32 txq_id)
+{
+ size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
+ int i;
+
+ if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds))
+ return -EINVAL;
+
+ txq->q.n_window = slots_num;
+
+ txq->meta = kcalloc(slots_num, sizeof(txq->meta[0]), GFP_KERNEL);
+ txq->cmd = kcalloc(slots_num, sizeof(txq->cmd[0]), GFP_KERNEL);
+
+ if (!txq->meta || !txq->cmd)
+ goto error;
+
+ if (txq_id == trans->shrd->cmd_queue)
+ for (i = 0; i < slots_num; i++) {
+ txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),
+ GFP_KERNEL);
+ if (!txq->cmd[i])
+ goto error;
+ }
+
+ /* Alloc driver data array and TFD circular buffer */
+ /* Driver private data, only for Tx (not command) queues,
+ * not shared with device. */
+ if (txq_id != trans->shrd->cmd_queue) {
+ txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->skbs[0]),
+ GFP_KERNEL);
+ if (!txq->skbs) {
+ IWL_ERR(trans, "kmalloc for auxiliary BD "
+ "structures failed\n");
+ goto error;
+ }
+ } else {
+ txq->skbs = NULL;
+ }
+
+ /* Circular buffer of transmit frame descriptors (TFDs),
+ * shared with device */
+ txq->tfds = dma_alloc_coherent(bus(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:
+ kfree(txq->skbs);
+ txq->skbs = NULL;
+ /* since txq->cmd has been zeroed,
+ * all non allocated cmd[i] will be NULL */
+ if (txq->cmd && txq_id == trans->shrd->cmd_queue)
+ for (i = 0; i < slots_num; i++)
+ kfree(txq->cmd[i]);
+ kfree(txq->meta);
+ kfree(txq->cmd);
+ txq->meta = NULL;
+ txq->cmd = 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;
+ memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num);
+
+ /*
+ * For the default queues 0-3, set up the swq_id
+ * already -- all others need to get one later
+ * (if they need one at all).
+ */
+ if (txq_id < 4)
+ iwl_set_swq_id(txq, txq_id, txq_id);
+
+ /* 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;
+
+ /*
+ * 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(bus(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;
+ unsigned long flags;
+
+ 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->shrd->cmd_queue)
+ dma_dir = DMA_BIDIRECTIONAL;
+ else
+ dma_dir = DMA_TO_DEVICE;
+
+ spin_lock_irqsave(&trans->shrd->sta_lock, flags);
+ while (q->write_ptr != q->read_ptr) {
+ /* The read_ptr needs to bound by q->n_window */
+ iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr),
+ dma_dir);
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
+ }
+ spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
+}
+
+/**
+ * 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 = bus(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->shrd->cmd_queue)
+ for (i = 0; i < txq->q.n_window; i++)
+ kfree(txq->cmd[i]);
+
+ /* 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));
+ }
+
+ /* De-alloc array of per-TFD driver data */
+ kfree(txq->skbs);
+ txq->skbs = NULL;
+
+ /* deallocate arrays */
+ kfree(txq->cmd);
+ kfree(txq->meta);
+ txq->cmd = NULL;
+ txq->meta = NULL;
+
+ /* 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 < hw_params(trans).max_txq_num; 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 = hw_params(trans).max_txq_num *
+ 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(hw_params(trans).max_txq_num,
+ 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 < hw_params(trans).max_txq_num; txq_id++) {
+ slots_num = (txq_id == trans->shrd->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)
+{
+ int ret;
+ int txq_id, slots_num;
+ unsigned long flags;
+ bool alloc = false;
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ if (!trans_pcie->txq) {
+ ret = iwl_trans_tx_alloc(trans);
+ if (ret)
+ goto error;
+ alloc = true;
+ }
+
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+
+ /* Turn off all Tx DMA fifos */
+ iwl_write_prph(bus(trans), SCD_TXFACT, 0);
+
+ /* Tell NIC where to find the "keep warm" buffer */
+ iwl_write_direct32(bus(trans), FH_KW_MEM_ADDR_REG,
+ trans_pcie->kw.dma >> 4);
+
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+ /* Alloc and init all Tx queues, including the command queue (#4/#9) */
+ for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
+ slots_num = (txq_id == trans->shrd->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)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do:
+
+ if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
+ iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG,
+ APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+ ~APMG_PS_CTRL_MSK_PWR_SRC);
+ */
+
+ iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG,
+ APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+ ~APMG_PS_CTRL_MSK_PWR_SRC);
+}
+
+static int iwl_nic_init(struct iwl_trans *trans)
+{
+ unsigned long flags;
+
+ /* nic_init */
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+ iwl_apm_init(priv(trans));
+
+ /* Set interrupt coalescing calibration timer to default (512 usecs) */
+ iwl_write8(bus(trans), CSR_INT_COALESCING,
+ IWL_HOST_INT_CALIB_TIMEOUT_DEF);
+
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+ iwl_set_pwr_vmain(trans);
+
+ iwl_nic_config(priv(trans));
+
+ /* Allocate the RX queue, or reset if it is already allocated */
+ iwl_rx_init(trans);
+
+ /* Allocate or reset and init all Tx and Command queues */
+ if (iwl_tx_init(trans))
+ return -ENOMEM;
+
+ if (hw_params(trans).shadow_reg_enable) {
+ /* enable shadow regs in HW */
+ iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL,
+ 0x800FFFFF);
+ }
+
+ set_bit(STATUS_INIT, &trans->shrd->status);
+
+ return 0;
+}
+
+#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)
+{
+ int ret;
+
+ iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
+
+ /* See if we got it */
+ ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+ CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+ HW_READY_TIMEOUT);
+
+ IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : "");
+ return ret;
+}
+
+/* Note: returns standard 0/-ERROR code */
+static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans)
+{
+ int ret;
+
+ IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
+
+ ret = iwl_set_hw_ready(trans);
+ if (ret >= 0)
+ return 0;
+
+ /* If HW is not ready, prepare the conditions to check again */
+ iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_PREPARE);
+
+ ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
+ ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
+ CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
+
+ if (ret < 0)
+ return ret;
+
+ /* HW should be ready by now, check again. */
+ ret = iwl_set_hw_ready(trans);
+ if (ret >= 0)
+ return 0;
+ return ret;
+}
+
+#define IWL_AC_UNSET -1
+
+struct queue_to_fifo_ac {
+ s8 fifo, ac;
+};
+
+static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = {
+ { IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
+ { IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
+ { IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
+ { IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
+ { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
+ { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+ { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+ { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+ { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+ { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+ { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+};
+
+static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = {
+ { IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
+ { IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
+ { IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
+ { IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
+ { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, },
+ { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, },
+ { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, },
+ { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, },
+ { IWL_TX_FIFO_BE_IPAN, 2, },
+ { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
+ { IWL_TX_FIFO_AUX, IWL_AC_UNSET, },
+};
+
+static const u8 iwlagn_bss_ac_to_fifo[] = {
+ IWL_TX_FIFO_VO,
+ IWL_TX_FIFO_VI,
+ IWL_TX_FIFO_BE,
+ IWL_TX_FIFO_BK,
+};
+static const u8 iwlagn_bss_ac_to_queue[] = {
+ 0, 1, 2, 3,
+};
+static const u8 iwlagn_pan_ac_to_fifo[] = {
+ IWL_TX_FIFO_VO_IPAN,
+ IWL_TX_FIFO_VI_IPAN,
+ IWL_TX_FIFO_BE_IPAN,
+ IWL_TX_FIFO_BK_IPAN,
+};
+static const u8 iwlagn_pan_ac_to_queue[] = {
+ 7, 6, 5, 4,
+};
+
+static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
+{
+ int ret;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER;
+ trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue;
+ trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue;
+
+ trans_pcie->ac_to_fifo[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_fifo;
+ trans_pcie->ac_to_fifo[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_fifo;
+
+ trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0;
+ trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE;
+
+ if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) &&
+ iwl_trans_pcie_prepare_card_hw(trans)) {
+ IWL_WARN(trans, "Exit HW not ready\n");
+ return -EIO;
+ }
+
+ /* If platform's RF_KILL switch is NOT set to KILL */
+ if (iwl_read32(bus(trans), CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+ clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+ else
+ set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+
+ if (iwl_is_rfkill(trans->shrd)) {
+ iwl_set_hw_rfkill_state(priv(trans), true);
+ iwl_enable_interrupts(trans);
+ return -ERFKILL;
+ }
+
+ iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF);
+
+ ret = iwl_nic_init(trans);
+ if (ret) {
+ IWL_ERR(trans, "Unable to init nic\n");
+ return ret;
+ }
+
+ /* make sure rfkill handshake bits are cleared */
+ iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR,
+ CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+ /* clear (again), then enable host interrupts */
+ iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF);
+ iwl_enable_interrupts(trans);
+
+ /* really make sure rfkill handshake bits are cleared */
+ iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+ return 0;
+}
+
+/*
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
+ * must be called under priv->shrd->lock and mac access
+ */
+static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
+{
+ iwl_write_prph(bus(trans), SCD_TXFACT, mask);
+}
+
+static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
+{
+ const struct queue_to_fifo_ac *queue_to_fifo;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+ u32 a;
+ unsigned long flags;
+ int i, chan;
+ u32 reg_val;
+
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+
+ trans_pcie->scd_base_addr =
+ iwl_read_prph(bus(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(bus(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(bus(trans), a, 0);
+ for (; a < trans_pcie->scd_base_addr +
+ SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num);
+ a += 4)
+ iwl_write_targ_mem(bus(trans), a, 0);
+
+ iwl_write_prph(bus(trans), SCD_DRAM_BASE_ADDR,
+ trans_pcie->scd_bc_tbls.dma >> 10);
+
+ /* Enable DMA channel */
+ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++)
+ iwl_write_direct32(bus(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(bus(trans), FH_TX_CHICKEN_BITS_REG);
+ iwl_write_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG,
+ reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
+
+ iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL,
+ SCD_QUEUECHAIN_SEL_ALL(trans));
+ iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0);
+
+ /* initiate the queues */
+ for (i = 0; i < hw_params(trans).max_txq_num; i++) {
+ iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0);
+ iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8));
+ iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
+ SCD_CONTEXT_QUEUE_OFFSET(i), 0);
+ iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
+ SCD_CONTEXT_QUEUE_OFFSET(i) +
+ sizeof(u32),
+ ((SCD_WIN_SIZE <<
+ SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
+ SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
+ ((SCD_FRAME_LIMIT <<
+ SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
+ SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
+ }
+
+ iwl_write_prph(bus(trans), SCD_INTERRUPT_MASK,
+ IWL_MASK(0, hw_params(trans).max_txq_num));
+
+ /* Activate all Tx DMA/FIFO channels */
+ iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7));
+
+ /* map queues to FIFOs */
+ if (trans->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS))
+ queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
+ else
+ queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
+
+ iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0);
+
+ /* make sure all queue are not stopped */
+ memset(&trans_pcie->queue_stopped[0], 0,
+ sizeof(trans_pcie->queue_stopped));
+ for (i = 0; i < 4; i++)
+ atomic_set(&trans_pcie->queue_stop_count[i], 0);
+
+ /* reset to 0 to enable all the queue first */
+ trans_pcie->txq_ctx_active_msk = 0;
+
+ BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) <
+ IWLAGN_FIRST_AMPDU_QUEUE);
+ BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) <
+ IWLAGN_FIRST_AMPDU_QUEUE);
+
+ for (i = 0; i < IWLAGN_FIRST_AMPDU_QUEUE; i++) {
+ int fifo = queue_to_fifo[i].fifo;
+ int ac = queue_to_fifo[i].ac;
+
+ iwl_txq_ctx_activate(trans_pcie, i);
+
+ if (fifo == IWL_TX_FIFO_UNUSED)
+ continue;
+
+ if (ac != IWL_AC_UNSET)
+ iwl_set_swq_id(&trans_pcie->txq[i], ac, i);
+ iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i],
+ fifo, 0);
+ }
+
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+ /* Enable L1-Active */
+ iwl_clear_bits_prph(bus(trans), APMG_PCIDEV_STT_REG,
+ APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+}
+
+/**
+ * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
+ */
+static int iwl_trans_tx_stop(struct iwl_trans *trans)
+{
+ int ch, txq_id;
+ unsigned long flags;
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ /* Turn off all Tx DMA fifos */
+ spin_lock_irqsave(&trans->shrd->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(bus(trans),
+ FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
+ if (iwl_poll_direct_bit(bus(trans), FH_TSSR_TX_STATUS_REG,
+ FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
+ 1000))
+ IWL_ERR(trans, "Failing on timeout while stopping"
+ " DMA channel %d [0x%08x]", ch,
+ iwl_read_direct32(bus(trans),
+ FH_TSSR_TX_STATUS_REG));
+ }
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+ if (!trans_pcie->txq) {
+ IWL_WARN(trans, "Stopping tx queues that aren't allocated...");
+ return 0;
+ }
+
+ /* Unmap DMA from host system and free skb's */
+ for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
+ iwl_tx_queue_unmap(trans, txq_id);
+
+ return 0;
+}
+
+static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans)
+{
+ unsigned long flags;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ spin_lock_irqsave(&trans->shrd->lock, flags);
+ iwl_disable_interrupts(trans);
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+ /* wait to make sure we flush pending tasklet*/
+ synchronize_irq(bus(trans)->irq);
+ tasklet_kill(&trans_pcie->irq_tasklet);
+}
+
+static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
+{
+ /* stop and reset the on-board processor */
+ iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+ /* tell the device to stop sending interrupts */
+ iwl_trans_pcie_disable_sync_irq(trans);
+
+ /* device going down, Stop using ICT table */
+ iwl_disable_ict(trans);
+
+ /*
+ * If a HW restart happens during firmware loading,
+ * then the firmware loading might call this function
+ * and later it might be called again due to the
+ * restart. So don't process again if the device is
+ * already dead.
+ */
+ if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) {
+ iwl_trans_tx_stop(trans);
+ iwl_trans_rx_stop(trans);
+
+ /* Power-down device's busmaster DMA clocks */
+ iwl_write_prph(bus(trans), APMG_CLK_DIS_REG,
+ APMG_CLK_VAL_DMA_CLK_RQT);
+ udelay(5);
+ }
+
+ /* Make sure (redundant) we've released our request to stay awake */
+ iwl_clear_bit(bus(trans), CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+ /* Stop the device, and put it in low power state */
+ iwl_apm_stop(priv(trans));
+}
+
+static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
+ struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
+ u8 sta_id)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ 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;
+ u16 seq_number = 0;
+ u8 wait_write_ptr = 0;
+ u8 txq_id;
+ u8 tid = 0;
+ bool is_agg = false;
+ __le16 fc = hdr->frame_control;
+ u8 hdr_len = ieee80211_hdrlen(fc);
+
+ /*
+ * Send this frame after DTIM -- there's a special queue
+ * reserved for this for contexts that support AP mode.
+ */
+ if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+ txq_id = trans_pcie->mcast_queue[ctx];
+
+ /*
+ * The microcode will clear the more data
+ * bit in the last frame it transmits.
+ */
+ hdr->frame_control |=
+ cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
+ txq_id = IWL_AUX_QUEUE;
+ else
+ txq_id =
+ trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)];
+
+ if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
+ u8 *qc = NULL;
+ struct iwl_tid_data *tid_data;
+ qc = ieee80211_get_qos_ctl(hdr);
+ tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+ tid_data = &trans->shrd->tid_data[sta_id][tid];
+
+ if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
+ return -1;
+
+ seq_number = tid_data->seq_number;
+ seq_number &= IEEE80211_SCTL_SEQ;
+ hdr->seq_ctrl = hdr->seq_ctrl &
+ cpu_to_le16(IEEE80211_SCTL_FRAG);
+ hdr->seq_ctrl |= cpu_to_le16(seq_number);
+ seq_number += 0x10;
+ /* aggregation is on for this <sta,tid> */
+ if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+ WARN_ON_ONCE(tid_data->agg.state != IWL_AGG_ON);
+ txq_id = tid_data->agg.txq_id;
+ is_agg = true;
+ }
+ }
+
+ /* Copy MAC header from skb into command buffer */
+ memcpy(tx_cmd->hdr, hdr, hdr_len);
+
+ txq = &trans_pcie->txq[txq_id];
+ q = &txq->q;
+
+ /* Set up driver data for this TFD */
+ txq->skbs[q->write_ptr] = skb;
+ txq->cmd[q->write_ptr] = 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->meta[q->write_ptr];
+
+ /*
+ * 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(bus(trans)->dev,
+ &dev_cmd->hdr, firstlen,
+ DMA_BIDIRECTIONAL);
+ if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys)))
+ return -1;
+ 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(bus(trans)->dev, skb->data + hdr_len,
+ secondlen, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) {
+ dma_unmap_single(bus(trans)->dev,
+ dma_unmap_addr(out_meta, mapping),
+ dma_unmap_len(out_meta, len),
+ DMA_BIDIRECTIONAL);
+ return -1;
+ }
+ }
+
+ /* 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(bus(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));
+ iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
+ iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
+
+ /* Set up entry for this TFD in Tx byte-count array */
+ if (is_agg)
+ iwl_trans_txq_update_byte_cnt_tbl(trans, txq,
+ le16_to_cpu(tx_cmd->len));
+
+ dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen,
+ DMA_BIDIRECTIONAL);
+
+ trace_iwlwifi_dev_tx(priv(trans),
+ &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
+ sizeof(struct iwl_tfd),
+ &dev_cmd->hdr, firstlen,
+ skb->data + hdr_len, secondlen);
+
+ /* 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);
+
+ if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
+ trans->shrd->tid_data[sta_id][tid].tfds_in_queue++;
+ if (!ieee80211_has_morefrags(fc))
+ trans->shrd->tid_data[sta_id][tid].seq_number =
+ seq_number;
+ }
+
+ /*
+ * 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);
+ }
+ }
+ return 0;
+}
+
+static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans)
+{
+ /* Remove all resets to allow NIC to operate */
+ iwl_write32(bus(trans), CSR_RESET, 0);
+}
+
+static int iwl_trans_pcie_request_irq(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+ int err;
+
+ trans_pcie->inta_mask = CSR_INI_SET_MASK;
+
+ tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long))
+ iwl_irq_tasklet, (unsigned long)trans);
+
+ iwl_alloc_isr_ict(trans);
+
+ err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED,
+ DRV_NAME, trans);
+ if (err) {
+ IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq);
+ iwl_free_isr_ict(trans);
+ return err;
+ }
+
+ INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish);
+ return 0;
+}
+
+static int iwlagn_txq_check_empty(struct iwl_trans *trans,
+ int sta_id, u8 tid, int txq_id)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_queue *q = &trans_pcie->txq[txq_id].q;
+ struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid];
+
+ lockdep_assert_held(&trans->shrd->sta_lock);
+
+ switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
+ case IWL_EMPTYING_HW_QUEUE_DELBA:
+ /* We are reclaiming the last packet of the */
+ /* aggregated HW queue */
+ if ((txq_id == tid_data->agg.txq_id) &&
+ (q->read_ptr == q->write_ptr)) {
+ IWL_DEBUG_HT(trans,
+ "HW queue empty: continue DELBA flow\n");
+ iwl_trans_pcie_txq_agg_disable(trans, txq_id);
+ tid_data->agg.state = IWL_AGG_OFF;
+ iwl_stop_tx_ba_trans_ready(priv(trans),
+ NUM_IWL_RXON_CTX,
+ sta_id, tid);
+ iwl_wake_queue(trans, &trans_pcie->txq[txq_id]);
+ }
+ break;
+ case IWL_EMPTYING_HW_QUEUE_ADDBA:
+ /* We are reclaiming the last packet of the queue */
+ if (tid_data->tfds_in_queue == 0) {
+ IWL_DEBUG_HT(trans,
+ "HW queue empty: continue ADDBA flow\n");
+ tid_data->agg.state = IWL_AGG_ON;
+ iwl_start_tx_ba_trans_ready(priv(trans),
+ NUM_IWL_RXON_CTX,
+ sta_id, tid);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void iwl_free_tfds_in_queue(struct iwl_trans *trans,
+ int sta_id, int tid, int freed)
+{
+ lockdep_assert_held(&trans->shrd->sta_lock);
+
+ if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed)
+ trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed;
+ else {
+ IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n",
+ trans->shrd->tid_data[sta_id][tid].tfds_in_queue,
+ freed);
+ trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0;
+ }
+}
+
+static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
+ int txq_id, int ssn, u32 status,
+ 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];
+ enum iwl_agg_state agg_state;
+ /* n_bd is usually 256 => n_bd - 1 = 0xff */
+ int tfd_num = ssn & (txq->q.n_bd - 1);
+ int freed = 0;
+ bool cond;
+
+ txq->time_stamp = jiffies;
+
+ if (txq->sched_retry) {
+ agg_state =
+ trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state;
+ cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA);
+ } else {
+ cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX);
+ }
+
+ if (txq->q.read_ptr != tfd_num) {
+ IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim "
+ "scd_ssn=%d idx=%d txq=%d swq=%d\n",
+ ssn , tfd_num, txq_id, txq->swq_id);
+ freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
+ if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond)
+ iwl_wake_queue(trans, txq);
+ }
+
+ iwl_free_tfds_in_queue(trans, sta_id, tid, freed);
+ iwlagn_txq_check_empty(trans, sta_id, tid, txq_id);
+}
+
+static void iwl_trans_pcie_free(struct iwl_trans *trans)
+{
+ iwl_trans_pcie_tx_free(trans);
+ iwl_trans_pcie_rx_free(trans);
+ free_irq(bus(trans)->irq, trans);
+ iwl_free_isr_ict(trans);
+ trans->shrd->trans = NULL;
+ kfree(trans);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
+{
+ /*
+ * This function is called when system goes into suspend state
+ * mac80211 will call iwlagn_mac_stop() from the mac80211 suspend
+ * function first but since iwlagn_mac_stop() has no knowledge of
+ * who the caller is,
+ * it will not call apm_ops.stop() to stop the DMA operation.
+ * Calling apm_ops.stop here to make sure we stop the DMA.
+ *
+ * But of course ... if we have configured WoWLAN then we did other
+ * things already :-)
+ */
+ if (!trans->shrd->wowlan) {
+ iwl_apm_stop(priv(trans));
+ } else {
+ iwl_disable_interrupts(trans);
+ iwl_clear_bit(bus(trans), CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ }
+
+ return 0;
+}
+
+static int iwl_trans_pcie_resume(struct iwl_trans *trans)
+{
+ bool hw_rfkill = false;
+
+ iwl_enable_interrupts(trans);
+
+ if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+ hw_rfkill = true;
+
+ if (hw_rfkill)
+ set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+ else
+ clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+
+ iwl_set_hw_rfkill_state(priv(trans), hw_rfkill);
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx)
+{
+ u8 ac, txq_id;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ for (ac = 0; ac < AC_NUM; ac++) {
+ txq_id = trans_pcie->ac_to_queue[ctx][ac];
+ IWL_DEBUG_INFO(trans, "Queue Status: Q[%d] %s\n",
+ ac,
+ (atomic_read(&trans_pcie->queue_stop_count[ac]) > 0)
+ ? "stopped" : "awake");
+ iwl_wake_queue(trans, &trans_pcie->txq[txq_id]);
+ }
+}
+
+const struct iwl_trans_ops trans_ops_pcie;
+
+static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd)
+{
+ struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) +
+ sizeof(struct iwl_trans_pcie),
+ GFP_KERNEL);
+ if (iwl_trans) {
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
+ iwl_trans->ops = &trans_ops_pcie;
+ iwl_trans->shrd = shrd;
+ trans_pcie->trans = iwl_trans;
+ spin_lock_init(&iwl_trans->hcmd_lock);
+ }
+
+ return iwl_trans;
+}
+
+static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ iwl_stop_queue(trans, &trans_pcie->txq[txq_id]);
+}
+
+#define IWL_FLUSH_WAIT_MS 2000
+
+static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_tx_queue *txq;
+ struct iwl_queue *q;
+ int cnt;
+ unsigned long now = jiffies;
+ int ret = 0;
+
+ /* waiting for all the tx frames complete might take a while */
+ for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
+ if (cnt == trans->shrd->cmd_queue)
+ continue;
+ txq = &trans_pcie->txq[cnt];
+ q = &txq->q;
+ while (q->read_ptr != q->write_ptr && !time_after(jiffies,
+ now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS)))
+ msleep(1);
+
+ if (q->read_ptr != q->write_ptr) {
+ IWL_ERR(trans, "fail to flush all tx fifo queues\n");
+ ret = -ETIMEDOUT;
+ break;
+ }
+ }
+ return ret;
+}
+
+/*
+ * On every watchdog tick we check (latest) time stamp. If it does not
+ * change during timeout period and queue is not empty we reset firmware.
+ */
+static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_tx_queue *txq = &trans_pcie->txq[cnt];
+ struct iwl_queue *q = &txq->q;
+ unsigned long timeout;
+
+ if (q->read_ptr == q->write_ptr) {
+ txq->time_stamp = jiffies;
+ return 0;
+ }
+
+ timeout = txq->time_stamp +
+ msecs_to_jiffies(hw_params(trans).wd_timeout);
+
+ if (time_after(jiffies, timeout)) {
+ IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id,
+ hw_params(trans).wd_timeout);
+ IWL_ERR(trans, "Current read_ptr %d write_ptr %d\n",
+ q->read_ptr, q->write_ptr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static const char *get_fh_string(int cmd)
+{
+ switch (cmd) {
+ IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
+ IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
+ IWL_CMD(FH_RSCSR_CHNL0_WPTR);
+ IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
+ IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
+ IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
+ IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
+ IWL_CMD(FH_TSSR_TX_STATUS_REG);
+ IWL_CMD(FH_TSSR_TX_ERROR_REG);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
+{
+ int i;
+#ifdef CONFIG_IWLWIFI_DEBUG
+ int pos = 0;
+ size_t bufsz = 0;
+#endif
+ static const u32 fh_tbl[] = {
+ FH_RSCSR_CHNL0_STTS_WPTR_REG,
+ FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+ FH_RSCSR_CHNL0_WPTR,
+ FH_MEM_RCSR_CHNL0_CONFIG_REG,
+ FH_MEM_RSSR_SHARED_CTRL_REG,
+ FH_MEM_RSSR_RX_STATUS_REG,
+ FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
+ FH_TSSR_TX_STATUS_REG,
+ FH_TSSR_TX_ERROR_REG
+ };
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (display) {
+ bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+ *buf = kmalloc(bufsz, GFP_KERNEL);
+ if (!*buf)
+ return -ENOMEM;
+ pos += scnprintf(*buf + pos, bufsz - pos,
+ "FH register values:\n");
+ for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+ pos += scnprintf(*buf + pos, bufsz - pos,
+ " %34s: 0X%08x\n",
+ get_fh_string(fh_tbl[i]),
+ iwl_read_direct32(bus(trans), fh_tbl[i]));
+ }
+ return pos;
+ }
+#endif
+ IWL_ERR(trans, "FH register values:\n");
+ for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+ IWL_ERR(trans, " %34s: 0X%08x\n",
+ get_fh_string(fh_tbl[i]),
+ iwl_read_direct32(bus(trans), fh_tbl[i]));
+ }
+ return 0;
+}
+
+static const char *get_csr_string(int cmd)
+{
+ switch (cmd) {
+ IWL_CMD(CSR_HW_IF_CONFIG_REG);
+ IWL_CMD(CSR_INT_COALESCING);
+ IWL_CMD(CSR_INT);
+ IWL_CMD(CSR_INT_MASK);
+ IWL_CMD(CSR_FH_INT_STATUS);
+ IWL_CMD(CSR_GPIO_IN);
+ IWL_CMD(CSR_RESET);
+ IWL_CMD(CSR_GP_CNTRL);
+ IWL_CMD(CSR_HW_REV);
+ IWL_CMD(CSR_EEPROM_REG);
+ IWL_CMD(CSR_EEPROM_GP);
+ IWL_CMD(CSR_OTP_GP_REG);
+ IWL_CMD(CSR_GIO_REG);
+ IWL_CMD(CSR_GP_UCODE_REG);
+ IWL_CMD(CSR_GP_DRIVER_REG);
+ IWL_CMD(CSR_UCODE_DRV_GP1);
+ IWL_CMD(CSR_UCODE_DRV_GP2);
+ IWL_CMD(CSR_LED_REG);
+ IWL_CMD(CSR_DRAM_INT_TBL_REG);
+ IWL_CMD(CSR_GIO_CHICKEN_BITS);
+ IWL_CMD(CSR_ANA_PLL_CFG);
+ IWL_CMD(CSR_HW_REV_WA_REG);
+ IWL_CMD(CSR_DBG_HPET_MEM_REG);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+void iwl_dump_csr(struct iwl_trans *trans)
+{
+ int i;
+ static const u32 csr_tbl[] = {
+ CSR_HW_IF_CONFIG_REG,
+ CSR_INT_COALESCING,
+ CSR_INT,
+ CSR_INT_MASK,
+ CSR_FH_INT_STATUS,
+ CSR_GPIO_IN,
+ CSR_RESET,
+ CSR_GP_CNTRL,
+ CSR_HW_REV,
+ CSR_EEPROM_REG,
+ CSR_EEPROM_GP,
+ CSR_OTP_GP_REG,
+ CSR_GIO_REG,
+ CSR_GP_UCODE_REG,
+ CSR_GP_DRIVER_REG,
+ CSR_UCODE_DRV_GP1,
+ CSR_UCODE_DRV_GP2,
+ CSR_LED_REG,
+ CSR_DRAM_INT_TBL_REG,
+ CSR_GIO_CHICKEN_BITS,
+ CSR_ANA_PLL_CFG,
+ CSR_HW_REV_WA_REG,
+ CSR_DBG_HPET_MEM_REG
+ };
+ IWL_ERR(trans, "CSR values:\n");
+ IWL_ERR(trans, "(2nd byte of CSR_INT_COALESCING is "
+ "CSR_INT_PERIODIC_REG)\n");
+ for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) {
+ IWL_ERR(trans, " %25s: 0X%08x\n",
+ get_csr_string(csr_tbl[i]),
+ iwl_read32(bus(trans), csr_tbl[i]));
+ }
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+/* create and remove of files */
+#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
+ if (!debugfs_create_file(#name, mode, parent, trans, \
+ &iwl_dbgfs_##name##_ops)) \
+ return -ENOMEM; \
+} while (0)
+
+/* file operation */
+#define DEBUGFS_READ_FUNC(name) \
+static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
+ char __user *user_buf, \
+ size_t count, loff_t *ppos);
+
+#define DEBUGFS_WRITE_FUNC(name) \
+static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
+ const char __user *user_buf, \
+ size_t count, loff_t *ppos);
+
+
+static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+#define DEBUGFS_READ_FILE_OPS(name) \
+ DEBUGFS_READ_FUNC(name); \
+static const struct file_operations iwl_dbgfs_##name##_ops = { \
+ .read = iwl_dbgfs_##name##_read, \
+ .open = iwl_dbgfs_open_file_generic, \
+ .llseek = generic_file_llseek, \
+};
+
+#define DEBUGFS_WRITE_FILE_OPS(name) \
+ DEBUGFS_WRITE_FUNC(name); \
+static const struct file_operations iwl_dbgfs_##name##_ops = { \
+ .write = iwl_dbgfs_##name##_write, \
+ .open = iwl_dbgfs_open_file_generic, \
+ .llseek = generic_file_llseek, \
+};
+
+#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
+ DEBUGFS_READ_FUNC(name); \
+ DEBUGFS_WRITE_FUNC(name); \
+static const struct file_operations iwl_dbgfs_##name##_ops = { \
+ .write = iwl_dbgfs_##name##_write, \
+ .read = iwl_dbgfs_##name##_read, \
+ .open = iwl_dbgfs_open_file_generic, \
+ .llseek = generic_file_llseek, \
+};
+
+static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ 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_queue *q;
+ char *buf;
+ int pos = 0;
+ int cnt;
+ int ret;
+ const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num;
+
+ if (!trans_pcie->txq) {
+ IWL_ERR(trans, "txq not ready\n");
+ return -EAGAIN;
+ }
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
+ txq = &trans_pcie->txq[cnt];
+ q = &txq->q;
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "hwq %.2d: read=%u write=%u stop=%d"
+ " swq_id=%#.2x (ac %d/hwq %d)\n",
+ cnt, q->read_ptr, q->write_ptr,
+ !!test_bit(cnt, trans_pcie->queue_stopped),
+ txq->swq_id, txq->swq_id & 3,
+ (txq->swq_id >> 2) & 0x1f);
+ if (cnt >= 4)
+ continue;
+ /* for the ACs, display the stop count too */
+ pos += scnprintf(buf + pos, bufsz - pos,
+ " stop-count: %d\n",
+ atomic_read(&trans_pcie->queue_stop_count[cnt]));
+ }
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos) {
+ 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;
+ char buf[256];
+ int pos = 0;
+ const size_t bufsz = sizeof(buf);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
+ rxq->read);
+ pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
+ rxq->write);
+ pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
+ rxq->free_count);
+ if (rxq->rb_stts) {
+ pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
+ le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF);
+ } else {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "closed_rb_num: Not Allocated\n");
+ }
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_dbgfs_log_event_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_trans *trans = file->private_data;
+ char *buf;
+ int pos = 0;
+ ssize_t ret = -ENOMEM;
+
+ ret = pos = iwl_dump_nic_event_log(trans, true, &buf, true);
+ if (buf) {
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ }
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_log_event_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_trans *trans = file->private_data;
+ u32 event_log_flag;
+ char buf[8];
+ int buf_size;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%d", &event_log_flag) != 1)
+ return -EFAULT;
+ if (event_log_flag == 1)
+ iwl_dump_nic_event_log(trans, true, NULL, false);
+
+ return count;
+}
+
+static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_trans *trans = file->private_data;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
+
+ int pos = 0;
+ char *buf;
+ int bufsz = 24 * 64; /* 24 items * 64 char per item */
+ ssize_t ret;
+
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERR(trans, "Can not allocate Buffer\n");
+ return -ENOMEM;
+ }
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Interrupt Statistics Report:\n");
+
+ pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
+ isr_stats->hw);
+ pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
+ isr_stats->sw);
+ if (isr_stats->sw || isr_stats->hw) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tLast Restarting Code: 0x%X\n",
+ isr_stats->err_code);
+ }
+#ifdef CONFIG_IWLWIFI_DEBUG
+ pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
+ isr_stats->sch);
+ pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
+ isr_stats->alive);
+#endif
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "HW RF KILL switch toggled:\t %u\n", isr_stats->rfkill);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
+ isr_stats->ctkill);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
+ isr_stats->wakeup);
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Rx command responses:\t\t %u\n", isr_stats->rx);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
+ isr_stats->tx);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
+ isr_stats->unhandled);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_trans *trans = file->private_data;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
+
+ char buf[8];
+ int buf_size;
+ u32 reset_flag;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%x", &reset_flag) != 1)
+ return -EFAULT;
+ if (reset_flag == 0)
+ memset(isr_stats, 0, sizeof(*isr_stats));
+
+ return count;
+}
+
+static ssize_t iwl_dbgfs_csr_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_trans *trans = file->private_data;
+ char buf[8];
+ int buf_size;
+ int csr;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%d", &csr) != 1)
+ return -EFAULT;
+
+ iwl_dump_csr(trans);
+
+ return count;
+}
+
+static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_trans *trans = file->private_data;
+ char *buf;
+ int pos = 0;
+ ssize_t ret = -EFAULT;
+
+ ret = pos = iwl_dump_fh(trans, &buf, true);
+ if (buf) {
+ ret = simple_read_from_buffer(user_buf,
+ count, ppos, buf, pos);
+ kfree(buf);
+ }
+
+ return ret;
+}
+
+DEBUGFS_READ_WRITE_FILE_OPS(log_event);
+DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
+DEBUGFS_READ_FILE_OPS(fh_reg);
+DEBUGFS_READ_FILE_OPS(rx_queue);
+DEBUGFS_READ_FILE_OPS(tx_queue);
+DEBUGFS_WRITE_FILE_OPS(csr);
+
+/*
+ * Create the debugfs files and directories
+ *
+ */
+static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
+ struct dentry *dir)
+{
+ DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR);
+ DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR);
+ DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(csr, dir, S_IWUSR);
+ DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
+ return 0;
+}
+#else
+static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
+ struct dentry *dir)
+{ return 0; }
+
+#endif /*CONFIG_IWLWIFI_DEBUGFS */
+
+const struct iwl_trans_ops trans_ops_pcie = {
+ .alloc = iwl_trans_pcie_alloc,
+ .request_irq = iwl_trans_pcie_request_irq,
+ .start_device = iwl_trans_pcie_start_device,
+ .prepare_card_hw = iwl_trans_pcie_prepare_card_hw,
+ .stop_device = iwl_trans_pcie_stop_device,
+
+ .tx_start = iwl_trans_pcie_tx_start,
+ .wake_any_queue = iwl_trans_pcie_wake_any_queue,
+
+ .send_cmd = iwl_trans_pcie_send_cmd,
+
+ .tx = iwl_trans_pcie_tx,
+ .reclaim = iwl_trans_pcie_reclaim,
+
+ .tx_agg_disable = iwl_trans_pcie_tx_agg_disable,
+ .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc,
+ .tx_agg_setup = iwl_trans_pcie_tx_agg_setup,
+
+ .kick_nic = iwl_trans_pcie_kick_nic,
+
+ .free = iwl_trans_pcie_free,
+ .stop_queue = iwl_trans_pcie_stop_queue,
+
+ .dbgfs_register = iwl_trans_pcie_dbgfs_register,
+
+ .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty,
+ .check_stuck_queue = iwl_trans_pcie_check_stuck_queue,
+
+#ifdef CONFIG_PM_SLEEP
+ .suspend = iwl_trans_pcie_suspend,
+ .resume = iwl_trans_pcie_resume,
+#endif
+};
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
deleted file mode 100644
index 474860290404..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
+++ /dev/null
@@ -1,979 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * 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:
- * Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/gfp.h>
-
-#include "iwl-dev.h"
-#include "iwl-agn.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-trans-int-pcie.h"
-
-/******************************************************************************
- *
- * RX path functions
- *
- ******************************************************************************/
-
-/*
- * Rx theory of operation
- *
- * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
- * each of which point to Receive Buffers to be filled by the NIC. These get
- * used not only for Rx frames, but for any command response or notification
- * from the NIC. The driver and NIC manage the Rx buffers by means
- * of indexes into the circular buffer.
- *
- * Rx Queue Indexes
- * The host/firmware share two index registers for managing the Rx buffers.
- *
- * The READ index maps to the first position that the firmware may be writing
- * to -- the driver can read up to (but not including) this position and get
- * good data.
- * The READ index is managed by the firmware once the card is enabled.
- *
- * The WRITE index maps to the last position the driver has read from -- the
- * position preceding WRITE is the last slot the firmware can place a packet.
- *
- * The queue is empty (no good data) if WRITE = READ - 1, and is full if
- * WRITE = READ.
- *
- * During initialization, the host sets up the READ queue position to the first
- * INDEX position, and WRITE to the last (READ - 1 wrapped)
- *
- * When the firmware places a packet in a buffer, it will advance the READ index
- * and fire the RX interrupt. The driver can then query the READ index and
- * process as many packets as possible, moving the WRITE index forward as it
- * resets the Rx queue buffers with new memory.
- *
- * The management in the driver is as follows:
- * + 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
- * 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,
- * detached from the iwl->rxq. The driver 'processed' index is updated.
- * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
- * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
- * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there
- * were enough free buffers and RX_STALLED is set it is cleared.
- *
- *
- * 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
- * queue, updates firmware pointers, and updates
- * the WRITE index. If insufficient rx_free buffers
- * are available, schedules iwl_rx_replenish
- *
- * -- enable interrupts --
- * 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
- * slots.
- * ...
- *
- */
-
-/**
- * iwl_rx_queue_space - Return number of free slots available in queue.
- */
-static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
-{
- int s = q->read - q->write;
- if (s <= 0)
- s += RX_QUEUE_SIZE;
- /* keep some buffer to not confuse full and empty queue */
- s -= 2;
- if (s < 0)
- s = 0;
- return s;
-}
-
-/**
- * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
- */
-void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl_rx_queue *q)
-{
- unsigned long flags;
- u32 reg;
-
- spin_lock_irqsave(&q->lock, flags);
-
- if (q->need_update == 0)
- goto exit_unlock;
-
- if (priv->cfg->base_params->shadow_reg_enable) {
- /* shadow register enabled */
- /* Device expects a multiple of 8 */
- q->write_actual = (q->write & ~0x7);
- iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual);
- } else {
- /* If power-saving is in use, make sure device is awake */
- if (test_bit(STATUS_POWER_PMI, &priv->status)) {
- reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
-
- if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
- IWL_DEBUG_INFO(priv,
- "Rx queue requesting wakeup,"
- " GP1 = 0x%x\n", reg);
- iwl_set_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- goto exit_unlock;
- }
-
- q->write_actual = (q->write & ~0x7);
- iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
- q->write_actual);
-
- /* Else device is assumed to be awake */
- } else {
- /* Device expects a multiple of 8 */
- q->write_actual = (q->write & ~0x7);
- iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
- q->write_actual);
- }
- }
- q->need_update = 0;
-
- exit_unlock:
- spin_unlock_irqrestore(&q->lock, flags);
-}
-
-/**
- * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
-static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv,
- dma_addr_t dma_addr)
-{
- return cpu_to_le32((u32)(dma_addr >> 8));
-}
-
-/**
- * iwlagn_rx_queue_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
- * as we can, pulling from rx_free.
- *
- * This moves the 'write' index forward to catch up with 'processed', and
- * also updates the memory address in the firmware to reference the new
- * target buffer.
- */
-static void iwlagn_rx_queue_restock(struct iwl_priv *priv)
-{
- struct iwl_rx_queue *rxq = &priv->rxq;
- struct list_head *element;
- struct iwl_rx_mem_buffer *rxb;
- unsigned long flags;
-
- spin_lock_irqsave(&rxq->lock, flags);
- while ((iwl_rx_queue_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);
-
- /* Point to Rx buffer via next RBD in circular buffer */
- rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv,
- rxb->page_dma);
- rxq->queue[rxq->write] = rxb;
- rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
- rxq->free_count--;
- }
- spin_unlock_irqrestore(&rxq->lock, flags);
- /* If the pre-allocated buffer pool is dropping low, schedule to
- * refill it */
- if (rxq->free_count <= RX_LOW_WATERMARK)
- queue_work(priv->workqueue, &priv->rx_replenish);
-
-
- /* If we've added more space for the firmware to place data, tell it.
- * Increment device's write pointer in multiples of 8. */
- if (rxq->write_actual != (rxq->write & ~0x7)) {
- spin_lock_irqsave(&rxq->lock, flags);
- rxq->need_update = 1;
- spin_unlock_irqrestore(&rxq->lock, flags);
- iwl_rx_queue_update_write_ptr(priv, rxq);
- }
-}
-
-/**
- * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free
- *
- * When moving to rx_free an SKB is allocated for the slot.
- *
- * Also restock the Rx queue via iwl_rx_queue_restock.
- * This is called as a scheduled work item (except for during initialization)
- */
-static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority)
-{
- struct iwl_rx_queue *rxq = &priv->rxq;
- struct list_head *element;
- struct iwl_rx_mem_buffer *rxb;
- struct page *page;
- unsigned long flags;
- gfp_t gfp_mask = priority;
-
- while (1) {
- spin_lock_irqsave(&rxq->lock, flags);
- if (list_empty(&rxq->rx_used)) {
- spin_unlock_irqrestore(&rxq->lock, flags);
- return;
- }
- spin_unlock_irqrestore(&rxq->lock, flags);
-
- if (rxq->free_count > RX_LOW_WATERMARK)
- gfp_mask |= __GFP_NOWARN;
-
- if (priv->hw_params.rx_page_order > 0)
- gfp_mask |= __GFP_COMP;
-
- /* Alloc a new receive buffer */
- page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
- if (!page) {
- if (net_ratelimit())
- IWL_DEBUG_INFO(priv, "alloc_pages failed, "
- "order: %d\n",
- priv->hw_params.rx_page_order);
-
- if ((rxq->free_count <= RX_LOW_WATERMARK) &&
- net_ratelimit())
- IWL_CRIT(priv, "Failed to alloc_pages with %s."
- "Only %u free buffers remaining.\n",
- priority == GFP_ATOMIC ?
- "GFP_ATOMIC" : "GFP_KERNEL",
- rxq->free_count);
- /* We don't reschedule replenish work here -- we will
- * call the restock method and if it still needs
- * more buffers it will schedule replenish */
- return;
- }
-
- spin_lock_irqsave(&rxq->lock, flags);
-
- if (list_empty(&rxq->rx_used)) {
- spin_unlock_irqrestore(&rxq->lock, flags);
- __free_pages(page, priv->hw_params.rx_page_order);
- return;
- }
- element = rxq->rx_used.next;
- rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
- list_del(element);
-
- spin_unlock_irqrestore(&rxq->lock, flags);
-
- BUG_ON(rxb->page);
- rxb->page = page;
- /* Get physical address of the RB */
- rxb->page_dma = dma_map_page(priv->bus->dev, page, 0,
- PAGE_SIZE << priv->hw_params.rx_page_order,
- DMA_FROM_DEVICE);
- /* dma address must be no more than 36 bits */
- BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
- /* and also 256 byte aligned! */
- BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
-
- spin_lock_irqsave(&rxq->lock, flags);
-
- list_add_tail(&rxb->list, &rxq->rx_free);
- rxq->free_count++;
-
- spin_unlock_irqrestore(&rxq->lock, flags);
- }
-}
-
-void iwlagn_rx_replenish(struct iwl_priv *priv)
-{
- unsigned long flags;
-
- iwlagn_rx_allocate(priv, GFP_KERNEL);
-
- spin_lock_irqsave(&priv->lock, flags);
- iwlagn_rx_queue_restock(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static void iwlagn_rx_replenish_now(struct iwl_priv *priv)
-{
- iwlagn_rx_allocate(priv, GFP_ATOMIC);
-
- iwlagn_rx_queue_restock(priv);
-}
-
-void iwl_bg_rx_replenish(struct work_struct *data)
-{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, rx_replenish);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- mutex_lock(&priv->mutex);
- iwlagn_rx_replenish(priv);
- mutex_unlock(&priv->mutex);
-}
-
-/**
- * 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.
- */
-static void iwl_rx_handle(struct iwl_priv *priv)
-{
- struct iwl_rx_mem_buffer *rxb;
- struct iwl_rx_packet *pkt;
- struct iwl_rx_queue *rxq = &priv->rxq;
- u32 r, i;
- int reclaim;
- unsigned long flags;
- u8 fill_rx = 0;
- u32 count = 8;
- int total_empty;
-
- /* 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;
- i = rxq->read;
-
- /* Rx interrupt, but nothing sent from uCode */
- if (i == r)
- IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
-
- /* calculate total frames need to be restock after handling RX */
- total_empty = r - rxq->write_actual;
- if (total_empty < 0)
- total_empty += RX_QUEUE_SIZE;
-
- if (total_empty > (RX_QUEUE_SIZE / 2))
- fill_rx = 1;
-
- while (i != r) {
- int len;
-
- rxb = rxq->queue[i];
-
- /* If an RXB doesn't have a Rx queue slot associated with it,
- * then a bug has been introduced in the queue refilling
- * routines -- catch it here */
- if (WARN_ON(rxb == NULL)) {
- i = (i + 1) & RX_QUEUE_MASK;
- continue;
- }
-
- rxq->queue[i] = NULL;
-
- dma_unmap_page(priv->bus->dev, rxb->page_dma,
- PAGE_SIZE << priv->hw_params.rx_page_order,
- DMA_FROM_DEVICE);
- pkt = rxb_addr(rxb);
-
- IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
- i, get_cmd_string(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(priv, pkt, len);
-
- /* Reclaim a command buffer only if this packet is a response
- * to a (driver-originated) command.
- * If the packet (e.g. Rx frame) originated from uCode,
- * there is no command buffer to reclaim.
- * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
- * but apparently a few don't get set; catch them here. */
- reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
- (pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
- (pkt->hdr.cmd != REPLY_RX) &&
- (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
- (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
- (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
- (pkt->hdr.cmd != REPLY_TX);
-
- iwl_rx_dispatch(priv, rxb);
-
- /*
- * XXX: After here, we should always check rxb->page
- * against NULL before touching it or its virtual
- * memory (pkt). Because some rx_handler might have
- * already taken or freed the pages.
- */
-
- if (reclaim) {
- /* Invoke any callbacks, transfer the buffer to caller,
- * and fire off the (possibly) blocking
- * trans_send_cmd()
- * as we reclaim the driver command queue */
- if (rxb->page)
- iwl_tx_cmd_complete(priv, rxb);
- else
- IWL_WARN(priv, "Claim null rxb?\n");
- }
-
- /* Reuse the page if possible. For notification packets and
- * SKBs that fail to Rx correctly, add them back into the
- * rx_free list for reuse later. */
- spin_lock_irqsave(&rxq->lock, flags);
- if (rxb->page != NULL) {
- rxb->page_dma = dma_map_page(priv->bus->dev, rxb->page,
- 0, PAGE_SIZE << priv->hw_params.rx_page_order,
- DMA_FROM_DEVICE);
- list_add_tail(&rxb->list, &rxq->rx_free);
- rxq->free_count++;
- } else
- list_add_tail(&rxb->list, &rxq->rx_used);
-
- spin_unlock_irqrestore(&rxq->lock, flags);
-
- i = (i + 1) & RX_QUEUE_MASK;
- /* If there are a lot of unused frames,
- * restock the Rx queue so ucode wont assert. */
- if (fill_rx) {
- count++;
- if (count >= 8) {
- rxq->read = i;
- iwlagn_rx_replenish_now(priv);
- count = 0;
- }
- }
- }
-
- /* Backtrack one entry */
- rxq->read = i;
- if (fill_rx)
- iwlagn_rx_replenish_now(priv);
- else
- iwlagn_rx_queue_restock(priv);
-}
-
-/* tasklet for iwlagn interrupt */
-void iwl_irq_tasklet(struct iwl_priv *priv)
-{
- u32 inta = 0;
- u32 handled = 0;
- unsigned long flags;
- u32 i;
-#ifdef CONFIG_IWLWIFI_DEBUG
- u32 inta_mask;
-#endif
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Ack/clear/reset pending uCode interrupts.
- * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
- */
- /* There is a hardware bug in the interrupt mask function that some
- * interrupts (i.e. CSR_INT_BIT_SCD) can still be generated even if
- * they are disabled in the CSR_INT_MASK register. Furthermore the
- * ICT interrupt handling mechanism has another bug that might cause
- * these unmasked interrupts fail to be detected. We workaround the
- * hardware bugs here by ACKing all the possible interrupts so that
- * interrupt coalescing can still be achieved.
- */
- iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask);
-
- inta = priv->inta;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
- /* just for debug */
- inta_mask = iwl_read32(priv, CSR_INT_MASK);
- IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ",
- inta, inta_mask);
- }
-#endif
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* saved interrupt in inta variable now we can reset priv->inta */
- priv->inta = 0;
-
- /* Now service all interrupt bits discovered above. */
- if (inta & CSR_INT_BIT_HW_ERR) {
- IWL_ERR(priv, "Hardware error detected. Restarting.\n");
-
- /* Tell the device to stop sending interrupts */
- iwl_disable_interrupts(priv);
-
- priv->isr_stats.hw++;
- iwl_irq_handle_error(priv);
-
- handled |= CSR_INT_BIT_HW_ERR;
-
- return;
- }
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
- /* NIC fires this, but we don't use it, redundant with WAKEUP */
- if (inta & CSR_INT_BIT_SCD) {
- IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
- "the frame/frames.\n");
- priv->isr_stats.sch++;
- }
-
- /* Alive notification via Rx interrupt will do the real work */
- if (inta & CSR_INT_BIT_ALIVE) {
- IWL_DEBUG_ISR(priv, "Alive interrupt\n");
- priv->isr_stats.alive++;
- }
- }
-#endif
- /* Safely ignore these bits for debug checks below */
- inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
-
- /* HW RF KILL switch toggled */
- if (inta & CSR_INT_BIT_RF_KILL) {
- int hw_rf_kill = 0;
- if (!(iwl_read32(priv, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
- hw_rf_kill = 1;
-
- IWL_WARN(priv, "RF_KILL bit toggled to %s.\n",
- hw_rf_kill ? "disable radio" : "enable radio");
-
- priv->isr_stats.rfkill++;
-
- /* driver only loads ucode once setting the interface up.
- * the driver allows loading the ucode even if the radio
- * is killed. Hence update the killswitch state here. The
- * rfkill handler will care about restarting if needed.
- */
- if (!test_bit(STATUS_ALIVE, &priv->status)) {
- if (hw_rf_kill)
- set_bit(STATUS_RF_KILL_HW, &priv->status);
- else
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
- wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
- }
-
- handled |= CSR_INT_BIT_RF_KILL;
- }
-
- /* Chip got too hot and stopped itself */
- if (inta & CSR_INT_BIT_CT_KILL) {
- IWL_ERR(priv, "Microcode CT kill error detected.\n");
- priv->isr_stats.ctkill++;
- handled |= CSR_INT_BIT_CT_KILL;
- }
-
- /* Error detected by uCode */
- if (inta & CSR_INT_BIT_SW_ERR) {
- IWL_ERR(priv, "Microcode SW error detected. "
- " Restarting 0x%X.\n", inta);
- priv->isr_stats.sw++;
- iwl_irq_handle_error(priv);
- handled |= CSR_INT_BIT_SW_ERR;
- }
-
- /* uCode wakes up after power-down sleep */
- if (inta & CSR_INT_BIT_WAKEUP) {
- IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
- iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
- for (i = 0; i < priv->hw_params.max_txq_num; i++)
- iwl_txq_update_write_ptr(priv, &priv->txq[i]);
-
- priv->isr_stats.wakeup++;
-
- handled |= CSR_INT_BIT_WAKEUP;
- }
-
- /* All uCode command responses, including Tx command responses,
- * Rx "responses" (frame-received notification), and other
- * notifications from uCode come through here*/
- if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX |
- CSR_INT_BIT_RX_PERIODIC)) {
- IWL_DEBUG_ISR(priv, "Rx interrupt\n");
- if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
- handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
- iwl_write32(priv, CSR_FH_INT_STATUS,
- CSR_FH_INT_RX_MASK);
- }
- if (inta & CSR_INT_BIT_RX_PERIODIC) {
- handled |= CSR_INT_BIT_RX_PERIODIC;
- iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC);
- }
- /* Sending RX interrupt require many steps to be done in the
- * the device:
- * 1- write interrupt to current index in ICT table.
- * 2- dma RX frame.
- * 3- update RX shared data to indicate last write index.
- * 4- send interrupt.
- * This could lead to RX race, driver could receive RX interrupt
- * but the shared data changes does not reflect this;
- * periodic interrupt will detect any dangling Rx activity.
- */
-
- /* Disable periodic interrupt; we use it as just a one-shot. */
- iwl_write8(priv, CSR_INT_PERIODIC_REG,
- CSR_INT_PERIODIC_DIS);
- iwl_rx_handle(priv);
-
- /*
- * Enable periodic interrupt in 8 msec only if we received
- * real RX interrupt (instead of just periodic int), to catch
- * any dangling Rx interrupt. If it was just the periodic
- * interrupt, there was no dangling Rx activity, and no need
- * to extend the periodic interrupt; one-shot is enough.
- */
- if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX))
- iwl_write8(priv, CSR_INT_PERIODIC_REG,
- CSR_INT_PERIODIC_ENA);
-
- priv->isr_stats.rx++;
- }
-
- /* This "Tx" DMA channel is used only for loading uCode */
- if (inta & CSR_INT_BIT_FH_TX) {
- iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK);
- IWL_DEBUG_ISR(priv, "uCode load interrupt\n");
- priv->isr_stats.tx++;
- handled |= CSR_INT_BIT_FH_TX;
- /* Wake up uCode load routine, now that load is complete */
- priv->ucode_write_complete = 1;
- wake_up_interruptible(&priv->wait_command_queue);
- }
-
- if (inta & ~handled) {
- IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
- priv->isr_stats.unhandled++;
- }
-
- if (inta & ~(priv->inta_mask)) {
- IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
- inta & ~priv->inta_mask);
- }
-
- /* Re-enable all interrupts */
- /* only Re-enable if disabled by irq */
- if (test_bit(STATUS_INT_ENABLED, &priv->status))
- iwl_enable_interrupts(priv);
- /* Re-enable RF_KILL if it occurred */
- else if (handled & CSR_INT_BIT_RF_KILL)
- iwl_enable_rfkill_int(priv);
-}
-
-/******************************************************************************
- *
- * ICT functions
- *
- ******************************************************************************/
-#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
-
-/* Free dram table */
-void iwl_free_isr_ict(struct iwl_priv *priv)
-{
- if (priv->ict_tbl_vir) {
- dma_free_coherent(priv->bus->dev,
- (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
- priv->ict_tbl_vir,
- priv->ict_tbl_dma);
- priv->ict_tbl_vir = NULL;
- memset(&priv->ict_tbl_dma, 0,
- sizeof(priv->ict_tbl_dma));
- memset(&priv->aligned_ict_tbl_dma, 0,
- sizeof(priv->aligned_ict_tbl_dma));
- }
-}
-
-
-/* allocate dram shared table it is a PAGE_SIZE aligned
- * also reset all data related to ICT table interrupt.
- */
-int iwl_alloc_isr_ict(struct iwl_priv *priv)
-{
-
- /* allocate shrared data table */
- priv->ict_tbl_vir =
- dma_alloc_coherent(priv->bus->dev,
- (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
- &priv->ict_tbl_dma, GFP_KERNEL);
- if (!priv->ict_tbl_vir)
- return -ENOMEM;
-
- /* align table to PAGE_SIZE boundary */
- priv->aligned_ict_tbl_dma =
- ALIGN(priv->ict_tbl_dma, PAGE_SIZE);
-
- IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
- (unsigned long long)priv->ict_tbl_dma,
- (unsigned long long)priv->aligned_ict_tbl_dma,
- (int)(priv->aligned_ict_tbl_dma -
- priv->ict_tbl_dma));
-
- priv->ict_tbl = priv->ict_tbl_vir +
- (priv->aligned_ict_tbl_dma -
- priv->ict_tbl_dma);
-
- IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n",
- priv->ict_tbl, priv->ict_tbl_vir,
- (int)(priv->aligned_ict_tbl_dma -
- priv->ict_tbl_dma));
-
- /* reset table and index to all 0 */
- memset(priv->ict_tbl_vir, 0,
- (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
- priv->ict_index = 0;
-
- /* add periodic RX interrupt */
- priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
- return 0;
-}
-
-/* Device is going up inform it about using ICT interrupt table,
- * also we need to tell the driver to start using ICT interrupt.
- */
-int iwl_reset_ict(struct iwl_priv *priv)
-{
- u32 val;
- unsigned long flags;
-
- if (!priv->ict_tbl_vir)
- return 0;
-
- spin_lock_irqsave(&priv->lock, flags);
- iwl_disable_interrupts(priv);
-
- memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
-
- val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT;
-
- val |= CSR_DRAM_INT_TBL_ENABLE;
- val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
-
- IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X "
- "aligned dma address %Lx\n",
- val,
- (unsigned long long)priv->aligned_ict_tbl_dma);
-
- iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
- priv->use_ict = true;
- priv->ict_index = 0;
- iwl_write32(priv, CSR_INT, priv->inta_mask);
- iwl_enable_interrupts(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-/* Device is going down disable ict interrupt usage */
-void iwl_disable_ict(struct iwl_priv *priv)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->use_ict = false;
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static irqreturn_t iwl_isr(int irq, void *data)
-{
- struct iwl_priv *priv = data;
- u32 inta, inta_mask;
- unsigned long flags;
-#ifdef CONFIG_IWLWIFI_DEBUG
- u32 inta_fh;
-#endif
- if (!priv)
- return IRQ_NONE;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* 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(priv, CSR_INT_MASK); /* just for debug */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
- /* Discover which interrupts are active/pending */
- inta = iwl_read32(priv, CSR_INT);
-
- /* 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. */
- if (!inta) {
- IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
- goto none;
- }
-
- if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
- /* Hardware disappeared. It might have already raised
- * an interrupt */
- IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
- goto unplugged;
- }
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
- inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
- IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
- "fh 0x%08x\n", inta, inta_mask, inta_fh);
- }
-#endif
-
- priv->inta |= inta;
- /* iwl_irq_tasklet() will service interrupts and re-enable them */
- if (likely(inta))
- tasklet_schedule(&priv->irq_tasklet);
- else if (test_bit(STATUS_INT_ENABLED, &priv->status) &&
- !priv->inta)
- iwl_enable_interrupts(priv);
-
- unplugged:
- spin_unlock_irqrestore(&priv->lock, flags);
- return IRQ_HANDLED;
-
- none:
- /* re-enable interrupts here since we don't have anything to service. */
- /* only Re-enable if disabled by irq and no schedules tasklet. */
- if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
- iwl_enable_interrupts(priv);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- return IRQ_NONE;
-}
-
-/* interrupt handler using ict table, with this interrupt driver will
- * stop using INTA register to get device's interrupt, reading this register
- * is expensive, device will write interrupts in ICT dram table, increment
- * index then will fire interrupt to driver, driver will OR all ICT table
- * entries from current index up to table entry with 0 value. the result is
- * 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)
-{
- struct iwl_priv *priv = data;
- u32 inta, inta_mask;
- u32 val = 0;
- unsigned long flags;
-
- if (!priv)
- return IRQ_NONE;
-
- /* dram interrupt table not set yet,
- * use legacy interrupt.
- */
- if (!priv->use_ict)
- return iwl_isr(irq, data);
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* 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(priv, CSR_INT_MASK); /* just for debug */
- iwl_write32(priv, 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. */
- if (!priv->ict_tbl[priv->ict_index]) {
- IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
- goto none;
- }
-
- /* read all entries that not 0 start with ict_index */
- while (priv->ict_tbl[priv->ict_index]) {
-
- val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]);
- IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
- priv->ict_index,
- le32_to_cpu(
- priv->ict_tbl[priv->ict_index]));
- priv->ict_tbl[priv->ict_index] = 0;
- priv->ict_index = iwl_queue_inc_wrap(priv->ict_index,
- ICT_COUNT);
-
- }
-
- /* We should not get this value, just ignore it. */
- if (val == 0xffffffff)
- val = 0;
-
- /*
- * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
- * (bit 15 before shifting it to 31) to clear when using interrupt
- * coalescing. fortunately, bits 18 and 19 stay set when this happens
- * so we use them to decide on the real state of the Rx bit.
- * In order words, bit 15 is set if bit 18 or bit 19 are set.
- */
- if (val & 0xC0000)
- val |= 0x8000;
-
- inta = (0xff & val) | ((0xff00 & val) << 16);
- IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
- inta, inta_mask, val);
-
- inta &= priv->inta_mask;
- priv->inta |= inta;
-
- /* iwl_irq_tasklet() will service interrupts and re-enable them */
- if (likely(inta))
- tasklet_schedule(&priv->irq_tasklet);
- else if (test_bit(STATUS_INT_ENABLED, &priv->status) &&
- !priv->inta) {
- /* Allow interrupt if was disabled by this handler and
- * no tasklet was schedules, We should not enable interrupt,
- * tasklet will enable it.
- */
- iwl_enable_interrupts(priv);
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
- return IRQ_HANDLED;
-
- none:
- /* re-enable interrupts here since we don't have anything to service.
- * only Re-enable if disabled by irq.
- */
- if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
- iwl_enable_interrupts(priv);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- return IRQ_NONE;
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
index 41f0de914008..1b20c4fb791b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -60,1113 +60,18 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
-#include "iwl-dev.h"
-#include "iwl-trans.h"
-#include "iwl-core.h"
-#include "iwl-helpers.h"
-#include "iwl-trans-int-pcie.h"
-/*TODO remove uneeded includes when the transport layer tx_free will be here */
-#include "iwl-agn.h"
-#include "iwl-core.h"
-
-static int iwl_trans_rx_alloc(struct iwl_priv *priv)
-{
- struct iwl_rx_queue *rxq = &priv->rxq;
- struct device *dev = priv->bus->dev;
-
- memset(&priv->rxq, 0, sizeof(priv->rxq));
-
- spin_lock_init(&rxq->lock);
- INIT_LIST_HEAD(&rxq->rx_free);
- INIT_LIST_HEAD(&rxq->rx_used);
-
- if (WARN_ON(rxq->bd || rxq->rb_stts))
- return -EINVAL;
-
- /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */
- rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
- &rxq->bd_dma, GFP_KERNEL);
- if (!rxq->bd)
- goto err_bd;
- memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE);
-
- /*Allocate the driver's pointer to receive buffer status */
- rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts),
- &rxq->rb_stts_dma, GFP_KERNEL);
- if (!rxq->rb_stts)
- goto err_rb_stts;
- memset(rxq->rb_stts, 0, sizeof(*rxq->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_priv *priv)
-{
- struct iwl_rx_queue *rxq = &priv->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(priv->bus->dev, rxq->pool[i].page_dma,
- PAGE_SIZE << priv->hw_params.rx_page_order,
- DMA_FROM_DEVICE);
- __iwl_free_pages(priv, rxq->pool[i].page);
- rxq->pool[i].page = NULL;
- }
- list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
- }
-}
-
-static void iwl_trans_rx_hw_init(struct iwl_priv *priv,
- struct iwl_rx_queue *rxq)
-{
- u32 rb_size;
- const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
- u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */
-
- rb_timeout = RX_RB_TIMEOUT;
-
- if (iwlagn_mod_params.amsdu_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(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-
- /* Reset driver's Rx queue write index */
- iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
-
- /* Tell device where to find RBD circular buffer in DRAM */
- iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
- (u32)(rxq->bd_dma >> 8));
-
- /* Tell device where in DRAM to update its Rx status */
- iwl_write_direct32(priv, 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(priv, 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 |
- FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
- 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(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
-}
-
-static int iwl_rx_init(struct iwl_priv *priv)
-{
- struct iwl_rx_queue *rxq = &priv->rxq;
- int i, err;
- unsigned long flags;
-
- if (!rxq->bd) {
- err = iwl_trans_rx_alloc(priv);
- 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(priv);
-
- 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);
-
- iwlagn_rx_replenish(priv);
-
- iwl_trans_rx_hw_init(priv, rxq);
-
- spin_lock_irqsave(&priv->lock, flags);
- rxq->need_update = 1;
- iwl_rx_queue_update_write_ptr(priv, rxq);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-static void iwl_trans_rx_free(struct iwl_priv *priv)
-{
- struct iwl_rx_queue *rxq = &priv->rxq;
- unsigned long flags;
-
- /*if rxq->bd is NULL, it means that nothing has been allocated,
- * exit now */
- if (!rxq->bd) {
- IWL_DEBUG_INFO(priv, "Free NULL rx context\n");
- return;
- }
-
- spin_lock_irqsave(&rxq->lock, flags);
- iwl_trans_rxq_free_rx_bufs(priv);
- spin_unlock_irqrestore(&rxq->lock, flags);
-
- dma_free_coherent(priv->bus->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(priv->bus->dev,
- sizeof(struct iwl_rb_status),
- rxq->rb_stts, rxq->rb_stts_dma);
- else
- IWL_DEBUG_INFO(priv, "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_priv *priv)
-{
-
- /* stop Rx DMA */
- iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
- return iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
- FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-}
-
-static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
- struct iwl_dma_ptr *ptr, size_t size)
-{
- if (WARN_ON(ptr->addr))
- return -EINVAL;
-
- ptr->addr = dma_alloc_coherent(priv->bus->dev, size,
- &ptr->dma, GFP_KERNEL);
- if (!ptr->addr)
- return -ENOMEM;
- ptr->size = size;
- return 0;
-}
-
-static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv,
- struct iwl_dma_ptr *ptr)
-{
- if (unlikely(!ptr->addr))
- return;
-
- dma_free_coherent(priv->bus->dev, ptr->size, ptr->addr, ptr->dma);
- memset(ptr, 0, sizeof(*ptr));
-}
-
-static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq,
- int slots_num, u32 txq_id)
-{
- size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
- int i;
-
- if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds))
- return -EINVAL;
-
- txq->q.n_window = slots_num;
-
- txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num,
- GFP_KERNEL);
- txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num,
- GFP_KERNEL);
-
- if (!txq->meta || !txq->cmd)
- goto error;
-
- for (i = 0; i < slots_num; i++) {
- txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),
- GFP_KERNEL);
- if (!txq->cmd[i])
- goto error;
- }
-
- /* Alloc driver data array and TFD circular buffer */
- /* Driver private data, only for Tx (not command) queues,
- * not shared with device. */
- if (txq_id != priv->cmd_queue) {
- txq->txb = kzalloc(sizeof(txq->txb[0]) *
- TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
- if (!txq->txb) {
- IWL_ERR(priv, "kmalloc for auxiliary BD "
- "structures failed\n");
- goto error;
- }
- } else {
- txq->txb = NULL;
- }
-
- /* Circular buffer of transmit frame descriptors (TFDs),
- * shared with device */
- txq->tfds = dma_alloc_coherent(priv->bus->dev, tfd_sz, &txq->q.dma_addr,
- GFP_KERNEL);
- if (!txq->tfds) {
- IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
- goto error;
- }
- txq->q.id = txq_id;
-
- return 0;
-error:
- kfree(txq->txb);
- txq->txb = NULL;
- /* since txq->cmd has been zeroed,
- * all non allocated cmd[i] will be NULL */
- if (txq->cmd)
- for (i = 0; i < slots_num; i++)
- kfree(txq->cmd[i]);
- kfree(txq->meta);
- kfree(txq->cmd);
- txq->meta = NULL;
- txq->cmd = NULL;
-
- return -ENOMEM;
-
-}
-
-static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
- int slots_num, u32 txq_id)
-{
- int ret;
-
- txq->need_update = 0;
- memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num);
-
- /*
- * For the default queues 0-3, set up the swq_id
- * already -- all others need to get one later
- * (if they need one at all).
- */
- if (txq_id < 4)
- iwl_set_swq_id(txq, txq_id, txq_id);
-
- /* 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(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
- txq_id);
- if (ret)
- return ret;
-
- /*
- * 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(priv, 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_priv *priv, int txq_id)
-{
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct iwl_queue *q = &txq->q;
-
- if (!q->n_bd)
- return;
-
- while (q->write_ptr != q->read_ptr) {
- /* The read_ptr needs to bound by q->n_window */
- iwlagn_txq_free_tfd(priv, txq, get_cmd_index(q, q->read_ptr));
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
- }
-}
-
-/**
- * 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_priv *priv, int txq_id)
-{
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct device *dev = priv->bus->dev;
- int i;
- if (WARN_ON(!txq))
- return;
-
- iwl_tx_queue_unmap(priv, txq_id);
-
- /* De-alloc array of command/tx buffers */
- for (i = 0; i < txq->q.n_window; i++)
- kfree(txq->cmd[i]);
-
- /* De-alloc circular buffer of TFDs */
- if (txq->q.n_bd) {
- dma_free_coherent(dev, priv->hw_params.tfd_size *
- txq->q.n_bd, txq->tfds, txq->q.dma_addr);
- memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
- }
-
- /* De-alloc array of per-TFD driver data */
- kfree(txq->txb);
- txq->txb = NULL;
-
- /* deallocate arrays */
- kfree(txq->cmd);
- kfree(txq->meta);
- txq->cmd = NULL;
- txq->meta = NULL;
-
- /* 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_tx_free(struct iwl_priv *priv)
-{
- int txq_id;
-
- /* Tx queues */
- if (priv->txq) {
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- iwl_tx_queue_free(priv, txq_id);
- }
-
- kfree(priv->txq);
- priv->txq = NULL;
-
- iwlagn_free_dma_ptr(priv, &priv->kw);
-
- iwlagn_free_dma_ptr(priv, &priv->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_priv *priv)
-{
- int ret;
- int txq_id, slots_num;
-
- /*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(priv->txq)) {
- ret = -EINVAL;
- goto error;
- }
-
- ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
- priv->hw_params.scd_bc_tbls_size);
- if (ret) {
- IWL_ERR(priv, "Scheduler BC Table allocation failed\n");
- goto error;
- }
-
- /* Alloc keep-warm buffer */
- ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
- if (ret) {
- IWL_ERR(priv, "Keep Warm allocation failed\n");
- goto error;
- }
-
- priv->txq = kzalloc(sizeof(struct iwl_tx_queue) *
- priv->cfg->base_params->num_of_queues, GFP_KERNEL);
- if (!priv->txq) {
- IWL_ERR(priv, "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 < priv->hw_params.max_txq_num; txq_id++) {
- slots_num = (txq_id == priv->cmd_queue) ?
- TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
- ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num,
- txq_id);
- if (ret) {
- IWL_ERR(priv, "Tx %d queue alloc failed\n", txq_id);
- goto error;
- }
- }
-
- return 0;
-
-error:
- trans_tx_free(&priv->trans);
-
- return ret;
-}
-static int iwl_tx_init(struct iwl_priv *priv)
-{
- int ret;
- int txq_id, slots_num;
- unsigned long flags;
- bool alloc = false;
-
- if (!priv->txq) {
- ret = iwl_trans_tx_alloc(priv);
- if (ret)
- goto error;
- alloc = true;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Turn off all Tx DMA fifos */
- iwl_write_prph(priv, SCD_TXFACT, 0);
-
- /* Tell NIC where to find the "keep warm" buffer */
- iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* Alloc and init all Tx queues, including the command queue (#4/#9) */
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
- slots_num = (txq_id == priv->cmd_queue) ?
- TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
- ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num,
- txq_id);
- if (ret) {
- IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
- goto error;
- }
- }
-
- return 0;
-error:
- /*Upon error, free only if we allocated something */
- if (alloc)
- trans_tx_free(&priv->trans);
- return ret;
-}
-
-static void iwl_set_pwr_vmain(struct iwl_priv *priv)
-{
-/*
- * (for documentation purposes)
- * to set power to V_AUX, do:
-
- if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
- iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
- APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
- ~APMG_PS_CTRL_MSK_PWR_SRC);
- */
-
- iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
- APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
- ~APMG_PS_CTRL_MSK_PWR_SRC);
-}
-
-static int iwl_nic_init(struct iwl_priv *priv)
-{
- unsigned long flags;
-
- /* nic_init */
- spin_lock_irqsave(&priv->lock, flags);
- iwl_apm_init(priv);
-
- /* Set interrupt coalescing calibration timer to default (512 usecs) */
- iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- iwl_set_pwr_vmain(priv);
-
- priv->cfg->lib->nic_config(priv);
-
- /* Allocate the RX queue, or reset if it is already allocated */
- iwl_rx_init(priv);
-
- /* Allocate or reset and init all Tx and Command queues */
- if (iwl_tx_init(priv))
- return -ENOMEM;
-
- if (priv->cfg->base_params->shadow_reg_enable) {
- /* enable shadow regs in HW */
- iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL,
- 0x800FFFFF);
- }
-
- set_bit(STATUS_INIT, &priv->status);
-
- return 0;
-}
-
-#define HW_READY_TIMEOUT (50)
-
-/* Note: returns poll_bit return value, which is >= 0 if success */
-static int iwl_set_hw_ready(struct iwl_priv *priv)
-{
- int ret;
-
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
-
- /* See if we got it */
- ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
- CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
- HW_READY_TIMEOUT);
-
- IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : "");
- return ret;
-}
-
-/* Note: returns standard 0/-ERROR code */
-static int iwl_trans_prepare_card_hw(struct iwl_priv *priv)
-{
- int ret;
-
- IWL_DEBUG_INFO(priv, "iwl_trans_prepare_card_hw enter\n");
-
- ret = iwl_set_hw_ready(priv);
- if (ret >= 0)
- return 0;
-
- /* If HW is not ready, prepare the conditions to check again */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_PREPARE);
-
- ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
- ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
- CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
-
- if (ret < 0)
- return ret;
-
- /* HW should be ready by now, check again. */
- ret = iwl_set_hw_ready(priv);
- if (ret >= 0)
- return 0;
- return ret;
-}
-
-static int iwl_trans_start_device(struct iwl_priv *priv)
-{
- int ret;
-
- priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
-
- if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) &&
- iwl_trans_prepare_card_hw(priv)) {
- IWL_WARN(priv, "Exit HW not ready\n");
- return -EIO;
- }
-
- /* If platform's RF_KILL switch is NOT set to KILL */
- if (iwl_read32(priv, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
- else
- set_bit(STATUS_RF_KILL_HW, &priv->status);
-
- if (iwl_is_rfkill(priv)) {
- wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
- iwl_enable_interrupts(priv);
- return -ERFKILL;
- }
-
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-
- ret = iwl_nic_init(priv);
- if (ret) {
- IWL_ERR(priv, "Unable to init nic\n");
- return ret;
- }
-
- /* make sure rfkill handshake bits are cleared */
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
- CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
- /* clear (again), then enable host interrupts */
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
- iwl_enable_interrupts(priv);
-
- /* really make sure rfkill handshake bits are cleared */
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
- return 0;
-}
-
-/*
- * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- * must be called under priv->lock and mac access
- */
-static void iwl_trans_txq_set_sched(struct iwl_priv *priv, u32 mask)
-{
- iwl_write_prph(priv, SCD_TXFACT, mask);
-}
-
-#define IWL_AC_UNSET -1
-
-struct queue_to_fifo_ac {
- s8 fifo, ac;
-};
-
-static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = {
- { IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
- { IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
- { IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
- { IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
- { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
- { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
- { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
- { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
- { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
- { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-};
-
-static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = {
- { IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
- { IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
- { IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
- { IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
- { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, },
- { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, },
- { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, },
- { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, },
- { IWL_TX_FIFO_BE_IPAN, 2, },
- { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
-};
-static void iwl_trans_tx_start(struct iwl_priv *priv)
-{
- const struct queue_to_fifo_ac *queue_to_fifo;
- struct iwl_rxon_context *ctx;
- u32 a;
- unsigned long flags;
- int i, chan;
- u32 reg_val;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- priv->scd_base_addr = iwl_read_prph(priv, SCD_SRAM_BASE_ADDR);
- a = priv->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND;
- /* reset conext data memory */
- for (; a < priv->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND;
- a += 4)
- iwl_write_targ_mem(priv, a, 0);
- /* reset tx status memory */
- for (; a < priv->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND;
- a += 4)
- iwl_write_targ_mem(priv, a, 0);
- for (; a < priv->scd_base_addr +
- SCD_TRANS_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
- iwl_write_targ_mem(priv, a, 0);
-
- iwl_write_prph(priv, SCD_DRAM_BASE_ADDR,
- priv->scd_bc_tbls.dma >> 10);
-
- /* Enable DMA channel */
- for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++)
- iwl_write_direct32(priv, 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(priv, FH_TX_CHICKEN_BITS_REG);
- iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
- reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
-
- iwl_write_prph(priv, SCD_QUEUECHAIN_SEL,
- SCD_QUEUECHAIN_SEL_ALL(priv));
- iwl_write_prph(priv, SCD_AGGR_SEL, 0);
-
- /* initiate the queues */
- for (i = 0; i < priv->hw_params.max_txq_num; i++) {
- iwl_write_prph(priv, SCD_QUEUE_RDPTR(i), 0);
- iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
- iwl_write_targ_mem(priv, priv->scd_base_addr +
- SCD_CONTEXT_QUEUE_OFFSET(i), 0);
- iwl_write_targ_mem(priv, priv->scd_base_addr +
- SCD_CONTEXT_QUEUE_OFFSET(i) +
- sizeof(u32),
- ((SCD_WIN_SIZE <<
- SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
- SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
- ((SCD_FRAME_LIMIT <<
- SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
- SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
- }
-
- iwl_write_prph(priv, SCD_INTERRUPT_MASK,
- IWL_MASK(0, priv->hw_params.max_txq_num));
-
- /* Activate all Tx DMA/FIFO channels */
- iwl_trans_txq_set_sched(priv, IWL_MASK(0, 7));
-
- /* map queues to FIFOs */
- if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
- queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
- else
- queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
-
- iwl_trans_set_wr_ptrs(priv, priv->cmd_queue, 0);
-
- /* make sure all queue are not stopped */
- memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
- for (i = 0; i < 4; i++)
- atomic_set(&priv->queue_stop_count[i], 0);
- for_each_context(priv, ctx)
- ctx->last_tx_rejected = false;
-
- /* reset to 0 to enable all the queue first */
- priv->txq_ctx_active_msk = 0;
-
- BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
- BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10);
-
- for (i = 0; i < 10; i++) {
- int fifo = queue_to_fifo[i].fifo;
- int ac = queue_to_fifo[i].ac;
-
- iwl_txq_ctx_activate(priv, i);
-
- if (fifo == IWL_TX_FIFO_UNUSED)
- continue;
-
- if (ac != IWL_AC_UNSET)
- iwl_set_swq_id(&priv->txq[i], ac, i);
- iwl_trans_tx_queue_set_status(priv, &priv->txq[i], fifo, 0);
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* Enable L1-Active */
- iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG,
- APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
-}
-
-/**
- * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
- */
-static int iwl_trans_tx_stop(struct iwl_priv *priv)
-{
- int ch, txq_id;
- unsigned long flags;
-
- /* Turn off all Tx DMA fifos */
- spin_lock_irqsave(&priv->lock, flags);
-
- iwl_trans_txq_set_sched(priv, 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(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
- if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
- FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
- 1000))
- IWL_ERR(priv, "Failing on timeout while stopping"
- " DMA channel %d [0x%08x]", ch,
- iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG));
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (!priv->txq) {
- IWL_WARN(priv, "Stopping tx queues that aren't allocated...");
- return 0;
- }
-
- /* Unmap DMA from host system and free skb's */
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- iwl_tx_queue_unmap(priv, txq_id);
-
- return 0;
-}
-
-static void iwl_trans_stop_device(struct iwl_priv *priv)
-{
- unsigned long flags;
-
- /* stop and reset the on-board processor */
- iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
- /* tell the device to stop sending interrupts */
- spin_lock_irqsave(&priv->lock, flags);
- iwl_disable_interrupts(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
- trans_sync_irq(&priv->trans);
-
- /* device going down, Stop using ICT table */
- iwl_disable_ict(priv);
-
- /*
- * If a HW restart happens during firmware loading,
- * then the firmware loading might call this function
- * and later it might be called again due to the
- * restart. So don't process again if the device is
- * already dead.
- */
- if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) {
- iwl_trans_tx_stop(priv);
- iwl_trans_rx_stop(priv);
-
- /* Power-down device's busmaster DMA clocks */
- iwl_write_prph(priv, APMG_CLK_DIS_REG,
- APMG_CLK_VAL_DMA_CLK_RQT);
- udelay(5);
- }
-
- /* Make sure (redundant) we've released our request to stay awake */
- iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
- /* Stop the device, and put it in low power state */
- iwl_apm_stop(priv);
-}
-
-static struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_priv *priv,
- int txq_id)
-{
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct iwl_queue *q = &txq->q;
- struct iwl_device_cmd *dev_cmd;
-
- if (unlikely(iwl_queue_space(q) < q->high_mark))
- return NULL;
-
- /*
- * Set up the Tx-command (not MAC!) header.
- * Store the chosen Tx queue and TFD index within the sequence field;
- * after Tx, uCode's Tx response will return this value so driver can
- * locate the frame within the tx queue and do post-tx processing.
- */
- dev_cmd = txq->cmd[q->write_ptr];
- memset(dev_cmd, 0, sizeof(*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)));
- return &dev_cmd->cmd.tx;
-}
-
-static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb,
- struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu,
- struct iwl_rxon_context *ctx)
-{
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct iwl_queue *q = &txq->q;
- struct iwl_device_cmd *dev_cmd = txq->cmd[q->write_ptr];
- struct iwl_cmd_meta *out_meta;
-
- 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;
- u8 hdr_len = ieee80211_hdrlen(fc);
-
- /* Set up driver data for this TFD */
- memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
- txq->txb[q->write_ptr].skb = skb;
- txq->txb[q->write_ptr].ctx = ctx;
-
- /* Set up first empty entry in queue's array of Tx/cmd buffers */
- out_meta = &txq->meta[q->write_ptr];
-
- /*
- * 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(priv->bus->dev,
- &dev_cmd->hdr, firstlen,
- DMA_BIDIRECTIONAL);
- if (unlikely(dma_mapping_error(priv->bus->dev, txcmd_phys)))
- return -1;
- 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(priv->bus->dev, skb->data + hdr_len,
- secondlen, DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) {
- dma_unmap_single(priv->bus->dev,
- dma_unmap_addr(out_meta, mapping),
- dma_unmap_len(out_meta, len),
- DMA_BIDIRECTIONAL);
- return -1;
- }
- }
-
- /* Attach buffers to TFD */
- iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1);
- if (secondlen > 0)
- iwlagn_txq_attach_buf_to_tfd(priv, 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(priv->bus->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(priv, "sequence nr = 0X%x\n",
- le16_to_cpu(dev_cmd->hdr.sequence));
- IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
- iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
- iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
-
- /* Set up entry for this TFD in Tx byte-count array */
- if (ampdu)
- iwl_trans_txq_update_byte_cnt_tbl(priv, txq,
- le16_to_cpu(tx_cmd->len));
-
- dma_sync_single_for_device(priv->bus->dev, txcmd_phys, firstlen,
- DMA_BIDIRECTIONAL);
-
- trace_iwlwifi_dev_tx(priv,
- &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
- sizeof(struct iwl_tfd),
- &dev_cmd->hdr, firstlen,
- skb->data + hdr_len, secondlen);
-
- /* 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(priv, 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) && priv->mac80211_registered) {
- if (wait_write_ptr) {
- txq->need_update = 1;
- iwl_txq_update_write_ptr(priv, txq);
- } else {
- iwl_stop_queue(priv, txq);
- }
- }
- return 0;
-}
-
-static void iwl_trans_kick_nic(struct iwl_priv *priv)
-{
- /* Remove all resets to allow NIC to operate */
- iwl_write32(priv, CSR_RESET, 0);
-}
-
-static void iwl_trans_sync_irq(struct iwl_priv *priv)
-{
- /* wait to make sure we flush pending tasklet*/
- synchronize_irq(priv->bus->irq);
- tasklet_kill(&priv->irq_tasklet);
-}
-
-static void iwl_trans_free(struct iwl_priv *priv)
-{
- free_irq(priv->bus->irq, priv);
- iwl_free_isr_ict(priv);
-}
-
-static const struct iwl_trans_ops trans_ops = {
- .start_device = iwl_trans_start_device,
- .prepare_card_hw = iwl_trans_prepare_card_hw,
- .stop_device = iwl_trans_stop_device,
-
- .tx_start = iwl_trans_tx_start,
-
- .rx_free = iwl_trans_rx_free,
- .tx_free = iwl_trans_tx_free,
-
- .send_cmd = iwl_send_cmd,
- .send_cmd_pdu = iwl_send_cmd_pdu,
-
- .get_tx_cmd = iwl_trans_get_tx_cmd,
- .tx = iwl_trans_tx,
-
- .txq_agg_disable = iwl_trans_txq_agg_disable,
- .txq_agg_setup = iwl_trans_txq_agg_setup,
-
- .kick_nic = iwl_trans_kick_nic,
-
- .sync_irq = iwl_trans_sync_irq,
- .free = iwl_trans_free,
-};
+#include "iwl-trans.h"
-int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv)
+int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
+ u32 flags, u16 len, const void *data)
{
- int err;
-
- priv->trans.ops = &trans_ops;
- priv->trans.priv = priv;
-
- tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
- iwl_irq_tasklet, (unsigned long)priv);
-
- iwl_alloc_isr_ict(priv);
-
- err = request_irq(priv->bus->irq, iwl_isr_ict, IRQF_SHARED,
- DRV_NAME, priv);
- if (err) {
- IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus->irq);
- iwl_free_isr_ict(priv);
- return err;
- }
-
- INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
+ struct iwl_host_cmd cmd = {
+ .id = id,
+ .len = { len, },
+ .data = { data, },
+ .flags = flags,
+ };
- return 0;
+ return iwl_trans_send_cmd(trans, &cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 7993aa7ae668..c5923125c3f9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -63,163 +63,289 @@
#ifndef __iwl_trans_h__
#define __iwl_trans_h__
+#include <linux/debugfs.h>
+#include <linux/skbuff.h>
+
+#include "iwl-shared.h"
+#include "iwl-commands.h"
+
/*This file includes the declaration that are exported from the transport
* layer */
struct iwl_priv;
-struct iwl_rxon_context;
-struct iwl_host_cmd;
+struct iwl_shared;
+
+#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
+#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
+
+enum {
+ CMD_SYNC = 0,
+ CMD_ASYNC = BIT(0),
+ CMD_WANT_SKB = BIT(1),
+ CMD_ON_DEMAND = BIT(2),
+};
+
+#define DEF_CMD_PAYLOAD_SIZE 320
+
+/**
+ * struct iwl_device_cmd
+ *
+ * For allocation of the command and tx queues, this establishes the overall
+ * size of the largest command we send to uCode, except for commands that
+ * aren't fully copied and use other TFD space.
+ */
+struct iwl_device_cmd {
+ struct iwl_cmd_header hdr; /* uCode API */
+ u8 payload[DEF_CMD_PAYLOAD_SIZE];
+} __packed;
+
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
+
+#define IWL_MAX_CMD_TFDS 2
+
+enum iwl_hcmd_dataflag {
+ IWL_HCMD_DFL_NOCOPY = BIT(0),
+};
+
+/**
+ * struct iwl_host_cmd - Host command to the uCode
+ * @data: array of chunks that composes the data of the host command
+ * @reply_page: pointer to the page that holds the response to the host command
+ * @handler_status: return value of the handler of the command
+ * (put in setup_rx_handlers) - valid for SYNC mode only
+ * @callback:
+ * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
+ * @len: array of the lenths of the chunks in data
+ * @dataflags:
+ * @id: id of the host command
+ */
+struct iwl_host_cmd {
+ const void *data[IWL_MAX_CMD_TFDS];
+ unsigned long reply_page;
+ int handler_status;
+
+ u32 flags;
+ u16 len[IWL_MAX_CMD_TFDS];
+ u8 dataflags[IWL_MAX_CMD_TFDS];
+ u8 id;
+};
/**
* struct iwl_trans_ops - transport specific operations
+ * @alloc: allocates the meta data (not the queues themselves)
+ * @request_irq: requests IRQ - will be called before the FW load in probe flow
* @start_device: allocates and inits all the resources for the transport
* layer.
* @prepare_card_hw: claim the ownership on the HW. Will be called during
* probe.
* @tx_start: starts and configures all the Tx fifo - usually done once the fw
* is alive.
+ * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
* @stop_device:stops the whole device (embedded CPU put to reset)
- * @rx_free: frees the rx memory
- * @tx_free: frees the tx memory
* @send_cmd:send a host command
- * @send_cmd_pdu:send a host command: flags can be CMD_*
- * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use
* @tx: send an skb
- * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
+ * @reclaim: free packet until ssn. Returns a list of freed packets.
+ * @tx_agg_alloc: allocate resources for a TX BA session
+ * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
* ready and a successful ADDBA response has been received.
- * @txq_agg_disable: de-configure a Tx queue to send AMPDUs
+ * @tx_agg_disable: de-configure a Tx queue to send AMPDUs
* @kick_nic: remove the RESET from the embedded CPU and let it run
- * @sync_irq: the upper layer will typically disable interrupt and call this
- * handler. After this handler returns, it is guaranteed that all
- * the ISR / tasklet etc... have finished running and the transport
- * layer shall not pass any Rx.
* @free: release all the ressource for the transport layer itself such as
* irq, tasklet etc...
+ * @stop_queue: stop a specific queue
+ * @check_stuck_queue: check if a specific queue is stuck
+ * @wait_tx_queue_empty: wait until all tx queues are empty
+ * @dbgfs_register: add the dbgfs files under this directory. Files will be
+ * automatically deleted.
+ * @suspend: stop the device unless WoWLAN is configured
+ * @resume: resume activity of the device
*/
struct iwl_trans_ops {
- int (*start_device)(struct iwl_priv *priv);
- int (*prepare_card_hw)(struct iwl_priv *priv);
- void (*stop_device)(struct iwl_priv *priv);
- void (*tx_start)(struct iwl_priv *priv);
- void (*tx_free)(struct iwl_priv *priv);
- void (*rx_free)(struct iwl_priv *priv);
+ struct iwl_trans *(*alloc)(struct iwl_shared *shrd);
+ int (*request_irq)(struct iwl_trans *iwl_trans);
+ int (*start_device)(struct iwl_trans *trans);
+ int (*prepare_card_hw)(struct iwl_trans *trans);
+ void (*stop_device)(struct iwl_trans *trans);
+ void (*tx_start)(struct iwl_trans *trans);
+
+ void (*wake_any_queue)(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx);
- int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+ int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
- int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len,
- const void *data);
- struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_priv *priv, int txq_id);
- int (*tx)(struct iwl_priv *priv, struct sk_buff *skb,
- struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu,
- struct iwl_rxon_context *ctx);
+ int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
+ struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
+ u8 sta_id);
+ void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
+ int txq_id, int ssn, u32 status,
+ struct sk_buff_head *skbs);
- int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id,
- u16 ssn_idx, u8 tx_fifo);
- void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid,
- int frame_limit);
+ int (*tx_agg_disable)(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx, int sta_id,
+ int tid);
+ int (*tx_agg_alloc)(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx, int sta_id, int tid,
+ u16 *ssn);
+ void (*tx_agg_setup)(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx, int sta_id, int tid,
+ int frame_limit);
- void (*kick_nic)(struct iwl_priv *priv);
+ void (*kick_nic)(struct iwl_trans *trans);
- void (*sync_irq)(struct iwl_priv *priv);
- void (*free)(struct iwl_priv *priv);
+ void (*free)(struct iwl_trans *trans);
+
+ void (*stop_queue)(struct iwl_trans *trans, int q);
+
+ int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
+ int (*check_stuck_queue)(struct iwl_trans *trans, int q);
+ int (*wait_tx_queue_empty)(struct iwl_trans *trans);
+#ifdef CONFIG_PM_SLEEP
+ int (*suspend)(struct iwl_trans *trans);
+ int (*resume)(struct iwl_trans *trans);
+#endif
};
+/**
+ * struct iwl_trans - transport common data
+ * @ops - pointer to iwl_trans_ops
+ * @shrd - pointer to iwl_shared which holds shared data from the upper layer
+ * @hcmd_lock: protects HCMD
+ */
struct iwl_trans {
const struct iwl_trans_ops *ops;
- struct iwl_priv *priv;
+ struct iwl_shared *shrd;
+ spinlock_t hcmd_lock;
+
+ /* pointer to trans specific struct */
+ /*Ensure that this pointer will always be aligned to sizeof pointer */
+ char trans_specific[0] __attribute__((__aligned__(sizeof(void *))));
};
-static inline int trans_start_device(struct iwl_trans *trans)
+static inline int iwl_trans_request_irq(struct iwl_trans *trans)
{
- return trans->ops->start_device(trans->priv);
+ return trans->ops->request_irq(trans);
}
-static inline int trans_prepare_card_hw(struct iwl_trans *trans)
+static inline int iwl_trans_start_device(struct iwl_trans *trans)
{
- return trans->ops->prepare_card_hw(trans->priv);
+ return trans->ops->start_device(trans);
}
-static inline void trans_stop_device(struct iwl_trans *trans)
+static inline int iwl_trans_prepare_card_hw(struct iwl_trans *trans)
{
- trans->ops->stop_device(trans->priv);
+ return trans->ops->prepare_card_hw(trans);
}
-static inline void trans_tx_start(struct iwl_trans *trans)
+static inline void iwl_trans_stop_device(struct iwl_trans *trans)
{
- trans->ops->tx_start(trans->priv);
+ trans->ops->stop_device(trans);
}
-static inline void trans_rx_free(struct iwl_trans *trans)
+static inline void iwl_trans_tx_start(struct iwl_trans *trans)
{
- trans->ops->rx_free(trans->priv);
+ trans->ops->tx_start(trans);
}
-static inline void trans_tx_free(struct iwl_trans *trans)
+static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx)
{
- trans->ops->tx_free(trans->priv);
+ trans->ops->wake_any_queue(trans, ctx);
}
-static inline int trans_send_cmd(struct iwl_trans *trans,
+
+static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
- return trans->ops->send_cmd(trans->priv, cmd);
+ return trans->ops->send_cmd(trans, cmd);
+}
+
+int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
+ u32 flags, u16 len, const void *data);
+
+static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
+ struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
+ u8 sta_id)
+{
+ return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id);
}
-static inline int trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags,
- u16 len, const void *data)
+static inline void iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
+ int tid, int txq_id, int ssn, u32 status,
+ struct sk_buff_head *skbs)
{
- return trans->ops->send_cmd_pdu(trans->priv, id, flags, len, data);
+ trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, status, skbs);
}
-static inline struct iwl_tx_cmd *trans_get_tx_cmd(struct iwl_trans *trans,
- int txq_id)
+static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx,
+ int sta_id, int tid)
{
- return trans->ops->get_tx_cmd(trans->priv, txq_id);
+ return trans->ops->tx_agg_disable(trans, ctx, sta_id, tid);
}
-static inline int trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
- struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu,
- struct iwl_rxon_context *ctx)
+static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx,
+ int sta_id, int tid, u16 *ssn)
{
- return trans->ops->tx(trans->priv, skb, tx_cmd, txq_id, fc, ampdu, ctx);
+ return trans->ops->tx_agg_alloc(trans, ctx, sta_id, tid, ssn);
}
-static inline int trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id,
- u16 ssn_idx, u8 tx_fifo)
+
+static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans,
+ enum iwl_rxon_context_id ctx,
+ int sta_id, int tid,
+ int frame_limit)
{
- return trans->ops->txq_agg_disable(trans->priv, txq_id,
- ssn_idx, tx_fifo);
+ trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit);
}
-static inline void trans_txq_agg_setup(struct iwl_trans *trans, int sta_id,
- int tid, int frame_limit)
+static inline void iwl_trans_kick_nic(struct iwl_trans *trans)
{
- trans->ops->txq_agg_setup(trans->priv, sta_id, tid, frame_limit);
+ trans->ops->kick_nic(trans);
}
-static inline void trans_kick_nic(struct iwl_trans *trans)
+static inline void iwl_trans_free(struct iwl_trans *trans)
{
- trans->ops->kick_nic(trans->priv);
+ trans->ops->free(trans);
}
-static inline void trans_sync_irq(struct iwl_trans *trans)
+static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q)
{
- trans->ops->sync_irq(trans->priv);
+ trans->ops->stop_queue(trans, q);
}
-static inline void trans_free(struct iwl_trans *trans)
+static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
+{
+ return trans->ops->wait_tx_queue_empty(trans);
+}
+
+static inline int iwl_trans_check_stuck_queue(struct iwl_trans *trans, int q)
+{
+ return trans->ops->check_stuck_queue(trans, q);
+}
+static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
+ struct dentry *dir)
{
- trans->ops->free(trans->priv);
+ return trans->ops->dbgfs_register(trans, dir);
}
-int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv);
+#ifdef CONFIG_PM_SLEEP
+static inline int iwl_trans_suspend(struct iwl_trans *trans)
+{
+ return trans->ops->suspend(trans);
+}
-/*TODO: this functions should NOT be exported from trans module - export it
- * until the reclaim flow will be brought to the transport module too */
+static inline int iwl_trans_resume(struct iwl_trans *trans)
+{
+ return trans->ops->resume(trans);
+}
+#endif
-struct iwl_tx_queue;
-void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
- struct iwl_tx_queue *txq);
+/*****************************************************
+* Transport layers implementations
+******************************************************/
+extern const struct iwl_trans_ops trans_ops_pcie;
#endif /* __iwl_trans_h__ */
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
index ed57e4402800..c42be81e979e 100644
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
@@ -187,13 +187,17 @@ static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
struct key_params*))
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
- struct iwm_key *key = &iwm->keys[key_index];
+ struct iwm_key *key;
struct key_params params;
IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
+ if (key_index >= IWM_NUM_KEYS)
+ return -ENOENT;
+
memset(&params, 0, sizeof(params));
+ key = &iwm->keys[key_index];
params.cipher = key->cipher;
params.key_len = key->key_len;
params.seq_len = key->seq_len;
diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
index 1453eec82a99..91f2ca90c70f 100644
--- a/drivers/net/wireless/libertas/README
+++ b/drivers/net/wireless/libertas/README
@@ -238,28 +238,3 @@ hostsleep
echo "1" > hostsleep : enable host sleep.
echo "0" > hostsleep : disable host sleep
-========================
-IWCONFIG COMMANDS
-========================
-power period
-
- This command is used to configure the station in deep sleep mode /
- auto deep sleep mode.
-
- The timer is implemented to monitor the activities (command, event,
- etc.). When an activity is detected station will exit from deep
- sleep mode automatically and restart the timer. At timer expiry
- (no activity for defined time period) the deep sleep mode is entered
- automatically.
-
- Note: this command is for SDIO interface only.
-
- Usage:
- To enable deep sleep mode do:
- iwconfig wlan0 power period 0
- To enable auto deep sleep mode with idle time period 5 seconds do:
- iwconfig wlan0 power period 5
- To disable deep sleep/auto deep sleep mode do:
- iwconfig wlan0 power period -1
-
-==============================================================================
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index b456a53b64b1..ff6378276ff0 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -19,6 +19,7 @@
#include "decl.h"
#include "cfg.h"
#include "cmd.h"
+#include "mesh.h"
#define CHAN2G(_channel, _freq, _flags) { \
@@ -442,13 +443,16 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy,
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);
+ lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d, type %d",
+ netdev_name(netdev), channel->center_freq, channel_type);
if (channel_type != NL80211_CHAN_NO_HT)
goto out;
- ret = lbs_set_channel(priv, channel->hw_value);
+ if (netdev == priv->mesh_dev)
+ ret = lbs_mesh_set_channel(priv, channel->hw_value);
+ else
+ ret = lbs_set_channel(priv, channel->hw_value);
out:
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
@@ -691,7 +695,7 @@ static void lbs_scan_worker(struct work_struct *work)
tlv = scan_cmd->tlvbuffer;
/* add SSID TLV */
- if (priv->scan_req->n_ssids)
+ if (priv->scan_req->n_ssids && priv->scan_req->ssids[0].ssid_len > 0)
tlv += lbs_add_ssid_tlv(tlv,
priv->scan_req->ssids[0].ssid,
priv->scan_req->ssids[0].ssid_len);
@@ -708,7 +712,7 @@ static void lbs_scan_worker(struct work_struct *work)
if (priv->scan_channel < priv->scan_req->n_channels) {
cancel_delayed_work(&priv->scan_work);
- if (!priv->stopping)
+ if (netif_running(priv->dev))
queue_delayed_work(priv->work_thread, &priv->scan_work,
msecs_to_jiffies(300));
}
@@ -732,7 +736,6 @@ static void lbs_scan_worker(struct work_struct *work)
cfg80211_scan_done(priv->scan_req, false);
priv->scan_req = NULL;
- priv->last_scan = jiffies;
}
/* Restart network */
@@ -1292,27 +1295,32 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
int ret = 0;
u8 preamble = RADIO_PREAMBLE_SHORT;
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
lbs_deb_enter(LBS_DEB_CFG80211);
if (!sme->bssid) {
- /* Run a scan if one isn't in-progress already and if the last
- * scan was done more than 2 seconds ago.
- */
- if (priv->scan_req == NULL &&
- time_after(jiffies, priv->last_scan + (2 * HZ))) {
- struct cfg80211_scan_request *creq;
+ struct cfg80211_scan_request *creq;
- creq = _new_connect_scan_req(wiphy, sme);
- if (!creq) {
- ret = -EINVAL;
- goto done;
- }
+ /*
+ * Scan for the requested network after waiting for existing
+ * scans to finish.
+ */
+ lbs_deb_assoc("assoc: waiting for existing scans\n");
+ wait_event_interruptible_timeout(priv->scan_q,
+ (priv->scan_req == NULL),
+ (15 * HZ));
- lbs_deb_assoc("assoc: scanning for compatible AP\n");
- _internal_start_scan(priv, true, creq);
+ creq = _new_connect_scan_req(wiphy, sme);
+ if (!creq) {
+ ret = -EINVAL;
+ goto done;
}
- /* Wait for any in-progress scan to complete */
+ lbs_deb_assoc("assoc: scanning for compatible AP\n");
+ _internal_start_scan(priv, true, creq);
+
lbs_deb_assoc("assoc: waiting for scan to complete\n");
wait_event_interruptible_timeout(priv->scan_q,
(priv->scan_req == NULL),
@@ -1402,28 +1410,23 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
-static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
- u16 reason_code)
+int lbs_disconnect(struct lbs_private *priv, u16 reason)
{
- struct lbs_private *priv = wiphy_priv(wiphy);
struct cmd_ds_802_11_deauthenticate cmd;
-
- lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
-
- /* store for lbs_cfg_ret_disconnect() */
- priv->disassoc_reason = reason_code;
+ int ret;
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
/* Mildly ugly to use a locally store my own BSSID ... */
memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN);
- cmd.reasoncode = cpu_to_le16(reason_code);
+ cmd.reasoncode = cpu_to_le16(reason);
- if (lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd))
- return -EFAULT;
+ ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
+ if (ret)
+ return ret;
cfg80211_disconnected(priv->dev,
- priv->disassoc_reason,
+ reason,
NULL, 0,
GFP_KERNEL);
priv->connect_status = LBS_DISCONNECTED;
@@ -1431,6 +1434,21 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
return 0;
}
+static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code)
+{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
+ lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
+
+ /* store for lbs_cfg_ret_disconnect() */
+ priv->disassoc_reason = reason_code;
+
+ return lbs_disconnect(priv, reason_code);
+}
static int lbs_cfg_set_default_key(struct wiphy *wiphy,
struct net_device *netdev,
@@ -1439,6 +1457,9 @@ static int lbs_cfg_set_default_key(struct wiphy *wiphy,
{
struct lbs_private *priv = wiphy_priv(wiphy);
+ if (netdev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
lbs_deb_enter(LBS_DEB_CFG80211);
if (key_index != priv->wep_tx_key) {
@@ -1460,6 +1481,9 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
u16 key_type;
int ret = 0;
+ if (netdev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
lbs_deb_enter(LBS_DEB_CFG80211);
lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n",
@@ -1603,6 +1627,9 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
s8 signal, noise;
int ret;
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
if (idx != 0)
ret = -ENOENT;
@@ -1636,28 +1663,23 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = 0;
- lbs_deb_enter(LBS_DEB_CFG80211);
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
switch (type) {
case NL80211_IFTYPE_MONITOR:
- ret = lbs_set_monitor_mode(priv, 1);
- break;
case NL80211_IFTYPE_STATION:
- if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
- ret = lbs_set_monitor_mode(priv, 0);
- if (!ret)
- ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
- break;
case NL80211_IFTYPE_ADHOC:
- if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
- ret = lbs_set_monitor_mode(priv, 0);
- if (!ret)
- ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
break;
default:
- ret = -ENOTSUPP;
+ return -EOPNOTSUPP;
}
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ if (priv->iface_running)
+ ret = lbs_set_iface_type(priv, type);
+
if (!ret)
priv->wdev->iftype = type;
@@ -1959,6 +1981,9 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_bss *bss;
DECLARE_SSID_BUF(ssid_buf);
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
lbs_deb_enter(LBS_DEB_CFG80211);
if (!params->channel) {
@@ -1995,6 +2020,9 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
struct cmd_ds_802_11_ad_hoc_stop cmd;
int ret = 0;
+ if (dev == priv->mesh_dev)
+ return -EOPNOTSUPP;
+
lbs_deb_enter(LBS_DEB_CFG80211);
memset(&cmd, 0, sizeof(cmd));
@@ -2117,6 +2145,8 @@ int lbs_cfg_register(struct lbs_private *priv)
BIT(NL80211_IFTYPE_ADHOC);
if (lbs_rtap_supported(priv))
wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
+ if (lbs_mesh_activated(priv))
+ wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT);
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h
index 4f46bb744bee..a02ee151710e 100644
--- a/drivers/net/wireless/libertas/cfg.h
+++ b/drivers/net/wireless/libertas/cfg.h
@@ -17,5 +17,6 @@ void lbs_send_disconnect_notification(struct lbs_private *priv);
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
void lbs_scan_deinit(struct lbs_private *priv);
+int lbs_disconnect(struct lbs_private *priv, u16 reason);
#endif
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index dbd24a4607ec..e08ab1de3d9d 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -1088,7 +1088,7 @@ void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
__lbs_cleanup_and_insert_cmd(priv, cmd);
priv->cur_cmd = NULL;
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
}
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
@@ -1627,7 +1627,7 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
/* Wake up main thread to execute next command */
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
cmdnode = ERR_PTR(-ENOBUFS);
goto done;
}
@@ -1647,7 +1647,7 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
cmdnode->cmdwaitqwoken = 0;
lbs_queue_cmd(priv, cmdnode);
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
done:
lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index da0b05bb89fe..bc951ab4b681 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -9,6 +9,7 @@
#include <linux/netdevice.h>
#include <linux/firmware.h>
+#include <linux/nl80211.h>
/* Should be terminated by a NULL entry */
struct lbs_fw_table {
@@ -43,10 +44,15 @@ int lbs_start_card(struct lbs_private *priv);
void lbs_stop_card(struct lbs_private *priv);
void lbs_host_to_card_done(struct lbs_private *priv);
+int lbs_start_iface(struct lbs_private *priv);
+int lbs_stop_iface(struct lbs_private *priv);
+int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type);
+
int lbs_rtap_supported(struct lbs_private *priv);
int lbs_set_mac_address(struct net_device *dev, void *addr);
void lbs_set_multicast_list(struct net_device *dev);
+void lbs_update_mcast(struct lbs_private *priv);
int lbs_suspend(struct lbs_private *priv);
int lbs_resume(struct lbs_private *priv);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index adb3490e3cf5..f3fd447131c2 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -6,7 +6,6 @@
#ifndef _LBS_DEV_H_
#define _LBS_DEV_H_
-#include "mesh.h"
#include "defs.h"
#include "host.h"
@@ -22,6 +21,17 @@ struct sleep_params {
uint16_t sp_reserved;
};
+/* Mesh statistics */
+struct lbs_mesh_stats {
+ u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
+ u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
+ u32 fwd_drop_ttl; /* Fwd: TTL zero */
+ u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
+ u32 fwd_drop_noroute; /* Fwd: No route to Destination */
+ u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
+ u32 drop_blind; /* Rx: Dropped by blinding table */
+ u32 tx_failed_cnt; /* Tx: Failed transmissions */
+};
/* Private structure for the MV device */
struct lbs_private {
@@ -36,7 +46,6 @@ struct lbs_private {
/* CFG80211 */
struct wireless_dev *wdev;
bool wiphy_registered;
- bool stopping;
struct cfg80211_scan_request *scan_req;
u8 assoc_bss[ETH_ALEN];
u8 disassoc_reason;
@@ -86,11 +95,14 @@ struct lbs_private {
/* Hardware access */
void *card;
+ bool iface_running;
u8 fw_ready;
u8 surpriseremoved;
u8 setup_fw_on_resume;
int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
void (*reset_card) (struct lbs_private *priv);
+ int (*power_save) (struct lbs_private *priv);
+ int (*power_restore) (struct lbs_private *priv);
int (*enter_deep_sleep) (struct lbs_private *priv);
int (*exit_deep_sleep) (struct lbs_private *priv);
int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
@@ -146,6 +158,7 @@ struct lbs_private {
/* protected by hard_start_xmit serialization */
u8 txretrycount;
struct sk_buff *currenttxskb;
+ struct timer_list tx_lockup_timer;
/* Locks */
struct mutex lock;
@@ -167,9 +180,20 @@ struct lbs_private {
wait_queue_head_t scan_q;
/* Whether the scan was initiated internally and not by cfg80211 */
bool internal_scan;
- unsigned long last_scan;
};
extern struct cmd_confirm_sleep confirm_sleep;
+/* Check if there is an interface active. */
+static inline int lbs_iface_active(struct lbs_private *priv)
+{
+ int r;
+
+ r = netif_running(priv->dev);
+ if (priv->mesh_dev)
+ r |= netif_running(priv->mesh_dev);
+
+ return r;
+}
+
#endif
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 4dfb3bfd2cf3..885ddc1c4fed 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -5,6 +5,7 @@
#include "decl.h"
#include "cmd.h"
+#include "mesh.h"
static void lbs_ethtool_get_drvinfo(struct net_device *dev,
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 387786e1b394..c962e21762dc 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -39,6 +39,7 @@
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/host.h>
+#include <linux/pm_runtime.h>
#include "host.h"
#include "decl.h"
@@ -47,6 +48,8 @@
#include "cmd.h"
#include "if_sdio.h"
+static void if_sdio_interrupt(struct sdio_func *func);
+
/* The if_sdio_remove() callback function is called when
* user removes this module from kernel space or ejects
* the card from the slot. The driver handles these 2 cases
@@ -757,6 +760,136 @@ out:
return ret;
}
+/********************************************************************/
+/* Power management */
+/********************************************************************/
+
+static int if_sdio_power_on(struct if_sdio_card *card)
+{
+ struct sdio_func *func = card->func;
+ struct lbs_private *priv = card->priv;
+ struct mmc_host *host = func->card->host;
+ int ret;
+
+ sdio_claim_host(func);
+
+ ret = sdio_enable_func(func);
+ if (ret)
+ goto release;
+
+ /* For 1-bit transfers to the 8686 model, we need to enable the
+ * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
+ * bit to allow access to non-vendor registers. */
+ if ((card->model == MODEL_8686) &&
+ (host->caps & MMC_CAP_SDIO_IRQ) &&
+ (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
+ u8 reg;
+
+ func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+ reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
+ if (ret)
+ goto disable;
+
+ reg |= SDIO_BUS_ECSI;
+ sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
+ if (ret)
+ goto disable;
+ }
+
+ card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
+ if (ret)
+ goto disable;
+
+ card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
+ if (ret)
+ goto disable;
+
+ card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
+ if (ret)
+ goto disable;
+
+ sdio_release_host(func);
+ ret = if_sdio_prog_firmware(card);
+ sdio_claim_host(func);
+ if (ret)
+ goto disable;
+
+ /*
+ * Get rx_unit if the chip is SD8688 or newer.
+ * SD8385 & SD8686 do not have rx_unit.
+ */
+ if ((card->model != MODEL_8385)
+ && (card->model != MODEL_8686))
+ card->rx_unit = if_sdio_read_rx_unit(card);
+ else
+ card->rx_unit = 0;
+
+ /*
+ * Set up the interrupt handler late.
+ *
+ * If we set it up earlier, the (buggy) hardware generates a spurious
+ * interrupt, even before the interrupt has been enabled, with
+ * CCCR_INTx = 0.
+ *
+ * We register the interrupt handler late so that we can handle any
+ * spurious interrupts, and also to avoid generation of that known
+ * spurious interrupt in the first place.
+ */
+ ret = sdio_claim_irq(func, if_sdio_interrupt);
+ if (ret)
+ goto disable;
+
+ /*
+ * Enable interrupts now that everything is set up
+ */
+ sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
+ if (ret)
+ goto release_irq;
+
+ sdio_release_host(func);
+
+ /*
+ * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
+ */
+ if (card->model == MODEL_8688) {
+ struct cmd_header cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ lbs_deb_sdio("send function INIT command\n");
+ if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
+ lbs_cmd_copyback, (unsigned long) &cmd))
+ netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
+ }
+
+ priv->fw_ready = 1;
+
+ return 0;
+
+release_irq:
+ sdio_release_irq(func);
+disable:
+ sdio_disable_func(func);
+release:
+ sdio_release_host(func);
+ return ret;
+}
+
+static int if_sdio_power_off(struct if_sdio_card *card)
+{
+ struct sdio_func *func = card->func;
+ struct lbs_private *priv = card->priv;
+
+ priv->fw_ready = 0;
+
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+ return 0;
+}
+
+
/*******************************************************************/
/* Libertas callbacks */
/*******************************************************************/
@@ -923,6 +1056,32 @@ static void if_sdio_reset_card(struct lbs_private *priv)
schedule_work(&card_reset_work);
}
+static int if_sdio_power_save(struct lbs_private *priv)
+{
+ struct if_sdio_card *card = priv->card;
+ int ret;
+
+ flush_workqueue(card->workqueue);
+
+ ret = if_sdio_power_off(card);
+
+ /* Let runtime PM know the card is powered off */
+ pm_runtime_put_sync(&card->func->dev);
+
+ return ret;
+}
+
+static int if_sdio_power_restore(struct lbs_private *priv)
+{
+ struct if_sdio_card *card = priv->card;
+
+ /* Make sure the card will not be powered off by runtime PM */
+ pm_runtime_get_sync(&card->func->dev);
+
+ return if_sdio_power_on(card);
+}
+
+
/*******************************************************************/
/* SDIO callbacks */
/*******************************************************************/
@@ -976,7 +1135,6 @@ static int if_sdio_probe(struct sdio_func *func,
int ret, i;
unsigned int model;
struct if_sdio_packet *packet;
- struct mmc_host *host = func->card->host;
lbs_deb_enter(LBS_DEB_SDIO);
@@ -1033,45 +1191,6 @@ static int if_sdio_probe(struct sdio_func *func,
goto free;
}
- sdio_claim_host(func);
-
- ret = sdio_enable_func(func);
- if (ret)
- goto release;
-
- /* For 1-bit transfers to the 8686 model, we need to enable the
- * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
- * bit to allow access to non-vendor registers. */
- if ((card->model == MODEL_8686) &&
- (host->caps & MMC_CAP_SDIO_IRQ) &&
- (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
- u8 reg;
-
- func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
- reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
- if (ret)
- goto release_int;
-
- reg |= SDIO_BUS_ECSI;
- sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
- if (ret)
- goto release_int;
- }
-
- card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
- if (ret)
- goto release_int;
-
- card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
- if (ret)
- goto release_int;
-
- card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
- if (ret)
- goto release_int;
-
- sdio_release_host(func);
-
sdio_set_drvdata(func, card);
lbs_deb_sdio("class = 0x%X, vendor = 0x%X, "
@@ -1079,14 +1198,11 @@ static int if_sdio_probe(struct sdio_func *func,
func->class, func->vendor, func->device,
model, (unsigned)card->ioport);
- ret = if_sdio_prog_firmware(card);
- if (ret)
- goto reclaim;
priv = lbs_add_card(card, &func->dev);
if (!priv) {
ret = -ENOMEM;
- goto reclaim;
+ goto free;
}
card->priv = priv;
@@ -1097,62 +1213,21 @@ static int if_sdio_probe(struct sdio_func *func,
priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
priv->reset_card = if_sdio_reset_card;
+ priv->power_save = if_sdio_power_save;
+ priv->power_restore = if_sdio_power_restore;
- sdio_claim_host(func);
-
- /*
- * Get rx_unit if the chip is SD8688 or newer.
- * SD8385 & SD8686 do not have rx_unit.
- */
- if ((card->model != MODEL_8385)
- && (card->model != MODEL_8686))
- card->rx_unit = if_sdio_read_rx_unit(card);
- else
- card->rx_unit = 0;
-
- /*
- * Set up the interrupt handler late.
- *
- * If we set it up earlier, the (buggy) hardware generates a spurious
- * interrupt, even before the interrupt has been enabled, with
- * CCCR_INTx = 0.
- *
- * We register the interrupt handler late so that we can handle any
- * spurious interrupts, and also to avoid generation of that known
- * spurious interrupt in the first place.
- */
- ret = sdio_claim_irq(func, if_sdio_interrupt);
- if (ret)
- goto disable;
-
- /*
- * Enable interrupts now that everything is set up
- */
- sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
- sdio_release_host(func);
+ ret = if_sdio_power_on(card);
if (ret)
- goto reclaim;
-
- priv->fw_ready = 1;
-
- /*
- * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
- */
- if (card->model == MODEL_8688) {
- struct cmd_header cmd;
-
- memset(&cmd, 0, sizeof(cmd));
-
- lbs_deb_sdio("send function INIT command\n");
- if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
- lbs_cmd_copyback, (unsigned long) &cmd))
- netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
- }
+ goto err_activate_card;
ret = lbs_start_card(priv);
+ if_sdio_power_off(card);
if (ret)
goto err_activate_card;
+ /* Tell PM core that we don't need the card to be powered now */
+ pm_runtime_put_noidle(&func->dev);
+
out:
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
@@ -1161,14 +1236,6 @@ out:
err_activate_card:
flush_workqueue(card->workqueue);
lbs_remove_card(priv);
-reclaim:
- sdio_claim_host(func);
-release_int:
- sdio_release_irq(func);
-disable:
- sdio_disable_func(func);
-release:
- sdio_release_host(func);
free:
destroy_workqueue(card->workqueue);
while (card->packets) {
@@ -1195,6 +1262,9 @@ static void if_sdio_remove(struct sdio_func *func)
card = sdio_get_drvdata(func);
+ /* Undo decrement done above in if_sdio_probe */
+ pm_runtime_get_noresume(&func->dev);
+
if (user_rmmod && (card->model == MODEL_8688)) {
/*
* FUNC_SHUTDOWN is required for SD8688 WLAN/BT
@@ -1219,11 +1289,6 @@ static void if_sdio_remove(struct sdio_func *func)
flush_workqueue(card->workqueue);
destroy_workqueue(card->workqueue);
- sdio_claim_host(func);
- sdio_release_irq(func);
- sdio_disable_func(func);
- sdio_release_host(func);
-
while (card->packets) {
packet = card->packets;
card->packets = card->packets->next;
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index e0286cfbc91d..622ae6de0d8b 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -531,10 +531,6 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
goto out;
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
- goto out;
-
- lbs_deb_spi("waiting for helper to boot...\n");
-
out:
if (err)
pr_err("failed to load helper firmware (err=%d)\n", err);
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index b5acc393a65a..8147f1e2a0b0 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -324,7 +324,7 @@ static int if_usb_probe(struct usb_interface *intf,
}
kparam_unblock_sysfs_write(fw_name);
- if (!(priv = lbs_add_card(cardp, &udev->dev)))
+ if (!(priv = lbs_add_card(cardp, &intf->dev)))
goto err_prog_firmware;
cardp->priv = priv;
@@ -956,7 +956,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp,
priv->dnld_sent = DNLD_RES_RECEIVED;
spin_unlock_irqrestore(&priv->driver_lock, flags);
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
return ret;
}
@@ -973,6 +973,23 @@ static const struct {
{ MODEL_8682, "libertas/usb8682.bin" }
};
+#ifdef CONFIG_OLPC
+
+static int try_olpc_fw(struct if_usb_card *cardp)
+{
+ int retval = -ENOENT;
+
+ /* try the OLPC firmware first; fall back to fw_table list */
+ if (machine_is_olpc() && cardp->model == MODEL_8388)
+ retval = request_firmware(&cardp->fw,
+ "libertas/usb8388_olpc.bin", &cardp->udev->dev);
+ return retval;
+}
+
+#else
+static int try_olpc_fw(struct if_usb_card *cardp) { return -ENOENT; }
+#endif /* !CONFIG_OLPC */
+
static int get_fw(struct if_usb_card *cardp, const char *fwname)
{
int i;
@@ -981,6 +998,10 @@ static int get_fw(struct if_usb_card *cardp, const char *fwname)
if (fwname)
return request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
+ /* Handle OLPC firmware */
+ if (try_olpc_fw(cardp) == 0)
+ return 0;
+
/* Otherwise search for firmware to use */
for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
if (fw_table[i].model != cardp->model)
@@ -1112,6 +1133,15 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
if (priv->psstate != PS_STATE_FULL_POWER)
return -1;
+#ifdef CONFIG_OLPC
+ if (machine_is_olpc()) {
+ if (priv->wol_criteria == EHS_REMOVE_WAKEUP)
+ olpc_ec_wakeup_clear(EC_SCI_SRC_WLAN);
+ else
+ olpc_ec_wakeup_set(EC_SCI_SRC_WLAN);
+ }
+#endif
+
ret = lbs_suspend(priv);
if (ret)
goto out;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 94652c5a25de..b03779bcd547 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -23,6 +23,7 @@
#include "cfg.h"
#include "debugfs.h"
#include "cmd.h"
+#include "mesh.h"
#define DRIVER_RELEASE_VERSION "323.p0"
const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
@@ -98,6 +99,69 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
return 0;
}
+int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type)
+{
+ int ret = 0;
+
+ switch (type) {
+ case NL80211_IFTYPE_MONITOR:
+ ret = lbs_set_monitor_mode(priv, 1);
+ break;
+ case NL80211_IFTYPE_STATION:
+ if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
+ ret = lbs_set_monitor_mode(priv, 0);
+ if (!ret)
+ ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
+ ret = lbs_set_monitor_mode(priv, 0);
+ if (!ret)
+ ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
+ break;
+ default:
+ ret = -ENOTSUPP;
+ }
+ return ret;
+}
+
+int lbs_start_iface(struct lbs_private *priv)
+{
+ struct cmd_ds_802_11_mac_address cmd;
+ int ret;
+
+ if (priv->power_restore) {
+ ret = priv->power_restore(priv);
+ if (ret)
+ return ret;
+ }
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+ memcpy(cmd.macadd, priv->current_addr, ETH_ALEN);
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
+ if (ret) {
+ lbs_deb_net("set MAC address failed\n");
+ goto err;
+ }
+
+ ret = lbs_set_iface_type(priv, priv->wdev->iftype);
+ if (ret) {
+ lbs_deb_net("set iface type failed\n");
+ goto err;
+ }
+
+ lbs_update_channel(priv);
+
+ priv->iface_running = true;
+ return 0;
+
+err:
+ if (priv->power_save)
+ priv->power_save(priv);
+ return ret;
+}
/**
* lbs_dev_open - open the ethX interface
@@ -111,23 +175,65 @@ static int lbs_dev_open(struct net_device *dev)
int ret = 0;
lbs_deb_enter(LBS_DEB_NET);
+ if (!priv->iface_running) {
+ ret = lbs_start_iface(priv);
+ if (ret)
+ goto out;
+ }
spin_lock_irq(&priv->driver_lock);
- priv->stopping = false;
- if (priv->connect_status == LBS_CONNECTED)
- netif_carrier_on(dev);
- else
- netif_carrier_off(dev);
+ netif_carrier_off(dev);
if (!priv->tx_pending_len)
netif_wake_queue(dev);
spin_unlock_irq(&priv->driver_lock);
+
+out:
lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
return ret;
}
+static bool lbs_command_queue_empty(struct lbs_private *priv)
+{
+ unsigned long flags;
+ bool ret;
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ ret = priv->cur_cmd == NULL && list_empty(&priv->cmdpendingq);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ return ret;
+}
+
+int lbs_stop_iface(struct lbs_private *priv)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_MAIN);
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ priv->iface_running = false;
+ kfree_skb(priv->currenttxskb);
+ priv->currenttxskb = NULL;
+ priv->tx_pending_len = 0;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ cancel_work_sync(&priv->mcast_work);
+ del_timer_sync(&priv->tx_lockup_timer);
+
+ /* Disable command processing, and wait for all commands to complete */
+ lbs_deb_main("waiting for commands to complete\n");
+ wait_event(priv->waitq, lbs_command_queue_empty(priv));
+ lbs_deb_main("all commands completed\n");
+
+ if (priv->power_save)
+ ret = priv->power_save(priv);
+
+ lbs_deb_leave(LBS_DEB_MAIN);
+ return ret;
+}
+
/**
* lbs_eth_stop - close the ethX interface
*
@@ -140,18 +246,25 @@ static int lbs_eth_stop(struct net_device *dev)
lbs_deb_enter(LBS_DEB_NET);
+ if (priv->connect_status == LBS_CONNECTED)
+ lbs_disconnect(priv, WLAN_REASON_DEAUTH_LEAVING);
+
spin_lock_irq(&priv->driver_lock);
- priv->stopping = true;
netif_stop_queue(dev);
spin_unlock_irq(&priv->driver_lock);
- schedule_work(&priv->mcast_work);
+ lbs_update_mcast(priv);
cancel_delayed_work_sync(&priv->scan_work);
if (priv->scan_req) {
cfg80211_scan_done(priv->scan_req, false);
priv->scan_req = NULL;
}
+ netif_carrier_off(priv->dev);
+
+ if (!lbs_iface_active(priv))
+ lbs_stop_iface(priv);
+
lbs_deb_leave(LBS_DEB_NET);
return 0;
}
@@ -163,13 +276,14 @@ void lbs_host_to_card_done(struct lbs_private *priv)
lbs_deb_enter(LBS_DEB_THREAD);
spin_lock_irqsave(&priv->driver_lock, flags);
+ del_timer(&priv->tx_lockup_timer);
priv->dnld_sent = DNLD_RES_RECEIVED;
/* Wake main thread if commands are pending */
if (!priv->cur_cmd || priv->tx_pending_len > 0) {
if (!priv->wakeup_dev_required)
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
@@ -182,29 +296,24 @@ int lbs_set_mac_address(struct net_device *dev, void *addr)
int ret = 0;
struct lbs_private *priv = dev->ml_priv;
struct sockaddr *phwaddr = addr;
- struct cmd_ds_802_11_mac_address cmd;
lbs_deb_enter(LBS_DEB_NET);
+ /*
+ * Can only set MAC address when all interfaces are down, to be written
+ * to the hardware when one of them is brought up.
+ */
+ if (lbs_iface_active(priv))
+ return -EBUSY;
+
/* In case it was called from the mesh device */
dev = priv->dev;
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_SET);
- memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
- if (ret) {
- lbs_deb_net("set MAC address failed\n");
- goto done;
- }
-
memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
if (priv->mesh_dev)
memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
-done:
lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
return ret;
}
@@ -258,18 +367,18 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd,
return i;
}
-static void lbs_set_mcast_worker(struct work_struct *work)
+void lbs_update_mcast(struct lbs_private *priv)
{
- struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work);
struct cmd_ds_mac_multicast_adr mcast_cmd;
- int dev_flags;
+ int dev_flags = 0;
int nr_addrs;
int old_mac_control = priv->mac_control;
lbs_deb_enter(LBS_DEB_NET);
- dev_flags = priv->dev->flags;
- if (priv->mesh_dev)
+ if (netif_running(priv->dev))
+ dev_flags |= priv->dev->flags;
+ if (priv->mesh_dev && netif_running(priv->mesh_dev))
dev_flags |= priv->mesh_dev->flags;
if (dev_flags & IFF_PROMISC) {
@@ -315,6 +424,12 @@ static void lbs_set_mcast_worker(struct work_struct *work)
lbs_deb_leave(LBS_DEB_NET);
}
+static void lbs_set_mcast_worker(struct work_struct *work)
+{
+ struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work);
+ lbs_update_mcast(priv);
+}
+
void lbs_set_multicast_list(struct net_device *dev)
{
struct lbs_private *priv = dev->ml_priv;
@@ -504,6 +619,9 @@ static int lbs_thread(void *data)
if (ret) {
lbs_deb_tx("host_to_card failed %d\n", ret);
priv->dnld_sent = DNLD_RES_RECEIVED;
+ } else {
+ mod_timer(&priv->tx_lockup_timer,
+ jiffies + (HZ * 5));
}
priv->tx_pending_len = 0;
if (!priv->currenttxskb) {
@@ -520,6 +638,7 @@ static int lbs_thread(void *data)
}
del_timer(&priv->command_timer);
+ del_timer(&priv->tx_lockup_timer);
del_timer(&priv->auto_deepsleep_timer);
lbs_deb_leave(LBS_DEB_THREAD);
@@ -647,13 +766,39 @@ static void lbs_cmd_timeout_handler(unsigned long data)
if (priv->dnld_sent == DNLD_CMD_SENT)
priv->dnld_sent = DNLD_RES_RECEIVED;
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
out:
spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_leave(LBS_DEB_CMD);
}
/**
+ * lbs_tx_lockup_handler - handles the timeout of the passing of TX frames
+ * to the hardware. This is known to frequently happen with SD8686 when
+ * waking up after a Wake-on-WLAN-triggered resume.
+ *
+ * @data: &struct lbs_private pointer
+ */
+static void lbs_tx_lockup_handler(unsigned long data)
+{
+ struct lbs_private *priv = (struct lbs_private *)data;
+ unsigned long flags;
+
+ lbs_deb_enter(LBS_DEB_TX);
+ spin_lock_irqsave(&priv->driver_lock, flags);
+
+ netdev_info(priv->dev, "TX lockup detected\n");
+ if (priv->reset_card)
+ priv->reset_card(priv);
+
+ priv->dnld_sent = DNLD_RES_RECEIVED;
+ wake_up_interruptible(&priv->waitq);
+
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ lbs_deb_leave(LBS_DEB_TX);
+}
+
+/**
* auto_deepsleep_timer_fn - put the device back to deep sleep mode when
* timer expires and no activity (command, event, data etc.) is detected.
* @data: &struct lbs_private pointer
@@ -739,6 +884,8 @@ static int lbs_init_adapter(struct lbs_private *priv)
setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
(unsigned long)priv);
+ setup_timer(&priv->tx_lockup_timer, lbs_tx_lockup_handler,
+ (unsigned long)priv);
setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn,
(unsigned long)priv);
@@ -776,6 +923,7 @@ static void lbs_free_adapter(struct lbs_private *priv)
lbs_free_cmd_buffer(priv);
kfifo_free(&priv->event_fifo);
del_timer(&priv->command_timer);
+ del_timer(&priv->tx_lockup_timer);
del_timer(&priv->auto_deepsleep_timer);
lbs_deb_leave(LBS_DEB_MAIN);
@@ -786,7 +934,7 @@ static const struct net_device_ops lbs_netdev_ops = {
.ndo_stop = lbs_eth_stop,
.ndo_start_xmit = lbs_hard_start_xmit,
.ndo_set_mac_address = lbs_set_mac_address,
- .ndo_set_multicast_list = lbs_set_multicast_list,
+ .ndo_set_rx_mode = lbs_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
@@ -889,10 +1037,6 @@ void lbs_remove_card(struct lbs_private *priv)
lbs_remove_mesh(priv);
lbs_scan_deinit(priv);
- dev = priv->dev;
-
- cancel_work_sync(&priv->mcast_work);
-
/* worker thread destruction blocks on the in-flight command which
* should have been cleared already in lbs_stop_card().
*/
@@ -950,17 +1094,18 @@ int lbs_start_card(struct lbs_private *priv)
if (ret)
goto done;
+ if (!lbs_disablemesh)
+ lbs_init_mesh(priv);
+ else
+ pr_info("%s: mesh disabled\n", dev->name);
+
if (lbs_cfg_register(priv)) {
pr_err("cannot register device\n");
goto done;
}
- lbs_update_channel(priv);
-
- if (!lbs_disablemesh)
- lbs_init_mesh(priv);
- else
- pr_info("%s: mesh disabled\n", dev->name);
+ if (lbs_mesh_activated(priv))
+ lbs_start_mesh(priv);
lbs_debugfs_init_one(priv, dev);
@@ -978,8 +1123,6 @@ EXPORT_SYMBOL_GPL(lbs_start_card);
void lbs_stop_card(struct lbs_private *priv)
{
struct net_device *dev;
- struct cmd_ctrl_node *cmdnode;
- unsigned long flags;
lbs_deb_enter(LBS_DEB_MAIN);
@@ -992,30 +1135,6 @@ void lbs_stop_card(struct lbs_private *priv)
lbs_debugfs_remove_one(priv);
lbs_deinit_mesh(priv);
-
- /* Delete the timeout of the currently processing command */
- del_timer_sync(&priv->command_timer);
- del_timer_sync(&priv->auto_deepsleep_timer);
-
- /* Flush pending command nodes */
- spin_lock_irqsave(&priv->driver_lock, flags);
- lbs_deb_main("clearing pending commands\n");
- list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
- cmdnode->result = -ENOENT;
- cmdnode->cmdwaitqwoken = 1;
- wake_up(&cmdnode->cmdwait_q);
- }
-
- /* Flush the command the card is currently processing */
- if (priv->cur_cmd) {
- lbs_deb_main("clearing current command\n");
- priv->cur_cmd->result = -ENOENT;
- priv->cur_cmd->cmdwaitqwoken = 1;
- wake_up(&priv->cur_cmd->cmdwait_q);
- }
- lbs_deb_main("done clearing commands\n");
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
unregister_netdev(dev);
out:
@@ -1036,7 +1155,7 @@ void lbs_queue_event(struct lbs_private *priv, u32 event)
kfifo_in(&priv->event_fifo, (unsigned char *) &event, sizeof(u32));
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_leave(LBS_DEB_THREAD);
@@ -1054,7 +1173,7 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
BUG_ON(resp_idx > 1);
priv->resp_idx = resp_idx;
- wake_up_interruptible(&priv->waitq);
+ wake_up(&priv->waitq);
lbs_deb_leave(LBS_DEB_THREAD);
}
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index be72c08ea2a7..e87c031b298f 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -129,6 +129,19 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
}
+int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel)
+{
+ return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel);
+}
+
+static uint16_t lbs_mesh_get_channel(struct lbs_private *priv)
+{
+ struct wireless_dev *mesh_wdev = priv->mesh_dev->ieee80211_ptr;
+ if (mesh_wdev->channel)
+ return mesh_wdev->channel->hw_value;
+ else
+ return 1;
+}
/***************************************************************************
* Mesh sysfs support
@@ -812,7 +825,6 @@ static void lbs_persist_config_remove(struct net_device *dev)
*/
int lbs_init_mesh(struct lbs_private *priv)
{
- struct net_device *dev = priv->dev;
int ret = 0;
lbs_deb_enter(LBS_DEB_MESH);
@@ -837,11 +849,9 @@ int lbs_init_mesh(struct lbs_private *priv)
useful */
priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
- if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->channel)) {
+ if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) {
priv->mesh_tlv = TLV_TYPE_MESH_ID;
- if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->channel))
+ if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
priv->mesh_tlv = 0;
}
} else
@@ -851,23 +861,16 @@ int lbs_init_mesh(struct lbs_private *priv)
* 0x100+37; Do not invoke command with old TLV.
*/
priv->mesh_tlv = TLV_TYPE_MESH_ID;
- if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->channel))
+ if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
priv->mesh_tlv = 0;
}
/* Stop meshing until interface is brought up */
- lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel);
+ lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 1);
if (priv->mesh_tlv) {
sprintf(priv->mesh_ssid, "mesh");
priv->mesh_ssid_len = 4;
-
- lbs_add_mesh(priv);
-
- if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
- netdev_err(dev, "cannot register lbs_mesh attribute\n");
-
ret = 1;
}
@@ -875,6 +878,13 @@ int lbs_init_mesh(struct lbs_private *priv)
return ret;
}
+void lbs_start_mesh(struct lbs_private *priv)
+{
+ lbs_add_mesh(priv);
+
+ if (device_create_file(&priv->dev->dev, &dev_attr_lbs_mesh))
+ netdev_err(priv->dev, "cannot register lbs_mesh attribute\n");
+}
int lbs_deinit_mesh(struct lbs_private *priv)
{
@@ -904,7 +914,8 @@ static int lbs_mesh_stop(struct net_device *dev)
struct lbs_private *priv = dev->ml_priv;
lbs_deb_enter(LBS_DEB_MESH);
- lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel);
+ lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
+ lbs_mesh_get_channel(priv));
spin_lock_irq(&priv->driver_lock);
@@ -913,7 +924,9 @@ static int lbs_mesh_stop(struct net_device *dev)
spin_unlock_irq(&priv->driver_lock);
- schedule_work(&priv->mcast_work);
+ lbs_update_mcast(priv);
+ if (!lbs_iface_active(priv))
+ lbs_stop_iface(priv);
lbs_deb_leave(LBS_DEB_MESH);
return 0;
@@ -931,6 +944,11 @@ static int lbs_mesh_dev_open(struct net_device *dev)
int ret = 0;
lbs_deb_enter(LBS_DEB_NET);
+ if (!priv->iface_running) {
+ ret = lbs_start_iface(priv);
+ if (ret)
+ goto out;
+ }
spin_lock_irq(&priv->driver_lock);
@@ -947,7 +965,8 @@ static int lbs_mesh_dev_open(struct net_device *dev)
spin_unlock_irq(&priv->driver_lock);
- ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->channel);
+ ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+ lbs_mesh_get_channel(priv));
out:
lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
@@ -959,7 +978,7 @@ static const struct net_device_ops mesh_netdev_ops = {
.ndo_stop = lbs_mesh_stop,
.ndo_start_xmit = lbs_hard_start_xmit,
.ndo_set_mac_address = lbs_set_mac_address,
- .ndo_set_multicast_list = lbs_set_multicast_list,
+ .ndo_set_rx_mode = lbs_set_multicast_list,
};
/**
@@ -971,18 +990,32 @@ static const struct net_device_ops mesh_netdev_ops = {
static int lbs_add_mesh(struct lbs_private *priv)
{
struct net_device *mesh_dev = NULL;
+ struct wireless_dev *mesh_wdev;
int ret = 0;
lbs_deb_enter(LBS_DEB_MESH);
/* Allocate a virtual mesh device */
+ mesh_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+ if (!mesh_wdev) {
+ lbs_deb_mesh("init mshX wireless device failed\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+
mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
if (!mesh_dev) {
lbs_deb_mesh("init mshX device failed\n");
ret = -ENOMEM;
- goto done;
+ goto err_free_wdev;
}
+
+ mesh_wdev->iftype = NL80211_IFTYPE_MESH_POINT;
+ mesh_wdev->wiphy = priv->wdev->wiphy;
+ mesh_wdev->netdev = mesh_dev;
+
mesh_dev->ml_priv = priv;
+ mesh_dev->ieee80211_ptr = mesh_wdev;
priv->mesh_dev = mesh_dev;
mesh_dev->netdev_ops = &mesh_netdev_ops;
@@ -996,7 +1029,7 @@ static int lbs_add_mesh(struct lbs_private *priv)
ret = register_netdev(mesh_dev);
if (ret) {
pr_err("cannot register mshX virtual interface\n");
- goto err_free;
+ goto err_free_netdev;
}
ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
@@ -1012,9 +1045,12 @@ static int lbs_add_mesh(struct lbs_private *priv)
err_unregister:
unregister_netdev(mesh_dev);
-err_free:
+err_free_netdev:
free_netdev(mesh_dev);
+err_free_wdev:
+ kfree(mesh_wdev);
+
done:
lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
return ret;
@@ -1035,6 +1071,7 @@ void lbs_remove_mesh(struct lbs_private *priv)
lbs_persist_config_remove(mesh_dev);
unregister_netdev(mesh_dev);
priv->mesh_dev = NULL;
+ kfree(mesh_dev->ieee80211_ptr);
free_netdev(mesh_dev);
lbs_deb_leave(LBS_DEB_MESH);
}
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
index 50144913f2ab..6603f341c874 100644
--- a/drivers/net/wireless/libertas/mesh.h
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -9,30 +9,25 @@
#include <net/lib80211.h>
#include "host.h"
+#include "dev.h"
#ifdef CONFIG_LIBERTAS_MESH
-/* Mesh statistics */
-struct lbs_mesh_stats {
- u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
- u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
- u32 fwd_drop_ttl; /* Fwd: TTL zero */
- u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
- u32 fwd_drop_noroute; /* Fwd: No route to Destination */
- u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
- u32 drop_blind; /* Rx: Dropped by blinding table */
- u32 tx_failed_cnt; /* Tx: Failed transmissions */
-};
-
-
struct net_device;
-struct lbs_private;
int lbs_init_mesh(struct lbs_private *priv);
+void lbs_start_mesh(struct lbs_private *priv);
int lbs_deinit_mesh(struct lbs_private *priv);
void lbs_remove_mesh(struct lbs_private *priv);
+static inline bool lbs_mesh_activated(struct lbs_private *priv)
+{
+ /* Mesh SSID is only programmed after successful init */
+ return priv->mesh_ssid_len != 0;
+}
+
+int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel);
/* Sending / Receiving */
@@ -67,11 +62,13 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
#define lbs_init_mesh(priv)
#define lbs_deinit_mesh(priv)
+#define lbs_start_mesh(priv)
#define lbs_add_mesh(priv)
#define lbs_remove_mesh(priv)
#define lbs_mesh_set_dev(priv, dev, rxpd) (dev)
#define lbs_mesh_set_txpd(priv, dev, txpd)
-#define lbs_mesh_config(priv, enable, chan)
+#define lbs_mesh_set_channel(priv, channel) (0)
+#define lbs_mesh_activated(priv) (false)
#endif
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index bfb8898ae518..62e10eeadd7e 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -15,6 +15,7 @@
#include "radiotap.h"
#include "decl.h"
#include "dev.h"
+#include "mesh.h"
struct eth803hdr {
u8 dest_addr[6];
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index a6e85134cfe1..8f127520d786 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -12,6 +12,7 @@
#include "decl.h"
#include "defs.h"
#include "dev.h"
+#include "mesh.h"
/**
* convert_radiotap_rate_to_mv - converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
diff --git a/drivers/net/wireless/libertas_tf/deb_defs.h b/drivers/net/wireless/libertas_tf/deb_defs.h
index ae753962d8b5..4bd3dc5adf7c 100644
--- a/drivers/net/wireless/libertas_tf/deb_defs.h
+++ b/drivers/net/wireless/libertas_tf/deb_defs.h
@@ -3,7 +3,7 @@
* global variable declaration.
*/
#ifndef _LBS_DEB_DEFS_H_
-#define _LBS_DEB_EFS_H_
+#define _LBS_DEB_DEFS_H_
#ifndef DRV_NAME
#define DRV_NAME "libertas_tf"
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 031cd89b1768..68455a2307cb 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -612,6 +612,12 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
rx_status.freq = data->channel->center_freq;
rx_status.band = data->channel->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;
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ rx_status.flag |= RX_FLAG_40MHZ;
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
+ rx_status.flag |= RX_FLAG_SHORT_GI;
/* TODO: simulate real signal strength (and optional packet loss) */
rx_status.signal = data->power_level - 50;
@@ -964,7 +970,8 @@ static int mac80211_hwsim_set_tim(struct ieee80211_hw *hw,
}
static int mac80211_hwsim_conf_tx(
- struct ieee80211_hw *hw, u16 queue,
+ struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
wiphy_debug(hw->wiphy,
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index 1a453a605b3f..079e5532e686 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -193,7 +193,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
skb_src = skb_dequeue(&pra_list->skb_head);
pra_list->total_pkts_size -= skb_src->len;
- pra_list->total_pkts--;
atomic_dec(&priv->wmm.tx_pkts_queued);
@@ -247,8 +246,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
tx_param.next_pkt_len = 0;
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
- skb_aggr->data,
- skb_aggr->len, &tx_param);
+ skb_aggr, &tx_param);
switch (ret) {
case -EBUSY:
spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
@@ -269,7 +267,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
skb_queue_tail(&pra_list->skb_head, skb_aggr);
pra_list->total_pkts_size += skb_aggr->len;
- pra_list->total_pkts++;
atomic_inc(&priv->wmm.tx_pkts_queued);
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.h b/drivers/net/wireless/mwifiex/11n_aggr.h
index 9c6dca7ab02c..900e1c62a0cc 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.h
+++ b/drivers/net/wireless/mwifiex/11n_aggr.h
@@ -21,6 +21,7 @@
#define _MWIFIEX_11N_AGGR_H_
#define PKT_TYPE_AMSDU 0xE6
+#define MIN_NUM_AMSDU 2
int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv,
struct sk_buff *skb);
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig
index 86962920cef3..8f2797aa0c60 100644
--- a/drivers/net/wireless/mwifiex/Kconfig
+++ b/drivers/net/wireless/mwifiex/Kconfig
@@ -19,3 +19,14 @@ config MWIFIEX_SDIO
If you choose to build it as a module, it will be called
mwifiex_sdio.
+
+config MWIFIEX_PCIE
+ tristate "Marvell WiFi-Ex Driver for PCIE 8766"
+ depends on MWIFIEX && PCI
+ select FW_LOADER
+ ---help---
+ This adds support for wireless adapters based on Marvell
+ 8766 chipset with PCIe interface.
+
+ If you choose to build it as a module, it will be called
+ mwifiex_pcie.
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
index 42cb733ea33a..b0257ad1bbed 100644
--- a/drivers/net/wireless/mwifiex/Makefile
+++ b/drivers/net/wireless/mwifiex/Makefile
@@ -39,3 +39,6 @@ obj-$(CONFIG_MWIFIEX) += mwifiex.o
mwifiex_sdio-y += sdio.o
obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o
+
+mwifiex_pcie-y += pcie.o
+obj-$(CONFIG_MWIFIEX_PCIE) += mwifiex_pcie.o
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 352d2c5da1fc..462c71067bfb 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -543,12 +543,28 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
ret = -EFAULT;
}
+ /*
+ * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid
+ * MCS index values for us are 0 to 7.
+ */
+ if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 8)) {
+ sinfo->txrate.mcs = priv->tx_rate;
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+ /* 40MHz rate */
+ if (priv->tx_htinfo & BIT(1))
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+ /* SGI enabled */
+ if (priv->tx_htinfo & BIT(2))
+ sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ }
+
sinfo->rx_bytes = priv->stats.rx_bytes;
sinfo->tx_bytes = priv->stats.tx_bytes;
sinfo->rx_packets = priv->stats.rx_packets;
sinfo->tx_packets = priv->stats.tx_packets;
- sinfo->signal = priv->w_stats.qual.level;
- sinfo->txrate.legacy = rate.rate;
+ sinfo->signal = priv->qual_level;
+ /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */
+ sinfo->txrate.legacy = rate.rate * 5;
return ret;
}
@@ -565,8 +581,6 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
- mwifiex_dump_station_info(priv, sinfo);
-
if (!priv->media_connected)
return -ENOENT;
if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
@@ -768,6 +782,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
struct mwifiex_bss_info bss_info;
int ie_len;
u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];
+ enum ieee80211_band band;
if (mwifiex_get_bss_info(priv, &bss_info))
return -1;
@@ -780,9 +795,10 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
bss_info.ssid.ssid_len);
ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
+ band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
chan = __ieee80211_get_channel(priv->wdev->wiphy,
ieee80211_channel_to_frequency(bss_info.bss_chan,
- priv->curr_bss_params.band));
+ band));
cfg80211_inform_bss(priv->wdev->wiphy, chan,
bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
@@ -793,139 +809,6 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
}
/*
- * This function informs the CFG802.11 subsystem of a new BSS connection.
- *
- * The following information are sent to the CFG802.11 subsystem
- * to register the new BSS connection. If we do not register the new BSS,
- * a kernel panic will result.
- * - MAC address
- * - Capabilities
- * - Beacon period
- * - RSSI value
- * - Channel
- * - Supported rates IE
- * - Extended capabilities IE
- * - DS parameter set IE
- * - HT Capability IE
- * - Vendor Specific IE (221)
- * - WPA IE
- * - RSN IE
- */
-static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *ssid)
-{
- struct mwifiex_bssdescriptor *scan_table;
- int i, j;
- struct ieee80211_channel *chan;
- u8 *ie, *ie_buf;
- u32 ie_len;
- u8 *beacon;
- int beacon_size;
- u8 element_id, element_len;
-
-#define MAX_IE_BUF 2048
- ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL);
- if (!ie_buf) {
- dev_err(priv->adapter->dev, "%s: failed to alloc ie_buf\n",
- __func__);
- return -ENOMEM;
- }
-
- scan_table = priv->adapter->scan_table;
- for (i = 0; i < priv->adapter->num_in_scan_table; i++) {
- if (ssid) {
- /* Inform specific BSS only */
- if (memcmp(ssid->ssid, scan_table[i].ssid.ssid,
- ssid->ssid_len))
- continue;
- }
- memset(ie_buf, 0, MAX_IE_BUF);
- ie_buf[0] = WLAN_EID_SSID;
- ie_buf[1] = scan_table[i].ssid.ssid_len;
- memcpy(&ie_buf[sizeof(struct ieee_types_header)],
- scan_table[i].ssid.ssid, ie_buf[1]);
-
- ie = ie_buf + ie_buf[1] + sizeof(struct ieee_types_header);
- ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
-
- ie[0] = WLAN_EID_SUPP_RATES;
-
- for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) {
- if (!scan_table[i].supported_rates[j])
- break;
- else
- ie[j + sizeof(struct ieee_types_header)] =
- scan_table[i].supported_rates[j];
- }
-
- ie[1] = j;
- ie_len += ie[1] + sizeof(struct ieee_types_header);
-
- beacon = scan_table[i].beacon_buf;
- beacon_size = scan_table[i].beacon_buf_size;
-
- /* Skip time stamp, beacon interval and capability */
-
- if (beacon) {
- beacon += sizeof(scan_table[i].beacon_period)
- + sizeof(scan_table[i].time_stamp) +
- +sizeof(scan_table[i].cap_info_bitmap);
-
- beacon_size -= sizeof(scan_table[i].beacon_period)
- + sizeof(scan_table[i].time_stamp)
- + sizeof(scan_table[i].cap_info_bitmap);
- }
-
- while (beacon_size >= sizeof(struct ieee_types_header)) {
- ie = ie_buf + ie_len;
- element_id = *beacon;
- element_len = *(beacon + 1);
- if (beacon_size < (int) element_len +
- sizeof(struct ieee_types_header)) {
- dev_err(priv->adapter->dev, "%s: in processing"
- " IE, bytes left < IE length\n",
- __func__);
- break;
- }
- switch (element_id) {
- case WLAN_EID_EXT_CAPABILITY:
- case WLAN_EID_DS_PARAMS:
- case WLAN_EID_HT_CAPABILITY:
- case WLAN_EID_VENDOR_SPECIFIC:
- case WLAN_EID_RSN:
- case WLAN_EID_BSS_AC_ACCESS_DELAY:
- ie[0] = element_id;
- ie[1] = element_len;
- memcpy(&ie[sizeof(struct ieee_types_header)],
- (u8 *) beacon
- + sizeof(struct ieee_types_header),
- element_len);
- ie_len += ie[1] +
- sizeof(struct ieee_types_header);
- break;
- default:
- break;
- }
- beacon += element_len +
- sizeof(struct ieee_types_header);
- beacon_size -= element_len +
- sizeof(struct ieee_types_header);
- }
- chan = ieee80211_get_channel(priv->wdev->wiphy,
- scan_table[i].freq);
- cfg80211_inform_bss(priv->wdev->wiphy, chan,
- scan_table[i].mac_address,
- 0, scan_table[i].cap_info_bitmap,
- scan_table[i].beacon_period,
- ie_buf, ie_len,
- scan_table[i].rssi, GFP_KERNEL);
- }
-
- kfree(ie_buf);
- return 0;
-}
-
-/*
* This function connects with a BSS.
*
* This function handles both Infra and Ad-Hoc modes. It also performs
@@ -937,8 +820,7 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
* For Infra mode, the function returns failure if the specified SSID
* is not found in scan table. However, for Ad-Hoc mode, it can create
* the IBSS if it does not exist. On successful completion in either case,
- * the function notifies the CFG802.11 subsystem of the new BSS connection,
- * otherwise the kernel will panic.
+ * the function notifies the CFG802.11 subsystem of the new BSS connection.
*/
static int
mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
@@ -946,11 +828,11 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
struct cfg80211_connect_params *sme, bool privacy)
{
struct mwifiex_802_11_ssid req_ssid;
- struct mwifiex_ssid_bssid ssid_bssid;
int ret, auth_type = 0;
+ struct cfg80211_bss *bss = NULL;
+ u8 is_scanning_required = 0;
memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid));
- memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
req_ssid.ssid_len = ssid_len;
if (ssid_len > IEEE80211_MAX_SSID_LEN) {
@@ -1028,30 +910,48 @@ done:
return -EFAULT;
}
+ /*
+ * Scan entries are valid for some time (15 sec). So we can save one
+ * active scan time if we just try cfg80211_get_bss first. If it fails
+ * then request scan and cfg80211_get_bss() again for final output.
+ */
+ while (1) {
+ if (is_scanning_required) {
+ /* Do specific SSID scanning */
+ if (mwifiex_request_scan(priv, &req_ssid)) {
+ dev_err(priv->adapter->dev, "scan error\n");
+ return -EFAULT;
+ }
+ }
- memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid));
-
- if (mode != NL80211_IFTYPE_ADHOC) {
- if (mwifiex_find_best_bss(priv, &ssid_bssid))
- return -EFAULT;
- /* Inform the BSS information to kernel, otherwise
- * kernel will give a panic after successful assoc */
- if (mwifiex_inform_bss_from_scan_result(priv, &req_ssid))
- return -EFAULT;
+ /* Find the BSS we want using available scan results */
+ if (mode == NL80211_IFTYPE_ADHOC)
+ bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
+ bssid, ssid, ssid_len,
+ WLAN_CAPABILITY_IBSS,
+ WLAN_CAPABILITY_IBSS);
+ else
+ bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
+ bssid, ssid, ssid_len,
+ WLAN_CAPABILITY_ESS,
+ WLAN_CAPABILITY_ESS);
+
+ if (!bss) {
+ if (is_scanning_required) {
+ dev_warn(priv->adapter->dev, "assoc: requested "
+ "bss not found in scan results\n");
+ break;
+ }
+ is_scanning_required = 1;
+ } else {
+ dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n",
+ (char *) req_ssid.ssid, bss->bssid);
+ memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
+ break;
+ }
}
- dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n",
- (char *) req_ssid.ssid, ssid_bssid.bssid);
-
- memcpy(&priv->cfg_bssid, ssid_bssid.bssid, 6);
-
- /* Connect to BSS by ESSID */
- memset(&ssid_bssid.bssid, 0, ETH_ALEN);
-
- if (!netif_queue_stopped(priv->netdev))
- netif_stop_queue(priv->netdev);
-
- if (mwifiex_bss_start(priv, &ssid_bssid))
+ if (mwifiex_bss_start(priv, bss, &req_ssid))
return -EFAULT;
if (mode == NL80211_IFTYPE_ADHOC) {
@@ -1262,8 +1162,150 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
}
+/*
+ * create a new virtual interface with the given name
+ */
+struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
+ char *name,
+ enum nl80211_iftype type,
+ u32 *flags,
+ struct vif_params *params)
+{
+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
+ struct mwifiex_adapter *adapter;
+ struct net_device *dev;
+ void *mdev_priv;
+
+ if (!priv)
+ return NULL;
+
+ adapter = priv->adapter;
+ if (!adapter)
+ return NULL;
+
+ switch (type) {
+ case NL80211_IFTYPE_UNSPECIFIED:
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ if (priv->bss_mode) {
+ wiphy_err(wiphy, "cannot create multiple"
+ " station/adhoc interfaces\n");
+ return NULL;
+ }
+
+ if (type == NL80211_IFTYPE_UNSPECIFIED)
+ priv->bss_mode = NL80211_IFTYPE_STATION;
+ else
+ priv->bss_mode = type;
+
+ priv->bss_type = MWIFIEX_BSS_TYPE_STA;
+ priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
+ priv->bss_priority = 0;
+ priv->bss_role = MWIFIEX_BSS_ROLE_STA;
+ priv->bss_index = 0;
+ priv->bss_num = 0;
+
+ break;
+ default:
+ wiphy_err(wiphy, "type not supported\n");
+ return NULL;
+ }
+
+ dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name,
+ ether_setup, 1);
+ if (!dev) {
+ wiphy_err(wiphy, "no memory available for netdevice\n");
+ goto error;
+ }
+
+ dev_net_set(dev, wiphy_net(wiphy));
+ dev->ieee80211_ptr = priv->wdev;
+ dev->ieee80211_ptr->iftype = priv->bss_mode;
+ memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
+ memcpy(dev->perm_addr, wiphy->perm_addr, ETH_ALEN);
+ SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
+
+ dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+ dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
+ dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
+
+ mdev_priv = netdev_priv(dev);
+ *((unsigned long *) mdev_priv) = (unsigned long) priv;
+
+ priv->netdev = dev;
+ mwifiex_init_priv_params(priv, dev);
+
+ SET_NETDEV_DEV(dev, adapter->dev);
+
+ /* Register network device */
+ if (register_netdevice(dev)) {
+ wiphy_err(wiphy, "cannot register virtual network device\n");
+ goto error;
+ }
+
+ 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);
+
+#ifdef CONFIG_DEBUG_FS
+ mwifiex_dev_debugfs_init(priv);
+#endif
+ return dev;
+error:
+ if (dev && (dev->reg_state == NETREG_UNREGISTERED))
+ free_netdev(dev);
+ priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
+
+/*
+ * del_virtual_intf: remove the virtual interface determined by dev
+ */
+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
+
+ if (!priv || !dev)
+ return 0;
+
+#ifdef CONFIG_DEBUG_FS
+ mwifiex_dev_debugfs_remove(priv);
+#endif
+
+ if (!netif_queue_stopped(priv->netdev))
+ netif_stop_queue(priv->netdev);
+
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
+
+ if (dev->reg_state == NETREG_REGISTERED)
+ unregister_netdevice(dev);
+
+ if (dev->reg_state == NETREG_UNREGISTERED)
+ free_netdev(dev);
+
+ /* Clear the priv in adapter */
+ priv->netdev = NULL;
+
+ priv->media_connected = false;
+
+ cancel_work_sync(&priv->cfg_workqueue);
+ flush_workqueue(priv->workqueue);
+ destroy_workqueue(priv->workqueue);
+
+ priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
+
/* station cfg80211 operations */
static struct cfg80211_ops mwifiex_cfg80211_ops = {
+ .add_virtual_intf = mwifiex_add_virtual_intf,
+ .del_virtual_intf = mwifiex_del_virtual_intf,
.change_virtual_intf = mwifiex_cfg80211_change_virtual_intf,
.scan = mwifiex_cfg80211_scan,
.connect = mwifiex_cfg80211_connect,
@@ -1288,8 +1330,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
* default parameters and handler function pointers, and finally
* registers the device.
*/
-int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,
- struct mwifiex_private *priv)
+int mwifiex_register_cfg80211(struct mwifiex_private *priv)
{
int ret;
void *wdev_priv;
@@ -1329,12 +1370,15 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,
wdev->wiphy->cipher_suites = mwifiex_cipher_suites;
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
- memcpy(wdev->wiphy->perm_addr, mac, 6);
+ memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
/* We are using custom domains */
wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+ /* Reserve space for bss band information */
+ wdev->wiphy->bss_priv_size = sizeof(u8);
+
wdev->wiphy->reg_notifier = mwifiex_reg_notifier;
/* Set struct mwifiex_private pointer in wiphy_priv */
@@ -1356,17 +1400,8 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,
"info: successfully registered wiphy device\n");
}
- dev_net_set(dev, wiphy_net(wdev->wiphy));
- dev->ieee80211_ptr = wdev;
- memcpy(dev->dev_addr, wdev->wiphy->perm_addr, 6);
- memcpy(dev->perm_addr, wdev->wiphy->perm_addr, 6);
- SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
priv->wdev = wdev;
- dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
- dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
- dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
-
return ret;
}
@@ -1416,13 +1451,8 @@ mwifiex_cfg80211_results(struct work_struct *work)
MWIFIEX_SCAN_TYPE_ACTIVE;
scan_req->chan_list[i].scan_time = 0;
}
- if (mwifiex_set_user_scan_ioctl(priv, scan_req)) {
+ if (mwifiex_set_user_scan_ioctl(priv, scan_req))
ret = -EFAULT;
- goto done;
- }
- if (mwifiex_inform_bss_from_scan_result(priv, NULL))
- ret = -EFAULT;
-done:
priv->scan_result_status = ret;
dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n",
__func__);
diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h
index c4db8f36aa16..8d010f2500c5 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.h
+++ b/drivers/net/wireless/mwifiex/cfg80211.h
@@ -24,8 +24,7 @@
#include "main.h"
-int mwifiex_register_cfg80211(struct net_device *, u8 *,
- struct mwifiex_private *);
+int mwifiex_register_cfg80211(struct mwifiex_private *);
void mwifiex_cfg80211_results(struct work_struct *work);
#endif
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c
index d0cada5a29a0..f2e6de03805c 100644
--- a/drivers/net/wireless/mwifiex/cfp.c
+++ b/drivers/net/wireless/mwifiex/cfp.c
@@ -48,7 +48,7 @@ static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96,
static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,
0xb0, 0x48, 0x60, 0x6c, 0 };
-u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
+static u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
0xb0, 0x48, 0x60, 0x6c, 0 };
static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04,
0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18,
@@ -57,19 +57,19 @@ static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04,
0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51,
0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 };
-u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 };
+static u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 };
-u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
+static u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
0x30, 0x48, 0x60, 0x6c, 0 };
-u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c,
+static u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c,
0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
0x60, 0x6c, 0 };
u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30,
0x32, 0x40, 0x41, 0xff };
-u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
+static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
/*
* This function maps an index in supported rates table into
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index b5352afb8714..ac278156d390 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -40,8 +40,12 @@ mwifiex_init_cmd_node(struct mwifiex_private *priv,
{
cmd_node->priv = priv;
cmd_node->cmd_oid = cmd_oid;
- cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required;
- priv->adapter->cmd_wait_q_required = false;
+ if (priv->adapter->cmd_wait_q_required) {
+ cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required;
+ priv->adapter->cmd_wait_q_required = false;
+ cmd_node->cmd_wait_q_woken = false;
+ cmd_node->condition = &cmd_node->cmd_wait_q_woken;
+ }
cmd_node->data_buf = data_buf;
cmd_node->cmd_skb = cmd_node->skb;
}
@@ -90,8 +94,11 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
cmd_node->data_buf = NULL;
cmd_node->wait_q_enabled = false;
+ if (cmd_node->cmd_skb)
+ skb_trim(cmd_node->cmd_skb, 0);
+
if (cmd_node->resp_skb) {
- dev_kfree_skb_any(cmd_node->resp_skb);
+ adapter->if_ops.cmdrsp_complete(adapter, cmd_node->resp_skb);
cmd_node->resp_skb = NULL;
}
}
@@ -173,8 +180,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
- cmd_node->cmd_skb->data,
- cmd_node->cmd_skb->len, NULL);
+ cmd_node->cmd_skb, NULL);
skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN);
@@ -235,8 +241,7 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
skb_push(adapter->sleep_cfm, INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
- adapter->sleep_cfm->data,
- adapter->sleep_cfm->len, NULL);
+ adapter->sleep_cfm, NULL);
skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN);
if (ret == -1) {
@@ -399,8 +404,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
adapter->event_cause = 0;
adapter->event_skb = NULL;
-
- dev_kfree_skb_any(skb);
+ adapter->if_ops.event_complete(adapter, skb);
return ret;
}
@@ -418,7 +422,6 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no,
struct mwifiex_adapter *adapter = priv->adapter;
adapter->cmd_wait_q_required = true;
- adapter->cmd_wait_q.condition = false;
ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
data_buf);
@@ -511,10 +514,12 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
}
/* Send command */
- if (cmd_no == HostCmd_CMD_802_11_SCAN)
+ if (cmd_no == HostCmd_CMD_802_11_SCAN) {
mwifiex_queue_scan_cmd(priv, cmd_node);
- else
+ } else {
+ adapter->cmd_queued = cmd_node;
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
+ }
return ret;
}
@@ -535,7 +540,7 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
return;
if (cmd_node->wait_q_enabled)
- mwifiex_complete_cmd(adapter);
+ mwifiex_complete_cmd(adapter, cmd_node);
/* Clean the node */
mwifiex_clean_cmd_node(adapter, cmd_node);
@@ -882,7 +887,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
adapter->curr_cmd->wait_q_enabled = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
adapter->cmd_wait_q.status = -1;
- mwifiex_complete_cmd(adapter);
+ mwifiex_complete_cmd(adapter, adapter->curr_cmd);
}
/* Cancel all pending command */
spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
@@ -893,7 +898,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
if (cmd_node->wait_q_enabled) {
adapter->cmd_wait_q.status = -1;
- mwifiex_complete_cmd(adapter);
+ mwifiex_complete_cmd(adapter, cmd_node);
cmd_node->wait_q_enabled = false;
}
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
@@ -976,7 +981,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
}
adapter->cmd_wait_q.status = -1;
- mwifiex_complete_cmd(adapter);
+ mwifiex_complete_cmd(adapter, adapter->curr_cmd);
}
/*
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 94ddc9038cb3..ae17ce02a3d0 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -98,7 +98,6 @@ struct mwifiex_802_11_ssid {
struct mwifiex_wait_queue {
wait_queue_head_t wait;
- u16 condition;
int status;
};
@@ -114,14 +113,6 @@ struct mwifiex_txinfo {
u8 bss_index;
};
-struct mwifiex_bss_attr {
- u8 bss_type;
- u8 frame_type;
- u8 active;
- u8 bss_priority;
- u8 bss_num;
-};
-
enum mwifiex_wmm_ac_e {
WMM_AC_BK,
WMM_AC_BE,
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 4fee0993b186..0cc5d73cb0c1 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -57,12 +57,6 @@ struct tx_packet_hdr {
#define GET_FW_DEFAULT_BANDS(adapter) \
((adapter->fw_cap_info >> 8) & ALL_802_11_BANDS)
-extern u8 supported_rates_b[B_SUPPORTED_RATES];
-extern u8 supported_rates_g[G_SUPPORTED_RATES];
-extern u8 supported_rates_bg[BG_SUPPORTED_RATES];
-extern u8 supported_rates_a[A_SUPPORTED_RATES];
-extern u8 supported_rates_n[N_SUPPORTED_RATES];
-
#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff
#define KEY_INFO_ENABLED 0x01
@@ -84,7 +78,8 @@ enum KEY_TYPE_ID {
#define MAX_FIRMWARE_POLL_TRIES 100
-#define FIRMWARE_READY 0xfedc
+#define FIRMWARE_READY_SDIO 0xfedc
+#define FIRMWARE_READY_PCIE 0xfedcba00
enum MWIFIEX_802_11_PRIVACY_FILTER {
MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL,
@@ -221,7 +216,7 @@ enum MWIFIEX_802_11_WEP_STATUS {
#define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5
#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed
#define HostCmd_CMD_SET_BSS_MODE 0x00f7
-
+#define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa
enum ENH_PS_MODES {
EN_PS = 1,
@@ -821,6 +816,14 @@ struct host_cmd_ds_txpwr_cfg {
__le32 mode;
} __packed;
+struct mwifiex_bcn_param {
+ u8 bssid[ETH_ALEN];
+ u8 rssi;
+ __le32 timestamp[2];
+ __le16 beacon_period;
+ __le16 cap_info_bitmap;
+} __packed;
+
#define MWIFIEX_USER_SCAN_CHAN_MAX 50
#define MWIFIEX_MAX_SSID_LIST_LENGTH 10
@@ -862,13 +865,6 @@ struct mwifiex_user_scan_ssid {
struct mwifiex_user_scan_cfg {
/*
- * Flag set to keep the previous scan table intact
- *
- * If set, the scan results will accumulate, replacing any previous
- * matched entries for a BSS with the new scan data
- */
- u8 keep_previous_scan;
- /*
* BSS mode to be sent in the firmware command
*/
u8 bss_mode;
@@ -1136,6 +1132,30 @@ struct host_cmd_ds_set_bss_mode {
u8 con_type;
} __packed;
+struct host_cmd_ds_pcie_details {
+ /* TX buffer descriptor ring address */
+ u32 txbd_addr_lo;
+ u32 txbd_addr_hi;
+ /* TX buffer descriptor ring count */
+ u32 txbd_count;
+
+ /* RX buffer descriptor ring address */
+ u32 rxbd_addr_lo;
+ u32 rxbd_addr_hi;
+ /* RX buffer descriptor ring count */
+ u32 rxbd_count;
+
+ /* Event buffer descriptor ring address */
+ u32 evtbd_addr_lo;
+ u32 evtbd_addr_hi;
+ /* Event buffer descriptor ring count */
+ u32 evtbd_count;
+
+ /* Sleep cookie buffer physical address */
+ u32 sleep_cookie_addr_lo;
+ u32 sleep_cookie_addr_hi;
+} __packed;
+
struct host_cmd_ds_command {
__le16 command;
__le16 size;
@@ -1183,6 +1203,7 @@ struct host_cmd_ds_command {
struct host_cmd_ds_rf_reg_access rf_reg;
struct host_cmd_ds_pmic_reg_access pmic_reg;
struct host_cmd_ds_set_bss_mode bss_mode;
+ struct host_cmd_ds_pcie_details pcie_host_spec;
struct host_cmd_ds_802_11_eeprom_access eeprom;
} params;
} __packed;
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 3f1559e61320..d792b3fb7c16 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -76,7 +76,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
memset(priv->curr_addr, 0xff, ETH_ALEN);
priv->pkt_tx_ctrl = 0;
- priv->bss_mode = NL80211_IFTYPE_STATION;
+ priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
priv->data_rate = 0; /* Initially indicate the rate as auto */
priv->is_data_rate_auto = true;
priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
@@ -152,19 +152,6 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
{
int ret;
- u32 buf_size;
- struct mwifiex_bssdescriptor *temp_scan_table;
-
- /* Allocate buffer to store the BSSID list */
- buf_size = sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP;
- temp_scan_table = kzalloc(buf_size, GFP_KERNEL);
- if (!temp_scan_table) {
- dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n",
- __func__);
- return -ENOMEM;
- }
-
- adapter->scan_table = temp_scan_table;
/* Allocate command buffer */
ret = mwifiex_alloc_cmd_buffer(adapter);
@@ -204,7 +191,12 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
(adapter->sleep_cfm->data);
adapter->cmd_sent = false;
- adapter->data_sent = true;
+
+ if (adapter->iface_type == MWIFIEX_PCIE)
+ adapter->data_sent = false;
+ else
+ adapter->data_sent = true;
+
adapter->cmd_resp_received = false;
adapter->event_received = false;
adapter->data_received = false;
@@ -222,14 +214,8 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME;
adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME;
- adapter->num_in_scan_table = 0;
- memset(adapter->scan_table, 0,
- (sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP));
adapter->scan_probes = 1;
- memset(adapter->bcn_buf, 0, sizeof(adapter->bcn_buf));
- adapter->bcn_buf_end = adapter->bcn_buf;
-
adapter->multiple_dtim = 1;
adapter->local_listen_interval = 0; /* default value in firmware
@@ -297,6 +283,34 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
}
/*
+ * This function releases the lock variables and frees the locks and
+ * associated locks.
+ */
+static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
+{
+ struct mwifiex_private *priv;
+ s32 i, j;
+
+ /* Free lists */
+ list_del(&adapter->cmd_free_q);
+ list_del(&adapter->cmd_pending_q);
+ list_del(&adapter->scan_pending_q);
+
+ for (i = 0; i < adapter->priv_num; i++)
+ list_del(&adapter->bss_prio_tbl[i].bss_prio_head);
+
+ for (i = 0; i < adapter->priv_num; i++) {
+ if (adapter->priv[i]) {
+ priv = adapter->priv[i];
+ for (j = 0; j < MAX_NUM_TID; ++j)
+ list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
+ list_del(&priv->tx_ba_stream_tbl_ptr);
+ list_del(&priv->rx_reorder_tbl_ptr);
+ }
+ }
+}
+
+/*
* This function frees the adapter structure.
*
* The freeing operation is done recursively, by canceling all
@@ -326,8 +340,6 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)
del_timer(&adapter->cmd_timer);
dev_dbg(adapter->dev, "info: free scan table\n");
- kfree(adapter->scan_table);
- adapter->scan_table = NULL;
adapter->if_ops.cleanup_if(adapter);
@@ -392,34 +404,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
}
/*
- * This function releases the lock variables and frees the locks and
- * associated locks.
- */
-void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
-{
- struct mwifiex_private *priv;
- s32 i, j;
-
- /* Free lists */
- list_del(&adapter->cmd_free_q);
- list_del(&adapter->cmd_pending_q);
- list_del(&adapter->scan_pending_q);
-
- for (i = 0; i < adapter->priv_num; i++)
- list_del(&adapter->bss_prio_tbl[i].bss_prio_head);
-
- for (i = 0; i < adapter->priv_num; i++) {
- if (adapter->priv[i]) {
- priv = adapter->priv[i];
- for (j = 0; j < MAX_NUM_TID; ++j)
- list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
- list_del(&priv->tx_ba_stream_tbl_ptr);
- list_del(&priv->rx_reorder_tbl_ptr);
- }
- }
-}
-
-/*
* This function initializes the firmware.
*
* The following operations are performed sequentially -
@@ -602,11 +586,13 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
struct mwifiex_fw_image *pmfw)
{
- int ret, winner;
+ int ret;
u32 poll_num = 1;
+ adapter->winner = 0;
+
/* Check if firmware is already running */
- ret = adapter->if_ops.check_fw_status(adapter, poll_num, &winner);
+ ret = adapter->if_ops.check_fw_status(adapter, poll_num);
if (!ret) {
dev_notice(adapter->dev,
"WLAN FW already running! Skip FW download\n");
@@ -615,7 +601,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
poll_num = MAX_FIRMWARE_POLL_TRIES;
/* Check if we are the winner for downloading FW */
- if (!winner) {
+ if (!adapter->winner) {
dev_notice(adapter->dev,
"Other interface already running!"
" Skip FW download\n");
@@ -633,7 +619,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
poll_fw:
/* Check if the firmware is downloaded successfully or not */
- ret = adapter->if_ops.check_fw_status(adapter, poll_num, NULL);
+ ret = adapter->if_ops.check_fw_status(adapter, poll_num);
if (ret) {
dev_err(adapter->dev, "FW failed to be active in time\n");
return -1;
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index f6bcc868562f..e0b68e7c8ca2 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -134,7 +134,6 @@ struct mwifiex_ver_ext {
struct mwifiex_bss_info {
u32 bss_mode;
struct mwifiex_802_11_ssid ssid;
- u32 scan_table_idx;
u32 bss_chan;
u32 region_code;
u32 media_connected;
@@ -307,10 +306,12 @@ struct mwifiex_ds_read_eeprom {
u8 value[MAX_EEPROM_DATA];
};
+#define IEEE_MAX_IE_SIZE 256
+
struct mwifiex_ds_misc_gen_ie {
u32 type;
u32 len;
- u8 ie_data[IW_CUSTOM_MAX];
+ u8 ie_data[IEEE_MAX_IE_SIZE];
};
struct mwifiex_ds_misc_cmd {
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 644e2e405cb5..62b4c2938608 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -147,13 +147,12 @@ static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1,
u8 *ptr = rate1, *tmp;
u32 i, j;
- tmp = kmalloc(rate1_size, GFP_KERNEL);
+ tmp = kmemdup(rate1, rate1_size, GFP_KERNEL);
if (!tmp) {
dev_err(priv->adapter->dev, "failed to alloc tmp buf\n");
return -ENOMEM;
}
- memcpy(tmp, rate1, rate1_size);
memset(rate1, 0, rate1_size);
for (i = 0; rate2[i] && i < rate2_size; i++) {
@@ -224,32 +223,6 @@ mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv,
}
/*
- * This function updates the scan entry TSF timestamps to reflect
- * a new association.
- */
-static void
-mwifiex_update_tsf_timestamps(struct mwifiex_private *priv,
- struct mwifiex_bssdescriptor *new_bss_desc)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u32 table_idx;
- long long new_tsf_base;
- signed long long tsf_delta;
-
- memcpy(&new_tsf_base, new_bss_desc->time_stamp, sizeof(new_tsf_base));
-
- tsf_delta = new_tsf_base - new_bss_desc->network_tsf;
-
- dev_dbg(adapter->dev, "info: TSF: update TSF timestamps, "
- "0x%016llx -> 0x%016llx\n",
- new_bss_desc->network_tsf, new_tsf_base);
-
- for (table_idx = 0; table_idx < adapter->num_in_scan_table;
- table_idx++)
- adapter->scan_table[table_idx].network_tsf += tsf_delta;
-}
-
-/*
* This function appends a WAPI IE.
*
* This function is called from the network join command preparation routine.
@@ -639,12 +612,6 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
priv->curr_bss_params.band = (u8) bss_desc->bss_band;
- /*
- * Adjust the timestamps in the scan table to be relative to the newly
- * associated AP's TSF
- */
- mwifiex_update_tsf_timestamps(priv, bss_desc);
-
if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)
priv->curr_bss_params.wmm_enabled = true;
else
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index e5fc53dc6887..67e6db7d672d 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -26,21 +26,6 @@
const char driver_version[] = "mwifiex " VERSION " (%s) ";
-static struct mwifiex_bss_attr mwifiex_bss_sta[] = {
- {MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0},
-};
-
-static int drv_mode = DRV_MODE_STA;
-
-/* Supported drv_mode table */
-static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
- {
- .drv_mode = DRV_MODE_STA,
- .intf_num = ARRAY_SIZE(mwifiex_bss_sta),
- .bss_attr = mwifiex_bss_sta,
- },
-};
-
/*
* This function registers the device and performs all the necessary
* initializations.
@@ -57,7 +42,6 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
* proper cleanup before exiting.
*/
static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
- struct mwifiex_drv_mode *drv_mode_ptr,
void **padapter)
{
struct mwifiex_adapter *adapter;
@@ -78,44 +62,20 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
goto error;
adapter->priv_num = 0;
- for (i = 0; i < drv_mode_ptr->intf_num; i++) {
- adapter->priv[i] = NULL;
-
- if (!drv_mode_ptr->bss_attr[i].active)
- continue;
- /* Allocate memory for private structure */
- adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private),
- GFP_KERNEL);
- if (!adapter->priv[i]) {
- dev_err(adapter->dev, "%s: failed to alloc priv[%d]\n",
- __func__, i);
- goto error;
- }
-
- adapter->priv_num++;
- adapter->priv[i]->adapter = adapter;
- /* Save bss_type, frame_type & bss_priority */
- adapter->priv[i]->bss_type = drv_mode_ptr->bss_attr[i].bss_type;
- adapter->priv[i]->frame_type =
- drv_mode_ptr->bss_attr[i].frame_type;
- adapter->priv[i]->bss_priority =
- drv_mode_ptr->bss_attr[i].bss_priority;
-
- if (drv_mode_ptr->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA)
- adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_STA;
- else if (drv_mode_ptr->bss_attr[i].bss_type ==
- MWIFIEX_BSS_TYPE_UAP)
- adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_UAP;
-
- /* Save bss_index & bss_num */
- adapter->priv[i]->bss_index = i;
- adapter->priv[i]->bss_num = drv_mode_ptr->bss_attr[i].bss_num;
+ /* Allocate memory for private structure */
+ adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private),
+ GFP_KERNEL);
+ if (!adapter->priv[0]) {
+ dev_err(adapter->dev, "%s: failed to alloc priv[0]\n",
+ __func__);
+ goto error;
}
- adapter->drv_mode = drv_mode_ptr;
- if (mwifiex_init_lock_list(adapter))
- goto error;
+ adapter->priv_num++;
+
+ adapter->priv[0]->adapter = adapter;
+ mwifiex_init_lock_list(adapter);
init_timer(&adapter->cmd_timer);
adapter->cmd_timer.function = mwifiex_cmd_timeout_func;
@@ -126,9 +86,9 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
error:
dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n");
- mwifiex_free_lock_list(adapter);
- for (i = 0; i < drv_mode_ptr->intf_num; i++)
+ for (i = 0; i < adapter->priv_num; i++)
kfree(adapter->priv[i]);
+
kfree(adapter);
return -1;
@@ -316,38 +276,6 @@ exit_main_proc:
}
/*
- * This function initializes the software.
- *
- * The main work includes allocating and initializing the adapter structure
- * and initializing the private structures.
- */
-static int
-mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **padapter)
-{
- int i;
- struct mwifiex_drv_mode *drv_mode_ptr;
-
- /* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */
- drv_mode_ptr = NULL;
- for (i = 0; i < ARRAY_SIZE(mwifiex_drv_mode_tbl); i++) {
- if (mwifiex_drv_mode_tbl[i].drv_mode == drv_mode) {
- drv_mode_ptr = &mwifiex_drv_mode_tbl[i];
- break;
- }
- }
-
- if (!drv_mode_ptr) {
- pr_err("invalid drv_mode=%d\n", drv_mode);
- return -1;
- }
-
- if (mwifiex_register(card, if_ops, drv_mode_ptr, padapter))
- return -1;
-
- return 0;
-}
-
-/*
* This function frees the adapter structure.
*
* Additionally, this closes the netlink socket, frees the timers
@@ -627,7 +555,7 @@ static const struct net_device_ops mwifiex_netdev_ops = {
.ndo_set_mac_address = mwifiex_set_mac_address,
.ndo_tx_timeout = mwifiex_tx_timeout,
.ndo_get_stats = mwifiex_get_stats,
- .ndo_set_multicast_list = mwifiex_set_multicast_list,
+ .ndo_set_rx_mode = mwifiex_set_multicast_list,
};
/*
@@ -649,8 +577,8 @@ static const struct net_device_ops mwifiex_netdev_ops = {
*
* In addition, the CFG80211 work queue is also created.
*/
-static void
-mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev)
+void mwifiex_init_priv_params(struct mwifiex_private *priv,
+ struct net_device *dev)
{
dev->netdev_ops = &mwifiex_netdev_ops;
/* Initialize private structure */
@@ -664,118 +592,6 @@ mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev)
}
/*
- * This function adds a new logical interface.
- *
- * It allocates, initializes and registers the interface by performing
- * the following opearations -
- * - Allocate a new net device structure
- * - Assign device name
- * - Register the new device with CFG80211 subsystem
- * - Initialize semaphore and private structure
- * - Register the new device with kernel
- * - Create the complete debug FS structure if configured
- */
-static struct mwifiex_private *mwifiex_add_interface(
- struct mwifiex_adapter *adapter,
- u8 bss_index, u8 bss_type)
-{
- struct net_device *dev;
- struct mwifiex_private *priv;
- void *mdev_priv;
-
- dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d",
- ether_setup, 1);
- if (!dev) {
- dev_err(adapter->dev, "no memory available for netdevice\n");
- goto error;
- }
-
- if (mwifiex_register_cfg80211(dev, adapter->priv[bss_index]->curr_addr,
- adapter->priv[bss_index]) != 0) {
- dev_err(adapter->dev, "cannot register netdevice with cfg80211\n");
- goto error;
- }
- /* Save the priv pointer in netdev */
- priv = adapter->priv[bss_index];
- mdev_priv = netdev_priv(dev);
- *((unsigned long *) mdev_priv) = (unsigned long) priv;
-
- priv->netdev = dev;
-
- sema_init(&priv->async_sem, 1);
- priv->scan_pending_on_block = false;
-
- mwifiex_init_priv_params(priv, dev);
-
- SET_NETDEV_DEV(dev, adapter->dev);
-
- /* Register network device */
- if (register_netdev(dev)) {
- dev_err(adapter->dev, "cannot register virtual network device\n");
- goto error;
- }
-
- dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
-#ifdef CONFIG_DEBUG_FS
- mwifiex_dev_debugfs_init(priv);
-#endif
- return priv;
-error:
- if (dev)
- free_netdev(dev);
- return NULL;
-}
-
-/*
- * This function removes a logical interface.
- *
- * It deregisters, resets and frees the interface by performing
- * the following operations -
- * - Disconnect the device if connected, send wireless event to
- * notify applications.
- * - Remove the debug FS structure if configured
- * - Unregister the device from kernel
- * - Free the net device structure
- * - Cancel all works and destroy work queue
- * - Unregister and free the wireless device from CFG80211 subsystem
- */
-static void
-mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index)
-{
- struct net_device *dev;
- struct mwifiex_private *priv = adapter->priv[bss_index];
-
- if (!priv)
- return;
- dev = priv->netdev;
-
- if (priv->media_connected)
- priv->media_connected = false;
-
-#ifdef CONFIG_DEBUG_FS
- mwifiex_dev_debugfs_remove(priv);
-#endif
- /* Last reference is our one */
- dev_dbg(adapter->dev, "info: %s: refcnt = %d\n",
- dev->name, netdev_refcnt_read(dev));
-
- if (dev->reg_state == NETREG_REGISTERED)
- unregister_netdev(dev);
-
- /* Clear the priv in adapter */
- priv->netdev = NULL;
- if (dev)
- free_netdev(dev);
-
- cancel_work_sync(&priv->cfg_workqueue);
- flush_workqueue(priv->workqueue);
- destroy_workqueue(priv->workqueue);
- wiphy_unregister(priv->wdev->wiphy);
- wiphy_free(priv->wdev->wiphy);
- kfree(priv->wdev);
-}
-
-/*
* This function check if command is pending.
*/
int is_command_pending(struct mwifiex_adapter *adapter)
@@ -845,19 +661,22 @@ mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
*/
int
mwifiex_add_card(void *card, struct semaphore *sem,
- struct mwifiex_if_ops *if_ops)
+ struct mwifiex_if_ops *if_ops, u8 iface_type)
{
- int i;
struct mwifiex_adapter *adapter;
+ char fmt[64];
+ struct mwifiex_private *priv;
if (down_interruptible(sem))
goto exit_sem_err;
- if (mwifiex_init_sw(card, if_ops, (void **)&adapter)) {
+ if (mwifiex_register(card, if_ops, (void **)&adapter)) {
pr_err("%s: software init failed\n", __func__);
goto err_init_sw;
}
+ adapter->iface_type = iface_type;
+
adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
adapter->surprise_removed = false;
init_waitqueue_head(&adapter->init_wait_q);
@@ -866,8 +685,8 @@ mwifiex_add_card(void *card, struct semaphore *sem,
init_waitqueue_head(&adapter->hs_activate_wait_q);
adapter->cmd_wait_q_required = false;
init_waitqueue_head(&adapter->cmd_wait_q.wait);
- adapter->cmd_wait_q.condition = false;
adapter->cmd_wait_q.status = 0;
+ adapter->scan_wait_q_woken = false;
adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE");
if (!adapter->workqueue)
@@ -887,21 +706,37 @@ mwifiex_add_card(void *card, struct semaphore *sem,
goto err_init_fw;
}
- /* Add interfaces */
- for (i = 0; i < adapter->drv_mode->intf_num; i++) {
- if (!mwifiex_add_interface(adapter, i,
- adapter->drv_mode->bss_attr[i].bss_type)) {
- goto err_add_intf;
- }
+ priv = adapter->priv[0];
+
+ if (mwifiex_register_cfg80211(priv) != 0) {
+ dev_err(adapter->dev, "cannot register netdevice"
+ " with cfg80211\n");
+ goto err_init_fw;
}
+ rtnl_lock();
+ /* Create station interface by default */
+ if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d",
+ NL80211_IFTYPE_STATION, NULL, NULL)) {
+ rtnl_unlock();
+ dev_err(adapter->dev, "cannot create default station"
+ " interface\n");
+ goto err_add_intf;
+ }
+
+ rtnl_unlock();
+
up(sem);
+ mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
+ dev_notice(adapter->dev, "driver_version = %s\n", fmt);
+
return 0;
err_add_intf:
- for (i = 0; i < adapter->priv_num; i++)
- mwifiex_remove_interface(adapter, i);
+ rtnl_lock();
+ mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
+ rtnl_unlock();
err_init_fw:
pr_debug("info: %s: unregister device\n", __func__);
adapter->if_ops.unregister_dev(adapter);
@@ -956,7 +791,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
/* Stop data */
for (i = 0; i < adapter->priv_num; i++) {
priv = adapter->priv[i];
- if (priv) {
+ if (priv && priv->netdev) {
if (!netif_queue_stopped(priv->netdev))
netif_stop_queue(priv->netdev);
if (netif_carrier_ok(priv->netdev))
@@ -981,9 +816,24 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
atomic_read(&adapter->cmd_pending));
}
- /* Remove interface */
- for (i = 0; i < adapter->priv_num; i++)
- mwifiex_remove_interface(adapter, i);
+ for (i = 0; i < adapter->priv_num; i++) {
+ priv = adapter->priv[i];
+
+ if (!priv)
+ continue;
+
+ rtnl_lock();
+ mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
+ rtnl_unlock();
+ }
+
+ priv = adapter->priv[0];
+ if (!priv)
+ goto exit_remove;
+
+ wiphy_unregister(priv->wdev->wiphy);
+ wiphy_free(priv->wdev->wiphy);
+ kfree(priv->wdev);
mwifiex_terminate_workqueue(adapter);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 2215c3c97354..30f138b6fa4c 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -37,6 +37,7 @@
#include "ioctl.h"
#include "util.h"
#include "fw.h"
+#include "pcie.h"
extern const char driver_version[];
@@ -45,14 +46,7 @@ enum {
MWIFIEX_SYNC_CMD
};
-#define DRV_MODE_STA 0x1
-
-struct mwifiex_drv_mode {
- u16 drv_mode;
- u16 intf_num;
- struct mwifiex_bss_attr *bss_attr;
-};
-
+#define MWIFIEX_MAX_AP 64
#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ)
@@ -114,6 +108,8 @@ struct mwifiex_drv_mode {
#define MAX_FREQUENCY_BAND_BG 2484
+#define MWIFIEX_EVENT_HEADER_LEN 4
+
struct mwifiex_dbg {
u32 num_cmd_host_to_card_failure;
u32 num_cmd_sleep_cfm_host_to_card_failure;
@@ -163,6 +159,11 @@ enum MWIFIEX_PS_STATE {
PS_STATE_SLEEP
};
+enum mwifiex_iface_type {
+ MWIFIEX_SDIO,
+ MWIFIEX_PCIE,
+};
+
struct mwifiex_add_ba_param {
u32 tx_win_size;
u32 rx_win_size;
@@ -180,7 +181,6 @@ struct mwifiex_ra_list_tbl {
struct sk_buff_head skb_head;
u8 ra[ETH_ALEN];
u32 total_pkts_size;
- u32 total_pkts;
u32 is_11n_enabled;
};
@@ -227,27 +227,10 @@ struct ieee_types_header {
u8 len;
} __packed;
-struct ieee_obss_scan_param {
- u16 obss_scan_passive_dwell;
- u16 obss_scan_active_dwell;
- u16 bss_chan_width_trigger_scan_int;
- u16 obss_scan_passive_total;
- u16 obss_scan_active_total;
- u16 bss_width_chan_trans_delay;
- u16 obss_scan_active_threshold;
-} __packed;
-
-struct ieee_types_obss_scan_param {
- struct ieee_types_header ieee_hdr;
- struct ieee_obss_scan_param obss_scan;
-} __packed;
-
#define MWIFIEX_SUPPORTED_RATES 14
#define MWIFIEX_SUPPORTED_RATES_EXT 32
-#define IEEE_MAX_IE_SIZE 256
-
struct ieee_types_vendor_specific {
struct ieee_types_vendor_header vend_hdr;
u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)];
@@ -291,8 +274,6 @@ struct mwifiex_bssdescriptor {
u16 bss_co_2040_offset;
u8 *bcn_ext_cap;
u16 ext_cap_offset;
- struct ieee_types_obss_scan_param *bcn_obss_scan;
- u16 overlap_bss_offset;
struct ieee_types_vendor_specific *bcn_wpa_ie;
u16 wpa_offset;
struct ieee_types_generic *bcn_rsn_ie;
@@ -301,8 +282,6 @@ struct mwifiex_bssdescriptor {
u16 wapi_offset;
u8 *beacon_buf;
u32 beacon_buf_size;
- u32 beacon_buf_size_max;
-
};
struct mwifiex_current_bss_params {
@@ -468,7 +447,7 @@ struct mwifiex_private {
struct dentry *dfs_dev_dir;
#endif
u8 nick_name[16];
- struct iw_statistics w_stats;
+ u8 qual_level, qual_noise;
u16 current_key_index;
struct semaphore async_sem;
u8 scan_pending_on_block;
@@ -541,33 +520,38 @@ struct cmd_ctrl_node {
void *data_buf;
u32 wait_q_enabled;
struct sk_buff *skb;
+ u8 *condition;
+ u8 cmd_wait_q_woken;
};
struct mwifiex_if_ops {
int (*init_if) (struct mwifiex_adapter *);
void (*cleanup_if) (struct mwifiex_adapter *);
- int (*check_fw_status) (struct mwifiex_adapter *, u32, int *);
+ int (*check_fw_status) (struct mwifiex_adapter *, u32);
int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
int (*register_dev) (struct mwifiex_adapter *);
void (*unregister_dev) (struct mwifiex_adapter *);
int (*enable_int) (struct mwifiex_adapter *);
int (*process_int_status) (struct mwifiex_adapter *);
- int (*host_to_card) (struct mwifiex_adapter *, u8,
- u8 *payload, u32 pkt_len,
+ int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *,
struct mwifiex_tx_param *);
int (*wakeup) (struct mwifiex_adapter *);
int (*wakeup_complete) (struct mwifiex_adapter *);
+ /* Interface specific functions */
void (*update_mp_end_port) (struct mwifiex_adapter *, u16);
void (*cleanup_mpa_buf) (struct mwifiex_adapter *);
+ int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *);
+ int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *);
};
struct mwifiex_adapter {
+ u8 iface_type;
struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM];
u8 priv_num;
- struct mwifiex_drv_mode *drv_mode;
const struct firmware *firmware;
char fw_name[32];
+ int winner;
struct device *dev;
bool surprise_removed;
u32 fw_release_number;
@@ -624,15 +608,11 @@ struct mwifiex_adapter {
u32 scan_processing;
u16 region_code;
struct mwifiex_802_11d_domain_reg domain_reg;
- struct mwifiex_bssdescriptor *scan_table;
- u32 num_in_scan_table;
u16 scan_probes;
u32 scan_mode;
u16 specific_scan_time;
u16 active_scan_time;
u16 passive_scan_time;
- u8 bcn_buf[MAX_SCAN_BEACON_BUFFER];
- u8 *bcn_buf_end;
u8 fw_bands;
u8 adhoc_start_band;
u8 config_bands;
@@ -673,10 +653,11 @@ struct mwifiex_adapter {
u32 arp_filter_size;
u16 cmd_wait_q_required;
struct mwifiex_wait_queue cmd_wait_q;
+ u8 scan_wait_q_woken;
+ struct cmd_ctrl_node *cmd_queued;
};
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
-void mwifiex_free_lock_list(struct mwifiex_adapter *adapter);
int mwifiex_init_fw(struct mwifiex_adapter *adapter);
@@ -692,7 +673,8 @@ int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb);
int mwifiex_process_event(struct mwifiex_adapter *adapter);
-int mwifiex_complete_cmd(struct mwifiex_adapter *adapter);
+int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
+ struct cmd_ctrl_node *cmd_node);
int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
u16 cmd_action, u32 cmd_oid, void *data_buf);
@@ -726,8 +708,6 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
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);
-int mwifiex_recv_packet_complete(struct mwifiex_adapter *,
- struct sk_buff *skb, 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);
@@ -757,21 +737,12 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
int mwifiex_process_sta_event(struct mwifiex_private *);
void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
-int mwifiex_scan_networks(struct mwifiex_private *priv,
- const struct mwifiex_user_scan_cfg *user_scan_in);
int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
struct mwifiex_scan_cmd_config *scan_cfg);
void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
struct cmd_ctrl_node *cmd_node);
int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
-s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *ssid, u8 *bssid,
- u32 mode);
-s32 mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid,
- u32 mode);
-int mwifiex_find_best_network(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *req_ssid_bssid);
s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
struct mwifiex_802_11_ssid *ssid2);
int mwifiex_associate(struct mwifiex_private *priv,
@@ -782,7 +753,6 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
void mwifiex_reset_connect_state(struct mwifiex_private *priv);
-void mwifiex_2040_coex_event(struct mwifiex_private *priv);
u8 mwifiex_band_to_radio_type(u8 band);
int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
int mwifiex_adhoc_start(struct mwifiex_private *priv,
@@ -823,6 +793,8 @@ int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv,
int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
int is_command_pending(struct mwifiex_adapter *adapter);
+void mwifiex_init_priv_params(struct mwifiex_private *priv,
+ struct net_device *dev);
/*
* This function checks if the queuing is RA based or not.
@@ -912,7 +884,7 @@ struct mwifiex_private *mwifiex_bss_index_to_priv(struct mwifiex_adapter
*adapter, u8 bss_index);
int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
u32 func_init_shutdown);
-int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *);
+int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
@@ -922,11 +894,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
struct net_device *dev);
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
-int mwifiex_bss_start(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *ssid_bssid);
-int mwifiex_set_hs_params(struct mwifiex_private *priv,
- u16 action, int cmd_type,
- struct mwifiex_ds_hs_cfg *hscfg);
+int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
+ struct mwifiex_802_11_ssid *req_ssid);
int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
int mwifiex_disable_auto_ds(struct mwifiex_private *priv);
@@ -934,8 +903,6 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv,
struct mwifiex_ds_get_signal *signal);
int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate);
-int mwifiex_find_best_bss(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *ssid_bssid);
int mwifiex_request_scan(struct mwifiex_private *priv,
struct mwifiex_802_11_ssid *req_ssid);
int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
@@ -984,12 +951,26 @@ int mwifiex_main_process(struct mwifiex_adapter *);
int mwifiex_bss_set_channel(struct mwifiex_private *,
struct mwifiex_chan_freq_power *cfp);
-int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *,
- struct mwifiex_ssid_bssid *);
int mwifiex_set_radio_band_cfg(struct mwifiex_private *,
struct mwifiex_ds_band_cfg *);
int mwifiex_get_bss_info(struct mwifiex_private *,
struct mwifiex_bss_info *);
+int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
+ u8 *bssid, s32 rssi, u8 *ie_buf,
+ size_t ie_len, u16 beacon_period,
+ u16 cap_info_bitmap, u8 band,
+ struct mwifiex_bssdescriptor *bss_desc);
+int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
+ struct mwifiex_bssdescriptor *bss_entry,
+ u8 *ie_buf, u32 ie_len);
+int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
+ struct mwifiex_bssdescriptor *bss_desc);
+
+struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
+ char *name, enum nl80211_iftype type,
+ u32 *flags, struct vif_params *params);
+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev);
+
#ifdef CONFIG_DEBUG_FS
void mwifiex_debugfs_init(void);
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
new file mode 100644
index 000000000000..d34acf082d3a
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -0,0 +1,1948 @@
+/*
+ * Marvell Wireless LAN device driver: PCIE specific handling
+ *
+ * Copyright (C) 2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include <linux/firmware.h>
+
+#include "decl.h"
+#include "ioctl.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+#include "11n.h"
+#include "pcie.h"
+
+#define PCIE_VERSION "1.0"
+#define DRV_NAME "Marvell mwifiex PCIe"
+
+static u8 user_rmmod;
+
+static struct mwifiex_if_ops pcie_ops;
+
+static struct semaphore add_remove_card_sem;
+static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter);
+static int mwifiex_pcie_resume(struct pci_dev *pdev);
+
+/*
+ * This function is called after skb allocation to update
+ * "skb->cb" with physical address of data pointer.
+ */
+static phys_addr_t *mwifiex_update_sk_buff_pa(struct sk_buff *skb)
+{
+ phys_addr_t *buf_pa = MWIFIEX_SKB_PACB(skb);
+
+ *buf_pa = (phys_addr_t)virt_to_phys(skb->data);
+
+ return buf_pa;
+}
+
+/*
+ * This function reads sleep cookie and checks if FW is ready
+ */
+static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
+{
+ u32 *cookie_addr;
+ struct pcie_service_card *card = adapter->card;
+
+ if (card->sleep_cookie) {
+ cookie_addr = (u32 *)card->sleep_cookie->data;
+ dev_dbg(adapter->dev, "info: ACCESS_HW: sleep cookie=0x%x\n",
+ *cookie_addr);
+ if (*cookie_addr == FW_AWAKE_COOKIE)
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * This function probes an mwifiex device and registers it. It allocates
+ * the card structure, enables PCIE function number and initiates the
+ * device registration and initialization procedure by adding a logical
+ * interface.
+ */
+static int mwifiex_pcie_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct pcie_service_card *card;
+
+ pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
+ pdev->vendor, pdev->device, pdev->revision);
+
+ card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL);
+ if (!card) {
+ pr_err("%s: failed to alloc memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ card->dev = pdev;
+
+ if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
+ MWIFIEX_PCIE)) {
+ pr_err("%s failed\n", __func__);
+ kfree(card);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * This function removes the interface and frees up the card structure.
+ */
+static void mwifiex_pcie_remove(struct pci_dev *pdev)
+{
+ struct pcie_service_card *card;
+ struct mwifiex_adapter *adapter;
+ int i;
+
+ card = pci_get_drvdata(pdev);
+ if (!card)
+ return;
+
+ adapter = card->adapter;
+ if (!adapter || !adapter->priv_num)
+ return;
+
+ if (user_rmmod) {
+#ifdef CONFIG_PM
+ if (adapter->is_suspended)
+ mwifiex_pcie_resume(pdev);
+#endif
+
+ for (i = 0; i < adapter->priv_num; i++)
+ if ((GET_BSS_ROLE(adapter->priv[i]) ==
+ MWIFIEX_BSS_ROLE_STA) &&
+ adapter->priv[i]->media_connected)
+ mwifiex_deauthenticate(adapter->priv[i], NULL);
+
+ mwifiex_disable_auto_ds(mwifiex_get_priv(adapter,
+ MWIFIEX_BSS_ROLE_ANY));
+
+ mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
+ MWIFIEX_BSS_ROLE_ANY),
+ MWIFIEX_FUNC_SHUTDOWN);
+ }
+
+ mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+ kfree(card);
+}
+
+/*
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not suspended, this function allocates and sends a host
+ * sleep activate request to the firmware and turns off the traffic.
+ */
+static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct mwifiex_adapter *adapter;
+ struct pcie_service_card *card;
+ int hs_actived, i;
+
+ if (pdev) {
+ card = (struct pcie_service_card *) pci_get_drvdata(pdev);
+ if (!card || card->adapter) {
+ pr_err("Card or adapter structure is not valid\n");
+ return 0;
+ }
+ } else {
+ pr_err("PCIE device is not specified\n");
+ return 0;
+ }
+
+ adapter = card->adapter;
+
+ hs_actived = mwifiex_enable_hs(adapter);
+
+ /* Indicate device suspended */
+ adapter->is_suspended = true;
+
+ for (i = 0; i < adapter->priv_num; i++)
+ netif_carrier_off(adapter->priv[i]->netdev);
+
+ return 0;
+}
+
+/*
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not resumed, this function turns on the traffic and
+ * sends a host sleep cancel request to the firmware.
+ */
+static int mwifiex_pcie_resume(struct pci_dev *pdev)
+{
+ struct mwifiex_adapter *adapter;
+ struct pcie_service_card *card;
+ int i;
+
+ if (pdev) {
+ card = (struct pcie_service_card *) pci_get_drvdata(pdev);
+ if (!card || !card->adapter) {
+ pr_err("Card or adapter structure is not valid\n");
+ return 0;
+ }
+ } else {
+ pr_err("PCIE device is not specified\n");
+ return 0;
+ }
+
+ adapter = card->adapter;
+
+ if (!adapter->is_suspended) {
+ dev_warn(adapter->dev, "Device already resumed\n");
+ return 0;
+ }
+
+ adapter->is_suspended = false;
+
+ for (i = 0; i < adapter->priv_num; i++)
+ if (adapter->priv[i]->media_connected)
+ netif_carrier_on(adapter->priv[i]->netdev);
+
+ mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
+ MWIFIEX_ASYNC_CMD);
+
+ return 0;
+}
+
+#define PCIE_VENDOR_ID_MARVELL (0x11ab)
+#define PCIE_DEVICE_ID_MARVELL_88W8766P (0x2b30)
+
+static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = {
+ {
+ PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(pci, mwifiex_ids);
+
+/* PCI Device Driver */
+static struct pci_driver __refdata mwifiex_pcie = {
+ .name = "mwifiex_pcie",
+ .id_table = mwifiex_ids,
+ .probe = mwifiex_pcie_probe,
+ .remove = mwifiex_pcie_remove,
+#ifdef CONFIG_PM
+ /* Power Management Hooks */
+ .suspend = mwifiex_pcie_suspend,
+ .resume = mwifiex_pcie_resume,
+#endif
+};
+
+/*
+ * This function writes data into PCIE card register.
+ */
+static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
+{
+ struct pcie_service_card *card = adapter->card;
+
+ iowrite32(data, card->pci_mmap1 + reg);
+
+ return 0;
+}
+
+/*
+ * This function reads data from PCIE card register.
+ */
+static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
+{
+ struct pcie_service_card *card = adapter->card;
+
+ *data = ioread32(card->pci_mmap1 + reg);
+
+ return 0;
+}
+
+/*
+ * This function wakes up the card.
+ *
+ * A host power up command is written to the card configuration
+ * register to wake up the card.
+ */
+static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
+{
+ int i = 0;
+
+ while (mwifiex_pcie_ok_to_access_hw(adapter)) {
+ i++;
+ udelay(10);
+ /* 50ms max wait */
+ if (i == 50000)
+ break;
+ }
+
+ dev_dbg(adapter->dev, "event: Wakeup device...\n");
+
+ /* Enable interrupts or any chip access will wakeup device */
+ if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, HOST_INTR_MASK)) {
+ dev_warn(adapter->dev, "Enable host interrupt failed\n");
+ return -1;
+ }
+
+ dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n");
+ adapter->ps_state = PS_STATE_AWAKE;
+
+ return 0;
+}
+
+/*
+ * This function is called after the card has woken up.
+ *
+ * The card configuration register is reset.
+ */
+static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
+{
+ dev_dbg(adapter->dev, "cmd: Wakeup device completed\n");
+
+ return 0;
+}
+
+/*
+ * This function disables the host interrupt.
+ *
+ * The host interrupt mask is read, the disable bit is reset and
+ * written back to the card host interrupt mask register.
+ */
+static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
+{
+ if (mwifiex_pcie_ok_to_access_hw(adapter)) {
+ if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
+ 0x00000000)) {
+ dev_warn(adapter->dev, "Disable host interrupt failed\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * This function enables the host interrupt.
+ *
+ * The host interrupt enable mask is written to the card
+ * host interrupt mask register.
+ */
+static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
+{
+ if (mwifiex_pcie_ok_to_access_hw(adapter)) {
+ /* Simply write the mask to the register */
+ if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
+ HOST_INTR_MASK)) {
+ dev_warn(adapter->dev, "Enable host interrupt failed\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * This function creates buffer descriptor ring for TX
+ */
+static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ struct sk_buff *skb;
+ int i;
+ phys_addr_t *buf_pa;
+
+ /*
+ * driver maintaines the write pointer and firmware maintaines the read
+ * pointer. The write pointer starts at 0 (zero) while the read pointer
+ * starts at zero with rollover bit set
+ */
+ card->txbd_wrptr = 0;
+ card->txbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND;
+
+ /* allocate shared memory for the BD ring and divide the same in to
+ several descriptors */
+ card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
+ MWIFIEX_MAX_TXRX_BD;
+ dev_dbg(adapter->dev, "info: txbd_ring: Allocating %d bytes\n",
+ card->txbd_ring_size);
+ card->txbd_ring_vbase = kzalloc(card->txbd_ring_size, GFP_KERNEL);
+ if (!card->txbd_ring_vbase) {
+ dev_err(adapter->dev, "Unable to allocate buffer for txbd ring.\n");
+ kfree(card->txbd_ring_vbase);
+ return -1;
+ }
+ card->txbd_ring_pbase = virt_to_phys(card->txbd_ring_vbase);
+
+ dev_dbg(adapter->dev, "info: txbd_ring - base: %p, pbase: %#x:%x,"
+ "len: %x\n", card->txbd_ring_vbase,
+ (u32)card->txbd_ring_pbase,
+ (u32)((u64)card->txbd_ring_pbase >> 32),
+ card->txbd_ring_size);
+
+ for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+ card->txbd_ring[i] = (struct mwifiex_pcie_buf_desc *)
+ (card->txbd_ring_vbase +
+ (sizeof(struct mwifiex_pcie_buf_desc) * i));
+
+ /* Allocate buffer here so that firmware can DMA data from it */
+ skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE);
+ if (!skb) {
+ dev_err(adapter->dev, "Unable to allocate skb for TX ring.\n");
+ kfree(card->txbd_ring_vbase);
+ return -ENOMEM;
+ }
+ buf_pa = mwifiex_update_sk_buff_pa(skb);
+
+ skb_put(skb, MWIFIEX_RX_DATA_BUF_SIZE);
+ dev_dbg(adapter->dev, "info: TX ring: add new skb base: %p, "
+ "buf_base: %p, buf_pbase: %#x:%x, "
+ "buf_len: %#x\n", skb, skb->data,
+ (u32)*buf_pa, (u32)(((u64)*buf_pa >> 32)),
+ skb->len);
+
+ card->tx_buf_list[i] = skb;
+ card->txbd_ring[i]->paddr = *buf_pa;
+ card->txbd_ring[i]->len = (u16)skb->len;
+ card->txbd_ring[i]->flags = 0;
+ }
+
+ return 0;
+}
+
+static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ int i;
+
+ for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+ if (card->tx_buf_list[i])
+ dev_kfree_skb_any(card->tx_buf_list[i]);
+ card->tx_buf_list[i] = NULL;
+ card->txbd_ring[i]->paddr = 0;
+ card->txbd_ring[i]->len = 0;
+ card->txbd_ring[i]->flags = 0;
+ card->txbd_ring[i] = NULL;
+ }
+
+ kfree(card->txbd_ring_vbase);
+ card->txbd_ring_size = 0;
+ card->txbd_wrptr = 0;
+ card->txbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND;
+ card->txbd_ring_vbase = NULL;
+
+ return 0;
+}
+
+/*
+ * This function creates buffer descriptor ring for RX
+ */
+static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ struct sk_buff *skb;
+ int i;
+ phys_addr_t *buf_pa;
+
+ /*
+ * driver maintaines the read pointer and firmware maintaines the write
+ * pointer. The write pointer starts at 0 (zero) while the read pointer
+ * starts at zero with rollover bit set
+ */
+ card->rxbd_wrptr = 0;
+ card->rxbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND;
+
+ card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
+ MWIFIEX_MAX_TXRX_BD;
+ dev_dbg(adapter->dev, "info: rxbd_ring: Allocating %d bytes\n",
+ card->rxbd_ring_size);
+ card->rxbd_ring_vbase = kzalloc(card->rxbd_ring_size, GFP_KERNEL);
+ if (!card->rxbd_ring_vbase) {
+ dev_err(adapter->dev, "Unable to allocate buffer for "
+ "rxbd_ring.\n");
+ return -1;
+ }
+ card->rxbd_ring_pbase = virt_to_phys(card->rxbd_ring_vbase);
+
+ dev_dbg(adapter->dev, "info: rxbd_ring - base: %p, pbase: %#x:%x,"
+ "len: %#x\n", card->rxbd_ring_vbase,
+ (u32)card->rxbd_ring_pbase,
+ (u32)((u64)card->rxbd_ring_pbase >> 32),
+ card->rxbd_ring_size);
+
+ for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+ card->rxbd_ring[i] = (struct mwifiex_pcie_buf_desc *)
+ (card->rxbd_ring_vbase +
+ (sizeof(struct mwifiex_pcie_buf_desc) * i));
+
+ /* Allocate skb here so that firmware can DMA data from it */
+ skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE);
+ if (!skb) {
+ dev_err(adapter->dev, "Unable to allocate skb for RX ring.\n");
+ kfree(card->rxbd_ring_vbase);
+ return -ENOMEM;
+ }
+ buf_pa = mwifiex_update_sk_buff_pa(skb);
+ skb_put(skb, MWIFIEX_RX_DATA_BUF_SIZE);
+
+ dev_dbg(adapter->dev, "info: RX ring: add new skb base: %p, "
+ "buf_base: %p, buf_pbase: %#x:%x, "
+ "buf_len: %#x\n", skb, skb->data,
+ (u32)*buf_pa, (u32)((u64)*buf_pa >> 32),
+ skb->len);
+
+ card->rx_buf_list[i] = skb;
+ card->rxbd_ring[i]->paddr = *buf_pa;
+ card->rxbd_ring[i]->len = (u16)skb->len;
+ card->rxbd_ring[i]->flags = 0;
+ }
+
+ return 0;
+}
+
+/*
+ * This function deletes Buffer descriptor ring for RX
+ */
+static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ int i;
+
+ for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+ if (card->rx_buf_list[i])
+ dev_kfree_skb_any(card->rx_buf_list[i]);
+ card->rx_buf_list[i] = NULL;
+ card->rxbd_ring[i]->paddr = 0;
+ card->rxbd_ring[i]->len = 0;
+ card->rxbd_ring[i]->flags = 0;
+ card->rxbd_ring[i] = NULL;
+ }
+
+ kfree(card->rxbd_ring_vbase);
+ card->rxbd_ring_size = 0;
+ card->rxbd_wrptr = 0;
+ card->rxbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND;
+ card->rxbd_ring_vbase = NULL;
+
+ return 0;
+}
+
+/*
+ * This function creates buffer descriptor ring for Events
+ */
+static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ struct sk_buff *skb;
+ int i;
+ phys_addr_t *buf_pa;
+
+ /*
+ * driver maintaines the read pointer and firmware maintaines the write
+ * pointer. The write pointer starts at 0 (zero) while the read pointer
+ * starts at zero with rollover bit set
+ */
+ card->evtbd_wrptr = 0;
+ card->evtbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND;
+
+ card->evtbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
+ MWIFIEX_MAX_EVT_BD;
+ dev_dbg(adapter->dev, "info: evtbd_ring: Allocating %d bytes\n",
+ card->evtbd_ring_size);
+ card->evtbd_ring_vbase = kzalloc(card->evtbd_ring_size, GFP_KERNEL);
+ if (!card->evtbd_ring_vbase) {
+ dev_err(adapter->dev, "Unable to allocate buffer. "
+ "Terminating download\n");
+ return -1;
+ }
+ card->evtbd_ring_pbase = virt_to_phys(card->evtbd_ring_vbase);
+
+ dev_dbg(adapter->dev, "info: CMDRSP/EVT bd_ring - base: %p, "
+ "pbase: %#x:%x, len: %#x\n", card->evtbd_ring_vbase,
+ (u32)card->evtbd_ring_pbase,
+ (u32)((u64)card->evtbd_ring_pbase >> 32),
+ card->evtbd_ring_size);
+
+ for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
+ card->evtbd_ring[i] = (struct mwifiex_pcie_buf_desc *)
+ (card->evtbd_ring_vbase +
+ (sizeof(struct mwifiex_pcie_buf_desc) * i));
+
+ /* Allocate skb here so that firmware can DMA data from it */
+ skb = dev_alloc_skb(MAX_EVENT_SIZE);
+ if (!skb) {
+ dev_err(adapter->dev, "Unable to allocate skb for EVENT buf.\n");
+ kfree(card->evtbd_ring_vbase);
+ return -ENOMEM;
+ }
+ buf_pa = mwifiex_update_sk_buff_pa(skb);
+ skb_put(skb, MAX_EVENT_SIZE);
+
+ dev_dbg(adapter->dev, "info: Evt ring: add new skb. base: %p, "
+ "buf_base: %p, buf_pbase: %#x:%x, "
+ "buf_len: %#x\n", skb, skb->data,
+ (u32)*buf_pa, (u32)((u64)*buf_pa >> 32),
+ skb->len);
+
+ card->evt_buf_list[i] = skb;
+ card->evtbd_ring[i]->paddr = *buf_pa;
+ card->evtbd_ring[i]->len = (u16)skb->len;
+ card->evtbd_ring[i]->flags = 0;
+ }
+
+ return 0;
+}
+
+/*
+ * This function deletes Buffer descriptor ring for Events
+ */
+static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ int i;
+
+ for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
+ if (card->evt_buf_list[i])
+ dev_kfree_skb_any(card->evt_buf_list[i]);
+ card->evt_buf_list[i] = NULL;
+ card->evtbd_ring[i]->paddr = 0;
+ card->evtbd_ring[i]->len = 0;
+ card->evtbd_ring[i]->flags = 0;
+ card->evtbd_ring[i] = NULL;
+ }
+
+ kfree(card->evtbd_ring_vbase);
+ card->evtbd_wrptr = 0;
+ card->evtbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND;
+ card->evtbd_ring_size = 0;
+ card->evtbd_ring_vbase = NULL;
+
+ return 0;
+}
+
+/*
+ * This function allocates a buffer for CMDRSP
+ */
+static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ struct sk_buff *skb;
+
+ /* Allocate memory for receiving command response data */
+ skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
+ if (!skb) {
+ dev_err(adapter->dev, "Unable to allocate skb for command "
+ "response data.\n");
+ return -ENOMEM;
+ }
+ mwifiex_update_sk_buff_pa(skb);
+ skb_put(skb, MWIFIEX_UPLD_SIZE);
+ card->cmdrsp_buf = skb;
+
+ skb = NULL;
+ /* Allocate memory for sending command to firmware */
+ skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER);
+ if (!skb) {
+ dev_err(adapter->dev, "Unable to allocate skb for command "
+ "data.\n");
+ return -ENOMEM;
+ }
+ mwifiex_update_sk_buff_pa(skb);
+ skb_put(skb, MWIFIEX_SIZE_OF_CMD_BUFFER);
+ card->cmd_buf = skb;
+
+ return 0;
+}
+
+/*
+ * This function deletes a buffer for CMDRSP
+ */
+static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card;
+
+ if (!adapter)
+ return 0;
+
+ card = adapter->card;
+
+ if (card && card->cmdrsp_buf)
+ dev_kfree_skb_any(card->cmdrsp_buf);
+
+ if (card && card->cmd_buf)
+ dev_kfree_skb_any(card->cmd_buf);
+
+ return 0;
+}
+
+/*
+ * This function allocates a buffer for sleep cookie
+ */
+static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
+{
+ struct sk_buff *skb;
+ struct pcie_service_card *card = adapter->card;
+
+ /* Allocate memory for sleep cookie */
+ skb = dev_alloc_skb(sizeof(u32));
+ if (!skb) {
+ dev_err(adapter->dev, "Unable to allocate skb for sleep "
+ "cookie!\n");
+ return -ENOMEM;
+ }
+ mwifiex_update_sk_buff_pa(skb);
+ skb_put(skb, sizeof(u32));
+
+ /* Init val of Sleep Cookie */
+ *(u32 *)skb->data = FW_AWAKE_COOKIE;
+
+ dev_dbg(adapter->dev, "alloc_scook: sleep cookie=0x%x\n",
+ *((u32 *)skb->data));
+
+ /* Save the sleep cookie */
+ card->sleep_cookie = skb;
+
+ return 0;
+}
+
+/*
+ * This function deletes buffer for sleep cookie
+ */
+static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card;
+
+ if (!adapter)
+ return 0;
+
+ card = adapter->card;
+
+ if (card && card->sleep_cookie) {
+ dev_kfree_skb_any(card->sleep_cookie);
+ card->sleep_cookie = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * This function sends data buffer to device
+ */
+static int
+mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb)
+{
+ struct pcie_service_card *card = adapter->card;
+ u32 wrindx, rdptr;
+ phys_addr_t *buf_pa;
+ __le16 *tmp;
+
+ if (!mwifiex_pcie_ok_to_access_hw(adapter))
+ mwifiex_pm_wakeup_card(adapter);
+
+ /* Read the TX ring read pointer set by firmware */
+ if (mwifiex_read_reg(adapter, REG_TXBD_RDPTR, &rdptr)) {
+ dev_err(adapter->dev, "SEND DATA: failed to read "
+ "REG_TXBD_RDPTR\n");
+ return -1;
+ }
+
+ wrindx = card->txbd_wrptr & MWIFIEX_TXBD_MASK;
+
+ dev_dbg(adapter->dev, "info: SEND DATA: <Rd: %#x, Wr: %#x>\n", rdptr,
+ card->txbd_wrptr);
+ if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) !=
+ (rdptr & MWIFIEX_TXBD_MASK)) ||
+ ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) !=
+ (rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) {
+ struct sk_buff *skb_data;
+ u8 *payload;
+
+ adapter->data_sent = true;
+ skb_data = card->tx_buf_list[wrindx];
+ memcpy(skb_data->data, skb->data, skb->len);
+ payload = skb_data->data;
+ tmp = (__le16 *)&payload[0];
+ *tmp = cpu_to_le16((u16)skb->len);
+ tmp = (__le16 *)&payload[2];
+ *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA);
+ skb_put(skb_data, MWIFIEX_RX_DATA_BUF_SIZE - skb_data->len);
+ skb_trim(skb_data, skb->len);
+ buf_pa = MWIFIEX_SKB_PACB(skb_data);
+ card->txbd_ring[wrindx]->paddr = *buf_pa;
+ card->txbd_ring[wrindx]->len = (u16)skb_data->len;
+ card->txbd_ring[wrindx]->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
+ MWIFIEX_BD_FLAG_LAST_DESC;
+
+ if ((++card->txbd_wrptr & MWIFIEX_TXBD_MASK) ==
+ MWIFIEX_MAX_TXRX_BD)
+ card->txbd_wrptr = ((card->txbd_wrptr &
+ MWIFIEX_BD_FLAG_ROLLOVER_IND) ^
+ MWIFIEX_BD_FLAG_ROLLOVER_IND);
+
+ /* Write the TX ring write pointer in to REG_TXBD_WRPTR */
+ if (mwifiex_write_reg(adapter, REG_TXBD_WRPTR,
+ card->txbd_wrptr)) {
+ dev_err(adapter->dev, "SEND DATA: failed to write "
+ "REG_TXBD_WRPTR\n");
+ return 0;
+ }
+
+ /* Send the TX ready interrupt */
+ if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+ CPU_INTR_DNLD_RDY)) {
+ dev_err(adapter->dev, "SEND DATA: failed to assert "
+ "door-bell interrupt.\n");
+ return -1;
+ }
+ dev_dbg(adapter->dev, "info: SEND DATA: Updated <Rd: %#x, Wr: "
+ "%#x> and sent packet to firmware "
+ "successfully\n", rdptr,
+ card->txbd_wrptr);
+ } else {
+ dev_dbg(adapter->dev, "info: TX Ring full, can't send anymore "
+ "packets to firmware\n");
+ adapter->data_sent = true;
+ /* Send the TX ready interrupt */
+ if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+ CPU_INTR_DNLD_RDY))
+ dev_err(adapter->dev, "SEND DATA: failed to assert "
+ "door-bell interrupt\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+/*
+ * This function handles received buffer ring and
+ * dispatches packets to upper
+ */
+static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ u32 wrptr, rd_index;
+ int ret = 0;
+ struct sk_buff *skb_tmp = NULL;
+
+ /* Read the RX ring Write pointer set by firmware */
+ if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) {
+ dev_err(adapter->dev, "RECV DATA: failed to read "
+ "REG_TXBD_RDPTR\n");
+ ret = -1;
+ goto done;
+ }
+
+ while (((wrptr & MWIFIEX_RXBD_MASK) !=
+ (card->rxbd_rdptr & MWIFIEX_RXBD_MASK)) ||
+ ((wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) ==
+ (card->rxbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) {
+ struct sk_buff *skb_data;
+ u16 rx_len;
+
+ rd_index = card->rxbd_rdptr & MWIFIEX_RXBD_MASK;
+ skb_data = card->rx_buf_list[rd_index];
+
+ /* Get data length from interface header -
+ first byte is len, second byte is type */
+ rx_len = *((u16 *)skb_data->data);
+ dev_dbg(adapter->dev, "info: RECV DATA: Rd=%#x, Wr=%#x, "
+ "Len=%d\n", card->rxbd_rdptr, wrptr, rx_len);
+ skb_tmp = dev_alloc_skb(rx_len);
+ if (!skb_tmp) {
+ dev_dbg(adapter->dev, "info: Failed to alloc skb "
+ "for RX\n");
+ ret = -EBUSY;
+ goto done;
+ }
+
+ skb_put(skb_tmp, rx_len);
+
+ memcpy(skb_tmp->data, skb_data->data + INTF_HEADER_LEN, rx_len);
+ if ((++card->rxbd_rdptr & MWIFIEX_RXBD_MASK) ==
+ MWIFIEX_MAX_TXRX_BD) {
+ card->rxbd_rdptr = ((card->rxbd_rdptr &
+ MWIFIEX_BD_FLAG_ROLLOVER_IND) ^
+ MWIFIEX_BD_FLAG_ROLLOVER_IND);
+ }
+ dev_dbg(adapter->dev, "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
+ card->rxbd_rdptr, wrptr);
+
+ /* Write the RX ring read pointer in to REG_RXBD_RDPTR */
+ if (mwifiex_write_reg(adapter, REG_RXBD_RDPTR,
+ card->rxbd_rdptr)) {
+ dev_err(adapter->dev, "RECV DATA: failed to "
+ "write REG_RXBD_RDPTR\n");
+ ret = -1;
+ goto done;
+ }
+
+ /* Read the RX ring Write pointer set by firmware */
+ if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) {
+ dev_err(adapter->dev, "RECV DATA: failed to read "
+ "REG_TXBD_RDPTR\n");
+ ret = -1;
+ goto done;
+ }
+ dev_dbg(adapter->dev, "info: RECV DATA: Received packet from "
+ "firmware successfully\n");
+ mwifiex_handle_rx_packet(adapter, skb_tmp);
+ }
+
+done:
+ if (ret && skb_tmp)
+ dev_kfree_skb_any(skb_tmp);
+ return ret;
+}
+
+/*
+ * This function downloads the boot command to device
+ */
+static int
+mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
+{
+ phys_addr_t *buf_pa = MWIFIEX_SKB_PACB(skb);
+
+ if (!(skb->data && skb->len && *buf_pa)) {
+ dev_err(adapter->dev, "Invalid parameter in %s <%p, %#x:%x, "
+ "%x>\n", __func__, skb->data, skb->len,
+ (u32)*buf_pa, (u32)((u64)*buf_pa >> 32));
+ return -1;
+ }
+
+ /* Write the lower 32bits of the physical address to scratch
+ * register 0 */
+ if (mwifiex_write_reg(adapter, PCIE_SCRATCH_0_REG, (u32)*buf_pa)) {
+ dev_err(adapter->dev, "%s: failed to write download command "
+ "to boot code.\n", __func__);
+ return -1;
+ }
+
+ /* Write the upper 32bits of the physical address to scratch
+ * register 1 */
+ if (mwifiex_write_reg(adapter, PCIE_SCRATCH_1_REG,
+ (u32)((u64)*buf_pa >> 32))) {
+ dev_err(adapter->dev, "%s: failed to write download command "
+ "to boot code.\n", __func__);
+ return -1;
+ }
+
+ /* Write the command length to scratch register 2 */
+ if (mwifiex_write_reg(adapter, PCIE_SCRATCH_2_REG, skb->len)) {
+ dev_err(adapter->dev, "%s: failed to write command length to "
+ "scratch register 2\n", __func__);
+ return -1;
+ }
+
+ /* Ring the door bell */
+ if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+ CPU_INTR_DOOR_BELL)) {
+ dev_err(adapter->dev, "%s: failed to assert door-bell "
+ "interrupt.\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * This function downloads commands to the device
+ */
+static int
+mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
+{
+ struct pcie_service_card *card = adapter->card;
+ int ret = 0;
+ phys_addr_t *cmd_buf_pa;
+ phys_addr_t *cmdrsp_buf_pa;
+
+ if (!(skb->data && skb->len)) {
+ dev_err(adapter->dev, "Invalid parameter in %s <%p, %#x>\n",
+ __func__, skb->data, skb->len);
+ return -1;
+ }
+
+ /* Make sure a command response buffer is available */
+ if (!card->cmdrsp_buf) {
+ dev_err(adapter->dev, "No response buffer available, send "
+ "command failed\n");
+ return -EBUSY;
+ }
+
+ /* Make sure a command buffer is available */
+ if (!card->cmd_buf) {
+ dev_err(adapter->dev, "Command buffer not available\n");
+ return -EBUSY;
+ }
+
+ adapter->cmd_sent = true;
+ /* Copy the given skb in to DMA accessable shared buffer */
+ skb_put(card->cmd_buf, MWIFIEX_SIZE_OF_CMD_BUFFER - card->cmd_buf->len);
+ skb_trim(card->cmd_buf, skb->len);
+ memcpy(card->cmd_buf->data, skb->data, skb->len);
+
+ /* To send a command, the driver will:
+ 1. Write the 64bit physical address of the data buffer to
+ SCRATCH1 + SCRATCH0
+ 2. Ring the door bell (i.e. set the door bell interrupt)
+
+ In response to door bell interrupt, the firmware will perform
+ the DMA of the command packet (first header to obtain the total
+ length and then rest of the command).
+ */
+
+ if (card->cmdrsp_buf) {
+ cmdrsp_buf_pa = MWIFIEX_SKB_PACB(card->cmdrsp_buf);
+ /* Write the lower 32bits of the cmdrsp buffer physical
+ address */
+ if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO,
+ (u32)*cmdrsp_buf_pa)) {
+ dev_err(adapter->dev, "Failed to write download command to boot code.\n");
+ ret = -1;
+ goto done;
+ }
+ /* Write the upper 32bits of the cmdrsp buffer physical
+ address */
+ if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI,
+ (u32)((u64)*cmdrsp_buf_pa >> 32))) {
+ dev_err(adapter->dev, "Failed to write download command"
+ " to boot code.\n");
+ ret = -1;
+ goto done;
+ }
+ }
+
+ cmd_buf_pa = MWIFIEX_SKB_PACB(card->cmd_buf);
+ /* Write the lower 32bits of the physical address to REG_CMD_ADDR_LO */
+ if (mwifiex_write_reg(adapter, REG_CMD_ADDR_LO,
+ (u32)*cmd_buf_pa)) {
+ dev_err(adapter->dev, "Failed to write download command "
+ "to boot code.\n");
+ ret = -1;
+ goto done;
+ }
+ /* Write the upper 32bits of the physical address to REG_CMD_ADDR_HI */
+ if (mwifiex_write_reg(adapter, REG_CMD_ADDR_HI,
+ (u32)((u64)*cmd_buf_pa >> 32))) {
+ dev_err(adapter->dev, "Failed to write download command "
+ "to boot code.\n");
+ ret = -1;
+ goto done;
+ }
+
+ /* Write the command length to REG_CMD_SIZE */
+ if (mwifiex_write_reg(adapter, REG_CMD_SIZE,
+ card->cmd_buf->len)) {
+ dev_err(adapter->dev, "Failed to write command length to "
+ "REG_CMD_SIZE\n");
+ ret = -1;
+ goto done;
+ }
+
+ /* Ring the door bell */
+ if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+ CPU_INTR_DOOR_BELL)) {
+ dev_err(adapter->dev, "Failed to assert door-bell "
+ "interrupt.\n");
+ ret = -1;
+ goto done;
+ }
+
+done:
+ if (ret)
+ adapter->cmd_sent = false;
+
+ return 0;
+}
+
+/*
+ * This function handles command complete interrupt
+ */
+static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ int count = 0;
+
+ dev_dbg(adapter->dev, "info: Rx CMD Response\n");
+
+ if (!adapter->curr_cmd) {
+ skb_pull(card->cmdrsp_buf, INTF_HEADER_LEN);
+ if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
+ mwifiex_process_sleep_confirm_resp(adapter,
+ card->cmdrsp_buf->data,
+ card->cmdrsp_buf->len);
+ while (mwifiex_pcie_ok_to_access_hw(adapter) &&
+ (count++ < 10))
+ udelay(50);
+ } else {
+ dev_err(adapter->dev, "There is no command but "
+ "got cmdrsp\n");
+ }
+ memcpy(adapter->upld_buf, card->cmdrsp_buf->data,
+ min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER,
+ card->cmdrsp_buf->len));
+ skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
+ } else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
+ skb_pull(card->cmdrsp_buf, INTF_HEADER_LEN);
+ adapter->curr_cmd->resp_skb = card->cmdrsp_buf;
+ adapter->cmd_resp_received = true;
+ /* Take the pointer and set it to CMD node and will
+ return in the response complete callback */
+ card->cmdrsp_buf = NULL;
+
+ /* Clear the cmd-rsp buffer address in scratch registers. This
+ will prevent firmware from writing to the same response
+ buffer again. */
+ if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO, 0)) {
+ dev_err(adapter->dev, "cmd_done: failed to clear "
+ "cmd_rsp address.\n");
+ return -1;
+ }
+ /* Write the upper 32bits of the cmdrsp buffer physical
+ address */
+ if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI, 0)) {
+ dev_err(adapter->dev, "cmd_done: failed to clear "
+ "cmd_rsp address.\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Command Response processing complete handler
+ */
+static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
+ struct sk_buff *skb)
+{
+ struct pcie_service_card *card = adapter->card;
+
+ if (skb) {
+ card->cmdrsp_buf = skb;
+ skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
+ }
+
+ return 0;
+}
+
+/*
+ * This function handles firmware event ready interrupt
+ */
+static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
+ u32 wrptr, event;
+
+ if (adapter->event_received) {
+ dev_dbg(adapter->dev, "info: Event being processed, "\
+ "do not process this interrupt just yet\n");
+ return 0;
+ }
+
+ if (rdptr >= MWIFIEX_MAX_EVT_BD) {
+ dev_dbg(adapter->dev, "info: Invalid read pointer...\n");
+ return -1;
+ }
+
+ /* Read the event ring write pointer set by firmware */
+ if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) {
+ dev_err(adapter->dev, "EventReady: failed to read REG_EVTBD_WRPTR\n");
+ return -1;
+ }
+
+ dev_dbg(adapter->dev, "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
+ card->evtbd_rdptr, wrptr);
+ if (((wrptr & MWIFIEX_EVTBD_MASK) !=
+ (card->evtbd_rdptr & MWIFIEX_EVTBD_MASK)) ||
+ ((wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) ==
+ (card->evtbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) {
+ struct sk_buff *skb_cmd;
+ __le16 data_len = 0;
+ u16 evt_len;
+
+ dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr);
+ skb_cmd = card->evt_buf_list[rdptr];
+ /* Take the pointer and set it to event pointer in adapter
+ and will return back after event handling callback */
+ card->evt_buf_list[rdptr] = NULL;
+ card->evtbd_ring[rdptr]->paddr = 0;
+ card->evtbd_ring[rdptr]->len = 0;
+ card->evtbd_ring[rdptr]->flags = 0;
+
+ event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN];
+ adapter->event_cause = event;
+ /* The first 4bytes will be the event transfer header
+ len is 2 bytes followed by type which is 2 bytes */
+ memcpy(&data_len, skb_cmd->data, sizeof(__le16));
+ evt_len = le16_to_cpu(data_len);
+
+ skb_pull(skb_cmd, INTF_HEADER_LEN);
+ dev_dbg(adapter->dev, "info: Event length: %d\n", evt_len);
+
+ if ((evt_len > 0) && (evt_len < MAX_EVENT_SIZE))
+ memcpy(adapter->event_body, skb_cmd->data +
+ MWIFIEX_EVENT_HEADER_LEN, evt_len -
+ MWIFIEX_EVENT_HEADER_LEN);
+
+ adapter->event_received = true;
+ adapter->event_skb = skb_cmd;
+
+ /* Do not update the event read pointer here, wait till the
+ buffer is released. This is just to make things simpler,
+ we need to find a better method of managing these buffers.
+ */
+ }
+
+ return 0;
+}
+
+/*
+ * Event processing complete handler
+ */
+static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
+ struct sk_buff *skb)
+{
+ struct pcie_service_card *card = adapter->card;
+ int ret = 0;
+ u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
+ u32 wrptr;
+ phys_addr_t *buf_pa;
+
+ if (!skb)
+ return 0;
+
+ if (rdptr >= MWIFIEX_MAX_EVT_BD)
+ dev_err(adapter->dev, "event_complete: Invalid rdptr 0x%x\n",
+ rdptr);
+
+ /* Read the event ring write pointer set by firmware */
+ if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) {
+ dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_WRPTR\n");
+ ret = -1;
+ goto done;
+ }
+
+ if (!card->evt_buf_list[rdptr]) {
+ skb_push(skb, INTF_HEADER_LEN);
+ card->evt_buf_list[rdptr] = skb;
+ buf_pa = MWIFIEX_SKB_PACB(skb);
+ card->evtbd_ring[rdptr]->paddr = *buf_pa;
+ card->evtbd_ring[rdptr]->len = (u16)skb->len;
+ card->evtbd_ring[rdptr]->flags = 0;
+ skb = NULL;
+ } else {
+ dev_dbg(adapter->dev, "info: ERROR: Buffer is still valid at "
+ "index %d, <%p, %p>\n", rdptr,
+ card->evt_buf_list[rdptr], skb);
+ }
+
+ if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
+ card->evtbd_rdptr = ((card->evtbd_rdptr &
+ MWIFIEX_BD_FLAG_ROLLOVER_IND) ^
+ MWIFIEX_BD_FLAG_ROLLOVER_IND);
+ }
+
+ dev_dbg(adapter->dev, "info: Updated <Rd: 0x%x, Wr: 0x%x>",
+ card->evtbd_rdptr, wrptr);
+
+ /* Write the event ring read pointer in to REG_EVTBD_RDPTR */
+ if (mwifiex_write_reg(adapter, REG_EVTBD_RDPTR, card->evtbd_rdptr)) {
+ dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_RDPTR\n");
+ ret = -1;
+ goto done;
+ }
+
+done:
+ /* Free the buffer for failure case */
+ if (ret && skb)
+ dev_kfree_skb_any(skb);
+
+ dev_dbg(adapter->dev, "info: Check Events Again\n");
+ ret = mwifiex_pcie_process_event_ready(adapter);
+
+ return ret;
+}
+
+/*
+ * This function downloads the firmware to the card.
+ *
+ * Firmware is downloaded to the card in blocks. Every block download
+ * is tested for CRC errors, and retried a number of times before
+ * returning failure.
+ */
+static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
+ struct mwifiex_fw_image *fw)
+{
+ int ret;
+ u8 *firmware = fw->fw_buf;
+ u32 firmware_len = fw->fw_len;
+ u32 offset = 0;
+ struct sk_buff *skb;
+ u32 txlen, tx_blocks = 0, tries, len;
+ u32 block_retry_cnt = 0;
+
+ if (!adapter) {
+ pr_err("adapter structure is not valid\n");
+ return -1;
+ }
+
+ if (!firmware || !firmware_len) {
+ dev_err(adapter->dev, "No firmware image found! "
+ "Terminating download\n");
+ return -1;
+ }
+
+ dev_dbg(adapter->dev, "info: Downloading FW image (%d bytes)\n",
+ firmware_len);
+
+ if (mwifiex_pcie_disable_host_int(adapter)) {
+ dev_err(adapter->dev, "%s: Disabling interrupts"
+ " failed.\n", __func__);
+ return -1;
+ }
+
+ skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
+ if (!skb) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ mwifiex_update_sk_buff_pa(skb);
+
+ /* Perform firmware data transfer */
+ do {
+ u32 ireg_intr = 0;
+
+ /* More data? */
+ if (offset >= firmware_len)
+ break;
+
+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+ ret = mwifiex_read_reg(adapter, PCIE_SCRATCH_2_REG,
+ &len);
+ if (ret) {
+ dev_warn(adapter->dev, "Failed reading length from boot code\n");
+ goto done;
+ }
+ if (len)
+ break;
+ udelay(10);
+ }
+
+ if (!len) {
+ break;
+ } else if (len > MWIFIEX_UPLD_SIZE) {
+ pr_err("FW download failure @ %d, invalid length %d\n",
+ offset, len);
+ ret = -1;
+ goto done;
+ }
+
+ txlen = len;
+
+ if (len & BIT(0)) {
+ block_retry_cnt++;
+ if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
+ pr_err("FW download failure @ %d, over max "
+ "retry count\n", offset);
+ ret = -1;
+ goto done;
+ }
+ dev_err(adapter->dev, "FW CRC error indicated by the "
+ "helper: len = 0x%04X, txlen = "
+ "%d\n", len, txlen);
+ len &= ~BIT(0);
+ /* Setting this to 0 to resend from same offset */
+ txlen = 0;
+ } else {
+ block_retry_cnt = 0;
+ /* Set blocksize to transfer - checking for
+ last block */
+ if (firmware_len - offset < txlen)
+ txlen = firmware_len - offset;
+
+ dev_dbg(adapter->dev, ".");
+
+ tx_blocks =
+ (txlen + MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD - 1) /
+ MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD;
+
+ /* Copy payload to buffer */
+ memmove(skb->data, &firmware[offset], txlen);
+ }
+
+ skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
+ skb_trim(skb, tx_blocks * MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD);
+
+ /* Send the boot command to device */
+ if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
+ dev_err(adapter->dev, "Failed to send firmware download command\n");
+ ret = -1;
+ goto done;
+ }
+ /* Wait for the command done interrupt */
+ do {
+ if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
+ &ireg_intr)) {
+ dev_err(adapter->dev, "%s: Failed to read "
+ "interrupt status during "
+ "fw dnld.\n", __func__);
+ ret = -1;
+ goto done;
+ }
+ } while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
+ CPU_INTR_DOOR_BELL);
+ offset += txlen;
+ } while (true);
+
+ dev_dbg(adapter->dev, "info:\nFW download over, size %d bytes\n",
+ offset);
+
+ ret = 0;
+
+done:
+ dev_kfree_skb_any(skb);
+ return ret;
+}
+
+/*
+ * This function checks the firmware status in card.
+ *
+ * The winner interface is also determined by this function.
+ */
+static int
+mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
+{
+ int ret = 0;
+ u32 firmware_stat, winner_status;
+ u32 tries;
+
+ /* Mask spurios interrupts */
+ if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
+ HOST_INTR_MASK)) {
+ dev_warn(adapter->dev, "Write register failed\n");
+ return -1;
+ }
+
+ dev_dbg(adapter->dev, "Setting driver ready signature\n");
+ if (mwifiex_write_reg(adapter, REG_DRV_READY, FIRMWARE_READY_PCIE)) {
+ dev_err(adapter->dev, "Failed to write driver ready signature\n");
+ return -1;
+ }
+
+ /* Wait for firmware initialization event */
+ for (tries = 0; tries < poll_num; tries++) {
+ if (mwifiex_read_reg(adapter, PCIE_SCRATCH_3_REG,
+ &firmware_stat))
+ ret = -1;
+ else
+ ret = 0;
+ if (ret)
+ continue;
+ if (firmware_stat == FIRMWARE_READY_PCIE) {
+ ret = 0;
+ break;
+ } else {
+ mdelay(100);
+ ret = -1;
+ }
+ }
+
+ if (ret) {
+ if (mwifiex_read_reg(adapter, PCIE_SCRATCH_3_REG,
+ &winner_status))
+ ret = -1;
+ else if (!winner_status) {
+ dev_err(adapter->dev, "PCI-E is the winner\n");
+ adapter->winner = 1;
+ ret = -1;
+ } else {
+ dev_err(adapter->dev, "PCI-E is not the winner <%#x, %d>, exit download\n",
+ ret, adapter->winner);
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * This function reads the interrupt status from card.
+ */
+static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
+{
+ u32 pcie_ireg;
+ unsigned long flags;
+
+ if (!mwifiex_pcie_ok_to_access_hw(adapter))
+ return;
+
+ if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, &pcie_ireg)) {
+ dev_warn(adapter->dev, "Read register failed\n");
+ return;
+ }
+
+ if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+
+ mwifiex_pcie_disable_host_int(adapter);
+
+ /* Clear the pending interrupts */
+ if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS,
+ ~pcie_ireg)) {
+ dev_warn(adapter->dev, "Write register failed\n");
+ return;
+ }
+ spin_lock_irqsave(&adapter->int_lock, flags);
+ adapter->int_status |= pcie_ireg;
+ spin_unlock_irqrestore(&adapter->int_lock, flags);
+
+ if (pcie_ireg & HOST_INTR_CMD_DONE) {
+ if ((adapter->ps_state == PS_STATE_SLEEP_CFM) ||
+ (adapter->ps_state == PS_STATE_SLEEP)) {
+ mwifiex_pcie_enable_host_int(adapter);
+ if (mwifiex_write_reg(adapter,
+ PCIE_CPU_INT_EVENT,
+ CPU_INTR_SLEEP_CFM_DONE)) {
+ dev_warn(adapter->dev, "Write register"
+ " failed\n");
+ return;
+
+ }
+ }
+ } else if (!adapter->pps_uapsd_mode &&
+ adapter->ps_state == PS_STATE_SLEEP) {
+ /* Potentially for PCIe we could get other
+ * interrupts like shared. Don't change power
+ * state until cookie is set */
+ if (mwifiex_pcie_ok_to_access_hw(adapter))
+ adapter->ps_state = PS_STATE_AWAKE;
+ }
+ }
+}
+
+/*
+ * Interrupt handler for PCIe root port
+ *
+ * This function reads the interrupt status from firmware and assigns
+ * the main process in workqueue which will handle the interrupt.
+ */
+static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
+{
+ struct pci_dev *pdev = (struct pci_dev *)context;
+ struct pcie_service_card *card;
+ struct mwifiex_adapter *adapter;
+
+ if (!pdev) {
+ pr_debug("info: %s: pdev is NULL\n", (u8 *)pdev);
+ goto exit;
+ }
+
+ card = (struct pcie_service_card *) pci_get_drvdata(pdev);
+ if (!card || !card->adapter) {
+ pr_debug("info: %s: card=%p adapter=%p\n", __func__, card,
+ card ? card->adapter : NULL);
+ goto exit;
+ }
+ adapter = card->adapter;
+
+ if (adapter->surprise_removed)
+ goto exit;
+
+ mwifiex_interrupt_status(adapter);
+ queue_work(adapter->workqueue, &adapter->main_work);
+
+exit:
+ return IRQ_HANDLED;
+}
+
+/*
+ * This function checks the current interrupt status.
+ *
+ * The following interrupts are checked and handled by this function -
+ * - Data sent
+ * - Command sent
+ * - Command received
+ * - Packets received
+ * - Events received
+ *
+ * In case of Rx packets received, the packets are uploaded from card to
+ * host and processed accordingly.
+ */
+static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
+{
+ int ret;
+ u32 pcie_ireg = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->int_lock, flags);
+ /* Clear out unused interrupts */
+ adapter->int_status &= HOST_INTR_MASK;
+ spin_unlock_irqrestore(&adapter->int_lock, flags);
+
+ while (adapter->int_status & HOST_INTR_MASK) {
+ if (adapter->int_status & HOST_INTR_DNLD_DONE) {
+ adapter->int_status &= ~HOST_INTR_DNLD_DONE;
+ if (adapter->data_sent) {
+ dev_dbg(adapter->dev, "info: DATA sent Interrupt\n");
+ adapter->data_sent = false;
+ }
+ }
+ if (adapter->int_status & HOST_INTR_UPLD_RDY) {
+ adapter->int_status &= ~HOST_INTR_UPLD_RDY;
+ dev_dbg(adapter->dev, "info: Rx DATA\n");
+ ret = mwifiex_pcie_process_recv_data(adapter);
+ if (ret)
+ return ret;
+ }
+ if (adapter->int_status & HOST_INTR_EVENT_RDY) {
+ adapter->int_status &= ~HOST_INTR_EVENT_RDY;
+ dev_dbg(adapter->dev, "info: Rx EVENT\n");
+ ret = mwifiex_pcie_process_event_ready(adapter);
+ if (ret)
+ return ret;
+ }
+
+ if (adapter->int_status & HOST_INTR_CMD_DONE) {
+ adapter->int_status &= ~HOST_INTR_CMD_DONE;
+ if (adapter->cmd_sent) {
+ dev_dbg(adapter->dev, "info: CMD sent Interrupt\n");
+ adapter->cmd_sent = false;
+ }
+ /* Handle command response */
+ ret = mwifiex_pcie_process_cmd_complete(adapter);
+ if (ret)
+ return ret;
+ }
+
+ if (mwifiex_pcie_ok_to_access_hw(adapter)) {
+ if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
+ &pcie_ireg)) {
+ dev_warn(adapter->dev, "Read register failed\n");
+ return -1;
+ }
+
+ if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+ if (mwifiex_write_reg(adapter,
+ PCIE_HOST_INT_STATUS, ~pcie_ireg)) {
+ dev_warn(adapter->dev, "Write register"
+ " failed\n");
+ return -1;
+ }
+ adapter->int_status |= pcie_ireg;
+ adapter->int_status &= HOST_INTR_MASK;
+ }
+
+ }
+ }
+ dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
+ adapter->cmd_sent, adapter->data_sent);
+ mwifiex_pcie_enable_host_int(adapter);
+
+ return 0;
+}
+
+/*
+ * This function downloads data from driver to card.
+ *
+ * Both commands and data packets are transferred to the card by this
+ * function.
+ *
+ * This function adds the PCIE specific header to the front of the buffer
+ * before transferring. The header contains the length of the packet and
+ * the type. The firmware handles the packets based upon this set type.
+ */
+static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
+ struct sk_buff *skb,
+ struct mwifiex_tx_param *tx_param)
+{
+ if (!adapter || !skb) {
+ dev_err(adapter->dev, "Invalid parameter in %s <%p, %p>\n",
+ __func__, adapter, skb);
+ return -1;
+ }
+
+ if (type == MWIFIEX_TYPE_DATA)
+ return mwifiex_pcie_send_data(adapter, skb);
+ else if (type == MWIFIEX_TYPE_CMD)
+ return mwifiex_pcie_send_cmd(adapter, skb);
+
+ return 0;
+}
+
+/*
+ * This function initializes the PCI-E host memory space, WCB rings, etc.
+ *
+ * The following initializations steps are followed -
+ * - Allocate TXBD ring buffers
+ * - Allocate RXBD ring buffers
+ * - Allocate event BD ring buffers
+ * - Allocate command response ring buffer
+ * - Allocate sleep cookie buffer
+ */
+static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ int ret;
+ struct pci_dev *pdev = card->dev;
+
+ pci_set_drvdata(pdev, card);
+
+ ret = pci_enable_device(pdev);
+ if (ret)
+ goto err_enable_dev;
+
+ pci_set_master(pdev);
+
+ dev_dbg(adapter->dev, "try set_consistent_dma_mask(32)\n");
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(adapter->dev, "set_dma_mask(32) failed\n");
+ goto err_set_dma_mask;
+ }
+
+ ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(adapter->dev, "set_consistent_dma_mask(64) failed\n");
+ goto err_set_dma_mask;
+ }
+
+ ret = pci_request_region(pdev, 0, DRV_NAME);
+ if (ret) {
+ dev_err(adapter->dev, "req_reg(0) error\n");
+ goto err_req_region0;
+ }
+ card->pci_mmap = pci_iomap(pdev, 0, 0);
+ if (!card->pci_mmap) {
+ dev_err(adapter->dev, "iomap(0) error\n");
+ goto err_iomap0;
+ }
+ ret = pci_request_region(pdev, 2, DRV_NAME);
+ if (ret) {
+ dev_err(adapter->dev, "req_reg(2) error\n");
+ goto err_req_region2;
+ }
+ card->pci_mmap1 = pci_iomap(pdev, 2, 0);
+ if (!card->pci_mmap1) {
+ dev_err(adapter->dev, "iomap(2) error\n");
+ goto err_iomap2;
+ }
+
+ dev_dbg(adapter->dev, "PCI memory map Virt0: %p PCI memory map Virt2: "
+ "%p\n", card->pci_mmap, card->pci_mmap1);
+
+ card->cmdrsp_buf = NULL;
+ ret = mwifiex_pcie_create_txbd_ring(adapter);
+ if (ret)
+ goto err_cre_txbd;
+ ret = mwifiex_pcie_create_rxbd_ring(adapter);
+ if (ret)
+ goto err_cre_rxbd;
+ ret = mwifiex_pcie_create_evtbd_ring(adapter);
+ if (ret)
+ goto err_cre_evtbd;
+ ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
+ if (ret)
+ goto err_alloc_cmdbuf;
+ ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
+ if (ret)
+ goto err_alloc_cookie;
+
+ return ret;
+
+err_alloc_cookie:
+ mwifiex_pcie_delete_cmdrsp_buf(adapter);
+err_alloc_cmdbuf:
+ mwifiex_pcie_delete_evtbd_ring(adapter);
+err_cre_evtbd:
+ mwifiex_pcie_delete_rxbd_ring(adapter);
+err_cre_rxbd:
+ mwifiex_pcie_delete_txbd_ring(adapter);
+err_cre_txbd:
+ pci_iounmap(pdev, card->pci_mmap1);
+err_iomap2:
+ pci_release_region(pdev, 2);
+err_req_region2:
+ pci_iounmap(pdev, card->pci_mmap);
+err_iomap0:
+ pci_release_region(pdev, 0);
+err_req_region0:
+err_set_dma_mask:
+ pci_disable_device(pdev);
+err_enable_dev:
+ pci_set_drvdata(pdev, NULL);
+ return ret;
+}
+
+/*
+ * This function cleans up the allocated card buffers.
+ *
+ * The following are freed by this function -
+ * - TXBD ring buffers
+ * - RXBD ring buffers
+ * - Event BD ring buffers
+ * - Command response ring buffer
+ * - Sleep cookie buffer
+ */
+static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ struct pci_dev *pdev = card->dev;
+
+ mwifiex_pcie_delete_sleep_cookie_buf(adapter);
+ mwifiex_pcie_delete_cmdrsp_buf(adapter);
+ mwifiex_pcie_delete_evtbd_ring(adapter);
+ mwifiex_pcie_delete_rxbd_ring(adapter);
+ mwifiex_pcie_delete_txbd_ring(adapter);
+ card->cmdrsp_buf = NULL;
+
+ dev_dbg(adapter->dev, "Clearing driver ready signature\n");
+ if (user_rmmod) {
+ if (mwifiex_write_reg(adapter, REG_DRV_READY, 0x00000000))
+ dev_err(adapter->dev, "Failed to write driver not-ready signature\n");
+ }
+
+ if (pdev) {
+ pci_iounmap(pdev, card->pci_mmap);
+ pci_iounmap(pdev, card->pci_mmap1);
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ }
+}
+
+/*
+ * This function registers the PCIE device.
+ *
+ * PCIE IRQ is claimed, block size is set and driver data is initialized.
+ */
+static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
+{
+ int ret;
+ struct pcie_service_card *card = adapter->card;
+ struct pci_dev *pdev = card->dev;
+
+ /* save adapter pointer in card */
+ card->adapter = adapter;
+
+ ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
+ "MRVL_PCIE", pdev);
+ if (ret) {
+ pr_err("request_irq failed: ret=%d\n", ret);
+ adapter->card = NULL;
+ return -1;
+ }
+
+ adapter->dev = &pdev->dev;
+ strcpy(adapter->fw_name, PCIE8766_DEFAULT_FW_NAME);
+
+ return 0;
+}
+
+/*
+ * This function unregisters the PCIE device.
+ *
+ * The PCIE IRQ is released, the function is disabled and driver
+ * data is set to null.
+ */
+static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+
+ if (card) {
+ dev_dbg(adapter->dev, "%s(): calling free_irq()\n", __func__);
+ free_irq(card->dev->irq, card->dev);
+ }
+}
+
+static struct mwifiex_if_ops pcie_ops = {
+ .init_if = mwifiex_pcie_init,
+ .cleanup_if = mwifiex_pcie_cleanup,
+ .check_fw_status = mwifiex_check_fw_status,
+ .prog_fw = mwifiex_prog_fw_w_helper,
+ .register_dev = mwifiex_register_dev,
+ .unregister_dev = mwifiex_unregister_dev,
+ .enable_int = mwifiex_pcie_enable_host_int,
+ .process_int_status = mwifiex_process_int_status,
+ .host_to_card = mwifiex_pcie_host_to_card,
+ .wakeup = mwifiex_pm_wakeup_card,
+ .wakeup_complete = mwifiex_pm_wakeup_card_complete,
+
+ /* PCIE specific */
+ .cmdrsp_complete = mwifiex_pcie_cmdrsp_complete,
+ .event_complete = mwifiex_pcie_event_complete,
+ .update_mp_end_port = NULL,
+ .cleanup_mpa_buf = NULL,
+};
+
+/*
+ * This function initializes the PCIE driver module.
+ *
+ * This initiates the semaphore and registers the device with
+ * PCIE bus.
+ */
+static int mwifiex_pcie_init_module(void)
+{
+ int ret;
+
+ pr_debug("Marvell 8766 PCIe Driver\n");
+
+ sema_init(&add_remove_card_sem, 1);
+
+ /* Clear the flag in case user removes the card. */
+ user_rmmod = 0;
+
+ ret = pci_register_driver(&mwifiex_pcie);
+ if (ret)
+ pr_err("Driver register failed!\n");
+ else
+ pr_debug("info: Driver registered successfully!\n");
+
+ return ret;
+}
+
+/*
+ * This function cleans up the PCIE driver.
+ *
+ * The following major steps are followed for cleanup -
+ * - Resume the device if its suspended
+ * - Disconnect the device if connected
+ * - Shutdown the firmware
+ * - Unregister the device from PCIE bus.
+ */
+static void mwifiex_pcie_cleanup_module(void)
+{
+ if (!down_interruptible(&add_remove_card_sem))
+ up(&add_remove_card_sem);
+
+ /* Set the flag as user is removing this module. */
+ user_rmmod = 1;
+
+ pci_unregister_driver(&mwifiex_pcie);
+}
+
+module_init(mwifiex_pcie_init_module);
+module_exit(mwifiex_pcie_cleanup_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION);
+MODULE_VERSION(PCIE_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE("mrvl/pcie8766_uapsta.bin");
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h
new file mode 100644
index 000000000000..445ff21772e2
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/pcie.h
@@ -0,0 +1,148 @@
+/* @file mwifiex_pcie.h
+ *
+ * @brief This file contains definitions for PCI-E interface.
+ * driver.
+ *
+ * Copyright (C) 2011, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#ifndef _MWIFIEX_PCIE_H
+#define _MWIFIEX_PCIE_H
+
+#include <linux/pci.h>
+#include <linux/pcieport_if.h>
+#include <linux/interrupt.h>
+
+#include "main.h"
+
+#define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin"
+
+/* Constants for Buffer Descriptor (BD) rings */
+#define MWIFIEX_MAX_TXRX_BD 0x20
+#define MWIFIEX_TXBD_MASK 0x3F
+#define MWIFIEX_RXBD_MASK 0x3F
+
+#define MWIFIEX_MAX_EVT_BD 0x04
+#define MWIFIEX_EVTBD_MASK 0x07
+
+/* PCIE INTERNAL REGISTERS */
+#define PCIE_SCRATCH_0_REG 0xC10
+#define PCIE_SCRATCH_1_REG 0xC14
+#define PCIE_CPU_INT_EVENT 0xC18
+#define PCIE_CPU_INT_STATUS 0xC1C
+#define PCIE_HOST_INT_STATUS 0xC30
+#define PCIE_HOST_INT_MASK 0xC34
+#define PCIE_HOST_INT_STATUS_MASK 0xC3C
+#define PCIE_SCRATCH_2_REG 0xC40
+#define PCIE_SCRATCH_3_REG 0xC44
+#define PCIE_SCRATCH_4_REG 0xCC0
+#define PCIE_SCRATCH_5_REG 0xCC4
+#define PCIE_SCRATCH_6_REG 0xCC8
+#define PCIE_SCRATCH_7_REG 0xCCC
+#define PCIE_SCRATCH_8_REG 0xCD0
+#define PCIE_SCRATCH_9_REG 0xCD4
+#define PCIE_SCRATCH_10_REG 0xCD8
+#define PCIE_SCRATCH_11_REG 0xCDC
+#define PCIE_SCRATCH_12_REG 0xCE0
+
+#define CPU_INTR_DNLD_RDY BIT(0)
+#define CPU_INTR_DOOR_BELL BIT(1)
+#define CPU_INTR_SLEEP_CFM_DONE BIT(2)
+#define CPU_INTR_RESET BIT(3)
+
+#define HOST_INTR_DNLD_DONE BIT(0)
+#define HOST_INTR_UPLD_RDY BIT(1)
+#define HOST_INTR_CMD_DONE BIT(2)
+#define HOST_INTR_EVENT_RDY BIT(3)
+#define HOST_INTR_MASK (HOST_INTR_DNLD_DONE | \
+ HOST_INTR_UPLD_RDY | \
+ HOST_INTR_CMD_DONE | \
+ HOST_INTR_EVENT_RDY)
+
+#define MWIFIEX_BD_FLAG_ROLLOVER_IND BIT(7)
+#define MWIFIEX_BD_FLAG_FIRST_DESC BIT(0)
+#define MWIFIEX_BD_FLAG_LAST_DESC BIT(1)
+#define REG_CMD_ADDR_LO PCIE_SCRATCH_0_REG
+#define REG_CMD_ADDR_HI PCIE_SCRATCH_1_REG
+#define REG_CMD_SIZE PCIE_SCRATCH_2_REG
+
+#define REG_CMDRSP_ADDR_LO PCIE_SCRATCH_4_REG
+#define REG_CMDRSP_ADDR_HI PCIE_SCRATCH_5_REG
+
+/* TX buffer description read pointer */
+#define REG_TXBD_RDPTR PCIE_SCRATCH_6_REG
+/* TX buffer description write pointer */
+#define REG_TXBD_WRPTR PCIE_SCRATCH_7_REG
+/* RX buffer description read pointer */
+#define REG_RXBD_RDPTR PCIE_SCRATCH_8_REG
+/* RX buffer description write pointer */
+#define REG_RXBD_WRPTR PCIE_SCRATCH_9_REG
+/* Event buffer description read pointer */
+#define REG_EVTBD_RDPTR PCIE_SCRATCH_10_REG
+/* Event buffer description write pointer */
+#define REG_EVTBD_WRPTR PCIE_SCRATCH_11_REG
+/* Driver ready signature write pointer */
+#define REG_DRV_READY PCIE_SCRATCH_12_REG
+
+/* Max retry number of command write */
+#define MAX_WRITE_IOMEM_RETRY 2
+/* Define PCIE block size for firmware download */
+#define MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD 256
+/* FW awake cookie after FW ready */
+#define FW_AWAKE_COOKIE (0xAA55AA55)
+
+struct mwifiex_pcie_buf_desc {
+ u64 paddr;
+ u16 len;
+ u16 flags;
+} __packed;
+
+struct pcie_service_card {
+ struct pci_dev *dev;
+ struct mwifiex_adapter *adapter;
+
+ u32 txbd_wrptr;
+ u32 txbd_rdptr;
+ u32 txbd_ring_size;
+ u8 *txbd_ring_vbase;
+ phys_addr_t txbd_ring_pbase;
+ struct mwifiex_pcie_buf_desc *txbd_ring[MWIFIEX_MAX_TXRX_BD];
+ struct sk_buff *tx_buf_list[MWIFIEX_MAX_TXRX_BD];
+
+ u32 rxbd_wrptr;
+ u32 rxbd_rdptr;
+ u32 rxbd_ring_size;
+ u8 *rxbd_ring_vbase;
+ phys_addr_t rxbd_ring_pbase;
+ struct mwifiex_pcie_buf_desc *rxbd_ring[MWIFIEX_MAX_TXRX_BD];
+ struct sk_buff *rx_buf_list[MWIFIEX_MAX_TXRX_BD];
+
+ u32 evtbd_wrptr;
+ u32 evtbd_rdptr;
+ u32 evtbd_ring_size;
+ u8 *evtbd_ring_vbase;
+ phys_addr_t evtbd_ring_pbase;
+ struct mwifiex_pcie_buf_desc *evtbd_ring[MWIFIEX_MAX_EVT_BD];
+ struct sk_buff *evt_buf_list[MWIFIEX_MAX_EVT_BD];
+
+ struct sk_buff *cmd_buf;
+ struct sk_buff *cmdrsp_buf;
+ struct sk_buff *sleep_cookie;
+ void __iomem *pci_mmap;
+ void __iomem *pci_mmap1;
+};
+
+#endif /* _MWIFIEX_PCIE_H */
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 6f88c8ab5de5..dae8dbb24a03 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -172,59 +172,6 @@ mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
}
/*
- * Sends IOCTL request to get the best BSS.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_find_best_bss(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *ssid_bssid)
-{
- struct mwifiex_ssid_bssid tmp_ssid_bssid;
- u8 *mac;
-
- if (!ssid_bssid)
- return -1;
-
- memcpy(&tmp_ssid_bssid, ssid_bssid,
- sizeof(struct mwifiex_ssid_bssid));
-
- if (!mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid)) {
- memcpy(ssid_bssid, &tmp_ssid_bssid,
- sizeof(struct mwifiex_ssid_bssid));
- mac = (u8 *) &ssid_bssid->bssid;
- dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s,"
- " %pM\n", ssid_bssid->ssid.ssid, mac);
- return 0;
- }
-
- return -1;
-}
-
-/*
- * Sends IOCTL request to start a scan with user configurations.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- *
- * Upon completion, it also generates a wireless event to notify
- * applications.
- */
-int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
- struct mwifiex_user_scan_cfg *scan_req)
-{
- int status;
-
- priv->adapter->cmd_wait_q.condition = false;
-
- status = mwifiex_scan_networks(priv, scan_req);
- if (!status)
- status = mwifiex_wait_queue_complete(priv->adapter);
-
- return status;
-}
-
-/*
* This function checks if wapi is enabled in driver and scanned network is
* compatible with it.
*/
@@ -286,8 +233,7 @@ mwifiex_is_network_compatible_for_static_wep(struct mwifiex_private *priv,
*/
static bool
mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
- struct mwifiex_bssdescriptor *bss_desc,
- int index)
+ struct mwifiex_bssdescriptor *bss_desc)
{
if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
&& priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
@@ -298,9 +244,9 @@ mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
* LinkSys WRT54G && bss_desc->privacy
*/
) {
- dev_dbg(priv->adapter->dev, "info: %s: WPA: index=%d"
+ dev_dbg(priv->adapter->dev, "info: %s: WPA:"
" wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
- "EncMode=%#x privacy=%#x\n", __func__, index,
+ "EncMode=%#x privacy=%#x\n", __func__,
(bss_desc->bcn_wpa_ie) ?
(*(bss_desc->bcn_wpa_ie)).
vend_hdr.element_id : 0,
@@ -324,8 +270,7 @@ mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
*/
static bool
mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv,
- struct mwifiex_bssdescriptor *bss_desc,
- int index)
+ struct mwifiex_bssdescriptor *bss_desc)
{
if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
&& !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled
@@ -336,9 +281,9 @@ mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv,
* LinkSys WRT54G && bss_desc->privacy
*/
) {
- dev_dbg(priv->adapter->dev, "info: %s: WPA2: index=%d"
+ dev_dbg(priv->adapter->dev, "info: %s: WPA2: "
" wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
- "EncMode=%#x privacy=%#x\n", __func__, index,
+ "EncMode=%#x privacy=%#x\n", __func__,
(bss_desc->bcn_wpa_ie) ?
(*(bss_desc->bcn_wpa_ie)).
vend_hdr.element_id : 0,
@@ -383,8 +328,7 @@ mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv,
*/
static bool
mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
- struct mwifiex_bssdescriptor *bss_desc,
- int index)
+ struct mwifiex_bssdescriptor *bss_desc)
{
if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
&& !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
@@ -395,9 +339,9 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
&& priv->sec_info.encryption_mode
&& bss_desc->privacy) {
dev_dbg(priv->adapter->dev, "info: %s: dynamic "
- "WEP: index=%d wpa_ie=%#x wpa2_ie=%#x "
+ "WEP: wpa_ie=%#x wpa2_ie=%#x "
"EncMode=%#x privacy=%#x\n",
- __func__, index,
+ __func__,
(bss_desc->bcn_wpa_ie) ?
(*(bss_desc->bcn_wpa_ie)).
vend_hdr.element_id : 0,
@@ -430,42 +374,41 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
* Compatibility is not matched while roaming, except for mode.
*/
static s32
-mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
+mwifiex_is_network_compatible(struct mwifiex_private *priv,
+ struct mwifiex_bssdescriptor *bss_desc, u32 mode)
{
struct mwifiex_adapter *adapter = priv->adapter;
- struct mwifiex_bssdescriptor *bss_desc;
- bss_desc = &adapter->scan_table[index];
bss_desc->disable_11n = false;
/* Don't check for compatibility if roaming */
if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION)
&& (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
- return index;
+ return 0;
if (priv->wps.session_enable) {
dev_dbg(adapter->dev,
"info: return success directly in WPS period\n");
- return index;
+ return 0;
}
if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) {
dev_dbg(adapter->dev, "info: return success for WAPI AP\n");
- return index;
+ return 0;
}
if (bss_desc->bss_mode == mode) {
if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) {
/* No security */
- return index;
+ return 0;
} else if (mwifiex_is_network_compatible_for_static_wep(priv,
bss_desc)) {
/* Static WEP enabled */
dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n");
bss_desc->disable_11n = true;
- return index;
- } else if (mwifiex_is_network_compatible_for_wpa(priv, bss_desc,
- index)) {
+ return 0;
+ } else if (mwifiex_is_network_compatible_for_wpa(priv,
+ bss_desc)) {
/* WPA enabled */
if (((priv->adapter->config_bands & BAND_GN
|| priv->adapter->config_bands & BAND_AN)
@@ -483,9 +426,9 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
return -1;
}
}
- return index;
+ return 0;
} else if (mwifiex_is_network_compatible_for_wpa2(priv,
- bss_desc, index)) {
+ bss_desc)) {
/* WPA2 enabled */
if (((priv->adapter->config_bands & BAND_GN
|| priv->adapter->config_bands & BAND_AN)
@@ -503,22 +446,22 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
return -1;
}
}
- return index;
+ return 0;
} else if (mwifiex_is_network_compatible_for_adhoc_aes(priv,
bss_desc)) {
/* Ad-hoc AES enabled */
- return index;
+ return 0;
} else if (mwifiex_is_network_compatible_for_dynamic_wep(priv,
- bss_desc, index)) {
+ bss_desc)) {
/* Dynamic WEP enabled */
- return index;
+ return 0;
}
/* Security doesn't match */
- dev_dbg(adapter->dev, "info: %s: failed: index=%d "
+ dev_dbg(adapter->dev, "info: %s: failed: "
"wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode"
"=%#x privacy=%#x\n",
- __func__, index,
+ __func__,
(bss_desc->bcn_wpa_ie) ?
(*(bss_desc->bcn_wpa_ie)).vend_hdr.
element_id : 0,
@@ -538,52 +481,6 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
}
/*
- * This function finds the best SSID in the scan list.
- *
- * It searches the scan table for the best SSID that also matches the current
- * adapter network preference (mode, security etc.).
- */
-static s32
-mwifiex_find_best_network_in_list(struct mwifiex_private *priv)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u32 mode = priv->bss_mode;
- s32 best_net = -1;
- s32 best_rssi = 0;
- u32 i;
-
- dev_dbg(adapter->dev, "info: num of BSSIDs = %d\n",
- adapter->num_in_scan_table);
-
- for (i = 0; i < adapter->num_in_scan_table; i++) {
- switch (mode) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- if (mwifiex_is_network_compatible(priv, i, mode) >= 0) {
- if (SCAN_RSSI(adapter->scan_table[i].rssi) >
- best_rssi) {
- best_rssi = SCAN_RSSI(adapter->
- scan_table[i].rssi);
- best_net = i;
- }
- }
- break;
- case NL80211_IFTYPE_UNSPECIFIED:
- default:
- if (SCAN_RSSI(adapter->scan_table[i].rssi) >
- best_rssi) {
- best_rssi = SCAN_RSSI(adapter->scan_table[i].
- rssi);
- best_net = i;
- }
- break;
- }
- }
-
- return best_net;
-}
-
-/*
* This function creates a channel list for the driver to scan, based
* on region/band information.
*
@@ -612,7 +509,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
sband = priv->wdev->wiphy->bands[band];
- for (i = 0; (i < sband->n_channels) ; i++, chan_idx++) {
+ for (i = 0; (i < sband->n_channels) ; i++) {
ch = &sband->channels[i];
if (ch->flags & IEEE80211_CHAN_DISABLED)
continue;
@@ -643,6 +540,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|= MWIFIEX_DISABLE_CHAN_FILT;
}
+ chan_idx++;
}
}
@@ -1161,34 +1059,13 @@ mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
}
/*
- * This function interprets a BSS scan response returned from the firmware.
- *
- * The various fixed fields and IEs are parsed and passed back for a BSS
- * probe response or beacon from scan command. Information is recorded as
- * needed in the scan table for that entry.
- *
- * The following IE types are recognized and parsed -
- * - SSID
- * - Supported rates
- * - FH parameters set
- * - DS parameters set
- * - CF parameters set
- * - IBSS parameters set
- * - ERP information
- * - Extended supported rates
- * - Vendor specific (221)
- * - RSN IE
- * - WAPI IE
- * - HT capability
- * - HT operation
- * - BSS Coexistence 20/40
- * - Extended capability
- * - Overlapping BSS scan parameters
+ * This function parses provided beacon buffer and updates
+ * respective fields in bss descriptor structure.
*/
-static int
-mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
- struct mwifiex_bssdescriptor *bss_entry,
- u8 **beacon_info, u32 *bytes_left)
+int
+mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
+ struct mwifiex_bssdescriptor *bss_entry,
+ u8 *ie_buf, u32 ie_len)
{
int ret = 0;
u8 element_id;
@@ -1196,135 +1073,43 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
struct ieee_types_ds_param_set *ds_param_set;
struct ieee_types_cf_param_set *cf_param_set;
struct ieee_types_ibss_param_set *ibss_param_set;
- __le16 beacon_interval;
- __le16 capabilities;
u8 *current_ptr;
u8 *rate;
u8 element_len;
u16 total_ie_len;
u8 bytes_to_copy;
u8 rate_size;
- u16 beacon_size;
u8 found_data_rate_ie;
- u32 bytes_left_for_current_beacon;
+ u32 bytes_left;
struct ieee_types_vendor_specific *vendor_ie;
const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
found_data_rate_ie = false;
rate_size = 0;
- beacon_size = 0;
-
- if (*bytes_left >= sizeof(beacon_size)) {
- /* Extract & convert beacon size from the command buffer */
- memcpy(&beacon_size, *beacon_info, sizeof(beacon_size));
- *bytes_left -= sizeof(beacon_size);
- *beacon_info += sizeof(beacon_size);
- }
-
- if (!beacon_size || beacon_size > *bytes_left) {
- *beacon_info += *bytes_left;
- *bytes_left = 0;
- return -1;
- }
-
- /* Initialize the current working beacon pointer for this BSS
- iteration */
- current_ptr = *beacon_info;
-
- /* Advance the return beacon pointer past the current beacon */
- *beacon_info += beacon_size;
- *bytes_left -= beacon_size;
-
- bytes_left_for_current_beacon = beacon_size;
-
- memcpy(bss_entry->mac_address, current_ptr, ETH_ALEN);
- dev_dbg(adapter->dev, "info: InterpretIE: AP MAC Addr: %pM\n",
- bss_entry->mac_address);
-
- current_ptr += ETH_ALEN;
- bytes_left_for_current_beacon -= ETH_ALEN;
-
- if (bytes_left_for_current_beacon < 12) {
- dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
- return -1;
- }
-
- /*
- * Next 4 fields are RSSI, time stamp, beacon interval,
- * and capability information
- */
-
- /* RSSI is 1 byte long */
- bss_entry->rssi = (s32) (*current_ptr);
- dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", *current_ptr);
- current_ptr += 1;
- bytes_left_for_current_beacon -= 1;
-
- /*
- * The RSSI is not part of the beacon/probe response. After we have
- * advanced current_ptr past the RSSI field, save the remaining
- * data for use at the application layer
- */
- bss_entry->beacon_buf = current_ptr;
- bss_entry->beacon_buf_size = bytes_left_for_current_beacon;
-
- /* Time stamp is 8 bytes long */
- memcpy(bss_entry->time_stamp, current_ptr, 8);
- current_ptr += 8;
- bytes_left_for_current_beacon -= 8;
-
- /* Beacon interval is 2 bytes long */
- memcpy(&beacon_interval, current_ptr, 2);
- bss_entry->beacon_period = le16_to_cpu(beacon_interval);
- current_ptr += 2;
- bytes_left_for_current_beacon -= 2;
-
- /* Capability information is 2 bytes long */
- memcpy(&capabilities, current_ptr, 2);
- dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
- capabilities);
- bss_entry->cap_info_bitmap = le16_to_cpu(capabilities);
- current_ptr += 2;
- bytes_left_for_current_beacon -= 2;
-
- /* Rest of the current buffer are IE's */
- dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n",
- bytes_left_for_current_beacon);
-
- if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
- dev_dbg(adapter->dev, "info: InterpretIE: AP WEP enabled\n");
- bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
- } else {
- bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
- }
-
- if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
- bss_entry->bss_mode = NL80211_IFTYPE_ADHOC;
- else
- bss_entry->bss_mode = NL80211_IFTYPE_STATION;
-
+ current_ptr = ie_buf;
+ bytes_left = ie_len;
+ bss_entry->beacon_buf = ie_buf;
+ bss_entry->beacon_buf_size = ie_len;
/* Process variable IE */
- while (bytes_left_for_current_beacon >= 2) {
+ while (bytes_left >= 2) {
element_id = *current_ptr;
element_len = *(current_ptr + 1);
total_ie_len = element_len + sizeof(struct ieee_types_header);
- if (bytes_left_for_current_beacon < total_ie_len) {
+ if (bytes_left < total_ie_len) {
dev_err(adapter->dev, "err: InterpretIE: in processing"
" IE, bytes left < IE length\n");
- bytes_left_for_current_beacon = 0;
- ret = -1;
- continue;
+ return -1;
}
switch (element_id) {
case WLAN_EID_SSID:
bss_entry->ssid.ssid_len = element_len;
memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
element_len);
- dev_dbg(adapter->dev, "info: InterpretIE: ssid: %-32s\n",
- bss_entry->ssid.ssid);
+ dev_dbg(adapter->dev, "info: InterpretIE: ssid: "
+ "%-32s\n", bss_entry->ssid.ssid);
break;
case WLAN_EID_SUPP_RATES:
@@ -1471,13 +1256,6 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
sizeof(struct ieee_types_header) -
bss_entry->beacon_buf);
break;
- case WLAN_EID_OVERLAP_BSS_SCAN_PARAM:
- bss_entry->bcn_obss_scan =
- (struct ieee_types_obss_scan_param *)
- current_ptr;
- bss_entry->overlap_bss_offset = (u16) (current_ptr -
- bss_entry->beacon_buf);
- break;
default:
break;
}
@@ -1485,577 +1263,13 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
current_ptr += element_len + 2;
/* Need to account for IE ID and IE Len */
- bytes_left_for_current_beacon -= (element_len + 2);
+ bytes_left -= (element_len + 2);
- } /* while (bytes_left_for_current_beacon > 2) */
+ } /* while (bytes_left > 2) */
return ret;
}
/*
- * This function adjusts the pointers used in beacon buffers to reflect
- * shifts.
- *
- * The memory allocated for beacon buffers is of fixed sizes where all the
- * saved beacons must be stored. New beacons are added in the free portion
- * of this memory, space permitting; while duplicate beacon buffers are
- * placed at the same start location. However, since duplicate beacon
- * buffers may not match the size of the old one, all the following buffers
- * in the memory must be shifted to either make space, or to fill up freed
- * up space.
- *
- * This function is used to update the beacon buffer pointers that are past
- * an existing beacon buffer that is updated with a new one of different
- * size. The pointers are shifted by a fixed amount, either forward or
- * backward.
- *
- * the following pointers in every affected beacon buffers are changed, if
- * present -
- * - WPA IE pointer
- * - RSN IE pointer
- * - WAPI IE pointer
- * - HT capability IE pointer
- * - HT information IE pointer
- * - BSS coexistence 20/40 IE pointer
- * - Extended capability IE pointer
- * - Overlapping BSS scan parameter IE pointer
- */
-static void
-mwifiex_adjust_beacon_buffer_ptrs(struct mwifiex_private *priv, u8 advance,
- u8 *bcn_store, u32 rem_bcn_size,
- u32 num_of_ent)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u32 adj_idx;
- for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) {
- if (adapter->scan_table[adj_idx].beacon_buf > bcn_store) {
-
- if (advance)
- adapter->scan_table[adj_idx].beacon_buf +=
- rem_bcn_size;
- else
- adapter->scan_table[adj_idx].beacon_buf -=
- rem_bcn_size;
-
- if (adapter->scan_table[adj_idx].bcn_wpa_ie)
- adapter->scan_table[adj_idx].bcn_wpa_ie =
- (struct ieee_types_vendor_specific *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].wpa_offset);
- if (adapter->scan_table[adj_idx].bcn_rsn_ie)
- adapter->scan_table[adj_idx].bcn_rsn_ie =
- (struct ieee_types_generic *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].rsn_offset);
- if (adapter->scan_table[adj_idx].bcn_wapi_ie)
- adapter->scan_table[adj_idx].bcn_wapi_ie =
- (struct ieee_types_generic *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].wapi_offset);
- if (adapter->scan_table[adj_idx].bcn_ht_cap)
- adapter->scan_table[adj_idx].bcn_ht_cap =
- (struct ieee80211_ht_cap *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].ht_cap_offset);
-
- if (adapter->scan_table[adj_idx].bcn_ht_info)
- adapter->scan_table[adj_idx].bcn_ht_info =
- (struct ieee80211_ht_info *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].ht_info_offset);
- if (adapter->scan_table[adj_idx].bcn_bss_co_2040)
- adapter->scan_table[adj_idx].bcn_bss_co_2040 =
- (u8 *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].bss_co_2040_offset);
- if (adapter->scan_table[adj_idx].bcn_ext_cap)
- adapter->scan_table[adj_idx].bcn_ext_cap =
- (u8 *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].ext_cap_offset);
- if (adapter->scan_table[adj_idx].bcn_obss_scan)
- adapter->scan_table[adj_idx].bcn_obss_scan =
- (struct ieee_types_obss_scan_param *)
- (adapter->scan_table[adj_idx].beacon_buf +
- adapter->scan_table[adj_idx].overlap_bss_offset);
- }
- }
-}
-
-/*
- * This function updates the pointers used in beacon buffer for given bss
- * descriptor to reflect shifts
- *
- * Following pointers are updated
- * - WPA IE pointer
- * - RSN IE pointer
- * - WAPI IE pointer
- * - HT capability IE pointer
- * - HT information IE pointer
- * - BSS coexistence 20/40 IE pointer
- * - Extended capability IE pointer
- * - Overlapping BSS scan parameter IE pointer
- */
-static void
-mwifiex_update_beacon_buffer_ptrs(struct mwifiex_bssdescriptor *beacon)
-{
- if (beacon->bcn_wpa_ie)
- beacon->bcn_wpa_ie = (struct ieee_types_vendor_specific *)
- (beacon->beacon_buf + beacon->wpa_offset);
- if (beacon->bcn_rsn_ie)
- beacon->bcn_rsn_ie = (struct ieee_types_generic *)
- (beacon->beacon_buf + beacon->rsn_offset);
- if (beacon->bcn_wapi_ie)
- beacon->bcn_wapi_ie = (struct ieee_types_generic *)
- (beacon->beacon_buf + beacon->wapi_offset);
- if (beacon->bcn_ht_cap)
- beacon->bcn_ht_cap = (struct ieee80211_ht_cap *)
- (beacon->beacon_buf + beacon->ht_cap_offset);
- if (beacon->bcn_ht_info)
- beacon->bcn_ht_info = (struct ieee80211_ht_info *)
- (beacon->beacon_buf + beacon->ht_info_offset);
- if (beacon->bcn_bss_co_2040)
- beacon->bcn_bss_co_2040 = (u8 *) (beacon->beacon_buf +
- beacon->bss_co_2040_offset);
- if (beacon->bcn_ext_cap)
- beacon->bcn_ext_cap = (u8 *) (beacon->beacon_buf +
- beacon->ext_cap_offset);
- if (beacon->bcn_obss_scan)
- beacon->bcn_obss_scan = (struct ieee_types_obss_scan_param *)
- (beacon->beacon_buf + beacon->overlap_bss_offset);
-}
-
-/*
- * This function stores a beacon or probe response for a BSS returned
- * in the scan.
- *
- * This stores a new scan response or an update for a previous scan response.
- * New entries need to verify that they do not exceed the total amount of
- * memory allocated for the table.
- *
- * Replacement entries need to take into consideration the amount of space
- * currently allocated for the beacon/probe response and adjust the entry
- * as needed.
- *
- * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved
- * for an entry in case it is a beacon since a probe response for the
- * network will by larger per the standard. This helps to reduce the
- * amount of memory copying to fit a new probe response into an entry
- * already occupied by a network's previously stored beacon.
- */
-static void
-mwifiex_ret_802_11_scan_store_beacon(struct mwifiex_private *priv,
- u32 beacon_idx, u32 num_of_ent,
- struct mwifiex_bssdescriptor *new_beacon)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u8 *bcn_store;
- u32 new_bcn_size;
- u32 old_bcn_size;
- u32 bcn_space;
-
- if (adapter->scan_table[beacon_idx].beacon_buf) {
-
- new_bcn_size = new_beacon->beacon_buf_size;
- old_bcn_size = adapter->scan_table[beacon_idx].beacon_buf_size;
- bcn_space = adapter->scan_table[beacon_idx].beacon_buf_size_max;
- bcn_store = adapter->scan_table[beacon_idx].beacon_buf;
-
- /* Set the max to be the same as current entry unless changed
- below */
- new_beacon->beacon_buf_size_max = bcn_space;
- if (new_bcn_size == old_bcn_size) {
- /*
- * Beacon is the same size as the previous entry.
- * Replace the previous contents with the scan result
- */
- memcpy(bcn_store, new_beacon->beacon_buf,
- new_beacon->beacon_buf_size);
-
- } else if (new_bcn_size <= bcn_space) {
- /*
- * New beacon size will fit in the amount of space
- * we have previously allocated for it
- */
-
- /* Copy the new beacon buffer entry over the old one */
- memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size);
-
- /*
- * If the old beacon size was less than the maximum
- * we had alloted for the entry, and the new entry
- * is even smaller, reset the max size to the old
- * beacon entry and compress the storage space
- * (leaving a new pad space of (old_bcn_size -
- * new_bcn_size).
- */
- if (old_bcn_size < bcn_space
- && new_bcn_size <= old_bcn_size) {
- /*
- * Old Beacon size is smaller than the alloted
- * storage size. Shrink the alloted storage
- * space.
- */
- dev_dbg(adapter->dev, "info: AppControl:"
- " smaller duplicate beacon "
- "(%d), old = %d, new = %d, space = %d,"
- "left = %d\n",
- beacon_idx, old_bcn_size, new_bcn_size,
- bcn_space,
- (int)(sizeof(adapter->bcn_buf) -
- (adapter->bcn_buf_end -
- adapter->bcn_buf)));
-
- /*
- * memmove (since the memory overlaps) the
- * data after the beacon we just stored to the
- * end of the current beacon. This cleans up
- * any unused space the old larger beacon was
- * using in the buffer
- */
- memmove(bcn_store + old_bcn_size,
- bcn_store + bcn_space,
- adapter->bcn_buf_end - (bcn_store +
- bcn_space));
-
- /*
- * Decrement the end pointer by the difference
- * between the old larger size and the new
- * smaller size since we are using less space
- * due to the new beacon being smaller
- */
- adapter->bcn_buf_end -=
- (bcn_space - old_bcn_size);
-
- /* Set the maximum storage size to the old
- beacon size */
- new_beacon->beacon_buf_size_max = old_bcn_size;
-
- /* Adjust beacon buffer pointers that are past
- the current */
- mwifiex_adjust_beacon_buffer_ptrs(priv, 0,
- bcn_store, (bcn_space - old_bcn_size),
- num_of_ent);
- }
- } else if (adapter->bcn_buf_end + (new_bcn_size - bcn_space)
- < (adapter->bcn_buf + sizeof(adapter->bcn_buf))) {
- /*
- * Beacon is larger than space previously allocated
- * (bcn_space) and there is enough space left in the
- * beaconBuffer to store the additional data
- */
- dev_dbg(adapter->dev, "info: AppControl:"
- " larger duplicate beacon (%d), "
- "old = %d, new = %d, space = %d, left = %d\n",
- beacon_idx, old_bcn_size, new_bcn_size,
- bcn_space,
- (int)(sizeof(adapter->bcn_buf) -
- (adapter->bcn_buf_end -
- adapter->bcn_buf)));
-
- /*
- * memmove (since the memory overlaps) the data
- * after the beacon we just stored to the end of
- * the current beacon. This moves the data for
- * the beacons after this further in memory to
- * make space for the new larger beacon we are
- * about to copy in.
- */
- memmove(bcn_store + new_bcn_size,
- bcn_store + bcn_space,
- adapter->bcn_buf_end - (bcn_store + bcn_space));
-
- /* Copy the new beacon buffer entry over the old one */
- memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size);
-
- /* Move the beacon end pointer by the amount of new
- beacon data we are adding */
- adapter->bcn_buf_end += (new_bcn_size - bcn_space);
-
- /*
- * This entry is bigger than the alloted max space
- * previously reserved. Increase the max space to
- * be equal to the new beacon size
- */
- new_beacon->beacon_buf_size_max = new_bcn_size;
-
- /* Adjust beacon buffer pointers that are past the
- current */
- mwifiex_adjust_beacon_buffer_ptrs(priv, 1, bcn_store,
- (new_bcn_size - bcn_space),
- num_of_ent);
- } else {
- /*
- * Beacon is larger than the previously allocated space,
- * but there is not enough free space to store the
- * additional data.
- */
- dev_err(adapter->dev, "AppControl: larger duplicate "
- " beacon (%d), old = %d new = %d, space = %d,"
- " left = %d\n", beacon_idx, old_bcn_size,
- new_bcn_size, bcn_space,
- (int)(sizeof(adapter->bcn_buf) -
- (adapter->bcn_buf_end - adapter->bcn_buf)));
-
- /* Storage failure, keep old beacon intact */
- new_beacon->beacon_buf_size = old_bcn_size;
- if (new_beacon->bcn_wpa_ie)
- new_beacon->wpa_offset =
- adapter->scan_table[beacon_idx].
- wpa_offset;
- if (new_beacon->bcn_rsn_ie)
- new_beacon->rsn_offset =
- adapter->scan_table[beacon_idx].
- rsn_offset;
- if (new_beacon->bcn_wapi_ie)
- new_beacon->wapi_offset =
- adapter->scan_table[beacon_idx].
- wapi_offset;
- if (new_beacon->bcn_ht_cap)
- new_beacon->ht_cap_offset =
- adapter->scan_table[beacon_idx].
- ht_cap_offset;
- if (new_beacon->bcn_ht_info)
- new_beacon->ht_info_offset =
- adapter->scan_table[beacon_idx].
- ht_info_offset;
- if (new_beacon->bcn_bss_co_2040)
- new_beacon->bss_co_2040_offset =
- adapter->scan_table[beacon_idx].
- bss_co_2040_offset;
- if (new_beacon->bcn_ext_cap)
- new_beacon->ext_cap_offset =
- adapter->scan_table[beacon_idx].
- ext_cap_offset;
- if (new_beacon->bcn_obss_scan)
- new_beacon->overlap_bss_offset =
- adapter->scan_table[beacon_idx].
- overlap_bss_offset;
- }
- /* Point the new entry to its permanent storage space */
- new_beacon->beacon_buf = bcn_store;
- mwifiex_update_beacon_buffer_ptrs(new_beacon);
- } else {
- /*
- * No existing beacon data exists for this entry, check to see
- * if we can fit it in the remaining space
- */
- if (adapter->bcn_buf_end + new_beacon->beacon_buf_size +
- SCAN_BEACON_ENTRY_PAD < (adapter->bcn_buf +
- sizeof(adapter->bcn_buf))) {
-
- /*
- * Copy the beacon buffer data from the local entry to
- * the adapter dev struct buffer space used to store
- * the raw beacon data for each entry in the scan table
- */
- memcpy(adapter->bcn_buf_end, new_beacon->beacon_buf,
- new_beacon->beacon_buf_size);
-
- /* Update the beacon ptr to point to the table save
- area */
- new_beacon->beacon_buf = adapter->bcn_buf_end;
- new_beacon->beacon_buf_size_max =
- (new_beacon->beacon_buf_size +
- SCAN_BEACON_ENTRY_PAD);
-
- mwifiex_update_beacon_buffer_ptrs(new_beacon);
-
- /* Increment the end pointer by the size reserved */
- adapter->bcn_buf_end += new_beacon->beacon_buf_size_max;
-
- dev_dbg(adapter->dev, "info: AppControl: beacon[%02d]"
- " sz=%03d, used = %04d, left = %04d\n",
- beacon_idx,
- new_beacon->beacon_buf_size,
- (int)(adapter->bcn_buf_end - adapter->bcn_buf),
- (int)(sizeof(adapter->bcn_buf) -
- (adapter->bcn_buf_end -
- adapter->bcn_buf)));
- } else {
- /* No space for new beacon */
- dev_dbg(adapter->dev, "info: AppControl: no space for"
- " beacon (%d): %pM sz=%03d, left=%03d\n",
- beacon_idx, new_beacon->mac_address,
- new_beacon->beacon_buf_size,
- (int)(sizeof(adapter->bcn_buf) -
- (adapter->bcn_buf_end -
- adapter->bcn_buf)));
-
- /* Storage failure; clear storage records for this
- bcn */
- new_beacon->beacon_buf = NULL;
- new_beacon->beacon_buf_size = 0;
- new_beacon->beacon_buf_size_max = 0;
- new_beacon->bcn_wpa_ie = NULL;
- new_beacon->wpa_offset = 0;
- new_beacon->bcn_rsn_ie = NULL;
- new_beacon->rsn_offset = 0;
- new_beacon->bcn_wapi_ie = NULL;
- new_beacon->wapi_offset = 0;
- new_beacon->bcn_ht_cap = NULL;
- new_beacon->ht_cap_offset = 0;
- new_beacon->bcn_ht_info = NULL;
- new_beacon->ht_info_offset = 0;
- new_beacon->bcn_bss_co_2040 = NULL;
- new_beacon->bss_co_2040_offset = 0;
- new_beacon->bcn_ext_cap = NULL;
- new_beacon->ext_cap_offset = 0;
- new_beacon->bcn_obss_scan = NULL;
- new_beacon->overlap_bss_offset = 0;
- }
- }
-}
-
-/*
- * This function restores a beacon buffer of the current BSS descriptor.
- */
-static void mwifiex_restore_curr_bcn(struct mwifiex_private *priv)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- struct mwifiex_bssdescriptor *curr_bss =
- &priv->curr_bss_params.bss_descriptor;
- unsigned long flags;
-
- if (priv->curr_bcn_buf &&
- ((adapter->bcn_buf_end + priv->curr_bcn_size) <
- (adapter->bcn_buf + sizeof(adapter->bcn_buf)))) {
- spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
-
- /* restore the current beacon buffer */
- memcpy(adapter->bcn_buf_end, priv->curr_bcn_buf,
- priv->curr_bcn_size);
- curr_bss->beacon_buf = adapter->bcn_buf_end;
- curr_bss->beacon_buf_size = priv->curr_bcn_size;
- adapter->bcn_buf_end += priv->curr_bcn_size;
-
- /* adjust the pointers in the current BSS descriptor */
- if (curr_bss->bcn_wpa_ie)
- curr_bss->bcn_wpa_ie =
- (struct ieee_types_vendor_specific *)
- (curr_bss->beacon_buf +
- curr_bss->wpa_offset);
-
- if (curr_bss->bcn_rsn_ie)
- curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
- (curr_bss->beacon_buf +
- curr_bss->rsn_offset);
-
- if (curr_bss->bcn_ht_cap)
- curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
- (curr_bss->beacon_buf +
- curr_bss->ht_cap_offset);
-
- if (curr_bss->bcn_ht_info)
- curr_bss->bcn_ht_info = (struct ieee80211_ht_info *)
- (curr_bss->beacon_buf +
- curr_bss->ht_info_offset);
-
- if (curr_bss->bcn_bss_co_2040)
- curr_bss->bcn_bss_co_2040 =
- (u8 *) (curr_bss->beacon_buf +
- curr_bss->bss_co_2040_offset);
-
- if (curr_bss->bcn_ext_cap)
- curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf +
- curr_bss->ext_cap_offset);
-
- if (curr_bss->bcn_obss_scan)
- curr_bss->bcn_obss_scan =
- (struct ieee_types_obss_scan_param *)
- (curr_bss->beacon_buf +
- curr_bss->overlap_bss_offset);
-
- spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
-
- dev_dbg(adapter->dev, "info: current beacon restored %d\n",
- priv->curr_bcn_size);
- } else {
- dev_warn(adapter->dev,
- "curr_bcn_buf not saved or bcn_buf has no space\n");
- }
-}
-
-/*
- * This function post processes the scan table after a new scan command has
- * completed.
- *
- * It inspects each entry of the scan table and tries to find an entry that
- * matches with our current associated/joined network from the scan. If
- * one is found, the stored copy of the BSS descriptor of our current network
- * is updated.
- *
- * It also debug dumps the current scan table contents after processing is over.
- */
-static void
-mwifiex_process_scan_results(struct mwifiex_private *priv)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- s32 j;
- u32 i;
- unsigned long flags;
-
- if (priv->media_connected) {
-
- j = mwifiex_find_ssid_in_list(priv, &priv->curr_bss_params.
- bss_descriptor.ssid,
- priv->curr_bss_params.
- bss_descriptor.mac_address,
- priv->bss_mode);
-
- if (j >= 0) {
- spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
- priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
- priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
- priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
- priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
- priv->curr_bss_params.bss_descriptor.ht_cap_offset =
- 0;
- priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL;
- priv->curr_bss_params.bss_descriptor.ht_info_offset =
- 0;
- priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 =
- NULL;
- priv->curr_bss_params.bss_descriptor.
- bss_co_2040_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
- priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
- priv->curr_bss_params.bss_descriptor.
- bcn_obss_scan = NULL;
- priv->curr_bss_params.bss_descriptor.
- overlap_bss_offset = 0;
- priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
- priv->curr_bss_params.bss_descriptor.beacon_buf_size =
- 0;
- priv->curr_bss_params.bss_descriptor.
- beacon_buf_size_max = 0;
-
- dev_dbg(adapter->dev, "info: Found current ssid/bssid"
- " in list @ index #%d\n", j);
- /* Make a copy of current BSSID descriptor */
- memcpy(&priv->curr_bss_params.bss_descriptor,
- &adapter->scan_table[j],
- sizeof(priv->curr_bss_params.bss_descriptor));
-
- mwifiex_save_curr_bcn(priv);
- spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
-
- } else {
- mwifiex_restore_curr_bcn(priv);
- }
- }
-
- for (i = 0; i < adapter->num_in_scan_table; i++)
- dev_dbg(adapter->dev, "info: scan:(%02d) %pM "
- "RSSI[%03d], SSID[%s]\n",
- i, adapter->scan_table[i].mac_address,
- (s32) adapter->scan_table[i].rssi,
- adapter->scan_table[i].ssid.ssid);
-}
-
-/*
* This function converts radio type scan parameter to a band configuration
* to be used in join command.
*/
@@ -2072,175 +1286,6 @@ mwifiex_radio_type_to_band(u8 radio_type)
}
/*
- * This function deletes a specific indexed entry from the scan table.
- *
- * This also compacts the remaining entries and adjusts any buffering
- * of beacon/probe response data if needed.
- */
-static void
-mwifiex_scan_delete_table_entry(struct mwifiex_private *priv, s32 table_idx)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u32 del_idx;
- u32 beacon_buf_adj;
- u8 *beacon_buf;
-
- /*
- * Shift the saved beacon buffer data for the scan table back over the
- * entry being removed. Update the end of buffer pointer. Save the
- * deleted buffer allocation size for pointer adjustments for entries
- * compacted after the deleted index.
- */
- beacon_buf_adj = adapter->scan_table[table_idx].beacon_buf_size_max;
-
- dev_dbg(adapter->dev, "info: Scan: Delete Entry %d, beacon buffer "
- "removal = %d bytes\n", table_idx, beacon_buf_adj);
-
- /* Check if the table entry had storage allocated for its beacon */
- if (beacon_buf_adj) {
- beacon_buf = adapter->scan_table[table_idx].beacon_buf;
-
- /*
- * Remove the entry's buffer space, decrement the table end
- * pointer by the amount we are removing
- */
- adapter->bcn_buf_end -= beacon_buf_adj;
-
- dev_dbg(adapter->dev, "info: scan: delete entry %d,"
- " compact data: %p <- %p (sz = %d)\n",
- table_idx, beacon_buf,
- beacon_buf + beacon_buf_adj,
- (int)(adapter->bcn_buf_end - beacon_buf));
-
- /*
- * Compact data storage. Copy all data after the deleted
- * entry's end address (beacon_buf + beacon_buf_adj) back
- * to the original start address (beacon_buf).
- *
- * Scan table entries affected by the move will have their
- * entry pointer adjusted below.
- *
- * Use memmove since the dest/src memory regions overlap.
- */
- memmove(beacon_buf, beacon_buf + beacon_buf_adj,
- adapter->bcn_buf_end - beacon_buf);
- }
-
- dev_dbg(adapter->dev,
- "info: Scan: Delete Entry %d, num_in_scan_table = %d\n",
- table_idx, adapter->num_in_scan_table);
-
- /* Shift all of the entries after the table_idx back by one, compacting
- the table and removing the requested entry */
- for (del_idx = table_idx; (del_idx + 1) < adapter->num_in_scan_table;
- del_idx++) {
- /* Copy the next entry over this one */
- memcpy(adapter->scan_table + del_idx,
- adapter->scan_table + del_idx + 1,
- sizeof(struct mwifiex_bssdescriptor));
-
- /*
- * Adjust this entry's pointer to its beacon buffer based on
- * the removed/compacted entry from the deleted index. Don't
- * decrement if the buffer pointer is NULL (no data stored for
- * this entry).
- */
- if (adapter->scan_table[del_idx].beacon_buf) {
- adapter->scan_table[del_idx].beacon_buf -=
- beacon_buf_adj;
- if (adapter->scan_table[del_idx].bcn_wpa_ie)
- adapter->scan_table[del_idx].bcn_wpa_ie =
- (struct ieee_types_vendor_specific *)
- (adapter->scan_table[del_idx].
- beacon_buf +
- adapter->scan_table[del_idx].
- wpa_offset);
- if (adapter->scan_table[del_idx].bcn_rsn_ie)
- adapter->scan_table[del_idx].bcn_rsn_ie =
- (struct ieee_types_generic *)
- (adapter->scan_table[del_idx].
- beacon_buf +
- adapter->scan_table[del_idx].
- rsn_offset);
- if (adapter->scan_table[del_idx].bcn_wapi_ie)
- adapter->scan_table[del_idx].bcn_wapi_ie =
- (struct ieee_types_generic *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- wapi_offset);
- if (adapter->scan_table[del_idx].bcn_ht_cap)
- adapter->scan_table[del_idx].bcn_ht_cap =
- (struct ieee80211_ht_cap *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- ht_cap_offset);
-
- if (adapter->scan_table[del_idx].bcn_ht_info)
- adapter->scan_table[del_idx].bcn_ht_info =
- (struct ieee80211_ht_info *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- ht_info_offset);
- if (adapter->scan_table[del_idx].bcn_bss_co_2040)
- adapter->scan_table[del_idx].bcn_bss_co_2040 =
- (u8 *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- bss_co_2040_offset);
- if (adapter->scan_table[del_idx].bcn_ext_cap)
- adapter->scan_table[del_idx].bcn_ext_cap =
- (u8 *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- ext_cap_offset);
- if (adapter->scan_table[del_idx].bcn_obss_scan)
- adapter->scan_table[del_idx].
- bcn_obss_scan =
- (struct ieee_types_obss_scan_param *)
- (adapter->scan_table[del_idx].beacon_buf
- + adapter->scan_table[del_idx].
- overlap_bss_offset);
- }
- }
-
- /* The last entry is invalid now that it has been deleted or moved
- back */
- memset(adapter->scan_table + adapter->num_in_scan_table - 1,
- 0x00, sizeof(struct mwifiex_bssdescriptor));
-
- adapter->num_in_scan_table--;
-}
-
-/*
- * This function deletes all occurrences of a given SSID from the scan table.
- *
- * This iterates through the scan table and deletes all entries that match
- * the given SSID. It also compacts the remaining scan table entries.
- */
-static int
-mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *del_ssid)
-{
- s32 table_idx = -1;
-
- dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n",
- del_ssid->ssid);
-
- /* If the requested SSID is found in the table, delete it. Then keep
- searching the table for multiple entires for the SSID until no
- more are found */
- while ((table_idx = mwifiex_find_ssid_in_list(priv, del_ssid, NULL,
- NL80211_IFTYPE_UNSPECIFIED)) >= 0) {
- dev_dbg(priv->adapter->dev,
- "info: Scan: Delete SSID Entry: Found Idx = %d\n",
- table_idx);
- mwifiex_scan_delete_table_entry(priv, table_idx);
- }
-
- return table_idx == -1 ? -1 : 0;
-}
-
-/*
* This is an internal function used to start a scan based on an input
* configuration.
*
@@ -2248,8 +1293,8 @@ mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,
* order to send the appropriate scan commands to firmware to populate or
* update the internal driver scan table.
*/
-int mwifiex_scan_networks(struct mwifiex_private *priv,
- const struct mwifiex_user_scan_cfg *user_scan_in)
+static int mwifiex_scan_networks(struct mwifiex_private *priv,
+ const struct mwifiex_user_scan_cfg *user_scan_in)
{
int ret = 0;
struct mwifiex_adapter *adapter = priv->adapter;
@@ -2258,7 +1303,6 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
u32 buf_size;
struct mwifiex_chan_scan_param_set *scan_chan_list;
- u8 keep_previous_scan;
u8 filtered_scan;
u8 scan_current_chan_only;
u8 max_chan_per_scan;
@@ -2295,24 +1339,11 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
return -ENOMEM;
}
- keep_previous_scan = false;
-
mwifiex_scan_setup_scan_config(priv, user_scan_in,
&scan_cfg_out->config, &chan_list_out,
scan_chan_list, &max_chan_per_scan,
&filtered_scan, &scan_current_chan_only);
- if (user_scan_in)
- keep_previous_scan = user_scan_in->keep_previous_scan;
-
-
- if (!keep_previous_scan) {
- memset(adapter->scan_table, 0x00,
- sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP);
- adapter->num_in_scan_table = 0;
- adapter->bcn_buf_end = adapter->bcn_buf;
- }
-
ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
&scan_cfg_out->config, chan_list_out,
scan_chan_list);
@@ -2326,6 +1357,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
list_del(&cmd_node->list);
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
+ adapter->cmd_queued = cmd_node;
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
true);
} else {
@@ -2344,6 +1376,29 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
}
/*
+ * Sends IOCTL request to start a scan with user configurations.
+ *
+ * This function allocates the IOCTL request buffer, fills it
+ * with requisite parameters and calls the IOCTL handler.
+ *
+ * Upon completion, it also generates a wireless event to notify
+ * applications.
+ */
+int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
+ struct mwifiex_user_scan_cfg *scan_req)
+{
+ int status;
+
+ priv->adapter->scan_wait_q_woken = false;
+
+ status = mwifiex_scan_networks(priv, scan_req);
+ if (!status)
+ status = mwifiex_wait_queue_complete(priv->adapter);
+
+ return status;
+}
+
+/*
* This function prepares a scan command to be sent to the firmware.
*
* This uses the scan command configuration sent to the command processing
@@ -2379,6 +1434,112 @@ int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
}
/*
+ * This function checks compatibility of requested network with current
+ * driver settings.
+ */
+int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
+ struct mwifiex_bssdescriptor *bss_desc)
+{
+ int ret = -1;
+
+ if (!bss_desc)
+ return -1;
+
+ if ((mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
+ (u8) bss_desc->bss_band, (u16) bss_desc->channel))) {
+ switch (priv->bss_mode) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ ret = mwifiex_is_network_compatible(priv, bss_desc,
+ priv->bss_mode);
+ if (ret)
+ dev_err(priv->adapter->dev, "cannot find ssid "
+ "%s\n", bss_desc->ssid.ssid);
+ break;
+ default:
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+static int
+mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid,
+ s32 rssi, const u8 *ie_buf, size_t ie_len,
+ u16 beacon_period, u16 cap_info_bitmap, u8 band)
+{
+ struct mwifiex_bssdescriptor *bss_desc = NULL;
+ int ret;
+ unsigned long flags;
+ u8 *beacon_ie;
+
+ /* Allocate and fill new bss descriptor */
+ bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
+ GFP_KERNEL);
+ if (!bss_desc) {
+ dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
+ return -ENOMEM;
+ }
+
+ beacon_ie = kmemdup(ie_buf, ie_len, GFP_KERNEL);
+ if (!beacon_ie) {
+ dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
+ return -ENOMEM;
+ }
+
+ ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie,
+ ie_len, beacon_period,
+ cap_info_bitmap, band, bss_desc);
+ if (ret)
+ goto done;
+
+ ret = mwifiex_check_network_compatibility(priv, bss_desc);
+ if (ret)
+ goto done;
+
+ /* Update current bss descriptor parameters */
+ spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
+ priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
+ priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
+ priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
+ priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
+ priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
+ priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
+ priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
+ priv->curr_bss_params.bss_descriptor.ht_cap_offset =
+ 0;
+ priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL;
+ priv->curr_bss_params.bss_descriptor.ht_info_offset =
+ 0;
+ priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 =
+ NULL;
+ priv->curr_bss_params.bss_descriptor.
+ bss_co_2040_offset = 0;
+ priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
+ priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
+ priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
+ priv->curr_bss_params.bss_descriptor.beacon_buf_size =
+ 0;
+
+ /* Make a copy of current BSSID descriptor */
+ memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
+ sizeof(priv->curr_bss_params.bss_descriptor));
+ mwifiex_save_curr_bcn(priv);
+ spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
+
+done:
+ kfree(bss_desc);
+ kfree(beacon_ie);
+ return 0;
+}
+
+static void mwifiex_free_bss_priv(struct cfg80211_bss *bss)
+{
+ kfree(bss->priv);
+}
+
+/*
* This function handles the command response of scan.
*
* The response buffer for the scan command has the following
@@ -2404,23 +1565,19 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
struct mwifiex_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *cmd_node;
struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
- struct mwifiex_bssdescriptor *bss_new_entry = NULL;
struct mwifiex_ie_types_data *tlv_data;
struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
u8 *bss_info;
u32 scan_resp_size;
u32 bytes_left;
- u32 num_in_table;
- u32 bss_idx;
u32 idx;
u32 tlv_buf_size;
- long long tsf_val;
struct mwifiex_chan_freq_power *cfp;
struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
struct chan_band_param_set *chan_band;
- u8 band;
u8 is_bgscan_resp;
unsigned long flags;
+ struct cfg80211_bss *bss;
is_bgscan_resp = (le16_to_cpu(resp->command)
== HostCmd_CMD_802_11_BG_SCAN_QUERY);
@@ -2430,7 +1587,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
scan_rsp = &resp->params.scan_resp;
- if (scan_rsp->number_of_sets > IW_MAX_AP) {
+ if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",
scan_rsp->number_of_sets);
ret = -1;
@@ -2447,7 +1604,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
"info: SCAN_RESP: returned %d APs before parsing\n",
scan_rsp->number_of_sets);
- num_in_table = adapter->num_in_scan_table;
bss_info = scan_rsp->bss_desc_and_tlv_buffer;
/*
@@ -2479,125 +1635,149 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
(struct mwifiex_ie_types_data **)
&chan_band_tlv);
- /*
- * Process each scan response returned (scan_rsp->number_of_sets).
- * Save the information in the bss_new_entry and then insert into the
- * driver scan table either as an update to an existing entry
- * or as an addition at the end of the table
- */
- bss_new_entry = kzalloc(sizeof(struct mwifiex_bssdescriptor),
- GFP_KERNEL);
- if (!bss_new_entry) {
- dev_err(adapter->dev, " failed to alloc bss_new_entry\n");
- return -ENOMEM;
- }
-
for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
- /* Zero out the bss_new_entry we are about to store info in */
- memset(bss_new_entry, 0x00,
- sizeof(struct mwifiex_bssdescriptor));
-
- if (mwifiex_interpret_bss_desc_with_ie(adapter, bss_new_entry,
- &bss_info,
- &bytes_left)) {
- /* Error parsing/interpreting scan response, skipped */
- dev_err(adapter->dev, "SCAN_RESP: "
- "mwifiex_interpret_bss_desc_with_ie "
- "returned ERROR\n");
- continue;
+ u8 bssid[ETH_ALEN];
+ s32 rssi;
+ const u8 *ie_buf;
+ size_t ie_len;
+ int channel = -1;
+ u64 network_tsf = 0;
+ u16 beacon_size = 0;
+ u32 curr_bcn_bytes;
+ u32 freq;
+ u16 beacon_period;
+ u16 cap_info_bitmap;
+ u8 *current_ptr;
+ struct mwifiex_bcn_param *bcn_param;
+
+ if (bytes_left >= sizeof(beacon_size)) {
+ /* Extract & convert beacon size from command buffer */
+ memcpy(&beacon_size, bss_info, sizeof(beacon_size));
+ bytes_left -= sizeof(beacon_size);
+ bss_info += sizeof(beacon_size);
}
- /* Process the data fields and IEs returned for this BSS */
- dev_dbg(adapter->dev, "info: SCAN_RESP: BSSID = %pM\n",
- bss_new_entry->mac_address);
+ if (!beacon_size || beacon_size > bytes_left) {
+ bss_info += bytes_left;
+ bytes_left = 0;
+ return -1;
+ }
- /* Search the scan table for the same bssid */
- for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
- if (memcmp(bss_new_entry->mac_address,
- adapter->scan_table[bss_idx].mac_address,
- sizeof(bss_new_entry->mac_address))) {
- continue;
+ /* Initialize the current working beacon pointer for this BSS
+ * iteration */
+ current_ptr = bss_info;
+
+ /* Advance the return beacon pointer past the current beacon */
+ bss_info += beacon_size;
+ bytes_left -= beacon_size;
+
+ curr_bcn_bytes = beacon_size;
+
+ /*
+ * First 5 fields are bssid, RSSI, time stamp, beacon interval,
+ * and capability information
+ */
+ if (curr_bcn_bytes < sizeof(struct mwifiex_bcn_param)) {
+ dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
+ continue;
+ }
+ bcn_param = (struct mwifiex_bcn_param *)current_ptr;
+ current_ptr += sizeof(*bcn_param);
+ curr_bcn_bytes -= sizeof(*bcn_param);
+
+ memcpy(bssid, bcn_param->bssid, ETH_ALEN);
+
+ rssi = (s32) (bcn_param->rssi);
+ dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n",
+ rssi);
+
+ beacon_period = le16_to_cpu(bcn_param->beacon_period);
+
+ cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
+ dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
+ cap_info_bitmap);
+
+ /* Rest of the current buffer are IE's */
+ ie_buf = current_ptr;
+ ie_len = curr_bcn_bytes;
+ dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP"
+ " = %d\n", curr_bcn_bytes);
+
+ while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
+ u8 element_id, element_len;
+
+ element_id = *current_ptr;
+ element_len = *(current_ptr + 1);
+ if (curr_bcn_bytes < element_len +
+ sizeof(struct ieee_types_header)) {
+ dev_err(priv->adapter->dev, "%s: in processing"
+ " IE, bytes left < IE length\n",
+ __func__);
+ goto done;
}
- /*
- * If the SSID matches as well, it is a
- * duplicate of this entry. Keep the bss_idx
- * set to this entry so we replace the old
- * contents in the table
- */
- if ((bss_new_entry->ssid.ssid_len
- == adapter->scan_table[bss_idx]. ssid.ssid_len)
- && (!memcmp(bss_new_entry->ssid.ssid,
- adapter->scan_table[bss_idx].ssid.ssid,
- bss_new_entry->ssid.ssid_len))) {
- dev_dbg(adapter->dev, "info: SCAN_RESP:"
- " duplicate of index: %d\n", bss_idx);
+ if (element_id == WLAN_EID_DS_PARAMS) {
+ channel = *(u8 *) (current_ptr +
+ sizeof(struct ieee_types_header));
break;
}
- }
- /*
- * If the bss_idx is equal to the number of entries in
- * the table, the new entry was not a duplicate; append
- * it to the scan table
- */
- if (bss_idx == num_in_table) {
- /* Range check the bss_idx, keep it limited to
- the last entry */
- if (bss_idx == IW_MAX_AP)
- bss_idx--;
- else
- num_in_table++;
+
+ current_ptr += element_len +
+ sizeof(struct ieee_types_header);
+ curr_bcn_bytes -= element_len +
+ sizeof(struct ieee_types_header);
}
/*
- * Save the beacon/probe response returned for later application
- * retrieval. Duplicate beacon/probe responses are updated if
- * possible
- */
- mwifiex_ret_802_11_scan_store_beacon(priv, bss_idx,
- num_in_table, bss_new_entry);
- /*
* If the TSF TLV was appended to the scan results, save this
* entry's TSF value in the networkTSF field.The networkTSF is
* the firmware's TSF value at the time the beacon or probe
* response was received.
*/
- if (tsf_tlv) {
- memcpy(&tsf_val, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE]
- , sizeof(tsf_val));
- memcpy(&bss_new_entry->network_tsf, &tsf_val,
- sizeof(bss_new_entry->network_tsf));
- }
- band = BAND_G;
- if (chan_band_tlv) {
- chan_band = &chan_band_tlv->chan_band_param[idx];
- band = mwifiex_radio_type_to_band(chan_band->radio_type
- & (BIT(0) | BIT(1)));
- }
+ if (tsf_tlv)
+ memcpy(&network_tsf,
+ &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
+ sizeof(network_tsf));
+
+ if (channel != -1) {
+ struct ieee80211_channel *chan;
+ u8 band;
+
+ band = BAND_G;
+ if (chan_band_tlv) {
+ chan_band =
+ &chan_band_tlv->chan_band_param[idx];
+ band = mwifiex_radio_type_to_band(
+ chan_band->radio_type
+ & (BIT(0) | BIT(1)));
+ }
- /* Save the band designation for this entry for use in join */
- bss_new_entry->bss_band = band;
- cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
- (u8) bss_new_entry->bss_band,
- (u16)bss_new_entry->channel);
+ cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(
+ priv, (u8)band, (u16)channel);
- if (cfp)
- bss_new_entry->freq = cfp->freq;
- else
- bss_new_entry->freq = 0;
+ freq = cfp ? cfp->freq : 0;
- /* Copy the locally created bss_new_entry to the scan table */
- memcpy(&adapter->scan_table[bss_idx], bss_new_entry,
- sizeof(adapter->scan_table[bss_idx]));
+ chan = ieee80211_get_channel(priv->wdev->wiphy, freq);
- }
+ if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
+ bss = cfg80211_inform_bss(priv->wdev->wiphy,
+ chan, bssid, network_tsf,
+ cap_info_bitmap, beacon_period,
+ ie_buf, ie_len, rssi, GFP_KERNEL);
+ *(u8 *)bss->priv = band;
+ bss->free_priv = mwifiex_free_bss_priv;
- dev_dbg(adapter->dev,
- "info: SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
- scan_rsp->number_of_sets,
- num_in_table - adapter->num_in_scan_table, num_in_table);
-
- /* Update the total number of BSSIDs in the scan table */
- adapter->num_in_scan_table = num_in_table;
+ if (priv->media_connected && !memcmp(bssid,
+ priv->curr_bss_params.bss_descriptor
+ .mac_address, ETH_ALEN))
+ mwifiex_update_curr_bss_params(priv,
+ bssid, rssi, ie_buf,
+ ie_len, beacon_period,
+ cap_info_bitmap, band);
+ }
+ } else {
+ dev_dbg(adapter->dev, "missing BSS channel IE\n");
+ }
+ }
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
if (list_empty(&adapter->scan_pending_q)) {
@@ -2605,17 +1785,11 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->scan_processing = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
- /*
- * Process the resulting scan table:
- * - Remove any bad ssids
- * - Update our current BSS information from scan data
- */
- mwifiex_process_scan_results(priv);
/* Need to indicate IOCTL complete */
if (adapter->curr_cmd->wait_q_enabled) {
adapter->cmd_wait_q.status = 0;
- mwifiex_complete_cmd(adapter);
+ mwifiex_complete_cmd(adapter, adapter->curr_cmd);
}
if (priv->report_scan_result)
priv->report_scan_result = false;
@@ -2636,7 +1810,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
}
done:
- kfree((u8 *) bss_new_entry);
return ret;
}
@@ -2663,141 +1836,6 @@ int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
}
/*
- * This function finds a SSID in the scan table.
- *
- * A BSSID may optionally be provided to qualify the SSID.
- * For non-Auto mode, further check is made to make sure the
- * BSS found in the scan table is compatible with the current
- * settings of the driver.
- */
-s32
-mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
- struct mwifiex_802_11_ssid *ssid, u8 *bssid,
- u32 mode)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- s32 net = -1, j;
- u8 best_rssi = 0;
- u32 i;
-
- dev_dbg(adapter->dev, "info: num of entries in table = %d\n",
- adapter->num_in_scan_table);
-
- /*
- * Loop through the table until the maximum is reached or until a match
- * is found based on the bssid field comparison
- */
- for (i = 0;
- i < adapter->num_in_scan_table && (!bssid || (bssid && net < 0));
- i++) {
- if (!mwifiex_ssid_cmp(&adapter->scan_table[i].ssid, ssid) &&
- (!bssid
- || !memcmp(adapter->scan_table[i].mac_address, bssid,
- ETH_ALEN))
- &&
- (mwifiex_get_cfp_by_band_and_channel_from_cfg80211
- (priv, (u8) adapter->scan_table[i].bss_band,
- (u16) adapter->scan_table[i].channel))) {
- switch (mode) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- j = mwifiex_is_network_compatible(priv, i,
- mode);
-
- if (j >= 0) {
- if (SCAN_RSSI
- (adapter->scan_table[i].rssi) >
- best_rssi) {
- best_rssi = SCAN_RSSI(adapter->
- scan_table
- [i].rssi);
- net = i;
- }
- } else {
- if (net == -1)
- net = j;
- }
- break;
- case NL80211_IFTYPE_UNSPECIFIED:
- default:
- /*
- * Do not check compatibility if the mode
- * requested is Auto/Unknown. Allows generic
- * find to work without verifying against the
- * Adapter security settings
- */
- if (SCAN_RSSI(adapter->scan_table[i].rssi) >
- best_rssi) {
- best_rssi = SCAN_RSSI(adapter->
- scan_table[i].rssi);
- net = i;
- }
- break;
- }
- }
- }
-
- return net;
-}
-
-/*
- * This function finds a specific compatible BSSID in the scan list.
- *
- * This function loops through the scan table looking for a compatible
- * match. If a BSSID matches, but the BSS is found to be not compatible
- * the function ignores it and continues to search through the rest of
- * the entries in case there is an AP with multiple SSIDs assigned to
- * the same BSSID.
- */
-s32
-mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid,
- u32 mode)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- s32 net = -1;
- u32 i;
-
- if (!bssid)
- return -1;
-
- dev_dbg(adapter->dev, "info: FindBSSID: Num of BSSIDs = %d\n",
- adapter->num_in_scan_table);
-
- /*
- * Look through the scan table for a compatible match. The ret return
- * variable will be equal to the index in the scan table (greater
- * than zero) if the network is compatible. The loop will continue
- * past a matched bssid that is not compatible in case there is an
- * AP with multiple SSIDs assigned to the same BSSID
- */
- for (i = 0; net < 0 && i < adapter->num_in_scan_table; i++) {
- if (!memcmp
- (adapter->scan_table[i].mac_address, bssid, ETH_ALEN)
- && mwifiex_get_cfp_by_band_and_channel_from_cfg80211
- (priv,
- (u8) adapter->
- scan_table[i].
- bss_band,
- (u16) adapter->
- scan_table[i].
- channel)) {
- switch (mode) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- net = mwifiex_is_network_compatible(priv, i,
- mode);
- break;
- default:
- net = i;
- break;
- }
- }
- }
-
- return net;
-}
-
-/*
* This function inserts scan command node to the scan pending queue.
*/
void
@@ -2808,48 +1846,13 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
unsigned long flags;
cmd_node->wait_q_enabled = true;
+ cmd_node->condition = &adapter->scan_wait_q_woken;
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
}
/*
- * This function finds an AP with specific ssid in the scan list.
- */
-int mwifiex_find_best_network(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *req_ssid_bssid)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- struct mwifiex_bssdescriptor *req_bss;
- s32 i;
-
- memset(req_ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
-
- i = mwifiex_find_best_network_in_list(priv);
-
- if (i >= 0) {
- req_bss = &adapter->scan_table[i];
- memcpy(&req_ssid_bssid->ssid, &req_bss->ssid,
- sizeof(struct mwifiex_802_11_ssid));
- memcpy((u8 *) &req_ssid_bssid->bssid,
- (u8 *) &req_bss->mac_address, ETH_ALEN);
-
- /* Make sure we are in the right mode */
- if (priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED)
- priv->bss_mode = req_bss->bss_mode;
- }
-
- if (!req_ssid_bssid->ssid.ssid_len)
- return -1;
-
- dev_dbg(adapter->dev, "info: Best network found = [%s], "
- "[%pM]\n", req_ssid_bssid->ssid.ssid,
- req_ssid_bssid->bssid);
-
- return 0;
-}
-
-/*
* This function sends a scan command for all available channels to the
* firmware, filtered on a specific SSID.
*/
@@ -2874,8 +1877,6 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
return ret;
}
- mwifiex_scan_delete_ssid_table_entry(priv, req_ssid);
-
scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
if (!scan_cfg) {
dev_err(adapter->dev, "failed to alloc scan_cfg\n");
@@ -2884,7 +1885,6 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid,
req_ssid->ssid_len);
- scan_cfg->keep_previous_scan = true;
ret = mwifiex_scan_networks(priv, scan_cfg);
@@ -2913,7 +1913,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
}
priv->scan_pending_on_block = true;
- priv->adapter->cmd_wait_q.condition = false;
+ priv->adapter->scan_wait_q_woken = false;
if (req_ssid && req_ssid->ssid_len != 0)
/* Specific SSID scan */
@@ -2997,7 +1997,7 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
priv->curr_bcn_size = curr_bss->beacon_buf_size;
kfree(priv->curr_bcn_buf);
- priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size,
+ priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
GFP_KERNEL);
if (!priv->curr_bcn_buf) {
dev_err(priv->adapter->dev,
@@ -3010,6 +2010,39 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
curr_bss->beacon_buf_size);
dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n",
priv->curr_bcn_size);
+
+ curr_bss->beacon_buf = priv->curr_bcn_buf;
+
+ /* adjust the pointers in the current BSS descriptor */
+ if (curr_bss->bcn_wpa_ie)
+ curr_bss->bcn_wpa_ie =
+ (struct ieee_types_vendor_specific *)
+ (curr_bss->beacon_buf +
+ curr_bss->wpa_offset);
+
+ if (curr_bss->bcn_rsn_ie)
+ curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
+ (curr_bss->beacon_buf +
+ curr_bss->rsn_offset);
+
+ if (curr_bss->bcn_ht_cap)
+ curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
+ (curr_bss->beacon_buf +
+ curr_bss->ht_cap_offset);
+
+ if (curr_bss->bcn_ht_info)
+ curr_bss->bcn_ht_info = (struct ieee80211_ht_info *)
+ (curr_bss->beacon_buf +
+ curr_bss->ht_info_offset);
+
+ if (curr_bss->bcn_bss_co_2040)
+ curr_bss->bcn_bss_co_2040 =
+ (u8 *) (curr_bss->beacon_buf +
+ curr_bss->bss_co_2040_offset);
+
+ if (curr_bss->bcn_ext_cap)
+ curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf +
+ curr_bss->ext_cap_offset);
}
/*
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 82098ac483b8..283171bbcedf 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -89,7 +89,8 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
return -EIO;
}
- if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops)) {
+ if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
+ MWIFIEX_SDIO)) {
pr_err("%s: add card failed\n", __func__);
kfree(card);
sdio_claim_host(func);
@@ -830,7 +831,7 @@ done:
* The winner interface is also determined by this function.
*/
static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
- u32 poll_num, int *winner)
+ u32 poll_num)
{
int ret = 0;
u16 firmware_stat;
@@ -842,7 +843,7 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat);
if (ret)
continue;
- if (firmware_stat == FIRMWARE_READY) {
+ if (firmware_stat == FIRMWARE_READY_SDIO) {
ret = 0;
break;
} else {
@@ -851,15 +852,15 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter,
}
}
- if (winner && ret) {
+ if (ret) {
if (mwifiex_read_reg
(adapter, CARD_FW_STATUS0_REG, &winner_status))
winner_status = 0;
if (winner_status)
- *winner = 0;
+ adapter->winner = 0;
else
- *winner = 1;
+ adapter->winner = 1;
}
return ret;
}
@@ -1413,7 +1414,7 @@ tx_curr_single:
* the type. The firmware handles the packets based upon this set type.
*/
static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
- u8 type, u8 *payload, u32 pkt_len,
+ u8 type, struct sk_buff *skb,
struct mwifiex_tx_param *tx_param)
{
struct sdio_mmc_card *card = adapter->card;
@@ -1421,6 +1422,8 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
u32 buf_block_len;
u32 blk_size;
u8 port = CTRL_PORT;
+ u8 *payload = (u8 *)skb->data;
+ u32 pkt_len = skb->len;
/* Allocate buffer and copy payload */
blk_size = MWIFIEX_SDIO_BLOCK_SIZE;
@@ -1722,6 +1725,8 @@ static struct mwifiex_if_ops sdio_ops = {
/* SDIO specific */
.update_mp_end_port = mwifiex_update_mp_end_port,
.cleanup_mpa_buf = mwifiex_cleanup_mpa_buf,
+ .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
+ .event_complete = mwifiex_sdio_event_complete,
};
/*
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 524f78f4ee69..3f711801e58a 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -169,9 +169,6 @@
/* Rx unit register */
#define CARD_RX_UNIT_REG 0x63
-/* Event header len w/o 4 bytes of interface header */
-#define MWIFIEX_EVENT_HEADER_LEN 4
-
/* Max retry number of CMD53 write */
#define MAX_WRITE_IOMEM_RETRY 2
@@ -304,4 +301,25 @@ struct sdio_mmc_card {
struct mwifiex_sdio_mpa_tx mpa_tx;
struct mwifiex_sdio_mpa_rx mpa_rx;
};
+
+/*
+ * .cmdrsp_complete handler
+ */
+static inline int mwifiex_sdio_cmdrsp_complete(struct mwifiex_adapter *adapter,
+ struct sk_buff *skb)
+{
+ dev_kfree_skb_any(skb);
+ return 0;
+}
+
+/*
+ * .event_complete handler
+ */
+static inline int mwifiex_sdio_event_complete(struct mwifiex_adapter *adapter,
+ struct sk_buff *skb)
+{
+ dev_kfree_skb_any(skb);
+ return 0;
+}
+
#endif /* _MWIFIEX_SDIO_H */
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index c54ee287b878..ea6518d1c9e3 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -902,6 +902,59 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
}
/*
+ * This function prepares command to set PCI-Express
+ * host buffer configuration
+ *
+ * Preparation includes -
+ * - Setting command ID, action and proper size
+ * - Setting host buffer configuration
+ * - Ensuring correct endian-ness
+ */
+static int
+mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd, u16 action)
+{
+ struct host_cmd_ds_pcie_details *host_spec =
+ &cmd->params.pcie_host_spec;
+ struct pcie_service_card *card = priv->adapter->card;
+ phys_addr_t *buf_pa;
+
+ cmd->command = cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS);
+ cmd->size = cpu_to_le16(sizeof(struct
+ host_cmd_ds_pcie_details) + S_DS_GEN);
+ cmd->result = 0;
+
+ memset(host_spec, 0, sizeof(struct host_cmd_ds_pcie_details));
+
+ if (action == HostCmd_ACT_GEN_SET) {
+ /* Send the ring base addresses and count to firmware */
+ host_spec->txbd_addr_lo = (u32)(card->txbd_ring_pbase);
+ host_spec->txbd_addr_hi =
+ (u32)(((u64)card->txbd_ring_pbase)>>32);
+ host_spec->txbd_count = MWIFIEX_MAX_TXRX_BD;
+ host_spec->rxbd_addr_lo = (u32)(card->rxbd_ring_pbase);
+ host_spec->rxbd_addr_hi =
+ (u32)(((u64)card->rxbd_ring_pbase)>>32);
+ host_spec->rxbd_count = MWIFIEX_MAX_TXRX_BD;
+ host_spec->evtbd_addr_lo =
+ (u32)(card->evtbd_ring_pbase);
+ host_spec->evtbd_addr_hi =
+ (u32)(((u64)card->evtbd_ring_pbase)>>32);
+ host_spec->evtbd_count = MWIFIEX_MAX_EVT_BD;
+ if (card->sleep_cookie) {
+ buf_pa = MWIFIEX_SKB_PACB(card->sleep_cookie);
+ host_spec->sleep_cookie_addr_lo = (u32) *buf_pa;
+ host_spec->sleep_cookie_addr_hi =
+ (u32) (((u64)*buf_pa) >> 32);
+ dev_dbg(priv->adapter->dev, "sleep_cook_lo phy addr: "
+ "0x%x\n", host_spec->sleep_cookie_addr_lo);
+ }
+ }
+
+ return 0;
+}
+
+/*
* This function prepares the commands before sending them to the firmware.
*
* This is a generic function which calls specific command preparation
@@ -1079,6 +1132,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
host_cmd_ds_set_bss_mode) + S_DS_GEN);
ret = 0;
break;
+ case HostCmd_CMD_PCIE_DESC_DETAILS:
+ ret = mwifiex_cmd_pcie_host_spec(priv, cmd_ptr, cmd_action);
+ break;
default:
dev_err(priv->adapter->dev,
"PREP_CMD: unknown cmd- %#x\n", cmd_no);
@@ -1095,6 +1151,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
* working state.
*
* The following commands are issued sequentially -
+ * - Set PCI-Express host buffer configuration (PCIE only)
* - Function init (for first interface only)
* - Read MAC address (for first interface only)
* - Reconfigure Tx buffer size (for first interface only)
@@ -1116,6 +1173,13 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
struct mwifiex_ds_11n_tx_cfg tx_cfg;
if (first_sta) {
+ if (priv->adapter->iface_type == MWIFIEX_PCIE) {
+ ret = mwifiex_send_cmd_async(priv,
+ HostCmd_CMD_PCIE_DESC_DETAILS,
+ HostCmd_ACT_GEN_SET, 0, NULL);
+ if (ret)
+ return -1;
+ }
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_FUNC_INIT,
HostCmd_ACT_GEN_SET, 0, NULL);
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 6804239d87bd..7a16b0c417af 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -952,6 +952,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
case HostCmd_CMD_11N_CFG:
ret = mwifiex_ret_11n_cfg(resp, data_buf);
break;
+ case HostCmd_CMD_PCIE_DESC_DETAILS:
+ break;
default:
dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
resp->command);
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index fc265cab0907..f204810e8338 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -130,8 +130,8 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv)
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
/* Reset wireless stats signal info */
- priv->w_stats.qual.level = 0;
- priv->w_stats.qual.noise = 0;
+ priv->qual_level = 0;
+ priv->qual_noise = 0;
}
/*
@@ -299,11 +299,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
case EVENT_BG_SCAN_REPORT:
dev_dbg(adapter->dev, "event: BGS_REPORT\n");
- /* Clear the previous scan result */
- memset(adapter->scan_table, 0x00,
- sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP);
- adapter->num_in_scan_table = 0;
- adapter->bcn_buf_end = adapter->bcn_buf;
ret = mwifiex_send_cmd_async(priv,
HostCmd_CMD_802_11_BG_SCAN_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index c34ff8c4f4f8..ea4a29b7e331 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -55,7 +55,9 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
{
bool cancel_flag = false;
int status = adapter->cmd_wait_q.status;
+ struct cmd_ctrl_node *cmd_queued = adapter->cmd_queued;
+ adapter->cmd_queued = NULL;
dev_dbg(adapter->dev, "cmd pending\n");
atomic_inc(&adapter->cmd_pending);
@@ -64,8 +66,8 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
/* Wait for completion */
wait_event_interruptible(adapter->cmd_wait_q.wait,
- adapter->cmd_wait_q.condition);
- if (!adapter->cmd_wait_q.condition)
+ *(cmd_queued->condition));
+ if (!*(cmd_queued->condition))
cancel_flag = true;
if (cancel_flag) {
@@ -142,90 +144,146 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
}
/*
+ * This function fills bss descriptor structure using provided
+ * information.
+ */
+int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
+ u8 *bssid, s32 rssi, u8 *ie_buf,
+ size_t ie_len, u16 beacon_period,
+ u16 cap_info_bitmap, u8 band,
+ struct mwifiex_bssdescriptor *bss_desc)
+{
+ int ret;
+
+ memcpy(bss_desc->mac_address, bssid, ETH_ALEN);
+ bss_desc->rssi = rssi;
+ bss_desc->beacon_buf = ie_buf;
+ bss_desc->beacon_buf_size = ie_len;
+ bss_desc->beacon_period = beacon_period;
+ bss_desc->cap_info_bitmap = cap_info_bitmap;
+ bss_desc->bss_band = band;
+ if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
+ dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n");
+ bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
+ } else {
+ bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
+ }
+ if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
+ bss_desc->bss_mode = NL80211_IFTYPE_ADHOC;
+ else
+ bss_desc->bss_mode = NL80211_IFTYPE_STATION;
+
+ ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc,
+ ie_buf, ie_len);
+
+ return ret;
+}
+
+/*
* In Ad-Hoc mode, the IBSS is created if not found in scan list.
* In both Ad-Hoc and infra mode, an deauthentication is performed
* first.
*/
-int mwifiex_bss_start(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *ssid_bssid)
+int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
+ struct mwifiex_802_11_ssid *req_ssid)
{
int ret;
struct mwifiex_adapter *adapter = priv->adapter;
- s32 i = -1;
+ struct mwifiex_bssdescriptor *bss_desc = NULL;
+ u8 *beacon_ie = NULL;
priv->scan_block = false;
- if (!ssid_bssid)
- return -1;
+
+ if (bss) {
+ /* Allocate and fill new bss descriptor */
+ bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
+ GFP_KERNEL);
+ if (!bss_desc) {
+ dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
+ return -ENOMEM;
+ }
+
+ beacon_ie = kmemdup(bss->information_elements,
+ bss->len_beacon_ies, GFP_KERNEL);
+ if (!beacon_ie) {
+ kfree(bss_desc);
+ dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
+ return -ENOMEM;
+ }
+
+ ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal,
+ beacon_ie, bss->len_beacon_ies,
+ bss->beacon_interval,
+ bss->capability,
+ *(u8 *)bss->priv, bss_desc);
+ if (ret)
+ goto done;
+ }
if (priv->bss_mode == NL80211_IFTYPE_STATION) {
/* Infra mode */
ret = mwifiex_deauthenticate(priv, NULL);
if (ret)
- return ret;
+ goto done;
- /* Search for the requested SSID in the scan table */
- if (ssid_bssid->ssid.ssid_len)
- i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid,
- NULL, NL80211_IFTYPE_STATION);
- else
- i = mwifiex_find_bssid_in_list(priv,
- (u8 *) &ssid_bssid->bssid,
- NL80211_IFTYPE_STATION);
- if (i < 0)
- return -1;
+ ret = mwifiex_check_network_compatibility(priv, bss_desc);
+ if (ret)
+ goto done;
- dev_dbg(adapter->dev,
- "info: SSID found in scan list ... associating...\n");
+ dev_dbg(adapter->dev, "info: SSID found in scan list ... "
+ "associating...\n");
+
+ if (!netif_queue_stopped(priv->netdev))
+ netif_stop_queue(priv->netdev);
/* Clear any past association response stored for
* application retrieval */
priv->assoc_rsp_size = 0;
- ret = mwifiex_associate(priv, &adapter->scan_table[i]);
- if (ret)
- return ret;
+ ret = mwifiex_associate(priv, bss_desc);
+ if (bss)
+ cfg80211_put_bss(bss);
} else {
/* Adhoc mode */
/* If the requested SSID matches current SSID, return */
- if (ssid_bssid->ssid.ssid_len &&
+ if (bss_desc && bss_desc->ssid.ssid_len &&
(!mwifiex_ssid_cmp
(&priv->curr_bss_params.bss_descriptor.ssid,
- &ssid_bssid->ssid)))
+ &bss_desc->ssid))) {
+ kfree(bss_desc);
+ kfree(beacon_ie);
return 0;
+ }
/* Exit Adhoc mode first */
dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
ret = mwifiex_deauthenticate(priv, NULL);
if (ret)
- return ret;
+ goto done;
priv->adhoc_is_link_sensed = false;
- /* Search for the requested network in the scan table */
- if (ssid_bssid->ssid.ssid_len)
- i = mwifiex_find_ssid_in_list(priv,
- &ssid_bssid->ssid, NULL,
- NL80211_IFTYPE_ADHOC);
- else
- i = mwifiex_find_bssid_in_list(priv,
- (u8 *)&ssid_bssid->bssid,
- NL80211_IFTYPE_ADHOC);
+ ret = mwifiex_check_network_compatibility(priv, bss_desc);
+
+ if (!netif_queue_stopped(priv->netdev))
+ netif_stop_queue(priv->netdev);
- if (i >= 0) {
+ if (!ret) {
dev_dbg(adapter->dev, "info: network found in scan"
" list. Joining...\n");
- ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]);
- if (ret)
- return ret;
+ ret = mwifiex_adhoc_join(priv, bss_desc);
+ if (bss)
+ cfg80211_put_bss(bss);
} else {
dev_dbg(adapter->dev, "info: Network not found in "
"the list, creating adhoc with ssid = %s\n",
- ssid_bssid->ssid.ssid);
- ret = mwifiex_adhoc_start(priv, &ssid_bssid->ssid);
- if (ret)
- return ret;
+ req_ssid->ssid);
+ ret = mwifiex_adhoc_start(priv, req_ssid);
}
}
+done:
+ kfree(bss_desc);
+ kfree(beacon_ie);
return ret;
}
@@ -235,8 +293,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv,
* This function prepares the correct firmware command and
* issues it.
*/
-int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
- int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
+static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
+ int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
{
struct mwifiex_adapter *adapter = priv->adapter;
@@ -376,7 +434,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
{
struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_bssdescriptor *bss_desc;
- s32 tbl_idx;
if (!info)
return -1;
@@ -394,17 +451,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
info->region_code = adapter->region_code;
- /* Scan table index if connected */
- info->scan_table_idx = 0;
- if (priv->media_connected) {
- tbl_idx =
- mwifiex_find_ssid_in_list(priv, &bss_desc->ssid,
- bss_desc->mac_address,
- priv->bss_mode);
- if (tbl_idx >= 0)
- info->scan_table_idx = tbl_idx;
- }
-
info->media_connected = priv->media_connected;
info->max_power_level = priv->max_tx_power_level;
@@ -586,50 +632,6 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,
}
/*
- * IOCTL request handler to find a particular BSS.
- *
- * The BSS can be searched with either a BSSID or a SSID. If none of
- * these are provided, just the best BSS (best RSSI) is returned.
- */
-int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv,
- struct mwifiex_ssid_bssid *ssid_bssid)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- struct mwifiex_bssdescriptor *bss_desc;
- u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
- u8 mac[ETH_ALEN];
- int i = 0;
-
- if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) {
- i = mwifiex_find_bssid_in_list(priv,
- (u8 *) ssid_bssid->bssid,
- priv->bss_mode);
- if (i < 0) {
- memcpy(mac, ssid_bssid->bssid, sizeof(mac));
- dev_err(adapter->dev, "cannot find bssid %pM\n", mac);
- return -1;
- }
- bss_desc = &adapter->scan_table[i];
- memcpy(&ssid_bssid->ssid, &bss_desc->ssid,
- sizeof(struct mwifiex_802_11_ssid));
- } else if (ssid_bssid->ssid.ssid_len) {
- i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, NULL,
- priv->bss_mode);
- if (i < 0) {
- dev_err(adapter->dev, "cannot find ssid %s\n",
- ssid_bssid->ssid.ssid);
- return -1;
- }
- bss_desc = &adapter->scan_table[i];
- memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN);
- } else {
- return mwifiex_find_best_network(priv, ssid_bssid);
- }
-
- return 0;
-}
-
-/*
* IOCTL request handler to change Ad-Hoc channel.
*
* This function allocates the IOCTL request buffer, fills it
@@ -653,6 +655,9 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
struct mwifiex_bss_info bss_info;
struct mwifiex_ssid_bssid ssid_bssid;
u16 curr_chan = 0;
+ struct cfg80211_bss *bss = NULL;
+ struct ieee80211_channel *chan;
+ enum ieee80211_band band;
memset(&bss_info, 0, sizeof(bss_info));
@@ -688,12 +693,20 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
ret = -1;
goto done;
}
- /* Start/Join Adhoc network */
- memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
- memcpy(&ssid_bssid.ssid, &bss_info.ssid,
- sizeof(struct mwifiex_802_11_ssid));
- ret = mwifiex_bss_start(priv, &ssid_bssid);
+ band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+ chan = __ieee80211_get_channel(priv->wdev->wiphy,
+ ieee80211_channel_to_frequency(channel, band));
+
+ /* Find the BSS we want using available scan results */
+ bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid,
+ bss_info.ssid.ssid, bss_info.ssid.ssid_len,
+ WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+ if (!bss)
+ wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n",
+ bss_info.bssid);
+
+ ret = mwifiex_bss_start(priv, bss, &bss_info.ssid);
done:
return ret;
}
@@ -709,51 +722,9 @@ done:
static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate_cfg)
{
- struct mwifiex_adapter *adapter = priv->adapter;
-
rate_cfg->is_rate_auto = priv->is_data_rate_auto;
- if (!priv->media_connected) {
- switch (adapter->config_bands) {
- case BAND_B:
- /* Return the lowest supported rate for B band */
- rate_cfg->rate = supported_rates_b[0] & 0x7f;
- break;
- case BAND_G:
- case BAND_G | BAND_GN:
- /* Return the lowest supported rate for G band */
- rate_cfg->rate = supported_rates_g[0] & 0x7f;
- break;
- case BAND_B | BAND_G:
- case BAND_A | BAND_B | BAND_G:
- case BAND_A | BAND_B:
- case BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN:
- case BAND_B | BAND_G | BAND_GN:
- /* Return the lowest supported rate for BG band */
- rate_cfg->rate = supported_rates_bg[0] & 0x7f;
- break;
- case BAND_A:
- case BAND_A | BAND_G:
- case BAND_A | BAND_G | BAND_AN | BAND_GN:
- case BAND_A | BAND_AN:
- /* Return the lowest supported rate for A band */
- rate_cfg->rate = supported_rates_a[0] & 0x7f;
- break;
- case BAND_GN:
- /* Return the lowest supported rate for N band */
- rate_cfg->rate = supported_rates_n[0] & 0x7f;
- break;
- default:
- dev_warn(adapter->dev, "invalid band %#x\n",
- adapter->config_bands);
- break;
- }
- } else {
- return mwifiex_send_cmd_sync(priv,
- HostCmd_CMD_802_11_TX_RATE_QUERY,
- HostCmd_ACT_GEN_GET, 0, NULL);
- }
-
- return 0;
+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+ HostCmd_ACT_GEN_GET, 0, NULL);
}
/*
@@ -794,7 +765,7 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,
if ((rate[i] & 0x7f) == (rate_cfg->rate & 0x7f))
break;
}
- if (!rate[i] || (i == MWIFIEX_SUPPORTED_RATES)) {
+ if ((i == MWIFIEX_SUPPORTED_RATES) || !rate[i]) {
dev_err(adapter->dev, "fixed data rate %#x is out "
"of range\n", rate_cfg->rate);
return -1;
@@ -860,10 +831,10 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
ret = mwifiex_rate_ioctl_cfg(priv, rate);
if (!ret) {
- if (rate && rate->is_rate_auto)
+ if (rate->is_rate_auto)
rate->rate = mwifiex_index_to_data_rate(priv->tx_rate,
priv->tx_htinfo);
- else if (rate)
+ else
rate->rate = priv->data_rate;
} else {
ret = -1;
@@ -1280,9 +1251,9 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv,
if (!status) {
if (signal->selector & BCN_RSSI_AVG_MASK)
- priv->w_stats.qual.level = signal->bcn_rssi_avg;
+ priv->qual_level = signal->bcn_rssi_avg;
if (signal->selector & BCN_NF_AVG_MASK)
- priv->w_stats.qual.noise = signal->bcn_nf_avg;
+ priv->qual_noise = signal->bcn_nf_avg;
}
return status;
@@ -1341,18 +1312,8 @@ int
mwifiex_get_stats_info(struct mwifiex_private *priv,
struct mwifiex_ds_get_stats *log)
{
- int ret;
-
- ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG,
+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG,
HostCmd_ACT_GEN_GET, 0, log);
-
- if (!ret) {
- priv->w_stats.discard.fragment = log->fcs_error;
- priv->w_stats.discard.retries = log->retry;
- priv->w_stats.discard.misc = log->ack_failure;
- }
-
- return ret;
}
/*
@@ -1594,7 +1555,7 @@ mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)
{
struct mwifiex_ds_misc_gen_ie gen_ie;
- if (ie_len > IW_CUSTOM_MAX)
+ if (ie_len > IEEE_MAX_IE_SIZE)
return -EFAULT;
gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE;
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index 1822bfad8896..d97facd70e88 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -151,7 +151,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
skb_push(skb, INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
- skb->data, skb->len, NULL);
+ skb, NULL);
switch (ret) {
case -EBUSY:
adapter->data_sent = true;
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index 6190b2fa57a3..a206f412875f 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -78,7 +78,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
(struct txpd *) (head_ptr + INTF_HEADER_LEN);
ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
- skb->data, skb->len, tx_param);
+ skb, tx_param);
}
switch (ret) {
@@ -87,7 +87,8 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
(adapter->pps_uapsd_mode) &&
(adapter->tx_lock_flag)) {
priv->adapter->tx_lock_flag = false;
- local_tx_pd->flags = 0;
+ if (local_tx_pd)
+ local_tx_pd->flags = 0;
}
dev_dbg(adapter->dev, "data: -EBUSY is returned\n");
break;
@@ -160,43 +161,3 @@ done:
return 0;
}
-/*
- * Packet receive completion callback handler.
- *
- * This function calls another completion callback handler which
- * updates the statistics, and optionally updates the parent buffer
- * use count before freeing the received packet.
- */
-int mwifiex_recv_packet_complete(struct mwifiex_adapter *adapter,
- struct sk_buff *skb, int status)
-{
- struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
- struct mwifiex_rxinfo *rx_info_parent;
- struct mwifiex_private *priv;
- struct sk_buff *skb_parent;
- unsigned long flags;
-
- priv = adapter->priv[rx_info->bss_index];
-
- if (priv && (status == -1))
- priv->stats.rx_dropped++;
-
- if (rx_info->parent) {
- skb_parent = rx_info->parent;
- rx_info_parent = MWIFIEX_SKB_RXCB(skb_parent);
-
- spin_lock_irqsave(&priv->rx_pkt_lock, flags);
- --rx_info_parent->use_count;
-
- if (!rx_info_parent->use_count) {
- spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
- dev_kfree_skb_any(skb_parent);
- } else {
- spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
- }
- } else {
- dev_kfree_skb_any(skb);
- }
-
- return 0;
-}
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index d41291529bc0..06976f517f66 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -185,13 +185,14 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb)
* corresponding waiting function. Otherwise, it processes the
* IOCTL response and frees the response buffer.
*/
-int mwifiex_complete_cmd(struct mwifiex_adapter *adapter)
+int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
+ struct cmd_ctrl_node *cmd_node)
{
atomic_dec(&adapter->cmd_pending);
dev_dbg(adapter->dev, "cmd completed: status=%d\n",
adapter->cmd_wait_q.status);
- adapter->cmd_wait_q.condition = true;
+ *(cmd_node->condition) = true;
if (adapter->cmd_wait_q.status == -ETIMEDOUT)
dev_err(adapter->dev, "cmd timeout\n");
diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h
index 9506afc6c0e4..f6d36b9654a0 100644
--- a/drivers/net/wireless/mwifiex/util.h
+++ b/drivers/net/wireless/mwifiex/util.h
@@ -22,11 +22,16 @@
static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb)
{
- return (struct mwifiex_rxinfo *)skb->cb;
+ return (struct mwifiex_rxinfo *)(skb->cb + sizeof(phys_addr_t));
}
static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb)
{
- return (struct mwifiex_txinfo *)skb->cb;
+ return (struct mwifiex_txinfo *)(skb->cb + sizeof(phys_addr_t));
+}
+
+static inline phys_addr_t *MWIFIEX_SKB_PACB(struct sk_buff *skb)
+{
+ return (phys_addr_t *)skb->cb;
}
#endif /* !_MWIFIEX_UTIL_H_ */
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 69e260b41711..6c239c3c8249 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -121,7 +121,6 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
memcpy(ra_list->ra, ra, ETH_ALEN);
ra_list->total_pkts_size = 0;
- ra_list->total_pkts = 0;
dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list);
@@ -648,7 +647,6 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter,
skb_queue_tail(&ra_list->skb_head, skb);
ra_list->total_pkts_size += skb->len;
- ra_list->total_pkts++;
atomic_inc(&priv->wmm.tx_pkts_queued);
@@ -975,6 +973,28 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
}
/*
+ * This function checks if 11n aggregation is possible.
+ */
+static int
+mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv,
+ struct mwifiex_ra_list_tbl *ptr,
+ int max_buf_size)
+{
+ int count = 0, total_size = 0;
+ struct sk_buff *skb, *tmp;
+
+ skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
+ total_size += skb->len;
+ if (total_size >= max_buf_size)
+ break;
+ if (++count >= MIN_NUM_AMSDU)
+ return true;
+ }
+
+ return false;
+}
+
+/*
* This function sends a single packet to firmware for transmission.
*/
static void
@@ -1001,7 +1021,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb);
ptr->total_pkts_size -= skb->len;
- ptr->total_pkts--;
if (!skb_queue_empty(&ptr->skb_head))
skb_next = skb_peek(&ptr->skb_head);
@@ -1027,7 +1046,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
skb_queue_tail(&ptr->skb_head, skb);
ptr->total_pkts_size += skb->len;
- ptr->total_pkts++;
tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
@@ -1107,8 +1125,8 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
tx_param.next_pkt_len =
((skb_next) ? skb_next->len +
sizeof(struct txpd) : 0);
- ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
- skb->data, skb->len, &tx_param);
+ ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, skb,
+ &tx_param);
switch (ret) {
case -EBUSY:
dev_dbg(adapter->dev, "data: -EBUSY is returned\n");
@@ -1213,11 +1231,9 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
mwifiex_send_delba(priv, tid_del, ra, 1);
}
}
-/* Minimum number of AMSDU */
-#define MIN_NUM_AMSDU 2
-
if (mwifiex_is_amsdu_allowed(priv, tid) &&
- (ptr->total_pkts >= MIN_NUM_AMSDU))
+ mwifiex_is_11n_aggragation_possible(priv, ptr,
+ adapter->tx_buf_size))
mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN,
ptr_index, flags);
/* ra_list_spinlock has been freed in
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index da36dbf8d871..995695c28d5c 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -4097,9 +4097,6 @@ static int mwl8k_set_key(struct ieee80211_hw *hw,
if (rc)
goto out;
-
- mwl8k_vif->is_hw_crypto_enabled = false;
-
}
out:
return rc;
@@ -4918,7 +4915,8 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw,
return ret;
}
-static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int mwl8k_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mwl8k_priv *priv = hw->priv;
@@ -5465,7 +5463,7 @@ static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image)
goto fail;
for (i = 0; i < MWL8K_TX_WMM_QUEUES; i++) {
- rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]);
+ rc = mwl8k_conf_tx(hw, NULL, i, &priv->wmm_params[i]);
if (rc)
goto fail;
}
@@ -5504,6 +5502,14 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
/* Set rssi values to dBm */
hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL;
+
+ /*
+ * Ask mac80211 to not to trigger PS mode
+ * based on PM bit of incoming frames.
+ */
+ if (priv->ap_fw)
+ hw->flags |= IEEE80211_HW_AP_LINK_PS;
+
hw->vif_data_size = sizeof(struct mwl8k_vif);
hw->sta_data_size = sizeof(struct mwl8k_sta);
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index ef7efe839bb8..b52acc4b4086 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -2135,7 +2135,7 @@ static const struct net_device_ops orinoco_netdev_ops = {
.ndo_open = orinoco_open,
.ndo_stop = orinoco_stop,
.ndo_start_xmit = orinoco_xmit,
- .ndo_set_multicast_list = orinoco_set_multicast_list,
+ .ndo_set_rx_mode = orinoco_set_multicast_list,
.ndo_change_mtu = orinoco_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index 811e87f8a349..0793e4265b43 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -1562,7 +1562,7 @@ static const struct net_device_ops ezusb_netdev_ops = {
.ndo_open = orinoco_open,
.ndo_stop = orinoco_stop,
.ndo_start_xmit = ezusb_xmit,
- .ndo_set_multicast_list = orinoco_set_multicast_list,
+ .ndo_set_rx_mode = orinoco_set_multicast_list,
.ndo_change_mtu = orinoco_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index bbb9beb206b1..33747e131a96 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -9,6 +9,7 @@
#include <linux/ieee80211.h>
#include <net/iw_handler.h>
#include <net/cfg80211.h>
+#include <net/cfg80211-wext.h>
#include "hermes.h"
#include "hermes_rid.h"
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index 54cc0bba66b9..8b6f363b3f7d 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -145,6 +145,7 @@ static int p54_fill_band_bitrates(struct ieee80211_hw *dev,
static int p54_generate_band(struct ieee80211_hw *dev,
struct p54_channel_list *list,
+ unsigned int *chan_num,
enum ieee80211_band band)
{
struct p54_common *priv = dev->priv;
@@ -190,7 +191,14 @@ static int p54_generate_band(struct ieee80211_hw *dev,
tmp->channels[j].band = chan->band;
tmp->channels[j].center_freq = chan->freq;
+ priv->survey[*chan_num].channel = &tmp->channels[j];
+ priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM |
+ SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ tmp->channels[j].hw_value = (*chan_num);
j++;
+ (*chan_num)++;
}
if (j == 0) {
@@ -263,7 +271,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
struct p54_channel_list *list;
- unsigned int i, j, max_channel_num;
+ unsigned int i, j, k, max_channel_num;
int ret = 0;
u16 freq;
@@ -283,6 +291,13 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
ret = -ENOMEM;
goto free;
}
+ priv->chan_num = max_channel_num;
+ priv->survey = kzalloc(sizeof(struct survey_info) * max_channel_num,
+ GFP_KERNEL);
+ if (!priv->survey) {
+ ret = -ENOMEM;
+ goto free;
+ }
list->max_entries = max_channel_num;
list->channels = kzalloc(sizeof(struct p54_channel_entry) *
@@ -321,8 +336,9 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
sort(list->channels, list->entries, sizeof(struct p54_channel_entry),
p54_compare_channels, NULL);
+ k = 0;
for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) {
- if (p54_generate_band(dev, list, i) == 0)
+ if (p54_generate_band(dev, list, &k, i) == 0)
j++;
}
if (j == 0) {
@@ -335,6 +351,10 @@ free:
kfree(list->channels);
kfree(list);
}
+ if (ret) {
+ kfree(priv->survey);
+ priv->survey = NULL;
+ }
return ret;
}
@@ -853,10 +873,12 @@ err:
kfree(priv->output_limit);
kfree(priv->curve_data);
kfree(priv->rssi_db);
+ kfree(priv->survey);
priv->iq_autocal = NULL;
priv->output_limit = NULL;
priv->curve_data = NULL;
priv->rssi_db = NULL;
+ priv->survey = NULL;
wiphy_err(dev->wiphy, "eeprom parse failed!\n");
return err;
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index b6a061cbbdec..53a3408931be 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -385,6 +385,7 @@ int p54_setup_mac(struct p54_common *priv)
setup->v2.osc_start_delay = cpu_to_le16(65535);
}
p54_tx(priv, skb);
+ priv->phy_idle = mode == P54_FILTER_TYPE_HIBERNATE;
return 0;
}
@@ -626,6 +627,7 @@ int p54_set_ps(struct p54_common *priv)
psm->exclude[0] = WLAN_EID_TIM;
p54_tx(priv, skb);
+ priv->phy_ps = mode != P54_PSM_CAM;
return 0;
}
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index a5a6d9e647bb..ad9ae04d07aa 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -204,13 +204,11 @@ static void p54_stop(struct ieee80211_hw *dev)
struct p54_common *priv = dev->priv;
int i;
- mutex_lock(&priv->conf_mutex);
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
priv->softled_state = 0;
- p54_set_leds(priv);
-
cancel_delayed_work_sync(&priv->work);
-
+ mutex_lock(&priv->conf_mutex);
+ p54_set_leds(priv);
priv->stop(dev);
skb_queue_purge(&priv->tx_pending);
skb_queue_purge(&priv->tx_queue);
@@ -278,6 +276,42 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
mutex_unlock(&priv->conf_mutex);
}
+static int p54_wait_for_stats(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+ int ret;
+
+ priv->update_stats = true;
+ ret = p54_fetch_statistics(priv);
+ if (ret)
+ return ret;
+
+ ret = wait_for_completion_interruptible_timeout(&priv->stat_comp, HZ);
+ if (ret == 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static void p54_reset_stats(struct p54_common *priv)
+{
+ struct ieee80211_channel *chan = priv->curchan;
+
+ if (chan) {
+ struct survey_info *info = &priv->survey[chan->hw_value];
+
+ /* only reset channel statistics, don't touch .filled, etc. */
+ info->channel_time = 0;
+ info->channel_time_busy = 0;
+ info->channel_time_tx = 0;
+ }
+
+ priv->update_stats = true;
+ priv->survey_raw.active = 0;
+ priv->survey_raw.cca = 0;
+ priv->survey_raw.tx = 0;
+}
+
static int p54_config(struct ieee80211_hw *dev, u32 changed)
{
int ret = 0;
@@ -288,19 +322,36 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_POWER)
priv->output_power = conf->power_level << 2;
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ struct ieee80211_channel *oldchan;
+ WARN_ON(p54_wait_for_stats(dev));
+ oldchan = priv->curchan;
+ priv->curchan = NULL;
ret = p54_scan(priv, P54_SCAN_EXIT, 0);
- if (ret)
+ if (ret) {
+ priv->curchan = oldchan;
goto out;
+ }
+ /*
+ * TODO: Use the LM_SCAN_TRAP to determine the current
+ * operating channel.
+ */
+ priv->curchan = priv->hw->conf.channel;
+ p54_reset_stats(priv);
+ WARN_ON(p54_fetch_statistics(priv));
}
if (changed & IEEE80211_CONF_CHANGE_PS) {
+ WARN_ON(p54_wait_for_stats(dev));
ret = p54_set_ps(priv);
if (ret)
goto out;
+ WARN_ON(p54_wait_for_stats(dev));
}
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+ WARN_ON(p54_wait_for_stats(dev));
ret = p54_setup_mac(priv);
if (ret)
goto out;
+ WARN_ON(p54_wait_for_stats(dev));
}
out:
@@ -353,7 +404,8 @@ static void p54_configure_filter(struct ieee80211_hw *dev,
p54_set_groupfilter(priv);
}
-static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
+static int p54_conf_tx(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct p54_common *priv = dev->priv;
@@ -384,7 +436,9 @@ static void p54_work(struct work_struct *work)
* 2. cancel stuck frames / reset the device if necessary.
*/
- p54_fetch_statistics(priv);
+ mutex_lock(&priv->conf_mutex);
+ WARN_ON_ONCE(p54_fetch_statistics(priv));
+ mutex_unlock(&priv->conf_mutex);
}
static int p54_get_stats(struct ieee80211_hw *dev,
@@ -541,16 +595,47 @@ static int p54_get_survey(struct ieee80211_hw *dev, int idx,
struct survey_info *survey)
{
struct p54_common *priv = dev->priv;
- struct ieee80211_conf *conf = &dev->conf;
+ struct ieee80211_channel *chan;
+ int err, tries;
+ bool in_use = false;
- if (idx != 0)
+ if (idx >= priv->chan_num)
return -ENOENT;
- survey->channel = conf->channel;
- survey->filled = SURVEY_INFO_NOISE_DBM;
- survey->noise = clamp_t(s8, priv->noise, -128, 127);
+#define MAX_TRIES 1
+ for (tries = 0; tries < MAX_TRIES; tries++) {
+ chan = priv->curchan;
+ if (chan && chan->hw_value == idx) {
+ mutex_lock(&priv->conf_mutex);
+ err = p54_wait_for_stats(dev);
+ mutex_unlock(&priv->conf_mutex);
+ if (err)
+ return err;
+
+ in_use = true;
+ }
- return 0;
+ memcpy(survey, &priv->survey[idx], sizeof(*survey));
+
+ if (in_use) {
+ /* test if the reported statistics are valid. */
+ if (survey->channel_time != 0) {
+ survey->filled |= SURVEY_INFO_IN_USE;
+ } else {
+ /*
+ * hw/fw has not accumulated enough sample sets.
+ * Wait for 100ms, this ought to be enough to
+ * to get at least one non-null set of channel
+ * usage statistics.
+ */
+ msleep(100);
+ continue;
+ }
+ }
+ return 0;
+ }
+ return -ETIMEDOUT;
+#undef MAX_TRIES
}
static unsigned int p54_flush_count(struct p54_common *priv)
@@ -686,11 +771,14 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
mutex_init(&priv->conf_mutex);
mutex_init(&priv->eeprom_mutex);
+ init_completion(&priv->stat_comp);
init_completion(&priv->eeprom_comp);
init_completion(&priv->beacon_comp);
INIT_DELAYED_WORK(&priv->work, p54_work);
memset(&priv->mc_maclist[0], ~0, ETH_ALEN);
+ priv->curchan = NULL;
+ p54_reset_stats(priv);
return dev;
}
EXPORT_SYMBOL_GPL(p54_init_common);
@@ -730,11 +818,13 @@ void p54_free_common(struct ieee80211_hw *dev)
kfree(priv->curve_data);
kfree(priv->rssi_db);
kfree(priv->used_rxkeys);
+ kfree(priv->survey);
priv->iq_autocal = NULL;
priv->output_limit = NULL;
priv->curve_data = NULL;
priv->rssi_db = NULL;
priv->used_rxkeys = NULL;
+ priv->survey = NULL;
ieee80211_free_hw(dev);
}
EXPORT_SYMBOL_GPL(p54_free_common);
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 799d05e12595..452fa3a64aa1 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -199,6 +199,22 @@ struct p54_common {
u8 tx_diversity_mask;
unsigned int output_power;
struct p54_rssi_db_entry *cur_rssi;
+ struct ieee80211_channel *curchan;
+ struct survey_info *survey;
+ unsigned int chan_num;
+ struct completion stat_comp;
+ bool update_stats;
+ struct {
+ unsigned int timestamp;
+ unsigned int cached_cca;
+ unsigned int cached_tx;
+ unsigned int cached_rssi;
+ u64 active;
+ u64 cca;
+ u64 tx;
+ u64 rssi;
+ } survey_raw;
+
int noise;
/* calibration, output power limit and rssi<->dBm conversation data */
struct pda_iq_autocal_entry *iq_autocal;
@@ -220,6 +236,8 @@ struct p54_common {
u32 basic_rate_mask;
u16 aid;
u8 coverage_class;
+ bool phy_idle;
+ bool phy_ps;
bool powersave_override;
__le32 beacon_req_id;
struct completion beacon_comp;
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index 6d9204fef90b..f18df82eeb92 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -41,7 +41,6 @@
#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
MODULE_FIRMWARE("3826.arm");
-MODULE_ALIAS("stlc45xx");
/*
* gpios should be handled in board files and provided via platform data,
@@ -738,3 +737,4 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
MODULE_ALIAS("spi:cx3110x");
MODULE_ALIAS("spi:p54spi");
+MODULE_ALIAS("spi:stlc45xx");
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 042842e704de..f485784a60ae 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
+#include <asm/div64.h>
#include <net/mac80211.h>
@@ -507,6 +508,8 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb)
struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
struct p54_statistics *stats = (struct p54_statistics *) hdr->data;
struct sk_buff *tmp;
+ struct ieee80211_channel *chan;
+ unsigned int i, rssi, tx, cca, dtime, dtotal, dcca, dtx, drssi, unit;
u32 tsf32;
if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
@@ -523,8 +526,75 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb)
priv->noise = p54_rssi_to_dbm(priv, le32_to_cpu(stats->noise));
+ /*
+ * STSW450X LMAC API page 26 - 3.8 Statistics
+ * "The exact measurement period can be derived from the
+ * timestamp member".
+ */
+ dtime = tsf32 - priv->survey_raw.timestamp;
+
+ /*
+ * STSW450X LMAC API page 26 - 3.8.1 Noise histogram
+ * The LMAC samples RSSI, CCA and transmit state at regular
+ * periods (typically 8 times per 1k [as in 1024] usec).
+ */
+ cca = le32_to_cpu(stats->sample_cca);
+ tx = le32_to_cpu(stats->sample_tx);
+ rssi = 0;
+ for (i = 0; i < ARRAY_SIZE(stats->sample_noise); i++)
+ rssi += le32_to_cpu(stats->sample_noise[i]);
+
+ dcca = cca - priv->survey_raw.cached_cca;
+ drssi = rssi - priv->survey_raw.cached_rssi;
+ dtx = tx - priv->survey_raw.cached_tx;
+ dtotal = dcca + drssi + dtx;
+
+ /*
+ * update statistics when more than a second is over since the
+ * last call, or when a update is badly needed.
+ */
+ if (dtotal && (priv->update_stats || dtime >= USEC_PER_SEC) &&
+ dtime >= dtotal) {
+ priv->survey_raw.timestamp = tsf32;
+ priv->update_stats = false;
+ unit = dtime / dtotal;
+
+ if (dcca) {
+ priv->survey_raw.cca += dcca * unit;
+ priv->survey_raw.cached_cca = cca;
+ }
+ if (dtx) {
+ priv->survey_raw.tx += dtx * unit;
+ priv->survey_raw.cached_tx = tx;
+ }
+ if (drssi) {
+ priv->survey_raw.rssi += drssi * unit;
+ priv->survey_raw.cached_rssi = rssi;
+ }
+
+ /* 1024 usec / 8 times = 128 usec / time */
+ if (!(priv->phy_ps || priv->phy_idle))
+ priv->survey_raw.active += dtotal * unit;
+ else
+ priv->survey_raw.active += (dcca + dtx) * unit;
+ }
+
+ chan = priv->curchan;
+ if (chan) {
+ struct survey_info *survey = &priv->survey[chan->hw_value];
+ survey->noise = clamp_t(s8, priv->noise, -128, 127);
+ survey->channel_time = priv->survey_raw.active;
+ survey->channel_time_tx = priv->survey_raw.tx;
+ survey->channel_time_busy = priv->survey_raw.tx +
+ priv->survey_raw.cca;
+ do_div(survey->channel_time, 1024);
+ do_div(survey->channel_time_tx, 1024);
+ do_div(survey->channel_time_busy, 1024);
+ }
+
tmp = p54_find_and_unlink_skb(priv, hdr->req_id);
dev_kfree_skb_any(tmp);
+ complete(&priv->stat_comp);
}
static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb)
@@ -619,7 +689,7 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb,
if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
*flags |= P54_HDR_FLAG_DATA_OUT_SEQNR;
- if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)
+ if (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)
*flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL;
if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 2a06ebcd67c5..0021e4948512 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -273,7 +273,7 @@ static const struct net_device_ops ray_netdev_ops = {
.ndo_start_xmit = ray_dev_start_xmit,
.ndo_set_config = ray_dev_config,
.ndo_get_stats = ray_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_rx_mode = set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 29f938930667..0c13840a7de5 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -36,13 +36,11 @@
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/usb/cdc.h>
-#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <linux/if_arp.h>
#include <linux/ctype.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
-#include <net/iw_handler.h>
#include <net/cfg80211.h>
#include <linux/usb/usbnet.h>
#include <linux/usb/rndis_host.h>
@@ -3392,7 +3390,7 @@ static const struct net_device_ops rndis_wlan_netdev_ops = {
.ndo_tx_timeout = usbnet_tx_timeout,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = rndis_wlan_set_multicast_list,
+ .ndo_set_rx_mode = rndis_wlan_set_multicast_list,
};
static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 76bcc3547976..3a6b40239bc1 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -645,11 +645,6 @@ static void rt2400pci_start_queue(struct data_queue *queue)
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- /*
- * Allow the tbtt tasklet to be scheduled.
- */
- tasklet_enable(&rt2x00dev->tbtt_tasklet);
-
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
@@ -715,7 +710,7 @@ static void rt2400pci_stop_queue(struct data_queue *queue)
/*
* Wait for possibly running tbtt tasklets.
*/
- tasklet_disable(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
break;
default:
break;
@@ -982,12 +977,6 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
if (state == STATE_RADIO_IRQ_ON) {
rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
rt2x00pci_register_write(rt2x00dev, CSR7, reg);
-
- /*
- * Enable tasklets.
- */
- tasklet_enable(&rt2x00dev->txstatus_tasklet);
- tasklet_enable(&rt2x00dev->rxdone_tasklet);
}
/*
@@ -1011,8 +1000,9 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* Ensure that all tasklets are finished before
* disabling the interrupts.
*/
- tasklet_disable(&rt2x00dev->txstatus_tasklet);
- tasklet_disable(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->txstatus_tasklet);
+ tasklet_kill(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
}
}
@@ -1249,7 +1239,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,
* call, we must decrease the higher 32bits with 1 to get
* to correct value.
*/
- tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw);
+ tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw, NULL);
rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME);
rx_high = upper_32_bits(tsf);
@@ -1347,22 +1337,25 @@ static void rt2400pci_txstatus_tasklet(unsigned long data)
/*
* Enable all TXDONE interrupts again.
*/
- spin_lock_irq(&rt2x00dev->irqmask_lock);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
+ spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
- rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
- rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
- rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
+ rt2x00pci_register_write(rt2x00dev, CSR8, reg);
- spin_unlock_irq(&rt2x00dev->irqmask_lock);
+ spin_unlock_irq(&rt2x00dev->irqmask_lock);
+ }
}
static void rt2400pci_tbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_beacondone(rt2x00dev);
- rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
}
static void rt2400pci_rxdone_tasklet(unsigned long data)
@@ -1370,7 +1363,7 @@ static void rt2400pci_rxdone_tasklet(unsigned long data)
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
if (rt2x00pci_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
- else
+ else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
}
@@ -1655,7 +1648,8 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int rt2400pci_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -1668,7 +1662,7 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,
if (queue != 0)
return -EINVAL;
- if (rt2x00mac_conf_tx(hw, queue, params))
+ if (rt2x00mac_conf_tx(hw, vif, queue, params))
return -EINVAL;
/*
@@ -1680,7 +1674,8 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,
return 0;
}
-static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw)
+static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
u64 tsf;
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index c288d951c034..dcc0e1fcca77 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -735,11 +735,6 @@ static void rt2500pci_start_queue(struct data_queue *queue)
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- /*
- * Allow the tbtt tasklet to be scheduled.
- */
- tasklet_enable(&rt2x00dev->tbtt_tasklet);
-
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
@@ -805,7 +800,7 @@ static void rt2500pci_stop_queue(struct data_queue *queue)
/*
* Wait for possibly running tbtt tasklets.
*/
- tasklet_disable(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
break;
default:
break;
@@ -1137,12 +1132,6 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
if (state == STATE_RADIO_IRQ_ON) {
rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
rt2x00pci_register_write(rt2x00dev, CSR7, reg);
-
- /*
- * Enable tasklets.
- */
- tasklet_enable(&rt2x00dev->txstatus_tasklet);
- tasklet_enable(&rt2x00dev->rxdone_tasklet);
}
/*
@@ -1165,8 +1154,9 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
/*
* Ensure that all tasklets are finished.
*/
- tasklet_disable(&rt2x00dev->txstatus_tasklet);
- tasklet_disable(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->txstatus_tasklet);
+ tasklet_kill(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
}
}
@@ -1479,22 +1469,25 @@ static void rt2500pci_txstatus_tasklet(unsigned long data)
/*
* Enable all TXDONE interrupts again.
*/
- spin_lock_irq(&rt2x00dev->irqmask_lock);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
+ spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
- rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
- rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
- rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
+ rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
+ rt2x00pci_register_write(rt2x00dev, CSR8, reg);
- spin_unlock_irq(&rt2x00dev->irqmask_lock);
+ spin_unlock_irq(&rt2x00dev->irqmask_lock);
+ }
}
static void rt2500pci_tbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_beacondone(rt2x00dev);
- rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
}
static void rt2500pci_rxdone_tasklet(unsigned long data)
@@ -1502,7 +1495,7 @@ static void rt2500pci_rxdone_tasklet(unsigned long data)
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
if (rt2x00pci_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
- else
+ else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
}
@@ -1973,7 +1966,8 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
+static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
u64 tsf;
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index c69a7d71f4ca..4778620347c4 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -664,6 +664,9 @@
/*
* LED_CFG: LED control
+ * ON_PERIOD: LED active time (ms) during TX (only used for LED mode 1)
+ * OFF_PERIOD: LED inactive time (ms) during TX (only used for LED mode 1)
+ * SLOW_BLINK_PERIOD: LED blink interval in seconds (only used for LED mode 2)
* color LED's:
* 0: off
* 1: blinking upon TX2
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 0019dfd8fb01..3f183a15186e 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -493,7 +493,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);
rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
- txdesc->key_idx : 0xff);
+ txdesc->key_idx : txdesc->u.ht.wcid);
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
txdesc->length);
rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
@@ -601,7 +601,7 @@ void rt2800_process_rxwi(struct queue_entry *entry,
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
@@ -609,13 +609,11 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
u32 word;
u16 mcs, real_mcs;
int aggr, ampdu;
- __le32 *txwi;
/*
* Obtain the status about this packet.
*/
txdesc.flags = 0;
- txwi = rt2800_drv_get_txwi(entry);
rt2x00_desc_read(txwi, 0, &word);
mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
@@ -899,28 +897,12 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,
}
}
-static int rt2800_blink_set(struct led_classdev *led_cdev,
- unsigned long *delay_on, unsigned long *delay_off)
-{
- struct rt2x00_led *led =
- container_of(led_cdev, struct rt2x00_led, led_dev);
- u32 reg;
-
- rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
- rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, *delay_on);
- rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off);
- rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
-
- return 0;
-}
-
static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
struct rt2x00_led *led, enum led_type type)
{
led->rt2x00dev = rt2x00dev;
led->type = type;
led->led_dev.brightness_set = rt2800_brightness_set;
- led->led_dev.blink_set = rt2800_blink_set;
led->flags = LED_INITIALIZED;
}
#endif /* CONFIG_RT2X00_LIB_LEDS */
@@ -928,11 +910,51 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
/*
* Configuration handlers.
*/
-static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_crypto *crypto,
- struct ieee80211_key_conf *key)
+static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev,
+ const u8 *address,
+ int wcid)
{
struct mac_wcid_entry wcid_entry;
+ u32 offset;
+
+ offset = MAC_WCID_ENTRY(wcid);
+
+ memset(&wcid_entry, 0xff, sizeof(wcid_entry));
+ if (address)
+ memcpy(wcid_entry.mac, address, ETH_ALEN);
+
+ rt2800_register_multiwrite(rt2x00dev, offset,
+ &wcid_entry, sizeof(wcid_entry));
+}
+
+static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid)
+{
+ u32 offset;
+ offset = MAC_WCID_ATTR_ENTRY(wcid);
+ rt2800_register_write(rt2x00dev, offset, 0);
+}
+
+static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
+ int wcid, u32 bssidx)
+{
+ u32 offset = MAC_WCID_ATTR_ENTRY(wcid);
+ u32 reg;
+
+ /*
+ * The BSS Idx numbers is split in a main value of 3 bits,
+ * and a extended field for adding one additional bit to the value.
+ */
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
+ (bssidx & 0x8) >> 3);
+ rt2800_register_write(rt2x00dev, offset, reg);
+}
+
+static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key)
+{
struct mac_iveiv_entry iveiv_entry;
u32 offset;
u32 reg;
@@ -952,14 +974,16 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
(crypto->cipher & 0x7));
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT,
(crypto->cipher & 0x8) >> 3);
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX,
- (crypto->bssidx & 0x7));
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
- (crypto->bssidx & 0x8) >> 3);
rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
rt2800_register_write(rt2x00dev, offset, reg);
} else {
- rt2800_register_write(rt2x00dev, offset, 0);
+ /* Delete the cipher without touching the bssidx */
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB, 0);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER, 0);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
+ rt2800_register_write(rt2x00dev, offset, reg);
}
offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
@@ -972,14 +996,6 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
iveiv_entry.iv[3] |= key->keyidx << 6;
rt2800_register_multiwrite(rt2x00dev, offset,
&iveiv_entry, sizeof(iveiv_entry));
-
- offset = MAC_WCID_ENTRY(key->hw_key_idx);
-
- memset(&wcid_entry, 0, sizeof(wcid_entry));
- if (crypto->cmd == SET_KEY)
- memcpy(wcid_entry.mac, crypto->address, ETH_ALEN);
- rt2800_register_multiwrite(rt2x00dev, offset,
- &wcid_entry, sizeof(wcid_entry));
}
int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
@@ -1026,20 +1042,24 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
/*
* Update WCID information
*/
- rt2800_config_wcid_attr(rt2x00dev, crypto, key);
+ rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx);
+ rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx,
+ crypto->bssidx);
+ rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
-static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
+static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev)
{
+ struct mac_wcid_entry wcid_entry;
int idx;
- u32 offset, reg;
+ u32 offset;
/*
- * Search for the first free pairwise key entry and return the
- * corresponding index.
+ * Search for the first free WCID entry and return the corresponding
+ * index.
*
* Make sure the WCID starts _after_ the last possible shared key
* entry (>32).
@@ -1049,11 +1069,17 @@ static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
* first 222 entries.
*/
for (idx = 33; idx <= 222; idx++) {
- offset = MAC_WCID_ATTR_ENTRY(idx);
- rt2800_register_read(rt2x00dev, offset, &reg);
- if (!reg)
+ offset = MAC_WCID_ENTRY(idx);
+ rt2800_register_multiread(rt2x00dev, offset, &wcid_entry,
+ sizeof(wcid_entry));
+ if (is_broadcast_ether_addr(wcid_entry.mac))
return idx;
}
+
+ /*
+ * Use -1 to indicate that we don't have any more space in the WCID
+ * table.
+ */
return -1;
}
@@ -1063,13 +1089,15 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
{
struct hw_key_entry key_entry;
u32 offset;
- int idx;
if (crypto->cmd == SET_KEY) {
- idx = rt2800_find_pairwise_keyslot(rt2x00dev);
- if (idx < 0)
+ /*
+ * Allow key configuration only for STAs that are
+ * known by the hw.
+ */
+ if (crypto->wcid < 0)
return -ENOSPC;
- key->hw_key_idx = idx;
+ key->hw_key_idx = crypto->wcid;
memcpy(key_entry.key, crypto->key,
sizeof(key_entry.key));
@@ -1086,12 +1114,59 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
/*
* Update WCID information
*/
- rt2800_config_wcid_attr(rt2x00dev, crypto, key);
+ rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key);
+int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ int wcid;
+ struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+
+ /*
+ * Find next free WCID.
+ */
+ wcid = rt2800_find_wcid(rt2x00dev);
+
+ /*
+ * Store selected wcid even if it is invalid so that we can
+ * later decide if the STA is uploaded into the hw.
+ */
+ sta_priv->wcid = wcid;
+
+ /*
+ * No space left in the device, however, we can still communicate
+ * with the STA -> No error.
+ */
+ if (wcid < 0)
+ return 0;
+
+ /*
+ * Clean up WCID attributes and write STA address to the device.
+ */
+ rt2800_delete_wcid_attr(rt2x00dev, wcid);
+ rt2800_config_wcid(rt2x00dev, sta->addr, wcid);
+ rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid,
+ rt2x00lib_get_bssidx(rt2x00dev, vif));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_sta_add);
+
+int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)
+{
+ /*
+ * Remove WCID entry, no need to clean the attributes as they will
+ * get renewed when the WCID is reused.
+ */
+ rt2800_config_wcid(rt2x00dev, NULL, wcid);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_sta_remove);
+
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags)
{
@@ -2771,11 +2846,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
SHARED_KEY_MODE_ENTRY(i), 0);
for (i = 0; i < 256; i++) {
- static const u32 wcid[2] = { 0xffffffff, 0x00ffffff };
- rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i),
- wcid, sizeof(wcid));
-
- rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 0);
+ rt2800_config_wcid(rt2x00dev, NULL, i);
+ rt2800_delete_wcid_attr(rt2x00dev, i);
rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
}
@@ -4326,7 +4398,8 @@ int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
}
EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold);
-int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+int rt2800_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -4342,7 +4415,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
* we are free to update the registers based on the value
* in the queue parameter.
*/
- retval = rt2x00mac_conf_tx(hw, queue_idx, params);
+ retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
if (retval)
return retval;
@@ -4394,7 +4467,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
}
EXPORT_SYMBOL_GPL(rt2800_conf_tx);
-u64 rt2800_get_tsf(struct ieee80211_hw *hw)
+u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
u64 tsf;
@@ -4414,8 +4487,19 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
u8 buf_size)
{
+ struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
int ret = 0;
+ /*
+ * Don't allow aggregation for stations the hardware isn't aware
+ * of because tx status reports for frames to an unknown station
+ * always contain wcid=255 and thus we can't distinguish between
+ * multiple stations which leads to unwanted situations when the
+ * hw reorders frames due to aggregation.
+ */
+ if (sta_priv->wcid < 0)
+ return 1;
+
switch (action) {
case IEEE80211_AMPDU_RX_START:
case IEEE80211_AMPDU_RX_STOP:
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 69deb3148ae7..8c3c281904fe 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -152,7 +152,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
struct txentry_desc *txdesc);
void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi);
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
void rt2800_clear_beacon(struct queue_entry *entry);
@@ -166,6 +166,9 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
+int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid);
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags);
void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
@@ -194,9 +197,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev);
void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32,
u16 *iv16);
int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
-int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+int rt2800_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue_idx,
const struct ieee80211_tx_queue_params *params);
-u64 rt2800_get_tsf(struct ieee80211_hw *hw);
+u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index ebc17ad61dec..da48c8ac27bd 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -200,13 +200,6 @@ static void rt2800pci_start_queue(struct data_queue *queue)
rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- /*
- * Allow beacon tasklets to be scheduled for periodic
- * beacon updates.
- */
- tasklet_enable(&rt2x00dev->tbtt_tasklet);
- tasklet_enable(&rt2x00dev->pretbtt_tasklet);
-
rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
@@ -269,10 +262,13 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
/*
- * Wait for tbtt tasklets to finish.
+ * Wait for current invocation to finish. The tasklet
+ * won't be scheduled anymore afterwards since we disabled
+ * the TBTT and PRE TBTT timer.
*/
- tasklet_disable(&rt2x00dev->tbtt_tasklet);
- tasklet_disable(&rt2x00dev->pretbtt_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->pretbtt_tasklet);
+
break;
default:
break;
@@ -437,14 +433,6 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
if (state == STATE_RADIO_IRQ_ON) {
rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
- /*
- * Enable tasklets. The beacon related tasklets are
- * enabled when the beacon queue is started.
- */
- tasklet_enable(&rt2x00dev->txstatus_tasklet);
- tasklet_enable(&rt2x00dev->rxdone_tasklet);
- tasklet_enable(&rt2x00dev->autowake_tasklet);
}
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
@@ -472,12 +460,13 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
if (state == STATE_RADIO_IRQ_OFF) {
/*
- * Ensure that all tasklets are finished before
- * disabling the interrupts.
+ * Wait for possibly running tasklets to finish.
*/
- tasklet_disable(&rt2x00dev->txstatus_tasklet);
- tasklet_disable(&rt2x00dev->rxdone_tasklet);
- tasklet_disable(&rt2x00dev->autowake_tasklet);
+ tasklet_kill(&rt2x00dev->txstatus_tasklet);
+ tasklet_kill(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->autowake_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->pretbtt_tasklet);
}
}
@@ -630,11 +619,11 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
/*
* Initialize TX descriptor
*/
- rt2x00_desc_read(txd, 0, &word);
+ word = 0;
rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma);
rt2x00_desc_write(txd, 0, word);
- rt2x00_desc_read(txd, 1, &word);
+ word = 0;
rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
!test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
@@ -645,12 +634,12 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
rt2x00_desc_write(txd, 1, word);
- rt2x00_desc_read(txd, 2, &word);
+ word = 0;
rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
skbdesc->skb_dma + TXWI_DESC_SIZE);
rt2x00_desc_write(txd, 2, word);
- rt2x00_desc_read(txd, 3, &word);
+ word = 0;
rt2x00_set_field32(&word, TXD_W3_WIV,
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
@@ -771,7 +760,7 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
}
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- rt2800_txdone_entry(entry, status);
+ rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry));
if (--max_tx_done == 0)
break;
@@ -813,14 +802,16 @@ static void rt2800pci_pretbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_pretbtt(rt2x00dev);
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
}
static void rt2800pci_tbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_beacondone(rt2x00dev);
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
}
static void rt2800pci_rxdone_tasklet(unsigned long data)
@@ -828,7 +819,7 @@ static void rt2800pci_rxdone_tasklet(unsigned long data)
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
if (rt2x00pci_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
- else
+ else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
}
@@ -836,7 +827,8 @@ static void rt2800pci_autowake_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2800pci_wakeup(rt2x00dev);
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP);
}
static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
@@ -1023,6 +1015,8 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.get_tkip_seq = rt2800_get_tkip_seq,
.set_rts_threshold = rt2800_set_rts_threshold,
+ .sta_add = rt2x00mac_sta_add,
+ .sta_remove = rt2x00mac_sta_remove,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf,
@@ -1084,6 +1078,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant,
.config = rt2800_config,
+ .sta_add = rt2800_sta_add,
+ .sta_remove = rt2800_sta_remove,
};
static const struct data_queue_desc rt2800pci_queue_rx = {
@@ -1161,6 +1157,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
#endif
#ifdef CONFIG_RT2800PCI_RT53XX
{ PCI_DEVICE(0x1814, 0x5390) },
+ { PCI_DEVICE(0x1814, 0x539a) },
{ PCI_DEVICE(0x1814, 0x539f) },
#endif
{ 0, }
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index dbf501ca317f..f1565792f270 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -542,7 +542,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
}
if (entry)
- rt2800_txdone_entry(entry, reg);
+ rt2800_txdone_entry(entry, reg,
+ rt2800usb_get_txwi(entry));
}
}
@@ -759,6 +760,8 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.get_stats = rt2x00mac_get_stats,
.get_tkip_seq = rt2800_get_tkip_seq,
.set_rts_threshold = rt2800_set_rts_threshold,
+ .sta_add = rt2x00mac_sta_add,
+ .sta_remove = rt2x00mac_sta_remove,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf,
@@ -816,6 +819,8 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant,
.config = rt2800_config,
+ .sta_add = rt2800_sta_add,
+ .sta_remove = rt2800_sta_remove,
};
static const struct data_queue_desc rt2800usb_queue_rx = {
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index f82bfeb79ebb..2ec5c00235e6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -478,6 +478,8 @@ struct rt2x00lib_crypto {
u8 key[16];
u8 tx_mic[8];
u8 rx_mic[8];
+
+ int wcid;
};
/*
@@ -512,6 +514,19 @@ struct rt2x00intf_conf {
};
/*
+ * Private structure for storing STA details
+ * wcid: Wireless Client ID
+ */
+struct rt2x00_sta {
+ int wcid;
+};
+
+static inline struct rt2x00_sta* sta_to_rt2x00_sta(struct ieee80211_sta *sta)
+{
+ return (struct rt2x00_sta *)sta->drv_priv;
+}
+
+/*
* rt2x00lib callback functions.
*/
struct rt2x00lib_ops {
@@ -620,6 +635,11 @@ struct rt2x00lib_ops {
void (*config) (struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int changed_flags);
+ int (*sta_add) (struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+ int (*sta_remove) (struct rt2x00_dev *rt2x00dev,
+ int wcid);
};
/*
@@ -1226,6 +1246,12 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
/*
+ * Utility functions.
+ */
+u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_vif *vif);
+
+/*
* Interrupt context handlers.
*/
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
@@ -1261,6 +1287,10 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
#else
#define rt2x00mac_set_key NULL
#endif /* CONFIG_RT2X00_LIB_CRYPTO */
+int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw);
void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw);
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
@@ -1269,7 +1299,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u32 changes);
-int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params);
void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 0955c941317f..e1fb2a8569be 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -33,6 +33,22 @@
#include "rt2x00lib.h"
/*
+ * Utility functions.
+ */
+u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_vif *vif)
+{
+ /*
+ * When in STA mode, bssidx is always 0 otherwise local_address[5]
+ * contains the bss number, see BSS_ID_MASK comments for details.
+ */
+ if (rt2x00dev->intf_sta_count)
+ return 0;
+ return vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_get_bssidx);
+
+/*
* Radio control handlers.
*/
int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -915,6 +931,11 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
/*
+ * Tell mac80211 about the size of our private STA structure.
+ */
+ rt2x00dev->hw->sta_data_size = sizeof(struct rt2x00_sta);
+
+ /*
* Allocate tx status FIFO for driver use.
*/
if (test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags)) {
@@ -946,7 +967,6 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
tasklet_init(&rt2x00dev->taskletname, \
rt2x00dev->ops->lib->taskletname, \
(unsigned long)rt2x00dev); \
- tasklet_disable(&rt2x00dev->taskletname); \
}
RT2X00_TASKLET_INIT(txstatus_tasklet);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 4ccf23805973..bf0acff07807 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -494,6 +494,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct rt2x00lib_crypto crypto;
static const u8 bcast_addr[ETH_ALEN] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
+ struct rt2x00_sta *sta_priv = NULL;
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
@@ -504,24 +505,18 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
memset(&crypto, 0, sizeof(crypto));
- /*
- * When in STA mode, bssidx is always 0 otherwise local_address[5]
- * contains the bss number, see BSS_ID_MASK comments for details.
- */
- if (rt2x00dev->intf_sta_count)
- crypto.bssidx = 0;
- else
- crypto.bssidx = vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
-
+ crypto.bssidx = rt2x00lib_get_bssidx(rt2x00dev, vif);
crypto.cipher = rt2x00crypto_key_to_cipher(key);
if (crypto.cipher == CIPHER_NONE)
return -EOPNOTSUPP;
crypto.cmd = cmd;
- if (sta)
+ if (sta) {
crypto.address = sta->addr;
- else
+ sta_priv = sta_to_rt2x00_sta(sta);
+ crypto.wcid = sta_priv->wcid;
+ } else
crypto.address = bcast_addr;
if (crypto.cipher == CIPHER_TKIP)
@@ -560,6 +555,39 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
#endif /* CONFIG_RT2X00_LIB_CRYPTO */
+int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+
+ /*
+ * If there's no space left in the device table store
+ * -1 as wcid but tell mac80211 everything went ok.
+ */
+ if (rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta))
+ sta_priv->wcid = -1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_sta_add);
+
+int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+
+ /*
+ * If we never sent the STA to the device no need to clean it up.
+ */
+ if (sta_priv->wcid < 0)
+ return 0;
+
+ return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
+
void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -685,7 +713,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
-int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 29edb9fbe6f1..5adfb3eab9cd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -310,11 +310,16 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct rt2x00_sta *sta_priv = NULL;
- if (tx_info->control.sta)
+ if (tx_info->control.sta) {
txdesc->u.ht.mpdu_density =
tx_info->control.sta->ht_cap.ampdu_density;
+ sta_priv = sta_to_rt2x00_sta(tx_info->control.sta);
+ txdesc->u.ht.wcid = sta_priv->wcid;
+ }
+
txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */
/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index f2100f4ddcff..349008d1fb28 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -288,8 +288,8 @@ enum txentry_desc_flags {
* @signal: PLCP signal.
* @service: PLCP service.
* @msc: MCS.
- * @stbc: STBC.
- * @ba_size: BA size.
+ * @stbc: Use Space Time Block Coding (only available for MCS rates < 8).
+ * @ba_size: Size of the recepients RX reorder buffer - 1.
* @rate_mode: Rate mode (See @enum rate_modulation).
* @mpdu_density: MDPU density.
* @retry_limit: Max number of retries.
@@ -321,6 +321,7 @@ struct txentry_desc {
u8 ba_size;
u8 mpdu_density;
enum txop txop;
+ int wcid;
} ht;
} u;
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 53110b83bf6e..bf55b4a311e3 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1142,11 +1142,6 @@ static void rt61pci_start_queue(struct data_queue *queue)
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
- /*
- * Allow the tbtt tasklet to be scheduled.
- */
- tasklet_enable(&rt2x00dev->tbtt_tasklet);
-
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
@@ -1230,7 +1225,7 @@ static void rt61pci_stop_queue(struct data_queue *queue)
/*
* Wait for possibly running tbtt tasklets.
*/
- tasklet_disable(&rt2x00dev->tbtt_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
break;
default:
break;
@@ -1731,13 +1726,6 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
-
- /*
- * Enable tasklets.
- */
- tasklet_enable(&rt2x00dev->txstatus_tasklet);
- tasklet_enable(&rt2x00dev->rxdone_tasklet);
- tasklet_enable(&rt2x00dev->autowake_tasklet);
}
/*
@@ -1772,9 +1760,10 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
/*
* Ensure that all tasklets are finished.
*/
- tasklet_disable(&rt2x00dev->txstatus_tasklet);
- tasklet_disable(&rt2x00dev->rxdone_tasklet);
- tasklet_disable(&rt2x00dev->autowake_tasklet);
+ tasklet_kill(&rt2x00dev->txstatus_tasklet);
+ tasklet_kill(&rt2x00dev->rxdone_tasklet);
+ tasklet_kill(&rt2x00dev->autowake_tasklet);
+ tasklet_kill(&rt2x00dev->tbtt_tasklet);
}
}
@@ -2300,22 +2289,24 @@ static void rt61pci_txstatus_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt61pci_txdone(rt2x00dev);
- rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE);
}
static void rt61pci_tbtt_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt2x00lib_beacondone(rt2x00dev);
- rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE);
}
static void rt61pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
if (rt2x00pci_rxdone(rt2x00dev))
- rt2x00pci_rxdone(rt2x00dev);
- else
+ tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+ else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
}
@@ -2325,7 +2316,8 @@ static void rt61pci_autowake_tasklet(unsigned long data)
rt61pci_wakeup(rt2x00dev);
rt2x00pci_register_write(rt2x00dev,
M2H_CMD_DONE_CSR, 0xffffffff);
- rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
+ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
}
static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
@@ -2891,7 +2883,8 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+static int rt61pci_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -2907,7 +2900,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
* we are free to update the registers based on the value
* in the queue parameter.
*/
- retval = rt2x00mac_conf_tx(hw, queue_idx, params);
+ retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
if (retval)
return retval;
@@ -2948,7 +2941,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
return 0;
}
-static u64 rt61pci_get_tsf(struct ieee80211_hw *hw)
+static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
u64 tsf;
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 0baeb894f093..cfb19dbb0a67 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2222,7 +2222,8 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+static int rt73usb_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -2238,7 +2239,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
* we are free to update the registers based on the value
* in the queue parameter.
*/
- retval = rt2x00mac_conf_tx(hw, queue_idx, params);
+ retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
if (retval)
return retval;
@@ -2279,7 +2280,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
return 0;
}
-static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
+static u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
u64 tsf;
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 66b29dc07cc3..0082015ff664 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -669,7 +669,8 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
rtl8180_free_tx_ring(dev, i);
}
-static u64 rtl8180_get_tsf(struct ieee80211_hw *dev)
+static u64 rtl8180_get_tsf(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif)
{
struct rtl8180_priv *priv = dev->priv;
@@ -701,7 +702,7 @@ static void rtl8180_beacon_work(struct work_struct *work)
* TODO: make hardware update beacon timestamp
*/
mgmt = (struct ieee80211_mgmt *)skb->data;
- mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev));
+ mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev, vif));
/* TODO: use actual beacon queue */
skb_set_queue_mapping(skb, 0);
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 1e0be14d10d4..24873b55b55c 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -1241,7 +1241,8 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev,
rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf);
}
-static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue,
+static int rtl8187_conf_tx(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct rtl8187_priv *priv = dev->priv;
@@ -1277,7 +1278,7 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue,
return 0;
}
-static u64 rtl8187_get_tsf(struct ieee80211_hw *dev)
+static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
{
struct rtl8187_priv *priv = dev->priv;
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index 45e14760c16e..d6c42e69bdbd 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -12,7 +12,7 @@ config RTL8192CE
config RTL8192SE
tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter"
- depends on MAC80211 && EXPERIMENTAL
+ depends on MAC80211 && EXPERIMENTAL && PCI
select FW_LOADER
select RTLWIFI
---help---
@@ -23,7 +23,7 @@ config RTL8192SE
config RTL8192DE
tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter"
- depends on MAC80211 && EXPERIMENTAL
+ depends on MAC80211 && EXPERIMENTAL && PCI
select FW_LOADER
select RTLWIFI
---help---
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 0b598db38da9..d4fdd2a5a739 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -311,6 +311,8 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_BEACON_FILTER |
IEEE80211_HW_AMPDU_AGGREGATION |
+ IEEE80211_HW_CONNECTION_MONITOR |
+ /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */
IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0;
/* swlps or hwlps has been set in diff chip in init_sw_vars */
@@ -664,6 +666,167 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw)
return hw_rate;
}
+/* mac80211's rate_idx is like this:
+ *
+ * 2.4G band:rx_status->band == IEEE80211_BAND_2GHZ
+ *
+ * B/G rate:
+ * (rx_status->flag & RX_FLAG_HT) = 0,
+ * DESC92_RATE1M-->DESC92_RATE54M ==> idx is 0-->11,
+ *
+ * N rate:
+ * (rx_status->flag & RX_FLAG_HT) = 1,
+ * DESC92_RATEMCS0-->DESC92_RATEMCS15 ==> idx is 0-->15
+ *
+ * 5G band:rx_status->band == IEEE80211_BAND_5GHZ
+ * A rate:
+ * (rx_status->flag & RX_FLAG_HT) = 0,
+ * DESC92_RATE6M-->DESC92_RATE54M ==> idx is 0-->7,
+ *
+ * N rate:
+ * (rx_status->flag & RX_FLAG_HT) = 1,
+ * DESC92_RATEMCS0-->DESC92_RATEMCS15 ==> idx is 0-->15
+ */
+int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
+ bool isht, u8 desc_rate, bool first_ampdu)
+{
+ int rate_idx;
+
+ if (false == isht) {
+ if (IEEE80211_BAND_2GHZ == hw->conf.channel->band) {
+ switch (desc_rate) {
+ case DESC92_RATE1M:
+ rate_idx = 0;
+ break;
+ case DESC92_RATE2M:
+ rate_idx = 1;
+ break;
+ case DESC92_RATE5_5M:
+ rate_idx = 2;
+ break;
+ case DESC92_RATE11M:
+ rate_idx = 3;
+ break;
+ case DESC92_RATE6M:
+ rate_idx = 4;
+ break;
+ case DESC92_RATE9M:
+ rate_idx = 5;
+ break;
+ case DESC92_RATE12M:
+ rate_idx = 6;
+ break;
+ case DESC92_RATE18M:
+ rate_idx = 7;
+ break;
+ case DESC92_RATE24M:
+ rate_idx = 8;
+ break;
+ case DESC92_RATE36M:
+ rate_idx = 9;
+ break;
+ case DESC92_RATE48M:
+ rate_idx = 10;
+ break;
+ case DESC92_RATE54M:
+ rate_idx = 11;
+ break;
+ default:
+ rate_idx = 0;
+ break;
+ }
+ } else {
+ switch (desc_rate) {
+ case DESC92_RATE6M:
+ rate_idx = 0;
+ break;
+ case DESC92_RATE9M:
+ rate_idx = 1;
+ break;
+ case DESC92_RATE12M:
+ rate_idx = 2;
+ break;
+ case DESC92_RATE18M:
+ rate_idx = 3;
+ break;
+ case DESC92_RATE24M:
+ rate_idx = 4;
+ break;
+ case DESC92_RATE36M:
+ rate_idx = 5;
+ break;
+ case DESC92_RATE48M:
+ rate_idx = 6;
+ break;
+ case DESC92_RATE54M:
+ rate_idx = 7;
+ break;
+ default:
+ rate_idx = 0;
+ break;
+ }
+ }
+
+ } else {
+
+ switch (desc_rate) {
+ case DESC92_RATEMCS0:
+ rate_idx = 0;
+ break;
+ case DESC92_RATEMCS1:
+ rate_idx = 1;
+ break;
+ case DESC92_RATEMCS2:
+ rate_idx = 2;
+ break;
+ case DESC92_RATEMCS3:
+ rate_idx = 3;
+ break;
+ case DESC92_RATEMCS4:
+ rate_idx = 4;
+ break;
+ case DESC92_RATEMCS5:
+ rate_idx = 5;
+ break;
+ case DESC92_RATEMCS6:
+ rate_idx = 6;
+ break;
+ case DESC92_RATEMCS7:
+ rate_idx = 7;
+ break;
+ case DESC92_RATEMCS8:
+ rate_idx = 8;
+ break;
+ case DESC92_RATEMCS9:
+ rate_idx = 9;
+ break;
+ case DESC92_RATEMCS10:
+ rate_idx = 10;
+ break;
+ case DESC92_RATEMCS11:
+ rate_idx = 11;
+ break;
+ case DESC92_RATEMCS12:
+ rate_idx = 12;
+ break;
+ case DESC92_RATEMCS13:
+ rate_idx = 13;
+ break;
+ case DESC92_RATEMCS14:
+ rate_idx = 14;
+ break;
+ case DESC92_RATEMCS15:
+ rate_idx = 15;
+ break;
+ default:
+ rate_idx = 0;
+ break;
+ }
+ }
+ return rate_idx;
+}
+EXPORT_SYMBOL(rtlwifi_rate_mapping);
+
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta,
@@ -689,7 +852,7 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
*So tcb_desc->hw_rate is just used for
*special data and mgt frames
*/
- if (info->control.rates[0].idx == 0 &&
+ if (info->control.rates[0].idx == 0 ||
ieee80211_is_nullfunc(fc)) {
tcb_desc->use_driver_rate = true;
tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
@@ -977,7 +1140,7 @@ void rtl_watchdog_wq_callback(void *data)
}
/*
- *<3> to check if traffic busy, if
+ *<2> to check if traffic busy, if
* busytraffic we don't change channel
*/
if (mac->link_state >= MAC80211_LINKED) {
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h
index a91f3eee59c8..4ae905983d0d 100644
--- a/drivers/net/wireless/rtlwifi/base.h
+++ b/drivers/net/wireless/rtlwifi/base.h
@@ -140,4 +140,6 @@ u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie);
void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);
u8 rtl_tid_to_ac(struct ieee80211_hw *hw, 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);
#endif
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index 04c4e9eb6ee6..3f0f056fae9c 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -504,7 +504,8 @@ static int _rtl_get_hal_qnum(u16 queue)
*for mac80211 VO=0, VI=1, BE=2, BK=3
*for rtl819x BE=0, BK=1, VI=2, VO=3
*/
-static int rtl_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int rtl_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *param)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -775,7 +776,7 @@ out:
mutex_unlock(&rtlpriv->locks.conf_mutex);
}
-static u64 rtl_op_get_tsf(struct ieee80211_hw *hw)
+static u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u64 tsf;
@@ -784,7 +785,8 @@ static u64 rtl_op_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
-static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+static void rtl_op_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u64 tsf)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -794,7 +796,8 @@ static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss));
}
-static void rtl_op_reset_tsf(struct ieee80211_hw *hw)
+static void rtl_op_reset_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 tmp = 0;
diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c
index 5fa73852cb66..1b5cb7153a52 100644
--- a/drivers/net/wireless/rtlwifi/debug.c
+++ b/drivers/net/wireless/rtlwifi/debug.c
@@ -33,8 +33,6 @@ void rtl_dbgp_flag_init(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 i;
- rtlpriv->dbg.global_debuglevel = DBG_EMERG;
-
rtlpriv->dbg.global_debugcomponents =
COMP_ERR | COMP_FW | COMP_INIT | COMP_RECV | COMP_SEND |
COMP_MLME | COMP_SCAN | COMP_INTR | COMP_LED | COMP_SEC |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 56f12358389d..177a8e669241 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -218,7 +218,6 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
- u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
/*Retrieve original configuration settings. */
u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg;
@@ -254,9 +253,8 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
udelay(50);
/*4 Disable Pci Bridge ASPM */
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + (num4bytes << 2));
- rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, pcibridge_linkctrlreg);
+ pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
+ pcibridge_linkctrlreg);
udelay(50);
}
@@ -277,7 +275,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum;
u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum;
u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
- u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
u16 aspmlevel;
u8 u_pcibridge_aspmsetting;
@@ -293,8 +290,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
}
/*4 Enable Pci Bridge ASPM */
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + (num4bytes << 2));
u_pcibridge_aspmsetting =
pcipriv->ndis_adapter.pcibridge_linkctrlreg |
@@ -303,7 +298,8 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL)
u_pcibridge_aspmsetting &= ~BIT(0);
- rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, u_pcibridge_aspmsetting);
+ pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
+ u_pcibridge_aspmsetting);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
("PlatformEnableASPM():PciBridge busnumber[%x], "
@@ -335,25 +331,18 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
{
- struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
- u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
bool status = false;
u8 offset_e0;
unsigned offset_e4;
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + 0xE0);
- rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, 0xA0);
+ pci_write_config_byte(rtlpci->pdev, 0xe0, 0xa0);
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + 0xE0);
- rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &offset_e0);
+ pci_read_config_byte(rtlpci->pdev, 0xe0, &offset_e0);
if (offset_e0 == 0xA0) {
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + 0xE4);
- rtl_pci_raw_read_port_ulong(PCI_CONF_DATA, &offset_e4);
+ pci_read_config_dword(rtlpci->pdev, 0xe4, &offset_e4);
if (offset_e4 & BIT(23))
status = true;
}
@@ -364,17 +353,15 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)
{
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset;
- u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
u8 linkctrl_reg;
u8 num4bbytes;
num4bbytes = (capabilityoffset + 0x10) / 4;
/*Read Link Control Register */
- rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
- pcicfg_addrport + (num4bbytes << 2));
- rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &linkctrl_reg);
+ pci_read_config_byte(rtlpci->pdev, (num4bbytes << 2), &linkctrl_reg);
pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg;
}
@@ -488,7 +475,7 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct sk_buff *skb = NULL;
struct ieee80211_tx_info *info = NULL;
- int tid; /* should be int */
+ int tid;
if (!rtlpriv->rtlhal.earlymode_enable)
return;
@@ -1538,7 +1525,7 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
rtl_init_rx_config(hw);
- /*should after adapter start and interrupt enable. */
+ /*should be after adapter start and interrupt enable. */
set_hal_start(rtlhal);
RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
@@ -1559,7 +1546,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
u8 RFInProgressTimeOut = 0;
/*
- *should before disable interrrupt&adapter
+ *should be before disable interrupt&adapter
*and will do it immediately.
*/
set_hal_stop(rtlhal);
@@ -1718,10 +1705,6 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
PCI_SLOT(bridge_pdev->devfn);
pcipriv->ndis_adapter.pcibridge_funcnum =
PCI_FUNC(bridge_pdev->devfn);
- pcipriv->ndis_adapter.pcicfg_addrport =
- (pcipriv->ndis_adapter.pcibridge_busnum << 16) |
- (pcipriv->ndis_adapter.pcibridge_devnum << 11) |
- (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31);
pcipriv->ndis_adapter.pcibridge_pciehdr_offset =
pci_pcie_cap(bridge_pdev);
pcipriv->ndis_adapter.num4bytes =
@@ -2010,36 +1993,25 @@ call rtl_mac_stop() from the mac80211
suspend function first, So there is
no need to call hw_disable here.
****************************************/
-int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+int rtl_pci_suspend(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->cfg->ops->hw_suspend(hw);
rtl_deinit_rfkill(hw);
- pci_save_state(pdev);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
return 0;
}
EXPORT_SYMBOL(rtl_pci_suspend);
-int rtl_pci_resume(struct pci_dev *pdev)
+int rtl_pci_resume(struct device *dev)
{
- int ret;
+ struct pci_dev *pdev = to_pci_dev(dev);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct rtl_priv *rtlpriv = rtl_priv(hw);
- pci_set_power_state(pdev, PCI_D0);
- ret = pci_enable_device(pdev);
- if (ret) {
- RT_ASSERT(false, ("ERR: <======\n"));
- return ret;
- }
-
- pci_restore_state(pdev);
-
rtlpriv->cfg->ops->hw_resume(hw);
rtl_init_rfkill(hw);
return 0;
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index c53c62046747..ebe0b42c0518 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -212,7 +212,6 @@ struct mp_adapter {
u16 pcibridge_vendorid;
u16 pcibridge_deviceid;
- u32 pcicfg_addrport;
u8 num4bytes;
u8 pcibridge_pciehdr_offset;
@@ -238,8 +237,8 @@ extern struct rtl_intf_ops rtl_pci_ops;
int __devinit rtl_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id);
void rtl_pci_disconnect(struct pci_dev *pdev);
-int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state);
-int rtl_pci_resume(struct pci_dev *pdev);
+int rtl_pci_suspend(struct device *dev);
+int rtl_pci_resume(struct device *dev);
static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
{
@@ -273,29 +272,4 @@ static inline void pci_write32_async(struct rtl_priv *rtlpriv,
writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
}
-static inline void rtl_pci_raw_write_port_ulong(u32 port, u32 val)
-{
- outl(val, port);
-}
-
-static inline void rtl_pci_raw_write_port_uchar(u32 port, u8 val)
-{
- outb(val, port);
-}
-
-static inline void rtl_pci_raw_read_port_uchar(u32 port, u8 *pval)
-{
- *pval = inb(port);
-}
-
-static inline void rtl_pci_raw_read_port_ushort(u32 port, u16 *pval)
-{
- *pval = inw(port);
-}
-
-static inline void rtl_pci_raw_read_port_ulong(u32 port, u32 *pval)
-{
- *pval = inl(port);
-}
-
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
index 35ff7df41a1d..9fc804d89d65 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
@@ -142,8 +142,22 @@ enum version_8192c {
VERSION_UNKNOWN = 0x88,
};
+#define CUT_VERSION_MASK (BIT(6)|BIT(7))
+#define CHIP_VENDOR_UMC BIT(5)
+#define CHIP_VENDOR_UMC_B_CUT BIT(6) /* Chip version for ECO */
+#define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) ? \
+ ((GET_CVID_CUT_VERSION(version)) ? false : true) : false)
#define IS_CHIP_VER_B(version) ((version & CHIP_VER_B) ? true : false)
+#define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) ? \
+ ((GET_CVID_CUT_VERSION(version)) ? false : true) : false)
#define IS_92C_SERIAL(version) ((version & CHIP_92C_BITMASK) ? true : false)
+#define IS_CHIP_VENDOR_UMC(version) \
+ ((version & CHIP_VENDOR_UMC) ? true : false)
+#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK)
+#define IS_81xxC_VENDOR_UMC_B_CUT(version) \
+ ((IS_CHIP_VENDOR_UMC(version)) ? \
+ ((GET_CVID_CUT_VERSION(version) == CHIP_VENDOR_UMC_B_CUT) ? \
+ true : false) : false)
enum rtl819x_loopback_e {
RTL819X_NO_LOOPBACK = 0,
@@ -220,41 +234,6 @@ enum rtl_desc_qsel {
QSLT_CMD = 0x13,
};
-enum rtl_desc92c_rate {
- DESC92C_RATE1M = 0x00,
- DESC92C_RATE2M = 0x01,
- DESC92C_RATE5_5M = 0x02,
- DESC92C_RATE11M = 0x03,
-
- DESC92C_RATE6M = 0x04,
- DESC92C_RATE9M = 0x05,
- DESC92C_RATE12M = 0x06,
- DESC92C_RATE18M = 0x07,
- DESC92C_RATE24M = 0x08,
- DESC92C_RATE36M = 0x09,
- DESC92C_RATE48M = 0x0a,
- DESC92C_RATE54M = 0x0b,
-
- DESC92C_RATEMCS0 = 0x0c,
- DESC92C_RATEMCS1 = 0x0d,
- DESC92C_RATEMCS2 = 0x0e,
- DESC92C_RATEMCS3 = 0x0f,
- DESC92C_RATEMCS4 = 0x10,
- DESC92C_RATEMCS5 = 0x11,
- DESC92C_RATEMCS6 = 0x12,
- DESC92C_RATEMCS7 = 0x13,
- DESC92C_RATEMCS8 = 0x14,
- DESC92C_RATEMCS9 = 0x15,
- DESC92C_RATEMCS10 = 0x16,
- DESC92C_RATEMCS11 = 0x17,
- DESC92C_RATEMCS12 = 0x18,
- DESC92C_RATEMCS13 = 0x19,
- DESC92C_RATEMCS14 = 0x1a,
- DESC92C_RATEMCS15 = 0x1b,
- DESC92C_RATEMCS15_SG = 0x1c,
- DESC92C_RATEMCS32 = 0x20,
-};
-
struct phy_sts_cck_8192s_t {
u8 adc_pwdb_X[4];
u8 sq_rpt;
@@ -267,108 +246,4 @@ struct h2c_cmd_8192c {
u8 *p_cmdbuffer;
};
-/* NOTE: reference to rtl8192c_rates struct */
-static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT,
- u8 desc_rate, bool first_ampdu)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- int rate_idx = 0;
-
- if (first_ampdu) {
- if (false == isHT) {
- switch (desc_rate) {
- case DESC92C_RATE1M:
- rate_idx = 0;
- break;
- case DESC92C_RATE2M:
- rate_idx = 1;
- break;
- case DESC92C_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92C_RATE11M:
- rate_idx = 3;
- break;
- case DESC92C_RATE6M:
- rate_idx = 4;
- break;
- case DESC92C_RATE9M:
- rate_idx = 5;
- break;
- case DESC92C_RATE12M:
- rate_idx = 6;
- break;
- case DESC92C_RATE18M:
- rate_idx = 7;
- break;
- case DESC92C_RATE24M:
- rate_idx = 8;
- break;
- case DESC92C_RATE36M:
- rate_idx = 9;
- break;
- case DESC92C_RATE48M:
- rate_idx = 10;
- break;
- case DESC92C_RATE54M:
- rate_idx = 11;
- break;
- default:
- RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
- ("Rate %d is not support, set to "
- "1M rate.\n", desc_rate));
- rate_idx = 0;
- break;
- }
- } else {
- rate_idx = 11;
- }
- return rate_idx;
- }
- switch (desc_rate) {
- case DESC92C_RATE1M:
- rate_idx = 0;
- break;
- case DESC92C_RATE2M:
- rate_idx = 1;
- break;
- case DESC92C_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92C_RATE11M:
- rate_idx = 3;
- break;
- case DESC92C_RATE6M:
- rate_idx = 4;
- break;
- case DESC92C_RATE9M:
- rate_idx = 5;
- break;
- case DESC92C_RATE12M:
- rate_idx = 6;
- break;
- case DESC92C_RATE18M:
- rate_idx = 7;
- break;
- case DESC92C_RATE24M:
- rate_idx = 8;
- break;
- case DESC92C_RATE36M:
- rate_idx = 9;
- break;
- case DESC92C_RATE48M:
- rate_idx = 10;
- break;
- case DESC92C_RATE54M:
- rate_idx = 11;
- break;
- /* TODO: How to mapping MCS rate? */
- /* NOTE: referenc to __ieee80211_rx */
- default:
- rate_idx = 11;
- break;
- }
- return rate_idx;
-}
-
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index 373dc78af1dc..a48404cc2b96 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -92,6 +92,8 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
const struct firmware *firmware;
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+ char *fw_name = NULL;
rtl8192ce_bt_reg_init(hw);
@@ -129,10 +131,16 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD | 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;
+ if (!rtlpriv->psc.inactiveps)
+ pr_info("rtl8192ce: Power Save off (module option)\n");
+ if (!rtlpriv->psc.fwctrl_lps)
+ pr_info("rtl8192ce: FW Power Save off (module option)\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
/* for ASPM, you can close aspm through
@@ -155,8 +163,14 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
}
/* request fw */
- err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
- rtlpriv->io.dev);
+ if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
+ !IS_92C_SERIAL(rtlhal->version))
+ fw_name = "rtlwifi/rtl8192cfwU.bin";
+ else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+ fw_name = "rtlwifi/rtl8192cfwU_B.bin";
+ else
+ fw_name = rtlpriv->cfg->fw_name;
+ err = request_firmware(&firmware, fw_name, rtlpriv->io.dev);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
("Failed to request firmware!\n"));
@@ -241,6 +255,7 @@ static struct rtl_mod_params rtl92ce_mod_params = {
.inactiveps = true,
.swctrl_lps = false,
.fwctrl_lps = true,
+ .debug = DBG_EMERG,
};
static struct rtl_hal_cfg rtl92ce_hal_cfg = {
@@ -318,21 +333,21 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = {
.maps[RTL_IMR_ROK] = IMR_ROK,
.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER),
- .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M,
- .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M,
- .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M,
- .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M,
- .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M,
- .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M,
- .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M,
- .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M,
- .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M,
- .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M,
- .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M,
- .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M,
-
- .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7,
- .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
+ .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,
};
DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = {
@@ -351,27 +366,35 @@ MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless");
MODULE_FIRMWARE("rtlwifi/rtl8192cfw.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192cfwU.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192cfwU_B.bin");
module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug, rtl92ce_mod_params.debug, int, 0444);
module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444);
-MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
-MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
-MODULE_PARM_DESC(fwlps, "using linked fw control power save "
- "(default 1 is open)\n");
+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 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 struct pci_driver rtl92ce_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl92ce_pci_ids,
.probe = rtl_pci_probe,
.remove = rtl_pci_disconnect,
-
-#ifdef CONFIG_PM
- .suspend = rtl_pci_suspend,
- .resume = rtl_pci_resume,
-#endif
-
+ .driver.pm = &rtlwifi_pm_ops,
};
static int __init rtl92ce_module_init(void)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 230bbe900d8d..4fb5ae24dee0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -48,104 +48,6 @@ static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
return skb->priority;
}
-static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu)
-{
- int rate_idx;
-
- if (first_ampdu) {
- if (false == isht) {
- switch (desc_rate) {
- case DESC92C_RATE1M:
- rate_idx = 0;
- break;
- case DESC92C_RATE2M:
- rate_idx = 1;
- break;
- case DESC92C_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92C_RATE11M:
- rate_idx = 3;
- break;
- case DESC92C_RATE6M:
- rate_idx = 4;
- break;
- case DESC92C_RATE9M:
- rate_idx = 5;
- break;
- case DESC92C_RATE12M:
- rate_idx = 6;
- break;
- case DESC92C_RATE18M:
- rate_idx = 7;
- break;
- case DESC92C_RATE24M:
- rate_idx = 8;
- break;
- case DESC92C_RATE36M:
- rate_idx = 9;
- break;
- case DESC92C_RATE48M:
- rate_idx = 10;
- break;
- case DESC92C_RATE54M:
- rate_idx = 11;
- break;
- default:
- rate_idx = 0;
- break;
- }
- } else {
- rate_idx = 11;
- }
-
- return rate_idx;
- }
-
- switch (desc_rate) {
- case DESC92C_RATE1M:
- rate_idx = 0;
- break;
- case DESC92C_RATE2M:
- rate_idx = 1;
- break;
- case DESC92C_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92C_RATE11M:
- rate_idx = 3;
- break;
- case DESC92C_RATE6M:
- rate_idx = 4;
- break;
- case DESC92C_RATE9M:
- rate_idx = 5;
- break;
- case DESC92C_RATE12M:
- rate_idx = 6;
- break;
- case DESC92C_RATE18M:
- rate_idx = 7;
- break;
- case DESC92C_RATE24M:
- rate_idx = 8;
- break;
- case DESC92C_RATE36M:
- rate_idx = 9;
- break;
- case DESC92C_RATE48M:
- rate_idx = 10;
- break;
- case DESC92C_RATE54M:
- rate_idx = 11;
- break;
- default:
- rate_idx = 11;
- break;
- }
- return rate_idx;
-}
-
static u8 _rtl92c_query_rxpwrpercentage(char antpower)
{
if ((antpower <= -100) || (antpower >= 20))
@@ -336,8 +238,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
pstats->rxpower = rx_pwr_all;
pstats->recvsignalpower = rx_pwr_all;
- if (pdesc->rxht && pdesc->rxmcs >= DESC92C_RATEMCS8 &&
- pdesc->rxmcs <= DESC92C_RATEMCS15)
+ if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 &&
+ pdesc->rxmcs <= DESC92_RATEMCS15)
max_spatial_stream = 2;
else
max_spatial_stream = 1;
@@ -670,12 +572,10 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
if (stats->decrypted)
rx_status->flag |= RX_FLAG_DECRYPTED;
- rx_status->rate_idx = _rtl92ce_rate_mapping((bool)
- GET_RX_DESC_RXHT(pdesc),
- (u8)
- GET_RX_DESC_RXMCS(pdesc),
- (bool)
- GET_RX_DESC_PAGGR(pdesc));
+ rx_status->rate_idx = rtlwifi_rate_mapping(hw,
+ (bool)GET_RX_DESC_RXHT(pdesc),
+ (u8)GET_RX_DESC_RXMCS(pdesc),
+ (bool)GET_RX_DESC_PAGGR(pdesc));
rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
if (phystatus) {
@@ -768,7 +668,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_RTS_BW(pdesc, 0);
SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc);
SET_TX_DESC_RTS_SHORT(pdesc,
- ((tcb_desc->rts_rate <= DESC92C_RATE54M) ?
+ ((tcb_desc->rts_rate <= DESC92_RATE54M) ?
(tcb_desc->rts_use_shortpreamble ? 1 : 0)
: (tcb_desc->rts_use_shortgi ? 1 : 0)));
@@ -886,7 +786,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
if (firstseg)
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
- SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
+ SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M);
SET_TX_DESC_SEQ(pdesc, 0);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
index 0f1177137501..c8977a50ca36 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
@@ -537,12 +537,6 @@ do { \
memset(__pdesc, 0, _size); \
} while (0);
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
- (_pdesc->rxmcs == DESC92C_RATE1M || \
- _pdesc->rxmcs == DESC92C_RATE2M || \
- _pdesc->rxmcs == DESC92C_RATE5_5M || \
- _pdesc->rxmcs == DESC92C_RATE11M)
-
struct rx_fwinfo_92c {
u8 gain_trsw[4];
u8 pwdb_all;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h b/drivers/net/wireless/rtlwifi/rtl8192cu/def.h
index c54940ea72fe..d097efb1e717 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/def.h
@@ -50,10 +50,6 @@
#define IS_VENDOR_UMC(version) \
(((version) & CHIP_VENDOR_UMC) ? true : false)
-#define IS_VENDOR_UMC_A_CUT(version) \
- (((version) & CHIP_VENDOR_UMC) ? (((version) & (BIT(6) | BIT(7))) ? \
- false : true) : false)
-
#define IS_VENDOR_8723_A_CUT(version) \
(((version) & CHIP_VENDOR_UMC) ? (((version) & (BIT(6))) ? \
false : true) : false)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
index 194fc693c1fa..060a06f4a885 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -892,8 +892,8 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
pstats->rxpower = rx_pwr_all;
pstats->recvsignalpower = rx_pwr_all;
if (GET_RX_DESC_RX_MCS(pdesc) &&
- GET_RX_DESC_RX_MCS(pdesc) >= DESC92C_RATEMCS8 &&
- GET_RX_DESC_RX_MCS(pdesc) <= DESC92C_RATEMCS15)
+ GET_RX_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 &&
+ GET_RX_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15)
max_spatial_stream = 2;
else
max_spatial_stream = 1;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
index 298fdb724aa5..626d88e88e26 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
@@ -87,12 +87,6 @@ void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter);
u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw);
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
- (GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE1M ||\
- GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE2M ||\
- GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE5_5M ||\
- GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE11M)
-
struct rx_fwinfo_92c {
u8 gain_trsw[4];
u8 pwdb_all;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
index 17a8e9628512..1e851aae58db 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
@@ -104,7 +104,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
tx_agc[RF90_PATH_A] = 0x10101010;
tx_agc[RF90_PATH_B] = 0x10101010;
} else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
- TXHIGHPWRLEVEL_LEVEL2) {
+ TXHIGHPWRLEVEL_LEVEL1) {
tx_agc[RF90_PATH_A] = 0x00000000;
tx_agc[RF90_PATH_B] = 0x00000000;
} else{
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index ef63c0df006a..feed1ed8d9b6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -60,6 +60,7 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->dm.dm_flag = 0;
rtlpriv->dm.disable_framebursting = 0;
rtlpriv->dm.thermalvalue = 0;
+ rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
rtlpriv->rtlhal.pfirmware = vmalloc(0x4000);
if (!rtlpriv->rtlhal.pfirmware) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
@@ -149,8 +150,14 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
static struct rtl_mod_params rtl92cu_mod_params = {
.sw_crypto = 0,
+ .debug = DBG_EMERG,
};
+module_param_named(swenc, rtl92cu_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug, rtl92cu_mod_params.debug, int, 0444);
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+
static struct rtl_hal_usbint_cfg rtl92cu_interface_cfg = {
/* rx */
.in_ep_num = RTL92C_USB_BULK_IN_NUM,
@@ -241,20 +248,20 @@ static struct rtl_hal_cfg rtl92cu_hal_cfg = {
.maps[RTL_IMR_ROK] = IMR_ROK,
.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER),
- .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M,
- .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M,
- .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M,
- .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M,
- .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M,
- .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M,
- .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M,
- .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M,
- .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M,
- .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M,
- .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M,
- .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M,
- .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7,
- .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
+ .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,
};
#define USB_VENDER_ID_REALTEK 0x0bda
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 3e52a5496224..bc33b147f44f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -337,10 +337,10 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
if (stats->decrypted)
rx_status->flag |= RX_FLAG_DECRYPTED;
- rx_status->rate_idx = _rtl92c_rate_mapping(hw,
- (bool)GET_RX_DESC_RX_HT(pdesc),
- (u8)GET_RX_DESC_RX_MCS(pdesc),
- (bool)GET_RX_DESC_PAGGR(pdesc));
+ rx_status->rate_idx = rtlwifi_rate_mapping(hw,
+ (bool)GET_RX_DESC_RX_HT(pdesc),
+ (u8)GET_RX_DESC_RX_MCS(pdesc),
+ (bool)GET_RX_DESC_PAGGR(pdesc));
rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
if (phystatus) {
p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE);
@@ -406,11 +406,10 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
if (GET_RX_DESC_RX_HT(rxdesc))
rx_status->flag |= RX_FLAG_HT;
/* Data rate */
- rx_status->rate_idx = _rtl92c_rate_mapping(hw,
- (bool)GET_RX_DESC_RX_HT(rxdesc),
- (u8)GET_RX_DESC_RX_MCS(rxdesc),
- (bool)GET_RX_DESC_PAGGR(rxdesc)
- );
+ rx_status->rate_idx = rtlwifi_rate_mapping(hw,
+ (bool)GET_RX_DESC_RX_HT(rxdesc),
+ (u8)GET_RX_DESC_RX_MCS(rxdesc),
+ (bool)GET_RX_DESC_PAGGR(rxdesc));
/* There is a phy status after this rx descriptor. */
if (GET_RX_DESC_PHY_STATUS(rxdesc)) {
p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE);
@@ -545,7 +544,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_RTS_BW(txdesc, 0);
SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc);
SET_TX_DESC_RTS_SHORT(txdesc,
- ((tcb_desc->rts_rate <= DESC92C_RATE54M) ?
+ ((tcb_desc->rts_rate <= DESC92_RATE54M) ?
(tcb_desc->rts_use_shortpreamble ? 1 : 0)
: (tcb_desc->rts_use_shortgi ? 1 : 0)));
if (mac->bw_40) {
@@ -644,7 +643,7 @@ void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc,
}
SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */
SET_TX_DESC_OWN(pDesc, 1);
- SET_TX_DESC_TX_RATE(pDesc, DESC92C_RATE1M);
+ SET_TX_DESC_TX_RATE(pDesc, DESC92_RATE1M);
_rtl_tx_desc_checksum(pDesc);
}
@@ -660,7 +659,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE);
if (firstseg)
SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE);
- SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
+ 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);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/rtlwifi/rtl8192de/def.h
index f0f5f9bfbb7b..946304771748 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/def.h
@@ -122,60 +122,99 @@
#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
-/*
- * 92D chip ver:
- * BIT8: IS 92D
- * BIT9: single phy
- * BIT10: C-cut
- * BIT11: D-cut
- */
-
-/* Chip specific */
-#define CHIP_92C BIT(0)
-#define CHIP_92C_1T2R BIT(1)
-#define CHIP_8723 BIT(2) /* RTL8723 With BT feature */
-#define CHIP_8723_DRV_REV BIT(3) /* RTL8723 Driver Revised */
-#define NORMAL_CHIP BIT(4)
-#define CHIP_VENDOR_UMC BIT(5)
-#define CHIP_VENDOR_UMC_B_CUT BIT(6) /* Chip version for ECO */
+enum version_8192d {
+ VERSION_TEST_CHIP_88C = 0x0000,
+ VERSION_TEST_CHIP_92C = 0x0020,
+ VERSION_TEST_UMC_CHIP_8723 = 0x0081,
+ VERSION_NORMAL_TSMC_CHIP_88C = 0x0008,
+ VERSION_NORMAL_TSMC_CHIP_92C = 0x0028,
+ VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x0018,
+ VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x0088,
+ VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x00a8,
+ VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x0098,
+ VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT = 0x0089,
+ VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT = 0x1089,
+ VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x1088,
+ VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x10a8,
+ VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x1090,
+ VERSION_TEST_CHIP_92D_SINGLEPHY = 0x0022,
+ VERSION_TEST_CHIP_92D_DUALPHY = 0x0002,
+ VERSION_NORMAL_CHIP_92D_SINGLEPHY = 0x002a,
+ VERSION_NORMAL_CHIP_92D_DUALPHY = 0x000a,
+ VERSION_NORMAL_CHIP_92D_C_CUT_SINGLEPHY = 0x202a,
+ VERSION_NORMAL_CHIP_92D_C_CUT_DUALPHY = 0x200a,
+ VERSION_NORMAL_CHIP_92D_D_CUT_SINGLEPHY = 0x302a,
+ VERSION_NORMAL_CHIP_92D_D_CUT_DUALPHY = 0x300a,
+ VERSION_NORMAL_CHIP_92D_E_CUT_SINGLEPHY = 0x402a,
+ VERSION_NORMAL_CHIP_92D_E_CUT_DUALPHY = 0x400a,
+};
/* for 92D */
-#define CHIP_92D BIT(8)
#define CHIP_92D_SINGLEPHY BIT(9)
+#define C_CUT_VERSION BIT(13)
+#define D_CUT_VERSION ((BIT(12)|BIT(13)))
+#define E_CUT_VERSION BIT(14)
+
+/* Chip specific */
+#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3)
+#define CHIP_BONDING_92C_1T2R 0x1
+#define CHIP_BONDING_88C_USB_MCARD 0x2
+#define CHIP_BONDING_88C_USB_HP 0x1
+
+/* [15:12] IC version(CUT): A-cut=0, B-cut=1, C-cut=2, D-cut=3 */
+/* [7] Manufacturer: TSMC=0, UMC=1 */
+/* [6:4] RF type: 1T1R=0, 1T2R=1, 2T2R=2 */
+/* [3] Chip type: TEST=0, NORMAL=1 */
+/* [2:0] IC type: 81xxC=0, 8723=1, 92D=2 */
+#define CHIP_8723 BIT(0)
+#define CHIP_92D BIT(1)
+#define NORMAL_CHIP BIT(3)
+#define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6)))
+#define RF_TYPE_1T2R BIT(4)
+#define RF_TYPE_2T2R BIT(5)
+#define CHIP_VENDOR_UMC BIT(7)
+#define B_CUT_VERSION BIT(12)
+
+/* 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_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK)
+#define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK)
+#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK)
+#define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK)
+#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK)
+
+#define IS_1T1R(version) ((GET_CVID_RF_TYPE(version)) ? \
+ false : true)
+#define IS_1T2R(version) ((GET_CVID_RF_TYPE(version) == \
+ RF_TYPE_1T2R) ? true : false)
+#define IS_2T2R(version) ((GET_CVID_RF_TYPE(version) == \
+ RF_TYPE_2T2R) ? true : false)
+
+#define IS_92D_SINGLEPHY(version) ((IS_92D(version)) ? \
+ (IS_2T2R(version) ? true : false) : false)
+#define IS_92D(version) ((GET_CVID_IC_TYPE(version) == \
+ CHIP_92D) ? true : false)
+#define IS_92D_C_CUT(version) ((IS_92D(version)) ? \
+ ((GET_CVID_CUT_VERSION(version) == \
+ 0x2000) ? true : false) : false)
+#define IS_92D_D_CUT(version) ((IS_92D(version)) ? \
+ ((GET_CVID_CUT_VERSION(version) == \
+ 0x3000) ? true : false) : false)
+#define IS_92D_E_CUT(version) ((IS_92D(version)) ? \
+ ((GET_CVID_CUT_VERSION(version) == \
+ 0x4000) ? true : false) : false)
#define CHIP_92D_C_CUT BIT(10)
#define CHIP_92D_D_CUT BIT(11)
-enum version_8192d {
- VERSION_TEST_CHIP_88C = 0x00,
- VERSION_TEST_CHIP_92C = 0x01,
- VERSION_NORMAL_TSMC_CHIP_88C = 0x10,
- VERSION_NORMAL_TSMC_CHIP_92C = 0x11,
- VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x13,
- VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x30,
- VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x31,
- VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x33,
- VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT = 0x34,
- VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT = 0x3c,
- VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x70,
- VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x71,
- VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x73,
- VERSION_TEST_CHIP_92D_SINGLEPHY = 0x300,
- VERSION_TEST_CHIP_92D_DUALPHY = 0x100,
- VERSION_NORMAL_CHIP_92D_SINGLEPHY = 0x310,
- VERSION_NORMAL_CHIP_92D_DUALPHY = 0x110,
- VERSION_NORMAL_CHIP_92D_C_CUT_SINGLEPHY = 0x710,
- VERSION_NORMAL_CHIP_92D_C_CUT_DUALPHY = 0x510,
- VERSION_NORMAL_CHIP_92D_D_CUT_SINGLEPHY = 0xB10,
- VERSION_NORMAL_CHIP_92D_D_CUT_DUALPHY = 0x910,
-};
-
-#define IS_92D_SINGLEPHY(version) \
- ((version & CHIP_92D_SINGLEPHY) ? true : false)
-#define IS_92D_C_CUT(version) \
- ((version & CHIP_92D_C_CUT) ? true : false)
-#define IS_92D_D_CUT(version) \
- ((version & CHIP_92D_D_CUT) ? true : false)
-
enum rf_optype {
RF_OP_BY_SW_3WIRE = 0,
RF_OP_BY_FW,
@@ -193,41 +232,6 @@ enum rtl_desc_qsel {
QSLT_CMD = 0x13,
};
-enum rtl_desc92d_rate {
- DESC92D_RATE1M = 0x00,
- DESC92D_RATE2M = 0x01,
- DESC92D_RATE5_5M = 0x02,
- DESC92D_RATE11M = 0x03,
-
- DESC92D_RATE6M = 0x04,
- DESC92D_RATE9M = 0x05,
- DESC92D_RATE12M = 0x06,
- DESC92D_RATE18M = 0x07,
- DESC92D_RATE24M = 0x08,
- DESC92D_RATE36M = 0x09,
- DESC92D_RATE48M = 0x0a,
- DESC92D_RATE54M = 0x0b,
-
- DESC92D_RATEMCS0 = 0x0c,
- DESC92D_RATEMCS1 = 0x0d,
- DESC92D_RATEMCS2 = 0x0e,
- DESC92D_RATEMCS3 = 0x0f,
- DESC92D_RATEMCS4 = 0x10,
- DESC92D_RATEMCS5 = 0x11,
- DESC92D_RATEMCS6 = 0x12,
- DESC92D_RATEMCS7 = 0x13,
- DESC92D_RATEMCS8 = 0x14,
- DESC92D_RATEMCS9 = 0x15,
- DESC92D_RATEMCS10 = 0x16,
- DESC92D_RATEMCS11 = 0x17,
- DESC92D_RATEMCS12 = 0x18,
- DESC92D_RATEMCS13 = 0x19,
- DESC92D_RATEMCS14 = 0x1a,
- DESC92D_RATEMCS15 = 0x1b,
- DESC92D_RATEMCS15_SG = 0x1c,
- DESC92D_RATEMCS32 = 0x20,
-};
-
enum channel_plan {
CHPL_FCC = 0,
CHPL_IC = 1,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
index 0073cf106af2..f5bd3a3cd34a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
@@ -1608,17 +1608,16 @@ static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw,
tempval[0] = hwinfo[EEPROM_IQK_DELTA] & 0x03;
tempval[1] = (hwinfo[EEPROM_LCK_DELTA] & 0x0C) >> 2;
rtlefuse->txpwr_fromeprom = true;
- if (IS_92D_D_CUT(rtlpriv->rtlhal.version)) {
+ if (IS_92D_D_CUT(rtlpriv->rtlhal.version) ||
+ IS_92D_E_CUT(rtlpriv->rtlhal.version)) {
rtlefuse->internal_pa_5g[0] =
- !((hwinfo[EEPROM_TSSI_A_5G] &
- BIT(6)) >> 6);
+ !((hwinfo[EEPROM_TSSI_A_5G] & BIT(6)) >> 6);
rtlefuse->internal_pa_5g[1] =
- !((hwinfo[EEPROM_TSSI_B_5G] &
- BIT(6)) >> 6);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+ !((hwinfo[EEPROM_TSSI_B_5G] & BIT(6)) >> 6);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
("Is D cut,Internal PA0 %d Internal PA1 %d\n",
- rtlefuse->internal_pa_5g[0],
- rtlefuse->internal_pa_5g[1]))
+ rtlefuse->internal_pa_5g[0],
+ rtlefuse->internal_pa_5g[1]))
}
rtlefuse->eeprom_c9 = hwinfo[EEPROM_RF_OPT6];
rtlefuse->eeprom_cc = hwinfo[EEPROM_RF_OPT7];
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
index 351765df517d..691f80092185 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
@@ -146,10 +146,16 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD);
+ /* 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;
+ if (!rtlpriv->psc.inactiveps)
+ pr_info("rtl8192ce: Power Save off (module option)\n");
+ if (!rtlpriv->psc.fwctrl_lps)
+ pr_info("rtl8192ce: FW Power Save off (module option)\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
/* for ASPM, you can close aspm through
@@ -263,6 +269,7 @@ static struct rtl_mod_params rtl92de_mod_params = {
.inactiveps = true,
.swctrl_lps = true,
.fwctrl_lps = false,
+ .debug = DBG_EMERG,
};
static struct rtl_hal_cfg rtl92de_hal_cfg = {
@@ -340,21 +347,21 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = {
.maps[RTL_IMR_ROK] = IMR_ROK,
.maps[RTL_IBSS_INT_MASKS] = (IMR_BcnInt | IMR_TBDOK | IMR_TBDER),
- .maps[RTL_RC_CCK_RATE1M] = DESC92D_RATE1M,
- .maps[RTL_RC_CCK_RATE2M] = DESC92D_RATE2M,
- .maps[RTL_RC_CCK_RATE5_5M] = DESC92D_RATE5_5M,
- .maps[RTL_RC_CCK_RATE11M] = DESC92D_RATE11M,
- .maps[RTL_RC_OFDM_RATE6M] = DESC92D_RATE6M,
- .maps[RTL_RC_OFDM_RATE9M] = DESC92D_RATE9M,
- .maps[RTL_RC_OFDM_RATE12M] = DESC92D_RATE12M,
- .maps[RTL_RC_OFDM_RATE18M] = DESC92D_RATE18M,
- .maps[RTL_RC_OFDM_RATE24M] = DESC92D_RATE24M,
- .maps[RTL_RC_OFDM_RATE36M] = DESC92D_RATE36M,
- .maps[RTL_RC_OFDM_RATE48M] = DESC92D_RATE48M,
- .maps[RTL_RC_OFDM_RATE54M] = DESC92D_RATE54M,
-
- .maps[RTL_RC_HT_RATEMCS7] = DESC92D_RATEMCS7,
- .maps[RTL_RC_HT_RATEMCS15] = DESC92D_RATEMCS15,
+ .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 rtl92de_pci_ids[] __devinitdata = {
@@ -373,25 +380,31 @@ MODULE_DESCRIPTION("Realtek 8192DE 802.11n Dual Mac PCI wireless");
MODULE_FIRMWARE("rtlwifi/rtl8192defw.bin");
module_param_named(swenc, rtl92de_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug, rtl92de_mod_params.debug, int, 0444);
module_param_named(ips, rtl92de_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl92de_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444);
-MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
-MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
-MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1"
- " is open)\n");
+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 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 struct pci_driver rtl92de_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl92de_pci_ids,
.probe = rtl_pci_probe,
.remove = rtl_pci_disconnect,
-
-#ifdef CONFIG_PM
- .suspend = rtl_pci_suspend,
- .resume = rtl_pci_resume,
-#endif
-
+ .driver.pm = &rtlwifi_pm_ops,
};
/* add global spin lock to solve the problem that
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
index dc86fcb0b3a3..3637c0c33525 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
@@ -48,99 +48,6 @@ static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
return skb->priority;
}
-static int _rtl92de_rate_mapping(bool isht, u8 desc_rate)
-{
- int rate_idx;
-
- if (false == isht) {
- switch (desc_rate) {
- case DESC92D_RATE1M:
- rate_idx = 0;
- break;
- case DESC92D_RATE2M:
- rate_idx = 1;
- break;
- case DESC92D_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92D_RATE11M:
- rate_idx = 3;
- break;
- case DESC92D_RATE6M:
- rate_idx = 4;
- break;
- case DESC92D_RATE9M:
- rate_idx = 5;
- break;
- case DESC92D_RATE12M:
- rate_idx = 6;
- break;
- case DESC92D_RATE18M:
- rate_idx = 7;
- break;
- case DESC92D_RATE24M:
- rate_idx = 8;
- break;
- case DESC92D_RATE36M:
- rate_idx = 9;
- break;
- case DESC92D_RATE48M:
- rate_idx = 10;
- break;
- case DESC92D_RATE54M:
- rate_idx = 11;
- break;
- default:
- rate_idx = 0;
- break;
- }
- return rate_idx;
- } else {
- switch (desc_rate) {
- case DESC92D_RATE1M:
- rate_idx = 0;
- break;
- case DESC92D_RATE2M:
- rate_idx = 1;
- break;
- case DESC92D_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92D_RATE11M:
- rate_idx = 3;
- break;
- case DESC92D_RATE6M:
- rate_idx = 4;
- break;
- case DESC92D_RATE9M:
- rate_idx = 5;
- break;
- case DESC92D_RATE12M:
- rate_idx = 6;
- break;
- case DESC92D_RATE18M:
- rate_idx = 7;
- break;
- case DESC92D_RATE24M:
- rate_idx = 8;
- break;
- case DESC92D_RATE36M:
- rate_idx = 9;
- break;
- case DESC92D_RATE48M:
- rate_idx = 10;
- break;
- case DESC92D_RATE54M:
- rate_idx = 11;
- break;
- default:
- rate_idx = 11;
- break;
- }
- return rate_idx;
- }
-}
-
static u8 _rtl92d_query_rxpwrpercentage(char antpower)
{
if ((antpower <= -100) || (antpower >= 20))
@@ -328,8 +235,8 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
pstats->rx_pwdb_all = pwdb_all;
pstats->rxpower = rx_pwr_all;
pstats->recvsignalpower = rx_pwr_all;
- if (pdesc->rxht && pdesc->rxmcs >= DESC92D_RATEMCS8 &&
- pdesc->rxmcs <= DESC92D_RATEMCS15)
+ if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 &&
+ pdesc->rxmcs <= DESC92_RATEMCS15)
max_spatial_stream = 2;
else
max_spatial_stream = 1;
@@ -609,10 +516,10 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
if (stats->decrypted)
rx_status->flag |= RX_FLAG_DECRYPTED;
- rx_status->rate_idx = _rtl92de_rate_mapping((bool)
- GET_RX_DESC_RXHT(pdesc),
- (u8)
- GET_RX_DESC_RXMCS(pdesc));
+ rx_status->rate_idx = rtlwifi_rate_mapping(hw,
+ (bool)GET_RX_DESC_RXHT(pdesc),
+ (u8)GET_RX_DESC_RXMCS(pdesc),
+ (bool)GET_RX_DESC_PAGGR(pdesc));
rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
if (phystatus) {
p_drvinfo = (struct rx_fwinfo_92d *)(skb->data +
@@ -705,14 +612,14 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
}
/* 5G have no CCK rate */
if (rtlhal->current_bandtype == BAND_ON_5G)
- if (ptcb_desc->hw_rate < DESC92D_RATE6M)
- ptcb_desc->hw_rate = DESC92D_RATE6M;
+ if (ptcb_desc->hw_rate < DESC92_RATE6M)
+ ptcb_desc->hw_rate = DESC92_RATE6M;
SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble)
SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
if (rtlhal->macphymode == DUALMAC_DUALPHY &&
- ptcb_desc->hw_rate == DESC92D_RATEMCS7)
+ ptcb_desc->hw_rate == DESC92_RATEMCS7)
SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
@@ -728,13 +635,13 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));
/* 5G have no CCK rate */
if (rtlhal->current_bandtype == BAND_ON_5G)
- if (ptcb_desc->rts_rate < DESC92D_RATE6M)
- ptcb_desc->rts_rate = DESC92D_RATE6M;
+ if (ptcb_desc->rts_rate < DESC92_RATE6M)
+ ptcb_desc->rts_rate = DESC92_RATE6M;
SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate);
SET_TX_DESC_RTS_BW(pdesc, 0);
SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc);
SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <=
- DESC92D_RATE54M) ?
+ DESC92_RATE54M) ?
(ptcb_desc->rts_use_shortpreamble ? 1 : 0) :
(ptcb_desc->rts_use_shortgi ? 1 : 0)));
if (bw_40) {
@@ -844,9 +751,9 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,
* The braces are needed no matter what checkpatch says
*/
if (rtlhal->current_bandtype == BAND_ON_5G) {
- SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE6M);
+ SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE6M);
} else {
- SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE1M);
+ SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M);
}
SET_TX_DESC_SEQ(pdesc, 0);
SET_TX_DESC_LINIP(pdesc, 0);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h
index 992d6766e667..4d55d0b6816d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h
@@ -537,12 +537,6 @@ do { \
memset((void *)__pdesc, 0, _size); \
} while (0);
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
- (_pdesc->rxmcs == DESC92D_RATE1M || \
- _pdesc->rxmcs == DESC92D_RATE2M || \
- _pdesc->rxmcs == DESC92D_RATE5_5M || \
- _pdesc->rxmcs == DESC92D_RATE11M)
-
/* For 92D early mode */
#define SET_EARLYMODE_PKTNUM(__paddr, __value) \
SET_BITS_OFFSET_LE(__paddr, 0, 3, __value)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
index 69828f2b3fab..c6c044816d39 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
@@ -33,37 +33,6 @@
#define RX_CMD_QUEUE 1
#define RX_MAX_QUEUE 2
-#define DESC92S_RATE1M 0x00
-#define DESC92S_RATE2M 0x01
-#define DESC92S_RATE5_5M 0x02
-#define DESC92S_RATE11M 0x03
-#define DESC92S_RATE6M 0x04
-#define DESC92S_RATE9M 0x05
-#define DESC92S_RATE12M 0x06
-#define DESC92S_RATE18M 0x07
-#define DESC92S_RATE24M 0x08
-#define DESC92S_RATE36M 0x09
-#define DESC92S_RATE48M 0x0a
-#define DESC92S_RATE54M 0x0b
-#define DESC92S_RATEMCS0 0x0c
-#define DESC92S_RATEMCS1 0x0d
-#define DESC92S_RATEMCS2 0x0e
-#define DESC92S_RATEMCS3 0x0f
-#define DESC92S_RATEMCS4 0x10
-#define DESC92S_RATEMCS5 0x11
-#define DESC92S_RATEMCS6 0x12
-#define DESC92S_RATEMCS7 0x13
-#define DESC92S_RATEMCS8 0x14
-#define DESC92S_RATEMCS9 0x15
-#define DESC92S_RATEMCS10 0x16
-#define DESC92S_RATEMCS11 0x17
-#define DESC92S_RATEMCS12 0x18
-#define DESC92S_RATEMCS13 0x19
-#define DESC92S_RATEMCS14 0x1a
-#define DESC92S_RATEMCS15 0x1b
-#define DESC92S_RATEMCS15_SG 0x1c
-#define DESC92S_RATEMCS32 0x20
-
#define SHORT_SLOT_TIME 9
#define NON_SHORT_SLOT_TIME 20
@@ -490,11 +459,11 @@ do { \
#define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val)
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
- (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE1M || \
- GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE2M || \
- GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE5_5M ||\
- GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE11M)
+#define SE_RX_HAL_IS_CCK_RATE(_pdesc)\
+ (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \
+ GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE2M || \
+ GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\
+ GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE11M)
enum rf_optype {
RF_OP_BY_SW_3WIRE = 0,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index d59f66cb7768..c474486e3911 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -1382,7 +1382,7 @@ static void _rtl92se_power_domain_init(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34);
/* Reset MAC-IO and CPU and Core Digital BIT10/11/15 */
- tmpu1b = rtl_read_byte(rtlpriv, SYS_FUNC_EN + 1);
+ tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
/* If IPS we need to turn LED on. So we not
* not disable BIT 3/7 of reg3. */
@@ -1391,7 +1391,7 @@ static void _rtl92se_power_domain_init(struct ieee80211_hw *hw)
else
tmpu1b &= 0x73;
- rtl_write_byte(rtlpriv, SYS_FUNC_EN + 1, tmpu1b);
+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b);
/* wait for BIT 10/11/15 to pull high automatically!! */
mdelay(1);
@@ -1428,15 +1428,15 @@ static void _rtl92se_power_domain_init(struct ieee80211_hw *hw)
rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0)));
/* Set Digital Vdd to Retention isolation Path. */
- tmpu2b = rtl_read_word(rtlpriv, SYS_ISO_CTRL);
- rtl_write_word(rtlpriv, SYS_ISO_CTRL, (tmpu2b | BIT(11)));
+ tmpu2b = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL);
+ rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, (tmpu2b | BIT(11)));
/* For warm reboot NIC disappera bug. */
- tmpu2b = rtl_read_word(rtlpriv, SYS_FUNC_EN);
- rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(13)));
+ tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(13)));
- rtl_write_byte(rtlpriv, SYS_ISO_CTRL + 1, 0x68);
+ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x68);
/* Enable AFE PLL Macro Block */
tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL);
@@ -1447,17 +1447,17 @@ static void _rtl92se_power_domain_init(struct ieee80211_hw *hw)
mdelay(1);
/* Release isolation AFE PLL & MD */
- rtl_write_byte(rtlpriv, SYS_ISO_CTRL, 0xA6);
+ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xA6);
/* Enable MAC clock */
tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR);
rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11)));
/* Enable Core digital and enable IOREG R/W */
- tmpu2b = rtl_read_word(rtlpriv, SYS_FUNC_EN);
- rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(11)));
+ tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11)));
/* enable REG_EN */
- rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15)));
+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15)));
/* Switch the control path. */
tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
index ea32ef2d4098..11f125c030ce 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
@@ -735,6 +735,7 @@
#define HWSET_MAX_SIZE_92S 128
#define EFUSE_MAX_SECTION 16
#define EFUSE_REAL_CONTENT_LEN 512
+#define EFUSE_OOB_PROTECT_BYTES 15
#define RTL8190_EEPROM_ID 0x8129
#define EEPROM_HPON 0x02
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index 3876078a63de..3ec9a0d41baf 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -160,10 +160,16 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
rtlpci->first_init = true;
+ /* 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;
+ if (!rtlpriv->psc.inactiveps)
+ pr_info("rtl8192ce: Power Save off (module option)\n");
+ if (!rtlpriv->psc.fwctrl_lps)
+ pr_info("rtl8192ce: FW Power Save off (module option)\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
/* for ASPM, you can close aspm through
@@ -268,6 +274,7 @@ static struct rtl_mod_params rtl92se_mod_params = {
.inactiveps = true,
.swctrl_lps = true,
.fwctrl_lps = false,
+ .debug = DBG_EMERG,
};
/* Because memory R/W bursting will cause system hang/crash
@@ -300,6 +307,7 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = {
.maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE_92S,
.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_RWCAM,
.maps[WCAMI] = REG_WCAMI,
@@ -348,21 +356,21 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = {
.maps[RTL_IMR_ROK] = IMR_ROK,
.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER),
- .maps[RTL_RC_CCK_RATE1M] = DESC92S_RATE1M,
- .maps[RTL_RC_CCK_RATE2M] = DESC92S_RATE2M,
- .maps[RTL_RC_CCK_RATE5_5M] = DESC92S_RATE5_5M,
- .maps[RTL_RC_CCK_RATE11M] = DESC92S_RATE11M,
- .maps[RTL_RC_OFDM_RATE6M] = DESC92S_RATE6M,
- .maps[RTL_RC_OFDM_RATE9M] = DESC92S_RATE9M,
- .maps[RTL_RC_OFDM_RATE12M] = DESC92S_RATE12M,
- .maps[RTL_RC_OFDM_RATE18M] = DESC92S_RATE18M,
- .maps[RTL_RC_OFDM_RATE24M] = DESC92S_RATE24M,
- .maps[RTL_RC_OFDM_RATE36M] = DESC92S_RATE36M,
- .maps[RTL_RC_OFDM_RATE48M] = DESC92S_RATE48M,
- .maps[RTL_RC_OFDM_RATE54M] = DESC92S_RATE54M,
-
- .maps[RTL_RC_HT_RATEMCS7] = DESC92S_RATEMCS7,
- .maps[RTL_RC_HT_RATEMCS15] = DESC92S_RATEMCS15,
+ .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 rtl92se_pci_ids[] __devinitdata = {
@@ -378,31 +386,37 @@ MODULE_DEVICE_TABLE(pci, rtl92se_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 8192S/8191S 802.11n PCI wireless");
MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin");
module_param_named(swenc, rtl92se_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug, rtl92se_mod_params.debug, int, 0444);
module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444);
-MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
-MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
-MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1 is "
- "open)\n");
+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 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 struct pci_driver rtl92se_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl92se_pci_ids,
.probe = rtl_pci_probe,
.remove = rtl_pci_disconnect,
-
-#ifdef CONFIG_PM
- .suspend = rtl_pci_suspend,
- .resume = rtl_pci_resume,
-#endif
-
+ .driver.pm = &rtlwifi_pm_ops,
};
static int __init rtl92se_module_init(void)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index cffe30851f79..fbebe3ea0a22 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -51,104 +51,6 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue)
return skb->priority;
}
-static int _rtl92se_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu)
-{
- int rate_idx = 0;
-
- if (first_ampdu) {
- if (false == isht) {
- switch (desc_rate) {
- case DESC92S_RATE1M:
- rate_idx = 0;
- break;
- case DESC92S_RATE2M:
- rate_idx = 1;
- break;
- case DESC92S_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92S_RATE11M:
- rate_idx = 3;
- break;
- case DESC92S_RATE6M:
- rate_idx = 4;
- break;
- case DESC92S_RATE9M:
- rate_idx = 5;
- break;
- case DESC92S_RATE12M:
- rate_idx = 6;
- break;
- case DESC92S_RATE18M:
- rate_idx = 7;
- break;
- case DESC92S_RATE24M:
- rate_idx = 8;
- break;
- case DESC92S_RATE36M:
- rate_idx = 9;
- break;
- case DESC92S_RATE48M:
- rate_idx = 10;
- break;
- case DESC92S_RATE54M:
- rate_idx = 11;
- break;
- default:
- rate_idx = 0;
- break;
- }
- } else {
- rate_idx = 11;
- }
-
- return rate_idx;
- }
-
- switch (desc_rate) {
- case DESC92S_RATE1M:
- rate_idx = 0;
- break;
- case DESC92S_RATE2M:
- rate_idx = 1;
- break;
- case DESC92S_RATE5_5M:
- rate_idx = 2;
- break;
- case DESC92S_RATE11M:
- rate_idx = 3;
- break;
- case DESC92S_RATE6M:
- rate_idx = 4;
- break;
- case DESC92S_RATE9M:
- rate_idx = 5;
- break;
- case DESC92S_RATE12M:
- rate_idx = 6;
- break;
- case DESC92S_RATE18M:
- rate_idx = 7;
- break;
- case DESC92S_RATE24M:
- rate_idx = 8;
- break;
- case DESC92S_RATE36M:
- rate_idx = 9;
- break;
- case DESC92S_RATE48M:
- rate_idx = 10;
- break;
- case DESC92S_RATE54M:
- rate_idx = 11;
- break;
- default:
- rate_idx = 11;
- break;
- }
- return rate_idx;
-}
-
static u8 _rtl92s_query_rxpwrpercentage(char antpower)
{
if ((antpower <= -100) || (antpower >= 20))
@@ -222,18 +124,15 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
u8 i, max_spatial_stream;
u32 rssi, total_rssi = 0;
bool in_powersavemode = false;
- bool is_cck_rate;
+ bool is_cck = pstats->is_cck;
- is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
pstats->packet_matchbssid = packet_match_bssid;
pstats->packet_toself = packet_toself;
- 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;
- if (is_cck_rate) {
+ if (is_cck) {
u8 report, cck_highpwr;
cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
@@ -344,9 +243,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
pstats->rxpower = rx_pwr_all;
pstats->recvsignalpower = rx_pwr_all;
- if (GET_RX_STATUS_DESC_RX_HT(pdesc) &&
- GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92S_RATEMCS8 &&
- GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92S_RATEMCS15)
+ if (pstats->is_ht && pstats->rate >= DESC92_RATEMCS8 &&
+ pstats->rate <= DESC92_RATEMCS15)
max_spatial_stream = 2;
else
max_spatial_stream = 1;
@@ -364,7 +262,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
}
}
- if (is_cck_rate)
+ if (is_cck)
pstats->signalstrength = (u8)(_rtl92se_signal_scale_mapping(hw,
pwdb_all));
else if (rf_rx_num != 0)
@@ -616,6 +514,8 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
{
struct rx_fwinfo *p_drvinfo;
u32 phystatus = (u32)GET_RX_STATUS_DESC_PHY_STATUS(pdesc);
+ struct ieee80211_hdr *hdr;
+ bool first_ampdu = false;
stats->length = (u16)GET_RX_STATUS_DESC_PKT_LEN(pdesc);
stats->rx_drvinfo_size = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE(pdesc) * 8;
@@ -628,8 +528,12 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
stats->rate = (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc);
stats->shortpreamble = (u16)GET_RX_STATUS_DESC_SPLCP(pdesc);
stats->isampdu = (bool)(GET_RX_STATUS_DESC_PAGGR(pdesc) == 1);
+ stats->isfirst_ampdu = (bool) ((GET_RX_STATUS_DESC_PAGGR(pdesc) == 1)
+ && (GET_RX_STATUS_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc);
stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc);
+ stats->is_ht = (bool)GET_RX_STATUS_DESC_RX_HT(pdesc);
+ stats->is_cck = SE_RX_HAL_IS_CCK_RATE(pdesc);
if (stats->hwerror)
return false;
@@ -637,30 +541,39 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
rx_status->freq = hw->conf.channel->center_freq;
rx_status->band = hw->conf.channel->band;
- if (GET_RX_STATUS_DESC_CRC32(pdesc))
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size
+ + stats->rx_bufshift);
- if (!GET_RX_STATUS_DESC_SWDEC(pdesc))
- rx_status->flag |= RX_FLAG_DECRYPTED;
+ if (stats->crc)
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (GET_RX_STATUS_DESC_BW(pdesc))
+ if (stats->rx_is40Mhzpacket)
rx_status->flag |= RX_FLAG_40MHZ;
- if (GET_RX_STATUS_DESC_RX_HT(pdesc))
+ if (stats->is_ht)
rx_status->flag |= RX_FLAG_HT;
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
- if (stats->decrypted)
- rx_status->flag |= RX_FLAG_DECRYPTED;
-
- rx_status->rate_idx = _rtl92se_rate_mapping((bool)
- GET_RX_STATUS_DESC_RX_HT(pdesc),
- (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc),
- (bool)GET_RX_STATUS_DESC_PAGGR(pdesc));
+ /* hw will set stats->decrypted true, if it finds the
+ * frame is open data frame or mgmt frame,
+ * hw will not decrypt robust managment frame
+ * for IEEE80211w but still set stats->decrypted
+ * true, so here we should set it back to undecrypted
+ * for IEEE80211w frame, and mac80211 sw will help
+ * to decrypt it */
+ if (stats->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;
+ }
+ rx_status->rate_idx = rtlwifi_rate_mapping(hw,
+ stats->is_ht, stats->rate, first_ampdu);
- rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc);
+ rx_status->mactime = stats->timestamp_low;
if (phystatus) {
p_drvinfo = (struct rx_fwinfo *)(skb->data +
stats->rx_bufshift);
@@ -723,14 +636,14 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid);
SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >=
- DESC92S_RATEMCS0) ? 1 : 0));
+ DESC92_RATEMCS0) ? 1 : 0));
if (rtlhal->version == VERSION_8192S_ACUT) {
- if (ptcb_desc->hw_rate == DESC92S_RATE1M ||
- ptcb_desc->hw_rate == DESC92S_RATE2M ||
- ptcb_desc->hw_rate == DESC92S_RATE5_5M ||
- ptcb_desc->hw_rate == DESC92S_RATE11M) {
- ptcb_desc->hw_rate = DESC92S_RATE12M;
+ if (ptcb_desc->hw_rate == DESC92_RATE1M ||
+ ptcb_desc->hw_rate == DESC92_RATE2M ||
+ ptcb_desc->hw_rate == DESC92_RATE5_5M ||
+ ptcb_desc->hw_rate == DESC92_RATE11M) {
+ ptcb_desc->hw_rate = DESC92_RATE12M;
}
}
@@ -759,7 +672,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0);
SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc);
SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <=
- DESC92S_RATE54M) ?
+ DESC92_RATE54M) ?
(ptcb_desc->rts_use_shortpreamble ? 1 : 0)
: (ptcb_desc->rts_use_shortgi ? 1 : 0)));
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index 4bf3cf457ef0..b42c2e2b2055 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -191,44 +191,6 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val)
_usb_write_async(to_usb_device(dev), addr, val, 4);
}
-static int _usb_nbytes_read_write(struct usb_device *udev, bool read, u32 addr,
- u16 len, u8 *pdata)
-{
- int status;
- u8 request;
- u16 wvalue;
- u16 index;
-
- request = REALTEK_USB_VENQT_CMD_REQ;
- index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
- wvalue = (u16)addr;
- if (read)
- status = _usbctrl_vendorreq_sync_read(udev, request, wvalue,
- index, pdata, len);
- else
- status = _usbctrl_vendorreq_async_write(udev, request, wvalue,
- index, pdata, len);
- return status;
-}
-
-static int _usb_readN_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len,
- u8 *pdata)
-{
- struct device *dev = rtlpriv->io.dev;
-
- return _usb_nbytes_read_write(to_usb_device(dev), true, addr, len,
- pdata);
-}
-
-static int _usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, u16 len,
- u8 *pdata)
-{
- struct device *dev = rtlpriv->io.dev;
-
- return _usb_nbytes_read_write(to_usb_device(dev), false, addr, len,
- pdata);
-}
-
static void _rtl_usb_io_handler_init(struct device *dev,
struct ieee80211_hw *hw)
{
@@ -239,11 +201,9 @@ static void _rtl_usb_io_handler_init(struct device *dev,
rtlpriv->io.write8_async = _usb_write8_async;
rtlpriv->io.write16_async = _usb_write16_async;
rtlpriv->io.write32_async = _usb_write32_async;
- rtlpriv->io.writeN_async = _usb_writeN_async;
rtlpriv->io.read8_sync = _usb_read8_sync;
rtlpriv->io.read16_sync = _usb_read16_sync;
rtlpriv->io.read32_sync = _usb_read32_sync;
- rtlpriv->io.readN_sync = _usb_readN_sync;
}
static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index d3c3ffd38984..713c7ddba8eb 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -165,6 +165,12 @@ enum hardware_type {
#define IS_HARDWARE_TYPE_8723U(rtlhal) \
(rtlhal->hw_type == HARDWARE_TYPE_RTL8723U)
+#define RX_HAL_IS_CCK_RATE(_pdesc)\
+ (_pdesc->rxmcs == DESC92_RATE1M || \
+ _pdesc->rxmcs == DESC92_RATE2M || \
+ _pdesc->rxmcs == DESC92_RATE5_5M || \
+ _pdesc->rxmcs == DESC92_RATE11M)
+
enum scan_operation_backup_opt {
SCAN_OPT_BACKUP = 0,
SCAN_OPT_RESTORE,
@@ -386,6 +392,41 @@ enum rtl_hal_state {
_HAL_STATE_START = 1,
};
+enum rtl_desc92_rate {
+ DESC92_RATE1M = 0x00,
+ DESC92_RATE2M = 0x01,
+ DESC92_RATE5_5M = 0x02,
+ DESC92_RATE11M = 0x03,
+
+ DESC92_RATE6M = 0x04,
+ DESC92_RATE9M = 0x05,
+ DESC92_RATE12M = 0x06,
+ DESC92_RATE18M = 0x07,
+ DESC92_RATE24M = 0x08,
+ DESC92_RATE36M = 0x09,
+ DESC92_RATE48M = 0x0a,
+ DESC92_RATE54M = 0x0b,
+
+ DESC92_RATEMCS0 = 0x0c,
+ DESC92_RATEMCS1 = 0x0d,
+ DESC92_RATEMCS2 = 0x0e,
+ DESC92_RATEMCS3 = 0x0f,
+ DESC92_RATEMCS4 = 0x10,
+ DESC92_RATEMCS5 = 0x11,
+ DESC92_RATEMCS6 = 0x12,
+ DESC92_RATEMCS7 = 0x13,
+ DESC92_RATEMCS8 = 0x14,
+ DESC92_RATEMCS9 = 0x15,
+ DESC92_RATEMCS10 = 0x16,
+ DESC92_RATEMCS11 = 0x17,
+ DESC92_RATEMCS12 = 0x18,
+ DESC92_RATEMCS13 = 0x19,
+ DESC92_RATEMCS14 = 0x1a,
+ DESC92_RATEMCS15 = 0x1b,
+ DESC92_RATEMCS15_SG = 0x1c,
+ DESC92_RATEMCS32 = 0x20,
+};
+
enum rtl_var_map {
/*reg map */
SYS_ISO_CTRL = 0,
@@ -409,6 +450,7 @@ enum rtl_var_map {
EFUSE_HWSET_MAX_SIZE,
EFUSE_MAX_SECTION_MAP,
EFUSE_REAL_CONTENT_SIZE,
+ EFUSE_OOB_PROTECT_BYTES_LEN,
/*CAM map */
RWCAM,
@@ -901,16 +943,12 @@ struct rtl_io {
unsigned long pci_base_addr; /*device I/O address */
void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val);
- void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val);
- void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val);
- int (*writeN_async) (struct rtl_priv *rtlpriv, u32 addr, u16 len,
- u8 *pdata);
+ void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, __le16 val);
+ void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, __le32 val);
u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr);
u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr);
u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr);
- int (*readN_sync) (struct rtl_priv *rtlpriv, u32 addr, u16 len,
- u8 *pdata);
};
@@ -1287,6 +1325,7 @@ struct rtl_stats {
s8 rx_mimo_signalquality[2];
bool packet_matchbssid;
bool is_cck;
+ bool is_ht;
bool packet_toself;
bool packet_beacon; /*for rssi */
char cck_adc_pwdb[4]; /*for rx path selection */
@@ -1448,6 +1487,9 @@ struct rtl_mod_params {
/* default: 0 = using hardware encryption */
int sw_crypto;
+ /* default: 0 = DBG_EMERG (0)*/
+ int debug;
+
/* default: 1 = using no linked power save */
bool inactiveps;
diff --git a/drivers/net/wireless/wl1251/cmd.h b/drivers/net/wireless/wl1251/cmd.h
index 79ca5273c9e9..ee4f2b391822 100644
--- a/drivers/net/wireless/wl1251/cmd.h
+++ b/drivers/net/wireless/wl1251/cmd.h
@@ -269,7 +269,7 @@ struct cmd_join {
u8 bss_type;
u8 channel;
u8 ssid_len;
- u8 ssid[IW_ESSID_MAX_SIZE];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ctrl; /* JOIN_CMD_CTRL_* */
u8 tx_mgt_frame_rate; /* OBSOLETE */
u8 tx_mgt_frame_mod; /* OBSOLETE */
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c
index a14a48c99cdc..ba3268ea81fe 100644
--- a/drivers/net/wireless/wl1251/main.c
+++ b/drivers/net/wireless/wl1251/main.c
@@ -1158,7 +1158,8 @@ static struct ieee80211_channel wl1251_channels[] = {
{ .hw_value = 13, .center_freq = 2472},
};
-static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int wl1251_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
enum wl1251_acx_ps_scheme ps_scheme;
diff --git a/drivers/net/wireless/wl1251/wl12xx_80211.h b/drivers/net/wireless/wl1251/wl12xx_80211.h
index 1417b1445c3d..04ed51495772 100644
--- a/drivers/net/wireless/wl1251/wl12xx_80211.h
+++ b/drivers/net/wireless/wl1251/wl12xx_80211.h
@@ -76,7 +76,7 @@ struct wl12xx_ie_header {
struct wl12xx_ie_ssid {
struct wl12xx_ie_header header;
- char ssid[IW_ESSID_MAX_SIZE];
+ char ssid[IEEE80211_MAX_SSID_LEN];
} __packed;
struct wl12xx_ie_rates {
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 07bcb1548d8b..3fe388b87c2e 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -19,16 +19,6 @@ config WL12XX
If you choose to build a module, it will be called wl12xx. Say N if
unsure.
-config WL12XX_HT
- bool "TI wl12xx 802.11 HT support (EXPERIMENTAL)"
- depends on WL12XX && EXPERIMENTAL
- default n
- ---help---
- This will enable 802.11 HT support in the wl12xx module.
-
- That configuration is temporary due to the code incomplete and
- still in testing process.
-
config WL12XX_SPI
tristate "TI wl12xx SPI support"
depends on WL12XX && SPI_MASTER
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index 521c0414e52e..621b3483ca2c 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -1,16 +1,16 @@
wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
boot.o init.o debugfs.o scan.o
-wl12xx_spi-objs = spi.o
+wl12xx_spi-objs = spi.o
wl12xx_sdio-objs = sdio.o
-wl12xx_sdio_test-objs = sdio_test.o
+wl12xx_sdio_test-objs = sdio_test.o
wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o
obj-$(CONFIG_WL12XX) += wl12xx.o
obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o
obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o
-obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o
+obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o
# small builtin driver bit
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 34f6ab53e519..ca044a743191 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -46,6 +46,7 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl)
goto out;
}
+ wake_up->role_id = wl->role_id;
wake_up->wake_up_event = wl->conf.conn.wake_up_event;
wake_up->listen_interval = wl->conf.conn.listen_interval;
@@ -99,6 +100,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
goto out;
}
+ acx->role_id = wl->role_id;
acx->current_tx_power = power * 10;
ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
@@ -126,6 +128,7 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl)
}
/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
+ feature->role_id = wl->role_id;
feature->data_flow_options = 0;
feature->options = 0;
@@ -181,34 +184,6 @@ out:
return ret;
}
-int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter)
-{
- struct acx_rx_config *rx_config;
- int ret;
-
- wl1271_debug(DEBUG_ACX, "acx rx config");
-
- rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
- if (!rx_config) {
- ret = -ENOMEM;
- goto out;
- }
-
- rx_config->config_options = cpu_to_le32(config);
- rx_config->filter_options = cpu_to_le32(filter);
-
- ret = wl1271_cmd_configure(wl, ACX_RX_CFG,
- rx_config, sizeof(*rx_config));
- if (ret < 0) {
- wl1271_warning("failed to set rx config: %d", ret);
- goto out;
- }
-
-out:
- kfree(rx_config);
- return ret;
-}
-
int wl1271_acx_pd_threshold(struct wl1271 *wl)
{
struct acx_packet_detection *pd;
@@ -248,6 +223,7 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
goto out;
}
+ slot->role_id = wl->role_id;
slot->wone_index = STATION_WONE_INDEX;
slot->slot_time = slot_time;
@@ -277,6 +253,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
}
/* MAC filtering */
+ acx->role_id = wl->role_id;
acx->enabled = enable;
acx->num_groups = mc_list_len;
memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
@@ -306,6 +283,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
wl1271_debug(DEBUG_ACX, "acx service period timeout");
+ rx_timeout->role_id = wl->role_id;
rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout);
rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout);
@@ -342,6 +320,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold)
goto out;
}
+ rts->role_id = wl->role_id;
rts->threshold = cpu_to_le16((u16)rts_threshold);
ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
@@ -401,6 +380,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
goto out;
}
+ beacon_filter->role_id = wl->role_id;
beacon_filter->enable = enable_filter;
/*
@@ -437,6 +417,7 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
}
/* configure default beacon pass-through rules */
+ ie_table->role_id = wl->role_id;
ie_table->num_ie = 0;
for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) {
struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]);
@@ -498,6 +479,7 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable)
timeout = wl->conf.conn.bss_lose_timeout;
}
+ acx->role_id = wl->role_id;
acx->synch_fail_thold = cpu_to_le32(threshold);
acx->bss_lose_timeout = cpu_to_le32(timeout);
@@ -544,43 +526,13 @@ out:
return ret;
}
-int wl1271_acx_sta_sg_cfg(struct wl1271 *wl)
-{
- struct acx_sta_bt_wlan_coex_param *param;
- struct conf_sg_settings *c = &wl->conf.sg;
- int i, ret;
-
- wl1271_debug(DEBUG_ACX, "acx sg sta cfg");
-
- param = kzalloc(sizeof(*param), GFP_KERNEL);
- if (!param) {
- ret = -ENOMEM;
- goto out;
- }
-
- /* BT-WLAN coext parameters */
- for (i = 0; i < CONF_SG_STA_PARAMS_MAX; i++)
- param->params[i] = cpu_to_le32(c->sta_params[i]);
- param->param_idx = CONF_SG_PARAMS_ALL;
-
- ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
- if (ret < 0) {
- wl1271_warning("failed to set sg config: %d", ret);
- goto out;
- }
-
-out:
- kfree(param);
- return ret;
-}
-
-int wl1271_acx_ap_sg_cfg(struct wl1271 *wl)
+int wl12xx_acx_sg_cfg(struct wl1271 *wl)
{
- struct acx_ap_bt_wlan_coex_param *param;
+ struct acx_bt_wlan_coex_param *param;
struct conf_sg_settings *c = &wl->conf.sg;
int i, ret;
- wl1271_debug(DEBUG_ACX, "acx sg ap cfg");
+ wl1271_debug(DEBUG_ACX, "acx sg cfg");
param = kzalloc(sizeof(*param), GFP_KERNEL);
if (!param) {
@@ -589,8 +541,8 @@ int wl1271_acx_ap_sg_cfg(struct wl1271 *wl)
}
/* BT-WLAN coext parameters */
- for (i = 0; i < CONF_SG_AP_PARAMS_MAX; i++)
- param->params[i] = cpu_to_le32(c->ap_params[i]);
+ for (i = 0; i < CONF_SG_PARAMS_MAX; i++)
+ param->params[i] = cpu_to_le32(c->params[i]);
param->param_idx = CONF_SG_PARAMS_ALL;
ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
@@ -643,6 +595,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
goto out;
}
+ bb->role_id = wl->role_id;
bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout);
bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout);
bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps;
@@ -672,6 +625,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
goto out;
}
+ acx_aid->role_id = wl->role_id;
acx_aid->aid = cpu_to_le16(aid);
ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
@@ -727,6 +681,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
goto out;
}
+ acx->role_id = wl->role_id;
acx->preamble = preamble;
ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
@@ -754,6 +709,7 @@ int wl1271_acx_cts_protect(struct wl1271 *wl,
goto out;
}
+ acx->role_id = wl->role_id;
acx->ctsprotect = ctsprotect;
ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
@@ -785,9 +741,8 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
{
- struct acx_sta_rate_policy *acx;
+ struct acx_rate_policy *acx;
struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf;
- int idx = 0;
int ret = 0;
wl1271_debug(DEBUG_ACX, "acx rate policies");
@@ -799,25 +754,46 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
goto out;
}
+ wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
+ wl->basic_rate, wl->rate_set);
+
/* configure one basic rate class */
- idx = ACX_TX_BASIC_RATE;
- acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate);
- acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
- acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
- acx->rate_class[idx].aflags = c->aflags;
+ acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE);
+ acx->rate_policy.enabled_rates = cpu_to_le32(wl->basic_rate);
+ acx->rate_policy.short_retry_limit = c->short_retry_limit;
+ acx->rate_policy.long_retry_limit = c->long_retry_limit;
+ acx->rate_policy.aflags = c->aflags;
+
+ ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of rate policies failed: %d", ret);
+ goto out;
+ }
/* configure one AP supported rate class */
- idx = ACX_TX_AP_FULL_RATE;
- acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set);
- acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
- acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
- acx->rate_class[idx].aflags = c->aflags;
+ acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE);
+ acx->rate_policy.enabled_rates = cpu_to_le32(wl->rate_set);
+ acx->rate_policy.short_retry_limit = c->short_retry_limit;
+ acx->rate_policy.long_retry_limit = c->long_retry_limit;
+ acx->rate_policy.aflags = c->aflags;
- acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
+ ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("Setting of rate policies failed: %d", ret);
+ goto out;
+ }
- wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
- acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates,
- acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates);
+ /*
+ * configure one rate class for basic p2p operations.
+ * (p2p packets should always go out with OFDM rates, even
+ * if we are currently connected to 11b AP)
+ */
+ acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE_P2P);
+ acx->rate_policy.enabled_rates =
+ cpu_to_le32(CONF_TX_RATE_MASK_BASIC_P2P);
+ acx->rate_policy.short_retry_limit = c->short_retry_limit;
+ acx->rate_policy.long_retry_limit = c->long_retry_limit;
+ acx->rate_policy.aflags = c->aflags;
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
if (ret < 0) {
@@ -833,7 +809,7 @@ out:
int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
u8 idx)
{
- struct acx_ap_rate_policy *acx;
+ struct acx_rate_policy *acx;
int ret = 0;
wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x",
@@ -879,6 +855,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
goto out;
}
+ acx->role_id = wl->role_id;
acx->ac = ac;
acx->cw_min = cw_min;
acx->cw_max = cpu_to_le16(cw_max);
@@ -912,6 +889,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
goto out;
}
+ acx->role_id = wl->role_id;
acx->queue_id = queue_id;
acx->channel_type = channel_type;
acx->tsid = tsid;
@@ -991,52 +969,9 @@ out:
return ret;
}
-int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
+int wl12xx_acx_mem_cfg(struct wl1271 *wl)
{
- struct wl1271_acx_ap_config_memory *mem_conf;
- struct conf_memory_settings *mem;
- int ret;
-
- wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
-
- mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
- if (!mem_conf) {
- ret = -ENOMEM;
- goto out;
- }
-
- if (wl->chip.id == CHIP_ID_1283_PG20)
- /*
- * FIXME: The 128x AP FW does not yet support dynamic memory.
- * Use the base memory configuration for 128x for now. This
- * should be fine tuned in the future.
- */
- mem = &wl->conf.mem_wl128x;
- else
- mem = &wl->conf.mem_wl127x;
-
- /* memory config */
- mem_conf->num_stations = mem->num_stations;
- mem_conf->rx_mem_block_num = mem->rx_block_num;
- mem_conf->tx_min_mem_block_num = mem->tx_min_block_num;
- mem_conf->num_ssid_profiles = mem->ssid_profiles;
- mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
-
- ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
- sizeof(*mem_conf));
- if (ret < 0) {
- wl1271_warning("wl1271 mem config failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(mem_conf);
- return ret;
-}
-
-int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
-{
- struct wl1271_acx_sta_config_memory *mem_conf;
+ struct wl12xx_acx_config_memory *mem_conf;
struct conf_memory_settings *mem;
int ret;
@@ -1179,6 +1114,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
goto out;
}
+ acx->role_id = wl->role_id;
acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE;
acx->max_consecutive = wl->conf.conn.bet_max_consecutive;
@@ -1206,6 +1142,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address)
goto out;
}
+ acx->role_id = wl->role_id;
acx->version = ACX_IPV4_VERSION;
acx->enable = enable;
@@ -1265,6 +1202,7 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable)
goto out;
}
+ acx->role_id = wl->role_id;
acx->enabled = enable;
ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx));
@@ -1291,6 +1229,7 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid)
goto out;
}
+ acx->role_id = wl->role_id;
acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval);
acx->index = index;
acx->tpl_validation = tpl_valid;
@@ -1324,6 +1263,7 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
wl->last_rssi_event = -1;
+ acx->role_id = wl->role_id;
acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing);
acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON;
acx->type = WL1271_ACX_TRIG_TYPE_EDGE;
@@ -1362,6 +1302,7 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl)
goto out;
}
+ acx->role_id = wl->role_id;
acx->rssi_beacon = c->avg_weight_rssi_beacon;
acx->rssi_data = c->avg_weight_rssi_data;
acx->snr_beacon = c->avg_weight_snr_beacon;
@@ -1380,14 +1321,15 @@ out:
int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
struct ieee80211_sta_ht_cap *ht_cap,
- bool allow_ht_operation)
+ bool allow_ht_operation, u8 hlid)
{
struct wl1271_acx_ht_capabilities *acx;
- u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
int ret = 0;
u32 ht_capabilites = 0;
- wl1271_debug(DEBUG_ACX, "acx ht capabilities setting");
+ wl1271_debug(DEBUG_ACX, "acx ht capabilities setting "
+ "sta supp: %d sta cap: %d", ht_cap->ht_supported,
+ ht_cap->cap);
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx) {
@@ -1395,26 +1337,22 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
goto out;
}
- /* Allow HT Operation ? */
- if (allow_ht_operation) {
- ht_capabilites =
- WL1271_ACX_FW_CAP_HT_OPERATION;
- if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD)
- ht_capabilites |=
- WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT;
- if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)
- ht_capabilites |=
- WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS;
- if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT)
- ht_capabilites |=
- WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION;
+ if (allow_ht_operation && ht_cap->ht_supported) {
+ /* no need to translate capabilities - use the spec values */
+ ht_capabilites = ht_cap->cap;
+
+ /*
+ * this bit is not employed by the spec but only by FW to
+ * indicate peer HT support
+ */
+ ht_capabilites |= WL12XX_HT_CAP_HT_OPERATION;
/* get data from A-MPDU parameters field */
acx->ampdu_max_length = ht_cap->ampdu_factor;
acx->ampdu_min_spacing = ht_cap->ampdu_density;
}
- memcpy(acx->mac_address, mac_address, ETH_ALEN);
+ acx->hlid = hlid;
acx->ht_capabilites = cpu_to_le32(ht_capabilites);
ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx));
@@ -1442,6 +1380,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
goto out;
}
+ acx->role_id = wl->role_id;
acx->ht_protection =
(u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION);
acx->rifs_mode = 0;
@@ -1463,14 +1402,12 @@ out:
}
/* Configure BA session initiator/receiver parameters setting in the FW. */
-int wl1271_acx_set_ba_session(struct wl1271 *wl,
- enum ieee80211_back_parties direction,
- u8 tid_index, u8 policy)
+int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl)
{
- struct wl1271_acx_ba_session_policy *acx;
+ struct wl1271_acx_ba_initiator_policy *acx;
int ret;
- wl1271_debug(DEBUG_ACX, "acx ba session setting");
+ wl1271_debug(DEBUG_ACX, "acx ba initiator policy");
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx) {
@@ -1478,33 +1415,18 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
goto out;
}
- /* ANY role */
- acx->role_id = 0xff;
- acx->tid = tid_index;
- acx->enable = policy;
- acx->ba_direction = direction;
-
- switch (direction) {
- case WLAN_BACK_INITIATOR:
- acx->win_size = wl->conf.ht.tx_ba_win_size;
- acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
- break;
- case WLAN_BACK_RECIPIENT:
- acx->win_size = RX_BA_WIN_SIZE;
- acx->inactivity_timeout = 0;
- break;
- default:
- wl1271_error("Incorrect acx command id=%x\n", direction);
- ret = -EINVAL;
- goto out;
- }
+ /* set for the current role */
+ acx->role_id = wl->role_id;
+ acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap;
+ acx->win_size = wl->conf.ht.tx_ba_win_size;
+ acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
ret = wl1271_cmd_configure(wl,
- ACX_BA_SESSION_POLICY_CFG,
+ ACX_BA_SESSION_INIT_POLICY,
acx,
sizeof(*acx));
if (ret < 0) {
- wl1271_warning("acx ba session setting failed: %d", ret);
+ wl1271_warning("acx ba initiator policy failed: %d", ret);
goto out;
}
@@ -1514,8 +1436,8 @@ out:
}
/* setup BA session receiver setting in the FW. */
-int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
- bool enable)
+int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
+ u16 ssn, bool enable, u8 peer_hlid)
{
struct wl1271_acx_ba_receiver_setup *acx;
int ret;
@@ -1528,11 +1450,10 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
goto out;
}
- /* Single link for now */
- acx->link_id = 1;
+ acx->hlid = peer_hlid;
acx->tid = tid_index;
acx->enable = enable;
- acx->win_size = 0;
+ acx->win_size = wl->conf.ht.rx_ba_win_size;
acx->ssn = ssn;
ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx,
@@ -1602,6 +1523,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
if (!(conf_queues & BIT(i)))
continue;
+ rx_streaming->role_id = wl->role_id;
rx_streaming->tid = i;
rx_streaming->enable = enable_queues & BIT(i);
rx_streaming->period = wl->conf.rx_streaming.interval;
@@ -1631,6 +1553,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
if (!acx)
return -ENOMEM;
+ acx->role_id = wl->role_id;
acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries);
ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
@@ -1699,31 +1622,6 @@ out:
return ret;
}
-int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable)
-{
- struct acx_ap_beacon_filter *acx = NULL;
- int ret;
-
- wl1271_debug(DEBUG_ACX, "acx set ap beacon filter: %d", enable);
-
- acx = kzalloc(sizeof(*acx), GFP_KERNEL);
- if (!acx)
- return -ENOMEM;
-
- acx->enable = enable ? 1 : 0;
-
- ret = wl1271_cmd_configure(wl, ACX_AP_BEACON_FILTER_OPT,
- acx, sizeof(*acx));
- if (ret < 0) {
- wl1271_warning("acx set ap beacon filter failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(acx);
- return ret;
-}
-
int wl1271_acx_fm_coex(struct wl1271 *wl)
{
struct wl1271_acx_fm_coex *acx;
@@ -1763,3 +1661,85 @@ out:
kfree(acx);
return ret;
}
+
+int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl)
+{
+ struct wl12xx_acx_set_rate_mgmt_params *acx = NULL;
+ struct conf_rate_policy_settings *conf = &wl->conf.rate;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx set rate mgmt params");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx)
+ return -ENOMEM;
+
+ acx->index = ACX_RATE_MGMT_ALL_PARAMS;
+ acx->rate_retry_score = cpu_to_le16(conf->rate_retry_score);
+ acx->per_add = cpu_to_le16(conf->per_add);
+ acx->per_th1 = cpu_to_le16(conf->per_th1);
+ acx->per_th2 = cpu_to_le16(conf->per_th2);
+ acx->max_per = cpu_to_le16(conf->max_per);
+ acx->inverse_curiosity_factor = conf->inverse_curiosity_factor;
+ acx->tx_fail_low_th = conf->tx_fail_low_th;
+ acx->tx_fail_high_th = conf->tx_fail_high_th;
+ acx->per_alpha_shift = conf->per_alpha_shift;
+ acx->per_add_shift = conf->per_add_shift;
+ acx->per_beta1_shift = conf->per_beta1_shift;
+ acx->per_beta2_shift = conf->per_beta2_shift;
+ acx->rate_check_up = conf->rate_check_up;
+ acx->rate_check_down = conf->rate_check_down;
+ memcpy(acx->rate_retry_policy, conf->rate_retry_policy,
+ sizeof(acx->rate_retry_policy));
+
+ ret = wl1271_cmd_configure(wl, ACX_SET_RATE_MGMT_PARAMS,
+ acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("acx set rate mgmt params failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+int wl12xx_acx_config_hangover(struct wl1271 *wl)
+{
+ struct wl12xx_acx_config_hangover *acx;
+ struct conf_hangover_settings *conf = &wl->conf.hangover;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx config hangover");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->recover_time = cpu_to_le32(conf->recover_time);
+ acx->hangover_period = conf->hangover_period;
+ acx->dynamic_mode = conf->dynamic_mode;
+ acx->early_termination_mode = conf->early_termination_mode;
+ acx->max_period = conf->max_period;
+ acx->min_period = conf->min_period;
+ acx->increase_delta = conf->increase_delta;
+ acx->decrease_delta = conf->decrease_delta;
+ acx->quiet_time = conf->quiet_time;
+ acx->increase_time = conf->increase_time;
+ acx->window_size = acx->window_size;
+
+ ret = wl1271_cmd_configure(wl, ACX_CONFIG_HANGOVER, acx,
+ sizeof(*acx));
+
+ if (ret < 0) {
+ wl1271_warning("acx config hangover failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+
+}
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index d2eb86eccc04..e3f93b4b3429 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -101,6 +101,17 @@ struct acx_error_counter {
__le32 seq_num_miss;
} __packed;
+enum wl12xx_role {
+ WL1271_ROLE_STA = 0,
+ WL1271_ROLE_IBSS,
+ WL1271_ROLE_AP,
+ WL1271_ROLE_DEVICE,
+ WL1271_ROLE_P2P_CL,
+ WL1271_ROLE_P2P_GO,
+
+ WL12XX_INVALID_ROLE_TYPE = 0xff
+};
+
enum wl1271_psm_mode {
/* Active mode */
WL1271_PSM_CAM = 0,
@@ -160,94 +171,6 @@ struct acx_rx_msdu_lifetime {
__le32 lifetime;
} __packed;
-/*
- * RX Config Options Table
- * Bit Definition
- * === ==========
- * 31:14 Reserved
- * 13 Copy RX Status - when set, write three receive status words
- * to top of rx'd MPDUs.
- * When cleared, do not write three status words (added rev 1.5)
- * 12 Reserved
- * 11 RX Complete upon FCS error - when set, give rx complete
- * interrupt for FCS errors, after the rx filtering, e.g. unicast
- * frames not to us with FCS error will not generate an interrupt.
- * 10 SSID Filter Enable - When set, the WiLink discards all beacon,
- * probe request, and probe response frames with an SSID that does
- * not match the SSID specified by the host in the START/JOIN
- * command.
- * When clear, the WiLink receives frames with any SSID.
- * 9 Broadcast Filter Enable - When set, the WiLink discards all
- * broadcast frames. When clear, the WiLink receives all received
- * broadcast frames.
- * 8:6 Reserved
- * 5 BSSID Filter Enable - When set, the WiLink discards any frames
- * with a BSSID that does not match the BSSID specified by the
- * host.
- * When clear, the WiLink receives frames from any BSSID.
- * 4 MAC Addr Filter - When set, the WiLink discards any frames
- * with a destination address that does not match the MAC address
- * of the adaptor.
- * When clear, the WiLink receives frames destined to any MAC
- * address.
- * 3 Promiscuous - When set, the WiLink receives all valid frames
- * (i.e., all frames that pass the FCS check).
- * When clear, only frames that pass the other filters specified
- * are received.
- * 2 FCS - When set, the WiLink includes the FCS with the received
- * frame.
- * When cleared, the FCS is discarded.
- * 1 PLCP header - When set, write all data from baseband to frame
- * buffer including PHY header.
- * 0 Reserved - Always equal to 0.
- *
- * RX Filter Options Table
- * Bit Definition
- * === ==========
- * 31:12 Reserved - Always equal to 0.
- * 11 Association - When set, the WiLink receives all association
- * related frames (association request/response, reassocation
- * request/response, and disassociation). When clear, these frames
- * are discarded.
- * 10 Auth/De auth - When set, the WiLink receives all authentication
- * and de-authentication frames. When clear, these frames are
- * discarded.
- * 9 Beacon - When set, the WiLink receives all beacon frames.
- * When clear, these frames are discarded.
- * 8 Contention Free - When set, the WiLink receives all contention
- * free frames.
- * When clear, these frames are discarded.
- * 7 Control - When set, the WiLink receives all control frames.
- * When clear, these frames are discarded.
- * 6 Data - When set, the WiLink receives all data frames.
- * When clear, these frames are discarded.
- * 5 FCS Error - When set, the WiLink receives frames that have FCS
- * errors.
- * When clear, these frames are discarded.
- * 4 Management - When set, the WiLink receives all management
- * frames.
- * When clear, these frames are discarded.
- * 3 Probe Request - When set, the WiLink receives all probe request
- * frames.
- * When clear, these frames are discarded.
- * 2 Probe Response - When set, the WiLink receives all probe
- * response frames.
- * When clear, these frames are discarded.
- * 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK
- * frames.
- * When clear, these frames are discarded.
- * 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames
- * that have reserved frame types and sub types as defined by the
- * 802.11 specification.
- * When clear, these frames are discarded.
- */
-struct acx_rx_config {
- struct acx_header header;
-
- __le32 config_options;
- __le32 filter_options;
-} __packed;
-
struct acx_packet_detection {
struct acx_header header;
@@ -267,9 +190,10 @@ enum acx_slot_type {
struct acx_slot {
struct acx_header header;
+ u8 role_id;
u8 wone_index; /* Reserved */
u8 slot_time;
- u8 reserved[6];
+ u8 reserved[5];
} __packed;
@@ -279,29 +203,35 @@ struct acx_slot {
struct acx_dot11_grp_addr_tbl {
struct acx_header header;
+ u8 role_id;
u8 enabled;
u8 num_groups;
- u8 pad[2];
+ u8 pad[1];
u8 mac_table[ADDRESS_GROUP_MAX_LEN];
} __packed;
struct acx_rx_timeout {
struct acx_header header;
+ u8 role_id;
+ u8 reserved;
__le16 ps_poll_timeout;
__le16 upsd_timeout;
+ u8 padding[2];
} __packed;
struct acx_rts_threshold {
struct acx_header header;
+ u8 role_id;
+ u8 reserved;
__le16 threshold;
- u8 pad[2];
} __packed;
struct acx_beacon_filter_option {
struct acx_header header;
+ u8 role_id;
u8 enable;
/*
* The number of beacons without the unicast TIM
@@ -311,7 +241,7 @@ struct acx_beacon_filter_option {
* without the unicast TIM bit set are dropped.
*/
u8 max_num_beacons;
- u8 pad[2];
+ u8 pad[1];
} __packed;
/*
@@ -350,14 +280,17 @@ struct acx_beacon_filter_option {
struct acx_beacon_filter_ie_table {
struct acx_header header;
+ u8 role_id;
u8 num_ie;
- u8 pad[3];
+ u8 pad[2];
u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
} __packed;
struct acx_conn_monit_params {
struct acx_header header;
+ u8 role_id;
+ u8 padding[3];
__le32 synch_fail_thold; /* number of beacons missed */
__le32 bss_lose_timeout; /* number of TU's from synch fail */
} __packed;
@@ -369,23 +302,14 @@ struct acx_bt_wlan_coex {
u8 pad[3];
} __packed;
-struct acx_sta_bt_wlan_coex_param {
- struct acx_header header;
-
- __le32 params[CONF_SG_STA_PARAMS_MAX];
- u8 param_idx;
- u8 padding[3];
-} __packed;
-
-struct acx_ap_bt_wlan_coex_param {
+struct acx_bt_wlan_coex_param {
struct acx_header header;
- __le32 params[CONF_SG_AP_PARAMS_MAX];
+ __le32 params[CONF_SG_PARAMS_MAX];
u8 param_idx;
u8 padding[3];
} __packed;
-
struct acx_dco_itrim_params {
struct acx_header header;
@@ -406,15 +330,16 @@ struct acx_energy_detection {
struct acx_beacon_broadcast {
struct acx_header header;
- __le16 beacon_rx_timeout;
- __le16 broadcast_timeout;
-
+ u8 role_id;
/* Enables receiving of broadcast packets in PS mode */
u8 rx_broadcast_in_ps;
+ __le16 beacon_rx_timeout;
+ __le16 broadcast_timeout;
+
/* Consecutive PS Poll failures before updating the host */
u8 ps_poll_threshold;
- u8 pad[2];
+ u8 pad[1];
} __packed;
struct acx_event_mask {
@@ -424,35 +349,6 @@ struct acx_event_mask {
__le32 high_event_mask; /* Unused */
} __packed;
-#define CFG_RX_FCS BIT(2)
-#define CFG_RX_ALL_GOOD BIT(3)
-#define CFG_UNI_FILTER_EN BIT(4)
-#define CFG_BSSID_FILTER_EN BIT(5)
-#define CFG_MC_FILTER_EN BIT(6)
-#define CFG_MC_ADDR0_EN BIT(7)
-#define CFG_MC_ADDR1_EN BIT(8)
-#define CFG_BC_REJECT_EN BIT(9)
-#define CFG_SSID_FILTER_EN BIT(10)
-#define CFG_RX_INT_FCS_ERROR BIT(11)
-#define CFG_RX_INT_ENCRYPTED BIT(12)
-#define CFG_RX_WR_RX_STATUS BIT(13)
-#define CFG_RX_FILTER_NULTI BIT(14)
-#define CFG_RX_RESERVE BIT(15)
-#define CFG_RX_TIMESTAMP_TSF BIT(16)
-
-#define CFG_RX_RSV_EN BIT(0)
-#define CFG_RX_RCTS_ACK BIT(1)
-#define CFG_RX_PRSP_EN BIT(2)
-#define CFG_RX_PREQ_EN BIT(3)
-#define CFG_RX_MGMT_EN BIT(4)
-#define CFG_RX_FCS_ERROR BIT(5)
-#define CFG_RX_DATA_EN BIT(6)
-#define CFG_RX_CTL_EN BIT(7)
-#define CFG_RX_CF_EN BIT(8)
-#define CFG_RX_BCN_EN BIT(9)
-#define CFG_RX_AUTH_EN BIT(10)
-#define CFG_RX_ASSOC_EN BIT(11)
-
#define SCAN_PASSIVE BIT(0)
#define SCAN_5GHZ_BAND BIT(1)
#define SCAN_TRIGGERED BIT(2)
@@ -465,6 +361,8 @@ struct acx_event_mask {
struct acx_feature_config {
struct acx_header header;
+ u8 role_id;
+ u8 padding[3];
__le32 options;
__le32 data_flow_options;
} __packed;
@@ -472,16 +370,18 @@ struct acx_feature_config {
struct acx_current_tx_power {
struct acx_header header;
+ u8 role_id;
u8 current_tx_power;
- u8 padding[3];
+ u8 padding[2];
} __packed;
struct acx_wake_up_condition {
struct acx_header header;
+ u8 role_id;
u8 wake_up_event; /* Only one bit can be set */
u8 listen_interval;
- u8 pad[2];
+ u8 pad[1];
} __packed;
struct acx_aid {
@@ -490,8 +390,9 @@ struct acx_aid {
/*
* To be set when associated with an AP.
*/
+ u8 role_id;
+ u8 reserved;
__le16 aid;
- u8 pad[2];
} __packed;
enum acx_preamble_type {
@@ -506,8 +407,9 @@ struct acx_preamble {
* When set, the WiLink transmits the frames with a short preamble and
* when cleared, the WiLink transmits the frames with a long preamble.
*/
+ u8 role_id;
u8 preamble;
- u8 padding[3];
+ u8 padding[2];
} __packed;
enum acx_ctsprotect_type {
@@ -517,8 +419,9 @@ enum acx_ctsprotect_type {
struct acx_ctsprotect {
struct acx_header header;
+ u8 role_id;
u8 ctsprotect;
- u8 padding[3];
+ u8 padding[2];
} __packed;
struct acx_tx_statistics {
@@ -753,18 +656,10 @@ struct acx_rate_class {
#define ACX_TX_BASIC_RATE 0
#define ACX_TX_AP_FULL_RATE 1
-#define ACX_TX_RATE_POLICY_CNT 2
-struct acx_sta_rate_policy {
- struct acx_header header;
-
- __le32 rate_class_cnt;
- struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES];
-} __packed;
-
-
+#define ACX_TX_BASIC_RATE_P2P 2
#define ACX_TX_AP_MODE_MGMT_RATE 4
#define ACX_TX_AP_MODE_BCST_RATE 5
-struct acx_ap_rate_policy {
+struct acx_rate_policy {
struct acx_header header;
__le32 rate_policy_idx;
@@ -773,22 +668,23 @@ struct acx_ap_rate_policy {
struct acx_ac_cfg {
struct acx_header header;
+ u8 role_id;
u8 ac;
+ u8 aifsn;
u8 cw_min;
__le16 cw_max;
- u8 aifsn;
- u8 reserved;
__le16 tx_op_limit;
} __packed;
struct acx_tid_config {
struct acx_header header;
+ u8 role_id;
u8 queue_id;
u8 channel_type;
u8 tsid;
u8 ps_scheme;
u8 ack_policy;
- u8 padding[3];
+ u8 padding[2];
__le32 apsd_conf[2];
} __packed;
@@ -804,19 +700,7 @@ struct acx_tx_config_options {
__le16 tx_compl_threshold; /* number of packets */
} __packed;
-#define ACX_TX_DESCRIPTORS 32
-
-struct wl1271_acx_ap_config_memory {
- struct acx_header header;
-
- u8 rx_mem_block_num;
- u8 tx_min_mem_block_num;
- u8 num_stations;
- u8 num_ssid_profiles;
- __le32 total_tx_descriptors;
-} __packed;
-
-struct wl1271_acx_sta_config_memory {
+struct wl12xx_acx_config_memory {
struct acx_header header;
u8 rx_mem_block_num;
@@ -890,9 +774,10 @@ struct wl1271_acx_rx_config_opt {
struct wl1271_acx_bet_enable {
struct acx_header header;
+ u8 role_id;
u8 enable;
u8 max_consecutive;
- u8 padding[2];
+ u8 padding[1];
} __packed;
#define ACX_IPV4_VERSION 4
@@ -905,9 +790,10 @@ struct wl1271_acx_bet_enable {
struct wl1271_acx_arp_filter {
struct acx_header header;
+ u8 role_id;
u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */
u8 enable; /* bitmap of enabled ARP filtering features */
- u8 padding[2];
+ u8 padding[1];
u8 address[16]; /* The configured device IP address - all ARP
requests directed to this IP address will pass
through. For IPv4, the first four bytes are
@@ -925,8 +811,9 @@ struct wl1271_acx_pm_config {
struct wl1271_acx_keep_alive_mode {
struct acx_header header;
+ u8 role_id;
u8 enabled;
- u8 padding[3];
+ u8 padding[2];
} __packed;
enum {
@@ -942,11 +829,11 @@ enum {
struct wl1271_acx_keep_alive_config {
struct acx_header header;
- __le32 period;
+ u8 role_id;
u8 index;
u8 tpl_validation;
u8 trigger;
- u8 padding;
+ __le32 period;
} __packed;
#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0)
@@ -990,26 +877,33 @@ enum {
struct wl1271_acx_rssi_snr_trigger {
struct acx_header header;
- __le16 threshold;
- __le16 pacing; /* 0 - 60000 ms */
+ u8 role_id;
u8 metric;
u8 type;
u8 dir;
+ __le16 threshold;
+ __le16 pacing; /* 0 - 60000 ms */
u8 hysteresis;
u8 index;
u8 enable;
- u8 padding[2];
+ u8 padding[1];
};
struct wl1271_acx_rssi_snr_avg_weights {
struct acx_header header;
+ u8 role_id;
+ u8 padding[3];
u8 rssi_beacon;
u8 rssi_data;
u8 snr_beacon;
u8 snr_data;
};
+
+/* special capability bit (not employed by the 802.11n spec) */
+#define WL12XX_HT_CAP_HT_OPERATION BIT(16)
+
/*
* ACX_PEER_HT_CAP
* Configure HT capabilities - declare the capabilities of the peer
@@ -1018,28 +912,11 @@ struct wl1271_acx_rssi_snr_avg_weights {
struct wl1271_acx_ht_capabilities {
struct acx_header header;
- /*
- * bit 0 - Allow HT Operation
- * bit 1 - Allow Greenfield format in TX
- * bit 2 - Allow Short GI in TX
- * bit 3 - Allow L-SIG TXOP Protection in TX
- * bit 4 - Allow HT Control fields in TX.
- * Note, driver will still leave space for HT control in packets
- * regardless of the value of this field. FW will be responsible
- * to drop the HT field from any frame when this Bit set to 0.
- * bit 5 - Allow RD initiation in TXOP. FW is allowed to initate RD.
- * Exact policy setting for this feature is TBD.
- * Note, this bit can only be set to 1 if bit 3 is set to 1.
- */
+ /* bitmask of capability bits supported by the peer */
__le32 ht_capabilites;
- /*
- * Indicates to which peer these capabilities apply.
- * For infrastructure use ff:ff:ff:ff:ff:ff that indicates relevance
- * for all peers.
- * Only valid for IBSS/DLS operation.
- */
- u8 mac_address[ETH_ALEN];
+ /* Indicates to which link these capabilities apply. */
+ u8 hlid;
/*
* This the maximum A-MPDU length supported by the AP. The FW may not
@@ -1049,16 +926,9 @@ struct wl1271_acx_ht_capabilities {
/* This is the minimal spacing required when sending A-MPDUs to the AP*/
u8 ampdu_min_spacing;
-} __packed;
-
-/* HT Capabilites Fw Bit Mask Mapping */
-#define WL1271_ACX_FW_CAP_HT_OPERATION BIT(0)
-#define WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT BIT(1)
-#define WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS BIT(2)
-#define WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION BIT(3)
-#define WL1271_ACX_FW_CAP_HT_CONTROL_FIELDS BIT(4)
-#define WL1271_ACX_FW_CAP_RD_INITIATION BIT(5)
+ u8 padding;
+} __packed;
/*
* ACX_HT_BSS_OPERATION
@@ -1067,6 +937,8 @@ struct wl1271_acx_ht_capabilities {
struct wl1271_acx_ht_information {
struct acx_header header;
+ u8 role_id;
+
/* Values: 0 - RIFS not allowed, 1 - RIFS allowed */
u8 rifs_mode;
@@ -1088,60 +960,51 @@ struct wl1271_acx_ht_information {
*/
u8 dual_cts_protection;
- u8 padding[3];
+ u8 padding[2];
} __packed;
-#define RX_BA_WIN_SIZE 8
+#define RX_BA_MAX_SESSIONS 2
-struct wl1271_acx_ba_session_policy {
+struct wl1271_acx_ba_initiator_policy {
struct acx_header header;
- /*
- * Specifies role Id, Range 0-7, 0xFF means ANY role.
- * Future use. For now this field is irrelevant
- */
+
+ /* Specifies role Id, Range 0-7, 0xFF means ANY role. */
u8 role_id;
+
/*
- * Specifies Link Id, Range 0-31, 0xFF means ANY Link Id.
- * Not applicable if Role Id is set to ANY.
+ * Per TID setting for allowing TX BA. Set a bit to 1 to allow
+ * TX BA sessions for the corresponding TID.
*/
- u8 link_id;
-
- u8 tid;
-
- u8 enable;
+ u8 tid_bitmap;
/* Windows size in number of packets */
- u16 win_size;
+ u8 win_size;
- /*
- * As initiator inactivity timeout in time units(TU) of 1024us.
- * As receiver reserved
- */
- u16 inactivity_timeout;
+ u8 padding1[1];
- /* Initiator = 1/Receiver = 0 */
- u8 ba_direction;
+ /* As initiator inactivity timeout in time units(TU) of 1024us */
+ u16 inactivity_timeout;
- u8 padding[3];
+ u8 padding[2];
} __packed;
struct wl1271_acx_ba_receiver_setup {
struct acx_header header;
- /* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id */
- u8 link_id;
+ /* Specifies link id, range 0-31 */
+ u8 hlid;
u8 tid;
u8 enable;
- u8 padding[1];
-
/* Windows size in number of packets */
- u16 win_size;
+ u8 win_size;
/* BA session starting sequence number. RANGE 0-FFF */
u16 ssn;
+
+ u8 padding[2];
} __packed;
struct wl1271_acx_fw_tsf_information {
@@ -1158,6 +1021,7 @@ struct wl1271_acx_fw_tsf_information {
struct wl1271_acx_ps_rx_streaming {
struct acx_header header;
+ u8 role_id;
u8 tid;
u8 enable;
@@ -1166,17 +1030,20 @@ struct wl1271_acx_ps_rx_streaming {
/* timeout before first trigger (0-200 msec) */
u8 timeout;
+ u8 padding[3];
} __packed;
struct wl1271_acx_ap_max_tx_retry {
struct acx_header header;
+ u8 role_id;
+ u8 padding_1;
+
/*
* the number of frames transmission failures before
* issuing the aging event.
*/
__le16 max_tx_retry;
- u8 padding_1[2];
} __packed;
struct wl1271_acx_config_ps {
@@ -1195,13 +1062,6 @@ struct wl1271_acx_inconnection_sta {
u8 padding1[2];
} __packed;
-struct acx_ap_beacon_filter {
- struct acx_header header;
-
- u8 enable;
- u8 pad[3];
-} __packed;
-
/*
* ACX_FM_COEX_CFG
* set the FM co-existence parameters.
@@ -1261,6 +1121,47 @@ struct wl1271_acx_fm_coex {
u8 swallow_clk_diff;
} __packed;
+#define ACX_RATE_MGMT_ALL_PARAMS 0xff
+struct wl12xx_acx_set_rate_mgmt_params {
+ struct acx_header header;
+
+ u8 index; /* 0xff to configure all params */
+ u8 padding1;
+ __le16 rate_retry_score;
+ __le16 per_add;
+ __le16 per_th1;
+ __le16 per_th2;
+ __le16 max_per;
+ u8 inverse_curiosity_factor;
+ u8 tx_fail_low_th;
+ u8 tx_fail_high_th;
+ u8 per_alpha_shift;
+ u8 per_add_shift;
+ u8 per_beta1_shift;
+ u8 per_beta2_shift;
+ u8 rate_check_up;
+ u8 rate_check_down;
+ u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES];
+ u8 padding2[2];
+} __packed;
+
+struct wl12xx_acx_config_hangover {
+ struct acx_header header;
+
+ __le32 recover_time;
+ u8 hangover_period;
+ u8 dynamic_mode;
+ u8 early_termination_mode;
+ u8 max_period;
+ u8 min_period;
+ u8 increase_delta;
+ u8 decrease_delta;
+ u8 quiet_time;
+ u8 increase_time;
+ u8 window_size;
+ u8 padding[2];
+} __packed;
+
enum {
ACX_WAKE_UP_CONDITIONS = 0x0002,
ACX_MEM_CFG = 0x0003,
@@ -1268,10 +1169,7 @@ enum {
ACX_AC_CFG = 0x0007,
ACX_MEM_MAP = 0x0008,
ACX_AID = 0x000A,
- /* ACX_FW_REV is missing in the ref driver, but seems to work */
- ACX_FW_REV = 0x000D,
ACX_MEDIUM_USAGE = 0x000F,
- ACX_RX_CFG = 0x0010,
ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */
ACX_STATISTICS = 0x0013, /* Debug API */
ACX_PWR_CONSUMPTION_STATISTICS = 0x0014,
@@ -1279,7 +1177,6 @@ enum {
ACX_TID_CFG = 0x001A,
ACX_PS_RX_STREAMING = 0x001B,
ACX_BEACON_FILTER_OPT = 0x001F,
- ACX_AP_BEACON_FILTER_OPT = 0x0020,
ACX_NOISE_HIST = 0x0021,
ACX_HDK_VERSION = 0x0022, /* ??? */
ACX_PD_THRESHOLD = 0x0023,
@@ -1287,7 +1184,6 @@ enum {
ACX_CCA_THRESHOLD = 0x0025,
ACX_EVENT_MBOX_MASK = 0x0026,
ACX_CONN_MONIT_PARAMS = 0x002D,
- ACX_CONS_TX_FAILURE = 0x002F,
ACX_BCN_DTIM_OPTIONS = 0x0031,
ACX_SG_ENABLE = 0x0032,
ACX_SG_CFG = 0x0033,
@@ -1314,11 +1210,14 @@ enum {
ACX_RSSI_SNR_WEIGHTS = 0x0052,
ACX_KEEP_ALIVE_MODE = 0x0053,
ACX_SET_KEEP_ALIVE_CONFIG = 0x0054,
- ACX_BA_SESSION_POLICY_CFG = 0x0055,
+ ACX_BA_SESSION_INIT_POLICY = 0x0055,
ACX_BA_SESSION_RX_SETUP = 0x0056,
ACX_PEER_HT_CAP = 0x0057,
ACX_HT_BSS_OPERATION = 0x0058,
ACX_COEX_ACTIVITY = 0x0059,
+ ACX_BURST_MODE = 0x005C,
+ ACX_SET_RATE_MGMT_PARAMS = 0x005D,
+ ACX_SET_RATE_ADAPT_PARAMS = 0x0060,
ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
ACX_GEN_FW_CMD = 0x0070,
ACX_HOST_IF_CFG_BITMAP = 0x0071,
@@ -1342,7 +1241,6 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl);
int wl1271_acx_mem_map(struct wl1271 *wl,
struct acx_header *mem_map, size_t len);
int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl);
-int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter);
int wl1271_acx_pd_threshold(struct wl1271 *wl);
int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
@@ -1354,8 +1252,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter);
int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable);
int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable);
-int wl1271_acx_sta_sg_cfg(struct wl1271 *wl);
-int wl1271_acx_ap_sg_cfg(struct wl1271 *wl);
+int wl12xx_acx_sg_cfg(struct wl1271 *wl);
int wl1271_acx_cca_threshold(struct wl1271 *wl);
int wl1271_acx_bcn_dtim_options(struct wl1271 *wl);
int wl1271_acx_aid(struct wl1271 *wl, u16 aid);
@@ -1374,8 +1271,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
u32 apsd_conf0, u32 apsd_conf1);
int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold);
int wl1271_acx_tx_config_options(struct wl1271 *wl);
-int wl1271_acx_ap_mem_cfg(struct wl1271 *wl);
-int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
+int wl12xx_acx_mem_cfg(struct wl1271 *wl);
int wl1271_acx_init_mem_config(struct wl1271 *wl);
int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap);
int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
@@ -1390,20 +1286,19 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl);
int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
struct ieee80211_sta_ht_cap *ht_cap,
- bool allow_ht_operation);
+ bool allow_ht_operation, u8 hlid);
int wl1271_acx_set_ht_information(struct wl1271 *wl,
u16 ht_operation_mode);
-int wl1271_acx_set_ba_session(struct wl1271 *wl,
- enum ieee80211_back_parties direction,
- u8 tid_index, u8 policy);
-int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
- bool enable);
+int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl);
+int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
+ u16 ssn, bool enable, u8 peer_hlid);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);
int wl1271_acx_config_ps(struct wl1271 *wl);
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
-int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable);
int wl1271_acx_fm_coex(struct wl1271 *wl);
+int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
+int wl12xx_acx_config_hangover(struct wl1271 *wl);
#endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 5ebc64d89407..d4e628db76b0 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -107,16 +107,6 @@ static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl)
unsigned int quirks = 0;
unsigned int *fw_ver = wl->chip.fw_ver;
- /* Only for wl127x */
- if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) &&
- /* Check STA version */
- (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
- (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) ||
- /* Check AP version */
- ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) &&
- (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN))))
- quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS;
-
/* Only new station firmwares support routing fw logs to the host */
if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
(fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN))
@@ -304,9 +294,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
*/
if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
- /* for now 11a is unsupported in AP mode */
- if (wl->bss_type != BSS_TYPE_AP_BSS &&
- nvs->general_params.dual_mode_select)
+ if (nvs->general_params.dual_mode_select)
wl->enable_11a = true;
}
@@ -504,21 +492,19 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
wl->event_mask = BSS_LOSE_EVENT_ID |
SCAN_COMPLETE_EVENT_ID |
PS_REPORT_EVENT_ID |
- JOIN_EVENT_COMPLETE_ID |
DISCONNECT_EVENT_COMPLETE_ID |
RSSI_SNR_TRIGGER_0_EVENT_ID |
PSPOLL_DELIVERY_FAILURE_EVENT_ID |
SOFT_GEMINI_SENSE_EVENT_ID |
PERIODIC_SCAN_REPORT_EVENT_ID |
- PERIODIC_SCAN_COMPLETE_EVENT_ID;
-
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID |
- INACTIVE_STA_EVENT_ID |
- MAX_TX_RETRY_EVENT_ID;
- else
- wl->event_mask |= DUMMY_PACKET_EVENT_ID |
- BA_SESSION_RX_CONSTRAINT_EVENT_ID;
+ PERIODIC_SCAN_COMPLETE_EVENT_ID |
+ DUMMY_PACKET_EVENT_ID |
+ PEER_REMOVE_COMPLETE_EVENT_ID |
+ BA_SESSION_RX_CONSTRAINT_EVENT_ID |
+ REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
+ INACTIVE_STA_EVENT_ID |
+ MAX_TX_RETRY_EVENT_ID |
+ CHANNEL_SWITCH_COMPLETE_EVENT_ID;
ret = wl1271_event_unmask(wl);
if (ret < 0) {
@@ -549,13 +535,13 @@ static void wl1271_boot_hw_version(struct wl1271 *wl)
{
u32 fuse;
- fuse = wl1271_top_reg_read(wl, REG_FUSE_DATA_2_1);
+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ fuse = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
+ else
+ fuse = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET;
wl->hw_pg_ver = (s8)fuse;
-
- if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
- wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
}
static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
@@ -696,7 +682,8 @@ static int wl127x_boot_clk(struct wl1271 *wl)
u32 pause;
u32 clk;
- wl1271_boot_hw_version(wl);
+ if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
+ wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
wl->ref_clock == CONF_REF_CLK_38_4_E ||
@@ -750,6 +737,8 @@ int wl1271_load_firmware(struct wl1271 *wl)
u32 tmp, clk;
int selected_clock = -1;
+ wl1271_boot_hw_version(wl);
+
if (wl->chip.id == CHIP_ID_1283_PG20) {
ret = wl128x_boot_clk(wl, &selected_clock);
if (ret < 0)
@@ -781,9 +770,6 @@ int wl1271_load_firmware(struct wl1271 *wl)
clk |= (wl->ref_clock << 1) << 4;
}
- if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
- clk |= SCRATCH_ENABLE_LPD;
-
wl1271_write32(wl, DRPW_SCRATCH_START, clk);
wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -852,9 +838,6 @@ int wl1271_boot(struct wl1271 *wl)
/* Enable firmware interrupts now */
wl1271_boot_enable_interrupts(wl);
- /* set the wl1271 default filters */
- wl1271_set_default_filters(wl);
-
wl1271_event_mbox_config(wl);
out:
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h
index e8f8255bbabe..06dad9380fa7 100644
--- a/drivers/net/wireless/wl12xx/boot.h
+++ b/drivers/net/wireless/wl12xx/boot.h
@@ -55,7 +55,8 @@ struct wl1271_static_data {
#define OCP_REG_CLK_POLARITY 0x0cb2
#define OCP_REG_CLK_PULL 0x0cb4
-#define REG_FUSE_DATA_2_1 0x050a
+#define WL127X_REG_FUSE_DATA_2_1 0x050a
+#define WL128X_REG_FUSE_DATA_2_1 0x2152
#define PG_VER_MASK 0x3c
#define PG_VER_OFFSET 2
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 97dd237a9580..a52299e548fa 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -134,11 +134,6 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
/* Override the REF CLK from the NVS with the one from platform data */
gen_parms->general_params.ref_clock = wl->ref_clock;
- /* LPD mode enable (bits 6-7) in WL1271 AP mode only */
- if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
- gen_parms->general_params.general_settings |=
- GENERAL_SETTINGS_DRPW_LPD;
-
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
if (ret < 0) {
wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
@@ -363,63 +358,476 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
return 0;
}
-int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
+int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id)
{
- struct wl1271_cmd_join *join;
- int ret, i;
- u8 *bssid;
+ struct wl12xx_cmd_role_enable *cmd;
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "cmd role enable");
+
+ if (WARN_ON(*role_id != WL12XX_INVALID_ROLE_ID))
+ return -EBUSY;
- join = kzalloc(sizeof(*join), GFP_KERNEL);
- if (!join) {
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
ret = -ENOMEM;
goto out;
}
- wl1271_debug(DEBUG_CMD, "cmd join");
+ /* get role id */
+ cmd->role_id = find_first_zero_bit(wl->roles_map, WL12XX_MAX_ROLES);
+ if (cmd->role_id >= WL12XX_MAX_ROLES) {
+ ret = -EBUSY;
+ goto out_free;
+ }
+
+ memcpy(cmd->mac_address, wl->mac_addr, ETH_ALEN);
+ cmd->role_type = role_type;
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role enable");
+ goto out_free;
+ }
+
+ __set_bit(cmd->role_id, wl->roles_map);
+ *role_id = cmd->role_id;
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id)
+{
+ struct wl12xx_cmd_role_disable *cmd;
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "cmd role disable");
+
+ if (WARN_ON(*role_id == WL12XX_INVALID_ROLE_ID))
+ return -ENOENT;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ cmd->role_id = *role_id;
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_DISABLE, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role disable");
+ goto out_free;
+ }
+
+ __clear_bit(*role_id, wl->roles_map);
+ *role_id = WL12XX_INVALID_ROLE_ID;
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid)
+{
+ u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS);
+ if (link >= WL12XX_MAX_LINKS)
+ return -EBUSY;
+
+ __set_bit(link, wl->links_map);
+ *hlid = link;
+ return 0;
+}
+
+static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid)
+{
+ if (*hlid == WL12XX_INVALID_LINK_ID)
+ return;
+
+ __clear_bit(*hlid, wl->links_map);
+ *hlid = WL12XX_INVALID_LINK_ID;
+}
+
+static int wl12xx_get_new_session_id(struct wl1271 *wl)
+{
+ if (wl->session_counter >= SESSION_COUNTER_MAX)
+ wl->session_counter = 0;
+
+ wl->session_counter++;
+
+ return wl->session_counter;
+}
- /* Reverse order BSSID */
- bssid = (u8 *) &join->bssid_lsb;
- for (i = 0; i < ETH_ALEN; i++)
- bssid[i] = wl->bssid[ETH_ALEN - i - 1];
+int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_start *cmd;
+ int ret;
- join->rx_config_options = cpu_to_le32(wl->rx_config);
- join->rx_filter_options = cpu_to_le32(wl->rx_filter);
- join->bss_type = bss_type;
- join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
- join->supported_rate_set = cpu_to_le32(wl->rate_set);
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wl->dev_role_id);
+
+ cmd->role_id = wl->dev_role_id;
if (wl->band == IEEE80211_BAND_5GHZ)
- join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
+ cmd->band = WL12XX_BAND_5GHZ;
+ cmd->channel = wl->channel;
+
+ if (wl->dev_hlid == WL12XX_INVALID_LINK_ID) {
+ ret = wl12xx_allocate_link(wl, &wl->dev_hlid);
+ if (ret)
+ goto out_free;
+ }
+ cmd->device.hlid = wl->dev_hlid;
+ cmd->device.session = wl->session_counter;
- join->beacon_interval = cpu_to_le16(wl->beacon_int);
- join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
+ wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d",
+ cmd->role_id, cmd->device.hlid, cmd->device.session);
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role enable");
+ goto err_hlid;
+ }
- join->channel = wl->channel;
- join->ssid_len = wl->ssid_len;
- memcpy(join->ssid, wl->ssid, wl->ssid_len);
+ goto out_free;
- join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
+err_hlid:
+ /* clear links on error */
+ __clear_bit(wl->dev_hlid, wl->links_map);
+ wl->dev_hlid = WL12XX_INVALID_LINK_ID;
- wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
- join->basic_rate_set, join->supported_rate_set);
- ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_stop_dev(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_stop *cmd;
+ int ret;
+
+ if (WARN_ON(wl->dev_hlid == WL12XX_INVALID_LINK_ID))
+ return -EINVAL;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd role stop dev");
+
+ cmd->role_id = wl->dev_role_id;
+ cmd->disc_type = DISCONNECT_IMMEDIATE;
+ cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role stop");
+ goto out_free;
+ }
+
+ ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
if (ret < 0) {
- wl1271_error("failed to initiate cmd join");
+ wl1271_error("cmd role stop dev event completion error");
goto out_free;
}
- ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID);
+ wl12xx_free_link(wl, &wl->dev_hlid);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_start *cmd;
+ int ret;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wl->role_id);
+
+ cmd->role_id = wl->role_id;
+ if (wl->band == IEEE80211_BAND_5GHZ)
+ cmd->band = WL12XX_BAND_5GHZ;
+ cmd->channel = wl->channel;
+ cmd->sta.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+ cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int);
+ cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY;
+ cmd->sta.ssid_len = wl->ssid_len;
+ memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len);
+ memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN);
+ cmd->sta.local_rates = cpu_to_le32(wl->rate_set);
+
+ if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) {
+ ret = wl12xx_allocate_link(wl, &wl->sta_hlid);
+ if (ret)
+ goto out_free;
+ }
+ cmd->sta.hlid = wl->sta_hlid;
+ cmd->sta.session = wl12xx_get_new_session_id(wl);
+ cmd->sta.remote_rates = cpu_to_le32(wl->rate_set);
+
+ wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
+ "basic_rate_set: 0x%x, remote_rates: 0x%x",
+ wl->role_id, cmd->sta.hlid, cmd->sta.session,
+ wl->basic_rate_set, wl->rate_set);
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role start sta");
+ goto err_hlid;
+ }
+
+ goto out_free;
+
+err_hlid:
+ /* clear links on error. */
+ wl12xx_free_link(wl, &wl->sta_hlid);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+/* use this function to stop ibss as well */
+int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_stop *cmd;
+ int ret;
+
+ if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID))
+ return -EINVAL;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wl->role_id);
+
+ cmd->role_id = wl->role_id;
+ cmd->disc_type = DISCONNECT_IMMEDIATE;
+ cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role stop sta");
+ goto out_free;
+ }
+
+ wl12xx_free_link(wl, &wl->sta_hlid);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_start *cmd;
+ struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id);
+
+ /* trying to use hidden SSID with an old hostapd version */
+ if (wl->ssid_len == 0 && !bss_conf->hidden_ssid) {
+ wl1271_error("got a null SSID from beacon/bss");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = wl12xx_allocate_link(wl, &wl->ap_global_hlid);
if (ret < 0)
- wl1271_error("cmd join event completion error");
+ goto out_free;
+
+ ret = wl12xx_allocate_link(wl, &wl->ap_bcast_hlid);
+ if (ret < 0)
+ goto out_free_global;
+
+ cmd->role_id = wl->role_id;
+ cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
+ cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
+ cmd->ap.global_hlid = wl->ap_global_hlid;
+ cmd->ap.broadcast_hlid = wl->ap_bcast_hlid;
+ cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+ cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int);
+ cmd->ap.dtim_interval = bss_conf->dtim_period;
+ cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
+ cmd->channel = wl->channel;
+
+ if (!bss_conf->hidden_ssid) {
+ /* take the SSID from the beacon for backward compatibility */
+ cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC;
+ cmd->ap.ssid_len = wl->ssid_len;
+ memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len);
+ } else {
+ cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN;
+ cmd->ap.ssid_len = bss_conf->ssid_len;
+ memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len);
+ }
+
+ cmd->ap.local_rates = cpu_to_le32(0xffffffff);
+
+ switch (wl->band) {
+ case IEEE80211_BAND_2GHZ:
+ cmd->band = RADIO_BAND_2_4GHZ;
+ break;
+ case IEEE80211_BAND_5GHZ:
+ cmd->band = RADIO_BAND_5GHZ;
+ break;
+ default:
+ wl1271_warning("ap start - unknown band: %d", (int)wl->band);
+ cmd->band = RADIO_BAND_2_4GHZ;
+ break;
+ }
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role start ap");
+ goto out_free_bcast;
+ }
+
+ goto out_free;
+
+out_free_bcast:
+ wl12xx_free_link(wl, &wl->ap_bcast_hlid);
+
+out_free_global:
+ wl12xx_free_link(wl, &wl->ap_global_hlid);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_stop *cmd;
+ int ret;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wl->role_id);
+
+ cmd->role_id = wl->role_id;
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role stop ap");
+ goto out_free;
+ }
+
+ wl12xx_free_link(wl, &wl->ap_bcast_hlid);
+ wl12xx_free_link(wl, &wl->ap_global_hlid);
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
+
+int wl12xx_cmd_role_start_ibss(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_role_start *cmd;
+ struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+ int ret;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wl->role_id);
+
+ cmd->role_id = wl->role_id;
+ if (wl->band == IEEE80211_BAND_5GHZ)
+ cmd->band = WL12XX_BAND_5GHZ;
+ cmd->channel = wl->channel;
+ cmd->ibss.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+ cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int);
+ cmd->ibss.dtim_interval = bss_conf->dtim_period;
+ cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY;
+ cmd->ibss.ssid_len = wl->ssid_len;
+ memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len);
+ memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN);
+ cmd->sta.local_rates = cpu_to_le32(wl->rate_set);
+
+ if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) {
+ ret = wl12xx_allocate_link(wl, &wl->sta_hlid);
+ if (ret)
+ goto out_free;
+ }
+ cmd->ibss.hlid = wl->sta_hlid;
+ cmd->ibss.remote_rates = cpu_to_le32(wl->rate_set);
+
+ wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
+ "basic_rate_set: 0x%x, remote_rates: 0x%x",
+ wl->role_id, cmd->sta.hlid, cmd->sta.session,
+ wl->basic_rate_set, wl->rate_set);
+
+ wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid);
+
+ ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to initiate cmd role enable");
+ goto err_hlid;
+ }
+
+ goto out_free;
+
+err_hlid:
+ /* clear links on error. */
+ wl12xx_free_link(wl, &wl->sta_hlid);
out_free:
- kfree(join);
+ kfree(cmd);
out:
return ret;
}
+
/**
* send test command to firmware
*
@@ -488,7 +896,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
struct acx_header *acx = buf;
int ret;
- wl1271_debug(DEBUG_CMD, "cmd configure");
+ wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id);
acx->id = cpu_to_le16(id);
@@ -567,6 +975,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
goto out;
}
+ ps_params->role_id = wl->role_id;
ps_params->ps_mode = ps_mode;
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
@@ -698,6 +1107,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
{
struct sk_buff *skb;
int ret;
+ u32 rate;
skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
ie, ie_len);
@@ -708,14 +1118,13 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
if (band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
- skb->data, skb->len, 0,
- wl->conf.tx.basic_rate);
+ skb->data, skb->len, 0, rate);
else
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- skb->data, skb->len, 0,
- wl->conf.tx.basic_rate_5);
+ skb->data, skb->len, 0, rate);
out:
dev_kfree_skb(skb);
@@ -726,6 +1135,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
struct sk_buff *skb)
{
int ret;
+ u32 rate;
if (!skb)
skb = ieee80211_ap_probereq_get(wl->hw, wl->vif);
@@ -734,14 +1144,13 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len);
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[wl->band]);
if (wl->band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
- skb->data, skb->len, 0,
- wl->conf.tx.basic_rate);
+ skb->data, skb->len, 0, rate);
else
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- skb->data, skb->len, 0,
- wl->conf.tx.basic_rate_5);
+ skb->data, skb->len, 0, rate);
if (ret < 0)
wl1271_error("Unable to set ap probe request template.");
@@ -813,9 +1222,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
wl->basic_rate);
}
-int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id)
+int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid)
{
- struct wl1271_cmd_set_sta_keys *cmd;
+ struct wl1271_cmd_set_keys *cmd;
int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
@@ -826,36 +1235,7 @@ int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id)
goto out;
}
- cmd->id = id;
- cmd->key_action = cpu_to_le16(KEY_SET_ID);
- cmd->key_type = KEY_WEP;
-
- ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
- if (ret < 0) {
- wl1271_warning("cmd set_default_wep_key failed: %d", ret);
- goto out;
- }
-
-out:
- kfree(cmd);
-
- return ret;
-}
-
-int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id)
-{
- struct wl1271_cmd_set_ap_keys *cmd;
- int ret = 0;
-
- wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id);
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (!cmd) {
- ret = -ENOMEM;
- goto out;
- }
-
- cmd->hlid = WL1271_AP_BROADCAST_HLID;
+ cmd->hlid = hlid;
cmd->key_id = id;
cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
cmd->key_action = cpu_to_le16(KEY_SET_ID);
@@ -863,7 +1243,7 @@ int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id)
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret);
+ wl1271_warning("cmd set_default_wep_key failed: %d", ret);
goto out;
}
@@ -877,17 +1257,27 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16)
{
- struct wl1271_cmd_set_sta_keys *cmd;
+ struct wl1271_cmd_set_keys *cmd;
int ret = 0;
+ /* hlid might have already been deleted */
+ if (wl->sta_hlid == WL12XX_INVALID_LINK_ID)
+ return 0;
+
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
- if (key_type != KEY_WEP)
- memcpy(cmd->addr, addr, ETH_ALEN);
+ cmd->hlid = wl->sta_hlid;
+
+ if (key_type == KEY_WEP)
+ cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
+ else if (is_broadcast_ether_addr(addr))
+ cmd->lid_key_type = BROADCAST_LID_TYPE;
+ else
+ cmd->lid_key_type = UNICAST_LID_TYPE;
cmd->key_action = cpu_to_le16(action);
cmd->key_size = key_size;
@@ -896,10 +1286,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16);
cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32);
- /* we have only one SSID profile */
- cmd->ssid_profile = 0;
-
- cmd->id = id;
+ cmd->key_id = id;
if (key_type == KEY_TKIP) {
/*
@@ -930,11 +1317,15 @@ out:
return ret;
}
+/*
+ * TODO: merge with sta/ibss into 1 set_key function.
+ * note there are slight diffs
+ */
int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
u16 tx_seq_16)
{
- struct wl1271_cmd_set_ap_keys *cmd;
+ struct wl1271_cmd_set_keys *cmd;
int ret = 0;
u8 lid_type;
@@ -942,7 +1333,7 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
if (!cmd)
return -ENOMEM;
- if (hlid == WL1271_AP_BROADCAST_HLID) {
+ if (hlid == wl->ap_bcast_hlid) {
if (key_type == KEY_WEP)
lid_type = WEP_DEFAULT_LID_TYPE;
else
@@ -991,12 +1382,12 @@ out:
return ret;
}
-int wl1271_cmd_disconnect(struct wl1271 *wl)
+int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid)
{
- struct wl1271_cmd_disconnect *cmd;
+ struct wl12xx_cmd_set_peer_state *cmd;
int ret = 0;
- wl1271_debug(DEBUG_CMD, "cmd disconnect");
+ wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", hlid);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1004,21 +1395,15 @@ int wl1271_cmd_disconnect(struct wl1271 *wl)
goto out;
}
- cmd->rx_config_options = cpu_to_le32(wl->rx_config);
- cmd->rx_filter_options = cpu_to_le32(wl->rx_filter);
- /* disconnect reason is not used in immediate disconnections */
- cmd->type = DISCONNECT_IMMEDIATE;
+ cmd->hlid = hlid;
+ cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
- ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0);
+ ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to send disconnect command");
+ wl1271_error("failed to send set peer state command");
goto out_free;
}
- ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
- if (ret < 0)
- wl1271_error("cmd disconnect event completion error");
-
out_free:
kfree(cmd);
@@ -1026,12 +1411,13 @@ out:
return ret;
}
-int wl1271_cmd_set_sta_state(struct wl1271 *wl)
+int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
{
- struct wl1271_cmd_set_sta_state *cmd;
- int ret = 0;
+ struct wl12xx_cmd_add_peer *cmd;
+ int i, ret;
+ u32 sta_rates;
- wl1271_debug(DEBUG_CMD, "cmd set sta state");
+ wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1039,11 +1425,33 @@ int wl1271_cmd_set_sta_state(struct wl1271 *wl)
goto out;
}
- cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
+ memcpy(cmd->addr, sta->addr, ETH_ALEN);
+ cmd->bss_index = WL1271_AP_BSS_INDEX;
+ cmd->aid = sta->aid;
+ cmd->hlid = hlid;
+ cmd->sp_len = sta->max_sp;
+ cmd->wmm = sta->wme ? 1 : 0;
+
+ for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++)
+ if (sta->wme && (sta->uapsd_queues & BIT(i)))
+ cmd->psd_type[i] = WL1271_PSD_UPSD_TRIGGER;
+ else
+ cmd->psd_type[i] = WL1271_PSD_LEGACY;
+
+ sta_rates = sta->supp_rates[wl->band];
+ if (sta->ht_cap.ht_supported)
+ sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;
- ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0);
+ cmd->supported_rates =
+ cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates,
+ wl->band));
+
+ wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x",
+ cmd->supported_rates, sta->uapsd_queues);
+
+ ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to send set STA state command");
+ wl1271_error("failed to initiate cmd add peer");
goto out_free;
}
@@ -1054,23 +1462,12 @@ out:
return ret;
}
-int wl1271_cmd_start_bss(struct wl1271 *wl)
+int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
{
- struct wl1271_cmd_bss_start *cmd;
- struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+ struct wl12xx_cmd_remove_peer *cmd;
int ret;
- wl1271_debug(DEBUG_CMD, "cmd start bss");
-
- /*
- * FIXME: We currently do not support hidden SSID. The real SSID
- * should be fetched from mac80211 first.
- */
- if (wl->ssid_len == 0) {
- wl1271_warning("Hidden SSID currently not supported for AP");
- ret = -EINVAL;
- goto out;
- }
+ wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1078,40 +1475,24 @@ int wl1271_cmd_start_bss(struct wl1271 *wl)
goto out;
}
- memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
-
- cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
- cmd->bss_index = WL1271_AP_BSS_INDEX;
- cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
- cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
- cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
- cmd->beacon_interval = cpu_to_le16(wl->beacon_int);
- cmd->dtim_interval = bss_conf->dtim_period;
- cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
- cmd->channel = wl->channel;
- cmd->ssid_len = wl->ssid_len;
- cmd->ssid_type = SSID_TYPE_PUBLIC;
- memcpy(cmd->ssid, wl->ssid, wl->ssid_len);
-
- switch (wl->band) {
- case IEEE80211_BAND_2GHZ:
- cmd->band = RADIO_BAND_2_4GHZ;
- break;
- case IEEE80211_BAND_5GHZ:
- cmd->band = RADIO_BAND_5GHZ;
- break;
- default:
- wl1271_warning("bss start - unknown band: %d", (int)wl->band);
- cmd->band = RADIO_BAND_2_4GHZ;
- break;
- }
+ cmd->hlid = hlid;
+ /* We never send a deauth, mac80211 is in charge of this */
+ cmd->reason_opcode = 0;
+ cmd->send_deauth_flag = 0;
- ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0);
+ ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to initiate cmd start bss");
+ wl1271_error("failed to initiate cmd remove peer");
goto out_free;
}
+ /*
+ * We are ok with a timeout here. The event is sometimes not sent
+ * due to a firmware bug.
+ */
+ wl1271_cmd_wait_for_event_or_timeout(wl,
+ PEER_REMOVE_COMPLETE_EVENT_ID);
+
out_free:
kfree(cmd);
@@ -1119,12 +1500,12 @@ out:
return ret;
}
-int wl1271_cmd_stop_bss(struct wl1271 *wl)
+int wl12xx_cmd_config_fwlog(struct wl1271 *wl)
{
- struct wl1271_cmd_bss_start *cmd;
- int ret;
+ struct wl12xx_cmd_config_fwlog *cmd;
+ int ret = 0;
- wl1271_debug(DEBUG_CMD, "cmd stop bss");
+ wl1271_debug(DEBUG_CMD, "cmd config firmware logger");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1132,11 +1513,15 @@ int wl1271_cmd_stop_bss(struct wl1271 *wl)
goto out;
}
- cmd->bss_index = WL1271_AP_BSS_INDEX;
+ cmd->logger_mode = wl->conf.fwlog.mode;
+ cmd->log_severity = wl->conf.fwlog.severity;
+ cmd->timestamp = wl->conf.fwlog.timestamp;
+ cmd->output = wl->conf.fwlog.output;
+ cmd->threshold = wl->conf.fwlog.threshold;
- ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0);
+ ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to initiate cmd stop bss");
+ wl1271_error("failed to send config firmware logger command");
goto out_free;
}
@@ -1147,12 +1532,12 @@ out:
return ret;
}
-int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
+int wl12xx_cmd_start_fwlog(struct wl1271 *wl)
{
- struct wl1271_cmd_add_sta *cmd;
- int ret;
+ struct wl12xx_cmd_start_fwlog *cmd;
+ int ret = 0;
- wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid);
+ wl1271_debug(DEBUG_CMD, "cmd start firmware logger");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1160,23 +1545,35 @@ int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
goto out;
}
- /* currently we don't support UAPSD */
- cmd->sp_len = 0;
+ ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to send start firmware logger command");
+ goto out_free;
+ }
- memcpy(cmd->addr, sta->addr, ETH_ALEN);
- cmd->bss_index = WL1271_AP_BSS_INDEX;
- cmd->aid = sta->aid;
- cmd->hlid = hlid;
- cmd->wmm = sta->wme ? 1 : 0;
+out_free:
+ kfree(cmd);
- cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
- sta->supp_rates[wl->band]));
+out:
+ return ret;
+}
- wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates);
+int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
+{
+ struct wl12xx_cmd_stop_fwlog *cmd;
+ int ret = 0;
- ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0);
+ wl1271_debug(DEBUG_CMD, "cmd stop firmware logger");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to initiate cmd add sta");
+ wl1271_error("failed to send stop firmware logger command");
goto out_free;
}
@@ -1187,12 +1584,15 @@ out:
return ret;
}
-int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
+static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
{
- struct wl1271_cmd_remove_sta *cmd;
- int ret;
+ struct wl12xx_cmd_roc *cmd;
+ int ret = 0;
- wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid);
+ wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wl->channel, role_id);
+
+ if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID))
+ return -EINVAL;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1200,23 +1600,28 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
goto out;
}
- cmd->hlid = hlid;
- /* We never send a deauth, mac80211 is in charge of this */
- cmd->reason_opcode = 0;
- cmd->send_deauth_flag = 0;
+ cmd->role_id = role_id;
+ cmd->channel = wl->channel;
+ switch (wl->band) {
+ case IEEE80211_BAND_2GHZ:
+ cmd->band = RADIO_BAND_2_4GHZ;
+ break;
+ case IEEE80211_BAND_5GHZ:
+ cmd->band = RADIO_BAND_5GHZ;
+ break;
+ default:
+ wl1271_error("roc - unknown band: %d", (int)wl->band);
+ ret = -EINVAL;
+ goto out_free;
+ }
- ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0);
+
+ ret = wl1271_cmd_send(wl, CMD_REMAIN_ON_CHANNEL, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to initiate cmd remove sta");
+ wl1271_error("failed to send ROC command");
goto out_free;
}
- /*
- * We are ok with a timeout here. The event is sometimes not sent
- * due to a firmware bug.
- */
- wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID);
-
out_free:
kfree(cmd);
@@ -1224,28 +1629,24 @@ out:
return ret;
}
-int wl12xx_cmd_config_fwlog(struct wl1271 *wl)
+static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id)
{
- struct wl12xx_cmd_config_fwlog *cmd;
+ struct wl12xx_cmd_croc *cmd;
int ret = 0;
- wl1271_debug(DEBUG_CMD, "cmd config firmware logger");
+ wl1271_debug(DEBUG_CMD, "cmd croc (%d)", role_id);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
ret = -ENOMEM;
goto out;
}
+ cmd->role_id = role_id;
- cmd->logger_mode = wl->conf.fwlog.mode;
- cmd->log_severity = wl->conf.fwlog.severity;
- cmd->timestamp = wl->conf.fwlog.timestamp;
- cmd->output = wl->conf.fwlog.output;
- cmd->threshold = wl->conf.fwlog.threshold;
-
- ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0);
+ ret = wl1271_cmd_send(wl, CMD_CANCEL_REMAIN_ON_CHANNEL, cmd,
+ sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to send config firmware logger command");
+ wl1271_error("failed to send ROC command");
goto out_free;
}
@@ -1256,12 +1657,52 @@ out:
return ret;
}
-int wl12xx_cmd_start_fwlog(struct wl1271 *wl)
+int wl12xx_roc(struct wl1271 *wl, u8 role_id)
{
- struct wl12xx_cmd_start_fwlog *cmd;
int ret = 0;
- wl1271_debug(DEBUG_CMD, "cmd start firmware logger");
+ if (WARN_ON(test_bit(role_id, wl->roc_map)))
+ return 0;
+
+ ret = wl12xx_cmd_roc(wl, role_id);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_cmd_wait_for_event(wl,
+ REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID);
+ if (ret < 0) {
+ wl1271_error("cmd roc event completion error");
+ goto out;
+ }
+
+ __set_bit(role_id, wl->roc_map);
+out:
+ return ret;
+}
+
+int wl12xx_croc(struct wl1271 *wl, u8 role_id)
+{
+ int ret = 0;
+
+ if (WARN_ON(!test_bit(role_id, wl->roc_map)))
+ return 0;
+
+ ret = wl12xx_cmd_croc(wl, role_id);
+ if (ret < 0)
+ goto out;
+
+ __clear_bit(role_id, wl->roc_map);
+out:
+ return ret;
+}
+
+int wl12xx_cmd_channel_switch(struct wl1271 *wl,
+ struct ieee80211_channel_switch *ch_switch)
+{
+ struct wl12xx_cmd_channel_switch *cmd;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "cmd channel switch");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1269,9 +1710,14 @@ int wl12xx_cmd_start_fwlog(struct wl1271 *wl)
goto out;
}
- ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0);
+ cmd->channel = ch_switch->channel->hw_value;
+ cmd->switch_time = ch_switch->count;
+ cmd->tx_suspend = ch_switch->block_tx;
+ cmd->flush = 0; /* this value is ignored by the FW */
+
+ ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to send start firmware logger command");
+ wl1271_error("failed to send channel switch command");
goto out_free;
}
@@ -1282,12 +1728,12 @@ out:
return ret;
}
-int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
+int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl)
{
- struct wl12xx_cmd_stop_fwlog *cmd;
- int ret = 0;
+ struct wl12xx_cmd_stop_channel_switch *cmd;
+ int ret;
- wl1271_debug(DEBUG_CMD, "cmd stop firmware logger");
+ wl1271_debug(DEBUG_ACX, "cmd stop channel switch");
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
@@ -1295,9 +1741,9 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
goto out;
}
- ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0);
+ ret = wl1271_cmd_send(wl, CMD_STOP_CHANNEL_SWICTH, cmd, sizeof(*cmd), 0);
if (ret < 0) {
- wl1271_error("failed to send stop firmware logger command");
+ wl1271_error("failed to stop channel switch command");
goto out_free;
}
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 1f7037292c15..b7bd42769aa7 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -36,7 +36,15 @@ int wl128x_cmd_general_parms(struct wl1271 *wl);
int wl1271_cmd_radio_parms(struct wl1271 *wl);
int wl128x_cmd_radio_parms(struct wl1271 *wl);
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
-int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type);
+int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id);
+int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id);
+int wl12xx_cmd_role_start_dev(struct wl1271 *wl);
+int wl12xx_cmd_role_stop_dev(struct wl1271 *wl);
+int wl12xx_cmd_role_start_sta(struct wl1271 *wl);
+int wl12xx_cmd_role_stop_sta(struct wl1271 *wl);
+int wl12xx_cmd_role_start_ap(struct wl1271 *wl);
+int wl12xx_cmd_role_stop_ap(struct wl1271 *wl);
+int wl12xx_cmd_role_start_ibss(struct wl1271 *wl);
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
@@ -56,23 +64,24 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr);
int wl1271_build_qos_null_data(struct wl1271 *wl);
int wl1271_cmd_build_klv_null_data(struct wl1271 *wl);
-int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id);
-int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id);
+int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid);
int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16);
int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
u16 tx_seq_16);
-int wl1271_cmd_disconnect(struct wl1271 *wl);
-int wl1271_cmd_set_sta_state(struct wl1271 *wl);
-int wl1271_cmd_start_bss(struct wl1271 *wl);
-int wl1271_cmd_stop_bss(struct wl1271 *wl);
-int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
-int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid);
+int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid);
+int wl12xx_roc(struct wl1271 *wl, u8 role_id);
+int wl12xx_croc(struct wl1271 *wl, u8 role_id);
+int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
+int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
+int wl12xx_cmd_channel_switch(struct wl1271 *wl,
+ struct ieee80211_channel_switch *ch_switch);
+int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl);
enum wl1271_commands {
CMD_INTERROGATE = 1, /*use this to read information elements*/
@@ -83,25 +92,21 @@ enum wl1271_commands {
CMD_DISABLE_TX = 6,
CMD_SCAN = 8,
CMD_STOP_SCAN = 9,
- CMD_START_JOIN = 11,
CMD_SET_KEYS = 12,
CMD_READ_MEMORY = 13,
CMD_WRITE_MEMORY = 14,
CMD_SET_TEMPLATE = 19,
CMD_TEST = 23,
CMD_NOISE_HIST = 28,
- CMD_LNA_CONTROL = 32,
+ CMD_QUIET_ELEMENT_SET_STATE = 29,
CMD_SET_BCN_MODE = 33,
CMD_MEASUREMENT = 34,
CMD_STOP_MEASUREMENT = 35,
- CMD_DISCONNECT = 36,
CMD_SET_PS_MODE = 37,
CMD_CHANNEL_SWITCH = 38,
CMD_STOP_CHANNEL_SWICTH = 39,
CMD_AP_DISCOVERY = 40,
CMD_STOP_AP_DISCOVERY = 41,
- CMD_SPS_SCAN = 42,
- CMD_STOP_SPS_SCAN = 43,
CMD_HEALTH_CHECK = 45,
CMD_DEBUG = 46,
CMD_TRIGGER_SCAN_TO = 47,
@@ -109,16 +114,30 @@ enum wl1271_commands {
CMD_CONNECTION_SCAN_SSID_CFG = 49,
CMD_START_PERIODIC_SCAN = 50,
CMD_STOP_PERIODIC_SCAN = 51,
- CMD_SET_STA_STATE = 52,
- CMD_CONFIG_FWLOGGER = 53,
- CMD_START_FWLOGGER = 54,
- CMD_STOP_FWLOGGER = 55,
+ CMD_SET_PEER_STATE = 52,
+ CMD_REMAIN_ON_CHANNEL = 53,
+ CMD_CANCEL_REMAIN_ON_CHANNEL = 54,
- /* AP mode commands */
- CMD_BSS_START = 60,
- CMD_BSS_STOP = 61,
- CMD_ADD_STA = 62,
- CMD_REMOVE_STA = 63,
+ CMD_CONFIG_FWLOGGER = 55,
+ CMD_START_FWLOGGER = 56,
+ CMD_STOP_FWLOGGER = 57,
+
+ /* AP commands */
+ CMD_ADD_PEER = 62,
+ CMD_REMOVE_PEER = 63,
+
+ /* Role API */
+ CMD_ROLE_ENABLE = 70,
+ CMD_ROLE_DISABLE = 71,
+ CMD_ROLE_START = 72,
+ CMD_ROLE_STOP = 73,
+
+ /* WIFI Direct */
+ CMD_WFD_START_DISCOVERY = 80,
+ CMD_WFD_STOP_DISCOVERY = 81,
+ CMD_WFD_ATTRIBUTE_CONFIG = 82,
+
+ CMD_NOP = 100,
NUM_COMMANDS,
MAX_COMMAND_ID = 0xFFFF,
@@ -147,21 +166,20 @@ enum cmd_templ {
CMD_TEMPL_CTS, /*
* For CTS-to-self (FastCTS) mechanism
* for BT/WLAN coexistence (SoftGemini). */
- CMD_TEMPL_ARP_RSP,
- CMD_TEMPL_LINK_MEASUREMENT_REPORT,
-
- /* AP-mode specific */
- CMD_TEMPL_AP_BEACON = 13,
+ CMD_TEMPL_AP_BEACON,
CMD_TEMPL_AP_PROBE_RESPONSE,
- CMD_TEMPL_AP_ARP_RSP,
+ CMD_TEMPL_ARP_RSP,
CMD_TEMPL_DEAUTH_AP,
+ CMD_TEMPL_TEMPORARY,
+ CMD_TEMPL_LINK_MEASUREMENT_REPORT,
CMD_TEMPL_MAX = 0xff
};
/* unit ms */
#define WL1271_COMMAND_TIMEOUT 2000
-#define WL1271_CMD_TEMPL_MAX_SIZE 252
+#define WL1271_CMD_TEMPL_DFLT_SIZE 252
+#define WL1271_CMD_TEMPL_MAX_SIZE 548
#define WL1271_EVENT_TIMEOUT 750
struct wl1271_cmd_header {
@@ -193,6 +211,8 @@ enum {
CMD_STATUS_WRONG_NESTING = 19,
CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/
CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/
+ CMD_STATUS_TEMPLATE_OOM = 23,
+ CMD_STATUS_NO_RX_BA_SESSION = 24,
MAX_COMMAND_STATUS = 0xff
};
@@ -210,38 +230,114 @@ enum {
#define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1
#define WL1271_JOIN_CMD_BSS_TYPE_5GHZ 0x10
-struct wl1271_cmd_join {
+struct wl12xx_cmd_role_enable {
struct wl1271_cmd_header header;
- __le32 bssid_lsb;
- __le16 bssid_msb;
- __le16 beacon_interval; /* in TBTTs */
- __le32 rx_config_options;
- __le32 rx_filter_options;
+ u8 role_id;
+ u8 role_type;
+ u8 mac_address[ETH_ALEN];
+} __packed;
- /*
- * The target uses this field to determine the rate at
- * which to transmit control frame responses (such as
- * ACK or CTS frames).
- */
- __le32 basic_rate_set;
- __le32 supported_rate_set;
- u8 dtim_interval;
- /*
- * bits 0-2: This bitwise field specifies the type
- * of BSS to start or join (BSS_TYPE_*).
- * bit 4: Band - The radio band in which to join
- * or start.
- * 0 - 2.4GHz band
- * 1 - 5GHz band
- * bits 3, 5-7: Reserved
- */
- u8 bss_type;
+struct wl12xx_cmd_role_disable {
+ struct wl1271_cmd_header header;
+
+ u8 role_id;
+ u8 padding[3];
+} __packed;
+
+enum wl12xx_band {
+ WL12XX_BAND_2_4GHZ = 0,
+ WL12XX_BAND_5GHZ = 1,
+ WL12XX_BAND_JAPAN_4_9_GHZ = 2,
+ WL12XX_BAND_DEFAULT = WL12XX_BAND_2_4GHZ,
+ WL12XX_BAND_INVALID = 0x7E,
+ WL12XX_BAND_MAX_RADIO = 0x7F,
+};
+
+struct wl12xx_cmd_role_start {
+ struct wl1271_cmd_header header;
+
+ u8 role_id;
+ u8 band;
u8 channel;
- u8 ssid_len;
- u8 ssid[IW_ESSID_MAX_SIZE];
- u8 ctrl; /* JOIN_CMD_CTRL_* */
- u8 reserved[3];
+ u8 padding;
+
+ union {
+ struct {
+ u8 hlid;
+ u8 session;
+ u8 padding_1[54];
+ } __packed device;
+ /* sta & p2p_cli use the same struct */
+ struct {
+ u8 bssid[ETH_ALEN];
+ u8 hlid; /* data hlid */
+ u8 session;
+ __le32 remote_rates; /* remote supported rates */
+
+ /*
+ * The target uses this field to determine the rate at
+ * which to transmit control frame responses (such as
+ * ACK or CTS frames).
+ */
+ __le32 basic_rate_set;
+ __le32 local_rates; /* local supported rates */
+
+ u8 ssid_type;
+ u8 ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+
+ __le16 beacon_interval; /* in TBTTs */
+ } __packed sta;
+ struct {
+ u8 bssid[ETH_ALEN];
+ u8 hlid; /* data hlid */
+ u8 dtim_interval;
+ __le32 remote_rates; /* remote supported rates */
+
+ __le32 basic_rate_set;
+ __le32 local_rates; /* local supported rates */
+
+ u8 ssid_type;
+ u8 ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+
+ __le16 beacon_interval; /* in TBTTs */
+
+ u8 padding_1[4];
+ } __packed ibss;
+ /* ap & p2p_go use the same struct */
+ struct {
+ __le16 aging_period; /* in secs */
+ u8 beacon_expiry; /* in ms */
+ u8 bss_index;
+ /* The host link id for the AP's global queue */
+ u8 global_hlid;
+ /* The host link id for the AP's broadcast queue */
+ u8 broadcast_hlid;
+
+ __le16 beacon_interval; /* in TBTTs */
+
+ __le32 basic_rate_set;
+ __le32 local_rates; /* local supported rates */
+
+ u8 dtim_interval;
+
+ u8 ssid_type;
+ u8 ssid_len;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+
+ u8 padding_1[5];
+ } __packed ap;
+ };
+} __packed;
+
+struct wl12xx_cmd_role_stop {
+ struct wl1271_cmd_header header;
+
+ u8 role_id;
+ u8 disc_type; /* only STA and P2P_CLI */
+ __le16 reason; /* only STA and P2P_CLI */
} __packed;
struct cmd_enabledisable_path {
@@ -287,8 +383,9 @@ enum wl1271_cmd_ps_mode {
struct wl1271_cmd_ps_params {
struct wl1271_cmd_header header;
+ u8 role_id;
u8 ps_mode; /* STATION_* */
- u8 padding[3];
+ u8 padding[2];
} __packed;
/* HW encryption keys */
@@ -301,6 +398,12 @@ enum wl1271_cmd_key_action {
MAX_KEY_ACTION = 0xffff,
};
+enum wl1271_cmd_lid_key_type {
+ UNICAST_LID_TYPE = 0,
+ BROADCAST_LID_TYPE = 1,
+ WEP_DEFAULT_LID_TYPE = 2
+};
+
enum wl1271_cmd_key_type {
KEY_NONE = 0,
KEY_WEP = 1,
@@ -309,44 +412,7 @@ enum wl1271_cmd_key_type {
KEY_GEM = 4,
};
-/* FIXME: Add description for key-types */
-
-struct wl1271_cmd_set_sta_keys {
- struct wl1271_cmd_header header;
-
- /* Ignored for default WEP key */
- u8 addr[ETH_ALEN];
-
- /* key_action_e */
- __le16 key_action;
-
- __le16 reserved_1;
-
- /* key size in bytes */
- u8 key_size;
-
- /* key_type_e */
- u8 key_type;
- u8 ssid_profile;
-
- /*
- * TKIP, AES: frame's key id field.
- * For WEP default key: key id;
- */
- u8 id;
- u8 reserved_2[6];
- u8 key[MAX_KEY_SIZE];
- __le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
- __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
-} __packed;
-
-enum wl1271_cmd_lid_key_type {
- UNICAST_LID_TYPE = 0,
- BROADCAST_LID_TYPE = 1,
- WEP_DEFAULT_LID_TYPE = 2
-};
-
-struct wl1271_cmd_set_ap_keys {
+struct wl1271_cmd_set_keys {
struct wl1271_cmd_header header;
/*
@@ -496,69 +562,46 @@ enum wl1271_disconnect_type {
DISCONNECT_DISASSOC
};
-struct wl1271_cmd_disconnect {
- struct wl1271_cmd_header header;
-
- __le32 rx_config_options;
- __le32 rx_filter_options;
-
- __le16 reason;
- u8 type;
-
- u8 padding;
-} __packed;
-
#define WL1271_CMD_STA_STATE_CONNECTED 1
-struct wl1271_cmd_set_sta_state {
+struct wl12xx_cmd_set_peer_state {
struct wl1271_cmd_header header;
+ u8 hlid;
u8 state;
- u8 padding[3];
+ u8 padding[2];
} __packed;
-enum wl1271_ssid_type {
- SSID_TYPE_PUBLIC = 0,
- SSID_TYPE_HIDDEN = 1
+struct wl12xx_cmd_roc {
+ struct wl1271_cmd_header header;
+
+ u8 role_id;
+ u8 channel;
+ u8 band;
+ u8 padding;
};
-struct wl1271_cmd_bss_start {
+struct wl12xx_cmd_croc {
struct wl1271_cmd_header header;
- /* wl1271_ssid_type */
- u8 ssid_type;
- u8 ssid_len;
- u8 ssid[IW_ESSID_MAX_SIZE];
- u8 padding_1[2];
+ u8 role_id;
+ u8 padding[3];
+};
- /* Basic rate set */
- __le32 basic_rate_set;
- /* Aging period in seconds*/
- __le16 aging_period;
+enum wl12xx_ssid_type {
+ WL12XX_SSID_TYPE_PUBLIC = 0,
+ WL12XX_SSID_TYPE_HIDDEN = 1,
+ WL12XX_SSID_TYPE_ANY = 2,
+};
- /*
- * This field specifies the time between target beacon
- * transmission times (TBTTs), in time units (TUs).
- * Valid values are 1 to 1024.
- */
- __le16 beacon_interval;
- u8 bssid[ETH_ALEN];
- u8 bss_index;
- /* Radio band */
- u8 band;
- u8 channel;
- /* The host link id for the AP's global queue */
- u8 global_hlid;
- /* The host link id for the AP's broadcast queue */
- u8 broadcast_hlid;
- /* DTIM count */
- u8 dtim_interval;
- /* Beacon expiry time in ms */
- u8 beacon_expiry;
- u8 padding_2[3];
-} __packed;
+enum wl1271_psd_type {
+ WL1271_PSD_LEGACY = 0,
+ WL1271_PSD_UPSD_TRIGGER = 1,
+ WL1271_PSD_LEGACY_PSPOLL = 2,
+ WL1271_PSD_SAPSD = 3
+};
-struct wl1271_cmd_add_sta {
+struct wl12xx_cmd_add_peer {
struct wl1271_cmd_header header;
u8 addr[ETH_ALEN];
@@ -572,7 +615,7 @@ struct wl1271_cmd_add_sta {
u8 padding1;
} __packed;
-struct wl1271_cmd_remove_sta {
+struct wl12xx_cmd_remove_peer {
struct wl1271_cmd_header header;
u8 hlid;
@@ -637,4 +680,21 @@ struct wl12xx_cmd_stop_fwlog {
struct wl1271_cmd_header header;
} __packed;
+struct wl12xx_cmd_channel_switch {
+ struct wl1271_cmd_header header;
+
+ /* The new serving channel */
+ u8 channel;
+ /* Relative time of the serving channel switch in TBTT units */
+ u8 switch_time;
+ /* 1: Suspend TX till switch time; 0: Do not suspend TX */
+ u8 tx_suspend;
+ /* 1: Flush TX at switch time; 0: Do not flush */
+ u8 flush;
+} __packed;
+
+struct wl12xx_cmd_stop_channel_switch {
+ struct wl1271_cmd_header header;
+} __packed;
+
#endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 6080e01d92c6..04bb8fbf93f9 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -99,40 +99,75 @@ enum {
enum {
/*
- * PER threshold in PPM of the BT voice
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT master basic rate
*
- * Range: 0 - 10000000
+ * Range: 0 - 255 (ms)
*/
- CONF_SG_BT_PER_THRESHOLD = 0,
+ CONF_SG_ACL_BT_MASTER_MIN_BR = 0,
+ CONF_SG_ACL_BT_MASTER_MAX_BR,
/*
- * Number of consequent RX_ACTIVE activities to override BT voice
- * frames to ensure WLAN connection
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT slave basic rate
*
- * Range: 0 - 100
+ * Range: 0 - 255 (ms)
*/
- CONF_SG_HV3_MAX_OVERRIDE,
+ CONF_SG_ACL_BT_SLAVE_MIN_BR,
+ CONF_SG_ACL_BT_SLAVE_MAX_BR,
/*
- * Defines the PER threshold of the BT voice
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT master EDR
*
- * Range: 0 - 65000
+ * Range: 0 - 255 (ms)
*/
- CONF_SG_BT_NFS_SAMPLE_INTERVAL,
+ CONF_SG_ACL_BT_MASTER_MIN_EDR,
+ CONF_SG_ACL_BT_MASTER_MAX_EDR,
/*
- * Defines the load ratio of BT
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT slave EDR
*
- * Range: 0 - 100 (%)
+ * Range: 0 - 255 (ms)
*/
- CONF_SG_BT_LOAD_RATIO,
+ CONF_SG_ACL_BT_SLAVE_MIN_EDR,
+ CONF_SG_ACL_BT_SLAVE_MAX_EDR,
/*
- * Defines whether the SG will force WLAN host to enter/exit PSM
+ * The maximum time WLAN can gain the antenna
+ * in WLAN PSM / BT master/slave BR
*
- * Range: 1 - SG can force, 0 - host handles PSM
+ * Range: 0 - 255 (ms)
*/
- CONF_SG_AUTO_PS_MODE,
+ CONF_SG_ACL_WLAN_PS_MASTER_BR,
+ CONF_SG_ACL_WLAN_PS_SLAVE_BR,
+
+ /*
+ * The maximum time WLAN can gain the antenna
+ * in WLAN PSM / BT master/slave EDR
+ *
+ * Range: 0 - 255 (ms)
+ */
+ CONF_SG_ACL_WLAN_PS_MASTER_EDR,
+ CONF_SG_ACL_WLAN_PS_SLAVE_EDR,
+
+ /* TODO: explain these values */
+ CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR,
+ CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR,
+ CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR,
+ CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR,
+ CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR,
+ CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR,
+ CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR,
+ CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR,
+
+ CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR,
+ CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR,
+ CONF_SG_ACL_PASSIVE_SCAN_BT_BR,
+ CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR,
+ CONF_SG_ACL_PASSIVE_SCAN_BT_EDR,
+ CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR,
/*
* Compensation percentage of probe requests when scan initiated
@@ -151,102 +186,70 @@ enum {
CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3,
/*
- * Defines antenna configuration (single/dual antenna)
- *
- * Range: 0 - single antenna, 1 - dual antenna
- */
- CONF_SG_ANTENNA_CONFIGURATION,
-
- /*
- * The threshold (percent) of max consequtive beacon misses before
- * increasing priority of beacon reception.
- *
- * Range: 0 - 100 (%)
- */
- CONF_SG_BEACON_MISS_PERCENT,
-
- /*
- * The rate threshold below which receiving a data frame from the AP
- * will increase the priority of the data frame above BT traffic.
- *
- * Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54
- */
- CONF_SG_RATE_ADAPT_THRESH,
-
- /*
- * Not used currently.
+ * Compensation percentage of WLAN active scan window if initiated
+ * during BT A2DP
*
- * Range: 0
+ * Range: 0 - 1000 (%)
*/
- CONF_SG_RATE_ADAPT_SNR,
+ CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
/*
- * Configure the min and max time BT gains the antenna
- * in WLAN PSM / BT master basic rate
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT A2DP BR
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 1000 (%)
*/
- CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR,
- CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR,
+ CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR,
/*
- * The time after it expires no new WLAN trigger frame is trasmitted
- * in WLAN PSM / BT master basic rate
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT A2DP EDR
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 1000 (%)
*/
- CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR,
+ CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR,
/*
- * Configure the min and max time BT gains the antenna
- * in WLAN PSM / BT slave basic rate
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT voice
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 1000 (%)
*/
- CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR,
- CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR,
+ CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
- /*
- * The time after it expires no new WLAN trigger frame is trasmitted
- * in WLAN PSM / BT slave basic rate
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR,
+ /* TODO: explain these values */
+ CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN,
+ CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN,
+ CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN,
/*
- * Configure the min and max time BT gains the antenna
- * in WLAN PSM / BT master EDR
+ * Defines whether the SG will force WLAN host to enter/exit PSM
*
- * Range: 0 - 255 (ms)
+ * Range: 1 - SG can force, 0 - host handles PSM
*/
- CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR,
- CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR,
+ CONF_SG_STA_FORCE_PS_IN_BT_SCO,
/*
- * The time after it expires no new WLAN trigger frame is trasmitted
- * in WLAN PSM / BT master EDR
+ * Defines antenna configuration (single/dual antenna)
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - single antenna, 1 - dual antenna
*/
- CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR,
+ CONF_SG_ANTENNA_CONFIGURATION,
/*
- * Configure the min and max time BT gains the antenna
- * in WLAN PSM / BT slave EDR
+ * The threshold (percent) of max consecutive beacon misses before
+ * increasing priority of beacon reception.
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 100 (%)
*/
- CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR,
- CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR,
+ CONF_SG_BEACON_MISS_PERCENT,
/*
- * The time after it expires no new WLAN trigger frame is trasmitted
- * in WLAN PSM / BT slave EDR
+ * Protection time of the DHCP procedure.
*
- * Range: 0 - 255 (ms)
+ * Range: 0 - 100000 (ms)
*/
- CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR,
+ CONF_SG_DHCP_TIME,
/*
* RX guard time before the beginning of a new BT voice frame during
@@ -273,166 +276,59 @@ enum {
*/
CONF_SG_ADAPTIVE_RXT_TXT,
- /*
- * The used WLAN legacy service period during active BT ACL link
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_PS_POLL_TIMEOUT,
+ /* TODO: explain this value */
+ CONF_SG_GENERAL_USAGE_BIT_MAP,
/*
- * The used WLAN UPSD service period during active BT ACL link
+ * Number of consecutive BT voice frames not interrupted by WLAN
*
- * Range: 0 - 255 (ms)
- */
- CONF_SG_UPSD_TIMEOUT,
-
- /*
- * Configure the min and max time BT gains the antenna
- * in WLAN Active / BT master EDR
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR,
- CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR,
-
- /*
- * The maximum time WLAN can gain the antenna for
- * in WLAN Active / BT master EDR
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR,
-
- /*
- * Configure the min and max time BT gains the antenna
- * in WLAN Active / BT slave EDR
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR,
- CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR,
-
- /*
- * The maximum time WLAN can gain the antenna for
- * in WLAN Active / BT slave EDR
- *
- * Range: 0 - 255 (ms)
+ * Range: 0 - 100
*/
- CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR,
+ CONF_SG_HV3_MAX_SERVED,
/*
- * Configure the min and max time BT gains the antenna
- * in WLAN Active / BT basic rate
+ * The used WLAN legacy service period during active BT ACL link
*
* Range: 0 - 255 (ms)
*/
- CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR,
- CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR,
+ CONF_SG_PS_POLL_TIMEOUT,
/*
- * The maximum time WLAN can gain the antenna for
- * in WLAN Active / BT basic rate
+ * The used WLAN UPSD service period during active BT ACL link
*
* Range: 0 - 255 (ms)
*/
- CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR,
-
- /*
- * Compensation percentage of WLAN passive scan window if initiated
- * during BT voice
- *
- * Range: 0 - 1000 (%)
- */
- CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
-
- /*
- * Compensation percentage of WLAN passive scan window if initiated
- * during BT A2DP
- *
- * Range: 0 - 1000 (%)
- */
- CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP,
+ CONF_SG_UPSD_TIMEOUT,
- /*
- * Fixed time ensured for BT traffic to gain the antenna during WLAN
- * passive scan.
- *
- * Range: 0 - 1000 ms
- */
- CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME,
+ CONF_SG_CONSECUTIVE_CTS_THRESHOLD,
+ CONF_SG_STA_RX_WINDOW_AFTER_DTIM,
+ CONF_SG_STA_CONNECTION_PROTECTION_TIME,
- /*
- * Fixed time ensured for WLAN traffic to gain the antenna during WLAN
- * passive scan.
- *
- * Range: 0 - 1000 ms
- */
- CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME,
+ /* AP params */
+ CONF_AP_BEACON_MISS_TX,
+ CONF_AP_RX_WINDOW_AFTER_BEACON,
+ CONF_AP_BEACON_WINDOW_INTERVAL,
+ CONF_AP_CONNECTION_PROTECTION_TIME,
+ CONF_AP_BT_ACL_VAL_BT_SERVE_TIME,
+ CONF_AP_BT_ACL_VAL_WL_SERVE_TIME,
- /*
- * Number of consequent BT voice frames not interrupted by WLAN
- *
- * Range: 0 - 100
- */
- CONF_SG_HV3_MAX_SERVED,
-
- /*
- * Protection time of the DHCP procedure.
- *
- * Range: 0 - 100000 (ms)
- */
- CONF_SG_DHCP_TIME,
-
- /*
- * Compensation percentage of WLAN active scan window if initiated
- * during BT A2DP
- *
- * Range: 0 - 1000 (%)
- */
- CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
CONF_SG_TEMP_PARAM_1,
CONF_SG_TEMP_PARAM_2,
CONF_SG_TEMP_PARAM_3,
CONF_SG_TEMP_PARAM_4,
CONF_SG_TEMP_PARAM_5,
-
- /*
- * AP beacon miss
- *
- * Range: 0 - 255
- */
- CONF_SG_AP_BEACON_MISS_TX,
-
- /*
- * AP RX window length
- *
- * Range: 0 - 50
- */
- CONF_SG_RX_WINDOW_LENGTH,
-
- /*
- * AP connection protection time
- *
- * Range: 0 - 5000
- */
- CONF_SG_AP_CONNECTION_PROTECTION_TIME,
-
CONF_SG_TEMP_PARAM_6,
CONF_SG_TEMP_PARAM_7,
CONF_SG_TEMP_PARAM_8,
CONF_SG_TEMP_PARAM_9,
CONF_SG_TEMP_PARAM_10,
- CONF_SG_STA_PARAMS_MAX = CONF_SG_TEMP_PARAM_5 + 1,
- CONF_SG_AP_PARAMS_MAX = CONF_SG_TEMP_PARAM_10 + 1,
-
+ CONF_SG_PARAMS_MAX,
CONF_SG_PARAMS_ALL = 0xff
};
struct conf_sg_settings {
- u32 sta_params[CONF_SG_STA_PARAMS_MAX];
- u32 ap_params[CONF_SG_AP_PARAMS_MAX];
+ u32 params[CONF_SG_PARAMS_MAX];
u8 state;
};
@@ -520,13 +416,17 @@ struct conf_rx_settings {
u8 queue_type;
};
-#define CONF_TX_MAX_RATE_CLASSES 8
+#define CONF_TX_MAX_RATE_CLASSES 10
#define CONF_TX_RATE_MASK_UNSPECIFIED 0
#define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \
CONF_HW_BIT_RATE_2MBPS)
#define CONF_TX_RATE_RETRY_LIMIT 10
+/* basic rates for p2p operations (probe req/resp, etc.) */
+#define CONF_TX_RATE_MASK_BASIC_P2P (CONF_HW_BIT_RATE_6MBPS | \
+ CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS)
+
/*
* Rates supported for data packets when operating as AP. Note the absence
* of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop
@@ -545,6 +445,11 @@ struct conf_rx_settings {
CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \
CONF_HW_BIT_RATE_54MBPS)
+#define CONF_TX_MCS_RATES (CONF_HW_BIT_RATE_MCS_0 | \
+ CONF_HW_BIT_RATE_MCS_1 | CONF_HW_BIT_RATE_MCS_2 | \
+ CONF_HW_BIT_RATE_MCS_3 | CONF_HW_BIT_RATE_MCS_4 | \
+ CONF_HW_BIT_RATE_MCS_5 | CONF_HW_BIT_RATE_MCS_6 | \
+ CONF_HW_BIT_RATE_MCS_7)
/*
* Default rates for management traffic when operating in AP mode. This
@@ -553,12 +458,10 @@ struct conf_rx_settings {
#define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS)
-/*
- * Default rates for working as IBSS. use 11b rates
- */
+/* default rates for working as IBSS (11b and OFDM) */
#define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \
- CONF_HW_BIT_RATE_11MBPS);
+ CONF_HW_BIT_RATE_11MBPS | CONF_TX_OFDM_RATES);
struct conf_tx_rate_class {
@@ -661,6 +564,9 @@ struct conf_tx_ac_category {
#define CONF_TX_MAX_TID_COUNT 8
+/* Allow TX BA on all TIDs but 6,7. These are currently reserved in the FW */
+#define CONF_TX_BA_ENABLED_TID_BITMAP 0x3F
+
enum {
CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/
CONF_CHANNEL_TYPE_EDCF = 1, /* EDCA*/
@@ -913,7 +819,7 @@ struct conf_conn_settings {
struct conf_bcn_filt_rule bcn_filt_ie[CONF_MAX_BCN_FILT_IE_COUNT];
/*
- * The number of consequtive beacons to lose, before the firmware
+ * The number of consecutive beacons to lose, before the firmware
* becomes out of synch.
*
* Range: u32
@@ -951,7 +857,7 @@ struct conf_conn_settings {
u8 rx_broadcast_in_ps;
/*
- * Consequtive PS Poll failures before sending event to driver
+ * Consecutive PS Poll failures before sending event to driver
*
* Range: u8
*/
@@ -1012,14 +918,6 @@ struct conf_conn_settings {
u8 psm_entry_nullfunc_retries;
/*
- * Specifies the time to linger in active mode after successfully
- * transmitting the PSM entry null-func frame.
- *
- * Range 0 - 255 TU's
- */
- u8 psm_entry_hangover_period;
-
- /*
*
* Specifies the interval of the connection keep-alive null-func
* frame in ms.
@@ -1199,8 +1097,12 @@ struct conf_rf_settings {
};
struct conf_ht_setting {
- u16 tx_ba_win_size;
+ u8 rx_ba_win_size;
+ u8 tx_ba_win_size;
u16 inactivity_timeout;
+
+ /* bitmap of enabled TIDs for TX BA sessions */
+ u8 tx_ba_tid_bitmap;
};
struct conf_memory_settings {
@@ -1309,6 +1211,39 @@ struct conf_fwlog {
u8 threshold;
};
+#define ACX_RATE_MGMT_NUM_OF_RATES 13
+struct conf_rate_policy_settings {
+ u16 rate_retry_score;
+ u16 per_add;
+ u16 per_th1;
+ u16 per_th2;
+ u16 max_per;
+ u8 inverse_curiosity_factor;
+ u8 tx_fail_low_th;
+ u8 tx_fail_high_th;
+ u8 per_alpha_shift;
+ u8 per_add_shift;
+ u8 per_beta1_shift;
+ u8 per_beta2_shift;
+ u8 rate_check_up;
+ u8 rate_check_down;
+ u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES];
+};
+
+struct conf_hangover_settings {
+ u32 recover_time;
+ u8 hangover_period;
+ u8 dynamic_mode;
+ u8 early_termination_mode;
+ u8 max_period;
+ u8 min_period;
+ u8 increase_delta;
+ u8 decrease_delta;
+ u8 quiet_time;
+ u8 increase_time;
+ u8 window_size;
+};
+
struct conf_drv_settings {
struct conf_sg_settings sg;
struct conf_rx_settings rx;
@@ -1326,6 +1261,8 @@ struct conf_drv_settings {
struct conf_fm_coex fm_coex;
struct conf_rx_streaming_settings rx_streaming;
struct conf_fwlog fwlog;
+ struct conf_rate_policy_settings rate;
+ struct conf_hangover_settings hangover;
u8 hci_io_ds;
};
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index 37934b5601cd..3999fd528302 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -265,18 +265,10 @@ static ssize_t gpio_power_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
- char buf[10];
- size_t len;
unsigned long value;
int ret;
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len)) {
- return -EFAULT;
- }
- buf[len] = '\0';
-
- ret = kstrtoul(buf, 0, &value);
+ ret = kstrtoul_from_user(user_buf, count, 10, &value);
if (ret < 0) {
wl1271_warning("illegal value in gpio_power");
return -EINVAL;
@@ -339,10 +331,11 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
#define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x")
DRIVER_STATE_PRINT_INT(tx_blocks_available);
- DRIVER_STATE_PRINT_INT(tx_allocated_blocks[0]);
- DRIVER_STATE_PRINT_INT(tx_allocated_blocks[1]);
- DRIVER_STATE_PRINT_INT(tx_allocated_blocks[2]);
- DRIVER_STATE_PRINT_INT(tx_allocated_blocks[3]);
+ DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]);
DRIVER_STATE_PRINT_INT(tx_frames_cnt);
DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
@@ -352,10 +345,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(tx_packets_count);
DRIVER_STATE_PRINT_INT(tx_results_count);
DRIVER_STATE_PRINT_LHEX(flags);
- DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]);
- DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]);
- DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]);
- DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]);
+ DRIVER_STATE_PRINT_INT(tx_blocks_freed);
DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb);
DRIVER_STATE_PRINT_INT(rx_counter);
DRIVER_STATE_PRINT_INT(session_counter);
@@ -369,9 +359,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(beacon_int);
DRIVER_STATE_PRINT_INT(psm_entry_retry);
DRIVER_STATE_PRINT_INT(ps_poll_failures);
- DRIVER_STATE_PRINT_HEX(filters);
- DRIVER_STATE_PRINT_HEX(rx_config);
- DRIVER_STATE_PRINT_HEX(rx_filter);
DRIVER_STATE_PRINT_INT(power_level);
DRIVER_STATE_PRINT_INT(rssi_thold);
DRIVER_STATE_PRINT_INT(last_rssi_event);
@@ -432,17 +419,10 @@ static ssize_t dtim_interval_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
- char buf[10];
- size_t len;
unsigned long value;
int ret;
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
- buf[len] = '\0';
-
- ret = kstrtoul(buf, 0, &value);
+ ret = kstrtoul_from_user(user_buf, count, 10, &value);
if (ret < 0) {
wl1271_warning("illegal value for dtim_interval");
return -EINVAL;
@@ -497,17 +477,10 @@ static ssize_t beacon_interval_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
- char buf[10];
- size_t len;
unsigned long value;
int ret;
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
- buf[len] = '\0';
-
- ret = kstrtoul(buf, 0, &value);
+ ret = kstrtoul_from_user(user_buf, count, 10, &value);
if (ret < 0) {
wl1271_warning("illegal value for beacon_interval");
return -EINVAL;
@@ -547,17 +520,10 @@ static ssize_t rx_streaming_interval_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
- char buf[10];
- size_t len;
unsigned long value;
int ret;
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
- buf[len] = '\0';
-
- ret = kstrtoul(buf, 0, &value);
+ ret = kstrtoul_from_user(user_buf, count, 10, &value);
if (ret < 0) {
wl1271_warning("illegal value in rx_streaming_interval!");
return -EINVAL;
@@ -606,17 +572,10 @@ static ssize_t rx_streaming_always_write(struct file *file,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
- char buf[10];
- size_t len;
unsigned long value;
int ret;
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
- buf[len] = '\0';
-
- ret = kstrtoul(buf, 0, &value);
+ ret = kstrtoul_from_user(user_buf, count, 10, &value);
if (ret < 0) {
wl1271_warning("illegal value in rx_streaming_write!");
return -EINVAL;
@@ -660,6 +619,47 @@ static const struct file_operations rx_streaming_always_ops = {
.llseek = default_llseek,
};
+static ssize_t beacon_filtering_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ char buf[10];
+ size_t len;
+ unsigned long value;
+ int ret;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+ buf[len] = '\0';
+
+ ret = kstrtoul(buf, 0, &value);
+ if (ret < 0) {
+ wl1271_warning("illegal value for beacon_filtering!");
+ return -EINVAL;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_acx_beacon_filter_opt(wl, !!value);
+
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static const struct file_operations beacon_filtering_ops = {
+ .write = beacon_filtering_write,
+ .open = wl1271_open_file_generic,
+ .llseek = default_llseek,
+};
+
static int wl1271_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
@@ -772,6 +772,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD(driver_state, rootdir);
DEBUGFS_ADD(dtim_interval, rootdir);
DEBUGFS_ADD(beacon_interval, rootdir);
+ DEBUGFS_ADD(beacon_filtering, rootdir);
streaming = debugfs_create_dir("rx_streaming", rootdir);
if (!streaming || IS_ERR(streaming))
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 304aaa2ee011..674ad2a9e409 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -171,19 +171,26 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl,
wl->last_rssi_event = event;
}
-static void wl1271_stop_ba_event(struct wl1271 *wl, u8 ba_allowed)
+static void wl1271_stop_ba_event(struct wl1271 *wl)
{
- /* Convert the value to bool */
- wl->ba_allowed = !!ba_allowed;
-
- /*
- * Return in case:
- * there are not BA open or the event indication is to allowed BA
- */
- if ((!wl->ba_rx_bitmap) || (wl->ba_allowed))
- return;
+ if (wl->bss_type != BSS_TYPE_AP_BSS) {
+ if (!wl->ba_rx_bitmap)
+ return;
+ ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap,
+ wl->bssid);
+ } else {
+ int i;
+ struct wl1271_link *lnk;
+ for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) {
+ lnk = &wl->links[i];
+ if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap)
+ continue;
- ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid);
+ ieee80211_stop_rx_ba_session(wl->vif,
+ lnk->ba_bitmap,
+ lnk->addr);
+ }
+ }
}
static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
@@ -283,15 +290,32 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_event_rssi_trigger(wl, mbox);
}
- if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) {
+ if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) {
wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
- "ba_allowed = 0x%x", mbox->ba_allowed);
+ "ba_allowed = 0x%x", mbox->rx_ba_allowed);
- if (wl->vif)
- wl1271_stop_ba_event(wl, mbox->ba_allowed);
+ wl->ba_allowed = !!mbox->rx_ba_allowed;
+
+ if (wl->vif && !wl->ba_allowed)
+ wl1271_stop_ba_event(wl);
+ }
+
+ if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) {
+ wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
+ "status = 0x%x",
+ mbox->channel_switch_status);
+ /*
+ * That event uses for two cases:
+ * 1) channel switch complete with status=0
+ * 2) channel switch failed status=1
+ */
+ if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags) &&
+ (wl->vif))
+ ieee80211_chswitch_done(wl->vif,
+ mbox->channel_switch_status ? false : true);
}
- if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {
+ if ((vector & DUMMY_PACKET_EVENT_ID)) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
if (wl->vif)
wl1271_tx_dummy_packet(wl);
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index e524ad6fe4e3..49c1a0ede5b1 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -49,32 +49,27 @@ enum {
MEASUREMENT_START_EVENT_ID = BIT(8),
MEASUREMENT_COMPLETE_EVENT_ID = BIT(9),
SCAN_COMPLETE_EVENT_ID = BIT(10),
- SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(11),
+ WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11),
AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12),
PS_REPORT_EVENT_ID = BIT(13),
PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14),
DISCONNECT_EVENT_COMPLETE_ID = BIT(15),
- JOIN_EVENT_COMPLETE_ID = BIT(16),
+ /* BIT(16) is reserved */
CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
BSS_LOSE_EVENT_ID = BIT(18),
REGAINED_BSS_EVENT_ID = BIT(19),
MAX_TX_RETRY_EVENT_ID = BIT(20),
- /* STA: dummy paket for dynamic mem blocks */
- DUMMY_PACKET_EVENT_ID = BIT(21),
- /* AP: STA remove complete */
- STA_REMOVE_COMPLETE_EVENT_ID = BIT(21),
+ DUMMY_PACKET_EVENT_ID = BIT(21),
SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
- /* STA: SG prediction */
- SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
- /* AP: Inactive STA */
- INACTIVE_STA_EVENT_ID = BIT(23),
+ CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID = BIT(23),
SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
- DBG_EVENT_ID = BIT(26),
- HEALTH_CHECK_REPLY_EVENT_ID = BIT(27),
+ INACTIVE_STA_EVENT_ID = BIT(26),
+ PEER_REMOVE_COMPLETE_EVENT_ID = BIT(27),
PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28),
PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29),
BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30),
+ REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(31),
EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff,
};
@@ -83,15 +78,6 @@ enum {
EVENT_ENTER_POWER_SAVE_SUCCESS,
};
-struct event_debug_report {
- u8 debug_event_id;
- u8 num_params;
- __le16 pad;
- __le32 report_1;
- __le32 report_2;
- __le32 report_3;
-} __packed;
-
#define NUM_OF_RSSI_SNR_TRIGGERS 8
struct event_mailbox {
@@ -100,49 +86,45 @@ struct event_mailbox {
__le32 reserved_1;
__le32 reserved_2;
- u8 dbg_event_id;
- u8 num_relevant_params;
- __le16 reserved_3;
- __le32 event_report_p1;
- __le32 event_report_p2;
- __le32 event_report_p3;
-
u8 number_of_scan_results;
u8 scan_tag;
- u8 reserved_4[2];
- __le32 compl_scheduled_scan_status;
+ u8 completed_scan_status;
+ u8 reserved_3;
- __le16 scheduled_scan_attended_channels;
u8 soft_gemini_sense_info;
u8 soft_gemini_protective_info;
s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
u8 channel_switch_status;
u8 scheduled_scan_status;
u8 ps_status;
+ /* tuned channel (roc) */
+ u8 roc_channel;
- /* AP FW only */
- u8 hlid_removed;
+ __le16 hlid_removed_bitmap;
- /* a bitmap of hlids for stations that have been inactive too long */
+ /* bitmap of aged stations (by HLID) */
__le16 sta_aging_status;
- /* a bitmap of hlids for stations which didn't respond to TX */
+ /* bitmap of stations (by HLID) which exceeded max tx retries */
__le16 sta_tx_retry_exceeded;
- /*
- * Bitmap, Each bit set represents the Role ID for which this constraint
- * is set. Range: 0 - FF, FF means ANY role
- */
- u8 ba_role_id;
- /*
- * Bitmap, Each bit set represents the Link ID for which this constraint
- * is set. Not applicable if ba_role_id is set to ANY role (FF).
- * Range: 0 - FFFF, FFFF means ANY link in that role
- */
- u8 ba_link_id;
- u8 ba_allowed;
-
- u8 reserved_5[21];
+ /* discovery completed results */
+ u8 discovery_tag;
+ u8 number_of_preq_results;
+ u8 number_of_prsp_results;
+ u8 reserved_5;
+
+ /* rx ba constraint */
+ u8 role_id; /* 0xFF means any role. */
+ u8 rx_ba_allowed;
+ u8 reserved_6[2];
+
+ u8 ps_poll_delivery_failure_role_ids;
+ u8 stopped_role_ids;
+ u8 started_role_ids;
+ u8 change_auto_mode_timeout;
+
+ u8 reserved_7[12];
} __packed;
int wl1271_event_unmask(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index c3e9a2e4410e..04db64c94e9a 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -39,13 +39,13 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
/* send empty templates for fw memory reservation */
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
- WL1271_CMD_TEMPL_MAX_SIZE,
+ WL1271_CMD_TEMPL_DFLT_SIZE,
0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0,
+ NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0,
WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
@@ -70,15 +70,13 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
- sizeof
- (struct wl12xx_probe_resp_template),
+ WL1271_CMD_TEMPL_DFLT_SIZE,
0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
- sizeof
- (struct wl12xx_beacon_template),
+ WL1271_CMD_TEMPL_DFLT_SIZE,
0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
@@ -92,7 +90,7 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
- WL1271_CMD_TEMPL_MAX_SIZE, i,
+ WL1271_CMD_TEMPL_DFLT_SIZE, i,
WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
@@ -105,6 +103,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
{
struct wl12xx_disconn_template *tmpl;
int ret;
+ u32 rate;
tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
if (!tmpl) {
@@ -115,9 +114,9 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_DEAUTH);
+ rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
- tmpl, sizeof(*tmpl), 0,
- wl1271_tx_min_rate_get(wl));
+ tmpl, sizeof(*tmpl), 0, rate);
out:
kfree(tmpl);
@@ -128,6 +127,7 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
{
struct ieee80211_hdr_3addr *nullfunc;
int ret;
+ u32 rate;
nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
if (!nullfunc) {
@@ -144,9 +144,9 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN);
memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN);
+ rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
- sizeof(*nullfunc), 0,
- wl1271_tx_min_rate_get(wl));
+ sizeof(*nullfunc), 0, rate);
out:
kfree(nullfunc);
@@ -157,6 +157,7 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
{
struct ieee80211_qos_hdr *qosnull;
int ret;
+ u32 rate;
qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
if (!qosnull) {
@@ -173,9 +174,9 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN);
memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN);
+ rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
- sizeof(*qosnull), 0,
- wl1271_tx_min_rate_get(wl));
+ sizeof(*qosnull), 0, rate);
out:
kfree(qosnull);
@@ -191,15 +192,13 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl)
* reserve memory for later.
*/
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
- sizeof
- (struct wl12xx_probe_resp_template),
+ WL1271_CMD_TEMPL_MAX_SIZE,
0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
- sizeof
- (struct wl12xx_beacon_template),
+ WL1271_CMD_TEMPL_MAX_SIZE,
0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
@@ -227,7 +226,7 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl)
return 0;
}
-static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
+static int wl12xx_init_rx_config(struct wl1271 *wl)
{
int ret;
@@ -235,10 +234,6 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
if (ret < 0)
return ret;
- ret = wl1271_acx_rx_config(wl, config, filter);
- if (ret < 0)
- return ret;
-
return 0;
}
@@ -285,10 +280,7 @@ int wl1271_init_pta(struct wl1271 *wl)
{
int ret;
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- ret = wl1271_acx_ap_sg_cfg(wl);
- else
- ret = wl1271_acx_sta_sg_cfg(wl);
+ ret = wl12xx_acx_sg_cfg(wl);
if (ret < 0)
return ret;
@@ -392,7 +384,7 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;
- ret = wl1271_acx_sta_mem_cfg(wl);
+ ret = wl12xx_acx_mem_cfg(wl);
if (ret < 0)
return ret;
@@ -408,12 +400,6 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
{
int ret, i;
- ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
- if (ret < 0) {
- wl1271_warning("couldn't set default key");
- return ret;
- }
-
/* disable all keep-alive templates */
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
ret = wl1271_acx_keep_alive_config(wl, i,
@@ -451,7 +437,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;
- ret = wl1271_acx_ap_mem_cfg(wl);
+ ret = wl12xx_acx_mem_cfg(wl);
if (ret < 0)
return ret;
@@ -483,7 +469,7 @@ int wl1271_ap_init_templates(struct wl1271 *wl)
* when operating as AP we want to receive external beacons for
* configuring ERP protection.
*/
- ret = wl1271_acx_set_ap_beacon_filter(wl, false);
+ ret = wl1271_acx_beacon_filter_opt(wl, false);
if (ret < 0)
return ret;
@@ -515,7 +501,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
return ret;
/* use the min basic rate for AP broadcast/multicast */
- rc.enabled_rates = wl1271_tx_min_rate_get(wl);
+ rc.enabled_rates = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
rc.short_retry_limit = 10;
rc.long_retry_limit = 10;
rc.aflags = 0;
@@ -532,6 +518,9 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
else
supported_rates = CONF_TX_AP_ENABLED_RATES;
+ /* unconditionally enable HT rates */
+ supported_rates |= CONF_TX_MCS_RATES;
+
/* configure unicast TX rate classes */
for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
rc.enabled_rates = supported_rates;
@@ -546,41 +535,24 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
return 0;
}
-static void wl1271_check_ba_support(struct wl1271 *wl)
-{
- /* validate FW cose ver x.x.x.50-60.x */
- if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
- (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
- wl->ba_support = true;
- return;
- }
-
- wl->ba_support = false;
-}
-
static int wl1271_set_ba_policies(struct wl1271 *wl)
{
- u8 tid_index;
- int ret = 0;
-
/* Reset the BA RX indicators */
wl->ba_rx_bitmap = 0;
wl->ba_allowed = true;
+ wl->ba_rx_session_count = 0;
- /* validate that FW support BA */
- wl1271_check_ba_support(wl);
+ /* BA is supported in STA/AP modes */
+ if (wl->bss_type != BSS_TYPE_AP_BSS &&
+ wl->bss_type != BSS_TYPE_STA_BSS) {
+ wl->ba_support = false;
+ return 0;
+ }
- if (wl->ba_support)
- /* 802.11n initiator BA session setting */
- for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
- ++tid_index) {
- ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
- tid_index, true);
- if (ret < 0)
- break;
- }
+ wl->ba_support = true;
- return ret;
+ /* 802.11n initiator BA session setting */
+ return wl12xx_acx_set_ba_initiator_policy(wl);
}
int wl1271_chip_specific_init(struct wl1271 *wl)
@@ -650,11 +622,7 @@ int wl1271_hw_init(struct wl1271 *wl)
return ret;
/* RX config */
- ret = wl1271_init_rx_config(wl,
- RX_CFG_PROMISCUOUS | RX_CFG_TSF,
- RX_FILTER_OPTION_DEF);
- /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
- RX_FILTER_OPTION_FILTER_ALL); */
+ ret = wl12xx_init_rx_config(wl);
if (ret < 0)
goto out_free_memmap;
@@ -733,11 +701,20 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;
+ ret = wl12xx_acx_set_rate_mgmt_params(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
/* Configure initiator BA sessions policies */
ret = wl1271_set_ba_policies(wl);
if (ret < 0)
goto out_free_memmap;
+ /* configure hangover */
+ ret = wl12xx_acx_config_hangover(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
return 0;
out_free_memmap:
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index a2fe4f506ada..e839341dfafe 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -186,6 +186,5 @@ int wl1271_free_hw(struct wl1271 *wl);
irqreturn_t wl1271_irq(int irq, void *data);
bool wl1271_set_block_size(struct wl1271 *wl);
int wl1271_tx_dummy_packet(struct wl1271 *wl);
-void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters);
#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index b70ae40ad660..884f82b63219 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -52,110 +52,67 @@
static struct conf_drv_settings default_conf = {
.sg = {
- .sta_params = {
- [CONF_SG_BT_PER_THRESHOLD] = 7500,
- [CONF_SG_HV3_MAX_OVERRIDE] = 0,
- [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
- [CONF_SG_BT_LOAD_RATIO] = 200,
- [CONF_SG_AUTO_PS_MODE] = 1,
- [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
- [CONF_SG_ANTENNA_CONFIGURATION] = 0,
- [CONF_SG_BEACON_MISS_PERCENT] = 60,
- [CONF_SG_RATE_ADAPT_THRESH] = 12,
- [CONF_SG_RATE_ADAPT_SNR] = 0,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 30,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 8,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 50,
- /* Note: with UPSD, this should be 4 */
- [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 8,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 20,
- /* Note: with UPDS, this should be 15 */
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8,
- /* Note: with UPDS, this should be 50 */
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 40,
- /* Note: with UPDS, this should be 10 */
- [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 20,
- [CONF_SG_RXT] = 1200,
- [CONF_SG_TXT] = 1000,
- [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
- [CONF_SG_PS_POLL_TIMEOUT] = 10,
- [CONF_SG_UPSD_TIMEOUT] = 10,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800,
- [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75,
- [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15,
- [CONF_SG_HV3_MAX_SERVED] = 6,
- [CONF_SG_DHCP_TIME] = 5000,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
- },
- .ap_params = {
- [CONF_SG_BT_PER_THRESHOLD] = 7500,
- [CONF_SG_HV3_MAX_OVERRIDE] = 0,
- [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
- [CONF_SG_BT_LOAD_RATIO] = 50,
- [CONF_SG_AUTO_PS_MODE] = 1,
- [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
- [CONF_SG_ANTENNA_CONFIGURATION] = 0,
- [CONF_SG_BEACON_MISS_PERCENT] = 60,
- [CONF_SG_RATE_ADAPT_THRESH] = 64,
- [CONF_SG_RATE_ADAPT_SNR] = 1,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 25,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 25,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 25,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 25,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7,
- [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 25,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8,
- [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 25,
- [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 25,
- [CONF_SG_RXT] = 1200,
- [CONF_SG_TXT] = 1000,
- [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
- [CONF_SG_PS_POLL_TIMEOUT] = 10,
- [CONF_SG_UPSD_TIMEOUT] = 10,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20,
- [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50,
- [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800,
- [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75,
- [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15,
- [CONF_SG_HV3_MAX_SERVED] = 6,
- [CONF_SG_DHCP_TIME] = 5000,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
- [CONF_SG_TEMP_PARAM_1] = 0,
- [CONF_SG_TEMP_PARAM_2] = 0,
- [CONF_SG_TEMP_PARAM_3] = 0,
- [CONF_SG_TEMP_PARAM_4] = 0,
- [CONF_SG_TEMP_PARAM_5] = 0,
- [CONF_SG_AP_BEACON_MISS_TX] = 3,
- [CONF_SG_RX_WINDOW_LENGTH] = 6,
- [CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 50,
- [CONF_SG_TEMP_PARAM_6] = 1,
+ .params = {
+ [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
+ [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
+ [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
+ [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
+ [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
+ [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
+ [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
+ [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
+ [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
+ [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
+ [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
+ [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
+ [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
+ [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
+ [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
+ [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
+ [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
+ [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
+ [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
+ [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
+ [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
+ [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
+ [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
+ [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
+ [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
+ [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
+ /* active scan params */
+ [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
+ [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
+ [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
+ /* passive scan params */
+ [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800,
+ [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200,
+ [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
+ /* passive scan in dual antenna params */
+ [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
+ [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0,
+ [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0,
+ /* general params */
+ [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
+ [CONF_SG_ANTENNA_CONFIGURATION] = 0,
+ [CONF_SG_BEACON_MISS_PERCENT] = 60,
+ [CONF_SG_DHCP_TIME] = 5000,
+ [CONF_SG_RXT] = 1200,
+ [CONF_SG_TXT] = 1000,
+ [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
+ [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
+ [CONF_SG_HV3_MAX_SERVED] = 6,
+ [CONF_SG_PS_POLL_TIMEOUT] = 10,
+ [CONF_SG_UPSD_TIMEOUT] = 10,
+ [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
+ [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
+ [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
+ /* AP params */
+ [CONF_AP_BEACON_MISS_TX] = 3,
+ [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
+ [CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
+ [CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
+ [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
+ [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
},
.state = CONF_SG_PROTECTIVE,
},
@@ -279,10 +236,9 @@ static struct conf_drv_settings default_conf = {
.ps_poll_recovery_period = 700,
.bet_enable = CONF_BET_MODE_ENABLE,
.bet_max_consecutive = 50,
- .psm_entry_retries = 5,
+ .psm_entry_retries = 8,
.psm_exit_retries = 16,
.psm_entry_nullfunc_retries = 3,
- .psm_entry_hangover_period = 1,
.keep_alive_interval = 55000,
.max_listen_interval = 20,
},
@@ -310,8 +266,8 @@ static struct conf_drv_settings default_conf = {
},
.sched_scan = {
/* sched_scan requires dwell times in TU instead of TU/1000 */
- .min_dwell_time_active = 8,
- .max_dwell_time_active = 30,
+ .min_dwell_time_active = 30,
+ .max_dwell_time_active = 60,
.dwell_time_passive = 100,
.dwell_time_dfs = 150,
.num_probe_reqs = 2,
@@ -329,8 +285,10 @@ static struct conf_drv_settings default_conf = {
},
},
.ht = {
+ .rx_ba_win_size = 8,
.tx_ba_win_size = 64,
.inactivity_timeout = 10000,
+ .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
},
.mem_wl127x = {
.num_stations = 1,
@@ -379,9 +337,44 @@ static struct conf_drv_settings default_conf = {
.threshold = 0,
},
.hci_io_ds = HCI_IO_DS_6MA,
+ .rate = {
+ .rate_retry_score = 32000,
+ .per_add = 8192,
+ .per_th1 = 2048,
+ .per_th2 = 4096,
+ .max_per = 8100,
+ .inverse_curiosity_factor = 5,
+ .tx_fail_low_th = 4,
+ .tx_fail_high_th = 10,
+ .per_alpha_shift = 4,
+ .per_add_shift = 13,
+ .per_beta1_shift = 10,
+ .per_beta2_shift = 8,
+ .rate_check_up = 2,
+ .rate_check_down = 12,
+ .rate_retry_policy = {
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ },
+ },
+ .hangover = {
+ .recover_time = 0,
+ .hangover_period = 20,
+ .dynamic_mode = 1,
+ .early_termination_mode = 1,
+ .max_period = 20,
+ .min_period = 1,
+ .increase_delta = 1,
+ .decrease_delta = 2,
+ .quiet_time = 4,
+ .increase_time = 1,
+ .window_size = 16,
+ },
};
static char *fwlog_param;
+static bool bug_on_recovery;
static void __wl1271_op_remove_interface(struct wl1271 *wl,
bool reset_tx_queues);
@@ -415,10 +408,12 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate)
if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags))
return 0;
- ret = wl1271_cmd_set_sta_state(wl);
+ ret = wl12xx_cmd_set_peer_state(wl, wl->sta_hlid);
if (ret < 0)
return ret;
+ wl12xx_croc(wl, wl->role_id);
+
wl1271_info("Association completed.");
return 0;
}
@@ -718,7 +713,7 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;
- ret = wl1271_acx_sta_mem_cfg(wl);
+ ret = wl12xx_acx_mem_cfg(wl);
if (ret < 0)
goto out_free_memmap;
@@ -773,33 +768,52 @@ static int wl1271_plt_init(struct wl1271 *wl)
return ret;
}
-static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks)
+static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
{
- bool fw_ps;
+ bool fw_ps, single_sta;
/* only regulate station links */
if (hlid < WL1271_AP_STA_HLID_START)
return;
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+ single_sta = (wl->active_sta_count == 1);
/*
* Wake up from high level PS if the STA is asleep with too little
- * blocks in FW or if the STA is awake.
+ * packets in FW or if the STA is awake.
*/
- if (!fw_ps || tx_blks < WL1271_PS_STA_MAX_BLOCKS)
+ if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS)
wl1271_ps_link_end(wl, hlid);
- /* Start high-level PS if the STA is asleep with enough blocks in FW */
- else if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+ /*
+ * Start high-level PS if the STA is asleep with enough blocks in FW.
+ * Make an exception if this is the only connected station. In this
+ * case FW-memory congestion is not a problem.
+ */
+ else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
wl1271_ps_link_start(wl, hlid, true);
}
-static void wl1271_irq_update_links_status(struct wl1271 *wl,
- struct wl1271_fw_ap_status *status)
+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
+{
+ int id;
+
+ /* global/broadcast "stations" are always active */
+ if (hlid < WL1271_AP_STA_HLID_START)
+ return true;
+
+ id = hlid - WL1271_AP_STA_HLID_START;
+ return test_bit(id, wl->ap_hlid_map);
+}
+
+static void wl12xx_irq_update_links_status(struct wl1271 *wl,
+ struct wl12xx_fw_status *status)
{
u32 cur_fw_ps_map;
- u8 hlid;
+ u8 hlid, cnt;
+
+ /* TODO: also use link_fast_bitmap here */
cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
if (wl->ap_fw_ps_map != cur_fw_ps_map) {
@@ -812,45 +826,30 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl,
}
for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) {
- u8 cnt = status->tx_lnk_free_blks[hlid] -
- wl->links[hlid].prev_freed_blks;
-
- wl->links[hlid].prev_freed_blks =
- status->tx_lnk_free_blks[hlid];
- wl->links[hlid].allocated_blks -= cnt;
-
- wl1271_irq_ps_regulate_link(wl, hlid,
- wl->links[hlid].allocated_blks);
- }
-}
+ if (!wl1271_is_active_sta(wl, hlid))
+ continue;
-static u32 wl1271_tx_allocated_blocks(struct wl1271 *wl)
-{
- int i;
- u32 total_alloc_blocks = 0;
+ cnt = status->tx_lnk_free_pkts[hlid] -
+ wl->links[hlid].prev_freed_pkts;
- for (i = 0; i < NUM_TX_QUEUES; i++)
- total_alloc_blocks += wl->tx_allocated_blocks[i];
+ wl->links[hlid].prev_freed_pkts =
+ status->tx_lnk_free_pkts[hlid];
+ wl->links[hlid].allocated_pkts -= cnt;
- return total_alloc_blocks;
+ wl12xx_irq_ps_regulate_link(wl, hlid,
+ wl->links[hlid].allocated_pkts);
+ }
}
-static void wl1271_fw_status(struct wl1271 *wl,
- struct wl1271_fw_full_status *full_status)
+static void wl12xx_fw_status(struct wl1271 *wl,
+ struct wl12xx_fw_status *status)
{
- struct wl1271_fw_common_status *status = &full_status->common;
struct timespec ts;
u32 old_tx_blk_count = wl->tx_blocks_available;
- u32 freed_blocks = 0, ac_freed_blocks;
+ int avail, freed_blocks;
int i;
- if (wl->bss_type == BSS_TYPE_AP_BSS) {
- wl1271_raw_read(wl, FW_STATUS_ADDR, status,
- sizeof(struct wl1271_fw_ap_status), false);
- } else {
- wl1271_raw_read(wl, FW_STATUS_ADDR, status,
- sizeof(struct wl1271_fw_sta_status), false);
- }
+ wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)",
@@ -859,42 +858,49 @@ static void wl1271_fw_status(struct wl1271 *wl,
status->drv_rx_counter,
status->tx_results_counter);
- /* update number of available TX blocks */
for (i = 0; i < NUM_TX_QUEUES; i++) {
- ac_freed_blocks = le32_to_cpu(status->tx_released_blks[i]) -
- wl->tx_blocks_freed[i];
- freed_blocks += ac_freed_blocks;
-
- wl->tx_allocated_blocks[i] -= ac_freed_blocks;
+ /* prevent wrap-around in freed-packets counter */
+ wl->tx_allocated_pkts[i] -=
+ (status->tx_released_pkts[i] -
+ wl->tx_pkts_freed[i]) & 0xff;
- wl->tx_blocks_freed[i] =
- le32_to_cpu(status->tx_released_blks[i]);
+ wl->tx_pkts_freed[i] = status->tx_released_pkts[i];
}
- if (wl->bss_type == BSS_TYPE_AP_BSS) {
- /* Update num of allocated TX blocks per link and ps status */
- wl1271_irq_update_links_status(wl, &full_status->ap);
- wl->tx_blocks_available += freed_blocks;
- } else {
- int avail = full_status->sta.tx_total -
- wl1271_tx_allocated_blocks(wl);
+ /* prevent wrap-around in total blocks counter */
+ if (likely(wl->tx_blocks_freed <=
+ le32_to_cpu(status->total_released_blks)))
+ freed_blocks = le32_to_cpu(status->total_released_blks) -
+ wl->tx_blocks_freed;
+ else
+ freed_blocks = 0x100000000LL - wl->tx_blocks_freed +
+ le32_to_cpu(status->total_released_blks);
- /*
- * The FW might change the total number of TX memblocks before
- * we get a notification about blocks being released. Thus, the
- * available blocks calculation might yield a temporary result
- * which is lower than the actual available blocks. Keeping in
- * mind that only blocks that were allocated can be moved from
- * TX to RX, tx_blocks_available should never decrease here.
- */
- wl->tx_blocks_available = max((int)wl->tx_blocks_available,
- avail);
- }
+ wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks);
+
+ wl->tx_allocated_blocks -= freed_blocks;
+
+ avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks;
+
+ /*
+ * The FW might change the total number of TX memblocks before
+ * we get a notification about blocks being released. Thus, the
+ * available blocks calculation might yield a temporary result
+ * which is lower than the actual available blocks. Keeping in
+ * mind that only blocks that were allocated can be moved from
+ * TX to RX, tx_blocks_available should never decrease here.
+ */
+ wl->tx_blocks_available = max((int)wl->tx_blocks_available,
+ avail);
/* if more blocks are available now, tx work can be scheduled */
if (wl->tx_blocks_available > old_tx_blk_count)
clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
+ /* for AP update num of allocated TX blocks per link and ps status */
+ if (wl->bss_type == BSS_TYPE_AP_BSS)
+ wl12xx_irq_update_links_status(wl, status);
+
/* update the host-chipset time offset */
getnstimeofday(&ts);
wl->time_offset = (timespec_to_ns(&ts) >> 10) -
@@ -967,8 +973,8 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
smp_mb__after_clear_bit();
- wl1271_fw_status(wl, wl->fw_status);
- intr = le32_to_cpu(wl->fw_status->common.intr);
+ wl12xx_fw_status(wl, wl->fw_status);
+ intr = le32_to_cpu(wl->fw_status->intr);
intr &= WL1271_INTR_MASK;
if (!intr) {
done = true;
@@ -987,7 +993,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
if (likely(intr & WL1271_ACX_INTR_DATA)) {
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
- wl1271_rx(wl, &wl->fw_status->common);
+ wl12xx_rx(wl, wl->fw_status);
/* Check if any tx blocks were freed */
spin_lock_irqsave(&wl->wl_lock, flags);
@@ -1004,7 +1010,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
}
/* check for tx results */
- if (wl->fw_status->common.tx_results_counter !=
+ if (wl->fw_status->tx_results_counter !=
(wl->tx_results_count & 0xff))
wl1271_tx_complete(wl);
@@ -1056,25 +1062,10 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
const char *fw_name;
int ret;
- switch (wl->bss_type) {
- case BSS_TYPE_AP_BSS:
- if (wl->chip.id == CHIP_ID_1283_PG20)
- fw_name = WL128X_AP_FW_NAME;
- else
- fw_name = WL127X_AP_FW_NAME;
- break;
- case BSS_TYPE_IBSS:
- case BSS_TYPE_STA_BSS:
- if (wl->chip.id == CHIP_ID_1283_PG20)
- fw_name = WL128X_FW_NAME;
- else
- fw_name = WL1271_FW_NAME;
- break;
- default:
- wl1271_error("no compatible firmware for bss_type %d",
- wl->bss_type);
- return -EINVAL;
- }
+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ fw_name = WL128X_FW_NAME;
+ else
+ fw_name = WL127X_FW_NAME;
wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name);
@@ -1103,7 +1094,6 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
}
memcpy(wl->fw, fw->data, wl->fw_len);
- wl->fw_bss_type = wl->bss_type;
ret = 0;
out:
@@ -1194,8 +1184,8 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
wl12xx_cmd_stop_fwlog(wl);
/* Read the first memory block address */
- wl1271_fw_status(wl, wl->fw_status);
- first_addr = __le32_to_cpu(wl->fw_status->sta.log_start_addr);
+ wl12xx_fw_status(wl, wl->fw_status);
+ first_addr = le32_to_cpu(wl->fw_status->log_start_addr);
if (!first_addr)
goto out;
@@ -1211,7 +1201,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
* of each memory block hold the hardware address of the next
* one. The last memory block points to the first one.
*/
- addr = __le32_to_cpup((__le32 *)block);
+ addr = le32_to_cpup((__le32 *)block);
if (!wl12xx_copy_fwlog(wl, block + sizeof(addr),
WL12XX_HW_BLOCK_SIZE - sizeof(addr)))
break;
@@ -1241,6 +1231,8 @@ static void wl1271_recovery_work(struct work_struct *work)
wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
+ BUG_ON(bug_on_recovery);
+
/*
* Advance security sequence number to overcome potential progress
* in the firmware during recovery. This doens't hurt if the network is
@@ -1250,9 +1242,6 @@ static void wl1271_recovery_work(struct work_struct *work)
test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING;
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
- ieee80211_connection_loss(wl->vif);
-
/* Prevent spurious TX during FW restart */
ieee80211_stop_queues(wl->hw);
@@ -1344,14 +1333,6 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
wl->chip.id);
- /*
- * 'end-of-transaction flag' and 'LPD mode flag'
- * should be set in wl127x AP mode only
- */
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- wl->quirks |= (WL12XX_QUIRK_END_OF_TRANSACTION |
- WL12XX_QUIRK_LPD_MODE);
-
ret = wl1271_setup(wl);
if (ret < 0)
goto out;
@@ -1374,8 +1355,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
goto out;
}
- /* Make sure the firmware type matches the BSS type */
- if (wl->fw == NULL || wl->fw_bss_type != wl->bss_type) {
+ if (wl->fw == NULL) {
ret = wl1271_fetch_firmware(wl);
if (ret < 0)
goto out;
@@ -1395,6 +1375,7 @@ out:
int wl1271_plt_start(struct wl1271 *wl)
{
int retries = WL1271_BOOT_RETRIES;
+ struct wiphy *wiphy = wl->hw->wiphy;
int ret;
mutex_lock(&wl->mutex);
@@ -1428,6 +1409,11 @@ int wl1271_plt_start(struct wl1271 *wl)
wl1271_notice("firmware booted in PLT mode (%s)",
wl->chip.fw_ver_str);
+ /* update hw/fw version info in wiphy struct */
+ wiphy->hw_version = wl->chip.id;
+ strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
+ sizeof(wiphy->fw_version));
+
goto out;
irq_disable:
@@ -1504,10 +1490,25 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
q = wl1271_tx_get_queue(mapping);
if (wl->bss_type == BSS_TYPE_AP_BSS)
- hlid = wl1271_tx_get_hlid(skb);
+ hlid = wl12xx_tx_get_hlid_ap(wl, skb);
spin_lock_irqsave(&wl->wl_lock, flags);
+ /* queue the packet */
+ if (wl->bss_type == BSS_TYPE_AP_BSS) {
+ if (!wl1271_is_active_sta(wl, hlid)) {
+ wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d",
+ hlid, q);
+ dev_kfree_skb(skb);
+ goto out;
+ }
+
+ wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
+ skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
+ } else {
+ skb_queue_tail(&wl->tx_queue[q], skb);
+ }
+
wl->tx_queue_count[q]++;
/*
@@ -1520,14 +1521,6 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
set_bit(q, &wl->stopped_queues_map);
}
- /* queue the packet */
- if (wl->bss_type == BSS_TYPE_AP_BSS) {
- wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
- skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
- } else {
- skb_queue_tail(&wl->tx_queue[q], skb);
- }
-
/*
* The chip specific setup must run before the first TX packet -
* before that, the tx_work will not be initialized!
@@ -1537,13 +1530,20 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
!test_bit(WL1271_FLAG_TX_PENDING, &wl->flags))
ieee80211_queue_work(wl->hw, &wl->tx_work);
+out:
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
int wl1271_tx_dummy_packet(struct wl1271 *wl)
{
unsigned long flags;
- int q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet));
+ int q;
+
+ /* no need to queue a new dummy packet if one is already pending */
+ if (test_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags))
+ return 0;
+
+ q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet));
spin_lock_irqsave(&wl->wl_lock, flags);
set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
@@ -1673,7 +1673,7 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl)
if (ret < 0)
goto out_unlock;
- ret = wl1271_acx_set_ap_beacon_filter(wl, true);
+ ret = wl1271_acx_beacon_filter_opt(wl, true);
wl1271_ps_elp_sleep(wl);
out_unlock:
@@ -1711,7 +1711,7 @@ static void wl1271_configure_resume(struct wl1271 *wl)
wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
wl->basic_rate, true);
} else if (is_ap) {
- wl1271_acx_set_ap_beacon_filter(wl, false);
+ wl1271_acx_beacon_filter_opt(wl, false);
}
wl1271_ps_elp_sleep(wl);
@@ -1803,9 +1803,6 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
*
* The MAC address is first known when the corresponding interface
* is added. That is where we will initialize the hardware.
- *
- * In addition, we currently have different firmwares for AP and managed
- * operation. We will know which to boot according to interface type.
*/
return 0;
@@ -1816,6 +1813,30 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
}
+static u8 wl12xx_get_role_type(struct wl1271 *wl)
+{
+ switch (wl->bss_type) {
+ case BSS_TYPE_AP_BSS:
+ if (wl->p2p)
+ return WL1271_ROLE_P2P_GO;
+ else
+ return WL1271_ROLE_AP;
+
+ case BSS_TYPE_STA_BSS:
+ if (wl->p2p)
+ return WL1271_ROLE_P2P_CL;
+ else
+ return WL1271_ROLE_STA;
+
+ case BSS_TYPE_IBSS:
+ return WL1271_ROLE_IBSS;
+
+ default:
+ wl1271_error("invalid bss_type: %d", wl->bss_type);
+ }
+ return WL12XX_INVALID_ROLE_TYPE;
+}
+
static int wl1271_op_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@@ -1823,10 +1844,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
struct wiphy *wiphy = hw->wiphy;
int retries = WL1271_BOOT_RETRIES;
int ret = 0;
+ u8 role_type;
bool booted = false;
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
- vif->type, vif->addr);
+ ieee80211_vif_type_p2p(vif), vif->addr);
mutex_lock(&wl->mutex);
if (wl->vif) {
@@ -1846,7 +1868,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto out;
}
- switch (vif->type) {
+ switch (ieee80211_vif_type_p2p(vif)) {
+ case NL80211_IFTYPE_P2P_CLIENT:
+ wl->p2p = 1;
+ /* fall-through */
case NL80211_IFTYPE_STATION:
wl->bss_type = BSS_TYPE_STA_BSS;
wl->set_bss_type = BSS_TYPE_STA_BSS;
@@ -1855,6 +1880,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
wl->bss_type = BSS_TYPE_IBSS;
wl->set_bss_type = BSS_TYPE_STA_BSS;
break;
+ case NL80211_IFTYPE_P2P_GO:
+ wl->p2p = 1;
+ /* fall-through */
case NL80211_IFTYPE_AP:
wl->bss_type = BSS_TYPE_AP_BSS;
break;
@@ -1863,6 +1891,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto out;
}
+ role_type = wl12xx_get_role_type(wl);
+ if (role_type == WL12XX_INVALID_ROLE_TYPE) {
+ ret = -EINVAL;
+ goto out;
+ }
memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
if (wl->state != WL1271_STATE_OFF) {
@@ -1882,6 +1915,25 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
if (ret < 0)
goto power_off;
+ if (wl->bss_type == BSS_TYPE_STA_BSS ||
+ wl->bss_type == BSS_TYPE_IBSS) {
+ /*
+ * The device role is a special role used for
+ * rx and tx frames prior to association (as
+ * the STA role can get packets only from
+ * its associated bssid)
+ */
+ ret = wl12xx_cmd_role_enable(wl,
+ WL1271_ROLE_DEVICE,
+ &wl->dev_role_id);
+ if (ret < 0)
+ goto irq_disable;
+ }
+
+ ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id);
+ if (ret < 0)
+ goto irq_disable;
+
ret = wl1271_hw_init(wl);
if (ret < 0)
goto irq_disable;
@@ -1946,7 +1998,7 @@ out:
static void __wl1271_op_remove_interface(struct wl1271 *wl,
bool reset_tx_queues)
{
- int i;
+ int ret, i;
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
@@ -1971,6 +2023,31 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
ieee80211_scan_completed(wl->hw, true);
}
+ if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) {
+ /* disable active roles */
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto deinit;
+
+ if (wl->bss_type == BSS_TYPE_STA_BSS) {
+ ret = wl12xx_cmd_role_disable(wl, &wl->dev_role_id);
+ if (ret < 0)
+ goto deinit;
+ }
+
+ ret = wl12xx_cmd_role_disable(wl, &wl->role_id);
+ if (ret < 0)
+ goto deinit;
+
+ wl1271_ps_elp_sleep(wl);
+ }
+deinit:
+ /* clear all hlids (except system_hlid) */
+ wl->sta_hlid = WL12XX_INVALID_LINK_ID;
+ wl->dev_hlid = WL12XX_INVALID_LINK_ID;
+ wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID;
+ wl->ap_global_hlid = WL12XX_INVALID_LINK_ID;
+
/*
* this must be before the cancel_work calls below, so that the work
* functions don't perform further work.
@@ -1997,28 +2074,41 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
wl1271_power_off(wl);
memset(wl->bssid, 0, ETH_ALEN);
- memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1);
+ memset(wl->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
wl->ssid_len = 0;
wl->bss_type = MAX_BSS_TYPE;
wl->set_bss_type = MAX_BSS_TYPE;
+ wl->p2p = 0;
wl->band = IEEE80211_BAND_2GHZ;
wl->rx_counter = 0;
wl->psm_entry_retry = 0;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
wl->tx_blocks_available = 0;
+ wl->tx_allocated_blocks = 0;
wl->tx_results_count = 0;
wl->tx_packets_count = 0;
wl->time_offset = 0;
wl->session_counter = 0;
wl->rate_set = CONF_TX_RATE_MASK_BASIC;
+ wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
+ wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
wl->vif = NULL;
- wl->filters = 0;
+ wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
wl1271_free_ap_keys(wl);
memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
wl->ap_fw_ps_map = 0;
wl->ap_ps_map = 0;
wl->sched_scanning = false;
+ wl->role_id = WL12XX_INVALID_ROLE_ID;
+ wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
+ memset(wl->roles_map, 0, sizeof(wl->roles_map));
+ memset(wl->links_map, 0, sizeof(wl->links_map));
+ memset(wl->roc_map, 0, sizeof(wl->roc_map));
+ wl->active_sta_count = 0;
+
+ /* The system link is always allocated */
+ __set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
/*
* this is performed after the cancel_work calls and the associated
@@ -2027,9 +2117,11 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
*/
wl->flags = 0;
+ wl->tx_blocks_freed = 0;
+
for (i = 0; i < NUM_TX_QUEUES; i++) {
- wl->tx_blocks_freed[i] = 0;
- wl->tx_allocated_blocks[i] = 0;
+ wl->tx_pkts_freed[i] = 0;
+ wl->tx_allocated_pkts[i] = 0;
}
wl1271_debugfs_reset(wl);
@@ -2061,64 +2153,10 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
cancel_work_sync(&wl->recovery_work);
}
-void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
-{
- wl1271_set_default_filters(wl);
-
- /* combine requested filters with current filter config */
- filters = wl->filters | filters;
-
- wl1271_debug(DEBUG_FILTERS, "RX filters set: ");
-
- if (filters & FIF_PROMISC_IN_BSS) {
- wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS");
- wl->rx_config &= ~CFG_UNI_FILTER_EN;
- wl->rx_config |= CFG_BSSID_FILTER_EN;
- }
- if (filters & FIF_BCN_PRBRESP_PROMISC) {
- wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC");
- wl->rx_config &= ~CFG_BSSID_FILTER_EN;
- wl->rx_config &= ~CFG_SSID_FILTER_EN;
- }
- if (filters & FIF_OTHER_BSS) {
- wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS");
- wl->rx_config &= ~CFG_BSSID_FILTER_EN;
- }
- if (filters & FIF_CONTROL) {
- wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL");
- wl->rx_filter |= CFG_RX_CTL_EN;
- }
- if (filters & FIF_FCSFAIL) {
- wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL");
- wl->rx_filter |= CFG_RX_FCS_ERROR;
- }
-}
-
-static int wl1271_dummy_join(struct wl1271 *wl)
-{
- int ret = 0;
- /* we need to use a dummy BSSID for now */
- static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
- 0xad, 0xbe, 0xef };
-
- memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
-
- /* pass through frames from all BSS */
- wl1271_configure_filters(wl, FIF_OTHER_BSS);
-
- ret = wl1271_cmd_join(wl, wl->set_bss_type);
- if (ret < 0)
- goto out;
-
- set_bit(WL1271_FLAG_JOINED, &wl->flags);
-
-out:
- return ret;
-}
-
static int wl1271_join(struct wl1271 *wl, bool set_assoc)
{
int ret;
+ bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
/*
* One of the side effects of the JOIN command is that is clears
@@ -2135,12 +2173,13 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc)
if (set_assoc)
set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
- ret = wl1271_cmd_join(wl, wl->set_bss_type);
+ if (is_ibss)
+ ret = wl12xx_cmd_role_start_ibss(wl);
+ else
+ ret = wl12xx_cmd_role_start_sta(wl);
if (ret < 0)
goto out;
- set_bit(WL1271_FLAG_JOINED, &wl->flags);
-
if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
goto out;
@@ -2175,31 +2214,41 @@ static int wl1271_unjoin(struct wl1271 *wl)
{
int ret;
+ if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) {
+ wl12xx_cmd_stop_channel_switch(wl);
+ ieee80211_chswitch_done(wl->vif, false);
+ }
+
/* to stop listening to a channel, we disconnect */
- ret = wl1271_cmd_disconnect(wl);
+ ret = wl12xx_cmd_role_stop_sta(wl);
if (ret < 0)
goto out;
- clear_bit(WL1271_FLAG_JOINED, &wl->flags);
memset(wl->bssid, 0, ETH_ALEN);
/* reset TX security counters on a clean disconnect */
wl->tx_security_last_seq_lsb = 0;
wl->tx_security_seq = 0;
- /* stop filtering packets based on bssid */
- wl1271_configure_filters(wl, FIF_OTHER_BSS);
-
out:
return ret;
}
static void wl1271_set_band_rate(struct wl1271 *wl)
{
- if (wl->band == IEEE80211_BAND_2GHZ)
- wl->basic_rate_set = wl->conf.tx.basic_rate;
- else
- wl->basic_rate_set = wl->conf.tx.basic_rate_5;
+ wl->basic_rate_set = wl->bitrate_masks[wl->band];
+ wl->rate_set = wl->basic_rate_set;
+}
+
+static bool wl12xx_is_roc(struct wl1271 *wl)
+{
+ u8 role_id;
+
+ role_id = find_first_bit(wl->roc_map, WL12XX_MAX_ROLES);
+ if (role_id >= WL12XX_MAX_ROLES)
+ return false;
+
+ return true;
}
static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
@@ -2207,12 +2256,17 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
int ret;
if (idle) {
- if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
- ret = wl1271_unjoin(wl);
+ /* no need to croc if we weren't busy (e.g. during boot) */
+ if (wl12xx_is_roc(wl)) {
+ ret = wl12xx_croc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_cmd_role_stop_dev(wl);
if (ret < 0)
goto out;
}
- wl->rate_set = wl1271_tx_min_rate_get(wl);
+ wl->rate_set = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0)
goto out;
@@ -2223,18 +2277,17 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
goto out;
set_bit(WL1271_FLAG_IDLE, &wl->flags);
} else {
- /* increment the session counter */
- wl->session_counter++;
- if (wl->session_counter >= SESSION_COUNTER_MAX)
- wl->session_counter = 0;
-
/* The current firmware only supports sched_scan in idle */
if (wl->sched_scanning) {
wl1271_scan_sched_scan_stop(wl);
ieee80211_sched_scan_stopped(wl->hw);
}
- ret = wl1271_dummy_join(wl);
+ ret = wl12xx_cmd_role_start_dev(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_roc(wl, wl->dev_role_id);
if (ret < 0)
goto out;
clear_bit(WL1271_FLAG_IDLE, &wl->flags);
@@ -2295,6 +2348,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL &&
((wl->band != conf->channel->band) ||
(wl->channel != channel))) {
+ /* send all pending packets */
+ wl1271_tx_work_locked(wl);
wl->band = conf->channel->band;
wl->channel = channel;
@@ -2308,17 +2363,41 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
wl1271_set_band_rate(wl);
- wl->basic_rate = wl1271_tx_min_rate_get(wl);
+ wl->basic_rate =
+ wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0)
wl1271_warning("rate policy for channel "
"failed %d", ret);
- if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
+ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+ if (wl12xx_is_roc(wl)) {
+ /* roaming */
+ ret = wl12xx_croc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out_sleep;
+ }
ret = wl1271_join(wl, false);
if (ret < 0)
wl1271_warning("cmd join on channel "
"failed %d", ret);
+ } else {
+ /*
+ * change the ROC channel. do it only if we are
+ * not idle. otherwise, CROC will be called
+ * anyway.
+ */
+ if (wl12xx_is_roc(wl) &&
+ !(conf->flags & IEEE80211_CONF_IDLE)) {
+ ret = wl12xx_croc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out_sleep;
+
+ ret = wl12xx_roc(wl, wl->dev_role_id);
+ if (ret < 0)
+ wl1271_warning("roc failed %d",
+ ret);
+ }
}
}
}
@@ -2458,18 +2537,11 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
goto out_sleep;
}
- /* determine, whether supported filter values have changed */
- if (changed == 0)
- goto out_sleep;
-
- /* configure filters */
- wl->filters = *total;
- wl1271_configure_filters(wl, 0);
-
- /* apply configured filters */
- ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
- if (ret < 0)
- goto out_sleep;
+ /*
+ * the fw doesn't provide an api to configure the filters. instead,
+ * the filters configuration is based on the active roles / ROC
+ * state.
+ */
out_sleep:
wl1271_ps_elp_sleep(wl);
@@ -2541,14 +2613,19 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl)
bool wep_key_added = false;
for (i = 0; i < MAX_NUM_KEYS; i++) {
+ u8 hlid;
if (wl->recorded_ap_keys[i] == NULL)
break;
key = wl->recorded_ap_keys[i];
+ hlid = key->hlid;
+ if (hlid == WL12XX_INVALID_LINK_ID)
+ hlid = wl->ap_bcast_hlid;
+
ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE,
key->id, key->key_type,
key->key_size, key->key,
- key->hlid, key->tx_seq_32,
+ hlid, key->tx_seq_32,
key->tx_seq_16);
if (ret < 0)
goto out;
@@ -2558,7 +2635,8 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl)
}
if (wep_key_added) {
- ret = wl1271_cmd_set_ap_default_wep_key(wl, wl->default_key);
+ ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key,
+ wl->ap_bcast_hlid);
if (ret < 0)
goto out;
}
@@ -2583,7 +2661,7 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
wl_sta = (struct wl1271_station *)sta->drv_priv;
hlid = wl_sta->hlid;
} else {
- hlid = WL1271_AP_BROADCAST_HLID;
+ hlid = wl->ap_bcast_hlid;
}
if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
@@ -2613,6 +2691,17 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
+ /*
+ * A STA set to GEM cipher requires 2 tx spare blocks.
+ * Return to default value when GEM cipher key is removed
+ */
+ if (key_type == KEY_GEM) {
+ if (action == KEY_ADD_OR_REPLACE)
+ wl->tx_spare_blocks = 2;
+ else if (action == KEY_REMOVE)
+ wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+ }
+
addr = sta ? sta->addr : bcast_addr;
if (is_zero_ether_addr(addr)) {
@@ -2627,6 +2716,11 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
if (action == KEY_REMOVE && !is_broadcast_ether_addr(addr))
return 0;
+ /* don't remove key if hlid was already deleted */
+ if (action == KEY_REMOVE &&
+ wl->sta_hlid == WL12XX_INVALID_LINK_ID)
+ return 0;
+
ret = wl1271_cmd_set_sta_key(wl, action,
id, key_type, key_size,
key, addr, tx_seq_32,
@@ -2636,8 +2730,9 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
/* the default WEP key needs to be configured at least once */
if (key_type == KEY_WEP) {
- ret = wl1271_cmd_set_sta_default_wep_key(wl,
- wl->default_key);
+ ret = wl12xx_cmd_set_default_wep_key(wl,
+ wl->default_key,
+ wl->sta_hlid);
if (ret < 0)
return ret;
}
@@ -2779,10 +2874,20 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- ret = wl1271_scan(hw->priv, ssid, len, req);
+ /* cancel ROC before scanning */
+ if (wl12xx_is_roc(wl)) {
+ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+ /* don't allow scanning right now */
+ ret = -EBUSY;
+ goto out_sleep;
+ }
+ wl12xx_croc(wl, wl->dev_role_id);
+ wl12xx_cmd_role_stop_dev(wl);
+ }
+ ret = wl1271_scan(hw->priv, ssid, len, req);
+out_sleep:
wl1271_ps_elp_sleep(wl);
-
out:
mutex_unlock(&wl->mutex);
@@ -2960,6 +3065,93 @@ static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
return 0;
}
+static void wl12xx_remove_ie(struct sk_buff *skb, u8 eid, int ieoffset)
+{
+ int len;
+ const u8 *next, *end = skb->data + skb->len;
+ u8 *ie = (u8 *)cfg80211_find_ie(eid, skb->data + ieoffset,
+ skb->len - ieoffset);
+ if (!ie)
+ return;
+ len = ie[1] + 2;
+ next = ie + len;
+ memmove(ie, next, end - next);
+ skb_trim(skb, skb->len - len);
+}
+
+static void wl12xx_remove_vendor_ie(struct sk_buff *skb,
+ unsigned int oui, u8 oui_type,
+ int ieoffset)
+{
+ int len;
+ const u8 *next, *end = skb->data + skb->len;
+ u8 *ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type,
+ skb->data + ieoffset,
+ skb->len - ieoffset);
+ if (!ie)
+ return;
+ len = ie[1] + 2;
+ next = ie + len;
+ memmove(ie, next, end - next);
+ skb_trim(skb, skb->len - len);
+}
+
+static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl,
+ u8 *probe_rsp_data,
+ size_t probe_rsp_len,
+ u32 rates)
+{
+ struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+ u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE];
+ int ssid_ie_offset, ie_offset, templ_len;
+ const u8 *ptr;
+
+ /* no need to change probe response if the SSID is set correctly */
+ if (wl->ssid_len > 0)
+ return wl1271_cmd_template_set(wl,
+ CMD_TEMPL_AP_PROBE_RESPONSE,
+ probe_rsp_data,
+ probe_rsp_len, 0,
+ rates);
+
+ if (probe_rsp_len + bss_conf->ssid_len > WL1271_CMD_TEMPL_MAX_SIZE) {
+ wl1271_error("probe_rsp template too big");
+ return -EINVAL;
+ }
+
+ /* start searching from IE offset */
+ ie_offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+
+ ptr = cfg80211_find_ie(WLAN_EID_SSID, probe_rsp_data + ie_offset,
+ probe_rsp_len - ie_offset);
+ if (!ptr) {
+ wl1271_error("No SSID in beacon!");
+ return -EINVAL;
+ }
+
+ ssid_ie_offset = ptr - probe_rsp_data;
+ ptr += (ptr[1] + 2);
+
+ memcpy(probe_rsp_templ, probe_rsp_data, ssid_ie_offset);
+
+ /* insert SSID from bss_conf */
+ probe_rsp_templ[ssid_ie_offset] = WLAN_EID_SSID;
+ probe_rsp_templ[ssid_ie_offset + 1] = bss_conf->ssid_len;
+ memcpy(probe_rsp_templ + ssid_ie_offset + 2,
+ bss_conf->ssid, bss_conf->ssid_len);
+ templ_len = ssid_ie_offset + 2 + bss_conf->ssid_len;
+
+ memcpy(probe_rsp_templ + ssid_ie_offset + 2 + bss_conf->ssid_len,
+ ptr, probe_rsp_len - (ptr - probe_rsp_data));
+ templ_len += probe_rsp_len - (ptr - probe_rsp_data);
+
+ return wl1271_cmd_template_set(wl,
+ CMD_TEMPL_AP_PROBE_RESPONSE,
+ probe_rsp_templ,
+ templ_len, 0,
+ rates);
+}
+
static int wl1271_bss_erp_info_changed(struct wl1271 *wl,
struct ieee80211_bss_conf *bss_conf,
u32 changed)
@@ -3016,6 +3208,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
if ((changed & BSS_CHANGED_BEACON)) {
struct ieee80211_hdr *hdr;
+ u32 min_rate;
int ieoffset = offsetof(struct ieee80211_mgmt,
u.beacon.variable);
struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif);
@@ -3031,28 +3224,46 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
dev_kfree_skb(beacon);
goto out;
}
+ min_rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON :
CMD_TEMPL_BEACON;
ret = wl1271_cmd_template_set(wl, tmpl_id,
beacon->data,
beacon->len, 0,
- wl1271_tx_min_rate_get(wl));
+ min_rate);
if (ret < 0) {
dev_kfree_skb(beacon);
goto out;
}
+ /* remove TIM ie from probe response */
+ wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset);
+
+ /*
+ * remove p2p ie from probe response.
+ * the fw reponds to probe requests that don't include
+ * the p2p ie. probe requests with p2p ie will be passed,
+ * and will be responded by the supplicant (the spec
+ * forbids including the p2p ie when responding to probe
+ * requests that didn't include it).
+ */
+ wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA,
+ WLAN_OUI_TYPE_WFA_P2P, ieoffset);
+
hdr = (struct ieee80211_hdr *) beacon->data;
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
-
- tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE :
- CMD_TEMPL_PROBE_RESPONSE;
- ret = wl1271_cmd_template_set(wl,
- tmpl_id,
- beacon->data,
- beacon->len, 0,
- wl1271_tx_min_rate_get(wl));
+ if (is_ap)
+ ret = wl1271_ap_set_probe_resp_tmpl(wl,
+ beacon->data,
+ beacon->len,
+ min_rate);
+ else
+ ret = wl1271_cmd_template_set(wl,
+ CMD_TEMPL_PROBE_RESPONSE,
+ beacon->data,
+ beacon->len, 0,
+ min_rate);
dev_kfree_skb(beacon);
if (ret < 0)
goto out;
@@ -3073,8 +3284,10 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
if ((changed & BSS_CHANGED_BASIC_RATES)) {
u32 rates = bss_conf->basic_rates;
- wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates);
- wl->basic_rate = wl1271_tx_min_rate_get(wl);
+ wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates,
+ wl->band);
+ wl->basic_rate = wl1271_tx_min_rate_get(wl,
+ wl->basic_rate_set);
ret = wl1271_init_ap_rates(wl);
if (ret < 0) {
@@ -3094,20 +3307,20 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
if ((changed & BSS_CHANGED_BEACON_ENABLED)) {
if (bss_conf->enable_beacon) {
if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
- ret = wl1271_cmd_start_bss(wl);
+ ret = wl12xx_cmd_role_start_ap(wl);
if (ret < 0)
goto out;
- set_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
- wl1271_debug(DEBUG_AP, "started AP");
-
ret = wl1271_ap_init_hwenc(wl);
if (ret < 0)
goto out;
+
+ set_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
+ wl1271_debug(DEBUG_AP, "started AP");
}
} else {
if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
- ret = wl1271_cmd_stop_bss(wl);
+ ret = wl12xx_cmd_role_stop_ap(wl);
if (ret < 0)
goto out;
@@ -3120,6 +3333,18 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
if (ret < 0)
goto out;
+
+ /* Handle HT information change */
+ if ((changed & BSS_CHANGED_HT) &&
+ (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+ ret = wl1271_acx_set_ht_information(wl,
+ bss_conf->ht_operation_mode);
+ if (ret < 0) {
+ wl1271_warning("Set ht information failed %d", ret);
+ goto out;
+ }
+ }
+
out:
return;
}
@@ -3132,6 +3357,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
{
bool do_join = false, set_assoc = false;
bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
+ bool ibss_joined = false;
u32 sta_rate_set = 0;
int ret;
struct ieee80211_sta *sta;
@@ -3145,14 +3371,28 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
goto out;
}
- if ((changed & BSS_CHANGED_BEACON_INT) && is_ibss)
+ if (changed & BSS_CHANGED_IBSS) {
+ if (bss_conf->ibss_joined) {
+ set_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags);
+ ibss_joined = true;
+ } else {
+ if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED,
+ &wl->flags)) {
+ wl1271_unjoin(wl);
+ wl12xx_cmd_role_start_dev(wl);
+ wl12xx_roc(wl, wl->dev_role_id);
+ }
+ }
+ }
+
+ if ((changed & BSS_CHANGED_BEACON_INT) && ibss_joined)
do_join = true;
/* Need to update the SSID (for filtering etc) */
- if ((changed & BSS_CHANGED_BEACON) && is_ibss)
+ if ((changed & BSS_CHANGED_BEACON) && ibss_joined)
do_join = true;
- if ((changed & BSS_CHANGED_BEACON_ENABLED) && is_ibss) {
+ if ((changed & BSS_CHANGED_BEACON_ENABLED) && ibss_joined) {
wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s",
bss_conf->enable_beacon ? "enabled" : "disabled");
@@ -3192,17 +3432,17 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
if (ret < 0)
goto out;
- /* filter out all packets not from this BSSID */
- wl1271_configure_filters(wl, 0);
-
/* Need to update the BSSID (for filtering etc) */
do_join = true;
}
}
- rcu_read_lock();
- sta = ieee80211_find_sta(vif, bss_conf->bssid);
- if (sta) {
+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
+ rcu_read_lock();
+ sta = ieee80211_find_sta(vif, bss_conf->bssid);
+ if (!sta)
+ goto sta_not_found;
+
/* save the supp_rates of the ap */
sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band];
if (sta->ht_cap.ht_supported)
@@ -3210,38 +3450,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
(sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
sta_ht_cap = sta->ht_cap;
sta_exists = true;
- }
- rcu_read_unlock();
- if (sta_exists) {
- /* handle new association with HT and HT information change */
- if ((changed & BSS_CHANGED_HT) &&
- (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
- ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
- true);
- if (ret < 0) {
- wl1271_warning("Set ht cap true failed %d",
- ret);
- goto out;
- }
- ret = wl1271_acx_set_ht_information(wl,
- bss_conf->ht_operation_mode);
- if (ret < 0) {
- wl1271_warning("Set ht information failed %d",
- ret);
- goto out;
- }
- }
- /* handle new association without HT and disassociation */
- else if (changed & BSS_CHANGED_ASSOC) {
- ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
- false);
- if (ret < 0) {
- wl1271_warning("Set ht cap false failed %d",
- ret);
- goto out;
- }
- }
+sta_not_found:
+ rcu_read_unlock();
}
if ((changed & BSS_CHANGED_ASSOC)) {
@@ -3258,12 +3469,15 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
* to use with control frames.
*/
rates = bss_conf->basic_rates;
- wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
- rates);
- wl->basic_rate = wl1271_tx_min_rate_get(wl);
+ wl->basic_rate_set =
+ wl1271_tx_enabled_rates_get(wl, rates,
+ wl->band);
+ wl->basic_rate =
+ wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
if (sta_rate_set)
wl->rate_set = wl1271_tx_enabled_rates_get(wl,
- sta_rate_set);
+ sta_rate_set,
+ wl->band);
ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0)
goto out;
@@ -3291,25 +3505,14 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
ret = wl1271_acx_conn_monit_params(wl, true);
if (ret < 0)
goto out;
-
- /* If we want to go in PSM but we're not there yet */
- if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
- !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
- enum wl1271_cmd_ps_mode mode;
-
- mode = STATION_POWER_SAVE_MODE;
- ret = wl1271_ps_set_mode(wl, mode,
- wl->basic_rate,
- true);
- if (ret < 0)
- goto out;
- }
} else {
/* use defaults when not associated */
bool was_assoc =
!!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED,
&wl->flags);
- clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags);
+ bool was_ifup =
+ !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT,
+ &wl->flags);
wl->aid = 0;
/* free probe-request template */
@@ -3321,7 +3524,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
/* revert back to minimum rates for the current band */
wl1271_set_band_rate(wl);
- wl->basic_rate = wl1271_tx_min_rate_get(wl);
+ wl->basic_rate =
+ wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0)
goto out;
@@ -3336,8 +3540,32 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
/* restore the bssid filter and go to dummy bssid */
if (was_assoc) {
+ u32 conf_flags = wl->hw->conf.flags;
+ /*
+ * we might have to disable roc, if there was
+ * no IF_OPER_UP notification.
+ */
+ if (!was_ifup) {
+ ret = wl12xx_croc(wl, wl->role_id);
+ if (ret < 0)
+ goto out;
+ }
+ /*
+ * (we also need to disable roc in case of
+ * roaming on the same channel. until we will
+ * have a better flow...)
+ */
+ if (test_bit(wl->dev_role_id, wl->roc_map)) {
+ ret = wl12xx_croc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out;
+ }
+
wl1271_unjoin(wl);
- wl1271_dummy_join(wl);
+ if (!(conf_flags & IEEE80211_CONF_IDLE)) {
+ wl12xx_cmd_role_start_dev(wl);
+ wl12xx_roc(wl, wl->dev_role_id);
+ }
}
}
}
@@ -3348,11 +3576,13 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
if (bss_conf->ibss_joined) {
u32 rates = bss_conf->basic_rates;
- wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
- rates);
- wl->basic_rate = wl1271_tx_min_rate_get(wl);
+ wl->basic_rate_set =
+ wl1271_tx_enabled_rates_get(wl, rates,
+ wl->band);
+ wl->basic_rate =
+ wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
- /* by default, use 11b rates */
+ /* by default, use 11b + OFDM rates */
wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;
ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0)
@@ -3398,7 +3628,81 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
wl1271_warning("cmd join failed %d", ret);
goto out;
}
- wl1271_check_operstate(wl, ieee80211_get_operstate(vif));
+
+ /* ROC until connected (after EAPOL exchange) */
+ if (!is_ibss) {
+ ret = wl12xx_roc(wl, wl->role_id);
+ if (ret < 0)
+ goto out;
+
+ wl1271_check_operstate(wl,
+ ieee80211_get_operstate(vif));
+ }
+ /*
+ * stop device role if started (we might already be in
+ * STA role). TODO: make it better.
+ */
+ if (wl->dev_role_id != WL12XX_INVALID_ROLE_ID) {
+ ret = wl12xx_croc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_cmd_role_stop_dev(wl);
+ if (ret < 0)
+ goto out;
+ }
+
+ /* If we want to go in PSM but we're not there yet */
+ if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
+ !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ enum wl1271_cmd_ps_mode mode;
+
+ mode = STATION_POWER_SAVE_MODE;
+ ret = wl1271_ps_set_mode(wl, mode,
+ wl->basic_rate,
+ true);
+ if (ret < 0)
+ goto out;
+ }
+ }
+
+ /* 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)) {
+ ret = wl1271_acx_set_ht_capabilities(wl,
+ &sta_ht_cap,
+ true,
+ wl->sta_hlid);
+ if (ret < 0) {
+ wl1271_warning("Set ht cap true failed %d",
+ ret);
+ goto out;
+ }
+ }
+ /* handle new association without HT and disassociation */
+ else if (changed & BSS_CHANGED_ASSOC) {
+ ret = wl1271_acx_set_ht_capabilities(wl,
+ &sta_ht_cap,
+ false,
+ wl->sta_hlid);
+ if (ret < 0) {
+ wl1271_warning("Set ht cap false failed %d",
+ ret);
+ goto out;
+ }
+ }
+ }
+
+ /* Handle HT information change. Done after join. */
+ if ((changed & BSS_CHANGED_HT) &&
+ (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+ ret = wl1271_acx_set_ht_information(wl,
+ bss_conf->ht_operation_mode);
+ if (ret < 0) {
+ wl1271_warning("Set ht information failed %d", ret);
+ goto out;
+ }
}
out:
@@ -3437,7 +3741,8 @@ out:
mutex_unlock(&wl->mutex);
}
-static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int wl1271_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct wl1271 *wl = hw->priv;
@@ -3508,7 +3813,8 @@ out:
return ret;
}
-static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw)
+static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct wl1271 *wl = hw->priv;
@@ -3568,31 +3874,31 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
}
wl_sta = (struct wl1271_station *)sta->drv_priv;
- __set_bit(id, wl->ap_hlid_map);
+ set_bit(id, wl->ap_hlid_map);
wl_sta->hlid = WL1271_AP_STA_HLID_START + id;
*hlid = wl_sta->hlid;
memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
+ wl->active_sta_count++;
return 0;
}
-static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
+void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
{
int id = hlid - WL1271_AP_STA_HLID_START;
- if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
+ if (hlid < WL1271_AP_STA_HLID_START)
+ return;
+
+ if (!test_bit(id, wl->ap_hlid_map))
return;
- __clear_bit(id, wl->ap_hlid_map);
+ clear_bit(id, wl->ap_hlid_map);
memset(wl->links[hlid].addr, 0, ETH_ALEN);
+ wl->links[hlid].ba_bitmap = 0;
wl1271_tx_reset_link_queues(wl, hlid);
__clear_bit(hlid, &wl->ap_ps_map);
__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
-}
-
-bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
-{
- int id = hlid - WL1271_AP_STA_HLID_START;
- return test_bit(id, wl->ap_hlid_map);
+ wl->active_sta_count--;
}
static int wl1271_op_sta_add(struct ieee80211_hw *hw,
@@ -3621,7 +3927,15 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
if (ret < 0)
goto out_free_sta;
- ret = wl1271_cmd_add_sta(wl, sta, hlid);
+ ret = wl12xx_cmd_add_peer(wl, sta, hlid);
+ if (ret < 0)
+ goto out_sleep;
+
+ ret = wl12xx_cmd_set_peer_state(wl, hlid);
+ if (ret < 0)
+ goto out_sleep;
+
+ ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, hlid);
if (ret < 0)
goto out_sleep;
@@ -3664,7 +3978,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid);
+ ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid);
if (ret < 0)
goto out_sleep;
@@ -3686,6 +4000,14 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
{
struct wl1271 *wl = hw->priv;
int ret;
+ u8 hlid, *ba_bitmap;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action,
+ tid);
+
+ /* sanity check - the fields in FW are only 8bits wide */
+ if (WARN_ON(tid > 0xFF))
+ return -ENOTSUPP;
mutex_lock(&wl->mutex);
@@ -3694,6 +4016,20 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
goto out;
}
+ if (wl->bss_type == BSS_TYPE_STA_BSS) {
+ hlid = wl->sta_hlid;
+ ba_bitmap = &wl->ba_rx_bitmap;
+ } else if (wl->bss_type == BSS_TYPE_AP_BSS) {
+ struct wl1271_station *wl_sta;
+
+ wl_sta = (struct wl1271_station *)sta->drv_priv;
+ hlid = wl_sta->hlid;
+ ba_bitmap = &wl->links[hlid].ba_bitmap;
+ } else {
+ ret = -EINVAL;
+ goto out;
+ }
+
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out;
@@ -3703,20 +4039,46 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
- if ((wl->ba_support) && (wl->ba_allowed)) {
- ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
- true);
- if (!ret)
- wl->ba_rx_bitmap |= BIT(tid);
- } else {
+ if (!wl->ba_support || !wl->ba_allowed) {
ret = -ENOTSUPP;
+ break;
+ }
+
+ if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) {
+ ret = -EBUSY;
+ wl1271_error("exceeded max RX BA sessions");
+ break;
+ }
+
+ if (*ba_bitmap & BIT(tid)) {
+ ret = -EINVAL;
+ wl1271_error("cannot enable RX BA session on active "
+ "tid: %d", tid);
+ break;
+ }
+
+ ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true,
+ hlid);
+ if (!ret) {
+ *ba_bitmap |= BIT(tid);
+ wl->ba_rx_session_count++;
}
break;
case IEEE80211_AMPDU_RX_STOP:
- ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false);
- if (!ret)
- wl->ba_rx_bitmap &= ~BIT(tid);
+ if (!(*ba_bitmap & BIT(tid))) {
+ ret = -EINVAL;
+ wl1271_error("no active RX BA session on tid: %d",
+ tid);
+ break;
+ }
+
+ ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false,
+ hlid);
+ if (!ret) {
+ *ba_bitmap &= ~BIT(tid);
+ wl->ba_rx_session_count--;
+ }
break;
/*
@@ -3742,6 +4104,60 @@ out:
return ret;
}
+static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct wl1271 *wl = hw->priv;
+ int i;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 set_bitrate_mask 0x%x 0x%x",
+ mask->control[NL80211_BAND_2GHZ].legacy,
+ mask->control[NL80211_BAND_5GHZ].legacy);
+
+ mutex_lock(&wl->mutex);
+
+ for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+ wl->bitrate_masks[i] =
+ wl1271_tx_enabled_rates_get(wl,
+ mask->control[i].legacy,
+ i);
+ mutex_unlock(&wl->mutex);
+
+ return 0;
+}
+
+static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_channel_switch *ch_switch)
+{
+ struct wl1271 *wl = hw->priv;
+ int ret;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state == WL1271_STATE_OFF)) {
+ mutex_unlock(&wl->mutex);
+ ieee80211_chswitch_done(wl->vif, false);
+ return;
+ }
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_cmd_channel_switch(wl, ch_switch);
+
+ if (!ret)
+ set_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags);
+
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
@@ -3858,7 +4274,6 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
/* 11n STA capabilities */
#define HW_RX_HIGHEST_RATE 72
-#ifdef CONFIG_WL12XX_HT
#define WL12XX_HT_CAP { \
.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \
(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \
@@ -3871,11 +4286,6 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
.tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
}, \
}
-#else
-#define WL12XX_HT_CAP { \
- .ht_supported = false, \
-}
-#endif
/* can't be const, mac80211 writes to this */
static struct ieee80211_supported_band wl1271_band_2ghz = {
@@ -4023,6 +4433,8 @@ static const struct ieee80211_ops wl1271_ops = {
.sta_remove = wl1271_op_sta_remove,
.ampdu_action = wl1271_op_ampdu_action,
.tx_frames_pending = wl1271_tx_frames_pending,
+ .set_bitrate_mask = wl12xx_set_bitrate_mask,
+ .channel_switch = wl12xx_op_channel_switch,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};
@@ -4126,7 +4538,7 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev,
return len;
}
-static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR,
+static DEVICE_ATTR(hw_pg_ver, S_IRUGO,
wl1271_sysfs_show_hw_pg_ver, NULL);
static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
@@ -4275,23 +4687,32 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_SUPPORTS_CQM_RSSI |
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_SPECTRUM_MGMT |
- IEEE80211_HW_AP_LINK_PS;
+ IEEE80211_HW_AP_LINK_PS |
+ IEEE80211_HW_AMPDU_AGGREGATION |
+ IEEE80211_HW_TX_AMPDU_SETUP_IN_HW;
wl->hw->wiphy->cipher_suites = cipher_suites;
wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
+ BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
wl->hw->wiphy->max_scan_ssids = 1;
- wl->hw->wiphy->max_sched_scan_ssids = 1;
+ wl->hw->wiphy->max_sched_scan_ssids = 16;
+ wl->hw->wiphy->max_match_sets = 16;
/*
* Maximum length of elements in scanning probe request templates
* should be the maximum length possible for a template, without
* the IEEE80211 header of the template
*/
- wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
+ wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE -
sizeof(struct ieee80211_header);
+ wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE -
+ sizeof(struct ieee80211_header);
+
+ wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+
/* make sure all our channels fit in the scanned_ch bitmask */
BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) +
ARRAY_SIZE(wl1271_channels_5ghz) >
@@ -4335,6 +4756,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
int i, j, ret;
unsigned int order;
+ BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS);
+
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
if (!hw) {
wl1271_error("could not alloc ieee80211_hw");
@@ -4388,8 +4811,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
wl->default_key = 0;
wl->rx_counter = 0;
- wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
- wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
wl->psm_entry_retry = 0;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
@@ -4402,7 +4823,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->hw_pg_ver = -1;
wl->bss_type = MAX_BSS_TYPE;
wl->set_bss_type = MAX_BSS_TYPE;
- wl->fw_bss_type = MAX_BSS_TYPE;
wl->last_tx_hlid = 0;
wl->ap_ps_map = 0;
wl->ap_fw_ps_map = 0;
@@ -4411,12 +4831,24 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->sched_scanning = false;
wl->tx_security_seq = 0;
wl->tx_security_last_seq_lsb = 0;
-
+ wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+ wl->role_id = WL12XX_INVALID_ROLE_ID;
+ wl->system_hlid = WL12XX_SYSTEM_HLID;
+ wl->sta_hlid = WL12XX_INVALID_LINK_ID;
+ wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
+ wl->dev_hlid = WL12XX_INVALID_LINK_ID;
+ wl->session_counter = 0;
+ wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID;
+ wl->ap_global_hlid = WL12XX_INVALID_LINK_ID;
+ wl->active_sta_count = 0;
setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
(unsigned long) wl);
wl->fwlog_size = 0;
init_waitqueue_head(&wl->fwlog_waitq);
+ /* The system link is always allocated */
+ __set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
+
memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
wl->tx_frames[i] = NULL;
@@ -4428,6 +4860,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
/* Apply default driver configuration. */
wl1271_conf_init(wl);
+ wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
+ wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
order = get_order(WL1271_AGGR_BUFFER_SIZE);
wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
@@ -4523,6 +4957,10 @@ int wl1271_free_hw(struct wl1271 *wl)
mutex_unlock(&wl->mutex);
device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr);
+
+ device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver);
+
+ device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state);
platform_device_unregister(wl->plat_dev);
free_page((unsigned long)wl->fwlog);
dev_kfree_skb(wl->dummy_packet);
@@ -4556,6 +4994,9 @@ module_param_named(fwlog, fwlog_param, charp, 0);
MODULE_PARM_DESC(keymap,
"FW logger options: continuous, ondemand, dbgpins or disable");
+module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 3548377ab9c2..c15ebf2efd40 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -199,15 +199,19 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
unsigned long flags;
int filtered[NUM_TX_QUEUES];
- /* filter all frames currently the low level queus for this hlid */
+ /* filter all frames currently in the low level queues for this hlid */
for (i = 0; i < NUM_TX_QUEUES; i++) {
filtered[i] = 0;
while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
+ filtered[i]++;
+
+ if (WARN_ON(wl12xx_is_dummy_packet(wl, skb)))
+ continue;
+
info = IEEE80211_SKB_CB(skb);
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
info->status.rates[0].idx = -1;
ieee80211_tx_status_ni(wl->hw, skb);
- filtered[i]++;
}
}
@@ -226,8 +230,8 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
if (test_bit(hlid, &wl->ap_ps_map))
return;
- wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d blks %d "
- "clean_queues %d", hlid, wl->links[hlid].allocated_blks,
+ wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d pkts %d "
+ "clean_queues %d", hlid, wl->links[hlid].allocated_pkts,
clean_queues);
rcu_read_lock();
diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h
index 440a4ee9cb42..3f570f397586 100644
--- a/drivers/net/wireless/wl12xx/reg.h
+++ b/drivers/net/wireless/wl12xx/reg.h
@@ -296,81 +296,6 @@
===============================================*/
#define REG_EVENT_MAILBOX_PTR (SCR_PAD1)
-
-/* Misc */
-
-#define REG_ENABLE_TX_RX (ENABLE)
-/*
- * Rx configuration (filter) information element
- * ---------------------------------------------
- */
-#define REG_RX_CONFIG (RX_CFG)
-#define REG_RX_FILTER (RX_FILTER_CFG)
-
-
-#define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002
-
-/* promiscuous - receives all valid frames */
-#define RX_CFG_PROMISCUOUS 0x0008
-
-/* receives frames from any BSSID */
-#define RX_CFG_BSSID 0x0020
-
-/* receives frames destined to any MAC address */
-#define RX_CFG_MAC 0x0010
-
-#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010
-#define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000
-#define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020
-#define RX_CFG_ENABLE_ANY_BSSID 0x0000
-
-/* discards all broadcast frames */
-#define RX_CFG_DISABLE_BCAST 0x0200
-
-#define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400
-#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800
-#define RX_CFG_COPY_RX_STATUS 0x2000
-#define RX_CFG_TSF 0x10000
-
-#define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
- RX_CFG_ENABLE_ONLY_MY_BSSID)
-
-#define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
- | RX_CFG_ENABLE_ANY_BSSID)
-
-#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
- RX_CFG_ENABLE_ANY_BSSID)
-
-#define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
- | RX_CFG_ENABLE_ONLY_MY_BSSID)
-
-#define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \
- | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \
- | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF)
-
-#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC)
-
-#define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \
- RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
-
-#define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \
- RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
-
-#define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
- | CFG_RX_CTL_EN | CFG_RX_BCN_EN\
- | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
-
-#define RX_FILTER_OPTION_FILTER_ALL 0
-
-#define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\
- | CFG_RX_RCTS_ACK | CFG_RX_BCN_EN)
-
-#define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
- | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\
- | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\
- | CFG_RX_PRSP_EN)
-
-
/*===============================================
EEPROM Read/Write Request 32bit RW
------------------------------------------
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 0450fb49dbb1..dee4cfe9ccc1 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -30,20 +30,28 @@
#include "rx.h"
#include "io.h"
-static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status,
+static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
u32 drv_rx_counter)
{
return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_MEM_BLOCK_MASK;
}
-static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status,
+static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status,
u32 drv_rx_counter)
{
return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
}
+static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status,
+ u32 drv_rx_counter)
+{
+ /* Convert the value to bool */
+ return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
+ RX_BUF_UNALIGNED_PAYLOAD);
+}
+
static void wl1271_rx_status(struct wl1271 *wl,
struct wl1271_rx_descriptor *desc,
struct ieee80211_rx_status *status,
@@ -58,11 +66,9 @@ static void wl1271_rx_status(struct wl1271 *wl,
status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band);
-#ifdef CONFIG_WL12XX_HT
/* 11n support */
if (desc->rate <= CONF_HW_RXTX_RATE_MCS0)
status->flag |= RX_FLAG_HT;
-#endif
status->signal = desc->rssi;
@@ -89,7 +95,8 @@ static void wl1271_rx_status(struct wl1271 *wl,
}
}
-static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
+static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
+ bool unaligned)
{
struct wl1271_rx_descriptor *desc;
struct sk_buff *skb;
@@ -97,6 +104,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
u8 *buf;
u8 beacon = 0;
u8 is_data = 0;
+ u8 reserved = unaligned ? NET_IP_ALIGN : 0;
+ u16 seq_num;
/*
* In PLT mode we seem to get frames and mac80211 warns about them,
@@ -131,17 +140,25 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
return -EINVAL;
}
- skb = __dev_alloc_skb(length, GFP_KERNEL);
+ /* skb length not included rx descriptor */
+ skb = __dev_alloc_skb(length + reserved - sizeof(*desc), GFP_KERNEL);
if (!skb) {
wl1271_error("Couldn't allocate RX frame");
return -ENOMEM;
}
- buf = skb_put(skb, length);
- memcpy(buf, data, length);
+ /* reserve the unaligned payload(if any) */
+ skb_reserve(skb, reserved);
- /* now we pull the descriptor out of the buffer */
- skb_pull(skb, sizeof(*desc));
+ buf = skb_put(skb, length - sizeof(*desc));
+
+ /*
+ * Copy packets from aggregation buffer to the skbs without rx
+ * descriptor and with packet payload aligned care. In case of unaligned
+ * packets copy the packets in offset of 2 bytes guarantee IP header
+ * payload aligned to 4 bytes.
+ */
+ memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_beacon(hdr->frame_control))
@@ -151,9 +168,11 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
- wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb,
+ seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+ wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb,
skb->len - desc->pad_len,
- beacon ? "beacon" : "");
+ beacon ? "beacon" : "",
+ seq_num);
skb_trim(skb, skb->len - desc->pad_len);
@@ -163,7 +182,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
return is_data;
}
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
+void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
{
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
u32 buf_size;
@@ -175,12 +194,13 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
u32 pkt_offset;
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
bool had_data = false;
+ bool unaligned = false;
while (drv_rx_counter != fw_rx_counter) {
buf_size = 0;
rx_counter = drv_rx_counter;
while (rx_counter != fw_rx_counter) {
- pkt_length = wl1271_rx_get_buf_size(status, rx_counter);
+ pkt_length = wl12xx_rx_get_buf_size(status, rx_counter);
if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
break;
buf_size += pkt_length;
@@ -199,7 +219,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
* For aggregated packets, only the first memory block
* should be retrieved. The FW takes care of the rest.
*/
- mem_block = wl1271_rx_get_mem_block(status,
+ mem_block = wl12xx_rx_get_mem_block(status,
drv_rx_counter);
wl->rx_mem_pool_addr.addr = (mem_block << 8) +
@@ -220,8 +240,12 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
/* Split data into separate packets */
pkt_offset = 0;
while (pkt_offset < buf_size) {
- pkt_length = wl1271_rx_get_buf_size(status,
+ pkt_length = wl12xx_rx_get_buf_size(status,
drv_rx_counter);
+
+ unaligned = wl12xx_rx_get_unaligned(status,
+ drv_rx_counter);
+
/*
* the handle data call can only fail in memory-outage
* conditions, in that case the received frame will just
@@ -229,7 +253,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
*/
if (wl1271_rx_handle_data(wl,
wl->aggr_buf + pkt_offset,
- pkt_length) == 1)
+ pkt_length, unaligned) == 1)
had_data = true;
wl->rx_counter++;
@@ -260,14 +284,3 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
jiffies + msecs_to_jiffies(timeout));
}
}
-
-void wl1271_set_default_filters(struct wl1271 *wl)
-{
- if (wl->bss_type == BSS_TYPE_AP_BSS) {
- wl->rx_config = WL1271_DEFAULT_AP_RX_CONFIG;
- wl->rx_filter = WL1271_DEFAULT_AP_RX_FILTER;
- } else {
- wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
- wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
- }
-}
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h
index c88e3fa1d603..86ba6b1d0cdc 100644
--- a/drivers/net/wireless/wl12xx/rx.h
+++ b/drivers/net/wireless/wl12xx/rx.h
@@ -86,16 +86,18 @@
* Bits 3-5 - process_id tag (AP mode FW)
* Bits 6-7 - reserved
*/
-#define WL1271_RX_DESC_STATUS_MASK 0x07
+#define WL1271_RX_DESC_STATUS_MASK 0x03
#define WL1271_RX_DESC_SUCCESS 0x00
#define WL1271_RX_DESC_DECRYPT_FAIL 0x01
#define WL1271_RX_DESC_MIC_FAIL 0x02
#define WL1271_RX_DESC_DRIVER_RX_Q_FAIL 0x03
-#define RX_MEM_BLOCK_MASK 0xFF
-#define RX_BUF_SIZE_MASK 0xFFF00
-#define RX_BUF_SIZE_SHIFT_DIV 6
+#define RX_MEM_BLOCK_MASK 0xFF
+#define RX_BUF_SIZE_MASK 0xFFF00
+#define RX_BUF_SIZE_SHIFT_DIV 6
+/* If set, the start of IP payload is not 4 bytes aligned */
+#define RX_BUF_UNALIGNED_PAYLOAD BIT(20)
enum {
WL12XX_RX_CLASS_UNKNOWN,
@@ -119,16 +121,12 @@ struct wl1271_rx_descriptor {
u8 snr;
__le32 timestamp;
u8 packet_class;
- union {
- u8 process_id; /* STA FW */
- u8 hlid; /* AP FW */
- } __packed;
+ u8 hlid;
u8 pad_len;
u8 reserved;
} __packed;
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status);
+void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
-void wl1271_set_default_filters(struct wl1271 *wl);
#endif
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index edfe01c321ca..128ccb79318c 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -28,11 +28,14 @@
#include "scan.h"
#include "acx.h"
#include "ps.h"
+#include "tx.h"
void wl1271_scan_complete_work(struct work_struct *work)
{
struct delayed_work *dwork;
struct wl1271 *wl;
+ int ret;
+ bool is_sta, is_ibss;
dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, scan_complete_work);
@@ -50,21 +53,35 @@ void wl1271_scan_complete_work(struct work_struct *work)
wl->scan.state = WL1271_SCAN_STATE_IDLE;
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
wl->scan.req = NULL;
- ieee80211_scan_completed(wl->hw, false);
- /* restore hardware connection monitoring template */
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
- if (wl1271_ps_elp_wakeup(wl) == 0) {
- wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
- wl1271_ps_elp_sleep(wl);
- }
+ /* restore hardware connection monitoring template */
+ wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
+ }
+
+ /* return to ROC if needed */
+ is_sta = (wl->bss_type == BSS_TYPE_STA_BSS);
+ is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
+ if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ||
+ (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) &&
+ !test_bit(wl->dev_role_id, wl->roc_map)) {
+ /* restore remain on channel */
+ wl12xx_cmd_role_start_dev(wl);
+ wl12xx_roc(wl, wl->dev_role_id);
}
+ wl1271_ps_elp_sleep(wl);
if (wl->scan.failed) {
wl1271_info("Scan completed due to error.");
wl12xx_queue_recovery_work(wl);
}
+ ieee80211_scan_completed(wl->hw, false);
+
out:
mutex_unlock(&wl->mutex);
@@ -83,14 +100,18 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
for (i = 0, j = 0;
i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS;
i++) {
-
flags = req->channels[i]->flags;
if (!test_bit(i, wl->scan.scanned_ch) &&
!(flags & IEEE80211_CHAN_DISABLED) &&
- ((!!(flags & IEEE80211_CHAN_PASSIVE_SCAN)) == passive) &&
- (req->channels[i]->band == band)) {
-
+ (req->channels[i]->band == band) &&
+ /*
+ * In passive scans, we scan all remaining
+ * channels, even if not marked as such.
+ * In active scans, we only scan channels not
+ * marked as passive.
+ */
+ (passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) {
wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
req->channels[i]->band,
req->channels[i]->center_freq);
@@ -142,6 +163,10 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
int ret;
u16 scan_options = 0;
+ /* skip active scans if we don't have SSIDs */
+ if (!passive && wl->scan.req->n_ssids == 0)
+ return WL1271_NOTHING_TO_SCAN;
+
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
if (!cmd || !trigger) {
@@ -149,13 +174,14 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
goto out;
}
- /* We always use high priority scans */
- scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
-
- /* No SSIDs means that we have a forced passive scan */
- if (passive || wl->scan.req->n_ssids == 0)
+ if (passive)
scan_options |= WL1271_SCAN_OPT_PASSIVE;
+ if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ cmd->params.role_id = wl->role_id;
cmd->params.scan_options = cpu_to_le16(scan_options);
cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
@@ -167,10 +193,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
}
cmd->params.tx_rate = cpu_to_le32(basic_rate);
- cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
- cmd->params.rx_filter_options =
- cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
-
cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
cmd->params.tx_rate = cpu_to_le32(basic_rate);
cmd->params.tid_trigger = 0;
@@ -186,6 +208,8 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len);
}
+ memcpy(cmd->addr, wl->mac_addr, ETH_ALEN);
+
ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len,
wl->scan.req->ie, wl->scan.req->ie_len,
band);
@@ -220,14 +244,17 @@ out:
void wl1271_scan_stm(struct wl1271 *wl)
{
int ret = 0;
+ enum ieee80211_band band;
+ u32 rate;
switch (wl->scan.state) {
case WL1271_SCAN_STATE_IDLE:
break;
case WL1271_SCAN_STATE_2GHZ_ACTIVE:
- ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, false,
- wl->conf.tx.basic_rate);
+ band = IEEE80211_BAND_2GHZ;
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ ret = wl1271_scan_send(wl, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE;
wl1271_scan_stm(wl);
@@ -236,8 +263,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
break;
case WL1271_SCAN_STATE_2GHZ_PASSIVE:
- ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true,
- wl->conf.tx.basic_rate);
+ band = IEEE80211_BAND_2GHZ;
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ ret = wl1271_scan_send(wl, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
if (wl->enable_11a)
wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
@@ -249,8 +277,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
break;
case WL1271_SCAN_STATE_5GHZ_ACTIVE:
- ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, false,
- wl->conf.tx.basic_rate_5);
+ band = IEEE80211_BAND_5GHZ;
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ ret = wl1271_scan_send(wl, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE;
wl1271_scan_stm(wl);
@@ -259,8 +288,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
break;
case WL1271_SCAN_STATE_5GHZ_PASSIVE:
- ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, true,
- wl->conf.tx.basic_rate_5);
+ band = IEEE80211_BAND_5GHZ;
+ rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
+ ret = wl1271_scan_send(wl, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_DONE;
wl1271_scan_stm(wl);
@@ -455,6 +485,105 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
cfg->passive[2] || cfg->active[2];
}
+/* Returns the scan type to be used or a negative value on error */
+static int
+wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
+ struct cfg80211_sched_scan_request *req)
+{
+ struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL;
+ struct cfg80211_match_set *sets = req->match_sets;
+ struct cfg80211_ssid *ssids = req->ssids;
+ int ret = 0, type, i, j, n_match_ssids = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list");
+
+ /* count the match sets that contain SSIDs */
+ for (i = 0; i < req->n_match_sets; i++)
+ if (sets[i].ssid.ssid_len > 0)
+ n_match_ssids++;
+
+ /* No filter, no ssids or only bcast ssid */
+ if (!n_match_ssids &&
+ (!req->n_ssids ||
+ (req->n_ssids == 1 && req->ssids[0].ssid_len == 0))) {
+ type = SCAN_SSID_FILTER_ANY;
+ goto out;
+ }
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (!n_match_ssids) {
+ /* No filter, with ssids */
+ type = SCAN_SSID_FILTER_DISABLED;
+
+ for (i = 0; i < req->n_ssids; i++) {
+ cmd->ssids[cmd->n_ssids].type = (ssids[i].ssid_len) ?
+ SCAN_SSID_TYPE_HIDDEN : SCAN_SSID_TYPE_PUBLIC;
+ cmd->ssids[cmd->n_ssids].len = ssids[i].ssid_len;
+ memcpy(cmd->ssids[cmd->n_ssids].ssid, ssids[i].ssid,
+ ssids[i].ssid_len);
+ cmd->n_ssids++;
+ }
+ } else {
+ type = SCAN_SSID_FILTER_LIST;
+
+ /* Add all SSIDs from the filters */
+ for (i = 0; i < req->n_match_sets; i++) {
+ /* ignore sets without SSIDs */
+ if (!sets[i].ssid.ssid_len)
+ continue;
+
+ cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
+ cmd->ssids[cmd->n_ssids].len = sets[i].ssid.ssid_len;
+ memcpy(cmd->ssids[cmd->n_ssids].ssid,
+ sets[i].ssid.ssid, sets[i].ssid.ssid_len);
+ cmd->n_ssids++;
+ }
+ if ((req->n_ssids > 1) ||
+ (req->n_ssids == 1 && req->ssids[0].ssid_len > 0)) {
+ /*
+ * Mark all the SSIDs passed in the SSID list as HIDDEN,
+ * so they're used in probe requests.
+ */
+ for (i = 0; i < req->n_ssids; i++) {
+ for (j = 0; j < cmd->n_ssids; j++)
+ if (!memcmp(req->ssids[i].ssid,
+ cmd->ssids[j].ssid,
+ req->ssids[i].ssid_len)) {
+ cmd->ssids[j].type =
+ SCAN_SSID_TYPE_HIDDEN;
+ break;
+ }
+ /* Fail if SSID isn't present in the filters */
+ if (j == req->n_ssids) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+ }
+ }
+ }
+
+ wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd));
+
+ ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_SSID_CFG, cmd,
+ sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("cmd sched scan ssid list failed");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+out:
+ if (ret < 0)
+ return ret;
+ return type;
+}
+
int wl1271_scan_sched_scan_config(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req,
struct ieee80211_sched_scan_ies *ies)
@@ -486,15 +615,14 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)
cfg->intervals[i] = cpu_to_le32(req->interval);
- if (!force_passive && req->ssids[0].ssid_len && req->ssids[0].ssid) {
- cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC;
- cfg->ssid_len = req->ssids[0].ssid_len;
- memcpy(cfg->ssid, req->ssids[0].ssid,
- req->ssids[0].ssid_len);
- } else {
- cfg->filter_type = SCAN_SSID_FILTER_ANY;
- cfg->ssid_len = 0;
- }
+ cfg->ssid_len = 0;
+ ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
+ if (ret < 0)
+ goto out;
+
+ cfg->filter_type = ret;
+
+ wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type);
if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {
wl1271_error("scan channel list is empty");
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h
index d882e4da71b7..92115156522f 100644
--- a/drivers/net/wireless/wl12xx/scan.h
+++ b/drivers/net/wireless/wl12xx/scan.h
@@ -46,7 +46,10 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl);
#define WL1271_SCAN_CURRENT_TX_PWR 0
#define WL1271_SCAN_OPT_ACTIVE 0
#define WL1271_SCAN_OPT_PASSIVE 1
+#define WL1271_SCAN_OPT_TRIGGERED_SCAN 2
#define WL1271_SCAN_OPT_PRIORITY_HIGH 4
+/* scan even if we fail to enter psm */
+#define WL1271_SCAN_OPT_FORCE 8
#define WL1271_SCAN_BAND_2_4_GHZ 0
#define WL1271_SCAN_BAND_5_GHZ 1
@@ -62,27 +65,27 @@ enum {
};
struct basic_scan_params {
- __le32 rx_config_options;
- __le32 rx_filter_options;
/* Scan option flags (WL1271_SCAN_OPT_*) */
__le16 scan_options;
+ u8 role_id;
/* Number of scan channels in the list (maximum 30) */
u8 n_ch;
/* This field indicates the number of probe requests to send
per channel for an active scan */
u8 n_probe_reqs;
- /* Rate bit field for sending the probes */
- __le32 tx_rate;
u8 tid_trigger;
u8 ssid_len;
- /* in order to align */
- u8 padding1[2];
- u8 ssid[IW_ESSID_MAX_SIZE];
+ u8 use_ssid_list;
+
+ /* Rate bit field for sending the probes */
+ __le32 tx_rate;
+
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
/* Band to scan */
u8 band;
- u8 use_ssid_list;
+
u8 scan_tag;
- u8 padding2;
+ u8 padding2[2];
} __packed;
struct basic_scan_channel_params {
@@ -105,6 +108,10 @@ struct wl1271_cmd_scan {
struct basic_scan_params params;
struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS];
+
+ /* src mac address */
+ u8 addr[ETH_ALEN];
+ u8 padding[2];
} __packed;
struct wl1271_cmd_trigger_scan_to {
@@ -167,7 +174,7 @@ struct wl1271_cmd_sched_scan_config {
u8 filter_type;
u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */
- u8 ssid[IW_ESSID_MAX_SIZE];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 n_probe_reqs; /* Number of probes requests per channel */
@@ -184,7 +191,7 @@ struct wl1271_cmd_sched_scan_config {
} __packed;
-#define SCHED_SCAN_MAX_SSIDS 8
+#define SCHED_SCAN_MAX_SSIDS 16
enum {
SCAN_SSID_TYPE_PUBLIC = 0,
@@ -194,7 +201,7 @@ enum {
struct wl1271_ssid {
u8 type;
u8 len;
- u8 ssid[IW_ESSID_MAX_SIZE];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
/* u8 padding[2]; */
} __packed;
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index fb1fd5af75ea..516a8980723c 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -412,7 +412,5 @@ module_exit(wl1271_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
-MODULE_FIRMWARE(WL1271_FW_NAME);
+MODULE_FIRMWARE(WL127X_FW_NAME);
MODULE_FIRMWARE(WL128X_FW_NAME);
-MODULE_FIRMWARE(WL127X_AP_FW_NAME);
-MODULE_FIRMWARE(WL128X_AP_FW_NAME);
diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c
index f28915392877..f25d5d9212e7 100644
--- a/drivers/net/wireless/wl12xx/sdio_test.c
+++ b/drivers/net/wireless/wl12xx/sdio_test.c
@@ -30,6 +30,7 @@
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
#include <linux/gpio.h>
#include <linux/wl12xx.h>
#include <linux/kthread.h>
@@ -142,14 +143,23 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
ret = pm_runtime_get_sync(&func->dev);
if (ret < 0)
goto out;
+
+ /* Runtime PM might be disabled, power up the card manually */
+ ret = mmc_power_restore_host(func->card->host);
+ if (ret < 0)
+ goto out;
+
sdio_claim_host(func);
sdio_enable_func(func);
- sdio_release_host(func);
} else {
- sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
+ /* Runtime PM might be disabled, power off the card manually */
+ ret = mmc_power_save_host(func->card->host);
+ if (ret < 0)
+ goto out;
+
/* Power down the card */
ret = pm_runtime_put_sync(&func->dev);
}
@@ -193,7 +203,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
ret = request_firmware(&fw, WL128X_FW_NAME,
wl1271_wl_to_dev(wl));
else
- ret = request_firmware(&fw, WL1271_FW_NAME,
+ ret = request_firmware(&fw, WL127X_FW_NAME,
wl1271_wl_to_dev(wl));
if (ret < 0) {
@@ -433,7 +443,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
sdio_set_drvdata(func, wl_test);
-
/* power up the device */
ret = wl1271_chip_wakeup(wl);
if (ret) {
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index e0b3736d7e19..0f9718677860 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -486,8 +486,6 @@ module_exit(wl1271_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
-MODULE_FIRMWARE(WL1271_FW_NAME);
+MODULE_FIRMWARE(WL127X_FW_NAME);
MODULE_FIRMWARE(WL128X_FW_NAME);
-MODULE_FIRMWARE(WL127X_AP_FW_NAME);
-MODULE_FIRMWARE(WL128X_AP_FW_NAME);
MODULE_ALIAS("spi:wl1271");
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 48fde96ce0d4..bad9e29d49b0 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -30,6 +30,7 @@
#include "reg.h"
#include "ps.h"
#include "tx.h"
+#include "event.h"
static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
{
@@ -37,9 +38,10 @@ static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
if (is_ap)
- ret = wl1271_cmd_set_ap_default_wep_key(wl, id);
+ ret = wl12xx_cmd_set_default_wep_key(wl, id,
+ wl->ap_bcast_hlid);
else
- ret = wl1271_cmd_set_sta_default_wep_key(wl, id);
+ ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid);
if (ret < 0)
return ret;
@@ -77,9 +79,9 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
+ int ret;
- hdr = (struct ieee80211_hdr *)(skb->data +
- sizeof(struct wl1271_tx_hw_descr));
+ hdr = (struct ieee80211_hdr *)skb->data;
/*
* stop bssid-based filtering before transmitting authentication
@@ -90,9 +92,19 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
if (!ieee80211_is_auth(hdr->frame_control))
return 0;
- wl1271_configure_filters(wl, FIF_OTHER_BSS);
+ if (wl->dev_hlid != WL12XX_INVALID_LINK_ID)
+ goto out;
- return wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
+ wl1271_debug(DEBUG_CMD, "starting device role for roaming");
+ ret = wl12xx_cmd_role_start_dev(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl12xx_roc(wl, wl->dev_role_id);
+ if (ret < 0)
+ goto out;
+out:
+ return 0;
}
static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
@@ -113,25 +125,36 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
{
- bool fw_ps;
- u8 tx_blks;
+ bool fw_ps, single_sta;
+ u8 tx_pkts;
/* only regulate station links */
if (hlid < WL1271_AP_STA_HLID_START)
return;
+ if (WARN_ON(!wl1271_is_active_sta(wl, hlid)))
+ return;
+
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
- tx_blks = wl->links[hlid].allocated_blks;
+ tx_pkts = wl->links[hlid].allocated_pkts;
+ single_sta = (wl->active_sta_count == 1);
/*
* if in FW PS and there is enough data in FW we can put the link
* into high-level PS and clean out its TX queues.
+ * Make an exception if this is the only connected station. In this
+ * case FW-memory congestion is not a problem.
*/
- if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+ if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
wl1271_ps_link_start(wl, hlid, true);
}
-u8 wl1271_tx_get_hlid(struct sk_buff *skb)
+bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
+{
+ return wl->dummy_packet == skb;
+}
+
+u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb)
{
struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb);
@@ -144,14 +167,38 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb)
} else {
struct ieee80211_hdr *hdr;
+ if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+ return wl->system_hlid;
+
hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_mgmt(hdr->frame_control))
- return WL1271_AP_GLOBAL_HLID;
+ return wl->ap_global_hlid;
else
- return WL1271_AP_BROADCAST_HLID;
+ return wl->ap_bcast_hlid;
}
}
+static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+ if (wl12xx_is_dummy_packet(wl, skb))
+ return wl->system_hlid;
+
+ if (wl->bss_type == BSS_TYPE_AP_BSS)
+ return wl12xx_tx_get_hlid_ap(wl, skb);
+
+ wl1271_tx_update_filters(wl, skb);
+
+ if ((test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+ test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) &&
+ !ieee80211_is_auth(hdr->frame_control) &&
+ !ieee80211_is_assoc_req(hdr->frame_control))
+ return wl->sta_hlid;
+ else
+ return wl->dev_hlid;
+}
+
static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl,
unsigned int packet_length)
{
@@ -169,12 +216,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
u32 len;
u32 total_blocks;
int id, ret = -EBUSY, ac;
- u32 spare_blocks;
-
- if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS))
- spare_blocks = 2;
- else
- spare_blocks = 1;
+ u32 spare_blocks = wl->tx_spare_blocks;
if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
return -EAGAIN;
@@ -188,6 +230,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
in the firmware */
len = wl12xx_calc_packet_alignment(wl, total_len);
+ /* in case of a dummy packet, use default amount of spare mem blocks */
+ if (unlikely(wl12xx_is_dummy_packet(wl, skb)))
+ spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+
total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
spare_blocks;
@@ -206,12 +252,14 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
desc->id = id;
wl->tx_blocks_available -= total_blocks;
+ wl->tx_allocated_blocks += total_blocks;
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
- wl->tx_allocated_blocks[ac] += total_blocks;
+ wl->tx_allocated_pkts[ac]++;
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- wl->links[hlid].allocated_blks += total_blocks;
+ if (wl->bss_type == BSS_TYPE_AP_BSS &&
+ hlid >= WL1271_AP_STA_HLID_START)
+ wl->links[hlid].allocated_pkts++;
ret = 0;
@@ -225,11 +273,6 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
return ret;
}
-static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
-{
- return wl->dummy_packet == skb;
-}
-
static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
u32 extra, struct ieee80211_tx_info *control,
u8 hlid)
@@ -280,9 +323,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
}
- if (wl->bss_type != BSS_TYPE_AP_BSS) {
- desc->aid = hlid;
+ desc->hlid = hlid;
+ if (wl->bss_type != BSS_TYPE_AP_BSS) {
/* if the packets are destined for AP (have a STA entry)
send them with AP rate policies, otherwise use default
basic rates */
@@ -291,18 +334,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
else
rate_idx = ACX_TX_BASIC_RATE;
} else {
- desc->hlid = hlid;
- switch (hlid) {
- case WL1271_AP_GLOBAL_HLID:
+ if (hlid == wl->ap_global_hlid)
rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
- break;
- case WL1271_AP_BROADCAST_HLID:
+ else if (hlid == wl->ap_bcast_hlid)
rate_idx = ACX_TX_AP_MODE_BCST_RATE;
- break;
- default:
+ else
rate_idx = ac;
- break;
- }
}
tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
@@ -376,10 +413,11 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
}
}
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- hlid = wl1271_tx_get_hlid(skb);
- else
- hlid = TX_HW_DEFAULT_AID;
+ hlid = wl1271_tx_get_hlid(wl, skb);
+ if (hlid == WL12XX_INVALID_LINK_ID) {
+ wl1271_error("invalid hlid. dropping skb 0x%p", skb);
+ return -EINVAL;
+ }
ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid);
if (ret < 0)
@@ -390,8 +428,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
if (wl->bss_type == BSS_TYPE_AP_BSS) {
wl1271_tx_ap_update_inconnection_sta(wl, skb);
wl1271_tx_regulate_link(wl, hlid);
- } else {
- wl1271_tx_update_filters(wl, skb);
}
/*
@@ -414,20 +450,20 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
return total_len;
}
-u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
+u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
+ enum ieee80211_band rate_band)
{
struct ieee80211_supported_band *band;
u32 enabled_rates = 0;
int bit;
- band = wl->hw->wiphy->bands[wl->band];
+ band = wl->hw->wiphy->bands[rate_band];
for (bit = 0; bit < band->n_bitrates; bit++) {
if (rate_set & 0x1)
enabled_rates |= band->bitrates[bit].hw_value;
rate_set >>= 1;
}
-#ifdef CONFIG_WL12XX_HT
/* MCS rates indication are on bits 16 - 23 */
rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates;
@@ -436,7 +472,6 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit);
rate_set >>= 1;
}
-#endif
return enabled_rates;
}
@@ -462,20 +497,24 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
struct sk_buff_head *queues)
{
- int i, q = -1;
- u32 min_blks = 0xffffffff;
+ int i, q = -1, ac;
+ u32 min_pkts = 0xffffffff;
/*
* Find a non-empty ac where:
* 1. There are packets to transmit
* 2. The FW has the least allocated blocks
+ *
+ * We prioritize the ACs according to VO>VI>BE>BK
*/
- for (i = 0; i < NUM_TX_QUEUES; i++)
- if (!skb_queue_empty(&queues[i]) &&
- (wl->tx_allocated_blocks[i] < min_blks)) {
- q = i;
- min_blks = wl->tx_allocated_blocks[q];
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
+ ac = wl1271_tx_get_queue(i);
+ if (!skb_queue_empty(&queues[ac]) &&
+ (wl->tx_allocated_pkts[ac] < min_pkts)) {
+ q = ac;
+ min_pkts = wl->tx_allocated_pkts[q];
}
+ }
if (q == -1)
return NULL;
@@ -579,7 +618,7 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
if (wl12xx_is_dummy_packet(wl, skb)) {
set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
} else if (wl->bss_type == BSS_TYPE_AP_BSS) {
- u8 hlid = wl1271_tx_get_hlid(skb);
+ u8 hlid = wl1271_tx_get_hlid(wl, skb);
skb_queue_head(&wl->links[hlid].tx_queue[q], skb);
/* make sure we dequeue the same packet next time */
@@ -826,10 +865,14 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
total[i] = 0;
while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb);
- info = IEEE80211_SKB_CB(skb);
- info->status.rates[0].idx = -1;
- info->status.rates[0].count = 0;
- ieee80211_tx_status_ni(wl->hw, skb);
+
+ if (!wl12xx_is_dummy_packet(wl, skb)) {
+ info = IEEE80211_SKB_CB(skb);
+ info->status.rates[0].idx = -1;
+ info->status.rates[0].count = 0;
+ ieee80211_tx_status_ni(wl->hw, skb);
+ }
+
total[i]++;
}
}
@@ -852,9 +895,10 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
/* TX failure */
if (wl->bss_type == BSS_TYPE_AP_BSS) {
for (i = 0; i < AP_MAX_LINKS; i++) {
+ wl1271_free_sta(wl, i);
wl1271_tx_reset_link_queues(wl, i);
- wl->links[i].allocated_blks = 0;
- wl->links[i].prev_freed_blks = 0;
+ wl->links[i].allocated_pkts = 0;
+ wl->links[i].prev_freed_pkts = 0;
}
wl->last_tx_hlid = 0;
@@ -871,10 +915,14 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
ieee80211_tx_status_ni(wl->hw, skb);
}
}
- wl->tx_queue_count[i] = 0;
}
+
+ wl->ba_rx_bitmap = 0;
}
+ for (i = 0; i < NUM_TX_QUEUES; i++)
+ wl->tx_queue_count[i] = 0;
+
wl->stopped_queues_map = 0;
/*
@@ -942,20 +990,10 @@ void wl1271_tx_flush(struct wl1271 *wl)
wl1271_warning("Unable to flush all TX buffers, timed out.");
}
-u32 wl1271_tx_min_rate_get(struct wl1271 *wl)
+u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set)
{
- int i;
- u32 rate = 0;
-
- if (!wl->basic_rate_set) {
- WARN_ON(1);
- wl->basic_rate_set = wl->conf.tx.basic_rate;
- }
-
- for (i = 0; !rate; i++) {
- if ((wl->basic_rate_set >> i) & 0x1)
- rate = 1 << i;
- }
+ if (WARN_ON(!rate_set))
+ return 0;
- return rate;
+ return BIT(__ffs(rate_set));
}
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 5d719b5a3d1d..dc4f09adf088 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -25,13 +25,11 @@
#ifndef __TX_H__
#define __TX_H__
+#define TX_HW_BLOCK_SPARE_DEFAULT 1
#define TX_HW_BLOCK_SIZE 252
#define TX_HW_MGMT_PKT_LIFETIME_TU 2000
#define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000
-/* The chipset reference driver states, that the "aid" value 1
- * is for infra-BSS, but is still always used */
-#define TX_HW_DEFAULT_AID 1
#define TX_HW_ATTR_SAVE_RETRIES BIT(0)
#define TX_HW_ATTR_HEADER_PAD BIT(1)
@@ -116,12 +114,8 @@ struct wl1271_tx_hw_descr {
u8 id;
/* The packet TID value (as User-Priority) */
u8 tid;
- union {
- /* STA - Identifier of the remote STA in IBSS, 1 in infra-BSS */
- u8 aid;
- /* AP - host link ID (HLID) */
- u8 hlid;
- } __packed;
+ /* host link ID (HLID) */
+ u8 hlid;
u8 reserved;
} __packed;
@@ -133,7 +127,8 @@ enum wl1271_tx_hw_res_status {
TX_TIMEOUT = 4,
TX_KEY_NOT_FOUND = 5,
TX_PEER_NOT_FOUND = 6,
- TX_SESSION_MISMATCH = 7
+ TX_SESSION_MISMATCH = 7,
+ TX_LINK_NOT_VALID = 8,
};
struct wl1271_tx_hw_res_descr {
@@ -214,10 +209,15 @@ void wl1271_tx_complete(struct wl1271 *wl);
void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
void wl1271_tx_flush(struct wl1271 *wl);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
-u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
-u32 wl1271_tx_min_rate_get(struct wl1271 *wl);
-u8 wl1271_tx_get_hlid(struct sk_buff *skb);
+u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
+ enum ieee80211_band rate_band);
+u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set);
+u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb);
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
+bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
+
+/* from main.c */
+void wl1271_free_sta(struct wl1271 *wl, u8 hlid);
#endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 1a8751eb8140..1ec90fc7505e 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -112,28 +112,8 @@ extern u32 wl12xx_debug_level;
true); \
} while (0)
-#define WL1271_DEFAULT_STA_RX_CONFIG (CFG_UNI_FILTER_EN | \
- CFG_BSSID_FILTER_EN | \
- CFG_MC_FILTER_EN)
-
-#define WL1271_DEFAULT_STA_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \
- CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
- CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
- CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
-
-#define WL1271_DEFAULT_AP_RX_CONFIG 0
-
-#define WL1271_DEFAULT_AP_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PREQ_EN | \
- CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
- CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \
- CFG_RX_ASSOC_EN)
-
-
-
-#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin"
-#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin"
-#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
-#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin"
+#define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin"
+#define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin"
/*
* wl127x and wl128x are using the same NVS file name. However, the
@@ -157,25 +137,34 @@ extern u32 wl12xx_debug_level;
#define WL1271_DEFAULT_BEACON_INT 100
#define WL1271_DEFAULT_DTIM_PERIOD 1
-#define WL1271_AP_GLOBAL_HLID 0
-#define WL1271_AP_BROADCAST_HLID 1
-#define WL1271_AP_STA_HLID_START 2
+#define WL12XX_MAX_ROLES 4
+#define WL12XX_MAX_LINKS 12
+#define WL12XX_INVALID_ROLE_ID 0xff
+#define WL12XX_INVALID_LINK_ID 0xff
+
+/* Defined by FW as 0. Will not be freed or allocated. */
+#define WL12XX_SYSTEM_HLID 0
+
+/*
+ * TODO: we currently don't support multirole. remove
+ * this constant from the code when we do.
+ */
+#define WL1271_AP_STA_HLID_START 3
/*
- * When in AP-mode, we allow (at least) this number of mem-blocks
+ * When in AP-mode, we allow (at least) this number of packets
* to be transmitted to FW for a STA in PS-mode. Only when packets are
* present in the FW buffers it will wake the sleeping STA. We want to put
* enough packets for the driver to transmit all of its buffered data before
- * the STA goes to sleep again. But we don't want to take too much mem-blocks
+ * the STA goes to sleep again. But we don't want to take too much memory
* as it might hurt the throughput of active STAs.
- * The number of blocks (18) is enough for 2 large packets.
*/
-#define WL1271_PS_STA_MAX_BLOCKS (2 * 9)
+#define WL1271_PS_STA_MAX_PACKETS 2
#define WL1271_AP_BSS_INDEX 0
#define WL1271_AP_DEF_BEACON_EXP 20
-#define ACX_TX_DESCRIPTORS 32
+#define ACX_TX_DESCRIPTORS 16
#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
@@ -245,28 +234,24 @@ struct wl1271_stats {
#define NUM_TX_QUEUES 4
#define NUM_RX_PKT_DESC 8
-#define AP_MAX_STATIONS 5
+#define AP_MAX_STATIONS 8
-/* Broadcast and Global links + links to stations */
-#define AP_MAX_LINKS (AP_MAX_STATIONS + 2)
+/* Broadcast and Global links + system link + links to stations */
+/*
+ * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all
+ * the places that use this.
+ */
+#define AP_MAX_LINKS (AP_MAX_STATIONS + WL1271_AP_STA_HLID_START)
-/* FW status registers common for AP/STA */
-struct wl1271_fw_common_status {
+/* FW status registers */
+struct wl12xx_fw_status {
__le32 intr;
u8 fw_rx_counter;
u8 drv_rx_counter;
u8 reserved;
u8 tx_results_counter;
__le32 rx_pkt_descs[NUM_RX_PKT_DESC];
- __le32 tx_released_blks[NUM_TX_QUEUES];
__le32 fw_localtime;
-} __packed;
-
-/* FW status registers for AP */
-struct wl1271_fw_ap_status {
- struct wl1271_fw_common_status common;
-
- /* Next fields valid only in AP FW */
/*
* A bitmap (where each bit represents a single HLID)
@@ -274,29 +259,29 @@ struct wl1271_fw_ap_status {
*/
__le32 link_ps_bitmap;
- /* Number of freed MBs per HLID */
- u8 tx_lnk_free_blks[AP_MAX_LINKS];
- u8 padding_1[1];
-} __packed;
+ /*
+ * A bitmap (where each bit represents a single HLID) to indicate
+ * if the station is in Fast mode
+ */
+ __le32 link_fast_bitmap;
-/* FW status registers for STA */
-struct wl1271_fw_sta_status {
- struct wl1271_fw_common_status common;
+ /* Cumulative counter of total released mem blocks since FW-reset */
+ __le32 total_released_blks;
- u8 tx_total;
- u8 reserved1;
- __le16 reserved2;
- __le32 log_start_addr;
-} __packed;
+ /* Size (in Memory Blocks) of TX pool */
+ __le32 tx_total;
-struct wl1271_fw_full_status {
- union {
- struct wl1271_fw_common_status common;
- struct wl1271_fw_sta_status sta;
- struct wl1271_fw_ap_status ap;
- };
-} __packed;
+ /* Cumulative counter of released packets per AC */
+ u8 tx_released_pkts[NUM_TX_QUEUES];
+ /* Cumulative counter of freed packets per HLID */
+ u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
+
+ /* Cumulative counter of released Voice memory blocks */
+ u8 tx_voice_released_blks;
+ u8 padding_1[3];
+ __le32 log_start_addr;
+} __packed;
struct wl1271_rx_mem_pool_addr {
u32 addr;
@@ -309,7 +294,7 @@ struct wl1271_scan {
unsigned long scanned_ch[BITS_TO_LONGS(WL1271_MAX_CHANNELS)];
bool failed;
u8 state;
- u8 ssid[IW_ESSID_MAX_SIZE+1];
+ u8 ssid[IEEE80211_MAX_SSID_LEN+1];
size_t ssid_len;
};
@@ -342,7 +327,7 @@ struct wl1271_ap_key {
enum wl12xx_flags {
WL1271_FLAG_STA_ASSOCIATED,
- WL1271_FLAG_JOINED,
+ WL1271_FLAG_IBSS_JOINED,
WL1271_FLAG_GPIO_POWER,
WL1271_FLAG_TX_QUEUE_STOPPED,
WL1271_FLAG_TX_PENDING,
@@ -363,17 +348,21 @@ enum wl12xx_flags {
WL1271_FLAG_SOFT_GEMINI,
WL1271_FLAG_RX_STREAMING_STARTED,
WL1271_FLAG_RECOVERY_IN_PROGRESS,
+ WL1271_FLAG_CS_PROGRESS,
};
struct wl1271_link {
/* AP-mode - TX queue per AC in link */
struct sk_buff_head tx_queue[NUM_TX_QUEUES];
- /* accounting for allocated / available TX blocks in FW */
- u8 allocated_blks;
- u8 prev_freed_blks;
+ /* accounting for allocated / freed packets in FW */
+ u8 allocated_pkts;
+ u8 prev_freed_pkts;
u8 addr[ETH_ALEN];
+
+ /* bitmap of TIDs where RX BA sessions are active for this link */
+ u8 ba_bitmap;
};
struct wl1271 {
@@ -405,7 +394,6 @@ struct wl1271 {
u8 *fw;
size_t fw_len;
- u8 fw_bss_type;
void *nvs;
size_t nvs_len;
@@ -415,18 +403,37 @@ struct wl1271 {
u8 mac_addr[ETH_ALEN];
u8 bss_type;
u8 set_bss_type;
- u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 p2p; /* we are using p2p role */
+ u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 ssid_len;
int channel;
+ u8 role_id;
+ u8 dev_role_id;
+ u8 system_hlid;
+ u8 sta_hlid;
+ u8 dev_hlid;
+ u8 ap_global_hlid;
+ u8 ap_bcast_hlid;
+
+ unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
+ unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
+ unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
struct wl1271_acx_mem_map *target_mem_map;
/* Accounting for allocated / available TX blocks on HW */
- u32 tx_blocks_freed[NUM_TX_QUEUES];
+ u32 tx_blocks_freed;
u32 tx_blocks_available;
- u32 tx_allocated_blocks[NUM_TX_QUEUES];
+ u32 tx_allocated_blocks;
u32 tx_results_count;
+ /* amount of spare TX blocks to use */
+ u32 tx_spare_blocks;
+
+ /* Accounting for allocated / available Tx packets in HW */
+ u32 tx_pkts_freed[NUM_TX_QUEUES];
+ u32 tx_allocated_pkts[NUM_TX_QUEUES];
+
/* Transmitted TX packets counter for chipset interface */
u32 tx_packets_count;
@@ -520,6 +527,7 @@ struct wl1271 {
u32 basic_rate_set;
u32 basic_rate;
u32 rate_set;
+ u32 bitrate_masks[IEEE80211_NUM_BANDS];
/* The current band */
enum ieee80211_band band;
@@ -535,10 +543,6 @@ struct wl1271 {
struct work_struct rx_streaming_disable_work;
struct timer_list rx_streaming_timer;
- unsigned int filters;
- unsigned int rx_config;
- unsigned int rx_filter;
-
struct completion *elp_compl;
struct completion *ps_compl;
struct delayed_work elp_work;
@@ -562,7 +566,7 @@ struct wl1271 {
u32 buffer_cmd;
u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
- struct wl1271_fw_full_status *fw_status;
+ struct wl12xx_fw_status *fw_status;
struct wl1271_tx_hw_res_if *tx_res_if;
struct ieee80211_vif *vif;
@@ -622,6 +626,12 @@ struct wl1271 {
/* Platform limitations */
unsigned int platform_quirks;
+
+ /* number of currently active RX BA sessions */
+ int ba_rx_session_count;
+
+ /* AP-mode - number of currently connected stations */
+ int active_sta_count;
};
struct wl1271_station {
@@ -659,21 +669,9 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
/* Each RX/TX transaction requires an end-of-transaction transfer */
#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0)
-/*
- * Older firmwares use 2 spare TX blocks
- * (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47)
- */
-#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1)
-
/* WL128X requires aggregated packets to be aligned to the SDIO block size */
#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2)
-/*
- * WL127X AP mode requires Low Power DRPw (LPD) enable to reduce power
- * consumption
- */
-#define WL12XX_QUIRK_LPD_MODE BIT(3)
-
/* Older firmwares did not implement the FW logger over bus feature */
#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4)
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h
index 18fe542360f2..f7971d3b0898 100644
--- a/drivers/net/wireless/wl12xx/wl12xx_80211.h
+++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h
@@ -77,7 +77,7 @@ struct wl12xx_ie_header {
struct wl12xx_ie_ssid {
struct wl12xx_ie_header header;
- char ssid[IW_ESSID_MAX_SIZE];
+ char ssid[IEEE80211_MAX_SSID_LEN];
} __packed;
struct wl12xx_ie_rates {
@@ -105,18 +105,6 @@ struct wl12xx_ie_country {
/* Templates */
-struct wl12xx_beacon_template {
- struct ieee80211_header header;
- __le32 time_stamp[2];
- __le16 beacon_interval;
- __le16 capability;
- struct wl12xx_ie_ssid ssid;
- struct wl12xx_ie_rates rates;
- struct wl12xx_ie_rates ext_rates;
- struct wl12xx_ie_ds_params ds_params;
- struct wl12xx_ie_country country;
-} __packed;
-
struct wl12xx_null_data_template {
struct ieee80211_header header;
} __packed;
@@ -146,19 +134,6 @@ struct wl12xx_arp_rsp_template {
__be32 target_ip;
} __packed;
-
-struct wl12xx_probe_resp_template {
- struct ieee80211_header header;
- __le32 time_stamp[2];
- __le16 beacon_interval;
- __le16 capability;
- struct wl12xx_ie_ssid ssid;
- struct wl12xx_ie_rates rates;
- struct wl12xx_ie_rates ext_rates;
- struct wl12xx_ie_ds_params ds_params;
- struct wl12xx_ie_country country;
-} __packed;
-
struct wl12xx_disconn_template {
struct ieee80211_header header;
__le16 disconn_reason;
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 6bc7c92fbff7..98fbf54f6004 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1781,7 +1781,7 @@ static int wl3501_get_encode(struct net_device *dev,
keys, len_keys);
if (rc)
goto out;
- tocopy = min_t(u8, len_keys, wrqu->encoding.length);
+ tocopy = min_t(u16, len_keys, wrqu->encoding.length);
tocopy = min_t(u8, tocopy, 100);
wrqu->encoding.length = tocopy;
memcpy(extra, keys, tocopy);
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index 415eec401e2e..8efa2f2d9579 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -1722,7 +1722,7 @@ static const struct net_device_ops zd1201_netdev_ops = {
.ndo_stop = zd1201_net_stop,
.ndo_start_xmit = zd1201_hard_start_xmit,
.ndo_tx_timeout = zd1201_tx_timeout,
- .ndo_set_multicast_list = zd1201_set_multicast,
+ .ndo_set_rx_mode = zd1201_set_multicast,
.ndo_set_mac_address = zd1201_set_mac_address,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index cabfae1e70b1..0a70149df3fc 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -1332,7 +1332,7 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
}
}
-static u64 zd_op_get_tsf(struct ieee80211_hw *hw)
+static u64 zd_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct zd_mac *mac = zd_hw_mac(hw);
return zd_chip_get_tsf(&mac->chip);
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index fd00f25d9850..d5508957200e 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -60,6 +60,9 @@ struct netbk_rx_meta {
#define MAX_PENDING_REQS 256
+/* Discriminate from any valid pending_idx value. */
+#define INVALID_PENDING_IDX 0xFFFF
+
#define MAX_BUFFER_OFFSET PAGE_SIZE
/* extra field used in struct page */
@@ -155,13 +158,13 @@ static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
u16 flags);
static inline unsigned long idx_to_pfn(struct xen_netbk *netbk,
- unsigned int idx)
+ u16 idx)
{
return page_to_pfn(netbk->mmap_pages[idx]);
}
static inline unsigned long idx_to_kaddr(struct xen_netbk *netbk,
- unsigned int idx)
+ u16 idx)
{
return (unsigned long)pfn_to_kaddr(idx_to_pfn(netbk, idx));
}
@@ -215,6 +218,16 @@ static int get_page_ext(struct page *pg,
sizeof(struct iphdr) + MAX_IPOPTLEN + \
sizeof(struct tcphdr) + MAX_TCP_OPTION_SPACE)
+static u16 frag_get_pending_idx(skb_frag_t *frag)
+{
+ return (u16)frag->page_offset;
+}
+
+static void frag_set_pending_idx(skb_frag_t *frag, u16 pending_idx)
+{
+ frag->page_offset = pending_idx;
+}
+
static inline pending_ring_idx_t pending_index(unsigned i)
{
return i & (MAX_PENDING_REQS-1);
@@ -321,7 +334,7 @@ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb)
count++;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- unsigned long size = skb_shinfo(skb)->frags[i].size;
+ unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
unsigned long bytes;
while (size > 0) {
BUG_ON(copy_off > MAX_BUFFER_OFFSET);
@@ -512,8 +525,8 @@ static int netbk_gop_skb(struct sk_buff *skb,
for (i = 0; i < nr_frags; i++) {
netbk_gop_frag_copy(vif, skb, npo,
- skb_shinfo(skb)->frags[i].page,
- skb_shinfo(skb)->frags[i].size,
+ skb_frag_page(&skb_shinfo(skb)->frags[i]),
+ skb_frag_size(&skb_shinfo(skb)->frags[i]),
skb_shinfo(skb)->frags[i].page_offset,
&head);
}
@@ -890,7 +903,7 @@ static int netbk_count_requests(struct xenvif *vif,
static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk,
struct sk_buff *skb,
- unsigned long pending_idx)
+ u16 pending_idx)
{
struct page *page;
page = alloc_page(GFP_KERNEL|__GFP_COLD);
@@ -909,11 +922,11 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
{
struct skb_shared_info *shinfo = skb_shinfo(skb);
skb_frag_t *frags = shinfo->frags;
- unsigned long pending_idx = *((u16 *)skb->data);
+ u16 pending_idx = *((u16 *)skb->data);
int i, start;
/* Skip first skb fragment if it is on same page as header fragment. */
- start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+ start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);
for (i = start; i < shinfo->nr_frags; i++, txp++) {
struct page *page;
@@ -945,7 +958,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp));
xenvif_get(vif);
pending_tx_info[pending_idx].vif = vif;
- frags[i].page = (void *)pending_idx;
+ frag_set_pending_idx(&frags[i], pending_idx);
}
return gop;
@@ -956,7 +969,7 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
struct gnttab_copy **gopp)
{
struct gnttab_copy *gop = *gopp;
- int pending_idx = *((u16 *)skb->data);
+ u16 pending_idx = *((u16 *)skb->data);
struct pending_tx_info *pending_tx_info = netbk->pending_tx_info;
struct xenvif *vif = pending_tx_info[pending_idx].vif;
struct xen_netif_tx_request *txp;
@@ -976,13 +989,13 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
}
/* Skip first skb fragment if it is on same page as header fragment. */
- start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+ start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);
for (i = start; i < nr_frags; i++) {
int j, newerr;
pending_ring_idx_t index;
- pending_idx = (unsigned long)shinfo->frags[i].page;
+ pending_idx = frag_get_pending_idx(&shinfo->frags[i]);
/* Check error status: if okay then remember grant handle. */
newerr = (++gop)->status;
@@ -1008,7 +1021,7 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
pending_idx = *((u16 *)skb->data);
xen_netbk_idx_release(netbk, pending_idx);
for (j = start; j < i; j++) {
- pending_idx = (unsigned long)shinfo->frags[i].page;
+ pending_idx = frag_get_pending_idx(&shinfo->frags[i]);
xen_netbk_idx_release(netbk, pending_idx);
}
@@ -1029,15 +1042,14 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb)
for (i = 0; i < nr_frags; i++) {
skb_frag_t *frag = shinfo->frags + i;
struct xen_netif_tx_request *txp;
- unsigned long pending_idx;
+ struct page *page;
+ u16 pending_idx;
- pending_idx = (unsigned long)frag->page;
+ pending_idx = frag_get_pending_idx(frag);
txp = &netbk->pending_tx_info[pending_idx].req;
- frag->page = virt_to_page(idx_to_kaddr(netbk, pending_idx));
- frag->size = txp->size;
- frag->page_offset = txp->offset;
-
+ page = virt_to_page(idx_to_kaddr(netbk, pending_idx));
+ __skb_fill_page_desc(skb, i, page, txp->offset, txp->size);
skb->len += txp->size;
skb->data_len += txp->size;
skb->truesize += txp->size;
@@ -1349,11 +1361,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
skb_shinfo(skb)->nr_frags = ret;
if (data_len < txreq.size) {
skb_shinfo(skb)->nr_frags++;
- skb_shinfo(skb)->frags[0].page =
- (void *)(unsigned long)pending_idx;
+ frag_set_pending_idx(&skb_shinfo(skb)->frags[0],
+ pending_idx);
} else {
- /* Discriminate from any valid pending_idx value. */
- skb_shinfo(skb)->frags[0].page = (void *)~0UL;
+ frag_set_pending_idx(&skb_shinfo(skb)->frags[0],
+ INVALID_PENDING_IDX);
}
__skb_queue_tail(&netbk->tx_queue, skb);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d7c8a98daff6..226faab23603 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -275,7 +275,7 @@ no_skb:
break;
}
- skb_shinfo(skb)->frags[0].page = page;
+ __skb_fill_page_desc(skb, 0, page, 0, 0);
skb_shinfo(skb)->nr_frags = 1;
__skb_queue_tail(&np->rx_batch, skb);
}
@@ -309,8 +309,8 @@ no_skb:
BUG_ON((signed short)ref < 0);
np->grant_rx_ref[id] = ref;
- pfn = page_to_pfn(skb_shinfo(skb)->frags[0].page);
- vaddr = page_address(skb_shinfo(skb)->frags[0].page);
+ pfn = page_to_pfn(skb_frag_page(&skb_shinfo(skb)->frags[0]));
+ vaddr = page_address(skb_frag_page(&skb_shinfo(skb)->frags[0]));
req = RING_GET_REQUEST(&np->rx, req_prod + i);
gnttab_grant_foreign_access_ref(ref,
@@ -461,13 +461,13 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
ref = gnttab_claim_grant_reference(&np->gref_tx_head);
BUG_ON((signed short)ref < 0);
- mfn = pfn_to_mfn(page_to_pfn(frag->page));
+ mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag)));
gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
mfn, GNTMAP_readonly);
tx->gref = np->grant_tx_ref[id] = ref;
tx->offset = frag->page_offset;
- tx->size = frag->size;
+ tx->size = skb_frag_size(frag);
tx->flags = 0;
}
@@ -762,23 +762,22 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np,
struct skb_shared_info *shinfo = skb_shinfo(skb);
int nr_frags = shinfo->nr_frags;
RING_IDX cons = np->rx.rsp_cons;
- skb_frag_t *frag = shinfo->frags + nr_frags;
struct sk_buff *nskb;
while ((nskb = __skb_dequeue(list))) {
struct xen_netif_rx_response *rx =
RING_GET_RESPONSE(&np->rx, ++cons);
+ skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0];
- frag->page = skb_shinfo(nskb)->frags[0].page;
- frag->page_offset = rx->offset;
- frag->size = rx->status;
+ __skb_fill_page_desc(skb, nr_frags,
+ skb_frag_page(nfrag),
+ rx->offset, rx->status);
skb->data_len += rx->status;
skb_shinfo(nskb)->nr_frags = 0;
kfree_skb(nskb);
- frag++;
nr_frags++;
}
@@ -873,7 +872,7 @@ static int handle_incoming_queue(struct net_device *dev,
memcpy(skb->data, vaddr + offset,
skb_headlen(skb));
- if (page != skb_shinfo(skb)->frags[0].page)
+ if (page != skb_frag_page(&skb_shinfo(skb)->frags[0]))
__free_page(page);
/* Ethernet work: Delayed to here as it peeks the header. */
@@ -954,7 +953,8 @@ err:
}
}
- NETFRONT_SKB_CB(skb)->page = skb_shinfo(skb)->frags[0].page;
+ NETFRONT_SKB_CB(skb)->page =
+ skb_frag_page(&skb_shinfo(skb)->frags[0]);
NETFRONT_SKB_CB(skb)->offset = rx->offset;
len = rx->status;
@@ -965,10 +965,10 @@ err:
if (rx->status > len) {
skb_shinfo(skb)->frags[0].page_offset =
rx->offset + len;
- skb_shinfo(skb)->frags[0].size = rx->status - len;
+ skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status - len);
skb->data_len = rx->status - len;
} else {
- skb_shinfo(skb)->frags[0].page = NULL;
+ __skb_fill_page_desc(skb, 0, NULL, 0, 0);
skb_shinfo(skb)->nr_frags = 0;
}
@@ -1143,7 +1143,8 @@ static void xennet_release_rx_bufs(struct netfront_info *np)
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
/* Remap the page. */
- struct page *page = skb_shinfo(skb)->frags[0].page;
+ const struct page *page =
+ skb_frag_page(&skb_shinfo(skb)->frags[0]);
unsigned long pfn = page_to_pfn(page);
void *vaddr = page_address(page);
@@ -1650,6 +1651,8 @@ static int xennet_connect(struct net_device *dev)
/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
+ skb_frag_t *frag;
+ const struct page *page;
if (!np->rx_skbs[i])
continue;
@@ -1657,10 +1660,11 @@ static int xennet_connect(struct net_device *dev)
ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
req = RING_GET_REQUEST(&np->rx, requeue_idx);
+ frag = &skb_shinfo(skb)->frags[0];
+ page = skb_frag_page(frag);
gnttab_grant_foreign_access_ref(
ref, np->xbdev->otherend_id,
- pfn_to_mfn(page_to_pfn(skb_shinfo(skb)->
- frags->page)),
+ pfn_to_mfn(page_to_pfn(page)),
0);
req->gref = ref;
req->id = requeue_idx;
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 2acff4307ca4..5af959274d4e 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -27,4 +27,15 @@ config NFC_PN533
Say Y here to compile support for PN533 devices into the
kernel or say M to compile it as module (pn533).
+config NFC_WILINK
+ tristate "Texas Instruments NFC WiLink driver"
+ depends on TI_ST && NFC_NCI
+ help
+ This enables the NFC driver for Texas Instrument's BT/FM/GPS/NFC
+ combo devices. This makes use of shared transport line discipline
+ core driver to communicate with the NFC core of the combo chip.
+
+ Say Y here to compile support for Texas Instrument's NFC WiLink driver
+ into the kernel or say M to compile it as module.
+
endmenu
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index 8ef446d2c1bd..ab99e8572f02 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -4,5 +4,6 @@
obj-$(CONFIG_PN544_NFC) += pn544.o
obj-$(CONFIG_NFC_PN533) += pn533.o
+obj-$(CONFIG_NFC_WILINK) += nfcwilink.o
ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c
new file mode 100644
index 000000000000..5b0f1ff80361
--- /dev/null
+++ b/drivers/nfc/nfcwilink.c
@@ -0,0 +1,342 @@
+/*
+ * Texas Instrument's NFC Driver For Shared Transport.
+ *
+ * NFC Driver acts as interface between NCI core and
+ * TI Shared Transport Layer.
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * Written by Ilan Elias <ilane@ti.com>
+ *
+ * Acknowledgements:
+ * This file is based on btwilink.c, which was written
+ * by Raja Mani and Pavan Savoy.
+ *
+ * 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
+ *
+ */
+#include <linux/platform_device.h>
+#include <linux/nfc.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+#include <linux/ti_wilink_st.h>
+
+#define NFCWILINK_CHNL 12
+#define NFCWILINK_OPCODE 7
+#define NFCWILINK_MAX_FRAME_SIZE 300
+#define NFCWILINK_HDR_LEN 4
+#define NFCWILINK_OFFSET_LEN_IN_HDR 1
+#define NFCWILINK_LEN_SIZE 2
+#define NFCWILINK_REGISTER_TIMEOUT 8000 /* 8 sec */
+
+struct nfcwilink_hdr {
+ u8 chnl;
+ u8 opcode;
+ u16 len;
+} __packed;
+
+struct nfcwilink {
+ struct platform_device *pdev;
+ struct nci_dev *ndev;
+ unsigned long flags;
+
+ char st_register_cb_status;
+ long (*st_write) (struct sk_buff *);
+ struct completion st_register_completed;
+};
+
+/* NFCWILINK driver flags */
+enum {
+ NFCWILINK_RUNNING,
+};
+
+/* Called by ST when registration is complete */
+static void nfcwilink_register_complete(void *priv_data, char data)
+{
+ struct nfcwilink *drv = priv_data;
+
+ nfc_dev_dbg(&drv->pdev->dev, "register_complete entry");
+
+ /* store ST registration status */
+ drv->st_register_cb_status = data;
+
+ /* complete the wait in nfc_st_open() */
+ complete(&drv->st_register_completed);
+}
+
+/* Called by ST when receive data is available */
+static long nfcwilink_receive(void *priv_data, struct sk_buff *skb)
+{
+ struct nfcwilink *drv = priv_data;
+ int rc;
+
+ nfc_dev_dbg(&drv->pdev->dev, "receive entry, len %d", skb->len);
+
+ if (!skb)
+ return -EFAULT;
+
+ if (!drv) {
+ kfree_skb(skb);
+ return -EFAULT;
+ }
+
+ /* strip the ST header
+ (apart for the chnl byte, which is not received in the hdr) */
+ skb_pull(skb, (NFCWILINK_HDR_LEN-1));
+
+ skb->dev = (void *) drv->ndev;
+
+ /* Forward skb to NCI core layer */
+ rc = nci_recv_frame(skb);
+ if (rc < 0) {
+ nfc_dev_err(&drv->pdev->dev, "nci_recv_frame failed %d", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+/* protocol structure registered with ST */
+static struct st_proto_s nfcwilink_proto = {
+ .chnl_id = NFCWILINK_CHNL,
+ .max_frame_size = NFCWILINK_MAX_FRAME_SIZE,
+ .hdr_len = (NFCWILINK_HDR_LEN-1), /* not including chnl byte */
+ .offset_len_in_hdr = NFCWILINK_OFFSET_LEN_IN_HDR,
+ .len_size = NFCWILINK_LEN_SIZE,
+ .reserve = 0,
+ .recv = nfcwilink_receive,
+ .reg_complete_cb = nfcwilink_register_complete,
+ .write = NULL,
+};
+
+static int nfcwilink_open(struct nci_dev *ndev)
+{
+ struct nfcwilink *drv = nci_get_drvdata(ndev);
+ unsigned long comp_ret;
+ int rc;
+
+ nfc_dev_dbg(&drv->pdev->dev, "open entry");
+
+ if (test_and_set_bit(NFCWILINK_RUNNING, &drv->flags)) {
+ rc = -EBUSY;
+ goto exit;
+ }
+
+ nfcwilink_proto.priv_data = drv;
+
+ init_completion(&drv->st_register_completed);
+ drv->st_register_cb_status = -EINPROGRESS;
+
+ rc = st_register(&nfcwilink_proto);
+ if (rc < 0) {
+ if (rc == -EINPROGRESS) {
+ comp_ret = wait_for_completion_timeout(
+ &drv->st_register_completed,
+ msecs_to_jiffies(NFCWILINK_REGISTER_TIMEOUT));
+
+ nfc_dev_dbg(&drv->pdev->dev,
+ "wait_for_completion_timeout returned %ld",
+ comp_ret);
+
+ if (comp_ret == 0) {
+ /* timeout */
+ rc = -ETIMEDOUT;
+ goto clear_exit;
+ } else if (drv->st_register_cb_status != 0) {
+ rc = drv->st_register_cb_status;
+ nfc_dev_err(&drv->pdev->dev,
+ "st_register_cb failed %d", rc);
+ goto clear_exit;
+ }
+ } else {
+ nfc_dev_err(&drv->pdev->dev,
+ "st_register failed %d", rc);
+ goto clear_exit;
+ }
+ }
+
+ /* st_register MUST fill the write callback */
+ BUG_ON(nfcwilink_proto.write == NULL);
+ drv->st_write = nfcwilink_proto.write;
+
+ goto exit;
+
+clear_exit:
+ clear_bit(NFCWILINK_RUNNING, &drv->flags);
+
+exit:
+ return rc;
+}
+
+static int nfcwilink_close(struct nci_dev *ndev)
+{
+ struct nfcwilink *drv = nci_get_drvdata(ndev);
+ int rc;
+
+ nfc_dev_dbg(&drv->pdev->dev, "close entry");
+
+ if (!test_and_clear_bit(NFCWILINK_RUNNING, &drv->flags))
+ return 0;
+
+ rc = st_unregister(&nfcwilink_proto);
+ if (rc)
+ nfc_dev_err(&drv->pdev->dev, "st_unregister failed %d", rc);
+
+ drv->st_write = NULL;
+
+ return rc;
+}
+
+static int nfcwilink_send(struct sk_buff *skb)
+{
+ struct nci_dev *ndev = (struct nci_dev *)skb->dev;
+ struct nfcwilink *drv = nci_get_drvdata(ndev);
+ struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000};
+ long len;
+
+ nfc_dev_dbg(&drv->pdev->dev, "send entry, len %d", skb->len);
+
+ if (!test_bit(NFCWILINK_RUNNING, &drv->flags))
+ return -EBUSY;
+
+ /* add the ST hdr to the start of the buffer */
+ hdr.len = skb->len;
+ memcpy(skb_push(skb, NFCWILINK_HDR_LEN), &hdr, NFCWILINK_HDR_LEN);
+
+ /* Insert skb to shared transport layer's transmit queue.
+ * Freeing skb memory is taken care in shared transport layer,
+ * so don't free skb memory here.
+ */
+ len = drv->st_write(skb);
+ if (len < 0) {
+ kfree_skb(skb);
+ nfc_dev_err(&drv->pdev->dev, "st_write failed %ld", len);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static struct nci_ops nfcwilink_ops = {
+ .open = nfcwilink_open,
+ .close = nfcwilink_close,
+ .send = nfcwilink_send,
+};
+
+static int nfcwilink_probe(struct platform_device *pdev)
+{
+ static struct nfcwilink *drv;
+ int rc;
+ u32 protocols;
+
+ nfc_dev_dbg(&pdev->dev, "probe entry");
+
+ drv = kzalloc(sizeof(struct nfcwilink), GFP_KERNEL);
+ if (!drv) {
+ rc = -ENOMEM;
+ goto exit;
+ }
+
+ drv->pdev = pdev;
+
+ protocols = NFC_PROTO_JEWEL_MASK
+ | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
+ | NFC_PROTO_ISO14443_MASK
+ | NFC_PROTO_NFC_DEP_MASK;
+
+ drv->ndev = nci_allocate_device(&nfcwilink_ops,
+ protocols,
+ NFCWILINK_HDR_LEN,
+ 0);
+ if (!drv->ndev) {
+ nfc_dev_err(&pdev->dev, "nci_allocate_device failed");
+ rc = -ENOMEM;
+ goto free_exit;
+ }
+
+ nci_set_parent_dev(drv->ndev, &pdev->dev);
+ nci_set_drvdata(drv->ndev, drv);
+
+ rc = nci_register_device(drv->ndev);
+ if (rc < 0) {
+ nfc_dev_err(&pdev->dev, "nci_register_device failed %d", rc);
+ goto free_dev_exit;
+ }
+
+ dev_set_drvdata(&pdev->dev, drv);
+
+ goto exit;
+
+free_dev_exit:
+ nci_free_device(drv->ndev);
+
+free_exit:
+ kfree(drv);
+
+exit:
+ return rc;
+}
+
+static int nfcwilink_remove(struct platform_device *pdev)
+{
+ struct nfcwilink *drv = dev_get_drvdata(&pdev->dev);
+ struct nci_dev *ndev;
+
+ nfc_dev_dbg(&pdev->dev, "remove entry");
+
+ if (!drv)
+ return -EFAULT;
+
+ ndev = drv->ndev;
+
+ nci_unregister_device(ndev);
+ nci_free_device(ndev);
+
+ kfree(drv);
+
+ dev_set_drvdata(&pdev->dev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver nfcwilink_driver = {
+ .probe = nfcwilink_probe,
+ .remove = nfcwilink_remove,
+ .driver = {
+ .name = "nfcwilink",
+ .owner = THIS_MODULE,
+ },
+};
+
+/* ------- Module Init/Exit interfaces ------ */
+static int __init nfcwilink_init(void)
+{
+ printk(KERN_INFO "NFC Driver for TI WiLink");
+
+ return platform_driver_register(&nfcwilink_driver);
+}
+
+static void __exit nfcwilink_exit(void)
+{
+ platform_driver_unregister(&nfcwilink_driver);
+}
+
+module_init(nfcwilink_init);
+module_exit(nfcwilink_exit);
+
+/* ------ Module Info ------ */
+
+MODULE_AUTHOR("Ilan Elias <ilane@ti.com>");
+MODULE_DESCRIPTION("NFC Driver for TI Shared Transport");
+MODULE_LICENSE("GPL");
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index c77e0543e502..7bcb1febef0d 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -28,7 +28,7 @@
#include <linux/usb.h>
#include <linux/nfc.h>
#include <linux/netdevice.h>
-#include <net/nfc.h>
+#include <net/nfc/nfc.h>
#define VERSION "0.1"
@@ -1246,7 +1246,6 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
{
int payload_len = skb->len;
struct pn533_frame *out_frame;
- struct sk_buff *discarded;
u8 tg;
nfc_dev_dbg(&dev->interface->dev, "%s - Sending %d bytes", __func__,
@@ -1260,18 +1259,6 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
return -ENOSYS;
}
- /* Reserving header space */
- if (skb_cow_head(skb, PN533_CMD_DATAEXCH_HEAD_LEN)) {
- nfc_dev_err(&dev->interface->dev, "Error to add header data");
- return -ENOMEM;
- }
-
- /* Reserving tail space, see pn533_tx_frame_finish */
- if (skb_cow_data(skb, PN533_FRAME_TAIL_SIZE, &discarded) < 0) {
- nfc_dev_err(&dev->interface->dev, "Error to add tail data");
- return -ENOMEM;
- }
-
skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
out_frame = (struct pn533_frame *) skb->data;
@@ -1445,6 +1432,8 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
}
struct nfc_ops pn533_nfc_ops = {
+ .dev_up = NULL,
+ .dev_down = NULL,
.start_poll = pn533_start_poll,
.stop_poll = pn533_stop_poll,
.activate_target = pn533_activate_target,
@@ -1536,7 +1525,9 @@ static int pn533_probe(struct usb_interface *interface,
| NFC_PROTO_ISO14443_MASK
| NFC_PROTO_NFC_DEP_MASK;
- dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols);
+ dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
+ PN533_CMD_DATAEXCH_HEAD_LEN,
+ PN533_FRAME_TAIL_SIZE);
if (!dev->nfc_dev)
goto kill_tasklet;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3ff22e32b602..9b6588ef0673 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -17,14 +17,39 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+/**
+ * struct alias_prop - Alias property in 'aliases' node
+ * @link: List node to link the structure in aliases_lookup list
+ * @alias: Alias property name
+ * @np: Pointer to device_node that the alias stands for
+ * @id: Index value from end of alias name
+ * @stem: Alias string without the index
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct alias_prop {
+ struct list_head link;
+ const char *alias;
+ struct device_node *np;
+ int id;
+ char stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
+
struct device_node *allnodes;
struct device_node *of_chosen;
+struct device_node *of_aliases;
+
+static DEFINE_MUTEX(of_aliases_mutex);
/* use when traversing tree through the allnext, child, sibling,
* or parent members of struct device_node.
@@ -632,6 +657,35 @@ int of_property_read_u32_array(const struct device_node *np,
EXPORT_SYMBOL_GPL(of_property_read_u32_array);
/**
+ * of_property_read_u64 - Find and read a 64 bit integer from a property
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ *
+ * Search for a property in a device node and read a 64-bit value from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_value is modified only if a valid u64 value can be decoded.
+ */
+int of_property_read_u64(const struct device_node *np, const char *propname,
+ u64 *out_value)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if (sizeof(*out_value) > prop->length)
+ return -EOVERFLOW;
+ *out_value = of_read_number(prop->value, 2);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u64);
+
+/**
* of_property_read_string - Find and read a string from a property
* @np: device node from which the property value is to be read.
* @propname: name of the property to be searched.
@@ -662,6 +716,90 @@ int of_property_read_string(struct device_node *np, const char *propname,
EXPORT_SYMBOL_GPL(of_property_read_string);
/**
+ * of_property_read_string_index - Find and read a string from a multiple
+ * strings property.
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @index: index of the string in the list of strings
+ * @out_string: pointer to null terminated return string, modified only if
+ * return value is 0.
+ *
+ * Search for a property in a device tree node and retrieve a null
+ * terminated string value (pointer to data, not a copy) in the list of strings
+ * contained in that property.
+ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
+ * property does not have a value, and -EILSEQ if the string is not
+ * null-terminated within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+int of_property_read_string_index(struct device_node *np, const char *propname,
+ int index, const char **output)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ int i = 0;
+ size_t l = 0, total = 0;
+ const char *p;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if (strnlen(prop->value, prop->length) >= prop->length)
+ return -EILSEQ;
+
+ p = prop->value;
+
+ for (i = 0; total < prop->length; total += l, p += l) {
+ l = strlen(p) + 1;
+ if ((*p != 0) && (i++ == index)) {
+ *output = p;
+ return 0;
+ }
+ }
+ return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(of_property_read_string_index);
+
+
+/**
+ * of_property_count_strings - Find and return the number of strings from a
+ * multiple strings property.
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ *
+ * Search for a property in a device tree node and retrieve the number of null
+ * terminated string contain in it. Returns the number of strings on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ */
+int of_property_count_strings(struct device_node *np, const char *propname)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ int i = 0;
+ size_t l = 0, total = 0;
+ const char *p;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if (strnlen(prop->value, prop->length) >= prop->length)
+ return -EILSEQ;
+
+ p = prop->value;
+
+ for (i = 0; total < prop->length; total += l, p += l) {
+ l = strlen(p) + 1;
+ if (*p != 0)
+ i++;
+ }
+ return i;
+}
+EXPORT_SYMBOL_GPL(of_property_count_strings);
+
+/**
* of_parse_phandle - Resolve a phandle property to a device_node pointer
* @np: Pointer to device node holding phandle property
* @phandle_name: Name of property holding a phandle value
@@ -988,3 +1126,99 @@ out_unlock:
}
#endif /* defined(CONFIG_OF_DYNAMIC) */
+static void of_alias_add(struct alias_prop *ap, struct device_node *np,
+ int id, const char *stem, int stem_len)
+{
+ ap->np = np;
+ ap->id = id;
+ strncpy(ap->stem, stem, stem_len);
+ ap->stem[stem_len] = 0;
+ list_add_tail(&ap->link, &aliases_lookup);
+ pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
+ ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
+}
+
+/**
+ * of_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties. It returns the
+ * number of alias_prop found, or error code in error case.
+ *
+ * @dt_alloc: An allocator that provides a virtual address to memory
+ * for the resulting tree
+ */
+void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
+{
+ struct property *pp;
+
+ of_chosen = of_find_node_by_path("/chosen");
+ if (of_chosen == NULL)
+ of_chosen = of_find_node_by_path("/chosen@0");
+ of_aliases = of_find_node_by_path("/aliases");
+ if (!of_aliases)
+ return;
+
+ for_each_property(pp, of_aliases->properties) {
+ const char *start = pp->name;
+ const char *end = start + strlen(start);
+ struct device_node *np;
+ struct alias_prop *ap;
+ int id, len;
+
+ /* Skip those we do not want to proceed */
+ if (!strcmp(pp->name, "name") ||
+ !strcmp(pp->name, "phandle") ||
+ !strcmp(pp->name, "linux,phandle"))
+ continue;
+
+ np = of_find_node_by_path(pp->value);
+ if (!np)
+ continue;
+
+ /* walk the alias backwards to extract the id and work out
+ * the 'stem' string */
+ while (isdigit(*(end-1)) && end > start)
+ end--;
+ len = end - start;
+
+ if (kstrtoint(end, 10, &id) < 0)
+ continue;
+
+ /* Allocate an alias_prop with enough space for the stem */
+ ap = dt_alloc(sizeof(*ap) + len + 1, 4);
+ if (!ap)
+ continue;
+ ap->alias = start;
+ of_alias_add(ap, np, id, start, len);
+ }
+}
+
+/**
+ * of_alias_get_id - Get alias id for the given device_node
+ * @np: Pointer to the given device_node
+ * @stem: Alias stem of the given device_node
+ *
+ * The function travels the lookup table to get alias id for the given
+ * device_node and alias stem. It returns the alias id if find it.
+ */
+int of_alias_get_id(struct device_node *np, const char *stem)
+{
+ struct alias_prop *app;
+ int id = -ENODEV;
+
+ mutex_lock(&of_aliases_mutex);
+ list_for_each_entry(app, &aliases_lookup, link) {
+ if (strcmp(app->stem, stem) != 0)
+ continue;
+
+ if (np == app->np) {
+ id = app->id;
+ break;
+ }
+ }
+ mutex_unlock(&of_aliases_mutex);
+
+ return id;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_id);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 65200af29c52..aeec35bc3789 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -707,10 +707,8 @@ void __init unflatten_device_tree(void)
__unflatten_device_tree(initial_boot_params, &allnodes,
early_init_dt_alloc_memory_arch);
- /* Get pointer to OF "/chosen" node for use everywhere */
- of_chosen = of_find_node_by_path("/chosen");
- if (of_chosen == NULL)
- of_chosen = of_find_node_by_path("/chosen@0");
+ /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
+ of_alias_scan(early_init_dt_alloc_memory_arch);
}
#endif /* CONFIG_OF_EARLY_FLATTREE */
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 9f689f1da0fc..6d3dd3988d0f 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -19,10 +19,12 @@
*/
#include <linux/errno.h>
+#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/string.h>
+#include <linux/slab.h>
/* For archs that don't support NO_IRQ (such as x86), provide a dummy value */
#ifndef NO_IRQ
@@ -58,27 +60,27 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
*/
struct device_node *of_irq_find_parent(struct device_node *child)
{
- struct device_node *p;
+ struct device_node *p, *c = child;
const __be32 *parp;
- if (!of_node_get(child))
+ if (!of_node_get(c))
return NULL;
do {
- parp = of_get_property(child, "interrupt-parent", NULL);
+ parp = of_get_property(c, "interrupt-parent", NULL);
if (parp == NULL)
- p = of_get_parent(child);
+ p = of_get_parent(c);
else {
if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
p = of_node_get(of_irq_dflt_pic);
else
p = of_find_node_by_phandle(be32_to_cpup(parp));
}
- of_node_put(child);
- child = p;
+ of_node_put(c);
+ c = p;
} while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
- return p;
+ return (p == child) ? NULL : p;
}
/**
@@ -386,3 +388,108 @@ int of_irq_to_resource_table(struct device_node *dev, struct resource *res,
return i;
}
+
+struct intc_desc {
+ struct list_head list;
+ struct device_node *dev;
+ struct device_node *interrupt_parent;
+};
+
+/**
+ * of_irq_init - Scan and init matching interrupt controllers in DT
+ * @matches: 0 terminated array of nodes to match and init function to call
+ *
+ * This function scans the device tree for matching interrupt controller nodes,
+ * and calls their initialization functions in order with parents first.
+ */
+void __init of_irq_init(const struct of_device_id *matches)
+{
+ struct device_node *np, *parent = NULL;
+ struct intc_desc *desc, *temp_desc;
+ struct list_head intc_desc_list, intc_parent_list;
+
+ INIT_LIST_HEAD(&intc_desc_list);
+ INIT_LIST_HEAD(&intc_parent_list);
+
+ for_each_matching_node(np, matches) {
+ if (!of_find_property(np, "interrupt-controller", NULL))
+ continue;
+ /*
+ * Here, we allocate and populate an intc_desc with the node
+ * pointer, interrupt-parent device_node etc.
+ */
+ desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+ if (WARN_ON(!desc))
+ goto err;
+
+ desc->dev = np;
+ desc->interrupt_parent = of_irq_find_parent(np);
+ list_add_tail(&desc->list, &intc_desc_list);
+ }
+
+ /*
+ * The root irq controller is the one without an interrupt-parent.
+ * That one goes first, followed by the controllers that reference it,
+ * followed by the ones that reference the 2nd level controllers, etc.
+ */
+ while (!list_empty(&intc_desc_list)) {
+ /*
+ * Process all controllers with the current 'parent'.
+ * First pass will be looking for NULL as the parent.
+ * The assumption is that NULL parent means a root controller.
+ */
+ list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
+ const struct of_device_id *match;
+ int ret;
+ of_irq_init_cb_t irq_init_cb;
+
+ if (desc->interrupt_parent != parent)
+ continue;
+
+ list_del(&desc->list);
+ match = of_match_node(matches, desc->dev);
+ if (WARN(!match->data,
+ "of_irq_init: no init function for %s\n",
+ match->compatible)) {
+ kfree(desc);
+ continue;
+ }
+
+ pr_debug("of_irq_init: init %s @ %p, parent %p\n",
+ match->compatible,
+ desc->dev, desc->interrupt_parent);
+ irq_init_cb = match->data;
+ ret = irq_init_cb(desc->dev, desc->interrupt_parent);
+ if (ret) {
+ kfree(desc);
+ continue;
+ }
+
+ /*
+ * This one is now set up; add it to the parent list so
+ * its children can get processed in a subsequent pass.
+ */
+ list_add_tail(&desc->list, &intc_parent_list);
+ }
+
+ /* Get the next pending parent that might have children */
+ desc = list_first_entry(&intc_parent_list, typeof(*desc), list);
+ if (list_empty(&intc_parent_list) || !desc) {
+ pr_err("of_irq_init: children remain, but no parents\n");
+ break;
+ }
+ list_del(&desc->list);
+ parent = desc->dev;
+ kfree(desc);
+ }
+
+ list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
+ list_del(&desc->list);
+ kfree(desc);
+ }
+err:
+ list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
+ list_del(&desc->list);
+ kfree(desc);
+ }
+}
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index d35e300b0ad1..980c079e4443 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -83,7 +83,6 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
addr);
continue;
}
- phy_scan_fixups(phy);
/* Associate the OF node with the device structure so it
* can be looked up later */
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index 4d87b5dc9284..bc5b3990f6ed 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -229,6 +229,11 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
return ret;
}
+static void *kernel_tree_alloc(u64 size, u64 align)
+{
+ return prom_early_alloc(size);
+}
+
void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
{
struct device_node **nextp;
@@ -245,4 +250,7 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
nextp = &allnodes->allnext;
allnodes->child = of_pdt_build_tree(allnodes,
of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
+
+ /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
+ of_alias_scan(kernel_tree_alloc);
}
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index dd87e86048be..c0cc4e7ff023 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -82,10 +82,10 @@ int alloc_event_buffer(void)
{
unsigned long flags;
- spin_lock_irqsave(&oprofilefs_lock, flags);
+ raw_spin_lock_irqsave(&oprofilefs_lock, flags);
buffer_size = oprofile_buffer_size;
buffer_watershed = oprofile_buffer_watershed;
- spin_unlock_irqrestore(&oprofilefs_lock, flags);
+ raw_spin_unlock_irqrestore(&oprofilefs_lock, flags);
if (buffer_watershed >= buffer_size)
return -EINVAL;
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
index 94796f39bc47..da14432806c6 100644
--- a/drivers/oprofile/oprofile_perf.c
+++ b/drivers/oprofile/oprofile_perf.c
@@ -160,9 +160,9 @@ static int oprofile_perf_create_files(struct super_block *sb, struct dentry *roo
static int oprofile_perf_setup(void)
{
- spin_lock(&oprofilefs_lock);
+ raw_spin_lock(&oprofilefs_lock);
op_perf_setup();
- spin_unlock(&oprofilefs_lock);
+ raw_spin_unlock(&oprofilefs_lock);
return 0;
}
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index e9ff6f7770be..d0de6cc2d7a5 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -21,7 +21,7 @@
#define OPROFILEFS_MAGIC 0x6f70726f
-DEFINE_SPINLOCK(oprofilefs_lock);
+DEFINE_RAW_SPINLOCK(oprofilefs_lock);
static struct inode *oprofilefs_get_inode(struct super_block *sb, int mode)
{
@@ -76,9 +76,9 @@ int oprofilefs_ulong_from_user(unsigned long *val, char const __user *buf, size_
if (copy_from_user(tmpbuf, buf, count))
return -EFAULT;
- spin_lock_irqsave(&oprofilefs_lock, flags);
+ raw_spin_lock_irqsave(&oprofilefs_lock, flags);
*val = simple_strtoul(tmpbuf, NULL, 0);
- spin_unlock_irqrestore(&oprofilefs_lock, flags);
+ raw_spin_unlock_irqrestore(&oprofilefs_lock, flags);
return 0;
}
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 57a6d19eba4c..a6f762188bc3 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -668,7 +668,7 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
* @dev: instance of PCI owned by the driver that's asking
* @mask: number of address bits this PCI device can handle
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static int sba_dma_supported( struct device *dev, u64 mask)
{
@@ -680,7 +680,7 @@ static int sba_dma_supported( struct device *dev, u64 mask)
return(0);
}
- /* Documentation/PCI/PCI-DMA-mapping.txt tells drivers to try 64-bit
+ /* Documentation/DMA-API-HOWTO.txt tells drivers to try 64-bit
* first, then fall back to 32-bit if that fails.
* We are just "encouraging" 32-bit DMA masks here since we can
* never allow IOMMU bypass unless we add special support for ZX1.
@@ -706,7 +706,7 @@ static int sba_dma_supported( struct device *dev, u64 mask)
* @size: number of bytes to map in driver buffer.
* @direction: R/W or both.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static dma_addr_t
sba_map_single(struct device *dev, void *addr, size_t size,
@@ -785,7 +785,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
* @size: number of bytes mapped in driver buffer.
* @direction: R/W or both.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void
sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
@@ -861,7 +861,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
* @size: number of bytes mapped in driver buffer.
* @dma_handle: IOVA of new buffer.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void *sba_alloc_consistent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
@@ -892,7 +892,7 @@ static void *sba_alloc_consistent(struct device *hwdev, size_t size,
* @vaddr: virtual address IOVA of "consistent" buffer.
* @dma_handler: IO virtual address of "consistent" buffer.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void
sba_free_consistent(struct device *hwdev, size_t size, void *vaddr,
@@ -927,7 +927,7 @@ int dump_run_sg = 0;
* @nents: number of entries in list
* @direction: R/W or both.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static int
sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
@@ -1011,7 +1011,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
* @nents: number of entries in list
* @direction: R/W or both.
*
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
*/
static void
sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index d1cdb9449f84..d0b597b50398 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2595,14 +2595,17 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq,
break;
case 0x6:
printk(KERN_INFO "parport_pc: ITE8873 found (1S)\n");
+ release_region(inta_addr[i], 32);
return 0;
case 0x8:
printk(KERN_INFO "parport_pc: ITE8874 found (2S)\n");
+ release_region(inta_addr[i], 32);
return 0;
default:
printk(KERN_INFO "parport_pc: unknown ITE887x\n");
printk(KERN_INFO "parport_pc: please mail 'lspci -nvv' "
"output to Rich.Liu@ite.com.tw\n");
+ release_region(inta_addr[i], 32);
return 0;
}
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 0fa466a91bf4..cec66064ee4b 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -71,9 +71,13 @@ config HT_IRQ
If unsure say Y.
+config PCI_ATS
+ bool
+
config PCI_IOV
bool "PCI IOV support"
depends on PCI
+ select PCI_ATS
help
I/O Virtualization is a PCI feature supported by some devices
which allows them to create virtual devices which share their
@@ -81,6 +85,28 @@ config PCI_IOV
If unsure, say N.
+config PCI_PRI
+ bool "PCI PRI support"
+ select PCI_ATS
+ help
+ PRI is the PCI Page Request Interface. It allows PCI devices that are
+ behind an IOMMU to recover from page faults.
+
+ If unsure, say N.
+
+config PCI_PASID
+ bool "PCI PASID support"
+ depends on PCI
+ select PCI_ATS
+ help
+ Process Address Space Identifiers (PASIDs) can be used by PCI devices
+ to access more than one IO address space at the same time. To make
+ use of this feature an IOMMU is required which also supports PASIDs.
+ Select this option if you have such an IOMMU and want to compile the
+ driver for it into your kernel.
+
+ If unsure, say N.
+
config PCI_IOAPIC
bool
depends on PCI
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 6fadae3ad134..083a49fee56a 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_PCI_MSI) += msi.o
# Build the Hypertransport interrupt support
obj-$(CONFIG_HT_IRQ) += htirq.o
+obj-$(CONFIG_PCI_ATS) += ats.o
obj-$(CONFIG_PCI_IOV) += iov.o
#
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
new file mode 100644
index 000000000000..f727a09eb72f
--- /dev/null
+++ b/drivers/pci/ats.c
@@ -0,0 +1,438 @@
+/*
+ * drivers/pci/ats.c
+ *
+ * Copyright (C) 2009 Intel Corporation, Yu Zhao <yu.zhao@intel.com>
+ * Copyright (C) 2011 Advanced Micro Devices,
+ *
+ * PCI Express I/O Virtualization (IOV) support.
+ * Address Translation Service 1.0
+ * Page Request Interface added by Joerg Roedel <joerg.roedel@amd.com>
+ * PASID support added by Joerg Roedel <joerg.roedel@amd.com>
+ */
+
+#include <linux/pci-ats.h>
+#include <linux/pci.h>
+
+#include "pci.h"
+
+static int ats_alloc_one(struct pci_dev *dev, int ps)
+{
+ int pos;
+ u16 cap;
+ struct pci_ats *ats;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
+ if (!pos)
+ return -ENODEV;
+
+ ats = kzalloc(sizeof(*ats), GFP_KERNEL);
+ if (!ats)
+ return -ENOMEM;
+
+ ats->pos = pos;
+ ats->stu = ps;
+ pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
+ ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
+ PCI_ATS_MAX_QDEP;
+ dev->ats = ats;
+
+ return 0;
+}
+
+static void ats_free_one(struct pci_dev *dev)
+{
+ kfree(dev->ats);
+ dev->ats = NULL;
+}
+
+/**
+ * pci_enable_ats - enable the ATS capability
+ * @dev: the PCI device
+ * @ps: the IOMMU page shift
+ *
+ * Returns 0 on success, or negative on failure.
+ */
+int pci_enable_ats(struct pci_dev *dev, int ps)
+{
+ int rc;
+ u16 ctrl;
+
+ BUG_ON(dev->ats && dev->ats->is_enabled);
+
+ if (ps < PCI_ATS_MIN_STU)
+ return -EINVAL;
+
+ if (dev->is_physfn || dev->is_virtfn) {
+ struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
+
+ mutex_lock(&pdev->sriov->lock);
+ if (pdev->ats)
+ rc = pdev->ats->stu == ps ? 0 : -EINVAL;
+ else
+ rc = ats_alloc_one(pdev, ps);
+
+ if (!rc)
+ pdev->ats->ref_cnt++;
+ mutex_unlock(&pdev->sriov->lock);
+ if (rc)
+ return rc;
+ }
+
+ if (!dev->is_physfn) {
+ rc = ats_alloc_one(dev, ps);
+ if (rc)
+ return rc;
+ }
+
+ ctrl = PCI_ATS_CTRL_ENABLE;
+ if (!dev->is_virtfn)
+ ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU);
+ pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
+
+ dev->ats->is_enabled = 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_enable_ats);
+
+/**
+ * pci_disable_ats - disable the ATS capability
+ * @dev: the PCI device
+ */
+void pci_disable_ats(struct pci_dev *dev)
+{
+ u16 ctrl;
+
+ BUG_ON(!dev->ats || !dev->ats->is_enabled);
+
+ pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl);
+ ctrl &= ~PCI_ATS_CTRL_ENABLE;
+ pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
+
+ dev->ats->is_enabled = 0;
+
+ if (dev->is_physfn || dev->is_virtfn) {
+ struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
+
+ mutex_lock(&pdev->sriov->lock);
+ pdev->ats->ref_cnt--;
+ if (!pdev->ats->ref_cnt)
+ ats_free_one(pdev);
+ mutex_unlock(&pdev->sriov->lock);
+ }
+
+ if (!dev->is_physfn)
+ ats_free_one(dev);
+}
+EXPORT_SYMBOL_GPL(pci_disable_ats);
+
+/**
+ * pci_ats_queue_depth - query the ATS Invalidate Queue Depth
+ * @dev: the PCI device
+ *
+ * Returns the queue depth on success, or negative on failure.
+ *
+ * The ATS spec uses 0 in the Invalidate Queue Depth field to
+ * indicate that the function can accept 32 Invalidate Request.
+ * But here we use the `real' values (i.e. 1~32) for the Queue
+ * Depth; and 0 indicates the function shares the Queue with
+ * other functions (doesn't exclusively own a Queue).
+ */
+int pci_ats_queue_depth(struct pci_dev *dev)
+{
+ int pos;
+ u16 cap;
+
+ if (dev->is_virtfn)
+ return 0;
+
+ if (dev->ats)
+ return dev->ats->qdep;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
+ if (!pos)
+ return -ENODEV;
+
+ pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
+
+ return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
+ PCI_ATS_MAX_QDEP;
+}
+EXPORT_SYMBOL_GPL(pci_ats_queue_depth);
+
+#ifdef CONFIG_PCI_PRI
+/**
+ * pci_enable_pri - Enable PRI capability
+ * @ pdev: PCI device structure
+ *
+ * Returns 0 on success, negative value on error
+ */
+int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
+{
+ u16 control, status;
+ u32 max_requests;
+ int pos;
+
+ pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
+ if (!pos)
+ return -EINVAL;
+
+ pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
+ pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status);
+ if ((control & PCI_PRI_ENABLE) || !(status & PCI_PRI_STATUS_STOPPED))
+ return -EBUSY;
+
+ pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ_OFF, &max_requests);
+ reqs = min(max_requests, reqs);
+ pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ_OFF, reqs);
+
+ control |= PCI_PRI_ENABLE;
+ pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_enable_pri);
+
+/**
+ * pci_disable_pri - Disable PRI capability
+ * @pdev: PCI device structure
+ *
+ * Only clears the enabled-bit, regardless of its former value
+ */
+void pci_disable_pri(struct pci_dev *pdev)
+{
+ u16 control;
+ int pos;
+
+ pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
+ if (!pos)
+ return;
+
+ pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
+ control &= ~PCI_PRI_ENABLE;
+ pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control);
+}
+EXPORT_SYMBOL_GPL(pci_disable_pri);
+
+/**
+ * pci_pri_enabled - Checks if PRI capability is enabled
+ * @pdev: PCI device structure
+ *
+ * Returns true if PRI is enabled on the device, false otherwise
+ */
+bool pci_pri_enabled(struct pci_dev *pdev)
+{
+ u16 control;
+ int pos;
+
+ pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
+ if (!pos)
+ return false;
+
+ pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
+
+ return (control & PCI_PRI_ENABLE) ? true : false;
+}
+EXPORT_SYMBOL_GPL(pci_pri_enabled);
+
+/**
+ * pci_reset_pri - Resets device's PRI state
+ * @pdev: PCI device structure
+ *
+ * The PRI capability must be disabled before this function is called.
+ * Returns 0 on success, negative value on error.
+ */
+int pci_reset_pri(struct pci_dev *pdev)
+{
+ u16 control;
+ int pos;
+
+ pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
+ if (!pos)
+ return -EINVAL;
+
+ pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
+ if (control & PCI_PRI_ENABLE)
+ return -EBUSY;
+
+ control |= PCI_PRI_RESET;
+
+ pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_reset_pri);
+
+/**
+ * pci_pri_stopped - Checks whether the PRI capability is stopped
+ * @pdev: PCI device structure
+ *
+ * Returns true if the PRI capability on the device is disabled and the
+ * device has no outstanding PRI requests, false otherwise. The device
+ * indicates this via the STOPPED bit in the status register of the
+ * capability.
+ * The device internal state can be cleared by resetting the PRI state
+ * with pci_reset_pri(). This can force the capability into the STOPPED
+ * state.
+ */
+bool pci_pri_stopped(struct pci_dev *pdev)
+{
+ u16 control, status;
+ int pos;
+
+ pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
+ if (!pos)
+ return true;
+
+ pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
+ pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status);
+
+ if (control & PCI_PRI_ENABLE)
+ return false;
+
+ return (status & PCI_PRI_STATUS_STOPPED) ? true : false;
+}
+EXPORT_SYMBOL_GPL(pci_pri_stopped);
+
+/**
+ * pci_pri_status - Request PRI status of a device
+ * @pdev: PCI device structure
+ *
+ * Returns negative value on failure, status on success. The status can
+ * be checked against status-bits. Supported bits are currently:
+ * PCI_PRI_STATUS_RF: Response failure
+ * PCI_PRI_STATUS_UPRGI: Unexpected Page Request Group Index
+ * PCI_PRI_STATUS_STOPPED: PRI has stopped
+ */
+int pci_pri_status(struct pci_dev *pdev)
+{
+ u16 status, control;
+ int pos;
+
+ pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
+ if (!pos)
+ return -EINVAL;
+
+ pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
+ pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status);
+
+ /* Stopped bit is undefined when enable == 1, so clear it */
+ if (control & PCI_PRI_ENABLE)
+ status &= ~PCI_PRI_STATUS_STOPPED;
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(pci_pri_status);
+#endif /* CONFIG_PCI_PRI */
+
+#ifdef CONFIG_PCI_PASID
+/**
+ * pci_enable_pasid - Enable the PASID capability
+ * @pdev: PCI device structure
+ * @features: Features to enable
+ *
+ * Returns 0 on success, negative value on error. This function checks
+ * whether the features are actually supported by the device and returns
+ * an error if not.
+ */
+int pci_enable_pasid(struct pci_dev *pdev, int features)
+{
+ u16 control, supported;
+ int pos;
+
+ pos = pci_find_ext_capability(pdev, PCI_PASID_CAP);
+ if (!pos)
+ return -EINVAL;
+
+ pci_read_config_word(pdev, pos + PCI_PASID_CONTROL_OFF, &control);
+ pci_read_config_word(pdev, pos + PCI_PASID_CAP_OFF, &supported);
+
+ if (!(supported & PCI_PASID_ENABLE))
+ return -EINVAL;
+
+ supported &= PCI_PASID_EXEC | PCI_PASID_PRIV;
+
+ /* User wants to enable anything unsupported? */
+ if ((supported & features) != features)
+ return -EINVAL;
+
+ control = PCI_PASID_ENABLE | features;
+
+ pci_write_config_word(pdev, pos + PCI_PASID_CONTROL_OFF, control);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_enable_pasid);
+
+/**
+ * pci_disable_pasid - Disable the PASID capability
+ * @pdev: PCI device structure
+ *
+ */
+void pci_disable_pasid(struct pci_dev *pdev)
+{
+ u16 control = 0;
+ int pos;
+
+ pos = pci_find_ext_capability(pdev, PCI_PASID_CAP);
+ if (!pos)
+ return;
+
+ pci_write_config_word(pdev, pos + PCI_PASID_CONTROL_OFF, control);
+}
+EXPORT_SYMBOL_GPL(pci_disable_pasid);
+
+/**
+ * pci_pasid_features - Check which PASID features are supported
+ * @pdev: PCI device structure
+ *
+ * Returns a negative value when no PASI capability is present.
+ * Otherwise is returns a bitmask with supported features. Current
+ * features reported are:
+ * PCI_PASID_ENABLE - PASID capability can be enabled
+ * PCI_PASID_EXEC - Execute permission supported
+ * PCI_PASID_PRIV - Priviledged mode supported
+ */
+int pci_pasid_features(struct pci_dev *pdev)
+{
+ u16 supported;
+ int pos;
+
+ pos = pci_find_ext_capability(pdev, PCI_PASID_CAP);
+ if (!pos)
+ return -EINVAL;
+
+ pci_read_config_word(pdev, pos + PCI_PASID_CAP_OFF, &supported);
+
+ supported &= PCI_PASID_ENABLE | PCI_PASID_EXEC | PCI_PASID_PRIV;
+
+ return supported;
+}
+EXPORT_SYMBOL_GPL(pci_pasid_features);
+
+#define PASID_NUMBER_SHIFT 8
+#define PASID_NUMBER_MASK (0x1f << PASID_NUMBER_SHIFT)
+/**
+ * pci_max_pasid - Get maximum number of PASIDs supported by device
+ * @pdev: PCI device structure
+ *
+ * Returns negative value when PASID capability is not present.
+ * Otherwise it returns the numer of supported PASIDs.
+ */
+int pci_max_pasids(struct pci_dev *pdev)
+{
+ u16 supported;
+ int pos;
+
+ pos = pci_find_ext_capability(pdev, PCI_PASID_CAP);
+ if (!pos)
+ return -EINVAL;
+
+ pci_read_config_word(pdev, pos + PCI_PASID_CAP_OFF, &supported);
+
+ supported = (supported & PASID_NUMBER_MASK) >> PASID_NUMBER_SHIFT;
+
+ return (1 << supported);
+}
+EXPORT_SYMBOL_GPL(pci_max_pasids);
+#endif /* CONFIG_PCI_PASID */
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 220285760b68..596172b4ae95 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -48,6 +48,7 @@
#include <linux/pci-acpi.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/acpi.h>
#include "../pci.h"
#include "acpiphp.h"
@@ -1149,15 +1150,35 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK ;
}
-/**
- * handle_hotplug_event_bridge - handle ACPI event on bridges
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @context: pointer to acpiphp_bridge structure
- *
- * Handles ACPI event notification on {host,p2p} bridges.
- */
-static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context)
+struct acpiphp_hp_work {
+ struct work_struct work;
+ acpi_handle handle;
+ u32 type;
+ void *context;
+};
+
+static void alloc_acpiphp_hp_work(acpi_handle handle, u32 type,
+ void *context,
+ void (*func)(struct work_struct *work))
+{
+ struct acpiphp_hp_work *hp_work;
+ int ret;
+
+ hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
+ if (!hp_work)
+ return;
+
+ hp_work->handle = handle;
+ hp_work->type = type;
+ hp_work->context = context;
+
+ INIT_WORK(&hp_work->work, func);
+ ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
+ if (!ret)
+ kfree(hp_work);
+}
+
+static void _handle_hotplug_event_bridge(struct work_struct *work)
{
struct acpiphp_bridge *bridge;
char objname[64];
@@ -1165,11 +1186,18 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
.pointer = objname };
struct acpi_device *device;
int num_sub_bridges = 0;
+ struct acpiphp_hp_work *hp_work;
+ acpi_handle handle;
+ u32 type;
+
+ hp_work = container_of(work, struct acpiphp_hp_work, work);
+ handle = hp_work->handle;
+ type = hp_work->type;
if (acpi_bus_get_device(handle, &device)) {
/* This bridge must have just been physically inserted */
handle_bridge_insertion(handle, type);
- return;
+ goto out;
}
bridge = acpiphp_handle_to_bridge(handle);
@@ -1180,7 +1208,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
if (!bridge && !num_sub_bridges) {
err("cannot get bridge info\n");
- return;
+ goto out;
}
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
@@ -1241,22 +1269,49 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
break;
}
+
+out:
+ kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
}
/**
- * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
+ * handle_hotplug_event_bridge - handle ACPI event on bridges
* @handle: Notify()'ed acpi_handle
* @type: Notify code
- * @context: pointer to acpiphp_func structure
+ * @context: pointer to acpiphp_bridge structure
*
- * Handles ACPI event notification on slots.
+ * Handles ACPI event notification on {host,p2p} bridges.
*/
-static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
+static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
+ void *context)
+{
+ /*
+ * Currently the code adds all hotplug events to the kacpid_wq
+ * queue when it should add hotplug events to the kacpi_hotplug_wq.
+ * The proper way to fix this is to reorganize the code so that
+ * drivers (dock, etc.) do not call acpi_os_execute(), etc.
+ * For now just re-add this work to the kacpi_hotplug_wq so we
+ * don't deadlock on hotplug actions.
+ */
+ alloc_acpiphp_hp_work(handle, type, context,
+ _handle_hotplug_event_bridge);
+}
+
+static void _handle_hotplug_event_func(struct work_struct *work)
{
struct acpiphp_func *func;
char objname[64];
struct acpi_buffer buffer = { .length = sizeof(objname),
.pointer = objname };
+ struct acpiphp_hp_work *hp_work;
+ acpi_handle handle;
+ u32 type;
+ void *context;
+
+ hp_work = container_of(work, struct acpiphp_hp_work, work);
+ handle = hp_work->handle;
+ type = hp_work->type;
+ context = hp_work->context;
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
@@ -1291,8 +1346,32 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
break;
}
+
+ kfree(hp_work); /* allocated in handle_hotplug_event_func */
}
+/**
+ * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
+ * @handle: Notify()'ed acpi_handle
+ * @type: Notify code
+ * @context: pointer to acpiphp_func structure
+ *
+ * Handles ACPI event notification on slots.
+ */
+static void handle_hotplug_event_func(acpi_handle handle, u32 type,
+ void *context)
+{
+ /*
+ * Currently the code adds all hotplug events to the kacpid_wq
+ * queue when it should add hotplug events to the kacpi_hotplug_wq.
+ * The proper way to fix this is to reorganize the code so that
+ * drivers (dock, etc.) do not call acpi_os_execute(), etc.
+ * For now just re-add this work to the kacpi_hotplug_wq so we
+ * don't deadlock on hotplug actions.
+ */
+ alloc_acpiphp_hp_work(handle, type, context,
+ _handle_hotplug_event_func);
+}
static acpi_status
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 42fae4776515..9b4e88c636f8 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -722,145 +722,3 @@ int pci_num_vf(struct pci_dev *dev)
return dev->sriov->nr_virtfn;
}
EXPORT_SYMBOL_GPL(pci_num_vf);
-
-static int ats_alloc_one(struct pci_dev *dev, int ps)
-{
- int pos;
- u16 cap;
- struct pci_ats *ats;
-
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
- if (!pos)
- return -ENODEV;
-
- ats = kzalloc(sizeof(*ats), GFP_KERNEL);
- if (!ats)
- return -ENOMEM;
-
- ats->pos = pos;
- ats->stu = ps;
- pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
- ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
- PCI_ATS_MAX_QDEP;
- dev->ats = ats;
-
- return 0;
-}
-
-static void ats_free_one(struct pci_dev *dev)
-{
- kfree(dev->ats);
- dev->ats = NULL;
-}
-
-/**
- * pci_enable_ats - enable the ATS capability
- * @dev: the PCI device
- * @ps: the IOMMU page shift
- *
- * Returns 0 on success, or negative on failure.
- */
-int pci_enable_ats(struct pci_dev *dev, int ps)
-{
- int rc;
- u16 ctrl;
-
- BUG_ON(dev->ats && dev->ats->is_enabled);
-
- if (ps < PCI_ATS_MIN_STU)
- return -EINVAL;
-
- if (dev->is_physfn || dev->is_virtfn) {
- struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
-
- mutex_lock(&pdev->sriov->lock);
- if (pdev->ats)
- rc = pdev->ats->stu == ps ? 0 : -EINVAL;
- else
- rc = ats_alloc_one(pdev, ps);
-
- if (!rc)
- pdev->ats->ref_cnt++;
- mutex_unlock(&pdev->sriov->lock);
- if (rc)
- return rc;
- }
-
- if (!dev->is_physfn) {
- rc = ats_alloc_one(dev, ps);
- if (rc)
- return rc;
- }
-
- ctrl = PCI_ATS_CTRL_ENABLE;
- if (!dev->is_virtfn)
- ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU);
- pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
-
- dev->ats->is_enabled = 1;
-
- return 0;
-}
-
-/**
- * pci_disable_ats - disable the ATS capability
- * @dev: the PCI device
- */
-void pci_disable_ats(struct pci_dev *dev)
-{
- u16 ctrl;
-
- BUG_ON(!dev->ats || !dev->ats->is_enabled);
-
- pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl);
- ctrl &= ~PCI_ATS_CTRL_ENABLE;
- pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
-
- dev->ats->is_enabled = 0;
-
- if (dev->is_physfn || dev->is_virtfn) {
- struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
-
- mutex_lock(&pdev->sriov->lock);
- pdev->ats->ref_cnt--;
- if (!pdev->ats->ref_cnt)
- ats_free_one(pdev);
- mutex_unlock(&pdev->sriov->lock);
- }
-
- if (!dev->is_physfn)
- ats_free_one(dev);
-}
-
-/**
- * pci_ats_queue_depth - query the ATS Invalidate Queue Depth
- * @dev: the PCI device
- *
- * Returns the queue depth on success, or negative on failure.
- *
- * The ATS spec uses 0 in the Invalidate Queue Depth field to
- * indicate that the function can accept 32 Invalidate Request.
- * But here we use the `real' values (i.e. 1~32) for the Queue
- * Depth; and 0 indicates the function shares the Queue with
- * other functions (doesn't exclusively own a Queue).
- */
-int pci_ats_queue_depth(struct pci_dev *dev)
-{
- int pos;
- u16 cap;
-
- if (dev->is_virtfn)
- return 0;
-
- if (dev->ats)
- return dev->ats->qdep;
-
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
- if (!pos)
- return -ENODEV;
-
- pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
-
- return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
- PCI_ATS_MAX_QDEP;
-}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index d36f41ea8cbf..4ecb6408b0d6 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -46,6 +46,9 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
struct pci_dev *pci_dev = context;
if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) {
+ if (pci_dev->pme_poll)
+ pci_dev->pme_poll = false;
+
pci_wakeup_event(pci_dev);
pci_check_pme_status(pci_dev);
pm_runtime_resume(&pci_dev->dev);
@@ -282,7 +285,6 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable)
{
struct acpi_device *dev;
acpi_handle handle;
- int error = -ENODEV;
if (!device_run_wake(phys_dev))
return -EINVAL;
@@ -302,7 +304,7 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable)
acpi_disable_wakeup_device_power(dev);
}
- return error;
+ return 0;
}
static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e9651f0a8817..6f45a73c6e9f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1407,13 +1407,16 @@ bool pci_check_pme_status(struct pci_dev *dev)
/**
* pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set.
* @dev: Device to handle.
- * @ign: Ignored.
+ * @pme_poll_reset: Whether or not to reset the device's pme_poll flag.
*
* Check if @dev has generated PME and queue a resume request for it in that
* case.
*/
-static int pci_pme_wakeup(struct pci_dev *dev, void *ign)
+static int pci_pme_wakeup(struct pci_dev *dev, void *pme_poll_reset)
{
+ if (pme_poll_reset && dev->pme_poll)
+ dev->pme_poll = false;
+
if (pci_check_pme_status(dev)) {
pci_wakeup_event(dev);
pm_request_resume(&dev->dev);
@@ -1428,7 +1431,7 @@ static int pci_pme_wakeup(struct pci_dev *dev, void *ign)
void pci_pme_wakeup_bus(struct pci_bus *bus)
{
if (bus)
- pci_walk_bus(bus, pci_pme_wakeup, NULL);
+ pci_walk_bus(bus, pci_pme_wakeup, (void *)true);
}
/**
@@ -1446,31 +1449,26 @@ bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
static void pci_pme_list_scan(struct work_struct *work)
{
- struct pci_pme_device *pme_dev;
+ struct pci_pme_device *pme_dev, *n;
mutex_lock(&pci_pme_list_mutex);
if (!list_empty(&pci_pme_list)) {
- list_for_each_entry(pme_dev, &pci_pme_list, list)
- pci_pme_wakeup(pme_dev->dev, NULL);
- schedule_delayed_work(&pci_pme_work, msecs_to_jiffies(PME_TIMEOUT));
+ list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
+ if (pme_dev->dev->pme_poll) {
+ pci_pme_wakeup(pme_dev->dev, NULL);
+ } else {
+ list_del(&pme_dev->list);
+ kfree(pme_dev);
+ }
+ }
+ if (!list_empty(&pci_pme_list))
+ schedule_delayed_work(&pci_pme_work,
+ msecs_to_jiffies(PME_TIMEOUT));
}
mutex_unlock(&pci_pme_list_mutex);
}
/**
- * pci_external_pme - is a device an external PCI PME source?
- * @dev: PCI device to check
- *
- */
-
-static bool pci_external_pme(struct pci_dev *dev)
-{
- if (pci_is_pcie(dev) || dev->bus->number == 0)
- return false;
- return true;
-}
-
-/**
* pci_pme_active - enable or disable PCI device's PME# function
* @dev: PCI device to handle.
* @enable: 'true' to enable PME# generation; 'false' to disable it.
@@ -1503,7 +1501,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
hit, and the power savings from the devices will still be a
win. */
- if (pci_external_pme(dev)) {
+ if (dev->pme_poll) {
struct pci_pme_device *pme_dev;
if (enable) {
pme_dev = kmalloc(sizeof(struct pci_pme_device),
@@ -1821,6 +1819,7 @@ void pci_pm_init(struct pci_dev *dev)
(pmc & PCI_PM_CAP_PME_D3) ? " D3hot" : "",
(pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : "");
dev->pme_support = pmc >> PCI_PM_CAP_PME_SHIFT;
+ dev->pme_poll = true;
/*
* Make device's PM flags reflect the wake-up capability, but
* let the user space enable it to wake up the system as needed.
@@ -3203,8 +3202,6 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
if (rq < 128 || rq > 4096 || !is_power_of_2(rq))
goto out;
- v = (ffs(rq) - 8) << 12;
-
cap = pci_pcie_cap(dev);
if (!cap)
goto out;
@@ -3212,6 +3209,22 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
if (err)
goto out;
+ /*
+ * If using the "performance" PCIe config, we clamp the
+ * read rq size to the max packet size to prevent the
+ * host bridge generating requests larger than we can
+ * cope with
+ */
+ if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
+ int mps = pcie_get_mps(dev);
+
+ if (mps < 0)
+ return mps;
+ if (mps < rq)
+ rq = mps;
+ }
+
+ v = (ffs(rq) - 8) << 12;
if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) {
ctl &= ~PCI_EXP_DEVCTL_READRQ;
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c
index 0057344a3fcb..001f1b78f39c 100644
--- a/drivers/pci/pcie/pme.c
+++ b/drivers/pci/pcie/pme.c
@@ -84,6 +84,9 @@ static bool pcie_pme_walk_bus(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) {
/* Skip PCIe devices in case we started from a root port. */
if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) {
+ if (dev->pme_poll)
+ dev->pme_poll = false;
+
pci_wakeup_event(dev);
pm_request_resume(&dev->dev);
ret = true;
@@ -142,6 +145,9 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
/* First, check if the PME is from the root port itself. */
if (port->devfn == devfn && port->bus->number == busnr) {
+ if (port->pme_poll)
+ port->pme_poll = false;
+
if (pci_check_pme_status(port)) {
pm_request_resume(&port->dev);
found = true;
@@ -187,6 +193,9 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
/* The device is there, but we have to check its PME status. */
found = pci_check_pme_status(dev);
if (found) {
+ if (dev->pme_poll)
+ dev->pme_poll = false;
+
pci_wakeup_event(dev);
pm_request_resume(&dev->dev);
}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6ab6bd3df4b2..04e74f485714 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1363,31 +1363,25 @@ static int pcie_find_smpss(struct pci_dev *dev, void *data)
static void pcie_write_mps(struct pci_dev *dev, int mps)
{
- int rc, dev_mpss;
-
- dev_mpss = 128 << dev->pcie_mpss;
+ int rc;
if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
- if (dev->bus->self) {
- dev_dbg(&dev->bus->dev, "Bus MPSS %d\n",
- 128 << dev->bus->self->pcie_mpss);
+ mps = 128 << dev->pcie_mpss;
- /* For "MPS Force Max", the assumption is made that
+ if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && dev->bus->self)
+ /* For "Performance", the assumption is made that
* downstream communication will never be larger than
* the MRRS. So, the MPS only needs to be configured
* for the upstream communication. This being the case,
* walk from the top down and set the MPS of the child
* to that of the parent bus.
+ *
+ * Configure the device MPS with the smaller of the
+ * device MPSS or the bridge MPS (which is assumed to be
+ * properly configured at this point to the largest
+ * allowable MPS based on its parent bus).
*/
- mps = 128 << dev->bus->self->pcie_mpss;
- if (mps > dev_mpss)
- dev_warn(&dev->dev, "MPS configured higher than"
- " maximum supported by the device. If"
- " a bus issue occurs, try running with"
- " pci=pcie_bus_safe.\n");
- }
-
- dev->pcie_mpss = ffs(mps) - 8;
+ mps = min(mps, pcie_get_mps(dev->bus->self));
}
rc = pcie_set_mps(dev, mps);
@@ -1395,25 +1389,22 @@ static void pcie_write_mps(struct pci_dev *dev, int mps)
dev_err(&dev->dev, "Failed attempting to set the MPS\n");
}
-static void pcie_write_mrrs(struct pci_dev *dev, int mps)
+static void pcie_write_mrrs(struct pci_dev *dev)
{
- int rc, mrrs, dev_mpss;
+ int rc, mrrs;
/* In the "safe" case, do not configure the MRRS. There appear to be
* issues with setting MRRS to 0 on a number of devices.
*/
-
if (pcie_bus_config != PCIE_BUS_PERFORMANCE)
return;
- dev_mpss = 128 << dev->pcie_mpss;
-
/* For Max performance, the MRRS must be set to the largest supported
* value. However, it cannot be configured larger than the MPS the
- * device or the bus can support. This assumes that the largest MRRS
- * available on the device cannot be smaller than the device MPSS.
+ * device or the bus can support. This should already be properly
+ * configured by a prior call to pcie_write_mps.
*/
- mrrs = min(mps, dev_mpss);
+ mrrs = pcie_get_mps(dev);
/* MRRS is a R/W register. Invalid values can be written, but a
* subsequent read will verify if the value is acceptable or not.
@@ -1421,38 +1412,41 @@ static void pcie_write_mrrs(struct pci_dev *dev, int mps)
* shrink the value until it is acceptable to the HW.
*/
while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) {
- dev_warn(&dev->dev, "Attempting to modify the PCI-E MRRS value"
- " to %d. If any issues are encountered, please try "
- "running with pci=pcie_bus_safe\n", mrrs);
rc = pcie_set_readrq(dev, mrrs);
- if (rc)
- dev_err(&dev->dev,
- "Failed attempting to set the MRRS\n");
+ if (!rc)
+ break;
+ dev_warn(&dev->dev, "Failed attempting to set the MRRS\n");
mrrs /= 2;
}
+
+ if (mrrs < 128)
+ dev_err(&dev->dev, "MRRS was unable to be configured with a "
+ "safe value. If problems are experienced, try running "
+ "with pci=pcie_bus_safe.\n");
}
static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
{
- int mps = 128 << *(u8 *)data;
+ int mps, orig_mps;
if (!pci_is_pcie(dev))
return 0;
- dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
- pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
+ mps = 128 << *(u8 *)data;
+ orig_mps = pcie_get_mps(dev);
pcie_write_mps(dev, mps);
- pcie_write_mrrs(dev, mps);
+ pcie_write_mrrs(dev);
- dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
- pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
+ dev_info(&dev->dev, "PCI-E Max Payload Size set to %4d/%4d (was %4d), "
+ "Max Read Rq %4d\n", pcie_get_mps(dev), 128 << dev->pcie_mpss,
+ orig_mps, pcie_get_readrq(dev));
return 0;
}
-/* pcie_bus_configure_mps requires that pci_walk_bus work in a top-down,
+/* pcie_bus_configure_settings requires that pci_walk_bus work in a top-down,
* parents then children fashion. If this changes, then this code will not
* work as designed.
*/
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 1196f61a4ab6..7285145ac1c9 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2745,20 +2745,6 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
/* disable must be done via function #0 */
if (PCI_FUNC(dev->devfn))
return;
-
- pci_read_config_byte(dev, 0xCB, &disable);
-
- if (disable & 0x02)
- return;
-
- pci_read_config_byte(dev, 0xCA, &write_enable);
- pci_write_config_byte(dev, 0xCA, 0x57);
- pci_write_config_byte(dev, 0xCB, disable | 0x02);
- pci_write_config_byte(dev, 0xCA, write_enable);
-
- dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n");
- dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n");
-
/*
* RICOH 0xe823 SD/MMC card reader fails to recognize
* certain types of SD/MMC cards. Lowering the SD base
@@ -2781,6 +2767,20 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
dev_notice(&dev->dev, "MMC controller base frequency changed to 50Mhz.\n");
}
+
+ pci_read_config_byte(dev, 0xCB, &disable);
+
+ if (disable & 0x02)
+ return;
+
+ pci_read_config_byte(dev, 0xCA, &write_enable);
+ pci_write_config_byte(dev, 0xCA, 0x57);
+ pci_write_config_byte(dev, 0xCB, disable | 0x02);
+ pci_write_config_byte(dev, 0xCA, write_enable);
+
+ dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n");
+ dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n");
+
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
@@ -2788,7 +2788,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832);
#endif /*CONFIG_MMC_RICOH_MMC*/
-#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
+#ifdef CONFIG_DMAR_TABLE
#define VTUNCERRMSK_REG 0x1ac
#define VTD_MSK_SPEC_ERRORS (1 << 31)
/*
@@ -2822,6 +2822,89 @@ static void __devinit fixup_ti816x_class(struct pci_dev* dev)
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_TI, 0xb800, fixup_ti816x_class);
+/* Some PCIe devices do not work reliably with the claimed maximum
+ * payload size supported.
+ */
+static void __devinit fixup_mpss_256(struct pci_dev *dev)
+{
+ dev->pcie_mpss = 1; /* 256 bytes */
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0, fixup_mpss_256);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000A_1, fixup_mpss_256);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
+ PCI_DEVICE_ID_SOLARFLARE_SFC4000B, fixup_mpss_256);
+
+/* Intel 5000 and 5100 Memory controllers have an errata with read completion
+ * coalescing (which is enabled by default on some BIOSes) and MPS of 256B.
+ * Since there is no way of knowing what the PCIE MPS on each fabric will be
+ * until all of the devices are discovered and buses walked, read completion
+ * coalescing must be disabled. Unfortunately, it cannot be re-enabled because
+ * it is possible to hotplug a device with MPS of 256B.
+ */
+static void __devinit quirk_intel_mc_errata(struct pci_dev *dev)
+{
+ int err;
+ u16 rcc;
+
+ if (pcie_bus_config == PCIE_BUS_TUNE_OFF)
+ return;
+
+ /* Intel errata specifies bits to change but does not say what they are.
+ * Keeping them magical until such time as the registers and values can
+ * be explained.
+ */
+ err = pci_read_config_word(dev, 0x48, &rcc);
+ if (err) {
+ dev_err(&dev->dev, "Error attempting to read the read "
+ "completion coalescing register.\n");
+ return;
+ }
+
+ if (!(rcc & (1 << 10)))
+ return;
+
+ rcc &= ~(1 << 10);
+
+ err = pci_write_config_word(dev, 0x48, rcc);
+ if (err) {
+ dev_err(&dev->dev, "Error attempting to write the read "
+ "completion coalescing register.\n");
+ return;
+ }
+
+ pr_info_once("Read completion coalescing disabled due to hardware "
+ "errata relating to 256B MPS.\n");
+}
+/* Intel 5000 series memory controllers and ports 2-7 */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25c0, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25d0, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25d4, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25d8, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e2, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e3, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e4, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e5, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e6, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25e7, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25f7, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25f8, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25f9, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25fa, quirk_intel_mc_errata);
+/* Intel 5100 series memory controllers and ports 2-7 */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65c0, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e2, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e3, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e4, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e5, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e6, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65e7, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f7, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f8, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata);
+
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
struct pci_fixup *end)
{
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 784da9d36029..86b69f85f900 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -426,7 +426,7 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
}
-static void pci_setup_bridge(struct pci_bus *bus)
+void pci_setup_bridge(struct pci_bus *bus)
{
unsigned long type = IORESOURCE_IO | IORESOURCE_MEM |
IORESOURCE_PREFETCH;
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 6fa215a38615..90832a955991 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -400,9 +400,8 @@ static int pcifront_claim_resource(struct pci_dev *dev, void *data)
dev_info(&pdev->xdev->dev, "claiming resource %s/%d\n",
pci_name(dev), i);
if (pci_claim_resource(dev, i)) {
- dev_err(&pdev->xdev->dev, "Could not claim "
- "resource %s/%d! Device offline. Try "
- "giving less than 4GB to domain.\n",
+ dev_err(&pdev->xdev->dev, "Could not claim resource %s/%d! "
+ "Device offline. Try using e820_host=1 in the guest config.\n",
pci_name(dev), i);
}
}
diff --git a/drivers/pcmcia/pxa2xx_balloon3.c b/drivers/pcmcia/pxa2xx_balloon3.c
index f56d7de7c751..22a75e610f12 100644
--- a/drivers/pcmcia/pxa2xx_balloon3.c
+++ b/drivers/pcmcia/pxa2xx_balloon3.c
@@ -97,7 +97,7 @@ static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
const socket_state_t *state)
{
- __raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG |
+ __raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG +
((state->flags & SS_RESET) ?
BALLOON3_FPGA_SETnCLR : 0));
return 0;
diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c
index e956f659089a..66ab92cf3105 100644
--- a/drivers/pcmcia/pxa2xx_vpac270.c
+++ b/drivers/pcmcia/pxa2xx_vpac270.c
@@ -17,7 +17,7 @@
#include <asm/mach-types.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <mach/vpac270.h>
#include "soc_common.h"
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index c998f7aaadbc..0fac9658b020 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -15,10 +15,6 @@
#include <mach/simpad.h>
#include "sa1100_generic.h"
-extern long get_cs3_shadow(void);
-extern void set_cs3_bit(int value);
-extern void clear_cs3_bit(int value);
-
static struct pcmcia_irqs irqs[] = {
{ 1, IRQ_GPIO_CF_CD, "CF_CD" },
};
@@ -26,7 +22,7 @@ static struct pcmcia_irqs irqs[] = {
static int simpad_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+ simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
skt->socket.pci_irq = IRQ_GPIO_CF_IRQ;
@@ -38,8 +34,8 @@ static void simpad_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* Disable CF bus: */
- //set_cs3_bit(PCMCIA_BUFF_DIS);
- clear_cs3_bit(PCMCIA_RESET);
+ /*simpad_set_cs3_bit(PCMCIA_BUFF_DIS);*/
+ simpad_clear_cs3_bit(PCMCIA_RESET);
}
static void
@@ -47,15 +43,16 @@ simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
struct pcmcia_state *state)
{
unsigned long levels = GPLR;
- long cs3reg = get_cs3_shadow();
+ long cs3reg = simpad_get_cs3_ro();
state->detect=((levels & GPIO_CF_CD)==0)?1:0;
state->ready=(levels & GPIO_CF_IRQ)?1:0;
- state->bvd1=1; /* Not available on Simpad. */
- state->bvd2=1; /* Not available on Simpad. */
+ state->bvd1 = 1; /* Might be cs3reg & PCMCIA_BVD1 */
+ state->bvd2 = 1; /* Might be cs3reg & PCMCIA_BVD2 */
state->wrprot=0; /* Not available on Simpad. */
-
- if((cs3reg & 0x0c) == 0x0c) {
+
+ if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) ==
+ (PCMCIA_VS1|PCMCIA_VS2)) {
state->vs_3v=0;
state->vs_Xv=0;
} else {
@@ -75,23 +72,23 @@ simpad_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
/* Murphy: see table of MIC2562a-1 */
switch (state->Vcc) {
case 0:
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+ simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
break;
case 33:
- clear_cs3_bit(VCC_3V_EN|EN1);
- set_cs3_bit(VCC_5V_EN|EN0);
+ simpad_clear_cs3_bit(VCC_3V_EN|EN1);
+ simpad_set_cs3_bit(VCC_5V_EN|EN0);
break;
case 50:
- clear_cs3_bit(VCC_5V_EN|EN1);
- set_cs3_bit(VCC_3V_EN|EN0);
+ simpad_clear_cs3_bit(VCC_5V_EN|EN1);
+ simpad_set_cs3_bit(VCC_3V_EN|EN0);
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
__func__, state->Vcc);
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+ simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
local_irq_restore(flags);
return -1;
}
@@ -110,7 +107,7 @@ static void simpad_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
static void simpad_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
{
soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
- set_cs3_bit(PCMCIA_RESET);
+ simpad_set_cs3_bit(PCMCIA_RESET);
}
static struct pcmcia_low_level simpad_pcmcia_ops = {
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
new file mode 100644
index 000000000000..ef566443f945
--- /dev/null
+++ b/drivers/pinctrl/Kconfig
@@ -0,0 +1,43 @@
+#
+# PINCTRL infrastructure and drivers
+#
+
+menuconfig PINCTRL
+ bool "PINCTRL Support"
+ depends on EXPERIMENTAL
+ help
+ This enables the PINCTRL subsystem for controlling pins
+ on chip packages, for example multiplexing pins on primarily
+ PGA and BGA packages for systems on chip.
+
+ If unsure, say N.
+
+if PINCTRL
+
+config PINMUX
+ bool "Support pinmux controllers"
+ help
+ Say Y here if you want the pincontrol subsystem to handle pin
+ multiplexing drivers.
+
+config DEBUG_PINCTRL
+ bool "Debug PINCTRL calls"
+ depends on DEBUG_KERNEL
+ help
+ Say Y here to add some extra checks and diagnostics to PINCTRL calls.
+
+config PINMUX_SIRF
+ bool "CSR SiRFprimaII pinmux driver"
+ depends on ARCH_PRIMA2
+ select PINMUX
+ help
+ Say Y here to enable the SiRFprimaII pinmux driver
+
+config PINMUX_U300
+ bool "U300 pinmux driver"
+ depends on ARCH_U300
+ select PINMUX
+ help
+ Say Y here to enable the U300 pinmux driver
+
+endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
new file mode 100644
index 000000000000..bdc548a6b7e9
--- /dev/null
+++ b/drivers/pinctrl/Makefile
@@ -0,0 +1,8 @@
+# generic pinmux support
+
+ccflags-$(CONFIG_DEBUG_PINMUX) += -DDEBUG
+
+obj-$(CONFIG_PINCTRL) += core.o
+obj-$(CONFIG_PINMUX) += pinmux.o
+obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o
+obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
new file mode 100644
index 000000000000..423522d87313
--- /dev/null
+++ b/drivers/pinctrl/core.c
@@ -0,0 +1,598 @@
+/*
+ * Core driver for the pin control subsystem
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ * Based on bits of regulator core, gpio core and clk core
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#define pr_fmt(fmt) "pinctrl core: " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/radix-tree.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/machine.h>
+#include "core.h"
+#include "pinmux.h"
+
+/* Global list of pin control devices */
+static DEFINE_MUTEX(pinctrldev_list_mutex);
+static LIST_HEAD(pinctrldev_list);
+
+static void pinctrl_dev_release(struct device *dev)
+{
+ struct pinctrl_dev *pctldev = dev_get_drvdata(dev);
+ kfree(pctldev);
+}
+
+const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev)
+{
+ /* We're not allowed to register devices without name */
+ return pctldev->desc->name;
+}
+EXPORT_SYMBOL_GPL(pinctrl_dev_get_name);
+
+void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev)
+{
+ return pctldev->driver_data;
+}
+EXPORT_SYMBOL_GPL(pinctrl_dev_get_drvdata);
+
+/**
+ * get_pinctrl_dev_from_dev() - look up pin controller device
+ * @dev: a device pointer, this may be NULL but then devname needs to be
+ * defined instead
+ * @devname: the name of a device instance, as returned by dev_name(), this
+ * may be NULL but then dev needs to be defined instead
+ *
+ * Looks up a pin control device matching a certain device name or pure device
+ * pointer, the pure device pointer will take precedence.
+ */
+struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,
+ const char *devname)
+{
+ struct pinctrl_dev *pctldev = NULL;
+ bool found = false;
+
+ mutex_lock(&pinctrldev_list_mutex);
+ list_for_each_entry(pctldev, &pinctrldev_list, node) {
+ if (dev && &pctldev->dev == dev) {
+ /* Matched on device pointer */
+ found = true;
+ break;
+ }
+
+ if (devname &&
+ !strcmp(dev_name(&pctldev->dev), devname)) {
+ /* Matched on device name */
+ found = true;
+ break;
+ }
+ }
+ mutex_unlock(&pinctrldev_list_mutex);
+
+ return found ? pctldev : NULL;
+}
+
+struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin)
+{
+ struct pin_desc *pindesc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pctldev->pin_desc_tree_lock, flags);
+ pindesc = radix_tree_lookup(&pctldev->pin_desc_tree, pin);
+ spin_unlock_irqrestore(&pctldev->pin_desc_tree_lock, flags);
+
+ return pindesc;
+}
+
+/**
+ * pin_is_valid() - check if pin exists on controller
+ * @pctldev: the pin control device to check the pin on
+ * @pin: pin to check, use the local pin controller index number
+ *
+ * This tells us whether a certain pin exist on a certain pin controller or
+ * not. Pin lists may be sparse, so some pins may not exist.
+ */
+bool pin_is_valid(struct pinctrl_dev *pctldev, int pin)
+{
+ struct pin_desc *pindesc;
+
+ if (pin < 0)
+ return false;
+
+ pindesc = pin_desc_get(pctldev, pin);
+ if (pindesc == NULL)
+ return false;
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(pin_is_valid);
+
+/* Deletes a range of pin descriptors */
+static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev,
+ const struct pinctrl_pin_desc *pins,
+ unsigned num_pins)
+{
+ int i;
+
+ spin_lock(&pctldev->pin_desc_tree_lock);
+ for (i = 0; i < num_pins; i++) {
+ struct pin_desc *pindesc;
+
+ pindesc = radix_tree_lookup(&pctldev->pin_desc_tree,
+ pins[i].number);
+ if (pindesc != NULL) {
+ radix_tree_delete(&pctldev->pin_desc_tree,
+ pins[i].number);
+ }
+ kfree(pindesc);
+ }
+ spin_unlock(&pctldev->pin_desc_tree_lock);
+}
+
+static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
+ unsigned number, const char *name)
+{
+ struct pin_desc *pindesc;
+
+ pindesc = pin_desc_get(pctldev, number);
+ if (pindesc != NULL) {
+ pr_err("pin %d already registered on %s\n", number,
+ pctldev->desc->name);
+ return -EINVAL;
+ }
+
+ pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL);
+ if (pindesc == NULL)
+ return -ENOMEM;
+ spin_lock_init(&pindesc->lock);
+
+ /* Set owner */
+ pindesc->pctldev = pctldev;
+
+ /* Copy basic pin info */
+ pindesc->name = name;
+
+ spin_lock(&pctldev->pin_desc_tree_lock);
+ radix_tree_insert(&pctldev->pin_desc_tree, number, pindesc);
+ spin_unlock(&pctldev->pin_desc_tree_lock);
+ pr_debug("registered pin %d (%s) on %s\n",
+ number, name ? name : "(unnamed)", pctldev->desc->name);
+ return 0;
+}
+
+static int pinctrl_register_pins(struct pinctrl_dev *pctldev,
+ struct pinctrl_pin_desc const *pins,
+ unsigned num_descs)
+{
+ unsigned i;
+ int ret = 0;
+
+ for (i = 0; i < num_descs; i++) {
+ ret = pinctrl_register_one_pin(pctldev,
+ pins[i].number, pins[i].name);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * pinctrl_match_gpio_range() - check if a certain GPIO pin is in range
+ * @pctldev: pin controller device to check
+ * @gpio: gpio pin to check taken from the global GPIO pin space
+ *
+ * Tries to match a GPIO pin number to the ranges handled by a certain pin
+ * controller, return the range or NULL
+ */
+static struct pinctrl_gpio_range *
+pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio)
+{
+ struct pinctrl_gpio_range *range = NULL;
+
+ /* Loop over the ranges */
+ mutex_lock(&pctldev->gpio_ranges_lock);
+ list_for_each_entry(range, &pctldev->gpio_ranges, node) {
+ /* Check if we're in the valid range */
+ if (gpio >= range->base &&
+ gpio < range->base + range->npins) {
+ mutex_unlock(&pctldev->gpio_ranges_lock);
+ return range;
+ }
+ }
+ mutex_unlock(&pctldev->gpio_ranges_lock);
+
+ return NULL;
+}
+
+/**
+ * pinctrl_get_device_gpio_range() - find device for GPIO range
+ * @gpio: the pin to locate the pin controller for
+ * @outdev: the pin control device if found
+ * @outrange: the GPIO range if found
+ *
+ * Find the pin controller handling a certain GPIO pin from the pinspace of
+ * the GPIO subsystem, return the device and the matching GPIO range. Returns
+ * negative if the GPIO range could not be found in any device.
+ */
+int pinctrl_get_device_gpio_range(unsigned gpio,
+ struct pinctrl_dev **outdev,
+ struct pinctrl_gpio_range **outrange)
+{
+ struct pinctrl_dev *pctldev = NULL;
+
+ /* Loop over the pin controllers */
+ mutex_lock(&pinctrldev_list_mutex);
+ list_for_each_entry(pctldev, &pinctrldev_list, node) {
+ struct pinctrl_gpio_range *range;
+
+ range = pinctrl_match_gpio_range(pctldev, gpio);
+ if (range != NULL) {
+ *outdev = pctldev;
+ *outrange = range;
+ mutex_unlock(&pinctrldev_list_mutex);
+ return 0;
+ }
+ }
+ mutex_unlock(&pinctrldev_list_mutex);
+
+ return -EINVAL;
+}
+
+/**
+ * pinctrl_add_gpio_range() - register a GPIO range for a controller
+ * @pctldev: pin controller device to add the range to
+ * @range: the GPIO range to add
+ *
+ * This adds a range of GPIOs to be handled by a certain pin controller. Call
+ * this to register handled ranges after registering your pin controller.
+ */
+void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range)
+{
+ mutex_lock(&pctldev->gpio_ranges_lock);
+ list_add(&range->node, &pctldev->gpio_ranges);
+ mutex_unlock(&pctldev->gpio_ranges_lock);
+}
+
+/**
+ * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller
+ * @pctldev: pin controller device to remove the range from
+ * @range: the GPIO range to remove
+ */
+void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range)
+{
+ mutex_lock(&pctldev->gpio_ranges_lock);
+ list_del(&range->node);
+ mutex_unlock(&pctldev->gpio_ranges_lock);
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+static int pinctrl_pins_show(struct seq_file *s, void *what)
+{
+ struct pinctrl_dev *pctldev = s->private;
+ const struct pinctrl_ops *ops = pctldev->desc->pctlops;
+ unsigned pin;
+
+ seq_printf(s, "registered pins: %d\n", pctldev->desc->npins);
+ seq_printf(s, "max pin number: %d\n", pctldev->desc->maxpin);
+
+ /* The highest pin number need to be included in the loop, thus <= */
+ for (pin = 0; pin <= pctldev->desc->maxpin; pin++) {
+ struct pin_desc *desc;
+
+ desc = pin_desc_get(pctldev, pin);
+ /* Pin space may be sparse */
+ if (desc == NULL)
+ continue;
+
+ seq_printf(s, "pin %d (%s) ", pin,
+ desc->name ? desc->name : "unnamed");
+
+ /* Driver-specific info per pin */
+ if (ops->pin_dbg_show)
+ ops->pin_dbg_show(pctldev, s, pin);
+
+ seq_puts(s, "\n");
+ }
+
+ return 0;
+}
+
+static int pinctrl_groups_show(struct seq_file *s, void *what)
+{
+ struct pinctrl_dev *pctldev = s->private;
+ const struct pinctrl_ops *ops = pctldev->desc->pctlops;
+ unsigned selector = 0;
+
+ /* No grouping */
+ if (!ops)
+ return 0;
+
+ seq_puts(s, "registered pin groups:\n");
+ while (ops->list_groups(pctldev, selector) >= 0) {
+ const unsigned *pins;
+ unsigned num_pins;
+ const char *gname = ops->get_group_name(pctldev, selector);
+ int ret;
+ int i;
+
+ ret = ops->get_group_pins(pctldev, selector,
+ &pins, &num_pins);
+ if (ret)
+ seq_printf(s, "%s [ERROR GETTING PINS]\n",
+ gname);
+ else {
+ seq_printf(s, "group: %s, pins = [ ", gname);
+ for (i = 0; i < num_pins; i++)
+ seq_printf(s, "%d ", pins[i]);
+ seq_puts(s, "]\n");
+ }
+ selector++;
+ }
+
+
+ return 0;
+}
+
+static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
+{
+ struct pinctrl_dev *pctldev = s->private;
+ struct pinctrl_gpio_range *range = NULL;
+
+ seq_puts(s, "GPIO ranges handled:\n");
+
+ /* Loop over the ranges */
+ mutex_lock(&pctldev->gpio_ranges_lock);
+ list_for_each_entry(range, &pctldev->gpio_ranges, node) {
+ seq_printf(s, "%u: %s [%u - %u]\n", range->id, range->name,
+ range->base, (range->base + range->npins - 1));
+ }
+ mutex_unlock(&pctldev->gpio_ranges_lock);
+
+ return 0;
+}
+
+static int pinctrl_devices_show(struct seq_file *s, void *what)
+{
+ struct pinctrl_dev *pctldev;
+
+ seq_puts(s, "name [pinmux]\n");
+ mutex_lock(&pinctrldev_list_mutex);
+ list_for_each_entry(pctldev, &pinctrldev_list, node) {
+ seq_printf(s, "%s ", pctldev->desc->name);
+ if (pctldev->desc->pmxops)
+ seq_puts(s, "yes");
+ else
+ seq_puts(s, "no");
+ seq_puts(s, "\n");
+ }
+ mutex_unlock(&pinctrldev_list_mutex);
+
+ return 0;
+}
+
+static int pinctrl_pins_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinctrl_pins_show, inode->i_private);
+}
+
+static int pinctrl_groups_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinctrl_groups_show, inode->i_private);
+}
+
+static int pinctrl_gpioranges_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinctrl_gpioranges_show, inode->i_private);
+}
+
+static int pinctrl_devices_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinctrl_devices_show, NULL);
+}
+
+static const struct file_operations pinctrl_pins_ops = {
+ .open = pinctrl_pins_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinctrl_groups_ops = {
+ .open = pinctrl_groups_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinctrl_gpioranges_ops = {
+ .open = pinctrl_gpioranges_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinctrl_devices_ops = {
+ .open = pinctrl_devices_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct dentry *debugfs_root;
+
+static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
+{
+ static struct dentry *device_root;
+
+ device_root = debugfs_create_dir(dev_name(&pctldev->dev),
+ debugfs_root);
+ if (IS_ERR(device_root) || !device_root) {
+ pr_warn("failed to create debugfs directory for %s\n",
+ dev_name(&pctldev->dev));
+ return;
+ }
+ debugfs_create_file("pins", S_IFREG | S_IRUGO,
+ device_root, pctldev, &pinctrl_pins_ops);
+ debugfs_create_file("pingroups", S_IFREG | S_IRUGO,
+ device_root, pctldev, &pinctrl_groups_ops);
+ debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO,
+ device_root, pctldev, &pinctrl_gpioranges_ops);
+ pinmux_init_device_debugfs(device_root, pctldev);
+}
+
+static void pinctrl_init_debugfs(void)
+{
+ debugfs_root = debugfs_create_dir("pinctrl", NULL);
+ if (IS_ERR(debugfs_root) || !debugfs_root) {
+ pr_warn("failed to create debugfs directory\n");
+ debugfs_root = NULL;
+ return;
+ }
+
+ debugfs_create_file("pinctrl-devices", S_IFREG | S_IRUGO,
+ debugfs_root, NULL, &pinctrl_devices_ops);
+ pinmux_init_debugfs(debugfs_root);
+}
+
+#else /* CONFIG_DEBUG_FS */
+
+static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
+{
+}
+
+static void pinctrl_init_debugfs(void)
+{
+}
+
+#endif
+
+/**
+ * pinctrl_register() - register a pin controller device
+ * @pctldesc: descriptor for this pin controller
+ * @dev: parent device for this pin controller
+ * @driver_data: private pin controller data for this pin controller
+ */
+struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
+ struct device *dev, void *driver_data)
+{
+ static atomic_t pinmux_no = ATOMIC_INIT(0);
+ struct pinctrl_dev *pctldev;
+ int ret;
+
+ if (pctldesc == NULL)
+ return NULL;
+ if (pctldesc->name == NULL)
+ return NULL;
+
+ /* If we're implementing pinmuxing, check the ops for sanity */
+ if (pctldesc->pmxops) {
+ ret = pinmux_check_ops(pctldesc->pmxops);
+ if (ret) {
+ pr_err("%s pinmux ops lacks necessary functions\n",
+ pctldesc->name);
+ return NULL;
+ }
+ }
+
+ pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
+ if (pctldev == NULL)
+ return NULL;
+
+ /* Initialize pin control device struct */
+ pctldev->owner = pctldesc->owner;
+ pctldev->desc = pctldesc;
+ pctldev->driver_data = driver_data;
+ INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
+ spin_lock_init(&pctldev->pin_desc_tree_lock);
+ INIT_LIST_HEAD(&pctldev->gpio_ranges);
+ mutex_init(&pctldev->gpio_ranges_lock);
+
+ /* Register device */
+ pctldev->dev.parent = dev;
+ dev_set_name(&pctldev->dev, "pinctrl.%d",
+ atomic_inc_return(&pinmux_no) - 1);
+ pctldev->dev.release = pinctrl_dev_release;
+ ret = device_register(&pctldev->dev);
+ if (ret != 0) {
+ pr_err("error in device registration\n");
+ goto out_reg_dev_err;
+ }
+ dev_set_drvdata(&pctldev->dev, pctldev);
+
+ /* Register all the pins */
+ pr_debug("try to register %d pins on %s...\n",
+ pctldesc->npins, pctldesc->name);
+ ret = pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);
+ if (ret) {
+ pr_err("error during pin registration\n");
+ pinctrl_free_pindescs(pctldev, pctldesc->pins,
+ pctldesc->npins);
+ goto out_reg_pins_err;
+ }
+
+ pinctrl_init_device_debugfs(pctldev);
+ mutex_lock(&pinctrldev_list_mutex);
+ list_add(&pctldev->node, &pinctrldev_list);
+ mutex_unlock(&pinctrldev_list_mutex);
+ pinmux_hog_maps(pctldev);
+ return pctldev;
+
+out_reg_pins_err:
+ device_del(&pctldev->dev);
+out_reg_dev_err:
+ put_device(&pctldev->dev);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(pinctrl_register);
+
+/**
+ * pinctrl_unregister() - unregister pinmux
+ * @pctldev: pin controller to unregister
+ *
+ * Called by pinmux drivers to unregister a pinmux.
+ */
+void pinctrl_unregister(struct pinctrl_dev *pctldev)
+{
+ if (pctldev == NULL)
+ return;
+
+ pinmux_unhog_maps(pctldev);
+ /* TODO: check that no pinmuxes are still active? */
+ mutex_lock(&pinctrldev_list_mutex);
+ list_del(&pctldev->node);
+ mutex_unlock(&pinctrldev_list_mutex);
+ /* Destroy descriptor tree */
+ pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
+ pctldev->desc->npins);
+ device_unregister(&pctldev->dev);
+}
+EXPORT_SYMBOL_GPL(pinctrl_unregister);
+
+static int __init pinctrl_init(void)
+{
+ pr_info("initialized pinctrl subsystem\n");
+ pinctrl_init_debugfs();
+ return 0;
+}
+
+/* init early since many drivers really need to initialized pinmux early */
+core_initcall(pinctrl_init);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
new file mode 100644
index 000000000000..472fa1341cc0
--- /dev/null
+++ b/drivers/pinctrl/core.h
@@ -0,0 +1,71 @@
+/*
+ * Core private header for the pin control subsystem
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+/**
+ * struct pinctrl_dev - pin control class device
+ * @node: node to include this pin controller in the global pin controller list
+ * @desc: the pin controller descriptor supplied when initializing this pin
+ * controller
+ * @pin_desc_tree: each pin descriptor for this pin controller is stored in
+ * this radix tree
+ * @pin_desc_tree_lock: lock for the descriptor tree
+ * @gpio_ranges: a list of GPIO ranges that is handled by this pin controller,
+ * ranges are added to this list at runtime
+ * @gpio_ranges_lock: lock for the GPIO ranges list
+ * @dev: the device entry for this pin controller
+ * @owner: module providing the pin controller, used for refcounting
+ * @driver_data: driver data for drivers registering to the pin controller
+ * subsystem
+ * @pinmux_hogs_lock: lock for the pinmux hog list
+ * @pinmux_hogs: list of pinmux maps hogged by this device
+ */
+struct pinctrl_dev {
+ struct list_head node;
+ struct pinctrl_desc *desc;
+ struct radix_tree_root pin_desc_tree;
+ spinlock_t pin_desc_tree_lock;
+ struct list_head gpio_ranges;
+ struct mutex gpio_ranges_lock;
+ struct device dev;
+ struct module *owner;
+ void *driver_data;
+#ifdef CONFIG_PINMUX
+ struct mutex pinmux_hogs_lock;
+ struct list_head pinmux_hogs;
+#endif
+};
+
+/**
+ * struct pin_desc - pin descriptor for each physical pin in the arch
+ * @pctldev: corresponding pin control device
+ * @name: a name for the pin, e.g. the name of the pin/pad/finger on a
+ * datasheet or such
+ * @lock: a lock to protect the descriptor structure
+ * @mux_requested: whether the pin is already requested by pinmux or not
+ * @mux_function: a named muxing function for the pin that will be passed to
+ * subdrivers and shown in debugfs etc
+ */
+struct pin_desc {
+ struct pinctrl_dev *pctldev;
+ const char *name;
+ spinlock_t lock;
+ /* These fields only added when supporting pinmux drivers */
+#ifdef CONFIG_PINMUX
+ const char *mux_function;
+#endif
+};
+
+struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,
+ const char *dev_name);
+struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin);
+int pinctrl_get_device_gpio_range(unsigned gpio,
+ struct pinctrl_dev **outdev,
+ struct pinctrl_gpio_range **outrange);
diff --git a/drivers/pinctrl/pinmux-sirf.c b/drivers/pinctrl/pinmux-sirf.c
new file mode 100644
index 000000000000..d76cae620956
--- /dev/null
+++ b/drivers/pinctrl/pinmux-sirf.c
@@ -0,0 +1,1215 @@
+/*
+ * pinmux driver for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/bitops.h>
+
+#define DRIVER_NAME "pinmux-sirf"
+
+#define SIRFSOC_NUM_PADS 622
+#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
+#define SIRFSOC_RSC_PIN_MUX 0x4
+
+/*
+ * pad list for the pinmux subsystem
+ * refer to CS-131858-DC-6A.xls
+ */
+static const struct pinctrl_pin_desc sirfsoc_pads[] = {
+ PINCTRL_PIN(4, "pwm0"),
+ PINCTRL_PIN(5, "pwm1"),
+ PINCTRL_PIN(6, "pwm2"),
+ PINCTRL_PIN(7, "pwm3"),
+ PINCTRL_PIN(8, "warm_rst_b"),
+ PINCTRL_PIN(9, "odo_0"),
+ PINCTRL_PIN(10, "odo_1"),
+ PINCTRL_PIN(11, "dr_dir"),
+ PINCTRL_PIN(13, "scl_1"),
+ PINCTRL_PIN(15, "sda_1"),
+ PINCTRL_PIN(16, "x_ldd[16]"),
+ PINCTRL_PIN(17, "x_ldd[17]"),
+ PINCTRL_PIN(18, "x_ldd[18]"),
+ PINCTRL_PIN(19, "x_ldd[19]"),
+ PINCTRL_PIN(20, "x_ldd[20]"),
+ PINCTRL_PIN(21, "x_ldd[21]"),
+ PINCTRL_PIN(22, "x_ldd[22]"),
+ PINCTRL_PIN(23, "x_ldd[23], lcdrom_frdy"),
+ PINCTRL_PIN(24, "gps_sgn"),
+ PINCTRL_PIN(25, "gps_mag"),
+ PINCTRL_PIN(26, "gps_clk"),
+ PINCTRL_PIN(27, "sd_cd_b_1"),
+ PINCTRL_PIN(28, "sd_vcc_on_1"),
+ PINCTRL_PIN(29, "sd_wp_b_1"),
+ PINCTRL_PIN(30, "sd_clk_3"),
+ PINCTRL_PIN(31, "sd_cmd_3"),
+
+ PINCTRL_PIN(32, "x_sd_dat_3[0]"),
+ PINCTRL_PIN(33, "x_sd_dat_3[1]"),
+ PINCTRL_PIN(34, "x_sd_dat_3[2]"),
+ PINCTRL_PIN(35, "x_sd_dat_3[3]"),
+ PINCTRL_PIN(36, "x_sd_clk_4"),
+ PINCTRL_PIN(37, "x_sd_cmd_4"),
+ PINCTRL_PIN(38, "x_sd_dat_4[0]"),
+ PINCTRL_PIN(39, "x_sd_dat_4[1]"),
+ PINCTRL_PIN(40, "x_sd_dat_4[2]"),
+ PINCTRL_PIN(41, "x_sd_dat_4[3]"),
+ PINCTRL_PIN(42, "x_cko_1"),
+ PINCTRL_PIN(43, "x_ac97_bit_clk"),
+ PINCTRL_PIN(44, "x_ac97_dout"),
+ PINCTRL_PIN(45, "x_ac97_din"),
+ PINCTRL_PIN(46, "x_ac97_sync"),
+ PINCTRL_PIN(47, "x_txd_1"),
+ PINCTRL_PIN(48, "x_txd_2"),
+ PINCTRL_PIN(49, "x_rxd_1"),
+ PINCTRL_PIN(50, "x_rxd_2"),
+ PINCTRL_PIN(51, "x_usclk_0"),
+ PINCTRL_PIN(52, "x_utxd_0"),
+ PINCTRL_PIN(53, "x_urxd_0"),
+ PINCTRL_PIN(54, "x_utfs_0"),
+ PINCTRL_PIN(55, "x_urfs_0"),
+ PINCTRL_PIN(56, "x_usclk_1"),
+ PINCTRL_PIN(57, "x_utxd_1"),
+ PINCTRL_PIN(58, "x_urxd_1"),
+ PINCTRL_PIN(59, "x_utfs_1"),
+ PINCTRL_PIN(60, "x_urfs_1"),
+ PINCTRL_PIN(61, "x_usclk_2"),
+ PINCTRL_PIN(62, "x_utxd_2"),
+ PINCTRL_PIN(63, "x_urxd_2"),
+
+ PINCTRL_PIN(64, "x_utfs_2"),
+ PINCTRL_PIN(65, "x_urfs_2"),
+ PINCTRL_PIN(66, "x_df_we_b"),
+ PINCTRL_PIN(67, "x_df_re_b"),
+ PINCTRL_PIN(68, "x_txd_0"),
+ PINCTRL_PIN(69, "x_rxd_0"),
+ PINCTRL_PIN(78, "x_cko_0"),
+ PINCTRL_PIN(79, "x_vip_pxd[7]"),
+ PINCTRL_PIN(80, "x_vip_pxd[6]"),
+ PINCTRL_PIN(81, "x_vip_pxd[5]"),
+ PINCTRL_PIN(82, "x_vip_pxd[4]"),
+ PINCTRL_PIN(83, "x_vip_pxd[3]"),
+ PINCTRL_PIN(84, "x_vip_pxd[2]"),
+ PINCTRL_PIN(85, "x_vip_pxd[1]"),
+ PINCTRL_PIN(86, "x_vip_pxd[0]"),
+ PINCTRL_PIN(87, "x_vip_vsync"),
+ PINCTRL_PIN(88, "x_vip_hsync"),
+ PINCTRL_PIN(89, "x_vip_pxclk"),
+ PINCTRL_PIN(90, "x_sda_0"),
+ PINCTRL_PIN(91, "x_scl_0"),
+ PINCTRL_PIN(92, "x_df_ry_by"),
+ PINCTRL_PIN(93, "x_df_cs_b[1]"),
+ PINCTRL_PIN(94, "x_df_cs_b[0]"),
+ PINCTRL_PIN(95, "x_l_pclk"),
+
+ PINCTRL_PIN(96, "x_l_lck"),
+ PINCTRL_PIN(97, "x_l_fck"),
+ PINCTRL_PIN(98, "x_l_de"),
+ PINCTRL_PIN(99, "x_ldd[0]"),
+ PINCTRL_PIN(100, "x_ldd[1]"),
+ PINCTRL_PIN(101, "x_ldd[2]"),
+ PINCTRL_PIN(102, "x_ldd[3]"),
+ PINCTRL_PIN(103, "x_ldd[4]"),
+ PINCTRL_PIN(104, "x_ldd[5]"),
+ PINCTRL_PIN(105, "x_ldd[6]"),
+ PINCTRL_PIN(106, "x_ldd[7]"),
+ PINCTRL_PIN(107, "x_ldd[8]"),
+ PINCTRL_PIN(108, "x_ldd[9]"),
+ PINCTRL_PIN(109, "x_ldd[10]"),
+ PINCTRL_PIN(110, "x_ldd[11]"),
+ PINCTRL_PIN(111, "x_ldd[12]"),
+ PINCTRL_PIN(112, "x_ldd[13]"),
+ PINCTRL_PIN(113, "x_ldd[14]"),
+ PINCTRL_PIN(114, "x_ldd[15]"),
+};
+
+/**
+ * @dev: a pointer back to containing device
+ * @virtbase: the offset to the controller in virtual memory
+ */
+struct sirfsoc_pmx {
+ struct device *dev;
+ struct pinctrl_dev *pmx;
+ void __iomem *gpio_virtbase;
+ void __iomem *rsc_virtbase;
+};
+
+/* SIRFSOC_GPIO_PAD_EN set */
+struct sirfsoc_muxmask {
+ unsigned long group;
+ unsigned long mask;
+};
+
+struct sirfsoc_padmux {
+ unsigned long muxmask_counts;
+ const struct sirfsoc_muxmask *muxmask;
+ /* RSC_PIN_MUX set */
+ unsigned long funcmask;
+ unsigned long funcval;
+};
+
+ /**
+ * struct sirfsoc_pin_group - describes a SiRFprimaII pin group
+ * @name: the name of this specific pin group
+ * @pins: an array of discrete physical pins used in this group, taken
+ * from the driver-local pin enumeration space
+ * @num_pins: the number of pins in this group array, i.e. the number of
+ * elements in .pins so we can iterate over that array
+ */
+struct sirfsoc_pin_group {
+ const char *name;
+ const unsigned int *pins;
+ const unsigned num_pins;
+};
+
+static const struct sirfsoc_muxmask lcd_16bits_sirfsoc_muxmask[] = {
+ {
+ .group = 3,
+ .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) |
+ BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
+ BIT(17) | BIT(18),
+ }, {
+ .group = 2,
+ .mask = BIT(31),
+ },
+};
+
+static const struct sirfsoc_padmux lcd_16bits_padmux = {
+ .muxmask_counts = ARRAY_SIZE(lcd_16bits_sirfsoc_muxmask),
+ .muxmask = lcd_16bits_sirfsoc_muxmask,
+ .funcmask = BIT(4),
+ .funcval = 0,
+};
+
+static const unsigned lcd_16bits_pins[] = { 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114 };
+
+static const struct sirfsoc_muxmask lcd_18bits_muxmask[] = {
+ {
+ .group = 3,
+ .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) |
+ BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
+ BIT(17) | BIT(18),
+ }, {
+ .group = 2,
+ .mask = BIT(31),
+ }, {
+ .group = 0,
+ .mask = BIT(16) | BIT(17),
+ },
+};
+
+static const struct sirfsoc_padmux lcd_18bits_padmux = {
+ .muxmask_counts = ARRAY_SIZE(lcd_18bits_muxmask),
+ .muxmask = lcd_18bits_muxmask,
+ .funcmask = BIT(4),
+ .funcval = 0,
+};
+
+static const unsigned lcd_18bits_pins[] = { 16, 17, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114};
+
+static const struct sirfsoc_muxmask lcd_24bits_muxmask[] = {
+ {
+ .group = 3,
+ .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) |
+ BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
+ BIT(17) | BIT(18),
+ }, {
+ .group = 2,
+ .mask = BIT(31),
+ }, {
+ .group = 0,
+ .mask = BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23),
+ },
+};
+
+static const struct sirfsoc_padmux lcd_24bits_padmux = {
+ .muxmask_counts = ARRAY_SIZE(lcd_24bits_muxmask),
+ .muxmask = lcd_24bits_muxmask,
+ .funcmask = BIT(4),
+ .funcval = 0,
+};
+
+static const unsigned lcd_24bits_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114 };
+
+static const struct sirfsoc_muxmask lcdrom_muxmask[] = {
+ {
+ .group = 3,
+ .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) |
+ BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
+ BIT(17) | BIT(18),
+ }, {
+ .group = 2,
+ .mask = BIT(31),
+ }, {
+ .group = 0,
+ .mask = BIT(23),
+ },
+};
+
+static const struct sirfsoc_padmux lcdrom_padmux = {
+ .muxmask_counts = ARRAY_SIZE(lcdrom_muxmask),
+ .muxmask = lcdrom_muxmask,
+ .funcmask = BIT(4),
+ .funcval = BIT(4),
+};
+
+static const unsigned lcdrom_pins[] = { 23, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114 };
+
+static const struct sirfsoc_muxmask uart0_muxmask[] = {
+ {
+ .group = 2,
+ .mask = BIT(4) | BIT(5),
+ }, {
+ .group = 1,
+ .mask = BIT(23) | BIT(28),
+ },
+};
+
+static const struct sirfsoc_padmux uart0_padmux = {
+ .muxmask_counts = ARRAY_SIZE(uart0_muxmask),
+ .muxmask = uart0_muxmask,
+ .funcmask = BIT(9),
+ .funcval = BIT(9),
+};
+
+static const unsigned uart0_pins[] = { 55, 60, 68, 69 };
+
+static const struct sirfsoc_muxmask uart0_nostreamctrl_muxmask[] = {
+ {
+ .group = 2,
+ .mask = BIT(4) | BIT(5),
+ },
+};
+
+static const struct sirfsoc_padmux uart0_nostreamctrl_padmux = {
+ .muxmask_counts = ARRAY_SIZE(uart0_nostreamctrl_muxmask),
+ .muxmask = uart0_nostreamctrl_muxmask,
+};
+
+static const unsigned uart0_nostreamctrl_pins[] = { 68, 39 };
+
+static const struct sirfsoc_muxmask uart1_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(15) | BIT(17),
+ },
+};
+
+static const struct sirfsoc_padmux uart1_padmux = {
+ .muxmask_counts = ARRAY_SIZE(uart1_muxmask),
+ .muxmask = uart1_muxmask,
+};
+
+static const unsigned uart1_pins[] = { 47, 49 };
+
+static const struct sirfsoc_muxmask uart2_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(16) | BIT(18) | BIT(24) | BIT(27),
+ },
+};
+
+static const struct sirfsoc_padmux uart2_padmux = {
+ .muxmask_counts = ARRAY_SIZE(uart2_muxmask),
+ .muxmask = uart2_muxmask,
+ .funcmask = BIT(10),
+ .funcval = BIT(10),
+};
+
+static const unsigned uart2_pins[] = { 48, 50, 56, 59 };
+
+static const struct sirfsoc_muxmask uart2_nostreamctrl_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(16) | BIT(18),
+ },
+};
+
+static const struct sirfsoc_padmux uart2_nostreamctrl_padmux = {
+ .muxmask_counts = ARRAY_SIZE(uart2_nostreamctrl_muxmask),
+ .muxmask = uart2_nostreamctrl_muxmask,
+};
+
+static const unsigned uart2_nostreamctrl_pins[] = { 48, 50 };
+
+static const struct sirfsoc_muxmask sdmmc3_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(30) | BIT(31),
+ }, {
+ .group = 1,
+ .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
+ },
+};
+
+static const struct sirfsoc_padmux sdmmc3_padmux = {
+ .muxmask_counts = ARRAY_SIZE(sdmmc3_muxmask),
+ .muxmask = sdmmc3_muxmask,
+ .funcmask = BIT(7),
+ .funcval = 0,
+};
+
+static const unsigned sdmmc3_pins[] = { 30, 31, 32, 33, 34, 35 };
+
+static const struct sirfsoc_muxmask spi0_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
+ },
+};
+
+static const struct sirfsoc_padmux spi0_padmux = {
+ .muxmask_counts = ARRAY_SIZE(spi0_muxmask),
+ .muxmask = spi0_muxmask,
+ .funcmask = BIT(7),
+ .funcval = BIT(7),
+};
+
+static const unsigned spi0_pins[] = { 32, 33, 34, 35 };
+
+static const struct sirfsoc_muxmask sdmmc4_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9),
+ },
+};
+
+static const struct sirfsoc_padmux sdmmc4_padmux = {
+ .muxmask_counts = ARRAY_SIZE(sdmmc4_muxmask),
+ .muxmask = sdmmc4_muxmask,
+};
+
+static const unsigned sdmmc4_pins[] = { 36, 37, 38, 39, 40, 41 };
+
+static const struct sirfsoc_muxmask cko1_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(10),
+ },
+};
+
+static const struct sirfsoc_padmux cko1_padmux = {
+ .muxmask_counts = ARRAY_SIZE(cko1_muxmask),
+ .muxmask = cko1_muxmask,
+ .funcmask = BIT(3),
+ .funcval = 0,
+};
+
+static const unsigned cko1_pins[] = { 42 };
+
+static const struct sirfsoc_muxmask i2s_muxmask[] = {
+ {
+ .group = 1,
+ .mask =
+ BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(19)
+ | BIT(23) | BIT(28),
+ },
+};
+
+static const struct sirfsoc_padmux i2s_padmux = {
+ .muxmask_counts = ARRAY_SIZE(i2s_muxmask),
+ .muxmask = i2s_muxmask,
+ .funcmask = BIT(3) | BIT(9),
+ .funcval = BIT(3),
+};
+
+static const unsigned i2s_pins[] = { 42, 43, 44, 45, 46, 51, 55, 60 };
+
+static const struct sirfsoc_muxmask ac97_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
+ },
+};
+
+static const struct sirfsoc_padmux ac97_padmux = {
+ .muxmask_counts = ARRAY_SIZE(ac97_muxmask),
+ .muxmask = ac97_muxmask,
+ .funcmask = BIT(8),
+ .funcval = 0,
+};
+
+static const unsigned ac97_pins[] = { 33, 34, 35, 36 };
+
+static const struct sirfsoc_muxmask spi1_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
+ },
+};
+
+static const struct sirfsoc_padmux spi1_padmux = {
+ .muxmask_counts = ARRAY_SIZE(spi1_muxmask),
+ .muxmask = spi1_muxmask,
+ .funcmask = BIT(8),
+ .funcval = BIT(8),
+};
+
+static const unsigned spi1_pins[] = { 33, 34, 35, 36 };
+
+static const struct sirfsoc_muxmask sdmmc1_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(27) | BIT(28) | BIT(29),
+ },
+};
+
+static const struct sirfsoc_padmux sdmmc1_padmux = {
+ .muxmask_counts = ARRAY_SIZE(sdmmc1_muxmask),
+ .muxmask = sdmmc1_muxmask,
+};
+
+static const unsigned sdmmc1_pins[] = { 27, 28, 29 };
+
+static const struct sirfsoc_muxmask gps_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(24) | BIT(25) | BIT(26),
+ },
+};
+
+static const struct sirfsoc_padmux gps_padmux = {
+ .muxmask_counts = ARRAY_SIZE(gps_muxmask),
+ .muxmask = gps_muxmask,
+ .funcmask = BIT(12) | BIT(13) | BIT(14),
+ .funcval = BIT(12),
+};
+
+static const unsigned gps_pins[] = { 24, 25, 26 };
+
+static const struct sirfsoc_muxmask sdmmc5_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(24) | BIT(25) | BIT(26),
+ }, {
+ .group = 1,
+ .mask = BIT(29),
+ }, {
+ .group = 2,
+ .mask = BIT(0) | BIT(1),
+ },
+};
+
+static const struct sirfsoc_padmux sdmmc5_padmux = {
+ .muxmask_counts = ARRAY_SIZE(sdmmc5_muxmask),
+ .muxmask = sdmmc5_muxmask,
+ .funcmask = BIT(13) | BIT(14),
+ .funcval = BIT(13) | BIT(14),
+};
+
+static const unsigned sdmmc5_pins[] = { 24, 25, 26, 61, 64, 65 };
+
+static const struct sirfsoc_muxmask usp0_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23),
+ },
+};
+
+static const struct sirfsoc_padmux usp0_padmux = {
+ .muxmask_counts = ARRAY_SIZE(usp0_muxmask),
+ .muxmask = usp0_muxmask,
+ .funcmask = BIT(1) | BIT(2) | BIT(6) | BIT(9),
+ .funcval = 0,
+};
+
+static const unsigned usp0_pins[] = { 51, 52, 53, 54, 55 };
+
+static const struct sirfsoc_muxmask usp1_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(24) | BIT(25) | BIT(26) | BIT(27) | BIT(28),
+ },
+};
+
+static const struct sirfsoc_padmux usp1_padmux = {
+ .muxmask_counts = ARRAY_SIZE(usp1_muxmask),
+ .muxmask = usp1_muxmask,
+ .funcmask = BIT(1) | BIT(9) | BIT(10) | BIT(11),
+ .funcval = 0,
+};
+
+static const unsigned usp1_pins[] = { 56, 57, 58, 59, 60 };
+
+static const struct sirfsoc_muxmask usp2_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(29) | BIT(30) | BIT(31),
+ }, {
+ .group = 2,
+ .mask = BIT(0) | BIT(1),
+ },
+};
+
+static const struct sirfsoc_padmux usp2_padmux = {
+ .muxmask_counts = ARRAY_SIZE(usp2_muxmask),
+ .muxmask = usp2_muxmask,
+ .funcmask = BIT(13) | BIT(14),
+ .funcval = 0,
+};
+
+static const unsigned usp2_pins[] = { 61, 62, 63, 64, 65 };
+
+static const struct sirfsoc_muxmask nand_muxmask[] = {
+ {
+ .group = 2,
+ .mask = BIT(2) | BIT(3) | BIT(28) | BIT(29) | BIT(30),
+ },
+};
+
+static const struct sirfsoc_padmux nand_padmux = {
+ .muxmask_counts = ARRAY_SIZE(nand_muxmask),
+ .muxmask = nand_muxmask,
+ .funcmask = BIT(5),
+ .funcval = 0,
+};
+
+static const unsigned nand_pins[] = { 64, 65, 92, 93, 94 };
+
+static const struct sirfsoc_padmux sdmmc0_padmux = {
+ .muxmask_counts = 0,
+ .funcmask = BIT(5),
+ .funcval = 0,
+};
+
+static const unsigned sdmmc0_pins[] = { };
+
+static const struct sirfsoc_muxmask sdmmc2_muxmask[] = {
+ {
+ .group = 2,
+ .mask = BIT(2) | BIT(3),
+ },
+};
+
+static const struct sirfsoc_padmux sdmmc2_padmux = {
+ .muxmask_counts = ARRAY_SIZE(sdmmc2_muxmask),
+ .muxmask = sdmmc2_muxmask,
+ .funcmask = BIT(5),
+ .funcval = BIT(5),
+};
+
+static const unsigned sdmmc2_pins[] = { 66, 67 };
+
+static const struct sirfsoc_muxmask cko0_muxmask[] = {
+ {
+ .group = 2,
+ .mask = BIT(14),
+ },
+};
+
+static const struct sirfsoc_padmux cko0_padmux = {
+ .muxmask_counts = ARRAY_SIZE(cko0_muxmask),
+ .muxmask = cko0_muxmask,
+};
+
+static const unsigned cko0_pins[] = { 78 };
+
+static const struct sirfsoc_muxmask vip_muxmask[] = {
+ {
+ .group = 2,
+ .mask = BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19)
+ | BIT(20) | BIT(21) | BIT(22) | BIT(23) | BIT(24) |
+ BIT(25),
+ },
+};
+
+static const struct sirfsoc_padmux vip_padmux = {
+ .muxmask_counts = ARRAY_SIZE(vip_muxmask),
+ .muxmask = vip_muxmask,
+ .funcmask = BIT(0),
+ .funcval = 0,
+};
+
+static const unsigned vip_pins[] = { 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 };
+
+static const struct sirfsoc_muxmask i2c0_muxmask[] = {
+ {
+ .group = 2,
+ .mask = BIT(26) | BIT(27),
+ },
+};
+
+static const struct sirfsoc_padmux i2c0_padmux = {
+ .muxmask_counts = ARRAY_SIZE(i2c0_muxmask),
+ .muxmask = i2c0_muxmask,
+};
+
+static const unsigned i2c0_pins[] = { 90, 91 };
+
+static const struct sirfsoc_muxmask i2c1_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(13) | BIT(15),
+ },
+};
+
+static const struct sirfsoc_padmux i2c1_padmux = {
+ .muxmask_counts = ARRAY_SIZE(i2c1_muxmask),
+ .muxmask = i2c1_muxmask,
+};
+
+static const unsigned i2c1_pins[] = { 13, 15 };
+
+static const struct sirfsoc_muxmask viprom_muxmask[] = {
+ {
+ .group = 2,
+ .mask = BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19)
+ | BIT(20) | BIT(21) | BIT(22) | BIT(23) | BIT(24) |
+ BIT(25),
+ }, {
+ .group = 0,
+ .mask = BIT(12),
+ },
+};
+
+static const struct sirfsoc_padmux viprom_padmux = {
+ .muxmask_counts = ARRAY_SIZE(viprom_muxmask),
+ .muxmask = viprom_muxmask,
+ .funcmask = BIT(0),
+ .funcval = BIT(0),
+};
+
+static const unsigned viprom_pins[] = { 12, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 };
+
+static const struct sirfsoc_muxmask pwm0_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(4),
+ },
+};
+
+static const struct sirfsoc_padmux pwm0_padmux = {
+ .muxmask_counts = ARRAY_SIZE(pwm0_muxmask),
+ .muxmask = pwm0_muxmask,
+ .funcmask = BIT(12),
+ .funcval = 0,
+};
+
+static const unsigned pwm0_pins[] = { 4 };
+
+static const struct sirfsoc_muxmask pwm1_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(5),
+ },
+};
+
+static const struct sirfsoc_padmux pwm1_padmux = {
+ .muxmask_counts = ARRAY_SIZE(pwm1_muxmask),
+ .muxmask = pwm1_muxmask,
+};
+
+static const unsigned pwm1_pins[] = { 5 };
+
+static const struct sirfsoc_muxmask pwm2_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(6),
+ },
+};
+
+static const struct sirfsoc_padmux pwm2_padmux = {
+ .muxmask_counts = ARRAY_SIZE(pwm2_muxmask),
+ .muxmask = pwm2_muxmask,
+};
+
+static const unsigned pwm2_pins[] = { 6 };
+
+static const struct sirfsoc_muxmask pwm3_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(7),
+ },
+};
+
+static const struct sirfsoc_padmux pwm3_padmux = {
+ .muxmask_counts = ARRAY_SIZE(pwm3_muxmask),
+ .muxmask = pwm3_muxmask,
+};
+
+static const unsigned pwm3_pins[] = { 7 };
+
+static const struct sirfsoc_muxmask warm_rst_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(8),
+ },
+};
+
+static const struct sirfsoc_padmux warm_rst_padmux = {
+ .muxmask_counts = ARRAY_SIZE(warm_rst_muxmask),
+ .muxmask = warm_rst_muxmask,
+};
+
+static const unsigned warm_rst_pins[] = { 8 };
+
+static const struct sirfsoc_muxmask usb0_utmi_drvbus_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(22),
+ },
+};
+static const struct sirfsoc_padmux usb0_utmi_drvbus_padmux = {
+ .muxmask_counts = ARRAY_SIZE(usb0_utmi_drvbus_muxmask),
+ .muxmask = usb0_utmi_drvbus_muxmask,
+ .funcmask = BIT(6),
+ .funcval = BIT(6), /* refer to PAD_UTMI_DRVVBUS0_ENABLE */
+};
+
+static const unsigned usb0_utmi_drvbus_pins[] = { 54 };
+
+static const struct sirfsoc_muxmask usb1_utmi_drvbus_muxmask[] = {
+ {
+ .group = 1,
+ .mask = BIT(27),
+ },
+};
+
+static const struct sirfsoc_padmux usb1_utmi_drvbus_padmux = {
+ .muxmask_counts = ARRAY_SIZE(usb1_utmi_drvbus_muxmask),
+ .muxmask = usb1_utmi_drvbus_muxmask,
+ .funcmask = BIT(11),
+ .funcval = BIT(11), /* refer to PAD_UTMI_DRVVBUS1_ENABLE */
+};
+
+static const unsigned usb1_utmi_drvbus_pins[] = { 59 };
+
+static const struct sirfsoc_muxmask pulse_count_muxmask[] = {
+ {
+ .group = 0,
+ .mask = BIT(9) | BIT(10) | BIT(11),
+ },
+};
+
+static const struct sirfsoc_padmux pulse_count_padmux = {
+ .muxmask_counts = ARRAY_SIZE(pulse_count_muxmask),
+ .muxmask = pulse_count_muxmask,
+};
+
+static const unsigned pulse_count_pins[] = { 9, 10, 11 };
+
+#define SIRFSOC_PIN_GROUP(n, p) \
+ { \
+ .name = n, \
+ .pins = p, \
+ .num_pins = ARRAY_SIZE(p), \
+ }
+
+static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = {
+ SIRFSOC_PIN_GROUP("lcd_16bitsgrp", lcd_16bits_pins),
+ SIRFSOC_PIN_GROUP("lcd_18bitsgrp", lcd_18bits_pins),
+ SIRFSOC_PIN_GROUP("lcd_24bitsgrp", lcd_24bits_pins),
+ SIRFSOC_PIN_GROUP("lcdrom_grp", lcdrom_pins),
+ SIRFSOC_PIN_GROUP("uart0grp", uart0_pins),
+ SIRFSOC_PIN_GROUP("uart1grp", uart1_pins),
+ SIRFSOC_PIN_GROUP("uart2grp", uart2_pins),
+ SIRFSOC_PIN_GROUP("uart2_nostreamctrlgrp", uart2_nostreamctrl_pins),
+ SIRFSOC_PIN_GROUP("usp0grp", usp0_pins),
+ SIRFSOC_PIN_GROUP("usp1grp", usp1_pins),
+ SIRFSOC_PIN_GROUP("usp2grp", usp2_pins),
+ SIRFSOC_PIN_GROUP("i2c0grp", i2c0_pins),
+ SIRFSOC_PIN_GROUP("i2c1grp", i2c1_pins),
+ SIRFSOC_PIN_GROUP("pwm0grp", pwm0_pins),
+ SIRFSOC_PIN_GROUP("pwm1grp", pwm1_pins),
+ SIRFSOC_PIN_GROUP("pwm2grp", pwm2_pins),
+ SIRFSOC_PIN_GROUP("pwm3grp", pwm3_pins),
+ SIRFSOC_PIN_GROUP("vipgrp", vip_pins),
+ SIRFSOC_PIN_GROUP("vipromgrp", viprom_pins),
+ SIRFSOC_PIN_GROUP("warm_rstgrp", warm_rst_pins),
+ SIRFSOC_PIN_GROUP("cko0_rstgrp", cko0_pins),
+ SIRFSOC_PIN_GROUP("cko1_rstgrp", cko1_pins),
+ SIRFSOC_PIN_GROUP("sdmmc0grp", sdmmc0_pins),
+ SIRFSOC_PIN_GROUP("sdmmc1grp", sdmmc1_pins),
+ SIRFSOC_PIN_GROUP("sdmmc2grp", sdmmc2_pins),
+ SIRFSOC_PIN_GROUP("sdmmc3grp", sdmmc3_pins),
+ SIRFSOC_PIN_GROUP("sdmmc4grp", sdmmc4_pins),
+ SIRFSOC_PIN_GROUP("sdmmc5grp", sdmmc5_pins),
+ SIRFSOC_PIN_GROUP("usb0_utmi_drvbusgrp", usb0_utmi_drvbus_pins),
+ SIRFSOC_PIN_GROUP("usb1_utmi_drvbusgrp", usb1_utmi_drvbus_pins),
+ SIRFSOC_PIN_GROUP("pulse_countgrp", pulse_count_pins),
+ SIRFSOC_PIN_GROUP("i2sgrp", i2s_pins),
+ SIRFSOC_PIN_GROUP("ac97grp", ac97_pins),
+ SIRFSOC_PIN_GROUP("nandgrp", nand_pins),
+ SIRFSOC_PIN_GROUP("spi0grp", spi0_pins),
+ SIRFSOC_PIN_GROUP("spi1grp", spi1_pins),
+ SIRFSOC_PIN_GROUP("gpsgrp", gps_pins),
+};
+
+static int sirfsoc_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
+ return -EINVAL;
+ return 0;
+}
+
+static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
+ return NULL;
+ return sirfsoc_pin_groups[selector].name;
+}
+
+static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
+ return -EINVAL;
+ *pins = sirfsoc_pin_groups[selector].pins;
+ *num_pins = sirfsoc_pin_groups[selector].num_pins;
+ return 0;
+}
+
+static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+ unsigned offset)
+{
+ seq_printf(s, " " DRIVER_NAME);
+}
+
+static struct pinctrl_ops sirfsoc_pctrl_ops = {
+ .list_groups = sirfsoc_list_groups,
+ .get_group_name = sirfsoc_get_group_name,
+ .get_group_pins = sirfsoc_get_group_pins,
+ .pin_dbg_show = sirfsoc_pin_dbg_show,
+};
+
+struct sirfsoc_pmx_func {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+ const struct sirfsoc_padmux *padmux;
+};
+
+static const char * const lcd_16bitsgrp[] = { "lcd_16bitsgrp" };
+static const char * const lcd_18bitsgrp[] = { "lcd_18bitsgrp" };
+static const char * const lcd_24bitsgrp[] = { "lcd_24bitsgrp" };
+static const char * const lcdromgrp[] = { "lcdromgrp" };
+static const char * const uart0grp[] = { "uart0grp" };
+static const char * const uart1grp[] = { "uart1grp" };
+static const char * const uart2grp[] = { "uart2grp" };
+static const char * const uart2_nostreamctrlgrp[] = { "uart2_nostreamctrlgrp" };
+static const char * const usp0grp[] = { "usp0grp" };
+static const char * const usp1grp[] = { "usp1grp" };
+static const char * const usp2grp[] = { "usp2grp" };
+static const char * const i2c0grp[] = { "i2c0grp" };
+static const char * const i2c1grp[] = { "i2c1grp" };
+static const char * const pwm0grp[] = { "pwm0grp" };
+static const char * const pwm1grp[] = { "pwm1grp" };
+static const char * const pwm2grp[] = { "pwm2grp" };
+static const char * const pwm3grp[] = { "pwm3grp" };
+static const char * const vipgrp[] = { "vipgrp" };
+static const char * const vipromgrp[] = { "vipromgrp" };
+static const char * const warm_rstgrp[] = { "warm_rstgrp" };
+static const char * const cko0grp[] = { "cko0grp" };
+static const char * const cko1grp[] = { "cko1grp" };
+static const char * const sdmmc0grp[] = { "sdmmc0grp" };
+static const char * const sdmmc1grp[] = { "sdmmc1grp" };
+static const char * const sdmmc2grp[] = { "sdmmc2grp" };
+static const char * const sdmmc3grp[] = { "sdmmc3grp" };
+static const char * const sdmmc4grp[] = { "sdmmc4grp" };
+static const char * const sdmmc5grp[] = { "sdmmc5grp" };
+static const char * const usb0_utmi_drvbusgrp[] = { "usb0_utmi_drvbusgrp" };
+static const char * const usb1_utmi_drvbusgrp[] = { "usb1_utmi_drvbusgrp" };
+static const char * const pulse_countgrp[] = { "pulse_countgrp" };
+static const char * const i2sgrp[] = { "i2sgrp" };
+static const char * const ac97grp[] = { "ac97grp" };
+static const char * const nandgrp[] = { "nandgrp" };
+static const char * const spi0grp[] = { "spi0grp" };
+static const char * const spi1grp[] = { "spi1grp" };
+static const char * const gpsgrp[] = { "gpsgrp" };
+
+#define SIRFSOC_PMX_FUNCTION(n, g, m) \
+ { \
+ .name = n, \
+ .groups = g, \
+ .num_groups = ARRAY_SIZE(g), \
+ .padmux = &m, \
+ }
+
+static const struct sirfsoc_pmx_func sirfsoc_pmx_functions[] = {
+ SIRFSOC_PMX_FUNCTION("lcd_16bits", lcd_16bitsgrp, lcd_16bits_padmux),
+ SIRFSOC_PMX_FUNCTION("lcd_18bits", lcd_18bitsgrp, lcd_18bits_padmux),
+ SIRFSOC_PMX_FUNCTION("lcd_24bits", lcd_24bitsgrp, lcd_24bits_padmux),
+ SIRFSOC_PMX_FUNCTION("lcdrom", lcdromgrp, lcdrom_padmux),
+ SIRFSOC_PMX_FUNCTION("uart0", uart0grp, uart0_padmux),
+ SIRFSOC_PMX_FUNCTION("uart1", uart1grp, uart1_padmux),
+ SIRFSOC_PMX_FUNCTION("uart2", uart2grp, uart2_padmux),
+ SIRFSOC_PMX_FUNCTION("uart2_nostreamctrl", uart2_nostreamctrlgrp, uart2_nostreamctrl_padmux),
+ SIRFSOC_PMX_FUNCTION("usp0", usp0grp, usp0_padmux),
+ SIRFSOC_PMX_FUNCTION("usp1", usp1grp, usp1_padmux),
+ SIRFSOC_PMX_FUNCTION("usp2", usp2grp, usp2_padmux),
+ SIRFSOC_PMX_FUNCTION("i2c0", i2c0grp, i2c0_padmux),
+ SIRFSOC_PMX_FUNCTION("i2c1", i2c1grp, i2c1_padmux),
+ SIRFSOC_PMX_FUNCTION("pwm0", pwm0grp, pwm0_padmux),
+ SIRFSOC_PMX_FUNCTION("pwm1", pwm1grp, pwm1_padmux),
+ SIRFSOC_PMX_FUNCTION("pwm2", pwm2grp, pwm2_padmux),
+ SIRFSOC_PMX_FUNCTION("pwm3", pwm3grp, pwm3_padmux),
+ SIRFSOC_PMX_FUNCTION("vip", vipgrp, vip_padmux),
+ SIRFSOC_PMX_FUNCTION("viprom", vipromgrp, viprom_padmux),
+ SIRFSOC_PMX_FUNCTION("warm_rst", warm_rstgrp, warm_rst_padmux),
+ SIRFSOC_PMX_FUNCTION("cko0", cko0grp, cko0_padmux),
+ SIRFSOC_PMX_FUNCTION("cko1", cko1grp, cko1_padmux),
+ SIRFSOC_PMX_FUNCTION("sdmmc0", sdmmc0grp, sdmmc0_padmux),
+ SIRFSOC_PMX_FUNCTION("sdmmc1", sdmmc1grp, sdmmc1_padmux),
+ SIRFSOC_PMX_FUNCTION("sdmmc2", sdmmc2grp, sdmmc2_padmux),
+ SIRFSOC_PMX_FUNCTION("sdmmc3", sdmmc3grp, sdmmc3_padmux),
+ SIRFSOC_PMX_FUNCTION("sdmmc4", sdmmc4grp, sdmmc4_padmux),
+ SIRFSOC_PMX_FUNCTION("sdmmc5", sdmmc5grp, sdmmc5_padmux),
+ SIRFSOC_PMX_FUNCTION("usb0_utmi_drvbus", usb0_utmi_drvbusgrp, usb0_utmi_drvbus_padmux),
+ SIRFSOC_PMX_FUNCTION("usb1_utmi_drvbus", usb1_utmi_drvbusgrp, usb1_utmi_drvbus_padmux),
+ SIRFSOC_PMX_FUNCTION("pulse_count", pulse_countgrp, pulse_count_padmux),
+ SIRFSOC_PMX_FUNCTION("i2s", i2sgrp, i2s_padmux),
+ SIRFSOC_PMX_FUNCTION("ac97", ac97grp, ac97_padmux),
+ SIRFSOC_PMX_FUNCTION("nand", nandgrp, nand_padmux),
+ SIRFSOC_PMX_FUNCTION("spi0", spi0grp, spi0_padmux),
+ SIRFSOC_PMX_FUNCTION("spi1", spi1grp, spi1_padmux),
+ SIRFSOC_PMX_FUNCTION("gps", gpsgrp, gps_padmux),
+};
+
+static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector,
+ bool enable)
+{
+ int i;
+ const struct sirfsoc_padmux *mux = sirfsoc_pmx_functions[selector].padmux;
+ const struct sirfsoc_muxmask *mask = mux->muxmask;
+
+ for (i = 0; i < mux->muxmask_counts; i++) {
+ u32 muxval;
+ muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+ if (enable)
+ muxval = muxval & ~mask[i].mask;
+ else
+ muxval = muxval | mask[i].mask;
+ writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+ }
+
+ if (mux->funcmask && enable) {
+ u32 func_en_val;
+ func_en_val =
+ readl(spmx->rsc_virtbase + SIRFSOC_RSC_PIN_MUX);
+ func_en_val =
+ (func_en_val & ~mux->funcmask) | (mux->
+ funcval);
+ writel(func_en_val, spmx->rsc_virtbase + SIRFSOC_RSC_PIN_MUX);
+ }
+}
+
+static int sirfsoc_pinmux_enable(struct pinctrl_dev *pmxdev, unsigned selector,
+ unsigned group)
+{
+ struct sirfsoc_pmx *spmx;
+
+ spmx = pinctrl_dev_get_drvdata(pmxdev);
+ sirfsoc_pinmux_endisable(spmx, selector, true);
+
+ return 0;
+}
+
+static void sirfsoc_pinmux_disable(struct pinctrl_dev *pmxdev, unsigned selector,
+ unsigned group)
+{
+ struct sirfsoc_pmx *spmx;
+
+ spmx = pinctrl_dev_get_drvdata(pmxdev);
+ sirfsoc_pinmux_endisable(spmx, selector, false);
+}
+
+static int sirfsoc_pinmux_list_funcs(struct pinctrl_dev *pmxdev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(sirfsoc_pmx_functions))
+ return -EINVAL;
+ return 0;
+}
+
+static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return sirfsoc_pmx_functions[selector].name;
+}
+
+static int sirfsoc_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = sirfsoc_pmx_functions[selector].groups;
+ *num_groups = sirfsoc_pmx_functions[selector].num_groups;
+ return 0;
+}
+
+static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
+ struct pinctrl_gpio_range *range, unsigned offset)
+{
+ struct sirfsoc_pmx *spmx;
+
+ int group = range->id;
+
+ u32 muxval;
+
+ spmx = pinctrl_dev_get_drvdata(pmxdev);
+
+ muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+ muxval = muxval | (1 << offset);
+ writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+
+ return 0;
+}
+
+static struct pinmux_ops sirfsoc_pinmux_ops = {
+ .list_functions = sirfsoc_pinmux_list_funcs,
+ .enable = sirfsoc_pinmux_enable,
+ .disable = sirfsoc_pinmux_disable,
+ .get_function_name = sirfsoc_pinmux_get_func_name,
+ .get_function_groups = sirfsoc_pinmux_get_groups,
+ .gpio_request_enable = sirfsoc_pinmux_request_gpio,
+};
+
+static struct pinctrl_desc sirfsoc_pinmux_desc = {
+ .name = DRIVER_NAME,
+ .pins = sirfsoc_pads,
+ .npins = ARRAY_SIZE(sirfsoc_pads),
+ .maxpin = SIRFSOC_NUM_PADS - 1,
+ .pctlops = &sirfsoc_pctrl_ops,
+ .pmxops = &sirfsoc_pinmux_ops,
+ .owner = THIS_MODULE,
+};
+
+/*
+ * Todo: bind irq_chip to every pinctrl_gpio_range
+ */
+static struct pinctrl_gpio_range sirfsoc_gpio_ranges[] = {
+ {
+ .name = "sirfsoc-gpio*",
+ .id = 0,
+ .base = 0,
+ .npins = 32,
+ }, {
+ .name = "sirfsoc-gpio*",
+ .id = 1,
+ .base = 32,
+ .npins = 32,
+ }, {
+ .name = "sirfsoc-gpio*",
+ .id = 2,
+ .base = 64,
+ .npins = 32,
+ }, {
+ .name = "sirfsoc-gpio*",
+ .id = 3,
+ .base = 96,
+ .npins = 19,
+ },
+};
+
+static void __iomem *sirfsoc_rsc_of_iomap(void)
+{
+ const struct of_device_id rsc_ids[] = {
+ { .compatible = "sirf,prima2-rsc" },
+ {}
+ };
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, rsc_ids);
+ if (!np)
+ panic("unable to find compatible rsc node in dtb\n");
+
+ return of_iomap(np, 0);
+}
+
+static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct sirfsoc_pmx *spmx;
+ struct device_node *np = pdev->dev.of_node;
+ int i;
+
+ /* Create state holders etc for this driver */
+ spmx = devm_kzalloc(&pdev->dev, sizeof(*spmx), GFP_KERNEL);
+ if (!spmx)
+ return -ENOMEM;
+
+ spmx->dev = &pdev->dev;
+
+ platform_set_drvdata(pdev, spmx);
+
+ spmx->gpio_virtbase = of_iomap(np, 0);
+ if (!spmx->gpio_virtbase) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "can't map gpio registers\n");
+ goto out_no_gpio_remap;
+ }
+
+ spmx->rsc_virtbase = sirfsoc_rsc_of_iomap();
+ if (!spmx->rsc_virtbase) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "can't map rsc registers\n");
+ goto out_no_rsc_remap;
+ }
+
+ /* Now register the pin controller and all pins it handles */
+ spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
+ if (!spmx->pmx) {
+ dev_err(&pdev->dev, "could not register SIRFSOC pinmux driver\n");
+ ret = -EINVAL;
+ goto out_no_pmx;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sirfsoc_gpio_ranges); i++)
+ pinctrl_add_gpio_range(spmx->pmx, &sirfsoc_gpio_ranges[i]);
+
+ dev_info(&pdev->dev, "initialized SIRFSOC pinmux driver\n");
+
+ return 0;
+
+out_no_pmx:
+ iounmap(spmx->rsc_virtbase);
+out_no_rsc_remap:
+ iounmap(spmx->gpio_virtbase);
+out_no_gpio_remap:
+ platform_set_drvdata(pdev, NULL);
+ devm_kfree(&pdev->dev, spmx);
+ return ret;
+}
+
+static const struct of_device_id pinmux_ids[] = {
+ { .compatible = "sirf,prima2-gpio-pinmux" },
+ {}
+};
+
+static struct platform_driver sirfsoc_pinmux_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = pinmux_ids,
+ },
+ .probe = sirfsoc_pinmux_probe,
+};
+
+static int __init sirfsoc_pinmux_init(void)
+{
+ return platform_driver_register(&sirfsoc_pinmux_driver);
+}
+arch_initcall(sirfsoc_pinmux_init);
+
+MODULE_AUTHOR("Rongjun Ying <rongjun.ying@csr.com>, "
+ "Barry Song <baohua.song@csr.com>");
+MODULE_DESCRIPTION("SIRFSOC pin control driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinmux-u300.c b/drivers/pinctrl/pinmux-u300.c
new file mode 100644
index 000000000000..4858a64131f8
--- /dev/null
+++ b/drivers/pinctrl/pinmux-u300.c
@@ -0,0 +1,1135 @@
+/*
+ * Driver for the U300 pin controller
+ *
+ * Based on the original U300 padmux functions
+ * Copyright (C) 2009-2011 ST-Ericsson AB
+ * Author: Martin Persson <martin.persson@stericsson.com>
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * The DB3350 design and control registers are oriented around pads rather than
+ * pins, so we enumerate the pads we can mux rather than actual pins. The pads
+ * are connected to different pins in different packaging types, so it would
+ * be confusing.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+/*
+ * Register definitions for the U300 Padmux control registers in the
+ * system controller
+ */
+
+/* PAD MUX Control register 1 (LOW) 16bit (R/W) */
+#define U300_SYSCON_PMC1LR 0x007C
+#define U300_SYSCON_PMC1LR_MASK 0xFFFF
+#define U300_SYSCON_PMC1LR_CDI_MASK 0xC000
+#define U300_SYSCON_PMC1LR_CDI_CDI 0x0000
+#define U300_SYSCON_PMC1LR_CDI_EMIF 0x4000
+/* For BS335 */
+#define U300_SYSCON_PMC1LR_CDI_CDI2 0x8000
+#define U300_SYSCON_PMC1LR_CDI_WCDMA_APP_GPIO 0xC000
+/* For BS365 */
+#define U300_SYSCON_PMC1LR_CDI_GPIO 0x8000
+#define U300_SYSCON_PMC1LR_CDI_WCDMA 0xC000
+/* Common defs */
+#define U300_SYSCON_PMC1LR_PDI_MASK 0x3000
+#define U300_SYSCON_PMC1LR_PDI_PDI 0x0000
+#define U300_SYSCON_PMC1LR_PDI_EGG 0x1000
+#define U300_SYSCON_PMC1LR_PDI_WCDMA 0x3000
+#define U300_SYSCON_PMC1LR_MMCSD_MASK 0x0C00
+#define U300_SYSCON_PMC1LR_MMCSD_MMCSD 0x0000
+#define U300_SYSCON_PMC1LR_MMCSD_MSPRO 0x0400
+#define U300_SYSCON_PMC1LR_MMCSD_DSP 0x0800
+#define U300_SYSCON_PMC1LR_MMCSD_WCDMA 0x0C00
+#define U300_SYSCON_PMC1LR_ETM_MASK 0x0300
+#define U300_SYSCON_PMC1LR_ETM_ACC 0x0000
+#define U300_SYSCON_PMC1LR_ETM_APP 0x0100
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK 0x00C0
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC 0x0000
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF 0x0040
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM 0x0080
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB 0x00C0
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK 0x0030
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC 0x0000
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF 0x0010
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM 0x0020
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI 0x0030
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK 0x000C
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC 0x0000
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF 0x0004
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM 0x0008
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI 0x000C
+#define U300_SYSCON_PMC1LR_EMIF_1_MASK 0x0003
+#define U300_SYSCON_PMC1LR_EMIF_1_STATIC 0x0000
+#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0 0x0001
+#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1 0x0002
+#define U300_SYSCON_PMC1LR_EMIF_1 0x0003
+/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */
+#define U300_SYSCON_PMC1HR 0x007E
+#define U300_SYSCON_PMC1HR_MASK 0xFFFF
+#define U300_SYSCON_PMC1HR_MISC_2_MASK 0xC000
+#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_MISC_2_MSPRO 0x4000
+#define U300_SYSCON_PMC1HR_MISC_2_DSP 0x8000
+#define U300_SYSCON_PMC1HR_MISC_2_AAIF 0xC000
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK 0x3000
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF 0x1000
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP 0x2000
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF 0x3000
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK 0x0C00
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC 0x0400
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP 0x0800
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF 0x0C00
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK 0x0300
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI 0x0100
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF 0x0300
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK 0x00C0
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI 0x0040
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF 0x00C0
+#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK 0x0030
+#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI 0x0010
+#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP 0x0020
+#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF 0x0030
+#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK 0x000C
+#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0 0x0004
+#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS 0x0008
+#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF 0x000C
+#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK 0x0003
+#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0 0x0001
+#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF 0x0003
+/* Padmux 2 control */
+#define U300_SYSCON_PMC2R 0x100
+#define U300_SYSCON_PMC2R_APP_MISC_0_MASK 0x00C0
+#define U300_SYSCON_PMC2R_APP_MISC_0_APP_GPIO 0x0000
+#define U300_SYSCON_PMC2R_APP_MISC_0_EMIF_SDRAM 0x0040
+#define U300_SYSCON_PMC2R_APP_MISC_0_MMC 0x0080
+#define U300_SYSCON_PMC2R_APP_MISC_0_CDI2 0x00C0
+#define U300_SYSCON_PMC2R_APP_MISC_1_MASK 0x0300
+#define U300_SYSCON_PMC2R_APP_MISC_1_APP_GPIO 0x0000
+#define U300_SYSCON_PMC2R_APP_MISC_1_EMIF_SDRAM 0x0100
+#define U300_SYSCON_PMC2R_APP_MISC_1_MMC 0x0200
+#define U300_SYSCON_PMC2R_APP_MISC_1_CDI2 0x0300
+#define U300_SYSCON_PMC2R_APP_MISC_2_MASK 0x0C00
+#define U300_SYSCON_PMC2R_APP_MISC_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC2R_APP_MISC_2_EMIF_SDRAM 0x0400
+#define U300_SYSCON_PMC2R_APP_MISC_2_MMC 0x0800
+#define U300_SYSCON_PMC2R_APP_MISC_2_CDI2 0x0C00
+#define U300_SYSCON_PMC2R_APP_MISC_3_MASK 0x3000
+#define U300_SYSCON_PMC2R_APP_MISC_3_APP_GPIO 0x0000
+#define U300_SYSCON_PMC2R_APP_MISC_3_EMIF_SDRAM 0x1000
+#define U300_SYSCON_PMC2R_APP_MISC_3_MMC 0x2000
+#define U300_SYSCON_PMC2R_APP_MISC_3_CDI2 0x3000
+#define U300_SYSCON_PMC2R_APP_MISC_4_MASK 0xC000
+#define U300_SYSCON_PMC2R_APP_MISC_4_APP_GPIO 0x0000
+#define U300_SYSCON_PMC2R_APP_MISC_4_EMIF_SDRAM 0x4000
+#define U300_SYSCON_PMC2R_APP_MISC_4_MMC 0x8000
+#define U300_SYSCON_PMC2R_APP_MISC_4_ACC_GPIO 0xC000
+/* TODO: More SYSCON registers missing */
+#define U300_SYSCON_PMC3R 0x10C
+#define U300_SYSCON_PMC3R_APP_MISC_11_MASK 0xC000
+#define U300_SYSCON_PMC3R_APP_MISC_11_SPI 0x4000
+#define U300_SYSCON_PMC3R_APP_MISC_10_MASK 0x3000
+#define U300_SYSCON_PMC3R_APP_MISC_10_SPI 0x1000
+/* TODO: Missing other configs */
+#define U300_SYSCON_PMC4R 0x168
+#define U300_SYSCON_PMC4R_APP_MISC_12_MASK 0x0003
+#define U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO 0x0000
+#define U300_SYSCON_PMC4R_APP_MISC_13_MASK 0x000C
+#define U300_SYSCON_PMC4R_APP_MISC_13_CDI 0x0000
+#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA 0x0004
+#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA2 0x0008
+#define U300_SYSCON_PMC4R_APP_MISC_13_APP_GPIO 0x000C
+#define U300_SYSCON_PMC4R_APP_MISC_14_MASK 0x0030
+#define U300_SYSCON_PMC4R_APP_MISC_14_CDI 0x0000
+#define U300_SYSCON_PMC4R_APP_MISC_14_SMIA 0x0010
+#define U300_SYSCON_PMC4R_APP_MISC_14_CDI2 0x0020
+#define U300_SYSCON_PMC4R_APP_MISC_14_APP_GPIO 0x0030
+#define U300_SYSCON_PMC4R_APP_MISC_16_MASK 0x0300
+#define U300_SYSCON_PMC4R_APP_MISC_16_APP_GPIO_13 0x0000
+#define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS 0x0100
+#define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N 0x0200
+
+#define DRIVER_NAME "pinmux-u300"
+
+/*
+ * The DB3350 has 467 pads, I have enumerated the pads clockwise around the
+ * edges of the silicon, finger by finger. LTCORNER upper left is pad 0.
+ * Data taken from the PadRing chart, arranged like this:
+ *
+ * 0 ..... 104
+ * 466 105
+ * . .
+ * . .
+ * 358 224
+ * 357 .... 225
+ */
+#define U300_NUM_PADS 467
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc u300_pads[] = {
+ /* Pads along the top edge of the chip */
+ PINCTRL_PIN(0, "P PAD VDD 28"),
+ PINCTRL_PIN(1, "P PAD GND 28"),
+ PINCTRL_PIN(2, "PO SIM RST N"),
+ PINCTRL_PIN(3, "VSSIO 25"),
+ PINCTRL_PIN(4, "VSSA ADDA ESDSUB"),
+ PINCTRL_PIN(5, "PWR VSSCOMMON"),
+ PINCTRL_PIN(6, "PI ADC I1 POS"),
+ PINCTRL_PIN(7, "PI ADC I1 NEG"),
+ PINCTRL_PIN(8, "PWR VSSAD0"),
+ PINCTRL_PIN(9, "PWR VCCAD0"),
+ PINCTRL_PIN(10, "PI ADC Q1 NEG"),
+ PINCTRL_PIN(11, "PI ADC Q1 POS"),
+ PINCTRL_PIN(12, "PWR VDDAD"),
+ PINCTRL_PIN(13, "PWR GNDAD"),
+ PINCTRL_PIN(14, "PI ADC I2 POS"),
+ PINCTRL_PIN(15, "PI ADC I2 NEG"),
+ PINCTRL_PIN(16, "PWR VSSAD1"),
+ PINCTRL_PIN(17, "PWR VCCAD1"),
+ PINCTRL_PIN(18, "PI ADC Q2 NEG"),
+ PINCTRL_PIN(19, "PI ADC Q2 POS"),
+ PINCTRL_PIN(20, "VSSA ADDA ESDSUB"),
+ PINCTRL_PIN(21, "PWR VCCGPAD"),
+ PINCTRL_PIN(22, "PI TX POW"),
+ PINCTRL_PIN(23, "PWR VSSGPAD"),
+ PINCTRL_PIN(24, "PO DAC I POS"),
+ PINCTRL_PIN(25, "PO DAC I NEG"),
+ PINCTRL_PIN(26, "PO DAC Q POS"),
+ PINCTRL_PIN(27, "PO DAC Q NEG"),
+ PINCTRL_PIN(28, "PWR VSSDA"),
+ PINCTRL_PIN(29, "PWR VCCDA"),
+ PINCTRL_PIN(30, "VSSA ADDA ESDSUB"),
+ PINCTRL_PIN(31, "P PAD VDDIO 11"),
+ PINCTRL_PIN(32, "PI PLL 26 FILTVDD"),
+ PINCTRL_PIN(33, "PI PLL 26 VCONT"),
+ PINCTRL_PIN(34, "PWR AGNDPLL2V5 32 13"),
+ PINCTRL_PIN(35, "PWR AVDDPLL2V5 32 13"),
+ PINCTRL_PIN(36, "VDDA PLL ESD"),
+ PINCTRL_PIN(37, "VSSA PLL ESD"),
+ PINCTRL_PIN(38, "VSS PLL"),
+ PINCTRL_PIN(39, "VDDC PLL"),
+ PINCTRL_PIN(40, "PWR AGNDPLL2V5 26 60"),
+ PINCTRL_PIN(41, "PWR AVDDPLL2V5 26 60"),
+ PINCTRL_PIN(42, "PWR AVDDPLL2V5 26 208"),
+ PINCTRL_PIN(43, "PWR AGNDPLL2V5 26 208"),
+ PINCTRL_PIN(44, "PWR AVDDPLL2V5 13 208"),
+ PINCTRL_PIN(45, "PWR AGNDPLL2V5 13 208"),
+ PINCTRL_PIN(46, "P PAD VSSIO 11"),
+ PINCTRL_PIN(47, "P PAD VSSIO 12"),
+ PINCTRL_PIN(48, "PI POW RST N"),
+ PINCTRL_PIN(49, "VDDC IO"),
+ PINCTRL_PIN(50, "P PAD VDDIO 16"),
+ PINCTRL_PIN(51, "PO RF WCDMA EN 4"),
+ PINCTRL_PIN(52, "PO RF WCDMA EN 3"),
+ PINCTRL_PIN(53, "PO RF WCDMA EN 2"),
+ PINCTRL_PIN(54, "PO RF WCDMA EN 1"),
+ PINCTRL_PIN(55, "PO RF WCDMA EN 0"),
+ PINCTRL_PIN(56, "PO GSM PA ENABLE"),
+ PINCTRL_PIN(57, "PO RF DATA STRB"),
+ PINCTRL_PIN(58, "PO RF DATA2"),
+ PINCTRL_PIN(59, "PIO RF DATA1"),
+ PINCTRL_PIN(60, "PIO RF DATA0"),
+ PINCTRL_PIN(61, "P PAD VDD 11"),
+ PINCTRL_PIN(62, "P PAD GND 11"),
+ PINCTRL_PIN(63, "P PAD VSSIO 16"),
+ PINCTRL_PIN(64, "P PAD VDDIO 18"),
+ PINCTRL_PIN(65, "PO RF CTRL STRB2"),
+ PINCTRL_PIN(66, "PO RF CTRL STRB1"),
+ PINCTRL_PIN(67, "PO RF CTRL STRB0"),
+ PINCTRL_PIN(68, "PIO RF CTRL DATA"),
+ PINCTRL_PIN(69, "PO RF CTRL CLK"),
+ PINCTRL_PIN(70, "PO TX ADC STRB"),
+ PINCTRL_PIN(71, "PO ANT SW 2"),
+ PINCTRL_PIN(72, "PO ANT SW 3"),
+ PINCTRL_PIN(73, "PO ANT SW 0"),
+ PINCTRL_PIN(74, "PO ANT SW 1"),
+ PINCTRL_PIN(75, "PO M CLKRQ"),
+ PINCTRL_PIN(76, "PI M CLK"),
+ PINCTRL_PIN(77, "PI RTC CLK"),
+ PINCTRL_PIN(78, "P PAD VDD 8"),
+ PINCTRL_PIN(79, "P PAD GND 8"),
+ PINCTRL_PIN(80, "P PAD VSSIO 13"),
+ PINCTRL_PIN(81, "P PAD VDDIO 13"),
+ PINCTRL_PIN(82, "PO SYS 1 CLK"),
+ PINCTRL_PIN(83, "PO SYS 2 CLK"),
+ PINCTRL_PIN(84, "PO SYS 0 CLK"),
+ PINCTRL_PIN(85, "PI SYS 0 CLKRQ"),
+ PINCTRL_PIN(86, "PO PWR MNGT CTRL 1"),
+ PINCTRL_PIN(87, "PO PWR MNGT CTRL 0"),
+ PINCTRL_PIN(88, "PO RESOUT2 RST N"),
+ PINCTRL_PIN(89, "PO RESOUT1 RST N"),
+ PINCTRL_PIN(90, "PO RESOUT0 RST N"),
+ PINCTRL_PIN(91, "PI SERVICE N"),
+ PINCTRL_PIN(92, "P PAD VDD 29"),
+ PINCTRL_PIN(93, "P PAD GND 29"),
+ PINCTRL_PIN(94, "P PAD VSSIO 8"),
+ PINCTRL_PIN(95, "P PAD VDDIO 8"),
+ PINCTRL_PIN(96, "PI EXT IRQ1 N"),
+ PINCTRL_PIN(97, "PI EXT IRQ0 N"),
+ PINCTRL_PIN(98, "PIO DC ON"),
+ PINCTRL_PIN(99, "PIO ACC APP I2C DATA"),
+ PINCTRL_PIN(100, "PIO ACC APP I2C CLK"),
+ PINCTRL_PIN(101, "P PAD VDD 12"),
+ PINCTRL_PIN(102, "P PAD GND 12"),
+ PINCTRL_PIN(103, "P PAD VSSIO 14"),
+ PINCTRL_PIN(104, "P PAD VDDIO 14"),
+ /* Pads along the right edge of the chip */
+ PINCTRL_PIN(105, "PIO APP I2C1 DATA"),
+ PINCTRL_PIN(106, "PIO APP I2C1 CLK"),
+ PINCTRL_PIN(107, "PO KEY OUT0"),
+ PINCTRL_PIN(108, "PO KEY OUT1"),
+ PINCTRL_PIN(109, "PO KEY OUT2"),
+ PINCTRL_PIN(110, "PO KEY OUT3"),
+ PINCTRL_PIN(111, "PO KEY OUT4"),
+ PINCTRL_PIN(112, "PI KEY IN0"),
+ PINCTRL_PIN(113, "PI KEY IN1"),
+ PINCTRL_PIN(114, "PI KEY IN2"),
+ PINCTRL_PIN(115, "P PAD VDDIO 15"),
+ PINCTRL_PIN(116, "P PAD VSSIO 15"),
+ PINCTRL_PIN(117, "P PAD GND 13"),
+ PINCTRL_PIN(118, "P PAD VDD 13"),
+ PINCTRL_PIN(119, "PI KEY IN3"),
+ PINCTRL_PIN(120, "PI KEY IN4"),
+ PINCTRL_PIN(121, "PI KEY IN5"),
+ PINCTRL_PIN(122, "PIO APP PCM I2S1 DATA B"),
+ PINCTRL_PIN(123, "PIO APP PCM I2S1 DATA A"),
+ PINCTRL_PIN(124, "PIO APP PCM I2S1 WS"),
+ PINCTRL_PIN(125, "PIO APP PCM I2S1 CLK"),
+ PINCTRL_PIN(126, "PIO APP PCM I2S0 DATA B"),
+ PINCTRL_PIN(127, "PIO APP PCM I2S0 DATA A"),
+ PINCTRL_PIN(128, "PIO APP PCM I2S0 WS"),
+ PINCTRL_PIN(129, "PIO APP PCM I2S0 CLK"),
+ PINCTRL_PIN(130, "P PAD VDD 17"),
+ PINCTRL_PIN(131, "P PAD GND 17"),
+ PINCTRL_PIN(132, "P PAD VSSIO 19"),
+ PINCTRL_PIN(133, "P PAD VDDIO 19"),
+ PINCTRL_PIN(134, "UART0 RTS"),
+ PINCTRL_PIN(135, "UART0 CTS"),
+ PINCTRL_PIN(136, "UART0 TX"),
+ PINCTRL_PIN(137, "UART0 RX"),
+ PINCTRL_PIN(138, "PIO ACC SPI DO"),
+ PINCTRL_PIN(139, "PIO ACC SPI DI"),
+ PINCTRL_PIN(140, "PIO ACC SPI CS0 N"),
+ PINCTRL_PIN(141, "PIO ACC SPI CS1 N"),
+ PINCTRL_PIN(142, "PIO ACC SPI CS2 N"),
+ PINCTRL_PIN(143, "PIO ACC SPI CLK"),
+ PINCTRL_PIN(144, "PO PDI EXT RST N"),
+ PINCTRL_PIN(145, "P PAD VDDIO 22"),
+ PINCTRL_PIN(146, "P PAD VSSIO 22"),
+ PINCTRL_PIN(147, "P PAD GND 18"),
+ PINCTRL_PIN(148, "P PAD VDD 18"),
+ PINCTRL_PIN(149, "PIO PDI C0"),
+ PINCTRL_PIN(150, "PIO PDI C1"),
+ PINCTRL_PIN(151, "PIO PDI C2"),
+ PINCTRL_PIN(152, "PIO PDI C3"),
+ PINCTRL_PIN(153, "PIO PDI C4"),
+ PINCTRL_PIN(154, "PIO PDI C5"),
+ PINCTRL_PIN(155, "PIO PDI D0"),
+ PINCTRL_PIN(156, "PIO PDI D1"),
+ PINCTRL_PIN(157, "PIO PDI D2"),
+ PINCTRL_PIN(158, "PIO PDI D3"),
+ PINCTRL_PIN(159, "P PAD VDDIO 21"),
+ PINCTRL_PIN(160, "P PAD VSSIO 21"),
+ PINCTRL_PIN(161, "PIO PDI D4"),
+ PINCTRL_PIN(162, "PIO PDI D5"),
+ PINCTRL_PIN(163, "PIO PDI D6"),
+ PINCTRL_PIN(164, "PIO PDI D7"),
+ PINCTRL_PIN(165, "PIO MS INS"),
+ PINCTRL_PIN(166, "MMC DATA DIR LS"),
+ PINCTRL_PIN(167, "MMC DATA 3"),
+ PINCTRL_PIN(168, "MMC DATA 2"),
+ PINCTRL_PIN(169, "MMC DATA 1"),
+ PINCTRL_PIN(170, "MMC DATA 0"),
+ PINCTRL_PIN(171, "MMC CMD DIR LS"),
+ PINCTRL_PIN(172, "P PAD VDD 27"),
+ PINCTRL_PIN(173, "P PAD GND 27"),
+ PINCTRL_PIN(174, "P PAD VSSIO 20"),
+ PINCTRL_PIN(175, "P PAD VDDIO 20"),
+ PINCTRL_PIN(176, "MMC CMD"),
+ PINCTRL_PIN(177, "MMC CLK"),
+ PINCTRL_PIN(178, "PIO APP GPIO 14"),
+ PINCTRL_PIN(179, "PIO APP GPIO 13"),
+ PINCTRL_PIN(180, "PIO APP GPIO 11"),
+ PINCTRL_PIN(181, "PIO APP GPIO 25"),
+ PINCTRL_PIN(182, "PIO APP GPIO 24"),
+ PINCTRL_PIN(183, "PIO APP GPIO 23"),
+ PINCTRL_PIN(184, "PIO APP GPIO 22"),
+ PINCTRL_PIN(185, "PIO APP GPIO 21"),
+ PINCTRL_PIN(186, "PIO APP GPIO 20"),
+ PINCTRL_PIN(187, "P PAD VDD 19"),
+ PINCTRL_PIN(188, "P PAD GND 19"),
+ PINCTRL_PIN(189, "P PAD VSSIO 23"),
+ PINCTRL_PIN(190, "P PAD VDDIO 23"),
+ PINCTRL_PIN(191, "PIO APP GPIO 19"),
+ PINCTRL_PIN(192, "PIO APP GPIO 18"),
+ PINCTRL_PIN(193, "PIO APP GPIO 17"),
+ PINCTRL_PIN(194, "PIO APP GPIO 16"),
+ PINCTRL_PIN(195, "PI CI D1"),
+ PINCTRL_PIN(196, "PI CI D0"),
+ PINCTRL_PIN(197, "PI CI HSYNC"),
+ PINCTRL_PIN(198, "PI CI VSYNC"),
+ PINCTRL_PIN(199, "PI CI EXT CLK"),
+ PINCTRL_PIN(200, "PO CI EXT RST N"),
+ PINCTRL_PIN(201, "P PAD VSSIO 43"),
+ PINCTRL_PIN(202, "P PAD VDDIO 43"),
+ PINCTRL_PIN(203, "PI CI D6"),
+ PINCTRL_PIN(204, "PI CI D7"),
+ PINCTRL_PIN(205, "PI CI D2"),
+ PINCTRL_PIN(206, "PI CI D3"),
+ PINCTRL_PIN(207, "PI CI D4"),
+ PINCTRL_PIN(208, "PI CI D5"),
+ PINCTRL_PIN(209, "PI CI D8"),
+ PINCTRL_PIN(210, "PI CI D9"),
+ PINCTRL_PIN(211, "P PAD VDD 20"),
+ PINCTRL_PIN(212, "P PAD GND 20"),
+ PINCTRL_PIN(213, "P PAD VSSIO 24"),
+ PINCTRL_PIN(214, "P PAD VDDIO 24"),
+ PINCTRL_PIN(215, "P PAD VDDIO 26"),
+ PINCTRL_PIN(216, "PO EMIF 1 A26"),
+ PINCTRL_PIN(217, "PO EMIF 1 A25"),
+ PINCTRL_PIN(218, "P PAD VSSIO 26"),
+ PINCTRL_PIN(219, "PO EMIF 1 A24"),
+ PINCTRL_PIN(220, "PO EMIF 1 A23"),
+ /* Pads along the bottom edge of the chip */
+ PINCTRL_PIN(221, "PO EMIF 1 A22"),
+ PINCTRL_PIN(222, "PO EMIF 1 A21"),
+ PINCTRL_PIN(223, "P PAD VDD 21"),
+ PINCTRL_PIN(224, "P PAD GND 21"),
+ PINCTRL_PIN(225, "P PAD VSSIO 27"),
+ PINCTRL_PIN(226, "P PAD VDDIO 27"),
+ PINCTRL_PIN(227, "PO EMIF 1 A20"),
+ PINCTRL_PIN(228, "PO EMIF 1 A19"),
+ PINCTRL_PIN(229, "PO EMIF 1 A18"),
+ PINCTRL_PIN(230, "PO EMIF 1 A17"),
+ PINCTRL_PIN(231, "P PAD VDDIO 28"),
+ PINCTRL_PIN(232, "P PAD VSSIO 28"),
+ PINCTRL_PIN(233, "PO EMIF 1 A16"),
+ PINCTRL_PIN(234, "PIO EMIF 1 D15"),
+ PINCTRL_PIN(235, "PO EMIF 1 A15"),
+ PINCTRL_PIN(236, "PIO EMIF 1 D14"),
+ PINCTRL_PIN(237, "P PAD VDD 22"),
+ PINCTRL_PIN(238, "P PAD GND 22"),
+ PINCTRL_PIN(239, "P PAD VSSIO 29"),
+ PINCTRL_PIN(240, "P PAD VDDIO 29"),
+ PINCTRL_PIN(241, "PO EMIF 1 A14"),
+ PINCTRL_PIN(242, "PIO EMIF 1 D13"),
+ PINCTRL_PIN(243, "PO EMIF 1 A13"),
+ PINCTRL_PIN(244, "PIO EMIF 1 D12"),
+ PINCTRL_PIN(245, "P PAD VSSIO 30"),
+ PINCTRL_PIN(246, "P PAD VDDIO 30"),
+ PINCTRL_PIN(247, "PO EMIF 1 A12"),
+ PINCTRL_PIN(248, "PIO EMIF 1 D11"),
+ PINCTRL_PIN(249, "PO EMIF 1 A11"),
+ PINCTRL_PIN(250, "PIO EMIF 1 D10"),
+ PINCTRL_PIN(251, "P PAD VSSIO 31"),
+ PINCTRL_PIN(252, "P PAD VDDIO 31"),
+ PINCTRL_PIN(253, "PO EMIF 1 A10"),
+ PINCTRL_PIN(254, "PIO EMIF 1 D09"),
+ PINCTRL_PIN(255, "PO EMIF 1 A09"),
+ PINCTRL_PIN(256, "P PAD VDDIO 32"),
+ PINCTRL_PIN(257, "P PAD VSSIO 32"),
+ PINCTRL_PIN(258, "P PAD GND 24"),
+ PINCTRL_PIN(259, "P PAD VDD 24"),
+ PINCTRL_PIN(260, "PIO EMIF 1 D08"),
+ PINCTRL_PIN(261, "PO EMIF 1 A08"),
+ PINCTRL_PIN(262, "PIO EMIF 1 D07"),
+ PINCTRL_PIN(263, "PO EMIF 1 A07"),
+ PINCTRL_PIN(264, "P PAD VDDIO 33"),
+ PINCTRL_PIN(265, "P PAD VSSIO 33"),
+ PINCTRL_PIN(266, "PIO EMIF 1 D06"),
+ PINCTRL_PIN(267, "PO EMIF 1 A06"),
+ PINCTRL_PIN(268, "PIO EMIF 1 D05"),
+ PINCTRL_PIN(269, "PO EMIF 1 A05"),
+ PINCTRL_PIN(270, "P PAD VDDIO 34"),
+ PINCTRL_PIN(271, "P PAD VSSIO 34"),
+ PINCTRL_PIN(272, "PIO EMIF 1 D04"),
+ PINCTRL_PIN(273, "PO EMIF 1 A04"),
+ PINCTRL_PIN(274, "PIO EMIF 1 D03"),
+ PINCTRL_PIN(275, "PO EMIF 1 A03"),
+ PINCTRL_PIN(276, "P PAD VDDIO 35"),
+ PINCTRL_PIN(277, "P PAD VSSIO 35"),
+ PINCTRL_PIN(278, "P PAD GND 23"),
+ PINCTRL_PIN(279, "P PAD VDD 23"),
+ PINCTRL_PIN(280, "PIO EMIF 1 D02"),
+ PINCTRL_PIN(281, "PO EMIF 1 A02"),
+ PINCTRL_PIN(282, "PIO EMIF 1 D01"),
+ PINCTRL_PIN(283, "PO EMIF 1 A01"),
+ PINCTRL_PIN(284, "P PAD VDDIO 36"),
+ PINCTRL_PIN(285, "P PAD VSSIO 36"),
+ PINCTRL_PIN(286, "PIO EMIF 1 D00"),
+ PINCTRL_PIN(287, "PO EMIF 1 BE1 N"),
+ PINCTRL_PIN(288, "PO EMIF 1 BE0 N"),
+ PINCTRL_PIN(289, "PO EMIF 1 ADV N"),
+ PINCTRL_PIN(290, "P PAD VDDIO 37"),
+ PINCTRL_PIN(291, "P PAD VSSIO 37"),
+ PINCTRL_PIN(292, "PO EMIF 1 SD CKE0"),
+ PINCTRL_PIN(293, "PO EMIF 1 OE N"),
+ PINCTRL_PIN(294, "PO EMIF 1 WE N"),
+ PINCTRL_PIN(295, "P PAD VDDIO 38"),
+ PINCTRL_PIN(296, "P PAD VSSIO 38"),
+ PINCTRL_PIN(297, "PO EMIF 1 CLK"),
+ PINCTRL_PIN(298, "PIO EMIF 1 SD CLK"),
+ PINCTRL_PIN(299, "P PAD VSSIO 45 (not bonded)"),
+ PINCTRL_PIN(300, "P PAD VDDIO 42"),
+ PINCTRL_PIN(301, "P PAD VSSIO 42"),
+ PINCTRL_PIN(302, "P PAD GND 31"),
+ PINCTRL_PIN(303, "P PAD VDD 31"),
+ PINCTRL_PIN(304, "PI EMIF 1 RET CLK"),
+ PINCTRL_PIN(305, "PI EMIF 1 WAIT N"),
+ PINCTRL_PIN(306, "PI EMIF 1 NFIF READY"),
+ PINCTRL_PIN(307, "PO EMIF 1 SD CKE1"),
+ PINCTRL_PIN(308, "PO EMIF 1 CS3 N"),
+ PINCTRL_PIN(309, "P PAD VDD 25"),
+ PINCTRL_PIN(310, "P PAD GND 25"),
+ PINCTRL_PIN(311, "P PAD VSSIO 39"),
+ PINCTRL_PIN(312, "P PAD VDDIO 39"),
+ PINCTRL_PIN(313, "PO EMIF 1 CS2 N"),
+ PINCTRL_PIN(314, "PO EMIF 1 CS1 N"),
+ PINCTRL_PIN(315, "PO EMIF 1 CS0 N"),
+ PINCTRL_PIN(316, "PO ETM TRACE PKT0"),
+ PINCTRL_PIN(317, "PO ETM TRACE PKT1"),
+ PINCTRL_PIN(318, "PO ETM TRACE PKT2"),
+ PINCTRL_PIN(319, "P PAD VDD 30"),
+ PINCTRL_PIN(320, "P PAD GND 30"),
+ PINCTRL_PIN(321, "P PAD VSSIO 44"),
+ PINCTRL_PIN(322, "P PAD VDDIO 44"),
+ PINCTRL_PIN(323, "PO ETM TRACE PKT3"),
+ PINCTRL_PIN(324, "PO ETM TRACE PKT4"),
+ PINCTRL_PIN(325, "PO ETM TRACE PKT5"),
+ PINCTRL_PIN(326, "PO ETM TRACE PKT6"),
+ PINCTRL_PIN(327, "PO ETM TRACE PKT7"),
+ PINCTRL_PIN(328, "PO ETM PIPE STAT0"),
+ PINCTRL_PIN(329, "P PAD VDD 26"),
+ PINCTRL_PIN(330, "P PAD GND 26"),
+ PINCTRL_PIN(331, "P PAD VSSIO 40"),
+ PINCTRL_PIN(332, "P PAD VDDIO 40"),
+ PINCTRL_PIN(333, "PO ETM PIPE STAT1"),
+ PINCTRL_PIN(334, "PO ETM PIPE STAT2"),
+ PINCTRL_PIN(335, "PO ETM TRACE CLK"),
+ PINCTRL_PIN(336, "PO ETM TRACE SYNC"),
+ PINCTRL_PIN(337, "PIO ACC GPIO 33"),
+ PINCTRL_PIN(338, "PIO ACC GPIO 32"),
+ PINCTRL_PIN(339, "PIO ACC GPIO 30"),
+ PINCTRL_PIN(340, "PIO ACC GPIO 29"),
+ PINCTRL_PIN(341, "P PAD VDDIO 17"),
+ PINCTRL_PIN(342, "P PAD VSSIO 17"),
+ PINCTRL_PIN(343, "P PAD GND 15"),
+ PINCTRL_PIN(344, "P PAD VDD 15"),
+ PINCTRL_PIN(345, "PIO ACC GPIO 28"),
+ PINCTRL_PIN(346, "PIO ACC GPIO 27"),
+ PINCTRL_PIN(347, "PIO ACC GPIO 16"),
+ PINCTRL_PIN(348, "PI TAP TMS"),
+ PINCTRL_PIN(349, "PI TAP TDI"),
+ PINCTRL_PIN(350, "PO TAP TDO"),
+ PINCTRL_PIN(351, "PI TAP RST N"),
+ /* Pads along the left edge of the chip */
+ PINCTRL_PIN(352, "PI EMU MODE 0"),
+ PINCTRL_PIN(353, "PO TAP RET CLK"),
+ PINCTRL_PIN(354, "PI TAP CLK"),
+ PINCTRL_PIN(355, "PO EMIF 0 SD CS N"),
+ PINCTRL_PIN(356, "PO EMIF 0 SD CAS N"),
+ PINCTRL_PIN(357, "PO EMIF 0 SD WE N"),
+ PINCTRL_PIN(358, "P PAD VDDIO 1"),
+ PINCTRL_PIN(359, "P PAD VSSIO 1"),
+ PINCTRL_PIN(360, "P PAD GND 1"),
+ PINCTRL_PIN(361, "P PAD VDD 1"),
+ PINCTRL_PIN(362, "PO EMIF 0 SD CKE"),
+ PINCTRL_PIN(363, "PO EMIF 0 SD DQML"),
+ PINCTRL_PIN(364, "PO EMIF 0 SD DQMU"),
+ PINCTRL_PIN(365, "PO EMIF 0 SD RAS N"),
+ PINCTRL_PIN(366, "PIO EMIF 0 D15"),
+ PINCTRL_PIN(367, "PO EMIF 0 A15"),
+ PINCTRL_PIN(368, "PIO EMIF 0 D14"),
+ PINCTRL_PIN(369, "PO EMIF 0 A14"),
+ PINCTRL_PIN(370, "PIO EMIF 0 D13"),
+ PINCTRL_PIN(371, "PO EMIF 0 A13"),
+ PINCTRL_PIN(372, "P PAD VDDIO 2"),
+ PINCTRL_PIN(373, "P PAD VSSIO 2"),
+ PINCTRL_PIN(374, "P PAD GND 2"),
+ PINCTRL_PIN(375, "P PAD VDD 2"),
+ PINCTRL_PIN(376, "PIO EMIF 0 D12"),
+ PINCTRL_PIN(377, "PO EMIF 0 A12"),
+ PINCTRL_PIN(378, "PIO EMIF 0 D11"),
+ PINCTRL_PIN(379, "PO EMIF 0 A11"),
+ PINCTRL_PIN(380, "PIO EMIF 0 D10"),
+ PINCTRL_PIN(381, "PO EMIF 0 A10"),
+ PINCTRL_PIN(382, "PIO EMIF 0 D09"),
+ PINCTRL_PIN(383, "PO EMIF 0 A09"),
+ PINCTRL_PIN(384, "PIO EMIF 0 D08"),
+ PINCTRL_PIN(385, "PO EMIF 0 A08"),
+ PINCTRL_PIN(386, "PIO EMIF 0 D07"),
+ PINCTRL_PIN(387, "PO EMIF 0 A07"),
+ PINCTRL_PIN(388, "P PAD VDDIO 3"),
+ PINCTRL_PIN(389, "P PAD VSSIO 3"),
+ PINCTRL_PIN(390, "P PAD GND 3"),
+ PINCTRL_PIN(391, "P PAD VDD 3"),
+ PINCTRL_PIN(392, "PO EFUSE RDOUT1"),
+ PINCTRL_PIN(393, "PIO EMIF 0 D06"),
+ PINCTRL_PIN(394, "PO EMIF 0 A06"),
+ PINCTRL_PIN(395, "PIO EMIF 0 D05"),
+ PINCTRL_PIN(396, "PO EMIF 0 A05"),
+ PINCTRL_PIN(397, "PIO EMIF 0 D04"),
+ PINCTRL_PIN(398, "PO EMIF 0 A04"),
+ PINCTRL_PIN(399, "A PADS/A VDDCO1v82v5 GND 80U SF LIN VDDCO AF"),
+ PINCTRL_PIN(400, "PWR VDDCO AF"),
+ PINCTRL_PIN(401, "PWR EFUSE HV1"),
+ PINCTRL_PIN(402, "P PAD VSSIO 4"),
+ PINCTRL_PIN(403, "P PAD VDDIO 4"),
+ PINCTRL_PIN(404, "P PAD GND 4"),
+ PINCTRL_PIN(405, "P PAD VDD 4"),
+ PINCTRL_PIN(406, "PIO EMIF 0 D03"),
+ PINCTRL_PIN(407, "PO EMIF 0 A03"),
+ PINCTRL_PIN(408, "PWR EFUSE HV2"),
+ PINCTRL_PIN(409, "PWR EFUSE HV3"),
+ PINCTRL_PIN(410, "PIO EMIF 0 D02"),
+ PINCTRL_PIN(411, "PO EMIF 0 A02"),
+ PINCTRL_PIN(412, "PIO EMIF 0 D01"),
+ PINCTRL_PIN(413, "P PAD VDDIO 5"),
+ PINCTRL_PIN(414, "P PAD VSSIO 5"),
+ PINCTRL_PIN(415, "P PAD GND 5"),
+ PINCTRL_PIN(416, "P PAD VDD 5"),
+ PINCTRL_PIN(417, "PO EMIF 0 A01"),
+ PINCTRL_PIN(418, "PIO EMIF 0 D00"),
+ PINCTRL_PIN(419, "IF 0 SD CLK"),
+ PINCTRL_PIN(420, "APP SPI CLK"),
+ PINCTRL_PIN(421, "APP SPI DO"),
+ PINCTRL_PIN(422, "APP SPI DI"),
+ PINCTRL_PIN(423, "APP SPI CS0"),
+ PINCTRL_PIN(424, "APP SPI CS1"),
+ PINCTRL_PIN(425, "APP SPI CS2"),
+ PINCTRL_PIN(426, "PIO APP GPIO 10"),
+ PINCTRL_PIN(427, "P PAD VDDIO 41"),
+ PINCTRL_PIN(428, "P PAD VSSIO 41"),
+ PINCTRL_PIN(429, "P PAD GND 6"),
+ PINCTRL_PIN(430, "P PAD VDD 6"),
+ PINCTRL_PIN(431, "PIO ACC SDIO0 CMD"),
+ PINCTRL_PIN(432, "PIO ACC SDIO0 CK"),
+ PINCTRL_PIN(433, "PIO ACC SDIO0 D3"),
+ PINCTRL_PIN(434, "PIO ACC SDIO0 D2"),
+ PINCTRL_PIN(435, "PIO ACC SDIO0 D1"),
+ PINCTRL_PIN(436, "PIO ACC SDIO0 D0"),
+ PINCTRL_PIN(437, "PIO USB PU"),
+ PINCTRL_PIN(438, "PIO USB SP"),
+ PINCTRL_PIN(439, "PIO USB DAT VP"),
+ PINCTRL_PIN(440, "PIO USB SE0 VM"),
+ PINCTRL_PIN(441, "PIO USB OE"),
+ PINCTRL_PIN(442, "PIO USB SUSP"),
+ PINCTRL_PIN(443, "P PAD VSSIO 6"),
+ PINCTRL_PIN(444, "P PAD VDDIO 6"),
+ PINCTRL_PIN(445, "PIO USB PUEN"),
+ PINCTRL_PIN(446, "PIO ACC UART0 RX"),
+ PINCTRL_PIN(447, "PIO ACC UART0 TX"),
+ PINCTRL_PIN(448, "PIO ACC UART0 CTS"),
+ PINCTRL_PIN(449, "PIO ACC UART0 RTS"),
+ PINCTRL_PIN(450, "PIO ACC UART3 RX"),
+ PINCTRL_PIN(451, "PIO ACC UART3 TX"),
+ PINCTRL_PIN(452, "PIO ACC UART3 CTS"),
+ PINCTRL_PIN(453, "PIO ACC UART3 RTS"),
+ PINCTRL_PIN(454, "PIO ACC IRDA TX"),
+ PINCTRL_PIN(455, "P PAD VDDIO 7"),
+ PINCTRL_PIN(456, "P PAD VSSIO 7"),
+ PINCTRL_PIN(457, "P PAD GND 7"),
+ PINCTRL_PIN(458, "P PAD VDD 7"),
+ PINCTRL_PIN(459, "PIO ACC IRDA RX"),
+ PINCTRL_PIN(460, "PIO ACC PCM I2S CLK"),
+ PINCTRL_PIN(461, "PIO ACC PCM I2S WS"),
+ PINCTRL_PIN(462, "PIO ACC PCM I2S DATA A"),
+ PINCTRL_PIN(463, "PIO ACC PCM I2S DATA B"),
+ PINCTRL_PIN(464, "PO SIM CLK"),
+ PINCTRL_PIN(465, "PIO ACC IRDA SD"),
+ PINCTRL_PIN(466, "PIO SIM DATA"),
+};
+
+/**
+ * @dev: a pointer back to containing device
+ * @virtbase: the offset to the controller in virtual memory
+ */
+struct u300_pmx {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ u32 phybase;
+ u32 physize;
+ void __iomem *virtbase;
+};
+
+/**
+ * u300_pmx_registers - the array of registers read/written for each pinmux
+ * shunt setting
+ */
+const u32 u300_pmx_registers[] = {
+ U300_SYSCON_PMC1LR,
+ U300_SYSCON_PMC1HR,
+ U300_SYSCON_PMC2R,
+ U300_SYSCON_PMC3R,
+ U300_SYSCON_PMC4R,
+};
+
+/**
+ * struct u300_pin_group - describes a U300 pin group
+ * @name: the name of this specific pin group
+ * @pins: an array of discrete physical pins used in this group, taken
+ * from the driver-local pin enumeration space
+ * @num_pins: the number of pins in this group array, i.e. the number of
+ * elements in .pins so we can iterate over that array
+ */
+struct u300_pin_group {
+ const char *name;
+ const unsigned int *pins;
+ const unsigned num_pins;
+};
+
+/**
+ * struct pmx_onmask - mask bits to enable/disable padmux
+ * @mask: mask bits to disable
+ * @val: mask bits to enable
+ *
+ * onmask lazy dog:
+ * onmask = {
+ * {"PMC1LR" mask, "PMC1LR" value},
+ * {"PMC1HR" mask, "PMC1HR" value},
+ * {"PMC2R" mask, "PMC2R" value},
+ * {"PMC3R" mask, "PMC3R" value},
+ * {"PMC4R" mask, "PMC4R" value}
+ * }
+ */
+struct u300_pmx_mask {
+ u16 mask;
+ u16 bits;
+};
+
+/* The chip power pins are VDD, GND, VDDIO and VSSIO */
+static const unsigned power_pins[] = { 0, 1, 3, 31, 46, 47, 49, 50, 61, 62, 63,
+ 64, 78, 79, 80, 81, 92, 93, 94, 95, 101, 102, 103, 104, 115, 116, 117,
+ 118, 130, 131, 132, 133, 145, 146, 147, 148, 159, 160, 172, 173, 174,
+ 175, 187, 188, 189, 190, 201, 202, 211, 212, 213, 214, 215, 218, 223,
+ 224, 225, 226, 231, 232, 237, 238, 239, 240, 245, 246, 251, 252, 256,
+ 257, 258, 259, 264, 265, 270, 271, 276, 277, 278, 279, 284, 285, 290,
+ 291, 295, 296, 299, 300, 301, 302, 303, 309, 310, 311, 312, 319, 320,
+ 321, 322, 329, 330, 331, 332, 341, 342, 343, 344, 358, 359, 360, 361,
+ 372, 373, 374, 375, 388, 389, 390, 391, 402, 403, 404, 405, 413, 414,
+ 415, 416, 427, 428, 429, 430, 443, 444, 455, 456, 457, 458 };
+static const unsigned emif0_pins[] = { 355, 356, 357, 362, 363, 364, 365, 366,
+ 367, 368, 369, 370, 371, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 393, 394, 395, 396, 397, 398, 406, 407, 410, 411, 412,
+ 417, 418 };
+static const unsigned emif1_pins[] = { 216, 217, 219, 220, 221, 222, 227, 228,
+ 229, 230, 233, 234, 235, 236, 241, 242, 243, 244, 247, 248, 249, 250,
+ 253, 254, 255, 260, 261, 262, 263, 266, 267, 268, 269, 272, 273, 274,
+ 275, 280, 281, 282, 283, 286, 287, 288, 289, 292, 293, 294, 297, 298,
+ 304, 305, 306, 307, 308, 313, 314, 315 };
+static const unsigned uart0_pins[] = { 134, 135, 136, 137 };
+static const unsigned mmc0_pins[] = { 166, 167, 168, 169, 170, 171, 176, 177 };
+static const unsigned spi0_pins[] = { 420, 421, 422, 423, 424, 425 };
+
+static const struct u300_pmx_mask emif0_mask[] = {
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+};
+
+static const struct u300_pmx_mask emif1_mask[] = {
+ /*
+ * This connects the SDRAM to CS2 and a NAND flash to
+ * CS0 on the EMIF.
+ */
+ {
+ U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK |
+ U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK |
+ U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK |
+ U300_SYSCON_PMC1LR_EMIF_1_MASK,
+ U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM |
+ U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC |
+ U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF |
+ U300_SYSCON_PMC1LR_EMIF_1_SDRAM0
+ },
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+};
+
+static const struct u300_pmx_mask uart0_mask[] = {
+ {0, 0},
+ {
+ U300_SYSCON_PMC1HR_APP_UART0_1_MASK |
+ U300_SYSCON_PMC1HR_APP_UART0_2_MASK,
+ U300_SYSCON_PMC1HR_APP_UART0_1_UART0 |
+ U300_SYSCON_PMC1HR_APP_UART0_2_UART0
+ },
+ {0, 0},
+ {0, 0},
+ {0, 0},
+};
+
+static const struct u300_pmx_mask mmc0_mask[] = {
+ { U300_SYSCON_PMC1LR_MMCSD_MASK, U300_SYSCON_PMC1LR_MMCSD_MMCSD},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ { U300_SYSCON_PMC4R_APP_MISC_12_MASK,
+ U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO }
+};
+
+static const struct u300_pmx_mask spi0_mask[] = {
+ {0, 0},
+ {
+ U300_SYSCON_PMC1HR_APP_SPI_2_MASK |
+ U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK |
+ U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK,
+ U300_SYSCON_PMC1HR_APP_SPI_2_SPI |
+ U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI |
+ U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI
+ },
+ {0, 0},
+ {0, 0},
+ {0, 0}
+};
+
+static const struct u300_pin_group u300_pin_groups[] = {
+ {
+ .name = "powergrp",
+ .pins = power_pins,
+ .num_pins = ARRAY_SIZE(power_pins),
+ },
+ {
+ .name = "emif0grp",
+ .pins = emif0_pins,
+ .num_pins = ARRAY_SIZE(emif0_pins),
+ },
+ {
+ .name = "emif1grp",
+ .pins = emif1_pins,
+ .num_pins = ARRAY_SIZE(emif1_pins),
+ },
+ {
+ .name = "uart0grp",
+ .pins = uart0_pins,
+ .num_pins = ARRAY_SIZE(uart0_pins),
+ },
+ {
+ .name = "mmc0grp",
+ .pins = mmc0_pins,
+ .num_pins = ARRAY_SIZE(mmc0_pins),
+ },
+ {
+ .name = "spi0grp",
+ .pins = spi0_pins,
+ .num_pins = ARRAY_SIZE(spi0_pins),
+ },
+};
+
+static int u300_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(u300_pin_groups))
+ return -EINVAL;
+ return 0;
+}
+
+static const char *u300_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(u300_pin_groups))
+ return NULL;
+ return u300_pin_groups[selector].name;
+}
+
+static int u300_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ if (selector >= ARRAY_SIZE(u300_pin_groups))
+ return -EINVAL;
+ *pins = u300_pin_groups[selector].pins;
+ *num_pins = u300_pin_groups[selector].num_pins;
+ return 0;
+}
+
+static void u300_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+ unsigned offset)
+{
+ seq_printf(s, " " DRIVER_NAME);
+}
+
+static struct pinctrl_ops u300_pctrl_ops = {
+ .list_groups = u300_list_groups,
+ .get_group_name = u300_get_group_name,
+ .get_group_pins = u300_get_group_pins,
+ .pin_dbg_show = u300_pin_dbg_show,
+};
+
+/*
+ * Here we define the available functions and their corresponding pin groups
+ */
+
+/**
+ * struct u300_pmx_func - describes U300 pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @onmask: bits to set to enable this when doing pin muxing
+ */
+struct u300_pmx_func {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+ const struct u300_pmx_mask *mask;
+};
+
+static const char * const powergrps[] = { "powergrp" };
+static const char * const emif0grps[] = { "emif0grp" };
+static const char * const emif1grps[] = { "emif1grp" };
+static const char * const uart0grps[] = { "uart0grp" };
+static const char * const mmc0grps[] = { "mmc0grp" };
+static const char * const spi0grps[] = { "spi0grp" };
+
+static const struct u300_pmx_func u300_pmx_functions[] = {
+ {
+ .name = "power",
+ .groups = powergrps,
+ .num_groups = ARRAY_SIZE(powergrps),
+ /* Mask is N/A */
+ },
+ {
+ .name = "emif0",
+ .groups = emif0grps,
+ .num_groups = ARRAY_SIZE(emif0grps),
+ .mask = emif0_mask,
+ },
+ {
+ .name = "emif1",
+ .groups = emif1grps,
+ .num_groups = ARRAY_SIZE(emif1grps),
+ .mask = emif1_mask,
+ },
+ {
+ .name = "uart0",
+ .groups = uart0grps,
+ .num_groups = ARRAY_SIZE(uart0grps),
+ .mask = uart0_mask,
+ },
+ {
+ .name = "mmc0",
+ .groups = mmc0grps,
+ .num_groups = ARRAY_SIZE(mmc0grps),
+ .mask = mmc0_mask,
+ },
+ {
+ .name = "spi0",
+ .groups = spi0grps,
+ .num_groups = ARRAY_SIZE(spi0grps),
+ .mask = spi0_mask,
+ },
+};
+
+static void u300_pmx_endisable(struct u300_pmx *upmx, unsigned selector,
+ bool enable)
+{
+ u16 regval, val, mask;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(u300_pmx_registers); i++) {
+ if (enable)
+ val = u300_pmx_functions[selector].mask->bits;
+ else
+ val = 0;
+
+ mask = u300_pmx_functions[selector].mask->mask;
+ if (mask != 0) {
+ regval = readw(upmx->virtbase + u300_pmx_registers[i]);
+ regval &= ~mask;
+ regval |= val;
+ writew(regval, upmx->virtbase + u300_pmx_registers[i]);
+ }
+ }
+}
+
+static int u300_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct u300_pmx *upmx;
+
+ /* There is nothing to do with the power pins */
+ if (selector == 0)
+ return 0;
+
+ upmx = pinctrl_dev_get_drvdata(pctldev);
+ u300_pmx_endisable(upmx, selector, true);
+
+ return 0;
+}
+
+static void u300_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct u300_pmx *upmx;
+
+ /* There is nothing to do with the power pins */
+ if (selector == 0)
+ return;
+
+ upmx = pinctrl_dev_get_drvdata(pctldev);
+ u300_pmx_endisable(upmx, selector, false);
+}
+
+static int u300_pmx_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(u300_pmx_functions))
+ return -EINVAL;
+ return 0;
+}
+
+static const char *u300_pmx_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return u300_pmx_functions[selector].name;
+}
+
+static int u300_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = u300_pmx_functions[selector].groups;
+ *num_groups = u300_pmx_functions[selector].num_groups;
+ return 0;
+}
+
+static struct pinmux_ops u300_pmx_ops = {
+ .list_functions = u300_pmx_list_funcs,
+ .get_function_name = u300_pmx_get_func_name,
+ .get_function_groups = u300_pmx_get_groups,
+ .enable = u300_pmx_enable,
+ .disable = u300_pmx_disable,
+};
+
+/*
+ * FIXME: this will be set to sane values as this driver engulfs
+ * drivers/gpio/gpio-u300.c and we really know this stuff.
+ */
+static struct pinctrl_gpio_range u300_gpio_range = {
+ .name = "COH901*",
+ .id = 0,
+ .base = 0,
+ .npins = 64,
+};
+
+static struct pinctrl_desc u300_pmx_desc = {
+ .name = DRIVER_NAME,
+ .pins = u300_pads,
+ .npins = ARRAY_SIZE(u300_pads),
+ .maxpin = U300_NUM_PADS-1,
+ .pctlops = &u300_pctrl_ops,
+ .pmxops = &u300_pmx_ops,
+ .owner = THIS_MODULE,
+};
+
+static int __init u300_pmx_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct u300_pmx *upmx;
+ struct resource *res;
+
+ /* Create state holders etc for this driver */
+ upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL);
+ if (!upmx)
+ return -ENOMEM;
+
+ upmx->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENOENT;
+ goto out_no_resource;
+ }
+ upmx->phybase = res->start;
+ upmx->physize = resource_size(res);
+
+ if (request_mem_region(upmx->phybase, upmx->physize,
+ DRIVER_NAME) == NULL) {
+ ret = -ENOMEM;
+ goto out_no_memregion;
+ }
+
+ upmx->virtbase = ioremap(upmx->phybase, upmx->physize);
+ if (!upmx->virtbase) {
+ ret = -ENOMEM;
+ goto out_no_remap;
+ }
+
+ upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx);
+ if (!upmx->pctl) {
+ dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
+ ret = -EINVAL;
+ goto out_no_pmx;
+ }
+
+ /* We will handle a range of GPIO pins */
+ pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_range);
+
+ platform_set_drvdata(pdev, upmx);
+
+ dev_info(&pdev->dev, "initialized U300 pinmux driver\n");
+
+ return 0;
+
+out_no_pmx:
+ iounmap(upmx->virtbase);
+out_no_remap:
+ platform_set_drvdata(pdev, NULL);
+out_no_memregion:
+ release_mem_region(upmx->phybase, upmx->physize);
+out_no_resource:
+ devm_kfree(&pdev->dev, upmx);
+ return ret;
+}
+
+static int __exit u300_pmx_remove(struct platform_device *pdev)
+{
+ struct u300_pmx *upmx = platform_get_drvdata(pdev);
+
+ pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_range);
+ pinctrl_unregister(upmx->pctl);
+ iounmap(upmx->virtbase);
+ release_mem_region(upmx->phybase, upmx->physize);
+ platform_set_drvdata(pdev, NULL);
+ devm_kfree(&pdev->dev, upmx);
+
+ return 0;
+}
+
+static struct platform_driver u300_pmx_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .remove = __exit_p(u300_pmx_remove),
+};
+
+static int __init u300_pmx_init(void)
+{
+ return platform_driver_probe(&u300_pmx_driver, u300_pmx_probe);
+}
+arch_initcall(u300_pmx_init);
+
+static void __exit u300_pmx_exit(void)
+{
+ platform_driver_unregister(&u300_pmx_driver);
+}
+module_exit(u300_pmx_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("U300 pin control driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
new file mode 100644
index 000000000000..a5467f8709e9
--- /dev/null
+++ b/drivers/pinctrl/pinmux.c
@@ -0,0 +1,1190 @@
+/*
+ * Core driver for the pin muxing portions of the pin control subsystem
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ * Based on bits of regulator core, gpio core and clk core
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#define pr_fmt(fmt) "pinmux core: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/radix-tree.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinmux.h>
+#include "core.h"
+
+/* List of pinmuxes */
+static DEFINE_MUTEX(pinmux_list_mutex);
+static LIST_HEAD(pinmux_list);
+
+/* List of pinmux hogs */
+static DEFINE_MUTEX(pinmux_hoglist_mutex);
+static LIST_HEAD(pinmux_hoglist);
+
+/* Global pinmux maps, we allow one set only */
+static struct pinmux_map const *pinmux_maps;
+static unsigned pinmux_maps_num;
+
+/**
+ * struct pinmux_group - group list item for pinmux groups
+ * @node: pinmux group list node
+ * @group_selector: the group selector for this group
+ */
+struct pinmux_group {
+ struct list_head node;
+ unsigned group_selector;
+};
+
+/**
+ * struct pinmux - per-device pinmux state holder
+ * @node: global list node
+ * @dev: the device using this pinmux
+ * @usecount: the number of active users of this mux setting, used to keep
+ * track of nested use cases
+ * @pins: an array of discrete physical pins used in this mapping, taken
+ * from the global pin enumeration space (copied from pinmux map)
+ * @num_pins: the number of pins in this mapping array, i.e. the number of
+ * elements in .pins so we can iterate over that array (copied from
+ * pinmux map)
+ * @pctldev: pin control device handling this pinmux
+ * @func_selector: the function selector for the pinmux device handling
+ * this pinmux
+ * @groups: the group selectors for the pinmux device and
+ * selector combination handling this pinmux, this is a list that
+ * will be traversed on all pinmux operations such as
+ * get/put/enable/disable
+ * @mutex: a lock for the pinmux state holder
+ */
+struct pinmux {
+ struct list_head node;
+ struct device *dev;
+ unsigned usecount;
+ struct pinctrl_dev *pctldev;
+ unsigned func_selector;
+ struct list_head groups;
+ struct mutex mutex;
+};
+
+/**
+ * struct pinmux_hog - a list item to stash mux hogs
+ * @node: pinmux hog list node
+ * @map: map entry responsible for this hogging
+ * @pmx: the pinmux hogged by this item
+ */
+struct pinmux_hog {
+ struct list_head node;
+ struct pinmux_map const *map;
+ struct pinmux *pmx;
+};
+
+/**
+ * pin_request() - request a single pin to be muxed in, typically for GPIO
+ * @pin: the pin number in the global pin space
+ * @function: a functional name to give to this pin, passed to the driver
+ * so it knows what function to mux in, e.g. the string "gpioNN"
+ * means that you want to mux in the pin for use as GPIO number NN
+ * @gpio: if this request concerns a single GPIO pin
+ * @gpio_range: the range matching the GPIO pin if this is a request for a
+ * single GPIO pin
+ */
+static int pin_request(struct pinctrl_dev *pctldev,
+ int pin, const char *function, bool gpio,
+ struct pinctrl_gpio_range *gpio_range)
+{
+ struct pin_desc *desc;
+ const struct pinmux_ops *ops = pctldev->desc->pmxops;
+ int status = -EINVAL;
+
+ dev_dbg(&pctldev->dev, "request pin %d for %s\n", pin, function);
+
+ if (!pin_is_valid(pctldev, pin)) {
+ dev_err(&pctldev->dev, "pin is invalid\n");
+ return -EINVAL;
+ }
+
+ if (!function) {
+ dev_err(&pctldev->dev, "no function name given\n");
+ return -EINVAL;
+ }
+
+ desc = pin_desc_get(pctldev, pin);
+ if (desc == NULL) {
+ dev_err(&pctldev->dev,
+ "pin is not registered so it cannot be requested\n");
+ goto out;
+ }
+
+ spin_lock(&desc->lock);
+ if (desc->mux_function) {
+ spin_unlock(&desc->lock);
+ dev_err(&pctldev->dev,
+ "pin already requested\n");
+ goto out;
+ }
+ desc->mux_function = function;
+ spin_unlock(&desc->lock);
+
+ /* Let each pin increase references to this module */
+ if (!try_module_get(pctldev->owner)) {
+ dev_err(&pctldev->dev,
+ "could not increase module refcount for pin %d\n",
+ pin);
+ status = -EINVAL;
+ goto out_free_pin;
+ }
+
+ /*
+ * If there is no kind of request function for the pin we just assume
+ * we got it by default and proceed.
+ */
+ if (gpio && ops->gpio_request_enable)
+ /* This requests and enables a single GPIO pin */
+ status = ops->gpio_request_enable(pctldev, gpio_range, pin);
+ else if (ops->request)
+ status = ops->request(pctldev, pin);
+ else
+ status = 0;
+
+ if (status)
+ dev_err(&pctldev->dev, "->request on device %s failed "
+ "for pin %d\n",
+ pctldev->desc->name, pin);
+out_free_pin:
+ if (status) {
+ spin_lock(&desc->lock);
+ desc->mux_function = NULL;
+ spin_unlock(&desc->lock);
+ }
+out:
+ if (status)
+ dev_err(&pctldev->dev, "pin-%d (%s) status %d\n",
+ pin, function ? : "?", status);
+
+ return status;
+}
+
+/**
+ * pin_free() - release a single muxed in pin so something else can be muxed
+ * @pctldev: pin controller device handling this pin
+ * @pin: the pin to free
+ * @free_func: whether to free the pin's assigned function name string
+ */
+static void pin_free(struct pinctrl_dev *pctldev, int pin, int free_func)
+{
+ const struct pinmux_ops *ops = pctldev->desc->pmxops;
+ struct pin_desc *desc;
+
+ desc = pin_desc_get(pctldev, pin);
+ if (desc == NULL) {
+ dev_err(&pctldev->dev,
+ "pin is not registered so it cannot be freed\n");
+ return;
+ }
+
+ if (ops->free)
+ ops->free(pctldev, pin);
+
+ spin_lock(&desc->lock);
+ if (free_func)
+ kfree(desc->mux_function);
+ desc->mux_function = NULL;
+ spin_unlock(&desc->lock);
+ module_put(pctldev->owner);
+}
+
+/**
+ * pinmux_request_gpio() - request a single pin to be muxed in as GPIO
+ * @gpio: the GPIO pin number from the GPIO subsystem number space
+ */
+int pinmux_request_gpio(unsigned gpio)
+{
+ char gpiostr[16];
+ const char *function;
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_gpio_range *range;
+ int ret;
+ int pin;
+
+ ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
+ if (ret)
+ return -EINVAL;
+
+ /* Convert to the pin controllers number space */
+ pin = gpio - range->base;
+
+ /* Conjure some name stating what chip and pin this is taken by */
+ snprintf(gpiostr, 15, "%s:%d", range->name, gpio);
+
+ function = kstrdup(gpiostr, GFP_KERNEL);
+ if (!function)
+ return -EINVAL;
+
+ ret = pin_request(pctldev, pin, function, true, range);
+ if (ret < 0)
+ kfree(function);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pinmux_request_gpio);
+
+/**
+ * pinmux_free_gpio() - free a single pin, currently used as GPIO
+ * @gpio: the GPIO pin number from the GPIO subsystem number space
+ */
+void pinmux_free_gpio(unsigned gpio)
+{
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_gpio_range *range;
+ int ret;
+ int pin;
+
+ ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
+ if (ret)
+ return;
+
+ /* Convert to the pin controllers number space */
+ pin = gpio - range->base;
+
+ pin_free(pctldev, pin, true);
+}
+EXPORT_SYMBOL_GPL(pinmux_free_gpio);
+
+/**
+ * pinmux_register_mappings() - register a set of pinmux mappings
+ * @maps: the pinmux mappings table to register
+ * @num_maps: the number of maps in the mapping table
+ *
+ * Only call this once during initialization of your machine, the function is
+ * tagged as __init and won't be callable after init has completed. The map
+ * passed into this function will be owned by the pinmux core and cannot be
+ * free:d.
+ */
+int __init pinmux_register_mappings(struct pinmux_map const *maps,
+ unsigned num_maps)
+{
+ int i;
+
+ if (pinmux_maps != NULL) {
+ pr_err("pinmux mappings already registered, you can only "
+ "register one set of maps\n");
+ return -EINVAL;
+ }
+
+ pr_debug("add %d pinmux maps\n", num_maps);
+ for (i = 0; i < num_maps; i++) {
+ /* Sanity check the mapping */
+ if (!maps[i].name) {
+ pr_err("failed to register map %d: "
+ "no map name given\n", i);
+ return -EINVAL;
+ }
+ if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
+ pr_err("failed to register map %s (%d): "
+ "no pin control device given\n",
+ maps[i].name, i);
+ return -EINVAL;
+ }
+ if (!maps[i].function) {
+ pr_err("failed to register map %s (%d): "
+ "no function ID given\n", maps[i].name, i);
+ return -EINVAL;
+ }
+
+ if (!maps[i].dev && !maps[i].dev_name)
+ pr_debug("add system map %s function %s with no device\n",
+ maps[i].name,
+ maps[i].function);
+ else
+ pr_debug("register map %s, function %s\n",
+ maps[i].name,
+ maps[i].function);
+ }
+
+ pinmux_maps = maps;
+ pinmux_maps_num = num_maps;
+
+ return 0;
+}
+
+/**
+ * acquire_pins() - acquire all the pins for a certain funcion on a pinmux
+ * @pctldev: the device to take the pins on
+ * @func_selector: the function selector to acquire the pins for
+ * @group_selector: the group selector containing the pins to acquire
+ */
+static int acquire_pins(struct pinctrl_dev *pctldev,
+ unsigned func_selector,
+ unsigned group_selector)
+{
+ const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
+ const char *func = pmxops->get_function_name(pctldev,
+ func_selector);
+ const unsigned *pins;
+ unsigned num_pins;
+ int ret;
+ int i;
+
+ ret = pctlops->get_group_pins(pctldev, group_selector,
+ &pins, &num_pins);
+ if (ret)
+ return ret;
+
+ dev_dbg(&pctldev->dev, "requesting the %u pins from group %u\n",
+ num_pins, group_selector);
+
+ /* Try to allocate all pins in this group, one by one */
+ for (i = 0; i < num_pins; i++) {
+ ret = pin_request(pctldev, pins[i], func, false, NULL);
+ if (ret) {
+ dev_err(&pctldev->dev,
+ "could not get pin %d for function %s "
+ "on device %s - conflicting mux mappings?\n",
+ pins[i], func ? : "(undefined)",
+ pinctrl_dev_get_name(pctldev));
+ /* On error release all taken pins */
+ i--; /* this pin just failed */
+ for (; i >= 0; i--)
+ pin_free(pctldev, pins[i], false);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+/**
+ * release_pins() - release pins taken by earlier acquirement
+ * @pctldev: the device to free the pinx on
+ * @group_selector: the group selector containing the pins to free
+ */
+static void release_pins(struct pinctrl_dev *pctldev,
+ unsigned group_selector)
+{
+ const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ const unsigned *pins;
+ unsigned num_pins;
+ int ret;
+ int i;
+
+ ret = pctlops->get_group_pins(pctldev, group_selector,
+ &pins, &num_pins);
+ if (ret) {
+ dev_err(&pctldev->dev, "could not get pins to release for "
+ "group selector %d\n",
+ group_selector);
+ return;
+ }
+ for (i = 0; i < num_pins; i++)
+ pin_free(pctldev, pins[i], false);
+}
+
+/**
+ * pinmux_get_group_selector() - returns the group selector for a group
+ * @pctldev: the pin controller handling the group
+ * @pin_group: the pin group to look up
+ */
+static int pinmux_get_group_selector(struct pinctrl_dev *pctldev,
+ const char *pin_group)
+{
+ const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ unsigned group_selector = 0;
+
+ while (pctlops->list_groups(pctldev, group_selector) >= 0) {
+ const char *gname = pctlops->get_group_name(pctldev,
+ group_selector);
+ if (!strcmp(gname, pin_group)) {
+ dev_dbg(&pctldev->dev,
+ "found group selector %u for %s\n",
+ group_selector,
+ pin_group);
+ return group_selector;
+ }
+
+ group_selector++;
+ }
+
+ dev_err(&pctldev->dev, "does not have pin group %s\n",
+ pin_group);
+
+ return -EINVAL;
+}
+
+/**
+ * pinmux_check_pin_group() - check function and pin group combo
+ * @pctldev: device to check the pin group vs function for
+ * @func_selector: the function selector to check the pin group for, we have
+ * already looked this up in the calling function
+ * @pin_group: the pin group to match to the function
+ *
+ * This function will check that the pinmux driver can supply the
+ * selected pin group for a certain function, returns the group selector if
+ * the group and function selector will work fine together, else returns
+ * negative
+ */
+static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
+ unsigned func_selector,
+ const char *pin_group)
+{
+ const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
+ const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ int ret;
+
+ /*
+ * If the driver does not support different pin groups for the
+ * functions, we only support group 0, and assume this exists.
+ */
+ if (!pctlops || !pctlops->list_groups)
+ return 0;
+
+ /*
+ * Passing NULL (no specific group) will select the first and
+ * hopefully only group of pins available for this function.
+ */
+ if (!pin_group) {
+ char const * const *groups;
+ unsigned num_groups;
+
+ ret = pmxops->get_function_groups(pctldev, func_selector,
+ &groups, &num_groups);
+ if (ret)
+ return ret;
+ if (num_groups < 1)
+ return -EINVAL;
+ ret = pinmux_get_group_selector(pctldev, groups[0]);
+ if (ret < 0) {
+ dev_err(&pctldev->dev,
+ "function %s wants group %s but the pin "
+ "controller does not seem to have that group\n",
+ pmxops->get_function_name(pctldev, func_selector),
+ groups[0]);
+ return ret;
+ }
+
+ if (num_groups > 1)
+ dev_dbg(&pctldev->dev,
+ "function %s support more than one group, "
+ "default-selecting first group %s (%d)\n",
+ pmxops->get_function_name(pctldev, func_selector),
+ groups[0],
+ ret);
+
+ return ret;
+ }
+
+ dev_dbg(&pctldev->dev,
+ "check if we have pin group %s on controller %s\n",
+ pin_group, pinctrl_dev_get_name(pctldev));
+
+ ret = pinmux_get_group_selector(pctldev, pin_group);
+ if (ret < 0) {
+ dev_dbg(&pctldev->dev,
+ "%s does not support pin group %s with function %s\n",
+ pinctrl_dev_get_name(pctldev),
+ pin_group,
+ pmxops->get_function_name(pctldev, func_selector));
+ }
+ return ret;
+}
+
+/**
+ * pinmux_search_function() - check pin control driver for a certain function
+ * @pctldev: device to check for function and position
+ * @map: function map containing the function and position to look for
+ * @func_selector: returns the applicable function selector if found
+ * @group_selector: returns the applicable group selector if found
+ *
+ * This will search the pinmux driver for an applicable
+ * function with a specific pin group, returns 0 if these can be mapped
+ * negative otherwise
+ */
+static int pinmux_search_function(struct pinctrl_dev *pctldev,
+ struct pinmux_map const *map,
+ unsigned *func_selector,
+ unsigned *group_selector)
+{
+ const struct pinmux_ops *ops = pctldev->desc->pmxops;
+ unsigned selector = 0;
+
+ /* See if this pctldev has this function */
+ while (ops->list_functions(pctldev, selector) >= 0) {
+ const char *fname = ops->get_function_name(pctldev,
+ selector);
+ int ret;
+
+ if (!strcmp(map->function, fname)) {
+ /* Found the function, check pin group */
+ ret = pinmux_check_pin_group(pctldev, selector,
+ map->group);
+ if (ret < 0)
+ return ret;
+
+ /* This function and group selector can be used */
+ *func_selector = selector;
+ *group_selector = ret;
+ return 0;
+
+ }
+ selector++;
+ }
+
+ pr_err("%s does not support function %s\n",
+ pinctrl_dev_get_name(pctldev), map->function);
+ return -EINVAL;
+}
+
+/**
+ * pinmux_enable_muxmap() - enable a map entry for a certain pinmux
+ */
+static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
+ struct pinmux *pmx,
+ struct device *dev,
+ const char *devname,
+ struct pinmux_map const *map)
+{
+ unsigned func_selector;
+ unsigned group_selector;
+ struct pinmux_group *grp;
+ int ret;
+
+ /*
+ * Note that we're not locking the pinmux mutex here, because
+ * this is only called at pinmux initialization time when it
+ * has not been added to any list and thus is not reachable
+ * by anyone else.
+ */
+
+ if (pmx->pctldev && pmx->pctldev != pctldev) {
+ dev_err(&pctldev->dev,
+ "different pin control devices given for device %s, "
+ "function %s\n",
+ devname,
+ map->function);
+ return -EINVAL;
+ }
+ pmx->dev = dev;
+ pmx->pctldev = pctldev;
+
+ /* Now go into the driver and try to match a function and group */
+ ret = pinmux_search_function(pctldev, map, &func_selector,
+ &group_selector);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * If the function selector is already set, it needs to be identical,
+ * we support several groups with one function but not several
+ * functions with one or several groups in the same pinmux.
+ */
+ if (pmx->func_selector != UINT_MAX &&
+ pmx->func_selector != func_selector) {
+ dev_err(&pctldev->dev,
+ "dual function defines in the map for device %s\n",
+ devname);
+ return -EINVAL;
+ }
+ pmx->func_selector = func_selector;
+
+ /* Now add this group selector, we may have many of them */
+ grp = kmalloc(sizeof(struct pinmux_group), GFP_KERNEL);
+ if (!grp)
+ return -ENOMEM;
+ grp->group_selector = group_selector;
+ ret = acquire_pins(pctldev, func_selector, group_selector);
+ if (ret) {
+ kfree(grp);
+ return ret;
+ }
+ list_add(&grp->node, &pmx->groups);
+
+ return 0;
+}
+
+static void pinmux_free_groups(struct pinmux *pmx)
+{
+ struct list_head *node, *tmp;
+
+ list_for_each_safe(node, tmp, &pmx->groups) {
+ struct pinmux_group *grp =
+ list_entry(node, struct pinmux_group, node);
+ /* Release all pins taken by this group */
+ release_pins(pmx->pctldev, grp->group_selector);
+ list_del(node);
+ kfree(grp);
+ }
+}
+
+/**
+ * pinmux_get() - retrieves the pinmux for a certain device
+ * @dev: the device to get the pinmux for
+ * @name: an optional specific mux mapping name or NULL, the name is only
+ * needed if you want to have more than one mapping per device, or if you
+ * need an anonymous pinmux (not tied to any specific device)
+ */
+struct pinmux *pinmux_get(struct device *dev, const char *name)
+{
+
+ struct pinmux_map const *map = NULL;
+ struct pinctrl_dev *pctldev = NULL;
+ const char *devname = NULL;
+ struct pinmux *pmx;
+ bool found_map;
+ unsigned num_maps = 0;
+ int ret = -ENODEV;
+ int i;
+
+ /* We must have dev or ID or both */
+ if (!dev && !name)
+ return ERR_PTR(-EINVAL);
+
+ if (dev)
+ devname = dev_name(dev);
+
+ pr_debug("get mux %s for device %s\n", name,
+ devname ? devname : "(none)");
+
+ /*
+ * create the state cookie holder struct pinmux for each
+ * mapping, this is what consumers will get when requesting
+ * a pinmux handle with pinmux_get()
+ */
+ pmx = kzalloc(sizeof(struct pinmux), GFP_KERNEL);
+ if (pmx == NULL)
+ return ERR_PTR(-ENOMEM);
+ mutex_init(&pmx->mutex);
+ pmx->func_selector = UINT_MAX;
+ INIT_LIST_HEAD(&pmx->groups);
+
+ /* Iterate over the pinmux maps to locate the right ones */
+ for (i = 0; i < pinmux_maps_num; i++) {
+ map = &pinmux_maps[i];
+ found_map = false;
+
+ /*
+ * First, try to find the pctldev given in the map
+ */
+ pctldev = get_pinctrl_dev_from_dev(map->ctrl_dev,
+ map->ctrl_dev_name);
+ if (!pctldev) {
+ const char *devname = NULL;
+
+ if (map->ctrl_dev)
+ devname = dev_name(map->ctrl_dev);
+ else if (map->ctrl_dev_name)
+ devname = map->ctrl_dev_name;
+
+ pr_warning("could not find a pinctrl device for pinmux "
+ "function %s, fishy, they shall all have one\n",
+ map->function);
+ pr_warning("given pinctrl device name: %s",
+ devname ? devname : "UNDEFINED");
+
+ /* Continue to check the other mappings anyway... */
+ continue;
+ }
+
+ pr_debug("in map, found pctldev %s to handle function %s",
+ dev_name(&pctldev->dev), map->function);
+
+
+ /*
+ * If we're looking for a specific named map, this must match,
+ * else we loop and look for the next.
+ */
+ if (name != NULL) {
+ if (map->name == NULL)
+ continue;
+ if (strcmp(map->name, name))
+ continue;
+ }
+
+ /*
+ * This is for the case where no device name is given, we
+ * already know that the function name matches from above
+ * code.
+ */
+ if (!map->dev_name && (name != NULL))
+ found_map = true;
+
+ /* If the mapping has a device set up it must match */
+ if (map->dev_name &&
+ (!devname || !strcmp(map->dev_name, devname)))
+ /* MATCH! */
+ found_map = true;
+
+ /* If this map is applicable, then apply it */
+ if (found_map) {
+ ret = pinmux_enable_muxmap(pctldev, pmx, dev,
+ devname, map);
+ if (ret) {
+ pinmux_free_groups(pmx);
+ kfree(pmx);
+ return ERR_PTR(ret);
+ }
+ num_maps++;
+ }
+ }
+
+
+ /* We should have atleast one map, right */
+ if (!num_maps) {
+ pr_err("could not find any mux maps for device %s, ID %s\n",
+ devname ? devname : "(anonymous)",
+ name ? name : "(undefined)");
+ kfree(pmx);
+ return ERR_PTR(-EINVAL);
+ }
+
+ pr_debug("found %u mux maps for device %s, UD %s\n",
+ num_maps,
+ devname ? devname : "(anonymous)",
+ name ? name : "(undefined)");
+
+ /* Add the pinmux to the global list */
+ mutex_lock(&pinmux_list_mutex);
+ list_add(&pmx->node, &pinmux_list);
+ mutex_unlock(&pinmux_list_mutex);
+
+ return pmx;
+}
+EXPORT_SYMBOL_GPL(pinmux_get);
+
+/**
+ * pinmux_put() - release a previously claimed pinmux
+ * @pmx: a pinmux previously claimed by pinmux_get()
+ */
+void pinmux_put(struct pinmux *pmx)
+{
+ if (pmx == NULL)
+ return;
+
+ mutex_lock(&pmx->mutex);
+ if (pmx->usecount)
+ pr_warn("releasing pinmux with active users!\n");
+ /* Free the groups and all acquired pins */
+ pinmux_free_groups(pmx);
+ mutex_unlock(&pmx->mutex);
+
+ /* Remove from list */
+ mutex_lock(&pinmux_list_mutex);
+ list_del(&pmx->node);
+ mutex_unlock(&pinmux_list_mutex);
+
+ kfree(pmx);
+}
+EXPORT_SYMBOL_GPL(pinmux_put);
+
+/**
+ * pinmux_enable() - enable a certain pinmux setting
+ * @pmx: the pinmux to enable, previously claimed by pinmux_get()
+ */
+int pinmux_enable(struct pinmux *pmx)
+{
+ int ret = 0;
+
+ if (pmx == NULL)
+ return -EINVAL;
+ mutex_lock(&pmx->mutex);
+ if (pmx->usecount++ == 0) {
+ struct pinctrl_dev *pctldev = pmx->pctldev;
+ const struct pinmux_ops *ops = pctldev->desc->pmxops;
+ struct pinmux_group *grp;
+
+ list_for_each_entry(grp, &pmx->groups, node) {
+ ret = ops->enable(pctldev, pmx->func_selector,
+ grp->group_selector);
+ if (ret) {
+ /*
+ * TODO: call disable() on all groups we called
+ * enable() on to this point?
+ */
+ pmx->usecount--;
+ break;
+ }
+ }
+ }
+ mutex_unlock(&pmx->mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pinmux_enable);
+
+/**
+ * pinmux_disable() - disable a certain pinmux setting
+ * @pmx: the pinmux to disable, previously claimed by pinmux_get()
+ */
+void pinmux_disable(struct pinmux *pmx)
+{
+ if (pmx == NULL)
+ return;
+
+ mutex_lock(&pmx->mutex);
+ if (--pmx->usecount == 0) {
+ struct pinctrl_dev *pctldev = pmx->pctldev;
+ const struct pinmux_ops *ops = pctldev->desc->pmxops;
+ struct pinmux_group *grp;
+
+ list_for_each_entry(grp, &pmx->groups, node) {
+ ops->disable(pctldev, pmx->func_selector,
+ grp->group_selector);
+ }
+ }
+ mutex_unlock(&pmx->mutex);
+}
+EXPORT_SYMBOL_GPL(pinmux_disable);
+
+int pinmux_check_ops(const struct pinmux_ops *ops)
+{
+ /* Check that we implement required operations */
+ if (!ops->list_functions ||
+ !ops->get_function_name ||
+ !ops->get_function_groups ||
+ !ops->enable ||
+ !ops->disable)
+ return -EINVAL;
+
+ return 0;
+}
+
+/* Hog a single map entry and add to the hoglist */
+static int pinmux_hog_map(struct pinctrl_dev *pctldev,
+ struct pinmux_map const *map)
+{
+ struct pinmux_hog *hog;
+ struct pinmux *pmx;
+ int ret;
+
+ if (map->dev || map->dev_name) {
+ /*
+ * TODO: the day we have device tree support, we can
+ * traverse the device tree and hog to specific device nodes
+ * without any problems, so then we can hog pinmuxes for
+ * all devices that just want a static pin mux at this point.
+ */
+ dev_err(&pctldev->dev, "map %s wants to hog a non-system "
+ "pinmux, this is not going to work\n", map->name);
+ return -EINVAL;
+ }
+
+ hog = kzalloc(sizeof(struct pinmux_hog), GFP_KERNEL);
+ if (!hog)
+ return -ENOMEM;
+
+ pmx = pinmux_get(NULL, map->name);
+ if (IS_ERR(pmx)) {
+ kfree(hog);
+ dev_err(&pctldev->dev,
+ "could not get the %s pinmux mapping for hogging\n",
+ map->name);
+ return PTR_ERR(pmx);
+ }
+
+ ret = pinmux_enable(pmx);
+ if (ret) {
+ pinmux_put(pmx);
+ kfree(hog);
+ dev_err(&pctldev->dev,
+ "could not enable the %s pinmux mapping for hogging\n",
+ map->name);
+ return ret;
+ }
+
+ hog->map = map;
+ hog->pmx = pmx;
+
+ dev_info(&pctldev->dev, "hogged map %s, function %s\n", map->name,
+ map->function);
+ mutex_lock(&pctldev->pinmux_hogs_lock);
+ list_add(&hog->node, &pctldev->pinmux_hogs);
+ mutex_unlock(&pctldev->pinmux_hogs_lock);
+
+ return 0;
+}
+
+/**
+ * pinmux_hog_maps() - hog specific map entries on controller device
+ * @pctldev: the pin control device to hog entries on
+ *
+ * When the pin controllers are registered, there may be some specific pinmux
+ * map entries that need to be hogged, i.e. get+enabled until the system shuts
+ * down.
+ */
+int pinmux_hog_maps(struct pinctrl_dev *pctldev)
+{
+ struct device *dev = &pctldev->dev;
+ const char *devname = dev_name(dev);
+ int ret;
+ int i;
+
+ INIT_LIST_HEAD(&pctldev->pinmux_hogs);
+ mutex_init(&pctldev->pinmux_hogs_lock);
+
+ for (i = 0; i < pinmux_maps_num; i++) {
+ struct pinmux_map const *map = &pinmux_maps[i];
+
+ if (((map->ctrl_dev == dev) ||
+ !strcmp(map->ctrl_dev_name, devname)) &&
+ map->hog_on_boot) {
+ /* OK time to hog! */
+ ret = pinmux_hog_map(pctldev, map);
+ if (ret)
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/**
+ * pinmux_hog_maps() - unhog specific map entries on controller device
+ * @pctldev: the pin control device to unhog entries on
+ */
+void pinmux_unhog_maps(struct pinctrl_dev *pctldev)
+{
+ struct list_head *node, *tmp;
+
+ mutex_lock(&pctldev->pinmux_hogs_lock);
+ list_for_each_safe(node, tmp, &pctldev->pinmux_hogs) {
+ struct pinmux_hog *hog =
+ list_entry(node, struct pinmux_hog, node);
+ pinmux_disable(hog->pmx);
+ pinmux_put(hog->pmx);
+ list_del(node);
+ kfree(hog);
+ }
+ mutex_unlock(&pctldev->pinmux_hogs_lock);
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+/* Called from pincontrol core */
+static int pinmux_functions_show(struct seq_file *s, void *what)
+{
+ struct pinctrl_dev *pctldev = s->private;
+ const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
+ unsigned func_selector = 0;
+
+ while (pmxops->list_functions(pctldev, func_selector) >= 0) {
+ const char *func = pmxops->get_function_name(pctldev,
+ func_selector);
+ const char * const *groups;
+ unsigned num_groups;
+ int ret;
+ int i;
+
+ ret = pmxops->get_function_groups(pctldev, func_selector,
+ &groups, &num_groups);
+ if (ret)
+ seq_printf(s, "function %s: COULD NOT GET GROUPS\n",
+ func);
+
+ seq_printf(s, "function: %s, groups = [ ", func);
+ for (i = 0; i < num_groups; i++)
+ seq_printf(s, "%s ", groups[i]);
+ seq_puts(s, "]\n");
+
+ func_selector++;
+
+ }
+
+ return 0;
+}
+
+static int pinmux_pins_show(struct seq_file *s, void *what)
+{
+ struct pinctrl_dev *pctldev = s->private;
+ unsigned pin;
+
+ seq_puts(s, "Pinmux settings per pin\n");
+ seq_puts(s, "Format: pin (name): pinmuxfunction\n");
+
+ /* The highest pin number need to be included in the loop, thus <= */
+ for (pin = 0; pin <= pctldev->desc->maxpin; pin++) {
+
+ struct pin_desc *desc;
+
+ desc = pin_desc_get(pctldev, pin);
+ /* Pin space may be sparse */
+ if (desc == NULL)
+ continue;
+
+ seq_printf(s, "pin %d (%s): %s\n", pin,
+ desc->name ? desc->name : "unnamed",
+ desc->mux_function ? desc->mux_function
+ : "UNCLAIMED");
+ }
+
+ return 0;
+}
+
+static int pinmux_hogs_show(struct seq_file *s, void *what)
+{
+ struct pinctrl_dev *pctldev = s->private;
+ struct pinmux_hog *hog;
+
+ seq_puts(s, "Pinmux map hogs held by device\n");
+
+ list_for_each_entry(hog, &pctldev->pinmux_hogs, node)
+ seq_printf(s, "%s\n", hog->map->name);
+
+ return 0;
+}
+
+static int pinmux_show(struct seq_file *s, void *what)
+{
+ struct pinmux *pmx;
+
+ seq_puts(s, "Requested pinmuxes and their maps:\n");
+ list_for_each_entry(pmx, &pinmux_list, node) {
+ struct pinctrl_dev *pctldev = pmx->pctldev;
+ const struct pinmux_ops *pmxops;
+ const struct pinctrl_ops *pctlops;
+ struct pinmux_group *grp;
+
+ if (!pctldev) {
+ seq_puts(s, "NO PIN CONTROLLER DEVICE\n");
+ continue;
+ }
+
+ pmxops = pctldev->desc->pmxops;
+ pctlops = pctldev->desc->pctlops;
+
+ seq_printf(s, "device: %s function: %s (%u),",
+ pinctrl_dev_get_name(pmx->pctldev),
+ pmxops->get_function_name(pctldev, pmx->func_selector),
+ pmx->func_selector);
+
+ seq_printf(s, " groups: [");
+ list_for_each_entry(grp, &pmx->groups, node) {
+ seq_printf(s, " %s (%u)",
+ pctlops->get_group_name(pctldev, grp->group_selector),
+ grp->group_selector);
+ }
+ seq_printf(s, " ]");
+
+ seq_printf(s, " users: %u map-> %s\n",
+ pmx->usecount,
+ pmx->dev ? dev_name(pmx->dev) : "(system)");
+ }
+
+ return 0;
+}
+
+static int pinmux_maps_show(struct seq_file *s, void *what)
+{
+ int i;
+
+ seq_puts(s, "Pinmux maps:\n");
+
+ for (i = 0; i < pinmux_maps_num; i++) {
+ struct pinmux_map const *map = &pinmux_maps[i];
+
+ seq_printf(s, "%s:\n", map->name);
+ if (map->dev || map->dev_name)
+ seq_printf(s, " device: %s\n",
+ map->dev ? dev_name(map->dev) :
+ map->dev_name);
+ else
+ seq_printf(s, " SYSTEM MUX\n");
+ seq_printf(s, " controlling device %s\n",
+ map->ctrl_dev ? dev_name(map->ctrl_dev) :
+ map->ctrl_dev_name);
+ seq_printf(s, " function: %s\n", map->function);
+ seq_printf(s, " group: %s\n", map->group ? map->group :
+ "(default)");
+ }
+ return 0;
+}
+
+static int pinmux_functions_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinmux_functions_show, inode->i_private);
+}
+
+static int pinmux_pins_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinmux_pins_show, inode->i_private);
+}
+
+static int pinmux_hogs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinmux_hogs_show, inode->i_private);
+}
+
+static int pinmux_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinmux_show, NULL);
+}
+
+static int pinmux_maps_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinmux_maps_show, NULL);
+}
+
+static const struct file_operations pinmux_functions_ops = {
+ .open = pinmux_functions_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinmux_pins_ops = {
+ .open = pinmux_pins_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinmux_hogs_ops = {
+ .open = pinmux_hogs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinmux_ops = {
+ .open = pinmux_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinmux_maps_ops = {
+ .open = pinmux_maps_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+void pinmux_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev)
+{
+ debugfs_create_file("pinmux-functions", S_IFREG | S_IRUGO,
+ devroot, pctldev, &pinmux_functions_ops);
+ debugfs_create_file("pinmux-pins", S_IFREG | S_IRUGO,
+ devroot, pctldev, &pinmux_pins_ops);
+ debugfs_create_file("pinmux-hogs", S_IFREG | S_IRUGO,
+ devroot, pctldev, &pinmux_hogs_ops);
+}
+
+void pinmux_init_debugfs(struct dentry *subsys_root)
+{
+ debugfs_create_file("pinmuxes", S_IFREG | S_IRUGO,
+ subsys_root, NULL, &pinmux_ops);
+ debugfs_create_file("pinmux-maps", S_IFREG | S_IRUGO,
+ subsys_root, NULL, &pinmux_maps_ops);
+}
+
+#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h
new file mode 100644
index 000000000000..844500b3331b
--- /dev/null
+++ b/drivers/pinctrl/pinmux.h
@@ -0,0 +1,47 @@
+/*
+ * Internal interface between the core pin control system and the
+ * pinmux portions
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ * Based on bits of regulator core, gpio core and clk core
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifdef CONFIG_PINMUX
+
+int pinmux_check_ops(const struct pinmux_ops *ops);
+void pinmux_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev);
+void pinmux_init_debugfs(struct dentry *subsys_root);
+int pinmux_hog_maps(struct pinctrl_dev *pctldev);
+void pinmux_unhog_maps(struct pinctrl_dev *pctldev);
+
+#else
+
+static inline int pinmux_check_ops(const struct pinmux_ops *ops)
+{
+ return 0;
+}
+
+static inline void pinmux_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev)
+{
+}
+
+static inline void pinmux_init_debugfs(struct dentry *subsys_root)
+{
+}
+
+static inline int pinmux_hog_maps(struct pinctrl_dev *pctldev)
+{
+ return 0;
+}
+
+static inline void pinmux_unhog_maps(struct pinctrl_dev *pctldev)
+{
+}
+
+#endif
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 1e88d4785321..f4e3d82379d7 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -31,9 +31,6 @@ config ACER_WMI
wireless radio and bluetooth control, and on some laptops,
exposes the mail LED and LCD backlight.
- For more information about this driver see
- <file:Documentation/laptops/acer-wmi.txt>
-
If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M
here.
@@ -64,15 +61,18 @@ config ASUS_LAPTOP
depends on INPUT
depends on RFKILL || RFKILL = n
select INPUT_SPARSEKMAP
+ select INPUT_POLLDEV
---help---
- This is the new Linux driver for Asus laptops. It may also support some
- MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
- standard ACPI events and input events. It also adds
- support for video output switching, LCD backlight control, Bluetooth and
- Wlan control, and most importantly, allows you to blink those fancy LEDs.
+ This is a driver for Asus laptops, Lenovo SL and the Pegatron
+ Lucid tablet. It may also support some MEDION, JVC or VICTOR
+ laptops. It makes all the extra buttons generate standard
+ ACPI events and input events, and on the Lucid the built-in
+ accelerometer appears as an input device. It also adds
+ support for video output switching, LCD backlight control,
+ Bluetooth and Wlan control, and most importantly, allows you
+ to blink those fancy LEDs.
- For more information and a userspace daemon for handling the extra
- buttons see <http://acpi4asus.sf.net>.
+ For more information see <http://acpi4asus.sf.net>.
If you have an ACPI-compatible ASUS laptop, say Y or M here.
@@ -164,7 +164,7 @@ config HP_ACCEL
Support for a led indicating disk protection will be provided as
hp::hddprotect. For more information on the feature, refer to
- Documentation/hwmon/lis3lv02d.
+ Documentation/misc-devices/lis3lv02d.
To compile this driver as a module, choose M here: the module will
be called hp_accel.
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index af2bb20cb2fb..b848277171a4 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -190,6 +190,7 @@ enum interface_flags {
ACER_AMW0,
ACER_AMW0_V2,
ACER_WMID,
+ ACER_WMID_v2,
};
#define ACER_DEFAULT_WIRELESS 0
@@ -205,6 +206,7 @@ static int threeg = -1;
static int force_series;
static bool ec_raw_mode;
static bool has_type_aa;
+static u16 commun_func_bitmap;
module_param(mailled, int, 0444);
module_param(brightness, int, 0444);
@@ -464,6 +466,15 @@ static struct dmi_system_id acer_quirks[] = {
},
.driver_data = &quirk_lenovo_ideapad_s205,
},
+ {
+ .callback = dmi_matched,
+ .ident = "Lenovo 3000 N200",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "0687A31"),
+ },
+ .driver_data = &quirk_fujitsu_amilo_li_1718,
+ },
{}
};
@@ -868,6 +879,174 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
return WMI_execute_u32(method_id, (u32)value, NULL);
}
+static acpi_status wmid3_get_device_status(u32 *value, u16 device)
+{
+ struct wmid3_gds_return_value return_value;
+ acpi_status status;
+ union acpi_object *obj;
+ struct wmid3_gds_input_param params = {
+ .function_num = 0x1,
+ .hotkey_number = 0x01,
+ .devices = device,
+ };
+ struct acpi_buffer input = {
+ sizeof(struct wmid3_gds_input_param),
+ &params
+ };
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ obj = output.pointer;
+
+ if (!obj)
+ return AE_ERROR;
+ else if (obj->type != ACPI_TYPE_BUFFER) {
+ kfree(obj);
+ return AE_ERROR;
+ }
+ if (obj->buffer.length != 8) {
+ pr_warn("Unknown buffer length %d\n", obj->buffer.length);
+ kfree(obj);
+ return AE_ERROR;
+ }
+
+ return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+ kfree(obj);
+
+ if (return_value.error_code || return_value.ec_return_value)
+ pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n",
+ device,
+ return_value.error_code,
+ return_value.ec_return_value);
+ else
+ *value = !!(return_value.devices & device);
+
+ return status;
+}
+
+static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
+{
+ u16 device;
+
+ switch (cap) {
+ case ACER_CAP_WIRELESS:
+ device = ACER_WMID3_GDS_WIRELESS;
+ break;
+ case ACER_CAP_BLUETOOTH:
+ device = ACER_WMID3_GDS_BLUETOOTH;
+ break;
+ case ACER_CAP_THREEG:
+ device = ACER_WMID3_GDS_THREEG;
+ break;
+ default:
+ return AE_ERROR;
+ }
+ return wmid3_get_device_status(value, device);
+}
+
+static acpi_status wmid3_set_device_status(u32 value, u16 device)
+{
+ struct wmid3_gds_return_value return_value;
+ acpi_status status;
+ union acpi_object *obj;
+ u16 devices;
+ struct wmid3_gds_input_param params = {
+ .function_num = 0x1,
+ .hotkey_number = 0x01,
+ .devices = commun_func_bitmap,
+ };
+ struct acpi_buffer input = {
+ sizeof(struct wmid3_gds_input_param),
+ &params
+ };
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ obj = output.pointer;
+
+ if (!obj)
+ return AE_ERROR;
+ else if (obj->type != ACPI_TYPE_BUFFER) {
+ kfree(obj);
+ return AE_ERROR;
+ }
+ if (obj->buffer.length != 8) {
+ pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+ kfree(obj);
+ return AE_ERROR;
+ }
+
+ return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+ kfree(obj);
+
+ if (return_value.error_code || return_value.ec_return_value) {
+ pr_warning("Get Current Device Status failed: "
+ "0x%x - 0x%x\n", return_value.error_code,
+ return_value.ec_return_value);
+ return status;
+ }
+
+ devices = return_value.devices;
+ params.function_num = 0x2;
+ params.hotkey_number = 0x01;
+ params.devices = (value) ? (devices | device) : (devices & ~device);
+
+ status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ obj = output2.pointer;
+
+ if (!obj)
+ return AE_ERROR;
+ else if (obj->type != ACPI_TYPE_BUFFER) {
+ kfree(obj);
+ return AE_ERROR;
+ }
+ if (obj->buffer.length != 4) {
+ pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+ kfree(obj);
+ return AE_ERROR;
+ }
+
+ return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+ kfree(obj);
+
+ if (return_value.error_code || return_value.ec_return_value)
+ pr_warning("Set Device Status failed: "
+ "0x%x - 0x%x\n", return_value.error_code,
+ return_value.ec_return_value);
+
+ return status;
+}
+
+static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
+{
+ u16 device;
+
+ switch (cap) {
+ case ACER_CAP_WIRELESS:
+ device = ACER_WMID3_GDS_WIRELESS;
+ break;
+ case ACER_CAP_BLUETOOTH:
+ device = ACER_WMID3_GDS_BLUETOOTH;
+ break;
+ case ACER_CAP_THREEG:
+ device = ACER_WMID3_GDS_THREEG;
+ break;
+ default:
+ return AE_ERROR;
+ }
+ return wmid3_set_device_status(value, device);
+}
+
static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
{
struct hotkey_function_type_aa *type_aa;
@@ -881,6 +1060,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
pr_info("Function bitmap for Communication Button: 0x%x\n",
type_aa->commun_func_bitmap);
+ commun_func_bitmap = type_aa->commun_func_bitmap;
if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
interface->capability |= ACER_CAP_WIRELESS;
@@ -913,17 +1093,13 @@ static acpi_status WMID_set_capabilities(void)
return AE_ERROR;
}
- dmi_walk(type_aa_dmi_decode, NULL);
- if (!has_type_aa) {
+ pr_info("Function bitmap for Communication Device: 0x%x\n", devices);
+ if (devices & 0x07)
interface->capability |= ACER_CAP_WIRELESS;
- if (devices & 0x40)
- interface->capability |= ACER_CAP_THREEG;
- if (devices & 0x10)
- interface->capability |= ACER_CAP_BLUETOOTH;
- }
-
- /* WMID always provides brightness methods */
- interface->capability |= ACER_CAP_BRIGHTNESS;
+ if (devices & 0x40)
+ interface->capability |= ACER_CAP_THREEG;
+ if (devices & 0x10)
+ interface->capability |= ACER_CAP_BLUETOOTH;
if (!(devices & 0x20))
max_brightness = 0x9;
@@ -936,6 +1112,10 @@ static struct wmi_interface wmid_interface = {
.type = ACER_WMID,
};
+static struct wmi_interface wmid_v2_interface = {
+ .type = ACER_WMID_v2,
+};
+
/*
* Generic Device (interface-independent)
*/
@@ -956,6 +1136,14 @@ static acpi_status get_u32(u32 *value, u32 cap)
case ACER_WMID:
status = WMID_get_u32(value, cap, interface);
break;
+ case ACER_WMID_v2:
+ if (cap & (ACER_CAP_WIRELESS |
+ ACER_CAP_BLUETOOTH |
+ ACER_CAP_THREEG))
+ status = wmid_v2_get_u32(value, cap);
+ else if (wmi_has_guid(WMID_GUID2))
+ status = WMID_get_u32(value, cap, interface);
+ break;
}
return status;
@@ -989,6 +1177,13 @@ static acpi_status set_u32(u32 value, u32 cap)
}
case ACER_WMID:
return WMID_set_u32(value, cap, interface);
+ case ACER_WMID_v2:
+ if (cap & (ACER_CAP_WIRELESS |
+ ACER_CAP_BLUETOOTH |
+ ACER_CAP_THREEG))
+ return wmid_v2_set_u32(value, cap);
+ else if (wmi_has_guid(WMID_GUID2))
+ return WMID_set_u32(value, cap, interface);
default:
return AE_BAD_PARAMETER;
}
@@ -1095,186 +1290,6 @@ static void acer_backlight_exit(void)
backlight_device_unregister(acer_backlight_device);
}
-static acpi_status wmid3_get_device_status(u32 *value, u16 device)
-{
- struct wmid3_gds_return_value return_value;
- acpi_status status;
- union acpi_object *obj;
- struct wmid3_gds_input_param params = {
- .function_num = 0x1,
- .hotkey_number = 0x01,
- .devices = device,
- };
- struct acpi_buffer input = {
- sizeof(struct wmid3_gds_input_param),
- &params
- };
- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-
- status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
- if (ACPI_FAILURE(status))
- return status;
-
- obj = output.pointer;
-
- if (!obj)
- return AE_ERROR;
- else if (obj->type != ACPI_TYPE_BUFFER) {
- kfree(obj);
- return AE_ERROR;
- }
- if (obj->buffer.length != 8) {
- pr_warn("Unknown buffer length %d\n", obj->buffer.length);
- kfree(obj);
- return AE_ERROR;
- }
-
- return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
- kfree(obj);
-
- if (return_value.error_code || return_value.ec_return_value)
- pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
- return_value.error_code,
- return_value.ec_return_value);
- else
- *value = !!(return_value.devices & device);
-
- return status;
-}
-
-static acpi_status get_device_status(u32 *value, u32 cap)
-{
- if (wmi_has_guid(WMID_GUID3)) {
- u16 device;
-
- switch (cap) {
- case ACER_CAP_WIRELESS:
- device = ACER_WMID3_GDS_WIRELESS;
- break;
- case ACER_CAP_BLUETOOTH:
- device = ACER_WMID3_GDS_BLUETOOTH;
- break;
- case ACER_CAP_THREEG:
- device = ACER_WMID3_GDS_THREEG;
- break;
- default:
- return AE_ERROR;
- }
- return wmid3_get_device_status(value, device);
-
- } else {
- return get_u32(value, cap);
- }
-}
-
-static acpi_status wmid3_set_device_status(u32 value, u16 device)
-{
- struct wmid3_gds_return_value return_value;
- acpi_status status;
- union acpi_object *obj;
- u16 devices;
- struct wmid3_gds_input_param params = {
- .function_num = 0x1,
- .hotkey_number = 0x01,
- .devices = ACER_WMID3_GDS_WIRELESS |
- ACER_WMID3_GDS_THREEG |
- ACER_WMID3_GDS_WIMAX |
- ACER_WMID3_GDS_BLUETOOTH,
- };
- struct acpi_buffer input = {
- sizeof(struct wmid3_gds_input_param),
- &params
- };
- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
-
- status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
- if (ACPI_FAILURE(status))
- return status;
-
- obj = output.pointer;
-
- if (!obj)
- return AE_ERROR;
- else if (obj->type != ACPI_TYPE_BUFFER) {
- kfree(obj);
- return AE_ERROR;
- }
- if (obj->buffer.length != 8) {
- pr_warning("Unknown buffer length %d\n", obj->buffer.length);
- kfree(obj);
- return AE_ERROR;
- }
-
- return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
- kfree(obj);
-
- if (return_value.error_code || return_value.ec_return_value) {
- pr_warning("Get Current Device Status failed: "
- "0x%x - 0x%x\n", return_value.error_code,
- return_value.ec_return_value);
- return status;
- }
-
- devices = return_value.devices;
- params.function_num = 0x2;
- params.hotkey_number = 0x01;
- params.devices = (value) ? (devices | device) : (devices & ~device);
-
- status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
- if (ACPI_FAILURE(status))
- return status;
-
- obj = output2.pointer;
-
- if (!obj)
- return AE_ERROR;
- else if (obj->type != ACPI_TYPE_BUFFER) {
- kfree(obj);
- return AE_ERROR;
- }
- if (obj->buffer.length != 4) {
- pr_warning("Unknown buffer length %d\n", obj->buffer.length);
- kfree(obj);
- return AE_ERROR;
- }
-
- return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
- kfree(obj);
-
- if (return_value.error_code || return_value.ec_return_value)
- pr_warning("Set Device Status failed: "
- "0x%x - 0x%x\n", return_value.error_code,
- return_value.ec_return_value);
-
- return status;
-}
-
-static acpi_status set_device_status(u32 value, u32 cap)
-{
- if (wmi_has_guid(WMID_GUID3)) {
- u16 device;
-
- switch (cap) {
- case ACER_CAP_WIRELESS:
- device = ACER_WMID3_GDS_WIRELESS;
- break;
- case ACER_CAP_BLUETOOTH:
- device = ACER_WMID3_GDS_BLUETOOTH;
- break;
- case ACER_CAP_THREEG:
- device = ACER_WMID3_GDS_THREEG;
- break;
- default:
- return AE_ERROR;
- }
- return wmid3_set_device_status(value, device);
-
- } else {
- return set_u32(value, cap);
- }
-}
-
/*
* Rfkill devices
*/
@@ -1285,12 +1300,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
u32 state;
acpi_status status;
- status = get_u32(&state, ACER_CAP_WIRELESS);
- if (ACPI_SUCCESS(status)) {
- if (quirks->wireless == 3) {
- rfkill_set_hw_state(wireless_rfkill, !state);
- } else {
- rfkill_set_sw_state(wireless_rfkill, !state);
+ if (has_cap(ACER_CAP_WIRELESS)) {
+ status = get_u32(&state, ACER_CAP_WIRELESS);
+ if (ACPI_SUCCESS(status)) {
+ if (quirks->wireless == 3)
+ rfkill_set_hw_state(wireless_rfkill, !state);
+ else
+ rfkill_set_sw_state(wireless_rfkill, !state);
}
}
@@ -1301,8 +1317,7 @@ static void acer_rfkill_update(struct work_struct *ignored)
}
if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
- status = wmid3_get_device_status(&state,
- ACER_WMID3_GDS_THREEG);
+ status = get_u32(&state, ACER_WMID3_GDS_THREEG);
if (ACPI_SUCCESS(status))
rfkill_set_sw_state(threeg_rfkill, !state);
}
@@ -1316,7 +1331,7 @@ static int acer_rfkill_set(void *data, bool blocked)
u32 cap = (unsigned long)data;
if (rfkill_inited) {
- status = set_device_status(!blocked, cap);
+ status = set_u32(!blocked, cap);
if (ACPI_FAILURE(status))
return -ENODEV;
}
@@ -1343,7 +1358,7 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
if (!rfkill_dev)
return ERR_PTR(-ENOMEM);
- status = get_device_status(&state, cap);
+ status = get_u32(&state, cap);
err = rfkill_register(rfkill_dev);
if (err) {
@@ -1359,19 +1374,24 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
static int acer_rfkill_init(struct device *dev)
{
- wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
- "acer-wireless", ACER_CAP_WIRELESS);
- if (IS_ERR(wireless_rfkill))
- return PTR_ERR(wireless_rfkill);
+ int err;
+
+ if (has_cap(ACER_CAP_WIRELESS)) {
+ wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
+ "acer-wireless", ACER_CAP_WIRELESS);
+ if (IS_ERR(wireless_rfkill)) {
+ err = PTR_ERR(wireless_rfkill);
+ goto error_wireless;
+ }
+ }
if (has_cap(ACER_CAP_BLUETOOTH)) {
bluetooth_rfkill = acer_rfkill_register(dev,
RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
ACER_CAP_BLUETOOTH);
if (IS_ERR(bluetooth_rfkill)) {
- rfkill_unregister(wireless_rfkill);
- rfkill_destroy(wireless_rfkill);
- return PTR_ERR(bluetooth_rfkill);
+ err = PTR_ERR(bluetooth_rfkill);
+ goto error_bluetooth;
}
}
@@ -1380,30 +1400,44 @@ static int acer_rfkill_init(struct device *dev)
RFKILL_TYPE_WWAN, "acer-threeg",
ACER_CAP_THREEG);
if (IS_ERR(threeg_rfkill)) {
- rfkill_unregister(wireless_rfkill);
- rfkill_destroy(wireless_rfkill);
- rfkill_unregister(bluetooth_rfkill);
- rfkill_destroy(bluetooth_rfkill);
- return PTR_ERR(threeg_rfkill);
+ err = PTR_ERR(threeg_rfkill);
+ goto error_threeg;
}
}
rfkill_inited = true;
- if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
+ if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
+ has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
schedule_delayed_work(&acer_rfkill_work,
round_jiffies_relative(HZ));
return 0;
+
+error_threeg:
+ if (has_cap(ACER_CAP_BLUETOOTH)) {
+ rfkill_unregister(bluetooth_rfkill);
+ rfkill_destroy(bluetooth_rfkill);
+ }
+error_bluetooth:
+ if (has_cap(ACER_CAP_WIRELESS)) {
+ rfkill_unregister(wireless_rfkill);
+ rfkill_destroy(wireless_rfkill);
+ }
+error_wireless:
+ return err;
}
static void acer_rfkill_exit(void)
{
- if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
+ if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
+ has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
cancel_delayed_work_sync(&acer_rfkill_work);
- rfkill_unregister(wireless_rfkill);
- rfkill_destroy(wireless_rfkill);
+ if (has_cap(ACER_CAP_WIRELESS)) {
+ rfkill_unregister(wireless_rfkill);
+ rfkill_destroy(wireless_rfkill);
+ }
if (has_cap(ACER_CAP_BLUETOOTH)) {
rfkill_unregister(bluetooth_rfkill);
@@ -1428,11 +1462,7 @@ static ssize_t show_bool_threeg(struct device *dev,
pr_info("This threeg sysfs will be removed in 2012"
" - used by: %s\n", current->comm);
- if (wmi_has_guid(WMID_GUID3))
- status = wmid3_get_device_status(&result,
- ACER_WMID3_GDS_THREEG);
- else
- status = get_u32(&result, ACER_CAP_THREEG);
+ status = get_u32(&result, ACER_CAP_THREEG);
if (ACPI_SUCCESS(status))
return sprintf(buf, "%u\n", result);
return sprintf(buf, "Read error\n");
@@ -1464,6 +1494,8 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "AMW0 v2\n");
case ACER_WMID:
return sprintf(buf, "WMID\n");
+ case ACER_WMID_v2:
+ return sprintf(buf, "WMID v2\n");
default:
return sprintf(buf, "Error!\n");
}
@@ -1883,12 +1915,20 @@ static int __init acer_wmi_init(void)
if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
interface = &wmid_interface;
+ if (wmi_has_guid(WMID_GUID3))
+ interface = &wmid_v2_interface;
+
+ if (interface)
+ dmi_walk(type_aa_dmi_decode, NULL);
+
if (wmi_has_guid(WMID_GUID2) && interface) {
- if (ACPI_FAILURE(WMID_set_capabilities())) {
+ if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
pr_err("Unable to detect available WMID devices\n");
return -ENODEV;
}
- } else if (!wmi_has_guid(WMID_GUID2) && interface) {
+ /* WMID always provides brightness methods */
+ interface->capability |= ACER_CAP_BRIGHTNESS;
+ } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
pr_err("No WMID device detection method found\n");
return -ENODEV;
}
@@ -1912,7 +1952,7 @@ static int __init acer_wmi_init(void)
set_quirks();
- if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
+ if (acpi_video_backlight_support()) {
interface->capability &= ~ACER_CAP_BRIGHTNESS;
pr_info("Brightness must be controlled by "
"generic video driver\n");
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index fa6d7ec68b26..edaccad9b5bf 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor
* Copyright (C) 2006-2007 Corentin Chary
+ * Copyright (C) 2011 Wind River Systems
*
* 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
@@ -48,6 +49,7 @@
#include <linux/uaccess.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
+#include <linux/input-polldev.h>
#include <linux/rfkill.h>
#include <linux/slab.h>
#include <linux/dmi.h>
@@ -83,26 +85,32 @@ static int wlan_status = 1;
static int bluetooth_status = 1;
static int wimax_status = -1;
static int wwan_status = -1;
+static int als_status;
module_param(wlan_status, int, 0444);
MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
- "default is 1");
+ "default is -1");
module_param(bluetooth_status, int, 0444);
MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
- "default is 1");
+ "default is -1");
module_param(wimax_status, int, 0444);
MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
- "default is 1");
+ "default is -1");
module_param(wwan_status, int, 0444);
MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
- "default is 1");
+ "default is -1");
+
+module_param(als_status, int, 0444);
+MODULE_PARM_DESC(als_status, "Set the ALS status on boot "
+ "(0 = disabled, 1 = enabled). "
+ "default is 0");
/*
* Some events we use, same for all Asus
@@ -173,6 +181,29 @@ MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
#define METHOD_KBD_LIGHT_SET "SLKB"
#define METHOD_KBD_LIGHT_GET "GLKB"
+/* For Pegatron Lucid tablet */
+#define DEVICE_NAME_PEGA "Lucid"
+
+#define METHOD_PEGA_ENABLE "ENPR"
+#define METHOD_PEGA_DISABLE "DAPR"
+#define PEGA_WLAN 0x00
+#define PEGA_BLUETOOTH 0x01
+#define PEGA_WWAN 0x02
+#define PEGA_ALS 0x04
+#define PEGA_ALS_POWER 0x05
+
+#define METHOD_PEGA_READ "RDLN"
+#define PEGA_READ_ALS_H 0x02
+#define PEGA_READ_ALS_L 0x03
+
+#define PEGA_ACCEL_NAME "pega_accel"
+#define PEGA_ACCEL_DESC "Pegatron Lucid Tablet Accelerometer"
+#define METHOD_XLRX "XLRX"
+#define METHOD_XLRY "XLRY"
+#define METHOD_XLRZ "XLRZ"
+#define PEGA_ACC_CLAMP 512 /* 1G accel is reported as ~256, so clamp to 2G */
+#define PEGA_ACC_RETRIES 3
+
/*
* Define a specific led structure to keep the main structure clean
*/
@@ -185,6 +216,15 @@ struct asus_led {
};
/*
+ * Same thing for rfkill
+ */
+struct asus_pega_rfkill {
+ int control_id; /* type of control. Maps to PEGA_* values */
+ struct rfkill *rfkill;
+ struct asus_laptop *asus;
+};
+
+/*
* This is the main structure, we can use it to store anything interesting
* about the hotk device
*/
@@ -198,6 +238,7 @@ struct asus_laptop {
struct input_dev *inputdev;
struct key_entry *keymap;
+ struct input_polled_dev *pega_accel_poll;
struct asus_led mled;
struct asus_led tled;
@@ -209,9 +250,18 @@ struct asus_laptop {
int wireless_status;
bool have_rsts;
+ bool is_pega_lucid;
+ bool pega_acc_live;
+ int pega_acc_x;
+ int pega_acc_y;
+ int pega_acc_z;
struct rfkill *gps_rfkill;
+ struct asus_pega_rfkill wlanrfk;
+ struct asus_pega_rfkill btrfk;
+ struct asus_pega_rfkill wwanrfk;
+
acpi_handle handle; /* the handle of the hotk device */
u32 ledd_status; /* status of the LED display */
u8 light_level; /* light sensor level */
@@ -323,6 +373,127 @@ static int acpi_check_handle(acpi_handle handle, const char *method,
return 0;
}
+static bool asus_check_pega_lucid(struct asus_laptop *asus)
+{
+ return !strcmp(asus->name, DEVICE_NAME_PEGA) &&
+ !acpi_check_handle(asus->handle, METHOD_PEGA_ENABLE, NULL) &&
+ !acpi_check_handle(asus->handle, METHOD_PEGA_DISABLE, NULL) &&
+ !acpi_check_handle(asus->handle, METHOD_PEGA_READ, NULL);
+}
+
+static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable)
+{
+ char *method = enable ? METHOD_PEGA_ENABLE : METHOD_PEGA_DISABLE;
+ return write_acpi_int(asus->handle, method, unit);
+}
+
+static int pega_acc_axis(struct asus_laptop *asus, int curr, char *method)
+{
+ int i, delta;
+ unsigned long long val;
+ for (i = 0; i < PEGA_ACC_RETRIES; i++) {
+ acpi_evaluate_integer(asus->handle, method, NULL, &val);
+
+ /* The output is noisy. From reading the ASL
+ * dissassembly, timeout errors are returned with 1's
+ * in the high word, and the lack of locking around
+ * thei hi/lo byte reads means that a transition
+ * between (for example) -1 and 0 could be read as
+ * 0xff00 or 0x00ff. */
+ delta = abs(curr - (short)val);
+ if (delta < 128 && !(val & ~0xffff))
+ break;
+ }
+ return clamp_val((short)val, -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP);
+}
+
+static void pega_accel_poll(struct input_polled_dev *ipd)
+{
+ struct device *parent = ipd->input->dev.parent;
+ struct asus_laptop *asus = dev_get_drvdata(parent);
+
+ /* In some cases, the very first call to poll causes a
+ * recursive fault under the polldev worker. This is
+ * apparently related to very early userspace access to the
+ * device, and perhaps a firmware bug. Fake the first report. */
+ if (!asus->pega_acc_live) {
+ asus->pega_acc_live = true;
+ input_report_abs(ipd->input, ABS_X, 0);
+ input_report_abs(ipd->input, ABS_Y, 0);
+ input_report_abs(ipd->input, ABS_Z, 0);
+ input_sync(ipd->input);
+ return;
+ }
+
+ asus->pega_acc_x = pega_acc_axis(asus, asus->pega_acc_x, METHOD_XLRX);
+ asus->pega_acc_y = pega_acc_axis(asus, asus->pega_acc_y, METHOD_XLRY);
+ asus->pega_acc_z = pega_acc_axis(asus, asus->pega_acc_z, METHOD_XLRZ);
+
+ /* Note transform, convert to "right/up/out" in the native
+ * landscape orientation (i.e. the vector is the direction of
+ * "real up" in the device's cartiesian coordinates). */
+ input_report_abs(ipd->input, ABS_X, -asus->pega_acc_x);
+ input_report_abs(ipd->input, ABS_Y, -asus->pega_acc_y);
+ input_report_abs(ipd->input, ABS_Z, asus->pega_acc_z);
+ input_sync(ipd->input);
+}
+
+static void pega_accel_exit(struct asus_laptop *asus)
+{
+ if (asus->pega_accel_poll) {
+ input_unregister_polled_device(asus->pega_accel_poll);
+ input_free_polled_device(asus->pega_accel_poll);
+ }
+ asus->pega_accel_poll = NULL;
+}
+
+static int pega_accel_init(struct asus_laptop *asus)
+{
+ int err;
+ struct input_polled_dev *ipd;
+
+ if (!asus->is_pega_lucid)
+ return -ENODEV;
+
+ if (acpi_check_handle(asus->handle, METHOD_XLRX, NULL) ||
+ acpi_check_handle(asus->handle, METHOD_XLRY, NULL) ||
+ acpi_check_handle(asus->handle, METHOD_XLRZ, NULL))
+ return -ENODEV;
+
+ ipd = input_allocate_polled_device();
+ if (!ipd)
+ return -ENOMEM;
+
+ ipd->poll = pega_accel_poll;
+ ipd->poll_interval = 125;
+ ipd->poll_interval_min = 50;
+ ipd->poll_interval_max = 2000;
+
+ ipd->input->name = PEGA_ACCEL_DESC;
+ ipd->input->phys = PEGA_ACCEL_NAME "/input0";
+ ipd->input->dev.parent = &asus->platform_device->dev;
+ ipd->input->id.bustype = BUS_HOST;
+
+ set_bit(EV_ABS, ipd->input->evbit);
+ input_set_abs_params(ipd->input, ABS_X,
+ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
+ input_set_abs_params(ipd->input, ABS_Y,
+ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
+ input_set_abs_params(ipd->input, ABS_Z,
+ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
+
+ err = input_register_polled_device(ipd);
+ if (err)
+ goto exit;
+
+ asus->pega_accel_poll = ipd;
+ return 0;
+
+exit:
+ input_free_polled_device(ipd);
+ return err;
+}
+
/* Generic LED function */
static int asus_led_set(struct asus_laptop *asus, const char *method,
int value)
@@ -430,17 +601,17 @@ static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev)
static void asus_led_exit(struct asus_laptop *asus)
{
- if (asus->mled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->mled.led.dev))
led_classdev_unregister(&asus->mled.led);
- if (asus->tled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->tled.led.dev))
led_classdev_unregister(&asus->tled.led);
- if (asus->pled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->pled.led.dev))
led_classdev_unregister(&asus->pled.led);
- if (asus->rled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->rled.led.dev))
led_classdev_unregister(&asus->rled.led);
- if (asus->gled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->gled.led.dev))
led_classdev_unregister(&asus->gled.led);
- if (asus->kled.led.dev)
+ if (!IS_ERR_OR_NULL(asus->kled.led.dev))
led_classdev_unregister(&asus->kled.led);
if (asus->led_workqueue) {
destroy_workqueue(asus->led_workqueue);
@@ -474,6 +645,13 @@ static int asus_led_init(struct asus_laptop *asus)
int r;
/*
+ * The Pegatron Lucid has no physical leds, but all methods are
+ * available in the DSDT...
+ */
+ if (asus->is_pega_lucid)
+ return 0;
+
+ /*
* Functions that actually update the LED's are called from a
* workqueue. By doing this as separate work rather than when the LED
* subsystem asks, we avoid messing with the Asus ACPI stuff during a
@@ -907,8 +1085,18 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
*/
static void asus_als_switch(struct asus_laptop *asus, int value)
{
- if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value))
- pr_warn("Error setting light sensor switch\n");
+ int ret;
+
+ if (asus->is_pega_lucid) {
+ ret = asus_pega_lucid_set(asus, PEGA_ALS, value);
+ if (!ret)
+ ret = asus_pega_lucid_set(asus, PEGA_ALS_POWER, value);
+ } else {
+ ret = write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value);
+ }
+ if (ret)
+ pr_warning("Error setting light sensor switch\n");
+
asus->light_switch = value;
}
@@ -964,6 +1152,35 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
return rv;
}
+static int pega_int_read(struct asus_laptop *asus, int arg, int *result)
+{
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ int err = write_acpi_int_ret(asus->handle, METHOD_PEGA_READ, arg,
+ &buffer);
+ if (!err) {
+ union acpi_object *obj = buffer.pointer;
+ if (obj && obj->type == ACPI_TYPE_INTEGER)
+ *result = obj->integer.value;
+ else
+ err = -EIO;
+ }
+ return err;
+}
+
+static ssize_t show_lsvalue(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+ int err, hi, lo;
+
+ err = pega_int_read(asus, PEGA_READ_ALS_H, &hi);
+ if (!err)
+ err = pega_int_read(asus, PEGA_READ_ALS_L, &lo);
+ if (!err)
+ return sprintf(buf, "%d\n", 10 * hi + lo);
+ return err;
+}
+
/*
* GPS
*/
@@ -1062,6 +1279,86 @@ static int asus_rfkill_init(struct asus_laptop *asus)
return result;
}
+static int pega_rfkill_set(void *data, bool blocked)
+{
+ struct asus_pega_rfkill *pega_rfk = data;
+
+ int ret = asus_pega_lucid_set(pega_rfk->asus, pega_rfk->control_id, !blocked);
+ pr_warn("Setting rfkill %d, to %d; returned %d\n", pega_rfk->control_id, !blocked, ret);
+
+ return ret;
+}
+
+static const struct rfkill_ops pega_rfkill_ops = {
+ .set_block = pega_rfkill_set,
+};
+
+static void pega_rfkill_terminate(struct asus_pega_rfkill *pega_rfk)
+{
+ pr_warn("Terminating %d\n", pega_rfk->control_id);
+ if (pega_rfk->rfkill) {
+ rfkill_unregister(pega_rfk->rfkill);
+ rfkill_destroy(pega_rfk->rfkill);
+ pega_rfk->rfkill = NULL;
+ }
+}
+
+static void pega_rfkill_exit(struct asus_laptop *asus)
+{
+ pega_rfkill_terminate(&asus->wwanrfk);
+ pega_rfkill_terminate(&asus->btrfk);
+ pega_rfkill_terminate(&asus->wlanrfk);
+}
+
+static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_pega_rfkill *pega_rfk,
+ const char *name, int controlid, int rfkill_type)
+{
+ int result;
+
+ pr_warn("Setting up rfk %s, control %d, type %d\n", name, controlid, rfkill_type);
+ pega_rfk->control_id = controlid;
+ pega_rfk->asus = asus;
+ pega_rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev,
+ rfkill_type, &pega_rfkill_ops, pega_rfk);
+ if (!pega_rfk->rfkill)
+ return -EINVAL;
+
+ result = rfkill_register(pega_rfk->rfkill);
+ if (result) {
+ rfkill_destroy(pega_rfk->rfkill);
+ pega_rfk->rfkill = NULL;
+ }
+
+ return result;
+}
+
+static int pega_rfkill_init(struct asus_laptop *asus)
+{
+ int ret = 0;
+
+ if(!asus->is_pega_lucid)
+ return -ENODEV;
+
+ ret = pega_rfkill_setup(asus, &asus->wlanrfk, "pega-wlan", PEGA_WLAN, RFKILL_TYPE_WLAN);
+ if(ret)
+ return ret;
+ ret = pega_rfkill_setup(asus, &asus->btrfk, "pega-bt", PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH);
+ if(ret)
+ goto err_btrfk;
+ ret = pega_rfkill_setup(asus, &asus->wwanrfk, "pega-wwan", PEGA_WWAN, RFKILL_TYPE_WWAN);
+ if(ret)
+ goto err_wwanrfk;
+
+ pr_warn("Pega rfkill init succeeded\n");
+ return 0;
+err_wwanrfk:
+ pega_rfkill_terminate(&asus->btrfk);
+err_btrfk:
+ pega_rfkill_terminate(&asus->wlanrfk);
+
+ return ret;
+}
+
/*
* Input device (i.e. hotkeys)
*/
@@ -1141,6 +1438,14 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
}
return ;
}
+
+ /* Accelerometer "coarse orientation change" event */
+ if (asus->pega_accel_poll && event == 0xEA) {
+ kobject_uevent(&asus->pega_accel_poll->input->dev.kobj,
+ KOBJ_CHANGE);
+ return ;
+ }
+
asus_input_notify(asus, event);
}
@@ -1152,6 +1457,7 @@ static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax);
static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan);
static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp);
static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
+static DEVICE_ATTR(ls_value, S_IRUGO, show_lsvalue, NULL);
static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
@@ -1164,6 +1470,7 @@ static struct attribute *asus_attributes[] = {
&dev_attr_wwan.attr,
&dev_attr_display.attr,
&dev_attr_ledd.attr,
+ &dev_attr_ls_value.attr,
&dev_attr_ls_level.attr,
&dev_attr_ls_switch.attr,
&dev_attr_gps.attr,
@@ -1180,6 +1487,19 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj,
acpi_handle handle = asus->handle;
bool supported;
+ if (asus->is_pega_lucid) {
+ /* no ls_level interface on the Lucid */
+ if (attr == &dev_attr_ls_switch.attr)
+ supported = true;
+ else if (attr == &dev_attr_ls_level.attr)
+ supported = false;
+ else
+ goto normal;
+
+ return supported;
+ }
+
+normal:
if (attr == &dev_attr_wlan.attr) {
supported = !acpi_check_handle(handle, METHOD_WLAN, NULL);
@@ -1202,8 +1522,9 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj,
} else if (attr == &dev_attr_ls_switch.attr ||
attr == &dev_attr_ls_level.attr) {
supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) &&
- !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
-
+ !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
+ } else if (attr == &dev_attr_ls_value.attr) {
+ supported = asus->is_pega_lucid;
} else if (attr == &dev_attr_gps.attr) {
supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) &&
!acpi_check_handle(handle, METHOD_GPS_OFF, NULL) &&
@@ -1258,7 +1579,7 @@ static struct platform_driver platform_driver = {
.driver = {
.name = ASUS_LAPTOP_FILE,
.owner = THIS_MODULE,
- }
+ },
};
/*
@@ -1388,11 +1709,13 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
asus->ledd_status = 0xFFF;
/* Set initial values of light sensor and level */
- asus->light_switch = 0; /* Default to light sensor disabled */
+ asus->light_switch = !!als_status;
asus->light_level = 5; /* level 5 for sensor sensitivity */
- if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
- !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
+ if (asus->is_pega_lucid) {
+ asus_als_switch(asus, asus->light_switch);
+ } else if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
+ !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
asus_als_switch(asus, asus->light_switch);
asus_als_level(asus, asus->light_level);
}
@@ -1439,9 +1762,10 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
goto fail_platform;
/*
- * Register the platform device first. It is used as a parent for the
- * sub-devices below.
+ * Need platform type detection first, then the platform
+ * device. It is used as a parent for the sub-devices below.
*/
+ asus->is_pega_lucid = asus_check_pega_lucid(asus);
result = asus_platform_init(asus);
if (result)
goto fail_platform;
@@ -1465,9 +1789,21 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
if (result)
goto fail_rfkill;
+ result = pega_accel_init(asus);
+ if (result && result != -ENODEV)
+ goto fail_pega_accel;
+
+ result = pega_rfkill_init(asus);
+ if (result && result != -ENODEV)
+ goto fail_pega_rfkill;
+
asus_device_present = true;
return 0;
+fail_pega_rfkill:
+ pega_accel_exit(asus);
+fail_pega_accel:
+ asus_rfkill_exit(asus);
fail_rfkill:
asus_led_exit(asus);
fail_led:
@@ -1491,6 +1827,8 @@ static int asus_acpi_remove(struct acpi_device *device, int type)
asus_rfkill_exit(asus);
asus_led_exit(asus);
asus_input_exit(asus);
+ pega_accel_exit(asus);
+ pega_rfkill_exit(asus);
asus_platform_exit(asus);
kfree(asus->name);
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 95cba9ebf6c0..d1049ee3c9e8 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -453,7 +453,9 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
static void asus_wmi_led_exit(struct asus_wmi *asus)
{
- if (asus->tpd_led.dev)
+ if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
+ led_classdev_unregister(&asus->kbd_led);
+ if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
led_classdev_unregister(&asus->tpd_led);
if (asus->led_workqueue)
destroy_workqueue(asus->led_workqueue);
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index f31fa4efa725..a43cfd906c6d 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -60,6 +60,22 @@ struct calling_interface_structure {
struct calling_interface_token tokens[];
} __packed;
+struct quirk_entry {
+ u8 touchpad_led;
+};
+
+static struct quirk_entry *quirks;
+
+static struct quirk_entry quirk_dell_vostro_v130 = {
+ .touchpad_led = 1,
+};
+
+static int dmi_matched(const struct dmi_system_id *dmi)
+{
+ quirks = dmi->driver_data;
+ return 1;
+}
+
static int da_command_address;
static int da_command_code;
static int da_num_tokens;
@@ -149,6 +165,27 @@ static struct dmi_system_id __devinitdata dell_blacklist[] = {
{}
};
+static struct dmi_system_id __devinitdata dell_quirks[] = {
+ {
+ .callback = dmi_matched,
+ .ident = "Dell Vostro V130",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V130"),
+ },
+ .driver_data = &quirk_dell_vostro_v130,
+ },
+ {
+ .callback = dmi_matched,
+ .ident = "Dell Vostro V131",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
+ },
+ .driver_data = &quirk_dell_vostro_v130,
+ },
+};
+
static struct calling_interface_buffer *buffer;
static struct page *bufferpage;
static DEFINE_MUTEX(buffer_mutex);
@@ -552,6 +589,44 @@ static const struct backlight_ops dell_ops = {
.update_status = dell_send_intensity,
};
+static void touchpad_led_on()
+{
+ int command = 0x97;
+ char data = 1;
+ i8042_command(&data, command | 1 << 12);
+}
+
+static void touchpad_led_off()
+{
+ int command = 0x97;
+ char data = 2;
+ i8042_command(&data, command | 1 << 12);
+}
+
+static void touchpad_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (value > 0)
+ touchpad_led_on();
+ else
+ touchpad_led_off();
+}
+
+static struct led_classdev touchpad_led = {
+ .name = "dell-laptop::touchpad",
+ .brightness_set = touchpad_led_set,
+};
+
+static int __devinit touchpad_led_init(struct device *dev)
+{
+ return led_classdev_register(dev, &touchpad_led);
+}
+
+static void touchpad_led_exit(void)
+{
+ led_classdev_unregister(&touchpad_led);
+}
+
static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
struct serio *port)
{
@@ -584,6 +659,10 @@ static int __init dell_init(void)
if (!dmi_check_system(dell_device_table))
return -ENODEV;
+ quirks = NULL;
+ /* find if this machine support other functions */
+ dmi_check_system(dell_quirks);
+
dmi_walk(find_tokens, NULL);
if (!da_tokens) {
@@ -626,6 +705,9 @@ static int __init dell_init(void)
goto fail_filter;
}
+ if (quirks && quirks->touchpad_led)
+ touchpad_led_init(&platform_device->dev);
+
dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
if (dell_laptop_dir != NULL)
debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
@@ -692,6 +774,8 @@ fail_platform_driver:
static void __exit dell_exit(void)
{
debugfs_remove_recursive(dell_laptop_dir);
+ if (quirks && quirks->touchpad_led)
+ touchpad_led_exit();
i8042_remove_filter(dell_laptop_i8042_filter);
cancel_delayed_work_sync(&dell_rfkill_work);
backlight_device_unregister(dell_backlight_device);
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 1c45d92e2163..ea44abd8df48 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -568,7 +568,7 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc)
static void eeepc_led_exit(struct eeepc_laptop *eeepc)
{
- if (eeepc->tpd_led.dev)
+ if (!IS_ERR_OR_NULL(eeepc->tpd_led.dev))
led_classdev_unregister(&eeepc->tpd_led);
if (eeepc->led_workqueue)
destroy_workqueue(eeepc->led_workqueue);
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
index 1b52d00e2f90..22b2dfa73148 100644
--- a/drivers/platform/x86/hp_accel.c
+++ b/drivers/platform/x86/hp_accel.c
@@ -76,6 +76,7 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
/* For automatic insertion of the module */
static struct acpi_device_id lis3lv02d_device_ids[] = {
{"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
+ {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
@@ -209,6 +210,8 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
+ AXIS_DMI_MATCH("NC854xx", "HP EliteBook 854", y_inverted),
+ AXIS_DMI_MATCH("NC273xx", "HP EliteBook 273", y_inverted),
/* Intel-based HP Pavilion dv5 */
AXIS_DMI_MATCH2("HPDV5_I",
PRODUCT_NAME, "HP Pavilion dv5",
@@ -227,7 +230,12 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
+ AXIS_DMI_MATCH("HPB655x", "HP ProBook 655", xy_swap_inverted),
AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
+ AXIS_DMI_MATCH("HPB63xx", "HP ProBook 63", xy_swap),
+ AXIS_DMI_MATCH("HPB64xx", "HP ProBook 64", xy_swap),
+ AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap),
+ AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted),
{ NULL, }
/* Laptop models without axis info (yet):
* "NC6910" "HP Compaq 6910"
@@ -320,7 +328,7 @@ static int lis3lv02d_add(struct acpi_device *device)
INIT_WORK(&hpled_led.work, delayed_set_status_worker);
ret = led_classdev_register(NULL, &hpled_led.led_classdev);
if (ret) {
- lis3lv02d_joystick_disable();
+ lis3lv02d_joystick_disable(&lis3_dev);
lis3lv02d_poweroff(&lis3_dev);
flush_work(&hpled_led.work);
return ret;
@@ -334,7 +342,7 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)
if (!device)
return -EINVAL;
- lis3lv02d_joystick_disable();
+ lis3lv02d_joystick_disable(&lis3_dev);
lis3lv02d_poweroff(&lis3_dev);
led_classdev_unregister(&hpled_led.led_classdev);
@@ -354,8 +362,7 @@ static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
static int lis3lv02d_resume(struct acpi_device *device)
{
- lis3lv02d_poweron(&lis3_dev);
- return 0;
+ return lis3lv02d_poweron(&lis3_dev);
}
#else
#define lis3lv02d_suspend NULL
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 0c595410e788..a36addf106a0 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -34,6 +34,8 @@
#include <linux/input/sparse-keymap.h>
#include <linux/backlight.h>
#include <linux/fb.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#define IDEAPAD_RFKILL_DEV_NUM (3)
@@ -42,15 +44,41 @@
#define CFG_WIFI_BIT (18)
#define CFG_CAMERA_BIT (19)
+enum {
+ VPCCMD_R_VPC1 = 0x10,
+ VPCCMD_R_BL_MAX,
+ VPCCMD_R_BL,
+ VPCCMD_W_BL,
+ VPCCMD_R_WIFI,
+ VPCCMD_W_WIFI,
+ VPCCMD_R_BT,
+ VPCCMD_W_BT,
+ VPCCMD_R_BL_POWER,
+ VPCCMD_R_NOVO,
+ VPCCMD_R_VPC2,
+ VPCCMD_R_TOUCHPAD,
+ VPCCMD_W_TOUCHPAD,
+ VPCCMD_R_CAMERA,
+ VPCCMD_W_CAMERA,
+ VPCCMD_R_3G,
+ VPCCMD_W_3G,
+ VPCCMD_R_ODD, /* 0x21 */
+ VPCCMD_R_RF = 0x23,
+ VPCCMD_W_RF,
+ VPCCMD_W_BL_POWER = 0x33,
+};
+
struct ideapad_private {
struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
struct platform_device *platform_device;
struct input_dev *inputdev;
struct backlight_device *blightdev;
+ struct dentry *debug;
unsigned long cfg;
};
static acpi_handle ideapad_handle;
+static struct ideapad_private *ideapad_priv;
static bool no_bt_rfkill;
module_param(no_bt_rfkill, bool, 0444);
MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
@@ -164,6 +192,146 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
}
/*
+ * debugfs
+ */
+#define DEBUGFS_EVENT_LEN (4096)
+static int debugfs_status_show(struct seq_file *s, void *data)
+{
+ unsigned long value;
+
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &value))
+ seq_printf(s, "Backlight max:\t%lu\n", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_BL, &value))
+ seq_printf(s, "Backlight now:\t%lu\n", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &value))
+ seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");
+ seq_printf(s, "=====================\n");
+
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_RF, &value))
+ seq_printf(s, "Radio status:\t%s(%lu)\n",
+ value ? "On" : "Off", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_WIFI, &value))
+ seq_printf(s, "Wifi status:\t%s(%lu)\n",
+ value ? "On" : "Off", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_BT, &value))
+ seq_printf(s, "BT status:\t%s(%lu)\n",
+ value ? "On" : "Off", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_3G, &value))
+ seq_printf(s, "3G status:\t%s(%lu)\n",
+ value ? "On" : "Off", value);
+ seq_printf(s, "=====================\n");
+
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_TOUCHPAD, &value))
+ seq_printf(s, "Touchpad status:%s(%lu)\n",
+ value ? "On" : "Off", value);
+ if (!read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &value))
+ seq_printf(s, "Camera status:\t%s(%lu)\n",
+ value ? "On" : "Off", value);
+
+ return 0;
+}
+
+static int debugfs_status_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, debugfs_status_show, NULL);
+}
+
+static const struct file_operations debugfs_status_fops = {
+ .owner = THIS_MODULE,
+ .open = debugfs_status_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int debugfs_cfg_show(struct seq_file *s, void *data)
+{
+ if (!ideapad_priv) {
+ seq_printf(s, "cfg: N/A\n");
+ } else {
+ seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
+ ideapad_priv->cfg);
+ if (test_bit(CFG_BT_BIT, &ideapad_priv->cfg))
+ seq_printf(s, "Bluetooth ");
+ if (test_bit(CFG_3G_BIT, &ideapad_priv->cfg))
+ seq_printf(s, "3G ");
+ if (test_bit(CFG_WIFI_BIT, &ideapad_priv->cfg))
+ seq_printf(s, "Wireless ");
+ if (test_bit(CFG_CAMERA_BIT, &ideapad_priv->cfg))
+ seq_printf(s, "Camera ");
+ seq_printf(s, "\nGraphic: ");
+ switch ((ideapad_priv->cfg)&0x700) {
+ case 0x100:
+ seq_printf(s, "Intel");
+ break;
+ case 0x200:
+ seq_printf(s, "ATI");
+ break;
+ case 0x300:
+ seq_printf(s, "Nvidia");
+ break;
+ case 0x400:
+ seq_printf(s, "Intel and ATI");
+ break;
+ case 0x500:
+ seq_printf(s, "Intel and Nvidia");
+ break;
+ }
+ seq_printf(s, "\n");
+ }
+ return 0;
+}
+
+static int debugfs_cfg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, debugfs_cfg_show, NULL);
+}
+
+static const struct file_operations debugfs_cfg_fops = {
+ .owner = THIS_MODULE,
+ .open = debugfs_cfg_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __devinit ideapad_debugfs_init(struct ideapad_private *priv)
+{
+ struct dentry *node;
+
+ priv->debug = debugfs_create_dir("ideapad", NULL);
+ if (priv->debug == NULL) {
+ pr_err("failed to create debugfs directory");
+ goto errout;
+ }
+
+ node = debugfs_create_file("cfg", S_IRUGO, priv->debug, NULL,
+ &debugfs_cfg_fops);
+ if (!node) {
+ pr_err("failed to create cfg in debugfs");
+ goto errout;
+ }
+
+ node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL,
+ &debugfs_status_fops);
+ if (!node) {
+ pr_err("failed to create event in debugfs");
+ goto errout;
+ }
+
+ return 0;
+
+errout:
+ return -ENOMEM;
+}
+
+static void ideapad_debugfs_exit(struct ideapad_private *priv)
+{
+ debugfs_remove_recursive(priv->debug);
+ priv->debug = NULL;
+}
+
+/*
* sysfs
*/
static ssize_t show_ideapad_cam(struct device *dev,
@@ -172,7 +340,7 @@ static ssize_t show_ideapad_cam(struct device *dev,
{
unsigned long result;
- if (read_ec_data(ideapad_handle, 0x1D, &result))
+ if (read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &result))
return sprintf(buf, "-1\n");
return sprintf(buf, "%lu\n", result);
}
@@ -187,7 +355,7 @@ static ssize_t store_ideapad_cam(struct device *dev,
return 0;
if (sscanf(buf, "%i", &state) != 1)
return -EINVAL;
- ret = write_ec_cmd(ideapad_handle, 0x1E, state);
+ ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state);
if (ret < 0)
return ret;
return count;
@@ -195,20 +363,8 @@ static ssize_t store_ideapad_cam(struct device *dev,
static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
-static ssize_t show_ideapad_cfg(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ideapad_private *priv = dev_get_drvdata(dev);
-
- return sprintf(buf, "0x%.8lX\n", priv->cfg);
-}
-
-static DEVICE_ATTR(cfg, 0444, show_ideapad_cfg, NULL);
-
static struct attribute *ideapad_attributes[] = {
&dev_attr_camera_power.attr,
- &dev_attr_cfg.attr,
NULL
};
@@ -244,9 +400,9 @@ struct ideapad_rfk_data {
};
const struct ideapad_rfk_data ideapad_rfk_data[] = {
- { "ideapad_wlan", CFG_WIFI_BIT, 0x15, RFKILL_TYPE_WLAN },
- { "ideapad_bluetooth", CFG_BT_BIT, 0x17, RFKILL_TYPE_BLUETOOTH },
- { "ideapad_3g", CFG_3G_BIT, 0x20, RFKILL_TYPE_WWAN },
+ { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
+ { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
+ { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
};
static int ideapad_rfk_set(void *data, bool blocked)
@@ -260,13 +416,12 @@ static struct rfkill_ops ideapad_rfk_ops = {
.set_block = ideapad_rfk_set,
};
-static void ideapad_sync_rfk_state(struct acpi_device *adevice)
+static void ideapad_sync_rfk_state(struct ideapad_private *priv)
{
- struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
unsigned long hw_blocked;
int i;
- if (read_ec_data(ideapad_handle, 0x23, &hw_blocked))
+ if (read_ec_data(ideapad_handle, VPCCMD_R_RF, &hw_blocked))
return;
hw_blocked = !hw_blocked;
@@ -363,8 +518,10 @@ static void ideapad_platform_exit(struct ideapad_private *priv)
* input device
*/
static const struct key_entry ideapad_keymap[] = {
- { KE_KEY, 0x06, { KEY_SWITCHVIDEOMODE } },
- { KE_KEY, 0x0D, { KEY_WLAN } },
+ { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } },
+ { KE_KEY, 13, { KEY_WLAN } },
+ { KE_KEY, 16, { KEY_PROG1 } },
+ { KE_KEY, 17, { KEY_PROG2 } },
{ KE_END, 0 },
};
@@ -419,6 +576,18 @@ static void ideapad_input_report(struct ideapad_private *priv,
sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
}
+static void ideapad_input_novokey(struct ideapad_private *priv)
+{
+ unsigned long long_pressed;
+
+ if (read_ec_data(ideapad_handle, VPCCMD_R_NOVO, &long_pressed))
+ return;
+ if (long_pressed)
+ ideapad_input_report(priv, 17);
+ else
+ ideapad_input_report(priv, 16);
+}
+
/*
* backlight
*/
@@ -426,16 +595,17 @@ static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
{
unsigned long now;
- if (read_ec_data(ideapad_handle, 0x12, &now))
+ if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
return -EIO;
return now;
}
static int ideapad_backlight_update_status(struct backlight_device *blightdev)
{
- if (write_ec_cmd(ideapad_handle, 0x13, blightdev->props.brightness))
+ if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL,
+ blightdev->props.brightness))
return -EIO;
- if (write_ec_cmd(ideapad_handle, 0x33,
+ if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL_POWER,
blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
return -EIO;
@@ -453,11 +623,11 @@ static int ideapad_backlight_init(struct ideapad_private *priv)
struct backlight_properties props;
unsigned long max, now, power;
- if (read_ec_data(ideapad_handle, 0x11, &max))
+ if (read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &max))
return -EIO;
- if (read_ec_data(ideapad_handle, 0x12, &now))
+ if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
return -EIO;
- if (read_ec_data(ideapad_handle, 0x18, &power))
+ if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
return -EIO;
memset(&props, 0, sizeof(struct backlight_properties));
@@ -493,7 +663,9 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv)
unsigned long power;
struct backlight_device *blightdev = priv->blightdev;
- if (read_ec_data(ideapad_handle, 0x18, &power))
+ if (!blightdev)
+ return;
+ if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
return;
blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
}
@@ -504,7 +676,7 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
/* if we control brightness via acpi video driver */
if (priv->blightdev == NULL) {
- read_ec_data(ideapad_handle, 0x12, &now);
+ read_ec_data(ideapad_handle, VPCCMD_R_BL, &now);
return;
}
@@ -533,6 +705,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
if (!priv)
return -ENOMEM;
dev_set_drvdata(&adevice->dev, priv);
+ ideapad_priv = priv;
ideapad_handle = adevice->handle;
priv->cfg = cfg;
@@ -540,6 +713,10 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
if (ret)
goto platform_failed;
+ ret = ideapad_debugfs_init(priv);
+ if (ret)
+ goto debugfs_failed;
+
ret = ideapad_input_init(priv);
if (ret)
goto input_failed;
@@ -550,7 +727,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
else
priv->rfk[i] = NULL;
}
- ideapad_sync_rfk_state(adevice);
+ ideapad_sync_rfk_state(priv);
if (!acpi_video_backlight_support()) {
ret = ideapad_backlight_init(priv);
@@ -565,6 +742,8 @@ backlight_failed:
ideapad_unregister_rfkill(adevice, i);
ideapad_input_exit(priv);
input_failed:
+ ideapad_debugfs_exit(priv);
+debugfs_failed:
ideapad_platform_exit(priv);
platform_failed:
kfree(priv);
@@ -580,6 +759,7 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
ideapad_unregister_rfkill(adevice, i);
ideapad_input_exit(priv);
+ ideapad_debugfs_exit(priv);
ideapad_platform_exit(priv);
dev_set_drvdata(&adevice->dev, NULL);
kfree(priv);
@@ -593,9 +773,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
acpi_handle handle = adevice->handle;
unsigned long vpc1, vpc2, vpc_bit;
- if (read_ec_data(handle, 0x10, &vpc1))
+ if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
return;
- if (read_ec_data(handle, 0x1A, &vpc2))
+ if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
return;
vpc1 = (vpc2 << 8) | vpc1;
@@ -603,11 +783,14 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
if (test_bit(vpc_bit, &vpc1)) {
switch (vpc_bit) {
case 9:
- ideapad_sync_rfk_state(adevice);
+ ideapad_sync_rfk_state(priv);
break;
case 4:
ideapad_backlight_notify_brightness(priv);
break;
+ case 3:
+ ideapad_input_novokey(priv);
+ break;
case 2:
ideapad_backlight_notify_power(priv);
break;
diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c
index b93a03259c16..2d0f9136ea9a 100644
--- a/drivers/platform/x86/intel_scu_ipcutil.c
+++ b/drivers/platform/x86/intel_scu_ipcutil.c
@@ -24,7 +24,7 @@
#include <linux/init.h>
#include <asm/intel_scu_ipc.h>
-static u32 major;
+static int major;
#define MAX_FW_SIZE 264192
@@ -117,7 +117,11 @@ static const struct file_operations scu_ipc_fops = {
static int __init ipc_module_init(void)
{
- return register_chrdev(0, "intel_mid_scu", &scu_ipc_fops);
+ major = register_chrdev(0, "intel_mid_scu", &scu_ipc_fops);
+ if (major < 0)
+ return major;
+
+ return 0;
}
static void __exit ipc_module_exit(void)
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
index 359163011044..09e26bfd4643 100644
--- a/drivers/platform/x86/samsung-laptop.c
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -226,6 +226,7 @@ static struct backlight_device *backlight_device;
static struct mutex sabi_mutex;
static struct platform_device *sdev;
static struct rfkill *rfk;
+static bool has_stepping_quirk;
static int force;
module_param(force, bool, 0);
@@ -370,15 +371,28 @@ static u8 read_brightness(void)
&sretval);
if (!retval) {
user_brightness = sretval.retval[0];
- if (user_brightness != 0)
+ if (user_brightness > sabi_config->min_brightness)
user_brightness -= sabi_config->min_brightness;
+ else
+ user_brightness = 0;
}
return user_brightness;
}
static void set_brightness(u8 user_brightness)
{
- u8 user_level = user_brightness - sabi_config->min_brightness;
+ u8 user_level = user_brightness + sabi_config->min_brightness;
+
+ if (has_stepping_quirk && user_level != 0) {
+ /*
+ * short circuit if the specified level is what's already set
+ * to prevent the screen from flickering needlessly
+ */
+ if (user_brightness == read_brightness())
+ return;
+
+ sabi_set_command(sabi_config->commands.set_brightness, 0);
+ }
sabi_set_command(sabi_config->commands.set_brightness, user_level);
}
@@ -388,6 +402,40 @@ static int get_brightness(struct backlight_device *bd)
return (int)read_brightness();
}
+static void check_for_stepping_quirk(void)
+{
+ u8 initial_level;
+ u8 check_level;
+ u8 orig_level = read_brightness();
+
+ /*
+ * Some laptops exhibit the strange behaviour of stepping toward
+ * (rather than setting) the brightness except when changing to/from
+ * brightness level 0. This behaviour is checked for here and worked
+ * around in set_brightness.
+ */
+
+ if (orig_level == 0)
+ set_brightness(1);
+
+ initial_level = read_brightness();
+
+ if (initial_level <= 2)
+ check_level = initial_level + 2;
+ else
+ check_level = initial_level - 2;
+
+ has_stepping_quirk = false;
+ set_brightness(check_level);
+
+ if (read_brightness() != check_level) {
+ has_stepping_quirk = true;
+ pr_info("enabled workaround for brightness stepping quirk\n");
+ }
+
+ set_brightness(orig_level);
+}
+
static int update_status(struct backlight_device *bd)
{
set_brightness(bd->props.brightness);
@@ -621,6 +669,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
.callback = dmi_check_cb,
},
{
+ .ident = "N220",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "N220"),
+ DMI_MATCH(DMI_BOARD_NAME, "N220"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
.ident = "N150/N210/N220/N230",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR,
@@ -641,6 +699,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
.callback = dmi_check_cb,
},
{
+ .ident = "R700",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SR700"),
+ DMI_MATCH(DMI_BOARD_NAME, "SR700"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
.ident = "R530/R730",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
@@ -686,6 +753,33 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
},
.callback = dmi_check_cb,
},
+ {
+ .ident = "R528/R728",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "R528/R728"),
+ DMI_MATCH(DMI_BOARD_NAME, "R528/R728"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
+ .ident = "NC210/NC110",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
+ DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
+ .ident = "X520",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X520"),
+ DMI_MATCH(DMI_BOARD_NAME, "X520"),
+ },
+ .callback = dmi_check_cb,
+ },
{ },
};
MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
@@ -770,7 +864,7 @@ static int __init samsung_init(void)
sabi_iface = ioremap_nocache(ifaceP, 16);
if (!sabi_iface) {
pr_err("Can't remap %x\n", ifaceP);
- goto exit;
+ goto error_no_signature;
}
if (debug) {
printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
@@ -794,6 +888,9 @@ static int __init samsung_init(void)
}
}
+ /* Check for stepping quirk */
+ check_for_stepping_quirk();
+
/* knock up a platform device to hang stuff off of */
sdev = platform_device_register_simple("samsung", -1, NULL, 0);
if (IS_ERR(sdev))
@@ -802,7 +899,8 @@ static int __init samsung_init(void)
/* create a backlight device to talk to this one */
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_PLATFORM;
- props.max_brightness = sabi_config->max_brightness;
+ props.max_brightness = sabi_config->max_brightness -
+ sabi_config->min_brightness;
backlight_device = backlight_device_register("samsung", &sdev->dev,
NULL, &backlight_ops,
&props);
@@ -821,7 +919,6 @@ static int __init samsung_init(void)
if (retval)
goto error_file_create;
-exit:
return 0;
error_file_create:
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index bbd182e178cb..c006dee5ebfe 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -3281,7 +3281,7 @@ static int sony_pic_add(struct acpi_device *device)
/* request IRQ */
list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
- IRQF_DISABLED, "sony-laptop", &spic_dev)) {
+ 0, "sony-laptop", &spic_dev)) {
dprintk("IRQ: %d - triggering: %d - "
"polarity: %d - shr: %d\n",
irq->irq.interrupts[0],
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 7bd829f247eb..7b828680b21d 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -4007,7 +4007,7 @@ static void bluetooth_shutdown(void)
pr_notice("failed to save bluetooth state to NVRAM\n");
else
vdbg_printk(TPACPI_DBG_RFKILL,
- "bluestooth state saved to NVRAM\n");
+ "bluetooth state saved to NVRAM\n");
}
static void bluetooth_exit(void)
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index 4c20447ddbb7..d528daa0e81c 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -41,6 +41,7 @@ static const struct key_entry topstar_keymap[] = {
{ KE_KEY, 0x8c, { KEY_MEDIA } },
/* Known non hotkey events don't handled or that we don't care yet */
+ { KE_IGNORE, 0x82, }, /* backlight event */
{ KE_IGNORE, 0x8e, },
{ KE_IGNORE, 0x8f, },
{ KE_IGNORE, 0x90, },
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index cb009b2629ee..13ef8c37471d 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -47,7 +47,6 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/backlight.h>
-#include <linux/platform_device.h>
#include <linux/rfkill.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
@@ -63,11 +62,7 @@ MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
MODULE_LICENSE("GPL");
/* Toshiba ACPI method paths */
-#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
-#define TOSH_INTERFACE_1 "\\_SB_.VALD"
-#define TOSH_INTERFACE_2 "\\_SB_.VALZ"
#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
-#define GHCI_METHOD ".GHCI"
/* Toshiba HCI interface definitions
*
@@ -111,6 +106,25 @@ MODULE_LICENSE("GPL");
#define HCI_WIRELESS_BT_ATTACH 0x40
#define HCI_WIRELESS_BT_POWER 0x80
+struct toshiba_acpi_dev {
+ struct acpi_device *acpi_dev;
+ const char *method_hci;
+ struct rfkill *bt_rfk;
+ struct input_dev *hotkey_dev;
+ struct backlight_device *backlight_dev;
+ struct led_classdev led_dev;
+
+ int force_fan;
+ int last_key_event;
+ int key_event_valid;
+
+ int illumination_supported:1;
+ int video_supported:1;
+ int fan_supported:1;
+
+ struct mutex mutex;
+};
+
static const struct acpi_device_id toshiba_device_ids[] = {
{"TOS6200", 0},
{"TOS6208", 0},
@@ -119,7 +133,7 @@ static const struct acpi_device_id toshiba_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
-static const struct key_entry toshiba_acpi_keymap[] __initconst = {
+static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
{ KE_KEY, 0x101, { KEY_MUTE } },
{ KE_KEY, 0x102, { KEY_ZOOMOUT } },
{ KE_KEY, 0x103, { KEY_ZOOMIN } },
@@ -155,15 +169,6 @@ static __inline__ void _set_bit(u32 * word, u32 mask, int value)
/* acpi interface wrappers
*/
-static int is_valid_acpi_path(const char *methodName)
-{
- acpi_handle handle;
- acpi_status status;
-
- status = acpi_get_handle(NULL, (char *)methodName, &handle);
- return !ACPI_FAILURE(status);
-}
-
static int write_acpi_int(const char *methodName, int val)
{
struct acpi_object_list params;
@@ -176,32 +181,14 @@ static int write_acpi_int(const char *methodName, int val)
in_objs[0].integer.value = val;
status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
- return (status == AE_OK);
-}
-
-#if 0
-static int read_acpi_int(const char *methodName, int *pVal)
-{
- struct acpi_buffer results;
- union acpi_object out_objs[1];
- acpi_status status;
-
- results.length = sizeof(out_objs);
- results.pointer = out_objs;
-
- status = acpi_evaluate_object(0, (char *)methodName, 0, &results);
- *pVal = out_objs[0].integer.value;
-
- return (status == AE_OK) && (out_objs[0].type == ACPI_TYPE_INTEGER);
+ return (status == AE_OK) ? 0 : -EIO;
}
-#endif
-
-static const char *method_hci /*= 0*/ ;
/* Perform a raw HCI call. Here we don't care about input or output buffer
* format.
*/
-static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
+static acpi_status hci_raw(struct toshiba_acpi_dev *dev,
+ const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
{
struct acpi_object_list params;
union acpi_object in_objs[HCI_WORDS];
@@ -220,7 +207,8 @@ static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
results.length = sizeof(out_objs);
results.pointer = out_objs;
- status = acpi_evaluate_object(NULL, (char *)method_hci, &params,
+ status = acpi_evaluate_object(dev->acpi_dev->handle,
+ (char *)dev->method_hci, &params,
&results);
if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
for (i = 0; i < out_objs->package.count; ++i) {
@@ -237,85 +225,79 @@ static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
* may be useful (such as "not supported").
*/
-static acpi_status hci_write1(u32 reg, u32 in1, u32 * result)
+static acpi_status hci_write1(struct toshiba_acpi_dev *dev, u32 reg,
+ u32 in1, u32 *result)
{
u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
u32 out[HCI_WORDS];
- acpi_status status = hci_raw(in, out);
+ acpi_status status = hci_raw(dev, in, out);
*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
return status;
}
-static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result)
+static acpi_status hci_read1(struct toshiba_acpi_dev *dev, u32 reg,
+ u32 *out1, u32 *result)
{
u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
- acpi_status status = hci_raw(in, out);
+ acpi_status status = hci_raw(dev, in, out);
*out1 = out[2];
*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
return status;
}
-static acpi_status hci_write2(u32 reg, u32 in1, u32 in2, u32 *result)
+static acpi_status hci_write2(struct toshiba_acpi_dev *dev, u32 reg,
+ u32 in1, u32 in2, u32 *result)
{
u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 };
u32 out[HCI_WORDS];
- acpi_status status = hci_raw(in, out);
+ acpi_status status = hci_raw(dev, in, out);
*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
return status;
}
-static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result)
+static acpi_status hci_read2(struct toshiba_acpi_dev *dev, u32 reg,
+ u32 *out1, u32 *out2, u32 *result)
{
u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 };
u32 out[HCI_WORDS];
- acpi_status status = hci_raw(in, out);
+ acpi_status status = hci_raw(dev, in, out);
*out1 = out[2];
*out2 = out[3];
*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
return status;
}
-struct toshiba_acpi_dev {
- struct platform_device *p_dev;
- struct rfkill *bt_rfk;
- struct input_dev *hotkey_dev;
- int illumination_installed;
- acpi_handle handle;
-
- const char *bt_name;
-
- struct mutex mutex;
-};
-
/* Illumination support */
-static int toshiba_illumination_available(void)
+static int toshiba_illumination_available(struct toshiba_acpi_dev *dev)
{
u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
acpi_status status;
in[0] = 0xf100;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("Illumination device not available\n");
return 0;
}
in[0] = 0xf400;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
return 1;
}
static void toshiba_illumination_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
+ struct toshiba_acpi_dev *dev = container_of(cdev,
+ struct toshiba_acpi_dev, led_dev);
u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
acpi_status status;
/* First request : initialize communication. */
in[0] = 0xf100;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("Illumination device not available\n");
return;
@@ -326,7 +308,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
in[0] = 0xf400;
in[1] = 0x14e;
in[2] = 1;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("ACPI call for illumination failed\n");
return;
@@ -336,7 +318,7 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
in[0] = 0xf400;
in[1] = 0x14e;
in[2] = 0;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("ACPI call for illumination failed.\n");
return;
@@ -347,11 +329,13 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
in[0] = 0xf200;
in[1] = 0;
in[2] = 0;
- hci_raw(in, out);
+ hci_raw(dev, in, out);
}
static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
{
+ struct toshiba_acpi_dev *dev = container_of(cdev,
+ struct toshiba_acpi_dev, led_dev);
u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
acpi_status status;
@@ -359,7 +343,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
/* First request : initialize communication. */
in[0] = 0xf100;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("Illumination device not available\n");
return LED_OFF;
@@ -368,7 +352,7 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
/* Check the illumination */
in[0] = 0xf300;
in[1] = 0x14e;
- status = hci_raw(in, out);
+ status = hci_raw(dev, in, out);
if (ACPI_FAILURE(status)) {
pr_info("ACPI call for illumination failed.\n");
return LED_OFF;
@@ -380,46 +364,35 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
in[0] = 0xf200;
in[1] = 0;
in[2] = 0;
- hci_raw(in, out);
+ hci_raw(dev, in, out);
return result;
}
-static struct led_classdev toshiba_led = {
- .name = "toshiba::illumination",
- .max_brightness = 1,
- .brightness_set = toshiba_illumination_set,
- .brightness_get = toshiba_illumination_get,
-};
-
-static struct toshiba_acpi_dev toshiba_acpi = {
- .bt_name = "Toshiba Bluetooth",
-};
-
/* Bluetooth rfkill handlers */
-static u32 hci_get_bt_present(bool *present)
+static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
{
u32 hci_result;
u32 value, value2;
value = 0;
value2 = 0;
- hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
+ hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result);
if (hci_result == HCI_SUCCESS)
*present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;
return hci_result;
}
-static u32 hci_get_radio_state(bool *radio_state)
+static u32 hci_get_radio_state(struct toshiba_acpi_dev *dev, bool *radio_state)
{
u32 hci_result;
u32 value, value2;
value = 0;
value2 = 0x0001;
- hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
+ hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result);
*radio_state = value & HCI_WIRELESS_KILL_SWITCH;
return hci_result;
@@ -436,8 +409,8 @@ static int bt_rfkill_set_block(void *data, bool blocked)
value = (blocked == false);
mutex_lock(&dev->mutex);
- if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) {
- err = -EBUSY;
+ if (hci_get_radio_state(dev, &radio_state) != HCI_SUCCESS) {
+ err = -EIO;
goto out;
}
@@ -446,11 +419,11 @@ static int bt_rfkill_set_block(void *data, bool blocked)
goto out;
}
- hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
- hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
+ hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
+ hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS)
- err = -EBUSY;
+ err = -EIO;
else
err = 0;
out:
@@ -467,7 +440,7 @@ static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
mutex_lock(&dev->mutex);
- hci_result = hci_get_radio_state(&value);
+ hci_result = hci_get_radio_state(dev, &value);
if (hci_result != HCI_SUCCESS) {
/* Can't do anything useful */
mutex_unlock(&dev->mutex);
@@ -488,63 +461,64 @@ static const struct rfkill_ops toshiba_rfk_ops = {
};
static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
-static struct backlight_device *toshiba_backlight_device;
-static int force_fan;
-static int last_key_event;
-static int key_event_valid;
static int get_lcd(struct backlight_device *bd)
{
+ struct toshiba_acpi_dev *dev = bl_get_data(bd);
u32 hci_result;
u32 value;
- hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
- if (hci_result == HCI_SUCCESS) {
+ hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result);
+ if (hci_result == HCI_SUCCESS)
return (value >> HCI_LCD_BRIGHTNESS_SHIFT);
- } else
- return -EFAULT;
+
+ return -EIO;
}
static int lcd_proc_show(struct seq_file *m, void *v)
{
- int value = get_lcd(NULL);
+ struct toshiba_acpi_dev *dev = m->private;
+ int value;
+
+ if (!dev->backlight_dev)
+ return -ENODEV;
+ value = get_lcd(dev->backlight_dev);
if (value >= 0) {
seq_printf(m, "brightness: %d\n", value);
seq_printf(m, "brightness_levels: %d\n",
HCI_LCD_BRIGHTNESS_LEVELS);
- } else {
- pr_err("Error reading LCD brightness\n");
+ return 0;
}
- return 0;
+ pr_err("Error reading LCD brightness\n");
+ return -EIO;
}
static int lcd_proc_open(struct inode *inode, struct file *file)
{
- return single_open(file, lcd_proc_show, NULL);
+ return single_open(file, lcd_proc_show, PDE(inode)->data);
}
-static int set_lcd(int value)
+static int set_lcd(struct toshiba_acpi_dev *dev, int value)
{
u32 hci_result;
value = value << HCI_LCD_BRIGHTNESS_SHIFT;
- hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
- if (hci_result != HCI_SUCCESS)
- return -EFAULT;
-
- return 0;
+ hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result);
+ return hci_result == HCI_SUCCESS ? 0 : -EIO;
}
static int set_lcd_status(struct backlight_device *bd)
{
- return set_lcd(bd->props.brightness);
+ struct toshiba_acpi_dev *dev = bl_get_data(bd);
+ return set_lcd(dev, bd->props.brightness);
}
static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
+ struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
char cmd[42];
size_t len;
int value;
@@ -557,7 +531,7 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
if (sscanf(cmd, " brightness : %i", &value) == 1 &&
value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
- ret = set_lcd(value);
+ ret = set_lcd(dev, value);
if (ret == 0)
ret = count;
} else {
@@ -575,41 +549,49 @@ static const struct file_operations lcd_proc_fops = {
.write = lcd_proc_write,
};
-static int video_proc_show(struct seq_file *m, void *v)
+static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status)
{
u32 hci_result;
+
+ hci_read1(dev, HCI_VIDEO_OUT, status, &hci_result);
+ return hci_result == HCI_SUCCESS ? 0 : -EIO;
+}
+
+static int video_proc_show(struct seq_file *m, void *v)
+{
+ struct toshiba_acpi_dev *dev = m->private;
u32 value;
+ int ret;
- hci_read1(HCI_VIDEO_OUT, &value, &hci_result);
- if (hci_result == HCI_SUCCESS) {
+ ret = get_video_status(dev, &value);
+ if (!ret) {
int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
seq_printf(m, "lcd_out: %d\n", is_lcd);
seq_printf(m, "crt_out: %d\n", is_crt);
seq_printf(m, "tv_out: %d\n", is_tv);
- } else {
- pr_err("Error reading video out status\n");
}
- return 0;
+ return ret;
}
static int video_proc_open(struct inode *inode, struct file *file)
{
- return single_open(file, video_proc_show, NULL);
+ return single_open(file, video_proc_show, PDE(inode)->data);
}
static ssize_t video_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
+ struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
char *cmd, *buffer;
+ int ret;
int value;
int remain = count;
int lcd_out = -1;
int crt_out = -1;
int tv_out = -1;
- u32 hci_result;
u32 video_out;
cmd = kmalloc(count + 1, GFP_KERNEL);
@@ -644,8 +626,8 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
kfree(cmd);
- hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
- if (hci_result == HCI_SUCCESS) {
+ ret = get_video_status(dev, &video_out);
+ if (!ret) {
unsigned int new_video_out = video_out;
if (lcd_out != -1)
_set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
@@ -656,12 +638,10 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
/* To avoid unnecessary video disruption, only write the new
* video setting if something changed. */
if (new_video_out != video_out)
- write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
- } else {
- return -EFAULT;
+ ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
}
- return count;
+ return ret ? ret : count;
}
static const struct file_operations video_proc_fops = {
@@ -673,30 +653,38 @@ static const struct file_operations video_proc_fops = {
.write = video_proc_write,
};
-static int fan_proc_show(struct seq_file *m, void *v)
+static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status)
{
u32 hci_result;
+
+ hci_read1(dev, HCI_FAN, status, &hci_result);
+ return hci_result == HCI_SUCCESS ? 0 : -EIO;
+}
+
+static int fan_proc_show(struct seq_file *m, void *v)
+{
+ struct toshiba_acpi_dev *dev = m->private;
+ int ret;
u32 value;
- hci_read1(HCI_FAN, &value, &hci_result);
- if (hci_result == HCI_SUCCESS) {
+ ret = get_fan_status(dev, &value);
+ if (!ret) {
seq_printf(m, "running: %d\n", (value > 0));
- seq_printf(m, "force_on: %d\n", force_fan);
- } else {
- pr_err("Error reading fan status\n");
+ seq_printf(m, "force_on: %d\n", dev->force_fan);
}
- return 0;
+ return ret;
}
static int fan_proc_open(struct inode *inode, struct file *file)
{
- return single_open(file, fan_proc_show, NULL);
+ return single_open(file, fan_proc_show, PDE(inode)->data);
}
static ssize_t fan_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
+ struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
char cmd[42];
size_t len;
int value;
@@ -709,11 +697,11 @@ static ssize_t fan_proc_write(struct file *file, const char __user *buf,
if (sscanf(cmd, " force_on : %i", &value) == 1 &&
value >= 0 && value <= 1) {
- hci_write1(HCI_FAN, value, &hci_result);
+ hci_write1(dev, HCI_FAN, value, &hci_result);
if (hci_result != HCI_SUCCESS)
- return -EFAULT;
+ return -EIO;
else
- force_fan = value;
+ dev->force_fan = value;
} else {
return -EINVAL;
}
@@ -732,42 +720,43 @@ static const struct file_operations fan_proc_fops = {
static int keys_proc_show(struct seq_file *m, void *v)
{
+ struct toshiba_acpi_dev *dev = m->private;
u32 hci_result;
u32 value;
- if (!key_event_valid) {
- hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
+ if (!dev->key_event_valid) {
+ hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
if (hci_result == HCI_SUCCESS) {
- key_event_valid = 1;
- last_key_event = value;
+ dev->key_event_valid = 1;
+ dev->last_key_event = value;
} else if (hci_result == HCI_EMPTY) {
/* better luck next time */
} else if (hci_result == HCI_NOT_SUPPORTED) {
/* This is a workaround for an unresolved issue on
* some machines where system events sporadically
* become disabled. */
- hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
+ hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
pr_notice("Re-enabled hotkeys\n");
} else {
pr_err("Error reading hotkey status\n");
- goto end;
+ return -EIO;
}
}
- seq_printf(m, "hotkey_ready: %d\n", key_event_valid);
- seq_printf(m, "hotkey: 0x%04x\n", last_key_event);
-end:
+ seq_printf(m, "hotkey_ready: %d\n", dev->key_event_valid);
+ seq_printf(m, "hotkey: 0x%04x\n", dev->last_key_event);
return 0;
}
static int keys_proc_open(struct inode *inode, struct file *file)
{
- return single_open(file, keys_proc_show, NULL);
+ return single_open(file, keys_proc_show, PDE(inode)->data);
}
static ssize_t keys_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
+ struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
char cmd[42];
size_t len;
int value;
@@ -778,7 +767,7 @@ static ssize_t keys_proc_write(struct file *file, const char __user *buf,
cmd[len] = '\0';
if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) {
- key_event_valid = 0;
+ dev->key_event_valid = 0;
} else {
return -EINVAL;
}
@@ -820,21 +809,35 @@ static const struct file_operations version_proc_fops = {
#define PROC_TOSHIBA "toshiba"
-static void __init create_toshiba_proc_entries(void)
+static void __devinit
+create_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
{
- proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops);
- proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops);
- proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops);
- proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops);
- proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops);
+ if (dev->backlight_dev)
+ proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir,
+ &lcd_proc_fops, dev);
+ if (dev->video_supported)
+ proc_create_data("video", S_IRUGO | S_IWUSR, toshiba_proc_dir,
+ &video_proc_fops, dev);
+ if (dev->fan_supported)
+ proc_create_data("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir,
+ &fan_proc_fops, dev);
+ if (dev->hotkey_dev)
+ proc_create_data("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir,
+ &keys_proc_fops, dev);
+ proc_create_data("version", S_IRUGO, toshiba_proc_dir,
+ &version_proc_fops, dev);
}
-static void remove_toshiba_proc_entries(void)
+static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
{
- remove_proc_entry("lcd", toshiba_proc_dir);
- remove_proc_entry("video", toshiba_proc_dir);
- remove_proc_entry("fan", toshiba_proc_dir);
- remove_proc_entry("keys", toshiba_proc_dir);
+ if (dev->backlight_dev)
+ remove_proc_entry("lcd", toshiba_proc_dir);
+ if (dev->video_supported)
+ remove_proc_entry("video", toshiba_proc_dir);
+ if (dev->fan_supported)
+ remove_proc_entry("fan", toshiba_proc_dir);
+ if (dev->hotkey_dev)
+ remove_proc_entry("keys", toshiba_proc_dir);
remove_proc_entry("version", toshiba_proc_dir);
}
@@ -843,224 +846,256 @@ static const struct backlight_ops toshiba_backlight_data = {
.update_status = set_lcd_status,
};
-static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
-{
- u32 hci_result, value;
-
- if (event != 0x80)
- return;
- do {
- hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
- if (hci_result == HCI_SUCCESS) {
- if (value == 0x100)
- continue;
- /* act on key press; ignore key release */
- if (value & 0x80)
- continue;
-
- if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev,
- value, 1, true)) {
- pr_info("Unknown key %x\n",
- value);
- }
- } else if (hci_result == HCI_NOT_SUPPORTED) {
- /* This is a workaround for an unresolved issue on
- * some machines where system events sporadically
- * become disabled. */
- hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
- pr_notice("Re-enabled hotkeys\n");
- }
- } while (hci_result != HCI_EMPTY);
-}
-
-static int __init toshiba_acpi_setup_keyboard(char *device)
+static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
{
acpi_status status;
int error;
- status = acpi_get_handle(NULL, device, &toshiba_acpi.handle);
- if (ACPI_FAILURE(status)) {
- pr_info("Unable to get notification device\n");
- return -ENODEV;
- }
-
- toshiba_acpi.hotkey_dev = input_allocate_device();
- if (!toshiba_acpi.hotkey_dev) {
+ dev->hotkey_dev = input_allocate_device();
+ if (!dev->hotkey_dev) {
pr_info("Unable to register input device\n");
return -ENOMEM;
}
- toshiba_acpi.hotkey_dev->name = "Toshiba input device";
- toshiba_acpi.hotkey_dev->phys = device;
- toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
+ dev->hotkey_dev->name = "Toshiba input device";
+ dev->hotkey_dev->phys = "toshiba_acpi/input0";
+ dev->hotkey_dev->id.bustype = BUS_HOST;
- error = sparse_keymap_setup(toshiba_acpi.hotkey_dev,
- toshiba_acpi_keymap, NULL);
+ error = sparse_keymap_setup(dev->hotkey_dev, toshiba_acpi_keymap, NULL);
if (error)
goto err_free_dev;
- status = acpi_install_notify_handler(toshiba_acpi.handle,
- ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL);
- if (ACPI_FAILURE(status)) {
- pr_info("Unable to install hotkey notification\n");
- error = -ENODEV;
- goto err_free_keymap;
- }
-
- status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL);
+ status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", NULL, NULL);
if (ACPI_FAILURE(status)) {
pr_info("Unable to enable hotkeys\n");
error = -ENODEV;
- goto err_remove_notify;
+ goto err_free_keymap;
}
- error = input_register_device(toshiba_acpi.hotkey_dev);
+ error = input_register_device(dev->hotkey_dev);
if (error) {
pr_info("Unable to register input device\n");
- goto err_remove_notify;
+ goto err_free_keymap;
}
return 0;
- err_remove_notify:
- acpi_remove_notify_handler(toshiba_acpi.handle,
- ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
err_free_keymap:
- sparse_keymap_free(toshiba_acpi.hotkey_dev);
+ sparse_keymap_free(dev->hotkey_dev);
err_free_dev:
- input_free_device(toshiba_acpi.hotkey_dev);
- toshiba_acpi.hotkey_dev = NULL;
+ input_free_device(dev->hotkey_dev);
+ dev->hotkey_dev = NULL;
return error;
}
-static void toshiba_acpi_exit(void)
+static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
{
- if (toshiba_acpi.hotkey_dev) {
- acpi_remove_notify_handler(toshiba_acpi.handle,
- ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
- sparse_keymap_free(toshiba_acpi.hotkey_dev);
- input_unregister_device(toshiba_acpi.hotkey_dev);
+ struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+
+ remove_toshiba_proc_entries(dev);
+
+ if (dev->hotkey_dev) {
+ input_unregister_device(dev->hotkey_dev);
+ sparse_keymap_free(dev->hotkey_dev);
}
- if (toshiba_acpi.bt_rfk) {
- rfkill_unregister(toshiba_acpi.bt_rfk);
- rfkill_destroy(toshiba_acpi.bt_rfk);
+ if (dev->bt_rfk) {
+ rfkill_unregister(dev->bt_rfk);
+ rfkill_destroy(dev->bt_rfk);
}
- if (toshiba_backlight_device)
- backlight_device_unregister(toshiba_backlight_device);
+ if (dev->backlight_dev)
+ backlight_device_unregister(dev->backlight_dev);
- remove_toshiba_proc_entries();
+ if (dev->illumination_supported)
+ led_classdev_unregister(&dev->led_dev);
- if (toshiba_proc_dir)
- remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+ kfree(dev);
+
+ return 0;
+}
+
+static const char * __devinit find_hci_method(acpi_handle handle)
+{
+ acpi_status status;
+ acpi_handle hci_handle;
- if (toshiba_acpi.illumination_installed)
- led_classdev_unregister(&toshiba_led);
+ status = acpi_get_handle(handle, "GHCI", &hci_handle);
+ if (ACPI_SUCCESS(status))
+ return "GHCI";
- platform_device_unregister(toshiba_acpi.p_dev);
+ status = acpi_get_handle(handle, "SPFC", &hci_handle);
+ if (ACPI_SUCCESS(status))
+ return "SPFC";
- return;
+ return NULL;
}
-static int __init toshiba_acpi_init(void)
+static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
{
+ struct toshiba_acpi_dev *dev;
+ const char *hci_method;
u32 hci_result;
+ u32 dummy;
bool bt_present;
int ret = 0;
struct backlight_properties props;
- if (acpi_disabled)
- return -ENODEV;
-
- /* simple device detection: look for HCI method */
- if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) {
- method_hci = TOSH_INTERFACE_1 GHCI_METHOD;
- if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1))
- pr_info("Unable to activate hotkeys\n");
- } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) {
- method_hci = TOSH_INTERFACE_2 GHCI_METHOD;
- if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2))
- pr_info("Unable to activate hotkeys\n");
- } else
- return -ENODEV;
-
pr_info("Toshiba Laptop ACPI Extras version %s\n",
TOSHIBA_ACPI_VERSION);
- pr_info(" HCI method: %s\n", method_hci);
-
- mutex_init(&toshiba_acpi.mutex);
-
- toshiba_acpi.p_dev = platform_device_register_simple("toshiba_acpi",
- -1, NULL, 0);
- if (IS_ERR(toshiba_acpi.p_dev)) {
- ret = PTR_ERR(toshiba_acpi.p_dev);
- pr_err("unable to register platform device\n");
- toshiba_acpi.p_dev = NULL;
- toshiba_acpi_exit();
- return ret;
+
+ hci_method = find_hci_method(acpi_dev->handle);
+ if (!hci_method) {
+ pr_err("HCI interface not found\n");
+ return -ENODEV;
}
- force_fan = 0;
- key_event_valid = 0;
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+ dev->acpi_dev = acpi_dev;
+ dev->method_hci = hci_method;
+ acpi_dev->driver_data = dev;
- /* enable event fifo */
- hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
+ if (toshiba_acpi_setup_keyboard(dev))
+ pr_info("Unable to activate hotkeys\n");
- toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
- if (!toshiba_proc_dir) {
- toshiba_acpi_exit();
- return -ENODEV;
- } else {
- create_toshiba_proc_entries();
- }
+ mutex_init(&dev->mutex);
+
+ /* enable event fifo */
+ hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
props.type = BACKLIGHT_PLATFORM;
props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
- toshiba_backlight_device = backlight_device_register("toshiba",
- &toshiba_acpi.p_dev->dev,
- NULL,
- &toshiba_backlight_data,
- &props);
- if (IS_ERR(toshiba_backlight_device)) {
- ret = PTR_ERR(toshiba_backlight_device);
+ dev->backlight_dev = backlight_device_register("toshiba",
+ &acpi_dev->dev,
+ dev,
+ &toshiba_backlight_data,
+ &props);
+ if (IS_ERR(dev->backlight_dev)) {
+ ret = PTR_ERR(dev->backlight_dev);
pr_err("Could not register toshiba backlight device\n");
- toshiba_backlight_device = NULL;
- toshiba_acpi_exit();
- return ret;
+ dev->backlight_dev = NULL;
+ goto error;
}
+ dev->backlight_dev->props.brightness = get_lcd(dev->backlight_dev);
/* Register rfkill switch for Bluetooth */
- if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) {
- toshiba_acpi.bt_rfk = rfkill_alloc(toshiba_acpi.bt_name,
- &toshiba_acpi.p_dev->dev,
- RFKILL_TYPE_BLUETOOTH,
- &toshiba_rfk_ops,
- &toshiba_acpi);
- if (!toshiba_acpi.bt_rfk) {
+ if (hci_get_bt_present(dev, &bt_present) == HCI_SUCCESS && bt_present) {
+ dev->bt_rfk = rfkill_alloc("Toshiba Bluetooth",
+ &acpi_dev->dev,
+ RFKILL_TYPE_BLUETOOTH,
+ &toshiba_rfk_ops,
+ dev);
+ if (!dev->bt_rfk) {
pr_err("unable to allocate rfkill device\n");
- toshiba_acpi_exit();
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto error;
}
- ret = rfkill_register(toshiba_acpi.bt_rfk);
+ ret = rfkill_register(dev->bt_rfk);
if (ret) {
pr_err("unable to register rfkill device\n");
- rfkill_destroy(toshiba_acpi.bt_rfk);
- toshiba_acpi_exit();
- return ret;
+ rfkill_destroy(dev->bt_rfk);
+ goto error;
}
}
- toshiba_acpi.illumination_installed = 0;
- if (toshiba_illumination_available()) {
- if (!led_classdev_register(&(toshiba_acpi.p_dev->dev),
- &toshiba_led))
- toshiba_acpi.illumination_installed = 1;
+ if (toshiba_illumination_available(dev)) {
+ dev->led_dev.name = "toshiba::illumination";
+ dev->led_dev.max_brightness = 1;
+ dev->led_dev.brightness_set = toshiba_illumination_set;
+ dev->led_dev.brightness_get = toshiba_illumination_get;
+ if (!led_classdev_register(&acpi_dev->dev, &dev->led_dev))
+ dev->illumination_supported = 1;
}
+ /* Determine whether or not BIOS supports fan and video interfaces */
+
+ ret = get_video_status(dev, &dummy);
+ dev->video_supported = !ret;
+
+ ret = get_fan_status(dev, &dummy);
+ dev->fan_supported = !ret;
+
+ create_toshiba_proc_entries(dev);
+
return 0;
+
+error:
+ toshiba_acpi_remove(acpi_dev, 0);
+ return ret;
+}
+
+static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
+{
+ struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+ u32 hci_result, value;
+
+ if (event != 0x80)
+ return;
+ do {
+ hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
+ if (hci_result == HCI_SUCCESS) {
+ if (value == 0x100)
+ continue;
+ /* act on key press; ignore key release */
+ if (value & 0x80)
+ continue;
+
+ if (!sparse_keymap_report_event(dev->hotkey_dev,
+ value, 1, true)) {
+ pr_info("Unknown key %x\n",
+ value);
+ }
+ } else if (hci_result == HCI_NOT_SUPPORTED) {
+ /* This is a workaround for an unresolved issue on
+ * some machines where system events sporadically
+ * become disabled. */
+ hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
+ pr_notice("Re-enabled hotkeys\n");
+ }
+ } while (hci_result != HCI_EMPTY);
+}
+
+
+static struct acpi_driver toshiba_acpi_driver = {
+ .name = "Toshiba ACPI driver",
+ .owner = THIS_MODULE,
+ .ids = toshiba_device_ids,
+ .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
+ .ops = {
+ .add = toshiba_acpi_add,
+ .remove = toshiba_acpi_remove,
+ .notify = toshiba_acpi_notify,
+ },
+};
+
+static int __init toshiba_acpi_init(void)
+{
+ int ret;
+
+ toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
+ if (!toshiba_proc_dir) {
+ pr_err("Unable to create proc dir " PROC_TOSHIBA "\n");
+ return -ENODEV;
+ }
+
+ ret = acpi_bus_register_driver(&toshiba_acpi_driver);
+ if (ret) {
+ pr_err("Failed to register ACPI driver: %d\n", ret);
+ remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+ }
+
+ return ret;
+}
+
+static void __exit toshiba_acpi_exit(void)
+{
+ acpi_bus_unregister_driver(&toshiba_acpi_driver);
+ if (toshiba_proc_dir)
+ remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
}
module_init(toshiba_acpi_init);
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index f23d5a84e7b1..9b88be42b6cd 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -754,9 +754,13 @@ static void wmi_free_devices(void)
struct wmi_block *wblock, *next;
/* Delete devices for all the GUIDs */
- list_for_each_entry_safe(wblock, next, &wmi_block_list, list)
+ list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
+ list_del(&wblock->list);
if (wblock->dev.class)
device_unregister(&wblock->dev);
+ else
+ kfree(wblock);
+ }
}
static bool guid_already_parsed(const char *guid_string)
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 57de051a74b3..9f88641e67f9 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -70,6 +70,7 @@ config BATTERY_DS2760
config BATTERY_DS2780
tristate "DS2780 battery driver"
+ depends on HAS_IOMEM
select W1
select W1_SLAVE_DS2780
help
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
index 1fefe82e12e3..91a783d72360 100644
--- a/drivers/power/ds2780_battery.c
+++ b/drivers/power/ds2780_battery.c
@@ -39,6 +39,7 @@ struct ds2780_device_info {
struct device *dev;
struct power_supply bat;
struct device *w1_dev;
+ struct task_struct *mutex_holder;
};
enum current_types {
@@ -49,8 +50,8 @@ enum current_types {
static const char model[] = "DS2780";
static const char manufacturer[] = "Maxim/Dallas";
-static inline struct ds2780_device_info *to_ds2780_device_info(
- struct power_supply *psy)
+static inline struct ds2780_device_info *
+to_ds2780_device_info(struct power_supply *psy)
{
return container_of(psy, struct ds2780_device_info, bat);
}
@@ -60,17 +61,28 @@ static inline struct power_supply *to_power_supply(struct device *dev)
return dev_get_drvdata(dev);
}
-static inline int ds2780_read8(struct device *dev, u8 *val, int addr)
+static inline int ds2780_battery_io(struct ds2780_device_info *dev_info,
+ char *buf, int addr, size_t count, int io)
{
- return w1_ds2780_io(dev, val, addr, sizeof(u8), 0);
+ if (dev_info->mutex_holder == current)
+ return w1_ds2780_io_nolock(dev_info->w1_dev, buf, addr, count, io);
+ else
+ return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io);
+}
+
+static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val,
+ int addr)
+{
+ return ds2780_battery_io(dev_info, val, addr, sizeof(u8), 0);
}
-static int ds2780_read16(struct device *dev, s16 *val, int addr)
+static int ds2780_read16(struct ds2780_device_info *dev_info, s16 *val,
+ int addr)
{
int ret;
u8 raw[2];
- ret = w1_ds2780_io(dev, raw, addr, sizeof(u8) * 2, 0);
+ ret = ds2780_battery_io(dev_info, raw, addr, sizeof(raw), 0);
if (ret < 0)
return ret;
@@ -79,16 +91,16 @@ static int ds2780_read16(struct device *dev, s16 *val, int addr)
return 0;
}
-static inline int ds2780_read_block(struct device *dev, u8 *val, int addr,
- size_t count)
+static inline int ds2780_read_block(struct ds2780_device_info *dev_info,
+ u8 *val, int addr, size_t count)
{
- return w1_ds2780_io(dev, val, addr, count, 0);
+ return ds2780_battery_io(dev_info, val, addr, count, 0);
}
-static inline int ds2780_write(struct device *dev, u8 *val, int addr,
- size_t count)
+static inline int ds2780_write(struct ds2780_device_info *dev_info, u8 *val,
+ int addr, size_t count)
{
- return w1_ds2780_io(dev, val, addr, count, 1);
+ return ds2780_battery_io(dev_info, val, addr, count, 1);
}
static inline int ds2780_store_eeprom(struct device *dev, int addr)
@@ -122,7 +134,7 @@ static int ds2780_set_sense_register(struct ds2780_device_info *dev_info,
{
int ret;
- ret = ds2780_write(dev_info->w1_dev, &conductance,
+ ret = ds2780_write(dev_info, &conductance,
DS2780_RSNSP_REG, sizeof(u8));
if (ret < 0)
return ret;
@@ -134,7 +146,7 @@ static int ds2780_set_sense_register(struct ds2780_device_info *dev_info,
static int ds2780_get_rsgain_register(struct ds2780_device_info *dev_info,
u16 *rsgain)
{
- return ds2780_read16(dev_info->w1_dev, rsgain, DS2780_RSGAIN_MSB_REG);
+ return ds2780_read16(dev_info, rsgain, DS2780_RSGAIN_MSB_REG);
}
/* Set RSGAIN value from 0 to 1.999 in steps of 0.001 */
@@ -144,8 +156,8 @@ static int ds2780_set_rsgain_register(struct ds2780_device_info *dev_info,
int ret;
u8 raw[] = {rsgain >> 8, rsgain & 0xFF};
- ret = ds2780_write(dev_info->w1_dev, raw,
- DS2780_RSGAIN_MSB_REG, sizeof(u8) * 2);
+ ret = ds2780_write(dev_info, raw,
+ DS2780_RSGAIN_MSB_REG, sizeof(raw));
if (ret < 0)
return ret;
@@ -167,7 +179,7 @@ static int ds2780_get_voltage(struct ds2780_device_info *dev_info,
* Bits 2 - 0 of the voltage value are in bits 7 - 5 of the
* voltage LSB register
*/
- ret = ds2780_read16(dev_info->w1_dev, &voltage_raw,
+ ret = ds2780_read16(dev_info, &voltage_raw,
DS2780_VOLT_MSB_REG);
if (ret < 0)
return ret;
@@ -196,7 +208,7 @@ static int ds2780_get_temperature(struct ds2780_device_info *dev_info,
* Bits 2 - 0 of the temperature value are in bits 7 - 5 of the
* temperature LSB register
*/
- ret = ds2780_read16(dev_info->w1_dev, &temperature_raw,
+ ret = ds2780_read16(dev_info, &temperature_raw,
DS2780_TEMP_MSB_REG);
if (ret < 0)
return ret;
@@ -222,13 +234,13 @@ static int ds2780_get_current(struct ds2780_device_info *dev_info,
* The units of measurement for current are dependent on the value of
* the sense resistor.
*/
- ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG);
+ ret = ds2780_read8(dev_info, &sense_res_raw, DS2780_RSNSP_REG);
if (ret < 0)
return ret;
if (sense_res_raw == 0) {
dev_err(dev_info->dev, "sense resistor value is 0\n");
- return -ENXIO;
+ return -EINVAL;
}
sense_res = 1000 / sense_res_raw;
@@ -248,7 +260,7 @@ static int ds2780_get_current(struct ds2780_device_info *dev_info,
* Bits 7 - 0 of the current value are in bits 7 - 0 of the current
* LSB register
*/
- ret = ds2780_read16(dev_info->w1_dev, &current_raw, reg_msb);
+ ret = ds2780_read16(dev_info, &current_raw, reg_msb);
if (ret < 0)
return ret;
@@ -267,7 +279,7 @@ static int ds2780_get_accumulated_current(struct ds2780_device_info *dev_info,
* The units of measurement for accumulated current are dependent on
* the value of the sense resistor.
*/
- ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG);
+ ret = ds2780_read8(dev_info, &sense_res_raw, DS2780_RSNSP_REG);
if (ret < 0)
return ret;
@@ -285,7 +297,7 @@ static int ds2780_get_accumulated_current(struct ds2780_device_info *dev_info,
* Bits 7 - 0 of the ACR value are in bits 7 - 0 of the ACR
* LSB register
*/
- ret = ds2780_read16(dev_info->w1_dev, &current_raw, DS2780_ACR_MSB_REG);
+ ret = ds2780_read16(dev_info, &current_raw, DS2780_ACR_MSB_REG);
if (ret < 0)
return ret;
@@ -299,7 +311,7 @@ static int ds2780_get_capacity(struct ds2780_device_info *dev_info,
int ret;
u8 raw;
- ret = ds2780_read8(dev_info->w1_dev, &raw, DS2780_RARC_REG);
+ ret = ds2780_read8(dev_info, &raw, DS2780_RARC_REG);
if (ret < 0)
return ret;
@@ -345,7 +357,7 @@ static int ds2780_get_charge_now(struct ds2780_device_info *dev_info,
* Bits 7 - 0 of the RAAC value are in bits 7 - 0 of the RAAC
* LSB register
*/
- ret = ds2780_read16(dev_info->w1_dev, &charge_raw, DS2780_RAAC_MSB_REG);
+ ret = ds2780_read16(dev_info, &charge_raw, DS2780_RAAC_MSB_REG);
if (ret < 0)
return ret;
@@ -356,7 +368,7 @@ static int ds2780_get_charge_now(struct ds2780_device_info *dev_info,
static int ds2780_get_control_register(struct ds2780_device_info *dev_info,
u8 *control_reg)
{
- return ds2780_read8(dev_info->w1_dev, control_reg, DS2780_CONTROL_REG);
+ return ds2780_read8(dev_info, control_reg, DS2780_CONTROL_REG);
}
static int ds2780_set_control_register(struct ds2780_device_info *dev_info,
@@ -364,7 +376,7 @@ static int ds2780_set_control_register(struct ds2780_device_info *dev_info,
{
int ret;
- ret = ds2780_write(dev_info->w1_dev, &control_reg,
+ ret = ds2780_write(dev_info, &control_reg,
DS2780_CONTROL_REG, sizeof(u8));
if (ret < 0)
return ret;
@@ -503,7 +515,7 @@ static ssize_t ds2780_get_sense_resistor_value(struct device *dev,
struct power_supply *psy = to_power_supply(dev);
struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
- ret = ds2780_read8(dev_info->w1_dev, &sense_resistor, DS2780_RSNSP_REG);
+ ret = ds2780_read8(dev_info, &sense_resistor, DS2780_RSNSP_REG);
if (ret < 0)
return ret;
@@ -584,7 +596,7 @@ static ssize_t ds2780_get_pio_pin(struct device *dev,
struct power_supply *psy = to_power_supply(dev);
struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
- ret = ds2780_read8(dev_info->w1_dev, &sfr, DS2780_SFR_REG);
+ ret = ds2780_read8(dev_info, &sfr, DS2780_SFR_REG);
if (ret < 0)
return ret;
@@ -611,7 +623,7 @@ static ssize_t ds2780_set_pio_pin(struct device *dev,
return -EINVAL;
}
- ret = ds2780_write(dev_info->w1_dev, &new_setting,
+ ret = ds2780_write(dev_info, &new_setting,
DS2780_SFR_REG, sizeof(u8));
if (ret < 0)
return ret;
@@ -632,7 +644,7 @@ static ssize_t ds2780_read_param_eeprom_bin(struct file *filp,
DS2780_EEPROM_BLOCK1_END -
DS2780_EEPROM_BLOCK1_START + 1 - off);
- return ds2780_read_block(dev_info->w1_dev, buf,
+ return ds2780_read_block(dev_info, buf,
DS2780_EEPROM_BLOCK1_START + off, count);
}
@@ -650,7 +662,7 @@ static ssize_t ds2780_write_param_eeprom_bin(struct file *filp,
DS2780_EEPROM_BLOCK1_END -
DS2780_EEPROM_BLOCK1_START + 1 - off);
- ret = ds2780_write(dev_info->w1_dev, buf,
+ ret = ds2780_write(dev_info, buf,
DS2780_EEPROM_BLOCK1_START + off, count);
if (ret < 0)
return ret;
@@ -685,9 +697,8 @@ static ssize_t ds2780_read_user_eeprom_bin(struct file *filp,
DS2780_EEPROM_BLOCK0_END -
DS2780_EEPROM_BLOCK0_START + 1 - off);
- return ds2780_read_block(dev_info->w1_dev, buf,
+ return ds2780_read_block(dev_info, buf,
DS2780_EEPROM_BLOCK0_START + off, count);
-
}
static ssize_t ds2780_write_user_eeprom_bin(struct file *filp,
@@ -704,7 +715,7 @@ static ssize_t ds2780_write_user_eeprom_bin(struct file *filp,
DS2780_EEPROM_BLOCK0_END -
DS2780_EEPROM_BLOCK0_START + 1 - off);
- ret = ds2780_write(dev_info->w1_dev, buf,
+ ret = ds2780_write(dev_info, buf,
DS2780_EEPROM_BLOCK0_START + off, count);
if (ret < 0)
return ret;
@@ -768,6 +779,7 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev)
dev_info->bat.properties = ds2780_battery_props;
dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props);
dev_info->bat.get_property = ds2780_battery_get_property;
+ dev_info->mutex_holder = current;
ret = power_supply_register(&pdev->dev, &dev_info->bat);
if (ret) {
@@ -797,6 +809,8 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev)
goto fail_remove_bin_file;
}
+ dev_info->mutex_holder = NULL;
+
return 0;
fail_remove_bin_file:
@@ -816,6 +830,8 @@ static int __devexit ds2780_battery_remove(struct platform_device *pdev)
{
struct ds2780_device_info *dev_info = platform_get_drvdata(pdev);
+ dev_info->mutex_holder = current;
+
/* remove attributes */
sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group);
diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig
index 8520a7f4dd62..445197d4a8c4 100644
--- a/drivers/pps/clients/Kconfig
+++ b/drivers/pps/clients/Kconfig
@@ -29,4 +29,13 @@ config PPS_CLIENT_PARPORT
If you say yes here you get support for a PPS source connected
with the interrupt pin of your parallel port.
+config PPS_CLIENT_GPIO
+ tristate "PPS client using GPIO"
+ depends on PPS && GENERIC_HARDIRQS
+ help
+ If you say yes here you get support for a PPS source using
+ GPIO. To be useful you must also register a platform device
+ specifying the GPIO pin and other options, usually in your board
+ setup.
+
endif
diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile
index 4feb7e9e71ee..a461d15f4a2e 100644
--- a/drivers/pps/clients/Makefile
+++ b/drivers/pps/clients/Makefile
@@ -5,5 +5,6 @@
obj-$(CONFIG_PPS_CLIENT_KTIMER) += pps-ktimer.o
obj-$(CONFIG_PPS_CLIENT_LDISC) += pps-ldisc.o
obj-$(CONFIG_PPS_CLIENT_PARPORT) += pps_parport.o
+obj-$(CONFIG_PPS_CLIENT_GPIO) += pps-gpio.o
ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c
new file mode 100644
index 000000000000..655055545479
--- /dev/null
+++ b/drivers/pps/clients/pps-gpio.c
@@ -0,0 +1,227 @@
+/*
+ * pps-gpio.c -- PPS client driver using GPIO
+ *
+ *
+ * Copyright (C) 2010 Ricardo Martins <rasm@fe.up.pt>
+ * Copyright (C) 2011 James Nuss <jamesnuss@nanometrics.ca>
+ *
+ * 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.
+ */
+
+#define PPS_GPIO_NAME "pps-gpio"
+#define pr_fmt(fmt) PPS_GPIO_NAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pps_kernel.h>
+#include <linux/pps-gpio.h>
+#include <linux/gpio.h>
+#include <linux/list.h>
+
+/* Info for each registered platform device */
+struct pps_gpio_device_data {
+ int irq; /* IRQ used as PPS source */
+ struct pps_device *pps; /* PPS source device */
+ struct pps_source_info info; /* PPS source information */
+ const struct pps_gpio_platform_data *pdata;
+};
+
+/*
+ * Report the PPS event
+ */
+
+static irqreturn_t pps_gpio_irq_handler(int irq, void *data)
+{
+ const struct pps_gpio_device_data *info;
+ struct pps_event_time ts;
+ int rising_edge;
+
+ /* Get the time stamp first */
+ pps_get_ts(&ts);
+
+ info = data;
+
+ rising_edge = gpio_get_value(info->pdata->gpio_pin);
+ if ((rising_edge && !info->pdata->assert_falling_edge) ||
+ (!rising_edge && info->pdata->assert_falling_edge))
+ pps_event(info->pps, &ts, PPS_CAPTUREASSERT, NULL);
+ else if (info->pdata->capture_clear &&
+ ((rising_edge && info->pdata->assert_falling_edge) ||
+ (!rising_edge && !info->pdata->assert_falling_edge)))
+ pps_event(info->pps, &ts, PPS_CAPTURECLEAR, NULL);
+
+ return IRQ_HANDLED;
+}
+
+static int pps_gpio_setup(struct platform_device *pdev)
+{
+ int ret;
+ const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
+
+ ret = gpio_request(pdata->gpio_pin, pdata->gpio_label);
+ if (ret) {
+ pr_warning("failed to request GPIO %u\n", pdata->gpio_pin);
+ return -EINVAL;
+ }
+
+ ret = gpio_direction_input(pdata->gpio_pin);
+ if (ret) {
+ pr_warning("failed to set pin direction\n");
+ gpio_free(pdata->gpio_pin);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static unsigned long
+get_irqf_trigger_flags(const struct pps_gpio_platform_data *pdata)
+{
+ unsigned long flags = pdata->assert_falling_edge ?
+ IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+
+ if (pdata->capture_clear) {
+ flags |= ((flags & IRQF_TRIGGER_RISING) ?
+ IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING);
+ }
+
+ return flags;
+}
+
+static int pps_gpio_probe(struct platform_device *pdev)
+{
+ struct pps_gpio_device_data *data;
+ int irq;
+ int ret;
+ int err;
+ int pps_default_params;
+ const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
+
+
+ /* GPIO setup */
+ ret = pps_gpio_setup(pdev);
+ if (ret)
+ return -EINVAL;
+
+ /* IRQ setup */
+ irq = gpio_to_irq(pdata->gpio_pin);
+ if (irq < 0) {
+ pr_err("failed to map GPIO to IRQ: %d\n", irq);
+ err = -EINVAL;
+ goto return_error;
+ }
+
+ /* allocate space for device info */
+ data = kzalloc(sizeof(struct pps_gpio_device_data), GFP_KERNEL);
+ if (data == NULL) {
+ err = -ENOMEM;
+ goto return_error;
+ }
+
+ /* initialize PPS specific parts of the bookkeeping data structure. */
+ data->info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
+ PPS_ECHOASSERT | PPS_CANWAIT | PPS_TSFMT_TSPEC;
+ if (pdata->capture_clear)
+ data->info.mode |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR |
+ PPS_ECHOCLEAR;
+ data->info.owner = THIS_MODULE;
+ snprintf(data->info.name, PPS_MAX_NAME_LEN - 1, "%s.%d",
+ pdev->name, pdev->id);
+
+ /* register PPS source */
+ pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
+ if (pdata->capture_clear)
+ pps_default_params |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR;
+ data->pps = pps_register_source(&data->info, pps_default_params);
+ if (data->pps == NULL) {
+ kfree(data);
+ pr_err("failed to register IRQ %d as PPS source\n", irq);
+ err = -EINVAL;
+ goto return_error;
+ }
+
+ data->irq = irq;
+ data->pdata = pdata;
+
+ /* register IRQ interrupt handler */
+ ret = request_irq(irq, pps_gpio_irq_handler,
+ get_irqf_trigger_flags(pdata), data->info.name, data);
+ if (ret) {
+ pps_unregister_source(data->pps);
+ kfree(data);
+ pr_err("failed to acquire IRQ %d\n", irq);
+ err = -EINVAL;
+ goto return_error;
+ }
+
+ platform_set_drvdata(pdev, data);
+ dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", irq);
+
+ return 0;
+
+return_error:
+ gpio_free(pdata->gpio_pin);
+ return err;
+}
+
+static int pps_gpio_remove(struct platform_device *pdev)
+{
+ struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
+ const struct pps_gpio_platform_data *pdata = data->pdata;
+
+ platform_set_drvdata(pdev, NULL);
+ free_irq(data->irq, data);
+ gpio_free(pdata->gpio_pin);
+ pps_unregister_source(data->pps);
+ pr_info("removed IRQ %d as PPS source\n", data->irq);
+ kfree(data);
+ return 0;
+}
+
+static struct platform_driver pps_gpio_driver = {
+ .probe = pps_gpio_probe,
+ .remove = __devexit_p(pps_gpio_remove),
+ .driver = {
+ .name = PPS_GPIO_NAME,
+ .owner = THIS_MODULE
+ },
+};
+
+static int __init pps_gpio_init(void)
+{
+ int ret = platform_driver_register(&pps_gpio_driver);
+ if (ret < 0)
+ pr_err("failed to register platform driver\n");
+ return ret;
+}
+
+static void __exit pps_gpio_exit(void)
+{
+ platform_driver_unregister(&pps_gpio_driver);
+ pr_debug("unregistered platform driver\n");
+}
+
+module_init(pps_gpio_init);
+module_exit(pps_gpio_exit);
+
+MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>");
+MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>");
+MODULE_DESCRIPTION("Use GPIO pin as PPS source");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.0");
diff --git a/drivers/pps/clients/pps-ktimer.c b/drivers/pps/clients/pps-ktimer.c
index 82583b0ff82d..436b4e4e71a1 100644
--- a/drivers/pps/clients/pps-ktimer.c
+++ b/drivers/pps/clients/pps-ktimer.c
@@ -52,17 +52,6 @@ static void pps_ktimer_event(unsigned long ptr)
}
/*
- * The echo function
- */
-
-static void pps_ktimer_echo(struct pps_device *pps, int event, void *data)
-{
- dev_info(pps->dev, "echo %s %s\n",
- event & PPS_CAPTUREASSERT ? "assert" : "",
- event & PPS_CAPTURECLEAR ? "clear" : "");
-}
-
-/*
* The PPS info struct
*/
@@ -72,7 +61,6 @@ static struct pps_source_info pps_ktimer_info = {
.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
PPS_ECHOASSERT |
PPS_CANWAIT | PPS_TSFMT_TSPEC,
- .echo = pps_ktimer_echo,
.owner = THIS_MODULE,
};
diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c
index c571d6dd8f61..e1b4705ae3ec 100644
--- a/drivers/pps/clients/pps_parport.c
+++ b/drivers/pps/clients/pps_parport.c
@@ -133,14 +133,6 @@ out_both:
return;
}
-/* the PPS echo function */
-static void pps_echo(struct pps_device *pps, int event, void *data)
-{
- dev_info(pps->dev, "echo %s %s\n",
- event & PPS_CAPTUREASSERT ? "assert" : "",
- event & PPS_CAPTURECLEAR ? "clear" : "");
-}
-
static void parport_attach(struct parport *port)
{
struct pps_client_pp *device;
@@ -151,7 +143,6 @@ static void parport_attach(struct parport *port)
PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \
PPS_ECHOASSERT | PPS_ECHOCLEAR | \
PPS_CANWAIT | PPS_TSFMT_TSPEC,
- .echo = pps_echo,
.owner = THIS_MODULE,
.dev = NULL
};
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index a4e8eb9fece6..f197e8ea185c 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -52,6 +52,14 @@ static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset)
ts->sec += offset->sec;
}
+static void pps_echo_client_default(struct pps_device *pps, int event,
+ void *data)
+{
+ dev_info(pps->dev, "echo %s %s\n",
+ event & PPS_CAPTUREASSERT ? "assert" : "",
+ event & PPS_CAPTURECLEAR ? "clear" : "");
+}
+
/*
* Exported functions
*/
@@ -80,13 +88,6 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
err = -EINVAL;
goto pps_register_source_exit;
}
- if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 &&
- info->echo == NULL) {
- pr_err("%s: echo function is not defined\n",
- info->name);
- err = -EINVAL;
- goto pps_register_source_exit;
- }
if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
pr_err("%s: unspecified time format\n",
info->name);
@@ -108,6 +109,11 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
pps->params.mode = default_params;
pps->info = *info;
+ /* check for default echo function */
+ if ((pps->info.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) &&
+ pps->info.echo == NULL)
+ pps->info.echo = pps_echo_client_default;
+
init_waitqueue_head(&pps->queue);
spin_lock_init(&pps->lock);
diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig
index 070211a5955c..bc8719238793 100644
--- a/drivers/rapidio/Kconfig
+++ b/drivers/rapidio/Kconfig
@@ -1,6 +1,8 @@
#
# RapidIO configuration
#
+source "drivers/rapidio/devices/Kconfig"
+
config RAPIDIO_DISC_TIMEOUT
int "Discovery timeout duration (seconds)"
depends on RAPIDIO
@@ -20,8 +22,6 @@ config RAPIDIO_ENABLE_RX_TX_PORTS
ports for Input/Output direction to allow other traffic
than Maintenance transfers.
-source "drivers/rapidio/switches/Kconfig"
-
config RAPIDIO_DEBUG
bool "RapidIO subsystem debug messages"
depends on RAPIDIO
@@ -32,3 +32,5 @@ config RAPIDIO_DEBUG
going on.
If you are unsure about this, say N here.
+
+source "drivers/rapidio/switches/Kconfig"
diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile
index 89b8eca825b5..ec3fb8121004 100644
--- a/drivers/rapidio/Makefile
+++ b/drivers/rapidio/Makefile
@@ -4,5 +4,6 @@
obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
obj-$(CONFIG_RAPIDIO) += switches/
+obj-$(CONFIG_RAPIDIO) += devices/
subdir-ccflags-$(CONFIG_RAPIDIO_DEBUG) := -DDEBUG
diff --git a/drivers/rapidio/devices/Kconfig b/drivers/rapidio/devices/Kconfig
new file mode 100644
index 000000000000..12a9d7f7040b
--- /dev/null
+++ b/drivers/rapidio/devices/Kconfig
@@ -0,0 +1,10 @@
+#
+# RapidIO master port configuration
+#
+
+config RAPIDIO_TSI721
+ bool "IDT Tsi721 PCI Express SRIO Controller support"
+ depends on RAPIDIO && PCIEPORTBUS
+ default "n"
+ ---help---
+ Include support for IDT Tsi721 PCI Express Serial RapidIO controller.
diff --git a/drivers/rapidio/devices/Makefile b/drivers/rapidio/devices/Makefile
new file mode 100644
index 000000000000..3b7b4e2dff7c
--- /dev/null
+++ b/drivers/rapidio/devices/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for RapidIO devices
+#
+
+obj-$(CONFIG_RAPIDIO_TSI721) += tsi721.o
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
new file mode 100644
index 000000000000..5225930a10cd
--- /dev/null
+++ b/drivers/rapidio/devices/tsi721.c
@@ -0,0 +1,2360 @@
+/*
+ * RapidIO mport driver for Tsi721 PCIExpress-to-SRIO bridge
+ *
+ * Copyright 2011 Integrated Device Technology, Inc.
+ * Alexandre Bounine <alexandre.bounine@idt.com>
+ * Chul Kim <chul.kim@idt.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/kfifo.h>
+#include <linux/delay.h>
+
+#include "tsi721.h"
+
+#define DEBUG_PW /* Inbound Port-Write debugging */
+
+static void tsi721_omsg_handler(struct tsi721_device *priv, int ch);
+static void tsi721_imsg_handler(struct tsi721_device *priv, int ch);
+
+/**
+ * tsi721_lcread - read from local SREP config space
+ * @mport: RapidIO master port info
+ * @index: ID of RapdiIO interface
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be read into
+ *
+ * Generates a local SREP space read. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int tsi721_lcread(struct rio_mport *mport, int index, u32 offset,
+ int len, u32 *data)
+{
+ struct tsi721_device *priv = mport->priv;
+
+ if (len != sizeof(u32))
+ return -EINVAL; /* only 32-bit access is supported */
+
+ *data = ioread32(priv->regs + offset);
+
+ return 0;
+}
+
+/**
+ * tsi721_lcwrite - write into local SREP config space
+ * @mport: RapidIO master port info
+ * @index: ID of RapdiIO interface
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be written
+ *
+ * Generates a local write into SREP configuration space. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int tsi721_lcwrite(struct rio_mport *mport, int index, u32 offset,
+ int len, u32 data)
+{
+ struct tsi721_device *priv = mport->priv;
+
+ if (len != sizeof(u32))
+ return -EINVAL; /* only 32-bit access is supported */
+
+ iowrite32(data, priv->regs + offset);
+
+ return 0;
+}
+
+/**
+ * tsi721_maint_dma - Helper function to generate RapidIO maintenance
+ * transactions using designated Tsi721 DMA channel.
+ * @priv: pointer to tsi721 private data
+ * @sys_size: RapdiIO transport system size
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Location to be read from or write into
+ * @do_wr: Operation flag (1 == MAINT_WR)
+ *
+ * Generates a RapidIO maintenance transaction (Read or Write).
+ * Returns %0 on success and %-EINVAL or %-EFAULT on failure.
+ */
+static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size,
+ u16 destid, u8 hopcount, u32 offset, int len,
+ u32 *data, int do_wr)
+{
+ struct tsi721_dma_desc *bd_ptr;
+ u32 rd_count, swr_ptr, ch_stat;
+ int i, err = 0;
+ u32 op = do_wr ? MAINT_WR : MAINT_RD;
+
+ if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32)))
+ return -EINVAL;
+
+ bd_ptr = priv->bdma[TSI721_DMACH_MAINT].bd_base;
+
+ rd_count = ioread32(
+ priv->regs + TSI721_DMAC_DRDCNT(TSI721_DMACH_MAINT));
+
+ /* Initialize DMA descriptor */
+ bd_ptr[0].type_id = cpu_to_le32((DTYPE2 << 29) | (op << 19) | destid);
+ bd_ptr[0].bcount = cpu_to_le32((sys_size << 26) | 0x04);
+ bd_ptr[0].raddr_lo = cpu_to_le32((hopcount << 24) | offset);
+ bd_ptr[0].raddr_hi = 0;
+ if (do_wr)
+ bd_ptr[0].data[0] = cpu_to_be32p(data);
+ else
+ bd_ptr[0].data[0] = 0xffffffff;
+
+ mb();
+
+ /* Start DMA operation */
+ iowrite32(rd_count + 2,
+ priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT));
+ ioread32(priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT));
+ i = 0;
+
+ /* Wait until DMA transfer is finished */
+ while ((ch_stat = ioread32(priv->regs +
+ TSI721_DMAC_STS(TSI721_DMACH_MAINT))) & TSI721_DMAC_STS_RUN) {
+ udelay(1);
+ if (++i >= 5000000) {
+ dev_dbg(&priv->pdev->dev,
+ "%s : DMA[%d] read timeout ch_status=%x\n",
+ __func__, TSI721_DMACH_MAINT, ch_stat);
+ if (!do_wr)
+ *data = 0xffffffff;
+ err = -EIO;
+ goto err_out;
+ }
+ }
+
+ if (ch_stat & TSI721_DMAC_STS_ABORT) {
+ /* If DMA operation aborted due to error,
+ * reinitialize DMA channel
+ */
+ dev_dbg(&priv->pdev->dev, "%s : DMA ABORT ch_stat=%x\n",
+ __func__, ch_stat);
+ dev_dbg(&priv->pdev->dev, "OP=%d : destid=%x hc=%x off=%x\n",
+ do_wr ? MAINT_WR : MAINT_RD, destid, hopcount, offset);
+ iowrite32(TSI721_DMAC_INT_ALL,
+ priv->regs + TSI721_DMAC_INT(TSI721_DMACH_MAINT));
+ iowrite32(TSI721_DMAC_CTL_INIT,
+ priv->regs + TSI721_DMAC_CTL(TSI721_DMACH_MAINT));
+ udelay(10);
+ iowrite32(0, priv->regs +
+ TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT));
+ udelay(1);
+ if (!do_wr)
+ *data = 0xffffffff;
+ err = -EIO;
+ goto err_out;
+ }
+
+ if (!do_wr)
+ *data = be32_to_cpu(bd_ptr[0].data[0]);
+
+ /*
+ * Update descriptor status FIFO RD pointer.
+ * NOTE: Skipping check and clear FIFO entries because we are waiting
+ * for transfer to be completed.
+ */
+ swr_ptr = ioread32(priv->regs + TSI721_DMAC_DSWP(TSI721_DMACH_MAINT));
+ iowrite32(swr_ptr, priv->regs + TSI721_DMAC_DSRP(TSI721_DMACH_MAINT));
+err_out:
+
+ return err;
+}
+
+/**
+ * tsi721_cread_dma - Generate a RapidIO maintenance read transaction
+ * using Tsi721 BDMA engine.
+ * @mport: RapidIO master port control structure
+ * @index: ID of RapdiIO interface
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Location to be read into
+ *
+ * Generates a RapidIO maintenance read transaction.
+ * Returns %0 on success and %-EINVAL or %-EFAULT on failure.
+ */
+static int tsi721_cread_dma(struct rio_mport *mport, int index, u16 destid,
+ u8 hopcount, u32 offset, int len, u32 *data)
+{
+ struct tsi721_device *priv = mport->priv;
+
+ return tsi721_maint_dma(priv, mport->sys_size, destid, hopcount,
+ offset, len, data, 0);
+}
+
+/**
+ * tsi721_cwrite_dma - Generate a RapidIO maintenance write transaction
+ * using Tsi721 BDMA engine
+ * @mport: RapidIO master port control structure
+ * @index: ID of RapdiIO interface
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Value to be written
+ *
+ * Generates a RapidIO maintenance write transaction.
+ * Returns %0 on success and %-EINVAL or %-EFAULT on failure.
+ */
+static int tsi721_cwrite_dma(struct rio_mport *mport, int index, u16 destid,
+ u8 hopcount, u32 offset, int len, u32 data)
+{
+ struct tsi721_device *priv = mport->priv;
+ u32 temp = data;
+
+ return tsi721_maint_dma(priv, mport->sys_size, destid, hopcount,
+ offset, len, &temp, 1);
+}
+
+/**
+ * tsi721_pw_handler - Tsi721 inbound port-write interrupt handler
+ * @mport: RapidIO master port structure
+ *
+ * Handles inbound port-write interrupts. Copies PW message from an internal
+ * buffer into PW message FIFO and schedules deferred routine to process
+ * queued messages.
+ */
+static int
+tsi721_pw_handler(struct rio_mport *mport)
+{
+ struct tsi721_device *priv = mport->priv;
+ u32 pw_stat;
+ u32 pw_buf[TSI721_RIO_PW_MSG_SIZE/sizeof(u32)];
+
+
+ pw_stat = ioread32(priv->regs + TSI721_RIO_PW_RX_STAT);
+
+ if (pw_stat & TSI721_RIO_PW_RX_STAT_PW_VAL) {
+ pw_buf[0] = ioread32(priv->regs + TSI721_RIO_PW_RX_CAPT(0));
+ pw_buf[1] = ioread32(priv->regs + TSI721_RIO_PW_RX_CAPT(1));
+ pw_buf[2] = ioread32(priv->regs + TSI721_RIO_PW_RX_CAPT(2));
+ pw_buf[3] = ioread32(priv->regs + TSI721_RIO_PW_RX_CAPT(3));
+
+ /* Queue PW message (if there is room in FIFO),
+ * otherwise discard it.
+ */
+ spin_lock(&priv->pw_fifo_lock);
+ if (kfifo_avail(&priv->pw_fifo) >= TSI721_RIO_PW_MSG_SIZE)
+ kfifo_in(&priv->pw_fifo, pw_buf,
+ TSI721_RIO_PW_MSG_SIZE);
+ else
+ priv->pw_discard_count++;
+ spin_unlock(&priv->pw_fifo_lock);
+ }
+
+ /* Clear pending PW interrupts */
+ iowrite32(TSI721_RIO_PW_RX_STAT_PW_DISC | TSI721_RIO_PW_RX_STAT_PW_VAL,
+ priv->regs + TSI721_RIO_PW_RX_STAT);
+
+ schedule_work(&priv->pw_work);
+
+ return 0;
+}
+
+static void tsi721_pw_dpc(struct work_struct *work)
+{
+ struct tsi721_device *priv = container_of(work, struct tsi721_device,
+ pw_work);
+ u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)]; /* Use full size PW message
+ buffer for RIO layer */
+
+ /*
+ * Process port-write messages
+ */
+ while (kfifo_out_spinlocked(&priv->pw_fifo, (unsigned char *)msg_buffer,
+ TSI721_RIO_PW_MSG_SIZE, &priv->pw_fifo_lock)) {
+ /* Process one message */
+#ifdef DEBUG_PW
+ {
+ u32 i;
+ pr_debug("%s : Port-Write Message:", __func__);
+ for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); ) {
+ pr_debug("0x%02x: %08x %08x %08x %08x", i*4,
+ msg_buffer[i], msg_buffer[i + 1],
+ msg_buffer[i + 2], msg_buffer[i + 3]);
+ i += 4;
+ }
+ pr_debug("\n");
+ }
+#endif
+ /* Pass the port-write message to RIO core for processing */
+ rio_inb_pwrite_handler((union rio_pw_msg *)msg_buffer);
+ }
+}
+
+/**
+ * tsi721_pw_enable - enable/disable port-write interface init
+ * @mport: Master port implementing the port write unit
+ * @enable: 1=enable; 0=disable port-write message handling
+ */
+static int tsi721_pw_enable(struct rio_mport *mport, int enable)
+{
+ struct tsi721_device *priv = mport->priv;
+ u32 rval;
+
+ rval = ioread32(priv->regs + TSI721_RIO_EM_INT_ENABLE);
+
+ if (enable)
+ rval |= TSI721_RIO_EM_INT_ENABLE_PW_RX;
+ else
+ rval &= ~TSI721_RIO_EM_INT_ENABLE_PW_RX;
+
+ /* Clear pending PW interrupts */
+ iowrite32(TSI721_RIO_PW_RX_STAT_PW_DISC | TSI721_RIO_PW_RX_STAT_PW_VAL,
+ priv->regs + TSI721_RIO_PW_RX_STAT);
+ /* Update enable bits */
+ iowrite32(rval, priv->regs + TSI721_RIO_EM_INT_ENABLE);
+
+ return 0;
+}
+
+/**
+ * tsi721_dsend - Send a RapidIO doorbell
+ * @mport: RapidIO master port info
+ * @index: ID of RapidIO interface
+ * @destid: Destination ID of target device
+ * @data: 16-bit info field of RapidIO doorbell
+ *
+ * Sends a RapidIO doorbell message. Always returns %0.
+ */
+static int tsi721_dsend(struct rio_mport *mport, int index,
+ u16 destid, u16 data)
+{
+ struct tsi721_device *priv = mport->priv;
+ u32 offset;
+
+ offset = (((mport->sys_size) ? RIO_TT_CODE_16 : RIO_TT_CODE_8) << 18) |
+ (destid << 2);
+
+ dev_dbg(&priv->pdev->dev,
+ "Send Doorbell 0x%04x to destID 0x%x\n", data, destid);
+ iowrite16be(data, priv->odb_base + offset);
+
+ return 0;
+}
+
+/**
+ * tsi721_dbell_handler - Tsi721 doorbell interrupt handler
+ * @mport: RapidIO master port structure
+ *
+ * Handles inbound doorbell interrupts. Copies doorbell entry from an internal
+ * buffer into DB message FIFO and schedules deferred routine to process
+ * queued DBs.
+ */
+static int
+tsi721_dbell_handler(struct rio_mport *mport)
+{
+ struct tsi721_device *priv = mport->priv;
+ u32 regval;
+
+ /* Disable IDB interrupts */
+ regval = ioread32(priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
+ regval &= ~TSI721_SR_CHINT_IDBQRCV;
+ iowrite32(regval,
+ priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
+
+ schedule_work(&priv->idb_work);
+
+ return 0;
+}
+
+static void tsi721_db_dpc(struct work_struct *work)
+{
+ struct tsi721_device *priv = container_of(work, struct tsi721_device,
+ idb_work);
+ struct rio_mport *mport;
+ struct rio_dbell *dbell;
+ int found = 0;
+ u32 wr_ptr, rd_ptr;
+ u64 *idb_entry;
+ u32 regval;
+ union {
+ u64 msg;
+ u8 bytes[8];
+ } idb;
+
+ /*
+ * Process queued inbound doorbells
+ */
+ mport = priv->mport;
+
+ wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE));
+ rd_ptr = ioread32(priv->regs + TSI721_IDQ_RP(IDB_QUEUE));
+
+ while (wr_ptr != rd_ptr) {
+ idb_entry = (u64 *)(priv->idb_base +
+ (TSI721_IDB_ENTRY_SIZE * rd_ptr));
+ rd_ptr++;
+ idb.msg = *idb_entry;
+ *idb_entry = 0;
+
+ /* Process one doorbell */
+ list_for_each_entry(dbell, &mport->dbells, node) {
+ if ((dbell->res->start <= DBELL_INF(idb.bytes)) &&
+ (dbell->res->end >= DBELL_INF(idb.bytes))) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ dbell->dinb(mport, dbell->dev_id, DBELL_SID(idb.bytes),
+ DBELL_TID(idb.bytes), DBELL_INF(idb.bytes));
+ } else {
+ dev_dbg(&priv->pdev->dev,
+ "spurious inb doorbell, sid %2.2x tid %2.2x"
+ " info %4.4x\n", DBELL_SID(idb.bytes),
+ DBELL_TID(idb.bytes), DBELL_INF(idb.bytes));
+ }
+ }
+
+ iowrite32(rd_ptr & (IDB_QSIZE - 1),
+ priv->regs + TSI721_IDQ_RP(IDB_QUEUE));
+
+ /* Re-enable IDB interrupts */
+ regval = ioread32(priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
+ regval |= TSI721_SR_CHINT_IDBQRCV;
+ iowrite32(regval,
+ priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
+}
+
+/**
+ * tsi721_irqhandler - Tsi721 interrupt handler
+ * @irq: Linux interrupt number
+ * @ptr: Pointer to interrupt-specific data (mport structure)
+ *
+ * Handles Tsi721 interrupts signaled using MSI and INTA. Checks reported
+ * interrupt events and calls an event-specific handler(s).
+ */
+static irqreturn_t tsi721_irqhandler(int irq, void *ptr)
+{
+ struct rio_mport *mport = (struct rio_mport *)ptr;
+ struct tsi721_device *priv = mport->priv;
+ u32 dev_int;
+ u32 dev_ch_int;
+ u32 intval;
+ u32 ch_inte;
+
+ dev_int = ioread32(priv->regs + TSI721_DEV_INT);
+ if (!dev_int)
+ return IRQ_NONE;
+
+ dev_ch_int = ioread32(priv->regs + TSI721_DEV_CHAN_INT);
+
+ if (dev_int & TSI721_DEV_INT_SR2PC_CH) {
+ /* Service SR2PC Channel interrupts */
+ if (dev_ch_int & TSI721_INT_SR2PC_CHAN(IDB_QUEUE)) {
+ /* Service Inbound Doorbell interrupt */
+ intval = ioread32(priv->regs +
+ TSI721_SR_CHINT(IDB_QUEUE));
+ if (intval & TSI721_SR_CHINT_IDBQRCV)
+ tsi721_dbell_handler(mport);
+ else
+ dev_info(&priv->pdev->dev,
+ "Unsupported SR_CH_INT %x\n", intval);
+
+ /* Clear interrupts */
+ iowrite32(intval,
+ priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+ ioread32(priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+ }
+ }
+
+ if (dev_int & TSI721_DEV_INT_SMSG_CH) {
+ int ch;
+
+ /*
+ * Service channel interrupts from Messaging Engine
+ */
+
+ if (dev_ch_int & TSI721_INT_IMSG_CHAN_M) { /* Inbound Msg */
+ /* Disable signaled OB MSG Channel interrupts */
+ ch_inte = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+ ch_inte &= ~(dev_ch_int & TSI721_INT_IMSG_CHAN_M);
+ iowrite32(ch_inte, priv->regs + TSI721_DEV_CHAN_INTE);
+
+ /*
+ * Process Inbound Message interrupt for each MBOX
+ */
+ for (ch = 4; ch < RIO_MAX_MBOX + 4; ch++) {
+ if (!(dev_ch_int & TSI721_INT_IMSG_CHAN(ch)))
+ continue;
+ tsi721_imsg_handler(priv, ch);
+ }
+ }
+
+ if (dev_ch_int & TSI721_INT_OMSG_CHAN_M) { /* Outbound Msg */
+ /* Disable signaled OB MSG Channel interrupts */
+ ch_inte = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+ ch_inte &= ~(dev_ch_int & TSI721_INT_OMSG_CHAN_M);
+ iowrite32(ch_inte, priv->regs + TSI721_DEV_CHAN_INTE);
+
+ /*
+ * Process Outbound Message interrupts for each MBOX
+ */
+
+ for (ch = 0; ch < RIO_MAX_MBOX; ch++) {
+ if (!(dev_ch_int & TSI721_INT_OMSG_CHAN(ch)))
+ continue;
+ tsi721_omsg_handler(priv, ch);
+ }
+ }
+ }
+
+ if (dev_int & TSI721_DEV_INT_SRIO) {
+ /* Service SRIO MAC interrupts */
+ intval = ioread32(priv->regs + TSI721_RIO_EM_INT_STAT);
+ if (intval & TSI721_RIO_EM_INT_STAT_PW_RX)
+ tsi721_pw_handler(mport);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void tsi721_interrupts_init(struct tsi721_device *priv)
+{
+ u32 intr;
+
+ /* Enable IDB interrupts */
+ iowrite32(TSI721_SR_CHINT_ALL,
+ priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+ iowrite32(TSI721_SR_CHINT_IDBQRCV,
+ priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
+ iowrite32(TSI721_INT_SR2PC_CHAN(IDB_QUEUE),
+ priv->regs + TSI721_DEV_CHAN_INTE);
+
+ /* Enable SRIO MAC interrupts */
+ iowrite32(TSI721_RIO_EM_DEV_INT_EN_INT,
+ priv->regs + TSI721_RIO_EM_DEV_INT_EN);
+
+ if (priv->flags & TSI721_USING_MSIX)
+ intr = TSI721_DEV_INT_SRIO;
+ else
+ intr = TSI721_DEV_INT_SR2PC_CH | TSI721_DEV_INT_SRIO |
+ TSI721_DEV_INT_SMSG_CH;
+
+ iowrite32(intr, priv->regs + TSI721_DEV_INTE);
+ ioread32(priv->regs + TSI721_DEV_INTE);
+}
+
+#ifdef CONFIG_PCI_MSI
+/**
+ * tsi721_omsg_msix - MSI-X interrupt handler for outbound messaging
+ * @irq: Linux interrupt number
+ * @ptr: Pointer to interrupt-specific data (mport structure)
+ *
+ * Handles outbound messaging interrupts signaled using MSI-X.
+ */
+static irqreturn_t tsi721_omsg_msix(int irq, void *ptr)
+{
+ struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv;
+ int mbox;
+
+ mbox = (irq - priv->msix[TSI721_VECT_OMB0_DONE].vector) % RIO_MAX_MBOX;
+ tsi721_omsg_handler(priv, mbox);
+ return IRQ_HANDLED;
+}
+
+/**
+ * tsi721_imsg_msix - MSI-X interrupt handler for inbound messaging
+ * @irq: Linux interrupt number
+ * @ptr: Pointer to interrupt-specific data (mport structure)
+ *
+ * Handles inbound messaging interrupts signaled using MSI-X.
+ */
+static irqreturn_t tsi721_imsg_msix(int irq, void *ptr)
+{
+ struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv;
+ int mbox;
+
+ mbox = (irq - priv->msix[TSI721_VECT_IMB0_RCV].vector) % RIO_MAX_MBOX;
+ tsi721_imsg_handler(priv, mbox + 4);
+ return IRQ_HANDLED;
+}
+
+/**
+ * tsi721_srio_msix - Tsi721 MSI-X SRIO MAC interrupt handler
+ * @irq: Linux interrupt number
+ * @ptr: Pointer to interrupt-specific data (mport structure)
+ *
+ * Handles Tsi721 interrupts from SRIO MAC.
+ */
+static irqreturn_t tsi721_srio_msix(int irq, void *ptr)
+{
+ struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv;
+ u32 srio_int;
+
+ /* Service SRIO MAC interrupts */
+ srio_int = ioread32(priv->regs + TSI721_RIO_EM_INT_STAT);
+ if (srio_int & TSI721_RIO_EM_INT_STAT_PW_RX)
+ tsi721_pw_handler((struct rio_mport *)ptr);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * tsi721_sr2pc_ch_msix - Tsi721 MSI-X SR2PC Channel interrupt handler
+ * @irq: Linux interrupt number
+ * @ptr: Pointer to interrupt-specific data (mport structure)
+ *
+ * Handles Tsi721 interrupts from SR2PC Channel.
+ * NOTE: At this moment services only one SR2PC channel associated with inbound
+ * doorbells.
+ */
+static irqreturn_t tsi721_sr2pc_ch_msix(int irq, void *ptr)
+{
+ struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv;
+ u32 sr_ch_int;
+
+ /* Service Inbound DB interrupt from SR2PC channel */
+ sr_ch_int = ioread32(priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+ if (sr_ch_int & TSI721_SR_CHINT_IDBQRCV)
+ tsi721_dbell_handler((struct rio_mport *)ptr);
+
+ /* Clear interrupts */
+ iowrite32(sr_ch_int, priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+ /* Read back to ensure that interrupt was cleared */
+ sr_ch_int = ioread32(priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * tsi721_request_msix - register interrupt service for MSI-X mode.
+ * @mport: RapidIO master port structure
+ *
+ * Registers MSI-X interrupt service routines for interrupts that are active
+ * immediately after mport initialization. Messaging interrupt service routines
+ * should be registered during corresponding open requests.
+ */
+static int tsi721_request_msix(struct rio_mport *mport)
+{
+ struct tsi721_device *priv = mport->priv;
+ int err = 0;
+
+ err = request_irq(priv->msix[TSI721_VECT_IDB].vector,
+ tsi721_sr2pc_ch_msix, 0,
+ priv->msix[TSI721_VECT_IDB].irq_name, (void *)mport);
+ if (err)
+ goto out;
+
+ err = request_irq(priv->msix[TSI721_VECT_PWRX].vector,
+ tsi721_srio_msix, 0,
+ priv->msix[TSI721_VECT_PWRX].irq_name, (void *)mport);
+ if (err)
+ free_irq(
+ priv->msix[TSI721_VECT_IDB].vector,
+ (void *)mport);
+out:
+ return err;
+}
+
+/**
+ * tsi721_enable_msix - Attempts to enable MSI-X support for Tsi721.
+ * @priv: pointer to tsi721 private data
+ *
+ * Configures MSI-X support for Tsi721. Supports only an exact number
+ * of requested vectors.
+ */
+static int tsi721_enable_msix(struct tsi721_device *priv)
+{
+ struct msix_entry entries[TSI721_VECT_MAX];
+ int err;
+ int i;
+
+ entries[TSI721_VECT_IDB].entry = TSI721_MSIX_SR2PC_IDBQ_RCV(IDB_QUEUE);
+ entries[TSI721_VECT_PWRX].entry = TSI721_MSIX_SRIO_MAC_INT;
+
+ /*
+ * Initialize MSI-X entries for Messaging Engine:
+ * this driver supports four RIO mailboxes (inbound and outbound)
+ * NOTE: Inbound message MBOX 0...4 use IB channels 4...7. Therefore
+ * offset +4 is added to IB MBOX number.
+ */
+ for (i = 0; i < RIO_MAX_MBOX; i++) {
+ entries[TSI721_VECT_IMB0_RCV + i].entry =
+ TSI721_MSIX_IMSG_DQ_RCV(i + 4);
+ entries[TSI721_VECT_IMB0_INT + i].entry =
+ TSI721_MSIX_IMSG_INT(i + 4);
+ entries[TSI721_VECT_OMB0_DONE + i].entry =
+ TSI721_MSIX_OMSG_DONE(i);
+ entries[TSI721_VECT_OMB0_INT + i].entry =
+ TSI721_MSIX_OMSG_INT(i);
+ }
+
+ err = pci_enable_msix(priv->pdev, entries, ARRAY_SIZE(entries));
+ if (err) {
+ if (err > 0)
+ dev_info(&priv->pdev->dev,
+ "Only %d MSI-X vectors available, "
+ "not using MSI-X\n", err);
+ return err;
+ }
+
+ /*
+ * Copy MSI-X vector information into tsi721 private structure
+ */
+ priv->msix[TSI721_VECT_IDB].vector = entries[TSI721_VECT_IDB].vector;
+ snprintf(priv->msix[TSI721_VECT_IDB].irq_name, IRQ_DEVICE_NAME_MAX,
+ DRV_NAME "-idb@pci:%s", pci_name(priv->pdev));
+ priv->msix[TSI721_VECT_PWRX].vector = entries[TSI721_VECT_PWRX].vector;
+ snprintf(priv->msix[TSI721_VECT_PWRX].irq_name, IRQ_DEVICE_NAME_MAX,
+ DRV_NAME "-pwrx@pci:%s", pci_name(priv->pdev));
+
+ for (i = 0; i < RIO_MAX_MBOX; i++) {
+ priv->msix[TSI721_VECT_IMB0_RCV + i].vector =
+ entries[TSI721_VECT_IMB0_RCV + i].vector;
+ snprintf(priv->msix[TSI721_VECT_IMB0_RCV + i].irq_name,
+ IRQ_DEVICE_NAME_MAX, DRV_NAME "-imbr%d@pci:%s",
+ i, pci_name(priv->pdev));
+
+ priv->msix[TSI721_VECT_IMB0_INT + i].vector =
+ entries[TSI721_VECT_IMB0_INT + i].vector;
+ snprintf(priv->msix[TSI721_VECT_IMB0_INT + i].irq_name,
+ IRQ_DEVICE_NAME_MAX, DRV_NAME "-imbi%d@pci:%s",
+ i, pci_name(priv->pdev));
+
+ priv->msix[TSI721_VECT_OMB0_DONE + i].vector =
+ entries[TSI721_VECT_OMB0_DONE + i].vector;
+ snprintf(priv->msix[TSI721_VECT_OMB0_DONE + i].irq_name,
+ IRQ_DEVICE_NAME_MAX, DRV_NAME "-ombd%d@pci:%s",
+ i, pci_name(priv->pdev));
+
+ priv->msix[TSI721_VECT_OMB0_INT + i].vector =
+ entries[TSI721_VECT_OMB0_INT + i].vector;
+ snprintf(priv->msix[TSI721_VECT_OMB0_INT + i].irq_name,
+ IRQ_DEVICE_NAME_MAX, DRV_NAME "-ombi%d@pci:%s",
+ i, pci_name(priv->pdev));
+ }
+
+ return 0;
+}
+#endif /* CONFIG_PCI_MSI */
+
+static int tsi721_request_irq(struct rio_mport *mport)
+{
+ struct tsi721_device *priv = mport->priv;
+ int err;
+
+#ifdef CONFIG_PCI_MSI
+ if (priv->flags & TSI721_USING_MSIX)
+ err = tsi721_request_msix(mport);
+ else
+#endif
+ err = request_irq(priv->pdev->irq, tsi721_irqhandler,
+ (priv->flags & TSI721_USING_MSI) ? 0 : IRQF_SHARED,
+ DRV_NAME, (void *)mport);
+
+ if (err)
+ dev_err(&priv->pdev->dev,
+ "Unable to allocate interrupt, Error: %d\n", err);
+
+ return err;
+}
+
+/**
+ * tsi721_init_pc2sr_mapping - initializes outbound (PCIe->SRIO)
+ * translation regions.
+ * @priv: pointer to tsi721 private data
+ *
+ * Disables SREP translation regions.
+ */
+static void tsi721_init_pc2sr_mapping(struct tsi721_device *priv)
+{
+ int i;
+
+ /* Disable all PC2SR translation windows */
+ for (i = 0; i < TSI721_OBWIN_NUM; i++)
+ iowrite32(0, priv->regs + TSI721_OBWINLB(i));
+}
+
+/**
+ * tsi721_init_sr2pc_mapping - initializes inbound (SRIO->PCIe)
+ * translation regions.
+ * @priv: pointer to tsi721 private data
+ *
+ * Disables inbound windows.
+ */
+static void tsi721_init_sr2pc_mapping(struct tsi721_device *priv)
+{
+ int i;
+
+ /* Disable all SR2PC inbound windows */
+ for (i = 0; i < TSI721_IBWIN_NUM; i++)
+ iowrite32(0, priv->regs + TSI721_IBWINLB(i));
+}
+
+/**
+ * tsi721_port_write_init - Inbound port write interface init
+ * @priv: pointer to tsi721 private data
+ *
+ * Initializes inbound port write handler.
+ * Returns %0 on success or %-ENOMEM on failure.
+ */
+static int tsi721_port_write_init(struct tsi721_device *priv)
+{
+ priv->pw_discard_count = 0;
+ INIT_WORK(&priv->pw_work, tsi721_pw_dpc);
+ spin_lock_init(&priv->pw_fifo_lock);
+ if (kfifo_alloc(&priv->pw_fifo,
+ TSI721_RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) {
+ dev_err(&priv->pdev->dev, "PW FIFO allocation failed\n");
+ return -ENOMEM;
+ }
+
+ /* Use reliable port-write capture mode */
+ iowrite32(TSI721_RIO_PW_CTL_PWC_REL, priv->regs + TSI721_RIO_PW_CTL);
+ return 0;
+}
+
+static int tsi721_doorbell_init(struct tsi721_device *priv)
+{
+ /* Outbound Doorbells do not require any setup.
+ * Tsi721 uses dedicated PCI BAR1 to generate doorbells.
+ * That BAR1 was mapped during the probe routine.
+ */
+
+ /* Initialize Inbound Doorbell processing DPC and queue */
+ priv->db_discard_count = 0;
+ INIT_WORK(&priv->idb_work, tsi721_db_dpc);
+
+ /* Allocate buffer for inbound doorbells queue */
+ priv->idb_base = dma_alloc_coherent(&priv->pdev->dev,
+ IDB_QSIZE * TSI721_IDB_ENTRY_SIZE,
+ &priv->idb_dma, GFP_KERNEL);
+ if (!priv->idb_base)
+ return -ENOMEM;
+
+ memset(priv->idb_base, 0, IDB_QSIZE * TSI721_IDB_ENTRY_SIZE);
+
+ dev_dbg(&priv->pdev->dev, "Allocated IDB buffer @ %p (phys = %llx)\n",
+ priv->idb_base, (unsigned long long)priv->idb_dma);
+
+ iowrite32(TSI721_IDQ_SIZE_VAL(IDB_QSIZE),
+ priv->regs + TSI721_IDQ_SIZE(IDB_QUEUE));
+ iowrite32(((u64)priv->idb_dma >> 32),
+ priv->regs + TSI721_IDQ_BASEU(IDB_QUEUE));
+ iowrite32(((u64)priv->idb_dma & TSI721_IDQ_BASEL_ADDR),
+ priv->regs + TSI721_IDQ_BASEL(IDB_QUEUE));
+ /* Enable accepting all inbound doorbells */
+ iowrite32(0, priv->regs + TSI721_IDQ_MASK(IDB_QUEUE));
+
+ iowrite32(TSI721_IDQ_INIT, priv->regs + TSI721_IDQ_CTL(IDB_QUEUE));
+
+ iowrite32(0, priv->regs + TSI721_IDQ_RP(IDB_QUEUE));
+
+ return 0;
+}
+
+static void tsi721_doorbell_free(struct tsi721_device *priv)
+{
+ if (priv->idb_base == NULL)
+ return;
+
+ /* Free buffer allocated for inbound doorbell queue */
+ dma_free_coherent(&priv->pdev->dev, IDB_QSIZE * TSI721_IDB_ENTRY_SIZE,
+ priv->idb_base, priv->idb_dma);
+ priv->idb_base = NULL;
+}
+
+static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum)
+{
+ struct tsi721_dma_desc *bd_ptr;
+ u64 *sts_ptr;
+ dma_addr_t bd_phys, sts_phys;
+ int sts_size;
+ int bd_num = priv->bdma[chnum].bd_num;
+
+ dev_dbg(&priv->pdev->dev, "Init Block DMA Engine, CH%d\n", chnum);
+
+ /*
+ * Initialize DMA channel for maintenance requests
+ */
+
+ /* Allocate space for DMA descriptors */
+ bd_ptr = dma_alloc_coherent(&priv->pdev->dev,
+ bd_num * sizeof(struct tsi721_dma_desc),
+ &bd_phys, GFP_KERNEL);
+ if (!bd_ptr)
+ return -ENOMEM;
+
+ priv->bdma[chnum].bd_phys = bd_phys;
+ priv->bdma[chnum].bd_base = bd_ptr;
+
+ memset(bd_ptr, 0, bd_num * sizeof(struct tsi721_dma_desc));
+
+ dev_dbg(&priv->pdev->dev, "DMA descriptors @ %p (phys = %llx)\n",
+ bd_ptr, (unsigned long long)bd_phys);
+
+ /* Allocate space for descriptor status FIFO */
+ sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ?
+ bd_num : TSI721_DMA_MINSTSSZ;
+ sts_size = roundup_pow_of_two(sts_size);
+ sts_ptr = dma_alloc_coherent(&priv->pdev->dev,
+ sts_size * sizeof(struct tsi721_dma_sts),
+ &sts_phys, GFP_KERNEL);
+ if (!sts_ptr) {
+ /* Free space allocated for DMA descriptors */
+ dma_free_coherent(&priv->pdev->dev,
+ bd_num * sizeof(struct tsi721_dma_desc),
+ bd_ptr, bd_phys);
+ priv->bdma[chnum].bd_base = NULL;
+ return -ENOMEM;
+ }
+
+ priv->bdma[chnum].sts_phys = sts_phys;
+ priv->bdma[chnum].sts_base = sts_ptr;
+ priv->bdma[chnum].sts_size = sts_size;
+
+ memset(sts_ptr, 0, sts_size);
+
+ dev_dbg(&priv->pdev->dev,
+ "desc status FIFO @ %p (phys = %llx) size=0x%x\n",
+ sts_ptr, (unsigned long long)sts_phys, sts_size);
+
+ /* Initialize DMA descriptors ring */
+ bd_ptr[bd_num - 1].type_id = cpu_to_le32(DTYPE3 << 29);
+ bd_ptr[bd_num - 1].next_lo = cpu_to_le32((u64)bd_phys &
+ TSI721_DMAC_DPTRL_MASK);
+ bd_ptr[bd_num - 1].next_hi = cpu_to_le32((u64)bd_phys >> 32);
+
+ /* Setup DMA descriptor pointers */
+ iowrite32(((u64)bd_phys >> 32),
+ priv->regs + TSI721_DMAC_DPTRH(chnum));
+ iowrite32(((u64)bd_phys & TSI721_DMAC_DPTRL_MASK),
+ priv->regs + TSI721_DMAC_DPTRL(chnum));
+
+ /* Setup descriptor status FIFO */
+ iowrite32(((u64)sts_phys >> 32),
+ priv->regs + TSI721_DMAC_DSBH(chnum));
+ iowrite32(((u64)sts_phys & TSI721_DMAC_DSBL_MASK),
+ priv->regs + TSI721_DMAC_DSBL(chnum));
+ iowrite32(TSI721_DMAC_DSSZ_SIZE(sts_size),
+ priv->regs + TSI721_DMAC_DSSZ(chnum));
+
+ /* Clear interrupt bits */
+ iowrite32(TSI721_DMAC_INT_ALL,
+ priv->regs + TSI721_DMAC_INT(chnum));
+
+ ioread32(priv->regs + TSI721_DMAC_INT(chnum));
+
+ /* Toggle DMA channel initialization */
+ iowrite32(TSI721_DMAC_CTL_INIT, priv->regs + TSI721_DMAC_CTL(chnum));
+ ioread32(priv->regs + TSI721_DMAC_CTL(chnum));
+ udelay(10);
+
+ return 0;
+}
+
+static int tsi721_bdma_ch_free(struct tsi721_device *priv, int chnum)
+{
+ u32 ch_stat;
+
+ if (priv->bdma[chnum].bd_base == NULL)
+ return 0;
+
+ /* Check if DMA channel still running */
+ ch_stat = ioread32(priv->regs + TSI721_DMAC_STS(chnum));
+ if (ch_stat & TSI721_DMAC_STS_RUN)
+ return -EFAULT;
+
+ /* Put DMA channel into init state */
+ iowrite32(TSI721_DMAC_CTL_INIT,
+ priv->regs + TSI721_DMAC_CTL(chnum));
+
+ /* Free space allocated for DMA descriptors */
+ dma_free_coherent(&priv->pdev->dev,
+ priv->bdma[chnum].bd_num * sizeof(struct tsi721_dma_desc),
+ priv->bdma[chnum].bd_base, priv->bdma[chnum].bd_phys);
+ priv->bdma[chnum].bd_base = NULL;
+
+ /* Free space allocated for status FIFO */
+ dma_free_coherent(&priv->pdev->dev,
+ priv->bdma[chnum].sts_size * sizeof(struct tsi721_dma_sts),
+ priv->bdma[chnum].sts_base, priv->bdma[chnum].sts_phys);
+ priv->bdma[chnum].sts_base = NULL;
+ return 0;
+}
+
+static int tsi721_bdma_init(struct tsi721_device *priv)
+{
+ /* Initialize BDMA channel allocated for RapidIO maintenance read/write
+ * request generation
+ */
+ priv->bdma[TSI721_DMACH_MAINT].bd_num = 2;
+ if (tsi721_bdma_ch_init(priv, TSI721_DMACH_MAINT)) {
+ dev_err(&priv->pdev->dev, "Unable to initialize maintenance DMA"
+ " channel %d, aborting\n", TSI721_DMACH_MAINT);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void tsi721_bdma_free(struct tsi721_device *priv)
+{
+ tsi721_bdma_ch_free(priv, TSI721_DMACH_MAINT);
+}
+
+/* Enable Inbound Messaging Interrupts */
+static void
+tsi721_imsg_interrupt_enable(struct tsi721_device *priv, int ch,
+ u32 inte_mask)
+{
+ u32 rval;
+
+ if (!inte_mask)
+ return;
+
+ /* Clear pending Inbound Messaging interrupts */
+ iowrite32(inte_mask, priv->regs + TSI721_IBDMAC_INT(ch));
+
+ /* Enable Inbound Messaging interrupts */
+ rval = ioread32(priv->regs + TSI721_IBDMAC_INTE(ch));
+ iowrite32(rval | inte_mask, priv->regs + TSI721_IBDMAC_INTE(ch));
+
+ if (priv->flags & TSI721_USING_MSIX)
+ return; /* Finished if we are in MSI-X mode */
+
+ /*
+ * For MSI and INTA interrupt signalling we need to enable next levels
+ */
+
+ /* Enable Device Channel Interrupt */
+ rval = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+ iowrite32(rval | TSI721_INT_IMSG_CHAN(ch),
+ priv->regs + TSI721_DEV_CHAN_INTE);
+}
+
+/* Disable Inbound Messaging Interrupts */
+static void
+tsi721_imsg_interrupt_disable(struct tsi721_device *priv, int ch,
+ u32 inte_mask)
+{
+ u32 rval;
+
+ if (!inte_mask)
+ return;
+
+ /* Clear pending Inbound Messaging interrupts */
+ iowrite32(inte_mask, priv->regs + TSI721_IBDMAC_INT(ch));
+
+ /* Disable Inbound Messaging interrupts */
+ rval = ioread32(priv->regs + TSI721_IBDMAC_INTE(ch));
+ rval &= ~inte_mask;
+ iowrite32(rval, priv->regs + TSI721_IBDMAC_INTE(ch));
+
+ if (priv->flags & TSI721_USING_MSIX)
+ return; /* Finished if we are in MSI-X mode */
+
+ /*
+ * For MSI and INTA interrupt signalling we need to disable next levels
+ */
+
+ /* Disable Device Channel Interrupt */
+ rval = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+ rval &= ~TSI721_INT_IMSG_CHAN(ch);
+ iowrite32(rval, priv->regs + TSI721_DEV_CHAN_INTE);
+}
+
+/* Enable Outbound Messaging interrupts */
+static void
+tsi721_omsg_interrupt_enable(struct tsi721_device *priv, int ch,
+ u32 inte_mask)
+{
+ u32 rval;
+
+ if (!inte_mask)
+ return;
+
+ /* Clear pending Outbound Messaging interrupts */
+ iowrite32(inte_mask, priv->regs + TSI721_OBDMAC_INT(ch));
+
+ /* Enable Outbound Messaging channel interrupts */
+ rval = ioread32(priv->regs + TSI721_OBDMAC_INTE(ch));
+ iowrite32(rval | inte_mask, priv->regs + TSI721_OBDMAC_INTE(ch));
+
+ if (priv->flags & TSI721_USING_MSIX)
+ return; /* Finished if we are in MSI-X mode */
+
+ /*
+ * For MSI and INTA interrupt signalling we need to enable next levels
+ */
+
+ /* Enable Device Channel Interrupt */
+ rval = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+ iowrite32(rval | TSI721_INT_OMSG_CHAN(ch),
+ priv->regs + TSI721_DEV_CHAN_INTE);
+}
+
+/* Disable Outbound Messaging interrupts */
+static void
+tsi721_omsg_interrupt_disable(struct tsi721_device *priv, int ch,
+ u32 inte_mask)
+{
+ u32 rval;
+
+ if (!inte_mask)
+ return;
+
+ /* Clear pending Outbound Messaging interrupts */
+ iowrite32(inte_mask, priv->regs + TSI721_OBDMAC_INT(ch));
+
+ /* Disable Outbound Messaging interrupts */
+ rval = ioread32(priv->regs + TSI721_OBDMAC_INTE(ch));
+ rval &= ~inte_mask;
+ iowrite32(rval, priv->regs + TSI721_OBDMAC_INTE(ch));
+
+ if (priv->flags & TSI721_USING_MSIX)
+ return; /* Finished if we are in MSI-X mode */
+
+ /*
+ * For MSI and INTA interrupt signalling we need to disable next levels
+ */
+
+ /* Disable Device Channel Interrupt */
+ rval = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+ rval &= ~TSI721_INT_OMSG_CHAN(ch);
+ iowrite32(rval, priv->regs + TSI721_DEV_CHAN_INTE);
+}
+
+/**
+ * tsi721_add_outb_message - Add message to the Tsi721 outbound message queue
+ * @mport: Master port with outbound message queue
+ * @rdev: Target of outbound message
+ * @mbox: Outbound mailbox
+ * @buffer: Message to add to outbound queue
+ * @len: Length of message
+ */
+static int
+tsi721_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
+ void *buffer, size_t len)
+{
+ struct tsi721_device *priv = mport->priv;
+ struct tsi721_omsg_desc *desc;
+ u32 tx_slot;
+
+ if (!priv->omsg_init[mbox] ||
+ len > TSI721_MSG_MAX_SIZE || len < 8)
+ return -EINVAL;
+
+ tx_slot = priv->omsg_ring[mbox].tx_slot;
+
+ /* Copy copy message into transfer buffer */
+ memcpy(priv->omsg_ring[mbox].omq_base[tx_slot], buffer, len);
+
+ if (len & 0x7)
+ len += 8;
+
+ /* Build descriptor associated with buffer */
+ desc = priv->omsg_ring[mbox].omd_base;
+ desc[tx_slot].type_id = cpu_to_le32((DTYPE4 << 29) | rdev->destid);
+ if (tx_slot % 4 == 0)
+ desc[tx_slot].type_id |= cpu_to_le32(TSI721_OMD_IOF);
+
+ desc[tx_slot].msg_info =
+ cpu_to_le32((mport->sys_size << 26) | (mbox << 22) |
+ (0xe << 12) | (len & 0xff8));
+ desc[tx_slot].bufptr_lo =
+ cpu_to_le32((u64)priv->omsg_ring[mbox].omq_phys[tx_slot] &
+ 0xffffffff);
+ desc[tx_slot].bufptr_hi =
+ cpu_to_le32((u64)priv->omsg_ring[mbox].omq_phys[tx_slot] >> 32);
+
+ priv->omsg_ring[mbox].wr_count++;
+
+ /* Go to next descriptor */
+ if (++priv->omsg_ring[mbox].tx_slot == priv->omsg_ring[mbox].size) {
+ priv->omsg_ring[mbox].tx_slot = 0;
+ /* Move through the ring link descriptor at the end */
+ priv->omsg_ring[mbox].wr_count++;
+ }
+
+ mb();
+
+ /* Set new write count value */
+ iowrite32(priv->omsg_ring[mbox].wr_count,
+ priv->regs + TSI721_OBDMAC_DWRCNT(mbox));
+ ioread32(priv->regs + TSI721_OBDMAC_DWRCNT(mbox));
+
+ return 0;
+}
+
+/**
+ * tsi721_omsg_handler - Outbound Message Interrupt Handler
+ * @priv: pointer to tsi721 private data
+ * @ch: number of OB MSG channel to service
+ *
+ * Services channel interrupts from outbound messaging engine.
+ */
+static void tsi721_omsg_handler(struct tsi721_device *priv, int ch)
+{
+ u32 omsg_int;
+
+ spin_lock(&priv->omsg_ring[ch].lock);
+
+ omsg_int = ioread32(priv->regs + TSI721_OBDMAC_INT(ch));
+
+ if (omsg_int & TSI721_OBDMAC_INT_ST_FULL)
+ dev_info(&priv->pdev->dev,
+ "OB MBOX%d: Status FIFO is full\n", ch);
+
+ if (omsg_int & (TSI721_OBDMAC_INT_DONE | TSI721_OBDMAC_INT_IOF_DONE)) {
+ u32 srd_ptr;
+ u64 *sts_ptr, last_ptr = 0, prev_ptr = 0;
+ int i, j;
+ u32 tx_slot;
+
+ /*
+ * Find last successfully processed descriptor
+ */
+
+ /* Check and clear descriptor status FIFO entries */
+ srd_ptr = priv->omsg_ring[ch].sts_rdptr;
+ sts_ptr = priv->omsg_ring[ch].sts_base;
+ j = srd_ptr * 8;
+ while (sts_ptr[j]) {
+ for (i = 0; i < 8 && sts_ptr[j]; i++, j++) {
+ prev_ptr = last_ptr;
+ last_ptr = le64_to_cpu(sts_ptr[j]);
+ sts_ptr[j] = 0;
+ }
+
+ ++srd_ptr;
+ srd_ptr %= priv->omsg_ring[ch].sts_size;
+ j = srd_ptr * 8;
+ }
+
+ if (last_ptr == 0)
+ goto no_sts_update;
+
+ priv->omsg_ring[ch].sts_rdptr = srd_ptr;
+ iowrite32(srd_ptr, priv->regs + TSI721_OBDMAC_DSRP(ch));
+
+ if (!priv->mport->outb_msg[ch].mcback)
+ goto no_sts_update;
+
+ /* Inform upper layer about transfer completion */
+
+ tx_slot = (last_ptr - (u64)priv->omsg_ring[ch].omd_phys)/
+ sizeof(struct tsi721_omsg_desc);
+
+ /*
+ * Check if this is a Link Descriptor (LD).
+ * If yes, ignore LD and use descriptor processed
+ * before LD.
+ */
+ if (tx_slot == priv->omsg_ring[ch].size) {
+ if (prev_ptr)
+ tx_slot = (prev_ptr -
+ (u64)priv->omsg_ring[ch].omd_phys)/
+ sizeof(struct tsi721_omsg_desc);
+ else
+ goto no_sts_update;
+ }
+
+ /* Move slot index to the next message to be sent */
+ ++tx_slot;
+ if (tx_slot == priv->omsg_ring[ch].size)
+ tx_slot = 0;
+ BUG_ON(tx_slot >= priv->omsg_ring[ch].size);
+ priv->mport->outb_msg[ch].mcback(priv->mport,
+ priv->omsg_ring[ch].dev_id, ch,
+ tx_slot);
+ }
+
+no_sts_update:
+
+ if (omsg_int & TSI721_OBDMAC_INT_ERROR) {
+ /*
+ * Outbound message operation aborted due to error,
+ * reinitialize OB MSG channel
+ */
+
+ dev_dbg(&priv->pdev->dev, "OB MSG ABORT ch_stat=%x\n",
+ ioread32(priv->regs + TSI721_OBDMAC_STS(ch)));
+
+ iowrite32(TSI721_OBDMAC_INT_ERROR,
+ priv->regs + TSI721_OBDMAC_INT(ch));
+ iowrite32(TSI721_OBDMAC_CTL_INIT,
+ priv->regs + TSI721_OBDMAC_CTL(ch));
+ ioread32(priv->regs + TSI721_OBDMAC_CTL(ch));
+
+ /* Inform upper level to clear all pending tx slots */
+ if (priv->mport->outb_msg[ch].mcback)
+ priv->mport->outb_msg[ch].mcback(priv->mport,
+ priv->omsg_ring[ch].dev_id, ch,
+ priv->omsg_ring[ch].tx_slot);
+ /* Synch tx_slot tracking */
+ iowrite32(priv->omsg_ring[ch].tx_slot,
+ priv->regs + TSI721_OBDMAC_DRDCNT(ch));
+ ioread32(priv->regs + TSI721_OBDMAC_DRDCNT(ch));
+ priv->omsg_ring[ch].wr_count = priv->omsg_ring[ch].tx_slot;
+ priv->omsg_ring[ch].sts_rdptr = 0;
+ }
+
+ /* Clear channel interrupts */
+ iowrite32(omsg_int, priv->regs + TSI721_OBDMAC_INT(ch));
+
+ if (!(priv->flags & TSI721_USING_MSIX)) {
+ u32 ch_inte;
+
+ /* Re-enable channel interrupts */
+ ch_inte = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+ ch_inte |= TSI721_INT_OMSG_CHAN(ch);
+ iowrite32(ch_inte, priv->regs + TSI721_DEV_CHAN_INTE);
+ }
+
+ spin_unlock(&priv->omsg_ring[ch].lock);
+}
+
+/**
+ * tsi721_open_outb_mbox - Initialize Tsi721 outbound mailbox
+ * @mport: Master port implementing Outbound Messaging Engine
+ * @dev_id: Device specific pointer to pass on event
+ * @mbox: Mailbox to open
+ * @entries: Number of entries in the outbound mailbox ring
+ */
+static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id,
+ int mbox, int entries)
+{
+ struct tsi721_device *priv = mport->priv;
+ struct tsi721_omsg_desc *bd_ptr;
+ int i, rc = 0;
+
+ if ((entries < TSI721_OMSGD_MIN_RING_SIZE) ||
+ (entries > (TSI721_OMSGD_RING_SIZE)) ||
+ (!is_power_of_2(entries)) || mbox >= RIO_MAX_MBOX) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ priv->omsg_ring[mbox].dev_id = dev_id;
+ priv->omsg_ring[mbox].size = entries;
+ priv->omsg_ring[mbox].sts_rdptr = 0;
+ spin_lock_init(&priv->omsg_ring[mbox].lock);
+
+ /* Outbound Msg Buffer allocation based on
+ the number of maximum descriptor entries */
+ for (i = 0; i < entries; i++) {
+ priv->omsg_ring[mbox].omq_base[i] =
+ dma_alloc_coherent(
+ &priv->pdev->dev, TSI721_MSG_BUFFER_SIZE,
+ &priv->omsg_ring[mbox].omq_phys[i],
+ GFP_KERNEL);
+ if (priv->omsg_ring[mbox].omq_base[i] == NULL) {
+ dev_dbg(&priv->pdev->dev,
+ "Unable to allocate OB MSG data buffer for"
+ " MBOX%d\n", mbox);
+ rc = -ENOMEM;
+ goto out_buf;
+ }
+ }
+
+ /* Outbound message descriptor allocation */
+ priv->omsg_ring[mbox].omd_base = dma_alloc_coherent(
+ &priv->pdev->dev,
+ (entries + 1) * sizeof(struct tsi721_omsg_desc),
+ &priv->omsg_ring[mbox].omd_phys, GFP_KERNEL);
+ if (priv->omsg_ring[mbox].omd_base == NULL) {
+ dev_dbg(&priv->pdev->dev,
+ "Unable to allocate OB MSG descriptor memory "
+ "for MBOX%d\n", mbox);
+ rc = -ENOMEM;
+ goto out_buf;
+ }
+
+ priv->omsg_ring[mbox].tx_slot = 0;
+
+ /* Outbound message descriptor status FIFO allocation */
+ priv->omsg_ring[mbox].sts_size = roundup_pow_of_two(entries + 1);
+ priv->omsg_ring[mbox].sts_base = dma_alloc_coherent(&priv->pdev->dev,
+ priv->omsg_ring[mbox].sts_size *
+ sizeof(struct tsi721_dma_sts),
+ &priv->omsg_ring[mbox].sts_phys, GFP_KERNEL);
+ if (priv->omsg_ring[mbox].sts_base == NULL) {
+ dev_dbg(&priv->pdev->dev,
+ "Unable to allocate OB MSG descriptor status FIFO "
+ "for MBOX%d\n", mbox);
+ rc = -ENOMEM;
+ goto out_desc;
+ }
+
+ memset(priv->omsg_ring[mbox].sts_base, 0,
+ entries * sizeof(struct tsi721_dma_sts));
+
+ /*
+ * Configure Outbound Messaging Engine
+ */
+
+ /* Setup Outbound Message descriptor pointer */
+ iowrite32(((u64)priv->omsg_ring[mbox].omd_phys >> 32),
+ priv->regs + TSI721_OBDMAC_DPTRH(mbox));
+ iowrite32(((u64)priv->omsg_ring[mbox].omd_phys &
+ TSI721_OBDMAC_DPTRL_MASK),
+ priv->regs + TSI721_OBDMAC_DPTRL(mbox));
+
+ /* Setup Outbound Message descriptor status FIFO */
+ iowrite32(((u64)priv->omsg_ring[mbox].sts_phys >> 32),
+ priv->regs + TSI721_OBDMAC_DSBH(mbox));
+ iowrite32(((u64)priv->omsg_ring[mbox].sts_phys &
+ TSI721_OBDMAC_DSBL_MASK),
+ priv->regs + TSI721_OBDMAC_DSBL(mbox));
+ iowrite32(TSI721_DMAC_DSSZ_SIZE(priv->omsg_ring[mbox].sts_size),
+ priv->regs + (u32)TSI721_OBDMAC_DSSZ(mbox));
+
+ /* Enable interrupts */
+
+#ifdef CONFIG_PCI_MSI
+ if (priv->flags & TSI721_USING_MSIX) {
+ /* Request interrupt service if we are in MSI-X mode */
+ rc = request_irq(
+ priv->msix[TSI721_VECT_OMB0_DONE + mbox].vector,
+ tsi721_omsg_msix, 0,
+ priv->msix[TSI721_VECT_OMB0_DONE + mbox].irq_name,
+ (void *)mport);
+
+ if (rc) {
+ dev_dbg(&priv->pdev->dev,
+ "Unable to allocate MSI-X interrupt for "
+ "OBOX%d-DONE\n", mbox);
+ goto out_stat;
+ }
+
+ rc = request_irq(priv->msix[TSI721_VECT_OMB0_INT + mbox].vector,
+ tsi721_omsg_msix, 0,
+ priv->msix[TSI721_VECT_OMB0_INT + mbox].irq_name,
+ (void *)mport);
+
+ if (rc) {
+ dev_dbg(&priv->pdev->dev,
+ "Unable to allocate MSI-X interrupt for "
+ "MBOX%d-INT\n", mbox);
+ free_irq(
+ priv->msix[TSI721_VECT_OMB0_DONE + mbox].vector,
+ (void *)mport);
+ goto out_stat;
+ }
+ }
+#endif /* CONFIG_PCI_MSI */
+
+ tsi721_omsg_interrupt_enable(priv, mbox, TSI721_OBDMAC_INT_ALL);
+
+ /* Initialize Outbound Message descriptors ring */
+ bd_ptr = priv->omsg_ring[mbox].omd_base;
+ bd_ptr[entries].type_id = cpu_to_le32(DTYPE5 << 29);
+ bd_ptr[entries].msg_info = 0;
+ bd_ptr[entries].next_lo =
+ cpu_to_le32((u64)priv->omsg_ring[mbox].omd_phys &
+ TSI721_OBDMAC_DPTRL_MASK);
+ bd_ptr[entries].next_hi =
+ cpu_to_le32((u64)priv->omsg_ring[mbox].omd_phys >> 32);
+ priv->omsg_ring[mbox].wr_count = 0;
+ mb();
+
+ /* Initialize Outbound Message engine */
+ iowrite32(TSI721_OBDMAC_CTL_INIT, priv->regs + TSI721_OBDMAC_CTL(mbox));
+ ioread32(priv->regs + TSI721_OBDMAC_DWRCNT(mbox));
+ udelay(10);
+
+ priv->omsg_init[mbox] = 1;
+
+ return 0;
+
+#ifdef CONFIG_PCI_MSI
+out_stat:
+ dma_free_coherent(&priv->pdev->dev,
+ priv->omsg_ring[mbox].sts_size * sizeof(struct tsi721_dma_sts),
+ priv->omsg_ring[mbox].sts_base,
+ priv->omsg_ring[mbox].sts_phys);
+
+ priv->omsg_ring[mbox].sts_base = NULL;
+#endif /* CONFIG_PCI_MSI */
+
+out_desc:
+ dma_free_coherent(&priv->pdev->dev,
+ (entries + 1) * sizeof(struct tsi721_omsg_desc),
+ priv->omsg_ring[mbox].omd_base,
+ priv->omsg_ring[mbox].omd_phys);
+
+ priv->omsg_ring[mbox].omd_base = NULL;
+
+out_buf:
+ for (i = 0; i < priv->omsg_ring[mbox].size; i++) {
+ if (priv->omsg_ring[mbox].omq_base[i]) {
+ dma_free_coherent(&priv->pdev->dev,
+ TSI721_MSG_BUFFER_SIZE,
+ priv->omsg_ring[mbox].omq_base[i],
+ priv->omsg_ring[mbox].omq_phys[i]);
+
+ priv->omsg_ring[mbox].omq_base[i] = NULL;
+ }
+ }
+
+out:
+ return rc;
+}
+
+/**
+ * tsi721_close_outb_mbox - Close Tsi721 outbound mailbox
+ * @mport: Master port implementing the outbound message unit
+ * @mbox: Mailbox to close
+ */
+static void tsi721_close_outb_mbox(struct rio_mport *mport, int mbox)
+{
+ struct tsi721_device *priv = mport->priv;
+ u32 i;
+
+ if (!priv->omsg_init[mbox])
+ return;
+ priv->omsg_init[mbox] = 0;
+
+ /* Disable Interrupts */
+
+ tsi721_omsg_interrupt_disable(priv, mbox, TSI721_OBDMAC_INT_ALL);
+
+#ifdef CONFIG_PCI_MSI
+ if (priv->flags & TSI721_USING_MSIX) {
+ free_irq(priv->msix[TSI721_VECT_OMB0_DONE + mbox].vector,
+ (void *)mport);
+ free_irq(priv->msix[TSI721_VECT_OMB0_INT + mbox].vector,
+ (void *)mport);
+ }
+#endif /* CONFIG_PCI_MSI */
+
+ /* Free OMSG Descriptor Status FIFO */
+ dma_free_coherent(&priv->pdev->dev,
+ priv->omsg_ring[mbox].sts_size * sizeof(struct tsi721_dma_sts),
+ priv->omsg_ring[mbox].sts_base,
+ priv->omsg_ring[mbox].sts_phys);
+
+ priv->omsg_ring[mbox].sts_base = NULL;
+
+ /* Free OMSG descriptors */
+ dma_free_coherent(&priv->pdev->dev,
+ (priv->omsg_ring[mbox].size + 1) *
+ sizeof(struct tsi721_omsg_desc),
+ priv->omsg_ring[mbox].omd_base,
+ priv->omsg_ring[mbox].omd_phys);
+
+ priv->omsg_ring[mbox].omd_base = NULL;
+
+ /* Free message buffers */
+ for (i = 0; i < priv->omsg_ring[mbox].size; i++) {
+ if (priv->omsg_ring[mbox].omq_base[i]) {
+ dma_free_coherent(&priv->pdev->dev,
+ TSI721_MSG_BUFFER_SIZE,
+ priv->omsg_ring[mbox].omq_base[i],
+ priv->omsg_ring[mbox].omq_phys[i]);
+
+ priv->omsg_ring[mbox].omq_base[i] = NULL;
+ }
+ }
+}
+
+/**
+ * tsi721_imsg_handler - Inbound Message Interrupt Handler
+ * @priv: pointer to tsi721 private data
+ * @ch: inbound message channel number to service
+ *
+ * Services channel interrupts from inbound messaging engine.
+ */
+static void tsi721_imsg_handler(struct tsi721_device *priv, int ch)
+{
+ u32 mbox = ch - 4;
+ u32 imsg_int;
+
+ spin_lock(&priv->imsg_ring[mbox].lock);
+
+ imsg_int = ioread32(priv->regs + TSI721_IBDMAC_INT(ch));
+
+ if (imsg_int & TSI721_IBDMAC_INT_SRTO)
+ dev_info(&priv->pdev->dev, "IB MBOX%d SRIO timeout\n",
+ mbox);
+
+ if (imsg_int & TSI721_IBDMAC_INT_PC_ERROR)
+ dev_info(&priv->pdev->dev, "IB MBOX%d PCIe error\n",
+ mbox);
+
+ if (imsg_int & TSI721_IBDMAC_INT_FQ_LOW)
+ dev_info(&priv->pdev->dev,
+ "IB MBOX%d IB free queue low\n", mbox);
+
+ /* Clear IB channel interrupts */
+ iowrite32(imsg_int, priv->regs + TSI721_IBDMAC_INT(ch));
+
+ /* If an IB Msg is received notify the upper layer */
+ if (imsg_int & TSI721_IBDMAC_INT_DQ_RCV &&
+ priv->mport->inb_msg[mbox].mcback)
+ priv->mport->inb_msg[mbox].mcback(priv->mport,
+ priv->imsg_ring[mbox].dev_id, mbox, -1);
+
+ if (!(priv->flags & TSI721_USING_MSIX)) {
+ u32 ch_inte;
+
+ /* Re-enable channel interrupts */
+ ch_inte = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+ ch_inte |= TSI721_INT_IMSG_CHAN(ch);
+ iowrite32(ch_inte, priv->regs + TSI721_DEV_CHAN_INTE);
+ }
+
+ spin_unlock(&priv->imsg_ring[mbox].lock);
+}
+
+/**
+ * tsi721_open_inb_mbox - Initialize Tsi721 inbound mailbox
+ * @mport: Master port implementing the Inbound Messaging Engine
+ * @dev_id: Device specific pointer to pass on event
+ * @mbox: Mailbox to open
+ * @entries: Number of entries in the inbound mailbox ring
+ */
+static int tsi721_open_inb_mbox(struct rio_mport *mport, void *dev_id,
+ int mbox, int entries)
+{
+ struct tsi721_device *priv = mport->priv;
+ int ch = mbox + 4;
+ int i;
+ u64 *free_ptr;
+ int rc = 0;
+
+ if ((entries < TSI721_IMSGD_MIN_RING_SIZE) ||
+ (entries > TSI721_IMSGD_RING_SIZE) ||
+ (!is_power_of_2(entries)) || mbox >= RIO_MAX_MBOX) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Initialize IB Messaging Ring */
+ priv->imsg_ring[mbox].dev_id = dev_id;
+ priv->imsg_ring[mbox].size = entries;
+ priv->imsg_ring[mbox].rx_slot = 0;
+ priv->imsg_ring[mbox].desc_rdptr = 0;
+ priv->imsg_ring[mbox].fq_wrptr = 0;
+ for (i = 0; i < priv->imsg_ring[mbox].size; i++)
+ priv->imsg_ring[mbox].imq_base[i] = NULL;
+ spin_lock_init(&priv->imsg_ring[mbox].lock);
+
+ /* Allocate buffers for incoming messages */
+ priv->imsg_ring[mbox].buf_base =
+ dma_alloc_coherent(&priv->pdev->dev,
+ entries * TSI721_MSG_BUFFER_SIZE,
+ &priv->imsg_ring[mbox].buf_phys,
+ GFP_KERNEL);
+
+ if (priv->imsg_ring[mbox].buf_base == NULL) {
+ dev_err(&priv->pdev->dev,
+ "Failed to allocate buffers for IB MBOX%d\n", mbox);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Allocate memory for circular free list */
+ priv->imsg_ring[mbox].imfq_base =
+ dma_alloc_coherent(&priv->pdev->dev,
+ entries * 8,
+ &priv->imsg_ring[mbox].imfq_phys,
+ GFP_KERNEL);
+
+ if (priv->imsg_ring[mbox].imfq_base == NULL) {
+ dev_err(&priv->pdev->dev,
+ "Failed to allocate free queue for IB MBOX%d\n", mbox);
+ rc = -ENOMEM;
+ goto out_buf;
+ }
+
+ /* Allocate memory for Inbound message descriptors */
+ priv->imsg_ring[mbox].imd_base =
+ dma_alloc_coherent(&priv->pdev->dev,
+ entries * sizeof(struct tsi721_imsg_desc),
+ &priv->imsg_ring[mbox].imd_phys, GFP_KERNEL);
+
+ if (priv->imsg_ring[mbox].imd_base == NULL) {
+ dev_err(&priv->pdev->dev,
+ "Failed to allocate descriptor memory for IB MBOX%d\n",
+ mbox);
+ rc = -ENOMEM;
+ goto out_dma;
+ }
+
+ /* Fill free buffer pointer list */
+ free_ptr = priv->imsg_ring[mbox].imfq_base;
+ for (i = 0; i < entries; i++)
+ free_ptr[i] = cpu_to_le64(
+ (u64)(priv->imsg_ring[mbox].buf_phys) +
+ i * 0x1000);
+
+ mb();
+
+ /*
+ * For mapping of inbound SRIO Messages into appropriate queues we need
+ * to set Inbound Device ID register in the messaging engine. We do it
+ * once when first inbound mailbox is requested.
+ */
+ if (!(priv->flags & TSI721_IMSGID_SET)) {
+ iowrite32((u32)priv->mport->host_deviceid,
+ priv->regs + TSI721_IB_DEVID);
+ priv->flags |= TSI721_IMSGID_SET;
+ }
+
+ /*
+ * Configure Inbound Messaging channel (ch = mbox + 4)
+ */
+
+ /* Setup Inbound Message free queue */
+ iowrite32(((u64)priv->imsg_ring[mbox].imfq_phys >> 32),
+ priv->regs + TSI721_IBDMAC_FQBH(ch));
+ iowrite32(((u64)priv->imsg_ring[mbox].imfq_phys &
+ TSI721_IBDMAC_FQBL_MASK),
+ priv->regs+TSI721_IBDMAC_FQBL(ch));
+ iowrite32(TSI721_DMAC_DSSZ_SIZE(entries),
+ priv->regs + TSI721_IBDMAC_FQSZ(ch));
+
+ /* Setup Inbound Message descriptor queue */
+ iowrite32(((u64)priv->imsg_ring[mbox].imd_phys >> 32),
+ priv->regs + TSI721_IBDMAC_DQBH(ch));
+ iowrite32(((u32)priv->imsg_ring[mbox].imd_phys &
+ (u32)TSI721_IBDMAC_DQBL_MASK),
+ priv->regs+TSI721_IBDMAC_DQBL(ch));
+ iowrite32(TSI721_DMAC_DSSZ_SIZE(entries),
+ priv->regs + TSI721_IBDMAC_DQSZ(ch));
+
+ /* Enable interrupts */
+
+#ifdef CONFIG_PCI_MSI
+ if (priv->flags & TSI721_USING_MSIX) {
+ /* Request interrupt service if we are in MSI-X mode */
+ rc = request_irq(priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector,
+ tsi721_imsg_msix, 0,
+ priv->msix[TSI721_VECT_IMB0_RCV + mbox].irq_name,
+ (void *)mport);
+
+ if (rc) {
+ dev_dbg(&priv->pdev->dev,
+ "Unable to allocate MSI-X interrupt for "
+ "IBOX%d-DONE\n", mbox);
+ goto out_desc;
+ }
+
+ rc = request_irq(priv->msix[TSI721_VECT_IMB0_INT + mbox].vector,
+ tsi721_imsg_msix, 0,
+ priv->msix[TSI721_VECT_IMB0_INT + mbox].irq_name,
+ (void *)mport);
+
+ if (rc) {
+ dev_dbg(&priv->pdev->dev,
+ "Unable to allocate MSI-X interrupt for "
+ "IBOX%d-INT\n", mbox);
+ free_irq(
+ priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector,
+ (void *)mport);
+ goto out_desc;
+ }
+ }
+#endif /* CONFIG_PCI_MSI */
+
+ tsi721_imsg_interrupt_enable(priv, ch, TSI721_IBDMAC_INT_ALL);
+
+ /* Initialize Inbound Message Engine */
+ iowrite32(TSI721_IBDMAC_CTL_INIT, priv->regs + TSI721_IBDMAC_CTL(ch));
+ ioread32(priv->regs + TSI721_IBDMAC_CTL(ch));
+ udelay(10);
+ priv->imsg_ring[mbox].fq_wrptr = entries - 1;
+ iowrite32(entries - 1, priv->regs + TSI721_IBDMAC_FQWP(ch));
+
+ priv->imsg_init[mbox] = 1;
+ return 0;
+
+#ifdef CONFIG_PCI_MSI
+out_desc:
+ dma_free_coherent(&priv->pdev->dev,
+ priv->imsg_ring[mbox].size * sizeof(struct tsi721_imsg_desc),
+ priv->imsg_ring[mbox].imd_base,
+ priv->imsg_ring[mbox].imd_phys);
+
+ priv->imsg_ring[mbox].imd_base = NULL;
+#endif /* CONFIG_PCI_MSI */
+
+out_dma:
+ dma_free_coherent(&priv->pdev->dev,
+ priv->imsg_ring[mbox].size * 8,
+ priv->imsg_ring[mbox].imfq_base,
+ priv->imsg_ring[mbox].imfq_phys);
+
+ priv->imsg_ring[mbox].imfq_base = NULL;
+
+out_buf:
+ dma_free_coherent(&priv->pdev->dev,
+ priv->imsg_ring[mbox].size * TSI721_MSG_BUFFER_SIZE,
+ priv->imsg_ring[mbox].buf_base,
+ priv->imsg_ring[mbox].buf_phys);
+
+ priv->imsg_ring[mbox].buf_base = NULL;
+
+out:
+ return rc;
+}
+
+/**
+ * tsi721_close_inb_mbox - Shut down Tsi721 inbound mailbox
+ * @mport: Master port implementing the Inbound Messaging Engine
+ * @mbox: Mailbox to close
+ */
+static void tsi721_close_inb_mbox(struct rio_mport *mport, int mbox)
+{
+ struct tsi721_device *priv = mport->priv;
+ u32 rx_slot;
+ int ch = mbox + 4;
+
+ if (!priv->imsg_init[mbox]) /* mbox isn't initialized yet */
+ return;
+ priv->imsg_init[mbox] = 0;
+
+ /* Disable Inbound Messaging Engine */
+
+ /* Disable Interrupts */
+ tsi721_imsg_interrupt_disable(priv, ch, TSI721_OBDMAC_INT_MASK);
+
+#ifdef CONFIG_PCI_MSI
+ if (priv->flags & TSI721_USING_MSIX) {
+ free_irq(priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector,
+ (void *)mport);
+ free_irq(priv->msix[TSI721_VECT_IMB0_INT + mbox].vector,
+ (void *)mport);
+ }
+#endif /* CONFIG_PCI_MSI */
+
+ /* Clear Inbound Buffer Queue */
+ for (rx_slot = 0; rx_slot < priv->imsg_ring[mbox].size; rx_slot++)
+ priv->imsg_ring[mbox].imq_base[rx_slot] = NULL;
+
+ /* Free memory allocated for message buffers */
+ dma_free_coherent(&priv->pdev->dev,
+ priv->imsg_ring[mbox].size * TSI721_MSG_BUFFER_SIZE,
+ priv->imsg_ring[mbox].buf_base,
+ priv->imsg_ring[mbox].buf_phys);
+
+ priv->imsg_ring[mbox].buf_base = NULL;
+
+ /* Free memory allocated for free pointr list */
+ dma_free_coherent(&priv->pdev->dev,
+ priv->imsg_ring[mbox].size * 8,
+ priv->imsg_ring[mbox].imfq_base,
+ priv->imsg_ring[mbox].imfq_phys);
+
+ priv->imsg_ring[mbox].imfq_base = NULL;
+
+ /* Free memory allocated for RX descriptors */
+ dma_free_coherent(&priv->pdev->dev,
+ priv->imsg_ring[mbox].size * sizeof(struct tsi721_imsg_desc),
+ priv->imsg_ring[mbox].imd_base,
+ priv->imsg_ring[mbox].imd_phys);
+
+ priv->imsg_ring[mbox].imd_base = NULL;
+}
+
+/**
+ * tsi721_add_inb_buffer - Add buffer to the Tsi721 inbound message queue
+ * @mport: Master port implementing the Inbound Messaging Engine
+ * @mbox: Inbound mailbox number
+ * @buf: Buffer to add to inbound queue
+ */
+static int tsi721_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
+{
+ struct tsi721_device *priv = mport->priv;
+ u32 rx_slot;
+ int rc = 0;
+
+ rx_slot = priv->imsg_ring[mbox].rx_slot;
+ if (priv->imsg_ring[mbox].imq_base[rx_slot]) {
+ dev_err(&priv->pdev->dev,
+ "Error adding inbound buffer %d, buffer exists\n",
+ rx_slot);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ priv->imsg_ring[mbox].imq_base[rx_slot] = buf;
+
+ if (++priv->imsg_ring[mbox].rx_slot == priv->imsg_ring[mbox].size)
+ priv->imsg_ring[mbox].rx_slot = 0;
+
+out:
+ return rc;
+}
+
+/**
+ * tsi721_get_inb_message - Fetch inbound message from the Tsi721 MSG Queue
+ * @mport: Master port implementing the Inbound Messaging Engine
+ * @mbox: Inbound mailbox number
+ *
+ * Returns pointer to the message on success or NULL on failure.
+ */
+static void *tsi721_get_inb_message(struct rio_mport *mport, int mbox)
+{
+ struct tsi721_device *priv = mport->priv;
+ struct tsi721_imsg_desc *desc;
+ u32 rx_slot;
+ void *rx_virt = NULL;
+ u64 rx_phys;
+ void *buf = NULL;
+ u64 *free_ptr;
+ int ch = mbox + 4;
+ int msg_size;
+
+ if (!priv->imsg_init[mbox])
+ return NULL;
+
+ desc = priv->imsg_ring[mbox].imd_base;
+ desc += priv->imsg_ring[mbox].desc_rdptr;
+
+ if (!(le32_to_cpu(desc->msg_info) & TSI721_IMD_HO))
+ goto out;
+
+ rx_slot = priv->imsg_ring[mbox].rx_slot;
+ while (priv->imsg_ring[mbox].imq_base[rx_slot] == NULL) {
+ if (++rx_slot == priv->imsg_ring[mbox].size)
+ rx_slot = 0;
+ }
+
+ rx_phys = ((u64)le32_to_cpu(desc->bufptr_hi) << 32) |
+ le32_to_cpu(desc->bufptr_lo);
+
+ rx_virt = priv->imsg_ring[mbox].buf_base +
+ (rx_phys - (u64)priv->imsg_ring[mbox].buf_phys);
+
+ buf = priv->imsg_ring[mbox].imq_base[rx_slot];
+ msg_size = le32_to_cpu(desc->msg_info) & TSI721_IMD_BCOUNT;
+ if (msg_size == 0)
+ msg_size = RIO_MAX_MSG_SIZE;
+
+ memcpy(buf, rx_virt, msg_size);
+ priv->imsg_ring[mbox].imq_base[rx_slot] = NULL;
+
+ desc->msg_info &= cpu_to_le32(~TSI721_IMD_HO);
+ if (++priv->imsg_ring[mbox].desc_rdptr == priv->imsg_ring[mbox].size)
+ priv->imsg_ring[mbox].desc_rdptr = 0;
+
+ iowrite32(priv->imsg_ring[mbox].desc_rdptr,
+ priv->regs + TSI721_IBDMAC_DQRP(ch));
+
+ /* Return free buffer into the pointer list */
+ free_ptr = priv->imsg_ring[mbox].imfq_base;
+ free_ptr[priv->imsg_ring[mbox].fq_wrptr] = cpu_to_le64(rx_phys);
+
+ if (++priv->imsg_ring[mbox].fq_wrptr == priv->imsg_ring[mbox].size)
+ priv->imsg_ring[mbox].fq_wrptr = 0;
+
+ iowrite32(priv->imsg_ring[mbox].fq_wrptr,
+ priv->regs + TSI721_IBDMAC_FQWP(ch));
+out:
+ return buf;
+}
+
+/**
+ * tsi721_messages_init - Initialization of Messaging Engine
+ * @priv: pointer to tsi721 private data
+ *
+ * Configures Tsi721 messaging engine.
+ */
+static int tsi721_messages_init(struct tsi721_device *priv)
+{
+ int ch;
+
+ iowrite32(0, priv->regs + TSI721_SMSG_ECC_LOG);
+ iowrite32(0, priv->regs + TSI721_RETRY_GEN_CNT);
+ iowrite32(0, priv->regs + TSI721_RETRY_RX_CNT);
+
+ /* Set SRIO Message Request/Response Timeout */
+ iowrite32(TSI721_RQRPTO_VAL, priv->regs + TSI721_RQRPTO);
+
+ /* Initialize Inbound Messaging Engine Registers */
+ for (ch = 0; ch < TSI721_IMSG_CHNUM; ch++) {
+ /* Clear interrupt bits */
+ iowrite32(TSI721_IBDMAC_INT_MASK,
+ priv->regs + TSI721_IBDMAC_INT(ch));
+ /* Clear Status */
+ iowrite32(0, priv->regs + TSI721_IBDMAC_STS(ch));
+
+ iowrite32(TSI721_SMSG_ECC_COR_LOG_MASK,
+ priv->regs + TSI721_SMSG_ECC_COR_LOG(ch));
+ iowrite32(TSI721_SMSG_ECC_NCOR_MASK,
+ priv->regs + TSI721_SMSG_ECC_NCOR(ch));
+ }
+
+ return 0;
+}
+
+/**
+ * tsi721_disable_ints - disables all device interrupts
+ * @priv: pointer to tsi721 private data
+ */
+static void tsi721_disable_ints(struct tsi721_device *priv)
+{
+ int ch;
+
+ /* Disable all device level interrupts */
+ iowrite32(0, priv->regs + TSI721_DEV_INTE);
+
+ /* Disable all Device Channel interrupts */
+ iowrite32(0, priv->regs + TSI721_DEV_CHAN_INTE);
+
+ /* Disable all Inbound Msg Channel interrupts */
+ for (ch = 0; ch < TSI721_IMSG_CHNUM; ch++)
+ iowrite32(0, priv->regs + TSI721_IBDMAC_INTE(ch));
+
+ /* Disable all Outbound Msg Channel interrupts */
+ for (ch = 0; ch < TSI721_OMSG_CHNUM; ch++)
+ iowrite32(0, priv->regs + TSI721_OBDMAC_INTE(ch));
+
+ /* Disable all general messaging interrupts */
+ iowrite32(0, priv->regs + TSI721_SMSG_INTE);
+
+ /* Disable all BDMA Channel interrupts */
+ for (ch = 0; ch < TSI721_DMA_MAXCH; ch++)
+ iowrite32(0, priv->regs + TSI721_DMAC_INTE(ch));
+
+ /* Disable all general BDMA interrupts */
+ iowrite32(0, priv->regs + TSI721_BDMA_INTE);
+
+ /* Disable all SRIO Channel interrupts */
+ for (ch = 0; ch < TSI721_SRIO_MAXCH; ch++)
+ iowrite32(0, priv->regs + TSI721_SR_CHINTE(ch));
+
+ /* Disable all general SR2PC interrupts */
+ iowrite32(0, priv->regs + TSI721_SR2PC_GEN_INTE);
+
+ /* Disable all PC2SR interrupts */
+ iowrite32(0, priv->regs + TSI721_PC2SR_INTE);
+
+ /* Disable all I2C interrupts */
+ iowrite32(0, priv->regs + TSI721_I2C_INT_ENABLE);
+
+ /* Disable SRIO MAC interrupts */
+ iowrite32(0, priv->regs + TSI721_RIO_EM_INT_ENABLE);
+ iowrite32(0, priv->regs + TSI721_RIO_EM_DEV_INT_EN);
+}
+
+/**
+ * tsi721_setup_mport - Setup Tsi721 as RapidIO subsystem master port
+ * @priv: pointer to tsi721 private data
+ *
+ * Configures Tsi721 as RapidIO master port.
+ */
+static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
+{
+ struct pci_dev *pdev = priv->pdev;
+ int err = 0;
+ struct rio_ops *ops;
+
+ struct rio_mport *mport;
+
+ ops = kzalloc(sizeof(struct rio_ops), GFP_KERNEL);
+ if (!ops) {
+ dev_dbg(&pdev->dev, "Unable to allocate memory for rio_ops\n");
+ return -ENOMEM;
+ }
+
+ ops->lcread = tsi721_lcread;
+ ops->lcwrite = tsi721_lcwrite;
+ ops->cread = tsi721_cread_dma;
+ ops->cwrite = tsi721_cwrite_dma;
+ ops->dsend = tsi721_dsend;
+ ops->open_inb_mbox = tsi721_open_inb_mbox;
+ ops->close_inb_mbox = tsi721_close_inb_mbox;
+ ops->open_outb_mbox = tsi721_open_outb_mbox;
+ ops->close_outb_mbox = tsi721_close_outb_mbox;
+ ops->add_outb_message = tsi721_add_outb_message;
+ ops->add_inb_buffer = tsi721_add_inb_buffer;
+ ops->get_inb_message = tsi721_get_inb_message;
+
+ mport = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
+ if (!mport) {
+ kfree(ops);
+ dev_dbg(&pdev->dev, "Unable to allocate memory for mport\n");
+ return -ENOMEM;
+ }
+
+ mport->ops = ops;
+ mport->index = 0;
+ mport->sys_size = 0; /* small system */
+ mport->phy_type = RIO_PHY_SERIAL;
+ mport->priv = (void *)priv;
+ mport->phys_efptr = 0x100;
+
+ INIT_LIST_HEAD(&mport->dbells);
+
+ rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
+ rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
+ rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
+ strcpy(mport->name, "Tsi721 mport");
+
+ /* Hook up interrupt handler */
+
+#ifdef CONFIG_PCI_MSI
+ if (!tsi721_enable_msix(priv))
+ priv->flags |= TSI721_USING_MSIX;
+ else if (!pci_enable_msi(pdev))
+ priv->flags |= TSI721_USING_MSI;
+ else
+ dev_info(&pdev->dev,
+ "MSI/MSI-X is not available. Using legacy INTx.\n");
+#endif /* CONFIG_PCI_MSI */
+
+ err = tsi721_request_irq(mport);
+
+ if (!err) {
+ tsi721_interrupts_init(priv);
+ ops->pwenable = tsi721_pw_enable;
+ } else
+ dev_err(&pdev->dev, "Unable to get assigned PCI IRQ "
+ "vector %02X err=0x%x\n", pdev->irq, err);
+
+ /* Enable SRIO link */
+ iowrite32(ioread32(priv->regs + TSI721_DEVCTL) |
+ TSI721_DEVCTL_SRBOOT_CMPL,
+ priv->regs + TSI721_DEVCTL);
+
+ rio_register_mport(mport);
+ priv->mport = mport;
+
+ if (mport->host_deviceid >= 0)
+ iowrite32(RIO_PORT_GEN_HOST | RIO_PORT_GEN_MASTER |
+ RIO_PORT_GEN_DISCOVERED,
+ priv->regs + (0x100 + RIO_PORT_GEN_CTL_CSR));
+ else
+ iowrite32(0, priv->regs + (0x100 + RIO_PORT_GEN_CTL_CSR));
+
+ return 0;
+}
+
+static int __devinit tsi721_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct tsi721_device *priv;
+ int i;
+ int err;
+ u32 regval;
+
+ priv = kzalloc(sizeof(struct tsi721_device), GFP_KERNEL);
+ if (priv == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate memory for device\n");
+ err = -ENOMEM;
+ goto err_exit;
+ }
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to enable PCI device\n");
+ goto err_clean;
+ }
+
+ priv->pdev = pdev;
+
+#ifdef DEBUG
+ for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {
+ dev_dbg(&pdev->dev, "res[%d] @ 0x%llx (0x%lx, 0x%lx)\n",
+ i, (unsigned long long)pci_resource_start(pdev, i),
+ (unsigned long)pci_resource_len(pdev, i),
+ pci_resource_flags(pdev, i));
+ }
+#endif
+ /*
+ * Verify BAR configuration
+ */
+
+ /* BAR_0 (registers) must be 512KB+ in 32-bit address space */
+ if (!(pci_resource_flags(pdev, BAR_0) & IORESOURCE_MEM) ||
+ pci_resource_flags(pdev, BAR_0) & IORESOURCE_MEM_64 ||
+ pci_resource_len(pdev, BAR_0) < TSI721_REG_SPACE_SIZE) {
+ dev_err(&pdev->dev,
+ "Missing or misconfigured CSR BAR0, aborting.\n");
+ err = -ENODEV;
+ goto err_disable_pdev;
+ }
+
+ /* BAR_1 (outbound doorbells) must be 16MB+ in 32-bit address space */
+ if (!(pci_resource_flags(pdev, BAR_1) & IORESOURCE_MEM) ||
+ pci_resource_flags(pdev, BAR_1) & IORESOURCE_MEM_64 ||
+ pci_resource_len(pdev, BAR_1) < TSI721_DB_WIN_SIZE) {
+ dev_err(&pdev->dev,
+ "Missing or misconfigured Doorbell BAR1, aborting.\n");
+ err = -ENODEV;
+ goto err_disable_pdev;
+ }
+
+ /*
+ * BAR_2 and BAR_4 (outbound translation) must be in 64-bit PCIe address
+ * space.
+ * NOTE: BAR_2 and BAR_4 are not used by this version of driver.
+ * It may be a good idea to keep them disabled using HW configuration
+ * to save PCI memory space.
+ */
+ if ((pci_resource_flags(pdev, BAR_2) & IORESOURCE_MEM) &&
+ (pci_resource_flags(pdev, BAR_2) & IORESOURCE_MEM_64)) {
+ dev_info(&pdev->dev, "Outbound BAR2 is not used but enabled.\n");
+ }
+
+ if ((pci_resource_flags(pdev, BAR_4) & IORESOURCE_MEM) &&
+ (pci_resource_flags(pdev, BAR_4) & IORESOURCE_MEM_64)) {
+ dev_info(&pdev->dev, "Outbound BAR4 is not used but enabled.\n");
+ }
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ dev_err(&pdev->dev, "Cannot obtain PCI resources, "
+ "aborting.\n");
+ goto err_disable_pdev;
+ }
+
+ pci_set_master(pdev);
+
+ priv->regs = pci_ioremap_bar(pdev, BAR_0);
+ if (!priv->regs) {
+ dev_err(&pdev->dev,
+ "Unable to map device registers space, aborting\n");
+ err = -ENOMEM;
+ goto err_free_res;
+ }
+
+ priv->odb_base = pci_ioremap_bar(pdev, BAR_1);
+ if (!priv->odb_base) {
+ dev_err(&pdev->dev,
+ "Unable to map outbound doorbells space, aborting\n");
+ err = -ENOMEM;
+ goto err_unmap_bars;
+ }
+
+ /* Configure DMA attributes. */
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+ dev_info(&pdev->dev, "Unable to set DMA mask\n");
+ goto err_unmap_bars;
+ }
+
+ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
+ dev_info(&pdev->dev, "Unable to set consistent DMA mask\n");
+ } else {
+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+ if (err)
+ dev_info(&pdev->dev, "Unable to set consistent DMA mask\n");
+ }
+
+ /* Clear "no snoop" and "relaxed ordering" bits. */
+ pci_read_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, &regval);
+ regval &= ~(PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN);
+ pci_write_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, regval);
+
+ /*
+ * FIXUP: correct offsets of MSI-X tables in the MSI-X Capability Block
+ */
+ pci_write_config_dword(pdev, TSI721_PCIECFG_EPCTL, 0x01);
+ pci_write_config_dword(pdev, TSI721_PCIECFG_MSIXTBL,
+ TSI721_MSIXTBL_OFFSET);
+ pci_write_config_dword(pdev, TSI721_PCIECFG_MSIXPBA,
+ TSI721_MSIXPBA_OFFSET);
+ pci_write_config_dword(pdev, TSI721_PCIECFG_EPCTL, 0);
+ /* End of FIXUP */
+
+ tsi721_disable_ints(priv);
+
+ tsi721_init_pc2sr_mapping(priv);
+ tsi721_init_sr2pc_mapping(priv);
+
+ if (tsi721_bdma_init(priv)) {
+ dev_err(&pdev->dev, "BDMA initialization failed, aborting\n");
+ err = -ENOMEM;
+ goto err_unmap_bars;
+ }
+
+ err = tsi721_doorbell_init(priv);
+ if (err)
+ goto err_free_bdma;
+
+ tsi721_port_write_init(priv);
+
+ err = tsi721_messages_init(priv);
+ if (err)
+ goto err_free_consistent;
+
+ err = tsi721_setup_mport(priv);
+ if (err)
+ goto err_free_consistent;
+
+ return 0;
+
+err_free_consistent:
+ tsi721_doorbell_free(priv);
+err_free_bdma:
+ tsi721_bdma_free(priv);
+err_unmap_bars:
+ if (priv->regs)
+ iounmap(priv->regs);
+ if (priv->odb_base)
+ iounmap(priv->odb_base);
+err_free_res:
+ pci_release_regions(pdev);
+ pci_clear_master(pdev);
+err_disable_pdev:
+ pci_disable_device(pdev);
+err_clean:
+ kfree(priv);
+err_exit:
+ return err;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(tsi721_pci_tbl) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_TSI721) },
+ { 0, } /* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, tsi721_pci_tbl);
+
+static struct pci_driver tsi721_driver = {
+ .name = "tsi721",
+ .id_table = tsi721_pci_tbl,
+ .probe = tsi721_probe,
+};
+
+static int __init tsi721_init(void)
+{
+ return pci_register_driver(&tsi721_driver);
+}
+
+static void __exit tsi721_exit(void)
+{
+ pci_unregister_driver(&tsi721_driver);
+}
+
+device_initcall(tsi721_init);
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h
new file mode 100644
index 000000000000..58be4deb1402
--- /dev/null
+++ b/drivers/rapidio/devices/tsi721.h
@@ -0,0 +1,766 @@
+/*
+ * Tsi721 PCIExpress-to-SRIO bridge definitions
+ *
+ * Copyright 2011, Integrated Device Technology, 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.
+ */
+
+#ifndef __TSI721_H
+#define __TSI721_H
+
+#define DRV_NAME "tsi721"
+
+#define DEFAULT_HOPCOUNT 0xff
+#define DEFAULT_DESTID 0xff
+
+/* PCI device ID */
+#define PCI_DEVICE_ID_TSI721 0x80ab
+
+#define BAR_0 0
+#define BAR_1 1
+#define BAR_2 2
+#define BAR_4 4
+
+#define TSI721_PC2SR_BARS 2
+#define TSI721_PC2SR_WINS 8
+#define TSI721_PC2SR_ZONES 8
+#define TSI721_MAINT_WIN 0 /* Window for outbound maintenance requests */
+#define IDB_QUEUE 0 /* Inbound Doorbell Queue to use */
+#define IDB_QSIZE 512 /* Inbound Doorbell Queue size */
+
+/* Memory space sizes */
+#define TSI721_REG_SPACE_SIZE (512 * 1024) /* 512K */
+#define TSI721_DB_WIN_SIZE (16 * 1024 * 1024) /* 16MB */
+
+#define RIO_TT_CODE_8 0x00000000
+#define RIO_TT_CODE_16 0x00000001
+
+#define TSI721_DMA_MAXCH 8
+#define TSI721_DMA_MINSTSSZ 32
+#define TSI721_DMA_STSBLKSZ 8
+
+#define TSI721_SRIO_MAXCH 8
+
+#define DBELL_SID(buf) (((u8)buf[2] << 8) | (u8)buf[3])
+#define DBELL_TID(buf) (((u8)buf[4] << 8) | (u8)buf[5])
+#define DBELL_INF(buf) (((u8)buf[0] << 8) | (u8)buf[1])
+
+#define TSI721_RIO_PW_MSG_SIZE 16 /* Tsi721 saves only 16 bytes of PW msg */
+
+/* Register definitions */
+
+/*
+ * Registers in PCIe configuration space
+ */
+
+#define TSI721_PCIECFG_MSIXTBL 0x0a4
+#define TSI721_MSIXTBL_OFFSET 0x2c000
+#define TSI721_PCIECFG_MSIXPBA 0x0a8
+#define TSI721_MSIXPBA_OFFSET 0x2a000
+#define TSI721_PCIECFG_EPCTL 0x400
+
+/*
+ * Event Management Registers
+ */
+
+#define TSI721_RIO_EM_INT_STAT 0x10910
+#define TSI721_RIO_EM_INT_STAT_PW_RX 0x00010000
+
+#define TSI721_RIO_EM_INT_ENABLE 0x10914
+#define TSI721_RIO_EM_INT_ENABLE_PW_RX 0x00010000
+
+#define TSI721_RIO_EM_DEV_INT_EN 0x10930
+#define TSI721_RIO_EM_DEV_INT_EN_INT 0x00000001
+
+/*
+ * Port-Write Block Registers
+ */
+
+#define TSI721_RIO_PW_CTL 0x10a04
+#define TSI721_RIO_PW_CTL_PW_TIMER 0xf0000000
+#define TSI721_RIO_PW_CTL_PWT_DIS (0 << 28)
+#define TSI721_RIO_PW_CTL_PWT_103 (1 << 28)
+#define TSI721_RIO_PW_CTL_PWT_205 (1 << 29)
+#define TSI721_RIO_PW_CTL_PWT_410 (1 << 30)
+#define TSI721_RIO_PW_CTL_PWT_820 (1 << 31)
+#define TSI721_RIO_PW_CTL_PWC_MODE 0x01000000
+#define TSI721_RIO_PW_CTL_PWC_CONT 0x00000000
+#define TSI721_RIO_PW_CTL_PWC_REL 0x01000000
+
+#define TSI721_RIO_PW_RX_STAT 0x10a10
+#define TSI721_RIO_PW_RX_STAT_WR_SIZE 0x0000f000
+#define TSI_RIO_PW_RX_STAT_WDPTR 0x00000100
+#define TSI721_RIO_PW_RX_STAT_PW_SHORT 0x00000008
+#define TSI721_RIO_PW_RX_STAT_PW_TRUNC 0x00000004
+#define TSI721_RIO_PW_RX_STAT_PW_DISC 0x00000002
+#define TSI721_RIO_PW_RX_STAT_PW_VAL 0x00000001
+
+#define TSI721_RIO_PW_RX_CAPT(x) (0x10a20 + (x)*4)
+
+/*
+ * Inbound Doorbells
+ */
+
+#define TSI721_IDB_ENTRY_SIZE 64
+
+#define TSI721_IDQ_CTL(x) (0x20000 + (x) * 1000)
+#define TSI721_IDQ_SUSPEND 0x00000002
+#define TSI721_IDQ_INIT 0x00000001
+
+#define TSI721_IDQ_STS(x) (0x20004 + (x) * 1000)
+#define TSI721_IDQ_RUN 0x00200000
+
+#define TSI721_IDQ_MASK(x) (0x20008 + (x) * 1000)
+#define TSI721_IDQ_MASK_MASK 0xffff0000
+#define TSI721_IDQ_MASK_PATT 0x0000ffff
+
+#define TSI721_IDQ_RP(x) (0x2000c + (x) * 1000)
+#define TSI721_IDQ_RP_PTR 0x0007ffff
+
+#define TSI721_IDQ_WP(x) (0x20010 + (x) * 1000)
+#define TSI721_IDQ_WP_PTR 0x0007ffff
+
+#define TSI721_IDQ_BASEL(x) (0x20014 + (x) * 1000)
+#define TSI721_IDQ_BASEL_ADDR 0xffffffc0
+#define TSI721_IDQ_BASEU(x) (0x20018 + (x) * 1000)
+#define TSI721_IDQ_SIZE(x) (0x2001c + (x) * 1000)
+#define TSI721_IDQ_SIZE_VAL(size) (__fls(size) - 4)
+#define TSI721_IDQ_SIZE_MIN 512
+#define TSI721_IDQ_SIZE_MAX (512 * 1024)
+
+#define TSI721_SR_CHINT(x) (0x20040 + (x) * 1000)
+#define TSI721_SR_CHINTE(x) (0x20044 + (x) * 1000)
+#define TSI721_SR_CHINTSET(x) (0x20048 + (x) * 1000)
+#define TSI721_SR_CHINT_ODBOK 0x00000020
+#define TSI721_SR_CHINT_IDBQRCV 0x00000010
+#define TSI721_SR_CHINT_SUSP 0x00000008
+#define TSI721_SR_CHINT_ODBTO 0x00000004
+#define TSI721_SR_CHINT_ODBRTRY 0x00000002
+#define TSI721_SR_CHINT_ODBERR 0x00000001
+#define TSI721_SR_CHINT_ALL 0x0000003f
+
+#define TSI721_IBWIN_NUM 8
+
+#define TSI721_IBWINLB(x) (0x29000 + (x) * 20)
+#define TSI721_IBWINLB_BA 0xfffff000
+#define TSI721_IBWINLB_WEN 0x00000001
+
+#define TSI721_SR2PC_GEN_INTE 0x29800
+#define TSI721_SR2PC_PWE 0x29804
+#define TSI721_SR2PC_GEN_INT 0x29808
+
+#define TSI721_DEV_INTE 0x29840
+#define TSI721_DEV_INT 0x29844
+#define TSI721_DEV_INTSET 0x29848
+#define TSI721_DEV_INT_SMSG_CH 0x00000800
+#define TSI721_DEV_INT_SMSG_NCH 0x00000400
+#define TSI721_DEV_INT_SR2PC_CH 0x00000200
+#define TSI721_DEV_INT_SRIO 0x00000020
+
+#define TSI721_DEV_CHAN_INTE 0x2984c
+#define TSI721_DEV_CHAN_INT 0x29850
+
+#define TSI721_INT_SR2PC_CHAN_M 0xff000000
+#define TSI721_INT_SR2PC_CHAN(x) (1 << (24 + (x)))
+#define TSI721_INT_IMSG_CHAN_M 0x00ff0000
+#define TSI721_INT_IMSG_CHAN(x) (1 << (16 + (x)))
+#define TSI721_INT_OMSG_CHAN_M 0x0000ff00
+#define TSI721_INT_OMSG_CHAN(x) (1 << (8 + (x)))
+
+/*
+ * PC2SR block registers
+ */
+#define TSI721_OBWIN_NUM TSI721_PC2SR_WINS
+
+#define TSI721_OBWINLB(x) (0x40000 + (x) * 20)
+#define TSI721_OBWINLB_BA 0xffff8000
+#define TSI721_OBWINLB_WEN 0x00000001
+
+#define TSI721_OBWINUB(x) (0x40004 + (x) * 20)
+
+#define TSI721_OBWINSZ(x) (0x40008 + (x) * 20)
+#define TSI721_OBWINSZ_SIZE 0x00001f00
+#define TSI721_OBWIN_SIZE(size) (__fls(size) - 15)
+
+#define TSI721_ZONE_SEL 0x41300
+#define TSI721_ZONE_SEL_RD_WRB 0x00020000
+#define TSI721_ZONE_SEL_GO 0x00010000
+#define TSI721_ZONE_SEL_WIN 0x00000038
+#define TSI721_ZONE_SEL_ZONE 0x00000007
+
+#define TSI721_LUT_DATA0 0x41304
+#define TSI721_LUT_DATA0_ADD 0xfffff000
+#define TSI721_LUT_DATA0_RDTYPE 0x00000f00
+#define TSI721_LUT_DATA0_NREAD 0x00000100
+#define TSI721_LUT_DATA0_MNTRD 0x00000200
+#define TSI721_LUT_DATA0_RDCRF 0x00000020
+#define TSI721_LUT_DATA0_WRCRF 0x00000010
+#define TSI721_LUT_DATA0_WRTYPE 0x0000000f
+#define TSI721_LUT_DATA0_NWR 0x00000001
+#define TSI721_LUT_DATA0_MNTWR 0x00000002
+#define TSI721_LUT_DATA0_NWR_R 0x00000004
+
+#define TSI721_LUT_DATA1 0x41308
+
+#define TSI721_LUT_DATA2 0x4130c
+#define TSI721_LUT_DATA2_HC 0xff000000
+#define TSI721_LUT_DATA2_ADD65 0x000c0000
+#define TSI721_LUT_DATA2_TT 0x00030000
+#define TSI721_LUT_DATA2_DSTID 0x0000ffff
+
+#define TSI721_PC2SR_INTE 0x41310
+
+#define TSI721_DEVCTL 0x48004
+#define TSI721_DEVCTL_SRBOOT_CMPL 0x00000004
+
+#define TSI721_I2C_INT_ENABLE 0x49120
+
+/*
+ * Block DMA Engine Registers
+ * x = 0..7
+ */
+
+#define TSI721_DMAC_DWRCNT(x) (0x51000 + (x) * 0x1000)
+#define TSI721_DMAC_DRDCNT(x) (0x51004 + (x) * 0x1000)
+
+#define TSI721_DMAC_CTL(x) (0x51008 + (x) * 0x1000)
+#define TSI721_DMAC_CTL_SUSP 0x00000002
+#define TSI721_DMAC_CTL_INIT 0x00000001
+
+#define TSI721_DMAC_INT(x) (0x5100c + (x) * 0x1000)
+#define TSI721_DMAC_INT_STFULL 0x00000010
+#define TSI721_DMAC_INT_DONE 0x00000008
+#define TSI721_DMAC_INT_SUSP 0x00000004
+#define TSI721_DMAC_INT_ERR 0x00000002
+#define TSI721_DMAC_INT_IOFDONE 0x00000001
+#define TSI721_DMAC_INT_ALL 0x0000001f
+
+#define TSI721_DMAC_INTSET(x) (0x51010 + (x) * 0x1000)
+
+#define TSI721_DMAC_STS(x) (0x51014 + (x) * 0x1000)
+#define TSI721_DMAC_STS_ABORT 0x00400000
+#define TSI721_DMAC_STS_RUN 0x00200000
+#define TSI721_DMAC_STS_CS 0x001f0000
+
+#define TSI721_DMAC_INTE(x) (0x51018 + (x) * 0x1000)
+
+#define TSI721_DMAC_DPTRL(x) (0x51024 + (x) * 0x1000)
+#define TSI721_DMAC_DPTRL_MASK 0xffffffe0
+
+#define TSI721_DMAC_DPTRH(x) (0x51028 + (x) * 0x1000)
+
+#define TSI721_DMAC_DSBL(x) (0x5102c + (x) * 0x1000)
+#define TSI721_DMAC_DSBL_MASK 0xffffffc0
+
+#define TSI721_DMAC_DSBH(x) (0x51030 + (x) * 0x1000)
+
+#define TSI721_DMAC_DSSZ(x) (0x51034 + (x) * 0x1000)
+#define TSI721_DMAC_DSSZ_SIZE_M 0x0000000f
+#define TSI721_DMAC_DSSZ_SIZE(size) (__fls(size) - 4)
+
+
+#define TSI721_DMAC_DSRP(x) (0x51038 + (x) * 0x1000)
+#define TSI721_DMAC_DSRP_MASK 0x0007ffff
+
+#define TSI721_DMAC_DSWP(x) (0x5103c + (x) * 0x1000)
+#define TSI721_DMAC_DSWP_MASK 0x0007ffff
+
+#define TSI721_BDMA_INTE 0x5f000
+
+/*
+ * Messaging definitions
+ */
+#define TSI721_MSG_BUFFER_SIZE RIO_MAX_MSG_SIZE
+#define TSI721_MSG_MAX_SIZE RIO_MAX_MSG_SIZE
+#define TSI721_IMSG_MAXCH 8
+#define TSI721_IMSG_CHNUM TSI721_IMSG_MAXCH
+#define TSI721_IMSGD_MIN_RING_SIZE 32
+#define TSI721_IMSGD_RING_SIZE 512
+
+#define TSI721_OMSG_CHNUM 4 /* One channel per MBOX */
+#define TSI721_OMSGD_MIN_RING_SIZE 32
+#define TSI721_OMSGD_RING_SIZE 512
+
+/*
+ * Outbound Messaging Engine Registers
+ * x = 0..7
+ */
+
+#define TSI721_OBDMAC_DWRCNT(x) (0x61000 + (x) * 0x1000)
+
+#define TSI721_OBDMAC_DRDCNT(x) (0x61004 + (x) * 0x1000)
+
+#define TSI721_OBDMAC_CTL(x) (0x61008 + (x) * 0x1000)
+#define TSI721_OBDMAC_CTL_MASK 0x00000007
+#define TSI721_OBDMAC_CTL_RETRY_THR 0x00000004
+#define TSI721_OBDMAC_CTL_SUSPEND 0x00000002
+#define TSI721_OBDMAC_CTL_INIT 0x00000001
+
+#define TSI721_OBDMAC_INT(x) (0x6100c + (x) * 0x1000)
+#define TSI721_OBDMAC_INTSET(x) (0x61010 + (x) * 0x1000)
+#define TSI721_OBDMAC_INTE(x) (0x61018 + (x) * 0x1000)
+#define TSI721_OBDMAC_INT_MASK 0x0000001F
+#define TSI721_OBDMAC_INT_ST_FULL 0x00000010
+#define TSI721_OBDMAC_INT_DONE 0x00000008
+#define TSI721_OBDMAC_INT_SUSPENDED 0x00000004
+#define TSI721_OBDMAC_INT_ERROR 0x00000002
+#define TSI721_OBDMAC_INT_IOF_DONE 0x00000001
+#define TSI721_OBDMAC_INT_ALL TSI721_OBDMAC_INT_MASK
+
+#define TSI721_OBDMAC_STS(x) (0x61014 + (x) * 0x1000)
+#define TSI721_OBDMAC_STS_MASK 0x007f0000
+#define TSI721_OBDMAC_STS_ABORT 0x00400000
+#define TSI721_OBDMAC_STS_RUN 0x00200000
+#define TSI721_OBDMAC_STS_CS 0x001f0000
+
+#define TSI721_OBDMAC_PWE(x) (0x6101c + (x) * 0x1000)
+#define TSI721_OBDMAC_PWE_MASK 0x00000002
+#define TSI721_OBDMAC_PWE_ERROR_EN 0x00000002
+
+#define TSI721_OBDMAC_DPTRL(x) (0x61020 + (x) * 0x1000)
+#define TSI721_OBDMAC_DPTRL_MASK 0xfffffff0
+
+#define TSI721_OBDMAC_DPTRH(x) (0x61024 + (x) * 0x1000)
+#define TSI721_OBDMAC_DPTRH_MASK 0xffffffff
+
+#define TSI721_OBDMAC_DSBL(x) (0x61040 + (x) * 0x1000)
+#define TSI721_OBDMAC_DSBL_MASK 0xffffffc0
+
+#define TSI721_OBDMAC_DSBH(x) (0x61044 + (x) * 0x1000)
+#define TSI721_OBDMAC_DSBH_MASK 0xffffffff
+
+#define TSI721_OBDMAC_DSSZ(x) (0x61048 + (x) * 0x1000)
+#define TSI721_OBDMAC_DSSZ_MASK 0x0000000f
+
+#define TSI721_OBDMAC_DSRP(x) (0x6104c + (x) * 0x1000)
+#define TSI721_OBDMAC_DSRP_MASK 0x0007ffff
+
+#define TSI721_OBDMAC_DSWP(x) (0x61050 + (x) * 0x1000)
+#define TSI721_OBDMAC_DSWP_MASK 0x0007ffff
+
+#define TSI721_RQRPTO 0x60010
+#define TSI721_RQRPTO_MASK 0x00ffffff
+#define TSI721_RQRPTO_VAL 400 /* Response TO value */
+
+/*
+ * Inbound Messaging Engine Registers
+ * x = 0..7
+ */
+
+#define TSI721_IB_DEVID_GLOBAL 0xffff
+#define TSI721_IBDMAC_FQBL(x) (0x61200 + (x) * 0x1000)
+#define TSI721_IBDMAC_FQBL_MASK 0xffffffc0
+
+#define TSI721_IBDMAC_FQBH(x) (0x61204 + (x) * 0x1000)
+#define TSI721_IBDMAC_FQBH_MASK 0xffffffff
+
+#define TSI721_IBDMAC_FQSZ_ENTRY_INX TSI721_IMSGD_RING_SIZE
+#define TSI721_IBDMAC_FQSZ(x) (0x61208 + (x) * 0x1000)
+#define TSI721_IBDMAC_FQSZ_MASK 0x0000000f
+
+#define TSI721_IBDMAC_FQRP(x) (0x6120c + (x) * 0x1000)
+#define TSI721_IBDMAC_FQRP_MASK 0x0007ffff
+
+#define TSI721_IBDMAC_FQWP(x) (0x61210 + (x) * 0x1000)
+#define TSI721_IBDMAC_FQWP_MASK 0x0007ffff
+
+#define TSI721_IBDMAC_FQTH(x) (0x61214 + (x) * 0x1000)
+#define TSI721_IBDMAC_FQTH_MASK 0x0007ffff
+
+#define TSI721_IB_DEVID 0x60020
+#define TSI721_IB_DEVID_MASK 0x0000ffff
+
+#define TSI721_IBDMAC_CTL(x) (0x61240 + (x) * 0x1000)
+#define TSI721_IBDMAC_CTL_MASK 0x00000003
+#define TSI721_IBDMAC_CTL_SUSPEND 0x00000002
+#define TSI721_IBDMAC_CTL_INIT 0x00000001
+
+#define TSI721_IBDMAC_STS(x) (0x61244 + (x) * 0x1000)
+#define TSI721_IBDMAC_STS_MASK 0x007f0000
+#define TSI721_IBSMAC_STS_ABORT 0x00400000
+#define TSI721_IBSMAC_STS_RUN 0x00200000
+#define TSI721_IBSMAC_STS_CS 0x001f0000
+
+#define TSI721_IBDMAC_INT(x) (0x61248 + (x) * 0x1000)
+#define TSI721_IBDMAC_INTSET(x) (0x6124c + (x) * 0x1000)
+#define TSI721_IBDMAC_INTE(x) (0x61250 + (x) * 0x1000)
+#define TSI721_IBDMAC_INT_MASK 0x0000100f
+#define TSI721_IBDMAC_INT_SRTO 0x00001000
+#define TSI721_IBDMAC_INT_SUSPENDED 0x00000008
+#define TSI721_IBDMAC_INT_PC_ERROR 0x00000004
+#define TSI721_IBDMAC_INT_FQ_LOW 0x00000002
+#define TSI721_IBDMAC_INT_DQ_RCV 0x00000001
+#define TSI721_IBDMAC_INT_ALL TSI721_IBDMAC_INT_MASK
+
+#define TSI721_IBDMAC_PWE(x) (0x61254 + (x) * 0x1000)
+#define TSI721_IBDMAC_PWE_MASK 0x00001700
+#define TSI721_IBDMAC_PWE_SRTO 0x00001000
+#define TSI721_IBDMAC_PWE_ILL_FMT 0x00000400
+#define TSI721_IBDMAC_PWE_ILL_DEC 0x00000200
+#define TSI721_IBDMAC_PWE_IMP_SP 0x00000100
+
+#define TSI721_IBDMAC_DQBL(x) (0x61300 + (x) * 0x1000)
+#define TSI721_IBDMAC_DQBL_MASK 0xffffffc0
+#define TSI721_IBDMAC_DQBL_ADDR 0xffffffc0
+
+#define TSI721_IBDMAC_DQBH(x) (0x61304 + (x) * 0x1000)
+#define TSI721_IBDMAC_DQBH_MASK 0xffffffff
+
+#define TSI721_IBDMAC_DQRP(x) (0x61308 + (x) * 0x1000)
+#define TSI721_IBDMAC_DQRP_MASK 0x0007ffff
+
+#define TSI721_IBDMAC_DQWR(x) (0x6130c + (x) * 0x1000)
+#define TSI721_IBDMAC_DQWR_MASK 0x0007ffff
+
+#define TSI721_IBDMAC_DQSZ(x) (0x61314 + (x) * 0x1000)
+#define TSI721_IBDMAC_DQSZ_MASK 0x0000000f
+
+/*
+ * Messaging Engine Interrupts
+ */
+
+#define TSI721_SMSG_PWE 0x6a004
+
+#define TSI721_SMSG_INTE 0x6a000
+#define TSI721_SMSG_INT 0x6a008
+#define TSI721_SMSG_INTSET 0x6a010
+#define TSI721_SMSG_INT_MASK 0x0086ffff
+#define TSI721_SMSG_INT_UNS_RSP 0x00800000
+#define TSI721_SMSG_INT_ECC_NCOR 0x00040000
+#define TSI721_SMSG_INT_ECC_COR 0x00020000
+#define TSI721_SMSG_INT_ECC_NCOR_CH 0x0000ff00
+#define TSI721_SMSG_INT_ECC_COR_CH 0x000000ff
+
+#define TSI721_SMSG_ECC_LOG 0x6a014
+#define TSI721_SMSG_ECC_LOG_MASK 0x00070007
+#define TSI721_SMSG_ECC_LOG_ECC_NCOR_M 0x00070000
+#define TSI721_SMSG_ECC_LOG_ECC_COR_M 0x00000007
+
+#define TSI721_RETRY_GEN_CNT 0x6a100
+#define TSI721_RETRY_GEN_CNT_MASK 0xffffffff
+
+#define TSI721_RETRY_RX_CNT 0x6a104
+#define TSI721_RETRY_RX_CNT_MASK 0xffffffff
+
+#define TSI721_SMSG_ECC_COR_LOG(x) (0x6a300 + (x) * 4)
+#define TSI721_SMSG_ECC_COR_LOG_MASK 0x000000ff
+
+#define TSI721_SMSG_ECC_NCOR(x) (0x6a340 + (x) * 4)
+#define TSI721_SMSG_ECC_NCOR_MASK 0x000000ff
+
+/*
+ * Block DMA Descriptors
+ */
+
+struct tsi721_dma_desc {
+ __le32 type_id;
+
+#define TSI721_DMAD_DEVID 0x0000ffff
+#define TSI721_DMAD_CRF 0x00010000
+#define TSI721_DMAD_PRIO 0x00060000
+#define TSI721_DMAD_RTYPE 0x00780000
+#define TSI721_DMAD_IOF 0x08000000
+#define TSI721_DMAD_DTYPE 0xe0000000
+
+ __le32 bcount;
+
+#define TSI721_DMAD_BCOUNT1 0x03ffffff /* if DTYPE == 1 */
+#define TSI721_DMAD_BCOUNT2 0x0000000f /* if DTYPE == 2 */
+#define TSI721_DMAD_TT 0x0c000000
+#define TSI721_DMAD_RADDR0 0xc0000000
+
+ union {
+ __le32 raddr_lo; /* if DTYPE == (1 || 2) */
+ __le32 next_lo; /* if DTYPE == 3 */
+ };
+
+#define TSI721_DMAD_CFGOFF 0x00ffffff
+#define TSI721_DMAD_HOPCNT 0xff000000
+
+ union {
+ __le32 raddr_hi; /* if DTYPE == (1 || 2) */
+ __le32 next_hi; /* if DTYPE == 3 */
+ };
+
+ union {
+ struct { /* if DTYPE == 1 */
+ __le32 bufptr_lo;
+ __le32 bufptr_hi;
+ __le32 s_dist;
+ __le32 s_size;
+ } t1;
+ __le32 data[4]; /* if DTYPE == 2 */
+ u32 reserved[4]; /* if DTYPE == 3 */
+ };
+} __aligned(32);
+
+/*
+ * Inbound Messaging Descriptor
+ */
+struct tsi721_imsg_desc {
+ __le32 type_id;
+
+#define TSI721_IMD_DEVID 0x0000ffff
+#define TSI721_IMD_CRF 0x00010000
+#define TSI721_IMD_PRIO 0x00060000
+#define TSI721_IMD_TT 0x00180000
+#define TSI721_IMD_DTYPE 0xe0000000
+
+ __le32 msg_info;
+
+#define TSI721_IMD_BCOUNT 0x00000ff8
+#define TSI721_IMD_SSIZE 0x0000f000
+#define TSI721_IMD_LETER 0x00030000
+#define TSI721_IMD_XMBOX 0x003c0000
+#define TSI721_IMD_MBOX 0x00c00000
+#define TSI721_IMD_CS 0x78000000
+#define TSI721_IMD_HO 0x80000000
+
+ __le32 bufptr_lo;
+ __le32 bufptr_hi;
+ u32 reserved[12];
+
+} __aligned(64);
+
+/*
+ * Outbound Messaging Descriptor
+ */
+struct tsi721_omsg_desc {
+ __le32 type_id;
+
+#define TSI721_OMD_DEVID 0x0000ffff
+#define TSI721_OMD_CRF 0x00010000
+#define TSI721_OMD_PRIO 0x00060000
+#define TSI721_OMD_IOF 0x08000000
+#define TSI721_OMD_DTYPE 0xe0000000
+#define TSI721_OMD_RSRVD 0x17f80000
+
+ __le32 msg_info;
+
+#define TSI721_OMD_BCOUNT 0x00000ff8
+#define TSI721_OMD_SSIZE 0x0000f000
+#define TSI721_OMD_LETER 0x00030000
+#define TSI721_OMD_XMBOX 0x003c0000
+#define TSI721_OMD_MBOX 0x00c00000
+#define TSI721_OMD_TT 0x0c000000
+
+ union {
+ __le32 bufptr_lo; /* if DTYPE == 4 */
+ __le32 next_lo; /* if DTYPE == 5 */
+ };
+
+ union {
+ __le32 bufptr_hi; /* if DTYPE == 4 */
+ __le32 next_hi; /* if DTYPE == 5 */
+ };
+
+} __aligned(16);
+
+struct tsi721_dma_sts {
+ __le64 desc_sts[8];
+} __aligned(64);
+
+struct tsi721_desc_sts_fifo {
+ union {
+ __le64 da64;
+ struct {
+ __le32 lo;
+ __le32 hi;
+ } da32;
+ } stat[8];
+} __aligned(64);
+
+/* Descriptor types for BDMA and Messaging blocks */
+enum dma_dtype {
+ DTYPE1 = 1, /* Data Transfer DMA Descriptor */
+ DTYPE2 = 2, /* Immediate Data Transfer DMA Descriptor */
+ DTYPE3 = 3, /* Block Pointer DMA Descriptor */
+ DTYPE4 = 4, /* Outbound Msg DMA Descriptor */
+ DTYPE5 = 5, /* OB Messaging Block Pointer Descriptor */
+ DTYPE6 = 6 /* Inbound Messaging Descriptor */
+};
+
+enum dma_rtype {
+ NREAD = 0,
+ LAST_NWRITE_R = 1,
+ ALL_NWRITE = 2,
+ ALL_NWRITE_R = 3,
+ MAINT_RD = 4,
+ MAINT_WR = 5
+};
+
+/*
+ * mport Driver Definitions
+ */
+#define TSI721_DMA_CHNUM TSI721_DMA_MAXCH
+
+#define TSI721_DMACH_MAINT 0 /* DMA channel for maint requests */
+#define TSI721_DMACH_MAINT_NBD 32 /* Number of BDs for maint requests */
+
+#define MSG_DMA_ENTRY_INX_TO_SIZE(x) ((0x10 << (x)) & 0xFFFF0)
+
+enum tsi721_smsg_int_flag {
+ SMSG_INT_NONE = 0x00000000,
+ SMSG_INT_ECC_COR_CH = 0x000000ff,
+ SMSG_INT_ECC_NCOR_CH = 0x0000ff00,
+ SMSG_INT_ECC_COR = 0x00020000,
+ SMSG_INT_ECC_NCOR = 0x00040000,
+ SMSG_INT_UNS_RSP = 0x00800000,
+ SMSG_INT_ALL = 0x0006ffff
+};
+
+/* Structures */
+
+struct tsi721_bdma_chan {
+ int bd_num; /* number of buffer descriptors */
+ void *bd_base; /* start of DMA descriptors */
+ dma_addr_t bd_phys;
+ void *sts_base; /* start of DMA BD status FIFO */
+ dma_addr_t sts_phys;
+ int sts_size;
+};
+
+struct tsi721_imsg_ring {
+ u32 size;
+ /* VA/PA of data buffers for incoming messages */
+ void *buf_base;
+ dma_addr_t buf_phys;
+ /* VA/PA of circular free buffer list */
+ void *imfq_base;
+ dma_addr_t imfq_phys;
+ /* VA/PA of Inbound message descriptors */
+ void *imd_base;
+ dma_addr_t imd_phys;
+ /* Inbound Queue buffer pointers */
+ void *imq_base[TSI721_IMSGD_RING_SIZE];
+
+ u32 rx_slot;
+ void *dev_id;
+ u32 fq_wrptr;
+ u32 desc_rdptr;
+ spinlock_t lock;
+};
+
+struct tsi721_omsg_ring {
+ u32 size;
+ /* VA/PA of OB Msg descriptors */
+ void *omd_base;
+ dma_addr_t omd_phys;
+ /* VA/PA of OB Msg data buffers */
+ void *omq_base[TSI721_OMSGD_RING_SIZE];
+ dma_addr_t omq_phys[TSI721_OMSGD_RING_SIZE];
+ /* VA/PA of OB Msg descriptor status FIFO */
+ void *sts_base;
+ dma_addr_t sts_phys;
+ u32 sts_size; /* # of allocated status entries */
+ u32 sts_rdptr;
+
+ u32 tx_slot;
+ void *dev_id;
+ u32 wr_count;
+ spinlock_t lock;
+};
+
+enum tsi721_flags {
+ TSI721_USING_MSI = (1 << 0),
+ TSI721_USING_MSIX = (1 << 1),
+ TSI721_IMSGID_SET = (1 << 2),
+};
+
+#ifdef CONFIG_PCI_MSI
+/*
+ * MSI-X Table Entries (0 ... 69)
+ */
+#define TSI721_MSIX_DMACH_DONE(x) (0 + (x))
+#define TSI721_MSIX_DMACH_INT(x) (8 + (x))
+#define TSI721_MSIX_BDMA_INT 16
+#define TSI721_MSIX_OMSG_DONE(x) (17 + (x))
+#define TSI721_MSIX_OMSG_INT(x) (25 + (x))
+#define TSI721_MSIX_IMSG_DQ_RCV(x) (33 + (x))
+#define TSI721_MSIX_IMSG_INT(x) (41 + (x))
+#define TSI721_MSIX_MSG_INT 49
+#define TSI721_MSIX_SR2PC_IDBQ_RCV(x) (50 + (x))
+#define TSI721_MSIX_SR2PC_CH_INT(x) (58 + (x))
+#define TSI721_MSIX_SR2PC_INT 66
+#define TSI721_MSIX_PC2SR_INT 67
+#define TSI721_MSIX_SRIO_MAC_INT 68
+#define TSI721_MSIX_I2C_INT 69
+
+/* MSI-X vector and init table entry indexes */
+enum tsi721_msix_vect {
+ TSI721_VECT_IDB,
+ TSI721_VECT_PWRX, /* PW_RX is part of SRIO MAC Interrupt reporting */
+ TSI721_VECT_OMB0_DONE,
+ TSI721_VECT_OMB1_DONE,
+ TSI721_VECT_OMB2_DONE,
+ TSI721_VECT_OMB3_DONE,
+ TSI721_VECT_OMB0_INT,
+ TSI721_VECT_OMB1_INT,
+ TSI721_VECT_OMB2_INT,
+ TSI721_VECT_OMB3_INT,
+ TSI721_VECT_IMB0_RCV,
+ TSI721_VECT_IMB1_RCV,
+ TSI721_VECT_IMB2_RCV,
+ TSI721_VECT_IMB3_RCV,
+ TSI721_VECT_IMB0_INT,
+ TSI721_VECT_IMB1_INT,
+ TSI721_VECT_IMB2_INT,
+ TSI721_VECT_IMB3_INT,
+ TSI721_VECT_MAX
+};
+
+#define IRQ_DEVICE_NAME_MAX 64
+
+struct msix_irq {
+ u16 vector;
+ char irq_name[IRQ_DEVICE_NAME_MAX];
+};
+#endif /* CONFIG_PCI_MSI */
+
+struct tsi721_device {
+ struct pci_dev *pdev;
+ struct rio_mport *mport;
+ u32 flags;
+ void __iomem *regs;
+#ifdef CONFIG_PCI_MSI
+ struct msix_irq msix[TSI721_VECT_MAX];
+#endif
+ /* Doorbells */
+ void __iomem *odb_base;
+ void *idb_base;
+ dma_addr_t idb_dma;
+ struct work_struct idb_work;
+ u32 db_discard_count;
+
+ /* Inbound Port-Write */
+ struct work_struct pw_work;
+ struct kfifo pw_fifo;
+ spinlock_t pw_fifo_lock;
+ u32 pw_discard_count;
+
+ /* BDMA Engine */
+ struct tsi721_bdma_chan bdma[TSI721_DMA_CHNUM];
+
+ /* Inbound Messaging */
+ int imsg_init[TSI721_IMSG_CHNUM];
+ struct tsi721_imsg_ring imsg_ring[TSI721_IMSG_CHNUM];
+
+ /* Outbound Messaging */
+ int omsg_init[TSI721_OMSG_CHNUM];
+ struct tsi721_omsg_ring omsg_ring[TSI721_OMSG_CHNUM];
+};
+
+#endif
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index ebe77dd87daf..2bebd791a092 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -516,7 +516,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
return rdev;
cleanup:
- if (rio_is_switch(rdev))
+ if (rswitch)
kfree(rswitch->route_table);
kfree(rdev);
@@ -923,7 +923,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
* rio_enum_complete- Tests if enumeration of a network is complete
* @port: Master port to send transaction
*
- * Tests the Component Tag CSR for non-zero value (enumeration
+ * Tests the PGCCSR discovered bit for non-zero value (enumeration
* complete flag). Return %1 if enumeration is complete or %0 if
* enumeration is incomplete.
*/
@@ -933,7 +933,7 @@ static int rio_enum_complete(struct rio_mport *port)
rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR,
&regval);
- return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0;
+ return (regval & RIO_PORT_GEN_DISCOVERED) ? 1 : 0;
}
/**
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index d63fddb0fbb0..e821b2159b4b 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -412,7 +412,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
if (info->desc.id == res->start)
break;
}
- if ((i < 0) || (i > PM8607_ID_RG_MAX)) {
+ if (i == ARRAY_SIZE(pm8607_regulator_info)) {
dev_err(&pdev->dev, "Failed to find regulator %llu\n",
(unsigned long long)res->start);
return -EINVAL;
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index c7fd2c0e3f2b..9713b1b860cb 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -64,6 +64,16 @@ config REGULATOR_USERSPACE_CONSUMER
If unsure, say no.
+config REGULATOR_GPIO
+ tristate "GPIO regulator support"
+ depends on GENERIC_GPIO
+ help
+ This driver provides support for regulators that can be
+ controlled via gpios.
+ It is capable of supporting current and voltage regulators
+ and the platform has to provide a mapping of GPIO-states
+ to target volts/amps.
+
config REGULATOR_BQ24022
tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC"
help
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 040d5aa63535..93a6318f5328 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
+obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
index cd4104542f0d..5abeb3ac3e8d 100644
--- a/drivers/regulator/aat2870-regulator.c
+++ b/drivers/regulator/aat2870-regulator.c
@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index d8e6a429e8ba..67fa2a3297ad 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1425,7 +1425,7 @@ int regulator_enable(struct regulator *regulator)
ret = _regulator_enable(rdev);
mutex_unlock(&rdev->mutex);
- if (ret != 0)
+ if (ret != 0 && rdev->supply)
regulator_disable(rdev->supply);
return ret;
@@ -1552,6 +1552,68 @@ int regulator_force_disable(struct regulator *regulator)
}
EXPORT_SYMBOL_GPL(regulator_force_disable);
+static void regulator_disable_work(struct work_struct *work)
+{
+ struct regulator_dev *rdev = container_of(work, struct regulator_dev,
+ disable_work.work);
+ int count, i, ret;
+
+ mutex_lock(&rdev->mutex);
+
+ BUG_ON(!rdev->deferred_disables);
+
+ count = rdev->deferred_disables;
+ rdev->deferred_disables = 0;
+
+ for (i = 0; i < count; i++) {
+ ret = _regulator_disable(rdev);
+ if (ret != 0)
+ rdev_err(rdev, "Deferred disable failed: %d\n", ret);
+ }
+
+ mutex_unlock(&rdev->mutex);
+
+ if (rdev->supply) {
+ for (i = 0; i < count; i++) {
+ ret = regulator_disable(rdev->supply);
+ if (ret != 0) {
+ rdev_err(rdev,
+ "Supply disable failed: %d\n", ret);
+ }
+ }
+ }
+}
+
+/**
+ * regulator_disable_deferred - disable regulator output with delay
+ * @regulator: regulator source
+ * @ms: miliseconds until the regulator is disabled
+ *
+ * Execute regulator_disable() on the regulator after a delay. This
+ * is intended for use with devices that require some time to quiesce.
+ *
+ * NOTE: this will only disable the regulator output if no other consumer
+ * devices have it enabled, the regulator device supports disabling and
+ * machine constraints permit this operation.
+ */
+int regulator_disable_deferred(struct regulator *regulator, int ms)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+ int ret;
+
+ mutex_lock(&rdev->mutex);
+ rdev->deferred_disables++;
+ mutex_unlock(&rdev->mutex);
+
+ ret = schedule_delayed_work(&rdev->disable_work,
+ msecs_to_jiffies(ms));
+ if (ret < 0)
+ return ret;
+ else
+ return 0;
+}
+EXPORT_SYMBOL_GPL(regulator_disable_deferred);
+
static int _regulator_is_enabled(struct regulator_dev *rdev)
{
/* If we don't know then assume that the regulator is always on */
@@ -2622,6 +2684,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
INIT_LIST_HEAD(&rdev->consumer_list);
INIT_LIST_HEAD(&rdev->list);
BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
+ INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
/* preform any regulator specific init */
if (init_data->regulator_init) {
@@ -2729,6 +2792,7 @@ void regulator_unregister(struct regulator_dev *rdev)
#ifdef CONFIG_DEBUG_FS
debugfs_remove_recursive(rdev->debugfs);
#endif
+ flush_work_sync(&rdev->disable_work.work);
WARN_ON(rdev->open_count);
unset_regulator_supplies(rdev);
list_del(&rdev->list);
@@ -2907,6 +2971,43 @@ void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
}
EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
+#ifdef CONFIG_DEBUG_FS
+static ssize_t supply_map_read_file(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ ssize_t len, ret = 0;
+ struct regulator_map *map;
+
+ if (!buf)
+ return -ENOMEM;
+
+ list_for_each_entry(map, &regulator_map_list, list) {
+ len = snprintf(buf + ret, PAGE_SIZE - ret,
+ "%s -> %s.%s\n",
+ rdev_get_name(map->regulator), map->dev_name,
+ map->supply);
+ if (len >= 0)
+ ret += len;
+ if (ret > PAGE_SIZE) {
+ ret = PAGE_SIZE;
+ break;
+ }
+ }
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+ kfree(buf);
+
+ return ret;
+}
+
+static const struct file_operations supply_map_fops = {
+ .read = supply_map_read_file,
+ .llseek = default_llseek,
+};
+#endif
+
static int __init regulator_init(void)
{
int ret;
@@ -2919,6 +3020,10 @@ static int __init regulator_init(void)
pr_warn("regulator: Failed to create debugfs directory\n");
debugfs_root = NULL;
}
+
+ if (IS_ERR(debugfs_create_file("supply_map", 0444, debugfs_root,
+ NULL, &supply_map_fops)))
+ pr_warn("regulator: Failed to create supplies debugfs\n");
#endif
regulator_dummy_init();
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
new file mode 100644
index 000000000000..f0acf52498bd
--- /dev/null
+++ b/drivers/regulator/gpio-regulator.c
@@ -0,0 +1,358 @@
+/*
+ * gpio-regulator.c
+ *
+ * Copyright 2011 Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on fixed.c
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * Copyright (c) 2009 Nokia Corporation
+ * Roger Quadros <ext-roger.quadros@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 is useful for systems with mixed controllable and
+ * non-controllable regulators, as well as for allowing testing on
+ * systems with no controllable regulators.
+ */
+
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/gpio-regulator.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+struct gpio_regulator_data {
+ struct regulator_desc desc;
+ struct regulator_dev *dev;
+
+ int enable_gpio;
+ bool enable_high;
+ bool is_enabled;
+ unsigned startup_delay;
+
+ struct gpio *gpios;
+ int nr_gpios;
+
+ struct gpio_regulator_state *states;
+ int nr_states;
+
+ int state;
+};
+
+static int gpio_regulator_is_enabled(struct regulator_dev *dev)
+{
+ struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+
+ return data->is_enabled;
+}
+
+static int gpio_regulator_enable(struct regulator_dev *dev)
+{
+ struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+
+ if (gpio_is_valid(data->enable_gpio)) {
+ gpio_set_value_cansleep(data->enable_gpio, data->enable_high);
+ data->is_enabled = true;
+ }
+
+ return 0;
+}
+
+static int gpio_regulator_disable(struct regulator_dev *dev)
+{
+ struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+
+ if (gpio_is_valid(data->enable_gpio)) {
+ gpio_set_value_cansleep(data->enable_gpio, !data->enable_high);
+ data->is_enabled = false;
+ }
+
+ return 0;
+}
+
+static int gpio_regulator_enable_time(struct regulator_dev *dev)
+{
+ struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+
+ return data->startup_delay;
+}
+
+static int gpio_regulator_get_value(struct regulator_dev *dev)
+{
+ struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+ int ptr;
+
+ for (ptr = 0; ptr < data->nr_states; ptr++)
+ if (data->states[ptr].gpios == data->state)
+ return data->states[ptr].value;
+
+ return -EINVAL;
+}
+
+static int gpio_regulator_set_value(struct regulator_dev *dev,
+ int min, int max)
+{
+ struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+ int ptr, target, state;
+
+ target = -1;
+ for (ptr = 0; ptr < data->nr_states; ptr++)
+ if (data->states[ptr].value >= min &&
+ data->states[ptr].value <= max)
+ target = data->states[ptr].gpios;
+
+ if (target < 0)
+ return -EINVAL;
+
+ for (ptr = 0; ptr < data->nr_gpios; ptr++) {
+ state = (target & (1 << ptr)) >> ptr;
+ gpio_set_value(data->gpios[ptr].gpio, state);
+ }
+ data->state = target;
+
+ return 0;
+}
+
+static int gpio_regulator_set_voltage(struct regulator_dev *dev,
+ int min_uV, int max_uV,
+ unsigned *selector)
+{
+ return gpio_regulator_set_value(dev, min_uV, max_uV);
+}
+
+static int gpio_regulator_list_voltage(struct regulator_dev *dev,
+ unsigned selector)
+{
+ struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+
+ if (selector >= data->nr_states)
+ return -EINVAL;
+
+ return data->states[selector].value;
+}
+
+static int gpio_regulator_set_current_limit(struct regulator_dev *dev,
+ int min_uA, int max_uA)
+{
+ return gpio_regulator_set_value(dev, min_uA, max_uA);
+}
+
+static struct regulator_ops gpio_regulator_voltage_ops = {
+ .is_enabled = gpio_regulator_is_enabled,
+ .enable = gpio_regulator_enable,
+ .disable = gpio_regulator_disable,
+ .enable_time = gpio_regulator_enable_time,
+ .get_voltage = gpio_regulator_get_value,
+ .set_voltage = gpio_regulator_set_voltage,
+ .list_voltage = gpio_regulator_list_voltage,
+};
+
+static struct regulator_ops gpio_regulator_current_ops = {
+ .is_enabled = gpio_regulator_is_enabled,
+ .enable = gpio_regulator_enable,
+ .disable = gpio_regulator_disable,
+ .enable_time = gpio_regulator_enable_time,
+ .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)
+{
+ struct gpio_regulator_config *config = pdev->dev.platform_data;
+ struct gpio_regulator_data *drvdata;
+ int ptr, ret, state;
+
+ drvdata = kzalloc(sizeof(struct gpio_regulator_data), GFP_KERNEL);
+ if (drvdata == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate device data\n");
+ return -ENOMEM;
+ }
+
+ drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
+ if (drvdata->desc.name == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate supply name\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ drvdata->gpios = kmemdup(config->gpios,
+ config->nr_gpios * sizeof(struct gpio),
+ GFP_KERNEL);
+ if (drvdata->gpios == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate gpio data\n");
+ ret = -ENOMEM;
+ goto err_name;
+ }
+
+ drvdata->states = kmemdup(config->states,
+ config->nr_states *
+ sizeof(struct gpio_regulator_state),
+ GFP_KERNEL);
+ if (drvdata->states == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate state data\n");
+ ret = -ENOMEM;
+ goto err_memgpio;
+ }
+ drvdata->nr_states = config->nr_states;
+
+ drvdata->desc.owner = THIS_MODULE;
+
+ /* handle regulator type*/
+ switch (config->type) {
+ case REGULATOR_VOLTAGE:
+ drvdata->desc.type = REGULATOR_VOLTAGE;
+ drvdata->desc.ops = &gpio_regulator_voltage_ops;
+ drvdata->desc.n_voltages = config->nr_states;
+ break;
+ case REGULATOR_CURRENT:
+ drvdata->desc.type = REGULATOR_CURRENT;
+ drvdata->desc.ops = &gpio_regulator_current_ops;
+ break;
+ default:
+ dev_err(&pdev->dev, "No regulator type set\n");
+ ret = -EINVAL;
+ goto err_memgpio;
+ break;
+ }
+
+ drvdata->enable_gpio = config->enable_gpio;
+ drvdata->startup_delay = config->startup_delay;
+
+ if (gpio_is_valid(config->enable_gpio)) {
+ drvdata->enable_high = config->enable_high;
+
+ ret = gpio_request(config->enable_gpio, config->supply_name);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Could not obtain regulator enable GPIO %d: %d\n",
+ config->enable_gpio, ret);
+ goto err_memstate;
+ }
+
+ /* set output direction without changing state
+ * to prevent glitch
+ */
+ if (config->enabled_at_boot) {
+ drvdata->is_enabled = true;
+ ret = gpio_direction_output(config->enable_gpio,
+ config->enable_high);
+ } else {
+ drvdata->is_enabled = false;
+ ret = gpio_direction_output(config->enable_gpio,
+ !config->enable_high);
+ }
+
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Could not configure regulator enable GPIO %d direction: %d\n",
+ config->enable_gpio, ret);
+ goto err_enablegpio;
+ }
+ } else {
+ /* Regulator without GPIO control is considered
+ * always enabled
+ */
+ drvdata->is_enabled = true;
+ }
+
+ drvdata->nr_gpios = config->nr_gpios;
+ ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Could not obtain regulator setting GPIOs: %d\n", ret);
+ goto err_enablegpio;
+ }
+
+ /* build initial state from gpio init data. */
+ state = 0;
+ for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) {
+ if (config->gpios[ptr].flags & GPIOF_OUT_INIT_HIGH)
+ state |= (1 << ptr);
+ }
+ drvdata->state = state;
+
+ drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
+ config->init_data, drvdata);
+ if (IS_ERR(drvdata->dev)) {
+ ret = PTR_ERR(drvdata->dev);
+ dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
+ goto err_stategpio;
+ }
+
+ platform_set_drvdata(pdev, drvdata);
+
+ return 0;
+
+err_stategpio:
+ gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
+err_enablegpio:
+ if (gpio_is_valid(config->enable_gpio))
+ gpio_free(config->enable_gpio);
+err_memstate:
+ kfree(drvdata->states);
+err_memgpio:
+ kfree(drvdata->gpios);
+err_name:
+ kfree(drvdata->desc.name);
+err:
+ kfree(drvdata);
+ return ret;
+}
+
+static int __devexit gpio_regulator_remove(struct platform_device *pdev)
+{
+ struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev);
+
+ regulator_unregister(drvdata->dev);
+
+ gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
+
+ kfree(drvdata->states);
+ kfree(drvdata->gpios);
+
+ if (gpio_is_valid(drvdata->enable_gpio))
+ gpio_free(drvdata->enable_gpio);
+
+ kfree(drvdata->desc.name);
+ kfree(drvdata);
+
+ return 0;
+}
+
+static struct platform_driver gpio_regulator_driver = {
+ .probe = gpio_regulator_probe,
+ .remove = __devexit_p(gpio_regulator_remove),
+ .driver = {
+ .name = "gpio-regulator",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init gpio_regulator_init(void)
+{
+ return platform_driver_register(&gpio_regulator_driver);
+}
+subsys_initcall(gpio_regulator_init);
+
+static void __exit gpio_regulator_exit(void)
+{
+ platform_driver_unregister(&gpio_regulator_driver);
+}
+module_exit(gpio_regulator_exit);
+
+MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
+MODULE_DESCRIPTION("gpio voltage regulator");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-regulator");
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 30eb9e54f7ec..1062cf9f02dc 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -221,7 +221,7 @@ static int max8649_enable_time(struct regulator_dev *rdev)
ret = (ret & MAX8649_RAMP_MASK) >> 5;
rate = (32 * 1000) >> ret; /* uV/uS */
- return (voltage / rate);
+ return DIV_ROUND_UP(voltage, rate);
}
static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode)
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 486ed8141fcd..3883d85c5b88 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -26,7 +26,6 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/max8952.h>
-#include <linux/mutex.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/slab.h>
@@ -47,7 +46,6 @@ enum {
struct max8952_data {
struct i2c_client *client;
struct device *dev;
- struct mutex mutex;
struct max8952_platform_data *pdata;
struct regulator_dev *rdev;
@@ -208,7 +206,6 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
max8952->client = client;
max8952->dev = &client->dev;
max8952->pdata = pdata;
- mutex_init(&max8952->mutex);
max8952->rdev = regulator_register(&regulator, max8952->dev,
&pdata->reg_data, max8952);
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 701a5900f83f..9fb4c7b81753 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -63,6 +63,13 @@
#define TPS65023_REG_CTRL_LDO2_EN BIT(2)
#define TPS65023_REG_CTRL_LDO1_EN BIT(1)
+/* REG_CTRL2 bitfields */
+#define TPS65023_REG_CTRL2_GO BIT(7)
+#define TPS65023_REG_CTRL2_CORE_ADJ BIT(6)
+#define TPS65023_REG_CTRL2_DCDC2 BIT(2)
+#define TPS65023_REG_CTRL2_DCDC1 BIT(1)
+#define TPS65023_REG_CTRL2_DCDC3 BIT(0)
+
/* LDO_CTRL bitfields */
#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4)
#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0xF0 >> ((ldo_id)*4))
@@ -85,7 +92,7 @@
#define TPS65023_MAX_REG_ID TPS65023_LDO_2
/* Supported voltage values for regulators */
-static const u16 VDCDC1_VSEL_table[] = {
+static const u16 VCORE_VSEL_table[] = {
800, 825, 850, 875,
900, 925, 950, 975,
1000, 1025, 1050, 1075,
@@ -96,20 +103,29 @@ static const u16 VDCDC1_VSEL_table[] = {
1500, 1525, 1550, 1600,
};
-static const u16 LDO1_VSEL_table[] = {
+/* Supported voltage values for LDO regulators for tps65020 */
+static const u16 TPS65020_LDO1_VSEL_table[] = {
+ 1000, 1050, 1100, 1300,
+ 1800, 2500, 3000, 3300,
+};
+
+static const u16 TPS65020_LDO2_VSEL_table[] = {
+ 1000, 1050, 1100, 1300,
+ 1800, 2500, 3000, 3300,
+};
+
+/* Supported voltage values for LDO regulators
+ * for tps65021 and tps65023 */
+static const u16 TPS65023_LDO1_VSEL_table[] = {
1000, 1100, 1300, 1800,
2200, 2600, 2800, 3150,
};
-static const u16 LDO2_VSEL_table[] = {
+static const u16 TPS65023_LDO2_VSEL_table[] = {
1050, 1200, 1300, 1800,
2500, 2800, 3000, 3300,
};
-static unsigned int num_voltages[] = {ARRAY_SIZE(VDCDC1_VSEL_table),
- 0, 0, ARRAY_SIZE(LDO1_VSEL_table),
- ARRAY_SIZE(LDO2_VSEL_table)};
-
/* Regulator specific details */
struct tps_info {
const char *name;
@@ -127,6 +143,13 @@ struct tps_pmic {
struct regulator_dev *rdev[TPS65023_NUM_REGULATOR];
const struct tps_info *info[TPS65023_NUM_REGULATOR];
struct regmap *regmap;
+ u8 core_regulator;
+};
+
+/* Struct passed as driver data */
+struct tps_driver_data {
+ const struct tps_info *info;
+ u8 core_regulator;
};
static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask)
@@ -253,7 +276,7 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
return -EINVAL;
- if (dcdc == TPS65023_DCDC_1) {
+ if (dcdc == tps->core_regulator) {
data = tps_65023_reg_read(tps, TPS65023_REG_DEF_CORE);
if (data < 0)
return data;
@@ -270,10 +293,10 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
struct tps_pmic *tps = rdev_get_drvdata(dev);
int dcdc = rdev_get_id(dev);
int vsel;
+ int ret;
- if (dcdc != TPS65023_DCDC_1)
+ if (dcdc != tps->core_regulator)
return -EINVAL;
-
if (min_uV < tps->info[dcdc]->min_uV
|| min_uV > tps->info[dcdc]->max_uV)
return -EINVAL;
@@ -292,11 +315,21 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
*selector = vsel;
- /* write to the register in case we found a match */
if (vsel == tps->info[dcdc]->table_len)
- return -EINVAL;
- else
- return tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel);
+ goto failed;
+
+ ret = tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel);
+
+ /* Tell the chip that we have changed the value in DEFCORE
+ * and its time to update the core voltage
+ */
+ tps_65023_set_bits(tps, TPS65023_REG_CON_CTRL2,
+ TPS65023_REG_CTRL2_GO);
+
+ return ret;
+
+failed:
+ return -EINVAL;
}
static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
@@ -362,7 +395,7 @@ static int tps65023_dcdc_list_voltage(struct regulator_dev *dev,
if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
return -EINVAL;
- if (dcdc == TPS65023_DCDC_1) {
+ if (dcdc == tps->core_regulator) {
if (selector >= tps->info[dcdc]->table_len)
return -EINVAL;
else
@@ -414,7 +447,8 @@ static struct regmap_config tps65023_regmap_config = {
static int __devinit tps_65023_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- const struct tps_info *info = (void *)id->driver_data;
+ const struct tps_driver_data *drv_data = (void *)id->driver_data;
+ const struct tps_info *info = drv_data->info;
struct regulator_init_data *init_data;
struct regulator_dev *rdev;
struct tps_pmic *tps;
@@ -446,6 +480,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
/* common for all regulators */
tps->client = client;
+ tps->core_regulator = drv_data->core_regulator;
for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) {
/* Store regulator specific information */
@@ -453,7 +488,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
tps->desc[i].name = info->name;
tps->desc[i].id = i;
- tps->desc[i].n_voltages = num_voltages[i];
+ tps->desc[i].n_voltages = info->table_len;
tps->desc[i].ops = (i > TPS65023_DCDC_3 ?
&tps65023_ldo_ops : &tps65023_dcdc_ops);
tps->desc[i].type = REGULATOR_VOLTAGE;
@@ -475,6 +510,14 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
i2c_set_clientdata(client, tps);
+ /* Enable setting output voltage by I2C */
+ tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2,
+ TPS65023_REG_CTRL2_CORE_ADJ);
+
+ /* Enable setting output voltage by I2C */
+ tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2,
+ TPS65023_REG_CTRL2_CORE_ADJ);
+
return 0;
fail:
@@ -507,13 +550,86 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
return 0;
}
+static const struct tps_info tps65020_regs[] = {
+ {
+ .name = "VDCDC1",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .fixed = 1,
+ },
+ {
+ .name = "VDCDC2",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .fixed = 1,
+ },
+ {
+ .name = "VDCDC3",
+ .min_uV = 800000,
+ .max_uV = 1600000,
+ .table_len = ARRAY_SIZE(VCORE_VSEL_table),
+ .table = VCORE_VSEL_table,
+ },
+
+ {
+ .name = "LDO1",
+ .min_uV = 1000000,
+ .max_uV = 3150000,
+ .table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table),
+ .table = TPS65020_LDO1_VSEL_table,
+ },
+ {
+ .name = "LDO2",
+ .min_uV = 1050000,
+ .max_uV = 3300000,
+ .table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table),
+ .table = TPS65020_LDO2_VSEL_table,
+ },
+};
+
+static const struct tps_info tps65021_regs[] = {
+ {
+ .name = "VDCDC1",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .fixed = 1,
+ },
+ {
+ .name = "VDCDC2",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .fixed = 1,
+ },
+ {
+ .name = "VDCDC3",
+ .min_uV = 800000,
+ .max_uV = 1600000,
+ .table_len = ARRAY_SIZE(VCORE_VSEL_table),
+ .table = VCORE_VSEL_table,
+ },
+ {
+ .name = "LDO1",
+ .min_uV = 1000000,
+ .max_uV = 3150000,
+ .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
+ .table = TPS65023_LDO1_VSEL_table,
+ },
+ {
+ .name = "LDO2",
+ .min_uV = 1050000,
+ .max_uV = 3300000,
+ .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
+ .table = TPS65023_LDO2_VSEL_table,
+ },
+};
+
static const struct tps_info tps65023_regs[] = {
{
.name = "VDCDC1",
.min_uV = 800000,
.max_uV = 1600000,
- .table_len = ARRAY_SIZE(VDCDC1_VSEL_table),
- .table = VDCDC1_VSEL_table,
+ .table_len = ARRAY_SIZE(VCORE_VSEL_table),
+ .table = VCORE_VSEL_table,
},
{
.name = "VDCDC2",
@@ -531,23 +647,40 @@ static const struct tps_info tps65023_regs[] = {
.name = "LDO1",
.min_uV = 1000000,
.max_uV = 3150000,
- .table_len = ARRAY_SIZE(LDO1_VSEL_table),
- .table = LDO1_VSEL_table,
+ .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
+ .table = TPS65023_LDO1_VSEL_table,
},
{
.name = "LDO2",
.min_uV = 1050000,
.max_uV = 3300000,
- .table_len = ARRAY_SIZE(LDO2_VSEL_table),
- .table = LDO2_VSEL_table,
+ .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
+ .table = TPS65023_LDO2_VSEL_table,
},
};
+static struct tps_driver_data tps65020_drv_data = {
+ .info = tps65020_regs,
+ .core_regulator = TPS65023_DCDC_3,
+};
+
+static struct tps_driver_data tps65021_drv_data = {
+ .info = tps65021_regs,
+ .core_regulator = TPS65023_DCDC_3,
+};
+
+static struct tps_driver_data tps65023_drv_data = {
+ .info = tps65023_regs,
+ .core_regulator = TPS65023_DCDC_1,
+};
+
static const struct i2c_device_id tps_65023_id[] = {
{.name = "tps65023",
- .driver_data = (unsigned long) tps65023_regs,},
+ .driver_data = (unsigned long) &tps65023_drv_data},
{.name = "tps65021",
- .driver_data = (unsigned long) tps65023_regs,},
+ .driver_data = (unsigned long) &tps65021_drv_data,},
+ {.name = "tps65020",
+ .driver_data = (unsigned long) &tps65020_drv_data},
{ },
};
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index bfffabc21eda..bdef70365f52 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -90,12 +90,6 @@ static const u16 LDO2_VSEL_table[] = {
3000, 3100, 3200, 3300,
};
-static unsigned int num_voltages[] = {ARRAY_SIZE(VDCDCx_VSEL_table),
- ARRAY_SIZE(VDCDCx_VSEL_table),
- ARRAY_SIZE(VDCDCx_VSEL_table),
- ARRAY_SIZE(LDO1_VSEL_table),
- ARRAY_SIZE(LDO2_VSEL_table)};
-
struct tps_info {
const char *name;
unsigned min_uV;
@@ -598,7 +592,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev)
tps->desc[i].name = info->name;
tps->desc[i].id = i;
- tps->desc[i].n_voltages = num_voltages[i];
+ tps->desc[i].n_voltages = info->table_len;
tps->desc[i].ops = (i > TPS6507X_DCDC_3 ?
&tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops);
tps->desc[i].type = REGULATOR_VOLTAGE;
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index bb04a75a4c98..dbcf09d5080c 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -332,6 +332,36 @@ 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)
+{
+ 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;
+
+ if (setting == NULL)
+ return 0;
+
+ if (!(setting->slew_rate & TPS6586X_SLEW_RATE_SET))
+ return 0;
+
+ /* only SM0 and SM1 can have the slew rate settings */
+ switch (pdev->id) {
+ case TPS6586X_ID_SM_0:
+ reg = TPS6586X_SM0SL;
+ break;
+ case TPS6586X_ID_SM_1:
+ reg = TPS6586X_SM1SL;
+ break;
+ default:
+ dev_warn(&pdev->dev, "Only SM0/SM1 can set slew rate\n");
+ return -EINVAL;
+ }
+
+ return tps6586x_write(parent, reg,
+ setting->slew_rate & TPS6586X_SLEW_RATE_MASK);
+}
+
static inline struct tps6586x_regulator *find_regulator_info(int id)
{
struct tps6586x_regulator *ri;
@@ -374,7 +404,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rdev);
- return 0;
+ return tps6586x_regulator_set_slew_rate(pdev);
}
static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 3a9313e00fac..39d4a1749e71 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -43,8 +43,6 @@
#define TPS65912_REG_LDO9 12
#define TPS65912_REG_LDO10 13
-#define TPS65912_MAX_REG_ID TPS65912_REG_LDO_10
-
/* Number of step-down converters available */
#define TPS65912_NUM_DCDC 4
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index 1a6a690f24db..b87bf5c841f8 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -140,6 +140,14 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
return (selector * 100000) + 900000;
case WM8958:
return (selector * 100000) + 1000000;
+ case WM1811:
+ switch (selector) {
+ case 0:
+ return -EINVAL;
+ default:
+ return (selector * 100000) + 950000;
+ }
+ break;
default:
return -EINVAL;
}
@@ -170,6 +178,11 @@ static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
case WM8958:
selector = (min_uV - 1000000) / 100000;
break;
+ case WM1811:
+ selector = (min_uV - 950000) / 100000;
+ if (selector == 0)
+ selector = 1;
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 5a538fc1cc85..53eb4e55b289 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -8,7 +8,7 @@ config RTC_LIB
menuconfig RTC_CLASS
bool "Real Time Clock"
default n
- depends on !S390
+ depends on !S390 && !UML
select RTC_LIB
help
Generic RTC class support. If you say yes here, you will
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 01a7df5317c1..e8326f26fa2f 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -21,16 +21,13 @@
#include "rtc-core.h"
-static DEFINE_IDR(rtc_idr);
-static DEFINE_MUTEX(idr_lock);
+static DEFINE_IDA(rtc_ida);
struct class *rtc_class;
static void rtc_device_release(struct device *dev)
{
struct rtc_device *rtc = to_rtc_device(dev);
- mutex_lock(&idr_lock);
- idr_remove(&rtc_idr, rtc->id);
- mutex_unlock(&idr_lock);
+ ida_simple_remove(&rtc_ida, rtc->id);
kfree(rtc);
}
@@ -146,25 +143,16 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
struct rtc_wkalrm alrm;
int id, err;
- if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) {
- err = -ENOMEM;
+ id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL);
+ if (id < 0) {
+ err = id;
goto exit;
}
-
- mutex_lock(&idr_lock);
- err = idr_get_new(&rtc_idr, NULL, &id);
- mutex_unlock(&idr_lock);
-
- if (err < 0)
- goto exit;
-
- id = id & MAX_ID_MASK;
-
rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL);
if (rtc == NULL) {
err = -ENOMEM;
- goto exit_idr;
+ goto exit_ida;
}
rtc->id = id;
@@ -222,10 +210,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
exit_kfree:
kfree(rtc);
-exit_idr:
- mutex_lock(&idr_lock);
- idr_remove(&rtc_idr, id);
- mutex_unlock(&idr_lock);
+exit_ida:
+ ida_simple_remove(&rtc_ida, id);
exit:
dev_err(dev, "rtc core: unable to register %s, err = %d\n",
@@ -276,7 +262,7 @@ static void __exit rtc_exit(void)
{
rtc_dev_exit();
class_destroy(rtc_class);
- idr_destroy(&rtc_idr);
+ ida_destroy(&rtc_ida);
}
subsys_initcall(rtc_init);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index b2005b44e4f7..62b0763b7b9a 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -34,6 +34,7 @@ enum ds_type {
ds_1388,
ds_3231,
m41t00,
+ mcp7941x,
rx_8025,
// rs5c372 too? different address...
};
@@ -43,6 +44,7 @@ enum ds_type {
#define DS1307_REG_SECS 0x00 /* 00-59 */
# define DS1307_BIT_CH 0x80
# define DS1340_BIT_nEOSC 0x80
+# define MCP7941X_BIT_ST 0x80
#define DS1307_REG_MIN 0x01 /* 00-59 */
#define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */
# define DS1307_BIT_12HR 0x40 /* in REG_HOUR */
@@ -50,6 +52,7 @@ enum ds_type {
# define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */
# define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */
#define DS1307_REG_WDAY 0x03 /* 01-07 */
+# define MCP7941X_BIT_VBATEN 0x08
#define DS1307_REG_MDAY 0x04 /* 01-31 */
#define DS1307_REG_MONTH 0x05 /* 01-12 */
# define DS1337_BIT_CENTURY 0x80 /* in REG_MONTH */
@@ -137,6 +140,8 @@ static const struct chip_desc chips[] = {
},
[m41t00] = {
},
+[mcp7941x] = {
+},
[rx_8025] = {
}, };
@@ -149,6 +154,7 @@ static const struct i2c_device_id ds1307_id[] = {
{ "ds1340", ds_1340 },
{ "ds3231", ds_3231 },
{ "m41t00", m41t00 },
+ { "mcp7941x", mcp7941x },
{ "pt7c4338", ds_1307 },
{ "rx8025", rx_8025 },
{ }
@@ -365,6 +371,10 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
| DS1340_BIT_CENTURY;
break;
+ case mcp7941x:
+ buf[DS1307_REG_SECS] |= MCP7941X_BIT_ST;
+ buf[DS1307_REG_WDAY] |= MCP7941X_BIT_VBATEN;
+ break;
default:
break;
}
@@ -809,6 +819,23 @@ read_rtc:
dev_warn(&client->dev, "SET TIME!\n");
}
break;
+ case mcp7941x:
+ /* make sure that the backup battery is enabled */
+ if (!(ds1307->regs[DS1307_REG_WDAY] & MCP7941X_BIT_VBATEN)) {
+ i2c_smbus_write_byte_data(client, DS1307_REG_WDAY,
+ ds1307->regs[DS1307_REG_WDAY]
+ | MCP7941X_BIT_VBATEN);
+ }
+
+ /* clock halted? turn it on, so clock can tick. */
+ if (!(tmp & MCP7941X_BIT_ST)) {
+ i2c_smbus_write_byte_data(client, DS1307_REG_SECS,
+ MCP7941X_BIT_ST);
+ dev_warn(&client->dev, "SET TIME!\n");
+ goto read_rtc;
+ }
+
+ break;
case rx_8025:
case ds_1337:
case ds_1339:
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index a1a278bc340d..9d0c3b478d55 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -309,7 +309,7 @@ static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev)
return IRQ_HANDLED;
}
-static int __devinit mc13xxx_rtc_probe(struct platform_device *pdev)
+static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
{
int ret;
struct mc13xxx_rtc *priv;
@@ -378,7 +378,7 @@ err_reset_irq_request:
return ret;
}
-static int __devexit mc13xxx_rtc_remove(struct platform_device *pdev)
+static int __exit mc13xxx_rtc_remove(struct platform_device *pdev)
{
struct mc13xxx_rtc *priv = platform_get_drvdata(pdev);
@@ -410,7 +410,7 @@ const struct platform_device_id mc13xxx_rtc_idtable[] = {
static struct platform_driver mc13xxx_rtc_driver = {
.id_table = mc13xxx_rtc_idtable,
- .remove = __devexit_p(mc13xxx_rtc_remove),
+ .remove = __exit_p(mc13xxx_rtc_remove),
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index a1d3ddba99cc..65894f05a801 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -11,7 +11,6 @@
#define KMSG_COMPONENT "dasd"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include <linux/kernel_stat.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -1594,7 +1593,6 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
unsigned long long now;
int expires;
- kstat_cpu(smp_processor_id()).irqs[IOINT_DAS]++;
if (IS_ERR(irb)) {
switch (PTR_ERR(irb)) {
case -EIO:
@@ -2061,13 +2059,14 @@ void dasd_add_request_tail(struct dasd_ccw_req *cqr)
/*
* Wakeup helper for the 'sleep_on' functions.
*/
-static void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data)
+void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data)
{
spin_lock_irq(get_ccwdev_lock(cqr->startdev->cdev));
cqr->callback_data = DASD_SLEEPON_END_TAG;
spin_unlock_irq(get_ccwdev_lock(cqr->startdev->cdev));
wake_up(&generic_waitq);
}
+EXPORT_SYMBOL_GPL(dasd_wakeup_cb);
static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr)
{
@@ -2167,7 +2166,9 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
} else
wait_event(generic_waitq, !(device->stopped));
- cqr->callback = dasd_wakeup_cb;
+ if (!cqr->callback)
+ cqr->callback = dasd_wakeup_cb;
+
cqr->callback_data = DASD_SLEEPON_START_TAG;
dasd_add_request_tail(cqr);
if (interruptible) {
@@ -2263,7 +2264,11 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
cqr->callback = dasd_wakeup_cb;
cqr->callback_data = DASD_SLEEPON_START_TAG;
cqr->status = DASD_CQR_QUEUED;
- list_add(&cqr->devlist, &device->ccw_queue);
+ /*
+ * add new request as second
+ * first the terminated cqr needs to be finished
+ */
+ list_add(&cqr->devlist, device->ccw_queue.next);
/* let the bh start the request to keep them in order */
dasd_schedule_device_bh(device);
@@ -3284,6 +3289,9 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
if (IS_ERR(device))
return PTR_ERR(device);
+ /* mark device as suspended */
+ set_bit(DASD_FLAG_SUSPENDED, &device->flags);
+
if (device->discipline->freeze)
rc = device->discipline->freeze(device);
@@ -3358,6 +3366,7 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
if (device->block)
dasd_schedule_block_bh(device->block);
+ clear_bit(DASD_FLAG_SUSPENDED, &device->flags);
dasd_put_device(device);
return 0;
}
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 6e835c9fdfcb..6ab29680586a 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -844,6 +844,30 @@ static void dasd_eckd_fill_rcd_cqr(struct dasd_device *device,
set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags);
}
+/*
+ * Wakeup helper for read_conf
+ * if the cqr is not done and needs some error recovery
+ * the buffer has to be re-initialized with the EBCDIC "V1.0"
+ * to show support for virtual device SNEQ
+ */
+static void read_conf_cb(struct dasd_ccw_req *cqr, void *data)
+{
+ struct ccw1 *ccw;
+ __u8 *rcd_buffer;
+
+ if (cqr->status != DASD_CQR_DONE) {
+ ccw = cqr->cpaddr;
+ rcd_buffer = (__u8 *)((addr_t) ccw->cda);
+ memset(rcd_buffer, 0, sizeof(*rcd_buffer));
+
+ rcd_buffer[0] = 0xE5;
+ rcd_buffer[1] = 0xF1;
+ rcd_buffer[2] = 0x4B;
+ rcd_buffer[3] = 0xF0;
+ }
+ dasd_wakeup_cb(cqr, data);
+}
+
static int dasd_eckd_read_conf_immediately(struct dasd_device *device,
struct dasd_ccw_req *cqr,
__u8 *rcd_buffer,
@@ -863,6 +887,7 @@ static int dasd_eckd_read_conf_immediately(struct dasd_device *device,
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
cqr->retries = 5;
+ cqr->callback = read_conf_cb;
rc = dasd_sleep_on_immediatly(cqr);
return rc;
}
@@ -900,6 +925,7 @@ static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
goto out_error;
}
dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buf, lpm);
+ cqr->callback = read_conf_cb;
ret = dasd_sleep_on(cqr);
/*
* on success we update the user input parms
@@ -1075,6 +1101,12 @@ static void do_path_verification_work(struct work_struct *work)
data = container_of(work, struct path_verification_work_data, worker);
device = data->device;
+ /* delay path verification until device was resumed */
+ if (test_bit(DASD_FLAG_SUSPENDED, &device->flags)) {
+ schedule_work(work);
+ return;
+ }
+
opm = 0;
npm = 0;
ppm = 0;
@@ -2021,9 +2053,13 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device,
/* first of all check for state change pending interrupt */
mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
if ((scsw_dstat(&irb->scsw) & mask) == mask) {
- /* for alias only and not in offline processing*/
+ /*
+ * for alias only, not in offline processing
+ * and only if not suspended
+ */
if (!device->block && private->lcu &&
- !test_bit(DASD_FLAG_OFFLINE, &device->flags)) {
+ !test_bit(DASD_FLAG_OFFLINE, &device->flags) &&
+ !test_bit(DASD_FLAG_SUSPENDED, &device->flags)) {
/*
* the state change could be caused by an alias
* reassignment remove device from alias handling
@@ -2350,7 +2386,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
new_track = 1;
end_idaw = 0;
len_to_track_end = 0;
- idaw_dst = 0;
+ idaw_dst = NULL;
idaw_len = 0;
rq_for_each_segment(bv, req, iter) {
dst = page_address(bv->bv_page) + bv->bv_offset;
@@ -2412,7 +2448,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
if (end_idaw) {
idaws = idal_create_words(idaws, idaw_dst,
idaw_len);
- idaw_dst = 0;
+ idaw_dst = NULL;
idaw_len = 0;
end_idaw = 0;
}
@@ -3998,6 +4034,7 @@ static struct ccw_driver dasd_eckd_driver = {
.thaw = dasd_generic_restore_device,
.restore = dasd_generic_restore_device,
.uc_handler = dasd_generic_uc_handler,
+ .int_class = IOINT_DAS,
};
/*
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 4b71b1164868..a62a75358eb9 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -79,6 +79,7 @@ static struct ccw_driver dasd_fba_driver = {
.freeze = dasd_generic_pm_freeze,
.thaw = dasd_generic_restore_device,
.restore = dasd_generic_restore_device,
+ .int_class = IOINT_DAS,
};
static void
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 1dd12bd85a69..afe8c33422ed 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -516,6 +516,7 @@ struct dasd_block {
*/
#define DASD_FLAG_IS_RESERVED 7 /* The device is reserved */
#define DASD_FLAG_LOCK_STOLEN 8 /* The device lock was stolen */
+#define DASD_FLAG_SUSPENDED 9 /* The device was suspended */
void dasd_put_device_wake(struct dasd_device *);
@@ -643,6 +644,7 @@ struct dasd_ccw_req *
dasd_smalloc_request(int , int, int, struct dasd_device *);
void dasd_kfree_request(struct dasd_ccw_req *, struct dasd_device *);
void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *);
+void dasd_wakeup_cb(struct dasd_ccw_req *, void *);
static inline int
dasd_kmalloc_set_cda(struct ccw1 *ccw, void *cda, struct dasd_device *device)
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 694464c65fcd..934458ad55e5 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -9,7 +9,6 @@
* Dan Morrison, IBM Corporation <dmorriso@cse.buffalo.edu>
*/
-#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
@@ -362,7 +361,6 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
int cstat, dstat;
int count;
- kstat_cpu(smp_processor_id()).irqs[IOINT_C15]++;
raw = dev_get_drvdata(&cdev->dev);
req = (struct raw3215_req *) intparm;
cstat = irb->scsw.cmd.cstat;
@@ -776,6 +774,7 @@ static struct ccw_driver raw3215_ccw_driver = {
.freeze = &raw3215_pm_stop,
.thaw = &raw3215_pm_start,
.restore = &raw3215_pm_start,
+ .int_class = IOINT_C15,
};
#ifdef CONFIG_TN3215_CONSOLE
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 810ac38631c3..e5cb9248a442 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -7,7 +7,6 @@
* Copyright IBM Corp. 2003, 2009
*/
-#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -330,7 +329,6 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
struct raw3270_request *rq;
int rc;
- kstat_cpu(smp_processor_id()).irqs[IOINT_C70]++;
rp = dev_get_drvdata(&cdev->dev);
if (!rp)
return;
@@ -1398,6 +1396,7 @@ static struct ccw_driver raw3270_ccw_driver = {
.freeze = &raw3270_pm_stop,
.thaw = &raw3270_pm_start,
.restore = &raw3270_pm_start,
+ .int_class = IOINT_C70,
};
static int
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 837e010299a8..0b54a91f8dcd 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -61,8 +61,8 @@ static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
rc = sclp_service_call(cmd, sccb);
if (rc)
goto out;
- __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
- PSW_MASK_WAIT | PSW_DEFAULT_KEY);
+ __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA |
+ PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT);
local_irq_disable();
out:
/* Contents of the sccb might have changed. */
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index a90a02c28d6a..87fc0ac11e67 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -30,7 +30,8 @@ static void do_machine_quiesce(void)
psw_t quiesce_psw;
smp_send_stop();
- quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
+ quiesce_psw.mask =
+ PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA | PSW_MASK_WAIT;
quiesce_psw.addr = 0xfff;
__load_psw(quiesce_psw);
}
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 9eff2df70ddb..934ef33eb9a4 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1330,6 +1330,7 @@ static struct ccw_driver tape_34xx_driver = {
.set_online = tape_34xx_online,
.set_offline = tape_generic_offline,
.freeze = tape_generic_pm_suspend,
+ .int_class = IOINT_TAP,
};
static int
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index a7d570728882..49c6aab7ad78 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -1762,6 +1762,7 @@ static struct ccw_driver tape_3590_driver = {
.set_offline = tape_generic_offline,
.set_online = tape_3590_online,
.freeze = tape_generic_pm_suspend,
+ .int_class = IOINT_TAP,
};
/*
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 7978a0adeaf3..b3a3e8e8656e 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -14,7 +14,6 @@
#define KMSG_COMPONENT "tape"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/init.h> // for kernel parameters
#include <linux/kmod.h> // for requesting modules
@@ -1115,7 +1114,6 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
struct tape_request *request;
int rc;
- kstat_cpu(smp_processor_id()).irqs[IOINT_TAP]++;
device = dev_get_drvdata(&cdev->dev);
if (device == NULL) {
return;
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index f6b00c3df425..d291a54acfad 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -11,7 +11,6 @@
#define KMSG_COMPONENT "vmur"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include <linux/kernel_stat.h>
#include <linux/cdev.h>
#include <linux/slab.h>
@@ -74,6 +73,7 @@ static struct ccw_driver ur_driver = {
.set_online = ur_set_online,
.set_offline = ur_set_offline,
.freeze = ur_pm_suspend,
+ .int_class = IOINT_VMR,
};
static DEFINE_MUTEX(vmur_mutex);
@@ -305,7 +305,6 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
{
struct urdev *urd;
- kstat_cpu(smp_processor_id()).irqs[IOINT_VMR]++;
TRACE("ur_int_handler: intparm=0x%lx cstat=%02x dstat=%02x res=%u\n",
intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
irb->scsw.cmd.count);
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 3b94044027c2..43068fbd0baa 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/debugfs.h>
+#include <linux/module.h>
#include <asm/asm-offsets.h>
#include <asm/ipl.h>
#include <asm/sclp.h>
@@ -142,22 +143,6 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
return memcpy_hsa(dest, src, count, TO_KERNEL);
}
-static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
-{
- static char buf[4096];
- int offs = 0, size;
-
- while (offs < count) {
- size = min(sizeof(buf), count - offs);
- if (memcpy_real(buf, (void *) src + offs, size))
- return -EFAULT;
- if (copy_to_user(dest + offs, buf, size))
- return -EFAULT;
- offs += size;
- }
- return 0;
-}
-
static int __init init_cpu_info(enum arch_id arch)
{
struct save_area *sa;
@@ -346,8 +331,8 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count,
/* Copy from real mem */
size = count - mem_offs - hdr_count;
- rc = memcpy_real_user(buf + hdr_count + mem_offs, mem_start + mem_offs,
- size);
+ rc = copy_to_user_real(buf + hdr_count + mem_offs,
+ (void *) mem_start + mem_offs, size);
if (rc)
goto fail;
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 76058a5166ed..08c66035dd19 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -335,10 +335,9 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
return -EINVAL;
if (user_len > 65536)
user_len = 65536;
- buf = vmalloc (user_len + 1); /* maybe better use the stack? */
+ buf = vzalloc(user_len + 1); /* maybe better use the stack? */
if (buf == NULL)
return -ENOMEM;
- memset(buf, 0, user_len + 1);
if (strncpy_from_user (buf, user_buf, user_len) < 0) {
rc = -EFAULT;
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 5c567414c4bb..4f1989d27b1f 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -29,31 +29,20 @@
/* a device matches a driver if all its slave devices match the same
* entry of the driver */
-static int
-ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
+static int ccwgroup_bus_match(struct device *dev, struct device_driver * drv)
{
- struct ccwgroup_device *gdev;
- struct ccwgroup_driver *gdrv;
-
- gdev = to_ccwgroupdev(dev);
- gdrv = to_ccwgroupdrv(drv);
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(drv);
if (gdev->creator_id == gdrv->driver_id)
return 1;
return 0;
}
-static int
-ccwgroup_uevent (struct device *dev, struct kobj_uevent_env *env)
-{
- /* TODO */
- return 0;
-}
static struct bus_type ccwgroup_bus_type;
-static void
-__ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
+static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
{
int i;
char str[8];
@@ -63,7 +52,6 @@ __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
sysfs_remove_link(&gdev->dev.kobj, str);
sysfs_remove_link(&gdev->cdev[i]->dev.kobj, "group_device");
}
-
}
/*
@@ -87,6 +75,87 @@ static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev)
}
}
+static int ccwgroup_set_online(struct ccwgroup_device *gdev)
+{
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
+ int ret = 0;
+
+ if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
+ return -EAGAIN;
+ if (gdev->state == CCWGROUP_ONLINE)
+ goto out;
+ if (gdrv->set_online)
+ ret = gdrv->set_online(gdev);
+ if (ret)
+ goto out;
+
+ gdev->state = CCWGROUP_ONLINE;
+out:
+ atomic_set(&gdev->onoff, 0);
+ return ret;
+}
+
+static int ccwgroup_set_offline(struct ccwgroup_device *gdev)
+{
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
+ int ret = 0;
+
+ if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
+ return -EAGAIN;
+ if (gdev->state == CCWGROUP_OFFLINE)
+ goto out;
+ if (gdrv->set_offline)
+ ret = gdrv->set_offline(gdev);
+ if (ret)
+ goto out;
+
+ gdev->state = CCWGROUP_OFFLINE;
+out:
+ atomic_set(&gdev->onoff, 0);
+ return ret;
+}
+
+static ssize_t ccwgroup_online_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
+ unsigned long value;
+ int ret;
+
+ if (!dev->driver)
+ return -EINVAL;
+ if (!try_module_get(gdrv->driver.owner))
+ return -EINVAL;
+
+ ret = strict_strtoul(buf, 0, &value);
+ if (ret)
+ goto out;
+
+ if (value == 1)
+ ret = ccwgroup_set_online(gdev);
+ else if (value == 0)
+ ret = ccwgroup_set_offline(gdev);
+ else
+ ret = -EINVAL;
+out:
+ module_put(gdrv->driver.owner);
+ return (ret == 0) ? count : ret;
+}
+
+static ssize_t ccwgroup_online_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ int online;
+
+ online = (gdev->state == CCWGROUP_ONLINE) ? 1 : 0;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", online);
+}
+
/*
* Provide an 'ungroup' attribute so the user can remove group devices no
* longer needed or accidentially created. Saves memory :)
@@ -104,14 +173,13 @@ static void ccwgroup_ungroup_callback(struct device *dev)
mutex_unlock(&gdev->reg_mutex);
}
-static ssize_t
-ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t ccwgroup_ungroup_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct ccwgroup_device *gdev;
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
int rc;
- gdev = to_ccwgroupdev(dev);
-
/* Prevent concurrent online/offline processing and ungrouping. */
if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
return -EAGAIN;
@@ -132,24 +200,35 @@ out:
}
return count;
}
-
static DEVICE_ATTR(ungroup, 0200, NULL, ccwgroup_ungroup_store);
+static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store);
-static void
-ccwgroup_release (struct device *dev)
+static struct attribute *ccwgroup_attrs[] = {
+ &dev_attr_online.attr,
+ &dev_attr_ungroup.attr,
+ NULL,
+};
+static struct attribute_group ccwgroup_attr_group = {
+ .attrs = ccwgroup_attrs,
+};
+static const struct attribute_group *ccwgroup_attr_groups[] = {
+ &ccwgroup_attr_group,
+ NULL,
+};
+
+static void ccwgroup_release(struct device *dev)
{
kfree(to_ccwgroupdev(dev));
}
-static int
-__ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
+static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
{
char str[8];
int i, rc;
for (i = 0; i < gdev->count; i++) {
- rc = sysfs_create_link(&gdev->cdev[i]->dev.kobj, &gdev->dev.kobj,
- "group_device");
+ rc = sysfs_create_link(&gdev->cdev[i]->dev.kobj,
+ &gdev->dev.kobj, "group_device");
if (rc) {
for (--i; i >= 0; i--)
sysfs_remove_link(&gdev->cdev[i]->dev.kobj,
@@ -159,8 +238,8 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
}
for (i = 0; i < gdev->count; i++) {
sprintf(str, "cdev%d", i);
- rc = sysfs_create_link(&gdev->dev.kobj, &gdev->cdev[i]->dev.kobj,
- str);
+ rc = sysfs_create_link(&gdev->dev.kobj,
+ &gdev->cdev[i]->dev.kobj, str);
if (rc) {
for (--i; i >= 0; i--) {
sprintf(str, "cdev%d", i);
@@ -293,26 +372,17 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
}
dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev));
-
+ gdev->dev.groups = ccwgroup_attr_groups;
rc = device_add(&gdev->dev);
if (rc)
goto error;
- get_device(&gdev->dev);
- rc = device_create_file(&gdev->dev, &dev_attr_ungroup);
-
+ rc = __ccwgroup_create_symlinks(gdev);
if (rc) {
- device_unregister(&gdev->dev);
+ device_del(&gdev->dev);
goto error;
}
-
- rc = __ccwgroup_create_symlinks(gdev);
- if (!rc) {
- mutex_unlock(&gdev->reg_mutex);
- put_device(&gdev->dev);
- return 0;
- }
- device_remove_file(&gdev->dev, &dev_attr_ungroup);
- device_unregister(&gdev->dev);
+ mutex_unlock(&gdev->reg_mutex);
+ return 0;
error:
for (i = 0; i < num_devices; i++)
if (gdev->cdev[i]) {
@@ -330,7 +400,15 @@ error:
EXPORT_SYMBOL(ccwgroup_create_from_string);
static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
- void *data);
+ void *data)
+{
+ struct device *dev = data;
+
+ if (action == BUS_NOTIFY_UNBIND_DRIVER)
+ device_schedule_callback(dev, ccwgroup_ungroup_callback);
+
+ return NOTIFY_OK;
+}
static struct notifier_block ccwgroup_nb = {
.notifier_call = ccwgroup_notifier
@@ -362,138 +440,21 @@ module_exit(cleanup_ccwgroup);
/************************** driver stuff ******************************/
-static int
-ccwgroup_set_online(struct ccwgroup_device *gdev)
+static int ccwgroup_probe(struct device *dev)
{
- struct ccwgroup_driver *gdrv;
- int ret;
-
- if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
- return -EAGAIN;
- if (gdev->state == CCWGROUP_ONLINE) {
- ret = 0;
- goto out;
- }
- if (!gdev->dev.driver) {
- ret = -EINVAL;
- goto out;
- }
- gdrv = to_ccwgroupdrv (gdev->dev.driver);
- if ((ret = gdrv->set_online ? gdrv->set_online(gdev) : 0))
- goto out;
-
- gdev->state = CCWGROUP_ONLINE;
- out:
- atomic_set(&gdev->onoff, 0);
- return ret;
-}
-
-static int
-ccwgroup_set_offline(struct ccwgroup_device *gdev)
-{
- struct ccwgroup_driver *gdrv;
- int ret;
-
- if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
- return -EAGAIN;
- if (gdev->state == CCWGROUP_OFFLINE) {
- ret = 0;
- goto out;
- }
- if (!gdev->dev.driver) {
- ret = -EINVAL;
- goto out;
- }
- gdrv = to_ccwgroupdrv (gdev->dev.driver);
- if ((ret = gdrv->set_offline ? gdrv->set_offline(gdev) : 0))
- goto out;
-
- gdev->state = CCWGROUP_OFFLINE;
- out:
- atomic_set(&gdev->onoff, 0);
- return ret;
-}
-
-static ssize_t
-ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
- struct ccwgroup_device *gdev;
- struct ccwgroup_driver *gdrv;
- unsigned long value;
- int ret;
-
- if (!dev->driver)
- return -ENODEV;
-
- gdev = to_ccwgroupdev(dev);
- gdrv = to_ccwgroupdrv(dev->driver);
-
- if (!try_module_get(gdrv->driver.owner))
- return -EINVAL;
-
- ret = strict_strtoul(buf, 0, &value);
- if (ret)
- goto out;
-
- if (value == 1)
- ret = ccwgroup_set_online(gdev);
- else if (value == 0)
- ret = ccwgroup_set_offline(gdev);
- else
- ret = -EINVAL;
-out:
- module_put(gdrv->driver.owner);
- return (ret == 0) ? count : ret;
-}
-
-static ssize_t
-ccwgroup_online_show (struct device *dev, struct device_attribute *attr, char *buf)
-{
- int online;
-
- online = (to_ccwgroupdev(dev)->state == CCWGROUP_ONLINE);
-
- return sprintf(buf, online ? "1\n" : "0\n");
-}
-
-static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store);
-
-static int
-ccwgroup_probe (struct device *dev)
-{
- struct ccwgroup_device *gdev;
- struct ccwgroup_driver *gdrv;
-
- int ret;
-
- gdev = to_ccwgroupdev(dev);
- gdrv = to_ccwgroupdrv(dev->driver);
-
- if ((ret = device_create_file(dev, &dev_attr_online)))
- return ret;
-
- ret = gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
- if (ret)
- device_remove_file(dev, &dev_attr_online);
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
- return ret;
+ return gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
}
-static int
-ccwgroup_remove (struct device *dev)
+static int ccwgroup_remove(struct device *dev)
{
- struct ccwgroup_device *gdev;
- struct ccwgroup_driver *gdrv;
-
- device_remove_file(dev, &dev_attr_online);
- device_remove_file(dev, &dev_attr_ungroup);
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
if (!dev->driver)
return 0;
-
- gdev = to_ccwgroupdev(dev);
- gdrv = to_ccwgroupdrv(dev->driver);
-
if (gdrv->remove)
gdrv->remove(gdev);
@@ -502,15 +463,11 @@ ccwgroup_remove (struct device *dev)
static void ccwgroup_shutdown(struct device *dev)
{
- struct ccwgroup_device *gdev;
- struct ccwgroup_driver *gdrv;
+ struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
if (!dev->driver)
return;
-
- gdev = to_ccwgroupdev(dev);
- gdrv = to_ccwgroupdrv(dev->driver);
-
if (gdrv->shutdown)
gdrv->shutdown(gdev);
}
@@ -586,26 +543,12 @@ static const struct dev_pm_ops ccwgroup_pm_ops = {
static struct bus_type ccwgroup_bus_type = {
.name = "ccwgroup",
.match = ccwgroup_bus_match,
- .uevent = ccwgroup_uevent,
.probe = ccwgroup_probe,
.remove = ccwgroup_remove,
.shutdown = ccwgroup_shutdown,
.pm = &ccwgroup_pm_ops,
};
-
-static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
- void *data)
-{
- struct device *dev = data;
-
- if (action == BUS_NOTIFY_UNBIND_DRIVER)
- device_schedule_callback(dev, ccwgroup_ungroup_callback);
-
- return NOTIFY_OK;
-}
-
-
/**
* ccwgroup_driver_register() - register a ccw group driver
* @cdriver: driver to be registered
@@ -619,9 +562,9 @@ int ccwgroup_driver_register(struct ccwgroup_driver *cdriver)
return driver_register(&cdriver->driver);
}
+EXPORT_SYMBOL(ccwgroup_driver_register);
-static int
-__ccwgroup_match_all(struct device *dev, void *data)
+static int __ccwgroup_match_all(struct device *dev, void *data)
{
return 1;
}
@@ -652,6 +595,7 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver)
put_driver(&cdriver->driver);
driver_unregister(&cdriver->driver);
}
+EXPORT_SYMBOL(ccwgroup_driver_unregister);
/**
* ccwgroup_probe_ccwdev() - probe function for slave devices
@@ -666,6 +610,7 @@ int ccwgroup_probe_ccwdev(struct ccw_device *cdev)
{
return 0;
}
+EXPORT_SYMBOL(ccwgroup_probe_ccwdev);
/**
* ccwgroup_remove_ccwdev() - remove function for slave devices
@@ -702,9 +647,5 @@ void ccwgroup_remove_ccwdev(struct ccw_device *cdev)
/* Release ccwgroup device reference for local processing. */
put_device(&gdev->dev);
}
-
-MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(ccwgroup_driver_register);
-EXPORT_SYMBOL(ccwgroup_driver_unregister);
-EXPORT_SYMBOL(ccwgroup_probe_ccwdev);
EXPORT_SYMBOL(ccwgroup_remove_ccwdev);
+MODULE_LICENSE("GPL");
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c
index d15f8b4d78bd..5156264d0c74 100644
--- a/drivers/s390/cio/ccwreq.c
+++ b/drivers/s390/cio/ccwreq.c
@@ -1,10 +1,13 @@
/*
* Handling of internal CCW device requests.
*
- * Copyright IBM Corp. 2009
+ * Copyright IBM Corp. 2009, 2011
* Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
*/
+#define KMSG_COMPONENT "cio"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/types.h>
#include <linux/err.h>
#include <asm/ccwdev.h>
@@ -323,7 +326,21 @@ void ccw_request_timeout(struct ccw_device *cdev)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
struct ccw_request *req = &cdev->private->req;
- int rc;
+ int rc = -ENODEV, chp;
+
+ if (cio_update_schib(sch))
+ goto err;
+
+ for (chp = 0; chp < 8; chp++) {
+ if ((0x80 >> chp) & sch->schib.pmcw.lpum)
+ pr_warning("%s: No interrupt was received within %lus "
+ "(CS=%02x, DS=%02x, CHPID=%x.%02x)\n",
+ dev_name(&cdev->dev), req->timeout / HZ,
+ scsw_cstat(&sch->schib.scsw),
+ scsw_dstat(&sch->schib.scsw),
+ sch->schid.cssid,
+ sch->schib.pmcw.chpid[chp]);
+ }
if (!ccwreq_next_path(cdev)) {
/* set the final return code for this request */
@@ -342,7 +359,7 @@ err:
* ccw_request_notoper - notoper handler for I/O request procedure
* @cdev: ccw device
*
- * Handle timeout during I/O request procedure.
+ * Handle notoper during I/O request procedure.
*/
void ccw_request_notoper(struct ccw_device *cdev)
{
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index e950f1ad4dd1..0c87b0fc7714 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -1,7 +1,7 @@
/*
* Driver for s390 chsc subchannels
*
- * Copyright IBM Corp. 2008, 2009
+ * Copyright IBM Corp. 2008, 2011
*
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
*
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
+#include <linux/kernel_stat.h>
#include <asm/compat.h>
#include <asm/cio.h>
@@ -56,6 +57,8 @@ static void chsc_subchannel_irq(struct subchannel *sch)
CHSC_LOG(4, "irb");
CHSC_LOG_HEX(4, irb, sizeof(*irb));
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CSC]++;
+
/* Copy irb to provided request and set done. */
if (!request) {
CHSC_MSG(0, "Interrupt on sch 0.%x.%04x with no request\n",
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index eb3140ee821e..dc67c397449e 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -622,6 +622,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
if (!sch) {
/* Clear pending interrupt condition. */
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
tsch(tpi_info->schid, irb);
continue;
}
@@ -634,7 +635,10 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
/* Call interrupt handler if there is one. */
if (sch->driver && sch->driver->irq)
sch->driver->irq(sch);
- }
+ else
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+ } else
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
spin_unlock(sch->lock);
/*
* Are more interrupts pending?
@@ -667,18 +671,23 @@ static int cio_tpi(void)
tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id;
if (tpi(NULL) != 1)
return 0;
+ kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
if (tpi_info->adapter_IO) {
do_adapter_IO(tpi_info->isc);
return 1;
}
irb = (struct irb *)&S390_lowcore.irb;
/* Store interrupt response block to lowcore. */
- if (tsch(tpi_info->schid, irb) != 0)
+ if (tsch(tpi_info->schid, irb) != 0) {
/* Not status pending or not operational. */
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
return 1;
+ }
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
- if (!sch)
+ if (!sch) {
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
return 1;
+ }
irq_context = in_interrupt();
if (!irq_context)
local_bh_disable();
@@ -687,6 +696,8 @@ static int cio_tpi(void)
memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
if (sch->driver && sch->driver->irq)
sch->driver->irq(sch);
+ else
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
spin_unlock(sch->lock);
irq_exit();
if (!irq_context)
@@ -1058,7 +1069,7 @@ void reipl_ccw_dev(struct ccw_dev_id *devid)
{
struct subchannel_id schid;
- s390_reset_system();
+ s390_reset_system(NULL, NULL);
if (reipl_find_schid(devid, &schid) != 0)
panic("IPL Device not found\n");
do_reipl_asm(*((__u32*)&schid));
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 80ebdddf7747..33bb4d891e16 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -133,6 +133,8 @@ struct channel_subsystem {
extern struct channel_subsystem *channel_subsystems[];
+void channel_subsystem_reinit(void);
+
/* Helper functions to build lists for the slow path. */
void css_schedule_eval(struct subchannel_id schid);
void css_schedule_eval_all(void);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 8e04c00cf0ad..d734f4a0ecac 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -21,6 +21,7 @@
#include <linux/device.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
+#include <linux/kernel_stat.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
@@ -747,6 +748,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
struct ccw_device *cdev)
{
cdev->private->cdev = cdev;
+ cdev->private->int_class = IOINT_CIO;
atomic_set(&cdev->private->onoff, 0);
cdev->dev.parent = &sch->dev;
cdev->dev.release = ccw_device_release;
@@ -1010,6 +1012,8 @@ static void io_subchannel_irq(struct subchannel *sch)
CIO_TRACE_EVENT(6, dev_name(&sch->dev));
if (cdev)
dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
+ else
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
}
void io_subchannel_init_config(struct subchannel *sch)
@@ -1621,6 +1625,7 @@ ccw_device_probe_console(void)
memset(&console_private, 0, sizeof(struct ccw_device_private));
console_cdev.private = &console_private;
console_private.cdev = &console_cdev;
+ console_private.int_class = IOINT_CIO;
ret = ccw_device_console_enable(&console_cdev, sch);
if (ret) {
cio_release_console();
@@ -1702,11 +1707,18 @@ ccw_device_probe (struct device *dev)
int ret;
cdev->drv = cdrv; /* to let the driver call _set_online */
+ /* Note: we interpret class 0 in this context as an uninitialized
+ * field since it translates to a non-I/O interrupt class. */
+ if (cdrv->int_class != 0)
+ cdev->private->int_class = cdrv->int_class;
+ else
+ cdev->private->int_class = IOINT_CIO;
ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV;
if (ret) {
cdev->drv = NULL;
+ cdev->private->int_class = IOINT_CIO;
return ret;
}
@@ -1740,6 +1752,7 @@ ccw_device_remove (struct device *dev)
}
ccw_device_set_timeout(cdev, 0);
cdev->drv = NULL;
+ cdev->private->int_class = IOINT_CIO;
return 0;
}
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 0b7245c72d5e..179824b3082f 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -5,6 +5,7 @@
#include <linux/atomic.h>
#include <linux/wait.h>
#include <linux/notifier.h>
+#include <linux/kernel_stat.h>
#include "io_sch.h"
/*
@@ -56,7 +57,17 @@ extern fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS];
static inline void
dev_fsm_event(struct ccw_device *cdev, enum dev_event dev_event)
{
- dev_jumptable[cdev->private->state][dev_event](cdev, dev_event);
+ int state = cdev->private->state;
+
+ if (dev_event == DEV_EVENT_INTERRUPT) {
+ if (state == DEV_STATE_ONLINE)
+ kstat_cpu(smp_processor_id()).
+ irqs[cdev->private->int_class]++;
+ else if (state != DEV_STATE_CMFCHANGE &&
+ state != DEV_STATE_CMFUPDATE)
+ kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+ }
+ dev_jumptable[state][dev_event](cdev, dev_event);
}
/*
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
index ba31ad88f4f7..2ebb492a5c17 100644
--- a/drivers/s390/cio/io_sch.h
+++ b/drivers/s390/cio/io_sch.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <asm/schid.h>
#include <asm/ccwdev.h>
+#include <asm/irq.h>
#include "css.h"
#include "orb.h"
@@ -157,6 +158,7 @@ struct ccw_device_private {
struct list_head cmb_list; /* list of measured devices */
u64 cmb_start_time; /* clock value of cmb reset */
void *cmb_wait; /* deferred cmb enable/disable */
+ enum interruption_class int_class;
};
static inline int rsch(struct subchannel_id schid)
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index e5c966462c5a..b962ffbc0803 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -18,14 +18,6 @@
#define QDIO_BUSY_BIT_RETRIES 1000 /* = 10s retry time */
#define QDIO_INPUT_THRESHOLD (500 << 12) /* 500 microseconds */
-/*
- * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait
- * till next initiative to give transmitted skbs back to the stack is too long.
- * Therefore polling is started in case of multicast queue is filled more
- * than 50 percent.
- */
-#define QDIO_IQDIO_POLL_LVL 65 /* HS multicast queue */
-
enum qdio_irq_states {
QDIO_IRQ_STATE_INACTIVE,
QDIO_IRQ_STATE_ESTABLISHED,
@@ -44,6 +36,7 @@ enum qdio_irq_states {
#define SLSB_STATE_NOT_INIT 0x0
#define SLSB_STATE_EMPTY 0x1
#define SLSB_STATE_PRIMED 0x2
+#define SLSB_STATE_PENDING 0x3
#define SLSB_STATE_HALTED 0xe
#define SLSB_STATE_ERROR 0xf
#define SLSB_TYPE_INPUT 0x0
@@ -67,6 +60,8 @@ enum qdio_irq_states {
(SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_NOT_INIT) /* 0xa0 */
#define SLSB_P_OUTPUT_EMPTY \
(SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_EMPTY) /* 0xa1 */
+#define SLSB_P_OUTPUT_PENDING \
+ (SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_PENDING) /* 0xa3 */
#define SLSB_CU_OUTPUT_PRIMED \
(SLSB_OWNER_CU | SLSB_TYPE_OUTPUT | SLSB_STATE_PRIMED) /* 0x62 */
#define SLSB_P_OUTPUT_HALTED \
@@ -84,19 +79,11 @@ enum qdio_irq_states {
#define CHSC_FLAG_QDIO_CAPABILITY 0x80
#define CHSC_FLAG_VALIDITY 0x40
-/* qdio adapter-characteristics-1 flag */
-#define AC1_SIGA_INPUT_NEEDED 0x40 /* process input queues */
-#define AC1_SIGA_OUTPUT_NEEDED 0x20 /* process output queues */
-#define AC1_SIGA_SYNC_NEEDED 0x10 /* ask hypervisor to sync */
-#define AC1_AUTOMATIC_SYNC_ON_THININT 0x08 /* set by hypervisor */
-#define AC1_AUTOMATIC_SYNC_ON_OUT_PCI 0x04 /* set by hypervisor */
-#define AC1_SC_QEBSM_AVAILABLE 0x02 /* available for subchannel */
-#define AC1_SC_QEBSM_ENABLED 0x01 /* enabled for subchannel */
-
/* SIGA flags */
#define QDIO_SIGA_WRITE 0x00
#define QDIO_SIGA_READ 0x01
#define QDIO_SIGA_SYNC 0x02
+#define QDIO_SIGA_WRITEQ 0x04
#define QDIO_SIGA_QEBSM_FLAG 0x80
#ifdef CONFIG_64BIT
@@ -253,6 +240,12 @@ struct qdio_input_q {
struct qdio_output_q {
/* PCIs are enabled for the queue */
int pci_out_enabled;
+ /* cq: use asynchronous output buffers */
+ int use_cq;
+ /* cq: aobs used for particual SBAL */
+ struct qaob **aobs;
+ /* cq: sbal state related to asynchronous operation */
+ struct qdio_outbuf_state *sbal_state;
/* timer to check for more outbound work */
struct timer_list timer;
/* used SBALs before tasklet schedule */
@@ -289,6 +282,9 @@ struct qdio_q {
/* error condition during a data transfer */
unsigned int qdio_error;
+ /* last scan of the queue */
+ u64 timestamp;
+
struct tasklet_struct tasklet;
struct qdio_queue_perf_stat q_stats;
@@ -422,20 +418,7 @@ static inline int multicast_outbound(struct qdio_q *q)
#define queue_irqs_disabled(q) \
(test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) != 0)
-#define TIQDIO_SHARED_IND 63
-
-/* device state change indicators */
-struct indicator_t {
- u32 ind; /* u32 because of compare-and-swap performance */
- atomic_t count; /* use count, 0 or 1 for non-shared indicators */
-};
-
-extern struct indicator_t *q_indicators;
-
-static inline int shared_ind(u32 *dsci)
-{
- return dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
-}
+extern u64 last_ai_time;
/* prototypes for thin interrupt */
void qdio_setup_thinint(struct qdio_irq *irq_ptr);
@@ -448,6 +431,8 @@ int tiqdio_allocate_memory(void);
void tiqdio_free_memory(void);
int tiqdio_register_thinints(void);
void tiqdio_unregister_thinints(void);
+void clear_nonshared_ind(struct qdio_irq *);
+int test_nonshared_ind(struct qdio_irq *);
/* prototypes for setup */
void qdio_inbound_processing(unsigned long data);
@@ -469,6 +454,9 @@ int qdio_setup_create_sysfs(struct ccw_device *cdev);
void qdio_setup_destroy_sysfs(struct ccw_device *cdev);
int qdio_setup_init(void);
void qdio_setup_exit(void);
+int qdio_enable_async_operation(struct qdio_output_q *q);
+void qdio_disable_async_operation(struct qdio_output_q *q);
+struct qaob *qdio_allocate_aob(void);
int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
unsigned char *state);
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index 0e615cb912d0..ed68245f9741 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -54,15 +54,17 @@ static int qstat_show(struct seq_file *m, void *v)
if (!q)
return 0;
- seq_printf(m, "DSCI: %d nr_used: %d\n",
- *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
- seq_printf(m, "ftc: %d last_move: %d\n",
+ seq_printf(m, "Timestamp: %Lx Last AI: %Lx\n",
+ q->timestamp, last_ai_time);
+ seq_printf(m, "nr_used: %d ftc: %d last_move: %d\n",
+ atomic_read(&q->nr_buf_used),
q->first_to_check, q->last_move);
if (q->is_input_q) {
seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
q->u.in.polling, q->u.in.ack_start,
q->u.in.ack_count);
- seq_printf(m, "IRQs disabled: %u\n",
+ seq_printf(m, "DSCI: %d IRQs disabled: %u\n",
+ *(u32 *)q->irq_ptr->dsci,
test_bit(QDIO_QUEUE_IRQS_DISABLED,
&q->u.in.queue_irq_state));
}
@@ -76,6 +78,9 @@ static int qstat_show(struct seq_file *m, void *v)
case SLSB_P_OUTPUT_NOT_INIT:
seq_printf(m, "N");
break;
+ case SLSB_P_OUTPUT_PENDING:
+ seq_printf(m, "P");
+ break;
case SLSB_P_INPUT_PRIMED:
case SLSB_CU_OUTPUT_PRIMED:
seq_printf(m, "+");
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 288c9140290e..3ef8d071c64a 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -14,7 +14,7 @@
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/gfp.h>
-#include <linux/kernel_stat.h>
+#include <linux/io.h>
#include <linux/atomic.h>
#include <asm/debug.h>
#include <asm/qdio.h>
@@ -77,11 +77,13 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask,
* Note: For IQDC unicast queues only the highest priority queue is processed.
*/
static inline int do_siga_output(unsigned long schid, unsigned long mask,
- unsigned int *bb, unsigned int fc)
+ unsigned int *bb, unsigned int fc,
+ unsigned long aob)
{
register unsigned long __fc asm("0") = fc;
register unsigned long __schid asm("1") = schid;
register unsigned long __mask asm("2") = mask;
+ register unsigned long __aob asm("3") = aob;
int cc = QDIO_ERROR_SIGA_ACCESS_EXCEPTION;
asm volatile(
@@ -90,7 +92,8 @@ static inline int do_siga_output(unsigned long schid, unsigned long mask,
" srl %0,28\n"
"1:\n"
EX_TABLE(0b, 1b)
- : "+d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask)
+ : "+d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask),
+ "+d" (__aob)
: : "cc", "memory");
*bb = ((unsigned int) __fc) >> 31;
return cc;
@@ -101,9 +104,12 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
/* all done or next buffer state different */
if (ccq == 0 || ccq == 32)
return 0;
- /* not all buffers processed */
- if (ccq == 96 || ccq == 97)
+ /* no buffer processed */
+ if (ccq == 97)
return 1;
+ /* not all buffers processed */
+ if (ccq == 96)
+ return 2;
/* notify devices immediately */
DBF_ERROR("%4x ccq:%3d", SCH_NO(q), ccq);
return -EIO;
@@ -123,10 +129,8 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
int start, int count, int auto_ack)
{
+ int rc, tmp_count = count, tmp_start = start, nr = q->nr, retried = 0;
unsigned int ccq = 0;
- int tmp_count = count, tmp_start = start;
- int nr = q->nr;
- int rc;
BUG_ON(!q->irq_ptr->sch_token);
qperf_inc(q, eqbs);
@@ -137,29 +141,34 @@ again:
ccq = do_eqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count,
auto_ack);
rc = qdio_check_ccq(q, ccq);
-
- /* At least one buffer was processed, return and extract the remaining
- * buffers later.
- */
- if ((ccq == 96) && (count != tmp_count)) {
- qperf_inc(q, eqbs_partial);
- return (count - tmp_count);
- }
+ if (!rc)
+ return count - tmp_count;
if (rc == 1) {
DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS again:%2d", ccq);
goto again;
}
- if (rc < 0) {
- DBF_ERROR("%4x EQBS ERROR", SCH_NO(q));
- DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
- q->handler(q->irq_ptr->cdev,
- QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
- 0, -1, -1, q->irq_ptr->int_parm);
- return 0;
+ if (rc == 2) {
+ BUG_ON(tmp_count == count);
+ qperf_inc(q, eqbs_partial);
+ DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS part:%02x",
+ tmp_count);
+ /*
+ * Retry once, if that fails bail out and process the
+ * extracted buffers before trying again.
+ */
+ if (!retried++)
+ goto again;
+ else
+ return count - tmp_count;
}
- return count - tmp_count;
+
+ DBF_ERROR("%4x EQBS ERROR", SCH_NO(q));
+ DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
+ q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
+ 0, -1, -1, q->irq_ptr->int_parm);
+ return 0;
}
/**
@@ -192,27 +201,28 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start,
again:
ccq = do_sqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count);
rc = qdio_check_ccq(q, ccq);
- if (rc == 1) {
+ if (!rc) {
+ WARN_ON(tmp_count);
+ return count - tmp_count;
+ }
+
+ if (rc == 1 || rc == 2) {
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq);
qperf_inc(q, sqbs_partial);
goto again;
}
- if (rc < 0) {
- DBF_ERROR("%4x SQBS ERROR", SCH_NO(q));
- DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
- q->handler(q->irq_ptr->cdev,
- QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
- 0, -1, -1, q->irq_ptr->int_parm);
- return 0;
- }
- WARN_ON(tmp_count);
- return count - tmp_count;
+
+ DBF_ERROR("%4x SQBS ERROR", SCH_NO(q));
+ DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
+ q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
+ 0, -1, -1, q->irq_ptr->int_parm);
+ return 0;
}
/* returns number of examined buffers and their common state in *state */
static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
unsigned char *state, unsigned int count,
- int auto_ack)
+ int auto_ack, int merge_pending)
{
unsigned char __state = 0;
int i;
@@ -224,9 +234,14 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
return qdio_do_eqbs(q, state, bufnr, count, auto_ack);
for (i = 0; i < count; i++) {
- if (!__state)
+ if (!__state) {
__state = q->slsb.val[bufnr];
- else if (q->slsb.val[bufnr] != __state)
+ if (merge_pending && __state == SLSB_P_OUTPUT_PENDING)
+ __state = SLSB_P_OUTPUT_EMPTY;
+ } else if (merge_pending) {
+ if ((q->slsb.val[bufnr] & __state) != __state)
+ break;
+ } else if (q->slsb.val[bufnr] != __state)
break;
bufnr = next_buf(bufnr);
}
@@ -237,7 +252,7 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
static inline int get_buf_state(struct qdio_q *q, unsigned int bufnr,
unsigned char *state, int auto_ack)
{
- return get_buf_states(q, bufnr, state, 1, auto_ack);
+ return get_buf_states(q, bufnr, state, 1, auto_ack, 0);
}
/* wrap-around safe setting of slsb states, returns number of changed buffers */
@@ -266,7 +281,7 @@ static inline int set_buf_state(struct qdio_q *q, int bufnr,
}
/* set slsb states to initial state */
-void qdio_init_buf_states(struct qdio_irq *irq_ptr)
+static void qdio_init_buf_states(struct qdio_irq *irq_ptr)
{
struct qdio_q *q;
int i;
@@ -308,19 +323,28 @@ static inline int qdio_siga_sync_q(struct qdio_q *q)
return qdio_siga_sync(q, q->mask, 0);
}
-static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit)
+static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
+ unsigned long aob)
{
unsigned long schid = *((u32 *) &q->irq_ptr->schid);
unsigned int fc = QDIO_SIGA_WRITE;
u64 start_time = 0;
int retries = 0, cc;
+ unsigned long laob = 0;
+
+ if (q->u.out.use_cq && aob != 0) {
+ fc = QDIO_SIGA_WRITEQ;
+ laob = aob;
+ }
if (is_qebsm(q)) {
schid = q->irq_ptr->sch_token;
fc |= QDIO_SIGA_QEBSM_FLAG;
}
again:
- cc = do_siga_output(schid, q->mask, busy_bit, fc);
+ WARN_ON_ONCE((aob && queue_type(q) != QDIO_IQDIO_QFMT) ||
+ (aob && fc != QDIO_SIGA_WRITEQ));
+ cc = do_siga_output(schid, q->mask, busy_bit, fc, laob);
/* hipersocket busy condition */
if (unlikely(*busy_bit)) {
@@ -379,7 +403,7 @@ int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
{
if (need_siga_sync(q))
qdio_siga_sync_q(q);
- return get_buf_states(q, bufnr, state, 1, 0);
+ return get_buf_states(q, bufnr, state, 1, 0, 0);
}
static inline void qdio_stop_polling(struct qdio_q *q)
@@ -426,7 +450,7 @@ static void process_buffer_error(struct qdio_q *q, int count)
qperf_inc(q, target_full);
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x",
q->first_to_check);
- return;
+ goto set;
}
DBF_ERROR("%4x BUF ERROR", SCH_NO(q));
@@ -436,6 +460,7 @@ static void process_buffer_error(struct qdio_q *q, int count)
q->sbal[q->first_to_check]->element[14].sflags,
q->sbal[q->first_to_check]->element[15].sflags);
+set:
/*
* Interrupts may be avoided as long as the error is present
* so change the buffer state immediately to avoid starvation.
@@ -493,6 +518,8 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
int count, stop;
unsigned char state = 0;
+ q->timestamp = get_clock_fast();
+
/*
* Don't check 128 buffers, as otherwise qdio_inbound_q_moved
* would return 0.
@@ -507,7 +534,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
* No siga sync here, as a PCI or we after a thin interrupt
* already sync'ed the queues.
*/
- count = get_buf_states(q, q->first_to_check, &state, count, 1);
+ count = get_buf_states(q, q->first_to_check, &state, count, 1, 0);
if (!count)
goto out;
@@ -590,6 +617,107 @@ static inline int qdio_inbound_q_done(struct qdio_q *q)
return 0;
}
+static inline int contains_aobs(struct qdio_q *q)
+{
+ return !q->is_input_q && q->u.out.use_cq;
+}
+
+static inline void qdio_trace_aob(struct qdio_irq *irq, struct qdio_q *q,
+ int i, struct qaob *aob)
+{
+ int tmp;
+
+ DBF_DEV_EVENT(DBF_INFO, irq, "AOB%d:%lx", i,
+ (unsigned long) virt_to_phys(aob));
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES00:%lx",
+ (unsigned long) aob->res0[0]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES01:%lx",
+ (unsigned long) aob->res0[1]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES02:%lx",
+ (unsigned long) aob->res0[2]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES03:%lx",
+ (unsigned long) aob->res0[3]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES04:%lx",
+ (unsigned long) aob->res0[4]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES05:%lx",
+ (unsigned long) aob->res0[5]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES1:%x", aob->res1);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES2:%x", aob->res2);
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES3:%x", aob->res3);
+ DBF_DEV_EVENT(DBF_INFO, irq, "AORC:%u", aob->aorc);
+ DBF_DEV_EVENT(DBF_INFO, irq, "FLAGS:%u", aob->flags);
+ DBF_DEV_EVENT(DBF_INFO, irq, "CBTBS:%u", aob->cbtbs);
+ DBF_DEV_EVENT(DBF_INFO, irq, "SBC:%u", aob->sb_count);
+ for (tmp = 0; tmp < QDIO_MAX_ELEMENTS_PER_BUFFER; ++tmp) {
+ DBF_DEV_EVENT(DBF_INFO, irq, "SBA%d:%lx", tmp,
+ (unsigned long) aob->sba[tmp]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "rSBA%d:%lx", tmp,
+ (unsigned long) q->sbal[i]->element[tmp].addr);
+ DBF_DEV_EVENT(DBF_INFO, irq, "DC%d:%u", tmp, aob->dcount[tmp]);
+ DBF_DEV_EVENT(DBF_INFO, irq, "rDC%d:%u", tmp,
+ q->sbal[i]->element[tmp].length);
+ }
+ DBF_DEV_EVENT(DBF_INFO, irq, "USER0:%lx", (unsigned long) aob->user0);
+ for (tmp = 0; tmp < 2; ++tmp) {
+ DBF_DEV_EVENT(DBF_INFO, irq, "RES4%d:%lx", tmp,
+ (unsigned long) aob->res4[tmp]);
+ }
+ DBF_DEV_EVENT(DBF_INFO, irq, "USER1:%lx", (unsigned long) aob->user1);
+ DBF_DEV_EVENT(DBF_INFO, irq, "USER2:%lx", (unsigned long) aob->user2);
+}
+
+static inline void qdio_handle_aobs(struct qdio_q *q, int start, int count)
+{
+ unsigned char state = 0;
+ int j, b = start;
+
+ if (!contains_aobs(q))
+ return;
+
+ for (j = 0; j < count; ++j) {
+ get_buf_state(q, b, &state, 0);
+ if (state == SLSB_P_OUTPUT_PENDING) {
+ struct qaob *aob = q->u.out.aobs[b];
+ if (aob == NULL)
+ continue;
+
+ BUG_ON(q->u.out.sbal_state == NULL);
+ q->u.out.sbal_state[b].flags |=
+ QDIO_OUTBUF_STATE_FLAG_PENDING;
+ q->u.out.aobs[b] = NULL;
+ } else if (state == SLSB_P_OUTPUT_EMPTY) {
+ BUG_ON(q->u.out.sbal_state == NULL);
+ q->u.out.sbal_state[b].aob = NULL;
+ }
+ b = next_buf(b);
+ }
+}
+
+static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q,
+ int bufnr)
+{
+ unsigned long phys_aob = 0;
+
+ if (!q->use_cq)
+ goto out;
+
+ if (!q->aobs[bufnr]) {
+ struct qaob *aob = qdio_allocate_aob();
+ q->aobs[bufnr] = aob;
+ }
+ if (q->aobs[bufnr]) {
+ BUG_ON(q->sbal_state == NULL);
+ q->sbal_state[bufnr].flags = QDIO_OUTBUF_STATE_FLAG_NONE;
+ q->sbal_state[bufnr].aob = q->aobs[bufnr];
+ q->aobs[bufnr]->user1 = (u64) q->sbal_state[bufnr].user;
+ phys_aob = virt_to_phys(q->aobs[bufnr]);
+ BUG_ON(phys_aob & 0xFF);
+ }
+
+out:
+ return phys_aob;
+}
+
static void qdio_kick_handler(struct qdio_q *q)
{
int start = q->first_to_kick;
@@ -610,6 +738,8 @@ static void qdio_kick_handler(struct qdio_q *q)
start, count);
}
+ qdio_handle_aobs(q, start, count);
+
q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count,
q->irq_ptr->int_parm);
@@ -659,6 +789,8 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
int count, stop;
unsigned char state = 0;
+ q->timestamp = get_clock_fast();
+
if (need_siga_sync(q))
if (((queue_type(q) != QDIO_IQDIO_QFMT) &&
!pci_out_supported(q)) ||
@@ -672,23 +804,26 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
*/
count = min(atomic_read(&q->nr_buf_used), QDIO_MAX_BUFFERS_MASK);
stop = add_buf(q->first_to_check, count);
-
if (q->first_to_check == stop)
- return q->first_to_check;
+ goto out;
- count = get_buf_states(q, q->first_to_check, &state, count, 0);
+ count = get_buf_states(q, q->first_to_check, &state, count, 0, 1);
if (!count)
- return q->first_to_check;
+ goto out;
switch (state) {
+ case SLSB_P_OUTPUT_PENDING:
+ BUG();
case SLSB_P_OUTPUT_EMPTY:
/* the adapter got it */
- DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out empty:%1d %02x", q->nr, count);
+ DBF_DEV_EVENT(DBF_INFO, q->irq_ptr,
+ "out empty:%1d %02x", q->nr, count);
atomic_sub(count, &q->nr_buf_used);
q->first_to_check = add_buf(q->first_to_check, count);
if (q->irq_ptr->perf_stat_enabled)
account_sbals(q, count);
+
break;
case SLSB_P_OUTPUT_ERROR:
process_buffer_error(q, count);
@@ -701,7 +836,8 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
/* the adapter has not fetched the output yet */
if (q->irq_ptr->perf_stat_enabled)
q->q_stats.nr_sbal_nop++;
- DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d", q->nr);
+ DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d",
+ q->nr);
break;
case SLSB_P_OUTPUT_NOT_INIT:
case SLSB_P_OUTPUT_HALTED:
@@ -709,6 +845,8 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
default:
BUG();
}
+
+out:
return q->first_to_check;
}
@@ -732,7 +870,7 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q)
return 0;
}
-static int qdio_kick_outbound_q(struct qdio_q *q)
+static int qdio_kick_outbound_q(struct qdio_q *q, unsigned long aob)
{
int retries = 0, cc;
unsigned int busy_bit;
@@ -744,7 +882,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q)
retry:
qperf_inc(q, siga_write);
- cc = qdio_siga_output(q, &busy_bit);
+ cc = qdio_siga_output(q, &busy_bit, aob);
switch (cc) {
case 0:
break;
@@ -783,21 +921,13 @@ static void __qdio_outbound_processing(struct qdio_q *q)
if (!pci_out_supported(q) && !qdio_outbound_q_done(q))
goto sched;
- /* bail out for HiperSockets unicast queues */
- if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q))
- return;
-
- if ((queue_type(q) == QDIO_IQDIO_QFMT) &&
- (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL)
- goto sched;
-
if (q->u.out.pci_out_enabled)
return;
/*
* Now we know that queue type is either qeth without pci enabled
- * or HiperSockets multicast. Make sure buffer switch from PRIMED to
- * EMPTY is noticed and outbound_handler is called after some time.
+ * or HiperSockets. Make sure buffer switch from PRIMED to EMPTY
+ * is noticed and outbound_handler is called after some time.
*/
if (qdio_outbound_q_done(q))
del_timer(&q->u.out.timer);
@@ -921,8 +1051,9 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
}
q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
q->irq_ptr->int_parm);
- } else
+ } else {
tasklet_schedule(&q->tasklet);
+ }
}
if (!pci_out_supported(q))
@@ -942,6 +1073,7 @@ static void qdio_handle_activate_check(struct ccw_device *cdev,
{
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
struct qdio_q *q;
+ int count;
DBF_ERROR("%4x ACT CHECK", irq_ptr->schid.sch_no);
DBF_ERROR("intp :%lx", intparm);
@@ -955,8 +1087,10 @@ static void qdio_handle_activate_check(struct ccw_device *cdev,
dump_stack();
goto no_handler;
}
+
+ count = sub_buf(q->first_to_check, q->first_to_kick);
q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
- 0, -1, -1, irq_ptr->int_parm);
+ q->nr, q->first_to_kick, count, irq_ptr->int_parm);
no_handler:
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
}
@@ -995,7 +1129,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
return;
}
- kstat_cpu(smp_processor_id()).irqs[IOINT_QDI]++;
if (irq_ptr->perf_stat_enabled)
irq_ptr->perf_stat.qdio_int++;
@@ -1236,6 +1369,26 @@ out_err:
}
EXPORT_SYMBOL_GPL(qdio_allocate);
+static void qdio_detect_hsicq(struct qdio_irq *irq_ptr)
+{
+ struct qdio_q *q = irq_ptr->input_qs[0];
+ int i, use_cq = 0;
+
+ if (irq_ptr->nr_input_qs > 1 && queue_type(q) == QDIO_IQDIO_QFMT)
+ use_cq = 1;
+
+ for_each_output_queue(irq_ptr, q, i) {
+ if (use_cq) {
+ if (qdio_enable_async_operation(&q->u.out) < 0) {
+ use_cq = 0;
+ continue;
+ }
+ } else
+ qdio_disable_async_operation(&q->u.out);
+ }
+ DBF_EVENT("use_cq:%d", use_cq);
+}
+
/**
* qdio_establish - establish queues on a qdio subchannel
* @init_data: initialization data
@@ -1301,6 +1454,8 @@ int qdio_establish(struct qdio_initialize *init_data)
qdio_setup_ssqd_info(irq_ptr);
DBF_EVENT("qib ac:%4x", irq_ptr->qib.ac);
+ qdio_detect_hsicq(irq_ptr);
+
/* qebsm is now setup if available, initialize buffer states */
qdio_init_buf_states(irq_ptr);
@@ -1442,12 +1597,9 @@ set:
used = atomic_add_return(count, &q->nr_buf_used) - count;
BUG_ON(used + count > QDIO_MAX_BUFFERS_PER_Q);
- /* no need to signal as long as the adapter had free buffers */
- if (used)
- return 0;
-
if (need_siga_in(q))
return qdio_siga_input(q);
+
return 0;
}
@@ -1480,17 +1632,21 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
q->u.out.pci_out_enabled = 0;
if (queue_type(q) == QDIO_IQDIO_QFMT) {
- /* One SIGA-W per buffer required for unicast HiperSockets. */
+ unsigned long phys_aob = 0;
+
+ /* One SIGA-W per buffer required for unicast HSI */
WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
- rc = qdio_kick_outbound_q(q);
+ phys_aob = qdio_aob_for_buffer(&q->u.out, bufnr);
+
+ rc = qdio_kick_outbound_q(q, phys_aob);
} else if (need_siga_sync(q)) {
rc = qdio_siga_sync_q(q);
} else {
/* try to fast requeue buffers */
get_buf_state(q, prev_buf(bufnr), &state, 0);
if (state != SLSB_CU_OUTPUT_PRIMED)
- rc = qdio_kick_outbound_q(q);
+ rc = qdio_kick_outbound_q(q, 0);
else
qperf_inc(q, fast_requeue);
}
@@ -1518,6 +1674,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
{
struct qdio_irq *irq_ptr;
+
if (bufnr >= QDIO_MAX_BUFFERS_PER_Q || count > QDIO_MAX_BUFFERS_PER_Q)
return -EINVAL;
@@ -1562,9 +1719,7 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
WARN_ON(queue_irqs_enabled(q));
- if (!shared_ind(q->irq_ptr->dsci))
- xchg(q->irq_ptr->dsci, 0);
-
+ clear_nonshared_ind(irq_ptr);
qdio_stop_polling(q);
clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state);
@@ -1572,7 +1727,7 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
* We need to check again to not lose initiative after
* resetting the ACK state.
*/
- if (!shared_ind(q->irq_ptr->dsci) && *q->irq_ptr->dsci)
+ if (test_nonshared_ind(irq_ptr))
goto rescan;
if (!qdio_inbound_q_done(q))
goto rescan;
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 89107d0938c4..d9a46a429bcc 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -19,6 +19,22 @@
#include "qdio_debug.h"
static struct kmem_cache *qdio_q_cache;
+static struct kmem_cache *qdio_aob_cache;
+
+struct qaob *qdio_allocate_aob()
+{
+ struct qaob *aob;
+
+ aob = kmem_cache_zalloc(qdio_aob_cache, GFP_ATOMIC);
+ return aob;
+}
+EXPORT_SYMBOL_GPL(qdio_allocate_aob);
+
+void qdio_release_aob(struct qaob *aob)
+{
+ kmem_cache_free(qdio_aob_cache, aob);
+}
+EXPORT_SYMBOL_GPL(qdio_release_aob);
/*
* qebsm is only available under 64bit but the adapter sets the feature
@@ -154,29 +170,36 @@ static void setup_queues(struct qdio_irq *irq_ptr,
struct qdio_q *q;
void **input_sbal_array = qdio_init->input_sbal_addr_array;
void **output_sbal_array = qdio_init->output_sbal_addr_array;
+ struct qdio_outbuf_state *output_sbal_state_array =
+ qdio_init->output_sbal_state_array;
int i;
for_each_input_queue(irq_ptr, q, i) {
- DBF_EVENT("in-q:%1d", i);
+ DBF_EVENT("inq:%1d", i);
setup_queues_misc(q, irq_ptr, qdio_init->input_handler, i);
q->is_input_q = 1;
- q->u.in.queue_start_poll = qdio_init->queue_start_poll;
+ q->u.in.queue_start_poll = qdio_init->queue_start_poll[i];
+
setup_storage_lists(q, irq_ptr, input_sbal_array, i);
input_sbal_array += QDIO_MAX_BUFFERS_PER_Q;
- if (is_thinint_irq(irq_ptr))
+ if (is_thinint_irq(irq_ptr)) {
tasklet_init(&q->tasklet, tiqdio_inbound_processing,
(unsigned long) q);
- else
+ } else {
tasklet_init(&q->tasklet, qdio_inbound_processing,
(unsigned long) q);
+ }
}
for_each_output_queue(irq_ptr, q, i) {
DBF_EVENT("outq:%1d", i);
setup_queues_misc(q, irq_ptr, qdio_init->output_handler, i);
+ q->u.out.sbal_state = output_sbal_state_array;
+ output_sbal_state_array += QDIO_MAX_BUFFERS_PER_Q;
+
q->is_input_q = 0;
q->u.out.scan_threshold = qdio_init->scan_threshold;
setup_storage_lists(q, irq_ptr, output_sbal_array, i);
@@ -311,6 +334,19 @@ void qdio_release_memory(struct qdio_irq *irq_ptr)
for (i = 0; i < QDIO_MAX_QUEUES_PER_IRQ; i++) {
q = irq_ptr->output_qs[i];
if (q) {
+ if (q->u.out.use_cq) {
+ int n;
+
+ for (n = 0; n < QDIO_MAX_BUFFERS_PER_Q; ++n) {
+ struct qaob *aob = q->u.out.aobs[n];
+ if (aob) {
+ qdio_release_aob(aob);
+ q->u.out.aobs[n] = NULL;
+ }
+ }
+
+ qdio_disable_async_operation(&q->u.out);
+ }
free_page((unsigned long) q->slib);
kmem_cache_free(qdio_q_cache, q);
}
@@ -345,6 +381,7 @@ static void setup_qdr(struct qdio_irq *irq_ptr,
int i;
irq_ptr->qdr->qfmt = qdio_init->q_format;
+ irq_ptr->qdr->ac = qdio_init->qdr_ac;
irq_ptr->qdr->iqdcnt = qdio_init->no_input_qs;
irq_ptr->qdr->oqdcnt = qdio_init->no_output_qs;
irq_ptr->qdr->iqdsz = sizeof(struct qdesfmt0) / 4; /* size in words */
@@ -465,23 +502,60 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
printk(KERN_INFO "%s", s);
}
+int qdio_enable_async_operation(struct qdio_output_q *outq)
+{
+ outq->aobs = kzalloc(sizeof(struct qaob *) * QDIO_MAX_BUFFERS_PER_Q,
+ GFP_ATOMIC);
+ if (!outq->aobs) {
+ outq->use_cq = 0;
+ return -ENOMEM;
+ }
+ outq->use_cq = 1;
+ return 0;
+}
+
+void qdio_disable_async_operation(struct qdio_output_q *q)
+{
+ kfree(q->aobs);
+ q->aobs = NULL;
+ q->use_cq = 0;
+}
+
int __init qdio_setup_init(void)
{
+ int rc;
+
qdio_q_cache = kmem_cache_create("qdio_q", sizeof(struct qdio_q),
256, 0, NULL);
if (!qdio_q_cache)
return -ENOMEM;
+ qdio_aob_cache = kmem_cache_create("qdio_aob",
+ sizeof(struct qaob),
+ sizeof(struct qaob),
+ 0,
+ NULL);
+ if (!qdio_aob_cache) {
+ rc = -ENOMEM;
+ goto free_qdio_q_cache;
+ }
+
/* Check for OSA/FCP thin interrupts (bit 67). */
DBF_EVENT("thinint:%1d",
(css_general_characteristics.aif_osa) ? 1 : 0);
/* Check for QEBSM support in general (bit 58). */
DBF_EVENT("cssQEBSM:%1d", (qebsm_possible()) ? 1 : 0);
- return 0;
+ rc = 0;
+out:
+ return rc;
+free_qdio_q_cache:
+ kmem_cache_destroy(qdio_q_cache);
+ goto out;
}
void qdio_setup_exit(void)
{
+ kmem_cache_destroy(qdio_aob_cache);
kmem_cache_destroy(qdio_q_cache);
}
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 2a1d4dfaf859..011eadea3ee4 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -26,17 +26,24 @@
*/
#define TIQDIO_NR_NONSHARED_IND 63
#define TIQDIO_NR_INDICATORS (TIQDIO_NR_NONSHARED_IND + 1)
+#define TIQDIO_SHARED_IND 63
+
+/* device state change indicators */
+struct indicator_t {
+ u32 ind; /* u32 because of compare-and-swap performance */
+ atomic_t count; /* use count, 0 or 1 for non-shared indicators */
+};
/* list of thin interrupt input queues */
static LIST_HEAD(tiq_list);
-DEFINE_MUTEX(tiq_list_lock);
+static DEFINE_MUTEX(tiq_list_lock);
/* adapter local summary indicator */
static u8 *tiqdio_alsi;
-struct indicator_t *q_indicators;
+static struct indicator_t *q_indicators;
-static u64 last_ai_time;
+u64 last_ai_time;
/* returns addr for the device state change indicator */
static u32 *get_indicator(void)
@@ -67,12 +74,9 @@ static void put_indicator(u32 *addr)
void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
{
- struct qdio_q *q;
- int i;
-
mutex_lock(&tiq_list_lock);
- for_each_input_queue(irq_ptr, q, i)
- list_add_rcu(&q->entry, &tiq_list);
+ BUG_ON(irq_ptr->nr_input_qs < 1);
+ list_add_rcu(&irq_ptr->input_qs[0]->entry, &tiq_list);
mutex_unlock(&tiq_list_lock);
xchg(irq_ptr->dsci, 1 << 7);
}
@@ -80,19 +84,54 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
{
struct qdio_q *q;
- int i;
- for (i = 0; i < irq_ptr->nr_input_qs; i++) {
- q = irq_ptr->input_qs[i];
- /* if establish triggered an error */
- if (!q || !q->entry.prev || !q->entry.next)
- continue;
+ BUG_ON(irq_ptr->nr_input_qs < 1);
+ q = irq_ptr->input_qs[0];
+ /* if establish triggered an error */
+ if (!q || !q->entry.prev || !q->entry.next)
+ return;
- mutex_lock(&tiq_list_lock);
- list_del_rcu(&q->entry);
- mutex_unlock(&tiq_list_lock);
- synchronize_rcu();
- }
+ mutex_lock(&tiq_list_lock);
+ list_del_rcu(&q->entry);
+ mutex_unlock(&tiq_list_lock);
+ synchronize_rcu();
+}
+
+static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq_ptr)
+{
+ return irq_ptr->nr_input_qs > 1;
+}
+
+static inline int references_shared_dsci(struct qdio_irq *irq_ptr)
+{
+ return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+}
+
+static inline int shared_ind(struct qdio_irq *irq_ptr)
+{
+ return references_shared_dsci(irq_ptr) ||
+ has_multiple_inq_on_dsci(irq_ptr);
+}
+
+void clear_nonshared_ind(struct qdio_irq *irq_ptr)
+{
+ if (!is_thinint_irq(irq_ptr))
+ return;
+ if (shared_ind(irq_ptr))
+ return;
+ xchg(irq_ptr->dsci, 0);
+}
+
+int test_nonshared_ind(struct qdio_irq *irq_ptr)
+{
+ if (!is_thinint_irq(irq_ptr))
+ return 0;
+ if (shared_ind(irq_ptr))
+ return 0;
+ if (*irq_ptr->dsci)
+ return 1;
+ else
+ return 0;
}
static inline u32 clear_shared_ind(void)
@@ -102,6 +141,40 @@ static inline u32 clear_shared_ind(void)
return xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
}
+static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq)
+{
+ struct qdio_q *q;
+ int i;
+
+ for_each_input_queue(irq, q, i) {
+ if (!references_shared_dsci(irq) &&
+ has_multiple_inq_on_dsci(irq))
+ xchg(q->irq_ptr->dsci, 0);
+
+ if (q->u.in.queue_start_poll) {
+ /* skip if polling is enabled or already in work */
+ if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+ &q->u.in.queue_irq_state)) {
+ qperf_inc(q, int_discarded);
+ continue;
+ }
+
+ /* avoid dsci clear here, done after processing */
+ q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
+ q->irq_ptr->int_parm);
+ } else {
+ if (!shared_ind(q->irq_ptr))
+ xchg(q->irq_ptr->dsci, 0);
+
+ /*
+ * Call inbound processing but not directly
+ * since that could starve other thinint queues.
+ */
+ tasklet_schedule(&q->tasklet);
+ }
+ }
+}
+
/**
* tiqdio_thinint_handler - thin interrupt handler for qdio
* @alsi: pointer to adapter local summary indicator
@@ -120,35 +193,18 @@ static void tiqdio_thinint_handler(void *alsi, void *data)
/* check for work on all inbound thinint queues */
list_for_each_entry_rcu(q, &tiq_list, entry) {
+ struct qdio_irq *irq;
/* only process queues from changed sets */
- if (unlikely(shared_ind(q->irq_ptr->dsci))) {
+ irq = q->irq_ptr;
+ if (unlikely(references_shared_dsci(irq))) {
if (!si_used)
continue;
- } else if (!*q->irq_ptr->dsci)
+ } else if (!*irq->dsci)
continue;
- if (q->u.in.queue_start_poll) {
- /* skip if polling is enabled or already in work */
- if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
- &q->u.in.queue_irq_state)) {
- qperf_inc(q, int_discarded);
- continue;
- }
+ tiqdio_call_inq_handlers(irq);
- /* avoid dsci clear here, done after processing */
- q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
- q->irq_ptr->int_parm);
- } else {
- /* only clear it if the indicator is non-shared */
- if (!shared_ind(q->irq_ptr->dsci))
- xchg(q->irq_ptr->dsci, 0);
- /*
- * Call inbound processing but not directly
- * since that could starve other thinint queues.
- */
- tasklet_schedule(&q->tasklet);
- }
qperf_inc(q, adapter_int);
}
rcu_read_unlock();
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index aec60d55b10d..3c2c923d5c0a 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -33,7 +33,7 @@
* The pointer to our (page) of device descriptions.
*/
static void *kvm_devices;
-struct work_struct hotplug_work;
+static struct work_struct hotplug_work;
struct kvm_device {
struct virtio_device vdev;
@@ -334,10 +334,10 @@ static void scan_devices(void)
*/
static int match_desc(struct device *dev, void *data)
{
- if ((ulong)to_kvmdev(dev_to_virtio(dev))->desc == (ulong)data)
- return 1;
+ struct virtio_device *vdev = dev_to_virtio(dev);
+ struct kvm_device *kdev = to_kvmdev(vdev);
- return 0;
+ return kdev->desc == data;
}
/*
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index f1fa2483ae6b..b41fae37d3af 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -63,7 +63,6 @@
#define KMSG_COMPONENT "claw"
-#include <linux/kernel_stat.h>
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>
#include <asm/debug.h>
@@ -291,6 +290,7 @@ static struct ccw_driver claw_ccw_driver = {
.ids = claw_ids,
.probe = ccwgroup_probe_ccwdev,
.remove = ccwgroup_remove_ccwdev,
+ .int_class = IOINT_CLW,
};
static ssize_t
@@ -645,7 +645,6 @@ claw_irq_handler(struct ccw_device *cdev,
struct claw_env *p_env;
struct chbk *p_ch_r=NULL;
- kstat_cpu(smp_processor_id()).irqs[IOINT_CLW]++;
CLAW_DBF_TEXT(4, trace, "clawirq");
/* Bypass all 'unsolicited interrupts' */
privptr = dev_get_drvdata(&cdev->dev);
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 426787efc492..5cb93a8e3403 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -24,7 +24,6 @@
#define KMSG_COMPONENT "ctcm"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -1203,7 +1202,6 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
int cstat;
int dstat;
- kstat_cpu(smp_processor_id()).irqs[IOINT_CTC]++;
CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
"Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev));
@@ -1769,6 +1767,7 @@ static struct ccw_driver ctcm_ccw_driver = {
.ids = ctcm_ids,
.probe = ccwgroup_probe_ccwdev,
.remove = ccwgroup_remove_ccwdev,
+ .int_class = IOINT_CTC,
};
static struct ccwgroup_driver ctcm_group_driver = {
diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c
index 8305319b2a84..650aec1839e9 100644
--- a/drivers/s390/net/ctcm_sysfs.c
+++ b/drivers/s390/net/ctcm_sysfs.c
@@ -159,7 +159,7 @@ static ssize_t ctcm_proto_store(struct device *dev,
return count;
}
-const char *ctcm_type[] = {
+static const char *ctcm_type[] = {
"not a channel",
"CTC/A",
"FICON channel",
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index c3b8064a102d..c28713da1ec5 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -26,7 +26,6 @@
#define KMSG_COMPONENT "lcs"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/if.h>
#include <linux/netdevice.h>
@@ -1399,7 +1398,6 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
int rc, index;
int cstat, dstat;
- kstat_cpu(smp_processor_id()).irqs[IOINT_LCS]++;
if (lcs_check_irb_error(cdev, irb))
return;
@@ -1972,7 +1970,7 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char
static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store);
-const char *lcs_type[] = {
+static const char *lcs_type[] = {
"not a channel",
"2216 parallel",
"2216 channel",
@@ -2122,7 +2120,7 @@ static const struct net_device_ops lcs_mc_netdev_ops = {
.ndo_stop = lcs_stop_device,
.ndo_get_stats = lcs_getstats,
.ndo_start_xmit = lcs_start_xmit,
- .ndo_set_multicast_list = lcs_set_multicast_list,
+ .ndo_set_rx_mode = lcs_set_multicast_list,
};
static int
@@ -2399,6 +2397,7 @@ static struct ccw_driver lcs_ccw_driver = {
.ids = lcs_ids,
.probe = ccwgroup_probe_ccwdev,
.remove = ccwgroup_remove_ccwdev,
+ .int_class = IOINT_LCS,
};
/**
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 26a4110eeb2d..b77c65ed1381 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -110,6 +110,10 @@ struct qeth_perf_stats {
unsigned int sc_dp_p;
unsigned int sc_p_dp;
+ /* qdio_cq_handler: number of times called, time spent in */
+ __u64 cq_start_time;
+ unsigned int cq_cnt;
+ unsigned int cq_time;
/* qdio_input_handler: number of times called, time spent in */
__u64 inbound_start_time;
unsigned int inbound_cnt;
@@ -213,6 +217,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
*/
#define QETH_TX_TIMEOUT 100 * HZ
#define QETH_RCD_TIMEOUT 60 * HZ
+#define QETH_RECLAIM_WORK_TIME HZ
#define QETH_HEADER_SIZE 32
#define QETH_MAX_PORTNO 15
@@ -231,7 +236,8 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
#define QETH_IN_BUF_COUNT_MAX 128
#define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
#define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
- ((card)->qdio.in_buf_pool.buf_count / 2)
+ ((card)->ssqd.qdioac1 & AC1_SIGA_INPUT_NEEDED ? 1 : \
+ ((card)->qdio.in_buf_pool.buf_count / 2))
/* buffers we have to be behind before we get a PCI */
#define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
@@ -260,6 +266,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
/* large receive scatter gather copy break */
#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
+#define QETH_RX_PULL_LEN 256
struct qeth_hdr_layer3 {
__u8 id;
@@ -375,6 +382,21 @@ enum qeth_qdio_buffer_states {
* outbound: filled by driver; owned by hardware in order to be sent
*/
QETH_QDIO_BUF_PRIMED,
+ /*
+ * inbound: not applicable
+ * outbound: identified to be pending in TPQ
+ */
+ QETH_QDIO_BUF_PENDING,
+ /*
+ * inbound: not applicable
+ * outbound: found in completion queue
+ */
+ QETH_QDIO_BUF_IN_CQ,
+ /*
+ * inbound: not applicable
+ * outbound: handled via transfer pending / completion queue
+ */
+ QETH_QDIO_BUF_HANDLED_DELAYED,
};
enum qeth_qdio_info_states {
@@ -399,6 +421,7 @@ struct qeth_qdio_buffer {
struct qdio_buffer *buffer;
/* the buffer pool entry currently associated to this buffer */
struct qeth_buffer_pool_entry *pool_entry;
+ struct sk_buff *rx_skb;
};
struct qeth_qdio_q {
@@ -412,8 +435,11 @@ struct qeth_qdio_out_buffer {
atomic_t state;
int next_element_to_fill;
struct sk_buff_head skb_list;
- struct list_head ctx_list;
int is_header[16];
+
+ struct qaob *aob;
+ struct qeth_qdio_out_q *q;
+ struct qeth_qdio_out_buffer *next_pending;
};
struct qeth_card;
@@ -426,7 +452,8 @@ enum qeth_out_q_states {
struct qeth_qdio_out_q {
struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
- struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
+ struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q];
+ struct qdio_outbuf_state *bufstates; /* convenience pointer */
int queue_no;
struct qeth_card *card;
atomic_t state;
@@ -447,7 +474,9 @@ struct qeth_qdio_out_q {
struct qeth_qdio_info {
atomic_t state;
/* input */
+ int no_in_queues;
struct qeth_qdio_q *in_q;
+ struct qeth_qdio_q *c_q;
struct qeth_qdio_buffer_pool in_buf_pool;
struct qeth_qdio_buffer_pool init_pool;
int in_buf_size;
@@ -455,6 +484,7 @@ struct qeth_qdio_info {
/* output */
int no_out_queues;
struct qeth_qdio_out_q **out_qs;
+ struct qdio_outbuf_state *out_bufstates;
/* priority queueing */
int do_prio_queueing;
@@ -526,6 +556,12 @@ enum qeth_cmd_buffer_state {
BUF_STATE_PROCESSED,
};
+enum qeth_cq {
+ QETH_CQ_DISABLED = 0,
+ QETH_CQ_ENABLED = 1,
+ QETH_CQ_NOTAVAILABLE = 2,
+};
+
struct qeth_ipato {
int enabled;
int invert4;
@@ -650,6 +686,8 @@ struct qeth_card_options {
int rx_sg_cb;
enum qeth_ipa_isolation_modes isolation;
int sniffer;
+ enum qeth_cq cq;
+ char hsuid[9];
};
/*
@@ -747,6 +785,8 @@ struct qeth_card {
struct mutex discipline_mutex;
struct napi_struct napi;
struct qeth_rx rx;
+ struct delayed_work buffer_reclaim_work;
+ int reclaim_index;
};
struct qeth_card_list_struct {
@@ -812,6 +852,7 @@ int qeth_core_create_device_attributes(struct device *);
void qeth_core_remove_device_attributes(struct device *);
int qeth_core_create_osn_attributes(struct device *);
void qeth_core_remove_osn_attributes(struct device *);
+void qeth_buffer_reclaim_work(struct work_struct *);
/* exports for qeth discipline device drivers */
extern struct qeth_card_list_struct qeth_core_card_list;
@@ -840,7 +881,7 @@ int qeth_check_qdio_errors(struct qeth_card *, struct qdio_buffer *,
unsigned int, const char *);
void qeth_queue_input_buffer(struct qeth_card *, int);
struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
- struct qdio_buffer *, struct qdio_buffer_element **, int *,
+ struct qeth_qdio_buffer *, struct qdio_buffer_element **, int *,
struct qeth_hdr **);
void qeth_schedule_recovery(struct qeth_card *);
void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long);
@@ -887,6 +928,7 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
int qeth_set_access_ctrl_online(struct qeth_card *card);
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);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 4550573c25e5..81534437373a 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -21,6 +21,7 @@
#include <linux/mii.h>
#include <linux/kthread.h>
#include <linux/slab.h>
+#include <net/iucv/af_iucv.h>
#include <asm/ebcdic.h>
#include <asm/io.h>
@@ -44,6 +45,7 @@ struct qeth_card_list_struct qeth_core_card_list;
EXPORT_SYMBOL_GPL(qeth_core_card_list);
struct kmem_cache *qeth_core_header_cache;
EXPORT_SYMBOL_GPL(qeth_core_header_cache);
+static struct kmem_cache *qeth_qdio_outbuf_cache;
static struct device *qeth_core_root_dev;
static unsigned int known_devices[][6] = QETH_MODELLIST_ARRAY;
@@ -56,6 +58,14 @@ static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *);
static void qeth_setup_ccw(struct qeth_channel *, unsigned char *, __u32);
static void qeth_free_buffer_pool(struct qeth_card *);
static int qeth_qdio_establish(struct qeth_card *);
+static void qeth_free_qdio_buffers(struct qeth_card *);
+static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
+ struct qeth_qdio_out_buffer *buf,
+ enum iucv_tx_notify notification);
+static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf);
+static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+ struct qeth_qdio_out_buffer *buf,
+ enum qeth_qdio_buffer_states newbufstate);
static inline const char *qeth_get_cardname(struct qeth_card *card)
@@ -199,7 +209,7 @@ static int qeth_alloc_buffer_pool(struct qeth_card *card)
QETH_CARD_TEXT(card, 5, "alocpool");
for (i = 0; i < card->qdio.init_pool.buf_count; ++i) {
- pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
+ pool_entry = kzalloc(sizeof(*pool_entry), GFP_KERNEL);
if (!pool_entry) {
qeth_free_buffer_pool(card);
return -ENOMEM;
@@ -239,6 +249,196 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
}
EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool);
+static inline int qeth_cq_init(struct qeth_card *card)
+{
+ int rc;
+
+ if (card->options.cq == QETH_CQ_ENABLED) {
+ QETH_DBF_TEXT(SETUP, 2, "cqinit");
+ memset(card->qdio.c_q->qdio_bufs, 0,
+ QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+ card->qdio.c_q->next_buf_to_init = 127;
+ rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT,
+ card->qdio.no_in_queues - 1, 0,
+ 127);
+ if (rc) {
+ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
+ goto out;
+ }
+ }
+ rc = 0;
+out:
+ return rc;
+}
+
+static inline int qeth_alloc_cq(struct qeth_card *card)
+{
+ int rc;
+
+ if (card->options.cq == QETH_CQ_ENABLED) {
+ int i;
+ struct qdio_outbuf_state *outbuf_states;
+
+ QETH_DBF_TEXT(SETUP, 2, "cqon");
+ card->qdio.c_q = kzalloc(sizeof(struct qeth_qdio_q),
+ GFP_KERNEL);
+ if (!card->qdio.c_q) {
+ rc = -1;
+ goto kmsg_out;
+ }
+ QETH_DBF_HEX(SETUP, 2, &card->qdio.c_q, sizeof(void *));
+
+ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
+ card->qdio.c_q->bufs[i].buffer =
+ &card->qdio.c_q->qdio_bufs[i];
+ }
+
+ card->qdio.no_in_queues = 2;
+
+ card->qdio.out_bufstates = (struct qdio_outbuf_state *)
+ kzalloc(card->qdio.no_out_queues *
+ QDIO_MAX_BUFFERS_PER_Q *
+ sizeof(struct qdio_outbuf_state), GFP_KERNEL);
+ outbuf_states = card->qdio.out_bufstates;
+ if (outbuf_states == NULL) {
+ rc = -1;
+ goto free_cq_out;
+ }
+ for (i = 0; i < card->qdio.no_out_queues; ++i) {
+ card->qdio.out_qs[i]->bufstates = outbuf_states;
+ outbuf_states += QDIO_MAX_BUFFERS_PER_Q;
+ }
+ } else {
+ QETH_DBF_TEXT(SETUP, 2, "nocq");
+ card->qdio.c_q = NULL;
+ card->qdio.no_in_queues = 1;
+ }
+ QETH_DBF_TEXT_(SETUP, 2, "iqc%d", card->qdio.no_in_queues);
+ rc = 0;
+out:
+ return rc;
+free_cq_out:
+ kfree(card->qdio.c_q);
+ card->qdio.c_q = NULL;
+kmsg_out:
+ dev_err(&card->gdev->dev, "Failed to create completion queue\n");
+ goto out;
+}
+
+static inline void qeth_free_cq(struct qeth_card *card)
+{
+ if (card->qdio.c_q) {
+ --card->qdio.no_in_queues;
+ kfree(card->qdio.c_q);
+ card->qdio.c_q = NULL;
+ }
+ kfree(card->qdio.out_bufstates);
+ card->qdio.out_bufstates = NULL;
+}
+
+static inline enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15,
+ int delayed) {
+ enum iucv_tx_notify n;
+
+ switch (sbalf15) {
+ case 0:
+ n = delayed ? TX_NOTIFY_DELAYED_OK : TX_NOTIFY_OK;
+ break;
+ case 4:
+ case 16:
+ case 17:
+ case 18:
+ n = delayed ? TX_NOTIFY_DELAYED_UNREACHABLE :
+ TX_NOTIFY_UNREACHABLE;
+ break;
+ default:
+ n = delayed ? TX_NOTIFY_DELAYED_GENERALERROR :
+ TX_NOTIFY_GENERALERROR;
+ break;
+ }
+
+ return n;
+}
+
+static inline void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q,
+ int bidx, int forced_cleanup)
+{
+ if (q->bufs[bidx]->next_pending != NULL) {
+ struct qeth_qdio_out_buffer *head = q->bufs[bidx];
+ struct qeth_qdio_out_buffer *c = q->bufs[bidx]->next_pending;
+
+ while (c) {
+ if (forced_cleanup ||
+ atomic_read(&c->state) ==
+ QETH_QDIO_BUF_HANDLED_DELAYED) {
+ struct qeth_qdio_out_buffer *f = c;
+ QETH_CARD_TEXT(f->q->card, 5, "fp");
+ QETH_CARD_TEXT_(f->q->card, 5, "%lx", (long) f);
+ /* release here to avoid interleaving between
+ outbound tasklet and inbound tasklet
+ regarding notifications and lifecycle */
+ qeth_release_skbs(c);
+
+ c = f->next_pending;
+ BUG_ON(head->next_pending != f);
+ head->next_pending = c;
+ kmem_cache_free(qeth_qdio_outbuf_cache, f);
+ } else {
+ head = c;
+ c = c->next_pending;
+ }
+
+ }
+ }
+}
+
+
+static inline void qeth_qdio_handle_aob(struct qeth_card *card,
+ unsigned long phys_aob_addr) {
+ struct qaob *aob;
+ struct qeth_qdio_out_buffer *buffer;
+ enum iucv_tx_notify notification;
+
+ aob = (struct qaob *) phys_to_virt(phys_aob_addr);
+ QETH_CARD_TEXT(card, 5, "haob");
+ QETH_CARD_TEXT_(card, 5, "%lx", phys_aob_addr);
+ 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);
+
+ atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ);
+ notification = TX_NOTIFY_DELAYED_OK;
+ }
+
+ if (aob->aorc != 0) {
+ QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc);
+ notification = qeth_compute_cq_notification(aob->aorc, 1);
+ }
+ qeth_notify_skbs(buffer->q, buffer, notification);
+
+ buffer->aob = NULL;
+ qeth_clear_output_buffer(buffer->q, buffer,
+ QETH_QDIO_BUF_HANDLED_DELAYED);
+ /* from here on: do not touch buffer anymore */
+ qdio_release_aob(aob);
+}
+
+static inline int qeth_is_cq(struct qeth_card *card, unsigned int queue)
+{
+ return card->options.cq == QETH_CQ_ENABLED &&
+ card->qdio.c_q != NULL &&
+ queue != 0 &&
+ queue == card->qdio.no_in_queues - 1;
+}
+
+
static int qeth_issue_next_read(struct qeth_card *card)
{
int rc;
@@ -589,7 +789,7 @@ static int qeth_setup_channel(struct qeth_channel *channel)
QETH_DBF_TEXT(SETUP, 2, "setupch");
for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
channel->iob[cnt].data =
- kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
+ kzalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
if (channel->iob[cnt].data == NULL)
break;
channel->iob[cnt].state = BUF_STATE_FREE;
@@ -681,6 +881,7 @@ EXPORT_SYMBOL_GPL(qeth_do_run_thread);
void qeth_schedule_recovery(struct qeth_card *card)
{
QETH_CARD_TEXT(card, 2, "startrec");
+ WARN_ON(1);
if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
schedule_work(&card->kernel_thread_starter);
}
@@ -883,22 +1084,60 @@ out:
return;
}
-static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
- struct qeth_qdio_out_buffer *buf)
+static void qeth_notify_skbs(struct qeth_qdio_out_q *q,
+ struct qeth_qdio_out_buffer *buf,
+ enum iucv_tx_notify notification)
{
- int i;
struct sk_buff *skb;
- /* is PCI flag set on buffer? */
- if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ)
- atomic_dec(&queue->set_pci_flags_count);
+ if (skb_queue_empty(&buf->skb_list))
+ goto out;
+ skb = skb_peek(&buf->skb_list);
+ while (skb) {
+ QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification);
+ QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb);
+ if (skb->protocol == ETH_P_AF_IUCV) {
+ if (skb->sk) {
+ struct iucv_sock *iucv = iucv_sk(skb->sk);
+ iucv->sk_txnotify(skb, notification);
+ }
+ }
+ if (skb_queue_is_last(&buf->skb_list, skb))
+ skb = NULL;
+ else
+ skb = skb_queue_next(&buf->skb_list, skb);
+ }
+out:
+ return;
+}
+
+static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
+{
+ struct sk_buff *skb;
skb = skb_dequeue(&buf->skb_list);
while (skb) {
+ QETH_CARD_TEXT(buf->q->card, 5, "skbr");
+ QETH_CARD_TEXT_(buf->q->card, 5, "%lx", (long) skb);
atomic_dec(&skb->users);
dev_kfree_skb_any(skb);
skb = skb_dequeue(&buf->skb_list);
}
+}
+
+static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+ struct qeth_qdio_out_buffer *buf,
+ enum qeth_qdio_buffer_states newbufstate)
+{
+ int i;
+
+ /* is PCI flag set on buffer? */
+ if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ)
+ atomic_dec(&queue->set_pci_flags_count);
+
+ if (newbufstate == QETH_QDIO_BUF_EMPTY) {
+ qeth_release_skbs(buf);
+ }
for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) {
if (buf->buffer->element[i].addr && buf->is_header[i])
kmem_cache_free(qeth_core_header_cache,
@@ -912,21 +1151,36 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
buf->buffer->element[15].eflags = 0;
buf->buffer->element[15].sflags = 0;
buf->next_element_to_fill = 0;
- atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
+ atomic_set(&buf->state, newbufstate);
+}
+
+static void qeth_clear_outq_buffers(struct qeth_qdio_out_q *q, int free)
+{
+ int j;
+
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
+ if (!q->bufs[j])
+ continue;
+ qeth_cleanup_handled_pending(q, j, free);
+ qeth_clear_output_buffer(q, q->bufs[j], QETH_QDIO_BUF_EMPTY);
+ if (free) {
+ kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]);
+ q->bufs[j] = NULL;
+ }
+ }
}
void qeth_clear_qdio_buffers(struct qeth_card *card)
{
- int i, j;
+ int i;
QETH_CARD_TEXT(card, 2, "clearqdbf");
/* clear outbound buffers to free skbs */
- for (i = 0; i < card->qdio.no_out_queues; ++i)
+ for (i = 0; i < card->qdio.no_out_queues; ++i) {
if (card->qdio.out_qs[i]) {
- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
- qeth_clear_output_buffer(card->qdio.out_qs[i],
- &card->qdio.out_qs[i]->bufs[j]);
+ qeth_clear_outq_buffers(card->qdio.out_qs[i], 0);
}
+ }
}
EXPORT_SYMBOL_GPL(qeth_clear_qdio_buffers);
@@ -950,6 +1204,11 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
QETH_QDIO_UNINITIALIZED)
return;
+
+ qeth_free_cq(card);
+ cancel_delayed_work_sync(&card->buffer_reclaim_work);
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+ kfree_skb(card->qdio.in_q->bufs[j].rx_skb);
kfree(card->qdio.in_q);
card->qdio.in_q = NULL;
/* inbound buffer pool */
@@ -957,9 +1216,7 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
/* free outbound qdio_qs */
if (card->qdio.out_qs) {
for (i = 0; i < card->qdio.no_out_queues; ++i) {
- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
- qeth_clear_output_buffer(card->qdio.out_qs[i],
- &card->qdio.out_qs[i]->bufs[j]);
+ qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
kfree(card->qdio.out_qs[i]);
}
kfree(card->qdio.out_qs);
@@ -995,27 +1252,29 @@ static void qeth_get_channel_path_desc(struct qeth_card *card)
ccwdev = card->data.ccwdev;
chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
if (chp_dsc != NULL) {
- /* CHPP field bit 6 == 1 -> single queue */
- if ((chp_dsc->chpp & 0x02) == 0x02) {
- if ((atomic_read(&card->qdio.state) !=
- QETH_QDIO_UNINITIALIZED) &&
- (card->qdio.no_out_queues == 4))
- /* change from 4 to 1 outbound queues */
- qeth_free_qdio_buffers(card);
- card->qdio.no_out_queues = 1;
- if (card->qdio.default_out_queue != 0)
- dev_info(&card->gdev->dev,
+ if (card->info.type != QETH_CARD_TYPE_IQD) {
+ /* CHPP field bit 6 == 1 -> single queue */
+ if ((chp_dsc->chpp & 0x02) == 0x02) {
+ if ((atomic_read(&card->qdio.state) !=
+ QETH_QDIO_UNINITIALIZED) &&
+ (card->qdio.no_out_queues == 4))
+ /* change from 4 to 1 outbound queues */
+ qeth_free_qdio_buffers(card);
+ card->qdio.no_out_queues = 1;
+ if (card->qdio.default_out_queue != 0)
+ dev_info(&card->gdev->dev,
"Priority Queueing not supported\n");
- card->qdio.default_out_queue = 0;
- } else {
- if ((atomic_read(&card->qdio.state) !=
- QETH_QDIO_UNINITIALIZED) &&
- (card->qdio.no_out_queues == 1)) {
- /* change from 1 to 4 outbound queues */
- qeth_free_qdio_buffers(card);
- card->qdio.default_out_queue = 2;
+ card->qdio.default_out_queue = 0;
+ } else {
+ if ((atomic_read(&card->qdio.state) !=
+ QETH_QDIO_UNINITIALIZED) &&
+ (card->qdio.no_out_queues == 1)) {
+ /* change from 1 to 4 outbound queues */
+ qeth_free_qdio_buffers(card);
+ card->qdio.default_out_queue = 2;
+ }
+ card->qdio.no_out_queues = 4;
}
- card->qdio.no_out_queues = 4;
}
card->info.func_level = 0x4100 + chp_dsc->desc;
kfree(chp_dsc);
@@ -1051,6 +1310,7 @@ static void qeth_set_intial_options(struct qeth_card *card)
card->options.performance_stats = 0;
card->options.rx_sg_cb = QETH_RX_SG_CB;
card->options.isolation = ISOLATION_MODE_NONE;
+ card->options.cq = QETH_CQ_DISABLED;
}
static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
@@ -1119,6 +1379,7 @@ static int qeth_setup_card(struct qeth_card *card)
card->ipato.invert6 = 0;
/* init QDIO stuff */
qeth_init_qdio_info(card);
+ INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work);
return 0;
}
@@ -1140,7 +1401,7 @@ static struct qeth_card *qeth_alloc_card(void)
if (!card)
goto out;
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
- card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ card->ip_tbd_list = kzalloc(sizeof(struct list_head), GFP_KERNEL);
if (!card->ip_tbd_list) {
QETH_DBF_TEXT(SETUP, 0, "iptbdnom");
goto out_card;
@@ -1180,6 +1441,7 @@ static int qeth_determine_card_type(struct qeth_card *card)
card->info.type = known_devices[i][QETH_DEV_MODEL_IND];
card->qdio.no_out_queues =
known_devices[i][QETH_QUEUE_NO_IND];
+ card->qdio.no_in_queues = 1;
card->info.is_multicast_different =
known_devices[i][QETH_MULTICAST_IND];
qeth_get_channel_path_desc(card);
@@ -2027,6 +2289,37 @@ static int qeth_ulp_setup(struct qeth_card *card)
return rc;
}
+static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
+{
+ int rc;
+ struct qeth_qdio_out_buffer *newbuf;
+
+ rc = 0;
+ newbuf = kmem_cache_zalloc(qeth_qdio_outbuf_cache, GFP_ATOMIC);
+ if (!newbuf) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ newbuf->buffer = &q->qdio_bufs[bidx];
+ skb_queue_head_init(&newbuf->skb_list);
+ lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key);
+ newbuf->q = q;
+ newbuf->aob = NULL;
+ newbuf->next_pending = q->bufs[bidx];
+ atomic_set(&newbuf->state, QETH_QDIO_BUF_EMPTY);
+ q->bufs[bidx] = newbuf;
+ if (q->bufstates) {
+ q->bufstates[bidx].user = newbuf;
+ QETH_CARD_TEXT_(q->card, 2, "nbs%d", bidx);
+ QETH_CARD_TEXT_(q->card, 2, "%lx", (long) newbuf);
+ QETH_CARD_TEXT_(q->card, 2, "%lx",
+ (long) newbuf->next_pending);
+ }
+out:
+ return rc;
+}
+
+
static int qeth_alloc_qdio_buffers(struct qeth_card *card)
{
int i, j;
@@ -2037,52 +2330,63 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
return 0;
- card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
- GFP_KERNEL);
+ card->qdio.in_q = kzalloc(sizeof(struct qeth_qdio_q),
+ GFP_KERNEL);
if (!card->qdio.in_q)
goto out_nomem;
QETH_DBF_TEXT(SETUP, 2, "inq");
QETH_DBF_HEX(SETUP, 2, &card->qdio.in_q, sizeof(void *));
memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
/* give inbound qeth_qdio_buffers their qdio_buffers */
- for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
card->qdio.in_q->bufs[i].buffer =
&card->qdio.in_q->qdio_bufs[i];
+ card->qdio.in_q->bufs[i].rx_skb = NULL;
+ }
/* inbound buffer pool */
if (qeth_alloc_buffer_pool(card))
goto out_freeinq;
+
/* outbound */
card->qdio.out_qs =
- kmalloc(card->qdio.no_out_queues *
+ kzalloc(card->qdio.no_out_queues *
sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
if (!card->qdio.out_qs)
goto out_freepool;
for (i = 0; i < card->qdio.no_out_queues; ++i) {
- card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
+ card->qdio.out_qs[i] = kzalloc(sizeof(struct qeth_qdio_out_q),
GFP_KERNEL);
if (!card->qdio.out_qs[i])
goto out_freeoutq;
QETH_DBF_TEXT_(SETUP, 2, "outq %i", i);
QETH_DBF_HEX(SETUP, 2, &card->qdio.out_qs[i], sizeof(void *));
- memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
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) {
- card->qdio.out_qs[i]->bufs[j].buffer =
- &card->qdio.out_qs[i]->qdio_bufs[j];
- skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
- skb_list);
- lockdep_set_class(
- &card->qdio.out_qs[i]->bufs[j].skb_list.lock,
- &qdio_out_skb_queue_key);
- INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
+ BUG_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
+ if (qeth_init_qdio_out_buf(card->qdio.out_qs[i], j))
+ goto out_freeoutqbufs;
}
}
+
+ /* completion */
+ if (qeth_alloc_cq(card))
+ goto out_freeoutq;
+
return 0;
+out_freeoutqbufs:
+ while (j > 0) {
+ --j;
+ kmem_cache_free(qeth_qdio_outbuf_cache,
+ card->qdio.out_qs[i]->bufs[j]);
+ card->qdio.out_qs[i]->bufs[j] = NULL;
+ }
out_freeoutq:
- while (i > 0)
+ while (i > 0) {
kfree(card->qdio.out_qs[--i]);
+ qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
+ }
kfree(card->qdio.out_qs);
card->qdio.out_qs = NULL;
out_freepool:
@@ -2353,6 +2657,12 @@ static int qeth_init_input_buffer(struct qeth_card *card,
struct qeth_buffer_pool_entry *pool_entry;
int i;
+ if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) {
+ buf->rx_skb = dev_alloc_skb(QETH_RX_PULL_LEN + ETH_HLEN);
+ if (!buf->rx_skb)
+ return 1;
+ }
+
pool_entry = qeth_find_free_buffer_pool_entry(card);
if (!pool_entry)
return 1;
@@ -2399,13 +2709,21 @@ int qeth_init_qdio_queues(struct qeth_card *card)
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
return rc;
}
+
+ /* completion */
+ rc = qeth_cq_init(card);
+ if (rc) {
+ return rc;
+ }
+
/* outbound queue */
for (i = 0; i < card->qdio.no_out_queues; ++i) {
memset(card->qdio.out_qs[i]->qdio_bufs, 0,
QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
qeth_clear_output_buffer(card->qdio.out_qs[i],
- &card->qdio.out_qs[i]->bufs[j]);
+ card->qdio.out_qs[i]->bufs[j],
+ QETH_QDIO_BUF_EMPTY);
}
card->qdio.out_qs[i]->card = card;
card->qdio.out_qs[i]->next_buf_to_fill = 0;
@@ -2734,9 +3052,19 @@ int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf,
}
EXPORT_SYMBOL_GPL(qeth_check_qdio_errors);
+void qeth_buffer_reclaim_work(struct work_struct *work)
+{
+ struct qeth_card *card = container_of(work, struct qeth_card,
+ buffer_reclaim_work.work);
+
+ QETH_CARD_TEXT_(card, 2, "brw:%x", card->reclaim_index);
+ qeth_queue_input_buffer(card, card->reclaim_index);
+}
+
void qeth_queue_input_buffer(struct qeth_card *card, int index)
{
struct qeth_qdio_q *queue = card->qdio.in_q;
+ struct list_head *lh;
int count;
int i;
int rc;
@@ -2768,6 +3096,20 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index)
atomic_add_unless(&card->force_alloc_skb, -1, 0);
}
+ if (!count) {
+ i = 0;
+ list_for_each(lh, &card->qdio.in_buf_pool.entry_list)
+ i++;
+ if (i == card->qdio.in_buf_pool.buf_count) {
+ QETH_CARD_TEXT(card, 2, "qsarbw");
+ card->reclaim_index = index;
+ schedule_delayed_work(
+ &card->buffer_reclaim_work,
+ QETH_RECLAIM_WORK_TIME);
+ }
+ return;
+ }
+
/*
* according to old code it should be avoided to requeue all
* 128 buffers in order to benefit from PCI avoidance.
@@ -2787,8 +3129,6 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index)
qeth_get_micros() -
card->perf_stats.inbound_do_qdio_start_time;
if (rc) {
- dev_warn(&card->gdev->dev,
- "QDIO reported an error, rc=%i\n", rc);
QETH_CARD_TEXT(card, 2, "qinberr");
}
queue->next_buf_to_init = (queue->next_buf_to_init + count) %
@@ -2862,12 +3202,12 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
queue->card->perf_stats.sc_p_dp++;
queue->do_pack = 0;
/* flush packing buffers */
- buffer = &queue->bufs[queue->next_buf_to_fill];
+ buffer = queue->bufs[queue->next_buf_to_fill];
if ((atomic_read(&buffer->state) ==
QETH_QDIO_BUF_EMPTY) &&
(buffer->next_element_to_fill > 0)) {
atomic_set(&buffer->state,
- QETH_QDIO_BUF_PRIMED);
+ QETH_QDIO_BUF_PRIMED);
flush_count++;
queue->next_buf_to_fill =
(queue->next_buf_to_fill + 1) %
@@ -2878,6 +3218,7 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
return flush_count;
}
+
/*
* Called to flush a packing buffer if no more pci flags are on the queue.
* Checks if there is a packing buffer and prepares it to be flushed.
@@ -2887,7 +3228,7 @@ static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
{
struct qeth_qdio_out_buffer *buffer;
- buffer = &queue->bufs[queue->next_buf_to_fill];
+ buffer = queue->bufs[queue->next_buf_to_fill];
if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
(buffer->next_element_to_fill > 0)) {
/* it's a packing buffer */
@@ -2908,10 +3249,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
unsigned int qdio_flags;
for (i = index; i < index + count; ++i) {
- buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+ int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
+ buf = queue->bufs[bidx];
buf->buffer->element[buf->next_element_to_fill - 1].eflags |=
SBAL_EFLAGS_LAST_ENTRY;
+ if (queue->bufstates)
+ queue->bufstates[bidx].user = buf;
+
if (queue->card->info.type == QETH_CARD_TYPE_IQD)
continue;
@@ -2963,6 +3308,9 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
if (rc == QDIO_ERROR_SIGA_TARGET)
return;
QETH_CARD_TEXT(queue->card, 2, "flushbuf");
+ QETH_CARD_TEXT_(queue->card, 2, " q%d", queue->queue_no);
+ QETH_CARD_TEXT_(queue->card, 2, " idx%d", index);
+ QETH_CARD_TEXT_(queue->card, 2, " c%d", count);
QETH_CARD_TEXT_(queue->card, 2, " err%d", rc);
/* this must not happen under normal circumstances. if it
@@ -3024,14 +3372,120 @@ void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
}
EXPORT_SYMBOL_GPL(qeth_qdio_start_poll);
+int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
+{
+ int rc;
+
+ if (card->options.cq == QETH_CQ_NOTAVAILABLE) {
+ rc = -1;
+ goto out;
+ } else {
+ if (card->options.cq == cq) {
+ rc = 0;
+ goto out;
+ }
+
+ if (card->state != CARD_STATE_DOWN &&
+ card->state != CARD_STATE_RECOVER) {
+ rc = -1;
+ goto out;
+ }
+
+ qeth_free_qdio_buffers(card);
+ card->options.cq = cq;
+ rc = 0;
+ }
+out:
+ return rc;
+
+}
+EXPORT_SYMBOL_GPL(qeth_configure_cq);
+
+
+static void qeth_qdio_cq_handler(struct qeth_card *card,
+ unsigned int qdio_err,
+ unsigned int queue, int first_element, int count) {
+ struct qeth_qdio_q *cq = card->qdio.c_q;
+ int i;
+ int rc;
+
+ if (!qeth_is_cq(card, queue))
+ goto out;
+
+ QETH_CARD_TEXT_(card, 5, "qcqhe%d", first_element);
+ QETH_CARD_TEXT_(card, 5, "qcqhc%d", count);
+ QETH_CARD_TEXT_(card, 5, "qcqherr%d", qdio_err);
+
+ if (qdio_err) {
+ netif_stop_queue(card->dev);
+ qeth_schedule_recovery(card);
+ goto out;
+ }
+
+ if (card->options.performance_stats) {
+ card->perf_stats.cq_cnt++;
+ card->perf_stats.cq_start_time = qeth_get_micros();
+ }
+
+ for (i = first_element; i < first_element + count; ++i) {
+ int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
+ struct qdio_buffer *buffer = &cq->qdio_bufs[bidx];
+ int e;
+
+ e = 0;
+ while (buffer->element[e].addr) {
+ unsigned long phys_aob_addr;
+
+ phys_aob_addr = (unsigned long) buffer->element[e].addr;
+ qeth_qdio_handle_aob(card, phys_aob_addr);
+ buffer->element[e].addr = NULL;
+ buffer->element[e].eflags = 0;
+ buffer->element[e].sflags = 0;
+ buffer->element[e].length = 0;
+
+ ++e;
+ }
+
+ buffer->element[15].eflags = 0;
+ buffer->element[15].sflags = 0;
+ }
+ rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, queue,
+ card->qdio.c_q->next_buf_to_init,
+ count);
+ if (rc) {
+ dev_warn(&card->gdev->dev,
+ "QDIO reported an error, rc=%i\n", rc);
+ QETH_CARD_TEXT(card, 2, "qcqherr");
+ }
+ card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init
+ + count) % QDIO_MAX_BUFFERS_PER_Q;
+
+ netif_wake_queue(card->dev);
+
+ if (card->options.performance_stats) {
+ int delta_t = qeth_get_micros();
+ delta_t -= card->perf_stats.cq_start_time;
+ card->perf_stats.cq_time += delta_t;
+ }
+out:
+ return;
+}
+
void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err,
- unsigned int queue, int first_element, int count,
+ unsigned int queue, int first_elem, int count,
unsigned long card_ptr)
{
struct qeth_card *card = (struct qeth_card *)card_ptr;
- if (qdio_err)
+ QETH_CARD_TEXT_(card, 2, "qihq%d", queue);
+ QETH_CARD_TEXT_(card, 2, "qiec%d", qdio_err);
+
+ if (qeth_is_cq(card, queue))
+ qeth_qdio_cq_handler(card, qdio_err, queue, first_elem, count);
+ else if (qdio_err)
qeth_schedule_recovery(card);
+
+
}
EXPORT_SYMBOL_GPL(qeth_qdio_input_handler);
@@ -3057,9 +3511,45 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
qeth_get_micros();
}
for (i = first_element; i < (first_element + count); ++i) {
- buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+ int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
+ buffer = queue->bufs[bidx];
qeth_handle_send_error(card, buffer, qdio_error);
- qeth_clear_output_buffer(queue, buffer);
+
+ if (queue->bufstates &&
+ (queue->bufstates[bidx].flags &
+ QDIO_OUTBUF_STATE_FLAG_PENDING) != 0) {
+ BUG_ON(card->options.cq != QETH_CQ_ENABLED);
+
+ if (atomic_cmpxchg(&buffer->state,
+ QETH_QDIO_BUF_PRIMED,
+ QETH_QDIO_BUF_PENDING) ==
+ QETH_QDIO_BUF_PRIMED) {
+ qeth_notify_skbs(queue, buffer,
+ TX_NOTIFY_PENDING);
+ }
+ buffer->aob = queue->bufstates[bidx].aob;
+ QETH_CARD_TEXT_(queue->card, 5, "pel%d", bidx);
+ 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);
+ }
+ } else {
+ if (card->options.cq == QETH_CQ_ENABLED) {
+ enum iucv_tx_notify n;
+
+ n = qeth_compute_cq_notification(
+ buffer->buffer->element[15].sflags, 0);
+ qeth_notify_skbs(queue, buffer, n);
+ }
+
+ qeth_clear_output_buffer(queue, buffer,
+ QETH_QDIO_BUF_EMPTY);
+ }
+ qeth_cleanup_handled_pending(queue, bidx, 0);
}
atomic_sub(count, &queue->used_buffers);
/* check if we need to do something on this outbound queue */
@@ -3204,7 +3694,8 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) {
frag = &skb_shinfo(skb)->frags[cnt];
- buffer->element[element].addr = (char *)page_to_phys(frag->page)
+ buffer->element[element].addr = (char *)
+ page_to_phys(skb_frag_page(frag))
+ frag->page_offset;
buffer->element[element].length = frag->size;
buffer->element[element].eflags = SBAL_EFLAGS_MIDDLE_FRAG;
@@ -3291,7 +3782,7 @@ int qeth_do_send_packet_fast(struct qeth_card *card,
QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
/* ... now we've got the queue */
index = queue->next_buf_to_fill;
- buffer = &queue->bufs[queue->next_buf_to_fill];
+ buffer = queue->bufs[queue->next_buf_to_fill];
/*
* check if buffer is empty to make sure that we do not 'overtake'
* ourselves and try to fill a buffer that is already primed
@@ -3325,7 +3816,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
start_index = queue->next_buf_to_fill;
- buffer = &queue->bufs[queue->next_buf_to_fill];
+ buffer = queue->bufs[queue->next_buf_to_fill];
/*
* check if buffer is empty to make sure that we do not 'overtake'
* ourselves and try to fill a buffer that is already primed
@@ -3347,7 +3838,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
queue->next_buf_to_fill =
(queue->next_buf_to_fill + 1) %
QDIO_MAX_BUFFERS_PER_Q;
- buffer = &queue->bufs[queue->next_buf_to_fill];
+ buffer = queue->bufs[queue->next_buf_to_fill];
/* we did a step forward, so check buffer state
* again */
if (atomic_read(&buffer->state) !=
@@ -3925,6 +4416,20 @@ static void qeth_determine_capabilities(struct qeth_card *card)
if (rc)
QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
+ QETH_DBF_TEXT_(SETUP, 2, "qfmt%d", card->ssqd.qfmt);
+ QETH_DBF_TEXT_(SETUP, 2, "%d", card->ssqd.qdioac1);
+ QETH_DBF_TEXT_(SETUP, 2, "%d", card->ssqd.qdioac3);
+ QETH_DBF_TEXT_(SETUP, 2, "icnt%d", card->ssqd.icnt);
+ if (!((card->ssqd.qfmt != QDIO_IQDIO_QFMT) ||
+ ((card->ssqd.qdioac1 & CHSC_AC1_INITIATE_INPUTQ) == 0) ||
+ ((card->ssqd.qdioac3 & CHSC_AC3_FORMAT2_CQ_AVAILABLE) == 0))) {
+ dev_info(&card->gdev->dev,
+ "Completion Queueing supported\n");
+ } else {
+ card->options.cq = QETH_CQ_NOTAVAILABLE;
+ }
+
+
out_offline:
if (ddev_offline == 1)
ccw_device_set_offline(ddev);
@@ -3932,11 +4437,30 @@ out:
return;
}
+static inline void qeth_qdio_establish_cq(struct qeth_card *card,
+ struct qdio_buffer **in_sbal_ptrs,
+ void (**queue_start_poll) (struct ccw_device *, int, unsigned long)) {
+ int i;
+
+ if (card->options.cq == QETH_CQ_ENABLED) {
+ int offset = QDIO_MAX_BUFFERS_PER_Q *
+ (card->qdio.no_in_queues - 1);
+ i = QDIO_MAX_BUFFERS_PER_Q * (card->qdio.no_in_queues - 1);
+ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
+ in_sbal_ptrs[offset + i] = (struct qdio_buffer *)
+ virt_to_phys(card->qdio.c_q->bufs[i].buffer);
+ }
+
+ queue_start_poll[card->qdio.no_in_queues - 1] = NULL;
+ }
+}
+
static int qeth_qdio_establish(struct qeth_card *card)
{
struct qdio_initialize init_data;
char *qib_param_field;
struct qdio_buffer **in_sbal_ptrs;
+ void (**queue_start_poll) (struct ccw_device *, int, unsigned long);
struct qdio_buffer **out_sbal_ptrs;
int i, j, k;
int rc = 0;
@@ -3945,34 +4469,48 @@ static int qeth_qdio_establish(struct qeth_card *card)
qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
GFP_KERNEL);
- if (!qib_param_field)
- return -ENOMEM;
+ if (!qib_param_field) {
+ rc = -ENOMEM;
+ goto out_free_nothing;
+ }
qeth_create_qib_param_field(card, qib_param_field);
qeth_create_qib_param_field_blkt(card, qib_param_field);
- in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
+ in_sbal_ptrs = kzalloc(card->qdio.no_in_queues *
+ QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
GFP_KERNEL);
if (!in_sbal_ptrs) {
- kfree(qib_param_field);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out_free_qib_param;
}
- for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
in_sbal_ptrs[i] = (struct qdio_buffer *)
virt_to_phys(card->qdio.in_q->bufs[i].buffer);
+ }
+
+ queue_start_poll = kzalloc(sizeof(void *) * card->qdio.no_in_queues,
+ GFP_KERNEL);
+ if (!queue_start_poll) {
+ rc = -ENOMEM;
+ goto out_free_in_sbals;
+ }
+ for (i = 0; i < card->qdio.no_in_queues; ++i)
+ queue_start_poll[i] = card->discipline.start_poll;
+
+ qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll);
out_sbal_ptrs =
- kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
+ kzalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
sizeof(void *), GFP_KERNEL);
if (!out_sbal_ptrs) {
- kfree(in_sbal_ptrs);
- kfree(qib_param_field);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out_free_queue_start_poll;
}
for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) {
out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys(
- card->qdio.out_qs[i]->bufs[j].buffer);
+ card->qdio.out_qs[i]->bufs[j]->buffer);
}
memset(&init_data, 0, sizeof(struct qdio_initialize));
@@ -3980,14 +4518,15 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.q_format = qeth_get_qdio_q_format(card);
init_data.qib_param_field_format = 0;
init_data.qib_param_field = qib_param_field;
- init_data.no_input_qs = 1;
+ init_data.no_input_qs = card->qdio.no_in_queues;
init_data.no_output_qs = card->qdio.no_out_queues;
init_data.input_handler = card->discipline.input_handler;
init_data.output_handler = card->discipline.output_handler;
- init_data.queue_start_poll = card->discipline.start_poll;
+ init_data.queue_start_poll = queue_start_poll;
init_data.int_parm = (unsigned long) card;
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+ init_data.output_sbal_state_array = card->qdio.out_bufstates;
init_data.scan_threshold =
(card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32;
@@ -4004,10 +4543,26 @@ static int qeth_qdio_establish(struct qeth_card *card)
qdio_free(CARD_DDEV(card));
}
}
+
+ switch (card->options.cq) {
+ case QETH_CQ_ENABLED:
+ dev_info(&card->gdev->dev, "Completion Queue support enabled");
+ break;
+ case QETH_CQ_DISABLED:
+ dev_info(&card->gdev->dev, "Completion Queue support disabled");
+ break;
+ default:
+ break;
+ }
out:
kfree(out_sbal_ptrs);
+out_free_queue_start_poll:
+ kfree(queue_start_poll);
+out_free_in_sbals:
kfree(in_sbal_ptrs);
+out_free_qib_param:
kfree(qib_param_field);
+out_free_nothing:
return rc;
}
@@ -4144,29 +4699,36 @@ out:
}
EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card);
-static inline int qeth_create_skb_frag(struct qdio_buffer_element *element,
+static inline int qeth_create_skb_frag(struct qeth_qdio_buffer *qethbuffer,
+ struct qdio_buffer_element *element,
struct sk_buff **pskb, int offset, int *pfrag, int data_len)
{
struct page *page = virt_to_page(element->addr);
if (*pskb == NULL) {
- /* the upper protocol layers assume that there is data in the
- * skb itself. Copy a small amount (64 bytes) to make them
- * happy. */
- *pskb = dev_alloc_skb(64 + ETH_HLEN);
- if (!(*pskb))
- return -ENOMEM;
+ if (qethbuffer->rx_skb) {
+ /* only if qeth_card.options.cq == QETH_CQ_ENABLED */
+ *pskb = qethbuffer->rx_skb;
+ qethbuffer->rx_skb = NULL;
+ } else {
+ *pskb = dev_alloc_skb(QETH_RX_PULL_LEN + ETH_HLEN);
+ if (!(*pskb))
+ return -ENOMEM;
+ }
+
skb_reserve(*pskb, ETH_HLEN);
- if (data_len <= 64) {
+ if (data_len <= QETH_RX_PULL_LEN) {
memcpy(skb_put(*pskb, data_len), element->addr + offset,
data_len);
} else {
get_page(page);
- memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
- skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
- data_len - 64);
- (*pskb)->data_len += data_len - 64;
- (*pskb)->len += data_len - 64;
- (*pskb)->truesize += data_len - 64;
+ memcpy(skb_put(*pskb, QETH_RX_PULL_LEN),
+ element->addr + offset, QETH_RX_PULL_LEN);
+ skb_fill_page_desc(*pskb, *pfrag, page,
+ offset + QETH_RX_PULL_LEN,
+ data_len - QETH_RX_PULL_LEN);
+ (*pskb)->data_len += data_len - QETH_RX_PULL_LEN;
+ (*pskb)->len += data_len - QETH_RX_PULL_LEN;
+ (*pskb)->truesize += data_len - QETH_RX_PULL_LEN;
(*pfrag)++;
}
} else {
@@ -4177,15 +4739,18 @@ static inline int qeth_create_skb_frag(struct qdio_buffer_element *element,
(*pskb)->truesize += data_len;
(*pfrag)++;
}
+
+
return 0;
}
struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
- struct qdio_buffer *buffer,
+ struct qeth_qdio_buffer *qethbuffer,
struct qdio_buffer_element **__element, int *__offset,
struct qeth_hdr **hdr)
{
struct qdio_buffer_element *element = *__element;
+ struct qdio_buffer *buffer = qethbuffer->buffer;
int offset = *__offset;
struct sk_buff *skb = NULL;
int skb_len = 0;
@@ -4230,9 +4795,10 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
if (!skb_len)
return NULL;
- if ((skb_len >= card->options.rx_sg_cb) &&
- (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
- (!atomic_read(&card->force_alloc_skb))) {
+ if (((skb_len >= card->options.rx_sg_cb) &&
+ (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
+ (!atomic_read(&card->force_alloc_skb))) ||
+ (card->options.cq == QETH_CQ_ENABLED)) {
use_rx_sg = 1;
} else {
skb = dev_alloc_skb(skb_len + headroom);
@@ -4247,8 +4813,8 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
data_len = min(skb_len, (int)(element->length - offset));
if (data_len) {
if (use_rx_sg) {
- if (qeth_create_skb_frag(element, &skb, offset,
- &frag, data_len))
+ if (qeth_create_skb_frag(qethbuffer, element,
+ &skb, offset, &frag, data_len))
goto no_mem;
} else {
memcpy(skb_put(skb, data_len), data_ptr,
@@ -4650,6 +5216,8 @@ static struct {
{"tx do_QDIO count"},
{"tx csum"},
{"tx lin"},
+ {"cq handler count"},
+ {"cq handler time"}
};
int qeth_core_get_sset_count(struct net_device *dev, int stringset)
@@ -4708,6 +5276,8 @@ void qeth_core_get_ethtool_stats(struct net_device *dev,
data[32] = card->perf_stats.outbound_do_qdio_cnt;
data[33] = card->perf_stats.tx_csum;
data[34] = card->perf_stats.tx_lin;
+ data[35] = card->perf_stats.cq_cnt;
+ data[36] = card->perf_stats.cq_time;
}
EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
@@ -4866,7 +5436,16 @@ static int __init qeth_core_init(void)
goto slab_err;
}
+ qeth_qdio_outbuf_cache = kmem_cache_create("qeth_buf",
+ sizeof(struct qeth_qdio_out_buffer), 0, 0, NULL);
+ if (!qeth_qdio_outbuf_cache) {
+ rc = -ENOMEM;
+ goto cqslab_err;
+ }
+
return 0;
+cqslab_err:
+ kmem_cache_destroy(qeth_core_header_cache);
slab_err:
root_device_unregister(qeth_core_root_dev);
register_err:
@@ -4891,6 +5470,7 @@ static void __exit qeth_core_exit(void)
&driver_attr_group);
ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
ccw_driver_unregister(&qeth_ccw_driver);
+ kmem_cache_destroy(qeth_qdio_outbuf_cache);
kmem_cache_destroy(qeth_core_header_cache);
qeth_unregister_dbf_views();
pr_info("core functions removed\n");
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index b70b47fbd6cd..a21ae3d549db 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -409,7 +409,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
BUG_ON(!budget);
while (budget) {
skb = qeth_core_get_next_skb(card,
- card->qdio.in_q->bufs[card->rx.b_index].buffer,
+ &card->qdio.in_q->bufs[card->rx.b_index],
&card->rx.b_element, &card->rx.e_offset, &hdr);
if (!skb) {
*done = 1;
@@ -925,7 +925,7 @@ static const struct net_device_ops qeth_l2_netdev_ops = {
.ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l2_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = qeth_l2_set_multicast_list,
+ .ndo_set_rx_mode = qeth_l2_set_multicast_list,
.ndo_do_ioctl = qeth_l2_do_ioctl,
.ndo_set_mac_address = qeth_l2_set_mac_address,
.ndo_change_mtu = qeth_change_mtu,
diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h
index 14a43aeb0c2a..e367315a63f0 100644
--- a/drivers/s390/net/qeth_l3.h
+++ b/drivers/s390/net/qeth_l3.h
@@ -63,5 +63,9 @@ int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions,
const u8 *);
int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *);
+struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions);
+int qeth_l3_add_ip(struct qeth_card *, struct qeth_ipaddr *);
+int qeth_l3_delete_ip(struct qeth_card *, struct qeth_ipaddr *);
+void qeth_l3_set_ip_addr_list(struct qeth_card *);
#endif /* __QETH_L3_H__ */
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index fafb8c299540..e4c1176ee25b 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -29,6 +29,7 @@
#include <net/ip.h>
#include <net/arp.h>
#include <net/ip6_checksum.h>
+#include <net/iucv/af_iucv.h>
#include "qeth_l3.h"
@@ -267,7 +268,7 @@ static int __qeth_l3_insert_ip_todo(struct qeth_card *card,
}
}
-static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
{
unsigned long flags;
int rc = 0;
@@ -286,7 +287,7 @@ static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
return rc;
}
-static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
{
unsigned long flags;
int rc = 0;
@@ -305,7 +306,7 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
}
-static struct qeth_ipaddr *qeth_l3_get_addr_buffer(
+struct qeth_ipaddr *qeth_l3_get_addr_buffer(
enum qeth_prot_versions prot)
{
struct qeth_ipaddr *addr;
@@ -421,7 +422,7 @@ again:
list_splice(&fail_list, &card->ip_list);
}
-static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
+void qeth_l3_set_ip_addr_list(struct qeth_card *card)
{
struct list_head *tbd_list;
struct qeth_ipaddr *todo, *addr;
@@ -438,7 +439,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
spin_lock_irqsave(&card->ip_lock, flags);
tbd_list = card->ip_tbd_list;
- card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
+ card->ip_tbd_list = kzalloc(sizeof(struct list_head), GFP_ATOMIC);
if (!card->ip_tbd_list) {
QETH_CARD_TEXT(card, 0, "silnomem");
card->ip_tbd_list = tbd_list;
@@ -1414,7 +1415,7 @@ static int qeth_l3_send_checksum_command(struct qeth_card *card)
return 0;
}
-int qeth_l3_set_rx_csum(struct qeth_card *card, int on)
+static int qeth_l3_set_rx_csum(struct qeth_card *card, int on)
{
int rc = 0;
@@ -1993,12 +1994,13 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
__u16 vlan_tag = 0;
int is_vlan;
unsigned int len;
+ __u16 magic;
*done = 0;
BUG_ON(!budget);
while (budget) {
skb = qeth_core_get_next_skb(card,
- card->qdio.in_q->bufs[card->rx.b_index].buffer,
+ &card->qdio.in_q->bufs[card->rx.b_index],
&card->rx.b_element, &card->rx.e_offset, &hdr);
if (!skb) {
*done = 1;
@@ -2007,12 +2009,26 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
skb->dev = card->dev;
switch (hdr->hdr.l3.id) {
case QETH_HEADER_TYPE_LAYER3:
- is_vlan = qeth_l3_rebuild_skb(card, skb, hdr,
+ magic = *(__u16 *)skb->data;
+ if ((card->info.type == QETH_CARD_TYPE_IQD) &&
+ (magic == ETH_P_AF_IUCV)) {
+ skb->protocol = ETH_P_AF_IUCV;
+ skb->pkt_type = PACKET_HOST;
+ skb->mac_header = NET_SKB_PAD;
+ skb->dev = card->dev;
+ len = skb->len;
+ card->dev->header_ops->create(skb, card->dev, 0,
+ card->dev->dev_addr, "FAKELL",
+ card->dev->addr_len);
+ netif_receive_skb(skb);
+ } else {
+ is_vlan = qeth_l3_rebuild_skb(card, skb, hdr,
&vlan_tag);
- len = skb->len;
- if (is_vlan && !card->options.sniffer)
- __vlan_hwaccel_put_tag(skb, vlan_tag);
- napi_gro_receive(&card->napi, skb);
+ len = skb->len;
+ if (is_vlan && !card->options.sniffer)
+ __vlan_hwaccel_put_tag(skb, vlan_tag);
+ napi_gro_receive(&card->napi, skb);
+ }
break;
case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
skb->pkt_type = PACKET_HOST;
@@ -2784,6 +2800,30 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
return cast_type;
}
+static void qeth_l3_fill_af_iucv_hdr(struct qeth_card *card,
+ struct qeth_hdr *hdr, struct sk_buff *skb)
+{
+ char daddr[16];
+ struct af_iucv_trans_hdr *iucv_hdr;
+
+ skb_pull(skb, 14);
+ card->dev->header_ops->create(skb, card->dev, 0,
+ card->dev->dev_addr, card->dev->dev_addr,
+ card->dev->addr_len);
+ skb_pull(skb, 14);
+ iucv_hdr = (struct af_iucv_trans_hdr *)skb->data;
+ memset(hdr, 0, sizeof(struct qeth_hdr));
+ hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
+ hdr->hdr.l3.ext_flags = 0;
+ hdr->hdr.l3.length = skb->len;
+ hdr->hdr.l3.flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST;
+ memset(daddr, 0, sizeof(daddr));
+ daddr[0] = 0xfe;
+ daddr[1] = 0x80;
+ memcpy(&daddr[8], iucv_hdr->destUserID, 8);
+ memcpy(hdr->hdr.l3.dest_addr, daddr, 16);
+}
+
static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int ipv, int cast_type)
{
@@ -2936,8 +2976,11 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
int data_offset = -1;
int nr_frags;
- if (((card->info.type == QETH_CARD_TYPE_IQD) && (!ipv)) ||
- card->options.sniffer)
+ if (((card->info.type == QETH_CARD_TYPE_IQD) &&
+ (((card->options.cq != QETH_CQ_ENABLED) && !ipv) ||
+ ((card->options.cq == QETH_CQ_ENABLED) &&
+ (skb->protocol != ETH_P_AF_IUCV)))) ||
+ card->options.sniffer)
goto tx_drop;
if ((card->state != CARD_STATE_UP) || !card->lan_online) {
@@ -2959,7 +3002,10 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) &&
(skb_shinfo(skb)->nr_frags == 0)) {
new_skb = skb;
- data_offset = ETH_HLEN;
+ if (new_skb->protocol == ETH_P_AF_IUCV)
+ data_offset = 0;
+ else
+ data_offset = ETH_HLEN;
hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
if (!hdr)
goto tx_drop;
@@ -2993,7 +3039,6 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
tag = (u16 *)(new_skb->data + 12);
*tag = __constant_htons(ETH_P_8021Q);
*(tag + 1) = htons(vlan_tx_tag_get(new_skb));
- new_skb->vlan_tci = 0;
}
}
@@ -3025,9 +3070,13 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
qeth_l3_fill_header(card, hdr, new_skb, ipv,
cast_type);
} else {
- qeth_l3_fill_header(card, hdr, new_skb, ipv,
- cast_type);
- hdr->hdr.l3.length = new_skb->len - data_offset;
+ if (new_skb->protocol == ETH_P_AF_IUCV)
+ qeth_l3_fill_af_iucv_hdr(card, hdr, new_skb);
+ else {
+ qeth_l3_fill_header(card, hdr, new_skb, ipv,
+ cast_type);
+ hdr->hdr.l3.length = new_skb->len - data_offset;
+ }
}
if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -3226,7 +3275,7 @@ static const struct net_device_ops qeth_l3_netdev_ops = {
.ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l3_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = qeth_l3_set_multicast_list,
+ .ndo_set_rx_mode = qeth_l3_set_multicast_list,
.ndo_do_ioctl = qeth_l3_do_ioctl,
.ndo_change_mtu = qeth_change_mtu,
.ndo_fix_features = qeth_l3_fix_features,
@@ -3242,7 +3291,7 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {
.ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l3_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = qeth_l3_set_multicast_list,
+ .ndo_set_rx_mode = qeth_l3_set_multicast_list,
.ndo_do_ioctl = qeth_l3_do_ioctl,
.ndo_change_mtu = qeth_change_mtu,
.ndo_fix_features = qeth_l3_fix_features,
@@ -3290,6 +3339,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
card->dev->flags |= IFF_NOARP;
card->dev->netdev_ops = &qeth_l3_netdev_ops;
qeth_l3_iqd_read_initial_mac(card);
+ if (card->options.hsuid[0])
+ memcpy(card->dev->perm_addr, card->options.hsuid, 9);
} else
return -ENODEV;
@@ -3660,7 +3711,6 @@ static int qeth_l3_ip6_event(struct notifier_block *this,
struct qeth_ipaddr *addr;
struct qeth_card *card;
-
card = qeth_l3_get_card_from_dev(dev);
if (!card)
return NOTIFY_DONE;
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c
index cd99210296e2..0ea2fbfe0e99 100644
--- a/drivers/s390/net/qeth_l3_sys.c
+++ b/drivers/s390/net/qeth_l3_sys.c
@@ -9,7 +9,7 @@
*/
#include <linux/slab.h>
-
+#include <asm/ebcdic.h>
#include "qeth_l3.h"
#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
@@ -308,6 +308,8 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
if (card->info.type != QETH_CARD_TYPE_IQD)
return -EPERM;
+ if (card->options.cq == QETH_CQ_ENABLED)
+ return -EPERM;
mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
@@ -347,6 +349,111 @@ out:
static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show,
qeth_l3_dev_sniffer_store);
+
+static ssize_t qeth_l3_dev_hsuid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct qeth_card *card = dev_get_drvdata(dev);
+ char tmp_hsuid[9];
+
+ if (!card)
+ return -EINVAL;
+
+ if (card->info.type != QETH_CARD_TYPE_IQD)
+ return -EPERM;
+
+ if (card->state == CARD_STATE_DOWN)
+ return -EPERM;
+
+ memcpy(tmp_hsuid, card->options.hsuid, sizeof(tmp_hsuid));
+ EBCASC(tmp_hsuid, 8);
+ return sprintf(buf, "%s\n", tmp_hsuid);
+}
+
+static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct qeth_card *card = dev_get_drvdata(dev);
+ struct qeth_ipaddr *addr;
+ char *tmp;
+ int i;
+
+ if (!card)
+ return -EINVAL;
+
+ if (card->info.type != QETH_CARD_TYPE_IQD)
+ return -EPERM;
+ if (card->state != CARD_STATE_DOWN &&
+ card->state != CARD_STATE_RECOVER)
+ return -EPERM;
+ if (card->options.sniffer)
+ return -EPERM;
+ if (card->options.cq == QETH_CQ_NOTAVAILABLE)
+ return -EPERM;
+
+ tmp = strsep((char **)&buf, "\n");
+ if (strlen(tmp) > 8)
+ return -EINVAL;
+
+ if (card->options.hsuid[0]) {
+ /* delete old ip address */
+ addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
+ if (addr != NULL) {
+ addr->u.a6.addr.s6_addr32[0] = 0xfe800000;
+ addr->u.a6.addr.s6_addr32[1] = 0x00000000;
+ for (i = 8; i < 16; i++)
+ addr->u.a6.addr.s6_addr[i] =
+ card->options.hsuid[i - 8];
+ addr->u.a6.pfxlen = 0;
+ addr->type = QETH_IP_TYPE_NORMAL;
+ } else
+ return -ENOMEM;
+ if (!qeth_l3_delete_ip(card, addr))
+ kfree(addr);
+ qeth_l3_set_ip_addr_list(card);
+ }
+
+ if (strlen(tmp) == 0) {
+ /* delete ip address only */
+ card->options.hsuid[0] = '\0';
+ if (card->dev)
+ memcpy(card->dev->perm_addr, card->options.hsuid, 9);
+ qeth_configure_cq(card, QETH_CQ_DISABLED);
+ return count;
+ }
+
+ if (qeth_configure_cq(card, QETH_CQ_ENABLED))
+ return -EPERM;
+
+ for (i = 0; i < 8; i++)
+ card->options.hsuid[i] = ' ';
+ card->options.hsuid[8] = '\0';
+ strncpy(card->options.hsuid, tmp, strlen(tmp));
+ ASCEBC(card->options.hsuid, 8);
+ if (card->dev)
+ memcpy(card->dev->perm_addr, card->options.hsuid, 9);
+
+ addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
+ if (addr != NULL) {
+ addr->u.a6.addr.s6_addr32[0] = 0xfe800000;
+ addr->u.a6.addr.s6_addr32[1] = 0x00000000;
+ for (i = 8; i < 16; i++)
+ addr->u.a6.addr.s6_addr[i] = card->options.hsuid[i - 8];
+ addr->u.a6.pfxlen = 0;
+ addr->type = QETH_IP_TYPE_NORMAL;
+ } else
+ return -ENOMEM;
+ if (!qeth_l3_add_ip(card, addr))
+ kfree(addr);
+ qeth_l3_set_ip_addr_list(card);
+
+ return count;
+}
+
+static DEVICE_ATTR(hsuid, 0644, qeth_l3_dev_hsuid_show,
+ qeth_l3_dev_hsuid_store);
+
+
static struct attribute *qeth_l3_device_attrs[] = {
&dev_attr_route4.attr,
&dev_attr_route6.attr,
@@ -354,6 +461,7 @@ static struct attribute *qeth_l3_device_attrs[] = {
&dev_attr_broadcast_mode.attr,
&dev_attr_canonical_macaddr.attr,
&dev_attr_sniffer.attr,
+ &dev_attr_hsuid.attr,
NULL,
};
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 96d1462e0bf5..967e7b70e977 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -163,6 +163,42 @@ void zfcp_dbf_hba_bit_err(char *tag, struct zfcp_fsf_req *req)
spin_unlock_irqrestore(&dbf->hba_lock, flags);
}
+/**
+ * zfcp_dbf_hba_def_err - trace event for deferred error messages
+ * @adapter: pointer to struct zfcp_adapter
+ * @req_id: request id which caused the deferred error message
+ * @scount: number of sbals incl. the signaling sbal
+ * @pl: array of all involved sbals
+ */
+void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount,
+ void **pl)
+{
+ struct zfcp_dbf *dbf = adapter->dbf;
+ struct zfcp_dbf_pay *payload = &dbf->pay_buf;
+ unsigned long flags;
+ u16 length;
+
+ if (!pl)
+ return;
+
+ spin_lock_irqsave(&dbf->pay_lock, flags);
+ memset(payload, 0, sizeof(*payload));
+
+ memcpy(payload->area, "def_err", 7);
+ payload->fsf_req_id = req_id;
+ payload->counter = 0;
+ length = min((u16)sizeof(struct qdio_buffer),
+ (u16)ZFCP_DBF_PAY_MAX_REC);
+
+ while ((char *)pl[payload->counter] && payload->counter < scount) {
+ memcpy(payload->data, (char *)pl[payload->counter], length);
+ debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length));
+ payload->counter++;
+ }
+
+ spin_unlock_irqrestore(&dbf->pay_lock, flags);
+}
+
static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec,
struct zfcp_adapter *adapter,
struct zfcp_port *port,
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 527ba48eea57..ed5d921e82cd 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -72,6 +72,7 @@ struct zfcp_reqlist;
#define ZFCP_STATUS_COMMON_NOESC 0x00200000
/* adapter status */
+#define ZFCP_STATUS_ADAPTER_MB_ACT 0x00000001
#define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002
#define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004
#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008
@@ -314,4 +315,10 @@ struct zfcp_fsf_req {
void (*handler)(struct zfcp_fsf_req *);
};
+static inline
+int zfcp_adapter_multi_buffer_active(struct zfcp_adapter *adapter)
+{
+ return atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_MB_ACT;
+}
+
#endif /* ZFCP_DEF_H */
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 03627cfd81cd..2302e1cfb76c 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -53,6 +53,7 @@ extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **);
extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 022fb6a8cb83..e9a787e2e6a5 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -936,39 +936,47 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
struct scatterlist *sg_resp)
{
struct zfcp_adapter *adapter = req->adapter;
+ struct zfcp_qdio *qdio = adapter->qdio;
+ struct fsf_qtcb *qtcb = req->qtcb;
u32 feat = adapter->adapter_features;
- int bytes;
- if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
- if (!zfcp_qdio_sg_one_sbale(sg_req) ||
- !zfcp_qdio_sg_one_sbale(sg_resp))
- return -EOPNOTSUPP;
+ if (zfcp_adapter_multi_buffer_active(adapter)) {
+ if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
+ return -EIO;
+ if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
+ return -EIO;
- zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req,
- sg_req, sg_resp);
+ zfcp_qdio_set_data_div(qdio, &req->qdio_req,
+ zfcp_qdio_sbale_count(sg_req));
+ zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
+ zfcp_qdio_set_scount(qdio, &req->qdio_req);
return 0;
}
/* use single, unchained SBAL if it can hold the request */
if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) {
- zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req,
+ zfcp_fsf_setup_ct_els_unchained(qdio, &req->qdio_req,
sg_req, sg_resp);
return 0;
}
- bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req, sg_req);
- if (bytes <= 0)
+ if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS))
+ return -EOPNOTSUPP;
+
+ if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
return -EIO;
- zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
- req->qtcb->bottom.support.req_buf_length = bytes;
- zfcp_qdio_skip_to_last_sbale(&req->qdio_req);
- bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req,
- sg_resp);
- req->qtcb->bottom.support.resp_buf_length = bytes;
- if (bytes <= 0)
+ qtcb->bottom.support.req_buf_length = zfcp_qdio_real_bytes(sg_req);
+
+ zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
+ zfcp_qdio_skip_to_last_sbale(qdio, &req->qdio_req);
+
+ if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
return -EIO;
- zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
+
+ qtcb->bottom.support.resp_buf_length = zfcp_qdio_real_bytes(sg_resp);
+
+ zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
return 0;
}
@@ -1119,7 +1127,8 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
- zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
+ if (!zfcp_adapter_multi_buffer_active(adapter))
+ zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, timeout);
@@ -2162,7 +2171,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
struct zfcp_fsf_req *req;
struct fcp_cmnd *fcp_cmnd;
u8 sbtype = SBAL_SFLAGS0_TYPE_READ;
- int real_bytes, retval = -EIO, dix_bytes = 0;
+ int retval = -EIO;
struct scsi_device *sdev = scsi_cmnd->device;
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
@@ -2207,7 +2216,8 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
io->ref_tag_value = scsi_get_lba(scsi_cmnd) & 0xFFFFFFFF;
}
- zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);
+ if (zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction))
+ goto failed_scsi_cmnd;
fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0);
@@ -2215,18 +2225,22 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
if (scsi_prot_sg_count(scsi_cmnd)) {
zfcp_qdio_set_data_div(qdio, &req->qdio_req,
scsi_prot_sg_count(scsi_cmnd));
- dix_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
+ retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
+ scsi_prot_sglist(scsi_cmnd));
+ if (retval)
+ goto failed_scsi_cmnd;
+ io->prot_data_length = zfcp_qdio_real_bytes(
scsi_prot_sglist(scsi_cmnd));
- io->prot_data_length = dix_bytes;
}
- real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
- scsi_sglist(scsi_cmnd));
-
- if (unlikely(real_bytes < 0) || unlikely(dix_bytes < 0))
+ retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
+ scsi_sglist(scsi_cmnd));
+ if (unlikely(retval))
goto failed_scsi_cmnd;
zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
+ if (zfcp_adapter_multi_buffer_active(adapter))
+ zfcp_qdio_set_scount(qdio, &req->qdio_req);
retval = zfcp_fsf_req_send(req);
if (unlikely(retval))
@@ -2328,7 +2342,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
struct zfcp_qdio *qdio = adapter->qdio;
struct zfcp_fsf_req *req = NULL;
struct fsf_qtcb_bottom_support *bottom;
- int retval = -EIO, bytes;
+ int retval = -EIO;
u8 direction;
if (!(adapter->adapter_features & FSF_FEATURE_CFDC))
@@ -2361,13 +2375,17 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
bottom->option = fsf_cfdc->option;
- bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg);
+ retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg);
- if (bytes != ZFCP_CFDC_MAX_SIZE) {
+ if (retval ||
+ (zfcp_qdio_real_bytes(fsf_cfdc->sg) != ZFCP_CFDC_MAX_SIZE)) {
zfcp_fsf_req_free(req);
+ retval = -EIO;
goto out;
}
- zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
+ zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
+ if (zfcp_adapter_multi_buffer_active(adapter))
+ zfcp_qdio_set_scount(qdio, &req->qdio_req);
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index d9c40ea73eef..df9e69f54742 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -15,6 +15,10 @@
#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
+static bool enable_multibuffer;
+module_param_named(datarouter, enable_multibuffer, bool, 0400);
+MODULE_PARM_DESC(datarouter, "Enable hardware data router support");
+
static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
{
int pos;
@@ -37,8 +41,11 @@ static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id,
dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
- if (qdio_err & QDIO_ERROR_SLSB_STATE)
+ if (qdio_err & QDIO_ERROR_SLSB_STATE) {
zfcp_qdio_siosl(adapter);
+ zfcp_erp_adapter_shutdown(adapter, 0, id);
+ return;
+ }
zfcp_erp_adapter_reopen(adapter,
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
ZFCP_STATUS_COMMON_ERP_FAILED, id);
@@ -93,9 +100,27 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
unsigned long parm)
{
struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
- int sbal_idx, sbal_no;
+ struct zfcp_adapter *adapter = qdio->adapter;
+ struct qdio_buffer_element *sbale;
+ int sbal_no, sbal_idx;
+ void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
+ u64 req_id;
+ u8 scount;
if (unlikely(qdio_err)) {
+ memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
+ if (zfcp_adapter_multi_buffer_active(adapter)) {
+ sbale = qdio->res_q[idx]->element;
+ req_id = (u64) sbale->addr;
+ scount = sbale->scount + 1; /* incl. signaling SBAL */
+
+ for (sbal_no = 0; sbal_no < scount; sbal_no++) {
+ sbal_idx = (idx + sbal_no) %
+ QDIO_MAX_BUFFERS_PER_Q;
+ pl[sbal_no] = qdio->res_q[sbal_idx];
+ }
+ zfcp_dbf_hba_def_err(adapter, req_id, scount, pl);
+ }
zfcp_qdio_handler_error(qdio, "qdires1", qdio_err);
return;
}
@@ -155,7 +180,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
static struct qdio_buffer_element *
zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
{
- if (q_req->sbale_curr == ZFCP_QDIO_LAST_SBALE_PER_SBAL)
+ if (q_req->sbale_curr == qdio->max_sbale_per_sbal - 1)
return zfcp_qdio_sbal_chain(qdio, q_req);
q_req->sbale_curr++;
return zfcp_qdio_sbale_curr(qdio, q_req);
@@ -167,13 +192,12 @@ zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
* @q_req: pointer to struct zfcp_qdio_req
* @sg: scatter-gather list
* @max_sbals: upper bound for number of SBALs to be used
- * Returns: number of bytes, or error (negativ)
+ * Returns: zero or -EINVAL on error
*/
int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
struct scatterlist *sg)
{
struct qdio_buffer_element *sbale;
- int bytes = 0;
/* set storage-block type for this request */
sbale = zfcp_qdio_sbale_req(qdio, q_req);
@@ -187,14 +211,10 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
q_req->sbal_number);
return -EINVAL;
}
-
sbale->addr = sg_virt(sg);
sbale->length = sg->length;
-
- bytes += sg->length;
}
-
- return bytes;
+ return 0;
}
static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
@@ -283,6 +303,8 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
ASCEBC(id->adapter_name, 8);
id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV;
+ if (enable_multibuffer)
+ id->qdr_ac |= QDR_AC_MULTI_BUFFER_ENABLE;
id->no_input_qs = 1;
id->no_output_qs = 1;
id->input_handler = zfcp_qdio_int_resp;
@@ -378,6 +400,17 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
atomic_set_mask(ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED,
&qdio->adapter->status);
+ if (ssqd.qdioac2 & CHSC_AC2_MULTI_BUFFER_ENABLED) {
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
+ qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER;
+ } else {
+ atomic_clear_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
+ qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER - 1;
+ }
+
+ qdio->max_sbale_per_req =
+ ZFCP_QDIO_MAX_SBALS_PER_REQ * qdio->max_sbale_per_sbal
+ - 2;
if (qdio_activate(cdev))
goto failed_qdio;
@@ -397,6 +430,11 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
+ if (adapter->scsi_host) {
+ adapter->scsi_host->sg_tablesize = qdio->max_sbale_per_req;
+ adapter->scsi_host->max_sectors = qdio->max_sbale_per_req * 8;
+ }
+
return 0;
failed_qdio:
diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h
index 54e22ace012b..8ac7f5342d29 100644
--- a/drivers/s390/scsi/zfcp_qdio.h
+++ b/drivers/s390/scsi/zfcp_qdio.h
@@ -13,20 +13,9 @@
#define ZFCP_QDIO_SBALE_LEN PAGE_SIZE
-/* DMQ bug workaround: don't use last SBALE */
-#define ZFCP_QDIO_MAX_SBALES_PER_SBAL (QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
-
-/* index of last SBALE (with respect to DMQ bug workaround) */
-#define ZFCP_QDIO_LAST_SBALE_PER_SBAL (ZFCP_QDIO_MAX_SBALES_PER_SBAL - 1)
-
/* Max SBALS for chaining */
#define ZFCP_QDIO_MAX_SBALS_PER_REQ 36
-/* max. number of (data buffer) SBALEs in largest SBAL chain
- * request ID + QTCB in SBALE 0 + 1 of first SBAL in chain */
-#define ZFCP_QDIO_MAX_SBALES_PER_REQ \
- (ZFCP_QDIO_MAX_SBALS_PER_REQ * ZFCP_QDIO_MAX_SBALES_PER_SBAL - 2)
-
/**
* struct zfcp_qdio - basic qdio data structure
* @res_q: response queue
@@ -53,6 +42,8 @@ struct zfcp_qdio {
atomic_t req_q_full;
wait_queue_head_t req_q_wq;
struct zfcp_adapter *adapter;
+ u16 max_sbale_per_sbal;
+ u16 max_sbale_per_req;
};
/**
@@ -155,7 +146,7 @@ void zfcp_qdio_fill_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
{
struct qdio_buffer_element *sbale;
- BUG_ON(q_req->sbale_curr == ZFCP_QDIO_LAST_SBALE_PER_SBAL);
+ BUG_ON(q_req->sbale_curr == qdio->max_sbale_per_sbal - 1);
q_req->sbale_curr++;
sbale = zfcp_qdio_sbale_curr(qdio, q_req);
sbale->addr = data;
@@ -195,9 +186,10 @@ int zfcp_qdio_sg_one_sbale(struct scatterlist *sg)
* @q_req: The current zfcp_qdio_req
*/
static inline
-void zfcp_qdio_skip_to_last_sbale(struct zfcp_qdio_req *q_req)
+void zfcp_qdio_skip_to_last_sbale(struct zfcp_qdio *qdio,
+ struct zfcp_qdio_req *q_req)
{
- q_req->sbale_curr = ZFCP_QDIO_LAST_SBALE_PER_SBAL;
+ q_req->sbale_curr = qdio->max_sbale_per_sbal - 1;
}
/**
@@ -228,8 +220,52 @@ void zfcp_qdio_set_data_div(struct zfcp_qdio *qdio,
{
struct qdio_buffer_element *sbale;
- sbale = &qdio->req_q[q_req->sbal_first]->element[0];
+ sbale = qdio->req_q[q_req->sbal_first]->element;
sbale->length = count;
}
+/**
+ * zfcp_qdio_sbale_count - count sbale used
+ * @sg: pointer to struct scatterlist
+ */
+static inline
+unsigned int zfcp_qdio_sbale_count(struct scatterlist *sg)
+{
+ unsigned int count = 0;
+
+ for (; sg; sg = sg_next(sg))
+ count++;
+
+ return count;
+}
+
+/**
+ * zfcp_qdio_real_bytes - count bytes used
+ * @sg: pointer to struct scatterlist
+ */
+static inline
+unsigned int zfcp_qdio_real_bytes(struct scatterlist *sg)
+{
+ unsigned int real_bytes = 0;
+
+ for (; sg; sg = sg_next(sg))
+ real_bytes += sg->length;
+
+ return real_bytes;
+}
+
+/**
+ * zfcp_qdio_set_scount - set SBAL count value
+ * @qdio: pointer to struct zfcp_qdio
+ * @q_req: The current zfcp_qdio_req
+ */
+static inline
+void zfcp_qdio_set_scount(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
+{
+ struct qdio_buffer_element *sbale;
+
+ sbale = qdio->req_q[q_req->sbal_first]->element;
+ sbale->scount = q_req->sbal_number - 1;
+}
+
#endif /* ZFCP_QDIO_H */
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 7cac873c7383..09126a9d62ff 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -24,11 +24,8 @@ module_param_named(queue_depth, default_depth, uint, 0600);
MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices");
static bool enable_dif;
-
-#ifdef CONFIG_ZFCP_DIF
-module_param_named(dif, enable_dif, bool, 0600);
+module_param_named(dif, enable_dif, bool, 0400);
MODULE_PARM_DESC(dif, "Enable DIF/DIX data integrity support");
-#endif
static bool allow_lun_scan = 1;
module_param(allow_lun_scan, bool, 0600);
@@ -309,8 +306,8 @@ static struct scsi_host_template zfcp_scsi_host_template = {
.proc_name = "zfcp",
.can_queue = 4096,
.this_id = -1,
- .sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ,
- .max_sectors = (ZFCP_QDIO_MAX_SBALES_PER_REQ * 8),
+ .sg_tablesize = 1, /* adjusted later */
+ .max_sectors = 8, /* adjusted later */
.dma_boundary = ZFCP_QDIO_SBALE_LEN - 1,
.cmd_per_lun = 1,
.use_clustering = 1,
@@ -668,9 +665,9 @@ void zfcp_scsi_set_prot(struct zfcp_adapter *adapter)
adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) {
mask |= SHOST_DIX_TYPE1_PROTECTION;
scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP);
- shost->sg_prot_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
- shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
- shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2;
+ shost->sg_prot_tablesize = adapter->qdio->max_sbale_per_req / 2;
+ shost->sg_tablesize = adapter->qdio->max_sbale_per_req / 2;
+ shost->max_sectors = shost->sg_tablesize * 8;
}
scsi_host_set_prot(shost, mask);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 3878b7395081..aa573c39f596 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -309,6 +309,7 @@ config SCSI_FC_TGT_ATTRS
config SCSI_ISCSI_ATTRS
tristate "iSCSI Transport Attributes"
depends on SCSI && NET
+ select BLK_DEV_BSGLIB
help
If you wish to export transport-specific information about
each attached iSCSI device to sysfs, say Y.
@@ -559,6 +560,15 @@ source "drivers/scsi/aic7xxx/Kconfig.aic79xx"
source "drivers/scsi/aic94xx/Kconfig"
source "drivers/scsi/mvsas/Kconfig"
+config SCSI_MVUMI
+ tristate "Marvell UMI driver"
+ depends on SCSI && PCI
+ help
+ Module for Marvell Universal Message Interface(UMI) driver
+
+ To compile this driver as a module, choose M here: the
+ module will be called mvumi.
+
config SCSI_DPT_I2O
tristate "Adaptec I2O RAID support "
depends on SCSI && PCI && VIRT_TO_BUS
@@ -1872,10 +1882,6 @@ config ZFCP
called zfcp. If you want to compile it as a module, say M here
and read <file:Documentation/kbuild/modules.txt>.
-config ZFCP_DIF
- tristate "T10 DIF/DIX support for the zfcp driver (EXPERIMENTAL)"
- depends on ZFCP && EXPERIMENTAL
-
config SCSI_PMCRAID
tristate "PMC SIERRA Linux MaxRAID adapter support"
depends on PCI && SCSI && NET
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 6153a66a8a31..2b887498be50 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -134,6 +134,7 @@ obj-$(CONFIG_SCSI_IBMVFC) += ibmvscsi/
obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o
obj-$(CONFIG_SCSI_STEX) += stex.o
obj-$(CONFIG_SCSI_MVSAS) += mvsas/
+obj-$(CONFIG_SCSI_MVUMI) += mvumi.o
obj-$(CONFIG_PS3_ROM) += ps3rom.o
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgbi/
obj-$(CONFIG_SCSI_CXGB4_ISCSI) += libiscsi.o libiscsi_tcp.o cxgbi/
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 3382475dc22d..4aa76d6f11df 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -894,16 +894,17 @@ static ssize_t aac_show_serial_number(struct device *device,
int len = 0;
if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
- len = snprintf(buf, PAGE_SIZE, "%06X\n",
+ len = snprintf(buf, 16, "%06X\n",
le32_to_cpu(dev->adapter_info.serial[0]));
if (len &&
!memcmp(&dev->supplement_adapter_info.MfgPcbaSerialNo[
sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)-len],
buf, len-1))
- len = snprintf(buf, PAGE_SIZE, "%.*s\n",
+ len = snprintf(buf, 16, "%.*s\n",
(int)sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo),
dev->supplement_adapter_info.MfgPcbaSerialNo);
- return len;
+
+ return min(len, 16);
}
static ssize_t aac_show_max_channel(struct device *device,
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c
index c20494660603..957595a7a45c 100644
--- a/drivers/scsi/aacraid/src.c
+++ b/drivers/scsi/aacraid/src.c
@@ -37,7 +37,6 @@
#include <linux/slab.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
-#include <linux/version.h>
#include <linux/completion.h>
#include <linux/time.h>
#include <linux/interrupt.h>
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index 5e6620f8dabc..6739069477de 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -31,8 +31,7 @@ config AIC79XX_CMDS_PER_DEVICE
on some devices. The upper bound is 253. 0 disables tagged queueing.
Per device tag depth can be controlled via the kernel command line
- "tag_info" option. See drivers/scsi/aic7xxx/README.aic79xx
- for details.
+ "tag_info" option. See Documentation/scsi/aic79xx.txt for details.
config AIC79XX_RESET_DELAY_MS
int "Initial bus reset delay in milli-seconds"
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 88da670a7915..55ac55ee6068 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -36,8 +36,7 @@ config AIC7XXX_CMDS_PER_DEVICE
on some devices. The upper bound is 253. 0 disables tagged queueing.
Per device tag depth can be controlled via the kernel command line
- "tag_info" option. See drivers/scsi/aic7xxx/README.aic7xxx
- for details.
+ "tag_info" option. See Documentation/scsi/aic7xxx.txt for details.
config AIC7XXX_RESET_DELAY_MS
int "Initial bus reset delay in milli-seconds"
diff --git a/drivers/scsi/aic94xx/aic94xx_dump.c b/drivers/scsi/aic94xx/aic94xx_dump.c
index 67eeba3bdb06..a16a77c8b9cf 100644
--- a/drivers/scsi/aic94xx/aic94xx_dump.c
+++ b/drivers/scsi/aic94xx/aic94xx_dump.c
@@ -29,7 +29,7 @@
*
*/
-#include "linux/pci.h"
+#include <linux/pci.h>
#include "aic94xx.h"
#include "aic94xx_reg.h"
#include "aic94xx_reg_def.h"
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index 29593275201a..fdac7c2fef37 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -906,6 +906,7 @@ int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func, void *arg)
switch (func) {
case PHY_FUNC_CLEAR_ERROR_LOG:
+ case PHY_FUNC_GET_EVENTS:
return -ENOSYS;
case PHY_FUNC_SET_LINK_RATE:
rates = arg;
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index b8a82f2c62c8..cdb15364bc69 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -660,6 +660,7 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
spin_lock(&phba->ctrl.mbox_lock);
ctrl = &phba->ctrl;
wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ memset(wrb, 0, sizeof(*wrb));
req = embedded_payload(wrb);
ctxt = &req->context;
@@ -868,3 +869,22 @@ error:
beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL);
return status;
}
+
+int beiscsi_cmd_reset_function(struct beiscsi_hba *phba)
+{
+ struct be_ctrl_info *ctrl = &phba->ctrl;
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_post_sgl_pages_req *req = embedded_payload(wrb);
+ int status;
+
+ spin_lock(&ctrl->mbox_lock);
+
+ req = embedded_payload(wrb);
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
+ status = be_mbox_notify_wait(phba);
+
+ spin_unlock(&ctrl->mbox_lock);
+ return status;
+}
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index 497eb29e5c9e..8b40a5b4366c 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -561,6 +561,8 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
struct be_dma_mem *q_mem, u32 page_offset,
u32 num_pages);
+int beiscsi_cmd_reset_function(struct beiscsi_hba *phba);
+
int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
struct be_queue_info *wrbq);
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 3cad10605023..8b002f6db6ca 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -177,9 +177,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
{
struct iscsi_conn *conn = cls_conn->dd_data;
struct beiscsi_conn *beiscsi_conn = conn->dd_data;
- struct Scsi_Host *shost =
- (struct Scsi_Host *)iscsi_session_to_shost(cls_session);
- struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
+ struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
struct beiscsi_endpoint *beiscsi_ep;
struct iscsi_endpoint *ep;
@@ -290,7 +289,7 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
int beiscsi_get_host_param(struct Scsi_Host *shost,
enum iscsi_host_param param, char *buf)
{
- struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
+ struct beiscsi_hba *phba = iscsi_host_priv(shost);
int status = 0;
SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param);
@@ -733,3 +732,56 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
}
+
+mode_t be2iscsi_attr_is_visible(int param_type, int param)
+{
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_HDRDGST_EN:
+ case ISCSI_PARAM_DATADGST_EN:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_EXP_STATSN:
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_PING_TMO:
+ case ISCSI_PARAM_RECV_TMO:
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_IMM_DATA_EN:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ case ISCSI_PARAM_ERL:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_USERNAME:
+ case ISCSI_PARAM_PASSWORD:
+ case ISCSI_PARAM_USERNAME_IN:
+ case ISCSI_PARAM_PASSWORD_IN:
+ case ISCSI_PARAM_FAST_ABORT:
+ case ISCSI_PARAM_ABORT_TMO:
+ case ISCSI_PARAM_LU_RESET_TMO:
+ case ISCSI_PARAM_IFACE_NAME:
+ case ISCSI_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
index ff60b7fd92d6..4a1f2e393f31 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.h
+++ b/drivers/scsi/be2iscsi/be_iscsi.h
@@ -26,6 +26,8 @@
#define BE2_IPV4 0x1
#define BE2_IPV6 0x10
+mode_t be2iscsi_attr_is_visible(int param_type, int param);
+
void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
struct beiscsi_offload_params *params);
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 0a9bdfa3d939..7b0a8ab71049 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -822,33 +822,47 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
struct hwi_controller *phwi_ctrlr;
struct hwi_context_memory *phwi_context;
int ret, msix_vec, i, j;
- char desc[32];
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
if (phba->msix_enabled) {
for (i = 0; i < phba->num_cpus; i++) {
- sprintf(desc, "beiscsi_msix_%04x", i);
+ phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME,
+ GFP_KERNEL);
+ if (!phba->msi_name[i]) {
+ ret = -ENOMEM;
+ goto free_msix_irqs;
+ }
+
+ sprintf(phba->msi_name[i], "beiscsi_%02x_%02x",
+ phba->shost->host_no, i);
msix_vec = phba->msix_entries[i].vector;
- ret = request_irq(msix_vec, be_isr_msix, 0, desc,
+ ret = request_irq(msix_vec, be_isr_msix, 0,
+ phba->msi_name[i],
&phwi_context->be_eq[i]);
if (ret) {
shost_printk(KERN_ERR, phba->shost,
"beiscsi_init_irqs-Failed to"
"register msix for i = %d\n", i);
- if (!i)
- return ret;
+ kfree(phba->msi_name[i]);
goto free_msix_irqs;
}
}
+ phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME, GFP_KERNEL);
+ if (!phba->msi_name[i]) {
+ ret = -ENOMEM;
+ goto free_msix_irqs;
+ }
+ sprintf(phba->msi_name[i], "beiscsi_mcc_%02x",
+ phba->shost->host_no);
msix_vec = phba->msix_entries[i].vector;
- ret = request_irq(msix_vec, be_isr_mcc, 0, "beiscsi_msix_mcc",
+ ret = request_irq(msix_vec, be_isr_mcc, 0, phba->msi_name[i],
&phwi_context->be_eq[i]);
if (ret) {
shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-"
"Failed to register beiscsi_msix_mcc\n");
- i++;
+ kfree(phba->msi_name[i]);
goto free_msix_irqs;
}
@@ -863,8 +877,11 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
}
return 0;
free_msix_irqs:
- for (j = i - 1; j == 0; j++)
+ for (j = i - 1; j >= 0; j--) {
+ kfree(phba->msi_name[j]);
+ msix_vec = phba->msix_entries[j].vector;
free_irq(msix_vec, &phwi_context->be_eq[j]);
+ }
return ret;
}
@@ -1106,7 +1123,12 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
& SOL_STS_MASK) >> 8);
flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
& SOL_FLAGS_MASK) >> 24) | 0x80;
+ if (!task->sc) {
+ if (io_task->scsi_cmnd)
+ scsi_dma_unmap(io_task->scsi_cmnd);
+ return;
+ }
task->sc->result = (DID_OK << 16) | status;
if (rsp != ISCSI_STATUS_CMD_COMPLETED) {
task->sc->result = DID_ERROR << 16;
@@ -4027,11 +4049,11 @@ static int beiscsi_mtask(struct iscsi_task *task)
TGT_DM_CMD);
AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt,
pwrb, 0);
- AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+ AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
} else {
AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
INI_RD_CMD);
- AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
+ AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
}
hwi_write_buffer(pwrb, task);
break;
@@ -4102,9 +4124,8 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
}
-static void beiscsi_remove(struct pci_dev *pcidev)
+static void beiscsi_quiesce(struct beiscsi_hba *phba)
{
- struct beiscsi_hba *phba = NULL;
struct hwi_controller *phwi_ctrlr;
struct hwi_context_memory *phwi_context;
struct be_eq_obj *pbe_eq;
@@ -4112,12 +4133,6 @@ static void beiscsi_remove(struct pci_dev *pcidev)
u8 *real_offset = 0;
u32 value = 0;
- phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev);
- if (!phba) {
- dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n");
- return;
- }
-
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
hwi_disable_intr(phba);
@@ -4125,6 +4140,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
for (i = 0; i <= phba->num_cpus; i++) {
msix_vec = phba->msix_entries[i].vector;
free_irq(msix_vec, &phwi_context->be_eq[i]);
+ kfree(phba->msi_name[i]);
}
} else
if (phba->pcidev->irq)
@@ -4152,10 +4168,40 @@ static void beiscsi_remove(struct pci_dev *pcidev)
phba->ctrl.mbox_mem_alloced.size,
phba->ctrl.mbox_mem_alloced.va,
phba->ctrl.mbox_mem_alloced.dma);
+}
+
+static void beiscsi_remove(struct pci_dev *pcidev)
+{
+
+ struct beiscsi_hba *phba = NULL;
+
+ phba = pci_get_drvdata(pcidev);
+ if (!phba) {
+ dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n");
+ return;
+ }
+
+ beiscsi_quiesce(phba);
iscsi_boot_destroy_kset(phba->boot_kset);
iscsi_host_remove(phba->shost);
pci_dev_put(phba->pcidev);
iscsi_host_free(phba->shost);
+ pci_disable_device(pcidev);
+}
+
+static void beiscsi_shutdown(struct pci_dev *pcidev)
+{
+
+ struct beiscsi_hba *phba = NULL;
+
+ phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev);
+ if (!phba) {
+ dev_err(&pcidev->dev, "beiscsi_shutdown called with no phba\n");
+ return;
+ }
+
+ beiscsi_quiesce(phba);
+ pci_disable_device(pcidev);
}
static void beiscsi_msix_enable(struct beiscsi_hba *phba)
@@ -4235,7 +4281,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
gcrashmode++;
shost_printk(KERN_ERR, phba->shost,
"Loading Driver in crashdump mode\n");
- ret = beiscsi_pci_soft_reset(phba);
+ ret = beiscsi_cmd_reset_function(phba);
if (ret) {
shost_printk(KERN_ERR, phba->shost,
"Reset Failed. Aborting Crashdump\n");
@@ -4364,37 +4410,12 @@ struct iscsi_transport beiscsi_iscsi_transport = {
.name = DRV_NAME,
.caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO |
CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD,
- .param_mask = ISCSI_MAX_RECV_DLENGTH |
- ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN |
- ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN |
- ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN |
- ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST |
- ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN |
- ISCSI_ERL |
- ISCSI_CONN_PORT |
- ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN |
- ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_INITIATOR_NAME,
.create_session = beiscsi_session_create,
.destroy_session = beiscsi_session_destroy,
.create_conn = beiscsi_conn_create,
.bind_conn = beiscsi_conn_bind,
.destroy_conn = iscsi_conn_teardown,
+ .attr_is_visible = be2iscsi_attr_is_visible,
.set_param = beiscsi_set_param,
.get_conn_param = iscsi_conn_get_param,
.get_session_param = iscsi_session_get_param,
@@ -4418,6 +4439,7 @@ static struct pci_driver beiscsi_pci_driver = {
.name = DRV_NAME,
.probe = beiscsi_dev_probe,
.remove = beiscsi_remove,
+ .shutdown = beiscsi_shutdown,
.id_table = beiscsi_pci_id_table
};
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index 5ce5170254ca..b4a06d5e5f9e 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -34,7 +34,7 @@
#include "be.h"
#define DRV_NAME "be2iscsi"
-#define BUILD_STR "2.103.298.0"
+#define BUILD_STR "4.1.239.0"
#define BE_NAME "ServerEngines BladeEngine2" \
"Linux iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
@@ -162,6 +162,8 @@ do { \
#define PAGES_REQUIRED(x) \
((x < PAGE_SIZE) ? 1 : ((x + PAGE_SIZE - 1) / PAGE_SIZE))
+#define BEISCSI_MSI_NAME 20 /* size of msi_name string */
+
enum be_mem_enum {
HWI_MEM_ADDN_CONTEXT,
HWI_MEM_WRB,
@@ -287,6 +289,7 @@ struct beiscsi_hba {
unsigned int num_cpus;
unsigned int nxt_cqid;
struct msix_entry msix_entries[MAX_CPUS + 1];
+ char *msi_name[MAX_CPUS + 1];
bool msix_enabled;
struct be_mem_descriptor *init_mem;
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index bda999ad9f52..5e19a5f820ec 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -27,7 +27,6 @@
#define __BFAD_DRV_H__
#include <linux/types.h>
-#include <linux/version.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/idr.h>
diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig
index 6a38080e35ed..cfcad8bde7cf 100644
--- a/drivers/scsi/bnx2fc/Kconfig
+++ b/drivers/scsi/bnx2fc/Kconfig
@@ -2,7 +2,8 @@ config SCSI_BNX2X_FCOE
tristate "Broadcom NetXtreme II FCoE support"
depends on PCI
select NETDEVICES
- select NETDEV_1000
+ select ETHERNET
+ select NET_VENDOR_BROADCOM
select LIBFC
select LIBFCOE
select CNIC
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 42228ca5a9d2..63de1c7cd0cb 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -58,11 +58,11 @@
#include "57xx_hsi_bnx2fc.h"
#include "bnx2fc_debug.h"
-#include "../../net/cnic_if.h"
+#include "../../net/ethernet/broadcom/cnic_if.h"
#include "bnx2fc_constants.h"
#define BNX2FC_NAME "bnx2fc"
-#define BNX2FC_VERSION "1.0.4"
+#define BNX2FC_VERSION "1.0.8"
#define PFX "bnx2fc: "
@@ -81,7 +81,7 @@
#define BNX2FC_RQ_WQES_MAX 16
#define BNX2FC_CQ_WQES_MAX (BNX2FC_SQ_WQES_MAX + BNX2FC_RQ_WQES_MAX)
-#define BNX2FC_NUM_MAX_SESS 128
+#define BNX2FC_NUM_MAX_SESS 1024
#define BNX2FC_NUM_MAX_SESS_LOG (ilog2(BNX2FC_NUM_MAX_SESS))
#define BNX2FC_MAX_OUTSTANDING_CMNDS 2048
@@ -224,6 +224,7 @@ struct bnx2fc_interface {
struct fcoe_ctlr ctlr;
u8 vlan_enabled;
int vlan_id;
+ bool enabled;
};
#define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_interface, ctlr)
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c
index d66dcbd0df10..fd382fe33f6e 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_els.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_els.c
@@ -391,18 +391,6 @@ void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg)
BNX2FC_IO_DBG(rec_req, "rec_compl: orig xid = 0x%x", orig_io_req->xid);
tgt = orig_io_req->tgt;
- if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags)) {
- BNX2FC_IO_DBG(rec_req, "completed"
- "orig_io - 0x%x\n",
- orig_io_req->xid);
- goto rec_compl_done;
- }
- if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
- BNX2FC_IO_DBG(rec_req, "abts in prog "
- "orig_io - 0x%x\n",
- orig_io_req->xid);
- goto rec_compl_done;
- }
/* Handle REC timeout case */
if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rec_req->req_flags)) {
BNX2FC_IO_DBG(rec_req, "timed out, abort "
@@ -433,6 +421,20 @@ void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg)
}
goto rec_compl_done;
}
+
+ if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags)) {
+ BNX2FC_IO_DBG(rec_req, "completed"
+ "orig_io - 0x%x\n",
+ orig_io_req->xid);
+ goto rec_compl_done;
+ }
+ if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
+ BNX2FC_IO_DBG(rec_req, "abts in prog "
+ "orig_io - 0x%x\n",
+ orig_io_req->xid);
+ goto rec_compl_done;
+ }
+
mp_req = &(rec_req->mp_req);
fc_hdr = &(mp_req->resp_fc_hdr);
resp_len = mp_req->resp_len;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 7cb2cd48b17b..85bcc4b55965 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
#define DRV_MODULE_NAME "bnx2fc"
#define DRV_MODULE_VERSION BNX2FC_VERSION
-#define DRV_MODULE_RELDATE "Jun 23, 2011"
+#define DRV_MODULE_RELDATE "Oct 02, 2011"
static char version[] __devinitdata =
@@ -56,6 +56,7 @@ static struct scsi_host_template bnx2fc_shost_template;
static struct fc_function_template bnx2fc_transport_function;
static struct fc_function_template bnx2fc_vport_xport_function;
static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode);
+static void __bnx2fc_destroy(struct bnx2fc_interface *interface);
static int bnx2fc_destroy(struct net_device *net_device);
static int bnx2fc_enable(struct net_device *netdev);
static int bnx2fc_disable(struct net_device *netdev);
@@ -64,7 +65,6 @@ static void bnx2fc_recv_frame(struct sk_buff *skb);
static void bnx2fc_start_disc(struct bnx2fc_interface *interface);
static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev);
-static int bnx2fc_net_config(struct fc_lport *lp);
static int bnx2fc_lport_config(struct fc_lport *lport);
static int bnx2fc_em_config(struct fc_lport *lport);
static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba);
@@ -78,6 +78,7 @@ static void bnx2fc_destroy_work(struct work_struct *work);
static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev);
static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device
*phys_dev);
+static inline void bnx2fc_interface_put(struct bnx2fc_interface *interface);
static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic);
static int bnx2fc_fw_init(struct bnx2fc_hba *hba);
@@ -98,6 +99,25 @@ static struct notifier_block bnx2fc_cpu_notifier = {
.notifier_call = bnx2fc_cpu_callback,
};
+static inline struct net_device *bnx2fc_netdev(const struct fc_lport *lport)
+{
+ return ((struct bnx2fc_interface *)
+ ((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
+}
+
+/**
+ * bnx2fc_get_lesb() - Fill the FCoE Link Error Status Block
+ * @lport: the local port
+ * @fc_lesb: the link error status block
+ */
+static void bnx2fc_get_lesb(struct fc_lport *lport,
+ struct fc_els_lesb *fc_lesb)
+{
+ struct net_device *netdev = bnx2fc_netdev(lport);
+
+ __fcoe_get_lesb(lport, fc_lesb, netdev);
+}
+
static void bnx2fc_clean_rx_queue(struct fc_lport *lp)
{
struct fcoe_percpu_s *bg;
@@ -302,7 +322,7 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
return -ENOMEM;
}
frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
- cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
+ cp = kmap_atomic(skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ)
+ frag->page_offset;
} else {
cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
@@ -545,6 +565,14 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
break;
}
}
+
+ if (fh->fh_r_ctl == FC_RCTL_BA_ABTS) {
+ /* Drop incoming ABTS */
+ put_cpu();
+ kfree_skb(skb);
+ return;
+ }
+
if (le32_to_cpu(fr_crc(fp)) !=
~crc32(~0, skb->data, fr_len)) {
if (stats->InvalidCRCCount < 5)
@@ -673,7 +701,7 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport)
struct net_device *netdev = interface->netdev;
struct ethtool_cmd ecmd;
- if (!dev_ethtool_get_settings(netdev, &ecmd)) {
+ if (!__ethtool_get_settings(netdev, &ecmd)) {
lport->link_supported_speeds &=
~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
if (ecmd.supported & (SUPPORTED_1000baseT_Half |
@@ -727,7 +755,7 @@ void bnx2fc_get_link_state(struct bnx2fc_hba *hba)
clear_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
}
-static int bnx2fc_net_config(struct fc_lport *lport)
+static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev)
{
struct bnx2fc_hba *hba;
struct bnx2fc_interface *interface;
@@ -753,11 +781,16 @@ static int bnx2fc_net_config(struct fc_lport *lport)
bnx2fc_link_speed_update(lport);
if (!lport->vport) {
- wwnn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, 1, 0);
+ if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN))
+ wwnn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr,
+ 1, 0);
BNX2FC_HBA_DBG(lport, "WWNN = 0x%llx\n", wwnn);
fc_set_wwnn(lport, wwnn);
- wwpn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, 2, 0);
+ if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN))
+ wwpn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr,
+ 2, 0);
+
BNX2FC_HBA_DBG(lport, "WWPN = 0x%llx\n", wwpn);
fc_set_wwpn(lport, wwpn);
}
@@ -769,8 +802,8 @@ static void bnx2fc_destroy_timer(unsigned long data)
{
struct bnx2fc_hba *hba = (struct bnx2fc_hba *)data;
- BNX2FC_MISC_DBG("ERROR:bnx2fc_destroy_timer - "
- "Destroy compl not received!!\n");
+ printk(KERN_ERR PFX "ERROR:bnx2fc_destroy_timer - "
+ "Destroy compl not received!!\n");
set_bit(BNX2FC_FLAG_DESTROY_CMPL, &hba->flags);
wake_up_interruptible(&hba->destroy_wait);
}
@@ -783,7 +816,7 @@ static void bnx2fc_destroy_timer(unsigned long data)
* @vlan_id: vlan id - associated vlan id with this event
*
* Handles NETDEV_UP, NETDEV_DOWN, NETDEV_GOING_DOWN,NETDEV_CHANGE and
- * NETDEV_CHANGE_MTU events
+ * NETDEV_CHANGE_MTU events. Handle NETDEV_UNREGISTER only for vlans.
*/
static void bnx2fc_indicate_netevent(void *context, unsigned long event,
u16 vlan_id)
@@ -791,12 +824,11 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
struct fc_lport *lport;
struct fc_lport *vport;
- struct bnx2fc_interface *interface;
+ struct bnx2fc_interface *interface, *tmp;
int wait_for_upload = 0;
u32 link_possible = 1;
- /* Ignore vlans for now */
- if (vlan_id != 0)
+ if (vlan_id != 0 && event != NETDEV_UNREGISTER)
return;
switch (event) {
@@ -820,6 +852,18 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
case NETDEV_CHANGE:
break;
+ case NETDEV_UNREGISTER:
+ if (!vlan_id)
+ return;
+ mutex_lock(&bnx2fc_dev_lock);
+ list_for_each_entry_safe(interface, tmp, &if_list, list) {
+ if (interface->hba == hba &&
+ interface->vlan_id == (vlan_id & VLAN_VID_MASK))
+ __bnx2fc_destroy(interface);
+ }
+ mutex_unlock(&bnx2fc_dev_lock);
+ return;
+
default:
printk(KERN_ERR PFX "Unkonwn netevent %ld", event);
return;
@@ -838,8 +882,15 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
bnx2fc_link_speed_update(lport);
if (link_possible && !bnx2fc_link_ok(lport)) {
- printk(KERN_ERR "indicate_netevent: ctlr_link_up\n");
- fcoe_ctlr_link_up(&interface->ctlr);
+ /* Reset max recv frame size to default */
+ fc_set_mfs(lport, BNX2FC_MFS);
+ /*
+ * ctlr link up will only be handled during
+ * enable to avoid sending discovery solicitation
+ * on a stale vlan
+ */
+ if (interface->enabled)
+ fcoe_ctlr_link_up(&interface->ctlr);
} else if (fcoe_ctlr_link_down(&interface->ctlr)) {
mutex_lock(&lport->lp_mutex);
list_for_each_entry(vport, &lport->vports, list)
@@ -995,15 +1046,28 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
struct bnx2fc_interface *interface = port->priv;
struct net_device *netdev = interface->netdev;
struct fc_lport *vn_port;
+ int rc;
+ char buf[32];
+
+ rc = fcoe_validate_vport_create(vport);
+ if (rc) {
+ fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf));
+ printk(KERN_ERR PFX "Failed to create vport, "
+ "WWPN (0x%s) already exists\n",
+ buf);
+ return rc;
+ }
if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) {
printk(KERN_ERR PFX "vn ports cannot be created on"
"this interface\n");
return -EIO;
}
+ rtnl_lock();
mutex_lock(&bnx2fc_dev_lock);
vn_port = bnx2fc_if_create(interface, &vport->dev, 1);
mutex_unlock(&bnx2fc_dev_lock);
+ rtnl_unlock();
if (IS_ERR(vn_port)) {
printk(KERN_ERR PFX "bnx2fc_vport_create (%s) failed\n",
@@ -1022,16 +1086,46 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
return 0;
}
+static void bnx2fc_free_vport(struct bnx2fc_hba *hba, struct fc_lport *lport)
+{
+ struct bnx2fc_lport *blport, *tmp;
+
+ spin_lock_bh(&hba->hba_lock);
+ list_for_each_entry_safe(blport, tmp, &hba->vports, list) {
+ if (blport->lport == lport) {
+ list_del(&blport->list);
+ kfree(blport);
+ }
+ }
+ spin_unlock_bh(&hba->hba_lock);
+}
+
static int bnx2fc_vport_destroy(struct fc_vport *vport)
{
struct Scsi_Host *shost = vport_to_shost(vport);
struct fc_lport *n_port = shost_priv(shost);
struct fc_lport *vn_port = vport->dd_data;
struct fcoe_port *port = lport_priv(vn_port);
+ struct bnx2fc_interface *interface = port->priv;
+ struct fc_lport *v_port;
+ bool found = false;
mutex_lock(&n_port->lp_mutex);
+ list_for_each_entry(v_port, &n_port->vports, list)
+ if (v_port->vport == vport) {
+ found = true;
+ break;
+ }
+
+ if (!found) {
+ mutex_unlock(&n_port->lp_mutex);
+ return -ENOENT;
+ }
list_del(&vn_port->list);
mutex_unlock(&n_port->lp_mutex);
+ bnx2fc_free_vport(interface->hba, port->lport);
+ bnx2fc_port_shutdown(port->lport);
+ bnx2fc_interface_put(interface);
queue_work(bnx2fc_wq, &port->destroy_work);
return 0;
}
@@ -1052,7 +1146,7 @@ static int bnx2fc_vport_disable(struct fc_vport *vport, bool disable)
}
-static int bnx2fc_netdev_setup(struct bnx2fc_interface *interface)
+static int bnx2fc_interface_setup(struct bnx2fc_interface *interface)
{
struct net_device *netdev = interface->netdev;
struct net_device *physdev = interface->hba->phys_dev;
@@ -1250,7 +1344,7 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba,
interface->ctlr.get_src_addr = bnx2fc_get_src_mac;
set_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags);
- rc = bnx2fc_netdev_setup(interface);
+ rc = bnx2fc_interface_setup(interface);
if (!rc)
return interface;
@@ -1316,7 +1410,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
fc_set_wwpn(lport, vport->port_name);
}
/* Configure netdev and networking properties of the lport */
- rc = bnx2fc_net_config(lport);
+ rc = bnx2fc_net_config(lport, interface->netdev);
if (rc) {
printk(KERN_ERR PFX "Error on bnx2fc_net_config\n");
goto lp_config_err;
@@ -1370,7 +1464,7 @@ free_blport:
return NULL;
}
-static void bnx2fc_netdev_cleanup(struct bnx2fc_interface *interface)
+static void bnx2fc_net_cleanup(struct bnx2fc_interface *interface)
{
/* Dont listen for Ethernet packets anymore */
__dev_remove_pack(&interface->fcoe_packet_type);
@@ -1378,10 +1472,11 @@ static void bnx2fc_netdev_cleanup(struct bnx2fc_interface *interface)
synchronize_net();
}
-static void bnx2fc_if_destroy(struct fc_lport *lport, struct bnx2fc_hba *hba)
+static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface)
{
+ struct fc_lport *lport = interface->ctlr.lp;
struct fcoe_port *port = lport_priv(lport);
- struct bnx2fc_lport *blport, *tmp;
+ struct bnx2fc_hba *hba = interface->hba;
/* Stop the transmit retry timer */
del_timer_sync(&port->timer);
@@ -1389,6 +1484,14 @@ static void bnx2fc_if_destroy(struct fc_lport *lport, struct bnx2fc_hba *hba)
/* Free existing transmit skbs */
fcoe_clean_pending_queue(lport);
+ bnx2fc_net_cleanup(interface);
+
+ bnx2fc_free_vport(hba, lport);
+}
+
+static void bnx2fc_if_destroy(struct fc_lport *lport)
+{
+
/* Free queued packets for the receive thread */
bnx2fc_clean_rx_queue(lport);
@@ -1405,19 +1508,22 @@ static void bnx2fc_if_destroy(struct fc_lport *lport, struct bnx2fc_hba *hba)
/* Free memory used by statistical counters */
fc_lport_free_stats(lport);
- spin_lock_bh(&hba->hba_lock);
- list_for_each_entry_safe(blport, tmp, &hba->vports, list) {
- if (blport->lport == lport) {
- list_del(&blport->list);
- kfree(blport);
- }
- }
- spin_unlock_bh(&hba->hba_lock);
-
/* Release Scsi_Host */
scsi_host_put(lport->host);
}
+static void __bnx2fc_destroy(struct bnx2fc_interface *interface)
+{
+ struct fc_lport *lport = interface->ctlr.lp;
+ struct fcoe_port *port = lport_priv(lport);
+
+ bnx2fc_interface_cleanup(interface);
+ bnx2fc_stop(interface);
+ list_del(&interface->list);
+ bnx2fc_interface_put(interface);
+ queue_work(bnx2fc_wq, &port->destroy_work);
+}
+
/**
* bnx2fc_destroy - Destroy a bnx2fc FCoE interface
*
@@ -1431,8 +1537,6 @@ static void bnx2fc_if_destroy(struct fc_lport *lport, struct bnx2fc_hba *hba)
static int bnx2fc_destroy(struct net_device *netdev)
{
struct bnx2fc_interface *interface = NULL;
- struct bnx2fc_hba *hba;
- struct fc_lport *lport;
int rc = 0;
rtnl_lock();
@@ -1445,15 +1549,9 @@ static int bnx2fc_destroy(struct net_device *netdev)
goto netdev_err;
}
- hba = interface->hba;
- bnx2fc_netdev_cleanup(interface);
- lport = interface->ctlr.lp;
- bnx2fc_stop(interface);
- list_del(&interface->list);
destroy_workqueue(interface->timer_work_queue);
- bnx2fc_interface_put(interface);
- bnx2fc_if_destroy(lport, hba);
+ __bnx2fc_destroy(interface);
netdev_err:
mutex_unlock(&bnx2fc_dev_lock);
@@ -1465,22 +1563,13 @@ static void bnx2fc_destroy_work(struct work_struct *work)
{
struct fcoe_port *port;
struct fc_lport *lport;
- struct bnx2fc_interface *interface;
- struct bnx2fc_hba *hba;
port = container_of(work, struct fcoe_port, destroy_work);
lport = port->lport;
- interface = port->priv;
- hba = interface->hba;
BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n");
- bnx2fc_port_shutdown(lport);
- rtnl_lock();
- mutex_lock(&bnx2fc_dev_lock);
- bnx2fc_if_destroy(lport, hba);
- mutex_unlock(&bnx2fc_dev_lock);
- rtnl_unlock();
+ bnx2fc_if_destroy(lport);
}
static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba)
@@ -1659,6 +1748,7 @@ static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba)
wait_event_interruptible(hba->destroy_wait,
test_bit(BNX2FC_FLAG_DESTROY_CMPL,
&hba->flags));
+ clear_bit(BNX2FC_FLAG_DESTROY_CMPL, &hba->flags);
/* This should never happen */
if (signal_pending(current))
flush_signals(current);
@@ -1721,7 +1811,7 @@ static void bnx2fc_start_disc(struct bnx2fc_interface *interface)
lport = interface->ctlr.lp;
BNX2FC_HBA_DBG(lport, "calling fc_fabric_login\n");
- if (!bnx2fc_link_ok(lport)) {
+ if (!bnx2fc_link_ok(lport) && interface->enabled) {
BNX2FC_HBA_DBG(lport, "ctlr_link_up\n");
fcoe_ctlr_link_up(&interface->ctlr);
fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
@@ -1735,6 +1825,11 @@ static void bnx2fc_start_disc(struct bnx2fc_interface *interface)
if (++wait_cnt > 12)
break;
}
+
+ /* Reset max receive frame size to default */
+ if (fc_set_mfs(lport, BNX2FC_MFS))
+ return;
+
fc_lport_init(lport);
fc_fabric_login(lport);
}
@@ -1798,6 +1893,7 @@ static int bnx2fc_disable(struct net_device *netdev)
rc = -ENODEV;
printk(KERN_ERR PFX "bnx2fc_disable: interface or lport not found\n");
} else {
+ interface->enabled = false;
fcoe_ctlr_link_down(&interface->ctlr);
fcoe_clean_pending_queue(interface->ctlr.lp);
}
@@ -1820,8 +1916,10 @@ static int bnx2fc_enable(struct net_device *netdev)
if (!interface || !interface->ctlr.lp) {
rc = -ENODEV;
printk(KERN_ERR PFX "bnx2fc_enable: interface or lport not found\n");
- } else if (!bnx2fc_link_ok(interface->ctlr.lp))
+ } else if (!bnx2fc_link_ok(interface->ctlr.lp)) {
fcoe_ctlr_link_up(&interface->ctlr);
+ interface->enabled = true;
+ }
mutex_unlock(&bnx2fc_dev_lock);
rtnl_unlock();
@@ -1921,7 +2019,6 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
if (!lport) {
printk(KERN_ERR PFX "Failed to create interface (%s)\n",
netdev->name);
- bnx2fc_netdev_cleanup(interface);
rc = -EINVAL;
goto if_create_err;
}
@@ -1934,8 +2031,15 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
/* Make this master N_port */
interface->ctlr.lp = lport;
+ if (!bnx2fc_link_ok(lport)) {
+ fcoe_ctlr_link_up(&interface->ctlr);
+ fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
+ set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state);
+ }
+
BNX2FC_HBA_DBG(lport, "create: START DISC\n");
bnx2fc_start_disc(interface);
+ interface->enabled = true;
/*
* Release from kref_init in bnx2fc_interface_setup, on success
* lport should be holding a reference taken in bnx2fc_if_create
@@ -1949,6 +2053,7 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
if_create_err:
destroy_workqueue(interface->timer_work_queue);
ifput_err:
+ bnx2fc_net_cleanup(interface);
bnx2fc_interface_put(interface);
netdev_err:
module_put(THIS_MODULE);
@@ -2015,7 +2120,6 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev)
{
struct bnx2fc_hba *hba;
struct bnx2fc_interface *interface, *tmp;
- struct fc_lport *lport;
BNX2FC_MISC_DBG("Entered bnx2fc_ulp_exit\n");
@@ -2037,18 +2141,10 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev)
list_del_init(&hba->list);
adapter_count--;
- list_for_each_entry_safe(interface, tmp, &if_list, list) {
+ list_for_each_entry_safe(interface, tmp, &if_list, list)
/* destroy not called yet, move to quiesced list */
- if (interface->hba == hba) {
- bnx2fc_netdev_cleanup(interface);
- bnx2fc_stop(interface);
-
- list_del(&interface->list);
- lport = interface->ctlr.lp;
- bnx2fc_interface_put(interface);
- bnx2fc_if_destroy(lport, hba);
- }
- }
+ if (interface->hba == hba)
+ __bnx2fc_destroy(interface);
mutex_unlock(&bnx2fc_dev_lock);
bnx2fc_ulp_stop(hba);
@@ -2117,7 +2213,7 @@ static void bnx2fc_percpu_thread_create(unsigned int cpu)
(void *)p,
"bnx2fc_thread/%d", cpu);
/* bind thread to the cpu */
- if (likely(!IS_ERR(p->iothread))) {
+ if (likely(!IS_ERR(thread))) {
kthread_bind(thread, cpu);
p->iothread = thread;
wake_up_process(thread);
@@ -2129,7 +2225,6 @@ static void bnx2fc_percpu_thread_destroy(unsigned int cpu)
struct bnx2fc_percpu_s *p;
struct task_struct *thread;
struct bnx2fc_work *work, *tmp;
- LIST_HEAD(work_list);
BNX2FC_MISC_DBG("destroying io thread for CPU %d\n", cpu);
@@ -2141,7 +2236,7 @@ static void bnx2fc_percpu_thread_destroy(unsigned int cpu)
/* Free all work in the list */
- list_for_each_entry_safe(work, tmp, &work_list, list) {
+ list_for_each_entry_safe(work, tmp, &p->work_list, list) {
list_del_init(&work->list);
bnx2fc_process_cq_compl(work->tgt, work->wqe);
kfree(work);
@@ -2374,6 +2469,7 @@ static struct fc_function_template bnx2fc_transport_function = {
.vport_create = bnx2fc_vport_create,
.vport_delete = bnx2fc_vport_destroy,
.vport_disable = bnx2fc_vport_disable,
+ .bsg_request = fc_lport_bsg_request,
};
static struct fc_function_template bnx2fc_vport_xport_function = {
@@ -2407,6 +2503,7 @@ static struct fc_function_template bnx2fc_vport_xport_function = {
.get_fc_host_stats = fc_get_host_stats,
.issue_fc_host_lip = bnx2fc_fcoe_reset,
.terminate_rport_io = fc_rport_terminate_io,
+ .bsg_request = fc_lport_bsg_request,
};
/**
@@ -2436,6 +2533,7 @@ static struct libfc_function_template bnx2fc_libfc_fcn_templ = {
.elsct_send = bnx2fc_elsct_send,
.fcp_abort_io = bnx2fc_abort_io,
.fcp_cleanup = bnx2fc_cleanup,
+ .get_lesb = bnx2fc_get_lesb,
.rport_event_callback = bnx2fc_rport_event_handler,
};
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index 72cfb14acd3a..1923a25cb6a2 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -1009,6 +1009,7 @@ int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
u32 cq_cons;
struct fcoe_cqe *cqe;
u32 num_free_sqes = 0;
+ u32 num_cqes = 0;
u16 wqe;
/*
@@ -1058,10 +1059,11 @@ unlock:
wake_up_process(fps->iothread);
else
bnx2fc_process_cq_compl(tgt, wqe);
+ num_free_sqes++;
}
cqe++;
tgt->cq_cons_idx++;
- num_free_sqes++;
+ num_cqes++;
if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
tgt->cq_cons_idx = 0;
@@ -1070,8 +1072,10 @@ unlock:
1 - tgt->cq_curr_toggle_bit;
}
}
- if (num_free_sqes) {
- bnx2fc_arm_cq(tgt);
+ if (num_cqes) {
+ /* Arm CQ only if doorbell is mapped */
+ if (tgt->ctx_base)
+ bnx2fc_arm_cq(tgt);
atomic_add(num_free_sqes, &tgt->free_sqes);
}
spin_unlock_bh(&tgt->cq_lock);
@@ -1739,11 +1743,13 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
/* Init state to NORMAL */
task->txwr_rxrd.const_ctx.init_flags |= task_type <<
FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
- if (dev_type == TYPE_TAPE)
+ if (dev_type == TYPE_TAPE) {
task->txwr_rxrd.const_ctx.init_flags |=
FCOE_TASK_DEV_TYPE_TAPE <<
FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
- else
+ io_req->rec_retry = 0;
+ io_req->rec_retry = 0;
+ } else
task->txwr_rxrd.const_ctx.init_flags |=
FCOE_TASK_DEV_TYPE_DISK <<
FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index 6cc3789075bc..0c64d184d731 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -17,7 +17,7 @@
static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
int bd_index);
static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req);
-static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req);
+static int bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req);
static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req);
static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req);
static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
@@ -1251,7 +1251,6 @@ void bnx2fc_process_seq_cleanup_compl(struct bnx2fc_cmd *seq_clnp_req,
seq_clnp_req->xid);
goto free_cb_arg;
}
- kref_get(&orig_io_req->refcount);
spin_unlock_bh(&tgt->tgt_lock);
rc = bnx2fc_send_srr(orig_io_req, offset, r_ctl);
@@ -1569,6 +1568,8 @@ static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req)
{
+ struct bnx2fc_interface *interface = io_req->port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
struct scsi_cmnd *sc = io_req->sc_cmd;
struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl;
struct scatterlist *sg;
@@ -1580,7 +1581,8 @@ static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req)
u64 addr;
int i;
- sg_count = scsi_dma_map(sc);
+ sg_count = dma_map_sg(&hba->pcidev->dev, scsi_sglist(sc),
+ scsi_sg_count(sc), sc->sc_data_direction);
scsi_for_each_sg(sc, sg, sg_count, i) {
sg_len = sg_dma_len(sg);
addr = sg_dma_address(sg);
@@ -1605,20 +1607,24 @@ static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req)
return bd_count;
}
-static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req)
+static int bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req)
{
struct scsi_cmnd *sc = io_req->sc_cmd;
struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl;
int bd_count;
- if (scsi_sg_count(sc))
+ if (scsi_sg_count(sc)) {
bd_count = bnx2fc_map_sg(io_req);
- else {
+ if (bd_count == 0)
+ return -ENOMEM;
+ } else {
bd_count = 0;
bd[0].buf_addr_lo = bd[0].buf_addr_hi = 0;
bd[0].buf_len = bd[0].flags = 0;
}
io_req->bd_tbl->bd_valid = bd_count;
+
+ return 0;
}
static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req)
@@ -1790,12 +1796,6 @@ int bnx2fc_queuecommand(struct Scsi_Host *host,
tgt = (struct bnx2fc_rport *)&rp[1];
if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
- if (test_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags)) {
- sc_cmd->result = DID_NO_CONNECT << 16;
- sc_cmd->scsi_done(sc_cmd);
- return 0;
-
- }
/*
* Session is not offloaded yet. Let SCSI-ml retry
* the command.
@@ -1946,7 +1946,13 @@ int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
xid = io_req->xid;
/* Build buffer descriptor list for firmware from sg list */
- bnx2fc_build_bd_list_from_sg(io_req);
+ if (bnx2fc_build_bd_list_from_sg(io_req)) {
+ printk(KERN_ERR PFX "BD list creation failed\n");
+ spin_lock_bh(&tgt->tgt_lock);
+ kref_put(&io_req->refcount, bnx2fc_cmd_release);
+ spin_unlock_bh(&tgt->tgt_lock);
+ return -EAGAIN;
+ }
task_idx = xid / BNX2FC_TASKS_PER_PAGE;
index = xid % BNX2FC_TASKS_PER_PAGE;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index d5311b577cca..c1800b531270 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -76,7 +76,7 @@ static void bnx2fc_offload_session(struct fcoe_port *port,
if (rval) {
printk(KERN_ERR PFX "Failed to allocate conn id for "
"port_id (%6x)\n", rport->port_id);
- goto ofld_err;
+ goto tgt_init_err;
}
/* Allocate session resources */
@@ -134,18 +134,17 @@ retry_ofld:
/* upload will take care of cleaning up sess resc */
lport->tt.rport_logoff(rdata);
}
- /* Arm CQ */
- bnx2fc_arm_cq(tgt);
return;
ofld_err:
/* couldn't offload the session. log off from this rport */
BNX2FC_TGT_DBG(tgt, "bnx2fc_offload_session - offload error\n");
- lport->tt.rport_logoff(rdata);
/* Free session resources */
bnx2fc_free_session_resc(hba, tgt);
+tgt_init_err:
if (tgt->fcoe_conn_id != -1)
bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
+ lport->tt.rport_logoff(rdata);
}
void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
@@ -624,7 +623,6 @@ static void bnx2fc_free_conn_id(struct bnx2fc_hba *hba, u32 conn_id)
/* called with hba mutex held */
spin_lock_bh(&hba->hba_lock);
hba->tgt_ofld_list[conn_id] = NULL;
- hba->next_conn_id = conn_id;
spin_unlock_bh(&hba->hba_lock);
}
@@ -791,8 +789,6 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
return 0;
mem_alloc_failure:
- bnx2fc_free_session_resc(hba, tgt);
- bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
return -ENOMEM;
}
@@ -807,14 +803,14 @@ mem_alloc_failure:
static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
struct bnx2fc_rport *tgt)
{
- BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
+ void __iomem *ctx_base_ptr;
- if (tgt->ctx_base) {
- iounmap(tgt->ctx_base);
- tgt->ctx_base = NULL;
- }
+ BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
spin_lock_bh(&tgt->cq_lock);
+ ctx_base_ptr = tgt->ctx_base;
+ tgt->ctx_base = NULL;
+
/* Free LCQ */
if (tgt->lcq) {
dma_free_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
@@ -868,4 +864,7 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
tgt->sq = NULL;
}
spin_unlock_bh(&tgt->cq_lock);
+
+ if (ctx_base_ptr)
+ iounmap(ctx_base_ptr);
}
diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig
index 45a6154ce972..01cff1894b6d 100644
--- a/drivers/scsi/bnx2i/Kconfig
+++ b/drivers/scsi/bnx2i/Kconfig
@@ -4,7 +4,8 @@ config SCSI_BNX2_ISCSI
depends on PCI
select SCSI_ISCSI_ATTRS
select NETDEVICES
- select NETDEV_1000
+ select ETHERNET
+ select NET_VENDOR_BROADCOM
select CNIC
---help---
This driver supports iSCSI offload for the Broadcom NetXtreme II
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index dc5700765db4..0bd70e80efe4 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -40,7 +40,7 @@
#include <scsi/libiscsi.h>
#include <scsi/scsi_transport_iscsi.h>
-#include "../../net/cnic_if.h"
+#include "../../net/ethernet/broadcom/cnic_if.h"
#include "57xx_iscsi_hsi.h"
#include "57xx_iscsi_constants.h"
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index cffd4d75df56..d1e697190970 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -2177,6 +2177,59 @@ static int bnx2i_nl_set_path(struct Scsi_Host *shost, struct iscsi_path *params)
return 0;
}
+static mode_t bnx2i_attr_is_visible(int param_type, int param)
+{
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_NETDEV_NAME:
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_HDRDGST_EN:
+ case ISCSI_PARAM_DATADGST_EN:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_EXP_STATSN:
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_PING_TMO:
+ case ISCSI_PARAM_RECV_TMO:
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_IMM_DATA_EN:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ case ISCSI_PARAM_ERL:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_USERNAME:
+ case ISCSI_PARAM_PASSWORD:
+ case ISCSI_PARAM_USERNAME_IN:
+ case ISCSI_PARAM_PASSWORD_IN:
+ case ISCSI_PARAM_FAST_ABORT:
+ case ISCSI_PARAM_ABORT_TMO:
+ case ISCSI_PARAM_LU_RESET_TMO:
+ case ISCSI_PARAM_TGT_RESET_TMO:
+ case ISCSI_PARAM_IFACE_NAME:
+ case ISCSI_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
/*
* 'Scsi_Host_Template' structure and 'iscsi_tranport' structure template
@@ -2207,37 +2260,12 @@ struct iscsi_transport bnx2i_iscsi_transport = {
CAP_MULTI_R2T | CAP_DATADGST |
CAP_DATA_PATH_OFFLOAD |
CAP_TEXT_NEGO,
- .param_mask = ISCSI_MAX_RECV_DLENGTH |
- ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN |
- ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN |
- ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN |
- ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST |
- ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN |
- ISCSI_ERL |
- ISCSI_CONN_PORT |
- ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN |
- ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_NETDEV_NAME,
.create_session = bnx2i_session_create,
.destroy_session = bnx2i_session_destroy,
.create_conn = bnx2i_conn_create,
.bind_conn = bnx2i_conn_bind,
.destroy_conn = bnx2i_conn_destroy,
+ .attr_is_visible = bnx2i_attr_is_visible,
.set_param = iscsi_set_param,
.get_conn_param = iscsi_conn_get_param,
.get_session_param = iscsi_session_get_param,
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kbuild b/drivers/scsi/cxgbi/cxgb3i/Kbuild
index 09dbf9efc8ea..6f095e28a974 100644
--- a/drivers/scsi/cxgbi/cxgb3i/Kbuild
+++ b/drivers/scsi/cxgbi/cxgb3i/Kbuild
@@ -1,3 +1,3 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb3
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kconfig b/drivers/scsi/cxgbi/cxgb3i/Kconfig
index 11dff23f7838..6bbc36fbd6ec 100644
--- a/drivers/scsi/cxgbi/cxgb3i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb3i/Kconfig
@@ -2,7 +2,8 @@ config SCSI_CXGB3_ISCSI
tristate "Chelsio T3 iSCSI support"
depends on PCI && INET
select NETDEVICES
- select NETDEV_10000
+ select ETHERNET
+ select NET_VENDOR_CHELSIO
select CHELSIO_T3
select SCSI_ISCSI_ATTRS
---help---
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index f58644850333..000294a9df80 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -14,7 +14,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <scsi/scsi_host.h>
@@ -106,25 +105,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
.caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
- .param_mask = ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
- ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_INITIATOR_NAME |
- ISCSI_HOST_NETDEV_NAME,
+ .attr_is_visible = cxgbi_attr_is_visible,
.get_host_param = cxgbi_get_host_param,
.set_host_param = cxgbi_set_host_param,
/* session management */
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kbuild b/drivers/scsi/cxgbi/cxgb4i/Kbuild
index b9f4af7454b7..8290cdaa4652 100644
--- a/drivers/scsi/cxgbi/cxgb4i/Kbuild
+++ b/drivers/scsi/cxgbi/cxgb4i/Kbuild
@@ -1,3 +1,3 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb4
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4
obj-$(CONFIG_SCSI_CXGB4_ISCSI) += cxgb4i.o
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig
index d5302c27f377..16b2c7d26617 100644
--- a/drivers/scsi/cxgbi/cxgb4i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig
@@ -2,7 +2,8 @@ config SCSI_CXGB4_ISCSI
tristate "Chelsio T4 iSCSI support"
depends on PCI && INET
select NETDEVICES
- select NETDEV_10000
+ select ETHERNET
+ select NET_VENDOR_CHELSIO
select CHELSIO_T4
select SCSI_ISCSI_ATTRS
---help---
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index ae13c4993aa3..ac7a9b1e3e23 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -13,7 +13,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <scsi/scsi_host.h>
@@ -107,25 +106,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
.caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
CAP_DATADGST | CAP_DIGEST_OFFLOAD |
CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
- .param_mask = ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
- ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_INITIATOR_NAME |
- ISCSI_HOST_NETDEV_NAME,
+ .attr_is_visible = cxgbi_attr_is_visible,
.get_host_param = cxgbi_get_host_param,
.set_host_param = cxgbi_set_host_param,
/* session management */
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index 77ac217ad5ce..c363a4b260fd 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -1787,7 +1787,7 @@ static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
}
static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
- unsigned int dlen, skb_frag_t *frags,
+ unsigned int dlen, struct page_frag *frags,
int frag_max)
{
unsigned int datalen = dlen;
@@ -1814,7 +1814,7 @@ static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
copy = min(datalen, sglen);
if (i && page == frags[i - 1].page &&
sgoffset + sg->offset ==
- frags[i - 1].page_offset + frags[i - 1].size) {
+ frags[i - 1].offset + frags[i - 1].size) {
frags[i - 1].size += copy;
} else {
if (i >= frag_max) {
@@ -1824,7 +1824,7 @@ static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
}
frags[i].page = page;
- frags[i].page_offset = sg->offset + sgoffset;
+ frags[i].offset = sg->offset + sgoffset;
frags[i].size = copy;
i++;
}
@@ -1944,14 +1944,14 @@ int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
if (tdata->nr_frags > MAX_SKB_FRAGS ||
(padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
char *dst = skb->data + task->hdr_len;
- skb_frag_t *frag = tdata->frags;
+ struct page_frag *frag = tdata->frags;
/* data fits in the skb's headroom */
for (i = 0; i < tdata->nr_frags; i++, frag++) {
char *src = kmap_atomic(frag->page,
KM_SOFTIRQ0);
- memcpy(dst, src+frag->page_offset, frag->size);
+ memcpy(dst, src+frag->offset, frag->size);
dst += frag->size;
kunmap_atomic(src, KM_SOFTIRQ0);
}
@@ -1962,11 +1962,13 @@ int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
skb_put(skb, count + padlen);
} else {
/* data fit into frag_list */
- for (i = 0; i < tdata->nr_frags; i++)
- get_page(tdata->frags[i].page);
-
- memcpy(skb_shinfo(skb)->frags, tdata->frags,
- sizeof(skb_frag_t) * tdata->nr_frags);
+ for (i = 0; i < tdata->nr_frags; i++) {
+ __skb_fill_page_desc(skb, i,
+ tdata->frags[i].page,
+ tdata->frags[i].offset,
+ tdata->frags[i].size);
+ skb_frag_ref(skb, i);
+ }
skb_shinfo(skb)->nr_frags = tdata->nr_frags;
skb->len += count;
skb->data_len += count;
@@ -2566,6 +2568,62 @@ void cxgbi_iscsi_cleanup(struct iscsi_transport *itp,
}
EXPORT_SYMBOL_GPL(cxgbi_iscsi_cleanup);
+mode_t cxgbi_attr_is_visible(int param_type, int param)
+{
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_NETDEV_NAME:
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_HDRDGST_EN:
+ case ISCSI_PARAM_DATADGST_EN:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_EXP_STATSN:
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_PING_TMO:
+ case ISCSI_PARAM_RECV_TMO:
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_IMM_DATA_EN:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ case ISCSI_PARAM_ERL:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_USERNAME:
+ case ISCSI_PARAM_PASSWORD:
+ case ISCSI_PARAM_USERNAME_IN:
+ case ISCSI_PARAM_PASSWORD_IN:
+ case ISCSI_PARAM_FAST_ABORT:
+ case ISCSI_PARAM_ABORT_TMO:
+ case ISCSI_PARAM_LU_RESET_TMO:
+ case ISCSI_PARAM_TGT_RESET_TMO:
+ case ISCSI_PARAM_IFACE_NAME:
+ case ISCSI_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_attr_is_visible);
+
static int __init libcxgbi_init_module(void)
{
sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index 9267844519c9..20c88279c7a6 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -574,7 +574,7 @@ struct cxgbi_endpoint {
#define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
struct cxgbi_task_data {
unsigned short nr_frags;
- skb_frag_t frags[MAX_PDU_FRAGS];
+ struct page_frag frags[MAX_PDU_FRAGS];
struct sk_buff *skb;
unsigned int offset;
unsigned int count;
@@ -709,6 +709,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *);
void cxgbi_cleanup_task(struct iscsi_task *task);
+mode_t cxgbi_attr_is_visible(int param_type, int param);
void cxgbi_get_conn_stats(struct iscsi_cls_conn *, struct iscsi_stats *);
int cxgbi_set_conn_param(struct iscsi_cls_conn *,
enum iscsi_param, char *, int);
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index 0119b8147797..7c05fd9dccfd 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -60,6 +60,46 @@ static struct scsi_device_handler *get_device_handler_by_idx(int idx)
}
/*
+ * device_handler_match_function - Match a device handler to a device
+ * @sdev - SCSI device to be tested
+ *
+ * Tests @sdev against the match function of all registered device_handler.
+ * Returns the found device handler or NULL if not found.
+ */
+static struct scsi_device_handler *
+device_handler_match_function(struct scsi_device *sdev)
+{
+ struct scsi_device_handler *tmp_dh, *found_dh = NULL;
+
+ spin_lock(&list_lock);
+ list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
+ if (tmp_dh->match && tmp_dh->match(sdev)) {
+ found_dh = tmp_dh;
+ break;
+ }
+ }
+ spin_unlock(&list_lock);
+ return found_dh;
+}
+
+/*
+ * device_handler_match_devlist - Match a device handler to a device
+ * @sdev - SCSI device to be tested
+ *
+ * Tests @sdev against all device_handler registered in the devlist.
+ * Returns the found device handler or NULL if not found.
+ */
+static struct scsi_device_handler *
+device_handler_match_devlist(struct scsi_device *sdev)
+{
+ int idx;
+
+ idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
+ SCSI_DEVINFO_DH);
+ return get_device_handler_by_idx(idx);
+}
+
+/*
* device_handler_match - Attach a device handler to a device
* @scsi_dh - The device handler to match against or NULL
* @sdev - SCSI device to be tested against @scsi_dh
@@ -72,12 +112,11 @@ static struct scsi_device_handler *
device_handler_match(struct scsi_device_handler *scsi_dh,
struct scsi_device *sdev)
{
- struct scsi_device_handler *found_dh = NULL;
- int idx;
+ struct scsi_device_handler *found_dh;
- idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
- SCSI_DEVINFO_DH);
- found_dh = get_device_handler_by_idx(idx);
+ found_dh = device_handler_match_function(sdev);
+ if (!found_dh)
+ found_dh = device_handler_match_devlist(sdev);
if (scsi_dh && found_dh != scsi_dh)
found_dh = NULL;
@@ -151,6 +190,10 @@ store_dh_state(struct device *dev, struct device_attribute *attr,
struct scsi_device_handler *scsi_dh;
int err = -EINVAL;
+ if (sdev->sdev_state == SDEV_CANCEL ||
+ sdev->sdev_state == SDEV_DEL)
+ return -ENODEV;
+
if (!sdev->scsi_dh_data) {
/*
* Attach to a device handler
@@ -327,7 +370,7 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
list_add(&scsi_dh->list, &scsi_dh_list);
spin_unlock(&list_lock);
- for (i = 0; scsi_dh->devlist[i].vendor; i++) {
+ for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) {
scsi_dev_info_list_add_keyed(0,
scsi_dh->devlist[i].vendor,
scsi_dh->devlist[i].model,
@@ -360,7 +403,7 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
scsi_dh_notifier_remove);
- for (i = 0; scsi_dh->devlist[i].vendor; i++) {
+ for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) {
scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor,
scsi_dh->devlist[i].model,
SCSI_DEVINFO_DH);
@@ -468,7 +511,7 @@ int scsi_dh_handler_exist(const char *name)
EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
/*
- * scsi_dh_handler_attach - Attach device handler
+ * scsi_dh_attach - Attach device handler
* @sdev - sdev the handler should be attached to
* @name - name of the handler to attach
*/
@@ -498,7 +541,7 @@ int scsi_dh_attach(struct request_queue *q, const char *name)
EXPORT_SYMBOL_GPL(scsi_dh_attach);
/*
- * scsi_dh_handler_detach - Detach device handler
+ * scsi_dh_detach - Detach device handler
* @sdev - sdev the handler should be detached from
*
* This function will detach the device handler only
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 6fec9fe5dc39..627f4b5e5176 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -128,43 +128,6 @@ static struct request *get_alua_req(struct scsi_device *sdev,
}
/*
- * submit_std_inquiry - Issue a standard INQUIRY command
- * @sdev: sdev the command should be send to
- */
-static int submit_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
-{
- struct request *rq;
- int err = SCSI_DH_RES_TEMP_UNAVAIL;
-
- rq = get_alua_req(sdev, h->inq, ALUA_INQUIRY_SIZE, READ);
- if (!rq)
- goto done;
-
- /* Prepare the command. */
- rq->cmd[0] = INQUIRY;
- rq->cmd[1] = 0;
- rq->cmd[2] = 0;
- rq->cmd[4] = ALUA_INQUIRY_SIZE;
- rq->cmd_len = COMMAND_SIZE(INQUIRY);
-
- rq->sense = h->sense;
- memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
- rq->sense_len = h->senselen = 0;
-
- err = blk_execute_rq(rq->q, NULL, rq, 1);
- if (err == -EIO) {
- sdev_printk(KERN_INFO, sdev,
- "%s: std inquiry failed with %x\n",
- ALUA_DH_NAME, rq->errors);
- h->senselen = rq->sense_len;
- err = SCSI_DH_IO;
- }
- blk_put_request(rq);
-done:
- return err;
-}
-
-/*
* submit_vpd_inquiry - Issue an INQUIRY VPD page 0x83 command
* @sdev: sdev the command should be sent to
*/
@@ -338,23 +301,17 @@ static unsigned submit_stpg(struct alua_dh_data *h)
}
/*
- * alua_std_inquiry - Evaluate standard INQUIRY command
+ * alua_check_tpgs - Evaluate TPGS setting
* @sdev: device to be checked
*
- * Just extract the TPGS setting to find out if ALUA
+ * Examine the TPGS setting of the sdev to find out if ALUA
* is supported.
*/
-static int alua_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
+static int alua_check_tpgs(struct scsi_device *sdev, struct alua_dh_data *h)
{
- int err;
-
- err = submit_std_inquiry(sdev, h);
-
- if (err != SCSI_DH_OK)
- return err;
+ int err = SCSI_DH_OK;
- /* Check TPGS setting */
- h->tpgs = (h->inq[5] >> 4) & 0x3;
+ h->tpgs = scsi_device_tpgs(sdev);
switch (h->tpgs) {
case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT:
sdev_printk(KERN_INFO, sdev,
@@ -508,27 +465,28 @@ static int alua_check_sense(struct scsi_device *sdev,
* Power On, Reset, or Bus Device Reset, just retry.
*/
return ADD_TO_MLQUEUE;
- if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06) {
+ if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06)
/*
* ALUA state changed
*/
return ADD_TO_MLQUEUE;
- }
- if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07) {
+ if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07)
/*
* Implicit ALUA state transition failed
*/
return ADD_TO_MLQUEUE;
- }
- if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x0e) {
+ if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x03)
+ /*
+ * Inquiry data has changed
+ */
+ return ADD_TO_MLQUEUE;
+ if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x0e)
/*
* REPORTED_LUNS_DATA_HAS_CHANGED is reported
* when switching controllers on targets like
* Intel Multi-Flex. We can just retry.
*/
return ADD_TO_MLQUEUE;
- }
-
break;
}
@@ -547,9 +505,9 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
{
struct scsi_sense_hdr sense_hdr;
int len, k, off, valid_states = 0;
- char *ucp;
+ unsigned char *ucp;
unsigned err;
- unsigned long expiry, interval = 10;
+ unsigned long expiry, interval = 1;
expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT);
retry:
@@ -610,7 +568,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
case TPGS_STATE_TRANSITIONING:
if (time_before(jiffies, expiry)) {
/* State transition, retry */
- interval *= 10;
+ interval *= 2;
msleep(interval);
goto retry;
}
@@ -642,7 +600,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
{
int err;
- err = alua_std_inquiry(sdev, h);
+ err = alua_check_tpgs(sdev, h);
if (err != SCSI_DH_OK)
goto out;
@@ -674,11 +632,9 @@ static int alua_activate(struct scsi_device *sdev,
struct alua_dh_data *h = get_alua_data(sdev);
int err = SCSI_DH_OK;
- if (h->group_id != -1) {
- err = alua_rtpg(sdev, h);
- if (err != SCSI_DH_OK)
- goto out;
- }
+ err = alua_rtpg(sdev, h);
+ if (err != SCSI_DH_OK)
+ goto out;
if (h->tpgs & TPGS_MODE_EXPLICIT &&
h->state != TPGS_STATE_OPTIMIZED &&
@@ -720,23 +676,10 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
}
-static const struct scsi_dh_devlist alua_dev_list[] = {
- {"HP", "MSA VOLUME" },
- {"HP", "HSV101" },
- {"HP", "HSV111" },
- {"HP", "HSV200" },
- {"HP", "HSV210" },
- {"HP", "HSV300" },
- {"IBM", "2107900" },
- {"IBM", "2145" },
- {"Pillar", "Axiom" },
- {"Intel", "Multi-Flex"},
- {"NETAPP", "LUN"},
- {"NETAPP", "LUN C-Mode"},
- {"AIX", "NVDISK"},
- {"Promise", "VTrak"},
- {NULL, NULL}
-};
+static bool alua_match(struct scsi_device *sdev)
+{
+ return (scsi_device_tpgs(sdev) != 0);
+}
static int alua_bus_attach(struct scsi_device *sdev);
static void alua_bus_detach(struct scsi_device *sdev);
@@ -744,12 +687,12 @@ static void alua_bus_detach(struct scsi_device *sdev);
static struct scsi_device_handler alua_dh = {
.name = ALUA_DH_NAME,
.module = THIS_MODULE,
- .devlist = alua_dev_list,
.attach = alua_bus_attach,
.detach = alua_bus_detach,
.prep_fn = alua_prep_fn,
.check_sense = alua_check_sense,
.activate = alua_activate,
+ .match = alua_match,
};
/*
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 27c9d65d54a9..82d612f0c49d 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -1,5 +1,5 @@
/*
- * Engenio/LSI RDAC SCSI Device Handler
+ * LSI/Engenio/NetApp E-Series RDAC SCSI Device Handler
*
* Copyright (C) 2005 Mike Christie. All rights reserved.
* Copyright (C) Chandra Seetharaman, IBM Corp. 2007
@@ -795,6 +795,7 @@ static const struct scsi_dh_devlist rdac_dev_list[] = {
{"IBM", "3526"},
{"SGI", "TP9400"},
{"SGI", "TP9500"},
+ {"SGI", "TP9700"},
{"SGI", "IS"},
{"STK", "OPENstorage D280"},
{"SUN", "CSM200_R"},
@@ -814,6 +815,7 @@ static const struct scsi_dh_devlist rdac_dev_list[] = {
{"SUN", "CSM100_R_FC"},
{"SUN", "STK6580_6780"},
{"SUN", "SUN_6180"},
+ {"SUN", "ArrayStorage"},
{NULL, NULL},
};
@@ -945,7 +947,7 @@ static void __exit rdac_exit(void)
module_init(rdac_init);
module_exit(rdac_exit);
-MODULE_DESCRIPTION("Multipath LSI/Engenio RDAC driver");
+MODULE_DESCRIPTION("Multipath LSI/Engenio/NetApp E-Series RDAC driver");
MODULE_AUTHOR("Mike Christie, Chandra Seetharaman");
MODULE_VERSION("01.00.0000.0000");
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 5d0e9a24ae94..61384ee4049b 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -18,7 +18,6 @@
*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -52,7 +51,7 @@ MODULE_DESCRIPTION("FCoE");
MODULE_LICENSE("GPL v2");
/* Performance tuning parameters for fcoe */
-static unsigned int fcoe_ddp_min;
+static unsigned int fcoe_ddp_min = 4096;
module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for " \
"Direct Data Placement (DDP).");
@@ -138,7 +137,6 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled);
static int fcoe_vport_disable(struct fc_vport *, bool disable);
static void fcoe_set_vport_symbolic_name(struct fc_vport *);
static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *);
-static int fcoe_validate_vport_create(struct fc_vport *);
static struct libfc_function_template fcoe_libfc_fcn_templ = {
.frame_send = fcoe_xmit,
@@ -281,6 +279,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
* use the first one for SPMA */
real_dev = (netdev->priv_flags & IFF_802_1Q_VLAN) ?
vlan_dev_real_dev(netdev) : netdev;
+ fcoe->realdev = real_dev;
rcu_read_lock();
for_each_dev_addr(real_dev, ha) {
if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
@@ -581,23 +580,6 @@ static int fcoe_lport_config(struct fc_lport *lport)
}
/**
- * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
- * @netdev: the associated net device
- * @wwn: the output WWN
- * @type: the type of WWN (WWPN or WWNN)
- *
- * Returns: 0 for success
- */
-static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
-{
- const struct net_device_ops *ops = netdev->netdev_ops;
-
- if (ops->ndo_fcoe_get_wwn)
- return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
- return -EINVAL;
-}
-
-/**
* fcoe_netdev_features_change - Updates the lport's offload flags based
* on the LLD netdev's FCoE feature flags
*/
@@ -1135,8 +1117,9 @@ static void fcoe_percpu_thread_create(unsigned int cpu)
p = &per_cpu(fcoe_percpu, cpu);
- thread = kthread_create(fcoe_percpu_receive_thread,
- (void *)p, "fcoethread/%d", cpu);
+ thread = kthread_create_on_node(fcoe_percpu_receive_thread,
+ (void *)p, cpu_to_node(cpu),
+ "fcoethread/%d", cpu);
if (likely(!IS_ERR(thread))) {
kthread_bind(thread, cpu);
@@ -1518,7 +1501,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
return -ENOMEM;
}
frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
- cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
+ cp = kmap_atomic(skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ)
+ frag->page_offset;
} else {
cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
@@ -1539,7 +1522,13 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
skb_reset_network_header(skb);
skb->mac_len = elen;
skb->protocol = htons(ETH_P_FCOE);
- skb->dev = fcoe->netdev;
+ if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN &&
+ fcoe->realdev->features & NETIF_F_HW_VLAN_TX) {
+ skb->vlan_tci = VLAN_TAG_PRESENT |
+ vlan_dev_vlan_id(fcoe->netdev);
+ skb->dev = fcoe->realdev;
+ } else
+ skb->dev = fcoe->netdev;
/* fill up mac and fcoe headers */
eh = eth_hdr(skb);
@@ -2046,7 +2035,7 @@ int fcoe_link_speed_update(struct fc_lport *lport)
struct net_device *netdev = fcoe_netdev(lport);
struct ethtool_cmd ecmd;
- if (!dev_ethtool_get_settings(netdev, &ecmd)) {
+ if (!__ethtool_get_settings(netdev, &ecmd)) {
lport->link_supported_speeds &=
~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
if (ecmd.supported & (SUPPORTED_1000baseT_Half |
@@ -2447,7 +2436,7 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled)
rc = fcoe_validate_vport_create(vport);
if (rc) {
- wwn_to_str(vport->port_name, buf, sizeof(buf));
+ fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf));
printk(KERN_ERR "fcoe: Failed to create vport, "
"WWPN (0x%s) already exists\n",
buf);
@@ -2455,7 +2444,9 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled)
}
mutex_lock(&fcoe_config_mutex);
+ rtnl_lock();
vn_port = fcoe_if_create(fcoe, &vport->dev, 1);
+ rtnl_unlock();
mutex_unlock(&fcoe_config_mutex);
if (IS_ERR(vn_port)) {
@@ -2554,28 +2545,9 @@ static void fcoe_set_vport_symbolic_name(struct fc_vport *vport)
static void fcoe_get_lesb(struct fc_lport *lport,
struct fc_els_lesb *fc_lesb)
{
- unsigned int cpu;
- u32 lfc, vlfc, mdac;
- struct fcoe_dev_stats *devst;
- struct fcoe_fc_els_lesb *lesb;
- struct rtnl_link_stats64 temp;
struct net_device *netdev = fcoe_netdev(lport);
- lfc = 0;
- vlfc = 0;
- mdac = 0;
- lesb = (struct fcoe_fc_els_lesb *)fc_lesb;
- memset(lesb, 0, sizeof(*lesb));
- for_each_possible_cpu(cpu) {
- devst = per_cpu_ptr(lport->dev_stats, cpu);
- lfc += devst->LinkFailureCount;
- vlfc += devst->VLinkFailureCount;
- mdac += devst->MissDiscAdvCount;
- }
- lesb->lesb_link_fail = htonl(lfc);
- lesb->lesb_vlink_fail = htonl(vlfc);
- lesb->lesb_miss_fka = htonl(mdac);
- lesb->lesb_fcs_error = htonl(dev_get_stats(netdev, &temp)->rx_crc_errors);
+ __fcoe_get_lesb(lport, fc_lesb, netdev);
}
/**
@@ -2599,49 +2571,3 @@ static void fcoe_set_port_id(struct fc_lport *lport,
if (fp && fc_frame_payload_op(fp) == ELS_FLOGI)
fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp);
}
-
-/**
- * fcoe_validate_vport_create() - Validate a vport before creating it
- * @vport: NPIV port to be created
- *
- * This routine is meant to add validation for a vport before creating it
- * via fcoe_vport_create().
- * Current validations are:
- * - WWPN supplied is unique for given lport
- *
- *
-*/
-static int fcoe_validate_vport_create(struct fc_vport *vport)
-{
- struct Scsi_Host *shost = vport_to_shost(vport);
- struct fc_lport *n_port = shost_priv(shost);
- struct fc_lport *vn_port;
- int rc = 0;
- char buf[32];
-
- mutex_lock(&n_port->lp_mutex);
-
- wwn_to_str(vport->port_name, buf, sizeof(buf));
- /* Check if the wwpn is not same as that of the lport */
- if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) {
- FCOE_DBG("vport WWPN 0x%s is same as that of the "
- "base port WWPN\n", buf);
- rc = -EINVAL;
- goto out;
- }
-
- /* Check if there is any existing vport with same wwpn */
- list_for_each_entry(vn_port, &n_port->vports, list) {
- if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) {
- FCOE_DBG("vport with given WWPN 0x%s already "
- "exists\n", buf);
- rc = -EINVAL;
- break;
- }
- }
-
-out:
- mutex_unlock(&n_port->lp_mutex);
-
- return rc;
-}
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index c4a93993c0cf..6c6884bcf840 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -80,6 +80,7 @@ do { \
struct fcoe_interface {
struct list_head list;
struct net_device *netdev;
+ struct net_device *realdev;
struct packet_type fcoe_packet_type;
struct packet_type fip_packet_type;
struct fcoe_ctlr ctlr;
@@ -99,14 +100,4 @@ static inline struct net_device *fcoe_netdev(const struct fc_lport *lport)
((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
}
-static inline void wwn_to_str(u64 wwn, char *buf, int len)
-{
- u8 wwpn[8];
-
- u64_to_wwn(wwn, wwpn);
- snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
- wwpn[0], wwpn[1], wwpn[2], wwpn[3],
- wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
-}
-
#endif /* _FCOE_H_ */
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c
index 41068e8748e7..bd97b2273f20 100644
--- a/drivers/scsi/fcoe/fcoe_transport.c
+++ b/drivers/scsi/fcoe/fcoe_transport.c
@@ -83,6 +83,107 @@ static struct notifier_block libfcoe_notifier = {
.notifier_call = libfcoe_device_notification,
};
+void __fcoe_get_lesb(struct fc_lport *lport,
+ struct fc_els_lesb *fc_lesb,
+ struct net_device *netdev)
+{
+ unsigned int cpu;
+ u32 lfc, vlfc, mdac;
+ struct fcoe_dev_stats *devst;
+ struct fcoe_fc_els_lesb *lesb;
+ struct rtnl_link_stats64 temp;
+
+ lfc = 0;
+ vlfc = 0;
+ mdac = 0;
+ lesb = (struct fcoe_fc_els_lesb *)fc_lesb;
+ memset(lesb, 0, sizeof(*lesb));
+ for_each_possible_cpu(cpu) {
+ devst = per_cpu_ptr(lport->dev_stats, cpu);
+ lfc += devst->LinkFailureCount;
+ vlfc += devst->VLinkFailureCount;
+ mdac += devst->MissDiscAdvCount;
+ }
+ lesb->lesb_link_fail = htonl(lfc);
+ lesb->lesb_vlink_fail = htonl(vlfc);
+ lesb->lesb_miss_fka = htonl(mdac);
+ lesb->lesb_fcs_error =
+ htonl(dev_get_stats(netdev, &temp)->rx_crc_errors);
+}
+EXPORT_SYMBOL_GPL(__fcoe_get_lesb);
+
+void fcoe_wwn_to_str(u64 wwn, char *buf, int len)
+{
+ u8 wwpn[8];
+
+ u64_to_wwn(wwn, wwpn);
+ snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
+ wwpn[0], wwpn[1], wwpn[2], wwpn[3],
+ wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
+}
+EXPORT_SYMBOL_GPL(fcoe_wwn_to_str);
+
+/**
+ * fcoe_validate_vport_create() - Validate a vport before creating it
+ * @vport: NPIV port to be created
+ *
+ * This routine is meant to add validation for a vport before creating it
+ * via fcoe_vport_create().
+ * Current validations are:
+ * - WWPN supplied is unique for given lport
+ */
+int fcoe_validate_vport_create(struct fc_vport *vport)
+{
+ struct Scsi_Host *shost = vport_to_shost(vport);
+ struct fc_lport *n_port = shost_priv(shost);
+ struct fc_lport *vn_port;
+ int rc = 0;
+ char buf[32];
+
+ mutex_lock(&n_port->lp_mutex);
+
+ fcoe_wwn_to_str(vport->port_name, buf, sizeof(buf));
+ /* Check if the wwpn is not same as that of the lport */
+ if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) {
+ LIBFCOE_TRANSPORT_DBG("vport WWPN 0x%s is same as that of the "
+ "base port WWPN\n", buf);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Check if there is any existing vport with same wwpn */
+ list_for_each_entry(vn_port, &n_port->vports, list) {
+ if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) {
+ LIBFCOE_TRANSPORT_DBG("vport with given WWPN 0x%s "
+ "already exists\n", buf);
+ rc = -EINVAL;
+ break;
+ }
+ }
+out:
+ mutex_unlock(&n_port->lp_mutex);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(fcoe_validate_vport_create);
+
+/**
+ * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
+ * @netdev: the associated net device
+ * @wwn: the output WWN
+ * @type: the type of WWN (WWPN or WWNN)
+ *
+ * Returns: 0 for success
+ */
+int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
+{
+ const struct net_device_ops *ops = netdev->netdev_ops;
+
+ if (ops->ndo_fcoe_get_wwn)
+ return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(fcoe_get_wwn);
+
/**
* fcoe_fc_crc() - Calculates the CRC for a given frame
* @fp: The frame to be checksumed
@@ -105,11 +206,12 @@ u32 fcoe_fc_crc(struct fc_frame *fp)
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
frag = &skb_shinfo(skb)->frags[i];
off = frag->page_offset;
- len = frag->size;
+ len = skb_frag_size(frag);
while (len > 0) {
clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
- data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
- KM_SKB_DATA_SOFTIRQ);
+ data = kmap_atomic(
+ skb_frag_page(frag) + (off >> PAGE_SHIFT),
+ KM_SKB_DATA_SOFTIRQ);
crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
off += clen;
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index b200b736b000..9825ecf34957 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3438,10 +3438,8 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
} else {
use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
if (use_doorbell) {
- dev_warn(&pdev->dev, "Controller claims that "
- "'Bit 2 doorbell reset' is "
- "supported, but not 'bit 5 doorbell reset'. "
- "Firmware update is recommended.\n");
+ dev_warn(&pdev->dev, "Soft reset not supported. "
+ "Firmware update is required.\n");
rc = -ENOTSUPP; /* try soft reset */
goto unmap_cfgtable;
}
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 8d636301e32c..73e24b48dced 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2901,7 +2901,7 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- if (ioa_cfg->sdt_state != GET_DUMP) {
+ if (ioa_cfg->sdt_state != READ_DUMP) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return;
}
@@ -3097,7 +3097,7 @@ static void ipr_worker_thread(struct work_struct *work)
ENTER;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- if (ioa_cfg->sdt_state == GET_DUMP) {
+ if (ioa_cfg->sdt_state == READ_DUMP) {
dump = ioa_cfg->dump;
if (!dump) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -3109,7 +3109,7 @@ static void ipr_worker_thread(struct work_struct *work)
kref_put(&dump->kref, ipr_release_dump);
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- if (ioa_cfg->sdt_state == DUMP_OBTAINED)
+ if (ioa_cfg->sdt_state == DUMP_OBTAINED && !ioa_cfg->dump_timeout)
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return;
@@ -3751,14 +3751,6 @@ static ssize_t ipr_store_update_fw(struct device *dev,
image_hdr = (struct ipr_ucode_image_header *)fw_entry->data;
- if (be32_to_cpu(image_hdr->header_length) > fw_entry->size ||
- (ioa_cfg->vpd_cbs->page3_data.card_type &&
- ioa_cfg->vpd_cbs->page3_data.card_type != image_hdr->card_type)) {
- dev_err(&ioa_cfg->pdev->dev, "Invalid microcode buffer\n");
- release_firmware(fw_entry);
- return -EINVAL;
- }
-
src = (u8 *)image_hdr + be32_to_cpu(image_hdr->header_length);
dnld_size = fw_entry->size - be32_to_cpu(image_hdr->header_length);
sglist = ipr_alloc_ucode_buffer(dnld_size);
@@ -3777,6 +3769,8 @@ static ssize_t ipr_store_update_fw(struct device *dev,
goto out;
}
+ ipr_info("Updating microcode, please be patient. This may take up to 30 minutes.\n");
+
result = ipr_update_ioa_ucode(ioa_cfg, sglist);
if (!result)
@@ -7449,8 +7443,11 @@ static int ipr_reset_wait_for_dump(struct ipr_cmnd *ipr_cmd)
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
if (ioa_cfg->sdt_state == GET_DUMP)
+ ioa_cfg->sdt_state = WAIT_FOR_DUMP;
+ else if (ioa_cfg->sdt_state == READ_DUMP)
ioa_cfg->sdt_state = ABORT_DUMP;
+ ioa_cfg->dump_timeout = 1;
ipr_cmd->job_step = ipr_reset_alert;
return IPR_RC_JOB_CONTINUE;
@@ -7614,6 +7611,8 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
ipr_cmd->job_step = ipr_reset_enable_ioa;
if (GET_DUMP == ioa_cfg->sdt_state) {
+ ioa_cfg->sdt_state = READ_DUMP;
+ ioa_cfg->dump_timeout = 0;
if (ioa_cfg->sis64)
ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT);
else
@@ -8003,8 +8002,12 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
if (ioa_cfg->ioa_is_dead)
return;
- if (ioa_cfg->in_reset_reload && ioa_cfg->sdt_state == GET_DUMP)
- ioa_cfg->sdt_state = ABORT_DUMP;
+ if (ioa_cfg->in_reset_reload) {
+ if (ioa_cfg->sdt_state == GET_DUMP)
+ ioa_cfg->sdt_state = WAIT_FOR_DUMP;
+ else if (ioa_cfg->sdt_state == READ_DUMP)
+ ioa_cfg->sdt_state = ABORT_DUMP;
+ }
if (ioa_cfg->reset_retries++ >= IPR_NUM_RESET_RELOAD_RETRIES) {
dev_err(&ioa_cfg->pdev->dev,
@@ -8812,7 +8815,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
uproc = readl(ioa_cfg->regs.sense_uproc_interrupt_reg32);
if ((mask & IPR_PCII_HRRQ_UPDATED) == 0 || (uproc & IPR_UPROCI_RESET_ALERT))
ioa_cfg->needs_hard_reset = 1;
- if (interrupts & IPR_PCII_ERROR_INTERRUPTS)
+ if ((interrupts & IPR_PCII_ERROR_INTERRUPTS) || reset_devices)
ioa_cfg->needs_hard_reset = 1;
if (interrupts & IPR_PCII_IOA_UNIT_CHECKED)
ioa_cfg->ioa_unit_checked = 1;
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index f93f8637c5a1..6d257e0dd6a5 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -208,7 +208,7 @@
#define IPR_CANCEL_ALL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
#define IPR_ABORT_TASK_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
#define IPR_INTERNAL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
-#define IPR_WRITE_BUFFER_TIMEOUT (10 * 60 * HZ)
+#define IPR_WRITE_BUFFER_TIMEOUT (30 * 60 * HZ)
#define IPR_SET_SUP_DEVICE_TIMEOUT (2 * 60 * HZ)
#define IPR_REQUEST_SENSE_TIMEOUT (10 * HZ)
#define IPR_OPERATIONAL_TIMEOUT (5 * 60)
@@ -1360,6 +1360,7 @@ enum ipr_sdt_state {
INACTIVE,
WAIT_FOR_DUMP,
GET_DUMP,
+ READ_DUMP,
ABORT_DUMP,
DUMP_OBTAINED
};
@@ -1384,6 +1385,7 @@ struct ipr_ioa_cfg {
u8 needs_warm_reset:1;
u8 msi_received:1;
u8 sis64:1;
+ u8 dump_timeout:1;
u8 revid;
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index 6981b773a88d..f07f30fada1b 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -1263,6 +1263,10 @@ void isci_host_deinit(struct isci_host *ihost)
{
int i;
+ /* disable output data selects */
+ for (i = 0; i < isci_gpio_count(ihost); i++)
+ writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]);
+
isci_host_change_state(ihost, isci_stopping);
for (i = 0; i < SCI_MAX_PORTS; i++) {
struct isci_port *iport = &ihost->ports[i];
@@ -1281,6 +1285,12 @@ void isci_host_deinit(struct isci_host *ihost)
spin_unlock_irq(&ihost->scic_lock);
wait_for_stop(ihost);
+
+ /* disable sgpio: where the above wait should give time for the
+ * enclosure to sample the gpios going inactive
+ */
+ writel(0, &ihost->scu_registers->peg0.sgpio.interface_control);
+
sci_controller_reset(ihost);
/* Cancel any/all outstanding port timers */
@@ -2365,6 +2375,12 @@ int isci_host_init(struct isci_host *ihost)
for (i = 0; i < SCI_MAX_PHYS; i++)
isci_phy_init(&ihost->phys[i], ihost, i);
+ /* enable sgpio */
+ writel(1, &ihost->scu_registers->peg0.sgpio.interface_control);
+ for (i = 0; i < isci_gpio_count(ihost); i++)
+ writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]);
+ writel(0, &ihost->scu_registers->peg0.sgpio.vendor_specific_code);
+
for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
struct isci_remote_device *idev = &ihost->devices[i];
@@ -2760,3 +2776,56 @@ enum sci_task_status sci_controller_start_task(struct isci_host *ihost,
return status;
}
+
+static int sci_write_gpio_tx_gp(struct isci_host *ihost, u8 reg_index, u8 reg_count, u8 *write_data)
+{
+ int d;
+
+ /* no support for TX_GP_CFG */
+ if (reg_index == 0)
+ return -EINVAL;
+
+ for (d = 0; d < isci_gpio_count(ihost); d++) {
+ u32 val = 0x444; /* all ODx.n clear */
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ int bit = (i << 2) + 2;
+
+ bit = try_test_sas_gpio_gp_bit(to_sas_gpio_od(d, i),
+ write_data, reg_index,
+ reg_count);
+ if (bit < 0)
+ break;
+
+ /* if od is set, clear the 'invert' bit */
+ val &= ~(bit << ((i << 2) + 2));
+ }
+
+ if (i < 3)
+ break;
+ writel(val, &ihost->scu_registers->peg0.sgpio.output_data_select[d]);
+ }
+
+ /* unless reg_index is > 1, we should always be able to write at
+ * least one register
+ */
+ return d > 0;
+}
+
+int isci_gpio_write(struct sas_ha_struct *sas_ha, u8 reg_type, u8 reg_index,
+ u8 reg_count, u8 *write_data)
+{
+ struct isci_host *ihost = sas_ha->lldd_ha;
+ int written;
+
+ switch (reg_type) {
+ case SAS_GPIO_REG_TX_GP:
+ written = sci_write_gpio_tx_gp(ihost, reg_index, reg_count, write_data);
+ break;
+ default:
+ written = -EINVAL;
+ }
+
+ return written;
+}
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 9f33831a2f04..646051afd3cb 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -440,6 +440,18 @@ static inline bool is_c0(struct pci_dev *pdev)
return false;
}
+/* set hw control for 'activity', even though active enclosures seem to drive
+ * the activity led on their own. Skip setting FSENG control on 'status' due
+ * to unexpected operation and 'error' due to not being a supported automatic
+ * FSENG output
+ */
+#define SGPIO_HW_CONTROL 0x00000443
+
+static inline int isci_gpio_count(struct isci_host *ihost)
+{
+ return ARRAY_SIZE(ihost->scu_registers->peg0.sgpio.output_data_select);
+}
+
void sci_controller_post_request(struct isci_host *ihost,
u32 request);
void sci_controller_release_frame(struct isci_host *ihost,
@@ -542,4 +554,7 @@ void sci_port_configuration_agent_construct(
enum sci_status sci_port_configuration_agent_initialize(
struct isci_host *ihost,
struct sci_port_configuration_agent *port_agent);
+
+int isci_gpio_write(struct sas_ha_struct *, u8 reg_type, u8 reg_index,
+ u8 reg_count, u8 *write_data);
#endif
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 29aa34efb0f5..43fe840fbe9c 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -192,6 +192,9 @@ static struct sas_domain_function_template isci_transport_ops = {
/* Phy management */
.lldd_control_phy = isci_phy_control,
+
+ /* GPIO support */
+ .lldd_write_gpio = isci_gpio_write,
};
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h
index d1de63312e7f..8efeb6b08321 100644
--- a/drivers/scsi/isci/isci.h
+++ b/drivers/scsi/isci/isci.h
@@ -97,7 +97,7 @@
#define SCU_MAX_COMPLETION_QUEUE_SHIFT (ilog2(SCU_MAX_COMPLETION_QUEUE_ENTRIES))
#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096)
-#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024)
+#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024U)
#define SCU_INVALID_FRAME_INDEX (0xFFFF)
#define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF)
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
index 430fc8ff014a..35f50c2183e1 100644
--- a/drivers/scsi/isci/phy.c
+++ b/drivers/scsi/isci/phy.c
@@ -708,7 +708,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)
__func__,
event_code);
- return SCI_FAILURE;;
+ return SCI_FAILURE;
}
return SCI_SUCCESS;
case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN:
@@ -1313,6 +1313,17 @@ int isci_phy_control(struct asd_sas_phy *sas_phy,
ret = isci_port_perform_hard_reset(ihost, iport, iphy);
break;
+ case PHY_FUNC_GET_EVENTS: {
+ struct scu_link_layer_registers __iomem *r;
+ struct sas_phy *phy = sas_phy->phy;
+
+ r = iphy->link_layer_registers;
+ phy->running_disparity_error_count = readl(&r->running_disparity_error_count);
+ phy->loss_of_dword_sync_count = readl(&r->loss_of_sync_error_count);
+ phy->phy_reset_problem_count = readl(&r->phy_reset_problem_count);
+ phy->invalid_dword_count = readl(&r->invalid_dword_counter);
+ break;
+ }
default:
dev_dbg(&ihost->pdev->dev,
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 8f6f9b77e41a..8e59c8865dcd 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -294,8 +294,8 @@ static void isci_port_link_down(struct isci_host *isci_host,
__func__, isci_device);
set_bit(IDEV_GONE, &isci_device->flags);
}
+ isci_port_change_state(isci_port, isci_stopping);
}
- isci_port_change_state(isci_port, isci_stopping);
}
/* Notify libsas of the borken link, this will trigger calls to our
diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c
index 486b113c634a..38a99d281141 100644
--- a/drivers/scsi/isci/port_config.c
+++ b/drivers/scsi/isci/port_config.c
@@ -678,7 +678,7 @@ static void apc_agent_timeout(unsigned long data)
configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
if (!configure_phy_mask)
- return;
+ goto done;
for (index = 0; index < SCI_MAX_PHYS; index++) {
if ((configure_phy_mask & (1 << index)) == 0)
diff --git a/drivers/scsi/isci/registers.h b/drivers/scsi/isci/registers.h
index 00afc738bbed..eaa541afc755 100644
--- a/drivers/scsi/isci/registers.h
+++ b/drivers/scsi/isci/registers.h
@@ -875,122 +875,6 @@ struct scu_iit_entry {
#define SCU_PTSxSR_GEN_BIT(name) \
SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ ## name)
-
-/*
- * *****************************************************************************
- * * SGPIO Register shift and mask values
- * ***************************************************************************** */
-#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_SHIFT (0)
-#define SCU_SGPIO_CONTROL_SGPIO_ENABLE_MASK (0x00000001)
-#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_SHIFT (1)
-#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_MASK (0x00000002)
-#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_SHIFT (2)
-#define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_MASK (0x00000004)
-#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_SHIFT (15)
-#define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_MASK (0x00008000)
-#define SCU_SGPIO_CONTROL_SGPIO_RESERVED_MASK (0xFFFF7FF8)
-
-#define SCU_SGICRx_GEN_BIT(name) \
- SCU_GEN_BIT(SCU_SGPIO_CONTROL_SGPIO_ ## name)
-
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_SHIFT (0)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_MASK (0x0000000F)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_SHIFT (4)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_MASK (0x000000F0)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_SHIFT (8)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_MASK (0x00000F00)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_SHIFT (12)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_MASK (0x0000F000)
-#define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_RESERVED_MASK (0xFFFF0000)
-
-#define SCU_SGPBRx_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_ ## name, value)
-
-#define SCU_SGPIO_START_DRIVE_LOWER_R0_SHIFT (0)
-#define SCU_SGPIO_START_DRIVE_LOWER_R0_MASK (0x00000003)
-#define SCU_SGPIO_START_DRIVE_LOWER_R1_SHIFT (4)
-#define SCU_SGPIO_START_DRIVE_LOWER_R1_MASK (0x00000030)
-#define SCU_SGPIO_START_DRIVE_LOWER_R2_SHIFT (8)
-#define SCU_SGPIO_START_DRIVE_LOWER_R2_MASK (0x00000300)
-#define SCU_SGPIO_START_DRIVE_LOWER_R3_SHIFT (12)
-#define SCU_SGPIO_START_DRIVE_LOWER_R3_MASK (0x00003000)
-#define SCU_SGPIO_START_DRIVE_LOWER_RESERVED_MASK (0xFFFF8888)
-
-#define SCU_SGSDLRx_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value)
-
-#define SCU_SGPIO_START_DRIVE_UPPER_R0_SHIFT (0)
-#define SCU_SGPIO_START_DRIVE_UPPER_R0_MASK (0x00000003)
-#define SCU_SGPIO_START_DRIVE_UPPER_R1_SHIFT (4)
-#define SCU_SGPIO_START_DRIVE_UPPER_R1_MASK (0x00000030)
-#define SCU_SGPIO_START_DRIVE_UPPER_R2_SHIFT (8)
-#define SCU_SGPIO_START_DRIVE_UPPER_R2_MASK (0x00000300)
-#define SCU_SGPIO_START_DRIVE_UPPER_R3_SHIFT (12)
-#define SCU_SGPIO_START_DRIVE_UPPER_R3_MASK (0x00003000)
-#define SCU_SGPIO_START_DRIVE_UPPER_RESERVED_MASK (0xFFFF8888)
-
-#define SCU_SGSDURx_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value)
-
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_SHIFT (0)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_MASK (0x00000003)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_SHIFT (4)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_MASK (0x00000030)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_SHIFT (8)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_MASK (0x00000300)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_SHIFT (12)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_MASK (0x00003000)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_RESERVED_MASK (0xFFFF8888)
-
-#define SCU_SGSIDLRx_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value)
-
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_SHIFT (0)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_MASK (0x00000003)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_SHIFT (4)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_MASK (0x00000030)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_SHIFT (8)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_MASK (0x00000300)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_SHIFT (12)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_MASK (0x00003000)
-#define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_RESERVED_MASK (0xFFFF8888)
-
-#define SCU_SGSIDURx_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value)
-
-#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_SHIFT (0)
-#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_MASK (0x0000000F)
-#define SCU_SGPIO_VENDOR_SPECIFIC_CODE_RESERVED_MASK (0xFFFFFFF0)
-
-#define SCU_SGVSCR_GEN_VAL(value) \
- SCU_GEN_VALUE(SCU_SGPIO_VENDOR_SPECIFIC_CODE ## name, value)
-
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_SHIFT (0)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_MASK (0x00000003)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_SHIFT (2)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_MASK (0x00000004)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_SHIFT (3)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_MASK (0x00000008)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_SHIFT (4)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_MASK (0x00000030)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_SHIFT (6)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_MASK (0x00000040)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_SHIFT (7)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_MASK (0x00000080)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_SHIFT (8)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_MASK (0x00000300)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_SHIFT (10)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_MASK (0x00000400)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_SHIFT (11)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_MASK (0x00000800)
-#define SCU_SGPIO_OUPUT_DATA_SELECT_RESERVED_MASK (0xFFFFF000)
-
-#define SCU_SGODSR_GEN_VAL(name, value) \
- SCU_GEN_VALUE(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name, value)
-
-#define SCU_SGODSR_GEN_BIT(name) \
- SCU_GEN_BIT(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name)
-
/*
* *****************************************************************************
* * SMU Registers
@@ -1529,10 +1413,12 @@ struct scu_sgpio_registers {
u32 serial_input_upper;
/* 0x0018 SGPIO_SGVSCR */
u32 vendor_specific_code;
+/* 0x001C Reserved */
+ u32 reserved_001c;
/* 0x0020 SGPIO_SGODSR */
- u32 ouput_data_select[8];
+ u32 output_data_select[8];
/* Remainder of memory space 256 bytes */
- u32 reserved_1444_14ff[0x31];
+ u32 reserved_1444_14ff[0x30];
};
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index b6e6368c2665..fbf9ce28c3f5 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -386,6 +386,18 @@ static bool is_remote_device_ready(struct isci_remote_device *idev)
}
}
+/*
+ * called once the remote node context has transisitioned to a ready
+ * state (after suspending RX and/or TX due to early D2H fis)
+ */
+static void atapi_remote_device_resume_done(void *_dev)
+{
+ struct isci_remote_device *idev = _dev;
+ struct isci_request *ireq = idev->working_request;
+
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+}
+
enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
u32 event_code)
{
@@ -432,6 +444,16 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
if (status != SCI_SUCCESS)
return status;
+ if (state == SCI_STP_DEV_ATAPI_ERROR) {
+ /* For ATAPI error state resume the RNC right away. */
+ if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
+ scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
+ return sci_remote_node_context_resume(&idev->rnc,
+ atapi_remote_device_resume_done,
+ idev);
+ }
+ }
+
if (state == SCI_STP_DEV_IDLE) {
/* We pick up suspension events to handle specifically to this
@@ -625,6 +647,7 @@ enum sci_status sci_remote_device_complete_io(struct isci_host *ihost,
case SCI_STP_DEV_CMD:
case SCI_STP_DEV_NCQ:
case SCI_STP_DEV_NCQ_ERROR:
+ case SCI_STP_DEV_ATAPI_ERROR:
status = common_complete_io(iport, idev, ireq);
if (status != SCI_SUCCESS)
break;
@@ -1020,6 +1043,7 @@ static const struct sci_base_state sci_remote_device_state_table[] = {
[SCI_STP_DEV_NCQ_ERROR] = {
.enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter,
},
+ [SCI_STP_DEV_ATAPI_ERROR] = { },
[SCI_STP_DEV_AWAIT_RESET] = { },
[SCI_SMP_DEV_IDLE] = {
.enter_state = sci_smp_remote_device_ready_idle_substate_enter,
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index 57ccfc3d6ad3..e1747ea0d0ea 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -244,6 +244,15 @@ enum sci_remote_device_states {
SCI_STP_DEV_NCQ_ERROR,
/**
+ * This is the ATAPI error state for the STP ATAPI remote device.
+ * This state is entered when ATAPI device sends error status FIS
+ * without data while the device object is in CMD state.
+ * A suspension event is expected in this state.
+ * The device object will resume right away.
+ */
+ SCI_STP_DEV_ATAPI_ERROR,
+
+ /**
* This is the READY substate indicates the device is waiting for the RESET task
* coming to be recovered from certain hardware specific error.
*/
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index b5d3a8c4d329..565a9f0a9bc2 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -481,7 +481,29 @@ static void sci_stp_optimized_request_construct(struct isci_request *ireq,
}
}
+static void sci_atapi_construct(struct isci_request *ireq)
+{
+ struct host_to_dev_fis *h2d_fis = &ireq->stp.cmd;
+ struct sas_task *task;
+
+ /* To simplify the implementation we take advantage of the
+ * silicon's partial acceleration of atapi protocol (dma data
+ * transfers), so we promote all commands to dma protocol. This
+ * breaks compatibility with ATA_HORKAGE_ATAPI_MOD16_DMA drives.
+ */
+ h2d_fis->features |= ATAPI_PKT_DMA;
+ scu_stp_raw_request_construct_task_context(ireq);
+
+ task = isci_request_access_task(ireq);
+ if (task->data_dir == DMA_NONE)
+ task->total_xfer_len = 0;
+
+ /* clear the response so we can detect arrivial of an
+ * unsolicited h2d fis
+ */
+ ireq->stp.rsp.fis_type = 0;
+}
static enum sci_status
sci_io_request_construct_sata(struct isci_request *ireq,
@@ -491,6 +513,7 @@ sci_io_request_construct_sata(struct isci_request *ireq,
{
enum sci_status status = SCI_SUCCESS;
struct sas_task *task = isci_request_access_task(ireq);
+ struct domain_device *dev = ireq->target_device->domain_dev;
/* check for management protocols */
if (ireq->ttype == tmf_task) {
@@ -519,6 +542,13 @@ sci_io_request_construct_sata(struct isci_request *ireq,
}
+ /* ATAPI */
+ if (dev->sata_dev.command_set == ATAPI_COMMAND_SET &&
+ task->ata_task.fis.command == ATA_CMD_PACKET) {
+ sci_atapi_construct(ireq);
+ return SCI_SUCCESS;
+ }
+
/* non data */
if (task->data_dir == DMA_NONE) {
scu_stp_raw_request_construct_task_context(ireq);
@@ -627,7 +657,7 @@ enum sci_status sci_task_request_construct_sata(struct isci_request *ireq)
/**
* sci_req_tx_bytes - bytes transferred when reply underruns request
- * @sci_req: request that was terminated early
+ * @ireq: request that was terminated early
*/
#define SCU_TASK_CONTEXT_SRAM 0x200000
static u32 sci_req_tx_bytes(struct isci_request *ireq)
@@ -729,6 +759,10 @@ sci_io_request_terminate(struct isci_request *ireq)
case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED:
case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG:
case SCI_REQ_STP_SOFT_RESET_WAIT_D2H:
+ case SCI_REQ_ATAPI_WAIT_H2D:
+ case SCI_REQ_ATAPI_WAIT_PIO_SETUP:
+ case SCI_REQ_ATAPI_WAIT_D2H:
+ case SCI_REQ_ATAPI_WAIT_TC_COMP:
sci_change_state(&ireq->sm, SCI_REQ_ABORTING);
return SCI_SUCCESS;
case SCI_REQ_TASK_WAIT_TC_RESP:
@@ -1194,8 +1228,8 @@ static enum sci_status sci_stp_request_pio_data_out_transmit_data(struct isci_re
{
struct isci_stp_request *stp_req = &ireq->stp.req;
struct scu_sgl_element_pair *sgl_pair;
+ enum sci_status status = SCI_SUCCESS;
struct scu_sgl_element *sgl;
- enum sci_status status;
u32 offset;
u32 len = 0;
@@ -1249,7 +1283,7 @@ static enum sci_status sci_stp_request_pio_data_out_transmit_data(struct isci_re
*/
static enum sci_status
sci_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req,
- u8 *data_buf, u32 len)
+ u8 *data_buf, u32 len)
{
struct isci_request *ireq;
u8 *src_addr;
@@ -1423,6 +1457,128 @@ static enum sci_status sci_stp_request_udma_general_frame_handler(struct isci_re
return status;
}
+static enum sci_status process_unsolicited_fis(struct isci_request *ireq,
+ u32 frame_index)
+{
+ struct isci_host *ihost = ireq->owning_controller;
+ enum sci_status status;
+ struct dev_to_host_fis *frame_header;
+ u32 *frame_buffer;
+
+ status = sci_unsolicited_frame_control_get_header(&ihost->uf_control,
+ frame_index,
+ (void **)&frame_header);
+
+ if (status != SCI_SUCCESS)
+ return status;
+
+ if (frame_header->fis_type != FIS_REGD2H) {
+ dev_err(&ireq->isci_host->pdev->dev,
+ "%s ERROR: invalid fis type 0x%X\n",
+ __func__, frame_header->fis_type);
+ return SCI_FAILURE;
+ }
+
+ sci_unsolicited_frame_control_get_buffer(&ihost->uf_control,
+ frame_index,
+ (void **)&frame_buffer);
+
+ sci_controller_copy_sata_response(&ireq->stp.rsp,
+ (u32 *)frame_header,
+ frame_buffer);
+
+ /* Frame has been decoded return it to the controller */
+ sci_controller_release_frame(ihost, frame_index);
+
+ return status;
+}
+
+static enum sci_status atapi_d2h_reg_frame_handler(struct isci_request *ireq,
+ u32 frame_index)
+{
+ struct sas_task *task = isci_request_access_task(ireq);
+ enum sci_status status;
+
+ status = process_unsolicited_fis(ireq, frame_index);
+
+ if (status == SCI_SUCCESS) {
+ if (ireq->stp.rsp.status & ATA_ERR)
+ status = SCI_IO_FAILURE_RESPONSE_VALID;
+ } else {
+ status = SCI_IO_FAILURE_RESPONSE_VALID;
+ }
+
+ if (status != SCI_SUCCESS) {
+ ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE;
+ ireq->sci_status = status;
+ } else {
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS;
+ }
+
+ /* the d2h ufi is the end of non-data commands */
+ if (task->data_dir == DMA_NONE)
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+
+ return status;
+}
+
+static void scu_atapi_reconstruct_raw_frame_task_context(struct isci_request *ireq)
+{
+ struct ata_device *dev = sas_to_ata_dev(ireq->target_device->domain_dev);
+ void *atapi_cdb = ireq->ttype_ptr.io_task_ptr->ata_task.atapi_packet;
+ struct scu_task_context *task_context = ireq->tc;
+
+ /* fill in the SCU Task Context for a DATA fis containing CDB in Raw Frame
+ * type. The TC for previous Packet fis was already there, we only need to
+ * change the H2D fis content.
+ */
+ memset(&ireq->stp.cmd, 0, sizeof(struct host_to_dev_fis));
+ memcpy(((u8 *)&ireq->stp.cmd + sizeof(u32)), atapi_cdb, ATAPI_CDB_LEN);
+ memset(&(task_context->type.stp), 0, sizeof(struct stp_task_context));
+ task_context->type.stp.fis_type = FIS_DATA;
+ task_context->transfer_length_bytes = dev->cdb_len;
+}
+
+static void scu_atapi_construct_task_context(struct isci_request *ireq)
+{
+ struct ata_device *dev = sas_to_ata_dev(ireq->target_device->domain_dev);
+ struct sas_task *task = isci_request_access_task(ireq);
+ struct scu_task_context *task_context = ireq->tc;
+ int cdb_len = dev->cdb_len;
+
+ /* reference: SSTL 1.13.4.2
+ * task_type, sata_direction
+ */
+ if (task->data_dir == DMA_TO_DEVICE) {
+ task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
+ task_context->sata_direction = 0;
+ } else {
+ /* todo: for NO_DATA command, we need to send out raw frame. */
+ task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
+ task_context->sata_direction = 1;
+ }
+
+ memset(&task_context->type.stp, 0, sizeof(task_context->type.stp));
+ task_context->type.stp.fis_type = FIS_DATA;
+
+ memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd));
+ memcpy(&ireq->stp.cmd.lbal, task->ata_task.atapi_packet, cdb_len);
+ task_context->ssp_command_iu_length = cdb_len / sizeof(u32);
+
+ /* task phase is set to TX_CMD */
+ task_context->task_phase = 0x1;
+
+ /* retry counter */
+ task_context->stp_retry_count = 0;
+
+ /* data transfer size. */
+ task_context->transfer_length_bytes = task->total_xfer_len;
+
+ /* setup sgl */
+ sci_request_build_sgl(ireq);
+}
+
enum sci_status
sci_io_request_frame_handler(struct isci_request *ireq,
u32 frame_index)
@@ -1490,29 +1646,30 @@ sci_io_request_frame_handler(struct isci_request *ireq,
return SCI_SUCCESS;
case SCI_REQ_SMP_WAIT_RESP: {
- struct smp_resp *rsp_hdr = &ireq->smp.rsp;
- void *frame_header;
+ struct sas_task *task = isci_request_access_task(ireq);
+ struct scatterlist *sg = &task->smp_task.smp_resp;
+ void *frame_header, *kaddr;
+ u8 *rsp;
sci_unsolicited_frame_control_get_header(&ihost->uf_control,
- frame_index,
- &frame_header);
-
- /* byte swap the header. */
- word_cnt = SMP_RESP_HDR_SZ / sizeof(u32);
- sci_swab32_cpy(rsp_hdr, frame_header, word_cnt);
+ frame_index,
+ &frame_header);
+ kaddr = kmap_atomic(sg_page(sg), KM_IRQ0);
+ rsp = kaddr + sg->offset;
+ sci_swab32_cpy(rsp, frame_header, 1);
- if (rsp_hdr->frame_type == SMP_RESPONSE) {
+ if (rsp[0] == SMP_RESPONSE) {
void *smp_resp;
sci_unsolicited_frame_control_get_buffer(&ihost->uf_control,
- frame_index,
- &smp_resp);
-
- word_cnt = (sizeof(struct smp_resp) - SMP_RESP_HDR_SZ) /
- sizeof(u32);
+ frame_index,
+ &smp_resp);
- sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ,
- smp_resp, word_cnt);
+ word_cnt = (sg->length/4)-1;
+ if (word_cnt > 0)
+ word_cnt = min_t(unsigned int, word_cnt,
+ SCU_UNSOLICITED_FRAME_BUFFER_SIZE/4);
+ sci_swab32_cpy(rsp + 4, smp_resp, word_cnt);
ireq->scu_status = SCU_TASK_DONE_GOOD;
ireq->sci_status = SCI_SUCCESS;
@@ -1528,12 +1685,13 @@ sci_io_request_frame_handler(struct isci_request *ireq,
__func__,
ireq,
frame_index,
- rsp_hdr->frame_type);
+ rsp[0]);
ireq->scu_status = SCU_TASK_DONE_SMP_FRM_TYPE_ERR;
ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR;
sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
}
+ kunmap_atomic(kaddr, KM_IRQ0);
sci_controller_release_frame(ihost, frame_index);
@@ -1833,6 +1991,24 @@ sci_io_request_frame_handler(struct isci_request *ireq,
return status;
}
+ case SCI_REQ_ATAPI_WAIT_PIO_SETUP: {
+ struct sas_task *task = isci_request_access_task(ireq);
+
+ sci_controller_release_frame(ihost, frame_index);
+ ireq->target_device->working_request = ireq;
+ if (task->data_dir == DMA_NONE) {
+ sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_TC_COMP);
+ scu_atapi_reconstruct_raw_frame_task_context(ireq);
+ } else {
+ sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_D2H);
+ scu_atapi_construct_task_context(ireq);
+ }
+
+ sci_controller_continue_io(ireq);
+ return SCI_SUCCESS;
+ }
+ case SCI_REQ_ATAPI_WAIT_D2H:
+ return atapi_d2h_reg_frame_handler(ireq, frame_index);
case SCI_REQ_ABORTING:
/*
* TODO: Is it even possible to get an unsolicited frame in the
@@ -1898,10 +2074,9 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
- case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR):
sci_remote_device_suspend(ireq->target_device,
SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)));
- /* Fall through to the default case */
+ /* Fall through to the default case */
default:
/* All other completion status cause the IO to be complete. */
ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code);
@@ -1964,6 +2139,112 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq,
return SCI_SUCCESS;
}
+static enum sci_status atapi_raw_completion(struct isci_request *ireq, u32 completion_code,
+ enum sci_base_request_states next)
+{
+ enum sci_status status = SCI_SUCCESS;
+
+ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+ case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS;
+ sci_change_state(&ireq->sm, next);
+ break;
+ default:
+ /* All other completion status cause the IO to be complete.
+ * If a NAK was received, then it is up to the user to retry
+ * the request.
+ */
+ ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code);
+ ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR;
+
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+ break;
+ }
+
+ return status;
+}
+
+static enum sci_status atapi_data_tc_completion_handler(struct isci_request *ireq,
+ u32 completion_code)
+{
+ struct isci_remote_device *idev = ireq->target_device;
+ struct dev_to_host_fis *d2h = &ireq->stp.rsp;
+ enum sci_status status = SCI_SUCCESS;
+
+ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+ case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+ break;
+
+ case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT): {
+ u16 len = sci_req_tx_bytes(ireq);
+
+ /* likely non-error data underrrun, workaround missing
+ * d2h frame from the controller
+ */
+ if (d2h->fis_type != FIS_REGD2H) {
+ d2h->fis_type = FIS_REGD2H;
+ d2h->flags = (1 << 6);
+ d2h->status = 0x50;
+ d2h->error = 0;
+ d2h->lbal = 0;
+ d2h->byte_count_low = len & 0xff;
+ d2h->byte_count_high = len >> 8;
+ d2h->device = 0xa0;
+ d2h->lbal_exp = 0;
+ d2h->lbam_exp = 0;
+ d2h->lbah_exp = 0;
+ d2h->_r_a = 0;
+ d2h->sector_count = 0x3;
+ d2h->sector_count_exp = 0;
+ d2h->_r_b = 0;
+ d2h->_r_c = 0;
+ d2h->_r_d = 0;
+ }
+
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS_IO_DONE_EARLY;
+ status = ireq->sci_status;
+
+ /* the hw will have suspended the rnc, so complete the
+ * request upon pending resume
+ */
+ sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR);
+ break;
+ }
+ case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
+ /* In this case, there is no UF coming after.
+ * compelte the IO now.
+ */
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS;
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+ break;
+
+ default:
+ if (d2h->fis_type == FIS_REGD2H) {
+ /* UF received change the device state to ATAPI_ERROR */
+ status = ireq->sci_status;
+ sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR);
+ } else {
+ /* If receiving any non-sucess TC status, no UF
+ * received yet, then an UF for the status fis
+ * is coming after (XXX: suspect this is
+ * actually a protocol error or a bug like the
+ * DONE_UNEXP_FIS case)
+ */
+ ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE;
+ ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
+
+ sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_D2H);
+ }
+ break;
+ }
+
+ return status;
+}
+
enum sci_status
sci_io_request_tc_completion(struct isci_request *ireq,
u32 completion_code)
@@ -2015,6 +2296,17 @@ sci_io_request_tc_completion(struct isci_request *ireq,
return request_aborting_state_tc_event(ireq,
completion_code);
+ case SCI_REQ_ATAPI_WAIT_H2D:
+ return atapi_raw_completion(ireq, completion_code,
+ SCI_REQ_ATAPI_WAIT_PIO_SETUP);
+
+ case SCI_REQ_ATAPI_WAIT_TC_COMP:
+ return atapi_raw_completion(ireq, completion_code,
+ SCI_REQ_ATAPI_WAIT_D2H);
+
+ case SCI_REQ_ATAPI_WAIT_D2H:
+ return atapi_data_tc_completion_handler(ireq, completion_code);
+
default:
dev_warn(&ihost->pdev->dev,
"%s: SCIC IO Request given task completion "
@@ -2421,6 +2713,8 @@ static void isci_process_stp_response(struct sas_task *task, struct dev_to_host_
*/
if (fis->status & ATA_DF)
ts->stat = SAS_PROTO_RESPONSE;
+ else if (fis->status & ATA_ERR)
+ ts->stat = SAM_STAT_CHECK_CONDITION;
else
ts->stat = SAM_STAT_GOOD;
@@ -2603,18 +2897,7 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
status = SAM_STAT_GOOD;
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
- if (task->task_proto == SAS_PROTOCOL_SMP) {
- void *rsp = &request->smp.rsp;
-
- dev_dbg(&ihost->pdev->dev,
- "%s: SMP protocol completion\n",
- __func__);
-
- sg_copy_from_buffer(
- &task->smp_task.smp_resp, 1,
- rsp, sizeof(struct smp_resp));
- } else if (completion_status
- == SCI_IO_SUCCESS_IO_DONE_EARLY) {
+ if (completion_status == SCI_IO_SUCCESS_IO_DONE_EARLY) {
/* This was an SSP / STP / SATA transfer.
* There is a possibility that less data than
@@ -2791,6 +3074,7 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
{
struct isci_request *ireq = container_of(sm, typeof(*ireq), sm);
struct domain_device *dev = ireq->target_device->domain_dev;
+ enum sci_base_request_states state;
struct sas_task *task;
/* XXX as hch said always creating an internal sas_task for tmf
@@ -2802,26 +3086,30 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
* substates
*/
if (!task && dev->dev_type == SAS_END_DEV) {
- sci_change_state(sm, SCI_REQ_TASK_WAIT_TC_COMP);
+ state = SCI_REQ_TASK_WAIT_TC_COMP;
} else if (!task &&
(isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_high ||
isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_low)) {
- sci_change_state(sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED);
+ state = SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED;
} else if (task && task->task_proto == SAS_PROTOCOL_SMP) {
- sci_change_state(sm, SCI_REQ_SMP_WAIT_RESP);
+ state = SCI_REQ_SMP_WAIT_RESP;
} else if (task && sas_protocol_ata(task->task_proto) &&
!task->ata_task.use_ncq) {
- u32 state;
-
- if (task->data_dir == DMA_NONE)
+ if (dev->sata_dev.command_set == ATAPI_COMMAND_SET &&
+ task->ata_task.fis.command == ATA_CMD_PACKET) {
+ state = SCI_REQ_ATAPI_WAIT_H2D;
+ } else if (task->data_dir == DMA_NONE) {
state = SCI_REQ_STP_NON_DATA_WAIT_H2D;
- else if (task->ata_task.dma_xfer)
+ } else if (task->ata_task.dma_xfer) {
state = SCI_REQ_STP_UDMA_WAIT_TC_COMP;
- else /* PIO */
+ } else /* PIO */ {
state = SCI_REQ_STP_PIO_WAIT_H2D;
-
- sci_change_state(sm, state);
+ }
+ } else {
+ /* SSP or NCQ are fully accelerated, no substates */
+ return;
}
+ sci_change_state(sm, state);
}
static void sci_request_completed_state_enter(struct sci_base_state_machine *sm)
@@ -2913,6 +3201,10 @@ static const struct sci_base_state sci_request_state_table[] = {
[SCI_REQ_TASK_WAIT_TC_RESP] = { },
[SCI_REQ_SMP_WAIT_RESP] = { },
[SCI_REQ_SMP_WAIT_TC_COMP] = { },
+ [SCI_REQ_ATAPI_WAIT_H2D] = { },
+ [SCI_REQ_ATAPI_WAIT_PIO_SETUP] = { },
+ [SCI_REQ_ATAPI_WAIT_D2H] = { },
+ [SCI_REQ_ATAPI_WAIT_TC_COMP] = { },
[SCI_REQ_COMPLETED] = {
.enter_state = sci_request_completed_state_enter,
},
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
index 7a1d5a9778eb..f720b97b7bb5 100644
--- a/drivers/scsi/isci/request.h
+++ b/drivers/scsi/isci/request.h
@@ -96,7 +96,6 @@ enum sci_request_protocol {
* to wait for another fis or if the transfer is complete. Upon
* receipt of a d2h fis this will be the status field of that fis.
* @sgl - track pio transfer progress as we iterate through the sgl
- * @device_cdb_len - atapi device advertises it's transfer constraints at setup
*/
struct isci_stp_request {
u32 pio_len;
@@ -107,7 +106,6 @@ struct isci_stp_request {
u8 set;
u32 offset;
} sgl;
- u32 device_cdb_len;
};
struct isci_request {
@@ -174,9 +172,6 @@ struct isci_request {
};
} ssp;
struct {
- struct smp_resp rsp;
- } smp;
- struct {
struct isci_stp_request req;
struct host_to_dev_fis cmd;
struct dev_to_host_fis rsp;
@@ -252,6 +247,32 @@ enum sci_base_request_states {
SCI_REQ_STP_PIO_DATA_OUT,
/*
+ * While in this state the IO request object is waiting for the TC
+ * completion notification for the H2D Register FIS
+ */
+ SCI_REQ_ATAPI_WAIT_H2D,
+
+ /*
+ * While in this state the IO request object is waiting for either a
+ * PIO Setup.
+ */
+ SCI_REQ_ATAPI_WAIT_PIO_SETUP,
+
+ /*
+ * The non-data IO transit to this state in this state after receiving
+ * TC completion. While in this state IO request object is waiting for
+ * D2H status frame as UF.
+ */
+ SCI_REQ_ATAPI_WAIT_D2H,
+
+ /*
+ * When transmitting raw frames hardware reports task context completion
+ * after every frame submission, so in the non-accelerated case we need
+ * to expect the completion for the "cdb" frame.
+ */
+ SCI_REQ_ATAPI_WAIT_TC_COMP,
+
+ /*
* The AWAIT_TC_COMPLETION sub-state indicates that the started raw
* task management request is waiting for the transmission of the
* initial frame (i.e. command, task, etc.).
diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h
index 462b15174d3f..dc26b4aea99e 100644
--- a/drivers/scsi/isci/sas.h
+++ b/drivers/scsi/isci/sas.h
@@ -204,8 +204,6 @@ struct smp_req {
u8 req_data[0];
} __packed;
-#define SMP_RESP_HDR_SZ 4
-
/*
* struct sci_sas_address - This structure depicts how a SAS address is
* represented by SCI.
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index d6bcdd013dc9..e2d9418683ce 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -1345,29 +1345,6 @@ static void isci_smp_task_done(struct sas_task *task)
complete(&task->completion);
}
-static struct sas_task *isci_alloc_task(void)
-{
- struct sas_task *task = kzalloc(sizeof(*task), GFP_KERNEL);
-
- if (task) {
- INIT_LIST_HEAD(&task->list);
- spin_lock_init(&task->task_state_lock);
- task->task_state_flags = SAS_TASK_STATE_PENDING;
- init_timer(&task->timer);
- init_completion(&task->completion);
- }
-
- return task;
-}
-
-static void isci_free_task(struct isci_host *ihost, struct sas_task *task)
-{
- if (task) {
- BUG_ON(!list_empty(&task->list));
- kfree(task);
- }
-}
-
static int isci_smp_execute_task(struct isci_host *ihost,
struct domain_device *dev, void *req,
int req_size, void *resp, int resp_size)
@@ -1376,7 +1353,7 @@ static int isci_smp_execute_task(struct isci_host *ihost,
struct sas_task *task = NULL;
for (retry = 0; retry < 3; retry++) {
- task = isci_alloc_task();
+ task = sas_alloc_task(GFP_KERNEL);
if (!task)
return -ENOMEM;
@@ -1439,13 +1416,13 @@ static int isci_smp_execute_task(struct isci_host *ihost,
SAS_ADDR(dev->sas_addr),
task->task_status.resp,
task->task_status.stat);
- isci_free_task(ihost, task);
+ sas_free_task(task);
task = NULL;
}
}
ex_err:
BUG_ON(retry == 3 && task != NULL);
- isci_free_task(ihost, task);
+ sas_free_task(task);
return res;
}
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index 4a7fa90287ef..15b18d158993 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -286,6 +286,25 @@ isci_task_set_completion_status(
task->task_status.resp = response;
task->task_status.stat = status;
+ switch (task->task_proto) {
+
+ case SAS_PROTOCOL_SATA:
+ case SAS_PROTOCOL_STP:
+ case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+
+ if (task_notification_selection
+ == isci_perform_error_io_completion) {
+ /* SATA/STP I/O has it's own means of scheduling device
+ * error handling on the normal path.
+ */
+ task_notification_selection
+ = isci_perform_normal_io_completion;
+ }
+ break;
+ default:
+ break;
+ }
+
switch (task_notification_selection) {
case isci_perform_error_io_completion:
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 7724414588fa..23e706673d06 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -872,6 +872,61 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
iscsi_host_free(shost);
}
+static mode_t iscsi_sw_tcp_attr_is_visible(int param_type, int param)
+{
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_NETDEV_NAME:
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_HDRDGST_EN:
+ case ISCSI_PARAM_DATADGST_EN:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_EXP_STATSN:
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_PING_TMO:
+ case ISCSI_PARAM_RECV_TMO:
+ case ISCSI_PARAM_INITIAL_R2T_EN:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_IMM_DATA_EN:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_PDU_INORDER_EN:
+ case ISCSI_PARAM_DATASEQ_INORDER_EN:
+ case ISCSI_PARAM_ERL:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_USERNAME:
+ case ISCSI_PARAM_PASSWORD:
+ case ISCSI_PARAM_USERNAME_IN:
+ case ISCSI_PARAM_PASSWORD_IN:
+ case ISCSI_PARAM_FAST_ABORT:
+ case ISCSI_PARAM_ABORT_TMO:
+ case ISCSI_PARAM_LU_RESET_TMO:
+ case ISCSI_PARAM_TGT_RESET_TMO:
+ case ISCSI_PARAM_IFACE_NAME:
+ case ISCSI_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev)
{
set_bit(QUEUE_FLAG_BIDI, &sdev->request_queue->queue_flags);
@@ -910,33 +965,6 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
.name = "tcp",
.caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
| CAP_DATADGST,
- .param_mask = ISCSI_MAX_RECV_DLENGTH |
- ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN |
- ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN |
- ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN |
- ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST |
- ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN |
- ISCSI_ERL |
- ISCSI_CONN_PORT |
- ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN |
- ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_INITIATOR_NAME |
- ISCSI_HOST_NETDEV_NAME,
/* session management */
.create_session = iscsi_sw_tcp_session_create,
.destroy_session = iscsi_sw_tcp_session_destroy,
@@ -944,6 +972,7 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
.create_conn = iscsi_sw_tcp_conn_create,
.bind_conn = iscsi_sw_tcp_conn_bind,
.destroy_conn = iscsi_sw_tcp_conn_destroy,
+ .attr_is_visible = iscsi_sw_tcp_attr_is_visible,
.set_param = iscsi_sw_tcp_conn_set_param,
.get_conn_param = iscsi_sw_tcp_conn_get_param,
.get_session_param = iscsi_session_get_param,
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index d261e982a2fa..7c055fdca45d 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -65,16 +65,15 @@ static struct workqueue_struct *fc_exch_workqueue;
* assigned range of exchanges to per cpu pool.
*/
struct fc_exch_pool {
+ spinlock_t lock;
+ struct list_head ex_list;
u16 next_index;
u16 total_exches;
/* two cache of free slot in exch array */
u16 left;
u16 right;
-
- spinlock_t lock;
- struct list_head ex_list;
-};
+} ____cacheline_aligned_in_smp;
/**
* struct fc_exch_mgr - The Exchange Manager (EM).
@@ -91,13 +90,13 @@ struct fc_exch_pool {
* It manages the allocation of exchange IDs.
*/
struct fc_exch_mgr {
+ struct fc_exch_pool *pool;
+ mempool_t *ep_pool;
enum fc_class class;
struct kref kref;
u16 min_xid;
u16 max_xid;
- mempool_t *ep_pool;
u16 pool_max_index;
- struct fc_exch_pool *pool;
/*
* currently exchange mgr stats are updated but not used.
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 4c41ee816f0b..221875ec3d7c 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -759,7 +759,6 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
goto out;
if (fc_fcp_lock_pkt(fsp))
goto out;
- fsp->last_pkt_time = jiffies;
if (fh->fh_type == FC_TYPE_BLS) {
fc_fcp_abts_resp(fsp, fp);
@@ -1148,7 +1147,6 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
rc = -1;
goto unlock;
}
- fsp->last_pkt_time = jiffies;
fsp->seq_ptr = seq;
fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 256a999d010b..d7c76f2eb636 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -3163,7 +3163,6 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
{
struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
- uint32_t value;
switch(param) {
case ISCSI_PARAM_FAST_ABORT:
@@ -3220,14 +3219,6 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
case ISCSI_PARAM_ERL:
sscanf(buf, "%d", &session->erl);
break;
- case ISCSI_PARAM_IFMARKER_EN:
- sscanf(buf, "%d", &value);
- BUG_ON(value);
- break;
- case ISCSI_PARAM_OFMARKER_EN:
- sscanf(buf, "%d", &value);
- BUG_ON(value);
- break;
case ISCSI_PARAM_EXP_STATSN:
sscanf(buf, "%u", &conn->exp_statsn);
break;
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index f5831930df9b..54a5199ceb56 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -219,17 +219,20 @@ out_err2:
/* ---------- Device registration and unregistration ---------- */
-static inline void sas_unregister_common_dev(struct domain_device *dev)
+static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_device *dev)
{
sas_notify_lldd_dev_gone(dev);
if (!dev->parent)
dev->port->port_dev = NULL;
else
list_del_init(&dev->siblings);
+
+ spin_lock_irq(&port->dev_list_lock);
list_del_init(&dev->dev_list_node);
+ spin_unlock_irq(&port->dev_list_lock);
}
-void sas_unregister_dev(struct domain_device *dev)
+void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
{
if (dev->rphy) {
sas_remove_children(&dev->rphy->dev);
@@ -241,15 +244,15 @@ void sas_unregister_dev(struct domain_device *dev)
kfree(dev->ex_dev.ex_phy);
dev->ex_dev.ex_phy = NULL;
}
- sas_unregister_common_dev(dev);
+ sas_unregister_common_dev(port, dev);
}
void sas_unregister_domain_devices(struct asd_sas_port *port)
{
struct domain_device *dev, *n;
- list_for_each_entry_safe_reverse(dev,n,&port->dev_list,dev_list_node)
- sas_unregister_dev(dev);
+ list_for_each_entry_safe_reverse(dev, n, &port->dev_list, dev_list_node)
+ sas_unregister_dev(port, dev);
port->port->rphy = NULL;
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 16ad97df5ba6..1b831c55ec6e 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -199,6 +199,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
phy->virtual = dr->virtual;
phy->last_da_index = -1;
+ phy->phy->identify.sas_address = SAS_ADDR(phy->attached_sas_addr);
+ phy->phy->identify.device_type = phy->attached_dev_type;
phy->phy->identify.initiator_port_protocols = phy->attached_iproto;
phy->phy->identify.target_port_protocols = phy->attached_tproto;
phy->phy->identify.phy_identifier = phy_id;
@@ -329,6 +331,7 @@ static void ex_assign_report_general(struct domain_device *dev,
dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count);
dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes);
dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS);
+ dev->ex_dev.t2t_supp = rg->t2t_supp;
dev->ex_dev.conf_route_table = rg->conf_route_table;
dev->ex_dev.configuring = rg->configuring;
memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8);
@@ -751,7 +754,10 @@ static struct domain_device *sas_ex_discover_end_dev(
out_list_del:
sas_rphy_free(child->rphy);
child->rphy = NULL;
+
+ spin_lock_irq(&parent->port->dev_list_lock);
list_del(&child->dev_list_node);
+ spin_unlock_irq(&parent->port->dev_list_lock);
out_free:
sas_port_delete(phy->port);
out_err:
@@ -1133,15 +1139,17 @@ static void sas_print_parent_topology_bug(struct domain_device *child,
};
struct domain_device *parent = child->parent;
- sas_printk("%s ex %016llx phy 0x%x <--> %s ex %016llx phy 0x%x "
- "has %c:%c routing link!\n",
+ sas_printk("%s ex %016llx (T2T supp:%d) phy 0x%x <--> %s ex %016llx "
+ "(T2T supp:%d) phy 0x%x has %c:%c routing link!\n",
ex_type[parent->dev_type],
SAS_ADDR(parent->sas_addr),
+ parent->ex_dev.t2t_supp,
parent_phy->phy_id,
ex_type[child->dev_type],
SAS_ADDR(child->sas_addr),
+ child->ex_dev.t2t_supp,
child_phy->phy_id,
ra_char[parent_phy->routing_attr],
@@ -1238,10 +1246,15 @@ static int sas_check_parent_topology(struct domain_device *child)
sas_print_parent_topology_bug(child, parent_phy, child_phy);
res = -ENODEV;
}
- } else if (parent_phy->routing_attr == TABLE_ROUTING &&
- child_phy->routing_attr != SUBTRACTIVE_ROUTING) {
- sas_print_parent_topology_bug(child, parent_phy, child_phy);
- res = -ENODEV;
+ } else if (parent_phy->routing_attr == TABLE_ROUTING) {
+ if (child_phy->routing_attr == SUBTRACTIVE_ROUTING ||
+ (child_phy->routing_attr == TABLE_ROUTING &&
+ child_ex->t2t_supp && parent_ex->t2t_supp)) {
+ /* All good */;
+ } else {
+ sas_print_parent_topology_bug(child, parent_phy, child_phy);
+ res = -ENODEV;
+ }
}
break;
case FANOUT_DEV:
@@ -1729,7 +1742,7 @@ out:
return res;
}
-static void sas_unregister_ex_tree(struct domain_device *dev)
+static void sas_unregister_ex_tree(struct asd_sas_port *port, struct domain_device *dev)
{
struct expander_device *ex = &dev->ex_dev;
struct domain_device *child, *n;
@@ -1738,11 +1751,11 @@ static void sas_unregister_ex_tree(struct domain_device *dev)
child->gone = 1;
if (child->dev_type == EDGE_DEV ||
child->dev_type == FANOUT_DEV)
- sas_unregister_ex_tree(child);
+ sas_unregister_ex_tree(port, child);
else
- sas_unregister_dev(child);
+ sas_unregister_dev(port, child);
}
- sas_unregister_dev(dev);
+ sas_unregister_dev(port, dev);
}
static void sas_unregister_devs_sas_addr(struct domain_device *parent,
@@ -1759,9 +1772,9 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
child->gone = 1;
if (child->dev_type == EDGE_DEV ||
child->dev_type == FANOUT_DEV)
- sas_unregister_ex_tree(child);
+ sas_unregister_ex_tree(parent->port, child);
else
- sas_unregister_dev(child);
+ sas_unregister_dev(parent->port, child);
break;
}
}
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
index 04ad8dd1a74c..e1aa17840c5b 100644
--- a/drivers/scsi/libsas/sas_host_smp.c
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -51,6 +51,91 @@ static void sas_host_smp_discover(struct sas_ha_struct *sas_ha, u8 *resp_data,
resp_data[15] = rphy->identify.target_port_protocols;
}
+/**
+ * to_sas_gpio_gp_bit - given the gpio frame data find the byte/bit position of 'od'
+ * @od: od bit to find
+ * @data: incoming bitstream (from frame)
+ * @index: requested data register index (from frame)
+ * @count: total number of registers in the bitstream (from frame)
+ * @bit: bit position of 'od' in the returned byte
+ *
+ * returns NULL if 'od' is not in 'data'
+ *
+ * From SFF-8485 v0.7:
+ * "In GPIO_TX[1], bit 0 of byte 3 contains the first bit (i.e., OD0.0)
+ * and bit 7 of byte 0 contains the 32nd bit (i.e., OD10.1).
+ *
+ * In GPIO_TX[2], bit 0 of byte 3 contains the 33rd bit (i.e., OD10.2)
+ * and bit 7 of byte 0 contains the 64th bit (i.e., OD21.0)."
+ *
+ * The general-purpose (raw-bitstream) RX registers have the same layout
+ * although 'od' is renamed 'id' for 'input data'.
+ *
+ * SFF-8489 defines the behavior of the LEDs in response to the 'od' values.
+ */
+static u8 *to_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count, u8 *bit)
+{
+ unsigned int reg;
+ u8 byte;
+
+ /* gp registers start at index 1 */
+ if (index == 0)
+ return NULL;
+
+ index--; /* make index 0-based */
+ if (od < index * 32)
+ return NULL;
+
+ od -= index * 32;
+ reg = od >> 5;
+
+ if (reg >= count)
+ return NULL;
+
+ od &= (1 << 5) - 1;
+ byte = 3 - (od >> 3);
+ *bit = od & ((1 << 3) - 1);
+
+ return &data[reg * 4 + byte];
+}
+
+int try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count)
+{
+ u8 *byte;
+ u8 bit;
+
+ byte = to_sas_gpio_gp_bit(od, data, index, count, &bit);
+ if (!byte)
+ return -1;
+
+ return (*byte >> bit) & 1;
+}
+EXPORT_SYMBOL(try_test_sas_gpio_gp_bit);
+
+static int sas_host_smp_write_gpio(struct sas_ha_struct *sas_ha, u8 *resp_data,
+ u8 reg_type, u8 reg_index, u8 reg_count,
+ u8 *req_data)
+{
+ struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt);
+ int written;
+
+ if (i->dft->lldd_write_gpio == NULL) {
+ resp_data[2] = SMP_RESP_FUNC_UNK;
+ return 0;
+ }
+
+ written = i->dft->lldd_write_gpio(sas_ha, reg_type, reg_index,
+ reg_count, req_data);
+
+ if (written < 0) {
+ resp_data[2] = SMP_RESP_FUNC_FAILED;
+ written = 0;
+ } else
+ resp_data[2] = SMP_RESP_FUNC_ACC;
+
+ return written;
+}
+
static void sas_report_phy_sata(struct sas_ha_struct *sas_ha, u8 *resp_data,
u8 phy_id)
{
@@ -230,9 +315,23 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
/* Can't implement; hosts have no routes */
break;
- case SMP_WRITE_GPIO_REG:
- /* FIXME: need GPIO support in the transport class */
+ case SMP_WRITE_GPIO_REG: {
+ /* SFF-8485 v0.7 */
+ const int base_frame_size = 11;
+ int to_write = req_data[4];
+
+ if (blk_rq_bytes(req) < base_frame_size + to_write * 4 ||
+ req->resid_len < base_frame_size + to_write * 4) {
+ resp_data[2] = SMP_RESP_INV_FRM_LEN;
+ break;
+ }
+
+ to_write = sas_host_smp_write_gpio(sas_ha, resp_data, req_data[2],
+ req_data[3], to_write, &req_data[8]);
+ req->resid_len -= base_frame_size + to_write * 4;
+ rsp->resid_len -= 8;
break;
+ }
case SMP_CONF_ROUTE_INFO:
/* Can't implement; hosts have no routes */
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2dc55343f671..d81c3b1989f7 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -37,7 +37,32 @@
#include "../scsi_sas_internal.h"
-struct kmem_cache *sas_task_cache;
+static struct kmem_cache *sas_task_cache;
+
+struct sas_task *sas_alloc_task(gfp_t flags)
+{
+ struct sas_task *task = kmem_cache_zalloc(sas_task_cache, flags);
+
+ if (task) {
+ INIT_LIST_HEAD(&task->list);
+ spin_lock_init(&task->task_state_lock);
+ task->task_state_flags = SAS_TASK_STATE_PENDING;
+ init_timer(&task->timer);
+ init_completion(&task->completion);
+ }
+
+ return task;
+}
+EXPORT_SYMBOL_GPL(sas_alloc_task);
+
+void sas_free_task(struct sas_task *task)
+{
+ if (task) {
+ BUG_ON(!list_empty(&task->list));
+ kmem_cache_free(sas_task_cache, task);
+ }
+}
+EXPORT_SYMBOL_GPL(sas_free_task);
/*------------ SAS addr hash -----------*/
void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
@@ -152,10 +177,15 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
static int sas_get_linkerrors(struct sas_phy *phy)
{
- if (scsi_is_sas_phy_local(phy))
- /* FIXME: we have no local phy stats
- * gathering at this time */
- return -EINVAL;
+ if (scsi_is_sas_phy_local(phy)) {
+ struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+ struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
+ struct sas_internal *i =
+ to_sas_internal(sas_ha->core.shost->transportt);
+
+ return i->dft->lldd_control_phy(asd_phy, PHY_FUNC_GET_EVENTS, NULL);
+ }
return sas_smp_get_phy_events(phy);
}
@@ -293,8 +323,7 @@ EXPORT_SYMBOL_GPL(sas_domain_release_transport);
static int __init sas_class_init(void)
{
- sas_task_cache = kmem_cache_create("sas_task", sizeof(struct sas_task),
- 0, SLAB_HWCACHE_ALIGN, NULL);
+ sas_task_cache = KMEM_CACHE(sas_task, SLAB_HWCACHE_ALIGN);
if (!sas_task_cache)
return -ENOMEM;
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index eeba76cdf774..b2c4a7731656 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -182,79 +182,56 @@ int sas_queue_up(struct sas_task *task)
return 0;
}
-/**
- * sas_queuecommand -- Enqueue a command for processing
- * @parameters: See SCSI Core documentation
- *
- * Note: XXX: Remove the host unlock/lock pair when SCSI Core can
- * call us without holding an IRQ spinlock...
- */
-static int sas_queuecommand_lck(struct scsi_cmnd *cmd,
- void (*scsi_done)(struct scsi_cmnd *))
- __releases(host->host_lock)
- __acquires(dev->sata_dev.ap->lock)
- __releases(dev->sata_dev.ap->lock)
- __acquires(host->host_lock)
+int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
{
- int res = 0;
- struct domain_device *dev = cmd_to_domain_dev(cmd);
- struct Scsi_Host *host = cmd->device->host;
struct sas_internal *i = to_sas_internal(host->transportt);
+ struct domain_device *dev = cmd_to_domain_dev(cmd);
+ struct sas_ha_struct *sas_ha = dev->port->ha;
+ struct sas_task *task;
+ int res = 0;
- spin_unlock_irq(host->host_lock);
+ /* If the device fell off, no sense in issuing commands */
+ if (dev->gone) {
+ cmd->result = DID_BAD_TARGET << 16;
+ goto out_done;
+ }
- {
- struct sas_ha_struct *sas_ha = dev->port->ha;
- struct sas_task *task;
-
- /* If the device fell off, no sense in issuing commands */
- if (dev->gone) {
- cmd->result = DID_BAD_TARGET << 16;
- scsi_done(cmd);
- goto out;
- }
+ if (dev_is_sata(dev)) {
+ unsigned long flags;
- if (dev_is_sata(dev)) {
- unsigned long flags;
+ spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
+ res = ata_sas_queuecmd(cmd, dev->sata_dev.ap);
+ spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
+ return res;
+ }
- spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
- res = ata_sas_queuecmd(cmd, dev->sata_dev.ap);
- spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
- goto out;
- }
+ task = sas_create_task(cmd, dev, GFP_ATOMIC);
+ if (!task)
+ return SCSI_MLQUEUE_HOST_BUSY;
- res = -ENOMEM;
- task = sas_create_task(cmd, dev, GFP_ATOMIC);
- if (!task)
- goto out;
+ /* Queue up, Direct Mode or Task Collector Mode. */
+ if (sas_ha->lldd_max_execute_num < 2)
+ res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
+ else
+ res = sas_queue_up(task);
- cmd->scsi_done = scsi_done;
- /* Queue up, Direct Mode or Task Collector Mode. */
- if (sas_ha->lldd_max_execute_num < 2)
- res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
- else
- res = sas_queue_up(task);
+ if (res)
+ goto out_free_task;
+ return 0;
- /* Examine */
- if (res) {
- SAS_DPRINTK("lldd_execute_task returned: %d\n", res);
- ASSIGN_SAS_TASK(cmd, NULL);
- sas_free_task(task);
- if (res == -SAS_QUEUE_FULL) {
- cmd->result = DID_SOFT_ERROR << 16; /* retry */
- res = 0;
- scsi_done(cmd);
- }
- goto out;
- }
- }
-out:
- spin_lock_irq(host->host_lock);
- return res;
+out_free_task:
+ SAS_DPRINTK("lldd_execute_task returned: %d\n", res);
+ ASSIGN_SAS_TASK(cmd, NULL);
+ sas_free_task(task);
+ if (res == -SAS_QUEUE_FULL)
+ cmd->result = DID_SOFT_ERROR << 16; /* retry */
+ else
+ cmd->result = DID_ERROR << 16;
+out_done:
+ cmd->scsi_done(cmd);
+ return 0;
}
-DEF_SCSI_QCMD(sas_queuecommand)
-
static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
{
struct sas_task *task = TO_SAS_TASK(cmd);
@@ -784,8 +761,7 @@ int sas_target_alloc(struct scsi_target *starget)
return 0;
}
-#define SAS_DEF_QD 32
-#define SAS_MAX_QD 64
+#define SAS_DEF_QD 256
int sas_slave_configure(struct scsi_device *scsi_dev)
{
@@ -825,34 +801,41 @@ void sas_slave_destroy(struct scsi_device *scsi_dev)
struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
if (dev_is_sata(dev))
- dev->sata_dev.ap->link.device[0].class = ATA_DEV_NONE;
+ sas_to_ata_dev(dev)->class = ATA_DEV_NONE;
}
-int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth,
- int reason)
+int sas_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
{
- int res = min(new_depth, SAS_MAX_QD);
+ struct domain_device *dev = sdev_to_domain_dev(sdev);
- if (reason != SCSI_QDEPTH_DEFAULT)
+ if (dev_is_sata(dev))
+ return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth,
+ reason);
+
+ switch (reason) {
+ case SCSI_QDEPTH_DEFAULT:
+ case SCSI_QDEPTH_RAMP_UP:
+ if (!sdev->tagged_supported)
+ depth = 1;
+ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+ break;
+ case SCSI_QDEPTH_QFULL:
+ scsi_track_queue_full(sdev, depth);
+ break;
+ default:
return -EOPNOTSUPP;
-
- if (scsi_dev->tagged_supported)
- scsi_adjust_queue_depth(scsi_dev, scsi_get_tag_type(scsi_dev),
- res);
- else {
- struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
- sas_printk("device %llx LUN %x queue depth changed to 1\n",
- SAS_ADDR(dev->sas_addr),
- scsi_dev->lun);
- scsi_adjust_queue_depth(scsi_dev, 0, 1);
- res = 1;
}
- return res;
+ return depth;
}
int sas_change_queue_type(struct scsi_device *scsi_dev, int qt)
{
+ struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
+
+ if (dev_is_sata(dev))
+ return -EINVAL;
+
if (!scsi_dev->tagged_supported)
return 0;
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index c088a36d1f33..bb4c8e0584e2 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -846,8 +846,24 @@ struct lpfc_hba {
struct dentry *debug_hbqinfo;
struct dentry *debug_dumpHostSlim;
struct dentry *debug_dumpHBASlim;
- struct dentry *debug_dumpData; /* BlockGuard BPL*/
- struct dentry *debug_dumpDif; /* BlockGuard BPL*/
+ struct dentry *debug_dumpData; /* BlockGuard BPL */
+ struct dentry *debug_dumpDif; /* BlockGuard BPL */
+ struct dentry *debug_InjErrLBA; /* LBA to inject errors at */
+ struct dentry *debug_writeGuard; /* inject write guard_tag errors */
+ struct dentry *debug_writeApp; /* inject write app_tag errors */
+ struct dentry *debug_writeRef; /* inject write ref_tag errors */
+ struct dentry *debug_readApp; /* inject read app_tag errors */
+ struct dentry *debug_readRef; /* inject read ref_tag errors */
+
+ /* T10 DIF error injection */
+ uint32_t lpfc_injerr_wgrd_cnt;
+ uint32_t lpfc_injerr_wapp_cnt;
+ uint32_t lpfc_injerr_wref_cnt;
+ uint32_t lpfc_injerr_rapp_cnt;
+ uint32_t lpfc_injerr_rref_cnt;
+ sector_t lpfc_injerr_lba;
+#define LPFC_INJERR_LBA_OFF (sector_t)0xffffffffffffffff
+
struct dentry *debug_slow_ring_trc;
struct lpfc_debugfs_trc *slow_ring_trc;
atomic_t slow_ring_trc_cnt;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 2542f1f8bf86..4b0333ee2d94 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -52,6 +52,13 @@
#define LPFC_MIN_DEVLOSS_TMO 1
#define LPFC_MAX_DEVLOSS_TMO 255
+/*
+ * Write key size should be multiple of 4. If write key is changed
+ * make sure that library write key is also changed.
+ */
+#define LPFC_REG_WRITE_KEY_SIZE 4
+#define LPFC_REG_WRITE_KEY "EMLX"
+
/**
* lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules
* @incr: integer to convert.
@@ -693,7 +700,7 @@ lpfc_selective_reset(struct lpfc_hba *phba)
int rc;
if (!phba->cfg_enable_hba_reset)
- return -EIO;
+ return -EACCES;
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
@@ -742,9 +749,11 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
-
int status = -EINVAL;
+ if (!phba->cfg_enable_hba_reset)
+ return -EACCES;
+
if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
status = phba->lpfc_selective_reset(phba);
@@ -765,16 +774,21 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
* Returns:
* zero for success
**/
-static int
+int
lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba)
{
- struct lpfc_register portstat_reg;
+ struct lpfc_register portstat_reg = {0};
int i;
-
+ msleep(100);
lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
&portstat_reg.word0);
+ /* verify if privilaged for the request operation */
+ if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) &&
+ !bf_get(lpfc_sliport_status_err, &portstat_reg))
+ return -EPERM;
+
/* wait for the SLI port firmware ready after firmware reset */
for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
msleep(10);
@@ -816,16 +830,13 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
int rc;
if (!phba->cfg_enable_hba_reset)
- return -EIO;
+ return -EACCES;
if ((phba->sli_rev < LPFC_SLI_REV4) ||
(bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
LPFC_SLI_INTF_IF_TYPE_2))
return -EPERM;
- if (!pdev->is_physfn)
- return -EPERM;
-
/* Disable SR-IOV virtual functions if enabled */
if (phba->cfg_sriov_nr_virtfn) {
pci_disable_sriov(pdev);
@@ -858,7 +869,7 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
rc = lpfc_sli4_pdev_status_reg_wait(phba);
if (rc)
- return -EIO;
+ return rc;
init_completion(&online_compl);
rc = lpfc_workq_post_event(phba, &status, &online_compl,
@@ -984,7 +995,7 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
if (!status)
return strlen(buf);
else
- return -EIO;
+ return status;
}
/**
@@ -3885,18 +3896,23 @@ sysfs_ctlreg_write(struct file *filp, struct kobject *kobj,
if ((off + count) > FF_REG_AREA_SIZE)
return -ERANGE;
- if (count == 0) return 0;
+ if (count <= LPFC_REG_WRITE_KEY_SIZE)
+ return 0;
if (off % 4 || count % 4 || (unsigned long)buf % 4)
return -EINVAL;
- if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
+ /* This is to protect HBA registers from accidental writes. */
+ if (memcmp(buf, LPFC_REG_WRITE_KEY, LPFC_REG_WRITE_KEY_SIZE))
+ return -EINVAL;
+
+ if (!(vport->fc_flag & FC_OFFLINE_MODE))
return -EPERM;
- }
spin_lock_irq(&phba->hbalock);
- for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t))
- writel(*((uint32_t *)(buf + buf_off)),
+ for (buf_off = 0; buf_off < count - LPFC_REG_WRITE_KEY_SIZE;
+ buf_off += sizeof(uint32_t))
+ writel(*((uint32_t *)(buf + buf_off + LPFC_REG_WRITE_KEY_SIZE)),
phba->ctrl_regs_memmap_p + off + buf_off);
spin_unlock_irq(&phba->hbalock);
@@ -4097,8 +4113,10 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj,
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
- int rc;
+ LPFC_MBOXQ_t *mboxq;
MAILBOX_t *pmb;
+ uint32_t mbox_tmo;
+ int rc;
if (off > MAILBOX_CMD_SIZE)
return -ERANGE;
@@ -4123,7 +4141,8 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj,
if (off == 0 &&
phba->sysfs_mbox.state == SMBOX_WRITING &&
phba->sysfs_mbox.offset >= 2 * sizeof(uint32_t)) {
- pmb = &phba->sysfs_mbox.mbox->u.mb;
+ mboxq = (LPFC_MBOXQ_t *)&phba->sysfs_mbox.mbox;
+ pmb = &mboxq->u.mb;
switch (pmb->mbxCommand) {
/* Offline only */
case MBX_INIT_LINK:
@@ -4233,9 +4252,8 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj,
} else {
spin_unlock_irq(&phba->hbalock);
- rc = lpfc_sli_issue_mbox_wait (phba,
- phba->sysfs_mbox.mbox,
- lpfc_mbox_tmo_val(phba, pmb->mbxCommand) * HZ);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
+ rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
spin_lock_irq(&phba->hbalock);
}
@@ -4480,9 +4498,10 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
spin_lock_irq(shost->host_lock);
- if ((vport->fc_flag & FC_FABRIC) ||
- ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
- (vport->fc_flag & FC_PUBLIC_LOOP)))
+ if ((vport->port_state > LPFC_FLOGI) &&
+ ((vport->fc_flag & FC_FABRIC) ||
+ ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
+ (vport->fc_flag & FC_PUBLIC_LOOP))))
node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
else
/* fabric is local port if there is no F/FL_Port */
@@ -4555,9 +4574,17 @@ lpfc_get_stats(struct Scsi_Host *shost)
memset(hs, 0, sizeof (struct fc_host_statistics));
hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt;
- hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256);
+ /*
+ * The MBX_READ_STATUS returns tx_k_bytes which has to
+ * converted to words
+ */
+ hs->tx_words = (uint64_t)
+ ((uint64_t)pmb->un.varRdStatus.xmitByteCnt
+ * (uint64_t)256);
hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt;
- hs->rx_words = (pmb->un.varRdStatus.rcvByteCnt * 256);
+ hs->rx_words = (uint64_t)
+ ((uint64_t)pmb->un.varRdStatus.rcvByteCnt
+ * (uint64_t)256);
memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
pmb->mbxCommand = MBX_READ_LNK_STAT;
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index a6db6aef1331..60f95347babf 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -209,7 +209,7 @@ void __lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_mbox_cmd_check(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_mbox_dev_check(struct lpfc_hba *);
-int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
+int lpfc_mbox_tmo_val(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_init_vfi(struct lpfcMboxq *, struct lpfc_vport *);
void lpfc_reg_vfi(struct lpfcMboxq *, struct lpfc_vport *, dma_addr_t);
void lpfc_init_vpi(struct lpfc_hba *, struct lpfcMboxq *, uint16_t);
@@ -451,3 +451,5 @@ int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *);
/* functions to support SR-IOV */
int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int);
uint16_t lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *);
+int lpfc_sli4_queue_create(struct lpfc_hba *);
+void lpfc_sli4_queue_destroy(struct lpfc_hba *);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 779b88e1469d..707081d0a226 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1856,6 +1856,9 @@ lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
case 2:
c = 'B';
break;
+ case 3:
+ c = 'X';
+ break;
default:
c = 0;
break;
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index a0424dd90e40..2cd844f7058f 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -996,6 +996,85 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf,
return nbytes;
}
+static int
+lpfc_debugfs_dif_err_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t
+lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct dentry *dent = file->f_dentry;
+ struct lpfc_hba *phba = file->private_data;
+ char cbuf[16];
+ int cnt = 0;
+
+ if (dent == phba->debug_writeGuard)
+ cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wgrd_cnt);
+ else if (dent == phba->debug_writeApp)
+ cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wapp_cnt);
+ else if (dent == phba->debug_writeRef)
+ cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wref_cnt);
+ else if (dent == phba->debug_readApp)
+ cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_rapp_cnt);
+ else if (dent == phba->debug_readRef)
+ cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_rref_cnt);
+ else if (dent == phba->debug_InjErrLBA)
+ cnt = snprintf(cbuf, 16, "0x%lx\n",
+ (unsigned long) phba->lpfc_injerr_lba);
+ else
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0547 Unknown debugfs error injection entry\n");
+
+ return simple_read_from_buffer(buf, nbytes, ppos, &cbuf, cnt);
+}
+
+static ssize_t
+lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct dentry *dent = file->f_dentry;
+ struct lpfc_hba *phba = file->private_data;
+ char dstbuf[32];
+ unsigned long tmp;
+ int size;
+
+ memset(dstbuf, 0, 32);
+ size = (nbytes < 32) ? nbytes : 32;
+ if (copy_from_user(dstbuf, buf, size))
+ return 0;
+
+ if (strict_strtoul(dstbuf, 0, &tmp))
+ return 0;
+
+ if (dent == phba->debug_writeGuard)
+ phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
+ else if (dent == phba->debug_writeApp)
+ phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp;
+ else if (dent == phba->debug_writeRef)
+ phba->lpfc_injerr_wref_cnt = (uint32_t)tmp;
+ else if (dent == phba->debug_readApp)
+ phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp;
+ else if (dent == phba->debug_readRef)
+ phba->lpfc_injerr_rref_cnt = (uint32_t)tmp;
+ else if (dent == phba->debug_InjErrLBA)
+ phba->lpfc_injerr_lba = (sector_t)tmp;
+ else
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0548 Unknown debugfs error injection entry\n");
+
+ return nbytes;
+}
+
+static int
+lpfc_debugfs_dif_err_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
/**
* lpfc_debugfs_nodelist_open - Open the nodelist debugfs file
* @inode: The inode pointer that contains a vport pointer.
@@ -3380,6 +3459,16 @@ static const struct file_operations lpfc_debugfs_op_dumpDif = {
.release = lpfc_debugfs_dumpDataDif_release,
};
+#undef lpfc_debugfs_op_dif_err
+static const struct file_operations lpfc_debugfs_op_dif_err = {
+ .owner = THIS_MODULE,
+ .open = lpfc_debugfs_dif_err_open,
+ .llseek = lpfc_debugfs_lseek,
+ .read = lpfc_debugfs_dif_err_read,
+ .write = lpfc_debugfs_dif_err_write,
+ .release = lpfc_debugfs_dif_err_release,
+};
+
#undef lpfc_debugfs_op_slow_ring_trc
static const struct file_operations lpfc_debugfs_op_slow_ring_trc = {
.owner = THIS_MODULE,
@@ -3788,6 +3877,74 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
goto debug_failed;
}
+ /* Setup DIF Error Injections */
+ snprintf(name, sizeof(name), "InjErrLBA");
+ phba->debug_InjErrLBA =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_InjErrLBA) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0807 Cannot create debugfs InjErrLBA\n");
+ goto debug_failed;
+ }
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+
+ snprintf(name, sizeof(name), "writeGuardInjErr");
+ phba->debug_writeGuard =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_writeGuard) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0802 Cannot create debugfs writeGuard\n");
+ goto debug_failed;
+ }
+
+ snprintf(name, sizeof(name), "writeAppInjErr");
+ phba->debug_writeApp =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_writeApp) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0803 Cannot create debugfs writeApp\n");
+ goto debug_failed;
+ }
+
+ snprintf(name, sizeof(name), "writeRefInjErr");
+ phba->debug_writeRef =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_writeRef) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0804 Cannot create debugfs writeRef\n");
+ goto debug_failed;
+ }
+
+ snprintf(name, sizeof(name), "readAppInjErr");
+ phba->debug_readApp =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_readApp) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0805 Cannot create debugfs readApp\n");
+ goto debug_failed;
+ }
+
+ snprintf(name, sizeof(name), "readRefInjErr");
+ phba->debug_readRef =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dif_err);
+ if (!phba->debug_readRef) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0806 Cannot create debugfs readApp\n");
+ goto debug_failed;
+ }
+
/* Setup slow ring trace */
if (lpfc_debugfs_max_slow_ring_trc) {
num = lpfc_debugfs_max_slow_ring_trc - 1;
@@ -4090,6 +4247,30 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
debugfs_remove(phba->debug_dumpDif); /* dumpDif */
phba->debug_dumpDif = NULL;
}
+ if (phba->debug_InjErrLBA) {
+ debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */
+ phba->debug_InjErrLBA = NULL;
+ }
+ if (phba->debug_writeGuard) {
+ debugfs_remove(phba->debug_writeGuard); /* writeGuard */
+ phba->debug_writeGuard = NULL;
+ }
+ if (phba->debug_writeApp) {
+ debugfs_remove(phba->debug_writeApp); /* writeApp */
+ phba->debug_writeApp = NULL;
+ }
+ if (phba->debug_writeRef) {
+ debugfs_remove(phba->debug_writeRef); /* writeRef */
+ phba->debug_writeRef = NULL;
+ }
+ if (phba->debug_readApp) {
+ debugfs_remove(phba->debug_readApp); /* readApp */
+ phba->debug_readApp = NULL;
+ }
+ if (phba->debug_readRef) {
+ debugfs_remove(phba->debug_readRef); /* readRef */
+ phba->debug_readRef = NULL;
+ }
if (phba->slow_ring_trc) {
kfree(phba->slow_ring_trc);
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 023da0e00d38..445826a4c981 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3386,7 +3386,14 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
cmdiocb->context1 = NULL;
}
}
+
+ /*
+ * The driver received a LOGO from the rport and has ACK'd it.
+ * At this point, the driver is done so release the IOCB and
+ * remove the ndlp reference.
+ */
lpfc_els_free_iocb(phba, cmdiocb);
+ lpfc_nlp_put(ndlp);
return;
}
@@ -4082,9 +4089,6 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
phba->fc_stat.elsXmitACC++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
- lpfc_nlp_put(ndlp);
- elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
- * it could be freed */
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
@@ -4166,6 +4170,11 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
psli = &phba->sli;
cmdsize = oldiocb->iocb.unsli3.rcvsli3.acc_len;
+ /* The accumulated length can exceed the BPL_SIZE. For
+ * now, use this as the limit
+ */
+ if (cmdsize > LPFC_BPL_SIZE)
+ cmdsize = LPFC_BPL_SIZE;
elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
ndlp->nlp_DID, ELS_CMD_ACC);
if (!elsiocb)
@@ -4189,9 +4198,6 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
phba->fc_stat.elsXmitACC++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
- lpfc_nlp_put(ndlp);
- elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
- * it could be freed */
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
@@ -7258,16 +7264,11 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
icmd->un.elsreq64.myID = 0;
icmd->un.elsreq64.fl = 1;
- if ((phba->sli_rev == LPFC_SLI_REV4) &&
- (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
- LPFC_SLI_INTF_IF_TYPE_0)) {
- /* FDISC needs to be 1 for WQE VPI */
- elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1;
- elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ;
- /* Set the ulpContext to the vpi */
- elsiocb->iocb.ulpContext = phba->vpi_ids[vport->vpi];
- } else {
- /* For FDISC, Let FDISC rsp set the NPortID for this VPI */
+ /*
+ * SLI3 ports require a different context type value than SLI4.
+ * Catch SLI3 ports here and override the prep.
+ */
+ if (phba->sli_rev == LPFC_SLI_REV3) {
icmd->ulpCt_h = 1;
icmd->ulpCt_l = 0;
}
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 0b47adf9fee8..091f68e5cb70 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1412,7 +1412,7 @@ lpfc_register_fcf(struct lpfc_hba *phba)
if (phba->pport->port_state != LPFC_FLOGI) {
phba->hba_flag |= FCF_RR_INPROG;
spin_unlock_irq(&phba->hbalock);
- lpfc_issue_init_vfi(phba->pport);
+ lpfc_initial_flogi(phba->pport);
return;
}
spin_unlock_irq(&phba->hbalock);
@@ -2646,7 +2646,9 @@ lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
{
struct lpfc_vport *vport = mboxq->vport;
- if (mboxq->u.mb.mbxStatus && (mboxq->u.mb.mbxStatus != 0x4002)) {
+ /* VFI not supported on interface type 0, just do the flogi */
+ if (mboxq->u.mb.mbxStatus && (bf_get(lpfc_sli_intf_if_type,
+ &phba->sli4_hba.sli_intf) != LPFC_SLI_INTF_IF_TYPE_0)) {
lpfc_printf_vlog(vport, KERN_ERR,
LOG_MBOX,
"2891 Init VFI mailbox failed 0x%x\n",
@@ -2655,6 +2657,7 @@ lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
return;
}
+
lpfc_initial_flogi(vport);
mempool_free(mboxq, phba->mbox_mem_pool);
return;
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 7f8003b5181e..98d21521f539 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -41,6 +41,8 @@
* Or clear that bit field:
* bf_set(example_bit_field, &t1, 0);
*/
+#define bf_get_be32(name, ptr) \
+ ((be32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK)
#define bf_get_le32(name, ptr) \
((le32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK)
#define bf_get(name, ptr) \
@@ -678,7 +680,6 @@ struct lpfc_register {
#define lpfc_rq_doorbell_num_posted_SHIFT 16
#define lpfc_rq_doorbell_num_posted_MASK 0x3FFF
#define lpfc_rq_doorbell_num_posted_WORD word0
-#define LPFC_RQ_POST_BATCH 8 /* RQEs to post at one time */
#define lpfc_rq_doorbell_id_SHIFT 0
#define lpfc_rq_doorbell_id_MASK 0xFFFF
#define lpfc_rq_doorbell_id_WORD word0
@@ -784,6 +785,8 @@ union lpfc_sli4_cfg_shdr {
#define LPFC_Q_CREATE_VERSION_2 2
#define LPFC_Q_CREATE_VERSION_1 1
#define LPFC_Q_CREATE_VERSION_0 0
+#define LPFC_OPCODE_VERSION_0 0
+#define LPFC_OPCODE_VERSION_1 1
} request;
struct {
uint32_t word6;
@@ -825,6 +828,7 @@ struct mbox_header {
#define LPFC_EXTENT_VERSION_DEFAULT 0
/* Subsystem Definitions */
+#define LPFC_MBOX_SUBSYSTEM_NA 0x0
#define LPFC_MBOX_SUBSYSTEM_COMMON 0x1
#define LPFC_MBOX_SUBSYSTEM_FCOE 0xC
@@ -835,25 +839,34 @@ struct mbox_header {
#define HOST_ENDIAN_HIGH_WORD1 0xFF7856FF
/* Common Opcodes */
-#define LPFC_MBOX_OPCODE_CQ_CREATE 0x0C
-#define LPFC_MBOX_OPCODE_EQ_CREATE 0x0D
-#define LPFC_MBOX_OPCODE_MQ_CREATE 0x15
-#define LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES 0x20
-#define LPFC_MBOX_OPCODE_NOP 0x21
-#define LPFC_MBOX_OPCODE_MQ_DESTROY 0x35
-#define LPFC_MBOX_OPCODE_CQ_DESTROY 0x36
-#define LPFC_MBOX_OPCODE_EQ_DESTROY 0x37
-#define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A
-#define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D
-#define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A
-#define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO 0x9A
-#define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT 0x9B
-#define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT 0x9C
-#define LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT 0x9D
-#define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG 0xA0
-#define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG 0xA4
-#define LPFC_MBOX_OPCODE_WRITE_OBJECT 0xAC
-#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5
+#define LPFC_MBOX_OPCODE_NA 0x00
+#define LPFC_MBOX_OPCODE_CQ_CREATE 0x0C
+#define LPFC_MBOX_OPCODE_EQ_CREATE 0x0D
+#define LPFC_MBOX_OPCODE_MQ_CREATE 0x15
+#define LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES 0x20
+#define LPFC_MBOX_OPCODE_NOP 0x21
+#define LPFC_MBOX_OPCODE_MQ_DESTROY 0x35
+#define LPFC_MBOX_OPCODE_CQ_DESTROY 0x36
+#define LPFC_MBOX_OPCODE_EQ_DESTROY 0x37
+#define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A
+#define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D
+#define LPFC_MBOX_OPCODE_GET_PORT_NAME 0x4D
+#define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A
+#define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO 0x9A
+#define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT 0x9B
+#define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT 0x9C
+#define LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT 0x9D
+#define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG 0xA0
+#define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG 0xA4
+#define LPFC_MBOX_OPCODE_SET_PROFILE_CONFIG 0xA5
+#define LPFC_MBOX_OPCODE_GET_PROFILE_LIST 0xA6
+#define LPFC_MBOX_OPCODE_SET_ACT_PROFILE 0xA8
+#define LPFC_MBOX_OPCODE_GET_FACTORY_PROFILE_CONFIG 0xA9
+#define LPFC_MBOX_OPCODE_READ_OBJECT 0xAB
+#define LPFC_MBOX_OPCODE_WRITE_OBJECT 0xAC
+#define LPFC_MBOX_OPCODE_READ_OBJECT_LIST 0xAD
+#define LPFC_MBOX_OPCODE_DELETE_OBJECT 0xAE
+#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5
/* FCoE Opcodes */
#define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE 0x01
@@ -867,6 +880,7 @@ struct mbox_header {
#define LPFC_MBOX_OPCODE_FCOE_DELETE_FCF 0x0A
#define LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE 0x0B
#define LPFC_MBOX_OPCODE_FCOE_REDISCOVER_FCF 0x10
+#define LPFC_MBOX_OPCODE_FCOE_SET_FCLINK_SETTINGS 0x21
#define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE 0x22
#define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK 0x23
@@ -1470,16 +1484,81 @@ struct sli4_sge { /* SLI-4 */
uint32_t addr_lo;
uint32_t word2;
-#define lpfc_sli4_sge_offset_SHIFT 0 /* Offset of buffer - Not used*/
-#define lpfc_sli4_sge_offset_MASK 0x1FFFFFFF
+#define lpfc_sli4_sge_offset_SHIFT 0
+#define lpfc_sli4_sge_offset_MASK 0x07FFFFFF
#define lpfc_sli4_sge_offset_WORD word2
-#define lpfc_sli4_sge_last_SHIFT 31 /* Last SEG in the SGL sets
- this flag !! */
+#define lpfc_sli4_sge_type_SHIFT 27
+#define lpfc_sli4_sge_type_MASK 0x0000000F
+#define lpfc_sli4_sge_type_WORD word2
+#define LPFC_SGE_TYPE_DATA 0x0
+#define LPFC_SGE_TYPE_DIF 0x4
+#define LPFC_SGE_TYPE_LSP 0x5
+#define LPFC_SGE_TYPE_PEDIF 0x6
+#define LPFC_SGE_TYPE_PESEED 0x7
+#define LPFC_SGE_TYPE_DISEED 0x8
+#define LPFC_SGE_TYPE_ENC 0x9
+#define LPFC_SGE_TYPE_ATM 0xA
+#define LPFC_SGE_TYPE_SKIP 0xC
+#define lpfc_sli4_sge_last_SHIFT 31 /* Last SEG in the SGL sets it */
#define lpfc_sli4_sge_last_MASK 0x00000001
#define lpfc_sli4_sge_last_WORD word2
uint32_t sge_len;
};
+struct sli4_sge_diseed { /* SLI-4 */
+ uint32_t ref_tag;
+ uint32_t ref_tag_tran;
+
+ uint32_t word2;
+#define lpfc_sli4_sge_dif_apptran_SHIFT 0
+#define lpfc_sli4_sge_dif_apptran_MASK 0x0000FFFF
+#define lpfc_sli4_sge_dif_apptran_WORD word2
+#define lpfc_sli4_sge_dif_af_SHIFT 24
+#define lpfc_sli4_sge_dif_af_MASK 0x00000001
+#define lpfc_sli4_sge_dif_af_WORD word2
+#define lpfc_sli4_sge_dif_na_SHIFT 25
+#define lpfc_sli4_sge_dif_na_MASK 0x00000001
+#define lpfc_sli4_sge_dif_na_WORD word2
+#define lpfc_sli4_sge_dif_hi_SHIFT 26
+#define lpfc_sli4_sge_dif_hi_MASK 0x00000001
+#define lpfc_sli4_sge_dif_hi_WORD word2
+#define lpfc_sli4_sge_dif_type_SHIFT 27
+#define lpfc_sli4_sge_dif_type_MASK 0x0000000F
+#define lpfc_sli4_sge_dif_type_WORD word2
+#define lpfc_sli4_sge_dif_last_SHIFT 31 /* Last SEG in the SGL sets it */
+#define lpfc_sli4_sge_dif_last_MASK 0x00000001
+#define lpfc_sli4_sge_dif_last_WORD word2
+ uint32_t word3;
+#define lpfc_sli4_sge_dif_apptag_SHIFT 0
+#define lpfc_sli4_sge_dif_apptag_MASK 0x0000FFFF
+#define lpfc_sli4_sge_dif_apptag_WORD word3
+#define lpfc_sli4_sge_dif_bs_SHIFT 16
+#define lpfc_sli4_sge_dif_bs_MASK 0x00000007
+#define lpfc_sli4_sge_dif_bs_WORD word3
+#define lpfc_sli4_sge_dif_ai_SHIFT 19
+#define lpfc_sli4_sge_dif_ai_MASK 0x00000001
+#define lpfc_sli4_sge_dif_ai_WORD word3
+#define lpfc_sli4_sge_dif_me_SHIFT 20
+#define lpfc_sli4_sge_dif_me_MASK 0x00000001
+#define lpfc_sli4_sge_dif_me_WORD word3
+#define lpfc_sli4_sge_dif_re_SHIFT 21
+#define lpfc_sli4_sge_dif_re_MASK 0x00000001
+#define lpfc_sli4_sge_dif_re_WORD word3
+#define lpfc_sli4_sge_dif_ce_SHIFT 22
+#define lpfc_sli4_sge_dif_ce_MASK 0x00000001
+#define lpfc_sli4_sge_dif_ce_WORD word3
+#define lpfc_sli4_sge_dif_nr_SHIFT 23
+#define lpfc_sli4_sge_dif_nr_MASK 0x00000001
+#define lpfc_sli4_sge_dif_nr_WORD word3
+#define lpfc_sli4_sge_dif_oprx_SHIFT 24
+#define lpfc_sli4_sge_dif_oprx_MASK 0x0000000F
+#define lpfc_sli4_sge_dif_oprx_WORD word3
+#define lpfc_sli4_sge_dif_optx_SHIFT 28
+#define lpfc_sli4_sge_dif_optx_MASK 0x0000000F
+#define lpfc_sli4_sge_dif_optx_WORD word3
+/* optx and oprx use BG_OP_IN defines in lpfc_hw.h */
+};
+
struct fcf_record {
uint32_t max_rcv_size;
uint32_t fka_adv_period;
@@ -2019,6 +2098,15 @@ struct lpfc_mbx_read_config {
#define lpfc_mbx_rd_conf_extnts_inuse_MASK 0x00000001
#define lpfc_mbx_rd_conf_extnts_inuse_WORD word1
uint32_t word2;
+#define lpfc_mbx_rd_conf_lnk_numb_SHIFT 0
+#define lpfc_mbx_rd_conf_lnk_numb_MASK 0x0000003F
+#define lpfc_mbx_rd_conf_lnk_numb_WORD word2
+#define lpfc_mbx_rd_conf_lnk_type_SHIFT 6
+#define lpfc_mbx_rd_conf_lnk_type_MASK 0x00000003
+#define lpfc_mbx_rd_conf_lnk_type_WORD word2
+#define lpfc_mbx_rd_conf_lnk_ldv_SHIFT 8
+#define lpfc_mbx_rd_conf_lnk_ldv_MASK 0x00000001
+#define lpfc_mbx_rd_conf_lnk_ldv_WORD word2
#define lpfc_mbx_rd_conf_topology_SHIFT 24
#define lpfc_mbx_rd_conf_topology_MASK 0x000000FF
#define lpfc_mbx_rd_conf_topology_WORD word2
@@ -2552,8 +2640,152 @@ struct lpfc_mbx_get_prof_cfg {
} u;
};
+struct lpfc_controller_attribute {
+ uint32_t version_string[8];
+ uint32_t manufacturer_name[8];
+ uint32_t supported_modes;
+ uint32_t word17;
+#define lpfc_cntl_attr_eprom_ver_lo_SHIFT 0
+#define lpfc_cntl_attr_eprom_ver_lo_MASK 0x000000ff
+#define lpfc_cntl_attr_eprom_ver_lo_WORD word17
+#define lpfc_cntl_attr_eprom_ver_hi_SHIFT 8
+#define lpfc_cntl_attr_eprom_ver_hi_MASK 0x000000ff
+#define lpfc_cntl_attr_eprom_ver_hi_WORD word17
+ uint32_t mbx_da_struct_ver;
+ uint32_t ep_fw_da_struct_ver;
+ uint32_t ncsi_ver_str[3];
+ uint32_t dflt_ext_timeout;
+ uint32_t model_number[8];
+ uint32_t description[16];
+ uint32_t serial_number[8];
+ uint32_t ip_ver_str[8];
+ uint32_t fw_ver_str[8];
+ uint32_t bios_ver_str[8];
+ uint32_t redboot_ver_str[8];
+ uint32_t driver_ver_str[8];
+ uint32_t flash_fw_ver_str[8];
+ uint32_t functionality;
+ uint32_t word105;
+#define lpfc_cntl_attr_max_cbd_len_SHIFT 0
+#define lpfc_cntl_attr_max_cbd_len_MASK 0x0000ffff
+#define lpfc_cntl_attr_max_cbd_len_WORD word105
+#define lpfc_cntl_attr_asic_rev_SHIFT 16
+#define lpfc_cntl_attr_asic_rev_MASK 0x000000ff
+#define lpfc_cntl_attr_asic_rev_WORD word105
+#define lpfc_cntl_attr_gen_guid0_SHIFT 24
+#define lpfc_cntl_attr_gen_guid0_MASK 0x000000ff
+#define lpfc_cntl_attr_gen_guid0_WORD word105
+ uint32_t gen_guid1_12[3];
+ uint32_t word109;
+#define lpfc_cntl_attr_gen_guid13_14_SHIFT 0
+#define lpfc_cntl_attr_gen_guid13_14_MASK 0x0000ffff
+#define lpfc_cntl_attr_gen_guid13_14_WORD word109
+#define lpfc_cntl_attr_gen_guid15_SHIFT 16
+#define lpfc_cntl_attr_gen_guid15_MASK 0x000000ff
+#define lpfc_cntl_attr_gen_guid15_WORD word109
+#define lpfc_cntl_attr_hba_port_cnt_SHIFT 24
+#define lpfc_cntl_attr_hba_port_cnt_MASK 0x000000ff
+#define lpfc_cntl_attr_hba_port_cnt_WORD word109
+ uint32_t word110;
+#define lpfc_cntl_attr_dflt_lnk_tmo_SHIFT 0
+#define lpfc_cntl_attr_dflt_lnk_tmo_MASK 0x0000ffff
+#define lpfc_cntl_attr_dflt_lnk_tmo_WORD word110
+#define lpfc_cntl_attr_multi_func_dev_SHIFT 24
+#define lpfc_cntl_attr_multi_func_dev_MASK 0x000000ff
+#define lpfc_cntl_attr_multi_func_dev_WORD word110
+ uint32_t word111;
+#define lpfc_cntl_attr_cache_valid_SHIFT 0
+#define lpfc_cntl_attr_cache_valid_MASK 0x000000ff
+#define lpfc_cntl_attr_cache_valid_WORD word111
+#define lpfc_cntl_attr_hba_status_SHIFT 8
+#define lpfc_cntl_attr_hba_status_MASK 0x000000ff
+#define lpfc_cntl_attr_hba_status_WORD word111
+#define lpfc_cntl_attr_max_domain_SHIFT 16
+#define lpfc_cntl_attr_max_domain_MASK 0x000000ff
+#define lpfc_cntl_attr_max_domain_WORD word111
+#define lpfc_cntl_attr_lnk_numb_SHIFT 24
+#define lpfc_cntl_attr_lnk_numb_MASK 0x0000003f
+#define lpfc_cntl_attr_lnk_numb_WORD word111
+#define lpfc_cntl_attr_lnk_type_SHIFT 30
+#define lpfc_cntl_attr_lnk_type_MASK 0x00000003
+#define lpfc_cntl_attr_lnk_type_WORD word111
+ uint32_t fw_post_status;
+ uint32_t hba_mtu[8];
+ uint32_t word121;
+ uint32_t reserved1[3];
+ uint32_t word125;
+#define lpfc_cntl_attr_pci_vendor_id_SHIFT 0
+#define lpfc_cntl_attr_pci_vendor_id_MASK 0x0000ffff
+#define lpfc_cntl_attr_pci_vendor_id_WORD word125
+#define lpfc_cntl_attr_pci_device_id_SHIFT 16
+#define lpfc_cntl_attr_pci_device_id_MASK 0x0000ffff
+#define lpfc_cntl_attr_pci_device_id_WORD word125
+ uint32_t word126;
+#define lpfc_cntl_attr_pci_subvdr_id_SHIFT 0
+#define lpfc_cntl_attr_pci_subvdr_id_MASK 0x0000ffff
+#define lpfc_cntl_attr_pci_subvdr_id_WORD word126
+#define lpfc_cntl_attr_pci_subsys_id_SHIFT 16
+#define lpfc_cntl_attr_pci_subsys_id_MASK 0x0000ffff
+#define lpfc_cntl_attr_pci_subsys_id_WORD word126
+ uint32_t word127;
+#define lpfc_cntl_attr_pci_bus_num_SHIFT 0
+#define lpfc_cntl_attr_pci_bus_num_MASK 0x000000ff
+#define lpfc_cntl_attr_pci_bus_num_WORD word127
+#define lpfc_cntl_attr_pci_dev_num_SHIFT 8
+#define lpfc_cntl_attr_pci_dev_num_MASK 0x000000ff
+#define lpfc_cntl_attr_pci_dev_num_WORD word127
+#define lpfc_cntl_attr_pci_fnc_num_SHIFT 16
+#define lpfc_cntl_attr_pci_fnc_num_MASK 0x000000ff
+#define lpfc_cntl_attr_pci_fnc_num_WORD word127
+#define lpfc_cntl_attr_inf_type_SHIFT 24
+#define lpfc_cntl_attr_inf_type_MASK 0x000000ff
+#define lpfc_cntl_attr_inf_type_WORD word127
+ uint32_t unique_id[2];
+ uint32_t word130;
+#define lpfc_cntl_attr_num_netfil_SHIFT 0
+#define lpfc_cntl_attr_num_netfil_MASK 0x000000ff
+#define lpfc_cntl_attr_num_netfil_WORD word130
+ uint32_t reserved2[4];
+};
+
+struct lpfc_mbx_get_cntl_attributes {
+ union lpfc_sli4_cfg_shdr cfg_shdr;
+ struct lpfc_controller_attribute cntl_attr;
+};
+
+struct lpfc_mbx_get_port_name {
+ struct mbox_header header;
+ union {
+ struct {
+ uint32_t word4;
+#define lpfc_mbx_get_port_name_lnk_type_SHIFT 0
+#define lpfc_mbx_get_port_name_lnk_type_MASK 0x00000003
+#define lpfc_mbx_get_port_name_lnk_type_WORD word4
+ } request;
+ struct {
+ uint32_t word4;
+#define lpfc_mbx_get_port_name_name0_SHIFT 0
+#define lpfc_mbx_get_port_name_name0_MASK 0x000000FF
+#define lpfc_mbx_get_port_name_name0_WORD word4
+#define lpfc_mbx_get_port_name_name1_SHIFT 8
+#define lpfc_mbx_get_port_name_name1_MASK 0x000000FF
+#define lpfc_mbx_get_port_name_name1_WORD word4
+#define lpfc_mbx_get_port_name_name2_SHIFT 16
+#define lpfc_mbx_get_port_name_name2_MASK 0x000000FF
+#define lpfc_mbx_get_port_name_name2_WORD word4
+#define lpfc_mbx_get_port_name_name3_SHIFT 24
+#define lpfc_mbx_get_port_name_name3_MASK 0x000000FF
+#define lpfc_mbx_get_port_name_name3_WORD word4
+#define LPFC_LINK_NUMBER_0 0
+#define LPFC_LINK_NUMBER_1 1
+#define LPFC_LINK_NUMBER_2 2
+#define LPFC_LINK_NUMBER_3 3
+ } response;
+ } u;
+};
+
/* Mailbox Completion Queue Error Messages */
-#define MB_CQE_STATUS_SUCCESS 0x0
+#define MB_CQE_STATUS_SUCCESS 0x0
#define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1
#define MB_CQE_STATUS_INVALID_PARAMETER 0x2
#define MB_CQE_STATUS_INSUFFICIENT_RESOURCES 0x3
@@ -2637,8 +2869,9 @@ struct lpfc_mqe {
struct lpfc_mbx_run_link_diag_test link_diag_test;
struct lpfc_mbx_get_func_cfg get_func_cfg;
struct lpfc_mbx_get_prof_cfg get_prof_cfg;
- struct lpfc_mbx_nop nop;
struct lpfc_mbx_wr_object wr_object;
+ struct lpfc_mbx_get_port_name get_port_name;
+ struct lpfc_mbx_nop nop;
} un;
};
@@ -2855,6 +3088,9 @@ struct wqe_common {
#define wqe_ctxt_tag_MASK 0x0000FFFF
#define wqe_ctxt_tag_WORD word6
uint32_t word7;
+#define wqe_dif_SHIFT 0
+#define wqe_dif_MASK 0x00000003
+#define wqe_dif_WORD word7
#define wqe_ct_SHIFT 2
#define wqe_ct_MASK 0x00000003
#define wqe_ct_WORD word7
@@ -2867,12 +3103,21 @@ struct wqe_common {
#define wqe_class_SHIFT 16
#define wqe_class_MASK 0x00000007
#define wqe_class_WORD word7
+#define wqe_ar_SHIFT 19
+#define wqe_ar_MASK 0x00000001
+#define wqe_ar_WORD word7
+#define wqe_ag_SHIFT wqe_ar_SHIFT
+#define wqe_ag_MASK wqe_ar_MASK
+#define wqe_ag_WORD wqe_ar_WORD
#define wqe_pu_SHIFT 20
#define wqe_pu_MASK 0x00000003
#define wqe_pu_WORD word7
#define wqe_erp_SHIFT 22
#define wqe_erp_MASK 0x00000001
#define wqe_erp_WORD word7
+#define wqe_conf_SHIFT wqe_erp_SHIFT
+#define wqe_conf_MASK wqe_erp_MASK
+#define wqe_conf_WORD wqe_erp_WORD
#define wqe_lnk_SHIFT 23
#define wqe_lnk_MASK 0x00000001
#define wqe_lnk_WORD word7
@@ -2931,6 +3176,9 @@ struct wqe_common {
#define wqe_xc_SHIFT 21
#define wqe_xc_MASK 0x00000001
#define wqe_xc_WORD word10
+#define wqe_sr_SHIFT 22
+#define wqe_sr_MASK 0x00000001
+#define wqe_sr_WORD word10
#define wqe_ccpe_SHIFT 23
#define wqe_ccpe_MASK 0x00000001
#define wqe_ccpe_WORD word10
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index a3c820083c36..907c94b9245d 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -58,8 +58,7 @@ spinlock_t _dump_buf_lock;
static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
static int lpfc_post_rcv_buf(struct lpfc_hba *);
-static int lpfc_sli4_queue_create(struct lpfc_hba *);
-static void lpfc_sli4_queue_destroy(struct lpfc_hba *);
+static int lpfc_sli4_queue_verify(struct lpfc_hba *);
static int lpfc_create_bootstrap_mbox(struct lpfc_hba *);
static int lpfc_setup_endian_order(struct lpfc_hba *);
static int lpfc_sli4_read_config(struct lpfc_hba *);
@@ -1438,6 +1437,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
struct Scsi_Host *shost;
uint32_t if_type;
struct lpfc_register portstat_reg;
+ int rc;
/* If the pci channel is offline, ignore possible errors, since
* we cannot communicate with the pci card anyway.
@@ -1480,16 +1480,24 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
lpfc_sli4_offline_eratt(phba);
return;
}
- if (bf_get(lpfc_sliport_status_rn, &portstat_reg)) {
- /*
- * TODO: Attempt port recovery via a port reset.
- * When fully implemented, the driver should
- * attempt to recover the port here and return.
- * For now, log an error and take the port offline.
- */
+ /*
+ * On error status condition, driver need to wait for port
+ * ready before performing reset.
+ */
+ rc = lpfc_sli4_pdev_status_reg_wait(phba);
+ if (!rc) {
+ /* need reset: attempt for port recovery */
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2887 Port Error: Attempting "
"Port Recovery\n");
+ lpfc_offline_prep(phba);
+ lpfc_offline(phba);
+ lpfc_sli_brdrestart(phba);
+ if (lpfc_online(phba) == 0) {
+ lpfc_unblock_mgmt_io(phba);
+ return;
+ }
+ /* fall through for not able to recover */
}
lpfc_sli4_offline_eratt(phba);
break;
@@ -1724,11 +1732,20 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
j = 0;
Length -= (3+i);
while(i--) {
- phba->Port[j++] = vpd[index++];
- if (j == 19)
- break;
+ if ((phba->sli_rev == LPFC_SLI_REV4) &&
+ (phba->sli4_hba.pport_name_sta ==
+ LPFC_SLI4_PPNAME_GET)) {
+ j++;
+ index++;
+ } else
+ phba->Port[j++] = vpd[index++];
+ if (j == 19)
+ break;
}
- phba->Port[j] = 0;
+ if ((phba->sli_rev != LPFC_SLI_REV4) ||
+ (phba->sli4_hba.pport_name_sta ==
+ LPFC_SLI4_PPNAME_NON))
+ phba->Port[j] = 0;
continue;
}
else {
@@ -1958,7 +1975,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
case PCI_DEVICE_ID_LANCER_FCOE:
case PCI_DEVICE_ID_LANCER_FCOE_VF:
oneConnect = 1;
- m = (typeof(m)){"OCe50100", "PCIe", "FCoE"};
+ m = (typeof(m)){"OCe15100", "PCIe", "FCoE"};
break;
default:
m = (typeof(m)){"Unknown", "", ""};
@@ -2432,17 +2449,19 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba)
uint8_t actcmd = MBX_HEARTBEAT;
unsigned long timeout;
-
+ timeout = msecs_to_jiffies(LPFC_MBOX_TMO * 1000) + jiffies;
spin_lock_irqsave(&phba->hbalock, iflag);
phba->sli.sli_flag |= LPFC_BLOCK_MGMT_IO;
- if (phba->sli.mbox_active)
+ if (phba->sli.mbox_active) {
actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
+ /* Determine how long we might wait for the active mailbox
+ * command to be gracefully completed by firmware.
+ */
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+ phba->sli.mbox_active) * 1000) + jiffies;
+ }
spin_unlock_irqrestore(&phba->hbalock, iflag);
- /* Determine how long we might wait for the active mailbox
- * command to be gracefully completed by firmware.
- */
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) +
- jiffies;
+
/* Wait for the outstnading mailbox command to complete */
while (phba->sli.mbox_active) {
/* Check active mailbox complete status every 2ms */
@@ -3949,7 +3968,7 @@ static int
lpfc_enable_pci_dev(struct lpfc_hba *phba)
{
struct pci_dev *pdev;
- int bars;
+ int bars = 0;
/* Obtain PCI device reference */
if (!phba->pcidev)
@@ -3978,6 +3997,8 @@ lpfc_enable_pci_dev(struct lpfc_hba *phba)
out_disable_device:
pci_disable_device(pdev);
out_error:
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "1401 Failed to enable pci device, bars:x%x\n", bars);
return -ENODEV;
}
@@ -4051,9 +4072,6 @@ lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *phba)
uint16_t nr_virtfn;
int pos;
- if (!pdev->is_physfn)
- return 0;
-
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
if (pos == 0)
return 0;
@@ -4474,15 +4492,15 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
}
}
mempool_free(mboxq, phba->mbox_mem_pool);
- /* Create all the SLI4 queues */
- rc = lpfc_sli4_queue_create(phba);
+ /* Verify all the SLI4 queues */
+ rc = lpfc_sli4_queue_verify(phba);
if (rc)
goto out_free_bsmbx;
/* Create driver internal CQE event pool */
rc = lpfc_sli4_cq_event_pool_create(phba);
if (rc)
- goto out_destroy_queue;
+ goto out_free_bsmbx;
/* Initialize and populate the iocb list per host */
rc = lpfc_init_sgl_list(phba);
@@ -4516,14 +4534,21 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
goto out_remove_rpi_hdrs;
}
- phba->sli4_hba.fcp_eq_hdl = kzalloc((sizeof(struct lpfc_fcp_eq_hdl) *
+ /*
+ * The cfg_fcp_eq_count can be zero whenever there is exactly one
+ * interrupt vector. This is not an error
+ */
+ if (phba->cfg_fcp_eq_count) {
+ phba->sli4_hba.fcp_eq_hdl =
+ kzalloc((sizeof(struct lpfc_fcp_eq_hdl) *
phba->cfg_fcp_eq_count), GFP_KERNEL);
- if (!phba->sli4_hba.fcp_eq_hdl) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2572 Failed allocate memory for fast-path "
- "per-EQ handle array\n");
- rc = -ENOMEM;
- goto out_free_fcf_rr_bmask;
+ if (!phba->sli4_hba.fcp_eq_hdl) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2572 Failed allocate memory for "
+ "fast-path per-EQ handle array\n");
+ rc = -ENOMEM;
+ goto out_free_fcf_rr_bmask;
+ }
}
phba->sli4_hba.msix_entries = kzalloc((sizeof(struct msix_entry) *
@@ -4567,8 +4592,6 @@ out_free_sgl_list:
lpfc_free_sgl_list(phba);
out_destroy_cq_event_pool:
lpfc_sli4_cq_event_pool_destroy(phba);
-out_destroy_queue:
- lpfc_sli4_queue_destroy(phba);
out_free_bsmbx:
lpfc_destroy_bootstrap_mbox(phba);
out_free_mem:
@@ -4608,9 +4631,6 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
/* Free the SCSI sgl management array */
kfree(phba->sli4_hba.lpfc_scsi_psb_array);
- /* Free the SLI4 queues */
- lpfc_sli4_queue_destroy(phba);
-
/* Free the completion queue EQ event pool */
lpfc_sli4_cq_event_release_all(phba);
lpfc_sli4_cq_event_pool_destroy(phba);
@@ -6139,24 +6159,21 @@ lpfc_setup_endian_order(struct lpfc_hba *phba)
}
/**
- * lpfc_sli4_queue_create - Create all the SLI4 queues
+ * lpfc_sli4_queue_verify - Verify and update EQ and CQ counts
* @phba: pointer to lpfc hba data structure.
*
- * This routine is invoked to allocate all the SLI4 queues for the FCoE HBA
- * operation. For each SLI4 queue type, the parameters such as queue entry
- * count (queue depth) shall be taken from the module parameter. For now,
- * we just use some constant number as place holder.
+ * This routine is invoked to check the user settable queue counts for EQs and
+ * CQs. after this routine is called the counts will be set to valid values that
+ * adhere to the constraints of the system's interrupt vectors and the port's
+ * queue resources.
*
* Return codes
* 0 - successful
* -ENOMEM - No available memory
- * -EIO - The mailbox failed to complete successfully.
**/
static int
-lpfc_sli4_queue_create(struct lpfc_hba *phba)
+lpfc_sli4_queue_verify(struct lpfc_hba *phba)
{
- struct lpfc_queue *qdesc;
- int fcp_eqidx, fcp_cqidx, fcp_wqidx;
int cfg_fcp_wq_count;
int cfg_fcp_eq_count;
@@ -6229,14 +6246,43 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
/* The overall number of event queues used */
phba->sli4_hba.cfg_eqn = phba->cfg_fcp_eq_count + LPFC_SP_EQN_DEF;
- /*
- * Create Event Queues (EQs)
- */
-
/* Get EQ depth from module parameter, fake the default for now */
phba->sli4_hba.eq_esize = LPFC_EQE_SIZE_4B;
phba->sli4_hba.eq_ecount = LPFC_EQE_DEF_COUNT;
+ /* Get CQ depth from module parameter, fake the default for now */
+ phba->sli4_hba.cq_esize = LPFC_CQE_SIZE;
+ phba->sli4_hba.cq_ecount = LPFC_CQE_DEF_COUNT;
+
+ return 0;
+out_error:
+ return -ENOMEM;
+}
+
+/**
+ * lpfc_sli4_queue_create - Create all the SLI4 queues
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to allocate all the SLI4 queues for the FCoE HBA
+ * operation. For each SLI4 queue type, the parameters such as queue entry
+ * count (queue depth) shall be taken from the module parameter. For now,
+ * we just use some constant number as place holder.
+ *
+ * Return codes
+ * 0 - sucessful
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
+ **/
+int
+lpfc_sli4_queue_create(struct lpfc_hba *phba)
+{
+ struct lpfc_queue *qdesc;
+ int fcp_eqidx, fcp_cqidx, fcp_wqidx;
+
+ /*
+ * Create Event Queues (EQs)
+ */
+
/* Create slow path event queue */
qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.eq_esize,
phba->sli4_hba.eq_ecount);
@@ -6247,14 +6293,20 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
}
phba->sli4_hba.sp_eq = qdesc;
- /* Create fast-path FCP Event Queue(s) */
- phba->sli4_hba.fp_eq = kzalloc((sizeof(struct lpfc_queue *) *
- phba->cfg_fcp_eq_count), GFP_KERNEL);
- if (!phba->sli4_hba.fp_eq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2576 Failed allocate memory for fast-path "
- "EQ record array\n");
- goto out_free_sp_eq;
+ /*
+ * Create fast-path FCP Event Queue(s). The cfg_fcp_eq_count can be
+ * zero whenever there is exactly one interrupt vector. This is not
+ * an error.
+ */
+ if (phba->cfg_fcp_eq_count) {
+ phba->sli4_hba.fp_eq = kzalloc((sizeof(struct lpfc_queue *) *
+ phba->cfg_fcp_eq_count), GFP_KERNEL);
+ if (!phba->sli4_hba.fp_eq) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2576 Failed allocate memory for "
+ "fast-path EQ record array\n");
+ goto out_free_sp_eq;
+ }
}
for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) {
qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.eq_esize,
@@ -6271,10 +6323,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
* Create Complete Queues (CQs)
*/
- /* Get CQ depth from module parameter, fake the default for now */
- phba->sli4_hba.cq_esize = LPFC_CQE_SIZE;
- phba->sli4_hba.cq_ecount = LPFC_CQE_DEF_COUNT;
-
/* Create slow-path Mailbox Command Complete Queue */
qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize,
phba->sli4_hba.cq_ecount);
@@ -6296,16 +6344,25 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
phba->sli4_hba.els_cq = qdesc;
- /* Create fast-path FCP Completion Queue(s), one-to-one with EQs */
- phba->sli4_hba.fcp_cq = kzalloc((sizeof(struct lpfc_queue *) *
- phba->cfg_fcp_eq_count), GFP_KERNEL);
+ /*
+ * Create fast-path FCP Completion Queue(s), one-to-one with FCP EQs.
+ * If there are no FCP EQs then create exactly one FCP CQ.
+ */
+ if (phba->cfg_fcp_eq_count)
+ phba->sli4_hba.fcp_cq = kzalloc((sizeof(struct lpfc_queue *) *
+ phba->cfg_fcp_eq_count),
+ GFP_KERNEL);
+ else
+ phba->sli4_hba.fcp_cq = kzalloc(sizeof(struct lpfc_queue *),
+ GFP_KERNEL);
if (!phba->sli4_hba.fcp_cq) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2577 Failed allocate memory for fast-path "
"CQ record array\n");
goto out_free_els_cq;
}
- for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_eq_count; fcp_cqidx++) {
+ fcp_cqidx = 0;
+ do {
qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize,
phba->sli4_hba.cq_ecount);
if (!qdesc) {
@@ -6315,7 +6372,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
goto out_free_fcp_cq;
}
phba->sli4_hba.fcp_cq[fcp_cqidx] = qdesc;
- }
+ } while (++fcp_cqidx < phba->cfg_fcp_eq_count);
/* Create Mailbox Command Queue */
phba->sli4_hba.mq_esize = LPFC_MQE_SIZE;
@@ -6447,7 +6504,7 @@ out_error:
* -ENOMEM - No available memory
* -EIO - The mailbox failed to complete successfully.
**/
-static void
+void
lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
{
int fcp_qidx;
@@ -6723,6 +6780,10 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
"0540 Receive Queue not allocated\n");
goto out_destroy_fcp_wq;
}
+
+ lpfc_rq_adjust_repost(phba, phba->sli4_hba.hdr_rq, LPFC_ELS_HBQ);
+ lpfc_rq_adjust_repost(phba, phba->sli4_hba.dat_rq, LPFC_ELS_HBQ);
+
rc = lpfc_rq_create(phba, phba->sli4_hba.hdr_rq, phba->sli4_hba.dat_rq,
phba->sli4_hba.els_cq, LPFC_USOL);
if (rc) {
@@ -6731,6 +6792,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
"rc = 0x%x\n", rc);
goto out_destroy_fcp_wq;
}
+
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"2592 USL RQ setup: hdr-rq-id=%d, dat-rq-id=%d "
"parent cq-id=%d\n",
@@ -6790,8 +6852,10 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba)
/* Unset ELS complete queue */
lpfc_cq_destroy(phba, phba->sli4_hba.els_cq);
/* Unset FCP response complete queue */
- for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++)
+ fcp_qidx = 0;
+ do {
lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_qidx]);
+ } while (++fcp_qidx < phba->cfg_fcp_eq_count);
/* Unset fast-path event queue */
for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++)
lpfc_eq_destroy(phba, phba->sli4_hba.fp_eq[fcp_qidx]);
@@ -7040,10 +7104,11 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
* the loop again.
*/
for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) {
+ msleep(10);
if (lpfc_readl(phba->sli4_hba.u.if_type2.
STATUSregaddr, &reg_data.word0)) {
rc = -ENODEV;
- break;
+ goto out;
}
if (bf_get(lpfc_sliport_status_rdy, &reg_data))
break;
@@ -7051,7 +7116,6 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
reset_again++;
break;
}
- msleep(10);
}
/*
@@ -7065,11 +7129,6 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
}
/* Detect any port errors. */
- if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
- &reg_data.word0)) {
- rc = -ENODEV;
- break;
- }
if ((bf_get(lpfc_sliport_status_err, &reg_data)) ||
(rdy_chk >= 1000)) {
phba->work_status[0] = readl(
@@ -7102,6 +7161,7 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
break;
}
+out:
/* Catch the not-ready port failure after a port reset. */
if (num_resets >= MAX_IF_TYPE_2_RESETS)
rc = -ENODEV;
@@ -7149,12 +7209,13 @@ lpfc_sli4_send_nop_mbox_cmds(struct lpfc_hba *phba, uint32_t cnt)
lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
LPFC_MBOX_OPCODE_NOP, length, LPFC_SLI4_MBX_EMBED);
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
for (cmdsent = 0; cmdsent < cnt; cmdsent++) {
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
- else
+ else {
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
+ }
if (rc == MBX_TIMEOUT)
break;
/* Check return status */
@@ -7974,6 +8035,7 @@ lpfc_sli4_unset_hba(struct lpfc_hba *phba)
/* Reset SLI4 HBA FCoE function */
lpfc_pci_function_reset(phba);
+ lpfc_sli4_queue_destroy(phba);
return;
}
@@ -8087,6 +8149,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
/* Reset SLI4 HBA FCoE function */
lpfc_pci_function_reset(phba);
+ lpfc_sli4_queue_destroy(phba);
/* Stop the SLI4 device port */
phba->pport->work_port_events = 0;
@@ -8120,7 +8183,7 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_PORT_CAPABILITIES);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
}
@@ -8182,6 +8245,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
int rc;
struct lpfc_mqe *mqe = &mboxq->u.mqe;
struct lpfc_pc_sli4_params *sli4_params;
+ uint32_t mbox_tmo;
int length;
struct lpfc_sli4_parameters *mbx_sli4_parameters;
@@ -8200,9 +8264,10 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
length, LPFC_SLI4_MBX_EMBED);
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
- else
- rc = lpfc_sli_issue_mbox_wait(phba, mboxq,
- lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG));
+ else {
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
+ rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
+ }
if (unlikely(rc))
return rc;
sli4_params = &phba->sli4_hba.pc_sli4_params;
@@ -8271,11 +8336,8 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
/* Perform generic PCI device enabling operation */
error = lpfc_enable_pci_dev(phba);
- if (error) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "1401 Failed to enable pci device.\n");
+ if (error)
goto out_free_phba;
- }
/* Set up SLI API function jump table for PCI-device group-0 HBAs */
error = lpfc_api_table_setup(phba, LPFC_PCI_DEV_LP);
@@ -8322,6 +8384,9 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_free_iocb_list;
}
+ /* Get the default values for Model Name and Description */
+ lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
+
/* Create SCSI host to the physical port */
error = lpfc_create_shost(phba);
if (error) {
@@ -8885,16 +8950,17 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
uint32_t offset = 0, temp_offset = 0;
INIT_LIST_HEAD(&dma_buffer_list);
- if ((image->magic_number != LPFC_GROUP_OJECT_MAGIC_NUM) ||
- (bf_get(lpfc_grp_hdr_file_type, image) != LPFC_FILE_TYPE_GROUP) ||
- (bf_get(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) ||
- (image->size != fw->size)) {
+ if ((be32_to_cpu(image->magic_number) != LPFC_GROUP_OJECT_MAGIC_NUM) ||
+ (bf_get_be32(lpfc_grp_hdr_file_type, image) !=
+ LPFC_FILE_TYPE_GROUP) ||
+ (bf_get_be32(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) ||
+ (be32_to_cpu(image->size) != fw->size)) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3022 Invalid FW image found. "
- "Magic:%d Type:%x ID:%x\n",
- image->magic_number,
- bf_get(lpfc_grp_hdr_file_type, image),
- bf_get(lpfc_grp_hdr_id, image));
+ "Magic:%x Type:%x ID:%x\n",
+ be32_to_cpu(image->magic_number),
+ bf_get_be32(lpfc_grp_hdr_file_type, image),
+ bf_get_be32(lpfc_grp_hdr_id, image));
return -EINVAL;
}
lpfc_decode_firmware_rev(phba, fwrev, 1);
@@ -8924,11 +8990,11 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
while (offset < fw->size) {
temp_offset = offset;
list_for_each_entry(dmabuf, &dma_buffer_list, list) {
- if (offset + SLI4_PAGE_SIZE > fw->size) {
- temp_offset += fw->size - offset;
+ if (temp_offset + SLI4_PAGE_SIZE > fw->size) {
memcpy(dmabuf->virt,
fw->data + temp_offset,
- fw->size - offset);
+ fw->size - temp_offset);
+ temp_offset = fw->size;
break;
}
memcpy(dmabuf->virt, fw->data + temp_offset,
@@ -8984,7 +9050,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
uint32_t cfg_mode, intr_mode;
int mcnt;
int adjusted_fcp_eq_count;
- int fcp_qidx;
const struct firmware *fw;
uint8_t file_name[16];
@@ -8995,11 +9060,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
/* Perform generic PCI device enabling operation */
error = lpfc_enable_pci_dev(phba);
- if (error) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "1409 Failed to enable pci device.\n");
+ if (error)
goto out_free_phba;
- }
/* Set up SLI API function jump table for PCI-device group-1 HBAs */
error = lpfc_api_table_setup(phba, LPFC_PCI_DEV_OC);
@@ -9054,6 +9116,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_free_iocb_list;
}
+ /* Get the default values for Model Name and Description */
+ lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
+
/* Create SCSI host to the physical port */
error = lpfc_create_shost(phba);
if (error) {
@@ -9093,16 +9158,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
adjusted_fcp_eq_count = phba->sli4_hba.msix_vec_nr - 1;
else
adjusted_fcp_eq_count = phba->cfg_fcp_eq_count;
- /* Free unused EQs */
- for (fcp_qidx = adjusted_fcp_eq_count;
- fcp_qidx < phba->cfg_fcp_eq_count;
- fcp_qidx++) {
- lpfc_sli4_queue_free(phba->sli4_hba.fp_eq[fcp_qidx]);
- /* do not delete the first fcp_cq */
- if (fcp_qidx)
- lpfc_sli4_queue_free(
- phba->sli4_hba.fcp_cq[fcp_qidx]);
- }
phba->cfg_fcp_eq_count = adjusted_fcp_eq_count;
/* Set up SLI-4 HBA */
if (lpfc_sli4_hba_setup(phba)) {
@@ -9285,6 +9340,7 @@ lpfc_pci_suspend_one_s4(struct pci_dev *pdev, pm_message_t msg)
/* Disable interrupt from device */
lpfc_sli4_disable_intr(phba);
+ lpfc_sli4_queue_destroy(phba);
/* Save device state to PCI config space */
pci_save_state(pdev);
@@ -9414,6 +9470,7 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba)
/* Disable interrupt and pci device */
lpfc_sli4_disable_intr(phba);
+ lpfc_sli4_queue_destroy(phba);
pci_disable_device(phba->pcidev);
/* Flush all driver's outstanding SCSI I/Os as we are to reset */
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index e3b790e59156..baf53e6c2bd1 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -36,6 +36,7 @@
#define LOG_SECURITY 0x00008000 /* Security events */
#define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */
#define LOG_FIP 0x00020000 /* FIP events */
+#define LOG_FCP_UNDER 0x00040000 /* FCP underruns errors */
#define LOG_ALL_MSG 0xffffffff /* LOG all messages */
#define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 83450cc5c4d3..2ebc7d2540c0 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -1598,9 +1598,12 @@ lpfc_mbox_dev_check(struct lpfc_hba *phba)
* Timeout value to be used for the given mailbox command
**/
int
-lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
+lpfc_mbox_tmo_val(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
{
- switch (cmd) {
+ MAILBOX_t *mbox = &mboxq->u.mb;
+ uint8_t subsys, opcode;
+
+ switch (mbox->mbxCommand) {
case MBX_WRITE_NV: /* 0x03 */
case MBX_UPDATE_CFG: /* 0x1B */
case MBX_DOWN_LOAD: /* 0x1C */
@@ -1610,6 +1613,28 @@ lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
case MBX_LOAD_EXP_ROM: /* 0x9C */
return LPFC_MBOX_TMO_FLASH_CMD;
case MBX_SLI4_CONFIG: /* 0x9b */
+ subsys = lpfc_sli_config_mbox_subsys_get(phba, mboxq);
+ opcode = lpfc_sli_config_mbox_opcode_get(phba, mboxq);
+ if (subsys == LPFC_MBOX_SUBSYSTEM_COMMON) {
+ switch (opcode) {
+ case LPFC_MBOX_OPCODE_READ_OBJECT:
+ case LPFC_MBOX_OPCODE_WRITE_OBJECT:
+ case LPFC_MBOX_OPCODE_READ_OBJECT_LIST:
+ case LPFC_MBOX_OPCODE_DELETE_OBJECT:
+ case LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG:
+ case LPFC_MBOX_OPCODE_GET_PROFILE_LIST:
+ case LPFC_MBOX_OPCODE_SET_ACT_PROFILE:
+ case LPFC_MBOX_OPCODE_SET_PROFILE_CONFIG:
+ case LPFC_MBOX_OPCODE_GET_FACTORY_PROFILE_CONFIG:
+ return LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO;
+ }
+ }
+ if (subsys == LPFC_MBOX_SUBSYSTEM_FCOE) {
+ switch (opcode) {
+ case LPFC_MBOX_OPCODE_FCOE_SET_FCLINK_SETTINGS:
+ return LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO;
+ }
+ }
return LPFC_MBOX_SLI4_CONFIG_TMO;
}
return LPFC_MBOX_TMO;
@@ -1859,7 +1884,7 @@ lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
}
/* Complete the initialization for the particular Opcode. */
- opcode = lpfc_sli4_mbox_opcode_get(phba, mbox);
+ opcode = lpfc_sli_config_mbox_opcode_get(phba, mbox);
switch (opcode) {
case LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT:
if (emb == LPFC_SLI4_MBX_EMBED)
@@ -1886,23 +1911,56 @@ lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
}
/**
- * lpfc_sli4_mbox_opcode_get - Get the opcode from a sli4 mailbox command
+ * lpfc_sli_config_mbox_subsys_get - Get subsystem from a sli_config mbox cmd
* @phba: pointer to lpfc hba data structure.
- * @mbox: pointer to lpfc mbox command.
+ * @mbox: pointer to lpfc mbox command queue entry.
+ *
+ * This routine gets the subsystem from a SLI4 specific SLI_CONFIG mailbox
+ * command. If the mailbox command is not MBX_SLI4_CONFIG (0x9B) or if the
+ * sub-header is not present, subsystem LPFC_MBOX_SUBSYSTEM_NA (0x0) shall
+ * be returned.
+ **/
+uint8_t
+lpfc_sli_config_mbox_subsys_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
+{
+ struct lpfc_mbx_sli4_config *sli4_cfg;
+ union lpfc_sli4_cfg_shdr *cfg_shdr;
+
+ if (mbox->u.mb.mbxCommand != MBX_SLI4_CONFIG)
+ return LPFC_MBOX_SUBSYSTEM_NA;
+ sli4_cfg = &mbox->u.mqe.un.sli4_config;
+
+ /* For embedded mbox command, get opcode from embedded sub-header*/
+ if (bf_get(lpfc_mbox_hdr_emb, &sli4_cfg->header.cfg_mhdr)) {
+ cfg_shdr = &mbox->u.mqe.un.sli4_config.header.cfg_shdr;
+ return bf_get(lpfc_mbox_hdr_subsystem, &cfg_shdr->request);
+ }
+
+ /* For non-embedded mbox command, get opcode from first dma page */
+ if (unlikely(!mbox->sge_array))
+ return LPFC_MBOX_SUBSYSTEM_NA;
+ cfg_shdr = (union lpfc_sli4_cfg_shdr *)mbox->sge_array->addr[0];
+ return bf_get(lpfc_mbox_hdr_subsystem, &cfg_shdr->request);
+}
+
+/**
+ * lpfc_sli_config_mbox_opcode_get - Get opcode from a sli_config mbox cmd
+ * @phba: pointer to lpfc hba data structure.
+ * @mbox: pointer to lpfc mbox command queue entry.
*
- * This routine gets the opcode from a SLI4 specific mailbox command for
- * sending IOCTL command. If the mailbox command is not MBX_SLI4_CONFIG
- * (0x9B) or if the IOCTL sub-header is not present, opcode 0x0 shall be
+ * This routine gets the opcode from a SLI4 specific SLI_CONFIG mailbox
+ * command. If the mailbox command is not MBX_SLI4_CONFIG (0x9B) or if
+ * the sub-header is not present, opcode LPFC_MBOX_OPCODE_NA (0x0) be
* returned.
**/
uint8_t
-lpfc_sli4_mbox_opcode_get(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
+lpfc_sli_config_mbox_opcode_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
{
struct lpfc_mbx_sli4_config *sli4_cfg;
union lpfc_sli4_cfg_shdr *cfg_shdr;
if (mbox->u.mb.mbxCommand != MBX_SLI4_CONFIG)
- return 0;
+ return LPFC_MBOX_OPCODE_NA;
sli4_cfg = &mbox->u.mqe.un.sli4_config;
/* For embedded mbox command, get opcode from embedded sub-header*/
@@ -1913,7 +1971,7 @@ lpfc_sli4_mbox_opcode_get(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
/* For non-embedded mbox command, get opcode from first dma page */
if (unlikely(!mbox->sge_array))
- return 0;
+ return LPFC_MBOX_OPCODE_NA;
cfg_shdr = (union lpfc_sli4_cfg_shdr *)mbox->sge_array->addr[0];
return bf_get(lpfc_mbox_hdr_opcode, &cfg_shdr->request);
}
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index eadd241eeff1..5b8790b3cf4b 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -58,6 +58,13 @@ static char *dif_op_str[] = {
"SCSI_PROT_READ_PASS",
"SCSI_PROT_WRITE_PASS",
};
+
+struct scsi_dif_tuple {
+ __be16 guard_tag; /* Checksum */
+ __be16 app_tag; /* Opaque storage */
+ __be32 ref_tag; /* Target LBA or indirect LBA */
+};
+
static void
lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb);
static void
@@ -1263,6 +1270,174 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
return 0;
}
+static inline unsigned
+lpfc_cmd_blksize(struct scsi_cmnd *sc)
+{
+ return sc->device->sector_size;
+}
+
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+/*
+ * Given a scsi cmnd, determine the BlockGuard tags to be used with it
+ * @sc: The SCSI command to examine
+ * @reftag: (out) BlockGuard reference tag for transmitted data
+ * @apptag: (out) BlockGuard application tag for transmitted data
+ * @new_guard (in) Value to replace CRC with if needed
+ *
+ * Returns (1) if error injection was performed, (0) otherwise
+ */
+static int
+lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
+ uint32_t *reftag, uint16_t *apptag, uint32_t new_guard)
+{
+ struct scatterlist *sgpe; /* s/g prot entry */
+ struct scatterlist *sgde; /* s/g data entry */
+ struct scsi_dif_tuple *src;
+ uint32_t op = scsi_get_prot_op(sc);
+ uint32_t blksize;
+ uint32_t numblks;
+ sector_t lba;
+ int rc = 0;
+
+ if (op == SCSI_PROT_NORMAL)
+ return 0;
+
+ lba = scsi_get_lba(sc);
+ if (phba->lpfc_injerr_lba != LPFC_INJERR_LBA_OFF) {
+ blksize = lpfc_cmd_blksize(sc);
+ numblks = (scsi_bufflen(sc) + blksize - 1) / blksize;
+
+ /* Make sure we have the right LBA if one is specified */
+ if ((phba->lpfc_injerr_lba < lba) ||
+ (phba->lpfc_injerr_lba >= (lba + numblks)))
+ return 0;
+ }
+
+ sgpe = scsi_prot_sglist(sc);
+ sgde = scsi_sglist(sc);
+
+ /* Should we change the Reference Tag */
+ if (reftag) {
+ /*
+ * If we are SCSI_PROT_WRITE_STRIP, the protection data is
+ * being stripped from the wire, thus it doesn't matter.
+ */
+ if ((op == SCSI_PROT_WRITE_PASS) ||
+ (op == SCSI_PROT_WRITE_INSERT)) {
+ if (phba->lpfc_injerr_wref_cnt) {
+
+ /* DEADBEEF will be the reftag on the wire */
+ *reftag = 0xDEADBEEF;
+ phba->lpfc_injerr_wref_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9081 BLKGRD: Injecting reftag error: "
+ "write lba x%lx\n", (unsigned long)lba);
+ }
+ } else {
+ if (phba->lpfc_injerr_rref_cnt) {
+ *reftag = 0xDEADBEEF;
+ phba->lpfc_injerr_rref_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9076 BLKGRD: Injecting reftag error: "
+ "read lba x%lx\n", (unsigned long)lba);
+ }
+ }
+ }
+
+ /* Should we change the Application Tag */
+ if (apptag) {
+ /*
+ * If we are SCSI_PROT_WRITE_STRIP, the protection data is
+ * being stripped from the wire, thus it doesn't matter.
+ */
+ if ((op == SCSI_PROT_WRITE_PASS) ||
+ (op == SCSI_PROT_WRITE_INSERT)) {
+ if (phba->lpfc_injerr_wapp_cnt) {
+
+ /* DEAD will be the apptag on the wire */
+ *apptag = 0xDEAD;
+ phba->lpfc_injerr_wapp_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9077 BLKGRD: Injecting apptag error: "
+ "write lba x%lx\n", (unsigned long)lba);
+ }
+ } else {
+ if (phba->lpfc_injerr_rapp_cnt) {
+ *apptag = 0xDEAD;
+ phba->lpfc_injerr_rapp_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9078 BLKGRD: Injecting apptag error: "
+ "read lba x%lx\n", (unsigned long)lba);
+ }
+ }
+ }
+
+ /* Should we change the Guard Tag */
+
+ /*
+ * If we are SCSI_PROT_WRITE_INSERT, the protection data is
+ * being on the wire is being fully generated on the HBA.
+ * The host cannot change it or force an error.
+ */
+ if (((op == SCSI_PROT_WRITE_STRIP) ||
+ (op == SCSI_PROT_WRITE_PASS)) &&
+ phba->lpfc_injerr_wgrd_cnt) {
+ if (sgpe) {
+ src = (struct scsi_dif_tuple *)sg_virt(sgpe);
+ /*
+ * Just inject an error in the first
+ * prot block.
+ */
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9079 BLKGRD: Injecting guard error: "
+ "write lba x%lx oldGuard x%x refTag x%x\n",
+ (unsigned long)lba, src->guard_tag,
+ src->ref_tag);
+
+ src->guard_tag = (uint16_t)new_guard;
+ phba->lpfc_injerr_wgrd_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+
+ } else {
+ blksize = lpfc_cmd_blksize(sc);
+ /*
+ * Jump past the first data block
+ * and inject an error in the
+ * prot data. The prot data is already
+ * embedded after the regular data.
+ */
+ src = (struct scsi_dif_tuple *)
+ (sg_virt(sgde) + blksize);
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ "9080 BLKGRD: Injecting guard error: "
+ "write lba x%lx oldGuard x%x refTag x%x\n",
+ (unsigned long)lba, src->guard_tag,
+ src->ref_tag);
+
+ src->guard_tag = (uint16_t)new_guard;
+ phba->lpfc_injerr_wgrd_cnt--;
+ phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ rc = 1;
+ }
+ }
+ return rc;
+}
+#endif
+
/*
* Given a scsi cmnd, determine the BlockGuard opcodes to be used with it
* @sc: The SCSI command to examine
@@ -1341,18 +1516,6 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
return ret;
}
-struct scsi_dif_tuple {
- __be16 guard_tag; /* Checksum */
- __be16 app_tag; /* Opaque storage */
- __be32 ref_tag; /* Target LBA or indirect LBA */
-};
-
-static inline unsigned
-lpfc_cmd_blksize(struct scsi_cmnd *sc)
-{
- return sc->device->sector_size;
-}
-
/*
* This function sets up buffer list for protection groups of
* type LPFC_PG_TYPE_NO_DIF
@@ -1401,6 +1564,11 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
blksize = lpfc_cmd_blksize(sc);
reftag = scsi_get_lba(sc) & 0xffffffff;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ /* reftag is the only error we can inject here */
+ lpfc_bg_err_inject(phba, sc, &reftag, 0, 0);
+#endif
+
/* setup PDE5 with what we have */
pde5 = (struct lpfc_pde5 *) bpl;
memset(pde5, 0, sizeof(struct lpfc_pde5));
@@ -1532,6 +1700,11 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
blksize = lpfc_cmd_blksize(sc);
reftag = scsi_get_lba(sc) & 0xffffffff;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ /* reftag / guard tag are the only errors we can inject here */
+ lpfc_bg_err_inject(phba, sc, &reftag, 0, 0xDEAD);
+#endif
+
split_offset = 0;
do {
/* setup PDE5 with what we have */
@@ -1671,7 +1844,6 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
}
} while (!alldone);
-
out:
return num_bde;
@@ -2075,6 +2247,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
else
bf_set(lpfc_sli4_sge_last, sgl, 0);
bf_set(lpfc_sli4_sge_offset, sgl, dma_offset);
+ bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA);
sgl->word2 = cpu_to_le32(sgl->word2);
sgl->sge_len = cpu_to_le32(dma_len);
dma_offset += dma_len;
@@ -2325,8 +2498,9 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
}
lp = (uint32_t *)cmnd->sense_buffer;
- if (!scsi_status && (resp_info & RESID_UNDER))
- logit = LOG_FCP;
+ if (!scsi_status && (resp_info & RESID_UNDER) &&
+ vport->cfg_log_verbose & LOG_FCP_UNDER)
+ logit = LOG_FCP_UNDER;
lpfc_printf_vlog(vport, KERN_WARNING, logit,
"9024 FCP command x%x failed: x%x SNS x%x x%x "
@@ -2342,7 +2516,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
if (resp_info & RESID_UNDER) {
scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId));
- lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_UNDER,
"9025 FCP Read Underrun, expected %d, "
"residual %d Data: x%x x%x x%x\n",
be32_to_cpu(fcpcmd->fcpDl),
@@ -2449,6 +2623,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
struct lpfc_fast_path_event *fast_path_evt;
struct Scsi_Host *shost;
uint32_t queue_depth, scsi_id;
+ uint32_t logit = LOG_FCP;
/* Sanity check on return of outstanding command */
if (!(lpfc_cmd->pCmd))
@@ -2470,16 +2645,22 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
else if (lpfc_cmd->status >= IOSTAT_CNT)
lpfc_cmd->status = IOSTAT_DEFAULT;
-
- lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
- "9030 FCP cmd x%x failed <%d/%d> "
- "status: x%x result: x%x Data: x%x x%x\n",
- cmd->cmnd[0],
- cmd->device ? cmd->device->id : 0xffff,
- cmd->device ? cmd->device->lun : 0xffff,
- lpfc_cmd->status, lpfc_cmd->result,
- pIocbOut->iocb.ulpContext,
- lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
+ if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR
+ && !lpfc_cmd->fcp_rsp->rspStatus3
+ && (lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER)
+ && !(phba->cfg_log_verbose & LOG_FCP_UNDER))
+ logit = 0;
+ else
+ logit = LOG_FCP | LOG_FCP_UNDER;
+ lpfc_printf_vlog(vport, KERN_WARNING, logit,
+ "9030 FCP cmd x%x failed <%d/%d> "
+ "status: x%x result: x%x Data: x%x x%x\n",
+ cmd->cmnd[0],
+ cmd->device ? cmd->device->id : 0xffff,
+ cmd->device ? cmd->device->lun : 0xffff,
+ lpfc_cmd->status, lpfc_cmd->result,
+ pIocbOut->iocb.ulpContext,
+ lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
switch (lpfc_cmd->status) {
case IOSTAT_FCP_RSP_ERROR:
@@ -3056,8 +3237,9 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
}
ndlp = rdata->pnode;
- if (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) &&
- scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) {
+ if ((scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) &&
+ (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) ||
+ (phba->sli_rev == LPFC_SLI_REV4))) {
lpfc_printf_log(phba, KERN_ERR, LOG_BG,
"9058 BLKGRD: ERROR: rcvd protected cmd:%02x"
@@ -3691,9 +3873,9 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
fc_host_post_vendor_event(shost, fc_get_event_number(),
sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID);
- ret = fc_block_scsi_eh(cmnd);
- if (ret)
- return ret;
+ status = fc_block_scsi_eh(cmnd);
+ if (status)
+ return status;
/*
* Since the driver manages a single bus device, reset all
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 8b799f047a99..4d4104f38c98 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -379,10 +379,10 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
dq->host_index = ((dq->host_index + 1) % dq->entry_count);
/* Ring The Header Receive Queue Doorbell */
- if (!(hq->host_index % LPFC_RQ_POST_BATCH)) {
+ if (!(hq->host_index % hq->entry_repost)) {
doorbell.word0 = 0;
bf_set(lpfc_rq_doorbell_num_posted, &doorbell,
- LPFC_RQ_POST_BATCH);
+ hq->entry_repost);
bf_set(lpfc_rq_doorbell_id, &doorbell, hq->queue_id);
writel(doorbell.word0, hq->phba->sli4_hba.RQDBregaddr);
}
@@ -1864,7 +1864,7 @@ lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
{
if (phba->sli_rev == LPFC_SLI_REV4)
return lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
- lpfc_hbq_defs[qno]->entry_count);
+ lpfc_hbq_defs[qno]->entry_count);
else
return lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
lpfc_hbq_defs[qno]->init_count);
@@ -2200,10 +2200,13 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
/* Unknown mailbox command compl */
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"(%d):0323 Unknown Mailbox command "
- "x%x (x%x) Cmpl\n",
+ "x%x (x%x/x%x) Cmpl\n",
pmb->vport ? pmb->vport->vpi : 0,
pmbox->mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, pmb));
+ lpfc_sli_config_mbox_subsys_get(phba,
+ pmb),
+ lpfc_sli_config_mbox_opcode_get(phba,
+ pmb));
phba->link_state = LPFC_HBA_ERROR;
phba->work_hs = HS_FFER3;
lpfc_handle_eratt(phba);
@@ -2215,17 +2218,19 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
if (pmbox->mbxStatus == MBXERR_NO_RESOURCES) {
/* Mbox cmd cmpl error - RETRYing */
lpfc_printf_log(phba, KERN_INFO,
- LOG_MBOX | LOG_SLI,
- "(%d):0305 Mbox cmd cmpl "
- "error - RETRYing Data: x%x "
- "(x%x) x%x x%x x%x\n",
- pmb->vport ? pmb->vport->vpi :0,
- pmbox->mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba,
- pmb),
- pmbox->mbxStatus,
- pmbox->un.varWords[0],
- pmb->vport->port_state);
+ LOG_MBOX | LOG_SLI,
+ "(%d):0305 Mbox cmd cmpl "
+ "error - RETRYing Data: x%x "
+ "(x%x/x%x) x%x x%x x%x\n",
+ pmb->vport ? pmb->vport->vpi : 0,
+ pmbox->mbxCommand,
+ lpfc_sli_config_mbox_subsys_get(phba,
+ pmb),
+ lpfc_sli_config_mbox_opcode_get(phba,
+ pmb),
+ pmbox->mbxStatus,
+ pmbox->un.varWords[0],
+ pmb->vport->port_state);
pmbox->mbxStatus = 0;
pmbox->mbxOwner = OWN_HOST;
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
@@ -2236,11 +2241,12 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
/* Mailbox cmd <cmd> Cmpl <cmpl> */
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "(%d):0307 Mailbox cmd x%x (x%x) Cmpl x%p "
+ "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl x%p "
"Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n",
pmb->vport ? pmb->vport->vpi : 0,
pmbox->mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, pmb),
+ lpfc_sli_config_mbox_subsys_get(phba, pmb),
+ lpfc_sli_config_mbox_opcode_get(phba, pmb),
pmb->mbox_cmpl,
*((uint32_t *) pmbox),
pmbox->un.varWords[0],
@@ -4686,6 +4692,175 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
}
/**
+ * lpfc_sli4_retrieve_pport_name - Retrieve SLI4 device physical port name
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine retrieves SLI4 device physical port name this PCI function
+ * is attached to.
+ *
+ * Return codes
+ * 0 - sucessful
+ * otherwise - failed to retrieve physical port name
+ **/
+static int
+lpfc_sli4_retrieve_pport_name(struct lpfc_hba *phba)
+{
+ LPFC_MBOXQ_t *mboxq;
+ struct lpfc_mbx_read_config *rd_config;
+ struct lpfc_mbx_get_cntl_attributes *mbx_cntl_attr;
+ struct lpfc_controller_attribute *cntl_attr;
+ struct lpfc_mbx_get_port_name *get_port_name;
+ void *virtaddr = NULL;
+ uint32_t alloclen, reqlen;
+ uint32_t shdr_status, shdr_add_status;
+ union lpfc_sli4_cfg_shdr *shdr;
+ char cport_name = 0;
+ int rc;
+
+ /* We assume nothing at this point */
+ phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_INVAL;
+ phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_NON;
+
+ mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mboxq)
+ return -ENOMEM;
+
+ /* obtain link type and link number via READ_CONFIG */
+ lpfc_read_config(phba, mboxq);
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ if (rc == MBX_SUCCESS) {
+ rd_config = &mboxq->u.mqe.un.rd_config;
+ if (bf_get(lpfc_mbx_rd_conf_lnk_ldv, rd_config)) {
+ phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_VAL;
+ phba->sli4_hba.lnk_info.lnk_tp =
+ bf_get(lpfc_mbx_rd_conf_lnk_type, rd_config);
+ phba->sli4_hba.lnk_info.lnk_no =
+ bf_get(lpfc_mbx_rd_conf_lnk_numb, rd_config);
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "3081 lnk_type:%d, lnk_numb:%d\n",
+ phba->sli4_hba.lnk_info.lnk_tp,
+ phba->sli4_hba.lnk_info.lnk_no);
+ goto retrieve_ppname;
+ } else
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3082 Mailbox (x%x) returned ldv:x0\n",
+ bf_get(lpfc_mqe_command,
+ &mboxq->u.mqe));
+ } else
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3083 Mailbox (x%x) failed, status:x%x\n",
+ bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+ bf_get(lpfc_mqe_status, &mboxq->u.mqe));
+
+ /* obtain link type and link number via COMMON_GET_CNTL_ATTRIBUTES */
+ reqlen = sizeof(struct lpfc_mbx_get_cntl_attributes);
+ alloclen = lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES, reqlen,
+ LPFC_SLI4_MBX_NEMBED);
+ if (alloclen < reqlen) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "3084 Allocated DMA memory size (%d) is "
+ "less than the requested DMA memory size "
+ "(%d)\n", alloclen, reqlen);
+ rc = -ENOMEM;
+ goto out_free_mboxq;
+ }
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ virtaddr = mboxq->sge_array->addr[0];
+ mbx_cntl_attr = (struct lpfc_mbx_get_cntl_attributes *)virtaddr;
+ shdr = &mbx_cntl_attr->cfg_shdr;
+ shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+ shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
+ if (shdr_status || shdr_add_status || rc) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3085 Mailbox x%x (x%x/x%x) failed, "
+ "rc:x%x, status:x%x, add_status:x%x\n",
+ bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
+ rc, shdr_status, shdr_add_status);
+ rc = -ENXIO;
+ goto out_free_mboxq;
+ }
+ cntl_attr = &mbx_cntl_attr->cntl_attr;
+ phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_VAL;
+ phba->sli4_hba.lnk_info.lnk_tp =
+ bf_get(lpfc_cntl_attr_lnk_type, cntl_attr);
+ phba->sli4_hba.lnk_info.lnk_no =
+ bf_get(lpfc_cntl_attr_lnk_numb, cntl_attr);
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "3086 lnk_type:%d, lnk_numb:%d\n",
+ phba->sli4_hba.lnk_info.lnk_tp,
+ phba->sli4_hba.lnk_info.lnk_no);
+
+retrieve_ppname:
+ lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_GET_PORT_NAME,
+ sizeof(struct lpfc_mbx_get_port_name) -
+ sizeof(struct lpfc_sli4_cfg_mhdr),
+ LPFC_SLI4_MBX_EMBED);
+ get_port_name = &mboxq->u.mqe.un.get_port_name;
+ shdr = (union lpfc_sli4_cfg_shdr *)&get_port_name->header.cfg_shdr;
+ bf_set(lpfc_mbox_hdr_version, &shdr->request, LPFC_OPCODE_VERSION_1);
+ bf_set(lpfc_mbx_get_port_name_lnk_type, &get_port_name->u.request,
+ phba->sli4_hba.lnk_info.lnk_tp);
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+ shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
+ if (shdr_status || shdr_add_status || rc) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "3087 Mailbox x%x (x%x/x%x) failed: "
+ "rc:x%x, status:x%x, add_status:x%x\n",
+ bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
+ rc, shdr_status, shdr_add_status);
+ rc = -ENXIO;
+ goto out_free_mboxq;
+ }
+ switch (phba->sli4_hba.lnk_info.lnk_no) {
+ case LPFC_LINK_NUMBER_0:
+ cport_name = bf_get(lpfc_mbx_get_port_name_name0,
+ &get_port_name->u.response);
+ phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+ break;
+ case LPFC_LINK_NUMBER_1:
+ cport_name = bf_get(lpfc_mbx_get_port_name_name1,
+ &get_port_name->u.response);
+ phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+ break;
+ case LPFC_LINK_NUMBER_2:
+ cport_name = bf_get(lpfc_mbx_get_port_name_name2,
+ &get_port_name->u.response);
+ phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+ break;
+ case LPFC_LINK_NUMBER_3:
+ cport_name = bf_get(lpfc_mbx_get_port_name_name3,
+ &get_port_name->u.response);
+ phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+ break;
+ default:
+ break;
+ }
+
+ if (phba->sli4_hba.pport_name_sta == LPFC_SLI4_PPNAME_GET) {
+ phba->Port[0] = cport_name;
+ phba->Port[1] = '\0';
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "3091 SLI get port name: %s\n", phba->Port);
+ }
+
+out_free_mboxq:
+ if (rc != MBX_TIMEOUT) {
+ if (bf_get(lpfc_mqe_command, &mboxq->u.mqe) == MBX_SLI4_CONFIG)
+ lpfc_sli4_mbox_cmd_free(phba, mboxq);
+ else
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ }
+ return rc;
+}
+
+/**
* lpfc_sli4_arm_cqeq_intr - Arm sli-4 device completion and event queues
* @phba: pointer to lpfc hba data structure.
*
@@ -4754,7 +4929,7 @@ lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
if (unlikely(rc)) {
@@ -4911,7 +5086,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
@@ -5194,7 +5369,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, mbox_tmo);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
if (unlikely(rc)) {
@@ -5619,7 +5794,7 @@ lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
@@ -5748,6 +5923,17 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
kfree(vpd);
goto out_free_mbox;
}
+
+ /*
+ * Retrieve sli4 device physical port name, failure of doing it
+ * is considered as non-fatal.
+ */
+ rc = lpfc_sli4_retrieve_pport_name(phba);
+ if (!rc)
+ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+ "3080 Successful retrieving SLI4 device "
+ "physical port name: %s.\n", phba->Port);
+
/*
* Evaluate the read rev and vpd data. Populate the driver
* state with the results. If this routine fails, the failure
@@ -5818,9 +6004,13 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
* then turn off the global config parameters to disable the
* feature in the driver. This is not a fatal error.
*/
- if ((phba->cfg_enable_bg) &&
- !(bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs)))
- ftr_rsp++;
+ phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED;
+ if (phba->cfg_enable_bg) {
+ if (bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs))
+ phba->sli3_options |= LPFC_SLI3_BG_ENABLED;
+ else
+ ftr_rsp++;
+ }
if (phba->max_vpi && phba->cfg_enable_npiv &&
!(bf_get(lpfc_mbx_rq_ftr_rsp_npiv, &mqe->un.req_ftrs)))
@@ -5937,12 +6127,20 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
goto out_free_mbox;
}
+ /* Create all the SLI4 queues */
+ rc = lpfc_sli4_queue_create(phba);
+ if (rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "3089 Failed to allocate queues\n");
+ rc = -ENODEV;
+ goto out_stop_timers;
+ }
/* Set up all the queues to the device */
rc = lpfc_sli4_queue_setup(phba);
if (unlikely(rc)) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"0381 Error %d during queue setup.\n ", rc);
- goto out_stop_timers;
+ goto out_destroy_queue;
}
/* Arm the CQs and then EQs on device */
@@ -6015,15 +6213,20 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
spin_lock_irq(&phba->hbalock);
phba->link_state = LPFC_LINK_DOWN;
spin_unlock_irq(&phba->hbalock);
- if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK)
+ if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) {
rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
+ if (rc)
+ goto out_unset_queue;
+ }
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ return rc;
out_unset_queue:
/* Unset all the queues set up in this routine when error out */
- if (rc)
- lpfc_sli4_queue_unset(phba);
+ lpfc_sli4_queue_unset(phba);
+out_destroy_queue:
+ lpfc_sli4_queue_destroy(phba);
out_stop_timers:
- if (rc)
- lpfc_stop_hba_timers(phba);
+ lpfc_stop_hba_timers(phba);
out_free_mbox:
mempool_free(mboxq, phba->mbox_mem_pool);
return rc;
@@ -6318,7 +6521,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
}
/* timeout active mbox command */
mod_timer(&psli->mbox_tmo, (jiffies +
- (HZ * lpfc_mbox_tmo_val(phba, mb->mbxCommand))));
+ (HZ * lpfc_mbox_tmo_val(phba, pmbox))));
}
/* Mailbox cmd <cmd> issue */
@@ -6442,9 +6645,8 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
drvr_flag);
goto out_not_finished;
}
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
- mb->mbxCommand) *
- 1000) + jiffies;
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, pmbox) *
+ 1000) + jiffies;
i = 0;
/* Wait for command to complete */
while (((word0 & OWN_CHIP) == OWN_CHIP) ||
@@ -6555,21 +6757,21 @@ static int
lpfc_sli4_async_mbox_block(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
- uint8_t actcmd = MBX_HEARTBEAT;
int rc = 0;
- unsigned long timeout;
+ unsigned long timeout = 0;
/* Mark the asynchronous mailbox command posting as blocked */
spin_lock_irq(&phba->hbalock);
psli->sli_flag |= LPFC_SLI_ASYNC_MBX_BLK;
- if (phba->sli.mbox_active)
- actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
- spin_unlock_irq(&phba->hbalock);
/* Determine how long we might wait for the active mailbox
* command to be gracefully completed by firmware.
*/
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) +
- jiffies;
+ if (phba->sli.mbox_active)
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+ phba->sli.mbox_active) *
+ 1000) + jiffies;
+ spin_unlock_irq(&phba->hbalock);
+
/* Wait for the outstnading mailbox command to complete */
while (phba->sli.mbox_active) {
/* Check active mailbox complete status every 2ms */
@@ -6664,11 +6866,12 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
spin_unlock_irqrestore(&phba->hbalock, iflag);
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "(%d):2532 Mailbox command x%x (x%x) "
+ "(%d):2532 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
psli->sli_flag, MBX_POLL);
return MBXERR_ERROR;
}
@@ -6691,7 +6894,7 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
dma_address = &phba->sli4_hba.bmbx.dma_address;
writel(dma_address->addr_hi, phba->sli4_hba.BMBXregaddr);
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mbx_cmnd)
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq)
* 1000) + jiffies;
do {
bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr);
@@ -6707,7 +6910,7 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
/* Post the low mailbox dma address to the port. */
writel(dma_address->addr_lo, phba->sli4_hba.BMBXregaddr);
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mbx_cmnd)
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq)
* 1000) + jiffies;
do {
bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr);
@@ -6746,11 +6949,12 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
lpfc_sli4_swap_str(phba, mboxq);
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "(%d):0356 Mailbox cmd x%x (x%x) Status x%x "
+ "(%d):0356 Mailbox cmd x%x (x%x/x%x) Status x%x "
"Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x x%x x%x"
" x%x x%x CQ: x%x x%x x%x x%x\n",
- mboxq->vport ? mboxq->vport->vpi : 0,
- mbx_cmnd, lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ mboxq->vport ? mboxq->vport->vpi : 0, mbx_cmnd,
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
bf_get(lpfc_mqe_status, mb),
mb->un.mb_words[0], mb->un.mb_words[1],
mb->un.mb_words[2], mb->un.mb_words[3],
@@ -6796,11 +7000,12 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
rc = lpfc_mbox_dev_check(phba);
if (unlikely(rc)) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "(%d):2544 Mailbox command x%x (x%x) "
+ "(%d):2544 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
psli->sli_flag, flag);
goto out_not_finished;
}
@@ -6814,20 +7019,25 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
if (rc != MBX_SUCCESS)
lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
"(%d):2541 Mailbox command x%x "
- "(x%x) cannot issue Data: x%x x%x\n",
+ "(x%x/x%x) cannot issue Data: "
+ "x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba,
+ mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba,
+ mboxq),
psli->sli_flag, flag);
return rc;
} else if (flag == MBX_POLL) {
lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
"(%d):2542 Try to issue mailbox command "
- "x%x (x%x) synchronously ahead of async"
+ "x%x (x%x/x%x) synchronously ahead of async"
"mailbox command queue: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
psli->sli_flag, flag);
/* Try to block the asynchronous mailbox posting */
rc = lpfc_sli4_async_mbox_block(phba);
@@ -6836,16 +7046,18 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
rc = lpfc_sli4_post_sync_mbox(phba, mboxq);
if (rc != MBX_SUCCESS)
lpfc_printf_log(phba, KERN_ERR,
- LOG_MBOX | LOG_SLI,
- "(%d):2597 Mailbox command "
- "x%x (x%x) cannot issue "
- "Data: x%x x%x\n",
- mboxq->vport ?
- mboxq->vport->vpi : 0,
- mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba,
- mboxq),
- psli->sli_flag, flag);
+ LOG_MBOX | LOG_SLI,
+ "(%d):2597 Mailbox command "
+ "x%x (x%x/x%x) cannot issue "
+ "Data: x%x x%x\n",
+ mboxq->vport ?
+ mboxq->vport->vpi : 0,
+ mboxq->u.mb.mbxCommand,
+ lpfc_sli_config_mbox_subsys_get(phba,
+ mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba,
+ mboxq),
+ psli->sli_flag, flag);
/* Unblock the async mailbox posting afterward */
lpfc_sli4_async_mbox_unblock(phba);
}
@@ -6856,11 +7068,12 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
rc = lpfc_mbox_cmd_check(phba, mboxq);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "(%d):2543 Mailbox command x%x (x%x) "
+ "(%d):2543 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
psli->sli_flag, flag);
goto out_not_finished;
}
@@ -6872,10 +7085,11 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
spin_unlock_irqrestore(&phba->hbalock, iflags);
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
"(%d):0354 Mbox cmd issue - Enqueue Data: "
- "x%x (x%x) x%x x%x x%x\n",
+ "x%x (x%x/x%x) x%x x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0xffffff,
bf_get(lpfc_mqe_command, &mboxq->u.mqe),
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
phba->pport->port_state,
psli->sli_flag, MBX_NOWAIT);
/* Wake up worker thread to transport mailbox command from head */
@@ -6952,13 +7166,14 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba)
/* Start timer for the mbox_tmo and log some mailbox post messages */
mod_timer(&psli->mbox_tmo, (jiffies +
- (HZ * lpfc_mbox_tmo_val(phba, mbx_cmnd))));
+ (HZ * lpfc_mbox_tmo_val(phba, mboxq))));
lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
- "(%d):0355 Mailbox cmd x%x (x%x) issue Data: "
+ "(%d):0355 Mailbox cmd x%x (x%x/x%x) issue Data: "
"x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0, mbx_cmnd,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
phba->pport->port_state, psli->sli_flag);
if (mbx_cmnd != MBX_HEARTBEAT) {
@@ -6982,11 +7197,12 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba)
rc = lpfc_sli4_mq_put(phba->sli4_hba.mbx_wq, mqe);
if (rc != MBX_SUCCESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
- "(%d):2533 Mailbox command x%x (x%x) "
+ "(%d):2533 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
- lpfc_sli4_mbox_opcode_get(phba, mboxq),
+ lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(phba, mboxq),
psli->sli_flag, MBX_NOWAIT);
goto out_not_finished;
}
@@ -7322,6 +7538,8 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
if (inbound == 1)
offset = 0;
bf_set(lpfc_sli4_sge_offset, sgl, offset);
+ bf_set(lpfc_sli4_sge_type, sgl,
+ LPFC_SGE_TYPE_DATA);
offset += bde.tus.f.bdeSize;
}
sgl->word2 = cpu_to_le32(sgl->word2);
@@ -9359,7 +9577,6 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
/* now issue the command */
retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
-
if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
wait_event_interruptible_timeout(done_q,
pmboxq->mbox_flag & LPFC_MBX_WAKE,
@@ -9403,23 +9620,24 @@ void
lpfc_sli_mbox_sys_shutdown(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
- uint8_t actcmd = MBX_HEARTBEAT;
unsigned long timeout;
+ timeout = msecs_to_jiffies(LPFC_MBOX_TMO * 1000) + jiffies;
spin_lock_irq(&phba->hbalock);
psli->sli_flag |= LPFC_SLI_ASYNC_MBX_BLK;
spin_unlock_irq(&phba->hbalock);
if (psli->sli_flag & LPFC_SLI_ACTIVE) {
spin_lock_irq(&phba->hbalock);
- if (phba->sli.mbox_active)
- actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
- spin_unlock_irq(&phba->hbalock);
/* Determine how long we might wait for the active mailbox
* command to be gracefully completed by firmware.
*/
- timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) *
- 1000) + jiffies;
+ if (phba->sli.mbox_active)
+ timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+ phba->sli.mbox_active) *
+ 1000) + jiffies;
+ spin_unlock_irq(&phba->hbalock);
+
while (phba->sli.mbox_active) {
/* Check active mailbox complete status every 2ms */
msleep(2);
@@ -10415,12 +10633,17 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe)
/* Move mbox data to caller's mailbox region, do endian swapping */
if (pmb->mbox_cmpl && mbox)
lpfc_sli_pcimem_bcopy(mbox, mqe, sizeof(struct lpfc_mqe));
- /* Set the mailbox status with SLI4 range 0x4000 */
- mcqe_status = bf_get(lpfc_mcqe_status, mcqe);
- if (mcqe_status != MB_CQE_STATUS_SUCCESS)
- bf_set(lpfc_mqe_status, mqe,
- (LPFC_MBX_ERROR_RANGE | mcqe_status));
+ /*
+ * For mcqe errors, conditionally move a modified error code to
+ * the mbox so that the error will not be missed.
+ */
+ mcqe_status = bf_get(lpfc_mcqe_status, mcqe);
+ if (mcqe_status != MB_CQE_STATUS_SUCCESS) {
+ if (bf_get(lpfc_mqe_status, mqe) == MBX_SUCCESS)
+ bf_set(lpfc_mqe_status, mqe,
+ (LPFC_MBX_ERROR_RANGE | mcqe_status));
+ }
if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_MBOX_VPORT,
@@ -10796,7 +11019,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
case LPFC_MCQ:
while ((cqe = lpfc_sli4_cq_get(cq))) {
workposted |= lpfc_sli4_sp_handle_mcqe(phba, cqe);
- if (!(++ecount % LPFC_GET_QE_REL_INT))
+ if (!(++ecount % cq->entry_repost))
lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
}
break;
@@ -10808,7 +11031,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
else
workposted |= lpfc_sli4_sp_handle_cqe(phba, cq,
cqe);
- if (!(++ecount % LPFC_GET_QE_REL_INT))
+ if (!(++ecount % cq->entry_repost))
lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
}
break;
@@ -11040,7 +11263,7 @@ lpfc_sli4_fp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
/* Process all the entries to the CQ */
while ((cqe = lpfc_sli4_cq_get(cq))) {
workposted |= lpfc_sli4_fp_handle_wcqe(phba, cq, cqe);
- if (!(++ecount % LPFC_GET_QE_REL_INT))
+ if (!(++ecount % cq->entry_repost))
lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
}
@@ -11110,6 +11333,8 @@ lpfc_sli4_sp_intr_handler(int irq, void *dev_id)
/* Get to the EQ struct associated with this vector */
speq = phba->sli4_hba.sp_eq;
+ if (unlikely(!speq))
+ return IRQ_NONE;
/* Check device state for handling interrupt */
if (unlikely(lpfc_intr_state_check(phba))) {
@@ -11127,7 +11352,7 @@ lpfc_sli4_sp_intr_handler(int irq, void *dev_id)
*/
while ((eqe = lpfc_sli4_eq_get(speq))) {
lpfc_sli4_sp_handle_eqe(phba, eqe);
- if (!(++ecount % LPFC_GET_QE_REL_INT))
+ if (!(++ecount % speq->entry_repost))
lpfc_sli4_eq_release(speq, LPFC_QUEUE_NOARM);
}
@@ -11187,6 +11412,8 @@ lpfc_sli4_fp_intr_handler(int irq, void *dev_id)
if (unlikely(!phba))
return IRQ_NONE;
+ if (unlikely(!phba->sli4_hba.fp_eq))
+ return IRQ_NONE;
/* Get to the EQ struct associated with this vector */
fpeq = phba->sli4_hba.fp_eq[fcp_eqidx];
@@ -11207,7 +11434,7 @@ lpfc_sli4_fp_intr_handler(int irq, void *dev_id)
*/
while ((eqe = lpfc_sli4_eq_get(fpeq))) {
lpfc_sli4_fp_handle_eqe(phba, eqe, fcp_eqidx);
- if (!(++ecount % LPFC_GET_QE_REL_INT))
+ if (!(++ecount % fpeq->entry_repost))
lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_NOARM);
}
@@ -11359,6 +11586,15 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size,
}
queue->entry_size = entry_size;
queue->entry_count = entry_count;
+
+ /*
+ * entry_repost is calculated based on the number of entries in the
+ * queue. This works out except for RQs. If buffers are NOT initially
+ * posted for every RQE, entry_repost should be adjusted accordingly.
+ */
+ queue->entry_repost = (entry_count >> 3);
+ if (queue->entry_repost < LPFC_QUEUE_MIN_REPOST)
+ queue->entry_repost = LPFC_QUEUE_MIN_REPOST;
queue->phba = phba;
return queue;
@@ -11924,6 +12160,31 @@ out:
}
/**
+ * lpfc_rq_adjust_repost - Adjust entry_repost for an RQ
+ * @phba: HBA structure that indicates port to create a queue on.
+ * @rq: The queue structure to use for the receive queue.
+ * @qno: The associated HBQ number
+ *
+ *
+ * For SLI4 we need to adjust the RQ repost value based on
+ * the number of buffers that are initially posted to the RQ.
+ */
+void
+lpfc_rq_adjust_repost(struct lpfc_hba *phba, struct lpfc_queue *rq, int qno)
+{
+ uint32_t cnt;
+
+ cnt = lpfc_hbq_defs[qno]->entry_count;
+
+ /* Recalc repost for RQs based on buffers initially posted */
+ cnt = (cnt >> 3);
+ if (cnt < LPFC_QUEUE_MIN_REPOST)
+ cnt = LPFC_QUEUE_MIN_REPOST;
+
+ rq->entry_repost = cnt;
+}
+
+/**
* lpfc_rq_create - Create a Receive Queue on the HBA
* @phba: HBA structure that indicates port to create a queue on.
* @hrq: The queue structure to use to create the header receive queue.
@@ -12489,7 +12750,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
/* The IOCTL status is embedded in the mailbox subheader. */
@@ -12704,7 +12965,7 @@ lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -12867,7 +13128,7 @@ lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba)
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -12991,7 +13252,7 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -13147,7 +13408,7 @@ lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *phba, struct list_head *sblist,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -13296,7 +13557,8 @@ lpfc_fc_frame_to_vport(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr,
uint32_t did = (fc_hdr->fh_d_id[0] << 16 |
fc_hdr->fh_d_id[1] << 8 |
fc_hdr->fh_d_id[2]);
-
+ if (did == Fabric_DID)
+ return phba->pport;
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
@@ -14312,7 +14574,7 @@ lpfc_sli4_init_vpi(struct lpfc_vport *vport)
if (!mboxq)
return -ENOMEM;
lpfc_init_vpi(phba, mboxq, vport->vpi);
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_INIT_VPI);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
if (rc != MBX_SUCCESS) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI,
@@ -15188,7 +15450,7 @@ lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list,
if (!phba->sli4_hba.intr_enable)
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+ mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
}
/* The IOCTL status is embedded in the mailbox subheader. */
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index a0075b0af142..29c13b63e323 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -293,13 +293,11 @@ struct lpfc_sli {
struct lpfc_lnk_stat lnk_stat_offsets;
};
-#define LPFC_MBOX_TMO 30 /* Sec tmo for outstanding mbox
- command */
-#define LPFC_MBOX_SLI4_CONFIG_TMO 60 /* Sec tmo for outstanding mbox
- command */
-#define LPFC_MBOX_TMO_FLASH_CMD 300 /* Sec tmo for outstanding FLASH write
- * or erase cmds. This is especially
- * long because of the potential of
- * multiple flash erases that can be
- * spawned.
- */
+/* Timeout for normal outstanding mbox command (Seconds) */
+#define LPFC_MBOX_TMO 30
+/* Timeout for non-flash-based outstanding sli_config mbox command (Seconds) */
+#define LPFC_MBOX_SLI4_CONFIG_TMO 60
+/* Timeout for flash-based outstanding sli_config mbox command (Seconds) */
+#define LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO 300
+/* Timeout for other flash-based outstanding mbox command (Seconds) */
+#define LPFC_MBOX_TMO_FLASH_CMD 300
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index 19bb87ae8597..d5cffd8af340 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -23,7 +23,6 @@
#define LPFC_XRI_EXCH_BUSY_WAIT_T1 10
#define LPFC_XRI_EXCH_BUSY_WAIT_T2 30000
#define LPFC_RELEASE_NOTIFICATION_INTERVAL 32
-#define LPFC_GET_QE_REL_INT 32
#define LPFC_RPI_LOW_WATER_MARK 10
#define LPFC_UNREG_FCF 1
@@ -126,6 +125,8 @@ struct lpfc_queue {
struct list_head child_list;
uint32_t entry_count; /* Number of entries to support on the queue */
uint32_t entry_size; /* Size of each queue entry. */
+ uint32_t entry_repost; /* Count of entries before doorbell is rung */
+#define LPFC_QUEUE_MIN_REPOST 8
uint32_t queue_id; /* Queue ID assigned by the hardware */
uint32_t assoc_qid; /* Queue ID associated with, for CQ/WQ/MQ */
struct list_head page_list;
@@ -388,6 +389,16 @@ struct lpfc_iov {
uint32_t vf_number;
};
+struct lpfc_sli4_lnk_info {
+ uint8_t lnk_dv;
+#define LPFC_LNK_DAT_INVAL 0
+#define LPFC_LNK_DAT_VAL 1
+ uint8_t lnk_tp;
+#define LPFC_LNK_GE 0x0 /* FCoE */
+#define LPFC_LNK_FC 0x1 /* FC */
+ uint8_t lnk_no;
+};
+
/* SLI4 HBA data structure entries */
struct lpfc_sli4_hba {
void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for
@@ -503,6 +514,10 @@ struct lpfc_sli4_hba {
struct list_head sp_els_xri_aborted_work_queue;
struct list_head sp_unsol_work_queue;
struct lpfc_sli4_link link_state;
+ struct lpfc_sli4_lnk_info lnk_info;
+ uint32_t pport_name_sta;
+#define LPFC_SLI4_PPNAME_NON 0
+#define LPFC_SLI4_PPNAME_GET 1
struct lpfc_iov iov;
spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */
spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */
@@ -553,6 +568,7 @@ struct lpfc_rsrc_blks {
* SLI4 specific function prototypes
*/
int lpfc_pci_function_reset(struct lpfc_hba *);
+int lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *);
int lpfc_sli4_hba_setup(struct lpfc_hba *);
int lpfc_sli4_config(struct lpfc_hba *, struct lpfcMboxq *, uint8_t,
uint8_t, uint32_t, bool);
@@ -576,6 +592,7 @@ uint32_t lpfc_wq_create(struct lpfc_hba *, struct lpfc_queue *,
struct lpfc_queue *, uint32_t);
uint32_t lpfc_rq_create(struct lpfc_hba *, struct lpfc_queue *,
struct lpfc_queue *, struct lpfc_queue *, uint32_t);
+void lpfc_rq_adjust_repost(struct lpfc_hba *, struct lpfc_queue *, int);
uint32_t lpfc_eq_destroy(struct lpfc_hba *, struct lpfc_queue *);
uint32_t lpfc_cq_destroy(struct lpfc_hba *, struct lpfc_queue *);
uint32_t lpfc_mq_destroy(struct lpfc_hba *, struct lpfc_queue *);
@@ -632,5 +649,5 @@ void lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_sli4_unregister_fcf(struct lpfc_hba *);
int lpfc_sli4_post_status_check(struct lpfc_hba *);
-uint8_t lpfc_sli4_mbox_opcode_get(struct lpfc_hba *, struct lpfcMboxq *);
-
+uint8_t lpfc_sli_config_mbox_subsys_get(struct lpfc_hba *, LPFC_MBOXQ_t *);
+uint8_t lpfc_sli_config_mbox_opcode_get(struct lpfc_hba *, LPFC_MBOXQ_t *);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index c1e0ae94d9f4..b0630e37f1ef 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.3.25"
+#define LPFC_DRIVER_VERSION "8.3.27"
#define LPFC_DRIVER_NAME "lpfc"
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 1feb551a57bc..cff6ca67415c 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -692,13 +692,14 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
/* Indicate free memory when release */
NLP_SET_FREE_REQ(ndlp);
} else {
- if (!NLP_CHK_NODE_ACT(ndlp))
+ if (!NLP_CHK_NODE_ACT(ndlp)) {
ndlp = lpfc_enable_node(vport, ndlp,
NLP_STE_UNUSED_NODE);
if (!ndlp)
goto skip_logo;
+ }
- /* Remove ndlp from vport npld list */
+ /* Remove ndlp from vport list */
lpfc_dequeue_node(vport, ndlp);
spin_lock_irq(&phba->ndlp_lock);
if (!NLP_CHK_FREE_REQ(ndlp))
@@ -711,8 +712,17 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
}
spin_unlock_irq(&phba->ndlp_lock);
}
- if (!(vport->vpi_state & LPFC_VPI_REGISTERED))
+
+ /*
+ * If the vpi is not registered, then a valid FDISC doesn't
+ * exist and there is no need for a ELS LOGO. Just cleanup
+ * the ndlp.
+ */
+ if (!(vport->vpi_state & LPFC_VPI_REGISTERED)) {
+ lpfc_nlp_put(ndlp);
goto skip_logo;
+ }
+
vport->unreg_vpi_cmpl = VPORT_INVAL;
timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
if (!lpfc_issue_els_npiv_logo(vport, ndlp))
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index 3893337e3dd3..590ce1ef2016 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -230,9 +230,6 @@ static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
u32 dma_count, int write, u8 cmd)
{
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
- unsigned long flags;
-
- local_irq_save(flags);
mep->error = 0;
@@ -270,8 +267,6 @@ static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
esp_count = n;
}
} while (esp_count);
-
- local_irq_restore(flags);
}
/*
@@ -353,8 +348,6 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
u8 *fifo = esp->regs + ESP_FDATA * 16;
- disable_irq(esp->host->irq);
-
cmd &= ~ESP_CMD_DMA;
mep->error = 0;
@@ -431,8 +424,6 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
scsi_esp_cmd(esp, ESP_CMD_TI);
}
}
-
- enable_irq(esp->host->irq);
}
static int mac_esp_irq_pending(struct esp *esp)
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 2e6619eff3ea..8883ca36f932 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -67,7 +67,7 @@
*
* NEC MegaRAID PCI Express ROMB 1000 0408 1033 8287
*
- * For history of changes, see Documentation/ChangeLog.megaraid
+ * For history of changes, see Documentation/scsi/ChangeLog.megaraid
*/
#include <linux/slab.h>
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 3948a00d81f4..dd94c7d574fb 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -33,9 +33,9 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.05.40-rc1"
-#define MEGASAS_RELDATE "Jul. 26, 2011"
-#define MEGASAS_EXT_VERSION "Tue. Jul. 26 17:00:00 PDT 2011"
+#define MEGASAS_VERSION "00.00.06.12-rc1"
+#define MEGASAS_RELDATE "Oct. 5, 2011"
+#define MEGASAS_EXT_VERSION "Wed. Oct. 5 17:00:00 PDT 2011"
/*
* Device IDs
@@ -48,6 +48,7 @@
#define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073
#define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071
#define PCI_DEVICE_ID_LSI_FUSION 0x005b
+#define PCI_DEVICE_ID_LSI_INVADER 0x005d
/*
* =====================================
@@ -138,6 +139,7 @@
#define MFI_CMD_ABORT 0x06
#define MFI_CMD_SMP 0x07
#define MFI_CMD_STP 0x08
+#define MFI_CMD_INVALID 0xff
#define MR_DCMD_CTRL_GET_INFO 0x01010000
#define MR_DCMD_LD_GET_LIST 0x03010000
@@ -221,6 +223,7 @@ enum MFI_STAT {
MFI_STAT_RESERVATION_IN_PROGRESS = 0x36,
MFI_STAT_I2C_ERRORS_DETECTED = 0x37,
MFI_STAT_PCI_ERRORS_DETECTED = 0x38,
+ MFI_STAT_CONFIG_SEQ_MISMATCH = 0x67,
MFI_STAT_INVALID_STATUS = 0xFF
};
@@ -716,7 +719,7 @@ struct megasas_ctrl_info {
#define MEGASAS_DEFAULT_INIT_ID -1
#define MEGASAS_MAX_LUN 8
#define MEGASAS_MAX_LD 64
-#define MEGASAS_DEFAULT_CMD_PER_LUN 128
+#define MEGASAS_DEFAULT_CMD_PER_LUN 256
#define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \
MEGASAS_MAX_DEV_PER_CHANNEL)
#define MEGASAS_MAX_LD_IDS (MEGASAS_MAX_LD_CHANNELS * \
@@ -755,6 +758,7 @@ struct megasas_ctrl_info {
#define MEGASAS_INT_CMDS 32
#define MEGASAS_SKINNY_INT_CMDS 5
+#define MEGASAS_MAX_MSIX_QUEUES 16
/*
* FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
* SGLs based on the size of dma_addr_t
@@ -1276,6 +1280,11 @@ struct megasas_aen_event {
struct megasas_instance *instance;
};
+struct megasas_irq_context {
+ struct megasas_instance *instance;
+ u32 MSIxIndex;
+};
+
struct megasas_instance {
u32 *producer;
@@ -1349,8 +1358,9 @@ struct megasas_instance {
/* Ptr to hba specific information */
void *ctrl_context;
- u8 msi_flag;
- struct msix_entry msixentry;
+ unsigned int msix_vectors;
+ struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES];
+ struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES];
u64 map_id;
struct megasas_cmd *map_update_cmd;
unsigned long bar;
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 776d01988660..29a994f9c4f1 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FILE: megaraid_sas_base.c
- * Version : v00.00.05.40-rc1
+ * Version : v00.00.06.12-rc1
*
* Authors: LSI Corporation
* Sreenivas Bagalkote
@@ -84,7 +84,7 @@ MODULE_VERSION(MEGASAS_VERSION);
MODULE_AUTHOR("megaraidlinux@lsi.com");
MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
-int megasas_transition_to_ready(struct megasas_instance *instance);
+int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
static int megasas_get_pd_list(struct megasas_instance *instance);
static int megasas_issue_init_mfi(struct megasas_instance *instance);
static int megasas_register_aen(struct megasas_instance *instance,
@@ -114,6 +114,8 @@ static struct pci_device_id megasas_pci_table[] = {
/* xscale IOP */
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FUSION)},
/* Fusion */
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INVADER)},
+ /* Invader */
{}
};
@@ -213,6 +215,10 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
cmd->scmd = NULL;
cmd->frame_count = 0;
+ if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
+ (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
+ (reset_devices))
+ cmd->frame->hdr.cmd = MFI_CMD_INVALID;
list_add_tail(&cmd->list, &instance->cmd_pool);
spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
@@ -1583,7 +1589,8 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance)
{
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)) {
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) {
writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
} else {
writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell);
@@ -1907,7 +1914,6 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
static enum
blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
{
- struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
struct megasas_instance *instance;
unsigned long flags;
@@ -1916,7 +1922,7 @@ blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
return BLK_EH_NOT_HANDLED;
}
- instance = cmd->instance;
+ instance = (struct megasas_instance *)scmd->device->host->hostdata;
if (!(instance->flag & MEGASAS_FW_BUSY)) {
/* FW is busy, throttle IO */
spin_lock_irqsave(instance->host->host_lock, flags);
@@ -1957,7 +1963,8 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
/*
* First wait for all commands to complete
*/
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER))
ret = megasas_reset_fusion(scmd->device->host);
else
ret = megasas_generic_reset(scmd);
@@ -2161,7 +2168,16 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
cmd->scmd->SCp.ptr = NULL;
switch (hdr->cmd) {
-
+ case MFI_CMD_INVALID:
+ /* Some older 1068 controller FW may keep a pended
+ MR_DCMD_CTRL_EVENT_GET_INFO left over from the main kernel
+ when booting the kdump kernel. Ignore this command to
+ prevent a kernel panic on shutdown of the kdump kernel. */
+ printk(KERN_WARNING "megaraid_sas: MFI_CMD_INVALID command "
+ "completed.\n");
+ printk(KERN_WARNING "megaraid_sas: If you have a controller "
+ "other than PERC5, please upgrade your firmware.\n");
+ break;
case MFI_CMD_PD_SCSI_IO:
case MFI_CMD_LD_SCSI_IO:
@@ -2477,7 +2493,7 @@ process_fw_state_change_wq(struct work_struct *work)
msleep(1000);
}
- if (megasas_transition_to_ready(instance)) {
+ if (megasas_transition_to_ready(instance, 1)) {
printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");
megaraid_sas_kill_hba(instance);
@@ -2532,7 +2548,7 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
instance->reg_set)
) == 0) {
/* Hardware may not set outbound_intr_status in MSI-X mode */
- if (!instance->msi_flag)
+ if (!instance->msix_vectors)
return IRQ_NONE;
}
@@ -2590,16 +2606,14 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
*/
static irqreturn_t megasas_isr(int irq, void *devp)
{
- struct megasas_instance *instance;
+ struct megasas_irq_context *irq_context = devp;
+ struct megasas_instance *instance = irq_context->instance;
unsigned long flags;
irqreturn_t rc;
- if (atomic_read(
- &(((struct megasas_instance *)devp)->fw_reset_no_pci_access)))
+ if (atomic_read(&instance->fw_reset_no_pci_access))
return IRQ_HANDLED;
- instance = (struct megasas_instance *)devp;
-
spin_lock_irqsave(&instance->hba_lock, flags);
rc = megasas_deplete_reply_queue(instance, DID_OK);
spin_unlock_irqrestore(&instance->hba_lock, flags);
@@ -2617,7 +2631,7 @@ static irqreturn_t megasas_isr(int irq, void *devp)
* has to wait for the ready state.
*/
int
-megasas_transition_to_ready(struct megasas_instance* instance)
+megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
{
int i;
u8 max_wait;
@@ -2639,11 +2653,13 @@ megasas_transition_to_ready(struct megasas_instance* instance)
switch (fw_state) {
case MFI_STATE_FAULT:
-
printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");
- max_wait = MEGASAS_RESET_WAIT_TIME;
- cur_state = MFI_STATE_FAULT;
- break;
+ if (ocr) {
+ max_wait = MEGASAS_RESET_WAIT_TIME;
+ cur_state = MFI_STATE_FAULT;
+ break;
+ } else
+ return -ENODEV;
case MFI_STATE_WAIT_HANDSHAKE:
/*
@@ -2654,7 +2670,9 @@ megasas_transition_to_ready(struct megasas_instance* instance)
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
(instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION)) {
+ PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER)) {
writel(
MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
&instance->reg_set->doorbell);
@@ -2674,7 +2692,9 @@ megasas_transition_to_ready(struct megasas_instance* instance)
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
(instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION)) {
+ PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER)) {
writel(MFI_INIT_HOTPLUG,
&instance->reg_set->doorbell);
} else
@@ -2695,11 +2715,15 @@ megasas_transition_to_ready(struct megasas_instance* instance)
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
(instance->pdev->device
- == PCI_DEVICE_ID_LSI_FUSION)) {
+ == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device
+ == PCI_DEVICE_ID_LSI_INVADER)) {
writel(MFI_RESET_FLAGS,
&instance->reg_set->doorbell);
- if (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_FUSION) {
+ if ((instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER)) {
for (i = 0; i < (10 * 1000); i += 20) {
if (readl(
&instance->
@@ -2922,6 +2946,10 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
memset(cmd->frame, 0, total_sz);
cmd->frame->io.context = cmd->index;
cmd->frame->io.pad_0 = 0;
+ if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
+ (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
+ (reset_devices))
+ cmd->frame->hdr.cmd = MFI_CMD_INVALID;
}
return 0;
@@ -3474,6 +3502,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
struct megasas_register_set __iomem *reg_set;
struct megasas_ctrl_info *ctrl_info;
unsigned long bar_list;
+ int i;
/* Find first memory bar */
bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
@@ -3496,6 +3525,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
+ case PCI_DEVICE_ID_LSI_INVADER:
instance->instancet = &megasas_instance_template_fusion;
break;
case PCI_DEVICE_ID_LSI_SAS1078R:
@@ -3520,15 +3550,39 @@ static int megasas_init_fw(struct megasas_instance *instance)
/*
* We expect the FW state to be READY
*/
- if (megasas_transition_to_ready(instance))
+ if (megasas_transition_to_ready(instance, 0))
goto fail_ready_state;
/* Check if MSI-X is supported while in ready state */
msix_enable = (instance->instancet->read_fw_status_reg(reg_set) &
0x4000000) >> 0x1a;
- if (msix_enable && !msix_disable &&
- !pci_enable_msix(instance->pdev, &instance->msixentry, 1))
- instance->msi_flag = 1;
+ if (msix_enable && !msix_disable) {
+ /* Check max MSI-X vectors */
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) {
+ instance->msix_vectors = (readl(&instance->reg_set->
+ outbound_scratch_pad_2
+ ) & 0x1F) + 1;
+ } else
+ instance->msix_vectors = 1;
+ /* Don't bother allocating more MSI-X vectors than cpus */
+ instance->msix_vectors = min(instance->msix_vectors,
+ (unsigned int)num_online_cpus());
+ for (i = 0; i < instance->msix_vectors; i++)
+ instance->msixentry[i].entry = i;
+ i = pci_enable_msix(instance->pdev, instance->msixentry,
+ instance->msix_vectors);
+ if (i >= 0) {
+ if (i) {
+ if (!pci_enable_msix(instance->pdev,
+ instance->msixentry, i))
+ instance->msix_vectors = i;
+ else
+ instance->msix_vectors = 0;
+ }
+ } else
+ instance->msix_vectors = 0;
+ }
/* Get operational params, sge flags, send init cmd to controller */
if (instance->instancet->init_adapter(instance))
@@ -3892,7 +3946,8 @@ static int megasas_io_attach(struct megasas_instance *instance)
host->max_cmd_len = 16;
/* Fusion only supports host reset */
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) {
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) {
host->hostt->eh_device_reset_handler = NULL;
host->hostt->eh_bus_reset_handler = NULL;
}
@@ -3942,7 +3997,7 @@ fail_set_dma_mask:
static int __devinit
megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
- int rval, pos;
+ int rval, pos, i, j;
struct Scsi_Host *host;
struct megasas_instance *instance;
u16 control = 0;
@@ -4002,6 +4057,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
+ case PCI_DEVICE_ID_LSI_INVADER:
{
struct fusion_context *fusion;
@@ -4094,7 +4150,8 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance->last_time = 0;
instance->disableOnlineCtrlReset = 1;
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER))
INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq);
else
INIT_WORK(&instance->work_init, process_fw_state_change_wq);
@@ -4108,11 +4165,32 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/*
* Register IRQ
*/
- if (request_irq(instance->msi_flag ? instance->msixentry.vector :
- pdev->irq, instance->instancet->service_isr,
- IRQF_SHARED, "megasas", instance)) {
- printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
- goto fail_irq;
+ if (instance->msix_vectors) {
+ for (i = 0 ; i < instance->msix_vectors; i++) {
+ instance->irq_context[i].instance = instance;
+ instance->irq_context[i].MSIxIndex = i;
+ if (request_irq(instance->msixentry[i].vector,
+ instance->instancet->service_isr, 0,
+ "megasas",
+ &instance->irq_context[i])) {
+ printk(KERN_DEBUG "megasas: Failed to "
+ "register IRQ for vector %d.\n", i);
+ for (j = 0 ; j < i ; j++)
+ free_irq(
+ instance->msixentry[j].vector,
+ &instance->irq_context[j]);
+ goto fail_irq;
+ }
+ }
+ } else {
+ instance->irq_context[0].instance = instance;
+ instance->irq_context[0].MSIxIndex = 0;
+ if (request_irq(pdev->irq, instance->instancet->service_isr,
+ IRQF_SHARED, "megasas",
+ &instance->irq_context[0])) {
+ printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
+ goto fail_irq;
+ }
}
instance->instancet->enable_intr(instance->reg_set);
@@ -4156,15 +4234,20 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, NULL);
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->msi_flag ? instance->msixentry.vector :
- instance->pdev->irq, instance);
+ if (instance->msix_vectors)
+ for (i = 0 ; i < instance->msix_vectors; i++)
+ free_irq(instance->msixentry[i].vector,
+ &instance->irq_context[i]);
+ else
+ free_irq(instance->pdev->irq, &instance->irq_context[0]);
fail_irq:
- if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER))
megasas_release_fusion(instance);
else
megasas_release_mfi(instance);
fail_init_mfi:
- if (instance->msi_flag)
+ if (instance->msix_vectors)
pci_disable_msix(instance->pdev);
fail_alloc_dma_buf:
if (instance->evt_detail)
@@ -4280,6 +4363,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct Scsi_Host *host;
struct megasas_instance *instance;
+ int i;
instance = pci_get_drvdata(pdev);
host = instance->host;
@@ -4303,9 +4387,14 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
pci_set_drvdata(instance->pdev, instance);
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->msi_flag ? instance->msixentry.vector :
- instance->pdev->irq, instance);
- if (instance->msi_flag)
+
+ if (instance->msix_vectors)
+ for (i = 0 ; i < instance->msix_vectors; i++)
+ free_irq(instance->msixentry[i].vector,
+ &instance->irq_context[i]);
+ else
+ free_irq(instance->pdev->irq, &instance->irq_context[0]);
+ if (instance->msix_vectors)
pci_disable_msix(instance->pdev);
pci_save_state(pdev);
@@ -4323,7 +4412,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
static int
megasas_resume(struct pci_dev *pdev)
{
- int rval;
+ int rval, i, j;
struct Scsi_Host *host;
struct megasas_instance *instance;
@@ -4357,15 +4446,17 @@ megasas_resume(struct pci_dev *pdev)
/*
* We expect the FW state to be READY
*/
- if (megasas_transition_to_ready(instance))
+ if (megasas_transition_to_ready(instance, 0))
goto fail_ready_state;
/* Now re-enable MSI-X */
- if (instance->msi_flag)
- pci_enable_msix(instance->pdev, &instance->msixentry, 1);
+ if (instance->msix_vectors)
+ pci_enable_msix(instance->pdev, instance->msixentry,
+ instance->msix_vectors);
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
+ case PCI_DEVICE_ID_LSI_INVADER:
{
megasas_reset_reply_desc(instance);
if (megasas_ioc_init_fusion(instance)) {
@@ -4391,11 +4482,32 @@ megasas_resume(struct pci_dev *pdev)
/*
* Register IRQ
*/
- if (request_irq(instance->msi_flag ? instance->msixentry.vector :
- pdev->irq, instance->instancet->service_isr,
- IRQF_SHARED, "megasas", instance)) {
- printk(KERN_ERR "megasas: Failed to register IRQ\n");
- goto fail_irq;
+ if (instance->msix_vectors) {
+ for (i = 0 ; i < instance->msix_vectors; i++) {
+ instance->irq_context[i].instance = instance;
+ instance->irq_context[i].MSIxIndex = i;
+ if (request_irq(instance->msixentry[i].vector,
+ instance->instancet->service_isr, 0,
+ "megasas",
+ &instance->irq_context[i])) {
+ printk(KERN_DEBUG "megasas: Failed to "
+ "register IRQ for vector %d.\n", i);
+ for (j = 0 ; j < i ; j++)
+ free_irq(
+ instance->msixentry[j].vector,
+ &instance->irq_context[j]);
+ goto fail_irq;
+ }
+ }
+ } else {
+ instance->irq_context[0].instance = instance;
+ instance->irq_context[0].MSIxIndex = 0;
+ if (request_irq(pdev->irq, instance->instancet->service_isr,
+ IRQF_SHARED, "megasas",
+ &instance->irq_context[0])) {
+ printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
+ goto fail_irq;
+ }
}
instance->instancet->enable_intr(instance->reg_set);
@@ -4492,13 +4604,18 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->msi_flag ? instance->msixentry.vector :
- instance->pdev->irq, instance);
- if (instance->msi_flag)
+ if (instance->msix_vectors)
+ for (i = 0 ; i < instance->msix_vectors; i++)
+ free_irq(instance->msixentry[i].vector,
+ &instance->irq_context[i]);
+ else
+ free_irq(instance->pdev->irq, &instance->irq_context[0]);
+ if (instance->msix_vectors)
pci_disable_msix(instance->pdev);
switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION:
+ case PCI_DEVICE_ID_LSI_INVADER:
megasas_release_fusion(instance);
for (i = 0; i < 2 ; i++)
if (fusion->ld_map[i])
@@ -4539,14 +4656,20 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
*/
static void megasas_shutdown(struct pci_dev *pdev)
{
+ int i;
struct megasas_instance *instance = pci_get_drvdata(pdev);
+
instance->unload = 1;
megasas_flush_cache(instance);
megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->msi_flag ? instance->msixentry.vector :
- instance->pdev->irq, instance);
- if (instance->msi_flag)
+ if (instance->msix_vectors)
+ for (i = 0 ; i < instance->msix_vectors; i++)
+ free_irq(instance->msixentry[i].vector,
+ &instance->irq_context[i]);
+ else
+ free_irq(instance->pdev->irq, &instance->irq_context[0]);
+ if (instance->msix_vectors)
pci_disable_msix(instance->pdev);
}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 5a5af1fe7581..5255dd688aca 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -52,6 +52,7 @@
#include <scsi/scsi_host.h>
#include "megaraid_sas_fusion.h"
+#include "megaraid_sas.h"
#include <asm/div64.h>
#define ABS_DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
@@ -226,8 +227,9 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
* span - Span number
* block - Absolute Block number in the physical disk
*/
-u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
- u16 *pDevHandle, struct RAID_CONTEXT *pRAID_Context,
+u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
+ u16 stripRef, u64 *pdBlock, u16 *pDevHandle,
+ struct RAID_CONTEXT *pRAID_Context,
struct MR_FW_RAID_MAP_ALL *map)
{
struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
@@ -279,7 +281,8 @@ u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
*pDevHandle = MR_PdDevHandleGet(pd, map);
else {
*pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
- if (raid->level >= 5)
+ if ((raid->level >= 5) &&
+ (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER))
pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
else if (raid->level == 1) {
/* Get alternate Pd. */
@@ -306,7 +309,8 @@ u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
* This function will return 0 if region lock was acquired OR return num strips
*/
u8
-MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
+MR_BuildRaidContext(struct megasas_instance *instance,
+ struct IO_REQUEST_INFO *io_info,
struct RAID_CONTEXT *pRAID_Context,
struct MR_FW_RAID_MAP_ALL *map)
{
@@ -394,8 +398,12 @@ MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
}
pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec;
- pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ :
- raid->regTypeReqOnWrite;
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)
+ pRAID_Context->regLockFlags = (isRead) ?
+ raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
+ else
+ pRAID_Context->regLockFlags = (isRead) ?
+ REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite;
pRAID_Context->VirtualDiskTgtId = raid->targetId;
pRAID_Context->regLockRowLBA = regStart;
pRAID_Context->regLockLength = regSize;
@@ -404,7 +412,8 @@ MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
/*Get Phy Params only if FP capable, or else leave it to MR firmware
to do the calculation.*/
if (io_info->fpOkForIo) {
- retval = MR_GetPhyParams(ld, start_strip, ref_in_start_stripe,
+ retval = MR_GetPhyParams(instance, ld, start_strip,
+ ref_in_start_stripe,
&io_info->pdBlock,
&io_info->devHandle, pRAID_Context,
map);
@@ -415,7 +424,8 @@ MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
} else if (isRead) {
uint stripIdx;
for (stripIdx = 0; stripIdx < num_strips; stripIdx++) {
- if (!MR_GetPhyParams(ld, start_strip + stripIdx,
+ if (!MR_GetPhyParams(instance, ld,
+ start_strip + stripIdx,
ref_in_start_stripe,
&io_info->pdBlock,
&io_info->devHandle,
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index f13e7abd345a..bfd87fab39aa 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -74,7 +74,8 @@ megasas_issue_polled(struct megasas_instance *instance,
struct megasas_cmd *cmd);
u8
-MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
+MR_BuildRaidContext(struct megasas_instance *instance,
+ struct IO_REQUEST_INFO *io_info,
struct RAID_CONTEXT *pRAID_Context,
struct MR_FW_RAID_MAP_ALL *map);
u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
@@ -89,7 +90,7 @@ u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
struct LD_LOAD_BALANCE_INFO *lbInfo);
u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
struct IO_REQUEST_INFO *in_info);
-int megasas_transition_to_ready(struct megasas_instance *instance);
+int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
void megaraid_sas_kill_hba(struct megasas_instance *instance);
extern u32 megasas_dbg_lvl;
@@ -101,6 +102,10 @@ extern u32 megasas_dbg_lvl;
void
megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
{
+ /* For Thunderbolt/Invader also clear intr on enable */
+ writel(~0, &regs->outbound_intr_status);
+ readl(&regs->outbound_intr_status);
+
writel(~MFI_FUSION_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
/* Dummy readl to force pci flush */
@@ -139,11 +144,6 @@ megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs)
if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
return 0;
- /*
- * dummy read to flush PCI
- */
- readl(&regs->outbound_intr_status);
-
return 1;
}
@@ -385,7 +385,7 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance)
int
megasas_alloc_cmds_fusion(struct megasas_instance *instance)
{
- int i, j;
+ int i, j, count;
u32 max_cmd, io_frames_sz;
struct fusion_context *fusion;
struct megasas_cmd_fusion *cmd;
@@ -409,9 +409,10 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance)
goto fail_req_desc;
}
+ count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
fusion->reply_frames_desc_pool =
pci_pool_create("reply_frames pool", instance->pdev,
- fusion->reply_alloc_sz, 16, 0);
+ fusion->reply_alloc_sz * count, 16, 0);
if (!fusion->reply_frames_desc_pool) {
printk(KERN_ERR "megasas; Could not allocate memory for "
@@ -430,7 +431,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance)
}
reply_desc = fusion->reply_frames_desc;
- for (i = 0; i < fusion->reply_q_depth; i++, reply_desc++)
+ for (i = 0; i < fusion->reply_q_depth * count; i++, reply_desc++)
reply_desc->Words = ULLONG_MAX;
io_frames_sz = fusion->io_frames_alloc_sz;
@@ -590,7 +591,6 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
struct megasas_init_frame *init_frame;
struct MPI2_IOC_INIT_REQUEST *IOCInitMessage;
dma_addr_t ioc_init_handle;
- u32 context;
struct megasas_cmd *cmd;
u8 ret;
struct fusion_context *fusion;
@@ -634,14 +634,13 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
fusion->reply_frames_desc_phys;
IOCInitMessage->SystemRequestFrameBaseAddress =
fusion->io_request_frames_phys;
-
+ /* Set to 0 for none or 1 MSI-X vectors */
+ IOCInitMessage->HostMSIxVectors = (instance->msix_vectors > 0 ?
+ instance->msix_vectors : 0);
init_frame = (struct megasas_init_frame *)cmd->frame;
memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
frame_hdr = &cmd->frame->hdr;
- context = init_frame->context;
- init_frame->context = context;
-
frame_hdr->cmd_status = 0xFF;
frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
@@ -881,7 +880,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
struct megasas_register_set __iomem *reg_set;
struct fusion_context *fusion;
u32 max_cmd;
- int i = 0;
+ int i = 0, count;
fusion = instance->ctrl_context;
@@ -933,7 +932,9 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
sizeof(union MPI2_SGE_IO_UNION))/16;
- fusion->last_reply_idx = 0;
+ count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
+ for (i = 0 ; i < count; i++)
+ fusion->last_reply_idx[i] = 0;
/*
* Allocate memory for descriptors
@@ -1043,7 +1044,9 @@ map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status)
case MFI_STAT_DEVICE_NOT_FOUND:
cmd->scmd->result = DID_BAD_TARGET << 16;
break;
-
+ case MFI_STAT_CONFIG_SEQ_MISMATCH:
+ cmd->scmd->result = DID_IMM_RETRY << 16;
+ break;
default:
printk(KERN_DEBUG "megasas: FW status %#x\n", status);
cmd->scmd->result = DID_ERROR << 16;
@@ -1066,14 +1069,17 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr,
struct megasas_cmd_fusion *cmd)
{
- int i, sg_processed;
- int sge_count, sge_idx;
+ int i, sg_processed, sge_count;
struct scatterlist *os_sgl;
struct fusion_context *fusion;
fusion = instance->ctrl_context;
- cmd->io_request->ChainOffset = 0;
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr;
+ sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
+ sgl_ptr_end->Flags = 0;
+ }
sge_count = scsi_dma_map(scp);
@@ -1082,16 +1088,14 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
if (sge_count > instance->max_num_sge || !sge_count)
return sge_count;
- if (sge_count > fusion->max_sge_in_main_msg) {
- /* One element to store the chain info */
- sge_idx = fusion->max_sge_in_main_msg - 1;
- } else
- sge_idx = sge_count;
-
scsi_for_each_sg(scp, os_sgl, sge_count, i) {
sgl_ptr->Length = sg_dma_len(os_sgl);
sgl_ptr->Address = sg_dma_address(os_sgl);
sgl_ptr->Flags = 0;
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if (i == sge_count - 1)
+ sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
+ }
sgl_ptr++;
sg_processed = i + 1;
@@ -1100,13 +1104,30 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
(sge_count > fusion->max_sge_in_main_msg)) {
struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
- cmd->io_request->ChainOffset =
- fusion->chain_offset_io_request;
+ if (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER) {
+ if ((cmd->io_request->IoFlags &
+ MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) !=
+ MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
+ cmd->io_request->ChainOffset =
+ fusion->
+ chain_offset_io_request;
+ else
+ cmd->io_request->ChainOffset = 0;
+ } else
+ cmd->io_request->ChainOffset =
+ fusion->chain_offset_io_request;
+
sg_chain = sgl_ptr;
/* Prepare chain element */
sg_chain->NextChainOffset = 0;
- sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
- MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
+ if (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_INVADER)
+ sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
+ else
+ sg_chain->Flags =
+ (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+ MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
sg_chain->Length = (sizeof(union MPI2_SGE_IO_UNION)
*(sge_count - sg_processed));
sg_chain->Address = cmd->sg_frame_phys_addr;
@@ -1399,11 +1420,18 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
io_request->RaidContext.regLockFlags = 0;
fp_possible = 0;
} else {
- if (MR_BuildRaidContext(&io_info, &io_request->RaidContext,
+ if (MR_BuildRaidContext(instance, &io_info,
+ &io_request->RaidContext,
local_map_ptr))
fp_possible = io_info.fpOkForIo;
}
+ /* Use smp_processor_id() for now until cmd->request->cpu is CPU
+ id by default, not CPU group id, otherwise all MSI-X queues won't
+ be utilized */
+ cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ?
+ smp_processor_id() % instance->msix_vectors : 0;
+
if (fp_possible) {
megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
local_map_ptr, start_lba_lo);
@@ -1412,6 +1440,20 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
cmd->request_desc->SCSIIO.RequestFlags =
(MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
<< MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if (io_request->RaidContext.regLockFlags ==
+ REGION_TYPE_UNUSED)
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
+ MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ io_request->RaidContext.Type = MPI2_TYPE_CUDA;
+ io_request->RaidContext.nseg = 0x1;
+ io_request->IoFlags |=
+ MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
+ io_request->RaidContext.regLockFlags |=
+ (MR_RL_FLAGS_GRANT_DESTINATION_CUDA |
+ MR_RL_FLAGS_SEQ_NUM_ENABLE);
+ }
if ((fusion->load_balance_info[device_id].loadBalanceFlag) &&
(io_info.isRead)) {
io_info.devHandle =
@@ -1426,11 +1468,23 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
} else {
io_request->RaidContext.timeoutValue =
local_map_ptr->raidMap.fpPdIoTimeoutSec;
- io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
- io_request->DevHandle = device_id;
cmd->request_desc->SCSIIO.RequestFlags =
(MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
<< MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ if (io_request->RaidContext.regLockFlags ==
+ REGION_TYPE_UNUSED)
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
+ MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ io_request->RaidContext.Type = MPI2_TYPE_CUDA;
+ io_request->RaidContext.regLockFlags |=
+ (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 |
+ MR_RL_FLAGS_SEQ_NUM_ENABLE);
+ io_request->RaidContext.nseg = 0x1;
+ }
+ io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
+ io_request->DevHandle = device_id;
} /* Not FP */
}
@@ -1513,8 +1567,10 @@ megasas_build_io_fusion(struct megasas_instance *instance,
io_request->EEDPFlags = 0;
io_request->Control = 0;
io_request->EEDPBlockSize = 0;
- io_request->IoFlags = 0;
+ io_request->ChainOffset = 0;
io_request->RaidContext.RAIDFlags = 0;
+ io_request->RaidContext.Type = 0;
+ io_request->RaidContext.nseg = 0;
memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len);
/*
@@ -1612,7 +1668,6 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
req_desc->Words = 0;
cmd->request_desc = req_desc;
- cmd->request_desc->Words = 0;
if (megasas_build_io_fusion(instance, scmd, cmd)) {
megasas_return_cmd_fusion(instance, cmd);
@@ -1647,7 +1702,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
* Completes all commands that is in reply descriptor queue
*/
int
-complete_cmd_fusion(struct megasas_instance *instance)
+complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
{
union MPI2_REPLY_DESCRIPTORS_UNION *desc;
struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
@@ -1667,7 +1722,9 @@ complete_cmd_fusion(struct megasas_instance *instance)
return IRQ_HANDLED;
desc = fusion->reply_frames_desc;
- desc += fusion->last_reply_idx;
+ desc += ((MSIxIndex * fusion->reply_alloc_sz)/
+ sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)) +
+ fusion->last_reply_idx[MSIxIndex];
reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
@@ -1740,16 +1797,19 @@ complete_cmd_fusion(struct megasas_instance *instance)
break;
}
- fusion->last_reply_idx++;
- if (fusion->last_reply_idx >= fusion->reply_q_depth)
- fusion->last_reply_idx = 0;
+ fusion->last_reply_idx[MSIxIndex]++;
+ if (fusion->last_reply_idx[MSIxIndex] >=
+ fusion->reply_q_depth)
+ fusion->last_reply_idx[MSIxIndex] = 0;
desc->Words = ULLONG_MAX;
num_completed++;
/* Get the next reply descriptor */
- if (!fusion->last_reply_idx)
- desc = fusion->reply_frames_desc;
+ if (!fusion->last_reply_idx[MSIxIndex])
+ desc = fusion->reply_frames_desc +
+ ((MSIxIndex * fusion->reply_alloc_sz)/
+ sizeof(union MPI2_REPLY_DESCRIPTORS_UNION));
else
desc++;
@@ -1769,7 +1829,7 @@ complete_cmd_fusion(struct megasas_instance *instance)
return IRQ_NONE;
wmb();
- writel(fusion->last_reply_idx,
+ writel((MSIxIndex << 24) | fusion->last_reply_idx[MSIxIndex],
&instance->reg_set->reply_post_host_index);
megasas_check_and_restore_queue_depth(instance);
return IRQ_HANDLED;
@@ -1787,6 +1847,9 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
struct megasas_instance *instance =
(struct megasas_instance *)instance_addr;
unsigned long flags;
+ u32 count, MSIxIndex;
+
+ count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
/* If we have already declared adapter dead, donot complete cmds */
spin_lock_irqsave(&instance->hba_lock, flags);
@@ -1797,7 +1860,8 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
spin_unlock_irqrestore(&instance->hba_lock, flags);
spin_lock_irqsave(&instance->completion_lock, flags);
- complete_cmd_fusion(instance);
+ for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
+ complete_cmd_fusion(instance, MSIxIndex);
spin_unlock_irqrestore(&instance->completion_lock, flags);
}
@@ -1806,20 +1870,24 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
*/
irqreturn_t megasas_isr_fusion(int irq, void *devp)
{
- struct megasas_instance *instance = (struct megasas_instance *)devp;
+ struct megasas_irq_context *irq_context = devp;
+ struct megasas_instance *instance = irq_context->instance;
u32 mfiStatus, fw_state;
- if (!instance->msi_flag) {
+ if (!instance->msix_vectors) {
mfiStatus = instance->instancet->clear_intr(instance->reg_set);
if (!mfiStatus)
return IRQ_NONE;
}
/* If we are resetting, bail */
- if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags))
+ if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) {
+ instance->instancet->clear_intr(instance->reg_set);
return IRQ_HANDLED;
+ }
- if (!complete_cmd_fusion(instance)) {
+ if (!complete_cmd_fusion(instance, irq_context->MSIxIndex)) {
+ instance->instancet->clear_intr(instance->reg_set);
/* If we didn't complete any commands, check for FW fault */
fw_state = instance->instancet->read_fw_status_reg(
instance->reg_set) & MFI_STATE_MASK;
@@ -1866,6 +1934,14 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
fusion = instance->ctrl_context;
io_req = cmd->io_request;
+
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) {
+ struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end =
+ (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL;
+ sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
+ sgl_ptr_end->Flags = 0;
+ }
+
mpi25_ieee_chain =
(struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
@@ -1928,15 +2004,12 @@ megasas_issue_dcmd_fusion(struct megasas_instance *instance,
struct megasas_cmd *cmd)
{
union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
- union desc_value d_val;
req_desc = build_mpt_cmd(instance, cmd);
if (!req_desc) {
printk(KERN_ERR "Couldn't issue MFI pass thru cmd\n");
return;
}
- d_val.word = req_desc->Words;
-
instance->instancet->fire_cmd(instance, req_desc->u.low,
req_desc->u.high, instance->reg_set);
}
@@ -2029,14 +2102,16 @@ out:
void megasas_reset_reply_desc(struct megasas_instance *instance)
{
- int i;
+ int i, count;
struct fusion_context *fusion;
union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
fusion = instance->ctrl_context;
- fusion->last_reply_idx = 0;
+ count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
+ for (i = 0 ; i < count ; i++)
+ fusion->last_reply_idx[i] = 0;
reply_desc = fusion->reply_frames_desc;
- for (i = 0 ; i < fusion->reply_q_depth; i++, reply_desc++)
+ for (i = 0 ; i < fusion->reply_q_depth * count; i++, reply_desc++)
reply_desc->Words = ULLONG_MAX;
}
@@ -2057,8 +2132,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
printk(KERN_WARNING "megaraid_sas: Hardware critical error, "
"returning FAILED.\n");
- retval = FAILED;
- goto out;
+ return FAILED;
}
mutex_lock(&instance->reset_mutex);
@@ -2173,7 +2247,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
}
/* Wait for FW to become ready */
- if (megasas_transition_to_ready(instance)) {
+ if (megasas_transition_to_ready(instance, 1)) {
printk(KERN_WARNING "megaraid_sas: Failed to "
"transition controller to ready.\n");
continue;
@@ -2186,6 +2260,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
continue;
}
+ clear_bit(MEGASAS_FUSION_IN_RESET,
+ &instance->reset_flags);
instance->instancet->enable_intr(instance->reg_set);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
@@ -2247,6 +2323,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
megaraid_sas_kill_hba(instance);
retval = FAILED;
} else {
+ clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
instance->instancet->enable_intr(instance->reg_set);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
index 82b577a72c8b..088c9f91da95 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -43,6 +43,15 @@
#define HOST_DIAG_WRITE_ENABLE 0x80
#define HOST_DIAG_RESET_ADAPTER 0x4
#define MEGASAS_FUSION_MAX_RESET_TRIES 3
+#define MAX_MSIX_QUEUES_FUSION 16
+
+/* Invader defines */
+#define MPI2_TYPE_CUDA 0x2
+#define MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH 0x4000
+#define MR_RL_FLAGS_GRANT_DESTINATION_CPU0 0x00
+#define MR_RL_FLAGS_GRANT_DESTINATION_CPU1 0x10
+#define MR_RL_FLAGS_GRANT_DESTINATION_CUDA 0x80
+#define MR_RL_FLAGS_SEQ_NUM_ENABLE 0x8
/* T10 PI defines */
#define MR_PROT_INFO_TYPE_CONTROLLER 0x8
@@ -70,7 +79,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
*/
#define MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO 0x7
#define MEGASAS_REQ_DESCRIPT_FLAGS_MFA 0x1
-
+#define MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK 0x2
#define MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT 1
#define MEGASAS_FP_CMD_LEN 16
@@ -82,7 +91,9 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
*/
struct RAID_CONTEXT {
- u16 resvd0;
+ u8 Type:4;
+ u8 nseg:4;
+ u8 resvd0;
u16 timeoutValue;
u8 regLockFlags;
u8 resvd1;
@@ -527,7 +538,7 @@ struct MR_LD_RAID {
u8 ldState;
u8 regTypeReqOnWrite;
u8 modFactor;
- u8 reserved2[1];
+ u8 regTypeReqOnRead;
u16 seqNum;
struct {
@@ -663,7 +674,7 @@ struct fusion_context {
union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc;
struct dma_pool *reply_frames_desc_pool;
- u16 last_reply_idx;
+ u16 last_reply_idx[MAX_MSIX_QUEUES_FUSION];
u32 reply_q_depth;
u32 request_alloc_sz;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 83035bd1c489..81209ca87274 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -42,7 +42,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -834,25 +833,31 @@ union reply_descriptor {
static irqreturn_t
_base_interrupt(int irq, void *bus_id)
{
+ struct adapter_reply_queue *reply_q = bus_id;
union reply_descriptor rd;
u32 completed_cmds;
u8 request_desript_type;
u16 smid;
u8 cb_idx;
u32 reply;
- u8 msix_index;
- struct MPT2SAS_ADAPTER *ioc = bus_id;
+ u8 msix_index = reply_q->msix_index;
+ struct MPT2SAS_ADAPTER *ioc = reply_q->ioc;
Mpi2ReplyDescriptorsUnion_t *rpf;
u8 rc;
if (ioc->mask_interrupts)
return IRQ_NONE;
- rpf = &ioc->reply_post_free[ioc->reply_post_host_index];
+ if (!atomic_add_unless(&reply_q->busy, 1, 1))
+ return IRQ_NONE;
+
+ rpf = &reply_q->reply_post_free[reply_q->reply_post_host_index];
request_desript_type = rpf->Default.ReplyFlags
& MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
- if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+ if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) {
+ atomic_dec(&reply_q->busy);
return IRQ_NONE;
+ }
completed_cmds = 0;
cb_idx = 0xFF;
@@ -861,9 +866,7 @@ _base_interrupt(int irq, void *bus_id)
if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
goto out;
reply = 0;
- cb_idx = 0xFF;
smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1);
- msix_index = rpf->Default.MSIxIndex;
if (request_desript_type ==
MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
reply = le32_to_cpu
@@ -907,32 +910,86 @@ _base_interrupt(int irq, void *bus_id)
next:
rpf->Words = cpu_to_le64(ULLONG_MAX);
- ioc->reply_post_host_index = (ioc->reply_post_host_index ==
+ reply_q->reply_post_host_index =
+ (reply_q->reply_post_host_index ==
(ioc->reply_post_queue_depth - 1)) ? 0 :
- ioc->reply_post_host_index + 1;
+ reply_q->reply_post_host_index + 1;
request_desript_type =
- ioc->reply_post_free[ioc->reply_post_host_index].Default.
- ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+ reply_q->reply_post_free[reply_q->reply_post_host_index].
+ Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
completed_cmds++;
if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
goto out;
- if (!ioc->reply_post_host_index)
- rpf = ioc->reply_post_free;
+ if (!reply_q->reply_post_host_index)
+ rpf = reply_q->reply_post_free;
else
rpf++;
} while (1);
out:
- if (!completed_cmds)
+ if (!completed_cmds) {
+ atomic_dec(&reply_q->busy);
return IRQ_NONE;
-
+ }
wmb();
- writel(ioc->reply_post_host_index, &ioc->chip->ReplyPostHostIndex);
+ if (ioc->is_warpdrive) {
+ writel(reply_q->reply_post_host_index,
+ ioc->reply_post_host_index[msix_index]);
+ atomic_dec(&reply_q->busy);
+ return IRQ_HANDLED;
+ }
+ writel(reply_q->reply_post_host_index | (msix_index <<
+ MPI2_RPHI_MSIX_INDEX_SHIFT), &ioc->chip->ReplyPostHostIndex);
+ atomic_dec(&reply_q->busy);
return IRQ_HANDLED;
}
/**
+ * _base_is_controller_msix_enabled - is controller support muli-reply queues
+ * @ioc: per adapter object
+ *
+ */
+static inline int
+_base_is_controller_msix_enabled(struct MPT2SAS_ADAPTER *ioc)
+{
+ return (ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable;
+}
+
+/**
+ * mpt2sas_base_flush_reply_queues - flushing the MSIX reply queues
+ * @ioc: per adapter object
+ * Context: ISR conext
+ *
+ * Called when a Task Management request has completed. We want
+ * to flush the other reply queues so all the outstanding IO has been
+ * completed back to OS before we process the TM completetion.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct adapter_reply_queue *reply_q;
+
+ /* If MSIX capability is turned off
+ * then multi-queues are not enabled
+ */
+ if (!_base_is_controller_msix_enabled(ioc))
+ return;
+
+ list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+ if (ioc->shost_recovery)
+ return;
+ /* TMs are on msix_index == 0 */
+ if (reply_q->msix_index == 0)
+ continue;
+ _base_interrupt(reply_q->vector, (void *)reply_q);
+ }
+}
+
+/**
* mpt2sas_base_release_callback_handler - clear interrupt callback handler
* @cb_idx: callback index
*
@@ -1082,74 +1139,171 @@ _base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
}
/**
- * _base_save_msix_table - backup msix vector table
+ * _base_check_enable_msix - checks MSIX capabable.
* @ioc: per adapter object
*
- * This address an errata where diag reset clears out the table
+ * Check to see if card is capable of MSIX, and set number
+ * of available msix vectors
*/
-static void
-_base_save_msix_table(struct MPT2SAS_ADAPTER *ioc)
+static int
+_base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
{
- int i;
+ int base;
+ u16 message_control;
- if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
- return;
- for (i = 0; i < ioc->msix_vector_count; i++)
- ioc->msix_table_backup[i] = ioc->msix_table[i];
+ base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
+ if (!base) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
+ "supported\n", ioc->name));
+ return -EINVAL;
+ }
+
+ /* get msix vector count */
+ /* NUMA_IO not supported for older controllers */
+ if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2004 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_1 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_2 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_3 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_1 ||
+ ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_2)
+ ioc->msix_vector_count = 1;
+ else {
+ pci_read_config_word(ioc->pdev, base + 2, &message_control);
+ ioc->msix_vector_count = (message_control & 0x3FF) + 1;
+ }
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
+ "vector_count(%d)\n", ioc->name, ioc->msix_vector_count));
+
+ return 0;
}
/**
- * _base_restore_msix_table - this restores the msix vector table
+ * _base_free_irq - free irq
* @ioc: per adapter object
*
+ * Freeing respective reply_queue from the list.
*/
static void
-_base_restore_msix_table(struct MPT2SAS_ADAPTER *ioc)
+_base_free_irq(struct MPT2SAS_ADAPTER *ioc)
{
- int i;
+ struct adapter_reply_queue *reply_q, *next;
- if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
+ if (list_empty(&ioc->reply_queue_list))
return;
- for (i = 0; i < ioc->msix_vector_count; i++)
- ioc->msix_table[i] = ioc->msix_table_backup[i];
+ list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) {
+ list_del(&reply_q->list);
+ synchronize_irq(reply_q->vector);
+ free_irq(reply_q->vector, reply_q);
+ kfree(reply_q);
+ }
}
/**
- * _base_check_enable_msix - checks MSIX capabable.
+ * _base_request_irq - request irq
* @ioc: per adapter object
+ * @index: msix index into vector table
+ * @vector: irq vector
*
- * Check to see if card is capable of MSIX, and set number
- * of available msix vectors
+ * Inserting respective reply_queue into the list.
*/
static int
-_base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
+_base_request_irq(struct MPT2SAS_ADAPTER *ioc, u8 index, u32 vector)
{
- int base;
- u16 message_control;
- u32 msix_table_offset;
+ struct adapter_reply_queue *reply_q;
+ int r;
- base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
- if (!base) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
- "supported\n", ioc->name));
- return -EINVAL;
+ reply_q = kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL);
+ if (!reply_q) {
+ printk(MPT2SAS_ERR_FMT "unable to allocate memory %d!\n",
+ ioc->name, (int)sizeof(struct adapter_reply_queue));
+ return -ENOMEM;
+ }
+ reply_q->ioc = ioc;
+ reply_q->msix_index = index;
+ reply_q->vector = vector;
+ atomic_set(&reply_q->busy, 0);
+ if (ioc->msix_enable)
+ snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
+ MPT2SAS_DRIVER_NAME, ioc->id, index);
+ else
+ snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d",
+ MPT2SAS_DRIVER_NAME, ioc->id);
+ r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name,
+ reply_q);
+ if (r) {
+ printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
+ reply_q->name, vector);
+ kfree(reply_q);
+ return -EBUSY;
}
- /* get msix vector count */
- pci_read_config_word(ioc->pdev, base + 2, &message_control);
- ioc->msix_vector_count = (message_control & 0x3FF) + 1;
+ INIT_LIST_HEAD(&reply_q->list);
+ list_add_tail(&reply_q->list, &ioc->reply_queue_list);
+ return 0;
+}
- /* get msix table */
- pci_read_config_dword(ioc->pdev, base + 4, &msix_table_offset);
- msix_table_offset &= 0xFFFFFFF8;
- ioc->msix_table = (u32 *)((void *)ioc->chip + msix_table_offset);
+/**
+ * _base_assign_reply_queues - assigning msix index for each cpu
+ * @ioc: per adapter object
+ *
+ * The enduser would need to set the affinity via /proc/irq/#/smp_affinity
+ *
+ * It would nice if we could call irq_set_affinity, however it is not
+ * an exported symbol
+ */
+static void
+_base_assign_reply_queues(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct adapter_reply_queue *reply_q;
+ int cpu_id;
+ int cpu_grouping, loop, grouping, grouping_mod;
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
- "vector_count(%d), table_offset(0x%08x), table(%p)\n", ioc->name,
- ioc->msix_vector_count, msix_table_offset, ioc->msix_table));
- return 0;
+ if (!_base_is_controller_msix_enabled(ioc))
+ return;
+
+ memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
+ /* when there are more cpus than available msix vectors,
+ * then group cpus togeather on same irq
+ */
+ if (ioc->cpu_count > ioc->msix_vector_count) {
+ grouping = ioc->cpu_count / ioc->msix_vector_count;
+ grouping_mod = ioc->cpu_count % ioc->msix_vector_count;
+ if (grouping < 2 || (grouping == 2 && !grouping_mod))
+ cpu_grouping = 2;
+ else if (grouping < 4 || (grouping == 4 && !grouping_mod))
+ cpu_grouping = 4;
+ else if (grouping < 8 || (grouping == 8 && !grouping_mod))
+ cpu_grouping = 8;
+ else
+ cpu_grouping = 16;
+ } else
+ cpu_grouping = 0;
+
+ loop = 0;
+ reply_q = list_entry(ioc->reply_queue_list.next,
+ struct adapter_reply_queue, list);
+ for_each_online_cpu(cpu_id) {
+ if (!cpu_grouping) {
+ ioc->cpu_msix_table[cpu_id] = reply_q->msix_index;
+ reply_q = list_entry(reply_q->list.next,
+ struct adapter_reply_queue, list);
+ } else {
+ if (loop < cpu_grouping) {
+ ioc->cpu_msix_table[cpu_id] =
+ reply_q->msix_index;
+ loop++;
+ } else {
+ reply_q = list_entry(reply_q->list.next,
+ struct adapter_reply_queue, list);
+ ioc->cpu_msix_table[cpu_id] =
+ reply_q->msix_index;
+ loop = 1;
+ }
+ }
+ }
}
/**
@@ -1162,8 +1316,6 @@ _base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
{
if (ioc->msix_enable) {
pci_disable_msix(ioc->pdev);
- kfree(ioc->msix_table_backup);
- ioc->msix_table_backup = NULL;
ioc->msix_enable = 0;
}
}
@@ -1176,10 +1328,13 @@ _base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
static int
_base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
{
- struct msix_entry entries;
+ struct msix_entry *entries, *a;
int r;
+ int i;
u8 try_msix = 0;
+ INIT_LIST_HEAD(&ioc->reply_queue_list);
+
if (msix_disable == -1 || msix_disable == 0)
try_msix = 1;
@@ -1189,51 +1344,48 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
if (_base_check_enable_msix(ioc) != 0)
goto try_ioapic;
- ioc->msix_table_backup = kcalloc(ioc->msix_vector_count,
- sizeof(u32), GFP_KERNEL);
- if (!ioc->msix_table_backup) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for "
- "msix_table_backup failed!!!\n", ioc->name));
+ ioc->reply_queue_count = min_t(u8, ioc->cpu_count,
+ ioc->msix_vector_count);
+
+ entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry),
+ GFP_KERNEL);
+ if (!entries) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "kcalloc "
+ "failed @ at %s:%d/%s() !!!\n", ioc->name, __FILE__,
+ __LINE__, __func__));
goto try_ioapic;
}
- memset(&entries, 0, sizeof(struct msix_entry));
- r = pci_enable_msix(ioc->pdev, &entries, 1);
+ for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++)
+ a->entry = i;
+
+ r = pci_enable_msix(ioc->pdev, entries, ioc->reply_queue_count);
if (r) {
dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix "
"failed (r=%d) !!!\n", ioc->name, r));
+ kfree(entries);
goto try_ioapic;
}
- r = request_irq(entries.vector, _base_interrupt, IRQF_SHARED,
- ioc->name, ioc);
- if (r) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "unable to allocate "
- "interrupt %d !!!\n", ioc->name, entries.vector));
- pci_disable_msix(ioc->pdev);
- goto try_ioapic;
+ ioc->msix_enable = 1;
+ for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) {
+ r = _base_request_irq(ioc, i, a->vector);
+ if (r) {
+ _base_free_irq(ioc);
+ _base_disable_msix(ioc);
+ kfree(entries);
+ goto try_ioapic;
+ }
}
- ioc->pci_irq = entries.vector;
- ioc->msix_enable = 1;
+ kfree(entries);
return 0;
/* failback to io_apic interrupt routing */
try_ioapic:
- r = request_irq(ioc->pdev->irq, _base_interrupt, IRQF_SHARED,
- ioc->name, ioc);
- if (r) {
- printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
- ioc->name, ioc->pdev->irq);
- r = -EBUSY;
- goto out_fail;
- }
+ r = _base_request_irq(ioc, 0, ioc->pdev->irq);
- ioc->pci_irq = ioc->pdev->irq;
- return 0;
-
- out_fail:
return r;
}
@@ -1252,6 +1404,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
int i, r = 0;
u64 pio_chip = 0;
u64 chip_phys = 0;
+ struct adapter_reply_queue *reply_q;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n",
ioc->name, __func__));
@@ -1314,9 +1467,11 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
if (r)
goto out_fail;
- printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
- ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
- "IO-APIC enabled"), ioc->pci_irq);
+ list_for_each_entry(reply_q, &ioc->reply_queue_list, list)
+ printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
+ reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
+ "IO-APIC enabled"), reply_q->vector);
+
printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n",
@@ -1331,7 +1486,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
if (ioc->chip_phys)
iounmap(ioc->chip);
ioc->chip_phys = 0;
- ioc->pci_irq = -1;
pci_release_selected_regions(ioc->pdev, ioc->bars);
pci_disable_pcie_error_reporting(pdev);
pci_disable_device(pdev);
@@ -1578,6 +1732,12 @@ static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
}
#endif
+static inline u8
+_base_get_msix_index(struct MPT2SAS_ADAPTER *ioc)
+{
+ return ioc->cpu_msix_table[smp_processor_id()];
+}
+
/**
* mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
* @ioc: per adapter object
@@ -1594,7 +1754,7 @@ mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle)
descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
- descriptor.SCSIIO.MSIxIndex = 0; /* TODO */
+ descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc);
descriptor.SCSIIO.SMID = cpu_to_le16(smid);
descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
descriptor.SCSIIO.LMID = 0;
@@ -1618,7 +1778,7 @@ mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid)
descriptor.HighPriority.RequestFlags =
MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
- descriptor.HighPriority.MSIxIndex = 0; /* TODO */
+ descriptor.HighPriority.MSIxIndex = 0;
descriptor.HighPriority.SMID = cpu_to_le16(smid);
descriptor.HighPriority.LMID = 0;
descriptor.HighPriority.Reserved1 = 0;
@@ -1640,7 +1800,7 @@ mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid)
u64 *request = (u64 *)&descriptor;
descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
- descriptor.Default.MSIxIndex = 0; /* TODO */
+ descriptor.Default.MSIxIndex = _base_get_msix_index(ioc);
descriptor.Default.SMID = cpu_to_le16(smid);
descriptor.Default.LMID = 0;
descriptor.Default.DescriptorTypeDependent = 0;
@@ -1665,7 +1825,7 @@ mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
descriptor.SCSITarget.RequestFlags =
MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET;
- descriptor.SCSITarget.MSIxIndex = 0; /* TODO */
+ descriptor.SCSITarget.MSIxIndex = _base_get_msix_index(ioc);
descriptor.SCSITarget.SMID = cpu_to_le16(smid);
descriptor.SCSITarget.LMID = 0;
descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index);
@@ -2172,7 +2332,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
u16 max_sge_elements;
u16 num_of_reply_frames;
u16 chains_needed_per_io;
- u32 sz, total_sz;
+ u32 sz, total_sz, reply_post_free_sz;
u32 retry_sz;
u16 max_request_credit;
int i;
@@ -2499,7 +2659,12 @@ chain_done:
total_sz += sz;
/* reply post queue, 16 byte align */
- sz = ioc->reply_post_queue_depth * sizeof(Mpi2DefaultReplyDescriptor_t);
+ reply_post_free_sz = ioc->reply_post_queue_depth *
+ sizeof(Mpi2DefaultReplyDescriptor_t);
+ if (_base_is_controller_msix_enabled(ioc))
+ sz = reply_post_free_sz * ioc->reply_queue_count;
+ else
+ sz = reply_post_free_sz;
ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
ioc->pdev, sz, 16, 0);
if (!ioc->reply_post_free_dma_pool) {
@@ -3187,6 +3352,7 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
facts->MaxChainDepth = mpi_reply.MaxChainDepth;
facts->WhoInit = mpi_reply.WhoInit;
facts->NumberOfPorts = mpi_reply.NumberOfPorts;
+ facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors;
facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
facts->MaxReplyDescriptorPostQueueDepth =
le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
@@ -3244,7 +3410,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
-
+ if (_base_is_controller_msix_enabled(ioc))
+ mpi_request.HostMSIxVectors = ioc->reply_queue_count;
mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
mpi_request.ReplyDescriptorPostQueueDepth =
cpu_to_le16(ioc->reply_post_queue_depth);
@@ -3513,9 +3680,6 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
u32 hcb_size;
printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name);
-
- _base_save_msix_table(ioc);
-
drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n",
ioc->name));
@@ -3611,7 +3775,6 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
goto out;
}
- _base_restore_msix_table(ioc);
printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name);
return 0;
@@ -3692,6 +3855,9 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
u16 smid;
struct _tr_list *delayed_tr, *delayed_tr_next;
u8 hide_flag;
+ struct adapter_reply_queue *reply_q;
+ long reply_post_free;
+ u32 reply_post_free_sz;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
@@ -3757,19 +3923,43 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
ioc->reply_sz)
ioc->reply_free[i] = cpu_to_le32(reply_address);
+ /* initialize reply queues */
+ _base_assign_reply_queues(ioc);
+
/* initialize Reply Post Free Queue */
- for (i = 0; i < ioc->reply_post_queue_depth; i++)
- ioc->reply_post_free[i].Words = cpu_to_le64(ULLONG_MAX);
+ reply_post_free = (long)ioc->reply_post_free;
+ reply_post_free_sz = ioc->reply_post_queue_depth *
+ sizeof(Mpi2DefaultReplyDescriptor_t);
+ list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+ reply_q->reply_post_host_index = 0;
+ reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *)
+ reply_post_free;
+ for (i = 0; i < ioc->reply_post_queue_depth; i++)
+ reply_q->reply_post_free[i].Words =
+ cpu_to_le64(ULLONG_MAX);
+ if (!_base_is_controller_msix_enabled(ioc))
+ goto skip_init_reply_post_free_queue;
+ reply_post_free += reply_post_free_sz;
+ }
+ skip_init_reply_post_free_queue:
r = _base_send_ioc_init(ioc, sleep_flag);
if (r)
return r;
- /* initialize the index's */
+ /* initialize reply free host index */
ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
- ioc->reply_post_host_index = 0;
writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex);
- writel(0, &ioc->chip->ReplyPostHostIndex);
+
+ /* initialize reply post host index */
+ list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+ writel(reply_q->msix_index << MPI2_RPHI_MSIX_INDEX_SHIFT,
+ &ioc->chip->ReplyPostHostIndex);
+ if (!_base_is_controller_msix_enabled(ioc))
+ goto skip_init_reply_post_host_index;
+ }
+
+ skip_init_reply_post_host_index:
_base_unmask_interrupts(ioc);
r = _base_event_notification(ioc, sleep_flag);
@@ -3820,14 +4010,10 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)
ioc->shost_recovery = 1;
_base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
ioc->shost_recovery = 0;
- if (ioc->pci_irq) {
- synchronize_irq(pdev->irq);
- free_irq(ioc->pci_irq, ioc);
- }
+ _base_free_irq(ioc);
_base_disable_msix(ioc);
if (ioc->chip_phys)
iounmap(ioc->chip);
- ioc->pci_irq = -1;
ioc->chip_phys = 0;
pci_release_selected_regions(ioc->pdev, ioc->bars);
pci_disable_pcie_error_reporting(pdev);
@@ -3845,14 +4031,50 @@ int
mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
{
int r, i;
+ int cpu_id, last_cpu_id = 0;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
+ /* setup cpu_msix_table */
+ ioc->cpu_count = num_online_cpus();
+ for_each_online_cpu(cpu_id)
+ last_cpu_id = cpu_id;
+ ioc->cpu_msix_table_sz = last_cpu_id + 1;
+ ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL);
+ ioc->reply_queue_count = 1;
+ if (!ioc->cpu_msix_table) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for "
+ "cpu_msix_table failed!!!\n", ioc->name));
+ r = -ENOMEM;
+ goto out_free_resources;
+ }
+
+ if (ioc->is_warpdrive) {
+ ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz,
+ sizeof(resource_size_t *), GFP_KERNEL);
+ if (!ioc->reply_post_host_index) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation "
+ "for cpu_msix_table failed!!!\n", ioc->name));
+ r = -ENOMEM;
+ goto out_free_resources;
+ }
+ }
+
r = mpt2sas_base_map_resources(ioc);
if (r)
return r;
+ if (ioc->is_warpdrive) {
+ ioc->reply_post_host_index[0] =
+ (resource_size_t *)&ioc->chip->ReplyPostHostIndex;
+
+ for (i = 1; i < ioc->cpu_msix_table_sz; i++)
+ ioc->reply_post_host_index[i] = (resource_size_t *)
+ ((u8 *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
+ * 4)));
+ }
+
pci_set_drvdata(ioc->pdev, ioc->shost);
r = _base_get_ioc_facts(ioc, CAN_SLEEP);
if (r)
@@ -3973,6 +4195,9 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
mpt2sas_base_free_resources(ioc);
_base_release_memory_pools(ioc);
pci_set_drvdata(ioc->pdev, NULL);
+ kfree(ioc->cpu_msix_table);
+ if (ioc->is_warpdrive)
+ kfree(ioc->reply_post_host_index);
kfree(ioc->pd_handles);
kfree(ioc->tm_cmds.reply);
kfree(ioc->transport_cmds.reply);
@@ -4010,6 +4235,9 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
mpt2sas_base_free_resources(ioc);
_base_release_memory_pools(ioc);
pci_set_drvdata(ioc->pdev, NULL);
+ kfree(ioc->cpu_msix_table);
+ if (ioc->is_warpdrive)
+ kfree(ioc->reply_post_host_index);
kfree(ioc->pd_handles);
kfree(ioc->pfacts);
kfree(ioc->ctl_cmds.reply);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 8d5be2120c63..59354dba68c0 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -69,11 +69,11 @@
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION "09.100.00.00"
+#define MPT2SAS_DRIVER_VERSION "09.100.00.01"
#define MPT2SAS_MAJOR_VERSION 09
#define MPT2SAS_MINOR_VERSION 100
#define MPT2SAS_BUILD_VERSION 00
-#define MPT2SAS_RELEASE_VERSION 00
+#define MPT2SAS_RELEASE_VERSION 01
/*
* Set MPT2SAS_SG_DEPTH value based on user input.
@@ -544,6 +544,28 @@ struct _tr_list {
typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
+/**
+ * struct adapter_reply_queue - the reply queue struct
+ * @ioc: per adapter object
+ * @msix_index: msix index into vector table
+ * @vector: irq vector
+ * @reply_post_host_index: head index in the pool where FW completes IO
+ * @reply_post_free: reply post base virt address
+ * @name: the name registered to request_irq()
+ * @busy: isr is actively processing replies on another cpu
+ * @list: this list
+*/
+struct adapter_reply_queue {
+ struct MPT2SAS_ADAPTER *ioc;
+ u8 msix_index;
+ unsigned int vector;
+ u32 reply_post_host_index;
+ Mpi2ReplyDescriptorsUnion_t *reply_post_free;
+ char name[MPT_NAME_LENGTH];
+ atomic_t busy;
+ struct list_head list;
+};
+
/* IOC Facts and Port Facts converted from little endian to cpu */
union mpi2_version_union {
MPI2_VERSION_STRUCT Struct;
@@ -606,7 +628,7 @@ enum mutex_type {
* @list: ioc_list
* @shost: shost object
* @id: unique adapter id
- * @pci_irq: irq number
+ * @cpu_count: number online cpus
* @name: generic ioc string
* @tmp_string: tmp string used for logging
* @pdev: pci pdev object
@@ -636,8 +658,8 @@ enum mutex_type {
* @wait_for_port_enable_to_complete:
* @msix_enable: flag indicating msix is enabled
* @msix_vector_count: number msix vectors
- * @msix_table: virt address to the msix table
- * @msix_table_backup: backup msix table
+ * @cpu_msix_table: table for mapping cpus to msix index
+ * @cpu_msix_table_sz: table size
* @scsi_io_cb_idx: shost generated commands
* @tm_cb_idx: task management commands
* @scsih_cb_idx: scsih internal commands
@@ -728,7 +750,8 @@ enum mutex_type {
* @reply_post_queue_depth: reply post queue depth
* @reply_post_free: pool for reply post (64bit descriptor)
* @reply_post_free_dma:
- * @reply_post_free_dma_pool:
+ * @reply_queue_count: number of reply queue's
+ * @reply_queue_list: link list contaning the reply queue info
* @reply_post_host_index: head index in the pool where FW completes IO
* @delayed_tr_list: target reset link list
* @delayed_tr_volume_list: volume target reset link list
@@ -737,7 +760,7 @@ struct MPT2SAS_ADAPTER {
struct list_head list;
struct Scsi_Host *shost;
u8 id;
- u32 pci_irq;
+ int cpu_count;
char name[MPT_NAME_LENGTH];
char tmp_string[MPT_STRING_LENGTH];
struct pci_dev *pdev;
@@ -779,8 +802,9 @@ struct MPT2SAS_ADAPTER {
u8 msix_enable;
u16 msix_vector_count;
- u32 *msix_table;
- u32 *msix_table_backup;
+ u8 *cpu_msix_table;
+ resource_size_t **reply_post_host_index;
+ u16 cpu_msix_table_sz;
u32 ioc_reset_count;
/* internal commands, callback index */
@@ -911,7 +935,8 @@ struct MPT2SAS_ADAPTER {
Mpi2ReplyDescriptorsUnion_t *reply_post_free;
dma_addr_t reply_post_free_dma;
struct dma_pool *reply_post_free_dma_pool;
- u32 reply_post_host_index;
+ u8 reply_queue_count;
+ struct list_head reply_queue_list;
struct list_head delayed_tr_list;
struct list_head delayed_tr_volume_list;
@@ -955,6 +980,7 @@ void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid);
void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr);
__le32 mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc,
u16 smid);
+void mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc);
/* hi-priority queue */
u16 mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c
index 6861244249a3..2b1101076cfe 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_config.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_config.c
@@ -41,7 +41,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 38ed0260959d..9adb0133d6fb 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -42,7 +42,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -2705,6 +2704,33 @@ _ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
_ctl_ioc_reset_count_show, NULL);
+/**
+ * _ctl_ioc_reply_queue_count_show - number of reply queues
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is number of reply queues
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_ioc_reply_queue_count_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 reply_queue_count;
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ if ((ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable)
+ reply_queue_count = ioc->reply_queue_count;
+ else
+ reply_queue_count = 1;
+ return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count);
+}
+static DEVICE_ATTR(reply_queue_count, S_IRUGO,
+ _ctl_ioc_reply_queue_count_show, NULL);
+
struct DIAG_BUFFER_START {
__le32 Size;
__le32 DiagVersion;
@@ -2915,6 +2941,7 @@ struct device_attribute *mpt2sas_host_attrs[] = {
&dev_attr_host_trace_buffer_size,
&dev_attr_host_trace_buffer,
&dev_attr_host_trace_buffer_enable,
+ &dev_attr_reply_queue_count,
NULL,
};
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 6abd2fcc43e2..1da1aa1a11e2 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -41,7 +41,6 @@
* USA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -2162,6 +2161,7 @@ _scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
return 1;
if (ioc->tm_cmds.smid != smid)
return 1;
+ mpt2sas_base_flush_reply_queues(ioc);
ioc->tm_cmds.status |= MPT2_CMD_COMPLETE;
mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
if (mpi_reply) {
@@ -7354,6 +7354,7 @@ _scsih_remove(struct pci_dev *pdev)
}
sas_remove_host(shost);
+ mpt2sas_base_detach(ioc);
list_del(&ioc->list);
scsi_remove_host(shost);
scsi_host_put(shost);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index 15c798026217..230732241aa2 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -163,7 +163,7 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
return -EIO;
}
- memset(identify, 0, sizeof(identify));
+ memset(identify, 0, sizeof(*identify));
device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
/* sas_address */
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c
index 3501291618fd..7e423e5ad5e1 100644
--- a/drivers/scsi/mvsas/mv_94xx.c
+++ b/drivers/scsi/mvsas/mv_94xx.c
@@ -398,6 +398,16 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
/* init phys */
mvs_phy_hacks(mvi);
+ /* disable non data frame retry */
+ tmp = mvs_cr32(mvi, CMD_SAS_CTL1);
+ if ((revision == VANIR_A0_REV) ||
+ (revision == VANIR_B0_REV) ||
+ (revision == VANIR_C0_REV)) {
+ tmp &= ~0xffff;
+ tmp |= 0x007f;
+ mvs_cw32(mvi, CMD_SAS_CTL1, tmp);
+ }
+
/* set LED blink when IO*/
mw32(MVS_PA_VSR_ADDR, VSR_PHY_ACT_LED);
tmp = mr32(MVS_PA_VSR_PORT);
@@ -500,6 +510,27 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
tmp |= CINT_PHY_MASK;
mw32(MVS_INT_MASK, tmp);
+ tmp = mvs_cr32(mvi, CMD_LINK_TIMER);
+ tmp |= 0xFFFF0000;
+ mvs_cw32(mvi, CMD_LINK_TIMER, tmp);
+
+ /* tune STP performance */
+ tmp = 0x003F003F;
+ mvs_cw32(mvi, CMD_PL_TIMER, tmp);
+
+ /* This can improve expander large block size seq write performance */
+ tmp = mvs_cr32(mvi, CMD_PORT_LAYER_TIMER1);
+ tmp |= 0xFFFF007F;
+ mvs_cw32(mvi, CMD_PORT_LAYER_TIMER1, tmp);
+
+ /* change the connection open-close behavior (bit 9)
+ * set bit8 to 1 for performance tuning */
+ tmp = mvs_cr32(mvi, CMD_SL_MODE0);
+ tmp |= 0x00000300;
+ /* set bit0 to 0 to enable retry for no_dest reject case */
+ tmp &= 0xFFFFFFFE;
+ mvs_cw32(mvi, CMD_SL_MODE0, tmp);
+
/* Enable SRS interrupt */
mw32(MVS_INT_MASK_SRS_0, 0xFFFF);
@@ -823,6 +854,10 @@ static void mvs_94xx_fix_phy_info(struct mvs_info *mvi, int i,
phy->att_dev_info = PORT_DEV_STP_TRGT | 1;
}
+ /* enable spin up bit */
+ mvs_write_port_cfg_addr(mvi, i, PHYR_PHY_STAT);
+ mvs_write_port_cfg_data(mvi, i, 0x04);
+
}
void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h
index dec7cadb7485..f5451940d289 100644
--- a/drivers/scsi/mvsas/mv_defs.h
+++ b/drivers/scsi/mvsas/mv_defs.h
@@ -387,6 +387,8 @@ enum sas_cmd_port_registers {
CMD_SL_MODE0 = 0x1BC, /* SL Mode 0 */
CMD_SL_MODE1 = 0x1C0, /* SL Mode 1 */
CMD_PND_FIFO_CTL1 = 0x1C4, /* Pending FIFO Control 1 */
+ CMD_PORT_LAYER_TIMER1 = 0x1E0, /* Port Layer Timer 1 */
+ CMD_LINK_TIMER = 0x1E4, /* Link Timer */
};
enum mvs_info_flags {
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index 4e9af66fd1d3..621b5e072758 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -59,7 +59,7 @@ static struct scsi_host_template mvs_sht = {
.name = DRV_NAME,
.queuecommand = sas_queuecommand,
.target_alloc = sas_target_alloc,
- .slave_configure = mvs_slave_configure,
+ .slave_configure = sas_slave_configure,
.slave_destroy = sas_slave_destroy,
.scan_finished = mvs_scan_finished,
.scan_start = mvs_scan_start,
@@ -74,7 +74,7 @@ static struct scsi_host_template mvs_sht = {
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_bus_reset_handler = sas_eh_bus_reset_handler,
- .slave_alloc = mvs_slave_alloc,
+ .slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = mvst_host_attrs,
@@ -707,6 +707,15 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
{ PCI_VDEVICE(TTI, 0x2760), chip_9480 },
{
.vendor = 0x1b4b,
+ .device = 0x9480,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = 0x9480,
+ .class = 0,
+ .class_mask = 0,
+ .driver_data = chip_9480,
+ },
+ {
+ .vendor = 0x1b4b,
.device = 0x9445,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 4958fefff365..a4884a57cf79 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -214,7 +214,7 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
break;
case PHY_FUNC_RELEASE_SPINUP_HOLD:
default:
- rc = -EOPNOTSUPP;
+ rc = -ENOSYS;
}
msleep(200);
return rc;
@@ -265,6 +265,12 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
id->dev_type = phy->identify.device_type;
id->initiator_bits = SAS_PROTOCOL_ALL;
id->target_bits = phy->identify.target_port_protocols;
+
+ /* direct attached SAS device */
+ if (phy->att_dev_info & PORT_SSP_TRGT_MASK) {
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_PHY_STAT);
+ MVS_CHIP_DISP->write_port_cfg_data(mvi, i, 0x00);
+ }
} else if (phy->phy_type & PORT_TYPE_SATA) {
/*Nothing*/
}
@@ -276,36 +282,6 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
PORTE_BYTES_DMAED);
}
-int mvs_slave_alloc(struct scsi_device *scsi_dev)
-{
- struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
- if (dev_is_sata(dev)) {
- /* We don't need to rescan targets
- * if REPORT_LUNS request is failed
- */
- if (scsi_dev->lun > 0)
- return -ENXIO;
- scsi_dev->tagged_supported = 1;
- }
-
- return sas_slave_alloc(scsi_dev);
-}
-
-int mvs_slave_configure(struct scsi_device *sdev)
-{
- struct domain_device *dev = sdev_to_domain_dev(sdev);
- int ret = sas_slave_configure(sdev);
-
- if (ret)
- return ret;
- if (!dev_is_sata(dev)) {
- sas_change_queue_depth(sdev,
- MVS_QUEUE_SIZE,
- SCSI_QDEPTH_DEFAULT);
- }
- return 0;
-}
-
void mvs_scan_start(struct Scsi_Host *shost)
{
int i, j;
@@ -426,7 +402,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
/* generate open address frame hdr (first 12 bytes) */
/* initiator, SMP, ftype 1h */
buf_oaf[0] = (1 << 7) | (PROTOCOL_SMP << 4) | 0x01;
- buf_oaf[1] = dev->linkrate & 0xf;
+ buf_oaf[1] = min(sas_port->linkrate, dev->linkrate) & 0xf;
*(u16 *)(buf_oaf + 2) = 0xFFFF; /* SAS SPEC */
memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE);
@@ -571,7 +547,7 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
/* generate open address frame hdr (first 12 bytes) */
/* initiator, STP, ftype 1h */
buf_oaf[0] = (1 << 7) | (PROTOCOL_STP << 4) | 0x1;
- buf_oaf[1] = dev->linkrate & 0xf;
+ buf_oaf[1] = min(sas_port->linkrate, dev->linkrate) & 0xf;
*(u16 *)(buf_oaf + 2) = cpu_to_be16(mvi_dev->device_id + 1);
memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE);
@@ -679,7 +655,7 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
/* generate open address frame hdr (first 12 bytes) */
/* initiator, SSP, ftype 1h */
buf_oaf[0] = (1 << 7) | (PROTOCOL_SSP << 4) | 0x1;
- buf_oaf[1] = dev->linkrate & 0xf;
+ buf_oaf[1] = min(sas_port->linkrate, dev->linkrate) & 0xf;
*(u16 *)(buf_oaf + 2) = cpu_to_be16(mvi_dev->device_id + 1);
memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE);
@@ -1241,6 +1217,12 @@ static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock)
port->wide_port_phymap = sas_port->phy_mask;
mv_printk("set wide port phy map %x\n", sas_port->phy_mask);
mvs_update_wideport(mvi, sas_phy->id);
+
+ /* direct attached SAS device */
+ if (phy->att_dev_info & PORT_SSP_TRGT_MASK) {
+ MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_PHY_STAT);
+ MVS_CHIP_DISP->write_port_cfg_data(mvi, i, 0x04);
+ }
}
if (lock)
spin_unlock_irqrestore(&mvi->lock, flags);
@@ -1387,28 +1369,6 @@ void mvs_dev_gone(struct domain_device *dev)
mvs_dev_gone_notify(dev);
}
-static struct sas_task *mvs_alloc_task(void)
-{
- struct sas_task *task = kzalloc(sizeof(struct sas_task), GFP_KERNEL);
-
- if (task) {
- INIT_LIST_HEAD(&task->list);
- spin_lock_init(&task->task_state_lock);
- task->task_state_flags = SAS_TASK_STATE_PENDING;
- init_timer(&task->timer);
- init_completion(&task->completion);
- }
- return task;
-}
-
-static void mvs_free_task(struct sas_task *task)
-{
- if (task) {
- BUG_ON(!list_empty(&task->list));
- kfree(task);
- }
-}
-
static void mvs_task_done(struct sas_task *task)
{
if (!del_timer(&task->timer))
@@ -1432,7 +1392,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
struct sas_task *task = NULL;
for (retry = 0; retry < 3; retry++) {
- task = mvs_alloc_task();
+ task = sas_alloc_task(GFP_KERNEL);
if (!task)
return -ENOMEM;
@@ -1490,15 +1450,14 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
SAS_ADDR(dev->sas_addr),
task->task_status.resp,
task->task_status.stat);
- mvs_free_task(task);
+ sas_free_task(task);
task = NULL;
}
}
ex_err:
BUG_ON(retry == 3 && task != NULL);
- if (task != NULL)
- mvs_free_task(task);
+ sas_free_task(task);
return res;
}
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
index 44d7885a4a1d..c04a4f5b5972 100644
--- a/drivers/scsi/mvsas/mv_sas.h
+++ b/drivers/scsi/mvsas/mv_sas.h
@@ -43,11 +43,10 @@
#include <scsi/scsi.h>
#include <scsi/scsi_tcq.h>
#include <scsi/sas_ata.h>
-#include <linux/version.h>
#include "mv_defs.h"
#define DRV_NAME "mvsas"
-#define DRV_VERSION "0.8.2"
+#define DRV_VERSION "0.8.16"
#define MVS_ID_NOT_MAPPED 0x7f
#define WIDE_PORT_MAX_PHY 4
#define mv_printk(fmt, arg ...) \
@@ -459,8 +458,6 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
void *funcdata);
void __devinit mvs_set_sas_addr(struct mvs_info *mvi, int port_id,
u32 off_lo, u32 off_hi, u64 sas_addr);
-int mvs_slave_alloc(struct scsi_device *scsi_dev);
-int mvs_slave_configure(struct scsi_device *sdev);
void mvs_scan_start(struct Scsi_Host *shost);
int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time);
int mvs_queue_command(struct sas_task *task, const int num,
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
new file mode 100644
index 000000000000..88cf1db21a79
--- /dev/null
+++ b/drivers/scsi/mvumi.c
@@ -0,0 +1,2018 @@
+/*
+ * Marvell UMI driver
+ *
+ * Copyright 2011 Marvell. <jyli@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/blkdev.h>
+#include <linux/io.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_eh.h>
+#include <linux/uaccess.h>
+
+#include "mvumi.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("jyli@marvell.com");
+MODULE_DESCRIPTION("Marvell UMI Driver");
+
+static DEFINE_PCI_DEVICE_TABLE(mvumi_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9143) },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, mvumi_pci_table);
+
+static void tag_init(struct mvumi_tag *st, unsigned short size)
+{
+ unsigned short i;
+ BUG_ON(size != st->size);
+ st->top = size;
+ for (i = 0; i < size; i++)
+ st->stack[i] = size - 1 - i;
+}
+
+static unsigned short tag_get_one(struct mvumi_hba *mhba, struct mvumi_tag *st)
+{
+ BUG_ON(st->top <= 0);
+ return st->stack[--st->top];
+}
+
+static void tag_release_one(struct mvumi_hba *mhba, struct mvumi_tag *st,
+ unsigned short tag)
+{
+ BUG_ON(st->top >= st->size);
+ st->stack[st->top++] = tag;
+}
+
+static bool tag_is_empty(struct mvumi_tag *st)
+{
+ if (st->top == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static void mvumi_unmap_pci_addr(struct pci_dev *dev, void **addr_array)
+{
+ int i;
+
+ for (i = 0; i < MAX_BASE_ADDRESS; i++)
+ if ((pci_resource_flags(dev, i) & IORESOURCE_MEM) &&
+ addr_array[i])
+ pci_iounmap(dev, addr_array[i]);
+}
+
+static int mvumi_map_pci_addr(struct pci_dev *dev, void **addr_array)
+{
+ int i;
+
+ for (i = 0; i < MAX_BASE_ADDRESS; i++) {
+ if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
+ addr_array[i] = pci_iomap(dev, i, 0);
+ if (!addr_array[i]) {
+ dev_err(&dev->dev, "failed to map Bar[%d]\n",
+ i);
+ mvumi_unmap_pci_addr(dev, addr_array);
+ return -ENOMEM;
+ }
+ } else
+ addr_array[i] = NULL;
+
+ dev_dbg(&dev->dev, "Bar %d : %p.\n", i, addr_array[i]);
+ }
+
+ return 0;
+}
+
+static struct mvumi_res *mvumi_alloc_mem_resource(struct mvumi_hba *mhba,
+ enum resource_type type, unsigned int size)
+{
+ struct mvumi_res *res = kzalloc(sizeof(*res), GFP_KERNEL);
+
+ if (!res) {
+ dev_err(&mhba->pdev->dev,
+ "Failed to allocate memory for resouce manager.\n");
+ return NULL;
+ }
+
+ switch (type) {
+ case RESOURCE_CACHED_MEMORY:
+ res->virt_addr = kzalloc(size, GFP_KERNEL);
+ if (!res->virt_addr) {
+ dev_err(&mhba->pdev->dev,
+ "unable to allocate memory,size = %d.\n", size);
+ kfree(res);
+ return NULL;
+ }
+ break;
+
+ case RESOURCE_UNCACHED_MEMORY:
+ size = round_up(size, 8);
+ res->virt_addr = pci_alloc_consistent(mhba->pdev, size,
+ &res->bus_addr);
+ if (!res->virt_addr) {
+ dev_err(&mhba->pdev->dev,
+ "unable to allocate consistent mem,"
+ "size = %d.\n", size);
+ kfree(res);
+ return NULL;
+ }
+ memset(res->virt_addr, 0, size);
+ break;
+
+ default:
+ dev_err(&mhba->pdev->dev, "unknown resource type %d.\n", type);
+ kfree(res);
+ return NULL;
+ }
+
+ res->type = type;
+ res->size = size;
+ INIT_LIST_HEAD(&res->entry);
+ list_add_tail(&res->entry, &mhba->res_list);
+
+ return res;
+}
+
+static void mvumi_release_mem_resource(struct mvumi_hba *mhba)
+{
+ struct mvumi_res *res, *tmp;
+
+ list_for_each_entry_safe(res, tmp, &mhba->res_list, entry) {
+ switch (res->type) {
+ case RESOURCE_UNCACHED_MEMORY:
+ pci_free_consistent(mhba->pdev, res->size,
+ res->virt_addr, res->bus_addr);
+ break;
+ case RESOURCE_CACHED_MEMORY:
+ kfree(res->virt_addr);
+ break;
+ default:
+ dev_err(&mhba->pdev->dev,
+ "unknown resource type %d\n", res->type);
+ break;
+ }
+ list_del(&res->entry);
+ kfree(res);
+ }
+ mhba->fw_flag &= ~MVUMI_FW_ALLOC;
+}
+
+/**
+ * mvumi_make_sgl - Prepares SGL
+ * @mhba: Adapter soft state
+ * @scmd: SCSI command from the mid-layer
+ * @sgl_p: SGL to be filled in
+ * @sg_count return the number of SG elements
+ *
+ * If successful, this function returns 0. otherwise, it returns -1.
+ */
+static int mvumi_make_sgl(struct mvumi_hba *mhba, struct scsi_cmnd *scmd,
+ void *sgl_p, unsigned char *sg_count)
+{
+ struct scatterlist *sg;
+ struct mvumi_sgl *m_sg = (struct mvumi_sgl *) sgl_p;
+ unsigned int i;
+ unsigned int sgnum = scsi_sg_count(scmd);
+ dma_addr_t busaddr;
+
+ if (sgnum) {
+ sg = scsi_sglist(scmd);
+ *sg_count = pci_map_sg(mhba->pdev, sg, sgnum,
+ (int) scmd->sc_data_direction);
+ if (*sg_count > mhba->max_sge) {
+ dev_err(&mhba->pdev->dev, "sg count[0x%x] is bigger "
+ "than max sg[0x%x].\n",
+ *sg_count, mhba->max_sge);
+ return -1;
+ }
+ for (i = 0; i < *sg_count; i++) {
+ busaddr = sg_dma_address(&sg[i]);
+ m_sg->baseaddr_l = cpu_to_le32(lower_32_bits(busaddr));
+ m_sg->baseaddr_h = cpu_to_le32(upper_32_bits(busaddr));
+ m_sg->flags = 0;
+ m_sg->size = cpu_to_le32(sg_dma_len(&sg[i]));
+ if ((i + 1) == *sg_count)
+ m_sg->flags |= SGD_EOT;
+
+ m_sg++;
+ }
+ } else {
+ scmd->SCp.dma_handle = scsi_bufflen(scmd) ?
+ pci_map_single(mhba->pdev, scsi_sglist(scmd),
+ scsi_bufflen(scmd),
+ (int) scmd->sc_data_direction)
+ : 0;
+ busaddr = scmd->SCp.dma_handle;
+ m_sg->baseaddr_l = cpu_to_le32(lower_32_bits(busaddr));
+ m_sg->baseaddr_h = cpu_to_le32(upper_32_bits(busaddr));
+ m_sg->flags = SGD_EOT;
+ m_sg->size = cpu_to_le32(scsi_bufflen(scmd));
+ *sg_count = 1;
+ }
+
+ return 0;
+}
+
+static int mvumi_internal_cmd_sgl(struct mvumi_hba *mhba, struct mvumi_cmd *cmd,
+ unsigned int size)
+{
+ struct mvumi_sgl *m_sg;
+ void *virt_addr;
+ dma_addr_t phy_addr;
+
+ if (size == 0)
+ return 0;
+
+ virt_addr = pci_alloc_consistent(mhba->pdev, size, &phy_addr);
+ if (!virt_addr)
+ return -1;
+
+ memset(virt_addr, 0, size);
+
+ m_sg = (struct mvumi_sgl *) &cmd->frame->payload[0];
+ cmd->frame->sg_counts = 1;
+ cmd->data_buf = virt_addr;
+
+ m_sg->baseaddr_l = cpu_to_le32(lower_32_bits(phy_addr));
+ m_sg->baseaddr_h = cpu_to_le32(upper_32_bits(phy_addr));
+ m_sg->flags = SGD_EOT;
+ m_sg->size = cpu_to_le32(size);
+
+ return 0;
+}
+
+static struct mvumi_cmd *mvumi_create_internal_cmd(struct mvumi_hba *mhba,
+ unsigned int buf_size)
+{
+ struct mvumi_cmd *cmd;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ dev_err(&mhba->pdev->dev, "failed to create a internal cmd\n");
+ return NULL;
+ }
+ INIT_LIST_HEAD(&cmd->queue_pointer);
+
+ cmd->frame = kzalloc(mhba->ib_max_size, GFP_KERNEL);
+ if (!cmd->frame) {
+ dev_err(&mhba->pdev->dev, "failed to allocate memory for FW"
+ " frame,size = %d.\n", mhba->ib_max_size);
+ kfree(cmd);
+ return NULL;
+ }
+
+ if (buf_size) {
+ if (mvumi_internal_cmd_sgl(mhba, cmd, buf_size)) {
+ dev_err(&mhba->pdev->dev, "failed to allocate memory"
+ " for internal frame\n");
+ kfree(cmd->frame);
+ kfree(cmd);
+ return NULL;
+ }
+ } else
+ cmd->frame->sg_counts = 0;
+
+ return cmd;
+}
+
+static void mvumi_delete_internal_cmd(struct mvumi_hba *mhba,
+ struct mvumi_cmd *cmd)
+{
+ struct mvumi_sgl *m_sg;
+ unsigned int size;
+ dma_addr_t phy_addr;
+
+ if (cmd && cmd->frame) {
+ if (cmd->frame->sg_counts) {
+ m_sg = (struct mvumi_sgl *) &cmd->frame->payload[0];
+ size = m_sg->size;
+
+ phy_addr = (dma_addr_t) m_sg->baseaddr_l |
+ (dma_addr_t) ((m_sg->baseaddr_h << 16) << 16);
+
+ pci_free_consistent(mhba->pdev, size, cmd->data_buf,
+ phy_addr);
+ }
+ kfree(cmd->frame);
+ kfree(cmd);
+ }
+}
+
+/**
+ * mvumi_get_cmd - Get a command from the free pool
+ * @mhba: Adapter soft state
+ *
+ * Returns a free command from the pool
+ */
+static struct mvumi_cmd *mvumi_get_cmd(struct mvumi_hba *mhba)
+{
+ struct mvumi_cmd *cmd = NULL;
+
+ if (likely(!list_empty(&mhba->cmd_pool))) {
+ cmd = list_entry((&mhba->cmd_pool)->next,
+ struct mvumi_cmd, queue_pointer);
+ list_del_init(&cmd->queue_pointer);
+ } else
+ dev_warn(&mhba->pdev->dev, "command pool is empty!\n");
+
+ return cmd;
+}
+
+/**
+ * mvumi_return_cmd - Return a cmd to free command pool
+ * @mhba: Adapter soft state
+ * @cmd: Command packet to be returned to free command pool
+ */
+static inline void mvumi_return_cmd(struct mvumi_hba *mhba,
+ struct mvumi_cmd *cmd)
+{
+ cmd->scmd = NULL;
+ list_add_tail(&cmd->queue_pointer, &mhba->cmd_pool);
+}
+
+/**
+ * mvumi_free_cmds - Free all the cmds in the free cmd pool
+ * @mhba: Adapter soft state
+ */
+static void mvumi_free_cmds(struct mvumi_hba *mhba)
+{
+ struct mvumi_cmd *cmd;
+
+ while (!list_empty(&mhba->cmd_pool)) {
+ cmd = list_first_entry(&mhba->cmd_pool, struct mvumi_cmd,
+ queue_pointer);
+ list_del(&cmd->queue_pointer);
+ kfree(cmd->frame);
+ kfree(cmd);
+ }
+}
+
+/**
+ * mvumi_alloc_cmds - Allocates the command packets
+ * @mhba: Adapter soft state
+ *
+ */
+static int mvumi_alloc_cmds(struct mvumi_hba *mhba)
+{
+ int i;
+ struct mvumi_cmd *cmd;
+
+ for (i = 0; i < mhba->max_io; i++) {
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ goto err_exit;
+
+ INIT_LIST_HEAD(&cmd->queue_pointer);
+ list_add_tail(&cmd->queue_pointer, &mhba->cmd_pool);
+ cmd->frame = kzalloc(mhba->ib_max_size, GFP_KERNEL);
+ if (!cmd->frame)
+ goto err_exit;
+ }
+ return 0;
+
+err_exit:
+ dev_err(&mhba->pdev->dev,
+ "failed to allocate memory for cmd[0x%x].\n", i);
+ while (!list_empty(&mhba->cmd_pool)) {
+ cmd = list_first_entry(&mhba->cmd_pool, struct mvumi_cmd,
+ queue_pointer);
+ list_del(&cmd->queue_pointer);
+ kfree(cmd->frame);
+ kfree(cmd);
+ }
+ return -ENOMEM;
+}
+
+static int mvumi_get_ib_list_entry(struct mvumi_hba *mhba, void **ib_entry)
+{
+ unsigned int ib_rp_reg, cur_ib_entry;
+
+ if (atomic_read(&mhba->fw_outstanding) >= mhba->max_io) {
+ dev_warn(&mhba->pdev->dev, "firmware io overflow.\n");
+ return -1;
+ }
+ ib_rp_reg = ioread32(mhba->mmio + CLA_INB_READ_POINTER);
+
+ if (unlikely(((ib_rp_reg & CL_SLOT_NUM_MASK) ==
+ (mhba->ib_cur_slot & CL_SLOT_NUM_MASK)) &&
+ ((ib_rp_reg & CL_POINTER_TOGGLE) !=
+ (mhba->ib_cur_slot & CL_POINTER_TOGGLE)))) {
+ dev_warn(&mhba->pdev->dev, "no free slot to use.\n");
+ return -1;
+ }
+
+ cur_ib_entry = mhba->ib_cur_slot & CL_SLOT_NUM_MASK;
+ cur_ib_entry++;
+ if (cur_ib_entry >= mhba->list_num_io) {
+ cur_ib_entry -= mhba->list_num_io;
+ mhba->ib_cur_slot ^= CL_POINTER_TOGGLE;
+ }
+ mhba->ib_cur_slot &= ~CL_SLOT_NUM_MASK;
+ mhba->ib_cur_slot |= (cur_ib_entry & CL_SLOT_NUM_MASK);
+ *ib_entry = mhba->ib_list + cur_ib_entry * mhba->ib_max_size;
+ atomic_inc(&mhba->fw_outstanding);
+
+ return 0;
+}
+
+static void mvumi_send_ib_list_entry(struct mvumi_hba *mhba)
+{
+ iowrite32(0xfff, mhba->ib_shadow);
+ iowrite32(mhba->ib_cur_slot, mhba->mmio + CLA_INB_WRITE_POINTER);
+}
+
+static char mvumi_check_ob_frame(struct mvumi_hba *mhba,
+ unsigned int cur_obf, struct mvumi_rsp_frame *p_outb_frame)
+{
+ unsigned short tag, request_id;
+
+ udelay(1);
+ p_outb_frame = mhba->ob_list + cur_obf * mhba->ob_max_size;
+ request_id = p_outb_frame->request_id;
+ tag = p_outb_frame->tag;
+ if (tag > mhba->tag_pool.size) {
+ dev_err(&mhba->pdev->dev, "ob frame data error\n");
+ return -1;
+ }
+ if (mhba->tag_cmd[tag] == NULL) {
+ dev_err(&mhba->pdev->dev, "tag[0x%x] with NO command\n", tag);
+ return -1;
+ } else if (mhba->tag_cmd[tag]->request_id != request_id &&
+ mhba->request_id_enabled) {
+ dev_err(&mhba->pdev->dev, "request ID from FW:0x%x,"
+ "cmd request ID:0x%x\n", request_id,
+ mhba->tag_cmd[tag]->request_id);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void mvumi_receive_ob_list_entry(struct mvumi_hba *mhba)
+{
+ unsigned int ob_write_reg, ob_write_shadow_reg;
+ unsigned int cur_obf, assign_obf_end, i;
+ struct mvumi_ob_data *ob_data;
+ struct mvumi_rsp_frame *p_outb_frame;
+
+ do {
+ ob_write_reg = ioread32(mhba->mmio + CLA_OUTB_COPY_POINTER);
+ ob_write_shadow_reg = ioread32(mhba->ob_shadow);
+ } while ((ob_write_reg & CL_SLOT_NUM_MASK) != ob_write_shadow_reg);
+
+ cur_obf = mhba->ob_cur_slot & CL_SLOT_NUM_MASK;
+ assign_obf_end = ob_write_reg & CL_SLOT_NUM_MASK;
+
+ if ((ob_write_reg & CL_POINTER_TOGGLE) !=
+ (mhba->ob_cur_slot & CL_POINTER_TOGGLE)) {
+ assign_obf_end += mhba->list_num_io;
+ }
+
+ for (i = (assign_obf_end - cur_obf); i != 0; i--) {
+ cur_obf++;
+ if (cur_obf >= mhba->list_num_io) {
+ cur_obf -= mhba->list_num_io;
+ mhba->ob_cur_slot ^= CL_POINTER_TOGGLE;
+ }
+
+ p_outb_frame = mhba->ob_list + cur_obf * mhba->ob_max_size;
+
+ /* Copy pointer may point to entry in outbound list
+ * before entry has valid data
+ */
+ if (unlikely(p_outb_frame->tag > mhba->tag_pool.size ||
+ mhba->tag_cmd[p_outb_frame->tag] == NULL ||
+ p_outb_frame->request_id !=
+ mhba->tag_cmd[p_outb_frame->tag]->request_id))
+ if (mvumi_check_ob_frame(mhba, cur_obf, p_outb_frame))
+ continue;
+
+ if (!list_empty(&mhba->ob_data_list)) {
+ ob_data = (struct mvumi_ob_data *)
+ list_first_entry(&mhba->ob_data_list,
+ struct mvumi_ob_data, list);
+ list_del_init(&ob_data->list);
+ } else {
+ ob_data = NULL;
+ if (cur_obf == 0) {
+ cur_obf = mhba->list_num_io - 1;
+ mhba->ob_cur_slot ^= CL_POINTER_TOGGLE;
+ } else
+ cur_obf -= 1;
+ break;
+ }
+
+ memcpy(ob_data->data, p_outb_frame, mhba->ob_max_size);
+ p_outb_frame->tag = 0xff;
+
+ list_add_tail(&ob_data->list, &mhba->free_ob_list);
+ }
+ mhba->ob_cur_slot &= ~CL_SLOT_NUM_MASK;
+ mhba->ob_cur_slot |= (cur_obf & CL_SLOT_NUM_MASK);
+ iowrite32(mhba->ob_cur_slot, mhba->mmio + CLA_OUTB_READ_POINTER);
+}
+
+static void mvumi_reset(void *regs)
+{
+ iowrite32(0, regs + CPU_ENPOINTA_MASK_REG);
+ if (ioread32(regs + CPU_ARM_TO_PCIEA_MSG1) != HANDSHAKE_DONESTATE)
+ return;
+
+ iowrite32(DRBL_SOFT_RESET, regs + CPU_PCIEA_TO_ARM_DRBL_REG);
+}
+
+static unsigned char mvumi_start(struct mvumi_hba *mhba);
+
+static int mvumi_wait_for_outstanding(struct mvumi_hba *mhba)
+{
+ mhba->fw_state = FW_STATE_ABORT;
+ mvumi_reset(mhba->mmio);
+
+ if (mvumi_start(mhba))
+ return FAILED;
+ else
+ return SUCCESS;
+}
+
+static int mvumi_host_reset(struct scsi_cmnd *scmd)
+{
+ struct mvumi_hba *mhba;
+
+ mhba = (struct mvumi_hba *) scmd->device->host->hostdata;
+
+ scmd_printk(KERN_NOTICE, scmd, "RESET -%ld cmd=%x retries=%x\n",
+ scmd->serial_number, scmd->cmnd[0], scmd->retries);
+
+ return mvumi_wait_for_outstanding(mhba);
+}
+
+static int mvumi_issue_blocked_cmd(struct mvumi_hba *mhba,
+ struct mvumi_cmd *cmd)
+{
+ unsigned long flags;
+
+ cmd->cmd_status = REQ_STATUS_PENDING;
+
+ if (atomic_read(&cmd->sync_cmd)) {
+ dev_err(&mhba->pdev->dev,
+ "last blocked cmd not finished, sync_cmd = %d\n",
+ atomic_read(&cmd->sync_cmd));
+ BUG_ON(1);
+ return -1;
+ }
+ atomic_inc(&cmd->sync_cmd);
+ spin_lock_irqsave(mhba->shost->host_lock, flags);
+ mhba->instancet->fire_cmd(mhba, cmd);
+ spin_unlock_irqrestore(mhba->shost->host_lock, flags);
+
+ wait_event_timeout(mhba->int_cmd_wait_q,
+ (cmd->cmd_status != REQ_STATUS_PENDING),
+ MVUMI_INTERNAL_CMD_WAIT_TIME * HZ);
+
+ /* command timeout */
+ if (atomic_read(&cmd->sync_cmd)) {
+ spin_lock_irqsave(mhba->shost->host_lock, flags);
+ atomic_dec(&cmd->sync_cmd);
+ if (mhba->tag_cmd[cmd->frame->tag]) {
+ mhba->tag_cmd[cmd->frame->tag] = 0;
+ dev_warn(&mhba->pdev->dev, "TIMEOUT:release tag [%d]\n",
+ cmd->frame->tag);
+ tag_release_one(mhba, &mhba->tag_pool, cmd->frame->tag);
+ }
+ if (!list_empty(&cmd->queue_pointer)) {
+ dev_warn(&mhba->pdev->dev,
+ "TIMEOUT:A internal command doesn't send!\n");
+ list_del_init(&cmd->queue_pointer);
+ } else
+ atomic_dec(&mhba->fw_outstanding);
+
+ spin_unlock_irqrestore(mhba->shost->host_lock, flags);
+ }
+ return 0;
+}
+
+static void mvumi_release_fw(struct mvumi_hba *mhba)
+{
+ mvumi_free_cmds(mhba);
+ mvumi_release_mem_resource(mhba);
+ mvumi_unmap_pci_addr(mhba->pdev, mhba->base_addr);
+ kfree(mhba->handshake_page);
+ pci_release_regions(mhba->pdev);
+}
+
+static unsigned char mvumi_flush_cache(struct mvumi_hba *mhba)
+{
+ struct mvumi_cmd *cmd;
+ struct mvumi_msg_frame *frame;
+ unsigned char device_id, retry = 0;
+ unsigned char bitcount = sizeof(unsigned char) * 8;
+
+ for (device_id = 0; device_id < mhba->max_target_id; device_id++) {
+ if (!(mhba->target_map[device_id / bitcount] &
+ (1 << (device_id % bitcount))))
+ continue;
+get_cmd: cmd = mvumi_create_internal_cmd(mhba, 0);
+ if (!cmd) {
+ if (retry++ >= 5) {
+ dev_err(&mhba->pdev->dev, "failed to get memory"
+ " for internal flush cache cmd for "
+ "device %d", device_id);
+ retry = 0;
+ continue;
+ } else
+ goto get_cmd;
+ }
+ cmd->scmd = NULL;
+ cmd->cmd_status = REQ_STATUS_PENDING;
+ atomic_set(&cmd->sync_cmd, 0);
+ frame = cmd->frame;
+ frame->req_function = CL_FUN_SCSI_CMD;
+ frame->device_id = device_id;
+ frame->cmd_flag = CMD_FLAG_NON_DATA;
+ frame->data_transfer_length = 0;
+ frame->cdb_length = MAX_COMMAND_SIZE;
+ memset(frame->cdb, 0, MAX_COMMAND_SIZE);
+ frame->cdb[0] = SCSI_CMD_MARVELL_SPECIFIC;
+ frame->cdb[2] = CDB_CORE_SHUTDOWN;
+
+ mvumi_issue_blocked_cmd(mhba, cmd);
+ if (cmd->cmd_status != SAM_STAT_GOOD) {
+ dev_err(&mhba->pdev->dev,
+ "device %d flush cache failed, status=0x%x.\n",
+ device_id, cmd->cmd_status);
+ }
+
+ mvumi_delete_internal_cmd(mhba, cmd);
+ }
+ return 0;
+}
+
+static unsigned char
+mvumi_calculate_checksum(struct mvumi_hs_header *p_header,
+ unsigned short len)
+{
+ unsigned char *ptr;
+ unsigned char ret = 0, i;
+
+ ptr = (unsigned char *) p_header->frame_content;
+ for (i = 0; i < len; i++) {
+ ret ^= *ptr;
+ ptr++;
+ }
+
+ return ret;
+}
+
+void mvumi_hs_build_page(struct mvumi_hba *mhba,
+ struct mvumi_hs_header *hs_header)
+{
+ struct mvumi_hs_page2 *hs_page2;
+ struct mvumi_hs_page4 *hs_page4;
+ struct mvumi_hs_page3 *hs_page3;
+ struct timeval time;
+ unsigned int local_time;
+
+ switch (hs_header->page_code) {
+ case HS_PAGE_HOST_INFO:
+ hs_page2 = (struct mvumi_hs_page2 *) hs_header;
+ hs_header->frame_length = sizeof(*hs_page2) - 4;
+ memset(hs_header->frame_content, 0, hs_header->frame_length);
+ hs_page2->host_type = 3; /* 3 mean linux*/
+ hs_page2->host_ver.ver_major = VER_MAJOR;
+ hs_page2->host_ver.ver_minor = VER_MINOR;
+ hs_page2->host_ver.ver_oem = VER_OEM;
+ hs_page2->host_ver.ver_build = VER_BUILD;
+ hs_page2->system_io_bus = 0;
+ hs_page2->slot_number = 0;
+ hs_page2->intr_level = 0;
+ hs_page2->intr_vector = 0;
+ do_gettimeofday(&time);
+ local_time = (unsigned int) (time.tv_sec -
+ (sys_tz.tz_minuteswest * 60));
+ hs_page2->seconds_since1970 = local_time;
+ hs_header->checksum = mvumi_calculate_checksum(hs_header,
+ hs_header->frame_length);
+ break;
+
+ case HS_PAGE_FIRM_CTL:
+ hs_page3 = (struct mvumi_hs_page3 *) hs_header;
+ hs_header->frame_length = sizeof(*hs_page3) - 4;
+ memset(hs_header->frame_content, 0, hs_header->frame_length);
+ hs_header->checksum = mvumi_calculate_checksum(hs_header,
+ hs_header->frame_length);
+ break;
+
+ case HS_PAGE_CL_INFO:
+ hs_page4 = (struct mvumi_hs_page4 *) hs_header;
+ hs_header->frame_length = sizeof(*hs_page4) - 4;
+ memset(hs_header->frame_content, 0, hs_header->frame_length);
+ hs_page4->ib_baseaddr_l = lower_32_bits(mhba->ib_list_phys);
+ hs_page4->ib_baseaddr_h = upper_32_bits(mhba->ib_list_phys);
+
+ hs_page4->ob_baseaddr_l = lower_32_bits(mhba->ob_list_phys);
+ hs_page4->ob_baseaddr_h = upper_32_bits(mhba->ob_list_phys);
+ hs_page4->ib_entry_size = mhba->ib_max_size_setting;
+ hs_page4->ob_entry_size = mhba->ob_max_size_setting;
+ hs_page4->ob_depth = mhba->list_num_io;
+ hs_page4->ib_depth = mhba->list_num_io;
+ hs_header->checksum = mvumi_calculate_checksum(hs_header,
+ hs_header->frame_length);
+ break;
+
+ default:
+ dev_err(&mhba->pdev->dev, "cannot build page, code[0x%x]\n",
+ hs_header->page_code);
+ break;
+ }
+}
+
+/**
+ * mvumi_init_data - Initialize requested date for FW
+ * @mhba: Adapter soft state
+ */
+static int mvumi_init_data(struct mvumi_hba *mhba)
+{
+ struct mvumi_ob_data *ob_pool;
+ struct mvumi_res *res_mgnt;
+ unsigned int tmp_size, offset, i;
+ void *virmem, *v;
+ dma_addr_t p;
+
+ if (mhba->fw_flag & MVUMI_FW_ALLOC)
+ return 0;
+
+ tmp_size = mhba->ib_max_size * mhba->max_io;
+ tmp_size += 128 + mhba->ob_max_size * mhba->max_io;
+ tmp_size += 8 + sizeof(u32) + 16;
+
+ res_mgnt = mvumi_alloc_mem_resource(mhba,
+ RESOURCE_UNCACHED_MEMORY, tmp_size);
+ if (!res_mgnt) {
+ dev_err(&mhba->pdev->dev,
+ "failed to allocate memory for inbound list\n");
+ goto fail_alloc_dma_buf;
+ }
+
+ p = res_mgnt->bus_addr;
+ v = res_mgnt->virt_addr;
+ /* ib_list */
+ offset = round_up(p, 128) - p;
+ p += offset;
+ v += offset;
+ mhba->ib_list = v;
+ mhba->ib_list_phys = p;
+ v += mhba->ib_max_size * mhba->max_io;
+ p += mhba->ib_max_size * mhba->max_io;
+ /* ib shadow */
+ offset = round_up(p, 8) - p;
+ p += offset;
+ v += offset;
+ mhba->ib_shadow = v;
+ mhba->ib_shadow_phys = p;
+ p += sizeof(u32);
+ v += sizeof(u32);
+ /* ob shadow */
+ offset = round_up(p, 8) - p;
+ p += offset;
+ v += offset;
+ mhba->ob_shadow = v;
+ mhba->ob_shadow_phys = p;
+ p += 8;
+ v += 8;
+
+ /* ob list */
+ offset = round_up(p, 128) - p;
+ p += offset;
+ v += offset;
+
+ mhba->ob_list = v;
+ mhba->ob_list_phys = p;
+
+ /* ob data pool */
+ tmp_size = mhba->max_io * (mhba->ob_max_size + sizeof(*ob_pool));
+ tmp_size = round_up(tmp_size, 8);
+
+ res_mgnt = mvumi_alloc_mem_resource(mhba,
+ RESOURCE_CACHED_MEMORY, tmp_size);
+ if (!res_mgnt) {
+ dev_err(&mhba->pdev->dev,
+ "failed to allocate memory for outbound data buffer\n");
+ goto fail_alloc_dma_buf;
+ }
+ virmem = res_mgnt->virt_addr;
+
+ for (i = mhba->max_io; i != 0; i--) {
+ ob_pool = (struct mvumi_ob_data *) virmem;
+ list_add_tail(&ob_pool->list, &mhba->ob_data_list);
+ virmem += mhba->ob_max_size + sizeof(*ob_pool);
+ }
+
+ tmp_size = sizeof(unsigned short) * mhba->max_io +
+ sizeof(struct mvumi_cmd *) * mhba->max_io;
+ tmp_size += round_up(mhba->max_target_id, sizeof(unsigned char) * 8) /
+ (sizeof(unsigned char) * 8);
+
+ res_mgnt = mvumi_alloc_mem_resource(mhba,
+ RESOURCE_CACHED_MEMORY, tmp_size);
+ if (!res_mgnt) {
+ dev_err(&mhba->pdev->dev,
+ "failed to allocate memory for tag and target map\n");
+ goto fail_alloc_dma_buf;
+ }
+
+ virmem = res_mgnt->virt_addr;
+ mhba->tag_pool.stack = virmem;
+ mhba->tag_pool.size = mhba->max_io;
+ tag_init(&mhba->tag_pool, mhba->max_io);
+ virmem += sizeof(unsigned short) * mhba->max_io;
+
+ mhba->tag_cmd = virmem;
+ virmem += sizeof(struct mvumi_cmd *) * mhba->max_io;
+
+ mhba->target_map = virmem;
+
+ mhba->fw_flag |= MVUMI_FW_ALLOC;
+ return 0;
+
+fail_alloc_dma_buf:
+ mvumi_release_mem_resource(mhba);
+ return -1;
+}
+
+static int mvumi_hs_process_page(struct mvumi_hba *mhba,
+ struct mvumi_hs_header *hs_header)
+{
+ struct mvumi_hs_page1 *hs_page1;
+ unsigned char page_checksum;
+
+ page_checksum = mvumi_calculate_checksum(hs_header,
+ hs_header->frame_length);
+ if (page_checksum != hs_header->checksum) {
+ dev_err(&mhba->pdev->dev, "checksum error\n");
+ return -1;
+ }
+
+ switch (hs_header->page_code) {
+ case HS_PAGE_FIRM_CAP:
+ hs_page1 = (struct mvumi_hs_page1 *) hs_header;
+
+ mhba->max_io = hs_page1->max_io_support;
+ mhba->list_num_io = hs_page1->cl_inout_list_depth;
+ mhba->max_transfer_size = hs_page1->max_transfer_size;
+ mhba->max_target_id = hs_page1->max_devices_support;
+ mhba->hba_capability = hs_page1->capability;
+ mhba->ib_max_size_setting = hs_page1->cl_in_max_entry_size;
+ mhba->ib_max_size = (1 << hs_page1->cl_in_max_entry_size) << 2;
+
+ mhba->ob_max_size_setting = hs_page1->cl_out_max_entry_size;
+ mhba->ob_max_size = (1 << hs_page1->cl_out_max_entry_size) << 2;
+
+ dev_dbg(&mhba->pdev->dev, "FW version:%d\n",
+ hs_page1->fw_ver.ver_build);
+
+ break;
+ default:
+ dev_err(&mhba->pdev->dev, "handshake: page code error\n");
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * mvumi_handshake - Move the FW to READY state
+ * @mhba: Adapter soft state
+ *
+ * During the initialization, FW passes can potentially be in any one of
+ * several possible states. If the FW in operational, waiting-for-handshake
+ * states, driver must take steps to bring it to ready state. Otherwise, it
+ * has to wait for the ready state.
+ */
+static int mvumi_handshake(struct mvumi_hba *mhba)
+{
+ unsigned int hs_state, tmp, hs_fun;
+ struct mvumi_hs_header *hs_header;
+ void *regs = mhba->mmio;
+
+ if (mhba->fw_state == FW_STATE_STARTING)
+ hs_state = HS_S_START;
+ else {
+ tmp = ioread32(regs + CPU_ARM_TO_PCIEA_MSG0);
+ hs_state = HS_GET_STATE(tmp);
+ dev_dbg(&mhba->pdev->dev, "handshake state[0x%x].\n", hs_state);
+ if (HS_GET_STATUS(tmp) != HS_STATUS_OK) {
+ mhba->fw_state = FW_STATE_STARTING;
+ return -1;
+ }
+ }
+
+ hs_fun = 0;
+ switch (hs_state) {
+ case HS_S_START:
+ mhba->fw_state = FW_STATE_HANDSHAKING;
+ HS_SET_STATUS(hs_fun, HS_STATUS_OK);
+ HS_SET_STATE(hs_fun, HS_S_RESET);
+ iowrite32(HANDSHAKE_SIGNATURE, regs + CPU_PCIEA_TO_ARM_MSG1);
+ iowrite32(hs_fun, regs + CPU_PCIEA_TO_ARM_MSG0);
+ iowrite32(DRBL_HANDSHAKE, regs + CPU_PCIEA_TO_ARM_DRBL_REG);
+ break;
+
+ case HS_S_RESET:
+ iowrite32(lower_32_bits(mhba->handshake_page_phys),
+ regs + CPU_PCIEA_TO_ARM_MSG1);
+ iowrite32(upper_32_bits(mhba->handshake_page_phys),
+ regs + CPU_ARM_TO_PCIEA_MSG1);
+ HS_SET_STATUS(hs_fun, HS_STATUS_OK);
+ HS_SET_STATE(hs_fun, HS_S_PAGE_ADDR);
+ iowrite32(hs_fun, regs + CPU_PCIEA_TO_ARM_MSG0);
+ iowrite32(DRBL_HANDSHAKE, regs + CPU_PCIEA_TO_ARM_DRBL_REG);
+
+ break;
+
+ case HS_S_PAGE_ADDR:
+ case HS_S_QUERY_PAGE:
+ case HS_S_SEND_PAGE:
+ hs_header = (struct mvumi_hs_header *) mhba->handshake_page;
+ if (hs_header->page_code == HS_PAGE_FIRM_CAP) {
+ mhba->hba_total_pages =
+ ((struct mvumi_hs_page1 *) hs_header)->total_pages;
+
+ if (mhba->hba_total_pages == 0)
+ mhba->hba_total_pages = HS_PAGE_TOTAL-1;
+ }
+
+ if (hs_state == HS_S_QUERY_PAGE) {
+ if (mvumi_hs_process_page(mhba, hs_header)) {
+ HS_SET_STATE(hs_fun, HS_S_ABORT);
+ return -1;
+ }
+ if (mvumi_init_data(mhba)) {
+ HS_SET_STATE(hs_fun, HS_S_ABORT);
+ return -1;
+ }
+ } else if (hs_state == HS_S_PAGE_ADDR) {
+ hs_header->page_code = 0;
+ mhba->hba_total_pages = HS_PAGE_TOTAL-1;
+ }
+
+ if ((hs_header->page_code + 1) <= mhba->hba_total_pages) {
+ hs_header->page_code++;
+ if (hs_header->page_code != HS_PAGE_FIRM_CAP) {
+ mvumi_hs_build_page(mhba, hs_header);
+ HS_SET_STATE(hs_fun, HS_S_SEND_PAGE);
+ } else
+ HS_SET_STATE(hs_fun, HS_S_QUERY_PAGE);
+ } else
+ HS_SET_STATE(hs_fun, HS_S_END);
+
+ HS_SET_STATUS(hs_fun, HS_STATUS_OK);
+ iowrite32(hs_fun, regs + CPU_PCIEA_TO_ARM_MSG0);
+ iowrite32(DRBL_HANDSHAKE, regs + CPU_PCIEA_TO_ARM_DRBL_REG);
+ break;
+
+ case HS_S_END:
+ /* Set communication list ISR */
+ tmp = ioread32(regs + CPU_ENPOINTA_MASK_REG);
+ tmp |= INT_MAP_COMAOUT | INT_MAP_COMAERR;
+ iowrite32(tmp, regs + CPU_ENPOINTA_MASK_REG);
+ iowrite32(mhba->list_num_io, mhba->ib_shadow);
+ /* Set InBound List Avaliable count shadow */
+ iowrite32(lower_32_bits(mhba->ib_shadow_phys),
+ regs + CLA_INB_AVAL_COUNT_BASEL);
+ iowrite32(upper_32_bits(mhba->ib_shadow_phys),
+ regs + CLA_INB_AVAL_COUNT_BASEH);
+
+ /* Set OutBound List Avaliable count shadow */
+ iowrite32((mhba->list_num_io-1) | CL_POINTER_TOGGLE,
+ mhba->ob_shadow);
+ iowrite32(lower_32_bits(mhba->ob_shadow_phys), regs + 0x5B0);
+ iowrite32(upper_32_bits(mhba->ob_shadow_phys), regs + 0x5B4);
+
+ mhba->ib_cur_slot = (mhba->list_num_io - 1) | CL_POINTER_TOGGLE;
+ mhba->ob_cur_slot = (mhba->list_num_io - 1) | CL_POINTER_TOGGLE;
+ mhba->fw_state = FW_STATE_STARTED;
+
+ break;
+ default:
+ dev_err(&mhba->pdev->dev, "unknown handshake state [0x%x].\n",
+ hs_state);
+ return -1;
+ }
+ return 0;
+}
+
+static unsigned char mvumi_handshake_event(struct mvumi_hba *mhba)
+{
+ unsigned int isr_status;
+ unsigned long before;
+
+ before = jiffies;
+ mvumi_handshake(mhba);
+ do {
+ isr_status = mhba->instancet->read_fw_status_reg(mhba->mmio);
+
+ if (mhba->fw_state == FW_STATE_STARTED)
+ return 0;
+ if (time_after(jiffies, before + FW_MAX_DELAY * HZ)) {
+ dev_err(&mhba->pdev->dev,
+ "no handshake response at state 0x%x.\n",
+ mhba->fw_state);
+ dev_err(&mhba->pdev->dev,
+ "isr : global=0x%x,status=0x%x.\n",
+ mhba->global_isr, isr_status);
+ return -1;
+ }
+ rmb();
+ usleep_range(1000, 2000);
+ } while (!(isr_status & DRBL_HANDSHAKE_ISR));
+
+ return 0;
+}
+
+static unsigned char mvumi_check_handshake(struct mvumi_hba *mhba)
+{
+ void *regs = mhba->mmio;
+ unsigned int tmp;
+ unsigned long before;
+
+ before = jiffies;
+ tmp = ioread32(regs + CPU_ARM_TO_PCIEA_MSG1);
+ while ((tmp != HANDSHAKE_READYSTATE) && (tmp != HANDSHAKE_DONESTATE)) {
+ if (tmp != HANDSHAKE_READYSTATE)
+ iowrite32(DRBL_MU_RESET,
+ regs + CPU_PCIEA_TO_ARM_DRBL_REG);
+ if (time_after(jiffies, before + FW_MAX_DELAY * HZ)) {
+ dev_err(&mhba->pdev->dev,
+ "invalid signature [0x%x].\n", tmp);
+ return -1;
+ }
+ usleep_range(1000, 2000);
+ rmb();
+ tmp = ioread32(regs + CPU_ARM_TO_PCIEA_MSG1);
+ }
+
+ mhba->fw_state = FW_STATE_STARTING;
+ dev_dbg(&mhba->pdev->dev, "start firmware handshake...\n");
+ do {
+ if (mvumi_handshake_event(mhba)) {
+ dev_err(&mhba->pdev->dev,
+ "handshake failed at state 0x%x.\n",
+ mhba->fw_state);
+ return -1;
+ }
+ } while (mhba->fw_state != FW_STATE_STARTED);
+
+ dev_dbg(&mhba->pdev->dev, "firmware handshake done\n");
+
+ return 0;
+}
+
+static unsigned char mvumi_start(struct mvumi_hba *mhba)
+{
+ void *regs = mhba->mmio;
+ unsigned int tmp;
+ /* clear Door bell */
+ tmp = ioread32(regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+ iowrite32(tmp, regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+
+ iowrite32(0x3FFFFFFF, regs + CPU_ARM_TO_PCIEA_MASK_REG);
+ tmp = ioread32(regs + CPU_ENPOINTA_MASK_REG) | INT_MAP_DL_CPU2PCIEA;
+ iowrite32(tmp, regs + CPU_ENPOINTA_MASK_REG);
+ if (mvumi_check_handshake(mhba))
+ return -1;
+
+ return 0;
+}
+
+/**
+ * mvumi_complete_cmd - Completes a command
+ * @mhba: Adapter soft state
+ * @cmd: Command to be completed
+ */
+static void mvumi_complete_cmd(struct mvumi_hba *mhba, struct mvumi_cmd *cmd,
+ struct mvumi_rsp_frame *ob_frame)
+{
+ struct scsi_cmnd *scmd = cmd->scmd;
+
+ cmd->scmd->SCp.ptr = NULL;
+ scmd->result = ob_frame->req_status;
+
+ switch (ob_frame->req_status) {
+ case SAM_STAT_GOOD:
+ scmd->result |= DID_OK << 16;
+ break;
+ case SAM_STAT_BUSY:
+ scmd->result |= DID_BUS_BUSY << 16;
+ break;
+ case SAM_STAT_CHECK_CONDITION:
+ scmd->result |= (DID_OK << 16);
+ if (ob_frame->rsp_flag & CL_RSP_FLAG_SENSEDATA) {
+ memcpy(cmd->scmd->sense_buffer, ob_frame->payload,
+ sizeof(struct mvumi_sense_data));
+ scmd->result |= (DRIVER_SENSE << 24);
+ }
+ break;
+ default:
+ scmd->result |= (DRIVER_INVALID << 24) | (DID_ABORT << 16);
+ break;
+ }
+
+ if (scsi_bufflen(scmd)) {
+ if (scsi_sg_count(scmd)) {
+ pci_unmap_sg(mhba->pdev,
+ scsi_sglist(scmd),
+ scsi_sg_count(scmd),
+ (int) scmd->sc_data_direction);
+ } else {
+ pci_unmap_single(mhba->pdev,
+ scmd->SCp.dma_handle,
+ scsi_bufflen(scmd),
+ (int) scmd->sc_data_direction);
+
+ scmd->SCp.dma_handle = 0;
+ }
+ }
+ cmd->scmd->scsi_done(scmd);
+ mvumi_return_cmd(mhba, cmd);
+}
+static void mvumi_complete_internal_cmd(struct mvumi_hba *mhba,
+ struct mvumi_cmd *cmd,
+ struct mvumi_rsp_frame *ob_frame)
+{
+ if (atomic_read(&cmd->sync_cmd)) {
+ cmd->cmd_status = ob_frame->req_status;
+
+ if ((ob_frame->req_status == SAM_STAT_CHECK_CONDITION) &&
+ (ob_frame->rsp_flag & CL_RSP_FLAG_SENSEDATA) &&
+ cmd->data_buf) {
+ memcpy(cmd->data_buf, ob_frame->payload,
+ sizeof(struct mvumi_sense_data));
+ }
+ atomic_dec(&cmd->sync_cmd);
+ wake_up(&mhba->int_cmd_wait_q);
+ }
+}
+
+static void mvumi_show_event(struct mvumi_hba *mhba,
+ struct mvumi_driver_event *ptr)
+{
+ unsigned int i;
+
+ dev_warn(&mhba->pdev->dev,
+ "Event[0x%x] id[0x%x] severity[0x%x] device id[0x%x]\n",
+ ptr->sequence_no, ptr->event_id, ptr->severity, ptr->device_id);
+ if (ptr->param_count) {
+ printk(KERN_WARNING "Event param(len 0x%x): ",
+ ptr->param_count);
+ for (i = 0; i < ptr->param_count; i++)
+ printk(KERN_WARNING "0x%x ", ptr->params[i]);
+
+ printk(KERN_WARNING "\n");
+ }
+
+ if (ptr->sense_data_length) {
+ printk(KERN_WARNING "Event sense data(len 0x%x): ",
+ ptr->sense_data_length);
+ for (i = 0; i < ptr->sense_data_length; i++)
+ printk(KERN_WARNING "0x%x ", ptr->sense_data[i]);
+ printk(KERN_WARNING "\n");
+ }
+}
+
+static void mvumi_notification(struct mvumi_hba *mhba, u8 msg, void *buffer)
+{
+ if (msg == APICDB1_EVENT_GETEVENT) {
+ int i, count;
+ struct mvumi_driver_event *param = NULL;
+ struct mvumi_event_req *er = buffer;
+ count = er->count;
+ if (count > MAX_EVENTS_RETURNED) {
+ dev_err(&mhba->pdev->dev, "event count[0x%x] is bigger"
+ " than max event count[0x%x].\n",
+ count, MAX_EVENTS_RETURNED);
+ return;
+ }
+ for (i = 0; i < count; i++) {
+ param = &er->events[i];
+ mvumi_show_event(mhba, param);
+ }
+ }
+}
+
+static int mvumi_get_event(struct mvumi_hba *mhba, unsigned char msg)
+{
+ struct mvumi_cmd *cmd;
+ struct mvumi_msg_frame *frame;
+
+ cmd = mvumi_create_internal_cmd(mhba, 512);
+ if (!cmd)
+ return -1;
+ cmd->scmd = NULL;
+ cmd->cmd_status = REQ_STATUS_PENDING;
+ atomic_set(&cmd->sync_cmd, 0);
+ frame = cmd->frame;
+ frame->device_id = 0;
+ frame->cmd_flag = CMD_FLAG_DATA_IN;
+ frame->req_function = CL_FUN_SCSI_CMD;
+ frame->cdb_length = MAX_COMMAND_SIZE;
+ frame->data_transfer_length = sizeof(struct mvumi_event_req);
+ memset(frame->cdb, 0, MAX_COMMAND_SIZE);
+ frame->cdb[0] = APICDB0_EVENT;
+ frame->cdb[1] = msg;
+ mvumi_issue_blocked_cmd(mhba, cmd);
+
+ if (cmd->cmd_status != SAM_STAT_GOOD)
+ dev_err(&mhba->pdev->dev, "get event failed, status=0x%x.\n",
+ cmd->cmd_status);
+ else
+ mvumi_notification(mhba, cmd->frame->cdb[1], cmd->data_buf);
+
+ mvumi_delete_internal_cmd(mhba, cmd);
+ return 0;
+}
+
+static void mvumi_scan_events(struct work_struct *work)
+{
+ struct mvumi_events_wq *mu_ev =
+ container_of(work, struct mvumi_events_wq, work_q);
+
+ mvumi_get_event(mu_ev->mhba, mu_ev->event);
+ kfree(mu_ev);
+}
+
+static void mvumi_launch_events(struct mvumi_hba *mhba, u8 msg)
+{
+ struct mvumi_events_wq *mu_ev;
+
+ mu_ev = kzalloc(sizeof(*mu_ev), GFP_ATOMIC);
+ if (mu_ev) {
+ INIT_WORK(&mu_ev->work_q, mvumi_scan_events);
+ mu_ev->mhba = mhba;
+ mu_ev->event = msg;
+ mu_ev->param = NULL;
+ schedule_work(&mu_ev->work_q);
+ }
+}
+
+static void mvumi_handle_clob(struct mvumi_hba *mhba)
+{
+ struct mvumi_rsp_frame *ob_frame;
+ struct mvumi_cmd *cmd;
+ struct mvumi_ob_data *pool;
+
+ while (!list_empty(&mhba->free_ob_list)) {
+ pool = list_first_entry(&mhba->free_ob_list,
+ struct mvumi_ob_data, list);
+ list_del_init(&pool->list);
+ list_add_tail(&pool->list, &mhba->ob_data_list);
+
+ ob_frame = (struct mvumi_rsp_frame *) &pool->data[0];
+ cmd = mhba->tag_cmd[ob_frame->tag];
+
+ atomic_dec(&mhba->fw_outstanding);
+ mhba->tag_cmd[ob_frame->tag] = 0;
+ tag_release_one(mhba, &mhba->tag_pool, ob_frame->tag);
+ if (cmd->scmd)
+ mvumi_complete_cmd(mhba, cmd, ob_frame);
+ else
+ mvumi_complete_internal_cmd(mhba, cmd, ob_frame);
+ }
+ mhba->instancet->fire_cmd(mhba, NULL);
+}
+
+static irqreturn_t mvumi_isr_handler(int irq, void *devp)
+{
+ struct mvumi_hba *mhba = (struct mvumi_hba *) devp;
+ unsigned long flags;
+
+ spin_lock_irqsave(mhba->shost->host_lock, flags);
+ if (unlikely(mhba->instancet->clear_intr(mhba) || !mhba->global_isr)) {
+ spin_unlock_irqrestore(mhba->shost->host_lock, flags);
+ return IRQ_NONE;
+ }
+
+ if (mhba->global_isr & INT_MAP_DL_CPU2PCIEA) {
+ if (mhba->isr_status & DRBL_HANDSHAKE_ISR) {
+ dev_warn(&mhba->pdev->dev, "enter handshake again!\n");
+ mvumi_handshake(mhba);
+ }
+ if (mhba->isr_status & DRBL_EVENT_NOTIFY)
+ mvumi_launch_events(mhba, APICDB1_EVENT_GETEVENT);
+ }
+
+ if (mhba->global_isr & INT_MAP_COMAOUT)
+ mvumi_receive_ob_list_entry(mhba);
+
+ mhba->global_isr = 0;
+ mhba->isr_status = 0;
+ if (mhba->fw_state == FW_STATE_STARTED)
+ mvumi_handle_clob(mhba);
+ spin_unlock_irqrestore(mhba->shost->host_lock, flags);
+ return IRQ_HANDLED;
+}
+
+static enum mvumi_qc_result mvumi_send_command(struct mvumi_hba *mhba,
+ struct mvumi_cmd *cmd)
+{
+ void *ib_entry;
+ struct mvumi_msg_frame *ib_frame;
+ unsigned int frame_len;
+
+ ib_frame = cmd->frame;
+ if (unlikely(mhba->fw_state != FW_STATE_STARTED)) {
+ dev_dbg(&mhba->pdev->dev, "firmware not ready.\n");
+ return MV_QUEUE_COMMAND_RESULT_NO_RESOURCE;
+ }
+ if (tag_is_empty(&mhba->tag_pool)) {
+ dev_dbg(&mhba->pdev->dev, "no free tag.\n");
+ return MV_QUEUE_COMMAND_RESULT_NO_RESOURCE;
+ }
+ if (mvumi_get_ib_list_entry(mhba, &ib_entry))
+ return MV_QUEUE_COMMAND_RESULT_NO_RESOURCE;
+
+ cmd->frame->tag = tag_get_one(mhba, &mhba->tag_pool);
+ cmd->frame->request_id = mhba->io_seq++;
+ cmd->request_id = cmd->frame->request_id;
+ mhba->tag_cmd[cmd->frame->tag] = cmd;
+ frame_len = sizeof(*ib_frame) - 4 +
+ ib_frame->sg_counts * sizeof(struct mvumi_sgl);
+ memcpy(ib_entry, ib_frame, frame_len);
+ return MV_QUEUE_COMMAND_RESULT_SENT;
+}
+
+static void mvumi_fire_cmd(struct mvumi_hba *mhba, struct mvumi_cmd *cmd)
+{
+ unsigned short num_of_cl_sent = 0;
+ enum mvumi_qc_result result;
+
+ if (cmd)
+ list_add_tail(&cmd->queue_pointer, &mhba->waiting_req_list);
+
+ while (!list_empty(&mhba->waiting_req_list)) {
+ cmd = list_first_entry(&mhba->waiting_req_list,
+ struct mvumi_cmd, queue_pointer);
+ list_del_init(&cmd->queue_pointer);
+ result = mvumi_send_command(mhba, cmd);
+ switch (result) {
+ case MV_QUEUE_COMMAND_RESULT_SENT:
+ num_of_cl_sent++;
+ break;
+ case MV_QUEUE_COMMAND_RESULT_NO_RESOURCE:
+ list_add(&cmd->queue_pointer, &mhba->waiting_req_list);
+ if (num_of_cl_sent > 0)
+ mvumi_send_ib_list_entry(mhba);
+
+ return;
+ }
+ }
+ if (num_of_cl_sent > 0)
+ mvumi_send_ib_list_entry(mhba);
+}
+
+/**
+ * mvumi_enable_intr - Enables interrupts
+ * @regs: FW register set
+ */
+static void mvumi_enable_intr(void *regs)
+{
+ unsigned int mask;
+
+ iowrite32(0x3FFFFFFF, regs + CPU_ARM_TO_PCIEA_MASK_REG);
+ mask = ioread32(regs + CPU_ENPOINTA_MASK_REG);
+ mask |= INT_MAP_DL_CPU2PCIEA | INT_MAP_COMAOUT | INT_MAP_COMAERR;
+ iowrite32(mask, regs + CPU_ENPOINTA_MASK_REG);
+}
+
+/**
+ * mvumi_disable_intr -Disables interrupt
+ * @regs: FW register set
+ */
+static void mvumi_disable_intr(void *regs)
+{
+ unsigned int mask;
+
+ iowrite32(0, regs + CPU_ARM_TO_PCIEA_MASK_REG);
+ mask = ioread32(regs + CPU_ENPOINTA_MASK_REG);
+ mask &= ~(INT_MAP_DL_CPU2PCIEA | INT_MAP_COMAOUT | INT_MAP_COMAERR);
+ iowrite32(mask, regs + CPU_ENPOINTA_MASK_REG);
+}
+
+static int mvumi_clear_intr(void *extend)
+{
+ struct mvumi_hba *mhba = (struct mvumi_hba *) extend;
+ unsigned int status, isr_status = 0, tmp = 0;
+ void *regs = mhba->mmio;
+
+ status = ioread32(regs + CPU_MAIN_INT_CAUSE_REG);
+ if (!(status & INT_MAP_MU) || status == 0xFFFFFFFF)
+ return 1;
+ if (unlikely(status & INT_MAP_COMAERR)) {
+ tmp = ioread32(regs + CLA_ISR_CAUSE);
+ if (tmp & (CLIC_IN_ERR_IRQ | CLIC_OUT_ERR_IRQ))
+ iowrite32(tmp & (CLIC_IN_ERR_IRQ | CLIC_OUT_ERR_IRQ),
+ regs + CLA_ISR_CAUSE);
+ status ^= INT_MAP_COMAERR;
+ /* inbound or outbound parity error, command will timeout */
+ }
+ if (status & INT_MAP_COMAOUT) {
+ tmp = ioread32(regs + CLA_ISR_CAUSE);
+ if (tmp & CLIC_OUT_IRQ)
+ iowrite32(tmp & CLIC_OUT_IRQ, regs + CLA_ISR_CAUSE);
+ }
+ if (status & INT_MAP_DL_CPU2PCIEA) {
+ isr_status = ioread32(regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+ if (isr_status)
+ iowrite32(isr_status, regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+ }
+
+ mhba->global_isr = status;
+ mhba->isr_status = isr_status;
+
+ return 0;
+}
+
+/**
+ * mvumi_read_fw_status_reg - returns the current FW status value
+ * @regs: FW register set
+ */
+static unsigned int mvumi_read_fw_status_reg(void *regs)
+{
+ unsigned int status;
+
+ status = ioread32(regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+ if (status)
+ iowrite32(status, regs + CPU_ARM_TO_PCIEA_DRBL_REG);
+ return status;
+}
+
+static struct mvumi_instance_template mvumi_instance_template = {
+ .fire_cmd = mvumi_fire_cmd,
+ .enable_intr = mvumi_enable_intr,
+ .disable_intr = mvumi_disable_intr,
+ .clear_intr = mvumi_clear_intr,
+ .read_fw_status_reg = mvumi_read_fw_status_reg,
+};
+
+static int mvumi_slave_configure(struct scsi_device *sdev)
+{
+ struct mvumi_hba *mhba;
+ unsigned char bitcount = sizeof(unsigned char) * 8;
+
+ mhba = (struct mvumi_hba *) sdev->host->hostdata;
+ if (sdev->id >= mhba->max_target_id)
+ return -EINVAL;
+
+ mhba->target_map[sdev->id / bitcount] |= (1 << (sdev->id % bitcount));
+ return 0;
+}
+
+/**
+ * mvumi_build_frame - Prepares a direct cdb (DCDB) command
+ * @mhba: Adapter soft state
+ * @scmd: SCSI command
+ * @cmd: Command to be prepared in
+ *
+ * This function prepares CDB commands. These are typcially pass-through
+ * commands to the devices.
+ */
+static unsigned char mvumi_build_frame(struct mvumi_hba *mhba,
+ struct scsi_cmnd *scmd, struct mvumi_cmd *cmd)
+{
+ struct mvumi_msg_frame *pframe;
+
+ cmd->scmd = scmd;
+ cmd->cmd_status = REQ_STATUS_PENDING;
+ pframe = cmd->frame;
+ pframe->device_id = ((unsigned short) scmd->device->id) |
+ (((unsigned short) scmd->device->lun) << 8);
+ pframe->cmd_flag = 0;
+
+ switch (scmd->sc_data_direction) {
+ case DMA_NONE:
+ pframe->cmd_flag |= CMD_FLAG_NON_DATA;
+ break;
+ case DMA_FROM_DEVICE:
+ pframe->cmd_flag |= CMD_FLAG_DATA_IN;
+ break;
+ case DMA_TO_DEVICE:
+ pframe->cmd_flag |= CMD_FLAG_DATA_OUT;
+ break;
+ case DMA_BIDIRECTIONAL:
+ default:
+ dev_warn(&mhba->pdev->dev, "unexpected data direction[%d] "
+ "cmd[0x%x]\n", scmd->sc_data_direction, scmd->cmnd[0]);
+ goto error;
+ }
+
+ pframe->cdb_length = scmd->cmd_len;
+ memcpy(pframe->cdb, scmd->cmnd, pframe->cdb_length);
+ pframe->req_function = CL_FUN_SCSI_CMD;
+ if (scsi_bufflen(scmd)) {
+ if (mvumi_make_sgl(mhba, scmd, &pframe->payload[0],
+ &pframe->sg_counts))
+ goto error;
+
+ pframe->data_transfer_length = scsi_bufflen(scmd);
+ } else {
+ pframe->sg_counts = 0;
+ pframe->data_transfer_length = 0;
+ }
+ return 0;
+
+error:
+ scmd->result = (DID_OK << 16) | (DRIVER_SENSE << 24) |
+ SAM_STAT_CHECK_CONDITION;
+ scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x24,
+ 0);
+ return -1;
+}
+
+/**
+ * mvumi_queue_command - Queue entry point
+ * @scmd: SCSI command to be queued
+ * @done: Callback entry point
+ */
+static int mvumi_queue_command(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
+{
+ struct mvumi_cmd *cmd;
+ struct mvumi_hba *mhba;
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(shost->host_lock, irq_flags);
+ scsi_cmd_get_serial(shost, scmd);
+
+ mhba = (struct mvumi_hba *) shost->hostdata;
+ scmd->result = 0;
+ cmd = mvumi_get_cmd(mhba);
+ if (unlikely(!cmd)) {
+ spin_unlock_irqrestore(shost->host_lock, irq_flags);
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
+
+ if (unlikely(mvumi_build_frame(mhba, scmd, cmd)))
+ goto out_return_cmd;
+
+ cmd->scmd = scmd;
+ scmd->SCp.ptr = (char *) cmd;
+ mhba->instancet->fire_cmd(mhba, cmd);
+ spin_unlock_irqrestore(shost->host_lock, irq_flags);
+ return 0;
+
+out_return_cmd:
+ mvumi_return_cmd(mhba, cmd);
+ scmd->scsi_done(scmd);
+ spin_unlock_irqrestore(shost->host_lock, irq_flags);
+ return 0;
+}
+
+static enum blk_eh_timer_return mvumi_timed_out(struct scsi_cmnd *scmd)
+{
+ struct mvumi_cmd *cmd = (struct mvumi_cmd *) scmd->SCp.ptr;
+ struct Scsi_Host *host = scmd->device->host;
+ struct mvumi_hba *mhba = shost_priv(host);
+ unsigned long flags;
+
+ spin_lock_irqsave(mhba->shost->host_lock, flags);
+
+ if (mhba->tag_cmd[cmd->frame->tag]) {
+ mhba->tag_cmd[cmd->frame->tag] = 0;
+ tag_release_one(mhba, &mhba->tag_pool, cmd->frame->tag);
+ }
+ if (!list_empty(&cmd->queue_pointer))
+ list_del_init(&cmd->queue_pointer);
+ else
+ atomic_dec(&mhba->fw_outstanding);
+
+ scmd->result = (DRIVER_INVALID << 24) | (DID_ABORT << 16);
+ scmd->SCp.ptr = NULL;
+ if (scsi_bufflen(scmd)) {
+ if (scsi_sg_count(scmd)) {
+ pci_unmap_sg(mhba->pdev,
+ scsi_sglist(scmd),
+ scsi_sg_count(scmd),
+ (int)scmd->sc_data_direction);
+ } else {
+ pci_unmap_single(mhba->pdev,
+ scmd->SCp.dma_handle,
+ scsi_bufflen(scmd),
+ (int)scmd->sc_data_direction);
+
+ scmd->SCp.dma_handle = 0;
+ }
+ }
+ mvumi_return_cmd(mhba, cmd);
+ spin_unlock_irqrestore(mhba->shost->host_lock, flags);
+
+ return BLK_EH_NOT_HANDLED;
+}
+
+static int
+mvumi_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+ sector_t capacity, int geom[])
+{
+ int heads, sectors;
+ sector_t cylinders;
+ unsigned long tmp;
+
+ heads = 64;
+ sectors = 32;
+ tmp = heads * sectors;
+ cylinders = capacity;
+ sector_div(cylinders, tmp);
+
+ if (capacity >= 0x200000) {
+ heads = 255;
+ sectors = 63;
+ tmp = heads * sectors;
+ cylinders = capacity;
+ sector_div(cylinders, tmp);
+ }
+ geom[0] = heads;
+ geom[1] = sectors;
+ geom[2] = cylinders;
+
+ return 0;
+}
+
+static struct scsi_host_template mvumi_template = {
+
+ .module = THIS_MODULE,
+ .name = "Marvell Storage Controller",
+ .slave_configure = mvumi_slave_configure,
+ .queuecommand = mvumi_queue_command,
+ .eh_host_reset_handler = mvumi_host_reset,
+ .bios_param = mvumi_bios_param,
+ .this_id = -1,
+};
+
+static struct scsi_transport_template mvumi_transport_template = {
+ .eh_timed_out = mvumi_timed_out,
+};
+
+/**
+ * mvumi_init_fw - Initializes the FW
+ * @mhba: Adapter soft state
+ *
+ * This is the main function for initializing firmware.
+ */
+static int mvumi_init_fw(struct mvumi_hba *mhba)
+{
+ int ret = 0;
+
+ if (pci_request_regions(mhba->pdev, MV_DRIVER_NAME)) {
+ dev_err(&mhba->pdev->dev, "IO memory region busy!\n");
+ return -EBUSY;
+ }
+ ret = mvumi_map_pci_addr(mhba->pdev, mhba->base_addr);
+ if (ret)
+ goto fail_ioremap;
+
+ mhba->mmio = mhba->base_addr[0];
+
+ switch (mhba->pdev->device) {
+ case PCI_DEVICE_ID_MARVELL_MV9143:
+ mhba->instancet = &mvumi_instance_template;
+ mhba->io_seq = 0;
+ mhba->max_sge = MVUMI_MAX_SG_ENTRY;
+ mhba->request_id_enabled = 1;
+ break;
+ default:
+ dev_err(&mhba->pdev->dev, "device 0x%x not supported!\n",
+ mhba->pdev->device);
+ mhba->instancet = NULL;
+ ret = -EINVAL;
+ goto fail_alloc_mem;
+ }
+ dev_dbg(&mhba->pdev->dev, "device id : %04X is found.\n",
+ mhba->pdev->device);
+
+ mhba->handshake_page = kzalloc(HSP_MAX_SIZE, GFP_KERNEL);
+ if (!mhba->handshake_page) {
+ dev_err(&mhba->pdev->dev,
+ "failed to allocate memory for handshake\n");
+ ret = -ENOMEM;
+ goto fail_alloc_mem;
+ }
+ mhba->handshake_page_phys = virt_to_phys(mhba->handshake_page);
+
+ if (mvumi_start(mhba)) {
+ ret = -EINVAL;
+ goto fail_ready_state;
+ }
+ ret = mvumi_alloc_cmds(mhba);
+ if (ret)
+ goto fail_ready_state;
+
+ return 0;
+
+fail_ready_state:
+ mvumi_release_mem_resource(mhba);
+ kfree(mhba->handshake_page);
+fail_alloc_mem:
+ mvumi_unmap_pci_addr(mhba->pdev, mhba->base_addr);
+fail_ioremap:
+ pci_release_regions(mhba->pdev);
+
+ return ret;
+}
+
+/**
+ * mvumi_io_attach - Attaches this driver to SCSI mid-layer
+ * @mhba: Adapter soft state
+ */
+static int mvumi_io_attach(struct mvumi_hba *mhba)
+{
+ struct Scsi_Host *host = mhba->shost;
+ int ret;
+ unsigned int max_sg = (mhba->ib_max_size + 4 -
+ sizeof(struct mvumi_msg_frame)) / sizeof(struct mvumi_sgl);
+
+ host->irq = mhba->pdev->irq;
+ host->unique_id = mhba->unique_id;
+ host->can_queue = (mhba->max_io - 1) ? (mhba->max_io - 1) : 1;
+ host->sg_tablesize = mhba->max_sge > max_sg ? max_sg : mhba->max_sge;
+ host->max_sectors = mhba->max_transfer_size / 512;
+ host->cmd_per_lun = (mhba->max_io - 1) ? (mhba->max_io - 1) : 1;
+ host->max_id = mhba->max_target_id;
+ host->max_cmd_len = MAX_COMMAND_SIZE;
+ host->transportt = &mvumi_transport_template;
+
+ ret = scsi_add_host(host, &mhba->pdev->dev);
+ if (ret) {
+ dev_err(&mhba->pdev->dev, "scsi_add_host failed\n");
+ return ret;
+ }
+ mhba->fw_flag |= MVUMI_FW_ATTACH;
+ scsi_scan_host(host);
+
+ return 0;
+}
+
+/**
+ * mvumi_probe_one - PCI hotplug entry point
+ * @pdev: PCI device structure
+ * @id: PCI ids of supported hotplugged adapter
+ */
+static int __devinit mvumi_probe_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct Scsi_Host *host;
+ struct mvumi_hba *mhba;
+ int ret;
+
+ dev_dbg(&pdev->dev, " %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
+ pdev->vendor, pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
+
+ ret = pci_enable_device(pdev);
+ if (ret)
+ return ret;
+
+ pci_set_master(pdev);
+
+ if (IS_DMA64) {
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ if (ret) {
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (ret)
+ goto fail_set_dma_mask;
+ }
+ } else {
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (ret)
+ goto fail_set_dma_mask;
+ }
+
+ host = scsi_host_alloc(&mvumi_template, sizeof(*mhba));
+ if (!host) {
+ dev_err(&pdev->dev, "scsi_host_alloc failed\n");
+ ret = -ENOMEM;
+ goto fail_alloc_instance;
+ }
+ mhba = shost_priv(host);
+
+ INIT_LIST_HEAD(&mhba->cmd_pool);
+ INIT_LIST_HEAD(&mhba->ob_data_list);
+ INIT_LIST_HEAD(&mhba->free_ob_list);
+ INIT_LIST_HEAD(&mhba->res_list);
+ INIT_LIST_HEAD(&mhba->waiting_req_list);
+ atomic_set(&mhba->fw_outstanding, 0);
+ init_waitqueue_head(&mhba->int_cmd_wait_q);
+
+ mhba->pdev = pdev;
+ mhba->shost = host;
+ mhba->unique_id = pdev->bus->number << 8 | pdev->devfn;
+
+ ret = mvumi_init_fw(mhba);
+ if (ret)
+ goto fail_init_fw;
+
+ ret = request_irq(mhba->pdev->irq, mvumi_isr_handler, IRQF_SHARED,
+ "mvumi", mhba);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register IRQ\n");
+ goto fail_init_irq;
+ }
+ mhba->instancet->enable_intr(mhba->mmio);
+ pci_set_drvdata(pdev, mhba);
+
+ ret = mvumi_io_attach(mhba);
+ if (ret)
+ goto fail_io_attach;
+ dev_dbg(&pdev->dev, "probe mvumi driver successfully.\n");
+
+ return 0;
+
+fail_io_attach:
+ pci_set_drvdata(pdev, NULL);
+ mhba->instancet->disable_intr(mhba->mmio);
+ free_irq(mhba->pdev->irq, mhba);
+fail_init_irq:
+ mvumi_release_fw(mhba);
+fail_init_fw:
+ scsi_host_put(host);
+
+fail_alloc_instance:
+fail_set_dma_mask:
+ pci_disable_device(pdev);
+
+ return ret;
+}
+
+static void mvumi_detach_one(struct pci_dev *pdev)
+{
+ struct Scsi_Host *host;
+ struct mvumi_hba *mhba;
+
+ mhba = pci_get_drvdata(pdev);
+ host = mhba->shost;
+ scsi_remove_host(mhba->shost);
+ mvumi_flush_cache(mhba);
+
+ mhba->instancet->disable_intr(mhba->mmio);
+ free_irq(mhba->pdev->irq, mhba);
+ mvumi_release_fw(mhba);
+ scsi_host_put(host);
+ pci_set_drvdata(pdev, NULL);
+ pci_disable_device(pdev);
+ dev_dbg(&pdev->dev, "driver is removed!\n");
+}
+
+/**
+ * mvumi_shutdown - Shutdown entry point
+ * @device: Generic device structure
+ */
+static void mvumi_shutdown(struct pci_dev *pdev)
+{
+ struct mvumi_hba *mhba = pci_get_drvdata(pdev);
+
+ mvumi_flush_cache(mhba);
+}
+
+static int mvumi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct mvumi_hba *mhba = NULL;
+
+ mhba = pci_get_drvdata(pdev);
+ mvumi_flush_cache(mhba);
+
+ pci_set_drvdata(pdev, mhba);
+ mhba->instancet->disable_intr(mhba->mmio);
+ free_irq(mhba->pdev->irq, mhba);
+ mvumi_unmap_pci_addr(pdev, mhba->base_addr);
+ pci_release_regions(pdev);
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int mvumi_resume(struct pci_dev *pdev)
+{
+ int ret;
+ struct mvumi_hba *mhba = NULL;
+
+ mhba = pci_get_drvdata(pdev);
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_enable_wake(pdev, PCI_D0, 0);
+ pci_restore_state(pdev);
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "enable device failed\n");
+ return ret;
+ }
+ pci_set_master(pdev);
+ if (IS_DMA64) {
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ if (ret) {
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (ret)
+ goto fail;
+ }
+ } else {
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (ret)
+ goto fail;
+ }
+ ret = pci_request_regions(mhba->pdev, MV_DRIVER_NAME);
+ if (ret)
+ goto fail;
+ ret = mvumi_map_pci_addr(mhba->pdev, mhba->base_addr);
+ if (ret)
+ goto release_regions;
+
+ mhba->mmio = mhba->base_addr[0];
+ mvumi_reset(mhba->mmio);
+
+ if (mvumi_start(mhba)) {
+ ret = -EINVAL;
+ goto unmap_pci_addr;
+ }
+
+ ret = request_irq(mhba->pdev->irq, mvumi_isr_handler, IRQF_SHARED,
+ "mvumi", mhba);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register IRQ\n");
+ goto unmap_pci_addr;
+ }
+ mhba->instancet->enable_intr(mhba->mmio);
+
+ return 0;
+
+unmap_pci_addr:
+ mvumi_unmap_pci_addr(pdev, mhba->base_addr);
+release_regions:
+ pci_release_regions(pdev);
+fail:
+ pci_disable_device(pdev);
+
+ return ret;
+}
+
+static struct pci_driver mvumi_pci_driver = {
+
+ .name = MV_DRIVER_NAME,
+ .id_table = mvumi_pci_table,
+ .probe = mvumi_probe_one,
+ .remove = __devexit_p(mvumi_detach_one),
+ .shutdown = mvumi_shutdown,
+#ifdef CONFIG_PM
+ .suspend = mvumi_suspend,
+ .resume = mvumi_resume,
+#endif
+};
+
+/**
+ * mvumi_init - Driver load entry point
+ */
+static int __init mvumi_init(void)
+{
+ return pci_register_driver(&mvumi_pci_driver);
+}
+
+/**
+ * mvumi_exit - Driver unload entry point
+ */
+static void __exit mvumi_exit(void)
+{
+
+ pci_unregister_driver(&mvumi_pci_driver);
+}
+
+module_init(mvumi_init);
+module_exit(mvumi_exit);
diff --git a/drivers/scsi/mvumi.h b/drivers/scsi/mvumi.h
new file mode 100644
index 000000000000..10b9237566f0
--- /dev/null
+++ b/drivers/scsi/mvumi.h
@@ -0,0 +1,505 @@
+/*
+ * Marvell UMI head file
+ *
+ * Copyright 2011 Marvell. <jyli@marvell.com>
+ *
+ * This file is licensed under GPLv2.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef MVUMI_H
+#define MVUMI_H
+
+#define MAX_BASE_ADDRESS 6
+
+#define VER_MAJOR 1
+#define VER_MINOR 1
+#define VER_OEM 0
+#define VER_BUILD 1500
+
+#define MV_DRIVER_NAME "mvumi"
+#define PCI_VENDOR_ID_MARVELL_2 0x1b4b
+#define PCI_DEVICE_ID_MARVELL_MV9143 0x9143
+
+#define MVUMI_INTERNAL_CMD_WAIT_TIME 45
+
+#define IS_DMA64 (sizeof(dma_addr_t) == 8)
+
+enum mvumi_qc_result {
+ MV_QUEUE_COMMAND_RESULT_SENT = 0,
+ MV_QUEUE_COMMAND_RESULT_NO_RESOURCE,
+};
+
+enum {
+ /*******************************************/
+
+ /* ARM Mbus Registers Map */
+
+ /*******************************************/
+ CPU_MAIN_INT_CAUSE_REG = 0x20200,
+ CPU_MAIN_IRQ_MASK_REG = 0x20204,
+ CPU_MAIN_FIQ_MASK_REG = 0x20208,
+ CPU_ENPOINTA_MASK_REG = 0x2020C,
+ CPU_ENPOINTB_MASK_REG = 0x20210,
+
+ INT_MAP_COMAERR = 1 << 6,
+ INT_MAP_COMAIN = 1 << 7,
+ INT_MAP_COMAOUT = 1 << 8,
+ INT_MAP_COMBERR = 1 << 9,
+ INT_MAP_COMBIN = 1 << 10,
+ INT_MAP_COMBOUT = 1 << 11,
+
+ INT_MAP_COMAINT = (INT_MAP_COMAOUT | INT_MAP_COMAERR),
+ INT_MAP_COMBINT = (INT_MAP_COMBOUT | INT_MAP_COMBIN | INT_MAP_COMBERR),
+
+ INT_MAP_DL_PCIEA2CPU = 1 << 0,
+ INT_MAP_DL_CPU2PCIEA = 1 << 1,
+
+ /***************************************/
+
+ /* ARM Doorbell Registers Map */
+
+ /***************************************/
+ CPU_PCIEA_TO_ARM_DRBL_REG = 0x20400,
+ CPU_PCIEA_TO_ARM_MASK_REG = 0x20404,
+ CPU_ARM_TO_PCIEA_DRBL_REG = 0x20408,
+ CPU_ARM_TO_PCIEA_MASK_REG = 0x2040C,
+
+ DRBL_HANDSHAKE = 1 << 0,
+ DRBL_SOFT_RESET = 1 << 1,
+ DRBL_BUS_CHANGE = 1 << 2,
+ DRBL_EVENT_NOTIFY = 1 << 3,
+ DRBL_MU_RESET = 1 << 4,
+ DRBL_HANDSHAKE_ISR = DRBL_HANDSHAKE,
+
+ CPU_PCIEA_TO_ARM_MSG0 = 0x20430,
+ CPU_PCIEA_TO_ARM_MSG1 = 0x20434,
+ CPU_ARM_TO_PCIEA_MSG0 = 0x20438,
+ CPU_ARM_TO_PCIEA_MSG1 = 0x2043C,
+
+ /*******************************************/
+
+ /* ARM Communication List Registers Map */
+
+ /*******************************************/
+ CLA_INB_LIST_BASEL = 0x500,
+ CLA_INB_LIST_BASEH = 0x504,
+ CLA_INB_AVAL_COUNT_BASEL = 0x508,
+ CLA_INB_AVAL_COUNT_BASEH = 0x50C,
+ CLA_INB_DESTI_LIST_BASEL = 0x510,
+ CLA_INB_DESTI_LIST_BASEH = 0x514,
+ CLA_INB_WRITE_POINTER = 0x518,
+ CLA_INB_READ_POINTER = 0x51C,
+
+ CLA_OUTB_LIST_BASEL = 0x530,
+ CLA_OUTB_LIST_BASEH = 0x534,
+ CLA_OUTB_SOURCE_LIST_BASEL = 0x538,
+ CLA_OUTB_SOURCE_LIST_BASEH = 0x53C,
+ CLA_OUTB_COPY_POINTER = 0x544,
+ CLA_OUTB_READ_POINTER = 0x548,
+
+ CLA_ISR_CAUSE = 0x560,
+ CLA_ISR_MASK = 0x564,
+
+ INT_MAP_MU = (INT_MAP_DL_CPU2PCIEA | INT_MAP_COMAINT),
+
+ CL_POINTER_TOGGLE = 1 << 12,
+
+ CLIC_IN_IRQ = 1 << 0,
+ CLIC_OUT_IRQ = 1 << 1,
+ CLIC_IN_ERR_IRQ = 1 << 8,
+ CLIC_OUT_ERR_IRQ = 1 << 12,
+
+ CL_SLOT_NUM_MASK = 0xFFF,
+
+ /*
+ * Command flag is the flag for the CDB command itself
+ */
+ /* 1-non data; 0-data command */
+ CMD_FLAG_NON_DATA = 1 << 0,
+ CMD_FLAG_DMA = 1 << 1,
+ CMD_FLAG_PIO = 1 << 2,
+ /* 1-host read data */
+ CMD_FLAG_DATA_IN = 1 << 3,
+ /* 1-host write data */
+ CMD_FLAG_DATA_OUT = 1 << 4,
+
+ SCSI_CMD_MARVELL_SPECIFIC = 0xE1,
+ CDB_CORE_SHUTDOWN = 0xB,
+};
+
+#define APICDB0_EVENT 0xF4
+#define APICDB1_EVENT_GETEVENT 0
+#define MAX_EVENTS_RETURNED 6
+
+struct mvumi_driver_event {
+ u32 time_stamp;
+ u32 sequence_no;
+ u32 event_id;
+ u8 severity;
+ u8 param_count;
+ u16 device_id;
+ u32 params[4];
+ u8 sense_data_length;
+ u8 Reserved1;
+ u8 sense_data[30];
+};
+
+struct mvumi_event_req {
+ unsigned char count;
+ unsigned char reserved[3];
+ struct mvumi_driver_event events[MAX_EVENTS_RETURNED];
+};
+
+struct mvumi_events_wq {
+ struct work_struct work_q;
+ struct mvumi_hba *mhba;
+ unsigned int event;
+ void *param;
+};
+
+#define MVUMI_MAX_SG_ENTRY 32
+#define SGD_EOT (1L << 27)
+
+struct mvumi_sgl {
+ u32 baseaddr_l;
+ u32 baseaddr_h;
+ u32 flags;
+ u32 size;
+};
+
+struct mvumi_res {
+ struct list_head entry;
+ dma_addr_t bus_addr;
+ void *virt_addr;
+ unsigned int size;
+ unsigned short type; /* enum Resource_Type */
+};
+
+/* Resource type */
+enum resource_type {
+ RESOURCE_CACHED_MEMORY = 0,
+ RESOURCE_UNCACHED_MEMORY
+};
+
+struct mvumi_sense_data {
+ u8 error_eode:7;
+ u8 valid:1;
+ u8 segment_number;
+ u8 sense_key:4;
+ u8 reserved:1;
+ u8 incorrect_length:1;
+ u8 end_of_media:1;
+ u8 file_mark:1;
+ u8 information[4];
+ u8 additional_sense_length;
+ u8 command_specific_information[4];
+ u8 additional_sense_code;
+ u8 additional_sense_code_qualifier;
+ u8 field_replaceable_unit_code;
+ u8 sense_key_specific[3];
+};
+
+/* Request initiator must set the status to REQ_STATUS_PENDING. */
+#define REQ_STATUS_PENDING 0x80
+
+struct mvumi_cmd {
+ struct list_head queue_pointer;
+ struct mvumi_msg_frame *frame;
+ struct scsi_cmnd *scmd;
+ atomic_t sync_cmd;
+ void *data_buf;
+ unsigned short request_id;
+ unsigned char cmd_status;
+};
+
+/*
+ * the function type of the in bound frame
+ */
+#define CL_FUN_SCSI_CMD 0x1
+
+struct mvumi_msg_frame {
+ u16 device_id;
+ u16 tag;
+ u8 cmd_flag;
+ u8 req_function;
+ u8 cdb_length;
+ u8 sg_counts;
+ u32 data_transfer_length;
+ u16 request_id;
+ u16 reserved1;
+ u8 cdb[MAX_COMMAND_SIZE];
+ u32 payload[1];
+};
+
+/*
+ * the respond flag for data_payload of the out bound frame
+ */
+#define CL_RSP_FLAG_NODATA 0x0
+#define CL_RSP_FLAG_SENSEDATA 0x1
+
+struct mvumi_rsp_frame {
+ u16 device_id;
+ u16 tag;
+ u8 req_status;
+ u8 rsp_flag; /* Indicates the type of Data_Payload.*/
+ u16 request_id;
+ u32 payload[1];
+};
+
+struct mvumi_ob_data {
+ struct list_head list;
+ unsigned char data[0];
+};
+
+struct version_info {
+ u32 ver_major;
+ u32 ver_minor;
+ u32 ver_oem;
+ u32 ver_build;
+};
+
+#define FW_MAX_DELAY 30
+#define MVUMI_FW_BUSY (1U << 0)
+#define MVUMI_FW_ATTACH (1U << 1)
+#define MVUMI_FW_ALLOC (1U << 2)
+
+/*
+ * State is the state of the MU
+ */
+#define FW_STATE_IDLE 0
+#define FW_STATE_STARTING 1
+#define FW_STATE_HANDSHAKING 2
+#define FW_STATE_STARTED 3
+#define FW_STATE_ABORT 4
+
+#define HANDSHAKE_SIGNATURE 0x5A5A5A5AL
+#define HANDSHAKE_READYSTATE 0x55AA5AA5L
+#define HANDSHAKE_DONESTATE 0x55AAA55AL
+
+/* HandShake Status definition */
+#define HS_STATUS_OK 1
+#define HS_STATUS_ERR 2
+#define HS_STATUS_INVALID 3
+
+/* HandShake State/Cmd definition */
+#define HS_S_START 1
+#define HS_S_RESET 2
+#define HS_S_PAGE_ADDR 3
+#define HS_S_QUERY_PAGE 4
+#define HS_S_SEND_PAGE 5
+#define HS_S_END 6
+#define HS_S_ABORT 7
+#define HS_PAGE_VERIFY_SIZE 128
+
+#define HS_GET_STATE(a) (a & 0xFFFF)
+#define HS_GET_STATUS(a) ((a & 0xFFFF0000) >> 16)
+#define HS_SET_STATE(a, b) (a |= (b & 0xFFFF))
+#define HS_SET_STATUS(a, b) (a |= ((b & 0xFFFF) << 16))
+
+/* handshake frame */
+struct mvumi_hs_frame {
+ u16 size;
+ /* host information */
+ u8 host_type;
+ u8 reserved_1[1];
+ struct version_info host_ver; /* bios or driver version */
+
+ /* controller information */
+ u32 system_io_bus;
+ u32 slot_number;
+ u32 intr_level;
+ u32 intr_vector;
+
+ /* communication list configuration */
+ u32 ib_baseaddr_l;
+ u32 ib_baseaddr_h;
+ u32 ob_baseaddr_l;
+ u32 ob_baseaddr_h;
+
+ u8 ib_entry_size;
+ u8 ob_entry_size;
+ u8 ob_depth;
+ u8 ib_depth;
+
+ /* system time */
+ u64 seconds_since1970;
+};
+
+struct mvumi_hs_header {
+ u8 page_code;
+ u8 checksum;
+ u16 frame_length;
+ u32 frame_content[1];
+};
+
+/*
+ * the page code type of the handshake header
+ */
+#define HS_PAGE_FIRM_CAP 0x1
+#define HS_PAGE_HOST_INFO 0x2
+#define HS_PAGE_FIRM_CTL 0x3
+#define HS_PAGE_CL_INFO 0x4
+#define HS_PAGE_TOTAL 0x5
+
+#define HSP_SIZE(i) sizeof(struct mvumi_hs_page##i)
+
+#define HSP_MAX_SIZE ({ \
+ int size, m1, m2; \
+ m1 = max(HSP_SIZE(1), HSP_SIZE(3)); \
+ m2 = max(HSP_SIZE(2), HSP_SIZE(4)); \
+ size = max(m1, m2); \
+ size; \
+})
+
+/* The format of the page code for Firmware capability */
+struct mvumi_hs_page1 {
+ u8 pagecode;
+ u8 checksum;
+ u16 frame_length;
+
+ u16 number_of_ports;
+ u16 max_devices_support;
+ u16 max_io_support;
+ u16 umi_ver;
+ u32 max_transfer_size;
+ struct version_info fw_ver;
+ u8 cl_in_max_entry_size;
+ u8 cl_out_max_entry_size;
+ u8 cl_inout_list_depth;
+ u8 total_pages;
+ u16 capability;
+ u16 reserved1;
+};
+
+/* The format of the page code for Host information */
+struct mvumi_hs_page2 {
+ u8 pagecode;
+ u8 checksum;
+ u16 frame_length;
+
+ u8 host_type;
+ u8 reserved[3];
+ struct version_info host_ver;
+ u32 system_io_bus;
+ u32 slot_number;
+ u32 intr_level;
+ u32 intr_vector;
+ u64 seconds_since1970;
+};
+
+/* The format of the page code for firmware control */
+struct mvumi_hs_page3 {
+ u8 pagecode;
+ u8 checksum;
+ u16 frame_length;
+ u16 control;
+ u8 reserved[2];
+ u32 host_bufferaddr_l;
+ u32 host_bufferaddr_h;
+ u32 host_eventaddr_l;
+ u32 host_eventaddr_h;
+};
+
+struct mvumi_hs_page4 {
+ u8 pagecode;
+ u8 checksum;
+ u16 frame_length;
+ u32 ib_baseaddr_l;
+ u32 ib_baseaddr_h;
+ u32 ob_baseaddr_l;
+ u32 ob_baseaddr_h;
+ u8 ib_entry_size;
+ u8 ob_entry_size;
+ u8 ob_depth;
+ u8 ib_depth;
+};
+
+struct mvumi_tag {
+ unsigned short *stack;
+ unsigned short top;
+ unsigned short size;
+};
+
+struct mvumi_hba {
+ void *base_addr[MAX_BASE_ADDRESS];
+ void *mmio;
+ struct list_head cmd_pool;
+ struct Scsi_Host *shost;
+ wait_queue_head_t int_cmd_wait_q;
+ struct pci_dev *pdev;
+ unsigned int unique_id;
+ atomic_t fw_outstanding;
+ struct mvumi_instance_template *instancet;
+
+ void *ib_list;
+ dma_addr_t ib_list_phys;
+
+ void *ob_list;
+ dma_addr_t ob_list_phys;
+
+ void *ib_shadow;
+ dma_addr_t ib_shadow_phys;
+
+ void *ob_shadow;
+ dma_addr_t ob_shadow_phys;
+
+ void *handshake_page;
+ dma_addr_t handshake_page_phys;
+
+ unsigned int global_isr;
+ unsigned int isr_status;
+
+ unsigned short max_sge;
+ unsigned short max_target_id;
+ unsigned char *target_map;
+ unsigned int max_io;
+ unsigned int list_num_io;
+ unsigned int ib_max_size;
+ unsigned int ob_max_size;
+ unsigned int ib_max_size_setting;
+ unsigned int ob_max_size_setting;
+ unsigned int max_transfer_size;
+ unsigned char hba_total_pages;
+ unsigned char fw_flag;
+ unsigned char request_id_enabled;
+ unsigned short hba_capability;
+ unsigned short io_seq;
+
+ unsigned int ib_cur_slot;
+ unsigned int ob_cur_slot;
+ unsigned int fw_state;
+
+ struct list_head ob_data_list;
+ struct list_head free_ob_list;
+ struct list_head res_list;
+ struct list_head waiting_req_list;
+
+ struct mvumi_tag tag_pool;
+ struct mvumi_cmd **tag_cmd;
+};
+
+struct mvumi_instance_template {
+ void (*fire_cmd)(struct mvumi_hba *, struct mvumi_cmd *);
+ void (*enable_intr)(void *) ;
+ void (*disable_intr)(void *);
+ int (*clear_intr)(void *);
+ unsigned int (*read_fw_status_reg)(void *);
+};
+
+extern struct timezone sys_tz;
+#endif
diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
index 861b5cebaeae..a0703514eb0f 100644
--- a/drivers/scsi/osd/Kconfig
+++ b/drivers/scsi/osd/Kconfig
@@ -11,10 +11,6 @@
# it under the terms of the GNU General Public version 2 License as
# published by the Free Software Foundation
#
-# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
-# How is it done properly?
-#
-
config SCSI_OSD_INITIATOR
tristate "OSD-Initiator library"
depends on SCSI
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 8b7db1e53c10..b7b92f7be2aa 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -567,11 +567,11 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
value = pm8001_cr32(pm8001_ha, 0, 0x44);
offset = value & 0x03FFFFFF;
PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Scratchpad 0 Offset: %x \n", offset));
+ pm8001_printk("Scratchpad 0 Offset: %x\n", offset));
pcilogic = (value & 0xFC000000) >> 26;
pcibar = get_pci_bar_index(pcilogic);
PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Scratchpad 0 PCI BAR: %d \n", pcibar));
+ pm8001_printk("Scratchpad 0 PCI BAR: %d\n", pcibar));
pm8001_ha->main_cfg_tbl_addr = base_addr =
pm8001_ha->io_mem[pcibar].memvirtaddr + offset;
pm8001_ha->general_stat_tbl_addr =
@@ -1245,7 +1245,7 @@ static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
if (mpi_msg_free_get(circularQ, 64, &pMessage) < 0) {
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("No free mpi buffer \n"));
+ pm8001_printk("No free mpi buffer\n"));
return -1;
}
BUG_ON(!payload);
@@ -1262,7 +1262,7 @@ static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar,
circularQ->pi_offset, circularQ->producer_idx);
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("after PI= %d CI= %d \n", circularQ->producer_idx,
+ pm8001_printk("after PI= %d CI= %d\n", circularQ->producer_idx,
circularQ->consumer_index));
return 0;
}
@@ -1474,7 +1474,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
switch (status) {
case IO_SUCCESS:
PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS"
- ",param = %d \n", param));
+ ",param = %d\n", param));
if (param == 0) {
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_GOOD;
@@ -1490,14 +1490,14 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
break;
case IO_ABORTED:
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ABORTED IOMB Tag \n"));
+ pm8001_printk("IO_ABORTED IOMB Tag\n"));
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
break;
case IO_UNDERFLOW:
/* SSP Completion with error */
PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW"
- ",param = %d \n", param));
+ ",param = %d\n", param));
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_UNDERRUN;
ts->residual = param;
@@ -1649,6 +1649,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ break;
default:
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", status));
@@ -1937,14 +1938,14 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->buf_valid_size = sizeof(*resp);
} else
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("response to large \n"));
+ pm8001_printk("response to large\n"));
}
if (pm8001_dev)
pm8001_dev->running_req--;
break;
case IO_ABORTED:
PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ABORTED IOMB Tag \n"));
+ pm8001_printk("IO_ABORTED IOMB Tag\n"));
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
if (pm8001_dev)
@@ -2728,11 +2729,11 @@ static int mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
u32 phy_op = le32_to_cpu(pPayload->phyop_phyid) & OP_BITS;
if (status != 0) {
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("%x phy execute %x phy op failed! \n",
+ pm8001_printk("%x phy execute %x phy op failed!\n",
phy_id, phy_op));
} else
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("%x phy execute %x phy op success! \n",
+ pm8001_printk("%x phy execute %x phy op success!\n",
phy_id, phy_op));
return 0;
}
@@ -3018,7 +3019,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
case PORT_INVALID:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" PortInvalid portID %d \n", port_id));
+ pm8001_printk(" PortInvalid portID %d\n", port_id));
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk(" Last phy Down and port invalid\n"));
port->port_attached = 0;
@@ -3027,7 +3028,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
case PORT_IN_RESET:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Port In Reset portID %d \n", port_id));
+ pm8001_printk(" Port In Reset portID %d\n", port_id));
break;
case PORT_NOT_ESTABLISHED:
PM8001_MSG_DBG(pm8001_ha,
@@ -3220,7 +3221,7 @@ mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
pm8001_printk(" status = 0x%x\n", status));
for (i = 0; i < GENERAL_EVENT_PAYLOAD; i++)
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("inb_IOMB_payload[0x%x] 0x%x, \n", i,
+ pm8001_printk("inb_IOMB_payload[0x%x] 0x%x,\n", i,
pPayload->inb_IOMB_payload[i]));
return 0;
}
@@ -3312,12 +3313,12 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
break;
case HW_EVENT_SAS_PHY_UP:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_START_STATUS \n"));
+ pm8001_printk("HW_EVENT_PHY_START_STATUS\n"));
hw_event_sas_phy_up(pm8001_ha, piomb);
break;
case HW_EVENT_SATA_PHY_UP:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_SATA_PHY_UP \n"));
+ pm8001_printk("HW_EVENT_SATA_PHY_UP\n"));
hw_event_sata_phy_up(pm8001_ha, piomb);
break;
case HW_EVENT_PHY_STOP_STATUS:
@@ -3329,12 +3330,12 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
break;
case HW_EVENT_SATA_SPINUP_HOLD:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD \n"));
+ pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n"));
sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
break;
case HW_EVENT_PHY_DOWN:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_DOWN \n"));
+ pm8001_printk("HW_EVENT_PHY_DOWN\n"));
sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
phy->phy_attached = 0;
phy->phy_state = 0;
@@ -3446,7 +3447,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
break;
case HW_EVENT_LINK_ERR_PHY_RESET_FAILED:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED \n"));
+ pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n"));
pm8001_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_PHY_RESET_FAILED,
port_id, phy_id, 0, 0);
@@ -3456,25 +3457,25 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
break;
case HW_EVENT_PORT_RESET_TIMER_TMO:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO \n"));
+ pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n"));
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_PORT_RECOVERY_TIMER_TMO:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO \n"));
+ pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"));
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_PORT_RECOVER:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RECOVER \n"));
+ pm8001_printk("HW_EVENT_PORT_RECOVER\n"));
break;
case HW_EVENT_PORT_RESET_COMPLETE:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE \n"));
+ pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE\n"));
break;
case EVENT_BROADCAST_ASYNCH_EVENT:
PM8001_MSG_DBG(pm8001_ha,
@@ -3502,21 +3503,21 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
switch (opc) {
case OPC_OUB_ECHO:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO \n"));
+ PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO\n"));
break;
case OPC_OUB_HW_EVENT:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_HW_EVENT \n"));
+ pm8001_printk("OPC_OUB_HW_EVENT\n"));
mpi_hw_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_COMP:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SSP_COMP \n"));
+ pm8001_printk("OPC_OUB_SSP_COMP\n"));
mpi_ssp_completion(pm8001_ha, piomb);
break;
case OPC_OUB_SMP_COMP:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SMP_COMP \n"));
+ pm8001_printk("OPC_OUB_SMP_COMP\n"));
mpi_smp_completion(pm8001_ha, piomb);
break;
case OPC_OUB_LOCAL_PHY_CNTRL:
@@ -3526,26 +3527,26 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
case OPC_OUB_DEV_REGIST:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_DEV_REGIST \n"));
+ pm8001_printk("OPC_OUB_DEV_REGIST\n"));
mpi_reg_resp(pm8001_ha, piomb);
break;
case OPC_OUB_DEREG_DEV:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("unresgister the deviece \n"));
+ pm8001_printk("unresgister the deviece\n"));
mpi_dereg_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_DEV_HANDLE:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GET_DEV_HANDLE \n"));
+ pm8001_printk("OPC_OUB_GET_DEV_HANDLE\n"));
break;
case OPC_OUB_SATA_COMP:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SATA_COMP \n"));
+ pm8001_printk("OPC_OUB_SATA_COMP\n"));
mpi_sata_completion(pm8001_ha, piomb);
break;
case OPC_OUB_SATA_EVENT:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SATA_EVENT \n"));
+ pm8001_printk("OPC_OUB_SATA_EVENT\n"));
mpi_sata_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_EVENT:
@@ -3858,19 +3859,19 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
circularQ = &pm8001_ha->inbnd_q_tbl[0];
if (task->data_dir == PCI_DMA_NONE) {
ATAP = 0x04; /* no data*/
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data \n"));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data\n"));
} else if (likely(!task->ata_task.device_control_reg_update)) {
if (task->ata_task.dma_xfer) {
ATAP = 0x06; /* DMA */
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA \n"));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA\n"));
} else {
ATAP = 0x05; /* PIO*/
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO \n"));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO\n"));
}
if (task->ata_task.use_ncq &&
dev->sata_dev.command_set != ATAPI_COMMAND_SET) {
ATAP = 0x07; /* FPDMA */
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA \n"));
+ PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n"));
}
}
if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag))
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 172cefb6deb9..c21a2163f9f6 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -61,7 +61,7 @@ static struct scsi_host_template pm8001_sht = {
.name = DRV_NAME,
.queuecommand = sas_queuecommand,
.target_alloc = sas_target_alloc,
- .slave_configure = pm8001_slave_configure,
+ .slave_configure = sas_slave_configure,
.slave_destroy = sas_slave_destroy,
.scan_finished = pm8001_scan_finished,
.scan_start = pm8001_scan_start,
@@ -76,7 +76,7 @@ static struct scsi_host_template pm8001_sht = {
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_bus_reset_handler = sas_eh_bus_reset_handler,
- .slave_alloc = pm8001_slave_alloc,
+ .slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = pm8001_host_attrs,
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 6ae059ebb4bb..fb3dc9978861 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -210,26 +210,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id);
break;
default:
- rc = -EOPNOTSUPP;
+ rc = -ENOSYS;
}
msleep(300);
return rc;
}
-int pm8001_slave_alloc(struct scsi_device *scsi_dev)
-{
- struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
- if (dev_is_sata(dev)) {
- /* We don't need to rescan targets
- * if REPORT_LUNS request is failed
- */
- if (scsi_dev->lun > 0)
- return -ENXIO;
- scsi_dev->tagged_supported = 1;
- }
- return sas_slave_alloc(scsi_dev);
-}
-
/**
* pm8001_scan_start - we should enable all HBA phys by sending the phy_start
* command to HBA.
@@ -314,22 +300,7 @@ static int pm8001_task_prep_ssp(struct pm8001_hba_info *pm8001_ha,
{
return PM8001_CHIP_DISP->ssp_io_req(pm8001_ha, ccb);
}
-int pm8001_slave_configure(struct scsi_device *sdev)
-{
- struct domain_device *dev = sdev_to_domain_dev(sdev);
- int ret = sas_slave_configure(sdev);
- if (ret)
- return ret;
- if (dev_is_sata(dev)) {
- #ifdef PM8001_DISABLE_NCQ
- struct ata_port *ap = dev->sata_dev.ap;
- struct ata_device *adev = ap->link.device;
- adev->flags |= ATA_DFLAG_NCQ_OFF;
- scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1);
- #endif
- }
- return 0;
-}
+
/* Find the local port id that's attached to this device */
static int sas_find_local_port_id(struct domain_device *dev)
{
@@ -385,21 +356,8 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
do {
dev = t->dev;
pm8001_dev = dev->lldd_dev;
- if (DEV_IS_GONE(pm8001_dev)) {
- if (pm8001_dev) {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("device %d not ready.\n",
- pm8001_dev->device_id));
- } else {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("device %016llx not "
- "ready.\n", SAS_ADDR(dev->sas_addr)));
- }
- rc = SAS_PHY_DOWN;
- goto out_done;
- }
port = &pm8001_ha->port[sas_find_local_port_id(dev)];
- if (!port->port_attached) {
+ if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
if (sas_protocol_ata(t->task_proto)) {
struct task_status_struct *ts = &t->task_status;
ts->resp = SAS_TASK_UNDELIVERED;
@@ -651,7 +609,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
flag = 1; /* directly sata*/
}
} /*register this device to HBA*/
- PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device \n"));
+ PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device\n"));
PM8001_CHIP_DISP->reg_dev_req(pm8001_ha, pm8001_device, flag);
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
wait_for_completion(&completion);
@@ -669,30 +627,6 @@ int pm8001_dev_found(struct domain_device *dev)
return pm8001_dev_found_notify(dev);
}
-/**
- * pm8001_alloc_task - allocate a task structure for TMF
- */
-static struct sas_task *pm8001_alloc_task(void)
-{
- struct sas_task *task = kzalloc(sizeof(*task), GFP_KERNEL);
- if (task) {
- INIT_LIST_HEAD(&task->list);
- spin_lock_init(&task->task_state_lock);
- task->task_state_flags = SAS_TASK_STATE_PENDING;
- init_timer(&task->timer);
- init_completion(&task->completion);
- }
- return task;
-}
-
-static void pm8001_free_task(struct sas_task *task)
-{
- if (task) {
- BUG_ON(!list_empty(&task->list));
- kfree(task);
- }
-}
-
static void pm8001_task_done(struct sas_task *task)
{
if (!del_timer(&task->timer))
@@ -728,7 +662,7 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
for (retry = 0; retry < 3; retry++) {
- task = pm8001_alloc_task();
+ task = sas_alloc_task(GFP_KERNEL);
if (!task)
return -ENOMEM;
@@ -789,14 +723,13 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
SAS_ADDR(dev->sas_addr),
task->task_status.resp,
task->task_status.stat));
- pm8001_free_task(task);
+ sas_free_task(task);
task = NULL;
}
}
ex_err:
BUG_ON(retry == 3 && task != NULL);
- if (task != NULL)
- pm8001_free_task(task);
+ sas_free_task(task);
return res;
}
@@ -811,7 +744,7 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
struct sas_task *task = NULL;
for (retry = 0; retry < 3; retry++) {
- task = pm8001_alloc_task();
+ task = sas_alloc_task(GFP_KERNEL);
if (!task)
return -ENOMEM;
@@ -864,14 +797,13 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
SAS_ADDR(dev->sas_addr),
task->task_status.resp,
task->task_status.stat));
- pm8001_free_task(task);
+ sas_free_task(task);
task = NULL;
}
}
ex_err:
BUG_ON(retry == 3 && task != NULL);
- if (task != NULL)
- pm8001_free_task(task);
+ sas_free_task(task);
return res;
}
@@ -1026,13 +958,14 @@ int pm8001_query_task(struct sas_task *task)
/* The task is still in Lun, release it then */
case TMF_RESP_FUNC_SUCC:
PM8001_EH_DBG(pm8001_ha,
- pm8001_printk("The task is still in Lun \n"));
+ pm8001_printk("The task is still in Lun\n"));
+ break;
/* The task is not in Lun or failed, reset the phy */
case TMF_RESP_FUNC_FAILED:
case TMF_RESP_FUNC_COMPLETE:
PM8001_EH_DBG(pm8001_ha,
pm8001_printk("The task is not in Lun or failed,"
- " reset the phy \n"));
+ " reset the phy\n"));
break;
}
}
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index b97c8ab0c20e..93959febe205 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -471,8 +471,6 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
struct sas_task *task, struct pm8001_ccb_info *ccb, u32 ccb_idx);
int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
void *funcdata);
-int pm8001_slave_alloc(struct scsi_device *scsi_dev);
-int pm8001_slave_configure(struct scsi_device *sdev);
void pm8001_scan_start(struct Scsi_Host *shost);
int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time);
int pm8001_queue_command(struct sas_task *task, const int num,
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index d079f9a3c6b3..b86db84d6f32 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -39,7 +39,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/hdreg.h>
-#include <linux/version.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <asm/irq.h>
diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h
index f920baf3ff24..ca496c7474e3 100644
--- a/drivers/scsi/pmcraid.h
+++ b/drivers/scsi/pmcraid.h
@@ -24,7 +24,6 @@
#ifndef _PMCRAID_H
#define _PMCRAID_H
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/completion.h>
#include <linux/list.h>
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index a31e05f3bfd4..ac326c41e931 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -23,11 +23,23 @@ qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj,
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
+ int rval = 0;
if (ha->fw_dump_reading == 0)
return 0;
- return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
+ if (IS_QLA82XX(ha)) {
+ if (off < ha->md_template_size) {
+ rval = memory_read_from_buffer(buf, count,
+ &off, ha->md_tmplt_hdr, ha->md_template_size);
+ return rval;
+ }
+ off -= ha->md_template_size;
+ rval = memory_read_from_buffer(buf, count,
+ &off, ha->md_dump, ha->md_dump_size);
+ return rval;
+ } else
+ return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
ha->fw_dump_len);
}
@@ -41,12 +53,6 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
struct qla_hw_data *ha = vha->hw;
int reading;
- if (IS_QLA82XX(ha)) {
- ql_dbg(ql_dbg_user, vha, 0x705b,
- "Firmware dump not supported for ISP82xx\n");
- return count;
- }
-
if (off != 0)
return (0);
@@ -59,6 +65,10 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
ql_log(ql_log_info, vha, 0x705d,
"Firmware dump cleared on (%ld).\n", vha->host_no);
+ if (IS_QLA82XX(vha->hw)) {
+ qla82xx_md_free(vha);
+ qla82xx_md_prep(vha);
+ }
ha->fw_dump_reading = 0;
ha->fw_dumped = 0;
break;
@@ -75,10 +85,29 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
qla2x00_alloc_fw_dump(vha);
break;
case 3:
- qla2x00_system_error(vha);
+ if (IS_QLA82XX(ha)) {
+ qla82xx_idc_lock(ha);
+ qla82xx_set_reset_owner(vha);
+ qla82xx_idc_unlock(ha);
+ } else
+ qla2x00_system_error(vha);
+ break;
+ case 4:
+ if (IS_QLA82XX(ha)) {
+ if (ha->md_tmplt_hdr)
+ ql_dbg(ql_dbg_user, vha, 0x705b,
+ "MiniDump supported with this firmware.\n");
+ else
+ ql_dbg(ql_dbg_user, vha, 0x709d,
+ "MiniDump not supported with this firmware.\n");
+ }
+ break;
+ case 5:
+ if (IS_QLA82XX(ha))
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
}
- return (count);
+ return -EINVAL;
}
static struct bin_attribute sysfs_fw_dump_attr = {
@@ -122,7 +151,7 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size ||
!ha->isp_ops->write_nvram)
- return 0;
+ return -EINVAL;
/* Checksum NVRAM. */
if (IS_FWI2_CAPABLE(ha)) {
@@ -165,7 +194,7 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj,
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_chip_reset(vha);
- return (count);
+ return count;
}
static struct bin_attribute sysfs_nvram_attr = {
@@ -239,10 +268,10 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
int val, valid;
if (off)
- return 0;
+ return -EINVAL;
if (unlikely(pci_channel_offline(ha->pdev)))
- return 0;
+ return -EAGAIN;
if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1)
return -EINVAL;
@@ -253,7 +282,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
case 0:
if (ha->optrom_state != QLA_SREADING &&
ha->optrom_state != QLA_SWRITING)
- break;
+ return -EINVAL;
ha->optrom_state = QLA_SWAITING;
@@ -266,7 +295,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
break;
case 1:
if (ha->optrom_state != QLA_SWAITING)
- break;
+ return -EINVAL;
ha->optrom_region_start = start;
ha->optrom_region_size = start + size > ha->optrom_size ?
@@ -280,7 +309,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
"(%x).\n", ha->optrom_region_size);
ha->optrom_state = QLA_SWAITING;
- return count;
+ return -ENOMEM;
}
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
@@ -299,7 +328,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
break;
case 2:
if (ha->optrom_state != QLA_SWAITING)
- break;
+ return -EINVAL;
/*
* We need to be more restrictive on which FLASH regions are
@@ -347,7 +376,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
"(%x)\n", ha->optrom_region_size);
ha->optrom_state = QLA_SWAITING;
- return count;
+ return -ENOMEM;
}
ql_dbg(ql_dbg_user, vha, 0x7067,
@@ -358,7 +387,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
break;
case 3:
if (ha->optrom_state != QLA_SWRITING)
- break;
+ return -ENOMEM;
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x7068,
@@ -374,7 +403,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
ha->optrom_region_start, ha->optrom_region_size);
break;
default:
- count = -EINVAL;
+ return -EINVAL;
}
return count;
}
@@ -398,10 +427,10 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,
struct qla_hw_data *ha = vha->hw;
if (unlikely(pci_channel_offline(ha->pdev)))
- return 0;
+ return -EAGAIN;
if (!capable(CAP_SYS_ADMIN))
- return 0;
+ return -EINVAL;
if (IS_NOCACHE_VPD_TYPE(ha))
ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
@@ -438,17 +467,17 @@ qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj,
/* Update flash version information for 4Gb & above. */
if (!IS_FWI2_CAPABLE(ha))
- goto done;
+ return -EINVAL;
tmp_data = vmalloc(256);
if (!tmp_data) {
ql_log(ql_log_warn, vha, 0x706b,
"Unable to allocate memory for VPD information update.\n");
- goto done;
+ return -ENOMEM;
}
ha->isp_ops->get_flash_version(vha, tmp_data);
vfree(tmp_data);
-done:
+
return count;
}
@@ -505,8 +534,7 @@ do_read:
"Unable to read SFP data (%x/%x/%x).\n", rval,
addr, offset);
- count = 0;
- break;
+ return -EIO;
}
memcpy(buf, ha->sfp_data, SFP_BLOCK_SIZE);
buf += SFP_BLOCK_SIZE;
@@ -536,7 +564,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
int type;
if (off != 0)
- return 0;
+ return -EINVAL;
type = simple_strtol(buf, NULL, 10);
switch (type) {
@@ -546,13 +574,18 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
scsi_block_requests(vha->host);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ if (IS_QLA82XX(ha)) {
+ qla82xx_idc_lock(ha);
+ qla82xx_set_reset_owner(vha);
+ qla82xx_idc_unlock(ha);
+ }
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_chip_reset(vha);
scsi_unblock_requests(vha->host);
break;
case 0x2025d:
if (!IS_QLA81XX(ha))
- break;
+ return -EPERM;
ql_log(ql_log_info, vha, 0x706f,
"Issuing MPI reset.\n");
@@ -571,7 +604,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
if (!IS_QLA82XX(ha) || vha != base_vha) {
ql_log(ql_log_info, vha, 0x7071,
"FCoE ctx reset no supported.\n");
- return count;
+ return -EPERM;
}
ql_log(ql_log_info, vha, 0x7072,
@@ -607,7 +640,7 @@ qla2x00_sysfs_write_edc(struct file *filp, struct kobject *kobj,
ha->edc_data_len = 0;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count < 8)
- return 0;
+ return -EINVAL;
if (!ha->edc_data) {
ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
@@ -615,7 +648,7 @@ qla2x00_sysfs_write_edc(struct file *filp, struct kobject *kobj,
if (!ha->edc_data) {
ql_log(ql_log_warn, vha, 0x7073,
"Unable to allocate memory for EDC write.\n");
- return 0;
+ return -ENOMEM;
}
}
@@ -634,9 +667,9 @@ qla2x00_sysfs_write_edc(struct file *filp, struct kobject *kobj,
dev, adr, len, opt);
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x7074,
- "Unable to write EDC (%x) %02x:%04x:%02x:%02x\n",
+ "Unable to write EDC (%x) %02x:%04x:%02x:%02hhx\n",
rval, dev, adr, opt, len, buf[8]);
- return 0;
+ return -EIO;
}
return count;
@@ -665,7 +698,7 @@ qla2x00_sysfs_write_edc_status(struct file *filp, struct kobject *kobj,
ha->edc_data_len = 0;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count < 8)
- return 0;
+ return -EINVAL;
if (!ha->edc_data) {
ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
@@ -673,7 +706,7 @@ qla2x00_sysfs_write_edc_status(struct file *filp, struct kobject *kobj,
if (!ha->edc_data) {
ql_log(ql_log_warn, vha, 0x708c,
"Unable to allocate memory for EDC status.\n");
- return 0;
+ return -ENOMEM;
}
}
@@ -693,7 +726,7 @@ qla2x00_sysfs_write_edc_status(struct file *filp, struct kobject *kobj,
ql_log(ql_log_info, vha, 0x7075,
"Unable to write EDC status (%x) %02x:%04x:%02x.\n",
rval, dev, adr, opt, len);
- return 0;
+ return -EIO;
}
ha->edc_data_len = len;
@@ -805,7 +838,7 @@ qla2x00_sysfs_read_dcbx_tlv(struct file *filp, struct kobject *kobj,
if (!ha->dcbx_tlv) {
ql_log(ql_log_warn, vha, 0x7078,
"Unable to allocate memory for DCBX TLV read-data.\n");
- return 0;
+ return -ENOMEM;
}
do_read:
@@ -817,7 +850,7 @@ do_read:
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x7079,
"Unable to read DCBX TLV (%x).\n", rval);
- count = 0;
+ return -EIO;
}
memcpy(buf, ha->dcbx_tlv, count);
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 07d1767cd26b..8b641a8a0c74 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -704,6 +704,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
if ((ha->current_topology == ISP_CFG_F ||
+ (atomic_read(&vha->loop_state) == LOOP_DOWN) ||
(IS_QLA81XX(ha) &&
le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE
&& req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
@@ -1447,6 +1448,148 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
}
static int
+qla2x00_update_fru_versions(struct fc_bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = bsg_job->shost;
+ scsi_qla_host_t *vha = shost_priv(host);
+ struct qla_hw_data *ha = vha->hw;
+ int rval = 0;
+ uint8_t bsg[DMA_POOL_SIZE];
+ struct qla_image_version_list *list = (void *)bsg;
+ struct qla_image_version *image;
+ uint32_t count;
+ dma_addr_t sfp_dma;
+ void *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+ if (!sfp) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, list, sizeof(bsg));
+
+ image = list->version;
+ count = list->count;
+ while (count--) {
+ memcpy(sfp, &image->field_info, sizeof(image->field_info));
+ rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
+ image->field_address.device, image->field_address.offset,
+ sizeof(image->field_info), image->field_address.option);
+ if (rval) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_MAILBOX;
+ goto dealloc;
+ }
+ image++;
+ }
+
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
+
+dealloc:
+ dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
+
+done:
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ bsg_job->reply->result = DID_OK << 16;
+ bsg_job->job_done(bsg_job);
+
+ return 0;
+}
+
+static int
+qla2x00_read_fru_status(struct fc_bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = bsg_job->shost;
+ scsi_qla_host_t *vha = shost_priv(host);
+ struct qla_hw_data *ha = vha->hw;
+ int rval = 0;
+ uint8_t bsg[DMA_POOL_SIZE];
+ struct qla_status_reg *sr = (void *)bsg;
+ dma_addr_t sfp_dma;
+ uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+ if (!sfp) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, sr, sizeof(*sr));
+
+ rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
+ sr->field_address.device, sr->field_address.offset,
+ sizeof(sr->status_reg), sr->field_address.option);
+ sr->status_reg = *sfp;
+
+ if (rval) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_MAILBOX;
+ goto dealloc;
+ }
+
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, sr, sizeof(*sr));
+
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
+
+dealloc:
+ dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
+
+done:
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ bsg_job->reply->reply_payload_rcv_len = sizeof(*sr);
+ bsg_job->reply->result = DID_OK << 16;
+ bsg_job->job_done(bsg_job);
+
+ return 0;
+}
+
+static int
+qla2x00_write_fru_status(struct fc_bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = bsg_job->shost;
+ scsi_qla_host_t *vha = shost_priv(host);
+ struct qla_hw_data *ha = vha->hw;
+ int rval = 0;
+ uint8_t bsg[DMA_POOL_SIZE];
+ struct qla_status_reg *sr = (void *)bsg;
+ dma_addr_t sfp_dma;
+ uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+ if (!sfp) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, sr, sizeof(*sr));
+
+ *sfp = sr->status_reg;
+ rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
+ sr->field_address.device, sr->field_address.offset,
+ sizeof(sr->status_reg), sr->field_address.option);
+
+ if (rval) {
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+ EXT_STATUS_MAILBOX;
+ goto dealloc;
+ }
+
+ bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
+
+dealloc:
+ dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
+
+done:
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ bsg_job->reply->result = DID_OK << 16;
+ bsg_job->job_done(bsg_job);
+
+ return 0;
+}
+
+static int
qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
{
switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
@@ -1474,6 +1617,15 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
case QL_VND_UPDATE_FLASH:
return qla2x00_update_optrom(bsg_job);
+ case QL_VND_SET_FRU_VERSION:
+ return qla2x00_update_fru_versions(bsg_job);
+
+ case QL_VND_READ_FRU_STATUS:
+ return qla2x00_read_fru_status(bsg_job);
+
+ case QL_VND_WRITE_FRU_STATUS:
+ return qla2x00_write_fru_status(bsg_job);
+
default:
bsg_job->reply->result = (DID_ERROR << 16);
bsg_job->job_done(bsg_job);
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 0f0f54e35f06..70caa63a8930 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -16,6 +16,16 @@
#define QL_VND_FCP_PRIO_CFG_CMD 0x06
#define QL_VND_READ_FLASH 0x07
#define QL_VND_UPDATE_FLASH 0x08
+#define QL_VND_SET_FRU_VERSION 0x0B
+#define QL_VND_READ_FRU_STATUS 0x0C
+#define QL_VND_WRITE_FRU_STATUS 0x0D
+
+/* BSG Vendor specific subcode returns */
+#define EXT_STATUS_OK 0
+#define EXT_STATUS_ERR 1
+#define EXT_STATUS_INVALID_PARAM 6
+#define EXT_STATUS_MAILBOX 11
+#define EXT_STATUS_NO_MEMORY 17
/* BSG definations for interpreting CommandSent field */
#define INT_DEF_LB_LOOPBACK_CMD 0
@@ -141,4 +151,36 @@ struct qla_port_param {
uint16_t mode;
uint16_t speed;
} __attribute__ ((packed));
+
+
+/* FRU VPD */
+
+#define MAX_FRU_SIZE 36
+
+struct qla_field_address {
+ uint16_t offset;
+ uint16_t device;
+ uint16_t option;
+} __packed;
+
+struct qla_field_info {
+ uint8_t version[MAX_FRU_SIZE];
+} __packed;
+
+struct qla_image_version {
+ struct qla_field_address field_address;
+ struct qla_field_info field_info;
+} __packed;
+
+struct qla_image_version_list {
+ uint32_t count;
+ struct qla_image_version version[0];
+} __packed;
+
+struct qla_status_reg {
+ struct qla_field_address field_address;
+ uint8_t status_reg;
+ uint8_t reserved[7];
+} __packed;
+
#endif
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index d79cd8a5f831..9df4787715c0 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -12,7 +12,7 @@
* | Level | Last Value Used | Holes |
* ----------------------------------------------------------------------
* | Module Init and Probe | 0x0116 | |
- * | Mailbox commands | 0x1126 | |
+ * | Mailbox commands | 0x1129 | |
* | Device Discovery | 0x2083 | |
* | Queue Command and IO tracing | 0x302e | 0x3008 |
* | DPC Thread | 0x401c | |
@@ -22,7 +22,7 @@
* | Task Management | 0x8041 | |
* | AER/EEH | 0x900f | |
* | Virtual Port | 0xa007 | |
- * | ISP82XX Specific | 0xb04f | |
+ * | ISP82XX Specific | 0xb051 | |
* | MultiQ | 0xc00b | |
* | Misc | 0xd00b | |
* ----------------------------------------------------------------------
@@ -403,7 +403,7 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
return ptr + sizeof(struct qla2xxx_mq_chain);
}
-static void
+void
qla2xxx_dump_post_process(scsi_qla_host_t *vha, int rval)
{
struct qla_hw_data *ha = vha->hw;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index a03eaf40f377..fcf052c50bf5 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2438,7 +2438,8 @@ struct qla_hw_data {
uint32_t quiesce_owner:1;
uint32_t thermal_supported:1;
uint32_t isp82xx_reset_hdlr_active:1;
- /* 26 bits */
+ uint32_t isp82xx_reset_owner:1;
+ /* 28 bits */
} flags;
/* This spinlock is used to protect "io transactions", you must
@@ -2822,6 +2823,12 @@ struct qla_hw_data {
uint8_t fw_type;
__le32 file_prd_off; /* File firmware product offset */
+
+ uint32_t md_template_size;
+ void *md_tmplt_hdr;
+ dma_addr_t md_tmplt_hdr_dma;
+ void *md_dump;
+ uint32_t md_dump_size;
};
/*
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 29b1a3e28231..ce32d8135c9e 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -104,6 +104,8 @@ extern int ql2xenablehba_err_chk;
extern int ql2xtargetreset;
extern int ql2xdontresethba;
extern unsigned int ql2xmaxlun;
+extern int ql2xmdcapmask;
+extern int ql2xmdenable;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -407,6 +409,8 @@ extern void qla2x00_beacon_blink(struct scsi_qla_host *);
extern int qla24xx_beacon_on(struct scsi_qla_host *);
extern int qla24xx_beacon_off(struct scsi_qla_host *);
extern void qla24xx_beacon_blink(struct scsi_qla_host *);
+extern int qla82xx_beacon_on(struct scsi_qla_host *);
+extern int qla82xx_beacon_off(struct scsi_qla_host *);
extern uint8_t *qla2x00_read_optrom_data(struct scsi_qla_host *, uint8_t *,
uint32_t, uint32_t);
@@ -442,6 +446,7 @@ extern void qla2x00_dump_buffer_zipped(uint8_t *, uint32_t);
extern void ql_dump_regs(uint32_t, scsi_qla_host_t *, int32_t);
extern void ql_dump_buffer(uint32_t, scsi_qla_host_t *, int32_t,
uint8_t *, uint32_t);
+extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int);
/*
* Global Function Prototypes in qla_gs.c source file.
@@ -569,7 +574,10 @@ extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *);
extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *);
extern void qla82xx_start_iocbs(srb_t *);
extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *);
+extern int qla82xx_check_md_needed(scsi_qla_host_t *);
extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *);
+extern int qla82xx_mbx_beacon_ctl(scsi_qla_host_t *, int);
+extern char *qdev_state(uint32_t);
/* BSG related functions */
extern int qla24xx_bsg_request(struct fc_bsg_job *);
@@ -579,4 +587,14 @@ extern int qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *,
dma_addr_t, size_t, uint32_t);
extern int qla2x00_get_idma_speed(scsi_qla_host_t *, uint16_t,
uint16_t *, uint16_t *);
+
+/* Minidump related functions */
+extern int qla82xx_md_get_template_size(scsi_qla_host_t *);
+extern int qla82xx_md_get_template(scsi_qla_host_t *);
+extern int qla82xx_md_alloc(scsi_qla_host_t *);
+extern void qla82xx_md_free(scsi_qla_host_t *);
+extern int qla82xx_md_collect(scsi_qla_host_t *);
+extern void qla82xx_md_prep(scsi_qla_host_t *);
+extern void qla82xx_set_reset_owner(scsi_qla_host_t *);
+
#endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 37da04d3db26..f03e915f1877 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1480,13 +1480,19 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
if (rval == QLA_SUCCESS) {
enable_82xx_npiv:
fw_major_version = ha->fw_major_version;
- rval = qla2x00_get_fw_version(vha,
- &ha->fw_major_version,
- &ha->fw_minor_version,
- &ha->fw_subminor_version,
- &ha->fw_attributes, &ha->fw_memory_size,
- ha->mpi_version, &ha->mpi_capabilities,
- ha->phy_version);
+ if (IS_QLA82XX(ha))
+ qla82xx_check_md_needed(vha);
+ else {
+ rval = qla2x00_get_fw_version(vha,
+ &ha->fw_major_version,
+ &ha->fw_minor_version,
+ &ha->fw_subminor_version,
+ &ha->fw_attributes,
+ &ha->fw_memory_size,
+ ha->mpi_version,
+ &ha->mpi_capabilities,
+ ha->phy_version);
+ }
if (rval != QLA_SUCCESS)
goto failed;
ha->flags.npiv_supported = 0;
@@ -1503,10 +1509,8 @@ enable_82xx_npiv:
&ha->fw_xcb_count, NULL, NULL,
&ha->max_npiv_vports, NULL);
- if (!fw_major_version && ql2xallocfwdump) {
- if (!IS_QLA82XX(ha))
- qla2x00_alloc_fw_dump(vha);
- }
+ if (!fw_major_version && ql2xallocfwdump)
+ qla2x00_alloc_fw_dump(vha);
}
} else {
ql_log(ql_log_fatal, vha, 0x00cd,
@@ -1924,7 +1928,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
rval = qla84xx_init_chip(vha);
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn,
- vha, 0x8043,
+ vha, 0x8026,
"Init chip failed.\n");
break;
}
@@ -1933,7 +1937,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
cs84xx_time = jiffies - cs84xx_time;
wtime += cs84xx_time;
mtime += cs84xx_time;
- ql_dbg(ql_dbg_taskm, vha, 0x8042,
+ ql_dbg(ql_dbg_taskm, vha, 0x8025,
"Increasing wait time by %ld. "
"New time %ld.\n", cs84xx_time,
wtime);
@@ -5443,11 +5447,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
/* Update the firmware version */
- qla2x00_get_fw_version(vha, &ha->fw_major_version,
- &ha->fw_minor_version, &ha->fw_subminor_version,
- &ha->fw_attributes, &ha->fw_memory_size,
- ha->mpi_version, &ha->mpi_capabilities,
- ha->phy_version);
+ status = qla82xx_check_md_needed(vha);
if (ha->fce) {
ha->flags.fce_enabled = 1;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 8a7591f035e6..3474e86e98ab 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -2060,6 +2060,11 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
case ELS_IOCB_TYPE:
qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE);
break;
+ case MARKER_TYPE:
+ /* Do nothing in this case, this check is to prevent it
+ * from falling into default case
+ */
+ break;
default:
/* Type Not Supported. */
ql_dbg(ql_dbg_async, vha, 0x5042,
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index f7604ea1af83..3b3cec9f6ac2 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -4186,3 +4186,130 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha)
return rval;
}
+
+int
+qla82xx_md_get_template_size(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ int rval = QLA_FUNCTION_FAILED;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x111f, "Entered %s.\n", __func__);
+
+ memset(mcp->mb, 0 , sizeof(mcp->mb));
+ mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
+ mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
+ mcp->mb[2] = LSW(RQST_TMPLT_SIZE);
+ mcp->mb[3] = MSW(RQST_TMPLT_SIZE);
+
+ mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|
+ MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+
+ mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
+ mcp->tov = MBX_TOV_SECONDS;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ /* Always copy back return mailbox values. */
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1120,
+ "mailbox command FAILED=0x%x, subcode=%x.\n",
+ (mcp->mb[1] << 16) | mcp->mb[0],
+ (mcp->mb[3] << 16) | mcp->mb[2]);
+ } else {
+ ql_dbg(ql_dbg_mbx, vha, 0x1121, "Done %s.\n", __func__);
+ ha->md_template_size = ((mcp->mb[3] << 16) | mcp->mb[2]);
+ if (!ha->md_template_size) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1122,
+ "Null template size obtained.\n");
+ rval = QLA_FUNCTION_FAILED;
+ }
+ }
+ return rval;
+}
+
+int
+qla82xx_md_get_template(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ int rval = QLA_FUNCTION_FAILED;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x1123, "Entered %s.\n", __func__);
+
+ ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev,
+ ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL);
+ if (!ha->md_tmplt_hdr) {
+ ql_log(ql_log_warn, vha, 0x1124,
+ "Unable to allocate memory for Minidump template.\n");
+ return rval;
+ }
+
+ memset(mcp->mb, 0 , sizeof(mcp->mb));
+ mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
+ mcp->mb[1] = MSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE);
+ mcp->mb[2] = LSW(RQST_TMPLT);
+ mcp->mb[3] = MSW(RQST_TMPLT);
+ mcp->mb[4] = LSW(LSD(ha->md_tmplt_hdr_dma));
+ mcp->mb[5] = MSW(LSD(ha->md_tmplt_hdr_dma));
+ mcp->mb[6] = LSW(MSD(ha->md_tmplt_hdr_dma));
+ mcp->mb[7] = MSW(MSD(ha->md_tmplt_hdr_dma));
+ mcp->mb[8] = LSW(ha->md_template_size);
+ mcp->mb[9] = MSW(ha->md_template_size);
+
+ mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->out_mb = MBX_11|MBX_10|MBX_9|MBX_8|
+ MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1125,
+ "mailbox command FAILED=0x%x, subcode=%x.\n",
+ ((mcp->mb[1] << 16) | mcp->mb[0]),
+ ((mcp->mb[3] << 16) | mcp->mb[2]));
+ } else
+ ql_dbg(ql_dbg_mbx, vha, 0x1126, "Done %s.\n", __func__);
+ return rval;
+}
+
+int
+qla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable)
+{
+ int rval;
+ struct qla_hw_data *ha = vha->hw;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ if (!IS_QLA82XX(ha))
+ return QLA_FUNCTION_FAILED;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x1127,
+ "Entered %s.\n", __func__);
+
+ memset(mcp, 0, sizeof(mbx_cmd_t));
+ mcp->mb[0] = MBC_SET_LED_CONFIG;
+ if (enable)
+ mcp->mb[7] = 0xE;
+ else
+ mcp->mb[7] = 0xD;
+
+ mcp->out_mb = MBX_7|MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = 30;
+ mcp->flags = 0;
+
+ rval = qla2x00_mailbox_command(vha, mcp);
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1128,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ } else {
+ ql_dbg(ql_dbg_mbx, vha, 0x1129,
+ "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 049807cda419..94bded5ddce4 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -7,6 +7,8 @@
#include "qla_def.h"
#include <linux/delay.h>
#include <linux/pci.h>
+#include <linux/ratelimit.h>
+#include <linux/vmalloc.h>
#include <scsi/scsi_tcq.h>
#define MASK(n) ((1ULL<<(n))-1)
@@ -328,7 +330,7 @@ unsigned qla82xx_crb_hub_agt[64] = {
};
/* Device states */
-char *qdev_state[] = {
+char *q_dev_state[] = {
"Unknown",
"Cold",
"Initializing",
@@ -339,6 +341,11 @@ char *qdev_state[] = {
"Quiescent",
};
+char *qdev_state(uint32_t dev_state)
+{
+ return q_dev_state[dev_state];
+}
+
/*
* In: 'off' is offset from CRB space in 128M pci map
* Out: 'off' is 2M pci map addr
@@ -2355,9 +2362,13 @@ qla82xx_need_reset(struct qla_hw_data *ha)
uint32_t drv_state;
int rval;
- drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
- rval = drv_state & (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
- return rval;
+ if (ha->flags.isp82xx_reset_owner)
+ return 1;
+ else {
+ drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+ rval = drv_state & (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
+ return rval;
+ }
}
static inline void
@@ -2374,8 +2385,8 @@ qla82xx_set_rst_ready(struct qla_hw_data *ha)
drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
}
drv_state |= (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
- ql_log(ql_log_info, vha, 0x00bb,
- "drv_state = 0x%x.\n", drv_state);
+ ql_dbg(ql_dbg_init, vha, 0x00bb,
+ "drv_state = 0x%08x.\n", drv_state);
qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state);
}
@@ -2598,7 +2609,7 @@ qla2xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address;
*dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
*dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
- *dsd_seg++ = cpu_to_le32(dsd_list_len);
+ cmd_pkt->fcp_data_dseg_len = cpu_to_le32(dsd_list_len);
} else {
*cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
*cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
@@ -3529,6 +3540,7 @@ static void
qla82xx_need_reset_handler(scsi_qla_host_t *vha)
{
uint32_t dev_state, drv_state, drv_active;
+ uint32_t active_mask = 0;
unsigned long reset_timeout;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
@@ -3541,15 +3553,32 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
qla82xx_idc_lock(ha);
}
- qla82xx_set_rst_ready(ha);
+ drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+ if (!ha->flags.isp82xx_reset_owner) {
+ ql_dbg(ql_dbg_p3p, vha, 0xb028,
+ "reset_acknowledged by 0x%x\n", ha->portnum);
+ qla82xx_set_rst_ready(ha);
+ } else {
+ active_mask = ~(QLA82XX_DRV_ACTIVE << (ha->portnum * 4));
+ drv_active &= active_mask;
+ ql_dbg(ql_dbg_p3p, vha, 0xb029,
+ "active_mask: 0x%08x\n", active_mask);
+ }
/* wait for 10 seconds for reset ack from all functions */
reset_timeout = jiffies + (ha->nx_reset_timeout * HZ);
drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+ dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
- while (drv_state != drv_active) {
+ ql_dbg(ql_dbg_p3p, vha, 0xb02a,
+ "drv_state: 0x%08x, drv_active: 0x%08x, "
+ "dev_state: 0x%08x, active_mask: 0x%08x\n",
+ drv_state, drv_active, dev_state, active_mask);
+
+ while (drv_state != drv_active &&
+ dev_state != QLA82XX_DEV_INITIALIZING) {
if (time_after_eq(jiffies, reset_timeout)) {
ql_log(ql_log_warn, vha, 0x00b5,
"Reset timeout.\n");
@@ -3560,23 +3589,87 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
qla82xx_idc_lock(ha);
drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+ if (ha->flags.isp82xx_reset_owner)
+ drv_active &= active_mask;
+ dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
}
- dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+ ql_dbg(ql_dbg_p3p, vha, 0xb02b,
+ "drv_state: 0x%08x, drv_active: 0x%08x, "
+ "dev_state: 0x%08x, active_mask: 0x%08x\n",
+ drv_state, drv_active, dev_state, active_mask);
+
ql_log(ql_log_info, vha, 0x00b6,
"Device state is 0x%x = %s.\n",
dev_state,
- dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
+ dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
/* Force to DEV_COLD unless someone else is starting a reset */
- if (dev_state != QLA82XX_DEV_INITIALIZING) {
+ if (dev_state != QLA82XX_DEV_INITIALIZING &&
+ dev_state != QLA82XX_DEV_COLD) {
ql_log(ql_log_info, vha, 0x00b7,
"HW State: COLD/RE-INIT.\n");
qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD);
+ if (ql2xmdenable) {
+ if (qla82xx_md_collect(vha))
+ ql_log(ql_log_warn, vha, 0xb02c,
+ "Not able to collect minidump.\n");
+ } else
+ ql_log(ql_log_warn, vha, 0xb04f,
+ "Minidump disabled.\n");
}
}
int
+qla82xx_check_md_needed(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint16_t fw_major_version, fw_minor_version, fw_subminor_version;
+ int rval = QLA_SUCCESS;
+
+ fw_major_version = ha->fw_major_version;
+ fw_minor_version = ha->fw_minor_version;
+ fw_subminor_version = ha->fw_subminor_version;
+
+ rval = qla2x00_get_fw_version(vha, &ha->fw_major_version,
+ &ha->fw_minor_version, &ha->fw_subminor_version,
+ &ha->fw_attributes, &ha->fw_memory_size,
+ ha->mpi_version, &ha->mpi_capabilities,
+ ha->phy_version);
+
+ if (rval != QLA_SUCCESS)
+ return rval;
+
+ if (ql2xmdenable) {
+ if (!ha->fw_dumped) {
+ if (fw_major_version != ha->fw_major_version ||
+ fw_minor_version != ha->fw_minor_version ||
+ fw_subminor_version != ha->fw_subminor_version) {
+
+ ql_log(ql_log_info, vha, 0xb02d,
+ "Firmware version differs "
+ "Previous version: %d:%d:%d - "
+ "New version: %d:%d:%d\n",
+ ha->fw_major_version,
+ ha->fw_minor_version,
+ ha->fw_subminor_version,
+ fw_major_version, fw_minor_version,
+ fw_subminor_version);
+ /* Release MiniDump resources */
+ qla82xx_md_free(vha);
+ /* ALlocate MiniDump resources */
+ qla82xx_md_prep(vha);
+ } else
+ ql_log(ql_log_info, vha, 0xb02e,
+ "Firmware dump available to retrieve\n",
+ vha->host_no);
+ }
+ }
+ return rval;
+}
+
+
+int
qla82xx_check_fw_alive(scsi_qla_host_t *vha)
{
uint32_t fw_heartbeat_counter;
@@ -3637,7 +3730,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
ql_log(ql_log_info, vha, 0x009b,
"Device state is 0x%x = %s.\n",
dev_state,
- dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
+ dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
/* wait for 30 seconds for device to go ready */
dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ);
@@ -3659,26 +3752,33 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
ql_log(ql_log_info, vha, 0x009d,
"Device state is 0x%x = %s.\n",
dev_state,
- dev_state < MAX_STATES ? qdev_state[dev_state] :
+ dev_state < MAX_STATES ? qdev_state(dev_state) :
"Unknown");
}
switch (dev_state) {
case QLA82XX_DEV_READY:
+ qla82xx_check_md_needed(vha);
+ ha->flags.isp82xx_reset_owner = 0;
goto exit;
case QLA82XX_DEV_COLD:
rval = qla82xx_device_bootstrap(vha);
- goto exit;
+ break;
case QLA82XX_DEV_INITIALIZING:
qla82xx_idc_unlock(ha);
msleep(1000);
qla82xx_idc_lock(ha);
break;
case QLA82XX_DEV_NEED_RESET:
- if (!ql2xdontresethba)
- qla82xx_need_reset_handler(vha);
+ if (!ql2xdontresethba)
+ qla82xx_need_reset_handler(vha);
+ else {
+ qla82xx_idc_unlock(ha);
+ msleep(1000);
+ qla82xx_idc_lock(ha);
+ }
dev_init_timeout = jiffies +
- (ha->nx_dev_init_timeout * HZ);
+ (ha->nx_dev_init_timeout * HZ);
break;
case QLA82XX_DEV_NEED_QUIESCENT:
qla82xx_need_qsnt_handler(vha);
@@ -3791,6 +3891,28 @@ int qla82xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
return rval;
}
+void
+qla82xx_set_reset_owner(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t dev_state;
+
+ dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+ if (dev_state == QLA82XX_DEV_READY) {
+ ql_log(ql_log_info, vha, 0xb02f,
+ "HW State: NEED RESET\n");
+ qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+ QLA82XX_DEV_NEED_RESET);
+ ha->flags.isp82xx_reset_owner = 1;
+ ql_dbg(ql_dbg_p3p, vha, 0xb030,
+ "reset_owner is 0x%x\n", ha->portnum);
+ } else
+ ql_log(ql_log_info, vha, 0xb031,
+ "Device state is 0x%x = %s.\n",
+ dev_state,
+ dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
+}
+
/*
* qla82xx_abort_isp
* Resets ISP and aborts all outstanding commands.
@@ -3806,7 +3928,6 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
{
int rval;
struct qla_hw_data *ha = vha->hw;
- uint32_t dev_state;
if (vha->device_flags & DFLG_DEV_FAILED) {
ql_log(ql_log_warn, vha, 0x8024,
@@ -3816,16 +3937,7 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
ha->flags.isp82xx_reset_hdlr_active = 1;
qla82xx_idc_lock(ha);
- dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
- if (dev_state == QLA82XX_DEV_READY) {
- ql_log(ql_log_info, vha, 0x8025,
- "HW State: NEED RESET.\n");
- qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
- QLA82XX_DEV_NEED_RESET);
- } else
- ql_log(ql_log_info, vha, 0x8026,
- "Hw State: %s.\n", dev_state < MAX_STATES ?
- qdev_state[dev_state] : "Unknown");
+ qla82xx_set_reset_owner(vha);
qla82xx_idc_unlock(ha);
rval = qla82xx_device_state_handler(vha);
@@ -4016,3 +4128,803 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
}
}
}
+
+/* Minidump related functions */
+int
+qla82xx_md_rw_32(struct qla_hw_data *ha, uint32_t off, u32 data, uint8_t flag)
+{
+ uint32_t off_value, rval = 0;
+
+ WRT_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase),
+ (off & 0xFFFF0000));
+
+ /* Read back value to make sure write has gone through */
+ RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase));
+ off_value = (off & 0x0000FFFF);
+
+ if (flag)
+ WRT_REG_DWORD((void *)
+ (off_value + CRB_INDIRECT_2M + ha->nx_pcibase),
+ data);
+ else
+ rval = RD_REG_DWORD((void *)
+ (off_value + CRB_INDIRECT_2M + ha->nx_pcibase));
+
+ return rval;
+}
+
+static int
+qla82xx_minidump_process_control(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct qla82xx_md_entry_crb *crb_entry;
+ uint32_t read_value, opcode, poll_time;
+ uint32_t addr, index, crb_addr;
+ unsigned long wtime;
+ struct qla82xx_md_template_hdr *tmplt_hdr;
+ uint32_t rval = QLA_SUCCESS;
+ int i;
+
+ tmplt_hdr = (struct qla82xx_md_template_hdr *)ha->md_tmplt_hdr;
+ crb_entry = (struct qla82xx_md_entry_crb *)entry_hdr;
+ crb_addr = crb_entry->addr;
+
+ for (i = 0; i < crb_entry->op_count; i++) {
+ opcode = crb_entry->crb_ctrl.opcode;
+ if (opcode & QLA82XX_DBG_OPCODE_WR) {
+ qla82xx_md_rw_32(ha, crb_addr,
+ crb_entry->value_1, 1);
+ opcode &= ~QLA82XX_DBG_OPCODE_WR;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_RW) {
+ read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
+ qla82xx_md_rw_32(ha, crb_addr, read_value, 1);
+ opcode &= ~QLA82XX_DBG_OPCODE_RW;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_AND) {
+ read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
+ read_value &= crb_entry->value_2;
+ opcode &= ~QLA82XX_DBG_OPCODE_AND;
+ if (opcode & QLA82XX_DBG_OPCODE_OR) {
+ read_value |= crb_entry->value_3;
+ opcode &= ~QLA82XX_DBG_OPCODE_OR;
+ }
+ qla82xx_md_rw_32(ha, crb_addr, read_value, 1);
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_OR) {
+ read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
+ read_value |= crb_entry->value_3;
+ qla82xx_md_rw_32(ha, crb_addr, read_value, 1);
+ opcode &= ~QLA82XX_DBG_OPCODE_OR;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_POLL) {
+ poll_time = crb_entry->crb_strd.poll_timeout;
+ wtime = jiffies + poll_time;
+ read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
+
+ do {
+ if ((read_value & crb_entry->value_2)
+ == crb_entry->value_1)
+ break;
+ else if (time_after_eq(jiffies, wtime)) {
+ /* capturing dump failed */
+ rval = QLA_FUNCTION_FAILED;
+ break;
+ } else
+ read_value = qla82xx_md_rw_32(ha,
+ crb_addr, 0, 0);
+ } while (1);
+ opcode &= ~QLA82XX_DBG_OPCODE_POLL;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) {
+ if (crb_entry->crb_strd.state_index_a) {
+ index = crb_entry->crb_strd.state_index_a;
+ addr = tmplt_hdr->saved_state_array[index];
+ } else
+ addr = crb_addr;
+
+ read_value = qla82xx_md_rw_32(ha, addr, 0, 0);
+ index = crb_entry->crb_ctrl.state_index_v;
+ tmplt_hdr->saved_state_array[index] = read_value;
+ opcode &= ~QLA82XX_DBG_OPCODE_RDSTATE;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) {
+ if (crb_entry->crb_strd.state_index_a) {
+ index = crb_entry->crb_strd.state_index_a;
+ addr = tmplt_hdr->saved_state_array[index];
+ } else
+ addr = crb_addr;
+
+ if (crb_entry->crb_ctrl.state_index_v) {
+ index = crb_entry->crb_ctrl.state_index_v;
+ read_value =
+ tmplt_hdr->saved_state_array[index];
+ } else
+ read_value = crb_entry->value_1;
+
+ qla82xx_md_rw_32(ha, addr, read_value, 1);
+ opcode &= ~QLA82XX_DBG_OPCODE_WRSTATE;
+ }
+
+ if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) {
+ index = crb_entry->crb_ctrl.state_index_v;
+ read_value = tmplt_hdr->saved_state_array[index];
+ read_value <<= crb_entry->crb_ctrl.shl;
+ read_value >>= crb_entry->crb_ctrl.shr;
+ if (crb_entry->value_2)
+ read_value &= crb_entry->value_2;
+ read_value |= crb_entry->value_3;
+ read_value += crb_entry->value_1;
+ tmplt_hdr->saved_state_array[index] = read_value;
+ opcode &= ~QLA82XX_DBG_OPCODE_MDSTATE;
+ }
+ crb_addr += crb_entry->crb_strd.addr_stride;
+ }
+ return rval;
+}
+
+static void
+qla82xx_minidump_process_rdocm(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t r_addr, r_stride, loop_cnt, i, r_value;
+ struct qla82xx_md_entry_rdocm *ocm_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ ocm_hdr = (struct qla82xx_md_entry_rdocm *)entry_hdr;
+ r_addr = ocm_hdr->read_addr;
+ r_stride = ocm_hdr->read_addr_stride;
+ loop_cnt = ocm_hdr->op_count;
+
+ for (i = 0; i < loop_cnt; i++) {
+ r_value = RD_REG_DWORD((void *)(r_addr + ha->nx_pcibase));
+ *data_ptr++ = cpu_to_le32(r_value);
+ r_addr += r_stride;
+ }
+ *d_ptr = data_ptr;
+}
+
+static void
+qla82xx_minidump_process_rdmux(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value;
+ struct qla82xx_md_entry_mux *mux_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ mux_hdr = (struct qla82xx_md_entry_mux *)entry_hdr;
+ r_addr = mux_hdr->read_addr;
+ s_addr = mux_hdr->select_addr;
+ s_stride = mux_hdr->select_value_stride;
+ s_value = mux_hdr->select_value;
+ loop_cnt = mux_hdr->op_count;
+
+ for (i = 0; i < loop_cnt; i++) {
+ qla82xx_md_rw_32(ha, s_addr, s_value, 1);
+ r_value = qla82xx_md_rw_32(ha, r_addr, 0, 0);
+ *data_ptr++ = cpu_to_le32(s_value);
+ *data_ptr++ = cpu_to_le32(r_value);
+ s_value += s_stride;
+ }
+ *d_ptr = data_ptr;
+}
+
+static void
+qla82xx_minidump_process_rdcrb(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t r_addr, r_stride, loop_cnt, i, r_value;
+ struct qla82xx_md_entry_crb *crb_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ crb_hdr = (struct qla82xx_md_entry_crb *)entry_hdr;
+ r_addr = crb_hdr->addr;
+ r_stride = crb_hdr->crb_strd.addr_stride;
+ loop_cnt = crb_hdr->op_count;
+
+ for (i = 0; i < loop_cnt; i++) {
+ r_value = qla82xx_md_rw_32(ha, r_addr, 0, 0);
+ *data_ptr++ = cpu_to_le32(r_addr);
+ *data_ptr++ = cpu_to_le32(r_value);
+ r_addr += r_stride;
+ }
+ *d_ptr = data_ptr;
+}
+
+static int
+qla82xx_minidump_process_l2tag(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t addr, r_addr, c_addr, t_r_addr;
+ uint32_t i, k, loop_count, t_value, r_cnt, r_value;
+ unsigned long p_wait, w_time, p_mask;
+ uint32_t c_value_w, c_value_r;
+ struct qla82xx_md_entry_cache *cache_hdr;
+ int rval = QLA_FUNCTION_FAILED;
+ uint32_t *data_ptr = *d_ptr;
+
+ cache_hdr = (struct qla82xx_md_entry_cache *)entry_hdr;
+ loop_count = cache_hdr->op_count;
+ r_addr = cache_hdr->read_addr;
+ c_addr = cache_hdr->control_addr;
+ c_value_w = cache_hdr->cache_ctrl.write_value;
+
+ t_r_addr = cache_hdr->tag_reg_addr;
+ t_value = cache_hdr->addr_ctrl.init_tag_value;
+ r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
+ p_wait = cache_hdr->cache_ctrl.poll_wait;
+ p_mask = cache_hdr->cache_ctrl.poll_mask;
+
+ for (i = 0; i < loop_count; i++) {
+ qla82xx_md_rw_32(ha, t_r_addr, t_value, 1);
+ if (c_value_w)
+ qla82xx_md_rw_32(ha, c_addr, c_value_w, 1);
+
+ if (p_mask) {
+ w_time = jiffies + p_wait;
+ do {
+ c_value_r = qla82xx_md_rw_32(ha, c_addr, 0, 0);
+ if ((c_value_r & p_mask) == 0)
+ break;
+ else if (time_after_eq(jiffies, w_time)) {
+ /* capturing dump failed */
+ ql_dbg(ql_dbg_p3p, vha, 0xb032,
+ "c_value_r: 0x%x, poll_mask: 0x%lx, "
+ "w_time: 0x%lx\n",
+ c_value_r, p_mask, w_time);
+ return rval;
+ }
+ } while (1);
+ }
+
+ addr = r_addr;
+ for (k = 0; k < r_cnt; k++) {
+ r_value = qla82xx_md_rw_32(ha, addr, 0, 0);
+ *data_ptr++ = cpu_to_le32(r_value);
+ addr += cache_hdr->read_ctrl.read_addr_stride;
+ }
+ t_value += cache_hdr->addr_ctrl.tag_value_stride;
+ }
+ *d_ptr = data_ptr;
+ return QLA_SUCCESS;
+}
+
+static void
+qla82xx_minidump_process_l1cache(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t addr, r_addr, c_addr, t_r_addr;
+ uint32_t i, k, loop_count, t_value, r_cnt, r_value;
+ uint32_t c_value_w;
+ struct qla82xx_md_entry_cache *cache_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ cache_hdr = (struct qla82xx_md_entry_cache *)entry_hdr;
+ loop_count = cache_hdr->op_count;
+ r_addr = cache_hdr->read_addr;
+ c_addr = cache_hdr->control_addr;
+ c_value_w = cache_hdr->cache_ctrl.write_value;
+
+ t_r_addr = cache_hdr->tag_reg_addr;
+ t_value = cache_hdr->addr_ctrl.init_tag_value;
+ r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
+
+ for (i = 0; i < loop_count; i++) {
+ qla82xx_md_rw_32(ha, t_r_addr, t_value, 1);
+ qla82xx_md_rw_32(ha, c_addr, c_value_w, 1);
+ addr = r_addr;
+ for (k = 0; k < r_cnt; k++) {
+ r_value = qla82xx_md_rw_32(ha, addr, 0, 0);
+ *data_ptr++ = cpu_to_le32(r_value);
+ addr += cache_hdr->read_ctrl.read_addr_stride;
+ }
+ t_value += cache_hdr->addr_ctrl.tag_value_stride;
+ }
+ *d_ptr = data_ptr;
+}
+
+static void
+qla82xx_minidump_process_queue(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t s_addr, r_addr;
+ uint32_t r_stride, r_value, r_cnt, qid = 0;
+ uint32_t i, k, loop_cnt;
+ struct qla82xx_md_entry_queue *q_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ q_hdr = (struct qla82xx_md_entry_queue *)entry_hdr;
+ s_addr = q_hdr->select_addr;
+ r_cnt = q_hdr->rd_strd.read_addr_cnt;
+ r_stride = q_hdr->rd_strd.read_addr_stride;
+ loop_cnt = q_hdr->op_count;
+
+ for (i = 0; i < loop_cnt; i++) {
+ qla82xx_md_rw_32(ha, s_addr, qid, 1);
+ r_addr = q_hdr->read_addr;
+ for (k = 0; k < r_cnt; k++) {
+ r_value = qla82xx_md_rw_32(ha, r_addr, 0, 0);
+ *data_ptr++ = cpu_to_le32(r_value);
+ r_addr += r_stride;
+ }
+ qid += q_hdr->q_strd.queue_id_stride;
+ }
+ *d_ptr = data_ptr;
+}
+
+static void
+qla82xx_minidump_process_rdrom(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t r_addr, r_value;
+ uint32_t i, loop_cnt;
+ struct qla82xx_md_entry_rdrom *rom_hdr;
+ uint32_t *data_ptr = *d_ptr;
+
+ rom_hdr = (struct qla82xx_md_entry_rdrom *)entry_hdr;
+ r_addr = rom_hdr->read_addr;
+ loop_cnt = rom_hdr->read_data_size/sizeof(uint32_t);
+
+ for (i = 0; i < loop_cnt; i++) {
+ qla82xx_md_rw_32(ha, MD_DIRECT_ROM_WINDOW,
+ (r_addr & 0xFFFF0000), 1);
+ r_value = qla82xx_md_rw_32(ha,
+ MD_DIRECT_ROM_READ_BASE +
+ (r_addr & 0x0000FFFF), 0, 0);
+ *data_ptr++ = cpu_to_le32(r_value);
+ r_addr += sizeof(uint32_t);
+ }
+ *d_ptr = data_ptr;
+}
+
+static int
+qla82xx_minidump_process_rdmem(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t r_addr, r_value, r_data;
+ uint32_t i, j, loop_cnt;
+ struct qla82xx_md_entry_rdmem *m_hdr;
+ unsigned long flags;
+ int rval = QLA_FUNCTION_FAILED;
+ uint32_t *data_ptr = *d_ptr;
+
+ m_hdr = (struct qla82xx_md_entry_rdmem *)entry_hdr;
+ r_addr = m_hdr->read_addr;
+ loop_cnt = m_hdr->read_data_size/16;
+
+ if (r_addr & 0xf) {
+ ql_log(ql_log_warn, vha, 0xb033,
+ "Read addr 0x%x not 16 bytes alligned\n", r_addr);
+ return rval;
+ }
+
+ if (m_hdr->read_data_size % 16) {
+ ql_log(ql_log_warn, vha, 0xb034,
+ "Read data[0x%x] not multiple of 16 bytes\n",
+ m_hdr->read_data_size);
+ return rval;
+ }
+
+ ql_dbg(ql_dbg_p3p, vha, 0xb035,
+ "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n",
+ __func__, r_addr, m_hdr->read_data_size, loop_cnt);
+
+ write_lock_irqsave(&ha->hw_lock, flags);
+ for (i = 0; i < loop_cnt; i++) {
+ qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_LO, r_addr, 1);
+ r_value = 0;
+ qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_HI, r_value, 1);
+ r_value = MIU_TA_CTL_ENABLE;
+ qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1);
+ r_value = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
+ qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ r_value = qla82xx_md_rw_32(ha,
+ MD_MIU_TEST_AGT_CTRL, 0, 0);
+ if ((r_value & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk_ratelimited(KERN_ERR
+ "failed to read through agent\n");
+ write_unlock_irqrestore(&ha->hw_lock, flags);
+ return rval;
+ }
+
+ for (j = 0; j < 4; j++) {
+ r_data = qla82xx_md_rw_32(ha,
+ MD_MIU_TEST_AGT_RDDATA[j], 0, 0);
+ *data_ptr++ = cpu_to_le32(r_data);
+ }
+ r_addr += 16;
+ }
+ write_unlock_irqrestore(&ha->hw_lock, flags);
+ *d_ptr = data_ptr;
+ return QLA_SUCCESS;
+}
+
+static int
+qla82xx_validate_template_chksum(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint64_t chksum = 0;
+ uint32_t *d_ptr = (uint32_t *)ha->md_tmplt_hdr;
+ int count = ha->md_template_size/sizeof(uint32_t);
+
+ while (count-- > 0)
+ chksum += *d_ptr++;
+ while (chksum >> 32)
+ chksum = (chksum & 0xFFFFFFFF) + (chksum >> 32);
+ return ~chksum;
+}
+
+static void
+qla82xx_mark_entry_skipped(scsi_qla_host_t *vha,
+ qla82xx_md_entry_hdr_t *entry_hdr, int index)
+{
+ entry_hdr->d_ctrl.driver_flags |= QLA82XX_DBG_SKIPPED_FLAG;
+ ql_dbg(ql_dbg_p3p, vha, 0xb036,
+ "Skipping entry[%d]: "
+ "ETYPE[0x%x]-ELEVEL[0x%x]\n",
+ index, entry_hdr->entry_type,
+ entry_hdr->d_ctrl.entry_capture_mask);
+}
+
+int
+qla82xx_md_collect(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ int no_entry_hdr = 0;
+ qla82xx_md_entry_hdr_t *entry_hdr;
+ struct qla82xx_md_template_hdr *tmplt_hdr;
+ uint32_t *data_ptr;
+ uint32_t total_data_size = 0, f_capture_mask, data_collected = 0;
+ int i = 0, rval = QLA_FUNCTION_FAILED;
+
+ tmplt_hdr = (struct qla82xx_md_template_hdr *)ha->md_tmplt_hdr;
+ data_ptr = (uint32_t *)ha->md_dump;
+
+ if (ha->fw_dumped) {
+ ql_log(ql_log_info, vha, 0xb037,
+ "Firmware dump available to retrive\n");
+ goto md_failed;
+ }
+
+ ha->fw_dumped = 0;
+
+ if (!ha->md_tmplt_hdr || !ha->md_dump) {
+ ql_log(ql_log_warn, vha, 0xb038,
+ "Memory not allocated for minidump capture\n");
+ goto md_failed;
+ }
+
+ if (qla82xx_validate_template_chksum(vha)) {
+ ql_log(ql_log_info, vha, 0xb039,
+ "Template checksum validation error\n");
+ goto md_failed;
+ }
+
+ no_entry_hdr = tmplt_hdr->num_of_entries;
+ ql_dbg(ql_dbg_p3p, vha, 0xb03a,
+ "No of entry headers in Template: 0x%x\n", no_entry_hdr);
+
+ ql_dbg(ql_dbg_p3p, vha, 0xb03b,
+ "Capture Mask obtained: 0x%x\n", tmplt_hdr->capture_debug_level);
+
+ f_capture_mask = tmplt_hdr->capture_debug_level & 0xFF;
+
+ /* Validate whether required debug level is set */
+ if ((f_capture_mask & 0x3) != 0x3) {
+ ql_log(ql_log_warn, vha, 0xb03c,
+ "Minimum required capture mask[0x%x] level not set\n",
+ f_capture_mask);
+ goto md_failed;
+ }
+ tmplt_hdr->driver_capture_mask = ql2xmdcapmask;
+
+ tmplt_hdr->driver_info[0] = vha->host_no;
+ tmplt_hdr->driver_info[1] = (QLA_DRIVER_MAJOR_VER << 24) |
+ (QLA_DRIVER_MINOR_VER << 16) | (QLA_DRIVER_PATCH_VER << 8) |
+ QLA_DRIVER_BETA_VER;
+
+ total_data_size = ha->md_dump_size;
+
+ ql_dbg(ql_log_info, vha, 0xb03d,
+ "Total minidump data_size 0x%x to be captured\n", total_data_size);
+
+ /* Check whether template obtained is valid */
+ if (tmplt_hdr->entry_type != QLA82XX_TLHDR) {
+ ql_log(ql_log_warn, vha, 0xb04e,
+ "Bad template header entry type: 0x%x obtained\n",
+ tmplt_hdr->entry_type);
+ goto md_failed;
+ }
+
+ entry_hdr = (qla82xx_md_entry_hdr_t *) \
+ (((uint8_t *)ha->md_tmplt_hdr) + tmplt_hdr->first_entry_offset);
+
+ /* Walk through the entry headers */
+ for (i = 0; i < no_entry_hdr; i++) {
+
+ if (data_collected > total_data_size) {
+ ql_log(ql_log_warn, vha, 0xb03e,
+ "More MiniDump data collected: [0x%x]\n",
+ data_collected);
+ goto md_failed;
+ }
+
+ if (!(entry_hdr->d_ctrl.entry_capture_mask &
+ ql2xmdcapmask)) {
+ entry_hdr->d_ctrl.driver_flags |=
+ QLA82XX_DBG_SKIPPED_FLAG;
+ ql_dbg(ql_dbg_p3p, vha, 0xb03f,
+ "Skipping entry[%d]: "
+ "ETYPE[0x%x]-ELEVEL[0x%x]\n",
+ i, entry_hdr->entry_type,
+ entry_hdr->d_ctrl.entry_capture_mask);
+ goto skip_nxt_entry;
+ }
+
+ ql_dbg(ql_dbg_p3p, vha, 0xb040,
+ "[%s]: data ptr[%d]: %p, entry_hdr: %p\n"
+ "entry_type: 0x%x, captrue_mask: 0x%x\n",
+ __func__, i, data_ptr, entry_hdr,
+ entry_hdr->entry_type,
+ entry_hdr->d_ctrl.entry_capture_mask);
+
+ ql_dbg(ql_dbg_p3p, vha, 0xb041,
+ "Data collected: [0x%x], Dump size left:[0x%x]\n",
+ data_collected, (ha->md_dump_size - data_collected));
+
+ /* Decode the entry type and take
+ * required action to capture debug data */
+ switch (entry_hdr->entry_type) {
+ case QLA82XX_RDEND:
+ qla82xx_mark_entry_skipped(vha, entry_hdr, i);
+ break;
+ case QLA82XX_CNTRL:
+ rval = qla82xx_minidump_process_control(vha,
+ entry_hdr, &data_ptr);
+ if (rval != QLA_SUCCESS) {
+ qla82xx_mark_entry_skipped(vha, entry_hdr, i);
+ goto md_failed;
+ }
+ break;
+ case QLA82XX_RDCRB:
+ qla82xx_minidump_process_rdcrb(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_RDMEM:
+ rval = qla82xx_minidump_process_rdmem(vha,
+ entry_hdr, &data_ptr);
+ if (rval != QLA_SUCCESS) {
+ qla82xx_mark_entry_skipped(vha, entry_hdr, i);
+ goto md_failed;
+ }
+ break;
+ case QLA82XX_BOARD:
+ case QLA82XX_RDROM:
+ qla82xx_minidump_process_rdrom(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_L2DTG:
+ case QLA82XX_L2ITG:
+ case QLA82XX_L2DAT:
+ case QLA82XX_L2INS:
+ rval = qla82xx_minidump_process_l2tag(vha,
+ entry_hdr, &data_ptr);
+ if (rval != QLA_SUCCESS) {
+ qla82xx_mark_entry_skipped(vha, entry_hdr, i);
+ goto md_failed;
+ }
+ break;
+ case QLA82XX_L1DAT:
+ case QLA82XX_L1INS:
+ qla82xx_minidump_process_l1cache(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_RDOCM:
+ qla82xx_minidump_process_rdocm(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_RDMUX:
+ qla82xx_minidump_process_rdmux(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_QUEUE:
+ qla82xx_minidump_process_queue(vha,
+ entry_hdr, &data_ptr);
+ break;
+ case QLA82XX_RDNOP:
+ default:
+ qla82xx_mark_entry_skipped(vha, entry_hdr, i);
+ break;
+ }
+
+ ql_dbg(ql_dbg_p3p, vha, 0xb042,
+ "[%s]: data ptr[%d]: %p\n", __func__, i, data_ptr);
+
+ data_collected = (uint8_t *)data_ptr -
+ (uint8_t *)ha->md_dump;
+skip_nxt_entry:
+ entry_hdr = (qla82xx_md_entry_hdr_t *) \
+ (((uint8_t *)entry_hdr) + entry_hdr->entry_size);
+ }
+
+ if (data_collected != total_data_size) {
+ ql_dbg(ql_log_warn, vha, 0xb043,
+ "MiniDump data mismatch: Data collected: [0x%x],"
+ "total_data_size:[0x%x]\n",
+ data_collected, total_data_size);
+ goto md_failed;
+ }
+
+ ql_log(ql_log_info, vha, 0xb044,
+ "Firmware dump saved to temp buffer (%ld/%p %ld/%p).\n",
+ vha->host_no, ha->md_tmplt_hdr, vha->host_no, ha->md_dump);
+ ha->fw_dumped = 1;
+ qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
+
+md_failed:
+ return rval;
+}
+
+int
+qla82xx_md_alloc(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ int i, k;
+ struct qla82xx_md_template_hdr *tmplt_hdr;
+
+ tmplt_hdr = (struct qla82xx_md_template_hdr *)ha->md_tmplt_hdr;
+
+ if (ql2xmdcapmask < 0x3 || ql2xmdcapmask > 0x7F) {
+ ql2xmdcapmask = tmplt_hdr->capture_debug_level & 0xFF;
+ ql_log(ql_log_info, vha, 0xb045,
+ "Forcing driver capture mask to firmware default capture mask: 0x%x.\n",
+ ql2xmdcapmask);
+ }
+
+ for (i = 0x2, k = 1; (i & QLA82XX_DEFAULT_CAP_MASK); i <<= 1, k++) {
+ if (i & ql2xmdcapmask)
+ ha->md_dump_size += tmplt_hdr->capture_size_array[k];
+ }
+
+ if (ha->md_dump) {
+ ql_log(ql_log_warn, vha, 0xb046,
+ "Firmware dump previously allocated.\n");
+ return 1;
+ }
+
+ ha->md_dump = vmalloc(ha->md_dump_size);
+ if (ha->md_dump == NULL) {
+ ql_log(ql_log_warn, vha, 0xb047,
+ "Unable to allocate memory for Minidump size "
+ "(0x%x).\n", ha->md_dump_size);
+ return 1;
+ }
+ return 0;
+}
+
+void
+qla82xx_md_free(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ /* Release the template header allocated */
+ if (ha->md_tmplt_hdr) {
+ ql_log(ql_log_info, vha, 0xb048,
+ "Free MiniDump template: %p, size (%d KB)\n",
+ ha->md_tmplt_hdr, ha->md_template_size / 1024);
+ dma_free_coherent(&ha->pdev->dev, ha->md_template_size,
+ ha->md_tmplt_hdr, ha->md_tmplt_hdr_dma);
+ ha->md_tmplt_hdr = 0;
+ }
+
+ /* Release the template data buffer allocated */
+ if (ha->md_dump) {
+ ql_log(ql_log_info, vha, 0xb049,
+ "Free MiniDump memory: %p, size (%d KB)\n",
+ ha->md_dump, ha->md_dump_size / 1024);
+ vfree(ha->md_dump);
+ ha->md_dump_size = 0;
+ ha->md_dump = 0;
+ }
+}
+
+void
+qla82xx_md_prep(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ int rval;
+
+ /* Get Minidump template size */
+ rval = qla82xx_md_get_template_size(vha);
+ if (rval == QLA_SUCCESS) {
+ ql_log(ql_log_info, vha, 0xb04a,
+ "MiniDump Template size obtained (%d KB)\n",
+ ha->md_template_size / 1024);
+
+ /* Get Minidump template */
+ rval = qla82xx_md_get_template(vha);
+ if (rval == QLA_SUCCESS) {
+ ql_dbg(ql_dbg_p3p, vha, 0xb04b,
+ "MiniDump Template obtained\n");
+
+ /* Allocate memory for minidump */
+ rval = qla82xx_md_alloc(vha);
+ if (rval == QLA_SUCCESS)
+ ql_log(ql_log_info, vha, 0xb04c,
+ "MiniDump memory allocated (%d KB)\n",
+ ha->md_dump_size / 1024);
+ else {
+ ql_log(ql_log_info, vha, 0xb04d,
+ "Free MiniDump template: %p, size: (%d KB)\n",
+ ha->md_tmplt_hdr,
+ ha->md_template_size / 1024);
+ dma_free_coherent(&ha->pdev->dev,
+ ha->md_template_size,
+ ha->md_tmplt_hdr, ha->md_tmplt_hdr_dma);
+ ha->md_tmplt_hdr = 0;
+ }
+
+ }
+ }
+}
+
+int
+qla82xx_beacon_on(struct scsi_qla_host *vha)
+{
+
+ int rval;
+ struct qla_hw_data *ha = vha->hw;
+ qla82xx_idc_lock(ha);
+ rval = qla82xx_mbx_beacon_ctl(vha, 1);
+
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0xb050,
+ "mbx set led config failed in %s\n", __func__);
+ goto exit;
+ }
+ ha->beacon_blink_led = 1;
+exit:
+ qla82xx_idc_unlock(ha);
+ return rval;
+}
+
+int
+qla82xx_beacon_off(struct scsi_qla_host *vha)
+{
+
+ int rval;
+ struct qla_hw_data *ha = vha->hw;
+ qla82xx_idc_lock(ha);
+ rval = qla82xx_mbx_beacon_ctl(vha, 0);
+
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0xb051,
+ "mbx set led config failed in %s\n", __func__);
+ goto exit;
+ }
+ ha->beacon_blink_led = 0;
+exit:
+ qla82xx_idc_unlock(ha);
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 8a21832c6693..57820c199bc2 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -484,8 +484,6 @@
#define QLA82XX_ADDR_OCM1 (0x0000000200400000ULL)
#define QLA82XX_ADDR_OCM1_MAX (0x00000002004fffffULL)
#define QLA82XX_ADDR_QDR_NET (0x0000000300000000ULL)
-
-#define QLA82XX_P2_ADDR_QDR_NET_MAX (0x00000003001fffffULL)
#define QLA82XX_P3_ADDR_QDR_NET_MAX (0x0000000303ffffffULL)
#define QLA82XX_PCI_CRBSPACE (unsigned long)0x06000000
@@ -890,6 +888,7 @@ struct ct6_dsd {
};
#define MBC_TOGGLE_INTERRUPT 0x10
+#define MBC_SET_LED_CONFIG 0x125
/* Flash offset */
#define FLT_REG_BOOTLOAD_82XX 0x72
@@ -922,4 +921,256 @@ struct ct6_dsd {
#define M25P_INSTR_DP 0xb9
#define M25P_INSTR_RES 0xab
+/* Minidump related */
+
+/*
+ * Version of the template
+ * 4 Bytes
+ * X.Major.Minor.RELEASE
+ */
+#define QLA82XX_MINIDUMP_VERSION 0x10101
+
+/*
+ * Entry Type Defines
+ */
+#define QLA82XX_RDNOP 0
+#define QLA82XX_RDCRB 1
+#define QLA82XX_RDMUX 2
+#define QLA82XX_QUEUE 3
+#define QLA82XX_BOARD 4
+#define QLA82XX_RDSRE 5
+#define QLA82XX_RDOCM 6
+#define QLA82XX_CACHE 10
+#define QLA82XX_L1DAT 11
+#define QLA82XX_L1INS 12
+#define QLA82XX_L2DTG 21
+#define QLA82XX_L2ITG 22
+#define QLA82XX_L2DAT 23
+#define QLA82XX_L2INS 24
+#define QLA82XX_RDROM 71
+#define QLA82XX_RDMEM 72
+#define QLA82XX_CNTRL 98
+#define QLA82XX_TLHDR 99
+#define QLA82XX_RDEND 255
+
+/*
+ * Opcodes for Control Entries.
+ * These Flags are bit fields.
+ */
+#define QLA82XX_DBG_OPCODE_WR 0x01
+#define QLA82XX_DBG_OPCODE_RW 0x02
+#define QLA82XX_DBG_OPCODE_AND 0x04
+#define QLA82XX_DBG_OPCODE_OR 0x08
+#define QLA82XX_DBG_OPCODE_POLL 0x10
+#define QLA82XX_DBG_OPCODE_RDSTATE 0x20
+#define QLA82XX_DBG_OPCODE_WRSTATE 0x40
+#define QLA82XX_DBG_OPCODE_MDSTATE 0x80
+
+/*
+ * Template Header and Entry Header definitions start here.
+ */
+
+/*
+ * Template Header
+ * Parts of the template header can be modified by the driver.
+ * These include the saved_state_array, capture_debug_level, driver_timestamp
+ */
+
+#define QLA82XX_DBG_STATE_ARRAY_LEN 16
+#define QLA82XX_DBG_CAP_SIZE_ARRAY_LEN 8
+#define QLA82XX_DBG_RSVD_ARRAY_LEN 8
+
+/*
+ * Driver Flags
+ */
+#define QLA82XX_DBG_SKIPPED_FLAG 0x80 /* driver skipped this entry */
+#define QLA82XX_DEFAULT_CAP_MASK 0xFF /* default capture mask */
+
+struct qla82xx_md_template_hdr {
+ uint32_t entry_type;
+ uint32_t first_entry_offset;
+ uint32_t size_of_template;
+ uint32_t capture_debug_level;
+
+ uint32_t num_of_entries;
+ uint32_t version;
+ uint32_t driver_timestamp;
+ uint32_t template_checksum;
+
+ uint32_t driver_capture_mask;
+ uint32_t driver_info[3];
+
+ uint32_t saved_state_array[QLA82XX_DBG_STATE_ARRAY_LEN];
+ uint32_t capture_size_array[QLA82XX_DBG_CAP_SIZE_ARRAY_LEN];
+
+ /* markers_array used to capture some special locations on board */
+ uint32_t markers_array[QLA82XX_DBG_RSVD_ARRAY_LEN];
+ uint32_t num_of_free_entries; /* For internal use */
+ uint32_t free_entry_offset; /* For internal use */
+ uint32_t total_table_size; /* For internal use */
+ uint32_t bkup_table_offset; /* For internal use */
+} __packed;
+
+/*
+ * Entry Header: Common to All Entry Types
+ */
+
+/*
+ * Driver Code is for driver to write some info about the entry.
+ * Currently not used.
+ */
+typedef struct qla82xx_md_entry_hdr {
+ uint32_t entry_type;
+ uint32_t entry_size;
+ uint32_t entry_capture_size;
+ struct {
+ uint8_t entry_capture_mask;
+ uint8_t entry_code;
+ uint8_t driver_code;
+ uint8_t driver_flags;
+ } d_ctrl;
+} __packed qla82xx_md_entry_hdr_t;
+
+/*
+ * Read CRB entry header
+ */
+struct qla82xx_md_entry_crb {
+ qla82xx_md_entry_hdr_t h;
+ uint32_t addr;
+ struct {
+ uint8_t addr_stride;
+ uint8_t state_index_a;
+ uint16_t poll_timeout;
+ } crb_strd;
+
+ uint32_t data_size;
+ uint32_t op_count;
+
+ struct {
+ uint8_t opcode;
+ uint8_t state_index_v;
+ uint8_t shl;
+ uint8_t shr;
+ } crb_ctrl;
+
+ uint32_t value_1;
+ uint32_t value_2;
+ uint32_t value_3;
+} __packed;
+
+/*
+ * Cache entry header
+ */
+struct qla82xx_md_entry_cache {
+ qla82xx_md_entry_hdr_t h;
+
+ uint32_t tag_reg_addr;
+ struct {
+ uint16_t tag_value_stride;
+ uint16_t init_tag_value;
+ } addr_ctrl;
+
+ uint32_t data_size;
+ uint32_t op_count;
+
+ uint32_t control_addr;
+ struct {
+ uint16_t write_value;
+ uint8_t poll_mask;
+ uint8_t poll_wait;
+ } cache_ctrl;
+
+ uint32_t read_addr;
+ struct {
+ uint8_t read_addr_stride;
+ uint8_t read_addr_cnt;
+ uint16_t rsvd_1;
+ } read_ctrl;
+} __packed;
+
+/*
+ * Read OCM
+ */
+struct qla82xx_md_entry_rdocm {
+ qla82xx_md_entry_hdr_t h;
+
+ uint32_t rsvd_0;
+ uint32_t rsvd_1;
+ uint32_t data_size;
+ uint32_t op_count;
+
+ uint32_t rsvd_2;
+ uint32_t rsvd_3;
+ uint32_t read_addr;
+ uint32_t read_addr_stride;
+ uint32_t read_addr_cntrl;
+} __packed;
+
+/*
+ * Read Memory
+ */
+struct qla82xx_md_entry_rdmem {
+ qla82xx_md_entry_hdr_t h;
+ uint32_t rsvd[6];
+ uint32_t read_addr;
+ uint32_t read_data_size;
+} __packed;
+
+/*
+ * Read ROM
+ */
+struct qla82xx_md_entry_rdrom {
+ qla82xx_md_entry_hdr_t h;
+ uint32_t rsvd[6];
+ uint32_t read_addr;
+ uint32_t read_data_size;
+} __packed;
+
+struct qla82xx_md_entry_mux {
+ qla82xx_md_entry_hdr_t h;
+
+ uint32_t select_addr;
+ uint32_t rsvd_0;
+ uint32_t data_size;
+ uint32_t op_count;
+
+ uint32_t select_value;
+ uint32_t select_value_stride;
+ uint32_t read_addr;
+ uint32_t rsvd_1;
+} __packed;
+
+struct qla82xx_md_entry_queue {
+ qla82xx_md_entry_hdr_t h;
+
+ uint32_t select_addr;
+ struct {
+ uint16_t queue_id_stride;
+ uint16_t rsvd_0;
+ } q_strd;
+
+ uint32_t data_size;
+ uint32_t op_count;
+ uint32_t rsvd_1;
+ uint32_t rsvd_2;
+
+ uint32_t read_addr;
+ struct {
+ uint8_t read_addr_stride;
+ uint8_t read_addr_cnt;
+ uint16_t rsvd_3;
+ } rd_strd;
+} __packed;
+
+#define MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE 0x129
+#define RQST_TMPLT_SIZE 0x0
+#define RQST_TMPLT 0x1
+#define MD_DIRECT_ROM_WINDOW 0x42110030
+#define MD_DIRECT_ROM_READ_BASE 0x42150000
+#define MD_MIU_TEST_AGT_CTRL 0x41000090
+#define MD_MIU_TEST_AGT_ADDR_LO 0x41000094
+#define MD_MIU_TEST_AGT_ADDR_HI 0x41000098
+
+static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, 0x410000AC,
+ 0x410000B8, 0x410000BC };
#endif
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 1e69527f1e4e..fd14c7bfc626 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -143,7 +143,7 @@ MODULE_PARM_DESC(ql2xmultique_tag,
"Set it to 1 to turn on the cpu affinity.");
int ql2xfwloadbin;
-module_param(ql2xfwloadbin, int, S_IRUGO);
+module_param(ql2xfwloadbin, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xfwloadbin,
"Option to specify location from which to load ISP firmware:.\n"
" 2 -- load firmware via the request_firmware() (hotplug).\n"
@@ -158,11 +158,11 @@ MODULE_PARM_DESC(ql2xetsenable,
"Default is 0 - skip ETS enablement.");
int ql2xdbwr = 1;
-module_param(ql2xdbwr, int, S_IRUGO);
+module_param(ql2xdbwr, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xdbwr,
- "Option to specify scheme for request queue posting.\n"
- " 0 -- Regular doorbell.\n"
- " 1 -- CAMRAM doorbell (faster).\n");
+ "Option to specify scheme for request queue posting.\n"
+ " 0 -- Regular doorbell.\n"
+ " 1 -- CAMRAM doorbell (faster).\n");
int ql2xtargetreset = 1;
module_param(ql2xtargetreset, int, S_IRUGO);
@@ -183,11 +183,11 @@ MODULE_PARM_DESC(ql2xasynctmfenable,
"Default is 0 - Issue TM IOCBs via mailbox mechanism.");
int ql2xdontresethba;
-module_param(ql2xdontresethba, int, S_IRUGO);
+module_param(ql2xdontresethba, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xdontresethba,
- "Option to specify reset behaviour.\n"
- " 0 (Default) -- Reset on failure.\n"
- " 1 -- Do not reset on failure.\n");
+ "Option to specify reset behaviour.\n"
+ " 0 (Default) -- Reset on failure.\n"
+ " 1 -- Do not reset on failure.\n");
uint ql2xmaxlun = MAX_LUNS;
module_param(ql2xmaxlun, uint, S_IRUGO);
@@ -195,6 +195,19 @@ MODULE_PARM_DESC(ql2xmaxlun,
"Defines the maximum LU number to register with the SCSI "
"midlayer. Default is 65535.");
+int ql2xmdcapmask = 0x1F;
+module_param(ql2xmdcapmask, int, S_IRUGO);
+MODULE_PARM_DESC(ql2xmdcapmask,
+ "Set the Minidump driver capture mask level. "
+ "Default is 0x7F - Can be set to 0x3, 0x7, 0xF, 0x1F, 0x7F.");
+
+int ql2xmdenable;
+module_param(ql2xmdenable, int, S_IRUGO);
+MODULE_PARM_DESC(ql2xmdenable,
+ "Enable/disable MiniDump. "
+ "0 (Default) - MiniDump disabled. "
+ "1 - MiniDump enabled.");
+
/*
* SCSI host template entry points
*/
@@ -1750,9 +1763,9 @@ static struct isp_operations qla82xx_isp_ops = {
.read_nvram = qla24xx_read_nvram_data,
.write_nvram = qla24xx_write_nvram_data,
.fw_dump = qla24xx_fw_dump,
- .beacon_on = qla24xx_beacon_on,
- .beacon_off = qla24xx_beacon_off,
- .beacon_blink = qla24xx_beacon_blink,
+ .beacon_on = qla82xx_beacon_on,
+ .beacon_off = qla82xx_beacon_off,
+ .beacon_blink = NULL,
.read_optrom = qla82xx_read_optrom_data,
.write_optrom = qla82xx_write_optrom_data,
.get_flash_version = qla24xx_get_flash_version,
@@ -2670,6 +2683,8 @@ qla2x00_free_device(scsi_qla_host_t *vha)
qla2x00_mem_free(ha);
+ qla82xx_md_free(vha);
+
qla2x00_free_queues(ha);
}
@@ -3903,8 +3918,11 @@ qla2x00_timer(scsi_qla_host_t *vha)
/* Check if beacon LED needs to be blinked for physical host only */
if (!vha->vp_idx && (ha->beacon_blink_led == 1)) {
- set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
- start_dpc++;
+ /* There is no beacon_blink function for ISP82xx */
+ if (!IS_QLA82XX(ha)) {
+ set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
+ start_dpc++;
+ }
}
/* Process any deferred work. */
diff --git a/drivers/scsi/qla4xxx/Kconfig b/drivers/scsi/qla4xxx/Kconfig
index 0f5599e0abf6..f1ad02ea212b 100644
--- a/drivers/scsi/qla4xxx/Kconfig
+++ b/drivers/scsi/qla4xxx/Kconfig
@@ -2,6 +2,7 @@ config SCSI_QLA_ISCSI
tristate "QLogic ISP4XXX and ISP82XX host adapter family support"
depends on PCI && SCSI && NET
select SCSI_ISCSI_ATTRS
+ select ISCSI_BOOT_SYSFS
---help---
This driver supports the QLogic 40xx (ISP4XXX) and 8022 (ISP82XX)
iSCSI host adapter family.
diff --git a/drivers/scsi/qla4xxx/Makefile b/drivers/scsi/qla4xxx/Makefile
index 252523d7847e..5b44139ff43d 100644
--- a/drivers/scsi/qla4xxx/Makefile
+++ b/drivers/scsi/qla4xxx/Makefile
@@ -1,5 +1,5 @@
qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \
- ql4_nx.o ql4_nvram.o ql4_dbg.o ql4_attr.o
+ ql4_nx.o ql4_nvram.o ql4_dbg.o ql4_attr.o ql4_bsg.o
obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o
diff --git a/drivers/scsi/qla4xxx/ql4_attr.c b/drivers/scsi/qla4xxx/ql4_attr.c
index 864d018631c0..0b0a7d42137d 100644
--- a/drivers/scsi/qla4xxx/ql4_attr.c
+++ b/drivers/scsi/qla4xxx/ql4_attr.c
@@ -55,15 +55,91 @@ qla4xxx_optrom_version_show(struct device *dev, struct device_attribute *attr,
ha->bootload_patch, ha->bootload_build);
}
+static ssize_t
+qla4xxx_board_id_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+ return snprintf(buf, PAGE_SIZE, "0x%08X\n", ha->board_id);
+}
+
+static ssize_t
+qla4xxx_fw_state_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+
+ qla4xxx_get_firmware_state(ha);
+ return snprintf(buf, PAGE_SIZE, "0x%08X%8X\n", ha->firmware_state,
+ ha->addl_fw_state);
+}
+
+static ssize_t
+qla4xxx_phy_port_cnt_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+
+ if (!is_qla8022(ha))
+ return -ENOSYS;
+
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->phy_port_cnt);
+}
+
+static ssize_t
+qla4xxx_phy_port_num_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+
+ if (!is_qla8022(ha))
+ return -ENOSYS;
+
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->phy_port_num);
+}
+
+static ssize_t
+qla4xxx_iscsi_func_cnt_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+
+ if (!is_qla8022(ha))
+ return -ENOSYS;
+
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->iscsi_pci_func_cnt);
+}
+
+static ssize_t
+qla4xxx_hba_model_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_name);
+}
+
static DEVICE_ATTR(fw_version, S_IRUGO, qla4xxx_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla4xxx_serial_num_show, NULL);
static DEVICE_ATTR(iscsi_version, S_IRUGO, qla4xxx_iscsi_version_show, NULL);
static DEVICE_ATTR(optrom_version, S_IRUGO, qla4xxx_optrom_version_show, NULL);
+static DEVICE_ATTR(board_id, S_IRUGO, qla4xxx_board_id_show, NULL);
+static DEVICE_ATTR(fw_state, S_IRUGO, qla4xxx_fw_state_show, NULL);
+static DEVICE_ATTR(phy_port_cnt, S_IRUGO, qla4xxx_phy_port_cnt_show, NULL);
+static DEVICE_ATTR(phy_port_num, S_IRUGO, qla4xxx_phy_port_num_show, NULL);
+static DEVICE_ATTR(iscsi_func_cnt, S_IRUGO, qla4xxx_iscsi_func_cnt_show, NULL);
+static DEVICE_ATTR(hba_model, S_IRUGO, qla4xxx_hba_model_show, NULL);
struct device_attribute *qla4xxx_host_attrs[] = {
&dev_attr_fw_version,
&dev_attr_serial_num,
&dev_attr_iscsi_version,
&dev_attr_optrom_version,
+ &dev_attr_board_id,
+ &dev_attr_fw_state,
+ &dev_attr_phy_port_cnt,
+ &dev_attr_phy_port_num,
+ &dev_attr_iscsi_func_cnt,
+ &dev_attr_hba_model,
NULL,
};
diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c
new file mode 100644
index 000000000000..8acdc582ff6d
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_bsg.c
@@ -0,0 +1,513 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c) 2011 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+
+#include "ql4_def.h"
+#include "ql4_glbl.h"
+#include "ql4_bsg.h"
+
+static int
+qla4xxx_read_flash(struct bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
+ struct scsi_qla_host *ha = to_qla_host(host);
+ struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
+ struct iscsi_bsg_request *bsg_req = bsg_job->request;
+ uint32_t offset = 0;
+ uint32_t length = 0;
+ dma_addr_t flash_dma;
+ uint8_t *flash = NULL;
+ int rval = -EINVAL;
+
+ bsg_reply->reply_payload_rcv_len = 0;
+
+ if (unlikely(pci_channel_offline(ha->pdev)))
+ goto leave;
+
+ if (ql4xxx_reset_active(ha)) {
+ ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
+ rval = -EBUSY;
+ goto leave;
+ }
+
+ if (ha->flash_state != QLFLASH_WAITING) {
+ ql4_printk(KERN_ERR, ha, "%s: another flash operation "
+ "active\n", __func__);
+ rval = -EBUSY;
+ goto leave;
+ }
+
+ ha->flash_state = QLFLASH_READING;
+ offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
+ length = bsg_job->reply_payload.payload_len;
+
+ flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
+ GFP_KERNEL);
+ if (!flash) {
+ ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
+ "data\n", __func__);
+ rval = -ENOMEM;
+ goto leave;
+ }
+
+ rval = qla4xxx_get_flash(ha, flash_dma, offset, length);
+ if (rval) {
+ ql4_printk(KERN_ERR, ha, "%s: get flash failed\n", __func__);
+ bsg_reply->result = DID_ERROR << 16;
+ rval = -EIO;
+ } else {
+ bsg_reply->reply_payload_rcv_len =
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt,
+ flash, length);
+ bsg_reply->result = DID_OK << 16;
+ }
+
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+ dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
+leave:
+ ha->flash_state = QLFLASH_WAITING;
+ return rval;
+}
+
+static int
+qla4xxx_update_flash(struct bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
+ struct scsi_qla_host *ha = to_qla_host(host);
+ struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
+ struct iscsi_bsg_request *bsg_req = bsg_job->request;
+ uint32_t length = 0;
+ uint32_t offset = 0;
+ uint32_t options = 0;
+ dma_addr_t flash_dma;
+ uint8_t *flash = NULL;
+ int rval = -EINVAL;
+
+ bsg_reply->reply_payload_rcv_len = 0;
+
+ if (unlikely(pci_channel_offline(ha->pdev)))
+ goto leave;
+
+ if (ql4xxx_reset_active(ha)) {
+ ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
+ rval = -EBUSY;
+ goto leave;
+ }
+
+ if (ha->flash_state != QLFLASH_WAITING) {
+ ql4_printk(KERN_ERR, ha, "%s: another flash operation "
+ "active\n", __func__);
+ rval = -EBUSY;
+ goto leave;
+ }
+
+ ha->flash_state = QLFLASH_WRITING;
+ length = bsg_job->request_payload.payload_len;
+ offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
+ options = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
+
+ flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
+ GFP_KERNEL);
+ if (!flash) {
+ ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
+ "data\n", __func__);
+ rval = -ENOMEM;
+ goto leave;
+ }
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, flash, length);
+
+ rval = qla4xxx_set_flash(ha, flash_dma, offset, length, options);
+ if (rval) {
+ ql4_printk(KERN_ERR, ha, "%s: set flash failed\n", __func__);
+ bsg_reply->result = DID_ERROR << 16;
+ rval = -EIO;
+ } else
+ bsg_reply->result = DID_OK << 16;
+
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+ dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
+leave:
+ ha->flash_state = QLFLASH_WAITING;
+ return rval;
+}
+
+static int
+qla4xxx_get_acb_state(struct bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
+ struct scsi_qla_host *ha = to_qla_host(host);
+ struct iscsi_bsg_request *bsg_req = bsg_job->request;
+ struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
+ uint32_t status[MBOX_REG_COUNT];
+ uint32_t acb_idx;
+ uint32_t ip_idx;
+ int rval = -EINVAL;
+
+ bsg_reply->reply_payload_rcv_len = 0;
+
+ if (unlikely(pci_channel_offline(ha->pdev)))
+ goto leave;
+
+ /* Only 4022 and above adapters are supported */
+ if (is_qla4010(ha))
+ goto leave;
+
+ if (ql4xxx_reset_active(ha)) {
+ ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
+ rval = -EBUSY;
+ goto leave;
+ }
+
+ if (bsg_job->reply_payload.payload_len < sizeof(status)) {
+ ql4_printk(KERN_ERR, ha, "%s: invalid payload len %d\n",
+ __func__, bsg_job->reply_payload.payload_len);
+ rval = -EINVAL;
+ goto leave;
+ }
+
+ acb_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
+ ip_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
+
+ rval = qla4xxx_get_ip_state(ha, acb_idx, ip_idx, status);
+ if (rval) {
+ ql4_printk(KERN_ERR, ha, "%s: get ip state failed\n",
+ __func__);
+ bsg_reply->result = DID_ERROR << 16;
+ rval = -EIO;
+ } else {
+ bsg_reply->reply_payload_rcv_len =
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt,
+ status, sizeof(status));
+ bsg_reply->result = DID_OK << 16;
+ }
+
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+leave:
+ return rval;
+}
+
+static int
+qla4xxx_read_nvram(struct bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
+ struct scsi_qla_host *ha = to_qla_host(host);
+ struct iscsi_bsg_request *bsg_req = bsg_job->request;
+ struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
+ uint32_t offset = 0;
+ uint32_t len = 0;
+ uint32_t total_len = 0;
+ dma_addr_t nvram_dma;
+ uint8_t *nvram = NULL;
+ int rval = -EINVAL;
+
+ bsg_reply->reply_payload_rcv_len = 0;
+
+ if (unlikely(pci_channel_offline(ha->pdev)))
+ goto leave;
+
+ /* Only 40xx adapters are supported */
+ if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha)))
+ goto leave;
+
+ if (ql4xxx_reset_active(ha)) {
+ ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
+ rval = -EBUSY;
+ goto leave;
+ }
+
+ offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
+ len = bsg_job->reply_payload.payload_len;
+ total_len = offset + len;
+
+ /* total len should not be greater than max NVRAM size */
+ if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) ||
+ ((is_qla4022(ha) || is_qla4032(ha)) &&
+ total_len > QL40X2_NVRAM_SIZE)) {
+ ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max"
+ " nvram size, offset=%d len=%d\n",
+ __func__, offset, len);
+ goto leave;
+ }
+
+ nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma,
+ GFP_KERNEL);
+ if (!nvram) {
+ ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for nvram "
+ "data\n", __func__);
+ rval = -ENOMEM;
+ goto leave;
+ }
+
+ rval = qla4xxx_get_nvram(ha, nvram_dma, offset, len);
+ if (rval) {
+ ql4_printk(KERN_ERR, ha, "%s: get nvram failed\n", __func__);
+ bsg_reply->result = DID_ERROR << 16;
+ rval = -EIO;
+ } else {
+ bsg_reply->reply_payload_rcv_len =
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt,
+ nvram, len);
+ bsg_reply->result = DID_OK << 16;
+ }
+
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+ dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma);
+leave:
+ return rval;
+}
+
+static int
+qla4xxx_update_nvram(struct bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
+ struct scsi_qla_host *ha = to_qla_host(host);
+ struct iscsi_bsg_request *bsg_req = bsg_job->request;
+ struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
+ uint32_t offset = 0;
+ uint32_t len = 0;
+ uint32_t total_len = 0;
+ dma_addr_t nvram_dma;
+ uint8_t *nvram = NULL;
+ int rval = -EINVAL;
+
+ bsg_reply->reply_payload_rcv_len = 0;
+
+ if (unlikely(pci_channel_offline(ha->pdev)))
+ goto leave;
+
+ if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha)))
+ goto leave;
+
+ if (ql4xxx_reset_active(ha)) {
+ ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
+ rval = -EBUSY;
+ goto leave;
+ }
+
+ offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
+ len = bsg_job->request_payload.payload_len;
+ total_len = offset + len;
+
+ /* total len should not be greater than max NVRAM size */
+ if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) ||
+ ((is_qla4022(ha) || is_qla4032(ha)) &&
+ total_len > QL40X2_NVRAM_SIZE)) {
+ ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max"
+ " nvram size, offset=%d len=%d\n",
+ __func__, offset, len);
+ goto leave;
+ }
+
+ nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma,
+ GFP_KERNEL);
+ if (!nvram) {
+ ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
+ "data\n", __func__);
+ rval = -ENOMEM;
+ goto leave;
+ }
+
+ sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, nvram, len);
+
+ rval = qla4xxx_set_nvram(ha, nvram_dma, offset, len);
+ if (rval) {
+ ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__);
+ bsg_reply->result = DID_ERROR << 16;
+ rval = -EIO;
+ } else
+ bsg_reply->result = DID_OK << 16;
+
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+ dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma);
+leave:
+ return rval;
+}
+
+static int
+qla4xxx_restore_defaults(struct bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
+ struct scsi_qla_host *ha = to_qla_host(host);
+ struct iscsi_bsg_request *bsg_req = bsg_job->request;
+ struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
+ uint32_t region = 0;
+ uint32_t field0 = 0;
+ uint32_t field1 = 0;
+ int rval = -EINVAL;
+
+ bsg_reply->reply_payload_rcv_len = 0;
+
+ if (unlikely(pci_channel_offline(ha->pdev)))
+ goto leave;
+
+ if (is_qla4010(ha))
+ goto leave;
+
+ if (ql4xxx_reset_active(ha)) {
+ ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
+ rval = -EBUSY;
+ goto leave;
+ }
+
+ region = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
+ field0 = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
+ field1 = bsg_req->rqst_data.h_vendor.vendor_cmd[3];
+
+ rval = qla4xxx_restore_factory_defaults(ha, region, field0, field1);
+ if (rval) {
+ ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__);
+ bsg_reply->result = DID_ERROR << 16;
+ rval = -EIO;
+ } else
+ bsg_reply->result = DID_OK << 16;
+
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+leave:
+ return rval;
+}
+
+static int
+qla4xxx_bsg_get_acb(struct bsg_job *bsg_job)
+{
+ struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
+ struct scsi_qla_host *ha = to_qla_host(host);
+ struct iscsi_bsg_request *bsg_req = bsg_job->request;
+ struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
+ uint32_t acb_type = 0;
+ uint32_t len = 0;
+ dma_addr_t acb_dma;
+ uint8_t *acb = NULL;
+ int rval = -EINVAL;
+
+ bsg_reply->reply_payload_rcv_len = 0;
+
+ if (unlikely(pci_channel_offline(ha->pdev)))
+ goto leave;
+
+ /* Only 4022 and above adapters are supported */
+ if (is_qla4010(ha))
+ goto leave;
+
+ if (ql4xxx_reset_active(ha)) {
+ ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
+ rval = -EBUSY;
+ goto leave;
+ }
+
+ acb_type = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
+ len = bsg_job->reply_payload.payload_len;
+ if (len < sizeof(struct addr_ctrl_blk)) {
+ ql4_printk(KERN_ERR, ha, "%s: invalid acb len %d\n",
+ __func__, len);
+ rval = -EINVAL;
+ goto leave;
+ }
+
+ acb = dma_alloc_coherent(&ha->pdev->dev, len, &acb_dma, GFP_KERNEL);
+ if (!acb) {
+ ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for acb "
+ "data\n", __func__);
+ rval = -ENOMEM;
+ goto leave;
+ }
+
+ rval = qla4xxx_get_acb(ha, acb_dma, acb_type, len);
+ if (rval) {
+ ql4_printk(KERN_ERR, ha, "%s: get acb failed\n", __func__);
+ bsg_reply->result = DID_ERROR << 16;
+ rval = -EIO;
+ } else {
+ bsg_reply->reply_payload_rcv_len =
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt,
+ acb, len);
+ bsg_reply->result = DID_OK << 16;
+ }
+
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+ dma_free_coherent(&ha->pdev->dev, len, acb, acb_dma);
+leave:
+ return rval;
+}
+
+/**
+ * qla4xxx_process_vendor_specific - handle vendor specific bsg request
+ * @job: iscsi_bsg_job to handle
+ **/
+int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job)
+{
+ struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
+ struct iscsi_bsg_request *bsg_req = bsg_job->request;
+ struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
+ struct scsi_qla_host *ha = to_qla_host(host);
+
+ switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
+ case QLISCSI_VND_READ_FLASH:
+ return qla4xxx_read_flash(bsg_job);
+
+ case QLISCSI_VND_UPDATE_FLASH:
+ return qla4xxx_update_flash(bsg_job);
+
+ case QLISCSI_VND_GET_ACB_STATE:
+ return qla4xxx_get_acb_state(bsg_job);
+
+ case QLISCSI_VND_READ_NVRAM:
+ return qla4xxx_read_nvram(bsg_job);
+
+ case QLISCSI_VND_UPDATE_NVRAM:
+ return qla4xxx_update_nvram(bsg_job);
+
+ case QLISCSI_VND_RESTORE_DEFAULTS:
+ return qla4xxx_restore_defaults(bsg_job);
+
+ case QLISCSI_VND_GET_ACB:
+ return qla4xxx_bsg_get_acb(bsg_job);
+
+ default:
+ ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: "
+ "0x%x\n", __func__, bsg_req->msgcode);
+ bsg_reply->result = (DID_ERROR << 16);
+ bsg_reply->reply_payload_rcv_len = 0;
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+ return -ENOSYS;
+ }
+}
+
+/**
+ * qla4xxx_bsg_request - handle bsg request from ISCSI transport
+ * @job: iscsi_bsg_job to handle
+ */
+int qla4xxx_bsg_request(struct bsg_job *bsg_job)
+{
+ struct iscsi_bsg_request *bsg_req = bsg_job->request;
+ struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
+ struct scsi_qla_host *ha = to_qla_host(host);
+
+ switch (bsg_req->msgcode) {
+ case ISCSI_BSG_HST_VENDOR:
+ return qla4xxx_process_vendor_specific(bsg_job);
+
+ default:
+ ql4_printk(KERN_ERR, ha, "%s: invalid BSG command: 0x%x\n",
+ __func__, bsg_req->msgcode);
+ }
+
+ return -ENOSYS;
+}
diff --git a/drivers/scsi/qla4xxx/ql4_bsg.h b/drivers/scsi/qla4xxx/ql4_bsg.h
new file mode 100644
index 000000000000..c6a0364509fd
--- /dev/null
+++ b/drivers/scsi/qla4xxx/ql4_bsg.h
@@ -0,0 +1,19 @@
+/*
+ * QLogic iSCSI HBA Driver
+ * Copyright (c) 2011 QLogic Corporation
+ *
+ * See LICENSE.qla4xxx for copyright and licensing details.
+ */
+#ifndef __QL4_BSG_H
+#define __QL4_BSG_H
+
+/* BSG Vendor specific commands */
+#define QLISCSI_VND_READ_FLASH 1
+#define QLISCSI_VND_UPDATE_FLASH 2
+#define QLISCSI_VND_GET_ACB_STATE 3
+#define QLISCSI_VND_READ_NVRAM 4
+#define QLISCSI_VND_UPDATE_NVRAM 5
+#define QLISCSI_VND_RESTORE_DEFAULTS 6
+#define QLISCSI_VND_GET_ACB 7
+
+#endif
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 473c5c872b39..ace637bf254e 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/aer.h>
+#include <linux/bsg-lib.h>
#include <net/tcp.h>
#include <scsi/scsi.h>
@@ -33,9 +34,14 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_iscsi.h>
+#include <scsi/scsi_bsg_iscsi.h>
+#include <scsi/scsi_netlink.h>
+#include <scsi/libiscsi.h>
#include "ql4_dbg.h"
#include "ql4_nx.h"
+#include "ql4_fw.h"
+#include "ql4_nvram.h"
#ifndef PCI_DEVICE_ID_QLOGIC_ISP4010
#define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010
@@ -109,7 +115,7 @@
#define MAX_BUSES 1
#define MAX_TARGETS MAX_DEV_DB_ENTRIES
#define MAX_LUNS 0xffff
-#define MAX_AEN_ENTRIES 256 /* should be > EXT_DEF_MAX_AEN_QUEUE */
+#define MAX_AEN_ENTRIES MAX_DEV_DB_ENTRIES
#define MAX_DDB_ENTRIES MAX_DEV_DB_ENTRIES
#define MAX_PDU_ENTRIES 32
#define INVALID_ENTRY 0xFFFF
@@ -166,6 +172,7 @@
#define RELOGIN_TOV 18
#define ISNS_DEREG_TOV 5
#define HBA_ONLINE_TOV 30
+#define DISABLE_ACB_TOV 30
#define MAX_RESET_HA_RETRIES 2
@@ -227,52 +234,12 @@ struct ql4_aen_log {
* Device Database (DDB) structure
*/
struct ddb_entry {
- struct list_head list; /* ddb list */
struct scsi_qla_host *ha;
struct iscsi_cls_session *sess;
struct iscsi_cls_conn *conn;
- atomic_t state; /* DDB State */
-
- unsigned long flags; /* DDB Flags */
-
uint16_t fw_ddb_index; /* DDB firmware index */
- uint16_t options;
uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */
-
- uint32_t CmdSn;
- uint16_t target_session_id;
- uint16_t connection_id;
- uint16_t exe_throttle; /* Max mumber of cmds outstanding
- * simultaneously */
- uint16_t task_mgmt_timeout; /* Min time for task mgmt cmds to
- * complete */
- uint16_t default_relogin_timeout; /* Max time to wait for
- * relogin to complete */
- uint16_t tcp_source_port_num;
- uint32_t default_time2wait; /* Default Min time between
- * relogins (+aens) */
-
- atomic_t retry_relogin_timer; /* Min Time between relogins
- * (4000 only) */
- atomic_t relogin_timer; /* Max Time to wait for relogin to complete */
- atomic_t relogin_retry_count; /* Num of times relogin has been
- * retried */
-
- uint16_t port;
- uint32_t tpgt;
- uint8_t ip_addr[IP_ADDR_LEN];
- uint8_t iscsi_name[ISCSI_NAME_SIZE]; /* 72 x48 */
- uint8_t iscsi_alias[0x20];
- uint8_t isid[6];
- uint16_t iscsi_max_burst_len;
- uint16_t iscsi_max_outsnd_r2t;
- uint16_t iscsi_first_burst_len;
- uint16_t iscsi_max_rcv_data_seg_len;
- uint16_t iscsi_max_snd_data_seg_len;
-
- struct in6_addr remote_ipv6_addr;
- struct in6_addr link_local_ipv6_addr;
};
/*
@@ -293,8 +260,6 @@ struct ddb_entry {
#define DF_FO_MASKED 3
-#include "ql4_fw.h"
-#include "ql4_nvram.h"
struct ql82xx_hw_data {
/* Offsets for flash/nvram access (set to ~0 if not used). */
@@ -312,7 +277,10 @@ struct ql82xx_hw_data {
uint32_t flt_region_boot;
uint32_t flt_region_bootload;
uint32_t flt_region_fw;
- uint32_t reserved;
+
+ uint32_t flt_iscsi_param;
+ uint32_t flt_region_chap;
+ uint32_t flt_chap_size;
};
struct qla4_8xxx_legacy_intr_set {
@@ -357,6 +325,68 @@ struct isp_operations {
int (*get_sys_info) (struct scsi_qla_host *);
};
+/*qla4xxx ipaddress configuration details */
+struct ipaddress_config {
+ uint16_t ipv4_options;
+ uint16_t tcp_options;
+ uint16_t ipv4_vlan_tag;
+ uint8_t ipv4_addr_state;
+ uint8_t ip_address[IP_ADDR_LEN];
+ uint8_t subnet_mask[IP_ADDR_LEN];
+ uint8_t gateway[IP_ADDR_LEN];
+ uint32_t ipv6_options;
+ uint32_t ipv6_addl_options;
+ uint8_t ipv6_link_local_state;
+ uint8_t ipv6_addr0_state;
+ uint8_t ipv6_addr1_state;
+ uint8_t ipv6_default_router_state;
+ uint16_t ipv6_vlan_tag;
+ struct in6_addr ipv6_link_local_addr;
+ struct in6_addr ipv6_addr0;
+ struct in6_addr ipv6_addr1;
+ struct in6_addr ipv6_default_router_addr;
+ uint16_t eth_mtu_size;
+ uint16_t ipv4_port;
+ uint16_t ipv6_port;
+};
+
+#define QL4_CHAP_MAX_NAME_LEN 256
+#define QL4_CHAP_MAX_SECRET_LEN 100
+#define LOCAL_CHAP 0
+#define BIDI_CHAP 1
+
+struct ql4_chap_format {
+ u8 intr_chap_name[QL4_CHAP_MAX_NAME_LEN];
+ u8 intr_secret[QL4_CHAP_MAX_SECRET_LEN];
+ u8 target_chap_name[QL4_CHAP_MAX_NAME_LEN];
+ u8 target_secret[QL4_CHAP_MAX_SECRET_LEN];
+ u16 intr_chap_name_length;
+ u16 intr_secret_length;
+ u16 target_chap_name_length;
+ u16 target_secret_length;
+};
+
+struct ip_address_format {
+ u8 ip_type;
+ u8 ip_address[16];
+};
+
+struct ql4_conn_info {
+ u16 dest_port;
+ struct ip_address_format dest_ipaddr;
+ struct ql4_chap_format chap;
+};
+
+struct ql4_boot_session_info {
+ u8 target_name[224];
+ struct ql4_conn_info conn_list[1];
+};
+
+struct ql4_boot_tgt_info {
+ struct ql4_boot_session_info boot_pri_sess;
+ struct ql4_boot_session_info boot_sec_sess;
+};
+
/*
* Linux Host Adapter structure
*/
@@ -451,10 +481,6 @@ struct scsi_qla_host {
/* --- From Init_FW --- */
/* init_cb_t *init_cb; */
uint16_t firmware_options;
- uint16_t tcp_options;
- uint8_t ip_address[IP_ADDR_LEN];
- uint8_t subnet_mask[IP_ADDR_LEN];
- uint8_t gateway[IP_ADDR_LEN];
uint8_t alias[32];
uint8_t name_string[256];
uint8_t heartbeat_interval;
@@ -462,7 +488,7 @@ struct scsi_qla_host {
/* --- From FlashSysInfo --- */
uint8_t my_mac[MAC_ADDR_LEN];
uint8_t serial_number[16];
-
+ uint16_t port_num;
/* --- From GetFwState --- */
uint32_t firmware_state;
uint32_t addl_fw_state;
@@ -524,31 +550,13 @@ struct scsi_qla_host {
volatile uint8_t mbox_status_count;
volatile uint32_t mbox_status[MBOX_REG_COUNT];
- /* local device database list (contains internal ddb entries) */
- struct list_head ddb_list;
-
- /* Map ddb_list entry by FW ddb index */
+ /* FW ddb index map */
struct ddb_entry *fw_ddb_index_map[MAX_DDB_ENTRIES];
/* Saved srb for status continuation entry processing */
struct srb *status_srb;
- /* IPv6 support info from InitFW */
uint8_t acb_version;
- uint8_t ipv4_addr_state;
- uint16_t ipv4_options;
-
- uint32_t resvd2;
- uint32_t ipv6_options;
- uint32_t ipv6_addl_options;
- uint8_t ipv6_link_local_state;
- uint8_t ipv6_addr0_state;
- uint8_t ipv6_addr1_state;
- uint8_t ipv6_default_router_state;
- struct in6_addr ipv6_link_local_addr;
- struct in6_addr ipv6_addr0;
- struct in6_addr ipv6_addr1;
- struct in6_addr ipv6_default_router_addr;
/* qla82xx specific fields */
struct device_reg_82xx __iomem *qla4_8xxx_reg; /* Base I/O address */
@@ -584,6 +592,11 @@ struct scsi_qla_host {
struct completion mbx_intr_comp;
+ struct ipaddress_config ip_config;
+ struct iscsi_iface *iface_ipv4;
+ struct iscsi_iface *iface_ipv6_0;
+ struct iscsi_iface *iface_ipv6_1;
+
/* --- From About Firmware --- */
uint16_t iscsi_major;
uint16_t iscsi_minor;
@@ -591,16 +604,60 @@ struct scsi_qla_host {
uint16_t bootload_minor;
uint16_t bootload_patch;
uint16_t bootload_build;
+
+ uint32_t flash_state;
+#define QLFLASH_WAITING 0
+#define QLFLASH_READING 1
+#define QLFLASH_WRITING 2
+ struct dma_pool *chap_dma_pool;
+ uint8_t *chap_list; /* CHAP table cache */
+ struct mutex chap_sem;
+#define CHAP_DMA_BLOCK_SIZE 512
+ struct workqueue_struct *task_wq;
+ unsigned long ddb_idx_map[MAX_DDB_ENTRIES / BITS_PER_LONG];
+#define SYSFS_FLAG_FW_SEL_BOOT 2
+ struct iscsi_boot_kset *boot_kset;
+ struct ql4_boot_tgt_info boot_tgt;
+ uint16_t phy_port_num;
+ uint16_t phy_port_cnt;
+ uint16_t iscsi_pci_func_cnt;
+ uint8_t model_name[16];
+ struct completion disable_acb_comp;
+};
+
+struct ql4_task_data {
+ struct scsi_qla_host *ha;
+ uint8_t iocb_req_cnt;
+ dma_addr_t data_dma;
+ void *req_buffer;
+ dma_addr_t req_dma;
+ uint32_t req_len;
+ void *resp_buffer;
+ dma_addr_t resp_dma;
+ uint32_t resp_len;
+ struct iscsi_task *task;
+ struct passthru_status sts;
+ struct work_struct task_work;
+};
+
+struct qla_endpoint {
+ struct Scsi_Host *host;
+ struct sockaddr dst_addr;
+};
+
+struct qla_conn {
+ struct qla_endpoint *qla_ep;
};
static inline int is_ipv4_enabled(struct scsi_qla_host *ha)
{
- return ((ha->ipv4_options & IPOPT_IPv4_PROTOCOL_ENABLE) != 0);
+ return ((ha->ip_config.ipv4_options & IPOPT_IPV4_PROTOCOL_ENABLE) != 0);
}
static inline int is_ipv6_enabled(struct scsi_qla_host *ha)
{
- return ((ha->ipv6_options & IPV6_OPT_IPV6_PROTOCOL_ENABLE) != 0);
+ return ((ha->ip_config.ipv6_options &
+ IPV6_OPT_IPV6_PROTOCOL_ENABLE) != 0);
}
static inline int is_qla4010(struct scsi_qla_host *ha)
@@ -618,6 +675,11 @@ static inline int is_qla4032(struct scsi_qla_host *ha)
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032;
}
+static inline int is_qla40XX(struct scsi_qla_host *ha)
+{
+ return is_qla4032(ha) || is_qla4022(ha) || is_qla4010(ha);
+}
+
static inline int is_qla8022(struct scsi_qla_host *ha)
{
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022;
@@ -640,7 +702,7 @@ static inline int adapter_up(struct scsi_qla_host *ha)
static inline struct scsi_qla_host* to_qla_host(struct Scsi_Host *shost)
{
- return (struct scsi_qla_host *)shost->hostdata;
+ return (struct scsi_qla_host *)iscsi_host_priv(shost);
}
static inline void __iomem* isp_semaphore(struct scsi_qla_host *ha)
@@ -760,6 +822,16 @@ static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a)
ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK);
}
+static inline int ql4xxx_reset_active(struct scsi_qla_host *ha)
+{
+ return test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
+ test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
+ test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) ||
+ test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
+ test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) ||
+ test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
+
+}
/*---------------------------------------------------------------------------*/
/* Defines for qla4xxx_initialize_adapter() and qla4xxx_recover_adapter() */
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 01082aa77098..cbd5a20dbbd1 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -146,6 +146,13 @@ struct isp_reg {
#define QL4022_NVRAM_SEM_MASK (QL4022_RESOURCE_MASK_BASE_CODE << (10+16))
#define QL4022_FLASH_SEM_MASK (QL4022_RESOURCE_MASK_BASE_CODE << (13+16))
+/* nvram address for 4032 */
+#define NVRAM_PORT0_BOOT_MODE 0x03b1
+#define NVRAM_PORT0_BOOT_PRI_TGT 0x03b2
+#define NVRAM_PORT0_BOOT_SEC_TGT 0x03bb
+#define NVRAM_PORT1_BOOT_MODE 0x07b1
+#define NVRAM_PORT1_BOOT_PRI_TGT 0x07b2
+#define NVRAM_PORT1_BOOT_SEC_TGT 0x07bb
/* Page # defines for 4022 */
@@ -194,6 +201,9 @@ static inline uint32_t clr_rmask(uint32_t val)
/* ISP 4022 nvram definitions */
#define NVR_WRITE_ENABLE 0x00000010 /* 4022 */
+#define QL4010_NVRAM_SIZE 0x200
+#define QL40X2_NVRAM_SIZE 0x800
+
/* ISP port_status definitions */
/* ISP Semaphore definitions */
@@ -241,6 +251,8 @@ union external_hw_config_reg {
#define FA_BOOT_CODE_ADDR_82 0x20000
#define FA_RISC_CODE_ADDR_82 0x40000
#define FA_GOLD_RISC_CODE_ADDR_82 0x80000
+#define FA_FLASH_ISCSI_CHAP 0x540000
+#define FA_FLASH_CHAP_SIZE 0xC0000
/* Flash Description Table */
struct qla_fdt_layout {
@@ -296,8 +308,11 @@ struct qla_flt_header {
#define FLT_REG_FLT 0x1c
#define FLT_REG_BOOTLOAD_82 0x72
#define FLT_REG_FW_82 0x74
+#define FLT_REG_FW_82_1 0x97
#define FLT_REG_GOLD_FW_82 0x75
#define FLT_REG_BOOT_CODE_82 0x78
+#define FLT_REG_ISCSI_PARAM 0x65
+#define FLT_REG_ISCSI_CHAP 0x63
struct qla_flt_region {
uint32_t code;
@@ -331,9 +346,11 @@ struct qla_flt_region {
#define MBOX_CMD_WRITE_FLASH 0x0025
#define MBOX_CMD_READ_FLASH 0x0026
#define MBOX_CMD_CLEAR_DATABASE_ENTRY 0x0031
+#define MBOX_CMD_CONN_OPEN 0x0074
#define MBOX_CMD_CONN_CLOSE_SESS_LOGOUT 0x0056
-#define LOGOUT_OPTION_CLOSE_SESSION 0x01
-#define LOGOUT_OPTION_RELOGIN 0x02
+#define LOGOUT_OPTION_CLOSE_SESSION 0x0002
+#define LOGOUT_OPTION_RELOGIN 0x0004
+#define LOGOUT_OPTION_FREE_DDB 0x0008
#define MBOX_CMD_EXECUTE_IOCB_A64 0x005A
#define MBOX_CMD_INITIALIZE_FIRMWARE 0x0060
#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK 0x0061
@@ -342,12 +359,15 @@ struct qla_flt_region {
#define MBOX_CMD_GET_DATABASE_ENTRY 0x0064
#define DDB_DS_UNASSIGNED 0x00
#define DDB_DS_NO_CONNECTION_ACTIVE 0x01
+#define DDB_DS_DISCOVERY 0x02
#define DDB_DS_SESSION_ACTIVE 0x04
#define DDB_DS_SESSION_FAILED 0x06
#define DDB_DS_LOGIN_IN_PROCESS 0x07
#define MBOX_CMD_GET_FW_STATE 0x0069
#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A
#define MBOX_CMD_GET_SYS_INFO 0x0078
+#define MBOX_CMD_GET_NVRAM 0x0078 /* For 40xx */
+#define MBOX_CMD_SET_NVRAM 0x0079 /* For 40xx */
#define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087
#define MBOX_CMD_SET_ACB 0x0088
#define MBOX_CMD_GET_ACB 0x0089
@@ -375,7 +395,10 @@ struct qla_flt_region {
#define FW_ADDSTATE_DHCPv4_LEASE_EXPIRED 0x0008
#define FW_ADDSTATE_LINK_UP 0x0010
#define FW_ADDSTATE_ISNS_SVC_ENABLED 0x0020
+
#define MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS 0x006B
+#define IPV6_DEFAULT_DDB_ENTRY 0x0001
+
#define MBOX_CMD_CONN_OPEN_SESS_LOGIN 0x0074
#define MBOX_CMD_GET_CRASH_RECORD 0x0076 /* 4010 only */
#define MBOX_CMD_GET_CONN_EVENT_LOG 0x0077
@@ -434,6 +457,14 @@ struct qla_flt_region {
#define ACB_STATE_VALID 0x05
#define ACB_STATE_DISABLING 0x06
+/* FLASH offsets */
+#define FLASH_SEGMENT_IFCB 0x04000000
+
+#define FLASH_OPT_RMW_HOLD 0
+#define FLASH_OPT_RMW_INIT 1
+#define FLASH_OPT_COMMIT 2
+#define FLASH_OPT_RMW_COMMIT 3
+
/*************************************************************************/
/* Host Adapter Initialization Control Block (from host) */
@@ -455,7 +486,8 @@ struct addr_ctrl_blk {
uint8_t res0; /* 07 */
uint16_t eth_mtu_size; /* 08-09 */
uint16_t add_fw_options; /* 0A-0B */
-#define SERIALIZE_TASK_MGMT 0x0400
+#define ADFWOPT_SERIALIZE_TASK_MGMT 0x0400
+#define ADFWOPT_AUTOCONN_DISABLE 0x0002
uint8_t hb_interval; /* 0C */
uint8_t inst_num; /* 0D */
@@ -473,8 +505,10 @@ struct addr_ctrl_blk {
uint16_t iscsi_opts; /* 30-31 */
uint16_t ipv4_tcp_opts; /* 32-33 */
+#define TCPOPT_DHCP_ENABLE 0x0200
uint16_t ipv4_ip_opts; /* 34-35 */
-#define IPOPT_IPv4_PROTOCOL_ENABLE 0x8000
+#define IPOPT_IPV4_PROTOCOL_ENABLE 0x8000
+#define IPOPT_VLAN_TAGGING_ENABLE 0x2000
uint16_t iscsi_max_pdu_size; /* 36-37 */
uint8_t ipv4_tos; /* 38 */
@@ -526,6 +560,7 @@ struct addr_ctrl_blk {
uint16_t ipv6_port; /* 204-205 */
uint16_t ipv6_opts; /* 206-207 */
#define IPV6_OPT_IPV6_PROTOCOL_ENABLE 0x8000
+#define IPV6_OPT_VLAN_TAGGING_ENABLE 0x2000
uint16_t ipv6_addtl_opts; /* 208-209 */
#define IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE 0x0002 /* Pri ACB
@@ -574,13 +609,105 @@ struct init_fw_ctrl_blk {
/* struct addr_ctrl_blk sec;*/
};
+#define PRIMARI_ACB 0
+#define SECONDARY_ACB 1
+
+struct addr_ctrl_blk_def {
+ uint8_t reserved1[1]; /* 00 */
+ uint8_t control; /* 01 */
+ uint8_t reserved2[11]; /* 02-0C */
+ uint8_t inst_num; /* 0D */
+ uint8_t reserved3[34]; /* 0E-2F */
+ uint16_t iscsi_opts; /* 30-31 */
+ uint16_t ipv4_tcp_opts; /* 32-33 */
+ uint16_t ipv4_ip_opts; /* 34-35 */
+ uint16_t iscsi_max_pdu_size; /* 36-37 */
+ uint8_t ipv4_tos; /* 38 */
+ uint8_t ipv4_ttl; /* 39 */
+ uint8_t reserved4[2]; /* 3A-3B */
+ uint16_t def_timeout; /* 3C-3D */
+ uint16_t iscsi_fburst_len; /* 3E-3F */
+ uint8_t reserved5[4]; /* 40-43 */
+ uint16_t iscsi_max_outstnd_r2t; /* 44-45 */
+ uint8_t reserved6[2]; /* 46-47 */
+ uint16_t ipv4_port; /* 48-49 */
+ uint16_t iscsi_max_burst_len; /* 4A-4B */
+ uint8_t reserved7[4]; /* 4C-4F */
+ uint8_t ipv4_addr[4]; /* 50-53 */
+ uint16_t ipv4_vlan_tag; /* 54-55 */
+ uint8_t ipv4_addr_state; /* 56 */
+ uint8_t ipv4_cacheid; /* 57 */
+ uint8_t reserved8[8]; /* 58-5F */
+ uint8_t ipv4_subnet[4]; /* 60-63 */
+ uint8_t reserved9[12]; /* 64-6F */
+ uint8_t ipv4_gw_addr[4]; /* 70-73 */
+ uint8_t reserved10[84]; /* 74-C7 */
+ uint8_t abort_timer; /* C8 */
+ uint8_t ipv4_tcp_wsf; /* C9 */
+ uint8_t reserved11[10]; /* CA-D3 */
+ uint8_t ipv4_dhcp_vid_len; /* D4 */
+ uint8_t ipv4_dhcp_vid[11]; /* D5-DF */
+ uint8_t reserved12[20]; /* E0-F3 */
+ uint8_t ipv4_dhcp_alt_cid_len; /* F4 */
+ uint8_t ipv4_dhcp_alt_cid[11]; /* F5-FF */
+ uint8_t iscsi_name[224]; /* 100-1DF */
+ uint8_t reserved13[32]; /* 1E0-1FF */
+ uint32_t cookie; /* 200-203 */
+ uint16_t ipv6_port; /* 204-205 */
+ uint16_t ipv6_opts; /* 206-207 */
+ uint16_t ipv6_addtl_opts; /* 208-209 */
+ uint16_t ipv6_tcp_opts; /* 20A-20B */
+ uint8_t ipv6_tcp_wsf; /* 20C */
+ uint16_t ipv6_flow_lbl; /* 20D-20F */
+ uint8_t ipv6_dflt_rtr_addr[16]; /* 210-21F */
+ uint16_t ipv6_vlan_tag; /* 220-221 */
+ uint8_t ipv6_lnk_lcl_addr_state; /* 222 */
+ uint8_t ipv6_addr0_state; /* 223 */
+ uint8_t ipv6_addr1_state; /* 224 */
+ uint8_t ipv6_dflt_rtr_state; /* 225 */
+ uint8_t ipv6_traffic_class; /* 226 */
+ uint8_t ipv6_hop_limit; /* 227 */
+ uint8_t ipv6_if_id[8]; /* 228-22F */
+ uint8_t ipv6_addr0[16]; /* 230-23F */
+ uint8_t ipv6_addr1[16]; /* 240-24F */
+ uint32_t ipv6_nd_reach_time; /* 250-253 */
+ uint32_t ipv6_nd_rexmit_timer; /* 254-257 */
+ uint32_t ipv6_nd_stale_timeout; /* 258-25B */
+ uint8_t ipv6_dup_addr_detect_count; /* 25C */
+ uint8_t ipv6_cache_id; /* 25D */
+ uint8_t reserved14[18]; /* 25E-26F */
+ uint32_t ipv6_gw_advrt_mtu; /* 270-273 */
+ uint8_t reserved15[140]; /* 274-2FF */
+};
+
/*************************************************************************/
+#define MAX_CHAP_ENTRIES_40XX 128
+#define MAX_CHAP_ENTRIES_82XX 1024
+#define MAX_RESRV_CHAP_IDX 3
+#define FLASH_CHAP_OFFSET 0x06000000
+
+struct ql4_chap_table {
+ uint16_t link;
+ uint8_t flags;
+ uint8_t secret_len;
+#define MIN_CHAP_SECRET_LEN 12
+#define MAX_CHAP_SECRET_LEN 100
+ uint8_t secret[MAX_CHAP_SECRET_LEN];
+#define MAX_CHAP_NAME_LEN 256
+ uint8_t name[MAX_CHAP_NAME_LEN];
+ uint16_t reserved;
+#define CHAP_VALID_COOKIE 0x4092
+#define CHAP_INVALID_COOKIE 0xFFEE
+ uint16_t cookie;
+};
+
struct dev_db_entry {
uint16_t options; /* 00-01 */
#define DDB_OPT_DISC_SESSION 0x10
#define DDB_OPT_TARGET 0x02 /* device is a target */
#define DDB_OPT_IPV6_DEVICE 0x100
+#define DDB_OPT_AUTO_SENDTGTS_DISABLE 0x40
#define DDB_OPT_IPV6_NULL_LINK_LOCAL 0x800 /* post connection */
#define DDB_OPT_IPV6_FW_DEFINED_LINK_LOCAL 0x800 /* pre connection */
@@ -591,6 +718,7 @@ struct dev_db_entry {
uint16_t tcp_options; /* 0A-0B */
uint16_t ip_options; /* 0C-0D */
uint16_t iscsi_max_rcv_data_seg_len; /* 0E-0F */
+#define BYTE_UNITS 512
uint32_t res1; /* 10-13 */
uint16_t iscsi_max_snd_data_seg_len; /* 14-15 */
uint16_t iscsi_first_burst_len; /* 16-17 */
@@ -627,7 +755,10 @@ struct dev_db_entry {
uint8_t tcp_rcv_wsf; /* 1C7 */
uint32_t stat_sn; /* 1C8-1CB */
uint32_t exp_stat_sn; /* 1CC-1CF */
- uint8_t res6[0x30]; /* 1D0-1FF */
+ uint8_t res6[0x2b]; /* 1D0-1FB */
+#define DDB_VALID_COOKIE 0x9034
+ uint16_t cookie; /* 1FC-1FD */
+ uint16_t len; /* 1FE-1FF */
};
/*************************************************************************/
@@ -639,6 +770,14 @@ struct dev_db_entry {
#define FLASH_EOF_OFFSET (FLASH_DEFAULTBLOCKSIZE-8) /* 4 bytes
* for EOF
* signature */
+#define FLASH_RAW_ACCESS_ADDR 0x8e000000
+
+#define BOOT_PARAM_OFFSET_PORT0 0x3b0
+#define BOOT_PARAM_OFFSET_PORT1 0x7b0
+
+#define FLASH_OFFSET_DB_INFO 0x05000000
+#define FLASH_OFFSET_DB_END (FLASH_OFFSET_DB_INFO + 0x7fff)
+
struct sys_info_phys_addr {
uint8_t address[6]; /* 00-05 */
@@ -774,6 +913,7 @@ struct qla4_header {
uint8_t entryStatus;
uint8_t systemDefined;
+#define SD_ISCSI_PDU 0x01
uint8_t entryCount;
/* SyetemDefined definition */
@@ -931,21 +1071,22 @@ struct passthru0 {
struct qla4_header hdr; /* 00-03 */
uint32_t handle; /* 04-07 */
uint16_t target; /* 08-09 */
- uint16_t connectionID; /* 0A-0B */
+ uint16_t connection_id; /* 0A-0B */
#define ISNS_DEFAULT_SERVER_CONN_ID ((uint16_t)0x8000)
- uint16_t controlFlags; /* 0C-0D */
+ uint16_t control_flags; /* 0C-0D */
#define PT_FLAG_ETHERNET_FRAME 0x8000
#define PT_FLAG_ISNS_PDU 0x8000
#define PT_FLAG_SEND_BUFFER 0x0200
#define PT_FLAG_WAIT_4_RESPONSE 0x0100
+#define PT_FLAG_ISCSI_PDU 0x1000
uint16_t timeout; /* 0E-0F */
#define PT_DEFAULT_TIMEOUT 30 /* seconds */
- struct data_seg_a64 outDataSeg64; /* 10-1B */
+ struct data_seg_a64 out_dsd; /* 10-1B */
uint32_t res1; /* 1C-1F */
- struct data_seg_a64 inDataSeg64; /* 20-2B */
+ struct data_seg_a64 in_dsd; /* 20-2B */
uint8_t res2[20]; /* 2C-3F */
};
@@ -978,4 +1119,43 @@ struct response {
#define RESPONSE_PROCESSED 0xDEADDEAD /* Signature */
};
+struct ql_iscsi_stats {
+ uint8_t reserved1[656]; /* 0000-028F */
+ uint32_t tx_cmd_pdu; /* 0290-0293 */
+ uint32_t tx_resp_pdu; /* 0294-0297 */
+ uint32_t rx_cmd_pdu; /* 0298-029B */
+ uint32_t rx_resp_pdu; /* 029C-029F */
+
+ uint64_t tx_data_octets; /* 02A0-02A7 */
+ uint64_t rx_data_octets; /* 02A8-02AF */
+
+ uint32_t hdr_digest_err; /* 02B0–02B3 */
+ uint32_t data_digest_err; /* 02B4–02B7 */
+ uint32_t conn_timeout_err; /* 02B8–02BB */
+ uint32_t framing_err; /* 02BC–02BF */
+
+ uint32_t tx_nopout_pdus; /* 02C0–02C3 */
+ uint32_t tx_scsi_cmd_pdus; /* 02C4–02C7 */
+ uint32_t tx_tmf_cmd_pdus; /* 02C8–02CB */
+ uint32_t tx_login_cmd_pdus; /* 02CC–02CF */
+ uint32_t tx_text_cmd_pdus; /* 02D0–02D3 */
+ uint32_t tx_scsi_write_pdus; /* 02D4–02D7 */
+ uint32_t tx_logout_cmd_pdus; /* 02D8–02DB */
+ uint32_t tx_snack_req_pdus; /* 02DC–02DF */
+
+ uint32_t rx_nopin_pdus; /* 02E0–02E3 */
+ uint32_t rx_scsi_resp_pdus; /* 02E4–02E7 */
+ uint32_t rx_tmf_resp_pdus; /* 02E8–02EB */
+ uint32_t rx_login_resp_pdus; /* 02EC–02EF */
+ uint32_t rx_text_resp_pdus; /* 02F0–02F3 */
+ uint32_t rx_scsi_read_pdus; /* 02F4–02F7 */
+ uint32_t rx_logout_resp_pdus; /* 02F8–02FB */
+
+ uint32_t rx_r2t_pdus; /* 02FC–02FF */
+ uint32_t rx_async_pdus; /* 0300–0303 */
+ uint32_t rx_reject_pdus; /* 0304–0307 */
+
+ uint8_t reserved2[264]; /* 0x0308 - 0x040F */
+};
+
#endif /* _QLA4X_FW_H */
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index a53a256c1f8d..160db9d5ea21 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -12,20 +12,15 @@ struct iscsi_cls_conn;
int qla4xxx_hw_reset(struct scsi_qla_host *ha);
int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a);
-int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port);
int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb *srb);
-int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
- uint8_t renew_ddb_list);
+int qla4xxx_initialize_adapter(struct scsi_qla_host *ha);
int qla4xxx_soft_reset(struct scsi_qla_host *ha);
irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id);
-void qla4xxx_free_ddb_list(struct scsi_qla_host *ha);
void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry);
void qla4xxx_process_aen(struct scsi_qla_host *ha, uint8_t process_aen);
int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host *ha);
-int qla4xxx_relogin_device(struct scsi_qla_host *ha,
- struct ddb_entry *ddb_entry);
int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb);
int qla4xxx_reset_lun(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry,
int lun);
@@ -51,15 +46,24 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
uint16_t *connection_id);
int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
- dma_addr_t fw_ddb_entry_dma);
-
-void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
- struct ddb_entry *ddb_entry);
+ dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts);
+uint8_t qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+ uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma);
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
+ uint16_t fw_ddb_index,
+ uint16_t connection_id,
+ uint16_t option);
+int qla4xxx_disable_acb(struct scsi_qla_host *ha);
+int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+ uint32_t *mbox_sts, dma_addr_t acb_dma);
+int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma,
+ uint32_t acb_type, uint32_t len);
+int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx,
+ uint32_t ip_idx, uint32_t *sts);
+void qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session);
u16 rd_nvram_word(struct scsi_qla_host *ha, int offset);
+u8 rd_nvram_byte(struct scsi_qla_host *ha, int offset);
void qla4xxx_get_crash_record(struct scsi_qla_host *ha);
-struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha);
-int qla4xxx_add_sess(struct ddb_entry *);
-void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry);
int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha);
int qla4xxx_about_firmware(struct scsi_qla_host *ha);
void qla4xxx_interrupt_service_routine(struct scsi_qla_host *ha,
@@ -68,14 +72,13 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha);
void qla4xxx_srb_compl(struct kref *ref);
struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
uint32_t index);
-int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha);
int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
uint32_t state, uint32_t conn_error);
void qla4xxx_dump_buffer(void *b, uint32_t size);
int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
-int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err);
-
+int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
+ uint32_t offset, uint32_t length, uint32_t options);
int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts);
@@ -95,6 +98,11 @@ void qla4xxx_wake_dpc(struct scsi_qla_host *ha);
void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha);
void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha);
void qla4xxx_dump_registers(struct scsi_qla_host *ha);
+uint8_t qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
+ uint32_t *mbox_cmd,
+ uint32_t *mbox_sts,
+ struct addr_ctrl_blk *init_fw_cb,
+ dma_addr_t init_fw_cb_dma);
void qla4_8xxx_pci_config(struct scsi_qla_host *);
int qla4_8xxx_iospace_config(struct scsi_qla_host *ha);
@@ -134,6 +142,37 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha);
void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha);
void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha);
void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha);
+int qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index);
+int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry,
+ struct iscsi_cls_conn *cls_conn,
+ uint32_t *mbx_sts);
+int qla4xxx_session_logout_ddb(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry, int options);
+int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
+ uint32_t *mbx_sts);
+int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index);
+int qla4xxx_send_passthru0(struct iscsi_task *task);
+int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,
+ uint16_t stats_size, dma_addr_t stats_dma);
+void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry);
+int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index);
+int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username,
+ char *password, uint16_t idx);
+int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
+ uint32_t offset, uint32_t size);
+int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
+ uint32_t offset, uint32_t size);
+int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha,
+ uint32_t region, uint32_t field0,
+ uint32_t field1);
+
+/* BSG Functions */
+int qla4xxx_bsg_request(struct bsg_job *bsg_job);
+int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job);
extern int ql4xextended_error_logging;
extern int ql4xdontresethba;
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 42ed5db2d530..3075fbaef553 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -11,9 +11,6 @@
#include "ql4_dbg.h"
#include "ql4_inline.h"
-static struct ddb_entry *qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
- uint32_t fw_ddb_index);
-
static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
{
uint32_t value;
@@ -48,41 +45,15 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
* @ha: pointer to host adapter structure.
* @ddb_entry: pointer to device database entry
*
- * This routine deallocates and unlinks the specified ddb_entry from the
- * adapter's
+ * This routine marks a DDB entry INVALID
**/
void qla4xxx_free_ddb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry)
{
- /* Remove device entry from list */
- list_del_init(&ddb_entry->list);
-
/* Remove device pointer from index mapping arrays */
ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] =
(struct ddb_entry *) INVALID_ENTRY;
ha->tot_ddbs--;
-
- /* Free memory and scsi-ml struct for device entry */
- qla4xxx_destroy_sess(ddb_entry);
-}
-
-/**
- * qla4xxx_free_ddb_list - deallocate all ddbs
- * @ha: pointer to host adapter structure.
- *
- * This routine deallocates and removes all devices on the sppecified adapter.
- **/
-void qla4xxx_free_ddb_list(struct scsi_qla_host *ha)
-{
- struct list_head *ptr;
- struct ddb_entry *ddb_entry;
-
- while (!list_empty(&ha->ddb_list)) {
- ptr = ha->ddb_list.next;
- /* Free memory for device entry and remove */
- ddb_entry = list_entry(ptr, struct ddb_entry, list);
- qla4xxx_free_ddb(ha, ddb_entry);
- }
}
/**
@@ -236,38 +207,44 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha)
FW_ADDSTATE_DHCPv4_LEASE_ACQUIRED) == 0)) {
ipv4_wait = 1;
}
- if (((ha->ipv6_addl_options &
- IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) &&
- ((ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING) ||
- (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING) ||
- (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING))) {
+ if (((ha->ip_config.ipv6_addl_options &
+ IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) &&
+ ((ha->ip_config.ipv6_link_local_state ==
+ IP_ADDRSTATE_ACQUIRING) ||
+ (ha->ip_config.ipv6_addr0_state ==
+ IP_ADDRSTATE_ACQUIRING) ||
+ (ha->ip_config.ipv6_addr1_state ==
+ IP_ADDRSTATE_ACQUIRING))) {
ipv6_wait = 1;
- if ((ha->ipv6_link_local_state ==
- IP_ADDRSTATE_PREFERRED) ||
- (ha->ipv6_addr0_state == IP_ADDRSTATE_PREFERRED) ||
- (ha->ipv6_addr1_state == IP_ADDRSTATE_PREFERRED)) {
+ if ((ha->ip_config.ipv6_link_local_state ==
+ IP_ADDRSTATE_PREFERRED) ||
+ (ha->ip_config.ipv6_addr0_state ==
+ IP_ADDRSTATE_PREFERRED) ||
+ (ha->ip_config.ipv6_addr1_state ==
+ IP_ADDRSTATE_PREFERRED)) {
DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
"Preferred IP configured."
" Don't wait!\n", ha->host_no,
__func__));
ipv6_wait = 0;
}
- if (memcmp(&ha->ipv6_default_router_addr, ip_address,
- IPv6_ADDR_LEN) == 0) {
+ if (memcmp(&ha->ip_config.ipv6_default_router_addr,
+ ip_address, IPv6_ADDR_LEN) == 0) {
DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
"No Router configured. "
"Don't wait!\n", ha->host_no,
__func__));
ipv6_wait = 0;
}
- if ((ha->ipv6_default_router_state ==
- IPV6_RTRSTATE_MANUAL) &&
- (ha->ipv6_link_local_state ==
- IP_ADDRSTATE_TENTATIVE) &&
- (memcmp(&ha->ipv6_link_local_addr,
- &ha->ipv6_default_router_addr, 4) == 0)) {
+ if ((ha->ip_config.ipv6_default_router_state ==
+ IPV6_RTRSTATE_MANUAL) &&
+ (ha->ip_config.ipv6_link_local_state ==
+ IP_ADDRSTATE_TENTATIVE) &&
+ (memcmp(&ha->ip_config.ipv6_link_local_addr,
+ &ha->ip_config.ipv6_default_router_addr, 4) ==
+ 0)) {
DEBUG2(printk("scsi%ld: %s: LinkLocal Router & "
"IP configured. Don't wait!\n",
ha->host_no, __func__));
@@ -279,11 +256,14 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha)
"IP(s) \"", ha->host_no, __func__));
if (ipv4_wait)
DEBUG2(printk("IPv4 "));
- if (ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING)
+ if (ha->ip_config.ipv6_link_local_state ==
+ IP_ADDRSTATE_ACQUIRING)
DEBUG2(printk("IPv6LinkLocal "));
- if (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING)
+ if (ha->ip_config.ipv6_addr0_state ==
+ IP_ADDRSTATE_ACQUIRING)
DEBUG2(printk("IPv6Addr0 "));
- if (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING)
+ if (ha->ip_config.ipv6_addr1_state ==
+ IP_ADDRSTATE_ACQUIRING)
DEBUG2(printk("IPv6Addr1 "));
DEBUG2(printk("\"\n"));
}
@@ -466,486 +446,19 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha)
return qla4xxx_get_firmware_status(ha);
}
-static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
- uint32_t fw_ddb_index,
- uint32_t *new_tgt)
-{
- struct dev_db_entry *fw_ddb_entry = NULL;
- dma_addr_t fw_ddb_entry_dma;
- struct ddb_entry *ddb_entry = NULL;
- int found = 0;
- uint32_t device_state;
-
- *new_tgt = 0;
- /* Make sure the dma buffer is valid */
- fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
- sizeof(*fw_ddb_entry),
- &fw_ddb_entry_dma, GFP_KERNEL);
- if (fw_ddb_entry == NULL) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
- ha->host_no, __func__));
- goto exit_get_ddb_entry_no_free;
- }
-
- if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
- fw_ddb_entry_dma, NULL, NULL,
- &device_state, NULL, NULL, NULL) ==
- QLA_ERROR) {
- DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for "
- "fw_ddb_index %d\n", ha->host_no, __func__,
- fw_ddb_index));
- goto exit_get_ddb_entry;
- }
-
- /* Allocate DDB if not already allocated. */
- DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no,
- __func__, fw_ddb_index));
- list_for_each_entry(ddb_entry, &ha->ddb_list, list) {
- if ((memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
- ISCSI_NAME_SIZE) == 0) &&
- (ddb_entry->tpgt ==
- le32_to_cpu(fw_ddb_entry->tgt_portal_grp)) &&
- (memcmp(ddb_entry->isid, fw_ddb_entry->isid,
- sizeof(ddb_entry->isid)) == 0)) {
- found++;
- break;
- }
- }
-
- /* if not found allocate new ddb */
- if (!found) {
- DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating "
- "new ddb\n", ha->host_no, __func__,
- fw_ddb_index));
- *new_tgt = 1;
- ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
- }
-
-exit_get_ddb_entry:
- dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry,
- fw_ddb_entry_dma);
-
-exit_get_ddb_entry_no_free:
- return ddb_entry;
-}
-
-/**
- * qla4xxx_update_ddb_entry - update driver's internal ddb
- * @ha: pointer to host adapter structure.
- * @ddb_entry: pointer to device database structure to be filled
- * @fw_ddb_index: index of the ddb entry in fw ddb table
- *
- * This routine updates the driver's internal device database entry
- * with information retrieved from the firmware's device database
- * entry for the specified device. The ddb_entry->fw_ddb_index field
- * must be initialized prior to calling this routine
- *
- **/
-static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
- struct ddb_entry *ddb_entry,
- uint32_t fw_ddb_index)
-{
- struct dev_db_entry *fw_ddb_entry = NULL;
- dma_addr_t fw_ddb_entry_dma;
- int status = QLA_ERROR;
- uint32_t conn_err;
-
- if (ddb_entry == NULL) {
- DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no,
- __func__));
-
- goto exit_update_ddb_no_free;
- }
-
- /* Make sure the dma buffer is valid */
- fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
- sizeof(*fw_ddb_entry),
- &fw_ddb_entry_dma, GFP_KERNEL);
- if (fw_ddb_entry == NULL) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
- ha->host_no, __func__));
-
- goto exit_update_ddb_no_free;
- }
-
- if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
- fw_ddb_entry_dma, NULL, NULL,
- &ddb_entry->fw_ddb_device_state, &conn_err,
- &ddb_entry->tcp_source_port_num,
- &ddb_entry->connection_id) ==
- QLA_ERROR) {
- DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for "
- "fw_ddb_index %d\n", ha->host_no, __func__,
- fw_ddb_index));
-
- goto exit_update_ddb;
- }
-
- status = QLA_SUCCESS;
- ddb_entry->options = le16_to_cpu(fw_ddb_entry->options);
- ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid);
- ddb_entry->task_mgmt_timeout =
- le16_to_cpu(fw_ddb_entry->def_timeout);
- ddb_entry->CmdSn = 0;
- ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exec_throttle);
- ddb_entry->default_relogin_timeout =
- le16_to_cpu(fw_ddb_entry->def_timeout);
- ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
-
- /* Update index in case it changed */
- ddb_entry->fw_ddb_index = fw_ddb_index;
- ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
-
- ddb_entry->port = le16_to_cpu(fw_ddb_entry->port);
- ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
- memcpy(ddb_entry->isid, fw_ddb_entry->isid, sizeof(ddb_entry->isid));
-
- memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
- min(sizeof(ddb_entry->iscsi_name),
- sizeof(fw_ddb_entry->iscsi_name)));
- memcpy(&ddb_entry->iscsi_alias[0], &fw_ddb_entry->iscsi_alias[0],
- min(sizeof(ddb_entry->iscsi_alias),
- sizeof(fw_ddb_entry->iscsi_alias)));
- memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0],
- min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr)));
-
- ddb_entry->iscsi_max_burst_len = fw_ddb_entry->iscsi_max_burst_len;
- ddb_entry->iscsi_max_outsnd_r2t = fw_ddb_entry->iscsi_max_outsnd_r2t;
- ddb_entry->iscsi_first_burst_len = fw_ddb_entry->iscsi_first_burst_len;
- ddb_entry->iscsi_max_rcv_data_seg_len =
- fw_ddb_entry->iscsi_max_rcv_data_seg_len;
- ddb_entry->iscsi_max_snd_data_seg_len =
- fw_ddb_entry->iscsi_max_snd_data_seg_len;
-
- if (ddb_entry->options & DDB_OPT_IPV6_DEVICE) {
- memcpy(&ddb_entry->remote_ipv6_addr,
- fw_ddb_entry->ip_addr,
- min(sizeof(ddb_entry->remote_ipv6_addr),
- sizeof(fw_ddb_entry->ip_addr)));
- memcpy(&ddb_entry->link_local_ipv6_addr,
- fw_ddb_entry->link_local_ipv6_addr,
- min(sizeof(ddb_entry->link_local_ipv6_addr),
- sizeof(fw_ddb_entry->link_local_ipv6_addr)));
-
- DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x"
- " ConnErr %08x IP %pI6 "
- ":%04d \"%s\"\n",
- __func__, fw_ddb_index,
- ddb_entry->fw_ddb_device_state,
- conn_err, fw_ddb_entry->ip_addr,
- le16_to_cpu(fw_ddb_entry->port),
- fw_ddb_entry->iscsi_name));
- } else
- DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x"
- " ConnErr %08x IP %pI4 "
- ":%04d \"%s\"\n",
- __func__, fw_ddb_index,
- ddb_entry->fw_ddb_device_state,
- conn_err, fw_ddb_entry->ip_addr,
- le16_to_cpu(fw_ddb_entry->port),
- fw_ddb_entry->iscsi_name));
-exit_update_ddb:
- if (fw_ddb_entry)
- dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
- fw_ddb_entry, fw_ddb_entry_dma);
-
-exit_update_ddb_no_free:
- return status;
-}
-
-/**
- * qla4xxx_alloc_ddb - allocate device database entry
- * @ha: Pointer to host adapter structure.
- * @fw_ddb_index: Firmware's device database index
- *
- * This routine allocates a ddb_entry, ititializes some values, and
- * inserts it into the ddb list.
- **/
-static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
- uint32_t fw_ddb_index)
+static void qla4xxx_set_model_info(struct scsi_qla_host *ha)
{
- struct ddb_entry *ddb_entry;
-
- DEBUG2(printk("scsi%ld: %s: fw_ddb_index [%d]\n", ha->host_no,
- __func__, fw_ddb_index));
-
- ddb_entry = qla4xxx_alloc_sess(ha);
- if (ddb_entry == NULL) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
- "to add fw_ddb_index [%d]\n",
- ha->host_no, __func__, fw_ddb_index));
- return ddb_entry;
- }
+ uint16_t board_id_string[8];
+ int i;
+ int size = sizeof(ha->nvram->isp4022.boardIdStr);
+ int offset = offsetof(struct eeprom_data, isp4022.boardIdStr) / 2;
- ddb_entry->fw_ddb_index = fw_ddb_index;
- atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
- atomic_set(&ddb_entry->relogin_timer, 0);
- atomic_set(&ddb_entry->relogin_retry_count, 0);
- atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
- list_add_tail(&ddb_entry->list, &ha->ddb_list);
- ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
- ha->tot_ddbs++;
-
- return ddb_entry;
-}
-
-/**
- * qla4_is_relogin_allowed - Are we allowed to login?
- * @ha: Pointer to host adapter structure.
- * @conn_err: Last connection error associated with the ddb
- *
- * This routine tests the given connection error to determine if
- * we are allowed to login.
- **/
-int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err)
-{
- uint32_t err_code, login_rsp_sts_class;
- int relogin = 1;
-
- err_code = ((conn_err & 0x00ff0000) >> 16);
- login_rsp_sts_class = ((conn_err & 0x0000ff00) >> 8);
- if (err_code == 0x1c || err_code == 0x06) {
- DEBUG2(ql4_printk(KERN_INFO, ha,
- ": conn_err=0x%08x, send target completed"
- " or access denied failure\n", conn_err));
- relogin = 0;
- }
- if ((err_code == 0x08) && (login_rsp_sts_class == 0x02)) {
- /* Login Response PDU returned an error.
- Login Response Status in Error Code Detail
- indicates login should not be retried.*/
- DEBUG2(ql4_printk(KERN_INFO, ha,
- ": conn_err=0x%08x, do not retry relogin\n",
- conn_err));
- relogin = 0;
+ for (i = 0; i < (size / 2) ; i++) {
+ board_id_string[i] = rd_nvram_word(ha, offset);
+ offset += 1;
}
- return relogin;
-}
-
-static void qla4xxx_flush_AENS(struct scsi_qla_host *ha)
-{
- unsigned long wtime;
-
- /* Flush the 0x8014 AEN from the firmware as a result of
- * Auto connect. We are basically doing get_firmware_ddb()
- * to determine whether we need to log back in or not.
- * Trying to do a set ddb before we have processed 0x8014
- * will result in another set_ddb() for the same ddb. In other
- * words there will be stale entries in the aen_q.
- */
- wtime = jiffies + (2 * HZ);
- do {
- if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS)
- if (ha->firmware_state & (BIT_2 | BIT_0))
- return;
-
- if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
- qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
-
- msleep(1000);
- } while (!time_after_eq(jiffies, wtime));
-}
-
-/**
- * qla4xxx_build_ddb_list - builds driver ddb list
- * @ha: Pointer to host adapter structure.
- *
- * This routine searches for all valid firmware ddb entries and builds
- * an internal ddb list. Ddbs that are considered valid are those with
- * a device state of SESSION_ACTIVE.
- * A relogin (set_ddb) is issued for DDBs that are not online.
- **/
-static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
-{
- int status = QLA_ERROR;
- uint32_t fw_ddb_index = 0;
- uint32_t next_fw_ddb_index = 0;
- uint32_t ddb_state;
- uint32_t conn_err;
- struct ddb_entry *ddb_entry;
- struct dev_db_entry *fw_ddb_entry = NULL;
- dma_addr_t fw_ddb_entry_dma;
- uint32_t ipv6_device;
- uint32_t new_tgt;
-
- qla4xxx_flush_AENS(ha);
-
- fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
- &fw_ddb_entry_dma, GFP_KERNEL);
- if (fw_ddb_entry == NULL) {
- DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DMA alloc failed\n",
- __func__));
-
- goto exit_build_ddb_list_no_free;
- }
-
- ql4_printk(KERN_INFO, ha, "Initializing DDBs ...\n");
- for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES;
- fw_ddb_index = next_fw_ddb_index) {
- /* First, let's see if a device exists here */
- if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
- 0, NULL, &next_fw_ddb_index,
- &ddb_state, &conn_err,
- NULL, NULL) ==
- QLA_ERROR) {
- DEBUG2(printk("scsi%ld: %s: get_ddb_entry, "
- "fw_ddb_index %d failed", ha->host_no,
- __func__, fw_ddb_index));
- goto exit_build_ddb_list;
- }
-
- DEBUG2(printk("scsi%ld: %s: Getting DDB[%d] ddbstate=0x%x, "
- "next_fw_ddb_index=%d.\n", ha->host_no, __func__,
- fw_ddb_index, ddb_state, next_fw_ddb_index));
-
- /* Issue relogin, if necessary. */
- if (ddb_state == DDB_DS_SESSION_FAILED ||
- ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) {
- /* Try and login to device */
- DEBUG2(printk("scsi%ld: %s: Login to DDB[%d]\n",
- ha->host_no, __func__, fw_ddb_index));
- ipv6_device = le16_to_cpu(fw_ddb_entry->options) &
- DDB_OPT_IPV6_DEVICE;
- if (qla4_is_relogin_allowed(ha, conn_err) &&
- ((!ipv6_device &&
- *((uint32_t *)fw_ddb_entry->ip_addr))
- || ipv6_device)) {
- qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0);
- if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index,
- NULL, 0, NULL,
- &next_fw_ddb_index,
- &ddb_state, &conn_err,
- NULL, NULL)
- == QLA_ERROR) {
- DEBUG2(printk("scsi%ld: %s:"
- "get_ddb_entry %d failed\n",
- ha->host_no,
- __func__, fw_ddb_index));
- goto exit_build_ddb_list;
- }
- }
- }
-
- if (ddb_state != DDB_DS_SESSION_ACTIVE)
- goto next_one;
- /*
- * if fw_ddb with session active state found,
- * add to ddb_list
- */
- DEBUG2(printk("scsi%ld: %s: DDB[%d] added to list\n",
- ha->host_no, __func__, fw_ddb_index));
-
- /* Add DDB to internal our ddb list. */
- ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
- if (ddb_entry == NULL) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
- "for device at fw_ddb_index %d\n",
- ha->host_no, __func__, fw_ddb_index));
- goto exit_build_ddb_list;
- }
- /* Fill in the device structure */
- if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
- QLA_ERROR) {
- ha->fw_ddb_index_map[fw_ddb_index] =
- (struct ddb_entry *)INVALID_ENTRY;
-
- DEBUG2(printk("scsi%ld: %s: update_ddb_entry failed "
- "for fw_ddb_index %d.\n",
- ha->host_no, __func__, fw_ddb_index));
- goto exit_build_ddb_list;
- }
-
-next_one:
- /* We know we've reached the last device when
- * next_fw_ddb_index is 0 */
- if (next_fw_ddb_index == 0)
- break;
- }
-
- status = QLA_SUCCESS;
- ql4_printk(KERN_INFO, ha, "DDB list done..\n");
-
-exit_build_ddb_list:
- dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry,
- fw_ddb_entry_dma);
-
-exit_build_ddb_list_no_free:
- return status;
-}
-
-static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha)
-{
- uint16_t fw_ddb_index;
- int status = QLA_SUCCESS;
-
- /* free the ddb list if is not empty */
- if (!list_empty(&ha->ddb_list))
- qla4xxx_free_ddb_list(ha);
-
- for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index++)
- ha->fw_ddb_index_map[fw_ddb_index] =
- (struct ddb_entry *)INVALID_ENTRY;
-
- ha->tot_ddbs = 0;
-
- /* Perform device discovery and build ddb list. */
- status = qla4xxx_build_ddb_list(ha);
-
- return status;
-}
-
-/**
- * qla4xxx_reinitialize_ddb_list - update the driver ddb list
- * @ha: pointer to host adapter structure.
- *
- * This routine obtains device information from the F/W database after
- * firmware or adapter resets. The device table is preserved.
- **/
-int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha)
-{
- int status = QLA_SUCCESS;
- struct ddb_entry *ddb_entry, *detemp;
-
- /* Update the device information for all devices. */
- list_for_each_entry_safe(ddb_entry, detemp, &ha->ddb_list, list) {
- qla4xxx_update_ddb_entry(ha, ddb_entry,
- ddb_entry->fw_ddb_index);
- if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
- atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
- DEBUG2(printk ("scsi%ld: %s: ddb index [%d] marked "
- "ONLINE\n", ha->host_no, __func__,
- ddb_entry->fw_ddb_index));
- iscsi_unblock_session(ddb_entry->sess);
- } else if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
- qla4xxx_mark_device_missing(ha, ddb_entry);
- }
- return status;
-}
-
-/**
- * qla4xxx_relogin_device - re-establish session
- * @ha: Pointer to host adapter structure.
- * @ddb_entry: Pointer to device database entry
- *
- * This routine does a session relogin with the specified device.
- * The ddb entry must be assigned prior to making this call.
- **/
-int qla4xxx_relogin_device(struct scsi_qla_host *ha,
- struct ddb_entry * ddb_entry)
-{
- uint16_t relogin_timer;
-
- relogin_timer = max(ddb_entry->default_relogin_timeout,
- (uint16_t)RELOGIN_TOV);
- atomic_set(&ddb_entry->relogin_timer, relogin_timer);
-
- DEBUG2(printk("scsi%ld: Relogin ddb [%d]. TOV=%d\n", ha->host_no,
- ddb_entry->fw_ddb_index, relogin_timer));
-
- qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 0);
-
- return QLA_SUCCESS;
+ memcpy(ha->model_name, board_id_string, size);
}
static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
@@ -983,6 +496,12 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
else
return QLA_ERROR;
}
+
+ if (is_qla4022(ha) || is_qla4032(ha))
+ qla4xxx_set_model_info(ha);
+ else
+ strcpy(ha->model_name, "QLA4010");
+
DEBUG(printk("scsi%ld: %s: Setting extHwConfig to 0xFFFF%04x\n",
ha->host_no, __func__, extHwConfig.Asuint32_t));
@@ -1246,23 +765,56 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha)
}
return status;
}
+/**
+ * qla4xxx_free_ddb_index - Free DDBs reserved by firmware
+ * @ha: pointer to adapter structure
+ *
+ * Since firmware is not running in autoconnect mode the DDB indices should
+ * be freed so that when login happens from user space there are free DDB
+ * indices available.
+ **/
+static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
+{
+ int max_ddbs;
+ int ret;
+ uint32_t idx = 0, next_idx = 0;
+ uint32_t state = 0, conn_err = 0;
+
+ max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES :
+ MAX_DEV_DB_ENTRIES;
+
+ for (idx = 0; idx < max_ddbs; idx = next_idx) {
+ ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL,
+ &next_idx, &state, &conn_err,
+ NULL, NULL);
+ if (ret == QLA_ERROR)
+ continue;
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
+ state == DDB_DS_SESSION_FAILED) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Freeing DDB index = 0x%x\n", idx));
+ ret = qla4xxx_clear_ddb_entry(ha, idx);
+ if (ret == QLA_ERROR)
+ ql4_printk(KERN_ERR, ha,
+ "Unable to clear DDB index = "
+ "0x%x\n", idx);
+ }
+ if (next_idx == 0)
+ break;
+ }
+}
/**
* qla4xxx_initialize_adapter - initiailizes hba
* @ha: Pointer to host adapter structure.
- * @renew_ddb_list: Indicates what to do with the adapter's ddb list
- * after adapter recovery has completed.
- * 0=preserve ddb list, 1=destroy and rebuild ddb list
*
* This routine parforms all of the steps necessary to initialize the adapter.
*
**/
-int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
- uint8_t renew_ddb_list)
+int qla4xxx_initialize_adapter(struct scsi_qla_host *ha)
{
int status = QLA_ERROR;
- int8_t ip_address[IP_ADDR_LEN] = {0} ;
ha->eeprom_cmd_data = 0;
@@ -1288,47 +840,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
if (status == QLA_ERROR)
goto exit_init_hba;
- /*
- * FW is waiting to get an IP address from DHCP server: Skip building
- * the ddb_list and wait for DHCP lease acquired aen to come in
- * followed by 0x8014 aen" to trigger the tgt discovery process.
- */
- if (ha->firmware_state & FW_STATE_CONFIGURING_IP)
- goto exit_init_online;
-
- /* Skip device discovery if ip and subnet is zero */
- if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 ||
- memcmp(ha->subnet_mask, ip_address, IP_ADDR_LEN) == 0)
- goto exit_init_online;
+ qla4xxx_free_ddb_index(ha);
- if (renew_ddb_list == PRESERVE_DDB_LIST) {
- /*
- * We want to preserve lun states (i.e. suspended, etc.)
- * for recovery initiated by the driver. So just update
- * the device states for the existing ddb_list.
- */
- qla4xxx_reinitialize_ddb_list(ha);
- } else if (renew_ddb_list == REBUILD_DDB_LIST) {
- /*
- * We want to build the ddb_list from scratch during
- * driver initialization and recovery initiated by the
- * INT_HBA_RESET IOCTL.
- */
- status = qla4xxx_initialize_ddb_list(ha);
- if (status == QLA_ERROR) {
- DEBUG2(printk("%s(%ld) Error occurred during build"
- "ddb list\n", __func__, ha->host_no));
- goto exit_init_hba;
- }
-
- }
- if (!ha->tot_ddbs) {
- DEBUG2(printk("scsi%ld: Failed to initialize devices or none "
- "present in Firmware device database\n",
- ha->host_no));
- }
-
-exit_init_online:
set_bit(AF_ONLINE, &ha->flags);
exit_init_hba:
if (is_qla8022(ha) && (status == QLA_ERROR)) {
@@ -1343,61 +856,6 @@ exit_init_hba:
}
/**
- * qla4xxx_add_device_dynamically - ddb addition due to an AEN
- * @ha: Pointer to host adapter structure.
- * @fw_ddb_index: Firmware's device database index
- *
- * This routine processes adds a device as a result of an 8014h AEN.
- **/
-static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha,
- uint32_t fw_ddb_index)
-{
- struct ddb_entry * ddb_entry;
- uint32_t new_tgt;
-
- /* First allocate a device structure */
- ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
- if (ddb_entry == NULL) {
- DEBUG2(printk(KERN_WARNING
- "scsi%ld: Unable to allocate memory to add "
- "fw_ddb_index %d\n", ha->host_no, fw_ddb_index));
- return;
- }
-
- if (!new_tgt && (ddb_entry->fw_ddb_index != fw_ddb_index)) {
- /* Target has been bound to a new fw_ddb_index */
- qla4xxx_free_ddb(ha, ddb_entry);
- ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
- if (ddb_entry == NULL) {
- DEBUG2(printk(KERN_WARNING
- "scsi%ld: Unable to allocate memory"
- " to add fw_ddb_index %d\n",
- ha->host_no, fw_ddb_index));
- return;
- }
- }
- if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
- QLA_ERROR) {
- ha->fw_ddb_index_map[fw_ddb_index] =
- (struct ddb_entry *)INVALID_ENTRY;
- DEBUG2(printk(KERN_WARNING
- "scsi%ld: failed to add new device at index "
- "[%d]\n Unable to retrieve fw ddb entry\n",
- ha->host_no, fw_ddb_index));
- qla4xxx_free_ddb(ha, ddb_entry);
- return;
- }
-
- if (qla4xxx_add_sess(ddb_entry)) {
- DEBUG2(printk(KERN_WARNING
- "scsi%ld: failed to add new device at index "
- "[%d]\n Unable to add connection and session\n",
- ha->host_no, fw_ddb_index));
- qla4xxx_free_ddb(ha, ddb_entry);
- }
-}
-
-/**
* qla4xxx_process_ddb_changed - process ddb state change
* @ha - Pointer to host adapter structure.
* @fw_ddb_index - Firmware's device database index
@@ -1409,88 +867,94 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
uint32_t state, uint32_t conn_err)
{
struct ddb_entry * ddb_entry;
+ uint32_t old_fw_ddb_device_state;
+ int status = QLA_ERROR;
/* check for out of range index */
if (fw_ddb_index >= MAX_DDB_ENTRIES)
- return QLA_ERROR;
+ goto exit_ddb_event;
/* Get the corresponging ddb entry */
ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
/* Device does not currently exist in our database. */
if (ddb_entry == NULL) {
- if (state == DDB_DS_SESSION_ACTIVE)
- qla4xxx_add_device_dynamically(ha, fw_ddb_index);
- return QLA_SUCCESS;
+ ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n",
+ __func__, fw_ddb_index);
+
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE)
+ clear_bit(fw_ddb_index, ha->ddb_idx_map);
+
+ goto exit_ddb_event;
}
- /* Device already exists in our database. */
- DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for "
- "index [%d]\n", ha->host_no, __func__,
- ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
+ old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: DDB - old state = 0x%x, new state = 0x%x for "
+ "index [%d]\n", __func__,
+ ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
ddb_entry->fw_ddb_device_state = state;
- /* Device is back online. */
- if ((ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) &&
- (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)) {
- atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
- atomic_set(&ddb_entry->relogin_retry_count, 0);
- atomic_set(&ddb_entry->relogin_timer, 0);
- clear_bit(DF_RELOGIN, &ddb_entry->flags);
- iscsi_unblock_session(ddb_entry->sess);
- iscsi_session_event(ddb_entry->sess,
- ISCSI_KEVENT_CREATE_SESSION);
- /*
- * Change the lun state to READY in case the lun TIMEOUT before
- * the device came back.
- */
- } else if (ddb_entry->fw_ddb_device_state != DDB_DS_SESSION_ACTIVE) {
- /* Device went away, mark device missing */
- if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
- DEBUG2(ql4_printk(KERN_INFO, ha, "%s mark missing "
- "ddb_entry 0x%p sess 0x%p conn 0x%p\n",
- __func__, ddb_entry,
- ddb_entry->sess, ddb_entry->conn));
- qla4xxx_mark_device_missing(ha, ddb_entry);
- }
- /*
- * Relogin if device state changed to a not active state.
- * However, do not relogin if a RELOGIN is in process, or
- * we are not allowed to relogin to this DDB.
- */
- if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED &&
- !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
- qla4_is_relogin_allowed(ha, conn_err)) {
+ switch (old_fw_ddb_device_state) {
+ case DDB_DS_LOGIN_IN_PROCESS:
+ switch (state) {
+ case DDB_DS_SESSION_ACTIVE:
+ case DDB_DS_DISCOVERY:
+ iscsi_conn_start(ddb_entry->conn);
+ iscsi_conn_login_event(ddb_entry->conn,
+ ISCSI_CONN_STATE_LOGGED_IN);
+ qla4xxx_update_session_conn_param(ha, ddb_entry);
+ status = QLA_SUCCESS;
+ break;
+ case DDB_DS_SESSION_FAILED:
+ case DDB_DS_NO_CONNECTION_ACTIVE:
+ iscsi_conn_login_event(ddb_entry->conn,
+ ISCSI_CONN_STATE_FREE);
+ status = QLA_SUCCESS;
+ break;
+ }
+ break;
+ case DDB_DS_SESSION_ACTIVE:
+ switch (state) {
+ case DDB_DS_SESSION_FAILED:
/*
- * This triggers a relogin. After the relogin_timer
- * expires, the relogin gets scheduled. We must wait a
- * minimum amount of time since receiving an 0x8014 AEN
- * with failed device_state or a logout response before
- * we can issue another relogin.
+ * iscsi_session failure will cause userspace to
+ * stop the connection which in turn would block the
+ * iscsi_session and start relogin
*/
- /* Firmware pads this timeout: (time2wait +1).
- * Driver retry to login should be longer than F/W.
- * Otherwise F/W will fail
- * set_ddb() mbx cmd with 0x4005 since it still
- * counting down its time2wait.
- */
- atomic_set(&ddb_entry->relogin_timer, 0);
- atomic_set(&ddb_entry->retry_relogin_timer,
- ddb_entry->default_time2wait + 4);
- DEBUG(printk("scsi%ld: %s: ddb[%d] "
- "initiate relogin after %d seconds\n",
- ha->host_no, __func__,
- ddb_entry->fw_ddb_index,
- ddb_entry->default_time2wait + 4));
- } else {
- DEBUG(printk("scsi%ld: %s: ddb[%d] "
- "relogin not initiated, state = %d, "
- "ddb_entry->flags = 0x%lx\n",
- ha->host_no, __func__,
- ddb_entry->fw_ddb_index,
- ddb_entry->fw_ddb_device_state,
- ddb_entry->flags));
+ iscsi_session_failure(ddb_entry->sess->dd_data,
+ ISCSI_ERR_CONN_FAILED);
+ status = QLA_SUCCESS;
+ break;
+ case DDB_DS_NO_CONNECTION_ACTIVE:
+ clear_bit(fw_ddb_index, ha->ddb_idx_map);
+ status = QLA_SUCCESS;
+ break;
+ }
+ break;
+ case DDB_DS_SESSION_FAILED:
+ switch (state) {
+ case DDB_DS_SESSION_ACTIVE:
+ case DDB_DS_DISCOVERY:
+ iscsi_conn_start(ddb_entry->conn);
+ iscsi_conn_login_event(ddb_entry->conn,
+ ISCSI_CONN_STATE_LOGGED_IN);
+ qla4xxx_update_session_conn_param(ha, ddb_entry);
+ status = QLA_SUCCESS;
+ break;
+ case DDB_DS_SESSION_FAILED:
+ iscsi_session_failure(ddb_entry->sess->dd_data,
+ ISCSI_ERR_CONN_FAILED);
+ status = QLA_SUCCESS;
+ break;
}
+ break;
+ default:
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n",
+ __func__));
+ break;
}
- return QLA_SUCCESS;
+
+exit_ddb_event:
+ return status;
}
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index 75fcd82a8fca..410669351906 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -313,10 +313,8 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
cmd_entry->hdr.entryType = ET_COMMAND;
cmd_entry->handle = cpu_to_le32(index);
cmd_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index);
- cmd_entry->connection_id = cpu_to_le16(ddb_entry->connection_id);
int_to_scsilun(cmd->device->lun, &cmd_entry->lun);
- cmd_entry->cmdSeqNum = cpu_to_le32(ddb_entry->CmdSn);
cmd_entry->ttlByteCnt = cpu_to_le32(scsi_bufflen(cmd));
memcpy(cmd_entry->cdb, cmd->cmnd, cmd->cmd_len);
cmd_entry->dataSegCnt = cpu_to_le16(tot_dsds);
@@ -381,3 +379,69 @@ queuing_error:
return QLA_ERROR;
}
+int qla4xxx_send_passthru0(struct iscsi_task *task)
+{
+ struct passthru0 *passthru_iocb;
+ struct iscsi_session *sess = task->conn->session;
+ struct ddb_entry *ddb_entry = sess->dd_data;
+ struct scsi_qla_host *ha = ddb_entry->ha;
+ struct ql4_task_data *task_data = task->dd_data;
+ uint16_t ctrl_flags = 0;
+ unsigned long flags;
+ int ret = QLA_ERROR;
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ task_data->iocb_req_cnt = 1;
+ /* Put the IOCB on the request queue */
+ if (!qla4xxx_space_in_req_ring(ha, task_data->iocb_req_cnt))
+ goto queuing_error;
+
+ passthru_iocb = (struct passthru0 *) ha->request_ptr;
+
+ memset(passthru_iocb, 0, sizeof(struct passthru0));
+ passthru_iocb->hdr.entryType = ET_PASSTHRU0;
+ passthru_iocb->hdr.systemDefined = SD_ISCSI_PDU;
+ passthru_iocb->hdr.entryCount = task_data->iocb_req_cnt;
+ passthru_iocb->handle = task->itt;
+ passthru_iocb->target = cpu_to_le16(ddb_entry->fw_ddb_index);
+ passthru_iocb->timeout = cpu_to_le16(PT_DEFAULT_TIMEOUT);
+
+ /* Setup the out & in DSDs */
+ if (task_data->req_len) {
+ memcpy((uint8_t *)task_data->req_buffer +
+ sizeof(struct iscsi_hdr), task->data, task->data_count);
+ ctrl_flags |= PT_FLAG_SEND_BUFFER;
+ passthru_iocb->out_dsd.base.addrLow =
+ cpu_to_le32(LSDW(task_data->req_dma));
+ passthru_iocb->out_dsd.base.addrHigh =
+ cpu_to_le32(MSDW(task_data->req_dma));
+ passthru_iocb->out_dsd.count =
+ cpu_to_le32(task->data_count +
+ sizeof(struct iscsi_hdr));
+ }
+ if (task_data->resp_len) {
+ passthru_iocb->in_dsd.base.addrLow =
+ cpu_to_le32(LSDW(task_data->resp_dma));
+ passthru_iocb->in_dsd.base.addrHigh =
+ cpu_to_le32(MSDW(task_data->resp_dma));
+ passthru_iocb->in_dsd.count =
+ cpu_to_le32(task_data->resp_len);
+ }
+
+ ctrl_flags |= (PT_FLAG_ISCSI_PDU | PT_FLAG_WAIT_4_RESPONSE);
+ passthru_iocb->control_flags = cpu_to_le16(ctrl_flags);
+
+ /* Update the request pointer */
+ qla4xxx_advance_req_ring_ptr(ha);
+ wmb();
+
+ /* Track IOCB used */
+ ha->iocb_cnt += task_data->iocb_req_cnt;
+ ha->req_q_count -= task_data->iocb_req_cnt;
+ ha->isp_ops->queue_iocb(ha);
+ ret = QLA_SUCCESS;
+
+queuing_error:
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ return ret;
+}
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 0e72921c752d..827e93078b94 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -224,8 +224,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
* I/O to this device. We should get a ddb state change
* AEN soon.
*/
- if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
- qla4xxx_mark_device_missing(ha, ddb_entry);
+ if (iscsi_is_session_online(ddb_entry->sess))
+ qla4xxx_mark_device_missing(ddb_entry->sess);
break;
case SCS_DATA_UNDERRUN:
@@ -306,8 +306,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
* send I/O to this device. We should get a ddb
* state change AEN soon.
*/
- if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
- qla4xxx_mark_device_missing(ha, ddb_entry);
+ if (iscsi_is_session_online(ddb_entry->sess))
+ qla4xxx_mark_device_missing(ddb_entry->sess);
cmd->result = DID_TRANSPORT_DISRUPTED << 16;
break;
@@ -341,6 +341,51 @@ status_entry_exit:
}
/**
+ * qla4xxx_passthru_status_entry - processes passthru status IOCBs (0x3C)
+ * @ha: Pointer to host adapter structure.
+ * @sts_entry: Pointer to status entry structure.
+ **/
+static void qla4xxx_passthru_status_entry(struct scsi_qla_host *ha,
+ struct passthru_status *sts_entry)
+{
+ struct iscsi_task *task;
+ struct ddb_entry *ddb_entry;
+ struct ql4_task_data *task_data;
+ struct iscsi_cls_conn *cls_conn;
+ struct iscsi_conn *conn;
+ itt_t itt;
+ uint32_t fw_ddb_index;
+
+ itt = sts_entry->handle;
+ fw_ddb_index = le32_to_cpu(sts_entry->target);
+
+ ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
+
+ if (ddb_entry == NULL) {
+ ql4_printk(KERN_ERR, ha, "%s: Invalid target index = 0x%x\n",
+ __func__, sts_entry->target);
+ return;
+ }
+
+ cls_conn = ddb_entry->conn;
+ conn = cls_conn->dd_data;
+ spin_lock(&conn->session->lock);
+ task = iscsi_itt_to_task(conn, itt);
+ spin_unlock(&conn->session->lock);
+
+ if (task == NULL) {
+ ql4_printk(KERN_ERR, ha, "%s: Task is NULL\n", __func__);
+ return;
+ }
+
+ task_data = task->dd_data;
+ memcpy(&task_data->sts, sts_entry, sizeof(struct passthru_status));
+ ha->req_q_count += task_data->iocb_req_cnt;
+ ha->iocb_cnt -= task_data->iocb_req_cnt;
+ queue_work(ha->task_wq, &task_data->task_work);
+}
+
+/**
* qla4xxx_process_response_queue - process response queue completions
* @ha: Pointer to host adapter structure.
*
@@ -375,6 +420,14 @@ void qla4xxx_process_response_queue(struct scsi_qla_host *ha)
break;
case ET_PASSTHRU_STATUS:
+ if (sts_entry->hdr.systemDefined == SD_ISCSI_PDU)
+ qla4xxx_passthru_status_entry(ha,
+ (struct passthru_status *)sts_entry);
+ else
+ ql4_printk(KERN_ERR, ha,
+ "%s: Invalid status received\n",
+ __func__);
+
break;
case ET_STATUS_CONTINUATION:
@@ -566,6 +619,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) &&
(mbox_sts[2] == ACB_STATE_VALID))
set_bit(DPC_RESET_HA, &ha->dpc_flags);
+ else if ((mbox_sts[3] == ACB_STATE_UNCONFIGURED))
+ complete(&ha->disable_acb_comp);
break;
case MBOX_ASTS_MAC_ADDRESS_CHANGED:
@@ -1009,23 +1064,23 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
switch (mbox_sts[0]) {
case MBOX_ASTS_DATABASE_CHANGED:
- if (process_aen == FLUSH_DDB_CHANGED_AENS) {
+ switch (process_aen) {
+ case FLUSH_DDB_CHANGED_AENS:
DEBUG2(printk("scsi%ld: AEN[%d] %04x, index "
"[%d] state=%04x FLUSHED!\n",
ha->host_no, ha->aen_out,
mbox_sts[0], mbox_sts[2],
mbox_sts[3]));
break;
+ case PROCESS_ALL_AENS:
+ default:
+ /* Specific device. */
+ if (mbox_sts[1] == 1)
+ qla4xxx_process_ddb_changed(ha,
+ mbox_sts[2], mbox_sts[3],
+ mbox_sts[4]);
+ break;
}
- case PROCESS_ALL_AENS:
- default:
- if (mbox_sts[1] == 0) { /* Global DB change. */
- qla4xxx_reinitialize_ddb_list(ha);
- } else if (mbox_sts[1] == 1) { /* Specific device. */
- qla4xxx_process_ddb_changed(ha, mbox_sts[2],
- mbox_sts[3], mbox_sts[4]);
- }
- break;
}
spin_lock_irqsave(&ha->hardware_lock, flags);
}
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index fce8289e9752..4c2b84870392 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -303,7 +303,7 @@ qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
return QLA_SUCCESS;
}
-static uint8_t
+uint8_t
qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
{
@@ -327,43 +327,69 @@ qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
static void
qla4xxx_update_local_ip(struct scsi_qla_host *ha,
- struct addr_ctrl_blk *init_fw_cb)
+ struct addr_ctrl_blk *init_fw_cb)
{
+ ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
+ ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
+ ha->ip_config.ipv4_addr_state =
+ le16_to_cpu(init_fw_cb->ipv4_addr_state);
+ ha->ip_config.eth_mtu_size =
+ le16_to_cpu(init_fw_cb->eth_mtu_size);
+ ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port);
+
+ if (ha->acb_version == ACB_SUPPORTED) {
+ ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts);
+ ha->ip_config.ipv6_addl_options =
+ le16_to_cpu(init_fw_cb->ipv6_addtl_opts);
+ }
+
/* Save IPv4 Address Info */
- memcpy(ha->ip_address, init_fw_cb->ipv4_addr,
- min(sizeof(ha->ip_address), sizeof(init_fw_cb->ipv4_addr)));
- memcpy(ha->subnet_mask, init_fw_cb->ipv4_subnet,
- min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->ipv4_subnet)));
- memcpy(ha->gateway, init_fw_cb->ipv4_gw_addr,
- min(sizeof(ha->gateway), sizeof(init_fw_cb->ipv4_gw_addr)));
+ memcpy(ha->ip_config.ip_address, init_fw_cb->ipv4_addr,
+ min(sizeof(ha->ip_config.ip_address),
+ sizeof(init_fw_cb->ipv4_addr)));
+ memcpy(ha->ip_config.subnet_mask, init_fw_cb->ipv4_subnet,
+ min(sizeof(ha->ip_config.subnet_mask),
+ sizeof(init_fw_cb->ipv4_subnet)));
+ memcpy(ha->ip_config.gateway, init_fw_cb->ipv4_gw_addr,
+ min(sizeof(ha->ip_config.gateway),
+ sizeof(init_fw_cb->ipv4_gw_addr)));
+
+ ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag);
if (is_ipv6_enabled(ha)) {
/* Save IPv6 Address */
- ha->ipv6_link_local_state = init_fw_cb->ipv6_lnk_lcl_addr_state;
- ha->ipv6_addr0_state = init_fw_cb->ipv6_addr0_state;
- ha->ipv6_addr1_state = init_fw_cb->ipv6_addr1_state;
- ha->ipv6_default_router_state = init_fw_cb->ipv6_dflt_rtr_state;
- ha->ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
- ha->ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
-
- memcpy(&ha->ipv6_link_local_addr.in6_u.u6_addr8[8],
- init_fw_cb->ipv6_if_id,
- min(sizeof(ha->ipv6_link_local_addr)/2,
- sizeof(init_fw_cb->ipv6_if_id)));
- memcpy(&ha->ipv6_addr0, init_fw_cb->ipv6_addr0,
- min(sizeof(ha->ipv6_addr0),
- sizeof(init_fw_cb->ipv6_addr0)));
- memcpy(&ha->ipv6_addr1, init_fw_cb->ipv6_addr1,
- min(sizeof(ha->ipv6_addr1),
- sizeof(init_fw_cb->ipv6_addr1)));
- memcpy(&ha->ipv6_default_router_addr,
- init_fw_cb->ipv6_dflt_rtr_addr,
- min(sizeof(ha->ipv6_default_router_addr),
- sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
+ ha->ip_config.ipv6_link_local_state =
+ le16_to_cpu(init_fw_cb->ipv6_lnk_lcl_addr_state);
+ ha->ip_config.ipv6_addr0_state =
+ le16_to_cpu(init_fw_cb->ipv6_addr0_state);
+ ha->ip_config.ipv6_addr1_state =
+ le16_to_cpu(init_fw_cb->ipv6_addr1_state);
+ ha->ip_config.ipv6_default_router_state =
+ le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state);
+ ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE;
+ ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80;
+
+ memcpy(&ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[8],
+ init_fw_cb->ipv6_if_id,
+ min(sizeof(ha->ip_config.ipv6_link_local_addr)/2,
+ sizeof(init_fw_cb->ipv6_if_id)));
+ memcpy(&ha->ip_config.ipv6_addr0, init_fw_cb->ipv6_addr0,
+ min(sizeof(ha->ip_config.ipv6_addr0),
+ sizeof(init_fw_cb->ipv6_addr0)));
+ memcpy(&ha->ip_config.ipv6_addr1, init_fw_cb->ipv6_addr1,
+ min(sizeof(ha->ip_config.ipv6_addr1),
+ sizeof(init_fw_cb->ipv6_addr1)));
+ memcpy(&ha->ip_config.ipv6_default_router_addr,
+ init_fw_cb->ipv6_dflt_rtr_addr,
+ min(sizeof(ha->ip_config.ipv6_default_router_addr),
+ sizeof(init_fw_cb->ipv6_dflt_rtr_addr)));
+ ha->ip_config.ipv6_vlan_tag =
+ be16_to_cpu(init_fw_cb->ipv6_vlan_tag);
+ ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port);
}
}
-static uint8_t
+uint8_t
qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
uint32_t *mbox_cmd,
uint32_t *mbox_sts,
@@ -383,9 +409,6 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
/* Save some info in adapter structure. */
ha->acb_version = init_fw_cb->acb_version;
ha->firmware_options = le16_to_cpu(init_fw_cb->fw_options);
- ha->tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts);
- ha->ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts);
- ha->ipv4_addr_state = le16_to_cpu(init_fw_cb->ipv4_addr_state);
ha->heartbeat_interval = init_fw_cb->hb_interval;
memcpy(ha->name_string, init_fw_cb->iscsi_name,
min(sizeof(ha->name_string),
@@ -393,10 +416,6 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
/*memcpy(ha->alias, init_fw_cb->Alias,
min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
- if (ha->acb_version == ACB_SUPPORTED) {
- ha->ipv6_options = init_fw_cb->ipv6_opts;
- ha->ipv6_addl_options = init_fw_cb->ipv6_addtl_opts;
- }
qla4xxx_update_local_ip(ha, init_fw_cb);
return QLA_SUCCESS;
@@ -462,10 +481,11 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
- /* Set bit for "serialize task mgmt" all other bits need to be zero */
init_fw_cb->add_fw_options = 0;
init_fw_cb->add_fw_options |=
- __constant_cpu_to_le16(SERIALIZE_TASK_MGMT);
+ __constant_cpu_to_le16(ADFWOPT_SERIALIZE_TASK_MGMT);
+ init_fw_cb->add_fw_options |=
+ __constant_cpu_to_le16(ADFWOPT_AUTOCONN_DISABLE);
if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
!= QLA_SUCCESS) {
@@ -691,19 +711,38 @@ exit_get_fwddb:
return status;
}
+int qla4xxx_conn_open(struct scsi_qla_host *ha, uint16_t fw_ddb_index)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_CONN_OPEN;
+ mbox_cmd[1] = fw_ddb_index;
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
+ &mbox_sts[0]);
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: status = %d mbx0 = 0x%x mbx1 = 0x%x\n",
+ __func__, status, mbox_sts[0], mbox_sts[1]));
+ return status;
+}
+
/**
* qla4xxx_set_fwddb_entry - sets a ddb entry.
* @ha: Pointer to host adapter structure.
* @fw_ddb_index: Firmware's device database index
- * @fw_ddb_entry: Pointer to firmware's ddb entry structure, or NULL.
+ * @fw_ddb_entry_dma: dma address of ddb entry
+ * @mbx_sts: mailbox 0 to be returned or NULL
*
* This routine initializes or updates the adapter's device database
- * entry for the specified device. It also triggers a login for the
- * specified device. Therefore, it may also be used as a secondary
- * login routine when a NULL pointer is specified for the fw_ddb_entry.
+ * entry for the specified device.
**/
int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
- dma_addr_t fw_ddb_entry_dma)
+ dma_addr_t fw_ddb_entry_dma, uint32_t *mbx_sts)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
@@ -722,13 +761,41 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
mbox_cmd[4] = sizeof(struct dev_db_entry);
status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
- &mbox_sts[0]);
+ &mbox_sts[0]);
+ if (mbx_sts)
+ *mbx_sts = mbox_sts[0];
DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n",
ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);)
return status;
}
+int qla4xxx_session_logout_ddb(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry, int options)
+{
+ int status;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
+ mbox_cmd[1] = ddb_entry->fw_ddb_index;
+ mbox_cmd[3] = options;
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
+ "failed sts %04X %04X", __func__,
+ mbox_sts[0], mbox_sts[1]));
+ }
+
+ return status;
+}
+
/**
* qla4xxx_get_crash_record - retrieves crash record.
* @ha: Pointer to host adapter structure.
@@ -805,7 +872,6 @@ void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
uint32_t max_event_log_entries;
uint8_t i;
-
memset(&mbox_cmd, 0, sizeof(mbox_cmd));
memset(&mbox_sts, 0, sizeof(mbox_cmd));
@@ -1104,7 +1170,7 @@ exit_about_fw:
return status;
}
-static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha,
+static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
dma_addr_t dma_addr)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
@@ -1114,6 +1180,7 @@ static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha,
memset(&mbox_sts, 0, sizeof(mbox_sts));
mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;
+ mbox_cmd[1] = options;
mbox_cmd[2] = LSDW(dma_addr);
mbox_cmd[3] = MSDW(dma_addr);
@@ -1126,8 +1193,10 @@ static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha,
return QLA_SUCCESS;
}
-static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
+int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index,
+ uint32_t *mbx_sts)
{
+ int status;
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
@@ -1135,75 +1204,646 @@ static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
memset(&mbox_sts, 0, sizeof(mbox_sts));
mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
- mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES;
+ mbox_cmd[1] = ddb_index;
- if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) !=
- QLA_SUCCESS) {
- if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) {
- *ddb_index = mbox_sts[2];
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
+ __func__, mbox_sts[0]));
+ }
+
+ *mbx_sts = mbox_sts[0];
+ return status;
+}
+
+int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t ddb_index)
+{
+ int status;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY;
+ mbox_cmd[1] = ddb_index;
+
+ status = qla4xxx_mailbox_command(ha, 2, 1, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n",
+ __func__, mbox_sts[0]));
+ }
+
+ return status;
+}
+
+int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
+ uint32_t offset, uint32_t length, uint32_t options)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status = QLA_SUCCESS;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_WRITE_FLASH;
+ mbox_cmd[1] = LSDW(dma_addr);
+ mbox_cmd[2] = MSDW(dma_addr);
+ mbox_cmd[3] = offset;
+ mbox_cmd[4] = length;
+ mbox_cmd[5] = options;
+
+ status = qla4xxx_mailbox_command(ha, 6, 2, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_WRITE_FLASH "
+ "failed w/ status %04X, mbx1 %04X\n",
+ __func__, mbox_sts[0], mbox_sts[1]));
+ }
+ return status;
+}
+
+int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
+{
+ uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;
+ uint32_t dev_db_end_offset;
+ int status = QLA_ERROR;
+
+ memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
+
+ dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));
+ dev_db_end_offset = FLASH_OFFSET_DB_END;
+
+ if (dev_db_start_offset > dev_db_end_offset) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s:Invalid DDB index %d", __func__,
+ ddb_index));
+ goto exit_bootdb_failed;
+ }
+
+ if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
+ sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
+ ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
+ "failed\n", ha->host_no, __func__);
+ goto exit_bootdb_failed;
+ }
+
+ if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
+ status = QLA_SUCCESS;
+
+exit_bootdb_failed:
+ return status;
+}
+
+int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
+ uint16_t idx)
+{
+ int ret = 0;
+ int rval = QLA_ERROR;
+ uint32_t offset = 0, chap_size;
+ struct ql4_chap_table *chap_table;
+ dma_addr_t chap_dma;
+
+ chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
+ if (chap_table == NULL) {
+ ret = -ENOMEM;
+ goto exit_get_chap;
+ }
+
+ chap_size = sizeof(struct ql4_chap_table);
+ memset(chap_table, 0, chap_size);
+
+ if (is_qla40XX(ha))
+ offset = FLASH_CHAP_OFFSET | (idx * chap_size);
+ else {
+ offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
+ /* flt_chap_size is CHAP table size for both ports
+ * so divide it by 2 to calculate the offset for second port
+ */
+ if (ha->port_num == 1)
+ offset += (ha->hw.flt_chap_size / 2);
+ offset += (idx * chap_size);
+ }
+
+ rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
+ if (rval != QLA_SUCCESS) {
+ ret = -EINVAL;
+ goto exit_get_chap;
+ }
+
+ DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",
+ __le16_to_cpu(chap_table->cookie)));
+
+ if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {
+ ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");
+ goto exit_get_chap;
+ }
+
+ strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
+ strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
+ chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
+
+exit_get_chap:
+ dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
+ return ret;
+}
+
+static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
+ char *password, uint16_t idx, int bidi)
+{
+ int ret = 0;
+ int rval = QLA_ERROR;
+ uint32_t offset = 0;
+ struct ql4_chap_table *chap_table;
+ dma_addr_t chap_dma;
+
+ chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
+ if (chap_table == NULL) {
+ ret = -ENOMEM;
+ goto exit_set_chap;
+ }
+
+ memset(chap_table, 0, sizeof(struct ql4_chap_table));
+ if (bidi)
+ chap_table->flags |= BIT_6; /* peer */
+ else
+ chap_table->flags |= BIT_7; /* local */
+ chap_table->secret_len = strlen(password);
+ strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN);
+ strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN);
+ chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
+ offset = FLASH_CHAP_OFFSET | (idx * sizeof(struct ql4_chap_table));
+ rval = qla4xxx_set_flash(ha, chap_dma, offset,
+ sizeof(struct ql4_chap_table),
+ FLASH_OPT_RMW_COMMIT);
+
+ if (rval == QLA_SUCCESS && ha->chap_list) {
+ /* Update ha chap_list cache */
+ memcpy((struct ql4_chap_table *)ha->chap_list + idx,
+ chap_table, sizeof(struct ql4_chap_table));
+ }
+ dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
+ if (rval != QLA_SUCCESS)
+ ret = -EINVAL;
+
+exit_set_chap:
+ return ret;
+}
+
+/**
+ * qla4xxx_get_chap_index - Get chap index given username and secret
+ * @ha: pointer to adapter structure
+ * @username: CHAP username to be searched
+ * @password: CHAP password to be searched
+ * @bidi: Is this a BIDI CHAP
+ * @chap_index: CHAP index to be returned
+ *
+ * Match the username and password in the chap_list, return the index if a
+ * match is found. If a match is not found then add the entry in FLASH and
+ * return the index at which entry is written in the FLASH.
+ **/
+static int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
+ char *password, int bidi, uint16_t *chap_index)
+{
+ int i, rval;
+ int free_index = -1;
+ int found_index = 0;
+ int max_chap_entries = 0;
+ struct ql4_chap_table *chap_table;
+
+ if (is_qla8022(ha))
+ max_chap_entries = (ha->hw.flt_chap_size / 2) /
+ sizeof(struct ql4_chap_table);
+ else
+ max_chap_entries = MAX_CHAP_ENTRIES_40XX;
+
+ if (!ha->chap_list) {
+ ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
+ return QLA_ERROR;
+ }
+
+ mutex_lock(&ha->chap_sem);
+ for (i = 0; i < max_chap_entries; i++) {
+ chap_table = (struct ql4_chap_table *)ha->chap_list + i;
+ if (chap_table->cookie !=
+ __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ if (i > MAX_RESRV_CHAP_IDX && free_index == -1)
+ free_index = i;
+ continue;
+ }
+ if (bidi) {
+ if (chap_table->flags & BIT_7)
+ continue;
} else {
- DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
- ha->host_no, __func__, mbox_sts[0]));
- return QLA_ERROR;
+ if (chap_table->flags & BIT_6)
+ continue;
+ }
+ if (!strncmp(chap_table->secret, password,
+ MAX_CHAP_SECRET_LEN) &&
+ !strncmp(chap_table->name, username,
+ MAX_CHAP_NAME_LEN)) {
+ *chap_index = i;
+ found_index = 1;
+ break;
}
- } else {
- *ddb_index = MAX_PRST_DEV_DB_ENTRIES;
}
- return QLA_SUCCESS;
+ /* If chap entry is not present and a free index is available then
+ * write the entry in flash
+ */
+ if (!found_index && free_index != -1) {
+ rval = qla4xxx_set_chap(ha, username, password,
+ free_index, bidi);
+ if (!rval) {
+ *chap_index = free_index;
+ found_index = 1;
+ }
+ }
+
+ mutex_unlock(&ha->chap_sem);
+
+ if (found_index)
+ return QLA_SUCCESS;
+ return QLA_ERROR;
}
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host *ha,
+ uint16_t fw_ddb_index,
+ uint16_t connection_id,
+ uint16_t option)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status = QLA_SUCCESS;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
+ mbox_cmd[1] = fw_ddb_index;
+ mbox_cmd[2] = connection_id;
+ mbox_cmd[3] = option;
-int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port)
+ status = qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_CONN_CLOSE "
+ "option %04x failed w/ status %04X %04X\n",
+ __func__, option, mbox_sts[0], mbox_sts[1]));
+ }
+ return status;
+}
+
+int qla4xxx_disable_acb(struct scsi_qla_host *ha)
{
- struct dev_db_entry *fw_ddb_entry;
- dma_addr_t fw_ddb_entry_dma;
- uint32_t ddb_index;
- int ret_val = QLA_SUCCESS;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status = QLA_SUCCESS;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_DISABLE_ACB;
+ status = qla4xxx_mailbox_command(ha, 8, 5, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_DISABLE_ACB "
+ "failed w/ status %04X %04X %04X", __func__,
+ mbox_sts[0], mbox_sts[1], mbox_sts[2]));
+ }
+ return status;
+}
+
+int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma,
+ uint32_t acb_type, uint32_t len)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status = QLA_SUCCESS;
- fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
- sizeof(*fw_ddb_entry),
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_GET_ACB;
+ mbox_cmd[1] = acb_type;
+ mbox_cmd[2] = LSDW(acb_dma);
+ mbox_cmd[3] = MSDW(acb_dma);
+ mbox_cmd[4] = len;
+
+ status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_GET_ACB "
+ "failed w/ status %04X\n", __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
+
+int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
+ uint32_t *mbox_sts, dma_addr_t acb_dma)
+{
+ int status = QLA_SUCCESS;
+
+ memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
+ memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
+ mbox_cmd[0] = MBOX_CMD_SET_ACB;
+ mbox_cmd[1] = 0; /* Primary ACB */
+ mbox_cmd[2] = LSDW(acb_dma);
+ mbox_cmd[3] = MSDW(acb_dma);
+ mbox_cmd[4] = sizeof(struct addr_ctrl_blk);
+
+ status = qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_SET_ACB "
+ "failed w/ status %04X\n", __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
+
+int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry,
+ struct iscsi_cls_conn *cls_conn,
+ uint32_t *mbx_sts)
+{
+ struct dev_db_entry *fw_ddb_entry;
+ struct iscsi_conn *conn;
+ struct iscsi_session *sess;
+ struct qla_conn *qla_conn;
+ struct sockaddr *dst_addr;
+ dma_addr_t fw_ddb_entry_dma;
+ int status = QLA_SUCCESS;
+ int rval = 0;
+ struct sockaddr_in *addr;
+ struct sockaddr_in6 *addr6;
+ char *ip;
+ uint16_t iscsi_opts = 0;
+ uint32_t options = 0;
+ uint16_t idx;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
&fw_ddb_entry_dma, GFP_KERNEL);
if (!fw_ddb_entry) {
- DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
- ha->host_no, __func__));
- ret_val = QLA_ERROR;
- goto exit_send_tgts_no_free;
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer.\n",
+ __func__));
+ rval = -ENOMEM;
+ goto exit_set_param_no_free;
}
- ret_val = qla4xxx_get_default_ddb(ha, fw_ddb_entry_dma);
- if (ret_val != QLA_SUCCESS)
- goto exit_send_tgts;
+ conn = cls_conn->dd_data;
+ qla_conn = conn->dd_data;
+ sess = conn->session;
+ dst_addr = &qla_conn->qla_ep->dst_addr;
- ret_val = qla4xxx_req_ddb_entry(ha, &ddb_index);
- if (ret_val != QLA_SUCCESS)
- goto exit_send_tgts;
+ if (dst_addr->sa_family == AF_INET6)
+ options |= IPV6_DEFAULT_DDB_ENTRY;
- memset(fw_ddb_entry->iscsi_alias, 0,
- sizeof(fw_ddb_entry->iscsi_alias));
+ status = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);
+ if (status == QLA_ERROR) {
+ rval = -EINVAL;
+ goto exit_set_param;
+ }
- memset(fw_ddb_entry->iscsi_name, 0,
- sizeof(fw_ddb_entry->iscsi_name));
+ iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options);
+ memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias));
+
+ memset(fw_ddb_entry->iscsi_name, 0, sizeof(fw_ddb_entry->iscsi_name));
+
+ if (sess->targetname != NULL) {
+ memcpy(fw_ddb_entry->iscsi_name, sess->targetname,
+ min(strlen(sess->targetname),
+ sizeof(fw_ddb_entry->iscsi_name)));
+ }
memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr));
- memset(fw_ddb_entry->tgt_addr, 0,
- sizeof(fw_ddb_entry->tgt_addr));
+ memset(fw_ddb_entry->tgt_addr, 0, sizeof(fw_ddb_entry->tgt_addr));
+
+ fw_ddb_entry->options = DDB_OPT_TARGET | DDB_OPT_AUTO_SENDTGTS_DISABLE;
+
+ if (dst_addr->sa_family == AF_INET) {
+ addr = (struct sockaddr_in *)dst_addr;
+ ip = (char *)&addr->sin_addr;
+ memcpy(fw_ddb_entry->ip_addr, ip, IP_ADDR_LEN);
+ fw_ddb_entry->port = cpu_to_le16(ntohs(addr->sin_port));
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: Destination Address [%pI4]: index [%d]\n",
+ __func__, fw_ddb_entry->ip_addr,
+ ddb_entry->fw_ddb_index));
+ } else if (dst_addr->sa_family == AF_INET6) {
+ addr6 = (struct sockaddr_in6 *)dst_addr;
+ ip = (char *)&addr6->sin6_addr;
+ memcpy(fw_ddb_entry->ip_addr, ip, IPv6_ADDR_LEN);
+ fw_ddb_entry->port = cpu_to_le16(ntohs(addr6->sin6_port));
+ fw_ddb_entry->options |= DDB_OPT_IPV6_DEVICE;
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "%s: Destination Address [%pI6]: index [%d]\n",
+ __func__, fw_ddb_entry->ip_addr,
+ ddb_entry->fw_ddb_index));
+ } else {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Failed to get IP Address\n",
+ __func__);
+ rval = -EINVAL;
+ goto exit_set_param;
+ }
+
+ /* CHAP */
+ if (sess->username != NULL && sess->password != NULL) {
+ if (strlen(sess->username) && strlen(sess->password)) {
+ iscsi_opts |= BIT_7;
+
+ rval = qla4xxx_get_chap_index(ha, sess->username,
+ sess->password,
+ LOCAL_CHAP, &idx);
+ if (rval)
+ goto exit_set_param;
+
+ fw_ddb_entry->chap_tbl_idx = cpu_to_le16(idx);
+ }
+ }
+
+ if (sess->username_in != NULL && sess->password_in != NULL) {
+ /* Check if BIDI CHAP */
+ if (strlen(sess->username_in) && strlen(sess->password_in)) {
+ iscsi_opts |= BIT_4;
+
+ rval = qla4xxx_get_chap_index(ha, sess->username_in,
+ sess->password_in,
+ BIDI_CHAP, &idx);
+ if (rval)
+ goto exit_set_param;
+ }
+ }
+
+ if (sess->initial_r2t_en)
+ iscsi_opts |= BIT_10;
+
+ if (sess->imm_data_en)
+ iscsi_opts |= BIT_11;
+
+ fw_ddb_entry->iscsi_options = cpu_to_le16(iscsi_opts);
+
+ if (conn->max_recv_dlength)
+ fw_ddb_entry->iscsi_max_rcv_data_seg_len =
+ __constant_cpu_to_le16((conn->max_recv_dlength / BYTE_UNITS));
- fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET);
- fw_ddb_entry->port = cpu_to_le16(ntohs(port));
+ if (sess->max_r2t)
+ fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t);
- fw_ddb_entry->ip_addr[0] = *ip;
- fw_ddb_entry->ip_addr[1] = *(ip + 1);
- fw_ddb_entry->ip_addr[2] = *(ip + 2);
- fw_ddb_entry->ip_addr[3] = *(ip + 3);
+ if (sess->first_burst)
+ fw_ddb_entry->iscsi_first_burst_len =
+ __constant_cpu_to_le16((sess->first_burst / BYTE_UNITS));
- ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma);
+ if (sess->max_burst)
+ fw_ddb_entry->iscsi_max_burst_len =
+ __constant_cpu_to_le16((sess->max_burst / BYTE_UNITS));
-exit_send_tgts:
+ if (sess->time2wait)
+ fw_ddb_entry->iscsi_def_time2wait =
+ cpu_to_le16(sess->time2wait);
+
+ if (sess->time2retain)
+ fw_ddb_entry->iscsi_def_time2retain =
+ cpu_to_le16(sess->time2retain);
+
+ status = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index,
+ fw_ddb_entry_dma, mbx_sts);
+
+ if (status != QLA_SUCCESS)
+ rval = -EINVAL;
+exit_set_param:
dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
fw_ddb_entry, fw_ddb_entry_dma);
-exit_send_tgts_no_free:
- return ret_val;
+exit_set_param_no_free:
+ return rval;
+}
+
+int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,
+ uint16_t stats_size, dma_addr_t stats_dma)
+{
+ int status = QLA_SUCCESS;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(mbox_cmd, 0, sizeof(mbox_cmd[0]) * MBOX_REG_COUNT);
+ memset(mbox_sts, 0, sizeof(mbox_sts[0]) * MBOX_REG_COUNT);
+ mbox_cmd[0] = MBOX_CMD_GET_MANAGEMENT_DATA;
+ mbox_cmd[1] = fw_ddb_index;
+ mbox_cmd[2] = LSDW(stats_dma);
+ mbox_cmd[3] = MSDW(stats_dma);
+ mbox_cmd[4] = stats_size;
+
+ status = qla4xxx_mailbox_command(ha, 5, 1, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha,
+ "%s: MBOX_CMD_GET_MANAGEMENT_DATA "
+ "failed w/ status %04X\n", __func__,
+ mbox_sts[0]));
+ }
+ return status;
}
+int qla4xxx_get_ip_state(struct scsi_qla_host *ha, uint32_t acb_idx,
+ uint32_t ip_idx, uint32_t *sts)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status = QLA_SUCCESS;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+ mbox_cmd[0] = MBOX_CMD_GET_IP_ADDR_STATE;
+ mbox_cmd[1] = acb_idx;
+ mbox_cmd[2] = ip_idx;
+
+ status = qla4xxx_mailbox_command(ha, 3, 8, &mbox_cmd[0], &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: "
+ "MBOX_CMD_GET_IP_ADDR_STATE failed w/ "
+ "status %04X\n", __func__, mbox_sts[0]));
+ }
+ memcpy(sts, mbox_sts, sizeof(mbox_sts));
+ return status;
+}
+
+int qla4xxx_get_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
+ uint32_t offset, uint32_t size)
+{
+ int status = QLA_SUCCESS;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_GET_NVRAM;
+ mbox_cmd[1] = LSDW(nvram_dma);
+ mbox_cmd[2] = MSDW(nvram_dma);
+ mbox_cmd[3] = offset;
+ mbox_cmd[4] = size;
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
+ "status %04X\n", ha->host_no, __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
+
+int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma,
+ uint32_t offset, uint32_t size)
+{
+ int status = QLA_SUCCESS;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_SET_NVRAM;
+ mbox_cmd[1] = LSDW(nvram_dma);
+ mbox_cmd[2] = MSDW(nvram_dma);
+ mbox_cmd[3] = offset;
+ mbox_cmd[4] = size;
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
+ "status %04X\n", ha->host_no, __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
+
+int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha,
+ uint32_t region, uint32_t field0,
+ uint32_t field1)
+{
+ int status = QLA_SUCCESS;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_RESTORE_FACTORY_DEFAULTS;
+ mbox_cmd[3] = region;
+ mbox_cmd[4] = field0;
+ mbox_cmd[5] = field1;
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0],
+ &mbox_sts[0]);
+ if (status != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
+ "status %04X\n", ha->host_no, __func__,
+ mbox_sts[0]));
+ }
+ return status;
+}
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c
index b4b859b2d47e..7851f314ba96 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.c
+++ b/drivers/scsi/qla4xxx/ql4_nvram.c
@@ -156,6 +156,27 @@ u16 rd_nvram_word(struct scsi_qla_host * ha, int offset)
return val;
}
+u8 rd_nvram_byte(struct scsi_qla_host *ha, int offset)
+{
+ u16 val = 0;
+ u8 rval = 0;
+ int index = 0;
+
+ if (offset & 0x1)
+ index = (offset - 1) / 2;
+ else
+ index = offset / 2;
+
+ val = le16_to_cpu(rd_nvram_word(ha, index));
+
+ if (offset & 0x1)
+ rval = (u8)((val & 0xff00) >> 8);
+ else
+ rval = (u8)((val & 0x00ff));
+
+ return rval;
+}
+
int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha)
{
int status = QLA_ERROR;
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index fdfe27b38698..f484ff438199 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -2015,11 +2015,19 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
hw->flt_region_boot = start;
break;
case FLT_REG_FW_82:
+ case FLT_REG_FW_82_1:
hw->flt_region_fw = start;
break;
case FLT_REG_BOOTLOAD_82:
hw->flt_region_bootload = start;
break;
+ case FLT_REG_ISCSI_PARAM:
+ hw->flt_iscsi_param = start;
+ break;
+ case FLT_REG_ISCSI_CHAP:
+ hw->flt_region_chap = start;
+ hw->flt_chap_size = le32_to_cpu(region->size);
+ break;
}
}
goto done;
@@ -2032,6 +2040,9 @@ no_flash_data:
hw->flt_region_boot = FA_BOOT_CODE_ADDR_82;
hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82;
hw->flt_region_fw = FA_RISC_CODE_ADDR_82;
+ hw->flt_region_chap = FA_FLASH_ISCSI_CHAP;
+ hw->flt_chap_size = FA_FLASH_CHAP_SIZE;
+
done:
DEBUG2(ql4_printk(KERN_INFO, ha, "FLT[%s]: flt=0x%x fdt=0x%x "
"boot=0x%x bootload=0x%x fw=0x%x\n", loc, hw->flt_region_flt,
@@ -2258,10 +2269,16 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha)
}
/* Save M.A.C. address & serial_number */
+ ha->port_num = sys_info->port_num;
memcpy(ha->my_mac, &sys_info->mac_addr[0],
min(sizeof(ha->my_mac), sizeof(sys_info->mac_addr)));
memcpy(ha->serial_number, &sys_info->serial_number,
min(sizeof(ha->serial_number), sizeof(sys_info->serial_number)));
+ memcpy(ha->model_name, &sys_info->board_id_str,
+ min(sizeof(ha->model_name), sizeof(sys_info->board_id_str)));
+ ha->phy_port_cnt = sys_info->phys_port_cnt;
+ ha->phy_port_num = sys_info->port_num;
+ ha->iscsi_pci_func_cnt = sys_info->iscsi_pci_func_cnt;
DEBUG2(printk("scsi%ld: %s: "
"mac %02x:%02x:%02x:%02x:%02x:%02x "
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index f2364ec59f03..30f31b127f33 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -6,6 +6,8 @@
*/
#include <linux/moduleparam.h>
#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/iscsi_boot_sysfs.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsicam.h>
@@ -63,6 +65,7 @@ MODULE_PARM_DESC(ql4xsess_recovery_tmo,
"Target Session Recovery Timeout.\n"
" Default: 30 sec.");
+static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);
/*
* SCSI host template entry points
*/
@@ -71,18 +74,41 @@ static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
/*
* iSCSI template entry points
*/
-static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
- enum iscsi_tgt_dscvr type, uint32_t enable,
- struct sockaddr *dst_addr);
static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
enum iscsi_param param, char *buf);
-static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
- enum iscsi_param param, char *buf);
static int qla4xxx_host_get_param(struct Scsi_Host *shost,
enum iscsi_host_param param, char *buf);
-static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+static int qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data,
+ uint32_t len);
+static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
+ enum iscsi_param_type param_type,
+ int param, char *buf);
static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
-
+static struct iscsi_endpoint *qla4xxx_ep_connect(struct Scsi_Host *shost,
+ struct sockaddr *dst_addr,
+ int non_blocking);
+static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms);
+static void qla4xxx_ep_disconnect(struct iscsi_endpoint *ep);
+static int qla4xxx_get_ep_param(struct iscsi_endpoint *ep,
+ enum iscsi_param param, char *buf);
+static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
+static struct iscsi_cls_conn *
+qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx);
+static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
+ struct iscsi_cls_conn *cls_conn,
+ uint64_t transport_fd, int is_leading);
+static void qla4xxx_conn_destroy(struct iscsi_cls_conn *conn);
+static struct iscsi_cls_session *
+qla4xxx_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ uint16_t qdepth, uint32_t initial_cmdsn);
+static void qla4xxx_session_destroy(struct iscsi_cls_session *sess);
+static void qla4xxx_task_work(struct work_struct *wdata);
+static int qla4xxx_alloc_pdu(struct iscsi_task *, uint8_t);
+static int qla4xxx_task_xmit(struct iscsi_task *);
+static void qla4xxx_task_cleanup(struct iscsi_task *);
+static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session);
+static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+ struct iscsi_stats *stats);
/*
* SCSI host template entry points
*/
@@ -94,7 +120,8 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
static int qla4xxx_slave_alloc(struct scsi_device *device);
static int qla4xxx_slave_configure(struct scsi_device *device);
static void qla4xxx_slave_destroy(struct scsi_device *sdev);
-static void qla4xxx_scan_start(struct Scsi_Host *shost);
+static mode_t ql4_attr_is_visible(int param_type, int param);
+static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type);
static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
QLA82XX_LEGACY_INTR_CONFIG;
@@ -115,9 +142,6 @@ static struct scsi_host_template qla4xxx_driver_template = {
.slave_alloc = qla4xxx_slave_alloc,
.slave_destroy = qla4xxx_slave_destroy,
- .scan_finished = iscsi_scan_finished,
- .scan_start = qla4xxx_scan_start,
-
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
@@ -125,58 +149,396 @@ static struct scsi_host_template qla4xxx_driver_template = {
.max_sectors = 0xFFFF,
.shost_attrs = qla4xxx_host_attrs,
+ .host_reset = qla4xxx_host_reset,
+ .vendor_id = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC,
};
static struct iscsi_transport qla4xxx_iscsi_transport = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
- .caps = CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD |
- CAP_DATA_PATH_OFFLOAD,
- .param_mask = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_TARGET_ALIAS,
- .host_param_mask = ISCSI_HOST_HWADDRESS |
- ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_INITIATOR_NAME,
- .tgt_dscvr = qla4xxx_tgt_dscvr,
+ .caps = CAP_TEXT_NEGO |
+ CAP_DATA_PATH_OFFLOAD | CAP_HDRDGST |
+ CAP_DATADGST | CAP_LOGIN_OFFLOAD |
+ CAP_MULTI_R2T,
+ .attr_is_visible = ql4_attr_is_visible,
+ .create_session = qla4xxx_session_create,
+ .destroy_session = qla4xxx_session_destroy,
+ .start_conn = qla4xxx_conn_start,
+ .create_conn = qla4xxx_conn_create,
+ .bind_conn = qla4xxx_conn_bind,
+ .stop_conn = iscsi_conn_stop,
+ .destroy_conn = qla4xxx_conn_destroy,
+ .set_param = iscsi_set_param,
.get_conn_param = qla4xxx_conn_get_param,
- .get_session_param = qla4xxx_sess_get_param,
+ .get_session_param = iscsi_session_get_param,
+ .get_ep_param = qla4xxx_get_ep_param,
+ .ep_connect = qla4xxx_ep_connect,
+ .ep_poll = qla4xxx_ep_poll,
+ .ep_disconnect = qla4xxx_ep_disconnect,
+ .get_stats = qla4xxx_conn_get_stats,
+ .send_pdu = iscsi_conn_send_pdu,
+ .xmit_task = qla4xxx_task_xmit,
+ .cleanup_task = qla4xxx_task_cleanup,
+ .alloc_pdu = qla4xxx_alloc_pdu,
+
.get_host_param = qla4xxx_host_get_param,
- .session_recovery_timedout = qla4xxx_recovery_timedout,
+ .set_iface_param = qla4xxx_iface_set_param,
+ .get_iface_param = qla4xxx_get_iface_param,
+ .bsg_request = qla4xxx_bsg_request,
};
static struct scsi_transport_template *qla4xxx_scsi_transport;
-static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
+static mode_t ql4_attr_is_visible(int param_type, int param)
{
- struct iscsi_cls_session *session;
- struct ddb_entry *ddb_entry;
+ switch (param_type) {
+ case ISCSI_HOST_PARAM:
+ switch (param) {
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ case ISCSI_HOST_PARAM_INITIATOR_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_PARAM:
+ switch (param) {
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_TARGET_NAME:
+ case ISCSI_PARAM_TPGT:
+ case ISCSI_PARAM_TARGET_ALIAS:
+ case ISCSI_PARAM_MAX_BURST:
+ case ISCSI_PARAM_MAX_R2T:
+ case ISCSI_PARAM_FIRST_BURST:
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ case ISCSI_PARAM_IFACE_NAME:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ case ISCSI_NET_PARAM:
+ switch (param) {
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ case ISCSI_NET_PARAM_IPV4_GW:
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
+ case ISCSI_NET_PARAM_IPV6_ADDR:
+ case ISCSI_NET_PARAM_IPV6_ROUTER:
+ case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
+ case ISCSI_NET_PARAM_VLAN_ID:
+ case ISCSI_NET_PARAM_VLAN_PRIORITY:
+ case ISCSI_NET_PARAM_VLAN_ENABLED:
+ case ISCSI_NET_PARAM_MTU:
+ case ISCSI_NET_PARAM_PORT:
+ return S_IRUGO;
+ default:
+ return 0;
+ }
+ }
- session = starget_to_session(scsi_target(sc->device));
- ddb_entry = session->dd_data;
+ return 0;
+}
- /* if we are not logged in then the LLD is going to clean up the cmd */
- if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
- return BLK_EH_RESET_TIMER;
- else
- return BLK_EH_NOT_HANDLED;
+static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
+ enum iscsi_param_type param_type,
+ int param, char *buf)
+{
+ struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ int len = -ENOSYS;
+
+ if (param_type != ISCSI_NET_PARAM)
+ return -ENOSYS;
+
+ switch (param) {
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);
+ break;
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ len = sprintf(buf, "%pI4\n", &ha->ip_config.subnet_mask);
+ break;
+ case ISCSI_NET_PARAM_IPV4_GW:
+ len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway);
+ break;
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv4_options &
+ IPOPT_IPV4_PROTOCOL_ENABLE) ?
+ "enabled" : "disabled");
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv6_options &
+ IPV6_OPT_IPV6_PROTOCOL_ENABLE) ?
+ "enabled" : "disabled");
+ break;
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.tcp_options & TCPOPT_DHCP_ENABLE) ?
+ "dhcp" : "static");
+ break;
+ case ISCSI_NET_PARAM_IPV6_ADDR:
+ if (iface->iface_num == 0)
+ len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr0);
+ if (iface->iface_num == 1)
+ len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr1);
+ break;
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
+ len = sprintf(buf, "%pI6\n",
+ &ha->ip_config.ipv6_link_local_addr);
+ break;
+ case ISCSI_NET_PARAM_IPV6_ROUTER:
+ len = sprintf(buf, "%pI6\n",
+ &ha->ip_config.ipv6_default_router_addr);
+ break;
+ case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv6_addl_options &
+ IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ?
+ "nd" : "static");
+ break;
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv6_addl_options &
+ IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ?
+ "auto" : "static");
+ break;
+ case ISCSI_NET_PARAM_VLAN_ID:
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
+ len = sprintf(buf, "%d\n",
+ (ha->ip_config.ipv4_vlan_tag &
+ ISCSI_MAX_VLAN_ID));
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ len = sprintf(buf, "%d\n",
+ (ha->ip_config.ipv6_vlan_tag &
+ ISCSI_MAX_VLAN_ID));
+ break;
+ case ISCSI_NET_PARAM_VLAN_PRIORITY:
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
+ len = sprintf(buf, "%d\n",
+ ((ha->ip_config.ipv4_vlan_tag >> 13) &
+ ISCSI_MAX_VLAN_PRIORITY));
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ len = sprintf(buf, "%d\n",
+ ((ha->ip_config.ipv6_vlan_tag >> 13) &
+ ISCSI_MAX_VLAN_PRIORITY));
+ break;
+ case ISCSI_NET_PARAM_VLAN_ENABLED:
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv4_options &
+ IPOPT_VLAN_TAGGING_ENABLE) ?
+ "enabled" : "disabled");
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ len = sprintf(buf, "%s\n",
+ (ha->ip_config.ipv6_options &
+ IPV6_OPT_VLAN_TAGGING_ENABLE) ?
+ "enabled" : "disabled");
+ break;
+ case ISCSI_NET_PARAM_MTU:
+ len = sprintf(buf, "%d\n", ha->ip_config.eth_mtu_size);
+ break;
+ case ISCSI_NET_PARAM_PORT:
+ if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
+ len = sprintf(buf, "%d\n", ha->ip_config.ipv4_port);
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
+ len = sprintf(buf, "%d\n", ha->ip_config.ipv6_port);
+ break;
+ default:
+ len = -ENOSYS;
+ }
+
+ return len;
}
-static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session)
+static struct iscsi_endpoint *
+qla4xxx_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
+ int non_blocking)
{
- struct ddb_entry *ddb_entry = session->dd_data;
- struct scsi_qla_host *ha = ddb_entry->ha;
+ int ret;
+ struct iscsi_endpoint *ep;
+ struct qla_endpoint *qla_ep;
+ struct scsi_qla_host *ha;
+ struct sockaddr_in *addr;
+ struct sockaddr_in6 *addr6;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ if (!shost) {
+ ret = -ENXIO;
+ printk(KERN_ERR "%s: shost is NULL\n",
+ __func__);
+ return ERR_PTR(ret);
+ }
+
+ ha = iscsi_host_priv(shost);
+
+ ep = iscsi_create_endpoint(sizeof(struct qla_endpoint));
+ if (!ep) {
+ ret = -ENOMEM;
+ return ERR_PTR(ret);
+ }
+
+ qla_ep = ep->dd_data;
+ memset(qla_ep, 0, sizeof(struct qla_endpoint));
+ if (dst_addr->sa_family == AF_INET) {
+ memcpy(&qla_ep->dst_addr, dst_addr, sizeof(struct sockaddr_in));
+ addr = (struct sockaddr_in *)&qla_ep->dst_addr;
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %pI4\n", __func__,
+ (char *)&addr->sin_addr));
+ } else if (dst_addr->sa_family == AF_INET6) {
+ memcpy(&qla_ep->dst_addr, dst_addr,
+ sizeof(struct sockaddr_in6));
+ addr6 = (struct sockaddr_in6 *)&qla_ep->dst_addr;
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %pI6\n", __func__,
+ (char *)&addr6->sin6_addr));
+ }
+
+ qla_ep->host = shost;
+
+ return ep;
+}
+
+static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
+{
+ struct qla_endpoint *qla_ep;
+ struct scsi_qla_host *ha;
+ int ret = 0;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ qla_ep = ep->dd_data;
+ ha = to_qla_host(qla_ep->host);
+
+ if (adapter_up(ha))
+ ret = 1;
+
+ return ret;
+}
+
+static void qla4xxx_ep_disconnect(struct iscsi_endpoint *ep)
+{
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ iscsi_destroy_endpoint(ep);
+}
+
+static int qla4xxx_get_ep_param(struct iscsi_endpoint *ep,
+ enum iscsi_param param,
+ char *buf)
+{
+ struct qla_endpoint *qla_ep = ep->dd_data;
+ struct sockaddr *dst_addr;
- if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
- atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
- DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout "
- "of (%d) secs exhausted, marking device DEAD.\n",
- ha->host_no, __func__, ddb_entry->fw_ddb_index,
- ddb_entry->sess->recovery_tmo));
+ switch (param) {
+ case ISCSI_PARAM_CONN_PORT:
+ case ISCSI_PARAM_CONN_ADDRESS:
+ if (!qla_ep)
+ return -ENOTCONN;
+
+ dst_addr = (struct sockaddr *)&qla_ep->dst_addr;
+ if (!dst_addr)
+ return -ENOTCONN;
+
+ return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+ &qla_ep->dst_addr, param, buf);
+ default:
+ return -ENOSYS;
}
}
+static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+ struct iscsi_stats *stats)
+{
+ struct iscsi_session *sess;
+ struct iscsi_cls_session *cls_sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+ struct ql_iscsi_stats *ql_iscsi_stats;
+ int stats_size;
+ int ret;
+ dma_addr_t iscsi_stats_dma;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+
+ cls_sess = iscsi_conn_to_session(cls_conn);
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+
+ stats_size = PAGE_ALIGN(sizeof(struct ql_iscsi_stats));
+ /* Allocate memory */
+ ql_iscsi_stats = dma_alloc_coherent(&ha->pdev->dev, stats_size,
+ &iscsi_stats_dma, GFP_KERNEL);
+ if (!ql_iscsi_stats) {
+ ql4_printk(KERN_ERR, ha,
+ "Unable to allocate memory for iscsi stats\n");
+ goto exit_get_stats;
+ }
+
+ ret = qla4xxx_get_mgmt_data(ha, ddb_entry->fw_ddb_index, stats_size,
+ iscsi_stats_dma);
+ if (ret != QLA_SUCCESS) {
+ ql4_printk(KERN_ERR, ha,
+ "Unable to retreive iscsi stats\n");
+ goto free_stats;
+ }
+
+ /* octets */
+ stats->txdata_octets = le64_to_cpu(ql_iscsi_stats->tx_data_octets);
+ stats->rxdata_octets = le64_to_cpu(ql_iscsi_stats->rx_data_octets);
+ /* xmit pdus */
+ stats->noptx_pdus = le32_to_cpu(ql_iscsi_stats->tx_nopout_pdus);
+ stats->scsicmd_pdus = le32_to_cpu(ql_iscsi_stats->tx_scsi_cmd_pdus);
+ stats->tmfcmd_pdus = le32_to_cpu(ql_iscsi_stats->tx_tmf_cmd_pdus);
+ stats->login_pdus = le32_to_cpu(ql_iscsi_stats->tx_login_cmd_pdus);
+ stats->text_pdus = le32_to_cpu(ql_iscsi_stats->tx_text_cmd_pdus);
+ stats->dataout_pdus = le32_to_cpu(ql_iscsi_stats->tx_scsi_write_pdus);
+ stats->logout_pdus = le32_to_cpu(ql_iscsi_stats->tx_logout_cmd_pdus);
+ stats->snack_pdus = le32_to_cpu(ql_iscsi_stats->tx_snack_req_pdus);
+ /* recv pdus */
+ stats->noprx_pdus = le32_to_cpu(ql_iscsi_stats->rx_nopin_pdus);
+ stats->scsirsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_scsi_resp_pdus);
+ stats->tmfrsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_tmf_resp_pdus);
+ stats->textrsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_text_resp_pdus);
+ stats->datain_pdus = le32_to_cpu(ql_iscsi_stats->rx_scsi_read_pdus);
+ stats->logoutrsp_pdus =
+ le32_to_cpu(ql_iscsi_stats->rx_logout_resp_pdus);
+ stats->r2t_pdus = le32_to_cpu(ql_iscsi_stats->rx_r2t_pdus);
+ stats->async_pdus = le32_to_cpu(ql_iscsi_stats->rx_async_pdus);
+ stats->rjt_pdus = le32_to_cpu(ql_iscsi_stats->rx_reject_pdus);
+
+free_stats:
+ dma_free_coherent(&ha->pdev->dev, stats_size, ql_iscsi_stats,
+ iscsi_stats_dma);
+exit_get_stats:
+ return;
+}
+
+static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
+{
+ struct iscsi_cls_session *session;
+ struct iscsi_session *sess;
+ unsigned long flags;
+ enum blk_eh_timer_return ret = BLK_EH_NOT_HANDLED;
+
+ session = starget_to_session(scsi_target(sc->device));
+ sess = session->dd_data;
+
+ spin_lock_irqsave(&session->lock, flags);
+ if (session->state == ISCSI_SESSION_FAILED)
+ ret = BLK_EH_RESET_TIMER;
+ spin_unlock_irqrestore(&session->lock, flags);
+
+ return ret;
+}
+
static int qla4xxx_host_get_param(struct Scsi_Host *shost,
enum iscsi_host_param param, char *buf)
{
@@ -188,9 +550,7 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
len = sysfs_format_mac(buf, ha->my_mac, MAC_ADDR_LEN);
break;
case ISCSI_HOST_PARAM_IPADDRESS:
- len = sprintf(buf, "%d.%d.%d.%d\n", ha->ip_address[0],
- ha->ip_address[1], ha->ip_address[2],
- ha->ip_address[3]);
+ len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);
break;
case ISCSI_HOST_PARAM_INITIATOR_NAME:
len = sprintf(buf, "%s\n", ha->name_string);
@@ -202,154 +562,851 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
return len;
}
-static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
- enum iscsi_param param, char *buf)
+static void qla4xxx_create_ipv4_iface(struct scsi_qla_host *ha)
{
- struct ddb_entry *ddb_entry = sess->dd_data;
- int len;
+ if (ha->iface_ipv4)
+ return;
- switch (param) {
- case ISCSI_PARAM_TARGET_NAME:
- len = snprintf(buf, PAGE_SIZE - 1, "%s\n",
- ddb_entry->iscsi_name);
+ /* IPv4 */
+ ha->iface_ipv4 = iscsi_create_iface(ha->host,
+ &qla4xxx_iscsi_transport,
+ ISCSI_IFACE_TYPE_IPV4, 0, 0);
+ if (!ha->iface_ipv4)
+ ql4_printk(KERN_ERR, ha, "Could not create IPv4 iSCSI "
+ "iface0.\n");
+}
+
+static void qla4xxx_create_ipv6_iface(struct scsi_qla_host *ha)
+{
+ if (!ha->iface_ipv6_0)
+ /* IPv6 iface-0 */
+ ha->iface_ipv6_0 = iscsi_create_iface(ha->host,
+ &qla4xxx_iscsi_transport,
+ ISCSI_IFACE_TYPE_IPV6, 0,
+ 0);
+ if (!ha->iface_ipv6_0)
+ ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI "
+ "iface0.\n");
+
+ if (!ha->iface_ipv6_1)
+ /* IPv6 iface-1 */
+ ha->iface_ipv6_1 = iscsi_create_iface(ha->host,
+ &qla4xxx_iscsi_transport,
+ ISCSI_IFACE_TYPE_IPV6, 1,
+ 0);
+ if (!ha->iface_ipv6_1)
+ ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI "
+ "iface1.\n");
+}
+
+static void qla4xxx_create_ifaces(struct scsi_qla_host *ha)
+{
+ if (ha->ip_config.ipv4_options & IPOPT_IPV4_PROTOCOL_ENABLE)
+ qla4xxx_create_ipv4_iface(ha);
+
+ if (ha->ip_config.ipv6_options & IPV6_OPT_IPV6_PROTOCOL_ENABLE)
+ qla4xxx_create_ipv6_iface(ha);
+}
+
+static void qla4xxx_destroy_ipv4_iface(struct scsi_qla_host *ha)
+{
+ if (ha->iface_ipv4) {
+ iscsi_destroy_iface(ha->iface_ipv4);
+ ha->iface_ipv4 = NULL;
+ }
+}
+
+static void qla4xxx_destroy_ipv6_iface(struct scsi_qla_host *ha)
+{
+ if (ha->iface_ipv6_0) {
+ iscsi_destroy_iface(ha->iface_ipv6_0);
+ ha->iface_ipv6_0 = NULL;
+ }
+ if (ha->iface_ipv6_1) {
+ iscsi_destroy_iface(ha->iface_ipv6_1);
+ ha->iface_ipv6_1 = NULL;
+ }
+}
+
+static void qla4xxx_destroy_ifaces(struct scsi_qla_host *ha)
+{
+ qla4xxx_destroy_ipv4_iface(ha);
+ qla4xxx_destroy_ipv6_iface(ha);
+}
+
+static void qla4xxx_set_ipv6(struct scsi_qla_host *ha,
+ struct iscsi_iface_param_info *iface_param,
+ struct addr_ctrl_blk *init_fw_cb)
+{
+ /*
+ * iface_num 0 is valid for IPv6 Addr, linklocal, router, autocfg.
+ * iface_num 1 is valid only for IPv6 Addr.
+ */
+ switch (iface_param->param) {
+ case ISCSI_NET_PARAM_IPV6_ADDR:
+ if (iface_param->iface_num & 0x1)
+ /* IPv6 Addr 1 */
+ memcpy(init_fw_cb->ipv6_addr1, iface_param->value,
+ sizeof(init_fw_cb->ipv6_addr1));
+ else
+ /* IPv6 Addr 0 */
+ memcpy(init_fw_cb->ipv6_addr0, iface_param->value,
+ sizeof(init_fw_cb->ipv6_addr0));
+ break;
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
+ if (iface_param->iface_num & 0x1)
+ break;
+ memcpy(init_fw_cb->ipv6_if_id, &iface_param->value[8],
+ sizeof(init_fw_cb->ipv6_if_id));
+ break;
+ case ISCSI_NET_PARAM_IPV6_ROUTER:
+ if (iface_param->iface_num & 0x1)
+ break;
+ memcpy(init_fw_cb->ipv6_dflt_rtr_addr, iface_param->value,
+ sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
+ break;
+ case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:
+ /* Autocfg applies to even interface */
+ if (iface_param->iface_num & 0x1)
+ break;
+
+ if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_DISABLE)
+ init_fw_cb->ipv6_addtl_opts &=
+ cpu_to_le16(
+ ~IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
+ else if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_ND_ENABLE)
+ init_fw_cb->ipv6_addtl_opts |=
+ cpu_to_le16(
+ IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);
+ else
+ ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
+ "IPv6 addr\n");
break;
- case ISCSI_PARAM_TPGT:
- len = sprintf(buf, "%u\n", ddb_entry->tpgt);
+ case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:
+ /* Autocfg applies to even interface */
+ if (iface_param->iface_num & 0x1)
+ break;
+
+ if (iface_param->value[0] ==
+ ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE)
+ init_fw_cb->ipv6_addtl_opts |= cpu_to_le16(
+ IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
+ else if (iface_param->value[0] ==
+ ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE)
+ init_fw_cb->ipv6_addtl_opts &= cpu_to_le16(
+ ~IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);
+ else
+ ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for "
+ "IPv6 linklocal addr\n");
break;
- case ISCSI_PARAM_TARGET_ALIAS:
- len = snprintf(buf, PAGE_SIZE - 1, "%s\n",
- ddb_entry->iscsi_alias);
+ case ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG:
+ /* Autocfg applies to even interface */
+ if (iface_param->iface_num & 0x1)
+ break;
+
+ if (iface_param->value[0] == ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE)
+ memset(init_fw_cb->ipv6_dflt_rtr_addr, 0,
+ sizeof(init_fw_cb->ipv6_dflt_rtr_addr));
+ break;
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ if (iface_param->value[0] == ISCSI_IFACE_ENABLE) {
+ init_fw_cb->ipv6_opts |=
+ cpu_to_le16(IPV6_OPT_IPV6_PROTOCOL_ENABLE);
+ qla4xxx_create_ipv6_iface(ha);
+ } else {
+ init_fw_cb->ipv6_opts &=
+ cpu_to_le16(~IPV6_OPT_IPV6_PROTOCOL_ENABLE &
+ 0xFFFF);
+ qla4xxx_destroy_ipv6_iface(ha);
+ }
+ break;
+ case ISCSI_NET_PARAM_VLAN_TAG:
+ if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag))
+ break;
+ init_fw_cb->ipv6_vlan_tag =
+ cpu_to_be16(*(uint16_t *)iface_param->value);
+ break;
+ case ISCSI_NET_PARAM_VLAN_ENABLED:
+ if (iface_param->value[0] == ISCSI_VLAN_ENABLE)
+ init_fw_cb->ipv6_opts |=
+ cpu_to_le16(IPV6_OPT_VLAN_TAGGING_ENABLE);
+ else
+ init_fw_cb->ipv6_opts &=
+ cpu_to_le16(~IPV6_OPT_VLAN_TAGGING_ENABLE);
+ break;
+ case ISCSI_NET_PARAM_MTU:
+ init_fw_cb->eth_mtu_size =
+ cpu_to_le16(*(uint16_t *)iface_param->value);
+ break;
+ case ISCSI_NET_PARAM_PORT:
+ /* Autocfg applies to even interface */
+ if (iface_param->iface_num & 0x1)
+ break;
+
+ init_fw_cb->ipv6_port =
+ cpu_to_le16(*(uint16_t *)iface_param->value);
break;
default:
- return -ENOSYS;
+ ql4_printk(KERN_ERR, ha, "Unknown IPv6 param = %d\n",
+ iface_param->param);
+ break;
}
+}
- return len;
+static void qla4xxx_set_ipv4(struct scsi_qla_host *ha,
+ struct iscsi_iface_param_info *iface_param,
+ struct addr_ctrl_blk *init_fw_cb)
+{
+ switch (iface_param->param) {
+ case ISCSI_NET_PARAM_IPV4_ADDR:
+ memcpy(init_fw_cb->ipv4_addr, iface_param->value,
+ sizeof(init_fw_cb->ipv4_addr));
+ break;
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ memcpy(init_fw_cb->ipv4_subnet, iface_param->value,
+ sizeof(init_fw_cb->ipv4_subnet));
+ break;
+ case ISCSI_NET_PARAM_IPV4_GW:
+ memcpy(init_fw_cb->ipv4_gw_addr, iface_param->value,
+ sizeof(init_fw_cb->ipv4_gw_addr));
+ break;
+ case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
+ if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
+ init_fw_cb->ipv4_tcp_opts |=
+ cpu_to_le16(TCPOPT_DHCP_ENABLE);
+ else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
+ init_fw_cb->ipv4_tcp_opts &=
+ cpu_to_le16(~TCPOPT_DHCP_ENABLE);
+ else
+ ql4_printk(KERN_ERR, ha, "Invalid IPv4 bootproto\n");
+ break;
+ case ISCSI_NET_PARAM_IFACE_ENABLE:
+ if (iface_param->value[0] == ISCSI_IFACE_ENABLE) {
+ init_fw_cb->ipv4_ip_opts |=
+ cpu_to_le16(IPOPT_IPV4_PROTOCOL_ENABLE);
+ qla4xxx_create_ipv4_iface(ha);
+ } else {
+ init_fw_cb->ipv4_ip_opts &=
+ cpu_to_le16(~IPOPT_IPV4_PROTOCOL_ENABLE &
+ 0xFFFF);
+ qla4xxx_destroy_ipv4_iface(ha);
+ }
+ break;
+ case ISCSI_NET_PARAM_VLAN_TAG:
+ if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag))
+ break;
+ init_fw_cb->ipv4_vlan_tag =
+ cpu_to_be16(*(uint16_t *)iface_param->value);
+ break;
+ case ISCSI_NET_PARAM_VLAN_ENABLED:
+ if (iface_param->value[0] == ISCSI_VLAN_ENABLE)
+ init_fw_cb->ipv4_ip_opts |=
+ cpu_to_le16(IPOPT_VLAN_TAGGING_ENABLE);
+ else
+ init_fw_cb->ipv4_ip_opts &=
+ cpu_to_le16(~IPOPT_VLAN_TAGGING_ENABLE);
+ break;
+ case ISCSI_NET_PARAM_MTU:
+ init_fw_cb->eth_mtu_size =
+ cpu_to_le16(*(uint16_t *)iface_param->value);
+ break;
+ case ISCSI_NET_PARAM_PORT:
+ init_fw_cb->ipv4_port =
+ cpu_to_le16(*(uint16_t *)iface_param->value);
+ break;
+ default:
+ ql4_printk(KERN_ERR, ha, "Unknown IPv4 param = %d\n",
+ iface_param->param);
+ break;
+ }
}
-static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
+static void
+qla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb)
+{
+ struct addr_ctrl_blk_def *acb;
+ acb = (struct addr_ctrl_blk_def *)init_fw_cb;
+ memset(acb->reserved1, 0, sizeof(acb->reserved1));
+ memset(acb->reserved2, 0, sizeof(acb->reserved2));
+ memset(acb->reserved3, 0, sizeof(acb->reserved3));
+ memset(acb->reserved4, 0, sizeof(acb->reserved4));
+ memset(acb->reserved5, 0, sizeof(acb->reserved5));
+ memset(acb->reserved6, 0, sizeof(acb->reserved6));
+ memset(acb->reserved7, 0, sizeof(acb->reserved7));
+ memset(acb->reserved8, 0, sizeof(acb->reserved8));
+ memset(acb->reserved9, 0, sizeof(acb->reserved9));
+ memset(acb->reserved10, 0, sizeof(acb->reserved10));
+ memset(acb->reserved11, 0, sizeof(acb->reserved11));
+ memset(acb->reserved12, 0, sizeof(acb->reserved12));
+ memset(acb->reserved13, 0, sizeof(acb->reserved13));
+ memset(acb->reserved14, 0, sizeof(acb->reserved14));
+ memset(acb->reserved15, 0, sizeof(acb->reserved15));
+}
+
+static int
+qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)
+{
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ int rval = 0;
+ struct iscsi_iface_param_info *iface_param = NULL;
+ struct addr_ctrl_blk *init_fw_cb = NULL;
+ dma_addr_t init_fw_cb_dma;
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ uint32_t rem = len;
+ struct nlattr *attr;
+
+ init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct addr_ctrl_blk),
+ &init_fw_cb_dma, GFP_KERNEL);
+ if (!init_fw_cb) {
+ ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)) {
+ ql4_printk(KERN_ERR, ha, "%s: get ifcb failed\n", __func__);
+ rval = -EIO;
+ goto exit_init_fw_cb;
+ }
+
+ nla_for_each_attr(attr, data, len, rem) {
+ iface_param = nla_data(attr);
+
+ if (iface_param->param_type != ISCSI_NET_PARAM)
+ continue;
+
+ switch (iface_param->iface_type) {
+ case ISCSI_IFACE_TYPE_IPV4:
+ switch (iface_param->iface_num) {
+ case 0:
+ qla4xxx_set_ipv4(ha, iface_param, init_fw_cb);
+ break;
+ default:
+ /* Cannot have more than one IPv4 interface */
+ ql4_printk(KERN_ERR, ha, "Invalid IPv4 iface "
+ "number = %d\n",
+ iface_param->iface_num);
+ break;
+ }
+ break;
+ case ISCSI_IFACE_TYPE_IPV6:
+ switch (iface_param->iface_num) {
+ case 0:
+ case 1:
+ qla4xxx_set_ipv6(ha, iface_param, init_fw_cb);
+ break;
+ default:
+ /* Cannot have more than two IPv6 interface */
+ ql4_printk(KERN_ERR, ha, "Invalid IPv6 iface "
+ "number = %d\n",
+ iface_param->iface_num);
+ break;
+ }
+ break;
+ default:
+ ql4_printk(KERN_ERR, ha, "Invalid iface type\n");
+ break;
+ }
+ }
+
+ init_fw_cb->cookie = cpu_to_le32(0x11BEAD5A);
+
+ rval = qla4xxx_set_flash(ha, init_fw_cb_dma, FLASH_SEGMENT_IFCB,
+ sizeof(struct addr_ctrl_blk),
+ FLASH_OPT_RMW_COMMIT);
+ if (rval != QLA_SUCCESS) {
+ ql4_printk(KERN_ERR, ha, "%s: set flash mbx failed\n",
+ __func__);
+ rval = -EIO;
+ goto exit_init_fw_cb;
+ }
+
+ qla4xxx_disable_acb(ha);
+
+ qla4xxx_initcb_to_acb(init_fw_cb);
+
+ rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma);
+ if (rval != QLA_SUCCESS) {
+ ql4_printk(KERN_ERR, ha, "%s: set acb mbx failed\n",
+ __func__);
+ rval = -EIO;
+ goto exit_init_fw_cb;
+ }
+
+ memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));
+ qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb,
+ init_fw_cb_dma);
+
+exit_init_fw_cb:
+ dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),
+ init_fw_cb, init_fw_cb_dma);
+
+ return rval;
+}
+
+static int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn,
enum iscsi_param param, char *buf)
{
- struct iscsi_cls_session *session;
- struct ddb_entry *ddb_entry;
- int len;
+ struct iscsi_conn *conn;
+ struct qla_conn *qla_conn;
+ struct sockaddr *dst_addr;
+ int len = 0;
- session = iscsi_dev_to_session(conn->dev.parent);
- ddb_entry = session->dd_data;
+ conn = cls_conn->dd_data;
+ qla_conn = conn->dd_data;
+ dst_addr = &qla_conn->qla_ep->dst_addr;
switch (param) {
case ISCSI_PARAM_CONN_PORT:
- len = sprintf(buf, "%hu\n", ddb_entry->port);
- break;
case ISCSI_PARAM_CONN_ADDRESS:
- /* TODO: what are the ipv6 bits */
- len = sprintf(buf, "%pI4\n", &ddb_entry->ip_addr);
- break;
+ return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+ dst_addr, param, buf);
default:
- return -ENOSYS;
+ return iscsi_conn_get_param(cls_conn, param, buf);
}
return len;
+
}
-static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost,
- enum iscsi_tgt_dscvr type, uint32_t enable,
- struct sockaddr *dst_addr)
+static struct iscsi_cls_session *
+qla4xxx_session_create(struct iscsi_endpoint *ep,
+ uint16_t cmds_max, uint16_t qdepth,
+ uint32_t initial_cmdsn)
{
+ struct iscsi_cls_session *cls_sess;
struct scsi_qla_host *ha;
- struct sockaddr_in *addr;
- struct sockaddr_in6 *addr6;
+ struct qla_endpoint *qla_ep;
+ struct ddb_entry *ddb_entry;
+ uint32_t ddb_index;
+ uint32_t mbx_sts = 0;
+ struct iscsi_session *sess;
+ struct sockaddr *dst_addr;
+ int ret;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ if (!ep) {
+ printk(KERN_ERR "qla4xxx: missing ep.\n");
+ return NULL;
+ }
+
+ qla_ep = ep->dd_data;
+ dst_addr = (struct sockaddr *)&qla_ep->dst_addr;
+ ha = to_qla_host(qla_ep->host);
+
+get_ddb_index:
+ ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES);
+
+ if (ddb_index >= MAX_DDB_ENTRIES) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Free DDB index not available\n"));
+ return NULL;
+ }
+
+ if (test_and_set_bit(ddb_index, ha->ddb_idx_map))
+ goto get_ddb_index;
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Found a free DDB index at %d\n", ddb_index));
+ ret = qla4xxx_req_ddb_entry(ha, ddb_index, &mbx_sts);
+ if (ret == QLA_ERROR) {
+ if (mbx_sts == MBOX_STS_COMMAND_ERROR) {
+ ql4_printk(KERN_INFO, ha,
+ "DDB index = %d not available trying next\n",
+ ddb_index);
+ goto get_ddb_index;
+ }
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Free FW DDB not available\n"));
+ return NULL;
+ }
+
+ cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, qla_ep->host,
+ cmds_max, sizeof(struct ddb_entry),
+ sizeof(struct ql4_task_data),
+ initial_cmdsn, ddb_index);
+ if (!cls_sess)
+ return NULL;
+
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ddb_entry->fw_ddb_index = ddb_index;
+ ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
+ ddb_entry->ha = ha;
+ ddb_entry->sess = cls_sess;
+ cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
+ ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry;
+ ha->tot_ddbs++;
+
+ return cls_sess;
+}
+
+static void qla4xxx_session_destroy(struct iscsi_cls_session *cls_sess)
+{
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+ unsigned long flags;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+
+ qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ qla4xxx_free_ddb(ha, ddb_entry);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ iscsi_session_teardown(cls_sess);
+}
+
+static struct iscsi_cls_conn *
+qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx)
+{
+ struct iscsi_cls_conn *cls_conn;
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn),
+ conn_idx);
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ddb_entry->conn = cls_conn;
+
+ return cls_conn;
+}
+
+static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
+ struct iscsi_cls_conn *cls_conn,
+ uint64_t transport_fd, int is_leading)
+{
+ struct iscsi_conn *conn;
+ struct qla_conn *qla_conn;
+ struct iscsi_endpoint *ep;
+
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+
+ if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
+ return -EINVAL;
+ ep = iscsi_lookup_endpoint(transport_fd);
+ conn = cls_conn->dd_data;
+ qla_conn = conn->dd_data;
+ qla_conn->qla_ep = ep->dd_data;
+ return 0;
+}
+
+static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn)
+{
+ struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+ struct dev_db_entry *fw_ddb_entry;
+ dma_addr_t fw_ddb_entry_dma;
+ uint32_t mbx_sts = 0;
int ret = 0;
+ int status = QLA_SUCCESS;
- ha = (struct scsi_qla_host *) shost->hostdata;
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
- switch (type) {
- case ISCSI_TGT_DSCVR_SEND_TARGETS:
- if (dst_addr->sa_family == AF_INET) {
- addr = (struct sockaddr_in *)dst_addr;
- if (qla4xxx_send_tgts(ha, (char *)&addr->sin_addr,
- addr->sin_port) != QLA_SUCCESS)
- ret = -EIO;
- } else if (dst_addr->sa_family == AF_INET6) {
- /*
- * TODO: fix qla4xxx_send_tgts
- */
- addr6 = (struct sockaddr_in6 *)dst_addr;
- if (qla4xxx_send_tgts(ha, (char *)&addr6->sin6_addr,
- addr6->sin6_port) != QLA_SUCCESS)
- ret = -EIO;
- } else
- ret = -ENOSYS;
- break;
- default:
- ret = -ENOSYS;
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = qla4xxx_set_param_ddbentry(ha, ddb_entry, cls_conn, &mbx_sts);
+ if (ret) {
+ /* If iscsid is stopped and started then no need to do
+ * set param again since ddb state will be already
+ * active and FW does not allow set ddb to an
+ * active session.
+ */
+ if (mbx_sts)
+ if (ddb_entry->fw_ddb_device_state ==
+ DDB_DS_SESSION_ACTIVE) {
+ iscsi_conn_start(ddb_entry->conn);
+ iscsi_conn_login_event(ddb_entry->conn,
+ ISCSI_CONN_STATE_LOGGED_IN);
+ goto exit_set_param;
+ }
+
+ ql4_printk(KERN_ERR, ha, "%s: Failed set param for index[%d]\n",
+ __func__, ddb_entry->fw_ddb_index);
+ goto exit_conn_start;
+ }
+
+ status = qla4xxx_conn_open(ha, ddb_entry->fw_ddb_index);
+ if (status == QLA_ERROR) {
+ ql4_printk(KERN_ERR, ha, "%s: Login failed: %s\n", __func__,
+ sess->targetname);
+ ret = -EINVAL;
+ goto exit_conn_start;
}
+
+ if (ddb_entry->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE)
+ ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;
+
+ DEBUG2(printk(KERN_INFO "%s: DDB state [%d]\n", __func__,
+ ddb_entry->fw_ddb_device_state));
+
+exit_set_param:
+ ret = 0;
+
+exit_conn_start:
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
return ret;
}
-void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry)
+static void qla4xxx_conn_destroy(struct iscsi_cls_conn *cls_conn)
{
- if (!ddb_entry->sess)
- return;
+ struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);
+ struct iscsi_session *sess;
+ struct scsi_qla_host *ha;
+ struct ddb_entry *ddb_entry;
+ int options;
- if (ddb_entry->conn) {
- atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
- iscsi_remove_session(ddb_entry->sess);
+ DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+
+ options = LOGOUT_OPTION_CLOSE_SESSION;
+ if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR)
+ ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__);
+}
+
+static void qla4xxx_task_work(struct work_struct *wdata)
+{
+ struct ql4_task_data *task_data;
+ struct scsi_qla_host *ha;
+ struct passthru_status *sts;
+ struct iscsi_task *task;
+ struct iscsi_hdr *hdr;
+ uint8_t *data;
+ uint32_t data_len;
+ struct iscsi_conn *conn;
+ int hdr_len;
+ itt_t itt;
+
+ task_data = container_of(wdata, struct ql4_task_data, task_work);
+ ha = task_data->ha;
+ task = task_data->task;
+ sts = &task_data->sts;
+ hdr_len = sizeof(struct iscsi_hdr);
+
+ DEBUG3(printk(KERN_INFO "Status returned\n"));
+ DEBUG3(qla4xxx_dump_buffer(sts, 64));
+ DEBUG3(printk(KERN_INFO "Response buffer"));
+ DEBUG3(qla4xxx_dump_buffer(task_data->resp_buffer, 64));
+
+ conn = task->conn;
+
+ switch (sts->completionStatus) {
+ case PASSTHRU_STATUS_COMPLETE:
+ hdr = (struct iscsi_hdr *)task_data->resp_buffer;
+ /* Assign back the itt in hdr, until we use the PREASSIGN_TAG */
+ itt = sts->handle;
+ hdr->itt = itt;
+ data = task_data->resp_buffer + hdr_len;
+ data_len = task_data->resp_len - hdr_len;
+ iscsi_complete_pdu(conn, hdr, data, data_len);
+ break;
+ default:
+ ql4_printk(KERN_ERR, ha, "Passthru failed status = 0x%x\n",
+ sts->completionStatus);
+ break;
}
- iscsi_free_session(ddb_entry->sess);
+ return;
}
-int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
+static int qla4xxx_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
{
- int err;
+ struct ql4_task_data *task_data;
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
+ int hdr_len;
- ddb_entry->sess->recovery_tmo = ql4xsess_recovery_tmo;
+ sess = task->conn->session;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+ task_data = task->dd_data;
+ memset(task_data, 0, sizeof(struct ql4_task_data));
- err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index);
- if (err) {
- DEBUG2(printk(KERN_ERR "Could not add session.\n"));
- return err;
+ if (task->sc) {
+ ql4_printk(KERN_INFO, ha,
+ "%s: SCSI Commands not implemented\n", __func__);
+ return -EINVAL;
}
- ddb_entry->conn = iscsi_create_conn(ddb_entry->sess, 0, 0);
- if (!ddb_entry->conn) {
- iscsi_remove_session(ddb_entry->sess);
- DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
- return -ENOMEM;
+ hdr_len = sizeof(struct iscsi_hdr);
+ task_data->ha = ha;
+ task_data->task = task;
+
+ if (task->data_count) {
+ task_data->data_dma = dma_map_single(&ha->pdev->dev, task->data,
+ task->data_count,
+ PCI_DMA_TODEVICE);
}
- /* finally ready to go */
- iscsi_unblock_session(ddb_entry->sess);
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n",
+ __func__, task->conn->max_recv_dlength, hdr_len));
+
+ task_data->resp_len = task->conn->max_recv_dlength + hdr_len;
+ task_data->resp_buffer = dma_alloc_coherent(&ha->pdev->dev,
+ task_data->resp_len,
+ &task_data->resp_dma,
+ GFP_ATOMIC);
+ if (!task_data->resp_buffer)
+ goto exit_alloc_pdu;
+
+ task_data->req_len = task->data_count + hdr_len;
+ task_data->req_buffer = dma_alloc_coherent(&ha->pdev->dev,
+ task_data->req_len,
+ &task_data->req_dma,
+ GFP_ATOMIC);
+ if (!task_data->req_buffer)
+ goto exit_alloc_pdu;
+
+ task->hdr = task_data->req_buffer;
+
+ INIT_WORK(&task_data->task_work, qla4xxx_task_work);
+
return 0;
+
+exit_alloc_pdu:
+ if (task_data->resp_buffer)
+ dma_free_coherent(&ha->pdev->dev, task_data->resp_len,
+ task_data->resp_buffer, task_data->resp_dma);
+
+ if (task_data->req_buffer)
+ dma_free_coherent(&ha->pdev->dev, task_data->req_len,
+ task_data->req_buffer, task_data->req_dma);
+ return -ENOMEM;
}
-struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha)
+static void qla4xxx_task_cleanup(struct iscsi_task *task)
{
+ struct ql4_task_data *task_data;
+ struct iscsi_session *sess;
struct ddb_entry *ddb_entry;
- struct iscsi_cls_session *sess;
-
- sess = iscsi_alloc_session(ha->host, &qla4xxx_iscsi_transport,
- sizeof(struct ddb_entry));
- if (!sess)
- return NULL;
+ struct scsi_qla_host *ha;
+ int hdr_len;
+ hdr_len = sizeof(struct iscsi_hdr);
+ sess = task->conn->session;
ddb_entry = sess->dd_data;
- memset(ddb_entry, 0, sizeof(*ddb_entry));
- ddb_entry->ha = ha;
- ddb_entry->sess = sess;
- return ddb_entry;
+ ha = ddb_entry->ha;
+ task_data = task->dd_data;
+
+ if (task->data_count) {
+ dma_unmap_single(&ha->pdev->dev, task_data->data_dma,
+ task->data_count, PCI_DMA_TODEVICE);
+ }
+
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n",
+ __func__, task->conn->max_recv_dlength, hdr_len));
+
+ dma_free_coherent(&ha->pdev->dev, task_data->resp_len,
+ task_data->resp_buffer, task_data->resp_dma);
+ dma_free_coherent(&ha->pdev->dev, task_data->req_len,
+ task_data->req_buffer, task_data->req_dma);
+ return;
}
-static void qla4xxx_scan_start(struct Scsi_Host *shost)
+static int qla4xxx_task_xmit(struct iscsi_task *task)
{
- struct scsi_qla_host *ha = shost_priv(shost);
- struct ddb_entry *ddb_entry, *ddbtemp;
+ struct scsi_cmnd *sc = task->sc;
+ struct iscsi_session *sess = task->conn->session;
+ struct ddb_entry *ddb_entry = sess->dd_data;
+ struct scsi_qla_host *ha = ddb_entry->ha;
+
+ if (!sc)
+ return qla4xxx_send_passthru0(task);
- /* finish setup of sessions that were already setup in firmware */
- list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
- if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE)
- qla4xxx_add_sess(ddb_entry);
+ ql4_printk(KERN_INFO, ha, "%s: scsi cmd xmit not implemented\n",
+ __func__);
+ return -ENOSYS;
+}
+
+void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
+ struct ddb_entry *ddb_entry)
+{
+ struct iscsi_cls_session *cls_sess;
+ struct iscsi_cls_conn *cls_conn;
+ struct iscsi_session *sess;
+ struct iscsi_conn *conn;
+ uint32_t ddb_state;
+ dma_addr_t fw_ddb_entry_dma;
+ struct dev_db_entry *fw_ddb_entry;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n", __func__);
+ return;
}
+
+ if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry,
+ fw_ddb_entry_dma, NULL, NULL, &ddb_state,
+ NULL, NULL, NULL) == QLA_ERROR) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "
+ "get_ddb_entry for fw_ddb_index %d\n",
+ ha->host_no, __func__,
+ ddb_entry->fw_ddb_index));
+ return;
+ }
+
+ cls_sess = ddb_entry->sess;
+ sess = cls_sess->dd_data;
+
+ cls_conn = ddb_entry->conn;
+ conn = cls_conn->dd_data;
+
+ /* Update params */
+ conn->max_recv_dlength = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);
+
+ conn->max_xmit_dlength = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len);
+
+ sess->initial_r2t_en =
+ (BIT_10 & le16_to_cpu(fw_ddb_entry->iscsi_options));
+
+ sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t);
+
+ sess->imm_data_en = (BIT_11 & le16_to_cpu(fw_ddb_entry->iscsi_options));
+
+ sess->first_burst = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len);
+
+ sess->max_burst = BYTE_UNITS *
+ le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len);
+
+ sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
+
+ sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain);
+
+ sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
+
+ memcpy(sess->initiatorname, ha->name_string,
+ min(sizeof(ha->name_string), sizeof(sess->initiatorname)));
}
/*
@@ -376,25 +1433,15 @@ static void qla4xxx_stop_timer(struct scsi_qla_host *ha)
}
/***
- * qla4xxx_mark_device_missing - mark a device as missing.
- * @ha: Pointer to host adapter structure.
+ * qla4xxx_mark_device_missing - blocks the session
+ * @cls_session: Pointer to the session to be blocked
* @ddb_entry: Pointer to device database entry
*
* This routine marks a device missing and close connection.
**/
-void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
- struct ddb_entry *ddb_entry)
+void qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session)
{
- if ((atomic_read(&ddb_entry->state) != DDB_STATE_DEAD)) {
- atomic_set(&ddb_entry->state, DDB_STATE_MISSING);
- DEBUG2(printk("scsi%ld: ddb [%d] marked MISSING\n",
- ha->host_no, ddb_entry->fw_ddb_index));
- } else
- DEBUG2(printk("scsi%ld: ddb [%d] DEAD\n", ha->host_no,
- ddb_entry->fw_ddb_index))
-
- iscsi_block_session(ddb_entry->sess);
- iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
+ iscsi_block_session(cls_session);
}
/**
@@ -405,10 +1452,7 @@ void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
**/
void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha)
{
- struct ddb_entry *ddb_entry, *ddbtemp;
- list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
- qla4xxx_mark_device_missing(ha, ddb_entry);
- }
+ iscsi_host_for_each_session(ha->host, qla4xxx_mark_device_missing);
}
static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,
@@ -495,20 +1539,13 @@ static int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
goto qc_fail_command;
}
- if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
- if (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) {
- cmd->result = DID_NO_CONNECT << 16;
- goto qc_fail_command;
- }
- return SCSI_MLQUEUE_TARGET_BUSY;
- }
-
if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) ||
test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||
!test_bit(AF_ONLINE, &ha->flags) ||
+ !test_bit(AF_LINK_UP, &ha->flags) ||
test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))
goto qc_host_busy;
@@ -563,6 +1600,13 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha)
ha->srb_mempool = NULL;
+ if (ha->chap_dma_pool)
+ dma_pool_destroy(ha->chap_dma_pool);
+
+ if (ha->chap_list)
+ vfree(ha->chap_list);
+ ha->chap_list = NULL;
+
/* release io space registers */
if (is_qla8022(ha)) {
if (ha->nx_pcibase)
@@ -636,6 +1680,15 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
goto mem_alloc_error_exit;
}
+ ha->chap_dma_pool = dma_pool_create("ql4_chap", &ha->pdev->dev,
+ CHAP_DMA_BLOCK_SIZE, 8, 0);
+
+ if (ha->chap_dma_pool == NULL) {
+ ql4_printk(KERN_WARNING, ha,
+ "%s: chap_dma_pool allocation failed..\n", __func__);
+ goto mem_alloc_error_exit;
+ }
+
return QLA_SUCCESS;
mem_alloc_error_exit:
@@ -753,7 +1806,6 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
**/
static void qla4xxx_timer(struct scsi_qla_host *ha)
{
- struct ddb_entry *ddb_entry, *dtemp;
int start_dpc = 0;
uint16_t w;
@@ -773,69 +1825,6 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
qla4_8xxx_watchdog(ha);
}
- /* Search for relogin's to time-out and port down retry. */
- list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) {
- /* Count down time between sending relogins */
- if (adapter_up(ha) &&
- !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
- atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
- if (atomic_read(&ddb_entry->retry_relogin_timer) !=
- INVALID_ENTRY) {
- if (atomic_read(&ddb_entry->retry_relogin_timer)
- == 0) {
- atomic_set(&ddb_entry->
- retry_relogin_timer,
- INVALID_ENTRY);
- set_bit(DPC_RELOGIN_DEVICE,
- &ha->dpc_flags);
- set_bit(DF_RELOGIN, &ddb_entry->flags);
- DEBUG2(printk("scsi%ld: %s: ddb [%d]"
- " login device\n",
- ha->host_no, __func__,
- ddb_entry->fw_ddb_index));
- } else
- atomic_dec(&ddb_entry->
- retry_relogin_timer);
- }
- }
-
- /* Wait for relogin to timeout */
- if (atomic_read(&ddb_entry->relogin_timer) &&
- (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) {
- /*
- * If the relogin times out and the device is
- * still NOT ONLINE then try and relogin again.
- */
- if (atomic_read(&ddb_entry->state) !=
- DDB_STATE_ONLINE &&
- ddb_entry->fw_ddb_device_state ==
- DDB_DS_SESSION_FAILED) {
- /* Reset retry relogin timer */
- atomic_inc(&ddb_entry->relogin_retry_count);
- DEBUG2(printk("scsi%ld: ddb [%d] relogin"
- " timed out-retrying"
- " relogin (%d)\n",
- ha->host_no,
- ddb_entry->fw_ddb_index,
- atomic_read(&ddb_entry->
- relogin_retry_count))
- );
- start_dpc++;
- DEBUG(printk("scsi%ld:%d:%d: ddb [%d] "
- "initiate relogin after"
- " %d seconds\n",
- ha->host_no, ddb_entry->bus,
- ddb_entry->target,
- ddb_entry->fw_ddb_index,
- ddb_entry->default_time2wait + 4)
- );
-
- atomic_set(&ddb_entry->retry_relogin_timer,
- ddb_entry->default_time2wait + 4);
- }
- }
- }
-
if (!is_qla8022(ha)) {
/* Check for heartbeat interval. */
if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE &&
@@ -1081,6 +2070,17 @@ void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha)
clear_bit(AF_INIT_DONE, &ha->flags);
}
+static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session)
+{
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+
+ sess = cls_session->dd_data;
+ ddb_entry = sess->dd_data;
+ ddb_entry->fw_ddb_device_state = DDB_DS_SESSION_FAILED;
+ iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
+}
+
/**
* qla4xxx_recover_adapter - recovers adapter after a fatal error
* @ha: Pointer to host adapter structure.
@@ -1093,11 +2093,14 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
/* Stall incoming I/O until we are done */
scsi_block_requests(ha->host);
clear_bit(AF_ONLINE, &ha->flags);
+ clear_bit(AF_LINK_UP, &ha->flags);
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__));
set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
+ iscsi_host_for_each_session(ha->host, qla4xxx_fail_session);
+
if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
reset_chip = 1;
@@ -1160,7 +2163,7 @@ recover_ha_init_adapter:
/* NOTE: AF_ONLINE flag set upon successful completion of
* qla4xxx_initialize_adapter */
- status = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST);
+ status = qla4xxx_initialize_adapter(ha);
}
/* Retry failed adapter initialization, if necessary
@@ -1225,27 +2228,34 @@ recover_ha_init_adapter:
return status;
}
-static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha)
+static void qla4xxx_relogin_devices(struct iscsi_cls_session *cls_session)
{
- struct ddb_entry *ddb_entry, *dtemp;
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb_entry;
+ struct scsi_qla_host *ha;
- list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) {
- if ((atomic_read(&ddb_entry->state) == DDB_STATE_MISSING) ||
- (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD)) {
- if (ddb_entry->fw_ddb_device_state ==
- DDB_DS_SESSION_ACTIVE) {
- atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
- ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
- " marked ONLINE\n", ha->host_no, __func__,
- ddb_entry->fw_ddb_index);
-
- iscsi_unblock_session(ddb_entry->sess);
- } else
- qla4xxx_relogin_device(ha, ddb_entry);
+ sess = cls_session->dd_data;
+ ddb_entry = sess->dd_data;
+ ha = ddb_entry->ha;
+ if (!iscsi_is_session_online(cls_session)) {
+ if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
+ ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
+ " unblock session\n", ha->host_no, __func__,
+ ddb_entry->fw_ddb_index);
+ iscsi_unblock_session(ddb_entry->sess);
+ } else {
+ /* Trigger relogin */
+ iscsi_session_failure(cls_session->dd_data,
+ ISCSI_ERR_CONN_FAILED);
}
}
}
+static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha)
+{
+ iscsi_host_for_each_session(ha->host, qla4xxx_relogin_devices);
+}
+
void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
{
if (ha->dpc_thread)
@@ -1267,7 +2277,6 @@ static void qla4xxx_do_dpc(struct work_struct *work)
{
struct scsi_qla_host *ha =
container_of(work, struct scsi_qla_host, dpc_work);
- struct ddb_entry *ddb_entry, *dtemp;
int status = QLA_ERROR;
DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
@@ -1363,31 +2372,6 @@ dpc_post_reset_ha:
qla4xxx_relogin_all_devices(ha);
}
}
-
- /* ---- relogin device? --- */
- if (adapter_up(ha) &&
- test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {
- list_for_each_entry_safe(ddb_entry, dtemp,
- &ha->ddb_list, list) {
- if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) &&
- atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
- qla4xxx_relogin_device(ha, ddb_entry);
-
- /*
- * If mbx cmd times out there is no point
- * in continuing further.
- * With large no of targets this can hang
- * the system.
- */
- if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
- printk(KERN_WARNING "scsi%ld: %s: "
- "need to reset hba\n",
- ha->host_no, __func__);
- break;
- }
- }
- }
-
}
/**
@@ -1410,6 +2394,10 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
if (ha->dpc_thread)
destroy_workqueue(ha->dpc_thread);
+ /* Kill the kernel thread for this host */
+ if (ha->task_wq)
+ destroy_workqueue(ha->task_wq);
+
/* Put firmware in known state */
ha->isp_ops->reset_firmware(ha);
@@ -1601,6 +2589,594 @@ uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in));
}
+static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf)
+{
+ struct scsi_qla_host *ha = data;
+ char *str = buf;
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_ETH_FLAGS:
+ rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT);
+ break;
+ case ISCSI_BOOT_ETH_INDEX:
+ rc = sprintf(str, "0\n");
+ break;
+ case ISCSI_BOOT_ETH_MAC:
+ rc = sysfs_format_mac(str, ha->my_mac,
+ MAC_ADDR_LEN);
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ return rc;
+}
+
+static mode_t qla4xxx_eth_get_attr_visibility(void *data, int type)
+{
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_ETH_FLAGS:
+ case ISCSI_BOOT_ETH_MAC:
+ case ISCSI_BOOT_ETH_INDEX:
+ rc = S_IRUGO;
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+static ssize_t qla4xxx_show_boot_ini_info(void *data, int type, char *buf)
+{
+ struct scsi_qla_host *ha = data;
+ char *str = buf;
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_INI_INITIATOR_NAME:
+ rc = sprintf(str, "%s\n", ha->name_string);
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ return rc;
+}
+
+static mode_t qla4xxx_ini_get_attr_visibility(void *data, int type)
+{
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_INI_INITIATOR_NAME:
+ rc = S_IRUGO;
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+static ssize_t
+qla4xxx_show_boot_tgt_info(struct ql4_boot_session_info *boot_sess, int type,
+ char *buf)
+{
+ struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0];
+ char *str = buf;
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_TGT_NAME:
+ rc = sprintf(buf, "%s\n", (char *)&boot_sess->target_name);
+ break;
+ case ISCSI_BOOT_TGT_IP_ADDR:
+ if (boot_sess->conn_list[0].dest_ipaddr.ip_type == 0x1)
+ rc = sprintf(buf, "%pI4\n",
+ &boot_conn->dest_ipaddr.ip_address);
+ else
+ rc = sprintf(str, "%pI6\n",
+ &boot_conn->dest_ipaddr.ip_address);
+ break;
+ case ISCSI_BOOT_TGT_PORT:
+ rc = sprintf(str, "%d\n", boot_conn->dest_port);
+ break;
+ case ISCSI_BOOT_TGT_CHAP_NAME:
+ rc = sprintf(str, "%.*s\n",
+ boot_conn->chap.target_chap_name_length,
+ (char *)&boot_conn->chap.target_chap_name);
+ break;
+ case ISCSI_BOOT_TGT_CHAP_SECRET:
+ rc = sprintf(str, "%.*s\n",
+ boot_conn->chap.target_secret_length,
+ (char *)&boot_conn->chap.target_secret);
+ break;
+ case ISCSI_BOOT_TGT_REV_CHAP_NAME:
+ rc = sprintf(str, "%.*s\n",
+ boot_conn->chap.intr_chap_name_length,
+ (char *)&boot_conn->chap.intr_chap_name);
+ break;
+ case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
+ rc = sprintf(str, "%.*s\n",
+ boot_conn->chap.intr_secret_length,
+ (char *)&boot_conn->chap.intr_secret);
+ break;
+ case ISCSI_BOOT_TGT_FLAGS:
+ rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT);
+ break;
+ case ISCSI_BOOT_TGT_NIC_ASSOC:
+ rc = sprintf(str, "0\n");
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ return rc;
+}
+
+static ssize_t qla4xxx_show_boot_tgt_pri_info(void *data, int type, char *buf)
+{
+ struct scsi_qla_host *ha = data;
+ struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_pri_sess);
+
+ return qla4xxx_show_boot_tgt_info(boot_sess, type, buf);
+}
+
+static ssize_t qla4xxx_show_boot_tgt_sec_info(void *data, int type, char *buf)
+{
+ struct scsi_qla_host *ha = data;
+ struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_sec_sess);
+
+ return qla4xxx_show_boot_tgt_info(boot_sess, type, buf);
+}
+
+static mode_t qla4xxx_tgt_get_attr_visibility(void *data, int type)
+{
+ int rc;
+
+ switch (type) {
+ case ISCSI_BOOT_TGT_NAME:
+ case ISCSI_BOOT_TGT_IP_ADDR:
+ case ISCSI_BOOT_TGT_PORT:
+ case ISCSI_BOOT_TGT_CHAP_NAME:
+ case ISCSI_BOOT_TGT_CHAP_SECRET:
+ case ISCSI_BOOT_TGT_REV_CHAP_NAME:
+ case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
+ case ISCSI_BOOT_TGT_NIC_ASSOC:
+ case ISCSI_BOOT_TGT_FLAGS:
+ rc = S_IRUGO;
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+static void qla4xxx_boot_release(void *data)
+{
+ struct scsi_qla_host *ha = data;
+
+ scsi_host_put(ha->host);
+}
+
+static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
+{
+ dma_addr_t buf_dma;
+ uint32_t addr, pri_addr, sec_addr;
+ uint32_t offset;
+ uint16_t func_num;
+ uint8_t val;
+ uint8_t *buf = NULL;
+ size_t size = 13 * sizeof(uint8_t);
+ int ret = QLA_SUCCESS;
+
+ func_num = PCI_FUNC(ha->pdev->devfn);
+
+ ql4_printk(KERN_INFO, ha, "%s: Get FW boot info for 0x%x func %d\n",
+ __func__, ha->pdev->device, func_num);
+
+ if (is_qla40XX(ha)) {
+ if (func_num == 1) {
+ addr = NVRAM_PORT0_BOOT_MODE;
+ pri_addr = NVRAM_PORT0_BOOT_PRI_TGT;
+ sec_addr = NVRAM_PORT0_BOOT_SEC_TGT;
+ } else if (func_num == 3) {
+ addr = NVRAM_PORT1_BOOT_MODE;
+ pri_addr = NVRAM_PORT1_BOOT_PRI_TGT;
+ sec_addr = NVRAM_PORT1_BOOT_SEC_TGT;
+ } else {
+ ret = QLA_ERROR;
+ goto exit_boot_info;
+ }
+
+ /* Check Boot Mode */
+ val = rd_nvram_byte(ha, addr);
+ if (!(val & 0x07)) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Failed Boot options : 0x%x\n",
+ __func__, val));
+ ret = QLA_ERROR;
+ goto exit_boot_info;
+ }
+
+ /* get primary valid target index */
+ val = rd_nvram_byte(ha, pri_addr);
+ if (val & BIT_7)
+ ddb_index[0] = (val & 0x7f);
+
+ /* get secondary valid target index */
+ val = rd_nvram_byte(ha, sec_addr);
+ if (val & BIT_7)
+ ddb_index[1] = (val & 0x7f);
+
+ } else if (is_qla8022(ha)) {
+ buf = dma_alloc_coherent(&ha->pdev->dev, size,
+ &buf_dma, GFP_KERNEL);
+ if (!buf) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer\n",
+ __func__));
+ ret = QLA_ERROR;
+ goto exit_boot_info;
+ }
+
+ if (ha->port_num == 0)
+ offset = BOOT_PARAM_OFFSET_PORT0;
+ else if (ha->port_num == 1)
+ offset = BOOT_PARAM_OFFSET_PORT1;
+ else {
+ ret = QLA_ERROR;
+ goto exit_boot_info_free;
+ }
+ addr = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_iscsi_param * 4) +
+ offset;
+ if (qla4xxx_get_flash(ha, buf_dma, addr,
+ 13 * sizeof(uint8_t)) != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
+ "failed\n", ha->host_no, __func__));
+ ret = QLA_ERROR;
+ goto exit_boot_info_free;
+ }
+ /* Check Boot Mode */
+ if (!(buf[1] & 0x07)) {
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Failed: Boot options : 0x%x\n",
+ buf[1]));
+ ret = QLA_ERROR;
+ goto exit_boot_info_free;
+ }
+
+ /* get primary valid target index */
+ if (buf[2] & BIT_7)
+ ddb_index[0] = buf[2] & 0x7f;
+
+ /* get secondary valid target index */
+ if (buf[11] & BIT_7)
+ ddb_index[1] = buf[11] & 0x7f;
+ } else {
+ ret = QLA_ERROR;
+ goto exit_boot_info;
+ }
+
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Primary target ID %d, Secondary"
+ " target ID %d\n", __func__, ddb_index[0],
+ ddb_index[1]));
+
+exit_boot_info_free:
+ dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma);
+exit_boot_info:
+ return ret;
+}
+
+/**
+ * qla4xxx_get_bidi_chap - Get a BIDI CHAP user and password
+ * @ha: pointer to adapter structure
+ * @username: CHAP username to be returned
+ * @password: CHAP password to be returned
+ *
+ * If a boot entry has BIDI CHAP enabled then we need to set the BIDI CHAP
+ * user and password in the sysfs entry in /sys/firmware/iscsi_boot#/.
+ * So from the CHAP cache find the first BIDI CHAP entry and set it
+ * to the boot record in sysfs.
+ **/
+static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username,
+ char *password)
+{
+ int i, ret = -EINVAL;
+ int max_chap_entries = 0;
+ struct ql4_chap_table *chap_table;
+
+ if (is_qla8022(ha))
+ max_chap_entries = (ha->hw.flt_chap_size / 2) /
+ sizeof(struct ql4_chap_table);
+ else
+ max_chap_entries = MAX_CHAP_ENTRIES_40XX;
+
+ if (!ha->chap_list) {
+ ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
+ return ret;
+ }
+
+ mutex_lock(&ha->chap_sem);
+ for (i = 0; i < max_chap_entries; i++) {
+ chap_table = (struct ql4_chap_table *)ha->chap_list + i;
+ if (chap_table->cookie !=
+ __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ continue;
+ }
+
+ if (chap_table->flags & BIT_7) /* local */
+ continue;
+
+ if (!(chap_table->flags & BIT_6)) /* Not BIDI */
+ continue;
+
+ strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
+ strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
+ ret = 0;
+ break;
+ }
+ mutex_unlock(&ha->chap_sem);
+
+ return ret;
+}
+
+
+static int qla4xxx_get_boot_target(struct scsi_qla_host *ha,
+ struct ql4_boot_session_info *boot_sess,
+ uint16_t ddb_index)
+{
+ struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0];
+ struct dev_db_entry *fw_ddb_entry;
+ dma_addr_t fw_ddb_entry_dma;
+ uint16_t idx;
+ uint16_t options;
+ int ret = QLA_SUCCESS;
+
+ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ &fw_ddb_entry_dma, GFP_KERNEL);
+ if (!fw_ddb_entry) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Unable to allocate dma buffer.\n",
+ __func__));
+ ret = QLA_ERROR;
+ return ret;
+ }
+
+ if (qla4xxx_bootdb_by_index(ha, fw_ddb_entry,
+ fw_ddb_entry_dma, ddb_index)) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Flash DDB read Failed\n", __func__));
+ ret = QLA_ERROR;
+ goto exit_boot_target;
+ }
+
+ /* Update target name and IP from DDB */
+ memcpy(boot_sess->target_name, fw_ddb_entry->iscsi_name,
+ min(sizeof(boot_sess->target_name),
+ sizeof(fw_ddb_entry->iscsi_name)));
+
+ options = le16_to_cpu(fw_ddb_entry->options);
+ if (options & DDB_OPT_IPV6_DEVICE) {
+ memcpy(&boot_conn->dest_ipaddr.ip_address,
+ &fw_ddb_entry->ip_addr[0], IPv6_ADDR_LEN);
+ } else {
+ boot_conn->dest_ipaddr.ip_type = 0x1;
+ memcpy(&boot_conn->dest_ipaddr.ip_address,
+ &fw_ddb_entry->ip_addr[0], IP_ADDR_LEN);
+ }
+
+ boot_conn->dest_port = le16_to_cpu(fw_ddb_entry->port);
+
+ /* update chap information */
+ idx = __le16_to_cpu(fw_ddb_entry->chap_tbl_idx);
+
+ if (BIT_7 & le16_to_cpu(fw_ddb_entry->iscsi_options)) {
+
+ DEBUG2(ql4_printk(KERN_INFO, ha, "Setting chap\n"));
+
+ ret = qla4xxx_get_chap(ha, (char *)&boot_conn->chap.
+ target_chap_name,
+ (char *)&boot_conn->chap.target_secret,
+ idx);
+ if (ret) {
+ ql4_printk(KERN_ERR, ha, "Failed to set chap\n");
+ ret = QLA_ERROR;
+ goto exit_boot_target;
+ }
+
+ boot_conn->chap.target_chap_name_length = QL4_CHAP_MAX_NAME_LEN;
+ boot_conn->chap.target_secret_length = QL4_CHAP_MAX_SECRET_LEN;
+ }
+
+ if (BIT_4 & le16_to_cpu(fw_ddb_entry->iscsi_options)) {
+
+ DEBUG2(ql4_printk(KERN_INFO, ha, "Setting BIDI chap\n"));
+
+ ret = qla4xxx_get_bidi_chap(ha,
+ (char *)&boot_conn->chap.intr_chap_name,
+ (char *)&boot_conn->chap.intr_secret);
+
+ if (ret) {
+ ql4_printk(KERN_ERR, ha, "Failed to set BIDI chap\n");
+ ret = QLA_ERROR;
+ goto exit_boot_target;
+ }
+
+ boot_conn->chap.intr_chap_name_length = QL4_CHAP_MAX_NAME_LEN;
+ boot_conn->chap.intr_secret_length = QL4_CHAP_MAX_SECRET_LEN;
+ }
+
+exit_boot_target:
+ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
+ fw_ddb_entry, fw_ddb_entry_dma);
+ return ret;
+}
+
+static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)
+{
+ uint16_t ddb_index[2];
+ int ret = QLA_ERROR;
+ int rval;
+
+ memset(ddb_index, 0, sizeof(ddb_index));
+ ddb_index[0] = 0xffff;
+ ddb_index[1] = 0xffff;
+ ret = get_fw_boot_info(ha, ddb_index);
+ if (ret != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha,
+ "%s: Failed to set boot info.\n", __func__));
+ return ret;
+ }
+
+ if (ddb_index[0] == 0xffff)
+ goto sec_target;
+
+ rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess),
+ ddb_index[0]);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get "
+ "primary target\n", __func__));
+ } else
+ ret = QLA_SUCCESS;
+
+sec_target:
+ if (ddb_index[1] == 0xffff)
+ goto exit_get_boot_info;
+
+ rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess),
+ ddb_index[1]);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get "
+ "secondary target\n", __func__));
+ } else
+ ret = QLA_SUCCESS;
+
+exit_get_boot_info:
+ return ret;
+}
+
+static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha)
+{
+ struct iscsi_boot_kobj *boot_kobj;
+
+ if (qla4xxx_get_boot_info(ha) != QLA_SUCCESS)
+ return 0;
+
+ ha->boot_kset = iscsi_boot_create_host_kset(ha->host->host_no);
+ if (!ha->boot_kset)
+ goto kset_free;
+
+ if (!scsi_host_get(ha->host))
+ goto kset_free;
+ boot_kobj = iscsi_boot_create_target(ha->boot_kset, 0, ha,
+ qla4xxx_show_boot_tgt_pri_info,
+ qla4xxx_tgt_get_attr_visibility,
+ qla4xxx_boot_release);
+ if (!boot_kobj)
+ goto put_host;
+
+ if (!scsi_host_get(ha->host))
+ goto kset_free;
+ boot_kobj = iscsi_boot_create_target(ha->boot_kset, 1, ha,
+ qla4xxx_show_boot_tgt_sec_info,
+ qla4xxx_tgt_get_attr_visibility,
+ qla4xxx_boot_release);
+ if (!boot_kobj)
+ goto put_host;
+
+ if (!scsi_host_get(ha->host))
+ goto kset_free;
+ boot_kobj = iscsi_boot_create_initiator(ha->boot_kset, 0, ha,
+ qla4xxx_show_boot_ini_info,
+ qla4xxx_ini_get_attr_visibility,
+ qla4xxx_boot_release);
+ if (!boot_kobj)
+ goto put_host;
+
+ if (!scsi_host_get(ha->host))
+ goto kset_free;
+ boot_kobj = iscsi_boot_create_ethernet(ha->boot_kset, 0, ha,
+ qla4xxx_show_boot_eth_info,
+ qla4xxx_eth_get_attr_visibility,
+ qla4xxx_boot_release);
+ if (!boot_kobj)
+ goto put_host;
+
+ return 0;
+
+put_host:
+ scsi_host_put(ha->host);
+kset_free:
+ iscsi_boot_destroy_kset(ha->boot_kset);
+ return -ENOMEM;
+}
+
+
+/**
+ * qla4xxx_create chap_list - Create CHAP list from FLASH
+ * @ha: pointer to adapter structure
+ *
+ * Read flash and make a list of CHAP entries, during login when a CHAP entry
+ * is received, it will be checked in this list. If entry exist then the CHAP
+ * entry index is set in the DDB. If CHAP entry does not exist in this list
+ * then a new entry is added in FLASH in CHAP table and the index obtained is
+ * used in the DDB.
+ **/
+static void qla4xxx_create_chap_list(struct scsi_qla_host *ha)
+{
+ int rval = 0;
+ uint8_t *chap_flash_data = NULL;
+ uint32_t offset;
+ dma_addr_t chap_dma;
+ uint32_t chap_size = 0;
+
+ if (is_qla40XX(ha))
+ chap_size = MAX_CHAP_ENTRIES_40XX *
+ sizeof(struct ql4_chap_table);
+ else /* Single region contains CHAP info for both
+ * ports which is divided into half for each port.
+ */
+ chap_size = ha->hw.flt_chap_size / 2;
+
+ chap_flash_data = dma_alloc_coherent(&ha->pdev->dev, chap_size,
+ &chap_dma, GFP_KERNEL);
+ if (!chap_flash_data) {
+ ql4_printk(KERN_ERR, ha, "No memory for chap_flash_data\n");
+ return;
+ }
+ if (is_qla40XX(ha))
+ offset = FLASH_CHAP_OFFSET;
+ else {
+ offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
+ if (ha->port_num == 1)
+ offset += chap_size;
+ }
+
+ rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
+ if (rval != QLA_SUCCESS)
+ goto exit_chap_list;
+
+ if (ha->chap_list == NULL)
+ ha->chap_list = vmalloc(chap_size);
+ if (ha->chap_list == NULL) {
+ ql4_printk(KERN_ERR, ha, "No memory for ha->chap_list\n");
+ goto exit_chap_list;
+ }
+
+ memcpy(ha->chap_list, chap_flash_data, chap_size);
+
+exit_chap_list:
+ dma_free_coherent(&ha->pdev->dev, chap_size,
+ chap_flash_data, chap_dma);
+ return;
+}
+
/**
* qla4xxx_probe_adapter - callback function to probe HBA
* @pdev: pointer to pci_dev structure
@@ -1624,7 +3200,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
if (pci_enable_device(pdev))
return -1;
- host = scsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha));
+ host = iscsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha), 0);
if (host == NULL) {
printk(KERN_WARNING
"qla4xxx: Couldn't allocate host from scsi layer!\n");
@@ -1632,7 +3208,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
}
/* Clear our data area */
- ha = (struct scsi_qla_host *) host->hostdata;
+ ha = to_qla_host(host);
memset(ha, 0, sizeof(*ha));
/* Save the information from PCI BIOS. */
@@ -1675,11 +3251,12 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
qla4xxx_config_dma_addressing(ha);
/* Initialize lists and spinlocks. */
- INIT_LIST_HEAD(&ha->ddb_list);
INIT_LIST_HEAD(&ha->free_srb_q);
mutex_init(&ha->mbox_sem);
+ mutex_init(&ha->chap_sem);
init_completion(&ha->mbx_intr_comp);
+ init_completion(&ha->disable_acb_comp);
spin_lock_init(&ha->hardware_lock);
@@ -1692,6 +3269,27 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
goto probe_failed;
}
+ host->cmd_per_lun = 3;
+ host->max_channel = 0;
+ host->max_lun = MAX_LUNS - 1;
+ host->max_id = MAX_TARGETS;
+ host->max_cmd_len = IOCB_MAX_CDB_LEN;
+ host->can_queue = MAX_SRBS ;
+ host->transportt = qla4xxx_scsi_transport;
+
+ ret = scsi_init_shared_tag_map(host, MAX_SRBS);
+ if (ret) {
+ ql4_printk(KERN_WARNING, ha,
+ "%s: scsi_init_shared_tag_map failed\n", __func__);
+ goto probe_failed;
+ }
+
+ pci_set_drvdata(pdev, ha);
+
+ ret = scsi_add_host(host, &pdev->dev);
+ if (ret)
+ goto probe_failed;
+
if (is_qla8022(ha))
(void) qla4_8xxx_get_flash_info(ha);
@@ -1700,7 +3298,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
* firmware
* NOTE: interrupts enabled upon successful completion
*/
- status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
+ status = qla4xxx_initialize_adapter(ha);
while ((!test_bit(AF_ONLINE, &ha->flags)) &&
init_retry_count++ < MAX_INIT_RETRIES) {
@@ -1721,7 +3319,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
if (ha->isp_ops->reset_chip(ha) == QLA_ERROR)
continue;
- status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
+ status = qla4xxx_initialize_adapter(ha);
}
if (!test_bit(AF_ONLINE, &ha->flags)) {
@@ -1736,24 +3334,9 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
qla4_8xxx_idc_unlock(ha);
}
ret = -ENODEV;
- goto probe_failed;
+ goto remove_host;
}
- host->cmd_per_lun = 3;
- host->max_channel = 0;
- host->max_lun = MAX_LUNS - 1;
- host->max_id = MAX_TARGETS;
- host->max_cmd_len = IOCB_MAX_CDB_LEN;
- host->can_queue = MAX_SRBS ;
- host->transportt = qla4xxx_scsi_transport;
-
- ret = scsi_init_shared_tag_map(host, MAX_SRBS);
- if (ret) {
- ql4_printk(KERN_WARNING, ha,
- "scsi_init_shared_tag_map failed\n");
- goto probe_failed;
- }
-
/* Startup the kernel thread for this host adapter. */
DEBUG2(printk("scsi: %s: Starting kernel thread for "
"qla4xxx_dpc\n", __func__));
@@ -1762,10 +3345,18 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
if (!ha->dpc_thread) {
ql4_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n");
ret = -ENODEV;
- goto probe_failed;
+ goto remove_host;
}
INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);
+ sprintf(buf, "qla4xxx_%lu_task", ha->host_no);
+ ha->task_wq = alloc_workqueue(buf, WQ_MEM_RECLAIM, 1);
+ if (!ha->task_wq) {
+ ql4_printk(KERN_WARNING, ha, "Unable to start task thread!\n");
+ ret = -ENODEV;
+ goto remove_host;
+ }
+
/* For ISP-82XX, request_irqs is called in qla4_8xxx_load_risc
* (which is called indirectly by qla4xxx_initialize_adapter),
* so that irqs will be registered after crbinit but before
@@ -1776,7 +3367,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
if (ret) {
ql4_printk(KERN_WARNING, ha, "Failed to reserve "
"interrupt %d already in use.\n", pdev->irq);
- goto probe_failed;
+ goto remove_host;
}
}
@@ -1788,21 +3379,25 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
set_bit(AF_INIT_DONE, &ha->flags);
- pci_set_drvdata(pdev, ha);
-
- ret = scsi_add_host(host, &pdev->dev);
- if (ret)
- goto probe_failed;
-
printk(KERN_INFO
" QLogic iSCSI HBA Driver version: %s\n"
" QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n",
qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev),
ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
ha->patch_number, ha->build_number);
- scsi_scan_host(host);
+
+ qla4xxx_create_chap_list(ha);
+
+ if (qla4xxx_setup_boot_info(ha))
+ ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n",
+ __func__);
+
+ qla4xxx_create_ifaces(ha);
return 0;
+remove_host:
+ scsi_remove_host(ha->host);
+
probe_failed:
qla4xxx_free_adapter(ha);
@@ -1867,8 +3462,11 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
if (!is_qla8022(ha))
qla4xxx_prevent_other_port_reinit(ha);
- /* remove devs from iscsi_sessions to scsi_devices */
- qla4xxx_free_ddb_list(ha);
+ /* destroy iface from sysfs */
+ qla4xxx_destroy_ifaces(ha);
+
+ if (ha->boot_kset)
+ iscsi_boot_destroy_kset(ha->boot_kset);
scsi_remove_host(ha->host);
@@ -1907,10 +3505,15 @@ static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)
static int qla4xxx_slave_alloc(struct scsi_device *sdev)
{
- struct iscsi_cls_session *sess = starget_to_session(sdev->sdev_target);
- struct ddb_entry *ddb = sess->dd_data;
+ struct iscsi_cls_session *cls_sess;
+ struct iscsi_session *sess;
+ struct ddb_entry *ddb;
int queue_depth = QL4_DEF_QDEPTH;
+ cls_sess = starget_to_session(sdev->sdev_target);
+ sess = cls_sess->dd_data;
+ ddb = sess->dd_data;
+
sdev->hostdata = ddb;
sdev->tagged_supported = 1;
@@ -2248,7 +3851,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
int return_status = FAILED;
struct scsi_qla_host *ha;
- ha = (struct scsi_qla_host *) cmd->device->host->hostdata;
+ ha = to_qla_host(cmd->device->host);
if (ql4xdontresethba) {
DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",
@@ -2284,6 +3887,110 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
return return_status;
}
+static int qla4xxx_context_reset(struct scsi_qla_host *ha)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ struct addr_ctrl_blk_def *acb = NULL;
+ uint32_t acb_len = sizeof(struct addr_ctrl_blk_def);
+ int rval = QLA_SUCCESS;
+ dma_addr_t acb_dma;
+
+ acb = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct addr_ctrl_blk_def),
+ &acb_dma, GFP_KERNEL);
+ if (!acb) {
+ ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n",
+ __func__);
+ rval = -ENOMEM;
+ goto exit_port_reset;
+ }
+
+ memset(acb, 0, acb_len);
+
+ rval = qla4xxx_get_acb(ha, acb_dma, PRIMARI_ACB, acb_len);
+ if (rval != QLA_SUCCESS) {
+ rval = -EIO;
+ goto exit_free_acb;
+ }
+
+ rval = qla4xxx_disable_acb(ha);
+ if (rval != QLA_SUCCESS) {
+ rval = -EIO;
+ goto exit_free_acb;
+ }
+
+ wait_for_completion_timeout(&ha->disable_acb_comp,
+ DISABLE_ACB_TOV * HZ);
+
+ rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma);
+ if (rval != QLA_SUCCESS) {
+ rval = -EIO;
+ goto exit_free_acb;
+ }
+
+exit_free_acb:
+ dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk_def),
+ acb, acb_dma);
+exit_port_reset:
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s %s\n", __func__,
+ rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED"));
+ return rval;
+}
+
+static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type)
+{
+ struct scsi_qla_host *ha = to_qla_host(shost);
+ int rval = QLA_SUCCESS;
+
+ if (ql4xdontresethba) {
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Don't Reset HBA\n",
+ __func__));
+ rval = -EPERM;
+ goto exit_host_reset;
+ }
+
+ rval = qla4xxx_wait_for_hba_online(ha);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unable to reset host "
+ "adapter\n", __func__));
+ rval = -EIO;
+ goto exit_host_reset;
+ }
+
+ if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
+ goto recover_adapter;
+
+ switch (reset_type) {
+ case SCSI_ADAPTER_RESET:
+ set_bit(DPC_RESET_HA, &ha->dpc_flags);
+ break;
+ case SCSI_FIRMWARE_RESET:
+ if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
+ if (is_qla8022(ha))
+ /* set firmware context reset */
+ set_bit(DPC_RESET_HA_FW_CONTEXT,
+ &ha->dpc_flags);
+ else {
+ rval = qla4xxx_context_reset(ha);
+ goto exit_host_reset;
+ }
+ }
+ break;
+ }
+
+recover_adapter:
+ rval = qla4xxx_recover_adapter(ha);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(ql4_printk(KERN_INFO, ha, "%s: recover adapter fail\n",
+ __func__));
+ rval = -EIO;
+ }
+
+exit_host_reset:
+ return rval;
+}
+
/* PCI AER driver recovers from all correctable errors w/o
* driver intervention. For uncorrectable errors PCI AER
* driver calls the following device driver's callbacks
@@ -2360,7 +4067,8 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
if (test_bit(AF_ONLINE, &ha->flags)) {
clear_bit(AF_ONLINE, &ha->flags);
- qla4xxx_mark_all_devices_missing(ha);
+ clear_bit(AF_LINK_UP, &ha->flags);
+ iscsi_host_for_each_session(ha->host, qla4xxx_fail_session);
qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
}
@@ -2407,7 +4115,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
qla4_8xxx_idc_unlock(ha);
clear_bit(AF_FW_RECOVERY, &ha->flags);
- rval = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST);
+ rval = qla4xxx_initialize_adapter(ha);
qla4_8xxx_idc_lock(ha);
if (rval != QLA_SUCCESS) {
@@ -2443,8 +4151,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)
if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
QLA82XX_DEV_READY)) {
clear_bit(AF_FW_RECOVERY, &ha->flags);
- rval = qla4xxx_initialize_adapter(ha,
- PRESERVE_DDB_LIST);
+ rval = qla4xxx_initialize_adapter(ha);
if (rval == QLA_SUCCESS) {
ret = qla4xxx_request_irqs(ha);
if (ret) {
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 610492877253..c15347d3f532 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,4 @@
* See LICENSE.qla4xxx for copyright and licensing details.
*/
-#define QLA4XXX_DRIVER_VERSION "5.02.00-k7"
+#define QLA4XXX_DRIVER_VERSION "5.02.00-k8"
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 9689d41c7888..e40dc1cb09a0 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -880,7 +880,7 @@ static inline void cmd_frob(struct Command_Entry *cmd, struct scsi_cmnd *Cmnd,
cmd->control_flags |= CFLAG_WRITE;
else
cmd->control_flags |= CFLAG_READ;
- cmd->time_out = 30;
+ cmd->time_out = Cmnd->request->timeout/HZ;
memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index a4b9cdbaaa0b..dc6131e6a1ba 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -293,8 +293,16 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
* so that we can deal with it there.
*/
if (scmd->device->expecting_cc_ua) {
- scmd->device->expecting_cc_ua = 0;
- return NEEDS_RETRY;
+ /*
+ * Because some device does not queue unit
+ * attentions correctly, we carefully check
+ * additional sense code and qualifier so as
+ * not to squash media change unit attention.
+ */
+ if (sshdr.asc != 0x28 || sshdr.ascq != 0x00) {
+ scmd->device->expecting_cc_ua = 0;
+ return NEEDS_RETRY;
+ }
}
/*
* if the device is in the process of becoming ready, we
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index e0bd3f790fca..04c2a278076e 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -246,6 +246,43 @@ show_shost_active_mode(struct device *dev,
static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
+static int check_reset_type(char *str)
+{
+ if (strncmp(str, "adapter", 10) == 0)
+ return SCSI_ADAPTER_RESET;
+ else if (strncmp(str, "firmware", 10) == 0)
+ return SCSI_FIRMWARE_RESET;
+ else
+ return 0;
+}
+
+static ssize_t
+store_host_reset(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct scsi_host_template *sht = shost->hostt;
+ int ret = -EINVAL;
+ char str[10];
+ int type;
+
+ sscanf(buf, "%s", str);
+ type = check_reset_type(str);
+
+ if (!type)
+ goto exit_store_host_reset;
+
+ if (sht->host_reset)
+ ret = sht->host_reset(shost, type);
+
+exit_store_host_reset:
+ if (ret == 0)
+ ret = count;
+ return ret;
+}
+
+static DEVICE_ATTR(host_reset, S_IWUSR, NULL, store_host_reset);
+
shost_rd_attr(unique_id, "%u\n");
shost_rd_attr(host_busy, "%hu\n");
shost_rd_attr(cmd_per_lun, "%hd\n");
@@ -272,6 +309,7 @@ static struct attribute *scsi_sysfs_shost_attrs[] = {
&dev_attr_active_mode.attr,
&dev_attr_prot_capabilities.attr,
&dev_attr_prot_guard_type.attr,
+ &dev_attr_host_reset.attr,
NULL
};
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 3fd16d7212de..1bcd65a509e6 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -23,6 +23,8 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/bsg-lib.h>
+#include <linux/idr.h>
#include <net/tcp.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
@@ -31,10 +33,7 @@
#include <scsi/scsi_transport_iscsi.h>
#include <scsi/iscsi_if.h>
#include <scsi/scsi_cmnd.h>
-
-#define ISCSI_SESSION_ATTRS 23
-#define ISCSI_CONN_ATTRS 13
-#define ISCSI_HOST_ATTRS 4
+#include <scsi/scsi_bsg_iscsi.h>
#define ISCSI_TRANSPORT_VERSION "2.0-870"
@@ -76,16 +75,14 @@ struct iscsi_internal {
struct list_head list;
struct device dev;
- struct device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
struct transport_container conn_cont;
- struct device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
struct transport_container session_cont;
- struct device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
};
static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
static struct workqueue_struct *iscsi_eh_timer_workq;
+static DEFINE_IDA(iscsi_sess_ida);
/*
* list of registered transports and lock that must
* be held while accessing list. The iscsi_transport_lock must
@@ -270,6 +267,291 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
}
EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
+/*
+ * Interface to display network param to sysfs
+ */
+
+static void iscsi_iface_release(struct device *dev)
+{
+ struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
+ struct device *parent = iface->dev.parent;
+
+ kfree(iface);
+ put_device(parent);
+}
+
+
+static struct class iscsi_iface_class = {
+ .name = "iscsi_iface",
+ .dev_release = iscsi_iface_release,
+};
+
+#define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store) \
+struct device_attribute dev_attr_##_prefix##_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+/* iface attrs show */
+#define iscsi_iface_attr_show(type, name, param_type, param) \
+static ssize_t \
+show_##type##_##name(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct iscsi_iface *iface = iscsi_dev_to_iface(dev); \
+ struct iscsi_transport *t = iface->transport; \
+ return t->get_iface_param(iface, param_type, param, buf); \
+} \
+
+#define iscsi_iface_net_attr(type, name, param) \
+ iscsi_iface_attr_show(type, name, ISCSI_NET_PARAM, param) \
+static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
+
+/* generic read only ipvi4 attribute */
+iscsi_iface_net_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR);
+iscsi_iface_net_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW);
+iscsi_iface_net_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET);
+iscsi_iface_net_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO);
+
+/* generic read only ipv6 attribute */
+iscsi_iface_net_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR);
+iscsi_iface_net_attr(ipv6_iface, link_local_addr, ISCSI_NET_PARAM_IPV6_LINKLOCAL);
+iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
+iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg,
+ ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
+iscsi_iface_net_attr(ipv6_iface, link_local_autocfg,
+ ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
+
+/* common read only iface attribute */
+iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
+iscsi_iface_net_attr(iface, vlan_id, ISCSI_NET_PARAM_VLAN_ID);
+iscsi_iface_net_attr(iface, vlan_priority, ISCSI_NET_PARAM_VLAN_PRIORITY);
+iscsi_iface_net_attr(iface, vlan_enabled, ISCSI_NET_PARAM_VLAN_ENABLED);
+iscsi_iface_net_attr(iface, mtu, ISCSI_NET_PARAM_MTU);
+iscsi_iface_net_attr(iface, port, ISCSI_NET_PARAM_PORT);
+
+static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int i)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
+ struct iscsi_transport *t = iface->transport;
+ int param;
+
+ if (attr == &dev_attr_iface_enabled.attr)
+ param = ISCSI_NET_PARAM_IFACE_ENABLE;
+ else if (attr == &dev_attr_iface_vlan_id.attr)
+ param = ISCSI_NET_PARAM_VLAN_ID;
+ else if (attr == &dev_attr_iface_vlan_priority.attr)
+ param = ISCSI_NET_PARAM_VLAN_PRIORITY;
+ else if (attr == &dev_attr_iface_vlan_enabled.attr)
+ param = ISCSI_NET_PARAM_VLAN_ENABLED;
+ else if (attr == &dev_attr_iface_mtu.attr)
+ param = ISCSI_NET_PARAM_MTU;
+ else if (attr == &dev_attr_iface_port.attr)
+ param = ISCSI_NET_PARAM_PORT;
+ else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
+ if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
+ param = ISCSI_NET_PARAM_IPV4_ADDR;
+ else if (attr == &dev_attr_ipv4_iface_gateway.attr)
+ param = ISCSI_NET_PARAM_IPV4_GW;
+ else if (attr == &dev_attr_ipv4_iface_subnet.attr)
+ param = ISCSI_NET_PARAM_IPV4_SUBNET;
+ else if (attr == &dev_attr_ipv4_iface_bootproto.attr)
+ param = ISCSI_NET_PARAM_IPV4_BOOTPROTO;
+ else
+ return 0;
+ } else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) {
+ if (attr == &dev_attr_ipv6_iface_ipaddress.attr)
+ param = ISCSI_NET_PARAM_IPV6_ADDR;
+ else if (attr == &dev_attr_ipv6_iface_link_local_addr.attr)
+ param = ISCSI_NET_PARAM_IPV6_LINKLOCAL;
+ else if (attr == &dev_attr_ipv6_iface_router_addr.attr)
+ param = ISCSI_NET_PARAM_IPV6_ROUTER;
+ else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
+ param = ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG;
+ else if (attr == &dev_attr_ipv6_iface_link_local_autocfg.attr)
+ param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG;
+ else
+ return 0;
+ } else {
+ WARN_ONCE(1, "Invalid iface attr");
+ return 0;
+ }
+
+ return t->attr_is_visible(ISCSI_NET_PARAM, param);
+}
+
+static struct attribute *iscsi_iface_attrs[] = {
+ &dev_attr_iface_enabled.attr,
+ &dev_attr_iface_vlan_id.attr,
+ &dev_attr_iface_vlan_priority.attr,
+ &dev_attr_iface_vlan_enabled.attr,
+ &dev_attr_ipv4_iface_ipaddress.attr,
+ &dev_attr_ipv4_iface_gateway.attr,
+ &dev_attr_ipv4_iface_subnet.attr,
+ &dev_attr_ipv4_iface_bootproto.attr,
+ &dev_attr_ipv6_iface_ipaddress.attr,
+ &dev_attr_ipv6_iface_link_local_addr.attr,
+ &dev_attr_ipv6_iface_router_addr.attr,
+ &dev_attr_ipv6_iface_ipaddr_autocfg.attr,
+ &dev_attr_ipv6_iface_link_local_autocfg.attr,
+ &dev_attr_iface_mtu.attr,
+ &dev_attr_iface_port.attr,
+ NULL,
+};
+
+static struct attribute_group iscsi_iface_group = {
+ .attrs = iscsi_iface_attrs,
+ .is_visible = iscsi_iface_attr_is_visible,
+};
+
+struct iscsi_iface *
+iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
+ uint32_t iface_type, uint32_t iface_num, int dd_size)
+{
+ struct iscsi_iface *iface;
+ int err;
+
+ iface = kzalloc(sizeof(*iface) + dd_size, GFP_KERNEL);
+ if (!iface)
+ return NULL;
+
+ iface->transport = transport;
+ iface->iface_type = iface_type;
+ iface->iface_num = iface_num;
+ iface->dev.release = iscsi_iface_release;
+ iface->dev.class = &iscsi_iface_class;
+ /* parent reference released in iscsi_iface_release */
+ iface->dev.parent = get_device(&shost->shost_gendev);
+ if (iface_type == ISCSI_IFACE_TYPE_IPV4)
+ dev_set_name(&iface->dev, "ipv4-iface-%u-%u", shost->host_no,
+ iface_num);
+ else
+ dev_set_name(&iface->dev, "ipv6-iface-%u-%u", shost->host_no,
+ iface_num);
+
+ err = device_register(&iface->dev);
+ if (err)
+ goto free_iface;
+
+ err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group);
+ if (err)
+ goto unreg_iface;
+
+ if (dd_size)
+ iface->dd_data = &iface[1];
+ return iface;
+
+unreg_iface:
+ device_unregister(&iface->dev);
+ return NULL;
+
+free_iface:
+ put_device(iface->dev.parent);
+ kfree(iface);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(iscsi_create_iface);
+
+void iscsi_destroy_iface(struct iscsi_iface *iface)
+{
+ sysfs_remove_group(&iface->dev.kobj, &iscsi_iface_group);
+ device_unregister(&iface->dev);
+}
+EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
+
+/*
+ * BSG support
+ */
+/**
+ * iscsi_bsg_host_dispatch - Dispatch command to LLD.
+ * @job: bsg job to be processed
+ */
+static int iscsi_bsg_host_dispatch(struct bsg_job *job)
+{
+ struct Scsi_Host *shost = iscsi_job_to_shost(job);
+ struct iscsi_bsg_request *req = job->request;
+ struct iscsi_bsg_reply *reply = job->reply;
+ struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
+ int cmdlen = sizeof(uint32_t); /* start with length of msgcode */
+ int ret;
+
+ /* check if we have the msgcode value at least */
+ if (job->request_len < sizeof(uint32_t)) {
+ ret = -ENOMSG;
+ goto fail_host_msg;
+ }
+
+ /* Validate the host command */
+ switch (req->msgcode) {
+ case ISCSI_BSG_HST_VENDOR:
+ cmdlen += sizeof(struct iscsi_bsg_host_vendor);
+ if ((shost->hostt->vendor_id == 0L) ||
+ (req->rqst_data.h_vendor.vendor_id !=
+ shost->hostt->vendor_id)) {
+ ret = -ESRCH;
+ goto fail_host_msg;
+ }
+ break;
+ default:
+ ret = -EBADR;
+ goto fail_host_msg;
+ }
+
+ /* check if we really have all the request data needed */
+ if (job->request_len < cmdlen) {
+ ret = -ENOMSG;
+ goto fail_host_msg;
+ }
+
+ ret = i->iscsi_transport->bsg_request(job);
+ if (!ret)
+ return 0;
+
+fail_host_msg:
+ /* return the errno failure code as the only status */
+ BUG_ON(job->reply_len < sizeof(uint32_t));
+ reply->reply_payload_rcv_len = 0;
+ reply->result = ret;
+ job->reply_len = sizeof(uint32_t);
+ bsg_job_done(job, ret, 0);
+ return 0;
+}
+
+/**
+ * iscsi_bsg_host_add - Create and add the bsg hooks to receive requests
+ * @shost: shost for iscsi_host
+ * @cls_host: iscsi_cls_host adding the structures to
+ */
+static int
+iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
+{
+ struct device *dev = &shost->shost_gendev;
+ struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
+ struct request_queue *q;
+ char bsg_name[20];
+ int ret;
+
+ if (!i->iscsi_transport->bsg_request)
+ return -ENOTSUPP;
+
+ snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
+
+ q = __scsi_alloc_queue(shost, bsg_request_fn);
+ if (!q)
+ return -ENOMEM;
+
+ ret = bsg_setup_queue(dev, q, bsg_name, iscsi_bsg_host_dispatch, 0);
+ if (ret) {
+ shost_printk(KERN_ERR, shost, "bsg interface failed to "
+ "initialize - no request queue\n");
+ blk_cleanup_queue(q);
+ return ret;
+ }
+
+ ihost->bsg_q = q;
+ return 0;
+}
+
static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
struct device *cdev)
{
@@ -279,13 +561,30 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
memset(ihost, 0, sizeof(*ihost));
atomic_set(&ihost->nr_scans, 0);
mutex_init(&ihost->mutex);
+
+ iscsi_bsg_host_add(shost, ihost);
+ /* ignore any bsg add error - we just can't do sgio */
+
+ return 0;
+}
+
+static int iscsi_remove_host(struct transport_container *tc,
+ struct device *dev, struct device *cdev)
+{
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct iscsi_cls_host *ihost = shost->shost_data;
+
+ if (ihost->bsg_q) {
+ bsg_remove_queue(ihost->bsg_q);
+ blk_cleanup_queue(ihost->bsg_q);
+ }
return 0;
}
static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
"iscsi_host",
iscsi_setup_host,
- NULL,
+ iscsi_remove_host,
NULL);
static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
@@ -404,6 +703,19 @@ int iscsi_session_chkready(struct iscsi_cls_session *session)
}
EXPORT_SYMBOL_GPL(iscsi_session_chkready);
+int iscsi_is_session_online(struct iscsi_cls_session *session)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&session->lock, flags);
+ if (session->state == ISCSI_SESSION_LOGGED_IN)
+ ret = 1;
+ spin_unlock_irqrestore(&session->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(iscsi_is_session_online);
+
static void iscsi_session_release(struct device *dev)
{
struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
@@ -680,6 +992,7 @@ static void __iscsi_unbind_session(struct work_struct *work)
struct Scsi_Host *shost = iscsi_session_to_shost(session);
struct iscsi_cls_host *ihost = shost->shost_data;
unsigned long flags;
+ unsigned int target_id;
ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
@@ -691,10 +1004,15 @@ static void __iscsi_unbind_session(struct work_struct *work)
mutex_unlock(&ihost->mutex);
return;
}
+
+ target_id = session->target_id;
session->target_id = ISCSI_MAX_TARGET;
spin_unlock_irqrestore(&session->lock, flags);
mutex_unlock(&ihost->mutex);
+ if (session->ida_used)
+ ida_simple_remove(&iscsi_sess_ida, target_id);
+
scsi_remove_target(&session->dev);
iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
@@ -735,59 +1053,36 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
}
EXPORT_SYMBOL_GPL(iscsi_alloc_session);
-static int iscsi_get_next_target_id(struct device *dev, void *data)
-{
- struct iscsi_cls_session *session;
- unsigned long flags;
- int err = 0;
-
- if (!iscsi_is_session_dev(dev))
- return 0;
-
- session = iscsi_dev_to_session(dev);
- spin_lock_irqsave(&session->lock, flags);
- if (*((unsigned int *) data) == session->target_id)
- err = -EEXIST;
- spin_unlock_irqrestore(&session->lock, flags);
- return err;
-}
-
int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
{
struct Scsi_Host *shost = iscsi_session_to_shost(session);
struct iscsi_cls_host *ihost;
unsigned long flags;
- unsigned int id = target_id;
+ int id = 0;
int err;
ihost = shost->shost_data;
session->sid = atomic_add_return(1, &iscsi_session_nr);
- if (id == ISCSI_MAX_TARGET) {
- for (id = 0; id < ISCSI_MAX_TARGET; id++) {
- err = device_for_each_child(&shost->shost_gendev, &id,
- iscsi_get_next_target_id);
- if (!err)
- break;
- }
+ if (target_id == ISCSI_MAX_TARGET) {
+ id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL);
- if (id == ISCSI_MAX_TARGET) {
+ if (id < 0) {
iscsi_cls_session_printk(KERN_ERR, session,
- "Too many iscsi targets. Max "
- "number of targets is %d.\n",
- ISCSI_MAX_TARGET - 1);
- err = -EOVERFLOW;
- goto release_host;
+ "Failure in Target ID Allocation\n");
+ return id;
}
- }
- session->target_id = id;
+ session->target_id = (unsigned int)id;
+ session->ida_used = true;
+ } else
+ session->target_id = target_id;
dev_set_name(&session->dev, "session%u", session->sid);
err = device_add(&session->dev);
if (err) {
iscsi_cls_session_printk(KERN_ERR, session,
"could not register session's dev\n");
- goto release_host;
+ goto release_ida;
}
transport_register_device(&session->dev);
@@ -799,8 +1094,10 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
return 0;
-release_host:
- scsi_host_put(shost);
+release_ida:
+ if (session->ida_used)
+ ida_simple_remove(&iscsi_sess_ida, session->target_id);
+
return err;
}
EXPORT_SYMBOL_GPL(iscsi_add_session);
@@ -1144,6 +1441,40 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
}
EXPORT_SYMBOL_GPL(iscsi_conn_error_event);
+void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
+ enum iscsi_conn_state state)
+{
+ struct nlmsghdr *nlh;
+ struct sk_buff *skb;
+ struct iscsi_uevent *ev;
+ struct iscsi_internal *priv;
+ int len = NLMSG_SPACE(sizeof(*ev));
+
+ priv = iscsi_if_transport_lookup(conn->transport);
+ if (!priv)
+ return;
+
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (!skb) {
+ iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
+ "conn login (%d)\n", state);
+ return;
+ }
+
+ nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
+ ev = NLMSG_DATA(nlh);
+ ev->transport_handle = iscsi_handle(conn->transport);
+ ev->type = ISCSI_KEVENT_CONN_LOGIN_STATE;
+ ev->r.conn_login.state = state;
+ ev->r.conn_login.cid = conn->cid;
+ ev->r.conn_login.sid = iscsi_conn_get_sid(conn);
+ iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
+
+ iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn login (%d)\n",
+ state);
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_login_event);
+
static int
iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
void *payload, int size)
@@ -1558,6 +1889,29 @@ iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
}
static int
+iscsi_set_iface_params(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev, uint32_t len)
+{
+ char *data = (char *)ev + sizeof(*ev);
+ struct Scsi_Host *shost;
+ int err;
+
+ if (!transport->set_iface_param)
+ return -ENOSYS;
+
+ shost = scsi_host_lookup(ev->u.set_iface_params.host_no);
+ if (!shost) {
+ printk(KERN_ERR "set_iface_params could not find host no %u\n",
+ ev->u.set_iface_params.host_no);
+ return -ENODEV;
+ }
+
+ err = transport->set_iface_param(shost, data, len);
+ scsi_host_put(shost);
+ return err;
+}
+
+static int
iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
{
int err = 0;
@@ -1696,6 +2050,10 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
case ISCSI_UEVENT_PATH_UPDATE:
err = iscsi_set_path(transport, ev);
break;
+ case ISCSI_UEVENT_SET_IFACE_PARAMS:
+ err = iscsi_set_iface_params(transport, ev,
+ nlmsg_attrlen(nlh, sizeof(*ev)));
+ break;
default:
err = -ENOSYS;
break;
@@ -1824,6 +2182,70 @@ static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, \
iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS);
iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT);
+static struct attribute *iscsi_conn_attrs[] = {
+ &dev_attr_conn_max_recv_dlength.attr,
+ &dev_attr_conn_max_xmit_dlength.attr,
+ &dev_attr_conn_header_digest.attr,
+ &dev_attr_conn_data_digest.attr,
+ &dev_attr_conn_ifmarker.attr,
+ &dev_attr_conn_ofmarker.attr,
+ &dev_attr_conn_address.attr,
+ &dev_attr_conn_port.attr,
+ &dev_attr_conn_exp_statsn.attr,
+ &dev_attr_conn_persistent_address.attr,
+ &dev_attr_conn_persistent_port.attr,
+ &dev_attr_conn_ping_tmo.attr,
+ &dev_attr_conn_recv_tmo.attr,
+ NULL,
+};
+
+static mode_t iscsi_conn_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int i)
+{
+ struct device *cdev = container_of(kobj, struct device, kobj);
+ struct iscsi_cls_conn *conn = transport_class_to_conn(cdev);
+ struct iscsi_transport *t = conn->transport;
+ int param;
+
+ if (attr == &dev_attr_conn_max_recv_dlength.attr)
+ param = ISCSI_PARAM_MAX_RECV_DLENGTH;
+ else if (attr == &dev_attr_conn_max_xmit_dlength.attr)
+ param = ISCSI_PARAM_MAX_XMIT_DLENGTH;
+ else if (attr == &dev_attr_conn_header_digest.attr)
+ param = ISCSI_PARAM_HDRDGST_EN;
+ else if (attr == &dev_attr_conn_data_digest.attr)
+ param = ISCSI_PARAM_DATADGST_EN;
+ else if (attr == &dev_attr_conn_ifmarker.attr)
+ param = ISCSI_PARAM_IFMARKER_EN;
+ else if (attr == &dev_attr_conn_ofmarker.attr)
+ param = ISCSI_PARAM_OFMARKER_EN;
+ else if (attr == &dev_attr_conn_address.attr)
+ param = ISCSI_PARAM_CONN_ADDRESS;
+ else if (attr == &dev_attr_conn_port.attr)
+ param = ISCSI_PARAM_CONN_PORT;
+ else if (attr == &dev_attr_conn_exp_statsn.attr)
+ param = ISCSI_PARAM_EXP_STATSN;
+ else if (attr == &dev_attr_conn_persistent_address.attr)
+ param = ISCSI_PARAM_PERSISTENT_ADDRESS;
+ else if (attr == &dev_attr_conn_persistent_port.attr)
+ param = ISCSI_PARAM_PERSISTENT_PORT;
+ else if (attr == &dev_attr_conn_ping_tmo.attr)
+ param = ISCSI_PARAM_PING_TMO;
+ else if (attr == &dev_attr_conn_recv_tmo.attr)
+ param = ISCSI_PARAM_RECV_TMO;
+ else {
+ WARN_ONCE(1, "Invalid conn attr");
+ return 0;
+ }
+
+ return t->attr_is_visible(ISCSI_PARAM, param);
+}
+
+static struct attribute_group iscsi_conn_group = {
+ .attrs = iscsi_conn_attrs,
+ .is_visible = iscsi_conn_attr_is_visible,
+};
+
/*
* iSCSI session attrs
*/
@@ -1845,7 +2267,6 @@ show_session_param_##param(struct device *dev, \
iscsi_session_attr_show(param, perm) \
static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
NULL);
-
iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
@@ -1922,6 +2343,100 @@ static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR, \
store_priv_session_##field)
iscsi_priv_session_rw_attr(recovery_tmo, "%d");
+static struct attribute *iscsi_session_attrs[] = {
+ &dev_attr_sess_initial_r2t.attr,
+ &dev_attr_sess_max_outstanding_r2t.attr,
+ &dev_attr_sess_immediate_data.attr,
+ &dev_attr_sess_first_burst_len.attr,
+ &dev_attr_sess_max_burst_len.attr,
+ &dev_attr_sess_data_pdu_in_order.attr,
+ &dev_attr_sess_data_seq_in_order.attr,
+ &dev_attr_sess_erl.attr,
+ &dev_attr_sess_targetname.attr,
+ &dev_attr_sess_tpgt.attr,
+ &dev_attr_sess_password.attr,
+ &dev_attr_sess_password_in.attr,
+ &dev_attr_sess_username.attr,
+ &dev_attr_sess_username_in.attr,
+ &dev_attr_sess_fast_abort.attr,
+ &dev_attr_sess_abort_tmo.attr,
+ &dev_attr_sess_lu_reset_tmo.attr,
+ &dev_attr_sess_tgt_reset_tmo.attr,
+ &dev_attr_sess_ifacename.attr,
+ &dev_attr_sess_initiatorname.attr,
+ &dev_attr_sess_targetalias.attr,
+ &dev_attr_priv_sess_recovery_tmo.attr,
+ &dev_attr_priv_sess_state.attr,
+ NULL,
+};
+
+static mode_t iscsi_session_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int i)
+{
+ struct device *cdev = container_of(kobj, struct device, kobj);
+ struct iscsi_cls_session *session = transport_class_to_session(cdev);
+ struct iscsi_transport *t = session->transport;
+ int param;
+
+ if (attr == &dev_attr_sess_initial_r2t.attr)
+ param = ISCSI_PARAM_INITIAL_R2T_EN;
+ else if (attr == &dev_attr_sess_max_outstanding_r2t.attr)
+ param = ISCSI_PARAM_MAX_R2T;
+ else if (attr == &dev_attr_sess_immediate_data.attr)
+ param = ISCSI_PARAM_IMM_DATA_EN;
+ else if (attr == &dev_attr_sess_first_burst_len.attr)
+ param = ISCSI_PARAM_FIRST_BURST;
+ else if (attr == &dev_attr_sess_max_burst_len.attr)
+ param = ISCSI_PARAM_MAX_BURST;
+ else if (attr == &dev_attr_sess_data_pdu_in_order.attr)
+ param = ISCSI_PARAM_PDU_INORDER_EN;
+ else if (attr == &dev_attr_sess_data_seq_in_order.attr)
+ param = ISCSI_PARAM_DATASEQ_INORDER_EN;
+ else if (attr == &dev_attr_sess_erl.attr)
+ param = ISCSI_PARAM_ERL;
+ else if (attr == &dev_attr_sess_targetname.attr)
+ param = ISCSI_PARAM_TARGET_NAME;
+ else if (attr == &dev_attr_sess_tpgt.attr)
+ param = ISCSI_PARAM_TPGT;
+ else if (attr == &dev_attr_sess_password.attr)
+ param = ISCSI_PARAM_USERNAME;
+ else if (attr == &dev_attr_sess_password_in.attr)
+ param = ISCSI_PARAM_USERNAME_IN;
+ else if (attr == &dev_attr_sess_username.attr)
+ param = ISCSI_PARAM_PASSWORD;
+ else if (attr == &dev_attr_sess_username_in.attr)
+ param = ISCSI_PARAM_PASSWORD_IN;
+ else if (attr == &dev_attr_sess_fast_abort.attr)
+ param = ISCSI_PARAM_FAST_ABORT;
+ else if (attr == &dev_attr_sess_abort_tmo.attr)
+ param = ISCSI_PARAM_ABORT_TMO;
+ else if (attr == &dev_attr_sess_lu_reset_tmo.attr)
+ param = ISCSI_PARAM_LU_RESET_TMO;
+ else if (attr == &dev_attr_sess_tgt_reset_tmo.attr)
+ param = ISCSI_PARAM_TGT_RESET_TMO;
+ else if (attr == &dev_attr_sess_ifacename.attr)
+ param = ISCSI_PARAM_IFACE_NAME;
+ else if (attr == &dev_attr_sess_initiatorname.attr)
+ param = ISCSI_PARAM_INITIATOR_NAME;
+ else if (attr == &dev_attr_sess_targetalias.attr)
+ param = ISCSI_PARAM_TARGET_ALIAS;
+ else if (attr == &dev_attr_priv_sess_recovery_tmo.attr)
+ return S_IRUGO | S_IWUSR;
+ else if (attr == &dev_attr_priv_sess_state.attr)
+ return S_IRUGO;
+ else {
+ WARN_ONCE(1, "Invalid session attr");
+ return 0;
+ }
+
+ return t->attr_is_visible(ISCSI_PARAM, param);
+}
+
+static struct attribute_group iscsi_session_group = {
+ .attrs = iscsi_session_attrs,
+ .is_visible = iscsi_session_attr_is_visible,
+};
+
/*
* iSCSI host attrs
*/
@@ -1945,41 +2460,42 @@ iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
-#define SETUP_PRIV_SESSION_RD_ATTR(field) \
-do { \
- priv->session_attrs[count] = &dev_attr_priv_sess_##field; \
- count++; \
-} while (0)
-
-#define SETUP_PRIV_SESSION_RW_ATTR(field) \
-do { \
- priv->session_attrs[count] = &dev_attr_priv_sess_##field; \
- count++; \
-} while (0)
-
-#define SETUP_SESSION_RD_ATTR(field, param_flag) \
-do { \
- if (tt->param_mask & param_flag) { \
- priv->session_attrs[count] = &dev_attr_sess_##field; \
- count++; \
- } \
-} while (0)
+static struct attribute *iscsi_host_attrs[] = {
+ &dev_attr_host_netdev.attr,
+ &dev_attr_host_hwaddress.attr,
+ &dev_attr_host_ipaddress.attr,
+ &dev_attr_host_initiatorname.attr,
+ NULL,
+};
-#define SETUP_CONN_RD_ATTR(field, param_flag) \
-do { \
- if (tt->param_mask & param_flag) { \
- priv->conn_attrs[count] = &dev_attr_conn_##field; \
- count++; \
- } \
-} while (0)
+static mode_t iscsi_host_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int i)
+{
+ struct device *cdev = container_of(kobj, struct device, kobj);
+ struct Scsi_Host *shost = transport_class_to_shost(cdev);
+ struct iscsi_internal *priv = to_iscsi_internal(shost->transportt);
+ int param;
+
+ if (attr == &dev_attr_host_netdev.attr)
+ param = ISCSI_HOST_PARAM_NETDEV_NAME;
+ else if (attr == &dev_attr_host_hwaddress.attr)
+ param = ISCSI_HOST_PARAM_HWADDRESS;
+ else if (attr == &dev_attr_host_ipaddress.attr)
+ param = ISCSI_HOST_PARAM_IPADDRESS;
+ else if (attr == &dev_attr_host_initiatorname.attr)
+ param = ISCSI_HOST_PARAM_INITIATOR_NAME;
+ else {
+ WARN_ONCE(1, "Invalid host attr");
+ return 0;
+ }
-#define SETUP_HOST_RD_ATTR(field, param_flag) \
-do { \
- if (tt->host_param_mask & param_flag) { \
- priv->host_attrs[count] = &dev_attr_host_##field; \
- count++; \
- } \
-} while (0)
+ return priv->iscsi_transport->attr_is_visible(ISCSI_HOST_PARAM, param);
+}
+
+static struct attribute_group iscsi_host_group = {
+ .attrs = iscsi_host_attrs,
+ .is_visible = iscsi_host_attr_is_visible,
+};
static int iscsi_session_match(struct attribute_container *cont,
struct device *dev)
@@ -2051,7 +2567,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
{
struct iscsi_internal *priv;
unsigned long flags;
- int count = 0, err;
+ int err;
BUG_ON(!tt);
@@ -2078,77 +2594,24 @@ iscsi_register_transport(struct iscsi_transport *tt)
goto unregister_dev;
/* host parameters */
- priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
priv->t.host_attrs.ac.class = &iscsi_host_class.class;
priv->t.host_attrs.ac.match = iscsi_host_match;
+ priv->t.host_attrs.ac.grp = &iscsi_host_group;
priv->t.host_size = sizeof(struct iscsi_cls_host);
transport_container_register(&priv->t.host_attrs);
- SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME);
- SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS);
- SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS);
- SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME);
- BUG_ON(count > ISCSI_HOST_ATTRS);
- priv->host_attrs[count] = NULL;
- count = 0;
-
/* connection parameters */
- priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
priv->conn_cont.ac.class = &iscsi_connection_class.class;
priv->conn_cont.ac.match = iscsi_conn_match;
+ priv->conn_cont.ac.grp = &iscsi_conn_group;
transport_container_register(&priv->conn_cont);
- SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH);
- SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH);
- SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN);
- SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN);
- SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN);
- SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN);
- SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS);
- SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT);
- SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
- SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
- SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
- SETUP_CONN_RD_ATTR(ping_tmo, ISCSI_PING_TMO);
- SETUP_CONN_RD_ATTR(recv_tmo, ISCSI_RECV_TMO);
-
- BUG_ON(count > ISCSI_CONN_ATTRS);
- priv->conn_attrs[count] = NULL;
- count = 0;
-
/* session parameters */
- priv->session_cont.ac.attrs = &priv->session_attrs[0];
priv->session_cont.ac.class = &iscsi_session_class.class;
priv->session_cont.ac.match = iscsi_session_match;
+ priv->session_cont.ac.grp = &iscsi_session_group;
transport_container_register(&priv->session_cont);
- SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN);
- SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T);
- SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN);
- SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST);
- SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST);
- SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
- SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
- SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
- SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
- SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
- SETUP_SESSION_RD_ATTR(password, ISCSI_USERNAME);
- SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN);
- SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD);
- SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN);
- SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);
- SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);
- SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO);
- SETUP_SESSION_RD_ATTR(tgt_reset_tmo,ISCSI_TGT_RESET_TMO);
- SETUP_SESSION_RD_ATTR(ifacename, ISCSI_IFACE_NAME);
- SETUP_SESSION_RD_ATTR(initiatorname, ISCSI_INITIATOR_NAME);
- SETUP_SESSION_RD_ATTR(targetalias, ISCSI_TARGET_ALIAS);
- SETUP_PRIV_SESSION_RW_ATTR(recovery_tmo);
- SETUP_PRIV_SESSION_RD_ATTR(state);
-
- BUG_ON(count > ISCSI_SESSION_ATTRS);
- priv->session_attrs[count] = NULL;
-
spin_lock_irqsave(&iscsi_transport_lock, flags);
list_add(&priv->list, &iscsi_transports);
spin_unlock_irqrestore(&iscsi_transport_lock, flags);
@@ -2210,10 +2673,14 @@ static __init int iscsi_transport_init(void)
if (err)
goto unregister_transport_class;
- err = transport_class_register(&iscsi_host_class);
+ err = class_register(&iscsi_iface_class);
if (err)
goto unregister_endpoint_class;
+ err = transport_class_register(&iscsi_host_class);
+ if (err)
+ goto unregister_iface_class;
+
err = transport_class_register(&iscsi_connection_class);
if (err)
goto unregister_host_class;
@@ -2243,6 +2710,8 @@ unregister_conn_class:
transport_class_unregister(&iscsi_connection_class);
unregister_host_class:
transport_class_unregister(&iscsi_host_class);
+unregister_iface_class:
+ class_unregister(&iscsi_iface_class);
unregister_endpoint_class:
class_unregister(&iscsi_endpoint_class);
unregister_transport_class:
@@ -2258,6 +2727,7 @@ static void __exit iscsi_transport_exit(void)
transport_class_unregister(&iscsi_session_class);
transport_class_unregister(&iscsi_host_class);
class_unregister(&iscsi_endpoint_class);
+ class_unregister(&iscsi_iface_class);
class_unregister(&iscsi_transport_class);
}
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index c6fcf76cade5..9d9330ae4213 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -1545,8 +1545,14 @@ int sas_rphy_add(struct sas_rphy *rphy)
if (identify->device_type == SAS_END_DEVICE &&
rphy->scsi_target_id != -1) {
- scsi_scan_target(&rphy->dev, 0,
- rphy->scsi_target_id, SCAN_WILD_CARD, 0);
+ int lun;
+
+ if (identify->target_port_protocols & SAS_PROTOCOL_SSP)
+ lun = SCAN_WILD_CARD;
+ else
+ lun = 0;
+
+ scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun, 0);
}
return 0;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 953773cb26d9..a7942e5c8be8 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1066,12 +1066,13 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
struct gendisk *disk = bdev->bd_disk;
- struct scsi_device *sdp = scsi_disk(disk)->device;
+ struct scsi_disk *sdkp = scsi_disk(disk);
+ struct scsi_device *sdp = sdkp->device;
void __user *p = (void __user *)arg;
int error;
- SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n",
- disk->disk_name, cmd));
+ SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
+ "cmd=0x%x\n", disk->disk_name, cmd));
/*
* If we are in the middle of error recovery, don't let anyone
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 909ed9ed24c0..441a1c5b8974 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -50,6 +50,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */
#include <linux/delay.h>
#include <linux/blktrace_api.h>
#include <linux/mutex.h>
+#include <linux/ratelimit.h>
#include "scsi.h"
#include <scsi/scsi_dbg.h>
@@ -626,14 +627,15 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
*/
if (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
static char cmd[TASK_COMM_LEN];
- if (strcmp(current->comm, cmd) && printk_ratelimit()) {
- printk(KERN_WARNING
- "sg_write: data in/out %d/%d bytes for SCSI command 0x%x--"
- "guessing data in;\n "
- "program %s not setting count and/or reply_len properly\n",
- old_hdr.reply_len - (int)SZ_SG_HEADER,
- input_size, (unsigned int) cmnd[0],
- current->comm);
+ if (strcmp(current->comm, cmd)) {
+ printk_ratelimited(KERN_WARNING
+ "sg_write: data in/out %d/%d bytes "
+ "for SCSI command 0x%x-- guessing "
+ "data in;\n program %s not setting "
+ "count and/or reply_len properly\n",
+ old_hdr.reply_len - (int)SZ_SG_HEADER,
+ input_size, (unsigned int) cmnd[0],
+ current->comm);
strcpy(cmd, current->comm);
}
}
diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c
index 33b2ed451e09..e0ada3773786 100644
--- a/drivers/sh/intc/chip.c
+++ b/drivers/sh/intc/chip.c
@@ -202,11 +202,16 @@ static int intc_set_type(struct irq_data *data, unsigned int type)
if (!value)
return -EINVAL;
+ value &= ~SENSE_VALID_FLAG;
+
ihp = intc_find_irq(d->sense, d->nr_sense, irq);
if (ihp) {
+ /* PINT has 2-bit sense registers, should fail on EDGE_BOTH */
+ if (value >= (1 << _INTC_WIDTH(ihp->handle)))
+ return -EINVAL;
+
addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
- intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle,
- value & ~SENSE_VALID_FLAG);
+ intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
}
return 0;
diff --git a/drivers/sh/intc/userimask.c b/drivers/sh/intc/userimask.c
index e32304b66cf1..56bf9336b92b 100644
--- a/drivers/sh/intc/userimask.c
+++ b/drivers/sh/intc/userimask.c
@@ -13,6 +13,7 @@
#include <linux/sysdev.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/stat.h>
#include <asm/sizes.h>
#include "internals.h"
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c
index 75934e3ea34e..e67fe170d8d5 100644
--- a/drivers/sh/pfc.c
+++ b/drivers/sh/pfc.c
@@ -217,7 +217,7 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
if (!r_width)
break;
- for (n = 0; n < (r_width / f_width) * 1 << f_width; n++) {
+ for (n = 0; n < (r_width / f_width) * (1 << f_width); n++) {
if (config_reg->enum_ids[n] == enum_id) {
*crp = config_reg;
*indexp = n;
@@ -577,6 +577,32 @@ static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
sh_gpio_set_value(chip_to_pinmux(chip), offset, value);
}
+static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct pinmux_info *gpioc = chip_to_pinmux(chip);
+ pinmux_enum_t enum_id;
+ pinmux_enum_t *enum_ids;
+ int i, k, pos;
+
+ pos = 0;
+ enum_id = 0;
+ while (1) {
+ pos = get_gpio_enum_id(gpioc, offset, pos, &enum_id);
+ if (pos <= 0 || !enum_id)
+ break;
+
+ for (i = 0; i < gpioc->gpio_irq_size; i++) {
+ enum_ids = gpioc->gpio_irq[i].enum_ids;
+ for (k = 0; enum_ids[k]; k++) {
+ if (enum_ids[k] == enum_id)
+ return gpioc->gpio_irq[i].irq;
+ }
+ }
+ }
+
+ return -ENOSYS;
+}
+
int register_pinmux(struct pinmux_info *pip)
{
struct gpio_chip *chip = &pip->chip;
@@ -592,6 +618,7 @@ int register_pinmux(struct pinmux_info *pip)
chip->get = sh_gpio_get;
chip->direction_output = sh_gpio_direction_output;
chip->set = sh_gpio_set;
+ chip->to_irq = sh_gpio_to_irq;
WARN_ON(pip->first_gpio != 0); /* needs testing */
diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c
index 4813a63ce6fb..881c1967741d 100644
--- a/drivers/spi/spi-altera.c
+++ b/drivers/spi/spi-altera.c
@@ -320,18 +320,7 @@ static struct platform_driver altera_spi_driver = {
.of_match_table = altera_spi_match,
},
};
-
-static int __init altera_spi_init(void)
-{
- return platform_driver_register(&altera_spi_driver);
-}
-module_init(altera_spi_init);
-
-static void __exit altera_spi_exit(void)
-{
- platform_driver_unregister(&altera_spi_driver);
-}
-module_exit(altera_spi_exit);
+module_platform_driver(altera_spi_driver);
MODULE_DESCRIPTION("Altera SPI driver");
MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index 03019bf5a5e9..024b48aed5ca 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -273,18 +273,7 @@ static struct platform_driver ath79_spi_driver = {
.owner = THIS_MODULE,
},
};
-
-static __init int ath79_spi_init(void)
-{
- return platform_driver_register(&ath79_spi_driver);
-}
-module_init(ath79_spi_init);
-
-static __exit void ath79_spi_exit(void)
-{
- platform_driver_unregister(&ath79_spi_driver);
-}
-module_exit(ath79_spi_exit);
+module_platform_driver(ath79_spi_driver);
MODULE_DESCRIPTION("SPI controller driver for Atheros AR71XX/AR724X/AR913X");
MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 82dee9a6c0de..79665e2e6ec5 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -22,7 +22,7 @@
#include <asm/io.h>
#include <mach/board.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <mach/cpu.h>
/* SPI register offsets */
@@ -1074,18 +1074,7 @@ static struct platform_driver atmel_spi_driver = {
.resume = atmel_spi_resume,
.remove = __exit_p(atmel_spi_remove),
};
-
-static int __init atmel_spi_init(void)
-{
- return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe);
-}
-module_init(atmel_spi_init);
-
-static void __exit atmel_spi_exit(void)
-{
- platform_driver_unregister(&atmel_spi_driver);
-}
-module_exit(atmel_spi_exit);
+module_platform_driver(atmel_spi_driver);
MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver");
MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c
index e557ff617b11..248a2cc671a9 100644
--- a/drivers/spi/spi-bfin-sport.c
+++ b/drivers/spi/spi-bfin-sport.c
@@ -938,15 +938,4 @@ static struct platform_driver bfin_sport_spi_driver = {
.suspend = bfin_sport_spi_suspend,
.resume = bfin_sport_spi_resume,
};
-
-static int __init bfin_sport_spi_init(void)
-{
- return platform_driver_register(&bfin_sport_spi_driver);
-}
-module_init(bfin_sport_spi_init);
-
-static void __exit bfin_sport_spi_exit(void)
-{
- platform_driver_unregister(&bfin_sport_spi_driver);
-}
-module_exit(bfin_sport_spi_exit);
+module_platform_driver(bfin_sport_spi_driver);
diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c
index b8d25f2b7038..3b83ff8b1e2b 100644
--- a/drivers/spi/spi-bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -1098,7 +1098,7 @@ static int bfin_spi_setup(struct spi_device *spi)
if (chip->pio_interrupt && !drv_data->irq_requested) {
ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler,
- IRQF_DISABLED, "BFIN_SPI", drv_data);
+ 0, "BFIN_SPI", drv_data);
if (ret) {
dev_err(&spi->dev, "Unable to register spi IRQ\n");
goto error;
diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c
index ae2cd1c1fda8..6eee64a5d240 100644
--- a/drivers/spi/spi-coldfire-qspi.c
+++ b/drivers/spi/spi-coldfire-qspi.c
@@ -487,7 +487,7 @@ static int __devinit mcfqspi_probe(struct platform_device *pdev)
goto fail2;
}
- status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, IRQF_DISABLED,
+ status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, 0,
pdev->name, mcfqspi);
if (status) {
dev_dbg(&pdev->dev, "request_irq failed\n");
@@ -621,20 +621,10 @@ static struct platform_driver mcfqspi_driver = {
.driver.name = DRIVER_NAME,
.driver.owner = THIS_MODULE,
.driver.pm = MCFQSPI_DEV_PM_OPS,
+ .probe = mcfqspi_probe,
.remove = __devexit_p(mcfqspi_remove),
};
-
-static int __init mcfqspi_init(void)
-{
- return platform_driver_probe(&mcfqspi_driver, mcfqspi_probe);
-}
-module_init(mcfqspi_init);
-
-static void __exit mcfqspi_exit(void)
-{
- platform_driver_unregister(&mcfqspi_driver);
-}
-module_exit(mcfqspi_exit);
+module_platform_driver(mcfqspi_driver);
MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
MODULE_DESCRIPTION("Coldfire QSPI Controller Driver");
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 1f0ed8005c91..31bfba805cf4 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -799,7 +799,7 @@ rx_dma_failed:
* It will invoke spi_bitbang_start to create work queue so that client driver
* can register transfer method to work queue.
*/
-static int davinci_spi_probe(struct platform_device *pdev)
+static int __devinit davinci_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct davinci_spi *dspi;
@@ -984,7 +984,7 @@ err:
* It will also call spi_bitbang_stop to destroy the work queue which was
* created by spi_bitbang_start.
*/
-static int __exit davinci_spi_remove(struct platform_device *pdev)
+static int __devexit davinci_spi_remove(struct platform_device *pdev)
{
struct davinci_spi *dspi;
struct spi_master *master;
@@ -1011,20 +1011,10 @@ static struct platform_driver davinci_spi_driver = {
.name = "spi_davinci",
.owner = THIS_MODULE,
},
- .remove = __exit_p(davinci_spi_remove),
+ .probe = davinci_spi_probe,
+ .remove = __devexit_p(davinci_spi_remove),
};
-
-static int __init davinci_spi_init(void)
-{
- return platform_driver_probe(&davinci_spi_driver, davinci_spi_probe);
-}
-module_init(davinci_spi_init);
-
-static void __exit davinci_spi_exit(void)
-{
- platform_driver_unregister(&davinci_spi_driver);
-}
-module_exit(davinci_spi_exit);
+module_platform_driver(davinci_spi_driver);
MODULE_DESCRIPTION("TI DaVinci SPI Master Controller Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index 130e55537db6..e743a45ee92c 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -116,13 +116,13 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
/* 1. setup DMA related registers */
if (cs_change) {
spi_enable_chip(dws, 0);
- dw_writew(dws, dmardlr, 0xf);
- dw_writew(dws, dmatdlr, 0x10);
+ dw_writew(dws, DW_SPI_DMARDLR, 0xf);
+ dw_writew(dws, DW_SPI_DMATDLR, 0x10);
if (dws->tx_dma)
dma_ctrl |= 0x2;
if (dws->rx_dma)
dma_ctrl |= 0x1;
- dw_writew(dws, dmacr, dma_ctrl);
+ dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
spi_enable_chip(dws, 1);
}
@@ -200,7 +200,8 @@ static struct dw_spi_dma_ops mid_dma_ops = {
int dw_spi_mid_init(struct dw_spi *dws)
{
- u32 *clk_reg, clk_cdiv;
+ void __iomem *clk_reg;
+ u32 clk_cdiv;
clk_reg = ioremap_nocache(MRST_CLK_SPI0_REG, 16);
if (!clk_reg)
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 34eb66501dbf..fac399c3022c 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -127,24 +127,14 @@ static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
}
static struct platform_driver dw_spi_mmio_driver = {
+ .probe = dw_spi_mmio_probe,
.remove = __devexit_p(dw_spi_mmio_remove),
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
-
-static int __init dw_spi_mmio_init(void)
-{
- return platform_driver_probe(&dw_spi_mmio_driver, dw_spi_mmio_probe);
-}
-module_init(dw_spi_mmio_init);
-
-static void __exit dw_spi_mmio_exit(void)
-{
- platform_driver_unregister(&dw_spi_mmio_driver);
-}
-module_exit(dw_spi_mmio_exit);
+module_platform_driver(dw_spi_mmio_driver);
MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 857cd30b44bb..296d94f4cf72 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -88,35 +88,35 @@ static ssize_t spi_show_regs(struct file *file, char __user *user_buf,
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
"=================================\n");
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "CTRL0: \t\t0x%08x\n", dw_readl(dws, ctrl0));
+ "CTRL0: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL0));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "CTRL1: \t\t0x%08x\n", dw_readl(dws, ctrl1));
+ "CTRL1: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL1));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "SSIENR: \t0x%08x\n", dw_readl(dws, ssienr));
+ "SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "SER: \t\t0x%08x\n", dw_readl(dws, ser));
+ "SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "BAUDR: \t\t0x%08x\n", dw_readl(dws, baudr));
+ "BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "TXFTLR: \t0x%08x\n", dw_readl(dws, txfltr));
+ "TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFLTR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "RXFTLR: \t0x%08x\n", dw_readl(dws, rxfltr));
+ "RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFLTR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "TXFLR: \t\t0x%08x\n", dw_readl(dws, txflr));
+ "TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "RXFLR: \t\t0x%08x\n", dw_readl(dws, rxflr));
+ "RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "SR: \t\t0x%08x\n", dw_readl(dws, sr));
+ "SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "IMR: \t\t0x%08x\n", dw_readl(dws, imr));
+ "IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "ISR: \t\t0x%08x\n", dw_readl(dws, isr));
+ "ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "DMACR: \t\t0x%08x\n", dw_readl(dws, dmacr));
+ "DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "DMATDLR: \t0x%08x\n", dw_readl(dws, dmatdlr));
+ "DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
- "DMARDLR: \t0x%08x\n", dw_readl(dws, dmardlr));
+ "DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
"=================================\n");
@@ -166,7 +166,7 @@ static inline u32 tx_max(struct dw_spi *dws)
u32 tx_left, tx_room, rxtx_gap;
tx_left = (dws->tx_end - dws->tx) / dws->n_bytes;
- tx_room = dws->fifo_len - dw_readw(dws, txflr);
+ tx_room = dws->fifo_len - dw_readw(dws, DW_SPI_TXFLR);
/*
* Another concern is about the tx/rx mismatch, we
@@ -187,7 +187,7 @@ static inline u32 rx_max(struct dw_spi *dws)
{
u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes;
- return min(rx_left, (u32)dw_readw(dws, rxflr));
+ return min(rx_left, (u32)dw_readw(dws, DW_SPI_RXFLR));
}
static void dw_writer(struct dw_spi *dws)
@@ -203,7 +203,7 @@ static void dw_writer(struct dw_spi *dws)
else
txw = *(u16 *)(dws->tx);
}
- dw_writew(dws, dr, txw);
+ dw_writew(dws, DW_SPI_DR, txw);
dws->tx += dws->n_bytes;
}
}
@@ -214,7 +214,7 @@ static void dw_reader(struct dw_spi *dws)
u16 rxw;
while (max--) {
- rxw = dw_readw(dws, dr);
+ rxw = dw_readw(dws, DW_SPI_DR);
/* Care rx only if the transfer's original "rx" is not null */
if (dws->rx_end - dws->len) {
if (dws->n_bytes == 1)
@@ -322,13 +322,13 @@ EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
static irqreturn_t interrupt_transfer(struct dw_spi *dws)
{
- u16 irq_status = dw_readw(dws, isr);
+ u16 irq_status = dw_readw(dws, DW_SPI_ISR);
/* Error handling */
if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
- dw_readw(dws, txoicr);
- dw_readw(dws, rxoicr);
- dw_readw(dws, rxuicr);
+ dw_readw(dws, DW_SPI_TXOICR);
+ dw_readw(dws, DW_SPI_RXOICR);
+ dw_readw(dws, DW_SPI_RXUICR);
int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun");
return IRQ_HANDLED;
}
@@ -352,7 +352,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
static irqreturn_t dw_spi_irq(int irq, void *dev_id)
{
struct dw_spi *dws = dev_id;
- u16 irq_status = dw_readw(dws, isr) & 0x3f;
+ u16 irq_status = dw_readw(dws, DW_SPI_ISR) & 0x3f;
if (!irq_status)
return IRQ_NONE;
@@ -520,11 +520,11 @@ static void pump_transfers(unsigned long data)
* 2. clk_div is changed
* 3. control value changes
*/
- if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div || imask) {
+ if (dw_readw(dws, DW_SPI_CTRL0) != cr0 || cs_change || clk_div || imask) {
spi_enable_chip(dws, 0);
- if (dw_readw(dws, ctrl0) != cr0)
- dw_writew(dws, ctrl0, cr0);
+ if (dw_readw(dws, DW_SPI_CTRL0) != cr0)
+ dw_writew(dws, DW_SPI_CTRL0, cr0);
spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
spi_chip_sel(dws, spi->chip_select);
@@ -534,7 +534,7 @@ static void pump_transfers(unsigned long data)
if (imask)
spi_umask_intr(dws, imask);
if (txint_level)
- dw_writew(dws, txfltr, txint_level);
+ dw_writew(dws, DW_SPI_TXFLTR, txint_level);
spi_enable_chip(dws, 1);
if (cs_change)
@@ -790,13 +790,13 @@ static void spi_hw_init(struct dw_spi *dws)
if (!dws->fifo_len) {
u32 fifo;
for (fifo = 2; fifo <= 257; fifo++) {
- dw_writew(dws, txfltr, fifo);
- if (fifo != dw_readw(dws, txfltr))
+ dw_writew(dws, DW_SPI_TXFLTR, fifo);
+ if (fifo != dw_readw(dws, DW_SPI_TXFLTR))
break;
}
dws->fifo_len = (fifo == 257) ? 0 : fifo;
- dw_writew(dws, txfltr, 0);
+ dw_writew(dws, DW_SPI_TXFLTR, 0);
}
}
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 8b7b07bf6c3f..9c57c078031e 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -4,6 +4,33 @@
#include <linux/io.h>
#include <linux/scatterlist.h>
+/* Register offsets */
+#define DW_SPI_CTRL0 0x00
+#define DW_SPI_CTRL1 0x04
+#define DW_SPI_SSIENR 0x08
+#define DW_SPI_MWCR 0x0c
+#define DW_SPI_SER 0x10
+#define DW_SPI_BAUDR 0x14
+#define DW_SPI_TXFLTR 0x18
+#define DW_SPI_RXFLTR 0x1c
+#define DW_SPI_TXFLR 0x20
+#define DW_SPI_RXFLR 0x24
+#define DW_SPI_SR 0x28
+#define DW_SPI_IMR 0x2c
+#define DW_SPI_ISR 0x30
+#define DW_SPI_RISR 0x34
+#define DW_SPI_TXOICR 0x38
+#define DW_SPI_RXOICR 0x3c
+#define DW_SPI_RXUICR 0x40
+#define DW_SPI_MSTICR 0x44
+#define DW_SPI_ICR 0x48
+#define DW_SPI_DMACR 0x4c
+#define DW_SPI_DMATDLR 0x50
+#define DW_SPI_DMARDLR 0x54
+#define DW_SPI_IDR 0x58
+#define DW_SPI_VERSION 0x5c
+#define DW_SPI_DR 0x60
+
/* Bit fields in CTRLR0 */
#define SPI_DFS_OFFSET 0
@@ -55,35 +82,6 @@ enum dw_ssi_type {
SSI_NS_MICROWIRE,
};
-struct dw_spi_reg {
- u32 ctrl0;
- u32 ctrl1;
- u32 ssienr;
- u32 mwcr;
- u32 ser;
- u32 baudr;
- u32 txfltr;
- u32 rxfltr;
- u32 txflr;
- u32 rxflr;
- u32 sr;
- u32 imr;
- u32 isr;
- u32 risr;
- u32 txoicr;
- u32 rxoicr;
- u32 rxuicr;
- u32 msticr;
- u32 icr;
- u32 dmacr;
- u32 dmatdlr;
- u32 dmardlr;
- u32 idr;
- u32 version;
- u32 dr; /* Currently oper as 32 bits,
- though only low 16 bits matters */
-} __packed;
-
struct dw_spi;
struct dw_spi_dma_ops {
int (*dma_init)(struct dw_spi *dws);
@@ -161,23 +159,34 @@ struct dw_spi {
#endif
};
-#define dw_readl(dw, name) \
- __raw_readl(&(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_writel(dw, name, val) \
- __raw_writel((val), &(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_readw(dw, name) \
- __raw_readw(&(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_writew(dw, name, val) \
- __raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name))
+static inline u32 dw_readl(struct dw_spi *dws, u32 offset)
+{
+ return __raw_readl(dws->regs + offset);
+}
+
+static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
+{
+ __raw_writel(val, dws->regs + offset);
+}
+
+static inline u16 dw_readw(struct dw_spi *dws, u32 offset)
+{
+ return __raw_readw(dws->regs + offset);
+}
+
+static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val)
+{
+ __raw_writew(val, dws->regs + offset);
+}
static inline void spi_enable_chip(struct dw_spi *dws, int enable)
{
- dw_writel(dws, ssienr, (enable ? 1 : 0));
+ dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
}
static inline void spi_set_clk(struct dw_spi *dws, u16 div)
{
- dw_writel(dws, baudr, div);
+ dw_writel(dws, DW_SPI_BAUDR, div);
}
static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
@@ -188,7 +197,7 @@ static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
if (dws->cs_control)
dws->cs_control(1);
- dw_writel(dws, ser, 1 << cs);
+ dw_writel(dws, DW_SPI_SER, 1 << cs);
}
/* Disable IRQ bits */
@@ -196,8 +205,8 @@ static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
{
u32 new_mask;
- new_mask = dw_readl(dws, imr) & ~mask;
- dw_writel(dws, imr, new_mask);
+ new_mask = dw_readl(dws, DW_SPI_IMR) & ~mask;
+ dw_writel(dws, DW_SPI_IMR, new_mask);
}
/* Enable IRQ bits */
@@ -205,8 +214,8 @@ static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
{
u32 new_mask;
- new_mask = dw_readl(dws, imr) | mask;
- dw_writel(dws, imr, new_mask);
+ new_mask = dw_readl(dws, DW_SPI_IMR) | mask;
+ dw_writel(dws, DW_SPI_IMR, new_mask);
}
/*
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index 1cf645479bfe..0a282e5fcc9c 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -24,6 +24,7 @@
#include <linux/dmaengine.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
@@ -1025,7 +1026,7 @@ static void ep93xx_spi_release_dma(struct ep93xx_spi *espi)
free_page((unsigned long)espi->zeropage);
}
-static int __init ep93xx_spi_probe(struct platform_device *pdev)
+static int __devinit ep93xx_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct ep93xx_spi_info *info;
@@ -1150,7 +1151,7 @@ fail_release_master:
return error;
}
-static int __exit ep93xx_spi_remove(struct platform_device *pdev)
+static int __devexit ep93xx_spi_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct ep93xx_spi *espi = spi_master_get_devdata(master);
@@ -1196,20 +1197,10 @@ static struct platform_driver ep93xx_spi_driver = {
.name = "ep93xx-spi",
.owner = THIS_MODULE,
},
- .remove = __exit_p(ep93xx_spi_remove),
+ .probe = ep93xx_spi_probe,
+ .remove = __devexit_p(ep93xx_spi_remove),
};
-
-static int __init ep93xx_spi_init(void)
-{
- return platform_driver_probe(&ep93xx_spi_driver, ep93xx_spi_probe);
-}
-module_init(ep93xx_spi_init);
-
-static void __exit ep93xx_spi_exit(void)
-{
- platform_driver_unregister(&ep93xx_spi_driver);
-}
-module_exit(ep93xx_spi_exit);
+module_platform_driver(ep93xx_spi_driver);
MODULE_DESCRIPTION("EP93xx SPI Controller driver");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index 54e499d5f92c..d770f03705c3 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -744,18 +744,7 @@ static struct platform_driver fsl_espi_driver = {
.probe = of_fsl_espi_probe,
.remove = __devexit_p(of_fsl_espi_remove),
};
-
-static int __init fsl_espi_init(void)
-{
- return platform_driver_register(&fsl_espi_driver);
-}
-module_init(fsl_espi_init);
-
-static void __exit fsl_espi_exit(void)
-{
- platform_driver_unregister(&fsl_espi_driver);
-}
-module_exit(fsl_espi_exit);
+module_platform_driver(fsl_espi_driver);
MODULE_AUTHOR("Mingkai Hu");
MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 0e88ab745490..635ff08b377f 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -311,7 +311,7 @@ done:
return value;
}
-static int __init spi_gpio_probe(struct platform_device *pdev)
+static int __devinit spi_gpio_probe(struct platform_device *pdev)
{
int status;
struct spi_master *master;
@@ -379,7 +379,7 @@ gpio_free:
return status;
}
-static int __exit spi_gpio_remove(struct platform_device *pdev)
+static int __devexit spi_gpio_remove(struct platform_device *pdev)
{
struct spi_gpio *spi_gpio;
struct spi_gpio_platform_data *pdata;
@@ -408,21 +408,10 @@ MODULE_ALIAS("platform:" DRIVER_NAME);
static struct platform_driver spi_gpio_driver = {
.driver.name = DRIVER_NAME,
.driver.owner = THIS_MODULE,
- .remove = __exit_p(spi_gpio_remove),
+ .probe = spi_gpio_probe,
+ .remove = __devexit_p(spi_gpio_remove),
};
-
-static int __init spi_gpio_init(void)
-{
- return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe);
-}
-module_init(spi_gpio_init);
-
-static void __exit spi_gpio_exit(void)
-{
- platform_driver_unregister(&spi_gpio_driver);
-}
-module_exit(spi_gpio_exit);
-
+module_platform_driver(spi_gpio_driver);
MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
MODULE_AUTHOR("David Brownell");
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index fa594d604aca..c6e697f5e007 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -929,19 +929,7 @@ static struct platform_driver spi_imx_driver = {
.probe = spi_imx_probe,
.remove = __devexit_p(spi_imx_remove),
};
-
-static int __init spi_imx_init(void)
-{
- return platform_driver_register(&spi_imx_driver);
-}
-
-static void __exit spi_imx_exit(void)
-{
- platform_driver_unregister(&spi_imx_driver);
-}
-
-module_init(spi_imx_init);
-module_exit(spi_imx_exit);
+module_platform_driver(spi_imx_driver);
MODULE_DESCRIPTION("SPI Master Controller driver");
MODULE_AUTHOR("Sascha Hauer, Pengutronix");
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 6a5b4238fb6b..4c63f772780a 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -559,18 +559,7 @@ static struct platform_driver mpc512x_psc_spi_of_driver = {
.of_match_table = mpc512x_psc_spi_of_match,
},
};
-
-static int __init mpc512x_psc_spi_init(void)
-{
- return platform_driver_register(&mpc512x_psc_spi_of_driver);
-}
-module_init(mpc512x_psc_spi_init);
-
-static void __exit mpc512x_psc_spi_exit(void)
-{
- platform_driver_unregister(&mpc512x_psc_spi_of_driver);
-}
-module_exit(mpc512x_psc_spi_exit);
+module_platform_driver(mpc512x_psc_spi_of_driver);
MODULE_AUTHOR("John Rigby");
MODULE_DESCRIPTION("MPC512x PSC SPI Driver");
diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c
index e30baf0852ac..66047156d90d 100644
--- a/drivers/spi/spi-mpc52xx-psc.c
+++ b/drivers/spi/spi-mpc52xx-psc.c
@@ -511,18 +511,7 @@ static struct platform_driver mpc52xx_psc_spi_of_driver = {
.of_match_table = mpc52xx_psc_spi_of_match,
},
};
-
-static int __init mpc52xx_psc_spi_init(void)
-{
- return platform_driver_register(&mpc52xx_psc_spi_of_driver);
-}
-module_init(mpc52xx_psc_spi_init);
-
-static void __exit mpc52xx_psc_spi_exit(void)
-{
- platform_driver_unregister(&mpc52xx_psc_spi_of_driver);
-}
-module_exit(mpc52xx_psc_spi_exit);
+module_platform_driver(mpc52xx_psc_spi_of_driver);
MODULE_AUTHOR("Dragos Carp");
MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c
index 015a974bed72..57633d963456 100644
--- a/drivers/spi/spi-mpc52xx.c
+++ b/drivers/spi/spi-mpc52xx.c
@@ -564,16 +564,4 @@ static struct platform_driver mpc52xx_spi_of_driver = {
.probe = mpc52xx_spi_probe,
.remove = __devexit_p(mpc52xx_spi_remove),
};
-
-static int __init mpc52xx_spi_init(void)
-{
- return platform_driver_register(&mpc52xx_spi_of_driver);
-}
-module_init(mpc52xx_spi_init);
-
-static void __exit mpc52xx_spi_exit(void)
-{
- platform_driver_unregister(&mpc52xx_spi_of_driver);
-}
-module_exit(mpc52xx_spi_exit);
-
+module_platform_driver(mpc52xx_spi_of_driver);
diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c
index c0a6ce81f9c0..e763254741c2 100644
--- a/drivers/spi/spi-nuc900.c
+++ b/drivers/spi/spi-nuc900.c
@@ -484,19 +484,7 @@ static struct platform_driver nuc900_spi_driver = {
.owner = THIS_MODULE,
},
};
-
-static int __init nuc900_spi_init(void)
-{
- return platform_driver_register(&nuc900_spi_driver);
-}
-
-static void __exit nuc900_spi_exit(void)
-{
- platform_driver_unregister(&nuc900_spi_driver);
-}
-
-module_init(nuc900_spi_init);
-module_exit(nuc900_spi_exit);
+module_platform_driver(nuc900_spi_driver);
MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
MODULE_DESCRIPTION("nuc900 spi driver!");
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
index f1bde66cea19..897274e8715c 100644
--- a/drivers/spi/spi-oc-tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
@@ -406,18 +406,7 @@ static struct platform_driver tiny_spi_driver = {
.of_match_table = tiny_spi_match,
},
};
-
-static int __init tiny_spi_init(void)
-{
- return platform_driver_register(&tiny_spi_driver);
-}
-module_init(tiny_spi_init);
-
-static void __exit tiny_spi_exit(void)
-{
- platform_driver_unregister(&tiny_spi_driver);
-}
-module_exit(tiny_spi_exit);
+module_platform_driver(tiny_spi_driver);
MODULE_DESCRIPTION("OpenCores tiny SPI driver");
MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index fde3a2d4f120..322be7aea8b4 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -1116,15 +1116,16 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
status = -ENODEV;
goto err1;
}
+
+ r->start += pdata->regs_offset;
+ r->end += pdata->regs_offset;
+ mcspi->phys = r->start;
if (!request_mem_region(r->start, resource_size(r),
dev_name(&pdev->dev))) {
status = -EBUSY;
goto err1;
}
- r->start += pdata->regs_offset;
- r->end += pdata->regs_offset;
- mcspi->phys = r->start;
mcspi->base = ioremap(r->start, resource_size(r));
if (!mcspi->base) {
dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 730b4a37b823..f103e470cb63 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -113,7 +113,6 @@
#define SSP_CR0_MASK_CSS_ST (0x1FUL << 16)
#define SSP_CR0_MASK_FRF_ST (0x3UL << 21)
-
/*
* SSP Control Register 0 - SSP_CR1
*/
@@ -283,7 +282,6 @@
#define SPI_POLLING_TIMEOUT 1000
-
/*
* The type of reading going on on this chip
*/
@@ -515,9 +513,6 @@ static void giveback(struct pl022 *pl022)
if (msg->complete)
msg->complete(msg->context);
/* This message is completed, so let's turn off the clocks & power */
- clk_disable(pl022->clk);
- amba_pclk_disable(pl022->adev);
- amba_vcore_disable(pl022->adev);
pm_runtime_put(&pl022->adev->dev);
}
@@ -752,7 +747,6 @@ static void readwriter(struct pl022 *pl022)
*/
}
-
/**
* next_transfer - Move to the Next transfer in the current spi message
* @pl022: SSP driver private data structure
@@ -1019,14 +1013,14 @@ static int configure_dma(struct pl022 *pl022)
dmaengine_slave_config(txchan, &tx_conf);
/* Create sglists for the transfers */
- pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1;
+ pages = DIV_ROUND_UP(pl022->cur_transfer->len, PAGE_SIZE);
dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
- ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_KERNEL);
+ ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_ATOMIC);
if (ret)
goto err_alloc_rx_sg;
- ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_KERNEL);
+ ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_ATOMIC);
if (ret)
goto err_alloc_tx_sg;
@@ -1534,8 +1528,7 @@ static void pump_messages(struct work_struct *work)
/* Initial message state */
pl022->cur_msg->state = STATE_START;
pl022->cur_transfer = list_entry(pl022->cur_msg->transfers.next,
- struct spi_transfer,
- transfer_list);
+ struct spi_transfer, transfer_list);
/* Setup the SPI using the per chip configuration */
pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
@@ -1545,9 +1538,6 @@ static void pump_messages(struct work_struct *work)
* (poll/interrupt/DMA)
*/
pm_runtime_get_sync(&pl022->adev->dev);
- amba_vcore_enable(pl022->adev);
- amba_pclk_enable(pl022->adev);
- clk_enable(pl022->clk);
restore_state(pl022);
flush(pl022);
@@ -1557,7 +1547,6 @@ static void pump_messages(struct work_struct *work)
do_interrupt_dma_transfer(pl022);
}
-
static int __init init_queue(struct pl022 *pl022)
{
INIT_LIST_HEAD(&pl022->queue);
@@ -1566,8 +1555,8 @@ static int __init init_queue(struct pl022 *pl022)
pl022->running = false;
pl022->busy = false;
- tasklet_init(&pl022->pump_transfers,
- pump_transfers, (unsigned long)pl022);
+ tasklet_init(&pl022->pump_transfers, pump_transfers,
+ (unsigned long)pl022);
INIT_WORK(&pl022->pump_messages, pump_messages);
pl022->workqueue = create_singlethread_workqueue(
@@ -1578,7 +1567,6 @@ static int __init init_queue(struct pl022 *pl022)
return 0;
}
-
static int start_queue(struct pl022 *pl022)
{
unsigned long flags;
@@ -1601,7 +1589,6 @@ static int start_queue(struct pl022 *pl022)
return 0;
}
-
static int stop_queue(struct pl022 *pl022)
{
unsigned long flags;
@@ -1797,71 +1784,70 @@ static int pl022_transfer(struct spi_device *spi, struct spi_message *msg)
return 0;
}
-static int calculate_effective_freq(struct pl022 *pl022,
- int freq,
- struct ssp_clock_params *clk_freq)
+static inline u32 spi_rate(u32 rate, u16 cpsdvsr, u16 scr)
+{
+ return rate / (cpsdvsr * (1 + scr));
+}
+
+static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
+ ssp_clock_params * clk_freq)
{
/* Lets calculate the frequency parameters */
- u16 cpsdvsr = 2;
- u16 scr = 0;
- bool freq_found = false;
- u32 rate;
- u32 max_tclk;
- u32 min_tclk;
+ u16 cpsdvsr = CPSDVR_MIN, scr = SCR_MIN;
+ u32 rate, max_tclk, min_tclk, best_freq = 0, best_cpsdvsr = 0,
+ best_scr = 0, tmp, found = 0;
rate = clk_get_rate(pl022->clk);
/* cpsdvscr = 2 & scr 0 */
- max_tclk = (rate / (CPSDVR_MIN * (1 + SCR_MIN)));
+ max_tclk = spi_rate(rate, CPSDVR_MIN, SCR_MIN);
/* cpsdvsr = 254 & scr = 255 */
- min_tclk = (rate / (CPSDVR_MAX * (1 + SCR_MAX)));
-
- if ((freq <= max_tclk) && (freq >= min_tclk)) {
- while (cpsdvsr <= CPSDVR_MAX && !freq_found) {
- while (scr <= SCR_MAX && !freq_found) {
- if ((rate /
- (cpsdvsr * (1 + scr))) > freq)
- scr += 1;
- else {
- /*
- * This bool is made true when
- * effective frequency >=
- * target frequency is found
- */
- freq_found = true;
- if ((rate /
- (cpsdvsr * (1 + scr))) != freq) {
- if (scr == SCR_MIN) {
- cpsdvsr -= 2;
- scr = SCR_MAX;
- } else
- scr -= 1;
- }
- }
- }
- if (!freq_found) {
- cpsdvsr += 2;
- scr = SCR_MIN;
- }
- }
- if (cpsdvsr != 0) {
- dev_dbg(&pl022->adev->dev,
- "SSP Effective Frequency is %u\n",
- (rate / (cpsdvsr * (1 + scr))));
- clk_freq->cpsdvsr = (u8) (cpsdvsr & 0xFF);
- clk_freq->scr = (u8) (scr & 0xFF);
- dev_dbg(&pl022->adev->dev,
- "SSP cpsdvsr = %d, scr = %d\n",
- clk_freq->cpsdvsr, clk_freq->scr);
- }
- } else {
+ min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
+
+ if (!((freq <= max_tclk) && (freq >= min_tclk))) {
dev_err(&pl022->adev->dev,
"controller data is incorrect: out of range frequency");
return -EINVAL;
}
+
+ /*
+ * best_freq will give closest possible available rate (<= requested
+ * freq) for all values of scr & cpsdvsr.
+ */
+ while ((cpsdvsr <= CPSDVR_MAX) && !found) {
+ while (scr <= SCR_MAX) {
+ tmp = spi_rate(rate, cpsdvsr, scr);
+
+ if (tmp > freq)
+ scr++;
+ /*
+ * If found exact value, update and break.
+ * If found more closer value, update and continue.
+ */
+ else if ((tmp == freq) || (tmp > best_freq)) {
+ best_freq = tmp;
+ best_cpsdvsr = cpsdvsr;
+ best_scr = scr;
+
+ if (tmp == freq)
+ break;
+ }
+ scr++;
+ }
+ cpsdvsr += 2;
+ scr = SCR_MIN;
+ }
+
+ clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
+ clk_freq->scr = (u8) (best_scr & 0xFF);
+ dev_dbg(&pl022->adev->dev,
+ "SSP Target Frequency is: %u, Effective Frequency is %u\n",
+ freq, best_freq);
+ dev_dbg(&pl022->adev->dev, "SSP cpsdvsr = %d, scr = %d\n",
+ clk_freq->cpsdvsr, clk_freq->scr);
+
return 0;
}
-
/*
* A piece of default chip info unless the platform
* supplies it.
@@ -1879,7 +1865,6 @@ static const struct pl022_config_chip pl022_default_chip_info = {
.cs_control = null_cs_control,
};
-
/**
* pl022_setup - setup function registered to SPI master framework
* @spi: spi device which is requesting setup
@@ -1956,7 +1941,6 @@ static int pl022_setup(struct spi_device *spi)
goto err_config_params;
}
-
status = verify_controller_parameters(pl022, chip_info);
if (status) {
dev_err(&spi->dev, "controller data is incorrect");
@@ -2096,7 +2080,8 @@ static int pl022_setup(struct spi_device *spi)
}
SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
- SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3);
+ SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD,
+ 3);
/* Save controller_state */
spi_set_ctldata(spi, chip);
@@ -2122,7 +2107,6 @@ static void pl022_cleanup(struct spi_device *spi)
kfree(chip);
}
-
static int __devinit
pl022_probe(struct amba_device *adev, const struct amba_id *id)
{
@@ -2186,8 +2170,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
}
printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
adev->res.start, pl022->virtbase);
- pm_runtime_enable(dev);
- pm_runtime_resume(dev);
pl022->clk = clk_get(&adev->dev, NULL);
if (IS_ERR(pl022->clk)) {
@@ -2196,6 +2178,12 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
goto err_no_clk;
}
+ status = clk_prepare(pl022->clk);
+ if (status) {
+ dev_err(&adev->dev, "could not prepare SSP/SPI bus clock\n");
+ goto err_clk_prep;
+ }
+
/* Disable SSP */
writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
SSP_CR1(pl022->virtbase));
@@ -2235,22 +2223,22 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
goto err_spi_register;
}
dev_dbg(dev, "probe succeeded\n");
- /*
- * Disable the silicon block pclk and any voltage domain and just
- * power it up and clock it when it's needed
- */
- amba_pclk_disable(adev);
- amba_vcore_disable(adev);
+
+ /* let runtime pm put suspend */
+ pm_runtime_put(dev);
return 0;
err_spi_register:
err_start_queue:
err_init_queue:
destroy_queue(pl022);
- pl022_dma_remove(pl022);
+ if (platform_info->enable_dma)
+ pl022_dma_remove(pl022);
+
free_irq(adev->irq[0], pl022);
- pm_runtime_disable(&adev->dev);
err_no_irq:
+ clk_unprepare(pl022->clk);
+ err_clk_prep:
clk_put(pl022->clk);
err_no_clk:
iounmap(pl022->virtbase);
@@ -2271,13 +2259,22 @@ pl022_remove(struct amba_device *adev)
if (!pl022)
return 0;
+ /*
+ * undo pm_runtime_put() in probe. I assume that we're not
+ * accessing the primecell here.
+ */
+ pm_runtime_get_noresume(&adev->dev);
+
/* Remove the queue */
if (destroy_queue(pl022) != 0)
dev_err(&adev->dev, "queue remove failed\n");
load_ssp_default_config(pl022);
- pl022_dma_remove(pl022);
+ if (pl022->master_info->enable_dma)
+ pl022_dma_remove(pl022);
+
free_irq(adev->irq[0], pl022);
clk_disable(pl022->clk);
+ clk_unprepare(pl022->clk);
clk_put(pl022->clk);
iounmap(pl022->virtbase);
amba_release_regions(adev);
@@ -2288,46 +2285,70 @@ pl022_remove(struct amba_device *adev)
return 0;
}
-#ifdef CONFIG_PM
-static int pl022_suspend(struct amba_device *adev, pm_message_t state)
+#ifdef CONFIG_SUSPEND
+static int pl022_suspend(struct device *dev)
{
- struct pl022 *pl022 = amba_get_drvdata(adev);
+ struct pl022 *pl022 = dev_get_drvdata(dev);
int status = 0;
status = stop_queue(pl022);
if (status) {
- dev_warn(&adev->dev, "suspend cannot stop queue\n");
+ dev_warn(dev, "suspend cannot stop queue\n");
return status;
}
- amba_vcore_enable(adev);
- amba_pclk_enable(adev);
+ amba_vcore_enable(pl022->adev);
+ amba_pclk_enable(pl022->adev);
load_ssp_default_config(pl022);
- amba_pclk_disable(adev);
- amba_vcore_disable(adev);
- dev_dbg(&adev->dev, "suspended\n");
+ amba_pclk_disable(pl022->adev);
+ amba_vcore_disable(pl022->adev);
+ dev_dbg(dev, "suspended\n");
return 0;
}
-static int pl022_resume(struct amba_device *adev)
+static int pl022_resume(struct device *dev)
{
- struct pl022 *pl022 = amba_get_drvdata(adev);
+ struct pl022 *pl022 = dev_get_drvdata(dev);
int status = 0;
/* Start the queue running */
status = start_queue(pl022);
if (status)
- dev_err(&adev->dev, "problem starting queue (%d)\n", status);
+ dev_err(dev, "problem starting queue (%d)\n", status);
else
- dev_dbg(&adev->dev, "resumed\n");
+ dev_dbg(dev, "resumed\n");
return status;
}
-#else
-#define pl022_suspend NULL
-#define pl022_resume NULL
#endif /* CONFIG_PM */
+#ifdef CONFIG_PM_RUNTIME
+static int pl022_runtime_suspend(struct device *dev)
+{
+ struct pl022 *pl022 = dev_get_drvdata(dev);
+
+ clk_disable(pl022->clk);
+ amba_vcore_disable(pl022->adev);
+
+ return 0;
+}
+
+static int pl022_runtime_resume(struct device *dev)
+{
+ struct pl022 *pl022 = dev_get_drvdata(dev);
+
+ amba_vcore_enable(pl022->adev);
+ clk_enable(pl022->clk);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops pl022_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume)
+ SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL)
+};
+
static struct vendor_data vendor_arm = {
.fifodepth = 8,
.max_bpw = 16,
@@ -2337,7 +2358,6 @@ static struct vendor_data vendor_arm = {
.loopback = true,
};
-
static struct vendor_data vendor_st = {
.fifodepth = 32,
.max_bpw = 32,
@@ -2392,9 +2412,9 @@ static struct amba_id pl022_ids[] = {
* and 32 locations deep TX/RX FIFO but no extended
* CR0/CR1 register
*/
- .id = 0x00080023,
- .mask = 0xffffffff,
- .data = &vendor_st_pl023,
+ .id = 0x00080023,
+ .mask = 0xffffffff,
+ .data = &vendor_st_pl023,
},
{
.id = 0x10080023,
@@ -2407,27 +2427,23 @@ static struct amba_id pl022_ids[] = {
static struct amba_driver pl022_driver = {
.drv = {
.name = "ssp-pl022",
+ .pm = &pl022_dev_pm_ops,
},
.id_table = pl022_ids,
.probe = pl022_probe,
.remove = __devexit_p(pl022_remove),
- .suspend = pl022_suspend,
- .resume = pl022_resume,
};
-
static int __init pl022_init(void)
{
return amba_driver_register(&pl022_driver);
}
-
subsys_initcall(pl022_init);
static void __exit pl022_exit(void)
{
amba_driver_unregister(&pl022_driver);
}
-
module_exit(pl022_exit);
MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c
index b267fd901e54..98ec53285fc7 100644
--- a/drivers/spi/spi-ppc4xx.c
+++ b/drivers/spi/spi-ppc4xx.c
@@ -514,7 +514,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op)
/* Request IRQ */
hw->irqnum = irq_of_parse_and_map(np, 0);
ret = request_irq(hw->irqnum, spi_ppc4xx_int,
- IRQF_DISABLED, "spi_ppc4xx_of", (void *)hw);
+ 0, "spi_ppc4xx_of", (void *)hw);
if (ret) {
dev_err(dev, "unable to allocate interrupt\n");
goto free_gpios;
@@ -594,18 +594,7 @@ static struct platform_driver spi_ppc4xx_of_driver = {
.of_match_table = spi_ppc4xx_of_match,
},
};
-
-static int __init spi_ppc4xx_init(void)
-{
- return platform_driver_register(&spi_ppc4xx_of_driver);
-}
-module_init(spi_ppc4xx_init);
-
-static void __exit spi_ppc4xx_exit(void)
-{
- platform_driver_unregister(&spi_ppc4xx_of_driver);
-}
-module_exit(spi_ppc4xx_exit);
+module_platform_driver(spi_ppc4xx_of_driver);
MODULE_AUTHOR("Gary Jennejohn & Stefan Roese");
MODULE_DESCRIPTION("Simple PPC4xx SPI Driver");
diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index 1996ac57ef91..b857a3e7af94 100644
--- a/drivers/spi/spi-s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -505,7 +505,7 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
}
}
-static int __init s3c24xx_spi_probe(struct platform_device *pdev)
+static int __devinit s3c24xx_spi_probe(struct platform_device *pdev)
{
struct s3c2410_spi_info *pdata;
struct s3c24xx_spi *hw;
@@ -661,7 +661,7 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev)
return err;
}
-static int __exit s3c24xx_spi_remove(struct platform_device *dev)
+static int __devexit s3c24xx_spi_remove(struct platform_device *dev)
{
struct s3c24xx_spi *hw = platform_get_drvdata(dev);
@@ -719,26 +719,15 @@ static const struct dev_pm_ops s3c24xx_spi_pmops = {
MODULE_ALIAS("platform:s3c2410-spi");
static struct platform_driver s3c24xx_spi_driver = {
- .remove = __exit_p(s3c24xx_spi_remove),
+ .probe = s3c24xx_spi_probe,
+ .remove = __devexit_p(s3c24xx_spi_remove),
.driver = {
.name = "s3c2410-spi",
.owner = THIS_MODULE,
.pm = S3C24XX_SPI_PMOPS,
},
};
-
-static int __init s3c24xx_spi_init(void)
-{
- return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe);
-}
-
-static void __exit s3c24xx_spi_exit(void)
-{
- platform_driver_unregister(&s3c24xx_spi_driver);
-}
-
-module_init(s3c24xx_spi_init);
-module_exit(s3c24xx_spi_exit);
+module_platform_driver(s3c24xx_spi_driver);
MODULE_DESCRIPTION("S3C24XX SPI Driver");
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index e00d94b22250..0f4834ae28cd 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -635,7 +635,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
goto err2;
}
- ret = request_irq(i, sh_msiof_spi_irq, IRQF_DISABLED,
+ ret = request_irq(i, sh_msiof_spi_irq, 0,
dev_name(&pdev->dev), p);
if (ret) {
dev_err(&pdev->dev, "unable to request irq\n");
@@ -730,18 +730,7 @@ static struct platform_driver sh_msiof_spi_drv = {
.pm = &sh_msiof_spi_dev_pm_ops,
},
};
-
-static int __init sh_msiof_spi_init(void)
-{
- return platform_driver_register(&sh_msiof_spi_drv);
-}
-module_init(sh_msiof_spi_init);
-
-static void __exit sh_msiof_spi_exit(void)
-{
- platform_driver_unregister(&sh_msiof_spi_drv);
-}
-module_exit(sh_msiof_spi_exit);
+module_platform_driver(sh_msiof_spi_drv);
MODULE_DESCRIPTION("SuperH MSIOF SPI Master Interface Driver");
MODULE_AUTHOR("Magnus Damm");
diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c
index e7779c09f6ef..8844bc342782 100644
--- a/drivers/spi/spi-sh-sci.c
+++ b/drivers/spi/spi-sh-sci.c
@@ -186,18 +186,7 @@ static struct platform_driver sh_sci_spi_drv = {
.owner = THIS_MODULE,
},
};
-
-static int __init sh_sci_spi_init(void)
-{
- return platform_driver_register(&sh_sci_spi_drv);
-}
-module_init(sh_sci_spi_init);
-
-static void __exit sh_sci_spi_exit(void)
-{
- platform_driver_unregister(&sh_sci_spi_drv);
-}
-module_exit(sh_sci_spi_exit);
+module_platform_driver(sh_sci_spi_drv);
MODULE_DESCRIPTION("SH SCI SPI Driver");
MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c
index 9eedd71ad898..70c8af9f7ccc 100644
--- a/drivers/spi/spi-sh.c
+++ b/drivers/spi/spi-sh.c
@@ -484,7 +484,7 @@ static int __devinit spi_sh_probe(struct platform_device *pdev)
goto error2;
}
- ret = request_irq(irq, spi_sh_irq, IRQF_DISABLED, "spi_sh", ss);
+ ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss);
if (ret < 0) {
dev_err(&pdev->dev, "request_irq error\n");
goto error3;
@@ -524,18 +524,7 @@ static struct platform_driver spi_sh_driver = {
.owner = THIS_MODULE,
},
};
-
-static int __init spi_sh_init(void)
-{
- return platform_driver_register(&spi_sh_driver);
-}
-module_init(spi_sh_init);
-
-static void __exit spi_sh_exit(void)
-{
- platform_driver_unregister(&spi_sh_driver);
-}
-module_exit(spi_sh_exit);
+module_platform_driver(spi_sh_driver);
MODULE_DESCRIPTION("SH SPI bus driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-stmp.c b/drivers/spi/spi-stmp.c
index fadff76eb7e0..58e385285323 100644
--- a/drivers/spi/spi-stmp.c
+++ b/drivers/spi/spi-stmp.c
@@ -659,19 +659,8 @@ static struct platform_driver stmp_spi_driver = {
.suspend = stmp_spi_suspend,
.resume = stmp_spi_resume,
};
+module_platform_driver(stmp_spi_driver);
-static int __init stmp_spi_init(void)
-{
- return platform_driver_register(&stmp_spi_driver);
-}
-
-static void __exit stmp_spi_exit(void)
-{
- platform_driver_unregister(&stmp_spi_driver);
-}
-
-module_init(stmp_spi_init);
-module_exit(stmp_spi_exit);
module_param(pio, int, S_IRUGO);
module_param(clock, int, S_IRUGO);
MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>");
diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c
index a5a6302dc8e0..ae6d78a3e912 100644
--- a/drivers/spi/spi-tegra.c
+++ b/drivers/spi/spi-tegra.c
@@ -18,6 +18,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/platform_device.h>
@@ -464,7 +465,7 @@ static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m)
return 0;
}
-static int __init spi_tegra_probe(struct platform_device *pdev)
+static int __devinit spi_tegra_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct spi_tegra_data *tspi;
@@ -612,19 +613,9 @@ static struct platform_driver spi_tegra_driver = {
.owner = THIS_MODULE,
.of_match_table = spi_tegra_of_match_table,
},
+ .probe = spi_tegra_probe,
.remove = __devexit_p(spi_tegra_remove),
};
-
-static int __init spi_tegra_init(void)
-{
- return platform_driver_probe(&spi_tegra_driver, spi_tegra_probe);
-}
-module_init(spi_tegra_init);
-
-static void __exit spi_tegra_exit(void)
-{
- platform_driver_unregister(&spi_tegra_driver);
-}
-module_exit(spi_tegra_exit);
+module_platform_driver(spi_tegra_driver);
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-ti-ssp.c b/drivers/spi/spi-ti-ssp.c
index ee22795c7973..7963c60063d6 100644
--- a/drivers/spi/spi-ti-ssp.c
+++ b/drivers/spi/spi-ti-ssp.c
@@ -383,18 +383,7 @@ static struct platform_driver ti_ssp_spi_driver = {
.owner = THIS_MODULE,
},
};
-
-static int __init ti_ssp_spi_init(void)
-{
- return platform_driver_register(&ti_ssp_spi_driver);
-}
-module_init(ti_ssp_spi_init);
-
-static void __exit ti_ssp_spi_exit(void)
-{
- platform_driver_unregister(&ti_ssp_spi_driver);
-}
-module_exit(ti_ssp_spi_exit);
+module_platform_driver(ti_ssp_spi_driver);
MODULE_DESCRIPTION("SSP SPI Master");
MODULE_AUTHOR("Cyril Chemparathy");
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 4d2c75df886c..4c5a663b9fa8 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -538,18 +538,7 @@ static struct platform_driver xilinx_spi_driver = {
.of_match_table = xilinx_spi_of_match,
},
};
-
-static int __init xilinx_spi_pltfm_init(void)
-{
- return platform_driver_register(&xilinx_spi_driver);
-}
-module_init(xilinx_spi_pltfm_init);
-
-static void __exit xilinx_spi_pltfm_exit(void)
-{
- platform_driver_unregister(&xilinx_spi_driver);
-}
-module_exit(xilinx_spi_pltfm_exit);
+module_platform_driver(xilinx_spi_driver);
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("Xilinx SPI driver");
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 29c7d4f9d1ae..d0cbdb0cf9d5 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -1260,16 +1260,34 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)
}
EXPORT_SYMBOL(ssb_device_disable);
+/* Some chipsets need routing known for PCIe and 64-bit DMA */
+static bool ssb_dma_translation_special_bit(struct ssb_device *dev)
+{
+ u16 chip_id = dev->bus->chip_id;
+
+ if (dev->id.coreid == SSB_DEV_80211) {
+ return (chip_id == 0x4322 || chip_id == 43221 ||
+ chip_id == 43231 || chip_id == 43222);
+ }
+
+ return 0;
+}
+
u32 ssb_dma_translation(struct ssb_device *dev)
{
switch (dev->bus->bustype) {
case SSB_BUSTYPE_SSB:
return 0;
case SSB_BUSTYPE_PCI:
- if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)
+ if (pci_is_pcie(dev->bus->host_pci) &&
+ ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64) {
return SSB_PCIE_DMA_H32;
- else
- return SSB_PCI_DMA;
+ } else {
+ if (ssb_dma_translation_special_bit(dev))
+ return SSB_PCIE_DMA_H32;
+ else
+ return SSB_PCI_DMA;
+ }
default:
__ssb_dma_not_implemented(dev);
}
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 06c9081d596d..d132c27dfb3f 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -24,6 +24,8 @@ menuconfig STAGING
if STAGING
+source "drivers/staging/serial/Kconfig"
+
source "drivers/staging/et131x/Kconfig"
source "drivers/staging/slicoss/Kconfig"
@@ -32,8 +34,6 @@ source "drivers/staging/go7007/Kconfig"
source "drivers/staging/cx25821/Kconfig"
-source "drivers/staging/tm6000/Kconfig"
-
source "drivers/staging/cxd2099/Kconfig"
source "drivers/staging/usbip/Kconfig"
@@ -44,8 +44,6 @@ source "drivers/staging/wlan-ng/Kconfig"
source "drivers/staging/echo/Kconfig"
-source "drivers/staging/brcm80211/Kconfig"
-
source "drivers/staging/comedi/Kconfig"
source "drivers/staging/olpc_dcon/Kconfig"
@@ -64,6 +62,8 @@ source "drivers/staging/rtl8712/Kconfig"
source "drivers/staging/rts_pstor/Kconfig"
+source "drivers/staging/rts5139/Kconfig"
+
source "drivers/staging/frontier/Kconfig"
source "drivers/staging/pohmelfs/Kconfig"
@@ -72,8 +72,6 @@ source "drivers/staging/phison/Kconfig"
source "drivers/staging/line6/Kconfig"
-source "drivers/gpu/drm/vmwgfx/Kconfig"
-
source "drivers/gpu/drm/nouveau/Kconfig"
source "drivers/staging/octeon/Kconfig"
@@ -126,8 +124,6 @@ source "drivers/staging/quickstart/Kconfig"
source "drivers/staging/sbe-2t3e3/Kconfig"
-source "drivers/staging/ath6kl/Kconfig"
-
source "drivers/staging/keucr/Kconfig"
source "drivers/staging/bcm/Kconfig"
@@ -144,8 +140,6 @@ source "drivers/staging/ste_rmi4/Kconfig"
source "drivers/staging/gma500/Kconfig"
-source "drivers/staging/altera-stapl/Kconfig"
-
source "drivers/staging/mei/Kconfig"
source "drivers/staging/nvec/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index f3c5e33bb263..936b7c22e18e 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -3,19 +3,17 @@
# fix for build system bug...
obj-$(CONFIG_STAGING) += staging.o
+obj-y += serial/
obj-$(CONFIG_ET131X) += et131x/
obj-$(CONFIG_SLICOSS) += slicoss/
obj-$(CONFIG_VIDEO_GO7007) += go7007/
obj-$(CONFIG_VIDEO_CX25821) += cx25821/
-obj-$(CONFIG_VIDEO_TM6000) += tm6000/
obj-$(CONFIG_DVB_CXD2099) += cxd2099/
obj-$(CONFIG_LIRC_STAGING) += lirc/
obj-$(CONFIG_USBIP_CORE) += usbip/
obj-$(CONFIG_W35UND) += winbond/
obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_ECHO) += echo/
-obj-$(CONFIG_BRCMSMAC) += brcm80211/
-obj-$(CONFIG_BRCMFMAC) += brcm80211/
obj-$(CONFIG_COMEDI) += comedi/
obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
obj-$(CONFIG_ASUS_OLED) += asus_oled/
@@ -25,6 +23,7 @@ obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_R8712U) += rtl8712/
obj-$(CONFIG_RTS_PSTOR) += rts_pstor/
+obj-$(CONFIG_RTS5139) += rts5139/
obj-$(CONFIG_SPECTRA) += spectra/
obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_POHMELFS) += pohmelfs/
@@ -54,13 +53,11 @@ obj-$(CONFIG_SOLO6X10) += solo6x10/
obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/
obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/
obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/
-obj-$(CONFIG_ATH6K_LEGACY) += ath6kl/
obj-$(CONFIG_USB_ENESTORAGE) += keucr/
obj-$(CONFIG_BCM_WIMAX) += bcm/
obj-$(CONFIG_FT1000) += ft1000/
obj-$(CONFIG_SND_INTEL_SST) += intel_sst/
obj-$(CONFIG_SPEAKUP) += speakup/
-obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
obj-$(CONFIG_DRM_PSB) += gma500/
diff --git a/drivers/staging/altera-stapl/Makefile b/drivers/staging/altera-stapl/Makefile
deleted file mode 100644
index ddeede3c4b96..000000000000
--- a/drivers/staging/altera-stapl/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-altera-stapl-y := altera-lpt.o altera-jtag.o altera-comp.o altera.o
-
-obj-$(CONFIG_ALTERA_STAPL) += altera-stapl.o
diff --git a/drivers/staging/ath6kl/Kconfig b/drivers/staging/ath6kl/Kconfig
deleted file mode 100644
index afd6cc16a2b8..000000000000
--- a/drivers/staging/ath6kl/Kconfig
+++ /dev/null
@@ -1,158 +0,0 @@
-config ATH6K_LEGACY
- tristate "Atheros AR6003 support (non mac80211)"
- depends on MMC && WLAN
- depends on CFG80211
- select WIRELESS_EXT
- select WEXT_PRIV
- help
- This module adds support for wireless adapters based on Atheros AR6003 chipset running over SDIO. If you choose to build it as a module, it will be called ath6kl. Pls note that AR6002 and AR6001 are not supported by this driver.
-
-choice
- prompt "AR6003 Board Data Configuration"
- depends on ATH6K_LEGACY
- default AR600x_SD31_XXX
- help
- Select the appropriate board data template from the list below that matches your AR6003 based reference design.
-
-config AR600x_SD31_XXX
- bool "SD31-xxx"
- help
- Board Data file for a standard SD31 reference design (File: bdata.SD31.bin)
-
-config AR600x_WB31_XXX
- bool "WB31-xxx"
- help
- Board Data file for a standard WB31 (BT/WiFi) reference design (File: bdata.WB31.bin)
-
-config AR600x_SD32_XXX
- bool "SD32-xxx"
- help
- Board Data file for a standard SD32 (5GHz) reference design (File: bdata.SD32.bin)
-
-config AR600x_CUSTOM_XXX
- bool "CUSTOM-xxx"
- help
- Board Data file for a custom reference design (File: should be named as bdata.CUSTOM.bin)
-endchoice
-
-config ATH6KL_ENABLE_COEXISTENCE
- bool "BT Coexistence support"
- depends on ATH6K_LEGACY
- help
- Enables WLAN/BT coexistence support. Select the apprpriate configuration from below.
-
-choice
- prompt "Front-End Antenna Configuration"
- depends on ATH6KL_ENABLE_COEXISTENCE
- default AR600x_DUAL_ANTENNA
- help
- Indicates the number of antennas being used by BT and WLAN. Select the appropriate configuration from the list below that matches your AR6003 based reference design.
-
-config AR600x_DUAL_ANTENNA
- bool "Dual Antenna"
- help
- Dual Antenna Design
-
-config AR600x_SINGLE_ANTENNA
- bool "Single Antenna"
- help
- Single Antenna Design
-endchoice
-
-choice
- prompt "Collocated Bluetooth Type"
- depends on ATH6KL_ENABLE_COEXISTENCE
- default AR600x_BT_AR3001
- help
- Select the appropriate configuration from the list below that matches your AR6003 based reference design.
-
-config AR600x_BT_QCOM
- bool "Qualcomm BTS4020X"
- help
- Qualcomm BT (3 Wire PTA)
-
-config AR600x_BT_CSR
- bool "CSR BC06"
- help
- CSR BT (3 Wire PTA)
-
-config AR600x_BT_AR3001
- bool "Atheros AR3001"
- help
- Atheros BT (3 Wire PTA)
-endchoice
-
-config ATH6KL_HCI_BRIDGE
- bool "HCI over SDIO support"
- depends on ATH6K_LEGACY
- help
- Enables BT over SDIO. Applicable only for combo designs (eg: WB31)
-
-config ATH6KL_CONFIG_GPIO_BT_RESET
- bool "Configure BT Reset GPIO"
- depends on ATH6KL_HCI_BRIDGE
- help
- Configure a WLAN GPIO for use with BT.
-
-config AR600x_BT_RESET_PIN
- int "GPIO"
- depends on ATH6KL_CONFIG_GPIO_BT_RESET
- default 22
- help
- WLAN GPIO to be used for resetting BT
-
-config ATH6KL_HTC_RAW_INTERFACE
- bool "RAW HTC support"
- depends on ATH6K_LEGACY
- help
- Enables raw HTC interface. Allows application to directly talk to the HTC interface via the ioctl interface
-
-config ATH6KL_VIRTUAL_SCATTER_GATHER
- bool "Virtual Scatter-Gather support"
- depends on ATH6K_LEGACY
- help
- Enables virtual scatter gather support for the hardware that does not support it natively.
-
-config ATH6KL_SKIP_ABI_VERSION_CHECK
- bool "Skip ABI version check support"
- depends on ATH6K_LEGACY
- help
- Forces the driver to disable ABI version check. Caution: Incompatilbity between the host driver and target firmware may lead to unknown side effects.
-
-config ATH6KL_BT_UART_FC_POLARITY
- int "UART Flow Control Polarity"
- depends on ATH6KL_LEGACY
- default 0
- help
- Configures the polarity of UART Flow Control. A value of 0 implies active low and is the default setting. Set it to 1 for active high.
-
-config ATH6KL_DEBUG
- bool "Debug support"
- depends on ATH6K_LEGACY
- help
- Enables debug support
-
-config ATH6KL_ENABLE_HOST_DEBUG
- bool "Host Debug support"
- depends on ATH6KL_DEBUG
- help
- Enables debug support in the driver
-
-config ATH6KL_ENABLE_TARGET_DEBUG_PRINTS
- bool "Target Debug support - Enable UART prints"
- depends on ATH6KL_DEBUG
- help
- Enables uart prints
-
-config AR600x_DEBUG_UART_TX_PIN
- int "GPIO"
- depends on ATH6KL_ENABLE_TARGET_DEBUG_PRINTS
- default 8
- help
- WLAN GPIO to be used for Debug UART (Tx)
-
-config ATH6KL_DISABLE_TARGET_DBGLOGS
- bool "Target Debug support - Disable Debug logs"
- depends on ATH6KL_DEBUG
- help
- Enables debug logs
diff --git a/drivers/staging/ath6kl/Makefile b/drivers/staging/ath6kl/Makefile
deleted file mode 100644
index 1d3f2390a172..000000000000
--- a/drivers/staging/ath6kl/Makefile
+++ /dev/null
@@ -1,122 +0,0 @@
-#------------------------------------------------------------------------------
-# Copyright (c) 2004-2010 Atheros Communications Inc.
-# All rights reserved.
-#
-#
-#
-# 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.
-#
-#
-#
-# Author(s): ="Atheros"
-#------------------------------------------------------------------------------
-
-ccflags-y += -I$(obj)/include
-ccflags-y += -I$(obj)/include/common
-ccflags-y += -I$(obj)/wlan/include
-ccflags-y += -I$(obj)/os/linux/include
-ccflags-y += -I$(obj)/os
-ccflags-y += -I$(obj)/bmi/include
-ccflags-y += -I$(obj)/include/common/AR6002/hw4.0
-
-ifeq ($(CONFIG_AR600x_DUAL_ANTENNA),y)
-ccflags-y += -DAR600x_DUAL_ANTENNA
-endif
-
-ifeq ($(CONFIG_AR600x_SINGLE_ANTENNA),y)
-ccflags-y += -DAR600x_SINGLE_ANTENNA
-endif
-
-ifeq ($(CONFIG_AR600x_BT_QCOM),y)
-ccflags-y += -DAR600x_BT_QCOM
-endif
-
-ifeq ($(CONFIG_AR600x_BT_CSR),y)
-ccflags-y += -DAR600x_BT_CSR
-endif
-
-ifeq ($(CONFIG_AR600x_BT_AR3001),y)
-ccflags-y += -DAR600x_BT_AR3001
-endif
-
-ifeq ($(CONFIG_ATH6KL_HCI_BRIDGE),y)
-ccflags-y += -DATH_AR6K_ENABLE_GMBOX
-ccflags-y += -DHCI_TRANSPORT_SDIO
-ccflags-y += -DSETUPHCI_ENABLED
-ccflags-y += -DSETUPBTDEV_ENABLED
-ath6kl-y += htc2/AR6000/ar6k_gmbox.o
-ath6kl-y += htc2/AR6000/ar6k_gmbox_hciuart.o
-ath6kl-y += miscdrv/ar3kconfig.o
-ath6kl-y += miscdrv/ar3kps/ar3kpsconfig.o
-ath6kl-y += miscdrv/ar3kps/ar3kpsparser.o
-endif
-
-ifeq ($(CONFIG_ATH6KL_CONFIG_GPIO_BT_RESET),y)
-ccflags-y += -DATH6KL_CONFIG_GPIO_BT_RESET
-endif
-
-ifeq ($(CONFIG_ATH6KL_HTC_RAW_INTERFACE),y)
-ccflags-y += -DHTC_RAW_INTERFACE
-endif
-
-ifeq ($(CONFIG_ATH6KL_ENABLE_HOST_DEBUG),y)
-ccflags-y += -DDEBUG
-ccflags-y += -DATH_DEBUG_MODULE
-endif
-
-ifeq ($(CONFIG_ATH6KL_ENABLE_TARGET_DEBUG_PRINTS),y)
-ccflags-y += -DENABLEUARTPRINT_SET
-endif
-
-ifeq ($(CONFIG_ATH6KL_DISABLE_TARGET_DBGLOGS),y)
-ccflags-y += -DATH6KL_DISABLE_TARGET_DBGLOGS
-endif
-
-ifeq ($(CONFIG_ATH6KL_VIRTUAL_SCATTER_GATHER),y)
-ccflags-y += -DATH6KL_CONFIG_HIF_VIRTUAL_SCATTER
-endif
-
-ifeq ($(CONFIG_ATH6KL_SKIP_ABI_VERSION_CHECK),y)
-ccflags-y += -DATH6KL_SKIP_ABI_VERSION_CHECK
-endif
-
-ccflags-y += -DWAPI_ENABLE
-ccflags-y += -DCHECKSUM_OFFLOAD
-
-obj-$(CONFIG_ATH6K_LEGACY) := ath6kl.o
-ath6kl-y += htc2/AR6000/ar6k.o
-ath6kl-y += htc2/AR6000/ar6k_events.o
-ath6kl-y += htc2/htc_send.o
-ath6kl-y += htc2/htc_recv.o
-ath6kl-y += htc2/htc_services.o
-ath6kl-y += htc2/htc.o
-ath6kl-y += bmi/src/bmi.o
-ath6kl-y += os/linux/cfg80211.o
-ath6kl-y += os/linux/ar6000_drv.o
-ath6kl-y += os/linux/ar6000_raw_if.o
-ath6kl-y += os/linux/ar6000_pm.o
-ath6kl-y += os/linux/netbuf.o
-ath6kl-y += os/linux/hci_bridge.o
-ath6kl-y += miscdrv/common_drv.o
-ath6kl-y += miscdrv/credit_dist.o
-ath6kl-y += wmi/wmi.o
-ath6kl-y += reorder/rcv_aggr.o
-ath6kl-y += wlan/src/wlan_node.o
-ath6kl-y += wlan/src/wlan_recv_beacon.o
-ath6kl-y += wlan/src/wlan_utils.o
-
-# ATH_HIF_TYPE := sdio
-ccflags-y += -I$(obj)/hif/sdio/linux_sdio/include
-ccflags-y += -DSDIO
-ath6kl-y += hif/sdio/linux_sdio/src/hif.o
-ath6kl-y += hif/sdio/linux_sdio/src/hif_scatter.o
diff --git a/drivers/staging/ath6kl/TODO b/drivers/staging/ath6kl/TODO
deleted file mode 100644
index 7be4b46ebb59..000000000000
--- a/drivers/staging/ath6kl/TODO
+++ /dev/null
@@ -1,25 +0,0 @@
-TODO:
-
-We are working hard on cleaning up the driver. There's sooooooooo much todo
-so instead of editing this file please use the wiki:
-
-http://wireless.kernel.org/en/users/Drivers/ath6kl
-
-There's a respective TODO page there. Please also subscribe to the wiki page
-to get e-mail updates on changes.
-
-IRC:
-
-We *really* need to coordinate development for ath6kl as the cleanup
-patches will break pretty much any other patches. Please use IRC to
-help coordinate better:
-
-irc.freenode.net
-#ath6kl
-
-Send patches to:
-
- - Greg Kroah-Hartman <greg@kroah.com>
- - Luis R. Rodriguez <mcgrof@gmail.com>
- - Joe Perches <joe@perches.com>
- - Naveen Singh <nsingh@atheros.com>
diff --git a/drivers/staging/ath6kl/bmi/include/bmi_internal.h b/drivers/staging/ath6kl/bmi/include/bmi_internal.h
deleted file mode 100644
index 8e2577074d65..000000000000
--- a/drivers/staging/ath6kl/bmi/include/bmi_internal.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef BMI_INTERNAL_H
-#define BMI_INTERNAL_H
-
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_osapi.h"
-#define ATH_MODULE_NAME bmi
-#include "a_debug.h"
-#include "hw/mbox_host_reg.h"
-#include "bmi_msg.h"
-
-#define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0)
-
-
-#define BMI_COMMUNICATION_TIMEOUT 100000
-
-/* ------ Global Variable Declarations ------- */
-static bool bmiDone;
-
-int
-bmiBufferSend(struct hif_device *device,
- u8 *buffer,
- u32 length);
-
-int
-bmiBufferReceive(struct hif_device *device,
- u8 *buffer,
- u32 length,
- bool want_timeout);
-
-#endif
diff --git a/drivers/staging/ath6kl/bmi/src/bmi.c b/drivers/staging/ath6kl/bmi/src/bmi.c
deleted file mode 100644
index f1f085eba9c8..000000000000
--- a/drivers/staging/ath6kl/bmi/src/bmi.c
+++ /dev/null
@@ -1,1010 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="bmi.c" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-
-#ifdef THREAD_X
-#include <string.h>
-#endif
-
-#include "hif.h"
-#include "bmi.h"
-#include "htc_api.h"
-#include "bmi_internal.h"
-
-#ifdef ATH_DEBUG_MODULE
-static struct ath_debug_mask_description bmi_debug_desc[] = {
- { ATH_DEBUG_BMI , "BMI Tracing"},
-};
-
-ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi,
- "bmi",
- "Boot Manager Interface",
- ATH_DEBUG_MASK_DEFAULTS,
- ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc),
- bmi_debug_desc);
-
-#endif
-
-/*
-Although we had envisioned BMI to run on top of HTC, this is not how the
-final implementation ended up. On the Target side, BMI is a part of the BSP
-and does not use the HTC protocol nor even DMA -- it is intentionally kept
-very simple.
-*/
-
-static bool pendingEventsFuncCheck = false;
-static u32 *pBMICmdCredits;
-static u8 *pBMICmdBuf;
-#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
- sizeof(u32) /* cmd */ + \
- sizeof(u32) /* addr */ + \
- sizeof(u32))/* length */
-#define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ)
-
-/* APIs visible to the driver */
-void
-BMIInit(void)
-{
- bmiDone = false;
- pendingEventsFuncCheck = false;
-
- /*
- * On some platforms, it's not possible to DMA to a static variable
- * in a device driver (e.g. Linux loadable driver module).
- * So we need to A_MALLOC space for "command credits" and for commands.
- *
- * Note: implicitly relies on A_MALLOC to provide a buffer that is
- * suitable for DMA (or PIO). This buffer will be passed down the
- * bus stack.
- */
- if (!pBMICmdCredits) {
- pBMICmdCredits = (u32 *)A_MALLOC_NOWAIT(4);
- A_ASSERT(pBMICmdCredits);
- }
-
- if (!pBMICmdBuf) {
- pBMICmdBuf = (u8 *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
- A_ASSERT(pBMICmdBuf);
- }
-
- A_REGISTER_MODULE_DEBUG_INFO(bmi);
-}
-
-void
-BMICleanup(void)
-{
- if (pBMICmdCredits) {
- kfree(pBMICmdCredits);
- pBMICmdCredits = NULL;
- }
-
- if (pBMICmdBuf) {
- kfree(pBMICmdBuf);
- pBMICmdBuf = NULL;
- }
-}
-
-int
-BMIDone(struct hif_device *device)
-{
- int status;
- u32 cid;
-
- if (bmiDone) {
- AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
- return 0;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
- bmiDone = true;
- cid = BMI_DONE;
-
- status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
-
- if (pBMICmdCredits) {
- kfree(pBMICmdCredits);
- pBMICmdCredits = NULL;
- }
-
- if (pBMICmdBuf) {
- kfree(pBMICmdBuf);
- pBMICmdBuf = NULL;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
-
- return 0;
-}
-
-int
-BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info)
-{
- int status;
- u32 cid;
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
- cid = BMI_GET_TARGET_INFO;
-
- status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
-
- status = bmiBufferReceive(device, (u8 *)&targ_info->target_ver,
- sizeof(targ_info->target_ver), true);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
- return A_ERROR;
- }
-
- if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
- /* Determine how many bytes are in the Target's targ_info */
- status = bmiBufferReceive(device, (u8 *)&targ_info->target_info_byte_count,
- sizeof(targ_info->target_info_byte_count), true);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
- return A_ERROR;
- }
-
- /*
- * The Target's targ_info doesn't match the Host's targ_info.
- * We need to do some backwards compatibility work to make this OK.
- */
- A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info));
-
- /* Read the remainder of the targ_info */
- status = bmiBufferReceive(device,
- ((u8 *)targ_info)+sizeof(targ_info->target_info_byte_count),
- sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), true);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
- targ_info->target_info_byte_count));
- return A_ERROR;
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
- targ_info->target_ver, targ_info->target_type));
-
- return 0;
-}
-
-int
-BMIReadMemory(struct hif_device *device,
- u32 address,
- u8 *buffer,
- u32 length)
-{
- u32 cid;
- int status;
- u32 offset;
- u32 remaining, rxlen;
-
- A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)));
- memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length));
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
- device, address, length));
-
- cid = BMI_READ_MEMORY;
-
- remaining = length;
-
- while (remaining)
- {
- rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
- offset += sizeof(address);
- memcpy(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
- offset += sizeof(length);
-
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
- status = bmiBufferReceive(device, pBMICmdBuf, rxlen, true);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
- return A_ERROR;
- }
- memcpy(&buffer[length - remaining], pBMICmdBuf, rxlen);
- remaining -= rxlen; address += rxlen;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
- return 0;
-}
-
-int
-BMIWriteMemory(struct hif_device *device,
- u32 address,
- u8 *buffer,
- u32 length)
-{
- u32 cid;
- int status;
- u32 offset;
- u32 remaining, txlen;
- const u32 header = sizeof(cid) + sizeof(address) + sizeof(length);
- u8 alignedBuffer[BMI_DATASZ_MAX];
- u8 *src;
-
- A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header));
- memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header);
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
- device, address, length));
-
- cid = BMI_WRITE_MEMORY;
-
- remaining = length;
- while (remaining)
- {
- src = &buffer[length - remaining];
- if (remaining < (BMI_DATASZ_MAX - header)) {
- if (remaining & 3) {
- /* align it with 4 bytes */
- remaining = remaining + (4 - (remaining & 3));
- memcpy(alignedBuffer, src, remaining);
- src = alignedBuffer;
- }
- txlen = remaining;
- } else {
- txlen = (BMI_DATASZ_MAX - header);
- }
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
- offset += sizeof(address);
- memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
- offset += sizeof(txlen);
- memcpy(&(pBMICmdBuf[offset]), src, txlen);
- offset += txlen;
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
- remaining -= txlen; address += txlen;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
-
- return 0;
-}
-
-int
-BMIExecute(struct hif_device *device,
- u32 address,
- u32 *param)
-{
- u32 cid;
- int status;
- u32 offset;
-
- A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
- memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
- device, address, *param));
-
- cid = BMI_EXECUTE;
-
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
- offset += sizeof(address);
- memcpy(&(pBMICmdBuf[offset]), param, sizeof(*param));
- offset += sizeof(*param);
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
-
- status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), false);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
- return A_ERROR;
- }
-
- memcpy(param, pBMICmdBuf, sizeof(*param));
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
- return 0;
-}
-
-int
-BMISetAppStart(struct hif_device *device,
- u32 address)
-{
- u32 cid;
- int status;
- u32 offset;
-
- A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
- memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
- device, address));
-
- cid = BMI_SET_APP_START;
-
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
- offset += sizeof(address);
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n"));
- return 0;
-}
-
-int
-BMIReadSOCRegister(struct hif_device *device,
- u32 address,
- u32 *param)
-{
- u32 cid;
- int status;
- u32 offset;
-
- A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
- memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
- device, address));
-
- cid = BMI_READ_SOC_REGISTER;
-
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
- offset += sizeof(address);
-
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
-
- status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), true);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
- return A_ERROR;
- }
- memcpy(param, pBMICmdBuf, sizeof(*param));
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
- return 0;
-}
-
-int
-BMIWriteSOCRegister(struct hif_device *device,
- u32 address,
- u32 param)
-{
- u32 cid;
- int status;
- u32 offset;
-
- A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
- memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
- device, address, param));
-
- cid = BMI_WRITE_SOC_REGISTER;
-
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
- offset += sizeof(address);
- memcpy(&(pBMICmdBuf[offset]), &param, sizeof(param));
- offset += sizeof(param);
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
- return 0;
-}
-
-int
-BMIrompatchInstall(struct hif_device *device,
- u32 ROM_addr,
- u32 RAM_addr,
- u32 nbytes,
- u32 do_activate,
- u32 *rompatch_id)
-{
- u32 cid;
- int status;
- u32 offset;
-
- A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
- sizeof(nbytes) + sizeof(do_activate)));
- memset(pBMICmdBuf, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
- sizeof(nbytes) + sizeof(do_activate));
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n",
- device, ROM_addr, RAM_addr, nbytes, do_activate));
-
- cid = BMI_ROMPATCH_INSTALL;
-
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
- offset += sizeof(ROM_addr);
- memcpy(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
- offset += sizeof(RAM_addr);
- memcpy(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
- offset += sizeof(nbytes);
- memcpy(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
- offset += sizeof(do_activate);
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
-
- status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), true);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
- return A_ERROR;
- }
- memcpy(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id));
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
- return 0;
-}
-
-int
-BMIrompatchUninstall(struct hif_device *device,
- u32 rompatch_id)
-{
- u32 cid;
- int status;
- u32 offset;
-
- A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id)));
- memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id));
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n",
- device, rompatch_id));
-
- cid = BMI_ROMPATCH_UNINSTALL;
-
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
- offset += sizeof(rompatch_id);
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
- return 0;
-}
-
-static int
-_BMIrompatchChangeActivation(struct hif_device *device,
- u32 rompatch_count,
- u32 *rompatch_list,
- u32 do_activate)
-{
- u32 cid;
- int status;
- u32 offset;
- u32 length;
-
- A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)));
- memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n",
- device, rompatch_count));
-
- cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
-
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
- offset += sizeof(rompatch_count);
- length = rompatch_count * sizeof(*rompatch_list);
- memcpy(&(pBMICmdBuf[offset]), rompatch_list, length);
- offset += length;
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
-
- return 0;
-}
-
-int
-BMIrompatchActivate(struct hif_device *device,
- u32 rompatch_count,
- u32 *rompatch_list)
-{
- return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
-}
-
-int
-BMIrompatchDeactivate(struct hif_device *device,
- u32 rompatch_count,
- u32 *rompatch_list)
-{
- return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
-}
-
-int
-BMILZData(struct hif_device *device,
- u8 *buffer,
- u32 length)
-{
- u32 cid;
- int status;
- u32 offset;
- u32 remaining, txlen;
- const u32 header = sizeof(cid) + sizeof(length);
-
- A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header));
- memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header);
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI Send LZ Data: Enter (device: 0x%p, length: %d)\n",
- device, length));
-
- cid = BMI_LZ_DATA;
-
- remaining = length;
- while (remaining)
- {
- txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
- remaining : (BMI_DATASZ_MAX - header);
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
- offset += sizeof(txlen);
- memcpy(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
- offset += txlen;
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
- return A_ERROR;
- }
- remaining -= txlen;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n"));
-
- return 0;
-}
-
-int
-BMILZStreamStart(struct hif_device *device,
- u32 address)
-{
- u32 cid;
- int status;
- u32 offset;
-
- A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
- memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
-
- if (bmiDone) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
- ("BMI LZ Stream Start: Enter (device: 0x%p, address: 0x%x)\n",
- device, address));
-
- cid = BMI_LZ_STREAM_START;
- offset = 0;
- memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
- offset += sizeof(cid);
- memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
- offset += sizeof(address);
- status = bmiBufferSend(device, pBMICmdBuf, offset);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n"));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n"));
-
- return 0;
-}
-
-/* BMI Access routines */
-int
-bmiBufferSend(struct hif_device *device,
- u8 *buffer,
- u32 length)
-{
- int status;
- u32 timeout;
- u32 address;
- u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
-
- HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
- &mboxAddress[0], sizeof(mboxAddress));
-
- *pBMICmdCredits = 0;
- timeout = BMI_COMMUNICATION_TIMEOUT;
-
- while(timeout-- && !(*pBMICmdCredits)) {
- /* Read the counter register to get the command credits */
- address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
- /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
- * a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to
- * make all HIF accesses 4-byte aligned */
- status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, 4,
- HIF_RD_SYNC_BYTE_INC, NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
- return A_ERROR;
- }
- /* the counter is only 8=bits, ignore anything in the upper 3 bytes */
- (*pBMICmdCredits) &= 0xFF;
- }
-
- if (*pBMICmdCredits) {
- address = mboxAddress[ENDPOINT1];
- status = HIFReadWrite(device, address, buffer, length,
- HIF_WR_SYNC_BYTE_INC, NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
- return A_ERROR;
- }
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n"));
- return A_ERROR;
- }
-
- return status;
-}
-
-int
-bmiBufferReceive(struct hif_device *device,
- u8 *buffer,
- u32 length,
- bool want_timeout)
-{
- int status;
- u32 address;
- u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
- struct hif_pending_events_info hifPendingEvents;
- static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL;
-
- if (!pendingEventsFuncCheck) {
- /* see if the HIF layer implements an alternative function to get pending events
- * do this only once! */
- HIFConfigureDevice(device,
- HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
- &getPendingEventsFunc,
- sizeof(getPendingEventsFunc));
- pendingEventsFuncCheck = true;
- }
-
- HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
- &mboxAddress[0], sizeof(mboxAddress));
-
- /*
- * During normal bootup, small reads may be required.
- * Rather than issue an HIF Read and then wait as the Target
- * adds successive bytes to the FIFO, we wait here until
- * we know that response data is available.
- *
- * This allows us to cleanly timeout on an unexpected
- * Target failure rather than risk problems at the HIF level. In
- * particular, this avoids SDIO timeouts and possibly garbage
- * data on some host controllers. And on an interconnect
- * such as Compact Flash (as well as some SDIO masters) which
- * does not provide any indication on data timeout, it avoids
- * a potential hang or garbage response.
- *
- * Synchronization is more difficult for reads larger than the
- * size of the MBOX FIFO (128B), because the Target is unable
- * to push the 129th byte of data until AFTER the Host posts an
- * HIF Read and removes some FIFO data. So for large reads the
- * Host proceeds to post an HIF Read BEFORE all the data is
- * actually available to read. Fortunately, large BMI reads do
- * not occur in practice -- they're supported for debug/development.
- *
- * So Host/Target BMI synchronization is divided into these cases:
- * CASE 1: length < 4
- * Should not happen
- *
- * CASE 2: 4 <= length <= 128
- * Wait for first 4 bytes to be in FIFO
- * If CONSERVATIVE_BMI_READ is enabled, also wait for
- * a BMI command credit, which indicates that the ENTIRE
- * response is available in the the FIFO
- *
- * CASE 3: length > 128
- * Wait for the first 4 bytes to be in FIFO
- *
- * For most uses, a small timeout should be sufficient and we will
- * usually see a response quickly; but there may be some unusual
- * (debug) cases of BMI_EXECUTE where we want an larger timeout.
- * For now, we use an unbounded busy loop while waiting for
- * BMI_EXECUTE.
- *
- * If BMI_EXECUTE ever needs to support longer-latency execution,
- * especially in production, this code needs to be enhanced to sleep
- * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently
- * a function of Host processor speed.
- */
- if (length >= 4) { /* NB: Currently, always true */
- /*
- * NB: word_available is declared static for esoteric reasons
- * having to do with protection on some OSes.
- */
- static u32 word_available;
- u32 timeout;
-
- word_available = 0;
- timeout = BMI_COMMUNICATION_TIMEOUT;
- while((!want_timeout || timeout--) && !word_available) {
-
- if (getPendingEventsFunc != NULL) {
- status = getPendingEventsFunc(device,
- &hifPendingEvents,
- NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n"));
- break;
- }
-
- if (hifPendingEvents.AvailableRecvBytes >= sizeof(u32)) {
- word_available = 1;
- }
- continue;
- }
-
- status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&word_available,
- sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n"));
- return A_ERROR;
- }
- /* We did a 4-byte read to the same register; all we really want is one bit */
- word_available &= (1 << ENDPOINT1);
- }
-
- if (!word_available) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n"));
- return A_ERROR;
- }
- }
-
-#define CONSERVATIVE_BMI_READ 0
-#if CONSERVATIVE_BMI_READ
- /*
- * This is an extra-conservative CREDIT check. It guarantees
- * that ALL data is available in the FIFO before we start to
- * read from the interconnect.
- *
- * This credit check is useless when firmware chooses to
- * allow multiple outstanding BMI Command Credits, since the next
- * credit will already be present. To restrict the Target to one
- * BMI Command Credit, see HI_OPTION_BMI_CRED_LIMIT.
- *
- * And for large reads (when HI_OPTION_BMI_CRED_LIMIT is set)
- * we cannot wait for the next credit because the Target's FIFO
- * will not hold the entire response. So we need the Host to
- * start to empty the FIFO sooner. (And again, large reads are
- * not used in practice; they are for debug/development only.)
- *
- * For a more conservative Host implementation (which would be
- * safer for a Compact Flash interconnect):
- * Set CONSERVATIVE_BMI_READ (above) to 1
- * Set HI_OPTION_BMI_CRED_LIMIT and
- * reduce BMI_DATASZ_MAX to 32 or 64
- */
- if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */
- u32 timeout;
-
- *pBMICmdCredits = 0;
- timeout = BMI_COMMUNICATION_TIMEOUT;
- while((!want_timeout || timeout--) && !(*pBMICmdCredits) {
- /* Read the counter register to get the command credits */
- address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
- /* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing,
- * we can read this counter multiple times using a non-incrementing address mode.
- * The rationale here is to make all HIF accesses a multiple of 4 bytes */
- status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
- HIF_RD_SYNC_BYTE_FIX, NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
- return A_ERROR;
- }
- /* we did a 4-byte read to the same count register so mask off upper bytes */
- (*pBMICmdCredits) &= 0xFF;
- }
-
- if (!(*pBMICmdCredits)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n"));
- return A_ERROR;
- }
- }
-#endif
-
- address = mboxAddress[ENDPOINT1];
- status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
- return A_ERROR;
- }
-
- return 0;
-}
-
-int
-BMIFastDownload(struct hif_device *device, u32 address, u8 *buffer, u32 length)
-{
- int status = A_ERROR;
- u32 lastWord = 0;
- u32 lastWordOffset = length & ~0x3;
- u32 unalignedBytes = length & 0x3;
-
- status = BMILZStreamStart (device, address);
- if (status) {
- return A_ERROR;
- }
-
- if (unalignedBytes) {
- /* copy the last word into a zero padded buffer */
- memcpy(&lastWord, &buffer[lastWordOffset], unalignedBytes);
- }
-
- status = BMILZData(device, buffer, lastWordOffset);
-
- if (status) {
- return A_ERROR;
- }
-
- if (unalignedBytes) {
- status = BMILZData(device, (u8 *)&lastWord, 4);
- }
-
- if (!status) {
- //
- // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches.
- //
- status = BMILZStreamStart (device, 0x00);
- if (status) {
- return A_ERROR;
- }
- }
- return status;
-}
-
-int
-BMIRawWrite(struct hif_device *device, u8 *buffer, u32 length)
-{
- return bmiBufferSend(device, buffer, length);
-}
-
-int
-BMIRawRead(struct hif_device *device, u8 *buffer, u32 length, bool want_timeout)
-{
- return bmiBufferReceive(device, buffer, length, want_timeout);
-}
diff --git a/drivers/staging/ath6kl/hif/common/hif_sdio_common.h b/drivers/staging/ath6kl/hif/common/hif_sdio_common.h
deleted file mode 100644
index 93a2adceca33..000000000000
--- a/drivers/staging/ath6kl/hif/common/hif_sdio_common.h
+++ /dev/null
@@ -1,87 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// common header file for HIF modules designed for SDIO
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef HIF_SDIO_COMMON_H_
-#define HIF_SDIO_COMMON_H_
-
- /* SDIO manufacturer ID and Codes */
-#define MANUFACTURER_ID_AR6002_BASE 0x200
-#define MANUFACTURER_ID_AR6003_BASE 0x300
-#define MANUFACTURER_ID_AR6K_BASE_MASK 0xFF00
-#define FUNCTION_CLASS 0x0
-#define MANUFACTURER_CODE 0x271 /* Atheros */
-
- /* Mailbox address in SDIO address space */
-#define HIF_MBOX_BASE_ADDR 0x800
-#define HIF_MBOX_WIDTH 0x800
-#define HIF_MBOX_START_ADDR(mbox) \
- ( HIF_MBOX_BASE_ADDR + mbox * HIF_MBOX_WIDTH)
-
-#define HIF_MBOX_END_ADDR(mbox) \
- (HIF_MBOX_START_ADDR(mbox) + HIF_MBOX_WIDTH - 1)
-
- /* extended MBOX address for larger MBOX writes to MBOX 0*/
-#define HIF_MBOX0_EXTENDED_BASE_ADDR 0x2800
-#define HIF_MBOX0_EXTENDED_WIDTH_AR6002 (6*1024)
-#define HIF_MBOX0_EXTENDED_WIDTH_AR6003 (18*1024)
-
- /* version 1 of the chip has only a 12K extended mbox range */
-#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1 0x4000
-#define HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1 (12*1024)
-
- /* GMBOX addresses */
-#define HIF_GMBOX_BASE_ADDR 0x7000
-#define HIF_GMBOX_WIDTH 0x4000
-
- /* for SDIO we recommend a 128-byte block size */
-#define HIF_DEFAULT_IO_BLOCK_SIZE 128
-
- /* set extended MBOX window information for SDIO interconnects */
-static INLINE void SetExtendedMboxWindowInfo(u16 Manfid, struct hif_device_mbox_info *pInfo)
-{
- switch (Manfid & MANUFACTURER_ID_AR6K_BASE_MASK) {
- case MANUFACTURER_ID_AR6002_BASE :
- /* MBOX 0 has an extended range */
- pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR;
- pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6002;
- break;
- case MANUFACTURER_ID_AR6003_BASE :
- /* MBOX 0 has an extended range */
- pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
- pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
- pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR;
- pInfo->GMboxSize = HIF_GMBOX_WIDTH;
- break;
- default:
- A_ASSERT(false);
- break;
- }
-}
-
-/* special CCCR (func 0) registers */
-
-#define CCCR_SDIO_IRQ_MODE_REG 0xF0 /* interrupt mode register */
-#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ (1 << 0) /* mode to enable special 4-bit interrupt assertion without clock*/
-
-#endif /*HIF_SDIO_COMMON_H_*/
diff --git a/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h b/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h
deleted file mode 100644
index ed7ad4786f5a..000000000000
--- a/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h
+++ /dev/null
@@ -1,131 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="hif_internal.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// internal header file for hif layer
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _HIF_INTERNAL_H_
-#define _HIF_INTERNAL_H_
-
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_osapi.h"
-#include "hif.h"
-#include "../../../common/hif_sdio_common.h"
-#include <linux/scatterlist.h>
-#define HIF_LINUX_MMC_SCATTER_SUPPORT
-
-#define BUS_REQUEST_MAX_NUM 64
-
-#define SDIO_CLOCK_FREQUENCY_DEFAULT 25000000
-#define SDWLAN_ENABLE_DISABLE_TIMEOUT 20
-#define FLAGS_CARD_ENAB 0x02
-#define FLAGS_CARD_IRQ_UNMSK 0x04
-
-#define HIF_MBOX_BLOCK_SIZE HIF_DEFAULT_IO_BLOCK_SIZE
-#define HIF_MBOX0_BLOCK_SIZE 1
-#define HIF_MBOX1_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
-#define HIF_MBOX2_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
-#define HIF_MBOX3_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
-
-typedef struct bus_request {
- struct bus_request *next; /* link list of available requests */
- struct bus_request *inusenext; /* link list of in use requests */
- struct semaphore sem_req;
- u32 address; /* request data */
- u8 *buffer;
- u32 length;
- u32 request;
- void *context;
- int status;
- struct hif_scatter_req_priv *pScatterReq; /* this request is a scatter request */
-} BUS_REQUEST;
-
-struct hif_device {
- struct sdio_func *func;
- spinlock_t asynclock;
- struct task_struct* async_task; /* task to handle async commands */
- struct semaphore sem_async; /* wake up for async task */
- int async_shutdown; /* stop the async task */
- struct completion async_completion; /* thread completion */
- BUS_REQUEST *asyncreq; /* request for async tasklet */
- BUS_REQUEST *taskreq; /* async tasklet data */
- spinlock_t lock;
- BUS_REQUEST *s_busRequestFreeQueue; /* free list */
- BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM]; /* available bus requests */
- void *claimedContext;
- HTC_CALLBACKS htcCallbacks;
- u8 *dma_buffer;
- struct dl_list ScatterReqHead; /* scatter request list head */
- bool scatter_enabled; /* scatter enabled flag */
- bool is_suspend;
- bool is_disabled;
- atomic_t irqHandling;
- HIF_DEVICE_POWER_CHANGE_TYPE powerConfig;
- const struct sdio_device_id *id;
-};
-
-#define HIF_DMA_BUFFER_SIZE (32 * 1024)
-#define CMD53_FIXED_ADDRESS 1
-#define CMD53_INCR_ADDRESS 2
-
-BUS_REQUEST *hifAllocateBusRequest(struct hif_device *device);
-void hifFreeBusRequest(struct hif_device *device, BUS_REQUEST *busrequest);
-void AddToAsyncList(struct hif_device *device, BUS_REQUEST *busrequest);
-
-#ifdef HIF_LINUX_MMC_SCATTER_SUPPORT
-
-#define MAX_SCATTER_REQUESTS 4
-#define MAX_SCATTER_ENTRIES_PER_REQ 16
-#define MAX_SCATTER_REQ_TRANSFER_SIZE 32*1024
-
-struct hif_scatter_req_priv {
- struct hif_scatter_req *pHifScatterReq; /* HIF scatter request with allocated entries */
- struct hif_device *device; /* this device */
- BUS_REQUEST *busrequest; /* request associated with request */
- /* scatter list for linux */
- struct scatterlist sgentries[MAX_SCATTER_ENTRIES_PER_REQ];
-};
-
-#define ATH_DEBUG_SCATTER ATH_DEBUG_MAKE_MODULE_MASK(0)
-
-int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo);
-void CleanupHIFScatterResources(struct hif_device *device);
-int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest);
-
-#else // HIF_LINUX_MMC_SCATTER_SUPPORT
-
-static inline int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo)
-{
- return A_ENOTSUP;
-}
-
-static inline int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest)
-{
- return A_ENOTSUP;
-}
-
-#define CleanupHIFScatterResources(d) { }
-
-#endif // HIF_LINUX_MMC_SCATTER_SUPPORT
-
-#endif // _HIF_INTERNAL_H_
-
diff --git a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
deleted file mode 100644
index 5f5d67720fa4..000000000000
--- a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="hif.c" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// HIF layer reference implementation for Linux Native MMC stack
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#include <linux/mmc/card.h>
-#include <linux/mmc/mmc.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/sd.h>
-#include <linux/kthread.h>
-
-/* by default setup a bounce buffer for the data packets, if the underlying host controller driver
- does not use DMA you may be able to skip this step and save the memory allocation and transfer time */
-#define HIF_USE_DMA_BOUNCE_BUFFER 1
-#include "hif_internal.h"
-#define ATH_MODULE_NAME hif
-#include "a_debug.h"
-#include "hw/mbox_host_reg.h"
-
-#if HIF_USE_DMA_BOUNCE_BUFFER
-/* macro to check if DMA buffer is WORD-aligned and DMA-able. Most host controllers assume the
- * buffer is DMA'able and will bug-check otherwise (i.e. buffers on the stack).
- * virt_addr_valid check fails on stack memory.
- */
-#define BUFFER_NEEDS_BOUNCE(buffer) (((unsigned long)(buffer) & 0x3) || !virt_addr_valid((buffer)))
-#else
-#define BUFFER_NEEDS_BOUNCE(buffer) (false)
-#endif
-
-/* ATHENV */
-#if defined(CONFIG_PM)
-#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)
-#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv)
-#endif /* CONFIG_PM */
-static void delHifDevice(struct hif_device * device);
-static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte);
-static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte);
-
-static int hifEnableFunc(struct hif_device *device, struct sdio_func *func);
-static int hifDisableFunc(struct hif_device *device, struct sdio_func *func);
-OSDRV_CALLBACKS osdrvCallbacks;
-
-int reset_sdio_on_unload = 0;
-module_param(reset_sdio_on_unload, int, 0644);
-
-extern u32 nohifscattersupport;
-
-static struct hif_device *ath6kl_alloc_hifdev(struct sdio_func *func)
-{
- struct hif_device *hifdevice;
-
- hifdevice = kzalloc(sizeof(struct hif_device), GFP_KERNEL);
-
-#if HIF_USE_DMA_BOUNCE_BUFFER
- hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL);
-#endif
- hifdevice->func = func;
- hifdevice->powerConfig = HIF_DEVICE_POWER_UP;
- sdio_set_drvdata(func, hifdevice);
-
- return hifdevice;
-}
-
-static struct hif_device *ath6kl_get_hifdev(struct sdio_func *func)
-{
- return (struct hif_device *) sdio_get_drvdata(func);
-}
-
-static const struct sdio_device_id ath6kl_hifdev_ids[] = {
- { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x0)) },
- { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x1)) },
- { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0)) },
- { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1)) },
- { /* null */ },
-};
-
-MODULE_DEVICE_TABLE(sdio, ath6kl_hifdev_ids);
-
-static int ath6kl_hifdev_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
-{
- int ret;
- struct hif_device *device;
- int count;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
- ("ath6kl: Function: 0x%X, Vendor ID: 0x%X, "
- "Device ID: 0x%X, block size: 0x%X/0x%X\n",
- func->num, func->vendor, func->device,
- func->max_blksize, func->cur_blksize));
-
- ath6kl_alloc_hifdev(func);
- device = ath6kl_get_hifdev(func);
-
- device->id = id;
- device->is_disabled = true;
-
- spin_lock_init(&device->lock);
- spin_lock_init(&device->asynclock);
-
- DL_LIST_INIT(&device->ScatterReqHead);
-
- /* Try to allow scatter unless globally overridden */
- if (!nohifscattersupport)
- device->scatter_enabled = true;
-
- A_MEMZERO(device->busRequest, sizeof(device->busRequest));
-
- for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) {
- sema_init(&device->busRequest[count].sem_req, 0);
- hifFreeBusRequest(device, &device->busRequest[count]);
- }
-
- sema_init(&device->sem_async, 0);
-
- ret = hifEnableFunc(device, func);
-
- return ret;
-}
-
-static void ath6kl_hifdev_remove(struct sdio_func *func)
-{
- int status = 0;
- struct hif_device *device;
-
- device = ath6kl_get_hifdev(func);
- if (device->claimedContext != NULL)
- status = osdrvCallbacks.
- deviceRemovedHandler(device->claimedContext, device);
-
- if (device->is_disabled)
- device->is_disabled = false;
- else
- status = hifDisableFunc(device, func);
-
- CleanupHIFScatterResources(device);
-
- delHifDevice(device);
-}
-
-#if defined(CONFIG_PM)
-static int ath6kl_hifdev_suspend(struct device *dev)
-{
- struct sdio_func *func = dev_to_sdio_func(dev);
- int status = 0;
- struct hif_device *device;
-
- device = ath6kl_get_hifdev(func);
-
- if (device && device->claimedContext &&
- osdrvCallbacks.deviceSuspendHandler) {
- /* set true first for PowerStateChangeNotify(..) */
- device->is_suspend = true;
- status = osdrvCallbacks.
- deviceSuspendHandler(device->claimedContext);
- if (status)
- device->is_suspend = false;
- }
-
- CleanupHIFScatterResources(device);
-
- switch (status) {
- case 0:
- return 0;
- case A_EBUSY:
- /* Hack for kernel in order to support deep sleep and wow */
- return -EBUSY;
- default:
- return -1;
- }
-}
-
-static int ath6kl_hifdev_resume(struct device *dev)
-{
- struct sdio_func *func = dev_to_sdio_func(dev);
- int status = 0;
- struct hif_device *device;
-
- device = ath6kl_get_hifdev(func);
- if (device && device->claimedContext &&
- osdrvCallbacks.deviceSuspendHandler) {
- status = osdrvCallbacks.
- deviceResumeHandler(device->claimedContext);
- if (status == 0)
- device->is_suspend = false;
- }
-
- return status;
-}
-
-static const struct dev_pm_ops ath6kl_hifdev_pmops = {
- .suspend = ath6kl_hifdev_suspend,
- .resume = ath6kl_hifdev_resume,
-};
-#endif /* CONFIG_PM */
-
-static struct sdio_driver ath6kl_hifdev_driver = {
- .name = "ath6kl_hifdev",
- .id_table = ath6kl_hifdev_ids,
- .probe = ath6kl_hifdev_probe,
- .remove = ath6kl_hifdev_remove,
-#if defined(CONFIG_PM)
- .drv = {
- .pm = &ath6kl_hifdev_pmops,
- },
-#endif
-};
-
-/* make sure we only unregister when registered. */
-static int registered = 0;
-
-extern u32 onebitmode;
-extern u32 busspeedlow;
-extern u32 debughif;
-
-static void ResetAllCards(void);
-
-#ifdef DEBUG
-
-ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif,
- "hif",
- "(Linux MMC) Host Interconnect Framework",
- ATH_DEBUG_MASK_DEFAULTS,
- 0,
- NULL);
-
-#endif
-
-
-/* ------ Functions ------ */
-int HIFInit(OSDRV_CALLBACKS *callbacks)
-{
- int r;
- AR_DEBUG_ASSERT(callbacks != NULL);
-
- A_REGISTER_MODULE_DEBUG_INFO(hif);
-
- /* store the callback handlers */
- osdrvCallbacks = *callbacks;
-
- /* Register with bus driver core */
- registered = 1;
-
- r = sdio_register_driver(&ath6kl_hifdev_driver);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int
-__HIFReadWrite(struct hif_device *device,
- u32 address,
- u8 *buffer,
- u32 length,
- u32 request,
- void *context)
-{
- u8 opcode;
- int status = 0;
- int ret;
- u8 *tbuffer;
- bool bounced = false;
-
- AR_DEBUG_ASSERT(device != NULL);
- AR_DEBUG_ASSERT(device->func != NULL);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: 0x%p, buffer:0x%p (addr:0x%X)\n",
- device, buffer, address));
-
- do {
- if (request & HIF_EXTENDED_IO) {
- //AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Command type: CMD53\n"));
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("AR6000: Invalid command type: 0x%08x\n", request));
- status = A_EINVAL;
- break;
- }
-
- if (request & HIF_BLOCK_BASIS) {
- /* round to whole block length size */
- length = (length / HIF_MBOX_BLOCK_SIZE) * HIF_MBOX_BLOCK_SIZE;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
- ("AR6000: Block mode (BlockLen: %d)\n",
- length));
- } else if (request & HIF_BYTE_BASIS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
- ("AR6000: Byte mode (BlockLen: %d)\n",
- length));
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("AR6000: Invalid data mode: 0x%08x\n", request));
- status = A_EINVAL;
- break;
- }
-
-#if 0
- /* useful for checking register accesses */
- if (length & 0x3) {
- A_PRINTF(KERN_ALERT"AR6000: HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n",
- request & HIF_WRITE ? "write":"read", address, length);
- }
-#endif
-
- if (request & HIF_WRITE) {
- if ((address >= HIF_MBOX_START_ADDR(0)) &&
- (address <= HIF_MBOX_END_ADDR(3)))
- {
-
- AR_DEBUG_ASSERT(length <= HIF_MBOX_WIDTH);
-
- /*
- * Mailbox write. Adjust the address so that the last byte
- * falls on the EOM address.
- */
- address += (HIF_MBOX_WIDTH - length);
- }
- }
-
- if (request & HIF_FIXED_ADDRESS) {
- opcode = CMD53_FIXED_ADDRESS;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Fixed 0x%X\n", address));
- } else if (request & HIF_INCREMENTAL_ADDRESS) {
- opcode = CMD53_INCR_ADDRESS;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Incremental 0x%X\n", address));
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("AR6000: Invalid address mode: 0x%08x\n", request));
- status = A_EINVAL;
- break;
- }
-
- if (request & HIF_WRITE) {
-#if HIF_USE_DMA_BOUNCE_BUFFER
- if (BUFFER_NEEDS_BOUNCE(buffer)) {
- AR_DEBUG_ASSERT(device->dma_buffer != NULL);
- tbuffer = device->dma_buffer;
- /* copy the write data to the dma buffer */
- AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
- memcpy(tbuffer, buffer, length);
- bounced = true;
- } else {
- tbuffer = buffer;
- }
-#else
- tbuffer = buffer;
-#endif
- if (opcode == CMD53_FIXED_ADDRESS) {
- ret = sdio_writesb(device->func, address, tbuffer, length);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writesb ret=%d address: 0x%X, len: %d, 0x%X\n",
- ret, address, length, *(int *)tbuffer));
- } else {
- ret = sdio_memcpy_toio(device->func, address, tbuffer, length);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writeio ret=%d address: 0x%X, len: %d, 0x%X\n",
- ret, address, length, *(int *)tbuffer));
- }
- } else if (request & HIF_READ) {
-#if HIF_USE_DMA_BOUNCE_BUFFER
- if (BUFFER_NEEDS_BOUNCE(buffer)) {
- AR_DEBUG_ASSERT(device->dma_buffer != NULL);
- AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
- tbuffer = device->dma_buffer;
- bounced = true;
- } else {
- tbuffer = buffer;
- }
-#else
- tbuffer = buffer;
-#endif
- if (opcode == CMD53_FIXED_ADDRESS) {
- ret = sdio_readsb(device->func, tbuffer, address, length);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readsb ret=%d address: 0x%X, len: %d, 0x%X\n",
- ret, address, length, *(int *)tbuffer));
- } else {
- ret = sdio_memcpy_fromio(device->func, tbuffer, address, length);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readio ret=%d address: 0x%X, len: %d, 0x%X\n",
- ret, address, length, *(int *)tbuffer));
- }
-#if HIF_USE_DMA_BOUNCE_BUFFER
- if (bounced) {
- /* copy the read data from the dma buffer */
- memcpy(buffer, tbuffer, length);
- }
-#endif
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("AR6000: Invalid direction: 0x%08x\n", request));
- status = A_EINVAL;
- break;
- }
-
- if (ret) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("AR6000: SDIO bus operation failed! MMC stack returned : %d \n", ret));
- status = A_ERROR;
- }
- } while (false);
-
- return status;
-}
-
-void AddToAsyncList(struct hif_device *device, BUS_REQUEST *busrequest)
-{
- unsigned long flags;
- BUS_REQUEST *async;
- BUS_REQUEST *active;
-
- spin_lock_irqsave(&device->asynclock, flags);
- active = device->asyncreq;
- if (active == NULL) {
- device->asyncreq = busrequest;
- device->asyncreq->inusenext = NULL;
- } else {
- for (async = device->asyncreq;
- async != NULL;
- async = async->inusenext) {
- active = async;
- }
- active->inusenext = busrequest;
- busrequest->inusenext = NULL;
- }
- spin_unlock_irqrestore(&device->asynclock, flags);
-}
-
-
-/* queue a read/write request */
-int
-HIFReadWrite(struct hif_device *device,
- u32 address,
- u8 *buffer,
- u32 length,
- u32 request,
- void *context)
-{
- int status = 0;
- BUS_REQUEST *busrequest;
-
-
- AR_DEBUG_ASSERT(device != NULL);
- AR_DEBUG_ASSERT(device->func != NULL);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: %p addr:0x%X\n", device,address));
-
- do {
- if ((request & HIF_ASYNCHRONOUS) || (request & HIF_SYNCHRONOUS)){
- /* serialize all requests through the async thread */
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Execution mode: %s\n",
- (request & HIF_ASYNCHRONOUS)?"Async":"Synch"));
- busrequest = hifAllocateBusRequest(device);
- if (busrequest == NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("AR6000: no async bus requests available (%s, addr:0x%X, len:%d) \n",
- request & HIF_READ ? "READ":"WRITE", address, length));
- return A_ERROR;
- }
- busrequest->address = address;
- busrequest->buffer = buffer;
- busrequest->length = length;
- busrequest->request = request;
- busrequest->context = context;
-
- AddToAsyncList(device, busrequest);
-
- if (request & HIF_SYNCHRONOUS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%lX\n", (unsigned long)busrequest));
-
- /* wait for completion */
- up(&device->sem_async);
- if (down_interruptible(&busrequest->sem_req) != 0) {
- /* interrupted, exit */
- return A_ERROR;
- } else {
- int status = busrequest->status;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freeing 0x%lX: 0x%X\n",
- (unsigned long)busrequest, busrequest->status));
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X\n", (unsigned int)request));
- hifFreeBusRequest(device, busrequest);
- return status;
- }
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x%lX\n", (unsigned long)busrequest));
- up(&device->sem_async);
- return A_PENDING;
- }
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("AR6000: Invalid execution mode: 0x%08x\n", (unsigned int)request));
- status = A_EINVAL;
- break;
- }
- } while(0);
-
- return status;
-}
-/* thread to serialize all requests, both sync and async */
-static int async_task(void *param)
- {
- struct hif_device *device;
- BUS_REQUEST *request;
- int status;
- unsigned long flags;
-
- device = (struct hif_device *)param;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task\n"));
- set_current_state(TASK_INTERRUPTIBLE);
- while(!device->async_shutdown) {
- /* wait for work */
- if (down_interruptible(&device->sem_async) != 0) {
- /* interrupted, exit */
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task interrupted\n"));
- break;
- }
- if (device->async_shutdown) {
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task stopping\n"));
- break;
- }
- /* we want to hold the host over multiple cmds if possible, but holding the host blocks card interrupts */
- sdio_claim_host(device->func);
- spin_lock_irqsave(&device->asynclock, flags);
- /* pull the request to work on */
- while (device->asyncreq != NULL) {
- request = device->asyncreq;
- if (request->inusenext != NULL) {
- device->asyncreq = request->inusenext;
- } else {
- device->asyncreq = NULL;
- }
- spin_unlock_irqrestore(&device->asynclock, flags);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task processing req: 0x%lX\n", (unsigned long)request));
-
- if (request->pScatterReq != NULL) {
- A_ASSERT(device->scatter_enabled);
- /* this is a queued scatter request, pass the request to scatter routine which
- * executes it synchronously, note, no need to free the request since scatter requests
- * are maintained on a separate list */
- status = DoHifReadWriteScatter(device,request);
- } else {
- /* call HIFReadWrite in sync mode to do the work */
- status = __HIFReadWrite(device, request->address, request->buffer,
- request->length, request->request & ~HIF_SYNCHRONOUS, NULL);
- if (request->request & HIF_ASYNCHRONOUS) {
- void *context = request->context;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task freeing req: 0x%lX\n", (unsigned long)request));
- hifFreeBusRequest(device, request);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task completion routine req: 0x%lX\n", (unsigned long)request));
- device->htcCallbacks.rwCompletionHandler(context, status);
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task upping req: 0x%lX\n", (unsigned long)request));
- request->status = status;
- up(&request->sem_req);
- }
- }
- spin_lock_irqsave(&device->asynclock, flags);
- }
- spin_unlock_irqrestore(&device->asynclock, flags);
- sdio_release_host(device->func);
- }
-
- complete_and_exit(&device->async_completion, 0);
- return 0;
-}
-
-static s32 IssueSDCommand(struct hif_device *device, u32 opcode, u32 arg, u32 flags, u32 *resp)
-{
- struct mmc_command cmd;
- s32 err;
- struct mmc_host *host;
- struct sdio_func *func;
-
- func = device->func;
- host = func->card->host;
-
- memset(&cmd, 0, sizeof(struct mmc_command));
- cmd.opcode = opcode;
- cmd.arg = arg;
- cmd.flags = flags;
- err = mmc_wait_for_cmd(host, &cmd, 3);
-
- if ((!err) && (resp)) {
- *resp = cmd.resp[0];
- }
-
- return err;
-}
-
-int ReinitSDIO(struct hif_device *device)
-{
- s32 err;
- struct mmc_host *host;
- struct mmc_card *card;
- struct sdio_func *func;
- u8 cmd52_resp;
- u32 clock;
-
- func = device->func;
- card = func->card;
- host = card->host;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +ReinitSDIO \n"));
- sdio_claim_host(func);
-
- do {
- if (!device->is_suspend) {
- u32 resp;
- u16 rca;
- u32 i;
- int bit = fls(host->ocr_avail) - 1;
- /* emulate the mmc_power_up(...) */
- host->ios.vdd = bit;
- host->ios.chip_select = MMC_CS_DONTCARE;
- host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
- host->ios.power_mode = MMC_POWER_UP;
- host->ios.bus_width = MMC_BUS_WIDTH_1;
- host->ios.timing = MMC_TIMING_LEGACY;
- host->ops->set_ios(host, &host->ios);
- /*
- * This delay should be sufficient to allow the power supply
- * to reach the minimum voltage.
- */
- msleep(2);
-
- host->ios.clock = host->f_min;
- host->ios.power_mode = MMC_POWER_ON;
- host->ops->set_ios(host, &host->ios);
-
- /*
- * This delay must be at least 74 clock sizes, or 1 ms, or the
- * time required to reach a stable voltage.
- */
- msleep(2);
-
- /* Issue CMD0. Goto idle state */
- host->ios.chip_select = MMC_CS_HIGH;
- host->ops->set_ios(host, &host->ios);
- msleep(1);
- err = IssueSDCommand(device, MMC_GO_IDLE_STATE, 0, (MMC_RSP_NONE | MMC_CMD_BC), NULL);
- host->ios.chip_select = MMC_CS_DONTCARE;
- host->ops->set_ios(host, &host->ios);
- msleep(1);
- host->use_spi_crc = 0;
-
- if (err) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD0 failed : %d \n",err));
- break;
- }
-
- if (!host->ocr) {
- /* Issue CMD5, arg = 0 */
- err = IssueSDCommand(device, SD_IO_SEND_OP_COND, 0, (MMC_RSP_R4 | MMC_CMD_BCR), &resp);
- if (err) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err));
- break;
- }
- host->ocr = resp;
- }
-
- /* Issue CMD5, arg = ocr. Wait till card is ready */
- for (i=0;i<100;i++) {
- err = IssueSDCommand(device, SD_IO_SEND_OP_COND, host->ocr, (MMC_RSP_R4 | MMC_CMD_BCR), &resp);
- if (err) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err));
- break;
- }
- if (resp & MMC_CARD_BUSY) {
- break;
- }
- msleep(10);
- }
-
- if ((i == 100) || (err)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: card in not ready : %d %d \n",i,err));
- break;
- }
-
- /* Issue CMD3, get RCA */
- err = IssueSDCommand(device, SD_SEND_RELATIVE_ADDR, 0, MMC_RSP_R6 | MMC_CMD_BCR, &resp);
- if (err) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD3 failed : %d \n",err));
- break;
- }
- rca = resp >> 16;
- host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
- host->ops->set_ios(host, &host->ios);
-
- /* Issue CMD7, select card */
- err = IssueSDCommand(device, MMC_SELECT_CARD, (rca << 16), MMC_RSP_R1 | MMC_CMD_AC, NULL);
- if (err) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD7 failed : %d \n",err));
- break;
- }
- }
-
- /* Enable high speed */
- if (card->host->caps & MMC_CAP_SD_HIGHSPEED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("ReinitSDIO: Set high speed mode\n"));
- err = Func0_CMD52ReadByte(card, SDIO_CCCR_SPEED, &cmd52_resp);
- if (err) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 read to CCCR speed register failed : %d \n",err));
- card->state &= ~MMC_STATE_HIGHSPEED;
- /* no need to break */
- } else {
- err = Func0_CMD52WriteByte(card, SDIO_CCCR_SPEED, (cmd52_resp | SDIO_SPEED_EHS));
- if (err) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 write to CCCR speed register failed : %d \n",err));
- break;
- }
- mmc_card_set_highspeed(card);
- host->ios.timing = MMC_TIMING_SD_HS;
- host->ops->set_ios(host, &host->ios);
- }
- }
-
- /* Set clock */
- if (mmc_card_highspeed(card)) {
- clock = 50000000;
- } else {
- clock = card->cis.max_dtr;
- }
-
- if (clock > host->f_max) {
- clock = host->f_max;
- }
- host->ios.clock = clock;
- host->ops->set_ios(host, &host->ios);
-
-
- if (card->host->caps & MMC_CAP_4_BIT_DATA) {
- /* CMD52: Set bus width & disable card detect resistor */
- err = Func0_CMD52WriteByte(card, SDIO_CCCR_IF, SDIO_BUS_CD_DISABLE | SDIO_BUS_WIDTH_4BIT);
- if (err) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 to set bus mode failed : %d \n",err));
- break;
- }
- host->ios.bus_width = MMC_BUS_WIDTH_4;
- host->ops->set_ios(host, &host->ios);
- }
- } while (0);
-
- sdio_release_host(func);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -ReinitSDIO \n"));
-
- return (err) ? A_ERROR : 0;
-}
-
-int
-PowerStateChangeNotify(struct hif_device *device, HIF_DEVICE_POWER_CHANGE_TYPE config)
-{
- int status = 0;
-#if defined(CONFIG_PM)
- struct sdio_func *func = device->func;
- int old_reset_val;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +PowerStateChangeNotify %d\n", config));
- switch (config) {
- case HIF_DEVICE_POWER_DOWN:
- case HIF_DEVICE_POWER_CUT:
- old_reset_val = reset_sdio_on_unload;
- reset_sdio_on_unload = 1;
- status = hifDisableFunc(device, func);
- reset_sdio_on_unload = old_reset_val;
- if (!device->is_suspend) {
- struct mmc_host *host = func->card->host;
- host->ios.clock = 0;
- host->ios.vdd = 0;
- host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
- host->ios.chip_select = MMC_CS_DONTCARE;
- host->ios.power_mode = MMC_POWER_OFF;
- host->ios.bus_width = MMC_BUS_WIDTH_1;
- host->ios.timing = MMC_TIMING_LEGACY;
- host->ops->set_ios(host, &host->ios);
- }
- break;
- case HIF_DEVICE_POWER_UP:
- if (device->powerConfig == HIF_DEVICE_POWER_CUT) {
- status = ReinitSDIO(device);
- }
- if (status == 0) {
- status = hifEnableFunc(device, func);
- }
- break;
- }
- device->powerConfig = config;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -PowerStateChangeNotify\n"));
-#endif
- return status;
-}
-
-int
-HIFConfigureDevice(struct hif_device *device, HIF_DEVICE_CONFIG_OPCODE opcode,
- void *config, u32 configLen)
-{
- u32 count;
- int status = 0;
-
- switch(opcode) {
- case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
- ((u32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
- ((u32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
- ((u32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
- ((u32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
- break;
-
- case HIF_DEVICE_GET_MBOX_ADDR:
- for (count = 0; count < 4; count ++) {
- ((u32 *)config)[count] = HIF_MBOX_START_ADDR(count);
- }
-
- if (configLen >= sizeof(struct hif_device_mbox_info)) {
- SetExtendedMboxWindowInfo((u16)device->func->device,
- (struct hif_device_mbox_info *)config);
- }
-
- break;
- case HIF_DEVICE_GET_IRQ_PROC_MODE:
- *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY;
- break;
- case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT:
- if (!device->scatter_enabled) {
- return A_ENOTSUP;
- }
- status = SetupHIFScatterSupport(device, (struct hif_device_scatter_support_info *)config);
- if (status) {
- device->scatter_enabled = false;
- }
- break;
- case HIF_DEVICE_GET_OS_DEVICE:
- /* pass back a pointer to the SDIO function's "dev" struct */
- ((struct hif_device_os_device_info *)config)->pOSDevice = &device->func->dev;
- break;
- case HIF_DEVICE_POWER_STATE_CHANGE:
- status = PowerStateChangeNotify(device, *(HIF_DEVICE_POWER_CHANGE_TYPE *)config);
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
- ("AR6000: Unsupported configuration opcode: %d\n", opcode));
- status = A_ERROR;
- }
-
- return status;
-}
-
-void
-HIFShutDownDevice(struct hif_device *device)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n"));
- if (device != NULL) {
- AR_DEBUG_ASSERT(device->func != NULL);
- } else {
- /* since we are unloading the driver anyways, reset all cards in case the SDIO card
- * is externally powered and we are unloading the SDIO stack. This avoids the problem when
- * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already
- * enumerated */
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFShutDownDevice, resetting\n"));
- ResetAllCards();
-
- /* Unregister with bus driver core */
- if (registered) {
- registered = 0;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
- ("AR6000: Unregistering with the bus driver\n"));
- sdio_unregister_driver(&ath6kl_hifdev_driver);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
- ("AR6000: Unregistered\n"));
- }
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -HIFShutDownDevice\n"));
-}
-
-static void
-hifIRQHandler(struct sdio_func *func)
-{
- int status;
- struct hif_device *device;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifIRQHandler\n"));
-
- device = ath6kl_get_hifdev(func);
- atomic_set(&device->irqHandling, 1);
- /* release the host during ints so we can pick it back up when we process cmds */
- sdio_release_host(device->func);
- status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context);
- sdio_claim_host(device->func);
- atomic_set(&device->irqHandling, 0);
- AR_DEBUG_ASSERT(status == 0 || status == A_ECANCELED);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifIRQHandler\n"));
-}
-
-/* handle HTC startup via thread*/
-static int startup_task(void *param)
-{
- struct hif_device *device;
-
- device = (struct hif_device *)param;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n"));
- /* start up inform DRV layer */
- if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
- }
- return 0;
-}
-
-#if defined(CONFIG_PM)
-static int enable_task(void *param)
-{
- struct hif_device *device;
- device = (struct hif_device *)param;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call from resume_task\n"));
-
- /* start up inform DRV layer */
- if (device &&
- device->claimedContext &&
- osdrvCallbacks.devicePowerChangeHandler &&
- osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
- }
-
- return 0;
-}
-#endif
-
-void
-HIFAckInterrupt(struct hif_device *device)
-{
- AR_DEBUG_ASSERT(device != NULL);
-
- /* Acknowledge our function IRQ */
-}
-
-void
-HIFUnMaskInterrupt(struct hif_device *device)
-{
- int ret;
-
- AR_DEBUG_ASSERT(device != NULL);
- AR_DEBUG_ASSERT(device->func != NULL);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFUnMaskInterrupt\n"));
-
- /* Register the IRQ Handler */
- sdio_claim_host(device->func);
- ret = sdio_claim_irq(device->func, hifIRQHandler);
- sdio_release_host(device->func);
- AR_DEBUG_ASSERT(ret == 0);
-}
-
-void HIFMaskInterrupt(struct hif_device *device)
-{
- int ret;
- AR_DEBUG_ASSERT(device != NULL);
- AR_DEBUG_ASSERT(device->func != NULL);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFMaskInterrupt\n"));
-
- /* Mask our function IRQ */
- sdio_claim_host(device->func);
- while (atomic_read(&device->irqHandling)) {
- sdio_release_host(device->func);
- schedule_timeout(HZ/10);
- sdio_claim_host(device->func);
- }
- ret = sdio_release_irq(device->func);
- sdio_release_host(device->func);
- AR_DEBUG_ASSERT(ret == 0);
-}
-
-BUS_REQUEST *hifAllocateBusRequest(struct hif_device *device)
-{
- BUS_REQUEST *busrequest;
- unsigned long flag;
-
- /* Acquire lock */
- spin_lock_irqsave(&device->lock, flag);
-
- /* Remove first in list */
- if((busrequest = device->s_busRequestFreeQueue) != NULL)
- {
- device->s_busRequestFreeQueue = busrequest->next;
- }
- /* Release lock */
- spin_unlock_irqrestore(&device->lock, flag);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifAllocateBusRequest: 0x%p\n", busrequest));
- return busrequest;
-}
-
-void
-hifFreeBusRequest(struct hif_device *device, BUS_REQUEST *busrequest)
-{
- unsigned long flag;
-
- AR_DEBUG_ASSERT(busrequest != NULL);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifFreeBusRequest: 0x%p\n", busrequest));
- /* Acquire lock */
- spin_lock_irqsave(&device->lock, flag);
-
-
- /* Insert first in list */
- busrequest->next = device->s_busRequestFreeQueue;
- busrequest->inusenext = NULL;
- device->s_busRequestFreeQueue = busrequest;
-
- /* Release lock */
- spin_unlock_irqrestore(&device->lock, flag);
-}
-
-static int hifDisableFunc(struct hif_device *device, struct sdio_func *func)
-{
- int ret;
- int status = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDisableFunc\n"));
- device = ath6kl_get_hifdev(func);
- if (!IS_ERR(device->async_task)) {
- init_completion(&device->async_completion);
- device->async_shutdown = 1;
- up(&device->sem_async);
- wait_for_completion(&device->async_completion);
- device->async_task = NULL;
- }
- /* Disable the card */
- sdio_claim_host(device->func);
- ret = sdio_disable_func(device->func);
- if (ret) {
- status = A_ERROR;
- }
-
- if (reset_sdio_on_unload) {
- /* reset the SDIO interface. This is useful in automated testing where the card
- * does not need to be removed at the end of the test. It is expected that the user will
- * also unload/reload the host controller driver to force the bus driver to re-enumerate the slot */
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: reseting SDIO card back to uninitialized state \n"));
-
- /* NOTE : sdio_f0_writeb() cannot be used here, that API only allows access
- * to undefined registers in the range of: 0xF0-0xFF */
-
- ret = Func0_CMD52WriteByte(device->func->card, SDIO_CCCR_ABORT, (1 << 3));
- if (ret) {
- status = A_ERROR;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: reset failed : %d \n",ret));
- }
- }
-
- sdio_release_host(device->func);
-
- if (status == 0) {
- device->is_disabled = true;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDisableFunc\n"));
-
- return status;
-}
-
-static int hifEnableFunc(struct hif_device *device, struct sdio_func *func)
-{
- struct task_struct* pTask;
- const char *taskName = NULL;
- int (*taskFunc)(void *) = NULL;
- int ret = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifEnableFunc\n"));
- device = ath6kl_get_hifdev(func);
-
- if (device->is_disabled) {
- /* enable the SDIO function */
- sdio_claim_host(func);
-
- if ((device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK) >= MANUFACTURER_ID_AR6003_BASE) {
- /* enable 4-bit ASYNC interrupt on AR6003 or later devices */
- ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG, SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
- if (ret) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to enable 4-bit ASYNC IRQ mode %d \n",ret));
- sdio_release_host(func);
- return ret;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: 4-bit ASYNC IRQ mode enabled\n"));
- }
- /* give us some time to enable, in ms */
- func->enable_timeout = 100;
- ret = sdio_enable_func(func);
- if (ret) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n",
- __FUNCTION__, ret));
- sdio_release_host(func);
- return ret;
- }
- ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
- sdio_release_host(func);
- if (ret) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x AR6K: 0x%X\n",
- __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret));
- return ret;
- }
- device->is_disabled = false;
- /* create async I/O thread */
- if (!device->async_task) {
- device->async_shutdown = 0;
- device->async_task = kthread_create(async_task,
- (void *)device,
- "AR6K Async");
- if (IS_ERR(device->async_task)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__));
- return -ENOMEM;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n"));
- wake_up_process(device->async_task );
- }
- }
-
- if (!device->claimedContext) {
- taskFunc = startup_task;
- taskName = "AR6K startup";
- ret = 0;
-#if defined(CONFIG_PM)
- } else {
- taskFunc = enable_task;
- taskName = "AR6K enable";
- ret = -ENOMEM;
-#endif /* CONFIG_PM */
- }
- /* create resume thread */
- pTask = kthread_create(taskFunc, (void *)device, taskName);
- if (IS_ERR(pTask)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create enabel task\n", __FUNCTION__));
- return -ENOMEM;
- }
- wake_up_process(pTask);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifEnableFunc\n"));
-
- /* task will call the enable func, indicate pending */
- return ret;
-}
-
-/*
- * This should be moved to AR6K HTC layer.
- */
-int hifWaitForPendingRecv(struct hif_device *device)
-{
- s32 cnt = 10;
- u8 host_int_status;
- int status = 0;
-
- do {
- while (atomic_read(&device->irqHandling)) {
- /* wait until irq handler finished all the jobs */
- schedule_timeout(HZ/10);
- }
- /* check if there is any pending irq due to force done */
- host_int_status = 0;
- status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS,
- (u8 *)&host_int_status, sizeof(host_int_status),
- HIF_RD_SYNC_BYTE_INC, NULL);
- host_int_status = !status ? (host_int_status & (1 << 0)) : 0;
- if (host_int_status) {
- schedule(); /* schedule for next dsrHandler */
- }
- } while (host_int_status && --cnt > 0);
-
- if (host_int_status && cnt == 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("AR6000: %s(), Unable clear up pending IRQ before the system suspended\n", __FUNCTION__));
- }
-
- return 0;
-}
-
-static void
-delHifDevice(struct hif_device * device)
-{
- AR_DEBUG_ASSERT(device!= NULL);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: delHifDevice; 0x%p\n", device));
- kfree(device->dma_buffer);
- kfree(device);
-}
-
-static void ResetAllCards(void)
-{
-}
-
-void HIFClaimDevice(struct hif_device *device, void *context)
-{
- device->claimedContext = context;
-}
-
-void HIFReleaseDevice(struct hif_device *device)
-{
- device->claimedContext = NULL;
-}
-
-int HIFAttachHTC(struct hif_device *device, HTC_CALLBACKS *callbacks)
-{
- if (device->htcCallbacks.context != NULL) {
- /* already in use! */
- return A_ERROR;
- }
- device->htcCallbacks = *callbacks;
- return 0;
-}
-
-void HIFDetachHTC(struct hif_device *device)
-{
- A_MEMZERO(&device->htcCallbacks,sizeof(device->htcCallbacks));
-}
-
-#define SDIO_SET_CMD52_ARG(arg,rw,func,raw,address,writedata) \
- (arg) = (((rw) & 1) << 31) | \
- (((func) & 0x7) << 28) | \
- (((raw) & 1) << 27) | \
- (1 << 26) | \
- (((address) & 0x1FFFF) << 9) | \
- (1 << 8) | \
- ((writedata) & 0xFF)
-
-#define SDIO_SET_CMD52_READ_ARG(arg,func,address) \
- SDIO_SET_CMD52_ARG(arg,0,(func),0,address,0x00)
-#define SDIO_SET_CMD52_WRITE_ARG(arg,func,address,value) \
- SDIO_SET_CMD52_ARG(arg,1,(func),0,address,value)
-
-static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte)
-{
- struct mmc_command ioCmd;
- unsigned long arg;
-
- memset(&ioCmd,0,sizeof(ioCmd));
- SDIO_SET_CMD52_WRITE_ARG(arg,0,address,byte);
- ioCmd.opcode = SD_IO_RW_DIRECT;
- ioCmd.arg = arg;
- ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
-
- return mmc_wait_for_cmd(card->host, &ioCmd, 0);
-}
-
-static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte)
-{
- struct mmc_command ioCmd;
- unsigned long arg;
- s32 err;
-
- memset(&ioCmd,0,sizeof(ioCmd));
- SDIO_SET_CMD52_READ_ARG(arg,0,address);
- ioCmd.opcode = SD_IO_RW_DIRECT;
- ioCmd.arg = arg;
- ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
-
- err = mmc_wait_for_cmd(card->host, &ioCmd, 0);
-
- if ((!err) && (byte)) {
- *byte = ioCmd.resp[0] & 0xFF;
- }
-
- return err;
-}
diff --git a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c
deleted file mode 100644
index 7516d913dab3..000000000000
--- a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c
+++ /dev/null
@@ -1,393 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// HIF scatter implementation
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/mmc/sdio.h>
-#include <linux/kthread.h>
-#include "hif_internal.h"
-#define ATH_MODULE_NAME hif
-#include "a_debug.h"
-
-#ifdef HIF_LINUX_MMC_SCATTER_SUPPORT
-
-#define _CMD53_ARG_READ 0
-#define _CMD53_ARG_WRITE 1
-#define _CMD53_ARG_BLOCK_BASIS 1
-#define _CMD53_ARG_FIXED_ADDRESS 0
-#define _CMD53_ARG_INCR_ADDRESS 1
-
-#define SDIO_SET_CMD53_ARG(arg,rw,func,mode,opcode,address,bytes_blocks) \
- (arg) = (((rw) & 1) << 31) | \
- (((func) & 0x7) << 28) | \
- (((mode) & 1) << 27) | \
- (((opcode) & 1) << 26) | \
- (((address) & 0x1FFFF) << 9) | \
- ((bytes_blocks) & 0x1FF)
-
-static void FreeScatterReq(struct hif_device *device, struct hif_scatter_req *pReq)
-{
- unsigned long flag;
-
- spin_lock_irqsave(&device->lock, flag);
-
- DL_ListInsertTail(&device->ScatterReqHead, &pReq->ListLink);
-
- spin_unlock_irqrestore(&device->lock, flag);
-
-}
-
-static struct hif_scatter_req *AllocScatterReq(struct hif_device *device)
-{
- struct dl_list *pItem;
- unsigned long flag;
-
- spin_lock_irqsave(&device->lock, flag);
-
- pItem = DL_ListRemoveItemFromHead(&device->ScatterReqHead);
-
- spin_unlock_irqrestore(&device->lock, flag);
-
- if (pItem != NULL) {
- return A_CONTAINING_STRUCT(pItem, struct hif_scatter_req, ListLink);
- }
-
- return NULL;
-}
-
- /* called by async task to perform the operation synchronously using direct MMC APIs */
-int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest)
-{
- int i;
- u8 rw;
- u8 opcode;
- struct mmc_request mmcreq;
- struct mmc_command cmd;
- struct mmc_data data;
- struct hif_scatter_req_priv *pReqPriv;
- struct hif_scatter_req *pReq;
- int status = 0;
- struct scatterlist *pSg;
-
- pReqPriv = busrequest->pScatterReq;
-
- A_ASSERT(pReqPriv != NULL);
-
- pReq = pReqPriv->pHifScatterReq;
-
- memset(&mmcreq, 0, sizeof(struct mmc_request));
- memset(&cmd, 0, sizeof(struct mmc_command));
- memset(&data, 0, sizeof(struct mmc_data));
-
- data.blksz = HIF_MBOX_BLOCK_SIZE;
- data.blocks = pReq->TotalLength / HIF_MBOX_BLOCK_SIZE;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: (%s) Address: 0x%X, (BlockLen: %d, BlockCount: %d) , (tot:%d,sg:%d)\n",
- (pReq->Request & HIF_WRITE) ? "WRITE":"READ", pReq->Address, data.blksz, data.blocks,
- pReq->TotalLength,pReq->ValidScatterEntries));
-
- if (pReq->Request & HIF_WRITE) {
- rw = _CMD53_ARG_WRITE;
- data.flags = MMC_DATA_WRITE;
- } else {
- rw = _CMD53_ARG_READ;
- data.flags = MMC_DATA_READ;
- }
-
- if (pReq->Request & HIF_FIXED_ADDRESS) {
- opcode = _CMD53_ARG_FIXED_ADDRESS;
- } else {
- opcode = _CMD53_ARG_INCR_ADDRESS;
- }
-
- /* fill SG entries */
- pSg = pReqPriv->sgentries;
- sg_init_table(pSg, pReq->ValidScatterEntries);
-
- /* assemble SG list */
- for (i = 0 ; i < pReq->ValidScatterEntries ; i++, pSg++) {
- /* setup each sg entry */
- if ((unsigned long)pReq->ScatterList[i].pBuffer & 0x3) {
- /* note some scatter engines can handle unaligned buffers, print this
- * as informational only */
- AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER,
- ("HIF: (%s) Scatter Buffer is unaligned 0x%lx\n",
- pReq->Request & HIF_WRITE ? "WRITE":"READ",
- (unsigned long)pReq->ScatterList[i].pBuffer));
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, (" %d: Addr:0x%lX, Len:%d \n",
- i,(unsigned long)pReq->ScatterList[i].pBuffer,pReq->ScatterList[i].Length));
-
- sg_set_buf(pSg, pReq->ScatterList[i].pBuffer, pReq->ScatterList[i].Length);
- }
- /* set scatter-gather table for request */
- data.sg = pReqPriv->sgentries;
- data.sg_len = pReq->ValidScatterEntries;
- /* set command argument */
- SDIO_SET_CMD53_ARG(cmd.arg,
- rw,
- device->func->num,
- _CMD53_ARG_BLOCK_BASIS,
- opcode,
- pReq->Address,
- data.blocks);
-
- cmd.opcode = SD_IO_RW_EXTENDED;
- cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
-
- mmcreq.cmd = &cmd;
- mmcreq.data = &data;
-
- mmc_set_data_timeout(&data, device->func->card);
- /* synchronous call to process request */
- mmc_wait_for_req(device->func->card->host, &mmcreq);
-
- if (cmd.error) {
- status = A_ERROR;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: cmd error: %d \n",cmd.error));
- }
-
- if (data.error) {
- status = A_ERROR;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: data error: %d \n",data.error));
- }
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: FAILED!!! (%s) Address: 0x%X, Block mode (BlockLen: %d, BlockCount: %d)\n",
- (pReq->Request & HIF_WRITE) ? "WRITE":"READ",pReq->Address, data.blksz, data.blocks));
- }
-
- /* set completion status, fail or success */
- pReq->CompletionStatus = status;
-
- if (pReq->Request & HIF_ASYNCHRONOUS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: async_task completion routine req: 0x%lX (%d)\n",(unsigned long)busrequest, status));
- /* complete the request */
- A_ASSERT(pReq->CompletionRoutine != NULL);
- pReq->CompletionRoutine(pReq);
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER async_task upping busrequest : 0x%lX (%d)\n", (unsigned long)busrequest,status));
- /* signal wait */
- up(&busrequest->sem_req);
- }
-
- return status;
-}
-
- /* callback to issue a read-write scatter request */
-static int HifReadWriteScatter(struct hif_device *device, struct hif_scatter_req *pReq)
-{
- int status = A_EINVAL;
- u32 request = pReq->Request;
- struct hif_scatter_req_priv *pReqPriv = (struct hif_scatter_req_priv *)pReq->HIFPrivate[0];
-
- do {
-
- A_ASSERT(pReqPriv != NULL);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: total len: %d Scatter Entries: %d\n",
- pReq->TotalLength, pReq->ValidScatterEntries));
-
- if (!(request & HIF_EXTENDED_IO)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("HIF-SCATTER: Invalid command type: 0x%08x\n", request));
- break;
- }
-
- if (!(request & (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS))) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("HIF-SCATTER: Invalid execution mode: 0x%08x\n", request));
- break;
- }
-
- if (!(request & HIF_BLOCK_BASIS)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("HIF-SCATTER: Invalid data mode: 0x%08x\n", request));
- break;
- }
-
- if (pReq->TotalLength > MAX_SCATTER_REQ_TRANSFER_SIZE) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
- ("HIF-SCATTER: Invalid length: %d \n", pReq->TotalLength));
- break;
- }
-
- if (pReq->TotalLength == 0) {
- A_ASSERT(false);
- break;
- }
-
- /* add bus request to the async list for the async I/O thread to process */
- AddToAsyncList(device, pReqPriv->busrequest);
-
- if (request & HIF_SYNCHRONOUS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued sync req: 0x%lX\n", (unsigned long)pReqPriv->busrequest));
- /* signal thread and wait */
- up(&device->sem_async);
- if (down_interruptible(&pReqPriv->busrequest->sem_req) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,("HIF-SCATTER: interrupted! \n"));
- /* interrupted, exit */
- status = A_ERROR;
- break;
- } else {
- status = pReq->CompletionStatus;
- }
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued async req: 0x%lX\n", (unsigned long)pReqPriv->busrequest));
- /* wake thread, it will process and then take care of the async callback */
- up(&device->sem_async);
- status = 0;
- }
-
- } while (false);
-
- if (status && (request & HIF_ASYNCHRONOUS)) {
- pReq->CompletionStatus = status;
- pReq->CompletionRoutine(pReq);
- status = 0;
- }
-
- return status;
-}
-
- /* setup of HIF scatter resources */
-int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo)
-{
- int status = A_ERROR;
- int i;
- struct hif_scatter_req_priv *pReqPriv;
- BUS_REQUEST *busrequest;
-
- do {
-
- /* check if host supports scatter requests and it meets our requirements */
- if (device->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : host only supports scatter of : %d entries, need: %d \n",
- device->func->card->host->max_segs, MAX_SCATTER_ENTRIES_PER_REQ));
- status = A_ENOTSUP;
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HIF-SCATTER Enabled: max scatter req : %d entries: %d \n",
- MAX_SCATTER_REQUESTS, MAX_SCATTER_ENTRIES_PER_REQ));
-
- for (i = 0; i < MAX_SCATTER_REQUESTS; i++) {
- /* allocate the private request blob */
- pReqPriv = (struct hif_scatter_req_priv *)A_MALLOC(sizeof(struct hif_scatter_req_priv));
- if (NULL == pReqPriv) {
- break;
- }
- A_MEMZERO(pReqPriv, sizeof(struct hif_scatter_req_priv));
- /* save the device instance*/
- pReqPriv->device = device;
- /* allocate the scatter request */
- pReqPriv->pHifScatterReq = (struct hif_scatter_req *)A_MALLOC(sizeof(struct hif_scatter_req) +
- (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(struct hif_scatter_item)));
-
- if (NULL == pReqPriv->pHifScatterReq) {
- kfree(pReqPriv);
- break;
- }
- /* just zero the main part of the scatter request */
- A_MEMZERO(pReqPriv->pHifScatterReq, sizeof(struct hif_scatter_req));
- /* back pointer to the private struct */
- pReqPriv->pHifScatterReq->HIFPrivate[0] = pReqPriv;
- /* allocate a bus request for this scatter request */
- busrequest = hifAllocateBusRequest(device);
- if (NULL == busrequest) {
- kfree(pReqPriv->pHifScatterReq);
- kfree(pReqPriv);
- break;
- }
- /* assign the scatter request to this bus request */
- busrequest->pScatterReq = pReqPriv;
- /* point back to the request */
- pReqPriv->busrequest = busrequest;
- /* add it to the scatter pool */
- FreeScatterReq(device,pReqPriv->pHifScatterReq);
- }
-
- if (i != MAX_SCATTER_REQUESTS) {
- status = A_NO_MEMORY;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : failed to alloc scatter resources !\n"));
- break;
- }
-
- /* set scatter function pointers */
- pInfo->pAllocateReqFunc = AllocScatterReq;
- pInfo->pFreeReqFunc = FreeScatterReq;
- pInfo->pReadWriteScatterFunc = HifReadWriteScatter;
- pInfo->MaxScatterEntries = MAX_SCATTER_ENTRIES_PER_REQ;
- pInfo->MaxTransferSizePerScatterReq = MAX_SCATTER_REQ_TRANSFER_SIZE;
-
- status = 0;
-
- } while (false);
-
- if (status) {
- CleanupHIFScatterResources(device);
- }
-
- return status;
-}
-
- /* clean up scatter support */
-void CleanupHIFScatterResources(struct hif_device *device)
-{
- struct hif_scatter_req_priv *pReqPriv;
- struct hif_scatter_req *pReq;
-
- /* empty the free list */
-
- while (1) {
-
- pReq = AllocScatterReq(device);
-
- if (NULL == pReq) {
- break;
- }
-
- pReqPriv = (struct hif_scatter_req_priv *)pReq->HIFPrivate[0];
- A_ASSERT(pReqPriv != NULL);
-
- if (pReqPriv->busrequest != NULL) {
- pReqPriv->busrequest->pScatterReq = NULL;
- /* free bus request */
- hifFreeBusRequest(device, pReqPriv->busrequest);
- pReqPriv->busrequest = NULL;
- }
-
- if (pReqPriv->pHifScatterReq != NULL) {
- kfree(pReqPriv->pHifScatterReq);
- pReqPriv->pHifScatterReq = NULL;
- }
-
- kfree(pReqPriv);
- }
-}
-
-#endif // HIF_LINUX_MMC_SCATTER_SUPPORT
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k.c
deleted file mode 100644
index f8607bc08929..000000000000
--- a/drivers/staging/ath6kl/htc2/AR6000/ar6k.c
+++ /dev/null
@@ -1,1479 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="ar6k.c" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// AR6K device layer that handles register level I/O
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-#include "a_config.h"
-#include "athdefs.h"
-#include "hw/mbox_host_reg.h"
-#include "a_osapi.h"
-#include "../htc_debug.h"
-#include "hif.h"
-#include "htc_packet.h"
-#include "ar6k.h"
-
-#define MAILBOX_FOR_BLOCK_SIZE 1
-
-int DevEnableInterrupts(struct ar6k_device *pDev);
-int DevDisableInterrupts(struct ar6k_device *pDev);
-
-static void DevCleanupVirtualScatterSupport(struct ar6k_device *pDev);
-
-void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket)
-{
- LOCK_AR6K(pDev);
- HTC_PACKET_ENQUEUE(&pDev->RegisterIOList,pPacket);
- UNLOCK_AR6K(pDev);
-}
-
-struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev)
-{
- struct htc_packet *pPacket;
-
- LOCK_AR6K(pDev);
- pPacket = HTC_PACKET_DEQUEUE(&pDev->RegisterIOList);
- UNLOCK_AR6K(pDev);
-
- return pPacket;
-}
-
-void DevCleanup(struct ar6k_device *pDev)
-{
- DevCleanupGMbox(pDev);
-
- if (pDev->HifAttached) {
- HIFDetachHTC(pDev->HIFDevice);
- pDev->HifAttached = false;
- }
-
- DevCleanupVirtualScatterSupport(pDev);
-
- if (A_IS_MUTEX_VALID(&pDev->Lock)) {
- A_MUTEX_DELETE(&pDev->Lock);
- }
-}
-
-int DevSetup(struct ar6k_device *pDev)
-{
- u32 blocksizes[AR6K_MAILBOXES];
- int status = 0;
- int i;
- HTC_CALLBACKS htcCallbacks;
-
- do {
-
- DL_LIST_INIT(&pDev->ScatterReqHead);
- /* initialize our free list of IO packets */
- INIT_HTC_PACKET_QUEUE(&pDev->RegisterIOList);
- A_MUTEX_INIT(&pDev->Lock);
-
- A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS));
- /* the device layer handles these */
- htcCallbacks.rwCompletionHandler = DevRWCompletionHandler;
- htcCallbacks.dsrHandler = DevDsrHandler;
- htcCallbacks.context = pDev;
-
- status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks);
-
- if (status) {
- break;
- }
-
- pDev->HifAttached = true;
-
- /* get the addresses for all 4 mailboxes */
- status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
- &pDev->MailBoxInfo, sizeof(pDev->MailBoxInfo));
-
- if (status) {
- A_ASSERT(false);
- break;
- }
-
- /* carve up register I/O packets (these are for ASYNC register I/O ) */
- for (i = 0; i < AR6K_MAX_REG_IO_BUFFERS; i++) {
- struct htc_packet *pIOPacket;
- pIOPacket = &pDev->RegIOBuffers[i].HtcPacket;
- SET_HTC_PACKET_INFO_RX_REFILL(pIOPacket,
- pDev,
- pDev->RegIOBuffers[i].Buffer,
- AR6K_REG_IO_BUFFER_SIZE,
- 0); /* don't care */
- AR6KFreeIOPacket(pDev,pIOPacket);
- }
-
- /* get the block sizes */
- status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
- blocksizes, sizeof(blocksizes));
-
- if (status) {
- A_ASSERT(false);
- break;
- }
-
- /* note: we actually get the block size of a mailbox other than 0, for SDIO the block
- * size on mailbox 0 is artificially set to 1. So we use the block size that is set
- * for the other 3 mailboxes */
- pDev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE];
- /* must be a power of 2 */
- A_ASSERT((pDev->BlockSize & (pDev->BlockSize - 1)) == 0);
-
- /* assemble mask, used for padding to a block */
- pDev->BlockMask = pDev->BlockSize - 1;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("BlockSize: %d, MailboxAddress:0x%X \n",
- pDev->BlockSize, pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX]));
-
- pDev->GetPendingEventsFunc = NULL;
- /* see if the HIF layer implements the get pending events function */
- HIFConfigureDevice(pDev->HIFDevice,
- HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
- &pDev->GetPendingEventsFunc,
- sizeof(pDev->GetPendingEventsFunc));
-
- /* assume we can process HIF interrupt events asynchronously */
- pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC;
-
- /* see if the HIF layer overrides this assumption */
- HIFConfigureDevice(pDev->HIFDevice,
- HIF_DEVICE_GET_IRQ_PROC_MODE,
- &pDev->HifIRQProcessingMode,
- sizeof(pDev->HifIRQProcessingMode));
-
- switch (pDev->HifIRQProcessingMode) {
- case HIF_DEVICE_IRQ_SYNC_ONLY:
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("HIF Interrupt processing is SYNC ONLY\n"));
- /* see if HIF layer wants HTC to yield */
- HIFConfigureDevice(pDev->HIFDevice,
- HIF_DEVICE_GET_IRQ_YIELD_PARAMS,
- &pDev->HifIRQYieldParams,
- sizeof(pDev->HifIRQYieldParams));
-
- if (pDev->HifIRQYieldParams.RecvPacketYieldCount > 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
- ("HIF requests that DSR yield per %d RECV packets \n",
- pDev->HifIRQYieldParams.RecvPacketYieldCount));
- pDev->DSRCanYield = true;
- }
- break;
- case HIF_DEVICE_IRQ_ASYNC_SYNC:
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n"));
- break;
- default:
- A_ASSERT(false);
- }
-
- pDev->HifMaskUmaskRecvEvent = NULL;
-
- /* see if the HIF layer implements the mask/unmask recv events function */
- HIFConfigureDevice(pDev->HIFDevice,
- HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC,
- &pDev->HifMaskUmaskRecvEvent,
- sizeof(pDev->HifMaskUmaskRecvEvent));
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%lX , 0x%lX\n",
- (unsigned long)pDev->GetPendingEventsFunc, (unsigned long)pDev->HifMaskUmaskRecvEvent));
-
- status = DevDisableInterrupts(pDev);
-
- if (status) {
- break;
- }
-
- status = DevSetupGMbox(pDev);
-
- } while (false);
-
- if (status) {
- if (pDev->HifAttached) {
- HIFDetachHTC(pDev->HIFDevice);
- pDev->HifAttached = false;
- }
- }
-
- return status;
-
-}
-
-int DevEnableInterrupts(struct ar6k_device *pDev)
-{
- int status;
- struct ar6k_irq_enable_registers regs;
-
- LOCK_AR6K(pDev);
-
- /* Enable all the interrupts except for the internal AR6000 CPU interrupt */
- pDev->IrqEnableRegisters.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) |
- INT_STATUS_ENABLE_CPU_SET(0x01) |
- INT_STATUS_ENABLE_COUNTER_SET(0x01);
-
- if (NULL == pDev->GetPendingEventsFunc) {
- pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
- } else {
- /* The HIF layer provided us with a pending events function which means that
- * the detection of pending mbox messages is handled in the HIF layer.
- * This is the case for the SPI2 interface.
- * In the normal case we enable MBOX interrupts, for the case
- * with HIFs that offer this mechanism, we keep these interrupts
- * masked */
- pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
- }
-
-
- /* Set up the CPU Interrupt Status Register */
- pDev->IrqEnableRegisters.cpu_int_status_enable = CPU_INT_STATUS_ENABLE_BIT_SET(0x00);
-
- /* Set up the Error Interrupt Status Register */
- pDev->IrqEnableRegisters.error_status_enable =
- ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01) |
- ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01);
-
- /* Set up the Counter Interrupt Status Register (only for debug interrupt to catch fatal errors) */
- pDev->IrqEnableRegisters.counter_int_status_enable =
- COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK);
-
- /* copy into our temp area */
- memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
-
- UNLOCK_AR6K(pDev);
-
- /* always synchronous */
- status = HIFReadWrite(pDev->HIFDevice,
- INT_STATUS_ENABLE_ADDRESS,
- &regs.int_status_enable,
- AR6K_IRQ_ENABLE_REGS_SIZE,
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-
- if (status) {
- /* Can't write it for some reason */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Failed to update interrupt control registers err: %d\n", status));
-
- }
-
- return status;
-}
-
-int DevDisableInterrupts(struct ar6k_device *pDev)
-{
- struct ar6k_irq_enable_registers regs;
-
- LOCK_AR6K(pDev);
- /* Disable all interrupts */
- pDev->IrqEnableRegisters.int_status_enable = 0;
- pDev->IrqEnableRegisters.cpu_int_status_enable = 0;
- pDev->IrqEnableRegisters.error_status_enable = 0;
- pDev->IrqEnableRegisters.counter_int_status_enable = 0;
- /* copy into our temp area */
- memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
-
- UNLOCK_AR6K(pDev);
-
- /* always synchronous */
- return HIFReadWrite(pDev->HIFDevice,
- INT_STATUS_ENABLE_ADDRESS,
- &regs.int_status_enable,
- AR6K_IRQ_ENABLE_REGS_SIZE,
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-}
-
-/* enable device interrupts */
-int DevUnmaskInterrupts(struct ar6k_device *pDev)
-{
- /* for good measure, make sure interrupt are disabled before unmasking at the HIF
- * layer.
- * The rationale here is that between device insertion (where we clear the interrupts the first time)
- * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets.
- * The AR6K interrupt enables reset back to an "enabled" state when this happens.
- * */
- int IntStatus = 0;
- DevDisableInterrupts(pDev);
-
-#ifdef THREAD_X
- // Tobe verified...
- IntStatus = DevEnableInterrupts(pDev);
- /* Unmask the host controller interrupts */
- HIFUnMaskInterrupt(pDev->HIFDevice);
-#else
- /* Unmask the host controller interrupts */
- HIFUnMaskInterrupt(pDev->HIFDevice);
- IntStatus = DevEnableInterrupts(pDev);
-#endif
-
- return IntStatus;
-}
-
-/* disable all device interrupts */
-int DevMaskInterrupts(struct ar6k_device *pDev)
-{
- /* mask the interrupt at the HIF layer, we don't want a stray interrupt taken while
- * we zero out our shadow registers in DevDisableInterrupts()*/
- HIFMaskInterrupt(pDev->HIFDevice);
-
- return DevDisableInterrupts(pDev);
-}
-
-/* callback when our fetch to enable/disable completes */
-static void DevDoEnableDisableRecvAsyncHandler(void *Context, struct htc_packet *pPacket)
-{
- struct ar6k_device *pDev = (struct ar6k_device *)Context;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
-
- if (pPacket->Status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- (" Failed to disable receiver, status:%d \n", pPacket->Status));
- }
- /* free this IO packet */
- AR6KFreeIOPacket(pDev,pPacket);
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDoEnableDisableRecvAsyncHandler \n"));
-}
-
-/* disable packet reception (used in case the host runs out of buffers)
- * this is the "override" method when the HIF reports another methods to
- * disable recv events */
-static int DevDoEnableDisableRecvOverride(struct ar6k_device *pDev, bool EnableRecv, bool AsyncMode)
-{
- int status = 0;
- struct htc_packet *pIOPacket = NULL;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n",
- EnableRecv,AsyncMode));
-
- do {
-
- if (AsyncMode) {
-
- pIOPacket = AR6KAllocIOPacket(pDev);
-
- if (NULL == pIOPacket) {
- status = A_NO_MEMORY;
- A_ASSERT(false);
- break;
- }
-
- /* stick in our completion routine when the I/O operation completes */
- pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
- pIOPacket->pContext = pDev;
-
- /* call the HIF layer override and do this asynchronously */
- status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice,
- EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
- pIOPacket);
- break;
- }
-
- /* if we get here we are doing it synchronously */
- status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice,
- EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
- NULL);
-
- } while (false);
-
- if (status && (pIOPacket != NULL)) {
- AR6KFreeIOPacket(pDev,pIOPacket);
- }
-
- return status;
-}
-
-/* disable packet reception (used in case the host runs out of buffers)
- * this is the "normal" method using the interrupt enable registers through
- * the host I/F */
-static int DevDoEnableDisableRecvNormal(struct ar6k_device *pDev, bool EnableRecv, bool AsyncMode)
-{
- int status = 0;
- struct htc_packet *pIOPacket = NULL;
- struct ar6k_irq_enable_registers regs;
-
- /* take the lock to protect interrupt enable shadows */
- LOCK_AR6K(pDev);
-
- if (EnableRecv) {
- pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
- } else {
- pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
- }
-
- /* copy into our temp area */
- memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
- UNLOCK_AR6K(pDev);
-
- do {
-
- if (AsyncMode) {
-
- pIOPacket = AR6KAllocIOPacket(pDev);
-
- if (NULL == pIOPacket) {
- status = A_NO_MEMORY;
- A_ASSERT(false);
- break;
- }
-
- /* copy values to write to our async I/O buffer */
- memcpy(pIOPacket->pBuffer,&regs,AR6K_IRQ_ENABLE_REGS_SIZE);
-
- /* stick in our completion routine when the I/O operation completes */
- pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
- pIOPacket->pContext = pDev;
-
- /* write it out asynchronously */
- HIFReadWrite(pDev->HIFDevice,
- INT_STATUS_ENABLE_ADDRESS,
- pIOPacket->pBuffer,
- AR6K_IRQ_ENABLE_REGS_SIZE,
- HIF_WR_ASYNC_BYTE_INC,
- pIOPacket);
- break;
- }
-
- /* if we get here we are doing it synchronously */
-
- status = HIFReadWrite(pDev->HIFDevice,
- INT_STATUS_ENABLE_ADDRESS,
- &regs.int_status_enable,
- AR6K_IRQ_ENABLE_REGS_SIZE,
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-
- } while (false);
-
- if (status && (pIOPacket != NULL)) {
- AR6KFreeIOPacket(pDev,pIOPacket);
- }
-
- return status;
-}
-
-
-int DevStopRecv(struct ar6k_device *pDev, bool AsyncMode)
-{
- if (NULL == pDev->HifMaskUmaskRecvEvent) {
- return DevDoEnableDisableRecvNormal(pDev,false,AsyncMode);
- } else {
- return DevDoEnableDisableRecvOverride(pDev,false,AsyncMode);
- }
-}
-
-int DevEnableRecv(struct ar6k_device *pDev, bool AsyncMode)
-{
- if (NULL == pDev->HifMaskUmaskRecvEvent) {
- return DevDoEnableDisableRecvNormal(pDev,true,AsyncMode);
- } else {
- return DevDoEnableDisableRecvOverride(pDev,true,AsyncMode);
- }
-}
-
-int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending)
-{
- int status = 0;
- u8 host_int_status = 0x0;
- u32 counter = 0x0;
-
- if(TimeoutInMs < 100)
- {
- TimeoutInMs = 100;
- }
-
- counter = TimeoutInMs / 100;
-
- do
- {
- //Read the Host Interrupt Status Register
- status = HIFReadWrite(pDev->HIFDevice,
- HOST_INT_STATUS_ADDRESS,
- &host_int_status,
- sizeof(u8),
- HIF_RD_SYNC_BYTE_INC,
- NULL);
- if (status)
- {
- AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status));
- break;
- }
-
- host_int_status = !status ? (host_int_status & (1 << 0)):0;
- if(!host_int_status)
- {
- status = 0;
- *pbIsRecvPending = false;
- break;
- }
- else
- {
- *pbIsRecvPending = true;
- }
-
- A_MDELAY(100);
-
- counter--;
-
- }while(counter);
- return status;
-}
-
-void DevDumpRegisters(struct ar6k_device *pDev,
- struct ar6k_irq_proc_registers *pIrqProcRegs,
- struct ar6k_irq_enable_registers *pIrqEnableRegs)
-{
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\n<------- Register Table -------->\n"));
-
- if (pIrqProcRegs != NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("Host Int Status: 0x%x\n",pIrqProcRegs->host_int_status));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("CPU Int Status: 0x%x\n",pIrqProcRegs->cpu_int_status));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("Error Int Status: 0x%x\n",pIrqProcRegs->error_int_status));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("Counter Int Status: 0x%x\n",pIrqProcRegs->counter_int_status));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("Mbox Frame: 0x%x\n",pIrqProcRegs->mbox_frame));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("Rx Lookahead Valid: 0x%x\n",pIrqProcRegs->rx_lookahead_valid));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("Rx Lookahead 0: 0x%x\n",pIrqProcRegs->rx_lookahead[0]));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("Rx Lookahead 1: 0x%x\n",pIrqProcRegs->rx_lookahead[1]));
-
- if (pDev->MailBoxInfo.GMboxAddress != 0) {
- /* if the target supports GMBOX hardware, dump some additional state */
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("GMBOX Host Int Status 2: 0x%x\n",pIrqProcRegs->host_int_status2));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("GMBOX RX Avail: 0x%x\n",pIrqProcRegs->gmbox_rx_avail));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("GMBOX lookahead alias 0: 0x%x\n",pIrqProcRegs->rx_gmbox_lookahead_alias[0]));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("GMBOX lookahead alias 1: 0x%x\n",pIrqProcRegs->rx_gmbox_lookahead_alias[1]));
- }
-
- }
-
- if (pIrqEnableRegs != NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("Int Status Enable: 0x%x\n",pIrqEnableRegs->int_status_enable));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("Counter Int Status Enable: 0x%x\n",pIrqEnableRegs->counter_int_status_enable));
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<------------------------------->\n"));
-}
-
-
-#define DEV_GET_VIRT_DMA_INFO(p) ((struct dev_scatter_dma_virtual_info *)((p)->HIFPrivate[0]))
-
-static struct hif_scatter_req *DevAllocScatterReq(struct hif_device *Context)
-{
- struct dl_list *pItem;
- struct ar6k_device *pDev = (struct ar6k_device *)Context;
- LOCK_AR6K(pDev);
- pItem = DL_ListRemoveItemFromHead(&pDev->ScatterReqHead);
- UNLOCK_AR6K(pDev);
- if (pItem != NULL) {
- return A_CONTAINING_STRUCT(pItem, struct hif_scatter_req, ListLink);
- }
- return NULL;
-}
-
-static void DevFreeScatterReq(struct hif_device *Context, struct hif_scatter_req *pReq)
-{
- struct ar6k_device *pDev = (struct ar6k_device *)Context;
- LOCK_AR6K(pDev);
- DL_ListInsertTail(&pDev->ScatterReqHead, &pReq->ListLink);
- UNLOCK_AR6K(pDev);
-}
-
-int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA)
-{
- u8 *pDMABuffer = NULL;
- int i, remaining;
- u32 length;
-
- pDMABuffer = pReq->pScatterBounceBuffer;
-
- if (pDMABuffer == NULL) {
- A_ASSERT(false);
- return A_EINVAL;
- }
-
- remaining = (int)pReq->TotalLength;
-
- for (i = 0; i < pReq->ValidScatterEntries; i++) {
-
- length = min((int)pReq->ScatterList[i].Length, remaining);
-
- if (length != (int)pReq->ScatterList[i].Length) {
- A_ASSERT(false);
- /* there is a problem with the scatter list */
- return A_EINVAL;
- }
-
- if (FromDMA) {
- /* from DMA buffer */
- memcpy(pReq->ScatterList[i].pBuffer, pDMABuffer , length);
- } else {
- /* to DMA buffer */
- memcpy(pDMABuffer, pReq->ScatterList[i].pBuffer, length);
- }
-
- pDMABuffer += length;
- remaining -= length;
- }
-
- return 0;
-}
-
-static void DevReadWriteScatterAsyncHandler(void *Context, struct htc_packet *pPacket)
-{
- struct ar6k_device *pDev = (struct ar6k_device *)Context;
- struct hif_scatter_req *pReq = (struct hif_scatter_req *)pPacket->pPktContext;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevReadWriteScatterAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
-
- pReq->CompletionStatus = pPacket->Status;
-
- AR6KFreeIOPacket(pDev,pPacket);
-
- pReq->CompletionRoutine(pReq);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevReadWriteScatterAsyncHandler \n"));
-}
-
-static int DevReadWriteScatter(struct hif_device *Context, struct hif_scatter_req *pReq)
-{
- struct ar6k_device *pDev = (struct ar6k_device *)Context;
- int status = 0;
- struct htc_packet *pIOPacket = NULL;
- u32 request = pReq->Request;
-
- do {
-
- if (pReq->TotalLength > AR6K_MAX_TRANSFER_SIZE_PER_SCATTER) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Invalid length: %d \n", pReq->TotalLength));
- break;
- }
-
- if (pReq->TotalLength == 0) {
- A_ASSERT(false);
- break;
- }
-
- if (request & HIF_ASYNCHRONOUS) {
- /* use an I/O packet to carry this request */
- pIOPacket = AR6KAllocIOPacket(pDev);
- if (NULL == pIOPacket) {
- status = A_NO_MEMORY;
- break;
- }
-
- /* save the request */
- pIOPacket->pPktContext = pReq;
- /* stick in our completion routine when the I/O operation completes */
- pIOPacket->Completion = DevReadWriteScatterAsyncHandler;
- pIOPacket->pContext = pDev;
- }
-
- if (request & HIF_WRITE) {
- /* in virtual DMA, we are issuing the requests through the legacy HIFReadWrite API
- * this API will adjust the address automatically for the last byte to fall on the mailbox
- * EOM. */
-
- /* if the address is an extended address, we can adjust the address here since the extended
- * address will bypass the normal checks in legacy HIF layers */
- if (pReq->Address == pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress) {
- pReq->Address += pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize - pReq->TotalLength;
- }
- }
-
- /* use legacy readwrite */
- status = HIFReadWrite(pDev->HIFDevice,
- pReq->Address,
- DEV_GET_VIRT_DMA_INFO(pReq)->pVirtDmaBuffer,
- pReq->TotalLength,
- request,
- (request & HIF_ASYNCHRONOUS) ? pIOPacket : NULL);
-
- } while (false);
-
- if ((status != A_PENDING) && status && (request & HIF_ASYNCHRONOUS)) {
- if (pIOPacket != NULL) {
- AR6KFreeIOPacket(pDev,pIOPacket);
- }
- pReq->CompletionStatus = status;
- pReq->CompletionRoutine(pReq);
- status = 0;
- }
-
- return status;
-}
-
-
-static void DevCleanupVirtualScatterSupport(struct ar6k_device *pDev)
-{
- struct hif_scatter_req *pReq;
-
- while (1) {
- pReq = DevAllocScatterReq((struct hif_device *)pDev);
- if (NULL == pReq) {
- break;
- }
- kfree(pReq);
- }
-
-}
-
- /* function to set up virtual scatter support if HIF layer has not implemented the interface */
-static int DevSetupVirtualScatterSupport(struct ar6k_device *pDev)
-{
- int status = 0;
- int bufferSize, sgreqSize;
- int i;
- struct dev_scatter_dma_virtual_info *pVirtualInfo;
- struct hif_scatter_req *pReq;
-
- bufferSize = sizeof(struct dev_scatter_dma_virtual_info) +
- 2 * (A_GET_CACHE_LINE_BYTES()) + AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
-
- sgreqSize = sizeof(struct hif_scatter_req) +
- (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(struct hif_scatter_item));
-
- for (i = 0; i < AR6K_SCATTER_REQS; i++) {
- /* allocate the scatter request, buffer info and the actual virtual buffer itself */
- pReq = (struct hif_scatter_req *)A_MALLOC(sgreqSize + bufferSize);
-
- if (NULL == pReq) {
- status = A_NO_MEMORY;
- break;
- }
-
- A_MEMZERO(pReq, sgreqSize);
-
- /* the virtual DMA starts after the scatter request struct */
- pVirtualInfo = (struct dev_scatter_dma_virtual_info *)((u8 *)pReq + sgreqSize);
- A_MEMZERO(pVirtualInfo, sizeof(struct dev_scatter_dma_virtual_info));
-
- pVirtualInfo->pVirtDmaBuffer = &pVirtualInfo->DataArea[0];
- /* align buffer to cache line in case host controller can actually DMA this */
- pVirtualInfo->pVirtDmaBuffer = A_ALIGN_TO_CACHE_LINE(pVirtualInfo->pVirtDmaBuffer);
- /* store the structure in the private area */
- pReq->HIFPrivate[0] = pVirtualInfo;
- /* we emulate a DMA bounce interface */
- pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE;
- pReq->pScatterBounceBuffer = pVirtualInfo->pVirtDmaBuffer;
- /* free request to the list */
- DevFreeScatterReq((struct hif_device *)pDev,pReq);
- }
-
- if (status) {
- DevCleanupVirtualScatterSupport(pDev);
- } else {
- pDev->HifScatterInfo.pAllocateReqFunc = DevAllocScatterReq;
- pDev->HifScatterInfo.pFreeReqFunc = DevFreeScatterReq;
- pDev->HifScatterInfo.pReadWriteScatterFunc = DevReadWriteScatter;
- if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K: SPI bus requires RX scatter limits\n"));
- pDev->HifScatterInfo.MaxScatterEntries = AR6K_MIN_SCATTER_ENTRIES_PER_REQ;
- pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MIN_TRANSFER_SIZE_PER_SCATTER;
- } else {
- pDev->HifScatterInfo.MaxScatterEntries = AR6K_SCATTER_ENTRIES_PER_REQ;
- pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
- }
- pDev->ScatterIsVirtual = true;
- }
-
- return status;
-}
-
-int DevCleanupMsgBundling(struct ar6k_device *pDev)
-{
- if(NULL != pDev)
- {
- DevCleanupVirtualScatterSupport(pDev);
- }
-
- return 0;
-}
-
-int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer)
-{
- int status;
-
- if (pDev->MailBoxInfo.Flags & HIF_MBOX_FLAG_NO_BUNDLING) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requires bundling disabled\n"));
- return A_ENOTSUP;
- }
-
- status = HIFConfigureDevice(pDev->HIFDevice,
- HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT,
- &pDev->HifScatterInfo,
- sizeof(pDev->HifScatterInfo));
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
- ("AR6K: ** HIF layer does not support scatter requests (%d) \n",status));
-
- /* we can try to use a virtual DMA scatter mechanism using legacy HIFReadWrite() */
- status = DevSetupVirtualScatterSupport(pDev);
-
- if (!status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("AR6K: virtual scatter transfers enabled (max scatter items:%d: maxlen:%d) \n",
- DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
- }
-
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("AR6K: HIF layer supports scatter requests (max scatter items:%d: maxlen:%d) \n",
- DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
- }
-
- if (!status) {
- /* for the recv path, the maximum number of bytes per recv bundle is just limited
- * by the maximum transfer size at the HIF layer */
- pDev->MaxRecvBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
-
- if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K : SPI bus requires TX bundling disabled\n"));
- pDev->MaxSendBundleSize = 0;
- } else {
- /* for the send path, the max transfer size is limited by the existence and size of
- * the extended mailbox address range */
- if (pDev->MailBoxInfo.MboxProp[0].ExtendedAddress != 0) {
- pDev->MaxSendBundleSize = pDev->MailBoxInfo.MboxProp[0].ExtendedSize;
- } else {
- /* legacy */
- pDev->MaxSendBundleSize = AR6K_LEGACY_MAX_WRITE_LENGTH;
- }
-
- if (pDev->MaxSendBundleSize > pDev->HifScatterInfo.MaxTransferSizePerScatterReq) {
- /* limit send bundle size to what the HIF can support for scatter requests */
- pDev->MaxSendBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("AR6K: max recv: %d max send: %d \n",
- DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev), DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)));
-
- }
- return status;
-}
-
-int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async)
-{
- int status;
-
- if (Read) {
- /* read operation */
- pScatterReq->Request = (Async) ? HIF_RD_ASYNC_BLOCK_FIX : HIF_RD_SYNC_BLOCK_FIX;
- pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
- A_ASSERT(pScatterReq->TotalLength <= (u32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev));
- } else {
- u32 mailboxWidth;
-
- /* write operation */
- pScatterReq->Request = (Async) ? HIF_WR_ASYNC_BLOCK_INC : HIF_WR_SYNC_BLOCK_INC;
- A_ASSERT(pScatterReq->TotalLength <= (u32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev));
- if (pScatterReq->TotalLength > AR6K_LEGACY_MAX_WRITE_LENGTH) {
- /* for large writes use the extended address */
- pScatterReq->Address = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress;
- mailboxWidth = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize;
- } else {
- pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
- mailboxWidth = AR6K_LEGACY_MAX_WRITE_LENGTH;
- }
-
- if (!pDev->ScatterIsVirtual) {
- /* we are passing this scatter list down to the HIF layer' scatter request handler, fixup the address
- * so that the last byte falls on the EOM, we do this for those HIFs that support the
- * scatter API */
- pScatterReq->Address += (mailboxWidth - pScatterReq->TotalLength);
- }
-
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV | ATH_DEBUG_SEND,
- ("DevSubmitScatterRequest, Entries: %d, Total Length: %d Mbox:0x%X (mode: %s : %s)\n",
- pScatterReq->ValidScatterEntries,
- pScatterReq->TotalLength,
- pScatterReq->Address,
- Async ? "ASYNC" : "SYNC",
- (Read) ? "RD" : "WR"));
-
- status = DEV_PREPARE_SCATTER_OPERATION(pScatterReq);
-
- if (status) {
- if (Async) {
- pScatterReq->CompletionStatus = status;
- pScatterReq->CompletionRoutine(pScatterReq);
- return 0;
- }
- return status;
- }
-
- status = pDev->HifScatterInfo.pReadWriteScatterFunc(pDev->ScatterIsVirtual ? pDev : pDev->HIFDevice,
- pScatterReq);
- if (!Async) {
- /* in sync mode, we can touch the scatter request */
- pScatterReq->CompletionStatus = status;
- DEV_FINISH_SCATTER_OPERATION(pScatterReq);
- } else {
- if (status == A_PENDING) {
- status = 0;
- }
- }
-
- return status;
-}
-
-
-#ifdef MBOXHW_UNIT_TEST
-
-
-/* This is a mailbox hardware unit test that must be called in a schedulable context
- * This test is very simple, it will send a list of buffers with a counting pattern
- * and the target will invert the data and send the message back
- *
- * the unit test has the following constraints:
- *
- * The target has at least 8 buffers of 256 bytes each. The host will send
- * the following pattern of buffers in rapid succession :
- *
- * 1 buffer - 128 bytes
- * 1 buffer - 256 bytes
- * 1 buffer - 512 bytes
- * 1 buffer - 1024 bytes
- *
- * The host will send the buffers to one mailbox and wait for buffers to be reflected
- * back from the same mailbox. The target sends the buffers FIFO order.
- * Once the final buffer has been received for a mailbox, the next mailbox is tested.
- *
- *
- * Note: To simplifythe test , we assume that the chosen buffer sizes
- * will fall on a nice block pad
- *
- * It is expected that higher-order tests will be written to stress the mailboxes using
- * a message-based protocol (with some performance timming) that can create more
- * randomness in the packets sent over mailboxes.
- *
- * */
-
-#define A_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1))
-
-#define BUFFER_BLOCK_PAD 128
-
-#if 0
-#define BUFFER1 128
-#define BUFFER2 256
-#define BUFFER3 512
-#define BUFFER4 1024
-#endif
-
-#if 1
-#define BUFFER1 80
-#define BUFFER2 200
-#define BUFFER3 444
-#define BUFFER4 800
-#endif
-
-#define TOTAL_BYTES (A_ROUND_UP_PWR2(BUFFER1,BUFFER_BLOCK_PAD) + \
- A_ROUND_UP_PWR2(BUFFER2,BUFFER_BLOCK_PAD) + \
- A_ROUND_UP_PWR2(BUFFER3,BUFFER_BLOCK_PAD) + \
- A_ROUND_UP_PWR2(BUFFER4,BUFFER_BLOCK_PAD) )
-
-#define TEST_BYTES (BUFFER1 + BUFFER2 + BUFFER3 + BUFFER4)
-
-#define TEST_CREDITS_RECV_TIMEOUT 100
-
-static u8 g_Buffer[TOTAL_BYTES];
-static u32 g_MailboxAddrs[AR6K_MAILBOXES];
-static u32 g_BlockSizes[AR6K_MAILBOXES];
-
-#define BUFFER_PROC_LIST_DEPTH 4
-
-struct buffer_proc_list {
- u8 *pBuffer;
- u32 length;
-};
-
-
-#define PUSH_BUFF_PROC_ENTRY(pList,len,pCurrpos) \
-{ \
- (pList)->pBuffer = (pCurrpos); \
- (pList)->length = (len); \
- (pCurrpos) += (len); \
- (pList)++; \
-}
-
-/* a simple and crude way to send different "message" sizes */
-static void AssembleBufferList(struct buffer_proc_list *pList)
-{
- u8 *pBuffer = g_Buffer;
-
-#if BUFFER_PROC_LIST_DEPTH < 4
-#error "Buffer processing list depth is not deep enough!!"
-#endif
-
- PUSH_BUFF_PROC_ENTRY(pList,BUFFER1,pBuffer);
- PUSH_BUFF_PROC_ENTRY(pList,BUFFER2,pBuffer);
- PUSH_BUFF_PROC_ENTRY(pList,BUFFER3,pBuffer);
- PUSH_BUFF_PROC_ENTRY(pList,BUFFER4,pBuffer);
-
-}
-
-#define FILL_ZERO true
-#define FILL_COUNTING false
-static void InitBuffers(bool Zero)
-{
- u16 *pBuffer16 = (u16 *)g_Buffer;
- int i;
-
- /* fill buffer with 16 bit counting pattern or zeros */
- for (i = 0; i < (TOTAL_BYTES / 2) ; i++) {
- if (!Zero) {
- pBuffer16[i] = (u16)i;
- } else {
- pBuffer16[i] = 0;
- }
- }
-}
-
-
-static bool CheckOneBuffer(u16 *pBuffer16, int Length)
-{
- int i;
- u16 startCount;
- bool success = true;
-
- /* get the starting count */
- startCount = pBuffer16[0];
- /* invert it, this is the expected value */
- startCount = ~startCount;
- /* scan the buffer and verify */
- for (i = 0; i < (Length / 2) ; i++,startCount++) {
- /* target will invert all the data */
- if ((u16)pBuffer16[i] != (u16)~startCount) {
- success = false;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Data Got:0x%X, Expecting:0x%X (offset:%d, total:%d) \n",
- pBuffer16[i], ((u16)~startCount), i, Length));
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("0x%X 0x%X 0x%X 0x%X \n",
- pBuffer16[i], pBuffer16[i + 1], pBuffer16[i + 2],pBuffer16[i+3]));
- break;
- }
- }
-
- return success;
-}
-
-static bool CheckBuffers(void)
-{
- int i;
- bool success = true;
- struct buffer_proc_list checkList[BUFFER_PROC_LIST_DEPTH];
-
- /* assemble the list */
- AssembleBufferList(checkList);
-
- /* scan the buffers and verify */
- for (i = 0; i < BUFFER_PROC_LIST_DEPTH ; i++) {
- success = CheckOneBuffer((u16 *)checkList[i].pBuffer, checkList[i].length);
- if (!success) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer : 0x%X, Length:%d failed verify \n",
- (u32)checkList[i].pBuffer, checkList[i].length));
- break;
- }
- }
-
- return success;
-}
-
- /* find the end marker for the last buffer we will be sending */
-static u16 GetEndMarker(void)
-{
- u8 *pBuffer;
- struct buffer_proc_list checkList[BUFFER_PROC_LIST_DEPTH];
-
- /* fill up buffers with the normal counting pattern */
- InitBuffers(FILL_COUNTING);
-
- /* assemble the list we will be sending down */
- AssembleBufferList(checkList);
- /* point to the last 2 bytes of the last buffer */
- pBuffer = &(checkList[BUFFER_PROC_LIST_DEPTH - 1].pBuffer[(checkList[BUFFER_PROC_LIST_DEPTH - 1].length) - 2]);
-
- /* the last count in the last buffer is the marker */
- return (u16)pBuffer[0] | ((u16)pBuffer[1] << 8);
-}
-
-#define ATH_PRINT_OUT_ZONE ATH_DEBUG_ERR
-
-/* send the ordered buffers to the target */
-static int SendBuffers(struct ar6k_device *pDev, int mbox)
-{
- int status = 0;
- u32 request = HIF_WR_SYNC_BLOCK_INC;
- struct buffer_proc_list sendList[BUFFER_PROC_LIST_DEPTH];
- int i;
- int totalBytes = 0;
- int paddedLength;
- int totalwPadding = 0;
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sending buffers on mailbox : %d \n",mbox));
-
- /* fill buffer with counting pattern */
- InitBuffers(FILL_COUNTING);
-
- /* assemble the order in which we send */
- AssembleBufferList(sendList);
-
- for (i = 0; i < BUFFER_PROC_LIST_DEPTH; i++) {
-
- /* we are doing block transfers, so we need to pad everything to a block size */
- paddedLength = (sendList[i].length + (g_BlockSizes[mbox] - 1)) &
- (~(g_BlockSizes[mbox] - 1));
-
- /* send each buffer synchronously */
- status = HIFReadWrite(pDev->HIFDevice,
- g_MailboxAddrs[mbox],
- sendList[i].pBuffer,
- paddedLength,
- request,
- NULL);
- if (status) {
- break;
- }
- totalBytes += sendList[i].length;
- totalwPadding += paddedLength;
- }
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sent %d bytes (%d padded bytes) to mailbox : %d \n",totalBytes,totalwPadding,mbox));
-
- return status;
-}
-
-/* poll the mailbox credit counter until we get a credit or timeout */
-static int GetCredits(struct ar6k_device *pDev, int mbox, int *pCredits)
-{
- int status = 0;
- int timeout = TEST_CREDITS_RECV_TIMEOUT;
- u8 credits = 0;
- u32 address;
-
- while (true) {
-
- /* Read the counter register to get credits, this auto-decrements */
- address = COUNT_DEC_ADDRESS + (AR6K_MAILBOXES + mbox) * 4;
- status = HIFReadWrite(pDev->HIFDevice, address, &credits, sizeof(credits),
- HIF_RD_SYNC_BYTE_FIX, NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Unable to decrement the command credit count register (mbox=%d)\n",mbox));
- status = A_ERROR;
- break;
- }
-
- if (credits) {
- break;
- }
-
- timeout--;
-
- if (timeout <= 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- (" Timeout reading credit registers (mbox=%d, address:0x%X) \n",mbox,address));
- status = A_ERROR;
- break;
- }
-
- /* delay a little, target may not be ready */
- A_MDELAY(1000);
-
- }
-
- if (status == 0) {
- *pCredits = credits;
- }
-
- return status;
-}
-
-
-/* wait for the buffers to come back */
-static int RecvBuffers(struct ar6k_device *pDev, int mbox)
-{
- int status = 0;
- u32 request = HIF_RD_SYNC_BLOCK_INC;
- struct buffer_proc_list recvList[BUFFER_PROC_LIST_DEPTH];
- int curBuffer;
- int credits;
- int i;
- int totalBytes = 0;
- int paddedLength;
- int totalwPadding = 0;
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for buffers on mailbox : %d \n",mbox));
-
- /* zero the buffers */
- InitBuffers(FILL_ZERO);
-
- /* assemble the order in which we should receive */
- AssembleBufferList(recvList);
-
- curBuffer = 0;
-
- while (curBuffer < BUFFER_PROC_LIST_DEPTH) {
-
- /* get number of buffers that have been completed, this blocks
- * until we get at least 1 credit or it times out */
- status = GetCredits(pDev, mbox, &credits);
-
- if (status) {
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got %d messages on mailbox : %d \n",credits, mbox));
-
- /* get all the buffers that are sitting on the queue */
- for (i = 0; i < credits; i++) {
- A_ASSERT(curBuffer < BUFFER_PROC_LIST_DEPTH);
- /* recv the current buffer synchronously, the buffers should come back in
- * order... with padding applied by the target */
- paddedLength = (recvList[curBuffer].length + (g_BlockSizes[mbox] - 1)) &
- (~(g_BlockSizes[mbox] - 1));
-
- status = HIFReadWrite(pDev->HIFDevice,
- g_MailboxAddrs[mbox],
- recvList[curBuffer].pBuffer,
- paddedLength,
- request,
- NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to read %d bytes on mailbox:%d : address:0x%X \n",
- recvList[curBuffer].length, mbox, g_MailboxAddrs[mbox]));
- break;
- }
-
- totalwPadding += paddedLength;
- totalBytes += recvList[curBuffer].length;
- curBuffer++;
- }
-
- if (status) {
- break;
- }
- /* go back and get some more */
- credits = 0;
- }
-
- if (totalBytes != TEST_BYTES) {
- A_ASSERT(false);
- } else {
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got all buffers on mbox:%d total recv :%d (w/Padding : %d) \n",
- mbox, totalBytes, totalwPadding));
- }
-
- return status;
-
-
-}
-
-static int DoOneMboxHWTest(struct ar6k_device *pDev, int mbox)
-{
- int status;
-
- do {
- /* send out buffers */
- status = SendBuffers(pDev,mbox);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Sending buffers Failed : %d mbox:%d\n",status,mbox));
- break;
- }
-
- /* go get them, this will block */
- status = RecvBuffers(pDev, mbox);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Recv buffers Failed : %d mbox:%d\n",status,mbox));
- break;
- }
-
- /* check the returned data patterns */
- if (!CheckBuffers()) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer Verify Failed : mbox:%d\n",mbox));
- status = A_ERROR;
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" Send/Recv success! mailbox : %d \n",mbox));
-
- } while (false);
-
- return status;
-}
-
-/* here is where the test starts */
-int DoMboxHWTest(struct ar6k_device *pDev)
-{
- int i;
- int status;
- int credits = 0;
- u8 params[4];
- int numBufs;
- int bufferSize;
- u16 temp;
-
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest START - \n"));
-
- do {
- /* get the addresses for all 4 mailboxes */
- status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
- g_MailboxAddrs, sizeof(g_MailboxAddrs));
-
- if (status) {
- A_ASSERT(false);
- break;
- }
-
- /* get the block sizes */
- status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
- g_BlockSizes, sizeof(g_BlockSizes));
-
- if (status) {
- A_ASSERT(false);
- break;
- }
-
- /* note, the HIF layer usually reports mbox 0 to have a block size of
- * 1, but our test wants to run in block-mode for all mailboxes, so we treat all mailboxes
- * the same. */
- g_BlockSizes[0] = g_BlockSizes[1];
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Block Size to use: %d \n",g_BlockSizes[0]));
-
- if (g_BlockSizes[1] > BUFFER_BLOCK_PAD) {
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("%d Block size is too large for buffer pad %d\n",
- g_BlockSizes[1], BUFFER_BLOCK_PAD));
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for target.... \n"));
-
- /* the target lets us know it is ready by giving us 1 credit on
- * mailbox 0 */
- status = GetCredits(pDev, 0, &credits);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait for target ready \n"));
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Target is ready ...\n"));
-
- /* read the first 4 scratch registers */
- status = HIFReadWrite(pDev->HIFDevice,
- SCRATCH_ADDRESS,
- params,
- 4,
- HIF_RD_SYNC_BYTE_INC,
- NULL);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait get parameters \n"));
- break;
- }
-
- numBufs = params[0];
- bufferSize = (int)(((u16)params[2] << 8) | (u16)params[1]);
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE,
- ("Target parameters: bufs per mailbox:%d, buffer size:%d bytes (total space: %d, minimum required space (w/padding): %d) \n",
- numBufs, bufferSize, (numBufs * bufferSize), TOTAL_BYTES));
-
- if ((numBufs * bufferSize) < TOTAL_BYTES) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Not Enough buffer space to run test! need:%d, got:%d \n",
- TOTAL_BYTES, (numBufs*bufferSize)));
- status = A_ERROR;
- break;
- }
-
- temp = GetEndMarker();
-
- status = HIFReadWrite(pDev->HIFDevice,
- SCRATCH_ADDRESS + 4,
- (u8 *)&temp,
- 2,
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write end marker \n"));
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("End Marker: 0x%X \n",temp));
-
- temp = (u16)g_BlockSizes[1];
- /* convert to a mask */
- temp = temp - 1;
- status = HIFReadWrite(pDev->HIFDevice,
- SCRATCH_ADDRESS + 6,
- (u8 *)&temp,
- 2,
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write block mask \n"));
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Set Block Mask: 0x%X \n",temp));
-
- /* execute the test on each mailbox */
- for (i = 0; i < AR6K_MAILBOXES; i++) {
- status = DoOneMboxHWTest(pDev, i);
- if (status) {
- break;
- }
- }
-
- } while (false);
-
- if (status == 0) {
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - SUCCESS! - \n"));
- } else {
- AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - FAILED! - \n"));
- }
- /* don't let HTC_Start continue, the target is actually not running any HTC code */
- return A_ERROR;
-}
-#endif
-
-
-
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k.h b/drivers/staging/ath6kl/htc2/AR6000/ar6k.h
deleted file mode 100644
index e551dbe674dc..000000000000
--- a/drivers/staging/ath6kl/htc2/AR6000/ar6k.h
+++ /dev/null
@@ -1,401 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="ar6k.h" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// AR6K device layer that handles register level I/O
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef AR6K_H_
-#define AR6K_H_
-
-#include "hci_transport_api.h"
-#include "../htc_debug.h"
-
-#define AR6K_MAILBOXES 4
-
-/* HTC runs over mailbox 0 */
-#define HTC_MAILBOX 0
-
-#define AR6K_TARGET_DEBUG_INTR_MASK 0x01
-
-#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \
- INT_STATUS_ENABLE_CPU_MASK | \
- INT_STATUS_ENABLE_COUNTER_MASK)
-
-
-//#define MBOXHW_UNIT_TEST 1
-
-PREPACK struct ar6k_irq_proc_registers {
- u8 host_int_status;
- u8 cpu_int_status;
- u8 error_int_status;
- u8 counter_int_status;
- u8 mbox_frame;
- u8 rx_lookahead_valid;
- u8 host_int_status2;
- u8 gmbox_rx_avail;
- u32 rx_lookahead[2];
- u32 rx_gmbox_lookahead_alias[2];
-} POSTPACK;
-
-#define AR6K_IRQ_PROC_REGS_SIZE sizeof(struct ar6k_irq_proc_registers)
-
-PREPACK struct ar6k_irq_enable_registers {
- u8 int_status_enable;
- u8 cpu_int_status_enable;
- u8 error_status_enable;
- u8 counter_int_status_enable;
-} POSTPACK;
-
-PREPACK struct ar6k_gmbox_ctrl_registers {
- u8 int_status_enable;
-} POSTPACK;
-
-#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(struct ar6k_irq_enable_registers)
-
-#define AR6K_REG_IO_BUFFER_SIZE 32
-#define AR6K_MAX_REG_IO_BUFFERS 8
-#define FROM_DMA_BUFFER true
-#define TO_DMA_BUFFER false
-#define AR6K_SCATTER_ENTRIES_PER_REQ 16
-#define AR6K_MAX_TRANSFER_SIZE_PER_SCATTER 16*1024
-#define AR6K_SCATTER_REQS 4
-#define AR6K_LEGACY_MAX_WRITE_LENGTH 2048
-
-#ifndef A_CACHE_LINE_PAD
-#define A_CACHE_LINE_PAD 128
-#endif
-#define AR6K_MIN_SCATTER_ENTRIES_PER_REQ 2
-#define AR6K_MIN_TRANSFER_SIZE_PER_SCATTER 4*1024
-
-/* buffers for ASYNC I/O */
-struct ar6k_async_reg_io_buffer {
- struct htc_packet HtcPacket; /* we use an HTC packet as a wrapper for our async register-based I/O */
- u8 _Pad1[A_CACHE_LINE_PAD];
- u8 Buffer[AR6K_REG_IO_BUFFER_SIZE]; /* cache-line safe with pads around */
- u8 _Pad2[A_CACHE_LINE_PAD];
-};
-
-struct ar6k_gmbox_info {
- void *pProtocolContext;
- int (*pMessagePendingCallBack)(void *pContext, u8 LookAheadBytes[], int ValidBytes);
- int (*pCreditsPendingCallback)(void *pContext, int NumCredits, bool CreditIRQEnabled);
- void (*pTargetFailureCallback)(void *pContext, int Status);
- void (*pStateDumpCallback)(void *pContext);
- bool CreditCountIRQEnabled;
-};
-
-struct ar6k_device {
- A_MUTEX_T Lock;
- u8 _Pad1[A_CACHE_LINE_PAD];
- struct ar6k_irq_proc_registers IrqProcRegisters; /* cache-line safe with pads around */
- u8 _Pad2[A_CACHE_LINE_PAD];
- struct ar6k_irq_enable_registers IrqEnableRegisters; /* cache-line safe with pads around */
- u8 _Pad3[A_CACHE_LINE_PAD];
- void *HIFDevice;
- u32 BlockSize;
- u32 BlockMask;
- struct hif_device_mbox_info MailBoxInfo;
- HIF_PENDING_EVENTS_FUNC GetPendingEventsFunc;
- void *HTCContext;
- struct htc_packet_queue RegisterIOList;
- struct ar6k_async_reg_io_buffer RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS];
- void (*TargetFailureCallback)(void *Context);
- int (*MessagePendingCallback)(void *Context,
- u32 LookAheads[],
- int NumLookAheads,
- bool *pAsyncProc,
- int *pNumPktsFetched);
- HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode;
- HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent;
- bool HifAttached;
- struct hif_device_irq_yield_params HifIRQYieldParams;
- bool DSRCanYield;
- int CurrentDSRRecvCount;
- struct hif_device_scatter_support_info HifScatterInfo;
- struct dl_list ScatterReqHead;
- bool ScatterIsVirtual;
- int MaxRecvBundleSize;
- int MaxSendBundleSize;
- struct ar6k_gmbox_info GMboxInfo;
- bool GMboxEnabled;
- struct ar6k_gmbox_ctrl_registers GMboxControlRegisters;
- int RecheckIRQStatusCnt;
-};
-
-#define LOCK_AR6K(p) A_MUTEX_LOCK(&(p)->Lock);
-#define UNLOCK_AR6K(p) A_MUTEX_UNLOCK(&(p)->Lock);
-#define REF_IRQ_STATUS_RECHECK(p) (p)->RecheckIRQStatusCnt = 1 /* note: no need to lock this, it only gets set */
-
-int DevSetup(struct ar6k_device *pDev);
-void DevCleanup(struct ar6k_device *pDev);
-int DevUnmaskInterrupts(struct ar6k_device *pDev);
-int DevMaskInterrupts(struct ar6k_device *pDev);
-int DevPollMboxMsgRecv(struct ar6k_device *pDev,
- u32 *pLookAhead,
- int TimeoutMS);
-int DevRWCompletionHandler(void *context, int status);
-int DevDsrHandler(void *context);
-int DevCheckPendingRecvMsgsAsync(void *context);
-void DevAsyncIrqProcessComplete(struct ar6k_device *pDev);
-void DevDumpRegisters(struct ar6k_device *pDev,
- struct ar6k_irq_proc_registers *pIrqProcRegs,
- struct ar6k_irq_enable_registers *pIrqEnableRegs);
-
-#define DEV_STOP_RECV_ASYNC true
-#define DEV_STOP_RECV_SYNC false
-#define DEV_ENABLE_RECV_ASYNC true
-#define DEV_ENABLE_RECV_SYNC false
-int DevStopRecv(struct ar6k_device *pDev, bool ASyncMode);
-int DevEnableRecv(struct ar6k_device *pDev, bool ASyncMode);
-int DevEnableInterrupts(struct ar6k_device *pDev);
-int DevDisableInterrupts(struct ar6k_device *pDev);
-int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending);
-
-#define DEV_CALC_RECV_PADDED_LEN(pDev, length) (((length) + (pDev)->BlockMask) & (~((pDev)->BlockMask)))
-#define DEV_CALC_SEND_PADDED_LEN(pDev, length) DEV_CALC_RECV_PADDED_LEN(pDev,length)
-#define DEV_IS_LEN_BLOCK_ALIGNED(pDev, length) (((length) % (pDev)->BlockSize) == 0)
-
-static INLINE int DevSendPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 SendLength) {
- u32 paddedLength;
- bool sync = (pPacket->Completion == NULL) ? true : false;
- int status;
-
- /* adjust the length to be a multiple of block size if appropriate */
- paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, SendLength);
-
-#if 0
- if (paddedLength > pPacket->BufferLength) {
- A_ASSERT(false);
- if (pPacket->Completion != NULL) {
- COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
- return 0;
- }
- return A_EINVAL;
- }
-#endif
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
- ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n",
- paddedLength,
- pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
- sync ? "SYNC" : "ASYNC"));
-
- status = HIFReadWrite(pDev->HIFDevice,
- pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
- pPacket->pBuffer,
- paddedLength, /* the padded length */
- sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC,
- sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
-
- if (sync) {
- pPacket->Status = status;
- } else {
- if (status == A_PENDING) {
- status = 0;
- }
- }
-
- return status;
-}
-
-static INLINE int DevRecvPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 RecvLength) {
- u32 paddedLength;
- int status;
- bool sync = (pPacket->Completion == NULL) ? true : false;
-
- /* adjust the length to be a multiple of block size if appropriate */
- paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, RecvLength);
-
- if (paddedLength > pPacket->BufferLength) {
- A_ASSERT(false);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
- paddedLength,RecvLength,pPacket->BufferLength));
- if (pPacket->Completion != NULL) {
- COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
- return 0;
- }
- return A_EINVAL;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("DevRecvPacket (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n",
- (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr,
- paddedLength,
- pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
- sync ? "SYNC" : "ASYNC"));
-
- status = HIFReadWrite(pDev->HIFDevice,
- pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
- pPacket->pBuffer,
- paddedLength,
- sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX,
- sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
-
- if (sync) {
- pPacket->Status = status;
- }
-
- return status;
-}
-
-#define DEV_CHECK_RECV_YIELD(pDev) \
- ((pDev)->CurrentDSRRecvCount >= (pDev)->HifIRQYieldParams.RecvPacketYieldCount)
-
-#define IS_DEV_IRQ_PROC_SYNC_MODE(pDev) (HIF_DEVICE_IRQ_SYNC_ONLY == (pDev)->HifIRQProcessingMode)
-#define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY)
-
-/**************************************************/
-/****** Scatter Function and Definitions
- *
- *
- */
-
-int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA);
-
- /* copy any READ data back into scatter list */
-#define DEV_FINISH_SCATTER_OPERATION(pR) \
-do { \
- if (!((pR)->CompletionStatus) && \
- !((pR)->Request & HIF_WRITE) && \
- ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) { \
- (pR)->CompletionStatus = \
- DevCopyScatterListToFromDMABuffer((pR), \
- FROM_DMA_BUFFER); \
- } \
-} while (0)
-
- /* copy any WRITE data to bounce buffer */
-static INLINE int DEV_PREPARE_SCATTER_OPERATION(struct hif_scatter_req *pReq) {
- if ((pReq->Request & HIF_WRITE) && (pReq->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {
- return DevCopyScatterListToFromDMABuffer(pReq,TO_DMA_BUFFER);
- } else {
- return 0;
- }
-}
-
-
-int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer);
-
-int DevCleanupMsgBundling(struct ar6k_device *pDev);
-
-#define DEV_GET_MAX_MSG_PER_BUNDLE(pDev) (pDev)->HifScatterInfo.MaxScatterEntries
-#define DEV_GET_MAX_BUNDLE_LENGTH(pDev) (pDev)->HifScatterInfo.MaxTransferSizePerScatterReq
-#define DEV_ALLOC_SCATTER_REQ(pDev) \
- (pDev)->HifScatterInfo.pAllocateReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice)
-
-#define DEV_FREE_SCATTER_REQ(pDev,pR) \
- (pDev)->HifScatterInfo.pFreeReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice,(pR))
-
-#define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev) (pDev)->MaxRecvBundleSize
-#define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev) (pDev)->MaxSendBundleSize
-
-#define DEV_SCATTER_READ true
-#define DEV_SCATTER_WRITE false
-#define DEV_SCATTER_ASYNC true
-#define DEV_SCATTER_SYNC false
-int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async);
-
-#ifdef MBOXHW_UNIT_TEST
-int DoMboxHWTest(struct ar6k_device *pDev);
-#endif
-
- /* completely virtual */
-struct dev_scatter_dma_virtual_info {
- u8 *pVirtDmaBuffer; /* dma-able buffer - CPU accessible address */
- u8 DataArea[1]; /* start of data area */
-};
-
-
-
-void DumpAR6KDevState(struct ar6k_device *pDev);
-
-/**************************************************/
-/****** GMBOX functions and definitions
- *
- *
- */
-
-#ifdef ATH_AR6K_ENABLE_GMBOX
-
-void DevCleanupGMbox(struct ar6k_device *pDev);
-int DevSetupGMbox(struct ar6k_device *pDev);
-int DevCheckGMboxInterrupts(struct ar6k_device *pDev);
-void DevNotifyGMboxTargetFailure(struct ar6k_device *pDev);
-
-#else
-
- /* compiled out */
-#define DevCleanupGMbox(p)
-#define DevCheckGMboxInterrupts(p) 0
-#define DevNotifyGMboxTargetFailure(p)
-
-static INLINE int DevSetupGMbox(struct ar6k_device *pDev) {
- pDev->GMboxEnabled = false;
- return 0;
-}
-
-#endif
-
-#ifdef ATH_AR6K_ENABLE_GMBOX
-
- /* GMBOX protocol modules must expose each of these internal APIs */
-HCI_TRANSPORT_HANDLE GMboxAttachProtocol(struct ar6k_device *pDev, struct hci_transport_config_info *pInfo);
-int GMboxProtocolInstall(struct ar6k_device *pDev);
-void GMboxProtocolUninstall(struct ar6k_device *pDev);
-
- /* API used by GMBOX protocol modules */
-struct ar6k_device *HTCGetAR6KDevice(void *HTCHandle);
-#define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,statedump,context) \
-{ \
- (pDev)->GMboxInfo.pProtocolContext = (context); \
- (pDev)->GMboxInfo.pMessagePendingCallBack = (recv_callback); \
- (pDev)->GMboxInfo.pCreditsPendingCallback = (credits_pending); \
- (pDev)->GMboxInfo.pTargetFailureCallback = (failure); \
- (pDev)->GMboxInfo.pStateDumpCallback = (statedump); \
-}
-
-#define DEV_GMBOX_GET_PROTOCOL(pDev) (pDev)->GMboxInfo.pProtocolContext
-
-int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength);
-int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength);
-
-#define PROC_IO_ASYNC true
-#define PROC_IO_SYNC false
-typedef enum GMBOX_IRQ_ACTION_TYPE {
- GMBOX_ACTION_NONE = 0,
- GMBOX_DISABLE_ALL,
- GMBOX_ERRORS_IRQ_ENABLE,
- GMBOX_RECV_IRQ_ENABLE,
- GMBOX_RECV_IRQ_DISABLE,
- GMBOX_CREDIT_IRQ_ENABLE,
- GMBOX_CREDIT_IRQ_DISABLE,
-} GMBOX_IRQ_ACTION_TYPE;
-
-int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE, bool AsyncMode);
-int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits);
-int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize);
-int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes);
-int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int SignalNumber, int AckTimeoutMS);
-
-#endif
-
-#endif /*AR6K_H_*/
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c
deleted file mode 100644
index d7af68f70560..000000000000
--- a/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c
+++ /dev/null
@@ -1,783 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="ar6k_events.c" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// AR6K Driver layer event handling (i.e. interrupts, message polling)
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-#include "a_config.h"
-#include "athdefs.h"
-#include "hw/mbox_host_reg.h"
-#include "a_osapi.h"
-#include "../htc_debug.h"
-#include "hif.h"
-#include "htc_packet.h"
-#include "ar6k.h"
-
-extern void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket);
-extern struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev);
-
-static int DevServiceDebugInterrupt(struct ar6k_device *pDev);
-
-#define DELAY_PER_INTERVAL_MS 10 /* 10 MS delay per polling interval */
-
-/* completion routine for ALL HIF layer async I/O */
-int DevRWCompletionHandler(void *context, int status)
-{
- struct htc_packet *pPacket = (struct htc_packet *)context;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("+DevRWCompletionHandler (Pkt:0x%lX) , Status: %d \n",
- (unsigned long)pPacket,
- status));
-
- COMPLETE_HTC_PACKET(pPacket,status);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("-DevRWCompletionHandler\n"));
-
- return 0;
-}
-
-/* mailbox recv message polling */
-int DevPollMboxMsgRecv(struct ar6k_device *pDev,
- u32 *pLookAhead,
- int TimeoutMS)
-{
- int status = 0;
- int timeout = TimeoutMS/DELAY_PER_INTERVAL_MS;
-
- A_ASSERT(timeout > 0);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n"));
-
- while (true) {
-
- if (pDev->GetPendingEventsFunc != NULL) {
-
- struct hif_pending_events_info events;
-
-#ifdef THREAD_X
- events.Polling =1;
-#endif
-
- /* the HIF layer uses a special mechanism to get events, do this
- * synchronously */
- status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
- &events,
- NULL);
- if (status)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n"));
- break;
- }
-
- if (events.Events & HIF_RECV_MSG_AVAIL)
- {
- /* there is a message available, the lookahead should be valid now */
- *pLookAhead = events.LookAhead;
-
- break;
- }
- } else {
-
- /* this is the standard HIF way.... */
- /* load the register table */
- status = HIFReadWrite(pDev->HIFDevice,
- HOST_INT_STATUS_ADDRESS,
- (u8 *)&pDev->IrqProcRegisters,
- AR6K_IRQ_PROC_REGS_SIZE,
- HIF_RD_SYNC_BYTE_INC,
- NULL);
-
- if (status){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n"));
- break;
- }
-
- /* check for MBOX data and valid lookahead */
- if (pDev->IrqProcRegisters.host_int_status & (1 << HTC_MAILBOX)) {
- if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX))
- {
- /* mailbox has a message and the look ahead is valid */
- *pLookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX];
- break;
- }
- }
-
- }
-
- timeout--;
-
- if (timeout <= 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Timeout waiting for recv message \n"));
- status = A_ERROR;
-
- /* check if the target asserted */
- if ( pDev->IrqProcRegisters.counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) {
- /* target signaled an assert, process this pending interrupt
- * this will call the target failure handler */
- DevServiceDebugInterrupt(pDev);
- }
-
- break;
- }
-
- /* delay a little */
- A_MDELAY(DELAY_PER_INTERVAL_MS);
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Retry Mbox Poll : %d \n",timeout));
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevPollMboxMsgRecv \n"));
-
- return status;
-}
-
-static int DevServiceCPUInterrupt(struct ar6k_device *pDev)
-{
- int status;
- u8 cpu_int_status;
- u8 regBuffer[4];
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n"));
- cpu_int_status = pDev->IrqProcRegisters.cpu_int_status &
- pDev->IrqEnableRegisters.cpu_int_status_enable;
- A_ASSERT(cpu_int_status);
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
- ("Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n",
- cpu_int_status));
-
- /* Clear the interrupt */
- pDev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status; /* W1C */
-
- /* set up the register transfer buffer to hit the register 4 times , this is done
- * to make the access 4-byte aligned to mitigate issues with host bus interconnects that
- * restrict bus transfer lengths to be a multiple of 4-bytes */
-
- /* set W1C value to clear the interrupt, this hits the register first */
- regBuffer[0] = cpu_int_status;
- /* the remaining 4 values are set to zero which have no-effect */
- regBuffer[1] = 0;
- regBuffer[2] = 0;
- regBuffer[3] = 0;
-
- status = HIFReadWrite(pDev->HIFDevice,
- CPU_INT_STATUS_ADDRESS,
- regBuffer,
- 4,
- HIF_WR_SYNC_BYTE_FIX,
- NULL);
-
- A_ASSERT(status == 0);
- return status;
-}
-
-
-static int DevServiceErrorInterrupt(struct ar6k_device *pDev)
-{
- int status;
- u8 error_int_status;
- u8 regBuffer[4];
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n"));
- error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F;
- A_ASSERT(error_int_status);
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
- ("Valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n",
- error_int_status));
-
- if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) {
- /* Wakeup */
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n"));
- }
-
- if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) {
- /* Rx Underflow */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Rx Underflow\n"));
- }
-
- if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) {
- /* Tx Overflow */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Tx Overflow\n"));
- }
-
- /* Clear the interrupt */
- pDev->IrqProcRegisters.error_int_status &= ~error_int_status; /* W1C */
-
- /* set up the register transfer buffer to hit the register 4 times , this is done
- * to make the access 4-byte aligned to mitigate issues with host bus interconnects that
- * restrict bus transfer lengths to be a multiple of 4-bytes */
-
- /* set W1C value to clear the interrupt, this hits the register first */
- regBuffer[0] = error_int_status;
- /* the remaining 4 values are set to zero which have no-effect */
- regBuffer[1] = 0;
- regBuffer[2] = 0;
- regBuffer[3] = 0;
-
- status = HIFReadWrite(pDev->HIFDevice,
- ERROR_INT_STATUS_ADDRESS,
- regBuffer,
- 4,
- HIF_WR_SYNC_BYTE_FIX,
- NULL);
-
- A_ASSERT(status == 0);
- return status;
-}
-
-static int DevServiceDebugInterrupt(struct ar6k_device *pDev)
-{
- u32 dummy;
- int status;
-
- /* Send a target failure event to the application */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n"));
-
- if (pDev->TargetFailureCallback != NULL) {
- pDev->TargetFailureCallback(pDev->HTCContext);
- }
-
- if (pDev->GMboxEnabled) {
- DevNotifyGMboxTargetFailure(pDev);
- }
-
- /* clear the interrupt , the debug error interrupt is
- * counter 0 */
- /* read counter to clear interrupt */
- status = HIFReadWrite(pDev->HIFDevice,
- COUNT_DEC_ADDRESS,
- (u8 *)&dummy,
- 4,
- HIF_RD_SYNC_BYTE_INC,
- NULL);
-
- A_ASSERT(status == 0);
- return status;
-}
-
-static int DevServiceCounterInterrupt(struct ar6k_device *pDev)
-{
- u8 counter_int_status;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n"));
-
- counter_int_status = pDev->IrqProcRegisters.counter_int_status &
- pDev->IrqEnableRegisters.counter_int_status_enable;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
- ("Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n",
- counter_int_status));
-
- /* Check if the debug interrupt is pending
- * NOTE: other modules like GMBOX may use the counter interrupt for
- * credit flow control on other counters, we only need to check for the debug assertion
- * counter interrupt */
- if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) {
- return DevServiceDebugInterrupt(pDev);
- }
-
- return 0;
-}
-
-/* callback when our fetch to get interrupt status registers completes */
-static void DevGetEventAsyncHandler(void *Context, struct htc_packet *pPacket)
-{
- struct ar6k_device *pDev = (struct ar6k_device *)Context;
- u32 lookAhead = 0;
- bool otherInts = false;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
-
- do {
-
- if (pPacket->Status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- (" GetEvents I/O request failed, status:%d \n", pPacket->Status));
- /* bail out, don't unmask HIF interrupt */
- break;
- }
-
- if (pDev->GetPendingEventsFunc != NULL) {
- /* the HIF layer collected the information for us */
- struct hif_pending_events_info *pEvents = (struct hif_pending_events_info *)pPacket->pBuffer;
- if (pEvents->Events & HIF_RECV_MSG_AVAIL) {
- lookAhead = pEvents->LookAhead;
- if (0 == lookAhead) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler1, lookAhead is zero! \n"));
- }
- }
- if (pEvents->Events & HIF_OTHER_EVENTS) {
- otherInts = true;
- }
- } else {
- /* standard interrupt table handling.... */
- struct ar6k_irq_proc_registers *pReg = (struct ar6k_irq_proc_registers *)pPacket->pBuffer;
- u8 host_int_status;
-
- host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.int_status_enable;
-
- if (host_int_status & (1 << HTC_MAILBOX)) {
- host_int_status &= ~(1 << HTC_MAILBOX);
- if (pReg->rx_lookahead_valid & (1 << HTC_MAILBOX)) {
- /* mailbox has a message and the look ahead is valid */
- lookAhead = pReg->rx_lookahead[HTC_MAILBOX];
- if (0 == lookAhead) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler2, lookAhead is zero! \n"));
- }
- }
- }
-
- if (host_int_status) {
- /* there are other interrupts to handle */
- otherInts = true;
- }
- }
-
- if (otherInts || (lookAhead == 0)) {
- /* if there are other interrupts to process, we cannot do this in the async handler so
- * ack the interrupt which will cause our sync handler to run again
- * if however there are no more messages, we can now ack the interrupt */
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
- (" Acking interrupt from DevGetEventAsyncHandler (otherints:%d, lookahead:0x%X)\n",
- otherInts, lookAhead));
- HIFAckInterrupt(pDev->HIFDevice);
- } else {
- int fetched = 0;
- int status;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
- (" DevGetEventAsyncHandler : detected another message, lookahead :0x%X \n",
- lookAhead));
- /* lookahead is non-zero and there are no other interrupts to service,
- * go get the next message */
- status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, NULL, &fetched);
-
- if (!status && !fetched) {
- /* HTC layer could not pull out messages due to lack of resources, stop IRQ processing */
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("MessagePendingCallback did not pull any messages, force-ack \n"));
- DevAsyncIrqProcessComplete(pDev);
- }
- }
-
- } while (false);
-
- /* free this IO packet */
- AR6KFreeIOPacket(pDev,pPacket);
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n"));
-}
-
-/* called by the HTC layer when it wants us to check if the device has any more pending
- * recv messages, this starts off a series of async requests to read interrupt registers */
-int DevCheckPendingRecvMsgsAsync(void *context)
-{
- struct ar6k_device *pDev = (struct ar6k_device *)context;
- int status = 0;
- struct htc_packet *pIOPacket;
-
- /* this is called in an ASYNC only context, we may NOT block, sleep or call any apis that can
- * cause us to switch contexts */
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%lX)\n", (unsigned long)pDev));
-
- do {
-
- if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) {
- /* break the async processing chain right here, no need to continue.
- * The DevDsrHandler() will handle things in a loop when things are driven
- * synchronously */
- break;
- }
-
- /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake
- * the target, if upper layers determine that we are in a low-throughput mode, we can
- * rely on taking another interrupt rather than re-checking the status registers which can
- * re-wake the target */
- if (pDev->RecheckIRQStatusCnt == 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, re-acking HIF interrupts\n"));
- /* ack interrupt */
- HIFAckInterrupt(pDev->HIFDevice);
- break;
- }
-
- /* first allocate one of our HTC packets we created for async I/O
- * we reuse HTC packet definitions so that we can use the completion mechanism
- * in DevRWCompletionHandler() */
- pIOPacket = AR6KAllocIOPacket(pDev);
-
- if (NULL == pIOPacket) {
- /* there should be only 1 asynchronous request out at a time to read these registers
- * so this should actually never happen */
- status = A_NO_MEMORY;
- A_ASSERT(false);
- break;
- }
-
- /* stick in our completion routine when the I/O operation completes */
- pIOPacket->Completion = DevGetEventAsyncHandler;
- pIOPacket->pContext = pDev;
-
- if (pDev->GetPendingEventsFunc) {
- /* HIF layer has it's own mechanism, pass the IO to it.. */
- status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
- (struct hif_pending_events_info *)pIOPacket->pBuffer,
- pIOPacket);
-
- } else {
- /* standard way, read the interrupt register table asynchronously again */
- status = HIFReadWrite(pDev->HIFDevice,
- HOST_INT_STATUS_ADDRESS,
- pIOPacket->pBuffer,
- AR6K_IRQ_PROC_REGS_SIZE,
- HIF_RD_ASYNC_BYTE_INC,
- pIOPacket);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status...\n"));
- } while (false);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n"));
-
- return status;
-}
-
-void DevAsyncIrqProcessComplete(struct ar6k_device *pDev)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("DevAsyncIrqProcessComplete - forcing HIF IRQ ACK \n"));
- HIFAckInterrupt(pDev->HIFDevice);
-}
-
-/* process pending interrupts synchronously */
-static int ProcessPendingIRQs(struct ar6k_device *pDev, bool *pDone, bool *pASyncProcessing)
-{
- int status = 0;
- u8 host_int_status = 0;
- u32 lookAhead = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%lX)\n", (unsigned long)pDev));
-
- /*** NOTE: the HIF implementation guarantees that the context of this call allows
- * us to perform SYNCHRONOUS I/O, that is we can block, sleep or call any API that
- * can block or switch thread/task ontexts.
- * This is a fully schedulable context.
- * */
- do {
-
- if (pDev->IrqEnableRegisters.int_status_enable == 0) {
- /* interrupt enables have been cleared, do not try to process any pending interrupts that
- * may result in more bus transactions. The target may be unresponsive at this
- * point. */
- break;
- }
-
- if (pDev->GetPendingEventsFunc != NULL) {
- struct hif_pending_events_info events;
-
-#ifdef THREAD_X
- events.Polling= 0;
-#endif
- /* the HIF layer uses a special mechanism to get events
- * get this synchronously */
- status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
- &events,
- NULL);
-
- if (status) {
- break;
- }
-
- if (events.Events & HIF_RECV_MSG_AVAIL) {
- lookAhead = events.LookAhead;
- if (0 == lookAhead) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs1 lookAhead is zero! \n"));
- }
- }
-
- if (!(events.Events & HIF_OTHER_EVENTS) ||
- !(pDev->IrqEnableRegisters.int_status_enable & OTHER_INTS_ENABLED)) {
- /* no need to read the register table, no other interesting interrupts.
- * Some interfaces (like SPI) can shadow interrupt sources without
- * requiring the host to do a full table read */
- break;
- }
-
- /* otherwise fall through and read the register table */
- }
-
- /*
- * Read the first 28 bytes of the HTC register table. This will yield us
- * the value of different int status registers and the lookahead
- * registers.
- * length = sizeof(int_status) + sizeof(cpu_int_status) +
- * sizeof(error_int_status) + sizeof(counter_int_status) +
- * sizeof(mbox_frame) + sizeof(rx_lookahead_valid) +
- * sizeof(hole) + sizeof(rx_lookahead) +
- * sizeof(int_status_enable) + sizeof(cpu_int_status_enable) +
- * sizeof(error_status_enable) +
- * sizeof(counter_int_status_enable);
- *
- */
-#ifdef CONFIG_MMC_SDHCI_S3C
- pDev->IrqProcRegisters.host_int_status = 0;
- pDev->IrqProcRegisters.rx_lookahead_valid = 0;
- pDev->IrqProcRegisters.host_int_status2 = 0;
- pDev->IrqProcRegisters.rx_lookahead[0] = 0;
- pDev->IrqProcRegisters.rx_lookahead[1] = 0xaaa5555;
-#endif /* CONFIG_MMC_SDHCI_S3C */
- status = HIFReadWrite(pDev->HIFDevice,
- HOST_INT_STATUS_ADDRESS,
- (u8 *)&pDev->IrqProcRegisters,
- AR6K_IRQ_PROC_REGS_SIZE,
- HIF_RD_SYNC_BYTE_INC,
- NULL);
-
- if (status) {
- break;
- }
-
-#ifdef ATH_DEBUG_MODULE
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) {
- DevDumpRegisters(pDev,
- &pDev->IrqProcRegisters,
- &pDev->IrqEnableRegisters);
- }
-#endif
-
- /* Update only those registers that are enabled */
- host_int_status = pDev->IrqProcRegisters.host_int_status &
- pDev->IrqEnableRegisters.int_status_enable;
-
- if (NULL == pDev->GetPendingEventsFunc) {
- /* only look at mailbox status if the HIF layer did not provide this function,
- * on some HIF interfaces reading the RX lookahead is not valid to do */
- if (host_int_status & (1 << HTC_MAILBOX)) {
- /* mask out pending mailbox value, we use "lookAhead" as the real flag for
- * mailbox processing below */
- host_int_status &= ~(1 << HTC_MAILBOX);
- if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX)) {
- /* mailbox has a message and the look ahead is valid */
- lookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX];
- if (0 == lookAhead) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs2, lookAhead is zero! \n"));
- }
- }
- }
- } else {
- /* not valid to check if the HIF has another mechanism for reading mailbox pending status*/
- host_int_status &= ~(1 << HTC_MAILBOX);
- }
-
- if (pDev->GMboxEnabled) {
- /*call GMBOX layer to process any interrupts of interest */
- status = DevCheckGMboxInterrupts(pDev);
- }
-
- } while (false);
-
-
- do {
-
- /* did the interrupt status fetches succeed? */
- if (status) {
- break;
- }
-
- if ((0 == host_int_status) && (0 == lookAhead)) {
- /* nothing to process, the caller can use this to break out of a loop */
- *pDone = true;
- break;
- }
-
- if (lookAhead != 0) {
- int fetched = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Pending mailbox message, LookAhead: 0x%X\n",lookAhead));
- /* Mailbox Interrupt, the HTC layer may issue async requests to empty the
- * mailbox...
- * When emptying the recv mailbox we use the async handler above called from the
- * completion routine of the callers read request. This can improve performance
- * by reducing context switching when we rapidly pull packets */
- status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, pASyncProcessing, &fetched);
- if (status) {
- break;
- }
-
- if (!fetched) {
- /* HTC could not pull any messages out due to lack of resources */
- /* force DSR handler to ack the interrupt */
- *pASyncProcessing = false;
- pDev->RecheckIRQStatusCnt = 0;
- }
- }
-
- /* now handle the rest of them */
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
- (" Valid interrupt source(s) for OTHER interrupts: 0x%x\n",
- host_int_status));
-
- if (HOST_INT_STATUS_CPU_GET(host_int_status)) {
- /* CPU Interrupt */
- status = DevServiceCPUInterrupt(pDev);
- if (status){
- break;
- }
- }
-
- if (HOST_INT_STATUS_ERROR_GET(host_int_status)) {
- /* Error Interrupt */
- status = DevServiceErrorInterrupt(pDev);
- if (status){
- break;
- }
- }
-
- if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) {
- /* Counter Interrupt */
- status = DevServiceCounterInterrupt(pDev);
- if (status){
- break;
- }
- }
-
- } while (false);
-
- /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake
- * the target, if upper layers determine that we are in a low-throughput mode, we can
- * rely on taking another interrupt rather than re-checking the status registers which can
- * re-wake the target.
- *
- * NOTE : for host interfaces that use the special GetPendingEventsFunc, this optimization cannot
- * be used due to possible side-effects. For example, SPI requires the host to drain all
- * messages from the mailbox before exiting the ISR routine. */
- if (!(*pASyncProcessing) && (pDev->RecheckIRQStatusCnt == 0) && (pDev->GetPendingEventsFunc == NULL)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, forcing done \n"));
- *pDone = true;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) status=%d \n",
- *pDone, *pASyncProcessing, status));
-
- return status;
-}
-
-
-/* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/
-int DevDsrHandler(void *context)
-{
- struct ar6k_device *pDev = (struct ar6k_device *)context;
- int status = 0;
- bool done = false;
- bool asyncProc = false;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
-
- /* reset the recv counter that tracks when we need to yield from the DSR */
- pDev->CurrentDSRRecvCount = 0;
- /* reset counter used to flag a re-scan of IRQ status registers on the target */
- pDev->RecheckIRQStatusCnt = 0;
-
- while (!done) {
- status = ProcessPendingIRQs(pDev, &done, &asyncProc);
- if (status) {
- break;
- }
-
- if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) {
- /* the HIF layer does not allow async IRQ processing, override the asyncProc flag */
- asyncProc = false;
- /* this will cause us to re-enter ProcessPendingIRQ() and re-read interrupt status registers.
- * this has a nice side effect of blocking us until all async read requests are completed.
- * This behavior is required on some HIF implementations that do not allow ASYNC
- * processing in interrupt handlers (like Windows CE) */
-
- if (pDev->DSRCanYield && DEV_CHECK_RECV_YIELD(pDev)) {
- /* ProcessPendingIRQs() pulled enough recv messages to satisfy the yield count, stop
- * checking for more messages and return */
- break;
- }
- }
-
- if (asyncProc) {
- /* the function performed some async I/O for performance, we
- need to exit the ISR immediately, the check below will prevent the interrupt from being
- Ack'd while we handle it asynchronously */
- break;
- }
-
- }
-
- if (!status && !asyncProc) {
- /* Ack the interrupt only if :
- * 1. we did not get any errors in processing interrupts
- * 2. there are no outstanding async processing requests */
- if (pDev->DSRCanYield) {
- /* if the DSR can yield do not ACK the interrupt, there could be more pending messages.
- * The HIF layer must ACK the interrupt on behalf of HTC */
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Yield in effect (cur RX count: %d) \n", pDev->CurrentDSRRecvCount));
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler \n"));
- HIFAckInterrupt(pDev->HIFDevice);
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n"));
- return status;
-}
-
-#ifdef ATH_DEBUG_MODULE
-void DumpAR6KDevState(struct ar6k_device *pDev)
-{
- int status;
- struct ar6k_irq_enable_registers regs;
- struct ar6k_irq_proc_registers procRegs;
-
- LOCK_AR6K(pDev);
- /* copy into our temp area */
- memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
- UNLOCK_AR6K(pDev);
-
- /* load the register table from the device */
- status = HIFReadWrite(pDev->HIFDevice,
- HOST_INT_STATUS_ADDRESS,
- (u8 *)&procRegs,
- AR6K_IRQ_PROC_REGS_SIZE,
- HIF_RD_SYNC_BYTE_INC,
- NULL);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("DumpAR6KDevState : Failed to read register table (%d) \n",status));
- return;
- }
-
- DevDumpRegisters(pDev,&procRegs,&regs);
-
- if (pDev->GMboxInfo.pStateDumpCallback != NULL) {
- pDev->GMboxInfo.pStateDumpCallback(pDev->GMboxInfo.pProtocolContext);
- }
-
- /* dump any bus state at the HIF layer */
- HIFConfigureDevice(pDev->HIFDevice,HIF_DEVICE_DEBUG_BUS_STATE,NULL,0);
-
-}
-#endif
-
-
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c
deleted file mode 100644
index 725540f9adde..000000000000
--- a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c
+++ /dev/null
@@ -1,755 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="ar6k_gmbox.c" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Generic MBOX API implementation
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_osapi.h"
-#include "../htc_debug.h"
-#include "hif.h"
-#include "htc_packet.h"
-#include "ar6k.h"
-#include "hw/mbox_host_reg.h"
-#include "gmboxif.h"
-
-/*
- * This file provides management functions and a toolbox for GMBOX protocol modules.
- * Only one protocol module can be installed at a time. The determination of which protocol
- * module is installed is determined at compile time.
- *
- */
-#ifdef ATH_AR6K_ENABLE_GMBOX
- /* GMBOX definitions */
-#define GMBOX_INT_STATUS_ENABLE_REG 0x488
-#define GMBOX_INT_STATUS_RX_DATA (1 << 0)
-#define GMBOX_INT_STATUS_TX_OVERFLOW (1 << 1)
-#define GMBOX_INT_STATUS_RX_OVERFLOW (1 << 2)
-
-#define GMBOX_LOOKAHEAD_MUX_REG 0x498
-#define GMBOX_LA_MUX_OVERRIDE_2_3 (1 << 0)
-
-#define AR6K_GMBOX_CREDIT_DEC_ADDRESS (COUNT_DEC_ADDRESS + 4 * AR6K_GMBOX_CREDIT_COUNTER)
-#define AR6K_GMBOX_CREDIT_SIZE_ADDRESS (COUNT_ADDRESS + AR6K_GMBOX_CREDIT_SIZE_COUNTER)
-
-
- /* external APIs for allocating and freeing internal I/O packets to handle ASYNC I/O */
-extern void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket);
-extern struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev);
-
-
-/* callback when our fetch to enable/disable completes */
-static void DevGMboxIRQActionAsyncHandler(void *Context, struct htc_packet *pPacket)
-{
- struct ar6k_device *pDev = (struct ar6k_device *)Context;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxIRQActionAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
-
- if (pPacket->Status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("IRQAction Operation (%d) failed! status:%d \n", pPacket->PktInfo.AsRx.HTCRxFlags,pPacket->Status));
- }
- /* free this IO packet */
- AR6KFreeIOPacket(pDev,pPacket);
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxIRQActionAsyncHandler \n"));
-}
-
-static int DevGMboxCounterEnableDisable(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, bool AsyncMode)
-{
- int status = 0;
- struct ar6k_irq_enable_registers regs;
- struct htc_packet *pIOPacket = NULL;
-
- LOCK_AR6K(pDev);
-
- if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) {
- pDev->GMboxInfo.CreditCountIRQEnabled = true;
- pDev->IrqEnableRegisters.counter_int_status_enable |=
- COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER);
- pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_COUNTER_SET(0x01);
- } else {
- pDev->GMboxInfo.CreditCountIRQEnabled = false;
- pDev->IrqEnableRegisters.counter_int_status_enable &=
- ~(COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER));
- }
- /* copy into our temp area */
- memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
-
- UNLOCK_AR6K(pDev);
-
- do {
-
- if (AsyncMode) {
-
- pIOPacket = AR6KAllocIOPacket(pDev);
-
- if (NULL == pIOPacket) {
- status = A_NO_MEMORY;
- A_ASSERT(false);
- break;
- }
-
- /* copy values to write to our async I/O buffer */
- memcpy(pIOPacket->pBuffer,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
-
- /* stick in our completion routine when the I/O operation completes */
- pIOPacket->Completion = DevGMboxIRQActionAsyncHandler;
- pIOPacket->pContext = pDev;
- pIOPacket->PktInfo.AsRx.HTCRxFlags = IrqAction;
- /* write it out asynchronously */
- HIFReadWrite(pDev->HIFDevice,
- INT_STATUS_ENABLE_ADDRESS,
- pIOPacket->pBuffer,
- AR6K_IRQ_ENABLE_REGS_SIZE,
- HIF_WR_ASYNC_BYTE_INC,
- pIOPacket);
-
- pIOPacket = NULL;
- break;
- }
-
- /* if we get here we are doing it synchronously */
- status = HIFReadWrite(pDev->HIFDevice,
- INT_STATUS_ENABLE_ADDRESS,
- &regs.int_status_enable,
- AR6K_IRQ_ENABLE_REGS_SIZE,
- HIF_WR_SYNC_BYTE_INC,
- NULL);
- } while (false);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status));
- } else {
- if (!AsyncMode) {
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
- (" IRQAction Operation (%d) success \n", IrqAction));
- }
- }
-
- if (pIOPacket != NULL) {
- AR6KFreeIOPacket(pDev,pIOPacket);
- }
-
- return status;
-}
-
-
-int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, bool AsyncMode)
-{
- int status = 0;
- struct htc_packet *pIOPacket = NULL;
- u8 GMboxIntControl[4];
-
- if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) {
- return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_ENABLE, AsyncMode);
- } else if(GMBOX_CREDIT_IRQ_DISABLE == IrqAction) {
- return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_DISABLE, AsyncMode);
- }
-
- if (GMBOX_DISABLE_ALL == IrqAction) {
- /* disable credit IRQ, those are on a different set of registers */
- DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_DISABLE, AsyncMode);
- }
-
- /* take the lock to protect interrupt enable shadows */
- LOCK_AR6K(pDev);
-
- switch (IrqAction) {
-
- case GMBOX_DISABLE_ALL:
- pDev->GMboxControlRegisters.int_status_enable = 0;
- break;
- case GMBOX_ERRORS_IRQ_ENABLE:
- pDev->GMboxControlRegisters.int_status_enable |= GMBOX_INT_STATUS_TX_OVERFLOW |
- GMBOX_INT_STATUS_RX_OVERFLOW;
- break;
- case GMBOX_RECV_IRQ_ENABLE:
- pDev->GMboxControlRegisters.int_status_enable |= GMBOX_INT_STATUS_RX_DATA;
- break;
- case GMBOX_RECV_IRQ_DISABLE:
- pDev->GMboxControlRegisters.int_status_enable &= ~GMBOX_INT_STATUS_RX_DATA;
- break;
- case GMBOX_ACTION_NONE:
- default:
- A_ASSERT(false);
- break;
- }
-
- GMboxIntControl[0] = pDev->GMboxControlRegisters.int_status_enable;
- GMboxIntControl[1] = GMboxIntControl[0];
- GMboxIntControl[2] = GMboxIntControl[0];
- GMboxIntControl[3] = GMboxIntControl[0];
-
- UNLOCK_AR6K(pDev);
-
- do {
-
- if (AsyncMode) {
-
- pIOPacket = AR6KAllocIOPacket(pDev);
-
- if (NULL == pIOPacket) {
- status = A_NO_MEMORY;
- A_ASSERT(false);
- break;
- }
-
- /* copy values to write to our async I/O buffer */
- memcpy(pIOPacket->pBuffer,GMboxIntControl,sizeof(GMboxIntControl));
-
- /* stick in our completion routine when the I/O operation completes */
- pIOPacket->Completion = DevGMboxIRQActionAsyncHandler;
- pIOPacket->pContext = pDev;
- pIOPacket->PktInfo.AsRx.HTCRxFlags = IrqAction;
- /* write it out asynchronously */
- HIFReadWrite(pDev->HIFDevice,
- GMBOX_INT_STATUS_ENABLE_REG,
- pIOPacket->pBuffer,
- sizeof(GMboxIntControl),
- HIF_WR_ASYNC_BYTE_FIX,
- pIOPacket);
- pIOPacket = NULL;
- break;
- }
-
- /* if we get here we are doing it synchronously */
-
- status = HIFReadWrite(pDev->HIFDevice,
- GMBOX_INT_STATUS_ENABLE_REG,
- GMboxIntControl,
- sizeof(GMboxIntControl),
- HIF_WR_SYNC_BYTE_FIX,
- NULL);
-
- } while (false);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status));
- } else {
- if (!AsyncMode) {
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
- (" IRQAction Operation (%d) success \n", IrqAction));
- }
- }
-
- if (pIOPacket != NULL) {
- AR6KFreeIOPacket(pDev,pIOPacket);
- }
-
- return status;
-}
-
-void DevCleanupGMbox(struct ar6k_device *pDev)
-{
- if (pDev->GMboxEnabled) {
- pDev->GMboxEnabled = false;
- GMboxProtocolUninstall(pDev);
- }
-}
-
-int DevSetupGMbox(struct ar6k_device *pDev)
-{
- int status = 0;
- u8 muxControl[4];
-
- do {
-
- if (0 == pDev->MailBoxInfo.GMboxAddress) {
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(" GMBOX Advertised: Address:0x%X , size:%d \n",
- pDev->MailBoxInfo.GMboxAddress, pDev->MailBoxInfo.GMboxSize));
-
- status = DevGMboxIRQAction(pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC);
-
- if (status) {
- break;
- }
-
- /* write to mailbox look ahead mux control register, we want the
- * GMBOX lookaheads to appear on lookaheads 2 and 3
- * the register is 1-byte wide so we need to hit it 4 times to align the operation
- * to 4-bytes */
- muxControl[0] = GMBOX_LA_MUX_OVERRIDE_2_3;
- muxControl[1] = GMBOX_LA_MUX_OVERRIDE_2_3;
- muxControl[2] = GMBOX_LA_MUX_OVERRIDE_2_3;
- muxControl[3] = GMBOX_LA_MUX_OVERRIDE_2_3;
-
- status = HIFReadWrite(pDev->HIFDevice,
- GMBOX_LOOKAHEAD_MUX_REG,
- muxControl,
- sizeof(muxControl),
- HIF_WR_SYNC_BYTE_FIX, /* hit this register 4 times */
- NULL);
-
- if (status) {
- break;
- }
-
- status = GMboxProtocolInstall(pDev);
-
- if (status) {
- break;
- }
-
- pDev->GMboxEnabled = true;
-
- } while (false);
-
- return status;
-}
-
-int DevCheckGMboxInterrupts(struct ar6k_device *pDev)
-{
- int status = 0;
- u8 counter_int_status;
- int credits;
- u8 host_int_status2;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("+DevCheckGMboxInterrupts \n"));
-
- /* the caller guarantees that this is a context that allows for blocking I/O */
-
- do {
-
- host_int_status2 = pDev->IrqProcRegisters.host_int_status2 &
- pDev->GMboxControlRegisters.int_status_enable;
-
- if (host_int_status2 & GMBOX_INT_STATUS_TX_OVERFLOW) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("GMBOX : TX Overflow \n"));
- status = A_ECOMM;
- }
-
- if (host_int_status2 & GMBOX_INT_STATUS_RX_OVERFLOW) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("GMBOX : RX Overflow \n"));
- status = A_ECOMM;
- }
-
- if (status) {
- if (pDev->GMboxInfo.pTargetFailureCallback != NULL) {
- pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, status);
- }
- break;
- }
-
- if (host_int_status2 & GMBOX_INT_STATUS_RX_DATA) {
- if (pDev->IrqProcRegisters.gmbox_rx_avail > 0) {
- A_ASSERT(pDev->GMboxInfo.pMessagePendingCallBack != NULL);
- status = pDev->GMboxInfo.pMessagePendingCallBack(
- pDev->GMboxInfo.pProtocolContext,
- (u8 *)&pDev->IrqProcRegisters.rx_gmbox_lookahead_alias[0],
- pDev->IrqProcRegisters.gmbox_rx_avail);
- }
- }
-
- if (status) {
- break;
- }
-
- counter_int_status = pDev->IrqProcRegisters.counter_int_status &
- pDev->IrqEnableRegisters.counter_int_status_enable;
-
- /* check if credit interrupt is pending */
- if (counter_int_status & (COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER))) {
-
- /* do synchronous read */
- status = DevGMboxReadCreditCounter(pDev, PROC_IO_SYNC, &credits);
-
- if (status) {
- break;
- }
-
- A_ASSERT(pDev->GMboxInfo.pCreditsPendingCallback != NULL);
- status = pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext,
- credits,
- pDev->GMboxInfo.CreditCountIRQEnabled);
- }
-
- } while (false);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("-DevCheckGMboxInterrupts (%d) \n",status));
-
- return status;
-}
-
-
-int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength)
-{
- u32 paddedLength;
- bool sync = (pPacket->Completion == NULL) ? true : false;
- int status;
- u32 address;
-
- /* adjust the length to be a multiple of block size if appropriate */
- paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, WriteLength);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
- ("DevGMboxWrite, Padded Length: %d Mbox:0x%X (mode:%s)\n",
- WriteLength,
- pDev->MailBoxInfo.GMboxAddress,
- sync ? "SYNC" : "ASYNC"));
-
- /* last byte of packet has to hit the EOM marker */
- address = pDev->MailBoxInfo.GMboxAddress + pDev->MailBoxInfo.GMboxSize - paddedLength;
-
- status = HIFReadWrite(pDev->HIFDevice,
- address,
- pPacket->pBuffer,
- paddedLength, /* the padded length */
- sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC,
- sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
-
- if (sync) {
- pPacket->Status = status;
- } else {
- if (status == A_PENDING) {
- status = 0;
- }
- }
-
- return status;
-}
-
-int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength)
-{
-
- u32 paddedLength;
- int status;
- bool sync = (pPacket->Completion == NULL) ? true : false;
-
- /* adjust the length to be a multiple of block size if appropriate */
- paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, ReadLength);
-
- if (paddedLength > pPacket->BufferLength) {
- A_ASSERT(false);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("DevGMboxRead, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
- paddedLength,ReadLength,pPacket->BufferLength));
- if (pPacket->Completion != NULL) {
- COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
- return 0;
- }
- return A_EINVAL;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("DevGMboxRead (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n",
- (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr,
- paddedLength,
- pDev->MailBoxInfo.GMboxAddress,
- sync ? "SYNC" : "ASYNC"));
-
- status = HIFReadWrite(pDev->HIFDevice,
- pDev->MailBoxInfo.GMboxAddress,
- pPacket->pBuffer,
- paddedLength,
- sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX,
- sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
-
- if (sync) {
- pPacket->Status = status;
- }
-
- return status;
-}
-
-
-static int ProcessCreditCounterReadBuffer(u8 *pBuffer, int Length)
-{
- int credits = 0;
-
- /* theory of how this works:
- * We read the credit decrement register multiple times on a byte-wide basis.
- * The number of times (32) aligns the I/O operation to be a multiple of 4 bytes and provides a
- * reasonable chance to acquire "all" pending credits in a single I/O operation.
- *
- * Once we obtain the filled buffer, we can walk through it looking for credit decrement transitions.
- * Each non-zero byte represents a single credit decrement (which is a credit given back to the host)
- * For example if the target provides 3 credits and added 4 more during the 32-byte read operation the following
- * pattern "could" appear:
- *
- * 0x3 0x2 0x1 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x1 0x0 0x1 0x0 0x1 0x0 ......rest zeros
- * <---------> <----------------------------->
- * \_ credits aleady there \_ target adding 4 more credits
- *
- * The total available credits would be 7, since there are 7 non-zero bytes in the buffer.
- *
- * */
-
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- DebugDumpBytes(pBuffer, Length, "GMBOX Credit read buffer");
- }
-
- while (Length) {
- if (*pBuffer != 0) {
- credits++;
- }
- Length--;
- pBuffer++;
- }
-
- return credits;
-}
-
-
-/* callback when our fetch to enable/disable completes */
-static void DevGMboxReadCreditsAsyncHandler(void *Context, struct htc_packet *pPacket)
-{
- struct ar6k_device *pDev = (struct ar6k_device *)Context;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxReadCreditsAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
-
- if (pPacket->Status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Read Credit Operation failed! status:%d \n", pPacket->Status));
- } else {
- int credits = 0;
- credits = ProcessCreditCounterReadBuffer(pPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE);
- pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext,
- credits,
- pDev->GMboxInfo.CreditCountIRQEnabled);
-
-
- }
- /* free this IO packet */
- AR6KFreeIOPacket(pDev,pPacket);
- AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxReadCreditsAsyncHandler \n"));
-}
-
-int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits)
-{
- int status = 0;
- struct htc_packet *pIOPacket = NULL;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+DevGMboxReadCreditCounter (%s) \n", AsyncMode ? "ASYNC" : "SYNC"));
-
- do {
-
- pIOPacket = AR6KAllocIOPacket(pDev);
-
- if (NULL == pIOPacket) {
- status = A_NO_MEMORY;
- A_ASSERT(false);
- break;
- }
-
- A_MEMZERO(pIOPacket->pBuffer,AR6K_REG_IO_BUFFER_SIZE);
-
- if (AsyncMode) {
- /* stick in our completion routine when the I/O operation completes */
- pIOPacket->Completion = DevGMboxReadCreditsAsyncHandler;
- pIOPacket->pContext = pDev;
- /* read registers asynchronously */
- HIFReadWrite(pDev->HIFDevice,
- AR6K_GMBOX_CREDIT_DEC_ADDRESS,
- pIOPacket->pBuffer,
- AR6K_REG_IO_BUFFER_SIZE, /* hit the register multiple times */
- HIF_RD_ASYNC_BYTE_FIX,
- pIOPacket);
- pIOPacket = NULL;
- break;
- }
-
- pIOPacket->Completion = NULL;
- /* if we get here we are doing it synchronously */
- status = HIFReadWrite(pDev->HIFDevice,
- AR6K_GMBOX_CREDIT_DEC_ADDRESS,
- pIOPacket->pBuffer,
- AR6K_REG_IO_BUFFER_SIZE,
- HIF_RD_SYNC_BYTE_FIX,
- NULL);
- } while (false);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- (" DevGMboxReadCreditCounter failed! status:%d \n", status));
- }
-
- if (pIOPacket != NULL) {
- if (!status) {
- /* sync mode processing */
- *pCredits = ProcessCreditCounterReadBuffer(pIOPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE);
- }
- AR6KFreeIOPacket(pDev,pIOPacket);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-DevGMboxReadCreditCounter (%s) (%d) \n",
- AsyncMode ? "ASYNC" : "SYNC", status));
-
- return status;
-}
-
-int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize)
-{
- int status;
- u8 buffer[4];
-
- status = HIFReadWrite(pDev->HIFDevice,
- AR6K_GMBOX_CREDIT_SIZE_ADDRESS,
- buffer,
- sizeof(buffer),
- HIF_RD_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
- NULL);
-
- if (!status) {
- if (buffer[0] == 0) {
- *pCreditSize = 256;
- } else {
- *pCreditSize = buffer[0];
- }
-
- }
-
- return status;
-}
-
-void DevNotifyGMboxTargetFailure(struct ar6k_device *pDev)
-{
- /* Target ASSERTED!!! */
- if (pDev->GMboxInfo.pTargetFailureCallback != NULL) {
- pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, A_HARDWARE);
- }
-}
-
-int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes)
-{
-
- int status = 0;
- struct ar6k_irq_proc_registers procRegs;
- int maxCopy;
-
- do {
- /* on entry the caller provides the length of the lookahead buffer */
- if (*pLookAheadBytes > sizeof(procRegs.rx_gmbox_lookahead_alias)) {
- A_ASSERT(false);
- status = A_EINVAL;
- break;
- }
-
- maxCopy = *pLookAheadBytes;
- *pLookAheadBytes = 0;
- /* load the register table from the device */
- status = HIFReadWrite(pDev->HIFDevice,
- HOST_INT_STATUS_ADDRESS,
- (u8 *)&procRegs,
- AR6K_IRQ_PROC_REGS_SIZE,
- HIF_RD_SYNC_BYTE_INC,
- NULL);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("DevGMboxRecvLookAheadPeek : Failed to read register table (%d) \n",status));
- break;
- }
-
- if (procRegs.gmbox_rx_avail > 0) {
- int bytes = procRegs.gmbox_rx_avail > maxCopy ? maxCopy : procRegs.gmbox_rx_avail;
- memcpy(pLookAheadBuffer,&procRegs.rx_gmbox_lookahead_alias[0],bytes);
- *pLookAheadBytes = bytes;
- }
-
- } while (false);
-
- return status;
-}
-
-int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int Signal, int AckTimeoutMS)
-{
- int status = 0;
- int i;
- u8 buffer[4];
-
- A_MEMZERO(buffer, sizeof(buffer));
-
- do {
-
- if (Signal >= MBOX_SIG_HCI_BRIDGE_MAX) {
- status = A_EINVAL;
- break;
- }
-
- /* set the last buffer to do the actual signal trigger */
- buffer[3] = (1 << Signal);
-
- status = HIFReadWrite(pDev->HIFDevice,
- INT_WLAN_ADDRESS,
- buffer,
- sizeof(buffer),
- HIF_WR_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
- NULL);
-
- if (status) {
- break;
- }
-
- } while (false);
-
-
- if (!status) {
- /* now read back the register to see if the bit cleared */
- while (AckTimeoutMS) {
- status = HIFReadWrite(pDev->HIFDevice,
- INT_WLAN_ADDRESS,
- buffer,
- sizeof(buffer),
- HIF_RD_SYNC_BYTE_FIX,
- NULL);
-
- if (status) {
- break;
- }
-
- for (i = 0; i < sizeof(buffer); i++) {
- if (buffer[i] & (1 << Signal)) {
- /* bit is still set */
- break;
- }
- }
-
- if (i >= sizeof(buffer)) {
- /* done */
- break;
- }
-
- AckTimeoutMS--;
- A_MDELAY(1);
- }
-
- if (0 == AckTimeoutMS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("DevGMboxSetTargetInterrupt : Ack Timed-out (sig:%d) \n",Signal));
- status = A_ERROR;
- }
- }
-
- return status;
-
-}
-
-#endif //ATH_AR6K_ENABLE_GMBOX
-
-
-
-
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c
deleted file mode 100644
index 56a0d7143804..000000000000
--- a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c
+++ /dev/null
@@ -1,1284 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="ar6k_prot_hciUart.c" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Protocol module for use in bridging HCI-UART packets over the GMBOX interface
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_osapi.h"
-#include "../htc_debug.h"
-#include "hif.h"
-#include "htc_packet.h"
-#include "ar6k.h"
-#include "hci_transport_api.h"
-#include "gmboxif.h"
-#include "ar6000_diag.h"
-#include "hw/apb_map.h"
-#include "hw/mbox_reg.h"
-
-#ifdef ATH_AR6K_ENABLE_GMBOX
-#define HCI_UART_COMMAND_PKT 0x01
-#define HCI_UART_ACL_PKT 0x02
-#define HCI_UART_SCO_PKT 0x03
-#define HCI_UART_EVENT_PKT 0x04
-
-#define HCI_RECV_WAIT_BUFFERS (1 << 0)
-
-#define HCI_SEND_WAIT_CREDITS (1 << 0)
-
-#define HCI_UART_BRIDGE_CREDIT_SIZE 128
-
-#define CREDIT_POLL_COUNT 256
-
-#define HCI_DELAY_PER_INTERVAL_MS 10
-#define BTON_TIMEOUT_MS 500
-#define BTOFF_TIMEOUT_MS 500
-#define BAUD_TIMEOUT_MS 1
-#define BTPWRSAV_TIMEOUT_MS 1
-
-struct gmbox_proto_hci_uart {
- struct hci_transport_config_info HCIConfig;
- bool HCIAttached;
- bool HCIStopped;
- u32 RecvStateFlags;
- u32 SendStateFlags;
- HCI_TRANSPORT_PACKET_TYPE WaitBufferType;
- struct htc_packet_queue SendQueue; /* write queue holding HCI Command and ACL packets */
- struct htc_packet_queue HCIACLRecvBuffers; /* recv queue holding buffers for incomming ACL packets */
- struct htc_packet_queue HCIEventBuffers; /* recv queue holding buffers for incomming event packets */
- struct ar6k_device *pDev;
- A_MUTEX_T HCIRxLock;
- A_MUTEX_T HCITxLock;
- int CreditsMax;
- int CreditsConsumed;
- int CreditsAvailable;
- int CreditSize;
- int CreditsCurrentSeek;
- int SendProcessCount;
-};
-
-#define LOCK_HCI_RX(t) A_MUTEX_LOCK(&(t)->HCIRxLock);
-#define UNLOCK_HCI_RX(t) A_MUTEX_UNLOCK(&(t)->HCIRxLock);
-#define LOCK_HCI_TX(t) A_MUTEX_LOCK(&(t)->HCITxLock);
-#define UNLOCK_HCI_TX(t) A_MUTEX_UNLOCK(&(t)->HCITxLock);
-
-#define DO_HCI_RECV_INDICATION(p, pt) \
-do { \
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, \
- ("HCI: Indicate Recv on packet:0x%lX status:%d len:%d type:%d \n", \
- (unsigned long)(pt), \
- (pt)->Status, \
- !(pt)->Status ? (pt)->ActualLength : 0, \
- HCI_GET_PACKET_TYPE(pt))); \
- (p)->HCIConfig.pHCIPktRecv((p)->HCIConfig.pContext, (pt)); \
-} while (0)
-
-#define DO_HCI_SEND_INDICATION(p,pt) \
-{ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Indicate Send on packet:0x%lX status:%d type:%d \n", \
- (unsigned long)(pt),(pt)->Status,HCI_GET_PACKET_TYPE(pt))); \
- (p)->HCIConfig.pHCISendComplete((p)->HCIConfig.pContext, (pt)); \
-}
-
-static int HCITrySend(struct gmbox_proto_hci_uart *pProt, struct htc_packet *pPacket, bool Synchronous);
-
-static void HCIUartCleanup(struct gmbox_proto_hci_uart *pProtocol)
-{
- A_ASSERT(pProtocol != NULL);
-
- A_MUTEX_DELETE(&pProtocol->HCIRxLock);
- A_MUTEX_DELETE(&pProtocol->HCITxLock);
-
- kfree(pProtocol);
-}
-
-static int InitTxCreditState(struct gmbox_proto_hci_uart *pProt)
-{
- int status;
- int credits;
- int creditPollCount = CREDIT_POLL_COUNT;
- bool gotCredits = false;
-
- pProt->CreditsConsumed = 0;
-
- do {
-
- if (pProt->CreditsMax != 0) {
- /* we can only call this only once per target reset */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI: InitTxCreditState - already called! \n"));
- A_ASSERT(false);
- status = A_EINVAL;
- break;
- }
-
- /* read the credit counter. At startup the target will set the credit counter
- * to the max available, we read this in a loop because it may take
- * multiple credit counter reads to get all credits */
-
- while (creditPollCount) {
-
- credits = 0;
-
- status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits);
-
- if (status) {
- break;
- }
-
- if (!gotCredits && (0 == credits)) {
- creditPollCount--;
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: credit is 0, retrying (%d) \n",creditPollCount));
- A_MDELAY(HCI_DELAY_PER_INTERVAL_MS);
- continue;
- } else {
- gotCredits = true;
- }
-
- if (0 == credits) {
- break;
- }
-
- pProt->CreditsMax += credits;
- }
-
- if (status) {
- break;
- }
-
- if (0 == creditPollCount) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("** HCI : Failed to get credits! GMBOX Target was not available \n"));
- status = A_ERROR;
- break;
- }
-
- /* now get the size */
- status = DevGMboxReadCreditSize(pProt->pDev, &pProt->CreditSize);
-
- if (status) {
- break;
- }
-
- } while (false);
-
- if (!status) {
- pProt->CreditsAvailable = pProt->CreditsMax;
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI : InitTxCreditState - credits avail: %d, size: %d \n",
- pProt->CreditsAvailable, pProt->CreditSize));
- }
-
- return status;
-}
-
-static int CreditsAvailableCallback(void *pContext, int Credits, bool CreditIRQEnabled)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext;
- bool enableCreditIrq = false;
- bool disableCreditIrq = false;
- bool doPendingSends = false;
- int status = 0;
-
- /** this callback is called under 2 conditions:
- * 1. The credit IRQ interrupt was enabled and signaled.
- * 2. A credit counter read completed.
- *
- * The function must not assume that the calling context can block !
- */
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback (Credits:%d, IRQ:%s) \n",
- Credits, CreditIRQEnabled ? "ON" : "OFF"));
-
- LOCK_HCI_TX(pProt);
-
- do {
-
- if (0 == Credits) {
- if (!CreditIRQEnabled) {
- /* enable credit IRQ */
- enableCreditIrq = true;
- }
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: current credit state, consumed:%d available:%d max:%d seek:%d\n",
- pProt->CreditsConsumed,
- pProt->CreditsAvailable,
- pProt->CreditsMax,
- pProt->CreditsCurrentSeek));
-
- pProt->CreditsAvailable += Credits;
- A_ASSERT(pProt->CreditsAvailable <= pProt->CreditsMax);
- pProt->CreditsConsumed -= Credits;
- A_ASSERT(pProt->CreditsConsumed >= 0);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state, consumed:%d available:%d max:%d seek:%d\n",
- pProt->CreditsConsumed,
- pProt->CreditsAvailable,
- pProt->CreditsMax,
- pProt->CreditsCurrentSeek));
-
- if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) {
- /* we have enough credits to fulfill at least 1 packet waiting in the queue */
- pProt->CreditsCurrentSeek = 0;
- pProt->SendStateFlags &= ~HCI_SEND_WAIT_CREDITS;
- doPendingSends = true;
- if (CreditIRQEnabled) {
- /* credit IRQ was enabled, we shouldn't need it anymore */
- disableCreditIrq = true;
- }
- } else {
- /* not enough credits yet, enable credit IRQ if we haven't already */
- if (!CreditIRQEnabled) {
- enableCreditIrq = true;
- }
- }
-
- } while (false);
-
- UNLOCK_HCI_TX(pProt);
-
- if (enableCreditIrq) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Enabling credit count IRQ...\n"));
- /* must use async only */
- status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_ENABLE, PROC_IO_ASYNC);
- } else if (disableCreditIrq) {
- /* must use async only */
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Disabling credit count IRQ...\n"));
- status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_DISABLE, PROC_IO_ASYNC);
- }
-
- if (doPendingSends) {
- HCITrySend(pProt, NULL, false);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback \n"));
- return status;
-}
-
-static INLINE void NotifyTransportFailure(struct gmbox_proto_hci_uart *pProt, int status)
-{
- if (pProt->HCIConfig.TransportFailure != NULL) {
- pProt->HCIConfig.TransportFailure(pProt->HCIConfig.pContext, status);
- }
-}
-
-static void FailureCallback(void *pContext, int Status)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext;
-
- /* target assertion occurred */
- NotifyTransportFailure(pProt, Status);
-}
-
-static void StateDumpCallback(void *pContext)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("============ HCIUart State ======================\n"));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("RecvStateFlags : 0x%X \n",pProt->RecvStateFlags));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendStateFlags : 0x%X \n",pProt->SendStateFlags));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("WaitBufferType : %d \n",pProt->WaitBufferType));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendQueue Depth : %d \n",HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue)));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsMax : %d \n",pProt->CreditsMax));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsConsumed : %d \n",pProt->CreditsConsumed));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsAvailable : %d \n",pProt->CreditsAvailable));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("==================================================\n"));
-}
-
-static int HCIUartMessagePending(void *pContext, u8 LookAheadBytes[], int ValidBytes)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext;
- int status = 0;
- int totalRecvLength = 0;
- HCI_TRANSPORT_PACKET_TYPE pktType = HCI_PACKET_INVALID;
- bool recvRefillCalled = false;
- bool blockRecv = false;
- struct htc_packet *pPacket = NULL;
-
- /** caller guarantees that this is a fully block-able context (synch I/O is allowed) */
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCIUartMessagePending Lookahead Bytes:%d \n",ValidBytes));
-
- LOCK_HCI_RX(pProt);
-
- do {
-
- if (ValidBytes < 3) {
- /* not enough for ACL or event header */
- break;
- }
-
- if ((LookAheadBytes[0] == HCI_UART_ACL_PKT) && (ValidBytes < 5)) {
- /* not enough for ACL data header */
- break;
- }
-
- switch (LookAheadBytes[0]) {
- case HCI_UART_EVENT_PKT:
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n",
- LookAheadBytes[1], LookAheadBytes[2]));
- totalRecvLength = LookAheadBytes[2];
- totalRecvLength += 3; /* add type + event code + length field */
- pktType = HCI_EVENT_TYPE;
- break;
- case HCI_UART_ACL_PKT:
- totalRecvLength = (LookAheadBytes[4] << 8) | LookAheadBytes[3];
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI ACL: conn:0x%X length: %d \n",
- ((LookAheadBytes[2] & 0xF0) << 8) | LookAheadBytes[1], totalRecvLength));
- totalRecvLength += 5; /* add type + connection handle + length field */
- pktType = HCI_ACL_TYPE;
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n",LookAheadBytes[0]));
- status = A_EPROTO;
- break;
- }
-
- if (status) {
- break;
- }
-
- if (pProt->HCIConfig.pHCIPktRecvAlloc != NULL) {
- UNLOCK_HCI_RX(pProt);
- /* user is using a per-packet allocation callback */
- pPacket = pProt->HCIConfig.pHCIPktRecvAlloc(pProt->HCIConfig.pContext,
- pktType,
- totalRecvLength);
- LOCK_HCI_RX(pProt);
-
- } else {
- struct htc_packet_queue *pQueue;
- /* user is using a refill handler that can refill multiple HTC buffers */
-
- /* select buffer queue */
- if (pktType == HCI_ACL_TYPE) {
- pQueue = &pProt->HCIACLRecvBuffers;
- } else {
- pQueue = &pProt->HCIEventBuffers;
- }
-
- if (HTC_QUEUE_EMPTY(pQueue)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("** HCI pkt type: %d has no buffers available calling allocation handler \n",
- pktType));
- /* check for refill handler */
- if (pProt->HCIConfig.pHCIPktRecvRefill != NULL) {
- recvRefillCalled = true;
- UNLOCK_HCI_RX(pProt);
- /* call the re-fill handler */
- pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext,
- pktType,
- 0);
- LOCK_HCI_RX(pProt);
- /* check if we have more buffers */
- pPacket = HTC_PACKET_DEQUEUE(pQueue);
- /* fall through */
- }
- } else {
- pPacket = HTC_PACKET_DEQUEUE(pQueue);
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("HCI pkt type: %d now has %d recv buffers left \n",
- pktType, HTC_PACKET_QUEUE_DEPTH(pQueue)));
- }
- }
-
- if (NULL == pPacket) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("** HCI pkt type: %d has no buffers available stopping recv...\n", pktType));
- /* this is not an error, we simply need to mark that we are waiting for buffers.*/
- pProt->RecvStateFlags |= HCI_RECV_WAIT_BUFFERS;
- pProt->WaitBufferType = pktType;
- blockRecv = true;
- break;
- }
-
- if (totalRecvLength > (int)pPacket->BufferLength) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI-UART pkt: %d requires %d bytes (%d buffer bytes avail) ! \n",
- LookAheadBytes[0], totalRecvLength, pPacket->BufferLength));
- status = A_EINVAL;
- break;
- }
-
- } while (false);
-
- UNLOCK_HCI_RX(pProt);
-
- /* locks are released, we can go fetch the packet */
-
- do {
-
- if (status || (NULL == pPacket)) {
- break;
- }
-
- /* do this synchronously, we don't need to be fast here */
- pPacket->Completion = NULL;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI : getting recv packet len:%d hci-uart-type: %s \n",
- totalRecvLength, (LookAheadBytes[0] == HCI_UART_EVENT_PKT) ? "EVENT" : "ACL"));
-
- status = DevGMboxRead(pProt->pDev, pPacket, totalRecvLength);
-
- if (status) {
- break;
- }
-
- if (pPacket->pBuffer[0] != LookAheadBytes[0]) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not contain expected packet type: %d ! \n",
- pPacket->pBuffer[0]));
- status = A_EPROTO;
- break;
- }
-
- if (pPacket->pBuffer[0] == HCI_UART_EVENT_PKT) {
- /* validate event header fields */
- if ((pPacket->pBuffer[1] != LookAheadBytes[1]) ||
- (pPacket->pBuffer[2] != LookAheadBytes[2])) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match lookahead! \n"));
- DebugDumpBytes(LookAheadBytes, 3, "Expected HCI-UART Header");
- DebugDumpBytes(pPacket->pBuffer, 3, "** Bad HCI-UART Header");
- status = A_EPROTO;
- break;
- }
- } else if (pPacket->pBuffer[0] == HCI_UART_ACL_PKT) {
- /* validate acl header fields */
- if ((pPacket->pBuffer[1] != LookAheadBytes[1]) ||
- (pPacket->pBuffer[2] != LookAheadBytes[2]) ||
- (pPacket->pBuffer[3] != LookAheadBytes[3]) ||
- (pPacket->pBuffer[4] != LookAheadBytes[4])) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match lookahead! \n"));
- DebugDumpBytes(LookAheadBytes, 5, "Expected HCI-UART Header");
- DebugDumpBytes(pPacket->pBuffer, 5, "** Bad HCI-UART Header");
- status = A_EPROTO;
- break;
- }
- }
-
- /* adjust buffer to move past packet ID */
- pPacket->pBuffer++;
- pPacket->ActualLength = totalRecvLength - 1;
- pPacket->Status = 0;
- /* indicate packet */
- DO_HCI_RECV_INDICATION(pProt,pPacket);
- pPacket = NULL;
-
- /* check if we need to refill recv buffers */
- if ((pProt->HCIConfig.pHCIPktRecvRefill != NULL) && !recvRefillCalled) {
- struct htc_packet_queue *pQueue;
- int watermark;
-
- if (pktType == HCI_ACL_TYPE) {
- watermark = pProt->HCIConfig.ACLRecvBufferWaterMark;
- pQueue = &pProt->HCIACLRecvBuffers;
- } else {
- watermark = pProt->HCIConfig.EventRecvBufferWaterMark;
- pQueue = &pProt->HCIEventBuffers;
- }
-
- if (HTC_PACKET_QUEUE_DEPTH(pQueue) < watermark) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("** HCI pkt type: %d watermark hit (%d) current:%d \n",
- pktType, watermark, HTC_PACKET_QUEUE_DEPTH(pQueue)));
- /* call the re-fill handler */
- pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext,
- pktType,
- HTC_PACKET_QUEUE_DEPTH(pQueue));
- }
- }
-
- } while (false);
-
- /* check if we need to disable the receiver */
- if (status || blockRecv) {
- DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_DISABLE, PROC_IO_SYNC);
- }
-
- /* see if we need to recycle the recv buffer */
- if (status && (pPacket != NULL)) {
- struct htc_packet_queue queue;
-
- if (A_EPROTO == status) {
- DebugDumpBytes(pPacket->pBuffer, totalRecvLength, "Bad HCI-UART Recv packet");
- }
- /* recycle packet */
- HTC_PACKET_RESET_RX(pPacket);
- INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
- HCI_TransportAddReceivePkts(pProt,&queue);
- NotifyTransportFailure(pProt,status);
- }
-
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCIUartMessagePending \n"));
-
- return status;
-}
-
-static void HCISendPacketCompletion(void *Context, struct htc_packet *pPacket)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)Context;
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion (pPacket:0x%lX) \n",(unsigned long)pPacket));
-
- if (pPacket->Status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Send Packet (0x%lX) failed: %d , len:%d \n",
- (unsigned long)pPacket, pPacket->Status, pPacket->ActualLength));
- }
-
- DO_HCI_SEND_INDICATION(pProt,pPacket);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion \n"));
-}
-
-static int SeekCreditsSynch(struct gmbox_proto_hci_uart *pProt)
-{
- int status = 0;
- int credits;
- int retry = 100;
-
- while (true) {
- credits = 0;
- status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits);
- if (status) {
- break;
- }
- LOCK_HCI_TX(pProt);
- pProt->CreditsAvailable += credits;
- pProt->CreditsConsumed -= credits;
- if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) {
- pProt->CreditsCurrentSeek = 0;
- UNLOCK_HCI_TX(pProt);
- break;
- }
- UNLOCK_HCI_TX(pProt);
- retry--;
- if (0 == retry) {
- status = A_EBUSY;
- break;
- }
- A_MDELAY(20);
- }
-
- return status;
-}
-
-static int HCITrySend(struct gmbox_proto_hci_uart *pProt, struct htc_packet *pPacket, bool Synchronous)
-{
- int status = 0;
- int transferLength;
- int creditsRequired, remainder;
- u8 hciUartType;
- bool synchSendComplete = false;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCITrySend (pPacket:0x%lX) %s \n",(unsigned long)pPacket,
- Synchronous ? "SYNC" :"ASYNC"));
-
- LOCK_HCI_TX(pProt);
-
- /* increment write processing count on entry */
- pProt->SendProcessCount++;
-
- do {
-
- if (pProt->HCIStopped) {
- status = A_ECANCELED;
- break;
- }
-
- if (pPacket != NULL) {
- /* packet was supplied */
- if (Synchronous) {
- /* in synchronous mode, the send queue can only hold 1 packet */
- if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
- status = A_EBUSY;
- A_ASSERT(false);
- break;
- }
-
- if (pProt->SendProcessCount > 1) {
- /* another thread or task is draining the TX queues */
- status = A_EBUSY;
- A_ASSERT(false);
- break;
- }
-
- HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket);
-
- } else {
- /* see if adding this packet hits the max depth (asynchronous mode only) */
- if ((pProt->HCIConfig.MaxSendQueueDepth > 0) &&
- ((HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue) + 1) >= pProt->HCIConfig.MaxSendQueueDepth)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("HCI Send queue is full, Depth:%d, Max:%d \n",
- HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue),
- pProt->HCIConfig.MaxSendQueueDepth));
- /* queue will be full, invoke any callbacks to determine what action to take */
- if (pProt->HCIConfig.pHCISendFull != NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
- ("HCI : Calling driver's send full callback.... \n"));
- if (pProt->HCIConfig.pHCISendFull(pProt->HCIConfig.pContext,
- pPacket) == HCI_SEND_FULL_DROP) {
- /* drop it */
- status = A_NO_RESOURCE;
- break;
- }
- }
- }
-
- HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket);
- }
-
- }
-
- if (pProt->SendStateFlags & HCI_SEND_WAIT_CREDITS) {
- break;
- }
-
- if (pProt->SendProcessCount > 1) {
- /* another thread or task is draining the TX queues */
- break;
- }
-
- /***** beyond this point only 1 thread may enter ******/
-
- /* now drain the send queue for transmission as long as we have enough
- * credits */
- while (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
-
- pPacket = HTC_PACKET_DEQUEUE(&pProt->SendQueue);
-
- switch (HCI_GET_PACKET_TYPE(pPacket)) {
- case HCI_COMMAND_TYPE:
- hciUartType = HCI_UART_COMMAND_PKT;
- break;
- case HCI_ACL_TYPE:
- hciUartType = HCI_UART_ACL_PKT;
- break;
- default:
- status = A_EINVAL;
- A_ASSERT(false);
- break;
- }
-
- if (status) {
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Got head packet:0x%lX , Type:%d Length: %d Remaining Queue Depth: %d\n",
- (unsigned long)pPacket, HCI_GET_PACKET_TYPE(pPacket), pPacket->ActualLength,
- HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue)));
-
- transferLength = 1; /* UART type header is 1 byte */
- transferLength += pPacket->ActualLength;
- transferLength = DEV_CALC_SEND_PADDED_LEN(pProt->pDev, transferLength);
-
- /* figure out how many credits this message requires */
- creditsRequired = transferLength / pProt->CreditSize;
- remainder = transferLength % pProt->CreditSize;
-
- if (remainder) {
- creditsRequired++;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Creds Required:%d Got:%d\n",
- creditsRequired, pProt->CreditsAvailable));
-
- if (creditsRequired > pProt->CreditsAvailable) {
- if (Synchronous) {
- /* in synchronous mode we need to seek credits in synchronously */
- pProt->CreditsCurrentSeek = creditsRequired;
- UNLOCK_HCI_TX(pProt);
- status = SeekCreditsSynch(pProt);
- LOCK_HCI_TX(pProt);
- if (status) {
- break;
- }
- /* fall through and continue processing this send op */
- } else {
- /* not enough credits, queue back to the head */
- HTC_PACKET_ENQUEUE_TO_HEAD(&pProt->SendQueue,pPacket);
- /* waiting for credits */
- pProt->SendStateFlags |= HCI_SEND_WAIT_CREDITS;
- /* provide a hint to reduce attempts to re-send if credits are dribbling back
- * this hint is the short fall of credits */
- pProt->CreditsCurrentSeek = creditsRequired;
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: packet:0x%lX placed back in queue. head packet needs: %d credits \n",
- (unsigned long)pPacket, pProt->CreditsCurrentSeek));
- pPacket = NULL;
- UNLOCK_HCI_TX(pProt);
-
- /* schedule a credit counter read, our CreditsAvailableCallback callback will be called
- * with the result */
- DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_ASYNC, NULL);
-
- LOCK_HCI_TX(pProt);
- break;
- }
- }
-
- /* caller guarantees some head room */
- pPacket->pBuffer--;
- pPacket->pBuffer[0] = hciUartType;
-
- pProt->CreditsAvailable -= creditsRequired;
- pProt->CreditsConsumed += creditsRequired;
- A_ASSERT(pProt->CreditsConsumed <= pProt->CreditsMax);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state: consumed:%d available:%d max:%d\n",
- pProt->CreditsConsumed, pProt->CreditsAvailable, pProt->CreditsMax));
-
- UNLOCK_HCI_TX(pProt);
-
- /* write it out */
- if (Synchronous) {
- pPacket->Completion = NULL;
- pPacket->pContext = NULL;
- } else {
- pPacket->Completion = HCISendPacketCompletion;
- pPacket->pContext = pProt;
- }
-
- status = DevGMboxWrite(pProt->pDev,pPacket,transferLength);
- if (Synchronous) {
- synchSendComplete = true;
- } else {
- pPacket = NULL;
- }
-
- LOCK_HCI_TX(pProt);
-
- }
-
- } while (false);
-
- pProt->SendProcessCount--;
- A_ASSERT(pProt->SendProcessCount >= 0);
- UNLOCK_HCI_TX(pProt);
-
- if (Synchronous) {
- A_ASSERT(pPacket != NULL);
- if (!status && (!synchSendComplete)) {
- status = A_EBUSY;
- A_ASSERT(false);
- LOCK_HCI_TX(pProt);
- if (pPacket->ListLink.pNext != NULL) {
- /* remove from the queue */
- HTC_PACKET_REMOVE(&pProt->SendQueue,pPacket);
- }
- UNLOCK_HCI_TX(pProt);
- }
- } else {
- if (status && (pPacket != NULL)) {
- pPacket->Status = status;
- DO_HCI_SEND_INDICATION(pProt,pPacket);
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HCITrySend: \n"));
- return status;
-}
-
-static void FlushSendQueue(struct gmbox_proto_hci_uart *pProt)
-{
- struct htc_packet *pPacket;
- struct htc_packet_queue discardQueue;
-
- INIT_HTC_PACKET_QUEUE(&discardQueue);
-
- LOCK_HCI_TX(pProt);
-
- if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->SendQueue);
- }
-
- UNLOCK_HCI_TX(pProt);
-
- /* discard packets */
- while (!HTC_QUEUE_EMPTY(&discardQueue)) {
- pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
- pPacket->Status = A_ECANCELED;
- DO_HCI_SEND_INDICATION(pProt,pPacket);
- }
-
-}
-
-static void FlushRecvBuffers(struct gmbox_proto_hci_uart *pProt)
-{
- struct htc_packet_queue discardQueue;
- struct htc_packet *pPacket;
-
- INIT_HTC_PACKET_QUEUE(&discardQueue);
-
- LOCK_HCI_RX(pProt);
- /*transfer list items from ACL and event buffer queues to the discard queue */
- if (!HTC_QUEUE_EMPTY(&pProt->HCIACLRecvBuffers)) {
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIACLRecvBuffers);
- }
- if (!HTC_QUEUE_EMPTY(&pProt->HCIEventBuffers)) {
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIEventBuffers);
- }
- UNLOCK_HCI_RX(pProt);
-
- /* now empty the discard queue */
- while (!HTC_QUEUE_EMPTY(&discardQueue)) {
- pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
- pPacket->Status = A_ECANCELED;
- DO_HCI_RECV_INDICATION(pProt,pPacket);
- }
-
-}
-
-/*** protocol module install entry point ***/
-
-int GMboxProtocolInstall(struct ar6k_device *pDev)
-{
- int status = 0;
- struct gmbox_proto_hci_uart *pProtocol = NULL;
-
- do {
-
- pProtocol = A_MALLOC(sizeof(struct gmbox_proto_hci_uart));
-
- if (NULL == pProtocol) {
- status = A_NO_MEMORY;
- break;
- }
-
- A_MEMZERO(pProtocol, sizeof(*pProtocol));
- pProtocol->pDev = pDev;
- INIT_HTC_PACKET_QUEUE(&pProtocol->SendQueue);
- INIT_HTC_PACKET_QUEUE(&pProtocol->HCIACLRecvBuffers);
- INIT_HTC_PACKET_QUEUE(&pProtocol->HCIEventBuffers);
- A_MUTEX_INIT(&pProtocol->HCIRxLock);
- A_MUTEX_INIT(&pProtocol->HCITxLock);
-
- } while (false);
-
- if (!status) {
- LOCK_AR6K(pDev);
- DEV_GMBOX_SET_PROTOCOL(pDev,
- HCIUartMessagePending,
- CreditsAvailableCallback,
- FailureCallback,
- StateDumpCallback,
- pProtocol);
- UNLOCK_AR6K(pDev);
- } else {
- if (pProtocol != NULL) {
- HCIUartCleanup(pProtocol);
- }
- }
-
- return status;
-}
-
-/*** protocol module uninstall entry point ***/
-void GMboxProtocolUninstall(struct ar6k_device *pDev)
-{
- struct gmbox_proto_hci_uart *pProtocol = (struct gmbox_proto_hci_uart *)DEV_GMBOX_GET_PROTOCOL(pDev);
-
- if (pProtocol != NULL) {
-
- /* notify anyone attached */
- if (pProtocol->HCIAttached) {
- A_ASSERT(pProtocol->HCIConfig.TransportRemoved != NULL);
- pProtocol->HCIConfig.TransportRemoved(pProtocol->HCIConfig.pContext);
- pProtocol->HCIAttached = false;
- }
-
- HCIUartCleanup(pProtocol);
- DEV_GMBOX_SET_PROTOCOL(pDev,NULL,NULL,NULL,NULL,NULL);
- }
-
-}
-
-static int NotifyTransportReady(struct gmbox_proto_hci_uart *pProt)
-{
- struct hci_transport_properties props;
- int status = 0;
-
- do {
-
- A_MEMZERO(&props,sizeof(props));
-
- /* HCI UART only needs one extra byte at the head to indicate the packet TYPE */
- props.HeadRoom = 1;
- props.TailRoom = 0;
- props.IOBlockPad = pProt->pDev->BlockSize;
- if (pProt->HCIAttached) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI: notifying attached client to transport... \n"));
- A_ASSERT(pProt->HCIConfig.TransportReady != NULL);
- status = pProt->HCIConfig.TransportReady(pProt,
- &props,
- pProt->HCIConfig.pContext);
- }
-
- } while (false);
-
- return status;
-}
-
-/*********** HCI UART protocol implementation ************************************************/
-
-HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, struct hci_transport_config_info *pInfo)
-{
- struct gmbox_proto_hci_uart *pProtocol = NULL;
- struct ar6k_device *pDev;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportAttach \n"));
-
- pDev = HTCGetAR6KDevice(HTCHandle);
-
- LOCK_AR6K(pDev);
-
- do {
-
- pProtocol = (struct gmbox_proto_hci_uart *)DEV_GMBOX_GET_PROTOCOL(pDev);
-
- if (NULL == pProtocol) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not installed! \n"));
- break;
- }
-
- if (pProtocol->HCIAttached) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol already attached! \n"));
- break;
- }
-
- memcpy(&pProtocol->HCIConfig, pInfo, sizeof(struct hci_transport_config_info));
-
- A_ASSERT(pProtocol->HCIConfig.pHCIPktRecv != NULL);
- A_ASSERT(pProtocol->HCIConfig.pHCISendComplete != NULL);
-
- pProtocol->HCIAttached = true;
-
- } while (false);
-
- UNLOCK_AR6K(pDev);
-
- if (pProtocol != NULL) {
- /* TODO ... should we use a worker? */
- NotifyTransportReady(pProtocol);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach (0x%lX) \n",(unsigned long)pProtocol));
- return (HCI_TRANSPORT_HANDLE)pProtocol;
-}
-
-void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans)
-{
- struct gmbox_proto_hci_uart *pProtocol = (struct gmbox_proto_hci_uart *)HciTrans;
- struct ar6k_device *pDev = pProtocol->pDev;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportDetach \n"));
-
- LOCK_AR6K(pDev);
- if (!pProtocol->HCIAttached) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not attached! \n"));
- UNLOCK_AR6K(pDev);
- return;
- }
- pProtocol->HCIAttached = false;
- UNLOCK_AR6K(pDev);
-
- HCI_TransportStop(HciTrans);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach \n"));
-}
-
-int HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
- int status = 0;
- bool unblockRecv = false;
- struct htc_packet *pPacket;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCI_TransportAddReceivePkt \n"));
-
- LOCK_HCI_RX(pProt);
-
- do {
-
- if (pProt->HCIStopped) {
- status = A_ECANCELED;
- break;
- }
-
- pPacket = HTC_GET_PKT_AT_HEAD(pQueue);
-
- if (NULL == pPacket) {
- status = A_EINVAL;
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv packet added, type :%d, len:%d num:%d \n",
- HCI_GET_PACKET_TYPE(pPacket), pPacket->BufferLength, HTC_PACKET_QUEUE_DEPTH(pQueue)));
-
- if (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) {
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIEventBuffers, pQueue);
- } else if (HCI_GET_PACKET_TYPE(pPacket) == HCI_ACL_TYPE) {
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIACLRecvBuffers, pQueue);
- } else {
- status = A_EINVAL;
- break;
- }
-
- if (pProt->RecvStateFlags & HCI_RECV_WAIT_BUFFERS) {
- if (pProt->WaitBufferType == HCI_GET_PACKET_TYPE(pPacket)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv was blocked on packet type :%d, unblocking.. \n",
- pProt->WaitBufferType));
- pProt->RecvStateFlags &= ~HCI_RECV_WAIT_BUFFERS;
- pProt->WaitBufferType = HCI_PACKET_INVALID;
- unblockRecv = true;
- }
- }
-
- } while (false);
-
- UNLOCK_HCI_RX(pProt);
-
- if (status) {
- while (!HTC_QUEUE_EMPTY(pQueue)) {
- pPacket = HTC_PACKET_DEQUEUE(pQueue);
- pPacket->Status = A_ECANCELED;
- DO_HCI_RECV_INDICATION(pProt,pPacket);
- }
- }
-
- if (unblockRecv) {
- DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_ASYNC);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCI_TransportAddReceivePkt \n"));
-
- return 0;
-}
-
-int HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
-
- return HCITrySend(pProt,pPacket,Synchronous);
-}
-
-void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStop \n"));
-
- LOCK_AR6K(pProt->pDev);
- if (pProt->HCIStopped) {
- UNLOCK_AR6K(pProt->pDev);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
- return;
- }
- pProt->HCIStopped = true;
- UNLOCK_AR6K(pProt->pDev);
-
- /* disable interrupts */
- DevGMboxIRQAction(pProt->pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC);
- FlushSendQueue(pProt);
- FlushRecvBuffers(pProt);
-
- /* signal bridge side to power down BT */
- DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_OFF, BTOFF_TIMEOUT_MS);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
-}
-
-int HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans)
-{
- int status;
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStart \n"));
-
- /* set stopped in case we have a problem in starting */
- pProt->HCIStopped = true;
-
- do {
-
- status = InitTxCreditState(pProt);
-
- if (status) {
- break;
- }
-
- status = DevGMboxIRQAction(pProt->pDev, GMBOX_ERRORS_IRQ_ENABLE, PROC_IO_SYNC);
-
- if (status) {
- break;
- }
- /* enable recv */
- status = DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_SYNC);
-
- if (status) {
- break;
- }
- /* signal bridge side to power up BT */
- status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_ON, BTON_TIMEOUT_MS);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI_TransportStart : Failed to trigger BT ON \n"));
- break;
- }
-
- /* we made it */
- pProt->HCIStopped = false;
-
- } while (false);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStart \n"));
-
- return status;
-}
-
-int HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, bool Enable)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
- return DevGMboxIRQAction(pProt->pDev,
- Enable ? GMBOX_RECV_IRQ_ENABLE : GMBOX_RECV_IRQ_DISABLE,
- PROC_IO_SYNC);
-
-}
-
-int HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
- struct htc_packet *pPacket,
- int MaxPollMS)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
- int status = 0;
- u8 lookAhead[8];
- int bytes;
- int totalRecvLength;
-
- MaxPollMS = MaxPollMS / 16;
-
- if (MaxPollMS < 2) {
- MaxPollMS = 2;
- }
-
- while (MaxPollMS) {
-
- bytes = sizeof(lookAhead);
- status = DevGMboxRecvLookAheadPeek(pProt->pDev,lookAhead,&bytes);
- if (status) {
- break;
- }
-
- if (bytes < 3) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI recv poll got bytes: %d, retry : %d \n",
- bytes, MaxPollMS));
- A_MDELAY(16);
- MaxPollMS--;
- continue;
- }
-
- totalRecvLength = 0;
- switch (lookAhead[0]) {
- case HCI_UART_EVENT_PKT:
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n",
- lookAhead[1], lookAhead[2]));
- totalRecvLength = lookAhead[2];
- totalRecvLength += 3; /* add type + event code + length field */
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n",lookAhead[0]));
- status = A_EPROTO;
- break;
- }
-
- if (status) {
- break;
- }
-
- pPacket->Completion = NULL;
- status = DevGMboxRead(pProt->pDev,pPacket,totalRecvLength);
- if (status) {
- break;
- }
-
- pPacket->pBuffer++;
- pPacket->ActualLength = totalRecvLength - 1;
- pPacket->Status = 0;
- break;
- }
-
- if (MaxPollMS == 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI recv poll timeout! \n"));
- status = A_ERROR;
- }
-
- return status;
-}
-
-#define LSB_SCRATCH_IDX 4
-#define MSB_SCRATCH_IDX 5
-int HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud)
-{
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
- struct hif_device *pHIFDevice = (struct hif_device *)(pProt->pDev->HIFDevice);
- u32 scaledBaud, scratchAddr;
- int status = 0;
-
- /* Divide the desired baud rate by 100
- * Store the LSB in the local scratch register 4 and the MSB in the local
- * scratch register 5 for the target to read
- */
- scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * LSB_SCRATCH_IDX);
- scaledBaud = (Baud / 100) & LOCAL_SCRATCH_VALUE_MASK;
- status = ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud);
- scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * MSB_SCRATCH_IDX);
- scaledBaud = ((Baud / 100) >> (LOCAL_SCRATCH_VALUE_MSB+1)) & LOCAL_SCRATCH_VALUE_MASK;
- status |= ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud);
- if (0 != status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to set up baud rate in scratch register!"));
- return status;
- }
-
- /* Now interrupt the target to tell it about the baud rate */
- status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BAUD_SET, BAUD_TIMEOUT_MS);
- if (0 != status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to tell target to change baud rate!"));
- }
-
- return status;
-}
-
-int HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, bool Enable)
-{
- int status;
- struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
-
- if (Enable) {
- status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_ON, BTPWRSAV_TIMEOUT_MS);
- } else {
- status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_OFF, BTPWRSAV_TIMEOUT_MS);
- }
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to enable/disable HCI power management!\n"));
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI power management enabled/disabled!\n"));
- }
-
- return status;
-}
-
-#endif //ATH_AR6K_ENABLE_GMBOX
-
diff --git a/drivers/staging/ath6kl/htc2/htc.c b/drivers/staging/ath6kl/htc2/htc.c
deleted file mode 100644
index ae54e64b6243..000000000000
--- a/drivers/staging/ath6kl/htc2/htc.c
+++ /dev/null
@@ -1,575 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc.c" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#include "htc_internal.h"
-
-#ifdef ATH_DEBUG_MODULE
-static struct ath_debug_mask_description g_HTCDebugDescription[] = {
- { ATH_DEBUG_SEND , "Send"},
- { ATH_DEBUG_RECV , "Recv"},
- { ATH_DEBUG_SYNC , "Sync"},
- { ATH_DEBUG_DUMP , "Dump Data (RX or TX)"},
- { ATH_DEBUG_IRQ , "Interrupt Processing"}
-};
-
-ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc,
- "htc",
- "Host Target Communications",
- ATH_DEBUG_MASK_DEFAULTS,
- ATH_DEBUG_DESCRIPTION_COUNT(g_HTCDebugDescription),
- g_HTCDebugDescription);
-
-#endif
-
-static void HTCReportFailure(void *Context);
-static void ResetEndpointStates(struct htc_target *target);
-
-void HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList)
-{
- LOCK_HTC(target);
- HTC_PACKET_ENQUEUE(pList,pPacket);
- UNLOCK_HTC(target);
-}
-
-struct htc_packet *HTCAllocControlBuffer(struct htc_target *target, struct htc_packet_queue *pList)
-{
- struct htc_packet *pPacket;
-
- LOCK_HTC(target);
- pPacket = HTC_PACKET_DEQUEUE(pList);
- UNLOCK_HTC(target);
-
- return pPacket;
-}
-
-/* cleanup the HTC instance */
-static void HTCCleanup(struct htc_target *target)
-{
- s32 i;
-
- DevCleanup(&target->Device);
-
- for (i = 0;i < NUM_CONTROL_BUFFERS;i++) {
- if (target->HTCControlBuffers[i].Buffer) {
- kfree(target->HTCControlBuffers[i].Buffer);
- }
- }
-
- if (A_IS_MUTEX_VALID(&target->HTCLock)) {
- A_MUTEX_DELETE(&target->HTCLock);
- }
-
- if (A_IS_MUTEX_VALID(&target->HTCRxLock)) {
- A_MUTEX_DELETE(&target->HTCRxLock);
- }
-
- if (A_IS_MUTEX_VALID(&target->HTCTxLock)) {
- A_MUTEX_DELETE(&target->HTCTxLock);
- }
- /* free our instance */
- kfree(target);
-}
-
-/* registered target arrival callback from the HIF layer */
-HTC_HANDLE HTCCreate(void *hif_handle, struct htc_init_info *pInfo)
-{
- struct htc_target *target = NULL;
- int status = 0;
- int i;
- u32 ctrl_bufsz;
- u32 blocksizes[HTC_MAILBOX_NUM_MAX];
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Enter\n"));
-
- A_REGISTER_MODULE_DEBUG_INFO(htc);
-
- do {
-
- /* allocate target memory */
- if ((target = (struct htc_target *)A_MALLOC(sizeof(struct htc_target))) == NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n"));
- status = A_ERROR;
- break;
- }
-
- A_MEMZERO(target, sizeof(struct htc_target));
- A_MUTEX_INIT(&target->HTCLock);
- A_MUTEX_INIT(&target->HTCRxLock);
- A_MUTEX_INIT(&target->HTCTxLock);
- INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList);
- INIT_HTC_PACKET_QUEUE(&target->ControlBufferRXFreeList);
-
- /* give device layer the hif device handle */
- target->Device.HIFDevice = hif_handle;
- /* give the device layer our context (for event processing)
- * the device layer will register it's own context with HIF
- * so we need to set this so we can fetch it in the target remove handler */
- target->Device.HTCContext = target;
- /* set device layer target failure callback */
- target->Device.TargetFailureCallback = HTCReportFailure;
- /* set device layer recv message pending callback */
- target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler;
- target->EpWaitingForBuffers = ENDPOINT_MAX;
-
- memcpy(&target->HTCInitInfo,pInfo,sizeof(struct htc_init_info));
-
- ResetEndpointStates(target);
-
- /* setup device layer */
- status = DevSetup(&target->Device);
-
- if (status) {
- break;
- }
-
-
- /* get the block sizes */
- status = HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
- blocksizes, sizeof(blocksizes));
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get block size info from HIF layer...\n"));
- break;
- }
-
- /* Set the control buffer size based on the block size */
- if (blocksizes[1] > HTC_MAX_CONTROL_MESSAGE_LENGTH) {
- ctrl_bufsz = blocksizes[1] + HTC_HDR_LENGTH;
- } else {
- ctrl_bufsz = HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH;
- }
- for (i = 0;i < NUM_CONTROL_BUFFERS;i++) {
- target->HTCControlBuffers[i].Buffer = A_MALLOC(ctrl_bufsz);
- if (target->HTCControlBuffers[i].Buffer == NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n"));
- status = A_ERROR;
- break;
- }
- }
-
- if (status) {
- break;
- }
-
- /* carve up buffers/packets for control messages */
- for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) {
- struct htc_packet *pControlPacket;
- pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
- SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket,
- target,
- target->HTCControlBuffers[i].Buffer,
- ctrl_bufsz,
- ENDPOINT_0);
- HTC_FREE_CONTROL_RX(target,pControlPacket);
- }
-
- for (;i < NUM_CONTROL_BUFFERS;i++) {
- struct htc_packet *pControlPacket;
- pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
- INIT_HTC_PACKET_INFO(pControlPacket,
- target->HTCControlBuffers[i].Buffer,
- ctrl_bufsz);
- HTC_FREE_CONTROL_TX(target,pControlPacket);
- }
-
- } while (false);
-
- if (status) {
- if (target != NULL) {
- HTCCleanup(target);
- target = NULL;
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Exit\n"));
-
- return target;
-}
-
-void HTCDestroy(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy .. Destroying :0x%lX \n",(unsigned long)target));
- HTCCleanup(target);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n"));
-}
-
-/* get the low level HIF device for the caller , the caller may wish to do low level
- * HIF requests */
-void *HTCGetHifDevice(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- return target->Device.HIFDevice;
-}
-
-/* wait for the target to arrive (sends HTC Ready message)
- * this operation is fully synchronous and the message is polled for */
-int HTCWaitTarget(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- int status;
- struct htc_packet *pPacket = NULL;
- HTC_READY_EX_MSG *pRdyMsg;
-
- struct htc_service_connect_req connect;
- struct htc_service_connect_resp resp;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%lX) \n", (unsigned long)target));
-
- do {
-
-#ifdef MBOXHW_UNIT_TEST
-
- status = DoMboxHWTest(&target->Device);
-
- if (status) {
- break;
- }
-
-#endif
-
- /* we should be getting 1 control message that the target is ready */
- status = HTCWaitforControlMessage(target, &pPacket);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n"));
- break;
- }
-
- /* we controlled the buffer creation so it has to be properly aligned */
- pRdyMsg = (HTC_READY_EX_MSG *)pPacket->pBuffer;
-
- if ((pRdyMsg->Version2_0_Info.MessageID != HTC_MSG_READY_ID) ||
- (pPacket->ActualLength < sizeof(HTC_READY_MSG))) {
- /* this message is not valid */
- AR_DEBUG_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
-
- if (pRdyMsg->Version2_0_Info.CreditCount == 0 || pRdyMsg->Version2_0_Info.CreditSize == 0) {
- /* this message is not valid */
- AR_DEBUG_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
- target->TargetCredits = pRdyMsg->Version2_0_Info.CreditCount;
- target->TargetCreditSize = pRdyMsg->Version2_0_Info.CreditSize;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, (" Target Ready: credits: %d credit size: %d\n",
- target->TargetCredits, target->TargetCreditSize));
-
- /* check if this is an extended ready message */
- if (pPacket->ActualLength >= sizeof(HTC_READY_EX_MSG)) {
- /* this is an extended message */
- target->HTCTargetVersion = pRdyMsg->HTCVersion;
- target->MaxMsgPerBundle = pRdyMsg->MaxMsgsPerHTCBundle;
- } else {
- /* legacy */
- target->HTCTargetVersion = HTC_VERSION_2P0;
- target->MaxMsgPerBundle = 0;
- }
-
-#ifdef HTC_FORCE_LEGACY_2P0
- /* for testing and comparison...*/
- target->HTCTargetVersion = HTC_VERSION_2P0;
- target->MaxMsgPerBundle = 0;
-#endif
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
- ("Using HTC Protocol Version : %s (%d)\n ",
- (target->HTCTargetVersion == HTC_VERSION_2P0) ? "2.0" : ">= 2.1",
- target->HTCTargetVersion));
-
- if (target->MaxMsgPerBundle > 0) {
- /* limit what HTC can handle */
- target->MaxMsgPerBundle = min(HTC_HOST_MAX_MSG_PER_BUNDLE, target->MaxMsgPerBundle);
- /* target supports message bundling, setup device layer */
- if (DevSetupMsgBundling(&target->Device,target->MaxMsgPerBundle)) {
- /* device layer can't handle bundling */
- target->MaxMsgPerBundle = 0;
- } else {
- /* limit bundle what the device layer can handle */
- target->MaxMsgPerBundle = min(DEV_GET_MAX_MSG_PER_BUNDLE(&target->Device),
- target->MaxMsgPerBundle);
- }
- }
-
- if (target->MaxMsgPerBundle > 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
- (" HTC bundling allowed. Max Msg Per HTC Bundle: %d\n", target->MaxMsgPerBundle));
-
- if (DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device) != 0) {
- target->SendBundlingEnabled = true;
- }
- if (DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device) != 0) {
- target->RecvBundlingEnabled = true;
- }
-
- if (!DEV_IS_LEN_BLOCK_ALIGNED(&target->Device,target->TargetCreditSize)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("*** Credit size: %d is not block aligned! Disabling send bundling \n",
- target->TargetCreditSize));
- /* disallow send bundling since the credit size is not aligned to a block size
- * the I/O block padding will spill into the next credit buffer which is fatal */
- target->SendBundlingEnabled = false;
- }
- }
-
- /* setup our pseudo HTC control endpoint connection */
- A_MEMZERO(&connect,sizeof(connect));
- A_MEMZERO(&resp,sizeof(resp));
- connect.EpCallbacks.pContext = target;
- connect.EpCallbacks.EpTxComplete = HTCControlTxComplete;
- connect.EpCallbacks.EpRecv = HTCControlRecv;
- connect.EpCallbacks.EpRecvRefill = NULL; /* not needed */
- connect.EpCallbacks.EpSendFull = NULL; /* not nedded */
- connect.MaxSendQueueDepth = NUM_CONTROL_BUFFERS;
- connect.ServiceID = HTC_CTRL_RSVD_SVC;
-
- /* connect fake service */
- status = HTCConnectService((HTC_HANDLE)target,
- &connect,
- &resp);
-
- if (!status) {
- break;
- }
-
- } while (false);
-
- if (pPacket != NULL) {
- HTC_FREE_CONTROL_RX(target,pPacket);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n"));
-
- return status;
-}
-
-
-
-/* Start HTC, enable interrupts and let the target know host has finished setup */
-int HTCStart(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- struct htc_packet *pPacket;
- int status;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n"));
-
- /* make sure interrupts are disabled at the chip level,
- * this function can be called again from a reboot of the target without shutting down HTC */
- DevDisableInterrupts(&target->Device);
- /* make sure state is cleared again */
- target->OpStateFlags = 0;
- target->RecvStateFlags = 0;
-
- /* now that we are starting, push control receive buffers into the
- * HTC control endpoint */
-
- while (1) {
- pPacket = HTC_ALLOC_CONTROL_RX(target);
- if (NULL == pPacket) {
- break;
- }
- HTCAddReceivePkt((HTC_HANDLE)target,pPacket);
- }
-
- do {
-
- AR_DEBUG_ASSERT(target->InitCredits != NULL);
- AR_DEBUG_ASSERT(target->EpCreditDistributionListHead != NULL);
- AR_DEBUG_ASSERT(target->EpCreditDistributionListHead->pNext != NULL);
-
- /* call init credits callback to do the distribution ,
- * NOTE: the first entry in the distribution list is ENDPOINT_0, so
- * we pass the start of the list after this one. */
- target->InitCredits(target->pCredDistContext,
- target->EpCreditDistributionListHead->pNext,
- target->TargetCredits);
-
-#ifdef ATH_DEBUG_MODULE
-
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
- DumpCreditDistStates(target);
- }
-#endif
-
- /* the caller is done connecting to services, so we can indicate to the
- * target that the setup phase is complete */
- status = HTCSendSetupComplete(target);
-
- if (status) {
- break;
- }
-
- /* unmask interrupts */
- status = DevUnmaskInterrupts(&target->Device);
-
- if (status) {
- HTCStop(target);
- }
-
- } while (false);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n"));
- return status;
-}
-
-static void ResetEndpointStates(struct htc_target *target)
-{
- struct htc_endpoint *pEndpoint;
- int i;
-
- for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
- pEndpoint = &target->EndPoint[i];
-
- A_MEMZERO(&pEndpoint->CreditDist, sizeof(pEndpoint->CreditDist));
- pEndpoint->ServiceID = 0;
- pEndpoint->MaxMsgLength = 0;
- pEndpoint->MaxTxQueueDepth = 0;
- A_MEMZERO(&pEndpoint->EndPointStats,sizeof(pEndpoint->EndPointStats));
- INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBuffers);
- INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue);
- INIT_HTC_PACKET_QUEUE(&pEndpoint->RecvIndicationQueue);
- pEndpoint->target = target;
- }
- /* reset distribution list */
- target->EpCreditDistributionListHead = NULL;
-}
-
-/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
-void HTCStop(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n"));
-
- LOCK_HTC(target);
- /* mark that we are shutting down .. */
- target->OpStateFlags |= HTC_OP_STATE_STOPPING;
- UNLOCK_HTC(target);
-
- /* Masking interrupts is a synchronous operation, when this function returns
- * all pending HIF I/O has completed, we can safely flush the queues */
- DevMaskInterrupts(&target->Device);
-
-#ifdef THREAD_X
- //
- // Is this delay required
- //
- A_MDELAY(200); // wait for IRQ process done
-#endif
- /* flush all send packets */
- HTCFlushSendPkts(target);
- /* flush all recv buffers */
- HTCFlushRecvBuffers(target);
-
- DevCleanupMsgBundling(&target->Device);
-
- ResetEndpointStates(target);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n"));
-}
-
-#ifdef ATH_DEBUG_MODULE
-void HTCDumpCreditStates(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-
- LOCK_HTC_TX(target);
-
- DumpCreditDistStates(target);
-
- UNLOCK_HTC_TX(target);
-
- DumpAR6KDevState(&target->Device);
-}
-#endif
-/* report a target failure from the device, this is a callback from the device layer
- * which uses a mechanism to report errors from the target (i.e. special interrupts) */
-static void HTCReportFailure(void *Context)
-{
- struct htc_target *target = (struct htc_target *)Context;
-
- target->TargetFailure = true;
-
- if (target->HTCInitInfo.TargetFailure != NULL) {
- /* let upper layer know, it needs to call HTCStop() */
- target->HTCInitInfo.TargetFailure(target->HTCInitInfo.pContext, A_ERROR);
- }
-}
-
-bool HTCGetEndpointStatistics(HTC_HANDLE HTCHandle,
- HTC_ENDPOINT_ID Endpoint,
- HTC_ENDPOINT_STAT_ACTION Action,
- struct htc_endpoint_stats *pStats)
-{
-
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- bool clearStats = false;
- bool sample = false;
-
- switch (Action) {
- case HTC_EP_STAT_SAMPLE :
- sample = true;
- break;
- case HTC_EP_STAT_SAMPLE_AND_CLEAR :
- sample = true;
- clearStats = true;
- break;
- case HTC_EP_STAT_CLEAR :
- clearStats = true;
- break;
- default:
- break;
- }
-
- A_ASSERT(Endpoint < ENDPOINT_MAX);
-
- /* lock out TX and RX while we sample and/or clear */
- LOCK_HTC_TX(target);
- LOCK_HTC_RX(target);
-
- if (sample) {
- A_ASSERT(pStats != NULL);
- /* return the stats to the caller */
- memcpy(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats));
- }
-
- if (clearStats) {
- /* reset stats */
- A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats));
- }
-
- UNLOCK_HTC_RX(target);
- UNLOCK_HTC_TX(target);
-
- return true;
-}
-
-struct ar6k_device *HTCGetAR6KDevice(void *HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- return &target->Device;
-}
-
diff --git a/drivers/staging/ath6kl/htc2/htc_debug.h b/drivers/staging/ath6kl/htc2/htc_debug.h
deleted file mode 100644
index 8455703e221c..000000000000
--- a/drivers/staging/ath6kl/htc2/htc_debug.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc_debug.h" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef HTC_DEBUG_H_
-#define HTC_DEBUG_H_
-
-#define ATH_MODULE_NAME htc
-#include "a_debug.h"
-
-/* ------- Debug related stuff ------- */
-
-#define ATH_DEBUG_SEND ATH_DEBUG_MAKE_MODULE_MASK(0)
-#define ATH_DEBUG_RECV ATH_DEBUG_MAKE_MODULE_MASK(1)
-#define ATH_DEBUG_SYNC ATH_DEBUG_MAKE_MODULE_MASK(2)
-#define ATH_DEBUG_DUMP ATH_DEBUG_MAKE_MODULE_MASK(3)
-#define ATH_DEBUG_IRQ ATH_DEBUG_MAKE_MODULE_MASK(4)
-
-
-#endif /*HTC_DEBUG_H_*/
diff --git a/drivers/staging/ath6kl/htc2/htc_internal.h b/drivers/staging/ath6kl/htc2/htc_internal.h
deleted file mode 100644
index cac97351769a..000000000000
--- a/drivers/staging/ath6kl/htc2/htc_internal.h
+++ /dev/null
@@ -1,211 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc_internal.h" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _HTC_INTERNAL_H_
-#define _HTC_INTERNAL_H_
-
-/* for debugging, uncomment this to capture the last frame header, on frame header
- * processing errors, the last frame header is dump for comparison */
-//#define HTC_CAPTURE_LAST_FRAME
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Header files */
-
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_osapi.h"
-#include "htc_debug.h"
-#include "htc.h"
-#include "htc_api.h"
-#include "bmi_msg.h"
-#include "hif.h"
-#include "AR6000/ar6k.h"
-
-/* HTC operational parameters */
-#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */
-#define HTC_TARGET_DEBUG_INTR_MASK 0x01
-#define HTC_TARGET_CREDIT_INTR_MASK 0xF0
-
-#define HTC_HOST_MAX_MSG_PER_BUNDLE 8
-#define HTC_MIN_HTC_MSGS_TO_BUNDLE 2
-
-/* packet flags */
-
-#define HTC_RX_PKT_IGNORE_LOOKAHEAD (1 << 0)
-#define HTC_RX_PKT_REFRESH_HDR (1 << 1)
-#define HTC_RX_PKT_PART_OF_BUNDLE (1 << 2)
-#define HTC_RX_PKT_NO_RECYCLE (1 << 3)
-
-/* scatter request flags */
-
-#define HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE (1 << 0)
-
-struct htc_endpoint {
- HTC_ENDPOINT_ID Id;
- HTC_SERVICE_ID ServiceID; /* service ID this endpoint is bound to
- non-zero value means this endpoint is in use */
- struct htc_packet_queue TxQueue; /* HTC frame buffer TX queue */
- struct htc_packet_queue RxBuffers; /* HTC frame buffer RX list */
- struct htc_endpoint_credit_dist CreditDist; /* credit distribution structure (exposed to driver layer) */
- struct htc_ep_callbacks EpCallBacks; /* callbacks associated with this endpoint */
- int MaxTxQueueDepth; /* max depth of the TX queue before we need to
- call driver's full handler */
- int MaxMsgLength; /* max length of endpoint message */
- int TxProcessCount; /* reference count to continue tx processing */
- struct htc_packet_queue RecvIndicationQueue; /* recv packets ready to be indicated */
- int RxProcessCount; /* reference count to allow single processing context */
- struct htc_target *target; /* back pointer to target */
- u8 SeqNo; /* TX seq no (helpful) for debugging */
- u32 LocalConnectionFlags; /* local connection flags */
- struct htc_endpoint_stats EndPointStats; /* endpoint statistics */
-};
-
-#define INC_HTC_EP_STAT(p,stat,count) (p)->EndPointStats.stat += (count);
-#define HTC_SERVICE_TX_PACKET_TAG HTC_TX_PACKET_TAG_INTERNAL
-
-#define NUM_CONTROL_BUFFERS 8
-#define NUM_CONTROL_TX_BUFFERS 2
-#define NUM_CONTROL_RX_BUFFERS (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS)
-
-struct htc_control_buffer {
- struct htc_packet HtcPacket;
- u8 *Buffer;
-};
-
-#define HTC_RECV_WAIT_BUFFERS (1 << 0)
-#define HTC_OP_STATE_STOPPING (1 << 0)
-
-/* our HTC target state */
-struct htc_target {
- struct htc_endpoint EndPoint[ENDPOINT_MAX];
- struct htc_control_buffer HTCControlBuffers[NUM_CONTROL_BUFFERS];
- struct htc_endpoint_credit_dist *EpCreditDistributionListHead;
- struct htc_packet_queue ControlBufferTXFreeList;
- struct htc_packet_queue ControlBufferRXFreeList;
- HTC_CREDIT_DIST_CALLBACK DistributeCredits;
- HTC_CREDIT_INIT_CALLBACK InitCredits;
- void *pCredDistContext;
- int TargetCredits;
- unsigned int TargetCreditSize;
- A_MUTEX_T HTCLock;
- A_MUTEX_T HTCRxLock;
- A_MUTEX_T HTCTxLock;
- struct ar6k_device Device; /* AR6K - specific state */
- u32 OpStateFlags;
- u32 RecvStateFlags;
- HTC_ENDPOINT_ID EpWaitingForBuffers;
- bool TargetFailure;
-#ifdef HTC_CAPTURE_LAST_FRAME
- struct htc_frame_hdr LastFrameHdr; /* useful for debugging */
- u8 LastTrailer[256];
- u8 LastTrailerLength;
-#endif
- struct htc_init_info HTCInitInfo;
- u8 HTCTargetVersion;
- int MaxMsgPerBundle; /* max messages per bundle for HTC */
- bool SendBundlingEnabled; /* run time enable for send bundling (dynamic) */
- int RecvBundlingEnabled; /* run time enable for recv bundling (dynamic) */
-};
-
-#define HTC_STOPPING(t) ((t)->OpStateFlags & HTC_OP_STATE_STOPPING)
-#define LOCK_HTC(t) A_MUTEX_LOCK(&(t)->HTCLock);
-#define UNLOCK_HTC(t) A_MUTEX_UNLOCK(&(t)->HTCLock);
-#define LOCK_HTC_RX(t) A_MUTEX_LOCK(&(t)->HTCRxLock);
-#define UNLOCK_HTC_RX(t) A_MUTEX_UNLOCK(&(t)->HTCRxLock);
-#define LOCK_HTC_TX(t) A_MUTEX_LOCK(&(t)->HTCTxLock);
-#define UNLOCK_HTC_TX(t) A_MUTEX_UNLOCK(&(t)->HTCTxLock);
-
-#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((struct htc_target *)(hnd))
-#define HTC_RECYCLE_RX_PKT(target,p,e) \
-{ \
- if ((p)->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_NO_RECYCLE) { \
- HTC_PACKET_RESET_RX(pPacket); \
- pPacket->Status = A_ECANCELED; \
- (e)->EpCallBacks.EpRecv((e)->EpCallBacks.pContext, \
- (p)); \
- } else { \
- HTC_PACKET_RESET_RX(pPacket); \
- HTCAddReceivePkt((HTC_HANDLE)(target),(p)); \
- } \
-}
-
-/* internal HTC functions */
-void HTCControlTxComplete(void *Context, struct htc_packet *pPacket);
-void HTCControlRecv(void *Context, struct htc_packet *pPacket);
-int HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket);
-struct htc_packet *HTCAllocControlBuffer(struct htc_target *target, struct htc_packet_queue *pList);
-void HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList);
-int HTCIssueSend(struct htc_target *target, struct htc_packet *pPacket);
-void HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket);
-int HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched);
-void HTCProcessCreditRpt(struct htc_target *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint);
-int HTCSendSetupComplete(struct htc_target *target);
-void HTCFlushRecvBuffers(struct htc_target *target);
-void HTCFlushSendPkts(struct htc_target *target);
-
-#ifdef ATH_DEBUG_MODULE
-void DumpCreditDist(struct htc_endpoint_credit_dist *pEPDist);
-void DumpCreditDistStates(struct htc_target *target);
-void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription);
-#endif
-
-static INLINE struct htc_packet *HTC_ALLOC_CONTROL_TX(struct htc_target *target) {
- struct htc_packet *pPacket = HTCAllocControlBuffer(target,&target->ControlBufferTXFreeList);
- if (pPacket != NULL) {
- /* set payload pointer area with some headroom */
- pPacket->pBuffer = pPacket->pBufferStart + HTC_HDR_LENGTH;
- }
- return pPacket;
-}
-
-#define HTC_FREE_CONTROL_TX(t,p) HTCFreeControlBuffer((t),(p),&(t)->ControlBufferTXFreeList)
-#define HTC_ALLOC_CONTROL_RX(t) HTCAllocControlBuffer((t),&(t)->ControlBufferRXFreeList)
-#define HTC_FREE_CONTROL_RX(t,p) \
-{ \
- HTC_PACKET_RESET_RX(p); \
- HTCFreeControlBuffer((t),(p),&(t)->ControlBufferRXFreeList); \
-}
-
-#define HTC_PREPARE_SEND_PKT(pP,sendflags,ctrl0,ctrl1) \
-{ \
- u8 *pHdrBuf; \
- (pP)->pBuffer -= HTC_HDR_LENGTH; \
- pHdrBuf = (pP)->pBuffer; \
- A_SET_UINT16_FIELD(pHdrBuf,struct htc_frame_hdr,PayloadLen,(u16)(pP)->ActualLength); \
- A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,Flags,(sendflags)); \
- A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,EndpointID, (u8)(pP)->Endpoint); \
- A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,ControlBytes[0], (u8)(ctrl0)); \
- A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,ControlBytes[1], (u8)(ctrl1)); \
-}
-
-#define HTC_UNPREPARE_SEND_PKT(pP) \
- (pP)->pBuffer += HTC_HDR_LENGTH; \
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HTC_INTERNAL_H_ */
diff --git a/drivers/staging/ath6kl/htc2/htc_recv.c b/drivers/staging/ath6kl/htc2/htc_recv.c
deleted file mode 100644
index 974cc8cd6936..000000000000
--- a/drivers/staging/ath6kl/htc2/htc_recv.c
+++ /dev/null
@@ -1,1572 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc_recv.c" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#include "htc_internal.h"
-
-#define HTCIssueRecv(t, p) \
- DevRecvPacket(&(t)->Device, \
- (p), \
- (p)->ActualLength)
-
-#define DO_RCV_COMPLETION(e,q) DoRecvCompletion(e,q)
-
-#define DUMP_RECV_PKT_INFO(pP) \
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC RECV packet 0x%lX (%d bytes) (hdr:0x%X) on ep : %d \n", \
- (unsigned long)(pP), \
- (pP)->ActualLength, \
- (pP)->PktInfo.AsRx.ExpectedHdr, \
- (pP)->Endpoint))
-
-#define HTC_RX_STAT_PROFILE(t,ep,numLookAheads) \
-{ \
- INC_HTC_EP_STAT((ep), RxReceived, 1); \
- if ((numLookAheads) == 1) { \
- INC_HTC_EP_STAT((ep), RxLookAheads, 1); \
- } else if ((numLookAheads) > 1) { \
- INC_HTC_EP_STAT((ep), RxBundleLookAheads, 1); \
- } \
-}
-
-static void DoRecvCompletion(struct htc_endpoint *pEndpoint,
- struct htc_packet_queue *pQueueToIndicate)
-{
-
- do {
-
- if (HTC_QUEUE_EMPTY(pQueueToIndicate)) {
- /* nothing to indicate */
- break;
- }
-
- if (pEndpoint->EpCallBacks.EpRecvPktMultiple != NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d, recv multiple callback (%d pkts) \n",
- pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate)));
- /* a recv multiple handler is being used, pass the queue to the handler */
- pEndpoint->EpCallBacks.EpRecvPktMultiple(pEndpoint->EpCallBacks.pContext,
- pQueueToIndicate);
- INIT_HTC_PACKET_QUEUE(pQueueToIndicate);
- } else {
- struct htc_packet *pPacket;
- /* using legacy EpRecv */
- do {
- pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d recv callback on packet 0x%lX \n", \
- pEndpoint->Id, (unsigned long)(pPacket)));
- pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket);
- } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));
- }
-
- } while (false);
-
-}
-
-static INLINE int HTCProcessTrailer(struct htc_target *target,
- u8 *pBuffer,
- int Length,
- u32 *pNextLookAheads,
- int *pNumLookAheads,
- HTC_ENDPOINT_ID FromEndpoint)
-{
- HTC_RECORD_HDR *pRecord;
- u8 *pRecordBuf;
- HTC_LOOKAHEAD_REPORT *pLookAhead;
- u8 *pOrigBuffer;
- int origLength;
- int status;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length));
-
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer");
- }
-
- pOrigBuffer = pBuffer;
- origLength = Length;
- status = 0;
-
- while (Length > 0) {
-
- if (Length < sizeof(HTC_RECORD_HDR)) {
- status = A_EPROTO;
- break;
- }
- /* these are byte aligned structs */
- pRecord = (HTC_RECORD_HDR *)pBuffer;
- Length -= sizeof(HTC_RECORD_HDR);
- pBuffer += sizeof(HTC_RECORD_HDR);
-
- if (pRecord->Length > Length) {
- /* no room left in buffer for record */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- (" invalid record length: %d (id:%d) buffer has: %d bytes left \n",
- pRecord->Length, pRecord->RecordID, Length));
- status = A_EPROTO;
- break;
- }
- /* start of record follows the header */
- pRecordBuf = pBuffer;
-
- switch (pRecord->RecordID) {
- case HTC_RECORD_CREDITS:
- AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_CREDIT_REPORT));
- HTCProcessCreditRpt(target,
- (HTC_CREDIT_REPORT *)pRecordBuf,
- pRecord->Length / (sizeof(HTC_CREDIT_REPORT)),
- FromEndpoint);
- break;
- case HTC_RECORD_LOOKAHEAD:
- AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_LOOKAHEAD_REPORT));
- pLookAhead = (HTC_LOOKAHEAD_REPORT *)pRecordBuf;
- if ((pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) &&
- (pNextLookAheads != NULL)) {
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) \n",
- pLookAhead->PreValid,
- pLookAhead->PostValid));
-
- /* look ahead bytes are valid, copy them over */
- ((u8 *)(&pNextLookAheads[0]))[0] = pLookAhead->LookAhead[0];
- ((u8 *)(&pNextLookAheads[0]))[1] = pLookAhead->LookAhead[1];
- ((u8 *)(&pNextLookAheads[0]))[2] = pLookAhead->LookAhead[2];
- ((u8 *)(&pNextLookAheads[0]))[3] = pLookAhead->LookAhead[3];
-
-#ifdef ATH_DEBUG_MODULE
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- DebugDumpBytes((u8 *)pNextLookAheads,4,"Next Look Ahead");
- }
-#endif
- /* just one normal lookahead */
- *pNumLookAheads = 1;
- }
- break;
- case HTC_RECORD_LOOKAHEAD_BUNDLE:
- AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT));
- if (pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT) &&
- (pNextLookAheads != NULL)) {
- HTC_BUNDLED_LOOKAHEAD_REPORT *pBundledLookAheadRpt;
- int i;
-
- pBundledLookAheadRpt = (HTC_BUNDLED_LOOKAHEAD_REPORT *)pRecordBuf;
-
-#ifdef ATH_DEBUG_MODULE
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- DebugDumpBytes(pRecordBuf,pRecord->Length,"Bundle LookAhead");
- }
-#endif
-
- if ((pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))) >
- HTC_HOST_MAX_MSG_PER_BUNDLE) {
- /* this should never happen, the target restricts the number
- * of messages per bundle configured by the host */
- A_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
- for (i = 0; i < (int)(pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))); i++) {
- ((u8 *)(&pNextLookAheads[i]))[0] = pBundledLookAheadRpt->LookAhead[0];
- ((u8 *)(&pNextLookAheads[i]))[1] = pBundledLookAheadRpt->LookAhead[1];
- ((u8 *)(&pNextLookAheads[i]))[2] = pBundledLookAheadRpt->LookAhead[2];
- ((u8 *)(&pNextLookAheads[i]))[3] = pBundledLookAheadRpt->LookAhead[3];
- pBundledLookAheadRpt++;
- }
-
- *pNumLookAheads = i;
- }
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" unhandled record: id:%d length:%d \n",
- pRecord->RecordID, pRecord->Length));
- break;
- }
-
- if (status) {
- break;
- }
-
- /* advance buffer past this record for next time around */
- pBuffer += pRecord->Length;
- Length -= pRecord->Length;
- }
-
-#ifdef ATH_DEBUG_MODULE
- if (status) {
- DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer");
- }
-#endif
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n"));
- return status;
-
-}
-
-/* process a received message (i.e. strip off header, process any trailer data)
- * note : locks must be released when this function is called */
-static int HTCProcessRecvHeader(struct htc_target *target,
- struct htc_packet *pPacket,
- u32 *pNextLookAheads,
- int *pNumLookAheads)
-{
- u8 temp;
- u8 *pBuf;
- int status = 0;
- u16 payloadLen;
- u32 lookAhead;
-
- pBuf = pPacket->pBuffer;
-
- if (pNumLookAheads != NULL) {
- *pNumLookAheads = 0;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader \n"));
-
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- AR_DEBUG_PRINTBUF(pBuf,pPacket->ActualLength,"HTC Recv PKT");
- }
-
- do {
- /* note, we cannot assume the alignment of pBuffer, so we use the safe macros to
- * retrieve 16 bit fields */
- payloadLen = A_GET_UINT16_FIELD(pBuf, struct htc_frame_hdr, PayloadLen);
-
- ((u8 *)&lookAhead)[0] = pBuf[0];
- ((u8 *)&lookAhead)[1] = pBuf[1];
- ((u8 *)&lookAhead)[2] = pBuf[2];
- ((u8 *)&lookAhead)[3] = pBuf[3];
-
- if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) {
- /* refresh expected hdr, since this was unknown at the time we grabbed the packets
- * as part of a bundle */
- pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead;
- /* refresh actual length since we now have the real header */
- pPacket->ActualLength = payloadLen + HTC_HDR_LENGTH;
-
- /* validate the actual header that was refreshed */
- if (pPacket->ActualLength > pPacket->BufferLength) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Refreshed HDR payload length (%d) in bundled RECV is invalid (hdr: 0x%X) \n",
- payloadLen, lookAhead));
- /* limit this to max buffer just to print out some of the buffer */
- pPacket->ActualLength = min(pPacket->ActualLength, pPacket->BufferLength);
- status = A_EPROTO;
- break;
- }
-
- if (pPacket->Endpoint != A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Refreshed HDR endpoint (%d) does not match expected endpoint (%d) \n",
- A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID), pPacket->Endpoint));
- status = A_EPROTO;
- break;
- }
- }
-
- if (lookAhead != pPacket->PktInfo.AsRx.ExpectedHdr) {
- /* somehow the lookahead that gave us the full read length did not
- * reflect the actual header in the pending message */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("HTCProcessRecvHeader, lookahead mismatch! (pPkt:0x%lX flags:0x%X) \n",
- (unsigned long)pPacket, pPacket->PktInfo.AsRx.HTCRxFlags));
-#ifdef ATH_DEBUG_MODULE
- DebugDumpBytes((u8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead");
- DebugDumpBytes(pBuf,sizeof(struct htc_frame_hdr),"Current Frame Header");
-#ifdef HTC_CAPTURE_LAST_FRAME
- DebugDumpBytes((u8 *)&target->LastFrameHdr,sizeof(struct htc_frame_hdr),"Last Frame Header");
- if (target->LastTrailerLength != 0) {
- DebugDumpBytes(target->LastTrailer,
- target->LastTrailerLength,
- "Last trailer");
- }
-#endif
-#endif
- status = A_EPROTO;
- break;
- }
-
- /* get flags */
- temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, Flags);
-
- if (temp & HTC_FLAGS_RECV_TRAILER) {
- /* this packet has a trailer */
-
- /* extract the trailer length in control byte 0 */
- temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, ControlBytes[0]);
-
- if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("HTCProcessRecvHeader, invalid header (payloadlength should be :%d, CB[0] is:%d) \n",
- payloadLen, temp));
- status = A_EPROTO;
- break;
- }
-
- if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
- /* this packet was fetched as part of an HTC bundle, the embedded lookahead is
- * not valid since the next packet may have already been fetched as part of the
- * bundle */
- pNextLookAheads = NULL;
- pNumLookAheads = NULL;
- }
-
- /* process trailer data that follows HDR + application payload */
- status = HTCProcessTrailer(target,
- (pBuf + HTC_HDR_LENGTH + payloadLen - temp),
- temp,
- pNextLookAheads,
- pNumLookAheads,
- pPacket->Endpoint);
-
- if (status) {
- break;
- }
-
-#ifdef HTC_CAPTURE_LAST_FRAME
- memcpy(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp);
- target->LastTrailerLength = temp;
-#endif
- /* trim length by trailer bytes */
- pPacket->ActualLength -= temp;
- }
-#ifdef HTC_CAPTURE_LAST_FRAME
- else {
- target->LastTrailerLength = 0;
- }
-#endif
-
- /* if we get to this point, the packet is good */
- /* remove header and adjust length */
- pPacket->pBuffer += HTC_HDR_LENGTH;
- pPacket->ActualLength -= HTC_HDR_LENGTH;
-
- } while (false);
-
- if (status) {
- /* dump the whole packet */
-#ifdef ATH_DEBUG_MODULE
- DebugDumpBytes(pBuf,pPacket->ActualLength < 256 ? pPacket->ActualLength : 256 ,"BAD HTC Recv PKT");
-#endif
- } else {
-#ifdef HTC_CAPTURE_LAST_FRAME
- memcpy(&target->LastFrameHdr,pBuf,sizeof(struct htc_frame_hdr));
-#endif
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- if (pPacket->ActualLength > 0) {
- AR_DEBUG_PRINTBUF(pPacket->pBuffer,pPacket->ActualLength,"HTC - Application Msg");
- }
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessRecvHeader \n"));
- return status;
-}
-
-static INLINE void HTCAsyncRecvCheckMorePackets(struct htc_target *target,
- u32 NextLookAheads[],
- int NumLookAheads,
- bool CheckMoreMsgs)
-{
- /* was there a lookahead for the next packet? */
- if (NumLookAheads > 0) {
- int nextStatus;
- int fetched = 0;
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("HTCAsyncRecvCheckMorePackets - num lookaheads were non-zero : %d \n",
- NumLookAheads));
- /* force status re-check */
- REF_IRQ_STATUS_RECHECK(&target->Device);
- /* we have more packets, get the next packet fetch started */
- nextStatus = HTCRecvMessagePendingHandler(target, NextLookAheads, NumLookAheads, NULL, &fetched);
- if (A_EPROTO == nextStatus) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Next look ahead from recv header was INVALID\n"));
-#ifdef ATH_DEBUG_MODULE
- DebugDumpBytes((u8 *)NextLookAheads,
- NumLookAheads * (sizeof(u32)),
- "BAD lookaheads from lookahead report");
-#endif
- }
- if (!nextStatus && !fetched) {
- /* we could not fetch any more packets due to resources */
- DevAsyncIrqProcessComplete(&target->Device);
- }
- } else {
- if (CheckMoreMsgs) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("HTCAsyncRecvCheckMorePackets - rechecking for more messages...\n"));
- /* if we did not get anything on the look-ahead,
- * call device layer to asynchronously re-check for messages. If we can keep the async
- * processing going we get better performance. If there is a pending message we will keep processing
- * messages asynchronously which should pipeline things nicely */
- DevCheckPendingRecvMsgsAsync(&target->Device);
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("HTCAsyncRecvCheckMorePackets - no check \n"));
- }
- }
-
-
-}
-
- /* unload the recv completion queue */
-static INLINE void DrainRecvIndicationQueue(struct htc_target *target, struct htc_endpoint *pEndpoint)
-{
- struct htc_packet_queue recvCompletions;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+DrainRecvIndicationQueue \n"));
-
- INIT_HTC_PACKET_QUEUE(&recvCompletions);
-
- LOCK_HTC_RX(target);
-
- /* increment rx processing count on entry */
- pEndpoint->RxProcessCount++;
- if (pEndpoint->RxProcessCount > 1) {
- pEndpoint->RxProcessCount--;
- /* another thread or task is draining the RX completion queue on this endpoint
- * that thread will reset the rx processing count when the queue is drained */
- UNLOCK_HTC_RX(target);
- return;
- }
-
- /******* at this point only 1 thread may enter ******/
-
- while (true) {
-
- /* transfer items from main recv queue to the local one so we can release the lock */
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&recvCompletions, &pEndpoint->RecvIndicationQueue);
-
- if (HTC_QUEUE_EMPTY(&recvCompletions)) {
- /* all drained */
- break;
- }
-
- /* release lock while we do the recv completions
- * other threads can now queue more recv completions */
- UNLOCK_HTC_RX(target);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("DrainRecvIndicationQueue : completing %d RECV packets \n",
- HTC_PACKET_QUEUE_DEPTH(&recvCompletions)));
- /* do completion */
- DO_RCV_COMPLETION(pEndpoint,&recvCompletions);
-
- /* re-acquire lock to grab some more completions */
- LOCK_HTC_RX(target);
- }
-
- /* reset count */
- pEndpoint->RxProcessCount = 0;
- UNLOCK_HTC_RX(target);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-DrainRecvIndicationQueue \n"));
-
-}
-
- /* optimization for recv packets, we can indicate a "hint" that there are more
- * single-packets to fetch on this endpoint */
-#define SET_MORE_RX_PACKET_INDICATION_FLAG(L,N,E,P) \
- if ((N) > 0) { SetRxPacketIndicationFlags((L)[0],(E),(P)); }
-
- /* for bundled frames, we can force the flag to indicate there are more packets */
-#define FORCE_MORE_RX_PACKET_INDICATION_FLAG(P) \
- (P)->PktInfo.AsRx.IndicationFlags |= HTC_RX_FLAGS_INDICATE_MORE_PKTS;
-
- /* note: this function can be called with the RX lock held */
-static INLINE void SetRxPacketIndicationFlags(u32 LookAhead,
- struct htc_endpoint *pEndpoint,
- struct htc_packet *pPacket)
-{
- struct htc_frame_hdr *pHdr = (struct htc_frame_hdr *)&LookAhead;
- /* check to see if the "next" packet is from the same endpoint of the
- completing packet */
- if (pHdr->EndpointID == pPacket->Endpoint) {
- /* check that there is a buffer available to actually fetch it */
- if (!HTC_QUEUE_EMPTY(&pEndpoint->RxBuffers)) {
- /* provide a hint that there are more RX packets to fetch */
- FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket);
- }
- }
-}
-
-
-/* asynchronous completion handler for recv packet fetching, when the device layer
- * completes a read request, it will call this completion handler */
-void HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket)
-{
- struct htc_target *target = (struct htc_target *)Context;
- struct htc_endpoint *pEndpoint;
- u32 nextLookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
- int numLookAheads = 0;
- int status;
- bool checkMorePkts = true;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (pkt:0x%lX, status:%d, ep:%d) \n",
- (unsigned long)pPacket, pPacket->Status, pPacket->Endpoint));
-
- A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device));
- AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
- pEndpoint = &target->EndPoint[pPacket->Endpoint];
- pPacket->Completion = NULL;
-
- /* get completion status */
- status = pPacket->Status;
-
- do {
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCRecvCompleteHandler: request failed (status:%d, ep:%d) \n",
- pPacket->Status, pPacket->Endpoint));
- break;
- }
- /* process the header for any trailer data */
- status = HTCProcessRecvHeader(target,pPacket,nextLookAheads,&numLookAheads);
-
- if (status) {
- break;
- }
-
- if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
- /* this packet was part of a bundle that had to be broken up.
- * It was fetched one message at a time. There may be other asynchronous reads queued behind this one.
- * Do no issue another check for more packets since the last one in the series of requests
- * will handle it */
- checkMorePkts = false;
- }
-
- DUMP_RECV_PKT_INFO(pPacket);
- LOCK_HTC_RX(target);
- SET_MORE_RX_PACKET_INDICATION_FLAG(nextLookAheads,numLookAheads,pEndpoint,pPacket);
- /* we have a good packet, queue it to the completion queue */
- HTC_PACKET_ENQUEUE(&pEndpoint->RecvIndicationQueue,pPacket);
- HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads);
- UNLOCK_HTC_RX(target);
-
- /* check for more recv packets before indicating */
- HTCAsyncRecvCheckMorePackets(target,nextLookAheads,numLookAheads,checkMorePkts);
-
- } while (false);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n",
- status));
- /* recycle this packet */
- HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint);
- } else {
- /* a good packet was queued, drain the queue */
- DrainRecvIndicationQueue(target,pEndpoint);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvCompleteHandler\n"));
-}
-
-/* synchronously wait for a control message from the target,
- * This function is used at initialization time ONLY. At init messages
- * on ENDPOINT 0 are expected. */
-int HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket)
-{
- int status;
- u32 lookAhead;
- struct htc_packet *pPacket = NULL;
- struct htc_frame_hdr *pHdr;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCWaitforControlMessage \n"));
-
- do {
-
- *ppControlPacket = NULL;
-
- /* call the polling function to see if we have a message */
- status = DevPollMboxMsgRecv(&target->Device,
- &lookAhead,
- HTC_TARGET_RESPONSE_TIMEOUT);
-
- if (status) {
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("HTCWaitforControlMessage : lookAhead : 0x%X \n", lookAhead));
-
- /* check the lookahead */
- pHdr = (struct htc_frame_hdr *)&lookAhead;
-
- if (pHdr->EndpointID != ENDPOINT_0) {
- /* unexpected endpoint number, should be zero */
- AR_DEBUG_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
- if (status) {
- /* bad message */
- AR_DEBUG_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
- pPacket = HTC_ALLOC_CONTROL_RX(target);
-
- if (pPacket == NULL) {
- AR_DEBUG_ASSERT(false);
- status = A_NO_MEMORY;
- break;
- }
-
- pPacket->PktInfo.AsRx.HTCRxFlags = 0;
- pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead;
- pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
-
- if (pPacket->ActualLength > pPacket->BufferLength) {
- AR_DEBUG_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
- /* we want synchronous operation */
- pPacket->Completion = NULL;
-
- /* get the message from the device, this will block */
- status = HTCIssueRecv(target, pPacket);
-
- if (status) {
- break;
- }
-
- /* process receive header */
- status = HTCProcessRecvHeader(target,pPacket,NULL,NULL);
-
- pPacket->Status = status;
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("HTCWaitforControlMessage, HTCProcessRecvHeader failed (status = %d) \n",
- status));
- break;
- }
-
- /* give the caller this control message packet, they are responsible to free */
- *ppControlPacket = pPacket;
-
- } while (false);
-
- if (status) {
- if (pPacket != NULL) {
- /* cleanup buffer on error */
- HTC_FREE_CONTROL_RX(target,pPacket);
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCWaitforControlMessage \n"));
-
- return status;
-}
-
-static int AllocAndPrepareRxPackets(struct htc_target *target,
- u32 LookAheads[],
- int Messages,
- struct htc_endpoint *pEndpoint,
- struct htc_packet_queue *pQueue)
-{
- int status = 0;
- struct htc_packet *pPacket;
- struct htc_frame_hdr *pHdr;
- int i,j;
- int numMessages;
- int fullLength;
- bool noRecycle;
-
- /* lock RX while we assemble the packet buffers */
- LOCK_HTC_RX(target);
-
- for (i = 0; i < Messages; i++) {
-
- pHdr = (struct htc_frame_hdr *)&LookAheads[i];
-
- if (pHdr->EndpointID >= ENDPOINT_MAX) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d \n",pHdr->EndpointID));
- /* invalid endpoint */
- status = A_EPROTO;
- break;
- }
-
- if (pHdr->EndpointID != pEndpoint->Id) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d should be : %d (index:%d)\n",
- pHdr->EndpointID, pEndpoint->Id, i));
- /* invalid endpoint */
- status = A_EPROTO;
- break;
- }
-
- if (pHdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Payload length %d exceeds max HTC : %d !\n",
- pHdr->PayloadLen, (u32)HTC_MAX_PAYLOAD_LENGTH));
- status = A_EPROTO;
- break;
- }
-
- if (0 == pEndpoint->ServiceID) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Endpoint %d is not connected !\n",pHdr->EndpointID));
- /* endpoint isn't even connected */
- status = A_EPROTO;
- break;
- }
-
- if ((pHdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) == 0) {
- /* HTC header only indicates 1 message to fetch */
- numMessages = 1;
- } else {
- /* HTC header indicates that every packet to follow has the same padded length so that it can
- * be optimally fetched as a full bundle */
- numMessages = (pHdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) >> HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT;
- /* the count doesn't include the starter frame, just a count of frames to follow */
- numMessages++;
- A_ASSERT(numMessages <= target->MaxMsgPerBundle);
- INC_HTC_EP_STAT(pEndpoint, RxBundleIndFromHdr, 1);
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("HTC header indicates :%d messages can be fetched as a bundle \n",numMessages));
- }
-
- fullLength = DEV_CALC_RECV_PADDED_LEN(&target->Device,pHdr->PayloadLen + sizeof(struct htc_frame_hdr));
-
- /* get packet buffers for each message, if there was a bundle detected in the header,
- * use pHdr as a template to fetch all packets in the bundle */
- for (j = 0; j < numMessages; j++) {
-
- /* reset flag, any packets allocated using the RecvAlloc() API cannot be recycled on cleanup,
- * they must be explicitly returned */
- noRecycle = false;
-
- if (pEndpoint->EpCallBacks.EpRecvAlloc != NULL) {
- UNLOCK_HTC_RX(target);
- noRecycle = true;
- /* user is using a per-packet allocation callback */
- pPacket = pEndpoint->EpCallBacks.EpRecvAlloc(pEndpoint->EpCallBacks.pContext,
- pEndpoint->Id,
- fullLength);
- LOCK_HTC_RX(target);
-
- } else if ((pEndpoint->EpCallBacks.EpRecvAllocThresh != NULL) &&
- (fullLength > pEndpoint->EpCallBacks.RecvAllocThreshold)) {
- INC_HTC_EP_STAT(pEndpoint,RxAllocThreshHit,1);
- INC_HTC_EP_STAT(pEndpoint,RxAllocThreshBytes,pHdr->PayloadLen);
- /* threshold was hit, call the special recv allocation callback */
- UNLOCK_HTC_RX(target);
- noRecycle = true;
- /* user wants to allocate packets above a certain threshold */
- pPacket = pEndpoint->EpCallBacks.EpRecvAllocThresh(pEndpoint->EpCallBacks.pContext,
- pEndpoint->Id,
- fullLength);
- LOCK_HTC_RX(target);
-
- } else {
- /* user is using a refill handler that can refill multiple HTC buffers */
-
- /* get a packet from the endpoint recv queue */
- pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
-
- if (NULL == pPacket) {
- /* check for refill handler */
- if (pEndpoint->EpCallBacks.EpRecvRefill != NULL) {
- UNLOCK_HTC_RX(target);
- /* call the re-fill handler */
- pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext,
- pEndpoint->Id);
- LOCK_HTC_RX(target);
- /* check if we have more buffers */
- pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
- /* fall through */
- }
- }
- }
-
- if (NULL == pPacket) {
- /* this is not an error, we simply need to mark that we are waiting for buffers.*/
- target->RecvStateFlags |= HTC_RECV_WAIT_BUFFERS;
- target->EpWaitingForBuffers = pEndpoint->Id;
- status = A_NO_RESOURCE;
- break;
- }
-
- AR_DEBUG_ASSERT(pPacket->Endpoint == pEndpoint->Id);
- /* clear flags */
- pPacket->PktInfo.AsRx.HTCRxFlags = 0;
- pPacket->PktInfo.AsRx.IndicationFlags = 0;
- pPacket->Status = 0;
-
- if (noRecycle) {
- /* flag that these packets cannot be recycled, they have to be returned to the
- * user */
- pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_NO_RECYCLE;
- }
- /* add packet to queue (also incase we need to cleanup down below) */
- HTC_PACKET_ENQUEUE(pQueue,pPacket);
-
- if (HTC_STOPPING(target)) {
- status = A_ECANCELED;
- break;
- }
-
- /* make sure this message can fit in the endpoint buffer */
- if ((u32)fullLength > pPacket->BufferLength) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Payload Length Error : header reports payload of: %d (%d) endpoint buffer size: %d \n",
- pHdr->PayloadLen, fullLength, pPacket->BufferLength));
- status = A_EPROTO;
- break;
- }
-
- if (j > 0) {
- /* for messages fetched in a bundle the expected lookahead is unknown since we
- * are only using the lookahead of the first packet as a template of what to
- * expect for lengths */
- /* flag that once we get the real HTC header we need to refesh the information */
- pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_REFRESH_HDR;
- /* set it to something invalid */
- pPacket->PktInfo.AsRx.ExpectedHdr = 0xFFFFFFFF;
- } else {
-
- pPacket->PktInfo.AsRx.ExpectedHdr = LookAheads[i]; /* set expected look ahead */
- }
- /* set the amount of data to fetch */
- pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
- }
-
- if (status) {
- if (A_NO_RESOURCE == status) {
- /* this is actually okay */
- status = 0;
- }
- break;
- }
-
- }
-
- UNLOCK_HTC_RX(target);
-
- if (status) {
- while (!HTC_QUEUE_EMPTY(pQueue)) {
- pPacket = HTC_PACKET_DEQUEUE(pQueue);
- /* recycle all allocated packets */
- HTC_RECYCLE_RX_PKT(target,pPacket,&target->EndPoint[pPacket->Endpoint]);
- }
- }
-
- return status;
-}
-
-static void HTCAsyncRecvScatterCompletion(struct hif_scatter_req *pScatterReq)
-{
- int i;
- struct htc_packet *pPacket;
- struct htc_endpoint *pEndpoint;
- u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
- int numLookAheads = 0;
- struct htc_target *target = (struct htc_target *)pScatterReq->Context;
- int status;
- bool partialBundle = false;
- struct htc_packet_queue localRecvQueue;
- bool procError = false;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCAsyncRecvScatterCompletion TotLen: %d Entries: %d\n",
- pScatterReq->TotalLength, pScatterReq->ValidScatterEntries));
-
- A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device));
-
- if (pScatterReq->CompletionStatus) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Recv Scatter Request Failed: %d \n",pScatterReq->CompletionStatus));
- }
-
- if (pScatterReq->CallerFlags & HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE) {
- partialBundle = true;
- }
-
- DEV_FINISH_SCATTER_OPERATION(pScatterReq);
-
- INIT_HTC_PACKET_QUEUE(&localRecvQueue);
-
- pPacket = (struct htc_packet *)pScatterReq->ScatterList[0].pCallerContexts[0];
- /* note: all packets in a scatter req are for the same endpoint ! */
- pEndpoint = &target->EndPoint[pPacket->Endpoint];
-
- /* walk through the scatter list and process */
- /* **** NOTE: DO NOT HOLD ANY LOCKS here, HTCProcessRecvHeader can take the TX lock
- * as it processes credit reports */
- for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
- pPacket = (struct htc_packet *)pScatterReq->ScatterList[i].pCallerContexts[0];
- A_ASSERT(pPacket != NULL);
- /* reset count, we are only interested in the look ahead in the last packet when we
- * break out of this loop */
- numLookAheads = 0;
-
- if (!pScatterReq->CompletionStatus) {
- /* process header for each of the recv packets */
- status = HTCProcessRecvHeader(target,pPacket,lookAheads,&numLookAheads);
- } else {
- status = A_ERROR;
- }
-
- if (!status) {
- LOCK_HTC_RX(target);
- HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads);
- INC_HTC_EP_STAT(pEndpoint, RxPacketsBundled, 1);
- UNLOCK_HTC_RX(target);
- if (i == (pScatterReq->ValidScatterEntries - 1)) {
- /* last packet's more packets flag is set based on the lookahead */
- SET_MORE_RX_PACKET_INDICATION_FLAG(lookAheads,numLookAheads,pEndpoint,pPacket);
- } else {
- /* packets in a bundle automatically have this flag set */
- FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket);
- }
-
- DUMP_RECV_PKT_INFO(pPacket);
- /* since we can't hold a lock in this loop, we insert into our local recv queue for
- * storage until we can transfer them to the recv completion queue */
- HTC_PACKET_ENQUEUE(&localRecvQueue,pPacket);
-
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Recv packet scatter entry %d failed (out of %d) \n",
- i, pScatterReq->ValidScatterEntries));
- /* recycle failed recv */
- HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint);
- /* set flag and continue processing the remaining scatter entries */
- procError = true;
- }
-
- }
-
- /* free scatter request */
- DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
-
- LOCK_HTC_RX(target);
- /* transfer the packets in the local recv queue to the recv completion queue */
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RecvIndicationQueue, &localRecvQueue);
-
- UNLOCK_HTC_RX(target);
-
- if (!procError) {
- /* pipeline the next check (asynchronously) for more packets */
- HTCAsyncRecvCheckMorePackets(target,
- lookAheads,
- numLookAheads,
- partialBundle ? false : true);
- }
-
- /* now drain the indication queue */
- DrainRecvIndicationQueue(target,pEndpoint);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCAsyncRecvScatterCompletion \n"));
-}
-
-static int HTCIssueRecvPacketBundle(struct htc_target *target,
- struct htc_packet_queue *pRecvPktQueue,
- struct htc_packet_queue *pSyncCompletionQueue,
- int *pNumPacketsFetched,
- bool PartialBundle)
-{
- int status = 0;
- struct hif_scatter_req *pScatterReq;
- int i, totalLength;
- int pktsToScatter;
- struct htc_packet *pPacket;
- bool asyncMode = (pSyncCompletionQueue == NULL) ? true : false;
- int scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device);
-
- pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue);
- pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle);
-
- if ((HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue) - pktsToScatter) > 0) {
- /* we were forced to split this bundle receive operation
- * all packets in this partial bundle must have their lookaheads ignored */
- PartialBundle = true;
- /* this would only happen if the target ignored our max bundle limit */
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
- ("HTCIssueRecvPacketBundle : partial bundle detected num:%d , %d \n",
- HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), pktsToScatter));
- }
-
- totalLength = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCIssueRecvPacketBundle (Numpackets: %d , actual : %d) \n",
- HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), pktsToScatter));
-
- do {
-
- pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device);
-
- if (pScatterReq == NULL) {
- /* no scatter resources left, just let caller handle it the legacy way */
- break;
- }
-
- pScatterReq->CallerFlags = 0;
-
- if (PartialBundle) {
- /* mark that this is a partial bundle, this has special ramifications to the
- * scatter completion routine */
- pScatterReq->CallerFlags |= HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE;
- }
-
- /* convert HTC packets to scatter list */
- for (i = 0; i < pktsToScatter; i++) {
- int paddedLength;
-
- pPacket = HTC_PACKET_DEQUEUE(pRecvPktQueue);
- A_ASSERT(pPacket != NULL);
-
- paddedLength = DEV_CALC_RECV_PADDED_LEN(&target->Device, pPacket->ActualLength);
-
- if ((scatterSpaceRemaining - paddedLength) < 0) {
- /* exceeds what we can transfer, put the packet back */
- HTC_PACKET_ENQUEUE_TO_HEAD(pRecvPktQueue,pPacket);
- break;
- }
-
- scatterSpaceRemaining -= paddedLength;
-
- if (PartialBundle || (i < (pktsToScatter - 1))) {
- /* packet 0..n-1 cannot be checked for look-aheads since we are fetching a bundle
- * the last packet however can have it's lookahead used */
- pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD;
- }
-
- /* note: 1 HTC packet per scatter entry */
- /* setup packet into */
- pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer;
- pScatterReq->ScatterList[i].Length = paddedLength;
-
- pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_PART_OF_BUNDLE;
-
- if (asyncMode) {
- /* save HTC packet for async completion routine */
- pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket;
- } else {
- /* queue to caller's sync completion queue, caller will unload this when we return */
- HTC_PACKET_ENQUEUE(pSyncCompletionQueue,pPacket);
- }
-
- A_ASSERT(pScatterReq->ScatterList[i].Length);
- totalLength += pScatterReq->ScatterList[i].Length;
- }
-
- pScatterReq->TotalLength = totalLength;
- pScatterReq->ValidScatterEntries = i;
-
- if (asyncMode) {
- pScatterReq->CompletionRoutine = HTCAsyncRecvScatterCompletion;
- pScatterReq->Context = target;
- }
-
- status = DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_READ, asyncMode);
-
- if (!status) {
- *pNumPacketsFetched = i;
- }
-
- if (!asyncMode) {
- /* free scatter request */
- DEV_FREE_SCATTER_REQ(&target->Device, pScatterReq);
- }
-
- } while (false);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCIssueRecvPacketBundle (status:%d) (fetched:%d) \n",
- status,*pNumPacketsFetched));
-
- return status;
-}
-
-static INLINE void CheckRecvWaterMark(struct htc_endpoint *pEndpoint)
-{
- /* see if endpoint is using a refill watermark
- * ** no need to use a lock here, since we are only inspecting...
- * caller may must not hold locks when calling this function */
- if (pEndpoint->EpCallBacks.RecvRefillWaterMark > 0) {
- if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBuffers) < pEndpoint->EpCallBacks.RecvRefillWaterMark) {
- /* call the re-fill handler before we continue */
- pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext,
- pEndpoint->Id);
- }
- }
-}
-
-/* callback when device layer or lookahead report parsing detects a pending message */
-int HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched)
-{
- struct htc_target *target = (struct htc_target *)Context;
- int status = 0;
- struct htc_packet *pPacket;
- struct htc_endpoint *pEndpoint;
- bool asyncProc = false;
- u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
- int pktsFetched;
- struct htc_packet_queue recvPktQueue, syncCompletedPktsQueue;
- bool partialBundle;
- HTC_ENDPOINT_ID id;
- int totalFetched = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCRecvMessagePendingHandler NumLookAheads: %d \n",NumLookAheads));
-
- if (pNumPktsFetched != NULL) {
- *pNumPktsFetched = 0;
- }
-
- if (IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(&target->Device)) {
- /* We use async mode to get the packets if the device layer supports it.
- * The device layer interfaces with HIF in which HIF may have restrictions on
- * how interrupts are processed */
- asyncProc = true;
- }
-
- if (pAsyncProc != NULL) {
- /* indicate to caller how we decided to process this */
- *pAsyncProc = asyncProc;
- }
-
- if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) {
- A_ASSERT(false);
- return A_EPROTO;
- }
-
- /* on first entry copy the lookaheads into our temp array for processing */
- memcpy(lookAheads, MsgLookAheads, (sizeof(u32)) * NumLookAheads);
-
- while (true) {
-
- /* reset packets queues */
- INIT_HTC_PACKET_QUEUE(&recvPktQueue);
- INIT_HTC_PACKET_QUEUE(&syncCompletedPktsQueue);
-
- if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) {
- status = A_EPROTO;
- A_ASSERT(false);
- break;
- }
-
- /* first lookahead sets the expected endpoint IDs for all packets in a bundle */
- id = ((struct htc_frame_hdr *)&lookAheads[0])->EndpointID;
- pEndpoint = &target->EndPoint[id];
-
- if (id >= ENDPOINT_MAX) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MsgPend, Invalid Endpoint in look-ahead: %d \n",id));
- status = A_EPROTO;
- break;
- }
-
- /* try to allocate as many HTC RX packets indicated by the lookaheads
- * these packets are stored in the recvPkt queue */
- status = AllocAndPrepareRxPackets(target,
- lookAheads,
- NumLookAheads,
- pEndpoint,
- &recvPktQueue);
- if (status) {
- break;
- }
-
- if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) >= 2) {
- /* a recv bundle was detected, force IRQ status re-check again */
- REF_IRQ_STATUS_RECHECK(&target->Device);
- }
-
- totalFetched += HTC_PACKET_QUEUE_DEPTH(&recvPktQueue);
-
- /* we've got packet buffers for all we can currently fetch,
- * this count is not valid anymore */
- NumLookAheads = 0;
- partialBundle = false;
-
- /* now go fetch the list of HTC packets */
- while (!HTC_QUEUE_EMPTY(&recvPktQueue)) {
-
- pktsFetched = 0;
-
- if (target->RecvBundlingEnabled && (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 1)) {
- /* there are enough packets to attempt a bundle transfer and recv bundling is allowed */
- status = HTCIssueRecvPacketBundle(target,
- &recvPktQueue,
- asyncProc ? NULL : &syncCompletedPktsQueue,
- &pktsFetched,
- partialBundle);
- if (status) {
- break;
- }
-
- if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) != 0) {
- /* we couldn't fetch all packets at one time, this creates a broken
- * bundle */
- partialBundle = true;
- }
- }
-
- /* see if the previous operation fetched any packets using bundling */
- if (0 == pktsFetched) {
- /* dequeue one packet */
- pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue);
- A_ASSERT(pPacket != NULL);
-
- if (asyncProc) {
- /* we use async mode to get the packet if the device layer supports it
- * set our callback and context */
- pPacket->Completion = HTCRecvCompleteHandler;
- pPacket->pContext = target;
- } else {
- /* fully synchronous */
- pPacket->Completion = NULL;
- }
-
- if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 0) {
- /* lookaheads in all packets except the last one in the bundle must be ignored */
- pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD;
- }
-
- /* go fetch the packet */
- status = HTCIssueRecv(target, pPacket);
- if (status) {
- break;
- }
-
- if (!asyncProc) {
- /* sent synchronously, queue this packet for synchronous completion */
- HTC_PACKET_ENQUEUE(&syncCompletedPktsQueue,pPacket);
- }
-
- }
-
- }
-
- if (!status) {
- CheckRecvWaterMark(pEndpoint);
- }
-
- if (asyncProc) {
- /* we did this asynchronously so we can get out of the loop, the asynch processing
- * creates a chain of requests to continue processing pending messages in the
- * context of callbacks */
- break;
- }
-
- /* synchronous handling */
- if (target->Device.DSRCanYield) {
- /* for the SYNC case, increment count that tracks when the DSR should yield */
- target->Device.CurrentDSRRecvCount++;
- }
-
- /* in the sync case, all packet buffers are now filled,
- * we can process each packet, check lookaheads and then repeat */
-
- /* unload sync completion queue */
- while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
- struct htc_packet_queue container;
-
- pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue);
- A_ASSERT(pPacket != NULL);
-
- pEndpoint = &target->EndPoint[pPacket->Endpoint];
- /* reset count on each iteration, we are only interested in the last packet's lookahead
- * information when we break out of this loop */
- NumLookAheads = 0;
- /* process header for each of the recv packets
- * note: the lookahead of the last packet is useful for us to continue in this loop */
- status = HTCProcessRecvHeader(target,pPacket,lookAheads,&NumLookAheads);
- if (status) {
- break;
- }
-
- if (HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
- /* last packet's more packets flag is set based on the lookahead */
- SET_MORE_RX_PACKET_INDICATION_FLAG(lookAheads,NumLookAheads,pEndpoint,pPacket);
- } else {
- /* packets in a bundle automatically have this flag set */
- FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket);
- }
- /* good packet, indicate it */
- HTC_RX_STAT_PROFILE(target,pEndpoint,NumLookAheads);
-
- if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_PART_OF_BUNDLE) {
- INC_HTC_EP_STAT(pEndpoint, RxPacketsBundled, 1);
- }
-
- INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
- DO_RCV_COMPLETION(pEndpoint,&container);
- }
-
- if (status) {
- break;
- }
-
- if (NumLookAheads == 0) {
- /* no more look aheads */
- break;
- }
-
- /* when we process recv synchronously we need to check if we should yield and stop
- * fetching more packets indicated by the embedded lookaheads */
- if (target->Device.DSRCanYield) {
- if (DEV_CHECK_RECV_YIELD(&target->Device)) {
- /* break out, don't fetch any more packets */
- break;
- }
- }
-
-
- /* check whether other OS contexts have queued any WMI command/data for WLAN.
- * This check is needed only if WLAN Tx and Rx happens in same thread context */
- A_CHECK_DRV_TX();
-
- /* for SYNCH processing, if we get here, we are running through the loop again due to a detected lookahead.
- * Set flag that we should re-check IRQ status registers again before leaving IRQ processing,
- * this can net better performance in high throughput situations */
- REF_IRQ_STATUS_RECHECK(&target->Device);
- }
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Failed to get pending recv messages (%d) \n",status));
- /* cleanup any packets we allocated but didn't use to actually fetch any packets */
- while (!HTC_QUEUE_EMPTY(&recvPktQueue)) {
- pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue);
- /* clean up packets */
- HTC_RECYCLE_RX_PKT(target, pPacket, &target->EndPoint[pPacket->Endpoint]);
- }
- /* cleanup any packets in sync completion queue */
- while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
- pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue);
- /* clean up packets */
- HTC_RECYCLE_RX_PKT(target, pPacket, &target->EndPoint[pPacket->Endpoint]);
- }
- if (HTC_STOPPING(target)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
- (" Host is going to stop. blocking receiver for HTCStop.. \n"));
- DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC);
- }
- }
- /* before leaving, check to see if host ran out of buffers and needs to stop the
- * receiver */
- if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
- (" Host has no RX buffers, blocking receiver to prevent overrun.. \n"));
- /* try to stop receive at the device layer */
- DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC);
- }
-
- if (pNumPktsFetched != NULL) {
- *pNumPktsFetched = totalFetched;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCRecvMessagePendingHandler \n"));
-
- return status;
-}
-
-int HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- struct htc_endpoint *pEndpoint;
- bool unblockRecv = false;
- int status = 0;
- struct htc_packet *pFirstPacket;
-
- pFirstPacket = HTC_GET_PKT_AT_HEAD(pPktQueue);
-
- if (NULL == pFirstPacket) {
- A_ASSERT(false);
- return A_EINVAL;
- }
-
- AR_DEBUG_ASSERT(pFirstPacket->Endpoint < ENDPOINT_MAX);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("+- HTCAddReceivePktMultiple : endPointId: %d, cnt:%d, length: %d\n",
- pFirstPacket->Endpoint,
- HTC_PACKET_QUEUE_DEPTH(pPktQueue),
- pFirstPacket->BufferLength));
-
- do {
-
- pEndpoint = &target->EndPoint[pFirstPacket->Endpoint];
-
- LOCK_HTC_RX(target);
-
- if (HTC_STOPPING(target)) {
- struct htc_packet *pPacket;
-
- UNLOCK_HTC_RX(target);
-
- /* walk through queue and mark each one canceled */
- HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) {
- pPacket->Status = A_ECANCELED;
- } HTC_PACKET_QUEUE_ITERATE_END;
-
- DO_RCV_COMPLETION(pEndpoint,pPktQueue);
- break;
- }
-
- /* store receive packets */
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBuffers, pPktQueue);
-
- /* check if we are blocked waiting for a new buffer */
- if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) {
- if (target->EpWaitingForBuffers == pFirstPacket->Endpoint) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" receiver was blocked on ep:%d, unblocking.. \n",
- target->EpWaitingForBuffers));
- target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS;
- target->EpWaitingForBuffers = ENDPOINT_MAX;
- unblockRecv = true;
- }
- }
-
- UNLOCK_HTC_RX(target);
-
- if (unblockRecv && !HTC_STOPPING(target)) {
- /* TODO : implement a buffer threshold count? */
- DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
- }
-
- } while (false);
-
- return status;
-}
-
-/* Makes a buffer available to the HTC module */
-int HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket)
-{
- struct htc_packet_queue queue;
- INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
- return HTCAddReceivePktMultiple(HTCHandle, &queue);
-}
-
-void HTCUnblockRecv(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- bool unblockRecv = false;
-
- LOCK_HTC_RX(target);
-
- /* check if we are blocked waiting for a new buffer */
- if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HTCUnblockRx : receiver was blocked on ep:%d, unblocking.. \n",
- target->EpWaitingForBuffers));
- target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS;
- target->EpWaitingForBuffers = ENDPOINT_MAX;
- unblockRecv = true;
- }
-
- UNLOCK_HTC_RX(target);
-
- if (unblockRecv && !HTC_STOPPING(target)) {
- /* re-enable */
- DevEnableRecv(&target->Device,DEV_ENABLE_RECV_ASYNC);
- }
-}
-
-static void HTCFlushRxQueue(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet_queue *pQueue)
-{
- struct htc_packet *pPacket;
- struct htc_packet_queue container;
-
- LOCK_HTC_RX(target);
-
- while (1) {
- pPacket = HTC_PACKET_DEQUEUE(pQueue);
- if (NULL == pPacket) {
- break;
- }
- UNLOCK_HTC_RX(target);
- pPacket->Status = A_ECANCELED;
- pPacket->ActualLength = 0;
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" Flushing RX packet:0x%lX, length:%d, ep:%d \n",
- (unsigned long)pPacket, pPacket->BufferLength, pPacket->Endpoint));
- INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
- /* give the packet back */
- DO_RCV_COMPLETION(pEndpoint,&container);
- LOCK_HTC_RX(target);
- }
-
- UNLOCK_HTC_RX(target);
-}
-
-static void HTCFlushEndpointRX(struct htc_target *target, struct htc_endpoint *pEndpoint)
-{
- /* flush any recv indications not already made */
- HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RecvIndicationQueue);
- /* flush any rx buffers */
- HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RxBuffers);
-}
-
-void HTCFlushRecvBuffers(struct htc_target *target)
-{
- struct htc_endpoint *pEndpoint;
- int i;
-
- for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
- pEndpoint = &target->EndPoint[i];
- if (pEndpoint->ServiceID == 0) {
- /* not in use.. */
- continue;
- }
- HTCFlushEndpointRX(target,pEndpoint);
- }
-}
-
-
-void HTCEnableRecv(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-
- if (!HTC_STOPPING(target)) {
- /* re-enable */
- DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
- }
-}
-
-void HTCDisableRecv(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-
- if (!HTC_STOPPING(target)) {
- /* disable */
- DevStopRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
- }
-}
-
-int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle,
- HTC_ENDPOINT_ID Endpoint)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- return HTC_PACKET_QUEUE_DEPTH(&(target->EndPoint[Endpoint].RxBuffers));
-}
-
-int HTCWaitForPendingRecv(HTC_HANDLE HTCHandle,
- u32 TimeoutInMs,
- bool *pbIsRecvPending)
-{
- int status = 0;
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-
- status = DevWaitForPendingRecv(&target->Device,
- TimeoutInMs,
- pbIsRecvPending);
-
- return status;
-}
diff --git a/drivers/staging/ath6kl/htc2/htc_send.c b/drivers/staging/ath6kl/htc2/htc_send.c
deleted file mode 100644
index 9310d4d5c992..000000000000
--- a/drivers/staging/ath6kl/htc2/htc_send.c
+++ /dev/null
@@ -1,1018 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc_send.c" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#include "htc_internal.h"
-
-typedef enum _HTC_SEND_QUEUE_RESULT {
- HTC_SEND_QUEUE_OK = 0, /* packet was queued */
- HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */
-} HTC_SEND_QUEUE_RESULT;
-
-#define DO_EP_TX_COMPLETION(ep,q) DoSendCompletion(ep,q)
-
-/* call the distribute credits callback with the distribution */
-#define DO_DISTRIBUTION(t,reason,description,pList) \
-{ \
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, \
- (" calling distribute function (%s) (dfn:0x%lX, ctxt:0x%lX, dist:0x%lX) \n", \
- (description), \
- (unsigned long)(t)->DistributeCredits, \
- (unsigned long)(t)->pCredDistContext, \
- (unsigned long)pList)); \
- (t)->DistributeCredits((t)->pCredDistContext, \
- (pList), \
- (reason)); \
-}
-
-static void DoSendCompletion(struct htc_endpoint *pEndpoint,
- struct htc_packet_queue *pQueueToIndicate)
-{
- do {
-
- if (HTC_QUEUE_EMPTY(pQueueToIndicate)) {
- /* nothing to indicate */
- break;
- }
-
- if (pEndpoint->EpCallBacks.EpTxCompleteMultiple != NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d, send complete multiple callback (%d pkts) \n",
- pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate)));
- /* a multiple send complete handler is being used, pass the queue to the handler */
- pEndpoint->EpCallBacks.EpTxCompleteMultiple(pEndpoint->EpCallBacks.pContext,
- pQueueToIndicate);
- /* all packets are now owned by the callback, reset queue to be safe */
- INIT_HTC_PACKET_QUEUE(pQueueToIndicate);
- } else {
- struct htc_packet *pPacket;
- /* using legacy EpTxComplete */
- do {
- pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d send complete callback on packet 0x%lX \n", \
- pEndpoint->Id, (unsigned long)(pPacket)));
- pEndpoint->EpCallBacks.EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket);
- } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));
- }
-
- } while (false);
-
-}
-
-/* do final completion on sent packet */
-static INLINE void CompleteSentPacket(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet *pPacket)
-{
- pPacket->Completion = NULL;
-
- if (pPacket->Status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("CompleteSentPacket: request failed (status:%d, ep:%d, length:%d creds:%d) \n",
- pPacket->Status, pPacket->Endpoint, pPacket->ActualLength, pPacket->PktInfo.AsTx.CreditsUsed));
- /* on failure to submit, reclaim credits for this packet */
- LOCK_HTC_TX(target);
- pEndpoint->CreditDist.TxCreditsToDist += pPacket->PktInfo.AsTx.CreditsUsed;
- pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
- DO_DISTRIBUTION(target,
- HTC_CREDIT_DIST_SEND_COMPLETE,
- "Send Complete",
- target->EpCreditDistributionListHead->pNext);
- UNLOCK_HTC_TX(target);
- }
- /* first, fixup the head room we allocated */
- pPacket->pBuffer += HTC_HDR_LENGTH;
-}
-
-/* our internal send packet completion handler when packets are submited to the AR6K device
- * layer */
-static void HTCSendPktCompletionHandler(void *Context, struct htc_packet *pPacket)
-{
- struct htc_target *target = (struct htc_target *)Context;
- struct htc_endpoint *pEndpoint = &target->EndPoint[pPacket->Endpoint];
- struct htc_packet_queue container;
-
- CompleteSentPacket(target,pEndpoint,pPacket);
- INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
- /* do completion */
- DO_EP_TX_COMPLETION(pEndpoint,&container);
-}
-
-int HTCIssueSend(struct htc_target *target, struct htc_packet *pPacket)
-{
- int status;
- bool sync = false;
-
- if (pPacket->Completion == NULL) {
- /* mark that this request was synchronously issued */
- sync = true;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
- ("+-HTCIssueSend: transmit length : %d (%s) \n",
- pPacket->ActualLength + (u32)HTC_HDR_LENGTH,
- sync ? "SYNC" : "ASYNC" ));
-
- /* send message to device */
- status = DevSendPacket(&target->Device,
- pPacket,
- pPacket->ActualLength + HTC_HDR_LENGTH);
-
- if (sync) {
- /* use local sync variable. If this was issued asynchronously, pPacket is no longer
- * safe to access. */
- pPacket->pBuffer += HTC_HDR_LENGTH;
- }
-
- /* if this request was asynchronous, the packet completion routine will be invoked by
- * the device layer when the HIF layer completes the request */
-
- return status;
-}
-
- /* get HTC send packets from the TX queue on an endpoint */
-static INLINE void GetHTCSendPackets(struct htc_target *target,
- struct htc_endpoint *pEndpoint,
- struct htc_packet_queue *pQueue)
-{
- int creditsRequired;
- int remainder;
- u8 sendFlags;
- struct htc_packet *pPacket;
- unsigned int transferLength;
-
- /****** NOTE : the TX lock is held when this function is called *****************/
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+GetHTCSendPackets \n"));
-
- /* loop until we can grab as many packets out of the queue as we can */
- while (true) {
-
- sendFlags = 0;
- /* get packet at head, but don't remove it */
- pPacket = HTC_GET_PKT_AT_HEAD(&pEndpoint->TxQueue);
- if (pPacket == NULL) {
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got head packet:0x%lX , Queue Depth: %d\n",
- (unsigned long)pPacket, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
-
- transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device, pPacket->ActualLength + HTC_HDR_LENGTH);
-
- if (transferLength <= target->TargetCreditSize) {
- creditsRequired = 1;
- } else {
- /* figure out how many credits this message requires */
- creditsRequired = transferLength / target->TargetCreditSize;
- remainder = transferLength % target->TargetCreditSize;
-
- if (remainder) {
- creditsRequired++;
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d Got:%d\n",
- creditsRequired, pEndpoint->CreditDist.TxCredits));
-
- if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
-
- /* not enough credits */
- if (pPacket->Endpoint == ENDPOINT_0) {
- /* leave it in the queue */
- break;
- }
- /* invoke the registered distribution function only if this is not
- * endpoint 0, we let the driver layer provide more credits if it can.
- * We pass the credit distribution list starting at the endpoint in question
- * */
-
- /* set how many credits we need */
- pEndpoint->CreditDist.TxCreditsSeek =
- creditsRequired - pEndpoint->CreditDist.TxCredits;
- DO_DISTRIBUTION(target,
- HTC_CREDIT_DIST_SEEK_CREDITS,
- "Seek Credits",
- &pEndpoint->CreditDist);
- pEndpoint->CreditDist.TxCreditsSeek = 0;
-
- if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
- /* still not enough credits to send, leave packet in the queue */
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
- (" Not enough credits for ep %d leaving packet in queue..\n",
- pPacket->Endpoint));
- break;
- }
-
- }
-
- pEndpoint->CreditDist.TxCredits -= creditsRequired;
- INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired);
-
- /* check if we need credits back from the target */
- if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
- /* we are getting low on credits, see if we can ask for more from the distribution function */
- pEndpoint->CreditDist.TxCreditsSeek =
- pEndpoint->CreditDist.TxCreditsPerMaxMsg - pEndpoint->CreditDist.TxCredits;
-
- DO_DISTRIBUTION(target,
- HTC_CREDIT_DIST_SEEK_CREDITS,
- "Seek Credits",
- &pEndpoint->CreditDist);
-
- pEndpoint->CreditDist.TxCreditsSeek = 0;
- /* see if we were successful in getting more */
- if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
- /* tell the target we need credits ASAP! */
- sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
- INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1);
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Host Needs Credits \n"));
- }
- }
-
- /* now we can fully dequeue */
- pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue);
- /* save the number of credits this packet consumed */
- pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired;
- /* all TX packets are handled asynchronously */
- pPacket->Completion = HTCSendPktCompletionHandler;
- pPacket->pContext = target;
- INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
- /* save send flags */
- pPacket->PktInfo.AsTx.SendFlags = sendFlags;
- pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
- pEndpoint->SeqNo++;
- /* queue this packet into the caller's queue */
- HTC_PACKET_ENQUEUE(pQueue,pPacket);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-GetHTCSendPackets \n"));
-
-}
-
-static void HTCAsyncSendScatterCompletion(struct hif_scatter_req *pScatterReq)
-{
- int i;
- struct htc_packet *pPacket;
- struct htc_endpoint *pEndpoint = (struct htc_endpoint *)pScatterReq->Context;
- struct htc_target *target = (struct htc_target *)pEndpoint->target;
- int status = 0;
- struct htc_packet_queue sendCompletes;
-
- INIT_HTC_PACKET_QUEUE(&sendCompletes);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCAsyncSendScatterCompletion TotLen: %d Entries: %d\n",
- pScatterReq->TotalLength, pScatterReq->ValidScatterEntries));
-
- DEV_FINISH_SCATTER_OPERATION(pScatterReq);
-
- if (pScatterReq->CompletionStatus) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Send Scatter Request Failed: %d \n",pScatterReq->CompletionStatus));
- status = A_ERROR;
- }
-
- /* walk through the scatter list and process */
- for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
- pPacket = (struct htc_packet *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
- A_ASSERT(pPacket != NULL);
- pPacket->Status = status;
- CompleteSentPacket(target,pEndpoint,pPacket);
- /* add it to the completion queue */
- HTC_PACKET_ENQUEUE(&sendCompletes, pPacket);
- }
-
- /* free scatter request */
- DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
- /* complete all packets */
- DO_EP_TX_COMPLETION(pEndpoint,&sendCompletes);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCAsyncSendScatterCompletion \n"));
-}
-
- /* drain a queue and send as bundles
- * this function may return without fully draining the queue under the following conditions :
- * - scatter resources are exhausted
- * - a message that will consume a partial credit will stop the bundling process early
- * - we drop below the minimum number of messages for a bundle
- * */
-static void HTCIssueSendBundle(struct htc_endpoint *pEndpoint,
- struct htc_packet_queue *pQueue,
- int *pBundlesSent,
- int *pTotalBundlesPkts)
-{
- int pktsToScatter;
- unsigned int scatterSpaceRemaining;
- struct hif_scatter_req *pScatterReq = NULL;
- int i, packetsInScatterReq;
- unsigned int transferLength;
- struct htc_packet *pPacket;
- bool done = false;
- int bundlesSent = 0;
- int totalPktsInBundle = 0;
- struct htc_target *target = pEndpoint->target;
- int creditRemainder = 0;
- int creditPad;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCIssueSendBundle \n"));
-
- while (!done) {
-
- pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pQueue);
- pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle);
-
- if (pktsToScatter < HTC_MIN_HTC_MSGS_TO_BUNDLE) {
- /* not enough to bundle */
- break;
- }
-
- pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device);
-
- if (pScatterReq == NULL) {
- /* no scatter resources */
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" No more scatter resources \n"));
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" pkts to scatter: %d \n", pktsToScatter));
-
- pScatterReq->TotalLength = 0;
- pScatterReq->ValidScatterEntries = 0;
-
- packetsInScatterReq = 0;
- scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device);
-
- for (i = 0; i < pktsToScatter; i++) {
-
- pScatterReq->ScatterList[i].pCallerContexts[0] = NULL;
-
- pPacket = HTC_GET_PKT_AT_HEAD(pQueue);
- if (pPacket == NULL) {
- A_ASSERT(false);
- break;
- }
-
- creditPad = 0;
- transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device,
- pPacket->ActualLength + HTC_HDR_LENGTH);
- /* see if the padded transfer length falls on a credit boundary */
- creditRemainder = transferLength % target->TargetCreditSize;
-
- if (creditRemainder != 0) {
- /* the transfer consumes a "partial" credit, this packet cannot be bundled unless
- * we add additional "dummy" padding (max 255 bytes) to consume the entire credit
- *** NOTE: only allow the send padding if the endpoint is allowed to */
- if (pEndpoint->LocalConnectionFlags & HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING) {
- if (transferLength < target->TargetCreditSize) {
- /* special case where the transfer is less than a credit */
- creditPad = target->TargetCreditSize - transferLength;
- } else {
- creditPad = creditRemainder;
- }
-
- /* now check to see if we can indicate padding in the HTC header */
- if ((creditPad > 0) && (creditPad <= 255)) {
- /* adjust the transferlength of this packet with the new credit padding */
- transferLength += creditPad;
- } else {
- /* the amount to pad is too large, bail on this packet, we have to
- * send it using the non-bundled method */
- pPacket = NULL;
- }
- } else {
- /* bail on this packet, user does not want padding applied */
- pPacket = NULL;
- }
- }
-
- if (NULL == pPacket) {
- /* can't bundle */
- done = true;
- break;
- }
-
- if (scatterSpaceRemaining < transferLength) {
- /* exceeds what we can transfer */
- break;
- }
-
- scatterSpaceRemaining -= transferLength;
- /* now remove it from the queue */
- pPacket = HTC_PACKET_DEQUEUE(pQueue);
- /* save it in the scatter list */
- pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket;
- /* prepare packet and flag message as part of a send bundle */
- HTC_PREPARE_SEND_PKT(pPacket,
- pPacket->PktInfo.AsTx.SendFlags | HTC_FLAGS_SEND_BUNDLE,
- creditPad,
- pPacket->PktInfo.AsTx.SeqNo);
- pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer;
- pScatterReq->ScatterList[i].Length = transferLength;
- A_ASSERT(transferLength);
- pScatterReq->TotalLength += transferLength;
- pScatterReq->ValidScatterEntries++;
- packetsInScatterReq++;
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" %d, Adding packet : 0x%lX, len:%d (remaining space:%d) \n",
- i, (unsigned long)pPacket,transferLength,scatterSpaceRemaining));
- }
-
- if (packetsInScatterReq >= HTC_MIN_HTC_MSGS_TO_BUNDLE) {
- /* send path is always asynchronous */
- pScatterReq->CompletionRoutine = HTCAsyncSendScatterCompletion;
- pScatterReq->Context = pEndpoint;
- bundlesSent++;
- totalPktsInBundle += packetsInScatterReq;
- packetsInScatterReq = 0;
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Send Scatter total bytes: %d , entries: %d\n",
- pScatterReq->TotalLength,pScatterReq->ValidScatterEntries));
- DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_WRITE, DEV_SCATTER_ASYNC);
- /* we don't own this anymore */
- pScatterReq = NULL;
- /* try to send some more */
- continue;
- }
-
- /* not enough packets to use the scatter request, cleanup */
- if (pScatterReq != NULL) {
- if (packetsInScatterReq > 0) {
- /* work backwards to requeue requests */
- for (i = (packetsInScatterReq - 1); i >= 0; i--) {
- pPacket = (struct htc_packet *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
- if (pPacket != NULL) {
- /* undo any prep */
- HTC_UNPREPARE_SEND_PKT(pPacket);
- /* queue back to the head */
- HTC_PACKET_ENQUEUE_TO_HEAD(pQueue,pPacket);
- }
- }
- }
- DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
- }
-
- /* if we get here, we sent all that we could, get out */
- break;
-
- }
-
- *pBundlesSent = bundlesSent;
- *pTotalBundlesPkts = totalPktsInBundle;
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCIssueSendBundle (sent:%d) \n",bundlesSent));
-
- return;
-}
-
-/*
- * if there are no credits, the packet(s) remains in the queue.
- * this function returns the result of the attempt to send a queue of HTC packets */
-static HTC_SEND_QUEUE_RESULT HTCTrySend(struct htc_target *target,
- struct htc_endpoint *pEndpoint,
- struct htc_packet_queue *pCallersSendQueue)
-{
- struct htc_packet_queue sendQueue; /* temp queue to hold packets at various stages */
- struct htc_packet *pPacket;
- int bundlesSent;
- int pktsInBundles;
- int overflow;
- HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (Queue:0x%lX Depth:%d)\n",
- (unsigned long)pCallersSendQueue,
- (pCallersSendQueue == NULL) ? 0 : HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue)));
-
- /* init the local send queue */
- INIT_HTC_PACKET_QUEUE(&sendQueue);
-
- do {
-
- if (NULL == pCallersSendQueue) {
- /* caller didn't provide a queue, just wants us to check queues and send */
- break;
- }
-
- if (HTC_QUEUE_EMPTY(pCallersSendQueue)) {
- /* empty queue */
- result = HTC_SEND_QUEUE_DROP;
- break;
- }
-
- if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >= pEndpoint->MaxTxQueueDepth) {
- /* we've already overflowed */
- overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
- } else {
- /* figure out how much we will overflow by */
- overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
- overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
- /* figure out how much we will overflow the TX queue by */
- overflow -= pEndpoint->MaxTxQueueDepth;
- }
-
- /* if overflow is negative or zero, we are okay */
- if (overflow > 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
- (" Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d \n",
- pEndpoint->Id, overflow, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue), pEndpoint->MaxTxQueueDepth));
- }
- if ((overflow <= 0) || (pEndpoint->EpCallBacks.EpSendFull == NULL)) {
- /* all packets will fit or caller did not provide send full indication handler
- * -- just move all of them to the local sendQueue object */
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue, pCallersSendQueue);
- } else {
- int i;
- int goodPkts = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) - overflow;
-
- A_ASSERT(goodPkts >= 0);
- /* we have overflowed, and a callback is provided */
- /* dequeue all non-overflow packets into the sendqueue */
- for (i = 0; i < goodPkts; i++) {
- /* pop off caller's queue*/
- pPacket = HTC_PACKET_DEQUEUE(pCallersSendQueue);
- A_ASSERT(pPacket != NULL);
- /* insert into local queue */
- HTC_PACKET_ENQUEUE(&sendQueue,pPacket);
- }
-
- /* the caller's queue has all the packets that won't fit*/
- /* walk through the caller's queue and indicate each one to the send full handler */
- ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacket, struct htc_packet, ListLink) {
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Indicating overflowed TX packet: 0x%lX \n",
- (unsigned long)pPacket));
- if (pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext,
- pPacket) == HTC_SEND_FULL_DROP) {
- /* callback wants the packet dropped */
- INC_HTC_EP_STAT(pEndpoint, TxDropped, 1);
- /* leave this one in the caller's queue for cleanup */
- } else {
- /* callback wants to keep this packet, remove from caller's queue */
- HTC_PACKET_REMOVE(pCallersSendQueue, pPacket);
- /* put it in the send queue */
- HTC_PACKET_ENQUEUE(&sendQueue,pPacket);
- }
-
- } ITERATE_END;
-
- if (HTC_QUEUE_EMPTY(&sendQueue)) {
- /* no packets made it in, caller will cleanup */
- result = HTC_SEND_QUEUE_DROP;
- break;
- }
- }
-
- } while (false);
-
- if (result != HTC_SEND_QUEUE_OK) {
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
- return result;
- }
-
- LOCK_HTC_TX(target);
-
- if (!HTC_QUEUE_EMPTY(&sendQueue)) {
- /* transfer packets */
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,&sendQueue);
- A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue));
- INIT_HTC_PACKET_QUEUE(&sendQueue);
- }
-
- /* increment tx processing count on entry */
- pEndpoint->TxProcessCount++;
- if (pEndpoint->TxProcessCount > 1) {
- /* another thread or task is draining the TX queues on this endpoint
- * that thread will reset the tx processing count when the queue is drained */
- pEndpoint->TxProcessCount--;
- UNLOCK_HTC_TX(target);
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend (busy) \n"));
- return HTC_SEND_QUEUE_OK;
- }
-
- /***** beyond this point only 1 thread may enter ******/
-
- /* now drain the endpoint TX queue for transmission as long as we have enough
- * credits */
- while (true) {
-
- if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) {
- break;
- }
-
- /* get all the packets for this endpoint that we can for this pass */
- GetHTCSendPackets(target, pEndpoint, &sendQueue);
-
- if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) {
- /* didn't get any packets due to a lack of credits */
- break;
- }
-
- UNLOCK_HTC_TX(target);
-
- /* any packets to send are now in our local send queue */
-
- bundlesSent = 0;
- pktsInBundles = 0;
-
- while (true) {
-
- /* try to send a bundle on each pass */
- if ((target->SendBundlingEnabled) &&
- (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >= HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
- int temp1,temp2;
- /* bundling is enabled and there is at least a minimum number of packets in the send queue
- * send what we can in this pass */
- HTCIssueSendBundle(pEndpoint, &sendQueue, &temp1, &temp2);
- bundlesSent += temp1;
- pktsInBundles += temp2;
- }
-
- /* if not bundling or there was a packet that could not be placed in a bundle, pull it out
- * and send it the normal way */
- pPacket = HTC_PACKET_DEQUEUE(&sendQueue);
- if (NULL == pPacket) {
- /* local queue is fully drained */
- break;
- }
- HTC_PREPARE_SEND_PKT(pPacket,
- pPacket->PktInfo.AsTx.SendFlags,
- 0,
- pPacket->PktInfo.AsTx.SeqNo);
- HTCIssueSend(target, pPacket);
-
- /* go back and see if we can bundle some more */
- }
-
- LOCK_HTC_TX(target);
-
- INC_HTC_EP_STAT(pEndpoint, TxBundles, bundlesSent);
- INC_HTC_EP_STAT(pEndpoint, TxPacketsBundled, pktsInBundles);
-
- }
-
- /* done with this endpoint, we can clear the count */
- pEndpoint->TxProcessCount = 0;
- UNLOCK_HTC_TX(target);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
-
- return HTC_SEND_QUEUE_OK;
-}
-
-int HTCSendPktsMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- struct htc_endpoint *pEndpoint;
- struct htc_packet *pPacket;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCSendPktsMultiple: Queue: 0x%lX, Pkts %d \n",
- (unsigned long)pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue)));
-
- /* get packet at head to figure out which endpoint these packets will go into */
- pPacket = HTC_GET_PKT_AT_HEAD(pPktQueue);
- if (NULL == pPacket) {
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n"));
- return A_EINVAL;
- }
-
- AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
- pEndpoint = &target->EndPoint[pPacket->Endpoint];
-
- HTCTrySend(target, pEndpoint, pPktQueue);
-
- /* do completion on any packets that couldn't get in */
- if (!HTC_QUEUE_EMPTY(pPktQueue)) {
-
- HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) {
- if (HTC_STOPPING(target)) {
- pPacket->Status = A_ECANCELED;
- } else {
- pPacket->Status = A_NO_RESOURCE;
- }
- } HTC_PACKET_QUEUE_ITERATE_END;
-
- DO_EP_TX_COMPLETION(pEndpoint,pPktQueue);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n"));
-
- return 0;
-}
-
-/* HTC API - HTCSendPkt */
-int HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket)
-{
- struct htc_packet_queue queue;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
- ("+-HTCSendPkt: Enter endPointId: %d, buffer: 0x%lX, length: %d \n",
- pPacket->Endpoint, (unsigned long)pPacket->pBuffer, pPacket->ActualLength));
- INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
- return HTCSendPktsMultiple(HTCHandle, &queue);
-}
-
-/* check TX queues to drain because of credit distribution update */
-static INLINE void HTCCheckEndpointTxQueues(struct htc_target *target)
-{
- struct htc_endpoint *pEndpoint;
- struct htc_endpoint_credit_dist *pDistItem;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n"));
- pDistItem = target->EpCreditDistributionListHead;
-
- /* run through the credit distribution list to see
- * if there are packets queued
- * NOTE: no locks need to be taken since the distribution list
- * is not dynamic (cannot be re-ordered) and we are not modifying any state */
- while (pDistItem != NULL) {
- pEndpoint = (struct htc_endpoint *)pDistItem->pHTCReserved;
-
- if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) > 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packets in TX Queue \n",
- pDistItem->Endpoint, pEndpoint->CreditDist.TxCredits, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
- /* try to start the stalled queue, this list is ordered by priority.
- * Highest priority queue get's processed first, if there are credits available the
- * highest priority queue will get a chance to reclaim credits from lower priority
- * ones */
- HTCTrySend(target, pEndpoint, NULL);
- }
-
- pDistItem = pDistItem->pNext;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCCheckEndpointTxQueues \n"));
-}
-
-/* process credit reports and call distribution function */
-void HTCProcessCreditRpt(struct htc_target *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
-{
- int i;
- struct htc_endpoint *pEndpoint;
- int totalCredits = 0;
- bool doDist = false;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries));
-
- /* lock out TX while we update credits */
- LOCK_HTC_TX(target);
-
- for (i = 0; i < NumEntries; i++, pRpt++) {
- if (pRpt->EndpointID >= ENDPOINT_MAX) {
- AR_DEBUG_ASSERT(false);
- break;
- }
-
- pEndpoint = &target->EndPoint[pRpt->EndpointID];
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d got %d credits \n",
- pRpt->EndpointID, pRpt->Credits));
-
- INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
- INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, pRpt->Credits);
-
- if (FromEndpoint == pRpt->EndpointID) {
- /* this credit report arrived on the same endpoint indicating it arrived in an RX
- * packet */
- INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, pRpt->Credits);
- INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1);
- } else if (FromEndpoint == ENDPOINT_0) {
- /* this credit arrived on endpoint 0 as a NULL message */
- INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, pRpt->Credits);
- INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1);
- } else {
- /* arrived on another endpoint */
- INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, pRpt->Credits);
- INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
- }
-
- if (ENDPOINT_0 == pRpt->EndpointID) {
- /* always give endpoint 0 credits back */
- pEndpoint->CreditDist.TxCredits += pRpt->Credits;
- } else {
- /* for all other endpoints, update credits to distribute, the distribution function
- * will handle giving out credits back to the endpoints */
- pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits;
- /* flag that we have to do the distribution */
- doDist = true;
- }
-
- /* refresh tx depth for distribution function that will recover these credits
- * NOTE: this is only valid when there are credits to recover! */
- pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
-
- totalCredits += pRpt->Credits;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribute \n", totalCredits));
-
- if (doDist) {
- /* this was a credit return based on a completed send operations
- * note, this is done with the lock held */
- DO_DISTRIBUTION(target,
- HTC_CREDIT_DIST_SEND_COMPLETE,
- "Send Complete",
- target->EpCreditDistributionListHead->pNext);
- }
-
- UNLOCK_HTC_TX(target);
-
- if (totalCredits) {
- HTCCheckEndpointTxQueues(target);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n"));
-}
-
-/* flush endpoint TX queue */
-static void HTCFlushEndpointTX(struct htc_target *target, struct htc_endpoint *pEndpoint, HTC_TX_TAG Tag)
-{
- struct htc_packet *pPacket;
- struct htc_packet_queue discardQueue;
- struct htc_packet_queue container;
-
- /* initialize the discard queue */
- INIT_HTC_PACKET_QUEUE(&discardQueue);
-
- LOCK_HTC_TX(target);
-
- /* interate from the front of the TX queue and flush out packets */
- ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, struct htc_packet, ListLink) {
-
- /* check for removal */
- if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag)) {
- /* remove from queue */
- HTC_PACKET_REMOVE(&pEndpoint->TxQueue, pPacket);
- /* add it to the discard pile */
- HTC_PACKET_ENQUEUE(&discardQueue, pPacket);
- }
-
- } ITERATE_END;
-
- UNLOCK_HTC_TX(target);
-
- /* empty the discard queue */
- while (1) {
- pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
- if (NULL == pPacket) {
- break;
- }
- pPacket->Status = A_ECANCELED;
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Flushing TX packet:0x%lX, length:%d, ep:%d tag:0x%X \n",
- (unsigned long)pPacket, pPacket->ActualLength, pPacket->Endpoint, pPacket->PktInfo.AsTx.Tag));
- INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
- DO_EP_TX_COMPLETION(pEndpoint,&container);
- }
-
-}
-
-void DumpCreditDist(struct htc_endpoint_credit_dist *pEPDist)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n",
- pEPDist->Endpoint, pEPDist->ServiceID));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" this:0x%lX next:0x%lX prev:0x%lX\n",
- (unsigned long)pEPDist, (unsigned long)pEPDist->pNext, (unsigned long)pEPDist->pPrev));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" DistFlags : 0x%X \n", pEPDist->DistFlags));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsNorm : %d \n", pEPDist->TxCreditsNorm));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsMin : %d \n", pEPDist->TxCreditsMin));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEPDist->TxCredits));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsAssigned : %d \n", pEPDist->TxCreditsAssigned));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsSeek : %d \n", pEPDist->TxCreditsSeek));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEPDist->TxCreditSize));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCreditsPerMaxMsg));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist : %d \n", pEPDist->TxCreditsToDist));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n",
- HTC_PACKET_QUEUE_DEPTH(&((struct htc_endpoint *)pEPDist->pHTCReserved)->TxQueue)));
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n"));
-}
-
-void DumpCreditDistStates(struct htc_target *target)
-{
- struct htc_endpoint_credit_dist *pEPList = target->EpCreditDistributionListHead;
-
- while (pEPList != NULL) {
- DumpCreditDist(pEPList);
- pEPList = pEPList->pNext;
- }
-
- if (target->DistributeCredits != NULL) {
- DO_DISTRIBUTION(target,
- HTC_DUMP_CREDIT_STATE,
- "Dump State",
- NULL);
- }
-}
-
-/* flush all send packets from all endpoint queues */
-void HTCFlushSendPkts(struct htc_target *target)
-{
- struct htc_endpoint *pEndpoint;
- int i;
-
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
- DumpCreditDistStates(target);
- }
-
- for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
- pEndpoint = &target->EndPoint[i];
- if (pEndpoint->ServiceID == 0) {
- /* not in use.. */
- continue;
- }
- HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL);
- }
-
-
-}
-
-/* HTC API to flush an endpoint's TX queue*/
-void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- struct htc_endpoint *pEndpoint = &target->EndPoint[Endpoint];
-
- if (pEndpoint->ServiceID == 0) {
- AR_DEBUG_ASSERT(false);
- /* not in use.. */
- return;
- }
-
- HTCFlushEndpointTX(target, pEndpoint, Tag);
-}
-
-/* HTC API to indicate activity to the credit distribution function */
-void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
- HTC_ENDPOINT_ID Endpoint,
- bool Active)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- struct htc_endpoint *pEndpoint = &target->EndPoint[Endpoint];
- bool doDist = false;
-
- if (pEndpoint->ServiceID == 0) {
- AR_DEBUG_ASSERT(false);
- /* not in use.. */
- return;
- }
-
- LOCK_HTC_TX(target);
-
- if (Active) {
- if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) {
- /* mark active now */
- pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE;
- doDist = true;
- }
- } else {
- if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
- /* mark inactive now */
- pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE;
- doDist = true;
- }
- }
-
- if (doDist) {
- /* indicate current Tx Queue depth to the credit distribution function */
- pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
- /* do distribution again based on activity change
- * note, this is done with the lock held */
- DO_DISTRIBUTION(target,
- HTC_CREDIT_DIST_ACTIVITY_CHANGE,
- "Activity Change",
- target->EpCreditDistributionListHead->pNext);
- }
-
- UNLOCK_HTC_TX(target);
-
- if (doDist && !Active) {
- /* if a stream went inactive and this resulted in a credit distribution change,
- * some credits may now be available for HTC packets that are stuck in
- * HTC queues */
- HTCCheckEndpointTxQueues(target);
- }
-}
-
-bool HTCIsEndpointActive(HTC_HANDLE HTCHandle,
- HTC_ENDPOINT_ID Endpoint)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- struct htc_endpoint *pEndpoint = &target->EndPoint[Endpoint];
-
- if (pEndpoint->ServiceID == 0) {
- return false;
- }
-
- if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
- return true;
- }
-
- return false;
-}
diff --git a/drivers/staging/ath6kl/htc2/htc_services.c b/drivers/staging/ath6kl/htc2/htc_services.c
deleted file mode 100644
index c48070cbd54f..000000000000
--- a/drivers/staging/ath6kl/htc2/htc_services.c
+++ /dev/null
@@ -1,450 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc_services.c" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#include "htc_internal.h"
-
-void HTCControlTxComplete(void *Context, struct htc_packet *pPacket)
-{
- /* not implemented
- * we do not send control TX frames during normal runtime, only during setup */
- AR_DEBUG_ASSERT(false);
-}
-
- /* callback when a control message arrives on this endpoint */
-void HTCControlRecv(void *Context, struct htc_packet *pPacket)
-{
- AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0);
-
- if (pPacket->Status == A_ECANCELED) {
- /* this is a flush operation, return the control packet back to the pool */
- HTC_FREE_CONTROL_RX((struct htc_target*)Context,pPacket);
- return;
- }
-
- /* the only control messages we are expecting are NULL messages (credit resports) */
- if (pPacket->ActualLength > 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("HTCControlRecv, got message with length:%d \n",
- pPacket->ActualLength + (u32)HTC_HDR_LENGTH));
-
-#ifdef ATH_DEBUG_MODULE
- /* dump header and message */
- DebugDumpBytes(pPacket->pBuffer - HTC_HDR_LENGTH,
- pPacket->ActualLength + HTC_HDR_LENGTH,
- "Unexpected ENDPOINT 0 Message");
-#endif
- }
-
- HTC_RECYCLE_RX_PKT((struct htc_target*)Context,pPacket,&((struct htc_target*)Context)->EndPoint[0]);
-}
-
-int HTCSendSetupComplete(struct htc_target *target)
-{
- struct htc_packet *pSendPacket = NULL;
- int status;
-
- do {
- /* allocate a packet to send to the target */
- pSendPacket = HTC_ALLOC_CONTROL_TX(target);
-
- if (NULL == pSendPacket) {
- status = A_NO_MEMORY;
- break;
- }
-
- if (target->HTCTargetVersion >= HTC_VERSION_2P1) {
- HTC_SETUP_COMPLETE_EX_MSG *pSetupCompleteEx;
- u32 setupFlags = 0;
-
- pSetupCompleteEx = (HTC_SETUP_COMPLETE_EX_MSG *)pSendPacket->pBuffer;
- A_MEMZERO(pSetupCompleteEx, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
- pSetupCompleteEx->MessageID = HTC_MSG_SETUP_COMPLETE_EX_ID;
- if (target->MaxMsgPerBundle > 0) {
- /* host can do HTC bundling, indicate this to the target */
- setupFlags |= HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV;
- pSetupCompleteEx->MaxMsgsPerBundledRecv = target->MaxMsgPerBundle;
- }
- memcpy(&pSetupCompleteEx->SetupFlags, &setupFlags, sizeof(pSetupCompleteEx->SetupFlags));
- SET_HTC_PACKET_INFO_TX(pSendPacket,
- NULL,
- (u8 *)pSetupCompleteEx,
- sizeof(HTC_SETUP_COMPLETE_EX_MSG),
- ENDPOINT_0,
- HTC_SERVICE_TX_PACKET_TAG);
-
- } else {
- HTC_SETUP_COMPLETE_MSG *pSetupComplete;
- /* assemble setup complete message */
- pSetupComplete = (HTC_SETUP_COMPLETE_MSG *)pSendPacket->pBuffer;
- A_MEMZERO(pSetupComplete, sizeof(HTC_SETUP_COMPLETE_MSG));
- pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID;
- SET_HTC_PACKET_INFO_TX(pSendPacket,
- NULL,
- (u8 *)pSetupComplete,
- sizeof(HTC_SETUP_COMPLETE_MSG),
- ENDPOINT_0,
- HTC_SERVICE_TX_PACKET_TAG);
- }
-
- /* we want synchronous operation */
- pSendPacket->Completion = NULL;
- HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0);
- /* send the message */
- status = HTCIssueSend(target,pSendPacket);
-
- } while (false);
-
- if (pSendPacket != NULL) {
- HTC_FREE_CONTROL_TX(target,pSendPacket);
- }
-
- return status;
-}
-
-
-int HTCConnectService(HTC_HANDLE HTCHandle,
- struct htc_service_connect_req *pConnectReq,
- struct htc_service_connect_resp *pConnectResp)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- int status = 0;
- struct htc_packet *pRecvPacket = NULL;
- struct htc_packet *pSendPacket = NULL;
- HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg;
- HTC_CONNECT_SERVICE_MSG *pConnectMsg;
- HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX;
- struct htc_endpoint *pEndpoint;
- unsigned int maxMsgSize = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%lX SvcID:0x%X \n",
- (unsigned long)target, pConnectReq->ServiceID));
-
- do {
-
- AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0);
-
- if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) {
- /* special case for pseudo control service */
- assignedEndpoint = ENDPOINT_0;
- maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH;
- } else {
- /* allocate a packet to send to the target */
- pSendPacket = HTC_ALLOC_CONTROL_TX(target);
-
- if (NULL == pSendPacket) {
- AR_DEBUG_ASSERT(false);
- status = A_NO_MEMORY;
- break;
- }
- /* assemble connect service message */
- pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)pSendPacket->pBuffer;
- AR_DEBUG_ASSERT(pConnectMsg != NULL);
- A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG));
- pConnectMsg->MessageID = HTC_MSG_CONNECT_SERVICE_ID;
- pConnectMsg->ServiceID = pConnectReq->ServiceID;
- pConnectMsg->ConnectionFlags = pConnectReq->ConnectionFlags;
- /* check caller if it wants to transfer meta data */
- if ((pConnectReq->pMetaData != NULL) &&
- (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) {
- /* copy meta data into message buffer (after header ) */
- memcpy((u8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG),
- pConnectReq->pMetaData,
- pConnectReq->MetaDataLength);
- pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength;
- }
-
- SET_HTC_PACKET_INFO_TX(pSendPacket,
- NULL,
- (u8 *)pConnectMsg,
- sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength,
- ENDPOINT_0,
- HTC_SERVICE_TX_PACKET_TAG);
-
- /* we want synchronous operation */
- pSendPacket->Completion = NULL;
- HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0);
- status = HTCIssueSend(target,pSendPacket);
-
- if (status) {
- break;
- }
-
- /* wait for response */
- status = HTCWaitforControlMessage(target, &pRecvPacket);
-
- if (status) {
- break;
- }
- /* we controlled the buffer creation so it has to be properly aligned */
- pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)pRecvPacket->pBuffer;
-
- if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) ||
- (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) {
- /* this message is not valid */
- AR_DEBUG_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
- pConnectResp->ConnectRespCode = pResponseMsg->Status;
- /* check response status */
- if (pResponseMsg->Status != HTC_SERVICE_SUCCESS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- (" Target failed service 0x%X connect request (status:%d)\n",
- pResponseMsg->ServiceID, pResponseMsg->Status));
- status = A_EPROTO;
- break;
- }
-
- assignedEndpoint = (HTC_ENDPOINT_ID) pResponseMsg->EndpointID;
- maxMsgSize = pResponseMsg->MaxMsgSize;
-
- if ((pConnectResp->pMetaData != NULL) &&
- (pResponseMsg->ServiceMetaLength > 0) &&
- (pResponseMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) {
- /* caller supplied a buffer and the target responded with data */
- int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength);
- /* copy the meta data */
- memcpy(pConnectResp->pMetaData,
- ((u8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG),
- copyLength);
- pConnectResp->ActualLength = copyLength;
- }
-
- }
-
- /* the rest of these are parameter checks so set the error status */
- status = A_EPROTO;
-
- if (assignedEndpoint >= ENDPOINT_MAX) {
- AR_DEBUG_ASSERT(false);
- break;
- }
-
- if (0 == maxMsgSize) {
- AR_DEBUG_ASSERT(false);
- break;
- }
-
- pEndpoint = &target->EndPoint[assignedEndpoint];
- pEndpoint->Id = assignedEndpoint;
- if (pEndpoint->ServiceID != 0) {
- /* endpoint already in use! */
- AR_DEBUG_ASSERT(false);
- break;
- }
-
- /* return assigned endpoint to caller */
- pConnectResp->Endpoint = assignedEndpoint;
- pConnectResp->MaxMsgLength = maxMsgSize;
-
- /* setup the endpoint */
- pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */
- pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth;
- pEndpoint->MaxMsgLength = maxMsgSize;
- /* copy all the callbacks */
- pEndpoint->EpCallBacks = pConnectReq->EpCallbacks;
- /* set the credit distribution info for this endpoint, this information is
- * passed back to the credit distribution callback function */
- pEndpoint->CreditDist.ServiceID = pConnectReq->ServiceID;
- pEndpoint->CreditDist.pHTCReserved = pEndpoint;
- pEndpoint->CreditDist.Endpoint = assignedEndpoint;
- pEndpoint->CreditDist.TxCreditSize = target->TargetCreditSize;
-
- if (pConnectReq->MaxSendMsgSize != 0) {
- /* override TxCreditsPerMaxMsg calculation, this optimizes the credit-low indications
- * since the host will actually issue smaller messages in the Send path */
- if (pConnectReq->MaxSendMsgSize > maxMsgSize) {
- /* can't be larger than the maximum the target can support */
- AR_DEBUG_ASSERT(false);
- break;
- }
- pEndpoint->CreditDist.TxCreditsPerMaxMsg = pConnectReq->MaxSendMsgSize / target->TargetCreditSize;
- } else {
- pEndpoint->CreditDist.TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize;
- }
-
- if (0 == pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
- pEndpoint->CreditDist.TxCreditsPerMaxMsg = 1;
- }
-
- /* save local connection flags */
- pEndpoint->LocalConnectionFlags = pConnectReq->LocalConnectionFlags;
-
- status = 0;
-
- } while (false);
-
- if (pSendPacket != NULL) {
- HTC_FREE_CONTROL_TX(target,pSendPacket);
- }
-
- if (pRecvPacket != NULL) {
- HTC_FREE_CONTROL_RX(target,pRecvPacket);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n"));
-
- return status;
-}
-
-static void AddToEndpointDistList(struct htc_target *target, struct htc_endpoint_credit_dist *pEpDist)
-{
- struct htc_endpoint_credit_dist *pCurEntry,*pLastEntry;
-
- if (NULL == target->EpCreditDistributionListHead) {
- target->EpCreditDistributionListHead = pEpDist;
- pEpDist->pNext = NULL;
- pEpDist->pPrev = NULL;
- return;
- }
-
- /* queue to the end of the list, this does not have to be very
- * fast since this list is built at startup time */
- pCurEntry = target->EpCreditDistributionListHead;
-
- while (pCurEntry) {
- pLastEntry = pCurEntry;
- pCurEntry = pCurEntry->pNext;
- }
-
- pLastEntry->pNext = pEpDist;
- pEpDist->pPrev = pLastEntry;
- pEpDist->pNext = NULL;
-}
-
-
-
-/* default credit init callback */
-static void HTCDefaultCreditInit(void *Context,
- struct htc_endpoint_credit_dist *pEPList,
- int TotalCredits)
-{
- struct htc_endpoint_credit_dist *pCurEpDist;
- int totalEps = 0;
- int creditsPerEndpoint;
-
- pCurEpDist = pEPList;
- /* first run through the list and figure out how many endpoints we are dealing with */
- while (pCurEpDist != NULL) {
- pCurEpDist = pCurEpDist->pNext;
- totalEps++;
- }
-
- /* even distribution */
- creditsPerEndpoint = TotalCredits/totalEps;
-
- pCurEpDist = pEPList;
- /* run through the list and set minimum and normal credits and
- * provide the endpoint with some credits to start */
- while (pCurEpDist != NULL) {
-
- if (creditsPerEndpoint < pCurEpDist->TxCreditsPerMaxMsg) {
- /* too many endpoints and not enough credits */
- AR_DEBUG_ASSERT(false);
- break;
- }
- /* our minimum is set for at least 1 max message */
- pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg;
- /* this value is ignored by our credit alg, since we do
- * not dynamically adjust credits, this is the policy of
- * the "default" credit distribution, something simple and easy */
- pCurEpDist->TxCreditsNorm = 0xFFFF;
- /* give the endpoint minimum credits */
- pCurEpDist->TxCredits = creditsPerEndpoint;
- pCurEpDist->TxCreditsAssigned = creditsPerEndpoint;
- pCurEpDist = pCurEpDist->pNext;
- }
-
-}
-
-/* default credit distribution callback, NOTE, this callback holds the TX lock */
-void HTCDefaultCreditDist(void *Context,
- struct htc_endpoint_credit_dist *pEPDistList,
- HTC_CREDIT_DIST_REASON Reason)
-{
- struct htc_endpoint_credit_dist *pCurEpDist;
-
- if (Reason == HTC_CREDIT_DIST_SEND_COMPLETE) {
- pCurEpDist = pEPDistList;
- /* simple distribution */
- while (pCurEpDist != NULL) {
- if (pCurEpDist->TxCreditsToDist > 0) {
- /* just give the endpoint back the credits */
- pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist;
- pCurEpDist->TxCreditsToDist = 0;
- }
- pCurEpDist = pCurEpDist->pNext;
- }
- }
-
- /* note we do not need to handle the other reason codes as this is a very
- * simple distribution scheme, no need to seek for more credits or handle inactivity */
-}
-
-void HTCSetCreditDistribution(HTC_HANDLE HTCHandle,
- void *pCreditDistContext,
- HTC_CREDIT_DIST_CALLBACK CreditDistFunc,
- HTC_CREDIT_INIT_CALLBACK CreditInitFunc,
- HTC_SERVICE_ID ServicePriorityOrder[],
- int ListLength)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- int i;
- int ep;
-
- if (CreditInitFunc != NULL) {
- /* caller has supplied their own distribution functions */
- target->InitCredits = CreditInitFunc;
- AR_DEBUG_ASSERT(CreditDistFunc != NULL);
- target->DistributeCredits = CreditDistFunc;
- target->pCredDistContext = pCreditDistContext;
- } else {
- /* caller wants HTC to do distribution */
- /* if caller wants service to handle distributions then
- * it must set both of these to NULL! */
- AR_DEBUG_ASSERT(CreditDistFunc == NULL);
- target->InitCredits = HTCDefaultCreditInit;
- target->DistributeCredits = HTCDefaultCreditDist;
- target->pCredDistContext = target;
- }
-
- /* always add HTC control endpoint first, we only expose the list after the
- * first one, this is added for TX queue checking */
- AddToEndpointDistList(target, &target->EndPoint[ENDPOINT_0].CreditDist);
-
- /* build the list of credit distribution structures in priority order
- * supplied by the caller, these will follow endpoint 0 */
- for (i = 0; i < ListLength; i++) {
- /* match services with endpoints and add the endpoints to the distribution list
- * in FIFO order */
- for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) {
- if (target->EndPoint[ep].ServiceID == ServicePriorityOrder[i]) {
- /* queue this one to the list */
- AddToEndpointDistList(target, &target->EndPoint[ep].CreditDist);
- break;
- }
- }
- AR_DEBUG_ASSERT(ep < ENDPOINT_MAX);
- }
-
-}
diff --git a/drivers/staging/ath6kl/include/a_config.h b/drivers/staging/ath6kl/include/a_config.h
deleted file mode 100644
index f7c09319433f..000000000000
--- a/drivers/staging/ath6kl/include/a_config.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="a_config.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains software configuration options that enables
-// specific software "features"
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _A_CONFIG_H_
-#define _A_CONFIG_H_
-
-#include "../os/linux/include/config_linux.h"
-
-#endif
diff --git a/drivers/staging/ath6kl/include/a_debug.h b/drivers/staging/ath6kl/include/a_debug.h
deleted file mode 100644
index 5154fcb1ca64..000000000000
--- a/drivers/staging/ath6kl/include/a_debug.h
+++ /dev/null
@@ -1,195 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="a_debug.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _A_DEBUG_H_
-#define _A_DEBUG_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#include <a_osapi.h>
-
- /* standard debug print masks bits 0..7 */
-#define ATH_DEBUG_ERR (1 << 0) /* errors */
-#define ATH_DEBUG_WARN (1 << 1) /* warnings */
-#define ATH_DEBUG_INFO (1 << 2) /* informational (module startup info) */
-#define ATH_DEBUG_TRC (1 << 3) /* generic function call tracing */
-#define ATH_DEBUG_RSVD1 (1 << 4)
-#define ATH_DEBUG_RSVD2 (1 << 5)
-#define ATH_DEBUG_RSVD3 (1 << 6)
-#define ATH_DEBUG_RSVD4 (1 << 7)
-
-#define ATH_DEBUG_MASK_DEFAULTS (ATH_DEBUG_ERR | ATH_DEBUG_WARN)
-#define ATH_DEBUG_ANY 0xFFFF
-
- /* other aliases used throughout */
-#define ATH_DEBUG_ERROR ATH_DEBUG_ERR
-#define ATH_LOG_ERR ATH_DEBUG_ERR
-#define ATH_LOG_INF ATH_DEBUG_INFO
-#define ATH_LOG_TRC ATH_DEBUG_TRC
-#define ATH_DEBUG_TRACE ATH_DEBUG_TRC
-#define ATH_DEBUG_INIT ATH_DEBUG_INFO
-
- /* bits 8..31 are module-specific masks */
-#define ATH_DEBUG_MODULE_MASK_SHIFT 8
-
- /* macro to make a module-specific masks */
-#define ATH_DEBUG_MAKE_MODULE_MASK(index) (1 << (ATH_DEBUG_MODULE_MASK_SHIFT + (index)))
-
-void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription);
-
-/* Debug support on a per-module basis
- *
- * Usage:
- *
- * Each module can utilize it's own debug mask variable. A set of commonly used
- * masks are provided (ERRORS, WARNINGS, TRACE etc..). It is up to each module
- * to define module-specific masks using the macros above.
- *
- * Each module defines a single debug mask variable debug_XXX where the "name" of the module is
- * common to all C-files within that module. This requires every C-file that includes a_debug.h
- * to define the module name in that file.
- *
- * Example:
- *
- * #define ATH_MODULE_NAME htc
- * #include "a_debug.h"
- *
- * This will define a debug mask structure called debug_htc and all debug macros will reference this
- * variable.
- *
- * A module can define module-specific bit masks using the ATH_DEBUG_MAKE_MODULE_MASK() macro:
- *
- * #define ATH_DEBUG_MY_MASK1 ATH_DEBUG_MAKE_MODULE_MASK(0)
- * #define ATH_DEBUG_MY_MASK2 ATH_DEBUG_MAKE_MODULE_MASK(1)
- *
- * The instantiation of the debug structure should be made by the module. When a module is
- * instantiated, the module can set a description string, a default mask and an array of description
- * entries containing information on each module-defined debug mask.
- * NOTE: The instantiation is statically allocated, only one instance can exist per module.
- *
- * Example:
- *
- *
- * #define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0)
- *
- * #ifdef DEBUG
- * static struct ath_debug_mask_description bmi_debug_desc[] = {
- * { ATH_DEBUG_BMI , "BMI Tracing"}, <== description of the module specific mask
- * };
- *
- * ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi,
- * "bmi" <== module name
- * "Boot Manager Interface", <== description of module
- * ATH_DEBUG_MASK_DEFAULTS, <== defaults
- * ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc),
- * bmi_debug_desc);
- *
- * #endif
- *
- * A module can optionally register it's debug module information in order for other tools to change the
- * bit mask at runtime. A module can call A_REGISTER_MODULE_DEBUG_INFO() in it's module
- * init code. This macro can be called multiple times without consequence. The debug info maintains
- * state to indicate whether the information was previously registered.
- *
- * */
-
-#define ATH_DEBUG_MAX_MASK_DESC_LENGTH 32
-#define ATH_DEBUG_MAX_MOD_DESC_LENGTH 64
-
-struct ath_debug_mask_description {
- u32 Mask;
- char Description[ATH_DEBUG_MAX_MASK_DESC_LENGTH];
-};
-
-#define ATH_DEBUG_INFO_FLAGS_REGISTERED (1 << 0)
-
-typedef struct _ATH_DEBUG_MODULE_DBG_INFO{
- struct _ATH_DEBUG_MODULE_DBG_INFO *pNext;
- char ModuleName[16];
- char ModuleDescription[ATH_DEBUG_MAX_MOD_DESC_LENGTH];
- u32 Flags;
- u32 CurrentMask;
- int MaxDescriptions;
- struct ath_debug_mask_description *pMaskDescriptions; /* pointer to array of descriptions */
-} ATH_DEBUG_MODULE_DBG_INFO;
-
-#define ATH_DEBUG_DESCRIPTION_COUNT(d) (int)((sizeof((d))) / (sizeof(struct ath_debug_mask_description)))
-
-#define GET_ATH_MODULE_DEBUG_VAR_NAME(s) _XGET_ATH_MODULE_NAME_DEBUG_(s)
-#define GET_ATH_MODULE_DEBUG_VAR_MASK(s) _XGET_ATH_MODULE_NAME_DEBUG_(s).CurrentMask
-#define _XGET_ATH_MODULE_NAME_DEBUG_(s) debug_ ## s
-
-#ifdef ATH_DEBUG_MODULE
-
- /* for source files that will instantiate the debug variables */
-#define ATH_DEBUG_INSTANTIATE_MODULE_VAR(s,name,moddesc,initmask,count,descriptions) \
-ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(s) = \
- {NULL,(name),(moddesc),0,(initmask),count,(descriptions)}
-
-#ifdef ATH_MODULE_NAME
-extern ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(ATH_MODULE_NAME);
-#define AR_DEBUG_LVL_CHECK(lvl) (GET_ATH_MODULE_DEBUG_VAR_MASK(ATH_MODULE_NAME) & (lvl))
-#endif /* ATH_MODULE_NAME */
-
-#define ATH_DEBUG_SET_DEBUG_MASK(s,lvl) GET_ATH_MODULE_DEBUG_VAR_MASK(s) = (lvl)
-
-#define ATH_DEBUG_DECLARE_EXTERN(s) \
- extern ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(s)
-
-#define AR_DEBUG_PRINTBUF(buffer, length, desc) DebugDumpBytes(buffer,length,desc)
-
-
-#define AR_DEBUG_ASSERT A_ASSERT
-
-void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo);
-void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo);
-#define A_DUMP_MODULE_DEBUG_INFO(s) a_dump_module_debug_info(&(GET_ATH_MODULE_DEBUG_VAR_NAME(s)))
-#define A_REGISTER_MODULE_DEBUG_INFO(s) a_register_module_debug_info(&(GET_ATH_MODULE_DEBUG_VAR_NAME(s)))
-
-#else /* !ATH_DEBUG_MODULE */
- /* NON ATH_DEBUG_MODULE */
-#define ATH_DEBUG_INSTANTIATE_MODULE_VAR(s,name,moddesc,initmask,count,descriptions)
-#define AR_DEBUG_LVL_CHECK(lvl) 0
-#define AR_DEBUG_PRINTBUF(buffer, length, desc)
-#define AR_DEBUG_ASSERT(test)
-#define ATH_DEBUG_DECLARE_EXTERN(s)
-#define ATH_DEBUG_SET_DEBUG_MASK(s,lvl)
-#define A_DUMP_MODULE_DEBUG_INFO(s)
-#define A_REGISTER_MODULE_DEBUG_INFO(s)
-
-#endif
-
-int a_get_module_mask(char *module_name, u32 *pMask);
-int a_set_module_mask(char *module_name, u32 Mask);
-void a_dump_module_debug_info_by_name(char *module_name);
-void a_module_debug_support_init(void);
-void a_module_debug_support_cleanup(void);
-
-#include "../os/linux/include/debug_linux.h"
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif
diff --git a/drivers/staging/ath6kl/include/a_drv.h b/drivers/staging/ath6kl/include/a_drv.h
deleted file mode 100644
index 1548604e8465..000000000000
--- a/drivers/staging/ath6kl/include/a_drv.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="a_drv.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains the definitions of the basic atheros data types.
-// It is used to map the data types in atheros files to a platform specific
-// type.
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _A_DRV_H_
-#define _A_DRV_H_
-
-#include "../os/linux/include/athdrv_linux.h"
-
-#endif /* _ADRV_H_ */
diff --git a/drivers/staging/ath6kl/include/a_drv_api.h b/drivers/staging/ath6kl/include/a_drv_api.h
deleted file mode 100644
index a40d97a84ffc..000000000000
--- a/drivers/staging/ath6kl/include/a_drv_api.h
+++ /dev/null
@@ -1,204 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="a_drv_api.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _A_DRV_API_H_
-#define _A_DRV_API_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/****************************************************************************/
-/****************************************************************************/
-/** **/
-/** WMI related hooks **/
-/** **/
-/****************************************************************************/
-/****************************************************************************/
-
-#include <ar6000_api.h>
-
-#define A_WMI_CHANNELLIST_RX(devt, numChan, chanList) \
- ar6000_channelList_rx((devt), (numChan), (chanList))
-
-#define A_WMI_SET_NUMDATAENDPTS(devt, num) \
- ar6000_set_numdataendpts((devt), (num))
-
-#define A_WMI_CONTROL_TX(devt, osbuf, streamID) \
- ar6000_control_tx((devt), (osbuf), (streamID))
-
-#define A_WMI_TARGETSTATS_EVENT(devt, pStats, len) \
- ar6000_targetStats_event((devt), (pStats), (len))
-
-#define A_WMI_SCANCOMPLETE_EVENT(devt, status) \
- ar6000_scanComplete_event((devt), (status))
-
-#ifdef CONFIG_HOST_DSET_SUPPORT
-
-#define A_WMI_DSET_DATA_REQ(devt, access_cookie, offset, length, targ_buf, targ_reply_fn, targ_reply_arg) \
- ar6000_dset_data_req((devt), (access_cookie), (offset), (length), (targ_buf), (targ_reply_fn), (targ_reply_arg))
-
-#define A_WMI_DSET_CLOSE(devt, access_cookie) \
- ar6000_dset_close((devt), (access_cookie))
-
-#endif
-
-#define A_WMI_DSET_OPEN_REQ(devt, id, targ_handle, targ_reply_fn, targ_reply_arg) \
- ar6000_dset_open_req((devt), (id), (targ_handle), (targ_reply_fn), (targ_reply_arg))
-
-#define A_WMI_CONNECT_EVENT(devt, channel, bssid, listenInterval, beaconInterval, networkType, beaconIeLen, assocReqLen, assocRespLen, assocInfo) \
- ar6000_connect_event((devt), (channel), (bssid), (listenInterval), (beaconInterval), (networkType), (beaconIeLen), (assocReqLen), (assocRespLen), (assocInfo))
-
-#define A_WMI_PSPOLL_EVENT(devt, aid)\
- ar6000_pspoll_event((devt),(aid))
-
-#define A_WMI_DTIMEXPIRY_EVENT(devt)\
- ar6000_dtimexpiry_event((devt))
-
-#ifdef WAPI_ENABLE
-#define A_WMI_WAPI_REKEY_EVENT(devt, type, mac)\
- ap_wapi_rekey_event((devt),(type),(mac))
-#endif
-
-#define A_WMI_REGDOMAIN_EVENT(devt, regCode) \
- ar6000_regDomain_event((devt), (regCode))
-
-#define A_WMI_NEIGHBORREPORT_EVENT(devt, numAps, info) \
- ar6000_neighborReport_event((devt), (numAps), (info))
-
-#define A_WMI_DISCONNECT_EVENT(devt, reason, bssid, assocRespLen, assocInfo, protocolReasonStatus) \
- ar6000_disconnect_event((devt), (reason), (bssid), (assocRespLen), (assocInfo), (protocolReasonStatus))
-
-#define A_WMI_TKIP_MICERR_EVENT(devt, keyid, ismcast) \
- ar6000_tkip_micerr_event((devt), (keyid), (ismcast))
-
-#define A_WMI_BITRATE_RX(devt, rateKbps) \
- ar6000_bitrate_rx((devt), (rateKbps))
-
-#define A_WMI_TXPWR_RX(devt, txPwr) \
- ar6000_txPwr_rx((devt), (txPwr))
-
-#define A_WMI_READY_EVENT(devt, datap, phyCap, sw_ver, abi_ver) \
- ar6000_ready_event((devt), (datap), (phyCap), (sw_ver), (abi_ver))
-
-#define A_WMI_DBGLOG_INIT_DONE(ar) \
- ar6000_dbglog_init_done(ar);
-
-#define A_WMI_RSSI_THRESHOLD_EVENT(devt, newThreshold, rssi) \
- ar6000_rssiThreshold_event((devt), (newThreshold), (rssi))
-
-#define A_WMI_REPORT_ERROR_EVENT(devt, errorVal) \
- ar6000_reportError_event((devt), (errorVal))
-
-#define A_WMI_ROAM_TABLE_EVENT(devt, pTbl) \
- ar6000_roam_tbl_event((devt), (pTbl))
-
-#define A_WMI_ROAM_DATA_EVENT(devt, p) \
- ar6000_roam_data_event((devt), (p))
-
-#define A_WMI_WOW_LIST_EVENT(devt, num_filters, wow_filters) \
- ar6000_wow_list_event((devt), (num_filters), (wow_filters))
-
-#define A_WMI_CAC_EVENT(devt, ac, cac_indication, statusCode, tspecSuggestion) \
- ar6000_cac_event((devt), (ac), (cac_indication), (statusCode), (tspecSuggestion))
-
-#define A_WMI_CHANNEL_CHANGE_EVENT(devt, oldChannel, newChannel) \
- ar6000_channel_change_event((devt), (oldChannel), (newChannel))
-
-#define A_WMI_PMKID_LIST_EVENT(devt, num_pmkid, pmkid_list, bssid_list) \
- ar6000_pmkid_list_event((devt), (num_pmkid), (pmkid_list), (bssid_list))
-
-#define A_WMI_PEER_EVENT(devt, eventCode, bssid) \
- ar6000_peer_event ((devt), (eventCode), (bssid))
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-#define A_WMI_TCMD_RX_REPORT_EVENT(devt, results, len) \
- ar6000_tcmd_rx_report_event((devt), (results), (len))
-#endif
-
-#define A_WMI_HBCHALLENGERESP_EVENT(devt, cookie, source) \
- ar6000_hbChallengeResp_event((devt), (cookie), (source))
-
-#define A_WMI_TX_RETRY_ERR_EVENT(devt) \
- ar6000_tx_retry_err_event((devt))
-
-#define A_WMI_SNR_THRESHOLD_EVENT_RX(devt, newThreshold, snr) \
- ar6000_snrThresholdEvent_rx((devt), (newThreshold), (snr))
-
-#define A_WMI_LQ_THRESHOLD_EVENT_RX(devt, range, lqVal) \
- ar6000_lqThresholdEvent_rx((devt), (range), (lqVal))
-
-#define A_WMI_RATEMASK_RX(devt, ratemask) \
- ar6000_ratemask_rx((devt), (ratemask))
-
-#define A_WMI_KEEPALIVE_RX(devt, configured) \
- ar6000_keepalive_rx((devt), (configured))
-
-#define A_WMI_BSSINFO_EVENT_RX(ar, datp, len) \
- ar6000_bssInfo_event_rx((ar), (datap), (len))
-
-#define A_WMI_DBGLOG_EVENT(ar, dropped, buffer, length) \
- ar6000_dbglog_event((ar), (dropped), (buffer), (length));
-
-#define A_WMI_STREAM_TX_ACTIVE(devt,trafficClass) \
- ar6000_indicate_tx_activity((devt),(trafficClass), true)
-
-#define A_WMI_STREAM_TX_INACTIVE(devt,trafficClass) \
- ar6000_indicate_tx_activity((devt),(trafficClass), false)
-#define A_WMI_Ac2EndpointID(devht, ac)\
- ar6000_ac2_endpoint_id((devht), (ac))
-
-#define A_WMI_AGGR_RECV_ADDBA_REQ_EVT(devt, cmd)\
- ar6000_aggr_rcv_addba_req_evt((devt), (cmd))
-#define A_WMI_AGGR_RECV_ADDBA_RESP_EVT(devt, cmd)\
- ar6000_aggr_rcv_addba_resp_evt((devt), (cmd))
-#define A_WMI_AGGR_RECV_DELBA_REQ_EVT(devt, cmd)\
- ar6000_aggr_rcv_delba_req_evt((devt), (cmd))
-#define A_WMI_HCI_EVENT_EVT(devt, cmd)\
- ar6000_hci_event_rcv_evt((devt), (cmd))
-
-#define A_WMI_Endpoint2Ac(devt, ep) \
- ar6000_endpoint_id2_ac((devt), (ep))
-
-#define A_WMI_BTCOEX_CONFIG_EVENT(devt, evt, len)\
- ar6000_btcoex_config_event((devt), (evt), (len))
-
-#define A_WMI_BTCOEX_STATS_EVENT(devt, datap, len)\
- ar6000_btcoex_stats_event((devt), (datap), (len))
-
-/****************************************************************************/
-/****************************************************************************/
-/** **/
-/** HTC related hooks **/
-/** **/
-/****************************************************************************/
-/****************************************************************************/
-
-#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-#define A_WMI_PROF_COUNT_RX(addr, count) prof_count_rx((addr), (count))
-#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/drivers/staging/ath6kl/include/a_osapi.h b/drivers/staging/ath6kl/include/a_osapi.h
deleted file mode 100644
index fd7ae0d612c6..000000000000
--- a/drivers/staging/ath6kl/include/a_osapi.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="a_osapi.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains the definitions of the basic atheros data types.
-// It is used to map the data types in atheros files to a platform specific
-// type.
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _A_OSAPI_H_
-#define _A_OSAPI_H_
-
-#include "../os/linux/include/osapi_linux.h"
-
-#endif /* _OSAPI_H_ */
diff --git a/drivers/staging/ath6kl/include/aggr_recv_api.h b/drivers/staging/ath6kl/include/aggr_recv_api.h
deleted file mode 100644
index 5ead58d5febd..000000000000
--- a/drivers/staging/ath6kl/include/aggr_recv_api.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- *
- * Copyright (c) 2004-2010 Atheros Communications Inc.
- * All rights reserved.
- *
- *
-//
-// 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 __AGGR_RECV_API_H__
-#define __AGGR_RECV_API_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (* RX_CALLBACK)(void * dev, void *osbuf);
-
-typedef void (* ALLOC_NETBUFS)(A_NETBUF_QUEUE_T *q, u16 num);
-
-/*
- * aggr_init:
- * Initialises the data structures, allocates data queues and
- * os buffers. Netbuf allocator is the input param, used by the
- * aggr module for allocation of NETBUFs from driver context.
- * These NETBUFs are used for AMSDU processing.
- * Returns the context for the aggr module.
- */
-void *
-aggr_init(ALLOC_NETBUFS netbuf_allocator);
-
-
-/*
- * aggr_register_rx_dispatcher:
- * Registers OS call back function to deliver the
- * frames to OS. This is generally the topmost layer of
- * the driver context, after which the frames go to
- * IP stack via the call back function.
- * This dispatcher is active only when aggregation is ON.
- */
-void
-aggr_register_rx_dispatcher(void *cntxt, void * dev, RX_CALLBACK fn);
-
-
-/*
- * aggr_process_bar:
- * When target receives BAR, it communicates to host driver
- * for modifying window parameters. Target indicates this via the
- * event: WMI_ADDBA_REQ_EVENTID. Host will dequeue all frames
- * up to the indicated sequence number.
- */
-void
-aggr_process_bar(void *cntxt, u8 tid, u16 seq_no);
-
-
-/*
- * aggr_recv_addba_req_evt:
- * This event is to initiate/modify the receive side window.
- * Target will send WMI_ADDBA_REQ_EVENTID event to host - to setup
- * recv re-ordering queues. Target will negotiate ADDBA with peer,
- * and indicate via this event after successfully completing the
- * negotiation. This happens in two situations:
- * 1. Initial setup of aggregation
- * 2. Renegotiation of current recv window.
- * Window size for re-ordering is limited by target buffer
- * space, which is reflected in win_sz.
- * (Re)Start the periodic timer to deliver long standing frames,
- * in hold_q to OS.
- */
-void
-aggr_recv_addba_req_evt(void * cntxt, u8 tid, u16 seq_no, u8 win_sz);
-
-
-/*
- * aggr_recv_delba_req_evt:
- * Target indicates deletion of a BA window for a tid via the
- * WMI_DELBA_EVENTID. Host would deliver all the frames in the
- * hold_q, reset tid config and disable the periodic timer, if
- * aggr is not enabled on any tid.
- */
-void
-aggr_recv_delba_req_evt(void * cntxt, u8 tid);
-
-
-
-/*
- * aggr_process_recv_frm:
- * Called only for data frames. When aggr is ON for a tid, the buffer
- * is always consumed, and osbuf would be NULL. For a non-aggr case,
- * osbuf is not modified.
- * AMSDU frames are consumed and are later freed. They are sliced and
- * diced to individual frames and dispatched to stack.
- * After consuming a osbuf(when aggr is ON), a previously registered
- * callback may be called to deliver frames in order.
- */
-void
-aggr_process_recv_frm(void *cntxt, u8 tid, u16 seq_no, bool is_amsdu, void **osbuf);
-
-
-/*
- * aggr_module_destroy:
- * Frees up all the queues and frames in them. Releases the cntxt to OS.
- */
-void
-aggr_module_destroy(void *cntxt);
-
-/*
- * Dumps the aggregation stats
- */
-void
-aggr_dump_stats(void *cntxt, PACKET_LOG **log_buf);
-
-/*
- * aggr_reset_state -- Called when it is deemed necessary to clear the aggregate
- * hold Q state. Examples include when a Connect event or disconnect event is
- * received.
- */
-void
-aggr_reset_state(void *cntxt);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*__AGGR_RECV_API_H__ */
diff --git a/drivers/staging/ath6kl/include/ar3kconfig.h b/drivers/staging/ath6kl/include/ar3kconfig.h
deleted file mode 100644
index 91bc4ee3512d..000000000000
--- a/drivers/staging/ath6kl/include/ar3kconfig.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-/* AR3K module configuration APIs for HCI-bridge operation */
-
-#ifndef AR3KCONFIG_H_
-#define AR3KCONFIG_H_
-
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT (1 << 0)
-#define AR3K_CONFIG_FLAG_SET_AR3K_BAUD (1 << 1)
-#define AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY (1 << 2)
-#define AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP (1 << 3)
-
-
-struct ar3k_config_info {
- u32 Flags; /* config flags */
- void *pHCIDev; /* HCI bridge device */
- struct hci_transport_properties *pHCIProps; /* HCI bridge props */
- struct hif_device *pHIFDevice; /* HIF layer device */
-
- u32 AR3KBaudRate; /* AR3K operational baud rate */
- u16 AR6KScale; /* AR6K UART scale value */
- u16 AR6KStep; /* AR6K UART step value */
- struct hci_dev *pBtStackHCIDev; /* BT Stack HCI dev */
- u32 PwrMgmtEnabled; /* TLPM enabled? */
- u16 IdleTimeout; /* TLPM idle timeout */
- u16 WakeupTimeout; /* TLPM wakeup timeout */
- u8 bdaddr[6]; /* Bluetooth device address */
-};
-
-int AR3KConfigure(struct ar3k_config_info *pConfigInfo);
-
-int AR3KConfigureExit(void *config);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*AR3KCONFIG_H_*/
diff --git a/drivers/staging/ath6kl/include/ar6000_api.h b/drivers/staging/ath6kl/include/ar6000_api.h
deleted file mode 100644
index e9460800272c..000000000000
--- a/drivers/staging/ath6kl/include/ar6000_api.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="ar6000_api.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains the API to access the OS dependent atheros host driver
-// by the WMI or WLAN generic modules.
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _AR6000_API_H_
-#define _AR6000_API_H_
-
-#include "../os/linux/include/ar6xapi_linux.h"
-
-#endif /* _AR6000_API_H */
-
diff --git a/drivers/staging/ath6kl/include/ar6000_diag.h b/drivers/staging/ath6kl/include/ar6000_diag.h
deleted file mode 100644
index 739c01c53f08..000000000000
--- a/drivers/staging/ath6kl/include/ar6000_diag.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="ar6000_diag.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef AR6000_DIAG_H_
-#define AR6000_DIAG_H_
-
-
-int
-ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
-
-int
-ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
-
-int
-ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address,
- u8 *data, u32 length);
-
-int
-ar6000_WriteDataDiag(struct hif_device *hifDevice, u32 address,
- u8 *data, u32 length);
-
-int
-ar6k_ReadTargetRegister(struct hif_device *hifDevice, int regsel, u32 *regval);
-
-void
-ar6k_FetchTargetRegs(struct hif_device *hifDevice, u32 *targregs);
-
-#endif /*AR6000_DIAG_H_*/
diff --git a/drivers/staging/ath6kl/include/ar6kap_common.h b/drivers/staging/ath6kl/include/ar6kap_common.h
deleted file mode 100644
index 532d8eba9326..000000000000
--- a/drivers/staging/ath6kl/include/ar6kap_common.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//------------------------------------------------------------------------------
-
-// <copyright file="ar6kap_common.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains the definitions of common AP mode data structures.
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef _AR6KAP_COMMON_H_
-#define _AR6KAP_COMMON_H_
-/*
- * Used with AR6000_XIOCTL_AP_GET_STA_LIST
- */
-typedef struct {
- u8 mac[ATH_MAC_LEN];
- u8 aid;
- u8 keymgmt;
- u8 ucipher;
- u8 auth;
-} station_t;
-typedef struct {
- station_t sta[AP_MAX_NUM_STA];
-} ap_get_sta_t;
-#endif /* _AR6KAP_COMMON_H_ */
diff --git a/drivers/staging/ath6kl/include/athbtfilter.h b/drivers/staging/ath6kl/include/athbtfilter.h
deleted file mode 100644
index 81456eea3b0b..000000000000
--- a/drivers/staging/ath6kl/include/athbtfilter.h
+++ /dev/null
@@ -1,135 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="athbtfilter.h" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Public Bluetooth filter APIs
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef ATHBTFILTER_H_
-#define ATHBTFILTER_H_
-
-#define ATH_DEBUG_INFO (1 << 2)
-#define ATH_DEBUG_INF ATH_DEBUG_INFO
-
-typedef enum _ATHBT_HCI_CTRL_TYPE {
- ATHBT_HCI_COMMAND = 0,
- ATHBT_HCI_EVENT = 1,
-} ATHBT_HCI_CTRL_TYPE;
-
-typedef enum _ATHBT_STATE_INDICATION {
- ATH_BT_NOOP = 0,
- ATH_BT_INQUIRY = 1,
- ATH_BT_CONNECT = 2,
- ATH_BT_SCO = 3,
- ATH_BT_ACL = 4,
- ATH_BT_A2DP = 5,
- ATH_BT_ESCO = 6,
- /* new states go here.. */
-
- ATH_BT_MAX_STATE_INDICATION
-} ATHBT_STATE_INDICATION;
-
- /* filter function for OUTGOING commands and INCOMMING events */
-typedef void (*ATHBT_FILTER_CMD_EVENTS_FN)(void *pContext, ATHBT_HCI_CTRL_TYPE Type, unsigned char *pBuffer, int Length);
-
- /* filter function for OUTGOING data HCI packets */
-typedef void (*ATHBT_FILTER_DATA_FN)(void *pContext, unsigned char *pBuffer, int Length);
-
-typedef enum _ATHBT_STATE {
- STATE_OFF = 0,
- STATE_ON = 1,
- STATE_MAX
-} ATHBT_STATE;
-
- /* BT state indication (when filter functions are not used) */
-
-typedef void (*ATHBT_INDICATE_STATE_FN)(void *pContext, ATHBT_STATE_INDICATION Indication, ATHBT_STATE State, unsigned char LMPVersion);
-
-struct athbt_filter_instance {
-#ifdef UNDER_CE
- WCHAR *pWlanAdapterName; /* filled in by user */
-#else
- char *pWlanAdapterName; /* filled in by user */
-#endif /* UNDER_CE */
- int FilterEnabled; /* filtering is enabled */
- int Attached; /* filter library is attached */
- void *pContext; /* private context for filter library */
- ATHBT_FILTER_CMD_EVENTS_FN pFilterCmdEvents; /* function ptr to filter a command or event */
- ATHBT_FILTER_DATA_FN pFilterAclDataOut; /* function ptr to filter ACL data out (to radio) */
- ATHBT_FILTER_DATA_FN pFilterAclDataIn; /* function ptr to filter ACL data in (from radio) */
- ATHBT_INDICATE_STATE_FN pIndicateState; /* function ptr to indicate a state */
-}; /* XXX: unused ? */
-
-
-/* API MACROS */
-
-#define AthBtFilterHciCommand(instance,packet,length) \
- if ((instance)->FilterEnabled) { \
- (instance)->pFilterCmdEvents((instance)->pContext, \
- ATHBT_HCI_COMMAND, \
- (unsigned char *)(packet), \
- (length)); \
- }
-
-#define AthBtFilterHciEvent(instance,packet,length) \
- if ((instance)->FilterEnabled) { \
- (instance)->pFilterCmdEvents((instance)->pContext, \
- ATHBT_HCI_EVENT, \
- (unsigned char *)(packet), \
- (length)); \
- }
-
-#define AthBtFilterHciAclDataOut(instance,packet,length) \
- if ((instance)->FilterEnabled) { \
- (instance)->pFilterAclDataOut((instance)->pContext, \
- (unsigned char *)(packet), \
- (length)); \
- }
-
-#define AthBtFilterHciAclDataIn(instance,packet,length) \
- if ((instance)->FilterEnabled) { \
- (instance)->pFilterAclDataIn((instance)->pContext, \
- (unsigned char *)(packet), \
- (length)); \
- }
-
-/* if filtering is not desired, the application can indicate the state directly using this
- * macro:
- */
-#define AthBtIndicateState(instance,indication,state) \
- if ((instance)->FilterEnabled) { \
- (instance)->pIndicateState((instance)->pContext, \
- (indication), \
- (state), \
- 0); \
- }
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* API prototypes */
-int AthBtFilter_Attach(ATH_BT_FILTER_INSTANCE *pInstance, unsigned int flags);
-void AthBtFilter_Detach(ATH_BT_FILTER_INSTANCE *pInstance);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*ATHBTFILTER_H_*/
diff --git a/drivers/staging/ath6kl/include/bmi.h b/drivers/staging/ath6kl/include/bmi.h
deleted file mode 100644
index d3227f77fa5d..000000000000
--- a/drivers/staging/ath6kl/include/bmi.h
+++ /dev/null
@@ -1,134 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="bmi.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// BMI declarations and prototypes
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _BMI_H_
-#define _BMI_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Header files */
-#include "a_config.h"
-#include "athdefs.h"
-#include "hif.h"
-#include "a_osapi.h"
-#include "bmi_msg.h"
-
-void
-BMIInit(void);
-
-void
-BMICleanup(void);
-
-int
-BMIDone(struct hif_device *device);
-
-int
-BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info);
-
-int
-BMIReadMemory(struct hif_device *device,
- u32 address,
- u8 *buffer,
- u32 length);
-
-int
-BMIWriteMemory(struct hif_device *device,
- u32 address,
- u8 *buffer,
- u32 length);
-
-int
-BMIExecute(struct hif_device *device,
- u32 address,
- u32 *param);
-
-int
-BMISetAppStart(struct hif_device *device,
- u32 address);
-
-int
-BMIReadSOCRegister(struct hif_device *device,
- u32 address,
- u32 *param);
-
-int
-BMIWriteSOCRegister(struct hif_device *device,
- u32 address,
- u32 param);
-
-int
-BMIrompatchInstall(struct hif_device *device,
- u32 ROM_addr,
- u32 RAM_addr,
- u32 nbytes,
- u32 do_activate,
- u32 *patch_id);
-
-int
-BMIrompatchUninstall(struct hif_device *device,
- u32 rompatch_id);
-
-int
-BMIrompatchActivate(struct hif_device *device,
- u32 rompatch_count,
- u32 *rompatch_list);
-
-int
-BMIrompatchDeactivate(struct hif_device *device,
- u32 rompatch_count,
- u32 *rompatch_list);
-
-int
-BMILZStreamStart(struct hif_device *device,
- u32 address);
-
-int
-BMILZData(struct hif_device *device,
- u8 *buffer,
- u32 length);
-
-int
-BMIFastDownload(struct hif_device *device,
- u32 address,
- u8 *buffer,
- u32 length);
-
-int
-BMIRawWrite(struct hif_device *device,
- u8 *buffer,
- u32 length);
-
-int
-BMIRawRead(struct hif_device *device,
- u8 *buffer,
- u32 length,
- bool want_timeout);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _BMI_H_ */
diff --git a/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h b/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h
deleted file mode 100644
index 5407e05d9b05..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="AR6K_version.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#define __VER_MAJOR_ 3
-#define __VER_MINOR_ 0
-#define __VER_PATCH_ 0
-
-/* The makear6ksdk script (used for release builds) modifies the following line. */
-#define __BUILD_NUMBER_ 233
-
-
-/* Format of the version number. */
-#define VER_MAJOR_BIT_OFFSET 28
-#define VER_MINOR_BIT_OFFSET 24
-#define VER_PATCH_BIT_OFFSET 16
-#define VER_BUILD_NUM_BIT_OFFSET 0
-
-
-/*
- * The version has the following format:
- * Bits 28-31: Major version
- * Bits 24-27: Minor version
- * Bits 16-23: Patch version
- * Bits 0-15: Build number (automatically generated during build process )
- * E.g. Build 1.1.3.7 would be represented as 0x11030007.
- *
- * DO NOT split the following macro into multiple lines as this may confuse the build scripts.
- */
-#define AR6K_SW_VERSION ( ( __VER_MAJOR_ << VER_MAJOR_BIT_OFFSET ) + ( __VER_MINOR_ << VER_MINOR_BIT_OFFSET ) + ( __VER_PATCH_ << VER_PATCH_BIT_OFFSET ) + ( __BUILD_NUMBER_ << VER_BUILD_NUM_BIT_OFFSET ) )
-
-/* ABI Version. Reflects the version of binary interface exposed by AR6K target firmware. Needs to be incremented by 1 for any change in the firmware that requires upgrade of the driver on the host side for the change to work correctly */
-#define AR6K_ABI_VERSION 1
diff --git a/drivers/staging/ath6kl/include/common/AR6002/addrs.h b/drivers/staging/ath6kl/include/common/AR6002/addrs.h
deleted file mode 100644
index bbf8d42828c1..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/addrs.h
+++ /dev/null
@@ -1,90 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef __ADDRS_H__
-#define __ADDRS_H__
-
-/*
- * Special AR6002 Addresses that may be needed by special
- * applications (e.g. ART) on the Host as well as Target.
- */
-
-#if defined(AR6002_REV2)
-#define AR6K_RAM_START 0x00500000
-#define TARG_RAM_OFFSET(vaddr) ((u32)(vaddr) & 0xfffff)
-#define TARG_RAM_SZ (184*1024)
-#define TARG_ROM_SZ (80*1024)
-#endif
-#if defined(AR6002_REV4) || defined(AR6003)
-#define AR6K_RAM_START 0x00540000
-#define TARG_RAM_OFFSET(vaddr) (((u32)(vaddr) & 0xfffff) - 0x40000)
-#define TARG_RAM_SZ (256*1024)
-#define TARG_ROM_SZ (256*1024)
-#endif
-
-#define AR6002_BOARD_DATA_SZ 768
-#define AR6002_BOARD_EXT_DATA_SZ 0
-#define AR6003_BOARD_DATA_SZ 1024
-#define AR6003_BOARD_EXT_DATA_SZ 768
-
-#define AR6K_RAM_ADDR(byte_offset) (AR6K_RAM_START+(byte_offset))
-#define TARG_RAM_ADDRS(byte_offset) AR6K_RAM_ADDR(byte_offset)
-
-#define AR6K_ROM_START 0x004e0000
-#define TARG_ROM_OFFSET(vaddr) (((u32)(vaddr) & 0x1fffff) - 0xe0000)
-#define AR6K_ROM_ADDR(byte_offset) (AR6K_ROM_START+(byte_offset))
-#define TARG_ROM_ADDRS(byte_offset) AR6K_ROM_ADDR(byte_offset)
-
-/*
- * At this ROM address is a pointer to the start of the ROM DataSet Index.
- * If there are no ROM DataSets, there's a 0 at this address.
- */
-#define ROM_DATASET_INDEX_ADDR (TARG_ROM_ADDRS(TARG_ROM_SZ)-8)
-#define ROM_MBIST_CKSUM_ADDR (TARG_ROM_ADDRS(TARG_ROM_SZ)-4)
-
-/*
- * The API A_BOARD_DATA_ADDR() is the proper way to get a read pointer to
- * board data.
- */
-
-/* Size of Board Data, in bytes */
-#if defined(AR6002_REV4) || defined(AR6003)
-#define BOARD_DATA_SZ AR6003_BOARD_DATA_SZ
-#else
-#define BOARD_DATA_SZ AR6002_BOARD_DATA_SZ
-#endif
-
-
-/*
- * Constants used by ASM code to access fields of host_interest_s,
- * which is at a fixed location in RAM.
- */
-#if defined(AR6002_REV4) || defined(AR6003)
-#define HOST_INTEREST_FLASH_IS_PRESENT_ADDR (AR6K_RAM_START + 0x60c)
-#else
-#define HOST_INTEREST_FLASH_IS_PRESENT_ADDR (AR6K_RAM_START + 0x40c)
-#endif
-#define FLASH_IS_PRESENT_TARGADDR HOST_INTEREST_FLASH_IS_PRESENT_ADDR
-
-#endif /* __ADDRS_H__ */
-
-
-
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h b/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h
deleted file mode 100644
index 609eb9841f59..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// ------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-// ------------------------------------------------------------------
-//===================================================================
-// Author(s): ="Atheros"
-//===================================================================
-
-
-#ifndef _APB_ATHR_WLAN_MAP_H_
-#define _APB_ATHR_WLAN_MAP_H_
-
-#define WLAN_RTC_BASE_ADDRESS 0x00004000
-#define WLAN_VMC_BASE_ADDRESS 0x00008000
-#define WLAN_UART_BASE_ADDRESS 0x0000c000
-#define WLAN_DBG_UART_BASE_ADDRESS 0x0000d000
-#define WLAN_UMBOX_BASE_ADDRESS 0x0000e000
-#define WLAN_SI_BASE_ADDRESS 0x00010000
-#define WLAN_GPIO_BASE_ADDRESS 0x00014000
-#define WLAN_MBOX_BASE_ADDRESS 0x00018000
-#define WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000
-#define WLAN_MAC_BASE_ADDRESS 0x00020000
-#define WLAN_RDMA_BASE_ADDRESS 0x00030100
-#define EFUSE_BASE_ADDRESS 0x00031000
-
-#endif /* _APB_ATHR_WLAN_MAP_REG_H_ */
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h b/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h
deleted file mode 100644
index 0068ca31b051..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// ------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-// ------------------------------------------------------------------
-//===================================================================
-// Author(s): ="Atheros"
-//===================================================================
-
-
-#include "apb_athr_wlan_map.h"
-
-#ifndef BT_HEADERS
-
-#define RTC_BASE_ADDRESS WLAN_RTC_BASE_ADDRESS
-#define VMC_BASE_ADDRESS WLAN_VMC_BASE_ADDRESS
-#define UART_BASE_ADDRESS WLAN_UART_BASE_ADDRESS
-#define DBG_UART_BASE_ADDRESS WLAN_DBG_UART_BASE_ADDRESS
-#define UMBOX_BASE_ADDRESS WLAN_UMBOX_BASE_ADDRESS
-#define SI_BASE_ADDRESS WLAN_SI_BASE_ADDRESS
-#define GPIO_BASE_ADDRESS WLAN_GPIO_BASE_ADDRESS
-#define MBOX_BASE_ADDRESS WLAN_MBOX_BASE_ADDRESS
-#define ANALOG_INTF_BASE_ADDRESS WLAN_ANALOG_INTF_BASE_ADDRESS
-#define MAC_BASE_ADDRESS WLAN_MAC_BASE_ADDRESS
-#define RDMA_BASE_ADDRESS WLAN_RDMA_BASE_ADDRESS
-
-#endif
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h b/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h
deleted file mode 100644
index 109f24e10a65..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// ------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-// ------------------------------------------------------------------
-//===================================================================
-// Author(s): ="Atheros"
-//===================================================================
-
-
-#include "mbox_wlan_host_reg.h"
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h b/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h
deleted file mode 100644
index 72fa483450d6..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h
+++ /dev/null
@@ -1,552 +0,0 @@
-// ------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-// ------------------------------------------------------------------
-//===================================================================
-// Author(s): ="Atheros"
-//===================================================================
-
-
-#include "mbox_wlan_reg.h"
-
-#ifndef BT_HEADERS
-
-#define MBOX_FIFO_ADDRESS WLAN_MBOX_FIFO_ADDRESS
-#define MBOX_FIFO_OFFSET WLAN_MBOX_FIFO_OFFSET
-#define MBOX_FIFO_DATA_MSB WLAN_MBOX_FIFO_DATA_MSB
-#define MBOX_FIFO_DATA_LSB WLAN_MBOX_FIFO_DATA_LSB
-#define MBOX_FIFO_DATA_MASK WLAN_MBOX_FIFO_DATA_MASK
-#define MBOX_FIFO_DATA_GET(x) WLAN_MBOX_FIFO_DATA_GET(x)
-#define MBOX_FIFO_DATA_SET(x) WLAN_MBOX_FIFO_DATA_SET(x)
-#define MBOX_FIFO_STATUS_ADDRESS WLAN_MBOX_FIFO_STATUS_ADDRESS
-#define MBOX_FIFO_STATUS_OFFSET WLAN_MBOX_FIFO_STATUS_OFFSET
-#define MBOX_FIFO_STATUS_EMPTY_MSB WLAN_MBOX_FIFO_STATUS_EMPTY_MSB
-#define MBOX_FIFO_STATUS_EMPTY_LSB WLAN_MBOX_FIFO_STATUS_EMPTY_LSB
-#define MBOX_FIFO_STATUS_EMPTY_MASK WLAN_MBOX_FIFO_STATUS_EMPTY_MASK
-#define MBOX_FIFO_STATUS_EMPTY_GET(x) WLAN_MBOX_FIFO_STATUS_EMPTY_GET(x)
-#define MBOX_FIFO_STATUS_EMPTY_SET(x) WLAN_MBOX_FIFO_STATUS_EMPTY_SET(x)
-#define MBOX_FIFO_STATUS_FULL_MSB WLAN_MBOX_FIFO_STATUS_FULL_MSB
-#define MBOX_FIFO_STATUS_FULL_LSB WLAN_MBOX_FIFO_STATUS_FULL_LSB
-#define MBOX_FIFO_STATUS_FULL_MASK WLAN_MBOX_FIFO_STATUS_FULL_MASK
-#define MBOX_FIFO_STATUS_FULL_GET(x) WLAN_MBOX_FIFO_STATUS_FULL_GET(x)
-#define MBOX_FIFO_STATUS_FULL_SET(x) WLAN_MBOX_FIFO_STATUS_FULL_SET(x)
-#define MBOX_DMA_POLICY_ADDRESS WLAN_MBOX_DMA_POLICY_ADDRESS
-#define MBOX_DMA_POLICY_OFFSET WLAN_MBOX_DMA_POLICY_OFFSET
-#define MBOX_DMA_POLICY_TX_QUANTUM_MSB WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MSB
-#define MBOX_DMA_POLICY_TX_QUANTUM_LSB WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB
-#define MBOX_DMA_POLICY_TX_QUANTUM_MASK WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK
-#define MBOX_DMA_POLICY_TX_QUANTUM_GET(x) WLAN_MBOX_DMA_POLICY_TX_QUANTUM_GET(x)
-#define MBOX_DMA_POLICY_TX_QUANTUM_SET(x) WLAN_MBOX_DMA_POLICY_TX_QUANTUM_SET(x)
-#define MBOX_DMA_POLICY_TX_ORDER_MSB WLAN_MBOX_DMA_POLICY_TX_ORDER_MSB
-#define MBOX_DMA_POLICY_TX_ORDER_LSB WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB
-#define MBOX_DMA_POLICY_TX_ORDER_MASK WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK
-#define MBOX_DMA_POLICY_TX_ORDER_GET(x) WLAN_MBOX_DMA_POLICY_TX_ORDER_GET(x)
-#define MBOX_DMA_POLICY_TX_ORDER_SET(x) WLAN_MBOX_DMA_POLICY_TX_ORDER_SET(x)
-#define MBOX_DMA_POLICY_RX_QUANTUM_MSB WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MSB
-#define MBOX_DMA_POLICY_RX_QUANTUM_LSB WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB
-#define MBOX_DMA_POLICY_RX_QUANTUM_MASK WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK
-#define MBOX_DMA_POLICY_RX_QUANTUM_GET(x) WLAN_MBOX_DMA_POLICY_RX_QUANTUM_GET(x)
-#define MBOX_DMA_POLICY_RX_QUANTUM_SET(x) WLAN_MBOX_DMA_POLICY_RX_QUANTUM_SET(x)
-#define MBOX_DMA_POLICY_RX_ORDER_MSB WLAN_MBOX_DMA_POLICY_RX_ORDER_MSB
-#define MBOX_DMA_POLICY_RX_ORDER_LSB WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB
-#define MBOX_DMA_POLICY_RX_ORDER_MASK WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK
-#define MBOX_DMA_POLICY_RX_ORDER_GET(x) WLAN_MBOX_DMA_POLICY_RX_ORDER_GET(x)
-#define MBOX_DMA_POLICY_RX_ORDER_SET(x) WLAN_MBOX_DMA_POLICY_RX_ORDER_SET(x)
-#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS
-#define MBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET
-#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB
-#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB
-#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK
-#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x)
-#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x)
-#define MBOX0_DMA_RX_CONTROL_ADDRESS WLAN_MBOX0_DMA_RX_CONTROL_ADDRESS
-#define MBOX0_DMA_RX_CONTROL_OFFSET WLAN_MBOX0_DMA_RX_CONTROL_OFFSET
-#define MBOX0_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MSB
-#define MBOX0_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB
-#define MBOX0_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK
-#define MBOX0_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX0_DMA_RX_CONTROL_RESUME_GET(x)
-#define MBOX0_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX0_DMA_RX_CONTROL_RESUME_SET(x)
-#define MBOX0_DMA_RX_CONTROL_START_MSB WLAN_MBOX0_DMA_RX_CONTROL_START_MSB
-#define MBOX0_DMA_RX_CONTROL_START_LSB WLAN_MBOX0_DMA_RX_CONTROL_START_LSB
-#define MBOX0_DMA_RX_CONTROL_START_MASK WLAN_MBOX0_DMA_RX_CONTROL_START_MASK
-#define MBOX0_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX0_DMA_RX_CONTROL_START_GET(x)
-#define MBOX0_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX0_DMA_RX_CONTROL_START_SET(x)
-#define MBOX0_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX0_DMA_RX_CONTROL_STOP_MSB
-#define MBOX0_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB
-#define MBOX0_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK
-#define MBOX0_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX0_DMA_RX_CONTROL_STOP_GET(x)
-#define MBOX0_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX0_DMA_RX_CONTROL_STOP_SET(x)
-#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS
-#define MBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET
-#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB
-#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB
-#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK
-#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x)
-#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x)
-#define MBOX0_DMA_TX_CONTROL_ADDRESS WLAN_MBOX0_DMA_TX_CONTROL_ADDRESS
-#define MBOX0_DMA_TX_CONTROL_OFFSET WLAN_MBOX0_DMA_TX_CONTROL_OFFSET
-#define MBOX0_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MSB
-#define MBOX0_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB
-#define MBOX0_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK
-#define MBOX0_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX0_DMA_TX_CONTROL_RESUME_GET(x)
-#define MBOX0_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX0_DMA_TX_CONTROL_RESUME_SET(x)
-#define MBOX0_DMA_TX_CONTROL_START_MSB WLAN_MBOX0_DMA_TX_CONTROL_START_MSB
-#define MBOX0_DMA_TX_CONTROL_START_LSB WLAN_MBOX0_DMA_TX_CONTROL_START_LSB
-#define MBOX0_DMA_TX_CONTROL_START_MASK WLAN_MBOX0_DMA_TX_CONTROL_START_MASK
-#define MBOX0_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX0_DMA_TX_CONTROL_START_GET(x)
-#define MBOX0_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX0_DMA_TX_CONTROL_START_SET(x)
-#define MBOX0_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX0_DMA_TX_CONTROL_STOP_MSB
-#define MBOX0_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB
-#define MBOX0_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK
-#define MBOX0_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX0_DMA_TX_CONTROL_STOP_GET(x)
-#define MBOX0_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX0_DMA_TX_CONTROL_STOP_SET(x)
-#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS
-#define MBOX1_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_OFFSET
-#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB
-#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB
-#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK
-#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x)
-#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x)
-#define MBOX1_DMA_RX_CONTROL_ADDRESS WLAN_MBOX1_DMA_RX_CONTROL_ADDRESS
-#define MBOX1_DMA_RX_CONTROL_OFFSET WLAN_MBOX1_DMA_RX_CONTROL_OFFSET
-#define MBOX1_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MSB
-#define MBOX1_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB
-#define MBOX1_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK
-#define MBOX1_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX1_DMA_RX_CONTROL_RESUME_GET(x)
-#define MBOX1_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX1_DMA_RX_CONTROL_RESUME_SET(x)
-#define MBOX1_DMA_RX_CONTROL_START_MSB WLAN_MBOX1_DMA_RX_CONTROL_START_MSB
-#define MBOX1_DMA_RX_CONTROL_START_LSB WLAN_MBOX1_DMA_RX_CONTROL_START_LSB
-#define MBOX1_DMA_RX_CONTROL_START_MASK WLAN_MBOX1_DMA_RX_CONTROL_START_MASK
-#define MBOX1_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX1_DMA_RX_CONTROL_START_GET(x)
-#define MBOX1_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX1_DMA_RX_CONTROL_START_SET(x)
-#define MBOX1_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX1_DMA_RX_CONTROL_STOP_MSB
-#define MBOX1_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB
-#define MBOX1_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK
-#define MBOX1_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX1_DMA_RX_CONTROL_STOP_GET(x)
-#define MBOX1_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX1_DMA_RX_CONTROL_STOP_SET(x)
-#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS
-#define MBOX1_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_OFFSET
-#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB
-#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB
-#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK
-#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x)
-#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x)
-#define MBOX1_DMA_TX_CONTROL_ADDRESS WLAN_MBOX1_DMA_TX_CONTROL_ADDRESS
-#define MBOX1_DMA_TX_CONTROL_OFFSET WLAN_MBOX1_DMA_TX_CONTROL_OFFSET
-#define MBOX1_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MSB
-#define MBOX1_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB
-#define MBOX1_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK
-#define MBOX1_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX1_DMA_TX_CONTROL_RESUME_GET(x)
-#define MBOX1_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX1_DMA_TX_CONTROL_RESUME_SET(x)
-#define MBOX1_DMA_TX_CONTROL_START_MSB WLAN_MBOX1_DMA_TX_CONTROL_START_MSB
-#define MBOX1_DMA_TX_CONTROL_START_LSB WLAN_MBOX1_DMA_TX_CONTROL_START_LSB
-#define MBOX1_DMA_TX_CONTROL_START_MASK WLAN_MBOX1_DMA_TX_CONTROL_START_MASK
-#define MBOX1_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX1_DMA_TX_CONTROL_START_GET(x)
-#define MBOX1_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX1_DMA_TX_CONTROL_START_SET(x)
-#define MBOX1_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX1_DMA_TX_CONTROL_STOP_MSB
-#define MBOX1_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB
-#define MBOX1_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK
-#define MBOX1_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX1_DMA_TX_CONTROL_STOP_GET(x)
-#define MBOX1_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX1_DMA_TX_CONTROL_STOP_SET(x)
-#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS
-#define MBOX2_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_OFFSET
-#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB
-#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB
-#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK
-#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x)
-#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x)
-#define MBOX2_DMA_RX_CONTROL_ADDRESS WLAN_MBOX2_DMA_RX_CONTROL_ADDRESS
-#define MBOX2_DMA_RX_CONTROL_OFFSET WLAN_MBOX2_DMA_RX_CONTROL_OFFSET
-#define MBOX2_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MSB
-#define MBOX2_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB
-#define MBOX2_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK
-#define MBOX2_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX2_DMA_RX_CONTROL_RESUME_GET(x)
-#define MBOX2_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX2_DMA_RX_CONTROL_RESUME_SET(x)
-#define MBOX2_DMA_RX_CONTROL_START_MSB WLAN_MBOX2_DMA_RX_CONTROL_START_MSB
-#define MBOX2_DMA_RX_CONTROL_START_LSB WLAN_MBOX2_DMA_RX_CONTROL_START_LSB
-#define MBOX2_DMA_RX_CONTROL_START_MASK WLAN_MBOX2_DMA_RX_CONTROL_START_MASK
-#define MBOX2_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX2_DMA_RX_CONTROL_START_GET(x)
-#define MBOX2_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX2_DMA_RX_CONTROL_START_SET(x)
-#define MBOX2_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX2_DMA_RX_CONTROL_STOP_MSB
-#define MBOX2_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB
-#define MBOX2_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK
-#define MBOX2_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX2_DMA_RX_CONTROL_STOP_GET(x)
-#define MBOX2_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX2_DMA_RX_CONTROL_STOP_SET(x)
-#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS
-#define MBOX2_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_OFFSET
-#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB
-#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB
-#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK
-#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x)
-#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x)
-#define MBOX2_DMA_TX_CONTROL_ADDRESS WLAN_MBOX2_DMA_TX_CONTROL_ADDRESS
-#define MBOX2_DMA_TX_CONTROL_OFFSET WLAN_MBOX2_DMA_TX_CONTROL_OFFSET
-#define MBOX2_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MSB
-#define MBOX2_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB
-#define MBOX2_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK
-#define MBOX2_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX2_DMA_TX_CONTROL_RESUME_GET(x)
-#define MBOX2_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX2_DMA_TX_CONTROL_RESUME_SET(x)
-#define MBOX2_DMA_TX_CONTROL_START_MSB WLAN_MBOX2_DMA_TX_CONTROL_START_MSB
-#define MBOX2_DMA_TX_CONTROL_START_LSB WLAN_MBOX2_DMA_TX_CONTROL_START_LSB
-#define MBOX2_DMA_TX_CONTROL_START_MASK WLAN_MBOX2_DMA_TX_CONTROL_START_MASK
-#define MBOX2_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX2_DMA_TX_CONTROL_START_GET(x)
-#define MBOX2_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX2_DMA_TX_CONTROL_START_SET(x)
-#define MBOX2_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX2_DMA_TX_CONTROL_STOP_MSB
-#define MBOX2_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB
-#define MBOX2_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK
-#define MBOX2_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX2_DMA_TX_CONTROL_STOP_GET(x)
-#define MBOX2_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX2_DMA_TX_CONTROL_STOP_SET(x)
-#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS
-#define MBOX3_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_OFFSET
-#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB
-#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB
-#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK
-#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x)
-#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x)
-#define MBOX3_DMA_RX_CONTROL_ADDRESS WLAN_MBOX3_DMA_RX_CONTROL_ADDRESS
-#define MBOX3_DMA_RX_CONTROL_OFFSET WLAN_MBOX3_DMA_RX_CONTROL_OFFSET
-#define MBOX3_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MSB
-#define MBOX3_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB
-#define MBOX3_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK
-#define MBOX3_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX3_DMA_RX_CONTROL_RESUME_GET(x)
-#define MBOX3_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX3_DMA_RX_CONTROL_RESUME_SET(x)
-#define MBOX3_DMA_RX_CONTROL_START_MSB WLAN_MBOX3_DMA_RX_CONTROL_START_MSB
-#define MBOX3_DMA_RX_CONTROL_START_LSB WLAN_MBOX3_DMA_RX_CONTROL_START_LSB
-#define MBOX3_DMA_RX_CONTROL_START_MASK WLAN_MBOX3_DMA_RX_CONTROL_START_MASK
-#define MBOX3_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX3_DMA_RX_CONTROL_START_GET(x)
-#define MBOX3_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX3_DMA_RX_CONTROL_START_SET(x)
-#define MBOX3_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX3_DMA_RX_CONTROL_STOP_MSB
-#define MBOX3_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB
-#define MBOX3_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK
-#define MBOX3_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX3_DMA_RX_CONTROL_STOP_GET(x)
-#define MBOX3_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX3_DMA_RX_CONTROL_STOP_SET(x)
-#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS
-#define MBOX3_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_OFFSET
-#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB
-#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB
-#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK
-#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x)
-#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x)
-#define MBOX3_DMA_TX_CONTROL_ADDRESS WLAN_MBOX3_DMA_TX_CONTROL_ADDRESS
-#define MBOX3_DMA_TX_CONTROL_OFFSET WLAN_MBOX3_DMA_TX_CONTROL_OFFSET
-#define MBOX3_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MSB
-#define MBOX3_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB
-#define MBOX3_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK
-#define MBOX3_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX3_DMA_TX_CONTROL_RESUME_GET(x)
-#define MBOX3_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX3_DMA_TX_CONTROL_RESUME_SET(x)
-#define MBOX3_DMA_TX_CONTROL_START_MSB WLAN_MBOX3_DMA_TX_CONTROL_START_MSB
-#define MBOX3_DMA_TX_CONTROL_START_LSB WLAN_MBOX3_DMA_TX_CONTROL_START_LSB
-#define MBOX3_DMA_TX_CONTROL_START_MASK WLAN_MBOX3_DMA_TX_CONTROL_START_MASK
-#define MBOX3_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX3_DMA_TX_CONTROL_START_GET(x)
-#define MBOX3_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX3_DMA_TX_CONTROL_START_SET(x)
-#define MBOX3_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX3_DMA_TX_CONTROL_STOP_MSB
-#define MBOX3_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB
-#define MBOX3_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK
-#define MBOX3_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX3_DMA_TX_CONTROL_STOP_GET(x)
-#define MBOX3_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX3_DMA_TX_CONTROL_STOP_SET(x)
-#define MBOX_INT_STATUS_ADDRESS WLAN_MBOX_INT_STATUS_ADDRESS
-#define MBOX_INT_STATUS_OFFSET WLAN_MBOX_INT_STATUS_OFFSET
-#define MBOX_INT_STATUS_RX_DMA_COMPLETE_MSB WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MSB
-#define MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB
-#define MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK
-#define MBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x)
-#define MBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x)
-#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB
-#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB
-#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK
-#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x)
-#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x)
-#define MBOX_INT_STATUS_TX_DMA_COMPLETE_MSB WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MSB
-#define MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB
-#define MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK
-#define MBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x)
-#define MBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x)
-#define MBOX_INT_STATUS_TX_OVERFLOW_MSB WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MSB
-#define MBOX_INT_STATUS_TX_OVERFLOW_LSB WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB
-#define MBOX_INT_STATUS_TX_OVERFLOW_MASK WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK
-#define MBOX_INT_STATUS_TX_OVERFLOW_GET(x) WLAN_MBOX_INT_STATUS_TX_OVERFLOW_GET(x)
-#define MBOX_INT_STATUS_TX_OVERFLOW_SET(x) WLAN_MBOX_INT_STATUS_TX_OVERFLOW_SET(x)
-#define MBOX_INT_STATUS_RX_UNDERFLOW_MSB WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MSB
-#define MBOX_INT_STATUS_RX_UNDERFLOW_LSB WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB
-#define MBOX_INT_STATUS_RX_UNDERFLOW_MASK WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK
-#define MBOX_INT_STATUS_RX_UNDERFLOW_GET(x) WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_GET(x)
-#define MBOX_INT_STATUS_RX_UNDERFLOW_SET(x) WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_SET(x)
-#define MBOX_INT_STATUS_TX_NOT_EMPTY_MSB WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MSB
-#define MBOX_INT_STATUS_TX_NOT_EMPTY_LSB WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB
-#define MBOX_INT_STATUS_TX_NOT_EMPTY_MASK WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK
-#define MBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_GET(x)
-#define MBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_SET(x)
-#define MBOX_INT_STATUS_RX_NOT_FULL_MSB WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MSB
-#define MBOX_INT_STATUS_RX_NOT_FULL_LSB WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB
-#define MBOX_INT_STATUS_RX_NOT_FULL_MASK WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK
-#define MBOX_INT_STATUS_RX_NOT_FULL_GET(x) WLAN_MBOX_INT_STATUS_RX_NOT_FULL_GET(x)
-#define MBOX_INT_STATUS_RX_NOT_FULL_SET(x) WLAN_MBOX_INT_STATUS_RX_NOT_FULL_SET(x)
-#define MBOX_INT_STATUS_HOST_MSB WLAN_MBOX_INT_STATUS_HOST_MSB
-#define MBOX_INT_STATUS_HOST_LSB WLAN_MBOX_INT_STATUS_HOST_LSB
-#define MBOX_INT_STATUS_HOST_MASK WLAN_MBOX_INT_STATUS_HOST_MASK
-#define MBOX_INT_STATUS_HOST_GET(x) WLAN_MBOX_INT_STATUS_HOST_GET(x)
-#define MBOX_INT_STATUS_HOST_SET(x) WLAN_MBOX_INT_STATUS_HOST_SET(x)
-#define MBOX_INT_ENABLE_ADDRESS WLAN_MBOX_INT_ENABLE_ADDRESS
-#define MBOX_INT_ENABLE_OFFSET WLAN_MBOX_INT_ENABLE_OFFSET
-#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB
-#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB
-#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK
-#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x)
-#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x)
-#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB
-#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB
-#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK
-#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x)
-#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x)
-#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB
-#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB
-#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK
-#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x)
-#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x)
-#define MBOX_INT_ENABLE_TX_OVERFLOW_MSB WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MSB
-#define MBOX_INT_ENABLE_TX_OVERFLOW_LSB WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB
-#define MBOX_INT_ENABLE_TX_OVERFLOW_MASK WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK
-#define MBOX_INT_ENABLE_TX_OVERFLOW_GET(x) WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_GET(x)
-#define MBOX_INT_ENABLE_TX_OVERFLOW_SET(x) WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_SET(x)
-#define MBOX_INT_ENABLE_RX_UNDERFLOW_MSB WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MSB
-#define MBOX_INT_ENABLE_RX_UNDERFLOW_LSB WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB
-#define MBOX_INT_ENABLE_RX_UNDERFLOW_MASK WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK
-#define MBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_GET(x)
-#define MBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_SET(x)
-#define MBOX_INT_ENABLE_TX_NOT_EMPTY_MSB WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MSB
-#define MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB
-#define MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK
-#define MBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x)
-#define MBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x)
-#define MBOX_INT_ENABLE_RX_NOT_FULL_MSB WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MSB
-#define MBOX_INT_ENABLE_RX_NOT_FULL_LSB WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB
-#define MBOX_INT_ENABLE_RX_NOT_FULL_MASK WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK
-#define MBOX_INT_ENABLE_RX_NOT_FULL_GET(x) WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_GET(x)
-#define MBOX_INT_ENABLE_RX_NOT_FULL_SET(x) WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_SET(x)
-#define MBOX_INT_ENABLE_HOST_MSB WLAN_MBOX_INT_ENABLE_HOST_MSB
-#define MBOX_INT_ENABLE_HOST_LSB WLAN_MBOX_INT_ENABLE_HOST_LSB
-#define MBOX_INT_ENABLE_HOST_MASK WLAN_MBOX_INT_ENABLE_HOST_MASK
-#define MBOX_INT_ENABLE_HOST_GET(x) WLAN_MBOX_INT_ENABLE_HOST_GET(x)
-#define MBOX_INT_ENABLE_HOST_SET(x) WLAN_MBOX_INT_ENABLE_HOST_SET(x)
-#define INT_HOST_ADDRESS WLAN_INT_HOST_ADDRESS
-#define INT_HOST_OFFSET WLAN_INT_HOST_OFFSET
-#define INT_HOST_VECTOR_MSB WLAN_INT_HOST_VECTOR_MSB
-#define INT_HOST_VECTOR_LSB WLAN_INT_HOST_VECTOR_LSB
-#define INT_HOST_VECTOR_MASK WLAN_INT_HOST_VECTOR_MASK
-#define INT_HOST_VECTOR_GET(x) WLAN_INT_HOST_VECTOR_GET(x)
-#define INT_HOST_VECTOR_SET(x) WLAN_INT_HOST_VECTOR_SET(x)
-#define LOCAL_COUNT_ADDRESS WLAN_LOCAL_COUNT_ADDRESS
-#define LOCAL_COUNT_OFFSET WLAN_LOCAL_COUNT_OFFSET
-#define LOCAL_COUNT_VALUE_MSB WLAN_LOCAL_COUNT_VALUE_MSB
-#define LOCAL_COUNT_VALUE_LSB WLAN_LOCAL_COUNT_VALUE_LSB
-#define LOCAL_COUNT_VALUE_MASK WLAN_LOCAL_COUNT_VALUE_MASK
-#define LOCAL_COUNT_VALUE_GET(x) WLAN_LOCAL_COUNT_VALUE_GET(x)
-#define LOCAL_COUNT_VALUE_SET(x) WLAN_LOCAL_COUNT_VALUE_SET(x)
-#define COUNT_INC_ADDRESS WLAN_COUNT_INC_ADDRESS
-#define COUNT_INC_OFFSET WLAN_COUNT_INC_OFFSET
-#define COUNT_INC_VALUE_MSB WLAN_COUNT_INC_VALUE_MSB
-#define COUNT_INC_VALUE_LSB WLAN_COUNT_INC_VALUE_LSB
-#define COUNT_INC_VALUE_MASK WLAN_COUNT_INC_VALUE_MASK
-#define COUNT_INC_VALUE_GET(x) WLAN_COUNT_INC_VALUE_GET(x)
-#define COUNT_INC_VALUE_SET(x) WLAN_COUNT_INC_VALUE_SET(x)
-#define LOCAL_SCRATCH_ADDRESS WLAN_LOCAL_SCRATCH_ADDRESS
-#define LOCAL_SCRATCH_OFFSET WLAN_LOCAL_SCRATCH_OFFSET
-#define LOCAL_SCRATCH_VALUE_MSB WLAN_LOCAL_SCRATCH_VALUE_MSB
-#define LOCAL_SCRATCH_VALUE_LSB WLAN_LOCAL_SCRATCH_VALUE_LSB
-#define LOCAL_SCRATCH_VALUE_MASK WLAN_LOCAL_SCRATCH_VALUE_MASK
-#define LOCAL_SCRATCH_VALUE_GET(x) WLAN_LOCAL_SCRATCH_VALUE_GET(x)
-#define LOCAL_SCRATCH_VALUE_SET(x) WLAN_LOCAL_SCRATCH_VALUE_SET(x)
-#define USE_LOCAL_BUS_ADDRESS WLAN_USE_LOCAL_BUS_ADDRESS
-#define USE_LOCAL_BUS_OFFSET WLAN_USE_LOCAL_BUS_OFFSET
-#define USE_LOCAL_BUS_PIN_INIT_MSB WLAN_USE_LOCAL_BUS_PIN_INIT_MSB
-#define USE_LOCAL_BUS_PIN_INIT_LSB WLAN_USE_LOCAL_BUS_PIN_INIT_LSB
-#define USE_LOCAL_BUS_PIN_INIT_MASK WLAN_USE_LOCAL_BUS_PIN_INIT_MASK
-#define USE_LOCAL_BUS_PIN_INIT_GET(x) WLAN_USE_LOCAL_BUS_PIN_INIT_GET(x)
-#define USE_LOCAL_BUS_PIN_INIT_SET(x) WLAN_USE_LOCAL_BUS_PIN_INIT_SET(x)
-#define SDIO_CONFIG_ADDRESS WLAN_SDIO_CONFIG_ADDRESS
-#define SDIO_CONFIG_OFFSET WLAN_SDIO_CONFIG_OFFSET
-#define SDIO_CONFIG_CCCR_IOR1_MSB WLAN_SDIO_CONFIG_CCCR_IOR1_MSB
-#define SDIO_CONFIG_CCCR_IOR1_LSB WLAN_SDIO_CONFIG_CCCR_IOR1_LSB
-#define SDIO_CONFIG_CCCR_IOR1_MASK WLAN_SDIO_CONFIG_CCCR_IOR1_MASK
-#define SDIO_CONFIG_CCCR_IOR1_GET(x) WLAN_SDIO_CONFIG_CCCR_IOR1_GET(x)
-#define SDIO_CONFIG_CCCR_IOR1_SET(x) WLAN_SDIO_CONFIG_CCCR_IOR1_SET(x)
-#define MBOX_DEBUG_ADDRESS WLAN_MBOX_DEBUG_ADDRESS
-#define MBOX_DEBUG_OFFSET WLAN_MBOX_DEBUG_OFFSET
-#define MBOX_DEBUG_SEL_MSB WLAN_MBOX_DEBUG_SEL_MSB
-#define MBOX_DEBUG_SEL_LSB WLAN_MBOX_DEBUG_SEL_LSB
-#define MBOX_DEBUG_SEL_MASK WLAN_MBOX_DEBUG_SEL_MASK
-#define MBOX_DEBUG_SEL_GET(x) WLAN_MBOX_DEBUG_SEL_GET(x)
-#define MBOX_DEBUG_SEL_SET(x) WLAN_MBOX_DEBUG_SEL_SET(x)
-#define MBOX_FIFO_RESET_ADDRESS WLAN_MBOX_FIFO_RESET_ADDRESS
-#define MBOX_FIFO_RESET_OFFSET WLAN_MBOX_FIFO_RESET_OFFSET
-#define MBOX_FIFO_RESET_INIT_MSB WLAN_MBOX_FIFO_RESET_INIT_MSB
-#define MBOX_FIFO_RESET_INIT_LSB WLAN_MBOX_FIFO_RESET_INIT_LSB
-#define MBOX_FIFO_RESET_INIT_MASK WLAN_MBOX_FIFO_RESET_INIT_MASK
-#define MBOX_FIFO_RESET_INIT_GET(x) WLAN_MBOX_FIFO_RESET_INIT_GET(x)
-#define MBOX_FIFO_RESET_INIT_SET(x) WLAN_MBOX_FIFO_RESET_INIT_SET(x)
-#define MBOX_TXFIFO_POP_ADDRESS WLAN_MBOX_TXFIFO_POP_ADDRESS
-#define MBOX_TXFIFO_POP_OFFSET WLAN_MBOX_TXFIFO_POP_OFFSET
-#define MBOX_TXFIFO_POP_DATA_MSB WLAN_MBOX_TXFIFO_POP_DATA_MSB
-#define MBOX_TXFIFO_POP_DATA_LSB WLAN_MBOX_TXFIFO_POP_DATA_LSB
-#define MBOX_TXFIFO_POP_DATA_MASK WLAN_MBOX_TXFIFO_POP_DATA_MASK
-#define MBOX_TXFIFO_POP_DATA_GET(x) WLAN_MBOX_TXFIFO_POP_DATA_GET(x)
-#define MBOX_TXFIFO_POP_DATA_SET(x) WLAN_MBOX_TXFIFO_POP_DATA_SET(x)
-#define MBOX_RXFIFO_POP_ADDRESS WLAN_MBOX_RXFIFO_POP_ADDRESS
-#define MBOX_RXFIFO_POP_OFFSET WLAN_MBOX_RXFIFO_POP_OFFSET
-#define MBOX_RXFIFO_POP_DATA_MSB WLAN_MBOX_RXFIFO_POP_DATA_MSB
-#define MBOX_RXFIFO_POP_DATA_LSB WLAN_MBOX_RXFIFO_POP_DATA_LSB
-#define MBOX_RXFIFO_POP_DATA_MASK WLAN_MBOX_RXFIFO_POP_DATA_MASK
-#define MBOX_RXFIFO_POP_DATA_GET(x) WLAN_MBOX_RXFIFO_POP_DATA_GET(x)
-#define MBOX_RXFIFO_POP_DATA_SET(x) WLAN_MBOX_RXFIFO_POP_DATA_SET(x)
-#define SDIO_DEBUG_ADDRESS WLAN_SDIO_DEBUG_ADDRESS
-#define SDIO_DEBUG_OFFSET WLAN_SDIO_DEBUG_OFFSET
-#define SDIO_DEBUG_SEL_MSB WLAN_SDIO_DEBUG_SEL_MSB
-#define SDIO_DEBUG_SEL_LSB WLAN_SDIO_DEBUG_SEL_LSB
-#define SDIO_DEBUG_SEL_MASK WLAN_SDIO_DEBUG_SEL_MASK
-#define SDIO_DEBUG_SEL_GET(x) WLAN_SDIO_DEBUG_SEL_GET(x)
-#define SDIO_DEBUG_SEL_SET(x) WLAN_SDIO_DEBUG_SEL_SET(x)
-#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS
-#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET
-#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB
-#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB
-#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK
-#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x)
-#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x)
-#define GMBOX0_DMA_RX_CONTROL_ADDRESS WLAN_GMBOX0_DMA_RX_CONTROL_ADDRESS
-#define GMBOX0_DMA_RX_CONTROL_OFFSET WLAN_GMBOX0_DMA_RX_CONTROL_OFFSET
-#define GMBOX0_DMA_RX_CONTROL_RESUME_MSB WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MSB
-#define GMBOX0_DMA_RX_CONTROL_RESUME_LSB WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB
-#define GMBOX0_DMA_RX_CONTROL_RESUME_MASK WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK
-#define GMBOX0_DMA_RX_CONTROL_RESUME_GET(x) WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_GET(x)
-#define GMBOX0_DMA_RX_CONTROL_RESUME_SET(x) WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_SET(x)
-#define GMBOX0_DMA_RX_CONTROL_START_MSB WLAN_GMBOX0_DMA_RX_CONTROL_START_MSB
-#define GMBOX0_DMA_RX_CONTROL_START_LSB WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB
-#define GMBOX0_DMA_RX_CONTROL_START_MASK WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK
-#define GMBOX0_DMA_RX_CONTROL_START_GET(x) WLAN_GMBOX0_DMA_RX_CONTROL_START_GET(x)
-#define GMBOX0_DMA_RX_CONTROL_START_SET(x) WLAN_GMBOX0_DMA_RX_CONTROL_START_SET(x)
-#define GMBOX0_DMA_RX_CONTROL_STOP_MSB WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MSB
-#define GMBOX0_DMA_RX_CONTROL_STOP_LSB WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB
-#define GMBOX0_DMA_RX_CONTROL_STOP_MASK WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK
-#define GMBOX0_DMA_RX_CONTROL_STOP_GET(x) WLAN_GMBOX0_DMA_RX_CONTROL_STOP_GET(x)
-#define GMBOX0_DMA_RX_CONTROL_STOP_SET(x) WLAN_GMBOX0_DMA_RX_CONTROL_STOP_SET(x)
-#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS
-#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET
-#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB
-#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB
-#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK
-#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x)
-#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x)
-#define GMBOX0_DMA_TX_CONTROL_ADDRESS WLAN_GMBOX0_DMA_TX_CONTROL_ADDRESS
-#define GMBOX0_DMA_TX_CONTROL_OFFSET WLAN_GMBOX0_DMA_TX_CONTROL_OFFSET
-#define GMBOX0_DMA_TX_CONTROL_RESUME_MSB WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MSB
-#define GMBOX0_DMA_TX_CONTROL_RESUME_LSB WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB
-#define GMBOX0_DMA_TX_CONTROL_RESUME_MASK WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK
-#define GMBOX0_DMA_TX_CONTROL_RESUME_GET(x) WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_GET(x)
-#define GMBOX0_DMA_TX_CONTROL_RESUME_SET(x) WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_SET(x)
-#define GMBOX0_DMA_TX_CONTROL_START_MSB WLAN_GMBOX0_DMA_TX_CONTROL_START_MSB
-#define GMBOX0_DMA_TX_CONTROL_START_LSB WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB
-#define GMBOX0_DMA_TX_CONTROL_START_MASK WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK
-#define GMBOX0_DMA_TX_CONTROL_START_GET(x) WLAN_GMBOX0_DMA_TX_CONTROL_START_GET(x)
-#define GMBOX0_DMA_TX_CONTROL_START_SET(x) WLAN_GMBOX0_DMA_TX_CONTROL_START_SET(x)
-#define GMBOX0_DMA_TX_CONTROL_STOP_MSB WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MSB
-#define GMBOX0_DMA_TX_CONTROL_STOP_LSB WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB
-#define GMBOX0_DMA_TX_CONTROL_STOP_MASK WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK
-#define GMBOX0_DMA_TX_CONTROL_STOP_GET(x) WLAN_GMBOX0_DMA_TX_CONTROL_STOP_GET(x)
-#define GMBOX0_DMA_TX_CONTROL_STOP_SET(x) WLAN_GMBOX0_DMA_TX_CONTROL_STOP_SET(x)
-#define GMBOX_INT_STATUS_ADDRESS WLAN_GMBOX_INT_STATUS_ADDRESS
-#define GMBOX_INT_STATUS_OFFSET WLAN_GMBOX_INT_STATUS_OFFSET
-#define GMBOX_INT_STATUS_TX_OVERFLOW_MSB WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MSB
-#define GMBOX_INT_STATUS_TX_OVERFLOW_LSB WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB
-#define GMBOX_INT_STATUS_TX_OVERFLOW_MASK WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK
-#define GMBOX_INT_STATUS_TX_OVERFLOW_GET(x) WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_GET(x)
-#define GMBOX_INT_STATUS_TX_OVERFLOW_SET(x) WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_SET(x)
-#define GMBOX_INT_STATUS_RX_UNDERFLOW_MSB WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MSB
-#define GMBOX_INT_STATUS_RX_UNDERFLOW_LSB WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB
-#define GMBOX_INT_STATUS_RX_UNDERFLOW_MASK WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK
-#define GMBOX_INT_STATUS_RX_UNDERFLOW_GET(x) WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_GET(x)
-#define GMBOX_INT_STATUS_RX_UNDERFLOW_SET(x) WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_SET(x)
-#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MSB
-#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB
-#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK
-#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x)
-#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x)
-#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB
-#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB
-#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK
-#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x)
-#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x)
-#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MSB
-#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB
-#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK
-#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x)
-#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x)
-#define GMBOX_INT_STATUS_TX_NOT_EMPTY_MSB WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MSB
-#define GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB
-#define GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK
-#define GMBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_GET(x)
-#define GMBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_SET(x)
-#define GMBOX_INT_STATUS_RX_NOT_FULL_MSB WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MSB
-#define GMBOX_INT_STATUS_RX_NOT_FULL_LSB WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB
-#define GMBOX_INT_STATUS_RX_NOT_FULL_MASK WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK
-#define GMBOX_INT_STATUS_RX_NOT_FULL_GET(x) WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_GET(x)
-#define GMBOX_INT_STATUS_RX_NOT_FULL_SET(x) WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_SET(x)
-#define GMBOX_INT_ENABLE_ADDRESS WLAN_GMBOX_INT_ENABLE_ADDRESS
-#define GMBOX_INT_ENABLE_OFFSET WLAN_GMBOX_INT_ENABLE_OFFSET
-#define GMBOX_INT_ENABLE_TX_OVERFLOW_MSB WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MSB
-#define GMBOX_INT_ENABLE_TX_OVERFLOW_LSB WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB
-#define GMBOX_INT_ENABLE_TX_OVERFLOW_MASK WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK
-#define GMBOX_INT_ENABLE_TX_OVERFLOW_GET(x) WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_GET(x)
-#define GMBOX_INT_ENABLE_TX_OVERFLOW_SET(x) WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_SET(x)
-#define GMBOX_INT_ENABLE_RX_UNDERFLOW_MSB WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MSB
-#define GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB
-#define GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK
-#define GMBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_GET(x)
-#define GMBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_SET(x)
-#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB
-#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB
-#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK
-#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x)
-#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x)
-#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB
-#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB
-#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK
-#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x)
-#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x)
-#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB
-#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB
-#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK
-#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x)
-#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x)
-#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_MSB WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MSB
-#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB
-#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK
-#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x)
-#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x)
-#define GMBOX_INT_ENABLE_RX_NOT_FULL_MSB WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MSB
-#define GMBOX_INT_ENABLE_RX_NOT_FULL_LSB WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB
-#define GMBOX_INT_ENABLE_RX_NOT_FULL_MASK WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK
-#define GMBOX_INT_ENABLE_RX_NOT_FULL_GET(x) WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_GET(x)
-#define GMBOX_INT_ENABLE_RX_NOT_FULL_SET(x) WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_SET(x)
-#define HOST_IF_WINDOW_ADDRESS WLAN_HOST_IF_WINDOW_ADDRESS
-#define HOST_IF_WINDOW_OFFSET WLAN_HOST_IF_WINDOW_OFFSET
-#define HOST_IF_WINDOW_DATA_MSB WLAN_HOST_IF_WINDOW_DATA_MSB
-#define HOST_IF_WINDOW_DATA_LSB WLAN_HOST_IF_WINDOW_DATA_LSB
-#define HOST_IF_WINDOW_DATA_MASK WLAN_HOST_IF_WINDOW_DATA_MASK
-#define HOST_IF_WINDOW_DATA_GET(x) WLAN_HOST_IF_WINDOW_DATA_GET(x)
-#define HOST_IF_WINDOW_DATA_SET(x) WLAN_HOST_IF_WINDOW_DATA_SET(x)
-
-#endif
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h b/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h
deleted file mode 100644
index 038d0d019273..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h
+++ /dev/null
@@ -1,471 +0,0 @@
-// ------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-// ------------------------------------------------------------------
-//===================================================================
-// Author(s): ="Atheros"
-//===================================================================
-
-
-#ifndef _MBOX_WLAN_HOST_REG_REG_H_
-#define _MBOX_WLAN_HOST_REG_REG_H_
-
-#define HOST_INT_STATUS_ADDRESS 0x00000400
-#define HOST_INT_STATUS_OFFSET 0x00000400
-#define HOST_INT_STATUS_ERROR_MSB 7
-#define HOST_INT_STATUS_ERROR_LSB 7
-#define HOST_INT_STATUS_ERROR_MASK 0x00000080
-#define HOST_INT_STATUS_ERROR_GET(x) (((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB)
-#define HOST_INT_STATUS_ERROR_SET(x) (((x) << HOST_INT_STATUS_ERROR_LSB) & HOST_INT_STATUS_ERROR_MASK)
-#define HOST_INT_STATUS_CPU_MSB 6
-#define HOST_INT_STATUS_CPU_LSB 6
-#define HOST_INT_STATUS_CPU_MASK 0x00000040
-#define HOST_INT_STATUS_CPU_GET(x) (((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB)
-#define HOST_INT_STATUS_CPU_SET(x) (((x) << HOST_INT_STATUS_CPU_LSB) & HOST_INT_STATUS_CPU_MASK)
-#define HOST_INT_STATUS_INT_MSB 5
-#define HOST_INT_STATUS_INT_LSB 5
-#define HOST_INT_STATUS_INT_MASK 0x00000020
-#define HOST_INT_STATUS_INT_GET(x) (((x) & HOST_INT_STATUS_INT_MASK) >> HOST_INT_STATUS_INT_LSB)
-#define HOST_INT_STATUS_INT_SET(x) (((x) << HOST_INT_STATUS_INT_LSB) & HOST_INT_STATUS_INT_MASK)
-#define HOST_INT_STATUS_COUNTER_MSB 4
-#define HOST_INT_STATUS_COUNTER_LSB 4
-#define HOST_INT_STATUS_COUNTER_MASK 0x00000010
-#define HOST_INT_STATUS_COUNTER_GET(x) (((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB)
-#define HOST_INT_STATUS_COUNTER_SET(x) (((x) << HOST_INT_STATUS_COUNTER_LSB) & HOST_INT_STATUS_COUNTER_MASK)
-#define HOST_INT_STATUS_MBOX_DATA_MSB 3
-#define HOST_INT_STATUS_MBOX_DATA_LSB 0
-#define HOST_INT_STATUS_MBOX_DATA_MASK 0x0000000f
-#define HOST_INT_STATUS_MBOX_DATA_GET(x) (((x) & HOST_INT_STATUS_MBOX_DATA_MASK) >> HOST_INT_STATUS_MBOX_DATA_LSB)
-#define HOST_INT_STATUS_MBOX_DATA_SET(x) (((x) << HOST_INT_STATUS_MBOX_DATA_LSB) & HOST_INT_STATUS_MBOX_DATA_MASK)
-
-#define CPU_INT_STATUS_ADDRESS 0x00000401
-#define CPU_INT_STATUS_OFFSET 0x00000401
-#define CPU_INT_STATUS_BIT_MSB 7
-#define CPU_INT_STATUS_BIT_LSB 0
-#define CPU_INT_STATUS_BIT_MASK 0x000000ff
-#define CPU_INT_STATUS_BIT_GET(x) (((x) & CPU_INT_STATUS_BIT_MASK) >> CPU_INT_STATUS_BIT_LSB)
-#define CPU_INT_STATUS_BIT_SET(x) (((x) << CPU_INT_STATUS_BIT_LSB) & CPU_INT_STATUS_BIT_MASK)
-
-#define ERROR_INT_STATUS_ADDRESS 0x00000402
-#define ERROR_INT_STATUS_OFFSET 0x00000402
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MSB 6
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_LSB 6
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MASK 0x00000040
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_GET(x) (((x) & ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MASK) >> ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_LSB)
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_SET(x) (((x) << ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_LSB) & ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MASK)
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MSB 5
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_LSB 5
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MASK 0x00000020
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MASK) >> ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_LSB)
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_SET(x) (((x) << ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_LSB) & ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MASK)
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MSB 4
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_LSB 4
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MASK 0x00000010
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MASK) >> ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_LSB)
-#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_SET(x) (((x) << ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_LSB) & ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MASK)
-#define ERROR_INT_STATUS_SPI_MSB 3
-#define ERROR_INT_STATUS_SPI_LSB 3
-#define ERROR_INT_STATUS_SPI_MASK 0x00000008
-#define ERROR_INT_STATUS_SPI_GET(x) (((x) & ERROR_INT_STATUS_SPI_MASK) >> ERROR_INT_STATUS_SPI_LSB)
-#define ERROR_INT_STATUS_SPI_SET(x) (((x) << ERROR_INT_STATUS_SPI_LSB) & ERROR_INT_STATUS_SPI_MASK)
-#define ERROR_INT_STATUS_WAKEUP_MSB 2
-#define ERROR_INT_STATUS_WAKEUP_LSB 2
-#define ERROR_INT_STATUS_WAKEUP_MASK 0x00000004
-#define ERROR_INT_STATUS_WAKEUP_GET(x) (((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> ERROR_INT_STATUS_WAKEUP_LSB)
-#define ERROR_INT_STATUS_WAKEUP_SET(x) (((x) << ERROR_INT_STATUS_WAKEUP_LSB) & ERROR_INT_STATUS_WAKEUP_MASK)
-#define ERROR_INT_STATUS_RX_UNDERFLOW_MSB 1
-#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB 1
-#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00000002
-#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> ERROR_INT_STATUS_RX_UNDERFLOW_LSB)
-#define ERROR_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << ERROR_INT_STATUS_RX_UNDERFLOW_LSB) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK)
-#define ERROR_INT_STATUS_TX_OVERFLOW_MSB 0
-#define ERROR_INT_STATUS_TX_OVERFLOW_LSB 0
-#define ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00000001
-#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> ERROR_INT_STATUS_TX_OVERFLOW_LSB)
-#define ERROR_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << ERROR_INT_STATUS_TX_OVERFLOW_LSB) & ERROR_INT_STATUS_TX_OVERFLOW_MASK)
-
-#define COUNTER_INT_STATUS_ADDRESS 0x00000403
-#define COUNTER_INT_STATUS_OFFSET 0x00000403
-#define COUNTER_INT_STATUS_COUNTER_MSB 7
-#define COUNTER_INT_STATUS_COUNTER_LSB 0
-#define COUNTER_INT_STATUS_COUNTER_MASK 0x000000ff
-#define COUNTER_INT_STATUS_COUNTER_GET(x) (((x) & COUNTER_INT_STATUS_COUNTER_MASK) >> COUNTER_INT_STATUS_COUNTER_LSB)
-#define COUNTER_INT_STATUS_COUNTER_SET(x) (((x) << COUNTER_INT_STATUS_COUNTER_LSB) & COUNTER_INT_STATUS_COUNTER_MASK)
-
-#define MBOX_FRAME_ADDRESS 0x00000404
-#define MBOX_FRAME_OFFSET 0x00000404
-#define MBOX_FRAME_RX_EOM_MSB 7
-#define MBOX_FRAME_RX_EOM_LSB 4
-#define MBOX_FRAME_RX_EOM_MASK 0x000000f0
-#define MBOX_FRAME_RX_EOM_GET(x) (((x) & MBOX_FRAME_RX_EOM_MASK) >> MBOX_FRAME_RX_EOM_LSB)
-#define MBOX_FRAME_RX_EOM_SET(x) (((x) << MBOX_FRAME_RX_EOM_LSB) & MBOX_FRAME_RX_EOM_MASK)
-#define MBOX_FRAME_RX_SOM_MSB 3
-#define MBOX_FRAME_RX_SOM_LSB 0
-#define MBOX_FRAME_RX_SOM_MASK 0x0000000f
-#define MBOX_FRAME_RX_SOM_GET(x) (((x) & MBOX_FRAME_RX_SOM_MASK) >> MBOX_FRAME_RX_SOM_LSB)
-#define MBOX_FRAME_RX_SOM_SET(x) (((x) << MBOX_FRAME_RX_SOM_LSB) & MBOX_FRAME_RX_SOM_MASK)
-
-#define RX_LOOKAHEAD_VALID_ADDRESS 0x00000405
-#define RX_LOOKAHEAD_VALID_OFFSET 0x00000405
-#define RX_LOOKAHEAD_VALID_MBOX_MSB 3
-#define RX_LOOKAHEAD_VALID_MBOX_LSB 0
-#define RX_LOOKAHEAD_VALID_MBOX_MASK 0x0000000f
-#define RX_LOOKAHEAD_VALID_MBOX_GET(x) (((x) & RX_LOOKAHEAD_VALID_MBOX_MASK) >> RX_LOOKAHEAD_VALID_MBOX_LSB)
-#define RX_LOOKAHEAD_VALID_MBOX_SET(x) (((x) << RX_LOOKAHEAD_VALID_MBOX_LSB) & RX_LOOKAHEAD_VALID_MBOX_MASK)
-
-#define HOST_INT_STATUS2_ADDRESS 0x00000406
-#define HOST_INT_STATUS2_OFFSET 0x00000406
-#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MSB 2
-#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_LSB 2
-#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MASK 0x00000004
-#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_GET(x) (((x) & HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MASK) >> HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_LSB)
-#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_SET(x) (((x) << HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_LSB) & HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MASK)
-#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MSB 1
-#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_LSB 1
-#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MASK 0x00000002
-#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_GET(x) (((x) & HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MASK) >> HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_LSB)
-#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_SET(x) (((x) << HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_LSB) & HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MASK)
-#define HOST_INT_STATUS2_GMBOX_DATA_MSB 0
-#define HOST_INT_STATUS2_GMBOX_DATA_LSB 0
-#define HOST_INT_STATUS2_GMBOX_DATA_MASK 0x00000001
-#define HOST_INT_STATUS2_GMBOX_DATA_GET(x) (((x) & HOST_INT_STATUS2_GMBOX_DATA_MASK) >> HOST_INT_STATUS2_GMBOX_DATA_LSB)
-#define HOST_INT_STATUS2_GMBOX_DATA_SET(x) (((x) << HOST_INT_STATUS2_GMBOX_DATA_LSB) & HOST_INT_STATUS2_GMBOX_DATA_MASK)
-
-#define GMBOX_RX_AVAIL_ADDRESS 0x00000407
-#define GMBOX_RX_AVAIL_OFFSET 0x00000407
-#define GMBOX_RX_AVAIL_BYTE_MSB 6
-#define GMBOX_RX_AVAIL_BYTE_LSB 0
-#define GMBOX_RX_AVAIL_BYTE_MASK 0x0000007f
-#define GMBOX_RX_AVAIL_BYTE_GET(x) (((x) & GMBOX_RX_AVAIL_BYTE_MASK) >> GMBOX_RX_AVAIL_BYTE_LSB)
-#define GMBOX_RX_AVAIL_BYTE_SET(x) (((x) << GMBOX_RX_AVAIL_BYTE_LSB) & GMBOX_RX_AVAIL_BYTE_MASK)
-
-#define RX_LOOKAHEAD0_ADDRESS 0x00000408
-#define RX_LOOKAHEAD0_OFFSET 0x00000408
-#define RX_LOOKAHEAD0_DATA_MSB 7
-#define RX_LOOKAHEAD0_DATA_LSB 0
-#define RX_LOOKAHEAD0_DATA_MASK 0x000000ff
-#define RX_LOOKAHEAD0_DATA_GET(x) (((x) & RX_LOOKAHEAD0_DATA_MASK) >> RX_LOOKAHEAD0_DATA_LSB)
-#define RX_LOOKAHEAD0_DATA_SET(x) (((x) << RX_LOOKAHEAD0_DATA_LSB) & RX_LOOKAHEAD0_DATA_MASK)
-
-#define RX_LOOKAHEAD1_ADDRESS 0x0000040c
-#define RX_LOOKAHEAD1_OFFSET 0x0000040c
-#define RX_LOOKAHEAD1_DATA_MSB 7
-#define RX_LOOKAHEAD1_DATA_LSB 0
-#define RX_LOOKAHEAD1_DATA_MASK 0x000000ff
-#define RX_LOOKAHEAD1_DATA_GET(x) (((x) & RX_LOOKAHEAD1_DATA_MASK) >> RX_LOOKAHEAD1_DATA_LSB)
-#define RX_LOOKAHEAD1_DATA_SET(x) (((x) << RX_LOOKAHEAD1_DATA_LSB) & RX_LOOKAHEAD1_DATA_MASK)
-
-#define RX_LOOKAHEAD2_ADDRESS 0x00000410
-#define RX_LOOKAHEAD2_OFFSET 0x00000410
-#define RX_LOOKAHEAD2_DATA_MSB 7
-#define RX_LOOKAHEAD2_DATA_LSB 0
-#define RX_LOOKAHEAD2_DATA_MASK 0x000000ff
-#define RX_LOOKAHEAD2_DATA_GET(x) (((x) & RX_LOOKAHEAD2_DATA_MASK) >> RX_LOOKAHEAD2_DATA_LSB)
-#define RX_LOOKAHEAD2_DATA_SET(x) (((x) << RX_LOOKAHEAD2_DATA_LSB) & RX_LOOKAHEAD2_DATA_MASK)
-
-#define RX_LOOKAHEAD3_ADDRESS 0x00000414
-#define RX_LOOKAHEAD3_OFFSET 0x00000414
-#define RX_LOOKAHEAD3_DATA_MSB 7
-#define RX_LOOKAHEAD3_DATA_LSB 0
-#define RX_LOOKAHEAD3_DATA_MASK 0x000000ff
-#define RX_LOOKAHEAD3_DATA_GET(x) (((x) & RX_LOOKAHEAD3_DATA_MASK) >> RX_LOOKAHEAD3_DATA_LSB)
-#define RX_LOOKAHEAD3_DATA_SET(x) (((x) << RX_LOOKAHEAD3_DATA_LSB) & RX_LOOKAHEAD3_DATA_MASK)
-
-#define INT_STATUS_ENABLE_ADDRESS 0x00000418
-#define INT_STATUS_ENABLE_OFFSET 0x00000418
-#define INT_STATUS_ENABLE_ERROR_MSB 7
-#define INT_STATUS_ENABLE_ERROR_LSB 7
-#define INT_STATUS_ENABLE_ERROR_MASK 0x00000080
-#define INT_STATUS_ENABLE_ERROR_GET(x) (((x) & INT_STATUS_ENABLE_ERROR_MASK) >> INT_STATUS_ENABLE_ERROR_LSB)
-#define INT_STATUS_ENABLE_ERROR_SET(x) (((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK)
-#define INT_STATUS_ENABLE_CPU_MSB 6
-#define INT_STATUS_ENABLE_CPU_LSB 6
-#define INT_STATUS_ENABLE_CPU_MASK 0x00000040
-#define INT_STATUS_ENABLE_CPU_GET(x) (((x) & INT_STATUS_ENABLE_CPU_MASK) >> INT_STATUS_ENABLE_CPU_LSB)
-#define INT_STATUS_ENABLE_CPU_SET(x) (((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK)
-#define INT_STATUS_ENABLE_INT_MSB 5
-#define INT_STATUS_ENABLE_INT_LSB 5
-#define INT_STATUS_ENABLE_INT_MASK 0x00000020
-#define INT_STATUS_ENABLE_INT_GET(x) (((x) & INT_STATUS_ENABLE_INT_MASK) >> INT_STATUS_ENABLE_INT_LSB)
-#define INT_STATUS_ENABLE_INT_SET(x) (((x) << INT_STATUS_ENABLE_INT_LSB) & INT_STATUS_ENABLE_INT_MASK)
-#define INT_STATUS_ENABLE_COUNTER_MSB 4
-#define INT_STATUS_ENABLE_COUNTER_LSB 4
-#define INT_STATUS_ENABLE_COUNTER_MASK 0x00000010
-#define INT_STATUS_ENABLE_COUNTER_GET(x) (((x) & INT_STATUS_ENABLE_COUNTER_MASK) >> INT_STATUS_ENABLE_COUNTER_LSB)
-#define INT_STATUS_ENABLE_COUNTER_SET(x) (((x) << INT_STATUS_ENABLE_COUNTER_LSB) & INT_STATUS_ENABLE_COUNTER_MASK)
-#define INT_STATUS_ENABLE_MBOX_DATA_MSB 3
-#define INT_STATUS_ENABLE_MBOX_DATA_LSB 0
-#define INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f
-#define INT_STATUS_ENABLE_MBOX_DATA_GET(x) (((x) & INT_STATUS_ENABLE_MBOX_DATA_MASK) >> INT_STATUS_ENABLE_MBOX_DATA_LSB)
-#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) (((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & INT_STATUS_ENABLE_MBOX_DATA_MASK)
-
-#define CPU_INT_STATUS_ENABLE_ADDRESS 0x00000419
-#define CPU_INT_STATUS_ENABLE_OFFSET 0x00000419
-#define CPU_INT_STATUS_ENABLE_BIT_MSB 7
-#define CPU_INT_STATUS_ENABLE_BIT_LSB 0
-#define CPU_INT_STATUS_ENABLE_BIT_MASK 0x000000ff
-#define CPU_INT_STATUS_ENABLE_BIT_GET(x) (((x) & CPU_INT_STATUS_ENABLE_BIT_MASK) >> CPU_INT_STATUS_ENABLE_BIT_LSB)
-#define CPU_INT_STATUS_ENABLE_BIT_SET(x) (((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & CPU_INT_STATUS_ENABLE_BIT_MASK)
-
-#define ERROR_STATUS_ENABLE_ADDRESS 0x0000041a
-#define ERROR_STATUS_ENABLE_OFFSET 0x0000041a
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MSB 6
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_LSB 6
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MASK 0x00000040
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_GET(x) (((x) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MASK) >> ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_LSB)
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_SET(x) (((x) << ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_LSB) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MASK)
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MSB 5
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_LSB 5
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MASK 0x00000020
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MASK) >> ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_LSB)
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MASK)
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MSB 4
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_LSB 4
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MASK 0x00000010
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MASK) >> ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_LSB)
-#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MASK)
-#define ERROR_STATUS_ENABLE_WAKEUP_MSB 2
-#define ERROR_STATUS_ENABLE_WAKEUP_LSB 2
-#define ERROR_STATUS_ENABLE_WAKEUP_MASK 0x00000004
-#define ERROR_STATUS_ENABLE_WAKEUP_GET(x) (((x) & ERROR_STATUS_ENABLE_WAKEUP_MASK) >> ERROR_STATUS_ENABLE_WAKEUP_LSB)
-#define ERROR_STATUS_ENABLE_WAKEUP_SET(x) (((x) << ERROR_STATUS_ENABLE_WAKEUP_LSB) & ERROR_STATUS_ENABLE_WAKEUP_MASK)
-#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MSB 1
-#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 1
-#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002
-#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) >> ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB)
-#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK)
-#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MSB 0
-#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 0
-#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00000001
-#define ERROR_STATUS_ENABLE_TX_OVERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) >> ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB)
-#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK)
-
-#define COUNTER_INT_STATUS_ENABLE_ADDRESS 0x0000041b
-#define COUNTER_INT_STATUS_ENABLE_OFFSET 0x0000041b
-#define COUNTER_INT_STATUS_ENABLE_BIT_MSB 7
-#define COUNTER_INT_STATUS_ENABLE_BIT_LSB 0
-#define COUNTER_INT_STATUS_ENABLE_BIT_MASK 0x000000ff
-#define COUNTER_INT_STATUS_ENABLE_BIT_GET(x) (((x) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) >> COUNTER_INT_STATUS_ENABLE_BIT_LSB)
-#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) (((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & COUNTER_INT_STATUS_ENABLE_BIT_MASK)
-
-#define COUNT_ADDRESS 0x00000420
-#define COUNT_OFFSET 0x00000420
-#define COUNT_VALUE_MSB 7
-#define COUNT_VALUE_LSB 0
-#define COUNT_VALUE_MASK 0x000000ff
-#define COUNT_VALUE_GET(x) (((x) & COUNT_VALUE_MASK) >> COUNT_VALUE_LSB)
-#define COUNT_VALUE_SET(x) (((x) << COUNT_VALUE_LSB) & COUNT_VALUE_MASK)
-
-#define COUNT_DEC_ADDRESS 0x00000440
-#define COUNT_DEC_OFFSET 0x00000440
-#define COUNT_DEC_VALUE_MSB 7
-#define COUNT_DEC_VALUE_LSB 0
-#define COUNT_DEC_VALUE_MASK 0x000000ff
-#define COUNT_DEC_VALUE_GET(x) (((x) & COUNT_DEC_VALUE_MASK) >> COUNT_DEC_VALUE_LSB)
-#define COUNT_DEC_VALUE_SET(x) (((x) << COUNT_DEC_VALUE_LSB) & COUNT_DEC_VALUE_MASK)
-
-#define SCRATCH_ADDRESS 0x00000460
-#define SCRATCH_OFFSET 0x00000460
-#define SCRATCH_VALUE_MSB 7
-#define SCRATCH_VALUE_LSB 0
-#define SCRATCH_VALUE_MASK 0x000000ff
-#define SCRATCH_VALUE_GET(x) (((x) & SCRATCH_VALUE_MASK) >> SCRATCH_VALUE_LSB)
-#define SCRATCH_VALUE_SET(x) (((x) << SCRATCH_VALUE_LSB) & SCRATCH_VALUE_MASK)
-
-#define FIFO_TIMEOUT_ADDRESS 0x00000468
-#define FIFO_TIMEOUT_OFFSET 0x00000468
-#define FIFO_TIMEOUT_VALUE_MSB 7
-#define FIFO_TIMEOUT_VALUE_LSB 0
-#define FIFO_TIMEOUT_VALUE_MASK 0x000000ff
-#define FIFO_TIMEOUT_VALUE_GET(x) (((x) & FIFO_TIMEOUT_VALUE_MASK) >> FIFO_TIMEOUT_VALUE_LSB)
-#define FIFO_TIMEOUT_VALUE_SET(x) (((x) << FIFO_TIMEOUT_VALUE_LSB) & FIFO_TIMEOUT_VALUE_MASK)
-
-#define FIFO_TIMEOUT_ENABLE_ADDRESS 0x00000469
-#define FIFO_TIMEOUT_ENABLE_OFFSET 0x00000469
-#define FIFO_TIMEOUT_ENABLE_SET_MSB 0
-#define FIFO_TIMEOUT_ENABLE_SET_LSB 0
-#define FIFO_TIMEOUT_ENABLE_SET_MASK 0x00000001
-#define FIFO_TIMEOUT_ENABLE_SET_GET(x) (((x) & FIFO_TIMEOUT_ENABLE_SET_MASK) >> FIFO_TIMEOUT_ENABLE_SET_LSB)
-#define FIFO_TIMEOUT_ENABLE_SET_SET(x) (((x) << FIFO_TIMEOUT_ENABLE_SET_LSB) & FIFO_TIMEOUT_ENABLE_SET_MASK)
-
-#define DISABLE_SLEEP_ADDRESS 0x0000046a
-#define DISABLE_SLEEP_OFFSET 0x0000046a
-#define DISABLE_SLEEP_FOR_INT_MSB 1
-#define DISABLE_SLEEP_FOR_INT_LSB 1
-#define DISABLE_SLEEP_FOR_INT_MASK 0x00000002
-#define DISABLE_SLEEP_FOR_INT_GET(x) (((x) & DISABLE_SLEEP_FOR_INT_MASK) >> DISABLE_SLEEP_FOR_INT_LSB)
-#define DISABLE_SLEEP_FOR_INT_SET(x) (((x) << DISABLE_SLEEP_FOR_INT_LSB) & DISABLE_SLEEP_FOR_INT_MASK)
-#define DISABLE_SLEEP_ON_MSB 0
-#define DISABLE_SLEEP_ON_LSB 0
-#define DISABLE_SLEEP_ON_MASK 0x00000001
-#define DISABLE_SLEEP_ON_GET(x) (((x) & DISABLE_SLEEP_ON_MASK) >> DISABLE_SLEEP_ON_LSB)
-#define DISABLE_SLEEP_ON_SET(x) (((x) << DISABLE_SLEEP_ON_LSB) & DISABLE_SLEEP_ON_MASK)
-
-#define LOCAL_BUS_ADDRESS 0x00000470
-#define LOCAL_BUS_OFFSET 0x00000470
-#define LOCAL_BUS_STATE_MSB 1
-#define LOCAL_BUS_STATE_LSB 0
-#define LOCAL_BUS_STATE_MASK 0x00000003
-#define LOCAL_BUS_STATE_GET(x) (((x) & LOCAL_BUS_STATE_MASK) >> LOCAL_BUS_STATE_LSB)
-#define LOCAL_BUS_STATE_SET(x) (((x) << LOCAL_BUS_STATE_LSB) & LOCAL_BUS_STATE_MASK)
-
-#define INT_WLAN_ADDRESS 0x00000472
-#define INT_WLAN_OFFSET 0x00000472
-#define INT_WLAN_VECTOR_MSB 7
-#define INT_WLAN_VECTOR_LSB 0
-#define INT_WLAN_VECTOR_MASK 0x000000ff
-#define INT_WLAN_VECTOR_GET(x) (((x) & INT_WLAN_VECTOR_MASK) >> INT_WLAN_VECTOR_LSB)
-#define INT_WLAN_VECTOR_SET(x) (((x) << INT_WLAN_VECTOR_LSB) & INT_WLAN_VECTOR_MASK)
-
-#define WINDOW_DATA_ADDRESS 0x00000474
-#define WINDOW_DATA_OFFSET 0x00000474
-#define WINDOW_DATA_DATA_MSB 7
-#define WINDOW_DATA_DATA_LSB 0
-#define WINDOW_DATA_DATA_MASK 0x000000ff
-#define WINDOW_DATA_DATA_GET(x) (((x) & WINDOW_DATA_DATA_MASK) >> WINDOW_DATA_DATA_LSB)
-#define WINDOW_DATA_DATA_SET(x) (((x) << WINDOW_DATA_DATA_LSB) & WINDOW_DATA_DATA_MASK)
-
-#define WINDOW_WRITE_ADDR_ADDRESS 0x00000478
-#define WINDOW_WRITE_ADDR_OFFSET 0x00000478
-#define WINDOW_WRITE_ADDR_ADDR_MSB 7
-#define WINDOW_WRITE_ADDR_ADDR_LSB 0
-#define WINDOW_WRITE_ADDR_ADDR_MASK 0x000000ff
-#define WINDOW_WRITE_ADDR_ADDR_GET(x) (((x) & WINDOW_WRITE_ADDR_ADDR_MASK) >> WINDOW_WRITE_ADDR_ADDR_LSB)
-#define WINDOW_WRITE_ADDR_ADDR_SET(x) (((x) << WINDOW_WRITE_ADDR_ADDR_LSB) & WINDOW_WRITE_ADDR_ADDR_MASK)
-
-#define WINDOW_READ_ADDR_ADDRESS 0x0000047c
-#define WINDOW_READ_ADDR_OFFSET 0x0000047c
-#define WINDOW_READ_ADDR_ADDR_MSB 7
-#define WINDOW_READ_ADDR_ADDR_LSB 0
-#define WINDOW_READ_ADDR_ADDR_MASK 0x000000ff
-#define WINDOW_READ_ADDR_ADDR_GET(x) (((x) & WINDOW_READ_ADDR_ADDR_MASK) >> WINDOW_READ_ADDR_ADDR_LSB)
-#define WINDOW_READ_ADDR_ADDR_SET(x) (((x) << WINDOW_READ_ADDR_ADDR_LSB) & WINDOW_READ_ADDR_ADDR_MASK)
-
-#define HOST_CTRL_SPI_CONFIG_ADDRESS 0x00000480
-#define HOST_CTRL_SPI_CONFIG_OFFSET 0x00000480
-#define HOST_CTRL_SPI_CONFIG_SPI_RESET_MSB 4
-#define HOST_CTRL_SPI_CONFIG_SPI_RESET_LSB 4
-#define HOST_CTRL_SPI_CONFIG_SPI_RESET_MASK 0x00000010
-#define HOST_CTRL_SPI_CONFIG_SPI_RESET_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_SPI_RESET_MASK) >> HOST_CTRL_SPI_CONFIG_SPI_RESET_LSB)
-#define HOST_CTRL_SPI_CONFIG_SPI_RESET_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_SPI_RESET_LSB) & HOST_CTRL_SPI_CONFIG_SPI_RESET_MASK)
-#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MSB 3
-#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_LSB 3
-#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MASK 0x00000008
-#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MASK) >> HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_LSB)
-#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_LSB) & HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MASK)
-#define HOST_CTRL_SPI_CONFIG_TEST_MODE_MSB 2
-#define HOST_CTRL_SPI_CONFIG_TEST_MODE_LSB 2
-#define HOST_CTRL_SPI_CONFIG_TEST_MODE_MASK 0x00000004
-#define HOST_CTRL_SPI_CONFIG_TEST_MODE_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_TEST_MODE_MASK) >> HOST_CTRL_SPI_CONFIG_TEST_MODE_LSB)
-#define HOST_CTRL_SPI_CONFIG_TEST_MODE_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_TEST_MODE_LSB) & HOST_CTRL_SPI_CONFIG_TEST_MODE_MASK)
-#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_MSB 1
-#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_LSB 0
-#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_MASK 0x00000003
-#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_DATA_SIZE_MASK) >> HOST_CTRL_SPI_CONFIG_DATA_SIZE_LSB)
-#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_DATA_SIZE_LSB) & HOST_CTRL_SPI_CONFIG_DATA_SIZE_MASK)
-
-#define HOST_CTRL_SPI_STATUS_ADDRESS 0x00000481
-#define HOST_CTRL_SPI_STATUS_OFFSET 0x00000481
-#define HOST_CTRL_SPI_STATUS_ADDR_ERR_MSB 3
-#define HOST_CTRL_SPI_STATUS_ADDR_ERR_LSB 3
-#define HOST_CTRL_SPI_STATUS_ADDR_ERR_MASK 0x00000008
-#define HOST_CTRL_SPI_STATUS_ADDR_ERR_GET(x) (((x) & HOST_CTRL_SPI_STATUS_ADDR_ERR_MASK) >> HOST_CTRL_SPI_STATUS_ADDR_ERR_LSB)
-#define HOST_CTRL_SPI_STATUS_ADDR_ERR_SET(x) (((x) << HOST_CTRL_SPI_STATUS_ADDR_ERR_LSB) & HOST_CTRL_SPI_STATUS_ADDR_ERR_MASK)
-#define HOST_CTRL_SPI_STATUS_RD_ERR_MSB 2
-#define HOST_CTRL_SPI_STATUS_RD_ERR_LSB 2
-#define HOST_CTRL_SPI_STATUS_RD_ERR_MASK 0x00000004
-#define HOST_CTRL_SPI_STATUS_RD_ERR_GET(x) (((x) & HOST_CTRL_SPI_STATUS_RD_ERR_MASK) >> HOST_CTRL_SPI_STATUS_RD_ERR_LSB)
-#define HOST_CTRL_SPI_STATUS_RD_ERR_SET(x) (((x) << HOST_CTRL_SPI_STATUS_RD_ERR_LSB) & HOST_CTRL_SPI_STATUS_RD_ERR_MASK)
-#define HOST_CTRL_SPI_STATUS_WR_ERR_MSB 1
-#define HOST_CTRL_SPI_STATUS_WR_ERR_LSB 1
-#define HOST_CTRL_SPI_STATUS_WR_ERR_MASK 0x00000002
-#define HOST_CTRL_SPI_STATUS_WR_ERR_GET(x) (((x) & HOST_CTRL_SPI_STATUS_WR_ERR_MASK) >> HOST_CTRL_SPI_STATUS_WR_ERR_LSB)
-#define HOST_CTRL_SPI_STATUS_WR_ERR_SET(x) (((x) << HOST_CTRL_SPI_STATUS_WR_ERR_LSB) & HOST_CTRL_SPI_STATUS_WR_ERR_MASK)
-#define HOST_CTRL_SPI_STATUS_READY_MSB 0
-#define HOST_CTRL_SPI_STATUS_READY_LSB 0
-#define HOST_CTRL_SPI_STATUS_READY_MASK 0x00000001
-#define HOST_CTRL_SPI_STATUS_READY_GET(x) (((x) & HOST_CTRL_SPI_STATUS_READY_MASK) >> HOST_CTRL_SPI_STATUS_READY_LSB)
-#define HOST_CTRL_SPI_STATUS_READY_SET(x) (((x) << HOST_CTRL_SPI_STATUS_READY_LSB) & HOST_CTRL_SPI_STATUS_READY_MASK)
-
-#define NON_ASSOC_SLEEP_EN_ADDRESS 0x00000482
-#define NON_ASSOC_SLEEP_EN_OFFSET 0x00000482
-#define NON_ASSOC_SLEEP_EN_BIT_MSB 0
-#define NON_ASSOC_SLEEP_EN_BIT_LSB 0
-#define NON_ASSOC_SLEEP_EN_BIT_MASK 0x00000001
-#define NON_ASSOC_SLEEP_EN_BIT_GET(x) (((x) & NON_ASSOC_SLEEP_EN_BIT_MASK) >> NON_ASSOC_SLEEP_EN_BIT_LSB)
-#define NON_ASSOC_SLEEP_EN_BIT_SET(x) (((x) << NON_ASSOC_SLEEP_EN_BIT_LSB) & NON_ASSOC_SLEEP_EN_BIT_MASK)
-
-#define CPU_DBG_SEL_ADDRESS 0x00000483
-#define CPU_DBG_SEL_OFFSET 0x00000483
-#define CPU_DBG_SEL_BIT_MSB 5
-#define CPU_DBG_SEL_BIT_LSB 0
-#define CPU_DBG_SEL_BIT_MASK 0x0000003f
-#define CPU_DBG_SEL_BIT_GET(x) (((x) & CPU_DBG_SEL_BIT_MASK) >> CPU_DBG_SEL_BIT_LSB)
-#define CPU_DBG_SEL_BIT_SET(x) (((x) << CPU_DBG_SEL_BIT_LSB) & CPU_DBG_SEL_BIT_MASK)
-
-#define CPU_DBG_ADDRESS 0x00000484
-#define CPU_DBG_OFFSET 0x00000484
-#define CPU_DBG_DATA_MSB 7
-#define CPU_DBG_DATA_LSB 0
-#define CPU_DBG_DATA_MASK 0x000000ff
-#define CPU_DBG_DATA_GET(x) (((x) & CPU_DBG_DATA_MASK) >> CPU_DBG_DATA_LSB)
-#define CPU_DBG_DATA_SET(x) (((x) << CPU_DBG_DATA_LSB) & CPU_DBG_DATA_MASK)
-
-#define INT_STATUS2_ENABLE_ADDRESS 0x00000488
-#define INT_STATUS2_ENABLE_OFFSET 0x00000488
-#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MSB 2
-#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_LSB 2
-#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MASK 0x00000004
-#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_GET(x) (((x) & INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MASK) >> INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_LSB)
-#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_SET(x) (((x) << INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_LSB) & INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MASK)
-#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MSB 1
-#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_LSB 1
-#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MASK 0x00000002
-#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_GET(x) (((x) & INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MASK) >> INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_LSB)
-#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_SET(x) (((x) << INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_LSB) & INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MASK)
-#define INT_STATUS2_ENABLE_GMBOX_DATA_MSB 0
-#define INT_STATUS2_ENABLE_GMBOX_DATA_LSB 0
-#define INT_STATUS2_ENABLE_GMBOX_DATA_MASK 0x00000001
-#define INT_STATUS2_ENABLE_GMBOX_DATA_GET(x) (((x) & INT_STATUS2_ENABLE_GMBOX_DATA_MASK) >> INT_STATUS2_ENABLE_GMBOX_DATA_LSB)
-#define INT_STATUS2_ENABLE_GMBOX_DATA_SET(x) (((x) << INT_STATUS2_ENABLE_GMBOX_DATA_LSB) & INT_STATUS2_ENABLE_GMBOX_DATA_MASK)
-
-#define GMBOX_RX_LOOKAHEAD_ADDRESS 0x00000490
-#define GMBOX_RX_LOOKAHEAD_OFFSET 0x00000490
-#define GMBOX_RX_LOOKAHEAD_DATA_MSB 7
-#define GMBOX_RX_LOOKAHEAD_DATA_LSB 0
-#define GMBOX_RX_LOOKAHEAD_DATA_MASK 0x000000ff
-#define GMBOX_RX_LOOKAHEAD_DATA_GET(x) (((x) & GMBOX_RX_LOOKAHEAD_DATA_MASK) >> GMBOX_RX_LOOKAHEAD_DATA_LSB)
-#define GMBOX_RX_LOOKAHEAD_DATA_SET(x) (((x) << GMBOX_RX_LOOKAHEAD_DATA_LSB) & GMBOX_RX_LOOKAHEAD_DATA_MASK)
-
-#define GMBOX_RX_LOOKAHEAD_MUX_ADDRESS 0x00000498
-#define GMBOX_RX_LOOKAHEAD_MUX_OFFSET 0x00000498
-#define GMBOX_RX_LOOKAHEAD_MUX_SEL_MSB 0
-#define GMBOX_RX_LOOKAHEAD_MUX_SEL_LSB 0
-#define GMBOX_RX_LOOKAHEAD_MUX_SEL_MASK 0x00000001
-#define GMBOX_RX_LOOKAHEAD_MUX_SEL_GET(x) (((x) & GMBOX_RX_LOOKAHEAD_MUX_SEL_MASK) >> GMBOX_RX_LOOKAHEAD_MUX_SEL_LSB)
-#define GMBOX_RX_LOOKAHEAD_MUX_SEL_SET(x) (((x) << GMBOX_RX_LOOKAHEAD_MUX_SEL_LSB) & GMBOX_RX_LOOKAHEAD_MUX_SEL_MASK)
-
-#define CIS_WINDOW_ADDRESS 0x00000600
-#define CIS_WINDOW_OFFSET 0x00000600
-#define CIS_WINDOW_DATA_MSB 7
-#define CIS_WINDOW_DATA_LSB 0
-#define CIS_WINDOW_DATA_MASK 0x000000ff
-#define CIS_WINDOW_DATA_GET(x) (((x) & CIS_WINDOW_DATA_MASK) >> CIS_WINDOW_DATA_LSB)
-#define CIS_WINDOW_DATA_SET(x) (((x) << CIS_WINDOW_DATA_LSB) & CIS_WINDOW_DATA_MASK)
-
-
-#endif /* _MBOX_WLAN_HOST_REG_H_ */
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h b/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h
deleted file mode 100644
index f5167b9ae8d0..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h
+++ /dev/null
@@ -1,589 +0,0 @@
-// ------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-// ------------------------------------------------------------------
-//===================================================================
-// Author(s): ="Atheros"
-//===================================================================
-
-
-#ifndef _MBOX_WLAN_REG_REG_H_
-#define _MBOX_WLAN_REG_REG_H_
-
-#define WLAN_MBOX_FIFO_ADDRESS 0x00000000
-#define WLAN_MBOX_FIFO_OFFSET 0x00000000
-#define WLAN_MBOX_FIFO_DATA_MSB 19
-#define WLAN_MBOX_FIFO_DATA_LSB 0
-#define WLAN_MBOX_FIFO_DATA_MASK 0x000fffff
-#define WLAN_MBOX_FIFO_DATA_GET(x) (((x) & WLAN_MBOX_FIFO_DATA_MASK) >> WLAN_MBOX_FIFO_DATA_LSB)
-#define WLAN_MBOX_FIFO_DATA_SET(x) (((x) << WLAN_MBOX_FIFO_DATA_LSB) & WLAN_MBOX_FIFO_DATA_MASK)
-
-#define WLAN_MBOX_FIFO_STATUS_ADDRESS 0x00000010
-#define WLAN_MBOX_FIFO_STATUS_OFFSET 0x00000010
-#define WLAN_MBOX_FIFO_STATUS_EMPTY_MSB 19
-#define WLAN_MBOX_FIFO_STATUS_EMPTY_LSB 16
-#define WLAN_MBOX_FIFO_STATUS_EMPTY_MASK 0x000f0000
-#define WLAN_MBOX_FIFO_STATUS_EMPTY_GET(x) (((x) & WLAN_MBOX_FIFO_STATUS_EMPTY_MASK) >> WLAN_MBOX_FIFO_STATUS_EMPTY_LSB)
-#define WLAN_MBOX_FIFO_STATUS_EMPTY_SET(x) (((x) << WLAN_MBOX_FIFO_STATUS_EMPTY_LSB) & WLAN_MBOX_FIFO_STATUS_EMPTY_MASK)
-#define WLAN_MBOX_FIFO_STATUS_FULL_MSB 15
-#define WLAN_MBOX_FIFO_STATUS_FULL_LSB 12
-#define WLAN_MBOX_FIFO_STATUS_FULL_MASK 0x0000f000
-#define WLAN_MBOX_FIFO_STATUS_FULL_GET(x) (((x) & WLAN_MBOX_FIFO_STATUS_FULL_MASK) >> WLAN_MBOX_FIFO_STATUS_FULL_LSB)
-#define WLAN_MBOX_FIFO_STATUS_FULL_SET(x) (((x) << WLAN_MBOX_FIFO_STATUS_FULL_LSB) & WLAN_MBOX_FIFO_STATUS_FULL_MASK)
-
-#define WLAN_MBOX_DMA_POLICY_ADDRESS 0x00000014
-#define WLAN_MBOX_DMA_POLICY_OFFSET 0x00000014
-#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MSB 3
-#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB 3
-#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK 0x00000008
-#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK) >> WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB)
-#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB) & WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK)
-#define WLAN_MBOX_DMA_POLICY_TX_ORDER_MSB 2
-#define WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB 2
-#define WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK 0x00000004
-#define WLAN_MBOX_DMA_POLICY_TX_ORDER_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK) >> WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB)
-#define WLAN_MBOX_DMA_POLICY_TX_ORDER_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB) & WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK)
-#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MSB 1
-#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB 1
-#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK 0x00000002
-#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK) >> WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB)
-#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB) & WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK)
-#define WLAN_MBOX_DMA_POLICY_RX_ORDER_MSB 0
-#define WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB 0
-#define WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK 0x00000001
-#define WLAN_MBOX_DMA_POLICY_RX_ORDER_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK) >> WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB)
-#define WLAN_MBOX_DMA_POLICY_RX_ORDER_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB) & WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK)
-
-#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000018
-#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000018
-#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27
-#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2
-#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc
-#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB)
-#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK)
-
-#define WLAN_MBOX0_DMA_RX_CONTROL_ADDRESS 0x0000001c
-#define WLAN_MBOX0_DMA_RX_CONTROL_OFFSET 0x0000001c
-#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MSB 2
-#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB 2
-#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK 0x00000004
-#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB)
-#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK)
-#define WLAN_MBOX0_DMA_RX_CONTROL_START_MSB 1
-#define WLAN_MBOX0_DMA_RX_CONTROL_START_LSB 1
-#define WLAN_MBOX0_DMA_RX_CONTROL_START_MASK 0x00000002
-#define WLAN_MBOX0_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX0_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX0_DMA_RX_CONTROL_START_LSB)
-#define WLAN_MBOX0_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX0_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX0_DMA_RX_CONTROL_START_MASK)
-#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_MSB 0
-#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB 0
-#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK 0x00000001
-#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB)
-#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK)
-
-#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000020
-#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000020
-#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27
-#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2
-#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc
-#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB)
-#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK)
-
-#define WLAN_MBOX0_DMA_TX_CONTROL_ADDRESS 0x00000024
-#define WLAN_MBOX0_DMA_TX_CONTROL_OFFSET 0x00000024
-#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MSB 2
-#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB 2
-#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK 0x00000004
-#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB)
-#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK)
-#define WLAN_MBOX0_DMA_TX_CONTROL_START_MSB 1
-#define WLAN_MBOX0_DMA_TX_CONTROL_START_LSB 1
-#define WLAN_MBOX0_DMA_TX_CONTROL_START_MASK 0x00000002
-#define WLAN_MBOX0_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX0_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX0_DMA_TX_CONTROL_START_LSB)
-#define WLAN_MBOX0_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX0_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX0_DMA_TX_CONTROL_START_MASK)
-#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_MSB 0
-#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB 0
-#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK 0x00000001
-#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB)
-#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK)
-
-#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000028
-#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000028
-#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27
-#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2
-#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc
-#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB)
-#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK)
-
-#define WLAN_MBOX1_DMA_RX_CONTROL_ADDRESS 0x0000002c
-#define WLAN_MBOX1_DMA_RX_CONTROL_OFFSET 0x0000002c
-#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MSB 2
-#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB 2
-#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK 0x00000004
-#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB)
-#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK)
-#define WLAN_MBOX1_DMA_RX_CONTROL_START_MSB 1
-#define WLAN_MBOX1_DMA_RX_CONTROL_START_LSB 1
-#define WLAN_MBOX1_DMA_RX_CONTROL_START_MASK 0x00000002
-#define WLAN_MBOX1_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX1_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX1_DMA_RX_CONTROL_START_LSB)
-#define WLAN_MBOX1_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX1_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX1_DMA_RX_CONTROL_START_MASK)
-#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_MSB 0
-#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB 0
-#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK 0x00000001
-#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB)
-#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK)
-
-#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000030
-#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000030
-#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27
-#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2
-#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc
-#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB)
-#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK)
-
-#define WLAN_MBOX1_DMA_TX_CONTROL_ADDRESS 0x00000034
-#define WLAN_MBOX1_DMA_TX_CONTROL_OFFSET 0x00000034
-#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MSB 2
-#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB 2
-#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK 0x00000004
-#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB)
-#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK)
-#define WLAN_MBOX1_DMA_TX_CONTROL_START_MSB 1
-#define WLAN_MBOX1_DMA_TX_CONTROL_START_LSB 1
-#define WLAN_MBOX1_DMA_TX_CONTROL_START_MASK 0x00000002
-#define WLAN_MBOX1_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX1_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX1_DMA_TX_CONTROL_START_LSB)
-#define WLAN_MBOX1_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX1_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX1_DMA_TX_CONTROL_START_MASK)
-#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_MSB 0
-#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB 0
-#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK 0x00000001
-#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB)
-#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK)
-
-#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000038
-#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000038
-#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27
-#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2
-#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc
-#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB)
-#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK)
-
-#define WLAN_MBOX2_DMA_RX_CONTROL_ADDRESS 0x0000003c
-#define WLAN_MBOX2_DMA_RX_CONTROL_OFFSET 0x0000003c
-#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MSB 2
-#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB 2
-#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK 0x00000004
-#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB)
-#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK)
-#define WLAN_MBOX2_DMA_RX_CONTROL_START_MSB 1
-#define WLAN_MBOX2_DMA_RX_CONTROL_START_LSB 1
-#define WLAN_MBOX2_DMA_RX_CONTROL_START_MASK 0x00000002
-#define WLAN_MBOX2_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX2_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX2_DMA_RX_CONTROL_START_LSB)
-#define WLAN_MBOX2_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX2_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX2_DMA_RX_CONTROL_START_MASK)
-#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_MSB 0
-#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB 0
-#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK 0x00000001
-#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB)
-#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK)
-
-#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000040
-#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000040
-#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27
-#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2
-#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc
-#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB)
-#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK)
-
-#define WLAN_MBOX2_DMA_TX_CONTROL_ADDRESS 0x00000044
-#define WLAN_MBOX2_DMA_TX_CONTROL_OFFSET 0x00000044
-#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MSB 2
-#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB 2
-#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK 0x00000004
-#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB)
-#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK)
-#define WLAN_MBOX2_DMA_TX_CONTROL_START_MSB 1
-#define WLAN_MBOX2_DMA_TX_CONTROL_START_LSB 1
-#define WLAN_MBOX2_DMA_TX_CONTROL_START_MASK 0x00000002
-#define WLAN_MBOX2_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX2_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX2_DMA_TX_CONTROL_START_LSB)
-#define WLAN_MBOX2_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX2_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX2_DMA_TX_CONTROL_START_MASK)
-#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_MSB 0
-#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB 0
-#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK 0x00000001
-#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB)
-#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK)
-
-#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000048
-#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000048
-#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27
-#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2
-#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc
-#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB)
-#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK)
-
-#define WLAN_MBOX3_DMA_RX_CONTROL_ADDRESS 0x0000004c
-#define WLAN_MBOX3_DMA_RX_CONTROL_OFFSET 0x0000004c
-#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MSB 2
-#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB 2
-#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK 0x00000004
-#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB)
-#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK)
-#define WLAN_MBOX3_DMA_RX_CONTROL_START_MSB 1
-#define WLAN_MBOX3_DMA_RX_CONTROL_START_LSB 1
-#define WLAN_MBOX3_DMA_RX_CONTROL_START_MASK 0x00000002
-#define WLAN_MBOX3_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX3_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX3_DMA_RX_CONTROL_START_LSB)
-#define WLAN_MBOX3_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX3_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX3_DMA_RX_CONTROL_START_MASK)
-#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_MSB 0
-#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB 0
-#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK 0x00000001
-#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB)
-#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK)
-
-#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000050
-#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000050
-#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27
-#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2
-#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc
-#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB)
-#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK)
-
-#define WLAN_MBOX3_DMA_TX_CONTROL_ADDRESS 0x00000054
-#define WLAN_MBOX3_DMA_TX_CONTROL_OFFSET 0x00000054
-#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MSB 2
-#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB 2
-#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK 0x00000004
-#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB)
-#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK)
-#define WLAN_MBOX3_DMA_TX_CONTROL_START_MSB 1
-#define WLAN_MBOX3_DMA_TX_CONTROL_START_LSB 1
-#define WLAN_MBOX3_DMA_TX_CONTROL_START_MASK 0x00000002
-#define WLAN_MBOX3_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX3_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX3_DMA_TX_CONTROL_START_LSB)
-#define WLAN_MBOX3_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX3_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX3_DMA_TX_CONTROL_START_MASK)
-#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_MSB 0
-#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB 0
-#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK 0x00000001
-#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB)
-#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK)
-
-#define WLAN_MBOX_INT_STATUS_ADDRESS 0x00000058
-#define WLAN_MBOX_INT_STATUS_OFFSET 0x00000058
-#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MSB 31
-#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB 28
-#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK 0xf0000000
-#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB)
-#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK)
-#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB 27
-#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB 24
-#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK 0x0f000000
-#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB)
-#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB) & WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK)
-#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MSB 23
-#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB 20
-#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK 0x00f00000
-#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB)
-#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK)
-#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MSB 17
-#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB 17
-#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK 0x00020000
-#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK) >> WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB)
-#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB) & WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK)
-#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MSB 16
-#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB 16
-#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK 0x00010000
-#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK) >> WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB)
-#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB) & WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK)
-#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MSB 15
-#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB 12
-#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK 0x0000f000
-#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK) >> WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB)
-#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB) & WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK)
-#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MSB 11
-#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB 8
-#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK 0x00000f00
-#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_GET(x) (((x) & WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK) >> WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB)
-#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_SET(x) (((x) << WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB) & WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK)
-#define WLAN_MBOX_INT_STATUS_HOST_MSB 7
-#define WLAN_MBOX_INT_STATUS_HOST_LSB 0
-#define WLAN_MBOX_INT_STATUS_HOST_MASK 0x000000ff
-#define WLAN_MBOX_INT_STATUS_HOST_GET(x) (((x) & WLAN_MBOX_INT_STATUS_HOST_MASK) >> WLAN_MBOX_INT_STATUS_HOST_LSB)
-#define WLAN_MBOX_INT_STATUS_HOST_SET(x) (((x) << WLAN_MBOX_INT_STATUS_HOST_LSB) & WLAN_MBOX_INT_STATUS_HOST_MASK)
-
-#define WLAN_MBOX_INT_ENABLE_ADDRESS 0x0000005c
-#define WLAN_MBOX_INT_ENABLE_OFFSET 0x0000005c
-#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB 31
-#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB 28
-#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK 0xf0000000
-#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB)
-#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK)
-#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB 27
-#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB 24
-#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK 0x0f000000
-#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB)
-#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB) & WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK)
-#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB 23
-#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB 20
-#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK 0x00f00000
-#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB)
-#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK)
-#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MSB 17
-#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB 17
-#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK 0x00020000
-#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK) >> WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB)
-#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB) & WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK)
-#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MSB 16
-#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB 16
-#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK 0x00010000
-#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK) >> WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB)
-#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB) & WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK)
-#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MSB 15
-#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB 12
-#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK 0x0000f000
-#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK) >> WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB)
-#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB) & WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK)
-#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MSB 11
-#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB 8
-#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK 0x00000f00
-#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK) >> WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB)
-#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB) & WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK)
-#define WLAN_MBOX_INT_ENABLE_HOST_MSB 7
-#define WLAN_MBOX_INT_ENABLE_HOST_LSB 0
-#define WLAN_MBOX_INT_ENABLE_HOST_MASK 0x000000ff
-#define WLAN_MBOX_INT_ENABLE_HOST_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_HOST_MASK) >> WLAN_MBOX_INT_ENABLE_HOST_LSB)
-#define WLAN_MBOX_INT_ENABLE_HOST_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_HOST_LSB) & WLAN_MBOX_INT_ENABLE_HOST_MASK)
-
-#define WLAN_INT_HOST_ADDRESS 0x00000060
-#define WLAN_INT_HOST_OFFSET 0x00000060
-#define WLAN_INT_HOST_VECTOR_MSB 7
-#define WLAN_INT_HOST_VECTOR_LSB 0
-#define WLAN_INT_HOST_VECTOR_MASK 0x000000ff
-#define WLAN_INT_HOST_VECTOR_GET(x) (((x) & WLAN_INT_HOST_VECTOR_MASK) >> WLAN_INT_HOST_VECTOR_LSB)
-#define WLAN_INT_HOST_VECTOR_SET(x) (((x) << WLAN_INT_HOST_VECTOR_LSB) & WLAN_INT_HOST_VECTOR_MASK)
-
-#define WLAN_LOCAL_COUNT_ADDRESS 0x00000080
-#define WLAN_LOCAL_COUNT_OFFSET 0x00000080
-#define WLAN_LOCAL_COUNT_VALUE_MSB 7
-#define WLAN_LOCAL_COUNT_VALUE_LSB 0
-#define WLAN_LOCAL_COUNT_VALUE_MASK 0x000000ff
-#define WLAN_LOCAL_COUNT_VALUE_GET(x) (((x) & WLAN_LOCAL_COUNT_VALUE_MASK) >> WLAN_LOCAL_COUNT_VALUE_LSB)
-#define WLAN_LOCAL_COUNT_VALUE_SET(x) (((x) << WLAN_LOCAL_COUNT_VALUE_LSB) & WLAN_LOCAL_COUNT_VALUE_MASK)
-
-#define WLAN_COUNT_INC_ADDRESS 0x000000a0
-#define WLAN_COUNT_INC_OFFSET 0x000000a0
-#define WLAN_COUNT_INC_VALUE_MSB 7
-#define WLAN_COUNT_INC_VALUE_LSB 0
-#define WLAN_COUNT_INC_VALUE_MASK 0x000000ff
-#define WLAN_COUNT_INC_VALUE_GET(x) (((x) & WLAN_COUNT_INC_VALUE_MASK) >> WLAN_COUNT_INC_VALUE_LSB)
-#define WLAN_COUNT_INC_VALUE_SET(x) (((x) << WLAN_COUNT_INC_VALUE_LSB) & WLAN_COUNT_INC_VALUE_MASK)
-
-#define WLAN_LOCAL_SCRATCH_ADDRESS 0x000000c0
-#define WLAN_LOCAL_SCRATCH_OFFSET 0x000000c0
-#define WLAN_LOCAL_SCRATCH_VALUE_MSB 7
-#define WLAN_LOCAL_SCRATCH_VALUE_LSB 0
-#define WLAN_LOCAL_SCRATCH_VALUE_MASK 0x000000ff
-#define WLAN_LOCAL_SCRATCH_VALUE_GET(x) (((x) & WLAN_LOCAL_SCRATCH_VALUE_MASK) >> WLAN_LOCAL_SCRATCH_VALUE_LSB)
-#define WLAN_LOCAL_SCRATCH_VALUE_SET(x) (((x) << WLAN_LOCAL_SCRATCH_VALUE_LSB) & WLAN_LOCAL_SCRATCH_VALUE_MASK)
-
-#define WLAN_USE_LOCAL_BUS_ADDRESS 0x000000e0
-#define WLAN_USE_LOCAL_BUS_OFFSET 0x000000e0
-#define WLAN_USE_LOCAL_BUS_PIN_INIT_MSB 0
-#define WLAN_USE_LOCAL_BUS_PIN_INIT_LSB 0
-#define WLAN_USE_LOCAL_BUS_PIN_INIT_MASK 0x00000001
-#define WLAN_USE_LOCAL_BUS_PIN_INIT_GET(x) (((x) & WLAN_USE_LOCAL_BUS_PIN_INIT_MASK) >> WLAN_USE_LOCAL_BUS_PIN_INIT_LSB)
-#define WLAN_USE_LOCAL_BUS_PIN_INIT_SET(x) (((x) << WLAN_USE_LOCAL_BUS_PIN_INIT_LSB) & WLAN_USE_LOCAL_BUS_PIN_INIT_MASK)
-
-#define WLAN_SDIO_CONFIG_ADDRESS 0x000000e4
-#define WLAN_SDIO_CONFIG_OFFSET 0x000000e4
-#define WLAN_SDIO_CONFIG_CCCR_IOR1_MSB 0
-#define WLAN_SDIO_CONFIG_CCCR_IOR1_LSB 0
-#define WLAN_SDIO_CONFIG_CCCR_IOR1_MASK 0x00000001
-#define WLAN_SDIO_CONFIG_CCCR_IOR1_GET(x) (((x) & WLAN_SDIO_CONFIG_CCCR_IOR1_MASK) >> WLAN_SDIO_CONFIG_CCCR_IOR1_LSB)
-#define WLAN_SDIO_CONFIG_CCCR_IOR1_SET(x) (((x) << WLAN_SDIO_CONFIG_CCCR_IOR1_LSB) & WLAN_SDIO_CONFIG_CCCR_IOR1_MASK)
-
-#define WLAN_MBOX_DEBUG_ADDRESS 0x000000e8
-#define WLAN_MBOX_DEBUG_OFFSET 0x000000e8
-#define WLAN_MBOX_DEBUG_SEL_MSB 2
-#define WLAN_MBOX_DEBUG_SEL_LSB 0
-#define WLAN_MBOX_DEBUG_SEL_MASK 0x00000007
-#define WLAN_MBOX_DEBUG_SEL_GET(x) (((x) & WLAN_MBOX_DEBUG_SEL_MASK) >> WLAN_MBOX_DEBUG_SEL_LSB)
-#define WLAN_MBOX_DEBUG_SEL_SET(x) (((x) << WLAN_MBOX_DEBUG_SEL_LSB) & WLAN_MBOX_DEBUG_SEL_MASK)
-
-#define WLAN_MBOX_FIFO_RESET_ADDRESS 0x000000ec
-#define WLAN_MBOX_FIFO_RESET_OFFSET 0x000000ec
-#define WLAN_MBOX_FIFO_RESET_INIT_MSB 0
-#define WLAN_MBOX_FIFO_RESET_INIT_LSB 0
-#define WLAN_MBOX_FIFO_RESET_INIT_MASK 0x00000001
-#define WLAN_MBOX_FIFO_RESET_INIT_GET(x) (((x) & WLAN_MBOX_FIFO_RESET_INIT_MASK) >> WLAN_MBOX_FIFO_RESET_INIT_LSB)
-#define WLAN_MBOX_FIFO_RESET_INIT_SET(x) (((x) << WLAN_MBOX_FIFO_RESET_INIT_LSB) & WLAN_MBOX_FIFO_RESET_INIT_MASK)
-
-#define WLAN_MBOX_TXFIFO_POP_ADDRESS 0x000000f0
-#define WLAN_MBOX_TXFIFO_POP_OFFSET 0x000000f0
-#define WLAN_MBOX_TXFIFO_POP_DATA_MSB 0
-#define WLAN_MBOX_TXFIFO_POP_DATA_LSB 0
-#define WLAN_MBOX_TXFIFO_POP_DATA_MASK 0x00000001
-#define WLAN_MBOX_TXFIFO_POP_DATA_GET(x) (((x) & WLAN_MBOX_TXFIFO_POP_DATA_MASK) >> WLAN_MBOX_TXFIFO_POP_DATA_LSB)
-#define WLAN_MBOX_TXFIFO_POP_DATA_SET(x) (((x) << WLAN_MBOX_TXFIFO_POP_DATA_LSB) & WLAN_MBOX_TXFIFO_POP_DATA_MASK)
-
-#define WLAN_MBOX_RXFIFO_POP_ADDRESS 0x00000100
-#define WLAN_MBOX_RXFIFO_POP_OFFSET 0x00000100
-#define WLAN_MBOX_RXFIFO_POP_DATA_MSB 0
-#define WLAN_MBOX_RXFIFO_POP_DATA_LSB 0
-#define WLAN_MBOX_RXFIFO_POP_DATA_MASK 0x00000001
-#define WLAN_MBOX_RXFIFO_POP_DATA_GET(x) (((x) & WLAN_MBOX_RXFIFO_POP_DATA_MASK) >> WLAN_MBOX_RXFIFO_POP_DATA_LSB)
-#define WLAN_MBOX_RXFIFO_POP_DATA_SET(x) (((x) << WLAN_MBOX_RXFIFO_POP_DATA_LSB) & WLAN_MBOX_RXFIFO_POP_DATA_MASK)
-
-#define WLAN_SDIO_DEBUG_ADDRESS 0x00000110
-#define WLAN_SDIO_DEBUG_OFFSET 0x00000110
-#define WLAN_SDIO_DEBUG_SEL_MSB 3
-#define WLAN_SDIO_DEBUG_SEL_LSB 0
-#define WLAN_SDIO_DEBUG_SEL_MASK 0x0000000f
-#define WLAN_SDIO_DEBUG_SEL_GET(x) (((x) & WLAN_SDIO_DEBUG_SEL_MASK) >> WLAN_SDIO_DEBUG_SEL_LSB)
-#define WLAN_SDIO_DEBUG_SEL_SET(x) (((x) << WLAN_SDIO_DEBUG_SEL_LSB) & WLAN_SDIO_DEBUG_SEL_MASK)
-
-#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000114
-#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000114
-#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27
-#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2
-#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc
-#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB)
-#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK)
-
-#define WLAN_GMBOX0_DMA_RX_CONTROL_ADDRESS 0x00000118
-#define WLAN_GMBOX0_DMA_RX_CONTROL_OFFSET 0x00000118
-#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MSB 2
-#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB 2
-#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK 0x00000004
-#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB)
-#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB) & WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK)
-#define WLAN_GMBOX0_DMA_RX_CONTROL_START_MSB 1
-#define WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB 1
-#define WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK 0x00000002
-#define WLAN_GMBOX0_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK) >> WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB)
-#define WLAN_GMBOX0_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB) & WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK)
-#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MSB 0
-#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB 0
-#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK 0x00000001
-#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK) >> WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB)
-#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB) & WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK)
-
-#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x0000011c
-#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x0000011c
-#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27
-#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2
-#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc
-#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB)
-#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK)
-
-#define WLAN_GMBOX0_DMA_TX_CONTROL_ADDRESS 0x00000120
-#define WLAN_GMBOX0_DMA_TX_CONTROL_OFFSET 0x00000120
-#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MSB 2
-#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB 2
-#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK 0x00000004
-#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB)
-#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB) & WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK)
-#define WLAN_GMBOX0_DMA_TX_CONTROL_START_MSB 1
-#define WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB 1
-#define WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK 0x00000002
-#define WLAN_GMBOX0_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK) >> WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB)
-#define WLAN_GMBOX0_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB) & WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK)
-#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MSB 0
-#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB 0
-#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK 0x00000001
-#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK) >> WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB)
-#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB) & WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK)
-
-#define WLAN_GMBOX_INT_STATUS_ADDRESS 0x00000124
-#define WLAN_GMBOX_INT_STATUS_OFFSET 0x00000124
-#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MSB 6
-#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB 6
-#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK 0x00000040
-#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK) >> WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB)
-#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB) & WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK)
-#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MSB 5
-#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB 5
-#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK 0x00000020
-#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK) >> WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB)
-#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB) & WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK)
-#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MSB 4
-#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB 4
-#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK 0x00000010
-#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB)
-#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK)
-#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB 3
-#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB 3
-#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK 0x00000008
-#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB)
-#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB) & WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK)
-#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MSB 2
-#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB 2
-#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK 0x00000004
-#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB)
-#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK)
-#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MSB 1
-#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB 1
-#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK 0x00000002
-#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK) >> WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB)
-#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB) & WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK)
-#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MSB 0
-#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB 0
-#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK 0x00000001
-#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK) >> WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB)
-#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB) & WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK)
-
-#define WLAN_GMBOX_INT_ENABLE_ADDRESS 0x00000128
-#define WLAN_GMBOX_INT_ENABLE_OFFSET 0x00000128
-#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MSB 6
-#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB 6
-#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK 0x00000040
-#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB)
-#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB) & WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK)
-#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MSB 5
-#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB 5
-#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK 0x00000020
-#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK) >> WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB)
-#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB) & WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK)
-#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB 4
-#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB 4
-#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK 0x00000010
-#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB)
-#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK)
-#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB 3
-#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB 3
-#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK 0x00000008
-#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB)
-#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB) & WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK)
-#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB 2
-#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB 2
-#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK 0x00000004
-#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB)
-#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK)
-#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MSB 1
-#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB 1
-#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK 0x00000002
-#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB)
-#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB) & WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK)
-#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MSB 0
-#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB 0
-#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK 0x00000001
-#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK) >> WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB)
-#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB) & WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK)
-
-#define WLAN_HOST_IF_WINDOW_ADDRESS 0x00002000
-#define WLAN_HOST_IF_WINDOW_OFFSET 0x00002000
-#define WLAN_HOST_IF_WINDOW_DATA_MSB 7
-#define WLAN_HOST_IF_WINDOW_DATA_LSB 0
-#define WLAN_HOST_IF_WINDOW_DATA_MASK 0x000000ff
-#define WLAN_HOST_IF_WINDOW_DATA_GET(x) (((x) & WLAN_HOST_IF_WINDOW_DATA_MASK) >> WLAN_HOST_IF_WINDOW_DATA_LSB)
-#define WLAN_HOST_IF_WINDOW_DATA_SET(x) (((x) << WLAN_HOST_IF_WINDOW_DATA_LSB) & WLAN_HOST_IF_WINDOW_DATA_MASK)
-
-#endif /* _MBOX_WLAN_REG_H_ */
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h b/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h
deleted file mode 100644
index fcafec88a6b9..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// ------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-// ------------------------------------------------------------------
-//===================================================================
-// Author(s): ="Atheros"
-//===================================================================
-
-
-#include "rtc_wlan_reg.h"
-
-#ifndef BT_HEADERS
-
-#define RESET_CONTROL_ADDRESS WLAN_RESET_CONTROL_ADDRESS
-#define RESET_CONTROL_OFFSET WLAN_RESET_CONTROL_OFFSET
-#define RESET_CONTROL_DEBUG_UART_RST_MSB WLAN_RESET_CONTROL_DEBUG_UART_RST_MSB
-#define RESET_CONTROL_DEBUG_UART_RST_LSB WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB
-#define RESET_CONTROL_DEBUG_UART_RST_MASK WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK
-#define RESET_CONTROL_DEBUG_UART_RST_GET(x) WLAN_RESET_CONTROL_DEBUG_UART_RST_GET(x)
-#define RESET_CONTROL_DEBUG_UART_RST_SET(x) WLAN_RESET_CONTROL_DEBUG_UART_RST_SET(x)
-#define RESET_CONTROL_BB_COLD_RST_MSB WLAN_RESET_CONTROL_BB_COLD_RST_MSB
-#define RESET_CONTROL_BB_COLD_RST_LSB WLAN_RESET_CONTROL_BB_COLD_RST_LSB
-#define RESET_CONTROL_BB_COLD_RST_MASK WLAN_RESET_CONTROL_BB_COLD_RST_MASK
-#define RESET_CONTROL_BB_COLD_RST_GET(x) WLAN_RESET_CONTROL_BB_COLD_RST_GET(x)
-#define RESET_CONTROL_BB_COLD_RST_SET(x) WLAN_RESET_CONTROL_BB_COLD_RST_SET(x)
-#define RESET_CONTROL_BB_WARM_RST_MSB WLAN_RESET_CONTROL_BB_WARM_RST_MSB
-#define RESET_CONTROL_BB_WARM_RST_LSB WLAN_RESET_CONTROL_BB_WARM_RST_LSB
-#define RESET_CONTROL_BB_WARM_RST_MASK WLAN_RESET_CONTROL_BB_WARM_RST_MASK
-#define RESET_CONTROL_BB_WARM_RST_GET(x) WLAN_RESET_CONTROL_BB_WARM_RST_GET(x)
-#define RESET_CONTROL_BB_WARM_RST_SET(x) WLAN_RESET_CONTROL_BB_WARM_RST_SET(x)
-#define RESET_CONTROL_CPU_INIT_RESET_MSB WLAN_RESET_CONTROL_CPU_INIT_RESET_MSB
-#define RESET_CONTROL_CPU_INIT_RESET_LSB WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB
-#define RESET_CONTROL_CPU_INIT_RESET_MASK WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK
-#define RESET_CONTROL_CPU_INIT_RESET_GET(x) WLAN_RESET_CONTROL_CPU_INIT_RESET_GET(x)
-#define RESET_CONTROL_CPU_INIT_RESET_SET(x) WLAN_RESET_CONTROL_CPU_INIT_RESET_SET(x)
-#define RESET_CONTROL_VMC_REMAP_RESET_MSB WLAN_RESET_CONTROL_VMC_REMAP_RESET_MSB
-#define RESET_CONTROL_VMC_REMAP_RESET_LSB WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB
-#define RESET_CONTROL_VMC_REMAP_RESET_MASK WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK
-#define RESET_CONTROL_VMC_REMAP_RESET_GET(x) WLAN_RESET_CONTROL_VMC_REMAP_RESET_GET(x)
-#define RESET_CONTROL_VMC_REMAP_RESET_SET(x) WLAN_RESET_CONTROL_VMC_REMAP_RESET_SET(x)
-#define RESET_CONTROL_RST_OUT_MSB WLAN_RESET_CONTROL_RST_OUT_MSB
-#define RESET_CONTROL_RST_OUT_LSB WLAN_RESET_CONTROL_RST_OUT_LSB
-#define RESET_CONTROL_RST_OUT_MASK WLAN_RESET_CONTROL_RST_OUT_MASK
-#define RESET_CONTROL_RST_OUT_GET(x) WLAN_RESET_CONTROL_RST_OUT_GET(x)
-#define RESET_CONTROL_RST_OUT_SET(x) WLAN_RESET_CONTROL_RST_OUT_SET(x)
-#define RESET_CONTROL_COLD_RST_MSB WLAN_RESET_CONTROL_COLD_RST_MSB
-#define RESET_CONTROL_COLD_RST_LSB WLAN_RESET_CONTROL_COLD_RST_LSB
-#define RESET_CONTROL_COLD_RST_MASK WLAN_RESET_CONTROL_COLD_RST_MASK
-#define RESET_CONTROL_COLD_RST_GET(x) WLAN_RESET_CONTROL_COLD_RST_GET(x)
-#define RESET_CONTROL_COLD_RST_SET(x) WLAN_RESET_CONTROL_COLD_RST_SET(x)
-#define RESET_CONTROL_WARM_RST_MSB WLAN_RESET_CONTROL_WARM_RST_MSB
-#define RESET_CONTROL_WARM_RST_LSB WLAN_RESET_CONTROL_WARM_RST_LSB
-#define RESET_CONTROL_WARM_RST_MASK WLAN_RESET_CONTROL_WARM_RST_MASK
-#define RESET_CONTROL_WARM_RST_GET(x) WLAN_RESET_CONTROL_WARM_RST_GET(x)
-#define RESET_CONTROL_WARM_RST_SET(x) WLAN_RESET_CONTROL_WARM_RST_SET(x)
-#define RESET_CONTROL_CPU_WARM_RST_MSB WLAN_RESET_CONTROL_CPU_WARM_RST_MSB
-#define RESET_CONTROL_CPU_WARM_RST_LSB WLAN_RESET_CONTROL_CPU_WARM_RST_LSB
-#define RESET_CONTROL_CPU_WARM_RST_MASK WLAN_RESET_CONTROL_CPU_WARM_RST_MASK
-#define RESET_CONTROL_CPU_WARM_RST_GET(x) WLAN_RESET_CONTROL_CPU_WARM_RST_GET(x)
-#define RESET_CONTROL_CPU_WARM_RST_SET(x) WLAN_RESET_CONTROL_CPU_WARM_RST_SET(x)
-#define RESET_CONTROL_MAC_COLD_RST_MSB WLAN_RESET_CONTROL_MAC_COLD_RST_MSB
-#define RESET_CONTROL_MAC_COLD_RST_LSB WLAN_RESET_CONTROL_MAC_COLD_RST_LSB
-#define RESET_CONTROL_MAC_COLD_RST_MASK WLAN_RESET_CONTROL_MAC_COLD_RST_MASK
-#define RESET_CONTROL_MAC_COLD_RST_GET(x) WLAN_RESET_CONTROL_MAC_COLD_RST_GET(x)
-#define RESET_CONTROL_MAC_COLD_RST_SET(x) WLAN_RESET_CONTROL_MAC_COLD_RST_SET(x)
-#define RESET_CONTROL_MAC_WARM_RST_MSB WLAN_RESET_CONTROL_MAC_WARM_RST_MSB
-#define RESET_CONTROL_MAC_WARM_RST_LSB WLAN_RESET_CONTROL_MAC_WARM_RST_LSB
-#define RESET_CONTROL_MAC_WARM_RST_MASK WLAN_RESET_CONTROL_MAC_WARM_RST_MASK
-#define RESET_CONTROL_MAC_WARM_RST_GET(x) WLAN_RESET_CONTROL_MAC_WARM_RST_GET(x)
-#define RESET_CONTROL_MAC_WARM_RST_SET(x) WLAN_RESET_CONTROL_MAC_WARM_RST_SET(x)
-#define RESET_CONTROL_MBOX_RST_MSB WLAN_RESET_CONTROL_MBOX_RST_MSB
-#define RESET_CONTROL_MBOX_RST_LSB WLAN_RESET_CONTROL_MBOX_RST_LSB
-#define RESET_CONTROL_MBOX_RST_MASK WLAN_RESET_CONTROL_MBOX_RST_MASK
-#define RESET_CONTROL_MBOX_RST_GET(x) WLAN_RESET_CONTROL_MBOX_RST_GET(x)
-#define RESET_CONTROL_MBOX_RST_SET(x) WLAN_RESET_CONTROL_MBOX_RST_SET(x)
-#define RESET_CONTROL_UART_RST_MSB WLAN_RESET_CONTROL_UART_RST_MSB
-#define RESET_CONTROL_UART_RST_LSB WLAN_RESET_CONTROL_UART_RST_LSB
-#define RESET_CONTROL_UART_RST_MASK WLAN_RESET_CONTROL_UART_RST_MASK
-#define RESET_CONTROL_UART_RST_GET(x) WLAN_RESET_CONTROL_UART_RST_GET(x)
-#define RESET_CONTROL_UART_RST_SET(x) WLAN_RESET_CONTROL_UART_RST_SET(x)
-#define RESET_CONTROL_SI0_RST_MSB WLAN_RESET_CONTROL_SI0_RST_MSB
-#define RESET_CONTROL_SI0_RST_LSB WLAN_RESET_CONTROL_SI0_RST_LSB
-#define RESET_CONTROL_SI0_RST_MASK WLAN_RESET_CONTROL_SI0_RST_MASK
-#define RESET_CONTROL_SI0_RST_GET(x) WLAN_RESET_CONTROL_SI0_RST_GET(x)
-#define RESET_CONTROL_SI0_RST_SET(x) WLAN_RESET_CONTROL_SI0_RST_SET(x)
-#define CPU_CLOCK_ADDRESS WLAN_CPU_CLOCK_ADDRESS
-#define CPU_CLOCK_OFFSET WLAN_CPU_CLOCK_OFFSET
-#define CPU_CLOCK_STANDARD_MSB WLAN_CPU_CLOCK_STANDARD_MSB
-#define CPU_CLOCK_STANDARD_LSB WLAN_CPU_CLOCK_STANDARD_LSB
-#define CPU_CLOCK_STANDARD_MASK WLAN_CPU_CLOCK_STANDARD_MASK
-#define CPU_CLOCK_STANDARD_GET(x) WLAN_CPU_CLOCK_STANDARD_GET(x)
-#define CPU_CLOCK_STANDARD_SET(x) WLAN_CPU_CLOCK_STANDARD_SET(x)
-#define CLOCK_OUT_ADDRESS WLAN_CLOCK_OUT_ADDRESS
-#define CLOCK_OUT_OFFSET WLAN_CLOCK_OUT_OFFSET
-#define CLOCK_OUT_SELECT_MSB WLAN_CLOCK_OUT_SELECT_MSB
-#define CLOCK_OUT_SELECT_LSB WLAN_CLOCK_OUT_SELECT_LSB
-#define CLOCK_OUT_SELECT_MASK WLAN_CLOCK_OUT_SELECT_MASK
-#define CLOCK_OUT_SELECT_GET(x) WLAN_CLOCK_OUT_SELECT_GET(x)
-#define CLOCK_OUT_SELECT_SET(x) WLAN_CLOCK_OUT_SELECT_SET(x)
-#define CLOCK_CONTROL_ADDRESS WLAN_CLOCK_CONTROL_ADDRESS
-#define CLOCK_CONTROL_OFFSET WLAN_CLOCK_CONTROL_OFFSET
-#define CLOCK_CONTROL_LF_CLK32_MSB WLAN_CLOCK_CONTROL_LF_CLK32_MSB
-#define CLOCK_CONTROL_LF_CLK32_LSB WLAN_CLOCK_CONTROL_LF_CLK32_LSB
-#define CLOCK_CONTROL_LF_CLK32_MASK WLAN_CLOCK_CONTROL_LF_CLK32_MASK
-#define CLOCK_CONTROL_LF_CLK32_GET(x) WLAN_CLOCK_CONTROL_LF_CLK32_GET(x)
-#define CLOCK_CONTROL_LF_CLK32_SET(x) WLAN_CLOCK_CONTROL_LF_CLK32_SET(x)
-#define CLOCK_CONTROL_SI0_CLK_MSB WLAN_CLOCK_CONTROL_SI0_CLK_MSB
-#define CLOCK_CONTROL_SI0_CLK_LSB WLAN_CLOCK_CONTROL_SI0_CLK_LSB
-#define CLOCK_CONTROL_SI0_CLK_MASK WLAN_CLOCK_CONTROL_SI0_CLK_MASK
-#define CLOCK_CONTROL_SI0_CLK_GET(x) WLAN_CLOCK_CONTROL_SI0_CLK_GET(x)
-#define CLOCK_CONTROL_SI0_CLK_SET(x) WLAN_CLOCK_CONTROL_SI0_CLK_SET(x)
-#define RESET_CAUSE_ADDRESS WLAN_RESET_CAUSE_ADDRESS
-#define RESET_CAUSE_OFFSET WLAN_RESET_CAUSE_OFFSET
-#define RESET_CAUSE_LAST_MSB WLAN_RESET_CAUSE_LAST_MSB
-#define RESET_CAUSE_LAST_LSB WLAN_RESET_CAUSE_LAST_LSB
-#define RESET_CAUSE_LAST_MASK WLAN_RESET_CAUSE_LAST_MASK
-#define RESET_CAUSE_LAST_GET(x) WLAN_RESET_CAUSE_LAST_GET(x)
-#define RESET_CAUSE_LAST_SET(x) WLAN_RESET_CAUSE_LAST_SET(x)
-#define SYSTEM_SLEEP_ADDRESS WLAN_SYSTEM_SLEEP_ADDRESS
-#define SYSTEM_SLEEP_OFFSET WLAN_SYSTEM_SLEEP_OFFSET
-#define SYSTEM_SLEEP_HOST_IF_MSB WLAN_SYSTEM_SLEEP_HOST_IF_MSB
-#define SYSTEM_SLEEP_HOST_IF_LSB WLAN_SYSTEM_SLEEP_HOST_IF_LSB
-#define SYSTEM_SLEEP_HOST_IF_MASK WLAN_SYSTEM_SLEEP_HOST_IF_MASK
-#define SYSTEM_SLEEP_HOST_IF_GET(x) WLAN_SYSTEM_SLEEP_HOST_IF_GET(x)
-#define SYSTEM_SLEEP_HOST_IF_SET(x) WLAN_SYSTEM_SLEEP_HOST_IF_SET(x)
-#define SYSTEM_SLEEP_MBOX_MSB WLAN_SYSTEM_SLEEP_MBOX_MSB
-#define SYSTEM_SLEEP_MBOX_LSB WLAN_SYSTEM_SLEEP_MBOX_LSB
-#define SYSTEM_SLEEP_MBOX_MASK WLAN_SYSTEM_SLEEP_MBOX_MASK
-#define SYSTEM_SLEEP_MBOX_GET(x) WLAN_SYSTEM_SLEEP_MBOX_GET(x)
-#define SYSTEM_SLEEP_MBOX_SET(x) WLAN_SYSTEM_SLEEP_MBOX_SET(x)
-#define SYSTEM_SLEEP_MAC_IF_MSB WLAN_SYSTEM_SLEEP_MAC_IF_MSB
-#define SYSTEM_SLEEP_MAC_IF_LSB WLAN_SYSTEM_SLEEP_MAC_IF_LSB
-#define SYSTEM_SLEEP_MAC_IF_MASK WLAN_SYSTEM_SLEEP_MAC_IF_MASK
-#define SYSTEM_SLEEP_MAC_IF_GET(x) WLAN_SYSTEM_SLEEP_MAC_IF_GET(x)
-#define SYSTEM_SLEEP_MAC_IF_SET(x) WLAN_SYSTEM_SLEEP_MAC_IF_SET(x)
-#define SYSTEM_SLEEP_LIGHT_MSB WLAN_SYSTEM_SLEEP_LIGHT_MSB
-#define SYSTEM_SLEEP_LIGHT_LSB WLAN_SYSTEM_SLEEP_LIGHT_LSB
-#define SYSTEM_SLEEP_LIGHT_MASK WLAN_SYSTEM_SLEEP_LIGHT_MASK
-#define SYSTEM_SLEEP_LIGHT_GET(x) WLAN_SYSTEM_SLEEP_LIGHT_GET(x)
-#define SYSTEM_SLEEP_LIGHT_SET(x) WLAN_SYSTEM_SLEEP_LIGHT_SET(x)
-#define SYSTEM_SLEEP_DISABLE_MSB WLAN_SYSTEM_SLEEP_DISABLE_MSB
-#define SYSTEM_SLEEP_DISABLE_LSB WLAN_SYSTEM_SLEEP_DISABLE_LSB
-#define SYSTEM_SLEEP_DISABLE_MASK WLAN_SYSTEM_SLEEP_DISABLE_MASK
-#define SYSTEM_SLEEP_DISABLE_GET(x) WLAN_SYSTEM_SLEEP_DISABLE_GET(x)
-#define SYSTEM_SLEEP_DISABLE_SET(x) WLAN_SYSTEM_SLEEP_DISABLE_SET(x)
-#define LPO_INIT_DIVIDEND_INT_ADDRESS WLAN_LPO_INIT_DIVIDEND_INT_ADDRESS
-#define LPO_INIT_DIVIDEND_INT_OFFSET WLAN_LPO_INIT_DIVIDEND_INT_OFFSET
-#define LPO_INIT_DIVIDEND_INT_VALUE_MSB WLAN_LPO_INIT_DIVIDEND_INT_VALUE_MSB
-#define LPO_INIT_DIVIDEND_INT_VALUE_LSB WLAN_LPO_INIT_DIVIDEND_INT_VALUE_LSB
-#define LPO_INIT_DIVIDEND_INT_VALUE_MASK WLAN_LPO_INIT_DIVIDEND_INT_VALUE_MASK
-#define LPO_INIT_DIVIDEND_INT_VALUE_GET(x) WLAN_LPO_INIT_DIVIDEND_INT_VALUE_GET(x)
-#define LPO_INIT_DIVIDEND_INT_VALUE_SET(x) WLAN_LPO_INIT_DIVIDEND_INT_VALUE_SET(x)
-#define LPO_INIT_DIVIDEND_FRACTION_ADDRESS WLAN_LPO_INIT_DIVIDEND_FRACTION_ADDRESS
-#define LPO_INIT_DIVIDEND_FRACTION_OFFSET WLAN_LPO_INIT_DIVIDEND_FRACTION_OFFSET
-#define LPO_INIT_DIVIDEND_FRACTION_VALUE_MSB WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_MSB
-#define LPO_INIT_DIVIDEND_FRACTION_VALUE_LSB WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_LSB
-#define LPO_INIT_DIVIDEND_FRACTION_VALUE_MASK WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_MASK
-#define LPO_INIT_DIVIDEND_FRACTION_VALUE_GET(x) WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_GET(x)
-#define LPO_INIT_DIVIDEND_FRACTION_VALUE_SET(x) WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_SET(x)
-#define LPO_CAL_ADDRESS WLAN_LPO_CAL_ADDRESS
-#define LPO_CAL_OFFSET WLAN_LPO_CAL_OFFSET
-#define LPO_CAL_ENABLE_MSB WLAN_LPO_CAL_ENABLE_MSB
-#define LPO_CAL_ENABLE_LSB WLAN_LPO_CAL_ENABLE_LSB
-#define LPO_CAL_ENABLE_MASK WLAN_LPO_CAL_ENABLE_MASK
-#define LPO_CAL_ENABLE_GET(x) WLAN_LPO_CAL_ENABLE_GET(x)
-#define LPO_CAL_ENABLE_SET(x) WLAN_LPO_CAL_ENABLE_SET(x)
-#define LPO_CAL_COUNT_MSB WLAN_LPO_CAL_COUNT_MSB
-#define LPO_CAL_COUNT_LSB WLAN_LPO_CAL_COUNT_LSB
-#define LPO_CAL_COUNT_MASK WLAN_LPO_CAL_COUNT_MASK
-#define LPO_CAL_COUNT_GET(x) WLAN_LPO_CAL_COUNT_GET(x)
-#define LPO_CAL_COUNT_SET(x) WLAN_LPO_CAL_COUNT_SET(x)
-
-#endif
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h b/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h
deleted file mode 100644
index 5c048ff51b07..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h
+++ /dev/null
@@ -1,162 +0,0 @@
-// ------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-// ------------------------------------------------------------------
-//===================================================================
-// Author(s): ="Atheros"
-//===================================================================
-
-
-#ifndef _RTC_WLAN_REG_REG_H_
-#define _RTC_WLAN_REG_REG_H_
-
-#define WLAN_RESET_CONTROL_ADDRESS 0x00000000
-#define WLAN_RESET_CONTROL_OFFSET 0x00000000
-#define WLAN_RESET_CONTROL_DEBUG_UART_RST_MSB 14
-#define WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB 14
-#define WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK 0x00004000
-#define WLAN_RESET_CONTROL_DEBUG_UART_RST_GET(x) (((x) & WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK) >> WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB)
-#define WLAN_RESET_CONTROL_DEBUG_UART_RST_SET(x) (((x) << WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB) & WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK)
-#define WLAN_RESET_CONTROL_BB_COLD_RST_MSB 13
-#define WLAN_RESET_CONTROL_BB_COLD_RST_LSB 13
-#define WLAN_RESET_CONTROL_BB_COLD_RST_MASK 0x00002000
-#define WLAN_RESET_CONTROL_BB_COLD_RST_GET(x) (((x) & WLAN_RESET_CONTROL_BB_COLD_RST_MASK) >> WLAN_RESET_CONTROL_BB_COLD_RST_LSB)
-#define WLAN_RESET_CONTROL_BB_COLD_RST_SET(x) (((x) << WLAN_RESET_CONTROL_BB_COLD_RST_LSB) & WLAN_RESET_CONTROL_BB_COLD_RST_MASK)
-#define WLAN_RESET_CONTROL_BB_WARM_RST_MSB 12
-#define WLAN_RESET_CONTROL_BB_WARM_RST_LSB 12
-#define WLAN_RESET_CONTROL_BB_WARM_RST_MASK 0x00001000
-#define WLAN_RESET_CONTROL_BB_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_BB_WARM_RST_MASK) >> WLAN_RESET_CONTROL_BB_WARM_RST_LSB)
-#define WLAN_RESET_CONTROL_BB_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_BB_WARM_RST_LSB) & WLAN_RESET_CONTROL_BB_WARM_RST_MASK)
-#define WLAN_RESET_CONTROL_CPU_INIT_RESET_MSB 11
-#define WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB 11
-#define WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK 0x00000800
-#define WLAN_RESET_CONTROL_CPU_INIT_RESET_GET(x) (((x) & WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK) >> WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB)
-#define WLAN_RESET_CONTROL_CPU_INIT_RESET_SET(x) (((x) << WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB) & WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK)
-#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_MSB 10
-#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB 10
-#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK 0x00000400
-#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_GET(x) (((x) & WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK) >> WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB)
-#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_SET(x) (((x) << WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB) & WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK)
-#define WLAN_RESET_CONTROL_RST_OUT_MSB 9
-#define WLAN_RESET_CONTROL_RST_OUT_LSB 9
-#define WLAN_RESET_CONTROL_RST_OUT_MASK 0x00000200
-#define WLAN_RESET_CONTROL_RST_OUT_GET(x) (((x) & WLAN_RESET_CONTROL_RST_OUT_MASK) >> WLAN_RESET_CONTROL_RST_OUT_LSB)
-#define WLAN_RESET_CONTROL_RST_OUT_SET(x) (((x) << WLAN_RESET_CONTROL_RST_OUT_LSB) & WLAN_RESET_CONTROL_RST_OUT_MASK)
-#define WLAN_RESET_CONTROL_COLD_RST_MSB 8
-#define WLAN_RESET_CONTROL_COLD_RST_LSB 8
-#define WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000100
-#define WLAN_RESET_CONTROL_COLD_RST_GET(x) (((x) & WLAN_RESET_CONTROL_COLD_RST_MASK) >> WLAN_RESET_CONTROL_COLD_RST_LSB)
-#define WLAN_RESET_CONTROL_COLD_RST_SET(x) (((x) << WLAN_RESET_CONTROL_COLD_RST_LSB) & WLAN_RESET_CONTROL_COLD_RST_MASK)
-#define WLAN_RESET_CONTROL_WARM_RST_MSB 7
-#define WLAN_RESET_CONTROL_WARM_RST_LSB 7
-#define WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000080
-#define WLAN_RESET_CONTROL_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_WARM_RST_MASK) >> WLAN_RESET_CONTROL_WARM_RST_LSB)
-#define WLAN_RESET_CONTROL_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_WARM_RST_LSB) & WLAN_RESET_CONTROL_WARM_RST_MASK)
-#define WLAN_RESET_CONTROL_CPU_WARM_RST_MSB 6
-#define WLAN_RESET_CONTROL_CPU_WARM_RST_LSB 6
-#define WLAN_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040
-#define WLAN_RESET_CONTROL_CPU_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_CPU_WARM_RST_MASK) >> WLAN_RESET_CONTROL_CPU_WARM_RST_LSB)
-#define WLAN_RESET_CONTROL_CPU_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_CPU_WARM_RST_LSB) & WLAN_RESET_CONTROL_CPU_WARM_RST_MASK)
-#define WLAN_RESET_CONTROL_MAC_COLD_RST_MSB 5
-#define WLAN_RESET_CONTROL_MAC_COLD_RST_LSB 5
-#define WLAN_RESET_CONTROL_MAC_COLD_RST_MASK 0x00000020
-#define WLAN_RESET_CONTROL_MAC_COLD_RST_GET(x) (((x) & WLAN_RESET_CONTROL_MAC_COLD_RST_MASK) >> WLAN_RESET_CONTROL_MAC_COLD_RST_LSB)
-#define WLAN_RESET_CONTROL_MAC_COLD_RST_SET(x) (((x) << WLAN_RESET_CONTROL_MAC_COLD_RST_LSB) & WLAN_RESET_CONTROL_MAC_COLD_RST_MASK)
-#define WLAN_RESET_CONTROL_MAC_WARM_RST_MSB 4
-#define WLAN_RESET_CONTROL_MAC_WARM_RST_LSB 4
-#define WLAN_RESET_CONTROL_MAC_WARM_RST_MASK 0x00000010
-#define WLAN_RESET_CONTROL_MAC_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_MAC_WARM_RST_MASK) >> WLAN_RESET_CONTROL_MAC_WARM_RST_LSB)
-#define WLAN_RESET_CONTROL_MAC_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_MAC_WARM_RST_LSB) & WLAN_RESET_CONTROL_MAC_WARM_RST_MASK)
-#define WLAN_RESET_CONTROL_MBOX_RST_MSB 2
-#define WLAN_RESET_CONTROL_MBOX_RST_LSB 2
-#define WLAN_RESET_CONTROL_MBOX_RST_MASK 0x00000004
-#define WLAN_RESET_CONTROL_MBOX_RST_GET(x) (((x) & WLAN_RESET_CONTROL_MBOX_RST_MASK) >> WLAN_RESET_CONTROL_MBOX_RST_LSB)
-#define WLAN_RESET_CONTROL_MBOX_RST_SET(x) (((x) << WLAN_RESET_CONTROL_MBOX_RST_LSB) & WLAN_RESET_CONTROL_MBOX_RST_MASK)
-#define WLAN_RESET_CONTROL_UART_RST_MSB 1
-#define WLAN_RESET_CONTROL_UART_RST_LSB 1
-#define WLAN_RESET_CONTROL_UART_RST_MASK 0x00000002
-#define WLAN_RESET_CONTROL_UART_RST_GET(x) (((x) & WLAN_RESET_CONTROL_UART_RST_MASK) >> WLAN_RESET_CONTROL_UART_RST_LSB)
-#define WLAN_RESET_CONTROL_UART_RST_SET(x) (((x) << WLAN_RESET_CONTROL_UART_RST_LSB) & WLAN_RESET_CONTROL_UART_RST_MASK)
-#define WLAN_RESET_CONTROL_SI0_RST_MSB 0
-#define WLAN_RESET_CONTROL_SI0_RST_LSB 0
-#define WLAN_RESET_CONTROL_SI0_RST_MASK 0x00000001
-#define WLAN_RESET_CONTROL_SI0_RST_GET(x) (((x) & WLAN_RESET_CONTROL_SI0_RST_MASK) >> WLAN_RESET_CONTROL_SI0_RST_LSB)
-#define WLAN_RESET_CONTROL_SI0_RST_SET(x) (((x) << WLAN_RESET_CONTROL_SI0_RST_LSB) & WLAN_RESET_CONTROL_SI0_RST_MASK)
-
-#define WLAN_CPU_CLOCK_ADDRESS 0x00000020
-#define WLAN_CPU_CLOCK_OFFSET 0x00000020
-#define WLAN_CPU_CLOCK_STANDARD_MSB 1
-#define WLAN_CPU_CLOCK_STANDARD_LSB 0
-#define WLAN_CPU_CLOCK_STANDARD_MASK 0x00000003
-#define WLAN_CPU_CLOCK_STANDARD_GET(x) (((x) & WLAN_CPU_CLOCK_STANDARD_MASK) >> WLAN_CPU_CLOCK_STANDARD_LSB)
-#define WLAN_CPU_CLOCK_STANDARD_SET(x) (((x) << WLAN_CPU_CLOCK_STANDARD_LSB) & WLAN_CPU_CLOCK_STANDARD_MASK)
-
-#define WLAN_CLOCK_CONTROL_ADDRESS 0x00000028
-#define WLAN_CLOCK_CONTROL_OFFSET 0x00000028
-#define WLAN_CLOCK_CONTROL_LF_CLK32_MSB 2
-#define WLAN_CLOCK_CONTROL_LF_CLK32_LSB 2
-#define WLAN_CLOCK_CONTROL_LF_CLK32_MASK 0x00000004
-#define WLAN_CLOCK_CONTROL_LF_CLK32_GET(x) (((x) & WLAN_CLOCK_CONTROL_LF_CLK32_MASK) >> WLAN_CLOCK_CONTROL_LF_CLK32_LSB)
-#define WLAN_CLOCK_CONTROL_LF_CLK32_SET(x) (((x) << WLAN_CLOCK_CONTROL_LF_CLK32_LSB) & WLAN_CLOCK_CONTROL_LF_CLK32_MASK)
-#define WLAN_CLOCK_CONTROL_SI0_CLK_MSB 0
-#define WLAN_CLOCK_CONTROL_SI0_CLK_LSB 0
-#define WLAN_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001
-#define WLAN_CLOCK_CONTROL_SI0_CLK_GET(x) (((x) & WLAN_CLOCK_CONTROL_SI0_CLK_MASK) >> WLAN_CLOCK_CONTROL_SI0_CLK_LSB)
-#define WLAN_CLOCK_CONTROL_SI0_CLK_SET(x) (((x) << WLAN_CLOCK_CONTROL_SI0_CLK_LSB) & WLAN_CLOCK_CONTROL_SI0_CLK_MASK)
-
-#define WLAN_SYSTEM_SLEEP_ADDRESS 0x000000c4
-#define WLAN_SYSTEM_SLEEP_OFFSET 0x000000c4
-#define WLAN_SYSTEM_SLEEP_HOST_IF_MSB 4
-#define WLAN_SYSTEM_SLEEP_HOST_IF_LSB 4
-#define WLAN_SYSTEM_SLEEP_HOST_IF_MASK 0x00000010
-#define WLAN_SYSTEM_SLEEP_HOST_IF_GET(x) (((x) & WLAN_SYSTEM_SLEEP_HOST_IF_MASK) >> WLAN_SYSTEM_SLEEP_HOST_IF_LSB)
-#define WLAN_SYSTEM_SLEEP_HOST_IF_SET(x) (((x) << WLAN_SYSTEM_SLEEP_HOST_IF_LSB) & WLAN_SYSTEM_SLEEP_HOST_IF_MASK)
-#define WLAN_SYSTEM_SLEEP_MBOX_MSB 3
-#define WLAN_SYSTEM_SLEEP_MBOX_LSB 3
-#define WLAN_SYSTEM_SLEEP_MBOX_MASK 0x00000008
-#define WLAN_SYSTEM_SLEEP_MBOX_GET(x) (((x) & WLAN_SYSTEM_SLEEP_MBOX_MASK) >> WLAN_SYSTEM_SLEEP_MBOX_LSB)
-#define WLAN_SYSTEM_SLEEP_MBOX_SET(x) (((x) << WLAN_SYSTEM_SLEEP_MBOX_LSB) & WLAN_SYSTEM_SLEEP_MBOX_MASK)
-#define WLAN_SYSTEM_SLEEP_MAC_IF_MSB 2
-#define WLAN_SYSTEM_SLEEP_MAC_IF_LSB 2
-#define WLAN_SYSTEM_SLEEP_MAC_IF_MASK 0x00000004
-#define WLAN_SYSTEM_SLEEP_MAC_IF_GET(x) (((x) & WLAN_SYSTEM_SLEEP_MAC_IF_MASK) >> WLAN_SYSTEM_SLEEP_MAC_IF_LSB)
-#define WLAN_SYSTEM_SLEEP_MAC_IF_SET(x) (((x) << WLAN_SYSTEM_SLEEP_MAC_IF_LSB) & WLAN_SYSTEM_SLEEP_MAC_IF_MASK)
-#define WLAN_SYSTEM_SLEEP_LIGHT_MSB 1
-#define WLAN_SYSTEM_SLEEP_LIGHT_LSB 1
-#define WLAN_SYSTEM_SLEEP_LIGHT_MASK 0x00000002
-#define WLAN_SYSTEM_SLEEP_LIGHT_GET(x) (((x) & WLAN_SYSTEM_SLEEP_LIGHT_MASK) >> WLAN_SYSTEM_SLEEP_LIGHT_LSB)
-#define WLAN_SYSTEM_SLEEP_LIGHT_SET(x) (((x) << WLAN_SYSTEM_SLEEP_LIGHT_LSB) & WLAN_SYSTEM_SLEEP_LIGHT_MASK)
-#define WLAN_SYSTEM_SLEEP_DISABLE_MSB 0
-#define WLAN_SYSTEM_SLEEP_DISABLE_LSB 0
-#define WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001
-#define WLAN_SYSTEM_SLEEP_DISABLE_GET(x) (((x) & WLAN_SYSTEM_SLEEP_DISABLE_MASK) >> WLAN_SYSTEM_SLEEP_DISABLE_LSB)
-#define WLAN_SYSTEM_SLEEP_DISABLE_SET(x) (((x) << WLAN_SYSTEM_SLEEP_DISABLE_LSB) & WLAN_SYSTEM_SLEEP_DISABLE_MASK)
-
-#define WLAN_LPO_CAL_ADDRESS 0x000000e0
-#define WLAN_LPO_CAL_OFFSET 0x000000e0
-#define WLAN_LPO_CAL_ENABLE_MSB 20
-#define WLAN_LPO_CAL_ENABLE_LSB 20
-#define WLAN_LPO_CAL_ENABLE_MASK 0x00100000
-#define WLAN_LPO_CAL_ENABLE_GET(x) (((x) & WLAN_LPO_CAL_ENABLE_MASK) >> WLAN_LPO_CAL_ENABLE_LSB)
-#define WLAN_LPO_CAL_ENABLE_SET(x) (((x) << WLAN_LPO_CAL_ENABLE_LSB) & WLAN_LPO_CAL_ENABLE_MASK)
-#define WLAN_LPO_CAL_COUNT_MSB 19
-#define WLAN_LPO_CAL_COUNT_LSB 0
-#define WLAN_LPO_CAL_COUNT_MASK 0x000fffff
-#define WLAN_LPO_CAL_COUNT_GET(x) (((x) & WLAN_LPO_CAL_COUNT_MASK) >> WLAN_LPO_CAL_COUNT_LSB)
-#define WLAN_LPO_CAL_COUNT_SET(x) (((x) << WLAN_LPO_CAL_COUNT_LSB) & WLAN_LPO_CAL_COUNT_MASK)
-
-#endif /* _RTC_WLAN_REG_H_ */
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h b/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h
deleted file mode 100644
index 302b20bc1bad..000000000000
--- a/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// ------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-// ------------------------------------------------------------------
-//===================================================================
-// Author(s): ="Atheros"
-//===================================================================
-
-
-#ifndef _UART_REG_REG_H_
-#define _UART_REG_REG_H_
-
-#define UART_CLKDIV_ADDRESS 0x00000008
-#define UART_CLKDIV_OFFSET 0x00000008
-#define UART_CLKDIV_CLK_SCALE_MSB 23
-#define UART_CLKDIV_CLK_SCALE_LSB 16
-#define UART_CLKDIV_CLK_SCALE_MASK 0x00ff0000
-#define UART_CLKDIV_CLK_SCALE_GET(x) (((x) & UART_CLKDIV_CLK_SCALE_MASK) >> UART_CLKDIV_CLK_SCALE_LSB)
-#define UART_CLKDIV_CLK_SCALE_SET(x) (((x) << UART_CLKDIV_CLK_SCALE_LSB) & UART_CLKDIV_CLK_SCALE_MASK)
-#define UART_CLKDIV_CLK_STEP_MSB 15
-#define UART_CLKDIV_CLK_STEP_LSB 0
-#define UART_CLKDIV_CLK_STEP_MASK 0x0000ffff
-#define UART_CLKDIV_CLK_STEP_GET(x) (((x) & UART_CLKDIV_CLK_STEP_MASK) >> UART_CLKDIV_CLK_STEP_LSB)
-#define UART_CLKDIV_CLK_STEP_SET(x) (((x) << UART_CLKDIV_CLK_STEP_LSB) & UART_CLKDIV_CLK_STEP_MASK)
-
-#endif /* _UART_REG_H_ */
diff --git a/drivers/staging/ath6kl/include/common/athdefs.h b/drivers/staging/ath6kl/include/common/athdefs.h
deleted file mode 100644
index 74922481e065..000000000000
--- a/drivers/staging/ath6kl/include/common/athdefs.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="athdefs.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef __ATHDEFS_H__
-#define __ATHDEFS_H__
-
-/*
- * This file contains definitions that may be used across both
- * Host and Target software. Nothing here is module-dependent
- * or platform-dependent.
- */
-
-/*
- * Generic error codes that can be used by hw, sta, ap, sim, dk
- * and any other environments.
- * Feel free to add any more non-zero codes that you need.
- */
-
-#define A_ERROR (-1) /* Generic error return */
-#define A_DEVICE_NOT_FOUND 1 /* not able to find PCI device */
-#define A_NO_MEMORY 2 /* not able to allocate memory,
- * not avail#defineable */
-#define A_MEMORY_NOT_AVAIL 3 /* memory region is not free for
- * mapping */
-#define A_NO_FREE_DESC 4 /* no free descriptors available */
-#define A_BAD_ADDRESS 5 /* address does not match descriptor */
-#define A_WIN_DRIVER_ERROR 6 /* used in NT_HW version,
- * if problem at init */
-#define A_REGS_NOT_MAPPED 7 /* registers not correctly mapped */
-#define A_EPERM 8 /* Not superuser */
-#define A_EACCES 0 /* Access denied */
-#define A_ENOENT 10 /* No such entry, search failed, etc. */
-#define A_EEXIST 11 /* The object already exists
- * (can't create) */
-#define A_EFAULT 12 /* Bad address fault */
-#define A_EBUSY 13 /* Object is busy */
-#define A_EINVAL 14 /* Invalid parameter */
-#define A_EMSGSIZE 15 /* Bad message buffer length */
-#define A_ECANCELED 16 /* Operation canceled */
-#define A_ENOTSUP 17 /* Operation not supported */
-#define A_ECOMM 18 /* Communication error on send */
-#define A_EPROTO 19 /* Protocol error */
-#define A_ENODEV 20 /* No such device */
-#define A_EDEVNOTUP 21 /* device is not UP */
-#define A_NO_RESOURCE 22 /* No resources for
- * requested operation */
-#define A_HARDWARE 23 /* Hardware failure */
-#define A_PENDING 24 /* Asynchronous routine; will send up
- * results later
- * (typically in callback) */
-#define A_EBADCHANNEL 25 /* The channel cannot be used */
-#define A_DECRYPT_ERROR 26 /* Decryption error */
-#define A_PHY_ERROR 27 /* RX PHY error */
-#define A_CONSUMED 28 /* Object was consumed */
-
-#endif /* __ATHDEFS_H__ */
diff --git a/drivers/staging/ath6kl/include/common/bmi_msg.h b/drivers/staging/ath6kl/include/common/bmi_msg.h
deleted file mode 100644
index 84e8db569a9f..000000000000
--- a/drivers/staging/ath6kl/include/common/bmi_msg.h
+++ /dev/null
@@ -1,233 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef __BMI_MSG_H__
-#define __BMI_MSG_H__
-
-/*
- * Bootloader Messaging Interface (BMI)
- *
- * BMI is a very simple messaging interface used during initialization
- * to read memory, write memory, execute code, and to define an
- * application entry PC.
- *
- * It is used to download an application to AR6K, to provide
- * patches to code that is already resident on AR6K, and generally
- * to examine and modify state. The Host has an opportunity to use
- * BMI only once during bootup. Once the Host issues a BMI_DONE
- * command, this opportunity ends.
- *
- * The Host writes BMI requests to mailbox0, and reads BMI responses
- * from mailbox0. BMI requests all begin with a command
- * (see below for specific commands), and are followed by
- * command-specific data.
- *
- * Flow control:
- * The Host can only issue a command once the Target gives it a
- * "BMI Command Credit", using AR6K Counter #4. As soon as the
- * Target has completed a command, it issues another BMI Command
- * Credit (so the Host can issue the next command).
- *
- * BMI handles all required Target-side cache flushing.
- */
-
-
-/* Maximum data size used for BMI transfers */
-#define BMI_DATASZ_MAX 256
-
-/* BMI Commands */
-
-#define BMI_NO_COMMAND 0
-
-#define BMI_DONE 1
- /*
- * Semantics: Host is done using BMI
- * Request format:
- * u32 command (BMI_DONE)
- * Response format: none
- */
-
-#define BMI_READ_MEMORY 2
- /*
- * Semantics: Host reads AR6K memory
- * Request format:
- * u32 command (BMI_READ_MEMORY)
- * u32 address
- * u32 length, at most BMI_DATASZ_MAX
- * Response format:
- * u8 data[length]
- */
-
-#define BMI_WRITE_MEMORY 3
- /*
- * Semantics: Host writes AR6K memory
- * Request format:
- * u32 command (BMI_WRITE_MEMORY)
- * u32 address
- * u32 length, at most BMI_DATASZ_MAX
- * u8 data[length]
- * Response format: none
- */
-
-#define BMI_EXECUTE 4
- /*
- * Semantics: Causes AR6K to execute code
- * Request format:
- * u32 command (BMI_EXECUTE)
- * u32 address
- * u32 parameter
- * Response format:
- * u32 return value
- */
-
-#define BMI_SET_APP_START 5
- /*
- * Semantics: Set Target application starting address
- * Request format:
- * u32 command (BMI_SET_APP_START)
- * u32 address
- * Response format: none
- */
-
-#define BMI_READ_SOC_REGISTER 6
- /*
- * Semantics: Read a 32-bit Target SOC register.
- * Request format:
- * u32 command (BMI_READ_REGISTER)
- * u32 address
- * Response format:
- * u32 value
- */
-
-#define BMI_WRITE_SOC_REGISTER 7
- /*
- * Semantics: Write a 32-bit Target SOC register.
- * Request format:
- * u32 command (BMI_WRITE_REGISTER)
- * u32 address
- * u32 value
- *
- * Response format: none
- */
-
-#define BMI_GET_TARGET_ID 8
-#define BMI_GET_TARGET_INFO 8
- /*
- * Semantics: Fetch the 4-byte Target information
- * Request format:
- * u32 command (BMI_GET_TARGET_ID/INFO)
- * Response format1 (old firmware):
- * u32 TargetVersionID
- * Response format2 (newer firmware):
- * u32 TARGET_VERSION_SENTINAL
- * struct bmi_target_info;
- */
-
-PREPACK struct bmi_target_info {
- u32 target_info_byte_count; /* size of this structure */
- u32 target_ver; /* Target Version ID */
- u32 target_type; /* Target type */
-} POSTPACK;
-#define TARGET_VERSION_SENTINAL 0xffffffff
-#define TARGET_TYPE_AR6001 1
-#define TARGET_TYPE_AR6002 2
-#define TARGET_TYPE_AR6003 3
-
-
-#define BMI_ROMPATCH_INSTALL 9
- /*
- * Semantics: Install a ROM Patch.
- * Request format:
- * u32 command (BMI_ROMPATCH_INSTALL)
- * u32 Target ROM Address
- * u32 Target RAM Address or Value (depending on Target Type)
- * u32 Size, in bytes
- * u32 Activate? 1-->activate;
- * 0-->install but do not activate
- * Response format:
- * u32 PatchID
- */
-
-#define BMI_ROMPATCH_UNINSTALL 10
- /*
- * Semantics: Uninstall a previously-installed ROM Patch,
- * automatically deactivating, if necessary.
- * Request format:
- * u32 command (BMI_ROMPATCH_UNINSTALL)
- * u32 PatchID
- *
- * Response format: none
- */
-
-#define BMI_ROMPATCH_ACTIVATE 11
- /*
- * Semantics: Activate a list of previously-installed ROM Patches.
- * Request format:
- * u32 command (BMI_ROMPATCH_ACTIVATE)
- * u32 rompatch_count
- * u32 PatchID[rompatch_count]
- *
- * Response format: none
- */
-
-#define BMI_ROMPATCH_DEACTIVATE 12
- /*
- * Semantics: Deactivate a list of active ROM Patches.
- * Request format:
- * u32 command (BMI_ROMPATCH_DEACTIVATE)
- * u32 rompatch_count
- * u32 PatchID[rompatch_count]
- *
- * Response format: none
- */
-
-
-#define BMI_LZ_STREAM_START 13
- /*
- * Semantics: Begin an LZ-compressed stream of input
- * which is to be uncompressed by the Target to an
- * output buffer at address. The output buffer must
- * be sufficiently large to hold the uncompressed
- * output from the compressed input stream. This BMI
- * command should be followed by a series of 1 or more
- * BMI_LZ_DATA commands.
- * u32 command (BMI_LZ_STREAM_START)
- * u32 address
- * Note: Not supported on all versions of ROM firmware.
- */
-
-#define BMI_LZ_DATA 14
- /*
- * Semantics: Host writes AR6K memory with LZ-compressed
- * data which is uncompressed by the Target. This command
- * must be preceded by a BMI_LZ_STREAM_START command. A series
- * of BMI_LZ_DATA commands are considered part of a single
- * input stream until another BMI_LZ_STREAM_START is issued.
- * Request format:
- * u32 command (BMI_LZ_DATA)
- * u32 length (of compressed data),
- * at most BMI_DATASZ_MAX
- * u8 CompressedData[length]
- * Response format: none
- * Note: Not supported on all versions of ROM firmware.
- */
-
-#endif /* __BMI_MSG_H__ */
diff --git a/drivers/staging/ath6kl/include/common/cnxmgmt.h b/drivers/staging/ath6kl/include/common/cnxmgmt.h
deleted file mode 100644
index 7a902cb54831..000000000000
--- a/drivers/staging/ath6kl/include/common/cnxmgmt.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="cnxmgmt.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef _CNXMGMT_H_
-#define _CNXMGMT_H_
-
-typedef enum {
- CM_CONNECT_WITHOUT_SCAN = 0x0001,
- CM_CONNECT_ASSOC_POLICY_USER = 0x0002,
- CM_CONNECT_SEND_REASSOC = 0x0004,
- CM_CONNECT_WITHOUT_ROAMTABLE_UPDATE = 0x0008,
- CM_CONNECT_DO_WPA_OFFLOAD = 0x0010,
- CM_CONNECT_DO_NOT_DEAUTH = 0x0020,
-} CM_CONNECT_TYPE;
-
-#endif /* _CNXMGMT_H_ */
diff --git a/drivers/staging/ath6kl/include/common/dbglog.h b/drivers/staging/ath6kl/include/common/dbglog.h
deleted file mode 100644
index 5566e568b83d..000000000000
--- a/drivers/staging/ath6kl/include/common/dbglog.h
+++ /dev/null
@@ -1,126 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="dbglog.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef _DBGLOG_H_
-#define _DBGLOG_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define DBGLOG_TIMESTAMP_OFFSET 0
-#define DBGLOG_TIMESTAMP_MASK 0x0000FFFF /* Bit 0-15. Contains bit
- 8-23 of the LF0 timer */
-#define DBGLOG_DBGID_OFFSET 16
-#define DBGLOG_DBGID_MASK 0x03FF0000 /* Bit 16-25 */
-#define DBGLOG_DBGID_NUM_MAX 256 /* Upper limit is width of mask */
-
-#define DBGLOG_MODULEID_OFFSET 26
-#define DBGLOG_MODULEID_MASK 0x3C000000 /* Bit 26-29 */
-#define DBGLOG_MODULEID_NUM_MAX 16 /* Upper limit is width of mask */
-
-/*
- * Please ensure that the definition of any new module introduced is captured
- * between the DBGLOG_MODULEID_START and DBGLOG_MODULEID_END defines. The
- * structure is required for the parser to correctly pick up the values for
- * different modules.
- */
-#define DBGLOG_MODULEID_START
-#define DBGLOG_MODULEID_INF 0
-#define DBGLOG_MODULEID_WMI 1
-#define DBGLOG_MODULEID_MISC 2
-#define DBGLOG_MODULEID_PM 3
-#define DBGLOG_MODULEID_TXRX_MGMTBUF 4
-#define DBGLOG_MODULEID_TXRX_TXBUF 5
-#define DBGLOG_MODULEID_TXRX_RXBUF 6
-#define DBGLOG_MODULEID_WOW 7
-#define DBGLOG_MODULEID_WHAL 8
-#define DBGLOG_MODULEID_DC 9
-#define DBGLOG_MODULEID_CO 10
-#define DBGLOG_MODULEID_RO 11
-#define DBGLOG_MODULEID_CM 12
-#define DBGLOG_MODULEID_MGMT 13
-#define DBGLOG_MODULEID_TMR 14
-#define DBGLOG_MODULEID_BTCOEX 15
-#define DBGLOG_MODULEID_END
-
-#define DBGLOG_NUM_ARGS_OFFSET 30
-#define DBGLOG_NUM_ARGS_MASK 0xC0000000 /* Bit 30-31 */
-#define DBGLOG_NUM_ARGS_MAX 2 /* Upper limit is width of mask */
-
-#define DBGLOG_MODULE_LOG_ENABLE_OFFSET 0
-#define DBGLOG_MODULE_LOG_ENABLE_MASK 0x0000FFFF
-
-#define DBGLOG_REPORTING_ENABLED_OFFSET 16
-#define DBGLOG_REPORTING_ENABLED_MASK 0x00010000
-
-#define DBGLOG_TIMESTAMP_RESOLUTION_OFFSET 17
-#define DBGLOG_TIMESTAMP_RESOLUTION_MASK 0x000E0000
-
-#define DBGLOG_REPORT_SIZE_OFFSET 20
-#define DBGLOG_REPORT_SIZE_MASK 0x3FF00000
-
-#define DBGLOG_LOG_BUFFER_SIZE 1500
-#define DBGLOG_DBGID_DEFINITION_LEN_MAX 90
-
-PREPACK struct dbglog_buf_s {
- struct dbglog_buf_s *next;
- u8 *buffer;
- u32 bufsize;
- u32 length;
- u32 count;
- u32 free;
-} POSTPACK;
-
-PREPACK struct dbglog_hdr_s {
- struct dbglog_buf_s *dbuf;
- u32 dropped;
-} POSTPACK;
-
-PREPACK struct dbglog_config_s {
- u32 cfgvalid; /* Mask with valid config bits */
- union {
- /* TODO: Take care of endianness */
- struct {
- u32 mmask:16; /* Mask of modules with logging on */
- u32 rep:1; /* Reporting enabled or not */
- u32 tsr:3; /* Time stamp resolution. Def: 1 ms */
- u32 size:10; /* Report size in number of messages */
- u32 reserved:2;
- } dbglog_config;
-
- u32 value;
- } u;
-} POSTPACK;
-
-#define cfgmmask u.dbglog_config.mmask
-#define cfgrep u.dbglog_config.rep
-#define cfgtsr u.dbglog_config.tsr
-#define cfgsize u.dbglog_config.size
-#define cfgvalue u.value
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DBGLOG_H_ */
diff --git a/drivers/staging/ath6kl/include/common/dbglog_id.h b/drivers/staging/ath6kl/include/common/dbglog_id.h
deleted file mode 100644
index 15ef829cab20..000000000000
--- a/drivers/staging/ath6kl/include/common/dbglog_id.h
+++ /dev/null
@@ -1,558 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="dbglog_id.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef _DBGLOG_ID_H_
-#define _DBGLOG_ID_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * The nomenclature for the debug identifiers is MODULE_DESCRIPTION.
- * Please ensure that the definition of any new debugid introduced is captured
- * between the <MODULE>_DBGID_DEFINITION_START and
- * <MODULE>_DBGID_DEFINITION_END defines. The structure is required for the
- * parser to correctly pick up the values for different debug identifiers.
- */
-
-/* INF debug identifier definitions */
-#define INF_DBGID_DEFINITION_START
-#define INF_ASSERTION_FAILED 1
-#define INF_TARGET_ID 2
-#define INF_DBGID_DEFINITION_END
-
-/* WMI debug identifier definitions */
-#define WMI_DBGID_DEFINITION_START
-#define WMI_CMD_RX_XTND_PKT_TOO_SHORT 1
-#define WMI_EXTENDED_CMD_NOT_HANDLED 2
-#define WMI_CMD_RX_PKT_TOO_SHORT 3
-#define WMI_CALLING_WMI_EXTENSION_FN 4
-#define WMI_CMD_NOT_HANDLED 5
-#define WMI_IN_SYNC 6
-#define WMI_TARGET_WMI_SYNC_CMD 7
-#define WMI_SET_SNR_THRESHOLD_PARAMS 8
-#define WMI_SET_RSSI_THRESHOLD_PARAMS 9
-#define WMI_SET_LQ_TRESHOLD_PARAMS 10
-#define WMI_TARGET_CREATE_PSTREAM_CMD 11
-#define WMI_WI_DTM_INUSE 12
-#define WMI_TARGET_DELETE_PSTREAM_CMD 13
-#define WMI_TARGET_IMPLICIT_DELETE_PSTREAM_CMD 14
-#define WMI_TARGET_GET_BIT_RATE_CMD 15
-#define WMI_GET_RATE_MASK_CMD_FIX_RATE_MASK_IS 16
-#define WMI_TARGET_GET_AVAILABLE_CHANNELS_CMD 17
-#define WMI_TARGET_GET_TX_PWR_CMD 18
-#define WMI_FREE_EVBUF_WMIBUF 19
-#define WMI_FREE_EVBUF_DATABUF 20
-#define WMI_FREE_EVBUF_BADFLAG 21
-#define WMI_HTC_RX_ERROR_DATA_PACKET 22
-#define WMI_HTC_RX_SYNC_PAUSING_FOR_MBOX 23
-#define WMI_INCORRECT_WMI_DATA_HDR_DROPPING_PKT 24
-#define WMI_SENDING_READY_EVENT 25
-#define WMI_SETPOWER_MDOE_TO_MAXPERF 26
-#define WMI_SETPOWER_MDOE_TO_REC 27
-#define WMI_BSSINFO_EVENT_FROM 28
-#define WMI_TARGET_GET_STATS_CMD 29
-#define WMI_SENDING_SCAN_COMPLETE_EVENT 30
-#define WMI_SENDING_RSSI_INDB_THRESHOLD_EVENT 31
-#define WMI_SENDING_RSSI_INDBM_THRESHOLD_EVENT 32
-#define WMI_SENDING_LINK_QUALITY_THRESHOLD_EVENT 33
-#define WMI_SENDING_ERROR_REPORT_EVENT 34
-#define WMI_SENDING_CAC_EVENT 35
-#define WMI_TARGET_GET_ROAM_TABLE_CMD 36
-#define WMI_TARGET_GET_ROAM_DATA_CMD 37
-#define WMI_SENDING_GPIO_INTR_EVENT 38
-#define WMI_SENDING_GPIO_ACK_EVENT 39
-#define WMI_SENDING_GPIO_DATA_EVENT 40
-#define WMI_CMD_RX 41
-#define WMI_CMD_RX_XTND 42
-#define WMI_EVENT_SEND 43
-#define WMI_EVENT_SEND_XTND 44
-#define WMI_CMD_PARAMS_DUMP_START 45
-#define WMI_CMD_PARAMS_DUMP_END 46
-#define WMI_CMD_PARAMS 47
-#define WMI_DBGID_DEFINITION_END
-
-/* MISC debug identifier definitions */
-#define MISC_DBGID_DEFINITION_START
-#define MISC_WLAN_SCHEDULER_EVENT_REGISTER_ERROR 1
-#define TLPM_INIT 2
-#define TLPM_FILTER_POWER_STATE 3
-#define TLPM_NOTIFY_NOT_IDLE 4
-#define TLPM_TIMEOUT_IDLE_HANDLER 5
-#define TLPM_TIMEOUT_WAKEUP_HANDLER 6
-#define TLPM_WAKEUP_SIGNAL_HANDLER 7
-#define TLPM_UNEXPECTED_GPIO_INTR_ERROR 8
-#define TLPM_BREAK_ON_NOT_RECEIVED_ERROR 9
-#define TLPM_BREAK_OFF_NOT_RECIVED_ERROR 10
-#define TLPM_ACK_GPIO_INTR 11
-#define TLPM_ON 12
-#define TLPM_OFF 13
-#define TLPM_WAKEUP_FROM_HOST 14
-#define TLPM_WAKEUP_FROM_BT 15
-#define TLPM_TX_BREAK_RECIVED 16
-#define TLPM_IDLE_TIMER_NOT_RUNNING 17
-#define MISC_DBGID_DEFINITION_END
-
-/* TXRX debug identifier definitions */
-#define TXRX_TXBUF_DBGID_DEFINITION_START
-#define TXRX_TXBUF_ALLOCATE_BUF 1
-#define TXRX_TXBUF_QUEUE_BUF_TO_MBOX 2
-#define TXRX_TXBUF_QUEUE_BUF_TO_TXQ 3
-#define TXRX_TXBUF_TXQ_DEPTH 4
-#define TXRX_TXBUF_IBSS_QUEUE_TO_SFQ 5
-#define TXRX_TXBUF_IBSS_QUEUE_TO_TXQ_FRM_SFQ 6
-#define TXRX_TXBUF_INITIALIZE_TIMER 7
-#define TXRX_TXBUF_ARM_TIMER 8
-#define TXRX_TXBUF_DISARM_TIMER 9
-#define TXRX_TXBUF_UNINITIALIZE_TIMER 10
-#define TXRX_TXBUF_DBGID_DEFINITION_END
-
-#define TXRX_RXBUF_DBGID_DEFINITION_START
-#define TXRX_RXBUF_ALLOCATE_BUF 1
-#define TXRX_RXBUF_QUEUE_TO_HOST 2
-#define TXRX_RXBUF_QUEUE_TO_WLAN 3
-#define TXRX_RXBUF_ZERO_LEN_BUF 4
-#define TXRX_RXBUF_QUEUE_TO_HOST_LASTBUF_IN_RXCHAIN 5
-#define TXRX_RXBUF_LASTBUF_IN_RXCHAIN_ZEROBUF 6
-#define TXRX_RXBUF_QUEUE_EMPTY_QUEUE_TO_WLAN 7
-#define TXRX_RXBUF_SEND_TO_RECV_MGMT 8
-#define TXRX_RXBUF_SEND_TO_IEEE_LAYER 9
-#define TXRX_RXBUF_REQUEUE_ERROR 10
-#define TXRX_RXBUF_DBGID_DEFINITION_END
-
-#define TXRX_MGMTBUF_DBGID_DEFINITION_START
-#define TXRX_MGMTBUF_ALLOCATE_BUF 1
-#define TXRX_MGMTBUF_ALLOCATE_SM_BUF 2
-#define TXRX_MGMTBUF_ALLOCATE_RMBUF 3
-#define TXRX_MGMTBUF_GET_BUF 4
-#define TXRX_MGMTBUF_GET_SM_BUF 5
-#define TXRX_MGMTBUF_QUEUE_BUF_TO_TXQ 6
-#define TXRX_MGMTBUF_REAPED_BUF 7
-#define TXRX_MGMTBUF_REAPED_SM_BUF 8
-#define TXRX_MGMTBUF_WAIT_FOR_TXQ_DRAIN 9
-#define TXRX_MGMTBUF_WAIT_FOR_TXQ_SFQ_DRAIN 10
-#define TXRX_MGMTBUF_ENQUEUE_INTO_DATA_SFQ 11
-#define TXRX_MGMTBUF_DEQUEUE_FROM_DATA_SFQ 12
-#define TXRX_MGMTBUF_PAUSE_DATA_TXQ 13
-#define TXRX_MGMTBUF_RESUME_DATA_TXQ 14
-#define TXRX_MGMTBUF_WAIT_FORTXQ_DRAIN_TIMEOUT 15
-#define TXRX_MGMTBUF_DRAINQ 16
-#define TXRX_MGMTBUF_INDICATE_Q_DRAINED 17
-#define TXRX_MGMTBUF_ENQUEUE_INTO_HW_SFQ 18
-#define TXRX_MGMTBUF_DEQUEUE_FROM_HW_SFQ 19
-#define TXRX_MGMTBUF_PAUSE_HW_TXQ 20
-#define TXRX_MGMTBUF_RESUME_HW_TXQ 21
-#define TXRX_MGMTBUF_TEAR_DOWN_BA 22
-#define TXRX_MGMTBUF_PROCESS_ADDBA_REQ 23
-#define TXRX_MGMTBUF_PROCESS_DELBA 24
-#define TXRX_MGMTBUF_PERFORM_BA 25
-#define TXRX_MGMTBUF_WLAN_RESET_ON_ERROR 26
-#define TXRX_MGMTBUF_DBGID_DEFINITION_END
-
-/* PM (Power Module) debug identifier definitions */
-#define PM_DBGID_DEFINITION_START
-#define PM_INIT 1
-#define PM_ENABLE 2
-#define PM_SET_STATE 3
-#define PM_SET_POWERMODE 4
-#define PM_CONN_NOTIFY 5
-#define PM_REF_COUNT_NEGATIVE 6
-#define PM_INFRA_STA_APSD_ENABLE 7
-#define PM_INFRA_STA_UPDATE_APSD_STATE 8
-#define PM_CHAN_OP_REQ 9
-#define PM_SET_MY_BEACON_POLICY 10
-#define PM_SET_ALL_BEACON_POLICY 11
-#define PM_INFRA_STA_SET_PM_PARAMS1 12
-#define PM_INFRA_STA_SET_PM_PARAMS2 13
-#define PM_ADHOC_SET_PM_CAPS_FAIL 14
-#define PM_ADHOC_UNKNOWN_IBSS_ATTRIB_ID 15
-#define PM_ADHOC_SET_PM_PARAMS 16
-#define PM_ADHOC_STATE1 18
-#define PM_ADHOC_STATE2 19
-#define PM_ADHOC_CONN_MAP 20
-#define PM_FAKE_SLEEP 21
-#define PM_AP_STATE1 22
-#define PM_AP_SET_PM_PARAMS 23
-#define PM_DBGID_DEFINITION_END
-
-/* Wake on Wireless debug identifier definitions */
-#define WOW_DBGID_DEFINITION_START
-#define WOW_INIT 1
-#define WOW_GET_CONFIG_DSET 2
-#define WOW_NO_CONFIG_DSET 3
-#define WOW_INVALID_CONFIG_DSET 4
-#define WOW_USE_DEFAULT_CONFIG 5
-#define WOW_SETUP_GPIO 6
-#define WOW_INIT_DONE 7
-#define WOW_SET_GPIO_PIN 8
-#define WOW_CLEAR_GPIO_PIN 9
-#define WOW_SET_WOW_MODE_CMD 10
-#define WOW_SET_HOST_MODE_CMD 11
-#define WOW_ADD_WOW_PATTERN_CMD 12
-#define WOW_NEW_WOW_PATTERN_AT_INDEX 13
-#define WOW_DEL_WOW_PATTERN_CMD 14
-#define WOW_LIST_CONTAINS_PATTERNS 15
-#define WOW_GET_WOW_LIST_CMD 16
-#define WOW_INVALID_FILTER_ID 17
-#define WOW_INVALID_FILTER_LISTID 18
-#define WOW_NO_VALID_FILTER_AT_ID 19
-#define WOW_NO_VALID_LIST_AT_ID 20
-#define WOW_NUM_PATTERNS_EXCEEDED 21
-#define WOW_NUM_LISTS_EXCEEDED 22
-#define WOW_GET_WOW_STATS 23
-#define WOW_CLEAR_WOW_STATS 24
-#define WOW_WAKEUP_HOST 25
-#define WOW_EVENT_WAKEUP_HOST 26
-#define WOW_EVENT_DISCARD 27
-#define WOW_PATTERN_MATCH 28
-#define WOW_PATTERN_NOT_MATCH 29
-#define WOW_PATTERN_NOT_MATCH_OFFSET 30
-#define WOW_DISABLED_HOST_ASLEEP 31
-#define WOW_ENABLED_HOST_ASLEEP_NO_PATTERNS 32
-#define WOW_ENABLED_HOST_ASLEEP_NO_MATCH_FOUND 33
-#define WOW_DBGID_DEFINITION_END
-
-/* WHAL debug identifier definitions */
-#define WHAL_DBGID_DEFINITION_START
-#define WHAL_ERROR_ANI_CONTROL 1
-#define WHAL_ERROR_CHIP_TEST1 2
-#define WHAL_ERROR_CHIP_TEST2 3
-#define WHAL_ERROR_EEPROM_CHECKSUM 4
-#define WHAL_ERROR_EEPROM_MACADDR 5
-#define WHAL_ERROR_INTERRUPT_HIU 6
-#define WHAL_ERROR_KEYCACHE_RESET 7
-#define WHAL_ERROR_KEYCACHE_SET 8
-#define WHAL_ERROR_KEYCACHE_TYPE 9
-#define WHAL_ERROR_KEYCACHE_TKIPENTRY 10
-#define WHAL_ERROR_KEYCACHE_WEPLENGTH 11
-#define WHAL_ERROR_PHY_INVALID_CHANNEL 12
-#define WHAL_ERROR_POWER_AWAKE 13
-#define WHAL_ERROR_POWER_SET 14
-#define WHAL_ERROR_RECV_STOPDMA 15
-#define WHAL_ERROR_RECV_STOPPCU 16
-#define WHAL_ERROR_RESET_CHANNF1 17
-#define WHAL_ERROR_RESET_CHANNF2 18
-#define WHAL_ERROR_RESET_PM 19
-#define WHAL_ERROR_RESET_OFFSETCAL 20
-#define WHAL_ERROR_RESET_RFGRANT 21
-#define WHAL_ERROR_RESET_RXFRAME 22
-#define WHAL_ERROR_RESET_STOPDMA 23
-#define WHAL_ERROR_RESET_RECOVER 24
-#define WHAL_ERROR_XMIT_COMPUTE 25
-#define WHAL_ERROR_XMIT_NOQUEUE 26
-#define WHAL_ERROR_XMIT_ACTIVEQUEUE 27
-#define WHAL_ERROR_XMIT_BADTYPE 28
-#define WHAL_ERROR_XMIT_STOPDMA 29
-#define WHAL_ERROR_INTERRUPT_BB_PANIC 30
-#define WHAL_ERROR_RESET_TXIQCAL 31
-#define WHAL_ERROR_PAPRD_MAXGAIN_ABOVE_WINDOW 32
-#define WHAL_DBGID_DEFINITION_END
-
-/* DC debug identifier definitions */
-#define DC_DBGID_DEFINITION_START
-#define DC_SCAN_CHAN_START 1
-#define DC_SCAN_CHAN_FINISH 2
-#define DC_BEACON_RECEIVE7 3
-#define DC_SSID_PROBE_CB 4
-#define DC_SEND_NEXT_SSID_PROBE 5
-#define DC_START_SEARCH 6
-#define DC_CANCEL_SEARCH_CB 7
-#define DC_STOP_SEARCH 8
-#define DC_END_SEARCH 9
-#define DC_MIN_CHDWELL_TIMEOUT 10
-#define DC_START_SEARCH_CANCELED 11
-#define DC_SET_POWER_MODE 12
-#define DC_INIT 13
-#define DC_SEARCH_OPPORTUNITY 14
-#define DC_RECEIVED_ANY_BEACON 15
-#define DC_RECEIVED_MY_BEACON 16
-#define DC_PROFILE_IS_ADHOC_BUT_BSS_IS_INFRA 17
-#define DC_PS_ENABLED_BUT_ATHEROS_IE_ABSENT 18
-#define DC_BSS_ADHOC_CHANNEL_NOT_ALLOWED 19
-#define DC_SET_BEACON_UPDATE 20
-#define DC_BEACON_UPDATE_COMPLETE 21
-#define DC_END_SEARCH_BEACON_UPDATE_COMP_CB 22
-#define DC_BSSINFO_EVENT_DROPPED 23
-#define DC_IEEEPS_ENABLED_BUT_ATIM_ABSENT 24
-#define DC_DBGID_DEFINITION_END
-
-/* CO debug identifier definitions */
-#define CO_DBGID_DEFINITION_START
-#define CO_INIT 1
-#define CO_ACQUIRE_LOCK 2
-#define CO_START_OP1 3
-#define CO_START_OP2 4
-#define CO_DRAIN_TX_COMPLETE_CB 5
-#define CO_CHANGE_CHANNEL_CB 6
-#define CO_RETURN_TO_HOME_CHANNEL 7
-#define CO_FINISH_OP_TIMEOUT 8
-#define CO_OP_END 9
-#define CO_CANCEL_OP 10
-#define CO_CHANGE_CHANNEL 11
-#define CO_RELEASE_LOCK 12
-#define CO_CHANGE_STATE 13
-#define CO_DBGID_DEFINITION_END
-
-/* RO debug identifier definitions */
-#define RO_DBGID_DEFINITION_START
-#define RO_REFRESH_ROAM_TABLE 1
-#define RO_UPDATE_ROAM_CANDIDATE 2
-#define RO_UPDATE_ROAM_CANDIDATE_CB 3
-#define RO_UPDATE_ROAM_CANDIDATE_FINISH 4
-#define RO_REFRESH_ROAM_TABLE_DONE 5
-#define RO_PERIODIC_SEARCH_CB 6
-#define RO_PERIODIC_SEARCH_TIMEOUT 7
-#define RO_INIT 8
-#define RO_BMISS_STATE1 9
-#define RO_BMISS_STATE2 10
-#define RO_SET_PERIODIC_SEARCH_ENABLE 11
-#define RO_SET_PERIODIC_SEARCH_DISABLE 12
-#define RO_ENABLE_SQ_THRESHOLD 13
-#define RO_DISABLE_SQ_THRESHOLD 14
-#define RO_ADD_BSS_TO_ROAM_TABLE 15
-#define RO_SET_PERIODIC_SEARCH_MODE 16
-#define RO_CONFIGURE_SQ_THRESHOLD1 17
-#define RO_CONFIGURE_SQ_THRESHOLD2 18
-#define RO_CONFIGURE_SQ_PARAMS 19
-#define RO_LOW_SIGNAL_QUALITY_EVENT 20
-#define RO_HIGH_SIGNAL_QUALITY_EVENT 21
-#define RO_REMOVE_BSS_FROM_ROAM_TABLE 22
-#define RO_UPDATE_CONNECTION_STATE_METRIC 23
-#define RO_DBGID_DEFINITION_END
-
-/* CM debug identifier definitions */
-#define CM_DBGID_DEFINITION_START
-#define CM_INITIATE_HANDOFF 1
-#define CM_INITIATE_HANDOFF_CB 2
-#define CM_CONNECT_EVENT 3
-#define CM_DISCONNECT_EVENT 4
-#define CM_INIT 5
-#define CM_HANDOFF_SOURCE 6
-#define CM_SET_HANDOFF_TRIGGERS 7
-#define CM_CONNECT_REQUEST 8
-#define CM_CONNECT_REQUEST_CB 9
-#define CM_CONTINUE_SCAN_CB 10
-#define CM_DBGID_DEFINITION_END
-
-
-/* mgmt debug identifier definitions */
-#define MGMT_DBGID_DEFINITION_START
-#define KEYMGMT_CONNECTION_INIT 1
-#define KEYMGMT_CONNECTION_COMPLETE 2
-#define KEYMGMT_CONNECTION_CLOSE 3
-#define KEYMGMT_ADD_KEY 4
-#define MLME_NEW_STATE 5
-#define MLME_CONN_INIT 6
-#define MLME_CONN_COMPLETE 7
-#define MLME_CONN_CLOSE 8
-#define MGMT_DBGID_DEFINITION_END
-
-/* TMR debug identifier definitions */
-#define TMR_DBGID_DEFINITION_START
-#define TMR_HANG_DETECTED 1
-#define TMR_WDT_TRIGGERED 2
-#define TMR_WDT_RESET 3
-#define TMR_HANDLER_ENTRY 4
-#define TMR_HANDLER_EXIT 5
-#define TMR_SAVED_START 6
-#define TMR_SAVED_END 7
-#define TMR_DBGID_DEFINITION_END
-
-/* BTCOEX debug identifier definitions */
-#define BTCOEX_DBGID_DEFINITION_START
-#define BTCOEX_STATUS_CMD 1
-#define BTCOEX_PARAMS_CMD 2
-#define BTCOEX_ANT_CONFIG 3
-#define BTCOEX_COLOCATED_BT_DEVICE 4
-#define BTCOEX_CLOSE_RANGE_SCO_ON 5
-#define BTCOEX_CLOSE_RANGE_SCO_OFF 6
-#define BTCOEX_CLOSE_RANGE_A2DP_ON 7
-#define BTCOEX_CLOSE_RANGE_A2DP_OFF 8
-#define BTCOEX_A2DP_PROTECT_ON 9
-#define BTCOEX_A2DP_PROTECT_OFF 10
-#define BTCOEX_SCO_PROTECT_ON 11
-#define BTCOEX_SCO_PROTECT_OFF 12
-#define BTCOEX_CLOSE_RANGE_DETECTOR_START 13
-#define BTCOEX_CLOSE_RANGE_DETECTOR_STOP 14
-#define BTCOEX_CLOSE_RANGE_TOGGLE 15
-#define BTCOEX_CLOSE_RANGE_TOGGLE_RSSI_LRCNT 16
-#define BTCOEX_CLOSE_RANGE_RSSI_THRESH 17
-#define BTCOEX_CLOSE_RANGE_LOW_RATE_THRESH 18
-#define BTCOEX_PTA_PRI_INTR_HANDLER 19
-#define BTCOEX_PSPOLL_QUEUED 20
-#define BTCOEX_PSPOLL_COMPLETE 21
-#define BTCOEX_DBG_PM_AWAKE 22
-#define BTCOEX_DBG_PM_SLEEP 23
-#define BTCOEX_DBG_SCO_COEX_ON 24
-#define BTCOEX_SCO_DATARECEIVE 25
-#define BTCOEX_INTR_INIT 26
-#define BTCOEX_PTA_PRI_DIFF 27
-#define BTCOEX_TIM_NOTIFICATION 28
-#define BTCOEX_SCO_WAKEUP_ON_DATA 29
-#define BTCOEX_SCO_SLEEP 30
-#define BTCOEX_SET_WEIGHTS 31
-#define BTCOEX_SCO_DATARECEIVE_LATENCY_VAL 32
-#define BTCOEX_SCO_MEASURE_TIME_DIFF 33
-#define BTCOEX_SET_EOL_VAL 34
-#define BTCOEX_OPT_DETECT_HANDLER 35
-#define BTCOEX_SCO_TOGGLE_STATE 36
-#define BTCOEX_SCO_STOMP 37
-#define BTCOEX_NULL_COMP_CALLBACK 38
-#define BTCOEX_RX_INCOMING 39
-#define BTCOEX_RX_INCOMING_CTL 40
-#define BTCOEX_RX_INCOMING_MGMT 41
-#define BTCOEX_RX_INCOMING_DATA 42
-#define BTCOEX_RTS_RECEPTION 43
-#define BTCOEX_FRAME_PRI_LOW_RATE_THRES 44
-#define BTCOEX_PM_FAKE_SLEEP 45
-#define BTCOEX_ACL_COEX_STATUS 46
-#define BTCOEX_ACL_COEX_DETECTION 47
-#define BTCOEX_A2DP_COEX_STATUS 48
-#define BTCOEX_SCO_STATUS 49
-#define BTCOEX_WAKEUP_ON_DATA 50
-#define BTCOEX_DATARECEIVE 51
-#define BTCOEX_GET_MAX_AGGR_SIZE 53
-#define BTCOEX_MAX_AGGR_AVAIL_TIME 54
-#define BTCOEX_DBG_WBTIMER_INTR 55
-#define BTCOEX_DBG_SCO_SYNC 57
-#define BTCOEX_UPLINK_QUEUED_RATE 59
-#define BTCOEX_DBG_UPLINK_ENABLE_EOL 60
-#define BTCOEX_UPLINK_FRAME_DURATION 61
-#define BTCOEX_UPLINK_SET_EOL 62
-#define BTCOEX_DBG_EOL_EXPIRED 63
-#define BTCOEX_DBG_DATA_COMPLETE 64
-#define BTCOEX_UPLINK_QUEUED_TIMESTAMP 65
-#define BTCOEX_DBG_DATA_COMPLETE_TIME 66
-#define BTCOEX_DBG_A2DP_ROLE_IS_SLAVE 67
-#define BTCOEX_DBG_A2DP_ROLE_IS_MASTER 68
-#define BTCOEX_DBG_UPLINK_SEQ_NUM 69
-#define BTCOEX_UPLINK_AGGR_SEQ 70
-#define BTCOEX_DBG_TX_COMP_SEQ_NO 71
-#define BTCOEX_DBG_MAX_AGGR_PAUSE_STATE 72
-#define BTCOEX_DBG_ACL_TRAFFIC 73
-#define BTCOEX_CURR_AGGR_PROP 74
-#define BTCOEX_DBG_SCO_GET_PER_TIME_DIFF 75
-#define BTCOEX_PSPOLL_PROCESS 76
-#define BTCOEX_RETURN_FROM_MAC 77
-#define BTCOEX_FREED_REQUEUED_CNT 78
-#define BTCOEX_DBG_TOGGLE_LOW_RATES 79
-#define BTCOEX_MAC_GOES_TO_SLEEP 80
-#define BTCOEX_DBG_A2DP_NO_SYNC 81
-#define BTCOEX_RETURN_FROM_MAC_HOLD_Q_INFO 82
-#define BTCOEX_RETURN_FROM_MAC_AC 83
-#define BTCOEX_DBG_DTIM_RECV 84
-#define BTCOEX_IS_PRE_UPDATE 86
-#define BTCOEX_ENQUEUED_BIT_MAP 87
-#define BTCOEX_TX_COMPLETE_FIRST_DESC_STATS 88
-#define BTCOEX_UPLINK_DESC 89
-#define BTCOEX_SCO_GET_PER_FIRST_FRM_TIMESTAMP 90
-#define BTCOEX_DBG_RECV_ACK 94
-#define BTCOEX_DBG_ADDBA_INDICATION 95
-#define BTCOEX_TX_COMPLETE_EOL_FAILED 96
-#define BTCOEX_DBG_A2DP_USAGE_COMPLETE 97
-#define BTCOEX_DBG_A2DP_STOMP_FOR_BCN_HANDLER 98
-#define BTCOEX_DBG_A2DP_SYNC_INTR 99
-#define BTCOEX_DBG_A2DP_STOMP_FOR_BCN_RECEPTION 100
-#define BTCOEX_FORM_AGGR_CURR_AGGR 101
-#define BTCOEX_DBG_TOGGLE_A2DP_BURST_CNT 102
-#define BTCOEX_DBG_BT_TRAFFIC 103
-#define BTCOEX_DBG_STOMP_BT_TRAFFIC 104
-#define BTCOEX_RECV_NULL 105
-#define BTCOEX_DBG_A2DP_MASTER_BT_END 106
-#define BTCOEX_DBG_A2DP_BT_START 107
-#define BTCOEX_DBG_A2DP_SLAVE_BT_END 108
-#define BTCOEX_DBG_A2DP_STOMP_BT 109
-#define BTCOEX_DBG_GO_TO_SLEEP 110
-#define BTCOEX_DBG_A2DP_PKT 111
-#define BTCOEX_DBG_A2DP_PSPOLL_DATA_RECV 112
-#define BTCOEX_DBG_A2DP_NULL 113
-#define BTCOEX_DBG_UPLINK_DATA 114
-#define BTCOEX_DBG_A2DP_STOMP_LOW_PRIO_NULL 115
-#define BTCOEX_DBG_ADD_BA_RESP_TIMEOUT 116
-#define BTCOEX_DBG_TXQ_STATE 117
-#define BTCOEX_DBG_ALLOW_SCAN 118
-#define BTCOEX_DBG_SCAN_REQUEST 119
-#define BTCOEX_A2DP_SLEEP 127
-#define BTCOEX_DBG_DATA_ACTIV_TIMEOUT 128
-#define BTCOEX_DBG_SWITCH_TO_PSPOLL_ON_MODE 129
-#define BTCOEX_DBG_SWITCH_TO_PSPOLL_OFF_MODE 130
-#define BTCOEX_DATARECEIVE_AGGR 131
-#define BTCOEX_DBG_DATA_RECV_SLEEPING_PENDING 132
-#define BTCOEX_DBG_DATARESP_TIMEOUT 133
-#define BTCOEX_BDG_BMISS 134
-#define BTCOEX_DBG_DATA_RECV_WAKEUP_TIM 135
-#define BTCOEX_DBG_SECOND_BMISS 136
-#define BTCOEX_DBG_SET_WLAN_STATE 138
-#define BTCOEX_BDG_FIRST_BMISS 139
-#define BTCOEX_DBG_A2DP_CHAN_OP 140
-#define BTCOEX_DBG_A2DP_INTR 141
-#define BTCOEX_DBG_BT_INQUIRY 142
-#define BTCOEX_DBG_BT_INQUIRY_DATA_FETCH 143
-#define BTCOEX_DBG_POST_INQUIRY_FINISH 144
-#define BTCOEX_DBG_SCO_OPT_MODE_TIMER_HANDLER 145
-#define BTCOEX_DBG_NULL_FRAME_SLEEP 146
-#define BTCOEX_DBG_NULL_FRAME_AWAKE 147
-#define BTCOEX_DBG_SET_AGGR_SIZE 152
-#define BTCOEX_DBG_TEAR_BA_TIMEOUT 153
-#define BTCOEX_DBG_MGMT_FRAME_SEQ_NO 154
-#define BTCOEX_DBG_SCO_STOMP_HIGH_PRI 155
-#define BTCOEX_DBG_COLOCATED_BT_DEV 156
-#define BTCOEX_DBG_FE_ANT_TYPE 157
-#define BTCOEX_DBG_BT_INQUIRY_CMD 158
-#define BTCOEX_DBG_SCO_CONFIG 159
-#define BTCOEX_DBG_SCO_PSPOLL_CONFIG 160
-#define BTCOEX_DBG_SCO_OPTMODE_CONFIG 161
-#define BTCOEX_DBG_A2DP_CONFIG 162
-#define BTCOEX_DBG_A2DP_PSPOLL_CONFIG 163
-#define BTCOEX_DBG_A2DP_OPTMODE_CONFIG 164
-#define BTCOEX_DBG_ACLCOEX_CONFIG 165
-#define BTCOEX_DBG_ACLCOEX_PSPOLL_CONFIG 166
-#define BTCOEX_DBG_ACLCOEX_OPTMODE_CONFIG 167
-#define BTCOEX_DBG_DEBUG_CMD 168
-#define BTCOEX_DBG_SET_BT_OPERATING_STATUS 169
-#define BTCOEX_DBG_GET_CONFIG 170
-#define BTCOEX_DBG_GET_STATS 171
-#define BTCOEX_DBG_BT_OPERATING_STATUS 172
-#define BTCOEX_DBG_PERFORM_RECONNECT 173
-#define BTCOEX_DBG_ACL_WLAN_MED 175
-#define BTCOEX_DBG_ACL_BT_MED 176
-#define BTCOEX_DBG_WLAN_CONNECT 177
-#define BTCOEX_DBG_A2DP_DUAL_START 178
-#define BTCOEX_DBG_PMAWAKE_NOTIFY 179
-#define BTCOEX_DBG_BEACON_SCAN_ENABLE 180
-#define BTCOEX_DBG_BEACON_SCAN_DISABLE 181
-#define BTCOEX_DBG_RX_NOTIFY 182
-#define BTCOEX_SCO_GET_PER_SECOND_FRM_TIMESTAMP 183
-#define BTCOEX_DBG_TXQ_DETAILS 184
-#define BTCOEX_DBG_SCO_STOMP_LOW_PRI 185
-#define BTCOEX_DBG_A2DP_FORCE_SCAN 186
-#define BTCOEX_DBG_DTIM_STOMP_COMP 187
-#define BTCOEX_ACL_PRESENCE_TIMER 188
-#define BTCOEX_DBGID_DEFINITION_END
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DBGLOG_ID_H_ */
diff --git a/drivers/staging/ath6kl/include/common/discovery.h b/drivers/staging/ath6kl/include/common/discovery.h
deleted file mode 100644
index da1b33245069..000000000000
--- a/drivers/staging/ath6kl/include/common/discovery.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="discovery.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef _DISCOVERY_H_
-#define _DISCOVERY_H_
-
-/*
- * DC_SCAN_PRIORITY is an 8-bit bitmap of the scan priority of a channel
- */
-typedef enum {
- DEFAULT_SCPRI = 0x01,
- POPULAR_SCPRI = 0x02,
- SSIDS_SCPRI = 0x04,
- PROF_SCPRI = 0x08,
-} DC_SCAN_PRIORITY;
-
-/* The following search type construct can be used to manipulate the behavior of the search module based on different bits set */
-typedef enum {
- SCAN_RESET = 0,
- SCAN_ALL = (DEFAULT_SCPRI | POPULAR_SCPRI | \
- SSIDS_SCPRI | PROF_SCPRI),
-
- SCAN_POPULAR = (POPULAR_SCPRI | SSIDS_SCPRI | PROF_SCPRI),
- SCAN_SSIDS = (SSIDS_SCPRI | PROF_SCPRI),
- SCAN_PROF_MASK = (PROF_SCPRI),
- SCAN_MULTI_CHANNEL = 0x000100,
- SCAN_DETERMINISTIC = 0x000200,
- SCAN_PROFILE_MATCH_TERMINATED = 0x000400,
- SCAN_HOME_CHANNEL_SKIP = 0x000800,
- SCAN_CHANNEL_LIST_CONTINUE = 0x001000,
- SCAN_CURRENT_SSID_SKIP = 0x002000,
- SCAN_ACTIVE_PROBE_DISABLE = 0x004000,
- SCAN_CHANNEL_HINT_ONLY = 0x008000,
- SCAN_ACTIVE_CHANNELS_ONLY = 0x010000,
- SCAN_UNUSED1 = 0x020000, /* unused */
- SCAN_PERIODIC = 0x040000,
- SCAN_FIXED_DURATION = 0x080000,
- SCAN_AP_ASSISTED = 0x100000,
-} DC_SCAN_TYPE;
-
-typedef enum {
- BSS_REPORTING_DEFAULT = 0x0,
- EXCLUDE_NON_SCAN_RESULTS = 0x1, /* Exclude results outside of scan */
-} DC_BSS_REPORTING_POLICY;
-
-typedef enum {
- DC_IGNORE_WPAx_GROUP_CIPHER = 0x01,
- DC_PROFILE_MATCH_DONE = 0x02,
- DC_IGNORE_AAC_BEACON = 0x04,
- DC_CSA_FOLLOW_BSS = 0x08,
-} DC_PROFILE_FILTER;
-
-#define DEFAULT_DC_PROFILE_FILTER (DC_CSA_FOLLOW_BSS)
-
-#endif /* _DISCOVERY_H_ */
diff --git a/drivers/staging/ath6kl/include/common/epping_test.h b/drivers/staging/ath6kl/include/common/epping_test.h
deleted file mode 100644
index 9eb5fdfa746a..000000000000
--- a/drivers/staging/ath6kl/include/common/epping_test.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//
-
-/* This file contains shared definitions for the host/target endpoint ping test */
-
-#ifndef EPPING_TEST_H_
-#define EPPING_TEST_H_
-
- /* alignment to 4-bytes */
-#define EPPING_ALIGNMENT_PAD (((sizeof(struct htc_frame_hdr) + 3) & (~0x3)) - sizeof(struct htc_frame_hdr))
-
-#ifndef A_OFFSETOF
-#define A_OFFSETOF(type,field) (int)(&(((type *)NULL)->field))
-#endif
-
-#define EPPING_RSVD_FILL 0xCC
-
-#define HCI_RSVD_EXPECTED_PKT_TYPE_RECV_OFFSET 7
-
-typedef PREPACK struct {
- u8 _HCIRsvd[8]; /* reserved for HCI packet header (GMBOX) testing */
- u8 StreamEcho_h; /* stream no. to echo this packet on (filled by host) */
- u8 StreamEchoSent_t; /* stream no. packet was echoed to (filled by target)
- When echoed: StreamEchoSent_t == StreamEcho_h */
- u8 StreamRecv_t; /* stream no. that target received this packet on (filled by target) */
- u8 StreamNo_h; /* stream number to send on (filled by host) */
- u8 Magic_h[4]; /* magic number to filter for this packet on the host*/
- u8 _rsvd[6]; /* reserved fields that must be set to a "reserved" value
- since this packet maps to a 14-byte ethernet frame we want
- to make sure ethertype field is set to something unknown */
-
- u8 _pad[2]; /* padding for alignment */
- u8 TimeStamp[8]; /* timestamp of packet (host or target) */
- u32 HostContext_h; /* 4 byte host context, target echos this back */
- u32 SeqNo; /* sequence number (set by host or target) */
- u16 Cmd_h; /* ping command (filled by host) */
- u16 CmdFlags_h; /* optional flags */
- u8 CmdBuffer_h[8]; /* buffer for command (host -> target) */
- u8 CmdBuffer_t[8]; /* buffer for command (target -> host) */
- u16 DataLength; /* length of data */
- u16 DataCRC; /* 16 bit CRC of data */
- u16 HeaderCRC; /* header CRC (fields : StreamNo_h to end, minus HeaderCRC) */
-} POSTPACK EPPING_HEADER;
-
-#define EPPING_PING_MAGIC_0 0xAA
-#define EPPING_PING_MAGIC_1 0x55
-#define EPPING_PING_MAGIC_2 0xCE
-#define EPPING_PING_MAGIC_3 0xEC
-
-
-
-#define IS_EPPING_PACKET(pPkt) (((pPkt)->Magic_h[0] == EPPING_PING_MAGIC_0) && \
- ((pPkt)->Magic_h[1] == EPPING_PING_MAGIC_1) && \
- ((pPkt)->Magic_h[2] == EPPING_PING_MAGIC_2) && \
- ((pPkt)->Magic_h[3] == EPPING_PING_MAGIC_3))
-
-#define SET_EPPING_PACKET_MAGIC(pPkt) { (pPkt)->Magic_h[0] = EPPING_PING_MAGIC_0; \
- (pPkt)->Magic_h[1] = EPPING_PING_MAGIC_1; \
- (pPkt)->Magic_h[2] = EPPING_PING_MAGIC_2; \
- (pPkt)->Magic_h[3] = EPPING_PING_MAGIC_3;}
-
-#define CMD_FLAGS_DATA_CRC (1 << 0) /* DataCRC field is valid */
-#define CMD_FLAGS_DELAY_ECHO (1 << 1) /* delay the echo of the packet */
-#define CMD_FLAGS_NO_DROP (1 << 2) /* do not drop at HTC layer no matter what the stream is */
-
-#define IS_EPING_PACKET_NO_DROP(pPkt) ((pPkt)->CmdFlags_h & CMD_FLAGS_NO_DROP)
-
-#define EPPING_CMD_ECHO_PACKET 1 /* echo packet test */
-#define EPPING_CMD_RESET_RECV_CNT 2 /* reset recv count */
-#define EPPING_CMD_CAPTURE_RECV_CNT 3 /* fetch recv count, 4-byte count returned in CmdBuffer_t */
-#define EPPING_CMD_NO_ECHO 4 /* non-echo packet test (tx-only) */
-#define EPPING_CMD_CONT_RX_START 5 /* continuous RX packets, parameters are in CmdBuffer_h */
-#define EPPING_CMD_CONT_RX_STOP 6 /* stop continuous RX packet transmission */
-
- /* test command parameters may be no more than 8 bytes */
-typedef PREPACK struct {
- u16 BurstCnt; /* number of packets to burst together (for HTC 2.1 testing) */
- u16 PacketLength; /* length of packet to generate including header */
- u16 Flags; /* flags */
-
-#define EPPING_CONT_RX_DATA_CRC (1 << 0) /* Add CRC to all data */
-#define EPPING_CONT_RX_RANDOM_DATA (1 << 1) /* randomize the data pattern */
-#define EPPING_CONT_RX_RANDOM_LEN (1 << 2) /* randomize the packet lengths */
-} POSTPACK EPPING_CONT_RX_PARAMS;
-
-#define EPPING_HDR_CRC_OFFSET A_OFFSETOF(EPPING_HEADER,StreamNo_h)
-#define EPPING_HDR_BYTES_CRC (sizeof(EPPING_HEADER) - EPPING_HDR_CRC_OFFSET - (sizeof(u16)))
-
-#define HCI_TRANSPORT_STREAM_NUM 16 /* this number is higher than the define WMM AC classes so we
- can use this to distinguish packets */
-
-#endif /*EPPING_TEST_H_*/
diff --git a/drivers/staging/ath6kl/include/common/gmboxif.h b/drivers/staging/ath6kl/include/common/gmboxif.h
deleted file mode 100644
index ea11c14def43..000000000000
--- a/drivers/staging/ath6kl/include/common/gmboxif.h
+++ /dev/null
@@ -1,70 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef __GMBOXIF_H__
-#define __GMBOXIF_H__
-
-/* GMBOX interface definitions */
-
-#define AR6K_GMBOX_CREDIT_COUNTER 1 /* we use credit counter 1 to track credits */
-#define AR6K_GMBOX_CREDIT_SIZE_COUNTER 2 /* credit counter 2 is used to pass the size of each credit */
-
-
- /* HCI UART transport definitions when used over GMBOX interface */
-#define HCI_UART_COMMAND_PKT 0x01
-#define HCI_UART_ACL_PKT 0x02
-#define HCI_UART_SCO_PKT 0x03
-#define HCI_UART_EVENT_PKT 0x04
-
- /* definitions for BT HCI packets */
-typedef PREPACK struct {
- u16 Flags_ConnHandle;
- u16 Length;
-} POSTPACK BT_HCI_ACL_HEADER;
-
-typedef PREPACK struct {
- u16 Flags_ConnHandle;
- u8 Length;
-} POSTPACK BT_HCI_SCO_HEADER;
-
-typedef PREPACK struct {
- u16 OpCode;
- u8 ParamLength;
-} POSTPACK BT_HCI_COMMAND_HEADER;
-
-typedef PREPACK struct {
- u8 EventCode;
- u8 ParamLength;
-} POSTPACK BT_HCI_EVENT_HEADER;
-
-/* MBOX host interrupt signal assignments */
-
-#define MBOX_SIG_HCI_BRIDGE_MAX 8
-#define MBOX_SIG_HCI_BRIDGE_BT_ON 0
-#define MBOX_SIG_HCI_BRIDGE_BT_OFF 1
-#define MBOX_SIG_HCI_BRIDGE_BAUD_SET 2
-#define MBOX_SIG_HCI_BRIDGE_PWR_SAV_ON 3
-#define MBOX_SIG_HCI_BRIDGE_PWR_SAV_OFF 4
-
-
-#endif /* __GMBOXIF_H__ */
-
diff --git a/drivers/staging/ath6kl/include/common/gpio_reg.h b/drivers/staging/ath6kl/include/common/gpio_reg.h
deleted file mode 100644
index f9d425d48dc2..000000000000
--- a/drivers/staging/ath6kl/include/common/gpio_reg.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _GPIO_REG_REG_H_
-#define _GPIO_REG_REG_H_
-
-#define GPIO_PIN10_ADDRESS 0x00000050
-#define GPIO_PIN11_ADDRESS 0x00000054
-#define GPIO_PIN12_ADDRESS 0x00000058
-#define GPIO_PIN13_ADDRESS 0x0000005c
-
-#endif /* _GPIO_REG_H_ */
diff --git a/drivers/staging/ath6kl/include/common/htc.h b/drivers/staging/ath6kl/include/common/htc.h
deleted file mode 100644
index 85cbfa89d670..000000000000
--- a/drivers/staging/ath6kl/include/common/htc.h
+++ /dev/null
@@ -1,227 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef __HTC_H__
-#define __HTC_H__
-
-#define A_OFFSETOF(type,field) (unsigned long)(&(((type *)NULL)->field))
-
-#define ASSEMBLE_UNALIGNED_UINT16(p,highbyte,lowbyte) \
- (((u16)(((u8 *)(p))[(highbyte)])) << 8 | (u16)(((u8 *)(p))[(lowbyte)]))
-
-/* alignment independent macros (little-endian) to fetch UINT16s or UINT8s from a
- * structure using only the type and field name.
- * Use these macros if there is the potential for unaligned buffer accesses. */
-#define A_GET_UINT16_FIELD(p,type,field) \
- ASSEMBLE_UNALIGNED_UINT16(p,\
- A_OFFSETOF(type,field) + 1, \
- A_OFFSETOF(type,field))
-
-#define A_SET_UINT16_FIELD(p,type,field,value) \
-{ \
- ((u8 *)(p))[A_OFFSETOF(type,field)] = (u8)(value); \
- ((u8 *)(p))[A_OFFSETOF(type,field) + 1] = (u8)((value) >> 8); \
-}
-
-#define A_GET_UINT8_FIELD(p,type,field) \
- ((u8 *)(p))[A_OFFSETOF(type,field)]
-
-#define A_SET_UINT8_FIELD(p,type,field,value) \
- ((u8 *)(p))[A_OFFSETOF(type,field)] = (value)
-
-/****** DANGER DANGER ***************
- *
- * The frame header length and message formats defined herein were
- * selected to accommodate optimal alignment for target processing. This reduces code
- * size and improves performance.
- *
- * Any changes to the header length may alter the alignment and cause exceptions
- * on the target. When adding to the message structures insure that fields are
- * properly aligned.
- *
- */
-
-/* HTC frame header */
-PREPACK struct htc_frame_hdr {
- /* do not remove or re-arrange these fields, these are minimally required
- * to take advantage of 4-byte lookaheads in some hardware implementations */
- u8 EndpointID;
- u8 Flags;
- u16 PayloadLen; /* length of data (including trailer) that follows the header */
-
- /***** end of 4-byte lookahead ****/
-
- u8 ControlBytes[2];
-
- /* message payload starts after the header */
-
-} POSTPACK;
-
-/* frame header flags */
-
- /* send direction */
-#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0)
-#define HTC_FLAGS_SEND_BUNDLE (1 << 1) /* start or part of bundle */
- /* receive direction */
-#define HTC_FLAGS_RECV_UNUSED_0 (1 << 0) /* bit 0 unused */
-#define HTC_FLAGS_RECV_TRAILER (1 << 1) /* bit 1 trailer data present */
-#define HTC_FLAGS_RECV_UNUSED_2 (1 << 0) /* bit 2 unused */
-#define HTC_FLAGS_RECV_UNUSED_3 (1 << 0) /* bit 3 unused */
-#define HTC_FLAGS_RECV_BUNDLE_CNT_MASK (0xF0) /* bits 7..4 */
-#define HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT 4
-
-#define HTC_HDR_LENGTH (sizeof(struct htc_frame_hdr))
-#define HTC_MAX_TRAILER_LENGTH 255
-#define HTC_MAX_PAYLOAD_LENGTH (4096 - sizeof(struct htc_frame_hdr))
-
-/* HTC control message IDs */
-
-#define HTC_MSG_READY_ID 1
-#define HTC_MSG_CONNECT_SERVICE_ID 2
-#define HTC_MSG_CONNECT_SERVICE_RESPONSE_ID 3
-#define HTC_MSG_SETUP_COMPLETE_ID 4
-#define HTC_MSG_SETUP_COMPLETE_EX_ID 5
-
-#define HTC_MAX_CONTROL_MESSAGE_LENGTH 256
-
-/* base message ID header */
-typedef PREPACK struct {
- u16 MessageID;
-} POSTPACK HTC_UNKNOWN_MSG;
-
-/* HTC ready message
- * direction : target-to-host */
-typedef PREPACK struct {
- u16 MessageID; /* ID */
- u16 CreditCount; /* number of credits the target can offer */
- u16 CreditSize; /* size of each credit */
- u8 MaxEndpoints; /* maximum number of endpoints the target has resources for */
- u8 _Pad1;
-} POSTPACK HTC_READY_MSG;
-
- /* extended HTC ready message */
-typedef PREPACK struct {
- HTC_READY_MSG Version2_0_Info; /* legacy version 2.0 information at the front... */
- /* extended information */
- u8 HTCVersion;
- u8 MaxMsgsPerHTCBundle;
-} POSTPACK HTC_READY_EX_MSG;
-
-#define HTC_VERSION_2P0 0x00
-#define HTC_VERSION_2P1 0x01 /* HTC 2.1 */
-
-#define HTC_SERVICE_META_DATA_MAX_LENGTH 128
-
-/* connect service
- * direction : host-to-target */
-typedef PREPACK struct {
- u16 MessageID;
- u16 ServiceID; /* service ID of the service to connect to */
- u16 ConnectionFlags; /* connection flags */
-
-#define HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE (1 << 2) /* reduce credit dribbling when
- the host needs credits */
-#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK (0x3)
-#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH 0x0
-#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF 0x1
-#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS 0x2
-#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_UNITY 0x3
-
- u8 ServiceMetaLength; /* length of meta data that follows */
- u8 _Pad1;
-
- /* service-specific meta data starts after the header */
-
-} POSTPACK HTC_CONNECT_SERVICE_MSG;
-
-/* connect response
- * direction : target-to-host */
-typedef PREPACK struct {
- u16 MessageID;
- u16 ServiceID; /* service ID that the connection request was made */
- u8 Status; /* service connection status */
- u8 EndpointID; /* assigned endpoint ID */
- u16 MaxMsgSize; /* maximum expected message size on this endpoint */
- u8 ServiceMetaLength; /* length of meta data that follows */
- u8 _Pad1;
-
- /* service-specific meta data starts after the header */
-
-} POSTPACK HTC_CONNECT_SERVICE_RESPONSE_MSG;
-
-typedef PREPACK struct {
- u16 MessageID;
- /* currently, no other fields */
-} POSTPACK HTC_SETUP_COMPLETE_MSG;
-
- /* extended setup completion message */
-typedef PREPACK struct {
- u16 MessageID;
- u32 SetupFlags;
- u8 MaxMsgsPerBundledRecv;
- u8 Rsvd[3];
-} POSTPACK HTC_SETUP_COMPLETE_EX_MSG;
-
-#define HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV (1 << 0)
-
-/* connect response status codes */
-#define HTC_SERVICE_SUCCESS 0 /* success */
-#define HTC_SERVICE_NOT_FOUND 1 /* service could not be found */
-#define HTC_SERVICE_FAILED 2 /* specific service failed the connect */
-#define HTC_SERVICE_NO_RESOURCES 3 /* no resources (i.e. no more endpoints) */
-#define HTC_SERVICE_NO_MORE_EP 4 /* specific service is not allowing any more
- endpoints */
-
-/* report record IDs */
-
-#define HTC_RECORD_NULL 0
-#define HTC_RECORD_CREDITS 1
-#define HTC_RECORD_LOOKAHEAD 2
-#define HTC_RECORD_LOOKAHEAD_BUNDLE 3
-
-typedef PREPACK struct {
- u8 RecordID; /* Record ID */
- u8 Length; /* Length of record */
-} POSTPACK HTC_RECORD_HDR;
-
-typedef PREPACK struct {
- u8 EndpointID; /* Endpoint that owns these credits */
- u8 Credits; /* credits to report since last report */
-} POSTPACK HTC_CREDIT_REPORT;
-
-typedef PREPACK struct {
- u8 PreValid; /* pre valid guard */
- u8 LookAhead[4]; /* 4 byte lookahead */
- u8 PostValid; /* post valid guard */
-
- /* NOTE: the LookAhead array is guarded by a PreValid and Post Valid guard bytes.
- * The PreValid bytes must equal the inverse of the PostValid byte */
-
-} POSTPACK HTC_LOOKAHEAD_REPORT;
-
-typedef PREPACK struct {
- u8 LookAhead[4]; /* 4 byte lookahead */
-} POSTPACK HTC_BUNDLED_LOOKAHEAD_REPORT;
-
-#endif /* __HTC_H__ */
-
diff --git a/drivers/staging/ath6kl/include/common/htc_services.h b/drivers/staging/ath6kl/include/common/htc_services.h
deleted file mode 100644
index fb22268a8d84..000000000000
--- a/drivers/staging/ath6kl/include/common/htc_services.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc_services.h" company="Atheros">
-// Copyright (c) 2007 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef __HTC_SERVICES_H__
-#define __HTC_SERVICES_H__
-
-/* Current service IDs */
-
-typedef enum {
- RSVD_SERVICE_GROUP = 0,
- WMI_SERVICE_GROUP = 1,
-
- HTC_TEST_GROUP = 254,
- HTC_SERVICE_GROUP_LAST = 255
-}HTC_SERVICE_GROUP_IDS;
-
-#define MAKE_SERVICE_ID(group,index) \
- (int)(((int)group << 8) | (int)(index))
-
-/* NOTE: service ID of 0x0000 is reserved and should never be used */
-#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP,1)
-#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,0)
-#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,1)
-#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,2)
-#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,3)
-#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,4)
-#define WMI_MAX_SERVICES 5
-
-/* raw stream service (i.e. flash, tcmd, calibration apps) */
-#define HTC_RAW_STREAMS_SVC MAKE_SERVICE_ID(HTC_TEST_GROUP,0)
-
-#endif /*HTC_SERVICES_H_*/
diff --git a/drivers/staging/ath6kl/include/common/pkt_log.h b/drivers/staging/ath6kl/include/common/pkt_log.h
deleted file mode 100644
index a3719adf54ca..000000000000
--- a/drivers/staging/ath6kl/include/common/pkt_log.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2005-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef __PKT_LOG_H__
-#define __PKT_LOG_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Pkt log info */
-typedef PREPACK struct pkt_log_t {
- struct info_t {
- u16 st;
- u16 end;
- u16 cur;
- }info[4096];
- u16 last_idx;
-}POSTPACK PACKET_LOG;
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* __PKT_LOG_H__ */
diff --git a/drivers/staging/ath6kl/include/common/roaming.h b/drivers/staging/ath6kl/include/common/roaming.h
deleted file mode 100644
index 8019850a0571..000000000000
--- a/drivers/staging/ath6kl/include/common/roaming.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="roaming.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef _ROAMING_H_
-#define _ROAMING_H_
-
-/*
- * The signal quality could be in terms of either snr or rssi. We should
- * have an enum for both of them. For the time being, we are going to move
- * it to wmi.h that is shared by both host and the target, since we are
- * repartitioning the code to the host
- */
-#define SIGNAL_QUALITY_NOISE_FLOOR -96
-#define SIGNAL_QUALITY_METRICS_NUM_MAX 2
-typedef enum {
- SIGNAL_QUALITY_METRICS_SNR = 0,
- SIGNAL_QUALITY_METRICS_RSSI,
- SIGNAL_QUALITY_METRICS_ALL,
-} SIGNAL_QUALITY_METRICS_TYPE;
-
-#endif /* _ROAMING_H_ */
diff --git a/drivers/staging/ath6kl/include/common/targaddrs.h b/drivers/staging/ath6kl/include/common/targaddrs.h
deleted file mode 100644
index c866cefbd8fd..000000000000
--- a/drivers/staging/ath6kl/include/common/targaddrs.h
+++ /dev/null
@@ -1,395 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef __TARGADDRS_H__
-#define __TARGADDRS_H__
-
-#if defined(AR6002)
-#include "AR6002/addrs.h"
-#endif
-
-/*
- * AR6K option bits, to enable/disable various features.
- * By default, all option bits are 0.
- * These bits can be set in LOCAL_SCRATCH register 0.
- */
-#define AR6K_OPTION_BMI_DISABLE 0x01 /* Disable BMI comm with Host */
-#define AR6K_OPTION_SERIAL_ENABLE 0x02 /* Enable serial port msgs */
-#define AR6K_OPTION_WDT_DISABLE 0x04 /* WatchDog Timer override */
-#define AR6K_OPTION_SLEEP_DISABLE 0x08 /* Disable system sleep */
-#define AR6K_OPTION_STOP_BOOT 0x10 /* Stop boot processes (for ATE) */
-#define AR6K_OPTION_ENABLE_NOANI 0x20 /* Operate without ANI */
-#define AR6K_OPTION_DSET_DISABLE 0x40 /* Ignore DataSets */
-#define AR6K_OPTION_IGNORE_FLASH 0x80 /* Ignore flash during bootup */
-
-/*
- * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the
- * host_interest structure. It must match the address of the _host_interest
- * symbol (see linker script).
- *
- * Host Interest is shared between Host and Target in order to coordinate
- * between the two, and is intended to remain constant (with additions only
- * at the end) across software releases.
- *
- * All addresses are available here so that it's possible to
- * write a single binary that works with all Target Types.
- * May be used in assembler code as well as C.
- */
-#define AR6002_HOST_INTEREST_ADDRESS 0x00500400
-#define AR6003_HOST_INTEREST_ADDRESS 0x00540600
-
-
-#define HOST_INTEREST_MAX_SIZE 0x100
-
-#if !defined(__ASSEMBLER__)
-struct register_dump_s;
-struct dbglog_hdr_s;
-
-/*
- * These are items that the Host may need to access
- * via BMI or via the Diagnostic Window. The position
- * of items in this structure must remain constant
- * across firmware revisions!
- *
- * Types for each item must be fixed size across
- * target and host platforms.
- *
- * More items may be added at the end.
- */
-PREPACK struct host_interest_s {
- /*
- * Pointer to application-defined area, if any.
- * Set by Target application during startup.
- */
- u32 hi_app_host_interest; /* 0x00 */
-
- /* Pointer to register dump area, valid after Target crash. */
- u32 hi_failure_state; /* 0x04 */
-
- /* Pointer to debug logging header */
- u32 hi_dbglog_hdr; /* 0x08 */
-
- u32 hi_unused1; /* 0x0c */
-
- /*
- * General-purpose flag bits, similar to AR6000_OPTION_* flags.
- * Can be used by application rather than by OS.
- */
- u32 hi_option_flag; /* 0x10 */
-
- /*
- * Boolean that determines whether or not to
- * display messages on the serial port.
- */
- u32 hi_serial_enable; /* 0x14 */
-
- /* Start address of DataSet index, if any */
- u32 hi_dset_list_head; /* 0x18 */
-
- /* Override Target application start address */
- u32 hi_app_start; /* 0x1c */
-
- /* Clock and voltage tuning */
- u32 hi_skip_clock_init; /* 0x20 */
- u32 hi_core_clock_setting; /* 0x24 */
- u32 hi_cpu_clock_setting; /* 0x28 */
- u32 hi_system_sleep_setting; /* 0x2c */
- u32 hi_xtal_control_setting; /* 0x30 */
- u32 hi_pll_ctrl_setting_24ghz; /* 0x34 */
- u32 hi_pll_ctrl_setting_5ghz; /* 0x38 */
- u32 hi_ref_voltage_trim_setting; /* 0x3c */
- u32 hi_clock_info; /* 0x40 */
-
- /*
- * Flash configuration overrides, used only
- * when firmware is not executing from flash.
- * (When using flash, modify the global variables
- * with equivalent names.)
- */
- u32 hi_bank0_addr_value; /* 0x44 */
- u32 hi_bank0_read_value; /* 0x48 */
- u32 hi_bank0_write_value; /* 0x4c */
- u32 hi_bank0_config_value; /* 0x50 */
-
- /* Pointer to Board Data */
- u32 hi_board_data; /* 0x54 */
- u32 hi_board_data_initialized; /* 0x58 */
-
- u32 hi_dset_RAM_index_table; /* 0x5c */
-
- u32 hi_desired_baud_rate; /* 0x60 */
- u32 hi_dbglog_config; /* 0x64 */
- u32 hi_end_RAM_reserve_sz; /* 0x68 */
- u32 hi_mbox_io_block_sz; /* 0x6c */
-
- u32 hi_num_bpatch_streams; /* 0x70 -- unused */
- u32 hi_mbox_isr_yield_limit; /* 0x74 */
-
- u32 hi_refclk_hz; /* 0x78 */
- u32 hi_ext_clk_detected; /* 0x7c */
- u32 hi_dbg_uart_txpin; /* 0x80 */
- u32 hi_dbg_uart_rxpin; /* 0x84 */
- u32 hi_hci_uart_baud; /* 0x88 */
- u32 hi_hci_uart_pin_assignments; /* 0x8C */
- /* NOTE: byte [0] = tx pin, [1] = rx pin, [2] = rts pin, [3] = cts pin */
- u32 hi_hci_uart_baud_scale_val; /* 0x90 */
- u32 hi_hci_uart_baud_step_val; /* 0x94 */
-
- u32 hi_allocram_start; /* 0x98 */
- u32 hi_allocram_sz; /* 0x9c */
- u32 hi_hci_bridge_flags; /* 0xa0 */
- u32 hi_hci_uart_support_pins; /* 0xa4 */
- /* NOTE: byte [0] = RESET pin (bit 7 is polarity), bytes[1]..bytes[3] are for future use */
- u32 hi_hci_uart_pwr_mgmt_params; /* 0xa8 */
- /*
- * 0xa8 - [1]: 0 = UART FC active low, 1 = UART FC active high
- * [31:16]: wakeup timeout in ms
- */
-
- /* Pointer to extended board data */
- u32 hi_board_ext_data; /* 0xac */
- u32 hi_board_ext_data_config; /* 0xb0 */
-
- /*
- * Bit [0] : valid
- * Bit[31:16: size
- */
- /*
- * hi_reset_flag is used to do some stuff when target reset.
- * such as restore app_start after warm reset or
- * preserve host Interest area, or preserve ROM data, literals etc.
- */
- u32 hi_reset_flag; /* 0xb4 */
- /* indicate hi_reset_flag is valid */
- u32 hi_reset_flag_valid; /* 0xb8 */
- u32 hi_hci_uart_pwr_mgmt_params_ext; /* 0xbc */
- /*
- * 0xbc - [31:0]: idle timeout in ms
- */
- /* ACS flags */
- u32 hi_acs_flags; /* 0xc0 */
- u32 hi_console_flags; /* 0xc4 */
- u32 hi_nvram_state; /* 0xc8 */
- u32 hi_option_flag2; /* 0xcc */
-
- /* If non-zero, override values sent to Host in WMI_READY event. */
- u32 hi_sw_version_override; /* 0xd0 */
- u32 hi_abi_version_override; /* 0xd4 */
-
- /*
- * Percentage of high priority RX traffic to total expected RX traffic -
- * applicable only to ar6004
- */
- u32 hi_hp_rx_traffic_ratio; /* 0xd8 */
-
- /* test applications flags */
- u32 hi_test_apps_related ; /* 0xdc */
- /* location of test script */
- u32 hi_ota_testscript; /* 0xe0 */
- /* location of CAL data */
- u32 hi_cal_data; /* 0xe4 */
- /* Number of packet log buffers */
- u32 hi_pktlog_num_buffers; /* 0xe8 */
-
-} POSTPACK;
-
-/* Bits defined in hi_option_flag */
-#define HI_OPTION_TIMER_WAR 0x01 /* Enable timer workaround */
-#define HI_OPTION_BMI_CRED_LIMIT 0x02 /* Limit BMI command credits */
-#define HI_OPTION_RELAY_DOT11_HDR 0x04 /* Relay Dot11 hdr to/from host */
-/* MAC addr method 0-locally administred 1-globally unique addrs */
-#define HI_OPTION_MAC_ADDR_METHOD 0x08
-#define HI_OPTION_FW_BRIDGE 0x10 /* Firmware Bridging */
-#define HI_OPTION_ENABLE_PROFILE 0x20 /* Enable CPU profiling */
-#define HI_OPTION_DISABLE_DBGLOG 0x40 /* Disable debug logging */
-#define HI_OPTION_SKIP_ERA_TRACKING 0x80 /* Skip Era Tracking */
-#define HI_OPTION_PAPRD_DISABLE 0x100 /* Disable PAPRD (debug) */
-#define HI_OPTION_NUM_DEV_LSB 0x200
-#define HI_OPTION_NUM_DEV_MSB 0x800
-#define HI_OPTION_DEV_MODE_LSB 0x1000
-#define HI_OPTION_DEV_MODE_MSB 0x8000000
-/* Disable LowFreq Timer Stabilization */
-#define HI_OPTION_NO_LFT_STBL 0x10000000
-#define HI_OPTION_SKIP_REG_SCAN 0x20000000 /* Skip regulatory scan */
-/* Do regulatory scan during init beforesending WMI ready event to host */
-#define HI_OPTION_INIT_REG_SCAN 0x40000000
-#define HI_OPTION_SKIP_MEMMAP 0x80000000 /* REV6: Do not adjust memory
- map */
-
-/* hi_option_flag2 options */
-#define HI_OPTION_OFFLOAD_AMSDU 0x01
-#define HI_OPTION_DFS_SUPPORT 0x02 /* Enable DFS support */
-
-#define HI_OPTION_MAC_ADDR_METHOD_SHIFT 3
-
-/* 2 bits of hi_option_flag are used to represent 3 modes */
-#define HI_OPTION_FW_MODE_IBSS 0x0 /* IBSS Mode */
-#define HI_OPTION_FW_MODE_BSS_STA 0x1 /* STA Mode */
-#define HI_OPTION_FW_MODE_AP 0x2 /* AP Mode */
-
-/* 2 bits of hi_option flag are usedto represent 4 submodes */
-#define HI_OPTION_FW_SUBMODE_NONE 0x0 /* Normal mode */
-#define HI_OPTION_FW_SUBMODE_P2PDEV 0x1 /* p2p device mode */
-#define HI_OPTION_FW_SUBMODE_P2PCLIENT 0x2 /* p2p client mode */
-#define HI_OPTION_FW_SUBMODE_P2PGO 0x3 /* p2p go mode */
-
-/* Num dev Mask */
-#define HI_OPTION_NUM_DEV_MASK 0x7
-#define HI_OPTION_NUM_DEV_SHIFT 0x9
-
-/* firmware bridging */
-#define HI_OPTION_FW_BRIDGE_SHIFT 0x04
-
-/* Fw Mode/SubMode Mask
-|------------------------------------------------------------------------------|
-| SUB | SUB | SUB | SUB | | | |
-| MODE[3] | MODE[2] | MODE[1] | MODE[0] | MODE[3] | MODE[2] | MODE[1] | MODE[0|
-| (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2)
-|------------------------------------------------------------------------------|
-*/
-#define HI_OPTION_FW_MODE_BITS 0x2
-#define HI_OPTION_FW_MODE_MASK 0x3
-#define HI_OPTION_FW_MODE_SHIFT 0xC
-#define HI_OPTION_ALL_FW_MODE_MASK 0xFF
-
-#define HI_OPTION_FW_SUBMODE_BITS 0x2
-#define HI_OPTION_FW_SUBMODE_MASK 0x3
-#define HI_OPTION_FW_SUBMODE_SHIFT 0x14
-#define HI_OPTION_ALL_FW_SUBMODE_MASK 0xFF00
-#define HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8
-
-/* hi_reset_flag */
-
-/* preserve App Start address */
-#define HI_RESET_FLAG_PRESERVE_APP_START 0x01
-/* preserve host interest */
-#define HI_RESET_FLAG_PRESERVE_HOST_INTEREST 0x02
-#define HI_RESET_FLAG_PRESERVE_ROMDATA 0x04 /* preserve ROM data */
-#define HI_RESET_FLAG_PRESERVE_NVRAM_STATE 0x08
-#define HI_RESET_FLAG_PRESERVE_BOOT_INFO 0x10
-
-#define HI_RESET_FLAG_IS_VALID 0x12345678 /* indicate the reset flag is
-valid */
-
-#define ON_RESET_FLAGS_VALID() \
- (HOST_INTEREST->hi_reset_flag_valid == HI_RESET_FLAG_IS_VALID)
-
-#define RESET_FLAGS_VALIDATE() \
- (HOST_INTEREST->hi_reset_flag_valid = HI_RESET_FLAG_IS_VALID)
-
-#define RESET_FLAGS_INVALIDATE() \
- (HOST_INTEREST->hi_reset_flag_valid = 0)
-
-#define ON_RESET_PRESERVE_APP_START() \
- (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_APP_START)
-
-#define ON_RESET_PRESERVE_NVRAM_STATE() \
- (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_NVRAM_STATE)
-
-#define ON_RESET_PRESERVE_HOST_INTEREST() \
- (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_HOST_INTEREST)
-
-#define ON_RESET_PRESERVE_ROMDATA() \
- (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_ROMDATA)
-
-#define ON_RESET_PRESERVE_BOOT_INFO() \
- (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_BOOT_INFO)
-
-#define HI_ACS_FLAGS_ENABLED (1 << 0) /* ACS is enabled */
-#define HI_ACS_FLAGS_USE_WWAN (1 << 1) /* Use physical WWAN device */
-#define HI_ACS_FLAGS_TEST_VAP (1 << 2) /* Use test VAP */
-
-/* CONSOLE FLAGS
- *
- * Bit Range Meaning
- * --------- --------------------------------
- * 2..0 UART ID (0 = Default)
- * 3 Baud Select (0 = 9600, 1 = 115200)
- * 30..4 Reserved
- * 31 Enable Console
- *
- */
-
-#define HI_CONSOLE_FLAGS_ENABLE (1 << 31)
-#define HI_CONSOLE_FLAGS_UART_MASK (0x7)
-#define HI_CONSOLE_FLAGS_UART_SHIFT 0
-#define HI_CONSOLE_FLAGS_BAUD_SELECT (1 << 3)
-
-/*
- * Intended for use by Host software, this macro returns the Target RAM
- * address of any item in the host_interest structure.
- * Example: target_addr = AR6002_HOST_INTEREST_ITEM_ADDRESS(hi_board_data);
- */
-#define AR6002_HOST_INTEREST_ITEM_ADDRESS(item) \
- (u32)((unsigned long)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item)))
-
-#define AR6003_HOST_INTEREST_ITEM_ADDRESS(item) \
- (u32)((unsigned long)&((((struct host_interest_s *)(AR6003_HOST_INTEREST_ADDRESS))->item)))
-
-#define AR6004_HOST_INTEREST_ITEM_ADDRESS(item) \
- ((u32)&((((struct host_interest_s *)(AR6004_HOST_INTEREST_ADDRESS))->item)))
-
-
-#define HOST_INTEREST_DBGLOG_IS_ENABLED() \
- (!(HOST_INTEREST->hi_option_flag & HI_OPTION_DISABLE_DBGLOG))
-
-#define HOST_INTEREST_PKTLOG_IS_ENABLED() \
- ((HOST_INTEREST->hi_pktlog_num_buffers))
-
-
-#define HOST_INTEREST_PROFILE_IS_ENABLED() \
- (HOST_INTEREST->hi_option_flag & HI_OPTION_ENABLE_PROFILE)
-
-#define LF_TIMER_STABILIZATION_IS_ENABLED() \
- (!(HOST_INTEREST->hi_option_flag & HI_OPTION_NO_LFT_STBL))
-
-#define IS_AMSDU_OFFLAOD_ENABLED() \
- ((HOST_INTEREST->hi_option_flag2 & HI_OPTION_OFFLOAD_AMSDU))
-
-#define HOST_INTEREST_DFS_IS_ENABLED() \
- ((HOST_INTEREST->hi_option_flag2 & HI_OPTION_DFS_SUPPORT))
-
-/* Convert a Target virtual address into a Target physical address */
-#define AR6002_VTOP(vaddr) ((vaddr) & 0x001fffff)
-#define AR6003_VTOP(vaddr) ((vaddr) & 0x001fffff)
-#define TARG_VTOP(TargetType, vaddr) \
- (((TargetType) == TARGET_TYPE_AR6002) ? AR6002_VTOP(vaddr) : AR6003_VTOP(vaddr))
-
-#define AR6003_REV2_APP_START_OVERRIDE 0x944C00
-#define AR6003_REV2_APP_LOAD_ADDRESS 0x543180
-#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500
-#define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884
-#define AR6003_REV2_RAM_RESERVE_SIZE 6912
-
-#define AR6003_REV3_APP_START_OVERRIDE 0x945d00
-#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000
-#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330
-#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74
-#define AR6003_REV3_RAM_RESERVE_SIZE 512
-
-#define AR6003_BOARD_EXT_DATA_ADDRESS 0x57E600
-
-/* # of u32 entries in targregs, used by DIAG_FETCH_TARG_REGS */
-#define AR6003_FETCH_TARG_REGS_COUNT 64
-
-#endif /* !__ASSEMBLER__ */
-
-#endif /* __TARGADDRS_H__ */
diff --git a/drivers/staging/ath6kl/include/common/testcmd.h b/drivers/staging/ath6kl/include/common/testcmd.h
deleted file mode 100644
index 7d94aee508b3..000000000000
--- a/drivers/staging/ath6kl/include/common/testcmd.h
+++ /dev/null
@@ -1,185 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="testcmd.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef TESTCMD_H_
-#define TESTCMD_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef AR6002_REV2
-#define TCMD_MAX_RATES 12
-#else
-#define TCMD_MAX_RATES 28
-#endif
-
-typedef enum {
- ZEROES_PATTERN = 0,
- ONES_PATTERN,
- REPEATING_10,
- PN7_PATTERN,
- PN9_PATTERN,
- PN15_PATTERN
-}TX_DATA_PATTERN;
-
-/* Continuous tx
- mode : TCMD_CONT_TX_OFF - Disabling continuous tx
- TCMD_CONT_TX_SINE - Enable continuous unmodulated tx
- TCMD_CONT_TX_FRAME- Enable continuous modulated tx
- freq : Channel freq in Mhz. (e.g 2412 for channel 1 in 11 g)
-dataRate: 0 - 1 Mbps
- 1 - 2 Mbps
- 2 - 5.5 Mbps
- 3 - 11 Mbps
- 4 - 6 Mbps
- 5 - 9 Mbps
- 6 - 12 Mbps
- 7 - 18 Mbps
- 8 - 24 Mbps
- 9 - 36 Mbps
- 10 - 28 Mbps
- 11 - 54 Mbps
- txPwr: Tx power in dBm[5 -11] for unmod Tx, [5-14] for mod Tx
-antenna: 1 - one antenna
- 2 - two antenna
-Note : Enable/disable continuous tx test cmd works only when target is awake.
-*/
-
-typedef enum {
- TCMD_CONT_TX_OFF = 0,
- TCMD_CONT_TX_SINE,
- TCMD_CONT_TX_FRAME,
- TCMD_CONT_TX_TX99,
- TCMD_CONT_TX_TX100
-} TCMD_CONT_TX_MODE;
-
-typedef enum {
- TCMD_WLAN_MODE_NOHT = 0,
- TCMD_WLAN_MODE_HT20 = 1,
- TCMD_WLAN_MODE_HT40PLUS = 2,
- TCMD_WLAN_MODE_HT40MINUS = 3,
-} TCMD_WLAN_MODE;
-
-typedef PREPACK struct {
- u32 testCmdId;
- u32 mode;
- u32 freq;
- u32 dataRate;
- s32 txPwr;
- u32 antenna;
- u32 enANI;
- u32 scramblerOff;
- u32 aifsn;
- u16 pktSz;
- u16 txPattern;
- u32 shortGuard;
- u32 numPackets;
- u32 wlanMode;
-} POSTPACK TCMD_CONT_TX;
-
-#define TCMD_TXPATTERN_ZERONE 0x1
-#define TCMD_TXPATTERN_ZERONE_DIS_SCRAMBLE 0x2
-
-/* Continuous Rx
- act: TCMD_CONT_RX_PROMIS - promiscuous mode (accept all incoming frames)
- TCMD_CONT_RX_FILTER - filter mode (accept only frames with dest
- address equal specified
- mac address (set via act =3)
- TCMD_CONT_RX_REPORT off mode (disable cont rx mode and get the
- report from the last cont
- Rx test)
-
- TCMD_CONT_RX_SETMAC - set MacAddr mode (sets the MAC address for the
- target. This Overrides
- the default MAC address.)
-
-*/
-typedef enum {
- TCMD_CONT_RX_PROMIS =0,
- TCMD_CONT_RX_FILTER,
- TCMD_CONT_RX_REPORT,
- TCMD_CONT_RX_SETMAC,
- TCMD_CONT_RX_SET_ANT_SWITCH_TABLE
-} TCMD_CONT_RX_ACT;
-
-typedef PREPACK struct {
- u32 testCmdId;
- u32 act;
- u32 enANI;
- PREPACK union {
- struct PREPACK TCMD_CONT_RX_PARA {
- u32 freq;
- u32 antenna;
- u32 wlanMode;
- } POSTPACK para;
- struct PREPACK TCMD_CONT_RX_REPORT {
- u32 totalPkt;
- s32 rssiInDBm;
- u32 crcErrPkt;
- u32 secErrPkt;
- u16 rateCnt[TCMD_MAX_RATES];
- u16 rateCntShortGuard[TCMD_MAX_RATES];
- } POSTPACK report;
- struct PREPACK TCMD_CONT_RX_MAC {
- u8 addr[ATH_MAC_LEN];
- } POSTPACK mac;
- struct PREPACK TCMD_CONT_RX_ANT_SWITCH_TABLE {
- u32 antswitch1;
- u32 antswitch2;
- }POSTPACK antswitchtable;
- } POSTPACK u;
-} POSTPACK TCMD_CONT_RX;
-
-/* Force sleep/wake test cmd
- mode: TCMD_PM_WAKEUP - Wakeup the target
- TCMD_PM_SLEEP - Force the target to sleep.
- */
-typedef enum {
- TCMD_PM_WAKEUP = 1, /* be consistent with target */
- TCMD_PM_SLEEP,
- TCMD_PM_DEEPSLEEP
-} TCMD_PM_MODE;
-
-typedef PREPACK struct {
- u32 testCmdId;
- u32 mode;
-} POSTPACK TCMD_PM;
-
-typedef enum {
- TCMD_CONT_TX_ID,
- TCMD_CONT_RX_ID,
- TCMD_PM_ID
-} TCMD_ID;
-
-typedef PREPACK union {
- TCMD_CONT_TX contTx;
- TCMD_CONT_RX contRx;
- TCMD_PM pm;
-} POSTPACK TEST_CMD;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TESTCMD_H_ */
diff --git a/drivers/staging/ath6kl/include/common/tlpm.h b/drivers/staging/ath6kl/include/common/tlpm.h
deleted file mode 100644
index 659b1c07ba90..000000000000
--- a/drivers/staging/ath6kl/include/common/tlpm.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifndef __TLPM_H__
-#define __TLPM_H__
-
-/* idle timeout in 16-bit value as in HOST_INTEREST hi_hci_uart_pwr_mgmt_params */
-#define TLPM_DEFAULT_IDLE_TIMEOUT_MS 1000
-/* hex in LSB and MSB for HCI command */
-#define TLPM_DEFAULT_IDLE_TIMEOUT_LSB 0xE8
-#define TLPM_DEFAULT_IDLE_TIMEOUT_MSB 0x3
-
-/* wakeup timeout in 8-bit value as in HOST_INTEREST hi_hci_uart_pwr_mgmt_params */
-#define TLPM_DEFAULT_WAKEUP_TIMEOUT_MS 10
-
-/* default UART FC polarity is low */
-#define TLPM_DEFAULT_UART_FC_POLARITY 0
-
-#endif
diff --git a/drivers/staging/ath6kl/include/common/wlan_defs.h b/drivers/staging/ath6kl/include/common/wlan_defs.h
deleted file mode 100644
index 03e4d23788ce..000000000000
--- a/drivers/staging/ath6kl/include/common/wlan_defs.h
+++ /dev/null
@@ -1,79 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="wlan_defs.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef __WLAN_DEFS_H__
-#define __WLAN_DEFS_H__
-
-/*
- * This file contains WLAN definitions that may be used across both
- * Host and Target software.
- */
-
-typedef enum {
- MODE_11A = 0, /* 11a Mode */
- MODE_11G = 1, /* 11b/g Mode */
- MODE_11B = 2, /* 11b Mode */
- MODE_11GONLY = 3, /* 11g only Mode */
-#ifdef SUPPORT_11N
- MODE_11NA_HT20 = 4, /* 11a HT20 mode */
- MODE_11NG_HT20 = 5, /* 11g HT20 mode */
- MODE_11NA_HT40 = 6, /* 11a HT40 mode */
- MODE_11NG_HT40 = 7, /* 11g HT40 mode */
- MODE_UNKNOWN = 8,
- MODE_MAX = 8
-#else
- MODE_UNKNOWN = 4,
- MODE_MAX = 4
-#endif
-} WLAN_PHY_MODE;
-
-typedef enum {
- WLAN_11A_CAPABILITY = 1,
- WLAN_11G_CAPABILITY = 2,
- WLAN_11AG_CAPABILITY = 3,
-}WLAN_CAPABILITY;
-
-#ifdef SUPPORT_11N
-typedef unsigned long A_RATEMASK;
-#else
-typedef unsigned short A_RATEMASK;
-#endif
-
-#ifdef SUPPORT_11N
-#define IS_MODE_11A(mode) (((mode) == MODE_11A) || \
- ((mode) == MODE_11NA_HT20) || \
- ((mode) == MODE_11NA_HT40))
-#define IS_MODE_11B(mode) ((mode) == MODE_11B)
-#define IS_MODE_11G(mode) (((mode) == MODE_11G) || \
- ((mode) == MODE_11GONLY) || \
- ((mode) == MODE_11NG_HT20) || \
- ((mode) == MODE_11NG_HT40))
-#define IS_MODE_11GONLY(mode) ((mode) == MODE_11GONLY)
-#else
-#define IS_MODE_11A(mode) ((mode) == MODE_11A)
-#define IS_MODE_11B(mode) ((mode) == MODE_11B)
-#define IS_MODE_11G(mode) (((mode) == MODE_11G) || \
- ((mode) == MODE_11GONLY))
-#define IS_MODE_11GONLY(mode) ((mode) == MODE_11GONLY)
-#endif /* SUPPORT_11N */
-
-#endif /* __WLANDEFS_H__ */
diff --git a/drivers/staging/ath6kl/include/common/wmi.h b/drivers/staging/ath6kl/include/common/wmi.h
deleted file mode 100644
index d9687443d32c..000000000000
--- a/drivers/staging/ath6kl/include/common/wmi.h
+++ /dev/null
@@ -1,3220 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-/*
- * This file contains the definitions of the WMI protocol specified in the
- * Wireless Module Interface (WMI). It includes definitions of all the
- * commands and events. Commands are messages from the host to the WM.
- * Events and Replies are messages from the WM to the host.
- *
- * Ownership of correctness in regards to commands
- * belongs to the host driver and the WMI is not required to validate
- * parameters for value, proper range, or any other checking.
- *
- */
-
-#ifndef _WMI_H_
-#define _WMI_H_
-
-#include "wmix.h"
-#include "wlan_defs.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define HTC_PROTOCOL_VERSION 0x0002
-#define HTC_PROTOCOL_REVISION 0x0000
-
-#define WMI_PROTOCOL_VERSION 0x0002
-#define WMI_PROTOCOL_REVISION 0x0000
-
-#define ATH_MAC_LEN 6 /* length of mac in bytes */
-#define WMI_CMD_MAX_LEN 100
-#define WMI_CONTROL_MSG_MAX_LEN 256
-#define WMI_OPT_CONTROL_MSG_MAX_LEN 1536
-#define IS_ETHERTYPE(_typeOrLen) ((_typeOrLen) >= 0x0600)
-#define RFC1042OUI {0x00, 0x00, 0x00}
-
-#define IP_ETHERTYPE 0x0800
-
-#define WMI_IMPLICIT_PSTREAM 0xFF
-#define WMI_MAX_THINSTREAM 15
-
-#ifdef AR6002_REV2
-#define IBSS_MAX_NUM_STA 4
-#else
-#define IBSS_MAX_NUM_STA 8
-#endif
-
-PREPACK struct host_app_area_s {
- u32 wmi_protocol_ver;
-} POSTPACK;
-
-/*
- * Data Path
- */
-typedef PREPACK struct {
- u8 dstMac[ATH_MAC_LEN];
- u8 srcMac[ATH_MAC_LEN];
- u16 typeOrLen;
-} POSTPACK ATH_MAC_HDR;
-
-typedef PREPACK struct {
- u8 dsap;
- u8 ssap;
- u8 cntl;
- u8 orgCode[3];
- u16 etherType;
-} POSTPACK ATH_LLC_SNAP_HDR;
-
-typedef enum {
- DATA_MSGTYPE = 0x0,
- CNTL_MSGTYPE,
- SYNC_MSGTYPE,
- OPT_MSGTYPE,
-} WMI_MSG_TYPE;
-
-
-/*
- * Macros for operating on WMI_DATA_HDR (info) field
- */
-
-#define WMI_DATA_HDR_MSG_TYPE_MASK 0x03
-#define WMI_DATA_HDR_MSG_TYPE_SHIFT 0
-#define WMI_DATA_HDR_UP_MASK 0x07
-#define WMI_DATA_HDR_UP_SHIFT 2
-/* In AP mode, the same bit (b5) is used to indicate Power save state in
- * the Rx dir and More data bit state in the tx direction.
- */
-#define WMI_DATA_HDR_PS_MASK 0x1
-#define WMI_DATA_HDR_PS_SHIFT 5
-
-#define WMI_DATA_HDR_MORE_MASK 0x1
-#define WMI_DATA_HDR_MORE_SHIFT 5
-
-typedef enum {
- WMI_DATA_HDR_DATA_TYPE_802_3 = 0,
- WMI_DATA_HDR_DATA_TYPE_802_11,
- WMI_DATA_HDR_DATA_TYPE_ACL, /* used to be used for the PAL */
-} WMI_DATA_HDR_DATA_TYPE;
-
-#define WMI_DATA_HDR_DATA_TYPE_MASK 0x3
-#define WMI_DATA_HDR_DATA_TYPE_SHIFT 6
-
-#define WMI_DATA_HDR_SET_MORE_BIT(h) ((h)->info |= (WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT))
-
-#define WMI_DATA_HDR_IS_MSG_TYPE(h, t) (((h)->info & (WMI_DATA_HDR_MSG_TYPE_MASK)) == (t))
-#define WMI_DATA_HDR_SET_MSG_TYPE(h, t) (h)->info = (((h)->info & ~(WMI_DATA_HDR_MSG_TYPE_MASK << WMI_DATA_HDR_MSG_TYPE_SHIFT)) | (t << WMI_DATA_HDR_MSG_TYPE_SHIFT))
-#define WMI_DATA_HDR_GET_UP(h) (((h)->info >> WMI_DATA_HDR_UP_SHIFT) & WMI_DATA_HDR_UP_MASK)
-#define WMI_DATA_HDR_SET_UP(h, p) (h)->info = (((h)->info & ~(WMI_DATA_HDR_UP_MASK << WMI_DATA_HDR_UP_SHIFT)) | (p << WMI_DATA_HDR_UP_SHIFT))
-
-#define WMI_DATA_HDR_GET_DATA_TYPE(h) (((h)->info >> WMI_DATA_HDR_DATA_TYPE_SHIFT) & WMI_DATA_HDR_DATA_TYPE_MASK)
-#define WMI_DATA_HDR_SET_DATA_TYPE(h, p) (h)->info = (((h)->info & ~(WMI_DATA_HDR_DATA_TYPE_MASK << WMI_DATA_HDR_DATA_TYPE_SHIFT)) | ((p) << WMI_DATA_HDR_DATA_TYPE_SHIFT))
-
-#define WMI_DATA_HDR_GET_DOT11(h) (WMI_DATA_HDR_GET_DATA_TYPE((h)) == WMI_DATA_HDR_DATA_TYPE_802_11)
-#define WMI_DATA_HDR_SET_DOT11(h, p) WMI_DATA_HDR_SET_DATA_TYPE((h), (p))
-
-/* Macros for operating on WMI_DATA_HDR (info2) field */
-#define WMI_DATA_HDR_SEQNO_MASK 0xFFF
-#define WMI_DATA_HDR_SEQNO_SHIFT 0
-
-#define WMI_DATA_HDR_AMSDU_MASK 0x1
-#define WMI_DATA_HDR_AMSDU_SHIFT 12
-
-#define WMI_DATA_HDR_META_MASK 0x7
-#define WMI_DATA_HDR_META_SHIFT 13
-
-#define GET_SEQ_NO(_v) ((_v) & WMI_DATA_HDR_SEQNO_MASK)
-#define GET_ISMSDU(_v) ((_v) & WMI_DATA_HDR_AMSDU_MASK)
-
-#define WMI_DATA_HDR_GET_SEQNO(h) GET_SEQ_NO((h)->info2 >> WMI_DATA_HDR_SEQNO_SHIFT)
-#define WMI_DATA_HDR_SET_SEQNO(h, _v) ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_SEQNO_MASK << WMI_DATA_HDR_SEQNO_SHIFT)) | (GET_SEQ_NO(_v) << WMI_DATA_HDR_SEQNO_SHIFT))
-
-#define WMI_DATA_HDR_IS_AMSDU(h) GET_ISMSDU((h)->info2 >> WMI_DATA_HDR_AMSDU_SHIFT)
-#define WMI_DATA_HDR_SET_AMSDU(h, _v) ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_AMSDU_MASK << WMI_DATA_HDR_AMSDU_SHIFT)) | (GET_ISMSDU(_v) << WMI_DATA_HDR_AMSDU_SHIFT))
-
-#define WMI_DATA_HDR_GET_META(h) (((h)->info2 >> WMI_DATA_HDR_META_SHIFT) & WMI_DATA_HDR_META_MASK)
-#define WMI_DATA_HDR_SET_META(h, _v) ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_META_MASK << WMI_DATA_HDR_META_SHIFT)) | ((_v) << WMI_DATA_HDR_META_SHIFT))
-
-/* Macros for operating on WMI_DATA_HDR (info3) field */
-#define WMI_DATA_HDR_DEVID_MASK 0xF
-#define WMI_DATA_HDR_DEVID_SHIFT 0
-#define GET_DEVID(_v) ((_v) & WMI_DATA_HDR_DEVID_MASK)
-
-#define WMI_DATA_HDR_GET_DEVID(h) \
- (((h)->info3 >> WMI_DATA_HDR_DEVID_SHIFT) & WMI_DATA_HDR_DEVID_MASK)
-#define WMI_DATA_HDR_SET_DEVID(h, _v) \
- ((h)->info3 = ((h)->info3 & ~(WMI_DATA_HDR_DEVID_MASK << WMI_DATA_HDR_DEVID_SHIFT)) | (GET_DEVID(_v) << WMI_DATA_HDR_DEVID_SHIFT))
-
-typedef PREPACK struct {
- s8 rssi;
- u8 info; /* usage of 'info' field(8-bit):
- * b1:b0 - WMI_MSG_TYPE
- * b4:b3:b2 - UP(tid)
- * b5 - Used in AP mode. More-data in tx dir, PS in rx.
- * b7:b6 - Dot3 header(0),
- * Dot11 Header(1),
- * ACL data(2)
- */
-
- u16 info2; /* usage of 'info2' field(16-bit):
- * b11:b0 - seq_no
- * b12 - A-MSDU?
- * b15:b13 - META_DATA_VERSION 0 - 7
- */
- u16 info3;
-} POSTPACK WMI_DATA_HDR;
-
-/*
- * TX META VERSION DEFINITIONS
- */
-#define WMI_MAX_TX_META_SZ (12)
-#define WMI_MAX_TX_META_VERSION (7)
-#define WMI_META_VERSION_1 (0x01)
-#define WMI_META_VERSION_2 (0X02)
-
-#define WMI_ACL_TO_DOT11_HEADROOM 36
-
-#if 0 /* removed to prevent compile errors for WM.. */
-typedef PREPACK struct {
-/* intentionally empty. Default version is no meta data. */
-} POSTPACK WMI_TX_META_V0;
-#endif
-
-typedef PREPACK struct {
- u8 pktID; /* The packet ID to identify the tx request */
- u8 ratePolicyID; /* The rate policy to be used for the tx of this frame */
-} POSTPACK WMI_TX_META_V1;
-
-
-#define WMI_CSUM_DIR_TX (0x1)
-#define TX_CSUM_CALC_FILL (0x1)
-typedef PREPACK struct {
- u8 csumStart; /*Offset from start of the WMI header for csum calculation to begin */
- u8 csumDest; /*Offset from start of WMI header where final csum goes*/
- u8 csumFlags; /*number of bytes over which csum is calculated*/
-} POSTPACK WMI_TX_META_V2;
-
-
-/*
- * RX META VERSION DEFINITIONS
- */
-/* if RX meta data is present at all then the meta data field
- * will consume WMI_MAX_RX_META_SZ bytes of space between the
- * WMI_DATA_HDR and the payload. How much of the available
- * Meta data is actually used depends on which meta data
- * version is active. */
-#define WMI_MAX_RX_META_SZ (12)
-#define WMI_MAX_RX_META_VERSION (7)
-
-#define WMI_RX_STATUS_OK 0 /* success */
-#define WMI_RX_STATUS_DECRYPT_ERR 1 /* decrypt error */
-#define WMI_RX_STATUS_MIC_ERR 2 /* tkip MIC error */
-#define WMI_RX_STATUS_ERR 3 /* undefined error */
-
-#define WMI_RX_FLAGS_AGGR 0x0001 /* part of AGGR */
-#define WMI_RX_FlAGS_STBC 0x0002 /* used STBC */
-#define WMI_RX_FLAGS_SGI 0x0004 /* used SGI */
-#define WMI_RX_FLAGS_HT 0x0008 /* is HT packet */
-/* the flags field is also used to store the CRYPTO_TYPE of the frame
- * that value is shifted by WMI_RX_FLAGS_CRYPTO_SHIFT */
-#define WMI_RX_FLAGS_CRYPTO_SHIFT 4
-#define WMI_RX_FLAGS_CRYPTO_MASK 0x1f
-#define WMI_RX_META_GET_CRYPTO(flags) (((flags) >> WMI_RX_FLAGS_CRYPTO_SHIFT) & WMI_RX_FLAGS_CRYPTO_MASK)
-
-#if 0 /* removed to prevent compile errors for WM.. */
-typedef PREPACK struct {
-/* intentionally empty. Default version is no meta data. */
-} POSTPACK WMI_RX_META_VERSION_0;
-#endif
-
-typedef PREPACK struct {
- u8 status; /* one of WMI_RX_STATUS_... */
- u8 rix; /* rate index mapped to rate at which this packet was received. */
- u8 rssi; /* rssi of packet */
- u8 channel;/* rf channel during packet reception */
- u16 flags; /* a combination of WMI_RX_FLAGS_... */
-} POSTPACK WMI_RX_META_V1;
-
-#define RX_CSUM_VALID_FLAG (0x1)
-typedef PREPACK struct {
- u16 csum;
- u8 csumFlags;/* bit 0 set -partial csum valid
- bit 1 set -test mode */
-} POSTPACK WMI_RX_META_V2;
-
-
-
-#define WMI_GET_DEVICE_ID(info1) ((info1) & 0xF)
-/* Macros for operating on WMI_CMD_HDR (info1) field */
-#define WMI_CMD_HDR_DEVID_MASK 0xF
-#define WMI_CMD_HDR_DEVID_SHIFT 0
-#define GET_CMD_DEVID(_v) ((_v) & WMI_CMD_HDR_DEVID_MASK)
-
-#define WMI_CMD_HDR_GET_DEVID(h) \
- (((h)->info1 >> WMI_CMD_HDR_DEVID_SHIFT) & WMI_CMD_HDR_DEVID_MASK)
-#define WMI_CMD_HDR_SET_DEVID(h, _v) \
- ((h)->info1 = ((h)->info1 & \
- ~(WMI_CMD_HDR_DEVID_MASK << WMI_CMD_HDR_DEVID_SHIFT)) | \
- (GET_CMD_DEVID(_v) << WMI_CMD_HDR_DEVID_SHIFT))
-
-/*
- * Control Path
- */
-typedef PREPACK struct {
- u16 commandId;
-/*
- * info1 - 16 bits
- * b03:b00 - id
- * b15:b04 - unused
- */
- u16 info1;
-
- u16 reserved; /* For alignment */
-} POSTPACK WMI_CMD_HDR; /* used for commands and events */
-
-/*
- * List of Commnands
- */
-typedef enum {
- WMI_CONNECT_CMDID = 0x0001,
- WMI_RECONNECT_CMDID,
- WMI_DISCONNECT_CMDID,
- WMI_SYNCHRONIZE_CMDID,
- WMI_CREATE_PSTREAM_CMDID,
- WMI_DELETE_PSTREAM_CMDID,
- WMI_START_SCAN_CMDID,
- WMI_SET_SCAN_PARAMS_CMDID,
- WMI_SET_BSS_FILTER_CMDID,
- WMI_SET_PROBED_SSID_CMDID, /* 10 */
- WMI_SET_LISTEN_INT_CMDID,
- WMI_SET_BMISS_TIME_CMDID,
- WMI_SET_DISC_TIMEOUT_CMDID,
- WMI_GET_CHANNEL_LIST_CMDID,
- WMI_SET_BEACON_INT_CMDID,
- WMI_GET_STATISTICS_CMDID,
- WMI_SET_CHANNEL_PARAMS_CMDID,
- WMI_SET_POWER_MODE_CMDID,
- WMI_SET_IBSS_PM_CAPS_CMDID,
- WMI_SET_POWER_PARAMS_CMDID, /* 20 */
- WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
- WMI_ADD_CIPHER_KEY_CMDID,
- WMI_DELETE_CIPHER_KEY_CMDID,
- WMI_ADD_KRK_CMDID,
- WMI_DELETE_KRK_CMDID,
- WMI_SET_PMKID_CMDID,
- WMI_SET_TX_PWR_CMDID,
- WMI_GET_TX_PWR_CMDID,
- WMI_SET_ASSOC_INFO_CMDID,
- WMI_ADD_BAD_AP_CMDID, /* 30 */
- WMI_DELETE_BAD_AP_CMDID,
- WMI_SET_TKIP_COUNTERMEASURES_CMDID,
- WMI_RSSI_THRESHOLD_PARAMS_CMDID,
- WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
- WMI_SET_ACCESS_PARAMS_CMDID,
- WMI_SET_RETRY_LIMITS_CMDID,
- WMI_SET_OPT_MODE_CMDID,
- WMI_OPT_TX_FRAME_CMDID,
- WMI_SET_VOICE_PKT_SIZE_CMDID,
- WMI_SET_MAX_SP_LEN_CMDID, /* 40 */
- WMI_SET_ROAM_CTRL_CMDID,
- WMI_GET_ROAM_TBL_CMDID,
- WMI_GET_ROAM_DATA_CMDID,
- WMI_ENABLE_RM_CMDID,
- WMI_SET_MAX_OFFHOME_DURATION_CMDID,
- WMI_EXTENSION_CMDID, /* Non-wireless extensions */
- WMI_SNR_THRESHOLD_PARAMS_CMDID,
- WMI_LQ_THRESHOLD_PARAMS_CMDID,
- WMI_SET_LPREAMBLE_CMDID,
- WMI_SET_RTS_CMDID, /* 50 */
- WMI_CLR_RSSI_SNR_CMDID,
- WMI_SET_FIXRATES_CMDID,
- WMI_GET_FIXRATES_CMDID,
- WMI_SET_AUTH_MODE_CMDID,
- WMI_SET_REASSOC_MODE_CMDID,
- WMI_SET_WMM_CMDID,
- WMI_SET_WMM_TXOP_CMDID,
- WMI_TEST_CMDID,
- /* COEX AR6002 only*/
- WMI_SET_BT_STATUS_CMDID,
- WMI_SET_BT_PARAMS_CMDID, /* 60 */
-
- WMI_SET_KEEPALIVE_CMDID,
- WMI_GET_KEEPALIVE_CMDID,
- WMI_SET_APPIE_CMDID,
- WMI_GET_APPIE_CMDID,
- WMI_SET_WSC_STATUS_CMDID,
-
- /* Wake on Wireless */
- WMI_SET_HOST_SLEEP_MODE_CMDID,
- WMI_SET_WOW_MODE_CMDID,
- WMI_GET_WOW_LIST_CMDID,
- WMI_ADD_WOW_PATTERN_CMDID,
- WMI_DEL_WOW_PATTERN_CMDID, /* 70 */
-
- WMI_SET_FRAMERATES_CMDID,
- WMI_SET_AP_PS_CMDID,
- WMI_SET_QOS_SUPP_CMDID,
- /* WMI_THIN_RESERVED_... mark the start and end
- * values for WMI_THIN_RESERVED command IDs. These
- * command IDs can be found in wmi_thin.h */
- WMI_THIN_RESERVED_START = 0x8000,
- WMI_THIN_RESERVED_END = 0x8fff,
- /*
- * Developer commands starts at 0xF000
- */
- WMI_SET_BITRATE_CMDID = 0xF000,
- WMI_GET_BITRATE_CMDID,
- WMI_SET_WHALPARAM_CMDID,
-
-
- /*Should add the new command to the tail for compatible with
- * etna.
- */
- WMI_SET_MAC_ADDRESS_CMDID,
- WMI_SET_AKMP_PARAMS_CMDID,
- WMI_SET_PMKID_LIST_CMDID,
- WMI_GET_PMKID_LIST_CMDID,
- WMI_ABORT_SCAN_CMDID,
- WMI_SET_TARGET_EVENT_REPORT_CMDID,
-
- // Unused
- WMI_UNUSED1,
- WMI_UNUSED2,
-
- /*
- * AP mode commands
- */
- WMI_AP_HIDDEN_SSID_CMDID,
- WMI_AP_SET_NUM_STA_CMDID,
- WMI_AP_ACL_POLICY_CMDID,
- WMI_AP_ACL_MAC_LIST_CMDID,
- WMI_AP_CONFIG_COMMIT_CMDID,
- WMI_AP_SET_MLME_CMDID,
- WMI_AP_SET_PVB_CMDID,
- WMI_AP_CONN_INACT_CMDID,
- WMI_AP_PROT_SCAN_TIME_CMDID,
- WMI_AP_SET_COUNTRY_CMDID,
- WMI_AP_SET_DTIM_CMDID,
- WMI_AP_MODE_STAT_CMDID,
-
- WMI_SET_IP_CMDID,
- WMI_SET_PARAMS_CMDID,
- WMI_SET_MCAST_FILTER_CMDID,
- WMI_DEL_MCAST_FILTER_CMDID,
-
- WMI_ALLOW_AGGR_CMDID,
- WMI_ADDBA_REQ_CMDID,
- WMI_DELBA_REQ_CMDID,
- WMI_SET_HT_CAP_CMDID,
- WMI_SET_HT_OP_CMDID,
- WMI_SET_TX_SELECT_RATES_CMDID,
- WMI_SET_TX_SGI_PARAM_CMDID,
- WMI_SET_RATE_POLICY_CMDID,
-
- WMI_HCI_CMD_CMDID,
- WMI_RX_FRAME_FORMAT_CMDID,
- WMI_SET_THIN_MODE_CMDID,
- WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID,
-
- WMI_AP_SET_11BG_RATESET_CMDID,
- WMI_SET_PMK_CMDID,
- WMI_MCAST_FILTER_CMDID,
- /* COEX CMDID AR6003*/
- WMI_SET_BTCOEX_FE_ANT_CMDID,
- WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
- WMI_SET_BTCOEX_SCO_CONFIG_CMDID,
- WMI_SET_BTCOEX_A2DP_CONFIG_CMDID,
- WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID,
- WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
- WMI_SET_BTCOEX_DEBUG_CMDID,
- WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID,
- WMI_GET_BTCOEX_STATS_CMDID,
- WMI_GET_BTCOEX_CONFIG_CMDID,
-
- WMI_SET_DFS_ENABLE_CMDID, /* F034 */
- WMI_SET_DFS_MINRSSITHRESH_CMDID,
- WMI_SET_DFS_MAXPULSEDUR_CMDID,
- WMI_DFS_RADAR_DETECTED_CMDID,
-
- /* P2P CMDS */
- WMI_P2P_SET_CONFIG_CMDID, /* F038 */
- WMI_WPS_SET_CONFIG_CMDID,
- WMI_SET_REQ_DEV_ATTR_CMDID,
- WMI_P2P_FIND_CMDID,
- WMI_P2P_STOP_FIND_CMDID,
- WMI_P2P_GO_NEG_START_CMDID,
- WMI_P2P_LISTEN_CMDID,
-
- WMI_CONFIG_TX_MAC_RULES_CMDID, /* F040 */
- WMI_SET_PROMISCUOUS_MODE_CMDID,
- WMI_RX_FRAME_FILTER_CMDID,
- WMI_SET_CHANNEL_CMDID,
-
- /* WAC commands */
- WMI_ENABLE_WAC_CMDID,
- WMI_WAC_SCAN_REPLY_CMDID,
- WMI_WAC_CTRL_REQ_CMDID,
- WMI_SET_DIV_PARAMS_CMDID,
-
- WMI_GET_PMK_CMDID,
- WMI_SET_PASSPHRASE_CMDID,
- WMI_SEND_ASSOC_RES_CMDID,
- WMI_SET_ASSOC_REQ_RELAY_CMDID,
- WMI_GET_RFKILL_MODE_CMDID,
-
- /* ACS command, consists of sub-commands */
- WMI_ACS_CTRL_CMDID,
-
- /* Ultra low power store / recall commands */
- WMI_STORERECALL_CONFIGURE_CMDID,
- WMI_STORERECALL_RECALL_CMDID,
- WMI_STORERECALL_HOST_READY_CMDID,
- WMI_FORCE_TARGET_ASSERT_CMDID,
- WMI_SET_EXCESS_TX_RETRY_THRES_CMDID,
-} WMI_COMMAND_ID;
-
-/*
- * Frame Types
- */
-typedef enum {
- WMI_FRAME_BEACON = 0,
- WMI_FRAME_PROBE_REQ,
- WMI_FRAME_PROBE_RESP,
- WMI_FRAME_ASSOC_REQ,
- WMI_FRAME_ASSOC_RESP,
- WMI_NUM_MGMT_FRAME
-} WMI_MGMT_FRAME_TYPE;
-
-/*
- * Connect Command
- */
-typedef enum {
- INFRA_NETWORK = 0x01,
- ADHOC_NETWORK = 0x02,
- ADHOC_CREATOR = 0x04,
- AP_NETWORK = 0x10,
-} NETWORK_TYPE;
-
-typedef enum {
- OPEN_AUTH = 0x01,
- SHARED_AUTH = 0x02,
- LEAP_AUTH = 0x04, /* different from IEEE_AUTH_MODE definitions */
-} DOT11_AUTH_MODE;
-
-enum {
- AUTH_IDLE,
- AUTH_OPEN_IN_PROGRESS,
-};
-
-typedef enum {
- NONE_AUTH = 0x01,
- WPA_AUTH = 0x02,
- WPA2_AUTH = 0x04,
- WPA_PSK_AUTH = 0x08,
- WPA2_PSK_AUTH = 0x10,
- WPA_AUTH_CCKM = 0x20,
- WPA2_AUTH_CCKM = 0x40,
-} AUTH_MODE;
-
-typedef enum {
- NONE_CRYPT = 0x01,
- WEP_CRYPT = 0x02,
- TKIP_CRYPT = 0x04,
- AES_CRYPT = 0x08,
-#ifdef WAPI_ENABLE
- WAPI_CRYPT = 0x10,
-#endif /*WAPI_ENABLE*/
-} CRYPTO_TYPE;
-
-#define WMI_MIN_CRYPTO_TYPE NONE_CRYPT
-#define WMI_MAX_CRYPTO_TYPE (AES_CRYPT + 1)
-
-#ifdef WAPI_ENABLE
-#undef WMI_MAX_CRYPTO_TYPE
-#define WMI_MAX_CRYPTO_TYPE (WAPI_CRYPT + 1)
-#endif /* WAPI_ENABLE */
-
-#ifdef WAPI_ENABLE
-#define IW_ENCODE_ALG_SM4 0x20
-#define IW_AUTH_WAPI_ENABLED 0x20
-#endif
-
-#define WMI_MIN_KEY_INDEX 0
-#define WMI_MAX_KEY_INDEX 3
-
-#ifdef WAPI_ENABLE
-#undef WMI_MAX_KEY_INDEX
-#define WMI_MAX_KEY_INDEX 7 /* wapi grpKey 0-3, prwKey 4-7 */
-#endif /* WAPI_ENABLE */
-
-#define WMI_MAX_KEY_LEN 32
-
-#define WMI_MAX_SSID_LEN 32
-
-typedef enum {
- CONNECT_ASSOC_POLICY_USER = 0x0001,
- CONNECT_SEND_REASSOC = 0x0002,
- CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004,
- CONNECT_PROFILE_MATCH_DONE = 0x0008,
- CONNECT_IGNORE_AAC_BEACON = 0x0010,
- CONNECT_CSA_FOLLOW_BSS = 0x0020,
- CONNECT_DO_WPA_OFFLOAD = 0x0040,
- CONNECT_DO_NOT_DEAUTH = 0x0080,
-} WMI_CONNECT_CTRL_FLAGS_BITS;
-
-#define DEFAULT_CONNECT_CTRL_FLAGS (CONNECT_CSA_FOLLOW_BSS)
-
-typedef PREPACK struct {
- u8 networkType;
- u8 dot11AuthMode;
- u8 authMode;
- u8 pairwiseCryptoType;
- u8 pairwiseCryptoLen;
- u8 groupCryptoType;
- u8 groupCryptoLen;
- u8 ssidLength;
- u8 ssid[WMI_MAX_SSID_LEN];
- u16 channel;
- u8 bssid[ATH_MAC_LEN];
- u32 ctrl_flags;
-} POSTPACK WMI_CONNECT_CMD;
-
-/*
- * WMI_RECONNECT_CMDID
- */
-typedef PREPACK struct {
- u16 channel; /* hint */
- u8 bssid[ATH_MAC_LEN]; /* mandatory if set */
-} POSTPACK WMI_RECONNECT_CMD;
-
-#define WMI_PMK_LEN 32
-typedef PREPACK struct {
- u8 pmk[WMI_PMK_LEN];
-} POSTPACK WMI_SET_PMK_CMD;
-
-/*
- * WMI_SET_EXCESS_TX_RETRY_THRES_CMDID
- */
-typedef PREPACK struct {
- u32 threshold;
-} POSTPACK WMI_SET_EXCESS_TX_RETRY_THRES_CMD;
-
-/*
- * WMI_ADD_CIPHER_KEY_CMDID
- */
-typedef enum {
- PAIRWISE_USAGE = 0x00,
- GROUP_USAGE = 0x01,
- TX_USAGE = 0x02, /* default Tx Key - Static WEP only */
-} KEY_USAGE;
-
-/*
- * Bit Flag
- * Bit 0 - Initialise TSC - default is Initialize
- */
-#define KEY_OP_INIT_TSC 0x01
-#define KEY_OP_INIT_RSC 0x02
-#ifdef WAPI_ENABLE
-#define KEY_OP_INIT_WAPIPN 0x10
-#endif /* WAPI_ENABLE */
-
-#define KEY_OP_INIT_VAL 0x03 /* Default Initialise the TSC & RSC */
-#define KEY_OP_VALID_MASK 0x03
-
-typedef PREPACK struct {
- u8 keyIndex;
- u8 keyType;
- u8 keyUsage; /* KEY_USAGE */
- u8 keyLength;
- u8 keyRSC[8]; /* key replay sequence counter */
- u8 key[WMI_MAX_KEY_LEN];
- u8 key_op_ctrl; /* Additional Key Control information */
- u8 key_macaddr[ATH_MAC_LEN];
-} POSTPACK WMI_ADD_CIPHER_KEY_CMD;
-
-/*
- * WMI_DELETE_CIPHER_KEY_CMDID
- */
-typedef PREPACK struct {
- u8 keyIndex;
-} POSTPACK WMI_DELETE_CIPHER_KEY_CMD;
-
-#define WMI_KRK_LEN 16
-/*
- * WMI_ADD_KRK_CMDID
- */
-typedef PREPACK struct {
- u8 krk[WMI_KRK_LEN];
-} POSTPACK WMI_ADD_KRK_CMD;
-
-/*
- * WMI_SET_TKIP_COUNTERMEASURES_CMDID
- */
-typedef enum {
- WMI_TKIP_CM_DISABLE = 0x0,
- WMI_TKIP_CM_ENABLE = 0x1,
-} WMI_TKIP_CM_CONTROL;
-
-typedef PREPACK struct {
- u8 cm_en; /* WMI_TKIP_CM_CONTROL */
-} POSTPACK WMI_SET_TKIP_COUNTERMEASURES_CMD;
-
-/*
- * WMI_SET_PMKID_CMDID
- */
-
-#define WMI_PMKID_LEN 16
-
-typedef enum {
- PMKID_DISABLE = 0,
- PMKID_ENABLE = 1,
-} PMKID_ENABLE_FLG;
-
-typedef PREPACK struct {
- u8 bssid[ATH_MAC_LEN];
- u8 enable; /* PMKID_ENABLE_FLG */
- u8 pmkid[WMI_PMKID_LEN];
-} POSTPACK WMI_SET_PMKID_CMD;
-
-/*
- * WMI_START_SCAN_CMD
- */
-typedef enum {
- WMI_LONG_SCAN = 0,
- WMI_SHORT_SCAN = 1,
-} WMI_SCAN_TYPE;
-
-typedef PREPACK struct {
- u32 forceFgScan;
- u32 isLegacy; /* For Legacy Cisco AP compatibility */
- u32 homeDwellTime; /* Maximum duration in the home channel(milliseconds) */
- u32 forceScanInterval; /* Time interval between scans (milliseconds)*/
- u8 scanType; /* WMI_SCAN_TYPE */
- u8 numChannels; /* how many channels follow */
- u16 channelList[1]; /* channels in Mhz */
-} POSTPACK WMI_START_SCAN_CMD;
-
-/*
- * WMI_SET_SCAN_PARAMS_CMDID
- */
-#define WMI_SHORTSCANRATIO_DEFAULT 3
-/*
- * Warning: ScanCtrlFlag value of 0xFF is used to disable all flags in WMI_SCAN_PARAMS_CMD
- * Do not add any more flags to WMI_SCAN_CTRL_FLAG_BITS
- */
-typedef enum {
- CONNECT_SCAN_CTRL_FLAGS = 0x01, /* set if can scan in the Connect cmd */
- SCAN_CONNECTED_CTRL_FLAGS = 0x02, /* set if scan for the SSID it is */
- /* already connected to */
- ACTIVE_SCAN_CTRL_FLAGS = 0x04, /* set if enable active scan */
- ROAM_SCAN_CTRL_FLAGS = 0x08, /* set if enable roam scan when bmiss and lowrssi */
- REPORT_BSSINFO_CTRL_FLAGS = 0x10, /* set if follows customer BSSINFO reporting rule */
- ENABLE_AUTO_CTRL_FLAGS = 0x20, /* if disabled, target doesn't
- scan after a disconnect event */
- ENABLE_SCAN_ABORT_EVENT = 0x40 /* Scan complete event with canceled status will be generated when a scan is prempted before it gets completed */
-} WMI_SCAN_CTRL_FLAGS_BITS;
-
-#define CAN_SCAN_IN_CONNECT(flags) (flags & CONNECT_SCAN_CTRL_FLAGS)
-#define CAN_SCAN_CONNECTED(flags) (flags & SCAN_CONNECTED_CTRL_FLAGS)
-#define ENABLE_ACTIVE_SCAN(flags) (flags & ACTIVE_SCAN_CTRL_FLAGS)
-#define ENABLE_ROAM_SCAN(flags) (flags & ROAM_SCAN_CTRL_FLAGS)
-#define CONFIG_REPORT_BSSINFO(flags) (flags & REPORT_BSSINFO_CTRL_FLAGS)
-#define IS_AUTO_SCAN_ENABLED(flags) (flags & ENABLE_AUTO_CTRL_FLAGS)
-#define SCAN_ABORT_EVENT_ENABLED(flags) (flags & ENABLE_SCAN_ABORT_EVENT)
-
-#define DEFAULT_SCAN_CTRL_FLAGS (CONNECT_SCAN_CTRL_FLAGS| SCAN_CONNECTED_CTRL_FLAGS| ACTIVE_SCAN_CTRL_FLAGS| ROAM_SCAN_CTRL_FLAGS | ENABLE_AUTO_CTRL_FLAGS)
-
-
-typedef PREPACK struct {
- u16 fg_start_period; /* seconds */
- u16 fg_end_period; /* seconds */
- u16 bg_period; /* seconds */
- u16 maxact_chdwell_time; /* msec */
- u16 pas_chdwell_time; /* msec */
- u8 shortScanRatio; /* how many shorts scan for one long */
- u8 scanCtrlFlags;
- u16 minact_chdwell_time; /* msec */
- u16 maxact_scan_per_ssid; /* max active scans per ssid */
- u32 max_dfsch_act_time; /* msecs */
-} POSTPACK WMI_SCAN_PARAMS_CMD;
-
-/*
- * WMI_SET_BSS_FILTER_CMDID
- */
-typedef enum {
- NONE_BSS_FILTER = 0x0, /* no beacons forwarded */
- ALL_BSS_FILTER, /* all beacons forwarded */
- PROFILE_FILTER, /* only beacons matching profile */
- ALL_BUT_PROFILE_FILTER, /* all but beacons matching profile */
- CURRENT_BSS_FILTER, /* only beacons matching current BSS */
- ALL_BUT_BSS_FILTER, /* all but beacons matching BSS */
- PROBED_SSID_FILTER, /* beacons matching probed ssid */
- LAST_BSS_FILTER, /* marker only */
-} WMI_BSS_FILTER;
-
-typedef PREPACK struct {
- u8 bssFilter; /* see WMI_BSS_FILTER */
- u8 reserved1; /* For alignment */
- u16 reserved2; /* For alignment */
- u32 ieMask;
-} POSTPACK WMI_BSS_FILTER_CMD;
-
-/*
- * WMI_SET_PROBED_SSID_CMDID
- */
-#define MAX_PROBED_SSID_INDEX 9
-
-typedef enum {
- DISABLE_SSID_FLAG = 0, /* disables entry */
- SPECIFIC_SSID_FLAG = 0x01, /* probes specified ssid */
- ANY_SSID_FLAG = 0x02, /* probes for any ssid */
-} WMI_SSID_FLAG;
-
-typedef PREPACK struct {
- u8 entryIndex; /* 0 to MAX_PROBED_SSID_INDEX */
- u8 flag; /* WMI_SSID_FLG */
- u8 ssidLength;
- u8 ssid[32];
-} POSTPACK WMI_PROBED_SSID_CMD;
-
-/*
- * WMI_SET_LISTEN_INT_CMDID
- * The Listen interval is between 15 and 3000 TUs
- */
-#define MIN_LISTEN_INTERVAL 15
-#define MAX_LISTEN_INTERVAL 5000
-#define MIN_LISTEN_BEACONS 1
-#define MAX_LISTEN_BEACONS 50
-
-typedef PREPACK struct {
- u16 listenInterval;
- u16 numBeacons;
-} POSTPACK WMI_LISTEN_INT_CMD;
-
-/*
- * WMI_SET_BEACON_INT_CMDID
- */
-typedef PREPACK struct {
- u16 beaconInterval;
-} POSTPACK WMI_BEACON_INT_CMD;
-
-/*
- * WMI_SET_BMISS_TIME_CMDID
- * valid values are between 1000 and 5000 TUs
- */
-
-#define MIN_BMISS_TIME 1000
-#define MAX_BMISS_TIME 5000
-#define MIN_BMISS_BEACONS 1
-#define MAX_BMISS_BEACONS 50
-
-typedef PREPACK struct {
- u16 bmissTime;
- u16 numBeacons;
-} POSTPACK WMI_BMISS_TIME_CMD;
-
-/*
- * WMI_SET_POWER_MODE_CMDID
- */
-typedef enum {
- REC_POWER = 0x01,
- MAX_PERF_POWER,
-} WMI_POWER_MODE;
-
-typedef PREPACK struct {
- u8 powerMode; /* WMI_POWER_MODE */
-} POSTPACK WMI_POWER_MODE_CMD;
-
-typedef PREPACK struct {
- s8 status; /* WMI_SET_PARAMS_REPLY */
-} POSTPACK WMI_SET_PARAMS_REPLY;
-
-typedef PREPACK struct {
- u32 opcode;
- u32 length;
- char buffer[1]; /* WMI_SET_PARAMS */
-} POSTPACK WMI_SET_PARAMS_CMD;
-
-typedef PREPACK struct {
- u8 multicast_mac[ATH_MAC_LEN]; /* WMI_SET_MCAST_FILTER */
-} POSTPACK WMI_SET_MCAST_FILTER_CMD;
-
-typedef PREPACK struct {
- u8 enable; /* WMI_MCAST_FILTER */
-} POSTPACK WMI_MCAST_FILTER_CMD;
-
-/*
- * WMI_SET_POWER_PARAMS_CMDID
- */
-typedef enum {
- IGNORE_DTIM = 0x01,
- NORMAL_DTIM = 0x02,
- STICK_DTIM = 0x03,
- AUTO_DTIM = 0x04,
-} WMI_DTIM_POLICY;
-
-/* Policy to determnine whether TX should wakeup WLAN if sleeping */
-typedef enum {
- TX_WAKEUP_UPON_SLEEP = 1,
- TX_DONT_WAKEUP_UPON_SLEEP = 2
-} WMI_TX_WAKEUP_POLICY_UPON_SLEEP;
-
-/*
- * Policy to determnine whether power save failure event should be sent to
- * host during scanning
- */
-typedef enum {
- SEND_POWER_SAVE_FAIL_EVENT_ALWAYS = 1,
- IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN = 2,
-} POWER_SAVE_FAIL_EVENT_POLICY;
-
-typedef PREPACK struct {
- u16 idle_period; /* msec */
- u16 pspoll_number;
- u16 dtim_policy;
- u16 tx_wakeup_policy;
- u16 num_tx_to_wakeup;
- u16 ps_fail_event_policy;
-} POSTPACK WMI_POWER_PARAMS_CMD;
-
-/* Adhoc power save types */
-typedef enum {
- ADHOC_PS_DISABLE=1,
- ADHOC_PS_ATH=2,
- ADHOC_PS_IEEE=3,
- ADHOC_PS_OTHER=4,
-} WMI_ADHOC_PS_TYPE;
-
-typedef PREPACK struct {
- u8 power_saving;
- u8 ttl; /* number of beacon periods */
- u16 atim_windows; /* msec */
- u16 timeout_value; /* msec */
-} POSTPACK WMI_IBSS_PM_CAPS_CMD;
-
-/* AP power save types */
-typedef enum {
- AP_PS_DISABLE=1,
- AP_PS_ATH=2,
-} WMI_AP_PS_TYPE;
-
-typedef PREPACK struct {
- u32 idle_time; /* in msec */
- u32 ps_period; /* in usec */
- u8 sleep_period; /* in ps periods */
- u8 psType;
-} POSTPACK WMI_AP_PS_CMD;
-
-/*
- * WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID
- */
-typedef enum {
- IGNORE_TIM_ALL_QUEUES_APSD = 0,
- PROCESS_TIM_ALL_QUEUES_APSD = 1,
- IGNORE_TIM_SIMULATED_APSD = 2,
- PROCESS_TIM_SIMULATED_APSD = 3,
-} APSD_TIM_POLICY;
-
-typedef PREPACK struct {
- u16 psPollTimeout; /* msec */
- u16 triggerTimeout; /* msec */
- u32 apsdTimPolicy; /* TIM behavior with ques APSD enabled. Default is IGNORE_TIM_ALL_QUEUES_APSD */
- u32 simulatedAPSDTimPolicy; /* TIM behavior with simulated APSD enabled. Default is PROCESS_TIM_SIMULATED_APSD */
-} POSTPACK WMI_POWERSAVE_TIMERS_POLICY_CMD;
-
-/*
- * WMI_SET_VOICE_PKT_SIZE_CMDID
- */
-typedef PREPACK struct {
- u16 voicePktSize;
-} POSTPACK WMI_SET_VOICE_PKT_SIZE_CMD;
-
-/*
- * WMI_SET_MAX_SP_LEN_CMDID
- */
-typedef enum {
- DELIVER_ALL_PKT = 0x0,
- DELIVER_2_PKT = 0x1,
- DELIVER_4_PKT = 0x2,
- DELIVER_6_PKT = 0x3,
-} APSD_SP_LEN_TYPE;
-
-typedef PREPACK struct {
- u8 maxSPLen;
-} POSTPACK WMI_SET_MAX_SP_LEN_CMD;
-
-/*
- * WMI_SET_DISC_TIMEOUT_CMDID
- */
-typedef PREPACK struct {
- u8 disconnectTimeout; /* seconds */
-} POSTPACK WMI_DISC_TIMEOUT_CMD;
-
-typedef enum {
- UPLINK_TRAFFIC = 0,
- DNLINK_TRAFFIC = 1,
- BIDIR_TRAFFIC = 2,
-} DIR_TYPE;
-
-typedef enum {
- DISABLE_FOR_THIS_AC = 0,
- ENABLE_FOR_THIS_AC = 1,
- ENABLE_FOR_ALL_AC = 2,
-} VOICEPS_CAP_TYPE;
-
-typedef enum {
- TRAFFIC_TYPE_APERIODIC = 0,
- TRAFFIC_TYPE_PERIODIC = 1,
-}TRAFFIC_TYPE;
-
-/*
- * WMI_SYNCHRONIZE_CMDID
- */
-typedef PREPACK struct {
- u8 dataSyncMap;
-} POSTPACK WMI_SYNC_CMD;
-
-/*
- * WMI_CREATE_PSTREAM_CMDID
- */
-typedef PREPACK struct {
- u32 minServiceInt; /* in milli-sec */
- u32 maxServiceInt; /* in milli-sec */
- u32 inactivityInt; /* in milli-sec */
- u32 suspensionInt; /* in milli-sec */
- u32 serviceStartTime;
- u32 minDataRate; /* in bps */
- u32 meanDataRate; /* in bps */
- u32 peakDataRate; /* in bps */
- u32 maxBurstSize;
- u32 delayBound;
- u32 minPhyRate; /* in bps */
- u32 sba;
- u32 mediumTime;
- u16 nominalMSDU; /* in octects */
- u16 maxMSDU; /* in octects */
- u8 trafficClass;
- u8 trafficDirection; /* DIR_TYPE */
- u8 rxQueueNum;
- u8 trafficType; /* TRAFFIC_TYPE */
- u8 voicePSCapability; /* VOICEPS_CAP_TYPE */
- u8 tsid;
- u8 userPriority; /* 802.1D user priority */
- u8 nominalPHY; /* nominal phy rate */
-} POSTPACK WMI_CREATE_PSTREAM_CMD;
-
-/*
- * WMI_DELETE_PSTREAM_CMDID
- */
-typedef PREPACK struct {
- u8 txQueueNumber;
- u8 rxQueueNumber;
- u8 trafficDirection;
- u8 trafficClass;
- u8 tsid;
-} POSTPACK WMI_DELETE_PSTREAM_CMD;
-
-/*
- * WMI_SET_CHANNEL_PARAMS_CMDID
- */
-typedef enum {
- WMI_11A_MODE = 0x1,
- WMI_11G_MODE = 0x2,
- WMI_11AG_MODE = 0x3,
- WMI_11B_MODE = 0x4,
- WMI_11GONLY_MODE = 0x5,
-} WMI_PHY_MODE;
-
-#define WMI_MAX_CHANNELS 32
-
-typedef PREPACK struct {
- u8 reserved1;
- u8 scanParam; /* set if enable scan */
- u8 phyMode; /* see WMI_PHY_MODE */
- u8 numChannels; /* how many channels follow */
- u16 channelList[1]; /* channels in Mhz */
-} POSTPACK WMI_CHANNEL_PARAMS_CMD;
-
-
-/*
- * WMI_RSSI_THRESHOLD_PARAMS_CMDID
- * Setting the polltime to 0 would disable polling.
- * Threshold values are in the ascending order, and should agree to:
- * (lowThreshold_lowerVal < lowThreshold_upperVal < highThreshold_lowerVal
- * < highThreshold_upperVal)
- */
-
-typedef PREPACK struct WMI_RSSI_THRESHOLD_PARAMS{
- u32 pollTime; /* Polling time as a factor of LI */
- s16 thresholdAbove1_Val; /* lowest of upper */
- s16 thresholdAbove2_Val;
- s16 thresholdAbove3_Val;
- s16 thresholdAbove4_Val;
- s16 thresholdAbove5_Val;
- s16 thresholdAbove6_Val; /* highest of upper */
- s16 thresholdBelow1_Val; /* lowest of bellow */
- s16 thresholdBelow2_Val;
- s16 thresholdBelow3_Val;
- s16 thresholdBelow4_Val;
- s16 thresholdBelow5_Val;
- s16 thresholdBelow6_Val; /* highest of bellow */
- u8 weight; /* "alpha" */
- u8 reserved[3];
-} POSTPACK WMI_RSSI_THRESHOLD_PARAMS_CMD;
-
-/*
- * WMI_SNR_THRESHOLD_PARAMS_CMDID
- * Setting the polltime to 0 would disable polling.
- */
-
-typedef PREPACK struct WMI_SNR_THRESHOLD_PARAMS{
- u32 pollTime; /* Polling time as a factor of LI */
- u8 weight; /* "alpha" */
- u8 thresholdAbove1_Val; /* lowest of uppper*/
- u8 thresholdAbove2_Val;
- u8 thresholdAbove3_Val;
- u8 thresholdAbove4_Val; /* highest of upper */
- u8 thresholdBelow1_Val; /* lowest of bellow */
- u8 thresholdBelow2_Val;
- u8 thresholdBelow3_Val;
- u8 thresholdBelow4_Val; /* highest of bellow */
- u8 reserved[3];
-} POSTPACK WMI_SNR_THRESHOLD_PARAMS_CMD;
-
-/*
- * WMI_LQ_THRESHOLD_PARAMS_CMDID
- */
-typedef PREPACK struct WMI_LQ_THRESHOLD_PARAMS {
- u8 enable;
- u8 thresholdAbove1_Val;
- u8 thresholdAbove2_Val;
- u8 thresholdAbove3_Val;
- u8 thresholdAbove4_Val;
- u8 thresholdBelow1_Val;
- u8 thresholdBelow2_Val;
- u8 thresholdBelow3_Val;
- u8 thresholdBelow4_Val;
- u8 reserved[3];
-} POSTPACK WMI_LQ_THRESHOLD_PARAMS_CMD;
-
-typedef enum {
- WMI_LPREAMBLE_DISABLED = 0,
- WMI_LPREAMBLE_ENABLED
-} WMI_LPREAMBLE_STATUS;
-
-typedef enum {
- WMI_IGNORE_BARKER_IN_ERP = 0,
- WMI_DONOT_IGNORE_BARKER_IN_ERP
-} WMI_PREAMBLE_POLICY;
-
-typedef PREPACK struct {
- u8 status;
- u8 preamblePolicy;
-}POSTPACK WMI_SET_LPREAMBLE_CMD;
-
-typedef PREPACK struct {
- u16 threshold;
-}POSTPACK WMI_SET_RTS_CMD;
-
-/*
- * WMI_TARGET_ERROR_REPORT_BITMASK_CMDID
- * Sets the error reporting event bitmask in target. Target clears it
- * upon an error. Subsequent errors are counted, but not reported
- * via event, unless the bitmask is set again.
- */
-typedef PREPACK struct {
- u32 bitmask;
-} POSTPACK WMI_TARGET_ERROR_REPORT_BITMASK;
-
-/*
- * WMI_SET_TX_PWR_CMDID
- */
-typedef PREPACK struct {
- u8 dbM; /* in dbM units */
-} POSTPACK WMI_SET_TX_PWR_CMD, WMI_TX_PWR_REPLY;
-
-/*
- * WMI_SET_ASSOC_INFO_CMDID
- *
- * A maximum of 2 private IEs can be sent in the [Re]Assoc request.
- * A 3rd one, the CCX version IE can also be set from the host.
- */
-#define WMI_MAX_ASSOC_INFO_TYPE 2
-#define WMI_CCX_VER_IE 2 /* ieType to set CCX Version IE */
-
-#define WMI_MAX_ASSOC_INFO_LEN 240
-
-typedef PREPACK struct {
- u8 ieType;
- u8 bufferSize;
- u8 assocInfo[1]; /* up to WMI_MAX_ASSOC_INFO_LEN */
-} POSTPACK WMI_SET_ASSOC_INFO_CMD;
-
-
-/*
- * WMI_GET_TX_PWR_CMDID does not take any parameters
- */
-
-/*
- * WMI_ADD_BAD_AP_CMDID
- */
-#define WMI_MAX_BAD_AP_INDEX 1
-
-typedef PREPACK struct {
- u8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */
- u8 bssid[ATH_MAC_LEN];
-} POSTPACK WMI_ADD_BAD_AP_CMD;
-
-/*
- * WMI_DELETE_BAD_AP_CMDID
- */
-typedef PREPACK struct {
- u8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */
-} POSTPACK WMI_DELETE_BAD_AP_CMD;
-
-/*
- * WMI_SET_ACCESS_PARAMS_CMDID
- */
-#define WMI_DEFAULT_TXOP_ACPARAM 0 /* implies one MSDU */
-#define WMI_DEFAULT_ECWMIN_ACPARAM 4 /* corresponds to CWmin of 15 */
-#define WMI_DEFAULT_ECWMAX_ACPARAM 10 /* corresponds to CWmax of 1023 */
-#define WMI_MAX_CW_ACPARAM 15 /* maximum eCWmin or eCWmax */
-#define WMI_DEFAULT_AIFSN_ACPARAM 2
-#define WMI_MAX_AIFSN_ACPARAM 15
-typedef PREPACK struct {
- u16 txop; /* in units of 32 usec */
- u8 eCWmin;
- u8 eCWmax;
- u8 aifsn;
- u8 ac;
-} POSTPACK WMI_SET_ACCESS_PARAMS_CMD;
-
-
-/*
- * WMI_SET_RETRY_LIMITS_CMDID
- *
- * This command is used to customize the number of retries the
- * wlan device will perform on a given frame.
- */
-#define WMI_MIN_RETRIES 2
-#define WMI_MAX_RETRIES 13
-typedef enum {
- MGMT_FRAMETYPE = 0,
- CONTROL_FRAMETYPE = 1,
- DATA_FRAMETYPE = 2
-} WMI_FRAMETYPE;
-
-typedef PREPACK struct {
- u8 frameType; /* WMI_FRAMETYPE */
- u8 trafficClass; /* applies only to DATA_FRAMETYPE */
- u8 maxRetries;
- u8 enableNotify;
-} POSTPACK WMI_SET_RETRY_LIMITS_CMD;
-
-/*
- * WMI_SET_ROAM_CTRL_CMDID
- *
- * This command is used to influence the Roaming behaviour
- * Set the host biases of the BSSs before setting the roam mode as bias
- * based.
- */
-
-/*
- * Different types of Roam Control
- */
-
-typedef enum {
- WMI_FORCE_ROAM = 1, /* Roam to the specified BSSID */
- WMI_SET_ROAM_MODE = 2, /* default ,progd bias, no roam */
- WMI_SET_HOST_BIAS = 3, /* Set the Host Bias */
- WMI_SET_LOWRSSI_SCAN_PARAMS = 4, /* Set lowrssi Scan parameters */
-} WMI_ROAM_CTRL_TYPE;
-
-#define WMI_MIN_ROAM_CTRL_TYPE WMI_FORCE_ROAM
-#define WMI_MAX_ROAM_CTRL_TYPE WMI_SET_LOWRSSI_SCAN_PARAMS
-
-/*
- * ROAM MODES
- */
-
-typedef enum {
- WMI_DEFAULT_ROAM_MODE = 1, /* RSSI based ROAM */
- WMI_HOST_BIAS_ROAM_MODE = 2, /* HOST BIAS based ROAM */
- WMI_LOCK_BSS_MODE = 3 /* Lock to the Current BSS - no Roam */
-} WMI_ROAM_MODE;
-
-/*
- * BSS HOST BIAS INFO
- */
-
-typedef PREPACK struct {
- u8 bssid[ATH_MAC_LEN];
- s8 bias;
-} POSTPACK WMI_BSS_BIAS;
-
-typedef PREPACK struct {
- u8 numBss;
- WMI_BSS_BIAS bssBias[1];
-} POSTPACK WMI_BSS_BIAS_INFO;
-
-typedef PREPACK struct WMI_LOWRSSI_SCAN_PARAMS {
- u16 lowrssi_scan_period;
- s16 lowrssi_scan_threshold;
- s16 lowrssi_roam_threshold;
- u8 roam_rssi_floor;
- u8 reserved[1]; /* For alignment */
-} POSTPACK WMI_LOWRSSI_SCAN_PARAMS;
-
-typedef PREPACK struct {
- PREPACK union {
- u8 bssid[ATH_MAC_LEN]; /* WMI_FORCE_ROAM */
- u8 roamMode; /* WMI_SET_ROAM_MODE */
- WMI_BSS_BIAS_INFO bssBiasInfo; /* WMI_SET_HOST_BIAS */
- WMI_LOWRSSI_SCAN_PARAMS lrScanParams;
- } POSTPACK info;
- u8 roamCtrlType ;
-} POSTPACK WMI_SET_ROAM_CTRL_CMD;
-
-/*
- * WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID
- */
-typedef enum {
- BT_WLAN_CONN_PRECDENCE_WLAN=0, /* Default */
- BT_WLAN_CONN_PRECDENCE_PAL,
-} BT_WLAN_CONN_PRECEDENCE;
-
-typedef PREPACK struct {
- u8 precedence;
-} POSTPACK WMI_SET_BT_WLAN_CONN_PRECEDENCE;
-
-/*
- * WMI_ENABLE_RM_CMDID
- */
-typedef PREPACK struct {
- u32 enable_radio_measurements;
-} POSTPACK WMI_ENABLE_RM_CMD;
-
-/*
- * WMI_SET_MAX_OFFHOME_DURATION_CMDID
- */
-typedef PREPACK struct {
- u8 max_offhome_duration;
-} POSTPACK WMI_SET_MAX_OFFHOME_DURATION_CMD;
-
-typedef PREPACK struct {
- u32 frequency;
- u8 threshold;
-} POSTPACK WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD;
-/*---------------------- BTCOEX RELATED -------------------------------------*/
-/*----------------------COMMON to AR6002 and AR6003 -------------------------*/
-typedef enum {
- BT_STREAM_UNDEF = 0,
- BT_STREAM_SCO, /* SCO stream */
- BT_STREAM_A2DP, /* A2DP stream */
- BT_STREAM_SCAN, /* BT Discovery or Page */
- BT_STREAM_ESCO,
- BT_STREAM_MAX
-} BT_STREAM_TYPE;
-
-typedef enum {
- BT_PARAM_SCO_PSPOLL_LATENCY_ONE_FOURTH =1,
- BT_PARAM_SCO_PSPOLL_LATENCY_HALF,
- BT_PARAM_SCO_PSPOLL_LATENCY_THREE_FOURTH,
-} BT_PARAMS_SCO_PSPOLL_LATENCY;
-
-typedef enum {
- BT_PARAMS_SCO_STOMP_SCO_NEVER =1,
- BT_PARAMS_SCO_STOMP_SCO_ALWAYS,
- BT_PARAMS_SCO_STOMP_SCO_IN_LOWRSSI,
-} BT_PARAMS_SCO_STOMP_RULES;
-
-typedef enum {
- BT_STATUS_UNDEF = 0,
- BT_STATUS_ON,
- BT_STATUS_OFF,
- BT_STATUS_MAX
-} BT_STREAM_STATUS;
-
-typedef PREPACK struct {
- u8 streamType;
- u8 status;
-} POSTPACK WMI_SET_BT_STATUS_CMD;
-
-typedef enum {
- BT_ANT_TYPE_UNDEF=0,
- BT_ANT_TYPE_DUAL,
- BT_ANT_TYPE_SPLITTER,
- BT_ANT_TYPE_SWITCH,
- BT_ANT_TYPE_HIGH_ISO_DUAL
-} BT_ANT_FRONTEND_CONFIG;
-
-typedef enum {
- BT_COLOCATED_DEV_BTS4020=0,
- BT_COLCATED_DEV_CSR ,
- BT_COLOCATED_DEV_VALKYRIE
-} BT_COLOCATED_DEV_TYPE;
-
-/*********************** Applicable to AR6002 ONLY ******************************/
-
-typedef enum {
- BT_PARAM_SCO = 1, /* SCO stream parameters */
- BT_PARAM_A2DP ,
- BT_PARAM_ANTENNA_CONFIG,
- BT_PARAM_COLOCATED_BT_DEVICE,
- BT_PARAM_ACLCOEX,
- BT_PARAM_11A_SEPARATE_ANT,
- BT_PARAM_MAX
-} BT_PARAM_TYPE;
-
-
-#define BT_SCO_ALLOW_CLOSE_RANGE_OPT (1 << 0)
-#define BT_SCO_FORCE_AWAKE_OPT (1 << 1)
-#define BT_SCO_SET_RSSI_OVERRIDE(flags) ((flags) |= (1 << 2))
-#define BT_SCO_GET_RSSI_OVERRIDE(flags) (((flags) >> 2) & 0x1)
-#define BT_SCO_SET_RTS_OVERRIDE(flags) ((flags) |= (1 << 3))
-#define BT_SCO_GET_RTS_OVERRIDE(flags) (((flags) >> 3) & 0x1)
-#define BT_SCO_GET_MIN_LOW_RATE_CNT(flags) (((flags) >> 8) & 0xFF)
-#define BT_SCO_GET_MAX_LOW_RATE_CNT(flags) (((flags) >> 16) & 0xFF)
-#define BT_SCO_SET_MIN_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 8)
-#define BT_SCO_SET_MAX_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 16)
-
-typedef PREPACK struct {
- u32 numScoCyclesForceTrigger; /* Number SCO cycles after which
- force a pspoll. default = 10 */
- u32 dataResponseTimeout; /* Timeout Waiting for Downlink pkt
- in response for ps-poll,
- default = 10 msecs */
- u32 stompScoRules;
- u32 scoOptFlags; /* SCO Options Flags :
- bits: meaning:
- 0 Allow Close Range Optimization
- 1 Force awake during close range
- 2 If set use host supplied RSSI for OPT
- 3 If set use host supplied RTS COUNT for OPT
- 4..7 Unused
- 8..15 Low Data Rate Min Cnt
- 16..23 Low Data Rate Max Cnt
- */
-
- u8 stompDutyCyleVal; /* Sco cycles to limit ps-poll queuing
- if stomped */
- u8 stompDutyCyleMaxVal; /*firm ware increases stomp duty cycle
- gradually uptill this value on need basis*/
- u8 psPollLatencyFraction; /* Fraction of idle
- period, within which
- additional ps-polls
- can be queued */
- u8 noSCOSlots; /* Number of SCO Tx/Rx slots.
- HVx, EV3, 2EV3 = 2 */
- u8 noIdleSlots; /* Number of Bluetooth idle slots between
- consecutive SCO Tx/Rx slots
- HVx, EV3 = 4
- 2EV3 = 10 */
- u8 scoOptOffRssi;/*RSSI value below which we go to ps poll*/
- u8 scoOptOnRssi; /*RSSI value above which we reenter opt mode*/
- u8 scoOptRtsCount;
-} POSTPACK BT_PARAMS_SCO;
-
-#define BT_A2DP_ALLOW_CLOSE_RANGE_OPT (1 << 0)
-#define BT_A2DP_FORCE_AWAKE_OPT (1 << 1)
-#define BT_A2DP_SET_RSSI_OVERRIDE(flags) ((flags) |= (1 << 2))
-#define BT_A2DP_GET_RSSI_OVERRIDE(flags) (((flags) >> 2) & 0x1)
-#define BT_A2DP_SET_RTS_OVERRIDE(flags) ((flags) |= (1 << 3))
-#define BT_A2DP_GET_RTS_OVERRIDE(flags) (((flags) >> 3) & 0x1)
-#define BT_A2DP_GET_MIN_LOW_RATE_CNT(flags) (((flags) >> 8) & 0xFF)
-#define BT_A2DP_GET_MAX_LOW_RATE_CNT(flags) (((flags) >> 16) & 0xFF)
-#define BT_A2DP_SET_MIN_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 8)
-#define BT_A2DP_SET_MAX_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 16)
-
-typedef PREPACK struct {
- u32 a2dpWlanUsageLimit; /* MAX time firmware uses the medium for
- wlan, after it identifies the idle time
- default (30 msecs) */
- u32 a2dpBurstCntMin; /* Minimum number of bluetooth data frames
- to replenish Wlan Usage limit (default 3) */
- u32 a2dpDataRespTimeout;
- u32 a2dpOptFlags; /* A2DP Option flags:
- bits: meaning:
- 0 Allow Close Range Optimization
- 1 Force awake during close range
- 2 If set use host supplied RSSI for OPT
- 3 If set use host supplied RTS COUNT for OPT
- 4..7 Unused
- 8..15 Low Data Rate Min Cnt
- 16..23 Low Data Rate Max Cnt
- */
- u8 isCoLocatedBtRoleMaster;
- u8 a2dpOptOffRssi;/*RSSI value below which we go to ps poll*/
- u8 a2dpOptOnRssi; /*RSSI value above which we reenter opt mode*/
- u8 a2dpOptRtsCount;
-}POSTPACK BT_PARAMS_A2DP;
-
-/* During BT ftp/ BT OPP or any another data based acl profile on bluetooth
- (non a2dp).*/
-typedef PREPACK struct {
- u32 aclWlanMediumUsageTime; /* Wlan usage time during Acl (non-a2dp)
- coexistence (default 30 msecs) */
- u32 aclBtMediumUsageTime; /* Bt usage time during acl coexistence
- (default 30 msecs)*/
- u32 aclDataRespTimeout;
- u32 aclDetectTimeout; /* ACL coexistence enabled if we get
- 10 Pkts in X msec(default 100 msecs) */
- u32 aclmaxPktCnt; /* No of ACL pkts to receive before
- enabling ACL coex */
-
-}POSTPACK BT_PARAMS_ACLCOEX;
-
-typedef PREPACK struct {
- PREPACK union {
- BT_PARAMS_SCO scoParams;
- BT_PARAMS_A2DP a2dpParams;
- BT_PARAMS_ACLCOEX aclCoexParams;
- u8 antType; /* 0 -Disabled (default)
- 1 - BT_ANT_TYPE_DUAL
- 2 - BT_ANT_TYPE_SPLITTER
- 3 - BT_ANT_TYPE_SWITCH */
- u8 coLocatedBtDev; /* 0 - BT_COLOCATED_DEV_BTS4020 (default)
- 1 - BT_COLCATED_DEV_CSR
- 2 - BT_COLOCATED_DEV_VALKYRIe
- */
- } POSTPACK info;
- u8 paramType ;
-} POSTPACK WMI_SET_BT_PARAMS_CMD;
-
-/************************ END AR6002 BTCOEX *******************************/
-/*-----------------------AR6003 BTCOEX -----------------------------------*/
-
-/* ---------------WMI_SET_BTCOEX_FE_ANT_CMDID --------------------------*/
-/* Indicates front end antenna configuration. This command needs to be issued
- * right after initialization and after WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID.
- * AR6003 enables coexistence and antenna switching based on the configuration.
- */
-typedef enum {
- WMI_BTCOEX_NOT_ENABLED = 0,
- WMI_BTCOEX_FE_ANT_SINGLE =1,
- WMI_BTCOEX_FE_ANT_DUAL=2,
- WMI_BTCOEX_FE_ANT_DUAL_HIGH_ISO=3,
- WMI_BTCOEX_FE_ANT_TYPE_MAX
-}WMI_BTCOEX_FE_ANT_TYPE;
-
-typedef PREPACK struct {
- u8 btcoexFeAntType; /* 1 - WMI_BTCOEX_FE_ANT_SINGLE for single antenna front end
- 2 - WMI_BTCOEX_FE_ANT_DUAL for dual antenna front end
- (for isolations less 35dB, for higher isolation there
- is not need to pass this command).
- (not implemented)
- */
-}POSTPACK WMI_SET_BTCOEX_FE_ANT_CMD;
-
-/* -------------WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID ----------------*/
-/* Indicate the bluetooth chip to the firmware. Firmware can have different algorithm based
- * bluetooth chip type.Based on bluetooth device, different coexistence protocol would be used.
- */
-typedef PREPACK struct {
- u8 btcoexCoLocatedBTdev; /*1 - Qcom BT (3 -wire PTA)
- 2 - CSR BT (3 wire PTA)
- 3 - Atheros 3001 BT (3 wire PTA)
- 4 - STE bluetooth (4-wire ePTA)
- 5 - Atheros 3002 BT (4-wire MCI)
- defaults= 3 (Atheros 3001 BT )
- */
-}POSTPACK WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD;
-
-/* -------------WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID ------------*/
-/* Configuration parameters during bluetooth inquiry and page. Page configuration
- * is applicable only on interfaces which can distinguish page (applicable only for ePTA -
- * STE bluetooth).
- * Bluetooth inquiry start and end is indicated via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID.
- * During this the station will be power-save mode.
- */
-typedef PREPACK struct {
- u32 btInquiryDataFetchFrequency;/* The frequency of querying the AP for data
- (via pspoll) is configured by this parameter.
- "default = 10 ms" */
-
- u32 protectBmissDurPostBtInquiry;/* The firmware will continue to be in inquiry state
- for configured duration, after inquiry completion
- . This is to ensure other bluetooth transactions
- (RDP, SDP profiles, link key exchange ...etc)
- goes through smoothly without wifi stomping.
- default = 10 secs*/
-
- u32 maxpageStomp; /*Applicable only for STE-BT interface. Currently not
- used */
- u32 btInquiryPageFlag; /* Not used */
-}POSTPACK WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD;
-
-/*---------------------WMI_SET_BTCOEX_SCO_CONFIG_CMDID ---------------*/
-/* Configure SCO parameters. These parameters would be used whenever firmware is indicated
- * of (e)SCO profile on bluetooth ( via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID).
- * Configration of BTCOEX_SCO_CONFIG data structure are common configuration and applies
- * ps-poll mode and opt mode.
- * Ps-poll Mode - Station is in power-save and retrieves downlink data between sco gaps.
- * Opt Mode - station is in awake state and access point can send data to station any time.
- * BTCOEX_PSPOLLMODE_SCO_CONFIG - Configuration applied only during ps-poll mode.
- * BTCOEX_OPTMODE_SCO_CONFIG - Configuration applied only during opt mode.
- */
-#define WMI_SCO_CONFIG_FLAG_ALLOW_OPTIMIZATION (1 << 0)
-#define WMI_SCO_CONFIG_FLAG_IS_EDR_CAPABLE (1 << 1)
-#define WMI_SCO_CONFIG_FLAG_IS_BT_MASTER (1 << 2)
-#define WMI_SCO_CONFIG_FLAG_FW_DETECT_OF_PER (1 << 3)
-typedef PREPACK struct {
- u32 scoSlots; /* Number of SCO Tx/Rx slots.
- HVx, EV3, 2EV3 = 2 */
- u32 scoIdleSlots; /* Number of Bluetooth idle slots between
- consecutive SCO Tx/Rx slots
- HVx, EV3 = 4
- 2EV3 = 10
- */
- u32 scoFlags; /* SCO Options Flags :
- bits: meaning:
- 0 Allow Close Range Optimization
- 1 Is EDR capable or Not
- 2 IS Co-located Bt role Master
- 3 Firmware determines the periodicity of SCO.
- */
-
- u32 linkId; /* applicable to STE-BT - not used */
-}POSTPACK BTCOEX_SCO_CONFIG;
-
-typedef PREPACK struct {
- u32 scoCyclesForceTrigger; /* Number SCO cycles after which
- force a pspoll. default = 10 */
- u32 scoDataResponseTimeout; /* Timeout Waiting for Downlink pkt
- in response for ps-poll,
- default = 20 msecs */
-
- u32 scoStompDutyCyleVal; /* not implemented */
-
- u32 scoStompDutyCyleMaxVal; /*Not implemented */
-
- u32 scoPsPollLatencyFraction; /* Fraction of idle
- period, within which
- additional ps-polls can be queued
- 1 - 1/4 of idle duration
- 2 - 1/2 of idle duration
- 3 - 3/4 of idle duration
- default =2 (1/2)
- */
-}POSTPACK BTCOEX_PSPOLLMODE_SCO_CONFIG;
-
-typedef PREPACK struct {
- u32 scoStompCntIn100ms;/*max number of SCO stomp in 100ms allowed in
- opt mode. If exceeds the configured value,
- switch to ps-poll mode
- default = 3 */
-
- u32 scoContStompMax; /* max number of continuous stomp allowed in opt mode.
- if exceeded switch to pspoll mode
- default = 3 */
-
- u32 scoMinlowRateMbps; /* Low rate threshold */
-
- u32 scoLowRateCnt; /* number of low rate pkts (< scoMinlowRateMbps) allowed in 100 ms.
- If exceeded switch/stay to ps-poll mode, lower stay in opt mode.
- default = 36
- */
-
- u32 scoHighPktRatio; /*(Total Rx pkts in 100 ms + 1)/
- ((Total tx pkts in 100 ms - No of high rate pkts in 100 ms) + 1) in 100 ms,
- if exceeded switch/stay in opt mode and if lower switch/stay in pspoll mode.
- default = 5 (80% of high rates)
- */
-
- u32 scoMaxAggrSize; /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates
- max number of aggregates if it was negogiated to higher value
- default = 1
- Recommended value Basic rate headsets = 1, EDR (2-EV3) =4.
- */
-}POSTPACK BTCOEX_OPTMODE_SCO_CONFIG;
-
-typedef PREPACK struct {
- u32 scanInterval;
- u32 maxScanStompCnt;
-}POSTPACK BTCOEX_WLANSCAN_SCO_CONFIG;
-
-typedef PREPACK struct {
- BTCOEX_SCO_CONFIG scoConfig;
- BTCOEX_PSPOLLMODE_SCO_CONFIG scoPspollConfig;
- BTCOEX_OPTMODE_SCO_CONFIG scoOptModeConfig;
- BTCOEX_WLANSCAN_SCO_CONFIG scoWlanScanConfig;
-}POSTPACK WMI_SET_BTCOEX_SCO_CONFIG_CMD;
-
-/* ------------------WMI_SET_BTCOEX_A2DP_CONFIG_CMDID -------------------*/
-/* Configure A2DP profile parameters. These parameters would be used whenver firmware is indicated
- * of A2DP profile on bluetooth ( via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID).
- * Configuration of BTCOEX_A2DP_CONFIG data structure are common configuration and applies to
- * ps-poll mode and opt mode.
- * Ps-poll Mode - Station is in power-save and retrieves downlink data between a2dp data bursts.
- * Opt Mode - station is in power save during a2dp bursts and awake in the gaps.
- * BTCOEX_PSPOLLMODE_A2DP_CONFIG - Configuration applied only during ps-poll mode.
- * BTCOEX_OPTMODE_A2DP_CONFIG - Configuration applied only during opt mode.
- */
-
-#define WMI_A2DP_CONFIG_FLAG_ALLOW_OPTIMIZATION (1 << 0)
-#define WMI_A2DP_CONFIG_FLAG_IS_EDR_CAPABLE (1 << 1)
-#define WMI_A2DP_CONFIG_FLAG_IS_BT_ROLE_MASTER (1 << 2)
-#define WMI_A2DP_CONFIG_FLAG_IS_A2DP_HIGH_PRI (1 << 3)
-#define WMI_A2DP_CONFIG_FLAG_FIND_BT_ROLE (1 << 4)
-
-typedef PREPACK struct {
- u32 a2dpFlags; /* A2DP Option flags:
- bits: meaning:
- 0 Allow Close Range Optimization
- 1 IS EDR capable
- 2 IS Co-located Bt role Master
- 3 a2dp traffic is high priority
- 4 Fw detect the role of bluetooth.
- */
- u32 linkId; /* Applicable only to STE-BT - not used */
-
-}POSTPACK BTCOEX_A2DP_CONFIG;
-
-typedef PREPACK struct {
- u32 a2dpWlanMaxDur; /* MAX time firmware uses the medium for
- wlan, after it identifies the idle time
- default (30 msecs) */
-
- u32 a2dpMinBurstCnt; /* Minimum number of bluetooth data frames
- to replenish Wlan Usage limit (default 3) */
-
- u32 a2dpDataRespTimeout; /* Max duration firmware waits for downlink
- by stomping on bluetooth
- after ps-poll is acknowledged.
- default = 20 ms
- */
-}POSTPACK BTCOEX_PSPOLLMODE_A2DP_CONFIG;
-
-typedef PREPACK struct {
- u32 a2dpMinlowRateMbps; /* Low rate threshold */
-
- u32 a2dpLowRateCnt; /* number of low rate pkts (< a2dpMinlowRateMbps) allowed in 100 ms.
- If exceeded switch/stay to ps-poll mode, lower stay in opt mode.
- default = 36
- */
-
- u32 a2dpHighPktRatio; /*(Total Rx pkts in 100 ms + 1)/
- ((Total tx pkts in 100 ms - No of high rate pkts in 100 ms) + 1) in 100 ms,
- if exceeded switch/stay in opt mode and if lower switch/stay in pspoll mode.
- default = 5 (80% of high rates)
- */
-
- u32 a2dpMaxAggrSize; /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates
- max number of aggregates if it was negogiated to higher value
- default = 1
- Recommended value Basic rate headsets = 1, EDR (2-EV3) =8.
- */
- u32 a2dpPktStompCnt; /*number of a2dp pkts that can be stomped per burst.
- default = 6*/
-
-}POSTPACK BTCOEX_OPTMODE_A2DP_CONFIG;
-
-typedef PREPACK struct {
- BTCOEX_A2DP_CONFIG a2dpConfig;
- BTCOEX_PSPOLLMODE_A2DP_CONFIG a2dppspollConfig;
- BTCOEX_OPTMODE_A2DP_CONFIG a2dpOptConfig;
-}POSTPACK WMI_SET_BTCOEX_A2DP_CONFIG_CMD;
-
-/*------------ WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID---------------------*/
-/* Configure non-A2dp ACL profile parameters.The starts of ACL profile can either be
- * indicated via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID orenabled via firmware detection
- * which is configured via "aclCoexFlags".
- * Configration of BTCOEX_ACLCOEX_CONFIG data structure are common configuration and applies
- * ps-poll mode and opt mode.
- * Ps-poll Mode - Station is in power-save and retrieves downlink data during wlan medium.
- * Opt Mode - station is in power save during bluetooth medium time and awake during wlan duration.
- * (Not implemented yet)
- *
- * BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG - Configuration applied only during ps-poll mode.
- * BTCOEX_OPTMODE_ACLCOEX_CONFIG - Configuration applied only during opt mode.
- */
-
-#define WMI_ACLCOEX_FLAGS_ALLOW_OPTIMIZATION (1 << 0)
-#define WMI_ACLCOEX_FLAGS_DISABLE_FW_DETECTION (1 << 1)
-
-typedef PREPACK struct {
- u32 aclWlanMediumDur; /* Wlan usage time during Acl (non-a2dp)
- coexistence (default 30 msecs)
- */
-
- u32 aclBtMediumDur; /* Bt usage time during acl coexistence
- (default 30 msecs)
- */
-
- u32 aclDetectTimeout; /* BT activity observation time limit.
- In this time duration, number of bt pkts are counted.
- If the Cnt reaches "aclPktCntLowerLimit" value
- for "aclIterToEnableCoex" iteration continuously,
- firmware gets into ACL coexistence mode.
- Similarly, if bt traffic count during ACL coexistence
- has not reached "aclPktCntLowerLimit" continuously
- for "aclIterToEnableCoex", then ACL coexistence is
- disabled.
- -default 100 msecs
- */
-
- u32 aclPktCntLowerLimit; /* Acl Pkt Cnt to be received in duration of
- "aclDetectTimeout" for
- "aclIterForEnDis" times to enabling ACL coex.
- Similar logic is used to disable acl coexistence.
- (If "aclPktCntLowerLimit" cnt of acl pkts
- are not seen by the for "aclIterForEnDis"
- then acl coexistence is disabled).
- default = 10
- */
-
- u32 aclIterForEnDis; /* number of Iteration of "aclPktCntLowerLimit" for Enabling and
- Disabling Acl Coexistence.
- default = 3
- */
-
- u32 aclPktCntUpperLimit; /* This is upperBound limit, if there is more than
- "aclPktCntUpperLimit" seen in "aclDetectTimeout",
- ACL coexistence is enabled right away.
- - default 15*/
-
- u32 aclCoexFlags; /* A2DP Option flags:
- bits: meaning:
- 0 Allow Close Range Optimization
- 1 disable Firmware detection
- (Currently supported configuration is aclCoexFlags =0)
- */
- u32 linkId; /* Applicable only for STE-BT - not used */
-
-}POSTPACK BTCOEX_ACLCOEX_CONFIG;
-
-typedef PREPACK struct {
- u32 aclDataRespTimeout; /* Max duration firmware waits for downlink
- by stomping on bluetooth
- after ps-poll is acknowledged.
- default = 20 ms */
-
-}POSTPACK BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG;
-
-
-/* Not implemented yet*/
-typedef PREPACK struct {
- u32 aclCoexMinlowRateMbps;
- u32 aclCoexLowRateCnt;
- u32 aclCoexHighPktRatio;
- u32 aclCoexMaxAggrSize;
- u32 aclPktStompCnt;
-}POSTPACK BTCOEX_OPTMODE_ACLCOEX_CONFIG;
-
-typedef PREPACK struct {
- BTCOEX_ACLCOEX_CONFIG aclCoexConfig;
- BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG aclCoexPspollConfig;
- BTCOEX_OPTMODE_ACLCOEX_CONFIG aclCoexOptConfig;
-}POSTPACK WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD;
-
-/* -----------WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ------------------*/
-typedef enum {
- WMI_BTCOEX_BT_PROFILE_SCO =1,
- WMI_BTCOEX_BT_PROFILE_A2DP,
- WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE,
- WMI_BTCOEX_BT_PROFILE_ACLCOEX,
-}WMI_BTCOEX_BT_PROFILE;
-
-typedef PREPACK struct {
- u32 btProfileType;
- u32 btOperatingStatus;
- u32 btLinkId;
-}WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD;
-
-/*--------------------- WMI_SET_BTCOEX_DEBUG_CMDID ---------------------*/
-/* Used for firmware development and debugging */
-typedef PREPACK struct {
- u32 btcoexDbgParam1;
- u32 btcoexDbgParam2;
- u32 btcoexDbgParam3;
- u32 btcoexDbgParam4;
- u32 btcoexDbgParam5;
-}WMI_SET_BTCOEX_DEBUG_CMD;
-
-/*---------------------WMI_GET_BTCOEX_CONFIG_CMDID --------------------- */
-/* Command to firmware to get configuration parameters of the bt profile
- * reported via WMI_BTCOEX_CONFIG_EVENTID */
-typedef PREPACK struct {
- u32 btProfileType; /* 1 - SCO
- 2 - A2DP
- 3 - INQUIRY_PAGE
- 4 - ACLCOEX
- */
- u32 linkId; /* not used */
-}WMI_GET_BTCOEX_CONFIG_CMD;
-
-/*------------------WMI_REPORT_BTCOEX_CONFIG_EVENTID------------------- */
-/* Event from firmware to host, sent in response to WMI_GET_BTCOEX_CONFIG_CMDID
- * */
-typedef PREPACK struct {
- u32 btProfileType;
- u32 linkId; /* not used */
- PREPACK union {
- WMI_SET_BTCOEX_SCO_CONFIG_CMD scoConfigCmd;
- WMI_SET_BTCOEX_A2DP_CONFIG_CMD a2dpConfigCmd;
- WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD aclcoexConfig;
- WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD btinquiryPageConfigCmd;
- } POSTPACK info;
-} POSTPACK WMI_BTCOEX_CONFIG_EVENT;
-
-/*------------- WMI_REPORT_BTCOEX_BTCOEX_STATS_EVENTID--------------------*/
-/* Used for firmware development and debugging*/
-typedef PREPACK struct {
- u32 highRatePktCnt;
- u32 firstBmissCnt;
- u32 psPollFailureCnt;
- u32 nullFrameFailureCnt;
- u32 optModeTransitionCnt;
-}BTCOEX_GENERAL_STATS;
-
-typedef PREPACK struct {
- u32 scoStompCntAvg;
- u32 scoStompIn100ms;
- u32 scoMaxContStomp;
- u32 scoAvgNoRetries;
- u32 scoMaxNoRetriesIn100ms;
-}BTCOEX_SCO_STATS;
-
-typedef PREPACK struct {
- u32 a2dpBurstCnt;
- u32 a2dpMaxBurstCnt;
- u32 a2dpAvgIdletimeIn100ms;
- u32 a2dpAvgStompCnt;
-}BTCOEX_A2DP_STATS;
-
-typedef PREPACK struct {
- u32 aclPktCntInBtTime;
- u32 aclStompCntInWlanTime;
- u32 aclPktCntIn100ms;
-}BTCOEX_ACLCOEX_STATS;
-
-typedef PREPACK struct {
- BTCOEX_GENERAL_STATS coexStats;
- BTCOEX_SCO_STATS scoStats;
- BTCOEX_A2DP_STATS a2dpStats;
- BTCOEX_ACLCOEX_STATS aclCoexStats;
-}WMI_BTCOEX_STATS_EVENT;
-
-
-/*--------------------------END OF BTCOEX -------------------------------------*/
-typedef PREPACK struct {
- u32 sleepState;
-}WMI_REPORT_SLEEP_STATE_EVENT;
-
-typedef enum {
- WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP =0,
- WMI_REPORT_SLEEP_STATUS_IS_AWAKE
-} WMI_REPORT_SLEEP_STATUS;
-typedef enum {
- DISCONN_EVT_IN_RECONN = 0, /* default */
- NO_DISCONN_EVT_IN_RECONN
-} TARGET_EVENT_REPORT_CONFIG;
-
-typedef PREPACK struct {
- u32 evtConfig;
-} POSTPACK WMI_SET_TARGET_EVENT_REPORT_CMD;
-
-
-typedef PREPACK struct {
- u16 cmd_buf_sz; /* HCI cmd buffer size */
- u8 buf[1]; /* Absolute HCI cmd */
-} POSTPACK WMI_HCI_CMD;
-
-/*
- * Command Replies
- */
-
-/*
- * WMI_GET_CHANNEL_LIST_CMDID reply
- */
-typedef PREPACK struct {
- u8 reserved1;
- u8 numChannels; /* number of channels in reply */
- u16 channelList[1]; /* channel in Mhz */
-} POSTPACK WMI_CHANNEL_LIST_REPLY;
-
-typedef enum {
- A_SUCCEEDED = 0,
- A_FAILED_DELETE_STREAM_DOESNOT_EXIST=250,
- A_SUCCEEDED_MODIFY_STREAM=251,
- A_FAILED_INVALID_STREAM = 252,
- A_FAILED_MAX_THINSTREAMS = 253,
- A_FAILED_CREATE_REMOVE_PSTREAM_FIRST = 254,
-} PSTREAM_REPLY_STATUS;
-
-typedef PREPACK struct {
- u8 status; /* PSTREAM_REPLY_STATUS */
- u8 txQueueNumber;
- u8 rxQueueNumber;
- u8 trafficClass;
- u8 trafficDirection; /* DIR_TYPE */
-} POSTPACK WMI_CRE_PRIORITY_STREAM_REPLY;
-
-typedef PREPACK struct {
- u8 status; /* PSTREAM_REPLY_STATUS */
- u8 txQueueNumber;
- u8 rxQueueNumber;
- u8 trafficDirection; /* DIR_TYPE */
- u8 trafficClass;
-} POSTPACK WMI_DEL_PRIORITY_STREAM_REPLY;
-
-/*
- * List of Events (target to host)
- */
-typedef enum {
- WMI_READY_EVENTID = 0x1001,
- WMI_CONNECT_EVENTID,
- WMI_DISCONNECT_EVENTID,
- WMI_BSSINFO_EVENTID,
- WMI_CMDERROR_EVENTID,
- WMI_REGDOMAIN_EVENTID,
- WMI_PSTREAM_TIMEOUT_EVENTID,
- WMI_NEIGHBOR_REPORT_EVENTID,
- WMI_TKIP_MICERR_EVENTID,
- WMI_SCAN_COMPLETE_EVENTID, /* 0x100a */
- WMI_REPORT_STATISTICS_EVENTID,
- WMI_RSSI_THRESHOLD_EVENTID,
- WMI_ERROR_REPORT_EVENTID,
- WMI_OPT_RX_FRAME_EVENTID,
- WMI_REPORT_ROAM_TBL_EVENTID,
- WMI_EXTENSION_EVENTID,
- WMI_CAC_EVENTID,
- WMI_SNR_THRESHOLD_EVENTID,
- WMI_LQ_THRESHOLD_EVENTID,
- WMI_TX_RETRY_ERR_EVENTID, /* 0x1014 */
- WMI_REPORT_ROAM_DATA_EVENTID,
- WMI_TEST_EVENTID,
- WMI_APLIST_EVENTID,
- WMI_GET_WOW_LIST_EVENTID,
- WMI_GET_PMKID_LIST_EVENTID,
- WMI_CHANNEL_CHANGE_EVENTID,
- WMI_PEER_NODE_EVENTID,
- WMI_PSPOLL_EVENTID,
- WMI_DTIMEXPIRY_EVENTID,
- WMI_WLAN_VERSION_EVENTID,
- WMI_SET_PARAMS_REPLY_EVENTID,
- WMI_ADDBA_REQ_EVENTID, /*0x1020 */
- WMI_ADDBA_RESP_EVENTID,
- WMI_DELBA_REQ_EVENTID,
- WMI_TX_COMPLETE_EVENTID,
- WMI_HCI_EVENT_EVENTID,
- WMI_ACL_DATA_EVENTID,
- WMI_REPORT_SLEEP_STATE_EVENTID,
-#ifdef WAPI_ENABLE
- WMI_WAPI_REKEY_EVENTID,
-#endif
- WMI_REPORT_BTCOEX_STATS_EVENTID,
- WMI_REPORT_BTCOEX_CONFIG_EVENTID,
- WMI_GET_PMK_EVENTID,
-
- /* DFS Events */
- WMI_DFS_HOST_ATTACH_EVENTID,
- WMI_DFS_HOST_INIT_EVENTID,
- WMI_DFS_RESET_DELAYLINES_EVENTID,
- WMI_DFS_RESET_RADARQ_EVENTID,
- WMI_DFS_RESET_AR_EVENTID,
- WMI_DFS_RESET_ARQ_EVENTID,
- WMI_DFS_SET_DUR_MULTIPLIER_EVENTID,
- WMI_DFS_SET_BANGRADAR_EVENTID,
- WMI_DFS_SET_DEBUGLEVEL_EVENTID,
- WMI_DFS_PHYERR_EVENTID,
- /* CCX Evants */
- WMI_CCX_RM_STATUS_EVENTID,
-
- /* P2P Events */
- WMI_P2P_GO_NEG_RESULT_EVENTID,
-
- WMI_WAC_SCAN_DONE_EVENTID,
- WMI_WAC_REPORT_BSS_EVENTID,
- WMI_WAC_START_WPS_EVENTID,
- WMI_WAC_CTRL_REQ_REPLY_EVENTID,
-
- /* RFKILL Events */
- WMI_RFKILL_STATE_CHANGE_EVENTID,
- WMI_RFKILL_GET_MODE_CMD_EVENTID,
- WMI_THIN_RESERVED_START_EVENTID = 0x8000,
-
- /*
- * Events in this range are reserved for thinmode
- * See wmi_thin.h for actual definitions
- */
- WMI_THIN_RESERVED_END_EVENTID = 0x8fff,
-
- WMI_SET_CHANNEL_EVENTID,
- WMI_ASSOC_REQ_EVENTID,
-
- /* generic ACS event */
- WMI_ACS_EVENTID,
- WMI_REPORT_WMM_PARAMS_EVENTID
-} WMI_EVENT_ID;
-
-
-typedef enum {
- WMI_11A_CAPABILITY = 1,
- WMI_11G_CAPABILITY = 2,
- WMI_11AG_CAPABILITY = 3,
- WMI_11NA_CAPABILITY = 4,
- WMI_11NG_CAPABILITY = 5,
- WMI_11NAG_CAPABILITY = 6,
- // END CAPABILITY
- WMI_11N_CAPABILITY_OFFSET = (WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY),
-} WMI_PHY_CAPABILITY;
-
-typedef PREPACK struct {
- u8 macaddr[ATH_MAC_LEN];
- u8 phyCapability; /* WMI_PHY_CAPABILITY */
-} POSTPACK WMI_READY_EVENT_1;
-
-typedef PREPACK struct {
- u32 sw_version;
- u32 abi_version;
- u8 macaddr[ATH_MAC_LEN];
- u8 phyCapability; /* WMI_PHY_CAPABILITY */
-} POSTPACK WMI_READY_EVENT_2;
-
-#if defined(ATH_TARGET)
-#ifdef AR6002_REV2
-#define WMI_READY_EVENT WMI_READY_EVENT_1 /* AR6002_REV2 target code */
-#else
-#define WMI_READY_EVENT WMI_READY_EVENT_2 /* AR6001, AR6002_REV4, AR6002_REV5 */
-#endif
-#else
-#define WMI_READY_EVENT WMI_READY_EVENT_2 /* host code */
-#endif
-
-
-/*
- * Connect Event
- */
-typedef PREPACK struct {
- u16 channel;
- u8 bssid[ATH_MAC_LEN];
- u16 listenInterval;
- u16 beaconInterval;
- u32 networkType;
- u8 beaconIeLen;
- u8 assocReqLen;
- u8 assocRespLen;
- u8 assocInfo[1];
-} POSTPACK WMI_CONNECT_EVENT;
-
-/*
- * Disconnect Event
- */
-typedef enum {
- NO_NETWORK_AVAIL = 0x01,
- LOST_LINK = 0x02, /* bmiss */
- DISCONNECT_CMD = 0x03,
- BSS_DISCONNECTED = 0x04,
- AUTH_FAILED = 0x05,
- ASSOC_FAILED = 0x06,
- NO_RESOURCES_AVAIL = 0x07,
- CSERV_DISCONNECT = 0x08,
- INVALID_PROFILE = 0x0a,
- DOT11H_CHANNEL_SWITCH = 0x0b,
- PROFILE_MISMATCH = 0x0c,
- CONNECTION_EVICTED = 0x0d,
- IBSS_MERGE = 0xe,
-} WMI_DISCONNECT_REASON;
-
-typedef PREPACK struct {
- u16 protocolReasonStatus; /* reason code, see 802.11 spec. */
- u8 bssid[ATH_MAC_LEN]; /* set if known */
- u8 disconnectReason ; /* see WMI_DISCONNECT_REASON */
- u8 assocRespLen;
- u8 assocInfo[1];
-} POSTPACK WMI_DISCONNECT_EVENT;
-
-/*
- * BSS Info Event.
- * Mechanism used to inform host of the presence and characteristic of
- * wireless networks present. Consists of bss info header followed by
- * the beacon or probe-response frame body. The 802.11 header is not included.
- */
-typedef enum {
- BEACON_FTYPE = 0x1,
- PROBERESP_FTYPE,
- ACTION_MGMT_FTYPE,
- PROBEREQ_FTYPE,
-} WMI_BI_FTYPE;
-
-enum {
- BSS_ELEMID_CHANSWITCH = 0x01,
- BSS_ELEMID_ATHEROS = 0x02,
-};
-
-typedef PREPACK struct {
- u16 channel;
- u8 frameType; /* see WMI_BI_FTYPE */
- u8 snr;
- s16 rssi;
- u8 bssid[ATH_MAC_LEN];
- u32 ieMask;
-} POSTPACK WMI_BSS_INFO_HDR;
-
-/*
- * BSS INFO HDR version 2.0
- * With 6 bytes HTC header and 6 bytes of WMI header
- * WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management
- * header space.
- * - Reduce the ieMask to 2 bytes as only two bit flags are used
- * - Remove rssi and compute it on the host. rssi = snr - 95
- */
-typedef PREPACK struct {
- u16 channel;
- u8 frameType; /* see WMI_BI_FTYPE */
- u8 snr;
- u8 bssid[ATH_MAC_LEN];
- u16 ieMask;
-} POSTPACK WMI_BSS_INFO_HDR2;
-
-/*
- * Command Error Event
- */
-typedef enum {
- INVALID_PARAM = 0x01,
- ILLEGAL_STATE = 0x02,
- INTERNAL_ERROR = 0x03,
-} WMI_ERROR_CODE;
-
-typedef PREPACK struct {
- u16 commandId;
- u8 errorCode;
-} POSTPACK WMI_CMD_ERROR_EVENT;
-
-/*
- * New Regulatory Domain Event
- */
-typedef PREPACK struct {
- u32 regDomain;
-} POSTPACK WMI_REG_DOMAIN_EVENT;
-
-typedef PREPACK struct {
- u8 txQueueNumber;
- u8 rxQueueNumber;
- u8 trafficDirection;
- u8 trafficClass;
-} POSTPACK WMI_PSTREAM_TIMEOUT_EVENT;
-
-typedef PREPACK struct {
- u8 reserve1;
- u8 reserve2;
- u8 reserve3;
- u8 trafficClass;
-} POSTPACK WMI_ACM_REJECT_EVENT;
-
-/*
- * The WMI_NEIGHBOR_REPORT Event is generated by the target to inform
- * the host of BSS's it has found that matches the current profile.
- * It can be used by the host to cache PMKs and/to initiate pre-authentication
- * if the BSS supports it. The first bssid is always the current associated
- * BSS.
- * The bssid and bssFlags information repeats according to the number
- * or APs reported.
- */
-typedef enum {
- WMI_DEFAULT_BSS_FLAGS = 0x00,
- WMI_PREAUTH_CAPABLE_BSS = 0x01,
- WMI_PMKID_VALID_BSS = 0x02,
-} WMI_BSS_FLAGS;
-
-typedef PREPACK struct {
- u8 bssid[ATH_MAC_LEN];
- u8 bssFlags; /* see WMI_BSS_FLAGS */
-} POSTPACK WMI_NEIGHBOR_INFO;
-
-typedef PREPACK struct {
- s8 numberOfAps;
- WMI_NEIGHBOR_INFO neighbor[1];
-} POSTPACK WMI_NEIGHBOR_REPORT_EVENT;
-
-/*
- * TKIP MIC Error Event
- */
-typedef PREPACK struct {
- u8 keyid;
- u8 ismcast;
-} POSTPACK WMI_TKIP_MICERR_EVENT;
-
-/*
- * WMI_SCAN_COMPLETE_EVENTID - no parameters (old), staus parameter (new)
- */
-typedef PREPACK struct {
- s32 status;
-} POSTPACK WMI_SCAN_COMPLETE_EVENT;
-
-#define MAX_OPT_DATA_LEN 1400
-
-/*
- * WMI_SET_ADHOC_BSSID_CMDID
- */
-typedef PREPACK struct {
- u8 bssid[ATH_MAC_LEN];
-} POSTPACK WMI_SET_ADHOC_BSSID_CMD;
-
-/*
- * WMI_SET_OPT_MODE_CMDID
- */
-typedef enum {
- SPECIAL_OFF,
- SPECIAL_ON,
-} OPT_MODE_TYPE;
-
-typedef PREPACK struct {
- u8 optMode;
-} POSTPACK WMI_SET_OPT_MODE_CMD;
-
-/*
- * WMI_TX_OPT_FRAME_CMDID
- */
-typedef enum {
- OPT_PROBE_REQ = 0x01,
- OPT_PROBE_RESP = 0x02,
- OPT_CPPP_START = 0x03,
- OPT_CPPP_STOP = 0x04,
-} WMI_OPT_FTYPE;
-
-typedef PREPACK struct {
- u16 optIEDataLen;
- u8 frmType;
- u8 dstAddr[ATH_MAC_LEN];
- u8 bssid[ATH_MAC_LEN];
- u8 reserved; /* For alignment */
- u8 optIEData[1];
-} POSTPACK WMI_OPT_TX_FRAME_CMD;
-
-/*
- * Special frame receive Event.
- * Mechanism used to inform host of the receiption of the special frames.
- * Consists of special frame info header followed by special frame body.
- * The 802.11 header is not included.
- */
-typedef PREPACK struct {
- u16 channel;
- u8 frameType; /* see WMI_OPT_FTYPE */
- s8 snr;
- u8 srcAddr[ATH_MAC_LEN];
- u8 bssid[ATH_MAC_LEN];
-} POSTPACK WMI_OPT_RX_INFO_HDR;
-
-/*
- * Reporting statistics.
- */
-typedef PREPACK struct {
- u32 tx_packets;
- u32 tx_bytes;
- u32 tx_unicast_pkts;
- u32 tx_unicast_bytes;
- u32 tx_multicast_pkts;
- u32 tx_multicast_bytes;
- u32 tx_broadcast_pkts;
- u32 tx_broadcast_bytes;
- u32 tx_rts_success_cnt;
- u32 tx_packet_per_ac[4];
- u32 tx_errors_per_ac[4];
-
- u32 tx_errors;
- u32 tx_failed_cnt;
- u32 tx_retry_cnt;
- u32 tx_mult_retry_cnt;
- u32 tx_rts_fail_cnt;
- s32 tx_unicast_rate;
-}POSTPACK tx_stats_t;
-
-typedef PREPACK struct {
- u32 rx_packets;
- u32 rx_bytes;
- u32 rx_unicast_pkts;
- u32 rx_unicast_bytes;
- u32 rx_multicast_pkts;
- u32 rx_multicast_bytes;
- u32 rx_broadcast_pkts;
- u32 rx_broadcast_bytes;
- u32 rx_fragment_pkt;
-
- u32 rx_errors;
- u32 rx_crcerr;
- u32 rx_key_cache_miss;
- u32 rx_decrypt_err;
- u32 rx_duplicate_frames;
- s32 rx_unicast_rate;
-}POSTPACK rx_stats_t;
-
-typedef PREPACK struct {
- u32 tkip_local_mic_failure;
- u32 tkip_counter_measures_invoked;
- u32 tkip_replays;
- u32 tkip_format_errors;
- u32 ccmp_format_errors;
- u32 ccmp_replays;
-}POSTPACK tkip_ccmp_stats_t;
-
-typedef PREPACK struct {
- u32 power_save_failure_cnt;
- u16 stop_tx_failure_cnt;
- u16 atim_tx_failure_cnt;
- u16 atim_rx_failure_cnt;
- u16 bcn_rx_failure_cnt;
-}POSTPACK pm_stats_t;
-
-typedef PREPACK struct {
- u32 cs_bmiss_cnt;
- u32 cs_lowRssi_cnt;
- u16 cs_connect_cnt;
- u16 cs_disconnect_cnt;
- s16 cs_aveBeacon_rssi;
- u16 cs_roam_count;
- s16 cs_rssi;
- u8 cs_snr;
- u8 cs_aveBeacon_snr;
- u8 cs_lastRoam_msec;
-} POSTPACK cserv_stats_t;
-
-typedef PREPACK struct {
- tx_stats_t tx_stats;
- rx_stats_t rx_stats;
- tkip_ccmp_stats_t tkipCcmpStats;
-}POSTPACK wlan_net_stats_t;
-
-typedef PREPACK struct {
- u32 arp_received;
- u32 arp_matched;
- u32 arp_replied;
-} POSTPACK arp_stats_t;
-
-typedef PREPACK struct {
- u32 wow_num_pkts_dropped;
- u16 wow_num_events_discarded;
- u8 wow_num_host_pkt_wakeups;
- u8 wow_num_host_event_wakeups;
-} POSTPACK wlan_wow_stats_t;
-
-typedef PREPACK struct {
- u32 lqVal;
- s32 noise_floor_calibation;
- pm_stats_t pmStats;
- wlan_net_stats_t txrxStats;
- wlan_wow_stats_t wowStats;
- arp_stats_t arpStats;
- cserv_stats_t cservStats;
-} POSTPACK WMI_TARGET_STATS;
-
-/*
- * WMI_RSSI_THRESHOLD_EVENTID.
- * Indicate the RSSI events to host. Events are indicated when we breach a
- * thresold value.
- */
-typedef enum{
- WMI_RSSI_THRESHOLD1_ABOVE = 0,
- WMI_RSSI_THRESHOLD2_ABOVE,
- WMI_RSSI_THRESHOLD3_ABOVE,
- WMI_RSSI_THRESHOLD4_ABOVE,
- WMI_RSSI_THRESHOLD5_ABOVE,
- WMI_RSSI_THRESHOLD6_ABOVE,
- WMI_RSSI_THRESHOLD1_BELOW,
- WMI_RSSI_THRESHOLD2_BELOW,
- WMI_RSSI_THRESHOLD3_BELOW,
- WMI_RSSI_THRESHOLD4_BELOW,
- WMI_RSSI_THRESHOLD5_BELOW,
- WMI_RSSI_THRESHOLD6_BELOW
-}WMI_RSSI_THRESHOLD_VAL;
-
-typedef PREPACK struct {
- s16 rssi;
- u8 range;
-}POSTPACK WMI_RSSI_THRESHOLD_EVENT;
-
-/*
- * WMI_ERROR_REPORT_EVENTID
- */
-typedef enum{
- WMI_TARGET_PM_ERR_FAIL = 0x00000001,
- WMI_TARGET_KEY_NOT_FOUND = 0x00000002,
- WMI_TARGET_DECRYPTION_ERR = 0x00000004,
- WMI_TARGET_BMISS = 0x00000008,
- WMI_PSDISABLE_NODE_JOIN = 0x00000010,
- WMI_TARGET_COM_ERR = 0x00000020,
- WMI_TARGET_FATAL_ERR = 0x00000040
-} WMI_TARGET_ERROR_VAL;
-
-typedef PREPACK struct {
- u32 errorVal;
-}POSTPACK WMI_TARGET_ERROR_REPORT_EVENT;
-
-typedef PREPACK struct {
- u8 retrys;
-}POSTPACK WMI_TX_RETRY_ERR_EVENT;
-
-typedef enum{
- WMI_SNR_THRESHOLD1_ABOVE = 1,
- WMI_SNR_THRESHOLD1_BELOW,
- WMI_SNR_THRESHOLD2_ABOVE,
- WMI_SNR_THRESHOLD2_BELOW,
- WMI_SNR_THRESHOLD3_ABOVE,
- WMI_SNR_THRESHOLD3_BELOW,
- WMI_SNR_THRESHOLD4_ABOVE,
- WMI_SNR_THRESHOLD4_BELOW
-} WMI_SNR_THRESHOLD_VAL;
-
-typedef PREPACK struct {
- u8 range; /* WMI_SNR_THRESHOLD_VAL */
- u8 snr;
-}POSTPACK WMI_SNR_THRESHOLD_EVENT;
-
-typedef enum{
- WMI_LQ_THRESHOLD1_ABOVE = 1,
- WMI_LQ_THRESHOLD1_BELOW,
- WMI_LQ_THRESHOLD2_ABOVE,
- WMI_LQ_THRESHOLD2_BELOW,
- WMI_LQ_THRESHOLD3_ABOVE,
- WMI_LQ_THRESHOLD3_BELOW,
- WMI_LQ_THRESHOLD4_ABOVE,
- WMI_LQ_THRESHOLD4_BELOW
-} WMI_LQ_THRESHOLD_VAL;
-
-typedef PREPACK struct {
- s32 lq;
- u8 range; /* WMI_LQ_THRESHOLD_VAL */
-}POSTPACK WMI_LQ_THRESHOLD_EVENT;
-/*
- * WMI_REPORT_ROAM_TBL_EVENTID
- */
-#define MAX_ROAM_TBL_CAND 5
-
-typedef PREPACK struct {
- s32 roam_util;
- u8 bssid[ATH_MAC_LEN];
- s8 rssi;
- s8 rssidt;
- s8 last_rssi;
- s8 util;
- s8 bias;
- u8 reserved; /* For alignment */
-} POSTPACK WMI_BSS_ROAM_INFO;
-
-
-typedef PREPACK struct {
- u16 roamMode;
- u16 numEntries;
- WMI_BSS_ROAM_INFO bssRoamInfo[1];
-} POSTPACK WMI_TARGET_ROAM_TBL;
-
-/*
- * WMI_HCI_EVENT_EVENTID
- */
-typedef PREPACK struct {
- u16 evt_buf_sz; /* HCI event buffer size */
- u8 buf[1]; /* HCI event */
-} POSTPACK WMI_HCI_EVENT;
-
-/*
- * WMI_CAC_EVENTID
- */
-typedef enum {
- CAC_INDICATION_ADMISSION = 0x00,
- CAC_INDICATION_ADMISSION_RESP = 0x01,
- CAC_INDICATION_DELETE = 0x02,
- CAC_INDICATION_NO_RESP = 0x03,
-}CAC_INDICATION;
-
-#define WMM_TSPEC_IE_LEN 63
-
-typedef PREPACK struct {
- u8 ac;
- u8 cac_indication;
- u8 statusCode;
- u8 tspecSuggestion[WMM_TSPEC_IE_LEN];
-}POSTPACK WMI_CAC_EVENT;
-
-/*
- * WMI_APLIST_EVENTID
- */
-
-typedef enum {
- APLIST_VER1 = 1,
-} APLIST_VER;
-
-typedef PREPACK struct {
- u8 bssid[ATH_MAC_LEN];
- u16 channel;
-} POSTPACK WMI_AP_INFO_V1;
-
-typedef PREPACK union {
- WMI_AP_INFO_V1 apInfoV1;
-} POSTPACK WMI_AP_INFO;
-
-typedef PREPACK struct {
- u8 apListVer;
- u8 numAP;
- WMI_AP_INFO apList[1];
-} POSTPACK WMI_APLIST_EVENT;
-
-/*
- * developer commands
- */
-
-/*
- * WMI_SET_BITRATE_CMDID
- *
- * Get bit rate cmd uses same definition as set bit rate cmd
- */
-typedef enum {
- RATE_AUTO = -1,
- RATE_1Mb = 0,
- RATE_2Mb = 1,
- RATE_5_5Mb = 2,
- RATE_11Mb = 3,
- RATE_6Mb = 4,
- RATE_9Mb = 5,
- RATE_12Mb = 6,
- RATE_18Mb = 7,
- RATE_24Mb = 8,
- RATE_36Mb = 9,
- RATE_48Mb = 10,
- RATE_54Mb = 11,
- RATE_MCS_0_20 = 12,
- RATE_MCS_1_20 = 13,
- RATE_MCS_2_20 = 14,
- RATE_MCS_3_20 = 15,
- RATE_MCS_4_20 = 16,
- RATE_MCS_5_20 = 17,
- RATE_MCS_6_20 = 18,
- RATE_MCS_7_20 = 19,
- RATE_MCS_0_40 = 20,
- RATE_MCS_1_40 = 21,
- RATE_MCS_2_40 = 22,
- RATE_MCS_3_40 = 23,
- RATE_MCS_4_40 = 24,
- RATE_MCS_5_40 = 25,
- RATE_MCS_6_40 = 26,
- RATE_MCS_7_40 = 27,
-} WMI_BIT_RATE;
-
-typedef PREPACK struct {
- s8 rateIndex; /* see WMI_BIT_RATE */
- s8 mgmtRateIndex;
- s8 ctlRateIndex;
-} POSTPACK WMI_BIT_RATE_CMD;
-
-
-typedef PREPACK struct {
- s8 rateIndex; /* see WMI_BIT_RATE */
-} POSTPACK WMI_BIT_RATE_REPLY;
-
-
-/*
- * WMI_SET_FIXRATES_CMDID
- *
- * Get fix rates cmd uses same definition as set fix rates cmd
- */
-#define FIX_RATE_1Mb ((u32)0x1)
-#define FIX_RATE_2Mb ((u32)0x2)
-#define FIX_RATE_5_5Mb ((u32)0x4)
-#define FIX_RATE_11Mb ((u32)0x8)
-#define FIX_RATE_6Mb ((u32)0x10)
-#define FIX_RATE_9Mb ((u32)0x20)
-#define FIX_RATE_12Mb ((u32)0x40)
-#define FIX_RATE_18Mb ((u32)0x80)
-#define FIX_RATE_24Mb ((u32)0x100)
-#define FIX_RATE_36Mb ((u32)0x200)
-#define FIX_RATE_48Mb ((u32)0x400)
-#define FIX_RATE_54Mb ((u32)0x800)
-#define FIX_RATE_MCS_0_20 ((u32)0x1000)
-#define FIX_RATE_MCS_1_20 ((u32)0x2000)
-#define FIX_RATE_MCS_2_20 ((u32)0x4000)
-#define FIX_RATE_MCS_3_20 ((u32)0x8000)
-#define FIX_RATE_MCS_4_20 ((u32)0x10000)
-#define FIX_RATE_MCS_5_20 ((u32)0x20000)
-#define FIX_RATE_MCS_6_20 ((u32)0x40000)
-#define FIX_RATE_MCS_7_20 ((u32)0x80000)
-#define FIX_RATE_MCS_0_40 ((u32)0x100000)
-#define FIX_RATE_MCS_1_40 ((u32)0x200000)
-#define FIX_RATE_MCS_2_40 ((u32)0x400000)
-#define FIX_RATE_MCS_3_40 ((u32)0x800000)
-#define FIX_RATE_MCS_4_40 ((u32)0x1000000)
-#define FIX_RATE_MCS_5_40 ((u32)0x2000000)
-#define FIX_RATE_MCS_6_40 ((u32)0x4000000)
-#define FIX_RATE_MCS_7_40 ((u32)0x8000000)
-
-typedef PREPACK struct {
- u32 fixRateMask; /* see WMI_BIT_RATE */
-} POSTPACK WMI_FIX_RATES_CMD, WMI_FIX_RATES_REPLY;
-
-typedef PREPACK struct {
- u8 bEnableMask;
- u8 frameType; /*type and subtype*/
- u32 frameRateMask; /* see WMI_BIT_RATE */
-} POSTPACK WMI_FRAME_RATES_CMD, WMI_FRAME_RATES_REPLY;
-
-/*
- * WMI_SET_RECONNECT_AUTH_MODE_CMDID
- *
- * Set authentication mode
- */
-typedef enum {
- RECONN_DO_AUTH = 0x00,
- RECONN_NOT_AUTH = 0x01
-} WMI_AUTH_MODE;
-
-typedef PREPACK struct {
- u8 mode;
-} POSTPACK WMI_SET_AUTH_MODE_CMD;
-
-/*
- * WMI_SET_REASSOC_MODE_CMDID
- *
- * Set authentication mode
- */
-typedef enum {
- REASSOC_DO_DISASSOC = 0x00,
- REASSOC_DONOT_DISASSOC = 0x01
-} WMI_REASSOC_MODE;
-
-typedef PREPACK struct {
- u8 mode;
-}POSTPACK WMI_SET_REASSOC_MODE_CMD;
-
-typedef enum {
- ROAM_DATA_TIME = 1, /* Get The Roam Time Data */
-} ROAM_DATA_TYPE;
-
-typedef PREPACK struct {
- u32 disassoc_time;
- u32 no_txrx_time;
- u32 assoc_time;
- u32 allow_txrx_time;
- u8 disassoc_bssid[ATH_MAC_LEN];
- s8 disassoc_bss_rssi;
- u8 assoc_bssid[ATH_MAC_LEN];
- s8 assoc_bss_rssi;
-} POSTPACK WMI_TARGET_ROAM_TIME;
-
-typedef PREPACK struct {
- PREPACK union {
- WMI_TARGET_ROAM_TIME roamTime;
- } POSTPACK u;
- u8 roamDataType ;
-} POSTPACK WMI_TARGET_ROAM_DATA;
-
-typedef enum {
- WMI_WMM_DISABLED = 0,
- WMI_WMM_ENABLED
-} WMI_WMM_STATUS;
-
-typedef PREPACK struct {
- u8 status;
-}POSTPACK WMI_SET_WMM_CMD;
-
-typedef PREPACK struct {
- u8 status;
-}POSTPACK WMI_SET_QOS_SUPP_CMD;
-
-typedef enum {
- WMI_TXOP_DISABLED = 0,
- WMI_TXOP_ENABLED
-} WMI_TXOP_CFG;
-
-typedef PREPACK struct {
- u8 txopEnable;
-}POSTPACK WMI_SET_WMM_TXOP_CMD;
-
-typedef PREPACK struct {
- u8 keepaliveInterval;
-} POSTPACK WMI_SET_KEEPALIVE_CMD;
-
-typedef PREPACK struct {
- u32 configured;
- u8 keepaliveInterval;
-} POSTPACK WMI_GET_KEEPALIVE_CMD;
-
-/*
- * Add Application specified IE to a management frame
- */
-#define WMI_MAX_IE_LEN 255
-
-typedef PREPACK struct {
- u8 mgmtFrmType; /* one of WMI_MGMT_FRAME_TYPE */
- u8 ieLen; /* Length of the IE that should be added to the MGMT frame */
- u8 ieInfo[1];
-} POSTPACK WMI_SET_APPIE_CMD;
-
-/*
- * Notify the WSC registration status to the target
- */
-#define WSC_REG_ACTIVE 1
-#define WSC_REG_INACTIVE 0
-/* Generic Hal Interface for setting hal paramters. */
-/* Add new Set HAL Param cmdIds here for newer params */
-typedef enum {
- WHAL_SETCABTO_CMDID = 1,
-}WHAL_CMDID;
-
-typedef PREPACK struct {
- u8 cabTimeOut;
-} POSTPACK WHAL_SETCABTO_PARAM;
-
-typedef PREPACK struct {
- u8 whalCmdId;
- u8 data[1];
-} POSTPACK WHAL_PARAMCMD;
-
-
-#define WOW_MAX_FILTER_LISTS 1 /*4*/
-#define WOW_MAX_FILTERS_PER_LIST 4
-#define WOW_PATTERN_SIZE 64
-#define WOW_MASK_SIZE 64
-
-#define MAC_MAX_FILTERS_PER_LIST 4
-
-typedef PREPACK struct {
- u8 wow_valid_filter;
- u8 wow_filter_id;
- u8 wow_filter_size;
- u8 wow_filter_offset;
- u8 wow_filter_mask[WOW_MASK_SIZE];
- u8 wow_filter_pattern[WOW_PATTERN_SIZE];
-} POSTPACK WOW_FILTER;
-
-
-typedef PREPACK struct {
- u8 wow_valid_list;
- u8 wow_list_id;
- u8 wow_num_filters;
- u8 wow_total_list_size;
- WOW_FILTER list[WOW_MAX_FILTERS_PER_LIST];
-} POSTPACK WOW_FILTER_LIST;
-
-typedef PREPACK struct {
- u8 valid_filter;
- u8 mac_addr[ATH_MAC_LEN];
-} POSTPACK MAC_FILTER;
-
-
-typedef PREPACK struct {
- u8 total_list_size;
- u8 enable;
- MAC_FILTER list[MAC_MAX_FILTERS_PER_LIST];
-} POSTPACK MAC_FILTER_LIST;
-
-#define MAX_IP_ADDRS 2
-typedef PREPACK struct {
- u32 ips[MAX_IP_ADDRS]; /* IP in Network Byte Order */
-} POSTPACK WMI_SET_IP_CMD;
-
-typedef PREPACK struct {
- u32 awake;
- u32 asleep;
-} POSTPACK WMI_SET_HOST_SLEEP_MODE_CMD;
-
-typedef enum {
- WOW_FILTER_SSID = 0x1
-} WMI_WOW_FILTER;
-
-typedef PREPACK struct {
- u32 enable_wow;
- WMI_WOW_FILTER filter;
- u16 hostReqDelay;
-} POSTPACK WMI_SET_WOW_MODE_CMD;
-
-typedef PREPACK struct {
- u8 filter_list_id;
-} POSTPACK WMI_GET_WOW_LIST_CMD;
-
-/*
- * WMI_GET_WOW_LIST_CMD reply
- */
-typedef PREPACK struct {
- u8 num_filters; /* number of patterns in reply */
- u8 this_filter_num; /* this is filter # x of total num_filters */
- u8 wow_mode;
- u8 host_mode;
- WOW_FILTER wow_filters[1];
-} POSTPACK WMI_GET_WOW_LIST_REPLY;
-
-typedef PREPACK struct {
- u8 filter_list_id;
- u8 filter_size;
- u8 filter_offset;
- u8 filter[1];
-} POSTPACK WMI_ADD_WOW_PATTERN_CMD;
-
-typedef PREPACK struct {
- u16 filter_list_id;
- u16 filter_id;
-} POSTPACK WMI_DEL_WOW_PATTERN_CMD;
-
-typedef PREPACK struct {
- u8 macaddr[ATH_MAC_LEN];
-} POSTPACK WMI_SET_MAC_ADDRESS_CMD;
-
-/*
- * WMI_SET_AKMP_PARAMS_CMD
- */
-
-#define WMI_AKMP_MULTI_PMKID_EN 0x000001
-
-typedef PREPACK struct {
- u32 akmpInfo;
-} POSTPACK WMI_SET_AKMP_PARAMS_CMD;
-
-typedef PREPACK struct {
- u8 pmkid[WMI_PMKID_LEN];
-} POSTPACK WMI_PMKID;
-
-/*
- * WMI_SET_PMKID_LIST_CMD
- */
-#define WMI_MAX_PMKID_CACHE 8
-
-typedef PREPACK struct {
- u32 numPMKID;
- WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE];
-} POSTPACK WMI_SET_PMKID_LIST_CMD;
-
-/*
- * WMI_GET_PMKID_LIST_CMD Reply
- * Following the Number of PMKIDs is the list of PMKIDs
- */
-typedef PREPACK struct {
- u32 numPMKID;
- u8 bssidList[ATH_MAC_LEN][1];
- WMI_PMKID pmkidList[1];
-} POSTPACK WMI_PMKID_LIST_REPLY;
-
-typedef PREPACK struct {
- u16 oldChannel;
- u32 newChannel;
-} POSTPACK WMI_CHANNEL_CHANGE_EVENT;
-
-typedef PREPACK struct {
- u32 version;
-} POSTPACK WMI_WLAN_VERSION_EVENT;
-
-
-/* WMI_ADDBA_REQ_EVENTID */
-typedef PREPACK struct {
- u8 tid;
- u8 win_sz;
- u16 st_seq_no;
- u8 status; /* f/w response for ADDBA Req; OK(0) or failure(!=0) */
-} POSTPACK WMI_ADDBA_REQ_EVENT;
-
-/* WMI_ADDBA_RESP_EVENTID */
-typedef PREPACK struct {
- u8 tid;
- u8 status; /* OK(0), failure (!=0) */
- u16 amsdu_sz; /* Three values: Not supported(0), 3839, 8k */
-} POSTPACK WMI_ADDBA_RESP_EVENT;
-
-/* WMI_DELBA_EVENTID
- * f/w received a DELBA for peer and processed it.
- * Host is notified of this
- */
-typedef PREPACK struct {
- u8 tid;
- u8 is_peer_initiator;
- u16 reason_code;
-} POSTPACK WMI_DELBA_EVENT;
-
-
-#ifdef WAPI_ENABLE
-#define WAPI_REKEY_UCAST 1
-#define WAPI_REKEY_MCAST 2
-typedef PREPACK struct {
- u8 type;
- u8 macAddr[ATH_MAC_LEN];
-} POSTPACK WMI_WAPIREKEY_EVENT;
-#endif
-
-
-/* WMI_ALLOW_AGGR_CMDID
- * Configures tid's to allow ADDBA negotiations
- * on each tid, in each direction
- */
-typedef PREPACK struct {
- u16 tx_allow_aggr; /* 16-bit mask to allow uplink ADDBA negotiation - bit position indicates tid*/
- u16 rx_allow_aggr; /* 16-bit mask to allow donwlink ADDBA negotiation - bit position indicates tid*/
-} POSTPACK WMI_ALLOW_AGGR_CMD;
-
-/* WMI_ADDBA_REQ_CMDID
- * f/w starts performing ADDBA negotiations with peer
- * on the given tid
- */
-typedef PREPACK struct {
- u8 tid;
-} POSTPACK WMI_ADDBA_REQ_CMD;
-
-/* WMI_DELBA_REQ_CMDID
- * f/w would teardown BA with peer.
- * is_send_initiator indicates if it's or tx or rx side
- */
-typedef PREPACK struct {
- u8 tid;
- u8 is_sender_initiator;
-
-} POSTPACK WMI_DELBA_REQ_CMD;
-
-#define PEER_NODE_JOIN_EVENT 0x00
-#define PEER_NODE_LEAVE_EVENT 0x01
-#define PEER_FIRST_NODE_JOIN_EVENT 0x10
-#define PEER_LAST_NODE_LEAVE_EVENT 0x11
-typedef PREPACK struct {
- u8 eventCode;
- u8 peerMacAddr[ATH_MAC_LEN];
-} POSTPACK WMI_PEER_NODE_EVENT;
-
-#define IEEE80211_FRAME_TYPE_MGT 0x00
-#define IEEE80211_FRAME_TYPE_CTL 0x04
-
-/*
- * Transmit complete event data structure(s)
- */
-
-
-typedef PREPACK struct {
-#define TX_COMPLETE_STATUS_SUCCESS 0
-#define TX_COMPLETE_STATUS_RETRIES 1
-#define TX_COMPLETE_STATUS_NOLINK 2
-#define TX_COMPLETE_STATUS_TIMEOUT 3
-#define TX_COMPLETE_STATUS_OTHER 4
-
- u8 status; /* one of TX_COMPLETE_STATUS_... */
- u8 pktID; /* packet ID to identify parent packet */
- u8 rateIdx; /* rate index on successful transmission */
- u8 ackFailures; /* number of ACK failures in tx attempt */
-#if 0 /* optional params currently omitted. */
- u32 queueDelay; // usec delay measured Tx Start time - host delivery time
- u32 mediaDelay; // usec delay measured ACK rx time - host delivery time
-#endif
-} POSTPACK TX_COMPLETE_MSG_V1; /* version 1 of tx complete msg */
-
-typedef PREPACK struct {
- u8 numMessages; /* number of tx comp msgs following this struct */
- u8 msgLen; /* length in bytes for each individual msg following this struct */
- u8 msgType; /* version of tx complete msg data following this struct */
- u8 reserved; /* individual messages follow this header */
-} POSTPACK WMI_TX_COMPLETE_EVENT;
-
-#define WMI_TXCOMPLETE_VERSION_1 (0x01)
-
-
-/*
- * ------- AP Mode definitions --------------
- */
-
-/*
- * !!! Warning !!!
- * -Changing the following values needs compilation of both driver and firmware
- */
-#ifdef AR6002_REV2
-#define AP_MAX_NUM_STA 4
-#else
-#define AP_MAX_NUM_STA 8
-#endif
-#define AP_ACL_SIZE 10
-#define IEEE80211_MAX_IE 256
-#define MCAST_AID 0xFF /* Spl. AID used to set DTIM flag in the beacons */
-#define DEF_AP_COUNTRY_CODE "US "
-#define DEF_AP_WMODE_G WMI_11G_MODE
-#define DEF_AP_WMODE_AG WMI_11AG_MODE
-#define DEF_AP_DTIM 5
-#define DEF_BEACON_INTERVAL 100
-
-/* AP mode disconnect reasons */
-#define AP_DISCONNECT_STA_LEFT 101
-#define AP_DISCONNECT_FROM_HOST 102
-#define AP_DISCONNECT_COMM_TIMEOUT 103
-
-/*
- * Used with WMI_AP_HIDDEN_SSID_CMDID
- */
-#define HIDDEN_SSID_FALSE 0
-#define HIDDEN_SSID_TRUE 1
-typedef PREPACK struct {
- u8 hidden_ssid;
-} POSTPACK WMI_AP_HIDDEN_SSID_CMD;
-
-/*
- * Used with WMI_AP_ACL_POLICY_CMDID
- */
-#define AP_ACL_DISABLE 0x00
-#define AP_ACL_ALLOW_MAC 0x01
-#define AP_ACL_DENY_MAC 0x02
-#define AP_ACL_RETAIN_LIST_MASK 0x80
-typedef PREPACK struct {
- u8 policy;
-} POSTPACK WMI_AP_ACL_POLICY_CMD;
-
-/*
- * Used with WMI_AP_ACL_MAC_LIST_CMDID
- */
-#define ADD_MAC_ADDR 1
-#define DEL_MAC_ADDR 2
-typedef PREPACK struct {
- u8 action;
- u8 index;
- u8 mac[ATH_MAC_LEN];
- u8 wildcard;
-} POSTPACK WMI_AP_ACL_MAC_CMD;
-
-typedef PREPACK struct {
- u16 index;
- u8 acl_mac[AP_ACL_SIZE][ATH_MAC_LEN];
- u8 wildcard[AP_ACL_SIZE];
- u8 policy;
-} POSTPACK WMI_AP_ACL;
-
-/*
- * Used with WMI_AP_SET_NUM_STA_CMDID
- */
-typedef PREPACK struct {
- u8 num_sta;
-} POSTPACK WMI_AP_SET_NUM_STA_CMD;
-
-/*
- * Used with WMI_AP_SET_MLME_CMDID
- */
-typedef PREPACK struct {
- u8 mac[ATH_MAC_LEN];
- u16 reason; /* 802.11 reason code */
- u8 cmd; /* operation to perform */
-#define WMI_AP_MLME_ASSOC 1 /* associate station */
-#define WMI_AP_DISASSOC 2 /* disassociate station */
-#define WMI_AP_DEAUTH 3 /* deauthenticate station */
-#define WMI_AP_MLME_AUTHORIZE 4 /* authorize station */
-#define WMI_AP_MLME_UNAUTHORIZE 5 /* unauthorize station */
-} POSTPACK WMI_AP_SET_MLME_CMD;
-
-typedef PREPACK struct {
- u32 period;
-} POSTPACK WMI_AP_CONN_INACT_CMD;
-
-typedef PREPACK struct {
- u32 period_min;
- u32 dwell_ms;
-} POSTPACK WMI_AP_PROT_SCAN_TIME_CMD;
-
-typedef PREPACK struct {
- u32 flag;
- u16 aid;
-} POSTPACK WMI_AP_SET_PVB_CMD;
-
-#define WMI_DISABLE_REGULATORY_CODE "FF"
-
-typedef PREPACK struct {
- u8 countryCode[3];
-} POSTPACK WMI_AP_SET_COUNTRY_CMD;
-
-typedef PREPACK struct {
- u8 dtim;
-} POSTPACK WMI_AP_SET_DTIM_CMD;
-
-typedef PREPACK struct {
- u8 band; /* specifies which band to apply these values */
- u8 enable; /* allows 11n to be disabled on a per band basis */
- u8 chan_width_40M_supported;
- u8 short_GI_20MHz;
- u8 short_GI_40MHz;
- u8 intolerance_40MHz;
- u8 max_ampdu_len_exp;
-} POSTPACK WMI_SET_HT_CAP_CMD;
-
-typedef PREPACK struct {
- u8 sta_chan_width;
-} POSTPACK WMI_SET_HT_OP_CMD;
-
-typedef PREPACK struct {
- u32 rateMasks[8];
-} POSTPACK WMI_SET_TX_SELECT_RATES_CMD;
-
-typedef PREPACK struct {
- u32 sgiMask;
- u8 sgiPERThreshold;
-} POSTPACK WMI_SET_TX_SGI_PARAM_CMD;
-
-#define DEFAULT_SGI_MASK 0x08080000
-#define DEFAULT_SGI_PER 10
-
-typedef PREPACK struct {
- u32 rateField; /* 1 bit per rate corresponding to index */
- u8 id;
- u8 shortTrys;
- u8 longTrys;
- u8 reserved; /* padding */
-} POSTPACK WMI_SET_RATE_POLICY_CMD;
-
-typedef PREPACK struct {
- u8 metaVersion; /* version of meta data for rx packets <0 = default> (0-7 = valid) */
- u8 dot11Hdr; /* 1 == leave .11 header intact , 0 == replace .11 header with .3 <default> */
- u8 defragOnHost; /* 1 == defragmentation is performed by host, 0 == performed by target <default> */
- u8 reserved[1]; /* alignment */
-} POSTPACK WMI_RX_FRAME_FORMAT_CMD;
-
-
-typedef PREPACK struct {
- u8 enable; /* 1 == device operates in thin mode , 0 == normal mode <default> */
- u8 reserved[3];
-} POSTPACK WMI_SET_THIN_MODE_CMD;
-
-/* AP mode events */
-/* WMI_PS_POLL_EVENT */
-typedef PREPACK struct {
- u16 aid;
-} POSTPACK WMI_PSPOLL_EVENT;
-
-typedef PREPACK struct {
- u32 tx_bytes;
- u32 tx_pkts;
- u32 tx_error;
- u32 tx_discard;
- u32 rx_bytes;
- u32 rx_pkts;
- u32 rx_error;
- u32 rx_discard;
- u32 aid;
-} POSTPACK WMI_PER_STA_STAT;
-
-#define AP_GET_STATS 0
-#define AP_CLEAR_STATS 1
-
-typedef PREPACK struct {
- u32 action;
- WMI_PER_STA_STAT sta[AP_MAX_NUM_STA+1];
-} POSTPACK WMI_AP_MODE_STAT;
-#define WMI_AP_MODE_STAT_SIZE(numSta) (sizeof(u32) + ((numSta + 1) * sizeof(WMI_PER_STA_STAT)))
-
-#define AP_11BG_RATESET1 1
-#define AP_11BG_RATESET2 2
-#define DEF_AP_11BG_RATESET AP_11BG_RATESET1
-typedef PREPACK struct {
- u8 rateset;
-} POSTPACK WMI_AP_SET_11BG_RATESET_CMD;
-/*
- * End of AP mode definitions
- */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _WMI_H_ */
diff --git a/drivers/staging/ath6kl/include/common/wmix.h b/drivers/staging/ath6kl/include/common/wmix.h
deleted file mode 100644
index 9435eab1b7f5..000000000000
--- a/drivers/staging/ath6kl/include/common/wmix.h
+++ /dev/null
@@ -1,271 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="wmix.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-/*
- * This file contains extensions of the WMI protocol specified in the
- * Wireless Module Interface (WMI). It includes definitions of all
- * extended commands and events. Extensions include useful commands
- * that are not directly related to wireless activities. They may
- * be hardware-specific, and they might not be supported on all
- * implementations.
- *
- * Extended WMIX commands are encapsulated in a WMI message with
- * cmd=WMI_EXTENSION_CMD.
- */
-
-#ifndef _WMIX_H_
-#define _WMIX_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "dbglog.h"
-
-/*
- * Extended WMI commands are those that are needed during wireless
- * operation, but which are not really wireless commands. This allows,
- * for instance, platform-specific commands. Extended WMI commands are
- * embedded in a WMI command message with WMI_COMMAND_ID=WMI_EXTENSION_CMDID.
- * Extended WMI events are similarly embedded in a WMI event message with
- * WMI_EVENT_ID=WMI_EXTENSION_EVENTID.
- */
-typedef PREPACK struct {
- u32 commandId;
-} POSTPACK WMIX_CMD_HDR;
-
-typedef enum {
- WMIX_DSETOPEN_REPLY_CMDID = 0x2001,
- WMIX_DSETDATA_REPLY_CMDID,
- WMIX_GPIO_OUTPUT_SET_CMDID,
- WMIX_GPIO_INPUT_GET_CMDID,
- WMIX_GPIO_REGISTER_SET_CMDID,
- WMIX_GPIO_REGISTER_GET_CMDID,
- WMIX_GPIO_INTR_ACK_CMDID,
- WMIX_HB_CHALLENGE_RESP_CMDID,
- WMIX_DBGLOG_CFG_MODULE_CMDID,
- WMIX_PROF_CFG_CMDID, /* 0x200a */
- WMIX_PROF_ADDR_SET_CMDID,
- WMIX_PROF_START_CMDID,
- WMIX_PROF_STOP_CMDID,
- WMIX_PROF_COUNT_GET_CMDID,
-} WMIX_COMMAND_ID;
-
-typedef enum {
- WMIX_DSETOPENREQ_EVENTID = 0x3001,
- WMIX_DSETCLOSE_EVENTID,
- WMIX_DSETDATAREQ_EVENTID,
- WMIX_GPIO_INTR_EVENTID,
- WMIX_GPIO_DATA_EVENTID,
- WMIX_GPIO_ACK_EVENTID,
- WMIX_HB_CHALLENGE_RESP_EVENTID,
- WMIX_DBGLOG_EVENTID,
- WMIX_PROF_COUNT_EVENTID,
-} WMIX_EVENT_ID;
-
-/*
- * =============DataSet support=================
- */
-
-/*
- * WMIX_DSETOPENREQ_EVENTID
- * DataSet Open Request Event
- */
-typedef PREPACK struct {
- u32 dset_id;
- u32 targ_dset_handle; /* echo'ed, not used by Host, */
- u32 targ_reply_fn; /* echo'ed, not used by Host, */
- u32 targ_reply_arg; /* echo'ed, not used by Host, */
-} POSTPACK WMIX_DSETOPENREQ_EVENT;
-
-/*
- * WMIX_DSETCLOSE_EVENTID
- * DataSet Close Event
- */
-typedef PREPACK struct {
- u32 access_cookie;
-} POSTPACK WMIX_DSETCLOSE_EVENT;
-
-/*
- * WMIX_DSETDATAREQ_EVENTID
- * DataSet Data Request Event
- */
-typedef PREPACK struct {
- u32 access_cookie;
- u32 offset;
- u32 length;
- u32 targ_buf; /* echo'ed, not used by Host, */
- u32 targ_reply_fn; /* echo'ed, not used by Host, */
- u32 targ_reply_arg; /* echo'ed, not used by Host, */
-} POSTPACK WMIX_DSETDATAREQ_EVENT;
-
-typedef PREPACK struct {
- u32 status;
- u32 targ_dset_handle;
- u32 targ_reply_fn;
- u32 targ_reply_arg;
- u32 access_cookie;
- u32 size;
- u32 version;
-} POSTPACK WMIX_DSETOPEN_REPLY_CMD;
-
-typedef PREPACK struct {
- u32 status;
- u32 targ_buf;
- u32 targ_reply_fn;
- u32 targ_reply_arg;
- u32 length;
- u8 buf[1];
-} POSTPACK WMIX_DSETDATA_REPLY_CMD;
-
-
-/*
- * =============GPIO support=================
- * All masks are 18-bit masks with bit N operating on GPIO pin N.
- */
-
-
-/*
- * Set GPIO pin output state.
- * In order for output to be driven, a pin must be enabled for output.
- * This can be done during initialization through the GPIO Configuration
- * DataSet, or during operation with the enable_mask.
- *
- * If a request is made to simultaneously set/clear or set/disable or
- * clear/disable or disable/enable, results are undefined.
- */
-typedef PREPACK struct {
- u32 set_mask; /* pins to set */
- u32 clear_mask; /* pins to clear */
- u32 enable_mask; /* pins to enable for output */
- u32 disable_mask; /* pins to disable/tristate */
-} POSTPACK WMIX_GPIO_OUTPUT_SET_CMD;
-
-/*
- * Set a GPIO register. For debug/exceptional cases.
- * Values for gpioreg_id are GPIO_REGISTER_IDs, defined in a
- * platform-dependent header.
- */
-typedef PREPACK struct {
- u32 gpioreg_id; /* GPIO register ID */
- u32 value; /* value to write */
-} POSTPACK WMIX_GPIO_REGISTER_SET_CMD;
-
-/* Get a GPIO register. For debug/exceptional cases. */
-typedef PREPACK struct {
- u32 gpioreg_id; /* GPIO register to read */
-} POSTPACK WMIX_GPIO_REGISTER_GET_CMD;
-
-/*
- * Host acknowledges and re-arms GPIO interrupts. A single
- * message should be used to acknowledge all interrupts that
- * were delivered in an earlier WMIX_GPIO_INTR_EVENT message.
- */
-typedef PREPACK struct {
- u32 ack_mask; /* interrupts to acknowledge */
-} POSTPACK WMIX_GPIO_INTR_ACK_CMD;
-
-/*
- * Target informs Host of GPIO interrupts that have occurred since the
- * last WMIX_GIPO_INTR_ACK_CMD was received. Additional information --
- * the current GPIO input values is provided -- in order to support
- * use of a GPIO interrupt as a Data Valid signal for other GPIO pins.
- */
-typedef PREPACK struct {
- u32 intr_mask; /* pending GPIO interrupts */
- u32 input_values; /* recent GPIO input values */
-} POSTPACK WMIX_GPIO_INTR_EVENT;
-
-/*
- * Target responds to Host's earlier WMIX_GPIO_INPUT_GET_CMDID request
- * using a GPIO_DATA_EVENT with
- * value set to the mask of GPIO pin inputs and
- * reg_id set to GPIO_ID_NONE
- *
- *
- * Target responds to Hosts's earlier WMIX_GPIO_REGISTER_GET_CMDID request
- * using a GPIO_DATA_EVENT with
- * value set to the value of the requested register and
- * reg_id identifying the register (reflects the original request)
- * NB: reg_id supports the future possibility of unsolicited
- * WMIX_GPIO_DATA_EVENTs (for polling GPIO input), and it may
- * simplify Host GPIO support.
- */
-typedef PREPACK struct {
- u32 value;
- u32 reg_id;
-} POSTPACK WMIX_GPIO_DATA_EVENT;
-
-/*
- * =============Error Detection support=================
- */
-
-/*
- * WMIX_HB_CHALLENGE_RESP_CMDID
- * Heartbeat Challenge Response command
- */
-typedef PREPACK struct {
- u32 cookie;
- u32 source;
-} POSTPACK WMIX_HB_CHALLENGE_RESP_CMD;
-
-/*
- * WMIX_HB_CHALLENGE_RESP_EVENTID
- * Heartbeat Challenge Response Event
- */
-#define WMIX_HB_CHALLENGE_RESP_EVENT WMIX_HB_CHALLENGE_RESP_CMD
-
-typedef PREPACK struct {
- struct dbglog_config_s config;
-} POSTPACK WMIX_DBGLOG_CFG_MODULE_CMD;
-
-/*
- * =============Target Profiling support=================
- */
-
-typedef PREPACK struct {
- u32 period; /* Time (in 30.5us ticks) between samples */
- u32 nbins;
-} POSTPACK WMIX_PROF_CFG_CMD;
-
-typedef PREPACK struct {
- u32 addr;
-} POSTPACK WMIX_PROF_ADDR_SET_CMD;
-
-/*
- * Target responds to Hosts's earlier WMIX_PROF_COUNT_GET_CMDID request
- * using a WMIX_PROF_COUNT_EVENT with
- * addr set to the next address
- * count set to the corresponding count
- */
-typedef PREPACK struct {
- u32 addr;
- u32 count;
-} POSTPACK WMIX_PROF_COUNT_EVENT;
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _WMIX_H_ */
diff --git a/drivers/staging/ath6kl/include/common_drv.h b/drivers/staging/ath6kl/include/common_drv.h
deleted file mode 100644
index 34db29958bcb..000000000000
--- a/drivers/staging/ath6kl/include/common_drv.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef COMMON_DRV_H_
-#define COMMON_DRV_H_
-
-#include "hif.h"
-#include "htc_packet.h"
-#include "htc_api.h"
-
-/* structure that is the state information for the default credit distribution callback
- * drivers should instantiate (zero-init as well) this structure in their driver instance
- * and pass it as a context to the HTC credit distribution functions */
-struct common_credit_state_info {
- int TotalAvailableCredits; /* total credits in the system at startup */
- int CurrentFreeCredits; /* credits available in the pool that have not been
- given out to endpoints */
- struct htc_endpoint_credit_dist *pLowestPriEpDist; /* pointer to the lowest priority endpoint dist struct */
-};
-
-struct hci_transport_callbacks {
- s32 (*setupTransport)(void *ar);
- void (*cleanupTransport)(void *ar);
-};
-
-struct hci_transport_misc_handles {
- void *netDevice;
- void *hifDevice;
- void *htcHandle;
-};
-
-/* HTC TX packet tagging definitions */
-#define AR6K_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED
-#define AR6K_DATA_PKT_TAG (AR6K_CONTROL_PKT_TAG + 1)
-
-#define AR6002_VERSION_REV1 0x20000086
-#define AR6002_VERSION_REV2 0x20000188
-#define AR6003_VERSION_REV1 0x300002ba
-#define AR6003_VERSION_REV2 0x30000384
-
-#define AR6002_CUST_DATA_SIZE 112
-#define AR6003_CUST_DATA_SIZE 16
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* OS-independent APIs */
-int ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, struct common_credit_state_info *pCredInfo);
-
-int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
-
-int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
-
-int ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address, u8 *data, u32 length);
-
-int ar6000_reset_device(struct hif_device *hifDevice, u32 TargetType, bool waitForCompletion, bool coldReset);
-
-void ar6000_dump_target_assert_info(struct hif_device *hifDevice, u32 TargetType);
-
-int ar6000_set_htc_params(struct hif_device *hifDevice,
- u32 TargetType,
- u32 MboxIsrYieldValue,
- u8 HtcControlBuffers);
-
-int ar6000_set_hci_bridge_flags(struct hif_device *hifDevice,
- u32 TargetType,
- u32 Flags);
-
-void ar6000_copy_cust_data_from_target(struct hif_device *hifDevice, u32 TargetType);
-
-u8 *ar6000_get_cust_data_buffer(u32 TargetType);
-
-int ar6000_setBTState(void *context, u8 *pInBuf, u32 InBufSize);
-
-int ar6000_setDevicePowerState(void *context, u8 *pInBuf, u32 InBufSize);
-
-int ar6000_setWowMode(void *context, u8 *pInBuf, u32 InBufSize);
-
-int ar6000_setHostMode(void *context, u8 *pInBuf, u32 InBufSize);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*COMMON_DRV_H_*/
diff --git a/drivers/staging/ath6kl/include/dbglog_api.h b/drivers/staging/ath6kl/include/dbglog_api.h
deleted file mode 100644
index a53aed316e3b..000000000000
--- a/drivers/staging/ath6kl/include/dbglog_api.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="dbglog_api.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains host side debug primitives.
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _DBGLOG_API_H_
-#define _DBGLOG_API_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "dbglog.h"
-
-#define DBGLOG_HOST_LOG_BUFFER_SIZE DBGLOG_LOG_BUFFER_SIZE
-
-#define DBGLOG_GET_DBGID(arg) \
- ((arg & DBGLOG_DBGID_MASK) >> DBGLOG_DBGID_OFFSET)
-
-#define DBGLOG_GET_MODULEID(arg) \
- ((arg & DBGLOG_MODULEID_MASK) >> DBGLOG_MODULEID_OFFSET)
-
-#define DBGLOG_GET_NUMARGS(arg) \
- ((arg & DBGLOG_NUM_ARGS_MASK) >> DBGLOG_NUM_ARGS_OFFSET)
-
-#define DBGLOG_GET_TIMESTAMP(arg) \
- ((arg & DBGLOG_TIMESTAMP_MASK) >> DBGLOG_TIMESTAMP_OFFSET)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DBGLOG_API_H_ */
diff --git a/drivers/staging/ath6kl/include/dl_list.h b/drivers/staging/ath6kl/include/dl_list.h
deleted file mode 100644
index 13b1e6956c22..000000000000
--- a/drivers/staging/ath6kl/include/dl_list.h
+++ /dev/null
@@ -1,153 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="dl_list.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Double-link list definitions (adapted from Atheros SDIO stack)
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef __DL_LIST_H___
-#define __DL_LIST_H___
-
-#include "a_osapi.h"
-
-#define A_CONTAINING_STRUCT(address, struct_type, field_name)\
- ((struct_type *)((unsigned long)(address) - (unsigned long)(&((struct_type *)0)->field_name)))
-
-/* list functions */
-/* pointers for the list */
-struct dl_list {
- struct dl_list *pPrev;
- struct dl_list *pNext;
-};
-/*
- * DL_LIST_INIT , initialize doubly linked list
-*/
-#define DL_LIST_INIT(pList)\
- {(pList)->pPrev = pList; (pList)->pNext = pList;}
-
-/* faster macro to init list and add a single item */
-#define DL_LIST_INIT_AND_ADD(pList,pItem) \
-{ (pList)->pPrev = (pItem); \
- (pList)->pNext = (pItem); \
- (pItem)->pNext = (pList); \
- (pItem)->pPrev = (pList); \
-}
-
-#define DL_LIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList)))
-#define DL_LIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext
-#define DL_LIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev
-/*
- * ITERATE_OVER_LIST pStart is the list, pTemp is a temp list member
- * NOT: do not use this function if the items in the list are deleted inside the
- * iteration loop
-*/
-#define ITERATE_OVER_LIST(pStart, pTemp) \
- for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext)
-
-
-/* safe iterate macro that allows the item to be removed from the list
- * the iteration continues to the next item in the list
- */
-#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \
-{ \
- struct dl_list * pTemp; \
- pTemp = (pStart)->pNext; \
- while (pTemp != (pStart)) { \
- (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset); \
- pTemp = pTemp->pNext; \
-
-#define ITERATE_END }}
-
-/*
- * DL_ListInsertTail - insert pAdd to the end of the list
-*/
-static INLINE struct dl_list *DL_ListInsertTail(struct dl_list *pList, struct dl_list *pAdd) {
- /* insert at tail */
- pAdd->pPrev = pList->pPrev;
- pAdd->pNext = pList;
- pList->pPrev->pNext = pAdd;
- pList->pPrev = pAdd;
- return pAdd;
-}
-
-/*
- * DL_ListInsertHead - insert pAdd into the head of the list
-*/
-static INLINE struct dl_list * DL_ListInsertHead(struct dl_list * pList, struct dl_list * pAdd) {
- /* insert at head */
- pAdd->pPrev = pList;
- pAdd->pNext = pList->pNext;
- pList->pNext->pPrev = pAdd;
- pList->pNext = pAdd;
- return pAdd;
-}
-
-#define DL_ListAdd(pList,pItem) DL_ListInsertHead((pList),(pItem))
-/*
- * DL_ListRemove - remove pDel from list
-*/
-static INLINE struct dl_list * DL_ListRemove(struct dl_list * pDel) {
- pDel->pNext->pPrev = pDel->pPrev;
- pDel->pPrev->pNext = pDel->pNext;
- /* point back to itself just to be safe, incase remove is called again */
- pDel->pNext = pDel;
- pDel->pPrev = pDel;
- return pDel;
-}
-
-/*
- * DL_ListRemoveItemFromHead - get a list item from the head
-*/
-static INLINE struct dl_list * DL_ListRemoveItemFromHead(struct dl_list * pList) {
- struct dl_list * pItem = NULL;
- if (pList->pNext != pList) {
- pItem = pList->pNext;
- /* remove the first item from head */
- DL_ListRemove(pItem);
- }
- return pItem;
-}
-
-static INLINE struct dl_list * DL_ListRemoveItemFromTail(struct dl_list * pList) {
- struct dl_list * pItem = NULL;
- if (pList->pPrev != pList) {
- pItem = pList->pPrev;
- /* remove the item from tail */
- DL_ListRemove(pItem);
- }
- return pItem;
-}
-
-/* transfer src list items to the tail of the destination list */
-static INLINE void DL_ListTransferItemsToTail(struct dl_list * pDest, struct dl_list * pSrc) {
- /* only concatenate if src is not empty */
- if (!DL_LIST_IS_EMPTY(pSrc)) {
- /* cut out circular list in src and re-attach to end of dest */
- pSrc->pPrev->pNext = pDest;
- pSrc->pNext->pPrev = pDest->pPrev;
- pDest->pPrev->pNext = pSrc->pNext;
- pDest->pPrev = pSrc->pPrev;
- /* terminate src list, it is now empty */
- pSrc->pPrev = pSrc;
- pSrc->pNext = pSrc;
- }
-}
-
-#endif /* __DL_LIST_H___ */
diff --git a/drivers/staging/ath6kl/include/dset_api.h b/drivers/staging/ath6kl/include/dset_api.h
deleted file mode 100644
index fe901ba40ec6..000000000000
--- a/drivers/staging/ath6kl/include/dset_api.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="dset_api.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Host-side DataSet API.
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _DSET_API_H_
-#define _DSET_API_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/*
- * Host-side DataSet support is optional, and is not
- * currently required for correct operation. To disable
- * Host-side DataSet support, set this to 0.
- */
-#ifndef CONFIG_HOST_DSET_SUPPORT
-#define CONFIG_HOST_DSET_SUPPORT 1
-#endif
-
-/* Called to send a DataSet Open Reply back to the Target. */
-int wmi_dset_open_reply(struct wmi_t *wmip,
- u32 status,
- u32 access_cookie,
- u32 size,
- u32 version,
- u32 targ_handle,
- u32 targ_reply_fn,
- u32 targ_reply_arg);
-
-/* Called to send a DataSet Data Reply back to the Target. */
-int wmi_dset_data_reply(struct wmi_t *wmip,
- u32 status,
- u8 *host_buf,
- u32 length,
- u32 targ_buf,
- u32 targ_reply_fn,
- u32 targ_reply_arg);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
-#endif /* _DSET_API_H_ */
diff --git a/drivers/staging/ath6kl/include/hci_transport_api.h b/drivers/staging/ath6kl/include/hci_transport_api.h
deleted file mode 100644
index 5e903fad23fc..000000000000
--- a/drivers/staging/ath6kl/include/hci_transport_api.h
+++ /dev/null
@@ -1,259 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _HCI_TRANSPORT_API_H_
-#define _HCI_TRANSPORT_API_H_
-
- /* Bluetooth HCI packets are stored in HTC packet containers */
-#include "htc_packet.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-typedef void *HCI_TRANSPORT_HANDLE;
-
-typedef HTC_ENDPOINT_ID HCI_TRANSPORT_PACKET_TYPE;
-
- /* we map each HCI packet class to a static Endpoint ID */
-#define HCI_COMMAND_TYPE ENDPOINT_1
-#define HCI_EVENT_TYPE ENDPOINT_2
-#define HCI_ACL_TYPE ENDPOINT_3
-#define HCI_PACKET_INVALID ENDPOINT_MAX
-
-#define HCI_GET_PACKET_TYPE(pP) (pP)->Endpoint
-#define HCI_SET_PACKET_TYPE(pP,s) (pP)->Endpoint = (s)
-
-/* callback when an HCI packet was completely sent */
-typedef void (*HCI_TRANSPORT_SEND_PKT_COMPLETE)(void *, struct htc_packet *);
-/* callback when an HCI packet is received */
-typedef void (*HCI_TRANSPORT_RECV_PKT)(void *, struct htc_packet *);
-/* Optional receive buffer re-fill callback,
- * On some OSes (like Linux) packets are allocated from a global pool and indicated up
- * to the network stack. The driver never gets the packets back from the OS. For these OSes
- * a refill callback can be used to allocate and re-queue buffers into HTC.
- * A refill callback is used for the reception of ACL and EVENT packets. The caller must
- * set the watermark trigger point to cause a refill.
- */
-typedef void (*HCI_TRANSPORT_RECV_REFILL)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable);
-/* Optional receive packet refill
- * On some systems packet buffers are an extremely limited resource. Rather than
- * queue largest-possible-sized buffers to the HCI bridge, some systems would rather
- * allocate a specific size as the packet is received. The trade off is
- * slightly more processing (callback invoked for each RX packet)
- * for the benefit of committing fewer buffer resources into the bridge.
- *
- * The callback is provided the length of the pending packet to fetch. This includes the
- * full transport header, HCI header, plus the length of payload. The callback can return a pointer to
- * the allocated HTC packet for immediate use.
- *
- * NOTE*** This callback is mutually exclusive with the the refill callback above.
- *
- * */
-typedef struct htc_packet *(*HCI_TRANSPORT_RECV_ALLOC)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int Length);
-
-typedef enum _HCI_SEND_FULL_ACTION {
- HCI_SEND_FULL_KEEP = 0, /* packet that overflowed should be kept in the queue */
- HCI_SEND_FULL_DROP = 1, /* packet that overflowed should be dropped */
-} HCI_SEND_FULL_ACTION;
-
-/* callback when an HCI send queue exceeds the caller's MaxSendQueueDepth threshold,
- * the callback must return the send full action to take (either DROP or KEEP) */
-typedef HCI_SEND_FULL_ACTION (*HCI_TRANSPORT_SEND_FULL)(void *, struct htc_packet *);
-
-struct hci_transport_properties {
- int HeadRoom; /* number of bytes in front of HCI packet for header space */
- int TailRoom; /* number of bytes at the end of the HCI packet for tail space */
- int IOBlockPad; /* I/O block padding required (always a power of 2) */
-};
-
-struct hci_transport_config_info {
- int ACLRecvBufferWaterMark; /* low watermark to trigger recv refill */
- int EventRecvBufferWaterMark; /* low watermark to trigger recv refill */
- int MaxSendQueueDepth; /* max number of packets in the single send queue */
- void *pContext; /* context for all callbacks */
- void (*TransportFailure)(void *pContext, int Status); /* transport failure callback */
- int (*TransportReady)(HCI_TRANSPORT_HANDLE, struct hci_transport_properties *,void *pContext); /* transport is ready */
- void (*TransportRemoved)(void *pContext); /* transport was removed */
- /* packet processing callbacks */
- HCI_TRANSPORT_SEND_PKT_COMPLETE pHCISendComplete;
- HCI_TRANSPORT_RECV_PKT pHCIPktRecv;
- HCI_TRANSPORT_RECV_REFILL pHCIPktRecvRefill;
- HCI_TRANSPORT_RECV_ALLOC pHCIPktRecvAlloc;
- HCI_TRANSPORT_SEND_FULL pHCISendFull;
-};
-
-/* ------ Function Prototypes ------ */
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Attach to the HCI transport module
- @function name: HCI_TransportAttach
- @input: HTCHandle - HTC handle (see HTC apis)
- pInfo - initialization information
- @output:
- @return: HCI_TRANSPORT_HANDLE on success, NULL on failure
- @notes: The HTC module provides HCI transport services.
- @example:
- @see also: HCI_TransportDetach
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, struct hci_transport_config_info *pInfo);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Detach from the HCI transport module
- @function name: HCI_TransportDetach
- @input: HciTrans - HCI transport handle
- pInfo - initialization information
- @output:
- @return:
- @notes:
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Add receive packets to the HCI transport
- @function name: HCI_TransportAddReceivePkts
- @input: HciTrans - HCI transport handle
- pQueue - a queue holding one or more packets
- @output:
- @return: 0 on success
- @notes: user must supply HTC packets for capturing incomming HCI packets. The caller
- must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
- macro. Each packet in the queue must be of the same type and length
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Send an HCI packet packet
- @function name: HCI_TransportSendPkt
- @input: HciTrans - HCI transport handle
- pPacket - packet to send
- Synchronous - send the packet synchronously (blocking)
- @output:
- @return: 0
- @notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() and
- HCI_SET_PACKET_TYPE() macros to prepare the packet.
- If Synchronous is set to false the call is fully asynchronous. On error or completion,
- the registered send complete callback will be called.
- If Synchronous is set to true, the call will block until the packet is sent, if the
- interface cannot send the packet within a 2 second timeout, the function will return
- the failure code : A_EBUSY.
-
- Synchronous Mode should only be used at start-up to initialize the HCI device using
- custom HCI commands. It should NOT be mixed with Asynchronous operations. Mixed synchronous
- and asynchronous operation behavior is undefined.
-
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous);
-
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Stop HCI transport
- @function name: HCI_TransportStop
- @input: HciTrans - hci transport handle
- @output:
- @return:
- @notes: HCI transport communication will be halted. All receive and pending TX packets will
- be flushed.
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Start the HCI transport
- @function name: HCI_TransportStart
- @input: HciTrans - hci transport handle
- @output:
- @return: 0 on success
- @notes: HCI transport communication will begin, the caller can expect the arrival
- of HCI recv packets as soon as this call returns.
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Enable or Disable Asynchronous Recv
- @function name: HCI_TransportEnableDisableAsyncRecv
- @input: HciTrans - hci transport handle
- Enable - enable or disable asynchronous recv
- @output:
- @return: 0 on success
- @notes: This API must be called when HCI recv is handled synchronously
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Receive an event packet from the HCI transport synchronously using polling
- @function name: HCI_TransportRecvHCIEventSync
- @input: HciTrans - hci transport handle
- pPacket - HTC packet to hold the recv data
- MaxPollMS - maximum polling duration in Milliseconds;
- @output:
- @return: 0 on success
- @notes: This API should be used only during HCI device initialization, the caller must call
- HCI_TransportEnableDisableAsyncRecv with Enable=false prior to using this API.
- This API will only capture HCI Event packets.
- @example:
- @see also: HCI_TransportEnableDisableAsyncRecv
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
- struct htc_packet *pPacket,
- int MaxPollMS);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Set the desired baud rate for the underlying transport layer
- @function name: HCI_TransportSetBaudRate
- @input: HciTrans - hci transport handle
- Baud - baud rate in bps
- @output:
- @return: 0 on success
- @notes: This API should be used only after HCI device initialization
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Enable/Disable HCI Transport Power Management
- @function name: HCI_TransportEnablePowerMgmt
- @input: HciTrans - hci transport handle
- Enable - 1 = Enable, 0 = Disable
- @output:
- @return: 0 on success
- @notes:
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HCI_TRANSPORT_API_H_ */
diff --git a/drivers/staging/ath6kl/include/hif.h b/drivers/staging/ath6kl/include/hif.h
deleted file mode 100644
index 24200e778c3b..000000000000
--- a/drivers/staging/ath6kl/include/hif.h
+++ /dev/null
@@ -1,456 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="hif.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// HIF specific declarations and prototypes
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _HIF_H_
-#define _HIF_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Header files */
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_osapi.h"
-#include "dl_list.h"
-
-
-typedef struct htc_callbacks HTC_CALLBACKS;
-struct hif_device;
-
-/*
- * direction - Direction of transfer (HIF_READ/HIF_WRITE).
- */
-#define HIF_READ 0x00000001
-#define HIF_WRITE 0x00000002
-#define HIF_DIR_MASK (HIF_READ | HIF_WRITE)
-
-/*
- * type - An interface may support different kind of read/write commands.
- * For example: SDIO supports CMD52/CMD53s. In case of MSIO it
- * translates to using different kinds of TPCs. The command type
- * is thus divided into a basic and an extended command and can
- * be specified using HIF_BASIC_IO/HIF_EXTENDED_IO.
- */
-#define HIF_BASIC_IO 0x00000004
-#define HIF_EXTENDED_IO 0x00000008
-#define HIF_TYPE_MASK (HIF_BASIC_IO | HIF_EXTENDED_IO)
-
-/*
- * emode - This indicates the whether the command is to be executed in a
- * blocking or non-blocking fashion (HIF_SYNCHRONOUS/
- * HIF_ASYNCHRONOUS). The read/write data paths in HTC have been
- * implemented using the asynchronous mode allowing the the bus
- * driver to indicate the completion of operation through the
- * registered callback routine. The requirement primarily comes
- * from the contexts these operations get called from (a driver's
- * transmit context or the ISR context in case of receive).
- * Support for both of these modes is essential.
- */
-#define HIF_SYNCHRONOUS 0x00000010
-#define HIF_ASYNCHRONOUS 0x00000020
-#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS)
-
-/*
- * dmode - An interface may support different kinds of commands based on
- * the tradeoff between the amount of data it can carry and the
- * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/
- * HIF_BLOCK_BASIS). In case of latter, the data is rounded off
- * to the nearest block size by padding. The size of the block is
- * configurable at compile time using the HIF_BLOCK_SIZE and is
- * negotiated with the target during initialization after the
- * AR6000 interrupts are enabled.
- */
-#define HIF_BYTE_BASIS 0x00000040
-#define HIF_BLOCK_BASIS 0x00000080
-#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS)
-
-/*
- * amode - This indicates if the address has to be incremented on AR6000
- * after every read/write operation (HIF?FIXED_ADDRESS/
- * HIF_INCREMENTAL_ADDRESS).
- */
-#define HIF_FIXED_ADDRESS 0x00000100
-#define HIF_INCREMENTAL_ADDRESS 0x00000200
-#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS)
-
-#define HIF_WR_ASYNC_BYTE_FIX \
- (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
-#define HIF_WR_ASYNC_BYTE_INC \
- (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
-#define HIF_WR_ASYNC_BLOCK_INC \
- (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
-#define HIF_WR_SYNC_BYTE_FIX \
- (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
-#define HIF_WR_SYNC_BYTE_INC \
- (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
-#define HIF_WR_SYNC_BLOCK_INC \
- (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
-#define HIF_WR_ASYNC_BLOCK_FIX \
- (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
-#define HIF_WR_SYNC_BLOCK_FIX \
- (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
-#define HIF_RD_SYNC_BYTE_INC \
- (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
-#define HIF_RD_SYNC_BYTE_FIX \
- (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
-#define HIF_RD_ASYNC_BYTE_FIX \
- (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
-#define HIF_RD_ASYNC_BLOCK_FIX \
- (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
-#define HIF_RD_ASYNC_BYTE_INC \
- (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
-#define HIF_RD_ASYNC_BLOCK_INC \
- (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
-#define HIF_RD_SYNC_BLOCK_INC \
- (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
-#define HIF_RD_SYNC_BLOCK_FIX \
- (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
-
-typedef enum {
- HIF_DEVICE_POWER_STATE = 0,
- HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
- HIF_DEVICE_GET_MBOX_ADDR,
- HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
- HIF_DEVICE_GET_IRQ_PROC_MODE,
- HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC,
- HIF_DEVICE_POWER_STATE_CHANGE,
- HIF_DEVICE_GET_IRQ_YIELD_PARAMS,
- HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT,
- HIF_DEVICE_GET_OS_DEVICE,
- HIF_DEVICE_DEBUG_BUS_STATE,
-} HIF_DEVICE_CONFIG_OPCODE;
-
-/*
- * HIF CONFIGURE definitions:
- *
- * HIF_DEVICE_GET_MBOX_BLOCK_SIZE
- * input : none
- * output : array of 4 u32s
- * notes: block size is returned for each mailbox (4)
- *
- * HIF_DEVICE_GET_MBOX_ADDR
- * input : none
- * output : struct hif_device_mbox_info
- * notes:
- *
- * HIF_DEVICE_GET_PENDING_EVENTS_FUNC
- * input : none
- * output: HIF_PENDING_EVENTS_FUNC function pointer
- * notes: this is optional for the HIF layer, if the request is
- * not handled then it indicates that the upper layer can use
- * the standard device methods to get pending events (IRQs, mailbox messages etc..)
- * otherwise it can call the function pointer to check pending events.
- *
- * HIF_DEVICE_GET_IRQ_PROC_MODE
- * input : none
- * output : HIF_DEVICE_IRQ_PROCESSING_MODE (interrupt processing mode)
- * note: the hif layer interfaces with the underlying OS-specific bus driver. The HIF
- * layer can report whether IRQ processing is requires synchronous behavior or
- * can be processed using asynchronous bus requests (typically faster).
- *
- * HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC
- * input :
- * output : HIF_MASK_UNMASK_RECV_EVENT function pointer
- * notes: this is optional for the HIF layer. The HIF layer may require a special mechanism
- * to mask receive message events. The upper layer can call this pointer when it needs
- * to mask/unmask receive events (in case it runs out of buffers).
- *
- * HIF_DEVICE_POWER_STATE_CHANGE
- *
- * input : HIF_DEVICE_POWER_CHANGE_TYPE
- * output : none
- * note: this is optional for the HIF layer. The HIF layer can handle power on/off state change
- * requests in an interconnect specific way. This is highly OS and bus driver dependent.
- * The caller must guarantee that no HIF read/write requests will be made after the device
- * is powered down.
- *
- * HIF_DEVICE_GET_IRQ_YIELD_PARAMS
- *
- * input : none
- * output : struct hif_device_irq_yield_params
- * note: This query checks if the HIF layer wishes to impose a processing yield count for the DSR handler.
- * The DSR callback handler will exit after a fixed number of RX packets or events are processed.
- * This query is only made if the device reports an IRQ processing mode of HIF_DEVICE_IRQ_SYNC_ONLY.
- * The HIF implementation can ignore this command if it does not desire the DSR callback to yield.
- * The HIF layer can indicate the maximum number of IRQ processing units (RX packets) before the
- * DSR handler callback must yield and return control back to the HIF layer. When a yield limit is
- * used the DSR callback will not call HIFAckInterrupts() as it would normally do before returning.
- * The HIF implementation that requires a yield count must call HIFAckInterrupt() when it is prepared
- * to process interrupts again.
- *
- * HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT
- * input : none
- * output : struct hif_device_scatter_support_info
- * note: This query checks if the HIF layer implements the SCATTER request interface. Scatter requests
- * allows upper layers to submit mailbox I/O operations using a list of buffers. This is useful for
- * multi-message transfers that can better utilize the bus interconnect.
- *
- *
- * HIF_DEVICE_GET_OS_DEVICE
- * intput : none
- * output : struct hif_device_os_device_info;
- * note: On some operating systems, the HIF layer has a parent device object for the bus. This object
- * may be required to register certain types of logical devices.
- *
- * HIF_DEVICE_DEBUG_BUS_STATE
- * input : none
- * output : none
- * note: This configure option triggers the HIF interface to dump as much bus interface state. This
- * configuration request is optional (No-OP on some HIF implementations)
- *
- */
-
-struct hif_mbox_properties {
- u32 ExtendedAddress; /* extended address for larger writes */
- u32 ExtendedSize;
-};
-
-#define HIF_MBOX_FLAG_NO_BUNDLING (1 << 0) /* do not allow bundling over the mailbox */
-
-typedef enum _MBOX_BUF_IF_TYPE {
- MBOX_BUS_IF_SDIO = 0,
- MBOX_BUS_IF_SPI = 1,
-} MBOX_BUF_IF_TYPE;
-
-struct hif_device_mbox_info {
- u32 MboxAddresses[4]; /* must be first element for legacy HIFs that return the address in
- and ARRAY of 32-bit words */
-
- /* the following describe extended mailbox properties */
- struct hif_mbox_properties MboxProp[4];
- /* if the HIF supports the GMbox extended address region it can report it
- * here, some interfaces cannot support the GMBOX address range and not set this */
- u32 GMboxAddress;
- u32 GMboxSize;
- u32 Flags; /* flags to describe mbox behavior or usage */
- MBOX_BUF_IF_TYPE MboxBusIFType; /* mailbox bus interface type */
-};
-
-typedef enum {
- HIF_DEVICE_IRQ_SYNC_ONLY, /* for HIF implementations that require the DSR to process all
- interrupts before returning */
- HIF_DEVICE_IRQ_ASYNC_SYNC, /* for HIF implementations that allow DSR to process interrupts
- using ASYNC I/O (that is HIFAckInterrupt can be called at a
- later time */
-} HIF_DEVICE_IRQ_PROCESSING_MODE;
-
-typedef enum {
- HIF_DEVICE_POWER_UP, /* HIF layer should power up interface and/or module */
- HIF_DEVICE_POWER_DOWN, /* HIF layer should initiate bus-specific measures to minimize power */
- HIF_DEVICE_POWER_CUT /* HIF layer should initiate bus-specific AND/OR platform-specific measures
- to completely power-off the module and associated hardware (i.e. cut power supplies)
- */
-} HIF_DEVICE_POWER_CHANGE_TYPE;
-
-struct hif_device_irq_yield_params {
- int RecvPacketYieldCount; /* max number of packets to force DSR to return */
-};
-
-
-struct hif_scatter_item {
- u8 *pBuffer; /* CPU accessible address of buffer */
- int Length; /* length of transfer to/from this buffer */
- void *pCallerContexts[2]; /* space for caller to insert a context associated with this item */
-};
-
-struct hif_scatter_req;
-typedef void ( *HIF_SCATTER_COMP_CB)(struct hif_scatter_req *);
-
-typedef enum _HIF_SCATTER_METHOD {
- HIF_SCATTER_NONE = 0,
- HIF_SCATTER_DMA_REAL, /* Real SG support no restrictions */
- HIF_SCATTER_DMA_BOUNCE, /* Uses SG DMA but HIF layer uses an internal bounce buffer */
-} HIF_SCATTER_METHOD;
-
-struct hif_scatter_req {
- struct dl_list ListLink; /* link management */
- u32 Address; /* address for the read/write operation */
- u32 Request; /* request flags */
- u32 TotalLength; /* total length of entire transfer */
- u32 CallerFlags; /* caller specific flags can be stored here */
- HIF_SCATTER_COMP_CB CompletionRoutine; /* completion routine set by caller */
- int CompletionStatus; /* status of completion */
- void *Context; /* caller context for this request */
- int ValidScatterEntries; /* number of valid entries set by caller */
- HIF_SCATTER_METHOD ScatterMethod; /* scatter method handled by HIF */
- void *HIFPrivate[4]; /* HIF private area */
- u8 *pScatterBounceBuffer; /* bounce buffer for upper layers to copy to/from */
- struct hif_scatter_item ScatterList[1]; /* start of scatter list */
-};
-
-typedef struct hif_scatter_req * ( *HIF_ALLOCATE_SCATTER_REQUEST)(struct hif_device *device);
-typedef void ( *HIF_FREE_SCATTER_REQUEST)(struct hif_device *device, struct hif_scatter_req *request);
-typedef int ( *HIF_READWRITE_SCATTER)(struct hif_device *device, struct hif_scatter_req *request);
-
-struct hif_device_scatter_support_info {
- /* information returned from HIF layer */
- HIF_ALLOCATE_SCATTER_REQUEST pAllocateReqFunc;
- HIF_FREE_SCATTER_REQUEST pFreeReqFunc;
- HIF_READWRITE_SCATTER pReadWriteScatterFunc;
- int MaxScatterEntries;
- int MaxTransferSizePerScatterReq;
-};
-
-struct hif_device_os_device_info {
- void *pOSDevice;
-};
-
-#define HIF_MAX_DEVICES 1
-
-struct htc_callbacks {
- void *context; /* context to pass to the dsrhandler
- note : rwCompletionHandler is provided the context passed to HIFReadWrite */
- int (* rwCompletionHandler)(void *rwContext, int status);
- int (* dsrHandler)(void *context);
-};
-
-typedef struct osdrv_callbacks {
- void *context; /* context to pass for all callbacks except deviceRemovedHandler
- the deviceRemovedHandler is only called if the device is claimed */
- int (* deviceInsertedHandler)(void *context, void *hif_handle);
- int (* deviceRemovedHandler)(void *claimedContext, void *hif_handle);
- int (* deviceSuspendHandler)(void *context);
- int (* deviceResumeHandler)(void *context);
- int (* deviceWakeupHandler)(void *context);
- int (* devicePowerChangeHandler)(void *context, HIF_DEVICE_POWER_CHANGE_TYPE config);
-} OSDRV_CALLBACKS;
-
-#define HIF_OTHER_EVENTS (1 << 0) /* other interrupts (non-Recv) are pending, host
- needs to read the register table to figure out what */
-#define HIF_RECV_MSG_AVAIL (1 << 1) /* pending recv packet */
-
-struct hif_pending_events_info {
- u32 Events;
- u32 LookAhead;
- u32 AvailableRecvBytes;
-#ifdef THREAD_X
- u32 Polling;
- u32 INT_CAUSE_REG;
-#endif
-};
-
- /* function to get pending events , some HIF modules use special mechanisms
- * to detect packet available and other interrupts */
-typedef int ( *HIF_PENDING_EVENTS_FUNC)(struct hif_device *device,
- struct hif_pending_events_info *pEvents,
- void *AsyncContext);
-
-#define HIF_MASK_RECV true
-#define HIF_UNMASK_RECV false
- /* function to mask recv events */
-typedef int ( *HIF_MASK_UNMASK_RECV_EVENT)(struct hif_device *device,
- bool Mask,
- void *AsyncContext);
-
-
-/*
- * This API is used to perform any global initialization of the HIF layer
- * and to set OS driver callbacks (i.e. insertion/removal) to the HIF layer
- *
- */
-int HIFInit(OSDRV_CALLBACKS *callbacks);
-
-/* This API claims the HIF device and provides a context for handling removal.
- * The device removal callback is only called when the OSDRV layer claims
- * a device. The claimed context must be non-NULL */
-void HIFClaimDevice(struct hif_device *device, void *claimedContext);
-/* release the claimed device */
-void HIFReleaseDevice(struct hif_device *device);
-
-/* This API allows the HTC layer to attach to the HIF device */
-int HIFAttachHTC(struct hif_device *device, HTC_CALLBACKS *callbacks);
-/* This API detaches the HTC layer from the HIF device */
-void HIFDetachHTC(struct hif_device *device);
-
-/*
- * This API is used to provide the read/write interface over the specific bus
- * interface.
- * address - Starting address in the AR6000's address space. For mailbox
- * writes, it refers to the start of the mbox boundary. It should
- * be ensured that the last byte falls on the mailbox's EOM. For
- * mailbox reads, it refers to the end of the mbox boundary.
- * buffer - Pointer to the buffer containg the data to be transmitted or
- * received.
- * length - Amount of data to be transmitted or received.
- * request - Characterizes the attributes of the command.
- */
-int
-HIFReadWrite(struct hif_device *device,
- u32 address,
- u8 *buffer,
- u32 length,
- u32 request,
- void *context);
-
-/*
- * This can be initiated from the unload driver context when the OSDRV layer has no more use for
- * the device.
- */
-void HIFShutDownDevice(struct hif_device *device);
-
-/*
- * This should translate to an acknowledgment to the bus driver indicating that
- * the previous interrupt request has been serviced and the all the relevant
- * sources have been cleared. HTC is ready to process more interrupts.
- * This should prevent the bus driver from raising an interrupt unless the
- * previous one has been serviced and acknowledged using the previous API.
- */
-void HIFAckInterrupt(struct hif_device *device);
-
-void HIFMaskInterrupt(struct hif_device *device);
-
-void HIFUnMaskInterrupt(struct hif_device *device);
-
-#ifdef THREAD_X
-/*
- * This set of functions are to be used by the bus driver to notify
- * the HIF module about various events.
- * These are not implemented if the bus driver provides an alternative
- * way for this notification though callbacks for instance.
- */
-int HIFInsertEventNotify(void);
-
-int HIFRemoveEventNotify(void);
-
-int HIFIRQEventNotify(void);
-
-int HIFRWCompleteEventNotify(void);
-#endif
-
-int
-HIFConfigureDevice(struct hif_device *device, HIF_DEVICE_CONFIG_OPCODE opcode,
- void *config, u32 configLen);
-
-/*
- * This API wait for the remaining MBOX messages to be drained
- * This should be moved to HTC AR6K layer
- */
-int hifWaitForPendingRecv(struct hif_device *device);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HIF_H_ */
diff --git a/drivers/staging/ath6kl/include/host_version.h b/drivers/staging/ath6kl/include/host_version.h
deleted file mode 100644
index 74f1982c681b..000000000000
--- a/drivers/staging/ath6kl/include/host_version.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="host_version.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains version information for the sample host driver for the
-// AR6000 chip
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _HOST_VERSION_H_
-#define _HOST_VERSION_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <AR6002/AR6K_version.h>
-
-/*
- * The version number is made up of major, minor, patch and build
- * numbers. These are 16 bit numbers. The build and release script will
- * set the build number using a Perforce counter. Here the build number is
- * set to 9999 so that builds done without the build-release script are easily
- * identifiable.
- */
-
-#define ATH_SW_VER_MAJOR __VER_MAJOR_
-#define ATH_SW_VER_MINOR __VER_MINOR_
-#define ATH_SW_VER_PATCH __VER_PATCH_
-#define ATH_SW_VER_BUILD __BUILD_NUMBER_
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HOST_VERSION_H_ */
diff --git a/drivers/staging/ath6kl/include/htc_api.h b/drivers/staging/ath6kl/include/htc_api.h
deleted file mode 100644
index 4fb767559f82..000000000000
--- a/drivers/staging/ath6kl/include/htc_api.h
+++ /dev/null
@@ -1,575 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc_api.h" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _HTC_API_H_
-#define _HTC_API_H_
-
-#include "htc_packet.h"
-#include <htc.h>
-#include <htc_services.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* TODO.. for BMI */
-#define ENDPOINT1 0
-// TODO -remove me, but we have to fix BMI first
-#define HTC_MAILBOX_NUM_MAX 4
-
-/* this is the amount of header room required by users of HTC */
-#define HTC_HEADER_LEN HTC_HDR_LENGTH
-
-typedef void *HTC_HANDLE;
-
-typedef u16 HTC_SERVICE_ID;
-
-struct htc_init_info {
- void *pContext; /* context for target failure notification */
- void (*TargetFailure)(void *Instance, int Status);
-};
-
-/* per service connection send completion */
-typedef void (*HTC_EP_SEND_PKT_COMPLETE)(void *,struct htc_packet *);
-/* per service connection callback when a plurality of packets have been sent
- * The struct htc_packet_queue is a temporary queue object (e.g. freed on return from the callback)
- * to hold a list of completed send packets.
- * If the handler cannot fully traverse the packet queue before returning, it should
- * transfer the items of the queue into the caller's private queue using:
- * HTC_PACKET_ENQUEUE() */
-typedef void (*HTC_EP_SEND_PKT_COMP_MULTIPLE)(void *,struct htc_packet_queue *);
-/* per service connection pkt received */
-typedef void (*HTC_EP_RECV_PKT)(void *,struct htc_packet *);
-/* per service connection callback when a plurality of packets are received
- * The struct htc_packet_queue is a temporary queue object (e.g. freed on return from the callback)
- * to hold a list of recv packets.
- * If the handler cannot fully traverse the packet queue before returning, it should
- * transfer the items of the queue into the caller's private queue using:
- * HTC_PACKET_ENQUEUE() */
-typedef void (*HTC_EP_RECV_PKT_MULTIPLE)(void *,struct htc_packet_queue *);
-
-/* Optional per service connection receive buffer re-fill callback,
- * On some OSes (like Linux) packets are allocated from a global pool and indicated up
- * to the network stack. The driver never gets the packets back from the OS. For these OSes
- * a refill callback can be used to allocate and re-queue buffers into HTC.
- *
- * On other OSes, the network stack can call into the driver's OS-specifc "return_packet" handler and
- * the driver can re-queue these buffers into HTC. In this regard a refill callback is
- * unnecessary */
-typedef void (*HTC_EP_RECV_REFILL)(void *, HTC_ENDPOINT_ID Endpoint);
-
-/* Optional per service connection receive buffer allocation callback.
- * On some systems packet buffers are an extremely limited resource. Rather than
- * queue largest-possible-sized buffers to HTC, some systems would rather
- * allocate a specific size as the packet is received. The trade off is
- * slightly more processing (callback invoked for each RX packet)
- * for the benefit of committing fewer buffer resources into HTC.
- *
- * The callback is provided the length of the pending packet to fetch. This includes the
- * HTC header length plus the length of payload. The callback can return a pointer to
- * the allocated HTC packet for immediate use.
- *
- * Alternatively a variant of this handler can be used to allocate large receive packets as needed.
- * For example an application can use the refill mechanism for normal packets and the recv-alloc mechanism to
- * handle the case where a large packet buffer is required. This can significantly reduce the
- * amount of "committed" memory used to receive packets.
- *
- * */
-typedef struct htc_packet *(*HTC_EP_RECV_ALLOC)(void *, HTC_ENDPOINT_ID Endpoint, int Length);
-
-typedef enum _HTC_SEND_FULL_ACTION {
- HTC_SEND_FULL_KEEP = 0, /* packet that overflowed should be kept in the queue */
- HTC_SEND_FULL_DROP = 1, /* packet that overflowed should be dropped */
-} HTC_SEND_FULL_ACTION;
-
-/* Optional per service connection callback when a send queue is full. This can occur if the
- * host continues queueing up TX packets faster than credits can arrive
- * To prevent the host (on some Oses like Linux) from continuously queueing packets
- * and consuming resources, this callback is provided so that that the host
- * can disable TX in the subsystem (i.e. network stack).
- * This callback is invoked for each packet that "overflows" the HTC queue. The callback can
- * determine whether the new packet that overflowed the queue can be kept (HTC_SEND_FULL_KEEP) or
- * dropped (HTC_SEND_FULL_DROP). If a packet is dropped, the EpTxComplete handler will be called
- * and the packet's status field will be set to A_NO_RESOURCE.
- * Other OSes require a "per-packet" indication for each completed TX packet, this
- * closed loop mechanism will prevent the network stack from overunning the NIC
- * The packet to keep or drop is passed for inspection to the registered handler the handler
- * must ONLY inspect the packet, it may not free or reclaim the packet. */
-typedef HTC_SEND_FULL_ACTION (*HTC_EP_SEND_QUEUE_FULL)(void *, struct htc_packet *pPacket);
-
-struct htc_ep_callbacks {
- void *pContext; /* context for each callback */
- HTC_EP_SEND_PKT_COMPLETE EpTxComplete; /* tx completion callback for connected endpoint */
- HTC_EP_RECV_PKT EpRecv; /* receive callback for connected endpoint */
- HTC_EP_RECV_REFILL EpRecvRefill; /* OPTIONAL receive re-fill callback for connected endpoint */
- HTC_EP_SEND_QUEUE_FULL EpSendFull; /* OPTIONAL send full callback */
- HTC_EP_RECV_ALLOC EpRecvAlloc; /* OPTIONAL recv allocation callback */
- HTC_EP_RECV_ALLOC EpRecvAllocThresh; /* OPTIONAL recv allocation callback based on a threshold */
- HTC_EP_SEND_PKT_COMP_MULTIPLE EpTxCompleteMultiple; /* OPTIONAL completion handler for multiple complete
- indications (EpTxComplete must be NULL) */
- HTC_EP_RECV_PKT_MULTIPLE EpRecvPktMultiple; /* OPTIONAL completion handler for multiple
- recv packet indications (EpRecv must be NULL) */
- int RecvAllocThreshold; /* if EpRecvAllocThresh is non-NULL, HTC will compare the
- threshold value to the current recv packet length and invoke
- the EpRecvAllocThresh callback to acquire a packet buffer */
- int RecvRefillWaterMark; /* if a EpRecvRefill handler is provided, this value
- can be used to set a trigger refill callback
- when the recv queue drops below this value
- if set to 0, the refill is only called when packets
- are empty */
-};
-
-/* service connection information */
-struct htc_service_connect_req {
- HTC_SERVICE_ID ServiceID; /* service ID to connect to */
- u16 ConnectionFlags; /* connection flags, see htc protocol definition */
- u8 *pMetaData; /* ptr to optional service-specific meta-data */
- u8 MetaDataLength; /* optional meta data length */
- struct htc_ep_callbacks EpCallbacks; /* endpoint callbacks */
- int MaxSendQueueDepth; /* maximum depth of any send queue */
- u32 LocalConnectionFlags; /* HTC flags for the host-side (local) connection */
- unsigned int MaxSendMsgSize; /* override max message size in send direction */
-};
-
-#define HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING (1 << 0) /* enable send bundle padding for this endpoint */
-
-/* service connection response information */
-struct htc_service_connect_resp {
- u8 *pMetaData; /* caller supplied buffer to optional meta-data */
- u8 BufferLength; /* length of caller supplied buffer */
- u8 ActualLength; /* actual length of meta data */
- HTC_ENDPOINT_ID Endpoint; /* endpoint to communicate over */
- unsigned int MaxMsgLength; /* max length of all messages over this endpoint */
- u8 ConnectRespCode; /* connect response code from target */
-};
-
-/* endpoint distribution structure */
-struct htc_endpoint_credit_dist {
- struct htc_endpoint_credit_dist *pNext;
- struct htc_endpoint_credit_dist *pPrev;
- HTC_SERVICE_ID ServiceID; /* Service ID (set by HTC) */
- HTC_ENDPOINT_ID Endpoint; /* endpoint for this distribution struct (set by HTC) */
- u32 DistFlags; /* distribution flags, distribution function can
- set default activity using SET_EP_ACTIVE() macro */
- int TxCreditsNorm; /* credits for normal operation, anything above this
- indicates the endpoint is over-subscribed, this field
- is only relevant to the credit distribution function */
- int TxCreditsMin; /* floor for credit distribution, this field is
- only relevant to the credit distribution function */
- int TxCreditsAssigned; /* number of credits assigned to this EP, this field
- is only relevant to the credit dist function */
- int TxCredits; /* current credits available, this field is used by
- HTC to determine whether a message can be sent or
- must be queued */
- int TxCreditsToDist; /* pending credits to distribute on this endpoint, this
- is set by HTC when credit reports arrive.
- The credit distribution functions sets this to zero
- when it distributes the credits */
- int TxCreditsSeek; /* this is the number of credits that the current pending TX
- packet needs to transmit. This is set by HTC when
- and endpoint needs credits in order to transmit */
- int TxCreditSize; /* size in bytes of each credit (set by HTC) */
- int TxCreditsPerMaxMsg; /* credits required for a maximum sized messages (set by HTC) */
- void *pHTCReserved; /* reserved for HTC use */
- int TxQueueDepth; /* current depth of TX queue , i.e. messages waiting for credits
- This field is valid only when HTC_CREDIT_DIST_ACTIVITY_CHANGE
- or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint
- that has non-zero credits to recover
- */
-};
-
-#define HTC_EP_ACTIVE ((u32) (1u << 31))
-
-/* macro to check if an endpoint has gone active, useful for credit
- * distributions */
-#define IS_EP_ACTIVE(epDist) ((epDist)->DistFlags & HTC_EP_ACTIVE)
-#define SET_EP_ACTIVE(epDist) (epDist)->DistFlags |= HTC_EP_ACTIVE
-
- /* credit distibution code that is passed into the distrbution function,
- * there are mandatory and optional codes that must be handled */
-typedef enum _HTC_CREDIT_DIST_REASON {
- HTC_CREDIT_DIST_SEND_COMPLETE = 0, /* credits available as a result of completed
- send operations (MANDATORY) resulting in credit reports */
- HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, /* a change in endpoint activity occurred (OPTIONAL) */
- HTC_CREDIT_DIST_SEEK_CREDITS, /* an endpoint needs to "seek" credits (OPTIONAL) */
- HTC_DUMP_CREDIT_STATE /* for debugging, dump any state information that is kept by
- the distribution function */
-} HTC_CREDIT_DIST_REASON;
-
-typedef void (*HTC_CREDIT_DIST_CALLBACK)(void *Context,
- struct htc_endpoint_credit_dist *pEPList,
- HTC_CREDIT_DIST_REASON Reason);
-
-typedef void (*HTC_CREDIT_INIT_CALLBACK)(void *Context,
- struct htc_endpoint_credit_dist *pEPList,
- int TotalCredits);
-
- /* endpoint statistics action */
-typedef enum _HTC_ENDPOINT_STAT_ACTION {
- HTC_EP_STAT_SAMPLE = 0, /* only read statistics */
- HTC_EP_STAT_SAMPLE_AND_CLEAR = 1, /* sample and immediately clear statistics */
- HTC_EP_STAT_CLEAR /* clear only */
-} HTC_ENDPOINT_STAT_ACTION;
-
- /* endpoint statistics */
-struct htc_endpoint_stats {
- u32 TxCreditLowIndications; /* number of times the host set the credit-low flag in a send message on
- this endpoint */
- u32 TxIssued; /* running count of total TX packets issued */
- u32 TxPacketsBundled; /* running count of TX packets that were issued in bundles */
- u32 TxBundles; /* running count of TX bundles that were issued */
- u32 TxDropped; /* tx packets that were dropped */
- u32 TxCreditRpts; /* running count of total credit reports received for this endpoint */
- u32 TxCreditRptsFromRx; /* credit reports received from this endpoint's RX packets */
- u32 TxCreditRptsFromOther; /* credit reports received from RX packets of other endpoints */
- u32 TxCreditRptsFromEp0; /* credit reports received from endpoint 0 RX packets */
- u32 TxCreditsFromRx; /* count of credits received via Rx packets on this endpoint */
- u32 TxCreditsFromOther; /* count of credits received via another endpoint */
- u32 TxCreditsFromEp0; /* count of credits received via another endpoint */
- u32 TxCreditsConsummed; /* count of consummed credits */
- u32 TxCreditsReturned; /* count of credits returned */
- u32 RxReceived; /* count of RX packets received */
- u32 RxLookAheads; /* count of lookahead records
- found in messages received on this endpoint */
- u32 RxPacketsBundled; /* count of recv packets received in a bundle */
- u32 RxBundleLookAheads; /* count of number of bundled lookaheads */
- u32 RxBundleIndFromHdr; /* count of the number of bundle indications from the HTC header */
- u32 RxAllocThreshHit; /* count of the number of times the recv allocation threshold was hit */
- u32 RxAllocThreshBytes; /* total number of bytes */
-};
-
-/* ------ Function Prototypes ------ */
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Create an instance of HTC over the underlying HIF device
- @function name: HTCCreate
- @input: HifDevice - hif device handle,
- pInfo - initialization information
- @output:
- @return: HTC_HANDLE on success, NULL on failure
- @notes:
- @example:
- @see also: HTCDestroy
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-HTC_HANDLE HTCCreate(void *HifDevice, struct htc_init_info *pInfo);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Get the underlying HIF device handle
- @function name: HTCGetHifDevice
- @input: HTCHandle - handle passed into the AddInstance callback
- @output:
- @return: opaque HIF device handle usable in HIF API calls.
- @notes:
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-void *HTCGetHifDevice(HTC_HANDLE HTCHandle);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Set credit distribution parameters
- @function name: HTCSetCreditDistribution
- @input: HTCHandle - HTC handle
- pCreditDistCont - caller supplied context to pass into distribution functions
- CreditDistFunc - Distribution function callback
- CreditDistInit - Credit Distribution initialization callback
- ServicePriorityOrder - Array containing list of service IDs, lowest index is highest
- priority
- ListLength - number of elements in ServicePriorityOrder
- @output:
- @return:
- @notes: The user can set a custom credit distribution function to handle special requirements
- for each endpoint. A default credit distribution routine can be used by setting
- CreditInitFunc to NULL. The default credit distribution is only provided for simple
- "fair" credit distribution without regard to any prioritization.
-
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-void HTCSetCreditDistribution(HTC_HANDLE HTCHandle,
- void *pCreditDistContext,
- HTC_CREDIT_DIST_CALLBACK CreditDistFunc,
- HTC_CREDIT_INIT_CALLBACK CreditInitFunc,
- HTC_SERVICE_ID ServicePriorityOrder[],
- int ListLength);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Wait for the target to indicate the HTC layer is ready
- @function name: HTCWaitTarget
- @input: HTCHandle - HTC handle
- @output:
- @return:
- @notes: This API blocks until the target responds with an HTC ready message.
- The caller should not connect services until the target has indicated it is
- ready.
- @example:
- @see also: HTCConnectService
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HTCWaitTarget(HTC_HANDLE HTCHandle);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Start target service communications
- @function name: HTCStart
- @input: HTCHandle - HTC handle
- @output:
- @return:
- @notes: This API indicates to the target that the service connection phase is complete
- and the target can freely start all connected services. This API should only be
- called AFTER all service connections have been made. TCStart will issue a
- SETUP_COMPLETE message to the target to indicate that all service connections
- have been made and the target can start communicating over the endpoints.
- @example:
- @see also: HTCConnectService
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HTCStart(HTC_HANDLE HTCHandle);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Add receive packet to HTC
- @function name: HTCAddReceivePkt
- @input: HTCHandle - HTC handle
- pPacket - HTC receive packet to add
- @output:
- @return: 0 on success
- @notes: user must supply HTC packets for capturing incomming HTC frames. The caller
- must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
- macro.
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Connect to an HTC service
- @function name: HTCConnectService
- @input: HTCHandle - HTC handle
- pReq - connection details
- @output: pResp - connection response
- @return:
- @notes: Service connections must be performed before HTCStart. User provides callback handlers
- for various endpoint events.
- @example:
- @see also: HTCStart
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HTCConnectService(HTC_HANDLE HTCHandle,
- struct htc_service_connect_req *pReq,
- struct htc_service_connect_resp *pResp);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Send an HTC packet
- @function name: HTCSendPkt
- @input: HTCHandle - HTC handle
- pPacket - packet to send
- @output:
- @return: 0
- @notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() macro.
- This interface is fully asynchronous. On error, HTC SendPkt will
- call the registered Endpoint callback to cleanup the packet.
- @example:
- @see also: HTCFlushEndpoint
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Stop HTC service communications
- @function name: HTCStop
- @input: HTCHandle - HTC handle
- @output:
- @return:
- @notes: HTC communications is halted. All receive and pending TX packets will
- be flushed.
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-void HTCStop(HTC_HANDLE HTCHandle);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Destroy HTC service
- @function name: HTCDestroy
- @input: HTCHandle
- @output:
- @return:
- @notes: This cleans up all resources allocated by HTCCreate().
- @example:
- @see also: HTCCreate
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-void HTCDestroy(HTC_HANDLE HTCHandle);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Flush pending TX packets
- @function name: HTCFlushEndpoint
- @input: HTCHandle - HTC handle
- Endpoint - Endpoint to flush
- Tag - flush tag
- @output:
- @return:
- @notes: The Tag parameter is used to selectively flush packets with matching tags.
- The value of 0 forces all packets to be flush regardless of tag.
- @example:
- @see also: HTCSendPkt
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Dump credit distribution state
- @function name: HTCDumpCreditStates
- @input: HTCHandle - HTC handle
- @output:
- @return:
- @notes: This dumps all credit distribution information to the debugger
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-void HTCDumpCreditStates(HTC_HANDLE HTCHandle);
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Indicate a traffic activity change on an endpoint
- @function name: HTCIndicateActivityChange
- @input: HTCHandle - HTC handle
- Endpoint - endpoint in which activity has changed
- Active - true if active, false if it has become inactive
- @output:
- @return:
- @notes: This triggers the registered credit distribution function to
- re-adjust credits for active/inactive endpoints.
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
- HTC_ENDPOINT_ID Endpoint,
- bool Active);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Get endpoint statistics
- @function name: HTCGetEndpointStatistics
- @input: HTCHandle - HTC handle
- Endpoint - Endpoint identifier
- Action - action to take with statistics
- @output:
- pStats - statistics that were sampled (can be NULL if Action is HTC_EP_STAT_CLEAR)
-
- @return: true if statistics profiling is enabled, otherwise false.
-
- @notes: Statistics is a compile-time option and this function may return false
- if HTC is not compiled with profiling.
-
- The caller can specify the statistic "action" to take when sampling
- the statistics. This includes:
-
- HTC_EP_STAT_SAMPLE: The pStats structure is filled with the current values.
- HTC_EP_STAT_SAMPLE_AND_CLEAR: The structure is filled and the current statistics
- are cleared.
- HTC_EP_STAT_CLEA : the statistics are cleared, the called can pass a NULL value for
- pStats
-
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-bool HTCGetEndpointStatistics(HTC_HANDLE HTCHandle,
- HTC_ENDPOINT_ID Endpoint,
- HTC_ENDPOINT_STAT_ACTION Action,
- struct htc_endpoint_stats *pStats);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Unblock HTC message reception
- @function name: HTCUnblockRecv
- @input: HTCHandle - HTC handle
- @output:
- @return:
- @notes:
- HTC will block the receiver if the EpRecvAlloc callback fails to provide a packet.
- The caller can use this API to indicate to HTC when resources (buffers) are available
- such that the receiver can be unblocked and HTC may re-attempt fetching the pending message.
-
- This API is not required if the user uses the EpRecvRefill callback or uses the HTCAddReceivePacket()
- API to recycle or provide receive packets to HTC.
-
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-void HTCUnblockRecv(HTC_HANDLE HTCHandle);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: send a series of HTC packets
- @function name: HTCSendPktsMultiple
- @input: HTCHandle - HTC handle
- pPktQueue - local queue holding packets to send
- @output:
- @return: 0
- @notes: Caller must initialize each packet using SET_HTC_PACKET_INFO_TX() macro.
- The queue must only contain packets directed at the same endpoint.
- Caller supplies a pointer to an struct htc_packet_queue structure holding the TX packets in FIFO order.
- This API will remove the packets from the pkt queue and place them into the HTC Tx Queue
- and bundle messages where possible.
- The caller may allocate the pkt queue on the stack to hold the packets.
- This interface is fully asynchronous. On error, HTCSendPkts will
- call the registered Endpoint callback to cleanup the packet.
- @example:
- @see also: HTCFlushEndpoint
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HTCSendPktsMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Add multiple receive packets to HTC
- @function name: HTCAddReceivePktMultiple
- @input: HTCHandle - HTC handle
- pPktQueue - HTC receive packet queue holding packets to add
- @output:
- @return: 0 on success
- @notes: user must supply HTC packets for capturing incomming HTC frames. The caller
- must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
- macro. The queue must only contain recv packets for the same endpoint.
- Caller supplies a pointer to an struct htc_packet_queue structure holding the recv packet.
- This API will remove the packets from the pkt queue and place them into internal
- recv packet list.
- The caller may allocate the pkt queue on the stack to hold the packets.
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue);
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Check if an endpoint is marked active
- @function name: HTCIsEndpointActive
- @input: HTCHandle - HTC handle
- Endpoint - endpoint to check for active state
- @output:
- @return: returns true if Endpoint is Active
- @notes:
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-bool HTCIsEndpointActive(HTC_HANDLE HTCHandle,
- HTC_ENDPOINT_ID Endpoint);
-
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- @desc: Get the number of recv buffers currently queued into an HTC endpoint
- @function name: HTCGetNumRecvBuffers
- @input: HTCHandle - HTC handle
- Endpoint - endpoint to check
- @output:
- @return: returns number of buffers in queue
- @notes:
- @example:
- @see also:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle,
- HTC_ENDPOINT_ID Endpoint);
-
-/* internally used functions for testing... */
-void HTCEnableRecv(HTC_HANDLE HTCHandle);
-void HTCDisableRecv(HTC_HANDLE HTCHandle);
-int HTCWaitForPendingRecv(HTC_HANDLE HTCHandle,
- u32 TimeoutInMs,
- bool *pbIsRecvPending);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HTC_API_H_ */
diff --git a/drivers/staging/ath6kl/include/htc_packet.h b/drivers/staging/ath6kl/include/htc_packet.h
deleted file mode 100644
index ba65c34ebc9c..000000000000
--- a/drivers/staging/ath6kl/include/htc_packet.h
+++ /dev/null
@@ -1,227 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc_packet.h" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef HTC_PACKET_H_
-#define HTC_PACKET_H_
-
-
-#include "dl_list.h"
-
-/* ------ Endpoint IDS ------ */
-typedef enum
-{
- ENDPOINT_UNUSED = -1,
- ENDPOINT_0 = 0,
- ENDPOINT_1 = 1,
- ENDPOINT_2 = 2,
- ENDPOINT_3,
- ENDPOINT_4,
- ENDPOINT_5,
- ENDPOINT_6,
- ENDPOINT_7,
- ENDPOINT_8,
- ENDPOINT_MAX,
-} HTC_ENDPOINT_ID;
-
-struct htc_packet;
-
-typedef void (* HTC_PACKET_COMPLETION)(void *,struct htc_packet *);
-
-typedef u16 HTC_TX_TAG;
-
-struct htc_tx_packet_info {
- HTC_TX_TAG Tag; /* tag used to selective flush packets */
- int CreditsUsed; /* number of credits used for this TX packet (HTC internal) */
- u8 SendFlags; /* send flags (HTC internal) */
- int SeqNo; /* internal seq no for debugging (HTC internal) */
-};
-
-#define HTC_TX_PACKET_TAG_ALL 0 /* a tag of zero is reserved and used to flush ALL packets */
-#define HTC_TX_PACKET_TAG_INTERNAL 1 /* internal tags start here */
-#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) /* user-defined tags start here */
-
-struct htc_rx_packet_info {
- u32 ExpectedHdr; /* HTC internal use */
- u32 HTCRxFlags; /* HTC internal use */
- u32 IndicationFlags; /* indication flags set on each RX packet indication */
-};
-
-#define HTC_RX_FLAGS_INDICATE_MORE_PKTS (1 << 0) /* more packets on this endpoint are being fetched */
-
-/* wrapper around endpoint-specific packets */
-struct htc_packet {
- struct dl_list ListLink; /* double link */
- void *pPktContext; /* caller's per packet specific context */
-
- u8 *pBufferStart; /* the true buffer start , the caller can
- store the real buffer start here. In
- receive callbacks, the HTC layer sets pBuffer
- to the start of the payload past the header. This
- field allows the caller to reset pBuffer when it
- recycles receive packets back to HTC */
- /*
- * Pointer to the start of the buffer. In the transmit
- * direction this points to the start of the payload. In the
- * receive direction, however, the buffer when queued up
- * points to the start of the HTC header but when returned
- * to the caller points to the start of the payload
- */
- u8 *pBuffer; /* payload start (RX/TX) */
- u32 BufferLength; /* length of buffer */
- u32 ActualLength; /* actual length of payload */
- HTC_ENDPOINT_ID Endpoint; /* endpoint that this packet was sent/recv'd from */
- int Status; /* completion status */
- union {
- struct htc_tx_packet_info AsTx; /* Tx Packet specific info */
- struct htc_rx_packet_info AsRx; /* Rx Packet specific info */
- } PktInfo;
-
- /* the following fields are for internal HTC use */
- HTC_PACKET_COMPLETION Completion; /* completion */
- void *pContext; /* HTC private completion context */
-};
-
-
-
-#define COMPLETE_HTC_PACKET(p,status) \
-{ \
- (p)->Status = (status); \
- (p)->Completion((p)->pContext,(p)); \
-}
-
-#define INIT_HTC_PACKET_INFO(p,b,len) \
-{ \
- (p)->pBufferStart = (b); \
- (p)->BufferLength = (len); \
-}
-
-/* macro to set an initial RX packet for refilling HTC */
-#define SET_HTC_PACKET_INFO_RX_REFILL(p,c,b,len,ep) \
-{ \
- (p)->pPktContext = (c); \
- (p)->pBuffer = (b); \
- (p)->pBufferStart = (b); \
- (p)->BufferLength = (len); \
- (p)->Endpoint = (ep); \
-}
-
-/* fast macro to recycle an RX packet that will be re-queued to HTC */
-#define HTC_PACKET_RESET_RX(p) \
- { (p)->pBuffer = (p)->pBufferStart; (p)->ActualLength = 0; }
-
-/* macro to set packet parameters for TX */
-#define SET_HTC_PACKET_INFO_TX(p,c,b,len,ep,tag) \
-{ \
- (p)->pPktContext = (c); \
- (p)->pBuffer = (b); \
- (p)->ActualLength = (len); \
- (p)->Endpoint = (ep); \
- (p)->PktInfo.AsTx.Tag = (tag); \
-}
-
-/* HTC Packet Queueing Macros */
-struct htc_packet_queue {
- struct dl_list QueueHead;
- int Depth;
-};
-
-/* initialize queue */
-#define INIT_HTC_PACKET_QUEUE(pQ) \
-{ \
- DL_LIST_INIT(&(pQ)->QueueHead); \
- (pQ)->Depth = 0; \
-}
-
-/* enqueue HTC packet to the tail of the queue */
-#define HTC_PACKET_ENQUEUE(pQ,p) \
-{ DL_ListInsertTail(&(pQ)->QueueHead,&(p)->ListLink); \
- (pQ)->Depth++; \
-}
-
-/* enqueue HTC packet to the tail of the queue */
-#define HTC_PACKET_ENQUEUE_TO_HEAD(pQ,p) \
-{ DL_ListInsertHead(&(pQ)->QueueHead,&(p)->ListLink); \
- (pQ)->Depth++; \
-}
-/* test if a queue is empty */
-#define HTC_QUEUE_EMPTY(pQ) ((pQ)->Depth == 0)
-/* get packet at head without removing it */
-static INLINE struct htc_packet *HTC_GET_PKT_AT_HEAD(struct htc_packet_queue *queue) {
- if (queue->Depth == 0) {
- return NULL;
- }
- return A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(&queue->QueueHead)),struct htc_packet,ListLink);
-}
-/* remove a packet from a queue, where-ever it is in the queue */
-#define HTC_PACKET_REMOVE(pQ,p) \
-{ \
- DL_ListRemove(&(p)->ListLink); \
- (pQ)->Depth--; \
-}
-
-/* dequeue an HTC packet from the head of the queue */
-static INLINE struct htc_packet *HTC_PACKET_DEQUEUE(struct htc_packet_queue *queue) {
- struct dl_list *pItem = DL_ListRemoveItemFromHead(&queue->QueueHead);
- if (pItem != NULL) {
- queue->Depth--;
- return A_CONTAINING_STRUCT(pItem, struct htc_packet, ListLink);
- }
- return NULL;
-}
-
-/* dequeue an HTC packet from the tail of the queue */
-static INLINE struct htc_packet *HTC_PACKET_DEQUEUE_TAIL(struct htc_packet_queue *queue) {
- struct dl_list *pItem = DL_ListRemoveItemFromTail(&queue->QueueHead);
- if (pItem != NULL) {
- queue->Depth--;
- return A_CONTAINING_STRUCT(pItem, struct htc_packet, ListLink);
- }
- return NULL;
-}
-
-#define HTC_PACKET_QUEUE_DEPTH(pQ) (pQ)->Depth
-
-
-#define HTC_GET_ENDPOINT_FROM_PKT(p) (p)->Endpoint
-#define HTC_GET_TAG_FROM_PKT(p) (p)->PktInfo.AsTx.Tag
-
- /* transfer the packets from one queue to the tail of another queue */
-#define HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(pQDest,pQSrc) \
-{ \
- DL_ListTransferItemsToTail(&(pQDest)->QueueHead,&(pQSrc)->QueueHead); \
- (pQDest)->Depth += (pQSrc)->Depth; \
- (pQSrc)->Depth = 0; \
-}
-
- /* fast version to init and add a single packet to a queue */
-#define INIT_HTC_PACKET_QUEUE_AND_ADD(pQ,pP) \
-{ \
- DL_LIST_INIT_AND_ADD(&(pQ)->QueueHead,&(pP)->ListLink) \
- (pQ)->Depth = 1; \
-}
-
-#define HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQ, pPTemp) \
- ITERATE_OVER_LIST_ALLOW_REMOVE(&(pQ)->QueueHead,(pPTemp), struct htc_packet, ListLink)
-
-#define HTC_PACKET_QUEUE_ITERATE_END ITERATE_END
-
-#endif /*HTC_PACKET_H_*/
diff --git a/drivers/staging/ath6kl/include/wlan_api.h b/drivers/staging/ath6kl/include/wlan_api.h
deleted file mode 100644
index 9eea5875dd38..000000000000
--- a/drivers/staging/ath6kl/include/wlan_api.h
+++ /dev/null
@@ -1,128 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains the API for the host wlan module
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _HOST_WLAN_API_H_
-#define _HOST_WLAN_API_H_
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <a_osapi.h>
-
-struct ieee80211_node_table;
-struct ieee80211_frame;
-
-struct ieee80211_common_ie {
- u16 ie_chan;
- u8 *ie_tstamp;
- u8 *ie_ssid;
- u8 *ie_rates;
- u8 *ie_xrates;
- u8 *ie_country;
- u8 *ie_wpa;
- u8 *ie_rsn;
- u8 *ie_wmm;
- u8 *ie_ath;
- u16 ie_capInfo;
- u16 ie_beaconInt;
- u8 *ie_tim;
- u8 *ie_chswitch;
- u8 ie_erp;
- u8 *ie_wsc;
- u8 *ie_htcap;
- u8 *ie_htop;
-#ifdef WAPI_ENABLE
- u8 *ie_wapi;
-#endif
-};
-
-typedef struct bss {
- u8 ni_macaddr[6];
- u8 ni_snr;
- s16 ni_rssi;
- struct bss *ni_list_next;
- struct bss *ni_list_prev;
- struct bss *ni_hash_next;
- struct bss *ni_hash_prev;
- struct ieee80211_common_ie ni_cie;
- u8 *ni_buf;
- u16 ni_framelen;
- struct ieee80211_node_table *ni_table;
- u32 ni_refcnt;
- int ni_scangen;
-
- u32 ni_tstamp;
- u32 ni_actcnt;
-#ifdef OS_ROAM_MANAGEMENT
- u32 ni_si_gen;
-#endif
-} bss_t;
-
-typedef void wlan_node_iter_func(void *arg, bss_t *);
-
-bss_t *wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size);
-void wlan_node_free(bss_t *ni);
-void wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
- const u8 *macaddr);
-bss_t *wlan_find_node(struct ieee80211_node_table *nt, const u8 *macaddr);
-void wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni);
-void wlan_free_allnodes(struct ieee80211_node_table *nt);
-void wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
- void *arg);
-
-void wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt);
-void wlan_node_table_reset(struct ieee80211_node_table *nt);
-void wlan_node_table_cleanup(struct ieee80211_node_table *nt);
-
-int wlan_parse_beacon(u8 *buf, int framelen,
- struct ieee80211_common_ie *cie);
-
-u16 wlan_ieee2freq(int chan);
-u32 wlan_freq2ieee(u16 freq);
-
-void wlan_set_nodeage(struct ieee80211_node_table *nt, u32 nodeAge);
-
-void
-wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt);
-
-bss_t *
-wlan_find_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
- u32 ssidLength, bool bIsWPA2, bool bMatchSSID);
-
-void
-wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni);
-
-bss_t *wlan_node_remove(struct ieee80211_node_table *nt, u8 *bssid);
-
-bss_t *
-wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
- u32 ssidLength, u32 dot11AuthMode, u32 authMode,
- u32 pairwiseCryptoType, u32 grpwiseCryptoTyp);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HOST_WLAN_API_H_ */
diff --git a/drivers/staging/ath6kl/include/wmi_api.h b/drivers/staging/ath6kl/include/wmi_api.h
deleted file mode 100644
index c8583e0c4a96..000000000000
--- a/drivers/staging/ath6kl/include/wmi_api.h
+++ /dev/null
@@ -1,441 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="wmi_api.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains the definitions for the Wireless Module Interface (WMI).
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _WMI_API_H_
-#define _WMI_API_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
- /* WMI converts a dix frame with an ethernet payload (up to 1500 bytes)
- * to an 802.3 frame (adds SNAP header) and adds on a WMI data header */
-#define WMI_MAX_TX_DATA_FRAME_LENGTH (1500 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR))
-
- /* A normal WMI data frame */
-#define WMI_MAX_NORMAL_RX_DATA_FRAME_LENGTH (1500 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR))
-
- /* An AMSDU frame */ /* The MAX AMSDU length of AR6003 is 3839 */
-#define WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH (3840 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR))
-
-/*
- * IP QoS Field definitions according to 802.1p
- */
-#define BEST_EFFORT_PRI 0
-#define BACKGROUND_PRI 1
-#define EXCELLENT_EFFORT_PRI 3
-#define CONTROLLED_LOAD_PRI 4
-#define VIDEO_PRI 5
-#define VOICE_PRI 6
-#define NETWORK_CONTROL_PRI 7
-#define MAX_NUM_PRI 8
-
-#define UNDEFINED_PRI (0xff)
-
-#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000 /* 5 seconds */
-
-#define A_ROUND_UP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
-
-typedef enum {
- ATHEROS_COMPLIANCE = 0x1,
-}TSPEC_PARAM_COMPLIANCE;
-
-struct wmi_t;
-
-void *wmi_init(void *devt);
-
-void wmi_qos_state_init(struct wmi_t *wmip);
-void wmi_shutdown(struct wmi_t *wmip);
-HTC_ENDPOINT_ID wmi_get_control_ep(struct wmi_t * wmip);
-void wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid);
-u16 wmi_get_mapped_qos_queue(struct wmi_t *, u8 );
-int wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf);
-int wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData, WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS);
-int wmi_dot3_2_dix(void *osbuf);
-
-int wmi_dot11_hdr_remove (struct wmi_t *wmip, void *osbuf);
-int wmi_dot11_hdr_add(struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode);
-
-int wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf);
-int wmi_syncpoint(struct wmi_t *wmip);
-int wmi_syncpoint_reset(struct wmi_t *wmip);
-u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled);
-
-u8 wmi_determine_userPriority (u8 *pkt, u32 layer2Pri);
-
-int wmi_control_rx(struct wmi_t *wmip, void *osbuf);
-void wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg);
-void wmi_free_allnodes(struct wmi_t *wmip);
-bss_t *wmi_find_node(struct wmi_t *wmip, const u8 *macaddr);
-void wmi_free_node(struct wmi_t *wmip, const u8 *macaddr);
-
-
-typedef enum {
- NO_SYNC_WMIFLAG = 0,
- SYNC_BEFORE_WMIFLAG, /* transmit all queued data before cmd */
- SYNC_AFTER_WMIFLAG, /* any new data waits until cmd execs */
- SYNC_BOTH_WMIFLAG,
- END_WMIFLAG /* end marker */
-} WMI_SYNC_FLAG;
-
-int wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
- WMI_SYNC_FLAG flag);
-
-int wmi_connect_cmd(struct wmi_t *wmip,
- NETWORK_TYPE netType,
- DOT11_AUTH_MODE dot11AuthMode,
- AUTH_MODE authMode,
- CRYPTO_TYPE pairwiseCrypto,
- u8 pairwiseCryptoLen,
- CRYPTO_TYPE groupCrypto,
- u8 groupCryptoLen,
- int ssidLength,
- u8 *ssid,
- u8 *bssid,
- u16 channel,
- u32 ctrl_flags);
-
-int wmi_reconnect_cmd(struct wmi_t *wmip,
- u8 *bssid,
- u16 channel);
-int wmi_disconnect_cmd(struct wmi_t *wmip);
-int wmi_getrev_cmd(struct wmi_t *wmip);
-int wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
- u32 forceFgScan, u32 isLegacy,
- u32 homeDwellTime, u32 forceScanInterval,
- s8 numChan, u16 *channelList);
-int wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
- u16 fg_end_sec, u16 bg_sec,
- u16 minact_chdw_msec,
- u16 maxact_chdw_msec, u16 pas_chdw_msec,
- u8 shScanRatio, u8 scanCtrlFlags,
- u32 max_dfsch_act_time,
- u16 maxact_scan_per_ssid);
-int wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask);
-int wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
- u8 ssidLength, u8 *ssid);
-int wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons);
-int wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmisstime, u16 bmissbeacons);
-int wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
- u8 ieLen, u8 *ieInfo);
-int wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode);
-int wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
- u16 atim_windows, u16 timeout_value);
-int wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
- u32 ps_period, u8 sleep_period);
-int wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
- u16 psPollNum, u16 dtimPolicy,
- u16 wakup_tx_policy, u16 num_tx_to_wakeup,
- u16 ps_fail_event_policy);
-int wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout);
-int wmi_sync_cmd(struct wmi_t *wmip, u8 syncNumber);
-int wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *pstream);
-int wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 streamID);
-int wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask);
-int wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate);
-int wmi_get_bitrate_cmd(struct wmi_t *wmip);
-s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx);
-int wmi_get_regDomain_cmd(struct wmi_t *wmip);
-int wmi_get_channelList_cmd(struct wmi_t *wmip);
-int wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
- WMI_PHY_MODE mode, s8 numChan,
- u16 *channelList);
-
-int wmi_set_snr_threshold_params(struct wmi_t *wmip,
- WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
-int wmi_set_rssi_threshold_params(struct wmi_t *wmip,
- WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
-int wmi_clr_rssi_snr(struct wmi_t *wmip);
-int wmi_set_lq_threshold_params(struct wmi_t *wmip,
- WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd);
-int wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold);
-int wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy);
-
-int wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 bitmask);
-
-int wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie,
- u32 source);
-
-int wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
- u16 tsr, bool rep, u16 size,
- u32 valid);
-
-int wmi_get_stats_cmd(struct wmi_t *wmip);
-
-int wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex,
- CRYPTO_TYPE keyType, u8 keyUsage,
- u8 keyLength,u8 *keyRSC,
- u8 *keyMaterial, u8 key_op_ctrl, u8 *mac,
- WMI_SYNC_FLAG sync_flag);
-int wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk);
-int wmi_delete_krk_cmd(struct wmi_t *wmip);
-int wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex);
-int wmi_set_akmp_params_cmd(struct wmi_t *wmip,
- WMI_SET_AKMP_PARAMS_CMD *akmpParams);
-int wmi_get_pmkid_list_cmd(struct wmi_t *wmip);
-int wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
- WMI_SET_PMKID_LIST_CMD *pmkInfo);
-int wmi_abort_scan_cmd(struct wmi_t *wmip);
-int wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM);
-int wmi_get_txPwr_cmd(struct wmi_t *wmip);
-int wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid);
-int wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex);
-int wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en);
-int wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
- bool set);
-int wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop,
- u8 eCWmin, u8 eCWmax,
- u8 aifsn);
-int wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
- u8 trafficClass, u8 maxRetries,
- u8 enableNotify);
-
-void wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid);
-
-int wmi_get_roam_tbl_cmd(struct wmi_t *wmip);
-int wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType);
-int wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
- u8 size);
-int wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
- WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
- u8 size);
-
-int wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode);
-int wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
- u8 frmType,
- u8 *dstMacAddr,
- u8 *bssid,
- u16 optIEDataLen,
- u8 *optIEData);
-
-int wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl);
-int wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize);
-int wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSpLen);
-u8 convert_userPriority_to_trafficClass(u8 userPriority);
-u8 wmi_get_power_mode_cmd(struct wmi_t *wmip);
-int wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance);
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-int wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len);
-#endif
-
-int wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status);
-int wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd);
-
-int wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd);
-
-int wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
- WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd);
-
-int wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
- WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *cmd);
-
-int wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
- WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd);
-
-int wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
- WMI_SET_BTCOEX_A2DP_CONFIG_CMD* cmd);
-
-
-int wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD* cmd);
-
-int wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd);
-
-int wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
- WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd);
-
-int wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd);
-
-int wmi_get_btcoex_stats_cmd(struct wmi_t * wmip);
-
-int wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold);
-
-/*
- * This function is used to configure the fix rates mask to the target.
- */
-int wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask);
-int wmi_get_ratemask_cmd(struct wmi_t *wmip);
-
-int wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode);
-
-int wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode);
-
-int wmi_set_qos_supp_cmd(struct wmi_t *wmip,u8 status);
-int wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status);
-int wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG txEnable);
-int wmi_set_country(struct wmi_t *wmip, u8 *countryCode);
-
-int wmi_get_keepalive_configured(struct wmi_t *wmip);
-u8 wmi_get_keepalive_cmd(struct wmi_t *wmip);
-int wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval);
-
-int wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType,
- u8 ieLen,u8 *ieInfo);
-
-int wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen);
-
-s32 wmi_get_rate(s8 rateindex);
-
-int wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *cmd);
-
-/*Wake on Wireless WMI commands*/
-int wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, WMI_SET_HOST_SLEEP_MODE_CMD *cmd);
-int wmi_set_wow_mode_cmd(struct wmi_t *wmip, WMI_SET_WOW_MODE_CMD *cmd);
-int wmi_get_wow_list_cmd(struct wmi_t *wmip, WMI_GET_WOW_LIST_CMD *cmd);
-int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
- WMI_ADD_WOW_PATTERN_CMD *cmd, u8 *pattern, u8 *mask, u8 pattern_size);
-int wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
- WMI_DEL_WOW_PATTERN_CMD *cmd);
-int wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status);
-
-int
-wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer);
-
-int
-wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4);
-
-int
-wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4);
-
-int
-wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable);
-
-bss_t *
-wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
- u32 ssidLength, bool bIsWPA2, bool bMatchSSID);
-
-
-void
-wmi_node_return (struct wmi_t *wmip, bss_t *bss);
-
-void
-wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge);
-
-#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-int wmi_prof_cfg_cmd(struct wmi_t *wmip, u32 period, u32 nbins);
-int wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr);
-int wmi_prof_start_cmd(struct wmi_t *wmip);
-int wmi_prof_stop_cmd(struct wmi_t *wmip);
-int wmi_prof_count_get_cmd(struct wmi_t *wmip);
-#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
-#ifdef OS_ROAM_MANAGEMENT
-void wmi_scan_indication (struct wmi_t *wmip);
-#endif
-
-int
-wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd);
-
-bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id);
-int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss);
-
-
-/*
- * AP mode
- */
-int
-wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p);
-
-int
-wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid);
-
-int
-wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta);
-
-int
-wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy);
-
-int
-wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *a);
-
-u8 acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl);
-
-int
-wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason);
-
-int
-wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag);
-
-int
-wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period);
-
-int
-wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell);
-
-int
-wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim);
-
-int
-wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset);
-
-int
-wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd);
-
-int
-wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width);
-
-int
-wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz);
-
-int
-wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray);
-
-int
-wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid);
-
-int
-wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink);
-
-int
-wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask);
-
-int
-wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion, bool rxDot11Hdr, bool defragOnHost);
-
-int
-wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode);
-
-int
-wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence);
-
-int
-wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk);
-
-int
-wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd);
-
-u16 wmi_ieee2freq (int chan);
-
-u32 wmi_freq2ieee (u16 freq);
-
-bss_t *
-wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
- u32 ssidLength,
- u32 dot11AuthMode, u32 authMode,
- u32 pairwiseCryptoType, u32 grpwiseCryptoTyp);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _WMI_API_H_ */
diff --git a/drivers/staging/ath6kl/miscdrv/ar3kconfig.c b/drivers/staging/ath6kl/miscdrv/ar3kconfig.c
deleted file mode 100644
index e0ea2183019d..000000000000
--- a/drivers/staging/ath6kl/miscdrv/ar3kconfig.c
+++ /dev/null
@@ -1,565 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// AR3K configuration implementation
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_osapi.h"
-#define ATH_MODULE_NAME misc
-#include "a_debug.h"
-#include "common_drv.h"
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-#include "export_hci_transport.h"
-#else
-#include "hci_transport_api.h"
-#endif
-#include "ar3kconfig.h"
-#include "tlpm.h"
-
-#define BAUD_CHANGE_COMMAND_STATUS_OFFSET 5
-#define HCI_EVENT_RESP_TIMEOUTMS 3000
-#define HCI_CMD_OPCODE_BYTE_LOW_OFFSET 0
-#define HCI_CMD_OPCODE_BYTE_HI_OFFSET 1
-#define HCI_EVENT_OPCODE_BYTE_LOW 3
-#define HCI_EVENT_OPCODE_BYTE_HI 4
-#define HCI_CMD_COMPLETE_EVENT_CODE 0xE
-#define HCI_MAX_EVT_RECV_LENGTH 257
-#define EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET 5
-
-int AthPSInitialize(struct ar3k_config_info *hdev);
-
-static int SendHCICommand(struct ar3k_config_info *pConfig,
- u8 *pBuffer,
- int Length)
-{
- struct htc_packet *pPacket = NULL;
- int status = 0;
-
- do {
-
- pPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet));
- if (NULL == pPacket) {
- status = A_NO_MEMORY;
- break;
- }
-
- A_MEMZERO(pPacket,sizeof(struct htc_packet));
- SET_HTC_PACKET_INFO_TX(pPacket,
- NULL,
- pBuffer,
- Length,
- HCI_COMMAND_TYPE,
- AR6K_CONTROL_PKT_TAG);
-
- /* issue synchronously */
- status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,true);
-
- } while (false);
-
- if (pPacket != NULL) {
- kfree(pPacket);
- }
-
- return status;
-}
-
-static int RecvHCIEvent(struct ar3k_config_info *pConfig,
- u8 *pBuffer,
- int *pLength)
-{
- int status = 0;
- struct htc_packet *pRecvPacket = NULL;
-
- do {
-
- pRecvPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet));
- if (NULL == pRecvPacket) {
- status = A_NO_MEMORY;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n"));
- break;
- }
-
- A_MEMZERO(pRecvPacket,sizeof(struct htc_packet));
-
- SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE);
-
- status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev,
- pRecvPacket,
- HCI_EVENT_RESP_TIMEOUTMS);
- if (status) {
- break;
- }
-
- *pLength = pRecvPacket->ActualLength;
-
- } while (false);
-
- if (pRecvPacket != NULL) {
- kfree(pRecvPacket);
- }
-
- return status;
-}
-
-int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
- u8 *pHCICommand,
- int CmdLength,
- u8 **ppEventBuffer,
- u8 **ppBufferToFree)
-{
- int status = 0;
- u8 *pBuffer = NULL;
- u8 *pTemp;
- int length;
- bool commandComplete = false;
- u8 opCodeBytes[2];
-
- do {
-
- length = max(HCI_MAX_EVT_RECV_LENGTH,CmdLength);
- length += pConfig->pHCIProps->HeadRoom + pConfig->pHCIProps->TailRoom;
- length += pConfig->pHCIProps->IOBlockPad;
-
- pBuffer = (u8 *)A_MALLOC(length);
- if (NULL == pBuffer) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to allocate bt buffer \n"));
- status = A_NO_MEMORY;
- break;
- }
-
- /* get the opcodes to check the command complete event */
- opCodeBytes[0] = pHCICommand[HCI_CMD_OPCODE_BYTE_LOW_OFFSET];
- opCodeBytes[1] = pHCICommand[HCI_CMD_OPCODE_BYTE_HI_OFFSET];
-
- /* copy HCI command */
- memcpy(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength);
- /* send command */
- status = SendHCICommand(pConfig,
- pBuffer + pConfig->pHCIProps->HeadRoom,
- CmdLength);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to send HCI Command (%d) \n", status));
- AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
- break;
- }
-
- /* reuse buffer to capture command complete event */
- A_MEMZERO(pBuffer,length);
- status = RecvHCIEvent(pConfig,pBuffer,&length);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI event recv failed \n"));
- AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
- break;
- }
-
- pTemp = pBuffer + pConfig->pHCIProps->HeadRoom;
- if (pTemp[0] == HCI_CMD_COMPLETE_EVENT_CODE) {
- if ((pTemp[HCI_EVENT_OPCODE_BYTE_LOW] == opCodeBytes[0]) &&
- (pTemp[HCI_EVENT_OPCODE_BYTE_HI] == opCodeBytes[1])) {
- commandComplete = true;
- }
- }
-
- if (!commandComplete) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Unexpected HCI event : %d \n",pTemp[0]));
- AR_DEBUG_PRINTBUF(pTemp,pTemp[1],"Unexpected HCI event");
- status = A_ECOMM;
- break;
- }
-
- if (ppEventBuffer != NULL) {
- /* caller wants to look at the event */
- *ppEventBuffer = pTemp;
- if (ppBufferToFree == NULL) {
- status = A_EINVAL;
- break;
- }
- /* caller must free the buffer */
- *ppBufferToFree = pBuffer;
- pBuffer = NULL;
- }
-
- } while (false);
-
- if (pBuffer != NULL) {
- kfree(pBuffer);
- }
-
- return status;
-}
-
-static int AR3KConfigureHCIBaud(struct ar3k_config_info *pConfig)
-{
- int status = 0;
- u8 hciBaudChangeCommand[] = {0x0c,0xfc,0x2,0,0};
- u16 baudVal;
- u8 *pEvent = NULL;
- u8 *pBufferToFree = NULL;
-
- do {
-
- if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) {
- baudVal = (u16)(pConfig->AR3KBaudRate / 100);
- hciBaudChangeCommand[3] = (u8)baudVal;
- hciBaudChangeCommand[4] = (u8)(baudVal >> 8);
-
- status = SendHCICommandWaitCommandComplete(pConfig,
- hciBaudChangeCommand,
- sizeof(hciBaudChangeCommand),
- &pEvent,
- &pBufferToFree);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n"));
- break;
- }
-
- if (pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET] != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("AR3K Config: Baud change command event status failed: %d \n",
- pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET]));
- status = A_ECOMM;
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate));
- }
-
- if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) {
- /* some versions of AR3K do not switch baud immediately, up to 300MS */
- A_MDELAY(325);
- }
-
- if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP) {
- /* Tell target to change UART baud rate for AR6K */
- status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("AR3K Config: failed to set scale and step values: %d \n", status));
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
- ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate));
- }
-
- } while (false);
-
- if (pBufferToFree != NULL) {
- kfree(pBufferToFree);
- }
-
- return status;
-}
-
-static int AR3KExitMinBoot(struct ar3k_config_info *pConfig)
-{
- int status;
- char exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00};
- u8 *pEvent = NULL;
- u8 *pBufferToFree = NULL;
-
- status = SendHCICommandWaitCommandComplete(pConfig,
- exitMinBootCmd,
- sizeof(exitMinBootCmd),
- &pEvent,
- &pBufferToFree);
-
- if (!status) {
- if (pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET] != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("AR3K Config: MinBoot exit command event status failed: %d \n",
- pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET]));
- status = A_ECOMM;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("AR3K Config: MinBoot Exit Command Complete (Success) \n"));
- A_MDELAY(1);
- }
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: MinBoot Exit Failed! \n"));
- }
-
- if (pBufferToFree != NULL) {
- kfree(pBufferToFree);
- }
-
- return status;
-}
-
-static int AR3KConfigureSendHCIReset(struct ar3k_config_info *pConfig)
-{
- int status = 0;
- u8 hciResetCommand[] = {0x03,0x0c,0x0};
- u8 *pEvent = NULL;
- u8 *pBufferToFree = NULL;
-
- status = SendHCICommandWaitCommandComplete( pConfig,
- hciResetCommand,
- sizeof(hciResetCommand),
- &pEvent,
- &pBufferToFree );
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI reset failed! \n"));
- }
-
- if (pBufferToFree != NULL) {
- kfree(pBufferToFree);
- }
-
- return status;
-}
-
-static int AR3KEnableTLPM(struct ar3k_config_info *pConfig)
-{
- int status;
- /* AR3K vendor specific command for Host Wakeup Config */
- char hostWakeupConfig[] = {0x31,0xFC,0x18,
- 0x02,0x00,0x00,0x00,
- 0x01,0x00,0x00,0x00,
- TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms
- 0x00,0x00,0x00,0x00,
- TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms
- 0x00,0x00,0x00,0x00};
- /* AR3K vendor specific command for Target Wakeup Config */
- char targetWakeupConfig[] = {0x31,0xFC,0x18,
- 0x04,0x00,0x00,0x00,
- 0x01,0x00,0x00,0x00,
- TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms
- 0x00,0x00,0x00,0x00,
- TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms
- 0x00,0x00,0x00,0x00};
- /* AR3K vendor specific command for Host Wakeup Enable */
- char hostWakeupEnable[] = {0x31,0xFC,0x4,
- 0x01,0x00,0x00,0x00};
- /* AR3K vendor specific command for Target Wakeup Enable */
- char targetWakeupEnable[] = {0x31,0xFC,0x4,
- 0x06,0x00,0x00,0x00};
- /* AR3K vendor specific command for Sleep Enable */
- char sleepEnable[] = {0x4,0xFC,0x1,
- 0x1};
- u8 *pEvent = NULL;
- u8 *pBufferToFree = NULL;
-
- if (0 != pConfig->IdleTimeout) {
- u8 idle_lsb = pConfig->IdleTimeout & 0xFF;
- u8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8;
- hostWakeupConfig[11] = targetWakeupConfig[11] = idle_lsb;
- hostWakeupConfig[12] = targetWakeupConfig[12] = idle_msb;
- }
-
- if (0 != pConfig->WakeupTimeout) {
- hostWakeupConfig[19] = targetWakeupConfig[19] = (pConfig->WakeupTimeout & 0xFF);
- }
-
- status = SendHCICommandWaitCommandComplete(pConfig,
- hostWakeupConfig,
- sizeof(hostWakeupConfig),
- &pEvent,
- &pBufferToFree);
- if (pBufferToFree != NULL) {
- kfree(pBufferToFree);
- }
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Config Failed! \n"));
- return status;
- }
-
- pEvent = NULL;
- pBufferToFree = NULL;
- status = SendHCICommandWaitCommandComplete(pConfig,
- targetWakeupConfig,
- sizeof(targetWakeupConfig),
- &pEvent,
- &pBufferToFree);
- if (pBufferToFree != NULL) {
- kfree(pBufferToFree);
- }
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Config Failed! \n"));
- return status;
- }
-
- pEvent = NULL;
- pBufferToFree = NULL;
- status = SendHCICommandWaitCommandComplete(pConfig,
- hostWakeupEnable,
- sizeof(hostWakeupEnable),
- &pEvent,
- &pBufferToFree);
- if (pBufferToFree != NULL) {
- kfree(pBufferToFree);
- }
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Enable Failed! \n"));
- return status;
- }
-
- pEvent = NULL;
- pBufferToFree = NULL;
- status = SendHCICommandWaitCommandComplete(pConfig,
- targetWakeupEnable,
- sizeof(targetWakeupEnable),
- &pEvent,
- &pBufferToFree);
- if (pBufferToFree != NULL) {
- kfree(pBufferToFree);
- }
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Enable Failed! \n"));
- return status;
- }
-
- pEvent = NULL;
- pBufferToFree = NULL;
- status = SendHCICommandWaitCommandComplete(pConfig,
- sleepEnable,
- sizeof(sleepEnable),
- &pEvent,
- &pBufferToFree);
- if (pBufferToFree != NULL) {
- kfree(pBufferToFree);
- }
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Sleep Enable Failed! \n"));
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Enable TLPM Completed (status = %d) \n",status));
-
- return status;
-}
-
-int AR3KConfigure(struct ar3k_config_info *pConfig)
-{
- int status = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuring AR3K ...\n"));
-
- do {
-
- if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) {
- status = A_EINVAL;
- break;
- }
-
- /* disable asynchronous recv while we issue commands and receive events synchronously */
- status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false);
- if (status) {
- break;
- }
-
- if (pConfig->Flags & AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT) {
- status = AR3KExitMinBoot(pConfig);
- if (status) {
- break;
- }
- }
-
-
- /* Load patching and PST file if available*/
- if (0 != AthPSInitialize(pConfig)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch Download Failed!\n"));
- }
-
- /* Send HCI reset to make PS tags take effect*/
- AR3KConfigureSendHCIReset(pConfig);
-
- if (pConfig->Flags &
- (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
- status = AR3KConfigureHCIBaud(pConfig);
- if (status) {
- break;
- }
- }
-
-
-
- if (pConfig->PwrMgmtEnabled) {
- /* the delay is required after the previous HCI reset before further
- * HCI commands can be issued
- */
- A_MDELAY(200);
- AR3KEnableTLPM(pConfig);
- }
-
- /* re-enable asynchronous recv */
- status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true);
- if (status) {
- break;
- }
-
-
- } while (false);
-
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuration Complete (status = %d) \n",status));
-
- return status;
-}
-
-int AR3KConfigureExit(void *config)
-{
- int status = 0;
- struct ar3k_config_info *pConfig = (struct ar3k_config_info *)config;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleaning up AR3K ...\n"));
-
- do {
-
- if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) {
- status = A_EINVAL;
- break;
- }
-
- /* disable asynchronous recv while we issue commands and receive events synchronously */
- status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false);
- if (status) {
- break;
- }
-
- if (pConfig->Flags &
- (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
- status = AR3KConfigureHCIBaud(pConfig);
- if (status) {
- break;
- }
- }
-
- /* re-enable asynchronous recv */
- status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true);
- if (status) {
- break;
- }
-
-
- } while (false);
-
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleanup Complete (status = %d) \n",status));
-
- return status;
-}
-
diff --git a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c
deleted file mode 100644
index 282ceac597b8..000000000000
--- a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * Copyright (c) 2004-2010 Atheros Communications Inc.
- * All rights reserved.
- *
- * This file implements the Atheros PS and patch downloaded for HCI UART Transport driver.
- * This file can be used for HCI SDIO transport implementation for AR6002 with HCI_TRANSPORT_SDIO
- * defined.
- *
- *
- * ar3kcpsconfig.c
- *
- *
- *
- * The software source and binaries included in this development package are
- * licensed, not sold. You, or your company, received the package under one
- * or more license agreements. The rights granted to you are specifically
- * listed in these license agreement(s). All other rights remain with Atheros
- * Communications, Inc., its subsidiaries, or the respective owner including
- * those listed on the included copyright notices.. Distribution of any
- * portion of this package must be in strict compliance with the license
- * agreement(s) terms.
- *
- *
- *
- */
-
-
-
-#include "ar3kpsconfig.h"
-#ifndef HCI_TRANSPORT_SDIO
-#include "hci_ath.h"
-#include "hci_uart.h"
-#endif /* #ifndef HCI_TRANSPORT_SDIO */
-
-#define MAX_FW_PATH_LEN 50
-#define MAX_BDADDR_FORMAT_LENGTH 30
-
-/*
- * Structure used to send HCI packet, hci packet length and device info
- * together as parameter to PSThread.
- */
-typedef struct {
-
- struct ps_cmd_packet *HciCmdList;
- u32 num_packets;
- struct ar3k_config_info *dev;
-}HciCommandListParam;
-
-int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
- u8 *pHCICommand,
- int CmdLength,
- u8 **ppEventBuffer,
- u8 **ppBufferToFree);
-
-u32 Rom_Version;
-u32 Build_Version;
-extern bool BDADDR;
-
-int getDeviceType(struct ar3k_config_info *pConfig, u32 *code);
-int ReadVersionInfo(struct ar3k_config_info *pConfig);
-#ifndef HCI_TRANSPORT_SDIO
-
-DECLARE_WAIT_QUEUE_HEAD(PsCompleteEvent);
-DECLARE_WAIT_QUEUE_HEAD(HciEvent);
-u8 *HciEventpacket;
-rwlock_t syncLock;
-wait_queue_t Eventwait;
-
-int PSHciWritepacket(struct hci_dev*,u8* Data, u32 len);
-extern char *bdaddr;
-#endif /* HCI_TRANSPORT_SDIO */
-
-int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type);
-
-int PSSendOps(void *arg);
-
-#ifdef BT_PS_DEBUG
-void Hci_log(u8 * log_string,u8 *data,u32 len)
-{
- int i;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s : ",log_string));
- for (i = 0; i < len; i++) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("0x%02x ", data[i]));
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n...................................\n"));
-}
-#else
-#define Hci_log(string,data,len)
-#endif /* BT_PS_DEBUG */
-
-
-
-
-int AthPSInitialize(struct ar3k_config_info *hdev)
-{
- int status = 0;
- if(hdev == NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Device handle received\n"));
- return A_ERROR;
- }
-
-#ifndef HCI_TRANSPORT_SDIO
- DECLARE_WAITQUEUE(wait, current);
-#endif /* HCI_TRANSPORT_SDIO */
-
-
-#ifdef HCI_TRANSPORT_SDIO
- status = PSSendOps((void*)hdev);
-#else
- if(InitPSState(hdev) == -1) {
- return A_ERROR;
- }
- allow_signal(SIGKILL);
- add_wait_queue(&PsCompleteEvent,&wait);
- set_current_state(TASK_INTERRUPTIBLE);
- if(!kernel_thread(PSSendOps,(void*)hdev,CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Kthread Failed\n"));
- remove_wait_queue(&PsCompleteEvent,&wait);
- return A_ERROR;
- }
- wait_event_interruptible(PsCompleteEvent,(PSTagMode == false));
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&PsCompleteEvent,&wait);
-
-#endif /* HCI_TRANSPORT_SDIO */
-
-
- return status;
-
-}
-
-int PSSendOps(void *arg)
-{
- int i;
- int status = 0;
- struct ps_cmd_packet *HciCmdList; /* List storing the commands */
- const struct firmware* firmware;
- u32 numCmds;
- u8 *event;
- u8 *bufferToFree;
- struct hci_dev *device;
- u8 *buffer;
- u32 len;
- u32 DevType;
- u8 *PsFileName;
- u8 *patchFileName;
- u8 *path = NULL;
- u8 *config_path = NULL;
- u8 config_bdaddr[MAX_BDADDR_FORMAT_LENGTH];
- struct ar3k_config_info *hdev = (struct ar3k_config_info*)arg;
- struct device *firmwareDev = NULL;
- status = 0;
- HciCmdList = NULL;
-#ifdef HCI_TRANSPORT_SDIO
- device = hdev->pBtStackHCIDev;
- firmwareDev = device->parent;
-#else
- device = hdev;
- firmwareDev = &device->dev;
- AthEnableSyncCommandOp(true);
-#endif /* HCI_TRANSPORT_SDIO */
- /* First verify if the controller is an FPGA or ASIC, so depending on the device type the PS file to be written will be different.
- */
-
- path =(u8 *)A_MALLOC(MAX_FW_PATH_LEN);
- if(path == NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for path\n", MAX_FW_PATH_LEN));
- goto complete;
- }
- config_path = (u8 *) A_MALLOC(MAX_FW_PATH_LEN);
- if(config_path == NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for config_path\n", MAX_FW_PATH_LEN));
- goto complete;
- }
-
- if(A_ERROR == getDeviceType(hdev,&DevType)) {
- status = 1;
- goto complete;
- }
- if(A_ERROR == ReadVersionInfo(hdev)) {
- status = 1;
- goto complete;
- }
-
- patchFileName = PATCH_FILE;
- snprintf(path, MAX_FW_PATH_LEN, "%s/%xcoex/",CONFIG_PATH,Rom_Version);
- if(DevType){
- if(DevType == 0xdeadc0de){
- PsFileName = PS_ASIC_FILE;
- } else{
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" FPGA Test Image : %x %x \n",Rom_Version,Build_Version));
- if((Rom_Version == 0x99999999) && (Build_Version == 1)){
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("FPGA Test Image : Skipping Patch File load\n"));
- patchFileName = NULL;
- }
- PsFileName = PS_FPGA_FILE;
- }
- }
- else{
- PsFileName = PS_ASIC_FILE;
- }
-
- snprintf(config_path, MAX_FW_PATH_LEN, "%s%s",path,PsFileName);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%x: FPGA/ASIC PS File Name %s\n", DevType,config_path));
- /* Read the PS file to a dynamically allocated buffer */
- if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ ));
- status = 1;
- goto complete;
-
- }
- if(NULL == firmware || firmware->size == 0) {
- status = 1;
- goto complete;
- }
- buffer = (u8 *)A_MALLOC(firmware->size);
- if(buffer != NULL) {
- /* Copy the read file to a local Dynamic buffer */
- memcpy(buffer,firmware->data,firmware->size);
- len = firmware->size;
- A_RELEASE_FIRMWARE(firmware);
- /* Parse the PS buffer to a global variable */
- status = AthDoParsePS(buffer,len);
- kfree(buffer);
- } else {
- A_RELEASE_FIRMWARE(firmware);
- }
-
-
- /* Read the patch file to a dynamically allocated buffer */
- if(patchFileName != NULL)
- snprintf(config_path,
- MAX_FW_PATH_LEN, "%s%s",path,patchFileName);
- else {
- status = 0;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch File Name %s\n", config_path));
- if((patchFileName == NULL) || (A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ ));
- /*
- * It is not necessary that Patch file be available, continue with PS Operations if.
- * failed.
- */
- status = 0;
-
- } else {
- if(NULL == firmware || firmware->size == 0) {
- status = 0;
- } else {
- buffer = (u8 *)A_MALLOC(firmware->size);
- if(buffer != NULL) {
- /* Copy the read file to a local Dynamic buffer */
- memcpy(buffer,firmware->data,firmware->size);
- len = firmware->size;
- A_RELEASE_FIRMWARE(firmware);
- /* parse and store the Patch file contents to a global variables */
- status = AthDoParsePatch(buffer,len);
- kfree(buffer);
- } else {
- A_RELEASE_FIRMWARE(firmware);
- }
- }
- }
-
- /* Create an HCI command list from the parsed PS and patch information */
- AthCreateCommandList(&HciCmdList,&numCmds);
-
- /* Form the parameter for PSSendOps() API */
-
-
- /*
- * First Send the CRC packet,
- * We have to continue with the PS operations only if the CRC packet has been replied with
- * a Command complete event with status Error.
- */
-
- if(SendHCICommandWaitCommandComplete
- (hdev,
- HciCmdList[0].Hcipacket,
- HciCmdList[0].packetLen,
- &event,
- &bufferToFree) == 0) {
- if(ReadPSEvent(event) == 0) { /* Exit if the status is success */
- if(bufferToFree != NULL) {
- kfree(bufferToFree);
- }
-
-#ifndef HCI_TRANSPORT_SDIO
- if(bdaddr && bdaddr[0] !='\0') {
- write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING);
- }
-#endif
- status = 1;
- goto complete;
- }
- if(bufferToFree != NULL) {
- kfree(bufferToFree);
- }
- } else {
- status = 0;
- goto complete;
- }
-
- for(i = 1; i <numCmds; i++) {
-
- if(SendHCICommandWaitCommandComplete
- (hdev,
- HciCmdList[i].Hcipacket,
- HciCmdList[i].packetLen,
- &event,
- &bufferToFree) == 0) {
- if(ReadPSEvent(event) != 0) { /* Exit if the status is success */
- if(bufferToFree != NULL) {
- kfree(bufferToFree);
- }
- status = 1;
- goto complete;
- }
- if(bufferToFree != NULL) {
- kfree(bufferToFree);
- }
- } else {
- status = 0;
- goto complete;
- }
- }
-#ifdef HCI_TRANSPORT_SDIO
- if(BDADDR == false)
- if(hdev->bdaddr[0] !=0x00 ||
- hdev->bdaddr[1] !=0x00 ||
- hdev->bdaddr[2] !=0x00 ||
- hdev->bdaddr[3] !=0x00 ||
- hdev->bdaddr[4] !=0x00 ||
- hdev->bdaddr[5] !=0x00)
- write_bdaddr(hdev,hdev->bdaddr,BDADDR_TYPE_HEX);
-
-#ifndef HCI_TRANSPORT_SDIO
-
- if(bdaddr && bdaddr[0] != '\0') {
- write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING);
- } else
-#endif /* HCI_TRANSPORT_SDIO */
- /* Write BDADDR Read from OTP here */
-
-
-
-#endif
-
- {
- /* Read Contents of BDADDR file if user has not provided any option */
- snprintf(config_path,MAX_FW_PATH_LEN, "%s%s",path,BDADDR_FILE);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch File Name %s\n", config_path));
- if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ ));
- status = 1;
- goto complete;
- }
- if(NULL == firmware || firmware->size == 0) {
- status = 1;
- goto complete;
- }
- len = min_t(size_t, firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1);
- memcpy(config_bdaddr, firmware->data, len);
- config_bdaddr[len] = '\0';
- write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING);
- A_RELEASE_FIRMWARE(firmware);
- }
-complete:
-#ifndef HCI_TRANSPORT_SDIO
- AthEnableSyncCommandOp(false);
- PSTagMode = false;
- wake_up_interruptible(&PsCompleteEvent);
-#endif /* HCI_TRANSPORT_SDIO */
- if(NULL != HciCmdList) {
- AthFreeCommandList(&HciCmdList,numCmds);
- }
- if(path) {
- kfree(path);
- }
- if(config_path) {
- kfree(config_path);
- }
- return status;
-}
-#ifndef HCI_TRANSPORT_SDIO
-/*
- * This API is used to send the HCI command to controller and return
- * with a HCI Command Complete event.
- * For HCI SDIO transport, this will be internally defined.
- */
-int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
- u8 *pHCICommand,
- int CmdLength,
- u8 **ppEventBuffer,
- u8 **ppBufferToFree)
-{
- if(CmdLength == 0) {
- return A_ERROR;
- }
- Hci_log("COM Write -->",pHCICommand,CmdLength);
- PSAcked = false;
- if(PSHciWritepacket(pConfig,pHCICommand,CmdLength) == 0) {
- /* If the controller is not available, return Error */
- return A_ERROR;
- }
- //add_timer(&psCmdTimer);
- wait_event_interruptible(HciEvent,(PSAcked == true));
- if(NULL != HciEventpacket) {
- *ppEventBuffer = HciEventpacket;
- *ppBufferToFree = HciEventpacket;
- } else {
- /* Did not get an event from controller. return error */
- *ppBufferToFree = NULL;
- return A_ERROR;
- }
-
- return 0;
-}
-#endif /* HCI_TRANSPORT_SDIO */
-
-int ReadPSEvent(u8* Data){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" PS Event %x %x %x\n",Data[4],Data[5],Data[3]));
-
- if(Data[4] == 0xFC && Data[5] == 0x00)
- {
- switch(Data[3]){
- case 0x0B:
- return 0;
- break;
- case 0x0C:
- /* Change Baudrate */
- return 0;
- break;
- case 0x04:
- return 0;
- break;
- case 0x1E:
- Rom_Version = Data[9];
- Rom_Version = ((Rom_Version << 8) |Data[8]);
- Rom_Version = ((Rom_Version << 8) |Data[7]);
- Rom_Version = ((Rom_Version << 8) |Data[6]);
-
- Build_Version = Data[13];
- Build_Version = ((Build_Version << 8) |Data[12]);
- Build_Version = ((Build_Version << 8) |Data[11]);
- Build_Version = ((Build_Version << 8) |Data[10]);
- return 0;
- break;
-
-
- }
- }
-
- return A_ERROR;
-}
-int str2ba(unsigned char *str_bdaddr,unsigned char *bdaddr)
-{
- unsigned char bdbyte[3];
- unsigned char *str_byte = str_bdaddr;
- int i,j;
- unsigned char colon_present = 0;
-
- if(NULL != strstr(str_bdaddr,":")) {
- colon_present = 1;
- }
-
-
- bdbyte[2] = '\0';
-
- for( i = 0,j = 5; i < 6; i++, j--) {
- bdbyte[0] = str_byte[0];
- bdbyte[1] = str_byte[1];
- bdaddr[j] = A_STRTOL(bdbyte,NULL,16);
- if(colon_present == 1) {
- str_byte+=3;
- } else {
- str_byte+=2;
- }
- }
- return 0;
-}
-
-int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type)
-{
- u8 bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01,
- 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
- u8 *event;
- u8 *bufferToFree = NULL;
- int result = A_ERROR;
- int inc,outc;
-
- if (type == BDADDR_TYPE_STRING)
- str2ba(bdaddr,&bdaddr_cmd[7]);
- else {
- /* Bdaddr has to be sent as LAP first */
- for(inc = 5 ,outc = 7; inc >=0; inc--, outc++)
- bdaddr_cmd[outc] = bdaddr[inc];
- }
-
- if(0 == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd,
- sizeof(bdaddr_cmd),
- &event,&bufferToFree)) {
-
- if(event[4] == 0xFC && event[5] == 0x00){
- if(event[3] == 0x0B){
- result = 0;
- }
- }
-
- }
- if(bufferToFree != NULL) {
- kfree(bufferToFree);
- }
- return result;
-
-}
-int ReadVersionInfo(struct ar3k_config_info *pConfig)
-{
- u8 hciCommand[] = {0x1E,0xfc,0x00};
- u8 *event;
- u8 *bufferToFree = NULL;
- int result = A_ERROR;
- if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
- result = ReadPSEvent(event);
-
- }
- if(bufferToFree != NULL) {
- kfree(bufferToFree);
- }
- return result;
-}
-int getDeviceType(struct ar3k_config_info *pConfig, u32 *code)
-{
- u8 hciCommand[] = {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04};
- u8 *event;
- u8 *bufferToFree = NULL;
- u32 reg;
- int result = A_ERROR;
- *code = 0;
- hciCommand[3] = (u8)(FPGA_REGISTER & 0xFF);
- hciCommand[4] = (u8)((FPGA_REGISTER >> 8) & 0xFF);
- hciCommand[5] = (u8)((FPGA_REGISTER >> 16) & 0xFF);
- hciCommand[6] = (u8)((FPGA_REGISTER >> 24) & 0xFF);
- if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
-
- if(event[4] == 0xFC && event[5] == 0x00){
- switch(event[3]){
- case 0x05:
- reg = event[9];
- reg = ((reg << 8) |event[8]);
- reg = ((reg << 8) |event[7]);
- reg = ((reg << 8) |event[6]);
- *code = reg;
- result = 0;
-
- break;
- case 0x06:
- //Sleep(500);
- break;
- }
- }
-
- }
- if(bufferToFree != NULL) {
- kfree(bufferToFree);
- }
- return result;
-}
-
-
diff --git a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h
deleted file mode 100644
index d44351307807..000000000000
--- a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2004-2010 Atheros Communications Inc.
- * All rights reserved.
- *
- * This file defines the symbols exported by Atheros PS and patch download module.
- * define the constant HCI_TRANSPORT_SDIO if the module is being used for HCI SDIO transport.
- * defined.
- *
- *
- * ar3kcpsconfig.h
- *
- *
- *
- * The software source and binaries included in this development package are
- * licensed, not sold. You, or your company, received the package under one
- * or more license agreements. The rights granted to you are specifically
- * listed in these license agreement(s). All other rights remain with Atheros
- * Communications, Inc., its subsidiaries, or the respective owner including
- * those listed on the included copyright notices.. Distribution of any
- * portion of this package must be in strict compliance with the license
- * agreement(s) terms.
- *
- *
- *
- */
-
-
-
-#ifndef __AR3KPSCONFIG_H
-#define __AR3KPSCONFIG_H
-
-/*
- * Define the flag HCI_TRANSPORT_SDIO and undefine HCI_TRANSPORT_UART if the transport being used is SDIO.
- */
-#undef HCI_TRANSPORT_UART
-
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-
-
-#include <linux/ioctl.h>
-#include <linux/firmware.h>
-
-
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-
-#include "ar3kpsparser.h"
-
-#define FPGA_REGISTER 0x4FFC
-#define BDADDR_TYPE_STRING 0
-#define BDADDR_TYPE_HEX 1
-#define CONFIG_PATH "ar3k"
-
-#define PS_ASIC_FILE "PS_ASIC.pst"
-#define PS_FPGA_FILE "PS_FPGA.pst"
-
-#define PATCH_FILE "RamPatch.txt"
-#define BDADDR_FILE "ar3kbdaddr.pst"
-
-#define ROM_VER_AR3001_3_1_0 30000
-#define ROM_VER_AR3001_3_1_1 30101
-
-
-#ifndef HCI_TRANSPORT_SDIO
-#define struct ar3k_config_info struct hci_dev
-extern wait_queue_head_t HciEvent;
-extern wait_queue_t Eventwait;
-extern u8 *HciEventpacket;
-#endif /* #ifndef HCI_TRANSPORT_SDIO */
-
-int AthPSInitialize(struct ar3k_config_info *hdev);
-int ReadPSEvent(u8* Data);
-#endif /* __AR3KPSCONFIG_H */
diff --git a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c
deleted file mode 100644
index b99a11a9dd69..000000000000
--- a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c
+++ /dev/null
@@ -1,969 +0,0 @@
-/*
- * Copyright (c) 2004-2010 Atheros Communications Inc.
- * All rights reserved.
- *
- * This file implements the Atheros PS and patch parser.
- * It implements APIs to parse data buffer with patch and PS information and convert it to HCI commands.
- *
- *
- *
- * ar3kpsparser.c
- *
- *
- *
- * The software source and binaries included in this development package are
- * licensed, not sold. You, or your company, received the package under one
- * or more license agreements. The rights granted to you are specifically
- * listed in these license agreement(s). All other rights remain with Atheros
- * Communications, Inc., its subsidiaries, or the respective owner including
- * those listed on the included copyright notices.. Distribution of any
- * portion of this package must be in strict compliance with the license
- * agreement(s) terms.
- *
- *
- *
- */
-
-
-#include "ar3kpsparser.h"
-
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-
-#define BD_ADDR_SIZE 6
-#define WRITE_PATCH 8
-#define ENABLE_PATCH 11
-#define PS_RESET 2
-#define PS_WRITE 1
-#define PS_VERIFY_CRC 9
-#define CHANGE_BDADDR 15
-
-#define HCI_COMMAND_HEADER 7
-
-#define HCI_EVENT_SIZE 7
-
-#define WRITE_PATCH_COMMAND_STATUS_OFFSET 5
-
-#define PS_RAM_SIZE 2048
-
-#define RAM_PS_REGION (1<<0)
-#define RAM_PATCH_REGION (1<<1)
-#define RAMPS_MAX_PS_DATA_PER_TAG 20000
-#define MAX_RADIO_CFG_TABLE_SIZE 244
-#define RAMPS_MAX_PS_TAGS_PER_FILE 50
-
-#define PS_MAX_LEN 500
-#define LINE_SIZE_MAX (PS_MAX_LEN *2)
-
-/* Constant values used by parser */
-#define BYTES_OF_PS_DATA_PER_LINE 16
-#define RAMPS_MAX_PS_DATA_PER_TAG 20000
-
-
-/* Number pf PS/Patch entries in an HCI packet */
-#define MAX_BYTE_LENGTH 244
-
-#define SKIP_BLANKS(str) while (*str == ' ') str++
-
-enum MinBootFileFormatE
-{
- MB_FILEFORMAT_RADIOTBL,
- MB_FILEFORMAT_PATCH,
- MB_FILEFORMAT_COEXCONFIG
-};
-
-enum RamPsSection
-{
- RAM_PS_SECTION,
- RAM_PATCH_SECTION,
- RAM_DYN_MEM_SECTION
-};
-
-enum eType {
- eHex,
- edecimal
-};
-
-
-typedef struct tPsTagEntry
-{
- u32 TagId;
- u32 TagLen;
- u8 *TagData;
-} tPsTagEntry, *tpPsTagEntry;
-
-typedef struct tRamPatch
-{
- u16 Len;
- u8 *Data;
-} tRamPatch, *ptRamPatch;
-
-
-
-struct st_ps_data_format {
- enum eType eDataType;
- bool bIsArray;
-};
-
-struct st_read_status {
- unsigned uTagID;
- unsigned uSection;
- unsigned uLineCount;
- unsigned uCharCount;
- unsigned uByteCount;
-};
-
-
-/* Stores the number of PS Tags */
-static u32 Tag_Count = 0;
-
-/* Stores the number of patch commands */
-static u32 Patch_Count = 0;
-static u32 Total_tag_lenght = 0;
-bool BDADDR = false;
-u32 StartTagId;
-
-tPsTagEntry PsTagEntry[RAMPS_MAX_PS_TAGS_PER_FILE];
-tRamPatch RamPatch[MAX_NUM_PATCH_ENTRY];
-
-
-int AthParseFilesUnified(u8 *srcbuffer,u32 srclen, int FileFormat);
-char AthReadChar(u8 *buffer, u32 len,u32 *pos);
-char *AthGetLine(char *buffer, int maxlen, u8 *srcbuffer,u32 len,u32 *pos);
-static int AthPSCreateHCICommand(u8 Opcode, u32 Param1,struct ps_cmd_packet *PSPatchPacket,u32 *index);
-
-/* Function to reads the next character from the input buffer */
-char AthReadChar(u8 *buffer, u32 len,u32 *pos)
-{
- char Ch;
- if(buffer == NULL || *pos >=len )
- {
- return '\0';
- } else {
- Ch = buffer[*pos];
- (*pos)++;
- return Ch;
- }
-}
-/* PS parser helper function */
-unsigned int uGetInputDataFormat(char *pCharLine, struct st_ps_data_format *pstFormat)
-{
- if(pCharLine[0] != '[') {
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = true;
- return 0;
- }
- switch(pCharLine[1]) {
- case 'H':
- case 'h':
- if(pCharLine[2]==':') {
- if((pCharLine[3]== 'a') || (pCharLine[3]== 'A')) {
- if(pCharLine[4] == ']') {
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = true;
- pCharLine += 5;
- return 0;
- }
- else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A
- return 1;
- }
- }
- if((pCharLine[3]== 'S') || (pCharLine[3]== 's')) {
- if(pCharLine[4] == ']') {
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = false;
- pCharLine += 5;
- return 0;
- }
- else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A
- return 1;
- }
- }
- else if(pCharLine[3] == ']') { //[H:]
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = true;
- pCharLine += 4;
- return 0;
- }
- else { //[H:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n"));
- return 1;
- }
- }
- else if(pCharLine[2]==']') { //[H]
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = true;
- pCharLine += 3;
- return 0;
- }
- else { //[H
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n"));
- return 1;
- }
- break;
-
- case 'A':
- case 'a':
- if(pCharLine[2]==':') {
- if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) {
- if(pCharLine[4] == ']') {
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = true;
- pCharLine += 5;
- return 0;
- }
- else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 1\n")); //[A:H
- return 1;
- }
- }
- else if(pCharLine[3]== ']') { //[A:]
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = true;
- pCharLine += 4;
- return 0;
- }
- else { //[A:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 2\n"));
- return 1;
- }
- }
- else if(pCharLine[2]==']') { //[H]
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = true;
- pCharLine += 3;
- return 0;
- }
- else { //[H
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 3\n"));
- return 1;
- }
- break;
-
- case 'S':
- case 's':
- if(pCharLine[2]==':') {
- if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) {
- if(pCharLine[4] == ']') {
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = true;
- pCharLine += 5;
- return 0;
- }
- else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 5\n")); //[A:H
- return 1;
- }
- }
- else if(pCharLine[3]== ']') { //[A:]
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = true;
- pCharLine += 4;
- return 0;
- }
- else { //[A:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 6\n"));
- return 1;
- }
- }
- else if(pCharLine[2]==']') { //[H]
- pstFormat->eDataType = eHex;
- pstFormat->bIsArray = true;
- pCharLine += 3;
- return 0;
- }
- else { //[H
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 7\n"));
- return 1;
- }
- break;
-
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 8\n"));
- return 1;
- }
-}
-
-unsigned int uReadDataInSection(char *pCharLine, struct st_ps_data_format stPS_DataFormat)
-{
- char *pTokenPtr = pCharLine;
-
- if(pTokenPtr[0] == '[') {
- while(pTokenPtr[0] != ']' && pTokenPtr[0] != '\0') {
- pTokenPtr++;
- }
- if(pTokenPtr[0] == '\0') {
- return (0x0FFF);
- }
- pTokenPtr++;
-
-
- }
- if(stPS_DataFormat.eDataType == eHex) {
- if(stPS_DataFormat.bIsArray == true) {
- //Not implemented
- return (0x0FFF);
- }
- else {
- return (A_STRTOL(pTokenPtr, NULL, 16));
- }
- }
- else {
- //Not implemented
- return (0x0FFF);
- }
-}
-int AthParseFilesUnified(u8 *srcbuffer,u32 srclen, int FileFormat)
-{
- char *Buffer;
- char *pCharLine;
- u8 TagCount;
- u16 ByteCount;
- u8 ParseSection=RAM_PS_SECTION;
- u32 pos;
-
-
-
- int uReadCount;
- struct st_ps_data_format stPS_DataFormat;
- struct st_read_status stReadStatus = {0, 0, 0,0};
- pos = 0;
- Buffer = NULL;
-
- if (srcbuffer == NULL || srclen == 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Could not open .\n"));
- return A_ERROR;
- }
- TagCount = 0;
- ByteCount = 0;
- Buffer = A_MALLOC(LINE_SIZE_MAX + 1);
- if(NULL == Buffer) {
- return A_ERROR;
- }
- if (FileFormat == MB_FILEFORMAT_PATCH)
- {
- int LineRead = 0;
- while((pCharLine = AthGetLine(Buffer, LINE_SIZE_MAX, srcbuffer,srclen,&pos)) != NULL)
- {
-
- SKIP_BLANKS(pCharLine);
-
- // Comment line or empty line
- if ((pCharLine[0] == '/') && (pCharLine[1] == '/'))
- {
- continue;
- }
-
- if ((pCharLine[0] == '#')) {
- if (stReadStatus.uSection != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("error\n"));
- if(Buffer != NULL) {
- kfree(Buffer);
- }
- return A_ERROR;
- }
- else {
- stReadStatus.uSection = 1;
- continue;
- }
- }
- if ((pCharLine[0] == '/') && (pCharLine[1] == '*'))
- {
- pCharLine+=2;
- SKIP_BLANKS(pCharLine);
-
- if(!strncmp(pCharLine,"PA",2)||!strncmp(pCharLine,"Pa",2)||!strncmp(pCharLine,"pa",2))
- ParseSection=RAM_PATCH_SECTION;
-
- if(!strncmp(pCharLine,"DY",2)||!strncmp(pCharLine,"Dy",2)||!strncmp(pCharLine,"dy",2))
- ParseSection=RAM_DYN_MEM_SECTION;
-
- if(!strncmp(pCharLine,"PS",2)||!strncmp(pCharLine,"Ps",2)||!strncmp(pCharLine,"ps",2))
- ParseSection=RAM_PS_SECTION;
-
- LineRead = 0;
- stReadStatus.uSection = 0;
-
- continue;
- }
-
- switch(ParseSection)
- {
- case RAM_PS_SECTION:
- {
- if (stReadStatus.uSection == 1) //TagID
- {
- SKIP_BLANKS(pCharLine);
- if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail\n"));
- if(Buffer != NULL) {
- kfree(Buffer);
- }
- return A_ERROR;
- }
- //pCharLine +=5;
- PsTagEntry[TagCount].TagId = uReadDataInSection(pCharLine, stPS_DataFormat);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG ID %d \n",PsTagEntry[TagCount].TagId));
-
- //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag # %x\n", PsTagEntry[TagCount].TagId);
- if (TagCount == 0)
- {
- StartTagId = PsTagEntry[TagCount].TagId;
- }
- stReadStatus.uSection = 2;
- }
- else if (stReadStatus.uSection == 2) //TagLength
- {
-
- if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail \n"));
- if(Buffer != NULL) {
- kfree(Buffer);
- }
- return A_ERROR;
- }
- //pCharLine +=5;
- ByteCount = uReadDataInSection(pCharLine, stPS_DataFormat);
-
- //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag length %x\n", ByteCount));
- if (ByteCount > LINE_SIZE_MAX/2)
- {
- if(Buffer != NULL) {
- kfree(Buffer);
- }
- return A_ERROR;
- }
- PsTagEntry[TagCount].TagLen = ByteCount;
- PsTagEntry[TagCount].TagData = (u8 *)A_MALLOC(ByteCount);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG Length %d Tag Index %d \n",PsTagEntry[TagCount].TagLen,TagCount));
- stReadStatus.uSection = 3;
- stReadStatus.uLineCount = 0;
- }
- else if( stReadStatus.uSection == 3) { //Data
-
- if(stReadStatus.uLineCount == 0) {
- if(uGetInputDataFormat(pCharLine,&stPS_DataFormat)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat Fail\n"));
- if(Buffer != NULL) {
- kfree(Buffer);
- }
- return A_ERROR;
- }
- //pCharLine +=5;
- }
- SKIP_BLANKS(pCharLine);
- stReadStatus.uCharCount = 0;
- if(pCharLine[stReadStatus.uCharCount] == '[') {
- while(pCharLine[stReadStatus.uCharCount] != ']' && pCharLine[stReadStatus.uCharCount] != '\0' ) {
- stReadStatus.uCharCount++;
- }
- if(pCharLine[stReadStatus.uCharCount] == ']' ) {
- stReadStatus.uCharCount++;
- } else {
- stReadStatus.uCharCount = 0;
- }
- }
- uReadCount = (ByteCount > BYTES_OF_PS_DATA_PER_LINE)? BYTES_OF_PS_DATA_PER_LINE: ByteCount;
- //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" "));
- if((stPS_DataFormat.eDataType == eHex) && stPS_DataFormat.bIsArray == true) {
- while(uReadCount > 0) {
- PsTagEntry[TagCount].TagData[stReadStatus.uByteCount] =
- (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount]) << 4)
- | (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 1]));
-
- PsTagEntry[TagCount].TagData[stReadStatus.uByteCount+1] =
- (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 3]) << 4)
- | (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 4]));
-
- stReadStatus.uCharCount += 6; // read two bytes, plus a space;
- stReadStatus.uByteCount += 2;
- uReadCount -= 2;
- }
- if(ByteCount > BYTES_OF_PS_DATA_PER_LINE) {
- ByteCount -= BYTES_OF_PS_DATA_PER_LINE;
- }
- else {
- ByteCount = 0;
- }
- }
- else {
- //to be implemented
- }
-
- stReadStatus.uLineCount++;
-
- if(ByteCount == 0) {
- stReadStatus.uSection = 0;
- stReadStatus.uCharCount = 0;
- stReadStatus.uLineCount = 0;
- stReadStatus.uByteCount = 0;
- }
- else {
- stReadStatus.uCharCount = 0;
- }
-
- if((stReadStatus.uSection == 0)&&(++TagCount == RAMPS_MAX_PS_TAGS_PER_FILE))
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n Buffer over flow PS File too big!!!"));
- if(Buffer != NULL) {
- kfree(Buffer);
- }
- return A_ERROR;
- //Sleep (3000);
- //exit(1);
- }
-
- }
- }
-
- break;
- default:
- {
- if(Buffer != NULL) {
- kfree(Buffer);
- }
- return A_ERROR;
- }
- break;
- }
- LineRead++;
- }
- Tag_Count = TagCount;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Number of Tags %d\n", Tag_Count));
- }
-
-
- if (TagCount > RAMPS_MAX_PS_TAGS_PER_FILE)
- {
-
- if(Buffer != NULL) {
- kfree(Buffer);
- }
- return A_ERROR;
- }
-
- if(Buffer != NULL) {
- kfree(Buffer);
- }
- return 0;
-
-}
-
-
-
-/********************/
-
-
-int GetNextTwoChar(u8 *srcbuffer,u32 len, u32 *pos, char *buffer)
-{
- unsigned char ch;
-
- ch = AthReadChar(srcbuffer,len,pos);
- if(ch != '\0' && isxdigit(ch)) {
- buffer[0] = ch;
- } else
- {
- return A_ERROR;
- }
- ch = AthReadChar(srcbuffer,len,pos);
- if(ch != '\0' && isxdigit(ch)) {
- buffer[1] = ch;
- } else
- {
- return A_ERROR;
- }
- return 0;
-}
-
-int AthDoParsePatch(u8 *patchbuffer, u32 patchlen)
-{
-
- char Byte[3];
- char Line[MAX_BYTE_LENGTH + 1];
- int ByteCount,ByteCount_Org;
- int count;
- int i,j,k;
- int data;
- u32 filepos;
- Byte[2] = '\0';
- j = 0;
- filepos = 0;
- Patch_Count = 0;
-
- while(NULL != AthGetLine(Line,MAX_BYTE_LENGTH,patchbuffer,patchlen,&filepos)) {
- if(strlen(Line) <= 1 || !isxdigit(Line[0])) {
- continue;
- } else {
- break;
- }
- }
- ByteCount = A_STRTOL(Line, NULL, 16);
- ByteCount_Org = ByteCount;
-
- while(ByteCount > MAX_BYTE_LENGTH){
-
- /* Handle case when the number of patch buffer is more than the 20K */
- if(MAX_NUM_PATCH_ENTRY == Patch_Count) {
- for(i = 0; i < Patch_Count; i++) {
- kfree(RamPatch[i].Data);
- }
- return A_ERROR;
- }
- RamPatch[Patch_Count].Len= MAX_BYTE_LENGTH;
- RamPatch[Patch_Count].Data = (u8 *)A_MALLOC(MAX_BYTE_LENGTH);
- Patch_Count ++;
-
-
- ByteCount= ByteCount - MAX_BYTE_LENGTH;
- }
-
- RamPatch[Patch_Count].Len= (ByteCount & 0xFF);
- if(ByteCount != 0) {
- RamPatch[Patch_Count].Data = (u8 *)A_MALLOC(ByteCount);
- Patch_Count ++;
- }
- count = 0;
- while(ByteCount_Org > MAX_BYTE_LENGTH){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j));
- for (i = 0,k=0; i < MAX_BYTE_LENGTH*2; i += 2,k++,count +=2) {
- if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) {
- return A_ERROR;
- }
- data = A_STRTOUL(&Byte[0], NULL, 16);
- RamPatch[j].Data[k] = (data & 0xFF);
-
-
- }
- j++;
- ByteCount_Org = ByteCount_Org - MAX_BYTE_LENGTH;
- }
- if(j == 0){
- j++;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j));
- for (k=0; k < ByteCount_Org; i += 2,k++,count+=2) {
- if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) {
- return A_ERROR;
- }
- data = A_STRTOUL(Byte, NULL, 16);
- RamPatch[j].Data[k] = (data & 0xFF);
-
-
- }
- return 0;
-}
-
-
-/********************/
-int AthDoParsePS(u8 *srcbuffer, u32 srclen)
-{
- int status;
- int i;
- bool BDADDR_Present = false;
-
- Tag_Count = 0;
-
- Total_tag_lenght = 0;
- BDADDR = false;
-
-
- status = A_ERROR;
-
- if(NULL != srcbuffer && srclen != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("File Open Operation Successful\n"));
-
- status = AthParseFilesUnified(srcbuffer,srclen,MB_FILEFORMAT_PATCH);
- }
-
-
-
- if(Tag_Count == 0){
- Total_tag_lenght = 10;
-
- }
- else{
- for(i=0; i<Tag_Count; i++){
- if(PsTagEntry[i].TagId == 1){
- BDADDR_Present = true;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR is present in Patch File \r\n"));
-
- }
- if(PsTagEntry[i].TagLen % 2 == 1){
- Total_tag_lenght = Total_tag_lenght + PsTagEntry[i].TagLen + 1;
- }
- else{
- Total_tag_lenght = Total_tag_lenght + PsTagEntry[i].TagLen;
- }
-
- }
- }
-
- if(Tag_Count > 0 && !BDADDR_Present){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR is not present adding 10 extra bytes \r\n"));
- Total_tag_lenght=Total_tag_lenght + 10;
- }
- Total_tag_lenght = Total_tag_lenght+ 10 + (Tag_Count*4);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Total Length %d\n",Total_tag_lenght));
-
-
- return status;
-}
-char *AthGetLine(char *buffer, int maxlen, u8 *srcbuffer,u32 len,u32 *pos)
-{
-
- int count;
- static short flag;
- char CharRead;
- count = 0;
- flag = A_ERROR;
-
- do
- {
- CharRead = AthReadChar(srcbuffer,len,pos);
- if( CharRead == '\0' ) {
- buffer[count+1] = '\0';
- if(count == 0) {
- return NULL;
- }
- else {
- return buffer;
- }
- }
-
- if(CharRead == 13) {
- } else if(CharRead == 10) {
- buffer[count] ='\0';
- flag = A_ERROR;
- return buffer;
- }else {
- buffer[count++] = CharRead;
- }
-
- }
- while(count < maxlen-1 && CharRead != '\0');
- buffer[count] = '\0';
-
- return buffer;
-}
-
-static void LoadHeader(u8 *HCI_PS_Command,u8 opcode,int length,int index){
-
- HCI_PS_Command[0]= 0x0B;
- HCI_PS_Command[1]= 0xFC;
- HCI_PS_Command[2]= length + 4;
- HCI_PS_Command[3]= opcode;
- HCI_PS_Command[4]= (index & 0xFF);
- HCI_PS_Command[5]= ((index>>8) & 0xFF);
- HCI_PS_Command[6]= length;
-}
-
-/////////////////////////
-//
-int AthCreateCommandList(struct ps_cmd_packet **HciPacketList, u32 *numPackets)
-{
-
- u8 count;
- u32 NumcmdEntry = 0;
-
- u32 Crc = 0;
- *numPackets = 0;
-
-
- if(Patch_Count > 0)
- Crc |= RAM_PATCH_REGION;
- if(Tag_Count > 0)
- Crc |= RAM_PS_REGION;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("PS Thread Started CRC %x Patch Count %d Tag Count %d \n",Crc,Patch_Count,Tag_Count));
-
- if(Patch_Count || Tag_Count ){
- NumcmdEntry+=(2 + Patch_Count + Tag_Count); /* CRC Packet + PS Reset Packet + Patch List + PS List*/
- if(Patch_Count > 0) {
- NumcmdEntry++; /* Patch Enable Command */
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Num Cmd Entries %d Size %d \r\n",NumcmdEntry,(u32)sizeof(struct ps_cmd_packet) * NumcmdEntry));
- (*HciPacketList) = A_MALLOC(sizeof(struct ps_cmd_packet) * NumcmdEntry);
- if(NULL == *HciPacketList) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("memory allocation failed \r\n"));
- }
- AthPSCreateHCICommand(PS_VERIFY_CRC,Crc,*HciPacketList,numPackets);
- if(Patch_Count > 0){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Write Patch**** \r\n"));
- AthPSCreateHCICommand(WRITE_PATCH,Patch_Count,*HciPacketList,numPackets);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Enable Patch**** \r\n"));
- AthPSCreateHCICommand(ENABLE_PATCH,0,*HciPacketList,numPackets);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Reset**** %d[0x%x] \r\n",PS_RAM_SIZE,PS_RAM_SIZE));
- AthPSCreateHCICommand(PS_RESET,PS_RAM_SIZE,*HciPacketList,numPackets);
- if(Tag_Count > 0){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Write**** \r\n"));
- AthPSCreateHCICommand(PS_WRITE,Tag_Count,*HciPacketList,numPackets);
- }
- }
- if(!BDADDR){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR not present \r\n"));
-
- }
- for(count = 0; count < Patch_Count; count++) {
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Freeing Patch Buffer %d \r\n",count));
- kfree(RamPatch[count].Data);
- }
-
- for(count = 0; count < Tag_Count; count++) {
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Freeing PS Buffer %d \r\n",count));
- kfree(PsTagEntry[count].TagData);
- }
-
-/*
- * SDIO Transport uses synchronous mode of data transfer
- * So, AthPSOperations() call returns only after receiving the
- * command complete event.
- */
- return *numPackets;
-}
-
-
-////////////////////////
-
-/////////////
-static int AthPSCreateHCICommand(u8 Opcode, u32 Param1,struct ps_cmd_packet *PSPatchPacket,u32 *index)
-{
- u8 *HCI_PS_Command;
- u32 Length;
- int i,j;
-
- switch(Opcode)
- {
- case WRITE_PATCH:
-
-
- for(i=0;i< Param1;i++){
-
- HCI_PS_Command = (u8 *) A_MALLOC(RamPatch[i].Len+HCI_COMMAND_HEADER);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Allocated Buffer Size %d\n",RamPatch[i].Len+HCI_COMMAND_HEADER));
- if(HCI_PS_Command == NULL){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
- return A_ERROR;
- }
- memset (HCI_PS_Command, 0, RamPatch[i].Len+HCI_COMMAND_HEADER);
- LoadHeader(HCI_PS_Command,Opcode,RamPatch[i].Len,i);
- for(j=0;j<RamPatch[i].Len;j++){
- HCI_PS_Command[HCI_COMMAND_HEADER+j]=RamPatch[i].Data[j];
- }
- PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
- PSPatchPacket[*index].packetLen = RamPatch[i].Len+HCI_COMMAND_HEADER;
- (*index)++;
-
-
- }
-
- break;
-
- case ENABLE_PATCH:
-
-
- Length = 0;
- i= 0;
- HCI_PS_Command = (u8 *) A_MALLOC(Length+HCI_COMMAND_HEADER);
- if(HCI_PS_Command == NULL){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
- return A_ERROR;
- }
-
- memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER);
- LoadHeader(HCI_PS_Command,Opcode,Length,i);
- PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
- PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER;
- (*index)++;
-
- break;
-
- case PS_RESET:
- Length = 0x06;
- i=0;
- HCI_PS_Command = (u8 *) A_MALLOC(Length+HCI_COMMAND_HEADER);
- if(HCI_PS_Command == NULL){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
- return A_ERROR;
- }
- memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER);
- LoadHeader(HCI_PS_Command,Opcode,Length,i);
- HCI_PS_Command[7]= 0x00;
- HCI_PS_Command[Length+HCI_COMMAND_HEADER -2]= (Param1 & 0xFF);
- HCI_PS_Command[Length+HCI_COMMAND_HEADER -1]= ((Param1 >> 8) & 0xFF);
- PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
- PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER;
- (*index)++;
-
- break;
-
- case PS_WRITE:
- for(i=0;i< Param1;i++){
- if(PsTagEntry[i].TagId ==1)
- BDADDR = true;
-
- HCI_PS_Command = (u8 *) A_MALLOC(PsTagEntry[i].TagLen+HCI_COMMAND_HEADER);
- if(HCI_PS_Command == NULL){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
- return A_ERROR;
- }
-
- memset (HCI_PS_Command, 0, PsTagEntry[i].TagLen+HCI_COMMAND_HEADER);
- LoadHeader(HCI_PS_Command,Opcode,PsTagEntry[i].TagLen,PsTagEntry[i].TagId);
-
- for(j=0;j<PsTagEntry[i].TagLen;j++){
- HCI_PS_Command[HCI_COMMAND_HEADER+j]=PsTagEntry[i].TagData[j];
- }
-
- PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
- PSPatchPacket[*index].packetLen = PsTagEntry[i].TagLen+HCI_COMMAND_HEADER;
- (*index)++;
-
- }
-
- break;
-
-
- case PS_VERIFY_CRC:
- Length = 0x0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("VALUE of CRC:%d At index %d\r\n",Param1,*index));
-
- HCI_PS_Command = (u8 *) A_MALLOC(Length+HCI_COMMAND_HEADER);
- if(HCI_PS_Command == NULL){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
- return A_ERROR;
- }
- memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER);
- LoadHeader(HCI_PS_Command,Opcode,Length,Param1);
-
- PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
- PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER;
- (*index)++;
-
- break;
-
- case CHANGE_BDADDR:
- break;
- }
- return 0;
-}
-int AthFreeCommandList(struct ps_cmd_packet **HciPacketList, u32 numPackets)
-{
- int i;
- if(*HciPacketList == NULL) {
- return A_ERROR;
- }
- for(i = 0; i < numPackets;i++) {
- kfree((*HciPacketList)[i].Hcipacket);
- }
- kfree(*HciPacketList);
- return 0;
-}
diff --git a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h
deleted file mode 100644
index 4e0f2f713a40..000000000000
--- a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h
+++ /dev/null
@@ -1,113 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file is the include file for Atheros PS and patch parser.
-// It implements APIs to parse data buffer with patch and PS information and convert it to HCI commands.
-//
-
-#ifndef __AR3KPSPARSER_H
-#define __AR3KPSPARSER_H
-
-
-
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "athdefs.h"
-#ifdef HCI_TRANSPORT_SDIO
-#include "a_config.h"
-#include "a_osapi.h"
-#define ATH_MODULE_NAME misc
-#include "a_debug.h"
-#include "common_drv.h"
-#include "hci_transport_api.h"
-#include "ar3kconfig.h"
-#else
-#ifndef A_PRINTF
-#define A_PRINTF(args...) printk(KERN_ALERT args)
-#endif /* A_PRINTF */
-#include "debug_linux.h"
-
-/* Helper data type declaration */
-
-#define ATH_DEBUG_ERR (1 << 0)
-#define ATH_DEBUG_WARN (1 << 1)
-#define ATH_DEBUG_INFO (1 << 2)
-
-
-
-#define false 0
-#define true 1
-
-#ifndef A_MALLOC
-#define A_MALLOC(size) kmalloc((size),GFP_KERNEL)
-#endif /* A_MALLOC */
-#endif /* HCI_TRANSPORT_UART */
-
-/* String manipulation APIs */
-#ifndef A_STRTOUL
-#define A_STRTOUL simple_strtoul
-#endif /* A_STRTOL */
-
-#ifndef A_STRTOL
-#define A_STRTOL simple_strtol
-#endif /* A_STRTOL */
-
-
-/* The maximum number of bytes possible in a patch entry */
-#define MAX_PATCH_SIZE 20000
-
-/* Maximum HCI packets that will be formed from the Patch file */
-#define MAX_NUM_PATCH_ENTRY (MAX_PATCH_SIZE/MAX_BYTE_LENGTH) + 1
-
-
-
-
-
-
-
-struct ps_cmd_packet
-{
- u8 *Hcipacket;
- int packetLen;
-};
-
-/* Parses a Patch information buffer and store it in global structure */
-int AthDoParsePatch(u8 *, u32 );
-
-/* parses a PS information buffer and stores it in a global structure */
-int AthDoParsePS(u8 *, u32 );
-
-/*
- * Uses the output of Both AthDoParsePS and AthDoParsePatch APIs to form HCI command array with
- * all the PS and patch commands.
- * The list will have the below mentioned commands in order.
- * CRC command packet
- * Download patch command(s)
- * Enable patch Command
- * PS Reset Command
- * PS Tag Command(s)
- *
- */
-int AthCreateCommandList(struct ps_cmd_packet **, u32 *);
-
-/* Cleanup the dynamically allicated HCI command list */
-int AthFreeCommandList(struct ps_cmd_packet **HciPacketList, u32 numPackets);
-#endif /* __AR3KPSPARSER_H */
diff --git a/drivers/staging/ath6kl/miscdrv/common_drv.c b/drivers/staging/ath6kl/miscdrv/common_drv.c
deleted file mode 100644
index 1ce539aa019b..000000000000
--- a/drivers/staging/ath6kl/miscdrv/common_drv.c
+++ /dev/null
@@ -1,910 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="common_drv.c" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#include "a_config.h"
-#include "athdefs.h"
-
-#include "hw/mbox_host_reg.h"
-#include "gpio_reg.h"
-#include "hw/rtc_reg.h"
-#include "hw/mbox_reg.h"
-#include "hw/apb_map.h"
-
-#include "a_osapi.h"
-#include "targaddrs.h"
-#include "hif.h"
-#include "htc_api.h"
-#include "wmi.h"
-#include "bmi.h"
-#include "bmi_msg.h"
-#include "common_drv.h"
-#define ATH_MODULE_NAME misc
-#include "a_debug.h"
-#include "ar6000_diag.h"
-
-static ATH_DEBUG_MODULE_DBG_INFO *g_pModuleInfoHead = NULL;
-static A_MUTEX_T g_ModuleListLock;
-static bool g_ModuleDebugInit = false;
-
-#ifdef ATH_DEBUG_MODULE
-
-ATH_DEBUG_INSTANTIATE_MODULE_VAR(misc,
- "misc",
- "Common and misc APIs",
- ATH_DEBUG_MASK_DEFAULTS,
- 0,
- NULL);
-
-#endif
-
-#define HOST_INTEREST_ITEM_ADDRESS(target, item) \
- ((((target) == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \
- (((target) == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0)))
-
-
-#define AR6001_LOCAL_COUNT_ADDRESS 0x0c014080
-#define AR6002_LOCAL_COUNT_ADDRESS 0x00018080
-#define AR6003_LOCAL_COUNT_ADDRESS 0x00018080
-#define CPU_DBG_SEL_ADDRESS 0x00000483
-#define CPU_DBG_ADDRESS 0x00000484
-
-static u8 custDataAR6002[AR6002_CUST_DATA_SIZE];
-static u8 custDataAR6003[AR6003_CUST_DATA_SIZE];
-
-/* Compile the 4BYTE version of the window register setup routine,
- * This mitigates host interconnect issues with non-4byte aligned bus requests, some
- * interconnects use bus adapters that impose strict limitations.
- * Since diag window access is not intended for performance critical operations, the 4byte mode should
- * be satisfactory even though it generates 4X the bus activity. */
-
-#ifdef USE_4BYTE_REGISTER_ACCESS
-
- /* set the window address register (using 4-byte register access ). */
-int ar6000_SetAddressWindowRegister(struct hif_device *hifDevice, u32 RegisterAddr, u32 Address)
-{
- int status;
- u8 addrValue[4];
- s32 i;
-
- /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
- * last to initiate the access cycle */
-
- for (i = 1; i <= 3; i++) {
- /* fill the buffer with the address byte value we want to hit 4 times*/
- addrValue[0] = ((u8 *)&Address)[i];
- addrValue[1] = addrValue[0];
- addrValue[2] = addrValue[0];
- addrValue[3] = addrValue[0];
-
- /* hit each byte of the register address with a 4-byte write operation to the same address,
- * this is a harmless operation */
- status = HIFReadWrite(hifDevice,
- RegisterAddr+i,
- addrValue,
- 4,
- HIF_WR_SYNC_BYTE_FIX,
- NULL);
- if (status) {
- break;
- }
- }
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
- Address, RegisterAddr));
- return status;
- }
-
- /* write the address register again, this time write the whole 4-byte value.
- * The effect here is that the LSB write causes the cycle to start, the extra
- * 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */
- status = HIFReadWrite(hifDevice,
- RegisterAddr,
- (u8 *)(&Address),
- 4,
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
- Address, RegisterAddr));
- return status;
- }
-
- return 0;
-
-
-
-}
-
-
-#else
-
- /* set the window address register */
-int ar6000_SetAddressWindowRegister(struct hif_device *hifDevice, u32 RegisterAddr, u32 Address)
-{
- int status;
-
- /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
- * last to initiate the access cycle */
- status = HIFReadWrite(hifDevice,
- RegisterAddr+1, /* write upper 3 bytes */
- ((u8 *)(&Address))+1,
- sizeof(u32)-1,
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
- RegisterAddr, Address));
- return status;
- }
-
- /* write the LSB of the register, this initiates the operation */
- status = HIFReadWrite(hifDevice,
- RegisterAddr,
- (u8 *)(&Address),
- sizeof(u8),
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
- RegisterAddr, Address));
- return status;
- }
-
- return 0;
-}
-
-#endif
-
-/*
- * Read from the AR6000 through its diagnostic window.
- * No cooperation from the Target is required for this.
- */
-int
-ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data)
-{
- int status;
-
- /* set window register to start read cycle */
- status = ar6000_SetAddressWindowRegister(hifDevice,
- WINDOW_READ_ADDR_ADDRESS,
- *address);
-
- if (status) {
- return status;
- }
-
- /* read the data */
- status = HIFReadWrite(hifDevice,
- WINDOW_DATA_ADDRESS,
- (u8 *)data,
- sizeof(u32),
- HIF_RD_SYNC_BYTE_INC,
- NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n"));
- return status;
- }
-
- return status;
-}
-
-
-/*
- * Write to the AR6000 through its diagnostic window.
- * No cooperation from the Target is required for this.
- */
-int
-ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data)
-{
- int status;
-
- /* set write data */
- status = HIFReadWrite(hifDevice,
- WINDOW_DATA_ADDRESS,
- (u8 *)data,
- sizeof(u32),
- HIF_WR_SYNC_BYTE_INC,
- NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data));
- return status;
- }
-
- /* set window register, which starts the write cycle */
- return ar6000_SetAddressWindowRegister(hifDevice,
- WINDOW_WRITE_ADDR_ADDRESS,
- *address);
- }
-
-int
-ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address,
- u8 *data, u32 length)
-{
- u32 count;
- int status = 0;
-
- for (count = 0; count < length; count += 4, address += 4) {
- if ((status = ar6000_ReadRegDiag(hifDevice, &address,
- (u32 *)&data[count])) != 0)
- {
- break;
- }
- }
-
- return status;
-}
-
-int
-ar6000_WriteDataDiag(struct hif_device *hifDevice, u32 address,
- u8 *data, u32 length)
-{
- u32 count;
- int status = 0;
-
- for (count = 0; count < length; count += 4, address += 4) {
- if ((status = ar6000_WriteRegDiag(hifDevice, &address,
- (u32 *)&data[count])) != 0)
- {
- break;
- }
- }
-
- return status;
-}
-
-int
-ar6k_ReadTargetRegister(struct hif_device *hifDevice, int regsel, u32 *regval)
-{
- int status;
- u8 vals[4];
- u8 register_selection[4];
-
- register_selection[0] = register_selection[1] = register_selection[2] = register_selection[3] = (regsel & 0xff);
- status = HIFReadWrite(hifDevice,
- CPU_DBG_SEL_ADDRESS,
- register_selection,
- 4,
- HIF_WR_SYNC_BYTE_FIX,
- NULL);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write CPU_DBG_SEL (%d)\n", regsel));
- return status;
- }
-
- status = HIFReadWrite(hifDevice,
- CPU_DBG_ADDRESS,
- (u8 *)vals,
- sizeof(vals),
- HIF_RD_SYNC_BYTE_INC,
- NULL);
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from CPU_DBG_ADDRESS\n"));
- return status;
- }
-
- *regval = vals[0]<<0 | vals[1]<<8 | vals[2]<<16 | vals[3]<<24;
-
- return status;
-}
-
-void
-ar6k_FetchTargetRegs(struct hif_device *hifDevice, u32 *targregs)
-{
- int i;
- u32 val;
-
- for (i=0; i<AR6003_FETCH_TARG_REGS_COUNT; i++) {
- val=0xffffffff;
- (void)ar6k_ReadTargetRegister(hifDevice, i, &val);
- targregs[i] = val;
- }
-}
-
-#if 0
-static int
-_do_write_diag(struct hif_device *hifDevice, u32 addr, u32 value)
-{
- int status;
-
- status = ar6000_WriteRegDiag(hifDevice, &addr, &value);
- if (status)
- {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot force Target to execute ROM!\n"));
- }
-
- return status;
-}
-#endif
-
-
-/*
- * Delay up to wait_msecs millisecs to allow Target to enter BMI phase,
- * which is a good sign that it's alive and well. This is used after
- * explicitly forcing the Target to reset.
- *
- * The wait_msecs time should be sufficiently long to cover any reasonable
- * boot-time delay. For instance, AR6001 firmware allow one second for a
- * low frequency crystal to settle before it calibrates the refclk frequency.
- *
- * TBD: Might want to add special handling for AR6K_OPTION_BMI_DISABLE.
- */
-#if 0
-static int
-_delay_until_target_alive(struct hif_device *hifDevice, s32 wait_msecs, u32 TargetType)
-{
- s32 actual_wait;
- s32 i;
- u32 address;
-
- actual_wait = 0;
-
- /* Hardcode the address of LOCAL_COUNT_ADDRESS based on the target type */
- if (TargetType == TARGET_TYPE_AR6002) {
- address = AR6002_LOCAL_COUNT_ADDRESS;
- } else if (TargetType == TARGET_TYPE_AR6003) {
- address = AR6003_LOCAL_COUNT_ADDRESS;
- } else {
- A_ASSERT(0);
- }
- address += 0x10;
- for (i=0; actual_wait < wait_msecs; i++) {
- u32 data;
-
- A_MDELAY(100);
- actual_wait += 100;
-
- data = 0;
- if (ar6000_ReadRegDiag(hifDevice, &address, &data) != 0) {
- return A_ERROR;
- }
-
- if (data != 0) {
- /* No need to wait longer -- we have a BMI credit */
- return 0;
- }
- }
- return A_ERROR; /* timed out */
-}
-#endif
-
-#define AR6001_RESET_CONTROL_ADDRESS 0x0C000000
-#define AR6002_RESET_CONTROL_ADDRESS 0x00004000
-#define AR6003_RESET_CONTROL_ADDRESS 0x00004000
-/* reset device */
-int ar6000_reset_device(struct hif_device *hifDevice, u32 TargetType, bool waitForCompletion, bool coldReset)
-{
- int status = 0;
- u32 address;
- u32 data;
-
- do {
-// Workaround BEGIN
- // address = RESET_CONTROL_ADDRESS;
-
- if (coldReset) {
- data = RESET_CONTROL_COLD_RST_MASK;
- }
- else {
- data = RESET_CONTROL_MBOX_RST_MASK;
- }
-
- /* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */
- if (TargetType == TARGET_TYPE_AR6002) {
- address = AR6002_RESET_CONTROL_ADDRESS;
- } else if (TargetType == TARGET_TYPE_AR6003) {
- address = AR6003_RESET_CONTROL_ADDRESS;
- } else {
- A_ASSERT(0);
- }
-
-
- status = ar6000_WriteRegDiag(hifDevice, &address, &data);
-
- if (status) {
- break;
- }
-
- if (!waitForCompletion) {
- break;
- }
-
-#if 0
- /* Up to 2 second delay to allow things to settle down */
- (void)_delay_until_target_alive(hifDevice, 2000, TargetType);
-
- /*
- * Read back the RESET CAUSE register to ensure that the cold reset
- * went through.
- */
-
- // address = RESET_CAUSE_ADDRESS;
- /* Hardcode the address of RESET_CAUSE_ADDRESS based on the target type */
- if (TargetType == TARGET_TYPE_AR6002) {
- address = 0x000040C0;
- } else if (TargetType == TARGET_TYPE_AR6003) {
- address = 0x000040C0;
- } else {
- A_ASSERT(0);
- }
-
- data = 0;
- status = ar6000_ReadRegDiag(hifDevice, &address, &data);
-
- if (status) {
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data));
- data &= RESET_CAUSE_LAST_MASK;
- if (data != 2) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n"));
- }
-#endif
-// Workaroud END
-
- } while (false);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
- }
-
- return 0;
-}
-
-/* This should be called in BMI phase after firmware is downloaded */
-void
-ar6000_copy_cust_data_from_target(struct hif_device *hifDevice, u32 TargetType)
-{
- u32 eepHeaderAddr;
- u8 AR6003CustDataShadow[AR6003_CUST_DATA_SIZE+4];
- s32 i;
-
- if (BMIReadMemory(hifDevice,
- HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_board_data),
- (u8 *)&eepHeaderAddr,
- 4)!= 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadMemory for reading board data address failed \n"));
- return;
- }
-
- if (TargetType == TARGET_TYPE_AR6003) {
- eepHeaderAddr += 36; /* AR6003 customer data section offset is 37 */
-
- for (i=0; i<AR6003_CUST_DATA_SIZE+4; i+=4){
- if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (u32 *)&AR6003CustDataShadow[i])!= 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n"));
- return ;
- }
- eepHeaderAddr +=4;
- }
-
- memcpy(custDataAR6003, AR6003CustDataShadow+1, AR6003_CUST_DATA_SIZE);
- }
-
- if (TargetType == TARGET_TYPE_AR6002) {
- eepHeaderAddr += 64; /* AR6002 customer data sectioin offset is 64 */
-
- for (i=0; i<AR6002_CUST_DATA_SIZE; i+=4){
- if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (u32 *)&custDataAR6002[i])!= 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n"));
- return ;
- }
- eepHeaderAddr +=4;
- }
- }
-
- return;
-}
-
-/* This is the function to call when need to use the cust data */
-u8 *ar6000_get_cust_data_buffer(u32 TargetType)
-{
- if (TargetType == TARGET_TYPE_AR6003)
- return custDataAR6003;
-
- if (TargetType == TARGET_TYPE_AR6002)
- return custDataAR6002;
-
- return NULL;
-}
-
-#define REG_DUMP_COUNT_AR6001 38 /* WORDs, derived from AR600x_regdump.h */
-#define REG_DUMP_COUNT_AR6002 60
-#define REG_DUMP_COUNT_AR6003 60
-#define REGISTER_DUMP_LEN_MAX 60
-#if REG_DUMP_COUNT_AR6001 > REGISTER_DUMP_LEN_MAX
-#error "REG_DUMP_COUNT_AR6001 too large"
-#endif
-#if REG_DUMP_COUNT_AR6002 > REGISTER_DUMP_LEN_MAX
-#error "REG_DUMP_COUNT_AR6002 too large"
-#endif
-#if REG_DUMP_COUNT_AR6003 > REGISTER_DUMP_LEN_MAX
-#error "REG_DUMP_COUNT_AR6003 too large"
-#endif
-
-
-void ar6000_dump_target_assert_info(struct hif_device *hifDevice, u32 TargetType)
-{
- u32 address;
- u32 regDumpArea = 0;
- int status;
- u32 regDumpValues[REGISTER_DUMP_LEN_MAX];
- u32 regDumpCount = 0;
- u32 i;
-
- do {
-
- /* the reg dump pointer is copied to the host interest area */
- address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state);
- address = TARG_VTOP(TargetType, address);
-
- if (TargetType == TARGET_TYPE_AR6002) {
- regDumpCount = REG_DUMP_COUNT_AR6002;
- } else if (TargetType == TARGET_TYPE_AR6003) {
- regDumpCount = REG_DUMP_COUNT_AR6003;
- } else {
- A_ASSERT(0);
- }
-
- /* read RAM location through diagnostic window */
- status = ar6000_ReadRegDiag(hifDevice, &address, &regDumpArea);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea));
-
- if (regDumpArea == 0) {
- /* no reg dump */
- break;
- }
-
- regDumpArea = TARG_VTOP(TargetType, regDumpArea);
-
- /* fetch register dump data */
- status = ar6000_ReadDataDiag(hifDevice,
- regDumpArea,
- (u8 *)&regDumpValues[0],
- regDumpCount * (sizeof(u32)));
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
- break;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n"));
-
- for (i = 0; i < regDumpCount; i++) {
- //ATHR_DISPLAY_MSG (_T(" %d : 0x%8.8X \n"), i, regDumpValues[i]);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d : 0x%8.8X \n",i, regDumpValues[i]));
-
-#ifdef UNDER_CE
- /*
- * For Every logPrintf() Open the File so that in case of Crashes
- * We will have until the Last Message Flushed on to the File
- * So use logPrintf Sparingly..!!
- */
- tgtassertPrintf (ATH_DEBUG_TRC," %d: 0x%8.8X \n",i, regDumpValues[i]);
-#endif
- }
-
- } while (false);
-
-}
-
-/* set HTC/Mbox operational parameters, this can only be called when the target is in the
- * BMI phase */
-int ar6000_set_htc_params(struct hif_device *hifDevice,
- u32 TargetType,
- u32 MboxIsrYieldValue,
- u8 HtcControlBuffers)
-{
- int status;
- u32 blocksizes[HTC_MAILBOX_NUM_MAX];
-
- do {
- /* get the block sizes */
- status = HIFConfigureDevice(hifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
- blocksizes, sizeof(blocksizes));
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR,("Failed to get block size info from HIF layer...\n"));
- break;
- }
- /* note: we actually get the block size for mailbox 1, for SDIO the block
- * size on mailbox 0 is artificially set to 1 */
- /* must be a power of 2 */
- A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0);
-
- if (HtcControlBuffers != 0) {
- /* set override for number of control buffers to use */
- blocksizes[1] |= ((u32)HtcControlBuffers) << 16;
- }
-
- /* set the host interest area for the block size */
- status = BMIWriteMemory(hifDevice,
- HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz),
- (u8 *)&blocksizes[1],
- 4);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for IO block size failed \n"));
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_LOG_INF,("Block Size Set: %d (target address:0x%X)\n",
- blocksizes[1], HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz)));
-
- if (MboxIsrYieldValue != 0) {
- /* set the host interest area for the mbox ISR yield limit */
- status = BMIWriteMemory(hifDevice,
- HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_isr_yield_limit),
- (u8 *)&MboxIsrYieldValue,
- 4);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for yield limit failed \n"));
- break;
- }
- }
-
- } while (false);
-
- return status;
-}
-
-void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription)
-{
- char stream[60];
- char byteOffsetStr[10];
- u32 i;
- u16 offset, count, byteOffset;
-
- A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length, pDescription);
-
- count = 0;
- offset = 0;
- byteOffset = 0;
- for(i = 0; i < length; i++) {
- A_SPRINTF(stream + offset, "%2.2X ", buffer[i]);
- count ++;
- offset += 3;
-
- if(count == 16) {
- count = 0;
- offset = 0;
- A_SPRINTF(byteOffsetStr,"%4.4X",byteOffset);
- A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
- A_MEMZERO(stream, 60);
- byteOffset += 16;
- }
- }
-
- if(offset != 0) {
- A_SPRINTF(byteOffsetStr,"%4.4X",byteOffset);
- A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
- }
-
- A_PRINTF("<------------------------------------------------->\n");
-}
-
-void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo)
-{
- int i;
- struct ath_debug_mask_description *pDesc;
-
- if (pInfo == NULL) {
- return;
- }
-
- pDesc = pInfo->pMaskDescriptions;
-
- A_PRINTF("========================================================\n\n");
- A_PRINTF("Module Debug Info => Name : %s \n", pInfo->ModuleName);
- A_PRINTF(" => Descr. : %s \n", pInfo->ModuleDescription);
- A_PRINTF("\n Current mask => 0x%8.8X \n", pInfo->CurrentMask);
- A_PRINTF("\n Avail. Debug Masks :\n\n");
-
- for (i = 0; i < pInfo->MaxDescriptions; i++,pDesc++) {
- A_PRINTF(" => 0x%8.8X -- %s \n", pDesc->Mask, pDesc->Description);
- }
-
- if (0 == i) {
- A_PRINTF(" => * none defined * \n");
- }
-
- A_PRINTF("\n Standard Debug Masks :\n\n");
- /* print standard masks */
- A_PRINTF(" => 0x%8.8X -- Errors \n", ATH_DEBUG_ERR);
- A_PRINTF(" => 0x%8.8X -- Warnings \n", ATH_DEBUG_WARN);
- A_PRINTF(" => 0x%8.8X -- Informational \n", ATH_DEBUG_INFO);
- A_PRINTF(" => 0x%8.8X -- Tracing \n", ATH_DEBUG_TRC);
- A_PRINTF("\n========================================================\n");
-
-}
-
-
-static ATH_DEBUG_MODULE_DBG_INFO *FindModule(char *module_name)
-{
- ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead;
-
- if (!g_ModuleDebugInit) {
- return NULL;
- }
-
- while (pInfo != NULL) {
- /* TODO: need to use something other than strlen */
- if (memcmp(pInfo->ModuleName,module_name,strlen(module_name)) == 0) {
- break;
- }
- pInfo = pInfo->pNext;
- }
-
- return pInfo;
-}
-
-
-void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo)
-{
- if (!g_ModuleDebugInit) {
- return;
- }
-
- A_MUTEX_LOCK(&g_ModuleListLock);
-
- if (!(pInfo->Flags & ATH_DEBUG_INFO_FLAGS_REGISTERED)) {
- if (g_pModuleInfoHead == NULL) {
- g_pModuleInfoHead = pInfo;
- } else {
- pInfo->pNext = g_pModuleInfoHead;
- g_pModuleInfoHead = pInfo;
- }
- pInfo->Flags |= ATH_DEBUG_INFO_FLAGS_REGISTERED;
- }
-
- A_MUTEX_UNLOCK(&g_ModuleListLock);
-}
-
-void a_dump_module_debug_info_by_name(char *module_name)
-{
- ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead;
-
- if (!g_ModuleDebugInit) {
- return;
- }
-
- if (memcmp(module_name,"all",3) == 0) {
- /* dump all */
- while (pInfo != NULL) {
- a_dump_module_debug_info(pInfo);
- pInfo = pInfo->pNext;
- }
- return;
- }
-
- pInfo = FindModule(module_name);
-
- if (pInfo != NULL) {
- a_dump_module_debug_info(pInfo);
- }
-
-}
-
-int a_get_module_mask(char *module_name, u32 *pMask)
-{
- ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name);
-
- if (NULL == pInfo) {
- return A_ERROR;
- }
-
- *pMask = pInfo->CurrentMask;
- return 0;
-}
-
-int a_set_module_mask(char *module_name, u32 Mask)
-{
- ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name);
-
- if (NULL == pInfo) {
- return A_ERROR;
- }
-
- pInfo->CurrentMask = Mask;
- A_PRINTF("Module %s, new mask: 0x%8.8X \n",module_name,pInfo->CurrentMask);
- return 0;
-}
-
-
-void a_module_debug_support_init(void)
-{
- if (g_ModuleDebugInit) {
- return;
- }
- A_MUTEX_INIT(&g_ModuleListLock);
- g_pModuleInfoHead = NULL;
- g_ModuleDebugInit = true;
- A_REGISTER_MODULE_DEBUG_INFO(misc);
-}
-
-void a_module_debug_support_cleanup(void)
-{
- ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead;
- ATH_DEBUG_MODULE_DBG_INFO *pCur;
-
- if (!g_ModuleDebugInit) {
- return;
- }
-
- g_ModuleDebugInit = false;
-
- A_MUTEX_LOCK(&g_ModuleListLock);
-
- while (pInfo != NULL) {
- pCur = pInfo;
- pInfo = pInfo->pNext;
- pCur->pNext = NULL;
- /* clear registered flag */
- pCur->Flags &= ~ATH_DEBUG_INFO_FLAGS_REGISTERED;
- }
-
- A_MUTEX_UNLOCK(&g_ModuleListLock);
-
- A_MUTEX_DELETE(&g_ModuleListLock);
- g_pModuleInfoHead = NULL;
-}
-
- /* can only be called during bmi init stage */
-int ar6000_set_hci_bridge_flags(struct hif_device *hifDevice,
- u32 TargetType,
- u32 Flags)
-{
- int status = 0;
-
- do {
-
- if (TargetType != TARGET_TYPE_AR6003) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Target Type:%d, does not support HCI bridging! \n",
- TargetType));
- break;
- }
-
- /* set hci bridge flags */
- status = BMIWriteMemory(hifDevice,
- HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_hci_bridge_flags),
- (u8 *)&Flags,
- 4);
-
-
- } while (false);
-
- return status;
-}
-
diff --git a/drivers/staging/ath6kl/miscdrv/credit_dist.c b/drivers/staging/ath6kl/miscdrv/credit_dist.c
deleted file mode 100644
index c777e98a756e..000000000000
--- a/drivers/staging/ath6kl/miscdrv/credit_dist.c
+++ /dev/null
@@ -1,417 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="credit_dist.c" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_osapi.h"
-#define ATH_MODULE_NAME misc
-#include "a_debug.h"
-#include "htc_api.h"
-#include "common_drv.h"
-
-/********* CREDIT DISTRIBUTION FUNCTIONS ******************************************/
-
-#define NO_VO_SERVICE 1 /* currently WMI only uses 3 data streams, so we leave VO service inactive */
-#define CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS 1
-
-#ifdef NO_VO_SERVICE
-#define DATA_SVCS_USED 3
-#else
-#define DATA_SVCS_USED 4
-#endif
-
-static void RedistributeCredits(struct common_credit_state_info *pCredInfo,
- struct htc_endpoint_credit_dist *pEPDistList);
-
-static void SeekCredits(struct common_credit_state_info *pCredInfo,
- struct htc_endpoint_credit_dist *pEPDistList);
-
-/* reduce an ep's credits back to a set limit */
-static INLINE void ReduceCredits(struct common_credit_state_info *pCredInfo,
- struct htc_endpoint_credit_dist *pEpDist,
- int Limit)
-{
- int credits;
-
- /* set the new limit */
- pEpDist->TxCreditsAssigned = Limit;
-
- if (pEpDist->TxCredits <= Limit) {
- return;
- }
-
- /* figure out how much to take away */
- credits = pEpDist->TxCredits - Limit;
- /* take them away */
- pEpDist->TxCredits -= credits;
- pCredInfo->CurrentFreeCredits += credits;
-}
-
-/* give an endpoint some credits from the free credit pool */
-#define GiveCredits(pCredInfo,pEpDist,credits) \
-{ \
- (pEpDist)->TxCredits += (credits); \
- (pEpDist)->TxCreditsAssigned += (credits); \
- (pCredInfo)->CurrentFreeCredits -= (credits); \
-}
-
-
-/* default credit init callback.
- * This function is called in the context of HTCStart() to setup initial (application-specific)
- * credit distributions */
-static void ar6000_credit_init(void *Context,
- struct htc_endpoint_credit_dist *pEPList,
- int TotalCredits)
-{
- struct htc_endpoint_credit_dist *pCurEpDist;
- int count;
- struct common_credit_state_info *pCredInfo = (struct common_credit_state_info *)Context;
-
- pCredInfo->CurrentFreeCredits = TotalCredits;
- pCredInfo->TotalAvailableCredits = TotalCredits;
-
- pCurEpDist = pEPList;
-
- /* run through the list and initialize */
- while (pCurEpDist != NULL) {
-
- /* set minimums for each endpoint */
- pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg;
-
-#ifdef CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS
-
- if (TotalCredits > 4)
- {
- if ((pCurEpDist->ServiceID == WMI_DATA_BK_SVC) || (pCurEpDist->ServiceID == WMI_DATA_BE_SVC)){
- /* assign at least min credits to lower than VO priority services */
- GiveCredits(pCredInfo,pCurEpDist,pCurEpDist->TxCreditsMin);
- /* force active */
- SET_EP_ACTIVE(pCurEpDist);
- }
- }
-
-#endif
-
- if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) {
- /* give control service some credits */
- GiveCredits(pCredInfo,pCurEpDist,pCurEpDist->TxCreditsMin);
- /* control service is always marked active, it never goes inactive EVER */
- SET_EP_ACTIVE(pCurEpDist);
- } else if (pCurEpDist->ServiceID == WMI_DATA_BK_SVC) {
- /* this is the lowest priority data endpoint, save this off for easy access */
- pCredInfo->pLowestPriEpDist = pCurEpDist;
- }
-
- /* Streams have to be created (explicit | implicit)for all kinds
- * of traffic. BE endpoints are also inactive in the beginning.
- * When BE traffic starts it creates implicit streams that
- * redistributes credits.
- */
-
- /* note, all other endpoints have minimums set but are initially given NO credits.
- * Credits will be distributed as traffic activity demands */
- pCurEpDist = pCurEpDist->pNext;
- }
-
- if (pCredInfo->CurrentFreeCredits <= 0) {
- AR_DEBUG_PRINTF(ATH_LOG_INF, ("Not enough credits (%d) to do credit distributions \n", TotalCredits));
- A_ASSERT(false);
- return;
- }
-
- /* reset list */
- pCurEpDist = pEPList;
- /* now run through the list and set max operating credit limits for everyone */
- while (pCurEpDist != NULL) {
- if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) {
- /* control service max is just 1 max message */
- pCurEpDist->TxCreditsNorm = pCurEpDist->TxCreditsPerMaxMsg;
- } else {
- /* for the remaining data endpoints, we assume that each TxCreditsPerMaxMsg are
- * the same.
- * We use a simple calculation here, we take the remaining credits and
- * determine how many max messages this can cover and then set each endpoint's
- * normal value equal to 3/4 this amount.
- * */
- count = (pCredInfo->CurrentFreeCredits/pCurEpDist->TxCreditsPerMaxMsg) * pCurEpDist->TxCreditsPerMaxMsg;
- count = (count * 3) >> 2;
- count = max(count,pCurEpDist->TxCreditsPerMaxMsg);
- /* set normal */
- pCurEpDist->TxCreditsNorm = count;
-
- }
- pCurEpDist = pCurEpDist->pNext;
- }
-
-}
-
-
-/* default credit distribution callback
- * This callback is invoked whenever endpoints require credit distributions.
- * A lock is held while this function is invoked, this function shall NOT block.
- * The pEPDistList is a list of distribution structures in prioritized order as
- * defined by the call to the HTCSetCreditDistribution() api.
- *
- */
-static void ar6000_credit_distribute(void *Context,
- struct htc_endpoint_credit_dist *pEPDistList,
- HTC_CREDIT_DIST_REASON Reason)
-{
- struct htc_endpoint_credit_dist *pCurEpDist;
- struct common_credit_state_info *pCredInfo = (struct common_credit_state_info *)Context;
-
- switch (Reason) {
- case HTC_CREDIT_DIST_SEND_COMPLETE :
- pCurEpDist = pEPDistList;
- /* we are given the start of the endpoint distribution list.
- * There may be one or more endpoints to service.
- * Run through the list and distribute credits */
- while (pCurEpDist != NULL) {
-
- if (pCurEpDist->TxCreditsToDist > 0) {
- /* return the credits back to the endpoint */
- pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist;
- /* always zero out when we are done */
- pCurEpDist->TxCreditsToDist = 0;
-
- if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsAssigned) {
- /* reduce to the assigned limit, previous credit reductions
- * could have caused the limit to change */
- ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsAssigned);
- }
-
- if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsNorm) {
- /* oversubscribed endpoints need to reduce back to normal */
- ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsNorm);
- }
-
- if (!IS_EP_ACTIVE(pCurEpDist)) {
- /* endpoint is inactive, now check for messages waiting for credits */
- if (pCurEpDist->TxQueueDepth == 0) {
- /* EP is inactive and there are no pending messages,
- * reduce credits back to zero to recover credits */
- ReduceCredits(pCredInfo, pCurEpDist, 0);
- }
- }
- }
-
- pCurEpDist = pCurEpDist->pNext;
- }
-
- break;
-
- case HTC_CREDIT_DIST_ACTIVITY_CHANGE :
- RedistributeCredits(pCredInfo,pEPDistList);
- break;
- case HTC_CREDIT_DIST_SEEK_CREDITS :
- SeekCredits(pCredInfo,pEPDistList);
- break;
- case HTC_DUMP_CREDIT_STATE :
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Credit Distribution, total : %d, free : %d\n",
- pCredInfo->TotalAvailableCredits, pCredInfo->CurrentFreeCredits));
- break;
- default:
- break;
-
- }
-
- /* sanity checks done after each distribution action */
- A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits);
- A_ASSERT(pCredInfo->CurrentFreeCredits >= 0);
-
-}
-
-/* redistribute credits based on activity change */
-static void RedistributeCredits(struct common_credit_state_info *pCredInfo,
- struct htc_endpoint_credit_dist *pEPDistList)
-{
- struct htc_endpoint_credit_dist *pCurEpDist = pEPDistList;
-
- /* walk through the list and remove credits from inactive endpoints */
- while (pCurEpDist != NULL) {
-
-#ifdef CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS
-
- if ((pCurEpDist->ServiceID == WMI_DATA_BK_SVC) || (pCurEpDist->ServiceID == WMI_DATA_BE_SVC)) {
- /* force low priority streams to always be active to retain their minimum credit distribution */
- SET_EP_ACTIVE(pCurEpDist);
- }
-#endif
-
- if (pCurEpDist->ServiceID != WMI_CONTROL_SVC) {
- if (!IS_EP_ACTIVE(pCurEpDist)) {
- if (pCurEpDist->TxQueueDepth == 0) {
- /* EP is inactive and there are no pending messages, reduce credits back to zero */
- ReduceCredits(pCredInfo, pCurEpDist, 0);
- } else {
- /* we cannot zero the credits assigned to this EP, but to keep
- * the credits available for these leftover packets, reduce to
- * a minimum */
- ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsMin);
- }
- }
- }
-
- /* NOTE in the active case, we do not need to do anything further,
- * when an EP goes active and needs credits, HTC will call into
- * our distribution function using a reason code of HTC_CREDIT_DIST_SEEK_CREDITS */
-
- pCurEpDist = pCurEpDist->pNext;
- }
-
-}
-
-/* HTC has an endpoint that needs credits, pEPDist is the endpoint in question */
-static void SeekCredits(struct common_credit_state_info *pCredInfo,
- struct htc_endpoint_credit_dist *pEPDist)
-{
- struct htc_endpoint_credit_dist *pCurEpDist;
- int credits = 0;
- int need;
-
- do {
-
- if (pEPDist->ServiceID == WMI_CONTROL_SVC) {
- /* we never oversubscribe on the control service, this is not
- * a high performance path and the target never holds onto control
- * credits for too long */
- break;
- }
-
-#ifdef CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS
- if (pEPDist->ServiceID == WMI_DATA_VI_SVC) {
- if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm)) {
- /* limit VI service from oversubscribing */
- break;
- }
- }
-
- if (pEPDist->ServiceID == WMI_DATA_VO_SVC) {
- if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm)) {
- /* limit VO service from oversubscribing */
- break;
- }
- }
-#else
- if (pEPDist->ServiceID == WMI_DATA_VI_SVC) {
- if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm) ||
- (pCredInfo->CurrentFreeCredits <= pEPDist->TxCreditsPerMaxMsg)) {
- /* limit VI service from oversubscribing */
- /* at least one free credit will not be used by VI */
- break;
- }
- }
-
- if (pEPDist->ServiceID == WMI_DATA_VO_SVC) {
- if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm) ||
- (pCredInfo->CurrentFreeCredits <= pEPDist->TxCreditsPerMaxMsg)) {
- /* limit VO service from oversubscribing */
- /* at least one free credit will not be used by VO */
- break;
- }
- }
-#endif
-
- /* for all other services, we follow a simple algorithm of
- * 1. checking the free pool for credits
- * 2. checking lower priority endpoints for credits to take */
-
- /* give what we can */
- credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
-
- if (credits >= pEPDist->TxCreditsSeek) {
- /* we found some to fulfill the seek request */
- break;
- }
-
- /* we don't have enough in the free pool, try taking away from lower priority services
- *
- * The rule for taking away credits:
- * 1. Only take from lower priority endpoints
- * 2. Only take what is allocated above the minimum (never starve an endpoint completely)
- * 3. Only take what you need.
- *
- * */
-
- /* starting at the lowest priority */
- pCurEpDist = pCredInfo->pLowestPriEpDist;
-
- /* work backwards until we hit the endpoint again */
- while (pCurEpDist != pEPDist) {
- /* calculate how many we need so far */
- need = pEPDist->TxCreditsSeek - pCredInfo->CurrentFreeCredits;
-
- if ((pCurEpDist->TxCreditsAssigned - need) >= pCurEpDist->TxCreditsMin) {
- /* the current one has been allocated more than it's minimum and it
- * has enough credits assigned above it's minimum to fulfill our need
- * try to take away just enough to fulfill our need */
- ReduceCredits(pCredInfo,
- pCurEpDist,
- pCurEpDist->TxCreditsAssigned - need);
-
- if (pCredInfo->CurrentFreeCredits >= pEPDist->TxCreditsSeek) {
- /* we have enough */
- break;
- }
- }
-
- pCurEpDist = pCurEpDist->pPrev;
- }
-
- /* return what we can get */
- credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
-
- } while (false);
-
- /* did we find some credits? */
- if (credits) {
- /* give what we can */
- GiveCredits(pCredInfo, pEPDist, credits);
- }
-
-}
-
-/* initialize and setup credit distribution */
-int ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, struct common_credit_state_info *pCredInfo)
-{
- HTC_SERVICE_ID servicepriority[5];
-
- A_MEMZERO(pCredInfo,sizeof(struct common_credit_state_info));
-
- servicepriority[0] = WMI_CONTROL_SVC; /* highest */
- servicepriority[1] = WMI_DATA_VO_SVC;
- servicepriority[2] = WMI_DATA_VI_SVC;
- servicepriority[3] = WMI_DATA_BE_SVC;
- servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */
-
- /* set callbacks and priority list */
- HTCSetCreditDistribution(HTCHandle,
- pCredInfo,
- ar6000_credit_distribute,
- ar6000_credit_init,
- servicepriority,
- 5);
-
- return 0;
-}
-
diff --git a/drivers/staging/ath6kl/miscdrv/miscdrv.h b/drivers/staging/ath6kl/miscdrv/miscdrv.h
deleted file mode 100644
index 41be5670db42..000000000000
--- a/drivers/staging/ath6kl/miscdrv/miscdrv.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="miscdrv.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _MISCDRV_H
-#define _MISCDRV_H
-
-
-#define HOST_INTEREST_ITEM_ADDRESS(target, item) \
- AR6002_HOST_INTEREST_ITEM_ADDRESS(item)
-
-u32 ar6kRev2Array[][128] = {
- {0xFFFF, 0xFFFF}, // No Patches
- };
-
-#define CFG_REV2_ITEMS 0 // no patches so far
-#define AR6K_RESET_ADDR 0x4000
-#define AR6K_RESET_VAL 0x100
-
-#define EEPROM_SZ 768
-#define EEPROM_WAIT_LIMIT 4
-
-#endif
-
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/drivers/staging/ath6kl/os/linux/ar6000_drv.c
deleted file mode 100644
index 32ee39ad00df..000000000000
--- a/drivers/staging/ath6kl/os/linux/ar6000_drv.c
+++ /dev/null
@@ -1,6267 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-/*
- * This driver is a pseudo ethernet driver to access the Atheros AR6000
- * WLAN Device
- */
-
-#include "ar6000_drv.h"
-#include "cfg80211.h"
-#include "htc.h"
-#include "wmi_filter_linux.h"
-#include "epping_test.h"
-#include "wlan_config.h"
-#include "ar3kconfig.h"
-#include "ar6k_pal.h"
-#include "AR6002/addrs.h"
-
-
-/* LINUX_HACK_FUDGE_FACTOR -- this is used to provide a workaround for linux behavior. When
- * the meta data was added to the header it was found that linux did not correctly provide
- * enough headroom. However when more headroom was requested beyond what was truly needed
- * Linux gave the requested headroom. Therefore to get the necessary headroom from Linux
- * the driver requests more than is needed by the amount = LINUX_HACK_FUDGE_FACTOR */
-#define LINUX_HACK_FUDGE_FACTOR 16
-#define BDATA_BDADDR_OFFSET 28
-
-u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-u8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
-
-#ifdef DEBUG
-
-#define ATH_DEBUG_DBG_LOG ATH_DEBUG_MAKE_MODULE_MASK(0)
-#define ATH_DEBUG_WLAN_CONNECT ATH_DEBUG_MAKE_MODULE_MASK(1)
-#define ATH_DEBUG_WLAN_SCAN ATH_DEBUG_MAKE_MODULE_MASK(2)
-#define ATH_DEBUG_WLAN_TX ATH_DEBUG_MAKE_MODULE_MASK(3)
-#define ATH_DEBUG_WLAN_RX ATH_DEBUG_MAKE_MODULE_MASK(4)
-#define ATH_DEBUG_HTC_RAW ATH_DEBUG_MAKE_MODULE_MASK(5)
-#define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6)
-
-static struct ath_debug_mask_description driver_debug_desc[] = {
- { ATH_DEBUG_DBG_LOG , "Target Debug Logs"},
- { ATH_DEBUG_WLAN_CONNECT , "WLAN connect"},
- { ATH_DEBUG_WLAN_SCAN , "WLAN scan"},
- { ATH_DEBUG_WLAN_TX , "WLAN Tx"},
- { ATH_DEBUG_WLAN_RX , "WLAN Rx"},
- { ATH_DEBUG_HTC_RAW , "HTC Raw IF tracing"},
- { ATH_DEBUG_HCI_BRIDGE , "HCI Bridge Setup"},
- { ATH_DEBUG_HCI_RECV , "HCI Recv tracing"},
- { ATH_DEBUG_HCI_DUMP , "HCI Packet dumps"},
-};
-
-ATH_DEBUG_INSTANTIATE_MODULE_VAR(driver,
- "driver",
- "Linux Driver Interface",
- ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_WLAN_SCAN |
- ATH_DEBUG_HCI_BRIDGE,
- ATH_DEBUG_DESCRIPTION_COUNT(driver_debug_desc),
- driver_debug_desc);
-
-#endif
-
-
-#define IS_MAC_NULL(mac) (mac[0]==0 && mac[1]==0 && mac[2]==0 && mac[3]==0 && mac[4]==0 && mac[5]==0)
-#define IS_MAC_BCAST(mac) (*mac==0xff)
-
-#define DESCRIPTION "Driver to access the Atheros AR600x Device, version " __stringify(__VER_MAJOR_) "." __stringify(__VER_MINOR_) "." __stringify(__VER_PATCH_) "." __stringify(__BUILD_NUMBER_)
-
-MODULE_AUTHOR("Atheros Communications, Inc.");
-MODULE_DESCRIPTION(DESCRIPTION);
-MODULE_LICENSE("Dual BSD/GPL");
-
-#ifndef REORG_APTC_HEURISTICS
-#undef ADAPTIVE_POWER_THROUGHPUT_CONTROL
-#endif /* REORG_APTC_HEURISTICS */
-
-#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
-#define APTC_TRAFFIC_SAMPLING_INTERVAL 100 /* msec */
-#define APTC_UPPER_THROUGHPUT_THRESHOLD 3000 /* Kbps */
-#define APTC_LOWER_THROUGHPUT_THRESHOLD 2000 /* Kbps */
-
-typedef struct aptc_traffic_record {
- bool timerScheduled;
- struct timeval samplingTS;
- unsigned long bytesReceived;
- unsigned long bytesTransmitted;
-} APTC_TRAFFIC_RECORD;
-
-A_TIMER aptcTimer;
-APTC_TRAFFIC_RECORD aptcTR;
-#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-// callbacks registered by HCI transport driver
-struct hci_transport_callbacks ar6kHciTransCallbacks = { NULL };
-#endif
-
-unsigned int processDot11Hdr = 0;
-
-char ifname[IFNAMSIZ] = {0,};
-
-int wlaninitmode = WLAN_INIT_MODE_DEFAULT;
-static bool bypasswmi;
-unsigned int debuglevel = 0;
-int tspecCompliance = ATHEROS_COMPLIANCE;
-unsigned int busspeedlow = 0;
-unsigned int onebitmode = 0;
-unsigned int skipflash = 0;
-unsigned int wmitimeout = 2;
-unsigned int wlanNodeCaching = 1;
-unsigned int enableuartprint = ENABLEUARTPRINT_DEFAULT;
-unsigned int logWmiRawMsgs = 0;
-unsigned int enabletimerwar = 0;
-unsigned int num_device = 1;
-unsigned int regscanmode;
-unsigned int fwmode = 1;
-unsigned int mbox_yield_limit = 99;
-unsigned int enablerssicompensation = 0;
-int reduce_credit_dribble = 1 + HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF;
-int allow_trace_signal = 0;
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-unsigned int testmode =0;
-#endif
-
-unsigned int irqprocmode = HIF_DEVICE_IRQ_SYNC_ONLY;//HIF_DEVICE_IRQ_ASYNC_SYNC;
-unsigned int panic_on_assert = 1;
-unsigned int nohifscattersupport = NOHIFSCATTERSUPPORT_DEFAULT;
-
-unsigned int setuphci = SETUPHCI_DEFAULT;
-unsigned int loghci = 0;
-unsigned int setupbtdev = SETUPBTDEV_DEFAULT;
-#ifndef EXPORT_HCI_BRIDGE_INTERFACE
-unsigned int ar3khcibaud = AR3KHCIBAUD_DEFAULT;
-unsigned int hciuartscale = HCIUARTSCALE_DEFAULT;
-unsigned int hciuartstep = HCIUARTSTEP_DEFAULT;
-#endif
-unsigned int csumOffload=0;
-unsigned int csumOffloadTest=0;
-unsigned int eppingtest=0;
-unsigned int mac_addr_method;
-unsigned int firmware_bridge;
-
-module_param_string(ifname, ifname, sizeof(ifname), 0644);
-module_param(wlaninitmode, int, 0644);
-module_param(bypasswmi, bool, 0644);
-module_param(debuglevel, uint, 0644);
-module_param(tspecCompliance, int, 0644);
-module_param(onebitmode, uint, 0644);
-module_param(busspeedlow, uint, 0644);
-module_param(skipflash, uint, 0644);
-module_param(wmitimeout, uint, 0644);
-module_param(wlanNodeCaching, uint, 0644);
-module_param(logWmiRawMsgs, uint, 0644);
-module_param(enableuartprint, uint, 0644);
-module_param(enabletimerwar, uint, 0644);
-module_param(fwmode, uint, 0644);
-module_param(mbox_yield_limit, uint, 0644);
-module_param(reduce_credit_dribble, int, 0644);
-module_param(allow_trace_signal, int, 0644);
-module_param(enablerssicompensation, uint, 0644);
-module_param(processDot11Hdr, uint, 0644);
-module_param(csumOffload, uint, 0644);
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-module_param(testmode, uint, 0644);
-#endif
-module_param(irqprocmode, uint, 0644);
-module_param(nohifscattersupport, uint, 0644);
-module_param(panic_on_assert, uint, 0644);
-module_param(setuphci, uint, 0644);
-module_param(loghci, uint, 0644);
-module_param(setupbtdev, uint, 0644);
-#ifndef EXPORT_HCI_BRIDGE_INTERFACE
-module_param(ar3khcibaud, uint, 0644);
-module_param(hciuartscale, uint, 0644);
-module_param(hciuartstep, uint, 0644);
-#endif
-module_param(eppingtest, uint, 0644);
-
-/* in 2.6.10 and later this is now a pointer to a uint */
-unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX;
-#define mboxnum &_mboxnum
-
-#ifdef DEBUG
-u32 g_dbg_flags = DBG_DEFAULTS;
-unsigned int debugflags = 0;
-int debugdriver = 0;
-unsigned int debughtc = 0;
-unsigned int debugbmi = 0;
-unsigned int debughif = 0;
-unsigned int txcreditsavailable[HTC_MAILBOX_NUM_MAX] = {0};
-unsigned int txcreditsconsumed[HTC_MAILBOX_NUM_MAX] = {0};
-unsigned int txcreditintrenable[HTC_MAILBOX_NUM_MAX] = {0};
-unsigned int txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX] = {0};
-module_param(debugflags, uint, 0644);
-module_param(debugdriver, int, 0644);
-module_param(debughtc, uint, 0644);
-module_param(debugbmi, uint, 0644);
-module_param(debughif, uint, 0644);
-module_param_array(txcreditsavailable, uint, mboxnum, 0644);
-module_param_array(txcreditsconsumed, uint, mboxnum, 0644);
-module_param_array(txcreditintrenable, uint, mboxnum, 0644);
-module_param_array(txcreditintrenableaggregate, uint, mboxnum, 0644);
-
-#endif /* DEBUG */
-
-unsigned int resetok = 1;
-unsigned int tx_attempt[HTC_MAILBOX_NUM_MAX] = {0};
-unsigned int tx_post[HTC_MAILBOX_NUM_MAX] = {0};
-unsigned int tx_complete[HTC_MAILBOX_NUM_MAX] = {0};
-unsigned int hifBusRequestNumMax = 40;
-unsigned int war23838_disabled = 0;
-#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
-unsigned int enableAPTCHeuristics = 1;
-#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
-module_param_array(tx_attempt, uint, mboxnum, 0644);
-module_param_array(tx_post, uint, mboxnum, 0644);
-module_param_array(tx_complete, uint, mboxnum, 0644);
-module_param(hifBusRequestNumMax, uint, 0644);
-module_param(war23838_disabled, uint, 0644);
-module_param(resetok, uint, 0644);
-#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
-module_param(enableAPTCHeuristics, uint, 0644);
-#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
-
-#ifdef BLOCK_TX_PATH_FLAG
-int blocktx = 0;
-module_param(blocktx, int, 0644);
-#endif /* BLOCK_TX_PATH_FLAG */
-
-typedef struct user_rssi_compensation_t {
- u16 customerID;
- union {
- u16 a_enable;
- u16 bg_enable;
- u16 enable;
- };
- s16 bg_param_a;
- s16 bg_param_b;
- s16 a_param_a;
- s16 a_param_b;
- u32 reserved;
-} USER_RSSI_CPENSATION;
-
-static USER_RSSI_CPENSATION rssi_compensation_param;
-
-static s16 rssi_compensation_table[96];
-
-int reconnect_flag = 0;
-static ar6k_pal_config_t ar6k_pal_config_g;
-
-/* Function declarations */
-static int ar6000_init_module(void);
-static void ar6000_cleanup_module(void);
-
-int ar6000_init(struct net_device *dev);
-static int ar6000_open(struct net_device *dev);
-static int ar6000_close(struct net_device *dev);
-static void ar6000_init_control_info(struct ar6_softc *ar);
-static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev);
-
-void ar6000_destroy(struct net_device *dev, unsigned int unregister);
-static void ar6000_detect_error(unsigned long ptr);
-static void ar6000_set_multicast_list(struct net_device *dev);
-static struct net_device_stats *ar6000_get_stats(struct net_device *dev);
-
-static void disconnect_timer_handler(unsigned long ptr);
-
-void read_rssi_compensation_param(struct ar6_softc *ar);
-
-/*
- * HTC service connection handlers
- */
-static int ar6000_avail_ev(void *context, void *hif_handle);
-
-static int ar6000_unavail_ev(void *context, void *hif_handle);
-
-int ar6000_configure_target(struct ar6_softc *ar);
-
-static void ar6000_target_failure(void *Instance, int Status);
-
-static void ar6000_rx(void *Context, struct htc_packet *pPacket);
-
-static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint);
-
-static void ar6000_tx_complete(void *Context, struct htc_packet_queue *pPackets);
-
-static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket);
-
-static void ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num);
-static void ar6000_deliver_frames_to_nw_stack(void * dev, void *osbuf);
-//static void ar6000_deliver_frames_to_bt_stack(void * dev, void *osbuf);
-
-static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length);
-
-static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count);
-
-static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar);
-
-static ssize_t
-ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t count);
-
-static ssize_t
-ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t count);
-
-static int
-ar6000_sysfs_bmi_init(struct ar6_softc *ar);
-
-void ar6k_cleanup_hci_pal(struct ar6_softc *ar);
-
-static void
-ar6000_sysfs_bmi_deinit(struct ar6_softc *ar);
-
-int
-ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode);
-
-/*
- * Static variables
- */
-
-struct net_device *ar6000_devices[MAX_AR6000];
-static int is_netdev_registered;
-DECLARE_WAIT_QUEUE_HEAD(arEvent);
-static void ar6000_cookie_init(struct ar6_softc *ar);
-static void ar6000_cookie_cleanup(struct ar6_softc *ar);
-static void ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie);
-static struct ar_cookie *ar6000_alloc_cookie(struct ar6_softc *ar);
-
-static int ar6000_reinstall_keys(struct ar6_softc *ar,u8 key_op_ctrl);
-
-#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
-struct net_device *arApNetDev;
-#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
-
-static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM];
-
-#define HOST_INTEREST_ITEM_ADDRESS(ar, item) \
- (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \
- (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0))
-
-
-static struct net_device_ops ar6000_netdev_ops = {
- .ndo_init = NULL,
- .ndo_open = ar6000_open,
- .ndo_stop = ar6000_close,
- .ndo_get_stats = ar6000_get_stats,
- .ndo_start_xmit = ar6000_data_tx,
- .ndo_set_multicast_list = ar6000_set_multicast_list,
-};
-
-/* Debug log support */
-
-/*
- * Flag to govern whether the debug logs should be parsed in the kernel
- * or reported to the application.
- */
-#define REPORT_DEBUG_LOGS_TO_APP
-
-int
-ar6000_set_host_app_area(struct ar6_softc *ar)
-{
- u32 address, data;
- struct host_app_area_s host_app_area;
-
- /* Fetch the address of the host_app_area_s instance in the host interest area */
- address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest));
- if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != 0) {
- return A_ERROR;
- }
- address = TARG_VTOP(ar->arTargetType, data);
- host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
- if (ar6000_WriteDataDiag(ar->arHifDevice, address,
- (u8 *)&host_app_area,
- sizeof(struct host_app_area_s)) != 0)
- {
- return A_ERROR;
- }
-
- return 0;
-}
-
-u32 dbglog_get_debug_hdr_ptr(struct ar6_softc *ar)
-{
- u32 param;
- u32 address;
- int status;
-
- address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr));
- if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address,
- (u8 *)&param, 4)) != 0)
- {
- param = 0;
- }
-
- return param;
-}
-
-/*
- * The dbglog module has been initialized. Its ok to access the relevant
- * data stuctures over the diagnostic window.
- */
-void
-ar6000_dbglog_init_done(struct ar6_softc *ar)
-{
- ar->dbglog_init_done = true;
-}
-
-u32 dbglog_get_debug_fragment(s8 *datap, u32 len, u32 limit)
-{
- s32 *buffer;
- u32 count;
- u32 numargs;
- u32 length;
- u32 fraglen;
-
- count = fraglen = 0;
- buffer = (s32 *)datap;
- length = (limit >> 2);
-
- if (len <= limit) {
- fraglen = len;
- } else {
- while (count < length) {
- numargs = DBGLOG_GET_NUMARGS(buffer[count]);
- fraglen = (count << 2);
- count += numargs + 1;
- }
- }
-
- return fraglen;
-}
-
-void
-dbglog_parse_debug_logs(s8 *datap, u32 len)
-{
- s32 *buffer;
- u32 count;
- u32 timestamp;
- u32 debugid;
- u32 moduleid;
- u32 numargs;
- u32 length;
-
- count = 0;
- buffer = (s32 *)datap;
- length = (len >> 2);
- while (count < length) {
- debugid = DBGLOG_GET_DBGID(buffer[count]);
- moduleid = DBGLOG_GET_MODULEID(buffer[count]);
- numargs = DBGLOG_GET_NUMARGS(buffer[count]);
- timestamp = DBGLOG_GET_TIMESTAMP(buffer[count]);
- switch (numargs) {
- case 0:
- AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d)\n", moduleid, debugid, timestamp));
- break;
-
- case 1:
- AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x\n", moduleid, debugid,
- timestamp, buffer[count+1]));
- break;
-
- case 2:
- AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x, 0x%x\n", moduleid, debugid,
- timestamp, buffer[count+1], buffer[count+2]));
- break;
-
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid args: %d\n", numargs));
- }
- count += numargs + 1;
- }
-}
-
-int
-ar6000_dbglog_get_debug_logs(struct ar6_softc *ar)
-{
- u32 data[8]; /* Should be able to accommodate struct dbglog_buf_s */
- u32 address;
- u32 length;
- u32 dropped;
- u32 firstbuf;
- u32 debug_hdr_ptr;
-
- if (!ar->dbglog_init_done) return A_ERROR;
-
-
- AR6000_SPIN_LOCK(&ar->arLock, 0);
-
- if (ar->dbgLogFetchInProgress) {
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- return A_EBUSY;
- }
-
- /* block out others */
- ar->dbgLogFetchInProgress = true;
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar);
- printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr);
-
- /* Get the contents of the ring buffer */
- if (debug_hdr_ptr) {
- address = TARG_VTOP(ar->arTargetType, debug_hdr_ptr);
- length = 4 /* sizeof(dbuf) */ + 4 /* sizeof(dropped) */;
- A_MEMZERO(data, sizeof(data));
- ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)data, length);
- address = TARG_VTOP(ar->arTargetType, data[0] /* dbuf */);
- firstbuf = address;
- dropped = data[1]; /* dropped */
- length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */;
- A_MEMZERO(data, sizeof(data));
- ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)&data, length);
-
- do {
- address = TARG_VTOP(ar->arTargetType, data[1] /* buffer*/);
- length = data[3]; /* length */
- if ((length) && (length <= data[2] /* bufsize*/)) {
- /* Rewind the index if it is about to overrun the buffer */
- if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) {
- ar->log_cnt = 0;
- }
- if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address,
- (u8 *)&ar->log_buffer[ar->log_cnt], length))
- {
- break;
- }
- ar6000_dbglog_event(ar, dropped, (s8 *)&ar->log_buffer[ar->log_cnt], length);
- ar->log_cnt += length;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("Length: %d (Total size: %d)\n",
- data[3], data[2]));
- }
-
- address = TARG_VTOP(ar->arTargetType, data[0] /* next */);
- length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */;
- A_MEMZERO(data, sizeof(data));
- if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address,
- (u8 *)&data, length))
- {
- break;
- }
-
- } while (address != firstbuf);
- }
-
- ar->dbgLogFetchInProgress = false;
-
- return 0;
-}
-
-void
-ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped,
- s8 *buffer, u32 length)
-{
-#ifdef REPORT_DEBUG_LOGS_TO_APP
- #define MAX_WIRELESS_EVENT_SIZE 252
- /*
- * Break it up into chunks of MAX_WIRELESS_EVENT_SIZE bytes of messages.
- * There seems to be a limitation on the length of message that could be
- * transmitted to the user app via this mechanism.
- */
- u32 send, sent;
-
- sent = 0;
- send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
- MAX_WIRELESS_EVENT_SIZE);
- while (send) {
- sent += send;
- send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
- MAX_WIRELESS_EVENT_SIZE);
- }
-#else
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Dropped logs: 0x%x\nDebug info length: %d\n",
- dropped, length));
-
- /* Interpret the debug logs */
- dbglog_parse_debug_logs((s8 *)buffer, length);
-#endif /* REPORT_DEBUG_LOGS_TO_APP */
-}
-
-
-static int __init
-ar6000_init_module(void)
-{
- static int probed = 0;
- int r;
- OSDRV_CALLBACKS osdrvCallbacks;
-
- a_module_debug_support_init();
-
-#ifdef DEBUG
- /* check for debug mask overrides */
- if (debughtc != 0) {
- ATH_DEBUG_SET_DEBUG_MASK(htc,debughtc);
- }
- if (debugbmi != 0) {
- ATH_DEBUG_SET_DEBUG_MASK(bmi,debugbmi);
- }
- if (debughif != 0) {
- ATH_DEBUG_SET_DEBUG_MASK(hif,debughif);
- }
- if (debugdriver != 0) {
- ATH_DEBUG_SET_DEBUG_MASK(driver,debugdriver);
- }
-
-#endif
-
- A_REGISTER_MODULE_DEBUG_INFO(driver);
-
- A_MEMZERO(&osdrvCallbacks,sizeof(osdrvCallbacks));
- osdrvCallbacks.deviceInsertedHandler = ar6000_avail_ev;
- osdrvCallbacks.deviceRemovedHandler = ar6000_unavail_ev;
-#ifdef CONFIG_PM
- osdrvCallbacks.deviceSuspendHandler = ar6000_suspend_ev;
- osdrvCallbacks.deviceResumeHandler = ar6000_resume_ev;
- osdrvCallbacks.devicePowerChangeHandler = ar6000_power_change_ev;
-#endif
-
-#ifdef DEBUG
- /* Set the debug flags if specified at load time */
- if(debugflags != 0)
- {
- g_dbg_flags = debugflags;
- }
-#endif
-
- if (probed) {
- return -ENODEV;
- }
- probed++;
-
-#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD));
-#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
-
- r = HIFInit(&osdrvCallbacks);
- if (r)
- return r;
-
- return 0;
-}
-
-static void __exit
-ar6000_cleanup_module(void)
-{
- int i = 0;
- struct net_device *ar6000_netdev;
-
-#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- /* Delete the Adaptive Power Control timer */
- if (timer_pending(&aptcTimer)) {
- del_timer_sync(&aptcTimer);
- }
-#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
-
- for (i=0; i < MAX_AR6000; i++) {
- if (ar6000_devices[i] != NULL) {
- ar6000_netdev = ar6000_devices[i];
- ar6000_devices[i] = NULL;
- ar6000_destroy(ar6000_netdev, 1);
- }
- }
-
- HIFShutDownDevice(NULL);
-
- a_module_debug_support_cleanup();
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_cleanup: success\n"));
-}
-
-#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
-void
-aptcTimerHandler(unsigned long arg)
-{
- u32 numbytes;
- u32 throughput;
- struct ar6_softc *ar;
- int status;
-
- ar = (struct ar6_softc *)arg;
- A_ASSERT(ar != NULL);
- A_ASSERT(!timer_pending(&aptcTimer));
-
- AR6000_SPIN_LOCK(&ar->arLock, 0);
-
- /* Get the number of bytes transferred */
- numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived;
- aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0;
-
- /* Calculate and decide based on throughput thresholds */
- throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */
- if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) {
- /* Enable Sleep and delete the timer */
- A_ASSERT(ar->arWmiReady == true);
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- status = wmi_powermode_cmd(ar->arWmi, REC_POWER);
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- A_ASSERT(status == 0);
- aptcTR.timerScheduled = false;
- } else {
- A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
- }
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-}
-#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
-
-static void
-ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num)
-{
- void * osbuf;
-
- while(num) {
- if((osbuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE))) {
- A_NETBUF_ENQUEUE(q, osbuf);
- } else {
- break;
- }
- num--;
- }
-
- if(num) {
- A_PRINTF("%s(), allocation of netbuf failed", __func__);
- }
-}
-
-static struct bin_attribute bmi_attr = {
- .attr = {.name = "bmi", .mode = 0600},
- .read = ar6000_sysfs_bmi_read,
- .write = ar6000_sysfs_bmi_write,
-};
-
-static ssize_t
-ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t count)
-{
- int index;
- struct ar6_softc *ar;
- struct hif_device_os_device_info *osDevInfo;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Read %d bytes\n", (u32)count));
- for (index=0; index < MAX_AR6000; index++) {
- ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]);
- osDevInfo = &ar->osDevInfo;
- if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) {
- break;
- }
- }
-
- if (index == MAX_AR6000) return 0;
-
- if ((BMIRawRead(ar->arHifDevice, (u8*)buf, count, true)) != 0) {
- return 0;
- }
-
- return count;
-}
-
-static ssize_t
-ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t count)
-{
- int index;
- struct ar6_softc *ar;
- struct hif_device_os_device_info *osDevInfo;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Write %d bytes\n", (u32)count));
- for (index=0; index < MAX_AR6000; index++) {
- ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]);
- osDevInfo = &ar->osDevInfo;
- if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) {
- break;
- }
- }
-
- if (index == MAX_AR6000) return 0;
-
- if ((BMIRawWrite(ar->arHifDevice, (u8*)buf, count)) != 0) {
- return 0;
- }
-
- return count;
-}
-
-static int
-ar6000_sysfs_bmi_init(struct ar6_softc *ar)
-{
- int status;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Creating sysfs entry\n"));
- A_MEMZERO(&ar->osDevInfo, sizeof(struct hif_device_os_device_info));
-
- /* Get the underlying OS device */
- status = HIFConfigureDevice(ar->arHifDevice,
- HIF_DEVICE_GET_OS_DEVICE,
- &ar->osDevInfo,
- sizeof(struct hif_device_os_device_info));
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failed to get OS device info from HIF\n"));
- return A_ERROR;
- }
-
- /* Create a bmi entry in the sysfs filesystem */
- if ((sysfs_create_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &bmi_attr)) < 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to create entry for bmi in sysfs filesystem\n"));
- return A_ERROR;
- }
-
- return 0;
-}
-
-static void
-ar6000_sysfs_bmi_deinit(struct ar6_softc *ar)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Deleting sysfs entry\n"));
-
- sysfs_remove_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &bmi_attr);
-}
-
-#define bmifn(fn) do { \
- if ((fn) < 0) { \
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); \
- return A_ERROR; \
- } \
-} while(0)
-
-#ifdef SOFTMAC_FILE_USED
-#define AR6002_MAC_ADDRESS_OFFSET 0x0A
-#define AR6003_MAC_ADDRESS_OFFSET 0x16
-static
-void calculate_crc(u32 TargetType, u8 *eeprom_data)
-{
- u16 *ptr_crc;
- u16 *ptr16_eeprom;
- u16 checksum;
- u32 i;
- u32 eeprom_size;
-
- if (TargetType == TARGET_TYPE_AR6001)
- {
- eeprom_size = 512;
- ptr_crc = (u16 *)eeprom_data;
- }
- else if (TargetType == TARGET_TYPE_AR6003)
- {
- eeprom_size = 1024;
- ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04);
- }
- else
- {
- eeprom_size = 768;
- ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04);
- }
-
-
- // Clear the crc
- *ptr_crc = 0;
-
- // Recalculate new CRC
- checksum = 0;
- ptr16_eeprom = (u16 *)eeprom_data;
- for (i = 0;i < eeprom_size; i += 2)
- {
- checksum = checksum ^ (*ptr16_eeprom);
- ptr16_eeprom++;
- }
- checksum = 0xFFFF ^ checksum;
- *ptr_crc = checksum;
-}
-
-static void
-ar6000_softmac_update(struct ar6_softc *ar, u8 *eeprom_data, size_t size)
-{
- const char *source = "random generated";
- const struct firmware *softmac_entry;
- u8 *ptr_mac;
- switch (ar->arTargetType) {
- case TARGET_TYPE_AR6002:
- ptr_mac = (u8 *)((u8 *)eeprom_data + AR6002_MAC_ADDRESS_OFFSET);
- break;
- case TARGET_TYPE_AR6003:
- ptr_mac = (u8 *)((u8 *)eeprom_data + AR6003_MAC_ADDRESS_OFFSET);
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Target Type\n"));
- return;
- }
- printk(KERN_DEBUG "MAC from EEPROM %pM\n", ptr_mac);
-
- /* create a random MAC in case we cannot read file from system */
- ptr_mac[0] = 0;
- ptr_mac[1] = 0x03;
- ptr_mac[2] = 0x7F;
- ptr_mac[3] = random32() & 0xff;
- ptr_mac[4] = random32() & 0xff;
- ptr_mac[5] = random32() & 0xff;
- if ((A_REQUEST_FIRMWARE(&softmac_entry, "softmac", ((struct device *)ar->osDevInfo.pOSDevice))) == 0)
- {
- char *macbuf = A_MALLOC_NOWAIT(softmac_entry->size+1);
- if (macbuf) {
- unsigned int softmac[6];
- memcpy(macbuf, softmac_entry->data, softmac_entry->size);
- macbuf[softmac_entry->size] = '\0';
- if (sscanf(macbuf, "%02x:%02x:%02x:%02x:%02x:%02x",
- &softmac[0], &softmac[1], &softmac[2],
- &softmac[3], &softmac[4], &softmac[5])==6) {
- int i;
- for (i=0; i<6; ++i) {
- ptr_mac[i] = softmac[i] & 0xff;
- }
- source = "softmac file";
- }
- kfree(macbuf);
- }
- A_RELEASE_FIRMWARE(softmac_entry);
- }
- printk(KERN_DEBUG "MAC from %s %pM\n", source, ptr_mac);
- calculate_crc(ar->arTargetType, eeprom_data);
-}
-#endif /* SOFTMAC_FILE_USED */
-
-static int
-ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, bool compressed)
-{
- int status;
- const char *filename;
- const struct firmware *fw_entry;
- u32 fw_entry_size;
- u8 **buf;
- size_t *buf_len;
-
- switch (file) {
- case AR6K_OTP_FILE:
- buf = &ar->fw_otp;
- buf_len = &ar->fw_otp_len;
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_OTP_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_OTP_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_OTP_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
- break;
-
- case AR6K_FIRMWARE_FILE:
- buf = &ar->fw;
- buf_len = &ar->fw_len;
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_FIRMWARE_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
-
- if (eppingtest) {
- bypasswmi = true;
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_EPPING_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_EPPING_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_EPPING_FIRMWARE_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("eppingtest : unsupported firmware revision: %d\n",
- ar->arVersion.target_ver));
- return A_ERROR;
- }
- compressed = false;
- }
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
- if(testmode) {
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_TCMD_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_TCMD_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_TCMD_FIRMWARE_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
- compressed = false;
- }
-#endif
-#ifdef HTC_RAW_INTERFACE
- if (!eppingtest && bypasswmi) {
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_ART_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_ART_FIRMWARE_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
- compressed = false;
- }
-#endif
- break;
-
- case AR6K_PATCH_FILE:
- buf = &ar->fw_patch;
- buf_len = &ar->fw_patch_len;
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_PATCH_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_PATCH_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_PATCH_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
- break;
-
- case AR6K_BOARD_DATA_FILE:
- buf = &ar->fw_data;
- buf_len = &ar->fw_data_len;
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_BOARD_DATA_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_BOARD_DATA_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_BOARD_DATA_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
- break;
-
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown file type: %d\n", file));
- return A_ERROR;
- }
-
- if (*buf == NULL) {
- if ((A_REQUEST_FIRMWARE(&fw_entry, filename, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to get %s\n", filename));
- return A_ENOENT;
- }
-
- *buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
- *buf_len = fw_entry->size;
- A_RELEASE_FIRMWARE(fw_entry);
- }
-
-#ifdef SOFTMAC_FILE_USED
- if (file==AR6K_BOARD_DATA_FILE && *buf_len) {
- ar6000_softmac_update(ar, *buf, *buf_len);
- }
-#endif
-
-
- fw_entry_size = *buf_len;
-
- /* Load extended board data for AR6003 */
- if ((file==AR6K_BOARD_DATA_FILE) && *buf) {
- u32 board_ext_address;
- u32 board_ext_data_size;
- u32 board_data_size;
-
- board_ext_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_EXT_DATA_SZ : \
- (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_EXT_DATA_SZ : 0));
-
- board_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_DATA_SZ : \
- (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_DATA_SZ : 0));
-
- /* Determine where in Target RAM to write Board Data */
- bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), (u8 *)&board_ext_address, 4));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board extended Data download address: 0x%x\n", board_ext_address));
-
- /* check whether the target has allocated memory for extended board data and file contains extended board data */
- if ((board_ext_address) && (*buf_len == (board_data_size + board_ext_data_size))) {
- u32 param;
-
- status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(*buf + board_data_size), board_ext_data_size);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
- return A_ERROR;
- }
-
- /* Record the fact that extended board Data IS initialized */
- param = (board_ext_data_size << 16) | 1;
- bmifn(BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data_config),
- (unsigned char *)&param, 4));
- }
- fw_entry_size = board_data_size;
- }
-
- if (compressed) {
- status = BMIFastDownload(ar->arHifDevice, address, *buf, fw_entry_size);
- } else {
- status = BMIWriteMemory(ar->arHifDevice, address, *buf, fw_entry_size);
- }
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
- return A_ERROR;
- }
-
- return 0;
-}
-
-int
-ar6000_update_bdaddr(struct ar6_softc *ar)
-{
-
- if (setupbtdev != 0) {
- u32 address;
-
- if (BMIReadMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for hi_board_data failed\n"));
- return A_ERROR;
- }
-
- if (BMIReadMemory(ar->arHifDevice, address + BDATA_BDADDR_OFFSET, (u8 *)ar->bdaddr, 6) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for BD address failed\n"));
- return A_ERROR;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BDADDR 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", ar->bdaddr[0],
- ar->bdaddr[1], ar->bdaddr[2], ar->bdaddr[3],
- ar->bdaddr[4], ar->bdaddr[5]));
- }
-
-return 0;
-}
-
-int
-ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Requesting device specific configuration\n"));
-
- if (mode == WLAN_INIT_MODE_UDEV) {
- char version[16];
- const struct firmware *fw_entry;
-
- /* Get config using udev through a script in user space */
- sprintf(version, "%2.2x", ar->arVersion.target_ver);
- if ((A_REQUEST_FIRMWARE(&fw_entry, version, ((struct device *)ar->osDevInfo.pOSDevice))) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get configuration for target version: %s\n", version));
- return A_ERROR;
- }
-
- A_RELEASE_FIRMWARE(fw_entry);
- } else {
- /* The config is contained within the driver itself */
- int status;
- u32 param, options, sleep, address;
-
- /* Temporarily disable system sleep */
- address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
- bmifn(BMIReadSOCRegister(ar->arHifDevice, address, &param));
- options = param;
- param |= AR6K_OPTION_SLEEP_DISABLE;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
-
- address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
- bmifn(BMIReadSOCRegister(ar->arHifDevice, address, &param));
- sleep = param;
- param |= WLAN_SYSTEM_SLEEP_DISABLE_SET(1);
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("old options: %d, old sleep: %d\n", options, sleep));
-
- if (ar->arTargetType == TARGET_TYPE_AR6003) {
- /* Program analog PLL register */
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, ANALOG_INTF_BASE_ADDRESS + 0x284, 0xF9104001));
- /* Run at 80/88MHz by default */
- param = CPU_CLOCK_STANDARD_SET(1);
- } else {
- /* Run at 40/44MHz by default */
- param = CPU_CLOCK_STANDARD_SET(0);
- }
- address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
-
- param = 0;
- if (ar->arTargetType == TARGET_TYPE_AR6002) {
- bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)&param, 4));
- }
-
- /* LPO_CAL.ENABLE = 1 if no external clk is detected */
- if (param != 1) {
- address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
- param = LPO_CAL_ENABLE_SET(1);
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- }
-
- /* Venus2.0: Lower SDIO pad drive strength,
- * temporary WAR to avoid SDIO CRC error */
- if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6K: Temporary WAR to avoid SDIO CRC error\n"));
- param = 0x20;
- address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
-
- address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
-
- address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
-
- address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- }
-
-#ifdef FORCE_INTERNAL_CLOCK
- /* Ignore external clock, if any, and force use of internal clock */
- if (ar->arTargetType == TARGET_TYPE_AR6003) {
- /* hi_ext_clk_detected = 0 */
- param = 0;
- bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)&param, 4));
-
- /* CLOCK_CONTROL &= ~LF_CLK32 */
- address = RTC_BASE_ADDRESS + CLOCK_CONTROL_ADDRESS;
- bmifn(BMIReadSOCRegister(ar->arHifDevice, address, &param));
- param &= (~CLOCK_CONTROL_LF_CLK32_SET(1));
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- }
-#endif /* FORCE_INTERNAL_CLOCK */
-
- /* Transfer Board Data from Target EEPROM to Target RAM */
- if (ar->arTargetType == TARGET_TYPE_AR6003) {
- /* Determine where in Target RAM to write Board Data */
- bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board Data download address: 0x%x\n", address));
-
- /* Write EEPROM data to Target RAM */
- if ((ar6000_transfer_bin_file(ar, AR6K_BOARD_DATA_FILE, address, false)) != 0) {
- return A_ERROR;
- }
-
- /* Record the fact that Board Data IS initialized */
- param = 1;
- bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data_initialized), (u8 *)&param, 4));
-
- /* Transfer One time Programmable data */
- AR6K_APP_LOAD_ADDRESS(address, ar->arVersion.target_ver);
- if (ar->arVersion.target_ver == AR6003_REV3_VERSION)
- address = 0x1234;
- status = ar6000_transfer_bin_file(ar, AR6K_OTP_FILE, address, true);
- if (status == 0) {
- /* Execute the OTP code */
- param = 0;
- AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver);
- bmifn(BMIExecute(ar->arHifDevice, address, &param));
- } else if (status != A_ENOENT) {
- return A_ERROR;
- }
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Programming of board data for chip %d not supported\n", ar->arTargetType));
- return A_ERROR;
- }
-
- /* Download Target firmware */
- AR6K_APP_LOAD_ADDRESS(address, ar->arVersion.target_ver);
- if (ar->arVersion.target_ver == AR6003_REV3_VERSION)
- address = 0x1234;
- if ((ar6000_transfer_bin_file(ar, AR6K_FIRMWARE_FILE, address, true)) != 0) {
- return A_ERROR;
- }
-
- /* Set starting address for firmware */
- AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver);
- bmifn(BMISetAppStart(ar->arHifDevice, address));
-
- if(ar->arTargetType == TARGET_TYPE_AR6003) {
- AR6K_DATASET_PATCH_ADDRESS(address, ar->arVersion.target_ver);
- if ((ar6000_transfer_bin_file(ar, AR6K_PATCH_FILE,
- address, false)) != 0)
- return A_ERROR;
- param = address;
- bmifn(BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_dset_list_head),
- (unsigned char *)&param, 4));
- }
-
- /* Restore system sleep */
- address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, sleep));
-
- address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
- param = options | 0x20;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
-
- if (ar->arTargetType == TARGET_TYPE_AR6003) {
- /* Configure GPIO AR6003 UART */
-#ifndef CONFIG_AR600x_DEBUG_UART_TX_PIN
-#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
-#endif
- param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
- bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbg_uart_txpin), (u8 *)&param, 4));
-
-#if (CONFIG_AR600x_DEBUG_UART_TX_PIN == 23)
- {
- address = GPIO_BASE_ADDRESS + CLOCK_GPIO_ADDRESS;
- bmifn(BMIReadSOCRegister(ar->arHifDevice, address, &param));
- param |= CLOCK_GPIO_BT_CLK_OUT_EN_SET(1);
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- }
-#endif
-
- /* Configure GPIO for BT Reset */
-#ifdef ATH6KL_CONFIG_GPIO_BT_RESET
-#define CONFIG_AR600x_BT_RESET_PIN 0x16
- param = CONFIG_AR600x_BT_RESET_PIN;
- bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_support_pins), (u8 *)&param, 4));
-#endif /* ATH6KL_CONFIG_GPIO_BT_RESET */
-
- /* Configure UART flow control polarity */
-#ifndef CONFIG_ATH6KL_BT_UART_FC_POLARITY
-#define CONFIG_ATH6KL_BT_UART_FC_POLARITY 0
-#endif
-
-#if (CONFIG_ATH6KL_BT_UART_FC_POLARITY == 1)
- if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- param = ((CONFIG_ATH6KL_BT_UART_FC_POLARITY << 1) & 0x2);
- bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_pwr_mgmt_params), (u8 *)&param, 4));
- }
-#endif /* CONFIG_ATH6KL_BT_UART_FC_POLARITY */
- }
-
-#ifdef HTC_RAW_INTERFACE
- if (!eppingtest && bypasswmi) {
- /* Don't run BMIDone for ART mode and force resetok=0 */
- resetok = 0;
- msleep(1000);
- }
-#endif /* HTC_RAW_INTERFACE */
- }
-
- return 0;
-}
-
-int
-ar6000_configure_target(struct ar6_softc *ar)
-{
- u32 param;
- if (enableuartprint) {
- param = 1;
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable),
- (u8 *)&param,
- 4)!= 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enableuartprint failed \n"));
- return A_ERROR;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Serial console prints enabled\n"));
- }
-
- /* Tell target which HTC version it is used*/
- param = HTC_PROTOCOL_VERSION;
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest),
- (u8 *)&param,
- 4)!= 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for htc version failed \n"));
- return A_ERROR;
- }
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
- if(testmode) {
- ar->arTargetMode = AR6000_TCMD_MODE;
- }else {
- ar->arTargetMode = AR6000_WLAN_MODE;
- }
-#endif
- if (enabletimerwar) {
- u32 param;
-
- if (BMIReadMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
- (u8 *)&param,
- 4)!= 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for enabletimerwar failed \n"));
- return A_ERROR;
- }
-
- param |= HI_OPTION_TIMER_WAR;
-
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
- (u8 *)&param,
- 4) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enabletimerwar failed \n"));
- return A_ERROR;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Timer WAR enabled\n"));
- }
-
- /* set the firmware mode to STA/IBSS/AP */
- {
- u32 param;
-
- if (BMIReadMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
- (u8 *)&param,
- 4)!= 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for setting fwmode failed \n"));
- return A_ERROR;
- }
-
- param |= (num_device << HI_OPTION_NUM_DEV_SHIFT);
- param |= (fwmode << HI_OPTION_FW_MODE_SHIFT);
- param |= (mac_addr_method << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
- param |= (firmware_bridge << HI_OPTION_FW_BRIDGE_SHIFT);
-
-
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
- (u8 *)&param,
- 4) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for setting fwmode failed \n"));
- return A_ERROR;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Firmware mode set\n"));
- }
-
-#ifdef ATH6KL_DISABLE_TARGET_DBGLOGS
- {
- u32 param;
-
- if (BMIReadMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
- (u8 *)&param,
- 4)!= 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for disabling debug logs failed\n"));
- return A_ERROR;
- }
-
- param |= HI_OPTION_DISABLE_DBGLOG;
-
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
- (u8 *)&param,
- 4) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for HI_OPTION_DISABLE_DBGLOG\n"));
- return A_ERROR;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Firmware mode set\n"));
- }
-#endif /* ATH6KL_DISABLE_TARGET_DBGLOGS */
-
- /*
- * Hardcode the address use for the extended board data
- * Ideally this should be pre-allocate by the OS at boot time
- * But since it is a new feature and board data is loaded
- * at init time, we have to workaround this from host.
- * It is difficult to patch the firmware boot code,
- * but possible in theory.
- */
-
- if (ar->arTargetType == TARGET_TYPE_AR6003) {
- u32 ramReservedSz;
- if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- param = AR6003_REV2_BOARD_EXT_DATA_ADDRESS;
- ramReservedSz = AR6003_REV2_RAM_RESERVE_SIZE;
- } else {
- param = AR6003_REV3_BOARD_EXT_DATA_ADDRESS;
- ramReservedSz = AR6003_REV3_RAM_RESERVE_SIZE;
- }
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data),
- (u8 *)&param, 4) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("BMIWriteMemory for "
- "hi_board_ext_data failed\n"));
- return A_ERROR;
- }
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar,
- hi_end_RAM_reserve_sz),
- (u8 *)&ramReservedSz, 4) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR ,
- ("BMIWriteMemory for "
- "hi_end_RAM_reserve_sz failed\n"));
- return A_ERROR;
- }
- }
-
- /* since BMIInit is called in the driver layer, we have to set the block
- * size here for the target */
-
- if (ar6000_set_htc_params(ar->arHifDevice, ar->arTargetType,
- mbox_yield_limit, 0)) {
- /* use default number of control buffers */
- return A_ERROR;
- }
-
- if (setupbtdev != 0) {
- if (ar6000_set_hci_bridge_flags(ar->arHifDevice,
- ar->arTargetType,
- setupbtdev)) {
- return A_ERROR;
- }
- }
- return 0;
-}
-
-static void
-init_netdev(struct net_device *dev, char *name)
-{
- dev->netdev_ops = &ar6000_netdev_ops;
- dev->watchdog_timeo = AR6000_TX_TIMEOUT;
-
- /*
- * We need the OS to provide us with more headroom in order to
- * perform dix to 802.3, WMI header encap, and the HTC header
- */
- if (processDot11Hdr) {
- dev->hard_header_len = sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN + WMI_MAX_TX_META_SZ + LINUX_HACK_FUDGE_FACTOR;
- } else {
- dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) +
- sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN + WMI_MAX_TX_META_SZ + LINUX_HACK_FUDGE_FACTOR;
- }
-
- if (name[0])
- {
- strcpy(dev->name, name);
- }
-
-#ifdef CONFIG_CHECKSUM_OFFLOAD
- if(csumOffload){
- dev->features |= NETIF_F_IP_CSUM; /*advertise kernel capability to do TCP/UDP CSUM offload for IPV4*/
- }
-#endif
-
- return;
-}
-
-static int __ath6kl_init_netdev(struct net_device *dev)
-{
- int r;
-
- rtnl_lock();
- r = ar6000_init(dev);
- rtnl_unlock();
-
- if (r) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_init\n"));
- return r;
- }
-
- return 0;
-}
-
-#ifdef HTC_RAW_INTERFACE
-static int ath6kl_init_netdev_wmi(struct net_device *dev)
-{
- if (!eppingtest && bypasswmi)
- return 0;
-
- return __ath6kl_init_netdev(dev);
-}
-#else
-static int ath6kl_init_netdev_wmi(struct net_device *dev)
-{
- return __ath6kl_init_netdev(dev);
-}
-#endif
-
-static int ath6kl_init_netdev(struct ar6_softc *ar)
-{
- int r;
-
- r = ar6000_sysfs_bmi_get_config(ar, wlaninitmode);
- if (r) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("ar6000_avail: "
- "ar6000_sysfs_bmi_get_config failed\n"));
- return r;
- }
-
- return ath6kl_init_netdev_wmi(ar->arNetDev);
-}
-
-/*
- * HTC Event handlers
- */
-static int
-ar6000_avail_ev(void *context, void *hif_handle)
-{
- int i;
- struct net_device *dev;
- void *ar_netif;
- struct ar6_softc *ar;
- int device_index = 0;
- struct htc_init_info htcInfo;
- struct wireless_dev *wdev;
- int r = 0;
- struct hif_device_os_device_info osDevInfo;
-
- memset(&osDevInfo, 0, sizeof(osDevInfo));
- if (HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_OS_DEVICE,
- &osDevInfo, sizeof(osDevInfo))) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Failed to get OS device instance\n", __func__));
- return A_ERROR;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_available\n"));
-
- for (i=0; i < MAX_AR6000; i++) {
- if (ar6000_devices[i] == NULL) {
- break;
- }
- }
-
- if (i == MAX_AR6000) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_available: max devices reached\n"));
- return A_ERROR;
- }
-
- /* Save this. It gives a bit better readability especially since */
- /* we use another local "i" variable below. */
- device_index = i;
-
- wdev = ar6k_cfg80211_init(osDevInfo.pOSDevice);
- if (IS_ERR(wdev)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ar6k_cfg80211_init failed\n", __func__));
- return A_ERROR;
- }
- ar_netif = wdev_priv(wdev);
-
- if (ar_netif == NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Can't allocate ar6k priv memory\n", __func__));
- return A_ERROR;
- }
-
- A_MEMZERO(ar_netif, sizeof(struct ar6_softc));
- ar = (struct ar6_softc *)ar_netif;
-
- ar->wdev = wdev;
- wdev->iftype = NL80211_IFTYPE_STATION;
-
- dev = alloc_netdev_mq(0, "wlan%d", ether_setup, 1);
- if (!dev) {
- printk(KERN_CRIT "AR6K: no memory for network device instance\n");
- ar6k_cfg80211_deinit(ar);
- return A_ERROR;
- }
-
- dev->ieee80211_ptr = wdev;
- SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
- wdev->netdev = dev;
- ar->arNetworkType = INFRA_NETWORK;
- ar->smeState = SME_DISCONNECTED;
- ar->arAutoAuthStage = AUTH_IDLE;
-
- init_netdev(dev, ifname);
-
-
- ar->arNetDev = dev;
- ar->arHifDevice = hif_handle;
- ar->arWlanState = WLAN_ENABLED;
- ar->arDeviceIndex = device_index;
-
- ar->arWlanPowerState = WLAN_POWER_STATE_ON;
- ar->arWlanOff = false; /* We are in ON state */
-#ifdef CONFIG_PM
- ar->arWowState = WLAN_WOW_STATE_NONE;
- ar->arBTOff = true; /* BT chip assumed to be OFF */
- ar->arBTSharing = WLAN_CONFIG_BT_SHARING;
- ar->arWlanOffConfig = WLAN_CONFIG_WLAN_OFF;
- ar->arSuspendConfig = WLAN_CONFIG_PM_SUSPEND;
- ar->arWow2Config = WLAN_CONFIG_PM_WOW2;
-#endif /* CONFIG_PM */
-
- A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev);
- ar->arHBChallengeResp.seqNum = 0;
- ar->arHBChallengeResp.outstanding = false;
- ar->arHBChallengeResp.missCnt = 0;
- ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT;
- ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT;
-
- ar6000_init_control_info(ar);
- init_waitqueue_head(&arEvent);
- sema_init(&ar->arSem, 1);
- ar->bIsDestroyProgress = false;
-
- INIT_HTC_PACKET_QUEUE(&ar->amsdu_rx_buffer_queue);
-
-#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar);
-#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
-
- A_INIT_TIMER(&ar->disconnect_timer, disconnect_timer_handler, dev);
-
- BMIInit();
-
- ar6000_sysfs_bmi_init(ar);
-
- {
- struct bmi_target_info targ_info;
-
- r = BMIGetTargetInfo(ar->arHifDevice, &targ_info);
- if (r)
- goto avail_ev_failed;
-
- ar->arVersion.target_ver = targ_info.target_ver;
- ar->arTargetType = targ_info.target_type;
- wdev->wiphy->hw_version = targ_info.target_ver;
- }
-
- r = ar6000_configure_target(ar);
- if (r)
- goto avail_ev_failed;
-
- A_MEMZERO(&htcInfo,sizeof(htcInfo));
- htcInfo.pContext = ar;
- htcInfo.TargetFailure = ar6000_target_failure;
-
- ar->arHtcTarget = HTCCreate(ar->arHifDevice,&htcInfo);
-
- if (!ar->arHtcTarget) {
- r = -ENOMEM;
- goto avail_ev_failed;
- }
-
- spin_lock_init(&ar->arLock);
-
-#ifdef WAPI_ENABLE
- ar->arWapiEnable = 0;
-#endif
-
-
- if(csumOffload){
- /*if external frame work is also needed, change and use an extended rxMetaVerion*/
- ar->rxMetaVersion=WMI_META_VERSION_2;
- }
-
- ar->aggr_cntxt = aggr_init(ar6000_alloc_netbufs);
- if (!ar->aggr_cntxt) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize aggr.\n", __func__));
- r = -ENOMEM;
- goto avail_ev_failed;
- }
-
- aggr_register_rx_dispatcher(ar->aggr_cntxt, (void *)dev, ar6000_deliver_frames_to_nw_stack);
-
- HIFClaimDevice(ar->arHifDevice, ar);
-
- /* We only register the device in the global list if we succeed. */
- /* If the device is in the global list, it will be destroyed */
- /* when the module is unloaded. */
- ar6000_devices[device_index] = dev;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("BMI enabled: %d\n", wlaninitmode));
- if ((wlaninitmode == WLAN_INIT_MODE_UDEV) ||
- (wlaninitmode == WLAN_INIT_MODE_DRV)) {
- r = ath6kl_init_netdev(ar);
- if (r)
- goto avail_ev_failed;
- }
-
- /* This runs the init function if registered */
- r = register_netdev(dev);
- if (r) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: register_netdev failed\n"));
- ar6000_destroy(dev, 0);
- return r;
- }
-
- is_netdev_registered = 1;
-
-#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
- arApNetDev = NULL;
-#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_avail: name=%s hifdevice=0x%lx, dev=0x%lx (%d), ar=0x%lx\n",
- dev->name, (unsigned long)ar->arHifDevice, (unsigned long)dev, device_index,
- (unsigned long)ar));
-
-avail_ev_failed :
- if (r)
- ar6000_sysfs_bmi_deinit(ar);
-
- return r;
-}
-
-static void ar6000_target_failure(void *Instance, int Status)
-{
- struct ar6_softc *ar = (struct ar6_softc *)Instance;
- WMI_TARGET_ERROR_REPORT_EVENT errEvent;
- static bool sip = false;
-
- if (Status != 0) {
-
- printk(KERN_ERR "ar6000_target_failure: target asserted \n");
-
- if (timer_pending(&ar->arHBChallengeResp.timer)) {
- A_UNTIMEOUT(&ar->arHBChallengeResp.timer);
- }
-
- /* try dumping target assertion information (if any) */
- ar6000_dump_target_assert_info(ar->arHifDevice,ar->arTargetType);
-
- /*
- * Fetch the logs from the target via the diagnostic
- * window.
- */
- ar6000_dbglog_get_debug_logs(ar);
-
- /* Report the error only once */
- if (!sip) {
- sip = true;
- errEvent.errorVal = WMI_TARGET_COM_ERR |
- WMI_TARGET_FATAL_ERR;
- }
- }
-}
-
-static int
-ar6000_unavail_ev(void *context, void *hif_handle)
-{
- struct ar6_softc *ar = (struct ar6_softc *)context;
- /* NULL out it's entry in the global list */
- ar6000_devices[ar->arDeviceIndex] = NULL;
- ar6000_destroy(ar->arNetDev, 1);
-
- return 0;
-}
-
-void
-ar6000_restart_endpoint(struct net_device *dev)
-{
- int status = 0;
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
-
- BMIInit();
- do {
- if ( (status=ar6000_configure_target(ar))!= 0)
- break;
- if ( (status=ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sysfs_bmi_get_config failed\n"));
- break;
- }
- rtnl_lock();
- status = (ar6000_init(dev)==0) ? 0 : A_ERROR;
- rtnl_unlock();
-
- if (status) {
- break;
- }
- if (ar->arSsidLen && ar->arWlanState == WLAN_ENABLED) {
- ar6000_connect_to_ap(ar);
- }
- } while (0);
-
- if (status== 0) {
- return;
- }
-
- ar6000_devices[ar->arDeviceIndex] = NULL;
- ar6000_destroy(ar->arNetDev, 1);
-}
-
-void
-ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
-
- /* Stop the transmit queues */
- netif_stop_queue(dev);
-
- /* Disable the target and the interrupts associated with it */
- if (ar->arWmiReady == true)
- {
- if (!bypasswmi)
- {
- bool disconnectIssued;
-
- disconnectIssued = (ar->arConnected) || (ar->arConnectPending);
- ar6000_disconnect(ar);
- if (!keepprofile) {
- ar6000_init_profile_info(ar);
- }
-
- A_UNTIMEOUT(&ar->disconnect_timer);
-
- if (getdbglogs) {
- ar6000_dbglog_get_debug_logs(ar);
- }
-
- ar->arWmiReady = false;
- wmi_shutdown(ar->arWmi);
- ar->arWmiEnabled = false;
- ar->arWmi = NULL;
- /*
- * After wmi_shudown all WMI events will be dropped.
- * We need to cleanup the buffers allocated in AP mode
- * and give disconnect notification to stack, which usually
- * happens in the disconnect_event.
- * Simulate the disconnect_event by calling the function directly.
- * Sometimes disconnect_event will be received when the debug logs
- * are collected.
- */
- if (disconnectIssued) {
- if(ar->arNetworkType & AP_NETWORK) {
- ar6000_disconnect_event(ar, DISCONNECT_CMD, bcast_mac, 0, NULL, 0);
- } else {
- ar6000_disconnect_event(ar, DISCONNECT_CMD, ar->arBssid, 0, NULL, 0);
- }
- }
- ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
- ar->user_key_ctrl = 0;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): WMI stopped\n", __func__));
- }
- else
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): WMI not ready 0x%lx 0x%lx\n",
- __func__, (unsigned long) ar, (unsigned long) ar->arWmi));
-
- /* Shut down WMI if we have started it */
- if(ar->arWmiEnabled == true)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): Shut down WMI\n", __func__));
- wmi_shutdown(ar->arWmi);
- ar->arWmiEnabled = false;
- ar->arWmi = NULL;
- }
- }
-
- if (ar->arHtcTarget != NULL) {
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- if (NULL != ar6kHciTransCallbacks.cleanupTransport) {
- ar6kHciTransCallbacks.cleanupTransport(NULL);
- }
-#else
- // FIXME: workaround to reset BT's UART baud rate to default
- if (NULL != ar->exitCallback) {
- struct ar3k_config_info ar3kconfig;
- int status;
-
- A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig));
- ar6000_set_default_ar3kconfig(ar, (void *)&ar3kconfig);
- status = ar->exitCallback(&ar3kconfig);
- if (0 != status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to reset AR3K baud rate! \n"));
- }
- }
- // END workaround
- if (setuphci)
- ar6000_cleanup_hci(ar);
-#endif
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Shutting down HTC .... \n"));
- /* stop HTC */
- HTCStop(ar->arHtcTarget);
- }
-
- if (resetok) {
- /* try to reset the device if we can
- * The driver may have been configure NOT to reset the target during
- * a debug session */
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Attempting to reset target on instance destroy.... \n"));
- if (ar->arHifDevice != NULL) {
- bool coldReset = (ar->arTargetType == TARGET_TYPE_AR6003) ? true: false;
- ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, coldReset);
- }
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Host does not want target reset. \n"));
- }
- /* Done with cookies */
- ar6000_cookie_cleanup(ar);
-
- /* cleanup any allocated AMSDU buffers */
- ar6000_cleanup_amsdu_rxbufs(ar);
-}
-/*
- * We need to differentiate between the surprise and planned removal of the
- * device because of the following consideration:
- * - In case of surprise removal, the hcd already frees up the pending
- * for the device and hence there is no need to unregister the function
- * driver inorder to get these requests. For planned removal, the function
- * driver has to explicitly unregister itself to have the hcd return all the
- * pending requests before the data structures for the devices are freed up.
- * Note that as per the current implementation, the function driver will
- * end up releasing all the devices since there is no API to selectively
- * release a particular device.
- * - Certain commands issued to the target can be skipped for surprise
- * removal since they will anyway not go through.
- */
-void
-ar6000_destroy(struct net_device *dev, unsigned int unregister)
-{
- struct ar6_softc *ar;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("+ar6000_destroy \n"));
-
- if((dev == NULL) || ((ar = ar6k_priv(dev)) == NULL))
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): Failed to get device structure.\n", __func__));
- return;
- }
-
- ar->bIsDestroyProgress = true;
-
- if (down_interruptible(&ar->arSem)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): down_interruptible failed \n", __func__));
- return;
- }
-
- if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) {
- /* only stop endpoint if we are not stop it in suspend_ev */
- ar6000_stop_endpoint(dev, false, true);
- }
-
- ar->arWlanState = WLAN_DISABLED;
- if (ar->arHtcTarget != NULL) {
- /* destroy HTC */
- HTCDestroy(ar->arHtcTarget);
- }
- if (ar->arHifDevice != NULL) {
- /*release the device so we do not get called back on remove incase we
- * we're explicity destroyed by module unload */
- HIFReleaseDevice(ar->arHifDevice);
- HIFShutDownDevice(ar->arHifDevice);
- }
- aggr_module_destroy(ar->aggr_cntxt);
-
- /* Done with cookies */
- ar6000_cookie_cleanup(ar);
-
- /* cleanup any allocated AMSDU buffers */
- ar6000_cleanup_amsdu_rxbufs(ar);
-
- ar6000_sysfs_bmi_deinit(ar);
-
- /* Cleanup BMI */
- BMICleanup();
-
- /* Clear the tx counters */
- memset(tx_attempt, 0, sizeof(tx_attempt));
- memset(tx_post, 0, sizeof(tx_post));
- memset(tx_complete, 0, sizeof(tx_complete));
-
-#ifdef HTC_RAW_INTERFACE
- if (ar->arRawHtc) {
- kfree(ar->arRawHtc);
- ar->arRawHtc = NULL;
- }
-#endif
- /* Free up the device data structure */
- if (unregister && is_netdev_registered) {
- unregister_netdev(dev);
- is_netdev_registered = 0;
- }
- free_netdev(dev);
-
- ar6k_cfg80211_deinit(ar);
-
-#ifdef CONFIG_AP_VIRTUL_ADAPTER_SUPPORT
- ar6000_remove_ap_interface();
-#endif /*CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
-
- kfree(ar->fw_otp);
- kfree(ar->fw);
- kfree(ar->fw_patch);
- kfree(ar->fw_data);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("-ar6000_destroy \n"));
-}
-
-static void disconnect_timer_handler(unsigned long ptr)
-{
- struct net_device *dev = (struct net_device *)ptr;
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
-
- A_UNTIMEOUT(&ar->disconnect_timer);
-
- ar6000_init_profile_info(ar);
- ar6000_disconnect(ar);
-}
-
-static void ar6000_detect_error(unsigned long ptr)
-{
- struct net_device *dev = (struct net_device *)ptr;
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
- WMI_TARGET_ERROR_REPORT_EVENT errEvent;
-
- AR6000_SPIN_LOCK(&ar->arLock, 0);
-
- if (ar->arHBChallengeResp.outstanding) {
- ar->arHBChallengeResp.missCnt++;
- } else {
- ar->arHBChallengeResp.missCnt = 0;
- }
-
- if (ar->arHBChallengeResp.missCnt > ar->arHBChallengeResp.missThres) {
- /* Send Error Detect event to the application layer and do not reschedule the error detection module timer */
- ar->arHBChallengeResp.missCnt = 0;
- ar->arHBChallengeResp.seqNum = 0;
- errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR;
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- return;
- }
-
- /* Generate the sequence number for the next challenge */
- ar->arHBChallengeResp.seqNum++;
- ar->arHBChallengeResp.outstanding = true;
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- /* Send the challenge on the control channel */
- if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to send heart beat challenge\n"));
- }
-
-
- /* Reschedule the timer for the next challenge */
- A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
-}
-
-void ar6000_init_profile_info(struct ar6_softc *ar)
-{
- ar->arSsidLen = 0;
- A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
-
- switch(fwmode) {
- case HI_OPTION_FW_MODE_IBSS:
- ar->arNetworkType = ar->arNextMode = ADHOC_NETWORK;
- break;
- case HI_OPTION_FW_MODE_BSS_STA:
- ar->arNetworkType = ar->arNextMode = INFRA_NETWORK;
- break;
- case HI_OPTION_FW_MODE_AP:
- ar->arNetworkType = ar->arNextMode = AP_NETWORK;
- break;
- }
-
- ar->arDot11AuthMode = OPEN_AUTH;
- ar->arAuthMode = NONE_AUTH;
- ar->arPairwiseCrypto = NONE_CRYPT;
- ar->arPairwiseCryptoLen = 0;
- ar->arGroupCrypto = NONE_CRYPT;
- ar->arGroupCryptoLen = 0;
- A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));
- A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
- A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
- ar->arBssChannel = 0;
-}
-
-static void
-ar6000_init_control_info(struct ar6_softc *ar)
-{
- ar->arWmiEnabled = false;
- ar6000_init_profile_info(ar);
- ar->arDefTxKeyIndex = 0;
- A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));
- ar->arChannelHint = 0;
- ar->arListenIntervalT = A_DEFAULT_LISTEN_INTERVAL;
- ar->arListenIntervalB = 0;
- ar->arVersion.host_ver = AR6K_SW_VERSION;
- ar->arRssi = 0;
- ar->arTxPwr = 0;
- ar->arTxPwrSet = false;
- ar->arSkipScan = 0;
- ar->arBeaconInterval = 0;
- ar->arBitRate = 0;
- ar->arMaxRetries = 0;
- ar->arWmmEnabled = true;
- ar->intra_bss = 1;
- ar->scan_triggered = 0;
- A_MEMZERO(&ar->scParams, sizeof(ar->scParams));
- ar->scParams.shortScanRatio = WMI_SHORTSCANRATIO_DEFAULT;
- ar->scParams.scanCtrlFlags = DEFAULT_SCAN_CTRL_FLAGS;
-
- /* Initialize the AP mode state info */
- {
- u8 ctr;
- A_MEMZERO((u8 *)ar->sta_list, AP_MAX_NUM_STA * sizeof(sta_t));
-
- /* init the Mutexes */
- A_MUTEX_INIT(&ar->mcastpsqLock);
-
- /* Init the PS queues */
- for (ctr=0; ctr < AP_MAX_NUM_STA ; ctr++) {
- A_MUTEX_INIT(&ar->sta_list[ctr].psqLock);
- A_NETBUF_QUEUE_INIT(&ar->sta_list[ctr].psq);
- }
-
- ar->ap_profile_flag = 0;
- A_NETBUF_QUEUE_INIT(&ar->mcastpsq);
-
- memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
- ar->ap_wmode = DEF_AP_WMODE_G;
- ar->ap_dtim_period = DEF_AP_DTIM;
- ar->ap_beacon_interval = DEF_BEACON_INTERVAL;
- }
-}
-
-static int
-ar6000_open(struct net_device *dev)
-{
- unsigned long flags;
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
-
- spin_lock_irqsave(&ar->arLock, flags);
-
- if(ar->arWlanState == WLAN_DISABLED) {
- ar->arWlanState = WLAN_ENABLED;
- }
-
- if( ar->arConnected || bypasswmi) {
- netif_carrier_on(dev);
- /* Wake up the queues */
- netif_wake_queue(dev);
- }
- else
- netif_carrier_off(dev);
-
- spin_unlock_irqrestore(&ar->arLock, flags);
- return 0;
-}
-
-static int
-ar6000_close(struct net_device *dev)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
- netif_stop_queue(dev);
-
- ar6000_disconnect(ar);
-
- if(ar->arWmiReady == true) {
- if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0,
- 0, 0, 0, 0, 0, 0, 0, 0) != 0) {
- return -EIO;
- }
- ar->arWlanState = WLAN_DISABLED;
- }
- ar6k_cfg80211_scanComplete_event(ar, A_ECANCELED);
-
- return 0;
-}
-
-/* connect to a service */
-static int ar6000_connectservice(struct ar6_softc *ar,
- struct htc_service_connect_req *pConnect,
- char *pDesc)
-{
- int status;
- struct htc_service_connect_resp response;
-
- do {
-
- A_MEMZERO(&response,sizeof(response));
-
- status = HTCConnectService(ar->arHtcTarget,
- pConnect,
- &response);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Failed to connect to %s service status:%d \n",
- pDesc, status));
- break;
- }
- switch (pConnect->ServiceID) {
- case WMI_CONTROL_SVC :
- if (ar->arWmiEnabled) {
- /* set control endpoint for WMI use */
- wmi_set_control_ep(ar->arWmi, response.Endpoint);
- }
- /* save EP for fast lookup */
- ar->arControlEp = response.Endpoint;
- break;
- case WMI_DATA_BE_SVC :
- arSetAc2EndpointIDMap(ar, WMM_AC_BE, response.Endpoint);
- break;
- case WMI_DATA_BK_SVC :
- arSetAc2EndpointIDMap(ar, WMM_AC_BK, response.Endpoint);
- break;
- case WMI_DATA_VI_SVC :
- arSetAc2EndpointIDMap(ar, WMM_AC_VI, response.Endpoint);
- break;
- case WMI_DATA_VO_SVC :
- arSetAc2EndpointIDMap(ar, WMM_AC_VO, response.Endpoint);
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ServiceID not mapped %d\n", pConnect->ServiceID));
- status = A_EINVAL;
- break;
- }
-
- } while (false);
-
- return status;
-}
-
-void ar6000_TxDataCleanup(struct ar6_softc *ar)
-{
- /* flush all the data (non-control) streams
- * we only flush packets that are tagged as data, we leave any control packets that
- * were in the TX queues alone */
- HTCFlushEndpoint(ar->arHtcTarget,
- arAc2EndpointID(ar, WMM_AC_BE),
- AR6K_DATA_PKT_TAG);
- HTCFlushEndpoint(ar->arHtcTarget,
- arAc2EndpointID(ar, WMM_AC_BK),
- AR6K_DATA_PKT_TAG);
- HTCFlushEndpoint(ar->arHtcTarget,
- arAc2EndpointID(ar, WMM_AC_VI),
- AR6K_DATA_PKT_TAG);
- HTCFlushEndpoint(ar->arHtcTarget,
- arAc2EndpointID(ar, WMM_AC_VO),
- AR6K_DATA_PKT_TAG);
-}
-
-HTC_ENDPOINT_ID
-ar6000_ac2_endpoint_id ( void * devt, u8 ac)
-{
- struct ar6_softc *ar = (struct ar6_softc *) devt;
- return(arAc2EndpointID(ar, ac));
-}
-
-u8 ar6000_endpoint_id2_ac(void * devt, HTC_ENDPOINT_ID ep )
-{
- struct ar6_softc *ar = (struct ar6_softc *) devt;
- return(arEndpoint2Ac(ar, ep ));
-}
-
-#if defined(CONFIG_ATH6KL_ENABLE_COEXISTENCE)
-static int ath6kl_config_btcoex_params(struct ar6_softc *ar)
-{
- int r;
- WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD sbcb_cmd;
- WMI_SET_BTCOEX_FE_ANT_CMD sbfa_cmd;
-
- /* Configure the type of BT collocated with WLAN */
- memset(&sbcb_cmd, 0, sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
- sbcb_cmd.btcoexCoLocatedBTdev = ATH6KL_BT_DEV;
-
- r = wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &sbcb_cmd);
-
- if (r) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Unable to set collocated BT type\n"));
- return r;
- }
-
- /* Configure the type of BT collocated with WLAN */
- memset(&sbfa_cmd, 0, sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
-
- sbfa_cmd.btcoexFeAntType = ATH6KL_BT_ANTENNA;
-
- r = wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &sbfa_cmd);
- if (r) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Unable to set fornt end antenna configuration\n"));
- return r;
- }
-
- return 0;
-}
-#else
-static int ath6kl_config_btcoex_params(struct ar6_softc *ar)
-{
- return 0;
-}
-#endif /* CONFIG_ATH6KL_ENABLE_COEXISTENCE */
-
-/*
- * This function applies WLAN specific configuration defined in wlan_config.h
- */
-int ar6000_target_config_wlan_params(struct ar6_softc *ar)
-{
- int status = 0;
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
- if (ar->arTargetMode != AR6000_WLAN_MODE) {
- return 0;
- }
-#endif /* CONFIG_HOST_TCMD_SUPPORT */
-
- /*
- * configure the device for rx dot11 header rules 0,0 are the default values
- * therefore this command can be skipped if the inputs are 0,FALSE,FALSE.Required
- * if checksum offload is needed. Set RxMetaVersion to 2
- */
- if ((wmi_set_rx_frame_format_cmd(ar->arWmi,ar->rxMetaVersion, processDot11Hdr, processDot11Hdr)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the rx frame format.\n"));
- status = A_ERROR;
- }
-
- status = ath6kl_config_btcoex_params(ar);
- if (status)
- return status;
-
-#if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN
- if ((wmi_pmparams_cmd(ar->arWmi, 0, 1, 0, 0, 1, IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power save fail event policy\n"));
- status = A_ERROR;
- }
-#endif
-
-#if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP
- if ((wmi_set_lpreamble_cmd(ar->arWmi, 0, WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set barker preamble policy\n"));
- status = A_ERROR;
- }
-#endif
-
- if ((wmi_set_keepalive_cmd(ar->arWmi, WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set keep alive interval\n"));
- status = A_ERROR;
- }
-
-#if WLAN_CONFIG_DISABLE_11N
- {
- WMI_SET_HT_CAP_CMD htCap;
-
- memset(&htCap, 0, sizeof(WMI_SET_HT_CAP_CMD));
- htCap.band = 0;
- if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n"));
- status = A_ERROR;
- }
-
- htCap.band = 1;
- if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n"));
- status = A_ERROR;
- }
- }
-#endif /* WLAN_CONFIG_DISABLE_11N */
-
-#ifdef ATH6K_CONFIG_OTA_MODE
- if ((wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power mode \n"));
- status = A_ERROR;
- }
-#endif
-
- if ((wmi_disctimeout_cmd(ar->arWmi, WLAN_CONFIG_DISCONNECT_TIMEOUT)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set disconnect timeout \n"));
- status = A_ERROR;
- }
-
-#if WLAN_CONFIG_DISABLE_TX_BURSTING
- if ((wmi_set_wmm_txop(ar->arWmi, WMI_TXOP_DISABLED)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set txop bursting \n"));
- status = A_ERROR;
- }
-#endif
-
- return status;
-}
-
-/* This function does one time initialization for the lifetime of the device */
-int ar6000_init(struct net_device *dev)
-{
- struct ar6_softc *ar;
- int status;
- s32 timeleft;
- s16 i;
- int ret = 0;
-
- if((ar = ar6k_priv(dev)) == NULL)
- {
- return -EIO;
- }
-
- if (wlaninitmode == WLAN_INIT_MODE_USR || wlaninitmode == WLAN_INIT_MODE_DRV) {
-
- ar6000_update_bdaddr(ar);
-
- if (enablerssicompensation) {
- ar6000_copy_cust_data_from_target(ar->arHifDevice, ar->arTargetType);
- read_rssi_compensation_param(ar);
- for (i=-95; i<=0; i++) {
- rssi_compensation_table[0-i] = rssi_compensation_calc(ar,i);
- }
- }
- }
-
- dev_hold(dev);
- rtnl_unlock();
-
- /* Do we need to finish the BMI phase */
- if ((wlaninitmode == WLAN_INIT_MODE_USR || wlaninitmode == WLAN_INIT_MODE_DRV) &&
- (BMIDone(ar->arHifDevice) != 0))
- {
- ret = -EIO;
- goto ar6000_init_done;
- }
-
- if (!bypasswmi)
- {
-#if 0 /* TBDXXX */
- if (ar->arVersion.host_ver != ar->arVersion.target_ver) {
- A_PRINTF("WARNING: Host version 0x%x does not match Target "
- " version 0x%x!\n",
- ar->arVersion.host_ver, ar->arVersion.target_ver);
- }
-#endif
-
- /* Indicate that WMI is enabled (although not ready yet) */
- ar->arWmiEnabled = true;
- if ((ar->arWmi = wmi_init((void *) ar)) == NULL)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize WMI.\n", __func__));
- ret = -EIO;
- goto ar6000_init_done;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Got WMI @ 0x%lx.\n", __func__,
- (unsigned long) ar->arWmi));
- }
-
- do {
- struct htc_service_connect_req connect;
-
- /* the reason we have to wait for the target here is that the driver layer
- * has to init BMI in order to set the host block size,
- */
- status = HTCWaitTarget(ar->arHtcTarget);
-
- if (status) {
- break;
- }
-
- A_MEMZERO(&connect,sizeof(connect));
- /* meta data is unused for now */
- connect.pMetaData = NULL;
- connect.MetaDataLength = 0;
- /* these fields are the same for all service endpoints */
- connect.EpCallbacks.pContext = ar;
- connect.EpCallbacks.EpTxCompleteMultiple = ar6000_tx_complete;
- connect.EpCallbacks.EpRecv = ar6000_rx;
- connect.EpCallbacks.EpRecvRefill = ar6000_rx_refill;
- connect.EpCallbacks.EpSendFull = ar6000_tx_queue_full;
- /* set the max queue depth so that our ar6000_tx_queue_full handler gets called.
- * Linux has the peculiarity of not providing flow control between the
- * NIC and the network stack. There is no API to indicate that a TX packet
- * was sent which could provide some back pressure to the network stack.
- * Under linux you would have to wait till the network stack consumed all sk_buffs
- * before any back-flow kicked in. Which isn't very friendly.
- * So we have to manage this ourselves */
- connect.MaxSendQueueDepth = MAX_DEFAULT_SEND_QUEUE_DEPTH;
- connect.EpCallbacks.RecvRefillWaterMark = AR6000_MAX_RX_BUFFERS / 4; /* set to 25 % */
- if (0 == connect.EpCallbacks.RecvRefillWaterMark) {
- connect.EpCallbacks.RecvRefillWaterMark++;
- }
- /* connect to control service */
- connect.ServiceID = WMI_CONTROL_SVC;
- status = ar6000_connectservice(ar,
- &connect,
- "WMI CONTROL");
- if (status) {
- break;
- }
-
- connect.LocalConnectionFlags |= HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING;
- /* limit the HTC message size on the send path, although we can receive A-MSDU frames of
- * 4K, we will only send ethernet-sized (802.3) frames on the send path. */
- connect.MaxSendMsgSize = WMI_MAX_TX_DATA_FRAME_LENGTH;
-
- /* to reduce the amount of committed memory for larger A_MSDU frames, use the recv-alloc threshold
- * mechanism for larger packets */
- connect.EpCallbacks.RecvAllocThreshold = AR6000_BUFFER_SIZE;
- connect.EpCallbacks.EpRecvAllocThresh = ar6000_alloc_amsdu_rxbuf;
-
- /* for the remaining data services set the connection flag to reduce dribbling,
- * if configured to do so */
- if (reduce_credit_dribble) {
- connect.ConnectionFlags |= HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE;
- /* the credit dribble trigger threshold is (reduce_credit_dribble - 1) for a value
- * of 0-3 */
- connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
- connect.ConnectionFlags |=
- ((u16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
- }
- /* connect to best-effort service */
- connect.ServiceID = WMI_DATA_BE_SVC;
-
- status = ar6000_connectservice(ar,
- &connect,
- "WMI DATA BE");
- if (status) {
- break;
- }
-
- /* connect to back-ground
- * map this to WMI LOW_PRI */
- connect.ServiceID = WMI_DATA_BK_SVC;
- status = ar6000_connectservice(ar,
- &connect,
- "WMI DATA BK");
- if (status) {
- break;
- }
-
- /* connect to Video service, map this to
- * to HI PRI */
- connect.ServiceID = WMI_DATA_VI_SVC;
- status = ar6000_connectservice(ar,
- &connect,
- "WMI DATA VI");
- if (status) {
- break;
- }
-
- /* connect to VO service, this is currently not
- * mapped to a WMI priority stream due to historical reasons.
- * WMI originally defined 3 priorities over 3 mailboxes
- * We can change this when WMI is reworked so that priorities are not
- * dependent on mailboxes */
- connect.ServiceID = WMI_DATA_VO_SVC;
- status = ar6000_connectservice(ar,
- &connect,
- "WMI DATA VO");
- if (status) {
- break;
- }
-
- A_ASSERT(arAc2EndpointID(ar,WMM_AC_BE) != 0);
- A_ASSERT(arAc2EndpointID(ar,WMM_AC_BK) != 0);
- A_ASSERT(arAc2EndpointID(ar,WMM_AC_VI) != 0);
- A_ASSERT(arAc2EndpointID(ar,WMM_AC_VO) != 0);
-
- /* setup access class priority mappings */
- ar->arAcStreamPriMap[WMM_AC_BK] = 0; /* lowest */
- ar->arAcStreamPriMap[WMM_AC_BE] = 1; /* */
- ar->arAcStreamPriMap[WMM_AC_VI] = 2; /* */
- ar->arAcStreamPriMap[WMM_AC_VO] = 3; /* highest */
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- if (setuphci && (NULL != ar6kHciTransCallbacks.setupTransport)) {
- struct hci_transport_misc_handles hciHandles;
-
- hciHandles.netDevice = ar->arNetDev;
- hciHandles.hifDevice = ar->arHifDevice;
- hciHandles.htcHandle = ar->arHtcTarget;
- status = (int)(ar6kHciTransCallbacks.setupTransport(&hciHandles));
- }
-#else
- if (setuphci) {
- /* setup HCI */
- status = ar6000_setup_hci(ar);
- }
-#endif
-
- } while (false);
-
- if (status) {
- ret = -EIO;
- goto ar6000_init_done;
- }
-
- if (regscanmode) {
- u32 param;
-
- if (BMIReadMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar,
- hi_option_flag),
- (u8 *)&param,
- 4) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("BMIReadMemory forsetting "
- "regscanmode failed\n"));
- return A_ERROR;
- }
-
- if (regscanmode == 1)
- param |= HI_OPTION_SKIP_REG_SCAN;
- else if (regscanmode == 2)
- param |= HI_OPTION_INIT_REG_SCAN;
-
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar,
- hi_option_flag),
- (u8 *)&param,
- 4) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("BMIWriteMemory forsetting "
- "regscanmode failed\n"));
- return A_ERROR;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Regulatory scan mode set\n"));
- }
-
- /*
- * give our connected endpoints some buffers
- */
-
- ar6000_rx_refill(ar, ar->arControlEp);
- ar6000_rx_refill(ar, arAc2EndpointID(ar,WMM_AC_BE));
-
- /*
- * We will post the receive buffers only for SPE or endpoint ping testing so we are
- * making it conditional on the 'bypasswmi' flag.
- */
- if (bypasswmi) {
- ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_BK));
- ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_VI));
- ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_VO));
- }
-
- /* allocate some buffers that handle larger AMSDU frames */
- ar6000_refill_amsdu_rxbufs(ar,AR6000_MAX_AMSDU_RX_BUFFERS);
-
- /* setup credit distribution */
- ar6000_setup_credit_dist(ar->arHtcTarget, &ar->arCreditStateInfo);
-
- /* Since cookies are used for HTC transports, they should be */
- /* initialized prior to enabling HTC. */
- ar6000_cookie_init(ar);
-
- /* start HTC */
- status = HTCStart(ar->arHtcTarget);
-
- if (status) {
- if (ar->arWmiEnabled == true) {
- wmi_shutdown(ar->arWmi);
- ar->arWmiEnabled = false;
- ar->arWmi = NULL;
- }
- ar6000_cookie_cleanup(ar);
- ret = -EIO;
- goto ar6000_init_done;
- }
-
- if (!bypasswmi) {
- /* Wait for Wmi event to be ready */
- timeleft = wait_event_interruptible_timeout(arEvent,
- (ar->arWmiReady == true), wmitimeout * HZ);
-
- if (ar->arVersion.abi_ver != AR6K_ABI_VERSION) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ABI Version mismatch: Host(0x%x), Target(0x%x)\n", AR6K_ABI_VERSION, ar->arVersion.abi_ver));
-#ifndef ATH6K_SKIP_ABI_VERSION_CHECK
- ret = -EIO;
- goto ar6000_init_done;
-#endif /* ATH6K_SKIP_ABI_VERSION_CHECK */
- }
-
- if(!timeleft || signal_pending(current))
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI is not ready or wait was interrupted\n"));
- ret = -EIO;
- goto ar6000_init_done;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() WMI is ready\n", __func__));
-
- /* Communicate the wmi protocol verision to the target */
- if ((ar6000_set_host_app_area(ar)) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the host app area\n"));
- }
- ar6000_target_config_wlan_params(ar);
- }
-
- ar->arNumDataEndPts = 1;
-
- if (bypasswmi) {
- /* for tests like endpoint ping, the MAC address needs to be non-zero otherwise
- * the data path through a raw socket is disabled */
- dev->dev_addr[0] = 0x00;
- dev->dev_addr[1] = 0x01;
- dev->dev_addr[2] = 0x02;
- dev->dev_addr[3] = 0xAA;
- dev->dev_addr[4] = 0xBB;
- dev->dev_addr[5] = 0xCC;
- }
-
-ar6000_init_done:
- rtnl_lock();
- dev_put(dev);
-
- return ret;
-}
-
-
-void
-ar6000_bitrate_rx(void *devt, s32 rateKbps)
-{
- struct ar6_softc *ar = (struct ar6_softc *)devt;
-
- ar->arBitRate = rateKbps;
- wake_up(&arEvent);
-}
-
-void
-ar6000_ratemask_rx(void *devt, u32 ratemask)
-{
- struct ar6_softc *ar = (struct ar6_softc *)devt;
-
- ar->arRateMask = ratemask;
- wake_up(&arEvent);
-}
-
-void
-ar6000_txPwr_rx(void *devt, u8 txPwr)
-{
- struct ar6_softc *ar = (struct ar6_softc *)devt;
-
- ar->arTxPwr = txPwr;
- wake_up(&arEvent);
-}
-
-
-void
-ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList)
-{
- struct ar6_softc *ar = (struct ar6_softc *)devt;
-
- memcpy(ar->arChannelList, chanList, numChan * sizeof (u16));
- ar->arNumChannels = numChan;
-
- wake_up(&arEvent);
-}
-
-u8 ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, u32 *mapNo)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
- u8 *datap;
- ATH_MAC_HDR *macHdr;
- u32 i, eptMap;
-
- (*mapNo) = 0;
- datap = A_NETBUF_DATA(skb);
- macHdr = (ATH_MAC_HDR *)(datap + sizeof(WMI_DATA_HDR));
- if (IEEE80211_IS_MULTICAST(macHdr->dstMac)) {
- return ENDPOINT_2;
- }
-
- eptMap = -1;
- for (i = 0; i < ar->arNodeNum; i ++) {
- if (IEEE80211_ADDR_EQ(macHdr->dstMac, ar->arNodeMap[i].macAddress)) {
- (*mapNo) = i + 1;
- ar->arNodeMap[i].txPending ++;
- return ar->arNodeMap[i].epId;
- }
-
- if ((eptMap == -1) && !ar->arNodeMap[i].txPending) {
- eptMap = i;
- }
- }
-
- if (eptMap == -1) {
- eptMap = ar->arNodeNum;
- ar->arNodeNum ++;
- A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM);
- }
-
- memcpy(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN);
-
- for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) {
- if (!ar->arTxPending[i]) {
- ar->arNodeMap[eptMap].epId = i;
- break;
- }
- // No free endpoint is available, start redistribution on the inuse endpoints.
- if (i == ENDPOINT_5) {
- ar->arNodeMap[eptMap].epId = ar->arNexEpId;
- ar->arNexEpId ++;
- if (ar->arNexEpId > ENDPOINT_5) {
- ar->arNexEpId = ENDPOINT_2;
- }
- }
- }
-
- (*mapNo) = eptMap + 1;
- ar->arNodeMap[eptMap].txPending ++;
-
- return ar->arNodeMap[eptMap].epId;
-}
-
-#ifdef DEBUG
-static void ar6000_dump_skb(struct sk_buff *skb)
-{
- u_char *ch;
- for (ch = A_NETBUF_DATA(skb);
- (unsigned long)ch < ((unsigned long)A_NETBUF_DATA(skb) +
- A_NETBUF_LEN(skb)); ch++)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("%2.2x ", *ch));
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("\n"));
-}
-#endif
-
-#ifdef HTC_TEST_SEND_PKTS
-static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *skb);
-#endif
-
-static int
-ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
-{
-#define AC_NOT_MAPPED 99
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
- u8 ac = AC_NOT_MAPPED;
- HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED;
- u32 mapNo = 0;
- int len;
- struct ar_cookie *cookie;
- bool checkAdHocPsMapping = false,bMoreData = false;
- HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG;
- u8 dot11Hdr = processDot11Hdr;
-#ifdef CONFIG_PM
- if (ar->arWowState != WLAN_WOW_STATE_NONE) {
- A_NETBUF_FREE(skb);
- return 0;
- }
-#endif /* CONFIG_PM */
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar6000_data_tx start - skb=0x%lx, data=0x%lx, len=0x%x\n",
- (unsigned long)skb, (unsigned long)A_NETBUF_DATA(skb),
- A_NETBUF_LEN(skb)));
-
- /* If target is not associated */
- if( (!ar->arConnected && !bypasswmi)
-#ifdef CONFIG_HOST_TCMD_SUPPORT
- /* TCMD doesn't support any data, free the buf and return */
- || (ar->arTargetMode == AR6000_TCMD_MODE)
-#endif
- ) {
- A_NETBUF_FREE(skb);
- return 0;
- }
-
- do {
-
- if (ar->arWmiReady == false && bypasswmi == 0) {
- break;
- }
-
-#ifdef BLOCK_TX_PATH_FLAG
- if (blocktx) {
- break;
- }
-#endif /* BLOCK_TX_PATH_FLAG */
-
- /* AP mode Power save processing */
- /* If the dst STA is in sleep state, queue the pkt in its PS queue */
-
- if (ar->arNetworkType == AP_NETWORK) {
- ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb);
- sta_t *conn = NULL;
-
- /* If the dstMac is a Multicast address & atleast one of the
- * associated STA is in PS mode, then queue the pkt to the
- * mcastq
- */
- if (IEEE80211_IS_MULTICAST(datap->dstMac)) {
- u8 ctr=0;
- bool qMcast=false;
-
-
- for (ctr=0; ctr<AP_MAX_NUM_STA; ctr++) {
- if (STA_IS_PWR_SLEEP((&ar->sta_list[ctr]))) {
- qMcast = true;
- }
- }
- if(qMcast) {
-
- /* If this transmit is not because of a Dtim Expiry q it */
- if (ar->DTIMExpired == false) {
- bool isMcastqEmpty = false;
-
- A_MUTEX_LOCK(&ar->mcastpsqLock);
- isMcastqEmpty = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq);
- A_NETBUF_ENQUEUE(&ar->mcastpsq, skb);
- A_MUTEX_UNLOCK(&ar->mcastpsqLock);
-
- /* If this is the first Mcast pkt getting queued
- * indicate to the target to set the BitmapControl LSB
- * of the TIM IE.
- */
- if (isMcastqEmpty) {
- wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 1);
- }
- return 0;
- } else {
- /* This transmit is because of Dtim expiry. Determine if
- * MoreData bit has to be set.
- */
- A_MUTEX_LOCK(&ar->mcastpsqLock);
- if(!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
- bMoreData = true;
- }
- A_MUTEX_UNLOCK(&ar->mcastpsqLock);
- }
- }
- } else {
- conn = ieee80211_find_conn(ar, datap->dstMac);
- if (conn) {
- if (STA_IS_PWR_SLEEP(conn)) {
- /* If this transmit is not because of a PsPoll q it*/
- if (!STA_IS_PS_POLLED(conn)) {
- bool isPsqEmpty = false;
- /* Queue the frames if the STA is sleeping */
- A_MUTEX_LOCK(&conn->psqLock);
- isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq);
- A_NETBUF_ENQUEUE(&conn->psq, skb);
- A_MUTEX_UNLOCK(&conn->psqLock);
-
- /* If this is the first pkt getting queued
- * for this STA, update the PVB for this STA
- */
- if (isPsqEmpty) {
- wmi_set_pvb_cmd(ar->arWmi, conn->aid, 1);
- }
-
- return 0;
- } else {
- /* This tx is because of a PsPoll. Determine if
- * MoreData bit has to be set
- */
- A_MUTEX_LOCK(&conn->psqLock);
- if (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) {
- bMoreData = true;
- }
- A_MUTEX_UNLOCK(&conn->psqLock);
- }
- }
- } else {
-
- /* non existent STA. drop the frame */
- A_NETBUF_FREE(skb);
- return 0;
- }
- }
- }
-
- if (ar->arWmiEnabled) {
- u8 csumStart=0;
- u8 csumDest=0;
- u8 csum=skb->ip_summed;
- if(csumOffload && (csum==CHECKSUM_PARTIAL)){
- csumStart = (skb->head + skb->csum_start - skb_network_header(skb) +
- sizeof(ATH_LLC_SNAP_HDR));
- csumDest=skb->csum_offset+csumStart;
- }
- if (A_NETBUF_HEADROOM(skb) < dev->hard_header_len - LINUX_HACK_FUDGE_FACTOR) {
- struct sk_buff *newbuf;
-
- /*
- * We really should have gotten enough headroom but sometimes
- * we still get packets with not enough headroom. Copy the packet.
- */
- len = A_NETBUF_LEN(skb);
- newbuf = A_NETBUF_ALLOC(len);
- if (newbuf == NULL) {
- break;
- }
- A_NETBUF_PUT(newbuf, len);
- memcpy(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len);
- A_NETBUF_FREE(skb);
- skb = newbuf;
- /* fall through and assemble header */
- }
-
- if (dot11Hdr) {
- if (wmi_dot11_hdr_add(ar->arWmi,skb,ar->arNetworkType) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx-wmi_dot11_hdr_add failed\n"));
- break;
- }
- } else {
- if (wmi_dix_2_dot3(ar->arWmi, skb) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_dix_2_dot3 failed\n"));
- break;
- }
- }
- if(csumOffload && (csum ==CHECKSUM_PARTIAL)){
- WMI_TX_META_V2 metaV2;
- metaV2.csumStart =csumStart;
- metaV2.csumDest = csumDest;
- metaV2.csumFlags = 0x1;/*instruct target to calculate checksum*/
- if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,
- WMI_META_VERSION_2,&metaV2) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n"));
- break;
- }
-
- }
- else
- {
- if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,0,NULL) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n"));
- break;
- }
- }
-
-
- if ((ar->arNetworkType == ADHOC_NETWORK) &&
- ar->arIbssPsEnable && ar->arConnected) {
- /* flag to check adhoc mapping once we take the lock below: */
- checkAdHocPsMapping = true;
-
- } else {
- /* get the stream mapping */
- ac = wmi_implicit_create_pstream(ar->arWmi, skb, 0, ar->arWmmEnabled);
- }
-
- } else {
- EPPING_HEADER *eppingHdr;
-
- eppingHdr = A_NETBUF_DATA(skb);
-
- if (IS_EPPING_PACKET(eppingHdr)) {
- /* the stream ID is mapped to an access class */
- ac = eppingHdr->StreamNo_h;
- /* some EPPING packets cannot be dropped no matter what access class it was
- * sent on. We can change the packet tag to guarantee it will not get dropped */
- if (IS_EPING_PACKET_NO_DROP(eppingHdr)) {
- htc_tag = AR6K_CONTROL_PKT_TAG;
- }
-
- if (ac == HCI_TRANSPORT_STREAM_NUM) {
- /* pass this to HCI */
-#ifndef EXPORT_HCI_BRIDGE_INTERFACE
- if (!hci_test_send(ar,skb)) {
- return 0;
- }
-#endif
- /* set AC to discard this skb */
- ac = AC_NOT_MAPPED;
- } else {
- /* a quirk of linux, the payload of the frame is 32-bit aligned and thus the addition
- * of the HTC header will mis-align the start of the HTC frame, so we add some
- * padding which will be stripped off in the target */
- if (EPPING_ALIGNMENT_PAD > 0) {
- A_NETBUF_PUSH(skb, EPPING_ALIGNMENT_PAD);
- }
- }
-
- } else {
- /* not a ping packet, drop it */
- ac = AC_NOT_MAPPED;
- }
- }
-
- } while (false);
-
- /* did we succeed ? */
- if ((ac == AC_NOT_MAPPED) && !checkAdHocPsMapping) {
- /* cleanup and exit */
- A_NETBUF_FREE(skb);
- AR6000_STAT_INC(ar, tx_dropped);
- AR6000_STAT_INC(ar, tx_aborted_errors);
- return 0;
- }
-
- cookie = NULL;
-
- /* take the lock to protect driver data */
- AR6000_SPIN_LOCK(&ar->arLock, 0);
-
- do {
-
- if (checkAdHocPsMapping) {
- eid = ar6000_ibss_map_epid(skb, dev, &mapNo);
- }else {
- eid = arAc2EndpointID (ar, ac);
- }
- /* validate that the endpoint is connected */
- if (eid == 0 || eid == ENDPOINT_UNUSED ) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" eid %d is NOT mapped!\n", eid));
- break;
- }
- /* allocate resource for this packet */
- cookie = ar6000_alloc_cookie(ar);
-
- if (cookie != NULL) {
- /* update counts while the lock is held */
- ar->arTxPending[eid]++;
- ar->arTotalTxDataPending++;
- }
-
- } while (false);
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- if (cookie != NULL) {
- cookie->arc_bp[0] = (unsigned long)skb;
- cookie->arc_bp[1] = mapNo;
- SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
- cookie,
- A_NETBUF_DATA(skb),
- A_NETBUF_LEN(skb),
- eid,
- htc_tag);
-
-#ifdef DEBUG
- if (debugdriver >= 3) {
- ar6000_dump_skb(skb);
- }
-#endif
-#ifdef HTC_TEST_SEND_PKTS
- DoHTCSendPktsTest(ar,mapNo,eid,skb);
-#endif
- /* HTC interface is asynchronous, if this fails, cleanup will happen in
- * the ar6000_tx_complete callback */
- HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
- } else {
- /* no packet to send, cleanup */
- A_NETBUF_FREE(skb);
- AR6000_STAT_INC(ar, tx_dropped);
- AR6000_STAT_INC(ar, tx_aborted_errors);
- }
-
- return 0;
-}
-
-int
-ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
- struct ar_cookie *cookie;
- HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED;
-
- cookie = NULL;
- AR6000_SPIN_LOCK(&ar->arLock, 0);
-
- /* For now we send ACL on BE endpoint: We can also have a dedicated EP */
- eid = arAc2EndpointID (ar, 0);
- /* allocate resource for this packet */
- cookie = ar6000_alloc_cookie(ar);
-
- if (cookie != NULL) {
- /* update counts while the lock is held */
- ar->arTxPending[eid]++;
- ar->arTotalTxDataPending++;
- }
-
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- if (cookie != NULL) {
- cookie->arc_bp[0] = (unsigned long)skb;
- cookie->arc_bp[1] = 0;
- SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
- cookie,
- A_NETBUF_DATA(skb),
- A_NETBUF_LEN(skb),
- eid,
- AR6K_DATA_PKT_TAG);
-
- /* HTC interface is asynchronous, if this fails, cleanup will happen in
- * the ar6000_tx_complete callback */
- HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
- } else {
- /* no packet to send, cleanup */
- A_NETBUF_FREE(skb);
- AR6000_STAT_INC(ar, tx_dropped);
- AR6000_STAT_INC(ar, tx_aborted_errors);
- }
- return 0;
-}
-
-
-#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
-static void
-tvsub(register struct timeval *out, register struct timeval *in)
-{
- if((out->tv_usec -= in->tv_usec) < 0) {
- out->tv_sec--;
- out->tv_usec += 1000000;
- }
- out->tv_sec -= in->tv_sec;
-}
-
-void
-applyAPTCHeuristics(struct ar6_softc *ar)
-{
- u32 duration;
- u32 numbytes;
- u32 throughput;
- struct timeval ts;
- int status;
-
- AR6000_SPIN_LOCK(&ar->arLock, 0);
-
- if ((enableAPTCHeuristics) && (!aptcTR.timerScheduled)) {
- do_gettimeofday(&ts);
- tvsub(&ts, &aptcTR.samplingTS);
- duration = ts.tv_sec * 1000 + ts.tv_usec / 1000; /* ms */
- numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived;
-
- if (duration > APTC_TRAFFIC_SAMPLING_INTERVAL) {
- /* Initialize the time stamp and byte count */
- aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0;
- do_gettimeofday(&aptcTR.samplingTS);
-
- /* Calculate and decide based on throughput thresholds */
- throughput = ((numbytes * 8) / duration);
- if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) {
- /* Disable Sleep and schedule a timer */
- A_ASSERT(ar->arWmiReady == true);
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER);
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
- aptcTR.timerScheduled = true;
- }
- }
- }
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-}
-#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
-
-static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket)
-{
- struct ar6_softc *ar = (struct ar6_softc *)Context;
- HTC_SEND_FULL_ACTION action = HTC_SEND_FULL_KEEP;
- bool stopNet = false;
- HTC_ENDPOINT_ID Endpoint = HTC_GET_ENDPOINT_FROM_PKT(pPacket);
-
- do {
-
- if (bypasswmi) {
- int accessClass;
-
- if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_CONTROL_PKT_TAG) {
- /* don't drop special control packets */
- break;
- }
-
- accessClass = arEndpoint2Ac(ar,Endpoint);
- /* for endpoint ping testing drop Best Effort and Background */
- if ((accessClass == WMM_AC_BE) || (accessClass == WMM_AC_BK)) {
- action = HTC_SEND_FULL_DROP;
- stopNet = false;
- } else {
- /* keep but stop the netqueues */
- stopNet = true;
- }
- break;
- }
-
- if (Endpoint == ar->arControlEp) {
- /* under normal WMI if this is getting full, then something is running rampant
- * the host should not be exhausting the WMI queue with too many commands
- * the only exception to this is during testing using endpointping */
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- /* set flag to handle subsequent messages */
- ar->arWMIControlEpFull = true;
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI Control Endpoint is FULL!!! \n"));
- /* no need to stop the network */
- stopNet = false;
- break;
- }
-
- /* if we get here, we are dealing with data endpoints getting full */
-
- if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_CONTROL_PKT_TAG) {
- /* don't drop control packets issued on ANY data endpoint */
- break;
- }
-
- if (ar->arNetworkType == ADHOC_NETWORK) {
- /* in adhoc mode, we cannot differentiate traffic priorities so there is no need to
- * continue, however we should stop the network */
- stopNet = true;
- break;
- }
- /* the last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for the highest
- * active stream */
- if (ar->arAcStreamPriMap[arEndpoint2Ac(ar,Endpoint)] < ar->arHiAcStreamActivePri &&
- ar->arCookieCount <= MAX_HI_COOKIE_NUM) {
- /* this stream's priority is less than the highest active priority, we
- * give preference to the highest priority stream by directing
- * HTC to drop the packet that overflowed */
- action = HTC_SEND_FULL_DROP;
- /* since we are dropping packets, no need to stop the network */
- stopNet = false;
- break;
- }
-
- } while (false);
-
- if (stopNet) {
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- ar->arNetQueueStopped = true;
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- /* one of the data endpoints queues is getting full..need to stop network stack
- * the queue will resume in ar6000_tx_complete() */
- netif_stop_queue(ar->arNetDev);
- }
-
- return action;
-}
-
-
-static void
-ar6000_tx_complete(void *Context, struct htc_packet_queue *pPacketQueue)
-{
- struct ar6_softc *ar = (struct ar6_softc *)Context;
- u32 mapNo = 0;
- int status;
- struct ar_cookie * ar_cookie;
- HTC_ENDPOINT_ID eid;
- bool wakeEvent = false;
- struct sk_buff_head skb_queue;
- struct htc_packet *pPacket;
- struct sk_buff *pktSkb;
- bool flushing = false;
-
- skb_queue_head_init(&skb_queue);
-
- /* lock the driver as we update internal state */
- AR6000_SPIN_LOCK(&ar->arLock, 0);
-
- /* reap completed packets */
- while (!HTC_QUEUE_EMPTY(pPacketQueue)) {
-
- pPacket = HTC_PACKET_DEQUEUE(pPacketQueue);
-
- ar_cookie = (struct ar_cookie *)pPacket->pPktContext;
- A_ASSERT(ar_cookie);
-
- status = pPacket->Status;
- pktSkb = (struct sk_buff *)ar_cookie->arc_bp[0];
- eid = pPacket->Endpoint;
- mapNo = ar_cookie->arc_bp[1];
-
- A_ASSERT(pktSkb);
- A_ASSERT(pPacket->pBuffer == A_NETBUF_DATA(pktSkb));
-
- /* add this to the list, use faster non-lock API */
- __skb_queue_tail(&skb_queue,pktSkb);
-
- if (!status) {
- A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(pktSkb));
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar6000_tx_complete skb=0x%lx data=0x%lx len=0x%x eid=%d ",
- (unsigned long)pktSkb, (unsigned long)pPacket->pBuffer,
- pPacket->ActualLength,
- eid));
-
- ar->arTxPending[eid]--;
-
- if ((eid != ar->arControlEp) || bypasswmi) {
- ar->arTotalTxDataPending--;
- }
-
- if (eid == ar->arControlEp)
- {
- if (ar->arWMIControlEpFull) {
- /* since this packet completed, the WMI EP is no longer full */
- ar->arWMIControlEpFull = false;
- }
-
- if (ar->arTxPending[eid] == 0) {
- wakeEvent = true;
- }
- }
-
- if (status) {
- if (status == A_ECANCELED) {
- /* a packet was flushed */
- flushing = true;
- }
- AR6000_STAT_INC(ar, tx_errors);
- if (status != A_NO_RESOURCE) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() -TX ERROR, status: 0x%x\n", __func__,
- status));
- }
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("OK\n"));
- flushing = false;
- AR6000_STAT_INC(ar, tx_packets);
- ar->arNetStats.tx_bytes += A_NETBUF_LEN(pktSkb);
-#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- aptcTR.bytesTransmitted += a_netbuf_to_len(pktSkb);
- applyAPTCHeuristics(ar);
-#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
- }
-
- // TODO this needs to be looked at
- if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable
- && (eid != ar->arControlEp) && mapNo)
- {
- mapNo --;
- ar->arNodeMap[mapNo].txPending --;
-
- if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) {
- u32 i;
- for (i = ar->arNodeNum; i > 0; i --) {
- if (!ar->arNodeMap[i - 1].txPending) {
- A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_mapping));
- ar->arNodeNum --;
- } else {
- break;
- }
- }
- }
- }
-
- ar6000_free_cookie(ar, ar_cookie);
-
- if (ar->arNetQueueStopped) {
- ar->arNetQueueStopped = false;
- }
- }
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- /* lock is released, we can freely call other kernel APIs */
-
- /* free all skbs in our local list */
- while (!skb_queue_empty(&skb_queue)) {
- /* use non-lock version */
- pktSkb = __skb_dequeue(&skb_queue);
- A_NETBUF_FREE(pktSkb);
- }
-
- if ((ar->arConnected == true) || bypasswmi) {
- if (!flushing) {
- /* don't wake the queue if we are flushing, other wise it will just
- * keep queueing packets, which will keep failing */
- netif_wake_queue(ar->arNetDev);
- }
- }
-
- if (wakeEvent) {
- wake_up(&arEvent);
- }
-
-}
-
-sta_t *
-ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr)
-{
- sta_t *conn = NULL;
- u8 i, max_conn;
-
- switch(ar->arNetworkType) {
- case AP_NETWORK:
- max_conn = AP_MAX_NUM_STA;
- break;
- default:
- max_conn=0;
- break;
- }
-
- for (i = 0; i < max_conn; i++) {
- if (IEEE80211_ADDR_EQ(node_addr, ar->sta_list[i].mac)) {
- conn = &ar->sta_list[i];
- break;
- }
- }
-
- return conn;
-}
-
-sta_t *ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid)
-{
- sta_t *conn = NULL;
- u8 ctr;
-
- for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
- if (ar->sta_list[ctr].aid == aid) {
- conn = &ar->sta_list[ctr];
- break;
- }
- }
- return conn;
-}
-
-/*
- * Receive event handler. This is called by HTC when a packet is received
- */
-int pktcount;
-static void
-ar6000_rx(void *Context, struct htc_packet *pPacket)
-{
- struct ar6_softc *ar = (struct ar6_softc *)Context;
- struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext;
- int minHdrLen;
- u8 containsDot11Hdr = 0;
- int status = pPacket->Status;
- HTC_ENDPOINT_ID ept = pPacket->Endpoint;
-
- A_ASSERT((status) ||
- (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN)));
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx ar=0x%lx eid=%d, skb=0x%lx, data=0x%lx, len=0x%x status:%d",
- (unsigned long)ar, ept, (unsigned long)skb, (unsigned long)pPacket->pBuffer,
- pPacket->ActualLength, status));
- if (status) {
- if (status != A_ECANCELED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("RX ERR (%d) \n",status));
- }
- }
-
- /* take lock to protect buffer counts
- * and adaptive power throughput state */
- AR6000_SPIN_LOCK(&ar->arLock, 0);
-
- if (!status) {
- AR6000_STAT_INC(ar, rx_packets);
- ar->arNetStats.rx_bytes += pPacket->ActualLength;
-#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- aptcTR.bytesReceived += a_netbuf_to_len(skb);
- applyAPTCHeuristics(ar);
-#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
-
- A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN);
- A_NETBUF_PULL(skb, HTC_HEADER_LEN);
-
-#ifdef DEBUG
- if (debugdriver >= 2) {
- ar6000_dump_skb(skb);
- }
-#endif /* DEBUG */
- }
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- skb->dev = ar->arNetDev;
- if (status) {
- AR6000_STAT_INC(ar, rx_errors);
- A_NETBUF_FREE(skb);
- } else if (ar->arWmiEnabled == true) {
- if (ept == ar->arControlEp) {
- /*
- * this is a wmi control msg
- */
-#ifdef CONFIG_PM
- ar6000_check_wow_status(ar, skb, true);
-#endif /* CONFIG_PM */
- wmi_control_rx(ar->arWmi, skb);
- } else {
- WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb);
- bool is_amsdu;
- u8 tid;
-
- /*
- * This check can be removed if after a while we do not
- * see the warning. For now we leave it to ensure
- * we drop these frames accordingly in case the
- * target generates them for some reason. These
- * were used for an internal PAL but that's not
- * used or supported anymore. These frames should
- * not come up from the target.
- */
- if (WARN_ON(WMI_DATA_HDR_GET_DATA_TYPE(dhdr) ==
- WMI_DATA_HDR_DATA_TYPE_ACL)) {
- AR6000_STAT_INC(ar, rx_errors);
- A_NETBUF_FREE(skb);
- return;
- }
-
-#ifdef CONFIG_PM
- ar6000_check_wow_status(ar, NULL, false);
-#endif /* CONFIG_PM */
- /*
- * this is a wmi data packet
- */
- // NWF
-
- if (processDot11Hdr) {
- minHdrLen = sizeof(WMI_DATA_HDR) + sizeof(struct ieee80211_frame) + sizeof(ATH_LLC_SNAP_HDR);
- } else {
- minHdrLen = sizeof (WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) +
- sizeof(ATH_LLC_SNAP_HDR);
- }
-
- /* In the case of AP mode we may receive NULL data frames
- * that do not have LLC hdr. They are 16 bytes in size.
- * Allow these frames in the AP mode.
- * ACL data frames don't follow ethernet frame bounds for
- * min length
- */
- if (ar->arNetworkType != AP_NETWORK &&
- ((pPacket->ActualLength < minHdrLen) ||
- (pPacket->ActualLength > AR6000_MAX_RX_MESSAGE_SIZE)))
- {
- /*
- * packet is too short or too long
- */
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("TOO SHORT or TOO LONG\n"));
- AR6000_STAT_INC(ar, rx_errors);
- AR6000_STAT_INC(ar, rx_length_errors);
- A_NETBUF_FREE(skb);
- } else {
- u16 seq_no;
- u8 meta_type;
-
-#if 0
- /* Access RSSI values here */
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("RSSI %d\n",
- ((WMI_DATA_HDR *) A_NETBUF_DATA(skb))->rssi));
-#endif
- /* Get the Power save state of the STA */
- if (ar->arNetworkType == AP_NETWORK) {
- sta_t *conn = NULL;
- u8 psState=0,prevPsState;
- ATH_MAC_HDR *datap=NULL;
- u16 offset;
-
- meta_type = WMI_DATA_HDR_GET_META(dhdr);
-
- psState = (((WMI_DATA_HDR *)A_NETBUF_DATA(skb))->info
- >> WMI_DATA_HDR_PS_SHIFT) & WMI_DATA_HDR_PS_MASK;
-
- offset = sizeof(WMI_DATA_HDR);
-
- switch (meta_type) {
- case 0:
- break;
- case WMI_META_VERSION_1:
- offset += sizeof(WMI_RX_META_V1);
- break;
- case WMI_META_VERSION_2:
- offset += sizeof(WMI_RX_META_V2);
- break;
- default:
- break;
- }
-
- datap = (ATH_MAC_HDR *)(A_NETBUF_DATA(skb)+offset);
- conn = ieee80211_find_conn(ar, datap->srcMac);
-
- if (conn) {
- /* if there is a change in PS state of the STA,
- * take appropriate steps.
- * 1. If Sleep-->Awake, flush the psq for the STA
- * Clear the PVB for the STA.
- * 2. If Awake-->Sleep, Starting queueing frames
- * the STA.
- */
- prevPsState = STA_IS_PWR_SLEEP(conn);
- if (psState) {
- STA_SET_PWR_SLEEP(conn);
- } else {
- STA_CLR_PWR_SLEEP(conn);
- }
-
- if (prevPsState ^ STA_IS_PWR_SLEEP(conn)) {
-
- if (!STA_IS_PWR_SLEEP(conn)) {
-
- A_MUTEX_LOCK(&conn->psqLock);
- while (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) {
- struct sk_buff *skb=NULL;
-
- skb = A_NETBUF_DEQUEUE(&conn->psq);
- A_MUTEX_UNLOCK(&conn->psqLock);
- ar6000_data_tx(skb,ar->arNetDev);
- A_MUTEX_LOCK(&conn->psqLock);
- }
- A_MUTEX_UNLOCK(&conn->psqLock);
- /* Clear the PVB for this STA */
- wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0);
- }
- }
- } else {
- /* This frame is from a STA that is not associated*/
- A_ASSERT(false);
- }
-
- /* Drop NULL data frames here */
- if((pPacket->ActualLength < minHdrLen) ||
- (pPacket->ActualLength > AR6000_MAX_RX_MESSAGE_SIZE)) {
- A_NETBUF_FREE(skb);
- goto rx_done;
- }
- }
-
- is_amsdu = WMI_DATA_HDR_IS_AMSDU(dhdr) ? true : false;
- tid = WMI_DATA_HDR_GET_UP(dhdr);
- seq_no = WMI_DATA_HDR_GET_SEQNO(dhdr);
- meta_type = WMI_DATA_HDR_GET_META(dhdr);
- containsDot11Hdr = WMI_DATA_HDR_GET_DOT11(dhdr);
-
- wmi_data_hdr_remove(ar->arWmi, skb);
-
- switch (meta_type) {
- case WMI_META_VERSION_1:
- {
- WMI_RX_META_V1 *pMeta = (WMI_RX_META_V1 *)A_NETBUF_DATA(skb);
- A_PRINTF("META %d %d %d %d %x\n", pMeta->status, pMeta->rix, pMeta->rssi, pMeta->channel, pMeta->flags);
- A_NETBUF_PULL((void*)skb, sizeof(WMI_RX_META_V1));
- break;
- }
- case WMI_META_VERSION_2:
- {
- WMI_RX_META_V2 *pMeta = (WMI_RX_META_V2 *)A_NETBUF_DATA(skb);
- if(pMeta->csumFlags & 0x1){
- skb->ip_summed=CHECKSUM_COMPLETE;
- skb->csum=(pMeta->csum);
- }
- A_NETBUF_PULL((void*)skb, sizeof(WMI_RX_META_V2));
- break;
- }
- default:
- break;
- }
-
- A_ASSERT(status == 0);
-
- /* NWF: print the 802.11 hdr bytes */
- if(containsDot11Hdr) {
- status = wmi_dot11_hdr_remove(ar->arWmi,skb);
- } else if(!is_amsdu) {
- status = wmi_dot3_2_dix(skb);
- }
-
- if (status) {
- /* Drop frames that could not be processed (lack of memory, etc.) */
- A_NETBUF_FREE(skb);
- goto rx_done;
- }
-
- if ((ar->arNetDev->flags & IFF_UP) == IFF_UP) {
- if (ar->arNetworkType == AP_NETWORK) {
- struct sk_buff *skb1 = NULL;
- ATH_MAC_HDR *datap;
-
- datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb);
- if (IEEE80211_IS_MULTICAST(datap->dstMac)) {
- /* Bcast/Mcast frames should be sent to the OS
- * stack as well as on the air.
- */
- skb1 = skb_copy(skb,GFP_ATOMIC);
- } else {
- /* Search for a connected STA with dstMac as
- * the Mac address. If found send the frame to
- * it on the air else send the frame up the
- * stack
- */
- sta_t *conn = NULL;
- conn = ieee80211_find_conn(ar, datap->dstMac);
-
- if (conn && ar->intra_bss) {
- skb1 = skb;
- skb = NULL;
- } else if(conn && !ar->intra_bss) {
- A_NETBUF_FREE(skb);
- skb = NULL;
- }
- }
- if (skb1) {
- ar6000_data_tx(skb1, ar->arNetDev);
- }
- }
- }
- aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, is_amsdu, (void **)&skb);
- ar6000_deliver_frames_to_nw_stack((void *) ar->arNetDev, (void *)skb);
- }
- }
- } else {
- if (EPPING_ALIGNMENT_PAD > 0) {
- A_NETBUF_PULL(skb, EPPING_ALIGNMENT_PAD);
- }
- ar6000_deliver_frames_to_nw_stack((void *)ar->arNetDev, (void *)skb);
- }
-
-rx_done:
-
- return;
-}
-
-static void
-ar6000_deliver_frames_to_nw_stack(void *dev, void *osbuf)
-{
- struct sk_buff *skb = (struct sk_buff *)osbuf;
-
- if(skb) {
- skb->dev = dev;
- if ((skb->dev->flags & IFF_UP) == IFF_UP) {
-#ifdef CONFIG_PM
- ar6000_check_wow_status((struct ar6_softc *)ar6k_priv(dev), skb, false);
-#endif /* CONFIG_PM */
- skb->protocol = eth_type_trans(skb, skb->dev);
- /*
- * If this routine is called on a ISR (Hard IRQ) or DSR (Soft IRQ)
- * or tasklet use the netif_rx to deliver the packet to the stack
- * netif_rx will queue the packet onto the receive queue and mark
- * the softirq thread has a pending action to complete. Kernel will
- * schedule the softIrq kernel thread after processing the DSR.
- *
- * If this routine is called on a process context, use netif_rx_ni
- * which will schedle the softIrq kernel thread after queuing the packet.
- */
- if (in_interrupt()) {
- netif_rx(skb);
- } else {
- netif_rx_ni(skb);
- }
- } else {
- A_NETBUF_FREE(skb);
- }
- }
-}
-
-#if 0
-static void
-ar6000_deliver_frames_to_bt_stack(void *dev, void *osbuf)
-{
- struct sk_buff *skb = (struct sk_buff *)osbuf;
-
- if(skb) {
- skb->dev = dev;
- if ((skb->dev->flags & IFF_UP) == IFF_UP) {
- skb->protocol = htons(ETH_P_CONTROL);
- netif_rx(skb);
- } else {
- A_NETBUF_FREE(skb);
- }
- }
-}
-#endif
-
-static void
-ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint)
-{
- struct ar6_softc *ar = (struct ar6_softc *)Context;
- void *osBuf;
- int RxBuffers;
- int buffersToRefill;
- struct htc_packet *pPacket;
- struct htc_packet_queue queue;
-
- buffersToRefill = (int)AR6000_MAX_RX_BUFFERS -
- HTCGetNumRecvBuffers(ar->arHtcTarget, Endpoint);
-
- if (buffersToRefill <= 0) {
- /* fast return, nothing to fill */
- return;
- }
-
- INIT_HTC_PACKET_QUEUE(&queue);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx_refill: providing htc with %d buffers at eid=%d\n",
- buffersToRefill, Endpoint));
-
- for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) {
- osBuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE);
- if (NULL == osBuf) {
- break;
- }
- /* the HTC packet wrapper is at the head of the reserved area
- * in the skb */
- pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf));
- /* set re-fill info */
- SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_BUFFER_SIZE,Endpoint);
- /* add to queue */
- HTC_PACKET_ENQUEUE(&queue,pPacket);
- }
-
- if (!HTC_QUEUE_EMPTY(&queue)) {
- /* add packets */
- HTCAddReceivePktMultiple(ar->arHtcTarget, &queue);
- }
-
-}
-
- /* clean up our amsdu buffer list */
-static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar)
-{
- struct htc_packet *pPacket;
- void *osBuf;
-
- /* empty AMSDU buffer queue and free OS bufs */
- while (true) {
-
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue);
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- if (NULL == pPacket) {
- break;
- }
-
- osBuf = pPacket->pPktContext;
- if (NULL == osBuf) {
- A_ASSERT(false);
- break;
- }
-
- A_NETBUF_FREE(osBuf);
- }
-
-}
-
-
- /* refill the amsdu buffer list */
-static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count)
-{
- struct htc_packet *pPacket;
- void *osBuf;
-
- while (Count > 0) {
- osBuf = A_NETBUF_ALLOC(AR6000_AMSDU_BUFFER_SIZE);
- if (NULL == osBuf) {
- break;
- }
- /* the HTC packet wrapper is at the head of the reserved area
- * in the skb */
- pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf));
- /* set re-fill info */
- SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_AMSDU_BUFFER_SIZE,0);
-
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- /* put it in the list */
- HTC_PACKET_ENQUEUE(&ar->amsdu_rx_buffer_queue,pPacket);
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- Count--;
- }
-
-}
-
- /* callback to allocate a large receive buffer for a pending packet. This function is called when
- * an HTC packet arrives whose length exceeds a threshold value
- *
- * We use a pre-allocated list of buffers of maximum AMSDU size (4K). Under linux it is more optimal to
- * keep the allocation size the same to optimize cached-slab allocations.
- *
- * */
-static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length)
-{
- struct htc_packet *pPacket = NULL;
- struct ar6_softc *ar = (struct ar6_softc *)Context;
- int refillCount = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_alloc_amsdu_rxbuf: eid=%d, Length:%d\n",Endpoint,Length));
-
- do {
-
- if (Length <= AR6000_BUFFER_SIZE) {
- /* shouldn't be getting called on normal sized packets */
- A_ASSERT(false);
- break;
- }
-
- if (Length > AR6000_AMSDU_BUFFER_SIZE) {
- A_ASSERT(false);
- break;
- }
-
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- /* allocate a packet from the list */
- pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue);
- /* see if we need to refill again */
- refillCount = AR6000_MAX_AMSDU_RX_BUFFERS - HTC_PACKET_QUEUE_DEPTH(&ar->amsdu_rx_buffer_queue);
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- if (NULL == pPacket) {
- break;
- }
- /* set actual endpoint ID */
- pPacket->Endpoint = Endpoint;
-
- } while (false);
-
- if (refillCount >= AR6000_AMSDU_REFILL_THRESHOLD) {
- ar6000_refill_amsdu_rxbufs(ar,refillCount);
- }
-
- return pPacket;
-}
-
-static void
-ar6000_set_multicast_list(struct net_device *dev)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000: Multicast filter not supported\n"));
-}
-
-static struct net_device_stats *
-ar6000_get_stats(struct net_device *dev)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
- return &ar->arNetStats;
-}
-
-void
-ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, u32 sw_ver, u32 abi_ver)
-{
- struct ar6_softc *ar = (struct ar6_softc *)devt;
- struct net_device *dev = ar->arNetDev;
-
- memcpy(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN);
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
- dev->dev_addr[0], dev->dev_addr[1],
- dev->dev_addr[2], dev->dev_addr[3],
- dev->dev_addr[4], dev->dev_addr[5]));
-
- ar->arPhyCapability = phyCap;
- ar->arVersion.wlan_ver = sw_ver;
- ar->arVersion.abi_ver = abi_ver;
-
- snprintf(ar->wdev->wiphy->fw_version, sizeof(ar->wdev->wiphy->fw_version),
- "%u:%u:%u:%u",
- (ar->arVersion.wlan_ver & 0xf0000000) >> 28,
- (ar->arVersion.wlan_ver & 0x0f000000) >> 24,
- (ar->arVersion.wlan_ver & 0x00ff0000) >> 16,
- (ar->arVersion.wlan_ver & 0x0000ffff));
-
- /* Indicate to the waiting thread that the ready event was received */
- ar->arWmiReady = true;
- wake_up(&arEvent);
-}
-
-void ar6000_install_static_wep_keys(struct ar6_softc *ar)
-{
- u8 index;
- u8 keyUsage;
-
- for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
- if (ar->arWepKeyList[index].arKeyLen) {
- keyUsage = GROUP_USAGE;
- if (index == ar->arDefTxKeyIndex) {
- keyUsage |= TX_USAGE;
- }
- wmi_addKey_cmd(ar->arWmi,
- index,
- WEP_CRYPT,
- keyUsage,
- ar->arWepKeyList[index].arKeyLen,
- NULL,
- ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL,
- NO_SYNC_WMIFLAG);
- }
- }
-}
-
-void
-add_new_sta(struct ar6_softc *ar, u8 *mac, u16 aid, u8 *wpaie,
- u8 ielen, u8 keymgmt, u8 ucipher, u8 auth)
-{
- u8 free_slot=aid-1;
-
- memcpy(ar->sta_list[free_slot].mac, mac, ATH_MAC_LEN);
- memcpy(ar->sta_list[free_slot].wpa_ie, wpaie, ielen);
- ar->sta_list[free_slot].aid = aid;
- ar->sta_list[free_slot].keymgmt = keymgmt;
- ar->sta_list[free_slot].ucipher = ucipher;
- ar->sta_list[free_slot].auth = auth;
- ar->sta_list_index = ar->sta_list_index | (1 << free_slot);
- ar->arAPStats.sta[free_slot].aid = aid;
-}
-
-void
-ar6000_connect_event(struct ar6_softc *ar, u16 channel, u8 *bssid,
- u16 listenInterval, u16 beaconInterval,
- NETWORK_TYPE networkType, u8 beaconIeLen,
- u8 assocReqLen, u8 assocRespLen,
- u8 *assocInfo)
-{
- union iwreq_data wrqu;
- int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos;
- static const char *tag1 = "ASSOCINFO(ReqIEs=";
- static const char *tag2 = "ASSOCRESPIE=";
- static const char *beaconIetag = "BEACONIE=";
- char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + strlen(tag1) + 1];
- char *pos;
- u8 key_op_ctrl;
- unsigned long flags;
- struct ieee80211req_key *ik;
- CRYPTO_TYPE keyType = NONE_CRYPT;
-
- if(ar->arNetworkType & AP_NETWORK) {
- struct net_device *dev = ar->arNetDev;
- if(memcmp(dev->dev_addr, bssid, ATH_MAC_LEN)==0) {
- ar->arACS = channel;
- ik = &ar->ap_mode_bkey;
-
- switch(ar->arAuthMode) {
- case NONE_AUTH:
- if(ar->arPairwiseCrypto == WEP_CRYPT) {
- ar6000_install_static_wep_keys(ar);
- }
-#ifdef WAPI_ENABLE
- else if(ar->arPairwiseCrypto == WAPI_CRYPT) {
- ap_set_wapi_key(ar, ik);
- }
-#endif
- break;
- case WPA_PSK_AUTH:
- case WPA2_PSK_AUTH:
- case (WPA_PSK_AUTH|WPA2_PSK_AUTH):
- switch (ik->ik_type) {
- case IEEE80211_CIPHER_TKIP:
- keyType = TKIP_CRYPT;
- break;
- case IEEE80211_CIPHER_AES_CCM:
- keyType = AES_CRYPT;
- break;
- default:
- goto skip_key;
- }
- wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, GROUP_USAGE,
- ik->ik_keylen, (u8 *)&ik->ik_keyrsc,
- ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr,
- SYNC_BOTH_WMIFLAG);
-
- break;
- }
-skip_key:
- ar->arConnected = true;
- return;
- }
-
- A_PRINTF("NEW STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n "
- " AID=%d \n", bssid[0], bssid[1], bssid[2],
- bssid[3], bssid[4], bssid[5], channel);
- switch ((listenInterval>>8)&0xFF) {
- case OPEN_AUTH:
- A_PRINTF("AUTH: OPEN\n");
- break;
- case SHARED_AUTH:
- A_PRINTF("AUTH: SHARED\n");
- break;
- default:
- A_PRINTF("AUTH: Unknown\n");
- break;
- }
- switch (listenInterval&0xFF) {
- case WPA_PSK_AUTH:
- A_PRINTF("KeyMgmt: WPA-PSK\n");
- break;
- case WPA2_PSK_AUTH:
- A_PRINTF("KeyMgmt: WPA2-PSK\n");
- break;
- default:
- A_PRINTF("KeyMgmt: NONE\n");
- break;
- }
- switch (beaconInterval) {
- case AES_CRYPT:
- A_PRINTF("Cipher: AES\n");
- break;
- case TKIP_CRYPT:
- A_PRINTF("Cipher: TKIP\n");
- break;
- case WEP_CRYPT:
- A_PRINTF("Cipher: WEP\n");
- break;
-#ifdef WAPI_ENABLE
- case WAPI_CRYPT:
- A_PRINTF("Cipher: WAPI\n");
- break;
-#endif
- default:
- A_PRINTF("Cipher: NONE\n");
- break;
- }
-
- add_new_sta(ar, bssid, channel /*aid*/,
- assocInfo /* WPA IE */, assocRespLen /* IE len */,
- listenInterval&0xFF /* Keymgmt */, beaconInterval /* cipher */,
- (listenInterval>>8)&0xFF /* auth alg */);
-
- /* Send event to application */
- A_MEMZERO(&wrqu, sizeof(wrqu));
- memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN);
- wireless_send_event(ar->arNetDev, IWEVREGISTERED, &wrqu, NULL);
- /* In case the queue is stopped when we switch modes, this will
- * wake it up
- */
- netif_wake_queue(ar->arNetDev);
- return;
- }
-
- ar6k_cfg80211_connect_event(ar, channel, bssid,
- listenInterval, beaconInterval,
- networkType, beaconIeLen,
- assocReqLen, assocRespLen,
- assocInfo);
-
- memcpy(ar->arBssid, bssid, sizeof(ar->arBssid));
- ar->arBssChannel = channel;
-
- A_PRINTF("AR6000 connected event on freq %d ", channel);
- A_PRINTF("with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
- " listenInterval=%d, beaconInterval = %d, beaconIeLen = %d assocReqLen=%d"
- " assocRespLen =%d\n",
- bssid[0], bssid[1], bssid[2],
- bssid[3], bssid[4], bssid[5],
- listenInterval, beaconInterval,
- beaconIeLen, assocReqLen, assocRespLen);
- if (networkType & ADHOC_NETWORK) {
- if (networkType & ADHOC_CREATOR) {
- A_PRINTF("Network: Adhoc (Creator)\n");
- } else {
- A_PRINTF("Network: Adhoc (Joiner)\n");
- }
- } else {
- A_PRINTF("Network: Infrastructure\n");
- }
-
- if ((ar->arNetworkType == INFRA_NETWORK)) {
- wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB);
- }
-
- if (beaconIeLen && (sizeof(buf) > (9 + beaconIeLen * 2))) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nBeaconIEs= "));
-
- beacon_ie_pos = 0;
- A_MEMZERO(buf, sizeof(buf));
- sprintf(buf, "%s", beaconIetag);
- pos = buf + 9;
- for (i = beacon_ie_pos; i < beacon_ie_pos + beaconIeLen; i++) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i]));
- sprintf(pos, "%2.2x", assocInfo[i]);
- pos += 2;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n"));
-
- A_MEMZERO(&wrqu, sizeof(wrqu));
- wrqu.data.length = strlen(buf);
- wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
- }
-
- if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2))))
- {
- assoc_resp_ie_pos = beaconIeLen + assocReqLen +
- sizeof(u16) + /* capinfo*/
- sizeof(u16) + /* status Code */
- sizeof(u16) ; /* associd */
- A_MEMZERO(buf, sizeof(buf));
- sprintf(buf, "%s", tag2);
- pos = buf + 12;
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nAssocRespIEs= "));
- /*
- * The Association Response Frame w.o. the WLAN header is delivered to
- * the host, so skip over to the IEs
- */
- for (i = assoc_resp_ie_pos; i < assoc_resp_ie_pos + assocRespLen - 6; i++)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i]));
- sprintf(pos, "%2.2x", assocInfo[i]);
- pos += 2;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n"));
-
- A_MEMZERO(&wrqu, sizeof(wrqu));
- wrqu.data.length = strlen(buf);
- wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
- }
-
- if (assocReqLen && (sizeof(buf) > (17 + (assocReqLen * 2)))) {
- /*
- * assoc Request includes capability and listen interval. Skip these.
- */
- assoc_req_ie_pos = beaconIeLen +
- sizeof(u16) + /* capinfo*/
- sizeof(u16); /* listen interval */
-
- A_MEMZERO(buf, sizeof(buf));
- sprintf(buf, "%s", tag1);
- pos = buf + 17;
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("AssocReqIEs= "));
- for (i = assoc_req_ie_pos; i < assoc_req_ie_pos + assocReqLen - 4; i++) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i]));
- sprintf(pos, "%2.2x", assocInfo[i]);
- pos += 2;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n"));
-
- A_MEMZERO(&wrqu, sizeof(wrqu));
- wrqu.data.length = strlen(buf);
- wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
- }
-
- if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN &&
- ar->user_saved_keys.keyOk == true)
- {
- key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC;
-
- if (ar->user_key_ctrl & AR6000_USER_SETKEYS_RSC_UNCHANGED) {
- key_op_ctrl &= ~KEY_OP_INIT_RSC;
- } else {
- key_op_ctrl |= KEY_OP_INIT_RSC;
- }
- ar6000_reinstall_keys(ar, key_op_ctrl);
- }
-
- netif_wake_queue(ar->arNetDev);
-
- /* Update connect & link status atomically */
- spin_lock_irqsave(&ar->arLock, flags);
- ar->arConnected = true;
- ar->arConnectPending = false;
- netif_carrier_on(ar->arNetDev);
- spin_unlock_irqrestore(&ar->arLock, flags);
- /* reset the rx aggr state */
- aggr_reset_state(ar->aggr_cntxt);
- reconnect_flag = 0;
-
- A_MEMZERO(&wrqu, sizeof(wrqu));
- memcpy(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN);
- wrqu.addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL);
- if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) {
- A_MEMZERO(ar->arNodeMap, sizeof(ar->arNodeMap));
- ar->arNodeNum = 0;
- ar->arNexEpId = ENDPOINT_2;
- }
- if (!ar->arUserBssFilter) {
- wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0);
- }
-
-}
-
-void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num)
-{
- A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1));
- ar->arNumDataEndPts = num;
-}
-
-void
-sta_cleanup(struct ar6_softc *ar, u8 i)
-{
- struct sk_buff *skb;
-
- /* empty the queued pkts in the PS queue if any */
- A_MUTEX_LOCK(&ar->sta_list[i].psqLock);
- while (!A_NETBUF_QUEUE_EMPTY(&ar->sta_list[i].psq)) {
- skb = A_NETBUF_DEQUEUE(&ar->sta_list[i].psq);
- A_NETBUF_FREE(skb);
- }
- A_MUTEX_UNLOCK(&ar->sta_list[i].psqLock);
-
- /* Zero out the state fields */
- A_MEMZERO(&ar->arAPStats.sta[ar->sta_list[i].aid-1], sizeof(WMI_PER_STA_STAT));
- A_MEMZERO(&ar->sta_list[i].mac, ATH_MAC_LEN);
- A_MEMZERO(&ar->sta_list[i].wpa_ie, IEEE80211_MAX_IE);
- ar->sta_list[i].aid = 0;
- ar->sta_list[i].flags = 0;
-
- ar->sta_list_index = ar->sta_list_index & ~(1 << i);
-
-}
-
-u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason)
-{
- u8 i, removed=0;
-
- if(IS_MAC_NULL(mac)) {
- return removed;
- }
-
- if(IS_MAC_BCAST(mac)) {
- A_PRINTF("DEL ALL STA\n");
- for(i=0; i < AP_MAX_NUM_STA; i++) {
- if(!IS_MAC_NULL(ar->sta_list[i].mac)) {
- sta_cleanup(ar, i);
- removed = 1;
- }
- }
- } else {
- for(i=0; i < AP_MAX_NUM_STA; i++) {
- if(memcmp(ar->sta_list[i].mac, mac, ATH_MAC_LEN)==0) {
- A_PRINTF("DEL STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
- " aid=%d REASON=%d\n", mac[0], mac[1], mac[2],
- mac[3], mac[4], mac[5], ar->sta_list[i].aid, reason);
-
- sta_cleanup(ar, i);
- removed = 1;
- break;
- }
- }
- }
- return removed;
-}
-
-void
-ar6000_disconnect_event(struct ar6_softc *ar, u8 reason, u8 *bssid,
- u8 assocRespLen, u8 *assocInfo, u16 protocolReasonStatus)
-{
- u8 i;
- unsigned long flags;
- union iwreq_data wrqu;
-
- if(ar->arNetworkType & AP_NETWORK) {
- union iwreq_data wrqu;
- struct sk_buff *skb;
-
- if(!remove_sta(ar, bssid, protocolReasonStatus)) {
- return;
- }
-
- /* If there are no more associated STAs, empty the mcast PS q */
- if (ar->sta_list_index == 0) {
- A_MUTEX_LOCK(&ar->mcastpsqLock);
- while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
- skb = A_NETBUF_DEQUEUE(&ar->mcastpsq);
- A_NETBUF_FREE(skb);
- }
- A_MUTEX_UNLOCK(&ar->mcastpsqLock);
-
- /* Clear the LSB of the BitMapCtl field of the TIM IE */
- if (ar->arWmiReady) {
- wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0);
- }
- }
-
- if(!IS_MAC_BCAST(bssid)) {
- /* Send event to application */
- A_MEMZERO(&wrqu, sizeof(wrqu));
- memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN);
- wireless_send_event(ar->arNetDev, IWEVEXPIRED, &wrqu, NULL);
- }
-
- ar->arConnected = false;
- return;
- }
-
- ar6k_cfg80211_disconnect_event(ar, reason, bssid,
- assocRespLen, assocInfo,
- protocolReasonStatus);
-
- /* Send disconnect event to supplicant */
- A_MEMZERO(&wrqu, sizeof(wrqu));
- wrqu.addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL);
-
- /* it is necessary to clear the host-side rx aggregation state */
- aggr_reset_state(ar->aggr_cntxt);
-
- A_UNTIMEOUT(&ar->disconnect_timer);
-
- A_PRINTF("AR6000 disconnected");
- if (bssid[0] || bssid[1] || bssid[2] || bssid[3] || bssid[4] || bssid[5]) {
- A_PRINTF(" from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",
- bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nDisconnect Reason is %d", reason));
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nProtocol Reason/Status Code is %d", protocolReasonStatus));
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nAssocResp Frame = %s",
- assocRespLen ? " " : "NULL"));
- for (i = 0; i < assocRespLen; i++) {
- if (!(i % 0x10)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n"));
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i]));
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n"));
- /*
- * If the event is due to disconnect cmd from the host, only they the target
- * would stop trying to connect. Under any other condition, target would
- * keep trying to connect.
- *
- */
- if( reason == DISCONNECT_CMD)
- {
- if ((!ar->arUserBssFilter) && (ar->arWmiReady)) {
- wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0);
- }
- } else {
- ar->arConnectPending = true;
- if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) ||
- ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) {
- ar->arConnected = true;
- return;
- }
- }
-
- if ((reason == NO_NETWORK_AVAIL) && (ar->arWmiReady))
- {
- bss_t *pWmiSsidnode = NULL;
-
- /* remove the current associated bssid node */
- wmi_free_node (ar->arWmi, bssid);
-
- /*
- * In case any other same SSID nodes are present
- * remove it, since those nodes also not available now
- */
- do
- {
- /*
- * Find the nodes based on SSID and remove it
- * NOTE :: This case will not work out for Hidden-SSID
- */
- pWmiSsidnode = wmi_find_Ssidnode (ar->arWmi, ar->arSsid, ar->arSsidLen, false, true);
-
- if (pWmiSsidnode)
- {
- wmi_free_node (ar->arWmi, pWmiSsidnode->ni_macaddr);
- }
-
- } while (pWmiSsidnode);
- }
-
- /* Update connect & link status atomically */
- spin_lock_irqsave(&ar->arLock, flags);
- ar->arConnected = false;
- netif_carrier_off(ar->arNetDev);
- spin_unlock_irqrestore(&ar->arLock, flags);
-
- if( (reason != CSERV_DISCONNECT) || (reconnect_flag != 1) ) {
- reconnect_flag = 0;
- }
-
- if (reason != CSERV_DISCONNECT)
- {
- ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
- ar->user_key_ctrl = 0;
- }
-
- netif_stop_queue(ar->arNetDev);
- A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
- ar->arBssChannel = 0;
- ar->arBeaconInterval = 0;
-
- ar6000_TxDataCleanup(ar);
-}
-
-void
-ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode)
-{
- A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode);
- ar->arRegCode = regCode;
-}
-
-void
-ar6000_aggr_rcv_addba_req_evt(struct ar6_softc *ar, WMI_ADDBA_REQ_EVENT *evt)
-{
- if(evt->status == 0) {
- aggr_recv_addba_req_evt(ar->aggr_cntxt, evt->tid, evt->st_seq_no, evt->win_sz);
- }
-}
-
-void
-ar6000_aggr_rcv_addba_resp_evt(struct ar6_softc *ar, WMI_ADDBA_RESP_EVENT *evt)
-{
- A_PRINTF("ADDBA RESP. tid %d status %d, sz %d\n", evt->tid, evt->status, evt->amsdu_sz);
- if(evt->status == 0) {
- }
-}
-
-void
-ar6000_aggr_rcv_delba_req_evt(struct ar6_softc *ar, WMI_DELBA_EVENT *evt)
-{
- aggr_recv_delba_req_evt(ar->aggr_cntxt, evt->tid);
-}
-
-void register_pal_cb(ar6k_pal_config_t *palConfig_p)
-{
- ar6k_pal_config_g = *palConfig_p;
-}
-
-void
-ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd)
-{
- void *osbuf = NULL;
- s8 i;
- u8 size, *buf;
- int ret = 0;
-
- size = cmd->evt_buf_sz + 4;
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- ret = A_NO_MEMORY;
- A_PRINTF("Error in allocating netbuf \n");
- return;
- }
-
- A_NETBUF_PUT(osbuf, size);
- buf = (u8 *)A_NETBUF_DATA(osbuf);
- /* First 2-bytes carry HCI event/ACL data type
- * the next 2 are free
- */
- *((short *)buf) = WMI_HCI_EVENT_EVENTID;
- buf += sizeof(int);
- memcpy(buf, cmd->buf, cmd->evt_buf_sz);
-
- ar6000_deliver_frames_to_nw_stack(ar->arNetDev, osbuf);
- if(loghci) {
- A_PRINTF_LOG("HCI Event From PAL <-- \n");
- for(i = 0; i < cmd->evt_buf_sz; i++) {
- A_PRINTF_LOG("0x%02x ", cmd->buf[i]);
- if((i % 10) == 0) {
- A_PRINTF_LOG("\n");
- }
- }
- A_PRINTF_LOG("\n");
- A_PRINTF_LOG("==================================\n");
- }
-}
-
-void
-ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, WMI_NEIGHBOR_INFO *info)
-{
-#if WIRELESS_EXT >= 18
- struct iw_pmkid_cand *pmkcand;
-#else /* WIRELESS_EXT >= 18 */
- static const char *tag = "PRE-AUTH";
- char buf[128];
-#endif /* WIRELESS_EXT >= 18 */
-
- union iwreq_data wrqu;
- int i;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("AR6000 Neighbor Report Event\n"));
- for (i=0; i < numAps; info++, i++) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",
- info->bssid[0], info->bssid[1], info->bssid[2],
- info->bssid[3], info->bssid[4], info->bssid[5]));
- if (info->bssFlags & WMI_PREAUTH_CAPABLE_BSS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("preauth-cap"));
- }
- if (info->bssFlags & WMI_PMKID_VALID_BSS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,(" pmkid-valid\n"));
- continue; /* we skip bss if the pmkid is already valid */
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("\n"));
- A_MEMZERO(&wrqu, sizeof(wrqu));
-#if WIRELESS_EXT >= 18
- pmkcand = A_MALLOC_NOWAIT(sizeof(struct iw_pmkid_cand));
- A_MEMZERO(pmkcand, sizeof(struct iw_pmkid_cand));
- pmkcand->index = i;
- pmkcand->flags = info->bssFlags;
- memcpy(pmkcand->bssid.sa_data, info->bssid, ATH_MAC_LEN);
- wrqu.data.length = sizeof(struct iw_pmkid_cand);
- wireless_send_event(ar->arNetDev, IWEVPMKIDCAND, &wrqu, (char *)pmkcand);
- kfree(pmkcand);
-#else /* WIRELESS_EXT >= 18 */
- snprintf(buf, sizeof(buf), "%s%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
- tag,
- info->bssid[0], info->bssid[1], info->bssid[2],
- info->bssid[3], info->bssid[4], info->bssid[5],
- i, info->bssFlags);
- wrqu.data.length = strlen(buf);
- wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
-#endif /* WIRELESS_EXT >= 18 */
- }
-}
-
-void
-ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast)
-{
- static const char *tag = "MLME-MICHAELMICFAILURE.indication";
- char buf[128];
- union iwreq_data wrqu;
-
- /*
- * For AP case, keyid will have aid of STA which sent pkt with
- * MIC error. Use this aid to get MAC & send it to hostapd.
- */
- if (ar->arNetworkType == AP_NETWORK) {
- sta_t *s = ieee80211_find_conn_for_aid(ar, (keyid >> 2));
- if(!s){
- A_PRINTF("AP TKIP MIC error received from Invalid aid / STA not found =%d\n", keyid);
- return;
- }
- A_PRINTF("AP TKIP MIC error received from aid=%d\n", keyid);
- snprintf(buf,sizeof(buf), "%s addr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
- tag, s->mac[0],s->mac[1],s->mac[2],s->mac[3],s->mac[4],s->mac[5]);
- } else {
-
- ar6k_cfg80211_tkip_micerr_event(ar, keyid, ismcast);
-
- A_PRINTF("AR6000 TKIP MIC error received for keyid %d %scast\n",
- keyid & 0x3, ismcast ? "multi": "uni");
- snprintf(buf, sizeof(buf), "%s(keyid=%d %sicast)", tag, keyid & 0x3,
- ismcast ? "mult" : "un");
- }
-
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = strlen(buf);
- wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
-}
-
-void
-ar6000_scanComplete_event(struct ar6_softc *ar, int status)
-{
-
- ar6k_cfg80211_scanComplete_event(ar, status);
-
- if (!ar->arUserBssFilter) {
- wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0);
- }
- if (ar->scan_triggered) {
- if (status== 0) {
- union iwreq_data wrqu;
- A_MEMZERO(&wrqu, sizeof(wrqu));
- wireless_send_event(ar->arNetDev, SIOCGIWSCAN, &wrqu, NULL);
- }
- ar->scan_triggered = 0;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,( "AR6000 scan complete: %d\n", status));
-}
-
-void
-ar6000_targetStats_event(struct ar6_softc *ar, u8 *ptr, u32 len)
-{
- u8 ac;
-
- if(ar->arNetworkType == AP_NETWORK) {
- WMI_AP_MODE_STAT *p = (WMI_AP_MODE_STAT *)ptr;
- WMI_AP_MODE_STAT *ap = &ar->arAPStats;
-
- if (len < sizeof(*p)) {
- return;
- }
-
- for(ac=0;ac<AP_MAX_NUM_STA;ac++) {
- ap->sta[ac].tx_bytes += p->sta[ac].tx_bytes;
- ap->sta[ac].tx_pkts += p->sta[ac].tx_pkts;
- ap->sta[ac].tx_error += p->sta[ac].tx_error;
- ap->sta[ac].tx_discard += p->sta[ac].tx_discard;
- ap->sta[ac].rx_bytes += p->sta[ac].rx_bytes;
- ap->sta[ac].rx_pkts += p->sta[ac].rx_pkts;
- ap->sta[ac].rx_error += p->sta[ac].rx_error;
- ap->sta[ac].rx_discard += p->sta[ac].rx_discard;
- }
-
- } else {
- WMI_TARGET_STATS *pTarget = (WMI_TARGET_STATS *)ptr;
- TARGET_STATS *pStats = &ar->arTargetStats;
-
- if (len < sizeof(*pTarget)) {
- return;
- }
-
- // Update the RSSI of the connected bss.
- if (ar->arConnected) {
- bss_t *pConnBss = NULL;
-
- pConnBss = wmi_find_node(ar->arWmi,ar->arBssid);
- if (pConnBss)
- {
- pConnBss->ni_rssi = pTarget->cservStats.cs_aveBeacon_rssi;
- pConnBss->ni_snr = pTarget->cservStats.cs_aveBeacon_snr;
- wmi_node_return(ar->arWmi, pConnBss);
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 updating target stats\n"));
- pStats->tx_packets += pTarget->txrxStats.tx_stats.tx_packets;
- pStats->tx_bytes += pTarget->txrxStats.tx_stats.tx_bytes;
- pStats->tx_unicast_pkts += pTarget->txrxStats.tx_stats.tx_unicast_pkts;
- pStats->tx_unicast_bytes += pTarget->txrxStats.tx_stats.tx_unicast_bytes;
- pStats->tx_multicast_pkts += pTarget->txrxStats.tx_stats.tx_multicast_pkts;
- pStats->tx_multicast_bytes += pTarget->txrxStats.tx_stats.tx_multicast_bytes;
- pStats->tx_broadcast_pkts += pTarget->txrxStats.tx_stats.tx_broadcast_pkts;
- pStats->tx_broadcast_bytes += pTarget->txrxStats.tx_stats.tx_broadcast_bytes;
- pStats->tx_rts_success_cnt += pTarget->txrxStats.tx_stats.tx_rts_success_cnt;
- for(ac = 0; ac < WMM_NUM_AC; ac++)
- pStats->tx_packet_per_ac[ac] += pTarget->txrxStats.tx_stats.tx_packet_per_ac[ac];
- pStats->tx_errors += pTarget->txrxStats.tx_stats.tx_errors;
- pStats->tx_failed_cnt += pTarget->txrxStats.tx_stats.tx_failed_cnt;
- pStats->tx_retry_cnt += pTarget->txrxStats.tx_stats.tx_retry_cnt;
- pStats->tx_mult_retry_cnt += pTarget->txrxStats.tx_stats.tx_mult_retry_cnt;
- pStats->tx_rts_fail_cnt += pTarget->txrxStats.tx_stats.tx_rts_fail_cnt;
- pStats->tx_unicast_rate = wmi_get_rate(pTarget->txrxStats.tx_stats.tx_unicast_rate);
-
- pStats->rx_packets += pTarget->txrxStats.rx_stats.rx_packets;
- pStats->rx_bytes += pTarget->txrxStats.rx_stats.rx_bytes;
- pStats->rx_unicast_pkts += pTarget->txrxStats.rx_stats.rx_unicast_pkts;
- pStats->rx_unicast_bytes += pTarget->txrxStats.rx_stats.rx_unicast_bytes;
- pStats->rx_multicast_pkts += pTarget->txrxStats.rx_stats.rx_multicast_pkts;
- pStats->rx_multicast_bytes += pTarget->txrxStats.rx_stats.rx_multicast_bytes;
- pStats->rx_broadcast_pkts += pTarget->txrxStats.rx_stats.rx_broadcast_pkts;
- pStats->rx_broadcast_bytes += pTarget->txrxStats.rx_stats.rx_broadcast_bytes;
- pStats->rx_fragment_pkt += pTarget->txrxStats.rx_stats.rx_fragment_pkt;
- pStats->rx_errors += pTarget->txrxStats.rx_stats.rx_errors;
- pStats->rx_crcerr += pTarget->txrxStats.rx_stats.rx_crcerr;
- pStats->rx_key_cache_miss += pTarget->txrxStats.rx_stats.rx_key_cache_miss;
- pStats->rx_decrypt_err += pTarget->txrxStats.rx_stats.rx_decrypt_err;
- pStats->rx_duplicate_frames += pTarget->txrxStats.rx_stats.rx_duplicate_frames;
- pStats->rx_unicast_rate = wmi_get_rate(pTarget->txrxStats.rx_stats.rx_unicast_rate);
-
-
- pStats->tkip_local_mic_failure
- += pTarget->txrxStats.tkipCcmpStats.tkip_local_mic_failure;
- pStats->tkip_counter_measures_invoked
- += pTarget->txrxStats.tkipCcmpStats.tkip_counter_measures_invoked;
- pStats->tkip_replays += pTarget->txrxStats.tkipCcmpStats.tkip_replays;
- pStats->tkip_format_errors += pTarget->txrxStats.tkipCcmpStats.tkip_format_errors;
- pStats->ccmp_format_errors += pTarget->txrxStats.tkipCcmpStats.ccmp_format_errors;
- pStats->ccmp_replays += pTarget->txrxStats.tkipCcmpStats.ccmp_replays;
-
- pStats->power_save_failure_cnt += pTarget->pmStats.power_save_failure_cnt;
- pStats->noise_floor_calibation = pTarget->noise_floor_calibation;
-
- pStats->cs_bmiss_cnt += pTarget->cservStats.cs_bmiss_cnt;
- pStats->cs_lowRssi_cnt += pTarget->cservStats.cs_lowRssi_cnt;
- pStats->cs_connect_cnt += pTarget->cservStats.cs_connect_cnt;
- pStats->cs_disconnect_cnt += pTarget->cservStats.cs_disconnect_cnt;
- pStats->cs_aveBeacon_snr = pTarget->cservStats.cs_aveBeacon_snr;
- pStats->cs_aveBeacon_rssi = pTarget->cservStats.cs_aveBeacon_rssi;
-
- if (enablerssicompensation) {
- pStats->cs_aveBeacon_rssi =
- rssi_compensation_calc(ar, pStats->cs_aveBeacon_rssi);
- }
- pStats->cs_lastRoam_msec = pTarget->cservStats.cs_lastRoam_msec;
- pStats->cs_snr = pTarget->cservStats.cs_snr;
- pStats->cs_rssi = pTarget->cservStats.cs_rssi;
-
- pStats->lq_val = pTarget->lqVal;
-
- pStats->wow_num_pkts_dropped += pTarget->wowStats.wow_num_pkts_dropped;
- pStats->wow_num_host_pkt_wakeups += pTarget->wowStats.wow_num_host_pkt_wakeups;
- pStats->wow_num_host_event_wakeups += pTarget->wowStats.wow_num_host_event_wakeups;
- pStats->wow_num_events_discarded += pTarget->wowStats.wow_num_events_discarded;
- pStats->arp_received += pTarget->arpStats.arp_received;
- pStats->arp_matched += pTarget->arpStats.arp_matched;
- pStats->arp_replied += pTarget->arpStats.arp_replied;
-
- if (ar->statsUpdatePending) {
- ar->statsUpdatePending = false;
- wake_up(&arEvent);
- }
- }
-}
-
-void
-ar6000_rssiThreshold_event(struct ar6_softc *ar, WMI_RSSI_THRESHOLD_VAL newThreshold, s16 rssi)
-{
- USER_RSSI_THOLD userRssiThold;
-
- rssi = rssi + SIGNAL_QUALITY_NOISE_FLOOR;
-
- if (enablerssicompensation) {
- rssi = rssi_compensation_calc(ar, rssi);
- }
-
- /* Send an event to the app */
- userRssiThold.tag = ar->rssi_map[newThreshold].tag;
- userRssiThold.rssi = rssi;
- A_PRINTF("rssi Threshold range = %d tag = %d rssi = %d\n", newThreshold,
- userRssiThold.tag, userRssiThold.rssi);
-}
-
-
-void
-ar6000_hbChallengeResp_event(struct ar6_softc *ar, u32 cookie, u32 source)
-{
- if (source != APP_HB_CHALLENGE) {
- /* This would ignore the replys that come in after their due time */
- if (cookie == ar->arHBChallengeResp.seqNum) {
- ar->arHBChallengeResp.outstanding = false;
- }
- }
-}
-
-
-void
-ar6000_reportError_event(struct ar6_softc *ar, WMI_TARGET_ERROR_VAL errorVal)
-{
- static const char * const errString[] = {
- [WMI_TARGET_PM_ERR_FAIL] "WMI_TARGET_PM_ERR_FAIL",
- [WMI_TARGET_KEY_NOT_FOUND] "WMI_TARGET_KEY_NOT_FOUND",
- [WMI_TARGET_DECRYPTION_ERR] "WMI_TARGET_DECRYPTION_ERR",
- [WMI_TARGET_BMISS] "WMI_TARGET_BMISS",
- [WMI_PSDISABLE_NODE_JOIN] "WMI_PSDISABLE_NODE_JOIN"
- };
-
- A_PRINTF("AR6000 Error on Target. Error = 0x%x\n", errorVal);
-
- /* One error is reported at a time, and errorval is a bitmask */
- if(errorVal & (errorVal - 1))
- return;
-
- A_PRINTF("AR6000 Error type = ");
- switch(errorVal)
- {
- case WMI_TARGET_PM_ERR_FAIL:
- case WMI_TARGET_KEY_NOT_FOUND:
- case WMI_TARGET_DECRYPTION_ERR:
- case WMI_TARGET_BMISS:
- case WMI_PSDISABLE_NODE_JOIN:
- A_PRINTF("%s\n", errString[errorVal]);
- break;
- default:
- A_PRINTF("INVALID\n");
- break;
- }
-
-}
-
-
-void
-ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cacIndication,
- u8 statusCode, u8 *tspecSuggestion)
-{
- WMM_TSPEC_IE *tspecIe;
-
- /*
- * This is the TSPEC IE suggestion from AP.
- * Suggestion provided by AP under some error
- * cases, could be helpful for the host app.
- * Check documentation.
- */
- tspecIe = (WMM_TSPEC_IE *)tspecSuggestion;
-
- /*
- * What do we do, if we get TSPEC rejection? One thought
- * that comes to mind is implictly delete the pstream...
- */
- A_PRINTF("AR6000 CAC notification. "
- "AC = %d, cacIndication = 0x%x, statusCode = 0x%x\n",
- ac, cacIndication, statusCode);
-}
-
-void
-ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel,
- u16 newChannel)
-{
- A_PRINTF("Channel Change notification\nOld Channel: %d, New Channel: %d\n",
- oldChannel, newChannel);
-}
-
-#define AR6000_PRINT_BSSID(_pBss) do { \
- A_PRINTF("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",\
- (_pBss)[0],(_pBss)[1],(_pBss)[2],(_pBss)[3],\
- (_pBss)[4],(_pBss)[5]); \
-} while(0)
-
-void
-ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl)
-{
- u8 i;
-
- A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n",
- pTbl->numEntries, pTbl->roamMode);
- for (i= 0; i < pTbl->numEntries; i++) {
- A_PRINTF("[%d]bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", i,
- pTbl->bssRoamInfo[i].bssid[0], pTbl->bssRoamInfo[i].bssid[1],
- pTbl->bssRoamInfo[i].bssid[2],
- pTbl->bssRoamInfo[i].bssid[3],
- pTbl->bssRoamInfo[i].bssid[4],
- pTbl->bssRoamInfo[i].bssid[5]);
- A_PRINTF("RSSI %d RSSIDT %d LAST RSSI %d UTIL %d ROAM_UTIL %d"
- " BIAS %d\n",
- pTbl->bssRoamInfo[i].rssi,
- pTbl->bssRoamInfo[i].rssidt,
- pTbl->bssRoamInfo[i].last_rssi,
- pTbl->bssRoamInfo[i].util,
- pTbl->bssRoamInfo[i].roam_util,
- pTbl->bssRoamInfo[i].bias);
- }
-}
-
-void
-ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply)
-{
- u8 i,j;
-
- /*Each event now contains exactly one filter, see bug 26613*/
- A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num, wow_reply->num_filters);
- A_PRINTF("wow mode = %s host mode = %s\n",
- (wow_reply->wow_mode == 0? "disabled":"enabled"),
- (wow_reply->host_mode == 1 ? "awake":"asleep"));
-
-
- /*If there are no patterns, the reply will only contain generic
- WoW information. Pattern information will exist only if there are
- patterns present. Bug 26716*/
-
- /* If this event contains pattern information, display it*/
- if (wow_reply->this_filter_num) {
- i=0;
- A_PRINTF("id=%d size=%d offset=%d\n",
- wow_reply->wow_filters[i].wow_filter_id,
- wow_reply->wow_filters[i].wow_filter_size,
- wow_reply->wow_filters[i].wow_filter_offset);
- A_PRINTF("wow pattern = ");
- for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) {
- A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_pattern[j]);
- }
-
- A_PRINTF("\nwow mask = ");
- for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) {
- A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_mask[j]);
- }
- A_PRINTF("\n");
- }
-}
-
-/*
- * Report the Roaming related data collected on the target
- */
-void
-ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p)
-{
- A_PRINTF("Disconnect Data : BSSID: ");
- AR6000_PRINT_BSSID(p->disassoc_bssid);
- A_PRINTF(" RSSI %d DISASSOC Time %d NO_TXRX_TIME %d\n",
- p->disassoc_bss_rssi,p->disassoc_time,
- p->no_txrx_time);
- A_PRINTF("Connect Data: BSSID: ");
- AR6000_PRINT_BSSID(p->assoc_bssid);
- A_PRINTF(" RSSI %d ASSOC Time %d TXRX_TIME %d\n",
- p->assoc_bss_rssi,p->assoc_time,
- p->allow_txrx_time);
-}
-
-void
-ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p)
-{
- switch (p->roamDataType) {
- case ROAM_DATA_TIME:
- ar6000_display_roam_time(&p->u.roamTime);
- break;
- default:
- break;
- }
-}
-
-void
-ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *datap, int len)
-{
- struct sk_buff *skb;
- WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap;
-
-
- if (!ar->arMgmtFilter) {
- return;
- }
- if (((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_BEACON) &&
- (bih->frameType != BEACON_FTYPE)) ||
- ((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_PROBE_RESP) &&
- (bih->frameType != PROBERESP_FTYPE)))
- {
- return;
- }
-
- if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) {
-
- A_NETBUF_PUT(skb, len);
- memcpy(A_NETBUF_DATA(skb), datap, len);
- skb->dev = ar->arNetDev;
- memcpy(skb_mac_header(skb), A_NETBUF_DATA(skb), 6);
- skb->ip_summed = CHECKSUM_NONE;
- skb->pkt_type = PACKET_OTHERHOST;
- skb->protocol = __constant_htons(0x0019);
- netif_rx(skb);
- }
-}
-
-u32 wmiSendCmdNum;
-
-int
-ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid)
-{
- struct ar6_softc *ar = (struct ar6_softc *)devt;
- int status = 0;
- struct ar_cookie *cookie = NULL;
- int i;
-#ifdef CONFIG_PM
- if (ar->arWowState != WLAN_WOW_STATE_NONE) {
- A_NETBUF_FREE(osbuf);
- return A_EACCES;
- }
-#endif /* CONFIG_PM */
- /* take lock to protect ar6000_alloc_cookie() */
- AR6000_SPIN_LOCK(&ar->arLock, 0);
-
- do {
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar_contrstatus = ol_tx: skb=0x%lx, len=0x%x eid =%d\n",
- (unsigned long)osbuf, A_NETBUF_LEN(osbuf), eid));
-
- if (ar->arWMIControlEpFull && (eid == ar->arControlEp)) {
- /* control endpoint is full, don't allocate resources, we
- * are just going to drop this packet */
- cookie = NULL;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" WMI Control EP full, dropping packet : 0x%lX, len:%d \n",
- (unsigned long)osbuf, A_NETBUF_LEN(osbuf)));
- } else {
- cookie = ar6000_alloc_cookie(ar);
- }
-
- if (cookie == NULL) {
- status = A_NO_MEMORY;
- break;
- }
-
- if(logWmiRawMsgs) {
- A_PRINTF("WMI cmd send, msgNo %d :", wmiSendCmdNum);
- for(i = 0; i < a_netbuf_to_len(osbuf); i++)
- A_PRINTF("%x ", ((u8 *)a_netbuf_to_data(osbuf))[i]);
- A_PRINTF("\n");
- }
-
- wmiSendCmdNum++;
-
- } while (false);
-
- if (cookie != NULL) {
- /* got a structure to send it out on */
- ar->arTxPending[eid]++;
-
- if (eid != ar->arControlEp) {
- ar->arTotalTxDataPending++;
- }
- }
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- if (cookie != NULL) {
- cookie->arc_bp[0] = (unsigned long)osbuf;
- cookie->arc_bp[1] = 0;
- SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
- cookie,
- A_NETBUF_DATA(osbuf),
- A_NETBUF_LEN(osbuf),
- eid,
- AR6K_CONTROL_PKT_TAG);
- /* this interface is asynchronous, if there is an error, cleanup will happen in the
- * TX completion callback */
- HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
- status = 0;
- }
-
- if (status) {
- A_NETBUF_FREE(osbuf);
- }
- return status;
-}
-
-/* indicate tx activity or inactivity on a WMI stream */
-void ar6000_indicate_tx_activity(void *devt, u8 TrafficClass, bool Active)
-{
- struct ar6_softc *ar = (struct ar6_softc *)devt;
- HTC_ENDPOINT_ID eid ;
- int i;
-
- if (ar->arWmiEnabled) {
- eid = arAc2EndpointID(ar, TrafficClass);
-
- AR6000_SPIN_LOCK(&ar->arLock, 0);
-
- ar->arAcStreamActive[TrafficClass] = Active;
-
- if (Active) {
- /* when a stream goes active, keep track of the active stream with the highest priority */
-
- if (ar->arAcStreamPriMap[TrafficClass] > ar->arHiAcStreamActivePri) {
- /* set the new highest active priority */
- ar->arHiAcStreamActivePri = ar->arAcStreamPriMap[TrafficClass];
- }
-
- } else {
- /* when a stream goes inactive, we may have to search for the next active stream
- * that is the highest priority */
-
- if (ar->arHiAcStreamActivePri == ar->arAcStreamPriMap[TrafficClass]) {
-
- /* the highest priority stream just went inactive */
-
- /* reset and search for the "next" highest "active" priority stream */
- ar->arHiAcStreamActivePri = 0;
- for (i = 0; i < WMM_NUM_AC; i++) {
- if (ar->arAcStreamActive[i]) {
- if (ar->arAcStreamPriMap[i] > ar->arHiAcStreamActivePri) {
- /* set the new highest active priority */
- ar->arHiAcStreamActivePri = ar->arAcStreamPriMap[i];
- }
- }
- }
- }
- }
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- } else {
- /* for mbox ping testing, the traffic class is mapped directly as a stream ID,
- * see handling of AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE in ioctl.c
- * convert the stream ID to a endpoint */
- eid = arAc2EndpointID(ar, TrafficClass);
- }
-
- /* notify HTC, this may cause credit distribution changes */
-
- HTCIndicateActivityChange(ar->arHtcTarget,
- eid,
- Active);
-
-}
-
-void
-ar6000_btcoex_config_event(struct ar6_softc *ar, u8 *ptr, u32 len)
-{
-
- WMI_BTCOEX_CONFIG_EVENT *pBtcoexConfig = (WMI_BTCOEX_CONFIG_EVENT *)ptr;
- WMI_BTCOEX_CONFIG_EVENT *pArbtcoexConfig =&ar->arBtcoexConfig;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n"));
-
- A_PRINTF("received config event\n");
- pArbtcoexConfig->btProfileType = pBtcoexConfig->btProfileType;
- pArbtcoexConfig->linkId = pBtcoexConfig->linkId;
-
- switch (pBtcoexConfig->btProfileType) {
- case WMI_BTCOEX_BT_PROFILE_SCO:
- memcpy(&pArbtcoexConfig->info.scoConfigCmd, &pBtcoexConfig->info.scoConfigCmd,
- sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
- break;
- case WMI_BTCOEX_BT_PROFILE_A2DP:
- memcpy(&pArbtcoexConfig->info.a2dpConfigCmd, &pBtcoexConfig->info.a2dpConfigCmd,
- sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
- break;
- case WMI_BTCOEX_BT_PROFILE_ACLCOEX:
- memcpy(&pArbtcoexConfig->info.aclcoexConfig, &pBtcoexConfig->info.aclcoexConfig,
- sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
- break;
- case WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE:
- memcpy(&pArbtcoexConfig->info.btinquiryPageConfigCmd, &pBtcoexConfig->info.btinquiryPageConfigCmd,
- sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
- break;
- }
- if (ar->statsUpdatePending) {
- ar->statsUpdatePending = false;
- wake_up(&arEvent);
- }
-}
-
-void
-ar6000_btcoex_stats_event(struct ar6_softc *ar, u8 *ptr, u32 len)
-{
- WMI_BTCOEX_STATS_EVENT *pBtcoexStats = (WMI_BTCOEX_STATS_EVENT *)ptr;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n"));
-
- memcpy(&ar->arBtcoexStats, pBtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT));
-
- if (ar->statsUpdatePending) {
- ar->statsUpdatePending = false;
- wake_up(&arEvent);
- }
-
-}
-module_init(ar6000_init_module);
-module_exit(ar6000_cleanup_module);
-
-/* Init cookie queue */
-static void
-ar6000_cookie_init(struct ar6_softc *ar)
-{
- u32 i;
-
- ar->arCookieList = NULL;
- ar->arCookieCount = 0;
-
- A_MEMZERO(s_ar_cookie_mem, sizeof(s_ar_cookie_mem));
-
- for (i = 0; i < MAX_COOKIE_NUM; i++) {
- ar6000_free_cookie(ar, &s_ar_cookie_mem[i]);
- }
-}
-
-/* cleanup cookie queue */
-static void
-ar6000_cookie_cleanup(struct ar6_softc *ar)
-{
- /* It is gone .... */
- ar->arCookieList = NULL;
- ar->arCookieCount = 0;
-}
-
-/* Init cookie queue */
-static void
-ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie)
-{
- /* Insert first */
- A_ASSERT(ar != NULL);
- A_ASSERT(cookie != NULL);
-
- cookie->arc_list_next = ar->arCookieList;
- ar->arCookieList = cookie;
- ar->arCookieCount++;
-}
-
-/* cleanup cookie queue */
-static struct ar_cookie *
-ar6000_alloc_cookie(struct ar6_softc *ar)
-{
- struct ar_cookie *cookie;
-
- cookie = ar->arCookieList;
- if(cookie != NULL)
- {
- ar->arCookieList = cookie->arc_list_next;
- ar->arCookieCount--;
- }
-
- return cookie;
-}
-
-void
-ar6000_tx_retry_err_event(void *devt)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Tx retries reach maximum!\n"));
-}
-
-void
-ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, u8 snr)
-{
- WMI_SNR_THRESHOLD_EVENT event;
-
- event.range = newThreshold;
- event.snr = snr;
-}
-
-void
-ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, u8 lq)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("lq threshold range %d, lq %d\n", newThreshold, lq));
-}
-
-
-
-u32 a_copy_to_user(void *to, const void *from, u32 n)
-{
- return(copy_to_user(to, from, n));
-}
-
-u32 a_copy_from_user(void *to, const void *from, u32 n)
-{
- return(copy_from_user(to, from, n));
-}
-
-
-int
-ar6000_get_driver_cfg(struct net_device *dev,
- u16 cfgParam,
- void *result)
-{
-
- int ret = 0;
-
- switch(cfgParam)
- {
- case AR6000_DRIVER_CFG_GET_WLANNODECACHING:
- *((u32 *)result) = wlanNodeCaching;
- break;
- case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS:
- *((u32 *)result) = logWmiRawMsgs;
- break;
- default:
- ret = EINVAL;
- break;
- }
-
- return ret;
-}
-
-void
-ar6000_keepalive_rx(void *devt, u8 configured)
-{
- struct ar6_softc *ar = (struct ar6_softc *)devt;
-
- ar->arKeepaliveConfigured = configured;
- wake_up(&arEvent);
-}
-
-void
-ar6000_pmkid_list_event(void *devt, u8 numPMKID, WMI_PMKID *pmkidList,
- u8 *bssidList)
-{
- u8 i, j;
-
- A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID);
-
- for (i = 0; i < numPMKID; i++) {
- A_PRINTF("\nBSSID %d ", i);
- for (j = 0; j < ATH_MAC_LEN; j++) {
- A_PRINTF("%2.2x", bssidList[j]);
- }
- bssidList += (ATH_MAC_LEN + WMI_PMKID_LEN);
- A_PRINTF("\nPMKID %d ", i);
- for (j = 0; j < WMI_PMKID_LEN; j++) {
- A_PRINTF("%2.2x", pmkidList->pmkid[j]);
- }
- pmkidList = (WMI_PMKID *)((u8 *)pmkidList + ATH_MAC_LEN +
- WMI_PMKID_LEN);
- }
-}
-
-void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid)
-{
- sta_t *conn=NULL;
- bool isPsqEmpty = false;
-
- conn = ieee80211_find_conn_for_aid(ar, aid);
-
- /* If the PS q for this STA is not empty, dequeue and send a pkt from
- * the head of the q. Also update the More data bit in the WMI_DATA_HDR
- * if there are more pkts for this STA in the PS q. If there are no more
- * pkts for this STA, update the PVB for this STA.
- */
- A_MUTEX_LOCK(&conn->psqLock);
- isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq);
- A_MUTEX_UNLOCK(&conn->psqLock);
-
- if (isPsqEmpty) {
- /* TODO:No buffered pkts for this STA. Send out a NULL data frame */
- } else {
- struct sk_buff *skb = NULL;
-
- A_MUTEX_LOCK(&conn->psqLock);
- skb = A_NETBUF_DEQUEUE(&conn->psq);
- A_MUTEX_UNLOCK(&conn->psqLock);
- /* Set the STA flag to PSPolled, so that the frame will go out */
- STA_SET_PS_POLLED(conn);
- ar6000_data_tx(skb, ar->arNetDev);
- STA_CLR_PS_POLLED(conn);
-
- /* Clear the PVB for this STA if the queue has become empty */
- A_MUTEX_LOCK(&conn->psqLock);
- isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq);
- A_MUTEX_UNLOCK(&conn->psqLock);
-
- if (isPsqEmpty) {
- wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0);
- }
- }
-}
-
-void ar6000_dtimexpiry_event(struct ar6_softc *ar)
-{
- bool isMcastQueued = false;
- struct sk_buff *skb = NULL;
-
- /* If there are no associated STAs, ignore the DTIM expiry event.
- * There can be potential race conditions where the last associated
- * STA may disconnect & before the host could clear the 'Indicate DTIM'
- * request to the firmware, the firmware would have just indicated a DTIM
- * expiry event. The race is between 'clear DTIM expiry cmd' going
- * from the host to the firmware & the DTIM expiry event happening from
- * the firmware to the host.
- */
- if (ar->sta_list_index == 0) {
- return;
- }
-
- A_MUTEX_LOCK(&ar->mcastpsqLock);
- isMcastQueued = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq);
- A_MUTEX_UNLOCK(&ar->mcastpsqLock);
-
- A_ASSERT(isMcastQueued == false);
-
- /* Flush the mcast psq to the target */
- /* Set the STA flag to DTIMExpired, so that the frame will go out */
- ar->DTIMExpired = true;
-
- A_MUTEX_LOCK(&ar->mcastpsqLock);
- while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
- skb = A_NETBUF_DEQUEUE(&ar->mcastpsq);
- A_MUTEX_UNLOCK(&ar->mcastpsqLock);
-
- ar6000_data_tx(skb, ar->arNetDev);
-
- A_MUTEX_LOCK(&ar->mcastpsqLock);
- }
- A_MUTEX_UNLOCK(&ar->mcastpsqLock);
-
- /* Reset the DTIMExpired flag back to 0 */
- ar->DTIMExpired = false;
-
- /* Clear the LSB of the BitMapCtl field of the TIM IE */
- wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0);
-}
-
-void
-read_rssi_compensation_param(struct ar6_softc *ar)
-{
- u8 *cust_data_ptr;
-
-//#define RSSICOMPENSATION_PRINT
-
-#ifdef RSSICOMPENSATION_PRINT
- s16 i;
- cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType);
- for (i=0; i<16; i++) {
- A_PRINTF("cust_data_%d = %x \n", i, *(u8 *)cust_data_ptr);
- cust_data_ptr += 1;
- }
-#endif
-
- cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType);
-
- rssi_compensation_param.customerID = *(u16 *)cust_data_ptr & 0xffff;
- rssi_compensation_param.enable = *(u16 *)(cust_data_ptr+2) & 0xffff;
- rssi_compensation_param.bg_param_a = *(u16 *)(cust_data_ptr+4) & 0xffff;
- rssi_compensation_param.bg_param_b = *(u16 *)(cust_data_ptr+6) & 0xffff;
- rssi_compensation_param.a_param_a = *(u16 *)(cust_data_ptr+8) & 0xffff;
- rssi_compensation_param.a_param_b = *(u16 *)(cust_data_ptr+10) &0xffff;
- rssi_compensation_param.reserved = *(u32 *)(cust_data_ptr+12);
-
-#ifdef RSSICOMPENSATION_PRINT
- A_PRINTF("customerID = 0x%x \n", rssi_compensation_param.customerID);
- A_PRINTF("enable = 0x%x \n", rssi_compensation_param.enable);
- A_PRINTF("bg_param_a = 0x%x and %d \n", rssi_compensation_param.bg_param_a, rssi_compensation_param.bg_param_a);
- A_PRINTF("bg_param_b = 0x%x and %d \n", rssi_compensation_param.bg_param_b, rssi_compensation_param.bg_param_b);
- A_PRINTF("a_param_a = 0x%x and %d \n", rssi_compensation_param.a_param_a, rssi_compensation_param.a_param_a);
- A_PRINTF("a_param_b = 0x%x and %d \n", rssi_compensation_param.a_param_b, rssi_compensation_param.a_param_b);
- A_PRINTF("Last 4 bytes = 0x%x \n", rssi_compensation_param.reserved);
-#endif
-
- if (rssi_compensation_param.enable != 0x1) {
- rssi_compensation_param.enable = 0;
- }
-
- return;
-}
-
-s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt)
-{
-
- if (freq > 5000)
- {
- if (rssi_compensation_param.enable)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n"));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d, totalPkt = %d\n", rssi,totalPkt));
- rssi = rssi * rssi_compensation_param.a_param_a + totalPkt * rssi_compensation_param.a_param_b;
- rssi = (rssi-50) /100;
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi));
- }
- }
- else
- {
- if (rssi_compensation_param.enable)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n"));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d, totalPkt = %d\n", rssi,totalPkt));
- rssi = rssi * rssi_compensation_param.bg_param_a + totalPkt * rssi_compensation_param.bg_param_b;
- rssi = (rssi-50) /100;
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi));
- }
- }
-
- return rssi;
-}
-
-s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi)
-{
- if (ar->arBssChannel > 5000)
- {
- if (rssi_compensation_param.enable)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n"));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d\n", rssi));
- rssi = rssi * rssi_compensation_param.a_param_a + rssi_compensation_param.a_param_b;
- rssi = (rssi-50) /100;
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi));
- }
- }
- else
- {
- if (rssi_compensation_param.enable)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n"));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d\n", rssi));
- rssi = rssi * rssi_compensation_param.bg_param_a + rssi_compensation_param.bg_param_b;
- rssi = (rssi-50) /100;
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi));
- }
- }
-
- return rssi;
-}
-
-s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above)
-{
- s16 i;
-
- if (ar->arBssChannel > 5000)
- {
- if (rssi_compensation_param.enable)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n"));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before rev compensation = %d\n", rssi));
- rssi = rssi * 100;
- rssi = (rssi - rssi_compensation_param.a_param_b) / rssi_compensation_param.a_param_a;
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after rev compensation = %d\n", rssi));
- }
- }
- else
- {
- if (rssi_compensation_param.enable)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n"));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before rev compensation = %d\n", rssi));
-
- if (Above) {
- for (i=95; i>=0; i--) {
- if (rssi <= rssi_compensation_table[i]) {
- rssi = 0 - i;
- break;
- }
- }
- } else {
- for (i=0; i<=95; i++) {
- if (rssi >= rssi_compensation_table[i]) {
- rssi = 0 - i;
- break;
- }
- }
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after rev compensation = %d\n", rssi));
- }
- }
-
- return rssi;
-}
-
-#ifdef WAPI_ENABLE
-void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac)
-{
- union iwreq_data wrqu;
- char buf[20];
-
- A_MEMZERO(buf, sizeof(buf));
-
- strcpy(buf, "WAPI_REKEY");
- buf[10] = type;
- memcpy(&buf[11], mac, ATH_MAC_LEN);
-
- A_MEMZERO(&wrqu, sizeof(wrqu));
- wrqu.data.length = 10+1+ATH_MAC_LEN;
- wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
-
- A_PRINTF("WAPI REKEY - %d - %02x:%02x\n", type, mac[4], mac[5]);
-}
-#endif
-
-static int
-ar6000_reinstall_keys(struct ar6_softc *ar, u8 key_op_ctrl)
-{
- int status = 0;
- struct ieee80211req_key *uik = &ar->user_saved_keys.ucast_ik;
- struct ieee80211req_key *bik = &ar->user_saved_keys.bcast_ik;
- CRYPTO_TYPE keyType = ar->user_saved_keys.keyType;
-
- if (IEEE80211_CIPHER_CCKM_KRK != uik->ik_type) {
- if (NONE_CRYPT == keyType) {
- goto _reinstall_keys_out;
- }
-
- if (uik->ik_keylen) {
- status = wmi_addKey_cmd(ar->arWmi, uik->ik_keyix,
- ar->user_saved_keys.keyType, PAIRWISE_USAGE,
- uik->ik_keylen, (u8 *)&uik->ik_keyrsc,
- uik->ik_keydata, key_op_ctrl, uik->ik_macaddr, SYNC_BEFORE_WMIFLAG);
- }
-
- } else {
- status = wmi_add_krk_cmd(ar->arWmi, uik->ik_keydata);
- }
-
- if (IEEE80211_CIPHER_CCKM_KRK != bik->ik_type) {
- if (NONE_CRYPT == keyType) {
- goto _reinstall_keys_out;
- }
-
- if (bik->ik_keylen) {
- status = wmi_addKey_cmd(ar->arWmi, bik->ik_keyix,
- ar->user_saved_keys.keyType, GROUP_USAGE,
- bik->ik_keylen, (u8 *)&bik->ik_keyrsc,
- bik->ik_keydata, key_op_ctrl, bik->ik_macaddr, NO_SYNC_WMIFLAG);
- }
- } else {
- status = wmi_add_krk_cmd(ar->arWmi, bik->ik_keydata);
- }
-
-_reinstall_keys_out:
- ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
- ar->user_key_ctrl = 0;
-
- return status;
-}
-
-
-void
-ar6000_dset_open_req(
- void *context,
- u32 id,
- u32 targHandle,
- u32 targReplyFn,
- u32 targReplyArg)
-{
-}
-
-void
-ar6000_dset_close(
- void *context,
- u32 access_cookie)
-{
- return;
-}
-
-void
-ar6000_dset_data_req(
- void *context,
- u32 accessCookie,
- u32 offset,
- u32 length,
- u32 targBuf,
- u32 targReplyFn,
- u32 targReplyArg)
-{
-}
-
-int
-ar6000_ap_mode_profile_commit(struct ar6_softc *ar)
-{
- WMI_CONNECT_CMD p;
- unsigned long flags;
-
- /* No change in AP's profile configuration */
- if(ar->ap_profile_flag==0) {
- A_PRINTF("COMMIT: No change in profile!!!\n");
- return -ENODATA;
- }
-
- if(!ar->arSsidLen) {
- A_PRINTF("SSID not set!!!\n");
- return -ECHRNG;
- }
-
- switch(ar->arAuthMode) {
- case NONE_AUTH:
- if((ar->arPairwiseCrypto != NONE_CRYPT) &&
-#ifdef WAPI_ENABLE
- (ar->arPairwiseCrypto != WAPI_CRYPT) &&
-#endif
- (ar->arPairwiseCrypto != WEP_CRYPT)) {
- A_PRINTF("Cipher not supported in AP mode Open auth\n");
- return -EOPNOTSUPP;
- }
- break;
- case WPA_PSK_AUTH:
- case WPA2_PSK_AUTH:
- case (WPA_PSK_AUTH|WPA2_PSK_AUTH):
- break;
- default:
- A_PRINTF("This key mgmt type not supported in AP mode\n");
- return -EOPNOTSUPP;
- }
-
- /* Update the arNetworkType */
- ar->arNetworkType = ar->arNextMode;
-
- A_MEMZERO(&p,sizeof(p));
- p.ssidLength = ar->arSsidLen;
- memcpy(p.ssid,ar->arSsid,p.ssidLength);
- p.channel = ar->arChannelHint;
- p.networkType = ar->arNetworkType;
-
- p.dot11AuthMode = ar->arDot11AuthMode;
- p.authMode = ar->arAuthMode;
- p.pairwiseCryptoType = ar->arPairwiseCrypto;
- p.pairwiseCryptoLen = ar->arPairwiseCryptoLen;
- p.groupCryptoType = ar->arGroupCrypto;
- p.groupCryptoLen = ar->arGroupCryptoLen;
- p.ctrl_flags = ar->arConnectCtrlFlags;
-
- wmi_ap_profile_commit(ar->arWmi, &p);
- spin_lock_irqsave(&ar->arLock, flags);
- ar->arConnected = true;
- netif_carrier_on(ar->arNetDev);
- spin_unlock_irqrestore(&ar->arLock, flags);
- ar->ap_profile_flag = 0;
- return 0;
-}
-
-int
-ar6000_connect_to_ap(struct ar6_softc *ar)
-{
- /* The ssid length check prevents second "essid off" from the user,
- to be treated as a connect cmd. The second "essid off" is ignored.
- */
- if((ar->arWmiReady == true) && (ar->arSsidLen > 0) && ar->arNetworkType!=AP_NETWORK)
- {
- int status;
- if((ADHOC_NETWORK != ar->arNetworkType) &&
- (NONE_AUTH==ar->arAuthMode) &&
- (WEP_CRYPT==ar->arPairwiseCrypto)) {
- ar6000_install_static_wep_keys(ar);
- }
-
- if (!ar->arUserBssFilter) {
- if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) {
- return -EIO;
- }
- }
-#ifdef WAPI_ENABLE
- if (ar->arWapiEnable) {
- ar->arPairwiseCrypto = WAPI_CRYPT;
- ar->arPairwiseCryptoLen = 0;
- ar->arGroupCrypto = WAPI_CRYPT;
- ar->arGroupCryptoLen = 0;
- ar->arAuthMode = NONE_AUTH;
- ar->arConnectCtrlFlags |= CONNECT_IGNORE_WPAx_GROUP_CIPHER;
- }
-#endif
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("Connect called with authmode %d dot11 auth %d"\
- " PW crypto %d PW crypto Len %d GRP crypto %d"\
- " GRP crypto Len %d\n",
- ar->arAuthMode, ar->arDot11AuthMode,
- ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
- ar->arGroupCrypto, ar->arGroupCryptoLen));
- reconnect_flag = 0;
- /* Set the listen interval into 1000TUs or more. This value will be indicated to Ap in the conn.
- later set it back locally at the STA to 100/1000 TUs depending on the power mode */
- if ((ar->arNetworkType == INFRA_NETWORK)) {
- wmi_listeninterval_cmd(ar->arWmi, max(ar->arListenIntervalT, (u16)A_MAX_WOW_LISTEN_INTERVAL), 0);
- }
- status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
- ar->arDot11AuthMode, ar->arAuthMode,
- ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
- ar->arGroupCrypto,ar->arGroupCryptoLen,
- ar->arSsidLen, ar->arSsid,
- ar->arReqBssid, ar->arChannelHint,
- ar->arConnectCtrlFlags);
- if (status) {
- wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB);
- if (!ar->arUserBssFilter) {
- wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0);
- }
- return status;
- }
-
- if ((!(ar->arConnectCtrlFlags & CONNECT_DO_WPA_OFFLOAD)) &&
- ((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)))
- {
- A_TIMEOUT_MS(&ar->disconnect_timer, A_DISCONNECT_TIMER_INTERVAL, 0);
- }
-
- ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD;
-
- ar->arConnectPending = true;
- return status;
- }
- return A_ERROR;
-}
-
-int
-ar6000_disconnect(struct ar6_softc *ar)
-{
- if ((ar->arConnected == true) || (ar->arConnectPending == true)) {
- wmi_disconnect_cmd(ar->arWmi);
- /*
- * Disconnect cmd is issued, clear connectPending.
- * arConnected will be cleard in disconnect_event notification.
- */
- ar->arConnectPending = false;
- }
-
- return 0;
-}
-
-int
-ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie)
-{
- sta_t *conn = NULL;
- conn = ieee80211_find_conn(ar, wpaie->wpa_macaddr);
-
- A_MEMZERO(wpaie->wpa_ie, IEEE80211_MAX_IE);
- A_MEMZERO(wpaie->rsn_ie, IEEE80211_MAX_IE);
-
- if(conn) {
- memcpy(wpaie->wpa_ie, conn->wpa_ie, IEEE80211_MAX_IE);
- }
-
- return 0;
-}
-
-int
-is_iwioctl_allowed(u8 mode, u16 cmd)
-{
- if(cmd >= SIOCSIWCOMMIT && cmd <= SIOCGIWPOWER) {
- cmd -= SIOCSIWCOMMIT;
- if(sioctl_filter[cmd] == 0xFF) return 0;
- if(sioctl_filter[cmd] & mode) return 0;
- } else if(cmd >= SIOCIWFIRSTPRIV && cmd <= (SIOCIWFIRSTPRIV+30)) {
- cmd -= SIOCIWFIRSTPRIV;
- if(pioctl_filter[cmd] == 0xFF) return 0;
- if(pioctl_filter[cmd] & mode) return 0;
- } else {
- return A_ERROR;
- }
- return A_ENOTSUP;
-}
-
-int
-is_xioctl_allowed(u8 mode, int cmd)
-{
- if(sizeof(xioctl_filter)-1 < cmd) {
- A_PRINTF("Filter for this cmd=%d not defined\n",cmd);
- return 0;
- }
- if(xioctl_filter[cmd] == 0xFF) return 0;
- if(xioctl_filter[cmd] & mode) return 0;
- return A_ERROR;
-}
-
-#ifdef WAPI_ENABLE
-int
-ap_set_wapi_key(struct ar6_softc *ar, void *ikey)
-{
- struct ieee80211req_key *ik = (struct ieee80211req_key *)ikey;
- KEY_USAGE keyUsage = 0;
- int status;
-
- if (memcmp(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN) == 0) {
- keyUsage = GROUP_USAGE;
- } else {
- keyUsage = PAIRWISE_USAGE;
- }
- A_PRINTF("WAPI_KEY: Type:%d ix:%d mac:%02x:%02x len:%d\n",
- keyUsage, ik->ik_keyix, ik->ik_macaddr[4], ik->ik_macaddr[5],
- ik->ik_keylen);
-
- status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, WAPI_CRYPT, keyUsage,
- ik->ik_keylen, (u8 *)&ik->ik_keyrsc,
- ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr,
- SYNC_BOTH_WMIFLAG);
-
- if (0 != status) {
- return -EIO;
- }
- return 0;
-}
-#endif
-
-void ar6000_peer_event(
- void *context,
- u8 eventCode,
- u8 *macAddr)
-{
- u8 pos;
-
- for (pos=0;pos<6;pos++)
- printk("%02x: ",*(macAddr+pos));
- printk("\n");
-}
-
-#ifdef HTC_TEST_SEND_PKTS
-#define HTC_TEST_DUPLICATE 8
-static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *dupskb)
-{
- struct ar_cookie *cookie;
- struct ar_cookie *cookieArray[HTC_TEST_DUPLICATE];
- struct sk_buff *new_skb;
- int i;
- int pkts = 0;
- struct htc_packet_queue pktQueue;
- EPPING_HEADER *eppingHdr;
-
- eppingHdr = A_NETBUF_DATA(dupskb);
-
- if (eppingHdr->Cmd_h == EPPING_CMD_NO_ECHO) {
- /* skip test if this is already a tx perf test */
- return;
- }
-
- for (i = 0; i < HTC_TEST_DUPLICATE; i++,pkts++) {
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- cookie = ar6000_alloc_cookie(ar);
- if (cookie != NULL) {
- ar->arTxPending[eid]++;
- ar->arTotalTxDataPending++;
- }
-
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-
- if (NULL == cookie) {
- break;
- }
-
- new_skb = A_NETBUF_ALLOC(A_NETBUF_LEN(dupskb));
-
- if (new_skb == NULL) {
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- ar6000_free_cookie(ar,cookie);
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- break;
- }
-
- A_NETBUF_PUT_DATA(new_skb, A_NETBUF_DATA(dupskb), A_NETBUF_LEN(dupskb));
- cookie->arc_bp[0] = (unsigned long)new_skb;
- cookie->arc_bp[1] = MapNo;
- SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
- cookie,
- A_NETBUF_DATA(new_skb),
- A_NETBUF_LEN(new_skb),
- eid,
- AR6K_DATA_PKT_TAG);
-
- cookieArray[i] = cookie;
-
- {
- EPPING_HEADER *pHdr = (EPPING_HEADER *)A_NETBUF_DATA(new_skb);
- pHdr->Cmd_h = EPPING_CMD_NO_ECHO; /* do not echo the packet */
- }
- }
-
- if (pkts == 0) {
- return;
- }
-
- INIT_HTC_PACKET_QUEUE(&pktQueue);
-
- for (i = 0; i < pkts; i++) {
- HTC_PACKET_ENQUEUE(&pktQueue,&cookieArray[i]->HtcPkt);
- }
-
- HTCSendPktsMultiple(ar->arHtcTarget, &pktQueue);
-
-}
-#endif
-
-#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
-/*
- * Add support for adding and removing a virtual adapter for soft AP.
- * Some OS requires different adapters names for station and soft AP mode.
- * To support these requirement, create and destroy a netdevice instance
- * when the AP mode is operational. A full fledged support for virual device
- * is not implemented. Rather a virtual interface is created and is linked
- * with the existing physical device instance during the operation of the
- * AP mode.
- */
-
-int ar6000_start_ap_interface(struct ar6_softc *ar)
-{
- struct ar_virtual_interface *arApDev;
-
- /* Change net_device to point to AP instance */
- arApDev = (struct ar_virtual_interface *)ar->arApDev;
- ar->arNetDev = arApDev->arNetDev;
-
- return 0;
-}
-
-int ar6000_stop_ap_interface(struct ar6_softc *ar)
-{
- struct ar_virtual_interface *arApDev;
-
- /* Change net_device to point to sta instance */
- arApDev = (struct ar_virtual_interface *)ar->arApDev;
- if (arApDev) {
- ar->arNetDev = arApDev->arStaNetDev;
- }
-
- return 0;
-}
-
-
-int ar6000_create_ap_interface(struct ar6_softc *ar, char *ap_ifname)
-{
- struct net_device *dev;
- struct ar_virtual_interface *arApDev;
-
- dev = alloc_etherdev(sizeof(struct ar_virtual_interface));
- if (dev == NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: can't alloc etherdev\n"));
- return A_ERROR;
- }
-
- ether_setup(dev);
- init_netdev(dev, ap_ifname);
- dev->priv_flags &= ~IFF_TX_SKB_SHARING;
-
- if (register_netdev(dev)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: register_netdev failed\n"));
- return A_ERROR;
- }
-
- arApDev = netdev_priv(dev);
- arApDev->arDev = ar;
- arApDev->arNetDev = dev;
- arApDev->arStaNetDev = ar->arNetDev;
-
- ar->arApDev = arApDev;
- arApNetDev = dev;
-
- /* Copy the MAC address */
- memcpy(dev->dev_addr, ar->arNetDev->dev_addr, AR6000_ETH_ADDR_LEN);
-
- return 0;
-}
-
-int ar6000_add_ap_interface(struct ar6_softc *ar, char *ap_ifname)
-{
- /* Interface already added, need not proceed further */
- if (ar->arApDev != NULL) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_add_ap_interface: interface already present \n"));
- return 0;
- }
-
- if (ar6000_create_ap_interface(ar, ap_ifname) != 0) {
- return A_ERROR;
- }
-
- A_PRINTF("Add AP interface %s \n",ap_ifname);
-
- return ar6000_start_ap_interface(ar);
-}
-
-int ar6000_remove_ap_interface(struct ar6_softc *ar)
-{
- if (arApNetDev) {
- ar6000_stop_ap_interface(ar);
-
- unregister_netdev(arApNetDev);
- free_netdev(apApNetDev);
-
- A_PRINTF("Remove AP interface\n");
- }
- ar->arApDev = NULL;
- arApNetDev = NULL;
-
-
- return 0;
-}
-#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
-
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-EXPORT_SYMBOL(setupbtdev);
-#endif
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_pm.c b/drivers/staging/ath6kl/os/linux/ar6000_pm.c
deleted file mode 100644
index 1e0ace8b6d13..000000000000
--- a/drivers/staging/ath6kl/os/linux/ar6000_pm.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- *
- * Copyright (c) 2004-2010 Atheros Communications Inc.
- * All rights reserved.
- *
- *
-//
-// 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.
-//
-//
- *
- */
-
-/*
- * Implementation of system power management
- */
-
-#include "ar6000_drv.h"
-#include <linux/inetdevice.h>
-#include <linux/platform_device.h>
-#include "wlan_config.h"
-
-#define WOW_ENABLE_MAX_INTERVAL 0
-#define WOW_SET_SCAN_PARAMS 0
-
-extern unsigned int wmitimeout;
-extern wait_queue_head_t arEvent;
-
-#undef ATH_MODULE_NAME
-#define ATH_MODULE_NAME pm
-#define ATH_DEBUG_PM ATH_DEBUG_MAKE_MODULE_MASK(0)
-
-#ifdef DEBUG
-static struct ath_debug_mask_description pm_debug_desc[] = {
- { ATH_DEBUG_PM , "System power management"},
-};
-
-ATH_DEBUG_INSTANTIATE_MODULE_VAR(pm,
- "pm",
- "System Power Management",
- ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_PM,
- ATH_DEBUG_DESCRIPTION_COUNT(pm_debug_desc),
- pm_debug_desc);
-
-#endif /* DEBUG */
-
-int ar6000_exit_cut_power_state(struct ar6_softc *ar);
-
-#ifdef CONFIG_PM
-static void ar6k_send_asleep_event_to_app(struct ar6_softc *ar, bool asleep)
-{
- char buf[128];
- union iwreq_data wrqu;
-
- snprintf(buf, sizeof(buf), "HOST_ASLEEP=%s", asleep ? "asleep" : "awake");
- A_MEMZERO(&wrqu, sizeof(wrqu));
- wrqu.data.length = strlen(buf);
- wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
-}
-
-static void ar6000_wow_resume(struct ar6_softc *ar)
-{
- if (ar->arWowState!= WLAN_WOW_STATE_NONE) {
- u16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period;
- u16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period;
- WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {true, false};
- ar->arWowState = WLAN_WOW_STATE_NONE;
- if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!= 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup restore host awake\n"));
- }
-#if WOW_SET_SCAN_PARAMS
- wmi_scanparams_cmd(ar->arWmi, fg_start_period,
- ar->scParams.fg_end_period,
- bg_period,
- ar->scParams.minact_chdwell_time,
- ar->scParams.maxact_chdwell_time,
- ar->scParams.pas_chdwell_time,
- ar->scParams.shortScanRatio,
- ar->scParams.scanCtrlFlags,
- ar->scParams.max_dfsch_act_time,
- ar->scParams.maxact_scan_per_ssid);
-#else
- (void)fg_start_period;
- (void)bg_period;
-#endif
-
-
-#if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */
- if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == 0) {
- }
-#endif
- ar6k_send_asleep_event_to_app(ar, false);
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Resume WoW successfully\n"));
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WoW does not invoked. skip resume"));
- }
- ar->arWlanPowerState = WLAN_POWER_STATE_ON;
-}
-
-static void ar6000_wow_suspend(struct ar6_softc *ar)
-{
-#define WOW_LIST_ID 1
- if (ar->arNetworkType != AP_NETWORK) {
- /* Setup WoW for unicast & Arp request for our own IP
- disable background scan. Set listen interval into 1000 TUs
- Enable keepliave for 110 seconds
- */
- struct in_ifaddr **ifap = NULL;
- struct in_ifaddr *ifa = NULL;
- struct in_device *in_dev;
- u8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- int status;
- WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } };
- WMI_DEL_WOW_PATTERN_CMD delWowCmd;
- WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {false, true};
- WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = true,
- .hostReqDelay = 500 };/*500 ms delay*/
-
- if (ar->arWowState!= WLAN_WOW_STATE_NONE) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("System already go into wow mode!\n"));
- return;
- }
-
- ar6000_TxDataCleanup(ar); /* IMPORTANT, otherwise there will be 11mA after listen interval as 1000*/
-
-#if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */
- if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == 0) {
- }
-#endif
-
-#if WOW_SET_SCAN_PARAMS
- status = wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0);
-#endif
- /* clear up our WoW pattern first */
- delWowCmd.filter_list_id = WOW_LIST_ID;
- delWowCmd.filter_id = 0;
- wmi_del_wow_pattern_cmd(ar->arWmi, &delWowCmd);
-
- /* setup unicast packet pattern for WoW */
- if (ar->arNetDev->dev_addr[1]) {
- addWowCmd.filter_list_id = WOW_LIST_ID;
- addWowCmd.filter_size = 6; /* MAC address */
- addWowCmd.filter_offset = 0;
- status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev->dev_addr, macMask, addWowCmd.filter_size);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n"));
- }
- }
- /* setup ARP request for our own IP */
- if ((in_dev = __in_dev_get_rtnl(ar->arNetDev)) != NULL) {
- for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) {
- if (!strcmp(ar->arNetDev->name, ifa->ifa_label)) {
- break; /* found */
- }
- }
- }
- if (ifa && ifa->ifa_local) {
- WMI_SET_IP_CMD ipCmd;
- memset(&ipCmd, 0, sizeof(ipCmd));
- ipCmd.ips[0] = ifa->ifa_local;
- status = wmi_set_ip_cmd(ar->arWmi, &ipCmd);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n"));
- }
- }
-
-#ifndef ATH6K_CONFIG_OTA_MODE
- wmi_powermode_cmd(ar->arWmi, REC_POWER);
-#endif
-
- status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n"));
- }
- ar6k_send_asleep_event_to_app(ar, true);
-
- status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n"));
- }
-
- ar->arWowState = WLAN_WOW_STATE_SUSPENDING;
- if (ar->arTxPending[ar->arControlEp]) {
- u32 timeleft = wait_event_interruptible_timeout(arEvent,
- ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ);
- if (!timeleft || signal_pending(current)) {
- /* what can I do? wow resume at once */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WoW. Pending wmi control data %d\n", ar->arTxPending[ar->arControlEp]));
- }
- }
-
- status = hifWaitForPendingRecv(ar->arHifDevice);
-
- ar->arWowState = WLAN_WOW_STATE_SUSPENDED;
- ar->arWlanPowerState = WLAN_POWER_STATE_WOW;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Not allowed to go to WOW at this moment.\n"));
- }
-}
-
-int ar6000_suspend_ev(void *context)
-{
- int status = 0;
- struct ar6_softc *ar = (struct ar6_softc *)context;
- s16 pmmode = ar->arSuspendConfig;
-wow_not_connected:
- switch (pmmode) {
- case WLAN_SUSPEND_WOW:
- if (ar->arWmiReady && ar->arWlanState==WLAN_ENABLED && ar->arConnected) {
- ar6000_wow_suspend(ar);
- AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for wow mode %d\n", __func__, ar->arWlanPowerState));
- } else {
- pmmode = ar->arWow2Config;
- goto wow_not_connected;
- }
- break;
- case WLAN_SUSPEND_CUT_PWR:
- /* fall through */
- case WLAN_SUSPEND_CUT_PWR_IF_BT_OFF:
- /* fall through */
- case WLAN_SUSPEND_DEEP_SLEEP:
- /* fall through */
- default:
- status = ar6000_update_wlan_pwr_state(ar, WLAN_DISABLED, true);
- if (ar->arWlanPowerState==WLAN_POWER_STATE_ON ||
- ar->arWlanPowerState==WLAN_POWER_STATE_WOW) {
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Strange suspend state for not wow mode %d", ar->arWlanPowerState));
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for %d mode pwr %d status %d\n", __func__, pmmode, ar->arWlanPowerState, status));
- status = (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) ? 0 : A_EBUSY;
- break;
- }
-
- ar->scan_triggered = 0;
- return status;
-}
-
-int ar6000_resume_ev(void *context)
-{
- struct ar6_softc *ar = (struct ar6_softc *)context;
- u16 powerState = ar->arWlanPowerState;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: enter previous state %d wowState %d\n", __func__, powerState, ar->arWowState));
- switch (powerState) {
- case WLAN_POWER_STATE_WOW:
- ar6000_wow_resume(ar);
- break;
- case WLAN_POWER_STATE_CUT_PWR:
- /* fall through */
- case WLAN_POWER_STATE_DEEP_SLEEP:
- ar6000_update_wlan_pwr_state(ar, WLAN_ENABLED, true);
- AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Resume for %d mode pwr %d\n", __func__, powerState, ar->arWlanPowerState));
- break;
- case WLAN_POWER_STATE_ON:
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange SDIO bus power mode!!\n"));
- break;
- }
- return 0;
-}
-
-void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent)
-{
- if (ar->arWowState!=WLAN_WOW_STATE_NONE) {
- if (ar->arWowState==WLAN_WOW_STATE_SUSPENDING) {
- AR_DEBUG_PRINTF(ATH_DEBUG_PM,("\n%s: Received IRQ while we are wow suspending!!!\n\n", __func__));
- return;
- }
- /* Wow resume from irq interrupt */
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: WoW resume from irq thread status %d\n", __func__, ar->arWlanPowerState));
- ar6000_wow_resume(ar);
- }
-}
-
-int ar6000_power_change_ev(void *context, u32 config)
-{
- struct ar6_softc *ar = (struct ar6_softc *)context;
- int status = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: power change event callback %d \n", __func__, config));
- switch (config) {
- case HIF_DEVICE_POWER_UP:
- ar6000_restart_endpoint(ar->arNetDev);
- status = 0;
- break;
- case HIF_DEVICE_POWER_DOWN:
- case HIF_DEVICE_POWER_CUT:
- status = 0;
- break;
- }
- return status;
-}
-
-#endif /* CONFIG_PM */
-
-int
-ar6000_setup_cut_power_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
-{
- int status = 0;
- HIF_DEVICE_POWER_CHANGE_TYPE config;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Cut power %d %d \n", __func__,state, ar->arWlanPowerState));
-#ifdef CONFIG_PM
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff));
-#endif
- do {
- if (state == WLAN_ENABLED) {
- /* Not in cut power state.. exit */
- if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) {
- break;
- }
-
- /* Change the state to ON */
- ar->arWlanPowerState = WLAN_POWER_STATE_ON;
-
-
- /* Indicate POWER_UP to HIF */
- config = HIF_DEVICE_POWER_UP;
- status = HIFConfigureDevice(ar->arHifDevice,
- HIF_DEVICE_POWER_STATE_CHANGE,
- &config,
- sizeof(HIF_DEVICE_POWER_CHANGE_TYPE));
-
- if (status == A_PENDING) {
- } else if (status == 0) {
- ar6000_restart_endpoint(ar->arNetDev);
- status = 0;
- }
- } else if (state == WLAN_DISABLED) {
-
-
- /* Already in cut power state.. exit */
- if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) {
- break;
- }
- ar6000_stop_endpoint(ar->arNetDev, true, false);
-
- config = HIF_DEVICE_POWER_CUT;
- status = HIFConfigureDevice(ar->arHifDevice,
- HIF_DEVICE_POWER_STATE_CHANGE,
- &config,
- sizeof(HIF_DEVICE_POWER_CHANGE_TYPE));
-
- ar->arWlanPowerState = WLAN_POWER_STATE_CUT_PWR;
- }
- } while (0);
-
- return status;
-}
-
-int
-ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
-{
- int status = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Deep sleep %d %d \n", __func__,state, ar->arWlanPowerState));
-#ifdef CONFIG_PM
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff));
-#endif
- do {
- WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode;
-
- if (state == WLAN_ENABLED) {
- u16 fg_start_period;
-
- /* Not in deep sleep state.. exit */
- if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) {
- if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange state when we resume from deep sleep %d\n", ar->arWlanPowerState));
- }
- break;
- }
-
- fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period;
- hostSleepMode.awake = true;
- hostSleepMode.asleep = false;
-
- if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)) != 0) {
- break;
- }
-
- /* Change the state to ON */
- ar->arWlanPowerState = WLAN_POWER_STATE_ON;
-
- /* Enable foreground scanning */
- if ((status=wmi_scanparams_cmd(ar->arWmi, fg_start_period,
- ar->scParams.fg_end_period,
- ar->scParams.bg_period,
- ar->scParams.minact_chdwell_time,
- ar->scParams.maxact_chdwell_time,
- ar->scParams.pas_chdwell_time,
- ar->scParams.shortScanRatio,
- ar->scParams.scanCtrlFlags,
- ar->scParams.max_dfsch_act_time,
- ar->scParams.maxact_scan_per_ssid)) != 0)
- {
- break;
- }
-
- if (ar->arNetworkType != AP_NETWORK)
- {
- if (ar->arSsidLen) {
- if (ar6000_connect_to_ap(ar) != 0) {
- /* no need to report error if connection failed */
- break;
- }
- }
- }
- } else if (state == WLAN_DISABLED){
- WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = false };
-
- /* Already in deep sleep state.. exit */
- if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) {
- if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange state when we suspend for deep sleep %d\n", ar->arWlanPowerState));
- }
- break;
- }
-
- if (ar->arNetworkType != AP_NETWORK)
- {
- /* Disconnect from the AP and disable foreground scanning */
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- if (ar->arConnected == true || ar->arConnectPending == true) {
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- wmi_disconnect_cmd(ar->arWmi);
- } else {
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- }
- }
-
- ar->scan_triggered = 0;
-
- if ((status=wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != 0) {
- break;
- }
-
- /* make sure we disable wow for deep sleep */
- if ((status=wmi_set_wow_mode_cmd(ar->arWmi, &wowMode))!= 0)
- {
- break;
- }
-
- ar6000_TxDataCleanup(ar);
-#ifndef ATH6K_CONFIG_OTA_MODE
- wmi_powermode_cmd(ar->arWmi, REC_POWER);
-#endif
-
- hostSleepMode.awake = false;
- hostSleepMode.asleep = true;
- if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode))!= 0) {
- break;
- }
- if (ar->arTxPending[ar->arControlEp]) {
- u32 timeleft = wait_event_interruptible_timeout(arEvent,
- ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ);
- if (!timeleft || signal_pending(current)) {
- status = A_ERROR;
- break;
- }
- }
- status = hifWaitForPendingRecv(ar->arHifDevice);
-
- ar->arWlanPowerState = WLAN_POWER_STATE_DEEP_SLEEP;
- }
- } while (0);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enter/exit deep sleep %d\n", state));
- }
-
- return status;
-}
-
-int
-ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool pmEvent)
-{
- int status = 0;
- u16 powerState, oldPowerState;
- AR6000_WLAN_STATE oldstate = ar->arWlanState;
- bool wlanOff = ar->arWlanOff;
-#ifdef CONFIG_PM
- bool btOff = ar->arBTOff;
-#endif /* CONFIG_PM */
-
- if ((state!=WLAN_DISABLED && state!=WLAN_ENABLED)) {
- return A_ERROR;
- }
-
- if (ar->bIsDestroyProgress) {
- return A_EBUSY;
- }
-
- if (down_interruptible(&ar->arSem)) {
- return A_ERROR;
- }
-
- if (ar->bIsDestroyProgress) {
- up(&ar->arSem);
- return A_EBUSY;
- }
-
- ar->arWlanState = wlanOff ? WLAN_DISABLED : state;
- oldPowerState = ar->arWlanPowerState;
- if (state == WLAN_ENABLED) {
- powerState = ar->arWlanPowerState;
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WLAN PWR set to ENABLE^^\n"));
- if (!wlanOff) {
- if (powerState == WLAN_POWER_STATE_DEEP_SLEEP) {
- status = ar6000_setup_deep_sleep_state(ar, WLAN_ENABLED);
- } else if (powerState == WLAN_POWER_STATE_CUT_PWR) {
- status = ar6000_setup_cut_power_state(ar, WLAN_ENABLED);
- }
- }
-#ifdef CONFIG_PM
- else if (pmEvent && wlanOff) {
- bool allowCutPwr = ((!ar->arBTSharing) || btOff);
- if ((powerState==WLAN_POWER_STATE_CUT_PWR) && (!allowCutPwr)) {
- /* Come out of cut power */
- ar6000_setup_cut_power_state(ar, WLAN_ENABLED);
- status = ar6000_setup_deep_sleep_state(ar, WLAN_DISABLED);
- }
- }
-#endif /* CONFIG_PM */
- } else if (state == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WLAN PWR set to DISABLED~\n"));
- powerState = WLAN_POWER_STATE_DEEP_SLEEP;
-#ifdef CONFIG_PM
- if (pmEvent) { /* disable due to suspend */
- bool suspendCutPwr = (ar->arSuspendConfig == WLAN_SUSPEND_CUT_PWR ||
- (ar->arSuspendConfig == WLAN_SUSPEND_WOW &&
- ar->arWow2Config==WLAN_SUSPEND_CUT_PWR));
- bool suspendCutIfBtOff = ((ar->arSuspendConfig ==
- WLAN_SUSPEND_CUT_PWR_IF_BT_OFF ||
- (ar->arSuspendConfig == WLAN_SUSPEND_WOW &&
- ar->arWow2Config==WLAN_SUSPEND_CUT_PWR_IF_BT_OFF)) &&
- (!ar->arBTSharing || btOff));
- if ((suspendCutPwr) ||
- (suspendCutIfBtOff) ||
- (ar->arWlanState==WLAN_POWER_STATE_CUT_PWR))
- {
- powerState = WLAN_POWER_STATE_CUT_PWR;
- }
- } else {
- if ((wlanOff) &&
- (ar->arWlanOffConfig == WLAN_OFF_CUT_PWR) &&
- (!ar->arBTSharing || btOff))
- {
- /* For BT clock sharing designs, CUT_POWER depend on BT state */
- powerState = WLAN_POWER_STATE_CUT_PWR;
- }
- }
-#endif /* CONFIG_PM */
-
- if (powerState == WLAN_POWER_STATE_DEEP_SLEEP) {
- if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) {
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Load firmware before set to deep sleep\n"));
- ar6000_setup_cut_power_state(ar, WLAN_ENABLED);
- }
- status = ar6000_setup_deep_sleep_state(ar, WLAN_DISABLED);
- } else if (powerState == WLAN_POWER_STATE_CUT_PWR) {
- status = ar6000_setup_cut_power_state(ar, WLAN_DISABLED);
- }
-
- }
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WLAN state %d\n", ar->arWlanState));
- ar->arWlanState = oldstate;
- } else if (status == 0) {
- WMI_REPORT_SLEEP_STATE_EVENT wmiSleepEvent, *pSleepEvent = NULL;
- if ((ar->arWlanPowerState == WLAN_POWER_STATE_ON) && (oldPowerState != WLAN_POWER_STATE_ON)) {
- wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_AWAKE;
- pSleepEvent = &wmiSleepEvent;
- } else if ((ar->arWlanPowerState != WLAN_POWER_STATE_ON) && (oldPowerState == WLAN_POWER_STATE_ON)) {
- wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP;
- pSleepEvent = &wmiSleepEvent;
- }
- if (pSleepEvent) {
- AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("SENT WLAN Sleep Event %d\n", wmiSleepEvent.sleepState));
- }
- }
- up(&ar->arSem);
- return status;
-}
-
-int
-ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 enable)
-{
-#ifdef CONFIG_PM
- bool off = (enable == 0);
- int status;
- if (ar->arBTOff == off) {
- return 0;
- }
- ar->arBTOff = off;
- status = ar6000_update_wlan_pwr_state(ar, ar->arWlanOff ? WLAN_DISABLED : WLAN_ENABLED, false);
- return status;
-#else
- return 0;
-#endif
-}
-
-int
-ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
-{
- int status;
- bool off = (state == WLAN_DISABLED);
- if (ar->arWlanOff == off) {
- return 0;
- }
- ar->arWlanOff = off;
- status = ar6000_update_wlan_pwr_state(ar, state, false);
- return status;
-}
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c b/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c
deleted file mode 100644
index ae7c1dd96d83..000000000000
--- a/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c
+++ /dev/null
@@ -1,455 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#include "ar6000_drv.h"
-
-#ifdef HTC_RAW_INTERFACE
-
-static void
-ar6000_htc_raw_read_cb(void *Context, struct htc_packet *pPacket)
-{
- struct ar6_softc *ar = (struct ar6_softc *)Context;
- raw_htc_buffer *busy;
- HTC_RAW_STREAM_ID streamID;
- AR_RAW_HTC_T *arRaw = ar->arRawHtc;
-
- busy = (raw_htc_buffer *)pPacket->pPktContext;
- A_ASSERT(busy != NULL);
-
- if (pPacket->Status == A_ECANCELED) {
- /*
- * HTC provides A_ECANCELED status when it doesn't want to be refilled
- * (probably due to a shutdown)
- */
- return;
- }
-
- streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint);
- A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED);
-
-#ifdef CF
- if (down_trylock(&arRaw->raw_htc_read_sem[streamID])) {
-#else
- if (down_interruptible(&arRaw->raw_htc_read_sem[streamID])) {
-#endif /* CF */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n"));
- }
-
- A_ASSERT((pPacket->Status != 0) ||
- (pPacket->pBuffer == (busy->data + HTC_HEADER_LEN)));
-
- busy->length = pPacket->ActualLength + HTC_HEADER_LEN;
- busy->currPtr = HTC_HEADER_LEN;
- arRaw->read_buffer_available[streamID] = true;
- //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("raw read cb: 0x%X 0x%X \n", busy->currPtr,busy->length);
- up(&arRaw->raw_htc_read_sem[streamID]);
-
- /* Signal the waiting process */
- AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Waking up the StreamID(%d) read process\n", streamID));
- wake_up_interruptible(&arRaw->raw_htc_read_queue[streamID]);
-}
-
-static void
-ar6000_htc_raw_write_cb(void *Context, struct htc_packet *pPacket)
-{
- struct ar6_softc *ar = (struct ar6_softc *)Context;
- raw_htc_buffer *free;
- HTC_RAW_STREAM_ID streamID;
- AR_RAW_HTC_T *arRaw = ar->arRawHtc;
-
- free = (raw_htc_buffer *)pPacket->pPktContext;
- A_ASSERT(free != NULL);
-
- if (pPacket->Status == A_ECANCELED) {
- /*
- * HTC provides A_ECANCELED status when it doesn't want to be refilled
- * (probably due to a shutdown)
- */
- return;
- }
-
- streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint);
- A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED);
-
-#ifdef CF
- if (down_trylock(&arRaw->raw_htc_write_sem[streamID])) {
-#else
- if (down_interruptible(&arRaw->raw_htc_write_sem[streamID])) {
-#endif
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n"));
- }
-
- A_ASSERT(pPacket->pBuffer == (free->data + HTC_HEADER_LEN));
-
- free->length = 0;
- arRaw->write_buffer_available[streamID] = true;
- up(&arRaw->raw_htc_write_sem[streamID]);
-
- /* Signal the waiting process */
- AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Waking up the StreamID(%d) write process\n", streamID));
- wake_up_interruptible(&arRaw->raw_htc_write_queue[streamID]);
-}
-
-/* connect to a service */
-static int ar6000_connect_raw_service(struct ar6_softc *ar,
- HTC_RAW_STREAM_ID StreamID)
-{
- int status;
- struct htc_service_connect_resp response;
- u8 streamNo;
- struct htc_service_connect_req connect;
-
- do {
-
- A_MEMZERO(&connect,sizeof(connect));
- /* pass the stream ID as meta data to the RAW streams service */
- streamNo = (u8)StreamID;
- connect.pMetaData = &streamNo;
- connect.MetaDataLength = sizeof(u8);
- /* these fields are the same for all endpoints */
- connect.EpCallbacks.pContext = ar;
- connect.EpCallbacks.EpTxComplete = ar6000_htc_raw_write_cb;
- connect.EpCallbacks.EpRecv = ar6000_htc_raw_read_cb;
- /* simple interface, we don't need these optional callbacks */
- connect.EpCallbacks.EpRecvRefill = NULL;
- connect.EpCallbacks.EpSendFull = NULL;
- connect.MaxSendQueueDepth = RAW_HTC_WRITE_BUFFERS_NUM;
-
- /* connect to the raw streams service, we may be able to get 1 or more
- * connections, depending on WHAT is running on the target */
- connect.ServiceID = HTC_RAW_STREAMS_SVC;
-
- A_MEMZERO(&response,sizeof(response));
-
- /* try to connect to the raw stream, it is okay if this fails with
- * status HTC_SERVICE_NO_MORE_EP */
- status = HTCConnectService(ar->arHtcTarget,
- &connect,
- &response);
-
- if (status) {
- if (response.ConnectRespCode == HTC_SERVICE_NO_MORE_EP) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC RAW , No more streams allowed \n"));
- status = 0;
- }
- break;
- }
-
- /* set endpoint mapping for the RAW HTC streams */
- arSetRawStream2EndpointIDMap(ar,StreamID,response.Endpoint);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("HTC RAW : stream ID: %d, endpoint: %d\n",
- StreamID, arRawStream2EndpointID(ar,StreamID)));
-
- } while (false);
-
- return status;
-}
-
-int ar6000_htc_raw_open(struct ar6_softc *ar)
-{
- int status;
- int streamID, endPt, count2;
- raw_htc_buffer *buffer;
- HTC_SERVICE_ID servicepriority;
- AR_RAW_HTC_T *arRaw = ar->arRawHtc;
- if (!arRaw) {
- arRaw = ar->arRawHtc = A_MALLOC(sizeof(AR_RAW_HTC_T));
- if (arRaw) {
- A_MEMZERO(arRaw, sizeof(AR_RAW_HTC_T));
- }
- }
- A_ASSERT(ar->arHtcTarget != NULL);
- if (!arRaw) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Faile to allocate memory for HTC RAW interface\n"));
- return -ENOMEM;
- }
- /* wait for target */
- status = HTCWaitTarget(ar->arHtcTarget);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTCWaitTarget failed (%d)\n", status));
- return -ENODEV;
- }
-
- for (endPt = 0; endPt < ENDPOINT_MAX; endPt++) {
- arRaw->arEp2RawMapping[endPt] = HTC_RAW_STREAM_NOT_MAPPED;
- }
-
- for (streamID = HTC_RAW_STREAM_0; streamID < HTC_RAW_STREAM_NUM_MAX; streamID++) {
- /* Initialize the data structures */
- sema_init(&arRaw->raw_htc_read_sem[streamID], 1);
- sema_init(&arRaw->raw_htc_write_sem[streamID], 1);
- init_waitqueue_head(&arRaw->raw_htc_read_queue[streamID]);
- init_waitqueue_head(&arRaw->raw_htc_write_queue[streamID]);
-
- /* try to connect to the raw service */
- status = ar6000_connect_raw_service(ar,streamID);
-
- if (status) {
- break;
- }
-
- if (arRawStream2EndpointID(ar,streamID) == 0) {
- break;
- }
-
- for (count2 = 0; count2 < RAW_HTC_READ_BUFFERS_NUM; count2 ++) {
- /* Initialize the receive buffers */
- buffer = &arRaw->raw_htc_write_buffer[streamID][count2];
- memset(buffer, 0, sizeof(raw_htc_buffer));
- buffer = &arRaw->raw_htc_read_buffer[streamID][count2];
- memset(buffer, 0, sizeof(raw_htc_buffer));
-
- SET_HTC_PACKET_INFO_RX_REFILL(&buffer->HTCPacket,
- buffer,
- buffer->data,
- HTC_RAW_BUFFER_SIZE,
- arRawStream2EndpointID(ar,streamID));
-
- /* Queue buffers to HTC for receive */
- if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != 0)
- {
- BMIInit();
- return -EIO;
- }
- }
-
- for (count2 = 0; count2 < RAW_HTC_WRITE_BUFFERS_NUM; count2 ++) {
- /* Initialize the receive buffers */
- buffer = &arRaw->raw_htc_write_buffer[streamID][count2];
- memset(buffer, 0, sizeof(raw_htc_buffer));
- }
-
- arRaw->read_buffer_available[streamID] = false;
- arRaw->write_buffer_available[streamID] = true;
- }
-
- if (status) {
- return -EIO;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("HTC RAW, number of streams the target supports: %d \n", streamID));
-
- servicepriority = HTC_RAW_STREAMS_SVC; /* only 1 */
-
- /* set callbacks and priority list */
- HTCSetCreditDistribution(ar->arHtcTarget,
- ar,
- NULL, /* use default */
- NULL, /* use default */
- &servicepriority,
- 1);
-
- /* Start the HTC component */
- if ((status = HTCStart(ar->arHtcTarget)) != 0) {
- BMIInit();
- return -EIO;
- }
-
- (ar)->arRawIfInit = true;
-
- return 0;
-}
-
-int ar6000_htc_raw_close(struct ar6_softc *ar)
-{
- A_PRINTF("ar6000_htc_raw_close called \n");
- HTCStop(ar->arHtcTarget);
-
- /* reset the device */
- ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, false);
- /* Initialize the BMI component */
- BMIInit();
-
- return 0;
-}
-
-raw_htc_buffer *
-get_filled_buffer(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID)
-{
- int count;
- raw_htc_buffer *busy;
- AR_RAW_HTC_T *arRaw = ar->arRawHtc;
-
- /* Check for data */
- for (count = 0; count < RAW_HTC_READ_BUFFERS_NUM; count ++) {
- busy = &arRaw->raw_htc_read_buffer[StreamID][count];
- if (busy->length) {
- break;
- }
- }
- if (busy->length) {
- arRaw->read_buffer_available[StreamID] = true;
- } else {
- arRaw->read_buffer_available[StreamID] = false;
- }
-
- return busy;
-}
-
-ssize_t ar6000_htc_raw_read(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID,
- char __user *buffer, size_t length)
-{
- int readPtr;
- raw_htc_buffer *busy;
- AR_RAW_HTC_T *arRaw = ar->arRawHtc;
-
- if (arRawStream2EndpointID(ar,StreamID) == 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID));
- return -EFAULT;
- }
-
- if (down_interruptible(&arRaw->raw_htc_read_sem[StreamID])) {
- return -ERESTARTSYS;
- }
-
- busy = get_filled_buffer(ar,StreamID);
- while (!arRaw->read_buffer_available[StreamID]) {
- up(&arRaw->raw_htc_read_sem[StreamID]);
-
- /* Wait for the data */
- AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) read process\n", StreamID));
- if (wait_event_interruptible(arRaw->raw_htc_read_queue[StreamID],
- arRaw->read_buffer_available[StreamID]))
- {
- return -EINTR;
- }
- if (down_interruptible(&arRaw->raw_htc_read_sem[StreamID])) {
- return -ERESTARTSYS;
- }
- busy = get_filled_buffer(ar,StreamID);
- }
-
- /* Read the data */
- readPtr = busy->currPtr;
- if (length > busy->length - HTC_HEADER_LEN) {
- length = busy->length - HTC_HEADER_LEN;
- }
- if (copy_to_user(buffer, &busy->data[readPtr], length)) {
- up(&arRaw->raw_htc_read_sem[StreamID]);
- return -EFAULT;
- }
-
- busy->currPtr += length;
-
- if (busy->currPtr == busy->length)
- {
- busy->currPtr = 0;
- busy->length = 0;
- HTC_PACKET_RESET_RX(&busy->HTCPacket);
- //AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("raw read ioctl: ep for packet:%d \n", busy->HTCPacket.Endpoint));
- HTCAddReceivePkt(ar->arHtcTarget, &busy->HTCPacket);
- }
- arRaw->read_buffer_available[StreamID] = false;
- up(&arRaw->raw_htc_read_sem[StreamID]);
-
- return length;
-}
-
-static raw_htc_buffer *
-get_free_buffer(struct ar6_softc *ar, HTC_ENDPOINT_ID StreamID)
-{
- int count;
- raw_htc_buffer *free;
- AR_RAW_HTC_T *arRaw = ar->arRawHtc;
-
- free = NULL;
- for (count = 0; count < RAW_HTC_WRITE_BUFFERS_NUM; count ++) {
- free = &arRaw->raw_htc_write_buffer[StreamID][count];
- if (free->length == 0) {
- break;
- }
- }
- if (!free->length) {
- arRaw->write_buffer_available[StreamID] = true;
- } else {
- arRaw->write_buffer_available[StreamID] = false;
- }
-
- return free;
-}
-
-ssize_t ar6000_htc_raw_write(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID,
- char __user *buffer, size_t length)
-{
- int writePtr;
- raw_htc_buffer *free;
- AR_RAW_HTC_T *arRaw = ar->arRawHtc;
- if (arRawStream2EndpointID(ar,StreamID) == 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID));
- return -EFAULT;
- }
-
- if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) {
- return -ERESTARTSYS;
- }
-
- /* Search for a free buffer */
- free = get_free_buffer(ar,StreamID);
-
- /* Check if there is space to write else wait */
- while (!arRaw->write_buffer_available[StreamID]) {
- up(&arRaw->raw_htc_write_sem[StreamID]);
-
- /* Wait for buffer to become free */
- AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) write process\n", StreamID));
- if (wait_event_interruptible(arRaw->raw_htc_write_queue[StreamID],
- arRaw->write_buffer_available[StreamID]))
- {
- return -EINTR;
- }
- if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) {
- return -ERESTARTSYS;
- }
- free = get_free_buffer(ar,StreamID);
- }
-
- /* Send the data */
- writePtr = HTC_HEADER_LEN;
- if (length > (HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN)) {
- length = HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN;
- }
-
- if (copy_from_user(&free->data[writePtr], buffer, length)) {
- up(&arRaw->raw_htc_read_sem[StreamID]);
- return -EFAULT;
- }
-
- free->length = length;
-
- SET_HTC_PACKET_INFO_TX(&free->HTCPacket,
- free,
- &free->data[writePtr],
- length,
- arRawStream2EndpointID(ar,StreamID),
- AR6K_DATA_PKT_TAG);
-
- HTCSendPkt(ar->arHtcTarget,&free->HTCPacket);
-
- arRaw->write_buffer_available[StreamID] = false;
- up(&arRaw->raw_htc_write_sem[StreamID]);
-
- return length;
-}
-#endif /* HTC_RAW_INTERFACE */
diff --git a/drivers/staging/ath6kl/os/linux/cfg80211.c b/drivers/staging/ath6kl/os/linux/cfg80211.c
deleted file mode 100644
index 5fdda4aa2fee..000000000000
--- a/drivers/staging/ath6kl/os/linux/cfg80211.c
+++ /dev/null
@@ -1,1892 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#include <linux/wireless.h>
-#include <linux/ieee80211.h>
-#include <net/cfg80211.h>
-#include <net/netlink.h>
-
-#include "ar6000_drv.h"
-
-
-extern A_WAITQUEUE_HEAD arEvent;
-extern unsigned int wmitimeout;
-extern int reconnect_flag;
-
-
-#define RATETAB_ENT(_rate, _rateid, _flags) { \
- .bitrate = (_rate), \
- .flags = (_flags), \
- .hw_value = (_rateid), \
-}
-
-#define CHAN2G(_channel, _freq, _flags) { \
- .band = IEEE80211_BAND_2GHZ, \
- .hw_value = (_channel), \
- .center_freq = (_freq), \
- .flags = (_flags), \
- .max_antenna_gain = 0, \
- .max_power = 30, \
-}
-
-#define CHAN5G(_channel, _flags) { \
- .band = IEEE80211_BAND_5GHZ, \
- .hw_value = (_channel), \
- .center_freq = 5000 + (5 * (_channel)), \
- .flags = (_flags), \
- .max_antenna_gain = 0, \
- .max_power = 30, \
-}
-
-static struct
-ieee80211_rate ar6k_rates[] = {
- RATETAB_ENT(10, 0x1, 0),
- RATETAB_ENT(20, 0x2, 0),
- RATETAB_ENT(55, 0x4, 0),
- RATETAB_ENT(110, 0x8, 0),
- RATETAB_ENT(60, 0x10, 0),
- RATETAB_ENT(90, 0x20, 0),
- RATETAB_ENT(120, 0x40, 0),
- RATETAB_ENT(180, 0x80, 0),
- RATETAB_ENT(240, 0x100, 0),
- RATETAB_ENT(360, 0x200, 0),
- RATETAB_ENT(480, 0x400, 0),
- RATETAB_ENT(540, 0x800, 0),
-};
-
-#define ar6k_a_rates (ar6k_rates + 4)
-#define ar6k_a_rates_size 8
-#define ar6k_g_rates (ar6k_rates + 0)
-#define ar6k_g_rates_size 12
-
-static struct
-ieee80211_channel ar6k_2ghz_channels[] = {
- CHAN2G(1, 2412, 0),
- CHAN2G(2, 2417, 0),
- CHAN2G(3, 2422, 0),
- CHAN2G(4, 2427, 0),
- CHAN2G(5, 2432, 0),
- CHAN2G(6, 2437, 0),
- CHAN2G(7, 2442, 0),
- CHAN2G(8, 2447, 0),
- CHAN2G(9, 2452, 0),
- CHAN2G(10, 2457, 0),
- CHAN2G(11, 2462, 0),
- CHAN2G(12, 2467, 0),
- CHAN2G(13, 2472, 0),
- CHAN2G(14, 2484, 0),
-};
-
-static struct
-ieee80211_channel ar6k_5ghz_a_channels[] = {
- CHAN5G(34, 0), CHAN5G(36, 0),
- CHAN5G(38, 0), CHAN5G(40, 0),
- CHAN5G(42, 0), CHAN5G(44, 0),
- CHAN5G(46, 0), CHAN5G(48, 0),
- CHAN5G(52, 0), CHAN5G(56, 0),
- CHAN5G(60, 0), CHAN5G(64, 0),
- CHAN5G(100, 0), CHAN5G(104, 0),
- CHAN5G(108, 0), CHAN5G(112, 0),
- CHAN5G(116, 0), CHAN5G(120, 0),
- CHAN5G(124, 0), CHAN5G(128, 0),
- CHAN5G(132, 0), CHAN5G(136, 0),
- CHAN5G(140, 0), CHAN5G(149, 0),
- CHAN5G(153, 0), CHAN5G(157, 0),
- CHAN5G(161, 0), CHAN5G(165, 0),
- CHAN5G(184, 0), CHAN5G(188, 0),
- CHAN5G(192, 0), CHAN5G(196, 0),
- CHAN5G(200, 0), CHAN5G(204, 0),
- CHAN5G(208, 0), CHAN5G(212, 0),
- CHAN5G(216, 0),
-};
-
-static struct
-ieee80211_supported_band ar6k_band_2ghz = {
- .n_channels = ARRAY_SIZE(ar6k_2ghz_channels),
- .channels = ar6k_2ghz_channels,
- .n_bitrates = ar6k_g_rates_size,
- .bitrates = ar6k_g_rates,
-};
-
-static struct
-ieee80211_supported_band ar6k_band_5ghz = {
- .n_channels = ARRAY_SIZE(ar6k_5ghz_a_channels),
- .channels = ar6k_5ghz_a_channels,
- .n_bitrates = ar6k_a_rates_size,
- .bitrates = ar6k_a_rates,
-};
-
-static int
-ar6k_set_wpa_version(struct ar6_softc *ar, enum nl80211_wpa_versions wpa_version)
-{
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: %u\n", __func__, wpa_version));
-
- if (!wpa_version) {
- ar->arAuthMode = NONE_AUTH;
- } else if (wpa_version & NL80211_WPA_VERSION_1) {
- ar->arAuthMode = WPA_AUTH;
- } else if (wpa_version & NL80211_WPA_VERSION_2) {
- ar->arAuthMode = WPA2_AUTH;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("%s: %u not spported\n", __func__, wpa_version));
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static int
-ar6k_set_auth_type(struct ar6_softc *ar, enum nl80211_auth_type auth_type)
-{
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, auth_type));
-
- switch (auth_type) {
- case NL80211_AUTHTYPE_OPEN_SYSTEM:
- ar->arDot11AuthMode = OPEN_AUTH;
- break;
- case NL80211_AUTHTYPE_SHARED_KEY:
- ar->arDot11AuthMode = SHARED_AUTH;
- break;
- case NL80211_AUTHTYPE_NETWORK_EAP:
- ar->arDot11AuthMode = LEAP_AUTH;
- break;
-
- case NL80211_AUTHTYPE_AUTOMATIC:
- ar->arDot11AuthMode = OPEN_AUTH;
- ar->arAutoAuthStage = AUTH_OPEN_IN_PROGRESS;
- break;
-
- default:
- ar->arDot11AuthMode = OPEN_AUTH;
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: 0x%x not spported\n", __func__, auth_type));
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static int
-ar6k_set_cipher(struct ar6_softc *ar, u32 cipher, bool ucast)
-{
- u8 *ar_cipher = ucast ? &ar->arPairwiseCrypto :
- &ar->arGroupCrypto;
- u8 *ar_cipher_len = ucast ? &ar->arPairwiseCryptoLen :
- &ar->arGroupCryptoLen;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: cipher 0x%x, ucast %u\n", __func__, cipher, ucast));
-
- switch (cipher) {
- case 0:
- case IW_AUTH_CIPHER_NONE:
- *ar_cipher = NONE_CRYPT;
- *ar_cipher_len = 0;
- break;
- case WLAN_CIPHER_SUITE_WEP40:
- *ar_cipher = WEP_CRYPT;
- *ar_cipher_len = 5;
- break;
- case WLAN_CIPHER_SUITE_WEP104:
- *ar_cipher = WEP_CRYPT;
- *ar_cipher_len = 13;
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- *ar_cipher = TKIP_CRYPT;
- *ar_cipher_len = 0;
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- *ar_cipher = AES_CRYPT;
- *ar_cipher_len = 0;
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("%s: cipher 0x%x not supported\n", __func__, cipher));
- return -ENOTSUPP;
- }
-
- return 0;
-}
-
-static void
-ar6k_set_key_mgmt(struct ar6_softc *ar, u32 key_mgmt)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, key_mgmt));
-
- if (WLAN_AKM_SUITE_PSK == key_mgmt) {
- if (WPA_AUTH == ar->arAuthMode) {
- ar->arAuthMode = WPA_PSK_AUTH;
- } else if (WPA2_AUTH == ar->arAuthMode) {
- ar->arAuthMode = WPA2_PSK_AUTH;
- }
- } else if (WLAN_AKM_SUITE_8021X != key_mgmt) {
- ar->arAuthMode = NONE_AUTH;
- }
-}
-
-static int
-ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_connect_params *sme)
-{
- struct ar6_softc *ar = ar6k_priv(dev);
- int status;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
- ar->smeState = SME_CONNECTING;
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready yet\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if(ar->bIsDestroyProgress) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: destroy in progress\n", __func__));
- return -EBUSY;
- }
-
- if(!sme->ssid_len || IEEE80211_MAX_SSID_LEN < sme->ssid_len) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ssid invalid\n", __func__));
- return -EINVAL;
- }
-
- if(ar->arSkipScan == true &&
- ((sme->channel && sme->channel->center_freq == 0) ||
- (sme->bssid && !sme->bssid[0] && !sme->bssid[1] && !sme->bssid[2] &&
- !sme->bssid[3] && !sme->bssid[4] && !sme->bssid[5])))
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s:SkipScan: channel or bssid invalid\n", __func__));
- return -EINVAL;
- }
-
- if(down_interruptible(&ar->arSem)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__));
- return -ERESTARTSYS;
- }
-
- if(ar->bIsDestroyProgress) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, destroy in progress\n", __func__));
- up(&ar->arSem);
- return -EBUSY;
- }
-
- if(ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) {
- /*
- * sleep until the command queue drains
- */
- wait_event_interruptible_timeout(arEvent,
- ar->arTxPending[wmi_get_control_ep(ar->arWmi)] == 0, wmitimeout * HZ);
- if (signal_pending(current)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: cmd queue drain timeout\n", __func__));
- up(&ar->arSem);
- return -EINTR;
- }
- }
-
- if(ar->arConnected == true &&
- ar->arSsidLen == sme->ssid_len &&
- !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) {
- reconnect_flag = true;
- status = wmi_reconnect_cmd(ar->arWmi,
- ar->arReqBssid,
- ar->arChannelHint);
-
- up(&ar->arSem);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_reconnect_cmd failed\n", __func__));
- return -EIO;
- }
- return 0;
- } else if(ar->arSsidLen == sme->ssid_len &&
- !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) {
- ar6000_disconnect(ar);
- }
-
- A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
- ar->arSsidLen = sme->ssid_len;
- memcpy(ar->arSsid, sme->ssid, sme->ssid_len);
-
- if(sme->channel){
- ar->arChannelHint = sme->channel->center_freq;
- }
-
- A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
- if(sme->bssid){
- if(memcmp(&sme->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) {
- memcpy(ar->arReqBssid, sme->bssid, sizeof(ar->arReqBssid));
- }
- }
-
- ar6k_set_wpa_version(ar, sme->crypto.wpa_versions);
- ar6k_set_auth_type(ar, sme->auth_type);
-
- if(sme->crypto.n_ciphers_pairwise) {
- ar6k_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true);
- } else {
- ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, true);
- }
- ar6k_set_cipher(ar, sme->crypto.cipher_group, false);
-
- if(sme->crypto.n_akm_suites) {
- ar6k_set_key_mgmt(ar, sme->crypto.akm_suites[0]);
- }
-
- if((sme->key_len) &&
- (NONE_AUTH == ar->arAuthMode) &&
- (WEP_CRYPT == ar->arPairwiseCrypto)) {
- struct ar_key *key = NULL;
-
- if(sme->key_idx < WMI_MIN_KEY_INDEX || sme->key_idx > WMI_MAX_KEY_INDEX) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("%s: key index %d out of bounds\n", __func__, sme->key_idx));
- up(&ar->arSem);
- return -ENOENT;
- }
-
- key = &ar->keys[sme->key_idx];
- key->key_len = sme->key_len;
- memcpy(key->key, sme->key, key->key_len);
- key->cipher = ar->arPairwiseCrypto;
- ar->arDefTxKeyIndex = sme->key_idx;
-
- wmi_addKey_cmd(ar->arWmi, sme->key_idx,
- ar->arPairwiseCrypto,
- GROUP_USAGE | TX_USAGE,
- key->key_len,
- NULL,
- key->key, KEY_OP_INIT_VAL, NULL,
- NO_SYNC_WMIFLAG);
- }
-
- if (!ar->arUserBssFilter) {
- if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__));
- up(&ar->arSem);
- return -EIO;
- }
- }
-
- ar->arNetworkType = ar->arNextMode;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Connect called with authmode %d dot11 auth %d"\
- " PW crypto %d PW crypto Len %d GRP crypto %d"\
- " GRP crypto Len %d channel hint %u\n",
- __func__, ar->arAuthMode, ar->arDot11AuthMode,
- ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
- ar->arGroupCrypto, ar->arGroupCryptoLen, ar->arChannelHint));
-
- reconnect_flag = 0;
- status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
- ar->arDot11AuthMode, ar->arAuthMode,
- ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
- ar->arGroupCrypto,ar->arGroupCryptoLen,
- ar->arSsidLen, ar->arSsid,
- ar->arReqBssid, ar->arChannelHint,
- ar->arConnectCtrlFlags);
-
- up(&ar->arSem);
-
- if (A_EINVAL == status) {
- A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
- ar->arSsidLen = 0;
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Invalid request\n", __func__));
- return -ENOENT;
- } else if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_connect_cmd failed\n", __func__));
- return -EIO;
- }
-
- if ((!(ar->arConnectCtrlFlags & CONNECT_DO_WPA_OFFLOAD)) &&
- ((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)))
- {
- A_TIMEOUT_MS(&ar->disconnect_timer, A_DISCONNECT_TIMER_INTERVAL, 0);
- }
-
- ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD;
- ar->arConnectPending = true;
-
- return 0;
-}
-
-void
-ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel,
- u8 *bssid, u16 listenInterval,
- u16 beaconInterval,NETWORK_TYPE networkType,
- u8 beaconIeLen, u8 assocReqLen,
- u8 assocRespLen, u8 *assocInfo)
-{
- u16 size = 0;
- u16 capability = 0;
- struct cfg80211_bss *bss = NULL;
- struct ieee80211_mgmt *mgmt = NULL;
- struct ieee80211_channel *ibss_channel = NULL;
- s32 signal = 50 * 100;
- u8 ie_buf_len = 0;
- unsigned char ie_buf[256];
- unsigned char *ptr_ie_buf = ie_buf;
- unsigned char *ieeemgmtbuf = NULL;
- u8 source_mac[ATH_MAC_LEN];
-
- u8 assocReqIeOffset = sizeof(u16) + /* capinfo*/
- sizeof(u16); /* listen interval */
- u8 assocRespIeOffset = sizeof(u16) + /* capinfo*/
- sizeof(u16) + /* status Code */
- sizeof(u16); /* associd */
- u8 *assocReqIe = assocInfo + beaconIeLen + assocReqIeOffset;
- u8 *assocRespIe = assocInfo + beaconIeLen + assocReqLen + assocRespIeOffset;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
-
- assocReqLen -= assocReqIeOffset;
- assocRespLen -= assocRespIeOffset;
-
- ar->arAutoAuthStage = AUTH_IDLE;
-
- if((ADHOC_NETWORK & networkType)) {
- if(NL80211_IFTYPE_ADHOC != ar->wdev->iftype) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: ath6k not in ibss mode\n", __func__));
- return;
- }
- }
-
- if((INFRA_NETWORK & networkType)) {
- if(NL80211_IFTYPE_STATION != ar->wdev->iftype) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: ath6k not in station mode\n", __func__));
- return;
- }
- }
-
- /* Before informing the join/connect event, make sure that
- * bss entry is present in scan list, if it not present
- * construct and insert into scan list, otherwise that
- * event will be dropped on the way by cfg80211, due to
- * this keys will not be plumbed in case of WEP and
- * application will not be aware of join/connect status. */
- bss = cfg80211_get_bss(ar->wdev->wiphy, NULL, bssid,
- ar->wdev->ssid, ar->wdev->ssid_len,
- ((ADHOC_NETWORK & networkType) ? WLAN_CAPABILITY_IBSS : WLAN_CAPABILITY_ESS),
- ((ADHOC_NETWORK & networkType) ? WLAN_CAPABILITY_IBSS : WLAN_CAPABILITY_ESS));
-
- /*
- * Earlier we were updating the cfg about bss by making a beacon frame
- * only if the entry for bss is not there. This can have some issue if
- * ROAM event is generated and a heavy traffic is ongoing. The ROAM
- * event is handled through a work queue and by the time it really gets
- * handled, BSS would have been aged out. So it is better to update the
- * cfg about BSS irrespective of its entry being present right now or
- * not.
- */
-
- if (ADHOC_NETWORK & networkType) {
- /* construct 802.11 mgmt beacon */
- if(ptr_ie_buf) {
- *ptr_ie_buf++ = WLAN_EID_SSID;
- *ptr_ie_buf++ = ar->arSsidLen;
- memcpy(ptr_ie_buf, ar->arSsid, ar->arSsidLen);
- ptr_ie_buf +=ar->arSsidLen;
-
- *ptr_ie_buf++ = WLAN_EID_IBSS_PARAMS;
- *ptr_ie_buf++ = 2; /* length */
- *ptr_ie_buf++ = 0; /* ATIM window */
- *ptr_ie_buf++ = 0; /* ATIM window */
-
- /* TODO: update ibss params and include supported rates,
- * DS param set, extened support rates, wmm. */
-
- ie_buf_len = ptr_ie_buf - ie_buf;
- }
-
- capability |= IEEE80211_CAPINFO_IBSS;
- if(WEP_CRYPT == ar->arPairwiseCrypto) {
- capability |= IEEE80211_CAPINFO_PRIVACY;
- }
- memcpy(source_mac, ar->arNetDev->dev_addr, ATH_MAC_LEN);
- ptr_ie_buf = ie_buf;
- } else {
- capability = *(u16 *)(&assocInfo[beaconIeLen]);
- memcpy(source_mac, bssid, ATH_MAC_LEN);
- ptr_ie_buf = assocReqIe;
- ie_buf_len = assocReqLen;
- }
-
- size = offsetof(struct ieee80211_mgmt, u)
- + sizeof(mgmt->u.beacon)
- + ie_buf_len;
-
- ieeemgmtbuf = A_MALLOC_NOWAIT(size);
- if(!ieeemgmtbuf) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("%s: ieeeMgmtbuf alloc error\n", __func__));
- cfg80211_put_bss(bss);
- return;
- }
-
- A_MEMZERO(ieeemgmtbuf, size);
- mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf;
- mgmt->frame_control = (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
- memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN);
- memcpy(mgmt->sa, source_mac, ATH_MAC_LEN);
- memcpy(mgmt->bssid, bssid, ATH_MAC_LEN);
- mgmt->u.beacon.beacon_int = beaconInterval;
- mgmt->u.beacon.capab_info = capability;
- memcpy(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len);
-
- ibss_channel = ieee80211_get_channel(ar->wdev->wiphy, (int)channel);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: inform bss with bssid %pM channel %d beaconInterval %d "
- "capability 0x%x\n", __func__, mgmt->bssid,
- ibss_channel->hw_value, beaconInterval, capability));
-
- bss = cfg80211_inform_bss_frame(ar->wdev->wiphy,
- ibss_channel, mgmt,
- le16_to_cpu(size),
- signal, GFP_KERNEL);
- kfree(ieeemgmtbuf);
- cfg80211_put_bss(bss);
-
- if((ADHOC_NETWORK & networkType)) {
- cfg80211_ibss_joined(ar->arNetDev, bssid, GFP_KERNEL);
- return;
- }
-
- if (false == ar->arConnected) {
- /* inform connect result to cfg80211 */
- ar->smeState = SME_DISCONNECTED;
- cfg80211_connect_result(ar->arNetDev, bssid,
- assocReqIe, assocReqLen,
- assocRespIe, assocRespLen,
- WLAN_STATUS_SUCCESS, GFP_KERNEL);
- } else {
- /* inform roam event to cfg80211 */
- cfg80211_roamed(ar->arNetDev, ibss_channel, bssid,
- assocReqIe, assocReqLen,
- assocRespIe, assocRespLen,
- GFP_KERNEL);
- }
-}
-
-static int
-ar6k_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
- u16 reason_code)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason_code));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if(ar->bIsDestroyProgress) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, destroy in progress\n", __func__));
- return -EBUSY;
- }
-
- if(down_interruptible(&ar->arSem)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__));
- return -ERESTARTSYS;
- }
-
- reconnect_flag = 0;
- ar6000_disconnect(ar);
- A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
- ar->arSsidLen = 0;
-
- if (ar->arSkipScan == false) {
- A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
- }
-
- up(&ar->arSem);
-
- return 0;
-}
-
-void
-ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason,
- u8 *bssid, u8 assocRespLen,
- u8 *assocInfo, u16 protocolReasonStatus)
-{
-
- u16 status;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason));
-
- if (ar->scan_request) {
- cfg80211_scan_done(ar->scan_request, true);
- ar->scan_request = NULL;
- }
- if((ADHOC_NETWORK & ar->arNetworkType)) {
- if(NL80211_IFTYPE_ADHOC != ar->wdev->iftype) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: ath6k not in ibss mode\n", __func__));
- return;
- }
- A_MEMZERO(bssid, ETH_ALEN);
- cfg80211_ibss_joined(ar->arNetDev, bssid, GFP_KERNEL);
- return;
- }
-
- if((INFRA_NETWORK & ar->arNetworkType)) {
- if(NL80211_IFTYPE_STATION != ar->wdev->iftype) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: ath6k not in station mode\n", __func__));
- return;
- }
- }
-
- if(true == ar->arConnectPending) {
- if(NO_NETWORK_AVAIL == reason) {
- /* connect cmd failed */
- wmi_disconnect_cmd(ar->arWmi);
- } else if (reason == DISCONNECT_CMD) {
- if (ar->arAutoAuthStage) {
- /*
- * If the current auth algorithm is open try shared
- * and make autoAuthStage idle. We do not make it
- * leap for now being.
- */
- if (ar->arDot11AuthMode == OPEN_AUTH) {
- struct ar_key *key = NULL;
- key = &ar->keys[ar->arDefTxKeyIndex];
- if (down_interruptible(&ar->arSem)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__));
- return;
- }
-
-
- ar->arDot11AuthMode = SHARED_AUTH;
- ar->arAutoAuthStage = AUTH_IDLE;
-
- wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex,
- ar->arPairwiseCrypto,
- GROUP_USAGE | TX_USAGE,
- key->key_len,
- NULL,
- key->key, KEY_OP_INIT_VAL, NULL,
- NO_SYNC_WMIFLAG);
-
- status = wmi_connect_cmd(ar->arWmi,
- ar->arNetworkType,
- ar->arDot11AuthMode,
- ar->arAuthMode,
- ar->arPairwiseCrypto,
- ar->arPairwiseCryptoLen,
- ar->arGroupCrypto,
- ar->arGroupCryptoLen,
- ar->arSsidLen,
- ar->arSsid,
- ar->arReqBssid,
- ar->arChannelHint,
- ar->arConnectCtrlFlags);
- up(&ar->arSem);
-
- } else if (ar->arDot11AuthMode == SHARED_AUTH) {
- /* should not reach here */
- }
- } else {
- ar->arConnectPending = false;
- if (ar->smeState == SME_CONNECTING) {
- cfg80211_connect_result(ar->arNetDev, bssid,
- NULL, 0,
- NULL, 0,
- WLAN_STATUS_UNSPECIFIED_FAILURE,
- GFP_KERNEL);
- } else {
- cfg80211_disconnected(ar->arNetDev,
- reason,
- NULL, 0,
- GFP_KERNEL);
- }
- ar->smeState = SME_DISCONNECTED;
- }
- }
- } else {
- if (reason != DISCONNECT_CMD)
- wmi_disconnect_cmd(ar->arWmi);
- }
-}
-
-void
-ar6k_cfg80211_scan_node(void *arg, bss_t *ni)
-{
- struct wiphy *wiphy = (struct wiphy *)arg;
- u16 size;
- unsigned char *ieeemgmtbuf = NULL;
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_channel *channel;
- struct ieee80211_supported_band *band;
- struct ieee80211_common_ie *cie;
- s32 signal;
- int freq;
-
- cie = &ni->ni_cie;
-
-#define CHAN_IS_11A(x) (!((x >= 2412) && (x <= 2484)))
- if(CHAN_IS_11A(cie->ie_chan)) {
- /* 11a */
- band = wiphy->bands[IEEE80211_BAND_5GHZ];
- } else if((cie->ie_erp) || (cie->ie_xrates)) {
- /* 11g */
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
- } else {
- /* 11b */
- band = wiphy->bands[IEEE80211_BAND_2GHZ];
- }
-
- size = ni->ni_framelen + offsetof(struct ieee80211_mgmt, u);
- ieeemgmtbuf = A_MALLOC_NOWAIT(size);
- if(!ieeemgmtbuf)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ieeeMgmtbuf alloc error\n", __func__));
- return;
- }
-
- /* Note:
- TODO: Update target to include 802.11 mac header while sending bss info.
- Target removes 802.11 mac header while sending the bss info to host,
- cfg80211 needs it, for time being just filling the da, sa and bssid fields alone.
- */
- mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf;
- memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN);
- memcpy(mgmt->sa, ni->ni_macaddr, ATH_MAC_LEN);
- memcpy(mgmt->bssid, ni->ni_macaddr, ATH_MAC_LEN);
- memcpy(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u),
- ni->ni_buf, ni->ni_framelen);
-
- freq = cie->ie_chan;
- channel = ieee80211_get_channel(wiphy, freq);
- signal = ni->ni_snr * 100;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: bssid %pM channel %d freq %d size %d\n", __func__,
- mgmt->bssid, channel->hw_value, freq, size));
- cfg80211_inform_bss_frame(wiphy, channel, mgmt,
- le16_to_cpu(size),
- signal, GFP_KERNEL);
-
- kfree (ieeemgmtbuf);
-}
-
-static int
-ar6k_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_scan_request *request)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
- int ret = 0;
- u32 forceFgScan = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if (!ar->arUserBssFilter) {
- if (wmi_bssfilter_cmd(ar->arWmi,
- (ar->arConnected ? ALL_BUT_BSS_FILTER : ALL_BSS_FILTER),
- 0) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__));
- return -EIO;
- }
- }
-
- if(request->n_ssids &&
- request->ssids[0].ssid_len) {
- u8 i;
-
- if(request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) {
- request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
- }
-
- for (i = 0; i < request->n_ssids; i++) {
- wmi_probedSsid_cmd(ar->arWmi, i+1, SPECIFIC_SSID_FLAG,
- request->ssids[i].ssid_len,
- request->ssids[i].ssid);
- }
- }
-
- if(ar->arConnected) {
- forceFgScan = 1;
- }
-
- if(wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, forceFgScan, false, \
- 0, 0, 0, NULL) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_startscan_cmd failed\n", __func__));
- ret = -EIO;
- }
-
- ar->scan_request = request;
-
- return ret;
-}
-
-void
-ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status)
-{
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: status %d\n", __func__, status));
-
- if (!ar->scan_request)
- return;
-
- if ((status == A_ECANCELED) || (status == A_EBUSY)) {
- cfg80211_scan_done(ar->scan_request, true);
- goto out;
- }
-
- /* Translate data to cfg80211 mgmt format */
- wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy);
-
- cfg80211_scan_done(ar->scan_request, false);
-
- if(ar->scan_request->n_ssids &&
- ar->scan_request->ssids[0].ssid_len) {
- u8 i;
-
- for (i = 0; i < ar->scan_request->n_ssids; i++) {
- wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG,
- 0, NULL);
- }
- }
-
-out:
- ar->scan_request = NULL;
-}
-
-static int
-ar6k_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index, bool pairwise, const u8 *mac_addr,
- struct key_params *params)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
- struct ar_key *key = NULL;
- u8 key_usage;
- u8 key_type;
- int status = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s:\n", __func__));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: key index %d out of bounds\n", __func__, key_index));
- return -ENOENT;
- }
-
- key = &ar->keys[key_index];
- A_MEMZERO(key, sizeof(struct ar_key));
-
- if(!mac_addr || is_broadcast_ether_addr(mac_addr)) {
- key_usage = GROUP_USAGE;
- } else {
- key_usage = PAIRWISE_USAGE;
- }
-
- if(params) {
- if(params->key_len > WLAN_MAX_KEY_LEN ||
- params->seq_len > IW_ENCODE_SEQ_MAX_SIZE)
- return -EINVAL;
-
- key->key_len = params->key_len;
- memcpy(key->key, params->key, key->key_len);
- key->seq_len = params->seq_len;
- memcpy(key->seq, params->seq, key->seq_len);
- key->cipher = params->cipher;
- }
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- key_type = WEP_CRYPT;
- break;
-
- case WLAN_CIPHER_SUITE_TKIP:
- key_type = TKIP_CRYPT;
- break;
-
- case WLAN_CIPHER_SUITE_CCMP:
- key_type = AES_CRYPT;
- break;
-
- default:
- return -ENOTSUPP;
- }
-
- if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)) &&
- (GROUP_USAGE & key_usage))
- {
- A_UNTIMEOUT(&ar->disconnect_timer);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: index %d, key_len %d, key_type 0x%x,"\
- " key_usage 0x%x, seq_len %d\n",
- __func__, key_index, key->key_len, key_type,
- key_usage, key->seq_len));
-
- ar->arDefTxKeyIndex = key_index;
- status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, key_type, key_usage,
- key->key_len, key->seq, key->key, KEY_OP_INIT_VAL,
- (u8 *)mac_addr, SYNC_BOTH_WMIFLAG);
-
-
- if (status) {
- return -EIO;
- }
-
- return 0;
-}
-
-static int
-ar6k_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index, bool pairwise, const u8 *mac_addr)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: key index %d out of bounds\n", __func__, key_index));
- return -ENOENT;
- }
-
- if(!ar->keys[key_index].key_len) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d is empty\n", __func__, key_index));
- return 0;
- }
-
- ar->keys[key_index].key_len = 0;
-
- return wmi_deleteKey_cmd(ar->arWmi, key_index);
-}
-
-
-static int
-ar6k_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index, bool pairwise, const u8 *mac_addr,
- void *cookie,
- void (*callback)(void *cookie, struct key_params*))
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
- struct ar_key *key = NULL;
- struct key_params params;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: key index %d out of bounds\n", __func__, key_index));
- return -ENOENT;
- }
-
- key = &ar->keys[key_index];
- A_MEMZERO(&params, sizeof(params));
- params.cipher = key->cipher;
- params.key_len = key->key_len;
- params.seq_len = key->seq_len;
- params.seq = key->seq;
- params.key = key->key;
-
- callback(cookie, &params);
-
- return key->key_len ? 0 : -ENOENT;
-}
-
-
-static int
-ar6k_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index, bool unicast, bool multicast)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
- struct ar_key *key = NULL;
- int status = 0;
- u8 key_usage;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: key index %d out of bounds\n",
- __func__, key_index));
- return -ENOENT;
- }
-
- if(!ar->keys[key_index].key_len) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: invalid key index %d\n",
- __func__, key_index));
- return -EINVAL;
- }
-
- ar->arDefTxKeyIndex = key_index;
- key = &ar->keys[ar->arDefTxKeyIndex];
- key_usage = GROUP_USAGE;
- if (WEP_CRYPT == ar->arPairwiseCrypto) {
- key_usage |= TX_USAGE;
- }
-
- status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex,
- ar->arPairwiseCrypto, key_usage,
- key->key_len, key->seq, key->key, KEY_OP_INIT_VAL,
- NULL, SYNC_BOTH_WMIFLAG);
- if (status) {
- return -EIO;
- }
-
- return 0;
-}
-
-static int
-ar6k_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__));
- return -ENOTSUPP;
-}
-
-void
-ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
- ("%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast));
-
- cfg80211_michael_mic_failure(ar->arNetDev, ar->arBssid,
- (ismcast ? NL80211_KEYTYPE_GROUP : NL80211_KEYTYPE_PAIRWISE),
- keyid, NULL, GFP_KERNEL);
-}
-
-static int
-ar6k_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
-{
- struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: changed 0x%x\n", __func__, changed));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
- if (wmi_set_rts_cmd(ar->arWmi,wiphy->rts_threshold) != 0){
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_set_rts_cmd failed\n", __func__));
- return -EIO;
- }
- }
-
- return 0;
-}
-
-static int
-ar6k_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
- const u8 *peer,
- const struct cfg80211_bitrate_mask *mask)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Setting rates: Not supported\n"));
- return -EIO;
-}
-
-/* The type nl80211_tx_power_setting replaces the following data type from 2.6.36 onwards */
-static int
-ar6k_cfg80211_set_txpower(struct wiphy *wiphy, enum nl80211_tx_power_setting type, int dbm)
-{
- struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy);
- u8 ar_dbm;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x, dbm %d\n", __func__, type, dbm));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- ar->arTxPwrSet = false;
- switch(type) {
- case NL80211_TX_POWER_AUTOMATIC:
- return 0;
- case NL80211_TX_POWER_LIMITED:
- ar->arTxPwr = ar_dbm = dbm;
- ar->arTxPwrSet = true;
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x not supported\n", __func__, type));
- return -EOPNOTSUPP;
- }
-
- wmi_set_txPwr_cmd(ar->arWmi, ar_dbm);
-
- return 0;
-}
-
-static int
-ar6k_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
-{
- struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if((ar->arConnected == true)) {
- ar->arTxPwr = 0;
-
- if(wmi_get_txPwr_cmd(ar->arWmi) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_get_txPwr_cmd failed\n", __func__));
- return -EIO;
- }
-
- wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, 5 * HZ);
-
- if(signal_pending(current)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Target did not respond\n", __func__));
- return -EINTR;
- }
- }
-
- *dbm = ar->arTxPwr;
- return 0;
-}
-
-static int
-ar6k_cfg80211_set_power_mgmt(struct wiphy *wiphy,
- struct net_device *dev,
- bool pmgmt, int timeout)
-{
- struct ar6_softc *ar = ar6k_priv(dev);
- WMI_POWER_MODE_CMD pwrMode;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: pmgmt %d, timeout %d\n", __func__, pmgmt, timeout));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if(pmgmt) {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Max Perf\n", __func__));
- pwrMode.powerMode = REC_POWER;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Rec Power\n", __func__));
- pwrMode.powerMode = MAX_PERF_POWER;
- }
-
- if(wmi_powermode_cmd(ar->arWmi, pwrMode.powerMode) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_powermode_cmd failed\n", __func__));
- return -EIO;
- }
-
- return 0;
-}
-
-static struct net_device *
-ar6k_cfg80211_add_virtual_intf(struct wiphy *wiphy, char *name,
- enum nl80211_iftype type, u32 *flags,
- struct vif_params *params)
-{
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__));
-
- /* Multiple virtual interface is not supported.
- * The default interface supports STA and IBSS type
- */
- return ERR_PTR(-EOPNOTSUPP);
-}
-
-static int
-ar6k_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
-{
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__));
-
- /* Multiple virtual interface is not supported.
- * The default interface supports STA and IBSS type
- */
- return -EOPNOTSUPP;
-}
-
-static int
-ar6k_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
- enum nl80211_iftype type, u32 *flags,
- struct vif_params *params)
-{
- struct ar6_softc *ar = ar6k_priv(ndev);
- struct wireless_dev *wdev = ar->wdev;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type %u\n", __func__, type));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- switch (type) {
- case NL80211_IFTYPE_STATION:
- ar->arNextMode = INFRA_NETWORK;
- break;
- case NL80211_IFTYPE_ADHOC:
- ar->arNextMode = ADHOC_NETWORK;
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: type %u\n", __func__, type));
- return -EOPNOTSUPP;
- }
-
- wdev->iftype = type;
-
- return 0;
-}
-
-static int
-ar6k_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_ibss_params *ibss_param)
-{
- struct ar6_softc *ar = ar6k_priv(dev);
- int status;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- if(!ibss_param->ssid_len || IEEE80211_MAX_SSID_LEN < ibss_param->ssid_len) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ssid invalid\n", __func__));
- return -EINVAL;
- }
-
- ar->arSsidLen = ibss_param->ssid_len;
- memcpy(ar->arSsid, ibss_param->ssid, ar->arSsidLen);
-
- if(ibss_param->channel) {
- ar->arChannelHint = ibss_param->channel->center_freq;
- }
-
- if(ibss_param->channel_fixed) {
- /* TODO: channel_fixed: The channel should be fixed, do not search for
- * IBSSs to join on other channels. Target firmware does not support this
- * feature, needs to be updated.*/
- }
-
- A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
- if(ibss_param->bssid) {
- if(memcmp(&ibss_param->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) {
- memcpy(ar->arReqBssid, ibss_param->bssid, sizeof(ar->arReqBssid));
- }
- }
-
- ar6k_set_wpa_version(ar, 0);
- ar6k_set_auth_type(ar, NL80211_AUTHTYPE_OPEN_SYSTEM);
-
- if(ibss_param->privacy) {
- ar6k_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, true);
- ar6k_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, false);
- } else {
- ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, true);
- ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, false);
- }
-
- ar->arNetworkType = ar->arNextMode;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Connect called with authmode %d dot11 auth %d"\
- " PW crypto %d PW crypto Len %d GRP crypto %d"\
- " GRP crypto Len %d channel hint %u\n",
- __func__, ar->arAuthMode, ar->arDot11AuthMode,
- ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
- ar->arGroupCrypto, ar->arGroupCryptoLen, ar->arChannelHint));
-
- status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
- ar->arDot11AuthMode, ar->arAuthMode,
- ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
- ar->arGroupCrypto,ar->arGroupCryptoLen,
- ar->arSsidLen, ar->arSsid,
- ar->arReqBssid, ar->arChannelHint,
- ar->arConnectCtrlFlags);
- ar->arConnectPending = true;
-
- return 0;
-}
-
-static int
-ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
-{
- struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
-
- if(ar->arWmiReady == false) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
- return -EIO;
- }
-
- if(ar->arWlanState == WLAN_DISABLED) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__));
- return -EIO;
- }
-
- ar6000_disconnect(ar);
- A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
- ar->arSsidLen = 0;
-
- return 0;
-}
-
-#ifdef CONFIG_NL80211_TESTMODE
-enum ar6k_testmode_attr {
- __AR6K_TM_ATTR_INVALID = 0,
- AR6K_TM_ATTR_CMD = 1,
- AR6K_TM_ATTR_DATA = 2,
-
- /* keep last */
- __AR6K_TM_ATTR_AFTER_LAST,
- AR6K_TM_ATTR_MAX = __AR6K_TM_ATTR_AFTER_LAST - 1
-};
-
-enum ar6k_testmode_cmd {
- AR6K_TM_CMD_TCMD = 0,
- AR6K_TM_CMD_RX_REPORT = 1,
-};
-
-#define AR6K_TM_DATA_MAX_LEN 5000
-
-static const struct nla_policy ar6k_testmode_policy[AR6K_TM_ATTR_MAX + 1] = {
- [AR6K_TM_ATTR_CMD] = { .type = NLA_U32 },
- [AR6K_TM_ATTR_DATA] = { .type = NLA_BINARY,
- .len = AR6K_TM_DATA_MAX_LEN },
-};
-
-void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf,
- int buf_len)
-{
- if (down_interruptible(&ar->arSem))
- return;
-
- kfree(ar->tcmd_rx_report);
-
- ar->tcmd_rx_report = kmemdup(buf, buf_len, GFP_KERNEL);
- ar->tcmd_rx_report_len = buf_len;
-
- up(&ar->arSem);
-
- wake_up(&arEvent);
-}
-
-static int ar6000_testmode_rx_report(struct ar6_softc *ar, void *buf,
- int buf_len, struct sk_buff *skb)
-{
- int ret = 0;
- long left;
-
- if (down_interruptible(&ar->arSem))
- return -ERESTARTSYS;
-
- if (ar->arWmiReady == false) {
- ret = -EIO;
- goto out;
- }
-
- if (ar->bIsDestroyProgress) {
- ret = -EBUSY;
- goto out;
- }
-
- WARN_ON(ar->tcmd_rx_report != NULL);
- WARN_ON(ar->tcmd_rx_report_len > 0);
-
- if (wmi_test_cmd(ar->arWmi, buf, buf_len) < 0) {
- up(&ar->arSem);
- return -EIO;
- }
-
- left = wait_event_interruptible_timeout(arEvent,
- ar->tcmd_rx_report != NULL,
- wmitimeout * HZ);
-
- if (left == 0) {
- ret = -ETIMEDOUT;
- goto out;
- } else if (left < 0) {
- ret = left;
- goto out;
- }
-
- if (ar->tcmd_rx_report == NULL || ar->tcmd_rx_report_len == 0) {
- ret = -EINVAL;
- goto out;
- }
-
- NLA_PUT(skb, AR6K_TM_ATTR_DATA, ar->tcmd_rx_report_len,
- ar->tcmd_rx_report);
-
- kfree(ar->tcmd_rx_report);
- ar->tcmd_rx_report = NULL;
-
-out:
- up(&ar->arSem);
-
- return ret;
-
-nla_put_failure:
- ret = -ENOBUFS;
- goto out;
-}
-
-static int ar6k_testmode_cmd(struct wiphy *wiphy, void *data, int len)
-{
- struct ar6_softc *ar = wiphy_priv(wiphy);
- struct nlattr *tb[AR6K_TM_ATTR_MAX + 1];
- int err, buf_len, reply_len;
- struct sk_buff *skb;
- void *buf;
-
- err = nla_parse(tb, AR6K_TM_ATTR_MAX, data, len,
- ar6k_testmode_policy);
- if (err)
- return err;
-
- if (!tb[AR6K_TM_ATTR_CMD])
- return -EINVAL;
-
- switch (nla_get_u32(tb[AR6K_TM_ATTR_CMD])) {
- case AR6K_TM_CMD_TCMD:
- if (!tb[AR6K_TM_ATTR_DATA])
- return -EINVAL;
-
- buf = nla_data(tb[AR6K_TM_ATTR_DATA]);
- buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]);
-
- wmi_test_cmd(ar->arWmi, buf, buf_len);
-
- return 0;
-
- break;
- case AR6K_TM_CMD_RX_REPORT:
- if (!tb[AR6K_TM_ATTR_DATA])
- return -EINVAL;
-
- buf = nla_data(tb[AR6K_TM_ATTR_DATA]);
- buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]);
-
- reply_len = nla_total_size(AR6K_TM_DATA_MAX_LEN);
- skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len);
- if (!skb)
- return -ENOMEM;
-
- err = ar6000_testmode_rx_report(ar, buf, buf_len, skb);
- if (err < 0) {
- kfree_skb(skb);
- return err;
- }
-
- return cfg80211_testmode_reply(skb);
- default:
- return -EOPNOTSUPP;
- }
-}
-#endif
-
-static const
-u32 cipher_suites[] = {
- WLAN_CIPHER_SUITE_WEP40,
- WLAN_CIPHER_SUITE_WEP104,
- WLAN_CIPHER_SUITE_TKIP,
- WLAN_CIPHER_SUITE_CCMP,
-};
-
-bool is_rate_legacy(s32 rate)
-{
- static const s32 legacy[] = { 1000, 2000, 5500, 11000,
- 6000, 9000, 12000, 18000, 24000,
- 36000, 48000, 54000 };
- u8 i;
-
- for (i = 0; i < ARRAY_SIZE(legacy); i++) {
- if (rate == legacy[i])
- return true;
- }
-
- return false;
-}
-
-bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
-{
- static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
- 52000, 58500, 65000, 72200 };
- u8 i;
-
- for (i = 0; i < ARRAY_SIZE(ht20); i++) {
- if (rate == ht20[i]) {
- if (i == ARRAY_SIZE(ht20) - 1)
- /* last rate uses sgi */
- *sgi = true;
- else
- *sgi = false;
-
- *mcs = i;
- return true;
- }
- }
- return false;
-}
-
-bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
-{
- static const s32 ht40[] = { 13500, 27000, 40500, 54000,
- 81000, 108000, 121500, 135000,
- 150000 };
- u8 i;
-
- for (i = 0; i < ARRAY_SIZE(ht40); i++) {
- if (rate == ht40[i]) {
- if (i == ARRAY_SIZE(ht40) - 1)
- /* last rate uses sgi */
- *sgi = true;
- else
- *sgi = false;
-
- *mcs = i;
- return true;
- }
- }
-
- return false;
-}
-
-static int ar6k_get_station(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac, struct station_info *sinfo)
-{
- struct ar6_softc *ar = ar6k_priv(dev);
- long left;
- bool sgi;
- s32 rate;
- int ret;
- u8 mcs;
-
- if (memcmp(mac, ar->arBssid, ETH_ALEN) != 0)
- return -ENOENT;
-
- if (down_interruptible(&ar->arSem))
- return -EBUSY;
-
- ar->statsUpdatePending = true;
-
- ret = wmi_get_stats_cmd(ar->arWmi);
-
- if (ret != 0) {
- up(&ar->arSem);
- return -EIO;
- }
-
- left = wait_event_interruptible_timeout(arEvent,
- ar->statsUpdatePending == false,
- wmitimeout * HZ);
-
- up(&ar->arSem);
-
- if (left == 0)
- return -ETIMEDOUT;
- else if (left < 0)
- return left;
-
- if (ar->arTargetStats.rx_bytes) {
- sinfo->rx_bytes = ar->arTargetStats.rx_bytes;
- sinfo->filled |= STATION_INFO_RX_BYTES;
- sinfo->rx_packets = ar->arTargetStats.rx_packets;
- sinfo->filled |= STATION_INFO_RX_PACKETS;
- }
-
- if (ar->arTargetStats.tx_bytes) {
- sinfo->tx_bytes = ar->arTargetStats.tx_bytes;
- sinfo->filled |= STATION_INFO_TX_BYTES;
- sinfo->tx_packets = ar->arTargetStats.tx_packets;
- sinfo->filled |= STATION_INFO_TX_PACKETS;
- }
-
- sinfo->signal = ar->arTargetStats.cs_rssi;
- sinfo->filled |= STATION_INFO_SIGNAL;
-
- rate = ar->arTargetStats.tx_unicast_rate;
-
- if (is_rate_legacy(rate)) {
- sinfo->txrate.legacy = rate / 100;
- } else if (is_rate_ht20(rate, &mcs, &sgi)) {
- if (sgi) {
- sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- sinfo->txrate.mcs = mcs - 1;
- } else {
- sinfo->txrate.mcs = mcs;
- }
-
- sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
- } else if (is_rate_ht40(rate, &mcs, &sgi)) {
- if (sgi) {
- sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- sinfo->txrate.mcs = mcs - 1;
- } else {
- sinfo->txrate.mcs = mcs;
- }
-
- sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
- sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
- } else {
- WARN(1, "invalid rate: %d", rate);
- return 0;
- }
-
- sinfo->filled |= STATION_INFO_TX_BITRATE;
-
- return 0;
-}
-
-static int ar6k_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
- struct cfg80211_pmksa *pmksa)
-{
- struct ar6_softc *ar = ar6k_priv(netdev);
- return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, true);
-}
-
-static int ar6k_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
- struct cfg80211_pmksa *pmksa)
-{
- struct ar6_softc *ar = ar6k_priv(netdev);
- return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, false);
-}
-
-static int ar6k_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
-{
- struct ar6_softc *ar = ar6k_priv(netdev);
- if (ar->arConnected)
- return wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, false);
- return 0;
-}
-
-static struct
-cfg80211_ops ar6k_cfg80211_ops = {
- .change_virtual_intf = ar6k_cfg80211_change_iface,
- .add_virtual_intf = ar6k_cfg80211_add_virtual_intf,
- .del_virtual_intf = ar6k_cfg80211_del_virtual_intf,
- .scan = ar6k_cfg80211_scan,
- .connect = ar6k_cfg80211_connect,
- .disconnect = ar6k_cfg80211_disconnect,
- .add_key = ar6k_cfg80211_add_key,
- .get_key = ar6k_cfg80211_get_key,
- .del_key = ar6k_cfg80211_del_key,
- .set_default_key = ar6k_cfg80211_set_default_key,
- .set_default_mgmt_key = ar6k_cfg80211_set_default_mgmt_key,
- .set_wiphy_params = ar6k_cfg80211_set_wiphy_params,
- .set_bitrate_mask = ar6k_cfg80211_set_bitrate_mask,
- .set_tx_power = ar6k_cfg80211_set_txpower,
- .get_tx_power = ar6k_cfg80211_get_txpower,
- .set_power_mgmt = ar6k_cfg80211_set_power_mgmt,
- .join_ibss = ar6k_cfg80211_join_ibss,
- .leave_ibss = ar6k_cfg80211_leave_ibss,
- .get_station = ar6k_get_station,
- .set_pmksa = ar6k_set_pmksa,
- .del_pmksa = ar6k_del_pmksa,
- .flush_pmksa = ar6k_flush_pmksa,
- CFG80211_TESTMODE_CMD(ar6k_testmode_cmd)
-};
-
-struct wireless_dev *
-ar6k_cfg80211_init(struct device *dev)
-{
- int ret = 0;
- struct wireless_dev *wdev;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
-
- wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
- if(!wdev) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("%s: Couldn't allocate wireless device\n", __func__));
- return ERR_PTR(-ENOMEM);
- }
-
- /* create a new wiphy for use with cfg80211 */
- wdev->wiphy = wiphy_new(&ar6k_cfg80211_ops, sizeof(struct ar6_softc));
- if(!wdev->wiphy) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("%s: Couldn't allocate wiphy device\n", __func__));
- kfree(wdev);
- return ERR_PTR(-ENOMEM);
- }
-
- /* set device pointer for wiphy */
- set_wiphy_dev(wdev->wiphy, dev);
-
- wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
- /* max num of ssids that can be probed during scanning */
- wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
- wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar6k_band_2ghz;
- wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar6k_band_5ghz;
- wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
-
- wdev->wiphy->cipher_suites = cipher_suites;
- wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
-
- ret = wiphy_register(wdev->wiphy);
- if(ret < 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("%s: Couldn't register wiphy device\n", __func__));
- wiphy_free(wdev->wiphy);
- return ERR_PTR(ret);
- }
-
- return wdev;
-}
-
-void
-ar6k_cfg80211_deinit(struct ar6_softc *ar)
-{
- struct wireless_dev *wdev = ar->wdev;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
-
- if(ar->scan_request) {
- cfg80211_scan_done(ar->scan_request, true);
- ar->scan_request = NULL;
- }
-
- if(!wdev)
- return;
-
- wiphy_unregister(wdev->wiphy);
- wiphy_free(wdev->wiphy);
- kfree(wdev);
-}
-
-
-
-
-
-
-
diff --git a/drivers/staging/ath6kl/os/linux/export_hci_transport.c b/drivers/staging/ath6kl/os/linux/export_hci_transport.c
deleted file mode 100644
index 430998edacc4..000000000000
--- a/drivers/staging/ath6kl/os/linux/export_hci_transport.c
+++ /dev/null
@@ -1,124 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// HCI bridge implementation
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#include <a_config.h>
-#include <athdefs.h>
-#include "a_osapi.h"
-#include "htc_api.h"
-#include "a_drv.h"
-#include "hif.h"
-#include "common_drv.h"
-#include "a_debug.h"
-#include "hci_transport_api.h"
-
-#include "AR6002/hw4.0/hw/apb_athr_wlan_map.h"
-#include "AR6002/hw4.0/hw/uart_reg.h"
-#include "AR6002/hw4.0/hw/rtc_wlan_reg.h"
-
-HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo);
-void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans);
-int (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue);
-int (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous);
-void (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans);
-int (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans);
-int (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
-int (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans,
- struct htc_packet *pPacket,
- int MaxPollMS);
-int (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud);
-int (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
-
-extern struct hci_transport_callbacks ar6kHciTransCallbacks;
-
-int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks)
-{
- ar6kHciTransCallbacks = *hciTransCallbacks;
-
- _HCI_TransportAttach = HCI_TransportAttach;
- _HCI_TransportDetach = HCI_TransportDetach;
- _HCI_TransportAddReceivePkts = HCI_TransportAddReceivePkts;
- _HCI_TransportSendPkt = HCI_TransportSendPkt;
- _HCI_TransportStop = HCI_TransportStop;
- _HCI_TransportStart = HCI_TransportStart;
- _HCI_TransportEnableDisableAsyncRecv = HCI_TransportEnableDisableAsyncRecv;
- _HCI_TransportRecvHCIEventSync = HCI_TransportRecvHCIEventSync;
- _HCI_TransportSetBaudRate = HCI_TransportSetBaudRate;
- _HCI_TransportEnablePowerMgmt = HCI_TransportEnablePowerMgmt;
-
- return 0;
-}
-
-int
-ar6000_get_hif_dev(struct hif_device *device, void *config)
-{
- int status;
-
- status = HIFConfigureDevice(device,
- HIF_DEVICE_GET_OS_DEVICE,
- (struct hif_device_os_device_info *)config,
- sizeof(struct hif_device_os_device_info));
- return status;
-}
-
-int ar6000_set_uart_config(struct hif_device *hifDevice,
- u32 scale,
- u32 step)
-{
- u32 regAddress;
- u32 regVal;
- int status;
-
- regAddress = WLAN_UART_BASE_ADDRESS | UART_CLKDIV_ADDRESS;
- regVal = ((u32)scale << 16) | step;
- /* change the HCI UART scale/step values through the diagnostic window */
- status = ar6000_WriteRegDiag(hifDevice, &regAddress, &regVal);
-
- return status;
-}
-
-int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data)
-{
- u32 regAddress;
- int status;
-
- regAddress = WLAN_RTC_BASE_ADDRESS | WLAN_CPU_CLOCK_ADDRESS;
- /* read CPU clock settings*/
- status = ar6000_ReadRegDiag(hifDevice, &regAddress, data);
-
- return status;
-}
-
-EXPORT_SYMBOL(ar6000_register_hci_transport);
-EXPORT_SYMBOL(ar6000_get_hif_dev);
-EXPORT_SYMBOL(ar6000_set_uart_config);
-EXPORT_SYMBOL(ar6000_get_core_clock_config);
-EXPORT_SYMBOL(_HCI_TransportAttach);
-EXPORT_SYMBOL(_HCI_TransportDetach);
-EXPORT_SYMBOL(_HCI_TransportAddReceivePkts);
-EXPORT_SYMBOL(_HCI_TransportSendPkt);
-EXPORT_SYMBOL(_HCI_TransportStop);
-EXPORT_SYMBOL(_HCI_TransportStart);
-EXPORT_SYMBOL(_HCI_TransportEnableDisableAsyncRecv);
-EXPORT_SYMBOL(_HCI_TransportRecvHCIEventSync);
-EXPORT_SYMBOL(_HCI_TransportSetBaudRate);
-EXPORT_SYMBOL(_HCI_TransportEnablePowerMgmt);
diff --git a/drivers/staging/ath6kl/os/linux/hci_bridge.c b/drivers/staging/ath6kl/os/linux/hci_bridge.c
deleted file mode 100644
index 6087edcb1d6a..000000000000
--- a/drivers/staging/ath6kl/os/linux/hci_bridge.c
+++ /dev/null
@@ -1,1141 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// HCI bridge implementation
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-#include <linux/etherdevice.h>
-#include <a_config.h>
-#include <athdefs.h>
-#include "a_osapi.h"
-#include "htc_api.h"
-#include "wmi.h"
-#include "a_drv.h"
-#include "hif.h"
-#include "common_drv.h"
-#include "a_debug.h"
-#define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6)
-#define ATH_DEBUG_HCI_RECV ATH_DEBUG_MAKE_MODULE_MASK(7)
-#define ATH_DEBUG_HCI_SEND ATH_DEBUG_MAKE_MODULE_MASK(8)
-#define ATH_DEBUG_HCI_DUMP ATH_DEBUG_MAKE_MODULE_MASK(9)
-#else
-#include "ar6000_drv.h"
-#endif /* EXPORT_HCI_BRIDGE_INTERFACE */
-
-#ifdef ATH_AR6K_ENABLE_GMBOX
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-#include "export_hci_transport.h"
-#else
-#include "hci_transport_api.h"
-#endif
-#include "epping_test.h"
-#include "gmboxif.h"
-#include "ar3kconfig.h"
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-
- /* only build on newer kernels which have BT configured */
-#if defined(CONFIG_BT_MODULE) || defined(CONFIG_BT)
-#define CONFIG_BLUEZ_HCI_BRIDGE
-#endif
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-unsigned int ar3khcibaud = 0;
-unsigned int hciuartscale = 0;
-unsigned int hciuartstep = 0;
-
-module_param(ar3khcibaud, int, 0644);
-module_param(hciuartscale, int, 0644);
-module_param(hciuartstep, int, 0644);
-#else
-extern unsigned int ar3khcibaud;
-extern unsigned int hciuartscale;
-extern unsigned int hciuartstep;
-#endif /* EXPORT_HCI_BRIDGE_INTERFACE */
-
-struct ar6k_hci_bridge_info {
- void *pHCIDev; /* HCI bridge device */
- struct hci_transport_properties HCIProps; /* HCI bridge props */
- struct hci_dev *pBtStackHCIDev; /* BT Stack HCI dev */
- bool HciNormalMode; /* Actual HCI mode enabled (non-TEST)*/
- bool HciRegistered; /* HCI device registered with stack */
- struct htc_packet_queue HTCPacketStructHead;
- u8 *pHTCStructAlloc;
- spinlock_t BridgeLock;
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- struct hci_transport_misc_handles HCITransHdl;
-#else
- struct ar6_softc *ar;
-#endif /* EXPORT_HCI_BRIDGE_INTERFACE */
-};
-
-#define MAX_ACL_RECV_BUFS 16
-#define MAX_EVT_RECV_BUFS 8
-#define MAX_HCI_WRITE_QUEUE_DEPTH 32
-#define MAX_ACL_RECV_LENGTH 1200
-#define MAX_EVT_RECV_LENGTH 257
-#define TX_PACKET_RSV_OFFSET 32
-#define NUM_HTC_PACKET_STRUCTS ((MAX_ACL_RECV_BUFS + MAX_EVT_RECV_BUFS + MAX_HCI_WRITE_QUEUE_DEPTH) * 2)
-
-#define HCI_GET_OP_CODE(p) (((u16)((p)[1])) << 8) | ((u16)((p)[0]))
-
-extern unsigned int setupbtdev;
-struct ar3k_config_info ar3kconfig;
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-struct ar6k_hci_bridge_info *g_pHcidevInfo;
-#endif
-
-static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo);
-static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo);
-static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo);
-static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo,
- HCI_TRANSPORT_PACKET_TYPE Type,
- struct sk_buff *skb);
-static struct sk_buff *bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length);
-static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb);
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-int ar6000_setup_hci(void *ar);
-void ar6000_cleanup_hci(void *ar);
-int hci_test_send(void *ar, struct sk_buff *skb);
-#else
-int ar6000_setup_hci(struct ar6_softc *ar);
-void ar6000_cleanup_hci(struct ar6_softc *ar);
-/* HCI bridge testing */
-int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb);
-#endif /* EXPORT_HCI_BRIDGE_INTERFACE */
-
-#define LOCK_BRIDGE(dev) spin_lock_bh(&(dev)->BridgeLock)
-#define UNLOCK_BRIDGE(dev) spin_unlock_bh(&(dev)->BridgeLock)
-
-static inline void FreeBtOsBuf(struct ar6k_hci_bridge_info *pHcidevInfo, void *osbuf)
-{
- if (pHcidevInfo->HciNormalMode) {
- bt_free_buffer(pHcidevInfo, (struct sk_buff *)osbuf);
- } else {
- /* in test mode, these are just ordinary netbuf allocations */
- A_NETBUF_FREE(osbuf);
- }
-}
-
-static void FreeHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo, struct htc_packet *pPacket)
-{
- LOCK_BRIDGE(pHcidevInfo);
- HTC_PACKET_ENQUEUE(&pHcidevInfo->HTCPacketStructHead,pPacket);
- UNLOCK_BRIDGE(pHcidevInfo);
-}
-
-static struct htc_packet * AllocHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo)
-{
- struct htc_packet *pPacket = NULL;
- LOCK_BRIDGE(pHcidevInfo);
- pPacket = HTC_PACKET_DEQUEUE(&pHcidevInfo->HTCPacketStructHead);
- UNLOCK_BRIDGE(pHcidevInfo);
- return pPacket;
-}
-
-#define BLOCK_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1))
-
-static void RefillRecvBuffers(struct ar6k_hci_bridge_info *pHcidevInfo,
- HCI_TRANSPORT_PACKET_TYPE Type,
- int NumBuffers)
-{
- int length, i;
- void *osBuf = NULL;
- struct htc_packet_queue queue;
- struct htc_packet *pPacket;
-
- INIT_HTC_PACKET_QUEUE(&queue);
-
- if (Type == HCI_ACL_TYPE) {
- if (pHcidevInfo->HciNormalMode) {
- length = HCI_MAX_FRAME_SIZE;
- } else {
- length = MAX_ACL_RECV_LENGTH;
- }
- } else {
- length = MAX_EVT_RECV_LENGTH;
- }
-
- /* add on transport head and tail room */
- length += pHcidevInfo->HCIProps.HeadRoom + pHcidevInfo->HCIProps.TailRoom;
- /* round up to the required I/O padding */
- length = BLOCK_ROUND_UP_PWR2(length,pHcidevInfo->HCIProps.IOBlockPad);
-
- for (i = 0; i < NumBuffers; i++) {
-
- if (pHcidevInfo->HciNormalMode) {
- osBuf = bt_alloc_buffer(pHcidevInfo,length);
- } else {
- osBuf = A_NETBUF_ALLOC(length);
- }
-
- if (NULL == osBuf) {
- break;
- }
-
- pPacket = AllocHTCStruct(pHcidevInfo);
- if (NULL == pPacket) {
- FreeBtOsBuf(pHcidevInfo,osBuf);
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n"));
- break;
- }
-
- SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),length,Type);
- /* add to queue */
- HTC_PACKET_ENQUEUE(&queue,pPacket);
- }
-
- if (i > 0) {
- HCI_TransportAddReceivePkts(pHcidevInfo->pHCIDev, &queue);
- }
-}
-
-#define HOST_INTEREST_ITEM_ADDRESS(ar, item) \
- (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \
- (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0))
-static int ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE HCIHandle,
- struct hci_transport_properties *pProps,
- void *pContext)
-{
- struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
- int status;
- u32 address, hci_uart_pwr_mgmt_params;
-// struct ar3k_config_info ar3kconfig;
-
- pHcidevInfo->pHCIDev = HCIHandle;
-
- memcpy(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps));
-
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%lX, headroom:%d, tailroom:%d blockpad:%d) \n",
- (unsigned long)HCIHandle,
- pHcidevInfo->HCIProps.HeadRoom,
- pHcidevInfo->HCIProps.TailRoom,
- pHcidevInfo->HCIProps.IOBlockPad));
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)->hard_header_len);
-#else
- A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= pHcidevInfo->ar->arNetDev->hard_header_len);
-#endif
-
- /* provide buffers */
- RefillRecvBuffers(pHcidevInfo, HCI_ACL_TYPE, MAX_ACL_RECV_BUFS);
- RefillRecvBuffers(pHcidevInfo, HCI_EVENT_TYPE, MAX_EVT_RECV_BUFS);
-
- do {
- /* start transport */
- status = HCI_TransportStart(pHcidevInfo->pHCIDev);
-
- if (status) {
- break;
- }
-
- if (!pHcidevInfo->HciNormalMode) {
- /* in test mode, no need to go any further */
- break;
- }
-
- // The delay is required when AR6K is driving the BT reset line
- // where time is needed after the BT chip is out of reset (HCI_TransportStart)
- // and before the first HCI command is issued (AR3KConfigure)
- // FIXME
- // The delay should be configurable and be only applied when AR6K driving the BT
- // reset line. This could be done by some module parameter or based on some HW config
- // info. For now apply 100ms delay blindly
- A_MDELAY(100);
-
- A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig));
- ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev;
- ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps;
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- ar3kconfig.pHIFDevice = (struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice);
-#else
- ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice;
-#endif
- ar3kconfig.pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev;
-
- if (ar3khcibaud != 0) {
- /* user wants ar3k baud rate change */
- ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD;
- ar3kconfig.Flags |= AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY;
- ar3kconfig.AR3KBaudRate = ar3khcibaud;
- }
-
- if ((hciuartscale != 0) || (hciuartstep != 0)) {
- /* user wants to tune HCI bridge UART scale/step values */
- ar3kconfig.AR6KScale = (u16)hciuartscale;
- ar3kconfig.AR6KStep = (u16)hciuartstep;
- ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP;
- }
-
- /* Fetch the address of the hi_hci_uart_pwr_mgmt_params instance in the host interest area */
- address = TARG_VTOP(pHcidevInfo->ar->arTargetType,
- HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar, hi_hci_uart_pwr_mgmt_params));
- status = ar6000_ReadRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params);
- if (0 == status) {
- ar3kconfig.PwrMgmtEnabled = (hci_uart_pwr_mgmt_params & 0x1);
- ar3kconfig.IdleTimeout = (hci_uart_pwr_mgmt_params & 0xFFFF0000) >> 16;
- ar3kconfig.WakeupTimeout = (hci_uart_pwr_mgmt_params & 0xFF00) >> 8;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to read hci_uart_pwr_mgmt_params! \n"));
- }
- /* configure the AR3K device */
- memcpy(ar3kconfig.bdaddr,pHcidevInfo->ar->bdaddr,6);
- status = AR3KConfigure(&ar3kconfig);
- if (status) {
- break;
- }
-
- /* Make sure both AR6K and AR3K have power management enabled */
- if (ar3kconfig.PwrMgmtEnabled) {
- status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, true);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to enable TLPM for AR6K! \n"));
- }
- }
-
- status = bt_register_hci(pHcidevInfo);
-
- } while (false);
-
- return status;
-}
-
-static void ar6000_hci_transport_failure(void *pContext, int Status)
-{
- struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: transport failure! \n"));
-
- if (pHcidevInfo->HciNormalMode) {
- /* TODO .. */
- }
-}
-
-static void ar6000_hci_transport_removed(void *pContext)
-{
- struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: transport removed. \n"));
-
- A_ASSERT(pHcidevInfo->pHCIDev != NULL);
-
- HCI_TransportDetach(pHcidevInfo->pHCIDev);
- bt_cleanup_hci(pHcidevInfo);
- pHcidevInfo->pHCIDev = NULL;
-}
-
-static void ar6000_hci_send_complete(void *pContext, struct htc_packet *pPacket)
-{
- struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
- void *osbuf = pPacket->pPktContext;
- A_ASSERT(osbuf != NULL);
- A_ASSERT(pHcidevInfo != NULL);
-
- if (pPacket->Status) {
- if ((pPacket->Status != A_ECANCELED) && (pPacket->Status != A_NO_RESOURCE)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Send Packet Failed: %d \n",pPacket->Status));
- }
- }
-
- FreeHTCStruct(pHcidevInfo,pPacket);
- FreeBtOsBuf(pHcidevInfo,osbuf);
-
-}
-
-static void ar6000_hci_pkt_recv(void *pContext, struct htc_packet *pPacket)
-{
- struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
- struct sk_buff *skb;
-
- A_ASSERT(pHcidevInfo != NULL);
- skb = (struct sk_buff *)pPacket->pPktContext;
- A_ASSERT(skb != NULL);
-
- do {
-
- if (pPacket->Status) {
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV,
- ("HCI Bridge, packet received type : %d len:%d \n",
- HCI_GET_PACKET_TYPE(pPacket),pPacket->ActualLength));
-
- /* set the actual buffer position in the os buffer, HTC recv buffers posted to HCI are set
- * to fill the front of the buffer */
- A_NETBUF_PUT(skb,pPacket->ActualLength + pHcidevInfo->HCIProps.HeadRoom);
- A_NETBUF_PULL(skb,pHcidevInfo->HCIProps.HeadRoom);
-
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("<<< Recv HCI %s packet len:%d \n",
- (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) ? "EVENT" : "ACL",
- skb->len));
- AR_DEBUG_PRINTBUF(skb->data, skb->len,"BT HCI RECV Packet Dump");
- }
-
- if (pHcidevInfo->HciNormalMode) {
- /* indicate the packet */
- if (bt_indicate_recv(pHcidevInfo,HCI_GET_PACKET_TYPE(pPacket),skb)) {
- /* bt stack accepted the packet */
- skb = NULL;
- }
- break;
- }
-
- /* for testing, indicate packet to the network stack */
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- skb->dev = (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice);
- if ((((struct net_device *)pHcidevInfo->HCITransHdl.netDevice)->flags & IFF_UP) == IFF_UP) {
- skb->protocol = eth_type_trans(skb, (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice));
-#else
- skb->dev = pHcidevInfo->ar->arNetDev;
- if ((pHcidevInfo->ar->arNetDev->flags & IFF_UP) == IFF_UP) {
- skb->protocol = eth_type_trans(skb, pHcidevInfo->ar->arNetDev);
-#endif
- netif_rx(skb);
- skb = NULL;
- }
-
- } while (false);
-
- FreeHTCStruct(pHcidevInfo,pPacket);
-
- if (skb != NULL) {
- /* packet was not accepted, free it */
- FreeBtOsBuf(pHcidevInfo,skb);
- }
-
-}
-
-static void ar6000_hci_pkt_refill(void *pContext, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable)
-{
- struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
- int refillCount;
-
- if (Type == HCI_ACL_TYPE) {
- refillCount = MAX_ACL_RECV_BUFS - BuffersAvailable;
- } else {
- refillCount = MAX_EVT_RECV_BUFS - BuffersAvailable;
- }
-
- if (refillCount > 0) {
- RefillRecvBuffers(pHcidevInfo,Type,refillCount);
- }
-
-}
-
-static HCI_SEND_FULL_ACTION ar6000_hci_pkt_send_full(void *pContext, struct htc_packet *pPacket)
-{
- struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
- HCI_SEND_FULL_ACTION action = HCI_SEND_FULL_KEEP;
-
- if (!pHcidevInfo->HciNormalMode) {
- /* for epping testing, check packet tag, some epping packets are
- * special and cannot be dropped */
- if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_DATA_PKT_TAG) {
- action = HCI_SEND_FULL_DROP;
- }
- }
-
- return action;
-}
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-int ar6000_setup_hci(void *ar)
-#else
-int ar6000_setup_hci(struct ar6_softc *ar)
-#endif
-{
- struct hci_transport_config_info config;
- int status = 0;
- int i;
- struct htc_packet *pPacket;
- struct ar6k_hci_bridge_info *pHcidevInfo;
-
-
- do {
-
- pHcidevInfo = (struct ar6k_hci_bridge_info *)A_MALLOC(sizeof(struct ar6k_hci_bridge_info));
-
- if (NULL == pHcidevInfo) {
- status = A_NO_MEMORY;
- break;
- }
-
- A_MEMZERO(pHcidevInfo, sizeof(struct ar6k_hci_bridge_info));
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- g_pHcidevInfo = pHcidevInfo;
- pHcidevInfo->HCITransHdl = *(struct hci_transport_misc_handles *)ar;
-#else
- ar->hcidev_info = pHcidevInfo;
- pHcidevInfo->ar = ar;
-#endif
- spin_lock_init(&pHcidevInfo->BridgeLock);
- INIT_HTC_PACKET_QUEUE(&pHcidevInfo->HTCPacketStructHead);
-
- ar->exitCallback = AR3KConfigureExit;
-
- status = bt_setup_hci(pHcidevInfo);
- if (status) {
- break;
- }
-
- if (pHcidevInfo->HciNormalMode) {
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in normal mode... \n"));
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in test mode... \n"));
- }
-
- pHcidevInfo->pHTCStructAlloc = (u8 *)A_MALLOC((sizeof(struct htc_packet)) * NUM_HTC_PACKET_STRUCTS);
-
- if (NULL == pHcidevInfo->pHTCStructAlloc) {
- status = A_NO_MEMORY;
- break;
- }
-
- pPacket = (struct htc_packet *)pHcidevInfo->pHTCStructAlloc;
- for (i = 0; i < NUM_HTC_PACKET_STRUCTS; i++,pPacket++) {
- FreeHTCStruct(pHcidevInfo,pPacket);
- }
-
- A_MEMZERO(&config,sizeof(struct hci_transport_config_info));
- config.ACLRecvBufferWaterMark = MAX_ACL_RECV_BUFS / 2;
- config.EventRecvBufferWaterMark = MAX_EVT_RECV_BUFS / 2;
- config.MaxSendQueueDepth = MAX_HCI_WRITE_QUEUE_DEPTH;
- config.pContext = pHcidevInfo;
- config.TransportFailure = ar6000_hci_transport_failure;
- config.TransportReady = ar6000_hci_transport_ready;
- config.TransportRemoved = ar6000_hci_transport_removed;
- config.pHCISendComplete = ar6000_hci_send_complete;
- config.pHCIPktRecv = ar6000_hci_pkt_recv;
- config.pHCIPktRecvRefill = ar6000_hci_pkt_refill;
- config.pHCISendFull = ar6000_hci_pkt_send_full;
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- pHcidevInfo->pHCIDev = HCI_TransportAttach(pHcidevInfo->HCITransHdl.htcHandle, &config);
-#else
- pHcidevInfo->pHCIDev = HCI_TransportAttach(ar->arHtcTarget, &config);
-#endif
-
- if (NULL == pHcidevInfo->pHCIDev) {
- status = A_ERROR;
- }
-
- } while (false);
-
- if (status) {
- if (pHcidevInfo != NULL) {
- if (NULL == pHcidevInfo->pHCIDev) {
- /* GMBOX may not be present in older chips */
- /* just return success */
- status = 0;
- }
- }
- ar6000_cleanup_hci(ar);
- }
-
- return status;
-}
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-void ar6000_cleanup_hci(void *ar)
-#else
-void ar6000_cleanup_hci(struct ar6_softc *ar)
-#endif
-{
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo;
-#else
- struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info;
-#endif
-
- if (pHcidevInfo != NULL) {
- bt_cleanup_hci(pHcidevInfo);
-
- if (pHcidevInfo->pHCIDev != NULL) {
- HCI_TransportStop(pHcidevInfo->pHCIDev);
- HCI_TransportDetach(pHcidevInfo->pHCIDev);
- pHcidevInfo->pHCIDev = NULL;
- }
-
- if (pHcidevInfo->pHTCStructAlloc != NULL) {
- kfree(pHcidevInfo->pHTCStructAlloc);
- pHcidevInfo->pHTCStructAlloc = NULL;
- }
-
- kfree(pHcidevInfo);
-#ifndef EXPORT_HCI_BRIDGE_INTERFACE
- ar->hcidev_info = NULL;
-#endif
- }
-
-
-}
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-int hci_test_send(void *ar, struct sk_buff *skb)
-#else
-int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb)
-#endif
-{
- int status = 0;
- int length;
- EPPING_HEADER *pHeader;
- struct htc_packet *pPacket;
- HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG;
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo;
-#else
- struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info;
-#endif
-
- do {
-
- if (NULL == pHcidevInfo) {
- status = A_ERROR;
- break;
- }
-
- if (NULL == pHcidevInfo->pHCIDev) {
- status = A_ERROR;
- break;
- }
-
- if (pHcidevInfo->HciNormalMode) {
- /* this interface cannot run when normal WMI is running */
- status = A_ERROR;
- break;
- }
-
- pHeader = (EPPING_HEADER *)A_NETBUF_DATA(skb);
-
- if (!IS_EPPING_PACKET(pHeader)) {
- status = A_EINVAL;
- break;
- }
-
- if (IS_EPING_PACKET_NO_DROP(pHeader)) {
- htc_tag = AR6K_CONTROL_PKT_TAG;
- }
-
- length = sizeof(EPPING_HEADER) + pHeader->DataLength;
-
- pPacket = AllocHTCStruct(pHcidevInfo);
- if (NULL == pPacket) {
- status = A_NO_MEMORY;
- break;
- }
-
- SET_HTC_PACKET_INFO_TX(pPacket,
- skb,
- A_NETBUF_DATA(skb),
- length,
- HCI_ACL_TYPE, /* send every thing out as ACL */
- htc_tag);
-
- HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false);
- pPacket = NULL;
-
- } while (false);
-
- return status;
-}
-
-void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig)
-{
- struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info;
- struct ar3k_config_info *config = (struct ar3k_config_info *)ar3kconfig;
-
- config->pHCIDev = pHcidevInfo->pHCIDev;
- config->pHCIProps = &pHcidevInfo->HCIProps;
- config->pHIFDevice = ar->arHifDevice;
- config->pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev;
- config->Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD;
- config->AR3KBaudRate = 115200;
-}
-
-#ifdef CONFIG_BLUEZ_HCI_BRIDGE
-/*** BT Stack Entrypoints *******/
-
-/*
- * bt_open - open a handle to the device
-*/
-static int bt_open(struct hci_dev *hdev)
-{
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_open - enter - x\n"));
- set_bit(HCI_RUNNING, &hdev->flags);
- set_bit(HCI_UP, &hdev->flags);
- set_bit(HCI_INIT, &hdev->flags);
- return 0;
-}
-
-/*
- * bt_close - close handle to the device
-*/
-static int bt_close(struct hci_dev *hdev)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_close - enter\n"));
- clear_bit(HCI_RUNNING, &hdev->flags);
- return 0;
-}
-
-/*
- * bt_send_frame - send data frames
-*/
-static int bt_send_frame(struct sk_buff *skb)
-{
- struct hci_dev *hdev = (struct hci_dev *)skb->dev;
- HCI_TRANSPORT_PACKET_TYPE type;
- struct ar6k_hci_bridge_info *pHcidevInfo;
- struct htc_packet *pPacket;
- int status = 0;
- struct sk_buff *txSkb = NULL;
-
- if (!hdev) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HCI Bridge: bt_send_frame - no device\n"));
- return -ENODEV;
- }
-
- if (!test_bit(HCI_RUNNING, &hdev->flags)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_send_frame - not open\n"));
- return -EBUSY;
- }
-
- pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data;
- A_ASSERT(pHcidevInfo != NULL);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("+bt_send_frame type: %d \n",bt_cb(skb)->pkt_type));
- type = HCI_COMMAND_TYPE;
-
- switch (bt_cb(skb)->pkt_type) {
- case HCI_COMMAND_PKT:
- type = HCI_COMMAND_TYPE;
- hdev->stat.cmd_tx++;
- break;
-
- case HCI_ACLDATA_PKT:
- type = HCI_ACL_TYPE;
- hdev->stat.acl_tx++;
- break;
-
- case HCI_SCODATA_PKT:
- /* we don't support SCO over the bridge */
- kfree_skb(skb);
- return 0;
- default:
- A_ASSERT(false);
- kfree_skb(skb);
- return 0;
- }
-
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(">>> Send HCI %s packet len: %d\n",
- (type == HCI_COMMAND_TYPE) ? "COMMAND" : "ACL",
- skb->len));
- if (type == HCI_COMMAND_TYPE) {
- u16 opcode = HCI_GET_OP_CODE(skb->data);
- AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(" HCI Command: OGF:0x%X OCF:0x%X \r\n",
- opcode >> 10, opcode & 0x3FF));
- }
- AR_DEBUG_PRINTBUF(skb->data,skb->len,"BT HCI SEND Packet Dump");
- }
-
- do {
-
- txSkb = bt_skb_alloc(TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom +
- pHcidevInfo->HCIProps.TailRoom + skb->len,
- GFP_ATOMIC);
-
- if (txSkb == NULL) {
- status = A_NO_MEMORY;
- break;
- }
-
- bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type;
- txSkb->dev = (void *)pHcidevInfo->pBtStackHCIDev;
- skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom);
- memcpy(txSkb->data, skb->data, skb->len);
- skb_put(txSkb,skb->len);
-
- pPacket = AllocHTCStruct(pHcidevInfo);
- if (NULL == pPacket) {
- status = A_NO_MEMORY;
- break;
- }
-
- /* HCI packet length here doesn't include the 1-byte transport header which
- * will be handled by the HCI transport layer. Enough headroom has already
- * been reserved above for the transport header
- */
- SET_HTC_PACKET_INFO_TX(pPacket,
- txSkb,
- txSkb->data,
- txSkb->len,
- type,
- AR6K_CONTROL_PKT_TAG); /* HCI packets cannot be dropped */
-
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: bt_send_frame skb:0x%lX \n",(unsigned long)txSkb));
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: type:%d, Total Length:%d Bytes \n",
- type, txSkb->len));
-
- status = HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false);
- pPacket = NULL;
- txSkb = NULL;
-
- } while (false);
-
- if (txSkb != NULL) {
- kfree_skb(txSkb);
- }
-
- kfree_skb(skb);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("-bt_send_frame \n"));
- return 0;
-}
-
-/*
- * bt_ioctl - ioctl processing
-*/
-static int bt_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_ioctl - enter\n"));
- return -ENOIOCTLCMD;
-}
-
-/*
- * bt_flush - flush outstandingbpackets
-*/
-static int bt_flush(struct hci_dev *hdev)
-{
- struct ar6k_hci_bridge_info *pHcidevInfo;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_flush - enter\n"));
-
- pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data;
-
- /* TODO??? */
-
- return 0;
-}
-
-
-/*
- * bt_destruct -
-*/
-static void bt_destruct(struct hci_dev *hdev)
-{
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_destruct - enter\n"));
- /* nothing to do here */
-}
-
-static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
-{
- int status = 0;
- struct hci_dev *pHciDev = NULL;
- struct hif_device_os_device_info osDevInfo;
-
- if (!setupbtdev) {
- return 0;
- }
-
- do {
-
- A_MEMZERO(&osDevInfo,sizeof(osDevInfo));
- /* get the underlying OS device */
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
- status = ar6000_get_hif_dev((struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice),
- &osDevInfo);
-#else
- status = HIFConfigureDevice(pHcidevInfo->ar->arHifDevice,
- HIF_DEVICE_GET_OS_DEVICE,
- &osDevInfo,
- sizeof(osDevInfo));
-#endif
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to OS device info from HIF\n"));
- break;
- }
-
- /* allocate a BT HCI struct for this device */
- pHciDev = hci_alloc_dev();
- if (NULL == pHciDev) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge - failed to allocate bt struct \n"));
- status = A_NO_MEMORY;
- break;
- }
- /* save the device, we'll register this later */
- pHcidevInfo->pBtStackHCIDev = pHciDev;
- SET_HCIDEV_DEV(pHciDev,osDevInfo.pOSDevice);
- SET_HCI_BUS_TYPE(pHciDev, HCI_VIRTUAL, HCI_BREDR);
- pHciDev->driver_data = pHcidevInfo;
- pHciDev->open = bt_open;
- pHciDev->close = bt_close;
- pHciDev->send = bt_send_frame;
- pHciDev->ioctl = bt_ioctl;
- pHciDev->flush = bt_flush;
- pHciDev->destruct = bt_destruct;
- pHciDev->owner = THIS_MODULE;
- /* driver is running in normal BT mode */
- pHcidevInfo->HciNormalMode = true;
-
- } while (false);
-
- if (status) {
- bt_cleanup_hci(pHcidevInfo);
- }
-
- return status;
-}
-
-static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
-{
- int err;
-
- if (pHcidevInfo->HciRegistered) {
- pHcidevInfo->HciRegistered = false;
- clear_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags);
- clear_bit(HCI_UP, &pHcidevInfo->pBtStackHCIDev->flags);
- clear_bit(HCI_INIT, &pHcidevInfo->pBtStackHCIDev->flags);
- A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL);
- /* unregister */
- if ((err = hci_unregister_dev(pHcidevInfo->pBtStackHCIDev)) < 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to unregister with bluetooth %d\n",err));
- }
- }
-
- kfree(pHcidevInfo->pBtStackHCIDev);
- pHcidevInfo->pBtStackHCIDev = NULL;
-}
-
-static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
-{
- int err;
- int status = 0;
-
- do {
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: registering HCI... \n"));
- A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL);
- /* mark that we are registered */
- pHcidevInfo->HciRegistered = true;
- if ((err = hci_register_dev(pHcidevInfo->pBtStackHCIDev)) < 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to register with bluetooth %d\n",err));
- pHcidevInfo->HciRegistered = false;
- status = A_ERROR;
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: HCI registered \n"));
-
- } while (false);
-
- return status;
-}
-
-static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo,
- HCI_TRANSPORT_PACKET_TYPE Type,
- struct sk_buff *skb)
-{
- u8 btType;
- int len;
- bool success = false;
- BT_HCI_EVENT_HEADER *pEvent;
-
- do {
-
- if (!test_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HCI Bridge: bt_indicate_recv - not running\n"));
- break;
- }
-
- switch (Type) {
- case HCI_ACL_TYPE:
- btType = HCI_ACLDATA_PKT;
- break;
- case HCI_EVENT_TYPE:
- btType = HCI_EVENT_PKT;
- break;
- default:
- btType = 0;
- A_ASSERT(false);
- break;
- }
-
- if (0 == btType) {
- break;
- }
-
- /* set the final type */
- bt_cb(skb)->pkt_type = btType;
- /* set dev */
- skb->dev = (void *)pHcidevInfo->pBtStackHCIDev;
- len = skb->len;
-
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_RECV)) {
- if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
- pEvent = (BT_HCI_EVENT_HEADER *)skb->data;
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, ("BT HCI EventCode: %d, len:%d \n",
- pEvent->EventCode, pEvent->ParamLength));
- }
- }
-
- /* pass receive packet up the stack */
- if (hci_recv_frame(skb) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: hci_recv_frame failed \n"));
- break;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV,
- ("HCI Bridge: Indicated RCV of type:%d, Length:%d \n",btType,len));
- }
-
- success = true;
-
- } while (false);
-
- return success;
-}
-
-static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length)
-{
- struct sk_buff *skb;
- /* in normal HCI mode we need to alloc from the bt core APIs */
- skb = bt_skb_alloc(Length, GFP_ATOMIC);
- if (NULL == skb) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc bt sk_buff \n"));
- }
- return skb;
-}
-
-static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb)
-{
- kfree_skb(skb);
-}
-
-#else // { CONFIG_BLUEZ_HCI_BRIDGE
-
- /* stubs when we only want to test the HCI bridging Interface without the HT stack */
-static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
-{
- return 0;
-}
-static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
-{
-
-}
-static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
-{
- A_ASSERT(false);
- return A_ERROR;
-}
-
-static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo,
- HCI_TRANSPORT_PACKET_TYPE Type,
- struct sk_buff *skb)
-{
- A_ASSERT(false);
- return false;
-}
-
-static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length)
-{
- A_ASSERT(false);
- return NULL;
-}
-static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb)
-{
- A_ASSERT(false);
-}
-
-#endif // } CONFIG_BLUEZ_HCI_BRIDGE
-
-#else // { ATH_AR6K_ENABLE_GMBOX
-
- /* stubs when GMBOX support is not needed */
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-int ar6000_setup_hci(void *ar)
-#else
-int ar6000_setup_hci(struct ar6_softc *ar)
-#endif
-{
- return 0;
-}
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-void ar6000_cleanup_hci(void *ar)
-#else
-void ar6000_cleanup_hci(struct ar6_softc *ar)
-#endif
-{
- return;
-}
-
-#ifndef EXPORT_HCI_BRIDGE_INTERFACE
-void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig)
-{
- return;
-}
-#endif
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-int hci_test_send(void *ar, struct sk_buff *skb)
-#else
-int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb)
-#endif
-{
- return -EOPNOTSUPP;
-}
-
-#endif // } ATH_AR6K_ENABLE_GMBOX
-
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-static int __init
-hcibridge_init_module(void)
-{
- int status;
- struct hci_transport_callbacks hciTransCallbacks;
-
- hciTransCallbacks.setupTransport = ar6000_setup_hci;
- hciTransCallbacks.cleanupTransport = ar6000_cleanup_hci;
-
- status = ar6000_register_hci_transport(&hciTransCallbacks);
- if (status)
- return -ENODEV;
-
- return 0;
-}
-
-static void __exit
-hcibridge_cleanup_module(void)
-{
-}
-
-module_init(hcibridge_init_module);
-module_exit(hcibridge_cleanup_module);
-MODULE_LICENSE("Dual BSD/GPL");
-#endif
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
deleted file mode 100644
index 80cef77738fb..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
+++ /dev/null
@@ -1,776 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef _AR6000_H_
-#define _AR6000_H_
-
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/if_ether.h>
-#include <linux/etherdevice.h>
-#include <net/iw_handler.h>
-#include <linux/if_arp.h>
-#include <linux/ip.h>
-#include <linux/wireless.h>
-#include <net/cfg80211.h>
-#include <linux/module.h>
-#include <asm/io.h>
-
-#include <a_config.h>
-#include <athdefs.h>
-#include "a_osapi.h"
-#include "htc_api.h"
-#include "wmi.h"
-#include "a_drv.h"
-#include "bmi.h"
-#include <ieee80211.h>
-#include <ieee80211_ioctl.h>
-#include <wlan_api.h>
-#include <wmi_api.h>
-#include "pkt_log.h"
-#include "aggr_recv_api.h"
-#include <host_version.h>
-#include <linux/rtnetlink.h>
-#include <linux/moduleparam.h>
-#include "ar6000_api.h"
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-#include <testcmd.h>
-#endif
-#include <linux/firmware.h>
-
-#include "targaddrs.h"
-#include "dbglog_api.h"
-#include "ar6000_diag.h"
-#include "common_drv.h"
-#include "roaming.h"
-#include "hci_transport_api.h"
-#define ATH_MODULE_NAME driver
-#include "a_debug.h"
-#include "hw/apb_map.h"
-#include "hw/rtc_reg.h"
-#include "hw/mbox_reg.h"
-#include "gpio_reg.h"
-
-#define ATH_DEBUG_DBG_LOG ATH_DEBUG_MAKE_MODULE_MASK(0)
-#define ATH_DEBUG_WLAN_CONNECT ATH_DEBUG_MAKE_MODULE_MASK(1)
-#define ATH_DEBUG_WLAN_SCAN ATH_DEBUG_MAKE_MODULE_MASK(2)
-#define ATH_DEBUG_WLAN_TX ATH_DEBUG_MAKE_MODULE_MASK(3)
-#define ATH_DEBUG_WLAN_RX ATH_DEBUG_MAKE_MODULE_MASK(4)
-#define ATH_DEBUG_HTC_RAW ATH_DEBUG_MAKE_MODULE_MASK(5)
-#define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6)
-#define ATH_DEBUG_HCI_RECV ATH_DEBUG_MAKE_MODULE_MASK(7)
-#define ATH_DEBUG_HCI_SEND ATH_DEBUG_MAKE_MODULE_MASK(8)
-#define ATH_DEBUG_HCI_DUMP ATH_DEBUG_MAKE_MODULE_MASK(9)
-
-#ifndef __dev_put
-#define __dev_put(dev) dev_put(dev)
-#endif
-
-
-#define USER_SAVEDKEYS_STAT_INIT 0
-#define USER_SAVEDKEYS_STAT_RUN 1
-
-// TODO this needs to move into the AR_SOFTC struct
-struct USER_SAVEDKEYS {
- struct ieee80211req_key ucast_ik;
- struct ieee80211req_key bcast_ik;
- CRYPTO_TYPE keyType;
- bool keyOk;
-};
-
-#define DBG_INFO 0x00000001
-#define DBG_ERROR 0x00000002
-#define DBG_WARNING 0x00000004
-#define DBG_SDIO 0x00000008
-#define DBG_HIF 0x00000010
-#define DBG_HTC 0x00000020
-#define DBG_WMI 0x00000040
-#define DBG_WMI2 0x00000080
-#define DBG_DRIVER 0x00000100
-
-#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING)
-
-
-int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
-int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define MAX_AR6000 1
-#define AR6000_MAX_RX_BUFFERS 16
-#define AR6000_BUFFER_SIZE 1664
-#define AR6000_MAX_AMSDU_RX_BUFFERS 4
-#define AR6000_AMSDU_REFILL_THRESHOLD 3
-#define AR6000_AMSDU_BUFFER_SIZE (WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH + 128)
-#define AR6000_MAX_RX_MESSAGE_SIZE (max(WMI_MAX_NORMAL_RX_DATA_FRAME_LENGTH,WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH))
-
-#define AR6000_TX_TIMEOUT 10
-#define AR6000_ETH_ADDR_LEN 6
-#define AR6000_MAX_ENDPOINTS 4
-#define MAX_NODE_NUM 15
-/* MAX_HI_COOKIE_NUM are reserved for high priority traffic */
-#define MAX_DEF_COOKIE_NUM 180
-#define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */
-#define MAX_COOKIE_NUM (MAX_DEF_COOKIE_NUM + MAX_HI_COOKIE_NUM)
-
-/* MAX_DEFAULT_SEND_QUEUE_DEPTH is used to set the default queue depth for the
- * WMM send queues. If a queue exceeds this depth htc will query back to the
- * OS specific layer by calling EpSendFull(). This gives the OS layer the
- * opportunity to drop the packet if desired. Therefore changing
- * MAX_DEFAULT_SEND_QUEUE_DEPTH does not affect resource utilization but
- * does impact the threshold used to identify if a packet should be
- * dropped. */
-#define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC)
-
-#define AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT 1
-#define AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT 1
-#define A_DISCONNECT_TIMER_INTERVAL 10 * 1000
-#define A_DEFAULT_LISTEN_INTERVAL 100
-#define A_MAX_WOW_LISTEN_INTERVAL 1000
-
-enum {
- DRV_HB_CHALLENGE = 0,
- APP_HB_CHALLENGE
-};
-
-enum {
- WLAN_INIT_MODE_NONE = 0,
- WLAN_INIT_MODE_USR,
- WLAN_INIT_MODE_UDEV,
- WLAN_INIT_MODE_DRV
-};
-
-/* Suspend - configuration */
-enum {
- WLAN_SUSPEND_CUT_PWR = 0,
- WLAN_SUSPEND_DEEP_SLEEP,
- WLAN_SUSPEND_WOW,
- WLAN_SUSPEND_CUT_PWR_IF_BT_OFF
-};
-
-/* WiFi OFF - configuration */
-enum {
- WLAN_OFF_CUT_PWR = 0,
- WLAN_OFF_DEEP_SLEEP,
-};
-
-/* WLAN low power state */
-enum {
- WLAN_POWER_STATE_ON = 0,
- WLAN_POWER_STATE_CUT_PWR = 1,
- WLAN_POWER_STATE_DEEP_SLEEP,
- WLAN_POWER_STATE_WOW
-};
-
-/* WLAN WoW State */
-enum {
- WLAN_WOW_STATE_NONE = 0,
- WLAN_WOW_STATE_SUSPENDED,
- WLAN_WOW_STATE_SUSPENDING
-};
-
-
-typedef enum _AR6K_BIN_FILE {
- AR6K_OTP_FILE,
- AR6K_FIRMWARE_FILE,
- AR6K_PATCH_FILE,
- AR6K_BOARD_DATA_FILE,
-} AR6K_BIN_FILE;
-
-#ifdef SETUPHCI_ENABLED
-#define SETUPHCI_DEFAULT 1
-#else
-#define SETUPHCI_DEFAULT 0
-#endif /* SETUPHCI_ENABLED */
-
-#ifdef SETUPBTDEV_ENABLED
-#define SETUPBTDEV_DEFAULT 1
-#else
-#define SETUPBTDEV_DEFAULT 0
-#endif /* SETUPBTDEV_ENABLED */
-
-#ifdef ENABLEUARTPRINT_SET
-#define ENABLEUARTPRINT_DEFAULT 1
-#else
-#define ENABLEUARTPRINT_DEFAULT 0
-#endif /* ENABLEARTPRINT_SET */
-
-#ifdef ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER
-#define NOHIFSCATTERSUPPORT_DEFAULT 1
-#else /* ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER */
-#define NOHIFSCATTERSUPPORT_DEFAULT 0
-#endif /* ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER */
-
-
-#if defined(CONFIG_ATH6KL_ENABLE_COEXISTENCE)
-
-#ifdef CONFIG_AR600x_BT_QCOM
-#define ATH6KL_BT_DEV 1
-#elif defined(CONFIG_AR600x_BT_CSR)
-#define ATH6KL_BT_DEV 2
-#else
-#define ATH6KL_BT_DEV 3
-#endif
-
-#ifdef CONFIG_AR600x_DUAL_ANTENNA
-#define ATH6KL_BT_ANTENNA 2
-#else
-#define ATH6KL_BT_ANTENNA 1
-#endif
-
-#endif /* CONFIG_ATH6KL_ENABLE_COEXISTENCE */
-
-#ifdef AR600x_BT_AR3001
-#define AR3KHCIBAUD_DEFAULT 3000000
-#define HCIUARTSCALE_DEFAULT 1
-#define HCIUARTSTEP_DEFAULT 8937
-#else
-#define AR3KHCIBAUD_DEFAULT 0
-#define HCIUARTSCALE_DEFAULT 0
-#define HCIUARTSTEP_DEFAULT 0
-#endif /* AR600x_BT_AR3001 */
-
-#define WLAN_INIT_MODE_DEFAULT WLAN_INIT_MODE_DRV
-
-#define AR6K_PATCH_DOWNLOAD_ADDRESS(_param, _ver) do { \
- if ((_ver) == AR6003_REV1_VERSION) { \
- (_param) = AR6003_REV1_PATCH_DOWNLOAD_ADDRESS; \
- } else if ((_ver) == AR6003_REV2_VERSION) { \
- (_param) = AR6003_REV2_PATCH_DOWNLOAD_ADDRESS; \
- } else { \
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \
- A_ASSERT(0); \
- } \
-} while (0)
-
-#define AR6K_DATA_DOWNLOAD_ADDRESS(_param, _ver) do { \
- if ((_ver) == AR6003_REV1_VERSION) { \
- (_param) = AR6003_REV1_DATA_DOWNLOAD_ADDRESS; \
- } else if ((_ver) == AR6003_REV2_VERSION) { \
- (_param) = AR6003_REV2_DATA_DOWNLOAD_ADDRESS; \
- } else { \
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \
- A_ASSERT(0); \
- } \
-} while (0)
-
-#define AR6K_DATASET_PATCH_ADDRESS(_param, _ver) do { \
- if ((_ver) == AR6003_REV2_VERSION) { \
- (_param) = AR6003_REV2_DATASET_PATCH_ADDRESS; \
- } else if ((_ver) == AR6003_REV3_VERSION) { \
- (_param) = AR6003_REV3_DATASET_PATCH_ADDRESS; \
- } else { \
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \
- A_ASSERT(0); \
- } \
-} while (0)
-
-#define AR6K_APP_LOAD_ADDRESS(_param, _ver) do { \
- if ((_ver) == AR6003_REV2_VERSION) { \
- (_param) = AR6003_REV2_APP_LOAD_ADDRESS; \
- } else if ((_ver) == AR6003_REV3_VERSION) { \
- (_param) = AR6003_REV3_APP_LOAD_ADDRESS; \
- } else { \
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \
- A_ASSERT(0); \
- } \
-} while (0)
-
-#define AR6K_APP_START_OVERRIDE_ADDRESS(_param, _ver) do { \
- if ((_ver) == AR6003_REV2_VERSION) { \
- (_param) = AR6003_REV2_APP_START_OVERRIDE; \
- } else if ((_ver) == AR6003_REV3_VERSION) { \
- (_param) = AR6003_REV3_APP_START_OVERRIDE; \
- } else { \
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \
- A_ASSERT(0); \
- } \
-} while (0)
-
-/* AR6003 1.0 definitions */
-#define AR6003_REV1_VERSION 0x300002ba
-#define AR6003_REV1_DATA_DOWNLOAD_ADDRESS AR6003_REV1_OTP_DATA_ADDRESS
-#define AR6003_REV1_PATCH_DOWNLOAD_ADDRESS 0x57ea6c
-#define AR6003_REV1_OTP_FILE "ath6k/AR6003/hw1.0/otp.bin.z77"
-#define AR6003_REV1_FIRMWARE_FILE "ath6k/AR6003/hw1.0/athwlan.bin.z77"
-#define AR6003_REV1_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw1.0/athtcmd_ram.bin"
-#define AR6003_REV1_ART_FIRMWARE_FILE "ath6k/AR6003/hw1.0/device.bin"
-#define AR6003_REV1_PATCH_FILE "ath6k/AR6003/hw1.0/data.patch.bin"
-#define AR6003_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw1.0/endpointping.bin"
-#ifdef CONFIG_AR600x_SD31_XXX
-#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.SD31.bin"
-#elif defined(CONFIG_AR600x_SD32_XXX)
-#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.SD32.bin"
-#elif defined(CONFIG_AR600x_WB31_XXX)
-#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.WB31.bin"
-#else
-#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.CUSTOM.bin"
-#endif /* Board Data File */
-
-/* AR6003 2.0 definitions */
-#define AR6003_REV2_VERSION 0x30000384
-#define AR6003_REV2_DATA_DOWNLOAD_ADDRESS AR6003_REV2_OTP_DATA_ADDRESS
-#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910
-#define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77"
-#define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77"
-#define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin"
-#define AR6003_REV2_ART_FIRMWARE_FILE "ath6k/AR6003/hw2.0/device.bin"
-#define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin"
-#define AR6003_REV2_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw2.0/endpointping.bin"
-#ifdef CONFIG_AR600x_SD31_XXX
-#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin"
-#elif defined(CONFIG_AR600x_SD32_XXX)
-#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD32.bin"
-#elif defined(CONFIG_AR600x_WB31_XXX)
-#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.WB31.bin"
-#else
-#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.CUSTOM.bin"
-#endif /* Board Data File */
-
-/* AR6003 3.0 definitions */
-#define AR6003_REV3_VERSION 0x30000582
-#define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin"
-#define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin"
-#define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin"
-#define AR6003_REV3_ART_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/device.bin"
-#define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin"
-#define AR6003_REV3_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/endpointping.bin"
-#ifdef CONFIG_AR600x_SD31_XXX
-#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
-#elif defined(CONFIG_AR600x_SD32_XXX)
-#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.SD32.bin"
-#elif defined(CONFIG_AR600x_WB31_XXX)
-#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.WB31.bin"
-#else
-#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.CUSTOM.bin"
-#endif /* Board Data File */
-
-
-/* Power states */
-enum {
- WLAN_PWR_CTRL_UP = 0,
- WLAN_PWR_CTRL_CUT_PWR,
- WLAN_PWR_CTRL_DEEP_SLEEP,
- WLAN_PWR_CTRL_WOW,
- WLAN_PWR_CTRL_DEEP_SLEEP_DISABLED
-};
-
-/* HTC RAW streams */
-typedef enum _HTC_RAW_STREAM_ID {
- HTC_RAW_STREAM_NOT_MAPPED = -1,
- HTC_RAW_STREAM_0 = 0,
- HTC_RAW_STREAM_1 = 1,
- HTC_RAW_STREAM_2 = 2,
- HTC_RAW_STREAM_3 = 3,
- HTC_RAW_STREAM_NUM_MAX
-} HTC_RAW_STREAM_ID;
-
-#define RAW_HTC_READ_BUFFERS_NUM 4
-#define RAW_HTC_WRITE_BUFFERS_NUM 4
-
-#define HTC_RAW_BUFFER_SIZE 1664
-
-typedef struct {
- int currPtr;
- int length;
- unsigned char data[HTC_RAW_BUFFER_SIZE];
- struct htc_packet HTCPacket;
-} raw_htc_buffer;
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-/*
- * add TCMD_MODE besides wmi and bypasswmi
- * in TCMD_MODE, only few TCMD releated wmi commands
- * counld be hanlder
- */
-enum {
- AR6000_WMI_MODE = 0,
- AR6000_BYPASS_MODE,
- AR6000_TCMD_MODE,
- AR6000_WLAN_MODE
-};
-#endif /* CONFIG_HOST_TCMD_SUPPORT */
-
-struct ar_wep_key {
- u8 arKeyIndex;
- u8 arKeyLen;
- u8 arKey[64];
-} ;
-
-struct ar_key {
- u8 key[WLAN_MAX_KEY_LEN];
- u8 key_len;
- u8 seq[IW_ENCODE_SEQ_MAX_SIZE];
- u8 seq_len;
- u32 cipher;
-};
-
-enum {
- SME_DISCONNECTED,
- SME_CONNECTING,
- SME_CONNECTED
-};
-
-struct ar_node_mapping {
- u8 macAddress[6];
- u8 epId;
- u8 txPending;
-};
-
-struct ar_cookie {
- unsigned long arc_bp[2]; /* Must be first field */
- struct htc_packet HtcPkt; /* HTC packet wrapper */
- struct ar_cookie *arc_list_next;
-};
-
-struct ar_hb_chlng_resp {
- A_TIMER timer;
- u32 frequency;
- u32 seqNum;
- bool outstanding;
- u8 missCnt;
- u8 missThres;
-};
-
-/* Per STA data, used in AP mode */
-/*TODO: All this should move to OS independent dir */
-
-#define STA_PWR_MGMT_MASK 0x1
-#define STA_PWR_MGMT_SHIFT 0x0
-#define STA_PWR_MGMT_AWAKE 0x0
-#define STA_PWR_MGMT_SLEEP 0x1
-
-#define STA_SET_PWR_SLEEP(sta) (sta->flags |= (STA_PWR_MGMT_MASK << STA_PWR_MGMT_SHIFT))
-#define STA_CLR_PWR_SLEEP(sta) (sta->flags &= ~(STA_PWR_MGMT_MASK << STA_PWR_MGMT_SHIFT))
-#define STA_IS_PWR_SLEEP(sta) ((sta->flags >> STA_PWR_MGMT_SHIFT) & STA_PWR_MGMT_MASK)
-
-#define STA_PS_POLLED_MASK 0x1
-#define STA_PS_POLLED_SHIFT 0x1
-#define STA_SET_PS_POLLED(sta) (sta->flags |= (STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT))
-#define STA_CLR_PS_POLLED(sta) (sta->flags &= ~(STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT))
-#define STA_IS_PS_POLLED(sta) (sta->flags & (STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT))
-
-typedef struct {
- u16 flags;
- u8 mac[ATH_MAC_LEN];
- u8 aid;
- u8 keymgmt;
- u8 ucipher;
- u8 auth;
- u8 wpa_ie[IEEE80211_MAX_IE];
- A_NETBUF_QUEUE_T psq; /* power save q */
- A_MUTEX_T psqLock;
-} sta_t;
-
-typedef struct ar6_raw_htc {
- HTC_ENDPOINT_ID arRaw2EpMapping[HTC_RAW_STREAM_NUM_MAX];
- HTC_RAW_STREAM_ID arEp2RawMapping[ENDPOINT_MAX];
- struct semaphore raw_htc_read_sem[HTC_RAW_STREAM_NUM_MAX];
- struct semaphore raw_htc_write_sem[HTC_RAW_STREAM_NUM_MAX];
- wait_queue_head_t raw_htc_read_queue[HTC_RAW_STREAM_NUM_MAX];
- wait_queue_head_t raw_htc_write_queue[HTC_RAW_STREAM_NUM_MAX];
- raw_htc_buffer raw_htc_read_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_READ_BUFFERS_NUM];
- raw_htc_buffer raw_htc_write_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_WRITE_BUFFERS_NUM];
- bool write_buffer_available[HTC_RAW_STREAM_NUM_MAX];
- bool read_buffer_available[HTC_RAW_STREAM_NUM_MAX];
-} AR_RAW_HTC_T;
-
-struct ar6_softc {
- struct net_device *arNetDev; /* net_device pointer */
- void *arWmi;
- int arTxPending[ENDPOINT_MAX];
- int arTotalTxDataPending;
- u8 arNumDataEndPts;
- bool arWmiEnabled;
- bool arWmiReady;
- bool arConnected;
- HTC_HANDLE arHtcTarget;
- void *arHifDevice;
- spinlock_t arLock;
- struct semaphore arSem;
- int arSsidLen;
- u_char arSsid[32];
- u8 arNextMode;
- u8 arNetworkType;
- u8 arDot11AuthMode;
- u8 arAuthMode;
- u8 arPairwiseCrypto;
- u8 arPairwiseCryptoLen;
- u8 arGroupCrypto;
- u8 arGroupCryptoLen;
- u8 arDefTxKeyIndex;
- struct ar_wep_key arWepKeyList[WMI_MAX_KEY_INDEX + 1];
- u8 arBssid[6];
- u8 arReqBssid[6];
- u16 arChannelHint;
- u16 arBssChannel;
- u16 arListenIntervalB;
- u16 arListenIntervalT;
- struct ar6000_version arVersion;
- u32 arTargetType;
- s8 arRssi;
- u8 arTxPwr;
- bool arTxPwrSet;
- s32 arBitRate;
- struct net_device_stats arNetStats;
- struct iw_statistics arIwStats;
- s8 arNumChannels;
- u16 arChannelList[32];
- u32 arRegCode;
- bool statsUpdatePending;
- TARGET_STATS arTargetStats;
- s8 arMaxRetries;
- u8 arPhyCapability;
-#ifdef CONFIG_HOST_TCMD_SUPPORT
- u32 arTargetMode;
- void *tcmd_rx_report;
- int tcmd_rx_report_len;
-#endif
- AR6000_WLAN_STATE arWlanState;
- struct ar_node_mapping arNodeMap[MAX_NODE_NUM];
- u8 arIbssPsEnable;
- u8 arNodeNum;
- u8 arNexEpId;
- struct ar_cookie *arCookieList;
- u32 arCookieCount;
- u32 arRateMask;
- u8 arSkipScan;
- u16 arBeaconInterval;
- bool arConnectPending;
- bool arWmmEnabled;
- struct ar_hb_chlng_resp arHBChallengeResp;
- u8 arKeepaliveConfigured;
- u32 arMgmtFilter;
- HTC_ENDPOINT_ID arAc2EpMapping[WMM_NUM_AC];
- bool arAcStreamActive[WMM_NUM_AC];
- u8 arAcStreamPriMap[WMM_NUM_AC];
- u8 arHiAcStreamActivePri;
- u8 arEp2AcMapping[ENDPOINT_MAX];
- HTC_ENDPOINT_ID arControlEp;
-#ifdef HTC_RAW_INTERFACE
- AR_RAW_HTC_T *arRawHtc;
-#endif
- bool arNetQueueStopped;
- bool arRawIfInit;
- int arDeviceIndex;
- struct common_credit_state_info arCreditStateInfo;
- bool arWMIControlEpFull;
- bool dbgLogFetchInProgress;
- u8 log_buffer[DBGLOG_HOST_LOG_BUFFER_SIZE];
- u32 log_cnt;
- u32 dbglog_init_done;
- u32 arConnectCtrlFlags;
- s32 user_savedkeys_stat;
- u32 user_key_ctrl;
- struct USER_SAVEDKEYS user_saved_keys;
- USER_RSSI_THOLD rssi_map[12];
- u8 arUserBssFilter;
- u16 ap_profile_flag; /* AP mode */
- WMI_AP_ACL g_acl; /* AP mode */
- sta_t sta_list[AP_MAX_NUM_STA]; /* AP mode */
- u8 sta_list_index; /* AP mode */
- struct ieee80211req_key ap_mode_bkey; /* AP mode */
- A_NETBUF_QUEUE_T mcastpsq; /* power save q for Mcast frames */
- A_MUTEX_T mcastpsqLock;
- bool DTIMExpired; /* flag to indicate DTIM expired */
- u8 intra_bss; /* enable/disable intra bss data forward */
- void *aggr_cntxt;
-#ifndef EXPORT_HCI_BRIDGE_INTERFACE
- void *hcidev_info;
-#endif
- WMI_AP_MODE_STAT arAPStats;
- u8 ap_hidden_ssid;
- u8 ap_country_code[3];
- u8 ap_wmode;
- u8 ap_dtim_period;
- u16 ap_beacon_interval;
- u16 arRTS;
- u16 arACS; /* AP mode - Auto Channel Selection */
- struct htc_packet_queue amsdu_rx_buffer_queue;
- bool bIsDestroyProgress; /* flag to indicate ar6k destroy is in progress */
- A_TIMER disconnect_timer;
- u8 rxMetaVersion;
-#ifdef WAPI_ENABLE
- u8 arWapiEnable;
-#endif
- WMI_BTCOEX_CONFIG_EVENT arBtcoexConfig;
- WMI_BTCOEX_STATS_EVENT arBtcoexStats;
- s32 (*exitCallback)(void *config); /* generic callback at AR6K exit */
- struct hif_device_os_device_info osDevInfo;
- struct wireless_dev *wdev;
- struct cfg80211_scan_request *scan_request;
- struct ar_key keys[WMI_MAX_KEY_INDEX + 1];
- u32 smeState;
- u16 arWlanPowerState;
- bool arWlanOff;
-#ifdef CONFIG_PM
- u16 arWowState;
- bool arBTOff;
- bool arBTSharing;
- u16 arSuspendConfig;
- u16 arWlanOffConfig;
- u16 arWow2Config;
-#endif
- u8 scan_triggered;
- WMI_SCAN_PARAMS_CMD scParams;
-#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4
- u8 mcast_filters[MAC_MAX_FILTERS_PER_LIST][AR_MCAST_FILTER_MAC_ADDR_SIZE];
- u8 bdaddr[6];
- bool scanSpecificSsid;
-#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
- void *arApDev;
-#endif
- u8 arAutoAuthStage;
-
- u8 *fw_otp;
- size_t fw_otp_len;
- u8 *fw;
- size_t fw_len;
- u8 *fw_patch;
- size_t fw_patch_len;
- u8 *fw_data;
- size_t fw_data_len;
-};
-
-#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
-struct ar_virtual_interface {
- struct net_device *arNetDev; /* net_device pointer */
- struct ar6_softc *arDev; /* ar device pointer */
- struct net_device *arStaNetDev; /* net_device pointer */
-};
-#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
-
-static inline void *ar6k_priv(struct net_device *dev)
-{
- return (wdev_priv(dev->ieee80211_ptr));
-}
-
-#define SET_HCI_BUS_TYPE(pHciDev, __bus, __type) do { \
- (pHciDev)->bus = (__bus); \
- (pHciDev)->dev_type = (__type); \
-} while(0)
-
-#define GET_INODE_FROM_FILEP(filp) \
- (filp)->f_path.dentry->d_inode
-
-#define arAc2EndpointID(ar,ac) (ar)->arAc2EpMapping[(ac)]
-#define arSetAc2EndpointIDMap(ar,ac,ep) \
-{ (ar)->arAc2EpMapping[(ac)] = (ep); \
- (ar)->arEp2AcMapping[(ep)] = (ac); }
-#define arEndpoint2Ac(ar,ep) (ar)->arEp2AcMapping[(ep)]
-
-#define arRawIfEnabled(ar) (ar)->arRawIfInit
-#define arRawStream2EndpointID(ar,raw) (ar)->arRawHtc->arRaw2EpMapping[(raw)]
-#define arSetRawStream2EndpointIDMap(ar,raw,ep) \
-{ (ar)->arRawHtc->arRaw2EpMapping[(raw)] = (ep); \
- (ar)->arRawHtc->arEp2RawMapping[(ep)] = (raw); }
-#define arEndpoint2RawStreamID(ar,ep) (ar)->arRawHtc->arEp2RawMapping[(ep)]
-
-struct ar_giwscan_param {
- char *current_ev;
- char *end_buf;
- u32 bytes_needed;
- struct iw_request_info *info;
-};
-
-#define AR6000_STAT_INC(ar, stat) (ar->arNetStats.stat++)
-
-#define AR6000_SPIN_LOCK(lock, param) do { \
- if (irqs_disabled()) { \
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("IRQs disabled:AR6000_LOCK\n")); \
- } \
- spin_lock_bh(lock); \
-} while (0)
-
-#define AR6000_SPIN_UNLOCK(lock, param) do { \
- if (irqs_disabled()) { \
- AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("IRQs disabled: AR6000_UNLOCK\n")); \
- } \
- spin_unlock_bh(lock); \
-} while (0)
-
-void ar6000_init_profile_info(struct ar6_softc *ar);
-void ar6000_install_static_wep_keys(struct ar6_softc *ar);
-int ar6000_init(struct net_device *dev);
-int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar);
-void ar6000_TxDataCleanup(struct ar6_softc *ar);
-int ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev);
-void ar6000_restart_endpoint(struct net_device *dev);
-void ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs);
-
-#ifdef HTC_RAW_INTERFACE
-
-#ifndef __user
-#define __user
-#endif
-
-int ar6000_htc_raw_open(struct ar6_softc *ar);
-int ar6000_htc_raw_close(struct ar6_softc *ar);
-ssize_t ar6000_htc_raw_read(struct ar6_softc *ar,
- HTC_RAW_STREAM_ID StreamID,
- char __user *buffer, size_t count);
-ssize_t ar6000_htc_raw_write(struct ar6_softc *ar,
- HTC_RAW_STREAM_ID StreamID,
- char __user *buffer, size_t count);
-
-#endif /* HTC_RAW_INTERFACE */
-
-/* AP mode */
-/*TODO: These routines should be moved to a file that is common across OS */
-sta_t *
-ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr);
-
-sta_t *
-ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid);
-
-u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason);
-
-/* HCI support */
-
-#ifndef EXPORT_HCI_BRIDGE_INTERFACE
-int ar6000_setup_hci(struct ar6_softc *ar);
-void ar6000_cleanup_hci(struct ar6_softc *ar);
-void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig);
-
-/* HCI bridge testing */
-int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb);
-#endif
-
-ATH_DEBUG_DECLARE_EXTERN(htc);
-ATH_DEBUG_DECLARE_EXTERN(wmi);
-ATH_DEBUG_DECLARE_EXTERN(bmi);
-ATH_DEBUG_DECLARE_EXTERN(hif);
-ATH_DEBUG_DECLARE_EXTERN(wlan);
-ATH_DEBUG_DECLARE_EXTERN(misc);
-
-extern u8 bcast_mac[];
-extern u8 null_mac[];
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _AR6000_H_ */
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h b/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h
deleted file mode 100644
index 39e0873aff24..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-// The software source and binaries included in this development package are
-// licensed, not sold. You, or your company, received the package under one
-// or more license agreements. The rights granted to you are specifically
-// listed in these license agreement(s). All other rights remain with Atheros
-// Communications, Inc., its subsidiaries, or the respective owner including
-// those listed on the included copyright notices. Distribution of any
-// portion of this package must be in strict compliance with the license
-// agreement(s) terms.
-// </copyright>
-//
-// <summary>
-// PAL driver for AR6003
-// </summary>
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _AR6K_PAL_H_
-#define _AR6K_PAL_H_
-#define HCI_GET_OP_CODE(p) (((u16)((p)[1])) << 8) | ((u16)((p)[0]))
-
-/* transmit packet reserve offset */
-#define TX_PACKET_RSV_OFFSET 32
-/* pal specific config structure */
-typedef bool (*ar6k_pal_recv_pkt_t)(void *pHciPalInfo, void *skb);
-typedef struct ar6k_pal_config_s
-{
- ar6k_pal_recv_pkt_t fpar6k_pal_recv_pkt;
-}ar6k_pal_config_t;
-
-void register_pal_cb(ar6k_pal_config_t *palConfig_p);
-#endif /* _AR6K_PAL_H_ */
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h b/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h
deleted file mode 100644
index 184dbdb50495..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h
+++ /dev/null
@@ -1,190 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef _AR6XAPI_LINUX_H
-#define _AR6XAPI_LINUX_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ar6_softc;
-
-void ar6000_ready_event(void *devt, u8 *datap, u8 phyCap,
- u32 sw_ver, u32 abi_ver);
-int ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid);
-void ar6000_connect_event(struct ar6_softc *ar, u16 channel,
- u8 *bssid, u16 listenInterval,
- u16 beaconInterval, NETWORK_TYPE networkType,
- u8 beaconIeLen, u8 assocReqLen,
- u8 assocRespLen,u8 *assocInfo);
-void ar6000_disconnect_event(struct ar6_softc *ar, u8 reason,
- u8 *bssid, u8 assocRespLen,
- u8 *assocInfo, u16 protocolReasonStatus);
-void ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid,
- bool ismcast);
-void ar6000_bitrate_rx(void *devt, s32 rateKbps);
-void ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList);
-void ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode);
-void ar6000_txPwr_rx(void *devt, u8 txPwr);
-void ar6000_keepalive_rx(void *devt, u8 configured);
-void ar6000_neighborReport_event(struct ar6_softc *ar, int numAps,
- WMI_NEIGHBOR_INFO *info);
-void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num);
-void ar6000_scanComplete_event(struct ar6_softc *ar, int status);
-void ar6000_targetStats_event(struct ar6_softc *ar, u8 *ptr, u32 len);
-void ar6000_rssiThreshold_event(struct ar6_softc *ar,
- WMI_RSSI_THRESHOLD_VAL newThreshold,
- s16 rssi);
-void ar6000_reportError_event(struct ar6_softc *, WMI_TARGET_ERROR_VAL errorVal);
-void ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cac_indication,
- u8 statusCode, u8 *tspecSuggestion);
-void ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel, u16 newChannel);
-void ar6000_hbChallengeResp_event(struct ar6_softc *, u32 cookie, u32 source);
-void
-ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl);
-
-void
-ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p);
-
-void
-ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters,
- WMI_GET_WOW_LIST_REPLY *wow_reply);
-
-void ar6000_pmkid_list_event(void *devt, u8 numPMKID,
- WMI_PMKID *pmkidList, u8 *bssidList);
-
-void ar6000_gpio_intr_rx(u32 intr_mask, u32 input_values);
-void ar6000_gpio_data_rx(u32 reg_id, u32 value);
-void ar6000_gpio_ack_rx(void);
-
-s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt);
-s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi);
-s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above);
-
-void ar6000_dbglog_init_done(struct ar6_softc *ar);
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-void ar6000_tcmd_rx_report_event(void *devt, u8 *results, int len);
-#endif
-
-void ar6000_tx_retry_err_event(void *devt);
-
-void ar6000_snrThresholdEvent_rx(void *devt,
- WMI_SNR_THRESHOLD_VAL newThreshold,
- u8 snr);
-
-void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, u8 lqVal);
-
-
-void ar6000_ratemask_rx(void *devt, u32 ratemask);
-
-int ar6000_get_driver_cfg(struct net_device *dev,
- u16 cfgParam,
- void *result);
-void ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *data, int len);
-
-void ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped,
- s8 *buffer, u32 length);
-
-int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar);
-
-void ar6000_peer_event(void *devt, u8 eventCode, u8 *bssid);
-
-void ar6000_indicate_tx_activity(void *devt, u8 trafficClass, bool Active);
-HTC_ENDPOINT_ID ar6000_ac2_endpoint_id ( void * devt, u8 ac);
-u8 ar6000_endpoint_id2_ac (void * devt, HTC_ENDPOINT_ID ep );
-
-void ar6000_btcoex_config_event(struct ar6_softc *ar, u8 *ptr, u32 len);
-
-void ar6000_btcoex_stats_event(struct ar6_softc *ar, u8 *ptr, u32 len) ;
-
-void ar6000_dset_open_req(void *devt,
- u32 id,
- u32 targ_handle,
- u32 targ_reply_fn,
- u32 targ_reply_arg);
-void ar6000_dset_close(void *devt, u32 access_cookie);
-void ar6000_dset_data_req(void *devt,
- u32 access_cookie,
- u32 offset,
- u32 length,
- u32 targ_buf,
- u32 targ_reply_fn,
- u32 targ_reply_arg);
-
-
-#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-void prof_count_rx(unsigned int addr, unsigned int count);
-#endif
-
-u32 ar6000_getnodeAge (void);
-
-u32 ar6000_getclkfreq (void);
-
-int ar6000_ap_mode_profile_commit(struct ar6_softc *ar);
-
-struct ieee80211req_wpaie;
-int
-ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie);
-
-int is_iwioctl_allowed(u8 mode, u16 cmd);
-
-int is_xioctl_allowed(u8 mode, int cmd);
-
-void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid);
-
-void ar6000_dtimexpiry_event(struct ar6_softc *ar);
-
-void ar6000_aggr_rcv_addba_req_evt(struct ar6_softc *ar, WMI_ADDBA_REQ_EVENT *cmd);
-void ar6000_aggr_rcv_addba_resp_evt(struct ar6_softc *ar, WMI_ADDBA_RESP_EVENT *cmd);
-void ar6000_aggr_rcv_delba_req_evt(struct ar6_softc *ar, WMI_DELBA_EVENT *cmd);
-void ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd);
-
-#ifdef WAPI_ENABLE
-int ap_set_wapi_key(struct ar6_softc *ar, void *ik);
-void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac);
-#endif
-
-int ar6000_connect_to_ap(struct ar6_softc *ar);
-int ar6000_disconnect(struct ar6_softc *ar);
-int ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool suspending);
-int ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state);
-int ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 state);
-
-#ifdef CONFIG_PM
-int ar6000_suspend_ev(void *context);
-int ar6000_resume_ev(void *context);
-int ar6000_power_change_ev(void *context, u32 config);
-void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent);
-#endif
-
-#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
-int ar6000_add_ap_interface(struct ar6_softc *ar, char *ifname);
-int ar6000_remove_ap_interface(struct ar6_softc *ar);
-#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h b/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h
deleted file mode 100644
index 3d5f01da543f..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h
+++ /dev/null
@@ -1,1217 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef _ATHDRV_LINUX_H
-#define _ATHDRV_LINUX_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*
- * There are two types of ioctl's here: Standard ioctls and
- * eXtended ioctls. All extended ioctls (XIOCTL) are multiplexed
- * off of the single ioctl command, AR6000_IOCTL_EXTENDED. The
- * arguments for every XIOCTL starts with a 32-bit command word
- * that is used to select which extended ioctl is in use. After
- * the command word are command-specific arguments.
- */
-
-/* Linux standard Wireless Extensions, private ioctl interfaces */
-#define IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0)
-#define IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+1)
-#define IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+2)
-#define IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+3)
-#define IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+4)
-#define IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+5)
-//#define IEEE80211_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+6)
-//#define IEEE80211_IOCTL_SETWMMPARAMS (SIOCIWFIRSTPRIV+7)
-//#define IEEE80211_IOCTL_GETWMMPARAMS (SIOCIWFIRSTPRIV+8)
-//#define IEEE80211_IOCTL_GETOPTIE (SIOCIWFIRSTPRIV+9)
-//#define IEEE80211_IOCTL_SETAUTHALG (SIOCIWFIRSTPRIV+10)
-#define IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+10)
-
-
-
-/* ====WMI Ioctls==== */
-/*
- *
- * Many ioctls simply provide WMI services to application code:
- * an application makes such an ioctl call with a set of arguments
- * that are packaged into the corresponding WMI message, and sent
- * to the Target.
- */
-
-#define AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+11)
-/*
- * arguments:
- * ar6000_version *revision
- */
-
-#define AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+12)
-/*
- * arguments:
- * WMI_POWER_MODE_CMD pwrModeCmd (see include/wmi.h)
- * uses: WMI_SET_POWER_MODE_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+13)
-/*
- * arguments:
- * WMI_SCAN_PARAMS_CMD scanParams (see include/wmi.h)
- * uses: WMI_SET_SCAN_PARAMS_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+14)
-/*
- * arguments:
- * UINT32 listenInterval
- * uses: WMI_SET_LISTEN_INT_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+15)
-/*
- * arguments:
- * WMI_BSS_FILTER filter (see include/wmi.h)
- * uses: WMI_SET_BSS_FILTER_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16)
-/*
- * arguments:
- * WMI_CHANNEL_PARAMS_CMD chParams
- * uses: WMI_SET_CHANNEL_PARAMS_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17)
-/*
- * arguments:
- * WMI_PROBED_SSID_CMD probedSsids (see include/wmi.h)
- * uses: WMI_SETPROBED_SSID_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18)
-/*
- * arguments:
- * WMI_POWER_PARAMS_CMD powerParams (see include/wmi.h)
- * uses: WMI_SET_POWER_PARAMS_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19)
-/*
- * arguments:
- * WMI_ADD_BAD_AP_CMD badAPs (see include/wmi.h)
- * uses: WMI_ADD_BAD_AP_CMDID
- */
-
-#define AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20)
-/*
- * arguments:
- * ar6000_queuereq queueRequest (see below)
- */
-
-#define AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21)
-/*
- * arguments:
- * WMI_CREATE_PSTREAM createPstreamCmd (see include/wmi.h)
- * uses: WMI_CREATE_PSTREAM_CMDID
- */
-
-#define AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22)
-/*
- * arguments:
- * WMI_DELETE_PSTREAM_CMD deletePstreamCmd (see include/wmi.h)
- * uses: WMI_DELETE_PSTREAM_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23)
-/*
- * arguments:
- * WMI_SNR_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h)
- * uses: WMI_SNR_THRESHOLD_PARAMS_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24)
-/*
- * arguments:
- * WMI_TARGET_ERROR_REPORT_BITMASK errorReportBitMask (see include/wmi.h)
- * uses: WMI_TARGET_ERROR_REPORT_BITMASK_CMDID
- */
-
-#define AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25)
-/*
- * arguments:
- * TARGET_STATS *targetStats (see below)
- * uses: WMI_GET_STATISTICS_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26)
-/*
- * arguments:
- * WMI_SET_ASSOC_INFO_CMD setAssocInfoCmd
- * uses: WMI_SET_ASSOC_INFO_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27)
-/*
- * arguments:
- * WMI_SET_ACCESS_PARAMS_CMD setAccessParams (see include/wmi.h)
- * uses: WMI_SET_ACCESS_PARAMS_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28)
-/*
- * arguments:
- * UINT32 beaconMissTime
- * uses: WMI_SET_BMISS_TIME_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29)
-/*
- * arguments:
- * WMI_DISC_TIMEOUT_CMD disconnectTimeoutCmd (see include/wmi.h)
- * uses: WMI_SET_DISC_TIMEOUT_CMDID
- */
-
-#define AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30)
-/*
- * arguments:
- * WMI_IBSS_PM_CAPS_CMD ibssPowerMgmtCapsCmd
- * uses: WMI_SET_IBSS_PM_CAPS_CMDID
- */
-
-/*
- * There is a very small space available for driver-private
- * wireless ioctls. In order to circumvent this limitation,
- * we multiplex a bunch of ioctls (XIOCTLs) on top of a
- * single AR6000_IOCTL_EXTENDED ioctl.
- */
-#define AR6000_IOCTL_EXTENDED (SIOCIWFIRSTPRIV+31)
-
-
-/* ====BMI Extended Ioctls==== */
-
-#define AR6000_XIOCTL_BMI_DONE 1
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_BMI_DONE)
- * uses: BMI_DONE
- */
-
-#define AR6000_XIOCTL_BMI_READ_MEMORY 2
-/*
- * arguments:
- * union {
- * struct {
- * UINT32 cmd (AR6000_XIOCTL_BMI_READ_MEMORY)
- * UINT32 address
- * UINT32 length
- * }
- * char results[length]
- * }
- * uses: BMI_READ_MEMORY
- */
-
-#define AR6000_XIOCTL_BMI_WRITE_MEMORY 3
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_MEMORY)
- * UINT32 address
- * UINT32 length
- * char data[length]
- * uses: BMI_WRITE_MEMORY
- */
-
-#define AR6000_XIOCTL_BMI_EXECUTE 4
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_BMI_EXECUTE)
- * UINT32 TargetAddress
- * UINT32 parameter
- * uses: BMI_EXECUTE
- */
-
-#define AR6000_XIOCTL_BMI_SET_APP_START 5
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_BMI_SET_APP_START)
- * UINT32 TargetAddress
- * uses: BMI_SET_APP_START
- */
-
-#define AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6
-/*
- * arguments:
- * union {
- * struct {
- * UINT32 cmd (AR6000_XIOCTL_BMI_READ_SOC_REGISTER)
- * UINT32 TargetAddress, 32-bit aligned
- * }
- * UINT32 result
- * }
- * uses: BMI_READ_SOC_REGISTER
- */
-
-#define AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7
-/*
- * arguments:
- * struct {
- * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER)
- * UINT32 TargetAddress, 32-bit aligned
- * UINT32 newValue
- * }
- * uses: BMI_WRITE_SOC_REGISTER
- */
-
-#define AR6000_XIOCTL_BMI_TEST 8
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_BMI_TEST)
- * UINT32 address
- * UINT32 length
- * UINT32 count
- */
-
-
-
-/* Historical Host-side DataSet support */
-#define AR6000_XIOCTL_UNUSED9 9
-#define AR6000_XIOCTL_UNUSED10 10
-#define AR6000_XIOCTL_UNUSED11 11
-
-/* ====Misc Extended Ioctls==== */
-
-#define AR6000_XIOCTL_FORCE_TARGET_RESET 12
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_FORCE_TARGET_RESET)
- */
-
-
-#ifdef HTC_RAW_INTERFACE
-/* HTC Raw Interface Ioctls */
-#define AR6000_XIOCTL_HTC_RAW_OPEN 13
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_OPEN)
- */
-
-#define AR6000_XIOCTL_HTC_RAW_CLOSE 14
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_CLOSE)
- */
-
-#define AR6000_XIOCTL_HTC_RAW_READ 15
-/*
- * arguments:
- * union {
- * struct {
- * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_READ)
- * UINT32 mailboxID
- * UINT32 length
- * }
- * results[length]
- * }
- */
-
-#define AR6000_XIOCTL_HTC_RAW_WRITE 16
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_WRITE)
- * UINT32 mailboxID
- * UINT32 length
- * char buffer[length]
- */
-#endif /* HTC_RAW_INTERFACE */
-
-#define AR6000_XIOCTL_CHECK_TARGET_READY 17
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_CHECK_TARGET_READY)
- */
-
-
-
-/* ====GPIO (General Purpose I/O) Extended Ioctls==== */
-
-#define AR6000_XIOCTL_GPIO_OUTPUT_SET 18
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_GPIO_OUTPUT_SET)
- * ar6000_gpio_output_set_cmd_s (see below)
- * uses: WMIX_GPIO_OUTPUT_SET_CMDID
- */
-
-#define AR6000_XIOCTL_GPIO_INPUT_GET 19
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_GPIO_INPUT_GET)
- * uses: WMIX_GPIO_INPUT_GET_CMDID
- */
-
-#define AR6000_XIOCTL_GPIO_REGISTER_SET 20
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_SET)
- * ar6000_gpio_register_cmd_s (see below)
- * uses: WMIX_GPIO_REGISTER_SET_CMDID
- */
-
-#define AR6000_XIOCTL_GPIO_REGISTER_GET 21
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_GET)
- * ar6000_gpio_register_cmd_s (see below)
- * uses: WMIX_GPIO_REGISTER_GET_CMDID
- */
-
-#define AR6000_XIOCTL_GPIO_INTR_ACK 22
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_ACK)
- * ar6000_cpio_intr_ack_cmd_s (see below)
- * uses: WMIX_GPIO_INTR_ACK_CMDID
- */
-
-#define AR6000_XIOCTL_GPIO_INTR_WAIT 23
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_WAIT)
- */
-
-
-
-/* ====more wireless commands==== */
-
-#define AR6000_XIOCTL_SET_ADHOC_BSSID 24
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BSSID)
- * WMI_SET_ADHOC_BSSID_CMD setAdHocBssidCmd (see include/wmi.h)
- */
-
-#define AR6000_XIOCTL_SET_OPT_MODE 25
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_SET_OPT_MODE)
- * WMI_SET_OPT_MODE_CMD setOptModeCmd (see include/wmi.h)
- * uses: WMI_SET_OPT_MODE_CMDID
- */
-
-#define AR6000_XIOCTL_OPT_SEND_FRAME 26
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_OPT_SEND_FRAME)
- * WMI_OPT_TX_FRAME_CMD optTxFrameCmd (see include/wmi.h)
- * uses: WMI_OPT_TX_FRAME_CMDID
- */
-
-#define AR6000_XIOCTL_SET_BEACON_INTVAL 27
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_SET_BEACON_INTVAL)
- * WMI_BEACON_INT_CMD beaconIntCmd (see include/wmi.h)
- * uses: WMI_SET_BEACON_INT_CMDID
- */
-
-
-#define IEEE80211_IOCTL_SETAUTHALG 28
-
-
-#define AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_SET_VOICE_PKT_SIZE)
- * WMI_SET_VOICE_PKT_SIZE_CMD setVoicePktSizeCmd (see include/wmi.h)
- * uses: WMI_SET_VOICE_PKT_SIZE_CMDID
- */
-
-
-#define AR6000_XIOCTL_SET_MAX_SP 30
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_SET_MAX_SP)
- * WMI_SET_MAX_SP_LEN_CMD maxSPLen(see include/wmi.h)
- * uses: WMI_SET_MAX_SP_LEN_CMDID
- */
-
-#define AR6000_XIOCTL_WMI_GET_ROAM_TBL 31
-
-#define AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32
-
-#define AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33
-
-
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS)
- * WMI_SET_POWERSAVE_TIMERS_CMD powerSaveTimers(see include/wmi.h)
- * WMI_SET_POWERSAVE_TIMERS_CMDID
- */
-
-#define AR6000_XIOCTRL_WMI_GET_POWER_MODE 34
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTRL_WMI_GET_POWER_MODE)
- */
-
-#define AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35
-typedef enum {
- WLAN_DISABLED,
- WLAN_ENABLED
-} AR6000_WLAN_STATE;
-/*
- * arguments:
- * enable/disable
- */
-
-#define AR6000_XIOCTL_WMI_GET_ROAM_DATA 36
-
-#define AR6000_XIOCTL_WMI_SETRETRYLIMITS 37
-/*
- * arguments:
- * WMI_SET_RETRY_LIMITS_CMD ibssSetRetryLimitsCmd
- * uses: WMI_SET_RETRY_LIMITS_CMDID
- */
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-/* ====extended commands for radio test ==== */
-
-#define AR6000_XIOCTL_TCMD_CONT_TX 38
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_TX)
- * WMI_TCMD_CONT_TX_CMD contTxCmd (see include/wmi.h)
- * uses: WMI_TCMD_CONT_TX_CMDID
- */
-
-#define AR6000_XIOCTL_TCMD_CONT_RX 39
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_RX)
- * WMI_TCMD_CONT_RX_CMD rxCmd (see include/wmi.h)
- * uses: WMI_TCMD_CONT_RX_CMDID
- */
-
-#define AR6000_XIOCTL_TCMD_PM 40
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_TCMD_PM)
- * WMI_TCMD_PM_CMD pmCmd (see include/wmi.h)
- * uses: WMI_TCMD_PM_CMDID
- */
-
-#endif /* CONFIG_HOST_TCMD_SUPPORT */
-
-#define AR6000_XIOCTL_WMI_STARTSCAN 41
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_WMI_STARTSCAN)
- * UINT8 scanType
- * UINT8 scanConnected
- * u32 forceFgScan
- * uses: WMI_START_SCAN_CMDID
- */
-
-#define AR6000_XIOCTL_WMI_SETFIXRATES 42
-
-#define AR6000_XIOCTL_WMI_GETFIXRATES 43
-
-
-#define AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44
-/*
- * arguments:
- * WMI_RSSI_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h)
- * uses: WMI_RSSI_THRESHOLD_PARAMS_CMDID
- */
-
-#define AR6000_XIOCTL_WMI_CLR_RSSISNR 45
-/*
- * arguments:
- * WMI_CLR_RSSISNR_CMD thresholdParams (see include/wmi.h)
- * uses: WMI_CLR_RSSISNR_CMDID
- */
-
-#define AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46
-/*
- * arguments:
- * WMI_LQ_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h)
- * uses: WMI_LQ_THRESHOLD_PARAMS_CMDID
- */
-
-#define AR6000_XIOCTL_WMI_SET_RTS 47
-/*
- * arguments:
- * WMI_SET_RTS_MODE_CMD (see include/wmi.h)
- * uses: WMI_SET_RTS_MODE_CMDID
- */
-
-#define AR6000_XIOCTL_WMI_SET_LPREAMBLE 48
-
-#define AR6000_XIOCTL_WMI_SET_AUTHMODE 49
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_WMI_SET_AUTHMODE)
- * UINT8 mode
- * uses: WMI_SET_RECONNECT_AUTH_MODE_CMDID
- */
-
-#define AR6000_XIOCTL_WMI_SET_REASSOCMODE 50
-
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_WMI_SET_WMM)
- * UINT8 mode
- * uses: WMI_SET_WMM_CMDID
- */
-#define AR6000_XIOCTL_WMI_SET_WMM 51
-
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS)
- * UINT32 frequency
- * UINT8 threshold
- */
-#define AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52
-
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP)
- * UINT32 cookie
- */
-#define AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53
-
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_WMI_GET_RD)
- * UINT32 regDomain
- */
-#define AR6000_XIOCTL_WMI_GET_RD 54
-
-#define AR6000_XIOCTL_DIAG_READ 55
-
-#define AR6000_XIOCTL_DIAG_WRITE 56
-
-/*
- * arguments cmd (AR6000_XIOCTL_SET_TXOP)
- * WMI_TXOP_CFG txopEnable
- */
-#define AR6000_XIOCTL_WMI_SET_TXOP 57
-
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_USER_SETKEYS)
- * UINT32 keyOpCtrl
- * uses struct ar6000_user_setkeys_info
- */
-#define AR6000_XIOCTL_USER_SETKEYS 58
-
-#define AR6000_XIOCTL_WMI_SET_KEEPALIVE 59
-/*
- * arguments:
- * UINT8 cmd (AR6000_XIOCTL_WMI_SET_KEEPALIVE)
- * UINT8 keepaliveInterval
- * uses: WMI_SET_KEEPALIVE_CMDID
- */
-
-#define AR6000_XIOCTL_WMI_GET_KEEPALIVE 60
-/*
- * arguments:
- * UINT8 cmd (AR6000_XIOCTL_WMI_GET_KEEPALIVE)
- * UINT8 keepaliveInterval
- * u32 configured
- * uses: WMI_GET_KEEPALIVE_CMDID
- */
-
-/* ====ROM Patching Extended Ioctls==== */
-
-#define AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61
-/*
- * arguments:
- * union {
- * struct {
- * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_INSTALL)
- * UINT32 ROM Address
- * UINT32 RAM Address
- * UINT32 number of bytes
- * UINT32 activate? (0 or 1)
- * }
- * u32 resulting rompatch ID
- * }
- * uses: BMI_ROMPATCH_INSTALL
- */
-
-#define AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62
-/*
- * arguments:
- * struct {
- * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL)
- * UINT32 rompatch ID
- * }
- * uses: BMI_ROMPATCH_UNINSTALL
- */
-
-#define AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63
-/*
- * arguments:
- * struct {
- * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE)
- * UINT32 rompatch count
- * UINT32 rompatch IDs[rompatch count]
- * }
- * uses: BMI_ROMPATCH_ACTIVATE
- */
-
-#define AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64
-/*
- * arguments:
- * struct {
- * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE)
- * UINT32 rompatch count
- * UINT32 rompatch IDs[rompatch count]
- * }
- * uses: BMI_ROMPATCH_DEACTIVATE
- */
-
-#define AR6000_XIOCTL_WMI_SET_APPIE 65
-/*
- * arguments:
- * struct {
- * UINT32 cmd (AR6000_XIOCTL_WMI_SET_APPIE)
- * UINT32 app_frmtype;
- * UINT32 app_buflen;
- * UINT8 app_buf[];
- * }
- */
-#define AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66
-/*
- * arguments:
- * u32 filter_type;
- */
-
-#define AR6000_XIOCTL_DBGLOG_CFG_MODULE 67
-
-#define AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68
-
-#define AR6000_XIOCTL_WMI_SET_WSC_STATUS 70
-/*
- * arguments:
- * u32 wsc_status;
- * (WSC_REG_INACTIVE or WSC_REG_ACTIVE)
- */
-
-/*
- * arguments:
- * struct {
- * u8 streamType;
- * u8 status;
- * }
- * uses: WMI_SET_BT_STATUS_CMDID
- */
-#define AR6000_XIOCTL_WMI_SET_BT_STATUS 71
-
-/*
- * arguments:
- * struct {
- * u8 paramType;
- * union {
- * u8 noSCOPkts;
- * BT_PARAMS_A2DP a2dpParams;
- * BT_COEX_REGS regs;
- * };
- * }
- * uses: WMI_SET_BT_PARAM_CMDID
- */
-#define AR6000_XIOCTL_WMI_SET_BT_PARAMS 72
-
-#define AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE 73
-#define AR6000_XIOCTL_WMI_SET_WOW_MODE 74
-#define AR6000_XIOCTL_WMI_GET_WOW_LIST 75
-#define AR6000_XIOCTL_WMI_ADD_WOW_PATTERN 76
-#define AR6000_XIOCTL_WMI_DEL_WOW_PATTERN 77
-
-
-
-#define AR6000_XIOCTL_TARGET_INFO 78
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_TARGET_INFO)
- * u32 TargetVersion (returned)
- * u32 TargetType (returned)
- * (See also bmi_msg.h target_ver and target_type)
- */
-
-#define AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79
-/*
- * arguments:
- * none
- */
-
-#define AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80
-/*
- * This ioctl is used to emulate traffic activity
- * timeouts. Activity/inactivity will trigger the driver
- * to re-balance credits.
- *
- * arguments:
- * ar6000_traffic_activity_change
- */
-
-#define AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81
-/*
- * This ioctl is used to set the connect control flags
- *
- * arguments:
- * u32 connectCtrlFlags
- */
-
-#define AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82
-/*
- * This IOCTL sets any Authentication,Key Management and Protection
- * related parameters. This is used along with the information set in
- * Connect Command.
- * Currently this enables Multiple PMKIDs to an AP.
- *
- * arguments:
- * struct {
- * u32 akmpInfo;
- * }
- * uses: WMI_SET_AKMP_PARAMS_CMD
- */
-
-#define AR6000_XIOCTL_WMI_GET_PMKID_LIST 83
-
-#define AR6000_XIOCTL_WMI_SET_PMKID_LIST 84
-/*
- * This IOCTL is used to set a list of PMKIDs. This list of
- * PMKIDs is used in the [Re]AssocReq Frame. This list is used
- * only if the MultiPMKID option is enabled via the
- * AR6000_XIOCTL_WMI_SET_AKMP_PARAMS IOCTL.
- *
- * arguments:
- * struct {
- * u32 numPMKID;
- * WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE];
- * }
- * uses: WMI_SET_PMKIDLIST_CMD
- */
-
-#define AR6000_XIOCTL_WMI_SET_PARAMS 85
-#define AR6000_XIOCTL_WMI_SET_MCAST_FILTER 86
-#define AR6000_XIOCTL_WMI_DEL_MCAST_FILTER 87
-
-
-/* Historical DSETPATCH support for INI patches */
-#define AR6000_XIOCTL_UNUSED90 90
-
-
-/* Support LZ-compressed firmware download */
-#define AR6000_XIOCTL_BMI_LZ_STREAM_START 91
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_BMI_LZ_STREAM_START)
- * UINT32 address
- * uses: BMI_LZ_STREAM_START
- */
-
-#define AR6000_XIOCTL_BMI_LZ_DATA 92
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_BMI_LZ_DATA)
- * UINT32 length
- * char data[length]
- * uses: BMI_LZ_DATA
- */
-
-#define AR6000_XIOCTL_PROF_CFG 93
-/*
- * arguments:
- * u32 period
- * u32 nbins
- */
-
-#define AR6000_XIOCTL_PROF_ADDR_SET 94
-/*
- * arguments:
- * u32 Target address
- */
-
-#define AR6000_XIOCTL_PROF_START 95
-
-#define AR6000_XIOCTL_PROF_STOP 96
-
-#define AR6000_XIOCTL_PROF_COUNT_GET 97
-
-#define AR6000_XIOCTL_WMI_ABORT_SCAN 98
-
-/*
- * AP mode
- */
-#define AR6000_XIOCTL_AP_GET_STA_LIST 99
-
-#define AR6000_XIOCTL_AP_HIDDEN_SSID 100
-
-#define AR6000_XIOCTL_AP_SET_NUM_STA 101
-
-#define AR6000_XIOCTL_AP_SET_ACL_MAC 102
-
-#define AR6000_XIOCTL_AP_GET_ACL_LIST 103
-
-#define AR6000_XIOCTL_AP_COMMIT_CONFIG 104
-
-#define IEEE80211_IOCTL_GETWPAIE 105
-
-#define AR6000_XIOCTL_AP_CONN_INACT_TIME 106
-
-#define AR6000_XIOCTL_AP_PROT_SCAN_TIME 107
-
-#define AR6000_XIOCTL_AP_SET_COUNTRY 108
-
-#define AR6000_XIOCTL_AP_SET_DTIM 109
-
-
-
-
-#define AR6000_XIOCTL_WMI_TARGET_EVENT_REPORT 110
-
-#define AR6000_XIOCTL_SET_IP 111
-
-#define AR6000_XIOCTL_AP_SET_ACL_POLICY 112
-
-#define AR6000_XIOCTL_AP_INTRA_BSS_COMM 113
-
-#define AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO 114
-
-#define AR6000_XIOCTL_MODULE_DEBUG_SET_MASK 115
-
-#define AR6000_XIOCTL_MODULE_DEBUG_GET_MASK 116
-
-#define AR6000_XIOCTL_DUMP_RCV_AGGR_STATS 117
-
-#define AR6000_XIOCTL_SET_HT_CAP 118
-
-#define AR6000_XIOCTL_SET_HT_OP 119
-
-#define AR6000_XIOCTL_AP_GET_STAT 120
-
-#define AR6000_XIOCTL_SET_TX_SELECT_RATES 121
-
-#define AR6000_XIOCTL_SETUP_AGGR 122
-
-#define AR6000_XIOCTL_ALLOW_AGGR 123
-
-#define AR6000_XIOCTL_AP_GET_HIDDEN_SSID 124
-
-#define AR6000_XIOCTL_AP_GET_COUNTRY 125
-
-#define AR6000_XIOCTL_AP_GET_WMODE 126
-
-#define AR6000_XIOCTL_AP_GET_DTIM 127
-
-#define AR6000_XIOCTL_AP_GET_BINTVL 128
-
-#define AR6000_XIOCTL_AP_GET_RTS 129
-
-#define AR6000_XIOCTL_DELE_AGGR 130
-
-#define AR6000_XIOCTL_FETCH_TARGET_REGS 131
-
-#define AR6000_XIOCTL_HCI_CMD 132
-
-#define AR6000_XIOCTL_ACL_DATA 133 /* used to be used for PAL */
-
-#define AR6000_XIOCTL_WLAN_CONN_PRECEDENCE 134
-
-#define AR6000_XIOCTL_AP_SET_11BG_RATESET 135
-
-/*
- * arguments:
- * WMI_AP_PS_CMD apPsCmd
- * uses: WMI_AP_PS_CMDID
- */
-
-#define AR6000_XIOCTL_WMI_SET_AP_PS 136
-
-#define AR6000_XIOCTL_WMI_MCAST_FILTER 137
-
-#define AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT 138
-
-#define AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV 139
-
-#define AR6000_XIOCTL_WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG 140
-
-#define AR6000_XIOCTL_WMI_SET_BTCOEX_SCO_CONFIG 141
-
-#define AR6000_XIOCTL_WMI_SET_BTCOEX_A2DP_CONFIG 142
-
-#define AR6000_XIOCTL_WMI_SET_BTCOEX_ACLCOEX_CONFIG 143
-
-#define AR6000_XIOCTL_WMI_SET_BTCOEX_DEBUG 144
-
-#define AR6000_XIOCTL_WMI_SET_BT_OPERATING_STATUS 145
-
-#define AR6000_XIOCTL_WMI_GET_BTCOEX_CONFIG 146
-
-#define AR6000_XIOCTL_WMI_GET_BTCOEX_STATS 147
-/*
- * arguments:
- * UINT32 cmd (AR6000_XIOCTL_WMI_SET_QOS_SUPP)
- * UINT8 mode
- * uses: WMI_SET_QOS_SUPP_CMDID
- */
-#define AR6000_XIOCTL_WMI_SET_QOS_SUPP 148
-
-#define AR6000_XIOCTL_GET_WLAN_SLEEP_STATE 149
-
-#define AR6000_XIOCTL_SET_BT_HW_POWER_STATE 150
-
-#define AR6000_XIOCTL_GET_BT_HW_POWER_STATE 151
-
-#define AR6000_XIOCTL_ADD_AP_INTERFACE 152
-
-#define AR6000_XIOCTL_REMOVE_AP_INTERFACE 153
-
-#define AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM 154
-
-#define AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES 161
-
-/* used by AR6000_IOCTL_WMI_GETREV */
-struct ar6000_version {
- u32 host_ver;
- u32 target_ver;
- u32 wlan_ver;
- u32 abi_ver;
-};
-
-/* used by AR6000_IOCTL_WMI_GET_QOS_QUEUE */
-struct ar6000_queuereq {
- u8 trafficClass;
- u16 activeTsids;
-};
-
-/* used by AR6000_IOCTL_WMI_GET_TARGET_STATS */
-typedef struct targetStats_t {
- u64 tx_packets;
- u64 tx_bytes;
- u64 tx_unicast_pkts;
- u64 tx_unicast_bytes;
- u64 tx_multicast_pkts;
- u64 tx_multicast_bytes;
- u64 tx_broadcast_pkts;
- u64 tx_broadcast_bytes;
- u64 tx_rts_success_cnt;
- u64 tx_packet_per_ac[4];
-
- u64 tx_errors;
- u64 tx_failed_cnt;
- u64 tx_retry_cnt;
- u64 tx_mult_retry_cnt;
- u64 tx_rts_fail_cnt;
-
- u64 rx_packets;
- u64 rx_bytes;
- u64 rx_unicast_pkts;
- u64 rx_unicast_bytes;
- u64 rx_multicast_pkts;
- u64 rx_multicast_bytes;
- u64 rx_broadcast_pkts;
- u64 rx_broadcast_bytes;
- u64 rx_fragment_pkt;
-
- u64 rx_errors;
- u64 rx_crcerr;
- u64 rx_key_cache_miss;
- u64 rx_decrypt_err;
- u64 rx_duplicate_frames;
-
- u64 tkip_local_mic_failure;
- u64 tkip_counter_measures_invoked;
- u64 tkip_replays;
- u64 tkip_format_errors;
- u64 ccmp_format_errors;
- u64 ccmp_replays;
-
- u64 power_save_failure_cnt;
-
- u64 cs_bmiss_cnt;
- u64 cs_lowRssi_cnt;
- u64 cs_connect_cnt;
- u64 cs_disconnect_cnt;
-
- s32 tx_unicast_rate;
- s32 rx_unicast_rate;
-
- u32 lq_val;
-
- u32 wow_num_pkts_dropped;
- u16 wow_num_events_discarded;
-
- s16 noise_floor_calibation;
- s16 cs_rssi;
- s16 cs_aveBeacon_rssi;
- u8 cs_aveBeacon_snr;
- u8 cs_lastRoam_msec;
- u8 cs_snr;
-
- u8 wow_num_host_pkt_wakeups;
- u8 wow_num_host_event_wakeups;
-
- u32 arp_received;
- u32 arp_matched;
- u32 arp_replied;
-}TARGET_STATS;
-
-typedef struct targetStats_cmd_t {
- TARGET_STATS targetStats;
- int clearStats;
-} TARGET_STATS_CMD;
-
-/* used by AR6000_XIOCTL_USER_SETKEYS */
-
-/*
- * Setting this bit to 1 doesnot initialize the RSC on the firmware
- */
-#define AR6000_XIOCTL_USER_SETKEYS_RSC_CTRL 1
-#define AR6000_USER_SETKEYS_RSC_UNCHANGED 0x00000002
-
-struct ar6000_user_setkeys_info {
- u32 keyOpCtrl; /* Bit Map of Key Mgmt Ctrl Flags */
-}; /* XXX: unused !? */
-
-/* used by AR6000_XIOCTL_GPIO_OUTPUT_SET */
-struct ar6000_gpio_output_set_cmd_s {
- u32 set_mask;
- u32 clear_mask;
- u32 enable_mask;
- u32 disable_mask;
-};
-
-/*
- * used by AR6000_XIOCTL_GPIO_REGISTER_GET and AR6000_XIOCTL_GPIO_REGISTER_SET
- */
-struct ar6000_gpio_register_cmd_s {
- u32 gpioreg_id;
- u32 value;
-};
-
-/* used by AR6000_XIOCTL_GPIO_INTR_ACK */
-struct ar6000_gpio_intr_ack_cmd_s {
- u32 ack_mask;
-};
-
-/* used by AR6000_XIOCTL_GPIO_INTR_WAIT */
-struct ar6000_gpio_intr_wait_cmd_s {
- u32 intr_mask;
- u32 input_values;
-};
-
-/* used by the AR6000_XIOCTL_DBGLOG_CFG_MODULE */
-typedef struct ar6000_dbglog_module_config_s {
- u32 valid;
- u16 mmask;
- u16 tsr;
- u32 rep;
- u16 size;
-} DBGLOG_MODULE_CONFIG;
-
-typedef struct user_rssi_thold_t {
- s16 tag;
- s16 rssi;
-} USER_RSSI_THOLD;
-
-typedef struct user_rssi_params_t {
- u8 weight;
- u32 pollTime;
- USER_RSSI_THOLD tholds[12];
-} USER_RSSI_PARAMS;
-
-typedef struct ar6000_get_btcoex_config_cmd_t{
- u32 btProfileType;
- u32 linkId;
- }AR6000_GET_BTCOEX_CONFIG_CMD;
-
-typedef struct ar6000_btcoex_config_t {
- AR6000_GET_BTCOEX_CONFIG_CMD configCmd;
- u32 *configEvent;
-} AR6000_BTCOEX_CONFIG;
-
-typedef struct ar6000_btcoex_stats_t {
- u32 *statsEvent;
- }AR6000_BTCOEX_STATS;
-/*
- * Host driver may have some config parameters. Typically, these
- * config params are one time config parameters. These could
- * correspond to any of the underlying modules. Host driver exposes
- * an api for the underlying modules to get this config.
- */
-#define AR6000_DRIVER_CFG_BASE 0x8000
-
-/* Should driver perform wlan node caching? */
-#define AR6000_DRIVER_CFG_GET_WLANNODECACHING 0x8001
-/*Should we log raw WMI msgs */
-#define AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS 0x8002
-
-/* used by AR6000_XIOCTL_DIAG_READ & AR6000_XIOCTL_DIAG_WRITE */
-struct ar6000_diag_window_cmd_s {
- unsigned int addr;
- unsigned int value;
-};
-
-
-struct ar6000_traffic_activity_change {
- u32 StreamID; /* stream ID to indicate activity change */
- u32 Active; /* active (1) or inactive (0) */
-};
-
-/* Used with AR6000_XIOCTL_PROF_COUNT_GET */
-struct prof_count_s {
- u32 addr; /* bin start address */
- u32 count; /* hit count */
-};
-
-
-/* used by AR6000_XIOCTL_MODULE_DEBUG_SET_MASK */
-/* AR6000_XIOCTL_MODULE_DEBUG_GET_MASK */
-/* AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO */
-struct drv_debug_module_s {
- char modulename[128]; /* name of module */
- u32 mask; /* new mask to set .. or .. current mask */
-};
-
-
-/* All HCI related rx events are sent up to the host app
- * via a wmi event id. It can contain ACL data or HCI event,
- * based on which it will be de-multiplexed.
- */
-typedef enum {
- PAL_HCI_EVENT = 0,
- PAL_HCI_RX_DATA,
-} WMI_PAL_EVENT_INFO;
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/drivers/staging/ath6kl/os/linux/include/cfg80211.h b/drivers/staging/ath6kl/os/linux/include/cfg80211.h
deleted file mode 100644
index d5253207b198..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/cfg80211.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef _AR6K_CFG80211_H_
-#define _AR6K_CFG80211_H_
-
-struct wireless_dev *ar6k_cfg80211_init(struct device *dev);
-void ar6k_cfg80211_deinit(struct ar6_softc *ar);
-
-void ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status);
-
-void ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel,
- u8 *bssid, u16 listenInterval,
- u16 beaconInterval,NETWORK_TYPE networkType,
- u8 beaconIeLen, u8 assocReqLen,
- u8 assocRespLen, u8 *assocInfo);
-
-void ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason,
- u8 *bssid, u8 assocRespLen,
- u8 *assocInfo, u16 protocolReasonStatus);
-
-void ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast);
-
-#ifdef CONFIG_NL80211_TESTMODE
-void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf,
- int buf_len);
-#else
-static inline void ar6000_testmode_rx_report_event(struct ar6_softc *ar,
- void *buf, int buf_len)
-{
-}
-#endif
-
-
-#endif /* _AR6K_CFG80211_H_ */
-
-
-
-
-
-
diff --git a/drivers/staging/ath6kl/os/linux/include/config_linux.h b/drivers/staging/ath6kl/os/linux/include/config_linux.h
deleted file mode 100644
index dbbe1a00b92c..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/config_linux.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef _CONFIG_LINUX_H_
-#define _CONFIG_LINUX_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Host side Test Command support
- */
-#define CONFIG_HOST_TCMD_SUPPORT
-
-#define USE_4BYTE_REGISTER_ACCESS
-
-/* Host-side support for Target-side profiling */
-#undef CONFIG_TARGET_PROFILE_SUPPORT
-
-/* IP/TCP checksum offload */
-/* Checksum offload is currently not supported for 64 bit platforms */
-#ifndef __LP64__
-#define CONFIG_CHECKSUM_OFFLOAD
-#endif /* __LP64__ */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/drivers/staging/ath6kl/os/linux/include/debug_linux.h b/drivers/staging/ath6kl/os/linux/include/debug_linux.h
deleted file mode 100644
index b8dba52badce..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/debug_linux.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef _DEBUG_LINUX_H_
-#define _DEBUG_LINUX_H_
-
- /* macro to remove parens */
-#define ATH_PRINTX_ARG(arg...) arg
-
-#ifdef DEBUG
- /* NOTE: the AR_DEBUG_PRINTF macro is defined here to handle special handling of variable arg macros
- * which may be compiler dependent. */
-#define AR_DEBUG_PRINTF(mask, args) do { \
- if (GET_ATH_MODULE_DEBUG_VAR_MASK(ATH_MODULE_NAME) & (mask)) { \
- A_LOGGER(mask, ATH_MODULE_NAME, ATH_PRINTX_ARG args); \
- } \
-} while (0)
-#else
- /* on non-debug builds, keep in error and warning messages in the driver, all other
- * message tracing will get compiled out */
-#define AR_DEBUG_PRINTF(mask, args) \
- if ((mask) & (ATH_DEBUG_ERR | ATH_DEBUG_WARN)) { A_PRINTF(ATH_PRINTX_ARG args); }
-
-#endif
-
- /* compile specific macro to get the function name string */
-#define _A_FUNCNAME_ __func__
-
-
-#endif /* _DEBUG_LINUX_H_ */
diff --git a/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h b/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h
deleted file mode 100644
index 74f986183347..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h
+++ /dev/null
@@ -1,76 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// HCI bridge implementation
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-#include "hci_transport_api.h"
-#include "common_drv.h"
-
-extern HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo);
-extern void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans);
-extern int (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue);
-extern int (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous);
-extern void (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans);
-extern int (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans);
-extern int (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
-extern int (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans,
- struct htc_packet *pPacket,
- int MaxPollMS);
-extern int (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud);
-extern int (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
-
-
-#define HCI_TransportAttach(HTCHandle, pInfo) \
- _HCI_TransportAttach((HTCHandle), (pInfo))
-#define HCI_TransportDetach(HciTrans) \
- _HCI_TransportDetach(HciTrans)
-#define HCI_TransportAddReceivePkts(HciTrans, pQueue) \
- _HCI_TransportAddReceivePkts((HciTrans), (pQueue))
-#define HCI_TransportSendPkt(HciTrans, pPacket, Synchronous) \
- _HCI_TransportSendPkt((HciTrans), (pPacket), (Synchronous))
-#define HCI_TransportStop(HciTrans) \
- _HCI_TransportStop((HciTrans))
-#define HCI_TransportStart(HciTrans) \
- _HCI_TransportStart((HciTrans))
-#define HCI_TransportEnableDisableAsyncRecv(HciTrans, Enable) \
- _HCI_TransportEnableDisableAsyncRecv((HciTrans), (Enable))
-#define HCI_TransportRecvHCIEventSync(HciTrans, pPacket, MaxPollMS) \
- _HCI_TransportRecvHCIEventSync((HciTrans), (pPacket), (MaxPollMS))
-#define HCI_TransportSetBaudRate(HciTrans, Baud) \
- _HCI_TransportSetBaudRate((HciTrans), (Baud))
-#define HCI_TransportEnablePowerMgmt(HciTrans, Enable) \
- _HCI_TransportEnablePowerMgmt((HciTrans), (Enable))
-
-
-extern int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks);
-
-extern int ar6000_get_hif_dev(struct hif_device *device, void *config);
-
-extern int ar6000_set_uart_config(struct hif_device *hifDevice, u32 scale, u32 step);
-
-/* get core clock register settings
- * data: 0 - 40/44MHz
- * 1 - 80/88MHz
- * where (5G band/2.4G band)
- * assume 2.4G band for now
- */
-extern int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data);
diff --git a/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h b/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h
deleted file mode 100644
index e6e96de3fc6b..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h
+++ /dev/null
@@ -1,177 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef _IEEE80211_IOCTL_H_
-#define _IEEE80211_IOCTL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Extracted from the MADWIFI net80211/ieee80211_ioctl.h
- */
-
-/*
- * WPA/RSN get/set key request. Specify the key/cipher
- * type and whether the key is to be used for sending and/or
- * receiving. The key index should be set only when working
- * with global keys (use IEEE80211_KEYIX_NONE for ``no index'').
- * Otherwise a unicast/pairwise key is specified by the bssid
- * (on a station) or mac address (on an ap). They key length
- * must include any MIC key data; otherwise it should be no
- more than IEEE80211_KEYBUF_SIZE.
- */
-struct ieee80211req_key {
- u_int8_t ik_type; /* key/cipher type */
- u_int8_t ik_pad;
- u_int16_t ik_keyix; /* key index */
- u_int8_t ik_keylen; /* key length in bytes */
- u_int8_t ik_flags;
-#define IEEE80211_KEY_XMIT 0x01
-#define IEEE80211_KEY_RECV 0x02
-#define IEEE80211_KEY_DEFAULT 0x80 /* default xmit key */
- u_int8_t ik_macaddr[IEEE80211_ADDR_LEN];
- u_int64_t ik_keyrsc; /* key receive sequence counter */
- u_int64_t ik_keytsc; /* key transmit sequence counter */
- u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
-};
-/*
- * Delete a key either by index or address. Set the index
- * to IEEE80211_KEYIX_NONE when deleting a unicast key.
- */
-struct ieee80211req_del_key {
- u_int8_t idk_keyix; /* key index */
- u_int8_t idk_macaddr[IEEE80211_ADDR_LEN];
-};
-/*
- * MLME state manipulation request. IEEE80211_MLME_ASSOC
- * only makes sense when operating as a station. The other
- * requests can be used when operating as a station or an
- * ap (to effect a station).
- */
-struct ieee80211req_mlme {
- u_int8_t im_op; /* operation to perform */
-#define IEEE80211_MLME_ASSOC 1 /* associate station */
-#define IEEE80211_MLME_DISASSOC 2 /* disassociate station */
-#define IEEE80211_MLME_DEAUTH 3 /* deauthenticate station */
-#define IEEE80211_MLME_AUTHORIZE 4 /* authorize station */
-#define IEEE80211_MLME_UNAUTHORIZE 5 /* unauthorize station */
- u_int16_t im_reason; /* 802.11 reason code */
- u_int8_t im_macaddr[IEEE80211_ADDR_LEN];
-};
-
-struct ieee80211req_addpmkid {
- u_int8_t pi_bssid[IEEE80211_ADDR_LEN];
- u_int8_t pi_enable;
- u_int8_t pi_pmkid[16];
-};
-
-#define AUTH_ALG_OPEN_SYSTEM 0x01
-#define AUTH_ALG_SHARED_KEY 0x02
-#define AUTH_ALG_LEAP 0x04
-
-struct ieee80211req_authalg {
- u_int8_t auth_alg;
-};
-
-/*
- * Request to add an IE to a Management Frame
- */
-enum{
- IEEE80211_APPIE_FRAME_BEACON = 0,
- IEEE80211_APPIE_FRAME_PROBE_REQ = 1,
- IEEE80211_APPIE_FRAME_PROBE_RESP = 2,
- IEEE80211_APPIE_FRAME_ASSOC_REQ = 3,
- IEEE80211_APPIE_FRAME_ASSOC_RESP = 4,
- IEEE80211_APPIE_NUM_OF_FRAME = 5
-};
-
-/*
- * The Maximum length of the IE that can be added to a Management frame
- */
-#define IEEE80211_APPIE_FRAME_MAX_LEN 200
-
-struct ieee80211req_getset_appiebuf {
- u_int32_t app_frmtype; /* management frame type for which buffer is added */
- u_int32_t app_buflen; /*application supplied buffer length */
- u_int8_t app_buf[];
-};
-
-/*
- * The following definitions are used by an application to set filter
- * for receiving management frames
- */
-enum {
- IEEE80211_FILTER_TYPE_BEACON = 0x1,
- IEEE80211_FILTER_TYPE_PROBE_REQ = 0x2,
- IEEE80211_FILTER_TYPE_PROBE_RESP = 0x4,
- IEEE80211_FILTER_TYPE_ASSOC_REQ = 0x8,
- IEEE80211_FILTER_TYPE_ASSOC_RESP = 0x10,
- IEEE80211_FILTER_TYPE_AUTH = 0x20,
- IEEE80211_FILTER_TYPE_DEAUTH = 0x40,
- IEEE80211_FILTER_TYPE_DISASSOC = 0x80,
- IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */
-};
-
-struct ieee80211req_set_filter {
- u_int32_t app_filterype; /* management frame filter type */
-};
-
-enum {
- IEEE80211_PARAM_AUTHMODE = 3, /* Authentication Mode */
- IEEE80211_PARAM_MCASTCIPHER = 5,
- IEEE80211_PARAM_MCASTKEYLEN = 6, /* multicast key length */
- IEEE80211_PARAM_UCASTCIPHER = 8,
- IEEE80211_PARAM_UCASTKEYLEN = 9, /* unicast key length */
- IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */
- IEEE80211_PARAM_ROAMING = 12, /* roaming mode */
- IEEE80211_PARAM_PRIVACY = 13, /* privacy invoked */
- IEEE80211_PARAM_COUNTERMEASURES = 14, /* WPA/TKIP countermeasures */
- IEEE80211_PARAM_DROPUNENCRYPTED = 15, /* discard unencrypted frames */
- IEEE80211_PARAM_WAPI = 16, /* WAPI policy from wapid */
-};
-
-/*
- * Values for IEEE80211_PARAM_WPA
- */
-#define WPA_MODE_WPA1 1
-#define WPA_MODE_WPA2 2
-#define WPA_MODE_AUTO 3
-#define WPA_MODE_NONE 4
-
-struct ieee80211req_wpaie {
- u_int8_t wpa_macaddr[IEEE80211_ADDR_LEN];
- u_int8_t wpa_ie[IEEE80211_MAX_IE];
- u_int8_t rsn_ie[IEEE80211_MAX_IE];
-};
-
-#ifndef IW_ENCODE_ALG_PMK
-#define IW_ENCODE_ALG_PMK 4
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _IEEE80211_IOCTL_H_ */
diff --git a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
deleted file mode 100644
index 41f437307727..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
+++ /dev/null
@@ -1,339 +0,0 @@
-//------------------------------------------------------------------------------
-// This file contains the definitions of the basic atheros data types.
-// It is used to map the data types in atheros files to a platform specific
-// type.
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef _OSAPI_LINUX_H_
-#define _OSAPI_LINUX_H_
-
-#ifdef __KERNEL__
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/semaphore.h>
-#include <linux/cache.h>
-
-#ifdef __GNUC__
-#define __ATTRIB_PACK __attribute__ ((packed))
-#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2)))
-#define __ATTRIB_NORETURN __attribute__ ((noreturn))
-#ifndef INLINE
-#define INLINE __inline__
-#endif
-#else /* Not GCC */
-#define __ATTRIB_PACK
-#define __ATTRIB_PRINTF
-#define __ATTRIB_NORETURN
-#ifndef INLINE
-#define INLINE __inline
-#endif
-#endif /* End __GNUC__ */
-
-#define PREPACK
-#define POSTPACK __ATTRIB_PACK
-
-/*
- * Endianes macros
- */
-#define A_BE2CPU8(x) ntohb(x)
-#define A_BE2CPU16(x) ntohs(x)
-#define A_BE2CPU32(x) ntohl(x)
-
-#define A_LE2CPU8(x) (x)
-#define A_LE2CPU16(x) (x)
-#define A_LE2CPU32(x) (x)
-
-#define A_CPU2BE8(x) htonb(x)
-#define A_CPU2BE16(x) htons(x)
-#define A_CPU2BE32(x) htonl(x)
-
-#define A_MEMZERO(addr, len) memset(addr, 0, len)
-#define A_MALLOC(size) kmalloc((size), GFP_KERNEL)
-#define A_MALLOC_NOWAIT(size) kmalloc((size), GFP_ATOMIC)
-
-#define A_LOGGER(mask, mod, args...) printk(KERN_ALERT args)
-#define A_PRINTF(args...) printk(KERN_ALERT args)
-
-#define A_PRINTF_LOG(args...) printk(args)
-#define A_SPRINTF(buf, args...) sprintf (buf, args)
-
-/* Mutual Exclusion */
-typedef spinlock_t A_MUTEX_T;
-#define A_MUTEX_INIT(mutex) spin_lock_init(mutex)
-#define A_MUTEX_LOCK(mutex) spin_lock_bh(mutex)
-#define A_MUTEX_UNLOCK(mutex) spin_unlock_bh(mutex)
-#define A_IS_MUTEX_VALID(mutex) true /* okay to return true, since A_MUTEX_DELETE does nothing */
-#define A_MUTEX_DELETE(mutex) /* spin locks are not kernel resources so nothing to free.. */
-
-/* Get current time in ms adding a constant offset (in ms) */
-#define A_GET_MS(offset) \
- (((jiffies / HZ) * 1000) + (offset))
-
-/*
- * Timer Functions
- */
-#define A_MDELAY(msecs) mdelay(msecs)
-typedef struct timer_list A_TIMER;
-
-#define A_INIT_TIMER(pTimer, pFunction, pArg) do { \
- init_timer(pTimer); \
- (pTimer)->function = (pFunction); \
- (pTimer)->data = (unsigned long)(pArg); \
-} while (0)
-
-/*
- * Start a Timer that elapses after 'periodMSec' milli-seconds
- * Support is provided for a one-shot timer. The 'repeatFlag' is
- * ignored.
- */
-#define A_TIMEOUT_MS(pTimer, periodMSec, repeatFlag) do { \
- if (repeatFlag) { \
- printk("\n" __FILE__ ":%d: Timer Repeat requested\n",__LINE__); \
- panic("Timer Repeat"); \
- } \
- mod_timer((pTimer), jiffies + HZ * (periodMSec) / 1000); \
-} while (0)
-
-/*
- * Cancel the Timer.
- */
-#define A_UNTIMEOUT(pTimer) do { \
- del_timer((pTimer)); \
-} while (0)
-
-#define A_DELETE_TIMER(pTimer) do { \
-} while (0)
-
-/*
- * Wait Queue related functions
- */
-typedef wait_queue_head_t A_WAITQUEUE_HEAD;
-#define A_INIT_WAITQUEUE_HEAD(head) init_waitqueue_head(head)
-#ifndef wait_event_interruptible_timeout
-#define __wait_event_interruptible_timeout(wq, condition, ret) \
-do { \
- wait_queue_t __wait; \
- init_waitqueue_entry(&__wait, current); \
- \
- add_wait_queue(&wq, &__wait); \
- for (;;) { \
- set_current_state(TASK_INTERRUPTIBLE); \
- if (condition) \
- break; \
- if (!signal_pending(current)) { \
- ret = schedule_timeout(ret); \
- if (!ret) \
- break; \
- continue; \
- } \
- ret = -ERESTARTSYS; \
- break; \
- } \
- current->state = TASK_RUNNING; \
- remove_wait_queue(&wq, &__wait); \
-} while (0)
-
-#define wait_event_interruptible_timeout(wq, condition, timeout) \
-({ \
- long __ret = timeout; \
- if (!(condition)) \
- __wait_event_interruptible_timeout(wq, condition, __ret); \
- __ret; \
-})
-#endif /* wait_event_interruptible_timeout */
-
-#define A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(head, condition, timeout) do { \
- wait_event_interruptible_timeout(head, condition, timeout); \
-} while (0)
-
-#define A_WAKE_UP(head) wake_up(head)
-
-#ifdef DEBUG
-extern unsigned int panic_on_assert;
-#define A_ASSERT(expr) \
- if (!(expr)) { \
- printk(KERN_ALERT"Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#expr); \
- if (panic_on_assert) panic(#expr); \
- }
-#else
-#define A_ASSERT(expr)
-#endif /* DEBUG */
-
-#define A_REQUEST_FIRMWARE(_ppf, _pfile, _dev) request_firmware(_ppf, _pfile, _dev)
-#define A_RELEASE_FIRMWARE(_pf) release_firmware(_pf)
-
-/*
- * Initialization of the network buffer subsystem
- */
-#define A_NETBUF_INIT()
-
-/*
- * Network buffer queue support
- */
-typedef struct sk_buff_head A_NETBUF_QUEUE_T;
-
-#define A_NETBUF_QUEUE_INIT(q) \
- a_netbuf_queue_init(q)
-
-#define A_NETBUF_ENQUEUE(q, pkt) \
- a_netbuf_enqueue((q), (pkt))
-#define A_NETBUF_PREQUEUE(q, pkt) \
- a_netbuf_prequeue((q), (pkt))
-#define A_NETBUF_DEQUEUE(q) \
- (a_netbuf_dequeue(q))
-#define A_NETBUF_QUEUE_SIZE(q) \
- a_netbuf_queue_size(q)
-#define A_NETBUF_QUEUE_EMPTY(q) \
- (a_netbuf_queue_empty(q) ? true : false)
-
-/*
- * Network buffer support
- */
-#define A_NETBUF_ALLOC(size) \
- a_netbuf_alloc(size)
-#define A_NETBUF_ALLOC_RAW(size) \
- a_netbuf_alloc_raw(size)
-#define A_NETBUF_FREE(bufPtr) \
- a_netbuf_free(bufPtr)
-#define A_NETBUF_DATA(bufPtr) \
- a_netbuf_to_data(bufPtr)
-#define A_NETBUF_LEN(bufPtr) \
- a_netbuf_to_len(bufPtr)
-#define A_NETBUF_PUSH(bufPtr, len) \
- a_netbuf_push(bufPtr, len)
-#define A_NETBUF_PUT(bufPtr, len) \
- a_netbuf_put(bufPtr, len)
-#define A_NETBUF_TRIM(bufPtr,len) \
- a_netbuf_trim(bufPtr, len)
-#define A_NETBUF_PULL(bufPtr, len) \
- a_netbuf_pull(bufPtr, len)
-#define A_NETBUF_HEADROOM(bufPtr)\
- a_netbuf_headroom(bufPtr)
-#define A_NETBUF_SETLEN(bufPtr,len) \
- a_netbuf_setlen(bufPtr, len)
-
-/* Add data to end of a buffer */
-#define A_NETBUF_PUT_DATA(bufPtr, srcPtr, len) \
- a_netbuf_put_data(bufPtr, srcPtr, len)
-
-/* Add data to start of the buffer */
-#define A_NETBUF_PUSH_DATA(bufPtr, srcPtr, len) \
- a_netbuf_push_data(bufPtr, srcPtr, len)
-
-/* Remove data at start of the buffer */
-#define A_NETBUF_PULL_DATA(bufPtr, dstPtr, len) \
- a_netbuf_pull_data(bufPtr, dstPtr, len)
-
-/* Remove data from the end of the buffer */
-#define A_NETBUF_TRIM_DATA(bufPtr, dstPtr, len) \
- a_netbuf_trim_data(bufPtr, dstPtr, len)
-
-/* View data as "size" contiguous bytes of type "t" */
-#define A_NETBUF_VIEW_DATA(bufPtr, t, size) \
- (t )( ((struct skbuf *)(bufPtr))->data)
-
-/* return the beginning of the headroom for the buffer */
-#define A_NETBUF_HEAD(bufPtr) \
- ((((struct sk_buff *)(bufPtr))->head))
-
-/*
- * OS specific network buffer access routines
- */
-void *a_netbuf_alloc(int size);
-void *a_netbuf_alloc_raw(int size);
-void a_netbuf_free(void *bufPtr);
-void *a_netbuf_to_data(void *bufPtr);
-u32 a_netbuf_to_len(void *bufPtr);
-int a_netbuf_push(void *bufPtr, s32 len);
-int a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len);
-int a_netbuf_put(void *bufPtr, s32 len);
-int a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len);
-int a_netbuf_pull(void *bufPtr, s32 len);
-int a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len);
-int a_netbuf_trim(void *bufPtr, s32 len);
-int a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len);
-int a_netbuf_setlen(void *bufPtr, s32 len);
-s32 a_netbuf_headroom(void *bufPtr);
-void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt);
-void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt);
-void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q);
-int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q);
-int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q);
-int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q);
-void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q);
-
-/*
- * Kernel v.s User space functions
- */
-u32 a_copy_to_user(void *to, const void *from, u32 n);
-u32 a_copy_from_user(void *to, const void *from, u32 n);
-
-/* In linux, WLAN Rx and Tx run in different contexts, so no need to check
- * for any commands/data queued for WLAN */
-#define A_CHECK_DRV_TX()
-
-#define A_GET_CACHE_LINE_BYTES() L1_CACHE_BYTES
-
-#define A_CACHE_LINE_PAD 128
-
-static inline void *A_ALIGN_TO_CACHE_LINE(void *ptr) {
- return (void *)L1_CACHE_ALIGN((unsigned long)ptr);
-}
-
-#else /* __KERNEL__ */
-
-#ifdef __GNUC__
-#define __ATTRIB_PACK __attribute__ ((packed))
-#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2)))
-#define __ATTRIB_NORETURN __attribute__ ((noreturn))
-#ifndef INLINE
-#define INLINE __inline__
-#endif
-#else /* Not GCC */
-#define __ATTRIB_PACK
-#define __ATTRIB_PRINTF
-#define __ATTRIB_NORETURN
-#ifndef INLINE
-#define INLINE __inline
-#endif
-#endif /* End __GNUC__ */
-
-#define PREPACK
-#define POSTPACK __ATTRIB_PACK
-
-#define A_MEMZERO(addr, len) memset((addr), 0, (len))
-#define A_MALLOC(size) malloc(size)
-
-#include <err.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* _OSAPI_LINUX_H_ */
diff --git a/drivers/staging/ath6kl/os/linux/include/wlan_config.h b/drivers/staging/ath6kl/os/linux/include/wlan_config.h
deleted file mode 100644
index c1fe0c6e4fa1..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/wlan_config.h
+++ /dev/null
@@ -1,108 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains the tunable configuration items for the WLAN module
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _HOST_WLAN_CONFIG_H_
-#define _HOST_WLAN_CONFIG_H_
-
-/* Include definitions here that can be used to tune the WLAN module behavior.
- * Different customers can tune the behavior as per their needs, here.
- */
-
-/* This configuration item when defined will consider the barker preamble
- * mentioned in the ERP IE of the beacons from the AP to determine the short
- * preamble support sent in the (Re)Assoc request frames.
- */
-#define WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP 0
-
-/* This config item when defined will not send the power module state transition
- * failure events that happen during scan, to the host.
- */
-#define WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN 0
-
-/*
- * This configuration item enable/disable keepalive support.
- * Keepalive support: In the absence of any data traffic to AP, null
- * frames will be sent to the AP at periodic interval, to keep the association
- * active. This configuration item defines the periodic interval.
- * Use value of zero to disable keepalive support
- * Default: 60 seconds
- */
-#define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60
-
-/*
- * This configuration item sets the value of disconnect timeout
- * Firmware delays sending the disconnec event to the host for this
- * timeout after is gets disconnected from the current AP.
- * If the firmware successly roams within the disconnect timeout
- * it sends a new connect event
- */
-#define WLAN_CONFIG_DISCONNECT_TIMEOUT 10
-
-/*
- * This configuration item disables 11n support.
- * 0 - Enable
- * 1 - Disable
- */
-#define WLAN_CONFIG_DISABLE_11N 0
-
-/*
- * This configuration item enable BT clock sharing support
- * 1 - Enable
- * 0 - Disable (Default)
- */
-#define WLAN_CONFIG_BT_SHARING 0
-
-/*
- * This configuration item sets WIFI OFF policy
- * 0 - CUT_POWER
- * 1 - DEEP_SLEEP (Default)
- */
-#define WLAN_CONFIG_WLAN_OFF 1
-
-/*
- * This configuration item sets suspend policy
- * 0 - CUT_POWER (Default)
- * 1 - DEEP_SLEEP
- * 2 - WoW
- * 3 - CUT_POWER if BT OFF (clock sharing designs only)
- */
-#define WLAN_CONFIG_PM_SUSPEND 0
-
-/*
- * This configuration item sets suspend policy to use if PM_SUSPEND is
- * set to WoW and device is not connected at the time of suspend
- * 0 - CUT_POWER (Default)
- * 1 - DEEP_SLEEP
- * 2 - WoW
- * 3 - CUT_POWER if BT OFF (clock sharing designs only)
- */
-#define WLAN_CONFIG_PM_WOW2 0
-
-/*
- * This configuration item enables/disables transmit bursting
- * 0 - Enable tx Bursting (default)
- * 1 - Disable tx bursting
- */
-#define WLAN_CONFIG_DISABLE_TX_BURSTING 0
-
-#endif /* _HOST_WLAN_CONFIG_H_ */
diff --git a/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h b/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h
deleted file mode 100644
index 1eb6f822d64e..000000000000
--- a/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h
+++ /dev/null
@@ -1,300 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-
-#ifndef _WMI_FILTER_LINUX_H_
-#define _WMI_FILTER_LINUX_H_
-
-/*
- * sioctl_filter - Standard ioctl
- * pioctl_filter - Priv ioctl
- * xioctl_filter - eXtended ioctl
- *
- * ---- Possible values for the WMI filter ---------------
- * (0) - Block this cmd always (or) not implemented
- * (INFRA_NETWORK) - Allow this cmd only in STA mode
- * (ADHOC_NETWORK) - Allow this cmd only in IBSS mode
- * (AP_NETWORK) - Allow this cmd only in AP mode
- * (INFRA_NETWORK | ADHOC_NETWORK) - Block this cmd in AP mode
- * (ADHOC_NETWORK | AP_NETWORK) - Block this cmd in STA mode
- * (INFRA_NETWORK | AP_NETWORK) - Block this cmd in IBSS mode
- * (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK)- allow only when mode is set
- * (0xFF) - Allow this cmd always irrespective of mode
- */
-
-u8 sioctl_filter[] = {
-(AP_NETWORK), /* SIOCSIWCOMMIT 0x8B00 */
-(0xFF), /* SIOCGIWNAME 0x8B01 */
-(0), /* SIOCSIWNWID 0x8B02 */
-(0), /* SIOCGIWNWID 0x8B03 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWFREQ 0x8B04 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWFREQ 0x8B05 */
-(0xFF), /* SIOCSIWMODE 0x8B06 */
-(0xFF), /* SIOCGIWMODE 0x8B07 */
-(0), /* SIOCSIWSENS 0x8B08 */
-(0), /* SIOCGIWSENS 0x8B09 */
-(0), /* SIOCSIWRANGE 0x8B0A */
-(0xFF), /* SIOCGIWRANGE 0x8B0B */
-(0), /* SIOCSIWPRIV 0x8B0C */
-(0), /* SIOCGIWPRIV 0x8B0D */
-(0), /* SIOCSIWSTATS 0x8B0E */
-(0), /* SIOCGIWSTATS 0x8B0F */
-(0), /* SIOCSIWSPY 0x8B10 */
-(0), /* SIOCGIWSPY 0x8B11 */
-(0), /* SIOCSIWTHRSPY 0x8B12 */
-(0), /* SIOCGIWTHRSPY 0x8B13 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWAP 0x8B14 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWAP 0x8B15 */
-#if (WIRELESS_EXT >= 18)
-(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWMLME 0X8B16 */
-#else
-(0), /* Dummy 0 */
-#endif /* WIRELESS_EXT */
-(0), /* SIOCGIWAPLIST 0x8B17 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWSCAN 0x8B18 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCGIWSCAN 0x8B19 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWESSID 0x8B1A */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWESSID 0x8B1B */
-(0), /* SIOCSIWNICKN 0x8B1C */
-(0), /* SIOCGIWNICKN 0x8B1D */
-(0), /* Dummy 0 */
-(0), /* Dummy 0 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWRATE 0x8B20 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWRATE 0x8B21 */
-(0), /* SIOCSIWRTS 0x8B22 */
-(0), /* SIOCGIWRTS 0x8B23 */
-(0), /* SIOCSIWFRAG 0x8B24 */
-(0), /* SIOCGIWFRAG 0x8B25 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWTXPOW 0x8B26 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWTXPOW 0x8B27 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWRETRY 0x8B28 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCGIWRETRY 0x8B29 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWENCODE 0x8B2A */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWENCODE 0x8B2B */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWPOWER 0x8B2C */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWPOWER 0x8B2D */
-};
-
-
-
-u8 pioctl_filter[] = {
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+1) */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+2) */
-(AP_NETWORK), /* IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+3) */
-(INFRA_NETWORK), /* IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+4) */
-(0), /* IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+5) */
-(0), /* (SIOCIWFIRSTPRIV+6) */
-(0), /* (SIOCIWFIRSTPRIV+7) */
-(0), /* (SIOCIWFIRSTPRIV+8) */
-(0), /* (SIOCIWFIRSTPRIV+9) */
-(0), /* IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+10) */
-(0xFF), /* AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+11) */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+12) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+13) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+14) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+15) */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18) */
-(INFRA_NETWORK), /* AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24)*/
-(0xFF), /* AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28) */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29) */
-(ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30) */
-};
-
-
-
-u8 xioctl_filter[] = {
-(0xFF), /* Dummy 0 */
-(0xFF), /* AR6000_XIOCTL_BMI_DONE 1 */
-(0xFF), /* AR6000_XIOCTL_BMI_READ_MEMORY 2 */
-(0xFF), /* AR6000_XIOCTL_BMI_WRITE_MEMORY 3 */
-(0xFF), /* AR6000_XIOCTL_BMI_EXECUTE 4 */
-(0xFF), /* AR6000_XIOCTL_BMI_SET_APP_START 5 */
-(0xFF), /* AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6 */
-(0xFF), /* AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7 */
-(0xFF), /* AR6000_XIOCTL_BMI_TEST 8 */
-(0xFF), /* AR6000_XIOCTL_UNUSED9 9 */
-(0xFF), /* AR6000_XIOCTL_UNUSED10 10 */
-(0xFF), /* AR6000_XIOCTL_UNUSED11 11 */
-(0xFF), /* AR6000_XIOCTL_FORCE_TARGET_RESET 12 */
-(0xFF), /* AR6000_XIOCTL_HTC_RAW_OPEN 13 */
-(0xFF), /* AR6000_XIOCTL_HTC_RAW_CLOSE 14 */
-(0xFF), /* AR6000_XIOCTL_HTC_RAW_READ 15 */
-(0xFF), /* AR6000_XIOCTL_HTC_RAW_WRITE 16 */
-(0xFF), /* AR6000_XIOCTL_CHECK_TARGET_READY 17 */
-(0xFF), /* AR6000_XIOCTL_GPIO_OUTPUT_SET 18 */
-(0xFF), /* AR6000_XIOCTL_GPIO_INPUT_GET 19 */
-(0xFF), /* AR6000_XIOCTL_GPIO_REGISTER_SET 20 */
-(0xFF), /* AR6000_XIOCTL_GPIO_REGISTER_GET 21 */
-(0xFF), /* AR6000_XIOCTL_GPIO_INTR_ACK 22 */
-(0xFF), /* AR6000_XIOCTL_GPIO_INTR_WAIT 23 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_ADHOC_BSSID 24 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_OPT_MODE 25 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_OPT_SEND_FRAME 26 */
-(ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_SET_BEACON_INTVAL 27 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETAUTHALG 28 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_MAX_SP 30 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_ROAM_TBL 31 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTRL_WMI_GET_POWER_MODE 34 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_ROAM_DATA 36 */
-(0xFF), /* AR6000_XIOCTL_WMI_SETRETRYLIMITS 37 */
-(0xFF), /* AR6000_XIOCTL_TCMD_CONT_TX 38 */
-(0xFF), /* AR6000_XIOCTL_TCMD_CONT_RX 39 */
-(0xFF), /* AR6000_XIOCTL_TCMD_PM 40 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_STARTSCAN 41 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SETFIXRATES 42 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_GETFIXRATES 43 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_CLR_RSSISNR 45 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_RTS 47 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_LPREAMBLE 48 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_AUTHMODE 49 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_REASSOCMODE 50 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WMM 51 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53 */
-(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_GET_RD 54 */
-(0xFF), /* AR6000_XIOCTL_DIAG_READ 55 */
-(0xFF), /* AR6000_XIOCTL_DIAG_WRITE 56 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_TXOP 57 */
-(INFRA_NETWORK), /* AR6000_XIOCTL_USER_SETKEYS 58 */
-(INFRA_NETWORK), /* AR6000_XIOCTL_WMI_SET_KEEPALIVE 59 */
-(INFRA_NETWORK), /* AR6000_XIOCTL_WMI_GET_KEEPALIVE 60 */
-(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61 */
-(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62 */
-(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63 */
-(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64 */
-(0xFF), /* AR6000_XIOCTL_WMI_SET_APPIE 65 */
-(0xFF), /* AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66 */
-(0xFF), /* AR6000_XIOCTL_DBGLOG_CFG_MODULE 67 */
-(0xFF), /* AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68 */
-(0xFF), /* Dummy 69 */
-(0xFF), /* AR6000_XIOCTL_WMI_SET_WSC_STATUS 70 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_STATUS 71 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_PARAMS 72 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE 73 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WOW_MODE 74 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_WOW_LIST 75 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_ADD_WOW_PATTERN 76 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_DEL_WOW_PATTERN 77 */
-(0xFF), /* AR6000_XIOCTL_TARGET_INFO 78 */
-(0xFF), /* AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79 */
-(0xFF), /* AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_PMKID_LIST 83 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_PMKID_LIST 84 */
-(0xFF), /* Dummy 85 */
-(0xFF), /* Dummy 86 */
-(0xFF), /* Dummy 87 */
-(0xFF), /* Dummy 88 */
-(0xFF), /* Dummy 89 */
-(0xFF), /* AR6000_XIOCTL_UNUSED90 90 */
-(0xFF), /* AR6000_XIOCTL_BMI_LZ_STREAM_START 91 */
-(0xFF), /* AR6000_XIOCTL_BMI_LZ_DATA 92 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_CFG 93 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_ADDR_SET 94 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_START 95 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_STOP 96 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_COUNT_GET 97 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_ABORT_SCAN 98 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_STA_LIST 99 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_HIDDEN_SSID 100 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_NUM_STA 101 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_ACL_MAC 102 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_ACL_LIST 103 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_COMMIT_CONFIG 104 */
-(AP_NETWORK), /* IEEE80211_IOCTL_GETWPAIE 105 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_CONN_INACT_TIME 106 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_PROT_SCAN_TIME 107 */
-(AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_COUNTRY 108 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_DTIM 109 */
-(0xFF), /* AR6000_XIOCTL_WMI_TARGET_EVENT_REPORT 110 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_IP 111 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_ACL_POLICY 112 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_INTRA_BSS_COMM 113 */
-(0xFF), /* AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO 114 */
-(0xFF), /* AR6000_XIOCTL_MODULE_DEBUG_SET_MASK 115 */
-(0xFF), /* AR6000_XIOCTL_MODULE_DEBUG_GET_MASK 116 */
-(0xFF), /* AR6000_XIOCTL_DUMP_RCV_AGGR_STATS 117 */
-(0xFF), /* AR6000_XIOCTL_SET_HT_CAP 118 */
-(0xFF), /* AR6000_XIOCTL_SET_HT_OP 119 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_STAT 120 */
-(0xFF), /* AR6000_XIOCTL_SET_TX_SELECT_RATES 121 */
-(0xFF), /* AR6000_XIOCTL_SETUP_AGGR 122 */
-(0xFF), /* AR6000_XIOCTL_ALLOW_AGGR 123 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_HIDDEN_SSID 124 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_COUNTRY 125 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_WMODE 126 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_DTIM 127 */
-(AP_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_AP_GET_BINTVL 128 */
-(0xFF), /* AR6000_XIOCTL_AP_GET_RTS 129 */
-(0xFF), /* AR6000_XIOCTL_DELE_AGGR 130 */
-(0xFF), /* AR6000_XIOCTL_FETCH_TARGET_REGS 131 */
-(0xFF), /* AR6000_XIOCTL_HCI_CMD 132 */
-(0xFF), /* AR6000_XIOCTL_ACL_DATA(used to be used for PAL) 133 */
-(0xFF), /* AR6000_XIOCTL_WLAN_CONN_PRECEDENCE 134 */
-(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_11BG_RATESET 135 */
-(0xFF),
-(0xFF),
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT 138 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV 139 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG 140 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_SCO_CONFIG 141 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_A2DP_CONFIG 142 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_ACLCOEX_CONFIG 143 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_DEBUG 144 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_OPERATING_STATUS 145 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_BTCOEX_CONFIG 146 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_BTCOEX_GET_STATS 147 */
-(0xFF), /* AR6000_XIOCTL_WMI_SET_QOS_SUPP 148 */
-(0xFF), /* AR6000_XIOCTL_GET_WLAN_SLEEP_STATE 149 */
-(0xFF), /* AR6000_XIOCTL_SET_BT_HW_POWER_STATE 150 */
-(0xFF), /* AR6000_XIOCTL_GET_BT_HW_POWER_STATE 151 */
-(0xFF), /* AR6000_XIOCTL_ADD_AP_INTERFACE 152 */
-(0xFF), /* AR6000_XIOCTL_REMOVE_AP_INTERFACE 153 */
-(0xFF), /* AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM 154 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WPA_OFFLOAD_STATE 155 */
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_PASSPHRASE 156 */
-(0xFF),
-(0xFF),
-(0xFF),
-(0xFF),
-(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES 161 */
-};
-
-#endif /*_WMI_FILTER_LINUX_H_*/
diff --git a/drivers/staging/ath6kl/os/linux/netbuf.c b/drivers/staging/ath6kl/os/linux/netbuf.c
deleted file mode 100644
index 963a2fb76a92..000000000000
--- a/drivers/staging/ath6kl/os/linux/netbuf.c
+++ /dev/null
@@ -1,231 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Communications Inc.
-// All rights reserved.
-//
-//
-//
-// 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.
-//
-//
-//
-// Author(s): ="Atheros"
-//------------------------------------------------------------------------------
-#include <a_config.h>
-#include "athdefs.h"
-#include "a_osapi.h"
-#include "htc_packet.h"
-
-#define AR6000_DATA_OFFSET 64
-
-void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt)
-{
- skb_queue_tail((struct sk_buff_head *) q, (struct sk_buff *) pkt);
-}
-
-void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt)
-{
- skb_queue_head((struct sk_buff_head *) q, (struct sk_buff *) pkt);
-}
-
-void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q)
-{
- return((void *) skb_dequeue((struct sk_buff_head *) q));
-}
-
-int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q)
-{
- return(skb_queue_len((struct sk_buff_head *) q));
-}
-
-int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q)
-{
- return(skb_queue_empty((struct sk_buff_head *) q));
-}
-
-void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q)
-{
- skb_queue_head_init((struct sk_buff_head *) q);
-}
-
-void *
-a_netbuf_alloc(int size)
-{
- struct sk_buff *skb;
- size += 2 * (A_GET_CACHE_LINE_BYTES()); /* add some cacheline space at front and back of buffer */
- skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(struct htc_packet) + size);
- skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(struct htc_packet) + A_GET_CACHE_LINE_BYTES());
- return ((void *)skb);
-}
-
-/*
- * Allocate an SKB w.o. any encapsulation requirement.
- */
-void *
-a_netbuf_alloc_raw(int size)
-{
- struct sk_buff *skb;
-
- skb = dev_alloc_skb(size);
-
- return ((void *)skb);
-}
-
-void
-a_netbuf_free(void *bufPtr)
-{
- struct sk_buff *skb = (struct sk_buff *)bufPtr;
-
- dev_kfree_skb(skb);
-}
-
-u32 a_netbuf_to_len(void *bufPtr)
-{
- return (((struct sk_buff *)bufPtr)->len);
-}
-
-void *
-a_netbuf_to_data(void *bufPtr)
-{
- return (((struct sk_buff *)bufPtr)->data);
-}
-
-/*
- * Add len # of bytes to the beginning of the network buffer
- * pointed to by bufPtr
- */
-int
-a_netbuf_push(void *bufPtr, s32 len)
-{
- skb_push((struct sk_buff *)bufPtr, len);
-
- return 0;
-}
-
-/*
- * Add len # of bytes to the beginning of the network buffer
- * pointed to by bufPtr and also fill with data
- */
-int
-a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len)
-{
- skb_push((struct sk_buff *) bufPtr, len);
- memcpy(((struct sk_buff *)bufPtr)->data, srcPtr, len);
-
- return 0;
-}
-
-/*
- * Add len # of bytes to the end of the network buffer
- * pointed to by bufPtr
- */
-int
-a_netbuf_put(void *bufPtr, s32 len)
-{
- skb_put((struct sk_buff *)bufPtr, len);
-
- return 0;
-}
-
-/*
- * Add len # of bytes to the end of the network buffer
- * pointed to by bufPtr and also fill with data
- */
-int
-a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len)
-{
- char *start = (char*)(((struct sk_buff *)bufPtr)->data +
- ((struct sk_buff *)bufPtr)->len);
- skb_put((struct sk_buff *)bufPtr, len);
- memcpy(start, srcPtr, len);
-
- return 0;
-}
-
-
-/*
- * Trim the network buffer pointed to by bufPtr to len # of bytes
- */
-int
-a_netbuf_setlen(void *bufPtr, s32 len)
-{
- skb_trim((struct sk_buff *)bufPtr, len);
-
- return 0;
-}
-
-/*
- * Chop of len # of bytes from the end of the buffer.
- */
-int
-a_netbuf_trim(void *bufPtr, s32 len)
-{
- skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len);
-
- return 0;
-}
-
-/*
- * Chop of len # of bytes from the end of the buffer and return the data.
- */
-int
-a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len)
-{
- char *start = (char*)(((struct sk_buff *)bufPtr)->data +
- (((struct sk_buff *)bufPtr)->len - len));
-
- memcpy(dstPtr, start, len);
- skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len);
-
- return 0;
-}
-
-
-/*
- * Returns the number of bytes available to a a_netbuf_push()
- */
-s32 a_netbuf_headroom(void *bufPtr)
-{
- return (skb_headroom((struct sk_buff *)bufPtr));
-}
-
-/*
- * Removes specified number of bytes from the beginning of the buffer
- */
-int
-a_netbuf_pull(void *bufPtr, s32 len)
-{
- skb_pull((struct sk_buff *)bufPtr, len);
-
- return 0;
-}
-
-/*
- * Removes specified number of bytes from the beginning of the buffer
- * and return the data
- */
-int
-a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len)
-{
- memcpy(dstPtr, ((struct sk_buff *)bufPtr)->data, len);
- skb_pull((struct sk_buff *)bufPtr, len);
-
- return 0;
-}
-
-#ifdef EXPORT_HCI_BRIDGE_INTERFACE
-EXPORT_SYMBOL(a_netbuf_to_data);
-EXPORT_SYMBOL(a_netbuf_put);
-EXPORT_SYMBOL(a_netbuf_pull);
-EXPORT_SYMBOL(a_netbuf_alloc);
-EXPORT_SYMBOL(a_netbuf_free);
-#endif
diff --git a/drivers/staging/ath6kl/reorder/aggr_rx_internal.h b/drivers/staging/ath6kl/reorder/aggr_rx_internal.h
deleted file mode 100644
index 11125967d53d..000000000000
--- a/drivers/staging/ath6kl/reorder/aggr_rx_internal.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- *
- * Copyright (c) 2004-2010 Atheros Communications Inc.
- * All rights reserved.
- *
- *
-//
-// 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 __AGGR_RX_INTERNAL_H__
-#define __AGGR_RX_INTERNAL_H__
-
-#include "a_osapi.h"
-#include "aggr_recv_api.h"
-
-#define AGGR_WIN_IDX(x, y) ((x) % (y))
-#define AGGR_INCR_IDX(x, y) AGGR_WIN_IDX(((x)+1), (y))
-#define AGGR_DCRM_IDX(x, y) AGGR_WIN_IDX(((x)-1), (y))
-#define IEEE80211_MAX_SEQ_NO 0xFFF
-#define IEEE80211_NEXT_SEQ_NO(x) (((x) + 1) & IEEE80211_MAX_SEQ_NO)
-
-
-#define NUM_OF_TIDS 8
-#define AGGR_SZ_DEFAULT 8
-
-#define AGGR_WIN_SZ_MIN 2
-#define AGGR_WIN_SZ_MAX 8
-/* TID Window sz is double of what is negotiated. Derive TID_WINDOW_SZ from win_sz, per tid */
-#define TID_WINDOW_SZ(_x) ((_x) << 1)
-
-#define AGGR_NUM_OF_FREE_NETBUFS 16
-
-#define AGGR_GET_RXTID_STATS(_p, _x) (&(_p->stat[(_x)]))
-#define AGGR_GET_RXTID(_p, _x) (&(_p->RxTid[(_x)]))
-
-/* Hold q is a function of win_sz, which is negotiated per tid */
-#define HOLD_Q_SZ(_x) (TID_WINDOW_SZ((_x))*sizeof(struct osbuf_hold_q))
-/* AGGR_RX_TIMEOUT value is important as a (too) small value can cause frames to be
- * delivered out of order and a (too) large value can cause undesirable latency in
- * certain situations. */
-#define AGGR_RX_TIMEOUT 400 /* Timeout(in ms) for delivery of frames, if they are stuck */
-
-typedef enum {
- ALL_SEQNO = 0,
- CONTIGUOUS_SEQNO = 1,
-}DELIVERY_ORDER;
-
-struct osbuf_hold_q {
- void *osbuf;
- bool is_amsdu;
- u16 seq_no;
-};
-
-
-#if 0
-/* XXX: unused ? */
-struct window_snapshot {
- u16 seqno_st;
- u16 seqno_end;
-};
-#endif
-
-struct rxtid {
- bool aggr; /* is it ON or OFF */
- bool progress; /* true when frames have arrived after a timer start */
- bool timerMon; /* true if the timer started for the sake of this TID */
- u16 win_sz; /* negotiated window size */
- u16 seq_next; /* Next seq no, in current window */
- u32 hold_q_sz; /* Num of frames that can be held in hold q */
- struct osbuf_hold_q *hold_q; /* Hold q for re-order */
-#if 0
- struct window_snapshot old_win; /* Sliding window snapshot - for timeout */
-#endif
- A_NETBUF_QUEUE_T q; /* q head for enqueuing frames for dispatch */
- A_MUTEX_T lock;
-};
-
-struct rxtid_stats {
- u32 num_into_aggr; /* hitting at the input of this module */
- u32 num_dups; /* duplicate */
- u32 num_oow; /* out of window */
- u32 num_mpdu; /* single payload 802.3/802.11 frame */
- u32 num_amsdu; /* AMSDU */
- u32 num_delivered; /* frames delivered to IP stack */
- u32 num_timeouts; /* num of timeouts, during which frames delivered */
- u32 num_hole; /* frame not present, when window moved over */
- u32 num_bar; /* num of resets of seq_num, via BAR */
-};
-
-struct aggr_info {
- u8 aggr_sz; /* config value of aggregation size */
- u8 timerScheduled;
- A_TIMER timer; /* timer for returning held up pkts in re-order que */
- void *dev; /* dev handle */
- RX_CALLBACK rx_fn; /* callback function to return frames; to upper layer */
- struct rxtid RxTid[NUM_OF_TIDS]; /* Per tid window */
- ALLOC_NETBUFS netbuf_allocator; /* OS netbuf alloc fn */
- A_NETBUF_QUEUE_T freeQ; /* pre-allocated buffers - for A_MSDU slicing */
- struct rxtid_stats stat[NUM_OF_TIDS]; /* Tid based statistics */
- PACKET_LOG pkt_log; /* Log info of the packets */
-};
-
-#endif /* __AGGR_RX_INTERNAL_H__ */
diff --git a/drivers/staging/ath6kl/reorder/rcv_aggr.c b/drivers/staging/ath6kl/reorder/rcv_aggr.c
deleted file mode 100644
index 9b1509ec5a7b..000000000000
--- a/drivers/staging/ath6kl/reorder/rcv_aggr.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- *
- * Copyright (c) 2010 Atheros Communications Inc.
- * All rights reserved.
- *
- *
-//
-// 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 <a_config.h>
-#include <athdefs.h>
-#include <a_osapi.h>
-#include <a_debug.h>
-#include "pkt_log.h"
-#include "aggr_recv_api.h"
-#include "aggr_rx_internal.h"
-#include "wmi.h"
-
-extern int
-wmi_dot3_2_dix(void *osbuf);
-
-static void
-aggr_slice_amsdu(struct aggr_info *p_aggr, struct rxtid *rxtid, void **osbuf);
-
-static void
-aggr_timeout(unsigned long arg);
-
-static void
-aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, u16 seq_no, u8 order);
-
-static void
-aggr_dispatch_frames(struct aggr_info *p_aggr, A_NETBUF_QUEUE_T *q);
-
-static void *
-aggr_get_osbuf(struct aggr_info *p_aggr);
-
-void *
-aggr_init(ALLOC_NETBUFS netbuf_allocator)
-{
- struct aggr_info *p_aggr = NULL;
- struct rxtid *rxtid;
- u8 i;
- int status = 0;
-
- A_PRINTF("In aggr_init..\n");
-
- do {
- p_aggr = A_MALLOC(sizeof(struct aggr_info));
- if(!p_aggr) {
- A_PRINTF("Failed to allocate memory for aggr_node\n");
- status = A_ERROR;
- break;
- }
-
- /* Init timer and data structures */
- A_MEMZERO(p_aggr, sizeof(struct aggr_info));
- p_aggr->aggr_sz = AGGR_SZ_DEFAULT;
- A_INIT_TIMER(&p_aggr->timer, aggr_timeout, p_aggr);
- p_aggr->timerScheduled = false;
- A_NETBUF_QUEUE_INIT(&p_aggr->freeQ);
-
- p_aggr->netbuf_allocator = netbuf_allocator;
- p_aggr->netbuf_allocator(&p_aggr->freeQ, AGGR_NUM_OF_FREE_NETBUFS);
-
- for(i = 0; i < NUM_OF_TIDS; i++) {
- rxtid = AGGR_GET_RXTID(p_aggr, i);
- rxtid->aggr = false;
- rxtid->progress = false;
- rxtid->timerMon = false;
- A_NETBUF_QUEUE_INIT(&rxtid->q);
- A_MUTEX_INIT(&rxtid->lock);
- }
- }while(false);
-
- A_PRINTF("going out of aggr_init..status %s\n",
- (status == 0) ? "OK":"Error");
-
- if (status) {
- /* Cleanup */
- aggr_module_destroy(p_aggr);
- }
- return ((status == 0) ? p_aggr : NULL);
-}
-
-/* utility function to clear rx hold_q for a tid */
-static void
-aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid)
-{
- struct rxtid *rxtid;
- struct rxtid_stats *stats;
-
- A_ASSERT(tid < NUM_OF_TIDS && p_aggr);
-
- rxtid = AGGR_GET_RXTID(p_aggr, tid);
- stats = AGGR_GET_RXTID_STATS(p_aggr, tid);
-
- if(rxtid->aggr) {
- aggr_deque_frms(p_aggr, tid, 0, ALL_SEQNO);
- }
-
- rxtid->aggr = false;
- rxtid->progress = false;
- rxtid->timerMon = false;
- rxtid->win_sz = 0;
- rxtid->seq_next = 0;
- rxtid->hold_q_sz = 0;
-
- if(rxtid->hold_q) {
- kfree(rxtid->hold_q);
- rxtid->hold_q = NULL;
- }
-
- A_MEMZERO(stats, sizeof(struct rxtid_stats));
-}
-
-void
-aggr_module_destroy(void *cntxt)
-{
- struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
- struct rxtid *rxtid;
- u8 i, k;
- A_PRINTF("%s(): aggr = %p\n",_A_FUNCNAME_, p_aggr);
- A_ASSERT(p_aggr);
-
- if(p_aggr) {
- if(p_aggr->timerScheduled) {
- A_UNTIMEOUT(&p_aggr->timer);
- p_aggr->timerScheduled = false;
- }
-
- for(i = 0; i < NUM_OF_TIDS; i++) {
- rxtid = AGGR_GET_RXTID(p_aggr, i);
- /* Free the hold q contents and hold_q*/
- if(rxtid->hold_q) {
- for(k = 0; k< rxtid->hold_q_sz; k++) {
- if(rxtid->hold_q[k].osbuf) {
- A_NETBUF_FREE(rxtid->hold_q[k].osbuf);
- }
- }
- kfree(rxtid->hold_q);
- }
- /* Free the dispatch q contents*/
- while(A_NETBUF_QUEUE_SIZE(&rxtid->q)) {
- A_NETBUF_FREE(A_NETBUF_DEQUEUE(&rxtid->q));
- }
- if (A_IS_MUTEX_VALID(&rxtid->lock)) {
- A_MUTEX_DELETE(&rxtid->lock);
- }
- }
- /* free the freeQ and its contents*/
- while(A_NETBUF_QUEUE_SIZE(&p_aggr->freeQ)) {
- A_NETBUF_FREE(A_NETBUF_DEQUEUE(&p_aggr->freeQ));
- }
- kfree(p_aggr);
- }
- A_PRINTF("out aggr_module_destroy\n");
-}
-
-
-void
-aggr_register_rx_dispatcher(void *cntxt, void * dev, RX_CALLBACK fn)
-{
- struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
-
- A_ASSERT(p_aggr && fn && dev);
-
- p_aggr->rx_fn = fn;
- p_aggr->dev = dev;
-}
-
-
-void
-aggr_process_bar(void *cntxt, u8 tid, u16 seq_no)
-{
- struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
- struct rxtid_stats *stats;
-
- A_ASSERT(p_aggr);
- stats = AGGR_GET_RXTID_STATS(p_aggr, tid);
- stats->num_bar++;
-
- aggr_deque_frms(p_aggr, tid, seq_no, ALL_SEQNO);
-}
-
-
-void
-aggr_recv_addba_req_evt(void *cntxt, u8 tid, u16 seq_no, u8 win_sz)
-{
- struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
- struct rxtid *rxtid;
- struct rxtid_stats *stats;
-
- A_ASSERT(p_aggr);
- rxtid = AGGR_GET_RXTID(p_aggr, tid);
- stats = AGGR_GET_RXTID_STATS(p_aggr, tid);
-
- A_PRINTF("%s(): win_sz = %d aggr %d\n", _A_FUNCNAME_, win_sz, rxtid->aggr);
- if(win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) {
- A_PRINTF("win_sz %d, tid %d\n", win_sz, tid);
- }
-
- if(rxtid->aggr) {
- /* Just go and deliver all the frames up from this
- * queue, as if we got DELBA and re-initialize the queue
- */
- aggr_delete_tid_state(p_aggr, tid);
- }
-
- rxtid->seq_next = seq_no;
- /* create these queues, only upon receiving of ADDBA for a
- * tid, reducing memory requirement
- */
- rxtid->hold_q = A_MALLOC(HOLD_Q_SZ(win_sz));
- if((rxtid->hold_q == NULL)) {
- A_PRINTF("Failed to allocate memory, tid = %d\n", tid);
- A_ASSERT(0);
- }
- A_MEMZERO(rxtid->hold_q, HOLD_Q_SZ(win_sz));
-
- /* Update rxtid for the window sz */
- rxtid->win_sz = win_sz;
- /* hold_q_sz inicates the depth of holding q - which is
- * a factor of win_sz. Compute once, as it will be used often
- */
- rxtid->hold_q_sz = TID_WINDOW_SZ(win_sz);
- /* There should be no frames on q - even when second ADDBA comes in.
- * If aggr was previously ON on this tid, we would have cleaned up
- * the q
- */
- if(A_NETBUF_QUEUE_SIZE(&rxtid->q) != 0) {
- A_PRINTF("ERROR: Frames still on queue ?\n");
- A_ASSERT(0);
- }
-
- rxtid->aggr = true;
-}
-
-void
-aggr_recv_delba_req_evt(void *cntxt, u8 tid)
-{
- struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
- struct rxtid *rxtid;
-
- A_ASSERT(p_aggr);
- A_PRINTF("%s(): tid %d\n", _A_FUNCNAME_, tid);
-
- rxtid = AGGR_GET_RXTID(p_aggr, tid);
-
- if(rxtid->aggr) {
- aggr_delete_tid_state(p_aggr, tid);
- }
-}
-
-static void
-aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, u16 seq_no, u8 order)
-{
- struct rxtid *rxtid;
- struct osbuf_hold_q *node;
- u16 idx, idx_end, seq_end;
- struct rxtid_stats *stats;
-
- A_ASSERT(p_aggr);
- rxtid = AGGR_GET_RXTID(p_aggr, tid);
- stats = AGGR_GET_RXTID_STATS(p_aggr, tid);
-
- /* idx is absolute location for first frame */
- idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
-
- /* idx_end is typically the last possible frame in the window,
- * but changes to 'the' seq_no, when BAR comes. If seq_no
- * is non-zero, we will go up to that and stop.
- * Note: last seq no in current window will occupy the same
- * index position as index that is just previous to start.
- * An imp point : if win_sz is 7, for seq_no space of 4095,
- * then, there would be holes when sequence wrap around occurs.
- * Target should judiciously choose the win_sz, based on
- * this condition. For 4095, (TID_WINDOW_SZ = 2 x win_sz
- * 2, 4, 8, 16 win_sz works fine).
- * We must deque from "idx" to "idx_end", including both.
- */
- seq_end = (seq_no) ? seq_no : rxtid->seq_next;
- idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz);
-
- /* Critical section begins */
- A_MUTEX_LOCK(&rxtid->lock);
- do {
-
- node = &rxtid->hold_q[idx];
-
- if((order == CONTIGUOUS_SEQNO) && (!node->osbuf))
- break;
-
- /* chain frames and deliver frames bcos:
- * 1. either the frames are in order and window is contiguous, OR
- * 2. we need to deque frames, irrespective of holes
- */
- if(node->osbuf) {
- if(node->is_amsdu) {
- aggr_slice_amsdu(p_aggr, rxtid, &node->osbuf);
- } else {
- A_NETBUF_ENQUEUE(&rxtid->q, node->osbuf);
- }
- node->osbuf = NULL;
- } else {
- stats->num_hole++;
- }
-
- /* window is moving */
- rxtid->seq_next = IEEE80211_NEXT_SEQ_NO(rxtid->seq_next);
- idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
- } while(idx != idx_end);
- /* Critical section ends */
- A_MUTEX_UNLOCK(&rxtid->lock);
-
- stats->num_delivered += A_NETBUF_QUEUE_SIZE(&rxtid->q);
- aggr_dispatch_frames(p_aggr, &rxtid->q);
-}
-
-static void *
-aggr_get_osbuf(struct aggr_info *p_aggr)
-{
- void *buf = NULL;
-
- /* Starving for buffers? get more from OS
- * check for low netbuffers( < 1/4 AGGR_NUM_OF_FREE_NETBUFS) :
- * re-allocate bufs if so
- * allocate a free buf from freeQ
- */
- if (A_NETBUF_QUEUE_SIZE(&p_aggr->freeQ) < (AGGR_NUM_OF_FREE_NETBUFS >> 2)) {
- p_aggr->netbuf_allocator(&p_aggr->freeQ, AGGR_NUM_OF_FREE_NETBUFS);
- }
-
- if (A_NETBUF_QUEUE_SIZE(&p_aggr->freeQ)) {
- buf = A_NETBUF_DEQUEUE(&p_aggr->freeQ);
- }
-
- return buf;
-}
-
-
-static void
-aggr_slice_amsdu(struct aggr_info *p_aggr, struct rxtid *rxtid, void **osbuf)
-{
- void *new_buf;
- u16 frame_8023_len, payload_8023_len, mac_hdr_len, amsdu_len;
- u8 *framep;
-
- /* Frame format at this point:
- * [DIX hdr | 802.3 | 802.3 | ... | 802.3]
- *
- * Strip the DIX header.
- * Iterate through the osbuf and do:
- * grab a free netbuf from freeQ
- * find the start and end of a frame
- * copy it to netbuf(Vista can do better here)
- * convert all msdu's(802.3) frames to upper layer format - os routine
- * -for now lets convert from 802.3 to dix
- * enque this to dispatch q of tid
- * repeat
- * free the osbuf - to OS. It's been sliced.
- */
-
- mac_hdr_len = sizeof(ATH_MAC_HDR);
- framep = A_NETBUF_DATA(*osbuf) + mac_hdr_len;
- amsdu_len = A_NETBUF_LEN(*osbuf) - mac_hdr_len;
-
- while(amsdu_len > mac_hdr_len) {
- /* Begin of a 802.3 frame */
- payload_8023_len = A_BE2CPU16(((ATH_MAC_HDR *)framep)->typeOrLen);
-#define MAX_MSDU_SUBFRAME_PAYLOAD_LEN 1508
-#define MIN_MSDU_SUBFRAME_PAYLOAD_LEN 46
- if(payload_8023_len < MIN_MSDU_SUBFRAME_PAYLOAD_LEN || payload_8023_len > MAX_MSDU_SUBFRAME_PAYLOAD_LEN) {
- A_PRINTF("802.3 AMSDU frame bound check failed. len %d\n", payload_8023_len);
- break;
- }
- frame_8023_len = payload_8023_len + mac_hdr_len;
- new_buf = aggr_get_osbuf(p_aggr);
- if(new_buf == NULL) {
- A_PRINTF("No buffer available \n");
- break;
- }
-
- memcpy(A_NETBUF_DATA(new_buf), framep, frame_8023_len);
- A_NETBUF_PUT(new_buf, frame_8023_len);
- if (wmi_dot3_2_dix(new_buf) != 0) {
- A_PRINTF("dot3_2_dix err..\n");
- A_NETBUF_FREE(new_buf);
- break;
- }
-
- A_NETBUF_ENQUEUE(&rxtid->q, new_buf);
-
- /* Is this the last subframe within this aggregate ? */
- if ((amsdu_len - frame_8023_len) == 0) {
- break;
- }
-
- /* Add the length of A-MSDU subframe padding bytes -
- * Round to nearest word.
- */
- frame_8023_len = ((frame_8023_len + 3) & ~3);
-
- framep += frame_8023_len;
- amsdu_len -= frame_8023_len;
- }
-
- A_NETBUF_FREE(*osbuf);
- *osbuf = NULL;
-}
-
-void
-aggr_process_recv_frm(void *cntxt, u8 tid, u16 seq_no, bool is_amsdu, void **osbuf)
-{
- struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
- struct rxtid *rxtid;
- struct rxtid_stats *stats;
- u16 idx, st, cur, end;
- u16 *log_idx;
- struct osbuf_hold_q *node;
- PACKET_LOG *log;
-
- A_ASSERT(p_aggr);
- A_ASSERT(tid < NUM_OF_TIDS);
-
- rxtid = AGGR_GET_RXTID(p_aggr, tid);
- stats = AGGR_GET_RXTID_STATS(p_aggr, tid);
-
- stats->num_into_aggr++;
-
- if(!rxtid->aggr) {
- if(is_amsdu) {
- aggr_slice_amsdu(p_aggr, rxtid, osbuf);
- stats->num_amsdu++;
- aggr_dispatch_frames(p_aggr, &rxtid->q);
- }
- return;
- }
-
- /* Check the incoming sequence no, if it's in the window */
- st = rxtid->seq_next;
- cur = seq_no;
- end = (st + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO;
- /* Log the pkt info for future analysis */
- log = &p_aggr->pkt_log;
- log_idx = &log->last_idx;
- log->info[*log_idx].cur = cur;
- log->info[*log_idx].st = st;
- log->info[*log_idx].end = end;
- *log_idx = IEEE80211_NEXT_SEQ_NO(*log_idx);
-
- if(((st < end) && (cur < st || cur > end)) ||
- ((st > end) && (cur > end) && (cur < st))) {
- /* the cur frame is outside the window. Since we know
- * our target would not do this without reason it must
- * be assumed that the window has moved for some valid reason.
- * Therefore, we dequeue all frames and start fresh.
- */
- u16 extended_end;
-
- extended_end = (end + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO;
-
- if(((end < extended_end) && (cur < end || cur > extended_end)) ||
- ((end > extended_end) && (cur > extended_end) && (cur < end))) {
- // dequeue all frames in queue and shift window to new frame
- aggr_deque_frms(p_aggr, tid, 0, ALL_SEQNO);
- //set window start so that new frame is last frame in window
- if(cur >= rxtid->hold_q_sz-1) {
- rxtid->seq_next = cur - (rxtid->hold_q_sz-1);
- }else{
- rxtid->seq_next = IEEE80211_MAX_SEQ_NO - (rxtid->hold_q_sz-2 - cur);
- }
- } else {
- // dequeue only those frames that are outside the new shifted window
- if(cur >= rxtid->hold_q_sz-1) {
- st = cur - (rxtid->hold_q_sz-1);
- }else{
- st = IEEE80211_MAX_SEQ_NO - (rxtid->hold_q_sz-2 - cur);
- }
-
- aggr_deque_frms(p_aggr, tid, st, ALL_SEQNO);
- }
-
- stats->num_oow++;
- }
-
- idx = AGGR_WIN_IDX(seq_no, rxtid->hold_q_sz);
-
- /*enque the frame, in hold_q */
- node = &rxtid->hold_q[idx];
-
- A_MUTEX_LOCK(&rxtid->lock);
- if(node->osbuf) {
- /* Is the cur frame duplicate or something beyond our
- * window(hold_q -> which is 2x, already)?
- * 1. Duplicate is easy - drop incoming frame.
- * 2. Not falling in current sliding window.
- * 2a. is the frame_seq_no preceding current tid_seq_no?
- * -> drop the frame. perhaps sender did not get our ACK.
- * this is taken care of above.
- * 2b. is the frame_seq_no beyond window(st, TID_WINDOW_SZ);
- * -> Taken care of it above, by moving window forward.
- *
- */
- A_NETBUF_FREE(node->osbuf);
- stats->num_dups++;
- }
-
- node->osbuf = *osbuf;
- node->is_amsdu = is_amsdu;
- node->seq_no = seq_no;
- if(node->is_amsdu) {
- stats->num_amsdu++;
- } else {
- stats->num_mpdu++;
- }
- A_MUTEX_UNLOCK(&rxtid->lock);
-
- *osbuf = NULL;
- aggr_deque_frms(p_aggr, tid, 0, CONTIGUOUS_SEQNO);
-
- if(p_aggr->timerScheduled) {
- rxtid->progress = true;
- }else{
- for(idx=0 ; idx<rxtid->hold_q_sz ; idx++) {
- if(rxtid->hold_q[idx].osbuf) {
- /* there is a frame in the queue and no timer so
- * start a timer to ensure that the frame doesn't remain
- * stuck forever. */
- p_aggr->timerScheduled = true;
- A_TIMEOUT_MS(&p_aggr->timer, AGGR_RX_TIMEOUT, 0);
- rxtid->progress = false;
- rxtid->timerMon = true;
- break;
- }
- }
- }
-}
-
-/*
- * aggr_reset_state -- Called when it is deemed necessary to clear the aggregate
- * hold Q state. Examples include when a Connect event or disconnect event is
- * received.
- */
-void
-aggr_reset_state(void *cntxt)
-{
- u8 tid;
- struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
-
- A_ASSERT(p_aggr);
-
- for(tid=0 ; tid<NUM_OF_TIDS ; tid++) {
- aggr_delete_tid_state(p_aggr, tid);
- }
-}
-
-
-static void
-aggr_timeout(unsigned long arg)
-{
- u8 i,j;
- struct aggr_info *p_aggr = (struct aggr_info *)arg;
- struct rxtid *rxtid;
- struct rxtid_stats *stats;
- /*
- * If the q for which the timer was originally started has
- * not progressed then it is necessary to dequeue all the
- * contained frames so that they are not held forever.
- */
- for(i = 0; i < NUM_OF_TIDS; i++) {
- rxtid = AGGR_GET_RXTID(p_aggr, i);
- stats = AGGR_GET_RXTID_STATS(p_aggr, i);
-
- if(rxtid->aggr == false ||
- rxtid->timerMon == false ||
- rxtid->progress == true) {
- continue;
- }
- // dequeue all frames in for this tid
- stats->num_timeouts++;
- A_PRINTF("TO: st %d end %d\n", rxtid->seq_next, ((rxtid->seq_next + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO));
- aggr_deque_frms(p_aggr, i, 0, ALL_SEQNO);
- }
-
- p_aggr->timerScheduled = false;
- // determine whether a new timer should be started.
- for(i = 0; i < NUM_OF_TIDS; i++) {
- rxtid = AGGR_GET_RXTID(p_aggr, i);
-
- if(rxtid->aggr == true && rxtid->hold_q) {
- for(j = 0 ; j < rxtid->hold_q_sz ; j++)
- {
- if(rxtid->hold_q[j].osbuf)
- {
- p_aggr->timerScheduled = true;
- rxtid->timerMon = true;
- rxtid->progress = false;
- break;
- }
- }
-
- if(j >= rxtid->hold_q_sz) {
- rxtid->timerMon = false;
- }
- }
- }
-
- if(p_aggr->timerScheduled) {
- /* Rearm the timer*/
- A_TIMEOUT_MS(&p_aggr->timer, AGGR_RX_TIMEOUT, 0);
- }
-
-}
-
-static void
-aggr_dispatch_frames(struct aggr_info *p_aggr, A_NETBUF_QUEUE_T *q)
-{
- void *osbuf;
-
- while((osbuf = A_NETBUF_DEQUEUE(q))) {
- p_aggr->rx_fn(p_aggr->dev, osbuf);
- }
-}
-
-void
-aggr_dump_stats(void *cntxt, PACKET_LOG **log_buf)
-{
- struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
- struct rxtid *rxtid;
- struct rxtid_stats *stats;
- u8 i;
-
- *log_buf = &p_aggr->pkt_log;
- A_PRINTF("\n\n================================================\n");
- A_PRINTF("tid: num_into_aggr, dups, oow, mpdu, amsdu, delivered, timeouts, holes, bar, seq_next\n");
- for(i = 0; i < NUM_OF_TIDS; i++) {
- stats = AGGR_GET_RXTID_STATS(p_aggr, i);
- rxtid = AGGR_GET_RXTID(p_aggr, i);
- A_PRINTF("%d: %d %d %d %d %d %d %d %d %d : %d\n", i, stats->num_into_aggr, stats->num_dups,
- stats->num_oow, stats->num_mpdu,
- stats->num_amsdu, stats->num_delivered, stats->num_timeouts,
- stats->num_hole, stats->num_bar,
- rxtid->seq_next);
- }
- A_PRINTF("================================================\n\n");
-
-}
diff --git a/drivers/staging/ath6kl/wlan/include/ieee80211.h b/drivers/staging/ath6kl/wlan/include/ieee80211.h
deleted file mode 100644
index cf47d0657e70..000000000000
--- a/drivers/staging/ath6kl/wlan/include/ieee80211.h
+++ /dev/null
@@ -1,397 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="ieee80211.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _NET80211_IEEE80211_H_
-#define _NET80211_IEEE80211_H_
-
-/*
- * 802.11 protocol definitions.
- */
-#define IEEE80211_WEP_KEYLEN 5 /* 40bit */
-#define IEEE80211_WEP_IVLEN 3 /* 24bit */
-#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */
-#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */
-#define IEEE80211_WEP_NKID 4 /* number of key ids */
-
-/*
- * 802.11i defines an extended IV for use with non-WEP ciphers.
- * When the EXTIV bit is set in the key id byte an additional
- * 4 bytes immediately follow the IV for TKIP. For CCMP the
- * EXTIV bit is likewise set but the 8 bytes represent the
- * CCMP header rather than IV+extended-IV.
- */
-#define IEEE80211_WEP_EXTIV 0x20
-#define IEEE80211_WEP_EXTIVLEN 4 /* extended IV length */
-#define IEEE80211_WEP_MICLEN 8 /* trailing MIC */
-
-#define IEEE80211_CRC_LEN 4
-
-#ifdef WAPI_ENABLE
-#define IEEE80211_WAPI_EXTIVLEN 10 /* extended IV length */
-#endif /* WAPI ENABLE */
-
-
-#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */
-/* is 802.11 address multicast/broadcast? */
-#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01)
-#define IEEE80211_IS_BROADCAST(_a) (*(_a) == 0xFF)
-#define WEP_HEADER (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
-#define WEP_TRAILER IEEE80211_WEP_CRCLEN
-#define CCMP_HEADER (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + \
- IEEE80211_WEP_EXTIVLEN)
-#define CCMP_TRAILER IEEE80211_WEP_MICLEN
-#define TKIP_HEADER (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + \
- IEEE80211_WEP_EXTIVLEN)
-#define TKIP_TRAILER IEEE80211_WEP_CRCLEN
-#define TKIP_MICLEN IEEE80211_WEP_MICLEN
-
-
-#define IEEE80211_ADDR_EQ(addr1, addr2) \
- (memcmp(addr1, addr2, IEEE80211_ADDR_LEN) == 0)
-
-#define IEEE80211_ADDR_COPY(dst,src) memcpy(dst,src,IEEE80211_ADDR_LEN)
-
-#define IEEE80211_KEYBUF_SIZE 16
-#define IEEE80211_MICBUF_SIZE (8+8) /* space for both tx and rx */
-
-/*
- * NB: these values are ordered carefully; there are lots of
- * of implications in any reordering. In particular beware
- * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY.
- */
-#define IEEE80211_CIPHER_WEP 0
-#define IEEE80211_CIPHER_TKIP 1
-#define IEEE80211_CIPHER_AES_OCB 2
-#define IEEE80211_CIPHER_AES_CCM 3
-#define IEEE80211_CIPHER_CKIP 5
-#define IEEE80211_CIPHER_CCKM_KRK 6
-#define IEEE80211_CIPHER_NONE 7 /* pseudo value */
-
-#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1)
-
-#define IEEE80211_IS_VALID_WEP_CIPHER_LEN(len) \
- (((len) == 5) || ((len) == 13) || ((len) == 16))
-
-
-
-/*
- * generic definitions for IEEE 802.11 frames
- */
-PREPACK struct ieee80211_frame {
- u8 i_fc[2];
- u8 i_dur[2];
- u8 i_addr1[IEEE80211_ADDR_LEN];
- u8 i_addr2[IEEE80211_ADDR_LEN];
- u8 i_addr3[IEEE80211_ADDR_LEN];
- u8 i_seq[2];
- /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
- /* see below */
-} POSTPACK;
-
-PREPACK struct ieee80211_qosframe {
- u8 i_fc[2];
- u8 i_dur[2];
- u8 i_addr1[IEEE80211_ADDR_LEN];
- u8 i_addr2[IEEE80211_ADDR_LEN];
- u8 i_addr3[IEEE80211_ADDR_LEN];
- u8 i_seq[2];
- u8 i_qos[2];
-} POSTPACK;
-
-#define IEEE80211_FC0_VERSION_MASK 0x03
-#define IEEE80211_FC0_VERSION_SHIFT 0
-#define IEEE80211_FC0_VERSION_0 0x00
-#define IEEE80211_FC0_TYPE_MASK 0x0c
-#define IEEE80211_FC0_TYPE_SHIFT 2
-#define IEEE80211_FC0_TYPE_MGT 0x00
-#define IEEE80211_FC0_TYPE_CTL 0x04
-#define IEEE80211_FC0_TYPE_DATA 0x08
-
-#define IEEE80211_FC0_SUBTYPE_MASK 0xf0
-#define IEEE80211_FC0_SUBTYPE_SHIFT 4
-/* for TYPE_MGT */
-#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00
-#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10
-#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20
-#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30
-#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40
-#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50
-#define IEEE80211_FC0_SUBTYPE_BEACON 0x80
-#define IEEE80211_FC0_SUBTYPE_ATIM 0x90
-#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0
-#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0
-#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0
-/* for TYPE_CTL */
-#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0
-#define IEEE80211_FC0_SUBTYPE_RTS 0xb0
-#define IEEE80211_FC0_SUBTYPE_CTS 0xc0
-#define IEEE80211_FC0_SUBTYPE_ACK 0xd0
-#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0
-#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0
-/* for TYPE_DATA (bit combination) */
-#define IEEE80211_FC0_SUBTYPE_DATA 0x00
-#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10
-#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20
-#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30
-#define IEEE80211_FC0_SUBTYPE_NODATA 0x40
-#define IEEE80211_FC0_SUBTYPE_CFACK 0x50
-#define IEEE80211_FC0_SUBTYPE_CFPOLL 0x60
-#define IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70
-#define IEEE80211_FC0_SUBTYPE_QOS 0x80
-#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0
-
-#define IEEE80211_FC1_DIR_MASK 0x03
-#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */
-#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */
-#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */
-#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */
-
-#define IEEE80211_FC1_MORE_FRAG 0x04
-#define IEEE80211_FC1_RETRY 0x08
-#define IEEE80211_FC1_PWR_MGT 0x10
-#define IEEE80211_FC1_MORE_DATA 0x20
-#define IEEE80211_FC1_WEP 0x40
-#define IEEE80211_FC1_ORDER 0x80
-
-#define IEEE80211_SEQ_FRAG_MASK 0x000f
-#define IEEE80211_SEQ_FRAG_SHIFT 0
-#define IEEE80211_SEQ_SEQ_MASK 0xfff0
-#define IEEE80211_SEQ_SEQ_SHIFT 4
-
-#define IEEE80211_NWID_LEN 32
-
-/*
- * 802.11 rate set.
- */
-#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */
-#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */
-
-#define WMM_NUM_AC 4 /* 4 AC categories */
-
-#define WMM_PARAM_ACI_M 0x60 /* Mask for ACI field */
-#define WMM_PARAM_ACI_S 5 /* Shift for ACI field */
-#define WMM_PARAM_ACM_M 0x10 /* Mask for ACM bit */
-#define WMM_PARAM_ACM_S 4 /* Shift for ACM bit */
-#define WMM_PARAM_AIFSN_M 0x0f /* Mask for aifsn field */
-#define WMM_PARAM_LOGCWMIN_M 0x0f /* Mask for CwMin field (in log) */
-#define WMM_PARAM_LOGCWMAX_M 0xf0 /* Mask for CwMax field (in log) */
-#define WMM_PARAM_LOGCWMAX_S 4 /* Shift for CwMax field */
-
-#define WMM_AC_TO_TID(_ac) ( \
- ((_ac) == WMM_AC_VO) ? 6 : \
- ((_ac) == WMM_AC_VI) ? 5 : \
- ((_ac) == WMM_AC_BK) ? 1 : \
- 0)
-
-#define TID_TO_WMM_AC(_tid) ( \
- ((_tid) < 1) ? WMM_AC_BE : \
- ((_tid) < 3) ? WMM_AC_BK : \
- ((_tid) < 6) ? WMM_AC_VI : \
- WMM_AC_VO)
-/*
- * Management information element payloads.
- */
-
-enum {
- IEEE80211_ELEMID_SSID = 0,
- IEEE80211_ELEMID_RATES = 1,
- IEEE80211_ELEMID_FHPARMS = 2,
- IEEE80211_ELEMID_DSPARMS = 3,
- IEEE80211_ELEMID_CFPARMS = 4,
- IEEE80211_ELEMID_TIM = 5,
- IEEE80211_ELEMID_IBSSPARMS = 6,
- IEEE80211_ELEMID_COUNTRY = 7,
- IEEE80211_ELEMID_CHALLENGE = 16,
- /* 17-31 reserved for challenge text extension */
- IEEE80211_ELEMID_PWRCNSTR = 32,
- IEEE80211_ELEMID_PWRCAP = 33,
- IEEE80211_ELEMID_TPCREQ = 34,
- IEEE80211_ELEMID_TPCREP = 35,
- IEEE80211_ELEMID_SUPPCHAN = 36,
- IEEE80211_ELEMID_CHANSWITCH = 37,
- IEEE80211_ELEMID_MEASREQ = 38,
- IEEE80211_ELEMID_MEASREP = 39,
- IEEE80211_ELEMID_QUIET = 40,
- IEEE80211_ELEMID_IBSSDFS = 41,
- IEEE80211_ELEMID_ERP = 42,
- IEEE80211_ELEMID_HTCAP_ANA = 45, /* Address ANA, and non-ANA story, for interop. CL#171733 */
- IEEE80211_ELEMID_RSN = 48,
- IEEE80211_ELEMID_XRATES = 50,
- IEEE80211_ELEMID_HTINFO_ANA = 61,
-#ifdef WAPI_ENABLE
- IEEE80211_ELEMID_WAPI = 68,
-#endif
- IEEE80211_ELEMID_TPC = 150,
- IEEE80211_ELEMID_CCKM = 156,
- IEEE80211_ELEMID_VENDOR = 221, /* vendor private */
-};
-
-#define ATH_OUI 0x7f0300 /* Atheros OUI */
-#define ATH_OUI_TYPE 0x01
-#define ATH_OUI_SUBTYPE 0x01
-#define ATH_OUI_VERSION 0x00
-
-#define WPA_OUI 0xf25000
-#define WPA_OUI_TYPE 0x01
-#define WPA_VERSION 1 /* current supported version */
-
-#define WPA_CSE_NULL 0x00
-#define WPA_CSE_WEP40 0x01
-#define WPA_CSE_TKIP 0x02
-#define WPA_CSE_CCMP 0x04
-#define WPA_CSE_WEP104 0x05
-
-#define WPA_ASE_NONE 0x00
-#define WPA_ASE_8021X_UNSPEC 0x01
-#define WPA_ASE_8021X_PSK 0x02
-
-#define RSN_OUI 0xac0f00
-#define RSN_VERSION 1 /* current supported version */
-
-#define RSN_CSE_NULL 0x00
-#define RSN_CSE_WEP40 0x01
-#define RSN_CSE_TKIP 0x02
-#define RSN_CSE_WRAP 0x03
-#define RSN_CSE_CCMP 0x04
-#define RSN_CSE_WEP104 0x05
-
-#define RSN_ASE_NONE 0x00
-#define RSN_ASE_8021X_UNSPEC 0x01
-#define RSN_ASE_8021X_PSK 0x02
-
-#define RSN_CAP_PREAUTH 0x01
-
-#define WMM_OUI 0xf25000
-#define WMM_OUI_TYPE 0x02
-#define WMM_INFO_OUI_SUBTYPE 0x00
-#define WMM_PARAM_OUI_SUBTYPE 0x01
-#define WMM_VERSION 1
-
-/* WMM stream classes */
-#define WMM_NUM_AC 4
-#define WMM_AC_BE 0 /* best effort */
-#define WMM_AC_BK 1 /* background */
-#define WMM_AC_VI 2 /* video */
-#define WMM_AC_VO 3 /* voice */
-
-/* TSPEC related */
-#define ACTION_CATEGORY_CODE_TSPEC 17
-#define ACTION_CODE_TSPEC_ADDTS 0
-#define ACTION_CODE_TSPEC_ADDTS_RESP 1
-#define ACTION_CODE_TSPEC_DELTS 2
-
-typedef enum {
- TSPEC_STATUS_CODE_ADMISSION_ACCEPTED = 0,
- TSPEC_STATUS_CODE_ADDTS_INVALID_PARAMS = 0x1,
- TSPEC_STATUS_CODE_ADDTS_REQUEST_REFUSED = 0x3,
- TSPEC_STATUS_CODE_UNSPECIFIED_QOS_RELATED_FAILURE = 0xC8,
- TSPEC_STATUS_CODE_REQUESTED_REFUSED_POLICY_CONFIGURATION = 0xC9,
- TSPEC_STATUS_CODE_INSUFFCIENT_BANDWIDTH = 0xCA,
- TSPEC_STATUS_CODE_INVALID_PARAMS = 0xCB,
- TSPEC_STATUS_CODE_DELTS_SENT = 0x30,
- TSPEC_STATUS_CODE_DELTS_RECV = 0x31,
-} TSPEC_STATUS_CODE;
-
-#define TSPEC_TSID_MASK 0xF
-#define TSPEC_TSID_S 1
-
-/*
- * WMM/802.11e Tspec Element
- */
-typedef PREPACK struct wmm_tspec_ie_t {
- u8 elementId;
- u8 len;
- u8 oui[3];
- u8 ouiType;
- u8 ouiSubType;
- u8 version;
- u16 tsInfo_info;
- u8 tsInfo_reserved;
- u16 nominalMSDU;
- u16 maxMSDU;
- u32 minServiceInt;
- u32 maxServiceInt;
- u32 inactivityInt;
- u32 suspensionInt;
- u32 serviceStartTime;
- u32 minDataRate;
- u32 meanDataRate;
- u32 peakDataRate;
- u32 maxBurstSize;
- u32 delayBound;
- u32 minPhyRate;
- u16 sba;
- u16 mediumTime;
-} POSTPACK WMM_TSPEC_IE;
-
-
-/*
- * BEACON management packets
- *
- * octet timestamp[8]
- * octet beacon interval[2]
- * octet capability information[2]
- * information element
- * octet elemid
- * octet length
- * octet information[length]
- */
-
-#define IEEE80211_BEACON_INTERVAL(beacon) \
- ((beacon)[8] | ((beacon)[9] << 8))
-#define IEEE80211_BEACON_CAPABILITY(beacon) \
- ((beacon)[10] | ((beacon)[11] << 8))
-
-#define IEEE80211_CAPINFO_ESS 0x0001
-#define IEEE80211_CAPINFO_IBSS 0x0002
-#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004
-#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008
-#define IEEE80211_CAPINFO_PRIVACY 0x0010
-#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020
-#define IEEE80211_CAPINFO_PBCC 0x0040
-#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080
-/* bits 8-9 are reserved */
-#define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400
-#define IEEE80211_CAPINFO_APSD 0x0800
-/* bit 12 is reserved */
-#define IEEE80211_CAPINFO_DSSSOFDM 0x2000
-/* bits 14-15 are reserved */
-
-/*
- * Authentication Modes
- */
-
-enum ieee80211_authmode {
- IEEE80211_AUTH_NONE = 0,
- IEEE80211_AUTH_OPEN = 1,
- IEEE80211_AUTH_SHARED = 2,
- IEEE80211_AUTH_8021X = 3,
- IEEE80211_AUTH_AUTO = 4, /* auto-select/accept */
- /* NB: these are used only for ioctls */
- IEEE80211_AUTH_WPA = 5, /* WPA/RSN w/ 802.1x */
- IEEE80211_AUTH_WPA_PSK = 6, /* WPA/RSN w/ PSK */
- IEEE80211_AUTH_WPA_CCKM = 7, /* WPA/RSN IE w/ CCKM */
-};
-
-#define IEEE80211_PS_MAX_QUEUE 50 /*Maximum no of buffers that can be queues for PS*/
-
-#endif /* _NET80211_IEEE80211_H_ */
diff --git a/drivers/staging/ath6kl/wlan/include/ieee80211_node.h b/drivers/staging/ath6kl/wlan/include/ieee80211_node.h
deleted file mode 100644
index 1cb01671c0d3..000000000000
--- a/drivers/staging/ath6kl/wlan/include/ieee80211_node.h
+++ /dev/null
@@ -1,93 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="ieee80211_node.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _IEEE80211_NODE_H_
-#define _IEEE80211_NODE_H_
-
-/*
- * Node locking definitions.
- */
-#define IEEE80211_NODE_LOCK_INIT(_nt) A_MUTEX_INIT(&(_nt)->nt_nodelock)
-#define IEEE80211_NODE_LOCK_DESTROY(_nt) if (A_IS_MUTEX_VALID(&(_nt)->nt_nodelock)) { \
- A_MUTEX_DELETE(&(_nt)->nt_nodelock); }
-
-#define IEEE80211_NODE_LOCK(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock)
-#define IEEE80211_NODE_UNLOCK(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock)
-#define IEEE80211_NODE_LOCK_BH(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock)
-#define IEEE80211_NODE_UNLOCK_BH(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock)
-#define IEEE80211_NODE_LOCK_ASSERT(_nt)
-
-/*
- * Node reference counting definitions.
- *
- * ieee80211_node_initref initialize the reference count to 1
- * ieee80211_node_incref add a reference
- * ieee80211_node_decref remove a reference
- * ieee80211_node_dectestref remove a reference and return 1 if this
- * is the last reference, otherwise 0
- * ieee80211_node_refcnt reference count for printing (only)
- */
-#define ieee80211_node_initref(_ni) ((_ni)->ni_refcnt = 1)
-#define ieee80211_node_incref(_ni) ((_ni)->ni_refcnt++)
-#define ieee80211_node_decref(_ni) ((_ni)->ni_refcnt--)
-#define ieee80211_node_dectestref(_ni) (((_ni)->ni_refcnt--) == 1)
-#define ieee80211_node_refcnt(_ni) ((_ni)->ni_refcnt)
-
-#define IEEE80211_NODE_HASHSIZE 32
-/* simple hash is enough for variation of macaddr */
-#define IEEE80211_NODE_HASH(addr) \
- (((const u8 *)(addr))[IEEE80211_ADDR_LEN - 1] % \
- IEEE80211_NODE_HASHSIZE)
-
-/*
- * Table of ieee80211_node instances. Each ieee80211com
- * has at least one for holding the scan candidates.
- * When operating as an access point or in ibss mode there
- * is a second table for associated stations or neighbors.
- */
-struct ieee80211_node_table {
- void *nt_wmip; /* back reference */
- A_MUTEX_T nt_nodelock; /* on node table */
- struct bss *nt_node_first; /* information of all nodes */
- struct bss *nt_node_last; /* information of all nodes */
- struct bss *nt_hash[IEEE80211_NODE_HASHSIZE];
- const char *nt_name; /* for debugging */
- u32 nt_scangen; /* gen# for timeout scan */
-#ifdef THREAD_X
- A_TIMER nt_inact_timer;
- u8 isTimerArmed; /* is the node timer armed */
-#endif
- u32 nt_nodeAge; /* node aging time */
-#ifdef OS_ROAM_MANAGEMENT
- u32 nt_si_gen; /* gen# for scan indication*/
-#endif
-};
-
-#ifdef THREAD_X
-#define WLAN_NODE_INACT_TIMEOUT_MSEC 20000
-#else
-#define WLAN_NODE_INACT_TIMEOUT_MSEC 120000
-#endif
-
-#define WLAN_NODE_INACT_CNT 4
-
-#endif /* _IEEE80211_NODE_H_ */
diff --git a/drivers/staging/ath6kl/wlan/src/wlan_node.c b/drivers/staging/ath6kl/wlan/src/wlan_node.c
deleted file mode 100644
index 0fe5f4b1346c..000000000000
--- a/drivers/staging/ath6kl/wlan/src/wlan_node.c
+++ /dev/null
@@ -1,636 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="wlan_node.c" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// IEEE 802.11 node handling support.
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#include <a_config.h>
-#include <athdefs.h>
-#include <a_osapi.h>
-#define ATH_MODULE_NAME wlan
-#include <a_debug.h>
-#include "htc.h"
-#include "htc_api.h"
-#include <wmi.h>
-#include <ieee80211.h>
-#include <wlan_api.h>
-#include <wmi_api.h>
-#include <ieee80211_node.h>
-
-#define ATH_DEBUG_WLAN ATH_DEBUG_MAKE_MODULE_MASK(0)
-
-#ifdef ATH_DEBUG_MODULE
-
-static struct ath_debug_mask_description wlan_debug_desc[] = {
- { ATH_DEBUG_WLAN , "General WLAN Node Tracing"},
-};
-
-ATH_DEBUG_INSTANTIATE_MODULE_VAR(wlan,
- "wlan",
- "WLAN Node Management",
- ATH_DEBUG_MASK_DEFAULTS,
- ATH_DEBUG_DESCRIPTION_COUNT(wlan_debug_desc),
- wlan_debug_desc);
-
-#endif
-
-#ifdef THREAD_X
-static void wlan_node_timeout(unsigned long arg);
-#endif
-
-static bss_t * _ieee80211_find_node (struct ieee80211_node_table *nt,
- const u8 *macaddr);
-
-bss_t *
-wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size)
-{
- bss_t *ni;
-
- ni = A_MALLOC_NOWAIT(sizeof(bss_t));
-
- if (ni != NULL) {
- if (wh_size)
- {
- ni->ni_buf = A_MALLOC_NOWAIT(wh_size);
- if (ni->ni_buf == NULL) {
- kfree(ni);
- ni = NULL;
- return ni;
- }
- }
- } else {
- return ni;
- }
-
- /* Make sure our lists are clean */
- ni->ni_list_next = NULL;
- ni->ni_list_prev = NULL;
- ni->ni_hash_next = NULL;
- ni->ni_hash_prev = NULL;
-
- //
- // ni_scangen never initialized before and during suspend/resume of winmobile,
- // that some junk has been stored in this, due to this scan list didn't properly updated
- //
- ni->ni_scangen = 0;
-
-#ifdef OS_ROAM_MANAGEMENT
- ni->ni_si_gen = 0;
-#endif
-
- return ni;
-}
-
-void
-wlan_node_free(bss_t *ni)
-{
- if (ni->ni_buf != NULL) {
- kfree(ni->ni_buf);
- }
- kfree(ni);
-}
-
-void
-wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
- const u8 *macaddr)
-{
- int hash;
- u32 timeoutValue = 0;
-
- memcpy(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN);
- hash = IEEE80211_NODE_HASH (macaddr);
- ieee80211_node_initref (ni); /* mark referenced */
-
- timeoutValue = nt->nt_nodeAge;
-
- ni->ni_tstamp = A_GET_MS (0);
- ni->ni_actcnt = WLAN_NODE_INACT_CNT;
-
- IEEE80211_NODE_LOCK_BH(nt);
-
- /* Insert at the end of the node list */
- ni->ni_list_next = NULL;
- ni->ni_list_prev = nt->nt_node_last;
- if(nt->nt_node_last != NULL)
- {
- nt->nt_node_last->ni_list_next = ni;
- }
- nt->nt_node_last = ni;
- if(nt->nt_node_first == NULL)
- {
- nt->nt_node_first = ni;
- }
-
- /* Insert into the hash list i.e. the bucket */
- if((ni->ni_hash_next = nt->nt_hash[hash]) != NULL)
- {
- nt->nt_hash[hash]->ni_hash_prev = ni;
- }
- ni->ni_hash_prev = NULL;
- nt->nt_hash[hash] = ni;
-
-#ifdef THREAD_X
- if (!nt->isTimerArmed) {
- A_TIMEOUT_MS(&nt->nt_inact_timer, timeoutValue, 0);
- nt->isTimerArmed = true;
- }
-#endif
-
- IEEE80211_NODE_UNLOCK_BH(nt);
-}
-
-static bss_t *
-_ieee80211_find_node(struct ieee80211_node_table *nt,
- const u8 *macaddr)
-{
- bss_t *ni;
- int hash;
-
- IEEE80211_NODE_LOCK_ASSERT(nt);
-
- hash = IEEE80211_NODE_HASH(macaddr);
- for(ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) {
- if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
- ieee80211_node_incref(ni); /* mark referenced */
- return ni;
- }
- }
- return NULL;
-}
-
-bss_t *
-wlan_find_node(struct ieee80211_node_table *nt, const u8 *macaddr)
-{
- bss_t *ni;
-
- IEEE80211_NODE_LOCK(nt);
- ni = _ieee80211_find_node(nt, macaddr);
- IEEE80211_NODE_UNLOCK(nt);
- return ni;
-}
-
-/*
- * Reclaim a node. If this is the last reference count then
- * do the normal free work. Otherwise remove it from the node
- * table and mark it gone by clearing the back-reference.
- */
-void
-wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni)
-{
- IEEE80211_NODE_LOCK(nt);
-
- if(ni->ni_list_prev == NULL)
- {
- /* First in list so fix the list head */
- nt->nt_node_first = ni->ni_list_next;
- }
- else
- {
- ni->ni_list_prev->ni_list_next = ni->ni_list_next;
- }
-
- if(ni->ni_list_next == NULL)
- {
- /* Last in list so fix list tail */
- nt->nt_node_last = ni->ni_list_prev;
- }
- else
- {
- ni->ni_list_next->ni_list_prev = ni->ni_list_prev;
- }
-
- if(ni->ni_hash_prev == NULL)
- {
- /* First in list so fix the list head */
- int hash;
- hash = IEEE80211_NODE_HASH(ni->ni_macaddr);
- nt->nt_hash[hash] = ni->ni_hash_next;
- }
- else
- {
- ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next;
- }
-
- if(ni->ni_hash_next != NULL)
- {
- ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev;
- }
- wlan_node_free(ni);
-
- IEEE80211_NODE_UNLOCK(nt);
-}
-
-static void
-wlan_node_dec_free(bss_t *ni)
-{
- if (ieee80211_node_dectestref(ni)) {
- wlan_node_free(ni);
- }
-}
-
-void
-wlan_free_allnodes(struct ieee80211_node_table *nt)
-{
- bss_t *ni;
-
- while ((ni = nt->nt_node_first) != NULL) {
- wlan_node_reclaim(nt, ni);
- }
-}
-
-void
-wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
- void *arg)
-{
- bss_t *ni;
- u32 gen;
-
- gen = ++nt->nt_scangen;
-
- IEEE80211_NODE_LOCK(nt);
- for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
- if (ni->ni_scangen != gen) {
- ni->ni_scangen = gen;
- (void) ieee80211_node_incref(ni);
- (*f)(arg, ni);
- wlan_node_dec_free(ni);
- }
- }
- IEEE80211_NODE_UNLOCK(nt);
-}
-
-/*
- * Node table support.
- */
-void
-wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt)
-{
- int i;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WLAN, ("node table = 0x%lx\n", (unsigned long)nt));
- IEEE80211_NODE_LOCK_INIT(nt);
-
- A_REGISTER_MODULE_DEBUG_INFO(wlan);
-
- nt->nt_node_first = nt->nt_node_last = NULL;
- for(i = 0; i < IEEE80211_NODE_HASHSIZE; i++)
- {
- nt->nt_hash[i] = NULL;
- }
-
-#ifdef THREAD_X
- A_INIT_TIMER(&nt->nt_inact_timer, wlan_node_timeout, nt);
- nt->isTimerArmed = false;
-#endif
- nt->nt_wmip = wmip;
- nt->nt_nodeAge = WLAN_NODE_INACT_TIMEOUT_MSEC;
-
- //
- // nt_scangen never initialized before and during suspend/resume of winmobile,
- // that some junk has been stored in this, due to this scan list didn't properly updated
- //
- nt->nt_scangen = 0;
-
-#ifdef OS_ROAM_MANAGEMENT
- nt->nt_si_gen = 0;
-#endif
-}
-
-void
-wlan_set_nodeage(struct ieee80211_node_table *nt, u32 nodeAge)
-{
- nt->nt_nodeAge = nodeAge;
- return;
-}
-void
-wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt)
-{
-#ifdef THREAD_X
- bss_t *bss, *nextBss;
- u8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = false;
-
- wmi_get_current_bssid(nt->nt_wmip, myBssid);
-
- bss = nt->nt_node_first;
- while (bss != NULL)
- {
- nextBss = bss->ni_list_next;
- if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
- {
- /*
- * free up all but the current bss - if set
- */
- wlan_node_reclaim(nt, bss);
-
- }
- bss = nextBss;
- }
-#else
- bss_t *bss, *nextBss;
- u8 myBssid[IEEE80211_ADDR_LEN];
- u32 timeoutValue = 0;
- u32 now = A_GET_MS(0);
- timeoutValue = nt->nt_nodeAge;
-
- wmi_get_current_bssid(nt->nt_wmip, myBssid);
-
- bss = nt->nt_node_first;
- while (bss != NULL)
- {
- nextBss = bss->ni_list_next;
- if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
- {
-
- if (((now - bss->ni_tstamp) > timeoutValue) || --bss->ni_actcnt == 0)
- {
- /*
- * free up all but the current bss - if set
- */
- wlan_node_reclaim(nt, bss);
- }
- }
- bss = nextBss;
- }
-#endif
-}
-
-#ifdef THREAD_X
-static void
-wlan_node_timeout (unsigned long arg)
-{
- struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg;
- bss_t *bss, *nextBss;
- u8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = false;
- u32 timeoutValue = 0;
- u32 now = A_GET_MS(0);
-
- timeoutValue = nt->nt_nodeAge;
-
- wmi_get_current_bssid(nt->nt_wmip, myBssid);
-
- bss = nt->nt_node_first;
- while (bss != NULL)
- {
- nextBss = bss->ni_list_next;
- if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
- {
-
- if ((now - bss->ni_tstamp) > timeoutValue)
- {
- /*
- * free up all but the current bss - if set
- */
- wlan_node_reclaim(nt, bss);
- }
- else
- {
- /*
- * Re-arm timer, only when we have a bss other than
- * current bss AND it is not aged-out.
- */
- reArmTimer = true;
- }
- }
- bss = nextBss;
- }
-
- if (reArmTimer)
- A_TIMEOUT_MS (&nt->nt_inact_timer, timeoutValue, 0);
-
- nt->isTimerArmed = reArmTimer;
-}
-#endif
-
-void
-wlan_node_table_cleanup(struct ieee80211_node_table *nt)
-{
-#ifdef THREAD_X
- A_UNTIMEOUT(&nt->nt_inact_timer);
- A_DELETE_TIMER(&nt->nt_inact_timer);
-#endif
- wlan_free_allnodes(nt);
- IEEE80211_NODE_LOCK_DESTROY(nt);
-}
-
-bss_t *
-wlan_find_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
- u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
-{
- bss_t *ni = NULL;
- u8 *pIESsid = NULL;
-
- IEEE80211_NODE_LOCK (nt);
-
- for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
- pIESsid = ni->ni_cie.ie_ssid;
- if (pIESsid[1] <= 32) {
-
- // Step 1 : Check SSID
- if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) {
-
- //
- // Step 2.1 : Check MatchSSID is true, if so, return Matched SSID
- // Profile, otherwise check whether WPA2 or WPA
- //
- if (true == bMatchSSID) {
- ieee80211_node_incref (ni); /* mark referenced */
- IEEE80211_NODE_UNLOCK (nt);
- return ni;
- }
-
- // Step 2 : if SSID matches, check WPA or WPA2
- if (true == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) {
- ieee80211_node_incref (ni); /* mark referenced */
- IEEE80211_NODE_UNLOCK (nt);
- return ni;
- }
- if (false == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) {
- ieee80211_node_incref(ni); /* mark referenced */
- IEEE80211_NODE_UNLOCK (nt);
- return ni;
- }
- }
- }
- }
-
- IEEE80211_NODE_UNLOCK (nt);
-
- return NULL;
-}
-
-void
-wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni)
-{
- IEEE80211_NODE_LOCK (nt);
- wlan_node_dec_free (ni);
- IEEE80211_NODE_UNLOCK (nt);
-}
-
-void
-wlan_node_remove_core (struct ieee80211_node_table *nt, bss_t *ni)
-{
- if(ni->ni_list_prev == NULL)
- {
- /* First in list so fix the list head */
- nt->nt_node_first = ni->ni_list_next;
- }
- else
- {
- ni->ni_list_prev->ni_list_next = ni->ni_list_next;
- }
-
- if(ni->ni_list_next == NULL)
- {
- /* Last in list so fix list tail */
- nt->nt_node_last = ni->ni_list_prev;
- }
- else
- {
- ni->ni_list_next->ni_list_prev = ni->ni_list_prev;
- }
-
- if(ni->ni_hash_prev == NULL)
- {
- /* First in list so fix the list head */
- int hash;
- hash = IEEE80211_NODE_HASH(ni->ni_macaddr);
- nt->nt_hash[hash] = ni->ni_hash_next;
- }
- else
- {
- ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next;
- }
-
- if(ni->ni_hash_next != NULL)
- {
- ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev;
- }
-}
-
-bss_t *
-wlan_node_remove(struct ieee80211_node_table *nt, u8 *bssid)
-{
- bss_t *bss, *nextBss;
-
- IEEE80211_NODE_LOCK(nt);
-
- bss = nt->nt_node_first;
-
- while (bss != NULL)
- {
- nextBss = bss->ni_list_next;
-
- if (memcmp(bssid, bss->ni_macaddr, 6) == 0)
- {
- wlan_node_remove_core (nt, bss);
- IEEE80211_NODE_UNLOCK(nt);
- return bss;
- }
-
- bss = nextBss;
- }
-
- IEEE80211_NODE_UNLOCK(nt);
- return NULL;
-}
-
-bss_t *
-wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
- u32 ssidLength, u32 dot11AuthMode, u32 authMode,
- u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
-{
- bss_t *ni = NULL;
- bss_t *best_ni = NULL;
- u8 *pIESsid = NULL;
-
- IEEE80211_NODE_LOCK (nt);
-
- for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
- pIESsid = ni->ni_cie.ie_ssid;
- if (pIESsid[1] <= 32) {
-
- // Step 1 : Check SSID
- if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) {
-
- if (ni->ni_cie.ie_capInfo & 0x10)
- {
-
- if ((NULL != ni->ni_cie.ie_rsn) && (WPA2_PSK_AUTH == authMode))
- {
- /* WPA2 */
- if (NULL == best_ni)
- {
- best_ni = ni;
- }
- else if (ni->ni_rssi > best_ni->ni_rssi)
- {
- best_ni = ni;
- }
- }
- else if ((NULL != ni->ni_cie.ie_wpa) && (WPA_PSK_AUTH == authMode))
- {
- /* WPA */
- if (NULL == best_ni)
- {
- best_ni = ni;
- }
- else if (ni->ni_rssi > best_ni->ni_rssi)
- {
- best_ni = ni;
- }
- }
- else if (WEP_CRYPT == pairwiseCryptoType)
- {
- /* WEP */
- if (NULL == best_ni)
- {
- best_ni = ni;
- }
- else if (ni->ni_rssi > best_ni->ni_rssi)
- {
- best_ni = ni;
- }
- }
- }
- else
- {
- /* open AP */
- if ((OPEN_AUTH == authMode) && (NONE_CRYPT == pairwiseCryptoType))
- {
- if (NULL == best_ni)
- {
- best_ni = ni;
- }
- else if (ni->ni_rssi > best_ni->ni_rssi)
- {
- best_ni = ni;
- }
- }
- }
- }
- }
- }
-
- IEEE80211_NODE_UNLOCK (nt);
-
- return best_ni;
-}
-
diff --git a/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c b/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c
deleted file mode 100644
index 07b8313b16e8..000000000000
--- a/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c
+++ /dev/null
@@ -1,199 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="wlan_recv_beacon.c" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// IEEE 802.11 input handling.
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_osapi.h"
-#include <wmi.h>
-#include <ieee80211.h>
-#include <wlan_api.h>
-
-#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \
- if ((_len) < (_minlen)) { \
- return A_EINVAL; \
- } \
-} while (0)
-
-#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \
- if ((__elem) == NULL) { \
- return A_EINVAL; \
- } \
- if ((__elem)[1] > (__maxlen)) { \
- return A_EINVAL; \
- } \
-} while (0)
-
-
-/* unaligned little endian access */
-#define LE_READ_2(p) \
- ((u16) \
- ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8)))
-
-#define LE_READ_4(p) \
- ((u32) \
- ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \
- (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
-
-
-static int __inline
-iswpaoui(const u8 *frm)
-{
- return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
-}
-
-static int __inline
-iswmmoui(const u8 *frm)
-{
- return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
-}
-
-/* unused functions for now */
-#if 0
-static int __inline
-iswmmparam(const u8 *frm)
-{
- return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
-}
-
-static int __inline
-iswmminfo(const u8 *frm)
-{
- return frm[1] > 5 && frm[6] == WMM_INFO_OUI_SUBTYPE;
-}
-#endif
-
-static int __inline
-isatherosoui(const u8 *frm)
-{
- return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
-}
-
-static int __inline
-iswscoui(const u8 *frm)
-{
- return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI);
-}
-
-int
-wlan_parse_beacon(u8 *buf, int framelen, struct ieee80211_common_ie *cie)
-{
- u8 *frm, *efrm;
- u8 elemid_ssid = false;
-
- frm = buf;
- efrm = (u8 *) (frm + framelen);
-
- /*
- * beacon/probe response frame format
- * [8] time stamp
- * [2] beacon interval
- * [2] capability information
- * [tlv] ssid
- * [tlv] supported rates
- * [tlv] country information
- * [tlv] parameter set (FH/DS)
- * [tlv] erp information
- * [tlv] extended supported rates
- * [tlv] WMM
- * [tlv] WPA or RSN
- * [tlv] Atheros Advanced Capabilities
- */
- IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
- A_MEMZERO(cie, sizeof(*cie));
-
- cie->ie_tstamp = frm; frm += 8;
- cie->ie_beaconInt = A_LE2CPU16(*(u16 *)frm); frm += 2;
- cie->ie_capInfo = A_LE2CPU16(*(u16 *)frm); frm += 2;
- cie->ie_chan = 0;
-
- while (frm < efrm) {
- switch (*frm) {
- case IEEE80211_ELEMID_SSID:
- if (!elemid_ssid) {
- cie->ie_ssid = frm;
- elemid_ssid = true;
- }
- break;
- case IEEE80211_ELEMID_RATES:
- cie->ie_rates = frm;
- break;
- case IEEE80211_ELEMID_COUNTRY:
- cie->ie_country = frm;
- break;
- case IEEE80211_ELEMID_FHPARMS:
- break;
- case IEEE80211_ELEMID_DSPARMS:
- cie->ie_chan = frm[2];
- break;
- case IEEE80211_ELEMID_TIM:
- cie->ie_tim = frm;
- break;
- case IEEE80211_ELEMID_IBSSPARMS:
- break;
- case IEEE80211_ELEMID_XRATES:
- cie->ie_xrates = frm;
- break;
- case IEEE80211_ELEMID_ERP:
- if (frm[1] != 1) {
- //A_PRINTF("Discarding ERP Element - Bad Len\n");
- return A_EINVAL;
- }
- cie->ie_erp = frm[2];
- break;
- case IEEE80211_ELEMID_RSN:
- cie->ie_rsn = frm;
- break;
- case IEEE80211_ELEMID_HTCAP_ANA:
- cie->ie_htcap = frm;
- break;
- case IEEE80211_ELEMID_HTINFO_ANA:
- cie->ie_htop = frm;
- break;
-#ifdef WAPI_ENABLE
- case IEEE80211_ELEMID_WAPI:
- cie->ie_wapi = frm;
- break;
-#endif
- case IEEE80211_ELEMID_VENDOR:
- if (iswpaoui(frm)) {
- cie->ie_wpa = frm;
- } else if (iswmmoui(frm)) {
- cie->ie_wmm = frm;
- } else if (isatherosoui(frm)) {
- cie->ie_ath = frm;
- } else if(iswscoui(frm)) {
- cie->ie_wsc = frm;
- }
- break;
- default:
- break;
- }
- frm += frm[1] + 2;
- }
- IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE);
- IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN);
-
- return 0;
-}
diff --git a/drivers/staging/ath6kl/wlan/src/wlan_utils.c b/drivers/staging/ath6kl/wlan/src/wlan_utils.c
deleted file mode 100644
index bc91599d9bf6..000000000000
--- a/drivers/staging/ath6kl/wlan/src/wlan_utils.c
+++ /dev/null
@@ -1,58 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="wlan_utils.c" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 module implements frequently used wlan utilies
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#include <a_config.h>
-#include <athdefs.h>
-#include <a_osapi.h>
-
-/*
- * converts ieee channel number to frequency
- */
-u16 wlan_ieee2freq(int chan)
-{
- if (chan == 14) {
- return 2484;
- }
- if (chan < 14) { /* 0-13 */
- return (2407 + (chan*5));
- }
- if (chan < 27) { /* 15-26 */
- return (2512 + ((chan-15)*20));
- }
- return (5000 + (chan*5));
-}
-
-/*
- * Converts MHz frequency to IEEE channel number.
- */
-u32 wlan_freq2ieee(u16 freq)
-{
- if (freq == 2484)
- return 14;
- if (freq < 2484)
- return (freq - 2407) / 5;
- if (freq < 5000)
- return 15 + ((freq - 2512) / 20);
- return (freq - 5000) / 5;
-}
diff --git a/drivers/staging/ath6kl/wmi/wmi.c b/drivers/staging/ath6kl/wmi/wmi.c
deleted file mode 100644
index c7b5e5cf9df7..000000000000
--- a/drivers/staging/ath6kl/wmi/wmi.c
+++ /dev/null
@@ -1,6444 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 module implements the hardware independent layer of the
-// Wireless Module Interface (WMI) protocol.
-//
-// Author(s): ="Atheros"
-//==============================================================================
-
-#include <a_config.h>
-#include <athdefs.h>
-#include <a_osapi.h>
-#include "htc.h"
-#include "htc_api.h"
-#include "wmi.h"
-#include <wlan_api.h>
-#include <wmi_api.h>
-#include <ieee80211.h>
-#include <ieee80211_node.h>
-#include "dset_api.h"
-#include "wmi_host.h"
-#include "a_drv.h"
-#include "a_drv_api.h"
-#define ATH_MODULE_NAME wmi
-#include "a_debug.h"
-#include "dbglog_api.h"
-#include "roaming.h"
-#include "cfg80211.h"
-
-#define ATH_DEBUG_WMI ATH_DEBUG_MAKE_MODULE_MASK(0)
-
-#ifdef ATH_DEBUG_MODULE
-
-static struct ath_debug_mask_description wmi_debug_desc[] = {
- { ATH_DEBUG_WMI , "General WMI Tracing"},
-};
-
-ATH_DEBUG_INSTANTIATE_MODULE_VAR(wmi,
- "wmi",
- "Wireless Module Interface",
- ATH_DEBUG_MASK_DEFAULTS,
- ATH_DEBUG_DESCRIPTION_COUNT(wmi_debug_desc),
- wmi_debug_desc);
-
-#endif
-
-#ifndef REXOS
-#define DBGARG _A_FUNCNAME_
-#define DBGFMT "%s() : "
-#define DBG_WMI ATH_DEBUG_WMI
-#define DBG_ERROR ATH_DEBUG_ERR
-#define DBG_WMI2 ATH_DEBUG_WMI
-#define A_DPRINTF AR_DEBUG_PRINTF
-#endif
-
-static int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len);
-
-static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-
-static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_sync_point(struct wmi_t *wmip);
-
-static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-
-static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-#ifdef CONFIG_HOST_DSET_SUPPORT
-static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-#endif /* CONFIG_HOST_DSET_SUPPORT */
-
-
-static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int
-wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
-
-static int
-wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
-
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-static int
-wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len);
-#endif
-
-static int
-wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
-
-static int
-wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
-
-static int
-wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
-
-static bool
-wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex);
-
-static int
-wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
-
-static int
-wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len);
-
-static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
-
-int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
- WMI_SYNC_FLAG syncflag);
-
-u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
-u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
-
-void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
-void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
-static int wmi_send_rssi_threshold_params(struct wmi_t *wmip,
- WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
-static int wmi_send_snr_threshold_params(struct wmi_t *wmip,
- WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
-#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-static int
-wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len);
-#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
-
-static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-
-static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap,
- int len);
-static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int);
-static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int);
-static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int);
-static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len);
-static int wmi_hci_event_rx(struct wmi_t *, u8 *, int);
-
-#ifdef WAPI_ENABLE
-static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,
- int len);
-#endif
-
-#if defined(UNDER_CE)
-#if defined(NDIS51_MINIPORT)
-unsigned int processDot11Hdr = 0;
-#else
-unsigned int processDot11Hdr = 1;
-#endif
-#else
-extern unsigned int processDot11Hdr;
-#endif
-
-int wps_enable;
-static const s32 wmi_rateTable[][2] = {
- //{W/O SGI, with SGI}
- {1000, 1000},
- {2000, 2000},
- {5500, 5500},
- {11000, 11000},
- {6000, 6000},
- {9000, 9000},
- {12000, 12000},
- {18000, 18000},
- {24000, 24000},
- {36000, 36000},
- {48000, 48000},
- {54000, 54000},
- {6500, 7200},
- {13000, 14400},
- {19500, 21700},
- {26000, 28900},
- {39000, 43300},
- {52000, 57800},
- {58500, 65000},
- {65000, 72200},
- {13500, 15000},
- {27000, 30000},
- {40500, 45000},
- {54000, 60000},
- {81000, 90000},
- {108000, 120000},
- {121500, 135000},
- {135000, 150000},
- {0, 0}};
-
-#define MODE_A_SUPPORT_RATE_START ((s32) 4)
-#define MODE_A_SUPPORT_RATE_STOP ((s32) 11)
-
-#define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START
-#define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP
-
-#define MODE_B_SUPPORT_RATE_START ((s32) 0)
-#define MODE_B_SUPPORT_RATE_STOP ((s32) 3)
-
-#define MODE_G_SUPPORT_RATE_START ((s32) 0)
-#define MODE_G_SUPPORT_RATE_STOP ((s32) 11)
-
-#define MODE_GHT20_SUPPORT_RATE_START ((s32) 0)
-#define MODE_GHT20_SUPPORT_RATE_STOP ((s32) 19)
-
-#define MAX_NUMBER_OF_SUPPORT_RATES (MODE_GHT20_SUPPORT_RATE_STOP + 1)
-
-/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
-const u8 up_to_ac[]= {
- WMM_AC_BE,
- WMM_AC_BK,
- WMM_AC_BK,
- WMM_AC_BE,
- WMM_AC_VI,
- WMM_AC_VI,
- WMM_AC_VO,
- WMM_AC_VO,
- };
-
-/* This stuff is used when we want a simple layer-3 visibility */
-typedef PREPACK struct _iphdr {
- u8 ip_ver_hdrlen; /* version and hdr length */
- u8 ip_tos; /* type of service */
- u16 ip_len; /* total length */
- u16 ip_id; /* identification */
- s16 ip_off; /* fragment offset field */
-#define IP_DF 0x4000 /* dont fragment flag */
-#define IP_MF 0x2000 /* more fragments flag */
-#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
- u8 ip_ttl; /* time to live */
- u8 ip_p; /* protocol */
- u16 ip_sum; /* checksum */
- u8 ip_src[4]; /* source and dest address */
- u8 ip_dst[4];
-} POSTPACK iphdr;
-
-static s16 rssi_event_value = 0;
-static s16 snr_event_value = 0;
-
-bool is_probe_ssid = false;
-
-void *
-wmi_init(void *devt)
-{
- struct wmi_t *wmip;
-
- A_REGISTER_MODULE_DEBUG_INFO(wmi);
-
- wmip = A_MALLOC (sizeof(struct wmi_t));
- if (wmip == NULL) {
- return (NULL);
- }
- A_MEMZERO(wmip, sizeof(struct wmi_t ));
-#ifdef THREAD_X
- INIT_WMI_LOCK(wmip);
-#else
- A_MUTEX_INIT(&wmip->wmi_lock);
-#endif
- wmip->wmi_devt = devt;
- wlan_node_table_init(wmip, &wmip->wmi_scan_table);
- wmi_qos_state_init(wmip);
-
- wmip->wmi_powerMode = REC_POWER;
- wmip->wmi_phyMode = WMI_11G_MODE;
-
- wmip->wmi_pair_crypto_type = NONE_CRYPT;
- wmip->wmi_grp_crypto_type = NONE_CRYPT;
-
- wmip->wmi_ht_allowed[A_BAND_24GHZ] = 1;
- wmip->wmi_ht_allowed[A_BAND_5GHZ] = 1;
-
- return (wmip);
-}
-
-void
-wmi_qos_state_init(struct wmi_t *wmip)
-{
- u8 i;
-
- if (wmip == NULL) {
- return;
- }
- LOCK_WMI(wmip);
-
- /* Initialize QoS States */
- wmip->wmi_numQoSStream = 0;
-
- wmip->wmi_fatPipeExists = 0;
-
- for (i=0; i < WMM_NUM_AC; i++) {
- wmip->wmi_streamExistsForAC[i]=0;
- }
-
- UNLOCK_WMI(wmip);
-
- A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1);
-}
-
-void
-wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid)
-{
- A_ASSERT( eid != ENDPOINT_UNUSED);
- wmip->wmi_endpoint_id = eid;
-}
-
-HTC_ENDPOINT_ID
-wmi_get_control_ep(struct wmi_t * wmip)
-{
- return(wmip->wmi_endpoint_id);
-}
-
-void
-wmi_shutdown(struct wmi_t *wmip)
-{
- if (wmip != NULL) {
- wlan_node_table_cleanup(&wmip->wmi_scan_table);
- if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) {
-#ifdef THREAD_X
- DELETE_WMI_LOCK(&wmip);
-#else
- A_MUTEX_DELETE(&wmip->wmi_lock);
-#endif
- }
- kfree(wmip);
- }
-}
-
-/*
- * performs DIX to 802.3 encapsulation for transmit packets.
- * uses passed in buffer. Returns buffer or NULL if failed.
- * Assumes the entire DIX header is contigous and that there is
- * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
- */
-int
-wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
-{
- u8 *datap;
- u16 typeorlen;
- ATH_MAC_HDR macHdr;
- ATH_LLC_SNAP_HDR *llcHdr;
-
- A_ASSERT(osbuf != NULL);
-
- if (A_NETBUF_HEADROOM(osbuf) <
- (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
- {
- return A_NO_MEMORY;
- }
-
- datap = A_NETBUF_DATA(osbuf);
-
- typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
-
- if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
- /*
- * packet is already in 802.3 format - return success
- */
- A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
- return (0);
- }
-
- /*
- * Save mac fields and length to be inserted later
- */
- memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
- memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
- macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
- sizeof(ATH_LLC_SNAP_HDR));
-
- /*
- * Make room for LLC+SNAP headers
- */
- if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
- return A_NO_MEMORY;
- }
- datap = A_NETBUF_DATA(osbuf);
-
- memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
-
- llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
- llcHdr->dsap = 0xAA;
- llcHdr->ssap = 0xAA;
- llcHdr->cntl = 0x03;
- llcHdr->orgCode[0] = 0x0;
- llcHdr->orgCode[1] = 0x0;
- llcHdr->orgCode[2] = 0x0;
- llcHdr->etherType = typeorlen;
-
- return (0);
-}
-
-int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS)
-{
- switch(*pVersion){
- case 0:
- return (0);
- case WMI_META_VERSION_1:
- {
- WMI_TX_META_V1 *pV1= NULL;
- A_ASSERT(osbuf != NULL);
- if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
- return A_NO_MEMORY;
- }
-
- pV1 = (WMI_TX_META_V1 *)A_NETBUF_DATA(osbuf);
- /* the pktID is used in conjunction with txComplete messages
- * allowing the target to notify which tx requests have been
- * completed and how. */
- pV1->pktID = 0;
- /* the ratePolicyID allows the host to specify which rate policy
- * to use for transmitting this packet. 0 means use default behavior. */
- pV1->ratePolicyID = 0;
- A_ASSERT(pVersion != NULL);
- /* the version must be used to populate the meta field of the WMI_DATA_HDR */
- *pVersion = WMI_META_VERSION_1;
- return (0);
- }
- case WMI_META_VERSION_2:
- {
- WMI_TX_META_V2 *pV2 ;
- A_ASSERT(osbuf != NULL);
- if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
- return A_NO_MEMORY;
- }
- pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf);
- memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
- return (0);
- }
- default:
- return (0);
- }
-}
-
-/* Adds a WMI data header */
-int
-wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData,
- WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS)
-{
- WMI_DATA_HDR *dtHdr;
-// u8 metaVersion = 0;
- int status;
-
- A_ASSERT(osbuf != NULL);
-
- /* adds the meta data field after the wmi data hdr. If metaVersion
- * is returns 0 then no meta field was added. */
- if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) {
- return status;
- }
-
- if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
- return A_NO_MEMORY;
- }
-
- dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
- A_MEMZERO(dtHdr, sizeof(WMI_DATA_HDR));
-
- WMI_DATA_HDR_SET_MSG_TYPE(dtHdr, msgType);
- WMI_DATA_HDR_SET_DATA_TYPE(dtHdr, data_type);
-
- if (bMoreData) {
- WMI_DATA_HDR_SET_MORE_BIT(dtHdr);
- }
-
- WMI_DATA_HDR_SET_META(dtHdr, metaVersion);
-
- dtHdr->info3 = 0;
-
- return (0);
-}
-
-
-u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled)
-{
- u8 *datap;
- u8 trafficClass = WMM_AC_BE;
- u16 ipType = IP_ETHERTYPE;
- WMI_DATA_HDR *dtHdr;
- u8 streamExists = 0;
- u8 userPriority;
- u32 hdrsize, metasize;
- ATH_LLC_SNAP_HDR *llcHdr;
-
- WMI_CREATE_PSTREAM_CMD cmd;
-
- A_ASSERT(osbuf != NULL);
-
- //
- // Initialize header size
- //
- hdrsize = 0;
-
- datap = A_NETBUF_DATA(osbuf);
- dtHdr = (WMI_DATA_HDR *)datap;
- metasize = (WMI_DATA_HDR_GET_META(dtHdr))? WMI_MAX_TX_META_SZ : 0;
-
- if (!wmmEnabled)
- {
- /* If WMM is disabled all traffic goes as BE traffic */
- userPriority = 0;
- }
- else
- {
- if (processDot11Hdr)
- {
- hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
- llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
- hdrsize);
-
-
- }
- else
- {
- llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
- sizeof(ATH_MAC_HDR));
- }
-
- if (llcHdr->etherType == A_CPU2BE16(ipType))
- {
- /* Extract the endpoint info from the TOS field in the IP header */
-
- userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority);
- }
- else
- {
- userPriority = layer2Priority & 0x7;
- }
- }
-
-
- /* workaround for WMM S5 */
- if ((WMM_AC_VI == wmip->wmi_traffic_class) && ((5 == userPriority) || (4 == userPriority)))
- {
- userPriority = 1;
- }
-
- trafficClass = convert_userPriority_to_trafficClass(userPriority);
-
- WMI_DATA_HDR_SET_UP(dtHdr, userPriority);
- /* lower 3-bits are 802.1d priority */
- //dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT;
-
- LOCK_WMI(wmip);
- streamExists = wmip->wmi_fatPipeExists;
- UNLOCK_WMI(wmip);
-
- if (!(streamExists & (1 << trafficClass)))
- {
-
- A_MEMZERO(&cmd, sizeof(cmd));
- cmd.trafficClass = trafficClass;
- cmd.userPriority = userPriority;
- cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT;
- /* Implicit streams are created with TSID 0xFF */
-
- cmd.tsid = WMI_IMPLICIT_PSTREAM;
- wmi_create_pstream_cmd(wmip, &cmd);
- }
-
- return trafficClass;
-}
-
-int
-wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
-{
- u8 *datap;
- u16 typeorlen;
- ATH_MAC_HDR macHdr;
- ATH_LLC_SNAP_HDR *llcHdr;
- struct ieee80211_frame *wh;
- u32 hdrsize;
-
- A_ASSERT(osbuf != NULL);
-
- if (A_NETBUF_HEADROOM(osbuf) <
- (sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
- {
- return A_NO_MEMORY;
- }
-
- datap = A_NETBUF_DATA(osbuf);
-
- typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
-
- if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
-/*
- * packet is already in 802.3 format - return success
- */
- A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
- goto AddDot11Hdr;
- }
-
- /*
- * Save mac fields and length to be inserted later
- */
- memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
- memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
- macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
- sizeof(ATH_LLC_SNAP_HDR));
-
- // Remove the Ethernet hdr
- A_NETBUF_PULL(osbuf, sizeof(ATH_MAC_HDR));
- /*
- * Make room for LLC+SNAP headers
- */
- if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
- return A_NO_MEMORY;
- }
- datap = A_NETBUF_DATA(osbuf);
-
- llcHdr = (ATH_LLC_SNAP_HDR *)(datap);
- llcHdr->dsap = 0xAA;
- llcHdr->ssap = 0xAA;
- llcHdr->cntl = 0x03;
- llcHdr->orgCode[0] = 0x0;
- llcHdr->orgCode[1] = 0x0;
- llcHdr->orgCode[2] = 0x0;
- llcHdr->etherType = typeorlen;
-
-AddDot11Hdr:
- /* Make room for 802.11 hdr */
- if (wmip->wmi_is_wmm_enabled)
- {
- hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
- if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
- {
- return A_NO_MEMORY;
- }
- wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf);
- wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_QOS;
- }
- else
- {
- hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32));
- if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
- {
- return A_NO_MEMORY;
- }
- wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf);
- wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_DATA;
- }
- /* Setup the SA & DA */
- IEEE80211_ADDR_COPY(wh->i_addr2, macHdr.srcMac);
-
- if (mode == INFRA_NETWORK) {
- IEEE80211_ADDR_COPY(wh->i_addr3, macHdr.dstMac);
- }
- else if (mode == ADHOC_NETWORK) {
- IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac);
- }
-
- return (0);
-}
-
-int
-wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
-{
- u8 *datap;
- struct ieee80211_frame *pwh,wh;
- u8 type,subtype;
- ATH_LLC_SNAP_HDR *llcHdr;
- ATH_MAC_HDR macHdr;
- u32 hdrsize;
-
- A_ASSERT(osbuf != NULL);
- datap = A_NETBUF_DATA(osbuf);
-
- pwh = (struct ieee80211_frame *)datap;
- type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
- subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
-
- memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame));
-
- /* strip off the 802.11 hdr*/
- if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
- hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
- A_NETBUF_PULL(osbuf, hdrsize);
- } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) {
- A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame));
- }
-
- datap = A_NETBUF_DATA(osbuf);
- llcHdr = (ATH_LLC_SNAP_HDR *)(datap);
-
- macHdr.typeOrLen = llcHdr->etherType;
- A_MEMZERO(macHdr.dstMac, sizeof(macHdr.dstMac));
- A_MEMZERO(macHdr.srcMac, sizeof(macHdr.srcMac));
-
- switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
- case IEEE80211_FC1_DIR_NODS:
- IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1);
- IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2);
- break;
- case IEEE80211_FC1_DIR_TODS:
- IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr3);
- IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2);
- break;
- case IEEE80211_FC1_DIR_FROMDS:
- IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1);
- IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr3);
- break;
- case IEEE80211_FC1_DIR_DSTODS:
- break;
- }
-
- // Remove the LLC Hdr.
- A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR));
-
- // Insert the ATH MAC hdr.
-
- A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR));
- datap = A_NETBUF_DATA(osbuf);
-
- memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR));
-
- return 0;
-}
-
-/*
- * performs 802.3 to DIX encapsulation for received packets.
- * Assumes the entire 802.3 header is contigous.
- */
-int
-wmi_dot3_2_dix(void *osbuf)
-{
- u8 *datap;
- ATH_MAC_HDR macHdr;
- ATH_LLC_SNAP_HDR *llcHdr;
-
- A_ASSERT(osbuf != NULL);
- datap = A_NETBUF_DATA(osbuf);
-
- memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR));
- llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
- macHdr.typeOrLen = llcHdr->etherType;
-
- if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
- return A_NO_MEMORY;
- }
-
- datap = A_NETBUF_DATA(osbuf);
-
- memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
-
- return (0);
-}
-
-/*
- * Removes a WMI data header
- */
-int
-wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
-{
- A_ASSERT(osbuf != NULL);
-
- return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR)));
-}
-
-void
-wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg)
-{
- wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg);
-}
-
-/*
- * WMI Extended Event received from Target.
- */
-int
-wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
-{
- WMIX_CMD_HDR *cmd;
- u16 id;
- u8 *datap;
- u32 len;
- int status = 0;
-
- if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) {
- A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
- wmip->wmi_stats.cmd_len_err++;
- return A_ERROR;
- }
-
- cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
- id = cmd->commandId;
-
- if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
- A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
- wmip->wmi_stats.cmd_len_err++;
- return A_ERROR;
- }
-
- datap = A_NETBUF_DATA(osbuf);
- len = A_NETBUF_LEN(osbuf);
-
- switch (id) {
- case (WMIX_DSETOPENREQ_EVENTID):
- status = wmi_dset_open_req_rx(wmip, datap, len);
- break;
-#ifdef CONFIG_HOST_DSET_SUPPORT
- case (WMIX_DSETCLOSE_EVENTID):
- status = wmi_dset_close_rx(wmip, datap, len);
- break;
- case (WMIX_DSETDATAREQ_EVENTID):
- status = wmi_dset_data_req_rx(wmip, datap, len);
- break;
-#endif /* CONFIG_HOST_DSET_SUPPORT */
- case (WMIX_HB_CHALLENGE_RESP_EVENTID):
- wmi_hbChallengeResp_rx(wmip, datap, len);
- break;
- case (WMIX_DBGLOG_EVENTID):
- wmi_dbglog_event_rx(wmip, datap, len);
- break;
-#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
- case (WMIX_PROF_COUNT_EVENTID):
- wmi_prof_count_rx(wmip, datap, len);
- break;
-#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
- default:
- A_DPRINTF(DBG_WMI|DBG_ERROR,
- (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
- wmip->wmi_stats.cmd_id_err++;
- status = A_ERROR;
- break;
- }
-
- return status;
-}
-
-/*
- * Control Path
- */
-u32 cmdRecvNum;
-
-int
-wmi_control_rx(struct wmi_t *wmip, void *osbuf)
-{
- WMI_CMD_HDR *cmd;
- u16 id;
- u8 *datap;
- u32 len, i, loggingReq;
- int status = 0;
-
- A_ASSERT(osbuf != NULL);
- if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) {
- A_NETBUF_FREE(osbuf);
- A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
- wmip->wmi_stats.cmd_len_err++;
- return A_ERROR;
- }
-
- cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
- id = cmd->commandId;
-
- if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
- A_NETBUF_FREE(osbuf);
- A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
- wmip->wmi_stats.cmd_len_err++;
- return A_ERROR;
- }
-
- datap = A_NETBUF_DATA(osbuf);
- len = A_NETBUF_LEN(osbuf);
-
- loggingReq = 0;
-
- ar6000_get_driver_cfg(wmip->wmi_devt,
- AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS,
- &loggingReq);
-
- if(loggingReq) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id));
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum));
- for(i = 0; i < len; i++)
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i]));
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n"));
- }
-
- LOCK_WMI(wmip);
- cmdRecvNum++;
- UNLOCK_WMI(wmip);
-
- switch (id) {
- case (WMI_GET_BITRATE_CMDID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG));
- status = wmi_bitrate_reply_rx(wmip, datap, len);
- break;
- case (WMI_GET_CHANNEL_LIST_CMDID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG));
- status = wmi_channelList_reply_rx(wmip, datap, len);
- break;
- case (WMI_GET_TX_PWR_CMDID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG));
- status = wmi_txPwr_reply_rx(wmip, datap, len);
- break;
- case (WMI_READY_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG));
- status = wmi_ready_event_rx(wmip, datap, len);
- A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt);
- break;
- case (WMI_CONNECT_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG));
- status = wmi_connect_event_rx(wmip, datap, len);
- break;
- case (WMI_DISCONNECT_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG));
- status = wmi_disconnect_event_rx(wmip, datap, len);
- break;
- case (WMI_PEER_NODE_EVENTID):
- A_DPRINTF (DBG_WMI, (DBGFMT "WMI_PEER_NODE_EVENTID\n", DBGARG));
- status = wmi_peer_node_event_rx(wmip, datap, len);
- break;
- case (WMI_TKIP_MICERR_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG));
- status = wmi_tkip_micerr_event_rx(wmip, datap, len);
- break;
- case (WMI_BSSINFO_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG));
- {
- /*
- * convert WMI_BSS_INFO_HDR2 to WMI_BSS_INFO_HDR
- * Take a local copy of the WMI_BSS_INFO_HDR2 from the wmi buffer
- * and reconstruct the WMI_BSS_INFO_HDR in its place
- */
- WMI_BSS_INFO_HDR2 bih2;
- WMI_BSS_INFO_HDR *bih;
- memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2));
-
- A_NETBUF_PUSH(osbuf, 4);
- datap = A_NETBUF_DATA(osbuf);
- len = A_NETBUF_LEN(osbuf);
- bih = (WMI_BSS_INFO_HDR *)datap;
-
- bih->channel = bih2.channel;
- bih->frameType = bih2.frameType;
- bih->snr = bih2.snr;
- bih->rssi = bih2.snr - 95;
- bih->ieMask = bih2.ieMask;
- memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN);
-
- status = wmi_bssInfo_event_rx(wmip, datap, len);
- }
- break;
- case (WMI_REGDOMAIN_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG));
- status = wmi_regDomain_event_rx(wmip, datap, len);
- break;
- case (WMI_PSTREAM_TIMEOUT_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG));
- status = wmi_pstream_timeout_event_rx(wmip, datap, len);
- break;
- case (WMI_NEIGHBOR_REPORT_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG));
- status = wmi_neighborReport_event_rx(wmip, datap, len);
- break;
- case (WMI_SCAN_COMPLETE_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG));
- status = wmi_scanComplete_rx(wmip, datap, len);
- break;
- case (WMI_CMDERROR_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG));
- status = wmi_errorEvent_rx(wmip, datap, len);
- break;
- case (WMI_REPORT_STATISTICS_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG));
- status = wmi_statsEvent_rx(wmip, datap, len);
- break;
- case (WMI_RSSI_THRESHOLD_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG));
- status = wmi_rssiThresholdEvent_rx(wmip, datap, len);
- break;
- case (WMI_ERROR_REPORT_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG));
- status = wmi_reportErrorEvent_rx(wmip, datap, len);
- break;
- case (WMI_OPT_RX_FRAME_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG));
- status = wmi_opt_frame_event_rx(wmip, datap, len);
- break;
- case (WMI_REPORT_ROAM_TBL_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG));
- status = wmi_roam_tbl_event_rx(wmip, datap, len);
- break;
- case (WMI_EXTENSION_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG));
- status = wmi_control_rx_xtnd(wmip, osbuf);
- break;
- case (WMI_CAC_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG));
- status = wmi_cac_event_rx(wmip, datap, len);
- break;
- case (WMI_CHANNEL_CHANGE_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CHANNEL_CHANGE_EVENTID\n", DBGARG));
- status = wmi_channel_change_event_rx(wmip, datap, len);
- break;
- case (WMI_REPORT_ROAM_DATA_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG));
- status = wmi_roam_data_event_rx(wmip, datap, len);
- break;
-#ifdef CONFIG_HOST_TCMD_SUPPORT
- case (WMI_TEST_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG));
- status = wmi_tcmd_test_report_rx(wmip, datap, len);
- break;
-#endif
- case (WMI_GET_FIXRATES_CMDID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG));
- status = wmi_ratemask_reply_rx(wmip, datap, len);
- break;
- case (WMI_TX_RETRY_ERR_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG));
- status = wmi_txRetryErrEvent_rx(wmip, datap, len);
- break;
- case (WMI_SNR_THRESHOLD_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG));
- status = wmi_snrThresholdEvent_rx(wmip, datap, len);
- break;
- case (WMI_LQ_THRESHOLD_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG));
- status = wmi_lqThresholdEvent_rx(wmip, datap, len);
- break;
- case (WMI_APLIST_EVENTID):
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n"));
- status = wmi_aplistEvent_rx(wmip, datap, len);
- break;
- case (WMI_GET_KEEPALIVE_CMDID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG));
- status = wmi_keepalive_reply_rx(wmip, datap, len);
- break;
- case (WMI_GET_WOW_LIST_EVENTID):
- status = wmi_get_wow_list_event_rx(wmip, datap, len);
- break;
- case (WMI_GET_PMKID_LIST_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG));
- status = wmi_get_pmkid_list_event_rx(wmip, datap, len);
- break;
- case (WMI_PSPOLL_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSPOLL_EVENT\n", DBGARG));
- status = wmi_pspoll_event_rx(wmip, datap, len);
- break;
- case (WMI_DTIMEXPIRY_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DTIMEXPIRY_EVENT\n", DBGARG));
- status = wmi_dtimexpiry_event_rx(wmip, datap, len);
- break;
- case (WMI_SET_PARAMS_REPLY_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG));
- status = wmi_set_params_event_rx(wmip, datap, len);
- break;
- case (WMI_ADDBA_REQ_EVENTID):
- status = wmi_addba_req_event_rx(wmip, datap, len);
- break;
- case (WMI_ADDBA_RESP_EVENTID):
- status = wmi_addba_resp_event_rx(wmip, datap, len);
- break;
- case (WMI_DELBA_REQ_EVENTID):
- status = wmi_delba_req_event_rx(wmip, datap, len);
- break;
- case (WMI_REPORT_BTCOEX_CONFIG_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_CONFIG_EVENTID", DBGARG));
- status = wmi_btcoex_config_event_rx(wmip, datap, len);
- break;
- case (WMI_REPORT_BTCOEX_STATS_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_STATS_EVENTID", DBGARG));
- status = wmi_btcoex_stats_event_rx(wmip, datap, len);
- break;
- case (WMI_TX_COMPLETE_EVENTID):
- {
- int index;
- TX_COMPLETE_MSG_V1 *pV1;
- WMI_TX_COMPLETE_EVENT *pEv = (WMI_TX_COMPLETE_EVENT *)datap;
- A_PRINTF("comp: %d %d %d\n", pEv->numMessages, pEv->msgLen, pEv->msgType);
-
- for(index = 0 ; index < pEv->numMessages ; index++) {
- pV1 = (TX_COMPLETE_MSG_V1 *)(datap + sizeof(WMI_TX_COMPLETE_EVENT) + index*sizeof(TX_COMPLETE_MSG_V1));
- A_PRINTF("msg: %d %d %d %d\n", pV1->status, pV1->pktID, pV1->rateIdx, pV1->ackFailures);
- }
- }
- break;
- case (WMI_HCI_EVENT_EVENTID):
- status = wmi_hci_event_rx(wmip, datap, len);
- break;
-#ifdef WAPI_ENABLE
- case (WMI_WAPI_REKEY_EVENTID):
- A_DPRINTF(DBG_WMI, (DBGFMT "WMI_WAPI_REKEY_EVENTID", DBGARG));
- status = wmi_wapi_rekey_event_rx(wmip, datap, len);
- break;
-#endif
- default:
- A_DPRINTF(DBG_WMI|DBG_ERROR,
- (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
- wmip->wmi_stats.cmd_id_err++;
- status = A_ERROR;
- break;
- }
-
- A_NETBUF_FREE(osbuf);
-
- return status;
-}
-
-/* Send a "simple" wmi command -- one with no arguments */
-static int
-wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid)
-{
- void *osbuf;
-
- osbuf = A_NETBUF_ALLOC(0);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- return (wmi_cmd_send(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG));
-}
-
-/* Send a "simple" extended wmi command -- one with no arguments.
- Enabling this command only if GPIO or profiling support is enabled.
- This is to suppress warnings on some platforms */
-#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-static int
-wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid)
-{
- void *osbuf;
-
- osbuf = A_NETBUF_ALLOC(0);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- return (wmi_cmd_send_xtnd(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG));
-}
-#endif
-
-static int
-wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
-
- if (len < sizeof(WMI_READY_EVENT)) {
- return A_EINVAL;
- }
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
- wmip->wmi_ready = true;
- A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability,
- ev->sw_version, ev->abi_version);
-
- return 0;
-}
-
-#define LE_READ_4(p) \
- ((u32) \
- ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \
- (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
-
-static int __inline
-iswmmoui(const u8 *frm)
-{
- return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
-}
-
-static int __inline
-iswmmparam(const u8 *frm)
-{
- return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
-}
-
-
-static int
-wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_CONNECT_EVENT *ev;
- u8 *pie,*peie;
-
- if (len < sizeof(WMI_CONNECT_EVENT))
- {
- return A_EINVAL;
- }
- ev = (WMI_CONNECT_EVENT *)datap;
-
- A_DPRINTF(DBG_WMI,
- (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
- DBGARG, ev->channel,
- ev->bssid[0], ev->bssid[1], ev->bssid[2],
- ev->bssid[3], ev->bssid[4], ev->bssid[5]));
-
- memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
-
- /* initialize pointer to start of assoc rsp IEs */
- pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen +
- sizeof(u16) + /* capinfo*/
- sizeof(u16) + /* status Code */
- sizeof(u16) ; /* associd */
-
- /* initialize pointer to end of assoc rsp IEs */
- peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen;
-
- while (pie < peie)
- {
- switch (*pie)
- {
- case IEEE80211_ELEMID_VENDOR:
- if (iswmmoui(pie))
- {
- if(iswmmparam (pie))
- {
- wmip->wmi_is_wmm_enabled = true;
- }
- }
- break;
- }
-
- if (wmip->wmi_is_wmm_enabled)
- {
- break;
- }
- pie += pie[1] + 2;
- }
-
- A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid,
- ev->listenInterval, ev->beaconInterval,
- (NETWORK_TYPE) ev->networkType, ev->beaconIeLen,
- ev->assocReqLen, ev->assocRespLen,
- ev->assocInfo);
-
- return 0;
-}
-
-static int
-wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_REG_DOMAIN_EVENT *ev;
-
- if (len < sizeof(*ev)) {
- return A_EINVAL;
- }
- ev = (WMI_REG_DOMAIN_EVENT *)datap;
-
- A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain);
-
- return 0;
-}
-
-static int
-wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_NEIGHBOR_REPORT_EVENT *ev;
- int numAps;
-
- if (len < sizeof(*ev)) {
- return A_EINVAL;
- }
- ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap;
- numAps = ev->numberOfAps;
-
- if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) {
- return A_EINVAL;
- }
-
- A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor);
-
- return 0;
-}
-
-static int
-wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_DISCONNECT_EVENT *ev;
- wmip->wmi_traffic_class = 100;
-
- if (len < sizeof(WMI_DISCONNECT_EVENT)) {
- return A_EINVAL;
- }
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- ev = (WMI_DISCONNECT_EVENT *)datap;
-
- A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
-
- wmip->wmi_is_wmm_enabled = false;
- wmip->wmi_pair_crypto_type = NONE_CRYPT;
- wmip->wmi_grp_crypto_type = NONE_CRYPT;
-
- A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
- ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
-
- return 0;
-}
-
-static int
-wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_PEER_NODE_EVENT *ev;
-
- if (len < sizeof(WMI_PEER_NODE_EVENT)) {
- return A_EINVAL;
- }
- ev = (WMI_PEER_NODE_EVENT *)datap;
- if (ev->eventCode == PEER_NODE_JOIN_EVENT) {
- A_DPRINTF (DBG_WMI, (DBGFMT "Joined node with Macaddr: ", DBGARG));
- } else if(ev->eventCode == PEER_NODE_LEAVE_EVENT) {
- A_DPRINTF (DBG_WMI, (DBGFMT "left node with Macaddr: ", DBGARG));
- }
-
- A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr);
-
- return 0;
-}
-
-static int
-wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_TKIP_MICERR_EVENT *ev;
-
- if (len < sizeof(*ev)) {
- return A_EINVAL;
- }
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- ev = (WMI_TKIP_MICERR_EVENT *)datap;
- A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast);
-
- return 0;
-}
-
-static int
-wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- bss_t *bss = NULL;
- WMI_BSS_INFO_HDR *bih;
- u8 *buf;
- u32 nodeCachingAllowed = 1;
- u8 cached_ssid_len = 0;
- u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
- u8 beacon_ssid_len = 0;
-
- if (len <= sizeof(WMI_BSS_INFO_HDR)) {
- return A_EINVAL;
- }
-
- bih = (WMI_BSS_INFO_HDR *)datap;
- bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
-
- if (bih->rssi > 0) {
- if (NULL == bss)
- return 0; //no node found in the table, just drop the node with incorrect RSSI
- else
- bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX
- }
-
- A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len);
- /* What is driver config for wlan node caching? */
- if(ar6000_get_driver_cfg(wmip->wmi_devt,
- AR6000_DRIVER_CFG_GET_WLANNODECACHING,
- &nodeCachingAllowed) != 0) {
- wmi_node_return(wmip, bss);
- return A_EINVAL;
- }
-
- if(!nodeCachingAllowed) {
- wmi_node_return(wmip, bss);
- return 0;
- }
-
- buf = datap + sizeof(WMI_BSS_INFO_HDR);
- len -= sizeof(WMI_BSS_INFO_HDR);
-
- A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, "
- "bssid \"%pM\"\n", DBGARG, bih->channel,
- (unsigned char) bih->rssi, bih->bssid));
-
- if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
- wmi_node_return(wmip, bss);
- return 0;
- }
-
- if (bss != NULL) {
- /*
- * Free up the node. Not the most efficient process given
- * we are about to allocate a new node but it is simple and should be
- * adequate.
- */
-
- /* In case of hidden AP, beacon will not have ssid,
- * but a directed probe response will have it,
- * so cache the probe-resp-ssid if already present. */
- if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType))
- {
- u8 *ie_ssid;
-
- ie_ssid = bss->ni_cie.ie_ssid;
- if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0))
- {
- cached_ssid_len = ie_ssid[1];
- memcpy(cached_ssid_buf, ie_ssid + 2, cached_ssid_len);
- }
- }
-
- /*
- * Use the current average rssi of associated AP base on assumpiton
- * 1. Most os with GUI will update RSSI by wmi_get_stats_cmd() periodically
- * 2. wmi_get_stats_cmd(..) will be called when calling wmi_startscan_cmd(...)
- * The average value of RSSI give end-user better feeling for instance value of scan result
- * It also sync up RSSI info in GUI between scan result and RSSI signal icon
- */
- if (IEEE80211_ADDR_EQ(wmip->wmi_bssid, bih->bssid)) {
- bih->rssi = bss->ni_rssi;
- bih->snr = bss->ni_snr;
- }
-
- wlan_node_reclaim(&wmip->wmi_scan_table, bss);
- }
-
- /* beacon/probe response frame format
- * [8] time stamp
- * [2] beacon interval
- * [2] capability information
- * [tlv] ssid */
- beacon_ssid_len = buf[SSID_IE_LEN_INDEX];
-
- /* If ssid is cached for this hidden AP, then change buffer len accordingly. */
- if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
- (0 != cached_ssid_len) &&
- (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
- {
- len += (cached_ssid_len - beacon_ssid_len);
- }
-
- bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
- if (bss == NULL) {
- return A_NO_MEMORY;
- }
-
- bss->ni_snr = bih->snr;
- bss->ni_rssi = bih->rssi;
- A_ASSERT(bss->ni_buf != NULL);
-
- /* In case of hidden AP, beacon will not have ssid,
- * but a directed probe response will have it,
- * so place the cached-ssid(probe-resp) in the bssinfo. */
- if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
- (0 != cached_ssid_len) &&
- (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
- {
- u8 *ni_buf = bss->ni_buf;
- int buf_len = len;
-
- /* copy the first 14 bytes such as
- * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */
- memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
-
- ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len;
- ni_buf += (SSID_IE_LEN_INDEX + 1);
-
- buf += (SSID_IE_LEN_INDEX + 1);
- buf_len -= (SSID_IE_LEN_INDEX + 1);
-
- /* copy the cached ssid */
- memcpy(ni_buf, cached_ssid_buf, cached_ssid_len);
- ni_buf += cached_ssid_len;
-
- buf += beacon_ssid_len;
- buf_len -= beacon_ssid_len;
-
- if (cached_ssid_len > beacon_ssid_len)
- buf_len -= (cached_ssid_len - beacon_ssid_len);
-
- /* now copy the rest of bytes */
- memcpy(ni_buf, buf, buf_len);
- }
- else
- memcpy(bss->ni_buf, buf, len);
-
- bss->ni_framelen = len;
- if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) {
- wlan_node_free(bss);
- return A_EINVAL;
- }
-
- /*
- * Update the frequency in ie_chan, overwriting of channel number
- * which is done in wlan_parse_beacon
- */
- bss->ni_cie.ie_chan = bih->channel;
- wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
-
- return 0;
-}
-
-static int
-wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- bss_t *bss;
- WMI_OPT_RX_INFO_HDR *bih;
- u8 *buf;
-
- if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
- return A_EINVAL;
- }
-
- bih = (WMI_OPT_RX_INFO_HDR *)datap;
- buf = datap + sizeof(WMI_OPT_RX_INFO_HDR);
- len -= sizeof(WMI_OPT_RX_INFO_HDR);
-
- A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG,
- bih->bssid[4], bih->bssid[5]));
-
- bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
- if (bss != NULL) {
- /*
- * Free up the node. Not the most efficient process given
- * we are about to allocate a new node but it is simple and should be
- * adequate.
- */
- wlan_node_reclaim(&wmip->wmi_scan_table, bss);
- }
-
- bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
- if (bss == NULL) {
- return A_NO_MEMORY;
- }
-
- bss->ni_snr = bih->snr;
- bss->ni_cie.ie_chan = bih->channel;
- A_ASSERT(bss->ni_buf != NULL);
- memcpy(bss->ni_buf, buf, len);
- wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
-
- return 0;
-}
-
- /* This event indicates inactivity timeout of a fatpipe(pstream)
- * at the target
- */
-static int
-wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_PSTREAM_TIMEOUT_EVENT *ev;
-
- if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) {
- return A_EINVAL;
- }
-
- A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG));
-
- ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap;
-
- /* When the pstream (fat pipe == AC) timesout, it means there were no
- * thinStreams within this pstream & it got implicitly created due to
- * data flow on this AC. We start the inactivity timer only for
- * implicitly created pstream. Just reset the host state.
- */
- /* Set the activeTsids for this AC to 0 */
- LOCK_WMI(wmip);
- wmip->wmi_streamExistsForAC[ev->trafficClass]=0;
- wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass);
- UNLOCK_WMI(wmip);
-
- /*Indicate inactivity to driver layer for this fatpipe (pstream)*/
- A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass);
-
- return 0;
-}
-
-static int
-wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_BIT_RATE_REPLY *reply;
- s32 rate;
- u32 sgi,index;
- /* 54149:
- * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY.
- * since there is difference in the length and to avoid returning
- * error value.
- */
- if (len < sizeof(WMI_BIT_RATE_REPLY)) {
- return A_EINVAL;
- }
- reply = (WMI_BIT_RATE_REPLY *)datap;
- A_DPRINTF(DBG_WMI,
- (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex));
-
- if (reply->rateIndex == (s8) RATE_AUTO) {
- rate = RATE_AUTO;
- } else {
- // the SGI state is stored as the MSb of the rateIndex
- index = reply->rateIndex & 0x7f;
- sgi = (reply->rateIndex & 0x80)? 1:0;
- rate = wmi_rateTable[index][sgi];
- }
-
- A_WMI_BITRATE_RX(wmip->wmi_devt, rate);
- return 0;
-}
-
-static int
-wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_FIX_RATES_REPLY *reply;
-
- if (len < sizeof(WMI_FIX_RATES_REPLY)) {
- return A_EINVAL;
- }
- reply = (WMI_FIX_RATES_REPLY *)datap;
- A_DPRINTF(DBG_WMI,
- (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask));
-
- A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask);
-
- return 0;
-}
-
-static int
-wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_CHANNEL_LIST_REPLY *reply;
-
- if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) {
- return A_EINVAL;
- }
- reply = (WMI_CHANNEL_LIST_REPLY *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels,
- reply->channelList);
-
- return 0;
-}
-
-static int
-wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_TX_PWR_REPLY *reply;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMI_TX_PWR_REPLY *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM);
-
- return 0;
-}
-static int
-wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_GET_KEEPALIVE_CMD *reply;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMI_GET_KEEPALIVE_CMD *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured);
-
- return 0;
-}
-
-
-static int
-wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMIX_DSETOPENREQ_EVENT *dsetopenreq;
-
- if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) {
- return A_EINVAL;
- }
- dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap;
- A_DPRINTF(DBG_WMI,
- (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id));
- A_WMI_DSET_OPEN_REQ(wmip->wmi_devt,
- dsetopenreq->dset_id,
- dsetopenreq->targ_dset_handle,
- dsetopenreq->targ_reply_fn,
- dsetopenreq->targ_reply_arg);
-
- return 0;
-}
-
-#ifdef CONFIG_HOST_DSET_SUPPORT
-static int
-wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMIX_DSETCLOSE_EVENT *dsetclose;
-
- if (len < sizeof(WMIX_DSETCLOSE_EVENT)) {
- return A_EINVAL;
- }
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- dsetclose = (WMIX_DSETCLOSE_EVENT *)datap;
- A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie);
-
- return 0;
-}
-
-static int
-wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMIX_DSETDATAREQ_EVENT *dsetdatareq;
-
- if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) {
- return A_EINVAL;
- }
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap;
- A_WMI_DSET_DATA_REQ(wmip->wmi_devt,
- dsetdatareq->access_cookie,
- dsetdatareq->offset,
- dsetdatareq->length,
- dsetdatareq->targ_buf,
- dsetdatareq->targ_reply_fn,
- dsetdatareq->targ_reply_arg);
-
- return 0;
-}
-#endif /* CONFIG_HOST_DSET_SUPPORT */
-
-static int
-wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_SCAN_COMPLETE_EVENT *ev;
-
- ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
- if ((int)ev->status == 0) {
- wlan_refresh_inactive_nodes(&wmip->wmi_scan_table);
- }
- A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status);
- is_probe_ssid = false;
-
- return 0;
-}
-
-/*
- * Target is reporting a programming error. This is for
- * developer aid only. Target only checks a few common violations
- * and it is responsibility of host to do all error checking.
- * Behavior of target after wmi error event is undefined.
- * A reset is recommended.
- */
-static int
-wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_CMD_ERROR_EVENT *ev;
-
- ev = (WMI_CMD_ERROR_EVENT *)datap;
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId));
- switch (ev->errorCode) {
- case (INVALID_PARAM):
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n"));
- break;
- case (ILLEGAL_STATE):
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n"));
- break;
- case (INTERNAL_ERROR):
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n"));
- break;
- }
-
- return 0;
-}
-
-
-static int
-wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len);
-
- return 0;
-}
-
-static int
-wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_RSSI_THRESHOLD_EVENT *reply;
- WMI_RSSI_THRESHOLD_VAL newThreshold;
- WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
- SQ_THRESHOLD_PARAMS *sq_thresh =
- &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
- u8 upper_rssi_threshold, lower_rssi_threshold;
- s16 rssi;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMI_RSSI_THRESHOLD_EVENT *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
- newThreshold = (WMI_RSSI_THRESHOLD_VAL) reply->range;
- rssi = reply->rssi;
-
- /*
- * Identify the threshold breached and communicate that to the app. After
- * that install a new set of thresholds based on the signal quality
- * reported by the target
- */
- if (newThreshold) {
- /* Upper threshold breached */
- if (rssi < sq_thresh->upper_threshold[0]) {
- A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper RSSI threshold event: "
- " %d\n", DBGARG, rssi));
- } else if ((rssi < sq_thresh->upper_threshold[1]) &&
- (rssi >= sq_thresh->upper_threshold[0]))
- {
- newThreshold = WMI_RSSI_THRESHOLD1_ABOVE;
- } else if ((rssi < sq_thresh->upper_threshold[2]) &&
- (rssi >= sq_thresh->upper_threshold[1]))
- {
- newThreshold = WMI_RSSI_THRESHOLD2_ABOVE;
- } else if ((rssi < sq_thresh->upper_threshold[3]) &&
- (rssi >= sq_thresh->upper_threshold[2]))
- {
- newThreshold = WMI_RSSI_THRESHOLD3_ABOVE;
- } else if ((rssi < sq_thresh->upper_threshold[4]) &&
- (rssi >= sq_thresh->upper_threshold[3]))
- {
- newThreshold = WMI_RSSI_THRESHOLD4_ABOVE;
- } else if ((rssi < sq_thresh->upper_threshold[5]) &&
- (rssi >= sq_thresh->upper_threshold[4]))
- {
- newThreshold = WMI_RSSI_THRESHOLD5_ABOVE;
- } else if (rssi >= sq_thresh->upper_threshold[5]) {
- newThreshold = WMI_RSSI_THRESHOLD6_ABOVE;
- }
- } else {
- /* Lower threshold breached */
- if (rssi > sq_thresh->lower_threshold[0]) {
- A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower RSSI threshold event: "
- "%d %d\n", DBGARG, rssi, sq_thresh->lower_threshold[0]));
- } else if ((rssi > sq_thresh->lower_threshold[1]) &&
- (rssi <= sq_thresh->lower_threshold[0]))
- {
- newThreshold = WMI_RSSI_THRESHOLD6_BELOW;
- } else if ((rssi > sq_thresh->lower_threshold[2]) &&
- (rssi <= sq_thresh->lower_threshold[1]))
- {
- newThreshold = WMI_RSSI_THRESHOLD5_BELOW;
- } else if ((rssi > sq_thresh->lower_threshold[3]) &&
- (rssi <= sq_thresh->lower_threshold[2]))
- {
- newThreshold = WMI_RSSI_THRESHOLD4_BELOW;
- } else if ((rssi > sq_thresh->lower_threshold[4]) &&
- (rssi <= sq_thresh->lower_threshold[3]))
- {
- newThreshold = WMI_RSSI_THRESHOLD3_BELOW;
- } else if ((rssi > sq_thresh->lower_threshold[5]) &&
- (rssi <= sq_thresh->lower_threshold[4]))
- {
- newThreshold = WMI_RSSI_THRESHOLD2_BELOW;
- } else if (rssi <= sq_thresh->lower_threshold[5]) {
- newThreshold = WMI_RSSI_THRESHOLD1_BELOW;
- }
- }
- /* Calculate and install the next set of thresholds */
- lower_rssi_threshold = ar6000_get_lower_threshold(rssi, sq_thresh,
- sq_thresh->lower_threshold_valid_count);
- upper_rssi_threshold = ar6000_get_upper_threshold(rssi, sq_thresh,
- sq_thresh->upper_threshold_valid_count);
- /* Issue a wmi command to install the thresholds */
- cmd.thresholdAbove1_Val = upper_rssi_threshold;
- cmd.thresholdBelow1_Val = lower_rssi_threshold;
- cmd.weight = sq_thresh->weight;
- cmd.pollTime = sq_thresh->polling_interval;
-
- rssi_event_value = rssi;
-
- if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) {
- A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n",
- DBGARG));
- }
-
- A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, reply->rssi);
-
- return 0;
-}
-
-
-static int
-wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_TARGET_ERROR_REPORT_EVENT *reply;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, (WMI_TARGET_ERROR_VAL) reply->errorVal);
-
- return 0;
-}
-
-static int
-wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_CAC_EVENT *reply;
- WMM_TSPEC_IE *tspec_ie;
- u16 activeTsids;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMI_CAC_EVENT *)datap;
-
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&
- (reply->statusCode != TSPEC_STATUS_CODE_ADMISSION_ACCEPTED)) {
- tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
-
- wmi_delete_pstream_cmd(wmip, reply->ac,
- (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
- }
- else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
- u8 i;
-
- /* following assumes that there is only one outstanding ADDTS request
- when this event is received */
- LOCK_WMI(wmip);
- activeTsids = wmip->wmi_streamExistsForAC[reply->ac];
- UNLOCK_WMI(wmip);
-
- for (i = 0; i < sizeof(activeTsids) * 8; i++) {
- if ((activeTsids >> i) & 1) {
- break;
- }
- }
- if (i < (sizeof(activeTsids) * 8)) {
- wmi_delete_pstream_cmd(wmip, reply->ac, i);
- }
- }
- /*
- * Ev#72990: Clear active tsids and Add missing handling
- * for delete qos stream from AP
- */
- else if (reply->cac_indication == CAC_INDICATION_DELETE) {
- u8 tsid = 0;
-
- tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
- tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
- LOCK_WMI(wmip);
- wmip->wmi_streamExistsForAC[reply->ac] &= ~(1<<tsid);
- activeTsids = wmip->wmi_streamExistsForAC[reply->ac];
- UNLOCK_WMI(wmip);
-
-
- /* Indicate stream inactivity to driver layer only if all tsids
- * within this AC are deleted.
- */
- if (!activeTsids) {
- A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, reply->ac);
- wmip->wmi_fatPipeExists &= ~(1 << reply->ac);
- }
- }
-
- A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac,
- reply->cac_indication, reply->statusCode,
- reply->tspecSuggestion);
-
- return 0;
-}
-
-static int
-wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_CHANNEL_CHANGE_EVENT *reply;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMI_CHANNEL_CHANGE_EVENT *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel,
- reply->newChannel);
-
- return 0;
-}
-
-static int
-wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMIX_HB_CHALLENGE_RESP_EVENT *reply;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG));
-
- A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source);
-
- return 0;
-}
-
-static int
-wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_TARGET_ROAM_TBL *reply;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMI_TARGET_ROAM_TBL *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply);
-
- return 0;
-}
-
-static int
-wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_TARGET_ROAM_DATA *reply;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMI_TARGET_ROAM_DATA *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply);
-
- return 0;
-}
-
-static int
-wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) {
- return A_EINVAL;
- }
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt);
-
- return 0;
-}
-
-static int
-wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_SNR_THRESHOLD_EVENT *reply;
- SQ_THRESHOLD_PARAMS *sq_thresh =
- &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
- WMI_SNR_THRESHOLD_VAL newThreshold;
- WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
- u8 upper_snr_threshold, lower_snr_threshold;
- s16 snr;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMI_SNR_THRESHOLD_EVENT *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- newThreshold = (WMI_SNR_THRESHOLD_VAL) reply->range;
- snr = reply->snr;
- /*
- * Identify the threshold breached and communicate that to the app. After
- * that install a new set of thresholds based on the signal quality
- * reported by the target
- */
- if (newThreshold) {
- /* Upper threshold breached */
- if (snr < sq_thresh->upper_threshold[0]) {
- A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper SNR threshold event: "
- "%d\n", DBGARG, snr));
- } else if ((snr < sq_thresh->upper_threshold[1]) &&
- (snr >= sq_thresh->upper_threshold[0]))
- {
- newThreshold = WMI_SNR_THRESHOLD1_ABOVE;
- } else if ((snr < sq_thresh->upper_threshold[2]) &&
- (snr >= sq_thresh->upper_threshold[1]))
- {
- newThreshold = WMI_SNR_THRESHOLD2_ABOVE;
- } else if ((snr < sq_thresh->upper_threshold[3]) &&
- (snr >= sq_thresh->upper_threshold[2]))
- {
- newThreshold = WMI_SNR_THRESHOLD3_ABOVE;
- } else if (snr >= sq_thresh->upper_threshold[3]) {
- newThreshold = WMI_SNR_THRESHOLD4_ABOVE;
- }
- } else {
- /* Lower threshold breached */
- if (snr > sq_thresh->lower_threshold[0]) {
- A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower SNR threshold event: "
- "%d %d\n", DBGARG, snr, sq_thresh->lower_threshold[0]));
- } else if ((snr > sq_thresh->lower_threshold[1]) &&
- (snr <= sq_thresh->lower_threshold[0]))
- {
- newThreshold = WMI_SNR_THRESHOLD4_BELOW;
- } else if ((snr > sq_thresh->lower_threshold[2]) &&
- (snr <= sq_thresh->lower_threshold[1]))
- {
- newThreshold = WMI_SNR_THRESHOLD3_BELOW;
- } else if ((snr > sq_thresh->lower_threshold[3]) &&
- (snr <= sq_thresh->lower_threshold[2]))
- {
- newThreshold = WMI_SNR_THRESHOLD2_BELOW;
- } else if (snr <= sq_thresh->lower_threshold[3]) {
- newThreshold = WMI_SNR_THRESHOLD1_BELOW;
- }
- }
-
- /* Calculate and install the next set of thresholds */
- lower_snr_threshold = ar6000_get_lower_threshold(snr, sq_thresh,
- sq_thresh->lower_threshold_valid_count);
- upper_snr_threshold = ar6000_get_upper_threshold(snr, sq_thresh,
- sq_thresh->upper_threshold_valid_count);
-
- /* Issue a wmi command to install the thresholds */
- cmd.thresholdAbove1_Val = upper_snr_threshold;
- cmd.thresholdBelow1_Val = lower_snr_threshold;
- cmd.weight = sq_thresh->weight;
- cmd.pollTime = sq_thresh->polling_interval;
-
- A_DPRINTF(DBG_WMI, (DBGFMT "snr: %d, threshold: %d, lower: %d, upper: %d\n"
- ,DBGARG, snr, newThreshold, lower_snr_threshold,
- upper_snr_threshold));
-
- snr_event_value = snr;
-
- if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) {
- A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n",
- DBGARG));
- }
- A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, reply->snr);
-
- return 0;
-}
-
-static int
-wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_LQ_THRESHOLD_EVENT *reply;
-
- if (len < sizeof(*reply)) {
- return A_EINVAL;
- }
- reply = (WMI_LQ_THRESHOLD_EVENT *)datap;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt,
- (WMI_LQ_THRESHOLD_VAL) reply->range,
- reply->lq);
-
- return 0;
-}
-
-static int
-wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- u16 ap_info_entry_size;
- WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
- WMI_AP_INFO_V1 *ap_info_v1;
- u8 i;
-
- if (len < sizeof(WMI_APLIST_EVENT)) {
- return A_EINVAL;
- }
-
- if (ev->apListVer == APLIST_VER1) {
- ap_info_entry_size = sizeof(WMI_AP_INFO_V1);
- ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList;
- } else {
- return A_EINVAL;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP));
- if (len < (int)(sizeof(WMI_APLIST_EVENT) +
- (ev->numAP - 1) * ap_info_entry_size))
- {
- return A_EINVAL;
- }
-
- /*
- * AP List Ver1 Contents
- */
- for (i = 0; i < ev->numAP; i++) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\
- "Channel %d\n", i,
- ap_info_v1->bssid[0], ap_info_v1->bssid[1],
- ap_info_v1->bssid[2], ap_info_v1->bssid[3],
- ap_info_v1->bssid[4], ap_info_v1->bssid[5],
- ap_info_v1->channel));
- ap_info_v1++;
- }
- return 0;
-}
-
-static int
-wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- u32 dropped;
-
- dropped = *((u32 *)datap);
- datap += sizeof(dropped);
- len -= sizeof(dropped);
- A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len);
- return 0;
-}
-
-/*
- * Called to send a wmi command. Command specific data is already built
- * on osbuf and current osbuf->data points to it.
- */
-int
-wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
- WMI_SYNC_FLAG syncflag)
-{
- int status;
-#define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID))
- WMI_CMD_HDR *cHdr;
- HTC_ENDPOINT_ID eid = wmip->wmi_endpoint_id;
-
- A_ASSERT(osbuf != NULL);
-
- if (syncflag >= END_WMIFLAG) {
- A_NETBUF_FREE(osbuf);
- return A_EINVAL;
- }
-
- if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
- /*
- * We want to make sure all data currently queued is transmitted before
- * the cmd execution. Establish a new sync point.
- */
- wmi_sync_point(wmip);
- }
-
- if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
- A_NETBUF_FREE(osbuf);
- return A_NO_MEMORY;
- }
-
- cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
- cHdr->commandId = (u16) cmdId;
- cHdr->info1 = 0; // added for virtual interface
-
- /*
- * Only for OPT_TX_CMD, use BE endpoint.
- */
- if (IS_OPT_TX_CMD(cmdId)) {
- if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) {
- A_NETBUF_FREE(osbuf);
- return status;
- }
- eid = A_WMI_Ac2EndpointID(wmip->wmi_devt, WMM_AC_BE);
- }
- A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid);
-
- if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
- /*
- * We want to make sure all new data queued waits for the command to
- * execute. Establish a new sync point.
- */
- wmi_sync_point(wmip);
- }
- return (0);
-#undef IS_OPT_TX_CMD
-}
-
-int
-wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
- WMI_SYNC_FLAG syncflag)
-{
- WMIX_CMD_HDR *cHdr;
-
- if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
- A_NETBUF_FREE(osbuf);
- return A_NO_MEMORY;
- }
-
- cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
- cHdr->commandId = (u32) cmdId;
-
- return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
-}
-
-int
-wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
- DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
- CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen,
- CRYPTO_TYPE groupCrypto, u8 groupCryptoLen,
- int ssidLength, u8 *ssid,
- u8 *bssid, u16 channel, u32 ctrl_flags)
-{
- void *osbuf;
- WMI_CONNECT_CMD *cc;
- wmip->wmi_traffic_class = 100;
-
- if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) {
- return A_EINVAL;
- }
- if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) {
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD));
-
- cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cc, sizeof(*cc));
-
- if (ssidLength)
- {
- memcpy(cc->ssid, ssid, ssidLength);
- }
-
- cc->ssidLength = ssidLength;
- cc->networkType = netType;
- cc->dot11AuthMode = dot11AuthMode;
- cc->authMode = authMode;
- cc->pairwiseCryptoType = pairwiseCrypto;
- cc->pairwiseCryptoLen = pairwiseCryptoLen;
- cc->groupCryptoType = groupCrypto;
- cc->groupCryptoLen = groupCryptoLen;
- cc->channel = channel;
- cc->ctrl_flags = ctrl_flags;
-
- if (bssid != NULL) {
- memcpy(cc->bssid, bssid, ATH_MAC_LEN);
- }
-
- wmip->wmi_pair_crypto_type = pairwiseCrypto;
- wmip->wmi_grp_crypto_type = groupCrypto;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel)
-{
- void *osbuf;
- WMI_RECONNECT_CMD *cc;
- wmip->wmi_traffic_class = 100;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD));
-
- cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cc, sizeof(*cc));
-
- cc->channel = channel;
-
- if (bssid != NULL) {
- memcpy(cc->bssid, bssid, ATH_MAC_LEN);
- }
-
- return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_disconnect_cmd(struct wmi_t *wmip)
-{
- int status;
- wmip->wmi_traffic_class = 100;
-
- /* Bug fix for 24817(elevator bug) - the disconnect command does not
- need to do a SYNC before.*/
- status = wmi_simple_cmd(wmip, WMI_DISCONNECT_CMDID);
-
- return status;
-}
-
-int
-wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
- u32 forceFgScan, u32 isLegacy,
- u32 homeDwellTime, u32 forceScanInterval,
- s8 numChan, u16 *channelList)
-{
- void *osbuf;
- WMI_START_SCAN_CMD *sc;
- s8 size;
-
- size = sizeof (*sc);
-
- if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) {
- return A_EINVAL;
- }
-
- if (numChan) {
- if (numChan > WMI_MAX_CHANNELS) {
- return A_EINVAL;
- }
- size += sizeof(u16) * (numChan - 1);
- }
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf));
- sc->scanType = scanType;
- sc->forceFgScan = forceFgScan;
- sc->isLegacy = isLegacy;
- sc->homeDwellTime = homeDwellTime;
- sc->forceScanInterval = forceScanInterval;
- sc->numChannels = numChan;
- if (numChan) {
- memcpy(sc->channelList, channelList, numChan * sizeof(u16));
- }
-
- return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
- u16 fg_end_sec, u16 bg_sec,
- u16 minact_chdw_msec, u16 maxact_chdw_msec,
- u16 pas_chdw_msec,
- u8 shScanRatio, u8 scanCtrlFlags,
- u32 max_dfsch_act_time, u16 maxact_scan_per_ssid)
-{
- void *osbuf;
- WMI_SCAN_PARAMS_CMD *sc;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*sc));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*sc));
-
- sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(sc, sizeof(*sc));
- sc->fg_start_period = fg_start_sec;
- sc->fg_end_period = fg_end_sec;
- sc->bg_period = bg_sec;
- sc->minact_chdwell_time = minact_chdw_msec;
- sc->maxact_chdwell_time = maxact_chdw_msec;
- sc->pas_chdwell_time = pas_chdw_msec;
- sc->shortScanRatio = shScanRatio;
- sc->scanCtrlFlags = scanCtrlFlags;
- sc->max_dfsch_act_time = max_dfsch_act_time;
- sc->maxact_scan_per_ssid = maxact_scan_per_ssid;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask)
-{
- void *osbuf;
- WMI_BSS_FILTER_CMD *cmd;
-
- if (filter >= LAST_BSS_FILTER) {
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->bssFilter = filter;
- cmd->ieMask = ieMask;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
- u8 ssidLength, u8 *ssid)
-{
- void *osbuf;
- WMI_PROBED_SSID_CMD *cmd;
-
- if (index > MAX_PROBED_SSID_INDEX) {
- return A_EINVAL;
- }
- if (ssidLength > sizeof(cmd->ssid)) {
- return A_EINVAL;
- }
- if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) {
- return A_EINVAL;
- }
- if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) {
- return A_EINVAL;
- }
-
- if (flag & SPECIFIC_SSID_FLAG) {
- is_probe_ssid = true;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->entryIndex = index;
- cmd->flag = flag;
- cmd->ssidLength = ssidLength;
- memcpy(cmd->ssid, ssid, ssidLength);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons)
-{
- void *osbuf;
- WMI_LISTEN_INT_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->listenInterval = listenInterval;
- cmd->numBeacons = listenBeacons;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons)
-{
- void *osbuf;
- WMI_BMISS_TIME_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->bmissTime = bmissTime;
- cmd->numBeacons = bmissBeacons;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
- u8 ieLen, u8 *ieInfo)
-{
- void *osbuf;
- WMI_SET_ASSOC_INFO_CMD *cmd;
- u16 cmdLen;
-
- cmdLen = sizeof(*cmd) + ieLen - 1;
- osbuf = A_NETBUF_ALLOC(cmdLen);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, cmdLen);
-
- cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, cmdLen);
- cmd->ieType = ieType;
- cmd->bufferSize = ieLen;
- memcpy(cmd->assocInfo, ieInfo, ieLen);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode)
-{
- void *osbuf;
- WMI_POWER_MODE_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->powerMode = powerMode;
- wmip->wmi_powerMode = powerMode;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
- u16 atim_windows, u16 timeout_value)
-{
- void *osbuf;
- WMI_IBSS_PM_CAPS_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->power_saving = pmEnable;
- cmd->ttl = ttl;
- cmd->atim_windows = atim_windows;
- cmd->timeout_value = timeout_value;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
- u32 ps_period, u8 sleep_period)
-{
- void *osbuf;
- WMI_AP_PS_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_AP_PS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->psType = psType;
- cmd->idle_time = idle_time;
- cmd->ps_period = ps_period;
- cmd->sleep_period = sleep_period;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_AP_PS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
- u16 psPollNum, u16 dtimPolicy,
- u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
- u16 ps_fail_event_policy)
-{
- void *osbuf;
- WMI_POWER_PARAMS_CMD *pm;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*pm));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*pm));
-
- pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(pm, sizeof(*pm));
- pm->idle_period = idlePeriod;
- pm->pspoll_number = psPollNum;
- pm->dtim_policy = dtimPolicy;
- pm->tx_wakeup_policy = tx_wakeup_policy;
- pm->num_tx_to_wakeup = num_tx_to_wakeup;
- pm->ps_fail_event_policy = ps_fail_event_policy;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout)
-{
- void *osbuf;
- WMI_DISC_TIMEOUT_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->disconnectTimeout = timeout;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType,
- u8 keyUsage, u8 keyLength, u8 *keyRSC,
- u8 *keyMaterial, u8 key_op_ctrl, u8 *macAddr,
- WMI_SYNC_FLAG sync_flag)
-{
- void *osbuf;
- WMI_ADD_CIPHER_KEY_CMD *cmd;
-
- if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) ||
- (keyMaterial == NULL))
- {
- return A_EINVAL;
- }
-
- if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) {
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->keyIndex = keyIndex;
- cmd->keyType = keyType;
- cmd->keyUsage = keyUsage;
- cmd->keyLength = keyLength;
- memcpy(cmd->key, keyMaterial, keyLength);
-#ifdef WAPI_ENABLE
- if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) {
-#else
- if (NULL != keyRSC) {
-#endif // WAPI_ENABLE
- memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
- }
- cmd->key_op_ctrl = key_op_ctrl;
-
- if(macAddr) {
- memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN);
- }
-
- return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
-}
-
-int
-wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk)
-{
- void *osbuf;
- WMI_ADD_KRK_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- memcpy(cmd->krk, krk, WMI_KRK_LEN);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_delete_krk_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID);
-}
-
-int
-wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex)
-{
- void *osbuf;
- WMI_DELETE_CIPHER_KEY_CMD *cmd;
-
- if (keyIndex > WMI_MAX_KEY_INDEX) {
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->keyIndex = keyIndex;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
- bool set)
-{
- void *osbuf;
- WMI_SET_PMKID_CMD *cmd;
-
- if (bssid == NULL) {
- return A_EINVAL;
- }
-
- if ((set == true) && (pmkId == NULL)) {
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf));
- memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
- if (set == true) {
- memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
- cmd->enable = PMKID_ENABLE;
- } else {
- A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
- cmd->enable = PMKID_DISABLE;
- }
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en)
-{
- void *osbuf;
- WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_akmp_params_cmd(struct wmi_t *wmip,
- WMI_SET_AKMP_PARAMS_CMD *akmpParams)
-{
- void *osbuf;
- WMI_SET_AKMP_PARAMS_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->akmpInfo = akmpParams->akmpInfo;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
- WMI_SET_PMKID_LIST_CMD *pmkInfo)
-{
- void *osbuf;
- WMI_SET_PMKID_LIST_CMD *cmd;
- u16 cmdLen;
- u8 i;
-
- cmdLen = sizeof(pmkInfo->numPMKID) +
- pmkInfo->numPMKID * sizeof(WMI_PMKID);
-
- osbuf = A_NETBUF_ALLOC(cmdLen);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, cmdLen);
- cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->numPMKID = pmkInfo->numPMKID;
-
- for (i = 0; i < cmd->numPMKID; i++) {
- memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
- WMI_PMKID_LEN);
- }
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID);
-}
-
-int
-wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid)
-{
- WMI_DATA_HDR *dtHdr;
-
- A_ASSERT( eid != wmip->wmi_endpoint_id);
- A_ASSERT(osbuf != NULL);
-
- if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
- return A_NO_MEMORY;
- }
-
- dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
- dtHdr->info =
- (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT;
-
- dtHdr->info3 = 0;
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter - eid %d\n", DBGARG, eid));
-
- return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid));
-}
-
-typedef struct _WMI_DATA_SYNC_BUFS {
- u8 trafficClass;
- void *osbuf;
-}WMI_DATA_SYNC_BUFS;
-
-static int
-wmi_sync_point(struct wmi_t *wmip)
-{
- void *cmd_osbuf;
- WMI_SYNC_CMD *cmd;
- WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC];
- u8 i,numPriStreams=0;
- int status = 0;
-
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- memset(dataSyncBufs,0,sizeof(dataSyncBufs));
-
- /* lock out while we walk through the priority list and assemble our local array */
- LOCK_WMI(wmip);
-
- for (i=0; i < WMM_NUM_AC ; i++) {
- if (wmip->wmi_fatPipeExists & (1 << i)) {
- numPriStreams++;
- dataSyncBufs[numPriStreams-1].trafficClass = i;
- }
- }
-
- UNLOCK_WMI(wmip);
-
- /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */
-
- do {
- /*
- * We allocate all network buffers needed so we will be able to
- * send all required frames.
- */
- cmd_osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (cmd_osbuf == NULL) {
- status = A_NO_MEMORY;
- break;
- }
-
- A_NETBUF_PUT(cmd_osbuf, sizeof(*cmd));
-
- cmd = (WMI_SYNC_CMD *)(A_NETBUF_DATA(cmd_osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
-
- /* In the SYNC cmd sent on the control Ep, send a bitmap of the data
- * eps on which the Data Sync will be sent
- */
- cmd->dataSyncMap = wmip->wmi_fatPipeExists;
-
- for (i=0; i < numPriStreams ; i++) {
- dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0);
- if (dataSyncBufs[i].osbuf == NULL) {
- status = A_NO_MEMORY;
- break;
- }
- } //end for
-
- /* if Buffer allocation for any of the dataSync fails, then do not
- * send the Synchronize cmd on the control ep
- */
- if (status) {
- break;
- }
-
- /*
- * Send sync cmd followed by sync data messages on all endpoints being
- * used
- */
- status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
- NO_SYNC_WMIFLAG);
-
- if (status) {
- break;
- }
- /* cmd buffer sent, we no longer own it */
- cmd_osbuf = NULL;
-
- for(i=0; i < numPriStreams; i++) {
- A_ASSERT(dataSyncBufs[i].osbuf != NULL);
- status = wmi_dataSync_send(wmip,
- dataSyncBufs[i].osbuf,
- A_WMI_Ac2EndpointID(wmip->wmi_devt,
- dataSyncBufs[i].
- trafficClass)
- );
-
- if (status) {
- break;
- }
- /* we don't own this buffer anymore, NULL it out of the array so it
- * won't get cleaned up */
- dataSyncBufs[i].osbuf = NULL;
- } //end for
-
- } while(false);
-
- /* free up any resources left over (possibly due to an error) */
-
- if (cmd_osbuf != NULL) {
- A_NETBUF_FREE(cmd_osbuf);
- }
-
- for (i = 0; i < numPriStreams; i++) {
- if (dataSyncBufs[i].osbuf != NULL) {
- A_NETBUF_FREE(dataSyncBufs[i].osbuf);
- }
- }
-
- return (status);
-}
-
-int
-wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
-{
- void *osbuf;
- WMI_CREATE_PSTREAM_CMD *cmd;
- u8 fatPipeExistsForAC=0;
- s32 minimalPHY = 0;
- s32 nominalPHY = 0;
-
- /* Validate all the parameters. */
- if( !((params->userPriority < 8) &&
- (params->userPriority <= 0x7) &&
- (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) &&
- (params->trafficDirection == UPLINK_TRAFFIC ||
- params->trafficDirection == DNLINK_TRAFFIC ||
- params->trafficDirection == BIDIR_TRAFFIC) &&
- (params->trafficType == TRAFFIC_TYPE_APERIODIC ||
- params->trafficType == TRAFFIC_TYPE_PERIODIC ) &&
- (params->voicePSCapability == DISABLE_FOR_THIS_AC ||
- params->voicePSCapability == ENABLE_FOR_THIS_AC ||
- params->voicePSCapability == ENABLE_FOR_ALL_AC) &&
- (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) )
- {
- return A_EINVAL;
- }
-
- //
- // check nominal PHY rate is >= minimalPHY, so that DUT
- // can allow TSRS IE
- //
-
- // get the physical rate
- minimalPHY = ((params->minPhyRate / 1000)/1000); // unit of bps
-
- // check minimal phy < nominal phy rate
- //
- if (params->nominalPHY >= minimalPHY)
- {
- nominalPHY = (params->nominalPHY * 1000)/500; // unit of 500 kbps
- A_DPRINTF(DBG_WMI,
- (DBGFMT "TSRS IE Enabled::MinPhy %x->NominalPhy ===> %x\n", DBGARG,
- minimalPHY, nominalPHY));
-
- params->nominalPHY = nominalPHY;
- }
- else
- {
- params->nominalPHY = 0;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- A_DPRINTF(DBG_WMI,
- (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG,
- params->trafficClass, params->tsid));
-
- cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- memcpy(cmd, params, sizeof(*cmd));
-
- /* this is an implicitly created Fat pipe */
- if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) {
- LOCK_WMI(wmip);
- fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
- wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
- UNLOCK_WMI(wmip);
- } else {
- /* this is an explicitly created thin stream within a fat pipe */
- LOCK_WMI(wmip);
- fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
- wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<<params->tsid);
- /* if a thinstream becomes active, the fat pipe automatically
- * becomes active
- */
- wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
- UNLOCK_WMI(wmip);
- }
-
- /* Indicate activty change to driver layer only if this is the
- * first TSID to get created in this AC explicitly or an implicit
- * fat pipe is getting created.
- */
- if (!fatPipeExistsForAC) {
- A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass);
- }
-
- /* mike: should be SYNC_BEFORE_WMIFLAG */
- return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid)
-{
- void *osbuf;
- WMI_DELETE_PSTREAM_CMD *cmd;
- int status;
- u16 activeTsids=0;
-
- /* validate the parameters */
- if (trafficClass > 3) {
- A_DPRINTF(DBG_WMI, (DBGFMT "Invalid trafficClass: %d\n", DBGARG, trafficClass));
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
-
- cmd->trafficClass = trafficClass;
- cmd->tsid = tsid;
-
- LOCK_WMI(wmip);
- activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
- UNLOCK_WMI(wmip);
-
- /* Check if the tsid was created & exists */
- if (!(activeTsids & (1<<tsid))) {
-
- A_NETBUF_FREE(osbuf);
- A_DPRINTF(DBG_WMI,
- (DBGFMT "TSID %d does'nt exist for trafficClass: %d\n", DBGARG, tsid, trafficClass));
- /* TODO: return a more appropriate err code */
- return A_ERROR;
- }
-
- A_DPRINTF(DBG_WMI,
- (DBGFMT "Sending delete_pstream_cmd: trafficClass: %d tsid=%d\n", DBGARG, trafficClass, tsid));
-
- status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID,
- SYNC_BEFORE_WMIFLAG));
-
- LOCK_WMI(wmip);
- wmip->wmi_streamExistsForAC[trafficClass] &= ~(1<<tsid);
- activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
- UNLOCK_WMI(wmip);
-
-
- /* Indicate stream inactivity to driver layer only if all tsids
- * within this AC are deleted.
- */
- if(!activeTsids) {
- A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass);
- wmip->wmi_fatPipeExists &= ~(1<<trafficClass);
- }
-
- return status;
-}
-
-int
-wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask)
-{
- void *osbuf;
- WMI_FRAME_RATES_CMD *cmd;
- u8 frameType;
-
- A_DPRINTF(DBG_WMI,
- (DBGFMT " type %02X, subType %02X, rateMask %04x\n", DBGARG, type, subType, rateMask));
-
- if((type != IEEE80211_FRAME_TYPE_MGT && type != IEEE80211_FRAME_TYPE_CTL) ||
- (subType > 15)){
-
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
-
- frameType = (u8)((subType << 4) | type);
-
- cmd->bEnableMask = bEnable;
- cmd->frameType = frameType;
- cmd->frameRateMask = rateMask;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_FRAMERATES_CMDID, NO_SYNC_WMIFLAG));
-}
-
-/*
- * used to set the bit rate. rate is in Kbps. If rate == -1
- * then auto selection is used.
- */
-int
-wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate)
-{
- void *osbuf;
- WMI_BIT_RATE_CMD *cmd;
- s8 drix, mrix, crix, ret_val;
-
- if (dataRate != -1) {
- ret_val = wmi_validate_bitrate(wmip, dataRate, &drix);
- if(ret_val == A_EINVAL){
- return A_EINVAL;
- }
- } else {
- drix = -1;
- }
-
- if (mgmtRate != -1) {
- ret_val = wmi_validate_bitrate(wmip, mgmtRate, &mrix);
- if(ret_val == A_EINVAL){
- return A_EINVAL;
- }
- } else {
- mrix = -1;
- }
- if (ctlRate != -1) {
- ret_val = wmi_validate_bitrate(wmip, ctlRate, &crix);
- if(ret_val == A_EINVAL){
- return A_EINVAL;
- }
- } else {
- crix = -1;
- }
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
-
- cmd->rateIndex = drix;
- cmd->mgmtRateIndex = mrix;
- cmd->ctlRateIndex = crix;
-
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_get_bitrate_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID);
-}
-
-/*
- * Returns true iff the given rate index is legal in the current PHY mode.
- */
-bool
-wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex)
-{
- WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode;
- bool isValid = true;
- switch(phyMode) {
- case WMI_11A_MODE:
- if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){
- if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
- isValid = false;
- }
- } else {
- if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) {
- isValid = false;
- }
- }
- break;
-
- case WMI_11B_MODE:
- if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
- isValid = false;
- }
- break;
-
- case WMI_11GONLY_MODE:
- if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
- if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
- isValid = false;
- }
- } else {
- if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
- isValid = false;
- }
- }
- break;
-
- case WMI_11G_MODE:
- case WMI_11AG_MODE:
- if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
- if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
- isValid = false;
- }
- } else {
- if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
- isValid = false;
- }
- }
- break;
- default:
- A_ASSERT(false);
- break;
- }
-
- return isValid;
-}
-
-s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx)
-{
- s8 i;
-
- for (i=0;;i++)
- {
- if (wmi_rateTable[(u32) i][0] == 0) {
- return A_EINVAL;
- }
- if (wmi_rateTable[(u32) i][0] == rate) {
- break;
- }
- }
-
- if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) {
- return A_EINVAL;
- }
-
- *rate_idx = i;
- return 0;
-}
-
-int
-wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask)
-{
- void *osbuf;
- WMI_FIX_RATES_CMD *cmd;
-#if 0
- s32 rateIndex;
-/* This check does not work for AR6003 as the HT modes are enabled only when
- * the STA is connected to a HT_BSS and is not based only on channel. It is
- * safe to skip this check however because rate control will only use rates
- * that are permitted by the valid rate mask and the fix rate mask. Meaning
- * the fix rate mask is not sufficient by itself to cause an invalid rate
- * to be used. */
- /* Make sure all rates in the mask are valid in the current PHY mode */
- for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) {
- if((1 << rateIndex) & (u32)fixRatesMask) {
- if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) {
- A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG));
- return A_EINVAL;
- }
- }
- }
-#endif
-
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
-
- cmd->fixRateMask = fixRatesMask;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_get_ratemask_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID);
-}
-
-int
-wmi_get_channelList_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID);
-}
-
-/*
- * used to generate a wmi sey channel Parameters cmd.
- * mode should always be specified and corresponds to the phy mode of the
- * wlan.
- * numChan should alway sbe specified. If zero indicates that all available
- * channels should be used.
- * channelList is an array of channel frequencies (in Mhz) which the radio
- * should limit its operation to. It should be NULL if numChan == 0. Size of
- * array should correspond to numChan entries.
- */
-int
-wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
- WMI_PHY_MODE mode, s8 numChan,
- u16 *channelList)
-{
- void *osbuf;
- WMI_CHANNEL_PARAMS_CMD *cmd;
- s8 size;
-
- size = sizeof (*cmd);
-
- if (numChan) {
- if (numChan > WMI_MAX_CHANNELS) {
- return A_EINVAL;
- }
- size += sizeof(u16) * (numChan - 1);
- }
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
-
- wmip->wmi_phyMode = mode;
- cmd->scanParam = scanParam;
- cmd->phyMode = mode;
- cmd->numChannels = numChan;
- memcpy(cmd->channelList, channelList, numChan * sizeof(u16));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-void
-wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
-{
- SQ_THRESHOLD_PARAMS *sq_thresh =
- &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
- /*
- * Parse the command and store the threshold values here. The checks
- * for valid values can be put here
- */
- sq_thresh->weight = rssiCmd->weight;
- sq_thresh->polling_interval = rssiCmd->pollTime;
-
- sq_thresh->upper_threshold[0] = rssiCmd->thresholdAbove1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->upper_threshold[1] = rssiCmd->thresholdAbove2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->upper_threshold[2] = rssiCmd->thresholdAbove3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->upper_threshold[3] = rssiCmd->thresholdAbove4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->upper_threshold[4] = rssiCmd->thresholdAbove5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->upper_threshold[5] = rssiCmd->thresholdAbove6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->upper_threshold_valid_count = 6;
-
- /* List sorted in descending order */
- sq_thresh->lower_threshold[0] = rssiCmd->thresholdBelow6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->lower_threshold[1] = rssiCmd->thresholdBelow5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->lower_threshold[2] = rssiCmd->thresholdBelow4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->lower_threshold[3] = rssiCmd->thresholdBelow3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->lower_threshold[4] = rssiCmd->thresholdBelow2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->lower_threshold[5] = rssiCmd->thresholdBelow1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
- sq_thresh->lower_threshold_valid_count = 6;
-
- if (!rssi_event_value) {
- /*
- * Configuring the thresholds to their extremes allows the host to get an
- * event from the target which is used for the configuring the correct
- * thresholds
- */
- rssiCmd->thresholdAbove1_Val = sq_thresh->upper_threshold[0];
- rssiCmd->thresholdBelow1_Val = sq_thresh->lower_threshold[0];
- } else {
- /*
- * In case the user issues multiple times of rssi_threshold_setting,
- * we should not use the extreames anymore, the target does not expect that.
- */
- rssiCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(rssi_event_value, sq_thresh,
- sq_thresh->upper_threshold_valid_count);
- rssiCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(rssi_event_value, sq_thresh,
- sq_thresh->lower_threshold_valid_count);
-}
-}
-
-int
-wmi_set_rssi_threshold_params(struct wmi_t *wmip,
- WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
-{
-
- /* Check these values are in ascending order */
- if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val ||
- rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val ||
- rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val ||
- rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val ||
- rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val ||
- rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val ||
- rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val ||
- rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val ||
- rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val ||
- rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val)
- {
- return A_EINVAL;
- }
-
- wmi_cache_configure_rssithreshold(wmip, rssiCmd);
-
- return (wmi_send_rssi_threshold_params(wmip, rssiCmd));
-}
-
-int
-wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd)
-{
- void *osbuf;
- WMI_SET_IP_CMD *cmd;
-
- /* Multicast address are not valid */
- if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) ||
- (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) {
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_IP_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD));
- cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf));
- memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
- WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
-{
- void *osbuf;
- s8 size;
- WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
- u16 activeTsids=0;
- u8 streamExists=0;
- u8 i;
-
- if( hostModeCmd->awake == hostModeCmd->asleep) {
- return A_EINVAL;
- }
-
- size = sizeof (*cmd);
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
- memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
-
- if(hostModeCmd->asleep) {
- /*
- * Relinquish credits from all implicitly created pstreams since when we
- * go to sleep. If user created explicit thinstreams exists with in a
- * fatpipe leave them intact for the user to delete
- */
- LOCK_WMI(wmip);
- streamExists = wmip->wmi_fatPipeExists;
- UNLOCK_WMI(wmip);
-
- for(i=0;i< WMM_NUM_AC;i++) {
- if (streamExists & (1<<i)) {
- LOCK_WMI(wmip);
- activeTsids = wmip->wmi_streamExistsForAC[i];
- UNLOCK_WMI(wmip);
- /* If there are no user created thin streams delete the fatpipe */
- if(!activeTsids) {
- streamExists &= ~(1<<i);
- /*Indicate inactivity to drv layer for this fatpipe(pstream)*/
- A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt,i);
- }
- }
- }
-
- /* Update the fatpipes that exists*/
- LOCK_WMI(wmip);
- wmip->wmi_fatPipeExists = streamExists;
- UNLOCK_WMI(wmip);
- }
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_wow_mode_cmd(struct wmi_t *wmip,
- WMI_SET_WOW_MODE_CMD *wowModeCmd)
-{
- void *osbuf;
- s8 size;
- WMI_SET_WOW_MODE_CMD *cmd;
-
- size = sizeof (*cmd);
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
- memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_get_wow_list_cmd(struct wmi_t *wmip,
- WMI_GET_WOW_LIST_CMD *wowListCmd)
-{
- void *osbuf;
- s8 size;
- WMI_GET_WOW_LIST_CMD *cmd;
-
- size = sizeof (*cmd);
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
- memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
- NO_SYNC_WMIFLAG));
-
-}
-
-static int
-wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_GET_WOW_LIST_REPLY *reply;
-
- if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) {
- return A_EINVAL;
- }
- reply = (WMI_GET_WOW_LIST_REPLY *)datap;
-
- A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
- reply);
-
- return 0;
-}
-
-int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
- WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
- u8 *pattern, u8 *mask,
- u8 pattern_size)
-{
- void *osbuf;
- s8 size;
- WMI_ADD_WOW_PATTERN_CMD *cmd;
- u8 *filter_mask = NULL;
-
- size = sizeof (*cmd);
-
- size += ((2 * addWowCmd->filter_size)* sizeof(u8));
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->filter_list_id = addWowCmd->filter_list_id;
- cmd->filter_offset = addWowCmd->filter_offset;
- cmd->filter_size = addWowCmd->filter_size;
-
- memcpy(cmd->filter, pattern, addWowCmd->filter_size);
-
- filter_mask = (u8 *)(cmd->filter + cmd->filter_size);
- memcpy(filter_mask, mask, addWowCmd->filter_size);
-
-
- return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
- WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
-{
- void *osbuf;
- s8 size;
- WMI_DEL_WOW_PATTERN_CMD *cmd;
-
- size = sizeof (*cmd);
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
- memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
- NO_SYNC_WMIFLAG));
-
-}
-
-void
-wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
-{
- SQ_THRESHOLD_PARAMS *sq_thresh =
- &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
- /*
- * Parse the command and store the threshold values here. The checks
- * for valid values can be put here
- */
- sq_thresh->weight = snrCmd->weight;
- sq_thresh->polling_interval = snrCmd->pollTime;
-
- sq_thresh->upper_threshold[0] = snrCmd->thresholdAbove1_Val;
- sq_thresh->upper_threshold[1] = snrCmd->thresholdAbove2_Val;
- sq_thresh->upper_threshold[2] = snrCmd->thresholdAbove3_Val;
- sq_thresh->upper_threshold[3] = snrCmd->thresholdAbove4_Val;
- sq_thresh->upper_threshold_valid_count = 4;
-
- /* List sorted in descending order */
- sq_thresh->lower_threshold[0] = snrCmd->thresholdBelow4_Val;
- sq_thresh->lower_threshold[1] = snrCmd->thresholdBelow3_Val;
- sq_thresh->lower_threshold[2] = snrCmd->thresholdBelow2_Val;
- sq_thresh->lower_threshold[3] = snrCmd->thresholdBelow1_Val;
- sq_thresh->lower_threshold_valid_count = 4;
-
- if (!snr_event_value) {
- /*
- * Configuring the thresholds to their extremes allows the host to get an
- * event from the target which is used for the configuring the correct
- * thresholds
- */
- snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0];
- snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0];
- } else {
- /*
- * In case the user issues multiple times of snr_threshold_setting,
- * we should not use the extreames anymore, the target does not expect that.
- */
- snrCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(snr_event_value, sq_thresh,
- sq_thresh->upper_threshold_valid_count);
- snrCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(snr_event_value, sq_thresh,
- sq_thresh->lower_threshold_valid_count);
- }
-
-}
-int
-wmi_set_snr_threshold_params(struct wmi_t *wmip,
- WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
-{
- if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val ||
- snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val ||
- snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val ||
- snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val ||
- snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val ||
- snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val)
- {
- return A_EINVAL;
- }
- wmi_cache_configure_snrthreshold(wmip, snrCmd);
- return (wmi_send_snr_threshold_params(wmip, snrCmd));
-}
-
-int
-wmi_clr_rssi_snr(struct wmi_t *wmip)
-{
- void *osbuf;
-
- osbuf = A_NETBUF_ALLOC(sizeof(int));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_lq_threshold_params(struct wmi_t *wmip,
- WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
-{
- void *osbuf;
- s8 size;
- WMI_LQ_THRESHOLD_PARAMS_CMD *cmd;
- /* These values are in ascending order */
- if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val ||
- lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val ||
- lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val ||
- lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val ||
- lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val ||
- lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) {
-
- return A_EINVAL;
- }
-
- size = sizeof (*cmd);
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
- memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask)
-{
- void *osbuf;
- s8 size;
- WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
-
- size = sizeof (*cmd);
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
-
- cmd->bitmask = mask;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source)
-{
- void *osbuf;
- WMIX_HB_CHALLENGE_RESP_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->cookie = cookie;
- cmd->source = source;
-
- return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
- u16 tsr, bool rep, u16 size,
- u32 valid)
-{
- void *osbuf;
- WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->config.cfgmmask = mmask;
- cmd->config.cfgtsr = tsr;
- cmd->config.cfgrep = rep;
- cmd->config.cfgsize = size;
- cmd->config.cfgvalid = valid;
-
- return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_get_stats_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID);
-}
-
-int
-wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid)
-{
- void *osbuf;
- WMI_ADD_BAD_AP_CMD *cmd;
-
- if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) {
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->badApIndex = apIndex;
- memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG));
-}
-
-int
-wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex)
-{
- void *osbuf;
- WMI_DELETE_BAD_AP_CMD *cmd;
-
- if (apIndex > WMI_MAX_BAD_AP_INDEX) {
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->badApIndex = apIndex;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_abort_scan_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID);
-}
-
-int
-wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM)
-{
- void *osbuf;
- WMI_SET_TX_PWR_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->dbM = dbM;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_get_txPwr_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID);
-}
-
-u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass)
-{
- u16 activeTsids=0;
-
- LOCK_WMI(wmip);
- activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
- UNLOCK_WMI(wmip);
-
- return activeTsids;
-}
-
-int
-wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID);
-}
-
-int
-wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType)
-{
- void *osbuf;
- u32 size = sizeof(u8);
- WMI_TARGET_ROAM_DATA *cmd;
-
- osbuf = A_NETBUF_ALLOC(size); /* no payload */
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf));
- cmd->roamDataType = roamDataType;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
- u8 size)
-{
- void *osbuf;
- WMI_SET_ROAM_CTRL_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
-
- memcpy(cmd, p, size);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
- WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
- u8 size)
-{
- void *osbuf;
- WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
-
- /* These timers can't be zero */
- if(!pCmd->psPollTimeout || !pCmd->triggerTimeout ||
- !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD ||
- pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) ||
- !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD ||
- pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD))
- return A_EINVAL;
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
-
- memcpy(cmd, pCmd, size);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop, u8 eCWmin,
- u8 eCWmax, u8 aifsn)
-{
- void *osbuf;
- WMI_SET_ACCESS_PARAMS_CMD *cmd;
-
- if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) ||
- (aifsn > WMI_MAX_AIFSN_ACPARAM) || (ac >= WMM_NUM_AC))
- {
- return A_EINVAL;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->txop = txop;
- cmd->eCWmin = eCWmin;
- cmd->eCWmax = eCWmax;
- cmd->aifsn = aifsn;
- cmd->ac = ac;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
- u8 trafficClass, u8 maxRetries,
- u8 enableNotify)
-{
- void *osbuf;
- WMI_SET_RETRY_LIMITS_CMD *cmd;
-
- if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) &&
- (frameType != DATA_FRAMETYPE))
- {
- return A_EINVAL;
- }
-
- if (maxRetries > WMI_MAX_RETRIES) {
- return A_EINVAL;
- }
-
- if (frameType != DATA_FRAMETYPE) {
- trafficClass = 0;
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->frameType = frameType;
- cmd->trafficClass = trafficClass;
- cmd->maxRetries = maxRetries;
- cmd->enableNotify = enableNotify;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-void
-wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid)
-{
- if (bssid != NULL) {
- memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
- }
-}
-
-int
-wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode)
-{
- void *osbuf;
- WMI_SET_OPT_MODE_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->optMode = optMode;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID,
- SYNC_BOTH_WMIFLAG));
-}
-
-int
-wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
- u8 frmType,
- u8 *dstMacAddr,
- u8 *bssid,
- u16 optIEDataLen,
- u8 *optIEData)
-{
- void *osbuf;
- WMI_OPT_TX_FRAME_CMD *cmd;
- osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd)));
-
- cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1));
-
- cmd->frmType = frmType;
- cmd->optIEDataLen = optIEDataLen;
- //cmd->optIEData = (u8 *)((int)cmd + sizeof(*cmd));
- memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
- memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
- memcpy(&cmd->optIEData[0], optIEData, optIEDataLen);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl)
-{
- void *osbuf;
- WMI_BEACON_INT_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->beaconInterval = intvl;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-
-int
-wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize)
-{
- void *osbuf;
- WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->voicePktSize = voicePktSize;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-
-int
-wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen)
-{
- void *osbuf;
- WMI_SET_MAX_SP_LEN_CMD *cmd;
-
- /* maxSPLen is a two-bit value. If user trys to set anything
- * other than this, then its invalid
- */
- if(maxSPLen & ~0x03)
- return A_EINVAL;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->maxSPLen = maxSPLen;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-u8 wmi_determine_userPriority(
- u8 *pkt,
- u32 layer2Pri)
-{
- u8 ipPri;
- iphdr *ipHdr = (iphdr *)pkt;
-
- /* Determine IPTOS priority */
- /*
- * IP Tos format :
- * (Refer Pg 57 WMM-test-plan-v1.2)
- * IP-TOS - 8bits
- * : DSCP(6-bits) ECN(2-bits)
- * : DSCP - P2 P1 P0 X X X
- * where (P2 P1 P0) form 802.1D
- */
- ipPri = ipHdr->ip_tos >> 5;
- ipPri &= 0x7;
-
- if ((layer2Pri & 0x7) > ipPri)
- return ((u8)layer2Pri & 0x7);
- else
- return ipPri;
-}
-
-u8 convert_userPriority_to_trafficClass(u8 userPriority)
-{
- return (up_to_ac[userPriority & 0x7]);
-}
-
-u8 wmi_get_power_mode_cmd(struct wmi_t *wmip)
-{
- return wmip->wmi_powerMode;
-}
-
-int
-wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
-{
- int ret = 0;
-
-#define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0)
-#define TSPEC_SERVICE_START_TIME_ATHEROS_DEF 0
-#define TSPEC_MAX_BURST_SIZE_ATHEROS_DEF 0
-#define TSPEC_DELAY_BOUND_ATHEROS_DEF 0
-#define TSPEC_MEDIUM_TIME_ATHEROS_DEF 0
-#define TSPEC_SBA_ATHEROS_DEF 0x2000 /* factor is 1 */
-
- /* Verify TSPEC params for ATHEROS compliance */
- if(tspecCompliance == ATHEROS_COMPLIANCE) {
- if ((pCmd->suspensionInt != TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF) ||
- (pCmd->serviceStartTime != TSPEC_SERVICE_START_TIME_ATHEROS_DEF) ||
- (pCmd->minDataRate != pCmd->meanDataRate) ||
- (pCmd->minDataRate != pCmd->peakDataRate) ||
- (pCmd->maxBurstSize != TSPEC_MAX_BURST_SIZE_ATHEROS_DEF) ||
- (pCmd->delayBound != TSPEC_DELAY_BOUND_ATHEROS_DEF) ||
- (pCmd->sba != TSPEC_SBA_ATHEROS_DEF) ||
- (pCmd->mediumTime != TSPEC_MEDIUM_TIME_ATHEROS_DEF)) {
-
- A_DPRINTF(DBG_WMI, (DBGFMT "Invalid TSPEC params\n", DBGARG));
- //A_PRINTF("%s: Invalid TSPEC params\n", __func__);
- ret = A_EINVAL;
- }
- }
-
- return ret;
-}
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-static int
-wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- ar6000_testmode_rx_report_event(wmip->wmi_devt, datap, len);
-
- return 0;
-}
-
-#endif /* CONFIG_HOST_TCMD_SUPPORT*/
-
-int
-wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode)
-{
- void *osbuf;
- WMI_SET_AUTH_MODE_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->mode = mode;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode)
-{
- void *osbuf;
- WMI_SET_REASSOC_MODE_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->mode = mode;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy)
-{
- void *osbuf;
- WMI_SET_LPREAMBLE_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->status = status;
- cmd->preamblePolicy = preamblePolicy;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold)
-{
- void *osbuf;
- WMI_SET_RTS_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->threshold = threshold;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
-{
- void *osbuf;
- WMI_SET_WMM_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->status = status;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status)
-{
- void *osbuf;
- WMI_SET_QOS_SUPP_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_QOS_SUPP_CMD*)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->status = status;
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_QOS_SUPP_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-
-int
-wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
-{
- void *osbuf;
- WMI_SET_WMM_TXOP_CMD *cmd;
-
- if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) )
- return A_EINVAL;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->txopEnable = cfg;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_set_country(struct wmi_t *wmip, u8 *countryCode)
-{
- void *osbuf;
- WMI_AP_SET_COUNTRY_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- memcpy(cmd->countryCode,countryCode,3);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-#ifdef CONFIG_HOST_TCMD_SUPPORT
-/* WMI layer doesn't need to know the data type of the test cmd.
- This would be beneficial for customers like Qualcomm, who might
- have different test command requirements from different manufacturers
- */
-int
-wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len)
-{
- void *osbuf;
- char *data;
-
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- osbuf= A_NETBUF_ALLOC(len);
- if(osbuf == NULL)
- {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, len);
- data = A_NETBUF_DATA(osbuf);
- memcpy(data, buf, len);
-
- return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-#endif
-
-int
-wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status)
-{
- void *osbuf;
- WMI_SET_BT_STATUS_CMD *cmd;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Enter - streamType=%d, status=%d\n", streamType, status));
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->streamType = streamType;
- cmd->status = status;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
-{
- void *osbuf;
- WMI_SET_BT_PARAMS_CMD* alloc_cmd;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("cmd params is %d\n", cmd->paramType));
-
- if (cmd->paramType == BT_PARAM_SCO) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("sco params %d %d %d %d %d %d %d %d %d %d %d %d\n", cmd->info.scoParams.numScoCyclesForceTrigger,
- cmd->info.scoParams.dataResponseTimeout,
- cmd->info.scoParams.stompScoRules,
- cmd->info.scoParams.scoOptFlags,
- cmd->info.scoParams.stompDutyCyleVal,
- cmd->info.scoParams.stompDutyCyleMaxVal,
- cmd->info.scoParams.psPollLatencyFraction,
- cmd->info.scoParams.noSCOSlots,
- cmd->info.scoParams.noIdleSlots,
- cmd->info.scoParams.scoOptOffRssi,
- cmd->info.scoParams.scoOptOnRssi,
- cmd->info.scoParams.scoOptRtsCount));
- }
- else if (cmd->paramType == BT_PARAM_A2DP) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("A2DP params %d %d %d %d %d %d %d %d\n", cmd->info.a2dpParams.a2dpWlanUsageLimit,
- cmd->info.a2dpParams.a2dpBurstCntMin,
- cmd->info.a2dpParams.a2dpDataRespTimeout,
- cmd->info.a2dpParams.a2dpOptFlags,
- cmd->info.a2dpParams.isCoLocatedBtRoleMaster,
- cmd->info.a2dpParams.a2dpOptOffRssi,
- cmd->info.a2dpParams.a2dpOptOnRssi,
- cmd->info.a2dpParams.a2dpOptRtsCount));
- }
- else if (cmd->paramType == BT_PARAM_ANTENNA_CONFIG) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Ant config %d\n", cmd->info.antType));
- }
- else if (cmd->paramType == BT_PARAM_COLOCATED_BT_DEVICE) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("co-located BT %d\n", cmd->info.coLocatedBtDev));
- }
- else if (cmd->paramType == BT_PARAM_ACLCOEX) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("ACL params %d %d %d\n", cmd->info.aclCoexParams.aclWlanMediumUsageTime,
- cmd->info.aclCoexParams.aclBtMediumUsageTime,
- cmd->info.aclCoexParams.aclDataRespTimeout));
- }
- else if (cmd->paramType == BT_PARAM_11A_SEPARATE_ANT) {
- A_DPRINTF(DBG_WMI, (DBGFMT "11A ant\n", DBGARG));
- }
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd, cmd, sizeof(*cmd));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd)
-{
- void *osbuf;
- WMI_SET_BTCOEX_FE_ANT_CMD *alloc_cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID,
- NO_SYNC_WMIFLAG));
-
-}
-
-
-int
-wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
- WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd)
-{
- void *osbuf;
- WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *alloc_cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
- A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev);
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
- WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd)
-{
- void *osbuf;
- WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *alloc_cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
- WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd)
-{
- void *osbuf;
- WMI_SET_BTCOEX_SCO_CONFIG_CMD *alloc_cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID ,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
- WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd)
-{
- void *osbuf;
- WMI_SET_BTCOEX_A2DP_CONFIG_CMD *alloc_cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID ,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip,
- WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd)
-{
- void *osbuf;
- WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *alloc_cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID ,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd)
-{
- void *osbuf;
- WMI_SET_BTCOEX_DEBUG_CMD *alloc_cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID ,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
- WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd)
-{
- void *osbuf;
- WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *alloc_cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd)
-{
- void *osbuf;
- WMI_GET_BTCOEX_CONFIG_CMD *alloc_cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
- return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID ,
- NO_SYNC_WMIFLAG));
-
-}
-
-int
-wmi_get_btcoex_stats_cmd(struct wmi_t *wmip)
-{
-
- return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID);
-
-}
-
-int
-wmi_get_keepalive_configured(struct wmi_t *wmip)
-{
- void *osbuf;
- WMI_GET_KEEPALIVE_CMD *cmd;
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
- cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-u8 wmi_get_keepalive_cmd(struct wmi_t *wmip)
-{
- return wmip->wmi_keepaliveInterval;
-}
-
-int
-wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval)
-{
- void *osbuf;
- WMI_SET_KEEPALIVE_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->keepaliveInterval = keepaliveInterval;
- wmip->wmi_keepaliveInterval = keepaliveInterval;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer)
-{
- void *osbuf;
- WMI_SET_PARAMS_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + length);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd) + length);
-
- cmd = (WMI_SET_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->opcode = opcode;
- cmd->length = length;
- memcpy(cmd->buffer, buffer, length);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-
-int
-wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
-{
- void *osbuf;
- WMI_SET_MCAST_FILTER_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->multicast_mac[0] = 0x01;
- cmd->multicast_mac[1] = 0x00;
- cmd->multicast_mac[2] = 0x5e;
- cmd->multicast_mac[3] = dot2&0x7F;
- cmd->multicast_mac[4] = dot3;
- cmd->multicast_mac[5] = dot4;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_MCAST_FILTER_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-
-int
-wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
-{
- void *osbuf;
- WMI_SET_MCAST_FILTER_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->multicast_mac[0] = 0x01;
- cmd->multicast_mac[1] = 0x00;
- cmd->multicast_mac[2] = 0x5e;
- cmd->multicast_mac[3] = dot2&0x7F;
- cmd->multicast_mac[4] = dot3;
- cmd->multicast_mac[5] = dot4;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_DEL_MCAST_FILTER_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable)
-{
- void *osbuf;
- WMI_MCAST_FILTER_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->enable = enable;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_MCAST_FILTER_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen,
- u8 *ieInfo)
-{
- void *osbuf;
- WMI_SET_APPIE_CMD *cmd;
- u16 cmdLen;
-
- cmdLen = sizeof(*cmd) + ieLen - 1;
- osbuf = A_NETBUF_ALLOC(cmdLen);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, cmdLen);
-
- cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, cmdLen);
-
- cmd->mgmtFrmType = mgmtFrmType;
- cmd->ieLen = ieLen;
- memcpy(cmd->ieInfo, ieInfo, ieLen);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen)
-{
- void *osbuf;
- u8 *data;
-
- osbuf = A_NETBUF_ALLOC(dataLen);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, dataLen);
-
- data = A_NETBUF_DATA(osbuf);
-
- memcpy(data, cmd, dataLen);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
-}
-
-s32 wmi_get_rate(s8 rateindex)
-{
- if (rateindex == RATE_AUTO) {
- return 0;
- } else {
- return(wmi_rateTable[(u32) rateindex][0]);
- }
-}
-
-void
-wmi_node_return (struct wmi_t *wmip, bss_t *bss)
-{
- if (NULL != bss)
- {
- wlan_node_return (&wmip->wmi_scan_table, bss);
- }
-}
-
-void
-wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge)
-{
- wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge);
-}
-
-bss_t *
-wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
- u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
-{
- bss_t *node = NULL;
- node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
- ssidLength, bIsWPA2, bMatchSSID);
- return node;
-}
-
-
-#ifdef THREAD_X
-void
-wmi_refresh_scan_table (struct wmi_t *wmip)
-{
- wlan_refresh_inactive_nodes (&wmip->wmi_scan_table);
-}
-#endif
-
-void
-wmi_free_allnodes(struct wmi_t *wmip)
-{
- wlan_free_allnodes(&wmip->wmi_scan_table);
-}
-
-bss_t *
-wmi_find_node(struct wmi_t *wmip, const u8 *macaddr)
-{
- bss_t *ni=NULL;
- ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
- return ni;
-}
-
-void
-wmi_free_node(struct wmi_t *wmip, const u8 *macaddr)
-{
- bss_t *ni=NULL;
-
- ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
- if (ni != NULL) {
- wlan_node_reclaim(&wmip->wmi_scan_table, ni);
- }
-
- return;
-}
-
-int
-wmi_dset_open_reply(struct wmi_t *wmip,
- u32 status,
- u32 access_cookie,
- u32 dset_size,
- u32 dset_version,
- u32 targ_handle,
- u32 targ_reply_fn,
- u32 targ_reply_arg)
-{
- void *osbuf;
- WMIX_DSETOPEN_REPLY_CMD *open_reply;
-
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%lx\n", DBGARG, (unsigned long)wmip));
-
- osbuf = A_NETBUF_ALLOC(sizeof(*open_reply));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*open_reply));
- open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
-
- open_reply->status = status;
- open_reply->targ_dset_handle = targ_handle;
- open_reply->targ_reply_fn = targ_reply_fn;
- open_reply->targ_reply_arg = targ_reply_arg;
- open_reply->access_cookie = access_cookie;
- open_reply->size = dset_size;
- open_reply->version = dset_version;
-
- return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-static int
-wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
-{
- WMI_PMKID_LIST_REPLY *reply;
- u32 expected_len;
-
- if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
- return A_EINVAL;
- }
- reply = (WMI_PMKID_LIST_REPLY *)datap;
- expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN;
-
- if (len < expected_len) {
- return A_EINVAL;
- }
-
- A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
- reply->pmkidList, reply->bssidList[0]);
-
- return 0;
-}
-
-
-static int
-wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
-{
- WMI_SET_PARAMS_REPLY *reply;
-
- if (len < sizeof(WMI_SET_PARAMS_REPLY)) {
- return A_EINVAL;
- }
- reply = (WMI_SET_PARAMS_REPLY *)datap;
-
- if (0 == reply->status)
- {
-
- }
- else
- {
-
- }
-
- return 0;
-}
-
-
-#ifdef CONFIG_HOST_DSET_SUPPORT
-int
-wmi_dset_data_reply(struct wmi_t *wmip,
- u32 status,
- u8 *user_buf,
- u32 length,
- u32 targ_buf,
- u32 targ_reply_fn,
- u32 targ_reply_arg)
-{
- void *osbuf;
- WMIX_DSETDATA_REPLY_CMD *data_reply;
- u32 size;
-
- size = sizeof(*data_reply) + length;
-
- if (size <= length) {
- return A_ERROR;
- }
-
- A_DPRINTF(DBG_WMI,
- (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status));
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
- A_NETBUF_PUT(osbuf, size);
- data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
-
- data_reply->status = status;
- data_reply->targ_buf = targ_buf;
- data_reply->targ_reply_fn = targ_reply_fn;
- data_reply->targ_reply_arg = targ_reply_arg;
- data_reply->length = length;
-
- if (status == 0) {
- if (a_copy_from_user(data_reply->buf, user_buf, length)) {
- A_NETBUF_FREE(osbuf);
- return A_ERROR;
- }
- }
-
- return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID,
- NO_SYNC_WMIFLAG));
-}
-#endif /* CONFIG_HOST_DSET_SUPPORT */
-
-int
-wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status)
-{
- void *osbuf;
- char *cmd;
-
- wps_enable = status;
-
- osbuf = a_netbuf_alloc(sizeof(1));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- a_netbuf_put(osbuf, sizeof(1));
-
- cmd = (char *)(a_netbuf_to_data(osbuf));
-
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd[0] = (status?1:0);
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-int
-wmi_prof_cfg_cmd(struct wmi_t *wmip,
- u32 period,
- u32 nbins)
-{
- void *osbuf;
- WMIX_PROF_CFG_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMIX_PROF_CFG_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->period = period;
- cmd->nbins = nbins;
-
- return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr)
-{
- void *osbuf;
- WMIX_PROF_ADDR_SET_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMIX_PROF_ADDR_SET_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->addr = addr;
-
- return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_prof_start_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID);
-}
-
-int
-wmi_prof_stop_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID);
-}
-
-int
-wmi_prof_count_get_cmd(struct wmi_t *wmip)
-{
- return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID);
-}
-
-/* Called to handle WMIX_PROF_CONT_EVENTID */
-static int
-wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap;
-
- A_DPRINTF(DBG_WMI,
- (DBGFMT "Enter - addr=0x%x count=%d\n", DBGARG,
- prof_data->addr, prof_data->count));
-
- A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count);
-
- return 0;
-}
-#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
-
-#ifdef OS_ROAM_MANAGEMENT
-
-#define ETHERNET_MAC_ADDRESS_LENGTH 6
-
-void
-wmi_scan_indication (struct wmi_t *wmip)
-{
- struct ieee80211_node_table *nt;
- u32 gen;
- u32 size;
- u32 bsssize;
- bss_t *bss;
- u32 numbss;
- PNDIS_802_11_BSSID_SCAN_INFO psi;
- PBYTE pie;
- NDIS_802_11_FIXED_IEs *pFixed;
- NDIS_802_11_VARIABLE_IEs *pVar;
- u32 RateSize;
-
- struct ar6kScanIndication
- {
- NDIS_802_11_STATUS_INDICATION ind;
- NDIS_802_11_BSSID_SCAN_INFO_LIST slist;
- } *pAr6kScanIndEvent;
-
- nt = &wmip->wmi_scan_table;
-
- ++nt->nt_si_gen;
-
-
- gen = nt->nt_si_gen;
-
- size = offsetof(struct ar6kScanIndication, slist) +
- offsetof(NDIS_802_11_BSSID_SCAN_INFO_LIST, BssidScanInfo);
-
- numbss = 0;
-
- IEEE80211_NODE_LOCK(nt);
-
- //calc size
- for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
- if (bss->ni_si_gen != gen) {
- bsssize = offsetof(NDIS_802_11_BSSID_SCAN_INFO, Bssid) + offsetof(NDIS_WLAN_BSSID_EX, IEs);
- bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
-
-#ifdef SUPPORT_WPA2
- if (bss->ni_cie.ie_rsn) {
- bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
- }
-#endif
- if (bss->ni_cie.ie_wpa) {
- bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
- }
-
- // bsssize must be a multiple of 4 to maintain alignment.
- bsssize = (bsssize + 3) & ~3;
-
- size += bsssize;
-
- numbss++;
- }
- }
-
- if (0 == numbss)
- {
-// RETAILMSG(1, (L"AR6K: scan indication: 0 bss\n"));
- ar6000_scan_indication (wmip->wmi_devt, NULL, 0);
- IEEE80211_NODE_UNLOCK (nt);
- return;
- }
-
- pAr6kScanIndEvent = A_MALLOC(size);
-
- if (NULL == pAr6kScanIndEvent)
- {
- IEEE80211_NODE_UNLOCK(nt);
- return;
- }
-
- A_MEMZERO(pAr6kScanIndEvent, size);
-
- //copy data
- pAr6kScanIndEvent->ind.StatusType = Ndis802_11StatusType_BssidScanInfoList;
- pAr6kScanIndEvent->slist.Version = 1;
- pAr6kScanIndEvent->slist.NumItems = numbss;
-
- psi = &pAr6kScanIndEvent->slist.BssidScanInfo[0];
-
- for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
- if (bss->ni_si_gen != gen) {
-
- bss->ni_si_gen = gen;
-
- //Set scan time
- psi->ScanTime = bss->ni_tstamp - WLAN_NODE_INACT_TIMEOUT_MSEC;
-
- // Copy data to bssid_ex
- bsssize = offsetof(NDIS_WLAN_BSSID_EX, IEs);
- bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
-
-#ifdef SUPPORT_WPA2
- if (bss->ni_cie.ie_rsn) {
- bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
- }
-#endif
- if (bss->ni_cie.ie_wpa) {
- bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
- }
-
- // bsssize must be a multiple of 4 to maintain alignment.
- bsssize = (bsssize + 3) & ~3;
-
- psi->Bssid.Length = bsssize;
-
- memcpy (psi->Bssid.MacAddress, bss->ni_macaddr, ETHERNET_MAC_ADDRESS_LENGTH);
-
-
-//if (((bss->ni_macaddr[3] == 0xCE) && (bss->ni_macaddr[4] == 0xF0) && (bss->ni_macaddr[5] == 0xE7)) ||
-// ((bss->ni_macaddr[3] == 0x03) && (bss->ni_macaddr[4] == 0xE2) && (bss->ni_macaddr[5] == 0x70)))
-// RETAILMSG (1, (L"%x\n",bss->ni_macaddr[5]));
-
- psi->Bssid.Ssid.SsidLength = 0;
- pie = bss->ni_cie.ie_ssid;
-
- if (pie) {
- // Format of SSID IE is:
- // Type (1 octet)
- // Length (1 octet)
- // SSID (Length octets)
- //
- // Validation of the IE should have occurred within WMI.
- //
- if (pie[1] <= 32) {
- psi->Bssid.Ssid.SsidLength = pie[1];
- memcpy(psi->Bssid.Ssid.Ssid, &pie[2], psi->Bssid.Ssid.SsidLength);
- }
- }
- psi->Bssid.Privacy = (bss->ni_cie.ie_capInfo & 0x10) ? 1 : 0;
-
- //Post the RSSI value relative to the Standard Noise floor value.
- psi->Bssid.Rssi = bss->ni_rssi;
-
- if (bss->ni_cie.ie_chan >= 2412 && bss->ni_cie.ie_chan <= 2484) {
-
- if (bss->ni_cie.ie_rates && bss->ni_cie.ie_xrates) {
- psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM24;
- }
- else {
- psi->Bssid.NetworkTypeInUse = Ndis802_11DS;
- }
- }
- else {
- psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM5;
- }
-
- psi->Bssid.Configuration.Length = sizeof(psi->Bssid.Configuration);
- psi->Bssid.Configuration.BeaconPeriod = bss->ni_cie.ie_beaconInt; // Units are Kmicroseconds (1024 us)
- psi->Bssid.Configuration.ATIMWindow = 0;
- psi->Bssid.Configuration.DSConfig = bss->ni_cie.ie_chan * 1000;
- psi->Bssid.InfrastructureMode = ((bss->ni_cie.ie_capInfo & 0x03) == 0x01 ) ? Ndis802_11Infrastructure : Ndis802_11IBSS;
-
- RateSize = 0;
- pie = bss->ni_cie.ie_rates;
- if (pie) {
- RateSize = (pie[1] < NDIS_802_11_LENGTH_RATES_EX) ? pie[1] : NDIS_802_11_LENGTH_RATES_EX;
- memcpy(psi->Bssid.SupportedRates, &pie[2], RateSize);
- }
- pie = bss->ni_cie.ie_xrates;
- if (pie && RateSize < NDIS_802_11_LENGTH_RATES_EX) {
- memcpy(psi->Bssid.SupportedRates + RateSize, &pie[2],
- (pie[1] < (NDIS_802_11_LENGTH_RATES_EX - RateSize)) ? pie[1] : (NDIS_802_11_LENGTH_RATES_EX - RateSize));
- }
-
- // Copy the fixed IEs
- psi->Bssid.IELength = sizeof(NDIS_802_11_FIXED_IEs);
-
- pFixed = (NDIS_802_11_FIXED_IEs *)psi->Bssid.IEs;
- memcpy(pFixed->Timestamp, bss->ni_cie.ie_tstamp, sizeof(pFixed->Timestamp));
- pFixed->BeaconInterval = bss->ni_cie.ie_beaconInt;
- pFixed->Capabilities = bss->ni_cie.ie_capInfo;
-
- // Copy selected variable IEs
-
- pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pFixed + sizeof(NDIS_802_11_FIXED_IEs));
-
-#ifdef SUPPORT_WPA2
- // Copy the WPAv2 IE
- if (bss->ni_cie.ie_rsn) {
- pie = bss->ni_cie.ie_rsn;
- psi->Bssid.IELength += pie[1] + 2;
- memcpy(pVar, pie, pie[1] + 2);
- pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
- }
-#endif
- // Copy the WPAv1 IE
- if (bss->ni_cie.ie_wpa) {
- pie = bss->ni_cie.ie_wpa;
- psi->Bssid.IELength += pie[1] + 2;
- memcpy(pVar, pie, pie[1] + 2);
- pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
- }
-
- // Advance buffer pointer
- psi = (PNDIS_802_11_BSSID_SCAN_INFO)((BYTE*)psi + bsssize + FIELD_OFFSET(NDIS_802_11_BSSID_SCAN_INFO, Bssid));
- }
- }
-
- IEEE80211_NODE_UNLOCK(nt);
-
-// wmi_free_allnodes(wmip);
-
-// RETAILMSG(1, (L"AR6K: scan indication: %u bss\n", numbss));
-
- ar6000_scan_indication (wmip->wmi_devt, pAr6kScanIndEvent, size);
-
- kfree(pAr6kScanIndEvent);
-}
-#endif
-
-u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
- u32 size)
-{
- u32 index;
- u8 threshold = (u8)sq_thresh->upper_threshold[size - 1];
-
- /* The list is already in sorted order. Get the next lower value */
- for (index = 0; index < size; index ++) {
- if (rssi < sq_thresh->upper_threshold[index]) {
- threshold = (u8)sq_thresh->upper_threshold[index];
- break;
- }
- }
-
- return threshold;
-}
-
-u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
- u32 size)
-{
- u32 index;
- u8 threshold = (u8)sq_thresh->lower_threshold[size - 1];
-
- /* The list is already in sorted order. Get the next lower value */
- for (index = 0; index < size; index ++) {
- if (rssi > sq_thresh->lower_threshold[index]) {
- threshold = (u8)sq_thresh->lower_threshold[index];
- break;
- }
- }
-
- return threshold;
-}
-static int
-wmi_send_rssi_threshold_params(struct wmi_t *wmip,
- WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
-{
- void *osbuf;
- s8 size;
- WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
-
- size = sizeof (*cmd);
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
-
- cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
- memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-static int
-wmi_send_snr_threshold_params(struct wmi_t *wmip,
- WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
-{
- void *osbuf;
- s8 size;
- WMI_SNR_THRESHOLD_PARAMS_CMD *cmd;
-
- size = sizeof (*cmd);
-
- osbuf = A_NETBUF_ALLOC(size);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, size);
- cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, size);
- memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd)
-{
- void *osbuf;
- WMI_SET_TARGET_EVENT_REPORT_CMD* alloc_cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(alloc_cmd, sizeof(*cmd));
- memcpy(alloc_cmd, cmd, sizeof(*cmd));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id)
-{
- wmi_get_current_bssid (wmip, id);
- return wlan_node_remove (&wmip->wmi_scan_table, id);
-}
-
-int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss)
-{
- wlan_setup_node (&wmip->wmi_scan_table, bss, id);
- return 0;
-}
-
-static int
-wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap;
-
- A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd);
-
- return 0;
-}
-
-
-static int
-wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap;
-
- A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd);
-
- return 0;
-}
-
-static int
-wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap;
-
- A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd);
-
- return 0;
-}
-
-int
-wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len);
-
- return 0;
-}
-
-
-int
-wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len)
-{
- A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
- A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len);
-
- return 0;
-
-}
-
-static int
-wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap;
- A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd);
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//// ////
-//// AP mode functions ////
-//// ////
-////////////////////////////////////////////////////////////////////////////////
-/*
- * IOCTL: AR6000_XIOCTL_AP_COMMIT_CONFIG
- *
- * When AR6K in AP mode, This command will be called after
- * changing ssid, channel etc. It will pass the profile to
- * target with a flag which will indicate which parameter changed,
- * also if this flag is 0, there was no change in parametes, so
- * commit cmd will not be sent to target. Without calling this IOCTL
- * the changes will not take effect.
- */
-int
-wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p)
-{
- void *osbuf;
- WMI_CONNECT_CMD *cm;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cm));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cm));
- cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cm, sizeof(*cm));
-
- memcpy(cm,p,sizeof(*cm));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG));
-}
-
-/*
- * IOCTL: AR6000_XIOCTL_AP_HIDDEN_SSID
- *
- * This command will be used to enable/disable hidden ssid functioanlity of
- * beacon. If it is enabled, ssid will be NULL in beacon.
- */
-int
-wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid)
-{
- void *osbuf;
- WMI_AP_HIDDEN_SSID_CMD *hs;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_HIDDEN_SSID_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_AP_HIDDEN_SSID_CMD));
- hs = (WMI_AP_HIDDEN_SSID_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(hs, sizeof(*hs));
-
- hs->hidden_ssid = hidden_ssid;
-
- A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_HIDDEN_SSID %d\n", DBGARG , hidden_ssid));
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_HIDDEN_SSID_CMDID, NO_SYNC_WMIFLAG));
-}
-
-/*
- * IOCTL: AR6000_XIOCTL_AP_SET_MAX_NUM_STA
- *
- * This command is used to limit max num of STA that can connect
- * with this AP. This value should not exceed AP_MAX_NUM_STA (this
- * is max num of STA supported by AP). Value was already validated
- * in ioctl.c
- */
-int
-wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta)
-{
- void *osbuf;
- WMI_AP_SET_NUM_STA_CMD *ns;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_NUM_STA_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_NUM_STA_CMD));
- ns = (WMI_AP_SET_NUM_STA_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(ns, sizeof(*ns));
-
- ns->num_sta = num_sta;
-
- A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_SET_MAX_NUM_STA %d\n", DBGARG , num_sta));
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_NUM_STA_CMDID, NO_SYNC_WMIFLAG));
-}
-
-/*
- * IOCTL: AR6000_XIOCTL_AP_SET_ACL_MAC
- *
- * This command is used to send list of mac of STAs which will
- * be allowed to connect with this AP. When this list is empty
- * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
- */
-int
-wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl)
-{
- void *osbuf;
- WMI_AP_ACL_MAC_CMD *a;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_MAC_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD));
- a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(a, sizeof(*a));
- memcpy(a,acl,sizeof(*acl));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG));
-}
-
-/*
- * IOCTL: AR6000_XIOCTL_AP_SET_MLME
- *
- * This command is used to send list of mac of STAs which will
- * be allowed to connect with this AP. When this list is empty
- * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
- */
-int
-wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason)
-{
- void *osbuf;
- WMI_AP_SET_MLME_CMD *mlme;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_MLME_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_MLME_CMD));
- mlme = (WMI_AP_SET_MLME_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(mlme, sizeof(*mlme));
-
- mlme->cmd = cmd;
- memcpy(mlme->mac, mac, ATH_MAC_LEN);
- mlme->reason = reason;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG));
-}
-
-static int
-wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len)
-{
- WMI_PSPOLL_EVENT *ev;
-
- if (len < sizeof(WMI_PSPOLL_EVENT)) {
- return A_EINVAL;
- }
- ev = (WMI_PSPOLL_EVENT *)datap;
-
- A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid);
- return 0;
-}
-
-static int
-wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len)
-{
- A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt);
- return 0;
-}
-
-#ifdef WAPI_ENABLE
-static int
-wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len)
-{
- u8 *ev;
-
- if (len < 7) {
- return A_EINVAL;
- }
- ev = (u8 *)datap;
-
- A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]);
- return 0;
-}
-#endif
-
-int
-wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag)
-{
- WMI_AP_SET_PVB_CMD *cmd;
- void *osbuf = NULL;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_PVB_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_PVB_CMD));
- cmd = (WMI_AP_SET_PVB_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
-
- cmd->aid = aid;
- cmd->flag = flag;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period)
-{
- WMI_AP_CONN_INACT_CMD *cmd;
- void *osbuf = NULL;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_CONN_INACT_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_AP_CONN_INACT_CMD));
- cmd = (WMI_AP_CONN_INACT_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
-
- cmd->period = period;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell)
-{
- WMI_AP_PROT_SCAN_TIME_CMD *cmd;
- void *osbuf = NULL;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
- cmd = (WMI_AP_PROT_SCAN_TIME_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
-
- cmd->period_min = period;
- cmd->dwell_ms = dwell;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim)
-{
- WMI_AP_SET_DTIM_CMD *cmd;
- void *osbuf = NULL;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_DTIM_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_DTIM_CMD));
- cmd = (WMI_AP_SET_DTIM_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
-
- cmd->dtim = dtim;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG));
-}
-
-/*
- * IOCTL: AR6000_XIOCTL_AP_SET_ACL_POLICY
- *
- * This command is used to set ACL policay. While changing policy, if you
- * want to retain the existing MAC addresses in the ACL list, policy should be
- * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared.
- * If there is no chage in policy, the list will be intact.
- */
-int
-wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy)
-{
- void *osbuf;
- WMI_AP_ACL_POLICY_CMD *po;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_POLICY_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
-}
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_POLICY_CMD));
- po = (WMI_AP_ACL_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(po, sizeof(*po));
-
- po->policy = policy;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset)
-{
- void *osbuf;
- WMI_AP_SET_11BG_RATESET_CMD *rs;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_11BG_RATESET_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_11BG_RATESET_CMD));
- rs = (WMI_AP_SET_11BG_RATESET_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(rs, sizeof(*rs));
-
- rs->rateset = rateset;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_11BG_RATESET_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd)
-{
- void *osbuf;
- WMI_SET_HT_CAP_CMD *htCap;
- u8 band;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*htCap));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*htCap));
-
- band = (cmd->band)? A_BAND_5GHZ : A_BAND_24GHZ;
- wmip->wmi_ht_allowed[band] = (cmd->enable)? 1:0;
-
- htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(htCap, sizeof(*htCap));
- memcpy(htCap, cmd, sizeof(*htCap));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width)
-{
- void *osbuf;
- WMI_SET_HT_OP_CMD *htInfo;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*htInfo));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*htInfo));
-
- htInfo = (WMI_SET_HT_OP_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(htInfo, sizeof(*htInfo));
- htInfo->sta_chan_width = sta_chan_width;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_OP_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray)
-{
- void *osbuf;
- WMI_SET_TX_SELECT_RATES_CMD *pData;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*pData));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*pData));
-
- pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf));
- memcpy(pData, pMaskArray, sizeof(*pData));
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-
-int
-wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz)
-{
- void *osbuf;
- WMI_HCI_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + sz);
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd) + sz);
- cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf));
-
- cmd->cmd_buf_sz = sz;
- memcpy(cmd->buf, buf, sz);
- return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask)
-{
- void *osbuf;
- WMI_ALLOW_AGGR_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_ALLOW_AGGR_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->tx_allow_aggr = tx_tidmask;
- cmd->rx_allow_aggr = rx_tidmask;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid)
-{
- void *osbuf;
- WMI_ADDBA_REQ_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_ADDBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->tid = tid;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink)
-{
- void *osbuf;
- WMI_DELBA_REQ_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_DELBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->tid = tid;
- cmd->is_sender_initiator = uplink; /* uplink =1 - uplink direction, 0=downlink direction */
-
- /* Delete the local aggr state, on host */
- return (wmi_cmd_send(wmip, osbuf, WMI_DELBA_REQ_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion,
- bool rxDot11Hdr, bool defragOnHost)
-{
- void *osbuf;
- WMI_RX_FRAME_FORMAT_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0;
- cmd->defragOnHost = (defragOnHost==true)? 1:0;
- cmd->metaVersion = rxMetaVersion; /* */
-
- /* Delete the local aggr state, on host */
- return (wmi_cmd_send(wmip, osbuf, WMI_RX_FRAME_FORMAT_CMDID, NO_SYNC_WMIFLAG));
-}
-
-
-int
-wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode)
-{
- void *osbuf;
- WMI_SET_THIN_MODE_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf));
- cmd->enable = (bThinMode==true)? 1:0;
-
- /* Delete the local aggr state, on host */
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG));
-}
-
-
-int
-wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence)
-{
- void *osbuf;
- WMI_SET_BT_WLAN_CONN_PRECEDENCE *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_BT_WLAN_CONN_PRECEDENCE *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->precedence = precedence;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk)
-{
- void *osbuf;
- WMI_SET_PMK_CMD *p;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_PMK_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_SET_PMK_CMD));
-
- p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(p, sizeof(*p));
-
- memcpy(p->pmk, pmk, WMI_PMK_LEN);
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd)
-{
- void *osbuf;
- WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p;
-
- osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
- if (osbuf == NULL) {
- return A_NO_MEMORY;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
-
- p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf));
- memset(p, 0, sizeof(*p));
-
- p->threshold = cmd->threshold;
-
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG));
-}
-
-int
-wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold)
-{
- void *osbuf;
- WMI_SET_TX_SGI_PARAM_CMD *cmd;
-
- osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
- if (osbuf == NULL) {
- return A_NO_MEMORY ;
- }
-
- A_NETBUF_PUT(osbuf, sizeof(*cmd));
-
- cmd = (WMI_SET_TX_SGI_PARAM_CMD *)(A_NETBUF_DATA(osbuf));
- A_MEMZERO(cmd, sizeof(*cmd));
- cmd->sgiMask = sgiMask;
- cmd->sgiPERThreshold = sgiPERThreshold;
- return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SGI_PARAM_CMDID,
- NO_SYNC_WMIFLAG));
-}
-
-bss_t *
-wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
- u32 ssidLength,
- u32 dot11AuthMode, u32 authMode,
- u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
-{
- bss_t *node = NULL;
- node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid,
- ssidLength, dot11AuthMode, authMode, pairwiseCryptoType, grpwiseCryptoTyp);
-
- return node;
-}
-
-u16 wmi_ieee2freq (int chan)
-{
- u16 freq = 0;
- freq = wlan_ieee2freq (chan);
- return freq;
-
-}
-
-u32 wmi_freq2ieee (u16 freq)
-{
- u16 chan = 0;
- chan = wlan_freq2ieee (freq);
- return chan;
-}
diff --git a/drivers/staging/ath6kl/wmi/wmi_host.h b/drivers/staging/ath6kl/wmi/wmi_host.h
deleted file mode 100644
index 53e4f085dfe6..000000000000
--- a/drivers/staging/ath6kl/wmi/wmi_host.h
+++ /dev/null
@@ -1,102 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="wmi_host.h" company="Atheros">
-// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
-//
-//
-// 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 file contains local definitios for the wmi host module.
-//
-// Author(s): ="Atheros"
-//==============================================================================
-#ifndef _WMI_HOST_H_
-#define _WMI_HOST_H_
-
-#include "roaming.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct wmi_stats {
- u32 cmd_len_err;
- u32 cmd_id_err;
-};
-
-#define SSID_IE_LEN_INDEX 13
-
-/* Host side link management data structures */
-#define SIGNAL_QUALITY_THRESHOLD_LEVELS 6
-#define SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS
-#define SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS
-typedef struct sq_threshold_params_s {
- s16 upper_threshold[SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS];
- s16 lower_threshold[SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS];
- u32 upper_threshold_valid_count;
- u32 lower_threshold_valid_count;
- u32 polling_interval;
- u8 weight;
- u8 last_rssi; //normally you would expect this to be bss specific but we keep only one instance because its only valid when the device is in a connected state. Not sure if it belongs to host or target.
- u8 last_rssi_poll_event; //Not sure if it belongs to host or target
-} SQ_THRESHOLD_PARAMS;
-
-/*
- * These constants are used with A_WLAN_BAND_SET.
- */
-#define A_BAND_24GHZ 0
-#define A_BAND_5GHZ 1
-#define A_NUM_BANDS 2
-
-struct wmi_t {
- bool wmi_ready;
- bool wmi_numQoSStream;
- u16 wmi_streamExistsForAC[WMM_NUM_AC];
- u8 wmi_fatPipeExists;
- void *wmi_devt;
- struct wmi_stats wmi_stats;
- struct ieee80211_node_table wmi_scan_table;
- u8 wmi_bssid[ATH_MAC_LEN];
- u8 wmi_powerMode;
- u8 wmi_phyMode;
- u8 wmi_keepaliveInterval;
-#ifdef THREAD_X
- A_CSECT_T wmi_lock;
-#else
- A_MUTEX_T wmi_lock;
-#endif
- HTC_ENDPOINT_ID wmi_endpoint_id;
- SQ_THRESHOLD_PARAMS wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_NUM_MAX];
- CRYPTO_TYPE wmi_pair_crypto_type;
- CRYPTO_TYPE wmi_grp_crypto_type;
- bool wmi_is_wmm_enabled;
- u8 wmi_ht_allowed[A_NUM_BANDS];
- u8 wmi_traffic_class;
-};
-
-#ifdef THREAD_X
-#define INIT_WMI_LOCK(w) A_CSECT_INIT(&(w)->wmi_lock)
-#define LOCK_WMI(w) A_CSECT_ENTER(&(w)->wmi_lock);
-#define UNLOCK_WMI(w) A_CSECT_LEAVE(&(w)->wmi_lock);
-#define DELETE_WMI_LOCK(w) A_CSECT_DELETE(&(w)->wmi_lock);
-#else
-#define LOCK_WMI(w) A_MUTEX_LOCK(&(w)->wmi_lock);
-#define UNLOCK_WMI(w) A_MUTEX_UNLOCK(&(w)->wmi_lock);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _WMI_HOST_H_ */
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
index 867dbf1c9926..2fa658eb74dc 100644
--- a/drivers/staging/bcm/Bcmchar.c
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -34,7 +34,7 @@ static int bcm_char_open(struct inode *inode, struct file * filp)
/* Store the Adapter structure */
filp->private_data = pTarang;
- /*Start Queuing the control response Packets*/
+ /* Start Queuing the control response Packets */
atomic_inc(&Adapter->ApplicationRunning);
nonseekable_open(inode, filp);
@@ -84,7 +84,7 @@ static int bcm_char_release(struct inode *inode, struct file *filp)
up(&Adapter->RxAppControlQueuelock);
- /*Stop Queuing the control response Packets*/
+ /* Stop Queuing the control response Packets */
atomic_dec(&Adapter->ApplicationRunning);
kfree(pTarang);
@@ -100,8 +100,8 @@ static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size,
PPER_TARANG_DATA pTarang = filp->private_data;
PMINI_ADAPTER Adapter = pTarang->Adapter;
struct sk_buff *Packet = NULL;
- ssize_t PktLen = 0;
- int wait_ret_val = 0;
+ ssize_t PktLen = 0;
+ int wait_ret_val = 0;
unsigned long ret = 0;
wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue,
@@ -157,1942 +157,1824 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
{
PPER_TARANG_DATA pTarang = filp->private_data;
void __user *argp = (void __user *)arg;
- PMINI_ADAPTER Adapter = pTarang->Adapter;
- INT Status = STATUS_FAILURE;
+ PMINI_ADAPTER Adapter = pTarang->Adapter;
+ INT Status = STATUS_FAILURE;
int timeout = 0;
- IOCTL_BUFFER IoBuffer;
+ IOCTL_BUFFER IoBuffer;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg);
- if(_IOC_TYPE(cmd) != BCM_IOCTL)
+ if (_IOC_TYPE(cmd) != BCM_IOCTL)
return -EFAULT;
- if(_IOC_DIR(cmd) & _IOC_READ)
+ if (_IOC_DIR(cmd) & _IOC_READ)
Status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
- Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
+ Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE))
- Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
- if(Status)
+ if (Status)
return -EFAULT;
- if(Adapter->device_removed)
- {
+ if (Adapter->device_removed)
return -EFAULT;
- }
- if(FALSE == Adapter->fw_download_done)
- {
- switch (cmd)
- {
- case IOCTL_MAC_ADDR_REQ:
- case IOCTL_LINK_REQ:
- case IOCTL_CM_REQUEST:
- case IOCTL_SS_INFO_REQ:
- case IOCTL_SEND_CONTROL_MESSAGE:
- case IOCTL_IDLE_REQ:
- case IOCTL_BCM_GPIO_SET_REQUEST:
- case IOCTL_BCM_GPIO_STATUS_REQUEST:
- return -EACCES;
- default:
- break;
+ if (FALSE == Adapter->fw_download_done) {
+ switch (cmd) {
+ case IOCTL_MAC_ADDR_REQ:
+ case IOCTL_LINK_REQ:
+ case IOCTL_CM_REQUEST:
+ case IOCTL_SS_INFO_REQ:
+ case IOCTL_SEND_CONTROL_MESSAGE:
+ case IOCTL_IDLE_REQ:
+ case IOCTL_BCM_GPIO_SET_REQUEST:
+ case IOCTL_BCM_GPIO_STATUS_REQUEST:
+ return -EACCES;
+ default:
+ break;
}
}
Status = vendorextnIoctl(Adapter, cmd, arg);
- if(Status != CONTINUE_COMMON_PATH )
- return Status;
+ if (Status != CONTINUE_COMMON_PATH)
+ return Status;
+
+ switch (cmd) {
+ /* Rdms for Swin Idle... */
+ case IOCTL_BCM_REGISTER_READ_PRIVATE: {
+ RDM_BUFFER sRdmBuffer = {0};
+ PCHAR temp_buff;
+ UINT Bufflen;
+ u16 temp_value;
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- switch(cmd){
- // Rdms for Swin Idle...
- case IOCTL_BCM_REGISTER_READ_PRIVATE:
- {
- RDM_BUFFER sRdmBuffer = {0};
- PCHAR temp_buff;
- UINT Bufflen;
+ if (IoBuffer.InputLength > sizeof(sRdmBuffer))
+ return -EINVAL;
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
- if (IoBuffer.InputLength > sizeof(sRdmBuffer))
- return -EINVAL;
+ if (IoBuffer.OutputLength > USHRT_MAX ||
+ IoBuffer.OutputLength == 0) {
+ return -EINVAL;
+ }
- if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ Bufflen = IoBuffer.OutputLength;
+ temp_value = 4 - (Bufflen % 4);
+ Bufflen += temp_value % 4;
- /* FIXME: need to restrict BuffLen */
- Bufflen = IoBuffer.OutputLength + (4 - IoBuffer.OutputLength%4)%4;
- temp_buff = kmalloc(Bufflen, GFP_KERNEL);
- if(!temp_buff)
- return -ENOMEM;
+ temp_buff = kmalloc(Bufflen, GFP_KERNEL);
+ if (!temp_buff)
+ return -ENOMEM;
- Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
- (PUINT)temp_buff, Bufflen);
- if(Status == STATUS_SUCCESS)
- {
- if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
- Status = -EFAULT;
- }
-
- kfree(temp_buff);
- break;
+ Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
+ (PUINT)temp_buff, Bufflen);
+ if (Status == STATUS_SUCCESS) {
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
+ Status = -EFAULT;
}
- case IOCTL_BCM_REGISTER_WRITE_PRIVATE:
- {
- WRM_BUFFER sWrmBuffer = {0};
- UINT uiTempVar=0;
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ kfree(temp_buff);
+ break;
+ }
- if (IoBuffer.InputLength > sizeof(sWrmBuffer))
- return -EINVAL;
+ case IOCTL_BCM_REGISTER_WRITE_PRIVATE: {
+ WRM_BUFFER sWrmBuffer = {0};
+ UINT uiTempVar = 0;
+ /* Copy Ioctl Buffer structure */
- /* Get WrmBuffer structure */
- if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(sWrmBuffer))
+ return -EINVAL;
- uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
- if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
- ((uiTempVar == EEPROM_REJECT_REG_1)||
+ /* Get WrmBuffer structure */
+ if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+
+ uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
+ if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1) ||
(uiTempVar == EEPROM_REJECT_REG_2) ||
(uiTempVar == EEPROM_REJECT_REG_3) ||
- (uiTempVar == EEPROM_REJECT_REG_4)))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
- return -EFAULT;
- }
- Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register,
- (PUINT)sWrmBuffer.Data, sizeof(ULONG));
- if(Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"WRM Done\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
- Status = -EFAULT;
- }
- break;
+ (uiTempVar == EEPROM_REJECT_REG_4))) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
+ return -EFAULT;
}
- case IOCTL_BCM_REGISTER_READ:
- case IOCTL_BCM_EEPROM_REGISTER_READ:
- {
- RDM_BUFFER sRdmBuffer = {0};
- PCHAR temp_buff = NULL;
- UINT uiTempVar = 0;
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n");
- return -EACCES;
- }
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register,
+ (PUINT)sWrmBuffer.Data, sizeof(ULONG));
- if (IoBuffer.InputLength > sizeof(sRdmBuffer))
- return -EINVAL;
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
+ Status = -EFAULT;
+ }
+ break;
+ }
- if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ case IOCTL_BCM_REGISTER_READ:
+ case IOCTL_BCM_EEPROM_REGISTER_READ: {
+ RDM_BUFFER sRdmBuffer = {0};
+ PCHAR temp_buff = NULL;
+ UINT uiTempVar = 0;
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n");
+ return -EACCES;
+ }
- /* FIXME: don't trust user supplied length */
- temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
- if(!temp_buff)
- return STATUS_FAILURE;
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) ||
- ((ULONG)sRdmBuffer.Register & 0x3))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n",
- (int)sRdmBuffer.Register);
- return -EINVAL;
- }
+ if (IoBuffer.InputLength > sizeof(sRdmBuffer))
+ return -EINVAL;
+
+ if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+
+ /* FIXME: don't trust user supplied length */
+ temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
+ if (!temp_buff)
+ return STATUS_FAILURE;
- uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
- Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register,
- (PUINT)temp_buff, IoBuffer.OutputLength);
- if(Status == STATUS_SUCCESS)
- if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
- Status = -EFAULT;
+ if ((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) ||
+ ((ULONG)sRdmBuffer.Register & 0x3)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n",
+ (int)sRdmBuffer.Register);
kfree(temp_buff);
- break;
+ return -EINVAL;
}
- case IOCTL_BCM_REGISTER_WRITE:
- case IOCTL_BCM_EEPROM_REGISTER_WRITE:
- {
- WRM_BUFFER sWrmBuffer = {0};
- UINT uiTempVar=0;
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n");
- return -EACCES;
- }
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
+ Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength);
- if (IoBuffer.InputLength > sizeof(sWrmBuffer))
- return -EINVAL;
+ if (Status == STATUS_SUCCESS)
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
+ Status = -EFAULT;
- /* Get WrmBuffer structure */
- if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ kfree(temp_buff);
+ break;
+ }
+ case IOCTL_BCM_REGISTER_WRITE:
+ case IOCTL_BCM_EEPROM_REGISTER_WRITE: {
+ WRM_BUFFER sWrmBuffer = {0};
+ UINT uiTempVar = 0;
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n");
+ return -EACCES;
+ }
- if( (((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) ||
- ((ULONG)sWrmBuffer.Register & 0x3) )
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n",
- (int)sWrmBuffer.Register);
- return -EINVAL;
- }
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(sWrmBuffer))
+ return -EINVAL;
- uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
- if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
- ((uiTempVar == EEPROM_REJECT_REG_1)||
+ /* Get WrmBuffer structure */
+ if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+
+ if ((((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) ||
+ ((ULONG)sWrmBuffer.Register & 0x3)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)sWrmBuffer.Register);
+ return -EINVAL;
+ }
+
+ uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
+ if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1) ||
(uiTempVar == EEPROM_REJECT_REG_2) ||
(uiTempVar == EEPROM_REJECT_REG_3) ||
(uiTempVar == EEPROM_REJECT_REG_4)) &&
- (cmd == IOCTL_BCM_REGISTER_WRITE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
+ (cmd == IOCTL_BCM_REGISTER_WRITE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
return -EFAULT;
- }
+ }
- Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register,
- (PUINT)sWrmBuffer.Data, sWrmBuffer.Length);
- if(Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
- Status = -EFAULT;
- }
+ Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register,
+ (PUINT)sWrmBuffer.Data, sWrmBuffer.Length);
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
+ Status = -EFAULT;
+ }
+ break;
+ }
+ case IOCTL_BCM_GPIO_SET_REQUEST: {
+ UCHAR ucResetValue[4];
+ UINT value = 0;
+ UINT uiBit = 0;
+ UINT uiOperation = 0;
+
+ GPIO_INFO gpio_info = {0};
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode");
+ return -EACCES;
+ }
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(gpio_info))
+ return -EINVAL;
+
+ if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+
+ uiBit = gpio_info.uiGpioNumber;
+ uiOperation = gpio_info.uiGpioValue;
+ value = (1<<uiBit);
+
+ if (IsReqGpioIsLedInNVM(Adapter, value) == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!", value);
+ Status = -EINVAL;
break;
}
- case IOCTL_BCM_GPIO_SET_REQUEST:
- {
- UCHAR ucResetValue[4];
- UINT value =0;
- UINT uiBit = 0;
- UINT uiOperation = 0;
-
- GPIO_INFO gpio_info = {0};
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode");
- return -EACCES;
- }
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
- if (IoBuffer.InputLength > sizeof(gpio_info))
- return -EINVAL;
- if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
- uiBit = gpio_info.uiGpioNumber;
- uiOperation = gpio_info.uiGpioValue;
- value= (1<<uiBit);
+ /* Set - setting 1 */
+ if (uiOperation) {
+ /* Set the gpio output register */
+ Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, (PUINT)(&value), sizeof(UINT));
- if(IsReqGpioIsLedInNVM(Adapter,value) ==FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!",value);
- Status = -EINVAL;
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to set the %dth GPIO\n", uiBit);
+ break;
+ }
+ } else {
+ /* Set the gpio output register */
+ Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)(&value), sizeof(UINT));
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to clear the %dth GPIO\n", uiBit);
break;
}
+ }
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
- if(uiOperation)//Set - setting 1
- {
- //Set the gpio output register
- Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_SET_REG ,
- (PUINT)(&value), sizeof(UINT));
- if(Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to set the %dth GPIO \n",uiBit);
- break;
- }
- }
- else//Unset - setting 0
- {
- //Set the gpio output register
- Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_CLR_REG ,
- (PUINT)(&value), sizeof(UINT));
- if(Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Set the GPIO bit\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to clear the %dth GPIO \n",uiBit);
- break;
- }
- }
+ if (STATUS_SUCCESS != Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "GPIO_MODE_REGISTER read failed");
+ break;
+ }
- Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER,
- (PUINT)ucResetValue, sizeof(UINT));
- if (STATUS_SUCCESS != Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO_MODE_REGISTER read failed");
- break;
- }
- //Set the gpio mode register to output
- *(UINT*)ucResetValue |= (1<<uiBit);
- Status = wrmaltWithLock(Adapter,GPIO_MODE_REGISTER ,
+ /* Set the gpio mode register to output */
+ *(UINT *)ucResetValue |= (1<<uiBit);
+ Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER,
(PUINT)ucResetValue, sizeof(UINT));
- if(Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Set the GPIO to output Mode\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to put GPIO in Output Mode\n");
- break;
- }
+
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO to output Mode\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to put GPIO in Output Mode\n");
+ break;
}
- break;
- case BCM_LED_THREAD_STATE_CHANGE_REQ:
- {
- USER_THREAD_REQ threadReq = { 0 };
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"User made LED thread InActive");
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode");
- Status = -EACCES;
- break;
- }
+ }
+ break;
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ case BCM_LED_THREAD_STATE_CHANGE_REQ: {
+ USER_THREAD_REQ threadReq = {0};
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "User made LED thread InActive");
- if (IoBuffer.InputLength > sizeof(threadReq))
- return -EINVAL;
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode");
+ Status = -EACCES;
+ break;
+ }
- //if LED thread is running(Actively or Inactively) set it state to make inactive
- if(Adapter->LEDInfo.led_thread_running)
- {
- if(threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Activating thread req");
- Adapter->DriverState = LED_THREAD_ACTIVE;
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DeActivating Thread req.....");
- Adapter->DriverState = LED_THREAD_INACTIVE;
- }
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- //signal thread.
- wake_up(&Adapter->LEDInfo.notify_led_event);
+ if (IoBuffer.InputLength > sizeof(threadReq))
+ return -EINVAL;
+
+ if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+ /* if LED thread is running(Actively or Inactively) set it state to make inactive */
+ if (Adapter->LEDInfo.led_thread_running) {
+ if (threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Activating thread req");
+ Adapter->DriverState = LED_THREAD_ACTIVE;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DeActivating Thread req.....");
+ Adapter->DriverState = LED_THREAD_INACTIVE;
}
+
+ /* signal thread. */
+ wake_up(&Adapter->LEDInfo.notify_led_event);
}
- break;
- case IOCTL_BCM_GPIO_STATUS_REQUEST:
- {
- ULONG uiBit = 0;
- UCHAR ucRead[4];
- GPIO_INFO gpio_info = {0};
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- return -EACCES;
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
- if (IoBuffer.InputLength > sizeof(gpio_info))
- return -EINVAL;
- if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
- uiBit = gpio_info.uiGpioNumber;
- //Set the gpio output register
- Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
- (PUINT)ucRead, sizeof(UINT));
- if(Status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n");
- return Status;
- }
+ }
+ break;
- }
- break;
- case IOCTL_BCM_GPIO_MULTI_REQUEST:
- {
- UCHAR ucResetValue[4];
- GPIO_MULTI_INFO gpio_multi_info[MAX_IDX];
- PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info;
-
- memset( pgpio_multi_info, 0, MAX_IDX * sizeof( GPIO_MULTI_INFO));
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- return -EINVAL;
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
- if (IoBuffer.InputLength > sizeof(gpio_multi_info))
- return -EINVAL;
- if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ case IOCTL_BCM_GPIO_STATUS_REQUEST: {
+ ULONG uiBit = 0;
+ UCHAR ucRead[4];
+ GPIO_INFO gpio_info = {0};
- if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_info[WIMAX_IDX].uiGPIOMask)== FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_info[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap);
- Status = -EINVAL;
- break;
- }
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE))
+ return -EACCES;
- /* Set the gpio output register */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if( ( pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
- ( pgpio_multi_info[WIMAX_IDX].uiGPIOCommand))
- {
- /* Set 1's in GPIO OUTPUT REGISTER */
- *(UINT*) ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
- pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
- pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
+ if (IoBuffer.InputLength > sizeof(gpio_info))
+ return -EINVAL;
- if( *(UINT*) ucResetValue)
- Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_SET_REG , (PUINT) ucResetValue, sizeof(ULONG));
+ if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
- if( Status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
- return Status;
- }
+ uiBit = gpio_info.uiGpioNumber;
+
+ /* Set the gpio output register */
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
+ (PUINT)ucRead, sizeof(UINT));
+
+ if (Status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n");
+ return Status;
+ }
+ }
+ break;
- /* Clear to 0's in GPIO OUTPUT REGISTER */
- *(UINT*) ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
- pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
- ( ~( pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
+ case IOCTL_BCM_GPIO_MULTI_REQUEST: {
+ UCHAR ucResetValue[4];
+ GPIO_MULTI_INFO gpio_multi_info[MAX_IDX];
+ PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info;
- if( *(UINT*) ucResetValue)
- Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_CLR_REG , (PUINT) ucResetValue, sizeof(ULONG));
+ memset(pgpio_multi_info, 0, MAX_IDX * sizeof(GPIO_MULTI_INFO));
- if( Status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_CLR_REG Failed." );
- return Status;
- }
- }
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE))
+ return -EINVAL;
- if( pgpio_multi_info[WIMAX_IDX].uiGPIOMask)
- {
- Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if(Status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM to GPIO_PIN_STATE_REGISTER Failed.");
- return Status;
- }
+ if (IoBuffer.InputLength > sizeof(gpio_multi_info))
+ return -EINVAL;
- pgpio_multi_info[WIMAX_IDX].uiGPIOValue = ( *(UINT*)ucResetValue &
- pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
- }
+ if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
- Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status);
- break;
- }
- }
+ if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask) == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
+ pgpio_multi_info[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap);
+ Status = -EINVAL;
break;
- case IOCTL_BCM_GPIO_MODE_REQUEST:
- {
- UCHAR ucResetValue[4];
- GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX];
- PGPIO_MULTI_MODE pgpio_multi_mode = ( PGPIO_MULTI_MODE) gpio_multi_mode;
+ }
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- return -EINVAL;
+ /* Set the gpio output register */
+ if ((pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
+ (pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) {
+ /* Set 1's in GPIO OUTPUT REGISTER */
+ *(UINT *)ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
- if (IoBuffer.InputLength > sizeof(gpio_multi_mode))
- return -EINVAL;
- if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ if (*(UINT *) ucResetValue)
+ Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG,
+ (PUINT)ucResetValue, sizeof(ULONG));
- Status = rdmaltWithLock( Adapter, ( UINT) GPIO_MODE_REGISTER, ( PUINT) ucResetValue, sizeof( UINT));
- if( STATUS_SUCCESS != Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Read of GPIO_MODE_REGISTER failed");
+ if (Status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
return Status;
}
- //Validating the request
- if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)== FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_mode[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap);
- Status = -EINVAL;
- break;
- }
+ /* Clear to 0's in GPIO OUTPUT REGISTER */
+ *(UINT *)ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
+ (~(pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
- if( pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)
- {
- /* write all OUT's (1's) */
- *( UINT*) ucResetValue |= ( pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
- pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
- /* write all IN's (0's) */
- *( UINT*) ucResetValue &= ~( ( ~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
- pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
-
- /* Currently implemented return the modes of all GPIO's
- * else needs to bit AND with mask
- * */
- pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT*)ucResetValue;
-
- Status = wrmaltWithLock( Adapter, GPIO_MODE_REGISTER , ( PUINT) ucResetValue, sizeof( ULONG));
- if( Status == STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM to GPIO_MODE_REGISTER Done");
- }
- else
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to GPIO_MODE_REGISTER Failed");
- Status = -EFAULT;
- break;
- }
- }
- else /* if uiGPIOMask is 0 then return mode register configuration */
- {
- pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *( UINT*) ucResetValue;
+ if (*(UINT *) ucResetValue)
+ Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)ucResetValue, sizeof(ULONG));
+
+ if (Status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_CLR_REG Failed.");
+ return Status;
}
- Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status);
- break;
+ }
+
+ if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) {
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+
+ if (Status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM to GPIO_PIN_STATE_REGISTER Failed.");
+ return Status;
}
+
+ pgpio_multi_info[WIMAX_IDX].uiGPIOValue = (*(UINT *)ucResetValue &
+ pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
}
- break;
- case IOCTL_MAC_ADDR_REQ:
- case IOCTL_LINK_REQ:
- case IOCTL_CM_REQUEST:
- case IOCTL_SS_INFO_REQ:
- case IOCTL_SEND_CONTROL_MESSAGE:
- case IOCTL_IDLE_REQ:
- {
- PVOID pvBuffer=NULL;
+ Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Failed while copying Content to IOBufer for user space err:%d", Status);
+ break;
+ }
+ }
+ break;
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ case IOCTL_BCM_GPIO_MODE_REQUEST: {
+ UCHAR ucResetValue[4];
+ GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX];
+ PGPIO_MULTI_MODE pgpio_multi_mode = (PGPIO_MULTI_MODE)gpio_multi_mode;
- /* FIXME: don't accept any length from user */
- pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
- if(!pvBuffer)
- return -ENOMEM;
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE))
+ return -EINVAL;
- if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- {
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength > sizeof(gpio_multi_mode))
+ return -EINVAL;
+
+ if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
+
+ Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
+
+ if (STATUS_SUCCESS != Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read of GPIO_MODE_REGISTER failed");
+ return Status;
+ }
+
+ /* Validating the request */
+ if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap);
+ Status = -EINVAL;
+ break;
+ }
+
+ if (pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) {
+ /* write all OUT's (1's) */
+ *(UINT *) ucResetValue |= (pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
+
+ /* write all IN's (0's) */
+ *(UINT *) ucResetValue &= ~((~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
+
+ /* Currently implemented return the modes of all GPIO's
+ * else needs to bit AND with mask
+ */
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
+
+ Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(ULONG));
+ if (Status == STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "WRM to GPIO_MODE_REGISTER Done");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "WRM to GPIO_MODE_REGISTER Failed");
Status = -EFAULT;
- kfree(pvBuffer);
break;
}
+ } else {
+/* if uiGPIOMask is 0 then return mode register configuration */
+ pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
+ }
- down(&Adapter->LowPowerModeSync);
- Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
- !Adapter->bPreparingForLowPowerMode,
- (1 * HZ));
- if(Status == -ERESTARTSYS)
- goto cntrlEnd;
-
- if(Adapter->bPreparingForLowPowerMode)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Preparing Idle Mode is still True - Hence Rejecting control message\n");
- Status = STATUS_FAILURE ;
- goto cntrlEnd ;
- }
- Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer);
- cntrlEnd:
- up(&Adapter->LowPowerModeSync);
+ Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Failed while copying Content to IOBufer for user space err:%d", Status);
+ break;
+ }
+ }
+ break;
+
+ case IOCTL_MAC_ADDR_REQ:
+ case IOCTL_LINK_REQ:
+ case IOCTL_CM_REQUEST:
+ case IOCTL_SS_INFO_REQ:
+ case IOCTL_SEND_CONTROL_MESSAGE:
+ case IOCTL_IDLE_REQ: {
+ PVOID pvBuffer = NULL;
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.InputLength < sizeof(struct link_request))
+ return -EINVAL;
+
+ if (IoBuffer.InputLength > MAX_CNTL_PKT_SIZE)
+ return -EINVAL;
+
+ pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
+ if (!pvBuffer)
+ return -ENOMEM;
+
+ if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
+ Status = -EFAULT;
kfree(pvBuffer);
break;
}
- case IOCTL_BCM_BUFFER_DOWNLOAD_START:
- {
- INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock) ;
- if(NVMAccess)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
- return -EACCES;
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
- if(!down_trylock(&Adapter->fw_download_sema))
- {
- Adapter->bBinDownloaded=FALSE;
- Adapter->fw_download_process_pid=current->pid;
- Adapter->bCfgDownloaded=FALSE;
- Adapter->fw_download_done=FALSE;
- netif_carrier_off(Adapter->dev);
- netif_stop_queue(Adapter->dev);
- Status = reset_card_proc(Adapter);
- if(Status)
- {
- pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name);
- up(&Adapter->fw_download_sema);
- up(&Adapter->NVMRdmWrmLock);
- break;
- }
- mdelay(10);
- }
- else
- {
- Status = -EBUSY;
+ down(&Adapter->LowPowerModeSync);
+ Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
+ !Adapter->bPreparingForLowPowerMode,
+ (1 * HZ));
+ if (Status == -ERESTARTSYS)
+ goto cntrlEnd;
+
+ if (Adapter->bPreparingForLowPowerMode) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "Preparing Idle Mode is still True - Hence Rejecting control message\n");
+ Status = STATUS_FAILURE;
+ goto cntrlEnd;
+ }
+ Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer);
+
+cntrlEnd:
+ up(&Adapter->LowPowerModeSync);
+ kfree(pvBuffer);
+ break;
+ }
+
+ case IOCTL_BCM_BUFFER_DOWNLOAD_START: {
+ INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ if (NVMAccess) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+ "IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
+ return -EACCES;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Starting the firmware download PID =0x%x!!!!\n", current->pid);
+
+ if (!down_trylock(&Adapter->fw_download_sema)) {
+ Adapter->bBinDownloaded = FALSE;
+ Adapter->fw_download_process_pid = current->pid;
+ Adapter->bCfgDownloaded = FALSE;
+ Adapter->fw_download_done = FALSE;
+ netif_carrier_off(Adapter->dev);
+ netif_stop_queue(Adapter->dev);
+ Status = reset_card_proc(Adapter);
+ if (Status) {
+ pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name);
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ break;
}
- up(&Adapter->NVMRdmWrmLock);
- break;
+ mdelay(10);
+ } else {
+ Status = -EBUSY;
}
- case IOCTL_BCM_BUFFER_DOWNLOAD:
- {
- FIRMWARE_INFO *psFwInfo = NULL;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
- do{
- if(!down_trylock(&Adapter->fw_download_sema))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid way to download buffer. Use Start and then call this!!!\n");
- Status=-EINVAL;
- break;
- }
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ up(&Adapter->NVMRdmWrmLock);
+ break;
+ }
+
+ case IOCTL_BCM_BUFFER_DOWNLOAD: {
+ FIRMWARE_INFO *psFwInfo = NULL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
+ do {
+ if (!down_trylock(&Adapter->fw_download_sema)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Invalid way to download buffer. Use Start and then call this!!!\n");
+ Status = -EINVAL;
+ break;
+ }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Length for FW DLD is : %lx\n",
- IoBuffer.InputLength);
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO))
- return -EINVAL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Length for FW DLD is : %lx\n", IoBuffer.InputLength);
- psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
- if(!psFwInfo)
- return -ENOMEM;
+ if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO))
+ return -EINVAL;
- if(copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength))
- return -EFAULT;
+ psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
+ if (!psFwInfo)
+ return -ENOMEM;
- if(!psFwInfo->pvMappedFirmwareAddress ||
- (psFwInfo->u32FirmwareLength == 0))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
- psFwInfo->u32FirmwareLength);
- Status = -EINVAL;
- break;
- }
- Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
- if(Status != STATUS_SUCCESS)
- {
- if(psFwInfo->u32StartingAddress==CONFIG_BEGIN_ADDR)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n");
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n");
- }
- //up(&Adapter->fw_download_sema);
+ if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength))
+ return -EFAULT;
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
- Adapter->DriverState = DRIVER_INIT;
- Adapter->LEDInfo.bLedInitDone = FALSE;
- wake_up(&Adapter->LEDInfo.notify_led_event);
- }
- }
- break ;
- }while(0);
+ if (!psFwInfo->pvMappedFirmwareAddress ||
+ (psFwInfo->u32FirmwareLength == 0)) {
- if(Status != STATUS_SUCCESS)
- up(&Adapter->fw_download_sema);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n");
- kfree(psFwInfo);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
+ psFwInfo->u32FirmwareLength);
+ Status = -EINVAL;
break;
}
- case IOCTL_BCM_BUFFER_DOWNLOAD_STOP:
- {
- INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
- if(NVMAccess)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " FW download blocked as EEPROM Read/Write is in progress\n");
- up(&Adapter->fw_download_sema);
- return -EACCES;
- }
- if(down_trylock(&Adapter->fw_download_sema))
- {
- Adapter->bBinDownloaded=TRUE;
- Adapter->bCfgDownloaded=TRUE;
- atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
-
- Adapter->CurrNumRecvDescs=0;
- Adapter->downloadDDR = 0;
-
- //setting the Mips to Run
- Status = run_card_proc(Adapter);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n");
- up(&Adapter->fw_download_sema);
- up(&Adapter->NVMRdmWrmLock);
- break;
- }
+
+ Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
+
+ if (Status != STATUS_SUCCESS) {
+ if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n");
else
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Firm Download Over...\n");
- mdelay(10);
- /* Wait for MailBox Interrupt */
- if(StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
- }
- timeout = 5*HZ;
- Adapter->waiting_to_fw_download_done = FALSE;
- wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
- Adapter->waiting_to_fw_download_done, timeout);
- Adapter->fw_download_process_pid=INVALID_PID;
- Adapter->fw_download_done=TRUE;
- atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
- Adapter->CurrNumRecvDescs = 0;
- Adapter->PrevNumRecvDescs = 0;
- atomic_set(&Adapter->cntrlpktCnt,0);
- Adapter->LinkUpStatus = 0;
- Adapter->LinkStatus = 0;
-
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
- Adapter->DriverState = FW_DOWNLOAD_DONE;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n");
+
+ /* up(&Adapter->fw_download_sema); */
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = DRIVER_INIT;
+ Adapter->LEDInfo.bLedInitDone = FALSE;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
+ }
+ break;
- if(!timeout)
- {
- Status = -ENODEV;
- }
+ } while (0);
+
+ if (Status != STATUS_SUCCESS)
+ up(&Adapter->fw_download_sema);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n");
+ kfree(psFwInfo);
+ break;
+ }
+
+ case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: {
+ INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+
+ if (NVMAccess) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "FW download blocked as EEPROM Read/Write is in progress\n");
+ up(&Adapter->fw_download_sema);
+ return -EACCES;
+ }
+
+ if (down_trylock(&Adapter->fw_download_sema)) {
+ Adapter->bBinDownloaded = TRUE;
+ Adapter->bCfgDownloaded = TRUE;
+ atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+ Adapter->CurrNumRecvDescs = 0;
+ Adapter->downloadDDR = 0;
+
+ /* setting the Mips to Run */
+ Status = run_card_proc(Adapter);
+
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n");
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ break;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
+ DBG_LVL_ALL, "Firm Download Over...\n");
}
- else
- {
- Status = -EINVAL;
+
+ mdelay(10);
+
+ /* Wait for MailBox Interrupt */
+ if (StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter))
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
+
+ timeout = 5*HZ;
+ Adapter->waiting_to_fw_download_done = FALSE;
+ wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
+ Adapter->waiting_to_fw_download_done, timeout);
+ Adapter->fw_download_process_pid = INVALID_PID;
+ Adapter->fw_download_done = TRUE;
+ atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
+ Adapter->CurrNumRecvDescs = 0;
+ Adapter->PrevNumRecvDescs = 0;
+ atomic_set(&Adapter->cntrlpktCnt, 0);
+ Adapter->LinkUpStatus = 0;
+ Adapter->LinkStatus = 0;
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = FW_DOWNLOAD_DONE;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
}
- up(&Adapter->fw_download_sema);
- up(&Adapter->NVMRdmWrmLock);
- break;
+
+ if (!timeout)
+ Status = -ENODEV;
+ } else {
+ Status = -EINVAL;
}
- case IOCTL_BE_BUCKET_SIZE:
- Status = 0;
- if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg))
- Status = -EFAULT;
- break;
- case IOCTL_RTPS_BUCKET_SIZE:
- Status = 0;
- if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg))
+ up(&Adapter->fw_download_sema);
+ up(&Adapter->NVMRdmWrmLock);
+ break;
+ }
+
+ case IOCTL_BE_BUCKET_SIZE:
+ Status = 0;
+ if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg))
+ Status = -EFAULT;
+ break;
+
+ case IOCTL_RTPS_BUCKET_SIZE:
+ Status = 0;
+ if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg))
+ Status = -EFAULT;
+ break;
+
+ case IOCTL_CHIP_RESET: {
+ INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ if (NVMAccess) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
+ return -EACCES;
+ }
+
+ down(&Adapter->RxAppControlQueuelock);
+ Status = reset_card_proc(Adapter);
+ flushAllAppQ();
+ up(&Adapter->RxAppControlQueuelock);
+ up(&Adapter->NVMRdmWrmLock);
+ ResetCounters(Adapter);
+ break;
+ }
+
+ case IOCTL_QOS_THRESHOLD: {
+ USHORT uiLoopIndex;
+
+ Status = 0;
+ for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
+ if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold,
+ (unsigned long __user *)arg)) {
Status = -EFAULT;
- break;
- case IOCTL_CHIP_RESET:
- {
- INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
- if(NVMAccess)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
- return -EACCES;
+ break;
}
- down(&Adapter->RxAppControlQueuelock);
- Status = reset_card_proc(Adapter);
- flushAllAppQ();
- up(&Adapter->RxAppControlQueuelock);
- up(&Adapter->NVMRdmWrmLock);
- ResetCounters(Adapter);
- break;
}
- case IOCTL_QOS_THRESHOLD:
- {
- USHORT uiLoopIndex;
+ break;
+ }
- Status = 0;
- for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
- if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold,
- (unsigned long __user *)arg)) {
- Status = -EFAULT;
- break;
- }
- }
- break;
+ case IOCTL_DUMP_PACKET_INFO:
+ DumpPackInfo(Adapter);
+ DumpPhsRules(&Adapter->stBCMPhsContext);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_GET_PACK_INFO:
+ if (copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES))
+ return -EFAULT;
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_BCM_SWITCH_TRANSFER_MODE: {
+ UINT uiData = 0;
+ if (copy_from_user(&uiData, argp, sizeof(UINT)))
+ return -EFAULT;
+
+ if (uiData) {
+ /* Allow All Packets */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
+ Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE;
+ } else {
+ /* Allow IP only Packets */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
+ Adapter->TransferMode = IP_PACKET_ONLY_MODE;
}
+ Status = STATUS_SUCCESS;
+ break;
+ }
- case IOCTL_DUMP_PACKET_INFO:
+ case IOCTL_BCM_GET_DRIVER_VERSION: {
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- DumpPackInfo(Adapter);
- DumpPhsRules(&Adapter->stBCMPhsContext);
- Status = STATUS_SUCCESS;
- break;
+ if (copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength))
+ return -EFAULT;
+ Status = STATUS_SUCCESS;
+ break;
+ }
- case IOCTL_GET_PACK_INFO:
- if(copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES))
- return -EFAULT;
- Status = STATUS_SUCCESS;
+ case IOCTL_BCM_GET_CURRENT_STATUS: {
+ LINK_STATE link_state;
+
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n");
+ Status = -EFAULT;
break;
- case IOCTL_BCM_SWITCH_TRANSFER_MODE:
- {
- UINT uiData = 0;
- if(copy_from_user(&uiData, argp, sizeof(UINT)))
- return -EFAULT;
+ }
- if(uiData) /* Allow All Packets */
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
- Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE;
- }
- else /* Allow IP only Packets */
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
- Adapter->TransferMode = IP_PACKET_ONLY_MODE;
- }
- Status = STATUS_SUCCESS;
+ if (IoBuffer.OutputLength != sizeof(link_state)) {
+ Status = -EINVAL;
break;
}
- case IOCTL_BCM_GET_DRIVER_VERSION:
- {
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ memset(&link_state, 0, sizeof(link_state));
+ link_state.bIdleMode = Adapter->IdleMode;
+ link_state.bShutdownMode = Adapter->bShutStatus;
+ link_state.ucLinkStatus = Adapter->LinkStatus;
- if(copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength))
- return -EFAULT;
- Status = STATUS_SUCCESS;
+ if (copy_to_user(IoBuffer.OutputBuffer, &link_state, min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n");
+ Status = -EFAULT;
break;
}
- case IOCTL_BCM_GET_CURRENT_STATUS:
- {
- LINK_STATE link_state;
+ Status = STATUS_SUCCESS;
+ break;
+ }
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n");
- Status = -EFAULT;
- break;
- }
- if (IoBuffer.OutputLength != sizeof(link_state)) {
- Status = -EINVAL;
- break;
- }
+ case IOCTL_BCM_SET_MAC_TRACING: {
+ UINT tracing_flag;
- memset(&link_state, 0, sizeof(link_state));
- link_state.bIdleMode = Adapter->IdleMode;
- link_state.bShutdownMode = Adapter->bShutStatus;
- link_state.ucLinkStatus = Adapter->LinkStatus;
+ /* copy ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if (copy_to_user(IoBuffer.OutputBuffer, &link_state,
- min_t(size_t, sizeof(link_state), IoBuffer.OutputLength)))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n");
- Status = -EFAULT;
- break;
- }
- Status = STATUS_SUCCESS;
- break;
+ if (copy_from_user(&tracing_flag, IoBuffer.InputBuffer, sizeof(UINT)))
+ return -EFAULT;
+
+ if (tracing_flag)
+ Adapter->pTarangs->MacTracingEnabled = TRUE;
+ else
+ Adapter->pTarangs->MacTracingEnabled = FALSE;
+ break;
+ }
+
+ case IOCTL_BCM_GET_DSX_INDICATION: {
+ ULONG ulSFId = 0;
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Mismatch req: %lx needed is =0x%zx!!!",
+ IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt));
+ return -EINVAL;
}
- case IOCTL_BCM_SET_MAC_TRACING:
- {
- UINT tracing_flag;
-
- /* copy ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
-
- if(copy_from_user(&tracing_flag,IoBuffer.InputBuffer,sizeof(UINT)))
- return -EFAULT;
-
- if (tracing_flag)
- Adapter->pTarangs->MacTracingEnabled = TRUE;
- else
- Adapter->pTarangs->MacTracingEnabled = FALSE;
- break;
- }
- case IOCTL_BCM_GET_DSX_INDICATION:
- {
- ULONG ulSFId=0;
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
- if(IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,
- "Mismatch req: %lx needed is =0x%zx!!!",
- IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt));
- return -EINVAL;
- }
+ if (copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId)))
+ return -EFAULT;
- if(copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId)))
- return -EFAULT;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId);
+ get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ case IOCTL_BCM_GET_HOST_MIBS: {
+ PVOID temp_buff;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId );
- get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer);
- Status=STATUS_SUCCESS;
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+ "Length Check failed %lu %zd\n",
+ IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS));
+ return -EINVAL;
}
- break;
- case IOCTL_BCM_GET_HOST_MIBS:
- {
- PVOID temp_buff;
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ /* FIXME: HOST_STATS are too big for kmalloc (122048)! */
+ temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL);
+ if (!temp_buff)
+ return STATUS_FAILURE;
- if(IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,
- "Length Check failed %lu %zd\n",
- IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS));
- return -EINVAL;
- }
+ Status = ProcessGetHostMibs(Adapter, temp_buff);
+ GetDroppedAppCntrlPktMibs(temp_buff, pTarang);
- /* FIXME: HOST_STATS are too big for kmalloc (122048)! */
- temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL);
- if(!temp_buff)
- return STATUS_FAILURE;
+ if (Status != STATUS_FAILURE)
+ if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS)))
+ Status = -EFAULT;
- Status = ProcessGetHostMibs(Adapter, temp_buff);
- GetDroppedAppCntrlPktMibs(temp_buff, pTarang);
+ kfree(temp_buff);
+ break;
+ }
- if (Status != STATUS_FAILURE)
- if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS)))
- Status = -EFAULT;
+ case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
+ if ((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE == Adapter->IdleMode)) {
+ Adapter->usIdleModePattern = ABORT_IDLE_MODE;
+ Adapter->bWakeUpDevice = TRUE;
+ wake_up(&Adapter->process_rx_cntrlpkt);
+ }
- kfree(temp_buff);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_BCM_BULK_WRM: {
+ PBULKWRM_BUFFER pBulkBuffer;
+ UINT uiTempVar = 0;
+ PCHAR pvBuffer = NULL;
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n");
+ Status = -EACCES;
break;
}
- case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
- if((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE==Adapter->IdleMode))
- {
- Adapter->usIdleModePattern = ABORT_IDLE_MODE;
- Adapter->bWakeUpDevice = TRUE;
- wake_up(&Adapter->process_rx_cntrlpkt);
- }
- Status = STATUS_SUCCESS;
- break;
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- case IOCTL_BCM_BULK_WRM:
- {
- PBULKWRM_BUFFER pBulkBuffer;
- UINT uiTempVar=0;
- PCHAR pvBuffer = NULL;
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n");
- Status = -EACCES;
- break;
- }
+ /* FIXME: restrict length */
+ pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
+ if (!pvBuffer)
+ return -ENOMEM;
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ /* Get WrmBuffer structure */
+ if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
+ kfree(pvBuffer);
+ Status = -EFAULT;
+ break;
+ }
- /* FIXME: restrict length */
- pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
- if(!pvBuffer)
- return -ENOMEM;
-
- /* Get WrmBuffer structure */
- if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
- {
- kfree(pvBuffer);
- Status = -EFAULT;
- break;
- }
+ pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer;
- pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer;
+ if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
+ ((ULONG)pBulkBuffer->Register & 0x3)) {
+ kfree(pvBuffer);
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)pBulkBuffer->Register);
+ Status = -EINVAL;
+ break;
+ }
- if(((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
- ((ULONG)pBulkBuffer->Register & 0x3))
- {
- kfree(pvBuffer);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"WRM Done On invalid Address : %x Access Denied.\n",(int)pBulkBuffer->Register);
- Status = -EINVAL;
- break;
- }
+ uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK;
+ if (!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) &&
+ ((uiTempVar == EEPROM_REJECT_REG_1) ||
+ (uiTempVar == EEPROM_REJECT_REG_2) ||
+ (uiTempVar == EEPROM_REJECT_REG_3) ||
+ (uiTempVar == EEPROM_REJECT_REG_4)) &&
+ (cmd == IOCTL_BCM_REGISTER_WRITE)) {
+ kfree(pvBuffer);
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
+ Status = -EFAULT;
+ break;
+ }
- uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK;
- if(!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE)
- && ((uiTempVar == EEPROM_REJECT_REG_1)||
- (uiTempVar == EEPROM_REJECT_REG_2) ||
- (uiTempVar == EEPROM_REJECT_REG_3) ||
- (uiTempVar == EEPROM_REJECT_REG_4)) &&
- (cmd == IOCTL_BCM_REGISTER_WRITE))
- {
- kfree(pvBuffer);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"EEPROM Access Denied, not in VSG Mode\n");
- Status = -EFAULT;
- break;
- }
+ if (pBulkBuffer->SwapEndian == FALSE)
+ Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
+ else
+ Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
- if(pBulkBuffer->SwapEndian == FALSE)
- Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
- else
- Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
+ if (Status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
- if(Status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
- }
+ kfree(pvBuffer);
+ break;
+ }
- kfree(pvBuffer);
- break;
- }
+ case IOCTL_BCM_GET_NVM_SIZE:
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- case IOCTL_BCM_GET_NVM_SIZE:
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ if (Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH) {
+ if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT)))
return -EFAULT;
+ }
- if(Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH ) {
- if(copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT)))
- return -EFAULT;
- }
- Status = STATUS_SUCCESS ;
- break;
+ Status = STATUS_SUCCESS;
+ break;
- case IOCTL_BCM_CAL_INIT :
+ case IOCTL_BCM_CAL_INIT: {
+ UINT uiSectorSize = 0 ;
+ if (Adapter->eNVMType == NVM_FLASH) {
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- {
- UINT uiSectorSize = 0 ;
- if(Adapter->eNVMType == NVM_FLASH)
- {
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT)))
+ return -EFAULT;
- if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT)))
+ if ((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) {
+ if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize,
+ sizeof(UINT)))
+ return -EFAULT;
+ } else {
+ if (IsFlash2x(Adapter)) {
+ if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize, sizeof(UINT)))
return -EFAULT;
-
- if((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE))
- {
- if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize,
- sizeof(UINT)))
- return -EFAULT;
- }
- else
- {
- if(IsFlash2x(Adapter))
- {
- if (copy_to_user(IoBuffer.OutputBuffer,
- &Adapter->uiSectorSize ,
- sizeof(UINT)))
- return -EFAULT;
- }
- else
- {
- if((TRUE == Adapter->bShutStatus) ||
- (TRUE == Adapter->IdleMode))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle/Shutdown Mode\n");
- return -EACCES;
- }
-
- Adapter->uiSectorSize = uiSectorSize ;
- BcmUpdateSectorSize(Adapter,Adapter->uiSectorSize);
- }
+ } else {
+ if ((TRUE == Adapter->bShutStatus) || (TRUE == Adapter->IdleMode)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is in Idle/Shutdown Mode\n");
+ return -EACCES;
}
- Status = STATUS_SUCCESS ;
- }
- else
- {
- Status = STATUS_FAILURE;
+
+ Adapter->uiSectorSize = uiSectorSize;
+ BcmUpdateSectorSize(Adapter, Adapter->uiSectorSize);
}
}
- break;
- case IOCTL_BCM_SET_DEBUG :
-#ifdef DEBUG
- {
- USER_BCM_DBG_STATE sUserDebugState;
-
-// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Entered the ioctl %x \n", IOCTL_BCM_SET_DEBUG );
+ Status = STATUS_SUCCESS;
+ } else {
+ Status = STATUS_FAILURE;
+ }
+ }
+ break;
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n");
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ case IOCTL_BCM_SET_DEBUG:
+#ifdef DEBUG
+ {
+ USER_BCM_DBG_STATE sUserDebugState;
- if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE)))
- return -EFAULT;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n");
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+ if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE)))
+ return -EFAULT;
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
sUserDebugState.OnOff, sUserDebugState.Type);
- //sUserDebugState.Subtype <<= 1;
- sUserDebugState.Subtype = 1 << sUserDebugState.Subtype;
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype);
-
- // Update new 'DebugState' in the Adapter
- Adapter->stDebugState.type |= sUserDebugState.Type;
- /* Subtype: A bitmap of 32 bits for Subtype per Type.
- * Valid indexes in 'subtype' array: 1,2,4,8
- * corresponding to valid Type values. Hence we can use the 'Type' field
- * as the index value, ignoring the array entries 0,3,5,6,7 !
- */
- if (sUserDebugState.OnOff)
- Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype;
- else
- Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype;
-
- BCM_SHOW_DEBUG_BITMAP(Adapter);
+ /* sUserDebugState.Subtype <<= 1; */
+ sUserDebugState.Subtype = 1 << sUserDebugState.Subtype;
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype);
+
+ /* Update new 'DebugState' in the Adapter */
+ Adapter->stDebugState.type |= sUserDebugState.Type;
+ /* Subtype: A bitmap of 32 bits for Subtype per Type.
+ * Valid indexes in 'subtype' array: 1,2,4,8
+ * corresponding to valid Type values. Hence we can use the 'Type' field
+ * as the index value, ignoring the array entries 0,3,5,6,7 !
+ */
+ if (sUserDebugState.OnOff)
+ Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype;
+ else
+ Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype;
- }
+ BCM_SHOW_DEBUG_BITMAP(Adapter);
+ }
#endif
+ break;
+
+ case IOCTL_BCM_NVM_READ:
+ case IOCTL_BCM_NVM_WRITE: {
+ NVM_READWRITE stNVMReadWrite;
+ PUCHAR pReadData = NULL;
+ ULONG ulDSDMagicNumInUsrBuff = 0;
+ struct timeval tv0, tv1;
+ memset(&tv0, 0, sizeof(struct timeval));
+ memset(&tv1, 0, sizeof(struct timeval));
+ if ((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
+ Status = -EFAULT;
break;
- case IOCTL_BCM_NVM_READ:
- case IOCTL_BCM_NVM_WRITE:
- {
- NVM_READWRITE stNVMReadWrite;
- PUCHAR pReadData = NULL;
- ULONG ulDSDMagicNumInUsrBuff = 0;
- struct timeval tv0, tv1;
- memset(&tv0,0,sizeof(struct timeval));
- memset(&tv1,0,sizeof(struct timeval));
- if((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0))
- {
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,"The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
- Status = -EFAULT;
- break;
- }
+ }
- if(IsFlash2x(Adapter))
- {
- if((Adapter->eActiveDSD != DSD0) &&
- (Adapter->eActiveDSD != DSD1) &&
- (Adapter->eActiveDSD != DSD2))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"No DSD is active..hence NVM Command is blocked");
- return STATUS_FAILURE ;
- }
- }
+ if (IsFlash2x(Adapter)) {
+ if ((Adapter->eActiveDSD != DSD0) &&
+ (Adapter->eActiveDSD != DSD1) &&
+ (Adapter->eActiveDSD != DSD2)) {
- /* Copy Ioctl Buffer structure */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No DSD is active..hence NVM Command is blocked");
+ return STATUS_FAILURE ;
+ }
+ }
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- if(copy_from_user(&stNVMReadWrite,
- (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer,
- sizeof(NVM_READWRITE)))
- return -EFAULT;
+ if (copy_from_user(&stNVMReadWrite,
+ (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer,
+ sizeof(NVM_READWRITE)))
+ return -EFAULT;
- //
- // Deny the access if the offset crosses the cal area limit.
- //
- if((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize)
- {
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset ,
-// stNVMReadWrite.uiNumBytes);
- Status = STATUS_FAILURE;
- break;
- }
+ /*
+ * Deny the access if the offset crosses the cal area limit.
+ */
- pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL);
- if(!pReadData)
- return -ENOMEM;
+ if ((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize) {
+ /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); */
+ Status = STATUS_FAILURE;
+ break;
+ }
- if(copy_from_user(pReadData, stNVMReadWrite.pBuffer,
- stNVMReadWrite.uiNumBytes))
- {
- Status = -EFAULT;
- kfree(pReadData);
- break;
- }
+ pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL);
+ if (!pReadData)
+ return -ENOMEM;
- do_gettimeofday(&tv0);
- if(IOCTL_BCM_NVM_READ == cmd)
- {
- down(&Adapter->NVMRdmWrmLock);
+ if (copy_from_user(pReadData, stNVMReadWrite.pBuffer, stNVMReadWrite.uiNumBytes)) {
+ Status = -EFAULT;
+ kfree(pReadData);
+ break;
+ }
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadData);
- return -EACCES;
- }
+ do_gettimeofday(&tv0);
+ if (IOCTL_BCM_NVM_READ == cmd) {
+ down(&Adapter->NVMRdmWrmLock);
- Status = BeceemNVMRead(Adapter, (PUINT)pReadData,
- stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes);
-
- up(&Adapter->NVMRdmWrmLock);
-
- if(Status != STATUS_SUCCESS)
- {
- kfree(pReadData);
- return Status;
- }
- if(copy_to_user(stNVMReadWrite.pBuffer,pReadData, stNVMReadWrite.uiNumBytes))
- {
- kfree(pReadData);
- Status = -EFAULT;
- }
- }
- else
- {
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- down(&Adapter->NVMRdmWrmLock);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadData);
+ return -EACCES;
+ }
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadData);
- return -EACCES;
- }
+ Status = BeceemNVMRead(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes);
+ up(&Adapter->NVMRdmWrmLock);
- Adapter->bHeaderChangeAllowed = TRUE ;
- if(IsFlash2x(Adapter))
- {
- /*
- New Requirement:-
- DSD section updation will be allowed in two case:-
- 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull
- 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is
- corrupted then user space program first modify the DSD header with valid DSD sig so
- that this as well as further write may be worthwhile.
-
- This restriction has been put assuming that if DSD sig is corrupted, DSD
- data won't be considered valid.
-
-
- */
- Status = BcmFlash2xCorruptSig(Adapter,Adapter->eActiveDSD);
- if(Status != STATUS_SUCCESS)
- {
- if(( (stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize ) ||
- (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input..");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadData);
- return Status;
- }
-
- ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE));
- if(ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input..");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadData);
- return Status;
- }
- }
- }
- Status = BeceemNVMWrite(Adapter, (PUINT )pReadData,
- stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify);
- if(IsFlash2x(Adapter))
- BcmFlash2xWriteSig(Adapter,Adapter->eActiveDSD);
+ if (Status != STATUS_SUCCESS) {
+ kfree(pReadData);
+ return Status;
+ }
- Adapter->bHeaderChangeAllowed = FALSE ;
+ if (copy_to_user(stNVMReadWrite.pBuffer, pReadData, stNVMReadWrite.uiNumBytes)) {
+ kfree(pReadData);
+ Status = -EFAULT;
+ }
+ } else {
+ down(&Adapter->NVMRdmWrmLock);
- up(&Adapter->NVMRdmWrmLock);
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadData);
+ return -EACCES;
+ }
- if(Status != STATUS_SUCCESS)
- {
+ Adapter->bHeaderChangeAllowed = TRUE;
+ if (IsFlash2x(Adapter)) {
+ /*
+ * New Requirement:-
+ * DSD section updation will be allowed in two case:-
+ * 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull
+ * 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is
+ * corrupted then user space program first modify the DSD header with valid DSD sig so
+ * that this as well as further write may be worthwhile.
+ *
+ * This restriction has been put assuming that if DSD sig is corrupted, DSD
+ * data won't be considered valid.
+ */
+
+ Status = BcmFlash2xCorruptSig(Adapter, Adapter->eActiveDSD);
+ if (Status != STATUS_SUCCESS) {
+ if (((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize) ||
+ (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input..");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadData);
+ return Status;
+ }
+
+ ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE));
+ if (ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input..");
+ up(&Adapter->NVMRdmWrmLock);
kfree(pReadData);
return Status;
}
}
- do_gettimeofday(&tv1);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n",(tv1.tv_sec - tv0.tv_sec)*1000 +(tv1.tv_usec - tv0.tv_usec)/1000);
+ }
+
+ Status = BeceemNVMWrite(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify);
+ if (IsFlash2x(Adapter))
+ BcmFlash2xWriteSig(Adapter, Adapter->eActiveDSD);
+
+ Adapter->bHeaderChangeAllowed = FALSE;
+ up(&Adapter->NVMRdmWrmLock);
+ if (Status != STATUS_SUCCESS) {
kfree(pReadData);
- Status = STATUS_SUCCESS;
+ return Status;
}
- break;
- case IOCTL_BCM_FLASH2X_SECTION_READ :
- {
-
- FLASH2X_READWRITE sFlash2xRead = {0};
- PUCHAR pReadBuff = NULL ;
- UINT NOB = 0;
- UINT BuffSize = 0;
- UINT ReadBytes = 0;
- UINT ReadOffset = 0;
- void __user *OutPutBuff;
-
- if(IsFlash2x(Adapter) != TRUE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
- return -EINVAL;
- }
+ }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ do_gettimeofday(&tv1);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n", (tv1.tv_sec - tv0.tv_sec)*1000 + (tv1.tv_usec - tv0.tv_usec)/1000);
- //Reading FLASH 2.x READ structure
- if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer,sizeof(FLASH2X_READWRITE)))
- return -EFAULT;
+ kfree(pReadData);
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ case IOCTL_BCM_FLASH2X_SECTION_READ: {
+ FLASH2X_READWRITE sFlash2xRead = {0};
+ PUCHAR pReadBuff = NULL ;
+ UINT NOB = 0;
+ UINT BuffSize = 0;
+ UINT ReadBytes = 0;
+ UINT ReadOffset = 0;
+ void __user *OutPutBuff;
+
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xRead.Section);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%x" ,sFlash2xRead.offset);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xRead.numOfBytes);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xRead.bVerify);
+ /* Reading FLASH 2.x READ structure */
+ if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)))
+ return -EFAULT;
- //This was internal to driver for raw read. now it has ben exposed to user space app.
- if(validateFlash2xReadWrite(Adapter,&sFlash2xRead) == FALSE)
- return STATUS_FAILURE ;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xRead.Section);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%x", sFlash2xRead.offset);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xRead.numOfBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xRead.bVerify);
- NOB = sFlash2xRead.numOfBytes;
- if(NOB > Adapter->uiSectorSize )
- BuffSize = Adapter->uiSectorSize;
- else
- BuffSize = NOB ;
+ /* This was internal to driver for raw read. now it has ben exposed to user space app. */
+ if (validateFlash2xReadWrite(Adapter, &sFlash2xRead) == FALSE)
+ return STATUS_FAILURE;
- ReadOffset = sFlash2xRead.offset ;
- OutPutBuff = IoBuffer.OutputBuffer;
+ NOB = sFlash2xRead.numOfBytes;
+ if (NOB > Adapter->uiSectorSize)
+ BuffSize = Adapter->uiSectorSize;
+ else
+ BuffSize = NOB;
+ ReadOffset = sFlash2xRead.offset ;
+ OutPutBuff = IoBuffer.OutputBuffer;
+ pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
- pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
- if(pReadBuff == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure");
- return -ENOMEM;
- }
- down(&Adapter->NVMRdmWrmLock);
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadBuff);
- return -EACCES;
- }
+ if (pReadBuff == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure");
+ return -ENOMEM;
+ }
+ down(&Adapter->NVMRdmWrmLock);
- while(NOB)
- {
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- if(NOB > Adapter->uiSectorSize )
- ReadBytes = Adapter->uiSectorSize;
- else
- ReadBytes = NOB;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ return -EACCES;
+ }
+ while (NOB) {
+ if (NOB > Adapter->uiSectorSize)
+ ReadBytes = Adapter->uiSectorSize;
+ else
+ ReadBytes = NOB;
- //Reading the data from Flash 2.x
+ /* Reading the data from Flash 2.x */
+ Status = BcmFlash2xBulkRead(Adapter, (PUINT)pReadBuff, sFlash2xRead.Section, ReadOffset, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Flash 2x read err with Status :%d", Status);
+ break;
+ }
- Status = BcmFlash2xBulkRead(Adapter,(PUINT)pReadBuff,sFlash2xRead.Section,ReadOffset,ReadBytes);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Flash 2x read err with Status :%d", Status);
- break ;
- }
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes);
- BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff, ReadBytes);
-
- Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Copy to use failed with status :%d", Status);
- break;
- }
- NOB = NOB - ReadBytes;
- if(NOB)
- {
- ReadOffset = ReadOffset + ReadBytes ;
- OutPutBuff = OutPutBuff + ReadBytes ;
- }
+ Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy to use failed with status :%d", Status);
+ break;
+ }
+ NOB = NOB - ReadBytes;
+ if (NOB) {
+ ReadOffset = ReadOffset + ReadBytes;
+ OutPutBuff = OutPutBuff + ReadBytes ;
+ }
+ }
- }
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadBuff);
-
- }
- break ;
- case IOCTL_BCM_FLASH2X_SECTION_WRITE :
- {
- FLASH2X_READWRITE sFlash2xWrite = {0};
- PUCHAR pWriteBuff;
- void __user *InputAddr;
- UINT NOB = 0;
- UINT BuffSize = 0;
- UINT WriteOffset = 0;
- UINT WriteBytes = 0;
-
- if(IsFlash2x(Adapter) != TRUE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
- return -EINVAL;
- }
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ }
+ break;
+
+ case IOCTL_BCM_FLASH2X_SECTION_WRITE: {
+ FLASH2X_READWRITE sFlash2xWrite = {0};
+ PUCHAR pWriteBuff;
+ void __user *InputAddr;
+ UINT NOB = 0;
+ UINT BuffSize = 0;
+ UINT WriteOffset = 0;
+ UINT WriteBytes = 0;
+
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
- //First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite
- Adapter->bAllDSDWriteAllow = FALSE;
+ /* First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite */
+ Adapter->bAllDSDWriteAllow = FALSE;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- //Reading FLASH 2.x READ structure
- if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)))
- return -EFAULT;
+ /* Reading FLASH 2.x READ structure */
+ if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)))
+ return -EFAULT;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xWrite.Section);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%d" ,sFlash2xWrite.offset);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xWrite.numOfBytes);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xWrite.bVerify);
- if((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) &&
- (sFlash2xWrite.Section != VSA2) )
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Only VSA write is allowed");
- return -EINVAL;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xWrite.Section);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%d", sFlash2xWrite.offset);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xWrite.numOfBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xWrite.bVerify);
+
+ if ((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && (sFlash2xWrite.Section != VSA2)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Only VSA write is allowed");
+ return -EINVAL;
+ }
- if(validateFlash2xReadWrite(Adapter,&sFlash2xWrite) == FALSE)
- return STATUS_FAILURE ;
+ if (validateFlash2xReadWrite(Adapter, &sFlash2xWrite) == FALSE)
+ return STATUS_FAILURE;
- InputAddr = sFlash2xWrite.pDataBuff;
- WriteOffset = sFlash2xWrite.offset ;
- NOB = sFlash2xWrite.numOfBytes;
+ InputAddr = sFlash2xWrite.pDataBuff;
+ WriteOffset = sFlash2xWrite.offset;
+ NOB = sFlash2xWrite.numOfBytes;
- if(NOB > Adapter->uiSectorSize )
- BuffSize = Adapter->uiSectorSize;
- else
- BuffSize = NOB ;
+ if (NOB > Adapter->uiSectorSize)
+ BuffSize = Adapter->uiSectorSize;
+ else
+ BuffSize = NOB ;
- pWriteBuff = kmalloc(BuffSize, GFP_KERNEL);
- if(pWriteBuff == NULL)
- return -ENOMEM;
+ pWriteBuff = kmalloc(BuffSize, GFP_KERNEL);
+ if (pWriteBuff == NULL)
+ return -ENOMEM;
- //extracting the remainder of the given offset.
- WriteBytes = Adapter->uiSectorSize ;
- if(WriteOffset % Adapter->uiSectorSize)
- WriteBytes =Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize);
- if(NOB < WriteBytes)
+ /* extracting the remainder of the given offset. */
+ WriteBytes = Adapter->uiSectorSize;
+ if (WriteOffset % Adapter->uiSectorSize)
+ WriteBytes = Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize);
+
+ if (NOB < WriteBytes)
+ WriteBytes = NOB;
+
+ down(&Adapter->NVMRdmWrmLock);
+
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pWriteBuff);
+ return -EACCES;
+ }
+
+ BcmFlash2xCorruptSig(Adapter, sFlash2xWrite.Section);
+ do {
+ Status = copy_from_user(pWriteBuff, InputAddr, WriteBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to user failed with status :%d", Status);
+ break;
+ }
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pWriteBuff, WriteBytes);
+
+ /* Writing the data from Flash 2.x */
+ Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pWriteBuff, sFlash2xWrite.Section, WriteOffset, WriteBytes, sFlash2xWrite.bVerify);
+
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status);
+ break;
+ }
+
+ NOB = NOB - WriteBytes;
+ if (NOB) {
+ WriteOffset = WriteOffset + WriteBytes;
+ InputAddr = InputAddr + WriteBytes;
+ if (NOB > Adapter->uiSectorSize)
+ WriteBytes = Adapter->uiSectorSize;
+ else
WriteBytes = NOB;
+ }
+ } while (NOB > 0);
- down(&Adapter->NVMRdmWrmLock);
+ BcmFlash2xWriteSig(Adapter, sFlash2xWrite.Section);
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pWriteBuff);
+ }
+ break;
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- kfree(pWriteBuff);
- return -EACCES;
- }
+ case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP: {
+ PFLASH2X_BITMAP psFlash2xBitMap;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
- BcmFlash2xCorruptSig(Adapter,sFlash2xWrite.Section);
- do
- {
- Status = copy_from_user(pWriteBuff,InputAddr,WriteBytes);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to user failed with status :%d", Status);
- break ;
- }
- BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pWriteBuff,WriteBytes);
- //Writing the data from Flash 2.x
- Status = BcmFlash2xBulkWrite(Adapter,(PUINT)pWriteBuff,sFlash2xWrite.Section,WriteOffset,WriteBytes,sFlash2xWrite.bVerify);
-
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status);
- break ;
- }
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
- NOB = NOB - WriteBytes;
- if(NOB)
- {
- WriteOffset = WriteOffset + WriteBytes ;
- InputAddr = InputAddr + WriteBytes ;
- if(NOB > Adapter->uiSectorSize )
- WriteBytes = Adapter->uiSectorSize;
- else
- WriteBytes = NOB;
- }
+ if (IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP))
+ return -EINVAL;
+ psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL);
+ if (psFlash2xBitMap == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory is not available");
+ return -ENOMEM;
+ }
- } while(NOB > 0);
- BcmFlash2xWriteSig(Adapter,sFlash2xWrite.Section);
- up(&Adapter->NVMRdmWrmLock);
- kfree(pWriteBuff);
- }
- break ;
- case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP :
- {
+ /* Reading the Flash Sectio Bit map */
+ down(&Adapter->NVMRdmWrmLock);
- PFLASH2X_BITMAP psFlash2xBitMap;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(psFlash2xBitMap);
+ return -EACCES;
+ }
- if(IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP))
- return -EINVAL;
+ BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
+ up(&Adapter->NVMRdmWrmLock);
+ if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP)))
+ Status = -EFAULT;
- psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL);
- if(psFlash2xBitMap == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory is not available");
- return -ENOMEM ;
- }
- //Reading the Flash Sectio Bit map
- down(&Adapter->NVMRdmWrmLock);
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- kfree(psFlash2xBitMap);
- return -EACCES;
- }
+ kfree(psFlash2xBitMap);
+ }
+ break;
- BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
- up(&Adapter->NVMRdmWrmLock);
- if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP)))
- Status = -EFAULT;
-
- kfree(psFlash2xBitMap);
- }
- break ;
- case IOCTL_BCM_SET_ACTIVE_SECTION :
- {
- FLASH2X_SECTION_VAL eFlash2xSectionVal = 0;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called");
-
- if(IsFlash2x(Adapter) != TRUE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
- return -EINVAL;
- }
+ case IOCTL_BCM_SET_ACTIVE_SECTION: {
+ FLASH2X_SECTION_VAL eFlash2xSectionVal = 0;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called");
- Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
- return Status;
- }
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
- Status = copy_from_user(&eFlash2xSectionVal,IoBuffer.InputBuffer, sizeof(INT));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
- return Status;
- }
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ return Status;
+ }
- down(&Adapter->NVMRdmWrmLock);
+ Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
+ return Status;
+ }
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- return -EACCES;
- }
+ down(&Adapter->NVMRdmWrmLock);
- Status = BcmSetActiveSection(Adapter,eFlash2xSectionVal);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed to make it's priority Highest. Status %d", Status);
- }
- up(&Adapter->NVMRdmWrmLock);
- }
- break ;
- case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION :
- {
- //Right Now we are taking care of only DSD
- Adapter->bAllDSDWriteAllow = FALSE ;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
-
- Status = STATUS_SUCCESS ;
- }
- break ;
- case IOCTL_BCM_COPY_SECTION :
- {
- FLASH2X_COPY_SECTION sCopySectStrut = {0};
- Status = STATUS_SUCCESS;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called");
-
- Adapter->bAllDSDWriteAllow = FALSE ;
- if(IsFlash2x(Adapter) != TRUE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
- return -EINVAL;
- }
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status);
- return Status;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
- Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status);
- return Status;
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes);
+ Status = BcmSetActiveSection(Adapter, eFlash2xSectionVal);
+ if (Status)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Failed to make it's priority Highest. Status %d", Status);
+ up(&Adapter->NVMRdmWrmLock);
+ }
+ break;
- if(IsSectionExistInFlash(Adapter,sCopySectStrut.SrcSection) == FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection);
- return -EINVAL;
- }
+ case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION: {
+ /* Right Now we are taking care of only DSD */
+ Adapter->bAllDSDWriteAllow = FALSE;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
+ Status = STATUS_SUCCESS;
+ }
+ break;
- if(IsSectionExistInFlash(Adapter,sCopySectStrut.DstSection) == FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection);
- return -EINVAL;
- }
+ case IOCTL_BCM_COPY_SECTION: {
+ FLASH2X_COPY_SECTION sCopySectStrut = {0};
+ Status = STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called");
- if(sCopySectStrut.SrcSection == sCopySectStrut.DstSection)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Source and Destination section should be different");
- return -EINVAL;
- }
+ Adapter->bAllDSDWriteAllow = FALSE;
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
- down(&Adapter->NVMRdmWrmLock);
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status);
+ return Status;
+ }
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- up(&Adapter->NVMRdmWrmLock);
- return -EACCES;
- }
+ Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status);
+ return Status;
+ }
- if(sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2)
- {
- if(IsNonCDLessDevice(Adapter))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is Non-CDLess hence won't have ISO !!");
- Status = -EINVAL ;
- }
- else if(sCopySectStrut.numOfBytes == 0)
- {
- Status = BcmCopyISO(Adapter,sCopySectStrut);
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Partial Copy of ISO section is not Allowed..");
- Status = STATUS_FAILURE ;
- }
- up(&Adapter->NVMRdmWrmLock);
- return Status;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes);
- Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection,
- sCopySectStrut.DstSection,sCopySectStrut.offset,sCopySectStrut.numOfBytes);
- up(&Adapter->NVMRdmWrmLock);
- }
- break ;
- case IOCTL_BCM_GET_FLASH_CS_INFO :
- {
- Status = STATUS_SUCCESS;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called");
-
- Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
- break;
- }
- if(Adapter->eNVMType != NVM_FLASH)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Connected device does not have flash");
- Status = -EINVAL;
- break;
- }
- if(IsFlash2x(Adapter) == TRUE)
- {
+ if (IsSectionExistInFlash(Adapter, sCopySectStrut.SrcSection) == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection);
+ return -EINVAL;
+ }
- if(IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO))
- return -EINVAL;
+ if (IsSectionExistInFlash(Adapter, sCopySectStrut.DstSection) == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection);
+ return -EINVAL;
+ }
- if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO)))
- return -EFAULT;
- }
- else
- {
- if(IoBuffer.OutputLength < sizeof(FLASH_CS_INFO))
- return -EINVAL;
+ if (sCopySectStrut.SrcSection == sCopySectStrut.DstSection) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source and Destination section should be different");
+ return -EINVAL;
+ }
- if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO)))
- return -EFAULT;
+ down(&Adapter->NVMRdmWrmLock);
- }
- }
- break ;
- case IOCTL_BCM_SELECT_DSD :
- {
- UINT SectOfset = 0;
- FLASH2X_SECTION_VAL eFlash2xSectionVal;
- eFlash2xSectionVal = NO_SECTION_VAL ;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_SELECT_DSD Called");
-
- if(IsFlash2x(Adapter) != TRUE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map");
- return -EINVAL;
- }
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
- return Status;
- }
- Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
- return Status;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Read Section :%d", eFlash2xSectionVal);
- if((eFlash2xSectionVal != DSD0) &&
- (eFlash2xSectionVal != DSD1) &&
- (eFlash2xSectionVal != DSD2) )
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Passed section<%x> is not DSD section", eFlash2xSectionVal);
- return STATUS_FAILURE ;
- }
+ if (sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2) {
+ if (IsNonCDLessDevice(Adapter)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is Non-CDLess hence won't have ISO !!");
+ Status = -EINVAL;
+ } else if (sCopySectStrut.numOfBytes == 0) {
+ Status = BcmCopyISO(Adapter, sCopySectStrut);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Partial Copy of ISO section is not Allowed..");
+ Status = STATUS_FAILURE;
+ }
+ up(&Adapter->NVMRdmWrmLock);
+ return Status;
+ }
- SectOfset= BcmGetSectionValStartOffset(Adapter,eFlash2xSectionVal);
- if(SectOfset == INVALID_OFFSET)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal);
- return -EINVAL;
- }
+ Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection,
+ sCopySectStrut.DstSection, sCopySectStrut.offset, sCopySectStrut.numOfBytes);
+ up(&Adapter->NVMRdmWrmLock);
+ }
+ break;
- Adapter->bAllDSDWriteAllow = TRUE ;
-
- Adapter->ulFlashCalStart = SectOfset ;
- Adapter->eActiveDSD = eFlash2xSectionVal;
- }
- Status = STATUS_SUCCESS ;
- break;
-
- case IOCTL_BCM_NVM_RAW_READ :
- {
-
- NVM_READWRITE stNVMRead;
- INT NOB ;
- INT BuffSize ;
- INT ReadOffset = 0;
- UINT ReadBytes = 0 ;
- PUCHAR pReadBuff;
- void __user *OutPutBuff;
-
- if(Adapter->eNVMType != NVM_FLASH)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"NVM TYPE is not Flash ");
- return -EINVAL ;
- }
+ case IOCTL_BCM_GET_FLASH_CS_INFO: {
+ Status = STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called");
- /* Copy Ioctl Buffer structure */
- if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
- Status = -EFAULT;
- break;
- }
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ break;
+ }
- if(copy_from_user(&stNVMRead, IoBuffer.OutputBuffer,sizeof(NVM_READWRITE)))
- return -EFAULT;
+ if (Adapter->eNVMType != NVM_FLASH) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Connected device does not have flash");
+ Status = -EINVAL;
+ break;
+ }
- NOB = stNVMRead.uiNumBytes;
- //In Raw-Read max Buff size : 64MB
+ if (IsFlash2x(Adapter) == TRUE) {
+ if (IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO))
+ return -EINVAL;
- if(NOB > DEFAULT_BUFF_SIZE)
- BuffSize = DEFAULT_BUFF_SIZE;
- else
- BuffSize = NOB ;
+ if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO)))
+ return -EFAULT;
+ } else {
+ if (IoBuffer.OutputLength < sizeof(FLASH_CS_INFO))
+ return -EINVAL;
- ReadOffset = stNVMRead.uiOffset;
- OutPutBuff = stNVMRead.pBuffer;
+ if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO)))
+ return -EFAULT;
+ }
+ }
+ break;
- pReadBuff = kzalloc(BuffSize , GFP_KERNEL);
- if(pReadBuff == NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure");
- Status = -ENOMEM;
- break;
- }
- down(&Adapter->NVMRdmWrmLock);
-
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n");
- kfree(pReadBuff);
- up(&Adapter->NVMRdmWrmLock);
- return -EACCES;
- }
+ case IOCTL_BCM_SELECT_DSD: {
+ UINT SectOfset = 0;
+ FLASH2X_SECTION_VAL eFlash2xSectionVal;
+ eFlash2xSectionVal = NO_SECTION_VAL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SELECT_DSD Called");
- Adapter->bFlashRawRead = TRUE ;
- while(NOB)
- {
- if(NOB > DEFAULT_BUFF_SIZE )
- ReadBytes = DEFAULT_BUFF_SIZE;
- else
- ReadBytes = NOB;
-
- //Reading the data from Flash 2.x
- Status = BeceemNVMRead(Adapter,(PUINT)pReadBuff,ReadOffset,ReadBytes);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status);
- break;
- }
+ if (IsFlash2x(Adapter) != TRUE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
+ return -EINVAL;
+ }
- BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff,ReadBytes);
-
- Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to use failed with status :%d", Status);
- break;
- }
- NOB = NOB - ReadBytes;
- if(NOB)
- {
- ReadOffset = ReadOffset + ReadBytes ;
- OutPutBuff = OutPutBuff + ReadBytes ;
- }
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
+ return Status;
+ }
+ Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
+ return Status;
+ }
- }
- Adapter->bFlashRawRead = FALSE ;
- up(&Adapter->NVMRdmWrmLock);
- kfree(pReadBuff);
- break ;
- }
-
- case IOCTL_BCM_CNTRLMSG_MASK:
- {
- ULONG RxCntrlMsgBitMask = 0 ;
-
- /* Copy Ioctl Buffer structure */
- Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of Ioctl buffer is failed from user space");
- Status = -EFAULT;
- break;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read Section :%d", eFlash2xSectionVal);
+ if ((eFlash2xSectionVal != DSD0) &&
+ (eFlash2xSectionVal != DSD1) &&
+ (eFlash2xSectionVal != DSD2)) {
- if (IoBuffer.InputLength != sizeof(unsigned long)) {
- Status = -EINVAL;
- break;
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Passed section<%x> is not DSD section", eFlash2xSectionVal);
+ return STATUS_FAILURE;
+ }
- Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength);
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of control bit mask failed from user space");
- Status = -EFAULT;
- break;
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
- pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask ;
- }
- break;
- case IOCTL_BCM_GET_DEVICE_DRIVER_INFO:
- {
- DEVICE_DRIVER_INFO DevInfo;
-
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
-
- DevInfo.MaxRDMBufferSize = BUFFER_4K;
- DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
- DevInfo.u32RxAlignmentCorrection = 0;
- DevInfo.u32NVMType = Adapter->eNVMType;
- DevInfo.u32InterfaceType = BCM_USB;
-
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ SectOfset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);
+ if (SectOfset == INVALID_OFFSET) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal);
+ return -EINVAL;
+ }
- if(IoBuffer.OutputLength < sizeof(DevInfo))
- return -EINVAL;
+ Adapter->bAllDSDWriteAllow = TRUE;
+ Adapter->ulFlashCalStart = SectOfset;
+ Adapter->eActiveDSD = eFlash2xSectionVal;
+ }
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IOCTL_BCM_NVM_RAW_READ: {
+ NVM_READWRITE stNVMRead;
+ INT NOB ;
+ INT BuffSize ;
+ INT ReadOffset = 0;
+ UINT ReadBytes = 0 ;
+ PUCHAR pReadBuff;
+ void __user *OutPutBuff;
+
+ if (Adapter->eNVMType != NVM_FLASH) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NVM TYPE is not Flash");
+ return -EINVAL;
+ }
- if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo)))
- return -EFAULT;
- }
- break ;
+ /* Copy Ioctl Buffer structure */
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
+ Status = -EFAULT;
+ break;
+ }
- case IOCTL_BCM_TIME_SINCE_NET_ENTRY:
- {
- ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0};
+ if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(NVM_READWRITE)))
+ return -EFAULT;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
+ NOB = stNVMRead.uiNumBytes;
+ /* In Raw-Read max Buff size : 64MB */
- if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
- return -EFAULT;
+ if (NOB > DEFAULT_BUFF_SIZE)
+ BuffSize = DEFAULT_BUFF_SIZE;
+ else
+ BuffSize = NOB;
- if(IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED))
- return -EINVAL;
+ ReadOffset = stNVMRead.uiOffset;
+ OutPutBuff = stNVMRead.pBuffer;
- stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry;
+ pReadBuff = kzalloc(BuffSize , GFP_KERNEL);
+ if (pReadBuff == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure");
+ Status = -ENOMEM;
+ break;
+ }
+ down(&Adapter->NVMRdmWrmLock);
- if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED)))
- return -EFAULT;
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
+ kfree(pReadBuff);
+ up(&Adapter->NVMRdmWrmLock);
+ return -EACCES;
+ }
+
+ Adapter->bFlashRawRead = TRUE;
+
+ while (NOB) {
+ if (NOB > DEFAULT_BUFF_SIZE)
+ ReadBytes = DEFAULT_BUFF_SIZE;
+ else
+ ReadBytes = NOB;
+
+ /* Reading the data from Flash 2.x */
+ Status = BeceemNVMRead(Adapter, (PUINT)pReadBuff, ReadOffset, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status);
+ break;
}
+
+ BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes);
+
+ Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to use failed with status :%d", Status);
+ break;
+ }
+ NOB = NOB - ReadBytes;
+ if (NOB) {
+ ReadOffset = ReadOffset + ReadBytes;
+ OutPutBuff = OutPutBuff + ReadBytes;
+ }
+ }
+ Adapter->bFlashRawRead = FALSE;
+ up(&Adapter->NVMRdmWrmLock);
+ kfree(pReadBuff);
+ break;
+ }
+
+ case IOCTL_BCM_CNTRLMSG_MASK: {
+ ULONG RxCntrlMsgBitMask = 0;
+
+ /* Copy Ioctl Buffer structure */
+ Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of Ioctl buffer is failed from user space");
+ Status = -EFAULT;
break;
+ }
- case IOCTL_CLOSE_NOTIFICATION:
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_CLOSE_NOTIFICATION");
+ if (IoBuffer.InputLength != sizeof(unsigned long)) {
+ Status = -EINVAL;
break;
+ }
- default:
- pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd);
- Status = STATUS_FAILURE;
+ Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength);
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of control bit mask failed from user space");
+ Status = -EFAULT;
break;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
+ pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask;
+ }
+ break;
+
+ case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: {
+ DEVICE_DRIVER_INFO DevInfo;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
+
+ DevInfo.MaxRDMBufferSize = BUFFER_4K;
+ DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
+ DevInfo.u32RxAlignmentCorrection = 0;
+ DevInfo.u32NVMType = Adapter->eNVMType;
+ DevInfo.u32InterfaceType = BCM_USB;
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength < sizeof(DevInfo))
+ return -EINVAL;
+
+ if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo)))
+ return -EFAULT;
+ }
+ break;
+
+ case IOCTL_BCM_TIME_SINCE_NET_ENTRY: {
+ ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0};
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
+
+ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+ return -EFAULT;
+
+ if (IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED))
+ return -EINVAL;
+
+ stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry;
+
+ if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED)))
+ return -EFAULT;
+ }
+ break;
+
+ case IOCTL_CLOSE_NOTIFICATION:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_CLOSE_NOTIFICATION");
+ break;
+
+ default:
+ pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd);
+ Status = STATUS_FAILURE;
+ break;
}
return Status;
}
@@ -2107,8 +1989,6 @@ static const struct file_operations bcm_fops = {
.llseek = no_llseek,
};
-extern struct class *bcm_class;
-
int register_control_device_interface(PMINI_ADAPTER Adapter)
{
@@ -2122,8 +2002,8 @@ int register_control_device_interface(PMINI_ADAPTER Adapter)
}
Adapter->pstCreatedClassDevice = device_create(bcm_class, NULL,
- MKDEV(Adapter->major, 0),
- Adapter, DEV_NAME);
+ MKDEV(Adapter->major, 0),
+ Adapter, DEV_NAME);
if (IS_ERR(Adapter->pstCreatedClassDevice)) {
pr_err(DRV_NAME ": class device create failed\n");
@@ -2141,3 +2021,4 @@ void unregister_control_device_interface(PMINI_ADAPTER Adapter)
unregister_chrdev(Adapter->major, DEV_NAME);
}
}
+
diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c
index df64acb06126..bcd86bbef2fd 100644
--- a/drivers/staging/bcm/InterfaceDld.c
+++ b/drivers/staging/bcm/InterfaceDld.c
@@ -1,204 +1,183 @@
#include "headers.h"
-
-int InterfaceFileDownload( PVOID arg,
- struct file *flp,
- unsigned int on_chip_loc)
+int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
{
- // unsigned int reg=0;
- mm_segment_t oldfs={0};
- int errno=0, len=0 /*,is_config_file = 0*/;
- loff_t pos=0;
+ /* unsigned int reg = 0; */
+ mm_segment_t oldfs = {0};
+ int errno = 0, len = 0; /* ,is_config_file = 0 */
+ loff_t pos = 0;
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
- //PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter;
- char *buff=kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
-
- if(!buff)
- {
- return -ENOMEM;
- }
- while(1)
- {
- oldfs=get_fs(); set_fs(get_ds());
- len=vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
- set_fs(oldfs);
- if(len<=0)
- {
- if(len<0)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
- errno=len;
- }
- else
- {
- errno = 0;
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
- }
- break;
- }
- //BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, buff, MAX_TRANSFER_CTRL_BYTE_USB);
- errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len) ;
- if(errno)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed! status: %d", errno);
- break;
+ /* PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; */
+ char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
+
+ if (!buff)
+ return -ENOMEM;
+ while (1) {
+ oldfs = get_fs();
+ set_fs(get_ds());
+ len = vfs_read(flp, (void __force __user *)buff,
+ MAX_TRANSFER_CTRL_BYTE_USB, &pos);
+ set_fs(oldfs);
+ if (len <= 0) {
+ if (len < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, MP_INIT,
+ DBG_LVL_ALL, "len < 0");
+ errno = len;
+ } else {
+ errno = 0;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, MP_INIT,
+ DBG_LVL_ALL,
+ "Got end of file!");
+ }
+ break;
}
- on_chip_loc+=MAX_TRANSFER_CTRL_BYTE_USB;
- }/* End of for(;;)*/
+ /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT,
+ * DBG_LVL_ALL, buff,
+ * MAX_TRANSFER_CTRL_BYTE_USB);
+ */
+ errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len);
+ if (errno) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_PRINTK, 0, 0,
+ "WRM Failed! status: %d", errno);
+ break;
+ }
+ on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
+ }
kfree(buff);
- return errno;
+ return errno;
}
-int InterfaceFileReadbackFromChip( PVOID arg,
- struct file *flp,
- unsigned int on_chip_loc)
+int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_chip_loc)
{
- char *buff, *buff_readback;
- unsigned int reg=0;
- mm_segment_t oldfs={0};
- int errno=0, len=0, is_config_file = 0;
- loff_t pos=0;
- static int fw_down = 0;
- INT Status = STATUS_SUCCESS;
+ char *buff, *buff_readback;
+ unsigned int reg = 0;
+ mm_segment_t oldfs = {0};
+ int errno = 0, len = 0, is_config_file = 0;
+ loff_t pos = 0;
+ static int fw_down;
+ INT Status = STATUS_SUCCESS;
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
- buff=kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
- buff_readback=kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
- if(!buff || !buff_readback)
- {
- kfree(buff);
- kfree(buff_readback);
+ buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
+ buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
+ if (!buff || !buff_readback) {
+ kfree(buff);
+ kfree(buff_readback);
- return -ENOMEM;
- }
+ return -ENOMEM;
+ }
- is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR)? 1:0;
+ is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0;
memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB);
memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB);
- while(1)
- {
- oldfs=get_fs(); set_fs(get_ds());
- len=vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
- set_fs(oldfs);
- fw_down++;
- if(len<=0)
- {
- if(len<0)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
- errno=len;
- }
- else
- {
- errno = 0;
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
- }
- break;
- }
-
+ while (1) {
+ oldfs = get_fs();
+ set_fs(get_ds());
+ len = vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
+ set_fs(oldfs);
+ fw_down++;
+
+ if (len <= 0) {
+ if (len < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
+ errno = len;
+ } else {
+ errno = 0;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
+ }
+ break;
+ }
Status = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len);
- if(Status)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg);
+ if (Status) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg);
goto exit;
}
reg++;
- if((len-sizeof(unsigned int))<4)
- {
- if(memcmp(buff_readback, buff, len))
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT,DBG_LVL_ALL,"Length is: %d",len);
+ if ((len-sizeof(unsigned int)) < 4) {
+ if (memcmp(buff_readback, buff, len)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Length is: %d", len);
Status = -EIO;
goto exit;
- }
- }
- else
- {
- len-=4;
- while(len)
- {
- if(*(unsigned int*)&buff_readback[len] != *(unsigned int *)&buff[len])
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]);
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
+ }
+ } else {
+ len -= 4;
+
+ while (len) {
+ if (*(unsigned int *)&buff_readback[len] != *(unsigned int *)&buff[len]) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
Status = -EIO;
goto exit;
- }
- len-=4;
- }
- }
- on_chip_loc+=MAX_TRANSFER_CTRL_BYTE_USB;
- }/* End of while(1)*/
+ }
+ len -= 4;
+ }
+ }
+ on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
+ } /* End of while(1) */
+
exit:
- kfree(buff);
- kfree(buff_readback);
+ kfree(buff);
+ kfree(buff_readback);
return Status;
}
-static int bcm_download_config_file(PMINI_ADAPTER Adapter,
- FIRMWARE_INFO *psFwInfo)
+static int bcm_download_config_file(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
{
int retval = STATUS_SUCCESS;
B_UINT32 value = 0;
- if(Adapter->pstargetparams == NULL)
- {
- if((Adapter->pstargetparams =
- kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL)) == NULL)
- {
- return -ENOMEM;
- }
- }
- if(psFwInfo->u32FirmwareLength != sizeof(STARGETPARAMS))
- {
- return -EIO;
+ if (Adapter->pstargetparams == NULL) {
+ Adapter->pstargetparams = kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL);
+ if (Adapter->pstargetparams == NULL)
+ return -ENOMEM;
}
- retval = copy_from_user(Adapter->pstargetparams,
- psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
- if(retval)
- {
+
+ if (psFwInfo->u32FirmwareLength != sizeof(STARGETPARAMS))
+ return -EIO;
+
+ retval = copy_from_user(Adapter->pstargetparams, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
+ if (retval) {
kfree(Adapter->pstargetparams);
Adapter->pstargetparams = NULL;
return -EFAULT;
}
+
/* Parse the structure and then Download the Firmware */
beceem_parse_target_struct(Adapter);
- //Initializing the NVM.
+ /* Initializing the NVM. */
BcmInitNVM(Adapter);
+ retval = InitLedSettings(Adapter);
- retval = InitLedSettings (Adapter);
-
- if(retval)
- {
- BCM_DEBUG_PRINT (Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n");
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n");
return retval;
}
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
Adapter->LEDInfo.bLedInitDone = FALSE;
Adapter->DriverState = DRIVER_INIT;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
Adapter->DriverState = FW_DOWNLOAD;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
/* Initialize the DDR Controller */
retval = ddr_init(Adapter);
- if(retval)
- {
- BCM_DEBUG_PRINT (Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n");
+ if (retval) {
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n");
return retval;
}
@@ -206,197 +185,166 @@ static int bcm_download_config_file(PMINI_ADAPTER Adapter,
wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
- if(Adapter->eNVMType == NVM_FLASH)
- {
+ if (Adapter->eNVMType == NVM_FLASH) {
retval = PropagateCalParamsFromFlashToMemory(Adapter);
- if(retval)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"propagaion of cal param failed with status :%d", retval);
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "propagaion of cal param failed with status :%d", retval);
return retval;
}
}
+ retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams, sizeof(STARGETPARAMS), CONFIG_BEGIN_ADDR);
- retval =buffDnldVerify(Adapter,(PUCHAR)Adapter->pstargetparams,sizeof(STARGETPARAMS),CONFIG_BEGIN_ADDR);
-
- if(retval)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly");
- }
+ if (retval)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly");
else
Adapter->bCfgDownloaded = TRUE;
-
return retval;
}
-static int bcm_compare_buff_contents(unsigned char *readbackbuff,
- unsigned char *buff,unsigned int len)
+
+static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char *buff, unsigned int len)
{
int retval = STATUS_SUCCESS;
- PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
- if((len-sizeof(unsigned int))<4)
- {
- if(memcmp(readbackbuff , buff, len))
- {
- retval=-EINVAL;
- }
- }
- else
- {
- len-=4;
- while(len)
- {
- if(*(unsigned int*)&readbackbuff[len] !=
- *(unsigned int *)&buff[len])
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper");
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
- retval=-EINVAL;
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ if ((len-sizeof(unsigned int)) < 4) {
+ if (memcmp(readbackbuff , buff, len))
+ retval = -EINVAL;
+ } else {
+ len -= 4;
+
+ while (len) {
+ if (*(unsigned int *)&readbackbuff[len] != *(unsigned int *)&buff[len]) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
+ retval = -EINVAL;
break;
}
- len-=4;
+ len -= 4;
}
}
return retval;
}
+
int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
{
int retval = STATUS_SUCCESS;
PUCHAR buff = NULL;
- /* Config File is needed for the Driver to download the Config file and
- Firmware. Check for the Config file to be first to be sent from the
- Application
- */
- atomic_set (&Adapter->uiMBupdate, FALSE);
- if(!Adapter->bCfgDownloaded &&
- psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR)
- {
- /*Can't Download Firmware.*/
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Download the config File first\n");
+ /* Config File is needed for the Driver to download the Config file and
+ * Firmware. Check for the Config file to be first to be sent from the
+ * Application
+ */
+ atomic_set(&Adapter->uiMBupdate, FALSE);
+ if (!Adapter->bCfgDownloaded && psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
+ /* Can't Download Firmware. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Download the config File first\n");
return -EINVAL;
}
/* If Config File, Finish the DDR Settings and then Download CFG File */
- if(psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
- {
- retval = bcm_download_config_file (Adapter, psFwInfo);
- }
- else
- {
-
- buff = kzalloc(psFwInfo->u32FirmwareLength,GFP_KERNEL);
- if(buff==NULL)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Failed in allocation memory");
+ if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) {
+ retval = bcm_download_config_file(Adapter, psFwInfo);
+ } else {
+ buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL);
+ if (buff == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed in allocation memory");
return -ENOMEM;
}
- retval = copy_from_user(buff,psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
- if(retval != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed");
+
+ retval = copy_from_user(buff, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
+ if (retval != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed");
retval = -EFAULT;
- goto error ;
+ goto error;
}
retval = buffDnldVerify(Adapter,
buff,
psFwInfo->u32FirmwareLength,
psFwInfo->u32StartingAddress);
- if(retval != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"f/w download failed status :%d", retval);
+
+ if (retval != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "f/w download failed status :%d", retval);
goto error;
}
}
+
error:
kfree(buff);
return retval;
}
-static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength,
- ULONG u32StartingAddress)
+static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
{
-
- unsigned int len = 0;
+ unsigned int len = 0;
int retval = STATUS_SUCCESS;
len = u32FirmwareLength;
- while(u32FirmwareLength)
- {
- len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
- retval = wrm (Adapter, u32StartingAddress, mappedbuffer, len);
- if(retval)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval);
+ while (u32FirmwareLength) {
+ len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
+ retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len);
+
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval);
break;
}
- u32StartingAddress += len;
- u32FirmwareLength -= len;
- mappedbuffer +=len;
+ u32StartingAddress += len;
+ u32FirmwareLength -= len;
+ mappedbuffer += len;
}
return retval;
-
}
-static INT buffRdbkVerify(PMINI_ADAPTER Adapter,
- PUCHAR mappedbuffer, UINT u32FirmwareLength,
- ULONG u32StartingAddress)
+static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
{
UINT len = u32FirmwareLength;
INT retval = STATUS_SUCCESS;
- PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB,GFP_KERNEL);
+ PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
- if(NULL == readbackbuff)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED");
+ if (NULL == readbackbuff) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED");
return -ENOMEM;
}
- while (u32FirmwareLength && !retval)
- {
- len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
+ while (u32FirmwareLength && !retval) {
+ len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
+ retval = rdm(Adapter, u32StartingAddress, readbackbuff, len);
- retval = rdm (Adapter, u32StartingAddress, readbackbuff, len);
- if(retval)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d" ,retval);
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval);
break;
}
- if (STATUS_SUCCESS != (retval = bcm_compare_buff_contents (readbackbuff, mappedbuffer, len)))
- {
+ retval = bcm_compare_buff_contents(readbackbuff, mappedbuffer, len);
+ if (STATUS_SUCCESS != retval)
break;
- }
- u32StartingAddress += len;
- u32FirmwareLength -= len;
- mappedbuffer +=len;
- }/* end of while (u32FirmwareLength && !retval) */
+
+ u32StartingAddress += len;
+ u32FirmwareLength -= len;
+ mappedbuffer += len;
+
+ } /* end of while (u32FirmwareLength && !retval) */
kfree(readbackbuff);
return retval;
}
-INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength,
- unsigned long u32StartingAddress)
+INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, unsigned long u32StartingAddress)
{
INT status = STATUS_SUCCESS;
- status = buffDnld(Adapter,mappedbuffer,u32FirmwareLength,u32StartingAddress);
- if(status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Buffer download failed");
+ status = buffDnld(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer download failed");
goto error;
}
- status= buffRdbkVerify(Adapter,mappedbuffer,u32FirmwareLength,u32StartingAddress);
- if(status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Buffer readback verifier failed");
+ status = buffRdbkVerify(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer readback verifier failed");
goto error;
}
error:
return status;
}
-
-
diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
index d78d5ef1f298..a09d35108f04 100644
--- a/drivers/staging/bcm/InterfaceInit.c
+++ b/drivers/staging/bcm/InterfaceInit.c
@@ -139,8 +139,7 @@ static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter)
BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1C2, 4, TRUE);
}
-static int
-usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
int retval;
@@ -281,8 +280,9 @@ static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
int i = 0;
for (i = 0; i < MAXIMUM_USB_TCB; i++) {
- if ((psIntfAdapter->asUsbTcb[i].urb =
- usb_alloc_urb(0, GFP_KERNEL)) == NULL) {
+ psIntfAdapter->asUsbTcb[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (psIntfAdapter->asUsbTcb[i].urb == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
"Can't allocate Tx urb for index %d\n", i);
return -ENOMEM;
@@ -290,14 +290,17 @@ static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
}
for (i = 0; i < MAXIMUM_USB_RCB; i++) {
- if ((psIntfAdapter->asUsbRcb[i].urb =
- usb_alloc_urb(0, GFP_KERNEL)) == NULL) {
+ psIntfAdapter->asUsbRcb[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (psIntfAdapter->asUsbRcb[i].urb == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
"Can't allocate Rx urb for index %d\n", i);
return -ENOMEM;
}
- if ((psIntfAdapter->asUsbRcb[i].urb->transfer_buffer =
- kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL)) == NULL) {
+
+ psIntfAdapter->asUsbRcb[i].urb->transfer_buffer = kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL);
+
+ if (psIntfAdapter->asUsbRcb[i].urb->transfer_buffer == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
"Can't allocate Rx buffer for index %d\n", i);
return -ENOMEM;
@@ -389,32 +392,32 @@ static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descripto
static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd));
+ return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd);
}
static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd));
+ return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd);
}
static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd));
+ return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd);
}
static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd));
+ return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd);
}
static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd));
+ return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd);
}
static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
{
- return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd));
+ return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd);
}
static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
@@ -462,7 +465,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
if (bBcm16 == TRUE) {
/* selecting alternate setting one as a default setting for High Speed modem. */
if (psIntfAdapter->bHighSpeedDevice)
- retval= usb_set_interface(psIntfAdapter->udev, DEFAULT_SETTING_0, ALTERNATE_SETTING_1);
+ retval = usb_set_interface(psIntfAdapter->udev, DEFAULT_SETTING_0, ALTERNATE_SETTING_1);
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
"BCM16 is applicable on this dongle\n");
if (retval || (psIntfAdapter->bHighSpeedDevice == FALSE)) {
@@ -497,7 +500,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
if ((psIntfAdapter->bHighSpeedDevice == FALSE) && bcm_usb_endpoint_is_bulk_out(endpoint)) {
/* Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. */
UINT _uiData = ntohl(EP2_CFG_INT);
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
"Reverting Bulk to INT as it is in Full Speed mode.\n");
BeceemEEPROMBulkWrite(psIntfAdapter->psAdapter, (PUCHAR)&_uiData, 0x136, 4, TRUE);
}
@@ -579,7 +582,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
psIntfAdapter->sIntrOut.int_out_size = buffer_size;
psIntfAdapter->sIntrOut.int_out_endpointAddr = endpoint->bEndpointAddress;
psIntfAdapter->sIntrOut.int_out_interval = endpoint->bInterval;
- psIntfAdapter->sIntrOut.int_out_buffer= kmalloc(buffer_size, GFP_KERNEL);
+ psIntfAdapter->sIntrOut.int_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!psIntfAdapter->sIntrOut.int_out_buffer) {
dev_err(&psIntfAdapter->udev->dev,
"could not allocate interrupt_out_buffer\n");
@@ -641,8 +644,8 @@ static int InterfaceSuspend(struct usb_interface *intf, pm_message_t message)
static int InterfaceResume(struct usb_interface *intf)
{
PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf);
- mdelay(100);
+ mdelay(100);
psIntfAdapter->bSuspended = FALSE;
StartInterruptUrb(psIntfAdapter);
diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c
index a51185b522cf..61f878b4f56c 100644
--- a/drivers/staging/bcm/InterfaceMisc.c
+++ b/drivers/staging/bcm/InterfaceMisc.c
@@ -1,246 +1,219 @@
#include "headers.h"
-INT
-InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
- UINT addr,
- PVOID buff,
- INT len)
+INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
+ UINT addr,
+ PVOID buff,
+ INT len)
{
int retval = 0;
- USHORT usRetries = 0 ;
- if(psIntfAdapter == NULL )
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Interface Adapter is NULL");
- return -EINVAL ;
+ USHORT usRetries = 0;
+
+ if (psIntfAdapter == NULL) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
+ return -EINVAL;
}
- if(psIntfAdapter->psAdapter->device_removed == TRUE)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed");
+ if (psIntfAdapter->psAdapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
return -ENODEV;
}
- if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB))
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus");
+ if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus");
return -EACCES;
}
- if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed..");
+ if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
return -EACCES;
}
- psIntfAdapter->psAdapter->DeviceAccess = TRUE ;
+ psIntfAdapter->psAdapter->DeviceAccess = TRUE;
+
do {
retval = usb_control_msg(psIntfAdapter->udev,
- usb_rcvctrlpipe(psIntfAdapter->udev,0),
- 0x02,
- 0xC2,
- (addr & 0xFFFF),
- ((addr >> 16) & 0xFFFF),
- buff,
- len,
- 5000);
-
- usRetries++ ;
- if(-ENODEV == retval)
- {
- psIntfAdapter->psAdapter->device_removed =TRUE;
+ usb_rcvctrlpipe(psIntfAdapter->udev, 0),
+ 0x02,
+ 0xC2,
+ (addr & 0xFFFF),
+ ((addr >> 16) & 0xFFFF),
+ buff,
+ len,
+ 5000);
+
+ usRetries++;
+ if (-ENODEV == retval) {
+ psIntfAdapter->psAdapter->device_removed = TRUE;
break;
}
- }while((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES ) );
+ } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
- if(retval < 0)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval,usRetries);
- psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
- return retval;
- }
- else
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval);
- psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
- return STATUS_SUCCESS;
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval, usRetries);
+ psIntfAdapter->psAdapter->DeviceAccess = FALSE;
+ return retval;
+ } else {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval);
+ psIntfAdapter->psAdapter->DeviceAccess = FALSE;
+ return STATUS_SUCCESS;
}
}
-INT
-InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
- UINT addr,
- PVOID buff,
- INT len)
+INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
+ UINT addr,
+ PVOID buff,
+ INT len)
{
int retval = 0;
- USHORT usRetries = 0 ;
+ USHORT usRetries = 0;
- if(psIntfAdapter == NULL )
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
+ if (psIntfAdapter == NULL) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
return -EINVAL;
}
- if(psIntfAdapter->psAdapter->device_removed == TRUE)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed");
+ if (psIntfAdapter->psAdapter->device_removed == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
return -ENODEV;
}
- if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB))
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus...");
+ if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus...");
return -EACCES;
}
- if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed..");
+ if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
return -EACCES;
}
- psIntfAdapter->psAdapter->DeviceAccess = TRUE ;
- do{
+
+ psIntfAdapter->psAdapter->DeviceAccess = TRUE;
+
+ do {
retval = usb_control_msg(psIntfAdapter->udev,
- usb_sndctrlpipe(psIntfAdapter->udev,0),
- 0x01,
- 0x42,
- (addr & 0xFFFF),
- ((addr >> 16) & 0xFFFF),
- buff,
- len,
- 5000);
-
- usRetries++ ;
- if(-ENODEV == retval)
- {
- psIntfAdapter->psAdapter->device_removed = TRUE ;
+ usb_sndctrlpipe(psIntfAdapter->udev, 0),
+ 0x01,
+ 0x42,
+ (addr & 0xFFFF),
+ ((addr >> 16) & 0xFFFF),
+ buff,
+ len,
+ 5000);
+
+ usRetries++;
+ if (-ENODEV == retval) {
+ psIntfAdapter->psAdapter->device_removed = TRUE;
break;
}
- }while((retval < 0) && ( usRetries < MAX_RDM_WRM_RETIRES));
+ } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
- if(retval < 0)
- {
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries);
- psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries);
+ psIntfAdapter->psAdapter->DeviceAccess = FALSE;
return retval;
- }
- else
- {
- psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
- BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval);
+ } else {
+ psIntfAdapter->psAdapter->DeviceAccess = FALSE;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval);
return STATUS_SUCCESS;
-
}
-
}
-INT
-BcmRDM(PVOID arg,
- UINT addr,
- PVOID buff,
- INT len)
+INT BcmRDM(PVOID arg,
+ UINT addr,
+ PVOID buff,
+ INT len)
{
return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
}
-INT
-BcmWRM(PVOID arg,
- UINT addr,
- PVOID buff,
- INT len)
+INT BcmWRM(PVOID arg,
+ UINT addr,
+ PVOID buff,
+ INT len)
{
return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
}
-
-
INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter)
{
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter);
- INT status = STATUS_SUCCESS ;
+ INT status = STATUS_SUCCESS;
/*
- usb_clear_halt - tells device to clear endpoint halt/stall condition
- @dev: device whose endpoint is halted
- @pipe: endpoint "pipe" being cleared
- @ Context: !in_interrupt ()
-
- usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code.
- This is used to clear halt conditions for bulk and interrupt endpoints only.
- Control and isochronous endpoints never halts.
-
- Any URBs queued for such an endpoint should normally be unlinked by the driver
- before clearing the halt condition.
-
- */
-
- //Killing all the submitted urbs to different end points.
+ * usb_clear_halt - tells device to clear endpoint halt/stall condition
+ * @dev: device whose endpoint is halted
+ * @pipe: endpoint "pipe" being cleared
+ * @ Context: !in_interrupt ()
+ *
+ * usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code.
+ * This is used to clear halt conditions for bulk and interrupt endpoints only.
+ * Control and isochronous endpoints never halts.
+ *
+ * Any URBs queued for such an endpoint should normally be unlinked by the driver
+ * before clearing the halt condition.
+ *
+ */
+
+ /* Killing all the submitted urbs to different end points. */
Bcm_kill_all_URBs(psIntfAdapter);
+ /* clear the halted/stalled state for every end point */
+ status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sIntrIn.int_in_pipe);
+ if (status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status);
- //clear the halted/stalled state for every end point
- status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sIntrIn.int_in_pipe);
- if(status != STATUS_SUCCESS)
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status);
+ status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_pipe);
+ if (status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status);
- status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkIn.bulk_in_pipe);
- if(status != STATUS_SUCCESS)
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status);
+ status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkOut.bulk_out_pipe);
+ if (status != STATUS_SUCCESS)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status);
- status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkOut.bulk_out_pipe);
- if(status != STATUS_SUCCESS)
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status);
-
- return status ;
+ return status;
}
-
VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
{
struct urb *tempUrb = NULL;
UINT i;
- /**
- * usb_kill_urb - cancel a transfer request and wait for it to finish
- * @urb: pointer to URB describing a previously submitted request,
- * returns nothing as it is void returned API.
- *
- * This routine cancels an in-progress request. It is guaranteed that
- * upon return all completion handlers will have finished and the URB
- * will be totally idle and available for reuse
-
- * This routine may not be used in an interrupt context (such as a bottom
- * half or a completion handler), or when holding a spinlock, or in other
- * situations where the caller can't schedule().
- *
- **/
+ /*
+ * usb_kill_urb - cancel a transfer request and wait for it to finish
+ * @urb: pointer to URB describing a previously submitted request,
+ * returns nothing as it is void returned API.
+ *
+ * This routine cancels an in-progress request. It is guaranteed that
+ * upon return all completion handlers will have finished and the URB
+ * will be totally idle and available for reuse
+ *
+ * This routine may not be used in an interrupt context (such as a bottom
+ * half or a completion handler), or when holding a spinlock, or in other
+ * situations where the caller can't schedule().
+ *
+ */
/* Cancel submitted Interrupt-URB's */
- if(psIntfAdapter->psInterruptUrb != NULL)
- {
- if(psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
- usb_kill_urb(psIntfAdapter->psInterruptUrb);
+ if (psIntfAdapter->psInterruptUrb != NULL) {
+ if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
+ usb_kill_urb(psIntfAdapter->psInterruptUrb);
}
/* Cancel All submitted TX URB's */
- for(i = 0; i < MAXIMUM_USB_TCB; i++)
- {
+ for (i = 0; i < MAXIMUM_USB_TCB; i++) {
tempUrb = psIntfAdapter->asUsbTcb[i].urb;
- if(tempUrb)
- {
- if(tempUrb->status == -EINPROGRESS)
+ if (tempUrb) {
+ if (tempUrb->status == -EINPROGRESS)
usb_kill_urb(tempUrb);
}
}
- for(i = 0; i < MAXIMUM_USB_RCB; i++)
- {
+ for (i = 0; i < MAXIMUM_USB_RCB; i++) {
tempUrb = psIntfAdapter->asUsbRcb[i].urb;
- if(tempUrb)
- {
- if(tempUrb->status == -EINPROGRESS)
- usb_kill_urb(tempUrb);
+ if (tempUrb) {
+ if (tempUrb->status == -EINPROGRESS)
+ usb_kill_urb(tempUrb);
}
}
@@ -253,13 +226,12 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
VOID putUsbSuspend(struct work_struct *work)
{
- PS_INTERFACE_ADAPTER psIntfAdapter = NULL ;
- struct usb_interface *intf = NULL ;
- psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER,usbSuspendWork);
- intf=psIntfAdapter->interface ;
+ PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
+ struct usb_interface *intf = NULL;
+ psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER, usbSuspendWork);
+ intf = psIntfAdapter->interface;
- if(psIntfAdapter->bSuspended == FALSE)
+ if (psIntfAdapter->bSuspended == FALSE)
usb_autopm_put_interface(intf);
-
}
diff --git a/drivers/staging/bcm/Macros.h b/drivers/staging/bcm/Macros.h
index 916bebb7ed50..46ed99c53764 100644
--- a/drivers/staging/bcm/Macros.h
+++ b/drivers/staging/bcm/Macros.h
@@ -1,17 +1,17 @@
/*************************************
-* Macros.h
+* Macros.h
**************************************/
-#ifndef __MACROS_H__
+#ifndef __MACROS_H__
#define __MACROS_H__
-#define TX_TIMER_PERIOD 10 //10 msec
+#define TX_TIMER_PERIOD 10 /*10 msec*/
#define MAX_CLASSIFIERS 100
-//#define MAX_CLASSIFIERS_PER_SF 20
+/* #define MAX_CLASSIFIERS_PER_SF 20 */
#define MAX_TARGET_DSX_BUFFERS 24
-#define MAX_CNTRL_PKTS 100
-#define MAX_DATA_PKTS 200
-#define MAX_ETH_SIZE 1536
+#define MAX_CNTRL_PKTS 100
+#define MAX_DATA_PKTS 200
+#define MAX_ETH_SIZE 1536
#define MAX_CNTL_PKT_SIZE 2048
#define MTU_SIZE 1400
@@ -20,102 +20,102 @@
#define MAC_ADDR_REGISTER 0xbf60d000
-///////////Quality of Service///////////////////////////
-#define NO_OF_QUEUES 17
-#define HiPriority NO_OF_QUEUES-1
-#define LowPriority 0
-#define BE 2
-#define rtPS 4
-#define ERTPS 5
-#define UGS 6
-
-#define BE_BUCKET_SIZE 1024*1024*100 //32kb
-#define rtPS_BUCKET_SIZE 1024*1024*100 //8kb
-#define MAX_ALLOWED_RATE 1024*1024*100
-#define TX_PACKET_THRESHOLD 10
-#define XSECONDS 1*HZ
-#define DSC_ACTIVATE_REQUEST 248
-#define QUEUE_DEPTH_OFFSET 0x1fc01000
-#define MAX_DEVICE_DESC_SIZE 2040
-#define MAX_CTRL_QUEUE_LEN 100
-#define MAX_APP_QUEUE_LEN 200
-#define MAX_LATENCY_ALLOWED 0xFFFFFFFF
-#define DEFAULT_UG_INTERVAL 250
-#define DEFAULT_UGI_FACTOR 4
-
-#define DEFAULT_PERSFCOUNT 60
-#define MAX_CONNECTIONS 10
-#define MAX_CLASS_NAME_LENGTH 32
-
-#define ETH_LENGTH_OF_ADDRESS 6
-#define MAX_MULTICAST_ADDRESSES 32
-#define IP_LENGTH_OF_ADDRESS 4
-
-#define IP_PACKET_ONLY_MODE 0
-#define ETH_PACKET_TUNNELING_MODE 1
-
-////////////Link Request//////////////
-#define SET_MAC_ADDRESS_REQUEST 0
-#define SYNC_UP_REQUEST 1
-#define SYNCED_UP 2
-#define LINK_UP_REQUEST 3
-#define LINK_CONNECTED 4
-#define SYNC_UP_NOTIFICATION 2
-#define LINK_UP_NOTIFICATION 4
+/* Quality of Service */
+#define NO_OF_QUEUES 17
+#define HiPriority (NO_OF_QUEUES-1)
+#define LowPriority 0
+#define BE 2
+#define rtPS 4
+#define ERTPS 5
+#define UGS 6
+
+#define BE_BUCKET_SIZE (1024*1024*100) /* 32kb */
+#define rtPS_BUCKET_SIZE (1024*1024*100) /* 8kb */
+#define MAX_ALLOWED_RATE (1024*1024*100)
+#define TX_PACKET_THRESHOLD 10
+#define XSECONDS (1*HZ)
+#define DSC_ACTIVATE_REQUEST 248
+#define QUEUE_DEPTH_OFFSET 0x1fc01000
+#define MAX_DEVICE_DESC_SIZE 2040
+#define MAX_CTRL_QUEUE_LEN 100
+#define MAX_APP_QUEUE_LEN 200
+#define MAX_LATENCY_ALLOWED 0xFFFFFFFF
+#define DEFAULT_UG_INTERVAL 250
+#define DEFAULT_UGI_FACTOR 4
+
+#define DEFAULT_PERSFCOUNT 60
+#define MAX_CONNECTIONS 10
+#define MAX_CLASS_NAME_LENGTH 32
+
+#define ETH_LENGTH_OF_ADDRESS 6
+#define MAX_MULTICAST_ADDRESSES 32
+#define IP_LENGTH_OF_ADDRESS 4
+
+#define IP_PACKET_ONLY_MODE 0
+#define ETH_PACKET_TUNNELING_MODE 1
+
+/* Link Request */
+#define SET_MAC_ADDRESS_REQUEST 0
+#define SYNC_UP_REQUEST 1
+#define SYNCED_UP 2
+#define LINK_UP_REQUEST 3
+#define LINK_CONNECTED 4
+#define SYNC_UP_NOTIFICATION 2
+#define LINK_UP_NOTIFICATION 4
#define LINK_NET_ENTRY 0x0002
-#define HMC_STATUS 0x0004
+#define HMC_STATUS 0x0004
#define LINK_UP_CONTROL_REQ 0x83
#define STATS_POINTER_REQ_STATUS 0x86
#define NETWORK_ENTRY_REQ_PAYLOAD 198
-#define LINK_DOWN_REQ_PAYLOAD 226
+#define LINK_DOWN_REQ_PAYLOAD 226
#define SYNC_UP_REQ_PAYLOAD 228
-#define STATISTICS_POINTER_REQ 237
+#define STATISTICS_POINTER_REQ 237
#define LINK_UP_REQ_PAYLOAD 245
#define LINK_UP_ACK 246
#define STATS_MSG_SIZE 4
#define INDEX_TO_DATA 4
-#define GO_TO_IDLE_MODE_PAYLOAD 210
-#define COME_UP_FROM_IDLE_MODE_PAYLOAD 211
-#define IDLE_MODE_SF_UPDATE_MSG 187
+#define GO_TO_IDLE_MODE_PAYLOAD 210
+#define COME_UP_FROM_IDLE_MODE_PAYLOAD 211
+#define IDLE_MODE_SF_UPDATE_MSG 187
-#define SKB_RESERVE_ETHERNET_HEADER 16
-#define SKB_RESERVE_PHS_BYTES 32
+#define SKB_RESERVE_ETHERNET_HEADER 16
+#define SKB_RESERVE_PHS_BYTES 32
-#define IP_PACKET_ONLY_MODE 0
-#define ETH_PACKET_TUNNELING_MODE 1
+#define IP_PACKET_ONLY_MODE 0
+#define ETH_PACKET_TUNNELING_MODE 1
-#define ETH_CS_802_3 1
-#define ETH_CS_802_1Q_VLAN 3
-#define IPV4_CS 1
-#define IPV6_CS 2
-#define ETH_CS_MASK 0x3f
+#define ETH_CS_802_3 1
+#define ETH_CS_802_1Q_VLAN 3
+#define IPV4_CS 1
+#define IPV6_CS 2
+#define ETH_CS_MASK 0x3f
/** \brief Validity bit maps for TLVs in packet classification rule */
-#define PKT_CLASSIFICATION_USER_PRIORITY_VALID 0
-#define PKT_CLASSIFICATION_VLANID_VALID 1
+#define PKT_CLASSIFICATION_USER_PRIORITY_VALID 0
+#define PKT_CLASSIFICATION_VLANID_VALID 1
#ifndef MIN
-#define MIN(_a, _b) ((_a) < (_b)? (_a): (_b))
+#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#endif
/*Leader related terms */
-#define LEADER_STATUS 0x00
-#define LEADER_STATUS_TCP_ACK 0x1
-#define LEADER_SIZE sizeof(LEADER)
-#define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND)
-#define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND)
-#define CM_REQUEST_SIZE LEADER_SIZE + sizeof(stLocalSFChangeRequest)
-#define IDLE_REQ_SIZE sizeof(PACKETTOSEND)
+#define LEADER_STATUS 0x00
+#define LEADER_STATUS_TCP_ACK 0x1
+#define LEADER_SIZE sizeof(LEADER)
+#define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND)
+#define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND)
+#define CM_REQUEST_SIZE (LEADER_SIZE + sizeof(stLocalSFChangeRequest))
+#define IDLE_REQ_SIZE sizeof(PACKETTOSEND)
-#define MAX_TRANSFER_CTRL_BYTE_USB 2 * 1024
+#define MAX_TRANSFER_CTRL_BYTE_USB (2*1024)
#define GET_MAILBOX1_REG_REQUEST 0x87
#define GET_MAILBOX1_REG_RESPONSE 0x67
@@ -124,40 +124,40 @@
#define TRANSMIT_NETWORK_DATA 0x00
#define RECEIVED_NETWORK_DATA 0x20
-#define CM_RESPONSES 0xA0
-#define STATUS_RSP 0xA1
-#define LINK_CONTROL_RESP 0xA2
-#define IDLE_MODE_STATUS 0xA3
-#define STATS_POINTER_RESP 0xA6
-#define MGMT_MSG_INFO_SW_STATUS 0xA7
-#define AUTH_SS_HOST_MSG 0xA8
-
-#define CM_DSA_ACK_PAYLOAD 247
-#define CM_DSC_ACK_PAYLOAD 248
-#define CM_DSD_ACK_PAYLOAD 249
-#define CM_DSDEACTVATE 250
-#define TOTAL_MASKED_ADDRESS_IN_BYTES 32
-
-#define MAC_REQ 0
-#define LINK_RESP 1
-#define RSSI_INDICATION 2
-
-#define SS_INFO 4
-#define STATISTICS_INFO 5
-#define CM_INDICATION 6
-#define PARAM_RESP 7
-#define BUFFER_1K 1024
-#define BUFFER_2K BUFFER_1K*2
-#define BUFFER_4K BUFFER_2K*2
-#define BUFFER_8K BUFFER_4K*2
-#define BUFFER_16K BUFFER_8K*2
-#define DOWNLINK_DIR 0
-#define UPLINK_DIR 1
-
-#define BCM_SIGNATURE "BECEEM"
-
-
-#define GPIO_OUTPUT_REGISTER 0x0F00003C
+#define CM_RESPONSES 0xA0
+#define STATUS_RSP 0xA1
+#define LINK_CONTROL_RESP 0xA2
+#define IDLE_MODE_STATUS 0xA3
+#define STATS_POINTER_RESP 0xA6
+#define MGMT_MSG_INFO_SW_STATUS 0xA7
+#define AUTH_SS_HOST_MSG 0xA8
+
+#define CM_DSA_ACK_PAYLOAD 247
+#define CM_DSC_ACK_PAYLOAD 248
+#define CM_DSD_ACK_PAYLOAD 249
+#define CM_DSDEACTVATE 250
+#define TOTAL_MASKED_ADDRESS_IN_BYTES 32
+
+#define MAC_REQ 0
+#define LINK_RESP 1
+#define RSSI_INDICATION 2
+
+#define SS_INFO 4
+#define STATISTICS_INFO 5
+#define CM_INDICATION 6
+#define PARAM_RESP 7
+#define BUFFER_1K 1024
+#define BUFFER_2K (BUFFER_1K*2)
+#define BUFFER_4K (BUFFER_2K*2)
+#define BUFFER_8K (BUFFER_4K*2)
+#define BUFFER_16K (BUFFER_8K*2)
+#define DOWNLINK_DIR 0
+#define UPLINK_DIR 1
+
+#define BCM_SIGNATURE "BECEEM"
+
+
+#define GPIO_OUTPUT_REGISTER 0x0F00003C
#define BCM_GPIO_OUTPUT_SET_REG 0x0F000040
#define BCM_GPIO_OUTPUT_CLR_REG 0x0F000044
#define GPIO_MODE_REGISTER 0x0F000034
@@ -165,44 +165,43 @@
typedef struct _LINK_STATE {
- UCHAR ucLinkStatus;
- UCHAR bIdleMode;
- UCHAR bShutdownMode;
-}LINK_STATE, *PLINK_STATE;
+ UCHAR ucLinkStatus;
+ UCHAR bIdleMode;
+ UCHAR bShutdownMode;
+} LINK_STATE, *PLINK_STATE;
enum enLinkStatus {
- WAIT_FOR_SYNC = 1,
- PHY_SYNC_ACHIVED = 2,
- LINKUP_IN_PROGRESS = 3,
- LINKUP_DONE = 4,
- DREG_RECEIVED = 5,
- LINK_STATUS_RESET_RECEIVED = 6,
- PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW = 7,
- LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8,
- COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW =9
+ WAIT_FOR_SYNC = 1,
+ PHY_SYNC_ACHIVED = 2,
+ LINKUP_IN_PROGRESS = 3,
+ LINKUP_DONE = 4,
+ DREG_RECEIVED = 5,
+ LINK_STATUS_RESET_RECEIVED = 6,
+ PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW = 7,
+ LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8,
+ COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW = 9
};
-typedef enum _E_PHS_DSC_ACTION
-{
- eAddPHSRule=0,
+typedef enum _E_PHS_DSC_ACTION {
+ eAddPHSRule = 0,
eSetPHSRule,
eDeletePHSRule,
eDeleteAllPHSRules
-}E_PHS_DSC_ACTION;
+} E_PHS_DSC_ACTION;
-#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 // Host to Mac
-#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 // Mac to Host
-#define MASK_DISABLE_HEADER_SUPPRESSION 0x10 //0b000010000
-#define MINIMUM_PENDING_DESCRIPTORS 5
+#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 /* Host to Mac */
+#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 /* Mac to Host */
+#define MASK_DISABLE_HEADER_SUPPRESSION 0x10 /* 0b000010000 */
+#define MINIMUM_PENDING_DESCRIPTORS 5
#define SHUTDOWN_HOSTINITIATED_REQUESTPAYLOAD 0xCC
#define SHUTDOWN_ACK_FROM_DRIVER 0x1
#define SHUTDOWN_NACK_FROM_DRIVER 0x2
-#define LINK_SYNC_UP_SUBTYPE 0x0001
-#define LINK_SYNC_DOWN_SUBTYPE 0x0001
+#define LINK_SYNC_UP_SUBTYPE 0x0001
+#define LINK_SYNC_DOWN_SUBTYPE 0x0001
@@ -226,9 +225,9 @@ typedef enum _E_PHS_DSC_ACTION
#define MAX_PENDING_CTRL_PACKET (MAX_CTRL_QUEUE_LEN-10)
-#define WIMAX_MAX_MTU (MTU_SIZE + ETH_HLEN)
+#define WIMAX_MAX_MTU (MTU_SIZE + ETH_HLEN)
#define AUTO_LINKUP_ENABLE 0x2
-#define AUTO_SYNC_DISABLE 0x1
+#define AUTO_SYNC_DISABLE 0x1
#define AUTO_FIRM_DOWNLOAD 0x1
#define SETTLE_DOWN_TIME 50
@@ -242,9 +241,9 @@ typedef enum _E_PHS_DSC_ACTION
#define TARGET_CAN_NOT_GO_TO_IDLE_MODE 3
#define IDLE_MODE_PAYLOAD_LENGTH 8
-#define IP_HEADER(Buffer) ((IPHeaderFormat*)(Buffer))
-#define IPV4 4
-#define IP_VERSION(byte) (((byte&0xF0)>>4))
+#define IP_HEADER(Buffer) ((IPHeaderFormat *)(Buffer))
+#define IPV4 4
+#define IP_VERSION(byte) (((byte&0xF0)>>4))
#define SET_MAC_ADDRESS 193
#define SET_MAC_ADDRESS_RESPONSE 236
@@ -263,15 +262,15 @@ typedef enum _E_PHS_DSC_ACTION
#define INVALID_QUEUE_INDEX NO_OF_QUEUES
-#define INVALID_PID (pid_t)-1
-#define DDR_80_MHZ 0
-#define DDR_100_MHZ 1
-#define DDR_120_MHZ 2 // Additional Frequency for T3LP
-#define DDR_133_MHZ 3
-#define DDR_140_MHZ 4 // Not Used (Reserved for future)
-#define DDR_160_MHZ 5 // Additional Frequency for T3LP
-#define DDR_180_MHZ 6 // Not Used (Reserved for future)
-#define DDR_200_MHZ 7 // Not Used (Reserved for future)
+#define INVALID_PID ((pid_t)-1)
+#define DDR_80_MHZ 0
+#define DDR_100_MHZ 1
+#define DDR_120_MHZ 2 /* Additional Frequency for T3LP */
+#define DDR_133_MHZ 3
+#define DDR_140_MHZ 4 /* Not Used (Reserved for future) */
+#define DDR_160_MHZ 5 /* Additional Frequency for T3LP */
+#define DDR_180_MHZ 6 /* Not Used (Reserved for future) */
+#define DDR_200_MHZ 7 /* Not Used (Reserved for future) */
#define MIPS_200_MHZ 0
#define MIPS_160_MHZ 1
@@ -291,27 +290,27 @@ typedef enum _E_PHS_DSC_ACTION
#define EEPROM_REJECT_REG_3 0x0f003008
#define EEPROM_REJECT_REG_4 0x0f003020
#define EEPROM_REJECT_MASK 0x0fffffff
-#define VSG_MODE 0x3
+#define VSG_MODE 0x3
/* Idle Mode Related Registers */
#define DEBUG_INTERRUPT_GENERATOR_REGISTOR 0x0F00007C
-#define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC
+#define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC
-#define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e
-#define DEVICE_INT_OUT_EP_REG0 0x0F011870
-#define DEVICE_INT_OUT_EP_REG1 0x0F011874
+#define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e
+#define DEVICE_INT_OUT_EP_REG0 0x0F011870
+#define DEVICE_INT_OUT_EP_REG1 0x0F011874
#define BIN_FILE "/lib/firmware/macxvi200.bin"
#define CFG_FILE "/lib/firmware/macxvi.cfg"
#define SF_MAX_ALLOWED_PACKETS_TO_BACKUP 128
-#define MIN_VAL(x,y) ((x)<(y)?(x):(y))
+#define MIN_VAL(x, y) ((x) < (y) ? (x) : (y))
#define MAC_ADDRESS_SIZE 6
#define EEPROM_COMMAND_Q_REG 0x0F003018
#define EEPROM_READ_DATA_Q_REG 0x0F003020
-#define CHIP_ID_REG 0x0F000000
-#define GPIO_MODE_REG 0x0F000034
-#define GPIO_OUTPUT_REG 0x0F00003C
-#define WIMAX_MAX_ALLOWED_RATE 1024*1024*50
+#define CHIP_ID_REG 0x0F000000
+#define GPIO_MODE_REG 0x0F000034
+#define GPIO_OUTPUT_REG 0x0F00003C
+#define WIMAX_MAX_ALLOWED_RATE (1024*1024*50)
#define T3 0xbece0300
#define TARGET_SFID_TXDESC_MAP_LOC 0xBFFFF400
@@ -319,31 +318,29 @@ typedef enum _E_PHS_DSC_ACTION
#define RWM_READ 0
#define RWM_WRITE 1
-#define T3LPB 0xbece3300
-#define BCS220_2 0xbece3311
-#define BCS220_2BC 0xBECE3310
-#define BCS250_BC 0xbece3301
-#define BCS220_3 0xbece3321
+#define T3LPB 0xbece3300
+#define BCS220_2 0xbece3311
+#define BCS220_2BC 0xBECE3310
+#define BCS250_BC 0xbece3301
+#define BCS220_3 0xbece3321
-#define HPM_CONFIG_LDO145 0x0F000D54
-#define HPM_CONFIG_MSW 0x0F000D58
+#define HPM_CONFIG_LDO145 0x0F000D54
+#define HPM_CONFIG_MSW 0x0F000D58
#define T3B 0xbece0310
-typedef enum eNVM_TYPE
-{
+typedef enum eNVM_TYPE {
NVM_AUTODETECT = 0,
NVM_EEPROM,
NVM_FLASH,
NVM_UNKNOWN
-}NVM_TYPE;
+} NVM_TYPE;
-typedef enum ePMU_MODES
-{
+typedef enum ePMU_MODES {
HYBRID_MODE_7C = 0,
INTERNAL_MODE_6 = 1,
HYBRID_MODE_6 = 2
-}PMU_MODE;
+} PMU_MODE;
#define MAX_RDM_WRM_RETIRES 1
@@ -360,4 +357,4 @@ enum eAbortPattern {
#define SKB_CB_LATENCY_OFFSET 1
#define SKB_CB_TCPACK_OFFSET 2
-#endif //__MACROS_H__
+#endif /* __MACROS_H__ */
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
index c5b3a3666bc7..e9f29d597518 100644
--- a/drivers/staging/bcm/Misc.c
+++ b/drivers/staging/bcm/Misc.c
@@ -1,113 +1,94 @@
#include "headers.h"
-static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path,
- unsigned int loc);
+static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path, unsigned int loc);
static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter);
-static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter,PUCHAR pucBuffer);
+static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter, PUCHAR pucBuffer);
static int bcm_parse_target_params(PMINI_ADAPTER Adapter);
-static void beceem_protocol_reset (PMINI_ADAPTER Adapter);
+static void beceem_protocol_reset(PMINI_ADAPTER Adapter);
static VOID default_wimax_protocol_initialize(PMINI_ADAPTER Adapter)
{
+ UINT uiLoopIndex;
- UINT uiLoopIndex;
-
- for(uiLoopIndex=0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++)
- {
- Adapter->PackInfo[uiLoopIndex].uiThreshold=TX_PACKET_THRESHOLD;
- Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate=MAX_ALLOWED_RATE;
- Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize=20*1024*1024;
- }
-
- Adapter->BEBucketSize=BE_BUCKET_SIZE;
- Adapter->rtPSBucketSize=rtPS_BUCKET_SIZE;
- Adapter->LinkStatus=SYNC_UP_REQUEST;
- Adapter->TransferMode=IP_PACKET_ONLY_MODE;
- Adapter->usBestEffortQueueIndex=-1;
- return;
-}
+ for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++) {
+ Adapter->PackInfo[uiLoopIndex].uiThreshold = TX_PACKET_THRESHOLD;
+ Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate = MAX_ALLOWED_RATE;
+ Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize = 20*1024*1024;
+ }
+ Adapter->BEBucketSize = BE_BUCKET_SIZE;
+ Adapter->rtPSBucketSize = rtPS_BUCKET_SIZE;
+ Adapter->LinkStatus = SYNC_UP_REQUEST;
+ Adapter->TransferMode = IP_PACKET_ONLY_MODE;
+ Adapter->usBestEffortQueueIndex = -1;
+ return;
+}
-INT
-InitAdapter(PMINI_ADAPTER psAdapter)
+INT InitAdapter(PMINI_ADAPTER psAdapter)
{
- int i = 0;
- INT Status = STATUS_SUCCESS ;
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter);
+ int i = 0;
+ INT Status = STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter);
- if(psAdapter == NULL)
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter is NULL");
+ if (psAdapter == NULL) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter is NULL");
return -EINVAL;
}
- sema_init(&psAdapter->NVMRdmWrmLock,1);
-// psAdapter->ulFlashCalStart = FLASH_AUTO_INIT_BASE_ADDR;
-
+ sema_init(&psAdapter->NVMRdmWrmLock, 1);
sema_init(&psAdapter->rdmwrmsync, 1);
spin_lock_init(&psAdapter->control_queue_lock);
spin_lock_init(&psAdapter->txtransmitlock);
- sema_init(&psAdapter->RxAppControlQueuelock, 1);
-// sema_init(&psAdapter->data_packet_queue_lock, 1);
- sema_init(&psAdapter->fw_download_sema, 1);
- sema_init(&psAdapter->LowPowerModeSync,1);
-
- // spin_lock_init(&psAdapter->sleeper_lock);
-
- for(i=0;i<NO_OF_QUEUES; i++)
- spin_lock_init(&psAdapter->PackInfo[i].SFQueueLock);
- i=0;
-
- init_waitqueue_head(&psAdapter->process_rx_cntrlpkt);
- init_waitqueue_head(&psAdapter->tx_packet_wait_queue);
- init_waitqueue_head(&psAdapter->process_read_wait_queue);
- init_waitqueue_head(&psAdapter->ioctl_fw_dnld_wait_queue);
- init_waitqueue_head(&psAdapter->lowpower_mode_wait_queue);
+ sema_init(&psAdapter->RxAppControlQueuelock, 1);
+ sema_init(&psAdapter->fw_download_sema, 1);
+ sema_init(&psAdapter->LowPowerModeSync, 1);
+
+ for (i = 0; i < NO_OF_QUEUES; i++)
+ spin_lock_init(&psAdapter->PackInfo[i].SFQueueLock);
+ i = 0;
+
+ init_waitqueue_head(&psAdapter->process_rx_cntrlpkt);
+ init_waitqueue_head(&psAdapter->tx_packet_wait_queue);
+ init_waitqueue_head(&psAdapter->process_read_wait_queue);
+ init_waitqueue_head(&psAdapter->ioctl_fw_dnld_wait_queue);
+ init_waitqueue_head(&psAdapter->lowpower_mode_wait_queue);
psAdapter->waiting_to_fw_download_done = TRUE;
- //init_waitqueue_head(&psAdapter->device_wake_queue);
- psAdapter->fw_download_done=FALSE;
-
+ psAdapter->fw_download_done = FALSE;
default_wimax_protocol_initialize(psAdapter);
- for (i=0;i<MAX_CNTRL_PKTS;i++)
- {
+ for (i = 0; i < MAX_CNTRL_PKTS; i++) {
psAdapter->txctlpacket[i] = kmalloc(MAX_CNTL_PKT_SIZE, GFP_KERNEL);
- if(!psAdapter->txctlpacket[i])
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No More Cntl pkts got, max got is %d", i);
+ if (!psAdapter->txctlpacket[i]) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No More Cntl pkts got, max got is %d", i);
return -ENOMEM;
}
}
- if(AllocAdapterDsxBuffer(psAdapter))
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to allocate DSX buffers");
+
+ if (AllocAdapterDsxBuffer(psAdapter)) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to allocate DSX buffers");
return -EINVAL;
}
- //Initialize PHS interface
- if(phs_init(&psAdapter->stBCMPhsContext,psAdapter)!=0)
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%s:%d:Error PHS Init Failed=====>\n", __FILE__, __FUNCTION__, __LINE__);
+ /* Initialize PHS interface */
+ if (phs_init(&psAdapter->stBCMPhsContext, psAdapter) != 0) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%s:%d:Error PHS Init Failed=====>\n", __FILE__, __func__, __LINE__);
return -ENOMEM;
}
Status = BcmAllocFlashCSStructure(psAdapter);
- if(Status)
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Memory Allocation for Flash structure failed");
- return Status ;
+ if (Status) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Memory Allocation for Flash structure failed");
+ return Status;
}
Status = vendorextnInit(psAdapter);
- if(STATUS_SUCCESS != Status)
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Vendor Init Failed");
- return Status ;
+ if (STATUS_SUCCESS != Status) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Vendor Init Failed");
+ return Status;
}
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter initialised");
-
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter initialised");
return STATUS_SUCCESS;
}
@@ -115,42 +96,37 @@ InitAdapter(PMINI_ADAPTER psAdapter)
VOID AdapterFree(PMINI_ADAPTER Adapter)
{
int count;
-
beceem_protocol_reset(Adapter);
-
vendorextnExit(Adapter);
- if(Adapter->control_packet_handler && !IS_ERR(Adapter->control_packet_handler))
- kthread_stop (Adapter->control_packet_handler);
+ if (Adapter->control_packet_handler && !IS_ERR(Adapter->control_packet_handler))
+ kthread_stop(Adapter->control_packet_handler);
- if(Adapter->transmit_packet_thread && !IS_ERR(Adapter->transmit_packet_thread))
- kthread_stop (Adapter->transmit_packet_thread);
+ if (Adapter->transmit_packet_thread && !IS_ERR(Adapter->transmit_packet_thread))
+ kthread_stop(Adapter->transmit_packet_thread);
wake_up(&Adapter->process_read_wait_queue);
- if(Adapter->LEDInfo.led_thread_running & (BCM_LED_THREAD_RUNNING_ACTIVELY | BCM_LED_THREAD_RUNNING_INACTIVELY))
- kthread_stop (Adapter->LEDInfo.led_cntrl_threadid);
+ if (Adapter->LEDInfo.led_thread_running & (BCM_LED_THREAD_RUNNING_ACTIVELY | BCM_LED_THREAD_RUNNING_INACTIVELY))
+ kthread_stop(Adapter->LEDInfo.led_cntrl_threadid);
unregister_networkdev(Adapter);
/* FIXME: use proper wait_event and refcounting */
- while(atomic_read(&Adapter->ApplicationRunning))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Waiting for Application to close.. %d\n",atomic_read(&Adapter->ApplicationRunning));
+ while (atomic_read(&Adapter->ApplicationRunning)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Waiting for Application to close.. %d\n", atomic_read(&Adapter->ApplicationRunning));
msleep(100);
}
unregister_control_device_interface(Adapter);
-
kfree(Adapter->pstargetparams);
- for (count =0;count < MAX_CNTRL_PKTS;count++)
+ for (count = 0; count < MAX_CNTRL_PKTS; count++)
kfree(Adapter->txctlpacket[count]);
FreeAdapterDsxBuffer(Adapter);
-
kfree(Adapter->pvInterfaceAdapter);
- //Free the PHS Interface
+ /* Free the PHS Interface */
PhsCleanup(&Adapter->stBCMPhsContext);
BcmDeAllocFlashCSStructure(Adapter);
@@ -160,20 +136,18 @@ VOID AdapterFree(PMINI_ADAPTER Adapter)
static int create_worker_threads(PMINI_ADAPTER psAdapter)
{
- // Rx Control Packets Processing
+ /* Rx Control Packets Processing */
psAdapter->control_packet_handler = kthread_run((int (*)(void *))
control_packet_handler, psAdapter, "%s-rx", DRV_NAME);
- if(IS_ERR(psAdapter->control_packet_handler))
- {
+ if (IS_ERR(psAdapter->control_packet_handler)) {
pr_notice(DRV_NAME ": could not create control thread\n");
return PTR_ERR(psAdapter->control_packet_handler);
}
- // Tx Thread
+ /* Tx Thread */
psAdapter->transmit_packet_thread = kthread_run((int (*)(void *))
tx_pkt_handler, psAdapter, "%s-tx", DRV_NAME);
- if(IS_ERR (psAdapter->transmit_packet_thread))
- {
+ if (IS_ERR(psAdapter->transmit_packet_thread)) {
pr_notice(DRV_NAME ": could not creat transmit thread\n");
kthread_stop(psAdapter->control_packet_handler);
return PTR_ERR(psAdapter->transmit_packet_thread);
@@ -183,275 +157,248 @@ static int create_worker_threads(PMINI_ADAPTER psAdapter)
static struct file *open_firmware_file(PMINI_ADAPTER Adapter, const char *path)
{
- struct file *flp=NULL;
- mm_segment_t oldfs;
- oldfs=get_fs();
+ struct file *flp = NULL;
+ mm_segment_t oldfs;
+ oldfs = get_fs();
set_fs(get_ds());
- flp=filp_open(path, O_RDONLY, S_IRWXU);
- set_fs(oldfs);
- if(IS_ERR(flp))
- {
- pr_err(DRV_NAME "Unable To Open File %s, err %ld",
- path, PTR_ERR(flp));
- flp = NULL;
- }
-
- if(Adapter->device_removed)
- flp = NULL;
-
- return flp;
-}
+ flp = filp_open(path, O_RDONLY, S_IRWXU);
+ set_fs(oldfs);
+ if (IS_ERR(flp)) {
+ pr_err(DRV_NAME "Unable To Open File %s, err %ld", path, PTR_ERR(flp));
+ flp = NULL;
+ }
+ if (Adapter->device_removed)
+ flp = NULL;
-static int BcmFileDownload(PMINI_ADAPTER Adapter,/**< Logical Adapter */
- const char *path, /**< path to image file */
- unsigned int loc /**< Download Address on the chip*/
- )
+ return flp;
+}
+
+/* Arguments:
+ * Logical Adapter
+ * Path to image file
+ * Download Address on the chip
+ */
+static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path, unsigned int loc)
{
- int errorno=0;
- struct file *flp=NULL;
- mm_segment_t oldfs;
- struct timeval tv={0};
-
- flp=open_firmware_file(Adapter, path);
- if(!flp)
- {
- errorno = -ENOENT;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path);
- goto exit_download;
- }
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path,(unsigned long)flp->f_dentry->d_inode->i_size, loc);
- do_gettimeofday(&tv);
-
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "download start %lx", ((tv.tv_sec * 1000) +
- (tv.tv_usec/1000)));
- if(Adapter->bcm_file_download(Adapter->pvInterfaceAdapter, flp, loc))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to download the firmware with error\
- %x!!!", -EIO);
- errorno=-EIO;
- goto exit_download;
- }
- oldfs=get_fs();set_fs(get_ds());
- vfs_llseek(flp, 0, 0);
- set_fs(oldfs);
- if(Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter,
- flp, loc))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!");
- errorno=-EIO;
- goto exit_download;
- }
+ int errorno = 0;
+ struct file *flp = NULL;
+ mm_segment_t oldfs;
+ struct timeval tv = {0};
+
+ flp = open_firmware_file(Adapter, path);
+ if (!flp) {
+ errorno = -ENOENT;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path);
+ goto exit_download;
+ }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path, (unsigned long)flp->f_dentry->d_inode->i_size, loc);
+ do_gettimeofday(&tv);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "download start %lx", ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)));
+ if (Adapter->bcm_file_download(Adapter->pvInterfaceAdapter, flp, loc)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to download the firmware with error %x!!!", -EIO);
+ errorno = -EIO;
+ goto exit_download;
+ }
+ oldfs = get_fs();
+ set_fs(get_ds());
+ vfs_llseek(flp, 0, 0);
+ set_fs(oldfs);
+ if (Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter, flp, loc)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!");
+ errorno = -EIO;
+ goto exit_download;
+ }
exit_download:
- oldfs=get_fs();set_fs(get_ds());
- if(flp && !(IS_ERR(flp)))
- filp_close(flp, current->files);
- set_fs(oldfs);
+ oldfs = get_fs();
+ set_fs(get_ds());
+ if (flp && !(IS_ERR(flp)))
+ filp_close(flp, current->files);
+ set_fs(oldfs);
- return errorno;
+ return errorno;
}
/**
-@ingroup ctrl_pkt_functions
-This function copies the contents of given buffer
-to the control packet and queues it for transmission.
-@note Do not acquire the spinock, as it it already acquired.
-@return SUCCESS/FAILURE.
-*/
-INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter,/**<Logical Adapter*/
- PVOID ioBuffer/**<Control Packet Buffer*/
- )
+ * @ingroup ctrl_pkt_functions
+ * This function copies the contents of given buffer
+ * to the control packet and queues it for transmission.
+ * @note Do not acquire the spinock, as it it already acquired.
+ * @return SUCCESS/FAILURE.
+ * Arguments:
+ * Logical Adapter
+ * Control Packet Buffer
+ */
+INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer)
{
- PLEADER pLeader=NULL;
- INT Status=0;
- unsigned char *ctrl_buff=NULL;
- UINT pktlen=0;
- PLINK_REQUEST pLinkReq = NULL;
- PUCHAR pucAddIndication = NULL;
-
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "======>");
- if(!ioBuffer)
- {
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Got Null Buffer\n");
+ PLEADER pLeader = NULL;
+ INT Status = 0;
+ unsigned char *ctrl_buff = NULL;
+ UINT pktlen = 0;
+ PLINK_REQUEST pLinkReq = NULL;
+ PUCHAR pucAddIndication = NULL;
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "======>");
+ if (!ioBuffer) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got Null Buffer\n");
return -EINVAL;
}
pLinkReq = (PLINK_REQUEST)ioBuffer;
- pLeader=(PLEADER)ioBuffer; //ioBuffer Contains sw_Status and Payload
+ pLeader = (PLEADER)ioBuffer; /* ioBuffer Contains sw_Status and Payload */
- if(Adapter->bShutStatus == TRUE &&
+ if (Adapter->bShutStatus == TRUE &&
pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD &&
- pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE)
- {
- //Got sync down in SHUTDOWN..we could not process this.
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "SYNC DOWN Request in Shut Down Mode..\n");
+ pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE) {
+
+ /* Got sync down in SHUTDOWN..we could not process this. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC DOWN Request in Shut Down Mode..\n");
return STATUS_FAILURE;
}
- if((pLeader->Status == LINK_UP_CONTROL_REQ) &&
+ if ((pLeader->Status == LINK_UP_CONTROL_REQ) &&
((pLinkReq->szData[0] == LINK_UP_REQ_PAYLOAD &&
- (pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE)) ||//Sync Up Command
- pLinkReq->szData[0] == NETWORK_ENTRY_REQ_PAYLOAD)) //Net Entry Command
- {
- if(Adapter->LinkStatus > PHY_SYNC_ACHIVED)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"LinkStatus is Greater than PHY_SYN_ACHIEVED");
+ (pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE)) || /* Sync Up Command */
+ pLinkReq->szData[0] == NETWORK_ENTRY_REQ_PAYLOAD)) /* Net Entry Command */ {
+
+ if (Adapter->LinkStatus > PHY_SYNC_ACHIVED) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "LinkStatus is Greater than PHY_SYN_ACHIEVED");
return STATUS_FAILURE;
}
- if(TRUE == Adapter->bShutStatus)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n");
- if(Adapter->bTriedToWakeUpFromlowPowerMode == FALSE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Waking up for the First Time..\n");
- Adapter->usIdleModePattern = ABORT_SHUTDOWN_MODE; // change it to 1 for current support.
+
+ if (TRUE == Adapter->bShutStatus) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n");
+ if (Adapter->bTriedToWakeUpFromlowPowerMode == FALSE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Waking up for the First Time..\n");
+ Adapter->usIdleModePattern = ABORT_SHUTDOWN_MODE; /* change it to 1 for current support. */
Adapter->bWakeUpDevice = TRUE;
wake_up(&Adapter->process_rx_cntrlpkt);
+ Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, !Adapter->bShutStatus, (5 * HZ));
- Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
- !Adapter->bShutStatus, (5 * HZ));
-
- if(Status == -ERESTARTSYS)
+ if (Status == -ERESTARTSYS)
return Status;
- if(Adapter->bShutStatus)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Shutdown Mode Wake up Failed - No Wake Up Received\n");
+ if (Adapter->bShutStatus) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shutdown Mode Wake up Failed - No Wake Up Received\n");
return STATUS_FAILURE;
}
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Wakeup has been tried already...\n");
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Wakeup has been tried already...\n");
}
}
-
}
- if(TRUE == Adapter->IdleMode)
- {
- //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence \n");
- if(pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 ||
- pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ )
- {
- if((pLeader->Status == LINK_UP_CONTROL_REQ) && (pLinkReq->szData[0]==LINK_DOWN_REQ_PAYLOAD))
- {
- if((pLinkReq->szData[1] == LINK_SYNC_DOWN_SUBTYPE))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Link Down Sent in Idle Mode\n");
- Adapter->usIdleModePattern = ABORT_IDLE_SYNCDOWN;//LINK DOWN sent in Idle Mode
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"ABORT_IDLE_MODE pattern is being written\n");
+ if (TRUE == Adapter->IdleMode) {
+ /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence\n"); */
+ if (pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 ||
+ pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ) {
+
+ if ((pLeader->Status == LINK_UP_CONTROL_REQ) && (pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD)) {
+ if ((pLinkReq->szData[1] == LINK_SYNC_DOWN_SUBTYPE)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Link Down Sent in Idle Mode\n");
+ Adapter->usIdleModePattern = ABORT_IDLE_SYNCDOWN; /* LINK DOWN sent in Idle Mode */
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "ABORT_IDLE_MODE pattern is being written\n");
Adapter->usIdleModePattern = ABORT_IDLE_REG;
}
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"ABORT_IDLE_MODE pattern is being written\n");
- Adapter->usIdleModePattern = ABORT_IDLE_MODE;
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "ABORT_IDLE_MODE pattern is being written\n");
+ Adapter->usIdleModePattern = ABORT_IDLE_MODE;
}
/*Setting bIdleMode_tx_from_host to TRUE to indicate LED control thread to represent
- the wake up from idlemode is from host*/
- //Adapter->LEDInfo.bIdleMode_tx_from_host = TRUE;
+ * the wake up from idlemode is from host
+ */
+ /* Adapter->LEDInfo.bIdleMode_tx_from_host = TRUE; */
Adapter->bWakeUpDevice = TRUE;
wake_up(&Adapter->process_rx_cntrlpkt);
-
-
- if(LINK_DOWN_REQ_PAYLOAD == pLinkReq->szData[0])
- {
- // We should not send DREG message down while in idlemode.
+ /* We should not send DREG message down while in idlemode. */
+ if (LINK_DOWN_REQ_PAYLOAD == pLinkReq->szData[0])
return STATUS_SUCCESS;
- }
- Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
- !Adapter->IdleMode, (5 * HZ));
+ Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, !Adapter->IdleMode, (5 * HZ));
- if(Status == -ERESTARTSYS)
+ if (Status == -ERESTARTSYS)
return Status;
- if(Adapter->IdleMode)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Idle Mode Wake up Failed - No Wake Up Received\n");
+ if (Adapter->IdleMode) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Wake up Failed - No Wake Up Received\n");
return STATUS_FAILURE;
}
- }
- else
+ } else {
return STATUS_SUCCESS;
+ }
}
- //The Driver has to send control messages with a particular VCID
- pLeader->Vcid = VCID_CONTROL_PACKET;//VCID for control packet.
+
+ /* The Driver has to send control messages with a particular VCID */
+ pLeader->Vcid = VCID_CONTROL_PACKET; /* VCID for control packet. */
/* Allocate skb for Control Packet */
pktlen = pLeader->PLength;
ctrl_buff = (char *)Adapter->txctlpacket[atomic_read(&Adapter->index_wr_txcntrlpkt)%MAX_CNTRL_PKTS];
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x",
- atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen);
- if(ctrl_buff)
- {
- if(pLeader)
- {
- if((pLeader->Status == 0x80) ||
- (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ))
- {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x",
+ atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen);
+ if (ctrl_buff) {
+ if (pLeader) {
+ if ((pLeader->Status == 0x80) ||
+ (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) {
/*
- //Restructure the DSX message to handle Multiple classifier Support
- // Write the Service Flow param Structures directly to the target
- //and embed the pointers in the DSX messages sent to target.
- */
- //Lets store the current length of the control packet we are transmitting
+ * Restructure the DSX message to handle Multiple classifier Support
+ * Write the Service Flow param Structures directly to the target
+ * and embed the pointers in the DSX messages sent to target.
+ */
+ /* Lets store the current length of the control packet we are transmitting */
pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE;
pktlen = pLeader->PLength;
- Status = StoreCmControlResponseMessage(Adapter,pucAddIndication, &pktlen);
- if(Status != 1)
- {
- ClearTargetDSXBuffer(Adapter,((stLocalSFAddIndicationAlt *)pucAddIndication)->u16TID, FALSE);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly ");
+ Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen);
+ if (Status != 1) {
+ ClearTargetDSXBuffer(Adapter, ((stLocalSFAddIndicationAlt *)pucAddIndication)->u16TID, FALSE);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly ");
return STATUS_FAILURE;
}
/*
- //update the leader to use the new length
- //The length of the control packet is length of message being sent + Leader length
- */
+ * update the leader to use the new length
+ * The length of the control packet is length of message being sent + Leader length
+ */
pLeader->PLength = pktlen;
}
}
+
+ if (pktlen + LEADER_SIZE > MAX_CNTL_PKT_SIZE)
+ return -EINVAL;
+
memset(ctrl_buff, 0, pktlen+LEADER_SIZE);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength);
- *(PLEADER)ctrl_buff=*pLeader;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength);
+ *(PLEADER)ctrl_buff = *pLeader;
memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet");
- /*Update the statistics counters */
+ /* Update the statistics counters */
spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
- Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost+=pLeader->PLength;
+ Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost += pLeader->PLength;
Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++;
atomic_inc(&Adapter->TotalPacketCount);
spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
-
Adapter->PackInfo[HiPriority].bValid = TRUE;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x",
- Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost,
- Adapter->PackInfo[HiPriority].bValid);
- Status=STATUS_SUCCESS;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x",
+ Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost,
+ Adapter->PackInfo[HiPriority].bValid);
+ Status = STATUS_SUCCESS;
/*Queue the packet for transmission */
atomic_inc(&Adapter->index_wr_txcntrlpkt);
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Calling transmit_packets");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Calling transmit_packets");
atomic_set(&Adapter->TxPktAvail, 1);
wake_up(&Adapter->tx_packet_wait_queue);
+ } else {
+ Status = -ENOMEM;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed");
}
- else
- {
- Status=-ENOMEM;
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed");
- }
- BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<====");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<====");
return Status;
}
@@ -460,33 +407,30 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter,/**<Logical Adapter*/
* Function - SendStatisticsPointerRequest()
*
* Description - This function builds and forwards the Statistics
-* Pointer Request control Packet.
+* Pointer Request control Packet.
*
* Parameters - Adapter : Pointer to Adapter structure.
-* - pstStatisticsPtrRequest : Pointer to link request.
+* - pstStatisticsPtrRequest : Pointer to link request.
*
* Returns - None.
*****************************************************************/
-static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter,
- PLINK_REQUEST pstStatisticsPtrRequest)
+static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, PLINK_REQUEST pstStatisticsPtrRequest)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "======>");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "======>");
pstStatisticsPtrRequest->Leader.Status = STATS_POINTER_REQ_STATUS;
- pstStatisticsPtrRequest->Leader.PLength = sizeof(ULONG);//minimum 4 bytes
+ pstStatisticsPtrRequest->Leader.PLength = sizeof(ULONG); /* minimum 4 bytes */
pstStatisticsPtrRequest->szData[0] = STATISTICS_POINTER_REQ;
-
- CopyBufferToControlPacket(Adapter,pstStatisticsPtrRequest);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "<=====");
+ CopyBufferToControlPacket(Adapter, pstStatisticsPtrRequest);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "<=====");
return;
}
#endif
-
/******************************************************************
* Function - LinkMessage()
*
* Description - This function builds the Sync-up and Link-up request
-* packet messages depending on the device Link status.
+* packet messages depending on the device Link status.
*
* Parameters - Adapter: Pointer to the Adapter structure.
*
@@ -494,102 +438,90 @@ static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter,
*******************************************************************/
VOID LinkMessage(PMINI_ADAPTER Adapter)
{
- PLINK_REQUEST pstLinkRequest=NULL;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>");
- if(Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup)
- {
+ PLINK_REQUEST pstLinkRequest = NULL;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>");
+ if (Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup) {
pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
- if(!pstLinkRequest)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
+ if (!pstLinkRequest) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
return;
}
- //sync up request...
- Adapter->LinkStatus = WAIT_FOR_SYNC;// current link status
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For SyncUp...");
- pstLinkRequest->szData[0]=LINK_UP_REQ_PAYLOAD;
- pstLinkRequest->szData[1]=LINK_SYNC_UP_SUBTYPE;
- pstLinkRequest->Leader.Status=LINK_UP_CONTROL_REQ;
- pstLinkRequest->Leader.PLength=sizeof(ULONG);
+ /* sync up request... */
+ Adapter->LinkStatus = WAIT_FOR_SYNC; /* current link status */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For SyncUp...");
+ pstLinkRequest->szData[0] = LINK_UP_REQ_PAYLOAD;
+ pstLinkRequest->szData[1] = LINK_SYNC_UP_SUBTYPE;
+ pstLinkRequest->Leader.Status = LINK_UP_CONTROL_REQ;
+ pstLinkRequest->Leader.PLength = sizeof(ULONG);
Adapter->bSyncUpRequestSent = TRUE;
- }
- else if(Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp)
- {
+
+ } else if (Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp) {
pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
- if(!pstLinkRequest)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
+ if (!pstLinkRequest) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
return;
}
- //LINK_UP_REQUEST
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For LinkUp...");
- pstLinkRequest->szData[0]=LINK_UP_REQ_PAYLOAD;
- pstLinkRequest->szData[1]=LINK_NET_ENTRY;
- pstLinkRequest->Leader.Status=LINK_UP_CONTROL_REQ;
- pstLinkRequest->Leader.PLength=sizeof(ULONG);
- }
- if(pstLinkRequest)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Calling CopyBufferToControlPacket");
+ /* LINK_UP_REQUEST */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For LinkUp...");
+ pstLinkRequest->szData[0] = LINK_UP_REQ_PAYLOAD;
+ pstLinkRequest->szData[1] = LINK_NET_ENTRY;
+ pstLinkRequest->Leader.Status = LINK_UP_CONTROL_REQ;
+ pstLinkRequest->Leader.PLength = sizeof(ULONG);
+ }
+ if (pstLinkRequest) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Calling CopyBufferToControlPacket");
CopyBufferToControlPacket(Adapter, pstLinkRequest);
kfree(pstLinkRequest);
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "LinkMessage <=====");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "LinkMessage <=====");
return;
}
-
/**********************************************************************
* Function - StatisticsResponse()
*
* Description - This function handles the Statistics response packet.
*
* Parameters - Adapter : Pointer to the Adapter structure.
-* - pvBuffer: Starting address of Statistic response data.
+* - pvBuffer: Starting address of Statistic response data.
*
* Returns - None.
************************************************************************/
-VOID StatisticsResponse(PMINI_ADAPTER Adapter,PVOID pvBuffer)
+VOID StatisticsResponse(PMINI_ADAPTER Adapter, PVOID pvBuffer)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>",__FUNCTION__);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>", __func__);
Adapter->StatisticsPointer = ntohl(*(__be32 *)pvBuffer);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (UINT)Adapter->StatisticsPointer);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====",__FUNCTION__);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (UINT)Adapter->StatisticsPointer);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====", __func__);
return;
}
-
/**********************************************************************
* Function - LinkControlResponseMessage()
*
* Description - This function handles the Link response packets.
*
* Parameters - Adapter : Pointer to the Adapter structure.
-* - pucBuffer: Starting address of Link response data.
+* - pucBuffer: Starting address of Link response data.
*
* Returns - None.
***********************************************************************/
-VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter,PUCHAR pucBuffer)
+VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter, PUCHAR pucBuffer)
{
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>");
- if(*pucBuffer==LINK_UP_ACK)
- {
- switch(*(pucBuffer+1))
- {
- case PHY_SYNC_ACHIVED: //SYNCed UP
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHY_SYNC_ACHIVED");
+ if (*pucBuffer == LINK_UP_ACK) {
+ switch (*(pucBuffer+1)) {
+ case PHY_SYNC_ACHIVED: /* SYNCed UP */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "PHY_SYNC_ACHIVED");
- if(Adapter->LinkStatus == LINKUP_DONE)
- {
+ if (Adapter->LinkStatus == LINKUP_DONE)
beceem_protocol_reset(Adapter);
- }
- Adapter->usBestEffortQueueIndex=INVALID_QUEUE_INDEX ;
- Adapter->LinkStatus=PHY_SYNC_ACHIVED;
+ Adapter->usBestEffortQueueIndex = INVALID_QUEUE_INDEX;
+ Adapter->LinkStatus = PHY_SYNC_ACHIVED;
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
Adapter->DriverState = NO_NETWORK_ENTRY;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
@@ -597,161 +529,145 @@ VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter,PUCHAR pucBuffer)
LinkMessage(Adapter);
break;
- case LINKUP_DONE:
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LINKUP_DONE");
- Adapter->LinkStatus=LINKUP_DONE;
- Adapter->bPHSEnabled = *(pucBuffer+3);
- Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Received In LinkUp Ack : %x \n",Adapter->bPHSEnabled);
- if((FALSE == Adapter->bShutStatus)&&
- (FALSE == Adapter->IdleMode))
- {
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
- Adapter->DriverState = NORMAL_OPERATION;
- wake_up(&Adapter->LEDInfo.notify_led_event);
- }
+ case LINKUP_DONE:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LINKUP_DONE");
+ Adapter->LinkStatus = LINKUP_DONE;
+ Adapter->bPHSEnabled = *(pucBuffer+3);
+ Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Received In LinkUp Ack : %x\n", Adapter->bPHSEnabled);
+
+ if ((FALSE == Adapter->bShutStatus) && (FALSE == Adapter->IdleMode)) {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = NORMAL_OPERATION;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
}
- LinkMessage(Adapter);
- break;
- case WAIT_FOR_SYNC:
+ }
+ LinkMessage(Adapter);
+ break;
- /*
- * Driver to ignore the DREG_RECEIVED
- * WiMAX Application should handle this Message
- */
- //Adapter->liTimeSinceLastNetEntry = 0;
- Adapter->LinkUpStatus = 0;
- Adapter->LinkStatus = 0;
- Adapter->usBestEffortQueueIndex=INVALID_QUEUE_INDEX ;
- Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
- Adapter->IdleMode = FALSE;
- beceem_protocol_reset(Adapter);
+ case WAIT_FOR_SYNC:
+ /*
+ * Driver to ignore the DREG_RECEIVED
+ * WiMAX Application should handle this Message
+ */
+ /* Adapter->liTimeSinceLastNetEntry = 0; */
+ Adapter->LinkUpStatus = 0;
+ Adapter->LinkStatus = 0;
+ Adapter->usBestEffortQueueIndex = INVALID_QUEUE_INDEX;
+ Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
+ Adapter->IdleMode = FALSE;
+ beceem_protocol_reset(Adapter);
- break;
- case LINK_SHUTDOWN_REQ_FROM_FIRMWARE:
- case COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW:
- {
- HandleShutDownModeRequest(Adapter, pucBuffer);
- }
- break;
- default:
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "default case:LinkResponse %x",*(pucBuffer+1));
- break;
+ break;
+ case LINK_SHUTDOWN_REQ_FROM_FIRMWARE:
+ case COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW:
+ {
+ HandleShutDownModeRequest(Adapter, pucBuffer);
}
- }
- else if(SET_MAC_ADDRESS_RESPONSE==*pucBuffer)
- {
+ break;
+ default:
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "default case:LinkResponse %x", *(pucBuffer + 1));
+ break;
+ }
+ } else if (SET_MAC_ADDRESS_RESPONSE == *pucBuffer) {
PUCHAR puMacAddr = (pucBuffer + 1);
- Adapter->LinkStatus=SYNC_UP_REQUEST;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "MAC address response, sending SYNC_UP");
+ Adapter->LinkStatus = SYNC_UP_REQUEST;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "MAC address response, sending SYNC_UP");
LinkMessage(Adapter);
memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE);
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "%s <=====",__FUNCTION__);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "%s <=====", __func__);
return;
}
void SendIdleModeResponse(PMINI_ADAPTER Adapter)
{
- INT status = 0, NVMAccess = 0,lowPwrAbortMsg = 0;
+ INT status = 0, NVMAccess = 0, lowPwrAbortMsg = 0;
struct timeval tv;
- CONTROL_MESSAGE stIdleResponse = {{0}};
+ CONTROL_MESSAGE stIdleResponse = {{0} };
memset(&tv, 0, sizeof(tv));
- stIdleResponse.Leader.Status = IDLE_MESSAGE;
+ stIdleResponse.Leader.Status = IDLE_MESSAGE;
stIdleResponse.Leader.PLength = IDLE_MODE_PAYLOAD_LENGTH;
stIdleResponse.szData[0] = GO_TO_IDLE_MODE_PAYLOAD;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL," ============>");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, " ============>");
/*********************************
- **down_trylock -
- ** if [ semaphore is available ]
- ** acquire semaphone and return value 0 ;
- ** else
- ** return non-zero value ;
- **
- ***********************************/
+ *down_trylock -
+ * if [ semaphore is available ]
+ * acquire semaphone and return value 0 ;
+ * else
+ * return non-zero value ;
+ *
+ ***********************************/
NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ lowPwrAbortMsg = down_trylock(&Adapter->LowPowerModeSync);
- lowPwrAbortMsg= down_trylock(&Adapter->LowPowerModeSync);
+ if ((NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) &&
+ (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)) {
- if((NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) &&
- (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) )
- {
- if(!NVMAccess)
+ if (!NVMAccess)
up(&Adapter->NVMRdmWrmLock);
- if(!lowPwrAbortMsg)
+ if (!lowPwrAbortMsg)
up(&Adapter->LowPowerModeSync);
- stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE;//NACK- device access is going on.
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "HOST IS NACKING Idle mode To F/W!!!!!!!!");
+ stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE; /* NACK- device access is going on. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "HOST IS NACKING Idle mode To F/W!!!!!!!!");
Adapter->bPreparingForLowPowerMode = FALSE;
- }
- else
- {
- stIdleResponse.szData[1] = TARGET_CAN_GO_TO_IDLE_MODE; //2;//Idle ACK
+ } else {
+ stIdleResponse.szData[1] = TARGET_CAN_GO_TO_IDLE_MODE; /* 2; Idle ACK */
Adapter->StatisticsPointer = 0;
/* Wait for the LED to TURN OFF before sending ACK response */
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
INT iRetVal = 0;
/* Wake the LED Thread with IDLEMODE_ENTER State */
Adapter->DriverState = LOWPOWER_MODE_ENTER;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"LED Thread is Running..Hence Setting LED Event as IDLEMODE_ENTER jiffies:%ld",jiffies);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LED Thread is Running..Hence Setting LED Event as IDLEMODE_ENTER jiffies:%ld", jiffies);
wake_up(&Adapter->LEDInfo.notify_led_event);
/* Wait for 1 SEC for LED to OFF */
- iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, \
- Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000));
-
+ iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000));
/* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */
- if(iRetVal <= 0)
- {
- stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE;//NACK- device access is going on.
+ if (iRetVal <= 0) {
+ stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE; /* NACK- device access is going on. */
Adapter->DriverState = NORMAL_OPERATION;
wake_up(&Adapter->LEDInfo.notify_led_event);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "NACKING Idle mode as time out happen from LED side!!!!!!!!");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "NACKING Idle mode as time out happen from LED side!!!!!!!!");
}
}
- if(stIdleResponse.szData[1] == TARGET_CAN_GO_TO_IDLE_MODE)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"ACKING IDLE MODE !!!!!!!!!");
+
+ if (stIdleResponse.szData[1] == TARGET_CAN_GO_TO_IDLE_MODE) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "ACKING IDLE MODE !!!!!!!!!");
down(&Adapter->rdmwrmsync);
Adapter->bPreparingForLowPowerMode = TRUE;
up(&Adapter->rdmwrmsync);
- //Killing all URBS.
- if(Adapter->bDoSuspend == TRUE)
+ /* Killing all URBS. */
+ if (Adapter->bDoSuspend == TRUE)
Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
-
- }
- else
- {
+ } else {
Adapter->bPreparingForLowPowerMode = FALSE;
}
- if(!NVMAccess)
+ if (!NVMAccess)
up(&Adapter->NVMRdmWrmLock);
- if(!lowPwrAbortMsg)
+ if (!lowPwrAbortMsg)
up(&Adapter->LowPowerModeSync);
-
}
- status = CopyBufferToControlPacket(Adapter,&stIdleResponse);
- if((status != STATUS_SUCCESS))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"fail to send the Idle mode Request \n");
+
+ status = CopyBufferToControlPacket(Adapter, &stIdleResponse);
+ if ((status != STATUS_SUCCESS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "fail to send the Idle mode Request\n");
Adapter->bPreparingForLowPowerMode = FALSE;
StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
}
do_gettimeofday(&tv);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "IdleMode Msg submitter to Q :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000);
-
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "IdleMode Msg submitter to Q :%ld ms", tv.tv_sec * 1000 + tv.tv_usec / 1000);
}
/******************************************************************
@@ -765,307 +681,264 @@ void SendIdleModeResponse(PMINI_ADAPTER Adapter)
*******************************************************************/
VOID DumpPackInfo(PMINI_ADAPTER Adapter)
{
-
- UINT uiLoopIndex = 0;
+ UINT uiLoopIndex = 0;
UINT uiIndex = 0;
UINT uiClsfrIndex = 0;
S_CLASSIFIER_RULE *pstClassifierEntry = NULL;
- for(uiLoopIndex=0;uiLoopIndex<NO_OF_QUEUES;uiLoopIndex++)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"*********** Showing Details Of Queue %d***** ******",uiLoopIndex);
- if(FALSE == Adapter->PackInfo[uiLoopIndex].bValid)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bValid is FALSE for %X index\n",uiLoopIndex);
+ for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "*********** Showing Details Of Queue %d***** ******", uiLoopIndex);
+ if (FALSE == Adapter->PackInfo[uiLoopIndex].bValid) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bValid is FALSE for %X index\n", uiLoopIndex);
continue;
}
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," Dumping SF Rule Entry For SFID %lX \n",Adapter->PackInfo[uiLoopIndex].ulSFID);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," ucDirection %X \n",Adapter->PackInfo[uiLoopIndex].ucDirection);
- if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Ipv6 Service Flow \n");
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, " Dumping SF Rule Entry For SFID %lX\n", Adapter->PackInfo[uiLoopIndex].ulSFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, " ucDirection %X\n", Adapter->PackInfo[uiLoopIndex].ucDirection);
+
+ if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Ipv6 Service Flow\n");
else
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Ipv4 Service Flow \n");
- }
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," SF Traffic Priority %X \n",Adapter->PackInfo[uiLoopIndex].u8TrafficPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Ipv4 Service Flow\n");
- for(uiClsfrIndex=0;uiClsfrIndex<MAX_CLASSIFIERS;uiClsfrIndex++)
- {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SF Traffic Priority %X\n", Adapter->PackInfo[uiLoopIndex].u8TrafficPriority);
+
+ for (uiClsfrIndex = 0; uiClsfrIndex < MAX_CLASSIFIERS; uiClsfrIndex++) {
pstClassifierEntry = &Adapter->astClassifierTable[uiClsfrIndex];
- if(!pstClassifierEntry->bUsed)
+ if (!pstClassifierEntry->bUsed)
continue;
- if(pstClassifierEntry->ulSFID != Adapter->PackInfo[uiLoopIndex].ulSFID)
+ if (pstClassifierEntry->ulSFID != Adapter->PackInfo[uiLoopIndex].ulSFID)
continue;
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X Classifier Rule ID : %X\n",uiClsfrIndex,pstClassifierEntry->uiClassifierRuleIndex);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X usVCID_Value : %X\n",uiClsfrIndex,pstClassifierEntry->usVCID_Value);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bProtocolValid : %X\n",uiClsfrIndex,pstClassifierEntry->bProtocolValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bTOSValid : %X\n",uiClsfrIndex,pstClassifierEntry->bTOSValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bDestIpValid : %X\n",uiClsfrIndex,pstClassifierEntry->bDestIpValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bSrcIpValid : %X\n",uiClsfrIndex,pstClassifierEntry->bSrcIpValid);
-
-
- for(uiIndex=0;uiIndex<MAX_PORT_RANGE;uiIndex++)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusSrcPortRangeLo:%X\n",pstClassifierEntry->usSrcPortRangeLo[uiIndex]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusSrcPortRangeHi:%X\n",pstClassifierEntry->usSrcPortRangeHi[uiIndex]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusDestPortRangeLo:%X\n",pstClassifierEntry->usDestPortRangeLo[uiIndex]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusDestPortRangeHi:%X\n",pstClassifierEntry->usDestPortRangeHi[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X Classifier Rule ID : %X\n", uiClsfrIndex, pstClassifierEntry->uiClassifierRuleIndex);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X usVCID_Value : %X\n", uiClsfrIndex, pstClassifierEntry->usVCID_Value);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bProtocolValid : %X\n", uiClsfrIndex, pstClassifierEntry->bProtocolValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bTOSValid : %X\n", uiClsfrIndex, pstClassifierEntry->bTOSValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bDestIpValid : %X\n", uiClsfrIndex, pstClassifierEntry->bDestIpValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bSrcIpValid : %X\n", uiClsfrIndex, pstClassifierEntry->bSrcIpValid);
+
+ for (uiIndex = 0; uiIndex < MAX_PORT_RANGE; uiIndex++) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusSrcPortRangeLo:%X\n", pstClassifierEntry->usSrcPortRangeLo[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusSrcPortRangeHi:%X\n", pstClassifierEntry->usSrcPortRangeHi[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusDestPortRangeLo:%X\n", pstClassifierEntry->usDestPortRangeLo[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusDestPortRangeHi:%X\n", pstClassifierEntry->usDestPortRangeHi[uiIndex]);
}
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," \tucIPSourceAddressLength : 0x%x\n",pstClassifierEntry->ucIPSourceAddressLength);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tucIPDestinationAddressLength : 0x%x\n",pstClassifierEntry->ucIPDestinationAddressLength);
- for(uiIndex=0;uiIndex<pstClassifierEntry->ucIPSourceAddressLength;uiIndex++)
- {
- if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulSrcIpAddr :\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucIPSourceAddressLength : 0x%x\n", pstClassifierEntry->ucIPSourceAddressLength);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucIPDestinationAddressLength : 0x%x\n", pstClassifierEntry->ucIPDestinationAddressLength);
+ for (uiIndex = 0; uiIndex < pstClassifierEntry->ucIPSourceAddressLength; uiIndex++) {
+ if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulSrcIpAddr :\n");
DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Addr);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulSrcIpMask :\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulSrcIpMask :\n");
DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Mask);
- }
- else
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulSrcIpAddr:%lX\n",pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[uiIndex]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulSrcIpMask:%lX\n",pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[uiIndex]);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulSrcIpAddr:%lX\n", pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulSrcIpMask:%lX\n", pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[uiIndex]);
}
}
- for(uiIndex=0;uiIndex<pstClassifierEntry->ucIPDestinationAddressLength;uiIndex++)
- {
- if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6)
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulDestIpAddr :\n");
+
+ for (uiIndex = 0; uiIndex < pstClassifierEntry->ucIPDestinationAddressLength; uiIndex++) {
+ if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulDestIpAddr :\n");
DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Addr);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulDestIpMask :\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulDestIpMask :\n");
DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Mask);
-
- }
- else
- {
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulDestIpAddr:%lX\n",pstClassifierEntry->stDestIpAddress.ulIpv4Addr[uiIndex]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulDestIpMask:%lX\n",pstClassifierEntry->stDestIpAddress.ulIpv4Mask[uiIndex]);
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulDestIpAddr:%lX\n", pstClassifierEntry->stDestIpAddress.ulIpv4Addr[uiIndex]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulDestIpMask:%lX\n", pstClassifierEntry->stDestIpAddress.ulIpv4Mask[uiIndex]);
}
}
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tucProtocol:0x%X\n",pstClassifierEntry->ucProtocol[0]);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tu8ClassifierRulePriority:%X\n",pstClassifierEntry->u8ClassifierRulePriority);
-
-
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucProtocol:0x%X\n", pstClassifierEntry->ucProtocol[0]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tu8ClassifierRulePriority:%X\n", pstClassifierEntry->u8ClassifierRulePriority);
}
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"ulSFID:%lX\n",Adapter->PackInfo[uiLoopIndex].ulSFID);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"usVCID_Value:%X\n",Adapter->PackInfo[uiLoopIndex].usVCID_Value);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"PhsEnabled: 0x%X\n",Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiThreshold:%X\n",Adapter->PackInfo[uiLoopIndex].uiThreshold);
-
-
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bValid:%X\n",Adapter->PackInfo[uiLoopIndex].bValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bActive:%X\n",Adapter->PackInfo[uiLoopIndex].bActive);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"ActivateReqSent: %x", Adapter->PackInfo[uiLoopIndex].bActivateRequestSent);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"u8QueueType:%X\n",Adapter->PackInfo[uiLoopIndex].u8QueueType);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiMaxBucketSize:%X\n",Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiPerSFTxResourceCount:%X\n",atomic_read(&Adapter->PackInfo[uiLoopIndex].uiPerSFTxResourceCount));
- //DumpDebug(DUMP_INFO,(" bCSSupport:%X\n",Adapter->PackInfo[uiLoopIndex].bCSSupport));
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"CurrQueueDepthOnTarget: %x\n", Adapter->PackInfo[uiLoopIndex].uiCurrentQueueDepthOnTarget);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentBytesOnHost:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentBytesOnHost);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentPacketsOnHost:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentPacketsOnHost);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiDroppedCountBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiDroppedCountBytes);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiDroppedCountPackets:%X\n",Adapter->PackInfo[uiLoopIndex].uiDroppedCountPackets);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiSentBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiSentBytes);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiSentPackets:%X\n",Adapter->PackInfo[uiLoopIndex].uiSentPackets);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentDrainRate:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentDrainRate);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiThisPeriodSentBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiThisPeriodSentBytes);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"liDrainCalculated:%llX\n",Adapter->PackInfo[uiLoopIndex].liDrainCalculated);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentTokenCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentTokenCount);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"liLastUpdateTokenAt:%llX\n",Adapter->PackInfo[uiLoopIndex].liLastUpdateTokenAt);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiMaxAllowedRate:%X\n",Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiPendedLast:%X\n",Adapter->PackInfo[uiLoopIndex].uiPendedLast);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"NumOfPacketsSent:%X\n",Adapter->PackInfo[uiLoopIndex].NumOfPacketsSent);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Direction: %x\n", Adapter->PackInfo[uiLoopIndex].ucDirection);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CID: %x\n", Adapter->PackInfo[uiLoopIndex].usCID);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ProtocolValid: %x\n", Adapter->PackInfo[uiLoopIndex].bProtocolValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "TOSValid: %x\n", Adapter->PackInfo[uiLoopIndex].bTOSValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "DestIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bDestIpValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SrcIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bSrcIpValid);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActiveSet: %x\n", Adapter->PackInfo[uiLoopIndex].bActiveSet);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AdmittedSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAdmittedSet);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AuthzSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAuthorizedSet);
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ClassifyPrority: %x\n", Adapter->PackInfo[uiLoopIndex].bClassifierPriority);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxLatency: %x\n",Adapter->PackInfo[uiLoopIndex].uiMaxLatency);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ServiceClassName: %x %x %x %x\n",Adapter->PackInfo[uiLoopIndex].ucServiceClassName[0],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[1],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[2],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[3]);
-// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bHeaderSuppressionEnabled :%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
-// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalTxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalTxBytes);
-// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalRxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalRxBytes);
-// DumpDebug(DUMP_INFO,(" uiRanOutOfResCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiRanOutOfResCount));
- }
-
- for(uiLoopIndex = 0 ; uiLoopIndex < MIBS_MAX_HIST_ENTRIES ; uiLoopIndex++)
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Adapter->aRxPktSizeHist[%x] = %x\n",uiLoopIndex,Adapter->aRxPktSizeHist[uiLoopIndex]);
-
- for(uiLoopIndex = 0 ; uiLoopIndex < MIBS_MAX_HIST_ENTRIES ; uiLoopIndex++)
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Adapter->aTxPktSizeHist[%x] = %x\n",uiLoopIndex,Adapter->aTxPktSizeHist[uiLoopIndex]);
-
-
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ulSFID:%lX\n", Adapter->PackInfo[uiLoopIndex].ulSFID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "usVCID_Value:%X\n", Adapter->PackInfo[uiLoopIndex].usVCID_Value);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "PhsEnabled: 0x%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiThreshold:%X\n", Adapter->PackInfo[uiLoopIndex].uiThreshold);
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bValid:%X\n", Adapter->PackInfo[uiLoopIndex].bValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bActive:%X\n", Adapter->PackInfo[uiLoopIndex].bActive);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActivateReqSent: %x", Adapter->PackInfo[uiLoopIndex].bActivateRequestSent);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "u8QueueType:%X\n", Adapter->PackInfo[uiLoopIndex].u8QueueType);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxBucketSize:%X\n", Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiPerSFTxResourceCount:%X\n", atomic_read(&Adapter->PackInfo[uiLoopIndex].uiPerSFTxResourceCount));
+ /* DumpDebug(DUMP_INFO,("bCSSupport:%X\n",Adapter->PackInfo[uiLoopIndex].bCSSupport)); */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CurrQueueDepthOnTarget: %x\n", Adapter->PackInfo[uiLoopIndex].uiCurrentQueueDepthOnTarget);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentBytesOnHost:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentBytesOnHost);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentPacketsOnHost:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentPacketsOnHost);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiDroppedCountBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiDroppedCountBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiDroppedCountPackets:%X\n", Adapter->PackInfo[uiLoopIndex].uiDroppedCountPackets);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiSentBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiSentBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiSentPackets:%X\n", Adapter->PackInfo[uiLoopIndex].uiSentPackets);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentDrainRate:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentDrainRate);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiThisPeriodSentBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiThisPeriodSentBytes);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "liDrainCalculated:%llX\n", Adapter->PackInfo[uiLoopIndex].liDrainCalculated);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentTokenCount:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentTokenCount);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "liLastUpdateTokenAt:%llX\n", Adapter->PackInfo[uiLoopIndex].liLastUpdateTokenAt);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxAllowedRate:%X\n", Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiPendedLast:%X\n", Adapter->PackInfo[uiLoopIndex].uiPendedLast);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "NumOfPacketsSent:%X\n", Adapter->PackInfo[uiLoopIndex].NumOfPacketsSent);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Direction: %x\n", Adapter->PackInfo[uiLoopIndex].ucDirection);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CID: %x\n", Adapter->PackInfo[uiLoopIndex].usCID);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ProtocolValid: %x\n", Adapter->PackInfo[uiLoopIndex].bProtocolValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "TOSValid: %x\n", Adapter->PackInfo[uiLoopIndex].bTOSValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "DestIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bDestIpValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SrcIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bSrcIpValid);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActiveSet: %x\n", Adapter->PackInfo[uiLoopIndex].bActiveSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AdmittedSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAdmittedSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AuthzSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAuthorizedSet);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ClassifyPrority: %x\n", Adapter->PackInfo[uiLoopIndex].bClassifierPriority);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxLatency: %x\n", Adapter->PackInfo[uiLoopIndex].uiMaxLatency);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ServiceClassName: %x %x %x %x\n", Adapter->PackInfo[uiLoopIndex].ucServiceClassName[0], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[1], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[2], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[3]);
+/* BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bHeaderSuppressionEnabled :%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
+ * BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalTxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalTxBytes);
+ * BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalRxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalRxBytes);
+ * DumpDebug(DUMP_INFO,(" uiRanOutOfResCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiRanOutOfResCount));
+ */
+ }
+
+ for (uiLoopIndex = 0; uiLoopIndex < MIBS_MAX_HIST_ENTRIES; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Adapter->aRxPktSizeHist[%x] = %x\n", uiLoopIndex, Adapter->aRxPktSizeHist[uiLoopIndex]);
+
+ for (uiLoopIndex = 0; uiLoopIndex < MIBS_MAX_HIST_ENTRIES; uiLoopIndex++)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Adapter->aTxPktSizeHist[%x] = %x\n", uiLoopIndex, Adapter->aTxPktSizeHist[uiLoopIndex]);
return;
-
-
}
int reset_card_proc(PMINI_ADAPTER ps_adapter)
{
int retval = STATUS_SUCCESS;
-
- PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
unsigned int value = 0, uiResetValue = 0;
- psIntfAdapter = ((PS_INTERFACE_ADAPTER)(ps_adapter->pvInterfaceAdapter)) ;
-
+ psIntfAdapter = ((PS_INTERFACE_ADAPTER)(ps_adapter->pvInterfaceAdapter));
ps_adapter->bDDRInitDone = FALSE;
- if(ps_adapter->chip_id >= T3LPB)
- {
- //SYS_CFG register is write protected hence for modifying this reg value, it should be read twice before
- rdmalt(ps_adapter,SYS_CFG, &value, sizeof(value));
- rdmalt(ps_adapter,SYS_CFG, &value, sizeof(value));
+ if (ps_adapter->chip_id >= T3LPB) {
+ /* SYS_CFG register is write protected hence for modifying this reg value, it should be read twice before */
+ rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
+ rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
- //making bit[6...5] same as was before f/w download. this setting force the h/w to
- //re-populated the SP RAM area with the string descriptor .
- value = value | (ps_adapter->syscfgBefFwDld & 0x00000060) ;
+ /* making bit[6...5] same as was before f/w download. this setting force the h/w to */
+ /* re-populated the SP RAM area with the string descriptor. */
+ value = value | (ps_adapter->syscfgBefFwDld & 0x00000060);
wrmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
}
- //killing all submitted URBs.
- psIntfAdapter->psAdapter->StopAllXaction = TRUE ;
+ /* killing all submitted URBs. */
+ psIntfAdapter->psAdapter->StopAllXaction = TRUE;
Bcm_kill_all_URBs(psIntfAdapter);
/* Reset the UMA-B Device */
- if(ps_adapter->chip_id >= T3LPB)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reseting UMA-B \n");
+ if (ps_adapter->chip_id >= T3LPB) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reseting UMA-B\n");
retval = usb_reset_device(psIntfAdapter->udev);
+ psIntfAdapter->psAdapter->StopAllXaction = FALSE;
- psIntfAdapter->psAdapter->StopAllXaction = FALSE ;
-
- if(retval != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reset failed with ret value :%d", retval);
+ if (retval != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reset failed with ret value :%d", retval);
goto err_exit;
}
+
if (ps_adapter->chip_id == BCS220_2 ||
ps_adapter->chip_id == BCS220_2BC ||
ps_adapter->chip_id == BCS250_BC ||
- ps_adapter->chip_id == BCS220_3)
- {
- retval = rdmalt(ps_adapter,HPM_CONFIG_LDO145, &value, sizeof(value));
- if( retval < 0)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"read failed with status :%d",retval);
+ ps_adapter->chip_id == BCS220_3) {
+
+ retval = rdmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval);
goto err_exit;
}
- //setting 0th bit
+ /* setting 0th bit */
value |= (1<<0);
retval = wrmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value));
- if( retval < 0)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval);
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
goto err_exit;
}
}
-
- }
- else
- {
- retval = rdmalt(ps_adapter,0x0f007018, &value, sizeof(value));
- if( retval < 0) {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"read failed with status :%d",retval);
+ } else {
+ retval = rdmalt(ps_adapter, 0x0f007018, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval);
goto err_exit;
}
- value&=(~(1<<16));
- retval= wrmalt(ps_adapter, 0x0f007018, &value, sizeof(value)) ;
- if( retval < 0) {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval);
+ value &= (~(1<<16));
+ retval = wrmalt(ps_adapter, 0x0f007018, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
goto err_exit;
}
- // Toggling the GPIO 8, 9
+ /* Toggling the GPIO 8, 9 */
value = 0;
retval = wrmalt(ps_adapter, GPIO_OUTPUT_REGISTER, &value, sizeof(value));
- if(retval < 0) {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval);
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
goto err_exit;
}
value = 0x300;
- retval = wrmalt(ps_adapter, GPIO_MODE_REGISTER, &value, sizeof(value)) ;
- if(retval < 0) {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval);
+ retval = wrmalt(ps_adapter, GPIO_MODE_REGISTER, &value, sizeof(value));
+ if (retval < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval);
goto err_exit;
}
mdelay(50);
}
- //ps_adapter->downloadDDR = false;
-
- if(ps_adapter->bFlashBoot)
- {
- //In flash boot mode MIPS state register has reverse polarity.
- // So just or with setting bit 30.
- //Make the MIPS in Reset state.
+ /* ps_adapter->downloadDDR = false; */
+ if (ps_adapter->bFlashBoot) {
+ /* In flash boot mode MIPS state register has reverse polarity.
+ * So just or with setting bit 30.
+ * Make the MIPS in Reset state.
+ */
rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue));
-
- uiResetValue |=(1<<30);
+ uiResetValue |= (1<<30);
wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue));
}
- if(ps_adapter->chip_id >= T3LPB)
- {
+ if (ps_adapter->chip_id >= T3LPB) {
uiResetValue = 0;
- //
- // WA for SYSConfig Issue.
- // Read SYSCFG Twice to make it writable.
- //
+ /*
+ * WA for SYSConfig Issue.
+ * Read SYSCFG Twice to make it writable.
+ */
rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue));
- if(uiResetValue & (1<<4))
- {
+ if (uiResetValue & (1<<4)) {
uiResetValue = 0;
- rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue));//2nd read to make it writable.
+ rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue)); /* 2nd read to make it writable. */
uiResetValue &= (~(1<<4));
- wrmalt(ps_adapter,SYS_CFG, &uiResetValue, sizeof(uiResetValue));
+ wrmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue));
}
-
}
uiResetValue = 0;
wrmalt(ps_adapter, 0x0f01186c, &uiResetValue, sizeof(uiResetValue));
-err_exit :
- psIntfAdapter->psAdapter->StopAllXaction = FALSE ;
+err_exit:
+ psIntfAdapter->psAdapter->StopAllXaction = FALSE;
return retval;
}
-int run_card_proc(PMINI_ADAPTER ps_adapter )
+int run_card_proc(PMINI_ADAPTER ps_adapter)
{
- unsigned int value=0;
+ unsigned int value = 0;
{
-
- if(rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%d\n", __FUNCTION__, __LINE__);
+ if (rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%d\n", __func__, __LINE__);
return STATUS_FAILURE;
}
- if(ps_adapter->bFlashBoot)
- {
-
- value&=(~(1<<30));
- }
+ if (ps_adapter->bFlashBoot)
+ value &= (~(1<<30));
else
- {
- value |=(1<<30);
- }
+ value |= (1<<30);
- if(wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%d\n", __FUNCTION__, __LINE__);
+ if (wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%d\n", __func__, __LINE__);
return STATUS_FAILURE;
}
}
@@ -1074,104 +947,87 @@ int run_card_proc(PMINI_ADAPTER ps_adapter )
int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter)
{
-
int status;
UINT value = 0;
/*
- * Create the threads first and then download the
- * Firm/DDR Settings..
- */
-
+ * Create the threads first and then download the
+ * Firm/DDR Settings..
+ */
status = create_worker_threads(ps_adapter);
- if (status<0)
+ if (status < 0)
return status;
- /*
- * For Downloading the Firm, parse the cfg file first.
- */
- status = bcm_parse_target_params (ps_adapter);
- if(status){
+ status = bcm_parse_target_params(ps_adapter);
+ if (status)
return status;
- }
- if(ps_adapter->chip_id >= T3LPB)
- {
- rdmalt(ps_adapter, SYS_CFG, &value, sizeof (value));
- ps_adapter->syscfgBefFwDld = value ;
- if((value & 0x60)== 0)
- {
+ if (ps_adapter->chip_id >= T3LPB) {
+ rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value));
+ ps_adapter->syscfgBefFwDld = value;
+
+ if ((value & 0x60) == 0)
ps_adapter->bFlashBoot = TRUE;
- }
}
reset_card_proc(ps_adapter);
- //Initializing the NVM.
+ /* Initializing the NVM. */
BcmInitNVM(ps_adapter);
status = ddr_init(ps_adapter);
- if(status)
- {
+ if (status) {
pr_err(DRV_NAME "ddr_init Failed\n");
return status;
}
/* Download cfg file */
status = buffDnldVerify(ps_adapter,
- (PUCHAR)ps_adapter->pstargetparams,
- sizeof(STARGETPARAMS),
- CONFIG_BEGIN_ADDR);
- if(status)
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Error downloading CFG file");
+ (PUCHAR)ps_adapter->pstargetparams,
+ sizeof(STARGETPARAMS),
+ CONFIG_BEGIN_ADDR);
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Error downloading CFG file");
goto OUT;
}
- if(register_networkdev(ps_adapter))
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Netdevice failed. Cleanup needs to be performed.");
+ if (register_networkdev(ps_adapter)) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Netdevice failed. Cleanup needs to be performed.");
return -EIO;
}
- if(FALSE == ps_adapter->AutoFirmDld)
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoFirmDld Disabled in CFG File..\n");
- //If Auto f/w download is disable, register the control interface,
- //register the control interface after the mailbox.
- if(register_control_device_interface(ps_adapter) < 0)
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Control Device failed. Cleanup needs to be performed.");
+ if (FALSE == ps_adapter->AutoFirmDld) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoFirmDld Disabled in CFG File..\n");
+ /* If Auto f/w download is disable, register the control interface, */
+ /* register the control interface after the mailbox. */
+ if (register_control_device_interface(ps_adapter) < 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Control Device failed. Cleanup needs to be performed.");
return -EIO;
}
-
return STATUS_SUCCESS;
}
/*
- * Do the LED Settings here. It will be used by the Firmware Download
- * Thread.
- */
+ * Do the LED Settings here. It will be used by the Firmware Download
+ * Thread.
+ */
/*
- * 1. If the LED Settings fails, do not stop and do the Firmware download.
- * 2. This init would happened only if the cfg file is present, else
- * call from the ioctl context.
- */
-
- status = InitLedSettings (ps_adapter);
+ * 1. If the LED Settings fails, do not stop and do the Firmware download.
+ * 2. This init would happened only if the cfg file is present, else
+ * call from the ioctl context.
+ */
- if(status)
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_PRINTK, 0, 0,"INIT LED FAILED\n");
+ status = InitLedSettings(ps_adapter);
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_PRINTK, 0, 0, "INIT LED FAILED\n");
return status;
}
- if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+
+ if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
ps_adapter->DriverState = DRIVER_INIT;
wake_up(&ps_adapter->LEDInfo.notify_led_event);
}
- if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
ps_adapter->DriverState = FW_DOWNLOAD;
wake_up(&ps_adapter->LEDInfo.notify_led_event);
}
@@ -1180,37 +1036,32 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter)
wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
- if(ps_adapter->eNVMType == NVM_FLASH)
- {
+ if (ps_adapter->eNVMType == NVM_FLASH) {
status = PropagateCalParamsFromFlashToMemory(ps_adapter);
- if(status)
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL," Propagation of Cal param failed .." );
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Propagation of Cal param failed ..");
goto OUT;
}
}
/* Download Firmare */
- if ((status = BcmFileDownload( ps_adapter, BIN_FILE, FIRMWARE_BEGIN_ADDR)))
- {
- BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Firmware File is present... \n");
+ status = BcmFileDownload(ps_adapter, BIN_FILE, FIRMWARE_BEGIN_ADDR);
+ if (status != 0) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Firmware File is present...\n");
goto OUT;
}
status = run_card_proc(ps_adapter);
- if(status)
- {
- BCM_DEBUG_PRINT (ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "run_card_proc Failed\n");
+ if (status) {
+ BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "run_card_proc Failed\n");
goto OUT;
}
-
ps_adapter->fw_download_done = TRUE;
mdelay(10);
OUT:
- if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
ps_adapter->DriverState = FW_DOWNLOAD_DONE;
wake_up(&ps_adapter->LEDInfo.notify_led_event);
}
@@ -1218,41 +1069,39 @@ OUT:
return status;
}
-
static int bcm_parse_target_params(PMINI_ADAPTER Adapter)
{
- struct file *flp=NULL;
- mm_segment_t oldfs={0};
+ struct file *flp = NULL;
+ mm_segment_t oldfs = {0};
char *buff;
int len = 0;
- loff_t pos = 0;
+ loff_t pos = 0;
- buff=kmalloc(BUFFER_1K, GFP_KERNEL);
- if(!buff)
- {
+ buff = kmalloc(BUFFER_1K, GFP_KERNEL);
+ if (!buff)
return -ENOMEM;
- }
- if((Adapter->pstargetparams =
- kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL)) == NULL)
- {
+
+ Adapter->pstargetparams = kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL);
+ if (Adapter->pstargetparams == NULL) {
kfree(buff);
return -ENOMEM;
}
- flp=open_firmware_file(Adapter, CFG_FILE);
- if(!flp) {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "NOT ABLE TO OPEN THE %s FILE \n", CFG_FILE);
+
+ flp = open_firmware_file(Adapter, CFG_FILE);
+ if (!flp) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "NOT ABLE TO OPEN THE %s FILE\n", CFG_FILE);
kfree(buff);
kfree(Adapter->pstargetparams);
Adapter->pstargetparams = NULL;
return -ENOENT;
}
- oldfs=get_fs(); set_fs(get_ds());
- len=vfs_read(flp, (void __user __force *)buff, BUFFER_1K, &pos);
+ oldfs = get_fs();
+ set_fs(get_ds());
+ len = vfs_read(flp, (void __user __force *)buff, BUFFER_1K, &pos);
set_fs(oldfs);
- if(len != sizeof(STARGETPARAMS))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Mismatch in Target Param Structure!\n");
+ if (len != sizeof(STARGETPARAMS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Mismatch in Target Param Structure!\n");
kfree(buff);
kfree(Adapter->pstargetparams);
Adapter->pstargetparams = NULL;
@@ -1266,122 +1115,97 @@ static int bcm_parse_target_params(PMINI_ADAPTER Adapter)
* Values in Adapter->pstargetparams are in network byte order
*/
memcpy(Adapter->pstargetparams, buff, sizeof(STARGETPARAMS));
- kfree (buff);
+ kfree(buff);
beceem_parse_target_struct(Adapter);
return STATUS_SUCCESS;
}
void beceem_parse_target_struct(PMINI_ADAPTER Adapter)
{
- UINT uiHostDrvrCfg6 =0, uiEEPROMFlag = 0;
+ UINT uiHostDrvrCfg6 = 0, uiEEPROMFlag = 0;
- if(ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE)
- {
+ if (ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE) {
pr_info(DRV_NAME ": AutoSyncup is Disabled\n");
Adapter->AutoSyncup = FALSE;
- }
- else
- {
+ } else {
pr_info(DRV_NAME ": AutoSyncup is Enabled\n");
- Adapter->AutoSyncup = TRUE;
+ Adapter->AutoSyncup = TRUE;
}
- if(ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_LINKUP_ENABLE)
- {
+ if (ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_LINKUP_ENABLE) {
pr_info(DRV_NAME ": Enabling autolink up");
Adapter->AutoLinkUp = TRUE;
- }
- else
- {
+ } else {
pr_info(DRV_NAME ": Disabling autolink up");
Adapter->AutoLinkUp = FALSE;
}
- // Setting the DDR Setting..
- Adapter->DDRSetting =
- (ntohl(Adapter->pstargetparams->HostDrvrConfig6) >>8)&0x0F;
- Adapter->ulPowerSaveMode =
- (ntohl(Adapter->pstargetparams->HostDrvrConfig6)>>12)&0x0F;
-
+ /* Setting the DDR Setting.. */
+ Adapter->DDRSetting = (ntohl(Adapter->pstargetparams->HostDrvrConfig6) >> 8)&0x0F;
+ Adapter->ulPowerSaveMode = (ntohl(Adapter->pstargetparams->HostDrvrConfig6)>>12)&0x0F;
pr_info(DRV_NAME ": DDR Setting: %x\n", Adapter->DDRSetting);
pr_info(DRV_NAME ": Power Save Mode: %lx\n", Adapter->ulPowerSaveMode);
- if(ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_FIRM_DOWNLOAD)
- {
- pr_info(DRV_NAME ": Enabling Auto Firmware Download\n");
- Adapter->AutoFirmDld = TRUE;
- }
- else
- {
- pr_info(DRV_NAME ": Disabling Auto Firmware Download\n");
- Adapter->AutoFirmDld = FALSE;
- }
+ if (ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_FIRM_DOWNLOAD) {
+ pr_info(DRV_NAME ": Enabling Auto Firmware Download\n");
+ Adapter->AutoFirmDld = TRUE;
+ } else {
+ pr_info(DRV_NAME ": Disabling Auto Firmware Download\n");
+ Adapter->AutoFirmDld = FALSE;
+ }
uiHostDrvrCfg6 = ntohl(Adapter->pstargetparams->HostDrvrConfig6);
Adapter->bMipsConfig = (uiHostDrvrCfg6>>20)&0x01;
- pr_info(DRV_NAME ": MIPSConfig : 0x%X\n",Adapter->bMipsConfig);
- //used for backward compatibility.
+ pr_info(DRV_NAME ": MIPSConfig : 0x%X\n", Adapter->bMipsConfig);
+ /* used for backward compatibility. */
Adapter->bDPLLConfig = (uiHostDrvrCfg6>>19)&0x01;
-
- Adapter->PmuMode= (uiHostDrvrCfg6 >> 24 ) & 0x03;
+ Adapter->PmuMode = (uiHostDrvrCfg6 >> 24) & 0x03;
pr_info(DRV_NAME ": PMU MODE: %x", Adapter->PmuMode);
- if((uiHostDrvrCfg6 >> HOST_BUS_SUSPEND_BIT ) & (0x01))
- {
- Adapter->bDoSuspend = TRUE;
- pr_info(DRV_NAME ": Making DoSuspend TRUE as per configFile");
- }
+ if ((uiHostDrvrCfg6 >> HOST_BUS_SUSPEND_BIT) & (0x01)) {
+ Adapter->bDoSuspend = TRUE;
+ pr_info(DRV_NAME ": Making DoSuspend TRUE as per configFile");
+ }
uiEEPROMFlag = ntohl(Adapter->pstargetparams->m_u32EEPROMFlag);
- pr_info(DRV_NAME ": uiEEPROMFlag : 0x%X\n",uiEEPROMFlag);
+ pr_info(DRV_NAME ": uiEEPROMFlag : 0x%X\n", uiEEPROMFlag);
Adapter->eNVMType = (NVM_TYPE)((uiEEPROMFlag>>4)&0x3);
-
Adapter->bStatusWrite = (uiEEPROMFlag>>6)&0x1;
-
Adapter->uiSectorSizeInCFG = 1024*(0xFFFF & ntohl(Adapter->pstargetparams->HostDrvrConfig4));
+ Adapter->bSectorSizeOverride = (bool) ((ntohl(Adapter->pstargetparams->HostDrvrConfig4))>>16)&0x1;
- Adapter->bSectorSizeOverride =(bool) ((ntohl(Adapter->pstargetparams->HostDrvrConfig4))>>16)&0x1;
-
- if(ntohl(Adapter->pstargetparams->m_u32PowerSavingModeOptions) &0x01)
+ if (ntohl(Adapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x01)
Adapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE;
- if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
+ if (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
doPowerAutoCorrection(Adapter);
-
}
static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter)
{
UINT reporting_mode;
- reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) &0x02 ;
+ reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x02;
psAdapter->bIsAutoCorrectEnabled = !((char)(psAdapter->ulPowerSaveMode >> 3) & 0x1);
- if(reporting_mode == TRUE)
- {
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"can't do suspen/resume as reporting mode is enable");
+ if (reporting_mode == TRUE) {
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "can't do suspen/resume as reporting mode is enable");
psAdapter->bDoSuspend = FALSE;
}
- if (psAdapter->bIsAutoCorrectEnabled && (psAdapter->chip_id >= T3LPB))
- {
- //If reporting mode is enable, switch PMU to PMC
+ if (psAdapter->bIsAutoCorrectEnabled && (psAdapter->chip_id >= T3LPB)) {
+ /* If reporting mode is enable, switch PMU to PMC */
{
psAdapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING;
- psAdapter->bDoSuspend =FALSE;
-
+ psAdapter->bDoSuspend = FALSE;
}
- //clearing space bit[15..12]
+ /* clearing space bit[15..12] */
psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl((0xF << 12)));
- //placing the power save mode option
+ /* placing the power save mode option */
psAdapter->pstargetparams->HostDrvrConfig6 |= htonl((psAdapter->ulPowerSaveMode << 12));
-
- }
- else if (psAdapter->bIsAutoCorrectEnabled == FALSE)
- {
-
- // remove the autocorrect disable bit set before dumping.
+ } else if (psAdapter->bIsAutoCorrectEnabled == FALSE) {
+ /* remove the autocorrect disable bit set before dumping. */
psAdapter->ulPowerSaveMode &= ~(1 << 3);
psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl(1 << 15));
- BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Using Forced User Choice: %lx\n", psAdapter->ulPowerSaveMode);
+ BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Using Forced User Choice: %lx\n", psAdapter->ulPowerSaveMode);
}
}
@@ -1392,63 +1216,56 @@ static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress)
unsigned int temp = 0;
unsigned char *pucmacaddr = kmalloc(MAC_ADDRESS_SIZE, GFP_KERNEL);
- if(!pucmacaddr)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "No Buffers to Read the EEPROM Address\n");
+ if (!pucmacaddr) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No Buffers to Read the EEPROM Address\n");
return NULL;
}
dwAddress |= 0x5b000000;
- status = wrmalt(Adapter, EEPROM_COMMAND_Q_REG,
- (PUINT)&dwAddress, sizeof(UINT));
- if(status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm Failed..\n");
+ status = wrmalt(Adapter, EEPROM_COMMAND_Q_REG, (PUINT)&dwAddress, sizeof(UINT));
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm Failed..\n");
kfree(pucmacaddr);
pucmacaddr = NULL;
goto OUT;
}
- for(i=0;i<MAC_ADDRESS_SIZE;i++)
- {
- status = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp,sizeof(temp));
- if(status != STATUS_SUCCESS)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm Failed..\n");
+
+ for (i = 0; i < MAC_ADDRESS_SIZE; i++) {
+ status = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp, sizeof(temp));
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm Failed..\n");
kfree(pucmacaddr);
pucmacaddr = NULL;
goto OUT;
}
pucmacaddr[i] = temp & 0xff;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"%x \n", pucmacaddr[i]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "%x\n", pucmacaddr[i]);
}
OUT:
return pucmacaddr;
}
#endif
-
static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount)
{
UINT uiIndex = 0;
- if(RWM_WRITE == rwFlag) {
- for(uiIndex =0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++) {
+ if (RWM_WRITE == rwFlag) {
+ for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++)
puiBuffer[uiIndex] = htonl(puiBuffer[uiIndex]);
- }
} else {
- for(uiIndex =0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++) {
+ for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++)
puiBuffer[uiIndex] = ntohl(puiBuffer[uiIndex]);
- }
}
}
-#define CACHE_ADDRESS_MASK 0x80000000
-#define UNCACHE_ADDRESS_MASK 0xa0000000
+#define CACHE_ADDRESS_MASK 0x80000000
+#define UNCACHE_ADDRESS_MASK 0xa0000000
int rdm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
{
return Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
- uiAddress, pucBuff, sSize);
+ uiAddress, pucBuff, sSize);
}
int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
@@ -1456,112 +1273,103 @@ int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
int iRetVal;
iRetVal = Adapter->interface_wrm(Adapter->pvInterfaceAdapter,
- uiAddress, pucBuff, sSize);
-
-
+ uiAddress, pucBuff, sSize);
return iRetVal;
}
-int wrmalt (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int wrmalt(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
{
convertEndian(RWM_WRITE, pucBuff, size);
return wrm(Adapter, uiAddress, (PUCHAR)pucBuff, size);
}
-int rdmalt (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int rdmalt(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
{
- INT uiRetVal =0;
+ INT uiRetVal = 0;
- uiRetVal = rdm(Adapter,uiAddress,(PUCHAR)pucBuff,size);
+ uiRetVal = rdm(Adapter, uiAddress, (PUCHAR)pucBuff, size);
convertEndian(RWM_READ, (PUINT)pucBuff, size);
return uiRetVal;
}
-
int wrmWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
{
- INT status = STATUS_SUCCESS ;
+ INT status = STATUS_SUCCESS;
down(&Adapter->rdmwrmsync);
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
status = -EACCES;
goto exit;
}
- status =wrm(Adapter, uiAddress, pucBuff, sSize);
-
+ status = wrm(Adapter, uiAddress, pucBuff, sSize);
exit:
up(&Adapter->rdmwrmsync);
- return status ;
+ return status;
}
-int wrmaltWithLock (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int wrmaltWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
{
int iRetVal = STATUS_SUCCESS;
down(&Adapter->rdmwrmsync);
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
+
iRetVal = -EACCES;
goto exit;
}
- iRetVal = wrmalt(Adapter,uiAddress,pucBuff,size);
-
+ iRetVal = wrmalt(Adapter, uiAddress, pucBuff, size);
exit:
up(&Adapter->rdmwrmsync);
return iRetVal;
}
-int rdmaltWithLock (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int rdmaltWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
{
- INT uiRetVal =STATUS_SUCCESS;
+ INT uiRetVal = STATUS_SUCCESS;
down(&Adapter->rdmwrmsync);
+ if ((Adapter->IdleMode == TRUE) ||
+ (Adapter->bShutStatus == TRUE) ||
+ (Adapter->bPreparingForLowPowerMode == TRUE)) {
- if((Adapter->IdleMode == TRUE) ||
- (Adapter->bShutStatus ==TRUE) ||
- (Adapter->bPreparingForLowPowerMode ==TRUE))
- {
uiRetVal = -EACCES;
goto exit;
}
- uiRetVal = rdmalt(Adapter,uiAddress, pucBuff, size);
-
+ uiRetVal = rdmalt(Adapter, uiAddress, pucBuff, size);
exit:
up(&Adapter->rdmwrmsync);
return uiRetVal;
}
-
static VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter)
{
- int clear_abort_pattern = 0,Status = 0;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
- //target has woken up From Shut Down
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n");
- Status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, (PUINT)&clear_abort_pattern, sizeof(clear_abort_pattern));
- if(Status)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"WRM to SW_ABORT_IDLEMODE_LOC failed with err:%d", Status);
+ int clear_abort_pattern = 0, Status = 0;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
+ /* target has woken up From Shut Down */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n");
+ Status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC, (PUINT)&clear_abort_pattern, sizeof(clear_abort_pattern));
+ if (Status) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "WRM to SW_ABORT_IDLEMODE_LOC failed with err:%d", Status);
return;
}
- if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
- {
+
+ if (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) {
msleep(100);
InterfaceHandleShutdownModeWakeup(Adapter);
msleep(100);
}
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
Adapter->DriverState = NO_NETWORK_ENTRY;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
@@ -1569,55 +1377,49 @@ static VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter)
Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
Adapter->bShutStatus = FALSE;
wake_up(&Adapter->lowpower_mode_wait_queue);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
}
static VOID SendShutModeResponse(PMINI_ADAPTER Adapter)
{
- CONTROL_MESSAGE stShutdownResponse;
- UINT NVMAccess = 0,lowPwrAbortMsg = 0;
+ CONTROL_MESSAGE stShutdownResponse;
+ UINT NVMAccess = 0, lowPwrAbortMsg = 0;
UINT Status = 0;
- memset (&stShutdownResponse, 0, sizeof(CONTROL_MESSAGE));
+ memset(&stShutdownResponse, 0, sizeof(CONTROL_MESSAGE));
stShutdownResponse.Leader.Status = LINK_UP_CONTROL_REQ;
- stShutdownResponse.Leader.PLength = 8;//8 bytes;
+ stShutdownResponse.Leader.PLength = 8; /* 8 bytes; */
stShutdownResponse.szData[0] = LINK_UP_ACK;
stShutdownResponse.szData[1] = LINK_SHUTDOWN_REQ_FROM_FIRMWARE;
/*********************************
- **down_trylock -
- ** if [ semaphore is available ]
- ** acquire semaphone and return value 0 ;
- ** else
- ** return non-zero value ;
- **
- ***********************************/
+ * down_trylock -
+ * if [ semaphore is available ]
+ * acquire semaphone and return value 0 ;
+ * else
+ * return non-zero value ;
+ *
+ ***********************************/
NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
+ lowPwrAbortMsg = down_trylock(&Adapter->LowPowerModeSync);
- lowPwrAbortMsg= down_trylock(&Adapter->LowPowerModeSync);
-
-
- if(NVMAccess || lowPwrAbortMsg|| atomic_read(&Adapter->TotalPacketCount))
- {
- if(!NVMAccess)
+ if (NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) {
+ if (!NVMAccess)
up(&Adapter->NVMRdmWrmLock);
- if(!lowPwrAbortMsg)
+ if (!lowPwrAbortMsg)
up(&Adapter->LowPowerModeSync);
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Device Access is going on NACK the Shut Down MODE\n");
- stShutdownResponse.szData[2] = SHUTDOWN_NACK_FROM_DRIVER;//NACK- device access is going on.
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Device Access is going on NACK the Shut Down MODE\n");
+ stShutdownResponse.szData[2] = SHUTDOWN_NACK_FROM_DRIVER; /* NACK- device access is going on. */
Adapter->bPreparingForLowPowerMode = FALSE;
- }
- else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Sending SHUTDOWN MODE ACK\n");
- stShutdownResponse.szData[2] = SHUTDOWN_ACK_FROM_DRIVER;//ShutDown ACK
+ } else {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Sending SHUTDOWN MODE ACK\n");
+ stShutdownResponse.szData[2] = SHUTDOWN_ACK_FROM_DRIVER; /* ShutDown ACK */
/* Wait for the LED to TURN OFF before sending ACK response */
- if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
- {
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
INT iRetVal = 0;
/* Wake the LED Thread with LOWPOWER_MODE_ENTER State */
@@ -1625,237 +1427,200 @@ static VOID SendShutModeResponse(PMINI_ADAPTER Adapter)
wake_up(&Adapter->LEDInfo.notify_led_event);
/* Wait for 1 SEC for LED to OFF */
- iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent,\
- Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000));
+ iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000));
/* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */
- if(iRetVal <= 0)
- {
- stShutdownResponse.szData[1] = SHUTDOWN_NACK_FROM_DRIVER;//NACK- device access is going on.
-
+ if (iRetVal <= 0) {
+ stShutdownResponse.szData[1] = SHUTDOWN_NACK_FROM_DRIVER; /* NACK- device access is going on. */
Adapter->DriverState = NO_NETWORK_ENTRY;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
}
- if(stShutdownResponse.szData[2] == SHUTDOWN_ACK_FROM_DRIVER)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"ACKING SHUTDOWN MODE !!!!!!!!!");
+ if (stShutdownResponse.szData[2] == SHUTDOWN_ACK_FROM_DRIVER) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ACKING SHUTDOWN MODE !!!!!!!!!");
down(&Adapter->rdmwrmsync);
Adapter->bPreparingForLowPowerMode = TRUE;
up(&Adapter->rdmwrmsync);
- //Killing all URBS.
- if(Adapter->bDoSuspend == TRUE)
+ /* Killing all URBS. */
+ if (Adapter->bDoSuspend == TRUE)
Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
- }
- else
- {
+ } else {
Adapter->bPreparingForLowPowerMode = FALSE;
}
- if(!NVMAccess)
+ if (!NVMAccess)
up(&Adapter->NVMRdmWrmLock);
- if(!lowPwrAbortMsg)
+ if (!lowPwrAbortMsg)
up(&Adapter->LowPowerModeSync);
}
- Status = CopyBufferToControlPacket(Adapter,&stShutdownResponse);
- if((Status != STATUS_SUCCESS))
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"fail to send the Idle mode Request \n");
- Adapter->bPreparingForLowPowerMode = FALSE;
+ Status = CopyBufferToControlPacket(Adapter, &stShutdownResponse);
+ if ((Status != STATUS_SUCCESS)) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "fail to send the Idle mode Request\n");
+ Adapter->bPreparingForLowPowerMode = FALSE;
StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
}
}
-
-static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter,PUCHAR pucBuffer)
+static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter, PUCHAR pucBuffer)
{
B_UINT32 uiResetValue = 0;
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
- if(*(pucBuffer+1) == COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW)
- {
+ if (*(pucBuffer+1) == COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW) {
HandleShutDownModeWakeup(Adapter);
- }
- else if(*(pucBuffer+1) == LINK_SHUTDOWN_REQ_FROM_FIRMWARE)
- {
- //Target wants to go to Shut Down Mode
- //InterfacePrepareForShutdown(Adapter);
- if(Adapter->chip_id == BCS220_2 ||
- Adapter->chip_id == BCS220_2BC ||
- Adapter->chip_id == BCS250_BC ||
- Adapter->chip_id == BCS220_3)
- {
- rdmalt(Adapter,HPM_CONFIG_MSW, &uiResetValue, 4);
+ } else if (*(pucBuffer+1) == LINK_SHUTDOWN_REQ_FROM_FIRMWARE) {
+ /* Target wants to go to Shut Down Mode */
+ /* InterfacePrepareForShutdown(Adapter); */
+ if (Adapter->chip_id == BCS220_2 ||
+ Adapter->chip_id == BCS220_2BC ||
+ Adapter->chip_id == BCS250_BC ||
+ Adapter->chip_id == BCS220_3) {
+
+ rdmalt(Adapter, HPM_CONFIG_MSW, &uiResetValue, 4);
uiResetValue |= (1<<17);
wrmalt(Adapter, HPM_CONFIG_MSW, &uiResetValue, 4);
}
SendShutModeResponse(Adapter);
- BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n");
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n");
}
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
return;
-
}
VOID ResetCounters(PMINI_ADAPTER Adapter)
{
-
- beceem_protocol_reset(Adapter);
-
+ beceem_protocol_reset(Adapter);
Adapter->CurrNumRecvDescs = 0;
- Adapter->PrevNumRecvDescs = 0;
- Adapter->LinkUpStatus = 0;
+ Adapter->PrevNumRecvDescs = 0;
+ Adapter->LinkUpStatus = 0;
Adapter->LinkStatus = 0;
- atomic_set(&Adapter->cntrlpktCnt,0);
- atomic_set (&Adapter->TotalPacketCount,0);
- Adapter->fw_download_done=FALSE;
+ atomic_set(&Adapter->cntrlpktCnt, 0);
+ atomic_set(&Adapter->TotalPacketCount, 0);
+ Adapter->fw_download_done = FALSE;
Adapter->LinkStatus = 0;
- Adapter->AutoLinkUp = FALSE;
+ Adapter->AutoLinkUp = FALSE;
Adapter->IdleMode = FALSE;
Adapter->bShutStatus = FALSE;
-
}
-S_CLASSIFIER_RULE *GetFragIPClsEntry(PMINI_ADAPTER Adapter,USHORT usIpIdentification,ULONG SrcIP)
+
+S_CLASSIFIER_RULE *GetFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG SrcIP)
{
- UINT uiIndex=0;
- for(uiIndex=0;uiIndex<MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES;uiIndex++)
- {
- if((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed)&&
- (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification)&&
- (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress== SrcIP)&&
+ UINT uiIndex = 0;
+ for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
+ if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress == SrcIP) &&
!Adapter->astFragmentedPktClassifierTable[uiIndex].bOutOfOrderFragment)
+
return Adapter->astFragmentedPktClassifierTable[uiIndex].pstMatchedClassifierEntry;
}
return NULL;
}
-void AddFragIPClsEntry(PMINI_ADAPTER Adapter,PS_FRAGMENTED_PACKET_INFO psFragPktInfo)
+void AddFragIPClsEntry(PMINI_ADAPTER Adapter, PS_FRAGMENTED_PACKET_INFO psFragPktInfo)
{
- UINT uiIndex=0;
- for(uiIndex=0;uiIndex<MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES;uiIndex++)
- {
- if(!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed)
- {
- memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex],psFragPktInfo,sizeof(S_FRAGMENTED_PACKET_INFO));
+ UINT uiIndex = 0;
+ for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
+ if (!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) {
+ memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex], psFragPktInfo, sizeof(S_FRAGMENTED_PACKET_INFO));
break;
}
}
-
}
-void DelFragIPClsEntry(PMINI_ADAPTER Adapter,USHORT usIpIdentification,ULONG SrcIp)
+void DelFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG SrcIp)
{
- UINT uiIndex=0;
- for(uiIndex=0;uiIndex<MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES;uiIndex++)
- {
- if((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed)&&
- (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification)&&
- (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress== SrcIp))
- memset(&Adapter->astFragmentedPktClassifierTable[uiIndex],0,sizeof(S_FRAGMENTED_PACKET_INFO));
+ UINT uiIndex = 0;
+ for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
+ if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
+ (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress == SrcIp))
+
+ memset(&Adapter->astFragmentedPktClassifierTable[uiIndex], 0, sizeof(S_FRAGMENTED_PACKET_INFO));
}
}
-void update_per_cid_rx (PMINI_ADAPTER Adapter)
+void update_per_cid_rx(PMINI_ADAPTER Adapter)
{
- UINT qindex = 0;
+ UINT qindex = 0;
- if((jiffies - Adapter->liDrainCalculated) < XSECONDS)
+ if ((jiffies - Adapter->liDrainCalculated) < XSECONDS)
return;
- for(qindex = 0; qindex < HiPriority; qindex++)
- {
- if(Adapter->PackInfo[qindex].ucDirection == 0)
- {
+ for (qindex = 0; qindex < HiPriority; qindex++) {
+ if (Adapter->PackInfo[qindex].ucDirection == 0) {
Adapter->PackInfo[qindex].uiCurrentRxRate =
(Adapter->PackInfo[qindex].uiCurrentRxRate +
- Adapter->PackInfo[qindex].uiThisPeriodRxBytes)/2;
+ Adapter->PackInfo[qindex].uiThisPeriodRxBytes) / 2;
Adapter->PackInfo[qindex].uiThisPeriodRxBytes = 0;
- }
- else
- {
+ } else {
Adapter->PackInfo[qindex].uiCurrentDrainRate =
(Adapter->PackInfo[qindex].uiCurrentDrainRate +
- Adapter->PackInfo[qindex].uiThisPeriodSentBytes)/2;
-
- Adapter->PackInfo[qindex].uiThisPeriodSentBytes=0;
+ Adapter->PackInfo[qindex].uiThisPeriodSentBytes) / 2;
+ Adapter->PackInfo[qindex].uiThisPeriodSentBytes = 0;
}
}
- Adapter->liDrainCalculated=jiffies;
+ Adapter->liDrainCalculated = jiffies;
}
-void update_per_sf_desc_cnts( PMINI_ADAPTER Adapter)
+
+void update_per_sf_desc_cnts(PMINI_ADAPTER Adapter)
{
INT iIndex = 0;
u32 uibuff[MAX_TARGET_DSX_BUFFERS];
- if(!atomic_read (&Adapter->uiMBupdate))
+ if (!atomic_read(&Adapter->uiMBupdate))
return;
- if(rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS)<0)
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed\n");
+ if (rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS) < 0) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm failed\n");
return;
}
- for(iIndex = 0;iIndex < HiPriority; iIndex++)
- {
- if(Adapter->PackInfo[iIndex].bValid && Adapter->PackInfo[iIndex].ucDirection)
- {
- if(Adapter->PackInfo[iIndex].usVCID_Value < MAX_TARGET_DSX_BUFFERS)
- {
+
+ for (iIndex = 0; iIndex < HiPriority; iIndex++) {
+ if (Adapter->PackInfo[iIndex].bValid && Adapter->PackInfo[iIndex].ucDirection) {
+ if (Adapter->PackInfo[iIndex].usVCID_Value < MAX_TARGET_DSX_BUFFERS)
atomic_set(&Adapter->PackInfo[iIndex].uiPerSFTxResourceCount, uibuff[Adapter->PackInfo[iIndex].usVCID_Value]);
- }
else
- {
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid VCID : %x \n",
- Adapter->PackInfo[iIndex].usVCID_Value);
- }
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid VCID : %x\n", Adapter->PackInfo[iIndex].usVCID_Value);
}
}
- atomic_set (&Adapter->uiMBupdate, FALSE);
+ atomic_set(&Adapter->uiMBupdate, FALSE);
}
void flush_queue(PMINI_ADAPTER Adapter, UINT iQIndex)
{
- struct sk_buff* PacketToDrop=NULL;
- struct net_device_stats* netstats = &Adapter->dev->stats;
-
+ struct sk_buff *PacketToDrop = NULL;
+ struct net_device_stats *netstats = &Adapter->dev->stats;
spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
- while(Adapter->PackInfo[iQIndex].FirstTxQueue &&
- atomic_read(&Adapter->TotalPacketCount))
- {
+ while (Adapter->PackInfo[iQIndex].FirstTxQueue && atomic_read(&Adapter->TotalPacketCount)) {
PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue;
- if(PacketToDrop && PacketToDrop->len)
- {
+ if (PacketToDrop && PacketToDrop->len) {
netstats->tx_dropped++;
- DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue, \
- Adapter->PackInfo[iQIndex].LastTxQueue);
-
+ DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue, Adapter->PackInfo[iQIndex].LastTxQueue);
Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--;
Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= PacketToDrop->len;
- //Adding dropped statistics
+ /* Adding dropped statistics */
Adapter->PackInfo[iQIndex].uiDroppedCountBytes += PacketToDrop->len;
Adapter->PackInfo[iQIndex].uiDroppedCountPackets++;
-
dev_kfree_skb(PacketToDrop);
atomic_dec(&Adapter->TotalPacketCount);
}
}
spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock);
-
}
-static void beceem_protocol_reset (PMINI_ADAPTER Adapter)
+static void beceem_protocol_reset(PMINI_ADAPTER Adapter)
{
int i;
-
if (netif_msg_link(Adapter))
pr_notice(PFX "%s: protocol reset\n", Adapter->dev->name);
@@ -1864,32 +1629,22 @@ static void beceem_protocol_reset (PMINI_ADAPTER Adapter)
Adapter->IdleMode = FALSE;
Adapter->LinkUpStatus = FALSE;
- ClearTargetDSXBuffer(Adapter,0, TRUE);
- //Delete All Classifier Rules
+ ClearTargetDSXBuffer(Adapter, 0, TRUE);
+ /* Delete All Classifier Rules */
- for(i = 0;i<HiPriority;i++)
- {
- DeleteAllClassifiersForSF(Adapter,i);
- }
+ for (i = 0; i < HiPriority; i++)
+ DeleteAllClassifiersForSF(Adapter, i);
flush_all_queues(Adapter);
- if(Adapter->TimerActive == TRUE)
+ if (Adapter->TimerActive == TRUE)
Adapter->TimerActive = FALSE;
- memset(Adapter->astFragmentedPktClassifierTable, 0,
- sizeof(S_FRAGMENTED_PACKET_INFO) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES);
+ memset(Adapter->astFragmentedPktClassifierTable, 0, sizeof(S_FRAGMENTED_PACKET_INFO) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES);
- for(i = 0;i<HiPriority;i++)
- {
- //resetting only the first size (S_MIBS_SERVICEFLOW_TABLE) for the SF.
- // It is same between MIBs and SF.
- memset(&Adapter->PackInfo[i].stMibsExtServiceFlowTable,
- 0, sizeof(S_MIBS_EXTSERVICEFLOW_PARAMETERS));
+ for (i = 0; i < HiPriority; i++) {
+ /* resetting only the first size (S_MIBS_SERVICEFLOW_TABLE) for the SF. */
+ /* It is same between MIBs and SF. */
+ memset(&Adapter->PackInfo[i].stMibsExtServiceFlowTable, 0, sizeof(S_MIBS_EXTSERVICEFLOW_PARAMETERS));
}
}
-
-
-
-
-
diff --git a/drivers/staging/bcm/headers.h b/drivers/staging/bcm/headers.h
index 947d06325681..da47db8c8f29 100644
--- a/drivers/staging/bcm/headers.h
+++ b/drivers/staging/bcm/headers.h
@@ -74,4 +74,6 @@
#define DRV_VERSION VER_FILEVERSION_STR
#define PFX DRV_NAME " "
+extern struct class *bcm_class;
+
#endif
diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c
index 4da5b7b54a1a..3de0daf5edb2 100644
--- a/drivers/staging/bcm/nvm.c
+++ b/drivers/staging/bcm/nvm.c
@@ -4013,7 +4013,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature");
- return STATUS_FAILURE;
+ Status = STATUS_FAILURE;
+ goto out;
}
uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) -
@@ -4026,7 +4027,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size");
- return STATUS_FAILURE;
+ Status = STATUS_FAILURE;
+ goto out;
}
uiTotalDataToCopy = ISOLength;
@@ -4143,7 +4145,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature");
- return STATUS_FAILURE;
+ Status = STATUS_FAILURE;
+ goto out;
}
uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) -
@@ -4156,7 +4159,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size");
- return STATUS_FAILURE;
+ Status = STATUS_FAILURE;
+ goto out;
}
uiTotalDataToCopy = ISOLength;
@@ -4257,6 +4261,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
}
+out:
kfree(Buff);
return Status;
diff --git a/drivers/staging/brcm80211/README b/drivers/staging/brcm80211/README
deleted file mode 100644
index bb86b1b3e58e..000000000000
--- a/drivers/staging/brcm80211/README
+++ /dev/null
@@ -1 +0,0 @@
-refer to: http://linuxwireless.org/en/users/Drivers/brcm80211
diff --git a/drivers/staging/brcm80211/TODO b/drivers/staging/brcm80211/TODO
deleted file mode 100644
index e2e2ef9bd7ac..000000000000
--- a/drivers/staging/brcm80211/TODO
+++ /dev/null
@@ -1,13 +0,0 @@
-To Do List for Broadcom Mac80211 driver before getting in mainline
-
-Bugs
-====
-- none known at this moment
-
-brcmfmac
-=====================
-- ASSERTS deprecated in mainline, replace by warning + error handling
-
-brcm80211 info page
-=====================
-http://linuxwireless.org/en/users/Drivers/brcm80211
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
deleted file mode 100644
index f4e72ed126b0..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-/* ****************** SDIO CARD Interface Functions **************************/
-
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include <linux/sched.h>
-#include <linux/completion.h>
-
-#include <defs.h>
-#include <brcm_hw_ids.h>
-#include <brcmu_utils.h>
-#include <brcmu_wifi.h>
-#include <soc.h>
-#include "dhd.h"
-#include "dhd_bus.h"
-#include "sdio_host.h"
-
-#define SDIOH_API_ACCESS_RETRY_LIMIT 2
-
-#define BRCMF_SD_ERROR_VAL 0x0001 /* Error */
-#define BRCMF_SD_INFO_VAL 0x0002 /* Info */
-
-
-#ifdef BCMDBG
-#define BRCMF_SD_ERROR(x) \
- do { \
- if ((brcmf_sdio_msglevel & BRCMF_SD_ERROR_VAL) && \
- net_ratelimit()) \
- printk x; \
- } while (0)
-#define BRCMF_SD_INFO(x) \
- do { \
- if ((brcmf_sdio_msglevel & BRCMF_SD_INFO_VAL) && \
- net_ratelimit()) \
- printk x; \
- } while (0)
-#else /* BCMDBG */
-#define BRCMF_SD_ERROR(x)
-#define BRCMF_SD_INFO(x)
-#endif /* BCMDBG */
-
-/* debugging macros */
-#define SDLX_MSG(x)
-
-#define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */
-#define SDIOH_CMD_TYPE_APPEND 1 /* Append command */
-#define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */
-
-#define SDIOH_DATA_PIO 0 /* PIO mode */
-#define SDIOH_DATA_DMA 1 /* DMA mode */
-
-struct brcmf_sdio_card {
- bool init_success; /* underlying driver successfully attached */
- void *sdioh; /* handler for sdioh */
- u32 vendevid; /* Target Vendor and Device ID on SD bus */
- bool regfail; /* Save status of last
- reg_read/reg_write call */
- u32 sbwad; /* Save backplane window address */
-};
-
-/**
- * SDIO Host Controller info
- */
-struct sdio_hc {
- struct sdio_hc *next;
- struct device *dev; /* platform device handle */
- void *regs; /* SDIO Host Controller address */
- struct brcmf_sdio_card *card;
- void *ch;
- unsigned int oob_irq;
- unsigned long oob_flags; /* OOB Host specifiction
- as edge and etc */
- bool oob_irq_registered;
-};
-
-/* local copy of bcm sd handler */
-static struct brcmf_sdio_card *l_card;
-
-const uint brcmf_sdio_msglevel = BRCMF_SD_ERROR_VAL;
-
-static struct sdio_hc *sdhcinfo;
-
-/* driver info, initialized when brcmf_sdio_register is called */
-static struct brcmf_sdioh_driver drvinfo = { NULL, NULL };
-
-/* Module parameters specific to each host-controller driver */
-
-module_param(sd_msglevel, uint, 0);
-
-extern uint sd_f2_blocksize;
-module_param(sd_f2_blocksize, int, 0);
-
-/* forward declarations */
-int brcmf_sdio_probe(struct device *dev);
-EXPORT_SYMBOL(brcmf_sdio_probe);
-
-int brcmf_sdio_remove(struct device *dev);
-EXPORT_SYMBOL(brcmf_sdio_remove);
-
-struct brcmf_sdio_card*
-brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq)
-{
- struct brcmf_sdio_card *card;
-
- card = kzalloc(sizeof(struct brcmf_sdio_card), GFP_ATOMIC);
- if (card == NULL) {
- BRCMF_SD_ERROR(("sdcard_attach: out of memory"));
- return NULL;
- }
-
- /* save the handler locally */
- l_card = card;
-
- card->sdioh = brcmf_sdioh_attach(cfghdl, irq);
- if (!card->sdioh) {
- brcmf_sdcard_detach(card);
- return NULL;
- }
-
- card->init_success = true;
-
- *regsva = SI_ENUM_BASE;
-
- /* Report the BAR, to fix if needed */
- card->sbwad = SI_ENUM_BASE;
- return card;
-}
-
-int brcmf_sdcard_detach(struct brcmf_sdio_card *card)
-{
- if (card != NULL) {
- if (card->sdioh) {
- brcmf_sdioh_detach(card->sdioh);
- card->sdioh = NULL;
- }
- kfree(card);
- }
-
- l_card = NULL;
- return 0;
-}
-
-int
-brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
- void *params, int plen, void *arg, int len, bool set)
-{
- return brcmf_sdioh_iovar_op(card->sdioh, name, params, plen, arg,
- len, set);
-}
-
-int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card)
-{
- return brcmf_sdioh_interrupt_set(card->sdioh, true);
-}
-
-int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card)
-{
- return brcmf_sdioh_interrupt_set(card->sdioh, false);
-}
-
-int brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
- void (*fn)(void *), void *argh)
-{
- return brcmf_sdioh_interrupt_register(card->sdioh, fn, argh);
-}
-
-int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card)
-{
- return brcmf_sdioh_interrupt_deregister(card->sdioh);
-}
-
-u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
- int *err)
-{
- int status;
- s32 retry = 0;
- u8 data = 0;
-
- if (!card)
- card = l_card;
-
- do {
- if (retry) /* wait for 1 ms till bus get settled down */
- udelay(1000);
- status =
- brcmf_sdioh_cfg_read(card->sdioh, fnc_num, addr,
- (u8 *) &data);
- } while (status != 0
- && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
- if (err)
- *err = status;
-
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
- __func__, fnc_num, addr, data));
-
- return data;
-}
-
-void
-brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
- u8 data, int *err)
-{
- int status;
- s32 retry = 0;
-
- if (!card)
- card = l_card;
-
- do {
- if (retry) /* wait for 1 ms till bus get settled down */
- udelay(1000);
- status =
- brcmf_sdioh_cfg_write(card->sdioh, fnc_num, addr,
- (u8 *) &data);
- } while (status != 0
- && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
- if (err)
- *err = status;
-
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
- __func__, fnc_num, addr, data));
-}
-
-u32 brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
- u32 addr, int *err)
-{
- int status;
- u32 data = 0;
-
- if (!card)
- card = l_card;
-
- status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
- SDIOH_READ, fnc_num, addr, &data, 4);
-
- if (err)
- *err = status;
-
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
- __func__, fnc_num, addr, data));
-
- return data;
-}
-
-void
-brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card, uint fnc_num,
- u32 addr, u32 data, int *err)
-{
- int status;
-
- if (!card)
- card = l_card;
-
- status =
- brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
- SDIOH_WRITE, fnc_num, addr, &data, 4);
-
- if (err)
- *err = status;
-
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
- __func__, fnc_num, addr, data));
-}
-
-int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func, u8 * cis,
- uint length)
-{
- int status;
-
- u8 *tmp_buf, *tmp_ptr;
- u8 *ptr;
- bool ascii = func & ~0xf;
- func &= 0x7;
-
- if (!card)
- card = l_card;
-
- status = brcmf_sdioh_cis_read(card->sdioh, func, cis, length);
-
- if (ascii) {
- /* Move binary bits to tmp and format them
- into the provided buffer. */
- tmp_buf = kmalloc(length, GFP_ATOMIC);
- if (tmp_buf == NULL) {
- BRCMF_SD_ERROR(("%s: out of memory\n", __func__));
- return -ENOMEM;
- }
- memcpy(tmp_buf, cis, length);
- for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
- tmp_ptr++) {
- ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
- if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
- ptr += sprintf((char *)ptr, "\n");
- }
- kfree(tmp_buf);
- }
-
- return status;
-}
-
-static int
-brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card *card, u32 address)
-{
- int err = 0;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
- (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
- if (!err)
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_SBADDRMID,
- (address >> 16) & SBSDIO_SBADDRMID_MASK,
- &err);
- if (!err)
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_SBADDRHIGH,
- (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
- &err);
-
- return err;
-}
-
-u32 brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size)
-{
- int status;
- u32 word = 0;
- uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
-
- BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
-
- if (!card)
- card = l_card;
-
- if (bar0 != card->sbwad) {
- if (brcmf_sdcard_set_sbaddr_window(card, bar0))
- return 0xFFFFFFFF;
-
- card->sbwad = bar0;
- }
-
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
- if (size == 4)
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
- SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
-
- card->regfail = (status != 0);
-
- BRCMF_SD_INFO(("u32data = 0x%x\n", word));
-
- /* if ok, return appropriately masked word */
- if (status == 0) {
- switch (size) {
- case sizeof(u8):
- return word & 0xff;
- case sizeof(u16):
- return word & 0xffff;
- case sizeof(u32):
- return word;
- default:
- card->regfail = true;
-
- }
- }
-
- /* otherwise, bad sdio access or invalid size */
- BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
- addr, size));
- return 0xFFFFFFFF;
-}
-
-u32 brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
- u32 data)
-{
- int status;
- uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
- int err = 0;
-
- BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
- __func__, addr, size * 8, data));
-
- if (!card)
- card = l_card;
-
- if (bar0 != card->sbwad) {
- err = brcmf_sdcard_set_sbaddr_window(card, bar0);
- if (err)
- return err;
-
- card->sbwad = bar0;
- }
-
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
- if (size == 4)
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- status =
- brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
- SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
- card->regfail = (status != 0);
-
- if (status == 0)
- return 0;
-
- BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
- __func__, data, addr, size));
- return 0xFFFFFFFF;
-}
-
-bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card)
-{
- return card->regfail;
-}
-
-int
-brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
- uint flags,
- u8 *buf, uint nbytes, struct sk_buff *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle)
-{
- int status;
- uint incr_fix;
- uint width;
- uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
- int err = 0;
-
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
- __func__, fn, addr, nbytes));
-
- /* Async not implemented yet */
- if (flags & SDIO_REQ_ASYNC)
- return -ENOTSUPP;
-
- if (bar0 != card->sbwad) {
- err = brcmf_sdcard_set_sbaddr_window(card, bar0);
- if (err)
- return err;
-
- card->sbwad = bar0;
- }
-
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
-
- incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
- width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
- if (width == 4)
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- status = brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
- incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
-
- return status;
-}
-
-int
-brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
- uint flags, u8 *buf, uint nbytes, void *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle)
-{
- uint incr_fix;
- uint width;
- uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
- int err = 0;
-
- BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
- __func__, fn, addr, nbytes));
-
- /* Async not implemented yet */
- if (flags & SDIO_REQ_ASYNC)
- return -ENOTSUPP;
-
- if (bar0 != card->sbwad) {
- err = brcmf_sdcard_set_sbaddr_window(card, bar0);
- if (err)
- return err;
-
- card->sbwad = bar0;
- }
-
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
-
- incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
- width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
- if (width == 4)
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
- incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
-}
-
-int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
- u8 *buf, uint nbytes)
-{
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
- SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
- addr, 4, nbytes, buf, NULL);
-}
-
-int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn)
-{
- return brcmf_sdioh_abort(card->sdioh, fn);
-}
-
-int brcmf_sdcard_query_device(struct brcmf_sdio_card *card)
-{
- card->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
- return card->vendevid;
-}
-
-u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card)
-{
- if (!card)
- card = l_card;
-
- return card->sbwad;
-}
-
-int brcmf_sdio_probe(struct device *dev)
-{
- struct sdio_hc *sdhc = NULL;
- u32 regs = 0;
- struct brcmf_sdio_card *card = NULL;
- int irq = 0;
- u32 vendevid;
- unsigned long irq_flags = 0;
-
- /* allocate SDIO Host Controller state info */
- sdhc = kzalloc(sizeof(struct sdio_hc), GFP_ATOMIC);
- if (!sdhc) {
- SDLX_MSG(("%s: out of memory\n", __func__));
- goto err;
- }
- sdhc->dev = (void *)dev;
-
- card = brcmf_sdcard_attach((void *)0, &regs, irq);
- if (!card) {
- SDLX_MSG(("%s: attach failed\n", __func__));
- goto err;
- }
-
- sdhc->card = card;
- sdhc->oob_irq = irq;
- sdhc->oob_flags = irq_flags;
- sdhc->oob_irq_registered = false; /* to make sure.. */
-
- /* chain SDIO Host Controller info together */
- sdhc->next = sdhcinfo;
- sdhcinfo = sdhc;
- /* Read the vendor/device ID from the CIS */
- vendevid = brcmf_sdcard_query_device(card);
-
- /* try to attach to the target device */
- sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
- 0, 0, 0, 0, regs, card);
- if (!sdhc->ch) {
- SDLX_MSG(("%s: device attach failed\n", __func__));
- goto err;
- }
-
- return 0;
-
- /* error handling */
-err:
- if (sdhc) {
- if (sdhc->card)
- brcmf_sdcard_detach(sdhc->card);
- kfree(sdhc);
- }
-
- return -ENODEV;
-}
-
-int brcmf_sdio_remove(struct device *dev)
-{
- struct sdio_hc *sdhc, *prev;
-
- sdhc = sdhcinfo;
- drvinfo.detach(sdhc->ch);
- brcmf_sdcard_detach(sdhc->card);
- /* find the SDIO Host Controller state for this pdev
- and take it out from the list */
- for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
- if (sdhc->dev == (void *)dev) {
- if (prev)
- prev->next = sdhc->next;
- else
- sdhcinfo = NULL;
- break;
- }
- prev = sdhc;
- }
- if (!sdhc) {
- SDLX_MSG(("%s: failed\n", __func__));
- return 0;
- }
-
- /* release SDIO Host Controller info */
- kfree(sdhc);
- return 0;
-}
-
-int brcmf_sdio_register(struct brcmf_sdioh_driver *driver)
-{
- drvinfo = *driver;
-
- SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
- return brcmf_sdio_function_init();
-}
-
-void brcmf_sdio_unregister(void)
-{
- brcmf_sdio_function_cleanup();
-}
-
-void brcmf_sdio_wdtmr_enable(bool enable)
-{
- if (enable)
- brcmf_sdbrcm_wd_timer(sdhcinfo->ch, brcmf_watchdog_ms);
- else
- brcmf_sdbrcm_wd_timer(sdhcinfo->ch, 0);
-}
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
deleted file mode 100644
index 38bd9ba3096f..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ /dev/null
@@ -1,1196 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/core.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/mmc/card.h>
-#include <linux/suspend.h>
-#include <linux/errno.h>
-#include <linux/sched.h> /* request_irq() */
-#include <net/cfg80211.h>
-
-#include <defs.h>
-#include <brcm_hw_ids.h>
-#include <brcmu_utils.h>
-#include <brcmu_wifi.h>
-#include "sdio_host.h"
-#include "dhd.h"
-#include "dhd_dbg.h"
-#include "wl_cfg80211.h"
-
-#define BLOCK_SIZE_64 64
-#define BLOCK_SIZE_512 512
-#define BLOCK_SIZE_4318 64
-#define BLOCK_SIZE_4328 512
-
-/* private bus modes */
-#define SDIOH_MODE_SD4 2
-
-#define CLIENT_INTR 0x100 /* Get rid of this! */
-
-#if !defined(SDIO_VENDOR_ID_BROADCOM)
-#define SDIO_VENDOR_ID_BROADCOM 0x02d0
-#endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */
-
-#define SDIO_DEVICE_ID_BROADCOM_DEFAULT 0x0000
-
-#define DMA_ALIGN_MASK 0x03
-
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)
-#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB 0x0492 /* BCM94325SDGWB */
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4325)
-#define SDIO_DEVICE_ID_BROADCOM_4325 0x0493
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4329)
-#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4319)
-#define SDIO_DEVICE_ID_BROADCOM_4319 0x4319
-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
-
-/* Common msglevel constants */
-#define SDH_ERROR_VAL 0x0001 /* Error */
-#define SDH_TRACE_VAL 0x0002 /* Trace */
-#define SDH_INFO_VAL 0x0004 /* Info */
-#define SDH_DEBUG_VAL 0x0008 /* Debug */
-#define SDH_DATA_VAL 0x0010 /* Data */
-#define SDH_CTRL_VAL 0x0020 /* Control Regs */
-#define SDH_LOG_VAL 0x0040 /* Enable bcmlog */
-#define SDH_DMA_VAL 0x0080 /* DMA */
-
-#ifdef BCMDBG
-#define sd_err(x) \
- do { \
- if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#define sd_trace(x) \
- do { \
- if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#define sd_info(x) \
- do { \
- if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#define sd_debug(x) \
- do { \
- if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#define sd_data(x) \
- do { \
- if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#define sd_ctrl(x) \
- do { \
- if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) \
- printk x; \
- } while (0)
-#else
-#define sd_err(x)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-#endif
-
-struct sdos_info {
- struct sdioh_info *sd;
- spinlock_t lock;
-};
-
-static void brcmf_sdioh_irqhandler(struct sdio_func *func);
-static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func);
-static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr);
-static int brcmf_ops_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id);
-static void brcmf_ops_sdio_remove(struct sdio_func *func);
-
-#ifdef CONFIG_PM
-static int brcmf_sdio_suspend(struct device *dev);
-static int brcmf_sdio_resume(struct device *dev);
-#endif /* CONFIG_PM */
-
-uint sd_f2_blocksize = 512; /* Default blocksize */
-
-uint sd_msglevel = 0x01;
-
-/* module param defaults */
-static int clockoverride;
-
-module_param(clockoverride, int, 0644);
-MODULE_PARM_DESC(clockoverride, "SDIO card clock override");
-
-struct brcmf_sdmmc_instance *gInstance;
-
-struct device sdmmc_dev;
-
-/* devices we support, null terminated */
-static const struct sdio_device_id brcmf_sdmmc_ids[] = {
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT)},
- {SDIO_DEVICE
- (SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319)},
- { /* end: all zeroes */ },
-};
-
-#ifdef CONFIG_PM
-static const struct dev_pm_ops brcmf_sdio_pm_ops = {
- .suspend = brcmf_sdio_suspend,
- .resume = brcmf_sdio_resume,
-};
-#endif /* CONFIG_PM */
-
-static struct sdio_driver brcmf_sdmmc_driver = {
- .probe = brcmf_ops_sdio_probe,
- .remove = brcmf_ops_sdio_remove,
- .name = "brcmfmac",
- .id_table = brcmf_sdmmc_ids,
-#ifdef CONFIG_PM
- .drv = {
- .pm = &brcmf_sdio_pm_ops,
- },
-#endif /* CONFIG_PM */
-};
-
-MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
-
-BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
-BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
-BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
-BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
-
-static int
-brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
- int regsize, u32 *data);
-
-static int brcmf_sdioh_enablefuncs(struct sdioh_info *sd)
-{
- int err_ret;
- u32 fbraddr;
- u8 func;
-
- sd_trace(("%s\n", __func__));
-
- /* Get the Card's common CIS address */
- sd->com_cis_ptr = brcmf_sdioh_get_cisaddr(sd, SDIO_CCCR_CIS);
- sd->func_cis_ptr[0] = sd->com_cis_ptr;
- sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
- sd->com_cis_ptr));
-
- /* Get the Card's function CIS (for each function) */
- for (fbraddr = SDIO_FBR_BASE(1), func = 1;
- func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
- sd->func_cis_ptr[func] =
- brcmf_sdioh_get_cisaddr(sd, SDIO_FBR_CIS + fbraddr);
- sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func,
- sd->func_cis_ptr[func]));
- }
-
- sd->func_cis_ptr[0] = sd->com_cis_ptr;
- sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
- sd->com_cis_ptr));
-
- /* Enable Function 1 */
- sdio_claim_host(gInstance->func[1]);
- err_ret = sdio_enable_func(gInstance->func[1]);
- sdio_release_host(gInstance->func[1]);
- if (err_ret) {
- sd_err(("brcmf_sdioh_enablefuncs: Failed to enable F1 "
- "Err: 0x%08x\n", err_ret));
- }
-
- return false;
-}
-
-/*
- * Public entry points & extern's
- */
-struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq)
-{
- struct sdioh_info *sd;
- int err_ret;
-
- sd_trace(("%s\n", __func__));
-
- if (gInstance == NULL) {
- sd_err(("%s: SDIO Device not present\n", __func__));
- return NULL;
- }
-
- sd = kzalloc(sizeof(struct sdioh_info), GFP_ATOMIC);
- if (sd == NULL) {
- sd_err(("sdioh_attach: out of memory\n"));
- return NULL;
- }
- if (brcmf_sdioh_osinit(sd) != 0) {
- sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
- kfree(sd);
- return NULL;
- }
-
- sd->num_funcs = 2;
- sd->use_client_ints = true;
- sd->client_block_size[0] = 64;
-
- gInstance->sd = sd;
-
- /* Claim host controller */
- sdio_claim_host(gInstance->func[1]);
-
- sd->client_block_size[1] = 64;
- err_ret = sdio_set_block_size(gInstance->func[1], 64);
- if (err_ret)
- sd_err(("brcmf_sdioh_attach: Failed to set F1 blocksize\n"));
-
- /* Release host controller F1 */
- sdio_release_host(gInstance->func[1]);
-
- if (gInstance->func[2]) {
- /* Claim host controller F2 */
- sdio_claim_host(gInstance->func[2]);
-
- sd->client_block_size[2] = sd_f2_blocksize;
- err_ret =
- sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
- if (err_ret)
- sd_err(("brcmf_sdioh_attach: Failed to set F2 blocksize"
- " to %d\n", sd_f2_blocksize));
-
- /* Release host controller F2 */
- sdio_release_host(gInstance->func[2]);
- }
-
- brcmf_sdioh_enablefuncs(sd);
-
- sd_trace(("%s: Done\n", __func__));
- return sd;
-}
-
-extern int brcmf_sdioh_detach(struct sdioh_info *sd)
-{
- sd_trace(("%s\n", __func__));
-
- if (sd) {
-
- /* Disable Function 2 */
- sdio_claim_host(gInstance->func[2]);
- sdio_disable_func(gInstance->func[2]);
- sdio_release_host(gInstance->func[2]);
-
- /* Disable Function 1 */
- sdio_claim_host(gInstance->func[1]);
- sdio_disable_func(gInstance->func[1]);
- sdio_release_host(gInstance->func[1]);
-
- /* deregister irq */
- brcmf_sdioh_osfree(sd);
-
- kfree(sd);
- }
- return 0;
-}
-
-/* Configure callback to client when we receive client interrupt */
-extern int
-brcmf_sdioh_interrupt_register(struct sdioh_info *sd, void (*fn)(void *),
- void *argh)
-{
- sd_trace(("%s: Entering\n", __func__));
- if (fn == NULL) {
- sd_err(("%s: interrupt handler is NULL, not registering\n",
- __func__));
- return -EINVAL;
- }
-
- sd->intr_handler = fn;
- sd->intr_handler_arg = argh;
- sd->intr_handler_valid = true;
-
- /* register and unmask irq */
- if (gInstance->func[2]) {
- sdio_claim_host(gInstance->func[2]);
- sdio_claim_irq(gInstance->func[2], brcmf_sdioh_irqhandler_f2);
- sdio_release_host(gInstance->func[2]);
- }
-
- if (gInstance->func[1]) {
- sdio_claim_host(gInstance->func[1]);
- sdio_claim_irq(gInstance->func[1], brcmf_sdioh_irqhandler);
- sdio_release_host(gInstance->func[1]);
- }
-
- return 0;
-}
-
-extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *sd)
-{
- sd_trace(("%s: Entering\n", __func__));
-
- if (gInstance->func[1]) {
- /* register and unmask irq */
- sdio_claim_host(gInstance->func[1]);
- sdio_release_irq(gInstance->func[1]);
- sdio_release_host(gInstance->func[1]);
- }
-
- if (gInstance->func[2]) {
- /* Claim host controller F2 */
- sdio_claim_host(gInstance->func[2]);
- sdio_release_irq(gInstance->func[2]);
- /* Release host controller F2 */
- sdio_release_host(gInstance->func[2]);
- }
-
- sd->intr_handler_valid = false;
- sd->intr_handler = NULL;
- sd->intr_handler_arg = NULL;
-
- return 0;
-}
-
-/* IOVar table */
-enum {
- IOV_MSGLEVEL = 1,
- IOV_BLOCKSIZE,
- IOV_USEINTS,
- IOV_NUMINTS,
- IOV_DEVREG,
- IOV_HCIREGS,
- IOV_RXCHAIN
-};
-
-const struct brcmu_iovar sdioh_iovars[] = {
- {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0},
- {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) |
- size) */
- {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0},
- {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0},
- {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
- ,
- {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
- ,
- {NULL, 0, 0, 0, 0}
-};
-
-int
-brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
- void *params, int plen, void *arg, int len, bool set)
-{
- const struct brcmu_iovar *vi = NULL;
- int bcmerror = 0;
- int val_size;
- s32 int_val = 0;
- bool bool_val;
- u32 actionid;
-
- if (name == NULL || len <= 0)
- return -EINVAL;
-
- /* Set does not take qualifiers */
- if (set && (params || plen))
- return -EINVAL;
-
- /* Get must have return space;*/
- if (!set && !(arg && len))
- return -EINVAL;
-
- sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
- name));
-
- vi = brcmu_iovar_lookup(sdioh_iovars, name);
- if (vi == NULL) {
- bcmerror = -ENOTSUPP;
- goto exit;
- }
-
- bcmerror = brcmu_iovar_lencheck(vi, arg, len, set);
- if (bcmerror != 0)
- goto exit;
-
- /* Set up params so get and set can share the convenience variables */
- if (params == NULL) {
- params = arg;
- plen = len;
- }
-
- if (vi->type == IOVT_VOID)
- val_size = 0;
- else if (vi->type == IOVT_BUFFER)
- val_size = len;
- else
- val_size = sizeof(int);
-
- if (plen >= (int)sizeof(int_val))
- memcpy(&int_val, params, sizeof(int_val));
-
- bool_val = (int_val != 0) ? true : false;
-
- actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
- switch (actionid) {
- case IOV_GVAL(IOV_MSGLEVEL):
- int_val = (s32) sd_msglevel;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_MSGLEVEL):
- sd_msglevel = int_val;
- break;
-
- case IOV_GVAL(IOV_BLOCKSIZE):
- if ((u32) int_val > si->num_funcs) {
- bcmerror = -EINVAL;
- break;
- }
- int_val = (s32) si->client_block_size[int_val];
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_BLOCKSIZE):
- {
- uint func = ((u32) int_val >> 16);
- uint blksize = (u16) int_val;
- uint maxsize;
-
- if (func > si->num_funcs) {
- bcmerror = -EINVAL;
- break;
- }
-
- switch (func) {
- case 0:
- maxsize = 32;
- break;
- case 1:
- maxsize = BLOCK_SIZE_4318;
- break;
- case 2:
- maxsize = BLOCK_SIZE_4328;
- break;
- default:
- maxsize = 0;
- }
- if (blksize > maxsize) {
- bcmerror = -EINVAL;
- break;
- }
- if (!blksize)
- blksize = maxsize;
-
- /* Now set it */
- si->client_block_size[func] = blksize;
-
- break;
- }
-
- case IOV_GVAL(IOV_RXCHAIN):
- int_val = false;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_GVAL(IOV_USEINTS):
- int_val = (s32) si->use_client_ints;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_USEINTS):
- si->use_client_ints = (bool) int_val;
- if (si->use_client_ints)
- si->intmask |= CLIENT_INTR;
- else
- si->intmask &= ~CLIENT_INTR;
-
- break;
-
- case IOV_GVAL(IOV_NUMINTS):
- int_val = (s32) si->intrcount;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_GVAL(IOV_DEVREG):
- {
- struct brcmf_sdreg *sd_ptr =
- (struct brcmf_sdreg *) params;
- u8 data = 0;
-
- if (brcmf_sdioh_cfg_read
- (si, sd_ptr->func, sd_ptr->offset, &data)) {
- bcmerror = -EIO;
- break;
- }
-
- int_val = (int)data;
- memcpy(arg, &int_val, sizeof(int_val));
- break;
- }
-
- case IOV_SVAL(IOV_DEVREG):
- {
- struct brcmf_sdreg *sd_ptr =
- (struct brcmf_sdreg *) params;
- u8 data = (u8) sd_ptr->value;
-
- if (brcmf_sdioh_cfg_write
- (si, sd_ptr->func, sd_ptr->offset, &data)) {
- bcmerror = -EIO;
- break;
- }
- break;
- }
-
- default:
- bcmerror = -ENOTSUPP;
- break;
- }
-exit:
-
- return bcmerror;
-}
-
-extern int
-brcmf_sdioh_cfg_read(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
-{
- int status;
- /* No lock needed since brcmf_sdioh_request_byte does locking */
- status = brcmf_sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
- return status;
-}
-
-extern int
-brcmf_sdioh_cfg_write(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
-{
- /* No lock needed since brcmf_sdioh_request_byte does locking */
- int status;
- status = brcmf_sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
- return status;
-}
-
-static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr)
-{
- /* read 24 bits and return valid 17 bit addr */
- int i;
- u32 scratch, regdata;
- u8 *ptr = (u8 *)&scratch;
- for (i = 0; i < 3; i++) {
- if ((brcmf_sdioh_card_regread(sd, 0, regaddr, 1, &regdata)) !=
- SUCCESS)
- sd_err(("%s: Can't read!\n", __func__));
-
- *ptr++ = (u8) regdata;
- regaddr++;
- }
-
- /* Only the lower 17-bits are valid */
- scratch = le32_to_cpu(scratch);
- scratch &= 0x0001FFFF;
- return scratch;
-}
-
-extern int
-brcmf_sdioh_cis_read(struct sdioh_info *sd, uint func, u8 *cisd, u32 length)
-{
- u32 count;
- int offset;
- u32 foo;
- u8 *cis = cisd;
-
- sd_trace(("%s: Func = %d\n", __func__, func));
-
- if (!sd->func_cis_ptr[func]) {
- memset(cis, 0, length);
- sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func));
- return -ENOTSUPP;
- }
-
- sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func,
- sd->func_cis_ptr[func]));
-
- for (count = 0; count < length; count++) {
- offset = sd->func_cis_ptr[func] + count;
- if (brcmf_sdioh_card_regread(sd, 0, offset, 1, &foo) < 0) {
- sd_err(("%s: regread failed: Can't read CIS\n",
- __func__));
- return -EIO;
- }
-
- *cis = (u8) (foo & 0xff);
- cis++;
- }
-
- return 0;
-}
-
-extern int
-brcmf_sdioh_request_byte(struct sdioh_info *sd, uint rw, uint func,
- uint regaddr, u8 *byte)
-{
- int err_ret;
-
- sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func,
- regaddr));
-
- BRCMF_PM_RESUME_WAIT(sdioh_request_byte_wait);
- BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
- if (rw) { /* CMD52 Write */
- if (func == 0) {
- /* Can only directly write to some F0 registers.
- * Handle F2 enable
- * as a special case.
- */
- if (regaddr == SDIO_CCCR_IOEx) {
- if (gInstance->func[2]) {
- sdio_claim_host(gInstance->func[2]);
- if (*byte & SDIO_FUNC_ENABLE_2) {
- /* Enable Function 2 */
- err_ret =
- sdio_enable_func
- (gInstance->func[2]);
- if (err_ret)
- sd_err(("request_byte: "
- "enable F2 "
- "failed:%d\n",
- err_ret));
- } else {
- /* Disable Function 2 */
- err_ret =
- sdio_disable_func
- (gInstance->func[2]);
- if (err_ret)
- sd_err(("request_byte: "
- "Disab F2 "
- "failed:%d\n",
- err_ret));
- }
- sdio_release_host(gInstance->func[2]);
- }
- }
- /* to allow abort command through F1 */
- else if (regaddr == SDIO_CCCR_ABORT) {
- sdio_claim_host(gInstance->func[func]);
- /*
- * this sdio_f0_writeb() can be replaced
- * with another api
- * depending upon MMC driver change.
- * As of this time, this is temporaray one
- */
- sdio_writeb(gInstance->func[func], *byte,
- regaddr, &err_ret);
- sdio_release_host(gInstance->func[func]);
- } else if (regaddr < 0xF0) {
- sd_err(("brcmf: F0 Wr:0x%02x: write "
- "disallowed\n", regaddr));
- } else {
- /* Claim host controller, perform F0 write,
- and release */
- sdio_claim_host(gInstance->func[func]);
- sdio_f0_writeb(gInstance->func[func], *byte,
- regaddr, &err_ret);
- sdio_release_host(gInstance->func[func]);
- }
- } else {
- /* Claim host controller, perform Fn write,
- and release */
- sdio_claim_host(gInstance->func[func]);
- sdio_writeb(gInstance->func[func], *byte, regaddr,
- &err_ret);
- sdio_release_host(gInstance->func[func]);
- }
- } else { /* CMD52 Read */
- /* Claim host controller, perform Fn read, and release */
- sdio_claim_host(gInstance->func[func]);
-
- if (func == 0) {
- *byte =
- sdio_f0_readb(gInstance->func[func], regaddr,
- &err_ret);
- } else {
- *byte =
- sdio_readb(gInstance->func[func], regaddr,
- &err_ret);
- }
-
- sdio_release_host(gInstance->func[func]);
- }
-
- if (err_ret)
- sd_err(("brcmf: Failed to %s byte F%d:@0x%05x=%02x, "
- "Err: %d\n", rw ? "Write" : "Read", func, regaddr,
- *byte, err_ret));
-
- return err_ret;
-}
-
-extern int
-brcmf_sdioh_request_word(struct sdioh_info *sd, uint cmd_type, uint rw,
- uint func, uint addr, u32 *word, uint nbytes)
-{
- int err_ret = -EIO;
-
- if (func == 0) {
- sd_err(("%s: Only CMD52 allowed to F0.\n", __func__));
- return -EINVAL;
- }
-
- sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
- __func__, cmd_type, rw, func, addr, nbytes));
-
- BRCMF_PM_RESUME_WAIT(sdioh_request_word_wait);
- BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
- /* Claim host controller */
- sdio_claim_host(gInstance->func[func]);
-
- if (rw) { /* CMD52 Write */
- if (nbytes == 4) {
- sdio_writel(gInstance->func[func], *word, addr,
- &err_ret);
- } else if (nbytes == 2) {
- sdio_writew(gInstance->func[func], (*word & 0xFFFF),
- addr, &err_ret);
- } else {
- sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
- }
- } else { /* CMD52 Read */
- if (nbytes == 4) {
- *word =
- sdio_readl(gInstance->func[func], addr, &err_ret);
- } else if (nbytes == 2) {
- *word =
- sdio_readw(gInstance->func[func], addr,
- &err_ret) & 0xFFFF;
- } else {
- sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
- }
- }
-
- /* Release host controller */
- sdio_release_host(gInstance->func[func]);
-
- if (err_ret) {
- sd_err(("brcmf: Failed to %s word, Err: 0x%08x\n",
- rw ? "Write" : "Read", err_ret));
- }
-
- return err_ret;
-}
-
-static int
-brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write,
- uint func, uint addr, struct sk_buff *pkt)
-{
- bool fifo = (fix_inc == SDIOH_DATA_FIX);
- u32 SGCount = 0;
- int err_ret = 0;
-
- struct sk_buff *pnext;
-
- sd_trace(("%s: Enter\n", __func__));
-
- BRCMF_PM_RESUME_WAIT(sdioh_request_packet_wait);
- BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
-
- /* Claim host controller */
- sdio_claim_host(gInstance->func[func]);
- for (pnext = pkt; pnext; pnext = pnext->next) {
- uint pkt_len = pnext->len;
- pkt_len += 3;
- pkt_len &= 0xFFFFFFFC;
-
- if ((write) && (!fifo)) {
- err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
- ((u8 *) (pnext->data)),
- pkt_len);
- } else if (write) {
- err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
- ((u8 *) (pnext->data)),
- pkt_len);
- } else if (fifo) {
- err_ret = sdio_readsb(gInstance->func[func],
- ((u8 *) (pnext->data)),
- addr, pkt_len);
- } else {
- err_ret = sdio_memcpy_fromio(gInstance->func[func],
- ((u8 *) (pnext->data)),
- addr, pkt_len);
- }
-
- if (err_ret) {
- sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d,"
- "ERR=0x%08x\n", __func__,
- (write) ? "TX" : "RX",
- pnext, SGCount, addr, pkt_len, err_ret));
- } else {
- sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
- __func__,
- (write) ? "TX" : "RX",
- pnext, SGCount, addr, pkt_len));
- }
-
- if (!fifo)
- addr += pkt_len;
- SGCount++;
-
- }
-
- /* Release host controller */
- sdio_release_host(gInstance->func[func]);
-
- sd_trace(("%s: Exit\n", __func__));
- return err_ret;
-}
-
-/*
- * This function takes a buffer or packet, and fixes everything up
- * so that in the end, a DMA-able packet is created.
- *
- * A buffer does not have an associated packet pointer,
- * and may or may not be aligned.
- * A packet may consist of a single packet, or a packet chain.
- * If it is a packet chain, then all the packets in the chain
- * must be properly aligned.
- *
- * If the packet data is not aligned, then there may only be
- * one packet, and in this case, it is copied to a new
- * aligned packet.
- *
- */
-extern int
-brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
- uint write, uint func, uint addr, uint reg_width,
- uint buflen_u, u8 *buffer, struct sk_buff *pkt)
-{
- int Status;
- struct sk_buff *mypkt = NULL;
-
- sd_trace(("%s: Enter\n", __func__));
-
- BRCMF_PM_RESUME_WAIT(sdioh_request_buffer_wait);
- BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
- /* Case 1: we don't have a packet. */
- if (pkt == NULL) {
- sd_data(("%s: Creating new %s Packet, len=%d\n",
- __func__, write ? "TX" : "RX", buflen_u));
- mypkt = brcmu_pkt_buf_get_skb(buflen_u);
- if (!mypkt) {
- sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
- __func__, buflen_u));
- return -EIO;
- }
-
- /* For a write, copy the buffer data into the packet. */
- if (write)
- memcpy(mypkt->data, buffer, buflen_u);
-
- Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
- addr, mypkt);
-
- /* For a read, copy the packet data back to the buffer. */
- if (!write)
- memcpy(buffer, mypkt->data, buflen_u);
-
- brcmu_pkt_buf_free_skb(mypkt);
- } else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) {
- /*
- * Case 2: We have a packet, but it is unaligned.
- * In this case, we cannot have a chain (pkt->next == NULL)
- */
- sd_data(("%s: Creating aligned %s Packet, len=%d\n",
- __func__, write ? "TX" : "RX", pkt->len));
- mypkt = brcmu_pkt_buf_get_skb(pkt->len);
- if (!mypkt) {
- sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
- __func__, pkt->len));
- return -EIO;
- }
-
- /* For a write, copy the buffer data into the packet. */
- if (write)
- memcpy(mypkt->data, pkt->data, pkt->len);
-
- Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
- addr, mypkt);
-
- /* For a read, copy the packet data back to the buffer. */
- if (!write)
- memcpy(pkt->data, mypkt->data, mypkt->len);
-
- brcmu_pkt_buf_free_skb(mypkt);
- } else { /* case 3: We have a packet and
- it is aligned. */
- sd_data(("%s: Aligned %s Packet, direct DMA\n",
- __func__, write ? "Tx" : "Rx"));
- Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
- addr, pkt);
- }
-
- return Status;
-}
-
-/* this function performs "abort" for both of host & device */
-extern int brcmf_sdioh_abort(struct sdioh_info *sd, uint func)
-{
- char t_func = (char)func;
- sd_trace(("%s: Enter\n", __func__));
-
- /* issue abort cmd52 command through F0 */
- brcmf_sdioh_request_byte(sd, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT,
- &t_func);
-
- sd_trace(("%s: Exit\n", __func__));
- return 0;
-}
-
-/* Disable device interrupt */
-void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd)
-{
- sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
- sd->intmask &= ~CLIENT_INTR;
-}
-
-/* Enable device interrupt */
-void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd)
-{
- sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
- sd->intmask |= CLIENT_INTR;
-}
-
-/* Read client card reg */
-int
-brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
- int regsize, u32 *data)
-{
-
- if ((func == 0) || (regsize == 1)) {
- u8 temp = 0;
-
- brcmf_sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
- *data = temp;
- *data &= 0xff;
- sd_data(("%s: byte read data=0x%02x\n", __func__, *data));
- } else {
- brcmf_sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
- regsize);
- if (regsize == 2)
- *data &= 0xffff;
-
- sd_data(("%s: word read data=0x%08x\n", __func__, *data));
- }
-
- return SUCCESS;
-}
-
-static void brcmf_sdioh_irqhandler(struct sdio_func *func)
-{
- struct sdioh_info *sd;
-
- sd_trace(("brcmf: ***IRQHandler\n"));
- sd = gInstance->sd;
-
- sdio_release_host(gInstance->func[0]);
-
- if (sd->use_client_ints) {
- sd->intrcount++;
- (sd->intr_handler) (sd->intr_handler_arg);
- } else {
- sd_err(("brcmf: ***IRQHandler\n"));
-
- sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
- __func__, sd->client_intr_enabled, sd->intr_handler));
- }
-
- sdio_claim_host(gInstance->func[0]);
-}
-
-/* interrupt handler for F2 (dummy handler) */
-static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func)
-{
- struct sdioh_info *sd;
-
- sd_trace(("brcmf: ***IRQHandlerF2\n"));
-
- sd = gInstance->sd;
-}
-
-static int brcmf_ops_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
-{
- int ret = 0;
- static struct sdio_func sdio_func_0;
- sd_trace(("sdio_probe: %s Enter\n", __func__));
- sd_trace(("sdio_probe: func->class=%x\n", func->class));
- sd_trace(("sdio_vendor: 0x%04x\n", func->vendor));
- sd_trace(("sdio_device: 0x%04x\n", func->device));
- sd_trace(("Function#: 0x%04x\n", func->num));
-
- if (func->num == 1) {
- sdio_func_0.num = 0;
- sdio_func_0.card = func->card;
- gInstance->func[0] = &sdio_func_0;
- if (func->device == 0x4) { /* 4318 */
- gInstance->func[2] = NULL;
- sd_trace(("NIC found, calling brcmf_sdio_probe...\n"));
- ret = brcmf_sdio_probe(&sdmmc_dev);
- }
- }
-
- gInstance->func[func->num] = func;
-
- if (func->num == 2) {
- brcmf_cfg80211_sdio_func(func);
- sd_trace(("F2 found, calling brcmf_sdio_probe...\n"));
- ret = brcmf_sdio_probe(&sdmmc_dev);
- }
-
- return ret;
-}
-
-static void brcmf_ops_sdio_remove(struct sdio_func *func)
-{
- sd_trace(("%s Enter\n", __func__));
- sd_info(("func->class=%x\n", func->class));
- sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
- sd_info(("sdio_device: 0x%04x\n", func->device));
- sd_info(("Function#: 0x%04x\n", func->num));
-
- if (func->num == 2) {
- sd_trace(("F2 found, calling brcmf_sdio_remove...\n"));
- brcmf_sdio_remove(&sdmmc_dev);
- }
-}
-
-
-#ifdef CONFIG_PM
-static int brcmf_sdio_suspend(struct device *dev)
-{
- mmc_pm_flag_t sdio_flags;
- int ret = 0;
-
- sd_trace(("%s\n", __func__));
-
- sdio_flags = sdio_get_host_pm_caps(gInstance->func[1]);
- if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
- sd_err(("Host can't keep power while suspended\n"));
- return -EINVAL;
- }
-
- ret = sdio_set_host_pm_flags(gInstance->func[1], MMC_PM_KEEP_POWER);
- if (ret) {
- sd_err(("Failed to set pm_flags\n"));
- return ret;
- }
-
- brcmf_sdio_wdtmr_enable(false);
-
- return ret;
-}
-
-static int brcmf_sdio_resume(struct device *dev)
-{
- brcmf_sdio_wdtmr_enable(true);
- return 0;
-}
-#endif /* CONFIG_PM */
-
-int brcmf_sdioh_osinit(struct sdioh_info *sd)
-{
- struct sdos_info *sdos;
-
- sdos = kmalloc(sizeof(struct sdos_info), GFP_ATOMIC);
- sd->sdos_info = (void *)sdos;
- if (sdos == NULL)
- return -ENOMEM;
-
- sdos->sd = sd;
- spin_lock_init(&sdos->lock);
- return 0;
-}
-
-void brcmf_sdioh_osfree(struct sdioh_info *sd)
-{
- struct sdos_info *sdos;
-
- sdos = (struct sdos_info *)sd->sdos_info;
- kfree(sdos);
-}
-
-/* Interrupt enable/disable */
-int brcmf_sdioh_interrupt_set(struct sdioh_info *sd, bool enable)
-{
- unsigned long flags;
- struct sdos_info *sdos;
-
- sd_trace(("%s: %s\n", __func__, enable ? "Enabling" : "Disabling"));
-
- sdos = (struct sdos_info *)sd->sdos_info;
-
- if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
- sd_err(("%s: no handler registered, will not enable\n",
- __func__));
- return -EINVAL;
- }
-
- /* Ensure atomicity for enable/disable calls */
- spin_lock_irqsave(&sdos->lock, flags);
-
- sd->client_intr_enabled = enable;
- if (enable)
- brcmf_sdioh_dev_intr_on(sd);
- else
- brcmf_sdioh_dev_intr_off(sd);
-
- spin_unlock_irqrestore(&sdos->lock, flags);
-
- return 0;
-}
-
-/*
- * module init
-*/
-int brcmf_sdio_function_init(void)
-{
- int error = 0;
- sd_trace(("brcmf_sdio_function_init: %s Enter\n", __func__));
-
- gInstance = kzalloc(sizeof(struct brcmf_sdmmc_instance), GFP_KERNEL);
- if (!gInstance)
- return -ENOMEM;
-
- memset(&sdmmc_dev, 0, sizeof(sdmmc_dev));
- error = sdio_register_driver(&brcmf_sdmmc_driver);
-
- return error;
-}
-
-/*
- * module cleanup
-*/
-void brcmf_sdio_function_cleanup(void)
-{
- sd_trace(("%s Enter\n", __func__));
-
- sdio_unregister_driver(&brcmf_sdmmc_driver);
-
- kfree(gInstance);
-}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_common.c b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
deleted file mode 100644
index fdec4683c422..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/dhd_common.c
+++ /dev/null
@@ -1,1196 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#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"
-
-#define BRCM_OUI "\x00\x10\x18"
-#define DOT11_OUI_LEN 3
-#define BCMILCP_BCM_SUBTYPE_EVENT 1
-#define PKTFILTER_BUF_SIZE 2048
-
-int brcmf_msg_level;
-
-#define MSGTRACE_VERSION 1
-
-#ifdef BCMDBG
-const char brcmf_version[] =
-"Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on " __DATE__
-" at " __TIME__;
-#else
-const char brcmf_version[] = "Dongle Host Driver, version " BRCMF_VERSION_STR;
-#endif
-
-/* IOVar table */
-enum {
- IOV_VERSION = 1,
- IOV_MSGLEVEL,
- IOV_BCMERRORSTR,
- IOV_BCMERROR,
- IOV_DUMP,
- IOV_CLEARCOUNTS,
- IOV_LOGDUMP,
- IOV_LOGCAL,
- IOV_LOGSTAMP,
- IOV_GPIOOB,
- IOV_IOCTLTIMEOUT,
- IOV_LAST
-};
-
-const struct brcmu_iovar brcmf_iovars[] = {
- {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(brcmf_version)}
- ,
-#ifdef BCMDBG
- {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0}
- ,
-#endif /* BCMDBG */
- {"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN}
- ,
- {"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0}
- ,
- {"dump", IOV_DUMP, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN}
- ,
- {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0}
- ,
- {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0}
- ,
- {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0}
- ,
- {NULL, 0, 0, 0, 0}
-};
-
-/* Message trace header */
-struct msgtrace_hdr {
- u8 version;
- u8 spare;
- u16 len; /* Len of the trace */
- u32 seqnum; /* Sequence number of message. Useful
- * if the messsage has been lost
- * because of DMA error or a bus reset
- * (ex: SDIO Func2)
- */
- u32 discarded_bytes; /* Number of discarded bytes because of
- trace overflow */
- u32 discarded_printf; /* Number of discarded printf
- because of trace overflow */
-} __packed;
-
-void brcmf_c_init(void)
-{
- /* Init global variables at run-time, not as part of the declaration.
- * This is required to support init/de-init of the driver.
- * Initialization
- * of globals as part of the declaration results in non-deterministic
- * behaviour since the value of the globals may be different on the
- * first time that the driver is initialized vs subsequent
- * initializations.
- */
- brcmf_msg_level = BRCMF_ERROR_VAL;
-}
-
-static int brcmf_c_dump(struct brcmf_pub *drvr, char *buf, int buflen)
-{
- struct brcmu_strbuf b;
- struct brcmu_strbuf *strbuf = &b;
-
- brcmu_binit(strbuf, buf, buflen);
-
- /* Base info */
- brcmu_bprintf(strbuf, "%s\n", brcmf_version);
- brcmu_bprintf(strbuf, "\n");
- brcmu_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n",
- drvr->up, drvr->txoff, drvr->busstate);
- brcmu_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n",
- drvr->hdrlen, drvr->maxctl, drvr->rxsz);
- brcmu_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %pM\n",
- drvr->iswl, drvr->drv_version, &drvr->mac);
- brcmu_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", drvr->bcmerror,
- drvr->tickcnt);
-
- brcmu_bprintf(strbuf, "dongle stats:\n");
- brcmu_bprintf(strbuf,
- "tx_packets %ld tx_bytes %ld tx_errors %ld tx_dropped %ld\n",
- drvr->dstats.tx_packets, drvr->dstats.tx_bytes,
- drvr->dstats.tx_errors, drvr->dstats.tx_dropped);
- brcmu_bprintf(strbuf,
- "rx_packets %ld rx_bytes %ld rx_errors %ld rx_dropped %ld\n",
- drvr->dstats.rx_packets, drvr->dstats.rx_bytes,
- drvr->dstats.rx_errors, drvr->dstats.rx_dropped);
- brcmu_bprintf(strbuf, "multicast %ld\n", drvr->dstats.multicast);
-
- brcmu_bprintf(strbuf, "bus stats:\n");
- brcmu_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n",
- drvr->tx_packets, drvr->tx_multicast, drvr->tx_errors);
- brcmu_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n",
- drvr->tx_ctlpkts, drvr->tx_ctlerrs);
- brcmu_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld\n",
- drvr->rx_packets, drvr->rx_multicast, drvr->rx_errors);
- brcmu_bprintf(strbuf,
- "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld rx_flushed %ld\n",
- drvr->rx_ctlpkts, drvr->rx_ctlerrs, drvr->rx_dropped,
- drvr->rx_flushed);
- brcmu_bprintf(strbuf,
- "rx_readahead_cnt %ld tx_realloc %ld fc_packets %ld\n",
- drvr->rx_readahead_cnt, drvr->tx_realloc, drvr->fc_packets);
- brcmu_bprintf(strbuf, "wd_dpc_sched %ld\n", drvr->wd_dpc_sched);
- brcmu_bprintf(strbuf, "\n");
-
- /* Add any prot info */
- brcmf_proto_dump(drvr, strbuf);
- brcmu_bprintf(strbuf, "\n");
-
- /* Add any bus info */
- brcmf_sdbrcm_bus_dump(drvr, strbuf);
-
- return !strbuf->size ? -EOVERFLOW : 0;
-}
-
-static int
-brcmf_c_doiovar(struct brcmf_pub *drvr, const struct brcmu_iovar *vi,
- u32 actionid, const char *name, void *params, int plen,
- void *arg, int len, int val_size)
-{
- int bcmerror = 0;
- s32 int_val = 0;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
- if (bcmerror != 0)
- goto exit;
-
- if (plen >= (int)sizeof(int_val))
- memcpy(&int_val, params, sizeof(int_val));
-
- switch (actionid) {
- case IOV_GVAL(IOV_VERSION):
- /* Need to have checked buffer length */
- strncpy((char *)arg, brcmf_version, len);
- break;
-
- case IOV_GVAL(IOV_MSGLEVEL):
- int_val = (s32) brcmf_msg_level;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_MSGLEVEL):
- brcmf_msg_level = int_val;
- break;
-
- case IOV_GVAL(IOV_BCMERRORSTR):
- strncpy((char *)arg, "bcm_error",
- BCME_STRLEN);
- ((char *)arg)[BCME_STRLEN - 1] = 0x00;
- break;
-
- case IOV_GVAL(IOV_BCMERROR):
- int_val = (s32) drvr->bcmerror;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_GVAL(IOV_DUMP):
- bcmerror = brcmf_c_dump(drvr, arg, len);
- break;
-
- case IOV_SVAL(IOV_CLEARCOUNTS):
- drvr->tx_packets = drvr->rx_packets = 0;
- drvr->tx_errors = drvr->rx_errors = 0;
- drvr->tx_ctlpkts = drvr->rx_ctlpkts = 0;
- drvr->tx_ctlerrs = drvr->rx_ctlerrs = 0;
- drvr->rx_dropped = 0;
- drvr->rx_readahead_cnt = 0;
- drvr->tx_realloc = 0;
- drvr->wd_dpc_sched = 0;
- memset(&drvr->dstats, 0, sizeof(drvr->dstats));
- brcmf_bus_clearcounts(drvr);
- break;
-
- case IOV_GVAL(IOV_IOCTLTIMEOUT):{
- int_val = (s32) brcmf_os_get_ioctl_resp_timeout();
- memcpy(arg, &int_val, sizeof(int_val));
- break;
- }
-
- case IOV_SVAL(IOV_IOCTLTIMEOUT):{
- if (int_val <= 0)
- bcmerror = -EINVAL;
- else
- brcmf_os_set_ioctl_resp_timeout((unsigned int)
- int_val);
- break;
- }
-
- default:
- bcmerror = -ENOTSUPP;
- break;
- }
-
-exit:
- return bcmerror;
-}
-
-bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
- struct sk_buff *pkt, int prec)
-{
- struct sk_buff *p;
- int eprec = -1; /* precedence to evict from */
- bool discard_oldest;
-
- /* Fast case, precedence queue is not full and we are also not
- * exceeding total queue length
- */
- if (!pktq_pfull(q, prec) && !pktq_full(q)) {
- brcmu_pktq_penq(q, prec, pkt);
- return true;
- }
-
- /* 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)
- return false;
- }
-
- /* Evict if needed */
- if (eprec >= 0) {
- /* Detect queueing to unconfigured precedence */
- discard_oldest = AC_BITMAP_TST(drvr->wme_dp, eprec);
- if (eprec == prec && !discard_oldest)
- return false; /* refuse newer (incoming) packet */
- /* Evict packet according to discard policy */
- p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
- brcmu_pktq_pdeq_tail(q, eprec);
- if (p == NULL) {
- BRCMF_ERROR(("%s: brcmu_pktq_penq() failed, oldest %d.",
- __func__, discard_oldest));
- }
- brcmu_pkt_buf_free_skb(p);
- }
-
- /* Enqueue */
- p = brcmu_pktq_penq(q, prec, pkt);
- if (p == NULL) {
- BRCMF_ERROR(("%s: brcmu_pktq_penq() failed.", __func__));
- }
-
- return p != NULL;
-}
-
-static int
-brcmf_c_iovar_op(struct brcmf_pub *drvr, const char *name,
- void *params, int plen, void *arg, int len, bool set)
-{
- int bcmerror = 0;
- int val_size;
- const struct brcmu_iovar *vi = NULL;
- u32 actionid;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (name == NULL || len <= 0)
- return -EINVAL;
-
- /* Set does not take qualifiers */
- if (set && (params || plen))
- return -EINVAL;
-
- /* Get must have return space;*/
- if (!set && !(arg && len))
- return -EINVAL;
-
- vi = brcmu_iovar_lookup(brcmf_iovars, name);
- if (vi == NULL) {
- bcmerror = -ENOTSUPP;
- goto exit;
- }
-
- BRCMF_CTL(("%s: %s %s, len %d plen %d\n", __func__,
- name, (set ? "set" : "get"), len, plen));
-
- /* set up 'params' pointer in case this is a set command so that
- * the convenience int and bool code can be common to set and get
- */
- if (params == NULL) {
- params = arg;
- plen = len;
- }
-
- if (vi->type == IOVT_VOID)
- val_size = 0;
- else if (vi->type == IOVT_BUFFER)
- val_size = len;
- else
- /* all other types are integer sized */
- val_size = sizeof(int);
-
- actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
- bcmerror =
- brcmf_c_doiovar(drvr, vi, actionid, name, params, plen, arg, len,
- val_size);
-
-exit:
- return bcmerror;
-}
-
-int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc, void *buf,
- uint buflen)
-{
- int bcmerror = 0;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (!buf)
- return -EINVAL;
-
- switch (ioc->cmd) {
- case BRCMF_GET_MAGIC:
- if (buflen < sizeof(int))
- bcmerror = -EOVERFLOW;
- else
- *(int *)buf = BRCMF_IOCTL_MAGIC;
- break;
-
- case BRCMF_GET_VERSION:
- if (buflen < sizeof(int))
- bcmerror = -EOVERFLOW;
- else
- *(int *)buf = BRCMF_IOCTL_VERSION;
- break;
-
- case BRCMF_GET_VAR:
- case BRCMF_SET_VAR:{
- char *arg;
- uint arglen;
-
- /* scan past the name to any arguments */
- for (arg = buf, arglen = buflen; *arg && arglen;
- arg++, arglen--)
- ;
-
- if (*arg) {
- bcmerror = -EOVERFLOW;
- break;
- }
-
- /* account for the NUL terminator */
- arg++, arglen--;
-
- /* call with the appropriate arguments */
- if (ioc->cmd == BRCMF_GET_VAR)
- bcmerror = brcmf_c_iovar_op(drvr, buf, arg,
- arglen, buf, buflen, IOV_GET);
- else
- bcmerror =
- brcmf_c_iovar_op(drvr, buf, NULL, 0, arg,
- arglen, IOV_SET);
- if (bcmerror != -ENOTSUPP)
- break;
-
- /* if still not found, try bus module */
- if (ioc->cmd == BRCMF_GET_VAR)
- bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr,
- buf, arg, arglen, buf, buflen,
- IOV_GET);
- else
- bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr,
- buf, NULL, 0, arg, arglen,
- IOV_SET);
-
- break;
- }
-
- default:
- bcmerror = -ENOTSUPP;
- }
-
- return bcmerror;
-}
-
-#ifdef SHOW_EVENTS
-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"}
- };
- uint event_type, flags, auth_type, datalen;
- 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_EVENT(("EVENT: %s, event ID = %d\n", event_name, event_type));
- BRCMF_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_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
- break;
-
- case BRCMF_E_ASSOC_IND:
- case BRCMF_E_REASSOC_IND:
- BRCMF_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_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n",
- event_name, eabuf));
- } else if (status == BRCMF_E_STATUS_TIMEOUT) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n",
- event_name, eabuf));
- } else if (status == BRCMF_E_STATUS_FAIL) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, FAILURE,"
- " reason %d\n", event_name, eabuf,
- (int)reason));
- } else {
- BRCMF_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_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_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name,
- eabuf, auth_str));
- } else if (status == BRCMF_E_STATUS_SUCCESS) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n",
- event_name, eabuf, auth_str));
- } else if (status == BRCMF_E_STATUS_TIMEOUT) {
- BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
- event_name, eabuf, auth_str));
- } else if (status == BRCMF_E_STATUS_FAIL) {
- BRCMF_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_EVENT(("MACEVENT: %s, MAC %s\n", event_name,
- eabuf));
- } else if (status == BRCMF_E_STATUS_FAIL) {
- BRCMF_EVENT(("MACEVENT: %s, failed\n", event_name));
- } else if (status == BRCMF_E_STATUS_NO_NETWORKS) {
- BRCMF_EVENT(("MACEVENT: %s, no networks found\n",
- event_name));
- } else {
- BRCMF_EVENT(("MACEVENT: %s, unexpected status %d\n",
- event_name, (int)status));
- }
- break;
-
- case BRCMF_E_BEACON_RX:
- if (status == BRCMF_E_STATUS_SUCCESS) {
- BRCMF_EVENT(("MACEVENT: %s, SUCCESS\n", event_name));
- } else if (status == BRCMF_E_STATUS_FAIL) {
- BRCMF_EVENT(("MACEVENT: %s, FAIL\n", event_name));
- } else {
- BRCMF_EVENT(("MACEVENT: %s, status %d\n", event_name,
- status));
- }
- break;
-
- case BRCMF_E_LINK:
- BRCMF_EVENT(("MACEVENT: %s %s\n", event_name,
- link ? "UP" : "DOWN"));
- break;
-
- case BRCMF_E_MIC_ERROR:
- BRCMF_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_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
- break;
-
- case BRCMF_E_TXFAIL:
- BRCMF_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf));
- break;
-
- case BRCMF_E_SCAN_COMPLETE:
- case BRCMF_E_PMKID_CACHE:
- BRCMF_EVENT(("MACEVENT: %s\n", event_name));
- break;
-
- case BRCMF_E_PFN_NET_FOUND:
- case BRCMF_E_PFN_NET_LOST:
- case BRCMF_E_PFN_SCAN_COMPLETE:
- BRCMF_EVENT(("PNOEVENT: %s\n", event_name));
- break;
-
- case BRCMF_E_PSK_SUP:
- case BRCMF_E_PRUNE:
- BRCMF_EVENT(("MACEVENT: %s, status %d, reason %d\n",
- event_name, (int)status, (int)reason));
- break;
-
- case BRCMF_E_TRACE:
- {
- static u32 seqnum_prev;
- struct msgtrace_hdr hdr;
- u32 nblost;
- char *s, *p;
-
- buf = (unsigned char *) event_data;
- memcpy(&hdr, buf, sizeof(struct msgtrace_hdr));
-
- if (hdr.version != MSGTRACE_VERSION) {
- BRCMF_ERROR(
- ("\nMACEVENT: %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_ERROR(
- ("\nWLC_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_ERROR(
- ("\nWLC_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';
- printk(KERN_DEBUG"%s\n", p);
- p = s + 1;
- }
- printk(KERN_DEBUG "%s\n", p);
-
- /* Reset datalen to avoid display below */
- datalen = 0;
- }
- break;
-
- case BRCMF_E_RSSI:
- BRCMF_EVENT(("MACEVENT: %s %d\n", event_name,
- be32_to_cpu(*((int *)event_data))));
- break;
-
- default:
- BRCMF_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 */
- if (datalen) {
- buf = (unsigned char *) event_data;
- BRCMF_EVENT((" data (%d) : ", datalen));
- for (i = 0; i < datalen; i++)
- BRCMF_EVENT((" 0x%02x ", *buf++));
- BRCMF_EVENT(("\n"));
- }
-}
-#endif /* SHOW_EVENTS */
-
-int
-brcmf_c_host_event(struct brcmf_info *drvr_priv, 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;
- char *event_data;
- u32 type, status;
- u16 flags;
- int evlen;
-
- if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) {
- BRCMF_ERROR(("%s: mismatched OUI, bailing\n", __func__));
- 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_ERROR(("%s: mismatched subtype, bailing\n", __func__));
- 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:
- {
- struct brcmf_if_event *ifevent =
- (struct brcmf_if_event *) event_data;
- BRCMF_TRACE(("%s: if event\n", __func__));
-
- if (ifevent->ifidx > 0 &&
- ifevent->ifidx < BRCMF_MAX_IFS) {
- if (ifevent->action == BRCMF_E_IF_ADD)
- brcmf_add_if(drvr_priv, ifevent->ifidx,
- NULL, event->ifname,
- pvt_data->eth.h_dest,
- ifevent->flags,
- ifevent->bssidx);
- else
- brcmf_del_if(drvr_priv, ifevent->ifidx);
- } else {
- BRCMF_ERROR(("%s: Invalid ifidx %d for %s\n",
- __func__, ifevent->ifidx,
- event->ifname));
- }
- }
- /* send up the if event: btamp user needs it */
- *ifidx = brcmf_ifname2idx(drvr_priv, 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_priv, event->ifname);
- BRCMF_TRACE(("%s: MAC event %d, flags %x, status %x\n",
- __func__, type, flags, status));
-
- /* put it back to BRCMF_E_NDIS_LINK */
- if (type == BRCMF_E_NDIS_LINK) {
- u32 temp;
-
- temp = get_unaligned_be32(&event->event_type);
- BRCMF_TRACE(("Converted to WLC_E_LINK type %d\n",
- temp));
-
- temp = be32_to_cpu(BRCMF_E_NDIS_LINK);
- memcpy((void *)(&pvt_data->msg.event_type), &temp,
- sizeof(pvt_data->msg.event_type));
- }
- break;
- }
-
-#ifdef SHOW_EVENTS
- brcmf_c_show_host_event(event, event_data);
-#endif /* SHOW_EVENTS */
-
- 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_ERROR(("Mask invalid format. Needs to start with 0x\n"));
- return -1;
- }
- src = src + 2; /* Skip past 0x */
- if (strlen(src) % 2 != 0) {
- BRCMF_ERROR(("Mask invalid format. Length must be even.\n"));
- return -1;
- }
- for (i = 0; *src != '\0'; i++) {
- char num[3];
- strncpy(num, src, 2);
- num[2] = '\0';
- dst[i] = (u8) simple_strtoul(num, NULL, 16);
- src += 2;
- }
- return i;
-}
-
-void
-brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
- int master_mode)
-{
- char *argv[8];
- int i = 0;
- const char *str;
- int buf_len;
- int str_len;
- char *arg_save = 0, *arg_org = 0;
- int rc;
- char buf[128];
- struct brcmf_pkt_filter_enable enable_parm;
- struct brcmf_pkt_filter_enable *pkt_filterp;
-
- arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
- if (!arg_save) {
- BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
- goto fail;
- }
- arg_org = arg_save;
- memcpy(arg_save, arg, strlen(arg) + 1);
-
- argv[i] = strsep(&arg_save, " ");
-
- i = 0;
- if (NULL == argv[i]) {
- BRCMF_ERROR(("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 *) (buf + str_len + 1);
-
- /* Parse packet filter id. */
- enable_parm.id = simple_strtoul(argv[i], NULL, 0);
-
- /* Parse enable/disable value. */
- enable_parm.enable = enable;
-
- buf_len += sizeof(enable_parm);
- memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
-
- /* Enable/disable the specified filter. */
- rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
- rc = rc >= 0 ? 0 : rc;
- if (rc)
- BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
- __func__, arg, rc));
- else
- BRCMF_TRACE(("%s: successfully added pktfilter %s\n",
- __func__, arg));
-
- /* Contorl the master mode */
- brcmu_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf,
- sizeof(buf));
- rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf,
- sizeof(buf));
- rc = rc >= 0 ? 0 : rc;
- if (rc)
- BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
- __func__, arg, rc));
-
-fail:
- kfree(arg_org);
-}
-
-void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
-{
- const char *str;
- struct brcmf_pkt_filter pkt_filter;
- struct brcmf_pkt_filter *pkt_filterp;
- int buf_len;
- int str_len;
- int rc;
- u32 mask_size;
- u32 pattern_size;
- char *argv[8], *buf = 0;
- int i = 0;
- char *arg_save = 0, *arg_org = 0;
-
- arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
- if (!arg_save) {
- BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
- goto fail;
- }
-
- arg_org = arg_save;
-
- buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC);
- if (!buf) {
- BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
- goto fail;
- }
-
- strcpy(arg_save, arg);
-
- argv[i] = strsep(&arg_save, " ");
- while (argv[i++])
- argv[i] = strsep(&arg_save, " ");
-
- i = 0;
- if (NULL == argv[i]) {
- BRCMF_ERROR(("No args provided\n"));
- goto fail;
- }
-
- str = "pkt_filter_add";
- strcpy(buf, str);
- str_len = strlen(str);
- buf_len = str_len + 1;
-
- pkt_filterp = (struct brcmf_pkt_filter *) (buf + str_len + 1);
-
- /* Parse packet filter id. */
- pkt_filter.id = simple_strtoul(argv[i], NULL, 0);
-
- if (NULL == argv[++i]) {
- BRCMF_ERROR(("Polarity not provided\n"));
- goto fail;
- }
-
- /* Parse filter polarity. */
- pkt_filter.negate_match = simple_strtoul(argv[i], NULL, 0);
-
- if (NULL == argv[++i]) {
- BRCMF_ERROR(("Filter type not provided\n"));
- goto fail;
- }
-
- /* Parse filter type. */
- pkt_filter.type = simple_strtoul(argv[i], NULL, 0);
-
- if (NULL == argv[++i]) {
- BRCMF_ERROR(("Offset not provided\n"));
- goto fail;
- }
-
- /* Parse pattern filter offset. */
- pkt_filter.u.pattern.offset = simple_strtoul(argv[i], NULL, 0);
-
- if (NULL == argv[++i]) {
- BRCMF_ERROR(("Bitmask not provided\n"));
- goto fail;
- }
-
- /* 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_ERROR(("Pattern not provided\n"));
- goto fail;
- }
-
- /* Parse pattern filter pattern. */
- pattern_size =
- brcmf_c_pattern_atoh(argv[i],
- (char *)&pkt_filterp->u.pattern.
- mask_and_pattern[mask_size]);
-
- if (mask_size != pattern_size) {
- BRCMF_ERROR(("Mask and pattern not the same size\n"));
- goto fail;
- }
-
- pkt_filter.u.pattern.size_bytes = 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_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
- rc = rc >= 0 ? 0 : rc;
-
- if (rc)
- BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
- __func__, arg, rc));
- else
- BRCMF_TRACE(("%s: successfully added pktfilter %s\n",
- __func__, arg));
-
-fail:
- kfree(arg_org);
-
- kfree(buf);
-}
-
-void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
-{
- char iovbuf[32];
- int retcode;
-
- brcmu_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
- retcode = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR,
- iovbuf, sizeof(iovbuf));
- retcode = retcode >= 0 ? 0 : retcode;
- if (retcode)
- BRCMF_TRACE(("%s: failed to set ARP offload mode to 0x%x, "
- "retcode = %d\n", __func__, arp_mode, retcode));
- else
- BRCMF_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
- __func__, arp_mode));
-}
-
-void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
-{
- char iovbuf[32];
- int retcode;
-
- brcmu_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
- retcode = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR,
- iovbuf, sizeof(iovbuf));
- retcode = retcode >= 0 ? 0 : retcode;
- if (retcode)
- BRCMF_TRACE(("%s: failed to enabe ARP offload to %d, "
- "retcode = %d\n", __func__, arp_enable, retcode));
- else
- BRCMF_TRACE(("%s: successfully enabed ARP offload to %d\n",
- __func__, arp_enable));
-}
-
-int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr)
-{
- char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for
- "event_msgs" + '\0' + bitvec */
- uint up = 0;
- char buf[128], *ptr;
- uint power_mode = PM_FAST;
- u32 dongle_align = BRCMF_SDALIGN;
- u32 glom = 0;
- uint bcn_timeout = 3;
- int scan_assoc_time = 40;
- int scan_unassoc_time = 40;
- int i;
-
- brcmf_os_proto_block(drvr);
-
- /* Set Country code */
- if (drvr->country_code[0] != 0) {
- if (brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_COUNTRY,
- drvr->country_code,
- sizeof(drvr->country_code)) < 0) {
- BRCMF_ERROR(("%s: country code setting failed\n",
- __func__));
- }
- }
-
- /* query for 'ver' to get version info from firmware */
- memset(buf, 0, sizeof(buf));
- ptr = buf;
- brcmu_mkiovar("ver", 0, 0, buf, sizeof(buf));
- brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf));
- strsep(&ptr, "\n");
- /* Print fw version info */
- BRCMF_ERROR(("Firmware version = %s\n", buf));
-
- /* Set PowerSave mode */
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_PM, (char *)&power_mode,
- sizeof(power_mode));
-
- /* Match Host and Dongle rx alignment */
- brcmu_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
- sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
- sizeof(iovbuf));
-
- /* disable glom option per default */
- brcmu_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
- sizeof(iovbuf));
-
- /* Setup timeout if Beacons are lost and roam is off to report
- link down */
- brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
- sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
- sizeof(iovbuf));
-
- /* Enable/Disable build-in roaming to allowed ext supplicant to take
- of romaing */
- brcmu_mkiovar("roam_off", (char *)&brcmf_roam, 4,
- iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
- sizeof(iovbuf));
-
- /* Force STA UP */
- if (brcmf_radio_up)
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_UP, (char *)&up,
- sizeof(up));
-
- /* Setup event_msgs */
- brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
- iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
- sizeof(iovbuf));
-
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
- (char *)&scan_assoc_time, sizeof(scan_assoc_time));
- brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
- (char *)&scan_unassoc_time, sizeof(scan_unassoc_time));
-
- /* Set and enable ARP offload feature */
- if (brcmf_arp_enable)
- brcmf_c_arp_offload_set(drvr, brcmf_arp_mode);
- brcmf_c_arp_offload_enable(drvr, brcmf_arp_enable);
-
- /* Set up pkt filter */
- if (brcmf_pkt_filter_enable) {
- 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],
- brcmf_pkt_filter_init,
- brcmf_master_mode);
- }
- }
-
- brcmf_os_proto_unblock(drvr);
-
- return 0;
-}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
deleted file mode 100644
index 05dada98eb6b..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+++ /dev/null
@@ -1,1736 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#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/interrupt.h>
-#include <linux/hardirq.h>
-#include <net/cfg80211.h>
-#include <defs.h>
-#include <brcmu_utils.h>
-#include <brcmu_wifi.h>
-
-#include "dhd.h"
-#include "dhd_bus.h"
-#include "dhd_proto.h"
-#include "dhd_dbg.h"
-#include "wl_cfg80211.h"
-#include "bcmchip.h"
-
-#if defined(CONFIG_PM_SLEEP)
-#include <linux/suspend.h>
-atomic_t brcmf_mmc_suspend;
-#endif /* defined(CONFIG_PM_SLEEP) */
-
-MODULE_AUTHOR("Broadcom Corporation");
-MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
-MODULE_LICENSE("Dual BSD/GPL");
-
-
-/* Interface control information */
-struct brcmf_if {
- struct brcmf_info *info; /* back pointer to brcmf_info */
- /* OS/stack specifics */
- struct net_device *net;
- struct net_device_stats stats;
- int idx; /* iface idx in dongle */
- int state; /* interface state */
- uint subunit; /* subunit */
- u8 mac_addr[ETH_ALEN]; /* assigned MAC address */
- bool attached; /* Delayed attachment when unset */
- bool txflowcontrol; /* Per interface flow control indicator */
- char name[IFNAMSIZ]; /* linux interface name */
-};
-
-/* Local private structure (extension of pub) */
-struct brcmf_info {
- struct brcmf_pub pub;
-
- /* OS/stack specifics */
- struct brcmf_if *iflist[BRCMF_MAX_IFS];
-
- struct semaphore proto_sem;
- wait_queue_head_t ioctl_resp_wait;
-
- /* Thread to issue ioctl for multicast */
- struct task_struct *sysioc_tsk;
- struct semaphore sysioc_sem;
- bool set_multicast;
- bool set_macaddress;
- u8 macvalue[ETH_ALEN];
- atomic_t pend_8021x_cnt;
-};
-
-/* Error bits */
-module_param(brcmf_msg_level, int, 0);
-
-/* Spawn a thread for system ioctls (set mac, set mcast) */
-uint brcmf_sysioc = true;
-module_param(brcmf_sysioc, uint, 0);
-
-/* ARP offload agent mode : Enable ARP Host Auto-Reply
-and ARP Peer Auto-Reply */
-uint brcmf_arp_mode = 0xb;
-module_param(brcmf_arp_mode, uint, 0);
-
-/* ARP offload enable */
-uint brcmf_arp_enable = true;
-module_param(brcmf_arp_enable, uint, 0);
-
-/* Global Pkt filter enable control */
-uint brcmf_pkt_filter_enable = true;
-module_param(brcmf_pkt_filter_enable, uint, 0);
-
-/* Pkt filter init setup */
-uint brcmf_pkt_filter_init;
-module_param(brcmf_pkt_filter_init, uint, 0);
-
-/* Pkt filter mode control */
-uint brcmf_master_mode = true;
-module_param(brcmf_master_mode, uint, 0);
-
-module_param(brcmf_dongle_memsize, int, 0);
-
-/* Contorl fw roaming */
-uint brcmf_roam = 1;
-
-/* Control radio state */
-uint brcmf_radio_up = 1;
-
-/* Network inteface name */
-char iface_name[IFNAMSIZ] = "wlan";
-module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
-
-/* The following are specific to the SDIO dongle */
-
-/* IOCTL response timeout */
-int brcmf_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT;
-
-/* Idle timeout for backplane clock */
-int brcmf_idletime = BRCMF_IDLETIME_TICKS;
-module_param(brcmf_idletime, int, 0);
-
-/* Use polling */
-uint brcmf_poll;
-module_param(brcmf_poll, uint, 0);
-
-/* Use interrupts */
-uint brcmf_intr = true;
-module_param(brcmf_intr, uint, 0);
-
-/* SDIO Drive Strength (in milliamps) */
-uint brcmf_sdiod_drive_strength = 6;
-module_param(brcmf_sdiod_drive_strength, uint, 0);
-
-/* Tx/Rx bounds */
-module_param(brcmf_txbound, uint, 0);
-module_param(brcmf_rxbound, uint, 0);
-
-#ifdef SDTEST
-/* Echo packet generator (pkts/s) */
-uint brcmf_pktgen;
-module_param(brcmf_pktgen, uint, 0);
-
-/* Echo packet len (0 => sawtooth, max 2040) */
-uint brcmf_pktgen_len;
-module_param(brcmf_pktgen_len, uint, 0);
-#endif
-
-static int brcmf_toe_get(struct brcmf_info *drvr_priv, int idx, u32 *toe_ol);
-static int brcmf_toe_set(struct brcmf_info *drvr_priv, int idx, u32 toe_ol);
-static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
- struct brcmf_event_msg *event_ptr,
- void **data_ptr);
-
-/*
- * Generalized timeout mechanism. Uses spin sleep with exponential
- * back-off until
- * the sleep time reaches one jiffy, then switches over to task delay. Usage:
- *
- * brcmf_timeout_start(&tmo, usec);
- * while (!brcmf_timeout_expired(&tmo))
- * if (poll_something())
- * break;
- * if (brcmf_timeout_expired(&tmo))
- * fatal();
- */
-
-void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec)
-{
- tmo->limit = usec;
- tmo->increment = 0;
- tmo->elapsed = 0;
- tmo->tick = 1000000 / HZ;
-}
-
-int brcmf_timeout_expired(struct brcmf_timeout *tmo)
-{
- /* Does nothing the first call */
- if (tmo->increment == 0) {
- tmo->increment = 1;
- return 0;
- }
-
- if (tmo->elapsed >= tmo->limit)
- return 1;
-
- /* Add the delay that's about to take place */
- tmo->elapsed += tmo->increment;
-
- if (tmo->increment < tmo->tick) {
- udelay(tmo->increment);
- tmo->increment *= 2;
- if (tmo->increment > tmo->tick)
- tmo->increment = tmo->tick;
- } else {
- wait_queue_head_t delay_wait;
- DECLARE_WAITQUEUE(wait, current);
- int pending;
- init_waitqueue_head(&delay_wait);
- add_wait_queue(&delay_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- pending = signal_pending(current);
- remove_wait_queue(&delay_wait, &wait);
- set_current_state(TASK_RUNNING);
- if (pending)
- return 1; /* Interrupted */
- }
-
- return 0;
-}
-
-static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *net)
-{
- int i = 0;
-
- while (i < BRCMF_MAX_IFS) {
- if (drvr_priv->iflist[i] && (drvr_priv->iflist[i]->net == net))
- return i;
- i++;
- }
-
- return BRCMF_BAD_IF;
-}
-
-int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
-{
- int i = BRCMF_MAX_IFS;
-
- if (name == NULL || *name == '\0')
- return 0;
-
- while (--i > 0)
- if (drvr_priv->iflist[i]
- && !strncmp(drvr_priv->iflist[i]->name, name, IFNAMSIZ))
- break;
-
- BRCMF_TRACE(("%s: return idx %d for \"%s\"\n", __func__, i, name));
-
- return i; /* default - the primary interface */
-}
-
-char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
-{
- struct brcmf_info *drvr_priv = drvr->info;
-
- if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
- BRCMF_ERROR(("%s: ifidx %d out of range\n", __func__, ifidx));
- return "<if_bad>";
- }
-
- if (drvr_priv->iflist[ifidx] == NULL) {
- BRCMF_ERROR(("%s: null i/f %d\n", __func__, ifidx));
- return "<if_null>";
- }
-
- if (drvr_priv->iflist[ifidx]->net)
- return drvr_priv->iflist[ifidx]->net->name;
-
- return "<if_none>";
-}
-
-static void _brcmf_set_multicast_list(struct brcmf_info *drvr_priv, int ifidx)
-{
- struct net_device *dev;
- struct netdev_hw_addr *ha;
- u32 allmulti, cnt;
-
- struct brcmf_ioctl ioc;
- char *buf, *bufp;
- uint buflen;
- int ret;
-
- dev = drvr_priv->iflist[ifidx]->net;
- cnt = netdev_mc_count(dev);
-
- /* Determine initial value of allmulti flag */
- allmulti = (dev->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) {
- BRCMF_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), cnt));
- return;
- }
-
- strcpy(bufp, "mcast_list");
- bufp += strlen("mcast_list") + 1;
-
- cnt = cpu_to_le32(cnt);
- memcpy(bufp, &cnt, sizeof(cnt));
- bufp += sizeof(cnt);
-
- netdev_for_each_mc_addr(ha, dev) {
- if (!cnt)
- break;
- memcpy(bufp, ha->addr, ETH_ALEN);
- bufp += ETH_ALEN;
- cnt--;
- }
-
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = BRCMF_C_SET_VAR;
- ioc.buf = buf;
- ioc.len = buflen;
- ioc.set = true;
-
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
- if (ret < 0) {
- BRCMF_ERROR(("%s: set mcast_list failed, cnt %d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), cnt));
- allmulti = cnt ? true : allmulti;
- }
-
- kfree(buf);
-
- /* 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...
- */
-
- buflen = sizeof("allmulti") + sizeof(allmulti);
- buf = kmalloc(buflen, GFP_ATOMIC);
- if (!buf) {
- BRCMF_ERROR(("%s: out of memory for allmulti\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
- return;
- }
- allmulti = cpu_to_le32(allmulti);
-
- if (!brcmu_mkiovar
- ("allmulti", (void *)&allmulti, sizeof(allmulti), buf, buflen)) {
- BRCMF_ERROR(("%s: mkiovar failed for allmulti, datalen %d "
- "buflen %u\n",
- brcmf_ifname(&drvr_priv->pub, ifidx),
- (int)sizeof(allmulti), buflen));
- kfree(buf);
- return;
- }
-
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = BRCMF_C_SET_VAR;
- ioc.buf = buf;
- ioc.len = buflen;
- ioc.set = true;
-
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
- if (ret < 0) {
- BRCMF_ERROR(("%s: set allmulti %d failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx),
- le32_to_cpu(allmulti)));
- }
-
- kfree(buf);
-
- /* Finally, pick up the PROMISC flag as well, like the NIC
- driver does */
-
- allmulti = (dev->flags & IFF_PROMISC) ? true : false;
- allmulti = cpu_to_le32(allmulti);
-
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = BRCMF_C_SET_PROMISC;
- ioc.buf = &allmulti;
- ioc.len = sizeof(allmulti);
- ioc.set = true;
-
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
- if (ret < 0) {
- BRCMF_ERROR(("%s: set promisc %d failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx),
- le32_to_cpu(allmulti)));
- }
-}
-
-static int _brcmf_set_mac_address(struct brcmf_info *drvr_priv, int ifidx, u8 *addr)
-{
- char buf[32];
- struct brcmf_ioctl ioc;
- int ret;
-
- BRCMF_TRACE(("%s enter\n", __func__));
- if (!brcmu_mkiovar
- ("cur_etheraddr", (char *)addr, ETH_ALEN, buf, 32)) {
- BRCMF_ERROR(("%s: mkiovar failed for cur_etheraddr\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
- return -1;
- }
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = BRCMF_C_SET_VAR;
- ioc.buf = buf;
- ioc.len = 32;
- ioc.set = true;
-
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
- if (ret < 0) {
- BRCMF_ERROR(("%s: set cur_etheraddr failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
- } else {
- memcpy(drvr_priv->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN);
- }
-
- return ret;
-}
-
-#ifdef SOFTAP
-extern struct net_device *ap_net_dev;
-#endif
-
-/* Virtual interfaces only ((ifp && ifp->info && ifp->idx == true) */
-static void brcmf_op_if(struct brcmf_if *ifp)
-{
- struct brcmf_info *drvr_priv;
- int ret = 0, err = 0;
-
- drvr_priv = ifp->info;
-
- BRCMF_TRACE(("%s: idx %d, state %d\n", __func__, ifp->idx, ifp->state));
-
- switch (ifp->state) {
- case BRCMF_E_IF_ADD:
- /*
- * Delete the existing interface before overwriting it
- * in case we missed the BRCMF_E_IF_DEL event.
- */
- if (ifp->net != NULL) {
- BRCMF_ERROR(("%s: ERROR: netdev:%s already exists, "
- "try free & unregister\n",
- __func__, ifp->net->name));
- netif_stop_queue(ifp->net);
- unregister_netdev(ifp->net);
- free_netdev(ifp->net);
- }
- /* Allocate etherdev, including space for private structure */
- ifp->net = alloc_etherdev(sizeof(drvr_priv));
- if (!ifp->net) {
- BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
- ret = -ENOMEM;
- }
- if (ret == 0) {
- strcpy(ifp->net->name, ifp->name);
- memcpy(netdev_priv(ifp->net), &drvr_priv, sizeof(drvr_priv));
- err = brcmf_net_attach(&drvr_priv->pub, ifp->idx);
- if (err != 0) {
- BRCMF_ERROR(("%s: brcmf_net_attach failed, "
- "err %d\n",
- __func__, err));
- ret = -EOPNOTSUPP;
- } else {
-#ifdef SOFTAP
- /* semaphore that the soft AP CODE
- waits on */
- extern struct semaphore ap_eth_sema;
-
- /* save ptr to wl0.1 netdev for use
- in wl_iw.c */
- ap_net_dev = ifp->net;
- /* signal to the SOFTAP 'sleeper' thread,
- wl0.1 is ready */
- up(&ap_eth_sema);
-#endif
- BRCMF_TRACE(("\n ==== pid:%x, net_device for "
- "if:%s created ===\n\n",
- current->pid, ifp->net->name));
- ifp->state = 0;
- }
- }
- break;
- case BRCMF_E_IF_DEL:
- if (ifp->net != NULL) {
- BRCMF_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n",
- __func__));
- netif_stop_queue(ifp->net);
- unregister_netdev(ifp->net);
- ret = BRCMF_DEL_IF; /* Make sure the free_netdev()
- is called */
- }
- break;
- default:
- BRCMF_ERROR(("%s: bad op %d\n", __func__, ifp->state));
- break;
- }
-
- if (ret < 0) {
- if (ifp->net)
- free_netdev(ifp->net);
-
- drvr_priv->iflist[ifp->idx] = NULL;
- kfree(ifp);
-#ifdef SOFTAP
- if (ifp->net == ap_net_dev)
- ap_net_dev = NULL; /* NULL SOFTAP global
- wl0.1 as well */
-#endif /* SOFTAP */
- }
-}
-
-static int _brcmf_sysioc_thread(void *data)
-{
- struct brcmf_info *drvr_priv = (struct brcmf_info *) data;
- int i;
-#ifdef SOFTAP
- bool in_ap = false;
-#endif
-
- allow_signal(SIGTERM);
-
- while (down_interruptible(&drvr_priv->sysioc_sem) == 0) {
- if (kthread_should_stop())
- break;
- for (i = 0; i < BRCMF_MAX_IFS; i++) {
- struct brcmf_if *ifentry = drvr_priv->iflist[i];
- if (ifentry) {
-#ifdef SOFTAP
- in_ap = (ap_net_dev != NULL);
-#endif /* SOFTAP */
- if (ifentry->state)
- brcmf_op_if(ifentry);
-#ifdef SOFTAP
- if (drvr_priv->iflist[i] == NULL) {
- BRCMF_TRACE(("\n\n %s: interface %d "
- "removed!\n", __func__,
- i));
- continue;
- }
-
- if (in_ap && drvr_priv->set_macaddress) {
- BRCMF_TRACE(("attempt to set MAC for"
- " %s in AP Mode,"
- " blocked.\n",
- ifentry->net->name));
- drvr_priv->set_macaddress = false;
- continue;
- }
-
- if (in_ap && drvr_priv->set_multicast) {
- BRCMF_TRACE(("attempt to set MULTICAST "
- "list for %s in AP Mode, "
- "blocked.\n",
- ifentry->net->name));
- drvr_priv->set_multicast = false;
- continue;
- }
-#endif /* SOFTAP */
- if (drvr_priv->set_multicast) {
- drvr_priv->set_multicast = false;
- _brcmf_set_multicast_list(drvr_priv, i);
- }
- if (drvr_priv->set_macaddress) {
- drvr_priv->set_macaddress = false;
- _brcmf_set_mac_address(drvr_priv, i,
- drvr_priv->macvalue);
- }
- }
- }
- }
- return 0;
-}
-
-static int brcmf_netdev_set_mac_address(struct net_device *dev, void *addr)
-{
- int ret = 0;
-
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
- struct sockaddr *sa = (struct sockaddr *)addr;
- int ifidx;
-
- ifidx = brcmf_net2idx(drvr_priv, dev);
- if (ifidx == BRCMF_BAD_IF)
- return -1;
-
- memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
- drvr_priv->set_macaddress = true;
- up(&drvr_priv->sysioc_sem);
-
- return ret;
-}
-
-static void brcmf_netdev_set_multicast_list(struct net_device *dev)
-{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
- int ifidx;
-
- ifidx = brcmf_net2idx(drvr_priv, dev);
- if (ifidx == BRCMF_BAD_IF)
- return;
-
- drvr_priv->set_multicast = true;
- up(&drvr_priv->sysioc_sem);
-}
-
-int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
-{
- struct brcmf_info *drvr_priv = drvr->info;
-
- /* Reject if down */
- if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN))
- return -ENODEV;
-
- /* Update multicast statistic */
- if (pktbuf->len >= ETH_ALEN) {
- u8 *pktdata = (u8 *) (pktbuf->data);
- struct ethhdr *eh = (struct ethhdr *)pktdata;
-
- if (is_multicast_ether_addr(eh->h_dest))
- drvr->tx_multicast++;
- if (ntohs(eh->h_proto) == ETH_P_PAE)
- atomic_inc(&drvr_priv->pend_8021x_cnt);
- }
-
- /* If the protocol uses a data header, apply it */
- brcmf_proto_hdrpush(drvr, ifidx, pktbuf);
-
- /* Use bus module to send data frame */
- return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf);
-}
-
-static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *net)
-{
- int ret;
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
- int ifidx;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* Reject if down */
- if (!drvr_priv->pub.up || (drvr_priv->pub.busstate == BRCMF_BUS_DOWN)) {
- BRCMF_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n",
- __func__, drvr_priv->pub.up,
- drvr_priv->pub.busstate));
- netif_stop_queue(net);
- return -ENODEV;
- }
-
- ifidx = brcmf_net2idx(drvr_priv, net);
- if (ifidx == BRCMF_BAD_IF) {
- BRCMF_ERROR(("%s: bad ifidx %d\n", __func__, ifidx));
- netif_stop_queue(net);
- return -ENODEV;
- }
-
- /* Make sure there's enough room for any header */
- if (skb_headroom(skb) < drvr_priv->pub.hdrlen) {
- struct sk_buff *skb2;
-
- BRCMF_INFO(("%s: insufficient headroom\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
- drvr_priv->pub.tx_realloc++;
- skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
- dev_kfree_skb(skb);
- skb = skb2;
- if (skb == NULL) {
- BRCMF_ERROR(("%s: skb_realloc_headroom failed\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
- ret = -ENOMEM;
- goto done;
- }
- }
-
- ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb);
-
-done:
- if (ret)
- drvr_priv->pub.dstats.tx_dropped++;
- else
- drvr_priv->pub.tx_packets++;
-
- /* Return ok: we always eat the packet */
- return 0;
-}
-
-void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state)
-{
- struct net_device *net;
- struct brcmf_info *drvr_priv = drvr->info;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- drvr->txoff = state;
- net = drvr_priv->iflist[ifidx]->net;
- if (state == ON)
- netif_stop_queue(net);
- else
- netif_wake_queue(net);
-}
-
-void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
- int numpkt)
-{
- struct brcmf_info *drvr_priv = drvr->info;
- unsigned char *eth;
- uint len;
- void *data;
- struct sk_buff *pnext, *save_pktbuf;
- int i;
- struct brcmf_if *ifp;
- struct brcmf_event_msg event;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- save_pktbuf = skb;
-
- for (i = 0; skb && i < numpkt; i++, skb = pnext) {
-
- pnext = skb->next;
- skb->next = NULL;
-
- /* Get the protocol, maintain skb around eth_type_trans()
- * The main reason for this hack is for the limitation of
- * Linux 2.4 where 'eth_type_trans' uses the
- * 'net->hard_header_len'
- * to perform skb_pull inside vs ETH_HLEN. Since to avoid
- * coping of the packet coming from the network stack to add
- * BDC, Hardware header etc, during network interface
- * registration
- * we set the 'net->hard_header_len' to ETH_HLEN + extra space
- * required
- * for BDC, Hardware header etc. and not just the ETH_HLEN
- */
- eth = skb->data;
- len = skb->len;
-
- ifp = drvr_priv->iflist[ifidx];
- if (ifp == NULL)
- ifp = drvr_priv->iflist[0];
-
- skb->dev = ifp->net;
- skb->protocol = eth_type_trans(skb, skb->dev);
-
- if (skb->pkt_type == PACKET_MULTICAST)
- drvr_priv->pub.rx_multicast++;
-
- skb->data = eth;
- skb->len = len;
-
- /* Strip header, count, deliver upward */
- 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_priv, &ifidx,
- skb_mac_header(skb),
- &event, &data);
-
- if (drvr_priv->iflist[ifidx] &&
- !drvr_priv->iflist[ifidx]->state)
- ifp = drvr_priv->iflist[ifidx];
-
- if (ifp->net)
- ifp->net->last_rx = jiffies;
-
- drvr->dstats.rx_bytes += skb->len;
- drvr->rx_packets++; /* Local count */
-
- if (in_interrupt()) {
- netif_rx(skb);
- } else {
- /* If the receive is not processed inside an ISR,
- * the softirqd must be woken explicitly to service
- * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled
- * by netif_rx_ni(), but in earlier kernels, we need
- * to do it manually.
- */
- netif_rx_ni(skb);
- }
- }
-}
-
-void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
-{
- uint ifidx;
- struct brcmf_info *drvr_priv = drvr->info;
- struct ethhdr *eh;
- u16 type;
-
- brcmf_proto_hdrpull(drvr, &ifidx, txp);
-
- eh = (struct ethhdr *)(txp->data);
- type = ntohs(eh->h_proto);
-
- if (type == ETH_P_PAE)
- atomic_dec(&drvr_priv->pend_8021x_cnt);
-
-}
-
-static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *net)
-{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
- struct brcmf_if *ifp;
- int ifidx;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- ifidx = brcmf_net2idx(drvr_priv, net);
- if (ifidx == BRCMF_BAD_IF)
- return NULL;
-
- ifp = drvr_priv->iflist[ifidx];
-
- if (drvr_priv->pub.up) {
- /* Use the protocol to get dongle stats */
- brcmf_proto_dstats(&drvr_priv->pub);
- }
-
- /* Copy dongle stats to net device stats */
- ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets;
- ifp->stats.tx_packets = drvr_priv->pub.dstats.tx_packets;
- ifp->stats.rx_bytes = drvr_priv->pub.dstats.rx_bytes;
- ifp->stats.tx_bytes = drvr_priv->pub.dstats.tx_bytes;
- ifp->stats.rx_errors = drvr_priv->pub.dstats.rx_errors;
- ifp->stats.tx_errors = drvr_priv->pub.dstats.tx_errors;
- ifp->stats.rx_dropped = drvr_priv->pub.dstats.rx_dropped;
- ifp->stats.tx_dropped = drvr_priv->pub.dstats.tx_dropped;
- ifp->stats.multicast = drvr_priv->pub.dstats.multicast;
-
- 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_info *drvr_priv, int ifidx, u32 *toe_ol)
-{
- struct brcmf_ioctl ioc;
- char buf[32];
- int ret;
-
- memset(&ioc, 0, sizeof(ioc));
-
- ioc.cmd = BRCMF_C_GET_VAR;
- ioc.buf = buf;
- ioc.len = (uint) sizeof(buf);
- ioc.set = false;
-
- strcpy(buf, "toe_ol");
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
- if (ret < 0) {
- /* Check for older dongle image that doesn't support toe_ol */
- if (ret == -EIO) {
- BRCMF_ERROR(("%s: toe not supported by device\n",
- brcmf_ifname(&drvr_priv->pub, ifidx)));
- return -EOPNOTSUPP;
- }
-
- BRCMF_INFO(("%s: could not get toe_ol: ret=%d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), ret));
- return ret;
- }
-
- memcpy(toe_ol, buf, sizeof(u32));
- return 0;
-}
-
-/* Set current toe component enables in toe_ol iovar,
- and set toe global enable iovar */
-static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
-{
- struct brcmf_ioctl ioc;
- char buf[32];
- int toe, ret;
-
- memset(&ioc, 0, sizeof(ioc));
-
- ioc.cmd = BRCMF_C_SET_VAR;
- ioc.buf = buf;
- ioc.len = (uint) sizeof(buf);
- ioc.set = true;
-
- /* Set toe_ol as requested */
-
- strcpy(buf, "toe_ol");
- memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(u32));
-
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
- if (ret < 0) {
- BRCMF_ERROR(("%s: could not set toe_ol: ret=%d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), ret));
- return ret;
- }
-
- /* Enable toe globally only if any components are enabled. */
-
- toe = (toe_ol != 0);
-
- strcpy(buf, "toe");
- memcpy(&buf[sizeof("toe")], &toe, sizeof(u32));
-
- ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
- if (ret < 0) {
- BRCMF_ERROR(("%s: could not set toe: ret=%d\n",
- brcmf_ifname(&drvr_priv->pub, ifidx), ret));
- return ret;
- }
-
- return 0;
-}
-
-static void brcmf_ethtool_get_drvinfo(struct net_device *net,
- struct ethtool_drvinfo *info)
-{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
-
- sprintf(info->driver, KBUILD_MODNAME);
- sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
- sprintf(info->fw_version, "%s", BCM4329_FW_NAME);
- sprintf(info->bus_info, "%s",
- dev_name(&brcmf_cfg80211_get_sdio_func()->dev));
-}
-
-struct ethtool_ops brcmf_ethtool_ops = {
- .get_drvinfo = brcmf_ethtool_get_drvinfo
-};
-
-static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
-{
- struct ethtool_drvinfo info;
- char drvname[sizeof(info.driver)];
- u32 cmd;
- struct ethtool_value edata;
- u32 toe_cmpnt, csum_dir;
- int ret;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* all ethtool calls start with a cmd word */
- if (copy_from_user(&cmd, uaddr, sizeof(u32)))
- return -EFAULT;
-
- switch (cmd) {
- case ETHTOOL_GDRVINFO:
- /* Copy out any request driver name */
- if (copy_from_user(&info, uaddr, sizeof(info)))
- return -EFAULT;
- strncpy(drvname, info.driver, sizeof(info.driver));
- drvname[sizeof(info.driver) - 1] = '\0';
-
- /* clear struct for return */
- memset(&info, 0, sizeof(info));
- info.cmd = cmd;
-
- /* if requested, identify ourselves */
- if (strcmp(drvname, "?dhd") == 0) {
- sprintf(info.driver, "dhd");
- strcpy(info.version, BRCMF_VERSION_STR);
- }
-
- /* otherwise, require dongle to be up */
- else if (!drvr_priv->pub.up) {
- BRCMF_ERROR(("%s: dongle is not up\n", __func__));
- return -ENODEV;
- }
-
- /* finally, report dongle driver type */
- else if (drvr_priv->pub.iswl)
- sprintf(info.driver, "wl");
- else
- sprintf(info.driver, "xx");
-
- sprintf(info.version, "%lu", drvr_priv->pub.drv_version);
- if (copy_to_user(uaddr, &info, sizeof(info)))
- return -EFAULT;
- BRCMF_CTL(("%s: given %*s, returning %s\n", __func__,
- (int)sizeof(drvname), drvname, info.driver));
- break;
-
- /* Get toe offload components from dongle */
- case ETHTOOL_GRXCSUM:
- case ETHTOOL_GTXCSUM:
- ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
- if (ret < 0)
- return ret;
-
- csum_dir =
- (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
-
- edata.cmd = cmd;
- edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;
-
- if (copy_to_user(uaddr, &edata, sizeof(edata)))
- return -EFAULT;
- break;
-
- /* Set toe offload components in dongle */
- case ETHTOOL_SRXCSUM:
- case ETHTOOL_STXCSUM:
- if (copy_from_user(&edata, uaddr, sizeof(edata)))
- return -EFAULT;
-
- /* Read the current settings, update and write back */
- ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
- if (ret < 0)
- return ret;
-
- csum_dir =
- (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
-
- if (edata.data != 0)
- toe_cmpnt |= csum_dir;
- else
- toe_cmpnt &= ~csum_dir;
-
- ret = brcmf_toe_set(drvr_priv, 0, 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_priv->iflist[0]->net->features |=
- NETIF_F_IP_CSUM;
- else
- drvr_priv->iflist[0]->net->features &=
- ~NETIF_F_IP_CSUM;
- }
-
- break;
-
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-static int brcmf_netdev_ioctl_entry(struct net_device *net, struct ifreq *ifr,
- int cmd)
-{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
- struct brcmf_c_ioctl ioc;
- int bcmerror = 0;
- int buflen = 0;
- void *buf = NULL;
- uint driver = 0;
- int ifidx;
- bool is_set_key_cmd;
-
- ifidx = brcmf_net2idx(drvr_priv, net);
- BRCMF_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __func__, ifidx, cmd));
-
- if (ifidx == BRCMF_BAD_IF)
- return -1;
-
- if (cmd == SIOCETHTOOL)
- return brcmf_ethtool(drvr_priv, (void *)ifr->ifr_data);
-
- if (cmd != SIOCDEVPRIVATE)
- return -EOPNOTSUPP;
-
- memset(&ioc, 0, sizeof(ioc));
-
- /* Copy the ioc control structure part of ioctl request */
- if (copy_from_user(&ioc, ifr->ifr_data, sizeof(struct brcmf_ioctl))) {
- bcmerror = -EINVAL;
- goto done;
- }
-
- /* Copy out any buffer passed */
- if (ioc.buf) {
- buflen = min_t(int, ioc.len, BRCMF_IOCTL_MAXLEN);
- /* optimization for direct ioctl calls from kernel */
- /*
- if (segment_eq(get_fs(), KERNEL_DS)) {
- buf = ioc.buf;
- } else {
- */
- {
- buf = kmalloc(buflen, GFP_ATOMIC);
- if (!buf) {
- bcmerror = -ENOMEM;
- goto done;
- }
- if (copy_from_user(buf, ioc.buf, buflen)) {
- bcmerror = -EINVAL;
- goto done;
- }
- }
- }
-
- /* To differentiate read 4 more byes */
- if ((copy_from_user(&driver, (char *)ifr->ifr_data +
- sizeof(struct brcmf_ioctl), sizeof(uint)) != 0)) {
- bcmerror = -EINVAL;
- goto done;
- }
-
- if (!capable(CAP_NET_ADMIN)) {
- bcmerror = -EPERM;
- goto done;
- }
-
- /* check for local brcmf ioctl and handle it */
- if (driver == BRCMF_IOCTL_MAGIC) {
- bcmerror = brcmf_c_ioctl((void *)&drvr_priv->pub, &ioc, buf, buflen);
- if (bcmerror)
- drvr_priv->pub.bcmerror = bcmerror;
- goto done;
- }
-
- /* send to dongle (must be up, and wl) */
- if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) {
- BRCMF_ERROR(("%s DONGLE_DOWN,__func__\n", __func__));
- bcmerror = -EIO;
- goto done;
- }
-
- if (!drvr_priv->pub.iswl) {
- bcmerror = -EIO;
- goto done;
- }
-
- /*
- * Intercept BRCMF_C_SET_KEY IOCTL - serialize M4 send and
- * set key IOCTL to prevent M4 encryption.
- */
- is_set_key_cmd = ((ioc.cmd == BRCMF_C_SET_KEY) ||
- ((ioc.cmd == BRCMF_C_SET_VAR) &&
- !(strncmp("wsec_key", ioc.buf, 9))) ||
- ((ioc.cmd == BRCMF_C_SET_VAR) &&
- !(strncmp("bsscfg:wsec_key", ioc.buf, 15))));
- if (is_set_key_cmd)
- brcmf_netdev_wait_pend8021x(net);
-
- bcmerror =
- brcmf_proto_ioctl(&drvr_priv->pub, ifidx, (struct brcmf_ioctl *)&ioc,
- buf, buflen);
-
-done:
- if (!bcmerror && buf && ioc.buf) {
- if (copy_to_user(ioc.buf, buf, buflen))
- bcmerror = -EFAULT;
- }
-
- kfree(buf);
-
- if (bcmerror > 0)
- bcmerror = 0;
-
- return bcmerror;
-}
-
-static int brcmf_netdev_stop(struct net_device *net)
-{
-#if !defined(IGNORE_ETH0_DOWN)
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
- brcmf_cfg80211_down();
- if (drvr_priv->pub.up == 0)
- return 0;
-
- /* Set state and stop OS transmissions */
- drvr_priv->pub.up = 0;
- netif_stop_queue(net);
-#else
- BRCMF_ERROR(("BYPASS %s:due to BRCM compilation: under investigation\n",
- __func__));
-#endif /* !defined(IGNORE_ETH0_DOWN) */
-
- return 0;
-}
-
-static int brcmf_netdev_open(struct net_device *net)
-{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
- u32 toe_ol;
- int ifidx = brcmf_net2idx(drvr_priv, net);
- s32 ret = 0;
-
- BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx));
-
- if (ifidx == 0) { /* do it only for primary eth0 */
-
- /* try to bring up bus */
- ret = brcmf_bus_start(&drvr_priv->pub);
- if (ret != 0) {
- BRCMF_ERROR(("%s: failed with code %d\n",
- __func__, ret));
- return -1;
- }
- atomic_set(&drvr_priv->pend_8021x_cnt, 0);
-
- memcpy(net->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
-
- /* Get current TOE mode from dongle */
- if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0
- && (toe_ol & TOE_TX_CSUM_OL) != 0)
- drvr_priv->iflist[ifidx]->net->features |=
- NETIF_F_IP_CSUM;
- else
- drvr_priv->iflist[ifidx]->net->features &=
- ~NETIF_F_IP_CSUM;
- }
- /* Allow transmit calls */
- netif_start_queue(net);
- drvr_priv->pub.up = 1;
- if (unlikely(brcmf_cfg80211_up())) {
- BRCMF_ERROR(("%s: failed to bring up cfg80211\n",
- __func__));
- return -1;
- }
-
- return ret;
-}
-
-int
-brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle, char *name,
- u8 *mac_addr, u32 flags, u8 bssidx)
-{
- struct brcmf_if *ifp;
-
- BRCMF_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, handle));
-
- ifp = drvr_priv->iflist[ifidx];
- if (!ifp) {
- ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC);
- if (!ifp) {
- BRCMF_ERROR(("%s: OOM - struct brcmf_if\n", __func__));
- return -ENOMEM;
- }
- }
-
- memset(ifp, 0, sizeof(struct brcmf_if));
- ifp->info = drvr_priv;
- drvr_priv->iflist[ifidx] = ifp;
- strlcpy(ifp->name, name, IFNAMSIZ);
- if (mac_addr != NULL)
- memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
-
- if (handle == NULL) {
- ifp->state = BRCMF_E_IF_ADD;
- ifp->idx = ifidx;
- up(&drvr_priv->sysioc_sem);
- } else
- ifp->net = (struct net_device *)handle;
-
- return 0;
-}
-
-void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
-{
- struct brcmf_if *ifp;
-
- BRCMF_TRACE(("%s: idx %d\n", __func__, ifidx));
-
- ifp = drvr_priv->iflist[ifidx];
- if (!ifp) {
- BRCMF_ERROR(("%s: Null interface\n", __func__));
- return;
- }
-
- ifp->state = BRCMF_E_IF_DEL;
- ifp->idx = ifidx;
- up(&drvr_priv->sysioc_sem);
-}
-
-struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
-{
- struct brcmf_info *drvr_priv = NULL;
- struct net_device *net;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* Allocate etherdev, including space for private structure */
- net = alloc_etherdev(sizeof(drvr_priv));
- if (!net) {
- BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
- goto fail;
- }
-
- /* Allocate primary brcmf_info */
- drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
- if (!drvr_priv) {
- BRCMF_ERROR(("%s: OOM - alloc brcmf_info\n", __func__));
- goto fail;
- }
-
- /*
- * Save the brcmf_info into the priv
- */
- memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
-
- /* Set network interface name if it was provided as module parameter */
- if (iface_name[0]) {
- int len;
- char ch;
- strncpy(net->name, iface_name, IFNAMSIZ);
- net->name[IFNAMSIZ - 1] = 0;
- len = strlen(net->name);
- ch = net->name[len - 1];
- if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2))
- strcat(net->name, "%d");
- }
-
- if (brcmf_add_if(drvr_priv, 0, (void *)net, net->name, NULL, 0, 0) ==
- BRCMF_BAD_IF)
- goto fail;
-
- net->netdev_ops = NULL;
- sema_init(&drvr_priv->proto_sem, 1);
- /* Initialize other structure content */
- init_waitqueue_head(&drvr_priv->ioctl_resp_wait);
-
- /* Link to info module */
- drvr_priv->pub.info = drvr_priv;
-
- /* Link to bus module */
- drvr_priv->pub.bus = bus;
- drvr_priv->pub.hdrlen = bus_hdrlen;
-
- /* Attach and link in the protocol */
- if (brcmf_proto_attach(&drvr_priv->pub) != 0) {
- BRCMF_ERROR(("brcmf_prot_attach failed\n"));
- goto fail;
- }
-
- /* Attach and link in the cfg80211 */
- if (unlikely(brcmf_cfg80211_attach(net, &drvr_priv->pub))) {
- BRCMF_ERROR(("wl_cfg80211_attach failed\n"));
- goto fail;
- }
-
- if (brcmf_sysioc) {
- sema_init(&drvr_priv->sysioc_sem, 0);
- drvr_priv->sysioc_tsk = kthread_run(_brcmf_sysioc_thread, drvr_priv,
- "_brcmf_sysioc");
- if (IS_ERR(drvr_priv->sysioc_tsk)) {
- printk(KERN_WARNING
- "_brcmf_sysioc thread failed to start\n");
- drvr_priv->sysioc_tsk = NULL;
- }
- } else
- drvr_priv->sysioc_tsk = NULL;
-
- /*
- * Save the brcmf_info into the priv
- */
- memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
-
-#if defined(CONFIG_PM_SLEEP)
- atomic_set(&brcmf_mmc_suspend, false);
-#endif /* defined(CONFIG_PM_SLEEP) */
- return &drvr_priv->pub;
-
-fail:
- if (net)
- free_netdev(net);
- if (drvr_priv)
- brcmf_detach(&drvr_priv->pub);
-
- return NULL;
-}
-
-int brcmf_bus_start(struct brcmf_pub *drvr)
-{
- int ret = -1;
- struct brcmf_info *drvr_priv = drvr->info;
- /* Room for "event_msgs" + '\0' + bitvec */
- char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
-
- BRCMF_TRACE(("%s:\n", __func__));
-
- /* Bring up the bus */
- ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub, true);
- if (ret != 0) {
- BRCMF_ERROR(("%s, brcmf_sdbrcm_bus_init failed %d\n", __func__,
- ret));
- return ret;
- }
-
- /* If bus is not ready, can't come up */
- if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) {
- BRCMF_ERROR(("%s failed bus is not ready\n", __func__));
- return -ENODEV;
- }
-
- brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
- iovbuf, sizeof(iovbuf));
- brcmf_proto_cdc_query_ioctl(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_priv->pub);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static struct net_device_ops brcmf_netdev_ops_pri = {
- .ndo_open = brcmf_netdev_open,
- .ndo_stop = brcmf_netdev_stop,
- .ndo_get_stats = brcmf_netdev_get_stats,
- .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
- .ndo_start_xmit = brcmf_netdev_start_xmit,
- .ndo_set_mac_address = brcmf_netdev_set_mac_address,
- .ndo_set_multicast_list = brcmf_netdev_set_multicast_list
-};
-
-int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
-{
- struct brcmf_info *drvr_priv = drvr->info;
- struct net_device *net;
- u8 temp_addr[ETH_ALEN] = {
- 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33};
-
- BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx));
-
- net = drvr_priv->iflist[ifidx]->net;
- net->netdev_ops = &brcmf_netdev_ops_pri;
-
- /*
- * We have to use the primary MAC for virtual interfaces
- */
- if (ifidx != 0) {
- /* for virtual interfaces use the primary MAC */
- memcpy(temp_addr, drvr_priv->pub.mac, ETH_ALEN);
-
- }
-
- if (ifidx == 1) {
- BRCMF_TRACE(("%s ACCESS POINT MAC:\n", __func__));
- /* ACCESSPOINT INTERFACE CASE */
- temp_addr[0] |= 0X02; /* set bit 2 ,
- - Locally Administered address */
-
- }
- net->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen;
- net->ethtool_ops = &brcmf_ethtool_ops;
-
- drvr_priv->pub.rxsz = net->mtu + net->hard_header_len +
- drvr_priv->pub.hdrlen;
-
- memcpy(net->dev_addr, temp_addr, ETH_ALEN);
-
- if (register_netdev(net) != 0) {
- BRCMF_ERROR(("%s: couldn't register the net device\n",
- __func__));
- goto fail;
- }
-
- BRCMF_INFO(("%s: Broadcom Dongle Host Driver\n", net->name));
-
- return 0;
-
-fail:
- net->netdev_ops = NULL;
- return -EBADE;
-}
-
-static void brcmf_bus_detach(struct brcmf_pub *drvr)
-{
- struct brcmf_info *drvr_priv;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (drvr) {
- drvr_priv = drvr->info;
- if (drvr_priv) {
- /* Stop the protocol module */
- brcmf_proto_stop(&drvr_priv->pub);
-
- /* Stop the bus module */
- brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus, true);
- }
- }
-}
-
-void brcmf_detach(struct brcmf_pub *drvr)
-{
- struct brcmf_info *drvr_priv;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (drvr) {
- drvr_priv = drvr->info;
- if (drvr_priv) {
- struct brcmf_if *ifp;
- int i;
-
- for (i = 1; i < BRCMF_MAX_IFS; i++)
- if (drvr_priv->iflist[i])
- brcmf_del_if(drvr_priv, i);
-
- ifp = drvr_priv->iflist[0];
- if (ifp->net->netdev_ops == &brcmf_netdev_ops_pri) {
- brcmf_netdev_stop(ifp->net);
- unregister_netdev(ifp->net);
- }
-
- if (drvr_priv->sysioc_tsk) {
- send_sig(SIGTERM, drvr_priv->sysioc_tsk, 1);
- kthread_stop(drvr_priv->sysioc_tsk);
- drvr_priv->sysioc_tsk = NULL;
- }
-
- brcmf_bus_detach(drvr);
-
- if (drvr->prot)
- brcmf_proto_detach(drvr);
-
- brcmf_cfg80211_detach();
-
- free_netdev(ifp->net);
- kfree(ifp);
- kfree(drvr_priv);
- }
- }
-}
-
-static void __exit brcmf_module_cleanup(void)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- brcmf_bus_unregister();
-}
-
-static int __init brcmf_module_init(void)
-{
- int error;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- error = brcmf_bus_register();
-
- if (error) {
- BRCMF_ERROR(("%s: brcmf_bus_register failed\n", __func__));
- goto failed;
- }
- return 0;
-
-failed:
- return -EINVAL;
-}
-
-module_init(brcmf_module_init);
-module_exit(brcmf_module_cleanup);
-
-int brcmf_os_proto_block(struct brcmf_pub *drvr)
-{
- struct brcmf_info *drvr_priv = drvr->info;
-
- if (drvr_priv) {
- down(&drvr_priv->proto_sem);
- return 1;
- }
- return 0;
-}
-
-int brcmf_os_proto_unblock(struct brcmf_pub *drvr)
-{
- struct brcmf_info *drvr_priv = drvr->info;
-
- if (drvr_priv) {
- up(&drvr_priv->proto_sem);
- return 1;
- }
-
- return 0;
-}
-
-unsigned int brcmf_os_get_ioctl_resp_timeout(void)
-{
- return (unsigned int)brcmf_ioctl_timeout_msec;
-}
-
-void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec)
-{
- brcmf_ioctl_timeout_msec = (int)timeout_msec;
-}
-
-int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition,
- bool *pending)
-{
- struct brcmf_info *drvr_priv = drvr->info;
- DECLARE_WAITQUEUE(wait, current);
- int timeout = brcmf_ioctl_timeout_msec;
-
- /* Convert timeout in millsecond to jiffies */
- timeout = timeout * HZ / 1000;
-
- /* Wait until control frame is available */
- add_wait_queue(&drvr_priv->ioctl_resp_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
-
- while (!(*condition) && (!signal_pending(current) && timeout))
- timeout = schedule_timeout(timeout);
-
- if (signal_pending(current))
- *pending = true;
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&drvr_priv->ioctl_resp_wait, &wait);
-
- return timeout;
-}
-
-int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr)
-{
- struct brcmf_info *drvr_priv = drvr->info;
-
- if (waitqueue_active(&drvr_priv->ioctl_resp_wait))
- wake_up_interruptible(&drvr_priv->ioctl_resp_wait);
-
- return 0;
-}
-
-static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
- struct brcmf_event_msg *event, void **data)
-{
- int bcmerror = 0;
-
- bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data);
- if (bcmerror != 0)
- return bcmerror;
-
- if (drvr_priv->iflist[*ifidx]->net)
- brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->net,
- event, *data);
-
- return bcmerror;
-}
-
-int brcmf_netdev_reset(struct net_device *dev, u8 flag)
-{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev);
-
- brcmf_bus_devreset(&drvr_priv->pub, flag);
-
- return 1;
-}
-
-static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
-{
- return atomic_read(&drvr_priv->pend_8021x_cnt);
-}
-
-#define MAX_WAIT_FOR_8021X_TX 10
-
-int brcmf_netdev_wait_pend8021x(struct net_device *dev)
-{
- struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev);
- int timeout = 10 * HZ / 1000;
- int ntimes = MAX_WAIT_FOR_8021X_TX;
- int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
-
- 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_priv);
- }
- return pend;
-}
-
-#ifdef BCMDBG
-int brcmf_write_to_file(struct brcmf_pub *drvr, 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_ERROR(("%s: open file error\n", __func__));
- ret = -1;
- goto exit;
- }
-
- /* Write buf to file */
- fp->f_op->write(fp, buf, size, &pos);
-
-exit:
- /* free buf before return */
- kfree(buf);
- /* close file before return */
- if (fp)
- filp_close(fp, current->files);
- /* restore previous address limit */
- set_fs(old_fs);
-
- return ret;
-}
-#endif /* BCMDBG */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
deleted file mode 100644
index 7fa95b6213c5..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
+++ /dev/null
@@ -1,6772 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/printk.h>
-#include <linux/pci_ids.h>
-#include <linux/netdevice.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/semaphore.h>
-#include <linux/firmware.h>
-#include <asm/unaligned.h>
-#include <defs.h>
-#include <brcmu_wifi.h>
-#include <brcmu_utils.h>
-#include <brcm_hw_ids.h>
-#include <soc.h>
-#include "sdio_host.h"
-
-/* register access macros */
-#ifndef __BIG_ENDIAN
-#ifndef __mips__
-#define R_REG(r, typ) \
- brcmf_sdcard_reg_read(NULL, (r), sizeof(typ))
-#else /* __mips__ */
-#define R_REG(r, typ) \
- ({ \
- __typeof(*(r)) __osl_v; \
- __asm__ __volatile__("sync"); \
- __osl_v = brcmf_sdcard_reg_read(NULL, (r),\
- sizeof(typ)); \
- __asm__ __volatile__("sync"); \
- __osl_v; \
- })
-#endif /* __mips__ */
-
-#else /* __BIG_ENDIAN */
-#define R_REG(r, typ) \
- brcmf_sdcard_reg_read(NULL, (r), sizeof(typ))
-#endif /* __BIG_ENDIAN */
-
-#define OR_REG(r, v, typ) \
- brcmf_sdcard_reg_write(NULL, (r), sizeof(typ), R_REG(r, typ) | (v))
-
-#ifdef BCMDBG
-
-/* ARM trap handling */
-
-/* Trap types defined by ARM (see arminc.h) */
-
-#if defined(__ARM_ARCH_4T__)
-#define MAX_TRAP_TYPE (TR_FIQ + 1)
-#elif defined(__ARM_ARCH_7M__)
-#define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS)
-#endif /* __ARM_ARCH_7M__ */
-
-/* The trap structure is defined here as offsets for assembly */
-#define TR_TYPE 0x00
-#define TR_EPC 0x04
-#define TR_CPSR 0x08
-#define TR_SPSR 0x0c
-#define TR_REGS 0x10
-#define TR_REG(n) (TR_REGS + (n) * 4)
-#define TR_SP TR_REG(13)
-#define TR_LR TR_REG(14)
-#define TR_PC TR_REG(15)
-
-#define TRAP_T_SIZE 80
-
-struct brcmf_trap {
- u32 type;
- u32 epc;
- u32 cpsr;
- u32 spsr;
- u32 r0;
- u32 r1;
- u32 r2;
- u32 r3;
- u32 r4;
- u32 r5;
- u32 r6;
- u32 r7;
- u32 r8;
- u32 r9;
- u32 r10;
- u32 r11;
- u32 r12;
- u32 r13;
- u32 r14;
- u32 pc;
-};
-
-#define CBUF_LEN (128)
-
-struct rte_log {
- u32 buf; /* Can't be pointer on (64-bit) hosts */
- uint buf_size;
- uint idx;
- char *_buf_compat; /* Redundant pointer for backward compat. */
-};
-
-struct rte_console {
- /* Virtual UART
- * When there is no UART (e.g. Quickturn),
- * the host should write a complete
- * input line directly into cbuf and then write
- * the length into vcons_in.
- * This may also be used when there is a real UART
- * (at risk of conflicting with
- * the real UART). vcons_out is currently unused.
- */
- volatile uint vcons_in;
- volatile uint vcons_out;
-
- /* Output (logging) buffer
- * Console output is written to a ring buffer log_buf at index log_idx.
- * The host may read the output when it sees log_idx advance.
- * Output will be lost if the output wraps around faster than the host
- * polls.
- */
- struct rte_log log;
-
- /* Console input line buffer
- * Characters are read one at a time into cbuf
- * until <CR> is received, then
- * the buffer is processed as a command line.
- * Also used for virtual UART.
- */
- uint cbuf_idx;
- char cbuf[CBUF_LEN];
-};
-
-#endif /* BCMDBG */
-#include <chipcommon.h>
-
-#include "dhd.h"
-#include "dhd_bus.h"
-#include "dhd_proto.h"
-#include "dhd_dbg.h"
-#include <bcmchip.h>
-
-#define TXQLEN 2048 /* bulk tx queue length */
-#define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */
-#define TXLOW (TXHI - 256) /* turn off flow control below TXLOW */
-#define PRIOMASK 7
-
-#define TXRETRIES 2 /* # of retries for tx frames */
-
-#define BRCMF_RXBOUND 50 /* Default for max rx frames in
- one scheduling */
-
-#define BRCMF_TXBOUND 20 /* Default for max tx frames in
- one scheduling */
-
-#define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */
-
-#define MEMBLOCK 2048 /* Block size used for downloading
- of dongle image */
-#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold
- biggest possible glom */
-
-#ifndef BRCMF_FIRSTREAD
-#define BRCMF_FIRSTREAD 32
-#endif
-
-#if !ISPOWEROF2(BRCMF_FIRSTREAD)
-#error BRCMF_FIRSTREAD is not a power of 2!
-#endif
-
-/* SBSDIO_DEVICE_CTL */
-#define SBSDIO_DEVCTL_SETBUSY 0x01 /* 1: device will assert busy signal when
- * receiving CMD53
- */
-#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 /* 1: assertion of sdio interrupt is
- * synchronous to the sdio clock
- */
-#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 /* 1: mask all interrupts to host
- * except the chipActive (rev 8)
- */
-#define SBSDIO_DEVCTL_PADS_ISO 0x08 /* 1: isolate internal sdio signals, put
- * external pads in tri-state; requires
- * sdio bus power cycle to clear (rev 9)
- */
-#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 /* Force SD->SB reset mapping (rev 11) */
-#define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */
-#define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */
-#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */
-
-/* SBSDIO_FUNC1_CHIPCLKCSR */
-#define SBSDIO_FORCE_ALP 0x01 /* Force ALP request to backplane */
-#define SBSDIO_FORCE_HT 0x02 /* Force HT request to backplane */
-#define SBSDIO_FORCE_ILP 0x04 /* Force ILP request to backplane */
-#define SBSDIO_ALP_AVAIL_REQ 0x08 /* Make ALP ready (power up xtal) */
-#define SBSDIO_HT_AVAIL_REQ 0x10 /* Make HT ready (power up PLL) */
-#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 /* Squelch clock requests from HW */
-#define SBSDIO_ALP_AVAIL 0x40 /* Status: ALP is ready */
-#define SBSDIO_HT_AVAIL 0x80 /* Status: HT is ready */
-
-#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
-#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
-#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
-#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
-#define SBSDIO_CLKAV(regval, alponly) (SBSDIO_ALPAV(regval) && \
- (alponly ? 1 : SBSDIO_HTAV(regval)))
-/* direct(mapped) cis space */
-#define SBSDIO_CIS_BASE_COMMON 0x1000 /* MAPPED common CIS address */
-#define SBSDIO_CIS_SIZE_LIMIT 0x200 /* maximum bytes in one CIS */
-#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF /* cis offset addr is < 17 bits */
-
-#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 /* manfid tuple length, include tuple,
- * link bytes
- */
-
-/* intstatus */
-#define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */
-#define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */
-#define I_SMB_SW2 (1 << 2) /* To SB Mail S/W interrupt 2 */
-#define I_SMB_SW3 (1 << 3) /* To SB Mail S/W interrupt 3 */
-#define I_SMB_SW_MASK 0x0000000f /* To SB Mail S/W interrupts mask */
-#define I_SMB_SW_SHIFT 0 /* To SB Mail S/W interrupts shift */
-#define I_HMB_SW0 (1 << 4) /* To Host Mail S/W interrupt 0 */
-#define I_HMB_SW1 (1 << 5) /* To Host Mail S/W interrupt 1 */
-#define I_HMB_SW2 (1 << 6) /* To Host Mail S/W interrupt 2 */
-#define I_HMB_SW3 (1 << 7) /* To Host Mail S/W interrupt 3 */
-#define I_HMB_SW_MASK 0x000000f0 /* To Host Mail S/W interrupts mask */
-#define I_HMB_SW_SHIFT 4 /* To Host Mail S/W interrupts shift */
-#define I_WR_OOSYNC (1 << 8) /* Write Frame Out Of Sync */
-#define I_RD_OOSYNC (1 << 9) /* Read Frame Out Of Sync */
-#define I_PC (1 << 10) /* descriptor error */
-#define I_PD (1 << 11) /* data error */
-#define I_DE (1 << 12) /* Descriptor protocol Error */
-#define I_RU (1 << 13) /* Receive descriptor Underflow */
-#define I_RO (1 << 14) /* Receive fifo Overflow */
-#define I_XU (1 << 15) /* Transmit fifo Underflow */
-#define I_RI (1 << 16) /* Receive Interrupt */
-#define I_BUSPWR (1 << 17) /* SDIO Bus Power Change (rev 9) */
-#define I_XMTDATA_AVAIL (1 << 23) /* bits in fifo */
-#define I_XI (1 << 24) /* Transmit Interrupt */
-#define I_RF_TERM (1 << 25) /* Read Frame Terminate */
-#define I_WF_TERM (1 << 26) /* Write Frame Terminate */
-#define I_PCMCIA_XU (1 << 27) /* PCMCIA Transmit FIFO Underflow */
-#define I_SBINT (1 << 28) /* sbintstatus Interrupt */
-#define I_CHIPACTIVE (1 << 29) /* chip from doze to active state */
-#define I_SRESET (1 << 30) /* CCCR RES interrupt */
-#define I_IOE2 (1U << 31) /* CCCR IOE2 Bit Changed */
-#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)
-#define I_DMA (I_RI | I_XI | I_ERRORS)
-
-/* corecontrol */
-#define CC_CISRDY (1 << 0) /* CIS Ready */
-#define CC_BPRESEN (1 << 1) /* CCCR RES signal */
-#define CC_F2RDY (1 << 2) /* set CCCR IOR2 bit */
-#define CC_CLRPADSISO (1 << 3) /* clear SDIO pads isolation */
-#define CC_XMTDATAAVAIL_MODE (1 << 4)
-#define CC_XMTDATAAVAIL_CTRL (1 << 5)
-
-/* SDA_FRAMECTRL */
-#define SFC_RF_TERM (1 << 0) /* Read Frame Terminate */
-#define SFC_WF_TERM (1 << 1) /* Write Frame Terminate */
-#define SFC_CRC4WOOS (1 << 2) /* CRC error for write out of sync */
-#define SFC_ABORTALL (1 << 3) /* Abort all in-progress frames */
-
-/* HW frame tag */
-#define SDPCM_FRAMETAG_LEN 4 /* 2 bytes len, 2 bytes check val */
-
-/* Total length of frame header for dongle protocol */
-#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
-#ifdef SDTEST
-#define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN)
-#else
-#define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN)
-#endif
-
-/*
- * Software allocation of To SB Mailbox resources
- */
-
-/* tosbmailbox bits corresponding to intstatus bits */
-#define SMB_NAK (1 << 0) /* Frame NAK */
-#define SMB_INT_ACK (1 << 1) /* Host Interrupt ACK */
-#define SMB_USE_OOB (1 << 2) /* Use OOB Wakeup */
-#define SMB_DEV_INT (1 << 3) /* Miscellaneous Interrupt */
-
-/* tosbmailboxdata */
-#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version */
-
-/*
- * Software allocation of To Host Mailbox resources
- */
-
-/* intstatus bits */
-#define I_HMB_FC_STATE I_HMB_SW0 /* Flow Control State */
-#define I_HMB_FC_CHANGE I_HMB_SW1 /* Flow Control State Changed */
-#define I_HMB_FRAME_IND I_HMB_SW2 /* Frame Indication */
-#define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */
-
-/* tohostmailboxdata */
-#define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */
-#define HMB_DATA_DEVREADY 2 /* talk to host after enable */
-#define HMB_DATA_FC 4 /* per prio flowcontrol update flag */
-#define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */
-
-#define HMB_DATA_FCDATA_MASK 0xff000000
-#define HMB_DATA_FCDATA_SHIFT 24
-
-#define HMB_DATA_VERSION_MASK 0x00ff0000
-#define HMB_DATA_VERSION_SHIFT 16
-
-/*
- * Software-defined protocol header
- */
-
-/* Current protocol version */
-#define SDPCM_PROT_VERSION 4
-
-/* SW frame header */
-#define SDPCM_PACKET_SEQUENCE(p) (((u8 *)p)[0] & 0xff)
-
-#define SDPCM_CHANNEL_MASK 0x00000f00
-#define SDPCM_CHANNEL_SHIFT 8
-#define SDPCM_PACKET_CHANNEL(p) (((u8 *)p)[1] & 0x0f)
-
-#define SDPCM_NEXTLEN_OFFSET 2
-
-/* Data Offset from SOF (HW Tag, SW Tag, Pad) */
-#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */
-#define SDPCM_DOFFSET_VALUE(p) (((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff)
-#define SDPCM_DOFFSET_MASK 0xff000000
-#define SDPCM_DOFFSET_SHIFT 24
-#define SDPCM_FCMASK_OFFSET 4 /* Flow control */
-#define SDPCM_FCMASK_VALUE(p) (((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff)
-#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */
-#define SDPCM_WINDOW_VALUE(p) (((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff)
-
-#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */
-
-/* logical channel numbers */
-#define SDPCM_CONTROL_CHANNEL 0 /* Control channel Id */
-#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */
-#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */
-#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets */
-#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */
-
-#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for 8bit frame seq */
-
-#define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80)
-
-/* For TEST_CHANNEL packets, define another 4-byte header */
-#define SDPCM_TEST_HDRLEN 4 /*
- * Generally: Cmd(1), Ext(1), Len(2);
- * Semantics of Ext byte depend on
- * command. Len is current or requested
- * frame length, not including test
- * header; sent little-endian.
- */
-#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext:pattern id. */
-#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext:pattern id. */
-#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext:pattern id. */
-#define SDPCM_TEST_BURST 0x04 /*
- * Receiver to send a burst.
- * Ext is a frame count
- */
-#define SDPCM_TEST_SEND 0x05 /*
- * Receiver sets send mode.
- * Ext is boolean on/off
- */
-
-/* Handy macro for filling in datagen packets with a pattern */
-#define SDPCM_TEST_FILL(byteno, id) ((u8)(id + byteno))
-
-/*
- * Shared structure between dongle and the host.
- * The structure contains pointers to trap or assert information.
- */
-#define SDPCM_SHARED_VERSION 0x0002
-#define SDPCM_SHARED_VERSION_MASK 0x00FF
-#define SDPCM_SHARED_ASSERT_BUILT 0x0100
-#define SDPCM_SHARED_ASSERT 0x0200
-#define SDPCM_SHARED_TRAP 0x0400
-
-
-/* Space for header read, limit for data packets */
-#ifndef MAX_HDR_READ
-#define MAX_HDR_READ 32
-#endif
-#if !ISPOWEROF2(MAX_HDR_READ)
-#error MAX_HDR_READ is not a power of 2!
-#endif
-
-#define MAX_RX_DATASZ 2048
-
-/* Maximum milliseconds to wait for F2 to come up */
-#define BRCMF_WAIT_F2RDY 3000
-
-/* Bump up limit on waiting for HT to account for first startup;
- * if the image is doing a CRC calculation before programming the PMU
- * for HT availability, it could take a couple hundred ms more, so
- * max out at a 1 second (1000000us).
- */
-#if (PMU_MAX_TRANSITION_DLY <= 1000000)
-#undef PMU_MAX_TRANSITION_DLY
-#define PMU_MAX_TRANSITION_DLY 1000000
-#endif
-
-/* Value for ChipClockCSR during initial setup */
-#define BRCMF_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \
- SBSDIO_ALP_AVAIL_REQ)
-
-/* Flags for SDH calls */
-#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
-
-/* sbimstate */
-#define SBIM_IBE 0x20000 /* inbanderror */
-#define SBIM_TO 0x40000 /* timeout */
-#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */
-#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */
-
-/* sbtmstatelow */
-#define SBTML_RESET 0x0001 /* reset */
-#define SBTML_REJ_MASK 0x0006 /* reject field */
-#define SBTML_REJ 0x0002 /* reject */
-#define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */
-
-#define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */
-
-/* sbtmstatehigh */
-#define SBTMH_SERR 0x0001 /* serror */
-#define SBTMH_INT 0x0002 /* interrupt */
-#define SBTMH_BUSY 0x0004 /* busy */
-#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */
-
-#define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */
-
-/* sbidlow */
-#define SBIDL_INIT 0x80 /* initiator */
-
-/* sbidhigh */
-#define SBIDH_RC_MASK 0x000f /* revision code */
-#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
-#define SBIDH_RCE_SHIFT 8
-#define SBCOREREV(sbidh) \
- ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK))
-#define SBIDH_CC_MASK 0x8ff0 /* core code */
-#define SBIDH_CC_SHIFT 4
-#define SBIDH_VC_MASK 0xffff0000 /* vendor code */
-#define SBIDH_VC_SHIFT 16
-
-/*
- * Conversion of 802.1D priority to precedence level
- */
-#define PRIO2PREC(prio) \
- (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \
- ((prio^2)) : (prio))
-
-BRCMF_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
-
-/*
- * Core reg address translation.
- * Both macro's returns a 32 bits byte address on the backplane bus.
- */
-#define CORE_CC_REG(base, field) (base + offsetof(chipcregs_t, field))
-#define CORE_BUS_REG(base, field) \
- (base + offsetof(struct sdpcmd_regs, field))
-#define CORE_SB(base, field) \
- (base + SBCONFIGOFF + offsetof(struct sbconfig, field))
-
-/* core registers */
-struct sdpcmd_regs {
- u32 corecontrol; /* 0x00, rev8 */
- u32 corestatus; /* rev8 */
- u32 PAD[1];
- u32 biststatus; /* rev8 */
-
- /* PCMCIA access */
- u16 pcmciamesportaladdr; /* 0x010, rev8 */
- u16 PAD[1];
- u16 pcmciamesportalmask; /* rev8 */
- u16 PAD[1];
- u16 pcmciawrframebc; /* rev8 */
- u16 PAD[1];
- u16 pcmciaunderflowtimer; /* rev8 */
- u16 PAD[1];
-
- /* interrupt */
- u32 intstatus; /* 0x020, rev8 */
- u32 hostintmask; /* rev8 */
- u32 intmask; /* rev8 */
- u32 sbintstatus; /* rev8 */
- u32 sbintmask; /* rev8 */
- u32 funcintmask; /* rev4 */
- u32 PAD[2];
- u32 tosbmailbox; /* 0x040, rev8 */
- u32 tohostmailbox; /* rev8 */
- u32 tosbmailboxdata; /* rev8 */
- u32 tohostmailboxdata; /* rev8 */
-
- /* synchronized access to registers in SDIO clock domain */
- u32 sdioaccess; /* 0x050, rev8 */
- u32 PAD[3];
-
- /* PCMCIA frame control */
- u8 pcmciaframectrl; /* 0x060, rev8 */
- u8 PAD[3];
- u8 pcmciawatermark; /* rev8 */
- u8 PAD[155];
-
- /* interrupt batching control */
- u32 intrcvlazy; /* 0x100, rev8 */
- u32 PAD[3];
-
- /* counters */
- u32 cmd52rd; /* 0x110, rev8 */
- u32 cmd52wr; /* rev8 */
- u32 cmd53rd; /* rev8 */
- u32 cmd53wr; /* rev8 */
- u32 abort; /* rev8 */
- u32 datacrcerror; /* rev8 */
- u32 rdoutofsync; /* rev8 */
- u32 wroutofsync; /* rev8 */
- u32 writebusy; /* rev8 */
- u32 readwait; /* rev8 */
- u32 readterm; /* rev8 */
- u32 writeterm; /* rev8 */
- u32 PAD[40];
- u32 clockctlstatus; /* rev8 */
- u32 PAD[7];
-
- u32 PAD[128]; /* DMA engines */
-
- /* SDIO/PCMCIA CIS region */
- char cis[512]; /* 0x400-0x5ff, rev6 */
-
- /* PCMCIA function control registers */
- char pcmciafcr[256]; /* 0x600-6ff, rev6 */
- u16 PAD[55];
-
- /* PCMCIA backplane access */
- u16 backplanecsr; /* 0x76E, rev6 */
- u16 backplaneaddr0; /* rev6 */
- u16 backplaneaddr1; /* rev6 */
- u16 backplaneaddr2; /* rev6 */
- u16 backplaneaddr3; /* rev6 */
- u16 backplanedata0; /* rev6 */
- u16 backplanedata1; /* rev6 */
- u16 backplanedata2; /* rev6 */
- u16 backplanedata3; /* rev6 */
- u16 PAD[31];
-
- /* sprom "size" & "blank" info */
- u16 spromstatus; /* 0x7BE, rev2 */
- u32 PAD[464];
-
- u16 PAD[0x80];
-};
-
-#ifdef BCMDBG
-/* Device console log buffer state */
-struct brcmf_console {
- uint count; /* Poll interval msec counter */
- uint log_addr; /* Log struct address (fixed) */
- struct rte_log log; /* Log struct (host copy) */
- uint bufsize; /* Size of log buffer */
- u8 *buf; /* Log buffer (host copy) */
- uint last; /* Last buffer read index */
-};
-#endif /* BCMDBG */
-
-struct sdpcm_shared {
- u32 flags;
- u32 trap_addr;
- u32 assert_exp_addr;
- u32 assert_file_addr;
- u32 assert_line;
- u32 console_addr; /* Address of struct rte_console */
- u32 msgtrace_addr;
- u8 tag[32];
-};
-
-
-/* misc chip info needed by some of the routines */
-struct chip_info {
- u32 chip;
- u32 chiprev;
- u32 cccorebase;
- u32 ccrev;
- u32 cccaps;
- u32 buscorebase; /* 32 bits backplane bus address */
- u32 buscorerev;
- u32 buscoretype;
- u32 ramcorebase;
- u32 armcorebase;
- u32 pmurev;
- u32 ramsize;
-};
-
-/* Private data for SDIO bus interaction */
-struct brcmf_bus {
- struct brcmf_pub *drvr;
-
- struct brcmf_sdio_card *card; /* Handle for sdio card calls */
- struct chip_info *ci; /* Chip info struct */
- char *vars; /* Variables (from CIS and/or other) */
- uint varsz; /* Size of variables buffer */
-
- u32 ramsize; /* Size of RAM in SOCRAM (bytes) */
- u32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */
-
- u32 bus; /* gSPI or SDIO bus */
- u32 hostintmask; /* Copy of Host Interrupt Mask */
- u32 intstatus; /* Intstatus bits (events) pending */
- bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
- bool fcstate; /* State of dongle flow-control */
-
- u16 cl_devid; /* cached devid for brcmf_sdio_probe_attach() */
-
- uint blocksize; /* Block size of SDIO transfers */
- uint roundup; /* Max roundup limit */
-
- struct pktq txq; /* Queue length used for flow-control */
- u8 flowcontrol; /* per prio flow control bitmask */
- u8 tx_seq; /* Transmit sequence number (next) */
- u8 tx_max; /* Maximum transmit sequence allowed */
-
- u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN];
- u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */
- u16 nextlen; /* Next Read Len from last header */
- u8 rx_seq; /* Receive sequence number (expected) */
- bool rxskip; /* Skip receive (awaiting NAK ACK) */
-
- struct sk_buff *glomd; /* Packet containing glomming descriptor */
- struct sk_buff *glom; /* Packet chain for glommed superframe */
- uint glomerr; /* Glom packet read errors */
-
- u8 *rxbuf; /* Buffer for receiving control packets */
- uint rxblen; /* Allocated length of rxbuf */
- u8 *rxctl; /* Aligned pointer into rxbuf */
- u8 *databuf; /* Buffer for receiving big glom packet */
- u8 *dataptr; /* Aligned pointer into databuf */
- uint rxlen; /* Length of valid data in buffer */
-
- u8 sdpcm_ver; /* Bus protocol reported by dongle */
-
- bool intr; /* Use interrupts */
- bool poll; /* Use polling */
- bool ipend; /* Device interrupt is pending */
- bool intdis; /* Interrupts disabled by isr */
- uint intrcount; /* Count of device interrupt callbacks */
- uint lastintrs; /* Count as of last watchdog timer */
- uint spurious; /* Count of spurious interrupts */
- uint pollrate; /* Ticks between device polls */
- uint polltick; /* Tick counter */
- uint pollcnt; /* Count of active polls */
-
-#ifdef BCMDBG
- struct brcmf_console console; /* Console output polling support */
- uint console_addr; /* Console address from shared struct */
-#endif /* BCMDBG */
-
- uint regfails; /* Count of R_REG failures */
-
- uint clkstate; /* State of sd and backplane clock(s) */
- bool activity; /* Activity flag for clock down */
- s32 idletime; /* Control for activity timeout */
- s32 idlecount; /* Activity timeout counter */
- s32 idleclock; /* How to set bus driver when idle */
- s32 sd_rxchain;
- bool use_rxchain; /* If brcmf should use PKT chains */
- bool sleeping; /* Is SDIO bus sleeping? */
- bool rxflow_mode; /* Rx flow control mode */
- bool rxflow; /* Is rx flow control on */
- bool alp_only; /* Don't use HT clock (ALP only) */
-/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
- bool usebufpool;
-
-#ifdef SDTEST
- /* external loopback */
- bool ext_loop;
- u8 loopid;
-
- /* pktgen configuration */
- uint pktgen_freq; /* Ticks between bursts */
- uint pktgen_count; /* Packets to send each burst */
- uint pktgen_print; /* Bursts between count displays */
- uint pktgen_total; /* Stop after this many */
- uint pktgen_minlen; /* Minimum packet data len */
- uint pktgen_maxlen; /* Maximum packet data len */
- uint pktgen_mode; /* Configured mode: tx, rx, or echo */
- uint pktgen_stop; /* Number of tx failures causing stop */
-
- /* active pktgen fields */
- uint pktgen_tick; /* Tick counter for bursts */
- uint pktgen_ptick; /* Burst counter for printing */
- uint pktgen_sent; /* Number of test packets generated */
- uint pktgen_rcvd; /* Number of test packets received */
- uint pktgen_fail; /* Number of failed send attempts */
- u16 pktgen_len; /* Length of next packet to send */
-#endif /* SDTEST */
-
- /* Some additional counters */
- uint tx_sderrs; /* Count of tx attempts with sd errors */
- uint fcqueued; /* Tx packets that got queued */
- uint rxrtx; /* Count of rtx requests (NAK to dongle) */
- uint rx_toolong; /* Receive frames too long to receive */
- uint rxc_errors; /* SDIO errors when reading control frames */
- uint rx_hdrfail; /* SDIO errors on header reads */
- uint rx_badhdr; /* Bad received headers (roosync?) */
- uint rx_badseq; /* Mismatched rx sequence number */
- uint fc_rcvd; /* Number of flow-control events received */
- uint fc_xoff; /* Number which turned on flow-control */
- uint fc_xon; /* Number which turned off flow-control */
- uint rxglomfail; /* Failed deglom attempts */
- uint rxglomframes; /* Number of glom frames (superframes) */
- uint rxglompkts; /* Number of packets from glom frames */
- uint f2rxhdrs; /* Number of header reads */
- uint f2rxdata; /* Number of frame data reads */
- uint f2txdata; /* Number of f2 frame writes */
- uint f1regdata; /* Number of f1 register accesses */
-
- u8 *ctrl_frame_buf;
- u32 ctrl_frame_len;
- bool ctrl_frame_stat;
-
- spinlock_t txqlock;
- wait_queue_head_t ctrl_wait;
-
- struct timer_list timer;
- struct completion watchdog_wait;
- struct task_struct *watchdog_tsk;
- bool wd_timer_valid;
-
- struct tasklet_struct tasklet;
- struct task_struct *dpc_tsk;
- struct completion dpc_wait;
-
- bool threads_only;
- struct semaphore sdsem;
- spinlock_t sdlock;
-
- const char *fw_name;
- const struct firmware *firmware;
- const char *nv_name;
- u32 fw_ptr;
-};
-
-struct sbconfig {
- u32 PAD[2];
- u32 sbipsflag; /* initiator port ocp slave flag */
- u32 PAD[3];
- u32 sbtpsflag; /* target port ocp slave flag */
- u32 PAD[11];
- u32 sbtmerrloga; /* (sonics >= 2.3) */
- u32 PAD;
- u32 sbtmerrlog; /* (sonics >= 2.3) */
- u32 PAD[3];
- u32 sbadmatch3; /* address match3 */
- u32 PAD;
- u32 sbadmatch2; /* address match2 */
- u32 PAD;
- u32 sbadmatch1; /* address match1 */
- u32 PAD[7];
- u32 sbimstate; /* initiator agent state */
- u32 sbintvec; /* interrupt mask */
- u32 sbtmstatelow; /* target state */
- u32 sbtmstatehigh; /* target state */
- u32 sbbwa0; /* bandwidth allocation table0 */
- u32 PAD;
- u32 sbimconfiglow; /* initiator configuration */
- u32 sbimconfighigh; /* initiator configuration */
- u32 sbadmatch0; /* address match0 */
- u32 PAD;
- u32 sbtmconfiglow; /* target configuration */
- u32 sbtmconfighigh; /* target configuration */
- u32 sbbconfig; /* broadcast configuration */
- u32 PAD;
- u32 sbbstate; /* broadcast state */
- u32 PAD[3];
- u32 sbactcnfg; /* activate configuration */
- u32 PAD[3];
- u32 sbflagst; /* current sbflags */
- u32 PAD[3];
- u32 sbidlow; /* identification */
- u32 sbidhigh; /* identification */
-};
-
-/* clkstate */
-#define CLK_NONE 0
-#define CLK_SDONLY 1
-#define CLK_PENDING 2 /* Not used yet */
-#define CLK_AVAIL 3
-
-#define BRCMF_NOPMU(brcmf) (false)
-
-#ifdef BCMDBG
-static int qcount[NUMPRIO];
-static int tx_packets[NUMPRIO];
-#endif /* BCMDBG */
-
-/* Deferred transmit */
-uint brcmf_deferred_tx = 1;
-module_param(brcmf_deferred_tx, uint, 0);
-
-/* Watchdog thread priority, -1 to use kernel timer */
-int brcmf_watchdog_prio = 97;
-module_param(brcmf_watchdog_prio, int, 0);
-
-/* Watchdog interval */
-uint brcmf_watchdog_ms = 10;
-module_param(brcmf_watchdog_ms, uint, 0);
-
-/* DPC thread priority, -1 to use tasklet */
-int brcmf_dpc_prio = 98;
-module_param(brcmf_dpc_prio, int, 0);
-
-#ifdef BCMDBG
-/* Console poll interval */
-uint brcmf_console_ms;
-module_param(brcmf_console_ms, uint, 0);
-#endif /* BCMDBG */
-
-/* Tx/Rx bounds */
-uint brcmf_txbound;
-uint brcmf_rxbound;
-uint brcmf_txminmax;
-
-/* override the RAM size if possible */
-#define DONGLE_MIN_MEMSIZE (128 * 1024)
-int brcmf_dongle_memsize;
-
-static bool brcmf_alignctl;
-
-static bool sd1idle;
-
-static bool retrydata;
-#define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
-
-static const uint watermark = 8;
-static const uint firstread = BRCMF_FIRSTREAD;
-
-/* Retry count for register access failures */
-static const uint retry_limit = 2;
-
-/* Force even SD lengths (some host controllers mess up on odd bytes) */
-static bool forcealign;
-
-#define ALIGNMENT 4
-
-#define PKTALIGN(_p, _len, _align) \
- do { \
- uint datalign; \
- datalign = (unsigned long)((_p)->data); \
- datalign = roundup(datalign, (_align)) - datalign; \
- if (datalign) \
- skb_pull((_p), datalign); \
- __skb_trim((_p), (_len)); \
- } while (0)
-
-/* Limit on rounding up frames */
-static const uint max_roundup = 512;
-
-/* Try doing readahead */
-static bool brcmf_readahead;
-
-/* To check if there's window offered */
-#define DATAOK(bus) \
- (((u8)(bus->tx_max - bus->tx_seq) != 0) && \
- (((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
-
-/*
- * Reads a register in the SDIO hardware block. This block occupies a series of
- * adresses on the 32 bit backplane bus.
- */
-static void
-r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
-{
- *retryvar = 0;
- do {
- *regvar = R_REG(bus->ci->buscorebase + reg_offset, u32);
- } while (brcmf_sdcard_regfail(bus->card) &&
- (++(*retryvar) <= retry_limit));
- if (*retryvar) {
- bus->regfails += (*retryvar-1);
- if (*retryvar > retry_limit) {
- BRCMF_ERROR(("FAILED READ %Xh\n", reg_offset));
- *regvar = 0;
- }
- }
-}
-
-static void
-w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar)
-{
- *retryvar = 0;
- do {
- brcmf_sdcard_reg_write(NULL, bus->ci->buscorebase + reg_offset,
- sizeof(u32), regval);
- } while (brcmf_sdcard_regfail(bus->card) &&
- (++(*retryvar) <= retry_limit));
- if (*retryvar) {
- bus->regfails += (*retryvar-1);
- if (*retryvar > retry_limit)
- BRCMF_ERROR(("FAILED REGISTER WRITE"
- " %Xh\n", reg_offset));
- }
-}
-
-#define BRCMF_BUS SDIO_BUS
-
-#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
-
-#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
-
-#ifdef SDTEST
-static void brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, void *pkt, uint seq);
-static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start);
-#endif
-
-#ifdef BCMDBG
-static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr,
- unsigned char *msg, uint msglen);
-static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size);
-static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus);
-#endif /* BCMDBG */
-static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter);
-
-static void brcmf_sdbrcm_release(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_disconnect(void *ptr);
-static bool brcmf_sdbrcm_chipmatch(u16 chipid);
-static bool brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card,
- u32 regsva, u16 devid);
-static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card);
-static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card);
-static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus);
-
-static uint brcmf_process_nvram_vars(char *varbuf, uint len);
-
-static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size);
-static int brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn,
- uint flags, u8 *buf, uint nbytes,
- struct sk_buff *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle);
-
-static bool brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card);
-static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus);
-
-static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus);
-static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus);
-
-static void
-brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase);
-
-static int brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs);
-
-static void
-brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase);
-
-static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus,
- u32 drivestrength);
-static void brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar);
-static void brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_watchdog(unsigned long data);
-static int brcmf_sdbrcm_watchdog_thread(void *data);
-static int brcmf_sdbrcm_dpc_thread(void *data);
-static void brcmf_sdbrcm_dpc_tasklet(unsigned long data);
-static void brcmf_sdbrcm_sched_dpc(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_sdlock(struct brcmf_bus *bus);
-static void brcmf_sdbrcm_sdunlock(struct brcmf_bus *bus);
-static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus);
-
-/* Packet free applicable unconditionally for sdio and sdspi.
- * Conditional if bufpool was present for gspi bus.
- */
-static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt)
-{
- if ((bus->bus != SPI_BUS) || bus->usebufpool)
- brcmu_pkt_buf_free_skb(pkt);
-}
-
-static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size)
-{
- s32 min_size = DONGLE_MIN_MEMSIZE;
- /* Restrict the memsize to user specified limit */
- BRCMF_ERROR(("user: Restrict the dongle ram size to %d, min %d\n",
- brcmf_dongle_memsize, min_size));
- if ((brcmf_dongle_memsize > min_size) &&
- (brcmf_dongle_memsize < (s32) bus->orig_ramsize))
- bus->ramsize = brcmf_dongle_memsize;
-}
-
-static int brcmf_sdbrcm_set_siaddr_window(struct brcmf_bus *bus, u32 address)
-{
- int err = 0;
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
- (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
- if (!err)
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_SBADDRMID,
- (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
- if (!err)
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_SBADDRHIGH,
- (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
- &err);
- return err;
-}
-
-/* Turn backplane clock on or off */
-static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
-{
- int err;
- u8 clkctl, clkreq, devctl;
- struct brcmf_sdio_card *card;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- clkctl = 0;
- card = bus->card;
-
- if (on) {
- /* Request HT Avail */
- clkreq =
- bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
-
- if ((bus->ci->chip == BCM4329_CHIP_ID)
- && (bus->ci->chiprev == 0))
- clkreq |= SBSDIO_FORCE_ALP;
-
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
- if (err) {
- BRCMF_ERROR(("%s: HT Avail request error: %d\n",
- __func__, err));
- return -EBADE;
- }
-
- if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID)
- && (bus->ci->buscorerev == 9))) {
- u32 dummy, retries;
- r_sdreg32(bus, &dummy,
- offsetof(struct sdpcmd_regs, clockctlstatus),
- &retries);
- }
-
- /* Check current status */
- clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (err) {
- BRCMF_ERROR(("%s: HT Avail read error: %d\n",
- __func__, err));
- return -EBADE;
- }
-
- /* Go to pending and await interrupt if appropriate */
- if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
- /* Allow only clock-available interrupt */
- devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL, &err);
- if (err) {
- BRCMF_ERROR(("%s: Devctl error setting CA:"
- " %d\n", __func__, err));
- return -EBADE;
- }
-
- devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL, devctl, &err);
- BRCMF_INFO(("CLKCTL: set PENDING\n"));
- bus->clkstate = CLK_PENDING;
-
- return 0;
- } else if (bus->clkstate == CLK_PENDING) {
- /* Cancel CA-only interrupt filter */
- devctl =
- brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL, &err);
- devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL, devctl, &err);
- }
-
- /* Otherwise, wait here (polling) for HT Avail */
- if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
- BRCMF_SPINWAIT_SLEEP(sdioh_spinwait_sleep,
- ((clkctl =
- brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- &err)),
- !SBSDIO_CLKAV(clkctl, bus->alp_only)),
- PMU_MAX_TRANSITION_DLY);
- }
- if (err) {
- BRCMF_ERROR(("%s: HT Avail request error: %d\n",
- __func__, err));
- return -EBADE;
- }
- if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
- BRCMF_ERROR(("%s: HT Avail timeout (%d): "
- "clkctl 0x%02x\n", __func__,
- PMU_MAX_TRANSITION_DLY, clkctl));
- return -EBADE;
- }
-
- /* Mark clock available */
- bus->clkstate = CLK_AVAIL;
- BRCMF_INFO(("CLKCTL: turned ON\n"));
-
-#if defined(BCMDBG)
- if (bus->alp_only != true) {
- if (SBSDIO_ALPONLY(clkctl)) {
- BRCMF_ERROR(("%s: HT Clock should be on.\n",
- __func__));
- }
- }
-#endif /* defined (BCMDBG) */
-
- bus->activity = true;
- } else {
- clkreq = 0;
-
- if (bus->clkstate == CLK_PENDING) {
- /* Cancel CA-only interrupt filter */
- devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL, &err);
- devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL, devctl, &err);
- }
-
- bus->clkstate = CLK_SDONLY;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
- BRCMF_INFO(("CLKCTL: turned OFF\n"));
- if (err) {
- BRCMF_ERROR(("%s: Failed access turning clock off:"
- " %d\n", __func__, err));
- return -EBADE;
- }
- }
- return 0;
-}
-
-/* Change idle/active SD state */
-static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (on)
- bus->clkstate = CLK_SDONLY;
- else
- bus->clkstate = CLK_NONE;
-
- return 0;
-}
-
-/* Transition SD and backplane clock readiness */
-static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
-{
-#ifdef BCMDBG
- uint oldstate = bus->clkstate;
-#endif /* BCMDBG */
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* Early exit if we're already there */
- if (bus->clkstate == target) {
- if (target == CLK_AVAIL) {
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
- bus->activity = true;
- }
- return 0;
- }
-
- switch (target) {
- case CLK_AVAIL:
- /* Make sure SD clock is available */
- if (bus->clkstate == CLK_NONE)
- brcmf_sdbrcm_sdclk(bus, true);
- /* Now request HT Avail on the backplane */
- brcmf_sdbrcm_htclk(bus, true, pendok);
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
- bus->activity = true;
- break;
-
- case CLK_SDONLY:
- /* Remove HT request, or bring up SD clock */
- if (bus->clkstate == CLK_NONE)
- brcmf_sdbrcm_sdclk(bus, true);
- else if (bus->clkstate == CLK_AVAIL)
- brcmf_sdbrcm_htclk(bus, false, false);
- else
- BRCMF_ERROR(("brcmf_sdbrcm_clkctl: request for %d -> %d"
- "\n", bus->clkstate, target));
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
- break;
-
- case CLK_NONE:
- /* Make sure to remove HT request */
- if (bus->clkstate == CLK_AVAIL)
- brcmf_sdbrcm_htclk(bus, false, false);
- /* Now remove the SD clock */
- brcmf_sdbrcm_sdclk(bus, false);
- brcmf_sdbrcm_wd_timer(bus, 0);
- break;
- }
-#ifdef BCMDBG
- BRCMF_INFO(("brcmf_sdbrcm_clkctl: %d -> %d\n",
- oldstate, bus->clkstate));
-#endif /* BCMDBG */
-
- return 0;
-}
-
-int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
-{
- struct brcmf_sdio_card *card = bus->card;
- uint retries = 0;
-
- BRCMF_INFO(("brcmf_sdbrcm_bussleep: request %s (currently %s)\n",
- (sleep ? "SLEEP" : "WAKE"),
- (bus->sleeping ? "SLEEP" : "WAKE")));
-
- /* Done if we're already in the requested state */
- if (sleep == bus->sleeping)
- return 0;
-
- /* Going to sleep: set the alarm and turn off the lights... */
- if (sleep) {
- /* Don't sleep if something is pending */
- if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
- return -EBUSY;
-
- /* Disable SDIO interrupts (no longer interested) */
- brcmf_sdcard_intr_disable(bus->card);
-
- /* Make sure the controller has the bus up */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- /* Tell device to start using OOB wakeup */
- w_sdreg32(bus, SMB_USE_OOB,
- offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
- if (retries > retry_limit)
- BRCMF_ERROR(("CANNOT SIGNAL CHIP, "
- "WILL NOT WAKE UP!!\n"));
-
- /* Turn off our contribution to the HT clock request */
- brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
-
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
-
- /* Isolate the bus */
- if (bus->ci->chip != BCM4329_CHIP_ID
- && bus->ci->chip != BCM4319_CHIP_ID) {
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL,
- SBSDIO_DEVCTL_PADS_ISO, NULL);
- }
-
- /* Change state */
- bus->sleeping = true;
-
- } else {
- /* Waking up: bus power up is ok, set local state */
-
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
-
- /* Force pad isolation off if possible
- (in case power never toggled) */
- if ((bus->ci->buscoretype == PCMCIA_CORE_ID)
- && (bus->ci->buscorerev >= 10))
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL, 0, NULL);
-
- /* Make sure the controller has the bus up */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- /* Send misc interrupt to indicate OOB not needed */
- w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata),
- &retries);
- if (retries <= retry_limit)
- w_sdreg32(bus, SMB_DEV_INT,
- offsetof(struct sdpcmd_regs, tosbmailbox),
- &retries);
-
- if (retries > retry_limit)
- BRCMF_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
-
- /* Make sure we have SD bus access */
- brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
-
- /* Change state */
- bus->sleeping = false;
-
- /* Enable interrupts again */
- if (bus->intr && (bus->drvr->busstate == BRCMF_BUS_DATA)) {
- bus->intdis = false;
- brcmf_sdcard_intr_enable(bus->card);
- }
- }
-
- return 0;
-}
-
-#define BUS_WAKE(bus) \
- do { \
- if ((bus)->sleeping) \
- brcmf_sdbrcm_bussleep((bus), false); \
- } while (0);
-
-/* Writes a HW/SW header into the packet and sends it. */
-/* Assumes: (a) header space already there, (b) caller holds lock */
-static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, uint chan,
- bool free_pkt)
-{
- int ret;
- u8 *frame;
- u16 len, pad = 0;
- u32 swheader;
- uint retries = 0;
- struct brcmf_sdio_card *card;
- struct sk_buff *new;
- int i;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- card = bus->card;
-
- if (bus->drvr->dongle_reset) {
- ret = -EPERM;
- goto done;
- }
-
- frame = (u8 *) (pkt->data);
-
- /* Add alignment padding, allocate new packet if needed */
- pad = ((unsigned long)frame % BRCMF_SDALIGN);
- if (pad) {
- if (skb_headroom(pkt) < pad) {
- BRCMF_INFO(("%s: insufficient headroom %d for %d pad\n",
- __func__, skb_headroom(pkt), pad));
- bus->drvr->tx_realloc++;
- new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
- if (!new) {
- BRCMF_ERROR(("%s: couldn't allocate new "
- "%d-byte packet\n", __func__,
- pkt->len + BRCMF_SDALIGN));
- ret = -ENOMEM;
- goto done;
- }
-
- PKTALIGN(new, pkt->len, BRCMF_SDALIGN);
- memcpy(new->data, pkt->data, pkt->len);
- if (free_pkt)
- brcmu_pkt_buf_free_skb(pkt);
- /* free the pkt if canned one is not used */
- free_pkt = true;
- pkt = new;
- frame = (u8 *) (pkt->data);
- /* precondition: (frame % BRCMF_SDALIGN) == 0) */
- pad = 0;
- } else {
- skb_push(pkt, pad);
- frame = (u8 *) (pkt->data);
- /* precondition: pad + SDPCM_HDRLEN <= pkt->len */
- memset(frame, 0, pad + SDPCM_HDRLEN);
- }
- }
- /* precondition: pad < BRCMF_SDALIGN */
-
- /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
- len = (u16) (pkt->len);
- *(u16 *) frame = cpu_to_le16(len);
- *(((u16 *) frame) + 1) = cpu_to_le16(~len);
-
- /* Software tag: channel, sequence number, data offset */
- swheader =
- ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
- (((pad +
- SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
-
- put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
- put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
-
-#ifdef BCMDBG
- tx_packets[pkt->priority]++;
- if (BRCMF_BYTES_ON() &&
- (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
- (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
- printk(KERN_DEBUG "Tx Frame:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len);
- } else if (BRCMF_HDRS_ON()) {
- printk(KERN_DEBUG "TxHdr:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- frame, min_t(u16, len, 16));
- }
-#endif
-
- /* Raise len to next SDIO block to eliminate tail command */
- if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
- u16 pad = bus->blocksize - (len % bus->blocksize);
- if ((pad <= bus->roundup) && (pad < bus->blocksize))
- len += pad;
- } else if (len % BRCMF_SDALIGN) {
- len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
- }
-
- /* Some controllers have trouble with odd bytes -- round to even */
- if (forcealign && (len & (ALIGNMENT - 1))) {
- len = roundup(len, ALIGNMENT);
- }
-
- do {
- ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2, F2SYNC, frame, len, pkt, NULL, NULL);
- bus->f2txdata++;
-
- if (ret < 0) {
- /* On failure, abort the command
- and terminate the frame */
- BRCMF_INFO(("%s: sdio error %d, abort command and "
- "terminate frame.\n", __func__, ret));
- bus->tx_sderrs++;
-
- brcmf_sdcard_abort(card, SDIO_FUNC_2);
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
- NULL);
- bus->f1regdata++;
-
- for (i = 0; i < 3; i++) {
- u8 hi, lo;
- hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_WFRAMEBCHI,
- NULL);
- lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_WFRAMEBCLO,
- NULL);
- bus->f1regdata += 2;
- if ((hi == 0) && (lo == 0))
- break;
- }
-
- }
- if (ret == 0)
- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
-
- } while ((ret < 0) && retrydata && retries++ < TXRETRIES);
-
-done:
- /* restore pkt buffer pointer before calling tx complete routine */
- skb_pull(pkt, SDPCM_HDRLEN + pad);
- brcmf_sdbrcm_sdunlock(bus);
- brcmf_txcomplete(bus->drvr, pkt, ret != 0);
- brcmf_sdbrcm_sdlock(bus);
-
- if (free_pkt)
- brcmu_pkt_buf_free_skb(pkt);
-
- return ret;
-}
-
-int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
-{
- int ret = -EBADE;
- uint datalen, prec;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- datalen = pkt->len;
-
-#ifdef SDTEST
- /* Push the test header if doing loopback */
- if (bus->ext_loop) {
- u8 *data;
- skb_push(pkt, SDPCM_TEST_HDRLEN);
- data = pkt->data;
- *data++ = SDPCM_TEST_ECHOREQ;
- *data++ = (u8) bus->loopid++;
- *data++ = (datalen >> 0);
- *data++ = (datalen >> 8);
- datalen += SDPCM_TEST_HDRLEN;
- }
-#endif /* SDTEST */
-
- /* Add space for the header */
- skb_push(pkt, SDPCM_HDRLEN);
- /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */
-
- prec = PRIO2PREC((pkt->priority & PRIOMASK));
-
- /* Check for existing queue, current flow-control,
- pending event, or pending clock */
- if (brcmf_deferred_tx || bus->fcstate || pktq_len(&bus->txq)
- || bus->dpc_sched || (!DATAOK(bus))
- || (bus->flowcontrol & NBITVAL(prec))
- || (bus->clkstate != CLK_AVAIL)) {
- BRCMF_TRACE(("%s: deferring pktq len %d\n", __func__,
- pktq_len(&bus->txq)));
- bus->fcqueued++;
-
- /* Priority based enq */
- spin_lock_bh(&bus->txqlock);
- if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) {
- skb_pull(pkt, SDPCM_HDRLEN);
- brcmf_txcomplete(bus->drvr, pkt, false);
- brcmu_pkt_buf_free_skb(pkt);
- BRCMF_ERROR(("%s: out of bus->txq !!!\n", __func__));
- ret = -ENOSR;
- } else {
- ret = 0;
- }
- spin_unlock_bh(&bus->txqlock);
-
- if (pktq_len(&bus->txq) >= TXHI)
- brcmf_txflowcontrol(bus->drvr, 0, ON);
-
-#ifdef BCMDBG
- if (pktq_plen(&bus->txq, prec) > qcount[prec])
- qcount[prec] = pktq_plen(&bus->txq, prec);
-#endif
- /* Schedule DPC if needed to send queued packet(s) */
- if (brcmf_deferred_tx && !bus->dpc_sched) {
- bus->dpc_sched = true;
- brcmf_sdbrcm_sched_dpc(bus);
- }
- } else {
- /* Lock: we're about to use shared data/code (and SDIO) */
- brcmf_sdbrcm_sdlock(bus);
-
- /* Otherwise, send it now */
- BUS_WAKE(bus);
- /* Make sure back plane ht clk is on, no pending allowed */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
-
-#ifndef SDTEST
- BRCMF_TRACE(("%s: calling txpkt\n", __func__));
- ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
-#else
- ret = brcmf_sdbrcm_txpkt(bus, pkt,
- (bus->ext_loop ? SDPCM_TEST_CHANNEL :
- SDPCM_DATA_CHANNEL), true);
-#endif
- if (ret)
- bus->drvr->tx_errors++;
- else
- bus->drvr->dstats.tx_bytes += datalen;
-
- if (bus->idletime == BRCMF_IDLE_IMMEDIATE &&
- !bus->dpc_sched) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
- }
-
- brcmf_sdbrcm_sdunlock(bus);
- }
-
- return ret;
-}
-
-static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes)
-{
- struct sk_buff *pkt;
- u32 intstatus = 0;
- uint retries = 0;
- int ret = 0, prec_out;
- uint cnt = 0;
- uint datalen;
- u8 tx_prec_map;
-
- struct brcmf_pub *drvr = bus->drvr;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- tx_prec_map = ~bus->flowcontrol;
-
- /* Send frames until the limit or some other event */
- for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) {
- spin_lock_bh(&bus->txqlock);
- pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
- if (pkt == NULL) {
- spin_unlock_bh(&bus->txqlock);
- break;
- }
- spin_unlock_bh(&bus->txqlock);
- datalen = pkt->len - SDPCM_HDRLEN;
-
-#ifndef SDTEST
- ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
-#else
- ret = brcmf_sdbrcm_txpkt(bus, pkt,
- (bus->ext_loop ? SDPCM_TEST_CHANNEL :
- SDPCM_DATA_CHANNEL), true);
-#endif
- if (ret)
- bus->drvr->tx_errors++;
- else
- bus->drvr->dstats.tx_bytes += datalen;
-
- /* In poll mode, need to check for other events */
- if (!bus->intr && cnt) {
- /* Check device status, signal pending interrupt */
- r_sdreg32(bus, &intstatus,
- offsetof(struct sdpcmd_regs, intstatus),
- &retries);
- bus->f2txdata++;
- if (brcmf_sdcard_regfail(bus->card))
- break;
- if (intstatus & bus->hostintmask)
- bus->ipend = true;
- }
- }
-
- /* Deflow-control stack if needed */
- if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) &&
- drvr->txoff && (pktq_len(&bus->txq) < TXLOW))
- brcmf_txflowcontrol(drvr, 0, OFF);
-
- return cnt;
-}
-
-int
-brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
-{
- u8 *frame;
- u16 len;
- u32 swheader;
- uint retries = 0;
- struct brcmf_sdio_card *card = bus->card;
- u8 doff = 0;
- int ret = -1;
- int i;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (bus->drvr->dongle_reset)
- return -EIO;
-
- /* Back the pointer to make a room for bus header */
- frame = msg - SDPCM_HDRLEN;
- len = (msglen += SDPCM_HDRLEN);
-
- /* Add alignment padding (optional for ctl frames) */
- if (brcmf_alignctl) {
- doff = ((unsigned long)frame % BRCMF_SDALIGN);
- if (doff) {
- frame -= doff;
- len += doff;
- msglen += doff;
- memset(frame, 0, doff + SDPCM_HDRLEN);
- }
- /* precondition: doff < BRCMF_SDALIGN */
- }
- doff += SDPCM_HDRLEN;
-
- /* Round send length to next SDIO block */
- if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
- u16 pad = bus->blocksize - (len % bus->blocksize);
- if ((pad <= bus->roundup) && (pad < bus->blocksize))
- len += pad;
- } else if (len % BRCMF_SDALIGN) {
- len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
- }
-
- /* Satisfy length-alignment requirements */
- if (forcealign && (len & (ALIGNMENT - 1)))
- len = roundup(len, ALIGNMENT);
-
- /* precondition: IS_ALIGNED((unsigned long)frame, 2) */
-
- /* Need to lock here to protect txseq and SDIO tx calls */
- brcmf_sdbrcm_sdlock(bus);
-
- BUS_WAKE(bus);
-
- /* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
- *(u16 *) frame = cpu_to_le16((u16) msglen);
- *(((u16 *) frame) + 1) = cpu_to_le16(~msglen);
-
- /* Software tag: channel, sequence number, data offset */
- swheader =
- ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) &
- SDPCM_CHANNEL_MASK)
- | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) &
- SDPCM_DOFFSET_MASK);
- put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
- put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
-
- if (!DATAOK(bus)) {
- BRCMF_INFO(("%s: No bus credit bus->tx_max %d,"
- " bus->tx_seq %d\n", __func__,
- bus->tx_max, bus->tx_seq));
- bus->ctrl_frame_stat = true;
- /* Send from dpc */
- bus->ctrl_frame_buf = frame;
- bus->ctrl_frame_len = len;
-
- brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
-
- if (bus->ctrl_frame_stat == false) {
- BRCMF_INFO(("%s: ctrl_frame_stat == false\n",
- __func__));
- ret = 0;
- } else {
- BRCMF_INFO(("%s: ctrl_frame_stat == true\n", __func__));
- ret = -1;
- }
- }
-
- if (ret == -1) {
-#ifdef BCMDBG
- if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
- printk(KERN_DEBUG "Tx Frame:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- frame, len);
- } else if (BRCMF_HDRS_ON()) {
- printk(KERN_DEBUG "TxHdr:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- frame, min_t(u16, len, 16));
- }
-#endif
-
- do {
- bus->ctrl_frame_stat = false;
- ret = brcmf_sdbrcm_send_buf(bus,
- brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2,
- F2SYNC, frame, len, NULL, NULL, NULL);
-
- if (ret < 0) {
- /* On failure, abort the command and
- terminate the frame */
- BRCMF_INFO(("%s: sdio error %d, abort command "
- "and terminate frame.\n",
- __func__, ret));
- bus->tx_sderrs++;
-
- brcmf_sdcard_abort(card, SDIO_FUNC_2);
-
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_FRAMECTRL,
- SFC_WF_TERM, NULL);
- bus->f1regdata++;
-
- for (i = 0; i < 3; i++) {
- u8 hi, lo;
- hi = brcmf_sdcard_cfg_read(card,
- SDIO_FUNC_1,
- SBSDIO_FUNC1_WFRAMEBCHI,
- NULL);
- lo = brcmf_sdcard_cfg_read(card,
- SDIO_FUNC_1,
- SBSDIO_FUNC1_WFRAMEBCLO,
- NULL);
- bus->f1regdata += 2;
- if ((hi == 0) && (lo == 0))
- break;
- }
-
- }
- if (ret == 0) {
- bus->tx_seq =
- (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
- }
- } while ((ret < 0) && retries++ < TXRETRIES);
- }
-
- if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
- }
-
- brcmf_sdbrcm_sdunlock(bus);
-
- if (ret)
- bus->drvr->tx_ctlerrs++;
- else
- bus->drvr->tx_ctlpkts++;
-
- return ret ? -EIO : 0;
-}
-
-int brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
-{
- int timeleft;
- uint rxlen = 0;
- bool pending;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (bus->drvr->dongle_reset)
- return -EIO;
-
- /* Wait until control frame is available */
- timeleft = brcmf_os_ioctl_resp_wait(bus->drvr, &bus->rxlen, &pending);
-
- brcmf_sdbrcm_sdlock(bus);
- rxlen = bus->rxlen;
- memcpy(msg, bus->rxctl, min(msglen, rxlen));
- bus->rxlen = 0;
- brcmf_sdbrcm_sdunlock(bus);
-
- if (rxlen) {
- BRCMF_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
- __func__, rxlen, msglen));
- } else if (timeleft == 0) {
- BRCMF_ERROR(("%s: resumed on timeout\n", __func__));
-#ifdef BCMDBG
- brcmf_sdbrcm_sdlock(bus);
- brcmf_sdbrcm_checkdied(bus, NULL, 0);
- brcmf_sdbrcm_sdunlock(bus);
-#endif /* BCMDBG */
- } else if (pending == true) {
- BRCMF_CTL(("%s: cancelled\n", __func__));
- return -ERESTARTSYS;
- } else {
- BRCMF_CTL(("%s: resumed for unknown reason?\n", __func__));
-#ifdef BCMDBG
- brcmf_sdbrcm_sdlock(bus);
- brcmf_sdbrcm_checkdied(bus, NULL, 0);
- brcmf_sdbrcm_sdunlock(bus);
-#endif /* BCMDBG */
- }
-
- if (rxlen)
- bus->drvr->rx_ctlpkts++;
- else
- bus->drvr->rx_ctlerrs++;
-
- return rxlen ? (int)rxlen : -ETIMEDOUT;
-}
-
-/* IOVar table */
-enum {
- IOV_INTR = 1,
- IOV_POLLRATE,
- IOV_SDREG,
- IOV_SBREG,
- IOV_SDCIS,
- IOV_MEMBYTES,
- IOV_MEMSIZE,
-#ifdef BCMDBG
- IOV_CHECKDIED,
- IOV_CONS,
- IOV_DCONSOLE_POLL,
-#endif
- IOV_DOWNLOAD,
- IOV_FORCEEVEN,
- IOV_SDIOD_DRIVE,
- IOV_READAHEAD,
- IOV_SDRXCHAIN,
- IOV_ALIGNCTL,
- IOV_SDALIGN,
- IOV_DEVRESET,
- IOV_CPU,
-#ifdef SDTEST
- IOV_PKTGEN,
- IOV_EXTLOOP,
-#endif /* SDTEST */
- IOV_SPROM,
- IOV_TXBOUND,
- IOV_RXBOUND,
- IOV_TXMINMAX,
- IOV_IDLETIME,
- IOV_IDLECLOCK,
- IOV_SD1IDLE,
- IOV_SLEEP,
- IOV_WDTICK,
- IOV_VARS
-};
-
-const struct brcmu_iovar brcmf_sdio_iovars[] = {
- {"intr", IOV_INTR, 0, IOVT_BOOL, 0},
- {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0},
- {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0},
- {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0},
- {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0},
- {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0},
- {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int)},
- {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0},
- {"download", IOV_DOWNLOAD, 0, IOVT_BOOL, 0},
- {"vars", IOV_VARS, 0, IOVT_BUFFER, 0},
- {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0},
- {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0},
- {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0},
- {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0},
- {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0},
- {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0},
- {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0},
-#ifdef BCMDBG
- {"cons", IOV_CONS, 0, IOVT_BUFFER, 0}
- ,
- {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0}
- ,
- {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
- ,
- {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
- ,
- {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN}
- ,
- {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0}
- ,
- {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0}
- ,
- {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0}
- ,
- {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0}
- ,
- {"cpu", IOV_CPU, 0, IOVT_BOOL, 0}
- ,
- {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0}
- ,
-#endif /* BCMDBG */
-#ifdef SDTEST
- {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0}
- ,
- {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(struct brcmf_pktgen)}
- ,
-#endif /* SDTEST */
-
- {NULL, 0, 0, 0, 0}
-};
-
-static void
-brcmf_dump_pct(struct brcmu_strbuf *strbuf, char *desc, uint num, uint div)
-{
- uint q1, q2;
-
- if (!div) {
- brcmu_bprintf(strbuf, "%s N/A", desc);
- } else {
- q1 = num / div;
- q2 = (100 * (num - (q1 * div))) / div;
- brcmu_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
- }
-}
-
-void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
-{
- struct brcmf_bus *bus = drvr->bus;
-
- brcmu_bprintf(strbuf, "Bus SDIO structure:\n");
- brcmu_bprintf(strbuf,
- "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
- bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
- brcmu_bprintf(strbuf,
- "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n",
- bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max,
- bus->rxskip, bus->rxlen, bus->rx_seq);
- brcmu_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
- bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
- brcmu_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
- bus->pollrate, bus->pollcnt, bus->regfails);
-
- brcmu_bprintf(strbuf, "\nAdditional counters:\n");
- brcmu_bprintf(strbuf,
- "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n",
- bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
- bus->rxc_errors);
- brcmu_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
- bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
- brcmu_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n",
- bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
- brcmu_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n",
- bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
- brcmu_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs"
- " %d\n",
- (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs,
- bus->f2rxdata, bus->f2txdata, bus->f1regdata);
- {
- brcmf_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->drvr->rx_packets,
- (bus->f2rxhdrs + bus->f2rxdata));
- brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->rx_packets,
- bus->f1regdata);
- brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->rx_packets,
- (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
- brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->rx_packets,
- bus->intrcount);
- brcmu_bprintf(strbuf, "\n");
-
- brcmf_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
- bus->drvr->rx_packets);
- brcmf_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts,
- bus->rxglomframes);
- brcmu_bprintf(strbuf, "\n");
-
- brcmf_dump_pct(strbuf, "Tx: pkts/f2wr", bus->drvr->tx_packets,
- bus->f2txdata);
- brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->tx_packets,
- bus->f1regdata);
- brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->tx_packets,
- (bus->f2txdata + bus->f1regdata));
- brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->tx_packets,
- bus->intrcount);
- brcmu_bprintf(strbuf, "\n");
-
- brcmf_dump_pct(strbuf, "Total: pkts/f2rw",
- (bus->drvr->tx_packets + bus->drvr->rx_packets),
- (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
- brcmf_dump_pct(strbuf, ", pkts/f1sd",
- (bus->drvr->tx_packets + bus->drvr->rx_packets),
- bus->f1regdata);
- brcmf_dump_pct(strbuf, ", pkts/sd",
- (bus->drvr->tx_packets + bus->drvr->rx_packets),
- (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata +
- bus->f1regdata));
- brcmf_dump_pct(strbuf, ", pkts/int",
- (bus->drvr->tx_packets + bus->drvr->rx_packets),
- bus->intrcount);
- brcmu_bprintf(strbuf, "\n\n");
- }
-
-#ifdef SDTEST
- if (bus->pktgen_count) {
- brcmu_bprintf(strbuf, "pktgen config and count:\n");
- brcmu_bprintf(strbuf,
- "freq %d count %d print %d total %d min %d len %d\n",
- bus->pktgen_freq, bus->pktgen_count,
- bus->pktgen_print, bus->pktgen_total,
- bus->pktgen_minlen, bus->pktgen_maxlen);
- brcmu_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
- bus->pktgen_sent, bus->pktgen_rcvd,
- bus->pktgen_fail);
- }
-#endif /* SDTEST */
-#ifdef BCMDBG
- brcmu_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
- bus->dpc_sched, " not ");
- brcmu_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize,
- bus->roundup);
-#endif /* BCMDBG */
- brcmu_bprintf(strbuf,
- "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
- bus->clkstate, bus->activity, bus->idletime, bus->idlecount,
- bus->sleeping);
-}
-
-void brcmf_bus_clearcounts(struct brcmf_pub *drvr)
-{
- struct brcmf_bus *bus = (struct brcmf_bus *) drvr->bus;
-
- bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
- bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
- bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
- bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
- bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
- bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
-}
-
-#ifdef SDTEST
-static int brcmf_sdbrcm_pktgen_get(struct brcmf_bus *bus, u8 *arg)
-{
- struct brcmf_pktgen pktgen;
-
- pktgen.version = BRCMF_PKTGEN_VERSION;
- pktgen.freq = bus->pktgen_freq;
- pktgen.count = bus->pktgen_count;
- pktgen.print = bus->pktgen_print;
- pktgen.total = bus->pktgen_total;
- pktgen.minlen = bus->pktgen_minlen;
- pktgen.maxlen = bus->pktgen_maxlen;
- pktgen.numsent = bus->pktgen_sent;
- pktgen.numrcvd = bus->pktgen_rcvd;
- pktgen.numfail = bus->pktgen_fail;
- pktgen.mode = bus->pktgen_mode;
- pktgen.stop = bus->pktgen_stop;
-
- memcpy(arg, &pktgen, sizeof(pktgen));
-
- return 0;
-}
-
-static int brcmf_sdbrcm_pktgen_set(struct brcmf_bus *bus, u8 *arg)
-{
- struct brcmf_pktgen pktgen;
- uint oldcnt, oldmode;
-
- memcpy(&pktgen, arg, sizeof(pktgen));
- if (pktgen.version != BRCMF_PKTGEN_VERSION)
- return -EINVAL;
-
- oldcnt = bus->pktgen_count;
- oldmode = bus->pktgen_mode;
-
- bus->pktgen_freq = pktgen.freq;
- bus->pktgen_count = pktgen.count;
- bus->pktgen_print = pktgen.print;
- bus->pktgen_total = pktgen.total;
- bus->pktgen_minlen = pktgen.minlen;
- bus->pktgen_maxlen = pktgen.maxlen;
- bus->pktgen_mode = pktgen.mode;
- bus->pktgen_stop = pktgen.stop;
-
- bus->pktgen_tick = bus->pktgen_ptick = 0;
- bus->pktgen_len = max(bus->pktgen_len, bus->pktgen_minlen);
- bus->pktgen_len = min(bus->pktgen_len, bus->pktgen_maxlen);
-
- /* Clear counts for a new pktgen (mode change, or was stopped) */
- if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode))
- bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0;
-
- return 0;
-}
-#endif /* SDTEST */
-
-static int
-brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data,
- uint size)
-{
- int bcmerror = 0;
- u32 sdaddr;
- uint dsize;
-
- /* Determine initial transfer parameters */
- sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
- if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
- dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
- else
- dsize = size;
-
- /* Set the backplane window to include the start address */
- bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address);
- if (bcmerror) {
- BRCMF_ERROR(("%s: window change failed\n", __func__));
- goto xfer_done;
- }
-
- /* Do the transfer(s) */
- while (size) {
- BRCMF_INFO(("%s: %s %d bytes at offset 0x%08x in window"
- " 0x%08x\n", __func__, (write ? "write" : "read"),
- dsize, sdaddr, (address & SBSDIO_SBWINDOW_MASK)));
- bcmerror =
- brcmf_sdcard_rwdata(bus->card, write, sdaddr, data, dsize);
- if (bcmerror) {
- BRCMF_ERROR(("%s: membytes transfer failed\n",
- __func__));
- break;
- }
-
- /* Adjust for next transfer (if any) */
- size -= dsize;
- if (size) {
- data += dsize;
- address += dsize;
- bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address);
- if (bcmerror) {
- BRCMF_ERROR(("%s: window change failed\n",
- __func__));
- break;
- }
- sdaddr = 0;
- dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
- }
- }
-
-xfer_done:
- /* Return the window to backplane enumeration space for core access */
- if (brcmf_sdbrcm_set_siaddr_window(bus,
- brcmf_sdcard_cur_sbwad(bus->card))) {
- BRCMF_ERROR(("%s: FAILED to set window back to 0x%x\n",
- __func__, brcmf_sdcard_cur_sbwad(bus->card)));
- }
-
- return bcmerror;
-}
-
-#ifdef BCMDBG
-static int brcmf_sdbrcm_readshared(struct brcmf_bus *bus, struct sdpcm_shared *sh)
-{
- u32 addr;
- int rv;
-
- /* Read last word in memory to determine address of
- sdpcm_shared structure */
- rv = brcmf_sdbrcm_membytes(bus, false, bus->ramsize - 4, (u8 *)&addr,
- 4);
- if (rv < 0)
- return rv;
-
- addr = le32_to_cpu(addr);
-
- BRCMF_INFO(("sdpcm_shared address 0x%08X\n", addr));
-
- /*
- * Check if addr is valid.
- * NVRAM length at the end of memory should have been overwritten.
- */
- if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
- BRCMF_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
- __func__, addr));
- return -EBADE;
- }
-
- /* Read rte_shared structure */
- rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *) sh,
- sizeof(struct sdpcm_shared));
- if (rv < 0)
- return rv;
-
- /* Endianness */
- sh->flags = le32_to_cpu(sh->flags);
- sh->trap_addr = le32_to_cpu(sh->trap_addr);
- sh->assert_exp_addr = le32_to_cpu(sh->assert_exp_addr);
- sh->assert_file_addr = le32_to_cpu(sh->assert_file_addr);
- sh->assert_line = le32_to_cpu(sh->assert_line);
- sh->console_addr = le32_to_cpu(sh->console_addr);
- sh->msgtrace_addr = le32_to_cpu(sh->msgtrace_addr);
-
- if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
- BRCMF_ERROR(("%s: sdpcm_shared version %d in brcmf "
- "is different than sdpcm_shared version %d in dongle\n",
- __func__, SDPCM_SHARED_VERSION,
- sh->flags & SDPCM_SHARED_VERSION_MASK));
- return -EBADE;
- }
-
- return 0;
-}
-
-static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size)
-{
- int bcmerror = 0;
- uint msize = 512;
- char *mbuffer = NULL;
- uint maxstrlen = 256;
- char *str = NULL;
- struct brcmf_trap tr;
- struct sdpcm_shared sdpcm_shared;
- struct brcmu_strbuf strbuf;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (data == NULL) {
- /*
- * Called after a rx ctrl timeout. "data" is NULL.
- * allocate memory to trace the trap or assert.
- */
- size = msize;
- mbuffer = data = kmalloc(msize, GFP_ATOMIC);
- if (mbuffer == NULL) {
- BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__,
- msize));
- bcmerror = -ENOMEM;
- goto done;
- }
- }
-
- str = kmalloc(maxstrlen, GFP_ATOMIC);
- if (str == NULL) {
- BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__, maxstrlen));
- bcmerror = -ENOMEM;
- goto done;
- }
-
- bcmerror = brcmf_sdbrcm_readshared(bus, &sdpcm_shared);
- if (bcmerror < 0)
- goto done;
-
- brcmu_binit(&strbuf, data, size);
-
- brcmu_bprintf(&strbuf,
- "msgtrace address : 0x%08X\nconsole address : 0x%08X\n",
- sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
-
- if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
- /* NOTE: Misspelled assert is intentional - DO NOT FIX.
- * (Avoids conflict with real asserts for programmatic
- * parsing of output.)
- */
- brcmu_bprintf(&strbuf, "Assrt not built in dongle\n");
- }
-
- if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) ==
- 0) {
- /* NOTE: Misspelled assert is intentional - DO NOT FIX.
- * (Avoids conflict with real asserts for programmatic
- * parsing of output.)
- */
- brcmu_bprintf(&strbuf, "No trap%s in dongle",
- (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
- ? "/assrt" : "");
- } else {
- if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
- /* Download assert */
- brcmu_bprintf(&strbuf, "Dongle assert");
- if (sdpcm_shared.assert_exp_addr != 0) {
- str[0] = '\0';
- bcmerror = brcmf_sdbrcm_membytes(bus, false,
- sdpcm_shared.assert_exp_addr,
- (u8 *) str, maxstrlen);
- if (bcmerror < 0)
- goto done;
-
- str[maxstrlen - 1] = '\0';
- brcmu_bprintf(&strbuf, " expr \"%s\"", str);
- }
-
- if (sdpcm_shared.assert_file_addr != 0) {
- str[0] = '\0';
- bcmerror = brcmf_sdbrcm_membytes(bus, false,
- sdpcm_shared.assert_file_addr,
- (u8 *) str, maxstrlen);
- if (bcmerror < 0)
- goto done;
-
- str[maxstrlen - 1] = '\0';
- brcmu_bprintf(&strbuf, " file \"%s\"", str);
- }
-
- brcmu_bprintf(&strbuf, " line %d ",
- sdpcm_shared.assert_line);
- }
-
- if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
- bcmerror = brcmf_sdbrcm_membytes(bus, false,
- sdpcm_shared.trap_addr, (u8 *)&tr,
- sizeof(struct brcmf_trap));
- if (bcmerror < 0)
- goto done;
-
- brcmu_bprintf(&strbuf,
- "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
- "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
- "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
- tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13,
- tr.r14, tr.pc, sdpcm_shared.trap_addr,
- tr.r0, tr.r1, tr.r2, tr.r3, tr.r4, tr.r5,
- tr.r6, tr.r7);
- }
- }
-
- if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP))
- BRCMF_ERROR(("%s: %s\n", __func__, strbuf.origbuf));
-
-#ifdef BCMDBG
- if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
- /* Mem dump to a file on device */
- brcmf_sdbrcm_mem_dump(bus);
- }
-#endif /* BCMDBG */
-
-done:
- kfree(mbuffer);
- kfree(str);
-
- return bcmerror;
-}
-
-static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus)
-{
- int ret = 0;
- int size; /* Full mem size */
- int start = 0; /* Start address */
- int read_size = 0; /* Read size of each iteration */
- u8 *buf = NULL, *databuf = NULL;
-
- /* Get full mem size */
- size = bus->ramsize;
- buf = kmalloc(size, GFP_ATOMIC);
- if (!buf) {
- BRCMF_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
- return -1;
- }
-
- /* Read mem content */
- printk(KERN_DEBUG "Dump dongle memory");
- databuf = buf;
- while (size) {
- read_size = min(MEMBLOCK, size);
- ret = brcmf_sdbrcm_membytes(bus, false, start, databuf,
- read_size);
- if (ret) {
- BRCMF_ERROR(("%s: Error membytes %d\n", __func__, ret));
- kfree(buf);
- return -1;
- }
- printk(".");
-
- /* Decrement size and increment start address */
- size -= read_size;
- start += read_size;
- databuf += read_size;
- }
- printk(KERN_DEBUG "Done\n");
-
- /* free buf before return !!! */
- if (brcmf_write_to_file(bus->drvr, buf, bus->ramsize)) {
- BRCMF_ERROR(("%s: Error writing to files\n", __func__));
- return -1;
- }
-
- /* buf free handled in brcmf_write_to_file, not here */
- return 0;
-}
-
-#define CONSOLE_LINE_MAX 192
-
-static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus)
-{
- struct brcmf_console *c = &bus->console;
- u8 line[CONSOLE_LINE_MAX], ch;
- u32 n, idx, addr;
- int rv;
-
- /* Don't do anything until FWREADY updates console address */
- if (bus->console_addr == 0)
- return 0;
-
- /* Read console log struct */
- addr = bus->console_addr + offsetof(struct rte_console, log);
- rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log,
- sizeof(c->log));
- if (rv < 0)
- return rv;
-
- /* Allocate console buffer (one time only) */
- if (c->buf == NULL) {
- c->bufsize = le32_to_cpu(c->log.buf_size);
- c->buf = kmalloc(c->bufsize, GFP_ATOMIC);
- if (c->buf == NULL)
- return -ENOMEM;
- }
-
- idx = le32_to_cpu(c->log.idx);
-
- /* Protect against corrupt value */
- if (idx > c->bufsize)
- return -EBADE;
-
- /* Skip reading the console buffer if the index pointer
- has not moved */
- if (idx == c->last)
- return 0;
-
- /* Read the console buffer */
- addr = le32_to_cpu(c->log.buf);
- rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
- if (rv < 0)
- return rv;
-
- while (c->last != idx) {
- for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
- if (c->last == idx) {
- /* This would output a partial line.
- * Instead, back up
- * the buffer pointer and output this
- * line next time around.
- */
- if (c->last >= n)
- c->last -= n;
- else
- c->last = c->bufsize - n;
- goto break2;
- }
- ch = c->buf[c->last];
- c->last = (c->last + 1) % c->bufsize;
- if (ch == '\n')
- break;
- line[n] = ch;
- }
-
- if (n > 0) {
- if (line[n - 1] == '\r')
- n--;
- line[n] = 0;
- printk(KERN_DEBUG "CONSOLE: %s\n", line);
- }
- }
-break2:
-
- return 0;
-}
-#endif /* BCMDBG */
-
-int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len)
-{
- int bcmerror = 0;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* Basic sanity checks */
- if (bus->drvr->up) {
- bcmerror = -EISCONN;
- goto err;
- }
- if (!len) {
- bcmerror = -EOVERFLOW;
- goto err;
- }
-
- /* Free the old ones and replace with passed variables */
- kfree(bus->vars);
-
- bus->vars = kmalloc(len, GFP_ATOMIC);
- bus->varsz = bus->vars ? len : 0;
- if (bus->vars == NULL) {
- bcmerror = -ENOMEM;
- goto err;
- }
-
- /* Copy the passed variables, which should include the
- terminating double-null */
- memcpy(bus->vars, arg, bus->varsz);
-err:
- return bcmerror;
-}
-
-static int
-brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, const struct brcmu_iovar *vi, u32 actionid,
- const char *name, void *params, int plen, void *arg, int len,
- int val_size)
-{
- int bcmerror = 0;
- s32 int_val = 0;
- bool bool_val = 0;
-
- BRCMF_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p "
- "len %d val_size %d\n", __func__, actionid, name, params,
- plen, arg, len, val_size));
-
- bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
- if (bcmerror != 0)
- goto exit;
-
- if (plen >= (int)sizeof(int_val))
- memcpy(&int_val, params, sizeof(int_val));
-
- bool_val = (int_val != 0) ? true : false;
-
- /* Some ioctls use the bus */
- brcmf_sdbrcm_sdlock(bus);
-
- /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
- if (bus->drvr->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
- actionid == IOV_GVAL(IOV_DEVRESET))) {
- bcmerror = -EPERM;
- goto exit;
- }
-
- /* Handle sleep stuff before any clock mucking */
- if (vi->varid == IOV_SLEEP) {
- if (IOV_ISSET(actionid)) {
- bcmerror = brcmf_sdbrcm_bussleep(bus, bool_val);
- } else {
- int_val = (s32) bus->sleeping;
- memcpy(arg, &int_val, val_size);
- }
- goto exit;
- }
-
- /* Request clock to allow SDIO accesses */
- if (!bus->drvr->dongle_reset) {
- BUS_WAKE(bus);
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- }
-
- switch (actionid) {
- case IOV_GVAL(IOV_INTR):
- int_val = (s32) bus->intr;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_INTR):
- bus->intr = bool_val;
- bus->intdis = false;
- if (bus->drvr->up) {
- BRCMF_INTR(("%s: %s SDIO interrupts\n", __func__,
- bus->intr ? "enable" : "disable"));
- if (bus->intr) {
- brcmf_sdcard_intr_enable(bus->card);
- } else {
- brcmf_sdcard_intr_disable(bus->card);
- }
- }
- break;
-
- case IOV_GVAL(IOV_POLLRATE):
- int_val = (s32) bus->pollrate;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_POLLRATE):
- bus->pollrate = (uint) int_val;
- bus->poll = (bus->pollrate != 0);
- break;
-
- case IOV_GVAL(IOV_IDLETIME):
- int_val = bus->idletime;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_IDLETIME):
- if ((int_val < 0) && (int_val != BRCMF_IDLE_IMMEDIATE))
- bcmerror = -EINVAL;
- else
- bus->idletime = int_val;
- break;
-
- case IOV_GVAL(IOV_IDLECLOCK):
- int_val = (s32) bus->idleclock;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_IDLECLOCK):
- bus->idleclock = int_val;
- break;
-
- case IOV_GVAL(IOV_SD1IDLE):
- int_val = (s32) sd1idle;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_SD1IDLE):
- sd1idle = bool_val;
- break;
-
- case IOV_SVAL(IOV_MEMBYTES):
- case IOV_GVAL(IOV_MEMBYTES):
- {
- u32 address;
- uint size, dsize;
- u8 *data;
-
- bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
-
- address = (u32) int_val;
- memcpy(&int_val, (char *)params + sizeof(int_val),
- sizeof(int_val));
- size = (uint) int_val;
-
- /* Do some validation */
- dsize = set ? plen - (2 * sizeof(int)) : len;
- if (dsize < size) {
- BRCMF_ERROR(("%s: error on %s membytes, addr "
- "0x%08x size %d dsize %d\n",
- __func__, (set ? "set" : "get"),
- address, size, dsize));
- bcmerror = -EINVAL;
- break;
- }
-
- BRCMF_INFO(("%s: Request to %s %d bytes at address "
- "0x%08x\n", __func__,
- (set ? "write" : "read"), size, address));
-
- /* If we know about SOCRAM, check for a fit */
- if ((bus->orig_ramsize) &&
- ((address > bus->orig_ramsize)
- || (address + size > bus->orig_ramsize))) {
- BRCMF_ERROR(("%s: ramsize 0x%08x doesn't have"
- " %d bytes at 0x%08x\n", __func__,
- bus->orig_ramsize, size, address));
- bcmerror = -EINVAL;
- break;
- }
-
- /* Generate the actual data pointer */
- data =
- set ? (u8 *) params +
- 2 * sizeof(int) : (u8 *) arg;
-
- /* Call to do the transfer */
- bcmerror = brcmf_sdbrcm_membytes(bus, set, address,
- data, size);
-
- break;
- }
-
- case IOV_GVAL(IOV_MEMSIZE):
- int_val = (s32) bus->ramsize;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_GVAL(IOV_SDIOD_DRIVE):
- int_val = (s32) brcmf_sdiod_drive_strength;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_SDIOD_DRIVE):
- brcmf_sdiod_drive_strength = int_val;
- brcmf_sdbrcm_sdiod_drive_strength_init(bus,
- brcmf_sdiod_drive_strength);
- break;
-
- case IOV_SVAL(IOV_DOWNLOAD):
- bcmerror = brcmf_sdbrcm_download_state(bus, bool_val);
- break;
-
- case IOV_SVAL(IOV_VARS):
- bcmerror = brcmf_sdbrcm_downloadvars(bus, arg, len);
- break;
-
- case IOV_GVAL(IOV_READAHEAD):
- int_val = (s32) brcmf_readahead;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_READAHEAD):
- if (bool_val && !brcmf_readahead)
- bus->nextlen = 0;
- brcmf_readahead = bool_val;
- break;
-
- case IOV_GVAL(IOV_SDRXCHAIN):
- int_val = (s32) bus->use_rxchain;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_SDRXCHAIN):
- if (bool_val && !bus->sd_rxchain)
- bcmerror = -ENOTSUPP;
- else
- bus->use_rxchain = bool_val;
- break;
- case IOV_GVAL(IOV_ALIGNCTL):
- int_val = (s32) brcmf_alignctl;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_ALIGNCTL):
- brcmf_alignctl = bool_val;
- break;
-
- case IOV_GVAL(IOV_SDALIGN):
- int_val = BRCMF_SDALIGN;
- memcpy(arg, &int_val, val_size);
- break;
-
-#ifdef BCMDBG
- case IOV_GVAL(IOV_VARS):
- if (bus->varsz < (uint) len)
- memcpy(arg, bus->vars, bus->varsz);
- else
- bcmerror = -EOVERFLOW;
- break;
-#endif /* BCMDBG */
-
-#ifdef BCMDBG
- case IOV_GVAL(IOV_DCONSOLE_POLL):
- int_val = (s32) brcmf_console_ms;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_DCONSOLE_POLL):
- brcmf_console_ms = (uint) int_val;
- break;
-
- case IOV_SVAL(IOV_CONS):
- if (len > 0)
- bcmerror = brcmf_sdbrcm_bus_console_in(bus->drvr,
- arg, len - 1);
- break;
-
- case IOV_GVAL(IOV_SDREG):
- {
- struct brcmf_sdreg *sd_ptr;
- u32 addr, size;
-
- sd_ptr = (struct brcmf_sdreg *) params;
-
- addr = bus->ci->buscorebase + sd_ptr->offset;
- size = sd_ptr->func;
- int_val = (s32) brcmf_sdcard_reg_read(bus->card, addr,
- size);
- if (brcmf_sdcard_regfail(bus->card))
- bcmerror = -EIO;
- memcpy(arg, &int_val, sizeof(s32));
- break;
- }
-
- case IOV_SVAL(IOV_SDREG):
- {
- struct brcmf_sdreg *sd_ptr;
- u32 addr, size;
-
- sd_ptr = (struct brcmf_sdreg *) params;
-
- addr = bus->ci->buscorebase + sd_ptr->offset;
- size = sd_ptr->func;
- brcmf_sdcard_reg_write(bus->card, addr, size,
- sd_ptr->value);
- if (brcmf_sdcard_regfail(bus->card))
- bcmerror = -EIO;
- break;
- }
-
- /* Same as above, but offset is not backplane
- (not SDIO core) */
- case IOV_GVAL(IOV_SBREG):
- {
- struct brcmf_sdreg sdreg;
- u32 addr, size;
-
- memcpy(&sdreg, params, sizeof(sdreg));
-
- addr = SI_ENUM_BASE + sdreg.offset;
- size = sdreg.func;
- int_val = (s32) brcmf_sdcard_reg_read(bus->card, addr,
- size);
- if (brcmf_sdcard_regfail(bus->card))
- bcmerror = -EIO;
- memcpy(arg, &int_val, sizeof(s32));
- break;
- }
-
- case IOV_SVAL(IOV_SBREG):
- {
- struct brcmf_sdreg sdreg;
- u32 addr, size;
-
- memcpy(&sdreg, params, sizeof(sdreg));
-
- addr = SI_ENUM_BASE + sdreg.offset;
- size = sdreg.func;
- brcmf_sdcard_reg_write(bus->card, addr, size,
- sdreg.value);
- if (brcmf_sdcard_regfail(bus->card))
- bcmerror = -EIO;
- break;
- }
-
- case IOV_GVAL(IOV_SDCIS):
- {
- *(char *)arg = 0;
-
- strcat(arg, "\nFunc 0\n");
- brcmf_sdcard_cis_read(bus->card, 0x10,
- (u8 *) arg + strlen(arg),
- SBSDIO_CIS_SIZE_LIMIT);
- strcat(arg, "\nFunc 1\n");
- brcmf_sdcard_cis_read(bus->card, 0x11,
- (u8 *) arg + strlen(arg),
- SBSDIO_CIS_SIZE_LIMIT);
- strcat(arg, "\nFunc 2\n");
- brcmf_sdcard_cis_read(bus->card, 0x12,
- (u8 *) arg + strlen(arg),
- SBSDIO_CIS_SIZE_LIMIT);
- break;
- }
-
- case IOV_GVAL(IOV_FORCEEVEN):
- int_val = (s32) forcealign;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_FORCEEVEN):
- forcealign = bool_val;
- break;
-
- case IOV_GVAL(IOV_TXBOUND):
- int_val = (s32) brcmf_txbound;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_TXBOUND):
- brcmf_txbound = (uint) int_val;
- break;
-
- case IOV_GVAL(IOV_RXBOUND):
- int_val = (s32) brcmf_rxbound;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_RXBOUND):
- brcmf_rxbound = (uint) int_val;
- break;
-
- case IOV_GVAL(IOV_TXMINMAX):
- int_val = (s32) brcmf_txminmax;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_TXMINMAX):
- brcmf_txminmax = (uint) int_val;
- break;
-#endif /* BCMDBG */
-
-#ifdef SDTEST
- case IOV_GVAL(IOV_EXTLOOP):
- int_val = (s32) bus->ext_loop;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_EXTLOOP):
- bus->ext_loop = bool_val;
- break;
-
- case IOV_GVAL(IOV_PKTGEN):
- bcmerror = brcmf_sdbrcm_pktgen_get(bus, arg);
- break;
-
- case IOV_SVAL(IOV_PKTGEN):
- bcmerror = brcmf_sdbrcm_pktgen_set(bus, arg);
- break;
-#endif /* SDTEST */
-
- case IOV_SVAL(IOV_DEVRESET):
- BRCMF_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d "
- "busstate=%d\n",
- __func__, bool_val, bus->drvr->dongle_reset,
- bus->drvr->busstate));
-
- brcmf_bus_devreset(bus->drvr, (u8) bool_val);
-
- break;
-
- case IOV_GVAL(IOV_DEVRESET):
- BRCMF_TRACE(("%s: Called get IOV_DEVRESET\n", __func__));
-
- /* Get its status */
- int_val = (bool) bus->drvr->dongle_reset;
- memcpy(arg, &int_val, val_size);
-
- break;
-
- case IOV_GVAL(IOV_WDTICK):
- int_val = (s32) brcmf_watchdog_ms;
- memcpy(arg, &int_val, val_size);
- break;
-
- case IOV_SVAL(IOV_WDTICK):
- if (!bus->drvr->up) {
- bcmerror = -ENOLINK;
- break;
- }
- brcmf_sdbrcm_wd_timer(bus, (uint) int_val);
- break;
-
- default:
- bcmerror = -ENOTSUPP;
- break;
- }
-
-exit:
- if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
- }
-
- brcmf_sdbrcm_sdunlock(bus);
-
- if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == false)
- brcmf_c_preinit_ioctls(bus->drvr);
-
- return bcmerror;
-}
-
-static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
-{
- int bcmerror = 0;
- u32 varsize;
- u32 varaddr;
- u8 *vbuffer;
- u32 varsizew;
-#ifdef BCMDBG
- char *nvram_ularray;
-#endif /* BCMDBG */
-
- /* Even if there are no vars are to be written, we still
- need to set the ramsize. */
- varsize = bus->varsz ? roundup(bus->varsz, 4) : 0;
- varaddr = (bus->ramsize - 4) - varsize;
-
- if (bus->vars) {
- vbuffer = kzalloc(varsize, GFP_ATOMIC);
- if (!vbuffer)
- return -ENOMEM;
-
- memcpy(vbuffer, bus->vars, bus->varsz);
-
- /* Write the vars list */
- bcmerror =
- brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize);
-#ifdef BCMDBG
- /* Verify NVRAM bytes */
- BRCMF_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
- nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
- if (!nvram_ularray)
- return -ENOMEM;
-
- /* Upload image to verify downloaded contents. */
- memset(nvram_ularray, 0xaa, varsize);
-
- /* Read the vars list to temp buffer for comparison */
- bcmerror =
- brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray,
- varsize);
- if (bcmerror) {
- BRCMF_ERROR(("%s: error %d on reading %d nvram bytes"
- " at 0x%08x\n", __func__, bcmerror,
- varsize, varaddr));
- }
- /* Compare the org NVRAM with the one read from RAM */
- if (memcmp(vbuffer, nvram_ularray, varsize)) {
- BRCMF_ERROR(("%s: Downloaded NVRAM image is "
- "corrupted.\n", __func__));
- } else
- BRCMF_ERROR(("%s: Download/Upload/Compare of"
- " NVRAM ok.\n", __func__));
-
- kfree(nvram_ularray);
-#endif /* BCMDBG */
-
- kfree(vbuffer);
- }
-
- /* adjust to the user specified RAM */
- BRCMF_INFO(("Physical memory size: %d, usable memory size: %d\n",
- bus->orig_ramsize, bus->ramsize));
- BRCMF_INFO(("Vars are at %d, orig varsize is %d\n", varaddr, varsize));
- varsize = ((bus->orig_ramsize - 4) - varaddr);
-
- /*
- * Determine the length token:
- * Varsize, converted to words, in lower 16-bits, checksum
- * in upper 16-bits.
- */
- if (bcmerror) {
- varsizew = 0;
- } else {
- varsizew = varsize / 4;
- varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
- varsizew = cpu_to_le32(varsizew);
- }
-
- BRCMF_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
- varsizew));
-
- /* Write the length token to the last word */
- bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->orig_ramsize - 4),
- (u8 *)&varsizew, 4);
-
- return bcmerror;
-}
-
-static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
-{
- uint retries;
- u32 regdata;
- int bcmerror = 0;
-
- /* To enter download state, disable ARM and reset SOCRAM.
- * To exit download state, simply reset ARM (default is RAM boot).
- */
- if (enter) {
- bus->alp_only = true;
-
- brcmf_sdbrcm_chip_disablecore(bus->card, bus->ci->armcorebase);
-
- brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->ramcorebase);
-
- /* Clear the top bit of memory */
- if (bus->ramsize) {
- u32 zeros = 0;
- brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
- (u8 *)&zeros, 4);
- }
- } else {
- regdata = brcmf_sdcard_reg_read(bus->card,
- CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4);
- regdata &= (SBTML_RESET | SBTML_REJ_MASK |
- (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
- if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) {
- BRCMF_ERROR(("%s: SOCRAM core is down after reset?\n",
- __func__));
- bcmerror = -EBADE;
- goto fail;
- }
-
- bcmerror = brcmf_sdbrcm_write_vars(bus);
- if (bcmerror) {
- BRCMF_ERROR(("%s: no vars written to RAM\n", __func__));
- bcmerror = 0;
- }
-
- w_sdreg32(bus, 0xFFFFFFFF,
- offsetof(struct sdpcmd_regs, intstatus), &retries);
-
- brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->armcorebase);
-
- /* Allow HT Clock now that the ARM is running. */
- bus->alp_only = false;
-
- bus->drvr->busstate = BRCMF_BUS_LOAD;
- }
-fail:
- return bcmerror;
-}
-
-int
-brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name,
- void *params, int plen, void *arg, int len, bool set)
-{
- struct brcmf_bus *bus = drvr->bus;
- const struct brcmu_iovar *vi = NULL;
- int bcmerror = 0;
- int val_size;
- u32 actionid;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (name == NULL || len <= 0)
- return -EINVAL;
-
- /* Set does not take qualifiers */
- if (set && (params || plen))
- return -EINVAL;
-
- /* Get must have return space;*/
- if (!set && !(arg && len))
- return -EINVAL;
-
- /* Look up var locally; if not found pass to host driver */
- vi = brcmu_iovar_lookup(brcmf_sdio_iovars, name);
- if (vi == NULL) {
- brcmf_sdbrcm_sdlock(bus);
-
- BUS_WAKE(bus);
-
- /* Turn on clock in case SD command needs backplane */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- bcmerror = brcmf_sdcard_iovar_op(bus->card, name, params, plen,
- arg, len, set);
-
- /* Similar check for blocksize change */
- if (set && strcmp(name, "sd_blocksize") == 0) {
- s32 fnum = 2;
- if (brcmf_sdcard_iovar_op
- (bus->card, "sd_blocksize", &fnum, sizeof(s32),
- &bus->blocksize, sizeof(s32),
- false) != 0) {
- bus->blocksize = 0;
- BRCMF_ERROR(("%s: fail on %s get\n", __func__,
- "sd_blocksize"));
- } else {
- BRCMF_INFO(("%s: noted sd_blocksize update,"
- " value now %d\n", __func__,
- bus->blocksize));
- }
- }
- bus->roundup = min(max_roundup, bus->blocksize);
-
- if (bus->idletime == BRCMF_IDLE_IMMEDIATE &&
- !bus->dpc_sched) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
- }
-
- brcmf_sdbrcm_sdunlock(bus);
- goto exit;
- }
-
- BRCMF_CTL(("%s: %s %s, len %d plen %d\n", __func__,
- name, (set ? "set" : "get"), len, plen));
-
- /* set up 'params' pointer in case this is a set command so that
- * the convenience int and bool code can be common to set and get
- */
- if (params == NULL) {
- params = arg;
- plen = len;
- }
-
- if (vi->type == IOVT_VOID)
- val_size = 0;
- else if (vi->type == IOVT_BUFFER)
- val_size = len;
- else
- /* all other types are integer sized */
- val_size = sizeof(int);
-
- actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
- bcmerror = brcmf_sdbrcm_doiovar(bus, vi, actionid, name, params, plen,
- arg, len, val_size);
-
-exit:
- return bcmerror;
-}
-
-void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex)
-{
- u32 local_hostintmask;
- u8 saveclk;
- uint retries;
- int err;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (enforce_mutex)
- brcmf_sdbrcm_sdlock(bus);
-
- BUS_WAKE(bus);
-
- /* Enable clock for device interrupts */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- if (bus->watchdog_tsk) {
- send_sig(SIGTERM, bus->watchdog_tsk, 1);
- kthread_stop(bus->watchdog_tsk);
- bus->watchdog_tsk = NULL;
- }
-
- if (bus->dpc_tsk) {
- send_sig(SIGTERM, bus->dpc_tsk, 1);
- kthread_stop(bus->dpc_tsk);
- bus->dpc_tsk = NULL;
- } else
- tasklet_kill(&bus->tasklet);
-
- /* Disable and clear interrupts at the chip level also */
- w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
- local_hostintmask = bus->hostintmask;
- bus->hostintmask = 0;
-
- /* Change our idea of bus state */
- bus->drvr->busstate = BRCMF_BUS_DOWN;
-
- /* Force clocks on backplane to be sure F2 interrupt propagates */
- saveclk = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (!err) {
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
- }
- if (err) {
- BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n",
- __func__, err));
- }
-
- /* Turn off the bus (F2), free any pending packets */
- BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
- brcmf_sdcard_intr_disable(bus->card);
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
- SDIO_FUNC_ENABLE_1, NULL);
-
- /* Clear any pending interrupts now that F2 is disabled */
- w_sdreg32(bus, local_hostintmask,
- offsetof(struct sdpcmd_regs, intstatus), &retries);
-
- /* Turn off the backplane clock (only) */
- brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
-
- /* Clear the data packet queues */
- brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
-
- /* Clear any held glomming stuff */
- if (bus->glomd)
- brcmu_pkt_buf_free_skb(bus->glomd);
-
- if (bus->glom)
- brcmu_pkt_buf_free_skb(bus->glom);
-
- bus->glom = bus->glomd = NULL;
-
- /* Clear rx control and wake any waiters */
- bus->rxlen = 0;
- brcmf_os_ioctl_resp_wake(bus->drvr);
-
- /* Reset some F2 state stuff */
- bus->rxskip = false;
- bus->tx_seq = bus->rx_seq = 0;
-
- if (enforce_mutex)
- brcmf_sdbrcm_sdunlock(bus);
-}
-
-int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex)
-{
- struct brcmf_bus *bus = drvr->bus;
- struct brcmf_timeout tmo;
- uint retries = 0;
- u8 ready, enable;
- int err, ret = 0;
- u8 saveclk;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* try to download image and nvram to the dongle */
- if (drvr->busstate == BRCMF_BUS_DOWN) {
- if (!(brcmf_sdbrcm_download_firmware(bus, bus->card)))
- return -1;
- }
-
- if (!bus->drvr)
- return 0;
-
- /* Start the watchdog timer */
- bus->drvr->tickcnt = 0;
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
-
- if (enforce_mutex)
- brcmf_sdbrcm_sdlock(bus);
-
- /* Make sure backplane clock is on, needed to generate F2 interrupt */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- if (bus->clkstate != CLK_AVAIL)
- goto exit;
-
- /* Force clocks on backplane to be sure F2 interrupt propagates */
- saveclk =
- brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (!err) {
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
- }
- if (err) {
- BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n",
- __func__, err));
- goto exit;
- }
-
- /* Enable function 2 (frame transfers) */
- w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
- offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries);
- enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
-
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx, enable,
- NULL);
-
- /* Give the dongle some time to do its thing and set IOR2 */
- brcmf_timeout_start(&tmo, BRCMF_WAIT_F2RDY * 1000);
-
- ready = 0;
- while (ready != enable && !brcmf_timeout_expired(&tmo))
- ready = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_0,
- SDIO_CCCR_IORx, NULL);
-
- BRCMF_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
- __func__, enable, ready, tmo.elapsed));
-
- /* If F2 successfully enabled, set core and enable interrupts */
- if (ready == enable) {
- /* Set up the interrupt mask and enable interrupts */
- bus->hostintmask = HOSTINTMASK;
- w_sdreg32(bus, bus->hostintmask,
- offsetof(struct sdpcmd_regs, hostintmask), &retries);
-
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_WATERMARK,
- (u8) watermark, &err);
-
- /* Set bus state according to enable result */
- drvr->busstate = BRCMF_BUS_DATA;
-
- bus->intdis = false;
- if (bus->intr) {
- BRCMF_INTR(("%s: enable SDIO device interrupts\n",
- __func__));
- brcmf_sdcard_intr_enable(bus->card);
- } else {
- BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
- brcmf_sdcard_intr_disable(bus->card);
- }
-
- }
-
- else {
- /* Disable F2 again */
- enable = SDIO_FUNC_ENABLE_1;
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
- enable, NULL);
- }
-
- /* Restore previous clock setting */
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- saveclk, &err);
-
-#if defined(OOB_INTR_ONLY)
- /* Host registration for OOB interrupt */
- if (brcmf_sdio_register_oob_intr(bus->dhd)) {
- brcmf_sdbrcm_wd_timer(bus, 0);
- BRCMF_ERROR(("%s Host failed to resgister for OOB\n",
- __func__));
- ret = -ENODEV;
- goto exit;
- }
-
- /* Enable oob at firmware */
- brcmf_sdbrcm_enable_oob_intr(bus, true);
-#endif /* defined(OOB_INTR_ONLY) */
-
- /* If we didn't come up, turn off backplane clock */
- if (drvr->busstate != BRCMF_BUS_DATA)
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
-
-exit:
- if (enforce_mutex)
- brcmf_sdbrcm_sdunlock(bus);
-
- return ret;
-}
-
-static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
-{
- struct brcmf_sdio_card *card = bus->card;
- uint retries = 0;
- u16 lastrbc;
- u8 hi, lo;
- int err;
-
- BRCMF_ERROR(("%s: %sterminate frame%s\n", __func__,
- (abort ? "abort command, " : ""),
- (rtx ? ", send NAK" : "")));
-
- if (abort)
- brcmf_sdcard_abort(card, SDIO_FUNC_2);
-
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
- SFC_RF_TERM, &err);
- bus->f1regdata++;
-
- /* Wait until the packet has been flushed (device/FIFO stable) */
- for (lastrbc = retries = 0xffff; retries > 0; retries--) {
- hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_RFRAMEBCHI, NULL);
- lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_RFRAMEBCLO, NULL);
- bus->f1regdata += 2;
-
- if ((hi == 0) && (lo == 0))
- break;
-
- if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
- BRCMF_ERROR(("%s: count growing: last 0x%04x now "
- "0x%04x\n",
- __func__, lastrbc, ((hi << 8) + lo)));
- }
- lastrbc = (hi << 8) + lo;
- }
-
- if (!retries) {
- BRCMF_ERROR(("%s: count never zeroed: last 0x%04x\n",
- __func__, lastrbc));
- } else {
- BRCMF_INFO(("%s: flush took %d iterations\n", __func__,
- (0xffff - retries)));
- }
-
- if (rtx) {
- bus->rxrtx++;
- w_sdreg32(bus, SMB_NAK,
- offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
-
- bus->f1regdata++;
- if (retries <= retry_limit)
- bus->rxskip = true;
- }
-
- /* Clear partial in any case */
- bus->nextlen = 0;
-
- /* If we can't reach the device, signal failure */
- if (err || brcmf_sdcard_regfail(card))
- bus->drvr->busstate = BRCMF_BUS_DOWN;
-}
-
-static void
-brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff)
-{
- struct brcmf_sdio_card *card = bus->card;
- uint rdlen, pad;
-
- int sdret;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* Control data already received in aligned rxctl */
- if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
- goto gotpkt;
-
- /* Set rxctl for frame (w/optional alignment) */
- bus->rxctl = bus->rxbuf;
- if (brcmf_alignctl) {
- bus->rxctl += firstread;
- pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN);
- if (pad)
- bus->rxctl += (BRCMF_SDALIGN - pad);
- bus->rxctl -= firstread;
- }
-
- /* Copy the already-read portion over */
- memcpy(bus->rxctl, hdr, firstread);
- if (len <= firstread)
- goto gotpkt;
-
- /* Copy the full data pkt in gSPI case and process ioctl. */
- if (bus->bus == SPI_BUS) {
- memcpy(bus->rxctl, hdr, len);
- goto gotpkt;
- }
-
- /* Raise rdlen to next SDIO block to avoid tail command */
- rdlen = len - firstread;
- if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
- pad = bus->blocksize - (rdlen % bus->blocksize);
- if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
- ((len + pad) < bus->drvr->maxctl))
- rdlen += pad;
- } else if (rdlen % BRCMF_SDALIGN) {
- rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
- }
-
- /* Satisfy length-alignment requirements */
- if (forcealign && (rdlen & (ALIGNMENT - 1)))
- rdlen = roundup(rdlen, ALIGNMENT);
-
- /* Drop if the read is too big or it exceeds our maximum */
- if ((rdlen + firstread) > bus->drvr->maxctl) {
- BRCMF_ERROR(("%s: %d-byte control read exceeds %d-byte"
- " buffer\n", __func__, rdlen, bus->drvr->maxctl));
- bus->drvr->rx_errors++;
- brcmf_sdbrcm_rxfail(bus, false, false);
- goto done;
- }
-
- if ((len - doff) > bus->drvr->maxctl) {
- BRCMF_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds "
- "%d-byte limit\n",
- __func__, len, (len - doff), bus->drvr->maxctl));
- bus->drvr->rx_errors++;
- bus->rx_toolong++;
- brcmf_sdbrcm_rxfail(bus, false, false);
- goto done;
- }
-
- /* Read remainder of frame body into the rxctl buffer */
- sdret = brcmf_sdcard_recv_buf(card, brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2,
- F2SYNC, (bus->rxctl + firstread), rdlen,
- NULL, NULL, NULL);
- bus->f2rxdata++;
-
- /* Control frame failures need retransmission */
- if (sdret < 0) {
- BRCMF_ERROR(("%s: read %d control bytes failed: %d\n",
- __func__, rdlen, sdret));
- bus->rxc_errors++;
- brcmf_sdbrcm_rxfail(bus, true, true);
- goto done;
- }
-
-gotpkt:
-
-#ifdef BCMDBG
- if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
- printk(KERN_DEBUG "RxCtrl:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len);
- }
-#endif
-
- /* Point to valid data and indicate its length */
- bus->rxctl += doff;
- bus->rxlen = len - doff;
-
-done:
- /* Awake any waiters */
- brcmf_os_ioctl_resp_wake(bus->drvr);
-}
-
-static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
-{
- u16 dlen, totlen;
- u8 *dptr, num = 0;
-
- u16 sublen, check;
- struct sk_buff *pfirst, *plast, *pnext, *save_pfirst;
-
- int errcode;
- u8 chan, seq, doff, sfdoff;
- u8 txmax;
-
- int ifidx = 0;
- bool usechain = bus->use_rxchain;
-
- /* If packets, issue read(s) and send up packet chain */
- /* Return sequence numbers consumed? */
-
- BRCMF_TRACE(("brcmf_sdbrcm_rxglom: start: glomd %p glom %p\n",
- bus->glomd, bus->glom));
-
- /* If there's a descriptor, generate the packet chain */
- if (bus->glomd) {
- pfirst = plast = pnext = NULL;
- dlen = (u16) (bus->glomd->len);
- dptr = bus->glomd->data;
- if (!dlen || (dlen & 1)) {
- BRCMF_ERROR(("%s: bad glomd len(%d),"
- " ignore descriptor\n",
- __func__, dlen));
- dlen = 0;
- }
-
- for (totlen = num = 0; dlen; num++) {
- /* Get (and move past) next length */
- sublen = get_unaligned_le16(dptr);
- dlen -= sizeof(u16);
- dptr += sizeof(u16);
- if ((sublen < SDPCM_HDRLEN) ||
- ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
- BRCMF_ERROR(("%s: descriptor len %d bad: %d\n",
- __func__, num, sublen));
- pnext = NULL;
- break;
- }
- if (sublen % BRCMF_SDALIGN) {
- BRCMF_ERROR(("%s: sublen %d not multiple of"
- " %d\n", __func__, sublen,
- BRCMF_SDALIGN));
- usechain = false;
- }
- totlen += sublen;
-
- /* For last frame, adjust read len so total
- is a block multiple */
- if (!dlen) {
- sublen +=
- (roundup(totlen, bus->blocksize) - totlen);
- totlen = roundup(totlen, bus->blocksize);
- }
-
- /* Allocate/chain packet for next subframe */
- pnext = brcmu_pkt_buf_get_skb(sublen + BRCMF_SDALIGN);
- if (pnext == NULL) {
- BRCMF_ERROR(("%s: bcm_pkt_buf_get_skb failed, "
- "num %d len %d\n", __func__,
- num, sublen));
- break;
- }
- if (!pfirst) {
- pfirst = plast = pnext;
- } else {
- plast->next = pnext;
- plast = pnext;
- }
-
- /* Adhere to start alignment requirements */
- PKTALIGN(pnext, sublen, BRCMF_SDALIGN);
- }
-
- /* If all allocations succeeded, save packet chain
- in bus structure */
- if (pnext) {
- BRCMF_GLOM(("%s: allocated %d-byte packet chain for %d "
- "subframes\n", __func__, totlen, num));
- if (BRCMF_GLOM_ON() && bus->nextlen) {
- if (totlen != bus->nextlen) {
- BRCMF_GLOM(("%s: glomdesc mismatch: "
- "nextlen %d glomdesc %d "
- "rxseq %d\n", __func__,
- bus->nextlen,
- totlen, rxseq));
- }
- }
- bus->glom = pfirst;
- pfirst = pnext = NULL;
- } else {
- if (pfirst)
- brcmu_pkt_buf_free_skb(pfirst);
- bus->glom = NULL;
- num = 0;
- }
-
- /* Done with descriptor packet */
- brcmu_pkt_buf_free_skb(bus->glomd);
- bus->glomd = NULL;
- bus->nextlen = 0;
- }
-
- /* Ok -- either we just generated a packet chain,
- or had one from before */
- if (bus->glom) {
- if (BRCMF_GLOM_ON()) {
- BRCMF_GLOM(("%s: try superframe read, packet chain:\n",
- __func__));
- for (pnext = bus->glom; pnext; pnext = pnext->next) {
- BRCMF_GLOM((" %p: %p len 0x%04x (%d)\n",
- pnext, (u8 *) (pnext->data),
- pnext->len, pnext->len));
- }
- }
-
- pfirst = bus->glom;
- dlen = (u16) brcmu_pkttotlen(pfirst);
-
- /* Do an SDIO read for the superframe. Configurable iovar to
- * read directly into the chained packet, or allocate a large
- * packet and and copy into the chain.
- */
- if (usechain) {
- errcode = brcmf_sdcard_recv_buf(bus->card,
- brcmf_sdcard_cur_sbwad(bus->card),
- SDIO_FUNC_2,
- F2SYNC, (u8 *) pfirst->data, dlen,
- pfirst, NULL, NULL);
- } else if (bus->dataptr) {
- errcode = brcmf_sdcard_recv_buf(bus->card,
- brcmf_sdcard_cur_sbwad(bus->card),
- SDIO_FUNC_2,
- F2SYNC, bus->dataptr, dlen,
- NULL, NULL, NULL);
- sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen,
- bus->dataptr);
- if (sublen != dlen) {
- BRCMF_ERROR(("%s: FAILED TO COPY, dlen %d "
- "sublen %d\n",
- __func__, dlen, sublen));
- errcode = -1;
- }
- pnext = NULL;
- } else {
- BRCMF_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, "
- "FORCE FAILURE\n", dlen));
- errcode = -1;
- }
- bus->f2rxdata++;
-
- /* On failure, kill the superframe, allow a couple retries */
- if (errcode < 0) {
- BRCMF_ERROR(("%s: glom read of %d bytes failed: %d\n",
- __func__, dlen, errcode));
- bus->drvr->rx_errors++;
-
- if (bus->glomerr++ < 3) {
- brcmf_sdbrcm_rxfail(bus, true, true);
- } else {
- bus->glomerr = 0;
- brcmf_sdbrcm_rxfail(bus, true, false);
- brcmu_pkt_buf_free_skb(bus->glom);
- bus->rxglomfail++;
- bus->glom = NULL;
- }
- return 0;
- }
-#ifdef BCMDBG
- if (BRCMF_GLOM_ON()) {
- printk(KERN_DEBUG "SUPERFRAME:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- pfirst->data, min_t(int, pfirst->len, 48));
- }
-#endif
-
- /* 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]);
- bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
- if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
- BRCMF_INFO(("%s: nextlen too large (%d) seq %d\n",
- __func__, bus->nextlen, seq));
- bus->nextlen = 0;
- }
- doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
- txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
-
- errcode = 0;
- if ((u16)~(sublen ^ check)) {
- BRCMF_ERROR(("%s (superframe): HW hdr error: len/check "
- "0x%04x/0x%04x\n", __func__, sublen,
- check));
- errcode = -1;
- } else if (roundup(sublen, bus->blocksize) != dlen) {
- BRCMF_ERROR(("%s (superframe): len 0x%04x, rounded "
- "0x%04x, expect 0x%04x\n",
- __func__, sublen,
- roundup(sublen, bus->blocksize), dlen));
- errcode = -1;
- } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) !=
- SDPCM_GLOM_CHANNEL) {
- BRCMF_ERROR(("%s (superframe): bad channel %d\n",
- __func__,
- SDPCM_PACKET_CHANNEL(&dptr
- [SDPCM_FRAMETAG_LEN])));
- errcode = -1;
- } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
- BRCMF_ERROR(("%s (superframe): got 2nd descriptor?\n",
- __func__));
- errcode = -1;
- } else if ((doff < SDPCM_HDRLEN) ||
- (doff > (pfirst->len - SDPCM_HDRLEN))) {
- BRCMF_ERROR(("%s (superframe): Bad data offset %d: "
- "HW %d pkt %d min %d\n",
- __func__, doff, sublen,
- pfirst->len, SDPCM_HDRLEN));
- errcode = -1;
- }
-
- /* Check sequence number of superframe SW header */
- if (rxseq != seq) {
- BRCMF_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
- __func__, seq, rxseq));
- bus->rx_badseq++;
- rxseq = seq;
- }
-
- /* Check window for sanity */
- if ((u8) (txmax - bus->tx_seq) > 0x40) {
- BRCMF_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
- __func__, txmax, bus->tx_seq));
- txmax = bus->tx_seq + 2;
- }
- bus->tx_max = txmax;
-
- /* Remove superframe header, remember offset */
- skb_pull(pfirst, doff);
- sfdoff = doff;
-
- /* Validate all the subframe headers */
- for (num = 0, pnext = pfirst; pnext && !errcode;
- num++, pnext = pnext->next) {
- 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]);
-#ifdef BCMDBG
- if (BRCMF_GLOM_ON()) {
- printk(KERN_DEBUG "subframe:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- dptr, 32);
- }
-#endif
-
- if ((u16)~(sublen ^ check)) {
- BRCMF_ERROR(("%s (subframe %d): HW hdr error: "
- "len/check 0x%04x/0x%04x\n",
- __func__, num, sublen, check));
- errcode = -1;
- } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
- BRCMF_ERROR(("%s (subframe %d): length mismatch"
- ": len 0x%04x, expect 0x%04x\n",
- __func__, num, sublen, dlen));
- errcode = -1;
- } else if ((chan != SDPCM_DATA_CHANNEL) &&
- (chan != SDPCM_EVENT_CHANNEL)) {
- BRCMF_ERROR(("%s (subframe %d): bad channel"
- " %d\n", __func__, num, chan));
- errcode = -1;
- } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
- BRCMF_ERROR(("%s (subframe %d): Bad data offset"
- " %d: HW %d min %d\n",
- __func__, num, doff, sublen,
- SDPCM_HDRLEN));
- errcode = -1;
- }
- }
-
- if (errcode) {
- /* Terminate frame on error, request
- a couple retries */
- if (bus->glomerr++ < 3) {
- /* Restore superframe header space */
- skb_push(pfirst, sfdoff);
- brcmf_sdbrcm_rxfail(bus, true, true);
- } else {
- bus->glomerr = 0;
- brcmf_sdbrcm_rxfail(bus, true, false);
- brcmu_pkt_buf_free_skb(bus->glom);
- bus->rxglomfail++;
- bus->glom = NULL;
- }
- bus->nextlen = 0;
- return 0;
- }
-
- /* Basic SD framing looks ok - process each packet (header) */
- save_pfirst = pfirst;
- bus->glom = NULL;
- plast = NULL;
-
- for (num = 0; pfirst; rxseq++, pfirst = pnext) {
- pnext = pfirst->next;
- pfirst->next = NULL;
-
- 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_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d "
- "chan %d seq %d\n",
- __func__, num, pfirst, pfirst->data,
- pfirst->len, sublen, chan, seq));
-
- /* precondition: chan == SDPCM_DATA_CHANNEL ||
- chan == SDPCM_EVENT_CHANNEL */
-
- if (rxseq != seq) {
- BRCMF_GLOM(("%s: rx_seq %d, expected %d\n",
- __func__, seq, rxseq));
- bus->rx_badseq++;
- rxseq = seq;
- }
-#ifdef BCMDBG
- if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
- printk(KERN_DEBUG "Rx Subframe Data:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- dptr, dlen);
- }
-#endif
-
- __skb_trim(pfirst, sublen);
- skb_pull(pfirst, doff);
-
- if (pfirst->len == 0) {
- brcmu_pkt_buf_free_skb(pfirst);
- if (plast) {
- plast->next = pnext;
- } else {
- save_pfirst = pnext;
- }
- continue;
- } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pfirst)
- != 0) {
- BRCMF_ERROR(("%s: rx protocol error\n",
- __func__));
- bus->drvr->rx_errors++;
- brcmu_pkt_buf_free_skb(pfirst);
- if (plast) {
- plast->next = pnext;
- } else {
- save_pfirst = pnext;
- }
- continue;
- }
-
- /* this packet will go up, link back into
- chain and count it */
- pfirst->next = pnext;
- plast = pfirst;
- num++;
-
-#ifdef BCMDBG
- if (BRCMF_GLOM_ON()) {
- BRCMF_GLOM(("%s subframe %d to stack, %p"
- "(%p/%d) nxt/lnk %p/%p\n",
- __func__, num, pfirst, pfirst->data,
- pfirst->len, pfirst->next,
- pfirst->prev));
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- pfirst->data,
- min_t(int, pfirst->len, 32));
- }
-#endif /* BCMDBG */
- }
- if (num) {
- brcmf_sdbrcm_sdunlock(bus);
- brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num);
- brcmf_sdbrcm_sdlock(bus);
- }
-
- bus->rxglomframes++;
- bus->rxglompkts += num;
- }
- return num;
-}
-
-/* Return true if there may be more frames to read */
-static uint
-brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
-{
- struct brcmf_sdio_card *card = bus->card;
-
- u16 len, check; /* Extracted hardware header fields */
- u8 chan, seq, doff; /* Extracted software header fields */
- u8 fcbits; /* Extracted fcbits from software header */
-
- struct sk_buff *pkt; /* Packet for event or data frames */
- u16 pad; /* Number of pad bytes to read */
- u16 rdlen; /* Total number of bytes to read */
- u8 rxseq; /* Next sequence number to expect */
- uint rxleft = 0; /* Remaining number of frames allowed */
- int sdret; /* Return code from calls */
- u8 txmax; /* Maximum tx sequence offered */
- bool len_consistent; /* Result of comparing readahead len and
- len from hw-hdr */
- u8 *rxbuf;
- int ifidx = 0;
- uint rxcount = 0; /* Total frames read */
-
-#if defined(BCMDBG) || defined(SDTEST)
- bool sdtest = false; /* To limit message spew from test mode */
-#endif
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
-#ifdef SDTEST
- /* Allow pktgen to override maxframes */
- if (bus->pktgen_count && (bus->pktgen_mode == BRCMF_PKTGEN_RECV)) {
- maxframes = bus->pktgen_count;
- sdtest = true;
- }
-#endif
-
- /* Not finished unless we encounter no more frames indication */
- *finished = false;
-
- for (rxseq = bus->rx_seq, rxleft = maxframes;
- !bus->rxskip && rxleft && bus->drvr->busstate != BRCMF_BUS_DOWN;
- rxseq++, rxleft--) {
-
- /* Handle glomming separately */
- if (bus->glom || bus->glomd) {
- u8 cnt;
- BRCMF_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
- __func__, bus->glomd, bus->glom));
- cnt = brcmf_sdbrcm_rxglom(bus, rxseq);
- BRCMF_GLOM(("%s: rxglom returned %d\n", __func__, cnt));
- rxseq += cnt - 1;
- rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
- continue;
- }
-
- /* Try doing single read if we can */
- if (brcmf_readahead && bus->nextlen) {
- u16 nextlen = bus->nextlen;
- bus->nextlen = 0;
-
- if (bus->bus == SPI_BUS) {
- rdlen = len = nextlen;
- } else {
- rdlen = len = nextlen << 4;
-
- /* Pad read to blocksize for efficiency */
- if (bus->roundup && bus->blocksize
- && (rdlen > bus->blocksize)) {
- pad =
- bus->blocksize -
- (rdlen % bus->blocksize);
- if ((pad <= bus->roundup)
- && (pad < bus->blocksize)
- && ((rdlen + pad + firstread) <
- MAX_RX_DATASZ))
- rdlen += pad;
- } else if (rdlen % BRCMF_SDALIGN) {
- rdlen +=
- BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
- }
- }
-
- /* We use bus->rxctl buffer in WinXP for initial
- * control pkt receives.
- * Later we use buffer-poll for data as well
- * as control packets.
- * This is required because dhd receives full
- * frame in gSPI unlike SDIO.
- * After the frame is received we have to
- * distinguish whether it is data
- * or non-data frame.
- */
- /* Allocate a packet buffer */
- pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN);
- if (!pkt) {
- if (bus->bus == SPI_BUS) {
- bus->usebufpool = false;
- bus->rxctl = bus->rxbuf;
- if (brcmf_alignctl) {
- bus->rxctl += firstread;
- pad = ((unsigned long)bus->rxctl %
- BRCMF_SDALIGN);
- if (pad)
- bus->rxctl +=
- (BRCMF_SDALIGN - pad);
- bus->rxctl -= firstread;
- }
- rxbuf = bus->rxctl;
- /* Read the entire frame */
- sdret = brcmf_sdcard_recv_buf(card,
- brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2, F2SYNC,
- rxbuf, rdlen,
- NULL, NULL, NULL);
- bus->f2rxdata++;
-
- /* Control frame failures need
- retransmission */
- if (sdret < 0) {
- BRCMF_ERROR(("%s: read %d "
- "control bytes "
- "failed: %d\n",
- __func__,
- rdlen, sdret));
- /* dhd.rx_ctlerrs is higher */
- bus->rxc_errors++;
- brcmf_sdbrcm_rxfail(bus, true,
- (bus->bus ==
- SPI_BUS) ? false
- : true);
- continue;
- }
- } else {
- /* Give up on data,
- request rtx of events */
- BRCMF_ERROR(("%s (nextlen): "
- "brcmu_pkt_buf_get_skb "
- "failed:"
- " len %d rdlen %d expected"
- " rxseq %d\n", __func__,
- len, rdlen, rxseq));
- continue;
- }
- } else {
- if (bus->bus == SPI_BUS)
- bus->usebufpool = true;
-
- PKTALIGN(pkt, rdlen, BRCMF_SDALIGN);
- rxbuf = (u8 *) (pkt->data);
- /* Read the entire frame */
- sdret = brcmf_sdcard_recv_buf(card,
- brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2, F2SYNC,
- rxbuf, rdlen,
- pkt, NULL, NULL);
- bus->f2rxdata++;
-
- if (sdret < 0) {
- BRCMF_ERROR(("%s (nextlen): read %d"
- " bytes failed: %d\n",
- __func__, rdlen, sdret));
- brcmu_pkt_buf_free_skb(pkt);
- bus->drvr->rx_errors++;
- /* Force retry w/normal header read.
- * Don't attempt NAK for
- * gSPI
- */
- brcmf_sdbrcm_rxfail(bus, true,
- (bus->bus ==
- SPI_BUS) ? false :
- true);
- continue;
- }
- }
-
- /* Now check the header */
- memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
-
- /* Extract hardware header fields */
- len = get_unaligned_le16(bus->rxhdr);
- check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
-
- /* All zeros means readahead info was bad */
- if (!(len | check)) {
- BRCMF_INFO(("%s (nextlen): read zeros in HW "
- "header???\n", __func__));
- brcmf_sdbrcm_pktfree2(bus, pkt);
- continue;
- }
-
- /* Validate check bytes */
- if ((u16)~(len ^ check)) {
- BRCMF_ERROR(("%s (nextlen): HW hdr error:"
- " nextlen/len/check"
- " 0x%04x/0x%04x/0x%04x\n",
- __func__, nextlen, len, check));
- bus->rx_badhdr++;
- brcmf_sdbrcm_rxfail(bus, false, false);
- brcmf_sdbrcm_pktfree2(bus, pkt);
- continue;
- }
-
- /* Validate frame length */
- if (len < SDPCM_HDRLEN) {
- BRCMF_ERROR(("%s (nextlen): HW hdr length "
- "invalid: %d\n", __func__, len));
- brcmf_sdbrcm_pktfree2(bus, pkt);
- continue;
- }
-
- /* Check for consistency withreadahead info */
- len_consistent = (nextlen != (roundup(len, 16) >> 4));
- if (len_consistent) {
- /* Mismatch, force retry w/normal
- header (may be >4K) */
- BRCMF_ERROR(("%s (nextlen): mismatch, "
- "nextlen %d len %d rnd %d; "
- "expected rxseq %d\n",
- __func__, nextlen,
- len, roundup(len, 16), rxseq));
- brcmf_sdbrcm_rxfail(bus, true,
- bus->bus != SPI_BUS);
- brcmf_sdbrcm_pktfree2(bus, pkt);
- continue;
- }
-
- /* Extract software header fields */
- chan = SDPCM_PACKET_CHANNEL(
- &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
- seq = SDPCM_PACKET_SEQUENCE(
- &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
- doff = SDPCM_DOFFSET_VALUE(
- &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
- txmax = SDPCM_WINDOW_VALUE(
- &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-
- bus->nextlen =
- bus->rxhdr[SDPCM_FRAMETAG_LEN +
- SDPCM_NEXTLEN_OFFSET];
- if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
- BRCMF_INFO(("%s (nextlen): got frame w/nextlen"
- " too large (%d), seq %d\n",
- __func__, bus->nextlen, seq));
- bus->nextlen = 0;
- }
-
- bus->drvr->rx_readahead_cnt++;
-
- /* Handle Flow Control */
- fcbits = SDPCM_FCMASK_VALUE(
- &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-
- if (bus->flowcontrol != fcbits) {
- if (~bus->flowcontrol & fcbits)
- bus->fc_xoff++;
-
- if (bus->flowcontrol & ~fcbits)
- bus->fc_xon++;
-
- bus->fc_rcvd++;
- bus->flowcontrol = fcbits;
- }
-
- /* Check and update sequence number */
- if (rxseq != seq) {
- BRCMF_INFO(("%s (nextlen): rx_seq %d, expected "
- "%d\n", __func__, seq, rxseq));
- bus->rx_badseq++;
- rxseq = seq;
- }
-
- /* Check window for sanity */
- if ((u8) (txmax - bus->tx_seq) > 0x40) {
- BRCMF_ERROR(("%s: got unlikely tx max %d with "
- "tx_seq %d\n",
- __func__, txmax, bus->tx_seq));
- txmax = bus->tx_seq + 2;
- }
- bus->tx_max = txmax;
-
-#ifdef BCMDBG
- if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
- printk(KERN_DEBUG "Rx Data:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- rxbuf, len);
- } else if (BRCMF_HDRS_ON()) {
- printk(KERN_DEBUG "RxHdr:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- bus->rxhdr, SDPCM_HDRLEN);
- }
-#endif
-
- if (chan == SDPCM_CONTROL_CHANNEL) {
- if (bus->bus == SPI_BUS) {
- brcmf_sdbrcm_read_control(bus, rxbuf,
- len, doff);
- } else {
- BRCMF_ERROR(("%s (nextlen): readahead"
- " on control packet %d?\n",
- __func__, seq));
- /* Force retry w/normal header read */
- bus->nextlen = 0;
- brcmf_sdbrcm_rxfail(bus, false, true);
- }
- brcmf_sdbrcm_pktfree2(bus, pkt);
- continue;
- }
-
- if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
- BRCMF_ERROR(("Received %d bytes on %d channel."
- " Running out of " "rx pktbuf's or"
- " not yet malloced.\n",
- len, chan));
- continue;
- }
-
- /* Validate data offset */
- if ((doff < SDPCM_HDRLEN) || (doff > len)) {
- BRCMF_ERROR(("%s (nextlen): bad data offset %d:"
- " HW len %d min %d\n", __func__,
- doff, len, SDPCM_HDRLEN));
- brcmf_sdbrcm_rxfail(bus, false, false);
- brcmf_sdbrcm_pktfree2(bus, pkt);
- continue;
- }
-
- /* All done with this one -- now deliver the packet */
- goto deliver;
- }
- /* gSPI frames should not be handled in fractions */
- if (bus->bus == SPI_BUS)
- break;
-
- /* Read frame header (hardware and software) */
- sdret = brcmf_sdcard_recv_buf(card,
- brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2, F2SYNC, bus->rxhdr, firstread,
- NULL, NULL, NULL);
- bus->f2rxhdrs++;
-
- if (sdret < 0) {
- BRCMF_ERROR(("%s: RXHEADER FAILED: %d\n", __func__,
- sdret));
- bus->rx_hdrfail++;
- brcmf_sdbrcm_rxfail(bus, true, true);
- continue;
- }
-#ifdef BCMDBG
- if (BRCMF_BYTES_ON() || BRCMF_HDRS_ON()) {
- printk(KERN_DEBUG "RxHdr:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- bus->rxhdr, SDPCM_HDRLEN);
- }
-#endif
-
- /* Extract hardware header fields */
- len = get_unaligned_le16(bus->rxhdr);
- check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
-
- /* All zeros means no more frames */
- if (!(len | check)) {
- *finished = true;
- break;
- }
-
- /* Validate check bytes */
- if ((u16) ~(len ^ check)) {
- BRCMF_ERROR(("%s: HW hdr err: len/check "
- "0x%04x/0x%04x\n", __func__, len, check));
- bus->rx_badhdr++;
- brcmf_sdbrcm_rxfail(bus, false, false);
- continue;
- }
-
- /* Validate frame length */
- if (len < SDPCM_HDRLEN) {
- BRCMF_ERROR(("%s: HW hdr length invalid: %d\n",
- __func__, len));
- continue;
- }
-
- /* Extract software header fields */
- chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
- seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
- doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
- txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-
- /* Validate data offset */
- if ((doff < SDPCM_HDRLEN) || (doff > len)) {
- BRCMF_ERROR(("%s: Bad data offset %d: HW len %d,"
- " min %d seq %d\n", __func__, doff,
- len, SDPCM_HDRLEN, seq));
- bus->rx_badhdr++;
- brcmf_sdbrcm_rxfail(bus, false, false);
- continue;
- }
-
- /* Save the readahead length if there is one */
- bus->nextlen =
- bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
- if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
- BRCMF_INFO(("%s (nextlen): got frame w/nextlen too"
- " large (%d), seq %d\n",
- __func__, bus->nextlen, seq));
- bus->nextlen = 0;
- }
-
- /* Handle Flow Control */
- fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
-
- if (bus->flowcontrol != fcbits) {
- if (~bus->flowcontrol & fcbits)
- bus->fc_xoff++;
-
- if (bus->flowcontrol & ~fcbits)
- bus->fc_xon++;
-
- bus->fc_rcvd++;
- bus->flowcontrol = fcbits;
- }
-
- /* Check and update sequence number */
- if (rxseq != seq) {
- BRCMF_INFO(("%s: rx_seq %d, expected %d\n", __func__,
- seq, rxseq));
- bus->rx_badseq++;
- rxseq = seq;
- }
-
- /* Check window for sanity */
- if ((u8) (txmax - bus->tx_seq) > 0x40) {
- BRCMF_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
- __func__, txmax, bus->tx_seq));
- txmax = bus->tx_seq + 2;
- }
- bus->tx_max = txmax;
-
- /* Call a separate function for control frames */
- if (chan == SDPCM_CONTROL_CHANNEL) {
- brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff);
- continue;
- }
-
- /* precondition: chan is either SDPCM_DATA_CHANNEL,
- SDPCM_EVENT_CHANNEL, SDPCM_TEST_CHANNEL or
- SDPCM_GLOM_CHANNEL */
-
- /* Length to read */
- rdlen = (len > firstread) ? (len - firstread) : 0;
-
- /* May pad read to blocksize for efficiency */
- if (bus->roundup && bus->blocksize &&
- (rdlen > bus->blocksize)) {
- pad = bus->blocksize - (rdlen % bus->blocksize);
- if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
- ((rdlen + pad + firstread) < MAX_RX_DATASZ))
- rdlen += pad;
- } else if (rdlen % BRCMF_SDALIGN) {
- rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
- }
-
- /* Satisfy length-alignment requirements */
- if (forcealign && (rdlen & (ALIGNMENT - 1)))
- rdlen = roundup(rdlen, ALIGNMENT);
-
- if ((rdlen + firstread) > MAX_RX_DATASZ) {
- /* Too long -- skip this frame */
- BRCMF_ERROR(("%s: too long: len %d rdlen %d\n",
- __func__, len, rdlen));
- bus->drvr->rx_errors++;
- bus->rx_toolong++;
- brcmf_sdbrcm_rxfail(bus, false, false);
- continue;
- }
-
- pkt = brcmu_pkt_buf_get_skb(rdlen + firstread + BRCMF_SDALIGN);
- if (!pkt) {
- /* Give up on data, request rtx of events */
- BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed:"
- " rdlen %d chan %d\n", __func__, rdlen,
- chan));
- bus->drvr->rx_dropped++;
- brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan));
- continue;
- }
-
- /* Leave room for what we already read, and align remainder */
- skb_pull(pkt, firstread);
- PKTALIGN(pkt, rdlen, BRCMF_SDALIGN);
-
- /* Read the remaining frame data */
- sdret = brcmf_sdcard_recv_buf(card,
- brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)),
- rdlen, pkt, NULL, NULL);
- bus->f2rxdata++;
-
- if (sdret < 0) {
- BRCMF_ERROR(("%s: read %d %s bytes failed: %d\n",
- __func__, rdlen,
- ((chan == SDPCM_EVENT_CHANNEL) ? "event"
- : ((chan == SDPCM_DATA_CHANNEL) ? "data"
- : "test")), sdret));
- brcmu_pkt_buf_free_skb(pkt);
- bus->drvr->rx_errors++;
- brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan));
- continue;
- }
-
- /* Copy the already-read portion */
- skb_push(pkt, firstread);
- memcpy(pkt->data, bus->rxhdr, firstread);
-
-#ifdef BCMDBG
- if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
- printk(KERN_DEBUG "Rx Data:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- pkt->data, len);
- }
-#endif
-
-deliver:
- /* Save superframe descriptor and allocate packet frame */
- if (chan == SDPCM_GLOM_CHANNEL) {
- if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
- BRCMF_GLOM(("%s: glom descriptor, %d bytes:\n",
- __func__, len));
-#ifdef BCMDBG
- if (BRCMF_GLOM_ON()) {
- printk(KERN_DEBUG "Glom Data:\n");
- print_hex_dump_bytes("",
- DUMP_PREFIX_OFFSET,
- pkt->data, len);
- }
-#endif
- __skb_trim(pkt, len);
- skb_pull(pkt, SDPCM_HDRLEN);
- bus->glomd = pkt;
- } else {
- BRCMF_ERROR(("%s: glom superframe w/o "
- "descriptor!\n", __func__));
- brcmf_sdbrcm_rxfail(bus, false, false);
- }
- continue;
- }
-
- /* Fill in packet len and prio, deliver upward */
- __skb_trim(pkt, len);
- skb_pull(pkt, doff);
-
-#ifdef SDTEST
- /* Test channel packets are processed separately */
- if (chan == SDPCM_TEST_CHANNEL) {
- brcmf_sdbrcm_checkdied(bus, pkt, seq);
- continue;
- }
-#endif /* SDTEST */
-
- if (pkt->len == 0) {
- brcmu_pkt_buf_free_skb(pkt);
- continue;
- } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pkt) != 0) {
- BRCMF_ERROR(("%s: rx protocol error\n", __func__));
- brcmu_pkt_buf_free_skb(pkt);
- bus->drvr->rx_errors++;
- continue;
- }
-
- /* Unlock during rx call */
- brcmf_sdbrcm_sdunlock(bus);
- brcmf_rx_frame(bus->drvr, ifidx, pkt, 1);
- brcmf_sdbrcm_sdlock(bus);
- }
- rxcount = maxframes - rxleft;
-#ifdef BCMDBG
- /* Message if we hit the limit */
- if (!rxleft && !sdtest)
- BRCMF_DATA(("%s: hit rx limit of %d frames\n", __func__,
- maxframes));
- else
-#endif /* BCMDBG */
- BRCMF_DATA(("%s: processed %d frames\n", __func__, rxcount));
- /* Back off rxseq if awaiting rtx, update rx_seq */
- if (bus->rxskip)
- rxseq--;
- bus->rx_seq = rxseq;
-
- return rxcount;
-}
-
-static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus)
-{
- u32 intstatus = 0;
- u32 hmb_data;
- u8 fcbits;
- uint retries = 0;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* Read mailbox data and ack that we did so */
- r_sdreg32(bus, &hmb_data,
- offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries);
-
- if (retries <= retry_limit)
- w_sdreg32(bus, SMB_INT_ACK,
- offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
- bus->f1regdata += 2;
-
- /* Dongle recomposed rx frames, accept them again */
- if (hmb_data & HMB_DATA_NAKHANDLED) {
- BRCMF_INFO(("Dongle reports NAK handled, expect rtx of %d\n",
- bus->rx_seq));
- if (!bus->rxskip)
- BRCMF_ERROR(("%s: unexpected NAKHANDLED!\n", __func__));
-
- bus->rxskip = false;
- intstatus |= I_HMB_FRAME_IND;
- }
-
- /*
- * DEVREADY does not occur with gSPI.
- */
- if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
- bus->sdpcm_ver =
- (hmb_data & HMB_DATA_VERSION_MASK) >>
- HMB_DATA_VERSION_SHIFT;
- if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
- BRCMF_ERROR(("Version mismatch, dongle reports %d, "
- "expecting %d\n",
- bus->sdpcm_ver, SDPCM_PROT_VERSION));
- else
- BRCMF_INFO(("Dongle ready, protocol version %d\n",
- bus->sdpcm_ver));
- }
-
- /*
- * Flow Control has been moved into the RX headers and this out of band
- * method isn't used any more.
- * remaining backward compatible with older dongles.
- */
- if (hmb_data & HMB_DATA_FC) {
- fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >>
- HMB_DATA_FCDATA_SHIFT;
-
- if (fcbits & ~bus->flowcontrol)
- bus->fc_xoff++;
-
- if (bus->flowcontrol & ~fcbits)
- bus->fc_xon++;
-
- bus->fc_rcvd++;
- bus->flowcontrol = fcbits;
- }
-
- /* Shouldn't be any others */
- if (hmb_data & ~(HMB_DATA_DEVREADY |
- HMB_DATA_NAKHANDLED |
- HMB_DATA_FC |
- HMB_DATA_FWREADY |
- HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) {
- BRCMF_ERROR(("Unknown mailbox data content: 0x%02x\n",
- hmb_data));
- }
-
- return intstatus;
-}
-
-static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
-{
- struct brcmf_sdio_card *card = bus->card;
- u32 intstatus, newstatus = 0;
- uint retries = 0;
- uint rxlimit = brcmf_rxbound; /* Rx frames to read before resched */
- uint txlimit = brcmf_txbound; /* Tx frames to send before resched */
- uint framecnt = 0; /* Temporary counter of tx/rx frames */
- bool rxdone = true; /* Flag for no more read data */
- bool resched = false; /* Flag indicating resched wanted */
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* Start with leftover status bits */
- intstatus = bus->intstatus;
-
- brcmf_sdbrcm_sdlock(bus);
-
- /* If waiting for HTAVAIL, check status */
- if (bus->clkstate == CLK_PENDING) {
- int err;
- u8 clkctl, devctl = 0;
-
-#ifdef BCMDBG
- /* Check for inconsistent device control */
- devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL, &err);
- if (err) {
- BRCMF_ERROR(("%s: error reading DEVCTL: %d\n",
- __func__, err));
- bus->drvr->busstate = BRCMF_BUS_DOWN;
- }
-#endif /* BCMDBG */
-
- /* Read CSR, if clock on switch to AVAIL, else ignore */
- clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (err) {
- BRCMF_ERROR(("%s: error reading CSR: %d\n", __func__,
- err));
- bus->drvr->busstate = BRCMF_BUS_DOWN;
- }
-
- BRCMF_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
- devctl, clkctl));
-
- if (SBSDIO_HTAV(clkctl)) {
- devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL, &err);
- if (err) {
- BRCMF_ERROR(("%s: error reading DEVCTL: %d\n",
- __func__, err));
- bus->drvr->busstate = BRCMF_BUS_DOWN;
- }
- devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_DEVICE_CTL, devctl, &err);
- if (err) {
- BRCMF_ERROR(("%s: error writing DEVCTL: %d\n",
- __func__, err));
- bus->drvr->busstate = BRCMF_BUS_DOWN;
- }
- bus->clkstate = CLK_AVAIL;
- } else {
- goto clkwait;
- }
- }
-
- BUS_WAKE(bus);
-
- /* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
- if (bus->clkstate == CLK_PENDING)
- goto clkwait;
-
- /* Pending interrupt indicates new device status */
- if (bus->ipend) {
- bus->ipend = false;
- r_sdreg32(bus, &newstatus,
- offsetof(struct sdpcmd_regs, intstatus), &retries);
- bus->f1regdata++;
- if (brcmf_sdcard_regfail(bus->card))
- newstatus = 0;
- newstatus &= bus->hostintmask;
- bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
- if (newstatus) {
- w_sdreg32(bus, newstatus,
- offsetof(struct sdpcmd_regs, intstatus),
- &retries);
- bus->f1regdata++;
- }
- }
-
- /* Merge new bits with previous */
- intstatus |= newstatus;
- bus->intstatus = 0;
-
- /* Handle flow-control change: read new state in case our ack
- * crossed another change interrupt. If change still set, assume
- * FC ON for safety, let next loop through do the debounce.
- */
- if (intstatus & I_HMB_FC_CHANGE) {
- intstatus &= ~I_HMB_FC_CHANGE;
- w_sdreg32(bus, I_HMB_FC_CHANGE,
- offsetof(struct sdpcmd_regs, intstatus), &retries);
-
- r_sdreg32(bus, &newstatus,
- offsetof(struct sdpcmd_regs, intstatus), &retries);
- bus->f1regdata += 2;
- bus->fcstate =
- !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
- intstatus |= (newstatus & bus->hostintmask);
- }
-
- /* Handle host mailbox indication */
- if (intstatus & I_HMB_HOST_INT) {
- intstatus &= ~I_HMB_HOST_INT;
- intstatus |= brcmf_sdbrcm_hostmail(bus);
- }
-
- /* Generally don't ask for these, can get CRC errors... */
- if (intstatus & I_WR_OOSYNC) {
- BRCMF_ERROR(("Dongle reports WR_OOSYNC\n"));
- intstatus &= ~I_WR_OOSYNC;
- }
-
- if (intstatus & I_RD_OOSYNC) {
- BRCMF_ERROR(("Dongle reports RD_OOSYNC\n"));
- intstatus &= ~I_RD_OOSYNC;
- }
-
- if (intstatus & I_SBINT) {
- BRCMF_ERROR(("Dongle reports SBINT\n"));
- intstatus &= ~I_SBINT;
- }
-
- /* Would be active due to wake-wlan in gSPI */
- if (intstatus & I_CHIPACTIVE) {
- BRCMF_INFO(("Dongle reports CHIPACTIVE\n"));
- intstatus &= ~I_CHIPACTIVE;
- }
-
- /* Ignore frame indications if rxskip is set */
- if (bus->rxskip)
- intstatus &= ~I_HMB_FRAME_IND;
-
- /* On frame indication, read available frames */
- if (PKT_AVAILABLE()) {
- framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone);
- if (rxdone || bus->rxskip)
- intstatus &= ~I_HMB_FRAME_IND;
- rxlimit -= min(framecnt, rxlimit);
- }
-
- /* Keep still-pending events for next scheduling */
- bus->intstatus = intstatus;
-
-clkwait:
- /* Re-enable interrupts to detect new device events (mailbox, rx frame)
- * or clock availability. (Allows tx loop to check ipend if desired.)
- * (Unless register access seems hosed, as we may not be able to ACK...)
- */
- if (bus->intr && bus->intdis && !brcmf_sdcard_regfail(card)) {
- BRCMF_INTR(("%s: enable SDIO interrupts, rxdone %d"
- " framecnt %d\n", __func__, rxdone, framecnt));
- bus->intdis = false;
- brcmf_sdcard_intr_enable(card);
- }
-
- if (DATAOK(bus) && bus->ctrl_frame_stat &&
- (bus->clkstate == CLK_AVAIL)) {
- int ret, i;
-
- ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card),
- SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf,
- (u32) bus->ctrl_frame_len, NULL, NULL, NULL);
-
- if (ret < 0) {
- /* On failure, abort the command and
- terminate the frame */
- BRCMF_INFO(("%s: sdio error %d, abort command and "
- "terminate frame.\n", __func__, ret));
- bus->tx_sderrs++;
-
- brcmf_sdcard_abort(card, SDIO_FUNC_2);
-
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
- NULL);
- bus->f1regdata++;
-
- for (i = 0; i < 3; i++) {
- u8 hi, lo;
- hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_WFRAMEBCHI,
- NULL);
- lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_WFRAMEBCLO,
- NULL);
- bus->f1regdata += 2;
- if ((hi == 0) && (lo == 0))
- break;
- }
-
- }
- if (ret == 0)
- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
-
- BRCMF_INFO(("Return_dpc value is : %d\n", ret));
- bus->ctrl_frame_stat = false;
- brcmf_sdbrcm_wait_event_wakeup(bus);
- }
- /* Send queued frames (limit 1 if rx may still be pending) */
- else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
- brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
- && DATAOK(bus)) {
- framecnt = rxdone ? txlimit : min(txlimit, brcmf_txminmax);
- framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt);
- txlimit -= framecnt;
- }
-
- /* Resched if events or tx frames are pending,
- else await next interrupt */
- /* On failed register access, all bets are off:
- no resched or interrupts */
- if ((bus->drvr->busstate == BRCMF_BUS_DOWN) ||
- brcmf_sdcard_regfail(card)) {
- BRCMF_ERROR(("%s: failed backplane access over SDIO, halting "
- "operation %d\n", __func__,
- brcmf_sdcard_regfail(card)));
- bus->drvr->busstate = BRCMF_BUS_DOWN;
- bus->intstatus = 0;
- } else if (bus->clkstate == CLK_PENDING) {
- BRCMF_INFO(("%s: rescheduled due to CLK_PENDING awaiting "
- "I_CHIPACTIVE interrupt\n", __func__));
- resched = true;
- } else if (bus->intstatus || bus->ipend ||
- (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)
- && DATAOK(bus)) || PKT_AVAILABLE()) {
- resched = true;
- }
-
- bus->dpc_sched = resched;
-
- /* If we're done for now, turn off clock request. */
- if ((bus->clkstate != CLK_PENDING)
- && bus->idletime == BRCMF_IDLE_IMMEDIATE) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
- }
-
- brcmf_sdbrcm_sdunlock(bus);
-
- return resched;
-}
-
-void brcmf_sdbrcm_isr(void *arg)
-{
- struct brcmf_bus *bus = (struct brcmf_bus *) arg;
- struct brcmf_sdio_card *card;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (!bus) {
- BRCMF_ERROR(("%s : bus is null pointer , exit\n", __func__));
- return;
- }
- card = bus->card;
-
- if (bus->drvr->busstate == BRCMF_BUS_DOWN) {
- BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
- __func__));
- return;
- }
- /* Count the interrupt call */
- bus->intrcount++;
- bus->ipend = true;
-
- /* Shouldn't get this interrupt if we're sleeping? */
- if (bus->sleeping) {
- BRCMF_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
- return;
- }
-
- /* Disable additional interrupts (is this needed now)? */
- if (bus->intr)
- BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
- else
- BRCMF_ERROR(("brcmf_sdbrcm_isr() w/o interrupt configured!\n"));
-
- brcmf_sdcard_intr_disable(card);
- bus->intdis = true;
-
-#if defined(SDIO_ISR_THREAD)
- BRCMF_TRACE(("Calling brcmf_sdbrcm_dpc() from %s\n", __func__));
- while (brcmf_sdbrcm_dpc(bus))
- ;
-#else
- bus->dpc_sched = true;
- brcmf_sdbrcm_sched_dpc(bus);
-#endif
-
-}
-
-#ifdef SDTEST
-static void brcmf_sdbrcm_pktgen_init(struct brcmf_bus *bus)
-{
- /* Default to specified length, or full range */
- if (brcmf_pktgen_len) {
- bus->pktgen_maxlen = min(brcmf_pktgen_len,
- BRCMF_MAX_PKTGEN_LEN);
- bus->pktgen_minlen = bus->pktgen_maxlen;
- } else {
- bus->pktgen_maxlen = BRCMF_MAX_PKTGEN_LEN;
- bus->pktgen_minlen = 0;
- }
- bus->pktgen_len = (u16) bus->pktgen_minlen;
-
- /* Default to per-watchdog burst with 10s print time */
- bus->pktgen_freq = 1;
- bus->pktgen_print = 10000 / brcmf_watchdog_ms;
- bus->pktgen_count = (brcmf_pktgen * brcmf_watchdog_ms + 999) / 1000;
-
- /* Default to echo mode */
- bus->pktgen_mode = BRCMF_PKTGEN_ECHO;
- bus->pktgen_stop = 1;
-}
-
-static void brcmf_sdbrcm_pktgen(struct brcmf_bus *bus)
-{
- struct sk_buff *pkt;
- u8 *data;
- uint pktcount;
- uint fillbyte;
- u16 len;
-
- /* Display current count if appropriate */
- if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
- bus->pktgen_ptick = 0;
- printk(KERN_DEBUG "%s: send attempts %d rcvd %d\n",
- __func__, bus->pktgen_sent, bus->pktgen_rcvd);
- }
-
- /* For recv mode, just make sure dongle has started sending */
- if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) {
- if (!bus->pktgen_rcvd)
- brcmf_sdbrcm_sdtest_set(bus, true);
- return;
- }
-
- /* Otherwise, generate or request the specified number of packets */
- for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
- /* Stop if total has been reached */
- if (bus->pktgen_total
- && (bus->pktgen_sent >= bus->pktgen_total)) {
- bus->pktgen_count = 0;
- break;
- }
-
- /* Allocate an appropriate-sized packet */
- len = bus->pktgen_len;
- pkt = brcmu_pkt_buf_get_skb(
- len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN,
- true);
- if (!pkt) {
- BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n",
- __func__));
- break;
- }
- PKTALIGN(pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
- BRCMF_SDALIGN);
- data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
-
- /* Write test header cmd and extra based on mode */
- switch (bus->pktgen_mode) {
- case BRCMF_PKTGEN_ECHO:
- *data++ = SDPCM_TEST_ECHOREQ;
- *data++ = (u8) bus->pktgen_sent;
- break;
-
- case BRCMF_PKTGEN_SEND:
- *data++ = SDPCM_TEST_DISCARD;
- *data++ = (u8) bus->pktgen_sent;
- break;
-
- case BRCMF_PKTGEN_RXBURST:
- *data++ = SDPCM_TEST_BURST;
- *data++ = (u8) bus->pktgen_count;
- break;
-
- default:
- BRCMF_ERROR(("Unrecognized pktgen mode %d\n",
- bus->pktgen_mode));
- brcmu_pkt_buf_free_skb(pkt, true);
- bus->pktgen_count = 0;
- return;
- }
-
- /* Write test header length field */
- *data++ = (len >> 0);
- *data++ = (len >> 8);
-
- /* Then fill in the remainder -- N/A for burst,
- but who cares... */
- for (fillbyte = 0; fillbyte < len; fillbyte++)
- *data++ =
- SDPCM_TEST_FILL(fillbyte, (u8) bus->pktgen_sent);
-
-#ifdef BCMDBG
- if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
- data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
- printk(KERN_DEBUG "brcmf_sdbrcm_pktgen: Tx Data:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data,
- pkt->len - SDPCM_HDRLEN);
- }
-#endif
-
- /* Send it */
- if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) {
- bus->pktgen_fail++;
- if (bus->pktgen_stop
- && bus->pktgen_stop == bus->pktgen_fail)
- bus->pktgen_count = 0;
- }
- bus->pktgen_sent++;
-
- /* Bump length if not fixed, wrap at max */
- if (++bus->pktgen_len > bus->pktgen_maxlen)
- bus->pktgen_len = (u16) bus->pktgen_minlen;
-
- /* Special case for burst mode: just send one request! */
- if (bus->pktgen_mode == BRCMF_PKTGEN_RXBURST)
- break;
- }
-}
-
-static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start)
-{
- struct sk_buff *pkt;
- u8 *data;
-
- /* Allocate the packet */
- pkt = brcmu_pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
- BRCMF_SDALIGN, true);
- if (!pkt) {
- BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n", __func__));
- return;
- }
- PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), BRCMF_SDALIGN);
- data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
-
- /* Fill in the test header */
- *data++ = SDPCM_TEST_SEND;
- *data++ = start;
- *data++ = (bus->pktgen_maxlen >> 0);
- *data++ = (bus->pktgen_maxlen >> 8);
-
- /* Send it */
- if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true))
- bus->pktgen_fail++;
-}
-
-static void
-brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, struct sk_buff *pkt, uint seq)
-{
- u8 *data;
- uint pktlen;
-
- u8 cmd;
- u8 extra;
- u16 len;
- u16 offset;
-
- /* Check for min length */
- pktlen = pkt->len;
- if (pktlen < SDPCM_TEST_HDRLEN) {
- BRCMF_ERROR(("brcmf_sdbrcm_checkdied: toss runt frame, pktlen "
- "%d\n", pktlen));
- brcmu_pkt_buf_free_skb(pkt, false);
- return;
- }
-
- /* Extract header fields */
- data = pkt->data;
- cmd = *data++;
- extra = *data++;
- len = *data++;
- len += *data++ << 8;
-
- /* Check length for relevant commands */
- if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ
- || cmd == SDPCM_TEST_ECHORSP) {
- if (pktlen != len + SDPCM_TEST_HDRLEN) {
- BRCMF_ERROR(("brcmf_sdbrcm_checkdied: frame length "
- "mismatch, pktlen %d seq %d"
- " cmd %d extra %d len %d\n",
- pktlen, seq, cmd, extra, len));
- brcmu_pkt_buf_free_skb(pkt, false);
- return;
- }
- }
-
- /* Process as per command */
- switch (cmd) {
- case SDPCM_TEST_ECHOREQ:
- /* Rx->Tx turnaround ok (even on NDIS w/current
- implementation) */
- *(u8 *) (pkt->data) = SDPCM_TEST_ECHORSP;
- if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true) == 0)
- bus->pktgen_sent++;
- else {
- bus->pktgen_fail++;
- brcmu_pkt_buf_free_skb(pkt, false);
- }
- bus->pktgen_rcvd++;
- break;
-
- case SDPCM_TEST_ECHORSP:
- if (bus->ext_loop) {
- brcmu_pkt_buf_free_skb(pkt, false);
- bus->pktgen_rcvd++;
- break;
- }
-
- for (offset = 0; offset < len; offset++, data++) {
- if (*data != SDPCM_TEST_FILL(offset, extra)) {
- BRCMF_ERROR(("brcmf_sdbrcm_checkdied: echo"
- " data mismatch: "
- "offset %d (len %d) "
- "expect 0x%02x rcvd 0x%02x\n",
- offset, len,
- SDPCM_TEST_FILL(offset, extra),
- *data));
- break;
- }
- }
- brcmu_pkt_buf_free_skb(pkt, false);
- bus->pktgen_rcvd++;
- break;
-
- case SDPCM_TEST_DISCARD:
- brcmu_pkt_buf_free_skb(pkt, false);
- bus->pktgen_rcvd++;
- break;
-
- case SDPCM_TEST_BURST:
- case SDPCM_TEST_SEND:
- default:
- BRCMF_INFO(("brcmf_sdbrcm_checkdied: unsupported or unknown "
- "command, pktlen %d seq %d" " cmd %d extra %d"
- " len %d\n", pktlen, seq, cmd, extra, len));
- brcmu_pkt_buf_free_skb(pkt, false);
- break;
- }
-
- /* For recv mode, stop at limie (and tell dongle to stop sending) */
- if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) {
- if (bus->pktgen_total
- && (bus->pktgen_rcvd >= bus->pktgen_total)) {
- bus->pktgen_count = 0;
- brcmf_sdbrcm_sdtest_set(bus, false);
- }
- }
-}
-#endif /* SDTEST */
-
-extern bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr)
-{
- struct brcmf_bus *bus;
-
- BRCMF_TIMER(("%s: Enter\n", __func__));
-
- bus = drvr->bus;
-
- if (bus->drvr->dongle_reset)
- return false;
-
- /* Ignore the timer if simulating bus down */
- if (bus->sleeping)
- return false;
-
- brcmf_sdbrcm_sdlock(bus);
-
- /* Poll period: check device if appropriate. */
- if (bus->poll && (++bus->polltick >= bus->pollrate)) {
- u32 intstatus = 0;
-
- /* Reset poll tick */
- bus->polltick = 0;
-
- /* Check device if no interrupts */
- if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
-
- if (!bus->dpc_sched) {
- u8 devpend;
- devpend = brcmf_sdcard_cfg_read(bus->card,
- SDIO_FUNC_0, SDIO_CCCR_INTx,
- NULL);
- intstatus =
- devpend & (INTR_STATUS_FUNC1 |
- INTR_STATUS_FUNC2);
- }
-
- /* If there is something, make like the ISR and
- schedule the DPC */
- if (intstatus) {
- bus->pollcnt++;
- bus->ipend = true;
- if (bus->intr)
- brcmf_sdcard_intr_disable(bus->card);
-
- bus->dpc_sched = true;
- brcmf_sdbrcm_sched_dpc(bus);
-
- }
- }
-
- /* Update interrupt tracking */
- bus->lastintrs = bus->intrcount;
- }
-#ifdef BCMDBG
- /* Poll for console output periodically */
- if (drvr->busstate == BRCMF_BUS_DATA && brcmf_console_ms != 0) {
- bus->console.count += brcmf_watchdog_ms;
- if (bus->console.count >= brcmf_console_ms) {
- bus->console.count -= brcmf_console_ms;
- /* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- if (brcmf_sdbrcm_readconsole(bus) < 0)
- brcmf_console_ms = 0; /* On error,
- stop trying */
- }
- }
-#endif /* BCMDBG */
-
-#ifdef SDTEST
- /* Generate packets if configured */
- if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
- /* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- bus->pktgen_tick = 0;
- brcmf_sdbrcm_pktgen(bus);
- }
-#endif
-
- /* On idle timeout clear activity flag and/or turn off clock */
- if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
- if (++bus->idlecount >= bus->idletime) {
- bus->idlecount = 0;
- if (bus->activity) {
- bus->activity = false;
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
- } else {
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
- }
- }
- }
-
- brcmf_sdbrcm_sdunlock(bus);
-
- return bus->ipend;
-}
-
-#ifdef BCMDBG
-static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr,
- unsigned char *msg, uint msglen)
-{
- struct brcmf_bus *bus = drvr->bus;
- u32 addr, val;
- int rv;
- struct sk_buff *pkt;
-
- /* Address could be zero if CONSOLE := 0 in dongle Makefile */
- if (bus->console_addr == 0)
- return -ENOTSUPP;
-
- /* Exclusive bus access */
- brcmf_sdbrcm_sdlock(bus);
-
- /* Don't allow input if dongle is in reset */
- if (bus->drvr->dongle_reset) {
- brcmf_sdbrcm_sdunlock(bus);
- return -EPERM;
- }
-
- /* Request clock to allow SDIO accesses */
- BUS_WAKE(bus);
- /* No pend allowed since txpkt is called later, ht clk has to be on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- /* Zero cbuf_index */
- addr = bus->console_addr + offsetof(struct rte_console, cbuf_idx);
- val = cpu_to_le32(0);
- rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
- if (rv < 0)
- goto done;
-
- /* Write message into cbuf */
- addr = bus->console_addr + offsetof(struct rte_console, cbuf);
- rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)msg, msglen);
- if (rv < 0)
- goto done;
-
- /* Write length into vcons_in */
- addr = bus->console_addr + offsetof(struct rte_console, vcons_in);
- val = cpu_to_le32(msglen);
- rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
- if (rv < 0)
- goto done;
-
- /* Bump dongle by sending an empty event pkt.
- * sdpcm_sendup (RX) checks for virtual console input.
- */
- pkt = brcmu_pkt_buf_get_skb(4 + SDPCM_RESERVE);
- if ((pkt != NULL) && bus->clkstate == CLK_AVAIL)
- brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
-
-done:
- if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
- bus->activity = false;
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
- }
-
- brcmf_sdbrcm_sdunlock(bus);
-
- return rv;
-}
-#endif /* BCMDBG */
-
-static bool brcmf_sdbrcm_chipmatch(u16 chipid)
-{
- if (chipid == BCM4325_CHIP_ID)
- return true;
- if (chipid == BCM4329_CHIP_ID)
- return true;
- if (chipid == BCM4319_CHIP_ID)
- return true;
- return false;
-}
-
-static void *brcmf_sdbrcm_probe(u16 venid, u16 devid, u16 bus_no,
- u16 slot, u16 func, uint bustype, u32 regsva,
- void *card)
-{
- int ret;
- struct brcmf_bus *bus;
-
- /* Init global variables at run-time, not as part of the declaration.
- * This is required to support init/de-init of the driver.
- * Initialization
- * of globals as part of the declaration results in non-deterministic
- * behavior since the value of the globals may be different on the
- * first time that the driver is initialized vs subsequent
- * initializations.
- */
- brcmf_txbound = BRCMF_TXBOUND;
- brcmf_rxbound = BRCMF_RXBOUND;
- brcmf_alignctl = true;
- sd1idle = true;
- brcmf_readahead = true;
- retrydata = false;
- brcmf_dongle_memsize = 0;
- brcmf_txminmax = BRCMF_TXMINMAX;
-
- forcealign = true;
-
- brcmf_c_init();
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
- BRCMF_INFO(("%s: venid 0x%04x devid 0x%04x\n", __func__, venid, devid));
-
- /* We make an assumption about address window mappings:
- * regsva == SI_ENUM_BASE*/
-
- /* SDIO car passes venid and devid based on CIS parsing -- but
- * low-power start
- * means early parse could fail, so here we should get either an ID
- * we recognize OR (-1) indicating we must request power first.
- */
- /* Check the Vendor ID */
- switch (venid) {
- case 0x0000:
- case PCI_VENDOR_ID_BROADCOM:
- break;
- default:
- BRCMF_ERROR(("%s: unknown vendor: 0x%04x\n", __func__, venid));
- return NULL;
- }
-
- /* Check the Device ID and make sure it's one that we support */
- switch (devid) {
- case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */
- case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */
- case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */
- BRCMF_INFO(("%s: found 4325 Dongle\n", __func__));
- break;
- case BCM4329_D11NDUAL_ID: /* 4329 802.11n dualband device */
- case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */
- case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */
- case 0x4329:
- BRCMF_INFO(("%s: found 4329 Dongle\n", __func__));
- break;
- case BCM4319_D11N_ID: /* 4319 802.11n id */
- case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */
- case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */
- BRCMF_INFO(("%s: found 4319 Dongle\n", __func__));
- break;
- case 0:
- BRCMF_INFO(("%s: allow device id 0, will check chip"
- " internals\n", __func__));
- break;
-
- default:
- BRCMF_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
- __func__, venid, devid));
- return NULL;
- }
-
- /* Allocate private bus interface state */
- bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
- if (!bus) {
- BRCMF_ERROR(("%s: kmalloc of struct dhd_bus failed\n",
- __func__));
- goto fail;
- }
- bus->card = card;
- bus->cl_devid = (u16) devid;
- bus->bus = BRCMF_BUS;
- bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
- bus->usebufpool = false; /* Use bufpool if allocated,
- else use locally malloced rxbuf */
-
- /* attempt to attach to the dongle */
- if (!(brcmf_sdbrcm_probe_attach(bus, card, regsva, devid))) {
- BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_attach failed\n",
- __func__));
- goto fail;
- }
-
- spin_lock_init(&bus->txqlock);
- init_waitqueue_head(&bus->ctrl_wait);
-
- /* 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 */
- if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)) {
- bus->threads_only = true;
- sema_init(&bus->sdsem, 1);
- } else {
- bus->threads_only = false;
- spin_lock_init(&bus->sdlock);
- }
-
- if (brcmf_dpc_prio >= 0) {
- /* Initialize watchdog thread */
- init_completion(&bus->watchdog_wait);
- bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,
- bus, "brcmf_watchdog");
- if (IS_ERR(bus->watchdog_tsk)) {
- printk(KERN_WARNING
- "brcmf_watchdog thread failed to start\n");
- bus->watchdog_tsk = NULL;
- }
- } else
- bus->watchdog_tsk = NULL;
-
- /* Set up the bottom half handler */
- if (brcmf_dpc_prio >= 0) {
- /* Initialize DPC thread */
- init_completion(&bus->dpc_wait);
- bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
- bus, "brcmf_dpc");
- if (IS_ERR(bus->dpc_tsk)) {
- printk(KERN_WARNING
- "brcmf_dpc thread failed to start\n");
- bus->dpc_tsk = NULL;
- }
- } else {
- tasklet_init(&bus->tasklet, brcmf_sdbrcm_dpc_tasklet,
- (unsigned long)bus);
- bus->dpc_tsk = NULL;
- }
-
- /* Attach to the brcmf/OS/network interface */
- bus->drvr = brcmf_attach(bus, SDPCM_RESERVE);
- if (!bus->drvr) {
- BRCMF_ERROR(("%s: brcmf_attach failed\n", __func__));
- goto fail;
- }
-
- /* Allocate buffers */
- if (!(brcmf_sdbrcm_probe_malloc(bus, card))) {
- BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_malloc failed\n",
- __func__));
- goto fail;
- }
-
- if (!(brcmf_sdbrcm_probe_init(bus, card))) {
- BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_init failed\n", __func__));
- goto fail;
- }
-
- /* Register interrupt callback, but mask it (not operational yet). */
- BRCMF_INTR(("%s: disable SDIO interrupts (not interested yet)\n",
- __func__));
- brcmf_sdcard_intr_disable(card);
- ret = brcmf_sdcard_intr_reg(card, brcmf_sdbrcm_isr, bus);
- if (ret != 0) {
- BRCMF_ERROR(("%s: FAILED: sdcard_intr_reg returned %d\n",
- __func__, ret));
- goto fail;
- }
- BRCMF_INTR(("%s: registered SDIO interrupt function ok\n", __func__));
-
- BRCMF_INFO(("%s: completed!!\n", __func__));
-
- /* if firmware path present try to download and bring up bus */
- ret = brcmf_bus_start(bus->drvr);
- if (ret != 0) {
- if (ret == -ENOLINK) {
- BRCMF_ERROR(("%s: dongle is not responding\n",
- __func__));
- goto fail;
- }
- }
- /* Ok, have the per-port tell the stack we're open for business */
- if (brcmf_net_attach(bus->drvr, 0) != 0) {
- BRCMF_ERROR(("%s: Net attach failed!!\n", __func__));
- goto fail;
- }
-
- return bus;
-
-fail:
- brcmf_sdbrcm_release(bus);
- return NULL;
-}
-
-static bool
-brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card, u32 regsva,
- u16 devid)
-{
- u8 clkctl = 0;
- int err = 0;
-
- bus->alp_only = true;
-
- /* Return the window to backplane enumeration space for core access */
- if (brcmf_sdbrcm_set_siaddr_window(bus, SI_ENUM_BASE))
- BRCMF_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n",
- __func__));
-
-#ifdef BCMDBG
- printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
- brcmf_sdcard_reg_read(bus->card, SI_ENUM_BASE, 4));
-
-#endif /* BCMDBG */
-
- /*
- * Force PLL off until brcmf_sdbrcm_chip_attach()
- * programs PLL control regs
- */
-
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- BRCMF_INIT_CLKCTL1, &err);
- if (!err)
- clkctl =
- brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
-
- if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
- BRCMF_ERROR(("brcmf_sdbrcm_probe: ChipClkCSR access: err %d"
- " wrote 0x%02x read 0x%02x\n",
- err, BRCMF_INIT_CLKCTL1, clkctl));
- goto fail;
- }
-
- if (brcmf_sdbrcm_chip_attach(bus, regsva)) {
- BRCMF_ERROR(("%s: brcmf_sdbrcm_chip_attach failed!\n",
- __func__));
- goto fail;
- }
-
- if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) {
- BRCMF_ERROR(("%s: unsupported chip: 0x%04x\n",
- __func__, bus->ci->chip));
- goto fail;
- }
-
- brcmf_sdbrcm_sdiod_drive_strength_init(bus, brcmf_sdiod_drive_strength);
-
- /* Get info on the ARM and SOCRAM cores... */
- if (!BRCMF_NOPMU(bus)) {
- brcmf_sdcard_reg_read(bus->card,
- CORE_SB(bus->ci->armcorebase, sbidhigh), 4);
- bus->orig_ramsize = bus->ci->ramsize;
- if (!(bus->orig_ramsize)) {
- BRCMF_ERROR(("%s: failed to find SOCRAM memory!\n",
- __func__));
- goto fail;
- }
- bus->ramsize = bus->orig_ramsize;
- if (brcmf_dongle_memsize)
- brcmf_sdbrcm_setmemsize(bus, brcmf_dongle_memsize);
-
- BRCMF_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
- bus->ramsize, bus->orig_ramsize));
- }
-
- /* Set core control so an SDIO reset does a backplane reset */
- OR_REG(bus->ci->buscorebase + offsetof(struct sdpcmd_regs,
- corecontrol),
- CC_BPRESEN, u32);
-
- brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
-
- /* Locate an appropriately-aligned portion of hdrbuf */
- bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
- BRCMF_SDALIGN);
-
- /* Set the poll and/or interrupt flags */
- bus->intr = (bool) brcmf_intr;
- bus->poll = (bool) brcmf_poll;
- if (bus->poll)
- bus->pollrate = 1;
-
- return true;
-
-fail:
- return false;
-}
-
-static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (bus->drvr->maxctl) {
- bus->rxblen =
- roundup((bus->drvr->maxctl + SDPCM_HDRLEN),
- ALIGNMENT) + BRCMF_SDALIGN;
- bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
- if (!(bus->rxbuf)) {
- BRCMF_ERROR(("%s: kmalloc of %d-byte rxbuf failed\n",
- __func__, bus->rxblen));
- goto fail;
- }
- }
-
- /* Allocate buffer to receive glomed packet */
- bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC);
- if (!(bus->databuf)) {
- BRCMF_ERROR(("%s: kmalloc of %d-byte databuf failed\n",
- __func__, MAX_DATA_BUF));
- /* release rxbuf which was already located as above */
- if (!bus->rxblen)
- kfree(bus->rxbuf);
- goto fail;
- }
-
- /* Align the buffer */
- if ((unsigned long)bus->databuf % BRCMF_SDALIGN)
- bus->dataptr = bus->databuf + (BRCMF_SDALIGN -
- ((unsigned long)bus->databuf % BRCMF_SDALIGN));
- else
- bus->dataptr = bus->databuf;
-
- return true;
-
-fail:
- return false;
-}
-
-static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card)
-{
- s32 fnum;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
-#ifdef SDTEST
- brcmf_sdbrcm_pktgen_init(bus);
-#endif /* SDTEST */
-
- /* Disable F2 to clear any intermediate frame state on the dongle */
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
- SDIO_FUNC_ENABLE_1, NULL);
-
- bus->drvr->busstate = BRCMF_BUS_DOWN;
- bus->sleeping = false;
- bus->rxflow = false;
-
- /* Done with backplane-dependent accesses, can drop clock... */
- brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0,
- NULL);
-
- /* ...and initialize clock/power states */
- bus->clkstate = CLK_SDONLY;
- bus->idletime = (s32) brcmf_idletime;
- bus->idleclock = BRCMF_IDLE_ACTIVE;
-
- /* Query the F2 block size, set roundup accordingly */
- fnum = 2;
- if (brcmf_sdcard_iovar_op(card, "sd_blocksize", &fnum, sizeof(s32),
- &bus->blocksize, sizeof(s32), false) != 0) {
- bus->blocksize = 0;
- BRCMF_ERROR(("%s: fail on %s get\n", __func__, "sd_blocksize"));
- } else {
- BRCMF_INFO(("%s: Initial value for %s is %d\n",
- __func__, "sd_blocksize", bus->blocksize));
- }
- bus->roundup = min(max_roundup, bus->blocksize);
-
- /* Query if bus module supports packet chaining,
- default to use if supported */
- if (brcmf_sdcard_iovar_op(card, "sd_rxchain", NULL, 0,
- &bus->sd_rxchain, sizeof(s32),
- false) != 0) {
- bus->sd_rxchain = false;
- } else {
- BRCMF_INFO(("%s: bus module (through sdiocard API) %s"
- " chaining\n", __func__, bus->sd_rxchain
- ? "supports" : "does not support"));
- }
- bus->use_rxchain = (bool) bus->sd_rxchain;
-
- return true;
-}
-
-static bool
-brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card)
-{
- bool ret;
-
- /* Download the firmware */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
-
- brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
-
- return ret;
-}
-
-/* Detach and free everything */
-static void brcmf_sdbrcm_release(struct brcmf_bus *bus)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (bus) {
- /* De-register interrupt handler */
- brcmf_sdcard_intr_disable(bus->card);
- brcmf_sdcard_intr_dereg(bus->card);
-
- if (bus->drvr) {
- brcmf_detach(bus->drvr);
- brcmf_sdbrcm_release_dongle(bus);
- bus->drvr = NULL;
- }
-
- brcmf_sdbrcm_release_malloc(bus);
-
- kfree(bus);
- }
-
- BRCMF_TRACE(("%s: Disconnected\n", __func__));
-}
-
-static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (bus->drvr && bus->drvr->dongle_reset)
- return;
-
- kfree(bus->rxbuf);
- bus->rxctl = bus->rxbuf = NULL;
- bus->rxlen = 0;
-
- kfree(bus->databuf);
- bus->databuf = NULL;
-}
-
-static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (bus->drvr && bus->drvr->dongle_reset)
- return;
-
- if (bus->ci) {
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
- brcmf_sdbrcm_chip_detach(bus);
- if (bus->vars && bus->varsz)
- kfree(bus->vars);
- bus->vars = NULL;
- }
-
- BRCMF_TRACE(("%s: Disconnected\n", __func__));
-}
-
-static void brcmf_sdbrcm_disconnect(void *ptr)
-{
- struct brcmf_bus *bus = (struct brcmf_bus *)ptr;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- if (bus) {
- brcmf_sdbrcm_release(bus);
- }
-
- BRCMF_TRACE(("%s: Disconnected\n", __func__));
-}
-
-/* Register/Unregister functions are called by the main DHD entry
- * point (e.g. module insertion) to link with the bus driver, in
- * order to look for or await the device.
- */
-
-static struct brcmf_sdioh_driver brcmf_sdio = {
- brcmf_sdbrcm_probe,
- brcmf_sdbrcm_disconnect
-};
-
-int brcmf_bus_register(void)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* Sanity check on the module parameters */
- do {
- /* Both watchdog and DPC as tasklets are ok */
- if ((brcmf_watchdog_prio < 0) && (brcmf_dpc_prio < 0))
- break;
-
- /* If both watchdog and DPC are threads, TX must be deferred */
- if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)
- && brcmf_deferred_tx)
- break;
-
- BRCMF_ERROR(("Invalid module parameters.\n"));
- return -EINVAL;
- } while (0);
-
- return brcmf_sdio_register(&brcmf_sdio);
-}
-
-void brcmf_bus_unregister(void)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- brcmf_sdio_unregister();
-}
-
-static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus)
-{
- int offset = 0;
- uint len;
- u8 *memblock = NULL, *memptr;
- int ret;
-
- BRCMF_INFO(("%s: Enter\n", __func__));
-
- bus->fw_name = BCM4329_FW_NAME;
- ret = request_firmware(&bus->firmware, bus->fw_name,
- &gInstance->func[2]->dev);
- if (ret) {
- BRCMF_ERROR(("%s: Fail to request firmware %d\n",
- __func__, ret));
- return ret;
- }
- bus->fw_ptr = 0;
-
- memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC);
- if (memblock == NULL) {
- BRCMF_ERROR(("%s: Failed to allocate memory %d bytes\n",
- __func__, MEMBLOCK));
- ret = -ENOMEM;
- goto err;
- }
- if ((u32)(unsigned long)memblock % BRCMF_SDALIGN)
- memptr += (BRCMF_SDALIGN -
- ((u32)(unsigned long)memblock % BRCMF_SDALIGN));
-
- /* Download image */
- while ((len =
- brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) {
- ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len);
- if (ret) {
- BRCMF_ERROR(("%s: error %d on writing %d membytes at "
- "0x%08x\n", __func__, ret, MEMBLOCK,
- offset));
- goto err;
- }
-
- offset += MEMBLOCK;
- }
-
-err:
- kfree(memblock);
-
- release_firmware(bus->firmware);
- bus->fw_ptr = 0;
-
- return ret;
-}
-
-/*
- * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file
- * and ending in a NUL.
- * Removes carriage returns, empty lines, comment lines, and converts
- * newlines to NULs.
- * Shortens buffer as needed and pads with NULs. End of buffer is marked
- * by two NULs.
-*/
-
-static uint brcmf_process_nvram_vars(char *varbuf, uint len)
-{
- char *dp;
- bool findNewline;
- int column;
- uint buf_len, n;
-
- dp = varbuf;
-
- findNewline = false;
- column = 0;
-
- for (n = 0; n < len; n++) {
- if (varbuf[n] == 0)
- break;
- if (varbuf[n] == '\r')
- continue;
- if (findNewline && varbuf[n] != '\n')
- continue;
- findNewline = false;
- if (varbuf[n] == '#') {
- findNewline = true;
- continue;
- }
- if (varbuf[n] == '\n') {
- if (column == 0)
- continue;
- *dp++ = 0;
- column = 0;
- continue;
- }
- *dp++ = varbuf[n];
- column++;
- }
- buf_len = dp - varbuf;
-
- while (dp < varbuf + n)
- *dp++ = 0;
-
- return buf_len;
-}
-
-static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus)
-{
- uint len;
- char *memblock = NULL;
- char *bufp;
- int ret;
-
- bus->nv_name = BCM4329_NV_NAME;
- ret = request_firmware(&bus->firmware, bus->nv_name,
- &gInstance->func[2]->dev);
- if (ret) {
- BRCMF_ERROR(("%s: Fail to request nvram %d\n", __func__, ret));
- return ret;
- }
- bus->fw_ptr = 0;
-
- memblock = kmalloc(MEMBLOCK, GFP_ATOMIC);
- if (memblock == NULL) {
- BRCMF_ERROR(("%s: Failed to allocate memory %d bytes\n",
- __func__, MEMBLOCK));
- ret = -ENOMEM;
- goto err;
- }
-
- len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus);
-
- if (len > 0 && len < MEMBLOCK) {
- bufp = (char *)memblock;
- bufp[len] = 0;
- len = brcmf_process_nvram_vars(bufp, len);
- bufp += len;
- *bufp++ = 0;
- if (len)
- ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1);
- if (ret)
- BRCMF_ERROR(("%s: error downloading vars: %d\n",
- __func__, ret));
- } else {
- BRCMF_ERROR(("%s: error reading nvram file: %d\n",
- __func__, len));
- ret = -EIO;
- }
-
-err:
- kfree(memblock);
-
- release_firmware(bus->firmware);
- bus->fw_ptr = 0;
-
- return ret;
-}
-
-static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
-{
- int bcmerror = -1;
-
- /* Keep arm in reset */
- if (brcmf_sdbrcm_download_state(bus, true)) {
- BRCMF_ERROR(("%s: error placing ARM core in reset\n",
- __func__));
- goto err;
- }
-
- /* External image takes precedence if specified */
- if (brcmf_sdbrcm_download_code_file(bus)) {
- BRCMF_ERROR(("%s: dongle image file download failed\n",
- __func__));
- goto err;
- }
-
- /* External nvram takes precedence if specified */
- if (brcmf_sdbrcm_download_nvram(bus)) {
- BRCMF_ERROR(("%s: dongle nvram file download failed\n",
- __func__));
- }
-
- /* Take arm out of reset */
- if (brcmf_sdbrcm_download_state(bus, false)) {
- BRCMF_ERROR(("%s: error getting out of ARM core reset\n",
- __func__));
- goto err;
- }
-
- bcmerror = 0;
-
-err:
- return bcmerror;
-}
-
-
-static int
-brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags,
- u8 *buf, uint nbytes, struct sk_buff *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle)
-{
- return brcmf_sdcard_send_buf
- (bus->card, addr, fn, flags, buf, nbytes, pkt, complete,
- handle);
-}
-
-int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag)
-{
- int bcmerror = 0;
- struct brcmf_bus *bus;
-
- bus = drvr->bus;
-
- if (flag == true) {
- brcmf_sdbrcm_wd_timer(bus, 0);
- if (!bus->drvr->dongle_reset) {
- /* Expect app to have torn down any
- connection before calling */
- /* Stop the bus, disable F2 */
- brcmf_sdbrcm_bus_stop(bus, false);
-
- /* Clean tx/rx buffer pointers,
- detach from the dongle */
- brcmf_sdbrcm_release_dongle(bus);
-
- bus->drvr->dongle_reset = true;
- bus->drvr->up = false;
-
- BRCMF_TRACE(("%s: WLAN OFF DONE\n", __func__));
- /* App can now remove power from device */
- } else
- bcmerror = -EIO;
- } else {
- /* App must have restored power to device before calling */
-
- BRCMF_TRACE(("\n\n%s: == WLAN ON ==\n", __func__));
-
- if (bus->drvr->dongle_reset) {
- /* Turn on WLAN */
-
- /* Attempt to re-attach & download */
- if (brcmf_sdbrcm_probe_attach(bus, bus->card,
- SI_ENUM_BASE,
- bus->cl_devid)) {
- /* Attempt to download binary to the dongle */
- if (brcmf_sdbrcm_probe_init(bus, bus->card)) {
- /* Re-init bus, enable F2 transfer */
- brcmf_sdbrcm_bus_init(bus->drvr, false);
-
- bus->drvr->dongle_reset = false;
- bus->drvr->up = true;
-
- BRCMF_TRACE(("%s: WLAN ON DONE\n",
- __func__));
- } else
- bcmerror = -EIO;
- } else
- bcmerror = -EIO;
- } else {
- bcmerror = -EISCONN;
- BRCMF_ERROR(("%s: Set DEVRESET=false invoked when"
- " device is on\n", __func__));
- bcmerror = -EIO;
- }
- brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
- }
- return bcmerror;
-}
-
-static int
-brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_card *card,
- struct chip_info *ci, u32 regs)
-{
- u32 regdata;
-
- /*
- * Get CC core rev
- * Chipid is assume to be at offset 0 from regs arg
- * For different chiptypes or old sdio hosts w/o chipcommon,
- * other ways of recognition should be added here.
- */
- ci->cccorebase = regs;
- regdata = brcmf_sdcard_reg_read(card,
- CORE_CC_REG(ci->cccorebase, chipid), 4);
- ci->chip = regdata & CID_ID_MASK;
- ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
-
- BRCMF_INFO(("%s: chipid=0x%x chiprev=%d\n",
- __func__, ci->chip, ci->chiprev));
-
- /* Address of cores for new chips should be added here */
- switch (ci->chip) {
- case BCM4329_CHIP_ID:
- ci->buscorebase = BCM4329_CORE_BUS_BASE;
- ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
- ci->armcorebase = BCM4329_CORE_ARM_BASE;
- ci->ramsize = BCM4329_RAMSIZE;
- break;
- default:
- BRCMF_ERROR(("%s: chipid 0x%x is not supported\n",
- __func__, ci->chip));
- return -ENODEV;
- }
-
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(ci->cccorebase, sbidhigh), 4);
- ci->ccrev = SBCOREREV(regdata);
-
- regdata = brcmf_sdcard_reg_read(card,
- CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
- ci->pmurev = regdata & PCAP_REV_MASK;
-
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(ci->buscorebase, sbidhigh), 4);
- ci->buscorerev = SBCOREREV(regdata);
- ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
-
- BRCMF_INFO(("%s: ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
- __func__, ci->ccrev, ci->pmurev,
- ci->buscorerev, ci->buscoretype));
-
- /* get chipcommon capabilites */
- ci->cccaps = brcmf_sdcard_reg_read(card,
- CORE_CC_REG(ci->cccorebase, capabilities), 4);
-
- return 0;
-}
-
-static void
-brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase)
-{
- u32 regdata;
-
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatelow), 4);
- if (regdata & SBTML_RESET)
- return;
-
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatelow), 4);
- if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
- /*
- * set target reject and spin until busy is clear
- * (preserve core-specific bits)
- */
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatelow), 4);
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
- regdata | SBTML_REJ);
-
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatelow), 4);
- udelay(1);
- SPINWAIT((brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatehigh), 4) &
- SBTMH_BUSY), 100000);
-
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatehigh), 4);
- if (regdata & SBTMH_BUSY)
- BRCMF_ERROR(("%s: ARM core still busy\n", __func__));
-
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbidlow), 4);
- if (regdata & SBIDL_INIT) {
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbimstate), 4) |
- SBIM_RJ;
- brcmf_sdcard_reg_write(card,
- CORE_SB(corebase, sbimstate), 4,
- regdata);
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbimstate), 4);
- udelay(1);
- SPINWAIT((brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbimstate), 4) &
- SBIM_BY), 100000);
- }
-
- /* set reset and reject while enabling the clocks */
- brcmf_sdcard_reg_write(card,
- CORE_SB(corebase, sbtmstatelow), 4,
- (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
- SBTML_REJ | SBTML_RESET));
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbtmstatelow), 4);
- udelay(10);
-
- /* clear the initiator reject bit */
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbidlow), 4);
- if (regdata & SBIDL_INIT) {
- regdata = brcmf_sdcard_reg_read(card,
- CORE_SB(corebase, sbimstate), 4) &
- ~SBIM_RJ;
- brcmf_sdcard_reg_write(card,
- CORE_SB(corebase, sbimstate), 4,
- regdata);
- }
- }
-
- /* leave reset and reject asserted */
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
- (SBTML_REJ | SBTML_RESET));
- udelay(1);
-}
-
-static int
-brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs)
-{
- struct chip_info *ci;
- int err;
- u8 clkval, clkset;
-
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- /* alloc chip_info_t */
- ci = kmalloc(sizeof(struct chip_info), GFP_ATOMIC);
- if (NULL == ci) {
- BRCMF_ERROR(("%s: malloc failed!\n", __func__));
- return -ENOMEM;
- }
-
- memset((unsigned char *)ci, 0, sizeof(struct chip_info));
-
- /* bus/core/clk setup for register access */
- /* Try forcing SDIO core to do ALPAvail request only */
- clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- clkset, &err);
- if (err) {
- BRCMF_ERROR(("%s: error writing for HT off\n", __func__));
- goto fail;
- }
-
- /* If register supported, wait for ALPAvail and then force ALP */
- /* This may take up to 15 milliseconds */
- clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR, NULL);
- if ((clkval & ~SBSDIO_AVBITS) == clkset) {
- SPINWAIT(((clkval =
- brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- NULL)),
- !SBSDIO_ALPAV(clkval)),
- PMU_MAX_TRANSITION_DLY);
- if (!SBSDIO_ALPAV(clkval)) {
- BRCMF_ERROR(("%s: timeout on ALPAV wait,"
- " clkval 0x%02x\n", __func__, clkval));
- err = -EBUSY;
- goto fail;
- }
- clkset = SBSDIO_FORCE_HW_CLKREQ_OFF |
- SBSDIO_FORCE_ALP;
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
- SBSDIO_FUNC1_CHIPCLKCSR,
- clkset, &err);
- udelay(65);
- } else {
- BRCMF_ERROR(("%s: ChipClkCSR access: wrote 0x%02x"
- " read 0x%02x\n", __func__, clkset, clkval));
- err = -EACCES;
- goto fail;
- }
-
- /* Also, disable the extra SDIO pull-ups */
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP,
- 0, NULL);
-
- err = brcmf_sdbrcm_chip_recognition(bus->card, ci, regs);
- if (err)
- goto fail;
-
- /*
- * Make sure any on-chip ARM is off (in case strapping is wrong),
- * or downloaded code was already running.
- */
- brcmf_sdbrcm_chip_disablecore(bus->card, ci->armcorebase);
-
- brcmf_sdcard_reg_write(bus->card,
- CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
- brcmf_sdcard_reg_write(bus->card,
- CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
-
- /* Disable F2 to clear any intermediate frame state on the dongle */
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
- SDIO_FUNC_ENABLE_1, NULL);
-
- /* WAR: cmd52 backplane read so core HW will drop ALPReq */
- clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
- 0, NULL);
-
- /* Done with backplane-dependent accesses, can drop clock... */
- brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
- 0, NULL);
-
- bus->ci = ci;
- return 0;
-fail:
- bus->ci = NULL;
- kfree(ci);
- return err;
-}
-
-static void
-brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase)
-{
- u32 regdata;
-
- /*
- * Must do the disable sequence first to work for
- * arbitrary current core state.
- */
- brcmf_sdbrcm_chip_disablecore(card, corebase);
-
- /*
- * Now do the initialization sequence.
- * set reset while enabling the clock and
- * forcing them on throughout the core
- */
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
- ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
- SBTML_RESET);
- udelay(1);
-
- regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatehigh),
- 4);
- if (regdata & SBTMH_SERR)
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatehigh),
- 4, 0);
-
- regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbimstate), 4);
- if (regdata & (SBIM_IBE | SBIM_TO))
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbimstate), 4,
- regdata & ~(SBIM_IBE | SBIM_TO));
-
- /* clear reset and allow it to propagate throughout the core */
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
- (SICF_FGC << SBTML_SICF_SHIFT) |
- (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
- udelay(1);
-
- /* leave clock enabled */
- brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
- (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
- udelay(1);
-}
-
-/* SDIO Pad drive strength to select value mappings */
-struct sdiod_drive_str {
- u8 strength; /* Pad Drive Strength in mA */
- u8 sel; /* Chip-specific select value */
-};
-
-/* SDIO Drive Strength to sel value table for PMU Rev 1 */
-static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
- {
- 4, 0x2}, {
- 2, 0x3}, {
- 1, 0x0}, {
- 0, 0x0}
- };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
-static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
- {
- 12, 0x7}, {
- 10, 0x6}, {
- 8, 0x5}, {
- 6, 0x4}, {
- 4, 0x2}, {
- 2, 0x1}, {
- 0, 0x0}
- };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
-static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
- {
- 32, 0x7}, {
- 26, 0x6}, {
- 22, 0x5}, {
- 16, 0x4}, {
- 12, 0x3}, {
- 8, 0x2}, {
- 4, 0x1}, {
- 0, 0x0}
- };
-
-#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
-
-static void
-brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, u32 drivestrength) {
- struct sdiod_drive_str *str_tab = NULL;
- u32 str_mask = 0;
- u32 str_shift = 0;
- char chn[8];
-
- if (!(bus->ci->cccaps & CC_CAP_PMU))
- return;
-
- switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->ci->pmurev)) {
- case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
- str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
- str_mask = 0x30000000;
- str_shift = 28;
- break;
- case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
- case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
- str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
- str_mask = 0x00003800;
- str_shift = 11;
- break;
- case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
- str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
- str_mask = 0x00003800;
- str_shift = 11;
- break;
- default:
- BRCMF_ERROR(("No SDIO Drive strength init"
- "done for chip %s rev %d pmurev %d\n",
- brcmu_chipname(bus->ci->chip, chn, 8),
- bus->ci->chiprev, bus->ci->pmurev));
- break;
- }
-
- if (str_tab != NULL) {
- u32 drivestrength_sel = 0;
- u32 cc_data_temp;
- int i;
-
- for (i = 0; str_tab[i].strength != 0; i++) {
- if (drivestrength >= str_tab[i].strength) {
- drivestrength_sel = str_tab[i].sel;
- break;
- }
- }
-
- brcmf_sdcard_reg_write(bus->card,
- CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
- 4, 1);
- cc_data_temp = brcmf_sdcard_reg_read(bus->card,
- CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4);
- cc_data_temp &= ~str_mask;
- drivestrength_sel <<= str_shift;
- cc_data_temp |= drivestrength_sel;
- brcmf_sdcard_reg_write(bus->card,
- CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
- 4, cc_data_temp);
-
- BRCMF_INFO(("SDIO: %dmA drive strength selected, "
- "set to 0x%08x\n", drivestrength, cc_data_temp));
- }
-}
-
-static void
-brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus)
-{
- BRCMF_TRACE(("%s: Enter\n", __func__));
-
- kfree(bus->ci);
- bus->ci = NULL;
-}
-
-static void
-brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar)
-{
- brcmf_sdbrcm_sdunlock(bus);
- wait_event_interruptible_timeout(bus->ctrl_wait,
- (*lockvar == false), HZ * 2);
- brcmf_sdbrcm_sdlock(bus);
- return;
-}
-
-static void
-brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus)
-{
- if (waitqueue_active(&bus->ctrl_wait))
- wake_up_interruptible(&bus->ctrl_wait);
- return;
-}
-
-static int
-brcmf_sdbrcm_watchdog_thread(void *data)
-{
- struct brcmf_bus *bus = (struct brcmf_bus *)data;
-
- /* This thread doesn't need any user-level access,
- * so get rid of all our resources
- */
- if (brcmf_watchdog_prio > 0) {
- struct sched_param param;
- param.sched_priority = (brcmf_watchdog_prio < MAX_RT_PRIO) ?
- brcmf_watchdog_prio : (MAX_RT_PRIO - 1);
- sched_setscheduler(current, SCHED_FIFO, &param);
- }
-
- allow_signal(SIGTERM);
- /* Run until signal received */
- while (1) {
- if (kthread_should_stop())
- break;
- if (!wait_for_completion_interruptible(&bus->watchdog_wait)) {
- if (bus->drvr->dongle_reset == false)
- brcmf_sdbrcm_bus_watchdog(bus->drvr);
- /* Count the tick for reference */
- bus->drvr->tickcnt++;
- } else
- break;
- }
- return 0;
-}
-
-static void
-brcmf_sdbrcm_watchdog(unsigned long data)
-{
- struct brcmf_bus *bus = (struct brcmf_bus *)data;
-
- if (brcmf_watchdog_prio >= 0) {
- if (bus->watchdog_tsk)
- complete(&bus->watchdog_wait);
- else
- return;
- } else {
- brcmf_sdbrcm_bus_watchdog(bus->drvr);
-
- /* Count the tick for reference */
- bus->drvr->tickcnt++;
- }
-
- /* Reschedule the watchdog */
- if (bus->wd_timer_valid)
- mod_timer(&bus->timer, jiffies + brcmf_watchdog_ms * HZ / 1000);
-}
-
-void
-brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
-{
- static uint save_ms;
-
- /* don't start the wd until fw is loaded */
- if (bus->drvr->busstate == BRCMF_BUS_DOWN)
- return;
-
- /* Totally stop the timer */
- if (!wdtick && bus->wd_timer_valid == true) {
- del_timer_sync(&bus->timer);
- bus->wd_timer_valid = false;
- save_ms = wdtick;
- return;
- }
-
- if (wdtick) {
- brcmf_watchdog_ms = (uint) wdtick;
-
- if (save_ms != brcmf_watchdog_ms) {
- if (bus->wd_timer_valid == true)
- /* Stop timer and restart at new value */
- del_timer_sync(&bus->timer);
-
- /* Create timer again when watchdog period is
- dynamically changed or in the first instance
- */
- bus->timer.expires =
- jiffies + brcmf_watchdog_ms * HZ / 1000;
- add_timer(&bus->timer);
-
- } else {
- /* Re arm the timer, at last watchdog period */
- mod_timer(&bus->timer,
- jiffies + brcmf_watchdog_ms * HZ / 1000);
- }
-
- bus->wd_timer_valid = true;
- save_ms = wdtick;
- }
-}
-
-static int brcmf_sdbrcm_dpc_thread(void *data)
-{
- struct brcmf_bus *bus = (struct brcmf_bus *) data;
-
- /* This thread doesn't need any user-level access,
- * so get rid of all our resources
- */
- if (brcmf_dpc_prio > 0) {
- struct sched_param param;
- param.sched_priority = (brcmf_dpc_prio < MAX_RT_PRIO) ?
- brcmf_dpc_prio : (MAX_RT_PRIO - 1);
- sched_setscheduler(current, SCHED_FIFO, &param);
- }
-
- allow_signal(SIGTERM);
- /* Run until signal received */
- while (1) {
- if (kthread_should_stop())
- break;
- if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
- /* Call bus dpc unless it indicated down
- (then clean stop) */
- if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
- if (brcmf_sdbrcm_dpc(bus))
- complete(&bus->dpc_wait);
- } else {
- brcmf_sdbrcm_bus_stop(bus, true);
- }
- } else
- break;
- }
- return 0;
-}
-
-static void brcmf_sdbrcm_dpc_tasklet(unsigned long data)
-{
- struct brcmf_bus *bus = (struct brcmf_bus *) data;
-
- /* Call bus dpc unless it indicated down (then clean stop) */
- if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
- if (brcmf_sdbrcm_dpc(bus))
- tasklet_schedule(&bus->tasklet);
- } else
- brcmf_sdbrcm_bus_stop(bus, true);
-}
-
-static void brcmf_sdbrcm_sched_dpc(struct brcmf_bus *bus)
-{
- if (bus->dpc_tsk) {
- complete(&bus->dpc_wait);
- return;
- }
-
- tasklet_schedule(&bus->tasklet);
-}
-
-static void brcmf_sdbrcm_sdlock(struct brcmf_bus *bus)
-{
- if (bus->threads_only)
- down(&bus->sdsem);
- else
- spin_lock_bh(&bus->sdlock);
-}
-
-static void brcmf_sdbrcm_sdunlock(struct brcmf_bus *bus)
-{
- if (bus->threads_only)
- up(&bus->sdsem);
- else
- spin_unlock_bh(&bus->sdlock);
-}
-
-static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus)
-{
- if (bus->firmware->size < bus->fw_ptr + len)
- len = bus->firmware->size - bus->fw_ptr;
-
- memcpy(buf, &bus->firmware->data[bus->fw_ptr], len);
- bus->fw_ptr += len;
- return len;
-}
-
-MODULE_FIRMWARE(BCM4329_FW_NAME);
-MODULE_FIRMWARE(BCM4329_NV_NAME);
diff --git a/drivers/staging/brcm80211/brcmfmac/sdio_host.h b/drivers/staging/brcm80211/brcmfmac/sdio_host.h
deleted file mode 100644
index d34547215060..000000000000
--- a/drivers/staging/brcm80211/brcmfmac/sdio_host.h
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BRCM_SDH_H_
-#define _BRCM_SDH_H_
-
-#include <linux/skbuff.h>
-extern const uint brcmf_sdio_msglevel;
-
-#define SDIO_FUNC_0 0
-#define SDIO_FUNC_1 1
-#define SDIO_FUNC_2 2
-
-#define SDIOD_FBR_SIZE 0x100
-
-/* io_en */
-#define SDIO_FUNC_ENABLE_1 0x02
-#define SDIO_FUNC_ENABLE_2 0x04
-
-/* io_rdys */
-#define SDIO_FUNC_READY_1 0x02
-#define SDIO_FUNC_READY_2 0x04
-
-/* intr_status */
-#define INTR_STATUS_FUNC1 0x2
-#define INTR_STATUS_FUNC2 0x4
-
-/* Maximum number of I/O funcs */
-#define SDIOD_MAX_IOFUNCS 7
-
-#define SBSDIO_NUM_FUNCTION 3 /* as of sdiod rev 0, supports 3 functions */
-
-/* function 1 miscellaneous registers */
-#define SBSDIO_SPROM_CS 0x10000 /* sprom command and status */
-#define SBSDIO_SPROM_INFO 0x10001 /* sprom info register */
-#define SBSDIO_SPROM_DATA_LOW 0x10002 /* sprom indirect access data byte 0 */
-#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* sprom indirect access data byte 1 */
-#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* sprom indirect access addr byte 0 */
-#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* sprom indirect access addr byte 0 */
-#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu (gpio) output */
-#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu (gpio) enable */
-#define SBSDIO_WATERMARK 0x10008 /* rev < 7, watermark for sdio device */
-#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */
-
-/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */
-#define SBSDIO_FUNC1_SBADDRLOW 0x1000A /* SB Address Window Low (b15) */
-#define SBSDIO_FUNC1_SBADDRMID 0x1000B /* SB Address Window Mid (b23:b16) */
-#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C /* SB Address Window High (b31:b24) */
-#define SBSDIO_FUNC1_FRAMECTRL 0x1000D /* Frame Control (frame term/abort) */
-#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E /* ChipClockCSR (ALP/HT ctl/status) */
-#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F /* SdioPullUp (on cmd, d0-d2) */
-#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 /* Write Frame Byte Count Low */
-#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A /* Write Frame Byte Count High */
-#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B /* Read Frame Byte Count Low */
-#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C /* Read Frame Byte Count High */
-
-#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
-#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */
-
-/* function 1 OCP space */
-#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF /* sb offset addr is <= 15 bits, 32k */
-#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000
-#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 /* with b15, maps to 32-bit SB access */
-
-/* some duplication with sbsdpcmdev.h here */
-/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
-#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
-#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
-#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
-#define SBSDIO_SBWINDOW_MASK 0xffff8000 /* Address bits from SBADDR regs */
-
-#define SDIOH_READ 0 /* Read request */
-#define SDIOH_WRITE 1 /* Write request */
-
-#define SDIOH_DATA_FIX 0 /* Fixed addressing */
-#define SDIOH_DATA_INC 1 /* Incremental addressing */
-
-/* internal return code */
-#define SUCCESS 0
-#define ERROR 1
-
-/* forward declarations */
-struct brcmf_sdio_card;
-
-struct brcmf_sdreg {
- int func;
- int offset;
- int value;
-};
-
-struct sdioh_info {
- struct osl_info *osh; /* osh handler */
- bool client_intr_enabled; /* interrupt connnected flag */
- bool intr_handler_valid; /* client driver interrupt handler valid */
- void (*intr_handler)(void *); /* registered interrupt handler */
- void *intr_handler_arg; /* argument to call interrupt handler */
- u16 intmask; /* Current active interrupts */
- void *sdos_info; /* Pointer to per-OS private data */
-
- uint irq; /* Client irq */
- int intrcount; /* Client interrupts */
- bool sd_blockmode; /* sd_blockmode == false => 64 Byte Cmd 53s. */
- /* Must be on for sd_multiblock to be effective */
- bool use_client_ints; /* If this is false, make sure to restore */
- int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
- u8 num_funcs; /* Supported funcs on client */
- u32 com_cis_ptr;
- u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
- uint max_dma_len;
- uint max_dma_descriptors; /* DMA Descriptors supported by this controller. */
- /* SDDMA_DESCRIPTOR SGList[32]; *//* Scatter/Gather DMA List */
-};
-
-struct brcmf_sdmmc_instance {
- struct sdioh_info *sd;
- struct sdio_func *func[SDIOD_MAX_IOFUNCS];
- u32 host_claimed;
-};
-
-/* Attach and build an interface to the underlying SD host driver.
- * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by
- * brcmf_sdcard.
- * - Returns the sdio card handle and virtual address base for register access.
- * The returned handle should be used in all subsequent calls, but the bcmsh
- * implementation may maintain a single "default" handle (e.g. the first or
- * most recent one) to enable single-instance implementations to pass NULL.
- */
-extern struct brcmf_sdio_card*
-brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq);
-
-/* Detach - freeup resources allocated in attach */
-extern int brcmf_sdcard_detach(struct brcmf_sdio_card *card);
-
-/* Enable/disable SD interrupt */
-extern int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card);
-extern int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card);
-
-/* Register/deregister device interrupt handler. */
-extern int
-brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
- void (*fn)(void *), void *argh);
-
-extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card);
-
-/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
- * fn: function number
- * addr: unmodified SDIO-space address
- * data: data byte to write
- * err: pointer to error code (or NULL)
- */
-extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint func,
- u32 addr, int *err);
-extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint func,
- u32 addr, u8 data, int *err);
-
-/* Read/Write 4bytes from/to cfg space */
-extern u32
-brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
- u32 addr, int *err);
-
-extern void brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card,
- uint fnc_num, u32 addr,
- u32 data, int *err);
-
-/* Read CIS content for specified function.
- * fn: function whose CIS is being requested (0 is common CIS)
- * cis: pointer to memory location to place results
- * length: number of bytes to read
- * Internally, this routine uses the values from the cis base regs (0x9-0xB)
- * to form an SDIO-space address to read the data from.
- */
-extern int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func,
- u8 *cis, uint length);
-
-/* Synchronous access to device (client) core registers via CMD53 to F1.
- * addr: backplane address (i.e. >= regsva from attach)
- * size: register width in bytes (2 or 4)
- * data: data for register write
- */
-extern u32
-brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size);
-
-extern u32
-brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
- u32 data);
-
-/* Indicate if last reg read/write failed */
-extern bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card);
-
-/* Buffer transfer to/from device (client) core via cmd53.
- * fn: function number
- * addr: backplane address (i.e. >= regsva from attach)
- * flags: backplane width, address increment, sync/async
- * buf: pointer to memory data buffer
- * nbytes: number of bytes to transfer to/from buf
- * pkt: pointer to packet associated with buf (if any)
- * complete: callback function for command completion (async only)
- * handle: handle for completion callback (first arg in callback)
- * Returns 0 or error code.
- * NOTE: Async operation is not currently supported.
- */
-extern int
-brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
- uint flags, u8 *buf, uint nbytes, void *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle);
-extern int
-brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
- uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt,
- void (*complete)(void *handle, int status,
- bool sync_waiting),
- void *handle);
-
-/* Flags bits */
-#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */
-#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */
-#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */
-
-/* Pending (non-error) return code */
-#define BCME_PENDING 1
-
-/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
- * rw: read or write (0/1)
- * addr: direct SDIO address
- * buf: pointer to memory data buffer
- * nbytes: number of bytes to transfer to/from buf
- * Returns 0 or error code.
- */
-extern int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
- u8 *buf, uint nbytes);
-
-/* Issue an abort to the specified function */
-extern int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn);
-
-/* Returns the "Device ID" of target device on the SDIO bus. */
-extern int brcmf_sdcard_query_device(struct brcmf_sdio_card *card);
-
-/* Miscellaneous knob tweaker. */
-extern int brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
- void *params, int plen, void *arg, int len,
- bool set);
-
-/* helper functions */
-
-/* callback functions */
-struct brcmf_sdioh_driver {
- /* attach to device */
- void *(*attach) (u16 vend_id, u16 dev_id, u16 bus, u16 slot,
- u16 func, uint bustype, u32 regsva, void *param);
- /* detach from device */
- void (*detach) (void *ch);
-};
-
-struct sdioh_info;
-
-/* platform specific/high level functions */
-extern int brcmf_sdio_function_init(void);
-extern int brcmf_sdio_register(struct brcmf_sdioh_driver *driver);
-extern void brcmf_sdio_unregister(void);
-extern void brcmf_sdio_function_cleanup(void);
-extern int brcmf_sdio_probe(struct device *dev);
-extern int brcmf_sdio_remove(struct device *dev);
-
-/* Function to return current window addr */
-extern u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card);
-
-/* Allocate/init/free per-OS private data */
-extern int brcmf_sdioh_osinit(struct sdioh_info *sd);
-extern void brcmf_sdioh_osfree(struct sdioh_info *sd);
-
-/* Core interrupt enable/disable of device interrupts */
-extern void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd);
-extern void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd);
-
-/* attach, return handler on success, NULL if failed.
- * The handler shall be provided by all subsequent calls. No local cache
- * cfghdl points to the starting address of pci device mapped memory
- */
-extern struct sdioh_info *brcmf_sdioh_attach(void *cfghdl, uint irq);
-extern int brcmf_sdioh_detach(struct sdioh_info *si);
-
-extern int
-brcmf_sdioh_interrupt_register(struct sdioh_info *si,
- void (*sdioh_cb_fn)(void *), void *argh);
-
-extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *si);
-
-/* enable or disable SD interrupt */
-extern int
-brcmf_sdioh_interrupt_set(struct sdioh_info *si, bool enable_disable);
-
-/* read or write one byte using cmd52 */
-extern int
-brcmf_sdioh_request_byte(struct sdioh_info *si, uint rw, uint fnc, uint addr,
- u8 *byte);
-
-/* read or write 2/4 bytes using cmd53 */
-extern int
-brcmf_sdioh_request_word(struct sdioh_info *si, uint cmd_type,
- uint rw, uint fnc, uint addr,
- u32 *word, uint nbyte);
-
-/* read or write any buffer using cmd53 */
-extern int
-brcmf_sdioh_request_buffer(struct sdioh_info *si, uint pio_dma,
- uint fix_inc, uint rw, uint fnc_num,
- u32 addr, uint regwidth,
- u32 buflen, u8 *buffer, struct sk_buff *pkt);
-
-/* get cis data */
-extern int
-brcmf_sdioh_cis_read(struct sdioh_info *si, uint fuc, u8 *cis, u32 length);
-
-extern int
-brcmf_sdioh_cfg_read(struct sdioh_info *si, uint fuc, u32 addr, u8 *data);
-extern int
-brcmf_sdioh_cfg_write(struct sdioh_info *si, uint fuc, u32 addr, u8 *data);
-
-/* handle iovars */
-extern int brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
- void *params, int plen, void *arg, int len, bool set);
-
-/* Issue abort to the specified function and clear controller as needed */
-extern int brcmf_sdioh_abort(struct sdioh_info *si, uint fnc);
-
-/* Watchdog timer interface for pm ops */
-extern void brcmf_sdio_wdtmr_enable(bool enable);
-
-extern uint sd_msglevel; /* Debug message level */
-
-extern struct brcmf_sdmmc_instance *gInstance;
-
-#endif /* _BRCM_SDH_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/alloc.c b/drivers/staging/brcm80211/brcmsmac/alloc.c
deleted file mode 100644
index 7f8dd7b396bf..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/alloc.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <brcmu_utils.h>
-#include "types.h"
-#include "pub.h"
-#include "main.h"
-#include "alloc.h"
-
-static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit);
-static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg);
-static struct brcms_pub *brcms_c_pub_malloc(uint unit,
- uint *err, uint devid);
-static void brcms_c_pub_mfree(struct brcms_pub *pub);
-static void brcms_c_tunables_init(struct brcms_tunables *tunables, uint devid);
-
-static void brcms_c_tunables_init(struct brcms_tunables *tunables, uint devid)
-{
- tunables->ntxd = NTXD;
- tunables->nrxd = NRXD;
- tunables->rxbufsz = RXBUFSZ;
- tunables->nrxbufpost = NRXBUFPOST;
- tunables->maxscb = MAXSCB;
- tunables->ampdunummpdu = AMPDU_NUM_MPDU;
- tunables->maxpktcb = MAXPKTCB;
- tunables->maxucodebss = BRCMS_MAX_UCODE_BSS;
- tunables->maxucodebss4 = BRCMS_MAX_UCODE_BSS4;
- tunables->maxbss = MAXBSS;
- tunables->datahiwat = BRCMS_DATAHIWAT;
- tunables->ampdudatahiwat = BRCMS_AMPDUDATAHIWAT;
- tunables->rxbnd = RXBND;
- tunables->txsbnd = TXSBND;
-}
-
-static struct brcms_pub *brcms_c_pub_malloc(uint unit, uint *err, uint devid)
-{
- struct brcms_pub *pub;
-
- pub = kzalloc(sizeof(struct brcms_pub), GFP_ATOMIC);
- if (pub == NULL) {
- *err = 1001;
- goto fail;
- }
-
- pub->tunables = kzalloc(sizeof(struct brcms_tunables), GFP_ATOMIC);
- if (pub->tunables == NULL) {
- *err = 1028;
- goto fail;
- }
-
- /* need to init the tunables now */
- brcms_c_tunables_init(pub->tunables, devid);
-
- pub->multicast = kzalloc(ETH_ALEN * MAXMULTILIST, GFP_ATOMIC);
- if (pub->multicast == NULL) {
- *err = 1003;
- goto fail;
- }
-
- return pub;
-
- fail:
- brcms_c_pub_mfree(pub);
- return NULL;
-}
-
-static void brcms_c_pub_mfree(struct brcms_pub *pub)
-{
- if (pub == NULL)
- return;
-
- kfree(pub->multicast);
- kfree(pub->tunables);
- kfree(pub);
-}
-
-static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit)
-{
- struct brcms_bss_cfg *cfg;
-
- cfg = kzalloc(sizeof(struct brcms_bss_cfg), GFP_ATOMIC);
- if (cfg == NULL)
- goto fail;
-
- cfg->current_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
- if (cfg->current_bss == NULL)
- goto fail;
-
- return cfg;
-
- fail:
- brcms_c_bsscfg_mfree(cfg);
- return NULL;
-}
-
-static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg)
-{
- if (cfg == NULL)
- return;
-
- kfree(cfg->maclist);
- kfree(cfg->current_bss);
- kfree(cfg);
-}
-
-static void brcms_c_bsscfg_ID_assign(struct brcms_c_info *wlc,
- struct brcms_bss_cfg *bsscfg)
-{
- bsscfg->ID = wlc->next_bsscfg_ID;
- wlc->next_bsscfg_ID++;
-}
-
-/*
- * The common driver entry routine. Error codes should be unique
- */
-struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err, uint devid)
-{
- struct brcms_c_info *wlc;
-
- wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC);
- if (wlc == NULL) {
- *err = 1002;
- goto fail;
- }
-
- /* allocate struct brcms_c_pub state structure */
- wlc->pub = brcms_c_pub_malloc(unit, err, devid);
- if (wlc->pub == NULL) {
- *err = 1003;
- goto fail;
- }
- wlc->pub->wlc = wlc;
-
- /* allocate struct brcms_hardware state structure */
-
- wlc->hw = kzalloc(sizeof(struct brcms_hardware), GFP_ATOMIC);
- if (wlc->hw == NULL) {
- *err = 1005;
- goto fail;
- }
- wlc->hw->wlc = wlc;
-
- wlc->hw->bandstate[0] =
- kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC);
- if (wlc->hw->bandstate[0] == NULL) {
- *err = 1006;
- goto fail;
- } else {
- int i;
-
- for (i = 1; i < MAXBANDS; i++) {
- wlc->hw->bandstate[i] = (struct brcms_hw_band *)
- ((unsigned long)wlc->hw->bandstate[0] +
- (sizeof(struct brcms_hw_band) * i));
- }
- }
-
- wlc->modulecb =
- kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC);
- if (wlc->modulecb == NULL) {
- *err = 1009;
- goto fail;
- }
-
- wlc->default_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
- if (wlc->default_bss == NULL) {
- *err = 1010;
- goto fail;
- }
-
- wlc->cfg = brcms_c_bsscfg_malloc(unit);
- if (wlc->cfg == NULL) {
- *err = 1011;
- goto fail;
- }
- brcms_c_bsscfg_ID_assign(wlc, wlc->cfg);
-
- wlc->wsec_def_keys[0] =
- kzalloc(sizeof(struct wsec_key) * BRCMS_DEFAULT_KEYS,
- GFP_ATOMIC);
- if (wlc->wsec_def_keys[0] == NULL) {
- *err = 1015;
- goto fail;
- } else {
- int i;
- for (i = 1; i < BRCMS_DEFAULT_KEYS; i++) {
- wlc->wsec_def_keys[i] = (struct wsec_key *)
- ((unsigned long)wlc->wsec_def_keys[0] +
- (sizeof(struct wsec_key) * i));
- }
- }
-
- wlc->protection = kzalloc(sizeof(struct brcms_protection),
- GFP_ATOMIC);
- if (wlc->protection == NULL) {
- *err = 1016;
- goto fail;
- }
-
- wlc->stf = kzalloc(sizeof(struct brcms_stf), GFP_ATOMIC);
- if (wlc->stf == NULL) {
- *err = 1017;
- goto fail;
- }
-
- wlc->bandstate[0] =
- kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC);
- if (wlc->bandstate[0] == NULL) {
- *err = 1025;
- goto fail;
- } else {
- int i;
-
- for (i = 1; i < MAXBANDS; i++) {
- wlc->bandstate[i] = (struct brcms_band *)
- ((unsigned long)wlc->bandstate[0]
- + (sizeof(struct brcms_band)*i));
- }
- }
-
- wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC);
- if (wlc->corestate == NULL) {
- *err = 1026;
- goto fail;
- }
-
- wlc->corestate->macstat_snapshot =
- kzalloc(sizeof(struct macstat), GFP_ATOMIC);
- if (wlc->corestate->macstat_snapshot == NULL) {
- *err = 1027;
- goto fail;
- }
-
- return wlc;
-
- fail:
- brcms_c_detach_mfree(wlc);
- return NULL;
-}
-
-void brcms_c_detach_mfree(struct brcms_c_info *wlc)
-{
- if (wlc == NULL)
- return;
-
- brcms_c_bsscfg_mfree(wlc->cfg);
- brcms_c_pub_mfree(wlc->pub);
- kfree(wlc->modulecb);
- kfree(wlc->default_bss);
- kfree(wlc->wsec_def_keys[0]);
- kfree(wlc->protection);
- kfree(wlc->stf);
- kfree(wlc->bandstate[0]);
- kfree(wlc->corestate->macstat_snapshot);
- kfree(wlc->corestate);
- kfree(wlc->hw->bandstate[0]);
- kfree(wlc->hw);
-
- /* free the wlc */
- kfree(wlc);
- wlc = NULL;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/bmac.c b/drivers/staging/brcm80211/brcmsmac/bmac.c
deleted file mode 100644
index b25c51705566..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/bmac.c
+++ /dev/null
@@ -1,3593 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/pci.h>
-#include <net/mac80211.h>
-
-#include <brcm_hw_ids.h>
-#include <aiutils.h>
-#include <chipcommon.h>
-#include "types.h"
-#include "rate.h"
-#include "phy/phy_hal.h"
-#include "channel.h"
-#include "main.h"
-#include "ucode_loader.h"
-#include "mac80211_if.h"
-#include "bmac.h"
-
-#define TIMER_INTERVAL_WATCHDOG_BMAC 1000 /* watchdog timer, in unit of ms */
-
-#define SYNTHPU_DLY_APHY_US 3700 /* a phy synthpu_dly time in us */
-#define SYNTHPU_DLY_BPHY_US 1050 /* b/g phy synthpu_dly time in us, default */
-#define SYNTHPU_DLY_NPHY_US 2048 /* n phy REV3 synthpu_dly time in us, default */
-#define SYNTHPU_DLY_LPPHY_US 300 /* lpphy synthpu_dly time in us */
-
-#define SYNTHPU_DLY_PHY_US_QT 100 /* QT synthpu_dly time in us */
-
-#ifndef BMAC_DUP_TO_REMOVE
-
-#define ANTCNT 10 /* vanilla M_MAX_ANTCNT value */
-
-#endif /* BMAC_DUP_TO_REMOVE */
-
-#define DMAREG(wlc_hw, direction, fifonum) \
- ((direction == DMA_TX) ? \
- (void *)&(wlc_hw->regs->fifo64regs[fifonum].dmaxmt) : \
- (void *)&(wlc_hw->regs->fifo64regs[fifonum].dmarcv))
-
-#define APHY_SLOT_TIME 9
-#define BPHY_SLOT_TIME 20
-
-/*
- * The following table lists the buffer memory allocated to xmt fifos in HW.
- * the size is in units of 256bytes(one block), total size is HW dependent
- * ucode has default fifo partition, sw can overwrite if necessary
- *
- * This is documented in twiki under the topic UcodeTxFifo. Please ensure
- * the twiki is updated before making changes.
- */
-
-#define XMTFIFOTBL_STARTREV 20 /* Starting corerev for the fifo size table */
-
-static u16 xmtfifo_sz[][NFIFO] = {
- {20, 192, 192, 21, 17, 5}, /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
- {9, 58, 22, 14, 14, 5}, /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
- {20, 192, 192, 21, 17, 5}, /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
- {20, 192, 192, 21, 17, 5}, /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
- {9, 58, 22, 14, 14, 5}, /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
-};
-
-static void brcms_b_clkctl_clk(struct brcms_hardware *wlc, uint mode);
-static void brcms_b_coreinit(struct brcms_c_info *wlc);
-
-/* used by wlc_wakeucode_init() */
-static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
- const struct d11init *inits);
-static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[],
- const uint nbytes);
-static void brcms_ucode_download(struct brcms_hardware *wlc);
-static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw);
-
-/* used by brcms_c_dpc() */
-static bool brcms_b_dotxstatus(struct brcms_hardware *wlc,
- struct tx_status *txs, u32 s2);
-static bool brcms_b_txstatus(struct brcms_hardware *wlc, bool bound,
- bool *fatal);
-static bool brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound);
-
-/* used by brcms_c_down() */
-static void brcms_c_flushqueues(struct brcms_c_info *wlc);
-
-static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs);
-static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw);
-static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw);
-static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw,
- uint tx_fifo);
-static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
- uint tx_fifo);
-static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
- uint tx_fifo);
-
-/* Low Level Prototypes */
-static int brcms_b_bandtype(struct brcms_hardware *wlc_hw);
-static void brcms_b_info_init(struct brcms_hardware *wlc_hw);
-static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want);
-static u16 brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset,
- u32 sel);
-static void brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset,
- u16 v, u32 sel);
-static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk);
-static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme);
-static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw);
-static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw);
-static bool brcms_c_validboardtype(struct brcms_hardware *wlc);
-static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw);
-static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw);
-static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw);
-static void brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init);
-static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw);
-static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool want,
- mbool flags);
-static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw);
-static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw);
-static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc);
-static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask);
-static void brcms_c_gpio_init(struct brcms_c_info *wlc);
-static void brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw,
- void *bcn, int len);
-static void brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw,
- void *bcn, int len);
-static void brcms_b_bsinit(struct brcms_c_info *wlc, chanspec_t chanspec);
-static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit);
-static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
- chanspec_t chanspec);
-static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
- bool shortslot);
-static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw);
-static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw,
- u8 rate);
-
-/* === Low Level functions === */
-
-void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
-{
- wlc_hw->shortslot = shortslot;
-
- if (BAND_2G(brcms_b_bandtype(wlc_hw)) && wlc_hw->up) {
- brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
- brcms_b_update_slot_timing(wlc_hw, shortslot);
- brcms_c_enable_mac(wlc_hw->wlc);
- }
-}
-
-/*
- * Update the slot timing for standard 11b/g (20us slots)
- * or shortslot 11g (9us slots)
- * The PSM needs to be suspended for this call.
- */
-static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
- bool shortslot)
-{
- d11regs_t *regs;
-
- regs = wlc_hw->regs;
-
- if (shortslot) {
- /* 11g short slot: 11a timing */
- W_REG(&regs->ifs_slot, 0x0207); /* APHY_SLOT_TIME */
- brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
- } else {
- /* 11g long slot: 11b timing */
- W_REG(&regs->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */
- brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
- }
-}
-
-static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
-{
- struct wiphy *wiphy = wlc_hw->wlc->wiphy;
-
- /* 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 (BRCMS_ISNPHY(wlc_hw->band)) {
- brcms_c_write_inits(wlc_hw, d11n0bsinitvals16);
- } else {
- wiphy_err(wiphy, "%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,
- d11lcn0bsinitvals24);
- } else
- wiphy_err(wiphy, "%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);
- }
- }
-}
-
-/* switch to new band but leave it inactive */
-static u32 brcms_c_setband_inact(struct brcms_c_info *wlc,
- uint bandunit)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- u32 macintmask;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
-
- /* disable interrupts */
- macintmask = brcms_intrsoff(wlc->wl);
-
- /* radio off */
- wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
-
- brcms_b_core_phy_clk(wlc_hw, OFF);
-
- brcms_c_setxband(wlc_hw, bandunit);
-
- return macintmask;
-}
-
-/* Process received frames */
-/*
- * Return true if more frames need to be processed. false otherwise.
- * Param 'bound' indicates max. # frames to process before break out.
- */
-static bool
-brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
-{
- struct sk_buff *p;
- struct sk_buff *head = NULL;
- struct sk_buff *tail = NULL;
- uint n = 0;
- uint bound_limit = bound ? wlc_hw->wlc->pub->tunables->rxbnd : -1;
- struct brcms_d11rxhdr *wlc_rxhdr = NULL;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
- /* gather received frames */
- while ((p = dma_rx(wlc_hw->di[fifo]))) {
-
- if (!tail)
- head = tail = p;
- else {
- tail->prev = p;
- tail = p;
- }
-
- /* !give others some time to run! */
- if (++n >= bound_limit)
- break;
- }
-
- /* post more rbufs */
- dma_rxfill(wlc_hw->di[fifo]);
-
- /* process each frame */
- while ((p = head) != NULL) {
- head = head->prev;
- p->prev = NULL;
-
- wlc_rxhdr = (struct brcms_d11rxhdr *) p->data;
-
- /* compute the RSSI from d11rxhdr and record it in wlc_rxd11hr */
- wlc_phy_rssi_compute(wlc_hw->band->pi, wlc_rxhdr);
-
- brcms_c_recv(wlc_hw->wlc, p);
- }
-
- return n >= bound_limit;
-}
-
-/* second-level interrupt processing
- * Return true if another dpc needs to be re-scheduled. false otherwise.
- * Param 'bounded' indicates if applicable loops should be bounded.
- */
-bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
-{
- u32 macintstatus;
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs = wlc_hw->regs;
- bool fatal = false;
- struct wiphy *wiphy = wlc->wiphy;
-
- if (DEVICEREMOVED(wlc)) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
- __func__);
- brcms_down(wlc->wl);
- return false;
- }
-
- /* grab and clear the saved software intstatus bits */
- macintstatus = wlc->macintstatus;
- wlc->macintstatus = 0;
-
- BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
- wlc_hw->unit, macintstatus);
-
- WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
-
- /* BCN template is available */
- /* ZZZ: Use AP_ACTIVE ? */
- if (AP_ENAB(wlc->pub) && (!APSTA_ENAB(wlc->pub))
- && (macintstatus & MI_BCNTPL)) {
- brcms_c_update_beacon(wlc);
- }
-
- /* tx status */
- if (macintstatus & MI_TFS) {
- if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
- wlc->macintstatus |= MI_TFS;
- if (fatal) {
- wiphy_err(wiphy, "MI_TFS: fatal\n");
- goto fatal;
- }
- }
-
- if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
- brcms_c_tbtt(wlc);
-
- /* ATIM window end */
- if (macintstatus & MI_ATIMWINEND) {
- BCMMSG(wlc->wiphy, "end of ATIM window\n");
- OR_REG(&regs->maccommand, wlc->qvalid);
- wlc->qvalid = 0;
- }
-
- /* received data or control frame, MI_DMAINT is indication of RX_FIFO interrupt */
- if (macintstatus & MI_DMAINT)
- if (brcms_b_recv(wlc_hw, RX_FIFO, bounded))
- wlc->macintstatus |= MI_DMAINT;
-
- /* TX FIFO suspend/flush completion */
- if (macintstatus & MI_TXSTOP)
- brcms_b_tx_fifo_suspended(wlc_hw, TX_DATA_FIFO);
-
- /* noise sample collected */
- if (macintstatus & MI_BG_NOISE) {
- wlc_phy_noise_sample_intr(wlc_hw->band->pi);
- }
-
- if (macintstatus & MI_GP0) {
- wiphy_err(wiphy, "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",
- __func__, wlc_hw->sih->chip,
- wlc_hw->sih->chiprev);
- /* big hammer */
- brcms_init(wlc->wl);
- }
-
- /* gptimer timeout */
- if (macintstatus & MI_TO) {
- W_REG(&regs->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_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;
-
- fatal:
- brcms_init(wlc->wl);
- return wlc->macintstatus != 0;
-}
-
-/* common low-level watchdog code */
-void brcms_b_watchdog(void *arg)
-{
- struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
- struct brcms_hardware *wlc_hw = wlc->hw;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- if (!wlc_hw->up)
- return;
-
- /* increment second count */
- wlc_hw->now++;
-
- /* Check for FIFO error interrupts */
- brcms_b_fifoerrors(wlc_hw);
-
- /* make sure RX dma has buffers */
- dma_rxfill(wlc->hw->di[RX_FIFO]);
-
- wlc_phy_watchdog(wlc_hw->band->pi);
-}
-
-void
-brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, chanspec_t chanspec,
- bool mute, struct txpwr_limits *txpwr)
-{
- uint bandunit;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec);
-
- wlc_hw->chanspec = chanspec;
-
- /* Switch bands if necessary */
- if (NBANDS_HW(wlc_hw) > 1) {
- bandunit = CHSPEC_BANDUNIT(chanspec);
- if (wlc_hw->band->bandunit != bandunit) {
- /* brcms_b_setband disables other bandunit,
- * use light band switch if not up yet
- */
- if (wlc_hw->up) {
- wlc_phy_chanspec_radio_set(wlc_hw->
- bandstate[bandunit]->
- pi, chanspec);
- brcms_b_setband(wlc_hw, bandunit, chanspec);
- } else {
- brcms_c_setxband(wlc_hw, bandunit);
- }
- }
- }
-
- wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
-
- if (!wlc_hw->up) {
- if (wlc_hw->clk)
- wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
- chanspec);
- wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
- } else {
- wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
- wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
-
- /* Update muting of the channel */
- brcms_b_mute(wlc_hw, mute, 0);
- }
-}
-
-int brcms_b_state_get(struct brcms_hardware *wlc_hw,
- struct brcms_b_state *state)
-{
- state->machwcap = wlc_hw->machwcap;
-
- return 0;
-}
-
-static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
-{
- uint i;
- char name[8];
- /* ucode host flag 2 needed for pio mode, independent of band and fifo */
- u16 pio_mhf2 = 0;
- struct brcms_hardware *wlc_hw = wlc->hw;
- uint unit = wlc_hw->unit;
- struct brcms_tunables *tune = wlc->pub->tunables;
- struct wiphy *wiphy = wlc->wiphy;
-
- /* name and offsets for dma_attach */
- snprintf(name, sizeof(name), "wl%d", unit);
-
- if (wlc_hw->di[0] == 0) { /* Init FIFOs */
- uint addrwidth;
- int dma_attach_err = 0;
- /* Find out the DMA addressing capability and let OS know
- * All the channels within one DMA core have 'common-minimum' same
- * capability
- */
- addrwidth =
- dma_addrwidth(wlc_hw->sih, DMAREG(wlc_hw, DMA_TX, 0));
-
- if (!wl_alloc_dma_resources(wlc_hw->wlc->wl, addrwidth)) {
- wiphy_err(wiphy, "wl%d: wlc_attach: alloc_dma_"
- "resources failed\n", unit);
- return false;
- }
-
- /*
- * FIFO 0
- * 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,
- (wme ? DMAREG(wlc_hw, DMA_TX, 0) :
- NULL), DMAREG(wlc_hw, DMA_RX, 0),
- (wme ? tune->ntxd : 0), tune->nrxd,
- tune->rxbufsz, -1, tune->nrxbufpost,
- BRCMS_HWRXOFF, &brcm_msg_level);
- dma_attach_err |= (NULL == wlc_hw->di[0]);
-
- /*
- * FIFO 1
- * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
- * (legacy) TX_DATA_FIFO (TX data packets)
- * RX: UNUSED
- */
- wlc_hw->di[1] = dma_attach(name, wlc_hw->sih,
- DMAREG(wlc_hw, DMA_TX, 1), NULL,
- tune->ntxd, 0, 0, -1, 0, 0,
- &brcm_msg_level);
- dma_attach_err |= (NULL == wlc_hw->di[1]);
-
- /*
- * FIFO 2
- * TX: TX_AC_VI_FIFO (TX AC Video data packets)
- * RX: UNUSED
- */
- wlc_hw->di[2] = dma_attach(name, wlc_hw->sih,
- DMAREG(wlc_hw, DMA_TX, 2), NULL,
- tune->ntxd, 0, 0, -1, 0, 0,
- &brcm_msg_level);
- 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,
- DMAREG(wlc_hw, DMA_TX, 3),
- NULL, tune->ntxd, 0, 0, -1,
- 0, 0, &brcm_msg_level);
- 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);
- return false;
- }
-
- /* get pointer to dma engine tx flow control variable */
- for (i = 0; i < NFIFO; i++)
- if (wlc_hw->di[i])
- wlc_hw->txavail[i] =
- (uint *) dma_getvar(wlc_hw->di[i],
- "&txavail");
- }
-
- /* initial ucode host flags */
- brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
-
- return true;
-}
-
-static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw)
-{
- uint j;
-
- for (j = 0; j < NFIFO; j++) {
- if (wlc_hw->di[j]) {
- dma_detach(wlc_hw->di[j]);
- wlc_hw->di[j] = NULL;
- }
- }
-}
-
-/* low level attach
- * run backplane attach, init nvram
- * run phy attach
- * initialize software state for each core and band
- * put the whole chip in reset(driver down state), no clock
- */
-int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, uint unit,
- bool piomode, void *regsva, uint bustype, void *btparam)
-{
- struct brcms_hardware *wlc_hw;
- d11regs_t *regs;
- char *macaddr = NULL;
- char *vars;
- uint err = 0;
- uint j;
- bool wme = false;
- struct shared_phy_params sha_params;
- struct wiphy *wiphy = wlc->wiphy;
-
- BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor,
- device);
-
- wme = true;
-
- wlc_hw = wlc->hw;
- wlc_hw->wlc = wlc;
- wlc_hw->unit = unit;
- wlc_hw->band = wlc_hw->bandstate[0];
- wlc_hw->_piomode = piomode;
-
- /* populate struct brcms_hardware with default values */
- brcms_b_info_init(wlc_hw);
-
- /*
- * Do the hardware portion of the attach.
- * Also initialize software state that depends on the particular hardware
- * we are running.
- */
- wlc_hw->sih = ai_attach(regsva, bustype, btparam,
- &wlc_hw->vars, &wlc_hw->vars_size);
- if (wlc_hw->sih == NULL) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n",
- unit);
- err = 11;
- goto fail;
- }
- vars = wlc_hw->vars;
-
- /*
- * Get vendid/devid nvram overwrites, which could be different
- * than those the BIOS recognizes for devices on PCMCIA_BUS,
- * SDIO_BUS, and SROMless devices on PCI_BUS.
- */
-#ifdef BCMBUSTYPE
- bustype = BCMBUSTYPE;
-#endif
- if (bustype != SI_BUS) {
- char *var;
-
- var = getvar(vars, "vendid");
- if (var) {
- vendor = (u16) simple_strtoul(var, NULL, 0);
- wiphy_err(wiphy, "Overriding vendor id = 0x%x\n",
- vendor);
- }
- var = getvar(vars, "devid");
- if (var) {
- u16 devid = (u16) simple_strtoul(var, NULL, 0);
- if (devid != 0xffff) {
- device = devid;
- wiphy_err(wiphy, "Overriding device id = 0x%x"
- "\n", device);
- }
- }
-
- /* verify again the device is supported */
- if (!brcms_c_chipmatch(vendor, device)) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported "
- "vendor/device (0x%x/0x%x)\n",
- unit, vendor, device);
- err = 12;
- goto fail;
- }
- }
-
- wlc_hw->vendorid = vendor;
- wlc_hw->deviceid = device;
-
- /* set bar0 window to point at D11 core */
- wlc_hw->regs = (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
- wlc_hw->corerev = ai_corerev(wlc_hw->sih);
-
- regs = wlc_hw->regs;
-
- wlc->regs = wlc_hw->regs;
-
- /* validate chip, chiprev and corerev */
- if (!brcms_c_isgoodchip(wlc_hw)) {
- err = 13;
- goto fail;
- }
-
- /* initialize power control registers */
- ai_clkctl_init(wlc_hw->sih);
-
- /* request fastclock and force fastclock for the rest of attach
- * bring the d11 core out of reset.
- * For PMU chips, the first wlc_clkctl_clk is no-op since core-clk is still false;
- * But it will be called again inside wlc_corereset, after d11 is out of reset.
- */
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
- brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
-
- if (!brcms_b_validate_chip_access(wlc_hw)) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access "
- "failed\n", unit);
- err = 14;
- goto fail;
- }
-
- /* get the board rev, used just below */
- j = getintvar(vars, "boardrev");
- /* promote srom boardrev of 0xFF to 1 */
- if (j == BOARDREV_PROMOTABLE)
- j = BOARDREV_PROMOTED;
- wlc_hw->boardrev = (u16) j;
- if (!brcms_c_validboardtype(wlc_hw)) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom "
- "board type (0x%x)" " or revision level (0x%x)\n",
- unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
- err = 15;
- goto fail;
- }
- wlc_hw->sromrev = (u8) getintvar(vars, "sromrev");
- wlc_hw->boardflags = (u32) getintvar(vars, "boardflags");
- wlc_hw->boardflags2 = (u32) getintvar(vars, "boardflags2");
-
- if (wlc_hw->boardflags & BFL_NOPLLDOWN)
- brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED);
-
- if ((wlc_hw->sih->bustype == PCI_BUS)
- && (ai_pci_war16165(wlc_hw->sih)))
- wlc->war16165 = true;
-
- /* check device id(srom, nvram etc.) to set bands */
- if (wlc_hw->deviceid == BCM43224_D11N_ID ||
- wlc_hw->deviceid == BCM43224_D11N_ID_VEN1) {
- /* Dualband boards */
- wlc_hw->_nbands = 2;
- } else
- wlc_hw->_nbands = 1;
-
- if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
- wlc_hw->_nbands = 1;
-
- /* BMAC_NOTE: remove init of pub values when brcms_c_attach()
- * unconditionally does the init of these values
- */
- wlc->vendorid = wlc_hw->vendorid;
- wlc->deviceid = wlc_hw->deviceid;
- wlc->pub->sih = wlc_hw->sih;
- wlc->pub->corerev = wlc_hw->corerev;
- wlc->pub->sromrev = wlc_hw->sromrev;
- wlc->pub->boardrev = wlc_hw->boardrev;
- wlc->pub->boardflags = wlc_hw->boardflags;
- wlc->pub->boardflags2 = wlc_hw->boardflags2;
- wlc->pub->_nbands = wlc_hw->_nbands;
-
- wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
-
- if (wlc_hw->physhim == NULL) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach "
- "failed\n", unit);
- err = 25;
- goto fail;
- }
-
- /* pass all the parameters to wlc_phy_shared_attach in one struct */
- sha_params.sih = wlc_hw->sih;
- sha_params.physhim = wlc_hw->physhim;
- sha_params.unit = unit;
- sha_params.corerev = wlc_hw->corerev;
- sha_params.vars = vars;
- sha_params.vid = wlc_hw->vendorid;
- sha_params.did = wlc_hw->deviceid;
- sha_params.chip = wlc_hw->sih->chip;
- sha_params.chiprev = wlc_hw->sih->chiprev;
- sha_params.chippkg = wlc_hw->sih->chippkg;
- sha_params.sromrev = wlc_hw->sromrev;
- sha_params.boardtype = wlc_hw->sih->boardtype;
- sha_params.boardrev = wlc_hw->boardrev;
- sha_params.boardvendor = wlc_hw->sih->boardvendor;
- sha_params.boardflags = wlc_hw->boardflags;
- sha_params.boardflags2 = wlc_hw->boardflags2;
- sha_params.bustype = wlc_hw->sih->bustype;
- sha_params.buscorerev = wlc_hw->sih->buscorerev;
-
- /* alloc and save pointer to shared phy state area */
- wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
- if (!wlc_hw->phy_sh) {
- err = 16;
- goto fail;
- }
-
- /* initialize software state for each core and band */
- for (j = 0; j < NBANDS_HW(wlc_hw); j++) {
- /*
- * band0 is always 2.4Ghz
- * band1, if present, is 5Ghz
- */
-
- /* So if this is a single band 11a card, use band 1 */
- if (IS_SINGLEBAND_5G(wlc_hw->deviceid))
- j = BAND_5G_INDEX;
-
- brcms_c_setxband(wlc_hw, j);
-
- wlc_hw->band->bandunit = j;
- wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
- wlc->band->bandunit = j;
- wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
- wlc->core->coreidx = ai_coreidx(wlc_hw->sih);
-
- wlc_hw->machwcap = R_REG(&regs->machwcap);
- wlc_hw->machwcap_backup = wlc_hw->machwcap;
-
- /* init tx fifo size */
- wlc_hw->xmtfifo_sz =
- xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
-
- /* Get a phy for this band */
- wlc_hw->band->pi = wlc_phy_attach(wlc_hw->phy_sh,
- (void *)regs, brcms_b_bandtype(wlc_hw), vars,
- wlc->wiphy);
- if (wlc_hw->band->pi == NULL) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_"
- "attach failed\n", unit);
- err = 17;
- goto fail;
- }
-
- wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
-
- wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
- &wlc_hw->band->phyrev,
- &wlc_hw->band->radioid,
- &wlc_hw->band->radiorev);
- wlc_hw->band->abgphy_encore =
- wlc_phy_get_encore(wlc_hw->band->pi);
- wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
- wlc_hw->band->core_flags =
- wlc_phy_get_coreflags(wlc_hw->band->pi);
-
- /* verify good phy_type & supported phy revision */
- if (BRCMS_ISNPHY(wlc_hw->band)) {
- if (NCONF_HAS(wlc_hw->band->phyrev))
- goto good_phy;
- else
- goto bad_phy;
- } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
- if (LCNCONF_HAS(wlc_hw->band->phyrev))
- goto good_phy;
- else
- goto bad_phy;
- } else {
- bad_phy:
- wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported "
- "phy type/rev (%d/%d)\n", unit,
- wlc_hw->band->phytype, wlc_hw->band->phyrev);
- err = 18;
- goto fail;
- }
-
- good_phy:
- /* BMAC_NOTE: wlc->band->pi should not be set below and should be done in the
- * high level attach. However we can not make that change until all low level access
- * is changed to wlc_hw->band->pi. Instead do the wlc->band->pi init below, keeping
- * wlc_hw->band->pi as well for incremental update of low level fns, and cut over
- * low only init when all fns updated.
- */
- wlc->band->pi = wlc_hw->band->pi;
- wlc->band->phytype = wlc_hw->band->phytype;
- wlc->band->phyrev = wlc_hw->band->phyrev;
- wlc->band->radioid = wlc_hw->band->radioid;
- wlc->band->radiorev = wlc_hw->band->radiorev;
-
- /* default contention windows size limits */
- wlc_hw->band->CWmin = APHY_CWMIN;
- wlc_hw->band->CWmax = PHY_CWMAX;
-
- if (!brcms_b_attach_dmapio(wlc, j, wme)) {
- err = 19;
- goto fail;
- }
- }
-
- /* disable core to match driver "down" state */
- brcms_c_coredisable(wlc_hw);
-
- /* Match driver "down" state */
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_down(wlc_hw->sih);
-
- /* register sb interrupt callback functions */
- ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff,
- (void *)brcms_c_wlintrsrestore, NULL, wlc);
-
- /* turn off pll and xtal to match driver "down" state */
- brcms_b_xtal(wlc_hw, OFF);
-
- /* *********************************************************************
- * The hardware is in the DOWN state at this point. D11 core
- * or cores are in reset with clocks off, and the board PLLs
- * are off if possible.
- *
- * Beyond this point, wlc->sbclk == false and chip registers
- * should not be touched.
- *********************************************************************
- */
-
- /* init etheraddr state variables */
- macaddr = brcms_c_get_macaddr(wlc_hw);
- if (macaddr == NULL) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n",
- unit);
- err = 21;
- goto fail;
- }
- brcmu_ether_atoe(macaddr, wlc_hw->etheraddr);
- if (is_broadcast_ether_addr(wlc_hw->etheraddr) ||
- is_zero_ether_addr(wlc_hw->etheraddr)) {
- wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n",
- unit, macaddr);
- err = 22;
- goto fail;
- }
-
- BCMMSG(wlc->wiphy,
- "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
- wlc_hw->deviceid, wlc_hw->_nbands,
- wlc_hw->sih->boardtype, macaddr);
-
- return err;
-
- fail:
- wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit,
- err);
- return err;
-}
-
-/*
- * Initialize brcms_c_info default values ...
- * may get overrides later in this function
- * BMAC_NOTES, move low out and resolve the dangling ones
- */
-static void brcms_b_info_init(struct brcms_hardware *wlc_hw)
-{
- struct brcms_c_info *wlc = wlc_hw->wlc;
-
- /* set default sw macintmask value */
- wlc->defmacintmask = DEF_MACINTMASK;
-
- /* various 802.11g modes */
- wlc_hw->shortslot = false;
-
- wlc_hw->SFBL = RETRY_SHORT_FB;
- wlc_hw->LFBL = RETRY_LONG_FB;
-
- /* default mac retry limits */
- wlc_hw->SRL = RETRY_SHORT_DEF;
- wlc_hw->LRL = RETRY_LONG_DEF;
- wlc_hw->chanspec = CH20MHZ_CHSPEC(1);
-}
-
-/*
- * low level detach
- */
-int brcms_b_detach(struct brcms_c_info *wlc)
-{
- uint i;
- struct brcms_hw_band *band;
- struct brcms_hardware *wlc_hw = wlc->hw;
- int callbacks;
-
- callbacks = 0;
-
- if (wlc_hw->sih) {
- /* detach interrupt sync mechanism since interrupt is disabled and per-port
- * interrupt object may has been freed. this must be done before sb core switch
- */
- ai_deregister_intr_callback(wlc_hw->sih);
-
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_sleep(wlc_hw->sih);
- }
-
- brcms_b_detach_dmapio(wlc_hw);
-
- band = wlc_hw->band;
- for (i = 0; i < NBANDS_HW(wlc_hw); i++) {
- if (band->pi) {
- /* Detach this band's phy */
- wlc_phy_detach(band->pi);
- band->pi = NULL;
- }
- band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
- }
-
- /* Free shared phy state */
- kfree(wlc_hw->phy_sh);
-
- wlc_phy_shim_detach(wlc_hw->physhim);
-
- /* free vars */
- kfree(wlc_hw->vars);
- wlc_hw->vars = NULL;
-
- if (wlc_hw->sih) {
- ai_detach(wlc_hw->sih);
- wlc_hw->sih = NULL;
- }
-
- return callbacks;
-
-}
-
-void brcms_b_reset(struct brcms_hardware *wlc_hw)
-{
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- /* reset the core */
- if (!DEVICEREMOVED(wlc_hw->wlc))
- brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
-
- /* purge the dma rings */
- brcms_c_flushqueues(wlc_hw->wlc);
-
- brcms_c_reset_bmac_done(wlc_hw->wlc);
-}
-
-void
-brcms_b_init(struct brcms_hardware *wlc_hw, chanspec_t chanspec,
- bool mute) {
- u32 macintmask;
- 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)
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- /* disable interrupts */
- macintmask = brcms_intrsoff(wlc->wl);
-
- /* set up the specified band and chanspec */
- brcms_c_setxband(wlc_hw, CHSPEC_BANDUNIT(chanspec));
- wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
-
- /* do one-time phy inits and calibration */
- wlc_phy_cal_init(wlc_hw->band->pi);
-
- /* core-specific initialization */
- brcms_b_coreinit(wlc);
-
- /* suspend the tx fifos and mute the phy for preism cac time */
- if (mute)
- brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
-
- /* band-specific inits */
- brcms_b_bsinit(wlc, chanspec);
-
- /* restore macintmask */
- brcms_intrsrestore(wlc->wl, macintmask);
-
- /* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac
- * is suspended and brcms_c_enable_mac() will clear this override bit.
- */
- mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
-
- /*
- * initialize mac_suspend_depth to 1 to match ucode initial suspended state
- */
- wlc_hw->mac_suspend_depth = 1;
-
- /* restore the clk */
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
-{
- uint coremask;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- /*
- * Enable pll and xtal, initialize the power control registers,
- * and force fastclock for the remainder of brcms_c_up().
- */
- brcms_b_xtal(wlc_hw, ON);
- ai_clkctl_init(wlc_hw->sih);
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- /*
- * Configure pci/pcmcia here instead of in brcms_c_attach()
- * to allow mfg hotswap: down, hotswap (chip power cycle), up.
- */
- coremask = (1 << wlc_hw->wlc->core->coreidx);
-
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_setup(wlc_hw->sih, coremask);
-
- /*
- * Need to read the hwradio status here to cover the case where the system
- * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
- */
- if (brcms_b_radio_read_hwdisabled(wlc_hw)) {
- /* put SB PCI in down state again */
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_down(wlc_hw->sih);
- brcms_b_xtal(wlc_hw, OFF);
- return -ENOMEDIUM;
- }
-
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_up(wlc_hw->sih);
-
- /* reset the d11 core */
- brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
-
- return 0;
-}
-
-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);
-
- /* FULLY enable dynamic power control and d11 core interrupt */
- brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
- brcms_intrson(wlc_hw->wlc->wl);
- return 0;
-}
-
-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;
-
- dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
- /* disable interrupts */
- if (dev_gone)
- wlc_hw->wlc->macintmask = 0;
- else {
- /* now disable interrupts */
- brcms_intrsoff(wlc_hw->wlc->wl);
-
- /* ensure we're running on the pll clock again */
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
- }
- /* down phy at the last of this stage */
- callbacks += wlc_phy_down(wlc_hw->band->pi);
-
- return callbacks;
-}
-
-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;
-
- wlc_hw->up = false;
- wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
-
- dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
- if (dev_gone) {
- wlc_hw->sbclk = false;
- wlc_hw->clk = false;
- wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
-
- /* reclaim any posted packets */
- brcms_c_flushqueues(wlc_hw->wlc);
- } else {
-
- /* Reset and disable the core */
- if (ai_iscoreup(wlc_hw->sih)) {
- if (R_REG(&wlc_hw->regs->maccontrol) &
- MCTL_EN_MAC)
- brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
- callbacks += brcms_reset(wlc_hw->wlc->wl);
- brcms_c_coredisable(wlc_hw);
- }
-
- /* turn off primary xtal and pll */
- if (!wlc_hw->noreset) {
- if (wlc_hw->sih->bustype == PCI_BUS)
- ai_pci_down(wlc_hw->sih);
- brcms_b_xtal(wlc_hw, OFF);
- }
- }
-
- return callbacks;
-}
-
-void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw)
-{
- /* delay before first read of ucode state */
- udelay(40);
-
- /* wait until ucode is no longer asleep */
- SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) ==
- DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
-}
-
-void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw, u8 *ea)
-{
- memcpy(ea, wlc_hw->etheraddr, ETH_ALEN);
-}
-
-static int brcms_b_bandtype(struct brcms_hardware *wlc_hw)
-{
- return wlc_hw->band->bandtype;
-}
-
-/* control chip clock to save power, enable dynamic clock or force fast clock */
-static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
-{
- if (PMUCTL_ENAB(wlc_hw->sih)) {
- /* new chips with PMU, CCS_FORCEHT will distribute the HT clock on backplane,
- * but mac core will still run on ALP(not HT) when it enters powersave mode,
- * which means the FCA bit may not be set.
- * should wakeup mac if driver wants it to run on HT.
- */
-
- if (wlc_hw->clk) {
- if (mode == CLK_FAST) {
- OR_REG(&wlc_hw->regs->clk_ctl_st,
- CCS_FORCEHT);
-
- udelay(64);
-
- SPINWAIT(((R_REG
- (&wlc_hw->regs->
- clk_ctl_st) & CCS_HTAVAIL) == 0),
- PMU_MAX_TRANSITION_DLY);
- WARN_ON(!(R_REG
- (&wlc_hw->regs->
- clk_ctl_st) & CCS_HTAVAIL));
- } else {
- if ((wlc_hw->sih->pmurev == 0) &&
- (R_REG
- (&wlc_hw->regs->
- clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
- SPINWAIT(((R_REG
- (&wlc_hw->regs->
- clk_ctl_st) & CCS_HTAVAIL)
- == 0),
- PMU_MAX_TRANSITION_DLY);
- AND_REG(&wlc_hw->regs->clk_ctl_st,
- ~CCS_FORCEHT);
- }
- }
- wlc_hw->forcefastclk = (mode == CLK_FAST);
- } else {
-
- /* old chips w/o PMU, force HT through cc,
- * then use FCA to verify mac is running fast clock
- */
-
- wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode);
-
- /* check fast clock is available (if core is not in reset) */
- if (wlc_hw->forcefastclk && wlc_hw->clk)
- WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) &
- SISF_FCLKA));
-
- /* keep the ucode wake bit on if forcefastclk is on
- * since we do not want ucode to put us back to slow clock
- * when it dozes for PM mode.
- * Code below matches the wake override bit with current forcefastclk state
- * Only setting bit in wake_override instead of waking ucode immediately
- * since old code (wlc.c 1.4499) had this behavior. Older code set
- * wlc->forcefastclk but only had the wake happen if the wakup_ucode work
- * (protected by an up check) was executed just below.
- */
- if (wlc_hw->forcefastclk)
- mboolset(wlc_hw->wake_override,
- BRCMS_WAKE_OVERRIDE_FORCEFAST);
- else
- mboolclr(wlc_hw->wake_override,
- BRCMS_WAKE_OVERRIDE_FORCEFAST);
- }
-}
-
-/* set initial host flags value */
-static void
-brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
-
- memset(mhfs, 0, MHFMAX * sizeof(u16));
-
- mhfs[MHF2] |= mhf2_init;
-
- /* prohibit use of slowclock on multifunction boards */
- if (wlc_hw->boardflags & BFL_NOPLLDOWN)
- mhfs[MHF1] |= MHF1_FORCEFASTCLK;
-
- if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
- mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
- mhfs[MHF1] |= MHF1_IQSWAP_WAR;
- }
-}
-
-/* set or clear ucode host flag bits
- * it has an optimization for no-change write
- * it only writes through shared memory when the core has clock;
- * pre-CLK changes should use wlc_write_mhf to get around the optimization
- *
- *
- * bands values are: BRCM_BAND_AUTO <--- Current band only
- * BRCM_BAND_5G <--- 5G band only
- * BRCM_BAND_2G <--- 2G band only
- * BRCM_BAND_ALL <--- All bands
- */
-void
-brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val,
- int bands)
-{
- u16 save;
- u16 addr[MHFMAX] = {
- M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
- M_HOST_FLAGS5
- };
- struct brcms_hw_band *band;
-
- if ((val & ~mask) || idx >= MHFMAX)
- return; /* error condition */
-
- switch (bands) {
- /* Current band only or all bands,
- * then set the band to current band
- */
- case BRCM_BAND_AUTO:
- case BRCM_BAND_ALL:
- band = wlc_hw->band;
- break;
- case BRCM_BAND_5G:
- band = wlc_hw->bandstate[BAND_5G_INDEX];
- break;
- case BRCM_BAND_2G:
- band = wlc_hw->bandstate[BAND_2G_INDEX];
- break;
- default:
- band = NULL; /* error condition */
- }
-
- if (band) {
- save = band->mhfs[idx];
- band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
-
- /* optimization: only write through if changed, and
- * changed band is the current band
- */
- if (wlc_hw->clk && (band->mhfs[idx] != save)
- && (band == wlc_hw->band))
- brcms_b_write_shm(wlc_hw, addr[idx],
- (u16) band->mhfs[idx]);
- }
-
- if (bands == BRCM_BAND_ALL) {
- wlc_hw->bandstate[0]->mhfs[idx] =
- (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
- wlc_hw->bandstate[1]->mhfs[idx] =
- (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
- }
-}
-
-u16 brcms_b_mhf_get(struct brcms_hardware *wlc_hw, u8 idx, int bands)
-{
- struct brcms_hw_band *band;
-
- if (idx >= MHFMAX)
- return 0; /* error condition */
- switch (bands) {
- case BRCM_BAND_AUTO:
- band = wlc_hw->band;
- break;
- case BRCM_BAND_5G:
- band = wlc_hw->bandstate[BAND_5G_INDEX];
- break;
- case BRCM_BAND_2G:
- band = wlc_hw->bandstate[BAND_2G_INDEX];
- break;
- default:
- band = NULL; /* error condition */
- }
-
- if (!band)
- return 0;
-
- return band->mhfs[idx];
-}
-
-static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs)
-{
- u8 idx;
- u16 addr[] = {
- M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
- M_HOST_FLAGS5
- };
-
- for (idx = 0; idx < MHFMAX; idx++) {
- brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]);
- }
-}
-
-/* set the maccontrol register to desired reset state and
- * initialize the sw cache of the register
- */
-static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw)
-{
- /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
- wlc_hw->maccontrol = 0;
- wlc_hw->suspended_fifos = 0;
- wlc_hw->wake_override = 0;
- wlc_hw->mute_override = 0;
- brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
-}
-
-/* set or clear maccontrol bits */
-void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val)
-{
- u32 maccontrol;
- u32 new_maccontrol;
-
- if (val & ~mask)
- return; /* error condition */
- maccontrol = wlc_hw->maccontrol;
- new_maccontrol = (maccontrol & ~mask) | val;
-
- /* if the new maccontrol value is the same as the old, nothing to do */
- if (new_maccontrol == maccontrol)
- return;
-
- /* something changed, cache the new value */
- wlc_hw->maccontrol = new_maccontrol;
-
- /* write the new values with overrides applied */
- brcms_c_mctrl_write(wlc_hw);
-}
-
-/* write the software state of maccontrol and overrides to the maccontrol register */
-static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw)
-{
- u32 maccontrol = wlc_hw->maccontrol;
-
- /* OR in the wake bit if overridden */
- if (wlc_hw->wake_override)
- maccontrol |= MCTL_WAKE;
-
- /* set AP and INFRA bits for mute if needed */
- if (wlc_hw->mute_override) {
- maccontrol &= ~(MCTL_AP);
- maccontrol |= MCTL_INFRA;
- }
-
- W_REG(&wlc_hw->regs->maccontrol, maccontrol);
-}
-
-void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
- u32 override_bit)
-{
- if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
- mboolset(wlc_hw->wake_override, override_bit);
- return;
- }
-
- mboolset(wlc_hw->wake_override, override_bit);
-
- brcms_c_mctrl_write(wlc_hw);
- brcms_b_wait_for_wake(wlc_hw);
-
- return;
-}
-
-void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
- u32 override_bit)
-{
- mboolclr(wlc_hw->wake_override, override_bit);
-
- if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
- return;
-
- brcms_c_mctrl_write(wlc_hw);
-
- return;
-}
-
-/* When driver needs ucode to stop beaconing, it has to make sure that
- * MCTL_AP is clear and MCTL_INFRA is set
- * Mode MCTL_AP MCTL_INFRA
- * AP 1 1
- * STA 0 1 <--- This will ensure no beacons
- * IBSS 0 0
- */
-static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw)
-{
- wlc_hw->mute_override = 1;
-
- /* if maccontrol already has AP == 0 and INFRA == 1 without this
- * override, then there is no change to write
- */
- if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
- return;
-
- brcms_c_mctrl_write(wlc_hw);
-
- return;
-}
-
-/* Clear the override on AP and INFRA bits */
-static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw)
-{
- if (wlc_hw->mute_override == 0)
- return;
-
- wlc_hw->mute_override = 0;
-
- /* if maccontrol already has AP == 0 and INFRA == 1 without this
- * override, then there is no change to write
- */
- if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
- return;
-
- brcms_c_mctrl_write(wlc_hw);
-}
-
-/*
- * Write a MAC address to the given match reg offset in the RXE match engine.
- */
-void
-brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
- const u8 *addr)
-{
- d11regs_t *regs;
- u16 mac_l;
- u16 mac_m;
- u16 mac_h;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n",
- wlc_hw->unit);
-
- regs = wlc_hw->regs;
- mac_l = addr[0] | (addr[1] << 8);
- mac_m = addr[2] | (addr[3] << 8);
- mac_h = addr[4] | (addr[5] << 8);
-
- /* enter the MAC addr into the RXE match registers */
- W_REG(&regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
- W_REG(&regs->rcm_mat_data, mac_l);
- W_REG(&regs->rcm_mat_data, mac_m);
- W_REG(&regs->rcm_mat_data, mac_h);
-
-}
-
-void
-brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
- void *buf)
-{
- d11regs_t *regs;
- u32 word;
- bool be_bit;
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- regs = wlc_hw->regs;
- W_REG(&regs->tplatewrptr, offset);
-
- /* if MCTL_BIGEND bit set in mac control register,
- * the chip swaps data in fifo, as well as data in
- * template ram
- */
- be_bit = (R_REG(&regs->maccontrol) & MCTL_BIGEND) != 0;
-
- while (len > 0) {
- memcpy(&word, buf, sizeof(u32));
-
- if (be_bit)
- word = cpu_to_be32(word);
- else
- word = cpu_to_le32(word);
-
- W_REG(&regs->tplatewrdata, word);
-
- buf = (u8 *) buf + sizeof(u32);
- len -= sizeof(u32);
- }
-}
-
-void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin)
-{
- wlc_hw->band->CWmin = newmin;
-
- W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
- (void)R_REG(&wlc_hw->regs->objaddr);
- W_REG(&wlc_hw->regs->objdata, newmin);
-}
-
-void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax)
-{
- wlc_hw->band->CWmax = newmax;
-
- W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
- (void)R_REG(&wlc_hw->regs->objaddr);
- W_REG(&wlc_hw->regs->objdata, newmax);
-}
-
-void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw)
-{
- bool fastclk;
-
- /* request FAST clock if not on */
- fastclk = wlc_hw->forcefastclk;
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
-
- brcms_b_phy_reset(wlc_hw);
- wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
-
- /* restore the clk */
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-static void
-brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw, void *bcn,
- int len)
-{
- d11regs_t *regs = wlc_hw->regs;
-
- brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, (len + 3) & ~3,
- bcn);
- /* write beacon length to SCR */
- brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
- /* mark beacon0 valid */
- OR_REG(&regs->maccommand, MCMD_BCN0VLD);
-}
-
-static void
-brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw, void *bcn,
- int len)
-{
- d11regs_t *regs = wlc_hw->regs;
-
- brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, (len + 3) & ~3,
- bcn);
- /* write beacon length to SCR */
- brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
- /* mark beacon1 valid */
- OR_REG(&regs->maccommand, MCMD_BCN1VLD);
-}
-
-/* mac is assumed to be suspended at this point */
-void
-brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw, void *bcn,
- int len, bool both)
-{
- d11regs_t *regs = wlc_hw->regs;
-
- if (both) {
- brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len);
- brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len);
- } else {
- /* bcn 0 */
- if (!(R_REG(&regs->maccommand) & MCMD_BCN0VLD))
- brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len);
- /* bcn 1 */
- else if (!
- (R_REG(&regs->maccommand) & MCMD_BCN1VLD))
- brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len);
- }
-}
-
-static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw)
-{
- u16 v;
- struct brcms_c_info *wlc = wlc_hw->wlc;
- /* update SYNTHPU_DLY */
-
- if (BRCMS_ISLCNPHY(wlc->band)) {
- v = SYNTHPU_DLY_LPPHY_US;
- } else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) {
- v = SYNTHPU_DLY_NPHY_US;
- } else {
- v = SYNTHPU_DLY_BPHY_US;
- }
-
- brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
-}
-
-/* band-specific init */
-static void
-brcms_b_bsinit(struct brcms_c_info *wlc, chanspec_t chanspec)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
-
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- wlc_hw->band->bandunit);
-
- brcms_c_ucode_bsinit(wlc_hw);
-
- wlc_phy_init(wlc_hw->band->pi, chanspec);
-
- brcms_c_ucode_txant_set(wlc_hw);
-
- /* cwmin is band-specific, update hardware with value for current band */
- brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
- brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
-
- brcms_b_update_slot_timing(wlc_hw,
- BAND_5G(wlc_hw->band->
- bandtype) ? true : wlc_hw->
- shortslot);
-
- /* write phytype and phyvers */
- brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
- brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
-
- /* initialize the txphyctl1 rate table since shmem is shared between bands */
- brcms_upd_ofdm_pctl1_table(wlc_hw);
-
- brcms_b_upd_synthpu(wlc_hw);
-}
-
-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);
-
- wlc_hw->phyclk = clk;
-
- if (OFF == clk) { /* clear gmode bit, put phy into reset */
-
- ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
- (SICF_PRST | SICF_FGC));
- udelay(1);
- ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
- udelay(1);
-
- } else { /* take phy out of reset */
-
- ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
- udelay(1);
- ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
- udelay(1);
-
- }
-}
-
-/* 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_corereg(wlc_hw->sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_addr), ~0, 0);
- udelay(1);
- ai_corereg(wlc_hw->sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
- udelay(1);
- ai_corereg(wlc_hw->sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data), 0x4, 4);
- udelay(1);
- ai_corereg(wlc_hw->sih, SI_CC_IDX,
- offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
- udelay(1);
-}
-
-/* light way to turn on phy clock without reset for NPHY only
- * refer to brcms_b_core_phy_clk for full version
- */
-void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk)
-{
- /* support(necessary for NPHY and HYPHY) only */
- if (!BRCMS_ISNPHY(wlc_hw->band))
- return;
-
- if (ON == clk)
- ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
- else
- ai_core_cflags(wlc_hw->sih, SICF_FGC, 0);
-
-}
-
-void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk)
-{
- if (ON == clk)
- ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
- else
- ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
-}
-
-void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
-{
- struct brcms_phy_pub *pih = wlc_hw->band->pi;
- u32 phy_bw_clkbits;
- bool phy_in_reset = false;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- if (pih == NULL)
- return;
-
- phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
-
- /* Specific reset sequence required for NPHY rev 3 and 4 */
- if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
- NREV_LE(wlc_hw->band->phyrev, 4)) {
- /* Set the PHY bandwidth */
- ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
-
- udelay(1);
-
- /* Perform a soft reset of the PHY PLL */
- brcms_b_core_phypll_reset(wlc_hw);
-
- /* reset the PHY */
- ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
- (SICF_PRST | SICF_PCLKE));
- phy_in_reset = true;
- } else {
-
- ai_core_cflags(wlc_hw->sih,
- (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
- (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
- }
-
- udelay(2);
- brcms_b_core_phy_clk(wlc_hw, ON);
-
- if (pih)
- wlc_phy_anacore(pih, ON);
-}
-
-/* switch to and initialize new band */
-static void
-brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
- chanspec_t chanspec) {
- struct brcms_c_info *wlc = wlc_hw->wlc;
- u32 macintmask;
-
- /* Enable the d11 core before accessing it */
- if (!ai_iscoreup(wlc_hw->sih)) {
- ai_core_reset(wlc_hw->sih, 0, 0);
- brcms_c_mctrl_reset(wlc_hw);
- }
-
- macintmask = brcms_c_setband_inact(wlc, bandunit);
-
- if (!wlc_hw->up)
- return;
-
- brcms_b_core_phy_clk(wlc_hw, ON);
-
- /* band-specific initializations */
- brcms_b_bsinit(wlc, chanspec);
-
- /*
- * If there are any pending software interrupt bits,
- * then replace these with a harmless nonzero value
- * so brcms_c_dpc() will re-enable interrupts when done.
- */
- if (wlc->macintstatus)
- wlc->macintstatus = MI_DMAINT;
-
- /* restore macintmask */
- brcms_intrsrestore(wlc->wl, macintmask);
-
- /* ucode should still be suspended.. */
- WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
-}
-
-/* low-level band switch utility routine */
-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);
-
- wlc_hw->band = wlc_hw->bandstate[bandunit];
-
- /* BMAC_NOTE: until we eliminate need for wlc->band refs in low level code */
- wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
-
- /* set gmode core flag */
- if (wlc_hw->sbclk && !wlc_hw->noreset) {
- ai_core_cflags(wlc_hw->sih, SICF_GMODE,
- ((bandunit == 0) ? SICF_GMODE : 0));
- }
-}
-
-static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw)
-{
-
- /* reject unsupported corerev */
- if (!VALID_COREREV(wlc_hw->corerev)) {
- wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n",
- wlc_hw->corerev);
- return false;
- }
-
- return true;
-}
-
-/* Validate some board info parameters */
-static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw)
-{
- uint boardrev = wlc_hw->boardrev;
-
- /* 4 bits each for board type, major, minor, and tiny version */
- uint brt = (boardrev & 0xf000) >> 12;
- uint b0 = (boardrev & 0xf00) >> 8;
- uint b1 = (boardrev & 0xf0) >> 4;
- uint b2 = boardrev & 0xf;
-
- /* voards from other vendors are always considered valid */
- if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM)
- return true;
-
- /* do some boardrev sanity checks when boardvendor is Broadcom */
- if (boardrev == 0)
- return false;
-
- if (boardrev <= 0xff)
- return true;
-
- if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
- || (b2 > 9))
- return false;
-
- return true;
-}
-
-static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw)
-{
- const char *varname = "macaddr";
- char *macaddr;
-
- /* If macaddr exists, use it (Sromrev4, CIS, ...). */
- macaddr = getvar(wlc_hw->vars, varname);
- if (macaddr != NULL)
- return macaddr;
-
- if (NBANDS_HW(wlc_hw) > 1)
- varname = "et1macaddr";
- else
- varname = "il0macaddr";
-
- macaddr = getvar(wlc_hw->vars, varname);
- if (macaddr == NULL) {
- wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr "
- "getvar(%s) not found\n", wlc_hw->unit, varname);
- }
-
- return macaddr;
-}
-
-/*
- * Return true if radio is disabled, otherwise false.
- * hw radio disable signal is an external pin, users activate it asynchronously
- * this function could be called when driver is down and w/o clock
- * it operates on different registers depending on corerev and boardflag.
- */
-bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
-{
- bool v, clk, xtal;
- u32 resetbits = 0, flags = 0;
-
- xtal = wlc_hw->sbclk;
- if (!xtal)
- brcms_b_xtal(wlc_hw, ON);
-
- /* may need to take core out of reset first */
- clk = wlc_hw->clk;
- if (!clk) {
- /*
- * mac no longer enables phyclk automatically when driver
- * accesses phyreg throughput mac. This can be skipped since
- * only mac reg is accessed below
- */
- flags |= SICF_PCLKE;
-
- /* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
- if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
- (wlc_hw->sih->chip == BCM43225_CHIP_ID))
- wlc_hw->regs =
- (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
- 0);
- ai_core_reset(wlc_hw->sih, flags, resetbits);
- brcms_c_mctrl_reset(wlc_hw);
- }
-
- v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
-
- /* put core back into reset */
- if (!clk)
- ai_core_disable(wlc_hw->sih, 0);
-
- if (!xtal)
- brcms_b_xtal(wlc_hw, OFF);
-
- return v;
-}
-
-/* Initialize just the hardware when coming out of POR or S3/S5 system states */
-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);
-
- /*
- * Enable pll and xtal, initialize the power control registers,
- * and force fastclock for the remainder of brcms_c_up().
- */
- brcms_b_xtal(wlc_hw, ON);
- ai_clkctl_init(wlc_hw->sih);
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- if (wlc_hw->sih->bustype == PCI_BUS) {
- ai_pci_fixcfg(wlc_hw->sih);
-
- /* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
- if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
- (wlc_hw->sih->chip == BCM43225_CHIP_ID))
- wlc_hw->regs =
- (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
- 0);
- }
-
- /* Inform phy that a POR reset has occurred so it does a complete phy init */
- wlc_phy_por_inform(wlc_hw->band->pi);
-
- wlc_hw->ucode_loaded = false;
- wlc_hw->wlc->pub->hw_up = true;
-
- if ((wlc_hw->boardflags & BFL_FEM)
- && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
- if (!
- (wlc_hw->boardrev >= 0x1250
- && (wlc_hw->boardflags & BFL_FEM_BT)))
- ai_epa_4313war(wlc_hw->sih);
- }
-}
-
-static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo)
-{
- struct dma_pub *di = wlc_hw->di[fifo];
- return dma_rxreset(di);
-}
-
-/* d11 core reset
- * ensure fask clock during reset
- * reset dma
- * reset d11(out of reset)
- * reset phy(out of reset)
- * clear software macintstatus for fresh new start
- * one testing hack wlc_hw->noreset will bypass the d11/phy reset
- */
-void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
-{
- d11regs_t *regs;
- uint i;
- bool fastclk;
- u32 resetbits = 0;
-
- 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);
-
- regs = wlc_hw->regs;
-
- /* request FAST clock if not on */
- fastclk = wlc_hw->forcefastclk;
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- /* reset the dma engines except first time thru */
- if (ai_iscoreup(wlc_hw->sih)) {
- 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: "
- "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"
- "[%d]: cannot stop dma\n",
- wlc_hw->unit, __func__, RX_FIFO);
- }
- }
- /* if noreset, just stop the psm and return */
- if (wlc_hw->noreset) {
- wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */
- brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
- return;
- }
-
- /*
- * mac no longer enables phyclk automatically when driver accesses
- * phyreg throughput mac, AND phy_reset is skipped at early stage when
- * band->pi is invalid. need to enable PHY CLK
- */
- flags |= SICF_PCLKE;
-
- /* reset the core
- * In chips with PMU, the fastclk request goes through d11 core reg 0x1e0, which
- * is cleared by the core_reset. have to re-request it.
- * This adds some delay and we can optimize it by also requesting fastclk through
- * chipcommon during this period if necessary. But that has to work coordinate
- * with other driver like mips/arm since they may touch chipcommon as well.
- */
- wlc_hw->clk = false;
- ai_core_reset(wlc_hw->sih, flags, resetbits);
- wlc_hw->clk = true;
- if (wlc_hw->band && wlc_hw->band->pi)
- wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
-
- brcms_c_mctrl_reset(wlc_hw);
-
- if (PMUCTL_ENAB(wlc_hw->sih))
- brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
-
- brcms_b_phy_reset(wlc_hw);
-
- /* turn on PHY_PLL */
- brcms_b_core_phypll_ctl(wlc_hw, true);
-
- /* clear sw intstatus */
- wlc_hw->wlc->macintstatus = 0;
-
- /* restore the clk setting */
- if (!fastclk)
- brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-/* txfifo sizes needs to be modified(increased) since the newer cores
- * have more memory.
- */
-static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw)
-{
- d11regs_t *regs = wlc_hw->regs;
- u16 fifo_nu;
- u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
- u16 txfifo_def, txfifo_def1;
- u16 txfifo_cmd;
-
- /* tx fifos start at TXFIFO_START_BLK from the Base address */
- txfifo_startblk = TXFIFO_START_BLK;
-
- /* sequence of operations: reset fifo, set fifo size, reset fifo */
- for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
-
- txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
- txfifo_def = (txfifo_startblk & 0xff) |
- (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
- txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
- ((((txfifo_endblk -
- 1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
- txfifo_cmd =
- TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
-
- W_REG(&regs->xmtfifocmd, txfifo_cmd);
- W_REG(&regs->xmtfifodef, txfifo_def);
- W_REG(&regs->xmtfifodef1, txfifo_def1);
-
- W_REG(&regs->xmtfifocmd, txfifo_cmd);
-
- txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
- }
- /*
- * need to propagate to shm location to be in sync since ucode/hw won't
- * do this
- */
- brcms_b_write_shm(wlc_hw, M_FIFOSIZE0,
- wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
- brcms_b_write_shm(wlc_hw, M_FIFOSIZE1,
- wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
- brcms_b_write_shm(wlc_hw, M_FIFOSIZE2,
- ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
- xmtfifo_sz[TX_AC_BK_FIFO]));
- brcms_b_write_shm(wlc_hw, M_FIFOSIZE3,
- ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
- xmtfifo_sz[TX_BCMC_FIFO]));
-}
-
-/* d11 core init
- * reset PSM
- * download ucode/PCM
- * let ucode run to suspended
- * download ucode inits
- * config other core registers
- * init dma
- */
-static void brcms_b_coreinit(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs;
- u32 sflags;
- uint bcnint_us;
- uint i = 0;
- bool fifosz_fixup = false;
- int err = 0;
- u16 buf[NFIFO];
- struct wiphy *wiphy = wlc->wiphy;
-
- regs = wlc_hw->regs;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- /* reset PSM */
- brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
-
- brcms_ucode_download(wlc_hw);
- /*
- * FIFOSZ fixup. driver wants to controls the fifo allocation.
- */
- fifosz_fixup = true;
-
- /* let the PSM run to the suspended state, set mode to BSS STA */
- W_REG(&regs->macintstatus, -1);
- brcms_b_mctrl(wlc_hw, ~0,
- (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
-
- /* wait for ucode to self-suspend after auto-init */
- SPINWAIT(((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0),
- 1000 * 1000);
- if ((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0)
- wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
- "suspend!\n", wlc_hw->unit);
-
- brcms_c_gpio_init(wlc);
-
- sflags = ai_core_sflags(wlc_hw->sih, 0, 0);
-
- if (D11REV_IS(wlc_hw->corerev, 23)) {
- if (BRCMS_ISNPHY(wlc_hw->band))
- brcms_c_write_inits(wlc_hw, d11n0initvals16);
- else
- wiphy_err(wiphy, "%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, d11lcn0initvals24);
- } else {
- wiphy_err(wiphy, "%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",
- __func__, wlc_hw->unit, wlc_hw->corerev);
- }
-
- /* For old ucode, txfifo sizes needs to be modified(increased) */
- if (fifosz_fixup == true) {
- brcms_b_corerev_fifofixup(wlc_hw);
- }
-
- /* check txfifo allocations match between ucode and driver */
- buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0);
- if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
- i = TX_AC_BE_FIFO;
- err = -1;
- }
- buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1);
- if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
- i = TX_AC_VI_FIFO;
- err = -1;
- }
- buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2);
- buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
- buf[TX_AC_BK_FIFO] &= 0xff;
- if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
- i = TX_AC_BK_FIFO;
- err = -1;
- }
- if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
- i = TX_AC_VO_FIFO;
- err = -1;
- }
- buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3);
- buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
- buf[TX_BCMC_FIFO] &= 0xff;
- if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
- i = TX_BCMC_FIFO;
- err = -1;
- }
- if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
- i = TX_ATIM_FIFO;
- err = -1;
- }
- if (err != 0) {
- wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d"
- " driver size %d index %d\n", buf[i],
- wlc_hw->xmtfifo_sz[i], i);
- }
-
- /* make sure we can still talk to the mac */
- WARN_ON(R_REG(&regs->maccontrol) == 0xffffffff);
-
- /* band-specific inits done by wlc_bsinit() */
-
- /* Set up frame burst size and antenna swap threshold init values */
- brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
- brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
-
- /* enable one rx interrupt per received frame */
- W_REG(&regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
-
- /* set the station mode (BSS STA) */
- brcms_b_mctrl(wlc_hw,
- (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
- (MCTL_INFRA | MCTL_DISCARD_PMQ));
-
- /* set up Beacon interval */
- bcnint_us = 0x8000 << 10;
- W_REG(&regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
- W_REG(&regs->tsf_cfpstart, bcnint_us);
- W_REG(&regs->macintstatus, MI_GP1);
-
- /* write interrupt mask */
- W_REG(&regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
-
- /* allow the MAC to control the PHY clock (dynamic on/off) */
- brcms_b_macphyclk_set(wlc_hw, ON);
-
- /* program dynamic clock control fast powerup delay register */
- wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih);
- W_REG(&regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
-
- /* tell the ucode the corerev */
- brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
-
- /* tell the ucode MAC capabilities */
- brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L,
- (u16) (wlc_hw->machwcap & 0xffff));
- brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H,
- (u16) ((wlc_hw->
- machwcap >> 16) & 0xffff));
-
- /* write retry limits to SCR, this done after PSM init */
- W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
- (void)R_REG(&regs->objaddr);
- W_REG(&regs->objdata, wlc_hw->SRL);
- W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
- (void)R_REG(&regs->objaddr);
- W_REG(&regs->objdata, wlc_hw->LRL);
-
- /* write rate fallback retry limits */
- brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
- brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
-
- AND_REG(&regs->ifs_ctl, 0x0FFF);
- W_REG(&regs->ifs_aifsn, EDCF_AIFSN_MIN);
-
- /* dma initializations */
- wlc->txpend16165war = 0;
-
- /* init the tx dma engines */
- for (i = 0; i < NFIFO; i++) {
- if (wlc_hw->di[i])
- dma_txinit(wlc_hw->di[i]);
- }
-
- /* init the rx dma engine(s) and post receive buffers */
- dma_rxinit(wlc_hw->di[RX_FIFO]);
- dma_rxfill(wlc_hw->di[RX_FIFO]);
-}
-
-/* This function is used for changing the tsf frac register
- * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
- * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
- * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
- * HTPHY Formula is 2^26/freq(MHz) e.g.
- * For spuron2 - 126MHz -> 2^26/126 = 532610.0
- * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
- * For spuron: 123MHz -> 2^26/123 = 545600.5
- * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
- * For spur off: 120MHz -> 2^26/120 = 559240.5
- * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
- */
-
-void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
-{
- d11regs_t *regs;
- regs = wlc_hw->regs;
-
- if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
- (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
- if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */
- W_REG(&regs->tsf_clk_frac_l, 0x2082);
- W_REG(&regs->tsf_clk_frac_h, 0x8);
- } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */
- W_REG(&regs->tsf_clk_frac_l, 0x5341);
- W_REG(&regs->tsf_clk_frac_h, 0x8);
- } else { /* 120Mhz */
- W_REG(&regs->tsf_clk_frac_l, 0x8889);
- W_REG(&regs->tsf_clk_frac_h, 0x8);
- }
- } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
- if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */
- W_REG(&regs->tsf_clk_frac_l, 0x7CE0);
- W_REG(&regs->tsf_clk_frac_h, 0xC);
- } else { /* 80Mhz */
- W_REG(&regs->tsf_clk_frac_l, 0xCCCD);
- W_REG(&regs->tsf_clk_frac_h, 0xC);
- }
- }
-}
-
-/* Initialize GPIOs that are controlled by D11 core */
-static void brcms_c_gpio_init(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs;
- u32 gc, gm;
-
- regs = wlc_hw->regs;
-
- /* use GPIO select 0 to get all gpio signals from the gpio out reg */
- brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
-
- /*
- * Common GPIO setup:
- * G0 = LED 0 = WLAN Activity
- * G1 = LED 1 = WLAN 2.4 GHz Radio State
- * G2 = LED 2 = WLAN 5 GHz Radio State
- * G4 = radio disable input (HI enabled, LO disabled)
- */
-
- gc = gm = 0;
-
- /* Allocate GPIOs for mimo antenna diversity feature */
- if (wlc_hw->antsel_type == ANTSEL_2x3) {
- /* Enable antenna diversity, use 2x3 mode */
- brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
- MHF3_ANTSEL_EN, BRCM_BAND_ALL);
- brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
- MHF3_ANTSEL_MODE, BRCM_BAND_ALL);
-
- /* init superswitch control */
- wlc_phy_antsel_init(wlc_hw->band->pi, false);
-
- } else if (wlc_hw->antsel_type == ANTSEL_2x4) {
- gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
- /*
- * The board itself is powered by these GPIOs
- * (when not sending pattern) so set them high
- */
- OR_REG(&regs->psm_gpio_oe,
- (BOARD_GPIO_12 | BOARD_GPIO_13));
- OR_REG(&regs->psm_gpio_out,
- (BOARD_GPIO_12 | BOARD_GPIO_13));
-
- /* Enable antenna diversity, use 2x4 mode */
- brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
- MHF3_ANTSEL_EN, BRCM_BAND_ALL);
- brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
- BRCM_BAND_ALL);
-
- /* Configure the desired clock to be 4Mhz */
- brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
- ANTSEL_CLKDIV_4MHZ);
- }
-
- /* gpio 9 controls the PA. ucode is responsible for wiggling out and oe */
- if (wlc_hw->boardflags & BFL_PACTRL)
- gm |= gc |= BOARD_GPIO_PACTRL;
-
- /* apply to gpiocontrol register */
- ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
-}
-
-static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
-{
- struct brcms_c_info *wlc;
- wlc = wlc_hw->wlc;
-
- if (wlc_hw->ucode_loaded)
- return;
-
- if (D11REV_IS(wlc_hw->corerev, 23)) {
- if (BRCMS_ISNPHY(wlc_hw->band)) {
- brcms_ucode_write(wlc_hw, bcm43xx_16_mimo,
- bcm43xx_16_mimosz);
- wlc_hw->ucode_loaded = true;
- } else
- wiphy_err(wlc->wiphy, "%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_ucode_write(wlc_hw, bcm43xx_24_lcn,
- bcm43xx_24_lcnsz);
- wlc_hw->ucode_loaded = true;
- } else {
- wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
- "corerev %d\n",
- __func__, wlc_hw->unit, wlc_hw->corerev);
- }
- }
-}
-
-static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[],
- const uint nbytes) {
- d11regs_t *regs = wlc_hw->regs;
- uint i;
- uint count;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- count = (nbytes / sizeof(u32));
-
- W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
- (void)R_REG(&regs->objaddr);
- for (i = 0; i < count; i++)
- W_REG(&regs->objdata, ucode[i]);
-}
-
-static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
- const struct d11init *inits)
-{
- int i;
- volatile u8 *base;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- base = (volatile u8 *)wlc_hw->regs;
-
- for (i = 0; inits[i].addr != 0xffff; i++) {
- if (inits[i].size == 2)
- W_REG((u16 *)(base + inits[i].addr),
- inits[i].value);
- else if (inits[i].size == 4)
- W_REG((u32 *)(base + inits[i].addr),
- inits[i].value);
- }
-}
-
-static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw)
-{
- u16 phyctl;
- u16 phytxant = wlc_hw->bmac_phytxant;
- u16 mask = PHY_TXC_ANT_MASK;
-
- /* set the Probe Response frame phy control word */
- phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
- phyctl = (phyctl & ~mask) | phytxant;
- brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
-
- /* set the Response (ACK/CTS) frame phy control word */
- phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD);
- phyctl = (phyctl & ~mask) | phytxant;
- brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
-}
-
-void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant)
-{
- /* update sw state */
- wlc_hw->bmac_phytxant = phytxant;
-
- /* push to ucode if up */
- if (!wlc_hw->up)
- return;
- brcms_c_ucode_txant_set(wlc_hw);
-
-}
-
-u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw)
-{
- return (u16) wlc_hw->wlc->stf->txant;
-}
-
-void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type)
-{
- wlc_hw->antsel_type = antsel_type;
-
- /* Update the antsel type for phy module to use */
- wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
-}
-
-void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
-{
- bool fatal = false;
- uint unit;
- uint intstatus, idx;
- d11regs_t *regs = wlc_hw->regs;
- struct wiphy *wiphy = wlc_hw->wlc->wiphy;
-
- unit = wlc_hw->unit;
-
- for (idx = 0; idx < NFIFO; idx++) {
- /* read intstatus register and ignore any non-error bits */
- intstatus =
- R_REG(&regs->intctrlregs[idx].intstatus) & I_ERRORS;
- if (!intstatus)
- continue;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n",
- unit, idx, intstatus);
-
- if (intstatus & I_RO) {
- wiphy_err(wiphy, "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);
- fatal = true;
- }
-
- if (intstatus & I_PD) {
- wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit,
- idx);
- fatal = true;
- }
-
- if (intstatus & I_DE) {
- wiphy_err(wiphy, "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 "
- "underflow\n", idx, unit);
- }
-
- if (intstatus & I_XU) {
- wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo "
- "underflow\n", idx, unit);
- fatal = true;
- }
-
- if (fatal) {
- brcms_c_fatal_error(wlc_hw->wlc); /* big hammer */
- break;
- } else
- W_REG(&regs->intctrlregs[idx].intstatus,
- intstatus);
- }
-}
-
-void brcms_c_intrson(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- wlc->macintmask = wlc->defmacintmask;
- W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
-}
-
-/* callback for siutils.c, which has only wlc handler, no wl
- * they both check up, not only because there is no need to off/restore d11 interrupt
- * but also because per-port code may require sync with valid interrupt.
- */
-
-static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc)
-{
- if (!wlc->hw->up)
- return 0;
-
- return brcms_intrsoff(wlc->wl);
-}
-
-static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask)
-{
- if (!wlc->hw->up)
- return;
-
- brcms_intrsrestore(wlc->wl, macintmask);
-}
-
-u32 brcms_c_intrsoff(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- u32 macintmask;
-
- if (!wlc_hw->clk)
- return 0;
-
- macintmask = wlc->macintmask; /* isr can still happen */
-
- W_REG(&wlc_hw->regs->macintmask, 0);
- (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */
- udelay(1); /* ensure int line is no longer driven */
- wlc->macintmask = 0;
-
- /* return previous macintmask; resolve race between us and our isr */
- return wlc->macintstatus ? 0 : macintmask;
-}
-
-void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- if (!wlc_hw->clk)
- return;
-
- wlc->macintmask = macintmask;
- W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
-}
-
-static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, mbool flags)
-{
- u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
-
- if (on) {
- /* suspend tx fifos */
- brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
- brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
- brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
- brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
-
- /* zero the address match register so we do not send ACKs */
- brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
- null_ether_addr);
- } else {
- /* resume tx fifos */
- if (!wlc_hw->wlc->tx_suspended) {
- brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
- }
- brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
- brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
- brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
-
- /* Restore address */
- brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
- wlc_hw->etheraddr);
- }
-
- wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
-
- if (on)
- brcms_c_ucode_mute_override_set(wlc_hw);
- else
- brcms_c_ucode_mute_override_clear(wlc_hw);
-}
-
-int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
- uint *blocks)
-{
- if (fifo >= NFIFO)
- return -EINVAL;
-
- *blocks = wlc_hw->xmtfifo_sz[fifo];
-
- return 0;
-}
-
-/* brcms_b_tx_fifo_suspended:
- * Check the MAC's tx suspend status for a tx fifo.
- *
- * When the MAC acknowledges a tx suspend, it indicates that no more
- * packets will be transmitted out the radio. This is independent of
- * DMA channel suspension---the DMA may have finished suspending, or may still
- * be pulling data into a tx fifo, by the time the MAC acks the suspend
- * request.
- */
-static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw,
- uint tx_fifo)
-{
- /* check that a suspend has been requested and is no longer pending */
-
- /*
- * for DMA mode, the suspend request is set in xmtcontrol of the DMA engine,
- * and the tx fifo suspend at the lower end of the MAC is acknowledged in the
- * chnstatus register.
- * The tx fifo suspend completion is independent of the DMA suspend completion and
- * may be acked before or after the DMA is suspended.
- */
- if (dma_txsuspended(wlc_hw->di[tx_fifo]) &&
- (R_REG(&wlc_hw->regs->chnstatus) &
- (1 << tx_fifo)) == 0)
- return true;
-
- return false;
-}
-
-static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
- uint tx_fifo)
-{
- u8 fifo = 1 << tx_fifo;
-
- /* Two clients of this code, 11h Quiet period and scanning. */
-
- /* only suspend if not already suspended */
- if ((wlc_hw->suspended_fifos & fifo) == fifo)
- return;
-
- /* force the core awake only if not already */
- if (wlc_hw->suspended_fifos == 0)
- brcms_c_ucode_wake_override_set(wlc_hw,
- BRCMS_WAKE_OVERRIDE_TXFIFO);
-
- wlc_hw->suspended_fifos |= fifo;
-
- if (wlc_hw->di[tx_fifo]) {
- /* Suspending AMPDU transmissions in the middle can cause underflow
- * which may result in mismatch between ucode and driver
- * so suspend the mac before suspending the FIFO
- */
- if (BRCMS_PHY_11N_CAP(wlc_hw->band))
- brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
-
- dma_txsuspend(wlc_hw->di[tx_fifo]);
-
- if (BRCMS_PHY_11N_CAP(wlc_hw->band))
- brcms_c_enable_mac(wlc_hw->wlc);
- }
-}
-
-static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
- uint tx_fifo)
-{
- /* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case
- * but need to be done here for PIO otherwise the watchdog will catch
- * the inconsistency and fire
- */
- /* Two clients of this code, 11h Quiet period and scanning. */
- if (wlc_hw->di[tx_fifo])
- dma_txresume(wlc_hw->di[tx_fifo]);
-
- /* allow core to sleep again */
- if (wlc_hw->suspended_fifos == 0)
- return;
- else {
- wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
- if (wlc_hw->suspended_fifos == 0)
- brcms_c_ucode_wake_override_clear(wlc_hw,
- BRCMS_WAKE_OVERRIDE_TXFIFO);
- }
-}
-
-/*
- * Read and clear macintmask and macintstatus and intstatus registers.
- * This routine should be called with interrupts off
- * Return:
- * -1 if DEVICEREMOVED(wlc) evaluates to true;
- * 0 if the interrupt is not for us, or we are in some special cases;
- * device interrupt status bits otherwise.
- */
-static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs = wlc_hw->regs;
- u32 macintstatus;
-
- /* macintstatus includes a DMA interrupt summary bit */
- macintstatus = R_REG(&regs->macintstatus);
-
- BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
- macintstatus);
-
- /* detect cardbus removed, in power down(suspend) and in reset */
- if (DEVICEREMOVED(wlc))
- return -1;
-
- /* DEVICEREMOVED succeeds even when the core is still resetting,
- * handle that case here.
- */
- if (macintstatus == 0xffffffff)
- return 0;
-
- /* defer unsolicited interrupts */
- macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
-
- /* 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 */
- W_REG(&regs->macintmask, 0);
- (void)R_REG(&regs->macintmask); /* sync readback */
- wlc->macintmask = 0;
-
- /* clear device interrupts */
- W_REG(&regs->macintstatus, macintstatus);
-
- /* MI_DMAINT is indication of non-zero intstatus */
- if (macintstatus & MI_DMAINT) {
- /*
- * only fifo interrupt enabled is I_RI in
- * RX_FIFO. If MI_DMAINT is set, assume it
- * is set and clear the interrupt.
- */
- W_REG(&regs->intctrlregs[RX_FIFO].intstatus,
- DEF_RXINTMASK);
- }
-
- return macintstatus;
-}
-
-/* Update wlc->macintstatus and wlc->intstatus[]. */
-/* Return true if they are updated successfully. false otherwise */
-bool brcms_c_intrsupd(struct brcms_c_info *wlc)
-{
- u32 macintstatus;
-
- /* read and clear macintstatus and intstatus registers */
- macintstatus = wlc_intstatus(wlc, false);
-
- /* device is removed */
- if (macintstatus == 0xffffffff)
- return false;
-
- /* update interrupt status in software */
- wlc->macintstatus |= macintstatus;
-
- return true;
-}
-
-/*
- * 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,
- * false otherwise.
- */
-bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc)
-{
- 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");
-
- /* it is not for us */
- if (macintstatus == 0)
- return false;
-
- *wantdpc = true;
-
- /* save interrupt status bits */
- wlc->macintstatus = macintstatus;
-
- return true;
-
-}
-
-static bool
-brcms_b_dotxstatus(struct brcms_hardware *wlc_hw, struct tx_status *txs,
- u32 s2)
-{
- /* discard intermediate indications for ucode with one legitimate case:
- * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
- * tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
- * transmission count)
- */
- if (!(txs->status & TX_STATUS_AMPDU)
- && (txs->status & TX_STATUS_INTERMEDIATE)) {
- return false;
- }
-
- return brcms_c_dotxstatus(wlc_hw->wlc, txs, s2);
-}
-
-/* process tx completion events in BMAC
- * Return true if more tx status need to be processed. false otherwise.
- */
-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;
- d11regs_t *regs;
- struct tx_status txstatus, *txs;
- u32 s1, s2;
- uint n = 0;
- /*
- * Param 'max_tx_num' indicates max. # tx status to process before
- * break out.
- */
- uint max_tx_num = bound ? wlc->pub->tunables->txsbnd : -1;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- txs = &txstatus;
- regs = wlc_hw->regs;
- while (!(*fatal)
- && (s1 = R_REG(&regs->frmtxstatus)) & TXS_V) {
-
- if (s1 == 0xffffffff) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
- wlc_hw->unit, __func__);
- return morepending;
- }
-
- s2 = R_REG(&regs->frmtxstatus2);
-
- txs->status = s1 & TXS_STATUS_MASK;
- txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
- txs->sequence = s2 & TXS_SEQ_MASK;
- txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
- txs->lasttxtime = 0;
-
- *fatal = brcms_b_dotxstatus(wlc_hw, txs, s2);
-
- /* !give others some time to run! */
- if (++n >= max_tx_num)
- break;
- }
-
- if (*fatal)
- return 0;
-
- if (n >= max_tx_num)
- morepending = true;
-
- if (!pktq_empty(&wlc->pkt_queue->q))
- brcms_c_send_q(wlc);
-
- return morepending;
-}
-
-void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs = wlc_hw->regs;
- u32 mc, mi;
- struct wiphy *wiphy = wlc->wiphy;
-
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- wlc_hw->band->bandunit);
-
- /*
- * Track overlapping suspend requests
- */
- wlc_hw->mac_suspend_depth++;
- if (wlc_hw->mac_suspend_depth > 1)
- return;
-
- /* force the core awake */
- brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
-
- mc = R_REG(&regs->maccontrol);
-
- if (mc == 0xffffffff) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
- __func__);
- brcms_down(wlc->wl);
- return;
- }
- WARN_ON(mc & MCTL_PSM_JMP_0);
- WARN_ON(!(mc & MCTL_PSM_RUN));
- WARN_ON(!(mc & MCTL_EN_MAC));
-
- mi = R_REG(&regs->macintstatus);
- if (mi == 0xffffffff) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
- __func__);
- brcms_down(wlc->wl);
- return;
- }
- WARN_ON(mi & MI_MACSSPNDD);
-
- brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0);
-
- SPINWAIT(!(R_REG(&regs->macintstatus) & MI_MACSSPNDD),
- BRCMS_MAX_MAC_SUSPEND);
-
- if (!(R_REG(&regs->macintstatus) & MI_MACSSPNDD)) {
- wiphy_err(wiphy, "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, "
- "psm_brc 0x%04x\n", wlc_hw->unit,
- R_REG(&regs->psmdebug),
- R_REG(&regs->phydebug),
- R_REG(&regs->psm_brc));
- }
-
- mc = R_REG(&regs->maccontrol);
- if (mc == 0xffffffff) {
- wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
- __func__);
- brcms_down(wlc->wl);
- return;
- }
- WARN_ON(mc & MCTL_PSM_JMP_0);
- WARN_ON(!(mc & MCTL_PSM_RUN));
- WARN_ON(mc & MCTL_EN_MAC);
-}
-
-void brcms_c_enable_mac(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- d11regs_t *regs = wlc_hw->regs;
- u32 mc, mi;
-
- BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
- wlc->band->bandunit);
-
- /*
- * Track overlapping suspend requests
- */
- wlc_hw->mac_suspend_depth--;
- if (wlc_hw->mac_suspend_depth > 0)
- return;
-
- mc = R_REG(&regs->maccontrol);
- WARN_ON(mc & MCTL_PSM_JMP_0);
- WARN_ON(mc & MCTL_EN_MAC);
- WARN_ON(!(mc & MCTL_PSM_RUN));
-
- brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
- W_REG(&regs->macintstatus, MI_MACSSPNDD);
-
- mc = R_REG(&regs->maccontrol);
- WARN_ON(mc & MCTL_PSM_JMP_0);
- WARN_ON(!(mc & MCTL_EN_MAC));
- WARN_ON(!(mc & MCTL_PSM_RUN));
-
- mi = R_REG(&regs->macintstatus);
- WARN_ON(mi & MI_MACSSPNDD);
-
- brcms_c_ucode_wake_override_clear(wlc_hw,
- BRCMS_WAKE_OVERRIDE_MACSUSPEND);
-}
-
-static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw)
-{
- u8 rate;
- u8 rates[8] = {
- BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M,
- BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M
- };
- u16 entry_ptr;
- u16 pctl1;
- uint i;
-
- if (!BRCMS_PHY_11N_CAP(wlc_hw->band))
- return;
-
- /* walk the phy rate table and update the entries */
- for (i = 0; i < ARRAY_SIZE(rates); i++) {
- rate = rates[i];
-
- entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate);
-
- /* read the SHM Rate Table entry OFDM PCTL1 values */
- pctl1 =
- brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
-
- /* modify the value */
- pctl1 &= ~PHY_TXC1_MODE_MASK;
- pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
-
- /* Update the SHM Rate Table entry OFDM PCTL1 values */
- brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
- pctl1);
- }
-}
-
-static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw,
- u8 rate)
-{
- uint i;
- u8 plcp_rate = 0;
- struct plcp_signal_rate_lookup {
- u8 rate;
- u8 signal_rate;
- };
- /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
- const struct plcp_signal_rate_lookup rate_lookup[] = {
- {BRCM_RATE_6M, 0xB},
- {BRCM_RATE_9M, 0xF},
- {BRCM_RATE_12M, 0xA},
- {BRCM_RATE_18M, 0xE},
- {BRCM_RATE_24M, 0x9},
- {BRCM_RATE_36M, 0xD},
- {BRCM_RATE_48M, 0x8},
- {BRCM_RATE_54M, 0xC}
- };
-
- for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
- if (rate == rate_lookup[i].rate) {
- plcp_rate = rate_lookup[i].signal_rate;
- break;
- }
- }
-
- /* Find the SHM pointer to the rate table entry by looking in the
- * Direct-map Table
- */
- return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
-}
-
-void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode)
-{
- wlc_hw->hw_stf_ss_opmode = stf_mode;
-
- if (wlc_hw->clk)
- brcms_upd_ofdm_pctl1_table(wlc_hw);
-}
-
-void
-brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
- u32 *tsf_h_ptr)
-{
- d11regs_t *regs = wlc_hw->regs;
-
- /* read the tsf timer low, then high to get an atomic read */
- *tsf_l_ptr = R_REG(&regs->tsf_timerlow);
- *tsf_h_ptr = R_REG(&regs->tsf_timerhigh);
-
- return;
-}
-
-static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
-{
- d11regs_t *regs;
- u32 w, val;
- struct wiphy *wiphy = wlc_hw->wlc->wiphy;
-
- BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
-
- regs = wlc_hw->regs;
-
- /* Validate dchip register access */
-
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- w = R_REG(&regs->objdata);
-
- /* Can we write and read back a 32bit register? */
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- W_REG(&regs->objdata, (u32) 0xaa5555aa);
-
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- val = R_REG(&regs->objdata);
- if (val != (u32) 0xaa5555aa) {
- wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
- "expected 0xaa5555aa\n", wlc_hw->unit, val);
- return false;
- }
-
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- W_REG(&regs->objdata, (u32) 0x55aaaa55);
-
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- val = R_REG(&regs->objdata);
- if (val != (u32) 0x55aaaa55) {
- wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
- "expected 0x55aaaa55\n", wlc_hw->unit, val);
- return false;
- }
-
- W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
- (void)R_REG(&regs->objaddr);
- W_REG(&regs->objdata, w);
-
- /* clear CFPStart */
- W_REG(&regs->tsf_cfpstart, 0);
-
- w = R_REG(&regs->maccontrol);
- if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
- (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
- wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = "
- "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w,
- (MCTL_IHR_EN | MCTL_WAKE),
- (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
- return false;
- }
-
- return true;
-}
-
-#define PHYPLL_WAIT_US 100000
-
-void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
-{
- d11regs_t *regs;
- u32 tmp;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- tmp = 0;
- regs = wlc_hw->regs;
-
- if (on) {
- if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
- OR_REG(&regs->clk_ctl_st,
- (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
- CCS_ERSRC_REQ_PHYPLL));
- SPINWAIT((R_REG(&regs->clk_ctl_st) &
- (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
- PHYPLL_WAIT_US);
-
- tmp = R_REG(&regs->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__);
- }
- } else {
- OR_REG(&regs->clk_ctl_st,
- (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
- SPINWAIT((R_REG(&regs->clk_ctl_st) &
- (CCS_ERSRC_AVAIL_D11PLL |
- CCS_ERSRC_AVAIL_PHYPLL)) !=
- (CCS_ERSRC_AVAIL_D11PLL |
- CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
-
- tmp = R_REG(&regs->clk_ctl_st);
- if ((tmp &
- (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__);
- }
- }
- } else {
- /* Since the PLL may be shared, other cores can still be requesting it;
- * so we'll deassert the request but not wait for status to comply.
- */
- AND_REG(&regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
- tmp = R_REG(&regs->clk_ctl_st);
- }
-}
-
-void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
-{
- bool dev_gone;
-
- BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
- dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
- if (dev_gone)
- return;
-
- if (wlc_hw->noreset)
- return;
-
- /* radio off */
- wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
-
- /* turn off analog core */
- wlc_phy_anacore(wlc_hw->band->pi, OFF);
-
- /* turn off PHYPLL to save power */
- brcms_b_core_phypll_ctl(wlc_hw, false);
-
- /* No need to set wlc->pub->radio_active = OFF
- * because this function needs down capability and
- * radio_active is designed for BCMNODOWN.
- */
-
- /* remove gpio controls */
- if (wlc_hw->ucode_dbgsel)
- ai_gpiocontrol(wlc_hw->sih, ~0, 0, GPIO_DRV_PRIORITY);
-
- wlc_hw->clk = false;
- ai_core_disable(wlc_hw->sih, 0);
- wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
-}
-
-/* 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);
-
- /* dont power down if plldown is false or we must poll hw radio disable */
- if (!want && wlc_hw->pllreq)
- return;
-
- if (wlc_hw->sih)
- ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
-
- wlc_hw->sbclk = want;
- if (!wlc_hw->sbclk) {
- wlc_hw->clk = false;
- if (wlc_hw->band && wlc_hw->band->pi)
- wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
- }
-}
-
-static void brcms_c_flushqueues(struct brcms_c_info *wlc)
-{
- struct brcms_hardware *wlc_hw = wlc->hw;
- uint i;
-
- wlc->txpend16165war = 0;
-
- /* free any posted tx packets */
- for (i = 0; i < NFIFO; i++)
- if (wlc_hw->di[i]) {
- dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL);
- TXPKTPENDCLR(wlc, i);
- BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i);
- }
-
- /* free any posted rx packets */
- dma_rxreclaim(wlc_hw->di[RX_FIFO]);
-}
-
-u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset)
-{
- return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
-}
-
-void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v)
-{
- brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
-}
-
-static u16
-brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel)
-{
- d11regs_t *regs = wlc_hw->regs;
- volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
- volatile u16 *objdata_hi = objdata_lo + 1;
- u16 v;
-
- W_REG(&regs->objaddr, sel | (offset >> 2));
- (void)R_REG(&regs->objaddr);
- if (offset & 2) {
- v = R_REG(objdata_hi);
- } else {
- v = R_REG(objdata_lo);
- }
-
- return v;
-}
-
-static void
-brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v,
- u32 sel)
-{
- d11regs_t *regs = wlc_hw->regs;
- volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
- volatile u16 *objdata_hi = objdata_lo + 1;
-
- W_REG(&regs->objaddr, sel | (offset >> 2));
- (void)R_REG(&regs->objaddr);
- if (offset & 2) {
- W_REG(objdata_hi, v);
- } else {
- W_REG(objdata_lo, v);
- }
-}
-
-/* Copy a buffer to shared memory of specified type .
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- * 'sel' selects the type of memory
- */
-void
-brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset,
- const void *buf, int len, u32 sel)
-{
- u16 v;
- const u8 *p = (const u8 *)buf;
- int i;
-
- if (len <= 0 || (offset & 1) || (len & 1))
- return;
-
- for (i = 0; i < len; i += 2) {
- v = p[i] | (p[i + 1] << 8);
- brcms_b_write_objmem(wlc_hw, offset + i, v, sel);
- }
-}
-
-/* Copy a piece of shared memory of specified type to a buffer .
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- * 'sel' selects the type of memory
- */
-void
-brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf,
- int len, u32 sel)
-{
- u16 v;
- u8 *p = (u8 *) buf;
- int i;
-
- if (len <= 0 || (offset & 1) || (len & 1))
- return;
-
- for (i = 0; i < len; i += 2) {
- v = brcms_b_read_objmem(wlc_hw, offset + i, sel);
- p[i] = v & 0xFF;
- p[i + 1] = (v >> 8) & 0xFF;
- }
-}
-
-void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf,
- uint *len)
-{
- BCMMSG(wlc_hw->wlc->wiphy, "nvram vars totlen=%d\n",
- wlc_hw->vars_size);
-
- *buf = wlc_hw->vars;
- *len = wlc_hw->vars_size;
-}
-
-void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL, u16 LRL)
-{
- wlc_hw->SRL = SRL;
- wlc_hw->LRL = LRL;
-
- /* write retry limit to SCR, shouldn't need to suspend */
- if (wlc_hw->up) {
- W_REG(&wlc_hw->regs->objaddr,
- OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
- (void)R_REG(&wlc_hw->regs->objaddr);
- W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL);
- W_REG(&wlc_hw->regs->objaddr,
- OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
- (void)R_REG(&wlc_hw->regs->objaddr);
- W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL);
- }
-}
-
-void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, mbool req_bit)
-{
- if (set) {
- if (mboolisset(wlc_hw->pllreq, req_bit))
- return;
-
- mboolset(wlc_hw->pllreq, req_bit);
-
- if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
- if (!wlc_hw->sbclk) {
- brcms_b_xtal(wlc_hw, ON);
- }
- }
- } else {
- if (!mboolisset(wlc_hw->pllreq, req_bit))
- return;
-
- mboolclr(wlc_hw->pllreq, req_bit);
-
- if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
- if (wlc_hw->sbclk) {
- brcms_b_xtal(wlc_hw, OFF);
- }
- }
- }
-
- return;
-}
-
-u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
-{
- u16 table_ptr;
- u8 phy_rate, index;
-
- /* get the phy specific rate encoding for the PLCP SIGNAL field */
- if (IS_OFDM(rate))
- table_ptr = M_RT_DIRMAP_A;
- else
- table_ptr = M_RT_DIRMAP_B;
-
- /* for a given rate, the LS-nibble of the PLCP SIGNAL field is
- * the index into the rate table.
- */
- phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
- index = phy_rate & 0xf;
-
- /* Find the SHM pointer to the rate table entry by looking in the
- * Direct-map Table
- */
- return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2));
-}
-
-void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
-{
- wlc_hw->antsel_avail = antsel_avail;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/bmac.h b/drivers/staging/brcm80211/brcmsmac/bmac.h
deleted file mode 100644
index 3c9ad4f3bd22..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/bmac.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef _BRCM_BOTTOM_MAC_H_
-#define _BRCM_BOTTOM_MAC_H_
-
-#include <brcmu_wifi.h>
-#include "types.h"
-
-/* dup state between BMAC(struct brcms_hardware) and HIGH(struct brcms_c_info)
- driver */
-struct brcms_b_state {
- u32 machwcap; /* mac hw capibility */
- u32 preamble_ovr; /* preamble override */
-};
-
-enum {
- IOV_BMAC_DIAG,
- IOV_BMAC_SBGPIOTIMERVAL,
- IOV_BMAC_SBGPIOOUT,
- IOV_BMAC_CCGPIOCTRL, /* CC GPIOCTRL REG */
- IOV_BMAC_CCGPIOOUT, /* CC GPIOOUT REG */
- IOV_BMAC_CCGPIOOUTEN, /* CC GPIOOUTEN REG */
- IOV_BMAC_CCGPIOIN, /* CC GPIOIN REG */
- IOV_BMAC_WPSGPIO, /* WPS push button GPIO pin */
- IOV_BMAC_OTPDUMP,
- IOV_BMAC_OTPSTAT,
- IOV_BMAC_PCIEASPM, /* obfuscation clkreq/aspm control */
- IOV_BMAC_PCIEADVCORRMASK, /* advanced correctable error mask */
- IOV_BMAC_PCIECLKREQ, /* PCIE 1.1 clockreq enab support */
- IOV_BMAC_PCIELCREG, /* PCIE LCREG */
- IOV_BMAC_SBGPIOTIMERMASK,
- IOV_BMAC_RFDISABLEDLY,
- IOV_BMAC_PCIEREG, /* PCIE REG */
- IOV_BMAC_PCICFGREG, /* PCI Config register */
- IOV_BMAC_PCIESERDESREG, /* PCIE SERDES REG (dev, 0}offset) */
- IOV_BMAC_PCIEGPIOOUT, /* PCIEOUT REG */
- IOV_BMAC_PCIEGPIOOUTEN, /* PCIEOUTEN REG */
- IOV_BMAC_PCIECLKREQENCTRL, /* clkreqenctrl REG (PCIE REV > 6.0 */
- IOV_BMAC_DMALPBK,
- IOV_BMAC_CCREG,
- IOV_BMAC_COREREG,
- IOV_BMAC_SDCIS,
- IOV_BMAC_SDIO_DRIVE,
- IOV_BMAC_OTPW,
- IOV_BMAC_NVOTPW,
- IOV_BMAC_SROM,
- IOV_BMAC_SRCRC,
- IOV_BMAC_CIS_SOURCE,
- IOV_BMAC_CISVAR,
- IOV_BMAC_OTPLOCK,
- IOV_BMAC_OTP_CHIPID,
- IOV_BMAC_CUSTOMVAR1,
- IOV_BMAC_BOARDFLAGS,
- IOV_BMAC_BOARDFLAGS2,
- IOV_BMAC_WPSLED,
- IOV_BMAC_NVRAM_SOURCE,
- IOV_BMAC_OTP_RAW_READ,
- IOV_BMAC_LAST
-};
-
-extern int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
- uint unit, bool piomode, void *regsva, uint bustype,
- void *btparam);
-extern int brcms_b_detach(struct brcms_c_info *wlc);
-extern void brcms_b_watchdog(void *arg);
-
-/* up/down, reset, clk */
-extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw,
- uint offset, const void *buf, int len,
- u32 sel);
-extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset,
- void *buf, int len, u32 sel);
-#define brcms_b_copyfrom_shm(wlc_hw, offset, buf, len) \
- brcms_b_copyfrom_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
-#define brcms_b_copyto_shm(wlc_hw, offset, buf, len) \
- brcms_b_copyto_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
-
-extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
-extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on);
-extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk);
-extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk);
-extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
-extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
-extern void brcms_b_reset(struct brcms_hardware *wlc_hw);
-extern void brcms_b_init(struct brcms_hardware *wlc_hw, chanspec_t chanspec,
- bool mute);
-extern int brcms_b_up_prep(struct brcms_hardware *wlc_hw);
-extern int brcms_b_up_finish(struct brcms_hardware *wlc_hw);
-extern int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw);
-extern int brcms_b_down_finish(struct brcms_hardware *wlc_hw);
-extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode);
-
-/* chanspec, ucode interface */
-extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw,
- chanspec_t chanspec,
- bool mute, struct txpwr_limits *txpwr);
-
-extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
- uint *blocks);
-extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask,
- u16 val, int bands);
-extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
-extern u16 brcms_b_mhf_get(struct brcms_hardware *wlc_hw, u8 idx, int bands);
-extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant);
-extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw);
-extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw,
- u8 antsel_type);
-extern int brcms_b_state_get(struct brcms_hardware *wlc_hw,
- struct brcms_b_state *state);
-extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset,
- u16 v);
-extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
-extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw,
- int offset, int len, void *buf);
-extern void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf,
- uint *len);
-
-extern void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw,
- u8 *ea);
-
-extern bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw);
-extern void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw,
- bool shortslot);
-extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw,
- u8 stf_mode);
-
-extern void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw);
-
-extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
- u32 override_bit);
-extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
- u32 override_bit);
-
-extern void brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw,
- int match_reg_offset,
- const u8 *addr);
-extern void brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw,
- void *bcn, int len, bool both);
-
-extern void brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
- u32 *tsf_h_ptr);
-extern void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin);
-extern void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax);
-
-extern void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL,
- u16 LRL);
-
-extern void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw);
-
-
-/* API for BMAC driver (e.g. wlc_phy.c etc) */
-
-extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
-extern void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set,
- mbool req_bit);
-extern void brcms_b_hw_up(struct brcms_hardware *wlc_hw);
-extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate);
-extern void brcms_b_antsel_set(struct brcms_hardware *wlc_hw,
- u32 antsel_avail);
-
-#endif /* _BRCM_BOTTOM_MAC_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/channel.h b/drivers/staging/brcm80211/brcmsmac/channel.h
deleted file mode 100644
index d22f2f5f592d..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/channel.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BRCM_CHANNEL_H_
-#define _BRCM_CHANNEL_H_
-
-/* conversion for phy txpwr calculations that use .25 dB units */
-#define BRCMS_TXPWR_DB_FACTOR 4
-
-
-/* maxpwr mapping to 5GHz band channels:
- * maxpwr[0] - channels [34-48]
- * maxpwr[1] - channels [52-60]
- * maxpwr[2] - channels [62-64]
- * maxpwr[3] - channels [100-140]
- * maxpwr[4] - channels [149-165]
- */
-#define BAND_5G_PWR_LVLS 5 /* 5 power levels for 5G */
-
-/* power level in group of 2.4GHz band channels:
- * maxpwr[0] - CCK channels [1]
- * maxpwr[1] - CCK channels [2-10]
- * maxpwr[2] - CCK channels [11-14]
- * maxpwr[3] - OFDM channels [1]
- * maxpwr[4] - OFDM channels [2-10]
- * maxpwr[5] - OFDM channels [11-14]
- */
-
-/* macro to get 2.4 GHz channel group index for tx power */
-#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2)) /* cck index */
-#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5)) /* ofdm index */
-
-/* macro to get 5 GHz channel group index for tx power */
-#define CHANNEL_POWER_IDX_5G(c) \
- (((c) < 52) ? 0 : (((c) < 62) ? 1 : (((c) < 100) ? 2 : (((c) < 149) ? 3 : 4))))
-
-/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
-#define BRCMS_MAXPWR_TBL_SIZE 6
-/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
-#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14
-
-#define NBANDS(wlc) ((wlc)->pub->_nbands)
-#define NBANDS_PUB(pub) ((pub)->_nbands)
-#define NBANDS_HW(hw) ((hw)->_nbands)
-
-#define IS_SINGLEBAND_5G(device) 0
-
-/* locale channel and power info. */
-struct locale_info {
- u32 valid_channels;
- /* List of radar sensitive channels */
- u8 radar_channels;
- /* List of channels used only if APs are detected */
- u8 restricted_channels;
- /* Max tx pwr in qdBm for each sub-band */
- s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
- s8 pub_maxpwr[BAND_5G_PWR_LVLS]; /* Country IE advertised max tx pwr in dBm
- * per sub-band
- */
- u8 flags;
-};
-
-/* bits for locale_info flags */
-#define BRCMS_PEAK_CONDUCTED 0x00 /* Peak for locals */
-#define BRCMS_EIRP 0x01 /* Flag for EIRP */
-#define BRCMS_DFS_TPC 0x02 /* Flag for DFS TPC */
-#define BRCMS_NO_OFDM 0x04 /* Flag for No OFDM */
-#define BRCMS_NO_40MHZ 0x08 /* Flag for No MIMO 40MHz */
-#define BRCMS_NO_MIMO 0x10 /* Flag for No MIMO, 20 or 40 MHz */
-#define BRCMS_RADAR_TYPE_EU 0x20 /* Flag for EU */
-#define BRCMS_DFS_FCC BRCMS_DFS_TPC /* Flag for DFS FCC */
-#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */
-
-#define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU)
-
-/* locale per-channel tx power limits for MIMO frames
- * maxpwr arrays are index by channel for 2.4 GHz limits, and
- * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
- */
-struct locale_mimo_info {
- /* tx 20 MHz power limits, qdBm units */
- s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
- /* tx 40 MHz power limits, qdBm units */
- s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
- u8 flags;
-};
-
-extern const chanvec_t chanvec_all_2G;
-extern const chanvec_t chanvec_all_5G;
-
-/*
- * Country names and abbreviations with locale defined from ISO 3166
- */
-struct country_info {
- const u8 locale_2G; /* 2.4G band locale */
- const u8 locale_5G; /* 5G band locale */
- const u8 locale_mimo_2G; /* 2.4G mimo info */
- const u8 locale_mimo_5G; /* 5G mimo info */
-};
-
-extern struct brcms_cm_info *
-brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
-
-extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
-
-extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit);
-
-extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm,
- chanspec_t chspec);
-
-extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm,
- chanspec_t chanspec,
- struct txpwr_limits *txpwr);
-extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
- chanspec_t chanspec,
- u8 local_constraint_qdbm);
-
-#endif /* _WLC_CHANNEL_H */
diff --git a/drivers/staging/brcm80211/brcmsmac/dma.c b/drivers/staging/brcm80211/brcmsmac/dma.c
deleted file mode 100644
index ea17671efb63..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/dma.c
+++ /dev/null
@@ -1,1917 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-
-#if defined(__mips__)
-#include <asm/addrspace.h>
-#endif
-
-#include <brcmu_utils.h>
-#include <aiutils.h>
-#include "types.h"
-#include "dma.h"
-
-/*
- * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical address.
- */
-#define D64RINGALIGN_BITS 13
-#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS)
-#define D64RINGALIGN (1 << D64RINGALIGN_BITS)
-
-#define D64MAXDD (D64MAXRINGSZ / sizeof(struct dma64desc))
-
-/* transmit channel control */
-#define D64_XC_XE 0x00000001 /* transmit enable */
-#define D64_XC_SE 0x00000002 /* transmit suspend request */
-#define D64_XC_LE 0x00000004 /* loopback enable */
-#define D64_XC_FL 0x00000010 /* flush request */
-#define D64_XC_PD 0x00000800 /* parity check disable */
-#define D64_XC_AE 0x00030000 /* address extension bits */
-#define D64_XC_AE_SHIFT 16
-
-/* transmit descriptor table pointer */
-#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */
-
-/* transmit channel status */
-#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */
-#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */
-#define D64_XS0_XS_SHIFT 28
-#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */
-#define D64_XS0_XS_ACTIVE 0x10000000 /* active */
-#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */
-#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */
-#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */
-
-#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */
-#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */
-#define D64_XS1_XE_SHIFT 28
-#define D64_XS1_XE_NOERR 0x00000000 /* no error */
-#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */
-#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */
-#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */
-#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */
-#define D64_XS1_XE_COREE 0x50000000 /* core error */
-
-/* receive channel control */
-#define D64_RC_RE 0x00000001 /* receive enable */
-#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */
-#define D64_RC_RO_SHIFT 1
-#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */
-#define D64_RC_SH 0x00000200 /* separate rx header descriptor enable */
-#define D64_RC_OC 0x00000400 /* overflow continue */
-#define D64_RC_PD 0x00000800 /* parity check disable */
-#define D64_RC_AE 0x00030000 /* address extension bits */
-#define D64_RC_AE_SHIFT 16
-
-/* flags for dma controller */
-#define DMA_CTRL_PEN (1 << 0) /* partity enable */
-#define DMA_CTRL_ROC (1 << 1) /* rx overflow continue */
-#define DMA_CTRL_RXMULTI (1 << 2) /* allow rx scatter to multiple descriptors */
-#define DMA_CTRL_UNFRAMED (1 << 3) /* Unframed Rx/Tx data */
-
-/* receive descriptor table pointer */
-#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */
-
-/* receive channel status */
-#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */
-#define D64_RS0_RS_MASK 0xf0000000 /* receive state */
-#define D64_RS0_RS_SHIFT 28
-#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */
-#define D64_RS0_RS_ACTIVE 0x10000000 /* active */
-#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */
-#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */
-#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */
-
-#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */
-#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */
-#define D64_RS1_RE_SHIFT 28
-#define D64_RS1_RE_NOERR 0x00000000 /* no error */
-#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */
-#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */
-#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */
-#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */
-#define D64_RS1_RE_COREE 0x50000000 /* core error */
-
-/* fifoaddr */
-#define D64_FA_OFF_MASK 0xffff /* offset */
-#define D64_FA_SEL_MASK 0xf0000 /* select */
-#define D64_FA_SEL_SHIFT 16
-#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */
-#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */
-#define D64_FA_SEL_RDD 0x40000 /* receive dma data */
-#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */
-#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */
-#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */
-#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */
-#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */
-#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */
-#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */
-
-/* descriptor control flags 1 */
-#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */
-#define D64_CTRL1_EOT ((u32)1 << 28) /* end of descriptor table */
-#define D64_CTRL1_IOC ((u32)1 << 29) /* interrupt on completion */
-#define D64_CTRL1_EOF ((u32)1 << 30) /* end of frame */
-#define D64_CTRL1_SOF ((u32)1 << 31) /* start of frame */
-
-/* descriptor control flags 2 */
-#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count. real data len must <= 16KB */
-#define D64_CTRL2_AE 0x00030000 /* address extension bits */
-#define D64_CTRL2_AE_SHIFT 16
-#define D64_CTRL2_PARITY 0x00040000 /* parity bit */
-
-/* control flags in the range [27:20] are core-specific and not defined here */
-#define D64_CTRL_CORE_MASK 0x0ff00000
-
-#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */
-#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */
-#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1 */
-#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */
-
-#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */
-#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */
-#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */
-#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */
-
-/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF).
- * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL.
- * There is a compile time check in wlc.c which ensure that this value is at least as big
- * as TXOFF. This value is used in dma_rxfill (dma.c).
- */
-
-#define BCMEXTRAHDROOM 172
-
-/* debug/trace */
-#ifdef BCMDBG
-#define DMA_ERROR(args) \
- do { \
- if (!(*di->msg_level & 1)) \
- ; \
- else \
- printk args; \
- } while (0)
-#define DMA_TRACE(args) \
- do { \
- if (!(*di->msg_level & 2)) \
- ; \
- else \
- printk args; \
- } while (0)
-#else
-#define DMA_ERROR(args)
-#define DMA_TRACE(args)
-#endif /* BCMDBG */
-
-#define DMA_NONE(args)
-
-typedef unsigned long dmaaddr_t;
-#define PHYSADDRHI(_pa) (0)
-#define PHYSADDRHISET(_pa, _val)
-#define PHYSADDRLO(_pa) ((_pa))
-#define PHYSADDRLOSET(_pa, _val) \
- do { \
- (_pa) = (_val); \
- } while (0)
-
-#define d64txregs dregs.d64_u.txregs_64
-#define d64rxregs dregs.d64_u.rxregs_64
-#define txd64 dregs.d64_u.txd_64
-#define rxd64 dregs.d64_u.rxd_64
-
-/* default dma message level (if input msg_level pointer is null in dma_attach()) */
-static uint dma_msg_level;
-
-#define MAXNAMEL 8 /* 8 char names */
-
-#define DI_INFO(dmah) ((dma_info_t *)dmah)
-
-#define R_SM(r) (*(r))
-#define W_SM(r, v) (*(r) = (v))
-
-/* One physical DMA segment */
-struct dma_seg {
- dmaaddr_t addr;
- u32 length;
-};
-
-struct dma_seg_map {
- void *oshdmah; /* Opaque handle for OSL to store its information */
- uint origsize; /* Size of the virtual packet */
- uint nsegs;
- struct dma_seg segs[MAX_DMA_SEGS];
-};
-
-/*
- * DMA Descriptor
- * Descriptors are only read by the hardware, never written back.
- */
-struct dma64desc {
- u32 ctrl1; /* misc control bits & bufcount */
- u32 ctrl2; /* buffer count and address extension */
- u32 addrlow; /* memory address of the date buffer, bits 31:0 */
- u32 addrhigh; /* memory address of the date buffer, bits 63:32 */
-};
-
-/* 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 */
-
- void *pbus; /* bus handle */
-
- bool dma64; /* this dma engine is operating in 64-bit mode */
- bool addrext; /* this dma engine supports DmaExtendedAddrChanges */
-
- union {
- struct {
- dma64regs_t *txregs_64; /* 64-bit dma tx engine registers */
- dma64regs_t *rxregs_64; /* 64-bit dma rx engine registers */
- /* pointer to dma64 tx descriptor ring */
- struct dma64desc *txd_64;
- /* pointer to dma64 rx descriptor ring */
- struct dma64desc *rxd_64;
- } d64_u;
- } dregs;
-
- u16 dmadesc_align; /* alignment requirement for dma descriptors */
-
- u16 ntxd; /* # tx descriptors tunable */
- u16 txin; /* index of next descriptor to reclaim */
- u16 txout; /* index of next descriptor to post */
- void **txp; /* pointer to parallel array of pointers to packets */
- struct dma_seg_map *txp_dmah; /* DMA MAP meta-data handle */
- dmaaddr_t txdpa; /* Aligned physical address of descriptor ring */
- dmaaddr_t txdpaorig; /* Original physical address of descriptor ring */
- u16 txdalign; /* #bytes added to alloc'd mem to align txd */
- u32 txdalloc; /* #bytes allocated for the ring */
- u32 xmtptrbase; /* When using unaligned descriptors, the ptr register
- * is not just an index, it needs all 13 bits to be
- * an offset from the addr register.
- */
-
- u16 nrxd; /* # rx descriptors tunable */
- u16 rxin; /* index of next descriptor to reclaim */
- u16 rxout; /* index of next descriptor to post */
- void **rxp; /* pointer to parallel array of pointers to packets */
- struct dma_seg_map *rxp_dmah; /* DMA MAP meta-data handle */
- dmaaddr_t rxdpa; /* Aligned physical address of descriptor ring */
- dmaaddr_t rxdpaorig; /* Original physical address of descriptor ring */
- u16 rxdalign; /* #bytes added to alloc'd mem to align rxd */
- u32 rxdalloc; /* #bytes allocated for the ring */
- u32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */
-
- /* tunables */
- unsigned int rxbufsize; /* rx buffer size in bytes,
- * not including the extra headroom
- */
- uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper stack
- * e.g. some rx pkt buffers will be bridged to tx side
- * without byte copying. The extra headroom needs to be
- * large enough to fit txheader needs.
- * Some dongle driver may not need it.
- */
- uint nrxpost; /* # rx buffers to keep posted */
- unsigned int rxoffset; /* rxcontrol offset */
- uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */
- uint ddoffsethigh; /* high 32 bits */
- uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */
- uint dataoffsethigh; /* high 32 bits */
- bool aligndesc_4k; /* descriptor base need to be aligned or not */
-};
-
-/* DMA Scatter-gather list is supported. Note this is limited to TX direction only */
-#ifdef BCMDMASGLISTOSL
-#define DMASGLIST_ENAB true
-#else
-#define DMASGLIST_ENAB false
-#endif /* BCMDMASGLISTOSL */
-
-/* descriptor bumping macros */
-#define XXD(x, n) ((x) & ((n) - 1)) /* faster than %, but n must be power of 2 */
-#define TXD(x) XXD((x), di->ntxd)
-#define RXD(x) XXD((x), di->nrxd)
-#define NEXTTXD(i) TXD((i) + 1)
-#define PREVTXD(i) TXD((i) - 1)
-#define NEXTRXD(i) RXD((i) + 1)
-#define PREVRXD(i) RXD((i) - 1)
-
-#define NTXDACTIVE(h, t) TXD((t) - (h))
-#define NRXDACTIVE(h, t) RXD((t) - (h))
-
-/* macros to convert between byte offsets and indexes */
-#define B2I(bytes, type) ((bytes) / sizeof(type))
-#define I2B(index, type) ((index) * sizeof(type))
-
-#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */
-#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */
-
-#define PCI64ADDR_HIGH 0x80000000 /* address[63] */
-#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */
-
-/* Common prototypes */
-static bool _dma_isaddrext(struct dma_info *di);
-static bool _dma_descriptor_align(struct dma_info *di);
-static bool _dma_alloc(struct dma_info *di, uint direction);
-static void _dma_detach(struct dma_info *di);
-static void _dma_ddtable_init(struct dma_info *di, uint direction,
- dmaaddr_t pa);
-static void _dma_rxinit(struct dma_info *di);
-static void *_dma_rx(struct dma_info *di);
-static bool _dma_rxfill(struct dma_info *di);
-static void _dma_rxreclaim(struct dma_info *di);
-static void _dma_rxenable(struct dma_info *di);
-static void *_dma_getnextrxp(struct dma_info *di, bool forceall);
-static void _dma_rx_param_get(struct dma_info *di, u16 *rxoffset,
- u16 *rxbufsize);
-
-static void _dma_txblock(struct dma_info *di);
-static void _dma_txunblock(struct dma_info *di);
-static uint _dma_txactive(struct dma_info *di);
-static uint _dma_rxactive(struct dma_info *di);
-static uint _dma_txpending(struct dma_info *di);
-static uint _dma_txcommitted(struct dma_info *di);
-
-static void *_dma_peeknexttxp(struct dma_info *di);
-static void *_dma_peeknextrxp(struct dma_info *di);
-static unsigned long _dma_getvar(struct dma_info *di, const char *name);
-static void _dma_counterreset(struct dma_info *di);
-static void _dma_fifoloopbackenable(struct dma_info *di);
-static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags);
-static u8 dma_align_sizetobits(uint size);
-static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
- u16 *alignbits, uint *alloced,
- dmaaddr_t *descpa);
-
-/* Prototypes for 64-bit routines */
-static bool dma64_alloc(struct dma_info *di, uint direction);
-static bool dma64_txreset(struct dma_info *di);
-static bool dma64_rxreset(struct dma_info *di);
-static bool dma64_txsuspendedidle(struct dma_info *di);
-static int dma64_txfast(struct dma_info *di, struct sk_buff *p0, bool commit);
-static int dma64_txunframed(struct dma_info *di, void *p0, uint len,
- bool commit);
-static void *dma64_getpos(struct dma_info *di, bool direction);
-static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range);
-static void *dma64_getnextrxp(struct dma_info *di, bool forceall);
-static void dma64_txrotate(struct dma_info *di);
-
-static bool dma64_rxidle(struct dma_info *di);
-static void dma64_txinit(struct dma_info *di);
-static bool dma64_txenabled(struct dma_info *di);
-static void dma64_txsuspend(struct dma_info *di);
-static void dma64_txresume(struct dma_info *di);
-static bool dma64_txsuspended(struct dma_info *di);
-static void dma64_txreclaim(struct dma_info *di, enum txd_range range);
-static bool dma64_txstopped(struct dma_info *di);
-static bool dma64_rxstopped(struct dma_info *di);
-static bool dma64_rxenabled(struct dma_info *di);
-static bool _dma64_addrext(dma64regs_t *dma64regs);
-
-static inline u32 parity32(u32 data);
-
-const struct di_fcn_s dma64proc = {
- (di_detach_t) _dma_detach,
- (di_txinit_t) dma64_txinit,
- (di_txreset_t) dma64_txreset,
- (di_txenabled_t) dma64_txenabled,
- (di_txsuspend_t) dma64_txsuspend,
- (di_txresume_t) dma64_txresume,
- (di_txsuspended_t) dma64_txsuspended,
- (di_txsuspendedidle_t) dma64_txsuspendedidle,
- (di_txfast_t) dma64_txfast,
- (di_txunframed_t) dma64_txunframed,
- (di_getpos_t) dma64_getpos,
- (di_txstopped_t) dma64_txstopped,
- (di_txreclaim_t) dma64_txreclaim,
- (di_getnexttxp_t) dma64_getnexttxp,
- (di_peeknexttxp_t) _dma_peeknexttxp,
- (di_txblock_t) _dma_txblock,
- (di_txunblock_t) _dma_txunblock,
- (di_txactive_t) _dma_txactive,
- (di_txrotate_t) dma64_txrotate,
-
- (di_rxinit_t) _dma_rxinit,
- (di_rxreset_t) dma64_rxreset,
- (di_rxidle_t) dma64_rxidle,
- (di_rxstopped_t) dma64_rxstopped,
- (di_rxenable_t) _dma_rxenable,
- (di_rxenabled_t) dma64_rxenabled,
- (di_rx_t) _dma_rx,
- (di_rxfill_t) _dma_rxfill,
- (di_rxreclaim_t) _dma_rxreclaim,
- (di_getnextrxp_t) _dma_getnextrxp,
- (di_peeknextrxp_t) _dma_peeknextrxp,
- (di_rxparam_get_t) _dma_rx_param_get,
-
- (di_fifoloopbackenable_t) _dma_fifoloopbackenable,
- (di_getvar_t) _dma_getvar,
- (di_counterreset_t) _dma_counterreset,
- (di_ctrlflags_t) _dma_ctrlflags,
- NULL,
- NULL,
- NULL,
- (di_rxactive_t) _dma_rxactive,
- (di_txpending_t) _dma_txpending,
- (di_txcommitted_t) _dma_txcommitted,
- 39
-};
-
-struct dma_pub *dma_attach(char *name, struct si_pub *sih,
- void *dmaregstx, void *dmaregsrx, uint ntxd,
- uint nrxd, uint rxbufsize, int rxextheadroom,
- uint nrxpost, uint rxoffset, uint *msg_level)
-{
- struct dma_info *di;
- uint size;
-
- /* allocate private info structure */
- di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC);
- if (di == NULL) {
-#ifdef BCMDBG
- printk(KERN_ERR "dma_attach: out of memory\n");
-#endif
- return NULL;
- }
-
- di->msg_level = msg_level ? msg_level : &dma_msg_level;
-
-
- di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64);
-
- /* init dma reg pointer */
- di->d64txregs = (dma64regs_t *) dmaregstx;
- di->d64rxregs = (dma64regs_t *) dmaregsrx;
- di->dma.di_fn = (const struct di_fcn_s *)&dma64proc;
-
- /* Default flags (which can be changed by the driver calling dma_ctrlflags
- * before enable): For backwards compatibility both Rx Overflow Continue
- * and Parity are DISABLED.
- * supports it.
- */
- di->dma.di_fn->ctrlflags(&di->dma, DMA_CTRL_ROC | DMA_CTRL_PEN,
- 0);
-
- DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d "
- "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
- "dmaregstx %p dmaregsrx %p\n", name, "DMA64",
- di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
- rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx));
-
- /* make a private copy of our callers name */
- strncpy(di->name, name, MAXNAMEL);
- di->name[MAXNAMEL - 1] = '\0';
-
- di->pbus = ((struct si_info *)sih)->pbus;
-
- /* save tunables */
- di->ntxd = (u16) ntxd;
- di->nrxd = (u16) nrxd;
-
- /* the actual dma size doesn't include the extra headroom */
- di->rxextrahdrroom =
- (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom;
- if (rxbufsize > BCMEXTRAHDROOM)
- di->rxbufsize = (u16) (rxbufsize - di->rxextrahdrroom);
- else
- di->rxbufsize = (u16) rxbufsize;
-
- di->nrxpost = (u16) nrxpost;
- di->rxoffset = (u8) rxoffset;
-
- /*
- * figure out the DMA physical address offset for dd and data
- * PCI/PCIE: they map silicon backplace address to zero based memory, need offset
- * Other bus: use zero
- * SI_BUS BIGENDIAN kludge: use sdram swapped region for data buffer, not descriptor
- */
- di->ddoffsetlow = 0;
- di->dataoffsetlow = 0;
- /* for pci bus, add offset */
- if (sih->bustype == PCI_BUS) {
- /* pcie with DMA64 */
- di->ddoffsetlow = 0;
- di->ddoffsethigh = SI_PCIE_DMA_H32;
- di->dataoffsetlow = di->ddoffsetlow;
- di->dataoffsethigh = di->ddoffsethigh;
- }
-#if defined(__mips__) && defined(IL_BIGENDIAN)
- di->dataoffsetlow = di->dataoffsetlow + SI_SDRAM_SWAPPED;
-#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */
- /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
- if ((ai_coreid(sih) == SDIOD_CORE_ID)
- && ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2)))
- di->addrext = 0;
- else if ((ai_coreid(sih) == I2S_CORE_ID) &&
- ((ai_corerev(sih) == 0) || (ai_corerev(sih) == 1)))
- di->addrext = 0;
- else
- di->addrext = _dma_isaddrext(di);
-
- /* does the descriptors need to be aligned and if yes, on 4K/8K or not */
- di->aligndesc_4k = _dma_descriptor_align(di);
- if (di->aligndesc_4k) {
- di->dmadesc_align = D64RINGALIGN_BITS;
- if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) {
- /* for smaller dd table, HW relax alignment reqmnt */
- di->dmadesc_align = D64RINGALIGN_BITS - 1;
- }
- } else
- di->dmadesc_align = 4; /* 16 byte alignment */
-
- DMA_NONE(("DMA descriptor align_needed %d, align %d\n",
- di->aligndesc_4k, di->dmadesc_align));
-
- /* allocate tx packet pointer vector */
- if (ntxd) {
- size = ntxd * sizeof(void *);
- di->txp = kzalloc(size, GFP_ATOMIC);
- if (di->txp == NULL) {
- DMA_ERROR(("%s: dma_attach: out of tx memory\n", di->name));
- goto fail;
- }
- }
-
- /* allocate rx packet pointer vector */
- if (nrxd) {
- size = nrxd * sizeof(void *);
- di->rxp = kzalloc(size, GFP_ATOMIC);
- if (di->rxp == NULL) {
- DMA_ERROR(("%s: dma_attach: out of rx memory\n", di->name));
- goto fail;
- }
- }
-
- /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */
- if (ntxd) {
- if (!_dma_alloc(di, DMA_TX))
- goto fail;
- }
-
- /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */
- if (nrxd) {
- if (!_dma_alloc(di, DMA_RX))
- goto fail;
- }
-
- if ((di->ddoffsetlow != 0) && !di->addrext) {
- if (PHYSADDRLO(di->txdpa) > SI_PCI_DMA_SZ) {
- DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->txdpa)));
- goto fail;
- }
- if (PHYSADDRLO(di->rxdpa) > SI_PCI_DMA_SZ) {
- DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(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));
-
- /* allocate DMA mapping vectors */
- if (DMASGLIST_ENAB) {
- if (ntxd) {
- size = ntxd * sizeof(struct dma_seg_map);
- di->txp_dmah = kzalloc(size, GFP_ATOMIC);
- if (di->txp_dmah == NULL)
- goto fail;
- }
-
- if (nrxd) {
- size = nrxd * sizeof(struct dma_seg_map);
- di->rxp_dmah = kzalloc(size, GFP_ATOMIC);
- if (di->rxp_dmah == NULL)
- goto fail;
- }
- }
-
- return (struct dma_pub *) di;
-
- fail:
- _dma_detach(di);
- return NULL;
-}
-
-/* Check for odd number of 1's */
-static inline u32 parity32(u32 data)
-{
- data ^= data >> 16;
- data ^= data >> 8;
- data ^= data >> 4;
- data ^= data >> 2;
- data ^= data >> 1;
-
- return data & 1;
-}
-
-#define DMA64_DD_PARITY(dd) parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2)
-
-static inline void
-dma64_dd_upd(struct dma_info *di, struct dma64desc *ddring,
- dmaaddr_t pa, uint outidx, u32 *flags, u32 bufcount)
-{
- u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK;
-
- /* PCI bus with big(>1G) physical address, use address extension */
-#if defined(__mips__) && defined(IL_BIGENDIAN)
- if ((di->dataoffsetlow == SI_SDRAM_SWAPPED)
- || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
-#else
- if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
-#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */
-
- W_SM(&ddring[outidx].addrlow,
- BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
- W_SM(&ddring[outidx].addrhigh,
- BUS_SWAP32(PHYSADDRHI(pa) + di->dataoffsethigh));
- W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags));
- W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2));
- } else {
- /* address extension for 32-bit PCI */
- u32 ae;
-
- ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
- PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
-
- ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE;
- W_SM(&ddring[outidx].addrlow,
- BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
- W_SM(&ddring[outidx].addrhigh,
- BUS_SWAP32(0 + di->dataoffsethigh));
- W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags));
- W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2));
- }
- if (di->dma.dmactrlflags & DMA_CTRL_PEN) {
- if (DMA64_DD_PARITY(&ddring[outidx])) {
- W_SM(&ddring[outidx].ctrl2,
- BUS_SWAP32(ctrl2 | D64_CTRL2_PARITY));
- }
- }
-}
-
-static bool _dma_alloc(struct dma_info *di, uint direction)
-{
- return dma64_alloc(di, direction);
-}
-
-void *dma_alloc_consistent(struct pci_dev *pdev, uint size, u16 align_bits,
- uint *alloced, unsigned long *pap)
-{
- if (align_bits) {
- u16 align = (1 << align_bits);
- if (!IS_ALIGNED(PAGE_SIZE, align))
- size += align;
- *alloced = size;
- }
- return pci_alloc_consistent(pdev, size, (dma_addr_t *) pap);
-}
-
-/* !! may be called with core in reset */
-static void _dma_detach(struct dma_info *di)
-{
-
- DMA_TRACE(("%s: dma_detach\n", di->name));
-
- /* free dma descriptor rings */
- if (di->txd64)
- pci_free_consistent(di->pbus, di->txdalloc,
- ((s8 *)di->txd64 - di->txdalign),
- (di->txdpaorig));
- if (di->rxd64)
- pci_free_consistent(di->pbus, di->rxdalloc,
- ((s8 *)di->rxd64 - di->rxdalign),
- (di->rxdpaorig));
-
- /* free packet pointer vectors */
- kfree(di->txp);
- kfree(di->rxp);
-
- /* free tx packet DMA handles */
- kfree(di->txp_dmah);
-
- /* free rx packet DMA handles */
- kfree(di->rxp_dmah);
-
- /* free our private info structure */
- kfree(di);
-
-}
-
-static bool _dma_descriptor_align(struct dma_info *di)
-{
- u32 addrl;
-
- /* Check to see if the descriptors need to be aligned on 4K/8K or not */
- if (di->d64txregs != NULL) {
- W_REG(&di->d64txregs->addrlow, 0xff0);
- addrl = R_REG(&di->d64txregs->addrlow);
- if (addrl != 0)
- return false;
- } else if (di->d64rxregs != NULL) {
- W_REG(&di->d64rxregs->addrlow, 0xff0);
- addrl = R_REG(&di->d64rxregs->addrlow);
- if (addrl != 0)
- return false;
- }
- return true;
-}
-
-/* return true if this dma engine supports DmaExtendedAddrChanges, otherwise false */
-static bool _dma_isaddrext(struct dma_info *di)
-{
- /* DMA64 supports full 32- or 64-bit operation. AE is always valid */
-
- /* not all tx or rx channel are available */
- if (di->d64txregs != NULL) {
- if (!_dma64_addrext(di->d64txregs)) {
- DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have "
- "AE set\n", di->name));
- }
- return true;
- } else if (di->d64rxregs != NULL) {
- if (!_dma64_addrext(di->d64rxregs)) {
- DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have "
- "AE set\n", di->name));
- }
- return true;
- }
- return false;
-}
-
-/* initialize descriptor table base address */
-static void _dma_ddtable_init(struct dma_info *di, uint direction, dmaaddr_t pa)
-{
- if (!di->aligndesc_4k) {
- if (direction == DMA_TX)
- di->xmtptrbase = PHYSADDRLO(pa);
- else
- di->rcvptrbase = PHYSADDRLO(pa);
- }
-
- if ((di->ddoffsetlow == 0)
- || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
- if (direction == DMA_TX) {
- W_REG(&di->d64txregs->addrlow,
- (PHYSADDRLO(pa) + di->ddoffsetlow));
- W_REG(&di->d64txregs->addrhigh,
- (PHYSADDRHI(pa) + di->ddoffsethigh));
- } else {
- W_REG(&di->d64rxregs->addrlow,
- (PHYSADDRLO(pa) + di->ddoffsetlow));
- W_REG(&di->d64rxregs->addrhigh,
- (PHYSADDRHI(pa) + di->ddoffsethigh));
- }
- } else {
- /* DMA64 32bits address extension */
- u32 ae;
-
- /* shift the high bit(s) from pa to ae */
- ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >>
- PCI32ADDR_HIGH_SHIFT;
- PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
-
- if (direction == DMA_TX) {
- W_REG(&di->d64txregs->addrlow,
- (PHYSADDRLO(pa) + di->ddoffsetlow));
- W_REG(&di->d64txregs->addrhigh,
- di->ddoffsethigh);
- SET_REG(&di->d64txregs->control,
- D64_XC_AE, (ae << D64_XC_AE_SHIFT));
- } else {
- W_REG(&di->d64rxregs->addrlow,
- (PHYSADDRLO(pa) + di->ddoffsetlow));
- W_REG(&di->d64rxregs->addrhigh,
- di->ddoffsethigh);
- SET_REG(&di->d64rxregs->control,
- D64_RC_AE, (ae << D64_RC_AE_SHIFT));
- }
- }
-}
-
-static void _dma_fifoloopbackenable(struct dma_info *di)
-{
- DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name));
-
- OR_REG(&di->d64txregs->control, D64_XC_LE);
-}
-
-static void _dma_rxinit(struct dma_info *di)
-{
- DMA_TRACE(("%s: dma_rxinit\n", di->name));
-
- if (di->nrxd == 0)
- return;
-
- di->rxin = di->rxout = 0;
-
- /* clear rx descriptor ring */
- memset((void *)di->rxd64, '\0',
- (di->nrxd * sizeof(struct dma64desc)));
-
- /* DMA engine with out alignment requirement requires table to be inited
- * before enabling the engine
- */
- if (!di->aligndesc_4k)
- _dma_ddtable_init(di, DMA_RX, di->rxdpa);
-
- _dma_rxenable(di);
-
- if (di->aligndesc_4k)
- _dma_ddtable_init(di, DMA_RX, di->rxdpa);
-}
-
-static void _dma_rxenable(struct dma_info *di)
-{
- uint dmactrlflags = di->dma.dmactrlflags;
- u32 control;
-
- DMA_TRACE(("%s: dma_rxenable\n", di->name));
-
- control =
- (R_REG(&di->d64rxregs->control) & D64_RC_AE) |
- D64_RC_RE;
-
- if ((dmactrlflags & DMA_CTRL_PEN) == 0)
- control |= D64_RC_PD;
-
- if (dmactrlflags & DMA_CTRL_ROC)
- control |= D64_RC_OC;
-
- W_REG(&di->d64rxregs->control,
- ((di->rxoffset << D64_RC_RO_SHIFT) | control));
-}
-
-static void
-_dma_rx_param_get(struct dma_info *di, u16 *rxoffset, u16 *rxbufsize)
-{
- /* the normal values fit into 16 bits */
- *rxoffset = (u16) di->rxoffset;
- *rxbufsize = (u16) di->rxbufsize;
-}
-
-/* !! rx entry routine
- * returns a pointer to the next frame received, or NULL if there are no more
- * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is supported
- * with pkts chain
- * otherwise, it's treated as giant pkt and will be tossed.
- * The DMA scattering starts with normal DMA header, followed by first buffer data.
- * After it reaches the max size of buffer, the data continues in next DMA descriptor
- * buffer WITHOUT DMA header
- */
-static void *_dma_rx(struct dma_info *di)
-{
- struct sk_buff *p, *head, *tail;
- uint len;
- uint pkt_len;
- int resid = 0;
-
- next_frame:
- head = _dma_getnextrxp(di, false);
- if (head == NULL)
- return NULL;
-
- len = le16_to_cpu(*(u16 *) (head->data));
- DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
- dma_spin_for_len(len, head);
-
- /* set actual length */
- pkt_len = min((di->rxoffset + len), di->rxbufsize);
- __skb_trim(head, pkt_len);
- resid = len - (di->rxbufsize - di->rxoffset);
-
- /* check for single or multi-buffer rx */
- if (resid > 0) {
- tail = head;
- while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {
- tail->next = p;
- pkt_len = min(resid, (int)di->rxbufsize);
- __skb_trim(p, pkt_len);
-
- tail = p;
- resid -= di->rxbufsize;
- }
-
-#ifdef BCMDBG
- if (resid > 0) {
- uint cur;
- cur =
- B2I(((R_REG(&di->d64rxregs->status0) &
- D64_RS0_CD_MASK) -
- di->rcvptrbase) & D64_RS0_CD_MASK,
- struct dma64desc);
- DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n",
- di->rxin, di->rxout, cur));
- }
-#endif /* BCMDBG */
-
- if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
- DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n",
- di->name, len));
- brcmu_pkt_buf_free_skb(head);
- di->dma.rxgiants++;
- goto next_frame;
- }
- }
-
- return head;
-}
-
-/* post receive buffers
- * return false is refill failed completely and ring is empty
- * this will stall the rx dma and user might want to call rxfill again asap
- * This unlikely happens on memory-rich NIC, but often on memory-constrained dongle
- */
-static bool _dma_rxfill(struct dma_info *di)
-{
- struct sk_buff *p;
- u16 rxin, rxout;
- u32 flags = 0;
- uint n;
- uint i;
- dmaaddr_t pa;
- uint extra_offset = 0;
- bool ring_empty;
-
- ring_empty = false;
-
- /*
- * Determine how many receive buffers we're lacking
- * from the full complement, allocate, initialize,
- * and post them, then update the chip rx lastdscr.
- */
-
- rxin = di->rxin;
- rxout = di->rxout;
-
- n = di->nrxpost - NRXDACTIVE(rxin, rxout);
-
- DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n));
-
- if (di->rxbufsize > BCMEXTRAHDROOM)
- extra_offset = di->rxextrahdrroom;
-
- for (i = 0; i < n; i++) {
- /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the
- size to be allocated
- */
-
- p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset);
-
- if (p == NULL) {
- DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n",
- di->name));
- if (i == 0 && dma64_rxidle(di)) {
- DMA_ERROR(("%s: rxfill64: ring is empty !\n",
- di->name));
- ring_empty = true;
- }
- di->dma.rxnobuf++;
- break;
- }
- /* reserve an extra headroom, if applicable */
- if (extra_offset)
- skb_pull(p, extra_offset);
-
- /* Do a cached write instead of uncached write since DMA_MAP
- * will flush the cache.
- */
- *(u32 *) (p->data) = 0;
-
- if (DMASGLIST_ENAB)
- memset(&di->rxp_dmah[rxout], 0,
- sizeof(struct dma_seg_map));
-
- pa = pci_map_single(di->pbus, p->data,
- di->rxbufsize, PCI_DMA_FROMDEVICE);
-
- /* save the free packet pointer */
- di->rxp[rxout] = p;
-
- /* reset flags for each descriptor */
- flags = 0;
- if (rxout == (di->nrxd - 1))
- flags = D64_CTRL1_EOT;
-
- dma64_dd_upd(di, di->rxd64, pa, rxout, &flags,
- di->rxbufsize);
- rxout = NEXTRXD(rxout);
- }
-
- di->rxout = rxout;
-
- /* update the chip lastdscr pointer */
- W_REG(&di->d64rxregs->ptr,
- di->rcvptrbase + I2B(rxout, struct dma64desc));
-
- return ring_empty;
-}
-
-/* like getnexttxp but no reclaim */
-static void *_dma_peeknexttxp(struct dma_info *di)
-{
- uint end, i;
-
- if (di->ntxd == 0)
- return NULL;
-
- end =
- B2I(((R_REG(&di->d64txregs->status0) &
- D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
- struct dma64desc);
-
- for (i = di->txin; i != end; i = NEXTTXD(i))
- if (di->txp[i])
- return di->txp[i];
-
- return NULL;
-}
-
-/* like getnextrxp but not take off the ring */
-static void *_dma_peeknextrxp(struct dma_info *di)
-{
- uint end, i;
-
- if (di->nrxd == 0)
- return NULL;
-
- end =
- B2I(((R_REG(&di->d64rxregs->status0) &
- D64_RS0_CD_MASK) - di->rcvptrbase) & D64_RS0_CD_MASK,
- struct dma64desc);
-
- for (i = di->rxin; i != end; i = NEXTRXD(i))
- if (di->rxp[i])
- return di->rxp[i];
-
- return NULL;
-}
-
-static void _dma_rxreclaim(struct dma_info *di)
-{
- void *p;
-
- DMA_TRACE(("%s: dma_rxreclaim\n", di->name));
-
- while ((p = _dma_getnextrxp(di, true)))
- brcmu_pkt_buf_free_skb(p);
-}
-
-static void *_dma_getnextrxp(struct dma_info *di, bool forceall)
-{
- if (di->nrxd == 0)
- return NULL;
-
- return dma64_getnextrxp(di, forceall);
-}
-
-static void _dma_txblock(struct dma_info *di)
-{
- di->dma.txavail = 0;
-}
-
-static void _dma_txunblock(struct dma_info *di)
-{
- di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-}
-
-static uint _dma_txactive(struct dma_info *di)
-{
- return NTXDACTIVE(di->txin, di->txout);
-}
-
-static uint _dma_txpending(struct dma_info *di)
-{
- uint curr;
-
- curr =
- B2I(((R_REG(&di->d64txregs->status0) &
- D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
- struct dma64desc);
-
- return NTXDACTIVE(curr, di->txout);
-}
-
-static uint _dma_txcommitted(struct dma_info *di)
-{
- uint ptr;
- uint txin = di->txin;
-
- if (txin == di->txout)
- return 0;
-
- ptr = B2I(R_REG(&di->d64txregs->ptr), struct dma64desc);
-
- return NTXDACTIVE(di->txin, ptr);
-}
-
-static uint _dma_rxactive(struct dma_info *di)
-{
- return NRXDACTIVE(di->rxin, di->rxout);
-}
-
-static void _dma_counterreset(struct dma_info *di)
-{
- /* reset all software counter */
- di->dma.rxgiants = 0;
- di->dma.rxnobuf = 0;
- di->dma.txnobuf = 0;
-}
-
-static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
-{
- uint dmactrlflags = di->dma.dmactrlflags;
-
- if (di == NULL) {
- DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name));
- return 0;
- }
-
- dmactrlflags &= ~mask;
- dmactrlflags |= flags;
-
- /* If trying to enable parity, check if parity is actually supported */
- if (dmactrlflags & DMA_CTRL_PEN) {
- u32 control;
-
- control = R_REG(&di->d64txregs->control);
- W_REG(&di->d64txregs->control,
- control | D64_XC_PD);
- if (R_REG(&di->d64txregs->control) & D64_XC_PD) {
- /* We *can* disable it so it is supported,
- * restore control register
- */
- W_REG(&di->d64txregs->control,
- control);
- } else {
- /* Not supported, don't allow it to be enabled */
- dmactrlflags &= ~DMA_CTRL_PEN;
- }
- }
-
- di->dma.dmactrlflags = dmactrlflags;
-
- return dmactrlflags;
-}
-
-/* get the address of the var in order to change later */
-static unsigned long _dma_getvar(struct dma_info *di, const char *name)
-{
- if (!strcmp(name, "&txavail"))
- return (unsigned long)&(di->dma.txavail);
- return 0;
-}
-
-static
-u8 dma_align_sizetobits(uint size)
-{
- u8 bitpos = 0;
- while (size >>= 1) {
- bitpos++;
- }
- return bitpos;
-}
-
-/* This function ensures that the DMA descriptor ring will not get allocated
- * across Page boundary. If the allocation is done across the page boundary
- * at the first time, then it is freed and the allocation is done at
- * descriptor ring size aligned location. This will ensure that the ring will
- * not cross page boundary
- */
-static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
- u16 *alignbits, uint *alloced,
- dmaaddr_t *descpa)
-{
- void *va;
- u32 desc_strtaddr;
- u32 alignbytes = 1 << *alignbits;
-
- va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa);
-
- if (NULL == va)
- return NULL;
-
- desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes);
- if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
- & boundary)) {
- *alignbits = dma_align_sizetobits(size);
- pci_free_consistent(di->pbus, size, va, *descpa);
- va = dma_alloc_consistent(di->pbus, size, *alignbits,
- alloced, descpa);
- }
- return va;
-}
-
-/* 64-bit DMA functions */
-
-static void dma64_txinit(struct dma_info *di)
-{
- u32 control = D64_XC_XE;
-
- DMA_TRACE(("%s: dma_txinit\n", di->name));
-
- if (di->ntxd == 0)
- return;
-
- di->txin = di->txout = 0;
- di->dma.txavail = di->ntxd - 1;
-
- /* clear tx descriptor ring */
- memset((void *)di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc)));
-
- /* DMA engine with out alignment requirement requires table to be inited
- * before enabling the engine
- */
- if (!di->aligndesc_4k)
- _dma_ddtable_init(di, DMA_TX, di->txdpa);
-
- if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0)
- control |= D64_XC_PD;
- OR_REG(&di->d64txregs->control, control);
-
- /* DMA engine with alignment requirement requires table to be inited
- * before enabling the engine
- */
- if (di->aligndesc_4k)
- _dma_ddtable_init(di, DMA_TX, di->txdpa);
-}
-
-static bool dma64_txenabled(struct dma_info *di)
-{
- u32 xc;
-
- /* If the chip is dead, it is not enabled :-) */
- xc = R_REG(&di->d64txregs->control);
- return (xc != 0xffffffff) && (xc & D64_XC_XE);
-}
-
-static void dma64_txsuspend(struct dma_info *di)
-{
- DMA_TRACE(("%s: dma_txsuspend\n", di->name));
-
- if (di->ntxd == 0)
- return;
-
- OR_REG(&di->d64txregs->control, D64_XC_SE);
-}
-
-static void dma64_txresume(struct dma_info *di)
-{
- DMA_TRACE(("%s: dma_txresume\n", di->name));
-
- if (di->ntxd == 0)
- return;
-
- AND_REG(&di->d64txregs->control, ~D64_XC_SE);
-}
-
-static bool dma64_txsuspended(struct dma_info *di)
-{
- return (di->ntxd == 0) ||
- ((R_REG(&di->d64txregs->control) & D64_XC_SE) ==
- D64_XC_SE);
-}
-
-static void dma64_txreclaim(struct dma_info *di, enum txd_range range)
-{
- void *p;
-
- DMA_TRACE(("%s: dma_txreclaim %s\n", di->name,
- (range == DMA_RANGE_ALL) ? "all" :
- ((range ==
- DMA_RANGE_TRANSMITTED) ? "transmitted" :
- "transferred")));
-
- if (di->txin == di->txout)
- return;
-
- while ((p = dma64_getnexttxp(di, range))) {
- /* For unframed data, we don't have any packets to free */
- if (!(di->dma.dmactrlflags & DMA_CTRL_UNFRAMED))
- brcmu_pkt_buf_free_skb(p);
- }
-}
-
-static bool dma64_txstopped(struct dma_info *di)
-{
- return ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
- D64_XS0_XS_STOPPED);
-}
-
-static bool dma64_rxstopped(struct dma_info *di)
-{
- return ((R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK) ==
- D64_RS0_RS_STOPPED);
-}
-
-static bool dma64_alloc(struct dma_info *di, uint direction)
-{
- u16 size;
- uint ddlen;
- void *va;
- uint alloced = 0;
- u16 align;
- u16 align_bits;
-
- ddlen = sizeof(struct dma64desc);
-
- size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
- align_bits = di->dmadesc_align;
- align = (1 << align_bits);
-
- if (direction == DMA_TX) {
- va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
- &alloced, &di->txdpaorig);
- if (va == NULL) {
- DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name));
- return false;
- }
- align = (1 << align_bits);
- di->txd64 = (struct dma64desc *)
- roundup((unsigned long)va, align);
- di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);
- PHYSADDRLOSET(di->txdpa,
- PHYSADDRLO(di->txdpaorig) + di->txdalign);
- PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig));
- di->txdalloc = alloced;
- } else {
- va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
- &alloced, &di->rxdpaorig);
- if (va == NULL) {
- DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name));
- return false;
- }
- align = (1 << align_bits);
- di->rxd64 = (struct dma64desc *)
- roundup((unsigned long)va, align);
- di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);
- PHYSADDRLOSET(di->rxdpa,
- PHYSADDRLO(di->rxdpaorig) + di->rxdalign);
- PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig));
- di->rxdalloc = alloced;
- }
-
- return true;
-}
-
-static bool dma64_txreset(struct dma_info *di)
-{
- u32 status;
-
- if (di->ntxd == 0)
- return true;
-
- /* suspend tx DMA first */
- W_REG(&di->d64txregs->control, D64_XC_SE);
- SPINWAIT(((status =
- (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
- != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE)
- && (status != D64_XS0_XS_STOPPED), 10000);
-
- W_REG(&di->d64txregs->control, 0);
- SPINWAIT(((status =
- (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
- != D64_XS0_XS_DISABLED), 10000);
-
- /* wait for the last transaction to complete */
- udelay(300);
-
- return status == D64_XS0_XS_DISABLED;
-}
-
-static bool dma64_rxidle(struct dma_info *di)
-{
- DMA_TRACE(("%s: dma_rxidle\n", di->name));
-
- if (di->nrxd == 0)
- return true;
-
- return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
- (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK));
-}
-
-static bool dma64_rxreset(struct dma_info *di)
-{
- u32 status;
-
- if (di->nrxd == 0)
- return true;
-
- W_REG(&di->d64rxregs->control, 0);
- SPINWAIT(((status =
- (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK))
- != D64_RS0_RS_DISABLED), 10000);
-
- return status == D64_RS0_RS_DISABLED;
-}
-
-static bool dma64_rxenabled(struct dma_info *di)
-{
- u32 rc;
-
- rc = R_REG(&di->d64rxregs->control);
- return (rc != 0xffffffff) && (rc & D64_RC_RE);
-}
-
-static bool dma64_txsuspendedidle(struct dma_info *di)
-{
-
- if (di->ntxd == 0)
- return true;
-
- if (!(R_REG(&di->d64txregs->control) & D64_XC_SE))
- return 0;
-
- if ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
- D64_XS0_XS_IDLE)
- return 1;
-
- return 0;
-}
-
-/* Useful when sending unframed data. This allows us to get a progress report from the DMA.
- * We return a pointer to the beginning of the DATA buffer of the current descriptor.
- * If DMA is idle, we return NULL.
- */
-static void *dma64_getpos(struct dma_info *di, bool direction)
-{
- void *va;
- bool idle;
- u32 cd_offset;
-
- if (direction == DMA_TX) {
- cd_offset =
- R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK;
- idle = !NTXDACTIVE(di->txin, di->txout);
- va = di->txp[B2I(cd_offset, struct dma64desc)];
- } else {
- cd_offset =
- R_REG(&di->d64rxregs->status0) & D64_XS0_CD_MASK;
- idle = !NRXDACTIVE(di->rxin, di->rxout);
- va = di->rxp[B2I(cd_offset, struct dma64desc)];
- }
-
- /* If DMA is IDLE, return NULL */
- if (idle) {
- DMA_TRACE(("%s: DMA idle, return NULL\n", __func__));
- va = NULL;
- }
-
- return va;
-}
-
-/* TX of unframed data
- *
- * Adds a DMA ring descriptor for the data pointed to by "buf".
- * This is for DMA of a buffer of data and is unlike other dma TX functions
- * that take a pointer to a "packet"
- * Each call to this is results in a single descriptor being added for "len" bytes of
- * data starting at "buf", it doesn't handle chained buffers.
- */
-static int
-dma64_txunframed(struct dma_info *di, void *buf, uint len, bool commit)
-{
- u16 txout;
- u32 flags = 0;
- dmaaddr_t pa; /* phys addr */
-
- txout = di->txout;
-
- /* return nonzero if out of tx descriptors */
- if (NEXTTXD(txout) == di->txin)
- goto outoftxd;
-
- if (len == 0)
- return 0;
-
- pa = pci_map_single(di->pbus, buf, len, PCI_DMA_TODEVICE);
-
- flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF);
-
- if (txout == (di->ntxd - 1))
- flags |= D64_CTRL1_EOT;
-
- dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
-
- /* save the buffer pointer - used by dma_getpos */
- di->txp[txout] = buf;
-
- txout = NEXTTXD(txout);
- /* bump the tx descriptor index */
- di->txout = txout;
-
- /* kick the chip */
- if (commit) {
- W_REG(&di->d64txregs->ptr,
- di->xmtptrbase + I2B(txout, struct dma64desc));
- }
-
- /* tx flow control */
- di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
- return 0;
-
- outoftxd:
- DMA_ERROR(("%s: %s: out of txds !!!\n", di->name, __func__));
- di->dma.txavail = 0;
- di->dma.txnobuf++;
- return -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
- */
-static int dma64_txfast(struct dma_info *di, struct sk_buff *p0,
- bool commit)
-{
- struct sk_buff *p, *next;
- unsigned char *data;
- uint len;
- u16 txout;
- u32 flags = 0;
- dmaaddr_t pa;
-
- DMA_TRACE(("%s: dma_txfast\n", di->name));
-
- txout = di->txout;
-
- /*
- * Walk the chain of packet buffers
- * allocating and initializing transmit descriptor entries.
- */
- for (p = p0; p; p = next) {
- uint nsegs, j;
- struct dma_seg_map *map;
-
- data = p->data;
- len = p->len;
- next = p->next;
-
- /* return nonzero if out of tx descriptors */
- if (NEXTTXD(txout) == di->txin)
- goto outoftxd;
-
- if (len == 0)
- continue;
-
- /* get physical address of buffer start */
- if (DMASGLIST_ENAB)
- memset(&di->txp_dmah[txout], 0,
- sizeof(struct dma_seg_map));
-
- pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE);
-
- if (DMASGLIST_ENAB) {
- map = &di->txp_dmah[txout];
-
- /* See if all the segments can be accounted for */
- if (map->nsegs >
- (uint) (di->ntxd - NTXDACTIVE(di->txin, di->txout) -
- 1))
- goto outoftxd;
-
- nsegs = map->nsegs;
- } else
- nsegs = 1;
-
- for (j = 1; j <= nsegs; j++) {
- flags = 0;
- if (p == p0 && j == 1)
- flags |= D64_CTRL1_SOF;
-
- /* With a DMA segment list, Descriptor table is filled
- * using the segment list instead of looping over
- * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when
- * end of segment list is reached.
- */
- if ((!DMASGLIST_ENAB && next == NULL) ||
- (DMASGLIST_ENAB && j == nsegs))
- flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF);
- if (txout == (di->ntxd - 1))
- flags |= D64_CTRL1_EOT;
-
- if (DMASGLIST_ENAB) {
- len = map->segs[j - 1].length;
- pa = map->segs[j - 1].addr;
- }
- dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
-
- txout = NEXTTXD(txout);
- }
-
- /* See above. No need to loop over individual buffers */
- if (DMASGLIST_ENAB)
- break;
- }
-
- /* if last txd eof not set, fix it */
- if (!(flags & D64_CTRL1_EOF))
- W_SM(&di->txd64[PREVTXD(txout)].ctrl1,
- BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF));
-
- /* save the packet */
- di->txp[PREVTXD(txout)] = p0;
-
- /* bump the tx descriptor index */
- di->txout = txout;
-
- /* kick the chip */
- if (commit)
- W_REG(&di->d64txregs->ptr,
- di->xmtptrbase + I2B(txout, struct dma64desc));
-
- /* tx flow control */
- di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
- return 0;
-
- outoftxd:
- DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name));
- brcmu_pkt_buf_free_skb(p0);
- di->dma.txavail = 0;
- di->dma.txnobuf++;
- return -1;
-}
-
-/*
- * Reclaim next completed txd (txds if using chained buffers) in the range
- * specified and return associated packet.
- * If range is DMA_RANGE_TRANSMITTED, reclaim descriptors that have be
- * transmitted as noted by the hardware "CurrDescr" pointer.
- * If range is DMA_RANGE_TRANSFERED, reclaim descriptors that have be
- * transferred by the DMA as noted by the hardware "ActiveDescr" pointer.
- * If range is DMA_RANGE_ALL, reclaim all txd(s) posted to the ring and
- * return associated packet regardless of the value of hardware pointers.
- */
-static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range)
-{
- u16 start, end, i;
- u16 active_desc;
- void *txp;
-
- DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name,
- (range == DMA_RANGE_ALL) ? "all" :
- ((range ==
- DMA_RANGE_TRANSMITTED) ? "transmitted" :
- "transferred")));
-
- if (di->ntxd == 0)
- return NULL;
-
- txp = NULL;
-
- start = di->txin;
- if (range == DMA_RANGE_ALL)
- end = di->txout;
- else {
- dma64regs_t *dregs = di->d64txregs;
-
- end = (u16) (B2I(((R_REG(&dregs->status0) &
- D64_XS0_CD_MASK) -
- di->xmtptrbase) & D64_XS0_CD_MASK,
- struct dma64desc));
-
- if (range == DMA_RANGE_TRANSFERED) {
- active_desc =
- (u16) (R_REG(&dregs->status1) &
- D64_XS1_AD_MASK);
- active_desc =
- (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;
- active_desc = B2I(active_desc, struct dma64desc);
- if (end != active_desc)
- end = PREVTXD(active_desc);
- }
- }
-
- if ((start == 0) && (end > di->txout))
- goto bogus;
-
- for (i = start; i != end && !txp; i = NEXTTXD(i)) {
- dmaaddr_t pa;
- struct dma_seg_map *map = NULL;
- uint size, j, nsegs;
-
- PHYSADDRLOSET(pa,
- (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) -
- di->dataoffsetlow));
- PHYSADDRHISET(pa,
- (BUS_SWAP32(R_SM(&di->txd64[i].addrhigh)) -
- di->dataoffsethigh));
-
- if (DMASGLIST_ENAB) {
- map = &di->txp_dmah[i];
- size = map->origsize;
- nsegs = map->nsegs;
- } else {
- size =
- (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) &
- D64_CTRL2_BC_MASK);
- nsegs = 1;
- }
-
- for (j = nsegs; j > 0; j--) {
- W_SM(&di->txd64[i].addrlow, 0xdeadbeef);
- W_SM(&di->txd64[i].addrhigh, 0xdeadbeef);
-
- txp = di->txp[i];
- di->txp[i] = NULL;
- if (j > 1)
- i = NEXTTXD(i);
- }
-
- pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE);
- }
-
- di->txin = i;
-
- /* tx flow control */
- di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
- return txp;
-
- bogus:
- DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", start, end, di->txout, forceall));
- return NULL;
-}
-
-static void *dma64_getnextrxp(struct dma_info *di, bool forceall)
-{
- uint i, curr;
- void *rxp;
- dmaaddr_t pa;
-
- i = di->rxin;
-
- /* return if no packets posted */
- if (i == di->rxout)
- return NULL;
-
- curr =
- B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) -
- di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc);
-
- /* ignore curr if forceall */
- if (!forceall && (i == curr))
- return NULL;
-
- /* get the packet pointer that corresponds to the rx descriptor */
- rxp = di->rxp[i];
- di->rxp[i] = NULL;
-
- PHYSADDRLOSET(pa,
- (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) -
- di->dataoffsetlow));
- PHYSADDRHISET(pa,
- (BUS_SWAP32(R_SM(&di->rxd64[i].addrhigh)) -
- di->dataoffsethigh));
-
- /* clear this packet from the descriptor ring */
- pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE);
-
- W_SM(&di->rxd64[i].addrlow, 0xdeadbeef);
- W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef);
-
- di->rxin = NEXTRXD(i);
-
- return rxp;
-}
-
-static bool _dma64_addrext(dma64regs_t *dma64regs)
-{
- u32 w;
- OR_REG(&dma64regs->control, D64_XC_AE);
- w = R_REG(&dma64regs->control);
- AND_REG(&dma64regs->control, ~D64_XC_AE);
- return (w & D64_XC_AE) == D64_XC_AE;
-}
-
-/*
- * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin).
- */
-static void dma64_txrotate(struct dma_info *di)
-{
- u16 ad;
- uint nactive;
- uint rot;
- u16 old, new;
- u32 w;
- u16 first, last;
-
- nactive = _dma_txactive(di);
- ad = (u16) (B2I((((R_REG(&di->d64txregs->status1) &
- D64_XS1_AD_MASK) - di->xmtptrbase) &
- D64_XS1_AD_MASK), struct dma64desc));
- rot = TXD(ad - di->txin);
-
- /* full-ring case is a lot harder - don't worry about this */
- if (rot >= (di->ntxd - nactive)) {
- DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name));
- return;
- }
-
- first = di->txin;
- last = PREVTXD(di->txout);
-
- /* move entries starting at last and moving backwards to first */
- for (old = last; old != PREVTXD(first); old = PREVTXD(old)) {
- new = TXD(old + rot);
-
- /*
- * Move the tx dma descriptor.
- * EOT is set only in the last entry in the ring.
- */
- w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl1)) & ~D64_CTRL1_EOT;
- if (new == (di->ntxd - 1))
- w |= D64_CTRL1_EOT;
- W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w));
-
- w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2));
- W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w));
-
- W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow));
- W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh));
-
- /* zap the old tx dma descriptor address field */
- W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef));
- W_SM(&di->txd64[old].addrhigh, BUS_SWAP32(0xdeadbeef));
-
- /* move the corresponding txp[] entry */
- di->txp[new] = di->txp[old];
-
- /* Move the map */
- if (DMASGLIST_ENAB) {
- memcpy(&di->txp_dmah[new], &di->txp_dmah[old],
- sizeof(struct dma_seg_map));
- memset(&di->txp_dmah[old], 0,
- sizeof(struct dma_seg_map));
- }
-
- di->txp[old] = NULL;
- }
-
- /* update txin and txout */
- di->txin = ad;
- di->txout = TXD(di->txout + rot);
- di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
- /* kick the chip */
- W_REG(&di->d64txregs->ptr,
- di->xmtptrbase + I2B(di->txout, struct dma64desc));
-}
-
-uint dma_addrwidth(struct si_pub *sih, void *dmaregs)
-{
- /* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */
- /* DMA engine is 64-bit capable */
- if ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) {
- /* backplane are 64-bit capable */
- if (ai_backplane64(sih))
- /* If bus is System Backplane or PCIE then we can access 64-bits */
- if ((sih->bustype == SI_BUS) ||
- ((sih->bustype == PCI_BUS) &&
- (sih->buscoretype == PCIE_CORE_ID)))
- return DMADDRWIDTH_64;
- }
- /* DMA hardware not supported by this driver*/
- return DMADDRWIDTH_64;
-}
-
-/*
- * Mac80211 initiated actions sometimes require packets in the DMA queue to be
- * modified. The modified portion of the packet is not under control of the DMA
- * engine. This function calls a caller-supplied function for each packet in
- * the caller specified dma chain.
- */
-void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
- (void *pkt, void *arg_a), void *arg_a)
-{
- struct dma_info *di = (struct dma_info *) dmah;
- uint i = di->txin;
- uint end = di->txout;
- struct sk_buff *skb;
- struct ieee80211_tx_info *tx_info;
-
- while (i != end) {
- skb = (struct sk_buff *)di->txp[i];
- if (skb != NULL) {
- tx_info = (struct ieee80211_tx_info *)skb->cb;
- (callback_fnc)(tx_info, arg_a);
- }
- i = NEXTTXD(i);
- }
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/dma.h b/drivers/staging/brcm80211/brcmsmac/dma.h
deleted file mode 100644
index 9c8b9a6a557e..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/dma.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BRCM_DMA_H_
-#define _BRCM_DMA_H_
-
-#include "types.h" /* forward structure declarations */
-
-/* DMA structure:
- * support two DMA engines: 32 bits address or 64 bit addressing
- * basic DMA register set is per channel(transmit or receive)
- * a pair of channels is defined for convenience
- */
-
-/* 32 bits addressing */
-
-struct dma32diag { /* diag access */
- u32 fifoaddr; /* diag address */
- u32 fifodatalow; /* low 32bits of data */
- u32 fifodatahigh; /* high 32bits of data */
- u32 pad; /* reserved */
-};
-
-/* 64 bits addressing */
-
-/* dma registers per channel(xmt or rcv) */
-struct dma64regs {
- u32 control; /* enable, et al */
- u32 ptr; /* last descriptor posted to chip */
- u32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */
- u32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */
- u32 status0; /* current descriptor, xmt state */
- u32 status1; /* active descriptor, xmt error */
-};
-
-/* map/unmap direction */
-#define DMA_TX 1 /* TX direction for DMA */
-#define DMA_RX 2 /* RX direction for DMA */
-#define BUS_SWAP32(v) (v)
-
-/* range param for dma_getnexttxp() and dma_txreclaim */
-enum txd_range {
- DMA_RANGE_ALL = 1,
- DMA_RANGE_TRANSMITTED,
- DMA_RANGE_TRANSFERED
-};
-
-/* dma function type */
-typedef void (*di_detach_t) (struct dma_pub *dmah);
-typedef bool(*di_txreset_t) (struct dma_pub *dmah);
-typedef bool(*di_rxreset_t) (struct dma_pub *dmah);
-typedef bool(*di_rxidle_t) (struct dma_pub *dmah);
-typedef void (*di_txinit_t) (struct dma_pub *dmah);
-typedef bool(*di_txenabled_t) (struct dma_pub *dmah);
-typedef void (*di_rxinit_t) (struct dma_pub *dmah);
-typedef void (*di_txsuspend_t) (struct dma_pub *dmah);
-typedef void (*di_txresume_t) (struct dma_pub *dmah);
-typedef bool(*di_txsuspended_t) (struct dma_pub *dmah);
-typedef bool(*di_txsuspendedidle_t) (struct dma_pub *dmah);
-typedef int (*di_txfast_t) (struct dma_pub *dmah, struct sk_buff *p,
- bool commit);
-typedef int (*di_txunframed_t) (struct dma_pub *dmah, void *p, uint len,
- bool commit);
-typedef void *(*di_getpos_t) (struct dma_pub *di, bool direction);
-typedef void (*di_fifoloopbackenable_t) (struct dma_pub *dmah);
-typedef bool(*di_txstopped_t) (struct dma_pub *dmah);
-typedef bool(*di_rxstopped_t) (struct dma_pub *dmah);
-typedef bool(*di_rxenable_t) (struct dma_pub *dmah);
-typedef bool(*di_rxenabled_t) (struct dma_pub *dmah);
-typedef void *(*di_rx_t) (struct dma_pub *dmah);
-typedef bool(*di_rxfill_t) (struct dma_pub *dmah);
-typedef void (*di_txreclaim_t) (struct dma_pub *dmah, enum txd_range range);
-typedef void (*di_rxreclaim_t) (struct dma_pub *dmah);
-typedef unsigned long (*di_getvar_t) (struct dma_pub *dmah,
- const char *name);
-typedef void *(*di_getnexttxp_t) (struct dma_pub *dmah, enum txd_range range);
-typedef void *(*di_getnextrxp_t) (struct dma_pub *dmah, bool forceall);
-typedef void *(*di_peeknexttxp_t) (struct dma_pub *dmah);
-typedef void *(*di_peeknextrxp_t) (struct dma_pub *dmah);
-typedef void (*di_rxparam_get_t) (struct dma_pub *dmah, u16 *rxoffset,
- u16 *rxbufsize);
-typedef void (*di_txblock_t) (struct dma_pub *dmah);
-typedef void (*di_txunblock_t) (struct dma_pub *dmah);
-typedef uint(*di_txactive_t) (struct dma_pub *dmah);
-typedef void (*di_txrotate_t) (struct dma_pub *dmah);
-typedef void (*di_counterreset_t) (struct dma_pub *dmah);
-typedef uint(*di_ctrlflags_t) (struct dma_pub *dmah, uint mask, uint flags);
-typedef char *(*di_dump_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
- bool dumpring);
-typedef char *(*di_dumptx_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
- bool dumpring);
-typedef char *(*di_dumprx_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
- bool dumpring);
-typedef uint(*di_rxactive_t) (struct dma_pub *dmah);
-typedef uint(*di_txpending_t) (struct dma_pub *dmah);
-typedef uint(*di_txcommitted_t) (struct dma_pub *dmah);
-
-/* dma opsvec */
-struct di_fcn_s {
- di_detach_t detach;
- di_txinit_t txinit;
- di_txreset_t txreset;
- di_txenabled_t txenabled;
- di_txsuspend_t txsuspend;
- di_txresume_t txresume;
- di_txsuspended_t txsuspended;
- di_txsuspendedidle_t txsuspendedidle;
- di_txfast_t txfast;
- di_txunframed_t txunframed;
- di_getpos_t getpos;
- di_txstopped_t txstopped;
- di_txreclaim_t txreclaim;
- di_getnexttxp_t getnexttxp;
- di_peeknexttxp_t peeknexttxp;
- di_txblock_t txblock;
- di_txunblock_t txunblock;
- di_txactive_t txactive;
- di_txrotate_t txrotate;
-
- di_rxinit_t rxinit;
- di_rxreset_t rxreset;
- di_rxidle_t rxidle;
- di_rxstopped_t rxstopped;
- di_rxenable_t rxenable;
- di_rxenabled_t rxenabled;
- di_rx_t rx;
- di_rxfill_t rxfill;
- di_rxreclaim_t rxreclaim;
- di_getnextrxp_t getnextrxp;
- di_peeknextrxp_t peeknextrxp;
- di_rxparam_get_t rxparam_get;
-
- di_fifoloopbackenable_t fifoloopbackenable;
- di_getvar_t d_getvar;
- di_counterreset_t counterreset;
- di_ctrlflags_t ctrlflags;
- di_dump_t dump;
- di_dumptx_t dumptx;
- di_dumprx_t dumprx;
- di_rxactive_t rxactive;
- di_txpending_t txpending;
- di_txcommitted_t txcommitted;
- uint endnum;
-};
-
-/*
- * Exported data structure (read-only)
- */
-/* export structure */
-struct dma_pub {
- const struct di_fcn_s *di_fn; /* DMA function pointers */
- uint txavail; /* # free tx descriptors */
- uint dmactrlflags; /* dma control flags */
-
- /* rx error counters */
- uint rxgiants; /* rx giant frames */
- uint rxnobuf; /* rx out of dma descriptors */
- /* tx error counters */
- uint txnobuf; /* tx out of dma descriptors */
-};
-
-extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
- void *dmaregstx, void *dmaregsrx, uint ntxd,
- uint nrxd, uint rxbufsize, int rxextheadroom,
- uint nrxpost, uint rxoffset, uint *msg_level);
-
-extern const struct di_fcn_s dma64proc;
-
-#define dma_detach(di) (dma64proc.detach(di))
-#define dma_txreset(di) (dma64proc.txreset(di))
-#define dma_rxreset(di) (dma64proc.rxreset(di))
-#define dma_rxidle(di) (dma64proc.rxidle(di))
-#define dma_txinit(di) (dma64proc.txinit(di))
-#define dma_txenabled(di) (dma64proc.txenabled(di))
-#define dma_rxinit(di) (dma64proc.rxinit(di))
-#define dma_txsuspend(di) (dma64proc.txsuspend(di))
-#define dma_txresume(di) (dma64proc.txresume(di))
-#define dma_txsuspended(di) (dma64proc.txsuspended(di))
-#define dma_txsuspendedidle(di) (dma64proc.txsuspendedidle(di))
-#define dma_txfast(di, p, commit) (dma64proc.txfast(di, p, commit))
-#define dma_txunframed(di, p, l, commit)(dma64proc.txunframed(di, p, l, commit))
-#define dma_getpos(di, dir) (dma64proc.getpos(di, dir))
-#define dma_fifoloopbackenable(di) (dma64proc.fifoloopbackenable(di))
-#define dma_txstopped(di) (dma64proc.txstopped(di))
-#define dma_rxstopped(di) (dma64proc.rxstopped(di))
-#define dma_rxenable(di) (dma64proc.rxenable(di))
-#define dma_rxenabled(di) (dma64proc.rxenabled(di))
-#define dma_rx(di) (dma64proc.rx(di))
-#define dma_rxfill(di) (dma64proc.rxfill(di))
-#define dma_txreclaim(di, range) (dma64proc.txreclaim(di, range))
-#define dma_rxreclaim(di) (dma64proc.rxreclaim(di))
-#define dma_getvar(di, name) (dma64proc.d_getvar(di, name))
-#define dma_getnexttxp(di, range) (dma64proc.getnexttxp(di, range))
-#define dma_getnextrxp(di, forceall) (dma64proc.getnextrxp(di, forceall))
-#define dma_peeknexttxp(di) (dma64proc.peeknexttxp(di))
-#define dma_peeknextrxp(di) (dma64proc.peeknextrxp(di))
-#define dma_rxparam_get(di, off, bufs) (dma64proc.rxparam_get(di, off, bufs))
-
-#define dma_txblock(di) (dma64proc.txblock(di))
-#define dma_txunblock(di) (dma64proc.txunblock(di))
-#define dma_txactive(di) (dma64proc.txactive(di))
-#define dma_rxactive(di) (dma64proc.rxactive(di))
-#define dma_txrotate(di) (dma64proc.txrotate(di))
-#define dma_counterreset(di) (dma64proc.counterreset(di))
-#define dma_ctrlflags(di, mask, flags) (dma64proc.ctrlflags((di), (mask), (flags)))
-#define dma_txpending(di) (dma64proc.txpending(di))
-#define dma_txcommitted(di) (dma64proc.txcommitted(di))
-
-
-/* return addresswidth allowed
- * This needs to be done after SB attach but before dma attach.
- * SB attach provides ability to probe backplane and dma core capabilities
- * This info is needed by DMA_ALLOC_CONSISTENT in dma attach
- */
-extern uint dma_addrwidth(struct si_pub *sih, void *dmaregs);
-void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
- (void *pkt, void *arg_a), void *arg_a);
-
-/*
- * DMA(Bug) on some chips seems to declare that the packet is ready, but the
- * packet length is not updated yet (by DMA) on the expected time.
- * Workaround is to hold processor till DMA updates the length, and stay off
- * the bus to allow DMA update the length in buffer
- */
-static inline void dma_spin_for_len(uint len, struct sk_buff *head)
-{
-#if defined(__mips__)
- if (!len) {
- while (!(len = *(u16 *) KSEG1ADDR(head->data)))
- udelay(1);
-
- *(u16 *) (head->data) = cpu_to_le16((u16) len);
- }
-#endif /* defined(__mips__) */
-}
-
-#endif /* _BRCM_DMA_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/main.c b/drivers/staging/brcm80211/brcmsmac/main.c
deleted file mode 100644
index 1763c4535cd2..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/main.c
+++ /dev/null
@@ -1,6102 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/pci_ids.h>
-#include <net/mac80211.h>
-
-#include <brcm_hw_ids.h>
-#include <aiutils.h>
-#include "rate.h"
-#include "scb.h"
-#include "phy/phy_hal.h"
-#include "channel.h"
-#include "bmac.h"
-#include "antsel.h"
-#include "stf.h"
-#include "ampdu.h"
-#include "alloc.h"
-#include "mac80211_if.h"
-#include "main.h"
-
-/*
- * WPA(2) definitions
- */
-#define RSN_CAP_4_REPLAY_CNTRS 2
-#define RSN_CAP_16_REPLAY_CNTRS 3
-
-#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS
-#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS
-
-/*
- * Indication for txflowcontrol that all priority bits in
- * TXQ_STOP_FOR_PRIOFC_MASK are to be considered.
- */
-#define ALLPRIO -1
-
-/*
- * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
- */
-#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1)
-
-#define TIMER_INTERVAL_WATCHDOG 1000 /* watchdog timer, in unit of ms */
-#define TIMER_INTERVAL_RADIOCHK 800 /* radio monitor timer, in unit of ms */
-
-/* Max MPC timeout, in unit of watchdog */
-#ifndef BRCMS_MPC_MAX_DELAYCNT
-#define BRCMS_MPC_MAX_DELAYCNT 10
-#endif
-
-/* Min MPC timeout, in unit of watchdog */
-#define BRCMS_MPC_MIN_DELAYCNT 1
-#define BRCMS_MPC_THRESHOLD 3 /* MPC count threshold level */
-
-#define BEACON_INTERVAL_DEFAULT 100 /* beacon interval, in unit of 1024TU */
-#define DTIM_INTERVAL_DEFAULT 3 /* DTIM interval, in unit of beacon interval */
-
-/* Scale down delays to accommodate QT slow speed */
-#define BEACON_INTERVAL_DEF_QT 20 /* beacon interval, in unit of 1024TU */
-#define DTIM_INTERVAL_DEF_QT 1 /* DTIM interval, in unit of beacon interval */
-
-#define TBTT_ALIGN_LEEWAY_US 100 /* min leeway before first TBTT in us */
-
-/* Software feature flag defines used by wlfeatureflag */
-#define WL_SWFL_NOHWRADIO 0x0004
-#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */
-#define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */
-
-/* n-mode support capability */
-/* 2x2 includes both 1x1 & 2x2 devices
- * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
- * control it independently
- */
-#define WL_11N_2x2 1
-#define WL_11N_3x3 3
-#define WL_11N_4x4 4
-
-/* define 11n feature disable flags */
-#define WLFEATURE_DISABLE_11N 0x00000001
-#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002
-#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004
-#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008
-#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010
-#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020
-#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040
-#define WLFEATURE_DISABLE_11N_GF 0x00000080
-
-#define EDCF_ACI_MASK 0x60
-#define EDCF_ACI_SHIFT 5
-#define EDCF_ECWMIN_MASK 0x0f
-#define EDCF_ECWMAX_SHIFT 4
-#define EDCF_AIFSN_MASK 0x0f
-#define EDCF_AIFSN_MAX 15
-#define EDCF_ECWMAX_MASK 0xf0
-
-#define EDCF_AC_BE_TXOP_STA 0x0000
-#define EDCF_AC_BK_TXOP_STA 0x0000
-#define EDCF_AC_VO_ACI_STA 0x62
-#define EDCF_AC_VO_ECW_STA 0x32
-#define EDCF_AC_VI_ACI_STA 0x42
-#define EDCF_AC_VI_ECW_STA 0x43
-#define EDCF_AC_BK_ECW_STA 0xA4
-#define EDCF_AC_VI_TXOP_STA 0x005e
-#define EDCF_AC_VO_TXOP_STA 0x002f
-#define EDCF_AC_BE_ACI_STA 0x03
-#define EDCF_AC_BE_ECW_STA 0xA4
-#define EDCF_AC_BK_ACI_STA 0x27
-#define EDCF_AC_VO_TXOP_AP 0x002f
-
-#define EDCF_TXOP2USEC(txop) ((txop) << 5)
-#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1)
-
-#define APHY_SYMBOL_TIME 4
-#define APHY_PREAMBLE_TIME 16
-#define APHY_SIGNAL_TIME 4
-#define APHY_SIFS_TIME 16
-#define APHY_SERVICE_NBITS 16
-#define APHY_TAIL_NBITS 6
-#define BPHY_SIFS_TIME 10
-#define BPHY_PLCP_SHORT_TIME 96
-
-#define PREN_PREAMBLE 24
-#define PREN_MM_EXT 12
-#define PREN_PREAMBLE_EXT 4
-
-#define DOT11_MAC_HDR_LEN 24
-#define DOT11_ACK_LEN 10
-#define DOT11_BA_LEN 4
-#define DOT11_OFDM_SIGNAL_EXTENSION 6
-#define DOT11_MIN_FRAG_LEN 256
-#define DOT11_RTS_LEN 16
-#define DOT11_CTS_LEN 10
-#define DOT11_BA_BITMAP_LEN 128
-#define DOT11_MIN_BEACON_PERIOD 1
-#define DOT11_MAX_BEACON_PERIOD 0xFFFF
-#define DOT11_MAXNUMFRAGS 16
-#define DOT11_MAX_FRAG_LEN 2346
-
-#define BPHY_PLCP_TIME 192
-#define RIFS_11N_TIME 2
-
-#define WME_VER 1
-#define WME_SUBTYPE_PARAM_IE 1
-#define WME_TYPE 2
-#define WME_OUI "\x00\x50\xf2"
-
-#define AC_BE 0
-#define AC_BK 1
-#define AC_VI 2
-#define AC_VO 3
-
-/*
- * driver maintains internal 'tick'(wlc->pub->now) which increments in 1s OS timer(soft
- * watchdog) it is not a wall clock and won't increment when driver is in "down" state
- * this low resolution driver tick can be used for maintenance tasks such as phy
- * calibration and scb update
- */
-
-/* To inform the ucode of the last mcast frame posted so that it can clear moredata bit */
-#define BCMCFID(wlc, fid) brcms_b_write_shm((wlc)->hw, M_BCMC_FID, (fid))
-
-#define BRCMS_WAR16165(wlc) (wlc->pub->sih->bustype == PCI_BUS && \
- (!AP_ENAB(wlc->pub)) && (wlc->war16165))
-
-/* debug/trace */
-uint brcm_msg_level =
-#if defined(BCMDBG)
- LOG_ERROR_VAL;
-#else
- 0;
-#endif /* BCMDBG */
-
-/* Find basic rate for a given rate */
-#define BRCMS_BASIC_RATE(wlc, rspec) (IS_MCS(rspec) ? \
- (wlc)->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK].leg_ofdm] : \
- (wlc)->band->basic_rate[rspec & RSPEC_RATE_MASK])
-
-#define FRAMETYPE(r, mimoframe) (IS_MCS(r) ? mimoframe : (IS_CCK(r) ? FT_CCK : FT_OFDM))
-
-#define RFDISABLE_DEFAULT 10000000 /* rfdisable delay timer 500 ms, runs of ALP clock */
-
-#define BRCMS_TEMPSENSE_PERIOD 10 /* 10 second timeout */
-
-#define SCAN_IN_PROGRESS(x) 0
-
-#define EPI_VERSION_NUM 0x054b0b00
-
-#ifdef BCMDBG
-/* pointer to most recently allocated wl/wlc */
-static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
-#endif
-
-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 */
-};
-
-/* 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 */
-
-#define MAXMACLIST 64 /* max # source MAC matches */
-#define BCN_TEMPLATE_COUNT 2
-
-/* The BSS is generating beacons in HW */
-#define BRCMS_BSSCFG_HW_BCN 0x20
-
-#define HWBCN_ENAB(cfg) (((cfg)->flags & BRCMS_BSSCFG_HW_BCN) != 0)
-
-#define MBSS_BCN_ENAB(cfg) 0
-#define MBSS_PRB_ENAB(cfg) 0
-#define SOFTBCN_ENAB(pub) (0)
-
-/* 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 */
-};
-
-/* Check if a particular BSS config is AP or STA */
-#define BSSCFG_AP(cfg) (0)
-#define BSSCFG_STA(cfg) (1)
-#define BSSCFG_IBSS(cfg) (!(cfg)->BSS)
-
-/* As above for all non-NULL BSS configs */
-#define FOREACH_BSS(wlc, idx, cfg) \
- for (idx = 0; (int) idx < BRCMS_MAXBSSCFG; idx++) \
- if ((cfg = (wlc)->bsscfg[idx]))
-
-/* TX FIFO number to WME/802.1E Access Category */
-const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE };
-
-/* WME/802.1E Access Category to TX FIFO number */
-static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 };
-
-static bool in_send_q;
-
-/* Shared memory location index for various AC params */
-#define wme_shmemacindex(ac) wme_ac2fifo[ac]
-
-#ifdef BCMDBG
-static const char * const fifo_names[] = {
- "AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
-#else
-static const char fifo_names[6][0];
-#endif
-
-static const u8 acbitmap2maxprio[] = {
- PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK,
- PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI,
- PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO,
- PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO
-};
-
-/* currently the best mechanism for determining SIFS is the band in use */
-#define SIFS(band) ((band)->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME : \
- BPHY_SIFS_TIME);
-
-/* local prototypes */
-static u16 brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc,
- struct ieee80211_hw *hw,
- struct sk_buff *p,
- struct scb *scb, uint frag,
- uint nfrags, uint queue,
- uint next_frag_len,
- struct wsec_key *key,
- ratespec_t rspec_override);
-static void brcms_c_bss_default_init(struct brcms_c_info *wlc);
-static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc);
-static ratespec_t mac80211_wlc_set_nrate(struct brcms_c_info *wlc,
- struct brcms_band *cur_band,
- u32 int_val);
-static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc);
-static void brcms_c_watchdog(void *arg);
-static void brcms_c_watchdog_by_timer(void *arg);
-static u16 brcms_c_rate_shm_offset(struct brcms_c_info *wlc, u8 rate);
-static int brcms_c_set_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs_arg);
-static u8 brcms_c_local_constraint_qdbm(struct brcms_c_info *wlc);
-
-/* send and receive */
-static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc);
-static void brcms_c_txq_free(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi);
-static void brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi,
- bool on, int prio);
-static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc);
-static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, ratespec_t rate,
- uint length, u8 *plcp);
-static void brcms_c_compute_ofdm_plcp(ratespec_t rate, uint length, u8 *plcp);
-static void brcms_c_compute_mimo_plcp(ratespec_t rate, uint length, u8 *plcp);
-static u16 brcms_c_compute_frame_dur(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type, uint next_frag_len);
-static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc,
- struct brcms_d11rxhdr *rxh);
-static void brcms_c_recvctl(struct brcms_c_info *wlc,
- struct d11rxhdr *rxh, struct sk_buff *p);
-static uint brcms_c_calc_frame_len(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type, uint dur);
-static uint brcms_c_calc_ack_time(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type);
-static uint brcms_c_calc_cts_time(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type);
-/* interrupt, up/down, band */
-static void brcms_c_setband(struct brcms_c_info *wlc, uint bandunit);
-static chanspec_t brcms_c_init_chanspec(struct brcms_c_info *wlc);
-static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
- chanspec_t chanspec);
-static void brcms_c_bsinit(struct brcms_c_info *wlc);
-static int brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle,
- bool isOFDM, bool writeToShm);
-static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc);
-static bool brcms_c_radio_monitor_start(struct brcms_c_info *wlc);
-static void brcms_c_radio_timer(void *arg);
-static void brcms_c_radio_enable(struct brcms_c_info *wlc);
-static void brcms_c_radio_upd(struct brcms_c_info *wlc);
-
-/* scan, association, BSS */
-static uint brcms_c_calc_ba_time(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type);
-static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap);
-static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val);
-static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val);
-static void brcms_c_war16165(struct brcms_c_info *wlc, bool tx);
-
-static void brcms_c_wme_retries_write(struct brcms_c_info *wlc);
-static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc);
-static uint brcms_c_attach_module(struct brcms_c_info *wlc);
-static void brcms_c_detach_module(struct brcms_c_info *wlc);
-static void brcms_c_timers_deinit(struct brcms_c_info *wlc);
-static void brcms_c_down_led_upd(struct brcms_c_info *wlc);
-static uint brcms_c_down_del_timer(struct brcms_c_info *wlc);
-static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc);
-static int _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
- struct brcms_c_if *wlcif);
-
-/* conditions under which the PM bit should be set in outgoing frames and STAY_AWAKE is meaningful
- */
-bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
-{
- int idx;
- struct brcms_bss_cfg *cfg;
-
- /* disallow PS when one of the following global conditions meets */
- if (!wlc->pub->associated)
- return false;
-
- /* disallow PS when one of these meets when not scanning */
- if (AP_ACTIVE(wlc) || wlc->monitor)
- return false;
-
- for (idx = 0; idx < BRCMS_MAXBSSCFG; idx++) {
- cfg = wlc->bsscfg[idx];
- if (cfg && BSSCFG_STA(cfg) && cfg->associated) {
- /*
- * disallow PS when one of the following
- * bsscfg specific conditions meets
- */
- if (!cfg->BSS || !BRCMS_PORTOPEN(cfg))
- return false;
-
- if (!cfg->dtim_programmed)
- return false;
- }
- }
-
- return true;
-}
-
-void brcms_c_reset(struct brcms_c_info *wlc)
-{
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
- /* slurp up hw mac counters before core reset */
- brcms_c_statsupd(wlc);
-
- /* reset our snapshot of macstat counters */
- memset((char *)wlc->core->macstat_snapshot, 0,
- sizeof(struct macstat));
-
- brcms_b_reset(wlc->hw);
-}
-
-void brcms_c_fatal_error(struct brcms_c_info *wlc)
-{
- wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n",
- wlc->pub->unit);
- brcms_init(wlc->wl);
-}
-
-/* Return the channel the driver should initialize during brcms_c_init.
- * the channel may have to be changed from the currently configured channel
- * if other configurations are in conflict (bandlocked, 11n mode disabled,
- * invalid channel for current country, etc.)
- */
-static chanspec_t brcms_c_init_chanspec(struct brcms_c_info *wlc)
-{
- chanspec_t chanspec =
- 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
- WL_CHANSPEC_BAND_2G;
-
- return chanspec;
-}
-
-struct scb global_scb;
-
-static void brcms_c_init_scb(struct brcms_c_info *wlc, struct scb *scb)
-{
- int i;
- scb->flags = SCB_WMECAP | SCB_HTCAP;
- for (i = 0; i < NUMPRIO; i++)
- scb->seqnum[i] = 0;
-}
-
-void brcms_c_init(struct brcms_c_info *wlc)
-{
- d11regs_t *regs;
- chanspec_t chanspec;
- int i;
- struct brcms_bss_cfg *bsscfg;
- bool mute = false;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
- regs = wlc->regs;
-
- /* This will happen if a big-hammer was executed. In that case, we want to go back
- * to the channel that we were on and not new channel
- */
- if (wlc->pub->associated)
- chanspec = wlc->home_chanspec;
- else
- chanspec = brcms_c_init_chanspec(wlc);
-
- brcms_b_init(wlc->hw, chanspec, mute);
-
- /* update beacon listen interval */
- brcms_c_bcn_li_upd(wlc);
-
- /* the world is new again, so is our reported rate */
- brcms_c_reprate_init(wlc);
-
- /* write ethernet address to core */
- FOREACH_BSS(wlc, i, bsscfg) {
- brcms_c_set_mac(bsscfg);
- brcms_c_set_bssid(bsscfg);
- }
-
- /* Update tsf_cfprep if associated and up */
- if (wlc->pub->associated) {
- FOREACH_BSS(wlc, i, bsscfg) {
- if (bsscfg->up) {
- u32 bi;
-
- /* get beacon period and convert to uS */
- bi = bsscfg->current_bss->beacon_period << 10;
- /*
- * update since init path would reset
- * to default value
- */
- W_REG(&regs->tsf_cfprep,
- (bi << CFPREP_CBI_SHIFT));
-
- /* Update maccontrol PM related bits */
- brcms_c_set_ps_ctrl(wlc);
-
- break;
- }
- }
- }
-
- brcms_c_bandinit_ordered(wlc, chanspec);
-
- brcms_c_init_scb(wlc, &global_scb);
-
- /* init probe response timeout */
- brcms_c_write_shm(wlc, M_PRS_MAXTIME, wlc->prb_resp_timeout);
-
- /* init max burst txop (framebursting) */
- brcms_c_write_shm(wlc, M_MBURST_TXOP,
- (wlc->
- _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
-
- /* initialize maximum allowed duty cycle */
- brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
- brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
-
- /* Update some shared memory locations related to max AMPDU size allowed to received */
- brcms_c_ampdu_shm_upd(wlc->ampdu);
-
- /* band-specific inits */
- brcms_c_bsinit(wlc);
-
- /* Enable EDCF mode (while the MAC is suspended) */
- if (EDCF_ENAB(wlc->pub)) {
- OR_REG(&regs->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 =
- brcms_c_read_shm(wlc, M_BOM_REV_MAJOR) << NBITS(u16);
- wlc->ucode_rev |= brcms_c_read_shm(wlc, M_BOM_REV_MINOR);
- }
-
- /* ..now really unleash hell (allow the MAC out of suspend) */
- brcms_c_enable_mac(wlc);
-
- /* clear tx flow control */
- brcms_c_txflowcontrol_reset(wlc);
-
- /* clear tx data fifo suspends */
- wlc->tx_suspended = false;
-
- /* enable the RF Disable Delay timer */
- W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
-
- /* initialize mpc delay */
- wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
-
- /*
- * Initialize WME parameters; if they haven't been set by some other
- * mechanism (IOVar, etc) then read them from the hardware.
- */
- if (BRCMS_WME_RETRY_SHORT_GET(wlc, 0) == 0) {
- /* Uninitialized; read from HW */
- int ac;
-
- for (ac = 0; ac < AC_COUNT; ac++) {
- wlc->wme_retries[ac] =
- brcms_c_read_shm(wlc, M_AC_TXLMT_ADDR(ac));
- }
- }
-}
-
-void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc)
-{
- wlc->bcnmisc_monitor = promisc;
- brcms_c_mac_bcn_promisc(wlc);
-}
-
-void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc)
-{
- if ((AP_ENAB(wlc->pub) && (N_ENAB(wlc->pub) || wlc->band->gmode)) ||
- wlc->bcnmisc_ibss || wlc->bcnmisc_scan || wlc->bcnmisc_monitor)
- brcms_c_mctrl(wlc, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
- else
- brcms_c_mctrl(wlc, MCTL_BCNS_PROMISC, 0);
-}
-
-/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */
-void brcms_c_mac_promisc(struct brcms_c_info *wlc)
-{
- u32 promisc_bits = 0;
-
- /* promiscuous mode just sets MCTL_PROMISC
- * Note: APs get all BSS traffic without the need to set the MCTL_PROMISC bit
- * since all BSS data traffic is directed at the AP
- */
- if (PROMISC_ENAB(wlc->pub) && !AP_ENAB(wlc->pub))
- promisc_bits |= MCTL_PROMISC;
-
- /* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL
- * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is
- * handled in brcms_c_mac_bcn_promisc()
- */
- if (MONITOR_ENAB(wlc))
- promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL;
-
- brcms_c_mctrl(wlc, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
-}
-
-/* push sw hps and wake state through hardware */
-void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
-{
- u32 v1, v2;
- bool hps;
- bool awake_before;
-
- hps = PS_ALLOWED(wlc);
-
- BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
-
- v1 = R_REG(&wlc->regs->maccontrol);
- v2 = MCTL_WAKE;
- if (hps)
- v2 |= MCTL_HPS;
-
- brcms_c_mctrl(wlc, MCTL_WAKE | MCTL_HPS, v2);
-
- awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
-
- if (!awake_before)
- brcms_b_wait_for_wake(wlc->hw);
-
-}
-
-/*
- * Write this BSS config's MAC address to core.
- * Updates RXE match engine.
- */
-int brcms_c_set_mac(struct brcms_bss_cfg *cfg)
-{
- int err = 0;
- struct brcms_c_info *wlc = cfg->wlc;
-
- if (cfg == wlc->cfg) {
- /* enter the MAC addr into the RXE match registers */
- brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, cfg->cur_etheraddr);
- }
-
- brcms_c_ampdu_macaddr_upd(wlc);
-
- return err;
-}
-
-/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl).
- * Updates RXE match engine.
- */
-void brcms_c_set_bssid(struct brcms_bss_cfg *cfg)
-{
- struct brcms_c_info *wlc = cfg->wlc;
-
- /* if primary config, we need to update BSSID in RXE match registers */
- if (cfg == wlc->cfg) {
- brcms_c_set_addrmatch(wlc, RCM_BSSID_OFFSET, cfg->BSSID);
- }
-#ifdef SUPPORT_HWKEYS
- else if (BSSCFG_STA(cfg) && cfg->BSS) {
- brcms_c_rcmta_add_bssid(wlc, cfg);
- }
-#endif
-}
-
-/*
- * Suspend the the MAC and update the slot timing
- * for standard 11b/g (20us slots) or shortslot 11g (9us slots).
- */
-void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
-{
- int idx;
- struct brcms_bss_cfg *cfg;
-
- /* use the override if it is set */
- if (wlc->shortslot_override != BRCMS_SHORTSLOT_AUTO)
- shortslot = (wlc->shortslot_override == BRCMS_SHORTSLOT_ON);
-
- if (wlc->shortslot == shortslot)
- return;
-
- wlc->shortslot = shortslot;
-
- /* update the capability based on current shortslot mode */
- FOREACH_BSS(wlc, idx, cfg) {
- if (!cfg->associated)
- continue;
- cfg->current_bss->capability &=
- ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
- if (wlc->shortslot)
- cfg->current_bss->capability |=
- WLAN_CAPABILITY_SHORT_SLOT_TIME;
- }
-
- brcms_b_set_shortslot(wlc->hw, shortslot);
-}
-
-static u8 brcms_c_local_constraint_qdbm(struct brcms_c_info *wlc)
-{
- u8 local;
- s16 local_max;
-
- local = BRCMS_TXPWR_MAX;
- if (wlc->pub->associated &&
- (brcmu_chspec_ctlchan(wlc->chanspec) ==
- brcmu_chspec_ctlchan(wlc->home_chanspec))) {
-
- /* get the local power constraint if we are on the AP's
- * channel [802.11h, 7.3.2.13]
- */
- /* Clamp the value between 0 and BRCMS_TXPWR_MAX w/o
- * overflowing the target */
- local_max =
- (wlc->txpwr_local_max -
- wlc->txpwr_local_constraint) * BRCMS_TXPWR_DB_FACTOR;
- if (local_max > 0 && local_max < BRCMS_TXPWR_MAX)
- return (u8) local_max;
- if (local_max < 0)
- return 0;
- }
-
- return local;
-}
-
-/* propagate home chanspec to all bsscfgs in case bsscfg->current_bss->chanspec is referenced */
-void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, chanspec_t chanspec)
-{
- if (wlc->home_chanspec != chanspec) {
- int idx;
- struct brcms_bss_cfg *cfg;
-
- wlc->home_chanspec = chanspec;
-
- FOREACH_BSS(wlc, idx, cfg) {
- if (!cfg->associated)
- continue;
-
- cfg->current_bss->chanspec = chanspec;
- }
-
- }
-}
-
-static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc,
- chanspec_t chanspec)
-{
- /* Save our copy of the chanspec */
- wlc->chanspec = chanspec;
-
- /* Set the chanspec and power limits for this locale after computing
- * any 11h local tx power constraints.
- */
- brcms_c_channel_set_chanspec(wlc->cmi, chanspec,
- brcms_c_local_constraint_qdbm(wlc));
-
- if (wlc->stf->ss_algosel_auto)
- brcms_c_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel,
- chanspec);
-
- brcms_c_stf_ss_update(wlc, wlc->band);
-
-}
-
-void brcms_c_set_chanspec(struct brcms_c_info *wlc, chanspec_t chanspec)
-{
- uint bandunit;
- bool switchband = false;
- chanspec_t old_chanspec = wlc->chanspec;
-
- if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n",
- wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec));
- return;
- }
-
- /* Switch bands if necessary */
- if (NBANDS(wlc) > 1) {
- bandunit = CHSPEC_BANDUNIT(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",
- wlc->pub->unit, __func__,
- CHSPEC_CHANNEL(chanspec));
- return;
- }
- /*
- * should the setband call come after the
- * brcms_b_chanspec() ? if the setband updates
- * (brcms_c_bsinit) use low level calls to inspect and
- * set state, the state inspected may be from the wrong
- * band, or the following brcms_b_set_chanspec() may
- * undo the work.
- */
- brcms_c_setband(wlc, bandunit);
- }
- }
-
- /* sync up phy/radio chanspec */
- brcms_c_set_phy_chanspec(wlc, chanspec);
-
- /* init antenna selection */
- if (CHSPEC_WLC_BW(old_chanspec) != CHSPEC_WLC_BW(chanspec)) {
- brcms_c_antsel_init(wlc->asi);
-
- /* Fix the hardware rateset based on bw.
- * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz
- */
- brcms_c_rateset_bw_mcs_filter(&wlc->band->hw_rateset,
- wlc->band->
- mimo_cap_40 ? CHSPEC_WLC_BW(chanspec)
- : 0);
- }
-
- /* update some mac configuration since chanspec changed */
- brcms_c_ucode_mac_upd(wlc);
-}
-
-ratespec_t brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc,
- wlc_rateset_t *rs)
-{
- ratespec_t lowest_basic_rspec;
- uint i;
-
- /* Use the lowest basic rate */
- lowest_basic_rspec = rs->rates[0] & BRCMS_RATE_MASK;
- for (i = 0; i < rs->count; i++) {
- if (rs->rates[i] & BRCMS_RATE_FLAG) {
- lowest_basic_rspec = rs->rates[i] & BRCMS_RATE_MASK;
- break;
- }
- }
-#if NCONF
- /* pick siso/cdd as default for OFDM (note no basic rate MCSs are supported yet) */
- if (IS_OFDM(lowest_basic_rspec)) {
- lowest_basic_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
- }
-#endif
-
- return lowest_basic_rspec;
-}
-
-/* This function changes the phytxctl for beacon based on current beacon ratespec AND txant
- * setting as per this table:
- * ratespec CCK ant = wlc->stf->txant
- * OFDM ant = 3
- */
-void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
- ratespec_t bcn_rspec)
-{
- u16 phyctl;
- u16 phytxant = wlc->stf->phytxant;
- u16 mask = PHY_TXC_ANT_MASK;
-
- /* for non-siso rates or default setting, use the available chains */
- if (BRCMS_PHY_11N_CAP(wlc->band))
- phytxant = brcms_c_stf_phytxchain_sel(wlc, bcn_rspec);
-
- phyctl = brcms_c_read_shm(wlc, M_BCN_PCTLWD);
- phyctl = (phyctl & ~mask) | phytxant;
- brcms_c_write_shm(wlc, M_BCN_PCTLWD, phyctl);
-}
-
-/* centralized protection config change function to simplify debugging, no consistency checking
- * this should be called only on changes to avoid overhead in periodic function
-*/
-void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val)
-{
- BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val);
-
- switch (idx) {
- case BRCMS_PROT_G_SPEC:
- wlc->protection->_g = (bool) val;
- break;
- case BRCMS_PROT_G_OVR:
- wlc->protection->g_override = (s8) val;
- break;
- case BRCMS_PROT_G_USER:
- wlc->protection->gmode_user = (u8) val;
- break;
- case BRCMS_PROT_OVERLAP:
- wlc->protection->overlap = (s8) val;
- break;
- case BRCMS_PROT_N_USER:
- wlc->protection->nmode_user = (s8) val;
- break;
- case BRCMS_PROT_N_CFG:
- wlc->protection->n_cfg = (s8) val;
- break;
- case BRCMS_PROT_N_CFG_OVR:
- wlc->protection->n_cfg_override = (s8) val;
- break;
- case BRCMS_PROT_N_NONGF:
- wlc->protection->nongf = (bool) val;
- break;
- case BRCMS_PROT_N_NONGF_OVR:
- wlc->protection->nongf_override = (s8) val;
- break;
- case BRCMS_PROT_N_PAM_OVR:
- wlc->protection->n_pam_override = (s8) val;
- break;
- case BRCMS_PROT_N_OBSS:
- wlc->protection->n_obss = (bool) val;
- break;
-
- default:
- break;
- }
-
-}
-
-static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val)
-{
- wlc->ht_cap.cap_info &= ~(IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40);
- wlc->ht_cap.cap_info |= (val & BRCMS_N_SGI_20) ?
- IEEE80211_HT_CAP_SGI_20 : 0;
- wlc->ht_cap.cap_info |= (val & BRCMS_N_SGI_40) ?
- IEEE80211_HT_CAP_SGI_40 : 0;
-
- if (wlc->pub->up) {
- brcms_c_update_beacon(wlc);
- brcms_c_update_probe_resp(wlc, true);
- }
-}
-
-static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val)
-{
- wlc->stf->ldpc = val;
-
- wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_LDPC_CODING;
- if (wlc->stf->ldpc != OFF)
- wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_LDPC_CODING;
-
- if (wlc->pub->up) {
- brcms_c_update_beacon(wlc);
- brcms_c_update_probe_resp(wlc, true);
- wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false));
- }
-}
-
-/*
- * ucode, hwmac update
- * Channel dependent updates for ucode and hw
- */
-static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc)
-{
- /* enable or disable any active IBSSs depending on whether or not
- * we are on the home channel
- */
- if (wlc->home_chanspec == BRCMS_BAND_PI_RADIO_CHANSPEC) {
- if (wlc->pub->associated) {
- /* BMAC_NOTE: This is something that should be fixed in ucode inits.
- * I think that the ucode inits set up the bcn templates and shm values
- * with a bogus beacon. This should not be done in the inits. If ucode needs
- * to set up a beacon for testing, the test routines should write it down,
- * not expect the inits to populate a bogus beacon.
- */
- if (BRCMS_PHY_11N_CAP(wlc->band)) {
- brcms_c_write_shm(wlc, M_BCN_TXTSF_OFFSET,
- wlc->band->bcntsfoff);
- }
- }
- } else {
- /* disable an active IBSS if we are not on the home channel */
- }
-
- /* update the various promisc bits */
- brcms_c_mac_bcn_promisc(wlc);
- brcms_c_mac_promisc(wlc);
-}
-
-static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
- chanspec_t chanspec)
-{
- wlc_rateset_t default_rateset;
- 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
- */
- if (wlc->bandlocked || NBANDS(wlc) == 1) {
- /* updated in brcms_c_bandlock() */
- parkband = wlc->band->bandunit;
- band_order[0] = band_order[1] = parkband;
- } else {
- /* park on the band of the specified chanspec */
- parkband = CHSPEC_BANDUNIT(chanspec);
-
- /* order so that parkband initialize last */
- band_order[0] = parkband ^ 1;
- band_order[1] = parkband;
- }
-
- /* make each band operational, software state init */
- for (i = 0; i < NBANDS(wlc); i++) {
- uint j = band_order[i];
-
- wlc->band = wlc->bandstate[j];
-
- brcms_default_rateset(wlc, &default_rateset);
-
- /* fill in hw_rate */
- brcms_c_rateset_filter(&default_rateset, &wlc->band->hw_rateset,
- false, BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
- (bool) N_ENAB(wlc->pub));
-
- /* init basic rate lookup */
- brcms_c_rate_lookup_init(wlc, &default_rateset);
- }
-
- /* sync up phy/radio chanspec */
- brcms_c_set_phy_chanspec(wlc, chanspec);
-}
-
-/* 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);
-
- /* write ucode ACK/CTS rate table */
- brcms_c_set_ratetable(wlc);
-
- /* update some band specific mac configuration */
- brcms_c_ucode_mac_upd(wlc);
-
- /* init antenna selection */
- brcms_c_antsel_init(wlc->asi);
-
-}
-
-/* switch to and initialize new band */
-static void brcms_c_setband(struct brcms_c_info *wlc,
- uint bandunit)
-{
- int idx;
- struct brcms_bss_cfg *cfg;
-
- wlc->band = wlc->bandstate[bandunit];
-
- if (!wlc->pub->up)
- return;
-
- /* wait for at least one beacon before entering sleeping state */
- for (idx = 0; idx < BRCMS_MAXBSSCFG; idx++) {
- cfg = wlc->bsscfg[idx];
- if (cfg && BSSCFG_STA(cfg) && cfg->associated)
- cfg->PMawakebcn = true;
- }
- brcms_c_set_ps_ctrl(wlc);
-
- /* band-specific initializations */
- brcms_c_bsinit(wlc);
-}
-
-/* Initialize a WME Parameter Info Element with default STA parameters from WMM Spec, Table 12 */
-void
-brcms_c_wme_initparams_sta(struct brcms_c_info *wlc, struct wme_param_ie *pe)
-{
- static const struct wme_param_ie stadef = {
- WME_OUI,
- WME_TYPE,
- WME_SUBTYPE_PARAM_IE,
- WME_VER,
- 0,
- 0,
- {
- {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA,
- cpu_to_le16(EDCF_AC_BE_TXOP_STA)},
- {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA,
- cpu_to_le16(EDCF_AC_BK_TXOP_STA)},
- {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA,
- cpu_to_le16(EDCF_AC_VI_TXOP_STA)},
- {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA,
- cpu_to_le16(EDCF_AC_VO_TXOP_STA)}
- }
- };
- memcpy(pe, &stadef, sizeof(*pe));
-}
-
-void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
- const struct ieee80211_tx_queue_params *params,
- bool suspend)
-{
- int i;
- struct shm_acparams acp_shm;
- u16 *shm_entry;
-
- /* 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__);
- return;
- }
-
- do {
- memset((char *)&acp_shm, 0, sizeof(struct shm_acparams));
- /* fill in shm ac params struct */
- acp_shm.txop = le16_to_cpu(params->txop);
- /* convert from units of 32us to us for ucode */
- wlc->edcf_txop[aci & 0x3] = acp_shm.txop =
- EDCF_TXOP2USEC(acp_shm.txop);
- acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK);
-
- if (aci == AC_VI && acp_shm.txop == 0
- && acp_shm.aifs < EDCF_AIFSN_MAX)
- acp_shm.aifs++;
-
- if (acp_shm.aifs < EDCF_AIFSN_MIN
- || acp_shm.aifs > EDCF_AIFSN_MAX) {
- wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad "
- "aifs %d\n", wlc->pub->unit, acp_shm.aifs);
- continue;
- }
-
- acp_shm.cwmin = params->cw_min;
- acp_shm.cwmax = params->cw_max;
- acp_shm.cwcur = acp_shm.cwmin;
- acp_shm.bslots =
- R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur;
- acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
- /* Indicate the new params to the ucode */
- acp_shm.status = brcms_c_read_shm(wlc, (M_EDCF_QINFO +
- wme_shmemacindex(aci) *
- M_EDCF_QLEN +
- M_EDCF_STATUS_OFF));
- acp_shm.status |= WME_STATUS_NEWAC;
-
- /* Fill in shm acparam table */
- shm_entry = (u16 *) &acp_shm;
- for (i = 0; i < (int)sizeof(struct shm_acparams); i += 2)
- brcms_c_write_shm(wlc,
- M_EDCF_QINFO +
- wme_shmemacindex(aci) * M_EDCF_QLEN + i,
- *shm_entry++);
-
- } while (0);
-
- if (suspend)
- brcms_c_suspend_mac_and_wait(wlc);
-
- if (suspend)
- brcms_c_enable_mac(wlc);
-
-}
-
-void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
-{
- u16 aci;
- int i_ac;
- struct edcf_acparam *edcf_acp;
-
- struct ieee80211_tx_queue_params txq_pars;
- struct ieee80211_tx_queue_params *params = &txq_pars;
-
- /*
- * AP uses AC params from wme_param_ie_ap.
- * AP advertises AC params from wme_param_ie.
- * STA uses AC params from wme_param_ie.
- */
-
- edcf_acp = (struct edcf_acparam *) &wlc->wme_param_ie.acparam[0];
-
- for (i_ac = 0; i_ac < AC_COUNT; i_ac++, edcf_acp++) {
- /* find out which ac this set of params applies to */
- aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT;
-
- /* fill in shm ac params struct */
- params->txop = edcf_acp->TXOP;
- params->aifs = edcf_acp->ACI;
-
- /* CWmin = 2^(ECWmin) - 1 */
- params->cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK);
- /* CWmax = 2^(ECWmax) - 1 */
- params->cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK)
- >> EDCF_ECWMAX_SHIFT);
- brcms_c_wme_setparams(wlc, aci, params, suspend);
- }
-
- if (suspend)
- brcms_c_suspend_mac_and_wait(wlc);
-
- if (AP_ENAB(wlc->pub) && WME_ENAB(wlc->pub)) {
- brcms_c_update_beacon(wlc);
- brcms_c_update_probe_resp(wlc, false);
- }
-
- if (suspend)
- brcms_c_enable_mac(wlc);
-
-}
-
-bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
-{
- wlc->wdtimer = brcms_init_timer(wlc->wl, brcms_c_watchdog_by_timer,
- wlc, "watchdog");
- if (!wlc->wdtimer) {
- wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for wdtimer "
- "failed\n", unit);
- goto fail;
- }
-
- wlc->radio_timer = brcms_init_timer(wlc->wl, brcms_c_radio_timer,
- wlc, "radio");
- if (!wlc->radio_timer) {
- wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for radio_timer "
- "failed\n", unit);
- goto fail;
- }
-
- return true;
-
- fail:
- return false;
-}
-
-/*
- * Initialize brcms_c_info default values ...
- * may get overrides later in this function
- */
-void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
-{
- int i;
- /* Assume the device is there until proven otherwise */
- wlc->device_present = true;
-
- /* Save our copy of the chanspec */
- wlc->chanspec = CH20MHZ_CHSPEC(1);
-
- /* various 802.11g modes */
- wlc->shortslot = false;
- wlc->shortslot_override = BRCMS_SHORTSLOT_AUTO;
-
- brcms_c_protection_upd(wlc, BRCMS_PROT_G_OVR, BRCMS_PROTECTION_AUTO);
- brcms_c_protection_upd(wlc, BRCMS_PROT_G_SPEC, false);
-
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG_OVR,
- BRCMS_PROTECTION_AUTO);
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG, BRCMS_N_PROTECTION_OFF);
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF_OVR,
- BRCMS_PROTECTION_AUTO);
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF, false);
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, AUTO);
-
- brcms_c_protection_upd(wlc, BRCMS_PROT_OVERLAP,
- BRCMS_PROTECTION_CTL_OVERLAP);
-
- /* 802.11g draft 4.0 NonERP elt advertisement */
- wlc->include_legacy_erp = true;
-
- wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF;
- wlc->stf->txant = ANT_TX_DEF;
-
- wlc->prb_resp_timeout = BRCMS_PRB_RESP_TIMEOUT;
-
- wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN;
- for (i = 0; i < NFIFO; i++)
- wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN;
- wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN;
-
- /* default rate fallback retry limits */
- wlc->SFBL = RETRY_SHORT_FB;
- wlc->LFBL = RETRY_LONG_FB;
-
- /* default mac retry limits */
- wlc->SRL = RETRY_SHORT_DEF;
- wlc->LRL = RETRY_LONG_DEF;
-
- /* Set flag to indicate that hw keys should be used when available. */
- wlc->wsec_swkeys = false;
-
- /* init the 4 static WEP default keys */
- for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
- wlc->wsec_keys[i] = wlc->wsec_def_keys[i];
- wlc->wsec_keys[i]->idx = (u8) i;
- }
-
- /* WME QoS mode is Auto by default */
- wlc->pub->_wme = AUTO;
-
-#ifdef BCMSDIODEV_ENABLED
- wlc->pub->_priofc = true; /* enable priority flow control for sdio dongle */
-#endif
-
- wlc->pub->_ampdu = AMPDU_AGG_HOST;
- wlc->pub->bcmerror = 0;
- wlc->pub->_coex = ON;
-
- /* initialize mpc delay */
- wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
-}
-
-static bool brcms_c_state_bmac_sync(struct brcms_c_info *wlc)
-{
- struct brcms_b_state state_bmac;
-
- if (brcms_b_state_get(wlc->hw, &state_bmac) != 0)
- return false;
-
- wlc->machwcap = state_bmac.machwcap;
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR,
- (s8) state_bmac.preamble_ovr);
-
- return true;
-}
-
-static uint brcms_c_attach_module(struct brcms_c_info *wlc)
-{
- uint err = 0;
- uint unit;
- unit = wlc->pub->unit;
-
- wlc->asi = brcms_c_antsel_attach(wlc);
- if (wlc->asi == NULL) {
- wiphy_err(wlc->wiphy, "wl%d: attach: antsel_attach "
- "failed\n", unit);
- err = 44;
- goto fail;
- }
-
- wlc->ampdu = brcms_c_ampdu_attach(wlc);
- if (wlc->ampdu == NULL) {
- wiphy_err(wlc->wiphy, "wl%d: attach: ampdu_attach "
- "failed\n", unit);
- err = 50;
- goto fail;
- }
-
- if ((brcms_c_stf_attach(wlc) != 0)) {
- wiphy_err(wlc->wiphy, "wl%d: attach: stf_attach "
- "failed\n", unit);
- err = 68;
- goto fail;
- }
- fail:
- return err;
-}
-
-struct brcms_pub *brcms_c_pub(void *wlc)
-{
- return ((struct brcms_c_info *) wlc)->pub;
-}
-
-#define CHIP_SUPPORTS_11N(wlc) 1
-
-/*
- * The common driver entry routine. Error codes should be unique
- */
-void *brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
- bool piomode, void *regsva, uint bustype, void *btparam,
- uint *perr)
-{
- struct brcms_c_info *wlc;
- uint err = 0;
- uint j;
- struct brcms_pub *pub;
- uint n_disabled;
-
- /* allocate struct brcms_c_info state and its substructures */
- wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device);
- if (wlc == NULL)
- goto fail;
- wlc->wiphy = wl->wiphy;
- pub = wlc->pub;
-
-#if defined(BCMDBG)
- wlc_info_dbg = wlc;
-#endif
-
- wlc->band = wlc->bandstate[0];
- wlc->core = wlc->corestate;
- wlc->wl = wl;
- pub->unit = unit;
- pub->_piomode = piomode;
- wlc->bandinit_pending = false;
-
- /* populate struct brcms_c_info with default values */
- brcms_c_info_init(wlc, unit);
-
- /* update sta/ap related parameters */
- brcms_c_ap_upd(wlc);
-
- /* 11n_disable nvram */
- n_disabled = getintvar(pub->vars, "11n_disable");
-
- /*
- * low level attach steps(all hw accesses go
- * inside, no more in rest of the attach)
- */
- err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva,
- bustype, btparam);
- if (err)
- goto fail;
-
- /* for some states, due to different info pointer(e,g, wlc, wlc_hw) or master/slave split,
- * HIGH driver(both monolithic and HIGH_ONLY) needs to sync states FROM BMAC portion driver
- */
- if (!brcms_c_state_bmac_sync(wlc)) {
- err = 20;
- goto fail;
- }
-
- pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band);
-
- /* propagate *vars* from BMAC driver to high driver */
- brcms_b_copyfrom_vars(wlc->hw, &pub->vars, &wlc->vars_size);
-
-
- /* set maximum allowed duty cycle */
- wlc->tx_duty_cycle_ofdm =
- (u16) getintvar(pub->vars, "tx_duty_cycle_ofdm");
- wlc->tx_duty_cycle_cck =
- (u16) getintvar(pub->vars, "tx_duty_cycle_cck");
-
- brcms_c_stf_phy_chain_calc(wlc);
-
- /* txchain 1: txant 0, txchain 2: txant 1 */
- if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
- wlc->stf->txant = wlc->stf->hw_txchain - 1;
-
- /* push to BMAC driver */
- wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
- wlc->stf->hw_rxchain);
-
- /* pull up some info resulting from the low attach */
- {
- int i;
- for (i = 0; i < NFIFO; i++)
- wlc->core->txavail[i] = wlc->hw->txavail[i];
- }
-
- brcms_b_hw_etheraddr(wlc->hw, wlc->perm_etheraddr);
-
- memcpy(&pub->cur_etheraddr, &wlc->perm_etheraddr, ETH_ALEN);
-
- for (j = 0; j < NBANDS(wlc); j++) {
- /* Use band 1 for single band 11a */
- if (IS_SINGLEBAND_5G(wlc->deviceid))
- j = BAND_5G_INDEX;
-
- wlc->band = wlc->bandstate[j];
-
- if (!brcms_c_attach_stf_ant_init(wlc)) {
- err = 24;
- goto fail;
- }
-
- /* default contention windows size limits */
- wlc->band->CWmin = APHY_CWMIN;
- wlc->band->CWmax = PHY_CWMAX;
-
- /* init gmode value */
- if (BAND_2G(wlc->band->bandtype)) {
- wlc->band->gmode = GMODE_AUTO;
- brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER,
- wlc->band->gmode);
- }
-
- /* init _n_enab supported mode */
- if (BRCMS_PHY_11N_CAP(wlc->band) && CHIP_SUPPORTS_11N(wlc)) {
- if (n_disabled & WLFEATURE_DISABLE_11N) {
- pub->_n_enab = OFF;
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
- OFF);
- } else {
- pub->_n_enab = SUPPORT_11N;
- brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
- ((pub->_n_enab ==
- SUPPORT_11N) ? WL_11N_2x2 :
- WL_11N_3x3));
- }
- }
-
- /* init per-band default rateset, depend on band->gmode */
- brcms_default_rateset(wlc, &wlc->band->defrateset);
-
- /* fill in hw_rateset (used early by BRCM_SET_RATESET) */
- brcms_c_rateset_filter(&wlc->band->defrateset,
- &wlc->band->hw_rateset, false,
- BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
- (bool) N_ENAB(wlc->pub));
- }
-
- /* update antenna config due to wlc->stf->txant/txchain/ant_rx_ovr change */
- brcms_c_stf_phy_txant_upd(wlc);
-
- /* attach each modules */
- err = brcms_c_attach_module(wlc);
- if (err != 0)
- goto fail;
-
- if (!brcms_c_timers_init(wlc, unit)) {
- wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit,
- __func__);
- err = 32;
- goto fail;
- }
-
- /* depend on rateset, gmode */
- wlc->cmi = brcms_c_channel_mgr_attach(wlc);
- if (!wlc->cmi) {
- wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed"
- "\n", unit, __func__);
- err = 33;
- goto fail;
- }
-
- /* init default when all parameters are ready, i.e. ->rateset */
- brcms_c_bss_default_init(wlc);
-
- /*
- * 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[0] = wlc->cfg;
- wlc->cfg->_idx = 0;
- wlc->cfg->wlc = wlc;
- pub->txmaxpkts = MAXTXPKTS;
-
- brcms_c_wme_initparams_sta(wlc, &wlc->wme_param_ie);
-
- wlc->mimoft = FT_HT;
- wlc->ht_cap.cap_info = HT_CAP;
- if (HT_ENAB(wlc->pub))
- wlc->stf->ldpc = AUTO;
-
- wlc->mimo_40txbw = AUTO;
- wlc->ofdm_40txbw = AUTO;
- wlc->cck_40txbw = AUTO;
- brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G);
-
- /* Set default values of SGI */
- if (BRCMS_SGI_CAP_PHY(wlc)) {
- brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
- BRCMS_N_SGI_40));
- wlc->sgi_tx = AUTO;
- } else if (BRCMS_ISSSLPNPHY(wlc->band)) {
- brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
- BRCMS_N_SGI_40));
- wlc->sgi_tx = AUTO;
- } else {
- brcms_c_ht_update_sgi_rx(wlc, 0);
- wlc->sgi_tx = OFF;
- }
-
- /* *******nvram 11n config overrides Start ********* */
-
- /* apply the sgi override from nvram conf */
- if (n_disabled & WLFEATURE_DISABLE_11N_SGI_TX)
- wlc->sgi_tx = OFF;
-
- if (n_disabled & WLFEATURE_DISABLE_11N_SGI_RX)
- brcms_c_ht_update_sgi_rx(wlc, 0);
-
- /* apply the stbc override from nvram conf */
- if (n_disabled & WLFEATURE_DISABLE_11N_STBC_TX) {
- wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
- wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
- wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
- }
- if (n_disabled & WLFEATURE_DISABLE_11N_STBC_RX)
- brcms_c_stf_stbc_rx_set(wlc, HT_CAP_RX_STBC_NO);
-
- /* apply the GF override from nvram conf */
- if (n_disabled & WLFEATURE_DISABLE_11N_GF)
- wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_GRN_FLD;
-
- /* initialize radio_mpc_disable according to wlc->mpc */
- brcms_c_radio_mpc_upd(wlc);
- brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail);
-
- if (perr)
- *perr = 0;
-
- return (void *)wlc;
-
- fail:
- wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n",
- unit, __func__, err);
- if (wlc)
- brcms_c_detach(wlc);
-
- if (perr)
- *perr = err;
- return NULL;
-}
-
-static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc)
-{
- uint unit;
- unit = wlc->pub->unit;
-
- if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
- /* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
- wlc->band->antgain = 8;
- } else if (wlc->band->antgain == -1) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
- " srom, using 2dB\n", unit, __func__);
- wlc->band->antgain = 8;
- } else {
- s8 gain, fract;
- /* Older sroms specified gain in whole dbm only. In order
- * be able to specify qdbm granularity and remain backward compatible
- * the whole dbms are now encoded in only low 6 bits and remaining qdbms
- * are encoded in the hi 2 bits. 6 bit signed number ranges from
- * -32 - 31. Examples: 0x1 = 1 db,
- * 0xc1 = 1.75 db (1 + 3 quarters),
- * 0x3f = -1 (-1 + 0 quarters),
- * 0x7f = -.75 (-1 in low 6 bits + 1 quarters in hi 2 bits) = -3 qdbm.
- * 0xbf = -.50 (-1 in low 6 bits + 2 quarters in hi 2 bits) = -2 qdbm.
- */
- gain = wlc->band->antgain & 0x3f;
- gain <<= 2; /* Sign extend */
- gain >>= 2;
- fract = (wlc->band->antgain & 0xc0) >> 6;
- wlc->band->antgain = 4 * gain + fract;
- }
-}
-
-static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
-{
- int aa;
- uint unit;
- char *vars;
- int bandtype;
-
- unit = wlc->pub->unit;
- vars = wlc->pub->vars;
- bandtype = wlc->band->bandtype;
-
- /* get antennas available */
- aa = (s8) getintvar(vars, (BAND_5G(bandtype) ? "aa5g" : "aa2g"));
- if (aa == 0)
- aa = (s8) getintvar(vars,
- (BAND_5G(bandtype) ? "aa1" : "aa0"));
- if ((aa < 1) || (aa > 15)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
- " srom (0x%x), using 3\n", unit, __func__, aa);
- aa = 3;
- }
-
- /* reset the defaults if we have a single antenna */
- if (aa == 1) {
- wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0;
- wlc->stf->txant = ANT_TX_FORCE_0;
- } else if (aa == 2) {
- wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1;
- wlc->stf->txant = ANT_TX_FORCE_1;
- } else {
- }
-
- /* Compute Antenna Gain */
- wlc->band->antgain =
- (s8) getintvar(vars, (BAND_5G(bandtype) ? "ag1" : "ag0"));
- brcms_c_attach_antgain_init(wlc);
-
- return true;
-}
-
-
-static void brcms_c_timers_deinit(struct brcms_c_info *wlc)
-{
- /* free timer state */
- if (wlc->wdtimer) {
- brcms_free_timer(wlc->wl, wlc->wdtimer);
- wlc->wdtimer = NULL;
- }
- if (wlc->radio_timer) {
- brcms_free_timer(wlc->wl, wlc->radio_timer);
- wlc->radio_timer = NULL;
- }
-}
-
-static void brcms_c_detach_module(struct brcms_c_info *wlc)
-{
- if (wlc->asi) {
- brcms_c_antsel_detach(wlc->asi);
- wlc->asi = NULL;
- }
-
- if (wlc->ampdu) {
- brcms_c_ampdu_detach(wlc->ampdu);
- wlc->ampdu = NULL;
- }
-
- brcms_c_stf_detach(wlc);
-}
-
-/*
- * Return a count of the number of driver callbacks still pending.
- *
- * General policy is that brcms_c_detach can only dealloc/free software states.
- * It can NOT touch hardware registers since the d11core may be in reset and
- * clock may not be available.
- * One exception is sb register access, which is possible if crystal is turned
- * on after "down" state, driver should avoid software timer with the exception
- * of radio_monitor.
- */
-uint brcms_c_detach(struct brcms_c_info *wlc)
-{
- uint callbacks = 0;
-
- if (wlc == NULL)
- return 0;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
- callbacks += brcms_b_detach(wlc);
-
- /* delete software timers */
- if (!brcms_c_radio_monitor_stop(wlc))
- callbacks++;
-
- brcms_c_channel_mgr_detach(wlc->cmi);
-
- brcms_c_timers_deinit(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;
-}
-
-/* update state that depends on the current value of "ap" */
-void brcms_c_ap_upd(struct brcms_c_info *wlc)
-{
- if (AP_ENAB(wlc->pub))
- /* AP: short not allowed, but not enforced */
- wlc->PLCPHdr_override = BRCMS_PLCP_AUTO;
- else
- /* STA-BSS; short capable */
- wlc->PLCPHdr_override = BRCMS_PLCP_SHORT;
-
- /* fixup mpc */
- wlc->mpc = true;
-}
-
-/* read hwdisable state and propagate to wlc flag */
-static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc)
-{
- if (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO || wlc->pub->hw_off)
- return;
-
- if (brcms_b_radio_read_hwdisabled(wlc->hw)) {
- mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
- } else {
- mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
- }
-}
-
-/* return true if Minimum Power Consumption should be entered, false otherwise */
-bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc)
-{
- return false;
-}
-
-bool brcms_c_ismpc(struct brcms_c_info *wlc)
-{
- return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc));
-}
-
-void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc)
-{
- bool mpc_radio, radio_state;
-
- /*
- * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
- * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
- * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
- * the radio is going down.
- */
- if (!wlc->mpc) {
- if (!wlc->pub->radio_disabled)
- return;
- mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
- brcms_c_radio_upd(wlc);
- if (!wlc->pub->radio_disabled)
- brcms_c_radio_monitor_stop(wlc);
- return;
- }
-
- /*
- * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in wlc->pub->radio_disabled
- * to go ON, always call radio_upd synchronously
- * to go OFF, postpone radio_upd to later when context is safe(e.g. watchdog)
- */
- radio_state =
- (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
- ON);
- mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON;
-
- if (radio_state == ON && mpc_radio == OFF)
- wlc->mpc_delay_off = wlc->mpc_dlycnt;
- else if (radio_state == OFF && mpc_radio == ON) {
- mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
- brcms_c_radio_upd(wlc);
- if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD)
- wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT;
- else
- wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
- wlc->mpc_dur += OSL_SYSUPTIME() - wlc->mpc_laston_ts;
- }
- /* Below logic is meant to capture the transition from mpc off to mpc on for reasons
- * other than wlc->mpc_delay_off keeping the mpc off. In that case reset
- * wlc->mpc_delay_off to wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
- */
- if ((wlc->prev_non_delay_mpc == false) &&
- (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) {
- wlc->mpc_delay_off = wlc->mpc_dlycnt;
- }
- wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc);
-}
-
-/*
- * centralized radio disable/enable function,
- * invoke radio enable/disable after updating hwradio status
- */
-static void brcms_c_radio_upd(struct brcms_c_info *wlc)
-{
- if (wlc->pub->radio_disabled) {
- brcms_c_radio_disable(wlc);
- } else {
- brcms_c_radio_enable(wlc);
- }
-}
-
-/* maintain LED behavior in down state */
-static void brcms_c_down_led_upd(struct brcms_c_info *wlc)
-{
- /* maintain LEDs while in down state, turn on sbclk if not available yet */
- /* turn on sbclk if necessary */
- if (!AP_ENAB(wlc->pub)) {
- brcms_c_pllreq(wlc, true, BRCMS_PLLREQ_FLIP);
-
- brcms_c_pllreq(wlc, false, BRCMS_PLLREQ_FLIP);
- }
-}
-
-/* update hwradio status and return it */
-bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc)
-{
- brcms_c_radio_hwdisable_upd(wlc);
-
- return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ? true : false;
-}
-
-void brcms_c_radio_disable(struct brcms_c_info *wlc)
-{
- if (!wlc->pub->up) {
- brcms_c_down_led_upd(wlc);
- return;
- }
-
- brcms_c_radio_monitor_start(wlc);
- brcms_down(wlc->wl);
-}
-
-static void brcms_c_radio_enable(struct brcms_c_info *wlc)
-{
- if (wlc->pub->up)
- return;
-
- if (DEVICEREMOVED(wlc))
- return;
-
- brcms_up(wlc->wl);
-}
-
-/* periodical query hw radio button while driver is "down" */
-static void brcms_c_radio_timer(void *arg)
-{
- struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
-
- if (DEVICEREMOVED(wlc)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
- __func__);
- brcms_down(wlc->wl);
- return;
- }
-
- /* cap mpc off count */
- if (wlc->mpc_offcnt < BRCMS_MPC_MAX_DELAYCNT)
- wlc->mpc_offcnt++;
-
- brcms_c_radio_hwdisable_upd(wlc);
- brcms_c_radio_upd(wlc);
-}
-
-static bool brcms_c_radio_monitor_start(struct brcms_c_info *wlc)
-{
- /* Don't start the timer if HWRADIO feature is disabled */
- if (wlc->radio_monitor || (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO))
- return true;
-
- wlc->radio_monitor = true;
- brcms_c_pllreq(wlc, true, BRCMS_PLLREQ_RADIO_MON);
- brcms_add_timer(wlc->wl, wlc->radio_timer, TIMER_INTERVAL_RADIOCHK,
- true);
- return true;
-}
-
-bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc)
-{
- if (!wlc->radio_monitor)
- return true;
-
- wlc->radio_monitor = false;
- brcms_c_pllreq(wlc, false, BRCMS_PLLREQ_RADIO_MON);
- return brcms_del_timer(wlc->wl, wlc->radio_timer);
-}
-
-static void brcms_c_watchdog_by_timer(void *arg)
-{
- brcms_c_watchdog(arg);
-}
-
-/* common watchdog code */
-static void brcms_c_watchdog(void *arg)
-{
- struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
- int i;
- struct brcms_bss_cfg *cfg;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
- if (!wlc->pub->up)
- return;
-
- if (DEVICEREMOVED(wlc)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
- __func__);
- brcms_down(wlc->wl);
- return;
- }
-
- /* increment second count */
- wlc->pub->now++;
-
- /* delay radio disable */
- if (wlc->mpc_delay_off) {
- if (--wlc->mpc_delay_off == 0) {
- mboolset(wlc->pub->radio_disabled,
- WL_RADIO_MPC_DISABLE);
- if (wlc->mpc && brcms_c_ismpc(wlc))
- wlc->mpc_offcnt = 0;
- wlc->mpc_laston_ts = OSL_SYSUPTIME();
- }
- }
-
- /* mpc sync */
- brcms_c_radio_mpc_upd(wlc);
- /* radio sync: sw/hw/mpc --> radio_disable/radio_enable */
- brcms_c_radio_hwdisable_upd(wlc);
- brcms_c_radio_upd(wlc);
- /* if radio is disable, driver may be down, quit here */
- if (wlc->pub->radio_disabled)
- return;
-
- brcms_b_watchdog(wlc);
-
- /* occasionally sample mac stat counters to detect 16-bit counter wrap */
- if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0)
- brcms_c_statsupd(wlc);
-
- /* Manage TKIP countermeasures timers */
- FOREACH_BSS(wlc, i, cfg) {
- if (cfg->tk_cm_dt) {
- cfg->tk_cm_dt--;
- }
- if (cfg->tk_cm_bt) {
- cfg->tk_cm_bt--;
- }
- }
-
- /* Call any registered watchdog handlers */
- for (i = 0; i < BRCMS_MAXMODULES; i++) {
- if (wlc->modulecb[i].watchdog_fn)
- wlc->modulecb[i].watchdog_fn(wlc->modulecb[i].hdl);
- }
-
- if (BRCMS_ISNPHY(wlc->band) && !wlc->pub->tempsense_disable &&
- ((wlc->pub->now - wlc->tempsense_lasttime) >=
- BRCMS_TEMPSENSE_PERIOD)) {
- wlc->tempsense_lasttime = wlc->pub->now;
- brcms_c_tempsense_upd(wlc);
- }
-}
-
-/* make interface operational */
-int brcms_c_up(struct brcms_c_info *wlc)
-{
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
- /* HW is turned off so don't try to access it */
- if (wlc->pub->hw_off || DEVICEREMOVED(wlc))
- return -ENOMEDIUM;
-
- if (!wlc->pub->hw_up) {
- brcms_b_hw_up(wlc->hw);
- wlc->pub->hw_up = true;
- }
-
- if ((wlc->pub->boardflags & BFL_FEM)
- && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) {
- if (wlc->pub->boardrev >= 0x1250
- && (wlc->pub->boardflags & BFL_FEM_BT)) {
- brcms_c_mhf(wlc, MHF5, MHF5_4313_GPIOCTRL,
- MHF5_4313_GPIOCTRL, BRCM_BAND_ALL);
- } else {
- brcms_c_mhf(wlc, MHF4, MHF4_EXTPA_ENABLE,
- MHF4_EXTPA_ENABLE, BRCM_BAND_ALL);
- }
- }
-
- /*
- * Need to read the hwradio status here to cover the case where the system
- * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
- * if radio is disabled, abort up, lower power, start radio timer and return 0(for NDIS)
- * don't call radio_update to avoid looping brcms_c_up.
- *
- * brcms_b_up_prep() returns either 0 or -BCME_RADIOOFF only
- */
- if (!wlc->pub->radio_disabled) {
- int status = brcms_b_up_prep(wlc->hw);
- if (status == -ENOMEDIUM) {
- if (!mboolisset
- (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) {
- int idx;
- struct brcms_bss_cfg *bsscfg;
- mboolset(wlc->pub->radio_disabled,
- WL_RADIO_HW_DISABLE);
-
- FOREACH_BSS(wlc, idx, bsscfg) {
- if (!BSSCFG_STA(bsscfg)
- || !bsscfg->enable || !bsscfg->BSS)
- continue;
- wiphy_err(wlc->wiphy, "wl%d.%d: up"
- ": rfdisable -> "
- "bsscfg_disable()\n",
- wlc->pub->unit, idx);
- }
- }
- }
- }
-
- if (wlc->pub->radio_disabled) {
- brcms_c_radio_monitor_start(wlc);
- return 0;
- }
-
- /* brcms_b_up_prep has done brcms_c_corereset(). so clk is on, set it */
- wlc->clk = true;
-
- brcms_c_radio_monitor_stop(wlc);
-
- /* Set EDCF hostflags */
- if (EDCF_ENAB(wlc->pub)) {
- brcms_c_mhf(wlc, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL);
- } else {
- brcms_c_mhf(wlc, MHF1, MHF1_EDCF, 0, BRCM_BAND_ALL);
- }
-
- if (BRCMS_WAR16165(wlc))
- brcms_c_mhf(wlc, MHF2, MHF2_PCISLOWCLKWAR, MHF2_PCISLOWCLKWAR,
- BRCM_BAND_ALL);
-
- brcms_init(wlc->wl);
- wlc->pub->up = true;
-
- if (wlc->bandinit_pending) {
- brcms_c_suspend_mac_and_wait(wlc);
- brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec);
- wlc->bandinit_pending = false;
- brcms_c_enable_mac(wlc);
- }
-
- brcms_b_up_finish(wlc->hw);
-
- /* other software states up after ISR is running */
- /* start APs that were to be brought up but are not up yet */
- /* if (AP_ENAB(wlc->pub)) brcms_c_restart_ap(wlc->ap); */
-
- /* Program the TX wme params with the current settings */
- brcms_c_wme_retries_write(wlc);
-
- /* start one second watchdog timer */
- brcms_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true);
- wlc->WDarmed = true;
-
- /* ensure antenna config is up to date */
- brcms_c_stf_phy_txant_upd(wlc);
- /* ensure LDPC config is in sync */
- brcms_c_ht_update_ldpc(wlc, wlc->stf->ldpc);
-
- 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));
-
- /* For non-WME, both fifos have overlapping MAXPRIO. So just disable all precedences
- * if either is full.
- */
- if (!EDCF_ENAB(wlc->pub)) {
- wlc->fifo2prec_map[TX_DATA_FIFO] = BRCMS_PREC_BMP_ALL;
- wlc->fifo2prec_map[TX_CTL_FIFO] = BRCMS_PREC_BMP_ALL;
- } else {
- 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 uint brcms_c_down_del_timer(struct brcms_c_info *wlc)
-{
- uint callbacks = 0;
-
- return callbacks;
-}
-
-/*
- * Mark the interface nonoperational, stop the software mechanisms,
- * disable the hardware, free any transient buffer state.
- * Return a count of the number of driver callbacks still pending.
- */
-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);
-
- /* 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__);
- return 0;
- }
- if (!wlc->pub->up)
- return callbacks;
-
- /* in between, mpc could try to bring down again.. */
- wlc->going_down = true;
-
- callbacks += brcms_b_bmac_down_prep(wlc->hw);
-
- dev_gone = DEVICEREMOVED(wlc);
-
- /* Call any registered down handlers */
- for (i = 0; i < BRCMS_MAXMODULES; i++) {
- if (wlc->modulecb[i].down_fn)
- callbacks +=
- wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl);
- }
-
- /* cancel the watchdog timer */
- if (wlc->WDarmed) {
- if (!brcms_del_timer(wlc->wl, wlc->wdtimer))
- callbacks++;
- wlc->WDarmed = false;
- }
- /* cancel all other timers */
- callbacks += brcms_c_down_del_timer(wlc);
-
- wlc->pub->up = false;
-
- 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 */
- wlc->clk = false;
-
- wlc->going_down = false;
- return callbacks;
-}
-
-/* Set the current gmode configuration */
-int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
-{
- int ret = 0;
- uint i;
- wlc_rateset_t rs;
- /* Default to 54g Auto */
- /* Advertise and use shortslot (-1/0/1 Auto/Off/On) */
- s8 shortslot = BRCMS_SHORTSLOT_AUTO;
- bool shortslot_restrict = false; /* Restrict association to stations that support shortslot
- */
- bool ofdm_basic = false; /* Make 6, 12, and 24 basic rates */
- /* Advertise and use short preambles (-1/0/1 Auto/Off/On) */
- int preamble = BRCMS_PLCP_LONG;
- bool preamble_restrict = false; /* Restrict association to stations that support short
- * preambles
- */
- struct brcms_band *band;
-
- /* if N-support is enabled, allow Gmode set as long as requested
- * Gmode is not GMODE_LEGACY_B
- */
- if (N_ENAB(wlc->pub) && gmode == GMODE_LEGACY_B)
- return -ENOTSUPP;
-
- /* verify that we are dealing with 2G band and grab the band pointer */
- if (wlc->band->bandtype == BRCM_BAND_2G)
- band = wlc->band;
- else if ((NBANDS(wlc) > 1) &&
- (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == BRCM_BAND_2G))
- band = wlc->bandstate[OTHERBANDUNIT(wlc)];
- else
- return -EINVAL;
-
- /* Legacy or bust when no OFDM is supported by regulatory */
- if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
- BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B))
- return -EINVAL;
-
- /* update configuration value */
- if (config == true)
- brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
-
- /* Clear supported rates filter */
- memset(&wlc->sup_rates_override, 0, sizeof(wlc_rateset_t));
-
- /* Clear rateset override */
- memset(&rs, 0, sizeof(wlc_rateset_t));
-
- switch (gmode) {
- case GMODE_LEGACY_B:
- shortslot = BRCMS_SHORTSLOT_OFF;
- brcms_c_rateset_copy(&gphy_legacy_rates, &rs);
-
- break;
-
- case GMODE_LRS:
- if (AP_ENAB(wlc->pub))
- brcms_c_rateset_copy(&cck_rates,
- &wlc->sup_rates_override);
- break;
-
- case GMODE_AUTO:
- /* Accept defaults */
- break;
-
- case GMODE_ONLY:
- ofdm_basic = true;
- preamble = BRCMS_PLCP_SHORT;
- preamble_restrict = true;
- break;
-
- case GMODE_PERFORMANCE:
- if (AP_ENAB(wlc->pub)) /* Put all rates into the Supported Rates element */
- brcms_c_rateset_copy(&cck_ofdm_rates,
- &wlc->sup_rates_override);
-
- shortslot = BRCMS_SHORTSLOT_ON;
- shortslot_restrict = true;
- ofdm_basic = true;
- preamble = BRCMS_PLCP_SHORT;
- preamble_restrict = true;
- break;
-
- default:
- /* Error */
- wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n",
- wlc->pub->unit, __func__, gmode);
- return -ENOTSUPP;
- }
-
- /*
- * If we are switching to gmode == GMODE_LEGACY_B,
- * clean up rate info that may refer to OFDM rates.
- */
- if ((gmode == GMODE_LEGACY_B) && (band->gmode != GMODE_LEGACY_B)) {
- band->gmode = gmode;
- if (band->rspec_override && !IS_CCK(band->rspec_override)) {
- band->rspec_override = 0;
- brcms_c_reprate_init(wlc);
- }
- if (band->mrspec_override && !IS_CCK(band->mrspec_override)) {
- band->mrspec_override = 0;
- }
- }
-
- band->gmode = gmode;
-
- wlc->shortslot_override = shortslot;
-
- if (AP_ENAB(wlc->pub)) {
- /* wlc->ap->shortslot_restrict = shortslot_restrict; */
- wlc->PLCPHdr_override =
- (preamble !=
- BRCMS_PLCP_LONG) ? BRCMS_PLCP_SHORT : BRCMS_PLCP_AUTO;
- }
-
- if ((AP_ENAB(wlc->pub) && preamble != BRCMS_PLCP_LONG)
- || preamble == BRCMS_PLCP_SHORT)
- wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
- else
- wlc->default_bss->capability &= ~WLAN_CAPABILITY_SHORT_PREAMBLE;
-
- /* Update shortslot capability bit for AP and IBSS */
- if ((AP_ENAB(wlc->pub) && shortslot == BRCMS_SHORTSLOT_AUTO) ||
- shortslot == BRCMS_SHORTSLOT_ON)
- wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
- else
- wlc->default_bss->capability &=
- ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
-
- /* Use the default 11g rateset */
- if (!rs.count)
- brcms_c_rateset_copy(&cck_ofdm_rates, &rs);
-
- if (ofdm_basic) {
- for (i = 0; i < rs.count; i++) {
- if (rs.rates[i] == BRCM_RATE_6M
- || rs.rates[i] == BRCM_RATE_12M
- || rs.rates[i] == BRCM_RATE_24M)
- rs.rates[i] |= BRCMS_RATE_FLAG;
- }
- }
-
- /* Set default bss rateset */
- wlc->default_bss->rateset.count = rs.count;
- memcpy(wlc->default_bss->rateset.rates, rs.rates,
- sizeof(wlc->default_bss->rateset.rates));
-
- return ret;
-}
-
-static int brcms_c_nmode_validate(struct brcms_c_info *wlc, s32 nmode)
-{
- int err = 0;
-
- switch (nmode) {
-
- case OFF:
- break;
-
- case AUTO:
- case WL_11N_2x2:
- case WL_11N_3x3:
- if (!(BRCMS_PHY_11N_CAP(wlc->band)))
- err = -EINVAL;
- break;
-
- default:
- err = -EINVAL;
- break;
- }
-
- return err;
-}
-
-int brcms_c_set_nmode(struct brcms_c_info *wlc, s32 nmode)
-{
- uint i;
- int err;
-
- err = brcms_c_nmode_validate(wlc, nmode);
- if (err)
- return err;
-
- switch (nmode) {
- case OFF:
- wlc->pub->_n_enab = OFF;
- wlc->default_bss->flags &= ~BRCMS_BSS_HT;
- /* delete the mcs rates from the default and hw ratesets */
- brcms_c_rateset_mcs_clear(&wlc->default_bss->rateset);
- for (i = 0; i < NBANDS(wlc); i++) {
- memset(wlc->bandstate[i]->hw_rateset.mcs, 0,
- MCSSET_LEN);
- if (IS_MCS(wlc->band->rspec_override)) {
- wlc->bandstate[i]->rspec_override = 0;
- brcms_c_reprate_init(wlc);
- }
- if (IS_MCS(wlc->band->mrspec_override))
- wlc->bandstate[i]->mrspec_override = 0;
- }
- break;
-
- case AUTO:
- if (wlc->stf->txstreams == WL_11N_3x3)
- nmode = WL_11N_3x3;
- else
- nmode = WL_11N_2x2;
- case WL_11N_2x2:
- case WL_11N_3x3:
- /* force GMODE_AUTO if NMODE is ON */
- brcms_c_set_gmode(wlc, GMODE_AUTO, true);
- if (nmode == WL_11N_3x3)
- wlc->pub->_n_enab = SUPPORT_HT;
- else
- wlc->pub->_n_enab = SUPPORT_11N;
- wlc->default_bss->flags |= BRCMS_BSS_HT;
- /* add the mcs rates to the default and hw ratesets */
- brcms_c_rateset_mcs_build(&wlc->default_bss->rateset,
- wlc->stf->txstreams);
- for (i = 0; i < NBANDS(wlc); i++)
- memcpy(wlc->bandstate[i]->hw_rateset.mcs,
- wlc->default_bss->rateset.mcs, MCSSET_LEN);
- break;
-
- default:
- break;
- }
-
- return err;
-}
-
-static int brcms_c_set_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs_arg)
-{
- wlc_rateset_t rs, new;
- uint bandunit;
-
- memcpy(&rs, rs_arg, sizeof(wlc_rateset_t));
-
- /* check for bad count value */
- if ((rs.count == 0) || (rs.count > BRCMS_NUMRATES))
- return -EINVAL;
-
- /* try the current band */
- bandunit = wlc->band->bandunit;
- memcpy(&new, &rs, sizeof(wlc_rateset_t));
- if (brcms_c_rate_hwrs_filter_sort_validate
- (&new, &wlc->bandstate[bandunit]->hw_rateset, true,
- wlc->stf->txstreams))
- goto good;
-
- /* try the other band */
- if (IS_MBAND_UNLOCKED(wlc)) {
- bandunit = OTHERBANDUNIT(wlc);
- memcpy(&new, &rs, sizeof(wlc_rateset_t));
- if (brcms_c_rate_hwrs_filter_sort_validate(&new,
- &wlc->
- bandstate[bandunit]->
- hw_rateset, true,
- wlc->stf->txstreams))
- goto good;
- }
-
- return -EBADE;
-
- good:
- /* apply new rateset */
- memcpy(&wlc->default_bss->rateset, &new, sizeof(wlc_rateset_t));
- memcpy(&wlc->bandstate[bandunit]->defrateset, &new,
- sizeof(wlc_rateset_t));
- return 0;
-}
-
-/* simplified integer set interface for common ioctl handler */
-int brcms_c_set(struct brcms_c_info *wlc, int cmd, int arg)
-{
- return brcms_c_ioctl(wlc, cmd, (void *)&arg, sizeof(arg), NULL);
-}
-
-/* simplified integer get interface for common ioctl handler */
-int brcms_c_get(struct brcms_c_info *wlc, int cmd, int *arg)
-{
- return brcms_c_ioctl(wlc, cmd, arg, sizeof(int), NULL);
-}
-
-static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
-{
- u8 r;
- bool war = false;
-
- if (wlc->cfg->associated)
- r = wlc->cfg->current_bss->rateset.rates[0];
- else
- r = wlc->default_bss->rateset.rates[0];
-
- wlc_phy_ofdm_rateset_war(wlc->band->pi, war);
-
- return;
-}
-
-int
-brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
- struct brcms_c_if *wlcif)
-{
- return _brcms_c_ioctl(wlc, cmd, arg, len, wlcif);
-}
-
-/* common ioctl handler. return: 0=ok, -1=error, positive=particular error */
-static int
-_brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
- struct brcms_c_if *wlcif)
-{
- int val, *pval;
- bool bool_val;
- int bcmerror;
- struct scb *nextscb;
- bool ta_ok;
- uint band;
- struct brcms_bss_cfg *bsscfg;
- struct brcms_bss_info *current_bss;
-
- /* update bsscfg pointer */
- bsscfg = wlc->cfg;
- current_bss = bsscfg->current_bss;
-
- /* initialize the following to get rid of compiler warning */
- nextscb = NULL;
- ta_ok = false;
- band = 0;
-
- /* If the device is turned off, then it's not "removed" */
- if (!wlc->pub->hw_off && DEVICEREMOVED(wlc)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
- __func__);
- brcms_down(wlc->wl);
- return -EBADE;
- }
-
- /* default argument is generic integer */
- pval = arg ? (int *)arg : NULL;
-
- /* This will prevent the misaligned access */
- if (pval && (u32) len >= sizeof(val))
- memcpy(&val, pval, sizeof(val));
- else
- val = 0;
-
- /* bool conversion to avoid duplication below */
- bool_val = val != 0;
- bcmerror = 0;
-
- if ((arg == NULL) || (len <= 0)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Command %d needs arguments\n",
- wlc->pub->unit, __func__, cmd);
- bcmerror = -EINVAL;
- goto done;
- }
-
- switch (cmd) {
-
- case BRCM_SET_CHANNEL:{
- chanspec_t chspec = CH20MHZ_CHSPEC(val);
-
- if (val < 0 || val > MAXCHANNEL) {
- bcmerror = -EINVAL;
- break;
- }
-
- if (!brcms_c_valid_chanspec_db(wlc->cmi, chspec)) {
- bcmerror = -EINVAL;
- break;
- }
-
- if (!wlc->pub->up && IS_MBAND_UNLOCKED(wlc)) {
- if (wlc->band->bandunit !=
- CHSPEC_BANDUNIT(chspec))
- wlc->bandinit_pending = true;
- else
- wlc->bandinit_pending = false;
- }
-
- wlc->default_bss->chanspec = chspec;
- /* brcms_c_BSSinit() will sanitize the rateset before
- * using it.. */
- if (wlc->pub->up &&
- (BRCMS_BAND_PI_RADIO_CHANSPEC != chspec)) {
- brcms_c_set_home_chanspec(wlc, chspec);
- brcms_c_suspend_mac_and_wait(wlc);
- brcms_c_set_chanspec(wlc, chspec);
- brcms_c_enable_mac(wlc);
- }
- break;
- }
-
- case BRCM_SET_SRL:
- if (val >= 1 && val <= RETRY_SHORT_MAX) {
- int ac;
- wlc->SRL = (u16) val;
-
- brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
-
- for (ac = 0; ac < AC_COUNT; ac++) {
- BRCMS_WME_RETRY_SHORT_SET(wlc, ac, wlc->SRL);
- }
- brcms_c_wme_retries_write(wlc);
- } else
- bcmerror = -EINVAL;
- break;
-
- case BRCM_SET_LRL:
- if (val >= 1 && val <= 255) {
- int ac;
- wlc->LRL = (u16) val;
-
- brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
-
- for (ac = 0; ac < AC_COUNT; ac++) {
- BRCMS_WME_RETRY_LONG_SET(wlc, ac, wlc->LRL);
- }
- brcms_c_wme_retries_write(wlc);
- } else
- bcmerror = -EINVAL;
- break;
-
- case BRCM_GET_CURR_RATESET:{
- wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
- wlc_rateset_t *rs;
-
- if (wlc->pub->associated)
- rs = &current_bss->rateset;
- else
- rs = &wlc->default_bss->rateset;
-
- if (len < (int)(rs->count + sizeof(rs->count))) {
- bcmerror = -EOVERFLOW;
- break;
- }
-
- /* Copy only legacy rateset section */
- ret_rs->count = rs->count;
- memcpy(&ret_rs->rates, &rs->rates, rs->count);
- break;
- }
-
- case BRCM_SET_RATESET:{
- wlc_rateset_t rs;
- wl_rateset_t *in_rs = (wl_rateset_t *) arg;
-
- if (len < (int)(in_rs->count + sizeof(in_rs->count))) {
- bcmerror = -EOVERFLOW;
- break;
- }
-
- if (in_rs->count > BRCMS_NUMRATES) {
- bcmerror = -ENOBUFS;
- break;
- }
-
- memset(&rs, 0, sizeof(wlc_rateset_t));
-
- /* Copy only legacy rateset section */
- rs.count = in_rs->count;
- memcpy(&rs.rates, &in_rs->rates, rs.count);
-
- /* merge rateset coming in with the current mcsset */
- if (N_ENAB(wlc->pub)) {
- if (bsscfg->associated)
- memcpy(rs.mcs,
- &current_bss->rateset.mcs[0],
- MCSSET_LEN);
- else
- memcpy(rs.mcs,
- &wlc->default_bss->rateset.mcs[0],
- MCSSET_LEN);
- }
-
- bcmerror = brcms_c_set_rateset(wlc, &rs);
-
- if (!bcmerror)
- brcms_c_ofdm_rateset_war(wlc);
-
- break;
- }
-
- case BRCM_SET_BCNPRD:
- /* range [1, 0xffff] */
- if (val >= DOT11_MIN_BEACON_PERIOD
- && val <= DOT11_MAX_BEACON_PERIOD)
- wlc->default_bss->beacon_period = (u16) val;
- else
- bcmerror = -EINVAL;
- break;
-
- case BRCM_GET_PHYLIST:
- {
- unsigned char *cp = arg;
- if (len < 3) {
- bcmerror = -EOVERFLOW;
- break;
- }
-
- if (BRCMS_ISNPHY(wlc->band))
- *cp++ = 'n';
- else if (BRCMS_ISLCNPHY(wlc->band))
- *cp++ = 'c';
- else if (BRCMS_ISSSLPNPHY(wlc->band))
- *cp++ = 's';
- *cp = '\0';
- break;
- }
-
- case BRCMS_SET_SHORTSLOT_OVERRIDE:
- if (val != BRCMS_SHORTSLOT_AUTO && val != BRCMS_SHORTSLOT_OFF &&
- val != BRCMS_SHORTSLOT_ON) {
- bcmerror = -EINVAL;
- break;
- }
-
- wlc->shortslot_override = (s8) val;
-
- /* shortslot is an 11g feature, so no more work if we are
- * currently on the 5G band
- */
- if (BAND_5G(wlc->band->bandtype))
- break;
-
- if (wlc->pub->up && wlc->pub->associated) {
- /* let watchdog or beacon processing update shortslot */
- } else if (wlc->pub->up) {
- /* unassociated shortslot is off */
- brcms_c_switch_shortslot(wlc, false);
- } else {
- /* driver is down, so just update the brcms_c_info
- * value */
- if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO) {
- wlc->shortslot = false;
- } else {
- wlc->shortslot =
- (wlc->shortslot_override ==
- BRCMS_SHORTSLOT_ON);
- }
- }
-
- break;
-
- }
- done:
-
- if (bcmerror)
- wlc->pub->bcmerror = bcmerror;
-
- return bcmerror;
-}
-
-/*
- * register watchdog and down handlers.
- */
-int brcms_c_module_register(struct brcms_pub *pub,
- const char *name, void *hdl,
- watchdog_fn_t w_fn, down_fn_t d_fn)
-{
- struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
- int i;
-
- /* find an empty entry and just add, no duplication check! */
- for (i = 0; i < BRCMS_MAXMODULES; i++) {
- if (wlc->modulecb[i].name[0] == '\0') {
- strncpy(wlc->modulecb[i].name, name,
- sizeof(wlc->modulecb[i].name) - 1);
- wlc->modulecb[i].hdl = hdl;
- wlc->modulecb[i].watchdog_fn = w_fn;
- wlc->modulecb[i].down_fn = d_fn;
- return 0;
- }
- }
-
- return -ENOSR;
-}
-
-/* unregister module callbacks */
-int
-brcms_c_module_unregister(struct brcms_pub *pub, const char *name, void *hdl)
-{
- struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
- int i;
-
- if (wlc == NULL)
- return -ENODATA;
-
- for (i = 0; i < BRCMS_MAXMODULES; i++) {
- if (!strcmp(wlc->modulecb[i].name, name) &&
- (wlc->modulecb[i].hdl == hdl)) {
- memset(&wlc->modulecb[i], 0, sizeof(struct modulecb));
- return 0;
- }
- }
-
- /* table not found! */
- return -ENODATA;
-}
-
-/* Write WME tunable parameters for retransmit/max rate from wlc struct to ucode */
-static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
-{
- int ac;
-
- /* Need clock to do this */
- if (!wlc->clk)
- return;
-
- for (ac = 0; ac < AC_COUNT; ac++) {
- brcms_c_write_shm(wlc, M_AC_TXLMT_ADDR(ac),
- wlc->wme_retries[ac]);
- }
-}
-
-#ifdef BCMDBG
-static const char * const supr_reason[] = {
- "None", "PMQ Entry", "Flush request",
- "Previous frag failure", "Channel mismatch",
- "Lifetime Expiry", "Underflow"
-};
-
-static void brcms_c_print_txs_status(u16 s)
-{
- printk(KERN_DEBUG "[15:12] %d frame attempts\n",
- (s & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT);
- printk(KERN_DEBUG " [11:8] %d rts attempts\n",
- (s & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT);
- printk(KERN_DEBUG " [7] %d PM mode indicated\n",
- ((s & TX_STATUS_PMINDCTD) ? 1 : 0));
- printk(KERN_DEBUG " [6] %d intermediate status\n",
- ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0));
- printk(KERN_DEBUG " [5] %d AMPDU\n",
- (s & TX_STATUS_AMPDU) ? 1 : 0);
- printk(KERN_DEBUG " [4:2] %d Frame Suppressed Reason (%s)\n",
- ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT),
- supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]);
- printk(KERN_DEBUG " [1] %d acked\n",
- ((s & TX_STATUS_ACK_RCV) ? 1 : 0));
-}
-#endif /* BCMDBG */
-
-void brcms_c_print_txstatus(struct tx_status *txs)
-{
-#if defined(BCMDBG)
- u16 s = txs->status;
- u16 ackphyrxsh = txs->ackphyrxsh;
-
- printk(KERN_DEBUG "\ntxpkt (MPDU) Complete\n");
-
- printk(KERN_DEBUG "FrameID: %04x ", txs->frameid);
- printk(KERN_DEBUG "TxStatus: %04x", s);
- printk(KERN_DEBUG "\n");
-
- brcms_c_print_txs_status(s);
-
- printk(KERN_DEBUG "LastTxTime: %04x ", txs->lasttxtime);
- printk(KERN_DEBUG "Seq: %04x ", txs->sequence);
- printk(KERN_DEBUG "PHYTxStatus: %04x ", txs->phyerr);
- printk(KERN_DEBUG "RxAckRSSI: %04x ",
- (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT);
- printk(KERN_DEBUG "RxAckSQ: %04x",
- (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
- printk(KERN_DEBUG "\n");
-#endif /* defined(BCMDBG) */
-}
-
-void brcms_c_statsupd(struct brcms_c_info *wlc)
-{
- int i;
- struct macstat macstats;
-#ifdef BCMDBG
- u16 delta;
- u16 rxf0ovfl;
- u16 txfunfl[NFIFO];
-#endif /* BCMDBG */
-
- /* if driver down, make no sense to update stats */
- if (!wlc->pub->up)
- return;
-
-#ifdef BCMDBG
- /* save last rx fifo 0 overflow count */
- rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
-
- /* save last tx fifo underflow count */
- for (i = 0; i < NFIFO; i++)
- txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
-#endif /* BCMDBG */
-
- /* Read mac stats from contiguous shared memory */
- brcms_b_copyfrom_shm(wlc->hw, M_UCODE_MACSTAT,
- &macstats, sizeof(struct macstat));
-
-#ifdef BCMDBG
- /* 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",
- wlc->pub->unit, delta);
-
- /* check for tx fifo underflows */
- for (i = 0; i < NFIFO; i++) {
- delta =
- (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);
- }
-#endif /* BCMDBG */
-
- /* merge counters from dma module */
- for (i = 0; i < NFIFO; i++) {
- if (wlc->hw->di[i]) {
- dma_counterreset(wlc->hw->di[i]);
- }
- }
-}
-
-bool brcms_c_chipmatch(u16 vendor, u16 device)
-{
- if (vendor != PCI_VENDOR_ID_BROADCOM) {
- pr_err("chipmatch: unknown vendor id %04x\n", vendor);
- return false;
- }
-
- if (device == BCM43224_D11N_ID_VEN1)
- return true;
- if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID))
- return true;
- if (device == BCM4313_D11N2G_ID)
- return true;
- if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID))
- return true;
-
- pr_err("chipmatch: unknown device id %04x\n", device);
- return false;
-}
-
-#if defined(BCMDBG)
-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;
- char hexbuf[256];
-
- /* add plcp header along with txh descriptor */
- printk(KERN_DEBUG "Raw TxDesc + plcp header:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
- txh, sizeof(struct d11txh) + 48);
-
- printk(KERN_DEBUG "TxCtlLow: %04x ", mtcl);
- printk(KERN_DEBUG "TxCtlHigh: %04x ", mtch);
- printk(KERN_DEBUG "FC: %04x ", mfc);
- printk(KERN_DEBUG "FES Time: %04x\n", tfest);
- printk(KERN_DEBUG "PhyCtl: %04x%s ", ptcw,
- (ptcw & PHY_TXC_SHORT_HDR) ? " short" : "");
- printk(KERN_DEBUG "PhyCtl_1: %04x ", ptcw_1);
- printk(KERN_DEBUG "PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr);
- printk(KERN_DEBUG "PhyCtl_1_Rts: %04x ", ptcw_1_Rts);
- printk(KERN_DEBUG "PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts);
- printk(KERN_DEBUG "MainRates: %04x ", mainrates);
- printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft);
- printk(KERN_DEBUG "\n");
-
- brcmu_format_hex(hexbuf, iv, sizeof(txh->IV));
- printk(KERN_DEBUG "SecIV: %s\n", hexbuf);
- brcmu_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA));
- printk(KERN_DEBUG "RA: %s\n", hexbuf);
-
- printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb);
- brcmu_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback));
- printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
- printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb);
- brcmu_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback));
- printk(KERN_DEBUG "PLCP: %s ", hexbuf);
- printk(KERN_DEBUG "DUR: %04x", fragdfb);
- printk(KERN_DEBUG "\n");
-
- printk(KERN_DEBUG "MModeLen: %04x ", mmodelen);
- printk(KERN_DEBUG "MModeFbrLen: %04x\n", mmodefbrlen);
-
- printk(KERN_DEBUG "FrameID: %04x\n", tfid);
- printk(KERN_DEBUG "TxStatus: %04x\n", txs);
-
- printk(KERN_DEBUG "MaxNumMpdu: %04x\n", mnmpdu);
- printk(KERN_DEBUG "MaxAggbyte: %04x\n", mabyte);
- printk(KERN_DEBUG "MaxAggbyte_fb: %04x\n", mabyte_f);
- printk(KERN_DEBUG "MinByte: %04x\n", mmbyte);
-
- brcmu_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader));
- printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
- brcmu_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame));
- printk(KERN_DEBUG "RTS Frame: %s", hexbuf);
- printk(KERN_DEBUG "\n");
-}
-#endif /* defined(BCMDBG) */
-
-#if defined(BCMDBG)
-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 brcmu_bit_desc macstat_flags[] = {
- {RXS_FCSERR, "FCSErr"},
- {RXS_RESPFRAMETX, "Reply"},
- {RXS_PBPRES, "PADDING"},
- {RXS_DECATMPT, "DeCr"},
- {RXS_DECERR, "DeCrErr"},
- {RXS_BCNSENT, "Bcn"},
- {0, NULL}
- };
-
- printk(KERN_DEBUG "Raw RxDesc:\n");
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, rxh,
- sizeof(struct d11rxhdr));
-
- brcmu_format_flags(macstat_flags, macstatus1, flagstr, 64);
-
- snprintf(lenbuf, sizeof(lenbuf), "0x%x", len);
-
- printk(KERN_DEBUG "RxFrameSize: %6s (%d)%s\n", lenbuf, len,
- (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : "");
- printk(KERN_DEBUG "RxPHYStatus: %04x %04x %04x %04x\n",
- phystatus_0, phystatus_1, phystatus_2, phystatus_3);
- printk(KERN_DEBUG "RxMACStatus: %x %s\n", macstatus1, flagstr);
- printk(KERN_DEBUG "RXMACaggtype: %x\n",
- (macstatus2 & RXS_AGGTYPE_MASK));
- printk(KERN_DEBUG "RxTSFTime: %04x\n", rxh->RxTSFTime);
-}
-#endif /* defined(BCMDBG) */
-
-static u16 brcms_c_rate_shm_offset(struct brcms_c_info *wlc, u8 rate)
-{
- return brcms_b_rate_shm_offset(wlc->hw, rate);
-}
-
-/* Callback for device removed */
-
-/*
- * 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.
- */
-bool
-brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q, void *pkt, int prec)
-{
- return brcms_c_prec_enq_head(wlc, q, pkt, prec, false);
-}
-
-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(wlc->wme_dp, 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;
-}
-
-void brcms_c_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
- uint prec)
-{
- struct brcms_c_info *wlc = (struct brcms_c_info *) ctx;
- 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)) {
- if (!EDCF_ENAB(wlc->pub)
- || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL))
- wiphy_err(wlc->wiphy, "wl%d: txq_enq: txq overflow"
- "\n", wlc->pub->unit);
-
- /*
- * we might hit this condtion in case
- * packet flooding from mac80211 stack
- */
- brcmu_pkt_buf_free_skb(sdu);
- }
-
- /* Check if flow control needs to be turned on after enqueuing the packet
- * Don't turn on flow control if EDCF is enabled. Driver would make the decision on what
- * to drop instead of relying on stack to make the right decision
- */
- if (!EDCF_ENAB(wlc->pub)
- || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
- if (pktq_len(q) >= wlc->pub->tunables->datahiwat) {
- brcms_c_txflowcontrol(wlc, qi, ON, ALLPRIO);
- }
- } else if (wlc->pub->_priofc) {
- if (pktq_plen(q, wlc_prio2prec_map[prio]) >=
- wlc->pub->tunables->datahiwat) {
- brcms_c_txflowcontrol(wlc, qi, ON, prio);
- }
- }
-}
-
-bool
-brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
- struct ieee80211_hw *hw)
-{
- u8 prio;
- uint fifo;
- void *pkt;
- struct scb *scb = &global_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];
- pkt = sdu;
- if (unlikely
- (brcms_c_d11hdrs_mac80211(
- wlc, hw, pkt, scb, 0, 1, fifo, 0, NULL, 0)))
- return -EINVAL;
- brcms_c_txq_enq(wlc, scb, pkt, BRCMS_PRIO_TO_PREC(prio));
- brcms_c_send_q(wlc);
- return 0;
-}
-
-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;
-
- if (in_send_q)
- return;
- else
- in_send_q = true;
-
- prec_map = wlc->tx_prec_map;
-
- /* 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;
- }
- }
-
- /* Check if flow control needs to be turned off after sending the packet */
- if (!EDCF_ENAB(wlc->pub)
- || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
- if (brcms_c_txflowcontrol_prio_isset(wlc, qi, ALLPRIO)
- && (pktq_len(q) < wlc->pub->tunables->datahiwat / 2)) {
- brcms_c_txflowcontrol(wlc, qi, OFF, ALLPRIO);
- }
- } else if (wlc->pub->_priofc) {
- int prio;
- for (prio = MAXPRIO; prio >= 0; prio--) {
- if (brcms_c_txflowcontrol_prio_isset(wlc, qi, prio) &&
- (pktq_plen(q, wlc_prio2prec_map[prio]) <
- wlc->pub->tunables->datahiwat / 2)) {
- brcms_c_txflowcontrol(wlc, qi, OFF, prio);
- }
- }
- }
- in_send_q = false;
-}
-
-/*
- * bcmc_fid_generate:
- * Generate frame ID for a BCMC packet. The frag field is not used
- * for MC frames so is used as part of the sequence number.
- */
-static inline u16
-bcmc_fid_generate(struct brcms_c_info *wlc, struct brcms_bss_cfg *bsscfg,
- struct d11txh *txh)
-{
- u16 frameid;
-
- frameid = le16_to_cpu(txh->TxFrameID) & ~(TXFID_SEQ_MASK |
- TXFID_QUEUE_MASK);
- frameid |=
- (((wlc->
- mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
- TX_BCMC_FIFO;
-
- return frameid;
-}
-
-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.
- */
- if (fifo == TX_BCMC_FIFO) {
- frameid = le16_to_cpu(txh->TxFrameID);
-
- }
-
- if (BRCMS_WAR16165(wlc))
- brcms_c_war16165(wlc, true);
-
-
- /* Bump up pending count for if not using rpc. If rpc is used, this will be handled
- * in brcms_b_txfifo()
- */
- if (commit) {
- TXPKTPENDINC(wlc, fifo, txpktpend);
- BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n",
- txpktpend, TXPKTPENDGET(wlc, fifo));
- }
-
- /* Commit BCMC sequence number in the SHM frame ID location */
- if (frameid != INVALIDFID)
- BCMCFID(wlc, frameid);
-
- if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) {
- wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n");
- }
-}
-
-void
-brcms_c_compute_plcp(struct brcms_c_info *wlc, ratespec_t rspec,
- uint length, u8 *plcp)
-{
- if (IS_MCS(rspec)) {
- brcms_c_compute_mimo_plcp(rspec, length, plcp);
- } else if (IS_OFDM(rspec)) {
- brcms_c_compute_ofdm_plcp(rspec, length, plcp);
- } else {
- brcms_c_compute_cck_plcp(wlc, rspec, length, plcp);
- }
- return;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void brcms_c_compute_mimo_plcp(ratespec_t rspec, uint length, u8 *plcp)
-{
- u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
- plcp[0] = mcs;
- if (RSPEC_IS40MHZ(rspec) || (mcs == 32))
- plcp[0] |= MIMO_PLCP_40MHZ;
- BRCMS_SET_MIMO_PLCP_LEN(plcp, length);
- plcp[3] = RSPEC_MIMOPLCP3(rspec); /* rspec already holds this byte */
- plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */
- plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */
- plcp[5] = 0;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void
-brcms_c_compute_ofdm_plcp(ratespec_t rspec, u32 length, u8 *plcp)
-{
- u8 rate_signal;
- u32 tmp = 0;
- int rate = RSPEC2RATE(rspec);
-
- /* encode rate per 802.11a-1999 sec 17.3.4.1, with lsb transmitted first */
- rate_signal = rate_info[rate] & BRCMS_RATE_MASK;
- memset(plcp, 0, D11_PHY_HDR_LEN);
- D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal);
-
- tmp = (length & 0xfff) << 5;
- plcp[2] |= (tmp >> 16) & 0xff;
- plcp[1] |= (tmp >> 8) & 0xff;
- plcp[0] |= tmp & 0xff;
-
- return;
-}
-
-/*
- * Compute PLCP, but only requires actual rate and length of pkt.
- * Rate is given in the driver standard multiple of 500 kbps.
- * le is set for 11 Mbps rate if necessary.
- * Broken out for PRQ.
- */
-
-static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
- uint length, u8 *plcp)
-{
- u16 usec = 0;
- u8 le = 0;
-
- switch (rate_500) {
- case BRCM_RATE_1M:
- usec = length << 3;
- break;
- case BRCM_RATE_2M:
- usec = length << 2;
- break;
- case BRCM_RATE_5M5:
- usec = (length << 4) / 11;
- if ((length << 4) - (usec * 11) > 0)
- usec++;
- break;
- case BRCM_RATE_11M:
- usec = (length << 3) / 11;
- if ((length << 3) - (usec * 11) > 0) {
- usec++;
- if ((usec * 11) - (length << 3) >= 8)
- le = D11B_PLCP_SIGNAL_LE;
- }
- break;
-
- default:
- wiphy_err(wlc->wiphy, "brcms_c_cck_plcp_set: unsupported rate %d"
- "\n", rate_500);
- rate_500 = BRCM_RATE_1M;
- usec = length << 3;
- break;
- }
- /* PLCP signal byte */
- plcp[0] = rate_500 * 5; /* r (500kbps) * 5 == r (100kbps) */
- /* PLCP service byte */
- plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED);
- /* PLCP length u16, little endian */
- plcp[2] = usec & 0xff;
- plcp[3] = (usec >> 8) & 0xff;
- /* PLCP CRC16 */
- plcp[4] = 0;
- plcp[5] = 0;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, ratespec_t rspec,
- uint length, u8 *plcp)
-{
- int rate = RSPEC2RATE(rspec);
-
- brcms_c_cck_plcp_set(wlc, rate, length, plcp);
-}
-
-/* brcms_c_compute_frame_dur()
- *
- * Calculate the 802.11 MAC header DUR field for MPDU
- * DUR for a single frame = 1 SIFS + 1 ACK
- * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time
- *
- * rate MPDU rate in unit of 500kbps
- * next_frag_len next MPDU length in bytes
- * preamble_type use short/GF or long/MM PLCP header
- */
-static u16
-brcms_c_compute_frame_dur(struct brcms_c_info *wlc, ratespec_t rate,
- u8 preamble_type, uint next_frag_len)
-{
- u16 dur, sifs;
-
- sifs = SIFS(wlc->band);
-
- dur = sifs;
- dur += (u16) brcms_c_calc_ack_time(wlc, rate, preamble_type);
-
- if (next_frag_len) {
- /* Double the current DUR to get 2 SIFS + 2 ACKs */
- dur *= 2;
- /* add another SIFS and the frag time */
- dur += sifs;
- dur +=
- (u16) brcms_c_calc_frame_time(wlc, rate, preamble_type,
- next_frag_len);
- }
- return dur;
-}
-
-/* brcms_c_compute_rtscts_dur()
- *
- * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame
- * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK
- * DUR for CTS-TO-SELF w/ frame = 2 SIFS + next frame time + 1 ACK
- *
- * cts cts-to-self or rts/cts
- * rts_rate rts or cts rate in unit of 500kbps
- * rate next MPDU rate in unit of 500kbps
- * frame_len next MPDU frame length in bytes
- */
-u16
-brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
- ratespec_t rts_rate,
- ratespec_t frame_rate, u8 rts_preamble_type,
- u8 frame_preamble_type, uint frame_len, bool ba)
-{
- u16 dur, sifs;
-
- sifs = SIFS(wlc->band);
-
- if (!cts_only) { /* RTS/CTS */
- dur = 3 * sifs;
- dur +=
- (u16) brcms_c_calc_cts_time(wlc, rts_rate,
- rts_preamble_type);
- } else { /* CTS-TO-SELF */
- dur = 2 * sifs;
- }
-
- dur +=
- (u16) brcms_c_calc_frame_time(wlc, frame_rate, frame_preamble_type,
- frame_len);
- if (ba)
- dur +=
- (u16) brcms_c_calc_ba_time(wlc, frame_rate,
- BRCMS_SHORT_PREAMBLE);
- else
- dur +=
- (u16) brcms_c_calc_ack_time(wlc, frame_rate,
- frame_preamble_type);
- return dur;
-}
-
-u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, ratespec_t rspec)
-{
- u16 phyctl1 = 0;
- u16 bw;
-
- if (BRCMS_ISLCNPHY(wlc->band)) {
- bw = PHY_TXC1_BW_20MHZ;
- } else {
- 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 "
- "not supported yet, set to 20L\n", bw);
- bw = PHY_TXC1_BW_20MHZ;
- }
- }
-
- if (IS_MCS(rspec)) {
- uint mcs = rspec & RSPEC_RATE_MASK;
-
- /* bw, stf, coding-type is part of RSPEC_PHYTXBYTE2 returns */
- phyctl1 = RSPEC_PHYTXBYTE2(rspec);
- /* set the upper byte of phyctl1 */
- phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
- } else if (IS_CCK(rspec) && !BRCMS_ISLCNPHY(wlc->band)
- && !BRCMS_ISSSLPNPHY(wlc->band)) {
- /* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
- /* Eventually MIMOPHY would also be converted to this format */
- /* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
- phyctl1 = (bw | (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
- } else { /* legacy OFDM/CCK */
- s16 phycfg;
- /* 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 "
- "legacy OFDM/CCK rate\n");
- phycfg = 0;
- }
- /* set the upper byte of phyctl1 */
- phyctl1 =
- (bw | (phycfg << 8) |
- (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
- }
- return phyctl1;
-}
-
-ratespec_t
-brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, ratespec_t rspec,
- bool use_rspec, u16 mimo_ctlchbw)
-{
- ratespec_t rts_rspec = 0;
-
- if (use_rspec) {
- /* use frame rate as rts rate */
- rts_rspec = rspec;
-
- } else if (wlc->band->gmode && wlc->protection->_g && !IS_CCK(rspec)) {
- /* Use 11Mbps as the g protection RTS target rate and fallback.
- * Use the BRCMS_BASIC_RATE() lookup to find the best basic rate
- * under the target in case 11 Mbps is not Basic.
- * 6 and 9 Mbps are not usually selected by rate selection, but even
- * if the OFDM rate we are protecting is 6 or 9 Mbps, 11 is more robust.
- */
- rts_rspec = BRCMS_BASIC_RATE(wlc, BRCM_RATE_11M);
- } else {
- /* calculate RTS rate and fallback rate based on the frame rate
- * RTS must be sent at a basic rate since it is a
- * control frame, sec 9.6 of 802.11 spec
- */
- rts_rspec = BRCMS_BASIC_RATE(wlc, rspec);
- }
-
- if (BRCMS_PHY_11N_CAP(wlc->band)) {
- /* set rts txbw to correct side band */
- rts_rspec &= ~RSPEC_BW_MASK;
-
- /* if rspec/rspec_fallback is 40MHz, then send RTS on both 20MHz channel
- * (DUP), otherwise send RTS on control channel
- */
- if (RSPEC_IS40MHZ(rspec) && !IS_CCK(rts_rspec))
- rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT);
- else
- rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
-
- /* pick siso/cdd as default for ofdm */
- if (IS_OFDM(rts_rspec)) {
- rts_rspec &= ~RSPEC_STF_MASK;
- rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
- }
- }
- return rts_rspec;
-}
-
-/*
- * Add struct d11txh, struct cck_phy_hdr.
- *
- * 'p' data must start with 802.11 MAC header
- * 'p' must allow enough bytes of local headers to be "pushed" onto the packet
- *
- * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes)
- *
- */
-static u16
-brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
- struct sk_buff *p, struct scb *scb, uint frag,
- uint nfrags, uint queue, uint next_frag_len,
- struct wsec_key *key, ratespec_t rspec_override)
-{
- struct ieee80211_hdr *h;
- struct d11txh *txh;
- u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN];
- int len, phylen, rts_phylen;
- u16 mch, phyctl, xfts, mainrates;
- u16 seq = 0, mcl = 0, status = 0, frameid = 0;
- ratespec_t rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }, rts_rspec[2] = {
- BRCM_RATE_1M, BRCM_RATE_1M};
- bool use_rts = false;
- bool use_cts = false;
- bool use_rifs = false;
- bool short_preamble[2] = { false, false };
- u8 preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
- u8 rts_preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
- u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN];
- struct ieee80211_rts *rts = NULL;
- bool qos;
- uint ac;
- u32 rate_val[2];
- bool hwtkmic = false;
- u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
-#define ANTCFG_NONE 0xFF
- u8 antcfg = ANTCFG_NONE;
- u8 fbantcfg = ANTCFG_NONE;
- uint phyctl1_stf = 0;
- u16 durid = 0;
- struct ieee80211_tx_rate *txrate[2];
- int k;
- struct ieee80211_tx_info *tx_info;
- bool is_mcs[2];
- u16 mimo_txbw;
- u8 mimo_preamble_type;
-
- /* locate 802.11 MAC header */
- h = (struct ieee80211_hdr *)(p->data);
- qos = ieee80211_is_data_qos(h->frame_control);
-
- /* compute length of frame in bytes for use in PLCP computations */
- len = brcmu_pkttotlen(p);
- phylen = len + FCS_LEN;
-
- /* If WEP enabled, add room in phylen for the additional bytes of
- * ICV which MAC generates. We do NOT add the additional bytes to
- * the packet itself, thus phylen = packet length + ICV_LEN + FCS_LEN
- * in this case
- */
- if (key) {
- phylen += key->icv_len;
- }
-
- /* Get tx_info */
- tx_info = IEEE80211_SKB_CB(p);
-
- /* add PLCP */
- plcp = skb_push(p, D11_PHY_HDR_LEN);
-
- /* add Broadcom tx descriptor header */
- txh = (struct d11txh *) skb_push(p, D11_TXH_LEN);
- memset(txh, 0, D11_TXH_LEN);
-
- /* setup frameid */
- 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", BRCMS_UNIT(wlc), __func__);
- frameid = bcmc_fid_generate(wlc, NULL, txh);
- } else {
- /* Increment the counter for first fragment */
- if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) {
- SCB_SEQNUM(scb, p->priority)++;
- }
-
- /* extract fragment number from frame first */
- seq = le16_to_cpu(seq) & FRAGNUM_MASK;
- seq |= (SCB_SEQNUM(scb, p->priority) << SEQNUM_SHIFT);
- h->seq_ctrl = cpu_to_le16(seq);
-
- frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
- (queue & TXFID_QUEUE_MASK);
- }
- }
- frameid |= queue & TXFID_QUEUE_MASK;
-
- /* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */
- if (SCB_PS(scb) || ieee80211_is_beacon(h->frame_control))
- mcl |= TXC_IGNOREPMQ;
-
- txrate[0] = tx_info->control.rates;
- txrate[1] = txrate[0] + 1;
-
- /* if rate control algorithm didn't give us a fallback rate, use the primary rate */
- if (txrate[1]->idx < 0) {
- txrate[1] = txrate[0];
- }
-
- for (k = 0; k < hw->max_rates; k++) {
- is_mcs[k] =
- txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false;
- if (!is_mcs[k]) {
- if ((txrate[k]->idx >= 0)
- && (txrate[k]->idx <
- hw->wiphy->bands[tx_info->band]->n_bitrates)) {
- rate_val[k] =
- hw->wiphy->bands[tx_info->band]->
- bitrates[txrate[k]->idx].hw_value;
- short_preamble[k] =
- txrate[k]->
- flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ?
- true : false;
- } else {
- rate_val[k] = BRCM_RATE_1M;
- }
- } else {
- rate_val[k] = txrate[k]->idx;
- }
- /* Currently only support same setting for primay and fallback rates.
- * Unify flags for each rate into a single value for the frame
- */
- use_rts |=
- txrate[k]->
- flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false;
- use_cts |=
- txrate[k]->
- flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false;
-
- if (is_mcs[k])
- rate_val[k] |= NRATE_MCS_INUSE;
-
- rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, rate_val[k]);
-
- /* (1) RATE: determine and validate primary rate and fallback rates */
- if (!RSPEC_ACTIVE(rspec[k])) {
- rspec[k] = BRCM_RATE_1M;
- } else {
- if (!is_multicast_ether_addr(h->addr1)) {
- /* set tx antenna config */
- brcms_c_antsel_antcfg_get(wlc->asi, false,
- false, 0, 0, &antcfg, &fbantcfg);
- }
- }
- }
-
- phyctl1_stf = wlc->stf->ss_opmode;
-
- if (N_ENAB(wlc->pub)) {
- for (k = 0; k < hw->max_rates; k++) {
- /* apply siso/cdd to single stream mcs's or ofdm if rspec is auto selected */
- if (((IS_MCS(rspec[k]) &&
- IS_SINGLE_STREAM(rspec[k] & RSPEC_RATE_MASK)) ||
- IS_OFDM(rspec[k]))
- && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY)
- || !(rspec[k] & RSPEC_OVERRIDE))) {
- rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK);
-
- /* For SISO MCS use STBC if possible */
- if (IS_MCS(rspec[k])
- && BRCMS_STF_SS_STBC_TX(wlc, scb)) {
- u8 stc;
-
- stc = 1; /* Nss for single stream is always 1 */
- rspec[k] |=
- (PHY_TXC1_MODE_STBC <<
- RSPEC_STF_SHIFT) | (stc <<
- RSPEC_STC_SHIFT);
- } else
- rspec[k] |=
- (phyctl1_stf << RSPEC_STF_SHIFT);
- }
-
- /* Is the phy configured to use 40MHZ frames? If so then pick the desired txbw */
- if (CHSPEC_WLC_BW(wlc->chanspec) == BRCMS_40_MHZ) {
- /* default txbw is 20in40 SB */
- mimo_ctlchbw = mimo_txbw =
- CHSPEC_SB_UPPER(BRCMS_BAND_PI_RADIO_CHANSPEC)
- ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
-
- if (IS_MCS(rspec[k])) {
- /* mcs 32 must be 40b/w DUP */
- if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
- mimo_txbw =
- PHY_TXC1_BW_40MHZ_DUP;
- /* use override */
- } else if (wlc->mimo_40txbw != AUTO)
- mimo_txbw = wlc->mimo_40txbw;
- /* else check if dst is using 40 Mhz */
- else if (scb->flags & SCB_IS40)
- mimo_txbw = PHY_TXC1_BW_40MHZ;
- } else if (IS_OFDM(rspec[k])) {
- if (wlc->ofdm_40txbw != AUTO)
- mimo_txbw = wlc->ofdm_40txbw;
- } else {
- if (wlc->cck_40txbw != AUTO)
- mimo_txbw = wlc->cck_40txbw;
- }
- } else {
- /* mcs32 is 40 b/w only.
- * This is possible for probe packets on a STA during SCAN
- */
- if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
- /* mcs 0 */
- rspec[k] = RSPEC_MIMORATE;
- }
- mimo_txbw = PHY_TXC1_BW_20MHZ;
- }
-
- /* Set channel width */
- rspec[k] &= ~RSPEC_BW_MASK;
- if ((k == 0) || ((k > 0) && IS_MCS(rspec[k])))
- rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT);
- else
- rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
-
- /* Set Short GI */
-#ifdef NOSGIYET
- if (IS_MCS(rspec[k])
- && (txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
- rspec[k] |= RSPEC_SHORT_GI;
- else if (!(txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
- rspec[k] &= ~RSPEC_SHORT_GI;
-#else
- rspec[k] &= ~RSPEC_SHORT_GI;
-#endif
-
- mimo_preamble_type = BRCMS_MM_PREAMBLE;
- if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD)
- mimo_preamble_type = BRCMS_GF_PREAMBLE;
-
- if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
- && (!IS_MCS(rspec[k]))) {
- wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_"
- "RC_MCS != IS_MCS(rspec)\n",
- BRCMS_UNIT(wlc), __func__);
- }
-
- if (IS_MCS(rspec[k])) {
- preamble_type[k] = mimo_preamble_type;
-
- /* if SGI is selected, then forced mm for single stream */
- if ((rspec[k] & RSPEC_SHORT_GI)
- && IS_SINGLE_STREAM(rspec[k] &
- RSPEC_RATE_MASK)) {
- preamble_type[k] = BRCMS_MM_PREAMBLE;
- }
- }
-
- /* should be better conditionalized */
- if (!IS_MCS(rspec[0])
- && (tx_info->control.rates[0].
- flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
- preamble_type[k] = BRCMS_SHORT_PREAMBLE;
- }
- } else {
- for (k = 0; k < hw->max_rates; k++) {
- /* Set ctrlchbw as 20Mhz */
- rspec[k] &= ~RSPEC_BW_MASK;
- rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT);
-
- /* for nphy, stf of ofdm frames must follow policies */
- if (BRCMS_ISNPHY(wlc->band) && IS_OFDM(rspec[k])) {
- rspec[k] &= ~RSPEC_STF_MASK;
- rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT;
- }
- }
- }
-
- /* Reset these for use with AMPDU's */
- txrate[0]->count = 0;
- txrate[1]->count = 0;
-
- /* (2) PROTECTION, may change rspec */
- if ((ieee80211_is_data(h->frame_control) ||
- ieee80211_is_mgmt(h->frame_control)) &&
- (phylen > wlc->RTSThresh) && !is_multicast_ether_addr(h->addr1))
- use_rts = true;
-
- /* (3) PLCP: determine PLCP header and MAC duration,
- * fill struct d11txh */
- brcms_c_compute_plcp(wlc, rspec[0], phylen, plcp);
- brcms_c_compute_plcp(wlc, rspec[1], phylen, plcp_fallback);
- memcpy(&txh->FragPLCPFallback,
- plcp_fallback, sizeof(txh->FragPLCPFallback));
-
- /* Length field now put in CCK FBR CRC field */
- if (IS_CCK(rspec[1])) {
- txh->FragPLCPFallback[4] = phylen & 0xff;
- txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8;
- }
-
- /* MIMO-RATE: need validation ?? */
- mainrates = IS_OFDM(rspec[0]) ?
- D11A_PHY_HDR_GRATE((struct ofdm_phy_hdr *) plcp) :
- plcp[0];
-
- /* DUR field for main rate */
- if (!ieee80211_is_pspoll(h->frame_control) &&
- !is_multicast_ether_addr(h->addr1) && !use_rifs) {
- durid =
- brcms_c_compute_frame_dur(wlc, rspec[0], preamble_type[0],
- next_frag_len);
- h->duration_id = cpu_to_le16(durid);
- } else if (use_rifs) {
- /* NAV protect to end of next max packet size */
- durid =
- (u16) brcms_c_calc_frame_time(wlc, rspec[0],
- preamble_type[0],
- DOT11_MAX_FRAG_LEN);
- durid += RIFS_11N_TIME;
- h->duration_id = cpu_to_le16(durid);
- }
-
- /* DUR field for fallback rate */
- if (ieee80211_is_pspoll(h->frame_control))
- txh->FragDurFallback = h->duration_id;
- else if (is_multicast_ether_addr(h->addr1) || use_rifs)
- txh->FragDurFallback = 0;
- else {
- durid = brcms_c_compute_frame_dur(wlc, rspec[1],
- preamble_type[1], next_frag_len);
- txh->FragDurFallback = cpu_to_le16(durid);
- }
-
- /* (4) MAC-HDR: MacTxControlLow */
- if (frag == 0)
- mcl |= TXC_STARTMSDU;
-
- if (!is_multicast_ether_addr(h->addr1))
- mcl |= TXC_IMMEDACK;
-
- if (BAND_5G(wlc->band->bandtype))
- mcl |= TXC_FREQBAND_5G;
-
- if (CHSPEC_IS40(BRCMS_BAND_PI_RADIO_CHANSPEC))
- mcl |= TXC_BW_40;
-
- /* set AMIC bit if using hardware TKIP MIC */
- if (hwtkmic)
- mcl |= TXC_AMIC;
-
- txh->MacTxControlLow = cpu_to_le16(mcl);
-
- /* MacTxControlHigh */
- mch = 0;
-
- /* Set fallback rate preamble type */
- if ((preamble_type[1] == BRCMS_SHORT_PREAMBLE) ||
- (preamble_type[1] == BRCMS_GF_PREAMBLE)) {
- if (RSPEC2RATE(rspec[1]) != BRCM_RATE_1M)
- mch |= TXC_PREAMBLE_DATA_FB_SHORT;
- }
-
- /* MacFrameControl */
- memcpy(&txh->MacFrameControl, &h->frame_control, sizeof(u16));
- txh->TxFesTimeNormal = cpu_to_le16(0);
-
- txh->TxFesTimeFallback = cpu_to_le16(0);
-
- /* TxFrameRA */
- memcpy(&txh->TxFrameRA, &h->addr1, ETH_ALEN);
-
- /* TxFrameID */
- txh->TxFrameID = cpu_to_le16(frameid);
-
- /* TxStatus, Note the case of recreating the first frag of a suppressed frame
- * then we may need to reset the retry cnt's via the status reg
- */
- txh->TxStatus = cpu_to_le16(status);
-
- /* extra fields for ucode AMPDU aggregation, the new fields are added to
- * the END of previous structure so that it's compatible in driver.
- */
- txh->MaxNMpdus = cpu_to_le16(0);
- txh->MaxABytes_MRT = cpu_to_le16(0);
- txh->MaxABytes_FBR = cpu_to_le16(0);
- txh->MinMBytes = cpu_to_le16(0);
-
- /* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration,
- * furnish struct d11txh */
- /* RTS PLCP header and RTS frame */
- if (use_rts || use_cts) {
- if (use_rts && use_cts)
- use_cts = false;
-
- for (k = 0; k < 2; k++) {
- rts_rspec[k] = brcms_c_rspec_to_rts_rspec(wlc, rspec[k],
- false,
- mimo_ctlchbw);
- }
-
- if (!IS_OFDM(rts_rspec[0]) &&
- !((RSPEC2RATE(rts_rspec[0]) == BRCM_RATE_1M) ||
- (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
- rts_preamble_type[0] = BRCMS_SHORT_PREAMBLE;
- mch |= TXC_PREAMBLE_RTS_MAIN_SHORT;
- }
-
- if (!IS_OFDM(rts_rspec[1]) &&
- !((RSPEC2RATE(rts_rspec[1]) == BRCM_RATE_1M) ||
- (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
- rts_preamble_type[1] = BRCMS_SHORT_PREAMBLE;
- mch |= TXC_PREAMBLE_RTS_FB_SHORT;
- }
-
- /* RTS/CTS additions to MacTxControlLow */
- if (use_cts) {
- txh->MacTxControlLow |= cpu_to_le16(TXC_SENDCTS);
- } else {
- txh->MacTxControlLow |= cpu_to_le16(TXC_SENDRTS);
- txh->MacTxControlLow |= cpu_to_le16(TXC_LONGFRAME);
- }
-
- /* RTS PLCP header */
- rts_plcp = txh->RTSPhyHeader;
- if (use_cts)
- rts_phylen = DOT11_CTS_LEN + FCS_LEN;
- else
- rts_phylen = DOT11_RTS_LEN + FCS_LEN;
-
- brcms_c_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp);
-
- /* fallback rate version of RTS PLCP header */
- brcms_c_compute_plcp(wlc, rts_rspec[1], rts_phylen,
- rts_plcp_fallback);
- memcpy(&txh->RTSPLCPFallback, rts_plcp_fallback,
- sizeof(txh->RTSPLCPFallback));
-
- /* RTS frame fields... */
- rts = (struct ieee80211_rts *)&txh->rts_frame;
-
- durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec[0],
- rspec[0], rts_preamble_type[0],
- preamble_type[0], phylen, false);
- rts->duration = cpu_to_le16(durid);
- /* fallback rate version of RTS DUR field */
- durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
- rts_rspec[1], rspec[1],
- rts_preamble_type[1],
- preamble_type[1], phylen, false);
- txh->RTSDurFallback = cpu_to_le16(durid);
-
- if (use_cts) {
- rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_CTS);
-
- memcpy(&rts->ra, &h->addr2, ETH_ALEN);
- } else {
- rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_RTS);
-
- memcpy(&rts->ra, &h->addr1, 2 * ETH_ALEN);
- }
-
- /* mainrate
- * low 8 bits: main frag rate/mcs,
- * high 8 bits: rts/cts rate/mcs
- */
- mainrates |= (IS_OFDM(rts_rspec[0]) ?
- D11A_PHY_HDR_GRATE(
- (struct ofdm_phy_hdr *) rts_plcp) :
- rts_plcp[0]) << 8;
- } else {
- memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN);
- memset((char *)&txh->rts_frame, 0,
- sizeof(struct ieee80211_rts));
- memset((char *)txh->RTSPLCPFallback, 0,
- sizeof(txh->RTSPLCPFallback));
- txh->RTSDurFallback = 0;
- }
-
-#ifdef SUPPORT_40MHZ
- /* add null delimiter count */
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && IS_MCS(rspec)) {
- txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] =
- brcm_c_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen);
- }
-#endif
-
- /* Now that RTS/RTS FB preamble types are updated, write the final value */
- txh->MacTxControlHigh = cpu_to_le16(mch);
-
- /* MainRates (both the rts and frag plcp rates have been calculated now) */
- txh->MainRates = cpu_to_le16(mainrates);
-
- /* XtraFrameTypes */
- xfts = FRAMETYPE(rspec[1], wlc->mimoft);
- xfts |= (FRAMETYPE(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT);
- xfts |= (FRAMETYPE(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT);
- xfts |=
- CHSPEC_CHANNEL(BRCMS_BAND_PI_RADIO_CHANSPEC) << XFTS_CHANNEL_SHIFT;
- txh->XtraFrameTypes = cpu_to_le16(xfts);
-
- /* PhyTxControlWord */
- phyctl = FRAMETYPE(rspec[0], wlc->mimoft);
- if ((preamble_type[0] == BRCMS_SHORT_PREAMBLE) ||
- (preamble_type[0] == BRCMS_GF_PREAMBLE)) {
- if (RSPEC2RATE(rspec[0]) != BRCM_RATE_1M)
- phyctl |= PHY_TXC_SHORT_HDR;
- }
-
- /* phytxant is properly bit shifted */
- phyctl |= brcms_c_stf_d11hdrs_phyctl_txant(wlc, rspec[0]);
- txh->PhyTxControlWord = cpu_to_le16(phyctl);
-
- /* PhyTxControlWord_1 */
- if (BRCMS_PHY_11N_CAP(wlc->band)) {
- u16 phyctl1 = 0;
-
- phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[0]);
- txh->PhyTxControlWord_1 = cpu_to_le16(phyctl1);
- phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[1]);
- txh->PhyTxControlWord_1_Fbr = cpu_to_le16(phyctl1);
-
- if (use_rts || use_cts) {
- phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[0]);
- txh->PhyTxControlWord_1_Rts = cpu_to_le16(phyctl1);
- phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[1]);
- txh->PhyTxControlWord_1_FbrRts = cpu_to_le16(phyctl1);
- }
-
- /*
- * For mcs frames, if mixedmode(overloaded with long preamble) is going to be set,
- * fill in non-zero MModeLen and/or MModeFbrLen
- * it will be unnecessary if they are separated
- */
- if (IS_MCS(rspec[0]) &&
- (preamble_type[0] == BRCMS_MM_PREAMBLE)) {
- u16 mmodelen =
- brcms_c_calc_lsig_len(wlc, rspec[0], phylen);
- txh->MModeLen = cpu_to_le16(mmodelen);
- }
-
- if (IS_MCS(rspec[1]) &&
- (preamble_type[1] == BRCMS_MM_PREAMBLE)) {
- u16 mmodefbrlen =
- brcms_c_calc_lsig_len(wlc, rspec[1], phylen);
- txh->MModeFbrLen = cpu_to_le16(mmodefbrlen);
- }
- }
-
- ac = skb_get_queue_mapping(p);
- if (SCB_WME(scb) && qos && wlc->edcf_txop[ac]) {
- uint frag_dur, dur, dur_fallback;
-
- /* WME: Update TXOP threshold */
- if ((!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) && (frag == 0)) {
- frag_dur =
- brcms_c_calc_frame_time(wlc, rspec[0],
- preamble_type[0], phylen);
-
- if (rts) {
- /* 1 RTS or CTS-to-self frame */
- dur =
- brcms_c_calc_cts_time(wlc, rts_rspec[0],
- rts_preamble_type[0]);
- dur_fallback =
- brcms_c_calc_cts_time(wlc, rts_rspec[1],
- rts_preamble_type[1]);
- /* (SIFS + CTS) + SIFS + frame + SIFS + ACK */
- dur += le16_to_cpu(rts->duration);
- dur_fallback +=
- le16_to_cpu(txh->RTSDurFallback);
- } else if (use_rifs) {
- dur = frag_dur;
- dur_fallback = 0;
- } else {
- /* frame + SIFS + ACK */
- dur = frag_dur;
- dur +=
- brcms_c_compute_frame_dur(wlc, rspec[0],
- preamble_type[0], 0);
-
- dur_fallback =
- brcms_c_calc_frame_time(wlc, rspec[1],
- preamble_type[1],
- phylen);
- dur_fallback +=
- brcms_c_compute_frame_dur(wlc, rspec[1],
- preamble_type[1], 0);
- }
- /* NEED to set TxFesTimeNormal (hard) */
- txh->TxFesTimeNormal = cpu_to_le16((u16) dur);
- /* NEED to set fallback rate version of TxFesTimeNormal (hard) */
- txh->TxFesTimeFallback =
- cpu_to_le16((u16) dur_fallback);
-
- /* update txop byte threshold (txop minus intraframe overhead) */
- if (wlc->edcf_txop[ac] >= (dur - frag_dur)) {
- {
- uint newfragthresh;
-
- newfragthresh =
- brcms_c_calc_frame_len(wlc,
- rspec[0], preamble_type[0],
- (wlc->edcf_txop[ac] -
- (dur - frag_dur)));
- /* range bound the fragthreshold */
- if (newfragthresh < DOT11_MIN_FRAG_LEN)
- newfragthresh =
- DOT11_MIN_FRAG_LEN;
- else if (newfragthresh >
- wlc->usr_fragthresh)
- newfragthresh =
- wlc->usr_fragthresh;
- /* update the fragthresh and do txc update */
- if (wlc->fragthresh[queue] !=
- (u16) newfragthresh) {
- wlc->fragthresh[queue] =
- (u16) newfragthresh;
- }
- }
- } else
- wiphy_err(wlc->wiphy, "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 "
- "exceeded phylen %d/%d dur %d/%d\n",
- wlc->pub->unit, __func__,
- fifo_names[queue],
- phylen, wlc->fragthresh[queue],
- dur, wlc->edcf_txop[ac]);
- }
- }
-
- return 0;
-}
-
-void brcms_c_tbtt(struct brcms_c_info *wlc)
-{
- struct brcms_bss_cfg *cfg = wlc->cfg;
-
- if (!cfg->BSS) {
- /* DirFrmQ is now valid...defer setting until end of ATIM window */
- wlc->qvalid |= MCMD_DIRFRMQVAL;
- }
-}
-
-static void brcms_c_war16165(struct brcms_c_info *wlc, bool tx)
-{
- if (tx) {
- /* the post-increment is used in STAY_AWAKE macro */
- if (wlc->txpend16165war++ == 0)
- brcms_c_set_ps_ctrl(wlc);
- } else {
- wlc->txpend16165war--;
- if (wlc->txpend16165war == 0)
- brcms_c_set_ps_ctrl(wlc);
- }
-}
-
-/* process an individual struct tx_status */
-bool
-brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs, u32 frm_tx2)
-{
- struct sk_buff *p;
- uint queue;
- struct d11txh *txh;
- struct scb *scb = NULL;
- bool free_pdu;
- int tx_rts, tx_frame_count, tx_rts_count;
- uint totlen, supr_status;
- bool lastframe;
- struct ieee80211_hdr *h;
- u16 mcl;
- struct ieee80211_tx_info *tx_info;
- struct ieee80211_tx_rate *txrate;
- int i;
-
- (void)(frm_tx2); /* Compiler reference to avoid unused variable warning */
-
- /* discard intermediate indications for ucode with one legitimate case:
- * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
- * tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
- * transmission count)
- */
- if (!(txs->status & TX_STATUS_AMPDU)
- && (txs->status & TX_STATUS_INTERMEDIATE)) {
- wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
- __func__);
- return false;
- }
-
- queue = txs->frameid & TXFID_QUEUE_MASK;
- if (queue >= NFIFO) {
- p = NULL;
- goto fatal;
- }
-
- p = GETNEXTTXP(wlc, queue);
- if (BRCMS_WAR16165(wlc))
- brcms_c_war16165(wlc, false);
- if (p == NULL)
- goto fatal;
-
- txh = (struct d11txh *) (p->data);
- mcl = le16_to_cpu(txh->MacTxControlLow);
-
- if (txs->phyerr) {
- if (WL_ERROR_ON()) {
- 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->frameid != cpu_to_le16(txh->TxFrameID))
- goto fatal;
- tx_info = IEEE80211_SKB_CB(p);
- h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
-
- if (tx_info->control.sta)
- scb = (struct scb *)tx_info->control.sta->drv_priv;
-
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
- brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
- return false;
- }
-
- 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));
-
- tx_rts = cpu_to_le16(txh->MacTxControlLow) & TXC_SENDRTS;
- tx_frame_count =
- (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT;
- tx_rts_count =
- (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT;
-
- lastframe = !ieee80211_has_morefrags(h->frame_control);
-
- if (!lastframe) {
- wiphy_err(wlc->wiphy, "Not last frame!\n");
- } else {
- /*
- * Set information to be consumed by Minstrel ht.
- *
- * The "fallback limit" is the number of tx attempts a given
- * MPDU is sent at the "primary" rate. Tx attempts beyond that
- * limit are sent at the "secondary" rate.
- * A 'short frame' does not exceed RTS treshold.
- */
- u16 sfbl, /* Short Frame Rate Fallback Limit */
- lfbl, /* Long Frame Rate Fallback Limit */
- fbl;
-
- if (queue < AC_COUNT) {
- sfbl = BRCMS_WME_RETRY_SFB_GET(wlc, wme_fifo2ac[queue]);
- lfbl = BRCMS_WME_RETRY_LFB_GET(wlc, wme_fifo2ac[queue]);
- } else {
- sfbl = wlc->SFBL;
- lfbl = wlc->LFBL;
- }
-
- txrate = tx_info->status.rates;
- if (txrate[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
- fbl = lfbl;
- else
- fbl = sfbl;
-
- ieee80211_tx_info_clear_status(tx_info);
-
- if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) {
- /* rate selection requested a fallback rate and we used it */
- txrate[0].count = fbl;
- txrate[1].count = tx_frame_count - fbl;
- } else {
- /* rate selection did not request fallback rate, or we didn't need it */
- txrate[0].count = tx_frame_count;
- /* rc80211_minstrel.c:minstrel_tx_status() expects unused rates to be marked with idx = -1 */
- txrate[1].idx = -1;
- txrate[1].count = 0;
- }
-
- /* clear the rest of the rates */
- for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
- txrate[i].idx = -1;
- txrate[i].count = 0;
- }
-
- if (txs->status & TX_STATUS_ACK_RCV)
- tx_info->flags |= IEEE80211_TX_STAT_ACK;
- }
-
- totlen = brcmu_pkttotlen(p);
- free_pdu = true;
-
- brcms_c_txfifo_complete(wlc, queue, 1);
-
- if (lastframe) {
- p->next = NULL;
- p->prev = NULL;
- /* 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__);
- }
-
- return false;
-
- fatal:
- if (p)
- brcmu_pkt_buf_free_skb(p);
-
- return true;
-
-}
-
-void
-brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend)
-{
- TXPKTPENDDEC(wlc, fifo, txpktpend);
- BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend,
- TXPKTPENDGET(wlc, fifo));
-
- /* There is more room; mark precedences related to this FIFO sendable */
- BRCMS_TX_FIFO_ENAB(wlc, fifo);
-
- /* Clear MHF2_TXBCMC_NOW flag if BCMC fifo has drained */
- if (AP_ENAB(wlc->pub) &&
- !TXPKTPENDGET(wlc, TX_BCMC_FIFO)) {
- brcms_c_mhf(wlc, MHF2, MHF2_TXBCMC_NOW, 0, BRCM_BAND_AUTO);
- }
-
- /* figure out which bsscfg is being worked on... */
-}
-
-/* Update beacon listen interval in shared memory */
-void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
-{
- if (AP_ENAB(wlc->pub))
- return;
-
- /* wake up every DTIM is the default */
- if (wlc->bcn_li_dtim == 1)
- brcms_c_write_shm(wlc, M_BCN_LI, 0);
- else
- brcms_c_write_shm(wlc, M_BCN_LI,
- (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn);
-}
-
-/*
- * recover 64bit TSF value from the 16bit TSF value in the rx header
- * given the assumption that the TSF passed in header is within 65ms
- * of the current tsf.
- *
- * 6 5 4 4 3 2 1
- * 3.......6.......8.......0.......2.......4.......6.......8......0
- * |<---------- tsf_h ----------->||<--- tsf_l -->||<-RxTSFTime ->|
- *
- * The RxTSFTime are the lowest 16 bits and provided by the ucode. The
- * tsf_l is filled in by brcms_b_recv, which is done earlier in the
- * receive call sequence after rx interrupt. Only the higher 16 bits
- * are used. Finally, the tsf_h is read from the tsf register.
- */
-static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc,
- struct brcms_d11rxhdr *rxh)
-{
- u32 tsf_h, tsf_l;
- u16 rx_tsf_0_15, rx_tsf_16_31;
-
- brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
-
- rx_tsf_16_31 = (u16)(tsf_l >> 16);
- rx_tsf_0_15 = rxh->rxhdr.RxTSFTime;
-
- /*
- * a greater tsf time indicates the low 16 bits of
- * tsf_l wrapped, so decrement the high 16 bits.
- */
- if ((u16)tsf_l < rx_tsf_0_15) {
- rx_tsf_16_31 -= 1;
- if (rx_tsf_16_31 == 0xffff)
- tsf_h -= 1;
- }
-
- return ((u64)tsf_h << 32) | (((u32)rx_tsf_16_31 << 16) + rx_tsf_0_15);
-}
-
-static void
-prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
- struct sk_buff *p,
- struct ieee80211_rx_status *rx_status)
-{
- struct brcms_d11rxhdr *wlc_rxh = (struct brcms_d11rxhdr *) rxh;
- int preamble;
- int channel;
- ratespec_t rspec;
- unsigned char *plcp;
-
- /* fill in TSF and flag its presence */
- rx_status->mactime = brcms_c_recover_tsf64(wlc, wlc_rxh);
- rx_status->flag |= RX_FLAG_MACTIME_MPDU;
-
- channel = BRCMS_CHAN_CHANNEL(rxh->RxChan);
-
- if (channel > 14) {
- rx_status->band = IEEE80211_BAND_5GHZ;
- rx_status->freq = ieee80211_ofdm_chan_to_freq(
- WF_CHAN_FACTOR_5_G/2, channel);
-
- } else {
- rx_status->band = IEEE80211_BAND_2GHZ;
- rx_status->freq = ieee80211_dsss_chan_to_freq(channel);
- }
-
- rx_status->signal = wlc_rxh->rssi; /* signal */
-
- /* noise */
- /* qual */
- rx_status->antenna = (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0; /* ant */
-
- plcp = p->data;
-
- rspec = brcms_c_compute_rspec(rxh, plcp);
- if (IS_MCS(rspec)) {
- rx_status->rate_idx = rspec & RSPEC_RATE_MASK;
- rx_status->flag |= RX_FLAG_HT;
- if (RSPEC_IS40MHZ(rspec))
- rx_status->flag |= RX_FLAG_40MHZ;
- } else {
- switch (RSPEC2RATE(rspec)) {
- case BRCM_RATE_1M:
- rx_status->rate_idx = 0;
- break;
- case BRCM_RATE_2M:
- rx_status->rate_idx = 1;
- break;
- case BRCM_RATE_5M5:
- rx_status->rate_idx = 2;
- break;
- case BRCM_RATE_11M:
- rx_status->rate_idx = 3;
- break;
- case BRCM_RATE_6M:
- rx_status->rate_idx = 4;
- break;
- case BRCM_RATE_9M:
- rx_status->rate_idx = 5;
- break;
- case BRCM_RATE_12M:
- rx_status->rate_idx = 6;
- break;
- case BRCM_RATE_18M:
- rx_status->rate_idx = 7;
- break;
- case BRCM_RATE_24M:
- rx_status->rate_idx = 8;
- break;
- case BRCM_RATE_36M:
- rx_status->rate_idx = 9;
- break;
- case BRCM_RATE_48M:
- rx_status->rate_idx = 10;
- break;
- case BRCM_RATE_54M:
- rx_status->rate_idx = 11;
- break;
- default:
- wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__);
- }
-
- /* Determine short preamble and rate_idx */
- preamble = 0;
- if (IS_CCK(rspec)) {
- if (rxh->PhyRxStatus_0 & PRXS0_SHORTH)
- rx_status->flag |= RX_FLAG_SHORTPRE;
- } else if (IS_OFDM(rspec)) {
- rx_status->flag |= RX_FLAG_SHORTPRE;
- } else {
- wiphy_err(wlc->wiphy, "%s: Unknown modulation\n",
- __func__);
- }
- }
-
- if (PLCP3_ISSGI(plcp[3]))
- rx_status->flag |= RX_FLAG_SHORT_GI;
-
- if (rxh->RxStatus1 & RXS_DECERR) {
- rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
- wiphy_err(wlc->wiphy, "%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",
- __func__);
- }
-}
-
-static void
-brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
- struct sk_buff *p)
-{
- int len_mpdu;
- struct ieee80211_rx_status rx_status;
-
- memset(&rx_status, 0, sizeof(rx_status));
- prep_mac80211_status(wlc, rxh, p, &rx_status);
-
- /* mac header+body length, exclude CRC and plcp header */
- len_mpdu = p->len - D11_PHY_HDR_LEN - FCS_LEN;
- skb_pull(p, D11_PHY_HDR_LEN);
- __skb_trim(p, len_mpdu);
-
- memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
- ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
- return;
-}
-
-/* Process received frames */
-/*
- * Return true if more frames need to be processed. false otherwise.
- * Param 'bound' indicates max. # frames to process before break out.
- */
-void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
-{
- struct d11rxhdr *rxh;
- struct ieee80211_hdr *h;
- uint len;
- bool is_amsdu;
-
- BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
- /* frame starts with rxhdr */
- rxh = (struct d11rxhdr *) (p->data);
-
- /* strip off rxhdr */
- skb_pull(p, BRCMS_HWRXOFF);
-
- /* fixup rx header endianness */
- rxh->RxFrameSize = le16_to_cpu(rxh->RxFrameSize);
- rxh->PhyRxStatus_0 = le16_to_cpu(rxh->PhyRxStatus_0);
- rxh->PhyRxStatus_1 = le16_to_cpu(rxh->PhyRxStatus_1);
- rxh->PhyRxStatus_2 = le16_to_cpu(rxh->PhyRxStatus_2);
- rxh->PhyRxStatus_3 = le16_to_cpu(rxh->PhyRxStatus_3);
- rxh->PhyRxStatus_4 = le16_to_cpu(rxh->PhyRxStatus_4);
- rxh->PhyRxStatus_5 = le16_to_cpu(rxh->PhyRxStatus_5);
- rxh->RxStatus1 = le16_to_cpu(rxh->RxStatus1);
- rxh->RxStatus2 = le16_to_cpu(rxh->RxStatus2);
- rxh->RxTSFTime = le16_to_cpu(rxh->RxTSFTime);
- rxh->RxChan = le16_to_cpu(rxh->RxChan);
-
- /* 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);
- goto toss;
- }
- skb_pull(p, 2);
- }
-
- h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
- len = p->len;
-
- if (rxh->RxStatus1 & RXS_FCSERR) {
- if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
- wiphy_err(wlc->wiphy, "FCSERR while scanning******* -"
- " tossing\n");
- goto toss;
- } else {
- wiphy_err(wlc->wiphy, "RCSERR!!!\n");
- goto toss;
- }
- }
-
- /* check received pkt has at least frame control field */
- if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control)) {
- goto toss;
- }
-
- is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
-
- /* explicitly test bad src address to avoid sending bad deauth */
- if (!is_amsdu) {
- /* CTS and ACK CTL frames are w/o a2 */
-
- if (ieee80211_is_data(h->frame_control) ||
- ieee80211_is_mgmt(h->frame_control)) {
- if ((is_zero_ether_addr(h->addr2) ||
- is_multicast_ether_addr(h->addr2))) {
- wiphy_err(wlc->wiphy, "wl%d: %s: dropping a "
- "frame with invalid src mac address,"
- " a2: %pM\n",
- wlc->pub->unit, __func__, h->addr2);
- goto toss;
- }
- }
- }
-
- /* due to sheer numbers, toss out probe reqs for now */
- if (ieee80211_is_probe_req(h->frame_control))
- goto toss;
-
- if (is_amsdu)
- goto toss;
-
- brcms_c_recvctl(wlc, rxh, p);
- return;
-
- toss:
- brcmu_pkt_buf_free_skb(p);
-}
-
-/* calculate frame duration for Mixed-mode L-SIG spoofing, return
- * number of bytes goes in the length field
- *
- * Formula given by HT PHY Spec v 1.13
- * len = 3(nsyms + nstream + 3) - 3
- */
-u16
-brcms_c_calc_lsig_len(struct brcms_c_info *wlc, ratespec_t ratespec,
- uint mac_len)
-{
- 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(ratespec)) {
- uint mcs = ratespec & RSPEC_RATE_MASK;
- /* MCS_TXS(mcs) returns num tx streams - 1 */
- int tot_streams = (MCS_TXS(mcs) + 1) + RSPEC_STC(ratespec);
-
- /* the payload duration calculation matches that of regular ofdm */
- /* 1000Ndbps = kbps * 4 */
- kNdps =
- MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
- RSPEC_ISSGI(ratespec)) * 4;
-
- if (RSPEC_STC(ratespec) == 0)
- /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
- nsyms =
- CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
- APHY_TAIL_NBITS) * 1000, kNdps);
- else
- /* STBC needs to have even number of symbols */
- nsyms =
- 2 *
- CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
- APHY_TAIL_NBITS) * 1000, 2 * kNdps);
-
- nsyms += (tot_streams + 3); /* (+3) account for HT-SIG(2) and HT-STF(1) */
- /* 3 bytes/symbol @ legacy 6Mbps rate */
- len = (3 * nsyms) - 3; /* (-3) excluding service bits and tail bits */
- }
-
- return (u16) len;
-}
-
-/* calculate frame duration of a given rate and length, return time in usec unit */
-uint
-brcms_c_calc_frame_time(struct brcms_c_info *wlc, ratespec_t ratespec,
- u8 preamble_type, uint mac_len)
-{
- uint nsyms, dur = 0, Ndps, kNdps;
- uint rate = RSPEC2RATE(ratespec);
-
- if (rate == 0) {
- wiphy_err(wlc->wiphy, "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(ratespec)) {
- uint mcs = ratespec & RSPEC_RATE_MASK;
- int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
-
- dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
- if (preamble_type == BRCMS_MM_PREAMBLE)
- dur += PREN_MM_EXT;
- /* 1000Ndbps = kbps * 4 */
- kNdps =
- MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
- RSPEC_ISSGI(ratespec)) * 4;
-
- if (RSPEC_STC(ratespec) == 0)
- /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
- nsyms =
- CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
- APHY_TAIL_NBITS) * 1000, kNdps);
- else
- /* STBC needs to have even number of symbols */
- nsyms =
- 2 *
- CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
- APHY_TAIL_NBITS) * 1000, 2 * kNdps);
-
- dur += APHY_SYMBOL_TIME * nsyms;
- if (BAND_2G(wlc->band->bandtype))
- dur += DOT11_OFDM_SIGNAL_EXTENSION;
- } else if (IS_OFDM(rate)) {
- dur = APHY_PREAMBLE_TIME;
- dur += APHY_SIGNAL_TIME;
- /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
- Ndps = rate * 2;
- /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
- nsyms =
- CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
- Ndps);
- dur += APHY_SYMBOL_TIME * nsyms;
- if (BAND_2G(wlc->band->bandtype))
- dur += DOT11_OFDM_SIGNAL_EXTENSION;
- } else {
- /* calc # bits * 2 so factor of 2 in rate (1/2 mbps) will divide out */
- mac_len = mac_len * 8 * 2;
- /* calc ceiling of bits/rate = microseconds of air time */
- dur = (mac_len + rate - 1) / rate;
- if (preamble_type & BRCMS_SHORT_PREAMBLE)
- dur += BPHY_PLCP_SHORT_TIME;
- else
- dur += BPHY_PLCP_TIME;
- }
- return dur;
-}
-
-/* The opposite of brcms_c_calc_frame_time */
-static uint
-brcms_c_calc_frame_len(struct brcms_c_info *wlc, ratespec_t ratespec,
- u8 preamble_type, uint dur)
-{
- 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(ratespec)) {
- uint mcs = ratespec & RSPEC_RATE_MASK;
- int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
- dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
- /* payload calculation matches that of regular ofdm */
- if (BAND_2G(wlc->band->bandtype))
- dur -= DOT11_OFDM_SIGNAL_EXTENSION;
- /* kNdbps = kbps * 4 */
- kNdps =
- MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
- RSPEC_ISSGI(ratespec)) * 4;
- nsyms = dur / APHY_SYMBOL_TIME;
- mac_len =
- ((nsyms * kNdps) -
- ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000;
- } else if (IS_OFDM(ratespec)) {
- dur -= APHY_PREAMBLE_TIME;
- dur -= APHY_SIGNAL_TIME;
- /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
- Ndps = rate * 2;
- nsyms = dur / APHY_SYMBOL_TIME;
- mac_len =
- ((nsyms * Ndps) -
- (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8;
- } else {
- if (preamble_type & BRCMS_SHORT_PREAMBLE)
- dur -= BPHY_PLCP_SHORT_TIME;
- else
- dur -= BPHY_PLCP_TIME;
- mac_len = dur * rate;
- /* divide out factor of 2 in rate (1/2 mbps) */
- mac_len = mac_len / 8 / 2;
- }
- return mac_len;
-}
-
-static uint
-brcms_c_calc_ba_time(struct brcms_c_info *wlc, ratespec_t 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 frame in the FES
- */
- rspec = BRCMS_BASIC_RATE(wlc, rspec);
- /* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */
- return brcms_c_calc_frame_time(wlc, rspec, preamble_type,
- (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN +
- FCS_LEN));
-}
-
-static uint
-brcms_c_calc_ack_time(struct brcms_c_info *wlc, ratespec_t rspec,
- u8 preamble_type)
-{
- 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 frame in the FES
- */
- rspec = BRCMS_BASIC_RATE(wlc, rspec);
- /* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */
- dur =
- brcms_c_calc_frame_time(wlc, rspec, preamble_type,
- (DOT11_ACK_LEN + FCS_LEN));
- return dur;
-}
-
-static uint
-brcms_c_calc_cts_time(struct brcms_c_info *wlc, ratespec_t 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);
-}
-
-/* derive wlc->band->basic_rate[] table from 'rateset' */
-void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, wlc_rateset_t *rateset)
-{
- u8 rate;
- u8 mandatory;
- u8 cck_basic = 0;
- u8 ofdm_basic = 0;
- u8 *br = wlc->band->basic_rate;
- uint i;
-
- /* incoming rates are in 500kbps units as in 802.11 Supported Rates */
- memset(br, 0, BRCM_MAXRATE + 1);
-
- /* For each basic rate in the rates list, make an entry in the
- * best basic lookup.
- */
- for (i = 0; i < rateset->count; i++) {
- /* only make an entry for a basic rate */
- if (!(rateset->rates[i] & BRCMS_RATE_FLAG))
- continue;
-
- /* mask off basic bit */
- rate = (rateset->rates[i] & BRCMS_RATE_MASK);
-
- if (rate > BRCM_MAXRATE) {
- wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: "
- "invalid rate 0x%X in rate set\n",
- rateset->rates[i]);
- continue;
- }
-
- br[rate] = rate;
- }
-
- /* The rate lookup table now has non-zero entries for each
- * basic rate, equal to the basic rate: br[basicN] = basicN
- *
- * To look up the best basic rate corresponding to any
- * particular rate, code can use the basic_rate table
- * like this
- *
- * basic_rate = wlc->band->basic_rate[tx_rate]
- *
- * Make sure there is a best basic rate entry for
- * every rate by walking up the table from low rates
- * to high, filling in holes in the lookup table
- */
-
- for (i = 0; i < wlc->band->hw_rateset.count; i++) {
- rate = wlc->band->hw_rateset.rates[i];
-
- if (br[rate] != 0) {
- /* This rate is a basic rate.
- * Keep track of the best basic rate so far by
- * modulation type.
- */
- if (IS_OFDM(rate))
- ofdm_basic = rate;
- else
- cck_basic = rate;
-
- continue;
- }
-
- /* This rate is not a basic rate so figure out the
- * best basic rate less than this rate and fill in
- * the hole in the table
- */
-
- br[rate] = IS_OFDM(rate) ? ofdm_basic : cck_basic;
-
- if (br[rate] != 0)
- continue;
-
- if (IS_OFDM(rate)) {
- /* In 11g and 11a, the OFDM mandatory rates are 6, 12, and 24 Mbps */
- if (rate >= BRCM_RATE_24M)
- mandatory = BRCM_RATE_24M;
- else if (rate >= BRCM_RATE_12M)
- mandatory = BRCM_RATE_12M;
- else
- mandatory = BRCM_RATE_6M;
- } else {
- /* In 11b, all the CCK rates are mandatory 1 - 11 Mbps */
- mandatory = rate;
- }
-
- br[rate] = mandatory;
- }
-}
-
-static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate,
- u8 basic_rate)
-{
- u8 phy_rate, index;
- u8 basic_phy_rate, basic_index;
- u16 dir_table, basic_table;
- u16 basic_ptr;
-
- /* Shared memory address for the table we are reading */
- dir_table = IS_OFDM(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
-
- /* Shared memory address for the table we are writing */
- basic_table = IS_OFDM(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
-
- /*
- * for a given rate, the LS-nibble of the PLCP SIGNAL field is
- * the index into the rate table.
- */
- phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
- basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK;
- index = phy_rate & 0xf;
- basic_index = basic_phy_rate & 0xf;
-
- /* Find the SHM pointer to the ACK rate entry by looking in the
- * Direct-map Table
- */
- basic_ptr = brcms_c_read_shm(wlc, (dir_table + basic_index * 2));
-
- /* Update the SHM BSS-basic-rate-set mapping table with the pointer
- * to the correct basic rate for the given incoming rate
- */
- brcms_c_write_shm(wlc, (basic_table + index * 2), basic_ptr);
-}
-
-static const wlc_rateset_t *brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc)
-{
- const wlc_rateset_t *rs_dflt;
-
- if (BRCMS_PHY_11N_CAP(wlc->band)) {
- if (BAND_5G(wlc->band->bandtype))
- rs_dflt = &ofdm_mimo_rates;
- else
- rs_dflt = &cck_ofdm_mimo_rates;
- } else if (wlc->band->gmode)
- rs_dflt = &cck_ofdm_rates;
- else
- rs_dflt = &cck_rates;
-
- return rs_dflt;
-}
-
-void brcms_c_set_ratetable(struct brcms_c_info *wlc)
-{
- const wlc_rateset_t *rs_dflt;
- wlc_rateset_t rs;
- u8 rate, basic_rate;
- uint i;
-
- rs_dflt = brcms_c_rateset_get_hwrs(wlc);
-
- brcms_c_rateset_copy(rs_dflt, &rs);
- brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
-
- /* walk the phy rate table and update SHM basic rate lookup table */
- for (i = 0; i < rs.count; i++) {
- rate = rs.rates[i] & BRCMS_RATE_MASK;
-
- /* for a given rate BRCMS_BASIC_RATE returns the rate at
- * which a response ACK/CTS should be sent.
- */
- basic_rate = BRCMS_BASIC_RATE(wlc, rate);
- if (basic_rate == 0) {
- /* This should only happen if we are using a
- * restricted rateset.
- */
- basic_rate = rs.rates[0] & BRCMS_RATE_MASK;
- }
-
- brcms_c_write_rate_shm(wlc, rate, basic_rate);
- }
-}
-
-/*
- * Return true if the specified rate is supported by the specified band.
- * BRCM_BAND_AUTO indicates the current band.
- */
-bool brcms_c_valid_rate(struct brcms_c_info *wlc, ratespec_t rspec, int band,
- bool verbose)
-{
- wlc_rateset_t *hw_rateset;
- uint i;
-
- if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype)) {
- hw_rateset = &wlc->band->hw_rateset;
- } else if (NBANDS(wlc) > 1) {
- hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
- } else {
- /* other band specified and we are a single band device */
- return false;
- }
-
- /* check if this is a mimo rate */
- if (IS_MCS(rspec)) {
- if (!VALID_MCS((rspec & RSPEC_RATE_MASK)))
- goto error;
-
- return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
- }
-
- for (i = 0; i < hw_rateset->count; i++)
- if (hw_rateset->rates[i] == RSPEC2RATE(rspec))
- return true;
- error:
- if (verbose) {
- wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x "
- "not in hw_rateset\n", wlc->pub->unit, rspec);
- }
-
- return false;
-}
-
-static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap)
-{
- uint i;
- struct brcms_band *band;
-
- for (i = 0; i < NBANDS(wlc); i++) {
- if (IS_SINGLEBAND_5G(wlc->deviceid))
- i = BAND_5G_INDEX;
- band = wlc->bandstate[i];
- if (band->bandtype == BRCM_BAND_5G) {
- if ((bwcap == BRCMS_N_BW_40ALL)
- || (bwcap == BRCMS_N_BW_20IN2G_40IN5G))
- band->mimo_cap_40 = true;
- else
- band->mimo_cap_40 = false;
- } else {
- if (bwcap == BRCMS_N_BW_40ALL)
- band->mimo_cap_40 = true;
- else
- band->mimo_cap_40 = false;
- }
- }
-}
-
-void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
-{
- const wlc_rateset_t *rs_dflt;
- wlc_rateset_t rs;
- u8 rate;
- u16 entry_ptr;
- u8 plcp[D11_PHY_HDR_LEN];
- u16 dur, sifs;
- uint i;
-
- sifs = SIFS(wlc->band);
-
- rs_dflt = brcms_c_rateset_get_hwrs(wlc);
-
- brcms_c_rateset_copy(rs_dflt, &rs);
- brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
-
- /* walk the phy rate table and update MAC core SHM basic rate table entries */
- for (i = 0; i < rs.count; i++) {
- rate = rs.rates[i] & BRCMS_RATE_MASK;
-
- entry_ptr = brcms_c_rate_shm_offset(wlc, rate);
-
- /* Calculate the Probe Response PLCP for the given rate */
- brcms_c_compute_plcp(wlc, rate, frame_len, plcp);
-
- /* Calculate the duration of the Probe Response frame plus SIFS for the MAC */
- dur = (u16) brcms_c_calc_frame_time(wlc, rate,
- BRCMS_LONG_PREAMBLE, frame_len);
- dur += sifs;
-
- /* Update the SHM Rate Table entry Probe Response values */
- brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS,
- (u16) (plcp[0] + (plcp[1] << 8)));
- brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS + 2,
- (u16) (plcp[2] + (plcp[3] << 8)));
- brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_DUR_POS, dur);
- }
-}
-
-/* Max buffering needed for beacon template/prb resp template is 142 bytes.
- *
- * PLCP header is 6 bytes.
- * 802.11 A3 header is 24 bytes.
- * Max beacon frame body template length is 112 bytes.
- * Max probe resp frame body template length is 110 bytes.
- *
- * *len on input contains the max length of the packet available.
- *
- * The *len value is set to the number of bytes in buf used, and starts with the PLCP
- * and included up to, but not including, the 4 byte FCS.
- */
-static void
-brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
- ratespec_t bcn_rspec,
- struct brcms_bss_cfg *cfg, u16 *buf, int *len)
-{
- static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
- struct cck_phy_hdr *plcp;
- struct ieee80211_mgmt *h;
- int hdr_len, body_len;
-
- if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
- hdr_len = DOT11_MAC_HDR_LEN;
- else
- hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
- body_len = *len - hdr_len; /* calc buffer size provided for frame body */
-
- *len = hdr_len + body_len; /* return actual size */
-
- /* format PHY and MAC headers */
- memset((char *)buf, 0, hdr_len);
-
- plcp = (struct cck_phy_hdr *) buf;
-
- /* PLCP for Probe Response frames are filled in from core's rate table */
- if (type == IEEE80211_STYPE_BEACON && !MBSS_BCN_ENAB(cfg)) {
- /* fill in PLCP */
- brcms_c_compute_plcp(wlc, bcn_rspec,
- (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
- (u8 *) plcp);
-
- }
- /* "Regular" and 16 MBSS but not for 4 MBSS */
- /* Update the phytxctl for the beacon based on the rspec */
- if (!SOFTBCN_ENAB(cfg))
- brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
-
- if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
- h = (struct ieee80211_mgmt *)&plcp[0];
- else
- h = (struct ieee80211_mgmt *)&plcp[1];
-
- /* fill in 802.11 header */
- h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
-
- /* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
- /* A1 filled in by MAC for prb resp, broadcast for bcn */
- if (type == IEEE80211_STYPE_BEACON)
- memcpy(&h->da, &ether_bcast, ETH_ALEN);
- memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN);
- memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
-
- /* SEQ filled in by MAC */
-
- return;
-}
-
-int brcms_c_get_header_len()
-{
- return TXOFF;
-}
-
-/* Update a beacon for a particular BSS
- * For MBSS, this updates the software template and sets "latest" to the index of the
- * template updated.
- * Otherwise, it updates the hardware template.
- */
-void brcms_c_bss_update_beacon(struct brcms_c_info *wlc,
- struct brcms_bss_cfg *cfg)
-{
- int len = BCN_TMPL_LEN;
-
- /* Clear the soft intmask */
- wlc->defmacintmask &= ~MI_BCNTPL;
-
- if (!cfg->up) { /* Only allow updates on an UP bss */
- return;
- }
-
- /* Optimize: Some of if/else could be combined */
- if (!MBSS_BCN_ENAB(cfg) && HWBCN_ENAB(cfg)) {
- /* Hardware beaconing for this config */
- u16 bcn[BCN_TMPL_LEN / 2];
- u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
- d11regs_t *regs = wlc->regs;
-
- /* Check if both templates are in use, if so sched. an interrupt
- * that will call back into this routine
- */
- if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
- /* clear any previous status */
- W_REG(&regs->macintstatus, MI_BCNTPL);
- }
- /* Check that after scheduling the interrupt both of the
- * templates are still busy. if not clear the int. & remask
- */
- if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
- wlc->defmacintmask |= MI_BCNTPL;
- return;
- }
-
- wlc->bcn_rspec =
- brcms_c_lowest_basic_rspec(wlc, &cfg->current_bss->rateset);
- /* update the template and ucode shm */
- brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_BEACON,
- wlc->bcn_rspec, cfg, bcn, &len);
- brcms_c_write_hw_bcntemplates(wlc, bcn, len, false);
- }
-}
-
-/*
- * Update all beacons for the system.
- */
-void brcms_c_update_beacon(struct brcms_c_info *wlc)
-{
- int idx;
- struct brcms_bss_cfg *bsscfg;
-
- /* update AP or IBSS beacons */
- FOREACH_BSS(wlc, idx, bsscfg) {
- if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
- brcms_c_bss_update_beacon(wlc, bsscfg);
- }
-}
-
-/* Write ssid into shared memory */
-void brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
-{
- u8 *ssidptr = cfg->SSID;
- u16 base = M_SSID;
- u8 ssidbuf[IEEE80211_MAX_SSID_LEN];
-
- /* padding the ssid with zero and copy it into shm */
- memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN);
- memcpy(ssidbuf, ssidptr, cfg->SSID_len);
-
- brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN);
-
- if (!MBSS_BCN_ENAB(cfg))
- brcms_c_write_shm(wlc, M_SSIDLEN, (u16) cfg->SSID_len);
-}
-
-void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
-{
- int idx;
- struct brcms_bss_cfg *bsscfg;
-
- /* update AP or IBSS probe responses */
- FOREACH_BSS(wlc, idx, bsscfg) {
- if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
- brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
- }
-}
-
-void
-brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
- struct brcms_bss_cfg *cfg,
- bool suspend)
-{
- u16 prb_resp[BCN_TMPL_LEN / 2];
- int len = BCN_TMPL_LEN;
-
- /* write the probe response to hardware, or save in the config structure */
- if (!MBSS_PRB_ENAB(cfg)) {
-
- /* create the probe response template */
- brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
- cfg, prb_resp, &len);
-
- if (suspend)
- brcms_c_suspend_mac_and_wait(wlc);
-
- /* write the probe response into the template region */
- brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
- (len + 3) & ~3, prb_resp);
-
- /* write the length of the probe response frame (+PLCP/-FCS) */
- brcms_c_write_shm(wlc, M_PRB_RESP_FRM_LEN, (u16) len);
-
- /* write the SSID and SSID length */
- brcms_c_shm_ssid_upd(wlc, cfg);
-
- /*
- * Write PLCP headers and durations for probe response frames at all rates.
- * Use the actual frame length covered by the PLCP header for the call to
- * brcms_c_mod_prb_rsp_rate_table() by subtracting the PLCP len
- * and adding the FCS.
- */
- len += (-D11_PHY_HDR_LEN + FCS_LEN);
- brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
-
- if (suspend)
- brcms_c_enable_mac(wlc);
- } else { /* Generating probe resp in sw; update local template */
- /* error: No software probe response support without MBSS */
- }
-}
-
-/* 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 (TXAVAIL(wlc, fifo) < MAX_DMA_SEGS) {
- /* Mark precedences related to this FIFO, unsendable */
- BRCMS_TX_FIFO_CLEAR(wlc, fifo);
- return -EBUSY;
- }
- return 0;
-}
-
-/* init tx reported rate mechanism */
-void brcms_c_reprate_init(struct brcms_c_info *wlc)
-{
- int i;
- struct brcms_bss_cfg *bsscfg;
-
- FOREACH_BSS(wlc, i, bsscfg) {
- brcms_c_bsscfg_reprate_init(bsscfg);
- }
-}
-
-/* per bsscfg init tx reported rate mechanism */
-void brcms_c_bsscfg_reprate_init(struct brcms_bss_cfg *bsscfg)
-{
- bsscfg->txrspecidx = 0;
- memset((char *)bsscfg->txrspec, 0, sizeof(bsscfg->txrspec));
-}
-
-void brcms_default_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs)
-{
- brcms_c_rateset_default(rs, NULL, wlc->band->phytype,
- wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL,
- (bool) N_ENAB(wlc->pub),
- CHSPEC_WLC_BW(wlc->default_bss->chanspec),
- wlc->stf->txstreams);
-}
-
-static void brcms_c_bss_default_init(struct brcms_c_info *wlc)
-{
- chanspec_t chanspec;
- struct brcms_band *band;
- struct brcms_bss_info *bi = wlc->default_bss;
-
- /* init default and target BSS with some sane initial values */
- memset((char *)(bi), 0, sizeof(struct brcms_bss_info));
- bi->beacon_period = BEACON_INTERVAL_DEFAULT;
- bi->dtim_period = DTIM_INTERVAL_DEFAULT;
-
- /* fill the default channel as the first valid channel
- * starting from the 2G channels
- */
- chanspec = CH20MHZ_CHSPEC(1);
- wlc->home_chanspec = bi->chanspec = chanspec;
-
- /* find the band of our default channel */
- band = wlc->band;
- if (NBANDS(wlc) > 1 && band->bandunit != CHSPEC_BANDUNIT(chanspec))
- band = wlc->bandstate[OTHERBANDUNIT(wlc)];
-
- /* init bss rates to the band specific default rate set */
- brcms_c_rateset_default(&bi->rateset, NULL, band->phytype,
- band->bandtype, false, BRCMS_RATE_MASK_FULL,
- (bool) N_ENAB(wlc->pub), CHSPEC_WLC_BW(chanspec),
- wlc->stf->txstreams);
-
- if (N_ENAB(wlc->pub))
- bi->flags |= BRCMS_BSS_HT;
-}
-
-static ratespec_t
-mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
- u32 int_val)
-{
- u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
- u8 rate = int_val & NRATE_RATE_MASK;
- ratespec_t rspec;
- bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE);
- bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT);
- bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY)
- == NRATE_OVERRIDE_MCS_ONLY);
- int bcmerror = 0;
-
- if (!ismcs) {
- return (ratespec_t) rate;
- }
-
- /* validate the combination of rate/mcs/stf is allowed */
- if (N_ENAB(wlc->pub) && ismcs) {
- /* mcs only allowed when nmode */
- if (stf > PHY_TXC1_MODE_SDM) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n",
- BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
-
- /* mcs 32 is a special case, DUP mode 40 only */
- if (rate == 32) {
- 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", BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
- /* mcs > 7 must use stf SDM */
- } 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",
- BRCMS_UNIT(wlc), rate);
- stf = PHY_TXC1_MODE_SDM;
- }
- } else {
- /* MCS 0-7 may use SISO, CDD, and for phy_rev >= 3 STBC */
- 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", BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
- }
- } else if (IS_OFDM(rate)) {
- if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n",
- BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
- } else if (IS_CCK(rate)) {
- if ((cur_band->bandtype != BRCM_BAND_2G)
- || (stf != PHY_TXC1_MODE_SISO)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n",
- BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
- } else {
- wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n",
- BRCMS_UNIT(wlc), __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 "
- "request\n", BRCMS_UNIT(wlc), __func__);
- bcmerror = -EINVAL;
- goto done;
- }
-
- rspec = rate;
- if (ismcs) {
- rspec |= RSPEC_MIMORATE;
- /* For STBC populate the STC field of the ratespec */
- if (stf == PHY_TXC1_MODE_STBC) {
- u8 stc;
- stc = 1; /* Nss for single stream is always 1 */
- rspec |= (stc << RSPEC_STC_SHIFT);
- }
- }
-
- rspec |= (stf << RSPEC_STF_SHIFT);
-
- if (override_mcs_only)
- rspec |= RSPEC_OVERRIDE_MCS_ONLY;
-
- if (issgi)
- rspec |= RSPEC_SHORT_GI;
-
- if ((rate != 0)
- && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true)) {
- return rate;
- }
-
- return rspec;
-done:
- return rate;
-}
-
-/* formula: IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */
-static int
-brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
- bool writeToShm)
-{
- int idle_busy_ratio_x_16 = 0;
- uint offset =
- 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",
- wlc->pub->unit);
- return -EINVAL;
- }
- if (duty_cycle)
- idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle;
- /* Only write to shared memory when wl is up */
- if (writeToShm)
- brcms_c_write_shm(wlc, offset, (u16) idle_busy_ratio_x_16);
-
- if (isOFDM)
- wlc->tx_duty_cycle_ofdm = (u16) duty_cycle;
- else
- wlc->tx_duty_cycle_cck = (u16) duty_cycle;
-
- return 0;
-}
-
-/* Read a single u16 from shared memory.
- * SHM 'offset' needs to be an even address
- */
-u16 brcms_c_read_shm(struct brcms_c_info *wlc, uint offset)
-{
- return brcms_b_read_shm(wlc->hw, offset);
-}
-
-/* Write a single u16 to shared memory.
- * SHM 'offset' needs to be an even address
- */
-void brcms_c_write_shm(struct brcms_c_info *wlc, uint offset, u16 v)
-{
- brcms_b_write_shm(wlc->hw, offset, v);
-}
-
-/* Copy a buffer to shared memory.
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- */
-void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset, const void *buf,
- int len)
-{
- /* offset and len need to be even */
- if (len <= 0 || (offset & 1) || (len & 1))
- return;
-
- brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
-
-}
-
-/* wrapper BMAC functions to for HIGH driver access */
-void brcms_c_mctrl(struct brcms_c_info *wlc, u32 mask, u32 val)
-{
- brcms_b_mctrl(wlc->hw, mask, val);
-}
-
-void brcms_c_mhf(struct brcms_c_info *wlc, u8 idx, u16 mask, u16 val, int bands)
-{
- brcms_b_mhf(wlc->hw, idx, mask, val, bands);
-}
-
-int brcms_c_xmtfifo_sz_get(struct brcms_c_info *wlc, uint fifo, uint *blocks)
-{
- return brcms_b_xmtfifo_sz_get(wlc->hw, fifo, blocks);
-}
-
-void brcms_c_write_template_ram(struct brcms_c_info *wlc, int offset, int len,
- void *buf)
-{
- brcms_b_write_template_ram(wlc->hw, offset, len, buf);
-}
-
-void brcms_c_write_hw_bcntemplates(struct brcms_c_info *wlc, void *bcn, int len,
- bool both)
-{
- brcms_b_write_hw_bcntemplates(wlc->hw, bcn, len, both);
-}
-
-void
-brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
- const u8 *addr)
-{
- brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr);
- if (match_reg_offset == RCM_BSSID_OFFSET)
- memcpy(wlc->cfg->BSSID, addr, ETH_ALEN);
-}
-
-void brcms_c_pllreq(struct brcms_c_info *wlc, bool set, mbool req_bit)
-{
- brcms_b_pllreq(wlc->hw, set, req_bit);
-}
-
-void brcms_c_reset_bmac_done(struct brcms_c_info *wlc)
-{
-}
-
-/* check for the particular priority flow control bit being set */
-bool
-brcms_c_txflowcontrol_prio_isset(struct brcms_c_info *wlc,
- struct brcms_txq_info *q,
- int prio)
-{
- uint prio_mask;
-
- if (prio == ALLPRIO) {
- prio_mask = TXQ_STOP_FOR_PRIOFC_MASK;
- } else {
- prio_mask = NBITVAL(prio);
- }
-
- return (q->stopped & prio_mask) == prio_mask;
-}
-
-/* propagate the flow control to all interfaces using the given tx queue */
-void brcms_c_txflowcontrol(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi,
- bool on, int prio)
-{
- uint prio_bits;
- uint cur_bits;
-
- BCMMSG(wlc->wiphy, "flow control kicks in\n");
-
- if (prio == ALLPRIO) {
- prio_bits = TXQ_STOP_FOR_PRIOFC_MASK;
- } else {
- prio_bits = NBITVAL(prio);
- }
-
- cur_bits = qi->stopped & prio_bits;
-
- /* Check for the case of no change and return early
- * Otherwise update the bit and continue
- */
- if (on) {
- if (cur_bits == prio_bits) {
- return;
- }
- mboolset(qi->stopped, prio_bits);
- } else {
- if (cur_bits == 0) {
- return;
- }
- mboolclr(qi->stopped, prio_bits);
- }
-
- /* If there is a flow control override we will not change the external
- * flow control state.
- */
- if (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK) {
- return;
- }
-
- brcms_c_txflowcontrol_signal(wlc, qi, on, prio);
-}
-
-void
-brcms_c_txflowcontrol_override(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi,
- bool on, uint override)
-{
- uint prev_override;
-
- prev_override = (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK);
-
- /* Update the flow control bits and do an early return if there is
- * no change in the external flow control state.
- */
- if (on) {
- mboolset(qi->stopped, override);
- /* if there was a previous override bit on, then setting this
- * makes no difference.
- */
- if (prev_override) {
- return;
- }
-
- brcms_c_txflowcontrol_signal(wlc, qi, ON, ALLPRIO);
- } else {
- mboolclr(qi->stopped, override);
- /* clearing an override bit will only make a difference for
- * flow control if it was the only bit set. For any other
- * override setting, just return
- */
- if (prev_override != override) {
- return;
- }
-
- if (qi->stopped == 0) {
- brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
- } else {
- int prio;
-
- for (prio = MAXPRIO; prio >= 0; prio--) {
- if (!mboolisset(qi->stopped, NBITVAL(prio)))
- brcms_c_txflowcontrol_signal(
- wlc, qi, OFF, prio);
- }
- }
- }
-}
-
-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;
- }
- }
-}
-
-static void
-brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc,
- struct brcms_txq_info *qi, bool on, int prio)
-{
-#ifdef NON_FUNCTIONAL
- /* wlcif_list is never filled so this function is not functional */
- struct brcms_c_if *wlcif;
-
- for (wlcif = wlc->wlcif_list; wlcif != NULL; wlcif = wlcif->next) {
- if (wlcif->qi == qi && wlcif->flags & BRCMS_IF_LINKED)
- brcms_txflowcontrol(wlc->wl, wlcif->wlif, on, prio);
- }
-#endif
-}
-
-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 * wlc->pub->tunables->datahiwat) + PKTQ_LEN_DEFAULT
- + wlc->pub->psq_pkts_total);
-
- /* 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);
-}
-
-/*
- * Flag 'scan in progress' to withhold dynamic phy calibration
- */
-void brcms_c_scan_start(struct brcms_c_info *wlc)
-{
- wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
-}
-
-void brcms_c_scan_stop(struct brcms_c_info *wlc)
-{
- wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
-}
-
-void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
-{
- wlc->pub->associated = state;
- wlc->cfg->associated = state;
-}
-
-/*
- * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
- * AMPDU traffic, packets pending in hardware have to be invalidated so that
- * when later on hardware releases them, they can be handled appropriately.
- */
-void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
- struct ieee80211_sta *sta,
- void (*dma_callback_fn))
-{
- struct dma_pub *dmah;
- int i;
- for (i = 0; i < NFIFO; i++) {
- dmah = hw->di[i];
- if (dmah != NULL)
- dma_walk_packets(dmah, dma_callback_fn, sta);
- }
-}
-
-int brcms_c_get_curband(struct brcms_c_info *wlc)
-{
- return wlc->band->bandunit;
-}
-
-void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
-{
- /* flush packet queue when requested */
- if (drop)
- brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
-
- /* wait for queue and DMA fifos to run dry */
- while (!pktq_empty(&wlc->pkt_queue->q) ||
- TXPKTPENDTOT(wlc) > 0) {
- brcms_msleep(wlc->wl, 1);
- }
-}
-
-int brcms_c_set_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
- int int_val)
-{
- int err = 0;
-
- switch (par_id) {
- case IOV_BCN_LI_BCN:
- wlc->bcn_li_bcn = (u8) int_val;
- if (wlc->pub->up)
- brcms_c_bcn_li_upd(wlc);
- break;
- /* As long as override is false, this only sets the *user*
- targets. User can twiddle this all he wants with no harm.
- wlc_phy_txpower_set() explicitly sets override to false if
- not internal or test.
- */
- case IOV_QTXPOWER:{
- u8 qdbm;
- bool override;
-
- /* Remove override bit and clip to max qdbm value */
- qdbm = (u8)min_t(u32, (int_val & ~WL_TXPWR_OVERRIDE), 0xff);
- /* Extract override setting */
- override = (int_val & WL_TXPWR_OVERRIDE) ? true : false;
- err =
- wlc_phy_txpower_set(wlc->band->pi, qdbm, override);
- break;
- }
- case IOV_MPC:
- wlc->mpc = (bool)int_val;
- brcms_c_radio_mpc_upd(wlc);
- break;
- default:
- err = -ENOTSUPP;
- }
- return err;
-}
-
-int brcms_c_get_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
- int *ret_int_ptr)
-{
- int err = 0;
-
- switch (par_id) {
- case IOV_BCN_LI_BCN:
- *ret_int_ptr = wlc->bcn_li_bcn;
- break;
- case IOV_QTXPOWER: {
- uint qdbm;
- bool override;
-
- err = wlc_phy_txpower_get(wlc->band->pi, &qdbm,
- &override);
- if (err != 0)
- return err;
-
- /* Return qdbm units */
- *ret_int_ptr =
- qdbm | (override ? WL_TXPWR_OVERRIDE : 0);
- break;
- }
- case IOV_MPC:
- *ret_int_ptr = (s32) wlc->mpc;
- break;
- default:
- err = -ENOTSUPP;
- }
- return err;
-}
-
-/*
- * Search the name=value vars for a specific one and return its value.
- * Returns NULL if not found.
- */
-char *getvar(char *vars, const char *name)
-{
- char *s;
- int len;
-
- if (!name)
- return NULL;
-
- len = strlen(name);
- if (len == 0)
- return NULL;
-
- /* first look in vars[] */
- for (s = vars; s && *s;) {
- if ((memcmp(s, name, len) == 0) && (s[len] == '='))
- return &s[len + 1];
-
- while (*s++)
- ;
- }
- /* nothing found */
- return NULL;
-}
-
-/*
- * Search the vars for a specific one and return its value as
- * an integer. Returns 0 if not found.
- */
-int getintvar(char *vars, const char *name)
-{
- char *val;
-
- val = getvar(vars, name);
- if (val == NULL)
- return 0;
-
- return simple_strtoul(val, NULL, 0);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/main.h b/drivers/staging/brcm80211/brcmsmac/main.h
deleted file mode 100644
index f204b1f47475..000000000000
--- a/drivers/staging/brcm80211/brcmsmac/main.h
+++ /dev/null
@@ -1,1025 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BRCM_MAIN_H_
-#define _BRCM_MAIN_H_
-
-#include <linux/etherdevice.h>
-
-#include <brcmu_utils.h>
-#include "types.h"
-#include "d11.h"
-
-#define MA_WINDOW_SZ 8 /* moving average window size */
-#define BRCMS_HWRXOFF 38 /* chip rx buffer offset */
-#define INVCHANNEL 255 /* invalid channel */
-/* max # supported core revisions (0 .. MAXCOREREV - 1) */
-#define MAXCOREREV 28
-/* max # brcms_c_module_register() calls */
-#define BRCMS_MAXMODULES 22
-
-#define SEQNUM_SHIFT 4
-#define AMPDU_DELIMITER_LEN 4
-#define SEQNUM_MAX 0x1000
-
-#define APHY_CWMIN 15
-#define PHY_CWMAX 1023
-
-#define EDCF_AIFSN_MIN 1
-#define FRAGNUM_MASK 0xF
-
-#define NTXRATE 64 /* # tx MPDUs rate is reported for */
-
-#define BRCMS_BITSCNT(x) brcmu_bitcount((u8 *)&(x), sizeof(u8))
-
-/* Maximum wait time for a MAC suspend */
-/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */
-#define BRCMS_MAX_MAC_SUSPEND 83000
-
-/* Probe Response timeout - responses for probe requests older that this are tossed, zero to disable
- */
-#define BRCMS_PRB_RESP_TIMEOUT 0 /* Disable probe response timeout */
-
-/* transmit buffer max headroom for protocol headers */
-#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN)
-
-#define AC_COUNT 4
-
-/* Macros for doing definition and get/set of bitfields
- * Usage example, e.g. a three-bit field (bits 4-6):
- * #define <NAME>_M BITFIELD_MASK(3)
- * #define <NAME>_S 4
- * ...
- * regval = R_REG(osh, &regs->regfoo);
- * field = GFIELD(regval, <NAME>);
- * regval = SFIELD(regval, <NAME>, 1);
- * W_REG(osh, &regs->regfoo, regval);
- */
-#define BITFIELD_MASK(width) \
- (((unsigned)1 << (width)) - 1)
-#define GFIELD(val, field) \
- (((val) >> field ## _S) & field ## _M)
-#define SFIELD(val, field, bits) \
- (((val) & (~(field ## _M << field ## _S))) | \
- ((unsigned)(bits) << field ## _S))
-
-#define SW_TIMER_MAC_STAT_UPD 30 /* periodic MAC stats update */
-
-/* Double check that unsupported cores are not enabled */
-#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV)
-#error "Configuration for D11CONF includes unsupported versions."
-#endif /* Bad versions */
-
-#define VALID_COREREV(corerev) CONF_HAS(D11CONF, corerev)
-
-/* values for shortslot_override */
-#define BRCMS_SHORTSLOT_AUTO -1 /* Driver will manage Shortslot setting */
-#define BRCMS_SHORTSLOT_OFF 0 /* Turn off short slot */
-#define BRCMS_SHORTSLOT_ON 1 /* Turn on short slot */
-
-/* value for short/long and mixmode/greenfield preamble */
-#define BRCMS_LONG_PREAMBLE (0)
-#define BRCMS_SHORT_PREAMBLE (1 << 0)
-#define BRCMS_GF_PREAMBLE (1 << 1)
-#define BRCMS_MM_PREAMBLE (1 << 2)
-#define BRCMS_IS_MIMO_PREAMBLE(_pre) (((_pre) == BRCMS_GF_PREAMBLE) || \
- ((_pre) == BRCMS_MM_PREAMBLE))
-
-/* values for barker_preamble */
-#define BRCMS_BARKER_SHORT_ALLOWED 0 /* Short pre-amble allowed */
-
-/* A fifo is full. Clear precedences related to that FIFO */
-#define BRCMS_TX_FIFO_CLEAR(wlc, fifo) \
- ((wlc)->tx_prec_map &= ~(wlc)->fifo2prec_map[fifo])
-
-/* Fifo is NOT full. Enable precedences for that FIFO */
-#define BRCMS_TX_FIFO_ENAB(wlc, fifo) \
- ((wlc)->tx_prec_map |= (wlc)->fifo2prec_map[fifo])
-
-/* TxFrameID */
-/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */
-/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */
-#define TXFID_QUEUE_MASK 0x0007 /* Bits 0-2 */
-#define TXFID_SEQ_MASK 0x7FE0 /* Bits 5-15 */
-#define TXFID_SEQ_SHIFT 5 /* Number of bit shifts */
-#define TXFID_RATE_PROBE_MASK 0x8000 /* Bit 15 for rate probe */
-#define TXFID_RATE_MASK 0x0018 /* Mask for bits 3 and 4 */
-#define TXFID_RATE_SHIFT 3 /* Shift 3 bits for rate mask */
-
-/* promote boardrev */
-#define BOARDREV_PROMOTABLE 0xFF /* from */
-#define BOARDREV_PROMOTED 1 /* to */
-
-/* if wpa is in use then portopen is true when the group key is plumbed otherwise it is always true
- */
-#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
-#define BRCMS_SW_KEYS(wlc, bsscfg) ((((wlc)->wsec_swkeys) || \
- ((bsscfg)->wsec & WSEC_SWFLAG)))
-
-#define BRCMS_PORTOPEN(cfg) \
- (((cfg)->WPA_auth != WPA_AUTH_DISABLED && WSEC_ENABLED((cfg)->wsec)) ? \
- (cfg)->wsec_portopen : true)
-
-#define PS_ALLOWED(wlc) brcms_c_ps_allowed(wlc)
-
-#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
-#define BRCMS_WAKE_OVERRIDE_MACSUSPEND 0x04
-#define BRCMS_WAKE_OVERRIDE_TXFIFO 0x08
-#define BRCMS_WAKE_OVERRIDE_FORCEFAST 0x10
-
-/* stuff pulled in from wlc.c */
-
-/* Interrupt bit error summary. Don't include I_RU: we refill DMA at other
- * times; and if we run out, constant I_RU interrupts may cause lockup. We
- * will still get error counts from rx0ovfl.
- */
-#define I_ERRORS (I_PC | I_PD | I_DE | I_RO | I_XU)
-/* default software intmasks */
-#define DEF_RXINTMASK (I_RI) /* enable rx int on rxfifo only */
-#define DEF_MACINTMASK (MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \
- MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \
- MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP)
-
-#define RETRY_SHORT_DEF 7 /* Default Short retry Limit */
-#define RETRY_SHORT_MAX 255 /* Maximum Short retry Limit */
-#define RETRY_LONG_DEF 4 /* Default Long retry count */
-#define RETRY_SHORT_FB 3 /* Short retry count for fallback rate */
-#define RETRY_LONG_FB 2 /* Long retry count for fallback rate */
-
-#define MAXTXPKTS 6 /* max # pkts pending */
-
-/* frameburst */
-#define MAXTXFRAMEBURST 8 /* vanilla xpress mode: max frames/burst */
-#define MAXFRAMEBURST_TXOP 10000 /* Frameburst TXOP in usec */
-
-/* Per-AC retry limit register definitions; uses defs.h bitfield macros */
-#define EDCF_SHORT_S 0
-#define EDCF_SFB_S 4
-#define EDCF_LONG_S 8
-#define EDCF_LFB_S 12
-#define EDCF_SHORT_M BITFIELD_MASK(4)
-#define EDCF_SFB_M BITFIELD_MASK(4)
-#define EDCF_LONG_M BITFIELD_MASK(4)
-#define EDCF_LFB_M BITFIELD_MASK(4)
-
-#define NFIFO 6 /* # tx/rx fifopairs */
-
-#define BRCMS_WME_RETRY_SHORT_GET(wlc, ac) \
- GFIELD(wlc->wme_retries[ac], EDCF_SHORT)
-#define BRCMS_WME_RETRY_SFB_GET(wlc, ac) \
- GFIELD(wlc->wme_retries[ac], EDCF_SFB)
-#define BRCMS_WME_RETRY_LONG_GET(wlc, ac) \
- GFIELD(wlc->wme_retries[ac], EDCF_LONG)
-#define BRCMS_WME_RETRY_LFB_GET(wlc, ac) \
- GFIELD(wlc->wme_retries[ac], EDCF_LFB)
-
-#define BRCMS_WME_RETRY_SHORT_SET(wlc, ac, val) \
- (wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SHORT, val))
-#define BRCMS_WME_RETRY_SFB_SET(wlc, ac, val) \
- (wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SFB, val))
-#define BRCMS_WME_RETRY_LONG_SET(wlc, ac, val) \
- (wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LONG, val))
-#define BRCMS_WME_RETRY_LFB_SET(wlc, ac, val) \
- (wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LFB, val))
-
-/* PLL requests */
-
-/* pll is shared on old chips */
-#define BRCMS_PLLREQ_SHARED 0x1
-/* hold pll for radio monitor register checking */
-#define BRCMS_PLLREQ_RADIO_MON 0x2
-/* hold/release pll for some short operation */
-#define BRCMS_PLLREQ_FLIP 0x4
-
-/*
- * Macros to check if AP or STA is active.
- * AP Active means more than just configured: driver and BSS are "up";
- * that is, we are beaconing/responding as an AP (aps_associated).
- * STA Active similarly means the driver is up and a configured STA BSS
- * is up: either associated (stas_associated) or trying.
- *
- * Macro definitions vary as per AP/STA ifdefs, allowing references to
- * ifdef'd structure fields and constant values (0) for optimization.
- * Make sure to enclose blocks of code such that any routines they
- * reference can also be unused and optimized out by the linker.
- */
-/* NOTE: References structure fields defined in wlc.h */
-#define AP_ACTIVE(wlc) (0)
-
-/*
- * Detect Card removed.
- * Even checking an sbconfig register read will not false trigger when the core is in reset.
- * it breaks CF address mechanism. Accessing gphy phyversion will cause SB error if aphy
- * is in reset on 4306B0-DB. Need a simple accessible reg with fixed 0/1 pattern
- * (some platforms return all 0).
- * If clocks are present, call the sb routine which will figure out if the device is removed.
- */
-#define DEVICEREMOVED(wlc) \
- ((wlc->hw->clk) ? \
- ((R_REG(&wlc->hw->regs->maccontrol) & \
- (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN) : \
- (ai_deviceremoved(wlc->hw->sih)))
-
-#define BRCMS_UNIT(wlc) ((wlc)->pub->unit)
-
-struct brcms_protection {
- bool _g; /* use g spec protection, driver internal */
- s8 g_override; /* override for use of g spec protection */
- u8 gmode_user; /* user config gmode, operating band->gmode is different */
- s8 overlap; /* Overlap BSS/IBSS protection for both 11g and 11n */
- s8 nmode_user; /* user config nmode, operating pub->nmode is different */
- s8 n_cfg; /* use OFDM protection on MIMO frames */
- s8 n_cfg_override; /* override for use of N protection */
- bool nongf; /* non-GF present protection */
- s8 nongf_override; /* override for use of GF protection */
- s8 n_pam_override; /* override for preamble: MM or GF */
- bool n_obss; /* indicated OBSS Non-HT STA present */
-};
-
-/* anything affects the single/dual streams/antenna operation */
-struct brcms_stf {
- u8 hw_txchain; /* HW txchain bitmap cfg */
- u8 txchain; /* txchain bitmap being used */
- u8 txstreams; /* number of txchains being used */
-
- u8 hw_rxchain; /* HW rxchain bitmap cfg */
- u8 rxchain; /* rxchain bitmap being used */
- u8 rxstreams; /* number of rxchains being used */
-
- u8 ant_rx_ovr; /* rx antenna override */
- s8 txant; /* userTx antenna setting */
- u16 phytxant; /* phyTx antenna setting in txheader */
-
- u8 ss_opmode; /* singlestream Operational mode, 0:siso; 1:cdd */
- bool ss_algosel_auto; /* if true, use wlc->stf->ss_algo_channel; */
- /* else use wlc->band->stf->ss_mode_band; */
- u16 ss_algo_channel; /* ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC */
- u8 no_cddstbc; /* stf override, 1: no CDD (or STBC) allowed */
-
- u8 rxchain_restore_delay; /* delay time to restore default rxchain */
-
- s8 ldpc; /* AUTO/ON/OFF ldpc cap supported */
- u8 txcore[MAX_STREAMS_SUPPORTED + 1]; /* bitmap of selected core for each Nsts */
- s8 spatial_policy;
-};
-
-#define BRCMS_STF_SS_STBC_TX(wlc, scb) \
- (((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) || \
- (SCB_STBC_CAP((scb)) && \
- (wlc)->band->band_stf_stbc_tx == AUTO && \
- isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC))))
-
-#define BRCMS_STBC_CAP_PHY(wlc) (BRCMS_ISNPHY(wlc->band) && \
- NREV_GE(wlc->band->phyrev, 3))
-
-#define BRCMS_SGI_CAP_PHY(wlc) ((BRCMS_ISNPHY(wlc->band) && \
- NREV_GE(wlc->band->phyrev, 3)) || \
- BRCMS_ISLCNPHY(wlc->band))
-
-#define BRCMS_CHAN_PHYTYPE(x) (((x) & RXS_CHAN_PHYTYPE_MASK) \
- >> RXS_CHAN_PHYTYPE_SHIFT)
-#define BRCMS_CHAN_CHANNEL(x) (((x) & RXS_CHAN_ID_MASK) \
- >> RXS_CHAN_ID_SHIFT)
-#define BRCMS_RX_CHANNEL(rxh) (BRCMS_CHAN_CHANNEL((rxh)->RxChan))
-
-/* brcms_bss_info flag bit values */
-#define BRCMS_BSS_HT 0x0020 /* BSS is HT (MIMO) capable */
-
-/* Flags used in brcms_c_txq_info.stopped */
-#define TXQ_STOP_FOR_PRIOFC_MASK 0x000000FF /* per prio flow control bits */
-#define TXQ_STOP_FOR_PKT_DRAIN 0x00000100 /* stop txq enqueue for packet drain */
-#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL 0x00000200 /* stop txq enqueue for ampdu flow control */
-
-#define BRCMS_HT_WEP_RESTRICT 0x01 /* restrict HT with WEP */
-#define BRCMS_HT_TKIP_RESTRICT 0x02 /* restrict HT with TKIP */
-
-/* Maximum # of keys that wl driver supports in S/W.
- * Keys supported in H/W is less than or equal to WSEC_MAX_KEYS.
- */
-#define WSEC_MAX_KEYS 54 /* Max # of keys (50 + 4 default keys) */
-#define BRCMS_DEFAULT_KEYS 4 /* Default # of keys */
-
-/*
-* Max # of keys currently supported:
-*
-* s/w keys if WSEC_SW(wlc->wsec).
-* h/w keys otherwise.
-*/
-#define BRCMS_MAX_WSEC_KEYS(wlc) WSEC_MAX_KEYS
-
-/* number of 802.11 default (non-paired, group keys) */